aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile44
-rw-r--r--lib/asn1/c_src/Makefile41
-rw-r--r--lib/asn1/c_src/asn1_erl_driver.c1670
-rw-r--r--lib/asn1/c_src/asn1_erl_nif.c1305
-rw-r--r--lib/asn1/doc/src/asn1_spec.xmlsrc8
-rw-r--r--lib/asn1/doc/src/asn1_ug.xml50
-rw-r--r--lib/asn1/doc/src/asn1ct.xml41
-rw-r--r--lib/asn1/doc/src/asn1rt.xml65
-rw-r--r--lib/asn1/doc/src/notes.xml45
-rw-r--r--lib/asn1/src/Makefile4
-rw-r--r--lib/asn1/src/asn1.app.src5
-rw-r--r--lib/asn1/src/asn1_app.erl2
-rw-r--r--lib/asn1/src/asn1_server.erl107
-rw-r--r--lib/asn1/src/asn1_sup.erl37
-rw-r--r--lib/asn1/src/asn1ct.erl41
-rw-r--r--lib/asn1/src/asn1ct_check.erl50
-rw-r--r--lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl12
-rw-r--r--lib/asn1/src/asn1ct_constructed_per.erl125
-rw-r--r--lib/asn1/src/asn1ct_gen.erl35
-rw-r--r--lib/asn1/src/asn1ct_gen_ber_bin_v2.erl25
-rw-r--r--lib/asn1/src/asn1ct_gen_per.erl5
-rw-r--r--lib/asn1/src/asn1ct_gen_per_rt2ct.erl5
-rw-r--r--lib/asn1/src/asn1ct_value.erl12
-rw-r--r--lib/asn1/src/asn1rt.erl40
-rw-r--r--lib/asn1/src/asn1rt_ber_bin_v2.erl160
-rw-r--r--lib/asn1/src/asn1rt_check.erl6
-rw-r--r--lib/asn1/src/asn1rt_driver_handler.erl144
-rw-r--r--lib/asn1/src/asn1rt_nif.erl87
-rw-r--r--lib/asn1/src/asn1rt_per_bin.erl4
-rw-r--r--lib/asn1/src/asn1rt_per_bin_rt2ct.erl131
-rw-r--r--lib/asn1/test/Makefile2
-rw-r--r--lib/asn1/test/asn1.cover1
-rw-r--r--lib/asn1/test/asn1_SUITE.erl2489
-rw-r--r--lib/asn1/test/asn1_SUITE.erl.src71
-rw-r--r--lib/asn1/test/asn1_bin_SUITE.erl2382
-rw-r--r--lib/asn1/test/asn1_bin_v2_SUITE.erl2474
-rw-r--r--lib/asn1/test/asn1_bin_v2_particular_SUITE.erl.src270
-rw-r--r--lib/asn1/test/asn1_common_SUITE.erl.src5
-rw-r--r--lib/asn1/test/ber_decode_error.erl6
-rw-r--r--lib/asn1/test/testContextSwitchingTypes.erl4
-rw-r--r--lib/asn1/test/testPrim.erl21
-rw-r--r--lib/asn1/test/test_compile_options.erl41
-rw-r--r--lib/asn1/test/test_inline.erl6
-rw-r--r--lib/asn1/vsn.mk2
-rw-r--r--lib/common_test/doc/src/common_test_app.xml46
-rw-r--r--lib/common_test/doc/src/config_file_chapter.xml6
-rw-r--r--lib/common_test/doc/src/ct_hooks.xml10
-rw-r--r--lib/common_test/doc/src/ct_hooks_chapter.xml51
-rw-r--r--lib/common_test/doc/src/ct_run.xml7
-rw-r--r--lib/common_test/doc/src/notes.xml294
-rw-r--r--lib/common_test/doc/src/run_test_chapter.xml52
-rw-r--r--lib/common_test/doc/src/write_test_chapter.xml26
-rw-r--r--lib/common_test/include/ct.hrl3
-rw-r--r--lib/common_test/src/Makefile7
-rw-r--r--lib/common_test/src/common_test.app.src1
-rw-r--r--lib/common_test/src/ct.erl9
-rw-r--r--lib/common_test/src/ct_config.erl40
-rw-r--r--lib/common_test/src/ct_config_plain.erl24
-rw-r--r--lib/common_test/src/ct_config_xml.erl48
-rw-r--r--lib/common_test/src/ct_framework.erl169
-rw-r--r--lib/common_test/src/ct_hooks.erl179
-rw-r--r--lib/common_test/src/ct_line.erl266
-rw-r--r--lib/common_test/src/ct_logs.erl305
-rw-r--r--lib/common_test/src/ct_make.erl2
-rw-r--r--lib/common_test/src/ct_run.erl621
-rw-r--r--lib/common_test/src/ct_telnet.erl9
-rw-r--r--lib/common_test/src/ct_testspec.erl35
-rw-r--r--lib/common_test/src/ct_util.erl171
-rw-r--r--lib/common_test/src/ct_util.hrl5
-rw-r--r--lib/common_test/src/cth_log_redirect.erl111
-rw-r--r--lib/common_test/src/vts.erl165
-rw-r--r--lib/common_test/test/Makefile2
-rw-r--r--lib/common_test/test/ct_config_SUITE.erl3
-rw-r--r--lib/common_test/test/ct_error_SUITE.erl324
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl33
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_2_SUITE.erl28
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_3_SUITE.erl146
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_4_SUITE.erl135
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_5_SUITE.erl155
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_6_SUITE.erl114
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_7_SUITE.erl137
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_utils.erl43
-rw-r--r--lib/common_test/test/ct_event_handler_SUITE.erl10
-rw-r--r--lib/common_test/test/ct_groups_test_1_SUITE.erl25
-rw-r--r--lib/common_test/test/ct_groups_test_2_SUITE.erl67
-rw-r--r--lib/common_test/test/ct_groups_test_2_SUITE_data/groups_2/groups_22_SUITE.erl53
-rw-r--r--lib/common_test/test/ct_hooks_SUITE.erl147
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_prio_SUITE.erl62
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_suite_crash_in_cth_SUITE.erl50
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl11
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/prio_cth.erl74
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/state_update_cth.erl2
-rw-r--r--lib/common_test/test/ct_master_SUITE.erl7
-rw-r--r--lib/common_test/test/ct_misc_1_SUITE.erl3
-rw-r--r--lib/common_test/test/ct_repeat_1_SUITE.erl11
-rw-r--r--lib/common_test/test/ct_sequence_1_SUITE.erl3
-rw-r--r--lib/common_test/test/ct_skip_SUITE.erl19
-rw-r--r--lib/common_test/test/ct_smoke_test_SUITE.erl39
-rw-r--r--lib/common_test/test/ct_test_server_if_1_SUITE.erl5
-rw-r--r--lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl2
-rw-r--r--lib/common_test/test/ct_test_support.erl232
-rw-r--r--lib/common_test/test/ct_testspec_1_SUITE.erl20
-rw-r--r--lib/common_test/vsn.mk2
-rw-r--r--lib/compiler/doc/src/compile.xml10
-rw-r--r--lib/compiler/doc/src/notes.xml54
-rw-r--r--lib/compiler/src/beam_asm.erl61
-rw-r--r--lib/compiler/src/beam_block.erl35
-rw-r--r--lib/compiler/src/beam_bsm.erl17
-rw-r--r--lib/compiler/src/beam_clean.erl26
-rw-r--r--lib/compiler/src/beam_dead.erl56
-rw-r--r--lib/compiler/src/beam_dict.erl66
-rw-r--r--lib/compiler/src/beam_disasm.erl35
-rw-r--r--lib/compiler/src/beam_jump.erl49
-rw-r--r--lib/compiler/src/beam_listing.erl2
-rw-r--r--lib/compiler/src/beam_receive.erl2
-rw-r--r--lib/compiler/src/beam_trim.erl13
-rw-r--r--lib/compiler/src/beam_type.erl1
-rw-r--r--lib/compiler/src/beam_utils.erl16
-rw-r--r--lib/compiler/src/beam_validator.erl15
-rw-r--r--lib/compiler/src/compile.erl58
-rw-r--r--lib/compiler/src/erl_bifs.erl1
-rw-r--r--lib/compiler/src/genop.tab4
-rw-r--r--lib/compiler/src/sys_core_fold.erl194
-rw-r--r--lib/compiler/src/sys_pre_expand.erl44
-rw-r--r--lib/compiler/src/v3_codegen.erl108
-rw-r--r--lib/compiler/src/v3_core.erl40
-rw-r--r--lib/compiler/src/v3_kernel.erl13
-rw-r--r--lib/compiler/src/v3_life.erl4
-rw-r--r--lib/compiler/test/Makefile3
-rw-r--r--lib/compiler/test/andor_SUITE.erl2
-rw-r--r--lib/compiler/test/apply_SUITE.erl2
-rw-r--r--lib/compiler/test/beam_disasm_SUITE.erl65
-rw-r--r--lib/compiler/test/beam_validator_SUITE.erl2
-rw-r--r--lib/compiler/test/bs_bincomp_SUITE.erl2
-rw-r--r--lib/compiler/test/bs_bit_binaries_SUITE.erl2
-rw-r--r--lib/compiler/test/bs_construct_SUITE.erl2
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl28
-rw-r--r--lib/compiler/test/bs_utf_SUITE.erl2
-rw-r--r--lib/compiler/test/compilation_SUITE.erl2
-rw-r--r--lib/compiler/test/compile_SUITE.erl3
-rw-r--r--lib/compiler/test/core_SUITE.erl2
-rw-r--r--lib/compiler/test/core_fold_SUITE.erl2
-rw-r--r--lib/compiler/test/error_SUITE.erl67
-rw-r--r--lib/compiler/test/float_SUITE.erl2
-rw-r--r--lib/compiler/test/fun_SUITE.erl2
-rw-r--r--lib/compiler/test/guard_SUITE.erl31
-rw-r--r--lib/compiler/test/inline_SUITE.erl5
-rw-r--r--lib/compiler/test/lc_SUITE.erl6
-rw-r--r--lib/compiler/test/match_SUITE.erl20
-rw-r--r--lib/compiler/test/misc_SUITE.erl6
-rw-r--r--lib/compiler/test/num_bif_SUITE.erl2
-rw-r--r--lib/compiler/test/pmod_SUITE.erl2
-rw-r--r--lib/compiler/test/receive_SUITE.erl2
-rw-r--r--lib/compiler/test/record_SUITE.erl21
-rw-r--r--lib/compiler/test/trycatch_SUITE.erl18
-rw-r--r--lib/compiler/test/warnings_SUITE.erl12
-rw-r--r--lib/compiler/vsn.mk2
-rw-r--r--lib/cosEvent/doc/src/CosEventChannelAdmin_ConsumerAdmin.xml3
-rw-r--r--lib/cosEvent/doc/src/CosEventChannelAdmin_EventChannel.xml3
-rw-r--r--lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPullConsumer.xml3
-rw-r--r--lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPullSupplier.xml3
-rw-r--r--lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPushConsumer.xml3
-rw-r--r--lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPushSupplier.xml3
-rw-r--r--lib/cosEvent/doc/src/CosEventChannelAdmin_SupplierAdmin.xml3
-rw-r--r--lib/cosEvent/doc/src/notes.xml21
-rw-r--r--lib/cosEvent/src/Makefile12
-rw-r--r--lib/cosEvent/test/Makefile14
-rw-r--r--lib/cosEvent/vsn.mk2
-rw-r--r--lib/cosEventDomain/doc/src/CosEventDomainAdmin_EventDomain.xml5
-rw-r--r--lib/cosEventDomain/doc/src/CosEventDomainAdmin_EventDomainFactory.xml3
-rw-r--r--lib/cosEventDomain/doc/src/notes.xml17
-rw-r--r--lib/cosEventDomain/src/Makefile7
-rw-r--r--lib/cosEventDomain/vsn.mk2
-rw-r--r--lib/cosFileTransfer/doc/src/CosFileTransfer_Directory.xml3
-rw-r--r--lib/cosFileTransfer/doc/src/CosFileTransfer_File.xml5
-rw-r--r--lib/cosFileTransfer/doc/src/CosFileTransfer_FileIterator.xml5
-rw-r--r--lib/cosFileTransfer/doc/src/CosFileTransfer_FileTransferSession.xml9
-rw-r--r--lib/cosFileTransfer/doc/src/CosFileTransfer_VirtualFileSystem.xml3
-rw-r--r--lib/cosFileTransfer/doc/src/notes.xml33
-rw-r--r--lib/cosFileTransfer/src/CosFileTransfer_FileTransferSession_impl.erl4
-rw-r--r--lib/cosFileTransfer/src/Makefile7
-rw-r--r--lib/cosFileTransfer/test/Makefile2
-rw-r--r--lib/cosFileTransfer/vsn.mk2
-rw-r--r--lib/cosNotification/doc/src/CosNotification_AdminPropertiesAdmin.xml7
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_ConsumerAdmin.xml9
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_EventChannel.xml5
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_EventChannelFactory.xml5
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyConsumer.xml9
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPullConsumer.xml9
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPullSupplier.xml9
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPushConsumer.xml7
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPushSupplier.xml9
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxySupplier.xml9
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPullConsumer.xml9
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPullSupplier.xml9
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPushConsumer.xml7
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPushSupplier.xml11
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPullConsumer.xml11
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPullSupplier.xml11
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPushConsumer.xml11
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPushSupplier.xml11
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_SupplierAdmin.xml7
-rw-r--r--lib/cosNotification/doc/src/CosNotifyComm_NotifySubscribe.xml9
-rw-r--r--lib/cosNotification/doc/src/ch_BNF.xml10
-rw-r--r--lib/cosNotification/doc/src/notes.xml15
-rw-r--r--lib/cosNotification/src/Makefile29
-rw-r--r--lib/cosNotification/test/Makefile11
-rw-r--r--lib/cosNotification/vsn.mk2
-rw-r--r--lib/cosProperty/doc/src/CosPropertyService_PropertiesIterator.xml5
-rw-r--r--lib/cosProperty/doc/src/CosPropertyService_PropertyNamesIterator.xml9
-rw-r--r--lib/cosProperty/doc/src/CosPropertyService_PropertySet.xml9
-rw-r--r--lib/cosProperty/doc/src/CosPropertyService_PropertySetDef.xml5
-rw-r--r--lib/cosProperty/doc/src/CosPropertyService_PropertySetDefFactory.xml7
-rw-r--r--lib/cosProperty/doc/src/CosPropertyService_PropertySetFactory.xml9
-rw-r--r--lib/cosProperty/doc/src/notes.xml19
-rw-r--r--lib/cosProperty/src/Makefile6
-rw-r--r--lib/cosProperty/vsn.mk2
-rw-r--r--lib/cosTime/doc/src/CosTimerEvent_TimerEventHandler.xml7
-rw-r--r--lib/cosTime/doc/src/CosTimerEvent_TimerEventService.xml3
-rw-r--r--lib/cosTime/doc/src/notes.xml17
-rw-r--r--lib/cosTime/src/Makefile11
-rw-r--r--lib/cosTime/vsn.mk2
-rw-r--r--lib/cosTransactions/doc/src/CosTransactions_RecoveryCoordinator.xml11
-rw-r--r--lib/cosTransactions/doc/src/CosTransactions_SubtransactionAwareResource.xml5
-rw-r--r--lib/cosTransactions/doc/src/CosTransactions_TransactionFactory.xml9
-rw-r--r--lib/cosTransactions/doc/src/notes.xml18
-rw-r--r--lib/cosTransactions/src/Makefile7
-rw-r--r--lib/cosTransactions/test/Makefile11
-rw-r--r--lib/cosTransactions/vsn.mk2
-rw-r--r--lib/crypto/c_src/Makefile.in19
-rw-r--r--lib/crypto/c_src/crypto.c241
-rw-r--r--lib/crypto/doc/src/crypto.xml237
-rw-r--r--lib/crypto/doc/src/licenses.xml4
-rw-r--r--lib/crypto/doc/src/notes.xml81
-rw-r--r--lib/crypto/src/crypto.erl122
-rw-r--r--lib/crypto/test/Makefile2
-rw-r--r--lib/crypto/test/crypto_SUITE.erl341
-rw-r--r--lib/crypto/vsn.mk2
-rw-r--r--lib/debugger/doc/src/debugger_chapter.xml42
-rw-r--r--lib/debugger/doc/src/int.xml4
-rw-r--r--lib/debugger/doc/src/notes.xml2
-rw-r--r--lib/debugger/src/Makefile1
-rw-r--r--lib/debugger/src/dbg_debugged.erl15
-rw-r--r--lib/debugger/src/dbg_icmd.erl16
-rw-r--r--lib/debugger/src/dbg_ieval.erl555
-rw-r--r--lib/debugger/src/dbg_ieval.hrl8
-rw-r--r--lib/debugger/src/dbg_iload.erl348
-rw-r--r--lib/debugger/src/dbg_iserver.erl5
-rw-r--r--lib/debugger/src/dbg_istk.erl245
-rw-r--r--lib/debugger/src/debugger.app.src1
-rw-r--r--lib/debugger/test/Makefile3
-rw-r--r--lib/debugger/test/bs_construct_SUITE.erl395
-rw-r--r--lib/debugger/test/bs_match_bin_SUITE.erl141
-rw-r--r--lib/debugger/test/bs_match_int_SUITE.erl206
-rw-r--r--lib/debugger/test/bs_match_misc_SUITE.erl453
-rw-r--r--lib/debugger/test/bs_match_tail_SUITE.erl12
-rw-r--r--lib/debugger/test/bug_SUITE.erl4
-rw-r--r--lib/debugger/test/exception_SUITE.erl264
-rw-r--r--lib/debugger/test/guard_SUITE.erl217
-rw-r--r--lib/debugger/test/int_eval_SUITE.erl47
-rw-r--r--lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl4
-rw-r--r--lib/debugger/test/int_eval_SUITE_data/stacktrace.erl130
-rw-r--r--lib/debugger/test/lc_SUITE.erl119
-rw-r--r--lib/debugger/test/line_number_SUITE.erl220
-rw-r--r--lib/debugger/test/test_lib.erl2
-rw-r--r--lib/debugger/test/trycatch_SUITE.erl17
-rw-r--r--lib/dialyzer/doc/manual.txt33
-rw-r--r--lib/dialyzer/doc/src/dialyzer.xml70
-rwxr-xr-xlib/dialyzer/doc/src/notes.xml150
-rw-r--r--lib/dialyzer/src/dialyzer_dataflow.erl74
-rw-r--r--lib/dialyzer/src/dialyzer_plt.erl2
-rw-r--r--lib/dialyzer/src/dialyzer_succ_typings.erl34
-rw-r--r--lib/dialyzer/src/dialyzer_typesig.erl206
-rw-r--r--lib/dialyzer/test/Makefile71
-rw-r--r--lib/dialyzer/test/README26
-rw-r--r--lib/dialyzer/test/callgraph_SUITE_data/dialyzer_options (renamed from lib/dialyzer/test/callgraph_tests_SUITE_data/dialyzer_options)0
-rw-r--r--lib/dialyzer/test/callgraph_SUITE_data/results/test_missing_functions (renamed from lib/dialyzer/test/callgraph_tests_SUITE_data/results/test_missing_functions)0
-rw-r--r--lib/dialyzer/test/callgraph_SUITE_data/src/test_missing_functions/t1.erl16
-rw-r--r--lib/dialyzer/test/callgraph_SUITE_data/src/test_missing_functions/t2.erl16
-rw-r--r--lib/dialyzer/test/callgraph_tests_SUITE.erl52
-rw-r--r--lib/dialyzer/test/callgraph_tests_SUITE_data/src/test_missing_functions/t1.erl16
-rw-r--r--lib/dialyzer/test/callgraph_tests_SUITE_data/src/test_missing_functions/t2.erl16
-rw-r--r--lib/dialyzer/test/dialyzer.spec2
-rw-r--r--lib/dialyzer/test/dialyzer_common.erl12
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/dialyzer_options (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/dialyzer_options)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/array (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/results/array)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/crash (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/results/crash)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/dict (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/results/dict)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/ets (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/results/ets)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/ewgi4
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/gb_sets (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/results/gb_sets)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/inf_loop1 (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/results/inf_loop1)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/int (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/results/int)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/mixed_opaque (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/results/mixed_opaque)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/my_digraph (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/results/my_digraph)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/my_queue (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/results/my_queue)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/opaque (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/results/opaque)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/queue (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/results/queue)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/rec (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/results/rec)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/timer (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/results/timer)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/union (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/results/union)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/wings (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/results/wings)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/array/array_use.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/array/array_use.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/crash/crash_1.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/crash/crash_1.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/dict/dict_use.erl82
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/ets/ets_use.erl16
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl240
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_api.erl65
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_testapp.erl46
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl241
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_api.erl65
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_testapp.erl46
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/gb_sets/gb_sets_rec.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/gb_sets/gb_sets_rec.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/inf_loop1.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/inf_loop1.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/int/int_adt.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/int/int_adt.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/int/int_use.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/int/int_use.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/mixed_opaque/mixed_opaque_queue_adt.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/mixed_opaque/mixed_opaque_queue_adt.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/mixed_opaque/mixed_opaque_rec_adt.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/mixed_opaque/mixed_opaque_rec_adt.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/mixed_opaque/mixed_opaque_use.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/mixed_opaque/mixed_opaque_use.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/my_digraph/my_digraph_adt.erl51
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/my_queue/my_queue_adt.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/my_queue/my_queue_adt.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/my_queue/my_queue_use.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/my_queue/my_queue_use.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_adt.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/opaque/opaque_adt.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_bug1.erl16
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_bug2.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/opaque/opaque_bug2.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_bug3.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/opaque/opaque_bug3.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_bug4.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/opaque/opaque_bug4.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/queue/queue_use.erl65
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/rec/rec_adt.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/rec/rec_adt.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/rec/rec_use.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/rec/rec_use.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/schuett_bug.erl28
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/timer/timer_use.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/timer/timer_use.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/union/union_adt.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/union/union_adt.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/union/union_use.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/union/union_use.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/wings/wings.hrl204
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_dissolve.erl375
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_edge.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_edge.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_edge_cmd.erl90
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_face.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_face.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_facemat.erl299
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_intl.hrl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_intl.hrl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_io.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_io.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_sel.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_sel.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_shape.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_shape.erl)0
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_util.erl38
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_we.erl250
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis1.erl14
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis2.erl14
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis3.erl14
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis4.erl13
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis5.erl14
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis6.erl (renamed from lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis6.erl)0
-rw-r--r--lib/dialyzer/test/opaque_tests_SUITE.erl184
-rw-r--r--lib/dialyzer/test/opaque_tests_SUITE_data/src/dict/dict_use.erl83
-rw-r--r--lib/dialyzer/test/opaque_tests_SUITE_data/src/ets/ets_use.erl17
-rw-r--r--lib/dialyzer/test/opaque_tests_SUITE_data/src/my_digraph/my_digraph_adt.erl51
-rw-r--r--lib/dialyzer/test/opaque_tests_SUITE_data/src/opaque/opaque_bug1.erl17
-rw-r--r--lib/dialyzer/test/opaque_tests_SUITE_data/src/queue/queue_use.erl66
-rw-r--r--lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings.hrl205
-rw-r--r--lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_dissolve.erl375
-rw-r--r--lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_edge_cmd.erl91
-rw-r--r--lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_facemat.erl299
-rw-r--r--lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_util.erl39
-rw-r--r--lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_we.erl250
-rw-r--r--lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis1.erl14
-rw-r--r--lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis2.erl14
-rw-r--r--lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis3.erl14
-rw-r--r--lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis4.erl14
-rw-r--r--lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis5.erl14
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/dialyzer_options (renamed from lib/dialyzer/test/options1_tests_SUITE_data/dialyzer_options)0
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/my_include/CVS/Entries (renamed from lib/dialyzer/test/options1_tests_SUITE_data/my_include/CVS/Entries)0
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/my_include/CVS/Repository (renamed from lib/dialyzer/test/options1_tests_SUITE_data/my_include/CVS/Repository)0
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/my_include/CVS/Root (renamed from lib/dialyzer/test/options1_tests_SUITE_data/my_include/CVS/Root)0
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/my_include/erl_bits.hrl43
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/my_include/erl_compile.hrl41
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/results/compiler35
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_asm.erl358
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_block.erl601
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_bool.erl617
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_clean.erl232
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_dict.erl196
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_disasm.erl964
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_flatten.erl137
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_jump.erl477
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_listing.erl117
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_opcodes.erl (renamed from lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_opcodes.erl)0
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_opcodes.hrl11
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_type.erl551
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_validator.erl1022
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl.erl4169
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl_clauses.erl409
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl_inline.erl2762
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl_trees.erl801
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/compile.erl1109
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/core_lib.erl509
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/core_lint.erl515
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/core_parse.erl4909
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/core_parse.hrl111
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/core_pp.erl430
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/core_scan.erl495
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/erl_bifs.erl486
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/rec_env.erl611
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/sys_expand_pmod.erl425
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/sys_pre_attributes.erl212
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/sys_pre_expand.erl1026
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_codegen.erl1755
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_core.erl1319
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_kernel.erl1567
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_kernel.hrl77
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_kernel_pp.erl444
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_life.erl448
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_life.hrl24
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE.erl54
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/my_include/erl_bits.hrl43
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/my_include/erl_compile.hrl42
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/results/compiler35
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_asm.erl358
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_block.erl601
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_bool.erl617
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_clean.erl232
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_dict.erl196
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_disasm.erl964
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_flatten.erl137
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_jump.erl477
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_listing.erl117
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_opcodes.hrl12
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_type.erl551
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_validator.erl1022
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/cerl.erl4169
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/cerl_clauses.erl409
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/cerl_inline.erl2762
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/cerl_trees.erl801
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/compile.erl1109
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_lib.erl509
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_lint.erl515
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_parse.erl4911
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_parse.hrl111
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_pp.erl430
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_scan.erl495
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/erl_bifs.erl486
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/rec_env.erl611
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/sys_expand_pmod.erl425
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/sys_pre_attributes.erl212
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/sys_pre_expand.erl1026
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_codegen.erl1755
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_core.erl1320
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_kernel.erl1568
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_kernel.hrl77
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_kernel_pp.erl444
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_life.erl448
-rw-r--r--lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_life.hrl25
-rw-r--r--lib/dialyzer/test/options2_SUITE_data/dialyzer_options (renamed from lib/dialyzer/test/options2_tests_SUITE_data/dialyzer_options)0
-rw-r--r--lib/dialyzer/test/options2_SUITE_data/results/kernel (renamed from lib/dialyzer/test/options2_tests_SUITE_data/results/kernel)0
-rw-r--r--lib/dialyzer/test/options2_SUITE_data/src/kernel/global.erl1999
-rw-r--r--lib/dialyzer/test/options2_tests_SUITE.erl52
-rw-r--r--lib/dialyzer/test/options2_tests_SUITE_data/src/kernel/global.erl1999
-rw-r--r--lib/dialyzer/test/plt_SUITE.erl21
-rw-r--r--lib/dialyzer/test/plt_tests_SUITE.erl21
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/dialyzer_options (renamed from lib/dialyzer/test/r9c_tests_SUITE_data/dialyzer_options)0
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/results/asn1106
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/results/inets64
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/results/mnesia37
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/Makefile142
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/Restrictions.txt55
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1.app.src (renamed from lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1.app.src)0
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1.appup.src162
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1_db.erl160
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1_records.hrl96
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct.erl1904
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_check.erl5566
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_constructed_ber.erl1468
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_constructed_ber_bin_v2.erl1357
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_constructed_per.erl1234
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen.erl1664
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_ber.erl1525
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_ber_bin_v2.erl1562
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_per.erl1189
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_per_rt2ct.erl1811
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_name.erl225
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_parser.yrl1162
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_parser2.erl2763
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_pretty_format.erl197
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_tok.erl351
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_value.erl330
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt.erl69
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_ber_bin.erl2310
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_ber_bin_v2.erl1849
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_check.erl333
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_driver_handler.erl108
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per.erl1593
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per_bin.erl2176
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per_bin_rt2ct.erl2102
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per_v1.erl1827
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/notes_history.sgml97
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/notes_latest.sgml97
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/Makefile178
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/ftp.erl1582
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/http.erl260
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/http.hrl127
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/http_lib.erl745
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/httpc_handler.erl724
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/httpc_manager.erl542
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd.erl594
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd.hrl77
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_acceptor.erl174
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_acceptor_sup.erl116
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_conf.erl688
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_example.erl134
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_manager.erl1029
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_misc_sup.erl113
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_parse.erl344
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_request_handler.erl994
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_response.erl437
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_socket.erl381
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_sup.erl202
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_util.erl773
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_verbosity.erl93
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_verbosity.hrl62
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/inets.app.src56
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/inets.appup.src133
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/inets.config2
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/inets_sup.erl158
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/jnets_httpd.hrl138
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_actions.erl92
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_alias.erl175
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth.erl748
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth.hrl26
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth_dets.erl222
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth_mnesia.erl269
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth_plain.erl338
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth_server.erl422
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_browser.erl213
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_cgi.erl692
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_dir.erl266
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_disk_log.erl404
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_esi.erl481
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_get.erl151
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_head.erl89
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_htaccess.erl1136
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_include.erl722
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_log.erl250
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_range.erl380
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_responsecontrol.erl320
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_security.erl307
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_security_server.erl727
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_trace.erl64
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/uri.erl349
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/Makefile136
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.app.src50
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.appup.src6
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.erl2191
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.hrl117
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_backup.erl194
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_bup.erl1168
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_checkpoint.erl1283
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_checkpoint_sup.erl39
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_controller.erl2010
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_dumper.erl1092
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_event.erl260
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_frag.erl1201
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_frag_hash.erl118
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_frag_old_hash.erl127
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_index.erl379
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_kernel_sup.erl60
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_late_loader.erl95
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_lib.erl1276
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_loader.erl805
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_locker.erl1021
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_log.erl1019
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_monitor.erl776
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_recover.erl1174
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_registry.erl276
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_schema.erl2898
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_snmp_hook.erl271
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_snmp_sup.erl39
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_sp.erl35
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_subscr.erl491
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_sup.erl136
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_text.erl189
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_tm.erl2173
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE.erl64
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/results/asn1106
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/results/inets59
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/results/mnesia34
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/Makefile151
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/Restrictions.txt55
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1.appup.src166
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1_db.erl162
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1_records.hrl96
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct.erl1904
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_check.erl5567
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_constructed_ber.erl1468
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_constructed_ber_bin_v2.erl1357
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_constructed_per.erl1235
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen.erl1664
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen_ber.erl1525
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen_ber_bin_v2.erl1568
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen_per.erl1190
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen_per_rt2ct.erl1811
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_name.erl225
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_parser.yrl1175
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_parser2.erl2764
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_pretty_format.erl199
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_tok.erl351
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_value.erl330
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt.erl69
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_ber_bin.erl2310
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_ber_bin_v2.erl1869
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_check.erl333
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_driver_handler.erl108
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per.erl1609
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per_bin.erl2182
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per_bin_rt2ct.erl2102
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per_v1.erl1843
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/notes_history.sgml100
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/notes_latest.sgml100
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/Makefile178
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/ftp.erl1582
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/http.erl260
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/http.hrl127
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/http_lib.erl745
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpc_handler.erl724
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpc_manager.erl542
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd.erl596
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd.hrl77
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_acceptor.erl176
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_acceptor_sup.erl118
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_conf.erl688
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_example.erl134
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_manager.erl1030
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_misc_sup.erl116
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_parse.erl348
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_request_handler.erl995
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_response.erl437
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_socket.erl381
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_sup.erl203
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_util.erl777
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_verbosity.erl94
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_verbosity.hrl65
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/inets.app.src56
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/inets.appup.src135
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/inets.config2
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/inets_sup.erl158
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/jnets_httpd.hrl138
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_actions.erl92
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_alias.erl175
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth.erl750
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth.hrl27
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth_dets.erl222
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth_mnesia.erl276
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth_plain.erl344
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth_server.erl424
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_browser.erl214
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_cgi.erl694
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_dir.erl266
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_disk_log.erl405
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_esi.erl490
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_get.erl179
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_head.erl89
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_htaccess.erl1150
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_include.erl726
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_log.erl250
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_range.erl397
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_responsecontrol.erl337
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_security.erl307
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_security_server.erl728
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_trace.erl69
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/uri.erl349
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/Makefile137
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia.app.src52
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia.appup.src6
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia.erl2191
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia.hrl118
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_backup.erl195
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_bup.erl1169
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_checkpoint.erl1284
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_checkpoint_sup.erl39
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_controller.erl2012
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_dumper.erl1092
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_event.erl263
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_frag.erl1201
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_frag_hash.erl118
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_frag_old_hash.erl127
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_index.erl380
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_kernel_sup.erl62
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_late_loader.erl95
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_lib.erl1278
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_loader.erl805
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_locker.erl1022
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_log.erl1019
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_monitor.erl776
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_recover.erl1175
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_registry.erl277
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_schema.erl2899
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_snmp_hook.erl271
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_snmp_sup.erl39
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_sp.erl39
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_subscr.erl492
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_sup.erl137
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_text.erl191
-rw-r--r--lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_tm.erl2173
-rw-r--r--lib/dialyzer/test/race_SUITE_data/dialyzer_options (renamed from lib/dialyzer/test/race_tests_SUITE_data/dialyzer_options)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_args1 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args1)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_args2 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args2)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_args3 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args3)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_args4 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args4)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_args5 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args5)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_args6 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args6)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_args7 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args7)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_args8 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args8)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow1 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_control_flow1)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow2 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_control_flow2)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow3 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_control_flow3)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow4 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_control_flow4)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow5 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_control_flow5)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race1 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_diff_atoms_race1)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race2 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_diff_atoms_race2)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race3 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_diff_atoms_race3)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race4 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_diff_atoms_race4)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race5 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_diff_atoms_race5)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race6 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_diff_atoms_race6)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_double1 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_double1)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_double2 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_double2)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_funs1 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_funs1)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_funs2 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_funs2)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_new (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_new)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_param (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_param)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_public2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/extract_translations5
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_diff_atoms_race1 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_diff_atoms_race1)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_diff_atoms_race2 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_diff_atoms_race2)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_one_write_two (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_one_write_two)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_two_write_one (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_two_write_one)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double1 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_write_double1)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double2 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_write_double2)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double3 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_write_double3)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double4 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_write_double4)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_one (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_write_one)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_two (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_write_two)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow1 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_control_flow1)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow2 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_control_flow2)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow3 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_control_flow3)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow4 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_control_flow4)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow5 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_control_flow5)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow6 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_control_flow6)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_atoms_no_race (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_atoms_no_race)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_atoms_race (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_atoms_race)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions1)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_nested (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions1_nested)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_pathsens (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions1_pathsens)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_twice (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions1_twice)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions2)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_nested (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions2_nested)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_pathsens (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions2_pathsens)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_twice (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions2_twice)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions3)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3_nested (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions3_nested)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3_pathsens (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions3_pathsens)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions4 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions4)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions5 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions5)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions6 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions6)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules1)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1_pathsens (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules1_pathsens)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1_rec (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules1_rec)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules2)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2_pathsens (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules2_pathsens)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2_rec (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules2_rec)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules3 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules3)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules_nested (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules_nested)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules_twice (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules_twice)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_vars_no_race (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_vars_no_race)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_vars_race (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_vars_race)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module1 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module1)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module2 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module2)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module3 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module3)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module4 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module4)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module5 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module5)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module6 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module6)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module7 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module7)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module8 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module8)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_param (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_param)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_param_inter_module (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_param_inter_module)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function1 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function1)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function2 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function2)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function3 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function3)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function4 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function4)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function5 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function5)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function6 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function6)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function7 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function7)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function8 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function8)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_try_catch (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_try_catch)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars1 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars1)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars10 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars10)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars11 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars11)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars12 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars12)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars13 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars13)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars14 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars14)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars15 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars15)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars16 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars16)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars17 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars17)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars18 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars18)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars19 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars19)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars2 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars2)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars20 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars20)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars21 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars21)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars22 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars22)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars3 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars3)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars4 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars4)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars5 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars5)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars6 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars6)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars7 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars7)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars8 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars8)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars9 (renamed from lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars9)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_args1.erl17
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_args2.erl17
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_args3.erl17
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_args4.erl17
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_args5.erl17
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_args6.erl17
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_args7.erl17
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_args8.erl16
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow1.erl20
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow2.erl26
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow3.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_control_flow3.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow4.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_control_flow4.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow5.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_control_flow5.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race1.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race2.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race3.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race4.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race5.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race6.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_double1.erl28
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_double2.erl28
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_funs1.erl18
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_funs2.erl18
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_new.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_new.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_param.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_param.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_public.erl23
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/extract_translations.erl293
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_diff_atoms_race1.erl33
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_diff_atoms_race2.erl37
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_one_write_two.erl20
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_two_write_one.erl20
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double1.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_double1.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double2.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_double2.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double3.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_double3.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double4.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_double4.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_one.erl20
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_two.erl20
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow1.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow1.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow2.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow2.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow3.erl25
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow4.erl29
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow5.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow5.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow6.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow6.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_atoms_no_race.erl23
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_atoms_race.erl34
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions1.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_nested.erl23
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_pathsens.erl32
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_twice.erl30
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2.erl25
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_nested.erl20
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_pathsens.erl29
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_twice.erl27
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3.erl11
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3_nested.erl21
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3_pathsens.erl29
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions4.erl32
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions5.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions6.erl29
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules1.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules1.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules2.erl11
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules1_pathsens.erl26
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules2_pathsens.erl12
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules1_rec.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules1_rec.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules2_rec.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules2_rec.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules3.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules3.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules4.erl11
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules3_pathsens.erl25
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules4_pathsens.erl13
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules3_rec.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules3_rec.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules4_rec.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules4_rec.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules5.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules5.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules6.erl11
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules1_nested.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules1_nested.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules2_nested.erl11
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules3_nested.erl11
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules1_twice.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules1_twice.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules2_twice.erl11
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_vars_no_race.erl13
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_vars_race.erl19
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module1.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module1.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module2.erl11
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module3.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module3.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module4.erl14
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module5.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module5.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module6.erl14
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module7.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module7.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module8.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module8.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module10.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module10.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module9.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module9.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module11.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module11.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module12.erl14
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module13.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module13.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module14.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module15.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module15.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module16.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_param.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_param.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module1.erl8
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module2.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module2.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function1.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function1.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function2.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function2.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function3.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function3.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function4.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function4.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function5.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function5.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function6.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function6.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function7.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function7.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function8.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function8.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_try_catch.erl25
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars1.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars1.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars10.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars10.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars11.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars11.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars12.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars12.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars13.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars13.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars14.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars14.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars15.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars15.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars16.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars16.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars17.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars17.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars18.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars18.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars19.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars19.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars2.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars2.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars20.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars20.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars21.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars21.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars22.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars22.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars3.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars3.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars4.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars4.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars5.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars5.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars6.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars6.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars7.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars7.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars8.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars8.erl)0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars9.erl (renamed from lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars9.erl)0
-rw-r--r--lib/dialyzer/test/race_tests_SUITE.erl799
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/results/extract_translations5
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args1.erl17
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args2.erl17
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args3.erl17
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args4.erl17
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args5.erl17
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args6.erl17
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args7.erl17
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args8.erl16
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_control_flow1.erl20
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_control_flow2.erl26
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race1.erl22
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race2.erl22
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race3.erl22
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race4.erl22
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race5.erl22
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race6.erl22
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_double1.erl28
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_double2.erl28
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_funs1.erl18
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_funs2.erl18
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/extract_translations.erl294
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_diff_atoms_race1.erl33
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_diff_atoms_race2.erl37
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_one_write_two.erl22
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_two_write_one.erl22
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_one.erl22
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_two.erl22
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow3.erl25
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow4.erl29
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_atoms_no_race.erl24
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_atoms_race.erl35
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions1_nested.erl23
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions1_pathsens.erl32
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions1_twice.erl30
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions2.erl25
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions2_nested.erl20
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions2_pathsens.erl29
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions2_twice.erl27
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions3.erl11
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions3_nested.erl21
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions3_pathsens.erl29
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions4.erl32
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions5.erl22
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions6.erl29
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules2.erl11
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules1_pathsens.erl26
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules2_pathsens.erl12
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules4.erl11
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules3_pathsens.erl25
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules4_pathsens.erl13
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules6.erl11
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules2_nested.erl11
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules3_nested.erl11
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules2_twice.erl11
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_vars_no_race.erl13
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_vars_race.erl19
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module2.erl11
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module4.erl14
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module6.erl14
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module12.erl14
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module14.erl23
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module16.erl23
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module1.erl9
-rw-r--r--lib/dialyzer/test/race_tests_SUITE_data/src/whereis_try_catch.erl25
-rwxr-xr-xlib/dialyzer/test/remake9
-rw-r--r--lib/dialyzer/test/small_SUITE_data/dialyzer_options (renamed from lib/dialyzer/test/small_tests_SUITE_data/dialyzer_options)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/andalso_test (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/andalso_test)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/app_call (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/app_call)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/appmon_place (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/appmon_place)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/areq (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/areq)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/atom_call (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/atom_call)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/atom_widen (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/atom_widen)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/blame_contract_range4
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/bs_fail_constr (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/bs_fail_constr)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/bs_utf8 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/bs_utf8)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/cerl_hipeify (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/cerl_hipeify)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/comm_layer (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/comm_layer)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/common_eunit2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/compare1 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/compare1)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/comparisons153
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/confusing_record_warning3
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/confusing_warning (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/confusing_warning)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/contract1 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/contract1)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/contract2 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/contract2)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/contract3 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/contract3)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/contract5 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/contract5)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/eqeq (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/eqeq)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/ets_select (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/ets_select)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/exhaust_case (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/exhaust_case)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/failing_funs20
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/failing_guard1 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/failing_guard1)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/flatten2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/fun_app (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/fun_app)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/fun_ref_match (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/fun_ref_match)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/gencall (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/gencall)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/gs_make (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/gs_make)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/guard_warnings97
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/guards17
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/inf_loop2 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/inf_loop2)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/invalid_specs3
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/letrec1 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/letrec1)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/list_match (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/list_match)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/lzip (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/lzip)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/make_tuple (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/make_tuple)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/minus_minus (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/minus_minus)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/mod_info (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/mod_info)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/my_filter (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/my_filter)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/my_sofs3
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/no_match (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/no_match)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/no_unused_fun (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/no_unused_fun)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/no_unused_fun2 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/no_unused_fun2)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/non_existing (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/non_existing)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/none_scc_inf_loop5
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/not_bogus_warning3
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/not_guard_crash (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/not_guard_crash)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/or_bug (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/or_bug)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/orelsebug (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/orelsebug)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/orelsebug2 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/orelsebug2)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/overloaded1 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/overloaded1)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/port_info_test (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/port_info_test)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/process_info_test (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/process_info_test)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/pubsub (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/pubsub)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/receive1 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/receive1)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/record_construct (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/record_construct)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/record_pat (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/record_pat)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/record_send_test (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/record_send_test)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/record_test (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/record_test)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/recursive_types1 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types1)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/recursive_types2 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types2)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/recursive_types3 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types3)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/recursive_types4 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types4)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/recursive_types5 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types5)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/recursive_types6 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types6)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/recursive_types7 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types7)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/refine_failing2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/toth (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/toth)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/trec (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/trec)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/try1 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/try1)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/tuple1 (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/tuple1)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/tuple_set_crash15
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/unsafe_beamcode_bug (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/unsafe_beamcode_bug)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/unused_cases (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/unused_cases)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/unused_clauses (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/unused_clauses)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/zero_tuple (renamed from lib/dialyzer/test/small_tests_SUITE_data/results/zero_tuple)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/app_call.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/app_call.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/appmon_place.erl70
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/areq.erl11
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/atom_call.erl14
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/atom_guard.erl8
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/atom_widen.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/atom_widen.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/bin_compr.erl16
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/binary_lc_bug.erl8
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/blame_contract_range.erl16
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/bs_fail_constr.erl15
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/bs_utf8.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/bs_utf8.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/cerl_hipeify.erl684
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/codec_can.erl35
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_acceptor.erl119
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_connection.erl206
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_layer.erl83
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_layer.hrl29
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_logger.erl143
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_port.erl240
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_port_sup.erl88
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/common_eunit.erl121
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/compare1.erl21
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/comparisons.erl322
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/confusing_record_warning.erl19
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/confusing_warning.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/confusing_warning.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/contract2.erl18
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/contract3.erl33
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/contract5.erl15
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/disj_norm_form.erl23
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/eqeq.erl15
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/ets_select.erl11
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/ets_update_counter.erl25
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/exhaust_case.erl23
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/failing_funs.erl250
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/failing_guard1.erl15
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/false_false.erl32
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl24
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/flatten.erl18
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/fun_app.erl41
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/fun_ref_match.erl21
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/fun_ref_record.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/fun_ref_record.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/gencall.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/gencall.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/gs_make.erl260
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/guard_warnings.erl118
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/guards.erl136
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/inf_loop2.erl23
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/invalid_specs/invalid_spec1.erl28
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/invalid_specs/invalid_spec2.erl11
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/letrec1.erl13
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/list_match.erl20
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/list_to_bitstring.erl21
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/lzip.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/lzip.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/make_tuple.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/make_tuple.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/minus_minus.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/minus_minus.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/mod_info.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/mod_info.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/my_filter.erl17
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/my_sofs.erl83
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/no_match.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/no_match.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/no_return_bug.erl42
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/no_unused_fun.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/no_unused_fun.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/no_unused_fun2.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/no_unused_fun2.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/non_existing.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/non_existing.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/none_scc_inf_loop.erl21
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/not_bogus_warning.erl25
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/not_guard_crash.erl49
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/nowarnunused.erl7
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/or_bug.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/or_bug.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/orelsebug.erl16
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/orelsebug2.erl23
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/overloaded1.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/overloaded1.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/param_types_crash.erl77
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/port_info_test.erl33
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/process_info_test.erl20
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/pubsub/pubsub_api.erl99
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/pubsub/pubsub_publish.erl49
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/rebar_no_return.erl19
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/receive1.erl16
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/record_construct.erl21
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/record_pat.erl15
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/record_send_test.erl32
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/record_test.erl22
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/recursive_types1.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types1.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/recursive_types2.erl12
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/recursive_types3.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types3.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/recursive_types4.erl13
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/recursive_types5.erl13
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/recursive_types6.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types6.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/recursive_types7.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types7.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/refine_bug1.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/refine_bug1.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/refine_failing.erl26
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/toth.erl99
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/trec.erl37
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/try1.erl26
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/tuple1.erl29
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/tuple_set_crash.erl207
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/unsafe_beamcode_bug.erl14
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/unused_cases.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/unused_cases.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/unused_clauses.erl (renamed from lib/dialyzer/test/small_tests_SUITE_data/src/unused_clauses.erl)0
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/zero_tuple.erl12
-rw-r--r--lib/dialyzer/test/small_tests_SUITE.erl483
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/results/flatten2
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/results/my_sofs3
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/appmon_place.erl71
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/areq.erl12
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/atom_call.erl14
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/atom_guard.erl9
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/bs_fail_constr.erl16
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/cerl_hipeify.erl684
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_acceptor.erl120
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_connection.erl206
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_layer.erl83
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_layer.hrl30
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_logger.erl143
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_port.erl240
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_port_sup.erl90
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/compare1.erl21
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/contract2.erl18
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/contract3.erl34
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/contract5.erl15
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/disj_norm_form.erl23
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/eqeq.erl16
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/ets_select.erl12
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/exhaust_case.erl24
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/failing_guard1.erl16
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/flatten.erl18
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/fun_app.erl42
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/fun_ref_match.erl21
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/gs_make.erl261
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/inf_loop2.erl23
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/letrec1.erl13
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/list_match.erl20
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/my_filter.erl17
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/my_sofs.erl83
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/not_guard_crash.erl49
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/orelsebug.erl17
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/orelsebug2.erl23
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/port_info_test.erl34
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/process_info_test.erl21
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/pubsub/pubsub_api.erl99
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/pubsub/pubsub_publish.erl50
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/receive1.erl17
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/record_construct.erl22
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/record_pat.erl19
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/record_send_test.erl33
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/record_test.erl24
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types2.erl12
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types4.erl13
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types5.erl13
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/toth.erl99
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/trec.erl37
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/try1.erl27
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/tuple1.erl29
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/unsafe_beamcode_bug.erl15
-rw-r--r--lib/dialyzer/test/small_tests_SUITE_data/src/zero_tuple.erl13
-rw-r--r--lib/dialyzer/test/user_SUITE_data/dialyzer_options (renamed from lib/dialyzer/test/user_tests_SUITE_data/dialyzer_options)0
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/broken_dialyzer (renamed from lib/dialyzer/test/user_tests_SUITE_data/results/broken_dialyzer)0
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/gcpFlowControl (renamed from lib/dialyzer/test/user_tests_SUITE_data/results/gcpFlowControl)0
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/qlc_error (renamed from lib/dialyzer/test/user_tests_SUITE_data/results/qlc_error)0
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/spvcOrig (renamed from lib/dialyzer/test/user_tests_SUITE_data/results/spvcOrig)0
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/wsp_pdu (renamed from lib/dialyzer/test/user_tests_SUITE_data/results/wsp_pdu)0
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/broken_dialyzer.erl130
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/gcp.hrl166
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/gcpFlowControl.erl397
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/qlc_error.erl15
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/spvcOrig.erl3520
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/wdp.hrl96
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/wsp.hrl239
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/wsp_pdu.erl5423
-rw-r--r--lib/dialyzer/test/user_tests_SUITE.erl78
-rw-r--r--lib/dialyzer/test/user_tests_SUITE_data/src/broken_dialyzer.erl130
-rw-r--r--lib/dialyzer/test/user_tests_SUITE_data/src/gcp.hrl166
-rw-r--r--lib/dialyzer/test/user_tests_SUITE_data/src/gcpFlowControl.erl397
-rw-r--r--lib/dialyzer/test/user_tests_SUITE_data/src/qlc_error.erl15
-rw-r--r--lib/dialyzer/test/user_tests_SUITE_data/src/spvcOrig.erl3523
-rw-r--r--lib/dialyzer/test/user_tests_SUITE_data/src/wdp.hrl97
-rw-r--r--lib/dialyzer/test/user_tests_SUITE_data/src/wsp.hrl242
-rw-r--r--lib/dialyzer/test/user_tests_SUITE_data/src/wsp_pdu.erl5423
-rw-r--r--lib/dialyzer/vsn.mk2
-rw-r--r--lib/diameter/.gitignore58
-rw-r--r--lib/diameter/AUTHORS10
-rw-r--r--lib/diameter/Makefile.in88
-rw-r--r--lib/diameter/TAR.exclude2
-rw-r--r--lib/diameter/aclocal.m465
-rwxr-xr-xlib/diameter/autoconf/config.guess1519
-rwxr-xr-xlib/diameter/autoconf/config.sub1630
-rwxr-xr-xlib/diameter/autoconf/configure.vxworks147
-rwxr-xr-xlib/diameter/autoconf/install-sh519
-rw-r--r--lib/diameter/autoconf/vxworks/sed.general125
-rw-r--r--lib/diameter/autoconf/vxworks/sed.vxworks_cpu3245
-rw-r--r--lib/diameter/autoconf/vxworks/sed.vxworks_ppc3252
-rw-r--r--lib/diameter/autoconf/vxworks/sed.vxworks_ppc60351
-rw-r--r--lib/diameter/autoconf/vxworks/sed.vxworks_ppc603_nolongcall51
-rw-r--r--lib/diameter/autoconf/vxworks/sed.vxworks_ppc86050
-rw-r--r--lib/diameter/autoconf/vxworks/sed.vxworks_simlinux59
-rw-r--r--lib/diameter/autoconf/vxworks/sed.vxworks_simso64
-rw-r--r--lib/diameter/autoconf/vxworks/sed.vxworks_sparc38
-rwxr-xr-xlib/diameter/bin/diameterc155
-rw-r--r--lib/diameter/configure.in138
-rw-r--r--lib/diameter/doc/html/.gitignore0
-rw-r--r--lib/diameter/doc/man1/.gitignore0
-rw-r--r--lib/diameter/doc/man3/.gitignore0
-rw-r--r--lib/diameter/doc/man4/.gitignore0
-rw-r--r--lib/diameter/doc/pdf/.gitignore0
-rw-r--r--lib/diameter/doc/src/.gitignore2
-rw-r--r--lib/diameter/doc/src/Makefile198
-rw-r--r--lib/diameter/doc/src/book.xml56
-rw-r--r--lib/diameter/doc/src/depend.sed38
-rw-r--r--lib/diameter/doc/src/diameter.xml1196
-rw-r--r--lib/diameter/doc/src/diameter_app.xml615
-rw-r--r--lib/diameter/doc/src/diameter_compile.xml124
-rw-r--r--lib/diameter/doc/src/diameter_dict.xml613
-rw-r--r--lib/diameter/doc/src/diameter_examples.xml45
-rw-r--r--lib/diameter/doc/src/diameter_intro.xml95
-rw-r--r--lib/diameter/doc/src/diameter_sctp.xml135
-rw-r--r--lib/diameter/doc/src/diameter_soc.xml114
-rw-r--r--lib/diameter/doc/src/diameter_tcp.xml149
-rw-r--r--lib/diameter/doc/src/diameter_transport.xml241
-rw-r--r--lib/diameter/doc/src/diameter_using.xml43
-rw-r--r--lib/diameter/doc/src/files.mk52
-rw-r--r--lib/diameter/doc/src/notes.gifbin0 -> 2005 bytes
-rw-r--r--lib/diameter/doc/src/notes.xml233
-rw-r--r--lib/diameter/doc/src/ref_man.xml48
-rw-r--r--lib/diameter/doc/src/user_man.xml44
-rw-r--r--lib/diameter/doc/standard/draft-ietf-dime-capablities-update-07.txt392
-rw-r--r--lib/diameter/doc/standard/draft-ietf-dime-rfc3588bis-26.txt8681
-rw-r--r--lib/diameter/doc/standard/rfc3124.txt1235
-rw-r--r--lib/diameter/doc/standard/rfc3539.txt2299
-rw-r--r--lib/diameter/doc/standard/rfc3588.txt8235
-rw-r--r--lib/diameter/doc/standard/rfc4005.txt4763
-rw-r--r--lib/diameter/doc/standard/rfc4006.txt6387
-rw-r--r--lib/diameter/doc/standard/rfc4072.txt1851
-rw-r--r--lib/diameter/doc/standard/rfc4740.txt4035
-rw-r--r--lib/diameter/doc/standard/rfc5447.txt955
-rw-r--r--lib/diameter/ebin/.gitignore5
-rw-r--r--lib/diameter/examples/.gitignore3
-rw-r--r--lib/diameter/examples/GNUmakefile35
-rw-r--r--lib/diameter/examples/client.erl125
-rw-r--r--lib/diameter/examples/client_cb.erl103
-rw-r--r--lib/diameter/examples/peer.erl139
-rw-r--r--lib/diameter/examples/redirect.erl70
-rw-r--r--lib/diameter/examples/redirect_cb.erl63
-rw-r--r--lib/diameter/examples/relay.erl92
-rw-r--r--lib/diameter/examples/relay_cb.erl69
-rw-r--r--lib/diameter/examples/sctp.erl113
-rw-r--r--lib/diameter/examples/server.erl88
-rw-r--r--lib/diameter/examples/server_cb.erl115
-rw-r--r--lib/diameter/include/diameter.hrl130
-rw-r--r--lib/diameter/include/diameter_gen.hrl431
-rw-r--r--lib/diameter/info3
-rw-r--r--lib/diameter/make/release_targets.mk92
-rw-r--r--lib/diameter/make/rules.mk.in195
-rw-r--r--lib/diameter/make/subdir.mk53
-rw-r--r--lib/diameter/make/target.mk33
-rw-r--r--lib/diameter/src/Makefile43
-rw-r--r--lib/diameter/src/app/.gitignore6
-rw-r--r--lib/diameter/src/app/Makefile218
-rw-r--r--lib/diameter/src/app/depend.sed31
-rw-r--r--lib/diameter/src/app/diameter.app.src28
-rw-r--r--lib/diameter/src/app/diameter.appup.src47
-rw-r--r--lib/diameter/src/app/diameter.erl190
-rw-r--r--lib/diameter/src/app/diameter.mk.in47
-rw-r--r--lib/diameter/src/app/diameter_app.erl36
-rw-r--r--lib/diameter/src/app/diameter_callback.erl91
-rw-r--r--lib/diameter/src/app/diameter_capx.erl405
-rw-r--r--lib/diameter/src/app/diameter_codec.erl561
-rw-r--r--lib/diameter/src/app/diameter_config.erl676
-rw-r--r--lib/diameter/src/app/diameter_dbg.erl516
-rw-r--r--lib/diameter/src/app/diameter_dict.erl153
-rw-r--r--lib/diameter/src/app/diameter_exprecs.erl301
-rw-r--r--lib/diameter/src/app/diameter_gen_base_accounting.dia68
-rw-r--r--lib/diameter/src/app/diameter_gen_base_rfc3588.dia413
-rw-r--r--lib/diameter/src/app/diameter_gen_relay.dia24
-rw-r--r--lib/diameter/src/app/diameter_info.erl869
-rw-r--r--lib/diameter/src/app/diameter_internal.hrl80
-rw-r--r--lib/diameter/src/app/diameter_lib.erl272
-rw-r--r--lib/diameter/src/app/diameter_misc_sup.erl58
-rw-r--r--lib/diameter/src/app/diameter_peer.erl225
-rw-r--r--lib/diameter/src/app/diameter_peer_fsm.erl777
-rw-r--r--lib/diameter/src/app/diameter_peer_fsm_sup.erl63
-rw-r--r--lib/diameter/src/app/diameter_reg.erl327
-rw-r--r--lib/diameter/src/app/diameter_service.erl2903
-rw-r--r--lib/diameter/src/app/diameter_service_sup.erl64
-rw-r--r--lib/diameter/src/app/diameter_session.erl172
-rw-r--r--lib/diameter/src/app/diameter_stats.erl342
-rw-r--r--lib/diameter/src/app/diameter_sup.erl101
-rw-r--r--lib/diameter/src/app/diameter_sync.erl550
-rw-r--r--lib/diameter/src/app/diameter_types.erl537
-rw-r--r--lib/diameter/src/app/diameter_types.hrl139
-rw-r--r--lib/diameter/src/app/diameter_watchdog.erl571
-rw-r--r--lib/diameter/src/app/diameter_watchdog_sup.erl60
-rw-r--r--lib/diameter/src/app/modules.mk70
-rw-r--r--lib/diameter/src/compiler/.gitignore3
-rw-r--r--lib/diameter/src/compiler/Makefile131
-rw-r--r--lib/diameter/src/compiler/diameter_codegen.erl827
-rw-r--r--lib/diameter/src/compiler/diameter_forms.hrl52
-rw-r--r--lib/diameter/src/compiler/diameter_make.erl120
-rw-r--r--lib/diameter/src/compiler/diameter_spec_scan.erl157
-rw-r--r--lib/diameter/src/compiler/diameter_spec_util.erl1068
-rw-r--r--lib/diameter/src/compiler/modules.mk27
-rw-r--r--lib/diameter/src/subdirs.mk21
-rw-r--r--lib/diameter/src/transport/.gitignore3
-rw-r--r--lib/diameter/src/transport/Makefile141
-rw-r--r--lib/diameter/src/transport/diameter_etcp.erl311
-rw-r--r--lib/diameter/src/transport/diameter_etcp_sup.erl64
-rw-r--r--lib/diameter/src/transport/diameter_sctp.erl696
-rw-r--r--lib/diameter/src/transport/diameter_sctp_sup.erl74
-rw-r--r--lib/diameter/src/transport/diameter_tcp.erl707
-rw-r--r--lib/diameter/src/transport/diameter_tcp_sup.erl78
-rw-r--r--lib/diameter/src/transport/diameter_transport_sup.erl68
-rw-r--r--lib/diameter/src/transport/modules.mk29
-rw-r--r--lib/diameter/subdirs.mk20
-rw-r--r--lib/diameter/test/.gitignore3
-rw-r--r--lib/diameter/test/Makefile184
-rw-r--r--lib/diameter/test/depend.sed31
-rw-r--r--lib/diameter/test/diameter.cover6
-rw-r--r--lib/diameter/test/diameter.spec1
-rw-r--r--lib/diameter/test/diameter_app_SUITE.erl263
-rw-r--r--lib/diameter/test/diameter_codec_SUITE.erl76
-rw-r--r--lib/diameter/test/diameter_codec_test.erl500
-rw-r--r--lib/diameter/test/diameter_ct.erl55
-rw-r--r--lib/diameter/test/diameter_ct.hrl21
-rw-r--r--lib/diameter/test/diameter_dict_SUITE.erl151
-rw-r--r--lib/diameter/test/diameter_enum.erl406
-rw-r--r--lib/diameter/test/diameter_failover_SUITE.erl262
-rw-r--r--lib/diameter/test/diameter_reg_SUITE.erl119
-rw-r--r--lib/diameter/test/diameter_relay_SUITE.erl368
-rw-r--r--lib/diameter/test/diameter_stats_SUITE.erl92
-rw-r--r--lib/diameter/test/diameter_sync_SUITE.erl139
-rw-r--r--lib/diameter/test/diameter_tls_SUITE.erl411
-rw-r--r--lib/diameter/test/diameter_tls_SUITE_data/Makefile.ca43
-rw-r--r--lib/diameter/test/diameter_traffic_SUITE.erl754
-rw-r--r--lib/diameter/test/diameter_transport_SUITE.erl436
-rw-r--r--lib/diameter/test/diameter_util.erl316
-rw-r--r--lib/diameter/test/diameter_watchdog_SUITE.erl540
-rw-r--r--lib/diameter/test/modules.mk42
-rw-r--r--lib/diameter/vsn.mk25
-rw-r--r--lib/docbuilder/doc/src/character_entities.xml4
-rw-r--r--lib/docbuilder/doc/src/inline_tags.xml7
-rw-r--r--lib/docbuilder/doc/src/notes.xml40
-rw-r--r--lib/docbuilder/src/docb_gen.erl4
-rw-r--r--lib/docbuilder/src/docb_main.erl12
-rw-r--r--lib/docbuilder/src/docb_transform.erl2
-rw-r--r--lib/docbuilder/src/docb_xml_check.erl1
-rw-r--r--lib/docbuilder/test/Makefile2
-rw-r--r--lib/docbuilder/vsn.mk2
-rw-r--r--lib/edoc/Makefile2
-rw-r--r--lib/edoc/doc/Makefile2
-rw-r--r--lib/edoc/doc/overview.edoc15
-rw-r--r--lib/edoc/doc/src/Makefile2
-rw-r--r--lib/edoc/doc/src/notes.xml87
-rw-r--r--lib/edoc/include/Makefile2
-rw-r--r--lib/edoc/include/edoc_doclet.hrl2
-rw-r--r--lib/edoc/priv/edoc_generate.src3
-rw-r--r--lib/edoc/src/Makefile2
-rw-r--r--lib/edoc/src/edoc.erl21
-rw-r--r--lib/edoc/src/edoc.hrl4
-rw-r--r--lib/edoc/src/edoc_data.erl4
-rw-r--r--lib/edoc/src/edoc_doclet.erl6
-rw-r--r--lib/edoc/src/edoc_extract.erl27
-rw-r--r--lib/edoc/src/edoc_layout.erl22
-rw-r--r--lib/edoc/src/edoc_lib.erl24
-rw-r--r--lib/edoc/src/edoc_macros.erl2
-rw-r--r--lib/edoc/src/edoc_parser.yrl18
-rw-r--r--lib/edoc/src/edoc_refs.erl2
-rw-r--r--lib/edoc/src/edoc_report.erl4
-rw-r--r--lib/edoc/src/edoc_run.erl4
-rw-r--r--lib/edoc/src/edoc_scanner.erl4
-rw-r--r--lib/edoc/src/edoc_specs.erl16
-rw-r--r--lib/edoc/src/edoc_tags.erl120
-rw-r--r--lib/edoc/src/edoc_types.erl9
-rw-r--r--lib/edoc/src/edoc_types.hrl2
-rw-r--r--lib/edoc/src/edoc_wiki.erl27
-rw-r--r--lib/edoc/src/otpsgml_layout.erl6
-rw-r--r--lib/edoc/test/Makefile2
-rw-r--r--lib/edoc/test/edoc_SUITE.erl2
-rw-r--r--lib/edoc/vsn.mk2
-rw-r--r--lib/erl_docgen/doc/src/notes.xml61
-rw-r--r--lib/erl_docgen/priv/bin/specs_gen.escript101
-rwxr-xr-xlib/erl_docgen/priv/bin/xref_mod_app.escript7
-rw-r--r--lib/erl_docgen/priv/xsl/db_eix.xsl180
-rw-r--r--lib/erl_docgen/priv/xsl/db_html.xsl558
-rw-r--r--lib/erl_docgen/priv/xsl/db_man.xsl551
-rw-r--r--lib/erl_docgen/priv/xsl/db_pdf.xsl497
-rw-r--r--lib/erl_docgen/priv/xsl/db_pdf_params.xsl8
-rw-r--r--lib/erl_docgen/src/otp_specs.erl14
-rw-r--r--lib/erl_docgen/vsn.mk2
-rw-r--r--lib/erl_interface/doc/src/ei.xml8
-rw-r--r--lib/erl_interface/doc/src/erl_format.xml4
-rw-r--r--lib/erl_interface/doc/src/notes.xml85
-rw-r--r--lib/erl_interface/src/Makefile.in34
-rw-r--r--lib/erl_interface/src/connect/ei_resolve.c7
-rw-r--r--lib/erl_interface/src/encode/encode_atom.c8
-rw-r--r--lib/erl_interface/src/encode/encode_string.c8
-rw-r--r--lib/erl_interface/src/epmd/epmd_port.c9
-rw-r--r--lib/erl_interface/src/legacy/erl_connect.c5
-rw-r--r--lib/erl_interface/src/legacy/erl_fix_alloc.c6
-rw-r--r--lib/erl_interface/src/legacy/erl_timeout.c1
-rw-r--r--lib/erl_interface/src/misc/ei_decode_term.c10
-rw-r--r--lib/erl_interface/src/registry/reg_dump.c1
-rw-r--r--lib/erl_interface/src/registry/reg_restore.c5
-rw-r--r--lib/erl_interface/test/Makefile2
-rw-r--r--lib/erl_interface/test/all_SUITE_data/Makefile.src2
-rw-r--r--lib/erl_interface/test/port_call_SUITE_data/Makefile.src4
-rw-r--r--lib/erl_interface/vsn.mk2
-rw-r--r--lib/et/doc/src/notes.xml32
-rw-r--r--lib/et/src/et_wx_contents_viewer.erl4
-rw-r--r--lib/et/src/et_wx_viewer.erl10
-rw-r--r--lib/et/test/Makefile2
-rw-r--r--lib/et/vsn.mk2
-rw-r--r--lib/eunit/AUTHORS2
-rw-r--r--lib/eunit/Makefile2
-rw-r--r--lib/eunit/doc/.gitignore4
-rw-r--r--lib/eunit/doc/edoc-info3
-rw-r--r--lib/eunit/doc/erlang.pngbin2109 -> 0 bytes
-rw-r--r--lib/eunit/doc/eunit.html71
-rw-r--r--lib/eunit/doc/eunit_surefire.html78
-rw-r--r--lib/eunit/doc/index.html17
-rw-r--r--lib/eunit/doc/modules-frame.html13
-rw-r--r--lib/eunit/doc/overview-summary.html1032
-rw-r--r--lib/eunit/doc/overview.edoc5
-rw-r--r--lib/eunit/doc/packages-frame.html11
-rw-r--r--lib/eunit/doc/src/notes.xml97
-rw-r--r--lib/eunit/doc/stylesheet.css55
-rw-r--r--lib/eunit/examples/Makefile2
-rw-r--r--lib/eunit/include/eunit.hrl104
-rw-r--r--lib/eunit/src/Makefile13
-rw-r--r--lib/eunit/src/eunit.app.src16
-rw-r--r--lib/eunit/src/eunit.erl17
-rw-r--r--lib/eunit/src/eunit_autoexport.erl4
-rw-r--r--lib/eunit/src/eunit_data.erl74
-rw-r--r--lib/eunit/src/eunit_internal.hrl6
-rw-r--r--lib/eunit/src/eunit_lib.erl23
-rw-r--r--lib/eunit/src/eunit_listener.erl4
-rw-r--r--lib/eunit/src/eunit_proc.erl4
-rw-r--r--lib/eunit/src/eunit_serial.erl4
-rw-r--r--lib/eunit/src/eunit_server.erl11
-rw-r--r--lib/eunit/src/eunit_striptests.erl6
-rw-r--r--lib/eunit/src/eunit_surefire.erl88
-rw-r--r--lib/eunit/src/eunit_test.erl76
-rw-r--r--lib/eunit/src/eunit_tests.erl30
-rw-r--r--lib/eunit/src/eunit_tty.erl4
-rw-r--r--lib/eunit/vsn.mk2
-rw-r--r--lib/gs/contribs/bonk/sounder.erl20
-rw-r--r--lib/gs/contribs/cols/cols.erl6
-rw-r--r--lib/gs/contribs/mandel/mandel.erl4
-rw-r--r--lib/gs/contribs/othello/othello_board.erl6
-rw-r--r--lib/gs/doc/src/notes.xml16
-rw-r--r--lib/gs/examples/calc2.erl4
-rw-r--r--lib/gs/src/Makefile4
-rw-r--r--lib/gs/vsn.mk2
-rw-r--r--lib/hipe/cerl/erl_bif_types.erl198
-rw-r--r--lib/hipe/cerl/erl_types.erl168
-rw-r--r--lib/hipe/doc/src/notes.xml98
-rw-r--r--lib/hipe/icode/hipe_beam_to_icode.erl13
-rw-r--r--lib/hipe/main/hipe.hrl.src9
-rw-r--r--lib/hipe/main/hipe_main.erl6
-rw-r--r--lib/hipe/ppc/hipe_ppc.erl172
-rw-r--r--lib/hipe/ppc/hipe_ppc_assemble.erl76
-rw-r--r--lib/hipe/ppc/hipe_ppc_frame.erl30
-rw-r--r--lib/hipe/ppc/hipe_rtl_to_ppc.erl260
-rw-r--r--lib/hipe/regalloc/hipe_node_sets.erl4
-rw-r--r--lib/hipe/rtl/hipe_rtl_arch.erl57
-rw-r--r--lib/hipe/rtl/hipe_rtl_lcm.erl4
-rw-r--r--lib/hipe/rtl/hipe_tagscheme.erl2
-rw-r--r--lib/hipe/vsn.mk2
-rw-r--r--lib/ic/c_src/Makefile.in8
-rw-r--r--lib/ic/doc/src/Makefile7
-rw-r--r--lib/ic/doc/src/notes.xml18
-rw-r--r--lib/ic/examples/pre_post_condition/Makefile7
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/ignore_config_record.inf1
-rw-r--r--lib/ic/src/ic.erl4
-rw-r--r--lib/ic/src/ic_pp.erl472
-rw-r--r--lib/ic/src/ic_pragma.erl19
-rw-r--r--lib/ic/vsn.mk2
-rw-r--r--lib/inets/Makefile6
-rw-r--r--lib/inets/doc/src/http_server.xml12
-rw-r--r--lib/inets/doc/src/httpc.xml256
-rw-r--r--lib/inets/doc/src/httpd.xml29
-rw-r--r--lib/inets/doc/src/inets.xml56
-rw-r--r--lib/inets/doc/src/mod_auth.xml2
-rw-r--r--lib/inets/doc/src/mod_esi.xml56
-rw-r--r--lib/inets/doc/src/mod_security.xml4
-rw-r--r--lib/inets/doc/src/notes.xml874
-rw-r--r--lib/inets/doc/src/notes_history.xml4
-rw-r--r--lib/inets/src/ftp/ftp.erl263
-rw-r--r--lib/inets/src/http_client/Makefile1
-rw-r--r--lib/inets/src/http_client/http.erl132
-rw-r--r--lib/inets/src/http_client/httpc.erl108
-rw-r--r--lib/inets/src/http_client/httpc_cookie.erl218
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl289
-rw-r--r--lib/inets/src/http_client/httpc_handler_sup.erl8
-rw-r--r--lib/inets/src/http_client/httpc_manager.erl515
-rw-r--r--lib/inets/src/http_client/httpc_request.erl104
-rw-r--r--lib/inets/src/http_lib/http_internal.hrl5
-rw-r--r--lib/inets/src/http_lib/http_transport.erl337
-rw-r--r--lib/inets/src/http_lib/http_util.erl36
-rw-r--r--lib/inets/src/http_server/httpd_conf.erl10
-rw-r--r--lib/inets/src/http_server/httpd_esi.erl4
-rw-r--r--lib/inets/src/http_server/httpd_file.erl19
-rw-r--r--lib/inets/src/http_server/httpd_log.erl4
-rw-r--r--lib/inets/src/http_server/httpd_request.erl6
-rw-r--r--lib/inets/src/http_server/httpd_request_handler.erl6
-rw-r--r--lib/inets/src/http_server/httpd_sup.erl49
-rw-r--r--lib/inets/src/http_server/httpd_util.erl40
-rw-r--r--lib/inets/src/http_server/mod_auth_mnesia.erl4
-rw-r--r--lib/inets/src/http_server/mod_esi.erl8
-rw-r--r--lib/inets/src/inets_app/inets.app.src3
-rw-r--r--lib/inets/src/inets_app/inets.appup.src22
-rw-r--r--lib/inets/src/inets_app/inets_service.erl28
-rw-r--r--lib/inets/src/tftp/tftp.erl47
-rw-r--r--lib/inets/test/Makefile4
-rw-r--r--lib/inets/test/ftp_SUITE.erl53
-rw-r--r--lib/inets/test/ftp_suite_lib.erl35
-rw-r--r--lib/inets/test/http_format_SUITE.erl4
-rw-r--r--lib/inets/test/httpc_SUITE.erl928
-rw-r--r--lib/inets/test/httpc_cookie_SUITE.erl185
-rw-r--r--lib/inets/test/httpd_SUITE.erl605
-rw-r--r--lib/inets/test/httpd_basic_SUITE.erl56
-rw-r--r--lib/inets/test/httpd_mod.erl5
-rw-r--r--lib/inets/test/httpd_test_lib.erl93
-rw-r--r--lib/inets/test/httpd_time_test.erl6
-rw-r--r--lib/inets/test/inets_app_test.erl16
-rw-r--r--lib/inets/test/inets_test_lib.erl160
-rw-r--r--lib/inets/test/inets_test_lib.hrl4
-rw-r--r--lib/inets/vsn.mk2
-rw-r--r--lib/inviso/test/Makefile2
-rw-r--r--lib/jinterface/doc/src/notes.xml2
-rw-r--r--lib/jinterface/java_src/Makefile16
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile113
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile.otp113
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/ignore_config_record.inf1
-rw-r--r--lib/kernel/doc/specs/.gitignore1
-rw-r--r--lib/kernel/doc/src/Makefile42
-rw-r--r--lib/kernel/doc/src/app.xml4
-rw-r--r--lib/kernel/doc/src/application.xml234
-rw-r--r--lib/kernel/doc/src/auth.xml51
-rw-r--r--lib/kernel/doc/src/code.xml349
-rw-r--r--lib/kernel/doc/src/disk_log.xml454
-rw-r--r--lib/kernel/doc/src/erl_boot_server.xml44
-rw-r--r--lib/kernel/doc/src/erl_ddll.xml131
-rw-r--r--lib/kernel/doc/src/error_handler.xml44
-rw-r--r--lib/kernel/doc/src/error_logger.xml135
-rw-r--r--lib/kernel/doc/src/file.xml918
-rw-r--r--lib/kernel/doc/src/gen_sctp.xml418
-rw-r--r--lib/kernel/doc/src/gen_tcp.xml162
-rw-r--r--lib/kernel/doc/src/gen_udp.xml88
-rw-r--r--lib/kernel/doc/src/global.xml176
-rw-r--r--lib/kernel/doc/src/global_group.xml157
-rw-r--r--lib/kernel/doc/src/heart.xml16
-rw-r--r--lib/kernel/doc/src/inet.xml247
-rw-r--r--lib/kernel/doc/src/inet_res.xml271
-rw-r--r--lib/kernel/doc/src/net_adm.xml74
-rw-r--r--lib/kernel/doc/src/net_kernel.xml98
-rw-r--r--lib/kernel/doc/src/notes.xml125
-rw-r--r--lib/kernel/doc/src/os.xml47
-rw-r--r--lib/kernel/doc/src/pg2.xml66
-rw-r--r--lib/kernel/doc/src/rpc.xml330
-rw-r--r--lib/kernel/doc/src/seq_trace.xml95
-rw-r--r--lib/kernel/doc/src/specs.xml33
-rw-r--r--lib/kernel/doc/src/wrap_log_reader.xml66
-rw-r--r--lib/kernel/examples/uds_dist/c_src/uds_drv.c6
-rw-r--r--lib/kernel/include/dist.hrl (renamed from lib/kernel/src/dist.hrl)0
-rw-r--r--lib/kernel/include/dist_util.hrl (renamed from lib/kernel/src/dist_util.hrl)0
-rw-r--r--lib/kernel/include/inet.hrl15
-rw-r--r--lib/kernel/include/net_address.hrl (renamed from lib/kernel/src/net_address.hrl)0
-rw-r--r--lib/kernel/src/Makefile17
-rw-r--r--lib/kernel/src/application.erl184
-rw-r--r--lib/kernel/src/auth.erl18
-rw-r--r--lib/kernel/src/code.erl135
-rw-r--r--lib/kernel/src/code_server.erl19
-rw-r--r--lib/kernel/src/disk_log.erl274
-rw-r--r--lib/kernel/src/disk_log.hrl24
-rw-r--r--lib/kernel/src/erl_boot_server.erl28
-rw-r--r--lib/kernel/src/erl_ddll.erl49
-rw-r--r--lib/kernel/src/error_handler.erl22
-rw-r--r--lib/kernel/src/error_logger.erl79
-rw-r--r--lib/kernel/src/file.erl376
-rw-r--r--lib/kernel/src/gen_sctp.erl182
-rw-r--r--lib/kernel/src/gen_tcp.erl156
-rw-r--r--lib/kernel/src/gen_udp.erl101
-rw-r--r--lib/kernel/src/global.erl92
-rw-r--r--lib/kernel/src/global_group.erl58
-rw-r--r--lib/kernel/src/global_search.erl5
-rw-r--r--lib/kernel/src/heart.erl10
-rw-r--r--lib/kernel/src/hipe_unified_loader.erl11
-rw-r--r--lib/kernel/src/inet.erl225
-rw-r--r--lib/kernel/src/inet_config.erl52
-rw-r--r--lib/kernel/src/inet_dns_record_adts.pl12
-rw-r--r--lib/kernel/src/inet_res.erl379
-rw-r--r--lib/kernel/src/inet_udp.erl6
-rw-r--r--lib/kernel/src/net_adm.erl41
-rw-r--r--lib/kernel/src/net_kernel.erl39
-rw-r--r--lib/kernel/src/os.erl23
-rw-r--r--lib/kernel/src/pg2.erl68
-rw-r--r--lib/kernel/src/rpc.erl193
-rw-r--r--lib/kernel/src/seq_trace.erl44
-rw-r--r--lib/kernel/src/wrap_log_reader.erl35
-rw-r--r--lib/kernel/test/Makefile4
-rw-r--r--lib/kernel/test/application_SUITE.erl44
-rw-r--r--lib/kernel/test/code_SUITE.erl55
-rw-r--r--lib/kernel/test/disk_log_SUITE.erl15
-rw-r--r--lib/kernel/test/erl_prim_loader_SUITE.erl2
-rw-r--r--lib/kernel/test/file_SUITE.erl83
-rw-r--r--lib/kernel/test/gen_sctp_SUITE.erl57
-rw-r--r--lib/kernel/test/gen_tcp_api_SUITE.erl8
-rw-r--r--lib/kernel/test/gen_udp_SUITE.erl15
-rw-r--r--lib/kernel/test/global_group_SUITE.erl16
-rw-r--r--lib/kernel/test/heart_SUITE.erl13
-rw-r--r--lib/kernel/test/inet_SUITE.erl2
-rw-r--r--lib/kernel/test/inet_res_SUITE.erl139
-rwxr-xr-xlib/kernel/test/inet_res_SUITE_data/run-named4
-rw-r--r--lib/kernel/test/init_SUITE.erl2
-rw-r--r--lib/kernel/test/prim_file_SUITE.erl74
-rw-r--r--lib/kernel/test/ram_file_SUITE.erl4
-rw-r--r--lib/kernel/test/zlib_SUITE.erl12
-rw-r--r--lib/kernel/vsn.mk2
-rw-r--r--lib/megaco/doc/src/megaco.xml6
-rw-r--r--lib/megaco/doc/src/notes.xml42
-rw-r--r--lib/megaco/src/app/megaco.appup.src11
-rw-r--r--lib/megaco/src/binary/depend.mk180
-rw-r--r--lib/megaco/src/flex/Makefile.in11
-rw-r--r--lib/megaco/test/Makefile2
-rw-r--r--lib/megaco/vsn.mk2
-rw-r--r--lib/mnesia/doc/src/Mnesia_chap7.xmlsrc9
-rw-r--r--lib/mnesia/doc/src/mnesia.xml38
-rw-r--r--lib/mnesia/doc/src/mnesia_frag_hash.xml2
-rw-r--r--lib/mnesia/doc/src/notes.xml107
-rw-r--r--lib/mnesia/src/Makefile4
-rw-r--r--lib/mnesia/src/mnesia.appup.src26
-rw-r--r--lib/mnesia/src/mnesia.erl11
-rw-r--r--lib/mnesia/src/mnesia.hrl3
-rw-r--r--lib/mnesia/src/mnesia_controller.erl156
-rw-r--r--lib/mnesia/src/mnesia_dumper.erl25
-rw-r--r--lib/mnesia/src/mnesia_lib.erl18
-rw-r--r--lib/mnesia/src/mnesia_loader.erl248
-rw-r--r--lib/mnesia/src/mnesia_locker.erl69
-rw-r--r--lib/mnesia/src/mnesia_log.erl5
-rw-r--r--lib/mnesia/src/mnesia_monitor.erl84
-rw-r--r--lib/mnesia/src/mnesia_recover.erl6
-rw-r--r--lib/mnesia/src/mnesia_schema.erl564
-rw-r--r--lib/mnesia/src/mnesia_text.erl5
-rw-r--r--lib/mnesia/src/mnesia_tm.erl66
-rw-r--r--lib/mnesia/test/.gitignore9
-rw-r--r--lib/mnesia/test/Makefile3
-rw-r--r--lib/mnesia/test/mnesia_SUITE.erl2
-rw-r--r--lib/mnesia/test/mnesia_durability_test.erl4
-rw-r--r--lib/mnesia/test/mnesia_majority_test.erl186
-rw-r--r--lib/mnesia/test/mnesia_qlc_test.erl3
-rw-r--r--lib/mnesia/test/mnesia_test_lib.erl90
-rw-r--r--lib/mnesia/test/mnesia_trans_access_test.erl36
-rw-r--r--lib/mnesia/test/mt.erl16
-rw-r--r--lib/mnesia/vsn.mk2
-rw-r--r--lib/observer/doc/src/notes.xml18
-rw-r--r--lib/observer/doc/src/ttb.xml233
-rw-r--r--lib/observer/doc/src/ttb_ug.xml385
-rw-r--r--lib/observer/src/Makefile9
-rw-r--r--lib/observer/src/ttb.erl711
-rw-r--r--lib/observer/test/Makefile3
-rw-r--r--lib/observer/test/client.erl28
-rw-r--r--lib/observer/test/crashdump_helper.erl4
-rw-r--r--lib/observer/test/server.erl43
-rw-r--r--lib/observer/test/ttb_SUITE.erl748
-rw-r--r--lib/observer/test/ttb_helper.erl157
-rw-r--r--lib/observer/vsn.mk2
-rw-r--r--lib/odbc/c_src/Makefile.in7
-rw-r--r--lib/odbc/c_src/odbcserver.c71
-rw-r--r--lib/odbc/c_src/odbcserver.h3
-rw-r--r--lib/odbc/doc/src/databases.xml6
-rw-r--r--lib/odbc/doc/src/notes.xml46
-rw-r--r--lib/odbc/doc/src/odbc.xml8
-rw-r--r--lib/odbc/src/odbc.appup.src6
-rw-r--r--lib/odbc/src/odbc.erl7
-rw-r--r--lib/odbc/src/odbc_internal.hrl3
-rw-r--r--lib/odbc/test/Makefile3
-rw-r--r--lib/odbc/test/mysql.erl277
-rw-r--r--lib/odbc/test/odbc.dynspec31
-rw-r--r--lib/odbc/test/odbc.spec24
-rw-r--r--lib/odbc/test/odbc.spec.win5
-rw-r--r--lib/odbc/test/odbc_connect_SUITE.erl237
-rw-r--r--lib/odbc/test/odbc_data_type_SUITE.erl516
-rw-r--r--lib/odbc/test/odbc_query_SUITE.erl64
-rw-r--r--lib/odbc/test/odbc_start_SUITE.erl27
-rw-r--r--lib/odbc/test/odbc_test.hrl13
-rw-r--r--lib/odbc/test/odbc_test_lib.erl83
-rw-r--r--lib/odbc/test/oracle.erl12
-rw-r--r--lib/odbc/test/postgres.erl23
-rw-r--r--lib/odbc/test/sqlserver.erl12
-rw-r--r--lib/odbc/vsn.mk2
-rw-r--r--lib/orber/COSS/CosNaming/Makefile6
-rw-r--r--lib/orber/doc/src/Orber/ignore_config_record.inf1
-rw-r--r--lib/orber/doc/src/notes.xml30
-rw-r--r--lib/orber/doc/src/orber_ifr.xml4
-rw-r--r--lib/orber/examples/Stack/Makefile10
-rw-r--r--lib/orber/include/Makefile66
-rw-r--r--lib/orber/src/Makefile11
-rw-r--r--lib/orber/src/corba.erl4
-rw-r--r--lib/orber/src/orber.erl2
-rw-r--r--lib/orber/src/orber_diagnostics.erl4
-rw-r--r--lib/orber/src/orber_ifr.erl2
-rw-r--r--lib/orber/test/Makefile28
-rw-r--r--lib/orber/vsn.mk2
-rw-r--r--lib/os_mon/c_src/Makefile.in8
-rw-r--r--lib/os_mon/c_src/cpu_sup.c21
-rw-r--r--lib/os_mon/doc/src/notes.xml45
-rw-r--r--lib/os_mon/mibs/Makefile3
-rw-r--r--lib/os_mon/src/disksup.erl6
-rw-r--r--lib/os_mon/src/memsup.erl12
-rw-r--r--lib/os_mon/vsn.mk2
-rw-r--r--lib/parsetools/doc/src/leex.xml6
-rw-r--r--lib/parsetools/doc/src/notes.xml46
-rw-r--r--lib/parsetools/doc/src/yecc.xml16
-rw-r--r--lib/parsetools/include/yeccpre.hrl4
-rw-r--r--lib/parsetools/src/leex.erl177
-rw-r--r--lib/parsetools/src/yecc.erl55
-rw-r--r--lib/parsetools/src/yeccparser.erl4
-rw-r--r--lib/parsetools/test/Makefile2
-rw-r--r--lib/parsetools/test/leex_SUITE.erl20
-rw-r--r--lib/parsetools/test/yecc_SUITE.erl14
-rw-r--r--lib/parsetools/vsn.mk2
-rw-r--r--lib/percept/doc/src/notes.xml26
-rw-r--r--lib/percept/src/percept_db.erl13
-rw-r--r--lib/percept/test/Makefile2
-rw-r--r--lib/percept/vsn.mk2
-rw-r--r--lib/public_key/asn1/Makefile4
-rw-r--r--lib/public_key/asn1/README2
-rw-r--r--lib/public_key/doc/src/Makefile3
-rw-r--r--lib/public_key/doc/src/introduction.xml8
-rw-r--r--lib/public_key/doc/src/notes.xml35
-rw-r--r--lib/public_key/doc/src/part.xml3
-rw-r--r--lib/public_key/doc/src/public_key.xml40
-rw-r--r--lib/public_key/doc/src/using_public_key.xml504
-rw-r--r--lib/public_key/src/public_key.appup.src20
-rw-r--r--lib/public_key/src/public_key.erl7
-rw-r--r--lib/public_key/test/Makefile2
-rw-r--r--lib/public_key/test/pkits_SUITE.erl1472
-rw-r--r--lib/public_key/vsn.mk2
-rw-r--r--lib/reltool/doc/src/notes.xml56
-rw-r--r--lib/reltool/src/reltool_server.erl189
-rw-r--r--lib/reltool/src/reltool_sys_win.erl159
-rw-r--r--lib/reltool/test/Makefile4
-rw-r--r--lib/reltool/test/reltool_server_SUITE.erl125
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/Makefile.src19
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/ebin/x.app7
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/src/mylib.erl4
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/src/x.erl4
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/ebin/y.app7
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/src/mylib.erl4
-rw-r--r--lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/src/y.erl4
-rw-r--r--lib/reltool/vsn.mk2
-rw-r--r--lib/runtime_tools/c_src/Makefile.in15
-rw-r--r--lib/runtime_tools/doc/src/dbg.xml35
-rw-r--r--lib/runtime_tools/doc/src/notes.xml19
-rw-r--r--lib/runtime_tools/src/Makefile3
-rw-r--r--lib/runtime_tools/src/dbg.erl13
-rw-r--r--lib/runtime_tools/src/observer_backend.erl123
-rw-r--r--lib/runtime_tools/src/runtime_tools.app.src3
-rw-r--r--lib/runtime_tools/src/runtime_tools_sup.erl4
-rw-r--r--lib/runtime_tools/src/ttb_autostart.erl55
-rw-r--r--lib/runtime_tools/test/Makefile2
-rw-r--r--lib/runtime_tools/vsn.mk2
-rw-r--r--lib/sasl/Makefile4
-rw-r--r--lib/sasl/doc/src/notes.xml196
-rw-r--r--lib/sasl/doc/src/release_handler.xml28
-rw-r--r--lib/sasl/doc/src/sasl_app.xml7
-rw-r--r--lib/sasl/doc/src/systools.xml24
-rw-r--r--lib/sasl/examples/ebin/.gitignore0
-rw-r--r--lib/sasl/examples/src/Makefile78
-rw-r--r--lib/sasl/examples/src/target_system.erl259
-rw-r--r--lib/sasl/src/erlsrv.erl31
-rw-r--r--lib/sasl/src/rb.erl18
-rw-r--r--lib/sasl/src/release_handler.erl241
-rw-r--r--lib/sasl/src/release_handler_1.erl289
-rw-r--r--lib/sasl/src/sasl.erl23
-rw-r--r--lib/sasl/src/systools_lib.erl40
-rw-r--r--lib/sasl/src/systools_make.erl251
-rw-r--r--lib/sasl/src/systools_relup.erl77
-rw-r--r--lib/sasl/test/.gitignore5
-rw-r--r--lib/sasl/test/Makefile92
-rw-r--r--lib/sasl/test/alarm_handler_SUITE.erl179
-rw-r--r--lib/sasl/test/installer.erl816
-rw-r--r--lib/sasl/test/overload_SUITE.erl175
-rw-r--r--lib/sasl/test/rb_SUITE.erl606
-rw-r--r--lib/sasl/test/release_handler_SUITE.erl2219
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/Makefile.src211
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/P2B/a-2.0/ebin/a.app8
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/P2B/a-2.0/src/a.erl47
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/P2B/a-2.0/src/a_sup.erl37
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app1-1.0/ebin/app1.app9
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app1-1.0/src/app1.erl22
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app1-1.0/src/app1_server.erl32
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app1-1.0/src/app1_sup.erl17
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app2-1.0/ebin/app2.app9
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app2-1.0/src/app2.erl17
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app2-1.0/src/app2_server.erl32
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app2-1.0/src/app2_sup.erl17
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/ebin/app1.app9
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/ebin/app1.appup4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/src/app1.erl22
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/src/app1_server.erl35
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/src/app1_sup.erl17
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app2-1.0/ebin/app2.app9
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app2-1.0/src/app2.erl17
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app2-1.0/src/app2_server.erl32
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app2-1.0/src/app2_sup.erl17
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/c/aa.erl41
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/c/b.erl38
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/c/c.app8
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/c/c_sup.erl40
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/erl.ini.src4
-rwxr-xr-xlib/sasl/test/release_handler_SUITE_data/heart_restart.bat3
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/README33
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-1.0/ebin/a.app8
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-1.0/src/a.erl49
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-1.0/src/a_sup.erl37
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-1.1/ebin/a.app8
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-1.1/ebin/a.appup3
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-1.1/src/a.erl54
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-1.1/src/a_sup.erl37
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/ebin/a.app8
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/ebin/a.appup3
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/priv/file0
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/src/a.erl54
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/src/a_sup.erl37
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/ebin/b.app7
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/src/b_lib.erl3
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/src/b_server.erl37
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/ebin/b.app7
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/ebin/b.appup6
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/src/b_lib.erl3
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/src/b_server.erl37
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/ebin/installer.app6
l---------lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/src/installer.erl1
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/ebin/many_mods.app17
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m.erl11
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m1.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m10.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m2.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m3.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m4.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m5.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m6.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m7.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m8.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m9.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/ebin/many_mods.app17
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/ebin/many_mods.appup22
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m.erl11
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m1.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m10.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m2.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m3.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m4.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m5.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m6.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m7.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m8.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m9.erl4
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/ebin/many_mods.app7
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/ebin/many_mods.appup24
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/src/m.erl11
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_atom.erl26
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_list.erl26
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_numeric.erl26
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_string.erl26
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_tuple.erl26
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/ebin/dummy.app7
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_app.erl9
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_server.erl56
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup.erl15
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl15
-rwxr-xr-xlib/sasl/test/release_handler_SUITE_data/start29
-rwxr-xr-xlib/sasl/test/release_handler_SUITE_data/start_client37
l---------lib/sasl/test/release_handler_SUITE_data/target_system.erl1
-rw-r--r--lib/sasl/test/rh_test_lib.erl100
-rw-r--r--lib/sasl/test/sasl.cover2
-rw-r--r--lib/sasl/test/sasl.spec1
-rw-r--r--lib/sasl/test/sasl_SUITE.erl98
-rw-r--r--lib/sasl/test/systools_SUITE.erl2191
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/db-2.1/ebin/db.app8
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/db-2.1/ebin/db.appup20
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/db-2.1/src/db1.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/db-2.1/src/db2.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/ebin/fe.app8
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/ebin/fe.appup27
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/src/fe1.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/src/fe2.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/src/fe3.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_appup/lib/fe-3.1/ebin/fe.app7
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_appup/lib/fe-3.1/ebin/fe.appup27
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/db-2.1/ebin/db.app8
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/db-2.1/ebin/db.appup20
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/db-2.1/src/db1.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/db-2.1/src/db2.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/ebin/fe.app8
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/ebin/fe.appup27
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/src/fe1.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/src/fe2.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/src/fe3.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_links/lib/db-2.1/ebin/db.app8
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_links/lib/db-2.1/ebin/db.appup20
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_links/lib/db-2.1/src/db2.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_links/lib/db-2.1/src/db3.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_links/lib/fe-3.1/ebin/fe.appup27
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_links/lib/fe-3.1/src/fe1.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_links/lib/fe-3.1/src/fe2.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_links/lib/fe-3.1/src/fe3.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/ebin/db.app8
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/ebin/db.appup20
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/src/db1.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/src/db2.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/ebin/fe.app8
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/ebin/fe.appup27
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/src/fe1.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/src/fe2.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/src/fe3.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_no_appup/lib/fe-2.1/ebin/fe.app8
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_no_appup/lib/fe-2.1/ebin/fe.appup27
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_no_appup/lib/fe-3.1/ebin/fe.app7
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.0/ebin/db.app8
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.0/src/db1.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.0/src/db2.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.1/ebin/db.app8
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.1/src/db1.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.1/src/db2.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/db-2.1/ebin/db.app7
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/db-2.1/ebin/db.appup20
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/db-2.1/src/db1.erl13
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/db-2.1/src/db2.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/db-3.1/ebin/db.app7
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/db-3.1/ebin/db.appup20
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/db-3.1/src/db1.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/db-3.1/src/db2.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1.1/ebin/fe.app8
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1.1/src/fe1.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1.1/src/fe2.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1.1/src/fe3.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1/ebin/fe.app8
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1/src/fe1.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1/src/fe2.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1/src/fe3.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/ebin/fe.app7
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/ebin/fe.appup27
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/src/fe1.erl7
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/src/fe2.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/src/fe3.erl2
-rw-r--r--lib/sasl/test/systools_SUITE_data/lib/kernel/ebin/kernel.app6
-rw-r--r--lib/sasl/test/systools_SUITE_data/lib/kernel/ebin/kernel.appup12
-rw-r--r--lib/sasl/test/systools_SUITE_data/lib/stdlib/ebin/stdlib.app6
-rw-r--r--lib/sasl/test/systools_SUITE_data/lib/stdlib/ebin/stdlib.appup12
-rw-r--r--lib/sasl/test/systools_rc_SUITE.erl488
-rw-r--r--lib/sasl/vsn.mk2
-rw-r--r--lib/snmp/Makefile7
-rw-r--r--lib/snmp/doc/src/Makefile4
-rw-r--r--lib/snmp/doc/src/files.mk1
-rw-r--r--lib/snmp/doc/src/notes.xml301
-rw-r--r--lib/snmp/doc/src/snmp_agent_config_files.xml60
-rw-r--r--lib/snmp/doc/src/snmp_agent_netif.xml203
-rw-r--r--lib/snmp/doc/src/snmp_community_mib.xml26
-rw-r--r--lib/snmp/doc/src/snmp_target_mib.xml24
-rw-r--r--lib/snmp/doc/src/snmpa.xml250
-rw-r--r--lib/snmp/doc/src/snmpa_conf.xml25
-rw-r--r--lib/snmp/doc/src/snmpc.xml15
-rw-r--r--lib/snmp/doc/src/snmpc_cmd.xml34
-rw-r--r--lib/snmp/doc/src/snmpm.xml601
-rw-r--r--lib/snmp/mibs/Makefile.in37
-rw-r--r--lib/snmp/mibs/TRANSPORT-ADDRESS-MIB.mib417
-rw-r--r--lib/snmp/priv/conf/agent/target_addr.conf10
-rw-r--r--lib/snmp/src/agent/snmp_community_mib.erl17
-rw-r--r--lib/snmp/src/agent/snmp_notification_mib.erl9
-rw-r--r--lib/snmp/src/agent/snmp_target_mib.erl189
-rw-r--r--lib/snmp/src/agent/snmp_view_based_acm_mib.erl6
-rw-r--r--lib/snmp/src/agent/snmpa.erl64
-rw-r--r--lib/snmp/src/agent/snmpa_acm.erl28
-rw-r--r--lib/snmp/src/agent/snmpa_agent.erl325
-rw-r--r--lib/snmp/src/agent/snmpa_authentication_service.erl11
-rw-r--r--lib/snmp/src/agent/snmpa_conf.erl72
-rw-r--r--lib/snmp/src/agent/snmpa_internal.hrl3
-rw-r--r--lib/snmp/src/agent/snmpa_mpd.erl150
-rw-r--r--lib/snmp/src/agent/snmpa_net_if.erl81
-rw-r--r--lib/snmp/src/agent/snmpa_set_lib.erl8
-rw-r--r--lib/snmp/src/agent/snmpa_trap.erl231
-rw-r--r--lib/snmp/src/agent/snmpa_usm.erl17
-rw-r--r--lib/snmp/src/app/snmp.appup.src214
-rw-r--r--lib/snmp/src/compile/Makefile11
-rw-r--r--lib/snmp/src/compile/snmpc.erl9
-rw-r--r--lib/snmp/src/compile/snmpc.src73
-rw-r--r--lib/snmp/src/compile/snmpc_lib.erl6
-rw-r--r--lib/snmp/src/compile/snmpc_lib.hrl15
-rw-r--r--lib/snmp/src/manager/snmpm.erl578
-rw-r--r--lib/snmp/src/manager/snmpm_config.erl515
-rw-r--r--lib/snmp/src/manager/snmpm_internal.hrl7
-rw-r--r--lib/snmp/src/manager/snmpm_mpd.erl49
-rw-r--r--lib/snmp/src/manager/snmpm_net_if.erl49
-rw-r--r--lib/snmp/src/manager/snmpm_server.erl751
-rw-r--r--lib/snmp/src/manager/snmpm_usm.erl7
-rw-r--r--lib/snmp/src/misc/snmp_conf.erl214
-rw-r--r--lib/snmp/src/misc/snmp_config.erl32
-rw-r--r--lib/snmp/src/misc/snmp_log.erl7
-rw-r--r--lib/snmp/src/misc/snmp_misc.erl13
-rw-r--r--lib/snmp/src/misc/snmp_pdus.erl46
-rw-r--r--lib/snmp/test/Makefile15
-rw-r--r--lib/snmp/test/snmp_agent_test.erl300
-rw-r--r--lib/snmp/test/snmp_agent_test_lib.erl17
-rw-r--r--lib/snmp/test/snmp_compiler_test.erl48
-rw-r--r--lib/snmp/test/snmp_manager_test.erl1253
-rw-r--r--lib/snmp/test/snmp_manager_user.erl137
-rw-r--r--lib/snmp/test/snmp_pdus_test.erl57
-rw-r--r--lib/snmp/test/test_config/Makefile18
-rw-r--r--lib/snmp/vsn.mk2
-rw-r--r--lib/ssh/doc/src/notes.xml55
-rw-r--r--lib/ssh/src/Makefile9
-rw-r--r--lib/ssh/src/ssh.appup.src38
-rwxr-xr-xlib/ssh/src/ssh_bits.erl56
-rw-r--r--lib/ssh/src/ssh_cli.erl2
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl25
-rwxr-xr-xlib/ssh/src/ssh_sftp.erl12
-rw-r--r--lib/ssh/src/ssh_userreg.erl28
-rw-r--r--lib/ssh/test/Makefile121
-rw-r--r--lib/ssh/test/ssh.cover2
-rw-r--r--lib/ssh/test/ssh.spec7
-rw-r--r--lib/ssh/test/ssh.spec.vxworks3
-rw-r--r--lib/ssh/test/ssh_SUITE.erl72
-rw-r--r--lib/ssh/test/ssh_basic_SUITE.erl389
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE.erl543
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE_data/id_rsa15
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE_data/id_rsa.pub1
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE_data/sftp.txt252
-rw-r--r--lib/ssh/test/ssh_sftpd_SUITE.erl934
-rw-r--r--lib/ssh/test/ssh_sftpd_SUITE_data/test.txt1
-rw-r--r--lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl328
-rw-r--r--lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_sftpd_file_alt.erl100
-rw-r--r--lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/test.txt1
-rw-r--r--lib/ssh/test/ssh_test_lib.erl684
-rw-r--r--lib/ssh/test/ssh_to_openssh_SUITE.erl458
-rw-r--r--lib/ssh/vsn.mk2
-rw-r--r--lib/ssl/Makefile4
-rw-r--r--lib/ssl/c_src/Makefile26
-rw-r--r--lib/ssl/c_src/Makefile.dist33
-rw-r--r--lib/ssl/c_src/Makefile.in213
-rw-r--r--lib/ssl/c_src/Makefile.win32147
-rw-r--r--lib/ssl/c_src/Makefile.win32.dist45
-rw-r--r--lib/ssl/c_src/debuglog.c251
-rw-r--r--lib/ssl/c_src/debuglog.h50
-rw-r--r--lib/ssl/c_src/esock.c1904
-rw-r--r--lib/ssl/c_src/esock.h273
-rw-r--r--lib/ssl/c_src/esock_openssl.c1213
-rw-r--r--lib/ssl/c_src/esock_osio.c328
-rw-r--r--lib/ssl/c_src/esock_osio.h34
-rw-r--r--lib/ssl/c_src/esock_poll.c222
-rw-r--r--lib/ssl/c_src/esock_poll.h60
-rw-r--r--lib/ssl/c_src/esock_posix_str.c642
-rw-r--r--lib/ssl/c_src/esock_posix_str.h28
-rw-r--r--lib/ssl/c_src/esock_ssl.h110
-rw-r--r--lib/ssl/c_src/esock_utils.c150
-rw-r--r--lib/ssl/c_src/esock_utils.h32
-rw-r--r--lib/ssl/c_src/esock_winsock.h36
-rw-r--r--lib/ssl/doc/src/Makefile4
-rw-r--r--lib/ssl/doc/src/notes.xml104
-rw-r--r--lib/ssl/doc/src/old_ssl.xml709
-rw-r--r--lib/ssl/doc/src/refman.xml5
-rw-r--r--lib/ssl/doc/src/ssl.xml61
-rw-r--r--lib/ssl/doc/src/ssl_distribution.xml209
-rw-r--r--lib/ssl/doc/src/ssl_protocol.xml18
-rw-r--r--lib/ssl/doc/src/using_ssl.xml8
-rw-r--r--lib/ssl/examples/certs/Makefile2
-rw-r--r--lib/ssl/examples/src/Makefile4
-rw-r--r--lib/ssl/src/Makefile12
-rw-r--r--lib/ssl/src/inet_ssl_dist.erl456
-rw-r--r--lib/ssl/src/inet_tls_dist.erl275
-rw-r--r--lib/ssl/src/ssl.app.src10
-rw-r--r--lib/ssl/src/ssl.appup.src8
-rw-r--r--lib/ssl/src/ssl.erl467
-rw-r--r--lib/ssl/src/ssl_broker.erl1188
-rw-r--r--lib/ssl/src/ssl_broker_int.hrl38
-rw-r--r--lib/ssl/src/ssl_broker_sup.erl46
-rw-r--r--lib/ssl/src/ssl_certificate.erl54
-rw-r--r--lib/ssl/src/ssl_certificate_db.erl49
-rw-r--r--lib/ssl/src/ssl_connection.erl210
-rw-r--r--lib/ssl/src/ssl_connection_sup.erl12
-rw-r--r--lib/ssl/src/ssl_dist_sup.erl84
-rw-r--r--lib/ssl/src/ssl_handshake.erl65
-rw-r--r--lib/ssl/src/ssl_int.hrl99
-rw-r--r--lib/ssl/src/ssl_internal.hrl14
-rw-r--r--lib/ssl/src/ssl_manager.erl131
-rw-r--r--lib/ssl/src/ssl_prim.erl173
-rw-r--r--lib/ssl/src/ssl_record.erl18
-rw-r--r--lib/ssl/src/ssl_server.erl1378
-rw-r--r--lib/ssl/src/ssl_session.erl6
-rw-r--r--lib/ssl/src/ssl_session_cache.erl18
-rw-r--r--lib/ssl/src/ssl_ssl2.erl4
-rw-r--r--lib/ssl/src/ssl_sup.erl42
-rw-r--r--lib/ssl/src/ssl_tls_dist_proxy.erl325
-rw-r--r--lib/ssl/test/Makefile23
-rw-r--r--lib/ssl/test/old_ssl_active_SUITE.erl395
-rw-r--r--lib/ssl/test/old_ssl_active_once_SUITE.erl417
-rw-r--r--lib/ssl/test/old_ssl_dist_SUITE.erl617
-rw-r--r--lib/ssl/test/old_ssl_misc_SUITE.erl117
-rw-r--r--lib/ssl/test/old_ssl_passive_SUITE.erl382
-rw-r--r--lib/ssl/test/old_ssl_peer_cert_SUITE.erl191
-rw-r--r--lib/ssl/test/old_ssl_protocol_SUITE.erl185
-rw-r--r--lib/ssl/test/old_ssl_verify_SUITE.erl153
-rw-r--r--lib/ssl/test/old_transport_accept_SUITE.erl258
-rw-r--r--lib/ssl/test/ssl.cover19
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl434
-rw-r--r--lib/ssl/test/ssl_dist_SUITE.erl725
-rw-r--r--lib/ssl/test/ssl_dist_SUITE_data/dHParam.pem5
-rw-r--r--lib/ssl/test/ssl_handshake_SUITE.erl67
-rw-r--r--lib/ssl/test/ssl_packet_SUITE.erl302
-rw-r--r--lib/ssl/test/ssl_session_cache_SUITE.erl108
-rw-r--r--lib/ssl/test/ssl_test_MACHINE.erl940
-rw-r--r--lib/ssl/test/ssl_test_MACHINE.hrl39
-rw-r--r--lib/ssl/test/ssl_test_lib.erl3
-rw-r--r--lib/ssl/vsn.mk2
-rw-r--r--lib/stdlib/doc/specs/.gitignore1
-rw-r--r--lib/stdlib/doc/src/Makefile15
-rw-r--r--lib/stdlib/doc/src/array.xml177
-rw-r--r--lib/stdlib/doc/src/base64.xml35
-rw-r--r--lib/stdlib/doc/src/beam_lib.xml272
-rw-r--r--lib/stdlib/doc/src/binary.xml150
-rw-r--r--lib/stdlib/doc/src/c.xml127
-rw-r--r--lib/stdlib/doc/src/calendar.xml221
-rw-r--r--lib/stdlib/doc/src/dets.xml704
-rw-r--r--lib/stdlib/doc/src/dict.xml212
-rw-r--r--lib/stdlib/doc/src/digraph.xml395
-rw-r--r--lib/stdlib/doc/src/digraph_utils.xml170
-rw-r--r--lib/stdlib/doc/src/epp.xml62
-rw-r--r--lib/stdlib/doc/src/erl_eval.xml153
-rw-r--r--lib/stdlib/doc/src/erl_expand_records.xml6
-rw-r--r--lib/stdlib/doc/src/erl_id_trans.xml6
-rw-r--r--lib/stdlib/doc/src/erl_internal.xml73
-rw-r--r--lib/stdlib/doc/src/erl_lint.xml50
-rw-r--r--lib/stdlib/doc/src/erl_parse.xml122
-rw-r--r--lib/stdlib/doc/src/erl_pp.xml123
-rw-r--r--lib/stdlib/doc/src/erl_scan.xml362
-rw-r--r--lib/stdlib/doc/src/erl_tar.xml60
-rw-r--r--lib/stdlib/doc/src/ets.xml269
-rw-r--r--lib/stdlib/doc/src/file_sorter.xml266
-rw-r--r--lib/stdlib/doc/src/filelib.xml89
-rw-r--r--lib/stdlib/doc/src/filename.xml156
-rw-r--r--lib/stdlib/doc/src/gb_sets.xml289
-rw-r--r--lib/stdlib/doc/src/gb_trees.xml216
-rw-r--r--lib/stdlib/doc/src/gen_event.xml16
-rw-r--r--lib/stdlib/doc/src/gen_fsm.xml11
-rw-r--r--lib/stdlib/doc/src/io.xml354
-rw-r--r--lib/stdlib/doc/src/io_lib.xml179
-rw-r--r--lib/stdlib/doc/src/lib.xml37
-rw-r--r--lib/stdlib/doc/src/lists.xml764
-rw-r--r--lib/stdlib/doc/src/log_mf_h.xml31
-rw-r--r--lib/stdlib/doc/src/math.xml2
-rw-r--r--lib/stdlib/doc/src/ms_transform.xml25
-rw-r--r--lib/stdlib/doc/src/notes.xml348
-rw-r--r--lib/stdlib/doc/src/orddict.xml213
-rw-r--r--lib/stdlib/doc/src/ordsets.xml153
-rw-r--r--lib/stdlib/doc/src/pg.xml55
-rw-r--r--lib/stdlib/doc/src/pool.xml46
-rw-r--r--lib/stdlib/doc/src/proc_lib.xml163
-rw-r--r--lib/stdlib/doc/src/proplists.xml210
-rw-r--r--lib/stdlib/doc/src/qlc.xml645
-rw-r--r--lib/stdlib/doc/src/queue.xml286
-rw-r--r--lib/stdlib/doc/src/random.xml48
-rw-r--r--lib/stdlib/doc/src/re.xml135
-rw-r--r--lib/stdlib/doc/src/regexp.xml152
-rw-r--r--lib/stdlib/doc/src/sets.xml153
-rw-r--r--lib/stdlib/doc/src/shell.xml37
-rw-r--r--lib/stdlib/doc/src/slave.xml60
-rw-r--r--lib/stdlib/doc/src/sofs.xml1021
-rw-r--r--lib/stdlib/doc/src/specs.xml63
-rw-r--r--lib/stdlib/doc/src/string.xml230
-rw-r--r--lib/stdlib/doc/src/supervisor.xml261
-rw-r--r--lib/stdlib/doc/src/supervisor_bridge.xml47
-rw-r--r--lib/stdlib/doc/src/sys.xml212
-rw-r--r--lib/stdlib/doc/src/timer.xml186
-rw-r--r--lib/stdlib/doc/src/unicode.xml188
-rw-r--r--lib/stdlib/doc/src/unicode_usage.xml4
-rw-r--r--lib/stdlib/doc/src/win32reg.xml98
-rw-r--r--lib/stdlib/doc/src/zip.xml303
-rw-r--r--lib/stdlib/include/zip.hrl4
-rw-r--r--lib/stdlib/src/array.erl111
-rw-r--r--lib/stdlib/src/base64.erl24
-rw-r--r--lib/stdlib/src/beam_lib.erl150
-rw-r--r--lib/stdlib/src/binary.erl37
-rw-r--r--lib/stdlib/src/c.erl68
-rw-r--r--lib/stdlib/src/calendar.erl109
-rw-r--r--lib/stdlib/src/dets.erl414
-rw-r--r--lib/stdlib/src/dets.hrl3
-rw-r--r--lib/stdlib/src/dets_v8.erl20
-rw-r--r--lib/stdlib/src/dets_v9.erl118
-rw-r--r--lib/stdlib/src/dict.erl99
-rw-r--r--lib/stdlib/src/digraph.erl159
-rw-r--r--lib/stdlib/src/digraph_utils.erl84
-rw-r--r--lib/stdlib/src/epp.erl52
-rw-r--r--lib/stdlib/src/erl_compile.erl3
-rw-r--r--lib/stdlib/src/erl_eval.erl144
-rw-r--r--lib/stdlib/src/erl_expand_records.erl8
-rw-r--r--lib/stdlib/src/erl_internal.erl42
-rw-r--r--lib/stdlib/src/erl_lint.erl79
-rw-r--r--lib/stdlib/src/erl_parse.yrl49
-rw-r--r--lib/stdlib/src/erl_pp.erl65
-rw-r--r--lib/stdlib/src/erl_scan.erl122
-rw-r--r--lib/stdlib/src/erl_tar.erl30
-rw-r--r--lib/stdlib/src/error_logger_tty_h.erl69
-rw-r--r--lib/stdlib/src/escript.erl8
-rw-r--r--lib/stdlib/src/ets.erl148
-rw-r--r--lib/stdlib/src/eval_bits.erl57
-rw-r--r--lib/stdlib/src/file_sorter.erl119
-rw-r--r--lib/stdlib/src/filelib.erl39
-rw-r--r--lib/stdlib/src/filename.erl84
-rw-r--r--lib/stdlib/src/gb_sets.erl147
-rw-r--r--lib/stdlib/src/gb_trees.erl109
-rw-r--r--lib/stdlib/src/gen.erl9
-rw-r--r--lib/stdlib/src/gen_event.erl97
-rw-r--r--lib/stdlib/src/gen_fsm.erl58
-rw-r--r--lib/stdlib/src/gen_server.erl52
-rw-r--r--lib/stdlib/src/io.erl195
-rw-r--r--lib/stdlib/src/io_lib.erl78
-rw-r--r--lib/stdlib/src/io_lib_fread.erl103
-rw-r--r--lib/stdlib/src/lib.erl66
-rw-r--r--lib/stdlib/src/lists.erl430
-rw-r--r--lib/stdlib/src/log_mf_h.erl21
-rw-r--r--lib/stdlib/src/ms_transform.erl16
-rw-r--r--lib/stdlib/src/orddict.erl98
-rw-r--r--lib/stdlib/src/ordsets.erl72
-rw-r--r--lib/stdlib/src/otp_internal.erl142
-rw-r--r--lib/stdlib/src/pg.erl28
-rw-r--r--lib/stdlib/src/pool.erl27
-rw-r--r--lib/stdlib/src/proc_lib.erl138
-rw-r--r--lib/stdlib/src/proplists.erl154
-rw-r--r--lib/stdlib/src/qlc.erl311
-rw-r--r--lib/stdlib/src/qlc_pt.erl18
-rw-r--r--lib/stdlib/src/queue.erl66
-rw-r--r--lib/stdlib/src/random.erl22
-rw-r--r--lib/stdlib/src/re.erl63
-rw-r--r--lib/stdlib/src/regexp.erl69
-rw-r--r--lib/stdlib/src/sets.erl74
-rw-r--r--lib/stdlib/src/shell.erl25
-rw-r--r--lib/stdlib/src/slave.erl52
-rw-r--r--lib/stdlib/src/sofs.erl546
-rw-r--r--lib/stdlib/src/string.erl175
-rw-r--r--lib/stdlib/src/supervisor.erl208
-rw-r--r--lib/stdlib/src/supervisor_bridge.erl27
-rw-r--r--lib/stdlib/src/sys.erl182
-rw-r--r--lib/stdlib/src/timer.erl142
-rw-r--r--lib/stdlib/src/unicode.erl63
-rw-r--r--lib/stdlib/src/win32reg.erl70
-rw-r--r--lib/stdlib/src/zip.erl187
-rw-r--r--lib/stdlib/test/Makefile2
-rw-r--r--lib/stdlib/test/beam_lib_SUITE.erl56
-rw-r--r--lib/stdlib/test/dets_SUITE.erl222
-rw-r--r--lib/stdlib/test/epp_SUITE.erl4
-rw-r--r--lib/stdlib/test/erl_eval_SUITE.erl4
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl2
-rw-r--r--lib/stdlib/test/erl_pp_SUITE.erl2
-rw-r--r--lib/stdlib/test/erl_scan_SUITE.erl4
-rw-r--r--lib/stdlib/test/ets_SUITE.erl134
-rw-r--r--lib/stdlib/test/file_sorter_SUITE.erl16
-rw-r--r--lib/stdlib/test/filelib_SUITE.erl11
-rw-r--r--lib/stdlib/test/gen_event_SUITE.erl21
-rw-r--r--lib/stdlib/test/io_SUITE.erl30
-rw-r--r--lib/stdlib/test/proc_lib_SUITE.erl2
-rw-r--r--lib/stdlib/test/re_SUITE.erl92
-rw-r--r--lib/stdlib/test/shell_SUITE.erl6
-rw-r--r--lib/stdlib/test/sofs_SUITE.erl33
-rw-r--r--lib/stdlib/test/string_SUITE.erl4
-rw-r--r--lib/stdlib/test/supervisor_1.erl6
-rw-r--r--lib/stdlib/test/supervisor_SUITE.erl1566
-rw-r--r--lib/stdlib/test/supervisor_bridge_SUITE.erl2
-rw-r--r--lib/stdlib/test/sys_SUITE.erl2
-rw-r--r--lib/stdlib/test/tar_SUITE.erl78
-rw-r--r--lib/stdlib/test/timer_simple_SUITE.erl31
-rw-r--r--lib/stdlib/test/zip_SUITE.erl3
-rw-r--r--lib/stdlib/vsn.mk2
-rw-r--r--lib/syntax_tools/doc/src/notes.xml21
-rw-r--r--lib/syntax_tools/src/erl_recomment.erl2
-rw-r--r--lib/syntax_tools/test/Makefile2
-rw-r--r--lib/syntax_tools/vsn.mk2
-rw-r--r--lib/test_server/doc/src/notes.xml205
-rw-r--r--lib/test_server/doc/src/ts.xml2
-rw-r--r--lib/test_server/include/test_server.hrl5
-rw-r--r--lib/test_server/include/test_server_line.hrl3
-rw-r--r--lib/test_server/src/Makefile1
-rw-r--r--lib/test_server/src/configure.in4
-rw-r--r--lib/test_server/src/test_server.app.src1
-rw-r--r--lib/test_server/src/test_server.erl645
-rw-r--r--lib/test_server/src/test_server_ctrl.erl202
-rw-r--r--lib/test_server/src/test_server_line.erl387
-rw-r--r--lib/test_server/src/test_server_sup.erl25
-rw-r--r--lib/test_server/src/ts.config2
-rw-r--r--lib/test_server/src/ts_erl_config.erl5
-rw-r--r--lib/test_server/src/ts_install.erl9
-rw-r--r--lib/test_server/src/ts_install_cth.erl17
-rw-r--r--lib/test_server/src/ts_run.erl18
-rw-r--r--lib/test_server/test/Makefile4
-rw-r--r--lib/test_server/test/test_server_SUITE.erl6
-rw-r--r--lib/test_server/vsn.mk2
-rw-r--r--lib/toolbar/doc/src/notes.xml16
-rw-r--r--lib/toolbar/src/toolbar_toolconfig.erl6
-rw-r--r--lib/toolbar/vsn.mk2
-rw-r--r--lib/tools/c_src/Makefile.in11
-rw-r--r--lib/tools/doc/src/instrument.xml6
-rw-r--r--lib/tools/doc/src/notes.xml107
-rw-r--r--lib/tools/doc/src/xref.xml8
-rw-r--r--lib/tools/emacs/erlang.el99
-rw-r--r--lib/tools/src/cover.erl14
-rw-r--r--lib/tools/src/make.erl17
-rw-r--r--lib/tools/test/Makefile2
-rw-r--r--lib/tools/test/cover_SUITE.erl4
-rw-r--r--lib/tools/vsn.mk2
-rw-r--r--lib/tv/doc/src/notes.xml26
-rw-r--r--lib/tv/src/tv_main.erl2
-rw-r--r--lib/tv/src/tv_mnesia_rpc.erl2
-rw-r--r--lib/tv/vsn.mk2
-rw-r--r--lib/typer/src/typer.erl31
-rw-r--r--lib/typer/vsn.mk2
-rw-r--r--lib/webtool/doc/src/notes.xml34
-rw-r--r--lib/webtool/doc/src/webtool_chapter.xml6
-rw-r--r--lib/webtool/priv/Makefile8
-rw-r--r--lib/webtool/vsn.mk2
-rw-r--r--lib/wx/api_gen/gen_util.erl50
-rw-r--r--lib/wx/api_gen/gl_gen.erl4
-rw-r--r--lib/wx/api_gen/wx_extra/wxListCtrl.c_src161
-rw-r--r--lib/wx/api_gen/wx_extra/wxListCtrl.erl112
-rw-r--r--lib/wx/api_gen/wx_gen.erl25
-rw-r--r--lib/wx/api_gen/wx_gen_cpp.erl362
-rw-r--r--lib/wx/api_gen/wx_gen_erl.erl310
-rw-r--r--lib/wx/api_gen/wxapi.conf13
-rw-r--r--lib/wx/c_src/egl_impl.cpp58
-rw-r--r--lib/wx/c_src/gen/wxe_derived_dest.h41
-rw-r--r--lib/wx/c_src/gen/wxe_events.cpp572
-rw-r--r--lib/wx/c_src/gen/wxe_funcs.cpp191
-rw-r--r--lib/wx/c_src/gen/wxe_init.cpp2
-rw-r--r--lib/wx/c_src/gen/wxe_macros.h3370
-rw-r--r--lib/wx/c_src/wxePrintout.cpp269
-rw-r--r--lib/wx/c_src/wxe_impl.cpp228
-rw-r--r--lib/wx/c_src/wxe_impl.h11
-rw-r--r--lib/wx/doc/src/notes.xml51
-rw-r--r--lib/wx/examples/demo/ex_listCtrl.erl50
-rw-r--r--lib/wx/include/gl.hrl1682
-rw-r--r--lib/wx/src/Makefile7
-rw-r--r--lib/wx/src/gen/wxBoxSizer.erl6
-rw-r--r--lib/wx/src/gen/wxFlexGridSizer.erl6
-rw-r--r--lib/wx/src/gen/wxGridBagSizer.erl6
-rw-r--r--lib/wx/src/gen/wxGridSizer.erl6
-rw-r--r--lib/wx/src/gen/wxListCtrl.erl94
-rw-r--r--lib/wx/src/gen/wxListItemAttr.erl122
-rw-r--r--lib/wx/src/gen/wxRegion.erl4
-rw-r--r--lib/wx/src/gen/wxSizer.erl26
-rw-r--r--lib/wx/src/gen/wxStaticBoxSizer.erl6
-rw-r--r--lib/wx/src/gen/wxStdDialogButtonSizer.erl6
-rw-r--r--lib/wx/src/gen/wxWindow.erl6
-rw-r--r--lib/wx/src/gen/wxe_debug.hrl3370
-rw-r--r--lib/wx/src/gen/wxe_funcs.hrl3370
-rw-r--r--lib/wx/src/wx.appup.src3
-rw-r--r--lib/wx/src/wx_object.erl6
-rw-r--r--lib/wx/src/wxe_server.erl52
-rw-r--r--lib/wx/test/wx_class_SUITE.erl146
-rw-r--r--lib/wx/test/wxt.erl6
-rw-r--r--lib/wx/vsn.mk2
-rw-r--r--lib/xmerl/doc/examples/Makefile61
-rw-r--r--lib/xmerl/doc/examples/mkdocs.erl9
-rw-r--r--lib/xmerl/doc/examples/sdocbook2xhtml.erl823
-rwxr-xr-xlib/xmerl/doc/examples/test_html.erl225
-rw-r--r--lib/xmerl/doc/examples/xmerl_test.erl522
-rwxr-xr-xlib/xmerl/doc/examples/xml/test.xml6
-rwxr-xr-xlib/xmerl/doc/examples/xml/test2.xml8
-rwxr-xr-xlib/xmerl/doc/examples/xml/test3.xml8
-rwxr-xr-xlib/xmerl/doc/examples/xml/test4.xml9
-rwxr-xr-xlib/xmerl/doc/examples/xml/test5.xml9
-rwxr-xr-xlib/xmerl/doc/examples/xml/testdtd.dtd17
-rwxr-xr-xlib/xmerl/doc/examples/xml/xmerl.xml523
-rw-r--r--lib/xmerl/doc/examples/xml/xmerl_xs.xml541
-rw-r--r--lib/xmerl/doc/examples/xserl_test.erl85
-rw-r--r--lib/xmerl/doc/src/notes.xml105
-rw-r--r--lib/xmerl/include/xmerl_xsd.hrl1
-rw-r--r--lib/xmerl/src/xmerl.erl2
-rw-r--r--lib/xmerl/src/xmerl_sax_parser.erl7
-rw-r--r--lib/xmerl/src/xmerl_scan.erl40
-rw-r--r--lib/xmerl/src/xmerl_ucs.erl37
-rw-r--r--lib/xmerl/src/xmerl_xpath.erl6
-rw-r--r--lib/xmerl/src/xmerl_xsd.erl65
-rw-r--r--lib/xmerl/src/xmerl_xsd_type.erl6
-rw-r--r--lib/xmerl/test/Makefile127
-rw-r--r--lib/xmerl/test/ReadMe24
-rw-r--r--lib/xmerl/test/testcases.dtd103
-rw-r--r--lib/xmerl/test/xmerl.cover2
-rw-r--r--lib/xmerl/test/xmerl.spec1
-rw-r--r--lib/xmerl/test/xmerl_SUITE.erl664
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/cpd.tar.gzbin0 -> 2128 bytes
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/eventp/CMOM.xml30261
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/eventp/CelloMOM.stub14
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/eventp/CelloMOM.xml30261
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/eventp/mp.dtd274
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/eventp/wurfl.stub5
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/eventp/wurfl.xml9
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/misc.tar.gzbin0 -> 47340 bytes
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/xpath/documentRoot.xml43
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/xpath/e1074.xml18
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/xpath/e1075.xml18
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/xpath/e1076.xml13
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/xpath/e1077.xml16
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/xpath/e1078.xml11
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/xpath/motorcycles.xml25
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/xpath/myBS_model.xml6
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/xpath/purchaseOrder.xml36
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/xpath/xpath.xml25
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl266
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_lib.erl184
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_text.erl28
-rw-r--r--lib/xmerl/test/xmerl_app_test.erl242
-rw-r--r--lib/xmerl/test/xmerl_appup_test.erl392
-rw-r--r--lib/xmerl/test/xmerl_sax_SUITE.erl110
-rw-r--r--lib/xmerl/test/xmerl_sax_std_SUITE.erl25635
-rw-r--r--lib/xmerl/test/xmerl_std_SUITE.erl11799
-rw-r--r--lib/xmerl/test/xmerl_std_SUITE_data/ibm.tgzbin0 -> 112986 bytes
-rw-r--r--lib/xmerl/test/xmerl_std_SUITE_data/japanese.tgzbin0 -> 376850 bytes
-rw-r--r--lib/xmerl/test/xmerl_std_SUITE_data/oasis.tgzbin0 -> 26750 bytes
-rw-r--r--lib/xmerl/test/xmerl_std_SUITE_data/sun.tgzbin0 -> 23117 bytes
-rw-r--r--lib/xmerl/test/xmerl_std_SUITE_data/w3c-copyright-19980720.html81
-rw-r--r--lib/xmerl/test/xmerl_std_SUITE_data/xmltest.tgzbin0 -> 43920 bytes
-rw-r--r--lib/xmerl/test/xmerl_test_lib.erl92
-rw-r--r--lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE.erl24131
-rw-r--r--lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE_data/msx_failed_cases.log2234
-rw-r--r--lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE_data/msxsdtest.tar.gzbin0 -> 703416 bytes
-rw-r--r--lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE_data/w3c-copyright-19990405.html82
-rw-r--r--lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE.erl15962
-rw-r--r--lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE_data/nist_failed_cases.log894
-rw-r--r--lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE_data/nisttest.tar.gzbin0 -> 1113062 bytes
-rw-r--r--lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE_data/w3c-copyright-19990405.html82
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE.erl1153
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/4Q99.xml25
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/CxDataType_Rel5.xsd211
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/address.xsd69
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/complexTypes.xsd112
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/complexTypes1.xml44
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/complexTypes2.xml44
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/enum_bug.xml2
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/enum_bug.xsd20
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/gpx/clementine_loop.gpx3594
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/gpx/gpx.xsd227
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/instance.xml149
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/int.xml4
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/ipo.xml32
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/ipo.xsd60
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/ipo_redefine.xml34
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/ipo_redefine.xsd73
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/ipo_substGroup.xml37
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/ipo_substGroup.xsd65
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/measCollec.xsd160
-rwxr-xr-xlib/xmerl/test/xmerl_xsd_SUITE_data/mim.xsd511
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/EricssonSpecificAttributes.5.1.xsd1531
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/EricssonSpecificAttributes.5.1Tran.xsd2164
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/ImportExportMap.xsd75
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/configData.xsd41
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/genericNrm.xsd230
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/geranNrm.xsd63
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/rnc.xml23763
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/utranNrm.xsd174
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/po.xml32
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/po.xsd67
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/po1.tab424
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/po1.tab2424
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/po1.xml36
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/po1.xsd64
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all.xsd65
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all1.xml36
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all2.xml35
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all_err1.xml37
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all_err2.xml28
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/po1_global.xsd86
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/po2.xml36
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/po_attrGroup.xml32
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/po_attrGroup.xsd81
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/report.tab850
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/report.tab2850
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/report.xsd82
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/report2.xsd82
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/simple_int.xsd13
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/sis/IntegratedSite.xsd5238
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/sis/IsTypes.xsd42
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/sis/MainSwitch_1.xsd1496
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/sis/MyBsModel_1.xsd502
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/sis/bs_mim.xml1187
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/sis/dummy_action_mim.xml186
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/sis/hwm_mim.xml631
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/sis/instance.xml240
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/sis/mim.xsd486
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/sis/mim2.xsd506
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/sis/nc.xsd14
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/sis/swm_mim.xml881
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/small.xml8
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/small.xsd60
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/ticket_7288.xml56
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/ticket_8599.xml6
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/ticket_8599.xsd17
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/vehicle.xml117
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/vehicle.xsd82
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/vehicle2.xml61
-rw-r--r--lib/xmerl/test/xmerl_xsd_SUITE_data/vehicle3.xml117
-rw-r--r--lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE.erl812
-rw-r--r--lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE_data/sun_failed_cases.log33
-rw-r--r--lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE_data/suntest.tar.gzbin0 -> 21294 bytes
-rw-r--r--lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE_data/w3c-copyright-19990405.html82
-rw-r--r--lib/xmerl/test/xmerl_xsd_lib.erl321
-rw-r--r--lib/xmerl/test/xmlconf.xml53
-rw-r--r--lib/xmerl/test/xmlconformance.msxsl527
-rw-r--r--lib/xmerl/test/xmlconformance.xsl498
-rw-r--r--lib/xmerl/vsn.mk2
2595 files changed, 475264 insertions, 189686 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 5faf0c8714..7e52d6e32e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -28,24 +28,11 @@ ifeq ($(findstring vxworks,$(TARGET)),vxworks)
snmp otp_mibs appmon erl_interface os_mon tools runtime_tools
ifdef BUILD_ALL
OTHER_SUB_DIRECTORIES += mnesia jinterface ic asn1 debugger \
- inets mnesia_session orber pman tv observer cosTransactions cosEvent \
- cosTime cosNotification cosProperty cosFileTransfer cosEventDomain
+ inets mnesia_session diameter orber pman tv observer \
+ cosTransactions cosEvent cosTime cosNotification cosProperty
+ cosFileTransfer cosEventDomain
endif
else
- ifeq ($(findstring ose,$(TARGET)),ose)
- ERTS_SUB_DIRECTORIES = stdlib sasl kernel compiler erl_interface
- OTHER_SUB_DIRECTORIES = \
- snmp otp_mibs appmon tools
-# OTHER_SUB_DIRECTORIES = \
-# appmon os_mon tools runtime_tools
- ifdef BUILD_ALL
- OTHER_SUB_DIRECTORIES += mnesia \
- inets pman tv observer
-# OTHER_SUB_DIRECTORIES += mnesia ic asn1 debugger \
-# inets orber pman tv observer cosTransactions cosEvent \
-# cosTime cosNotification cosProperty cosFileTransfer cosEventDomain
- endif
- else
#
# unix and win32
# --------------
@@ -57,10 +44,12 @@ else
OTHER_SUB_DIRECTORIES += \
snmp otp_mibs appmon erl_interface asn1 jinterface gs wx inets ic \
mnesia crypto orber os_mon parsetools syntax_tools pman \
- public_key ssl toolbar tv observer debugger reltool odbc runtime_tools \
+ public_key ssl toolbar tv observer debugger reltool odbc \
+ diameter \
cosTransactions cosEvent cosTime cosNotification cosProperty \
cosFileTransfer cosEventDomain et megaco webtool \
- xmerl edoc eunit ssh inviso typer docbuilder erl_docgen common_test percept
+ xmerl edoc eunit ssh inviso typer docbuilder erl_docgen \
+ common_test percept dialyzer
# dialyzer
OTHER_SUB_DIRECTORIES += hipe
else # BUILD_ALL on unix
@@ -68,31 +57,28 @@ else
snmp otp_mibs appmon erl_interface asn1 jinterface wx debugger reltool gs inets \
ic mnesia crypto orber os_mon parsetools syntax_tools \
pman public_key ssl toolbar tv observer odbc \
- runtime_tools cosTransactions cosEvent cosTime cosNotification \
+ diameter \
+ cosTransactions cosEvent cosTime cosNotification \
cosProperty cosFileTransfer cosEventDomain et megaco webtool \
- xmerl edoc eunit ssh inviso typer docbuilder erl_docgen common_test percept
+ xmerl edoc eunit ssh inviso typer docbuilder erl_docgen \
+ common_test percept dialyzer
# dialyzer
OTHER_SUB_DIRECTORIES += hipe $(TSP_APP)
endif
endif
- endif
endif
ifdef BOOTSTRAP
SUB_DIRECTORIES = \
- kernel stdlib compiler orber/include
+ kernel stdlib compiler
else
ifdef SECONDARY_BOOTSTRAP
SUB_DIRECTORIES = hipe parsetools asn1/src
else
ifdef TERTIARY_BOOTSTRAP
- SUB_DIRECTORIES = snmp
- else
- ifdef FOURTH_BOOTSTRAP
- SUB_DIRECTORIES = sasl jinterface ic syntax_tools
- else # Not bootstrap build
- SUB_DIRECTORIES = $(ERTS_SUB_DIRECTORIES) $(OTHER_SUB_DIRECTORIES)
- endif
+ SUB_DIRECTORIES = snmp sasl jinterface ic syntax_tools
+ else # Not bootstrap build
+ SUB_DIRECTORIES = $(ERTS_SUB_DIRECTORIES) $(OTHER_SUB_DIRECTORIES)
endif
endif
endif
diff --git a/lib/asn1/c_src/Makefile b/lib/asn1/c_src/Makefile
index 9e9cb18524..8c06be56f8 100644
--- a/lib/asn1/c_src/Makefile
+++ b/lib/asn1/c_src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2002-2010. All Rights Reserved.
+# Copyright Ericsson AB 2002-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -51,33 +51,26 @@ EI_LIBDIR = $(ERL_TOP)/lib/erl_interface/obj$(TYPEMARKER)/$(TARGET)
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
-EI_INCLUDES = -I$(ERL_TOP)/lib/erl_interface/include
CFLAGS = $(DED_INCLUDES) $(EI_INCLUDES) $(DED_CFLAGS)
LDFLAGS += $(DED_LDFLAGS)
-LD_INCL_EI = -L$(EI_LIBDIR)
-
# ----------------------------------------------------
# Target Specs
# ----------------------------------------------------
-C_FILES = asn1_erl_driver.c
+NIF_OBJ_FILES = $(OBJDIR)/asn1_erl_nif.o
ifeq ($(TARGET),win32)
-LD_EI = -lei_md
-SHARED_OBJ_FILES = $(LIBDIR)/asn1_erl_drv.dll
-OBJ_FILES = $(OBJDIR)/asn1_erl_drv.o
+NIF_SHARED_OBJ_FILE = $(LIBDIR)/asn1_erl_nif.dll
CLIB_FLAGS =
LN=cp
else
-LD_EI = -lei
-OBJ_FILES = $(OBJDIR)/asn1_erl_drv.o
ifeq ($(findstring vxworks,$(TARGET)),vxworks)
-SHARED_OBJ_FILES = $(LIBDIR)/asn1_erl_drv.eld
+NIF_SHARED_OBJ_FILE = $(LIBDIR)/asn1_erl_nif.eld
CLIB_FLAGS =
else
-SHARED_OBJ_FILES = $(LIBDIR)/asn1_erl_drv.so
+NIF_SHARED_OBJ_FILE = $(LIBDIR)/asn1_erl_nif.so
CLIB_FLAGS = -lc
endif
LN= ln -s
@@ -87,7 +80,9 @@ endif
# Targets
# ----------------------------------------------------
-opt: $(OBJDIR) $(LIBDIR) $(SHARED_OBJ_FILES)
+_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
+
+opt: $(NIF_SHARED_OBJ_FILE)
debug: opt
@@ -103,20 +98,12 @@ docs:
# ----------------------------------------------------
-$(OBJ_FILES): $(C_FILES)
- $(CC) -c $(CFLAGS) -o $(OBJ_FILES) $(C_FILES)
-
-$(SHARED_OBJ_FILES): $(OBJ_FILES)
- $(LD) $(LDFLAGS) $(LD_INCL_EI) -o $(SHARED_OBJ_FILES) $(OBJ_FILES) $(LD_EI) $(CLIB_FLAGS) $(LIBS)
-
-$(LIBDIR):
- -mkdir -p $(LIBDIR)
-
-$(OBJDIR):
- -mkdir -p $(OBJDIR)
+$(OBJDIR)/%.o: %.c
+ $(CC) -c $(CFLAGS) -O3 -o $@ $<
+$(NIF_SHARED_OBJ_FILE): $(NIF_OBJ_FILES)
+ $(LD) $(LDFLAGS) -o $(NIF_SHARED_OBJ_FILE) $(NIF_OBJ_FILES) $(CLIB_FLAGS) $(LIBS)
-
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
@@ -124,9 +111,9 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)/priv/lib
- $(INSTALL_PROGRAM) $(SHARED_OBJ_FILES) $(RELSYSDIR)/priv/lib
+ $(INSTALL_PROGRAM) $(NIF_SHARED_OBJ_FILE) $(RELSYSDIR)/priv/lib
$(INSTALL_DIR) $(RELSYSDIR)/c_src
- $(INSTALL_DATA) $(C_FILES) $(RELSYSDIR)/c_src
+ $(INSTALL_DATA) *.c $(RELSYSDIR)/c_src
release_docs_spec:
diff --git a/lib/asn1/c_src/asn1_erl_driver.c b/lib/asn1/c_src/asn1_erl_driver.c
deleted file mode 100644
index 9dd3a0fd7d..0000000000
--- a/lib/asn1/c_src/asn1_erl_driver.c
+++ /dev/null
@@ -1,1670 +0,0 @@
-/*
- * %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 <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include "erl_driver.h"
-#include "ei.h"
-
-
-/* #define ASN1_DEBUG 1 */
-
-#define ASN1_OK 0
-#define ASN1_ERROR -1
-#define ASN1_COMPL_ERROR 1
-#define ASN1_MEMORY_ERROR 0
-#define ASN1_DECODE_ERROR 2
-#define ASN1_TAG_ERROR -3
-#define ASN1_LEN_ERROR -4
-#define ASN1_INDEF_LEN_ERROR -5
-#define ASN1_VALUE_ERROR -6
-
-
-#define ASN1_CLASS 0xc0
-#define ASN1_FORM 0x20
-#define ASN1_CLASSFORM (ASN1_CLASS | ASN1_FORM)
-#define ASN1_TAG 0x1f
-#define ASN1_LONG_TAG 0x7f
-
-#define ASN1_INDEFINITE_LENGTH 0x80
-#define ASN1_SHORT_DEFINITE_LENGTH 0
-
-#define ASN1_PRIMITIVE 0
-#define ASN1_CONSTRUCTED 0x20
-
-#define ASN1_COMPLETE 1
-#define ASN1_BER_TLV_DECODE 2
-#define ASN1_BER_TLV_PARTIAL_DECODE 3
-
-#define ASN1_NOVALUE 0
-
-#define ASN1_SKIPPED 0
-#define ASN1_OPTIONAL 1
-#define ASN1_CHOOSEN 2
-
-
-#define CEIL(X,Y) ((X-1) / Y + 1)
-
-#define INVMASK(X,M) (X & (M ^ 0xff))
-#define MASK(X,M) (X & M)
-
-typedef struct {
- ErlDrvPort port;
- int buffer_size;
-} asn1_data;
-
-/* int min_alloc_bytes; */
-
-
-static ErlDrvData asn1_drv_start(ErlDrvPort, char *);
-
-static void asn1_drv_stop(ErlDrvData);
-
-int asn1_drv_control(ErlDrvData, unsigned int, char *, int, char **, int);
-
-int complete(ErlDrvBinary **,unsigned char *,unsigned char *, int);
-
-int insert_octets(int, unsigned char **, unsigned char **, int *);
-
-int insert_octets_except_unused(int, unsigned char **, unsigned char **,
- int *, int);
-
-int insert_octets_as_bits_exact_len(int, int, unsigned char **,
- unsigned char **, int *);
-
-int insert_octets_as_bits(int, unsigned char **, unsigned char **,int *);
-
-int pad_bits(int, unsigned char **, int *);
-
-int insert_least_sign_bits(int, unsigned char, unsigned char **, int *);
-
-int insert_most_sign_bits(int, unsigned char, unsigned char **, int *);
-
-int insert_bits_as_bits(int, int, unsigned char **, unsigned char **, int *);
-
-int insert_octets_unaligned(int, unsigned char **, unsigned char **, int);
-
-int realloc_memory(ErlDrvBinary **,int,unsigned char **,unsigned char **);
-
-int decode_begin(ErlDrvBinary **,unsigned char *, int, unsigned int *);
-
-int decode(ErlDrvBinary **,int *,unsigned char *,int *, int);
-
-int decode_tag(char *,int *,unsigned char *,int,int *);
-
-int decode_value(int *,unsigned char *,int *,ErlDrvBinary **,int ,int);
-
-
-/* declaration of functions used for partial decode of a BER encoded
- message */
-
-int decode_partial(ErlDrvBinary **,unsigned char *, int);
-
-int skip_tag(unsigned char *,int *,int);
-
-int skip_length_and_value(unsigned char *,int *,int);
-
-int get_tag(unsigned char *,int *,int);
-
-int get_value(char *,unsigned char *,int *,int);
-
-static ErlDrvEntry asn1_drv_entry = {
- NULL, /* init, always NULL for dynamic drivers */
- asn1_drv_start, /* start, called when port is opened */
- asn1_drv_stop, /* stop, called when port is closed */
- NULL, /* output, called when erlang has sent */
- NULL, /* ready_input, called when input descriptor ready */
- NULL, /* ready_output, called when output descriptor ready */
- "asn1_erl_drv", /* char *driver_name, the argument to open_port */
- NULL, /* finish, called when unloaded */
- NULL, /* void * that is not used (BC) */
- asn1_drv_control, /* control, port_control callback */
- NULL, /* timeout, called on timeouts */
- NULL, /* outputv, vector output interface */
-
- NULL, /* ready_async */
- NULL, /* flush */
- NULL, /* call */
- NULL, /* event */
- ERL_DRV_EXTENDED_MARKER,
- ERL_DRV_EXTENDED_MAJOR_VERSION,
- ERL_DRV_EXTENDED_MINOR_VERSION,
- ERL_DRV_FLAG_USE_PORT_LOCKING,
- NULL, /* handle2 */
- NULL /* process_exit */
-};
-
-
-
-DRIVER_INIT(asn1_erl_drv) /* must match name in driver_entry */
-{
- return &asn1_drv_entry;
-}
-
-static ErlDrvData asn1_drv_start(ErlDrvPort port, char *buff)
-{
- /* extern int min_alloc_bytes; */
- char *ptr;
- asn1_data* d;
-
- d = (asn1_data*)driver_alloc(sizeof(asn1_data));
- set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
- d->port = port;
-
- if ((ptr = getenv("ASN1_MIN_BUF_SIZE")) == NULL)
- d->buffer_size = 1024;
- else
- d->buffer_size = atoi(ptr);
- return (ErlDrvData)d;
-}
-
-
-static void asn1_drv_stop(ErlDrvData handle)
-{
- driver_free((char*)handle);
-}
-
-
-
-int asn1_drv_control(ErlDrvData handle,
- unsigned int command,
- char *buf,
- int buf_len,
- char **res_buf,
- int res_buf_len)
-{
- char *complete_buf;
- int complete_len, decode_len;
- ErlDrvBinary *drv_binary;
- ErlDrvBinary **drv_bin_ptr;
- asn1_data* a_data;
- int min_alloc_bytes;
- unsigned int err_pos = 0; /* in case of error, return last correct position */
- int ret_err; /* return value in case of error in TLV decode, i.e. length of list in res_buf */
-
- /* In case previous call to asn1_drv_control resulted in a change of
- return value from binary to integer list */
- a_data = (asn1_data *)handle;
- min_alloc_bytes = a_data->buffer_size;
- set_port_control_flags(a_data->port, PORT_CONTROL_FLAG_BINARY);
-
- if (command == ASN1_COMPLETE)
- {
- if (buf_len==0) {
- return 0; /* Avoid binary buffer overwrite (OTP-8451) */
- }
- /* Do the PER complete encode step */
- if ((drv_binary = driver_alloc_binary(buf_len))==NULL) {
- /* error handling */
- set_port_control_flags(a_data->port, 0);
- return ASN1_MEMORY_ERROR;
- }
- complete_buf = drv_binary->orig_bytes;
- if ((complete_len = complete(&drv_binary,complete_buf,buf,buf_len)) == ASN1_ERROR)
- {
- /* error handling due to failure in complete */
- /* printf("error when running complete\n\r"); */
- driver_free_binary(drv_binary);
- set_port_control_flags(a_data->port, 0);
- **res_buf = '1';
- return ASN1_COMPL_ERROR;
- }
- /* printf("complete_len=%dbuf_len=%d,orig_size=%d\n\r",complete_len,buf_len,drv_binary->orig_size); */
- /* now the message is complete packed, return to Erlang */
- /* if (complete_len < buf_len) {*/
- if (complete_len < drv_binary->orig_size) {
- ErlDrvBinary *tmp;
- if ((tmp=driver_realloc_binary(drv_binary,complete_len)) == NULL){
- /*error handling due to memory allocation failure */
- driver_free_binary(drv_binary);
- set_port_control_flags(a_data->port, 0);
- return ASN1_MEMORY_ERROR;
- }else
- drv_binary=tmp;
- }
- *res_buf = (char *)drv_binary;
- return complete_len;
- } else if (command == ASN1_BER_TLV_DECODE) { /* control == 2 */
- /* Do the tlv decode,
- return the resulting term encoded on the Erlang
- external format */
-/* printf("driver: buffer_len = %d, min_alloc_bytes = %d\r\n",buf_len,min_alloc_bytes); */
- if ((drv_binary = driver_alloc_binary((buf_len*5)+min_alloc_bytes))==NULL) {
- /* error handling */
- set_port_control_flags(a_data->port, 0);
- return ASN1_MEMORY_ERROR;
- }
- drv_bin_ptr = &drv_binary;
- if ((decode_len = decode_begin(drv_bin_ptr,buf,buf_len,&err_pos)) <= ASN1_ERROR)
- {
- /* error handling due to failure in decode */
- char tmp_res_buf[5];
- driver_free_binary(*drv_bin_ptr);
- set_port_control_flags(a_data->port, 0);
-
- if(decode_len==ASN1_ERROR)
- tmp_res_buf[0]='1';
- else if(decode_len==ASN1_TAG_ERROR)
- tmp_res_buf[0]='2';
- else if(decode_len==ASN1_LEN_ERROR)
- tmp_res_buf[0]='3';
- else if(decode_len==ASN1_INDEF_LEN_ERROR)
- tmp_res_buf[0]='4';
- else if(decode_len==ASN1_VALUE_ERROR)
- tmp_res_buf[0]='5';
-/* printf("err_pos=%d\r\n",err_pos); */
-/* printf("decode_len:%d\r\n",decode_len); */
- ret_err = 1;
- while(err_pos>0){
- tmp_res_buf[ret_err] =(char)err_pos;/* c;*/
- err_pos = err_pos >> 8;
- ret_err++;
- }
- strncpy(*res_buf,tmp_res_buf,ret_err);
- return ret_err;
- }
-/* printf("decode_len=%d\r\n",decode_len); */
- if (decode_len < ((buf_len * 5) + min_alloc_bytes)) {
- /* not all memory was used => we have to reallocate */
- ErlDrvBinary *tmp;
- if ((tmp=driver_realloc_binary(*drv_bin_ptr,decode_len)) == NULL){
- /*error handling due to memory allocation failure */
- driver_free_binary(*drv_bin_ptr);
- set_port_control_flags(a_data->port, 0);
- return ASN1_MEMORY_ERROR;
- }else
- *drv_bin_ptr=tmp;
- }
- *res_buf = (char *)(*drv_bin_ptr);
- return decode_len;
- } else { /*command == ASN1_BER_TLV_PARTIAL_DECODE */
- if ((drv_binary = driver_alloc_binary(buf_len))==NULL) {
- /* error handling */
- set_port_control_flags(a_data->port, 0);
- return ASN1_MEMORY_ERROR;
- }
- drv_bin_ptr = &drv_binary;
- if ((decode_len = decode_partial(drv_bin_ptr,buf,buf_len))
- <= ASN1_ERROR) {
- /* error handling due to failure in decode */
- driver_free_binary(*drv_bin_ptr);
- set_port_control_flags(a_data->port, 0);
-
-/* printf("asn1_drv_control 1: decode_len=%d\r\n",decode_len); */
-
- if(decode_len==ASN1_ERROR)
- **res_buf = '1';
- return ASN1_DECODE_ERROR;
- }
- if (decode_len < buf_len) {
- /* not all memory was used => we have to reallocate */
- ErlDrvBinary *tmp;
-/* printf("asn1_drv_control 2: decode_len=%d\r\n",decode_len); */
- if ((tmp=driver_realloc_binary(*drv_bin_ptr,decode_len)) == NULL){
- /*error handling due to memory allocation failure */
- driver_free_binary(*drv_bin_ptr);
- set_port_control_flags(a_data->port, 0);
- return ASN1_MEMORY_ERROR;
- }else
- *drv_bin_ptr=tmp;
- }
- *res_buf = (char *)(*drv_bin_ptr);
- return decode_len;
- }
-}
-
-
-
-/*
- *
- * This section defines functionality for the complete encode of a
- * PER encoded message
- *
- */
-
-int complete(ErlDrvBinary **drv_binary,unsigned char *complete_buf,
- unsigned char *in_buf, int in_buf_len)
-{
- int counter = in_buf_len;
- /* counter keeps track of number of bytes left in the
- input buffer */
-
- int buf_space = in_buf_len;
- /* This is the amount of allocated space left of the complete_buf. It
- is possible when padding is applied that more space is needed than
- was originally allocated. */
-
- int buf_size = in_buf_len;
- /* Size of the buffer. May become reallocated and thus other than
- in_buf_len */
-
- unsigned char *in_ptr, *ptr;
- /* in_ptr points at the next byte in in_buf to be moved to
- complete_buf.
- ptr points into the new completed buffer, complete_buf, at the
- position of the next byte that will be set */
- int unused = 8;
- /* unused = [1,...,8] indicates how many of the rigthmost bits of
- the byte that ptr points at that are unassigned */
-
- int no_bits,no_bytes,in_unused,desired_len,ret, saved_mem, needed, pad_bits;
-
- unsigned char val;
-
- in_ptr = in_buf;
- ptr = complete_buf;
- *ptr = 0x00;
- while(counter > 0) {
- counter--;
-/* printf("*in_ptr = %d\n\r",*in_ptr); */
- switch (*in_ptr) {
- case 0:
- /* just one zero-bit should be added to the buffer */
- if(unused == 1){
- unused = 8;
- *++ptr = 0x00;
- buf_space--;
- } else
- unused--;
- break;
-
- case 1:
- /* one one-bit should be added to the buffer */
- if(unused == 1){
- *ptr = *ptr | 1;
- unused = 8;
- *++ptr = 0x00;
- buf_space--;
- } else {
- *ptr = *ptr | (1 << (unused - 1));
- unused--;
- }
- break;
-
- case 2:
- /* align buffer to end of byte */
- if (unused != 8) {
- *++ptr = 0x00;
- buf_space--;
- unused = 8;
- }
- break;
-
- case 10:
- /* next byte in in_buf tells how many bits in the second next
- byte that will be used */
- /* The leftmost unused bits in the value byte are supposed to be
- zero bits */
- no_bits = (int)*(++in_ptr);
- val = *(++in_ptr);
- counter -= 2;
- if ((ret=insert_least_sign_bits(no_bits,val,&ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- case 20:
- /* in this case the next value in_ptr points at holds the number
- of following bytes that holds the value that will be inserted
- in the completed buffer */
- no_bytes = (int)*(++in_ptr);
- counter -= (no_bytes + 1);
- if ((counter<0) ||
- (ret=insert_octets(no_bytes,&in_ptr,&ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- case 21:
- /* in this case the next two bytes in_ptr points at holds the number
- of following bytes that holds the value that will be inserted
- in the completed buffer */
- no_bytes = (int)*(++in_ptr);
- no_bytes = no_bytes << 8;
- no_bytes = no_bytes | (int)*(++in_ptr);
- counter -= (2 + no_bytes);
- if ((counter<0) ||
- (ret=insert_octets(no_bytes,&in_ptr,&ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- case 30:
- /* If we call the following bytes, in the buffer in_ptr points at,
- By1,By2,Rest then Rest is the value that will be transfered to
- the completed buffer. By1 tells how many of the rightmost bits in
- Rest that should not be used. By2 is the length of Rest in bytes.*/
- in_unused = (int)*(++in_ptr);
- no_bytes = (int)*(++in_ptr);
- counter -= (2 + no_bytes);
-/* printf("%d: case 30: in_unused=%d, no_bytes=%d,counter=%d\n\r",__LINE__,in_unused,no_bytes,counter); */
- ret = -4711;
- if ((counter<0) ||
- (ret=insert_octets_except_unused(no_bytes,&in_ptr,&ptr,&unused,in_unused)) == ASN1_ERROR)
- return ASN1_ERROR;
-/* printf("%d: ret=%d\n\r",__LINE__, ret); */
- buf_space -= ret;
- break;
-
- case 31:
- /* If we call the following bytes, in the buffer in_ptr points at,
- By1,By2,By3,Rest then Rest is the value that will be transfered to
- the completed buffer. By1 tells how many of the rightmost bits in
- Rest that should not be used. By2 and By3 is the length of
- Rest in bytes.*/
- in_unused = (int)*(++in_ptr);
- no_bytes = (int)*(++in_ptr);
- no_bytes = no_bytes << 8;
- no_bytes = no_bytes | (int)*(++in_ptr);
- counter -= (3 + no_bytes);
- if ((counter<0) ||
- (ret=insert_octets_except_unused(no_bytes,&in_ptr,&ptr,&unused,in_unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- case 40:
- /* This case implies that next byte,By1,(..,By1,By2,Bin,...)
- is the desired length of the completed value, maybe needs
- padding zero bits or removal of trailing zero bits from Bin.
- By2 is the length of Bin and Bin is the value that will be
- put into the completed buffer. Each byte in Bin has the value
- 1 or 0.*/
- desired_len = (int)*(++in_ptr);
- no_bytes=(int)*(++in_ptr);
-
- /* This is the algorithm for need of memory reallocation:
- Only when padding (cases 40 - 43,45 - 47) more memory may be
- used than allocated. Therefore one has to keep track of how
- much of the allocated memory that has been saved, i.e. the
- difference between the number of parsed bytes of the input buffer
- and the number of used bytes of the output buffer.
- If saved memory is less than needed for the padding then we
- need more memory. */
- saved_mem = buf_space - counter;
- pad_bits = desired_len - no_bytes - unused;
- needed = (pad_bits > 0) ? CEIL(pad_bits,8) : 0;
- if (saved_mem < needed) {
- /* Have to allocate more memory */
- buf_size += needed;
- buf_space += needed;
- if (realloc_memory(drv_binary,buf_size,&ptr,
- &complete_buf) == ASN1_ERROR)
- return ASN1_ERROR;
- }
-
- counter -= (2 + no_bytes);
- if ((counter<0) ||
- (ret=insert_octets_as_bits_exact_len(desired_len,no_bytes,&in_ptr,
- &ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- case 41:
- /* Same as case 40 apart from By2, the length of Bin, which is in
- two bytes*/
- desired_len = (int)*(++in_ptr);
- no_bytes=(int)*(++in_ptr);
- no_bytes = no_bytes << 8;
- no_bytes = no_bytes | (int)*(++in_ptr);
-
- saved_mem = buf_space - counter;
- needed = CEIL((desired_len-unused),8) - no_bytes;
- if (saved_mem < needed) {
- /* Have to allocate more memory */
- buf_size += needed;
- buf_space += needed;
- if (realloc_memory(drv_binary,buf_size,&ptr,
- &complete_buf) == ASN1_ERROR)
- return ASN1_ERROR;
- }
-
- counter -= (3 + no_bytes);
- if ((counter<0) ||
- (ret=insert_octets_as_bits_exact_len(desired_len,no_bytes,&in_ptr,
- &ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- case 42:
- /* Same as case 40 apart from By1, the desired length, which is in
- two bytes*/
- desired_len = (int)*(++in_ptr);
- desired_len = desired_len << 8;
- desired_len = desired_len | (int)*(++in_ptr);
- no_bytes=(int)*(++in_ptr);
-
- saved_mem = buf_space - counter;
- needed = CEIL((desired_len-unused),8) - no_bytes;
- if (saved_mem < needed) {
- /* Have to allocate more memory */
- buf_size += needed;
- buf_space += needed;
- if (realloc_memory(drv_binary,buf_size,&ptr,
- &complete_buf) == ASN1_ERROR)
- return ASN1_ERROR;
- }
-
- counter -= (3 + no_bytes);
- if ((counter<0) ||
- (ret=insert_octets_as_bits_exact_len(desired_len,no_bytes,&in_ptr,
- &ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- case 43:
- /* Same as case 40 apart from By1 and By2, the desired length and
- the length of Bin, which are in two bytes each. */
- desired_len = (int)*(++in_ptr);
- desired_len = desired_len << 8;
- desired_len = desired_len | (int)*(++in_ptr);
- no_bytes=(int)*(++in_ptr);
- no_bytes = no_bytes << 8;
- no_bytes = no_bytes | (int)*(++in_ptr);
-
- saved_mem = buf_space - counter;
- needed = CEIL((desired_len-unused),8) - no_bytes;
- if (saved_mem < needed) {
- /* Have to allocate more memory */
- buf_size += needed;
- buf_space += needed;
- if (realloc_memory(drv_binary,buf_size,&ptr,
- &complete_buf) == ASN1_ERROR)
- return ASN1_ERROR;
- }
-
- counter -= (4 + no_bytes);
- if ((counter<0) ||
- (ret=insert_octets_as_bits_exact_len(desired_len,no_bytes,&in_ptr,
- &ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- case 45:
- /* This case assumes that the following bytes in the incoming buffer
- (called By1,By2,Bin) is By1, which is the number of bits (n) that
- will be inserted in the completed buffer. By2 is the number of
- bytes in Bin. Each bit in the buffer Bin should be inserted from
- the leftmost until the nth.*/
- desired_len = (int)*(++in_ptr);
- no_bytes=(int)*(++in_ptr);
-
- saved_mem = buf_space - counter;
- needed = CEIL((desired_len-unused),8) - no_bytes;
-/* printf("buf_space=%d, counter=%d, needed=%d",buf_space,counter,needed); */
- if (saved_mem < needed) {
- /* Have to allocate more memory */
- buf_size += needed;
- buf_space += needed;
- if (realloc_memory(drv_binary,buf_size,&ptr,
- &complete_buf) == ASN1_ERROR)
- return ASN1_ERROR;
- }
-
- counter -= (2 + no_bytes);
-/* printf("calling insert_bits_as_bits: desired_len=%d, no_bytes=%d\n\r",desired_len,no_bytes); */
-/* printf("1in_ptr=%d\n\r",in_ptr); */
-
- if((counter<0) ||
- (ret=insert_bits_as_bits(desired_len,no_bytes,&in_ptr,
- &ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
-/* printf("2in_ptr=%d, ptr=%d, complete_buf=%d\n\r",in_ptr,ptr,complete_buf); */
-/* printf("buf_space=%d, ret=%d, counter=%d\n\r",buf_space,ret,counter); */
- buf_space -= ret;
- break;
-
- case 46:
- /* Same as case 45 apart from By1, the desired length, which is
- in two bytes. */
- desired_len = (int)*(++in_ptr);
- desired_len = desired_len << 8;
- desired_len = desired_len | (int)*(++in_ptr);
- no_bytes=(int)*(++in_ptr);
-
- saved_mem = buf_space - counter;
- needed = CEIL((desired_len-unused),8) - no_bytes;
- if (saved_mem < needed) {
- /* Have to allocate more memory */
- buf_size += needed;
- buf_space += needed;
- if (realloc_memory(drv_binary,buf_size,&ptr,
- &complete_buf) == ASN1_ERROR)
- return ASN1_ERROR;
- }
-
- counter -= (3 + no_bytes);
- if((counter<0) ||
- (ret=insert_bits_as_bits(desired_len,no_bytes,&in_ptr,
- &ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- case 47:
- /* Same as case 45 apart from By1 and By2, the desired length
- and the length of Bin, which are in two bytes each. */
- desired_len = (int)*(++in_ptr);
- desired_len = desired_len << 8;
- desired_len = desired_len | (int)*(++in_ptr);
- no_bytes=(int)*(++in_ptr);
- no_bytes = no_bytes << 8;
- no_bytes = no_bytes | (int)*(++in_ptr);
-
- saved_mem = buf_space - counter;
- needed = CEIL((desired_len-unused),8) - no_bytes;
- if (saved_mem < needed) {
- /* Have to allocate more memory */
- buf_size += needed;
- buf_space += needed;
- if (realloc_memory(drv_binary,buf_size,&ptr,
- &complete_buf) == ASN1_ERROR)
- return ASN1_ERROR;
- }
-
- counter -= (4 + no_bytes);
- if((counter<0) ||
- (ret=insert_bits_as_bits(desired_len,no_bytes,&in_ptr,
- &ptr,&unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- buf_space -= ret;
- break;
-
- default:
- return ASN1_ERROR;
- }
- in_ptr++;
- }
- /* The returned buffer must be at least one byte and
- it must be octet aligned */
- if ((unused == 8) && (ptr != complete_buf))
- return (ptr - complete_buf);
- else {
- ptr++; /* octet align buffer */
- return (ptr - complete_buf);
- }
-}
-
-
-int realloc_memory(ErlDrvBinary **drv_binary,
- int amount,
- unsigned char **ptr,
- unsigned char **complete_buf) {
-
- ErlDrvBinary *tmp_bin;
- int i;
-
-/* printf("realloc_momory: amount = %d\n",amount); */
- if ((tmp_bin=driver_realloc_binary(*drv_binary,amount)) == NULL) {
- /*error handling due to memory allocation failure */
-/* printf("error when allocating memory\n"); */
- return ASN1_ERROR;
- }else {
- i = *ptr - *complete_buf;
- *drv_binary=tmp_bin;
- *complete_buf = (*drv_binary)->orig_bytes;
- *ptr = *complete_buf + i;
- }
- return ASN1_OK;
-}
-
-
-int insert_most_sign_bits(int no_bits,
- unsigned char val,
- unsigned char **output_ptr,
- int *unused) {
- unsigned char *ptr = *output_ptr;
-
- if (no_bits < *unused){
- *ptr = *ptr | (val >> (8 - *unused));
- *unused -= no_bits;
- } else if (no_bits == *unused) {
- *ptr = *ptr | (val >> (8 - *unused));
- *unused = 8;
- *++ptr = 0x00;
- } else {
- *ptr = *ptr | (val >> (8 - *unused));
- *++ptr = 0x00;
- *ptr = *ptr | (val << *unused);
- *unused = 8 - (no_bits - *unused);
- }
- *output_ptr = ptr;
- return ASN1_OK;
-}
-
-
-int insert_least_sign_bits(int no_bits,
- unsigned char val,
- unsigned char **output_ptr,
- int *unused) {
- unsigned char *ptr = *output_ptr;
- int ret = 0;
-
- if (no_bits < *unused){
- *ptr = *ptr | (val << (*unused - no_bits));
- *unused -= no_bits;
- } else if (no_bits == *unused){
- *ptr = *ptr | val;
- *unused = 8;
- *++ptr = 0x00;
- ret++;
- } else {
- /* first in the begun byte in the completed buffer insert
- so many bits that fit, then insert the rest in next byte.*/
- *ptr = *ptr | (val >> (no_bits - *unused));
- *++ptr = 0x00;
- ret++;
- *ptr = *ptr | (val << (8 - (no_bits - *unused)));
- *unused = 8 - (no_bits - *unused);
- }
- *output_ptr = ptr;
- return ret;
-}
-
-/* pad_bits adds no_bits bits in the buffer that output_ptr
- points at.
- */
-int pad_bits(int no_bits, unsigned char **output_ptr, int *unused)
- {
- unsigned char *ptr = *output_ptr;
- int ret = 0;
-
- while (no_bits > 0) {
- if(*unused == 1){
- *unused = 8;
- *++ptr = 0x00;
- ret++;
- } else
- (*unused)--;
- no_bits--;
- }
- *output_ptr = ptr;
- return ret;
- }
-
-
-/* insert_bits_as_bits removes no_bytes bytes from the buffer that in_ptr
- points at and takes the desired_no leftmost bits from those removed
- bytes and inserts them in the buffer(output buffer) that ptr points at.
- The unused parameter tells how many bits that are not set in the
- actual byte in the output buffer. If desired_no is more bits than the
- input buffer has in no_bytes bytes, then zero bits is padded.*/
-int insert_bits_as_bits(int desired_no,
- int no_bytes,
- unsigned char **input_ptr,
- unsigned char **output_ptr,
- int *unused)
-{
- unsigned char *in_ptr = *input_ptr;
- unsigned char val;
- int no_bits, ret, ret2;
-
- if (desired_no == (no_bytes * 8)) {
- if(insert_octets_unaligned(no_bytes,&in_ptr,output_ptr,*unused)
- == ASN1_ERROR)
- return ASN1_ERROR;
- ret = no_bytes;
- }
- else if (desired_no < (no_bytes * 8)) {
-/* printf("insert_bits_as_bits 1\n\r"); */
- if(insert_octets_unaligned(desired_no/8,&in_ptr,output_ptr,*unused)
- == ASN1_ERROR)
- return ASN1_ERROR;
-/* printf("insert_bits_as_bits 2\n\r"); */
- val = *++in_ptr;
-/* printf("val = %d\n\r",(int)val); */
- no_bits = desired_no % 8;
-/* printf("no_bits = %d\n\r",no_bits); */
- insert_most_sign_bits(no_bits,val,output_ptr,unused);
- ret = CEIL(desired_no,8);
- }
- else {
- if(insert_octets_unaligned(no_bytes,&in_ptr,output_ptr,*unused)
- == ASN1_ERROR)
- return ASN1_ERROR;
- ret2 = pad_bits(desired_no - (no_bytes * 8),output_ptr,unused);
-/* printf("ret2 = %d\n\r",ret2); */
- ret = CEIL(desired_no,8);
-/* printf("ret = %d\n\r",ret); */
- }
-/* printf("*unused = %d\n\r",*unused); */
- *input_ptr = in_ptr;
- return ret;
-}
-
-
-/* insert_octets_as_bits_exact_len */
-int
-insert_octets_as_bits_exact_len(int desired_len,
- int in_buff_len,
- unsigned char **in_ptr,
- unsigned char **ptr,
- int *unused)
-{
- int ret = 0;
- int ret2 = 0;
-
- if (desired_len == in_buff_len) {
- if ((ret = insert_octets_as_bits(in_buff_len,in_ptr,ptr,unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- }
- else if(desired_len > in_buff_len) {
- if((ret = insert_octets_as_bits(in_buff_len,in_ptr,ptr,unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- /* now pad with zero bits */
-/* printf("~npad_bits: called with %d bits padding~n~n~r",desired_len - in_buff_len); */
- if ((ret2=pad_bits(desired_len - in_buff_len,ptr,unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- }
- else {/* desired_len < no_bits */
- if ((ret=insert_octets_as_bits(desired_len,in_ptr,ptr,unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- /* now remove no_bits - desired_len bytes from in buffer */
- *in_ptr += (in_buff_len - desired_len);
- }
- return (ret+ret2);
-}
-
-
-
-/* insert_octets_as_bits takes no_bytes bytes from the buffer that input_ptr
- points at and inserts the least significant bit of it in the buffer that
- output_ptr points at. Each byte in the input buffer must be 1 or 0
- otherwise the function returns ASN1_ERROR. The output buffer is concatenated
- without alignment.
- */
-int insert_octets_as_bits(int no_bytes,
- unsigned char **input_ptr,
- unsigned char **output_ptr,
- int *unused)
-{
- unsigned char *in_ptr = *input_ptr;
- unsigned char *ptr = *output_ptr;
- int used_bits = 8 - *unused;
-
- while (no_bytes > 0) {
- switch (*++in_ptr) {
- case 0:
- if(*unused == 1){
- *unused = 8;
- *++ptr = 0x00;
- } else
- (*unused)--;
- break;
- case 1:
- if(*unused == 1){
- *ptr = *ptr | 1;
- *unused = 8;
- *++ptr = 0x00;
- } else {
- *ptr = *ptr | (1 << (*unused - 1));
- (*unused)--;
- }
- break;
- default:
- return ASN1_ERROR;
- }
- no_bytes--;
- }
- *input_ptr = in_ptr;
- *output_ptr = ptr;
- return ((used_bits+no_bytes) / 8); /*return number of new bytes
- in completed buffer */
-}
-
-/* insert_octets inserts bytes from the input buffer, *input_ptr,
- into the output buffer, *output_ptr. Before the first byte is
- inserted the input buffer is aligned.
- */
-int insert_octets(int no_bytes,
- unsigned char **input_ptr,
- unsigned char **output_ptr,
- int *unused)
-{
- unsigned char *in_ptr = *input_ptr;
- unsigned char *ptr = *output_ptr;
- int ret = 0;
-
- if (*unused != 8) {/* must align before octets are added */
- *++ptr = 0x00;
- ret++;
- *unused = 8;
- }
- while(no_bytes > 0) {
- *ptr = *(++in_ptr);
- *++ptr = 0x00;
- /* *unused = *unused - 1; */
- no_bytes--;
- }
- *input_ptr = in_ptr;
- *output_ptr = ptr;
- return (ret + no_bytes);
-}
-
-/* insert_octets_unaligned inserts bytes from the input buffer, *input_ptr,
- into the output buffer, *output_ptr.No alignment is done.
- */
-int insert_octets_unaligned(int no_bytes,
- unsigned char **input_ptr,
- unsigned char **output_ptr,
- int unused)
-{
- unsigned char *in_ptr = *input_ptr;
- unsigned char *ptr = *output_ptr;
- int n = no_bytes;
- unsigned char val;
-
- while (n > 0) {
- if (unused == 8) {
- *ptr = *++in_ptr;
- *++ptr = 0x00;
- }else {
- val = *++in_ptr;
- *ptr = *ptr | val >> (8 - unused);
- *++ptr = 0x00;
- *ptr = val << unused;
- }
- n--;
- }
- *input_ptr = in_ptr;
- *output_ptr = ptr;
- return no_bytes;
-}
-
-
-int insert_octets_except_unused(int no_bytes,
- unsigned char **input_ptr,
- unsigned char **output_ptr,
- int *unused,
- int in_unused)
-{
- unsigned char *in_ptr = *input_ptr;
- unsigned char *ptr = *output_ptr;
- int val, no_bits;
- int ret = 0;
-
- if (in_unused == 0){
-/* printf("%d: insert_octets_except_unused: if\n\r",__LINE__); */
- if ((ret = insert_octets_unaligned(no_bytes,&in_ptr,&ptr,
- *unused)) == ASN1_ERROR)
- return ASN1_ERROR;
- }
- else {
-/* printf("%d: insert_octets_except_unused: else\n\r",__LINE__); */
- if ((ret=insert_octets_unaligned(no_bytes - 1,&in_ptr,&ptr,*unused)) != ASN1_ERROR) {
- val = (int) *(++in_ptr);
- no_bits = 8 - in_unused;
- /* no_bits is always less than *unused since the buffer is
- octet aligned after insert:octets call, so the following
- if clasuse is obsolete I think */
- if(no_bits < *unused){
- *ptr = *ptr | (val >> (8 - *unused));
- *unused = *unused - no_bits;
- } else if (no_bits == *unused) {
- *ptr = *ptr | (val >> (8 - *unused));
- *++ptr = 0x00;
- ret++;
- *unused = 8;
- } else {
- *ptr = *ptr | (val >> (8 - *unused));
- *++ptr = 0x00;
- ret++;
- *ptr = *ptr | (val << *unused);
- *unused = 8 - (no_bits - *unused);
- }
- } else
- return ASN1_ERROR;
- }
- *input_ptr = in_ptr;
- *output_ptr = ptr;
-/* printf("%d: insert_octets_except_unused: ret=%d\n\r",__LINE__,ret); */
- return ret;
-}
-
-
-
-/*
- *
- * This section defines functionality for the partial decode of a
- * BER encoded message
- *
- */
-
-/*
- * int decode(ErlDrvBinary **drv_binary,unsigned char *decode_buf,
- * unsigned char *in_buf, int in_buf_len)
- * drv_binary is a pointer to a pointer to an allocated driver binary.
- * in_buf is a pointer into the buffer of incoming bytes.
- * in_buf_len is the length of the incoming buffer.
- * The function reads the bytes in the incoming buffer and structures
- * it in a nested way as Erlang terms. The buffer contains data in the
- * order tag - length - value. Tag, length and value has the following
- * format:
- * A tag is normally one byte but may be of any length, if the tag number
- * is greater than 30. +----------+
- * |CL|C|NNNNN|
- * +----------+
- * If NNNNN is 31 then will the 7 l.s.b of each of the following tag number
- * bytes contain the tag number. Each tag number byte that is not the last one
- * has the m.s.b. set to 1.
- * The length can be short definite length (sdl), long definite length (ldl)
- * or indefinite length (il).
- * sdl: +---------+ the L bits is the length
- * |0|LLLLLLL|
- * +---------+
- * ldl: +---------+ +---------+ +---------+ +-----------+
- * |1|lllllll| |first len| | | |the Nth len|
- * +---------+ +---------+ +---------+ ... +-----------+
- * The first byte tells how many len octets will follow, max 127
- * il: +---------+ +----------------------+ +--------+ +--------+
- * |1|0000000| |content octets (Value)| |00000000| |00000000|
- * +---------+ +----------------------+ +--------+ +--------+
- * The value octets are preceded by one octet and followed by two
- * exactly as above. The value must be some tag-length-value encoding.
- *
- * The function returns a value in Erlnag term format:
- * {{TagNo,Value},Rest}
- * TagNo is an integer ((CL bsl 16) + tag number) which limits the tag number
- * to 65535.
- * Value is a binary if the C bit in tag was unset, otherwise (if tag was
- * constructed) Value is a list, List.
- * List is like: [{TagNo,Value},{TagNo,Value},...]
- * Rest is a binary, i.e. the undecoded part of the buffer. Most often Rest
- * is the empty binary.
- * If some error occured during the decoding of the in_buf an error is returned.
- */
-int decode_begin(ErlDrvBinary **drv_binary,unsigned char *in_buf, int in_buf_len, unsigned int *err_pos)
-{
- int maybe_ret;
- char *decode_buf = (*drv_binary)->orig_bytes;
- int ei_index = 0;
- int ib_index = 0;
- /* ei_index is the index used by the ei functions to encode an
- Erlang term into the buffer decode_buf */
- /* ib_index is the index were to read the next byte from in_buf */
-
-
-#ifdef ASN1_DEBUG
- printf("decode_begin1: ei_index=%d, ib_index=%d\n\r",ei_index,ib_index);
-#endif
- /* the first byte must be a "version magic" */
- if(ei_encode_version(decode_buf,&ei_index) == ASN1_ERROR)
- return ASN1_ERROR; /* 1 byte */
-#ifdef ASN1_DEBUG
- printf("decode_begin2: ei_index=%d, ib_index=%d\n\r",ei_index,ib_index);
-#endif
- if (ei_encode_tuple_header(decode_buf,&ei_index,2) == ASN1_ERROR)
- return ASN1_ERROR; /* 2 bytes */
-#ifdef ASN1_DEBUG
- printf("decode_begin3: ei_index=%d, ib_index=%d\n\r",ei_index,ib_index);
-#endif
- if((maybe_ret=decode(drv_binary,&ei_index,in_buf,&ib_index,in_buf_len)) <= ASN1_ERROR)
- {
- *err_pos = ib_index;
-#ifdef ASN1_DEBUG
- printf("err_pos=%d,ib_index=%d\r\n",*err_pos,ib_index);
-#endif
- return maybe_ret;
- };
-
- decode_buf = (*drv_binary)->orig_bytes; /* maybe a realloc during decode_value */
-#ifdef ASN1_DEBUG
- printf("decode_begin4: in_buf_len=%d, ei_index=%d, ib_index=%d\n\r",
- in_buf_len,ei_index,ib_index);
-#endif
- /* "{{TagNo,Value},Rest}" */
- if (ei_encode_binary(decode_buf,&ei_index,&(in_buf[ib_index]),in_buf_len-ib_index)
- == ASN1_ERROR) /* at least 5 bytes */
- return ASN1_ERROR;
-#ifdef ASN1_DEBUG
- printf("decode_begin5: ei_index=%d, ib_index=%d\n\r",ei_index,ib_index);
-#endif
- return ei_index;
-}
-
-int decode(ErlDrvBinary **drv_binary,int *ei_index,unsigned char *in_buf,
- int *ib_index, int in_buf_len)
-{
- int maybe_ret;
- char *decode_buf = (*drv_binary)->orig_bytes;
- int form;
-#ifdef ASN1_DEBUG
- printf("decode 1\n\r");
-#endif
- if (((*drv_binary)->orig_size - *ei_index) < 19) {/* minimum amount of bytes */
- /* allocate more memory */
- if (realloc_decode_buf(drv_binary,(*drv_binary)->orig_size * 2) ==
- ASN1_ERROR)
- return ASN1_ERROR;
- decode_buf = (*drv_binary)->orig_bytes;
- }
-/* printf("decode 2\n\r"); */
- /* "{" */
- if (ei_encode_tuple_header(decode_buf,ei_index,2) == ASN1_ERROR)
- return ASN1_ERROR; /* 2 bytes */
-#ifdef ASN1_DEBUG
- printf("decode 3:orig_size=%d, ei_index=%d, ib_index=%d\n\r",(*drv_binary)->orig_size,*ei_index,*ib_index);
-#endif
-
- /*buffer must hold at least two bytes*/
- if ((*ib_index +2) > in_buf_len)
- return ASN1_VALUE_ERROR;
- /* "{{TagNo," */
- if ((form = decode_tag(decode_buf,ei_index,in_buf,in_buf_len,ib_index)) <= ASN1_ERROR)
- return form; /* 5 bytes */
-#ifdef ASN1_DEBUG
- printf("i_i=%d,in_buf_len=%d\r\n",*ei_index,in_buf_len);
-#endif
- if (*ib_index >= in_buf_len){
- return ASN1_TAG_ERROR;
- }
-#ifdef ASN1_DEBUG
- printf("decode 5 ib_index=%d\n\r",*ib_index);
-#endif
- /* buffer must hold at least one byte (0 as length and nothing as
- value) */
- /* "{{TagNo,Value}," */
- if ((maybe_ret=decode_value(ei_index,in_buf,ib_index,drv_binary,form,
- in_buf_len)) <= ASN1_ERROR)
- return maybe_ret; /* at least 5 bytes */
-#ifdef ASN1_DEBUG
- printf("decode 7\n\r");
-#endif
- return *ei_index;
-}
-
-/*
- * decode_tag decodes the BER encoded tag in in_buf and puts it in the
- * decode_buf encoded by the Erlang extern format as an Erlang term.
- */
-int decode_tag(char *decode_buf,int *db_index,unsigned char *in_buf,
- int in_buf_len, int *ib_index)
-{
- int tag_no, tmp_tag, form;
-
-
- /* first get the class of tag and bit shift left 16*/
- tag_no = ((MASK(in_buf[*ib_index],ASN1_CLASS)) << 10);
-
- form = (MASK(in_buf[*ib_index],ASN1_FORM));
-#ifdef ASN1_DEBUG
- printf("decode_tag0:ii=%d, tag_no=%d, form=%d.\r\n",
- *ib_index,tag_no,form);
-#endif
-
- /* then get the tag number */
- if((tmp_tag = (int) INVMASK(in_buf[*ib_index],ASN1_CLASSFORM)) < 31) {
- ei_encode_ulong(decode_buf,db_index,tag_no+tmp_tag); /* usual case */
- (*ib_index)++;
-#ifdef ASN1_DEBUG
- printf("decode_tag1:ii=%d.\r\n",*ib_index);
-#endif
- }
- else
- {
- int n = 0; /* n is used to check that the 64K limit is not
- exceeded*/
-#ifdef ASN1_DEBUG
- printf("decode_tag1:ii=%d, in_buf_len=%d.\r\n",*ib_index,in_buf_len);
-#endif
-
- /* should check that at least three bytes are left in
- in-buffer,at least two tag byte and at least one length byte */
- if ((*ib_index +3) > in_buf_len)
- return ASN1_VALUE_ERROR;
- (*ib_index)++;
-#ifdef ASN1_DEBUG
- printf("decode_tag2:ii=%d.\r\n",*ib_index);
-#endif
- /* The tag is in the following bytes in in_buf as
- 1ttttttt 1ttttttt ... 0ttttttt, where the t-bits
- is the tag number*/
- /* In practice is the tag size limited to 64K, i.e. 16 bits. If
- the tag is greater then 64K return an error */
- while (((tmp_tag = (int)in_buf[*ib_index]) >= 128) && n < 2){
- /* m.s.b. = 1 */
- tag_no = tag_no + (MASK(tmp_tag,ASN1_LONG_TAG) << 7);
- (*ib_index)++;
-#ifdef ASN1_DEBUG
- printf("decode_tag3:ii=%d.\r\n",*ib_index);
-#endif
- n++;
- };
- if ((n==2) && in_buf[*ib_index] > 3)
- return ASN1_TAG_ERROR; /* tag number > 64K */
- tag_no = tag_no + in_buf[*ib_index];
- (*ib_index)++;
-#ifdef ASN1_DEBUG
- printf("decode_tag4:ii=%d.\r\n",*ib_index);
-#endif
- ei_encode_ulong(decode_buf,db_index,tag_no);
- }
- return form;
-}
-
-
-/*
- * decode_value decodes the BER encoded length and value fields in the
- * in_buf and puts the value part in the decode_buf as an Erlang term
- * encoded by the Erlang extern format
- */
-int decode_value(int *ei_index,unsigned char *in_buf,
- int *ib_index,ErlDrvBinary **drv_binary,int form,
- int in_buf_len)
-{
- int maybe_ret;
- char *decode_buf = (*drv_binary)->orig_bytes;
- int len, lenoflen;
- int indef = 0;
-
-#ifdef ASN1_DEBUG
- printf("decode_value1:ib_index=%d\n\r",*ib_index);
-#endif
- if (((in_buf[*ib_index]) & 0x80) == ASN1_SHORT_DEFINITE_LENGTH) {
- len = in_buf[*ib_index];
- if (len > (in_buf_len - (*ib_index + 1)))
- return ASN1_LEN_ERROR;
- }
- else if (in_buf[*ib_index] == ASN1_INDEFINITE_LENGTH)
- indef = 1;
- else /* long definite length */ {
- lenoflen = (in_buf[*ib_index] & 0x7f); /*length of length */
-#ifdef ASN1_DEBUG
- printf("decode_value,lenoflen:%d\r\n",lenoflen);
-#endif
- len = 0;
- while (lenoflen-- && (*ib_index <= in_buf_len)) {
- (*ib_index)++;
-#ifdef ASN1_DEBUG
- printf("decode_value1:ii=%d.\r\n",*ib_index);
-#endif
- len = (len << 8) + in_buf[*ib_index];
- }
- if (len > (in_buf_len - (*ib_index + 1)))
- return ASN1_LEN_ERROR;
- }
- (*ib_index)++;
-#ifdef ASN1_DEBUG
- printf("decode_value2:ii=%d.\r\n",*ib_index);
-#endif
- if (indef == 1)
- { /* in this case it is desireably to check that indefinite length
- end bytes exist in inbuffer */
- while (!(in_buf[*ib_index]==0 && in_buf[*ib_index + 1]==0)) {
-#ifdef ASN1_DEBUG
- printf("decode_value while:ib_index=%d in_buf_len=%d\n\r",
- *ib_index,in_buf_len);
-#endif
- if(*ib_index >= in_buf_len)
- return ASN1_INDEF_LEN_ERROR;
- ei_encode_list_header(decode_buf,ei_index,1); /* 5 bytes */
- if((maybe_ret=decode(drv_binary,ei_index,in_buf,
- ib_index,in_buf_len)) <= ASN1_ERROR)
- return maybe_ret;
- decode_buf = (*drv_binary)->orig_bytes;
- }
- (*ib_index) += 2; /* skip the indefinite length end bytes */
-#ifdef ASN1_DEBUG
- printf("decode_value3:ii=%d.\r\n",*ib_index);
-#endif
- ei_encode_empty_list(decode_buf,ei_index); /* 1 byte */
- }
- else if (form == ASN1_CONSTRUCTED)
- {
- int end_index = *ib_index + len;
- if(end_index > in_buf_len)
- return ASN1_LEN_ERROR;
- while (*ib_index < end_index) {
-
-#ifdef ASN1_DEBUG
- printf("decode_value3:*ib_index=%d, end_index=%d\n\r",*ib_index,end_index);
-#endif
- ei_encode_list_header(decode_buf,ei_index,1); /* 5 bytes */
- if((maybe_ret=decode(drv_binary,ei_index,in_buf,
- ib_index,in_buf_len))<=ASN1_ERROR)
- return maybe_ret;
- decode_buf = (*drv_binary)->orig_bytes;
- }
- ei_encode_empty_list(decode_buf,ei_index); /* 1 byte */
- }
- else
- {
- if (((*drv_binary)->orig_size - *ei_index) < 10+len) { /* 5+len for the binary*/
- if (realloc_decode_buf(drv_binary,(*drv_binary)->orig_size * 2) ==
- ASN1_ERROR)
- return ASN1_ERROR;
- decode_buf = (*drv_binary)->orig_bytes;
- }
- if((*ib_index + len) > in_buf_len)
- return ASN1_LEN_ERROR;
- ei_encode_binary(decode_buf,ei_index,&in_buf[*ib_index],len);
- *ib_index = *ib_index + len;
-#ifdef ASN1_DEBUG
- printf("decode_value4:ii=%d.\r\n",*ib_index);
-#endif
- }
- return ASN1_OK;
-}
-
-int realloc_decode_buf(ErlDrvBinary **drv_binary,int amount) {
- ErlDrvBinary *tmp_bin;
-
- if ((tmp_bin=driver_realloc_binary(*drv_binary,amount)) == NULL)
- return ASN1_ERROR;
- *drv_binary = tmp_bin;
- return ASN1_OK;
-}
-
-
-
-/*
- * int decode_partial(drv_binary,in_buf,in_buf_len)
- */
-/*
- * The in_buf contains two parts: first information about which value
- * will be decoded, as a sequence of tags and tag codes, then the
- * encoded BER value. First of all comes a length field that tells how
- * many following bytes contains the sequence of tags. Then starts the
- * BER encoded message. The tag sequence length field is a single
- * byte. The sequence of tags/tag codes may be one of the codes
- * ASN1_SKIPPED, ASN1_CHOOSEN and a tag or ASN1_OPTIONAL and a
- * tag. ASN1_SKIPPED means that the following tag is mandatory and is
- * skipped. ASN1_CHOOSEN means that the value of this tag shall, if
- * this was the last tag in tag sequence, be returned or be searched
- * in for the next tag. ASN1_OPTIONAL means that this tag shall be
- * skipped but it may be missing. Each tag in the tag sequence
- * correspond to a tag in the BER encoded message. If the decode
- * arives to a position where there is no matching tag, an error is
- * returned (if it wasn't the last tag and it was OPTIONAL). After the
- * right value has been detected it is returned in the out_buf.
- *
- */
-int decode_partial(ErlDrvBinary **drv_binary,unsigned char *in_buf, int in_buf_len)
-{
- char *out_buf = (*drv_binary)->orig_bytes;
- int tag_index_val = 1;
- int msg_index_val;
- int *msg_index, *tag_index, tmp_index;
- int tag_seq_length;
- int wanted_tag, next_tag;
- int buf_end_index = in_buf_len;
- int ret = 0, length, old_index;
-
- tag_index = &tag_index_val;
- tag_seq_length = in_buf[0];
- msg_index = &msg_index_val;
- *msg_index = tag_seq_length + 1;
-
-
-/* printf("decode_partial 1: in_buf_len=%d, tag_index=%d, msg_index=%d\r\n,tag_seq_length=%d\r\n",in_buf_len,*tag_index,*msg_index,tag_seq_length); */
- while(*tag_index < tag_seq_length) {
- switch(in_buf[*tag_index]) {
- case ASN1_SKIPPED:
-/* printf("decode_partial ASN1_SKIPPED: in_buf[*msg_index]=%d\r\n",in_buf[*msg_index]); */
- (*tag_index)++;
-/* printf("decode_partial ASN1_SKIPPED 2: *msg_index=%d\r\n",*msg_index); */
- skip_tag(in_buf,msg_index,buf_end_index);
-/* printf("decode_partial ASN1_SKIPPED 3: *msg_index=%d\r\n",*msg_index); */
- skip_length_and_value(in_buf,msg_index,buf_end_index);
-/* printf("decode_partial ASN1_SKIPPED 4: *msg_index=%d\r\n",*msg_index); */
- break;
- case ASN1_OPTIONAL:
- (*tag_index)++;
-/* printf("decode_partial ASN1_OPTIONAL: in_buf[*tag_index]=%d\r\n",in_buf[*tag_index]); */
- wanted_tag = in_buf[*tag_index];
- (*tag_index)++;
- tmp_index = *msg_index;
- next_tag = get_tag(in_buf,msg_index,buf_end_index);
- if (wanted_tag != next_tag) {
- *msg_index = tmp_index;
- } else
- skip_length_and_value(in_buf,msg_index,buf_end_index);
- break;
- case ASN1_CHOOSEN:
-/* printf("decode_partial ASN1_CHOOSEN: in_buf[*msg_index]=%d, *msg_index=%d\r\n",in_buf[*msg_index],*msg_index); */
- (*tag_index)++;
- wanted_tag = in_buf[*tag_index];
- (*tag_index)++;
- old_index = *msg_index;
-/* printf("decode_partial ASN1_CHOOSEN 2: *msg_index=%d\r\n",*msg_index); */
- next_tag = get_tag(in_buf,msg_index,buf_end_index);
-/* printf("decode_partial ASN1_CHOOSEN 3: *msg_index=%d\r\n,wanted_tag=%d, next_tag=%d\r\n",*msg_index,wanted_tag,next_tag); */
- if (wanted_tag != next_tag)
- return ASN1_NOVALUE; /* an empty binary will be returned to Erlang */
- if (*tag_index == (tag_seq_length + 1)) {
- /* get the value and return*/
- if((ret = get_value(out_buf,in_buf,msg_index,buf_end_index)) <= ASN1_ERROR)
- return ASN1_ERROR;
- return ret;
- }
- else {
- /* calculate the length of the sub buffer and let *msg_index
- be at the value part of this BER encoded type*/
- int indef;
- indef = 0;
- length = get_length(in_buf,msg_index,&indef,buf_end_index);
-/* printf("decode_partial ASN1_CHOOSEN 4: length=%d, *msg_index=%d\r\n",length,*msg_index); */
- if ((length == 0) && (indef == 1)) {
- /* indefinite length of value */
- old_index = *msg_index;
- length = skip_length_and_value(in_buf,msg_index,buf_end_index);
- *msg_index = old_index;
- buf_end_index = *msg_index + length - 2;
- /* remove two bytes due to indefinete length end zeros */
- } else
- buf_end_index = (*msg_index + length);
- }
- break;
- default:
- return ASN1_ERROR;
- }
- }
- return ASN1_ERROR;
-}
-
-
-/*
- * int skip_tag(unsigned char *in_buf,int *index,int buf_len)
- * steps past the BER encoded tag in in_buf and updates *index.
- * Returns the number of skipped bytes.
- */
-int skip_tag(unsigned char *in_buf,int *index,int buf_len)
-{
- int start_index = *index;
- if ((MASK(in_buf[*index],ASN1_TAG)) == 31){
- do {
- (*index)++;
- if (*index >= buf_len)
- return ASN1_ERROR;
- }
- while(in_buf[*index] >=128);
- }
- (*index)++;
- return (*index - start_index);
-}
-
-
-/*
- * int skip_length_and_value(unsigned char *in_buf,int *index,int buf_len)
- * steps past the BER encoded length and value in in_buf and updates *index.
- * returns the length if the skipped "length value".
- * Returns the number of skipped bytes.
- */
-int skip_length_and_value(unsigned char *in_buf,int *index,int buf_len)
-{
- long len;
- int indef = 0, lenoflen;
- int start_index = *index;
-
- if ((MASK(in_buf[*index],0x80)) == ASN1_SHORT_DEFINITE_LENGTH){
- len = in_buf[*index];
- if (len > (buf_len - (*index + 1)))
- return ASN1_LEN_ERROR;
- } else if (in_buf[*index] == ASN1_INDEFINITE_LENGTH)
- indef = 1;
- else /* long definite length */ {
- lenoflen = (in_buf[*index] & 0x7f); /*length of length */
- len = 0;
- while (lenoflen--) {
- (*index)++;
- len = (len << 8) + in_buf[*index];
- }
- if (len > (buf_len - (*index + 1)))
- return ASN1_LEN_ERROR;
- }
- (*index)++;
- if (indef == 1)
- {
- while(!(in_buf[*index]==0 && in_buf[*index + 1]==0)) {
- skip_tag(in_buf,index,buf_len);
- skip_length_and_value(in_buf,index,buf_len);
- }
- (*index) += 2;
- }
- else
- (*index) += len;
- return (*index - start_index);
-}
-
-/* int get_tag(unsigned char *in_buf,int *index)
- *
- * assumes next byte/bytes in in_buf is an encoded BER tag. A tag
- * number has theoretically no upper limit in size. Here the tag
- * number is assumed to be less than 64K. Returns an integer value
- * on the format:
- * xxxxxxxx xxxxxxcc tttttttt tttttttt
- * the x-bits are 0 (insignificant)
- * the c-bits are the class of the tag
- * the t-bits are the tag number. This implies that the tag number
- * is limited to 64K-1
- *
- */
-int get_tag(unsigned char *in_buf,int *index,int buf_len)
-{
- int tag_no = 0,tmp_tag = 0;
-
- tag_no = (MASK(in_buf[*index],ASN1_CLASSFORM));
- if ((MASK(in_buf[*index],ASN1_TAG)) == ASN1_TAG) {
- /* long form of tag */
- do {
- (*index)++;
- if (*index >= buf_len)
- return ASN1_TAG_ERROR;
- tmp_tag = tmp_tag << 7;
- tmp_tag += (MASK(in_buf[*index],ASN1_LONG_TAG));
- } while (in_buf[*index] >= 128);
- (*index)++;
- tag_no = tag_no + tmp_tag;
- } else {
- tag_no += (MASK(in_buf[*index],ASN1_TAG));
- (*index)++;
- }
- if (*index >= buf_len)
- return ASN1_TAG_ERROR;
- return tag_no;
-}
-
-
-/*
- * int get_value(char *out_buf,unsigned char *in_buf,
- * int *msg_index,int in_buf_len)
- */
-/* assumes next byte/bytes in in_buf is an encoded BER value preceeded by a BER encoded length. Puts value in out_buf.
- */
-int get_value(char *out_buf,
- unsigned char *in_buf,
- int *msg_index,
- int in_buf_len)
-{
- int len, lenoflen, indef=0, skip_len;
- int ret=0;
- int start_index;
-
-/* printf("get_value 1\n\r"); */
- if (in_buf[*msg_index] < 0x80){ /* short definite length */
- len = in_buf[*msg_index];
-/* printf("short definite length\r\n"); */
- } else if (in_buf[*msg_index] > 0x80) { /* long definite length */
- lenoflen = (in_buf[*msg_index] & 0x7f); /*length of length */
- len = 0;
- while (lenoflen--) {
- (*msg_index)++;
- len = (len << 8) + in_buf[*msg_index];
- }
- if (len > (in_buf_len - (*msg_index + 1)))
- return ASN1_LEN_ERROR;
- } else
- indef = 1;
- (*msg_index)++;
-/* printf("get_value 2: len = %d, *msg_index = %d\r\n",len,*msg_index); */
- if (indef == 1) {
- while(!(in_buf[*msg_index]==0 && in_buf[*msg_index + 1]==0)) {
- start_index = *msg_index;
- skip_len = skip_tag(in_buf,msg_index,in_buf_len);
-/* printf("get_value 3: skip_len=%d,start_index=%d,*msg_index=%d\n\r", */
-/* skip_len,start_index,*msg_index); */
- memcpy(&out_buf[ret],&in_buf[start_index],skip_len);
- ret += skip_len;
- start_index = *msg_index;
- skip_len = skip_length_and_value(in_buf,msg_index,in_buf_len);
-/* printf("get_value 4: skip_len=%d,start_index=%d,*msg_index=%d\n\r", */
-/* skip_len,start_index,*msg_index); */
- memcpy(&out_buf[ret],&in_buf[start_index],skip_len);
- ret += skip_len;
- }
- return ret;
- }
- else
- memcpy(&out_buf[ret],&in_buf[*msg_index],len);
- return len;
-}
-
-
-/*
- * int get_length(unsigned char *in_buf,int *msg_index)
- * assumes next byte/bytes contain a BER encoded length field,
- * which is decoded. The value of the length is returned. If it
- * is an indefinite length the *indef is set to one.
- */
-int get_length(unsigned char *in_buf,int *msg_index,
- int *indef,int in_buf_len)
-{
- int len=0, lenoflen;
-
- if (in_buf[*msg_index] < 0x80) /* short definite length */
- len = in_buf[*msg_index];
- else if (in_buf[*msg_index] > 0x80) { /* long definite length */
- lenoflen = (in_buf[*msg_index] & 0x7f); /*length of length */
- len = 0;
- while (lenoflen--) {
- (*msg_index)++;
- len = (len << 8) + in_buf[*msg_index];
- }
- if (len > (in_buf_len - (*msg_index + 1)))
- return ASN1_LEN_ERROR;
- } else
- *indef = 1;
- (*msg_index)++;
- return len;
-}
diff --git a/lib/asn1/c_src/asn1_erl_nif.c b/lib/asn1/c_src/asn1_erl_nif.c
new file mode 100644
index 0000000000..9c9f83bc2a
--- /dev/null
+++ b/lib/asn1/c_src/asn1_erl_nif.c
@@ -0,0 +1,1305 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2002-2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "erl_nif.h"
+
+/* #define ASN1_DEBUG 1 */
+
+#define ASN1_OK 0
+#define ASN1_ERROR -1
+#define ASN1_COMPL_ERROR 1
+#define ASN1_MEMORY_ERROR 0
+#define ASN1_DECODE_ERROR 2
+#define ASN1_TAG_ERROR -3
+#define ASN1_LEN_ERROR -4
+#define ASN1_INDEF_LEN_ERROR -5
+#define ASN1_VALUE_ERROR -6
+
+#define ASN1_CLASS 0xc0
+#define ASN1_FORM 0x20
+#define ASN1_CLASSFORM (ASN1_CLASS | ASN1_FORM)
+#define ASN1_TAG 0x1f
+#define ASN1_LONG_TAG 0x7f
+
+#define ASN1_INDEFINITE_LENGTH 0x80
+#define ASN1_SHORT_DEFINITE_LENGTH 0
+
+#define ASN1_PRIMITIVE 0
+#define ASN1_CONSTRUCTED 0x20
+
+#define ASN1_NOVALUE 0
+
+#define ASN1_SKIPPED 0
+#define ASN1_OPTIONAL 1
+#define ASN1_CHOOSEN 2
+
+#define CEIL(X,Y) ((X-1) / Y + 1)
+
+#define INVMASK(X,M) (X & (M ^ 0xff))
+#define MASK(X,M) (X & M)
+
+/* PER COMPLETE */
+int per_complete(ErlNifBinary *, unsigned char *, int);
+
+int per_insert_octets(int, unsigned char **, unsigned char **, int *);
+
+int per_insert_octets_except_unused(int, unsigned char **, unsigned char **,
+ int *, int);
+
+int per_insert_octets_as_bits_exact_len(int, int, unsigned char **,
+ unsigned char **, int *);
+
+int per_insert_octets_as_bits(int, unsigned char **, unsigned char **, int *);
+
+int per_pad_bits(int, unsigned char **, int *);
+
+int per_insert_least_sign_bits(int, unsigned char, unsigned char **, int *);
+
+int per_insert_most_sign_bits(int, unsigned char, unsigned char **, int *);
+
+int per_insert_bits_as_bits(int, int, unsigned char **, unsigned char **, int *);
+
+int per_insert_octets_unaligned(int, unsigned char **, unsigned char **, int);
+
+int per_realloc_memory(ErlNifBinary *, int, unsigned char **);
+
+/* BER DECODE */
+int ber_decode_begin(ErlNifEnv *, ERL_NIF_TERM *, unsigned char *, int,
+ unsigned int *);
+
+int ber_decode(ErlNifEnv *, ERL_NIF_TERM *, unsigned char *, int *, int);
+
+int ber_decode_tag(ErlNifEnv *, ERL_NIF_TERM *, unsigned char *, int, int *);
+
+int ber_decode_value(ErlNifEnv*, ERL_NIF_TERM *, unsigned char *, int *, int,
+ int);
+
+/* BER ENCODE */
+typedef struct ber_encode_mem_chunk mem_chunk_t;
+
+int ber_encode(ErlNifEnv *, ERL_NIF_TERM , mem_chunk_t **, unsigned int *);
+
+void ber_free_chunks(mem_chunk_t *chunk);
+mem_chunk_t *ber_new_chunk(unsigned int length);
+int ber_check_memory(mem_chunk_t **curr, unsigned int needed);
+
+int ber_encode_tag(ErlNifEnv *, ERL_NIF_TERM , unsigned int ,
+ mem_chunk_t **, unsigned int *);
+
+int ber_encode_length(size_t , mem_chunk_t **, unsigned int *);
+
+/*
+ *
+ * This section defines functionality for the complete encode of a
+ * PER encoded message
+ *
+ */
+
+int per_complete(ErlNifBinary *out_binary, unsigned char *in_buf,
+ int in_buf_len) {
+ int counter = in_buf_len;
+ /* counter keeps track of number of bytes left in the
+ input buffer */
+
+ int buf_space = in_buf_len;
+ /* This is the amount of allocated space left of the out_binary. It
+ is possible when padding is applied that more space is needed than
+ was originally allocated. */
+
+ int buf_size = in_buf_len;
+ /* Size of the buffer. May become reallocated and thus other than
+ in_buf_len */
+
+ unsigned char *in_ptr, *ptr;
+ /* in_ptr points at the next byte in in_buf to be moved to
+ complete_buf.
+ ptr points into the new completed buffer, complete_buf, at the
+ position of the next byte that will be set */
+ int unused = 8;
+ /* unused = [1,...,8] indicates how many of the rigthmost bits of
+ the byte that ptr points at that are unassigned */
+
+ int no_bits, no_bytes, in_unused, desired_len, ret, saved_mem, needed,
+ pad_bits;
+
+ unsigned char val;
+
+ in_ptr = in_buf;
+ ptr = out_binary->data;
+ *ptr = 0x00;
+ while (counter > 0) {
+ counter--;
+ switch (*in_ptr) {
+ case 0:
+ /* just one zero-bit should be added to the buffer */
+ if (unused == 1) {
+ unused = 8;
+ *++ptr = 0x00;
+ buf_space--;
+ } else
+ unused--;
+ break;
+
+ case 1:
+ /* one one-bit should be added to the buffer */
+ if (unused == 1) {
+ *ptr = *ptr | 1;
+ unused = 8;
+ *++ptr = 0x00;
+ buf_space--;
+ } else {
+ *ptr = *ptr | (1 << (unused - 1));
+ unused--;
+ }
+ break;
+
+ case 2:
+ /* align buffer to end of byte */
+ if (unused != 8) {
+ *++ptr = 0x00;
+ buf_space--;
+ unused = 8;
+ }
+ break;
+
+ case 10:
+ /* next byte in in_buf tells how many bits in the second next
+ byte that will be used */
+ /* The leftmost unused bits in the value byte are supposed to be
+ zero bits */
+ no_bits = (int) *(++in_ptr);
+ val = *(++in_ptr);
+ counter -= 2;
+ if ((ret = per_insert_least_sign_bits(no_bits, val, &ptr, &unused))
+ == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 20:
+ /* in this case the next value in_ptr points at holds the number
+ of following bytes that holds the value that will be inserted
+ in the completed buffer */
+ no_bytes = (int) *(++in_ptr);
+ counter -= (no_bytes + 1);
+ if ((counter < 0)
+ || (ret = per_insert_octets(no_bytes, &in_ptr, &ptr,
+ &unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 21:
+ /* in this case the next two bytes in_ptr points at holds the number
+ of following bytes that holds the value that will be inserted
+ in the completed buffer */
+ no_bytes = (int) *(++in_ptr);
+ no_bytes = no_bytes << 8;
+ no_bytes = no_bytes | (int) *(++in_ptr);
+ counter -= (2 + no_bytes);
+ if ((counter < 0)
+ || (ret = per_insert_octets(no_bytes, &in_ptr, &ptr,
+ &unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 30:
+ /* If we call the following bytes, in the buffer in_ptr points at,
+ By1,By2,Rest then Rest is the value that will be transfered to
+ the completed buffer. By1 tells how many of the rightmost bits in
+ Rest that should not be used. By2 is the length of Rest in bytes.*/
+ in_unused = (int) *(++in_ptr);
+ no_bytes = (int) *(++in_ptr);
+ counter -= (2 + no_bytes);
+ ret = -4711;
+ if ((counter < 0)
+ || (ret = per_insert_octets_except_unused(no_bytes, &in_ptr,
+ &ptr, &unused, in_unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 31:
+ /* If we call the following bytes, in the buffer in_ptr points at,
+ By1,By2,By3,Rest then Rest is the value that will be transfered to
+ the completed buffer. By1 tells how many of the rightmost bits in
+ Rest that should not be used. By2 and By3 is the length of
+ Rest in bytes.*/
+ in_unused = (int) *(++in_ptr);
+ no_bytes = (int) *(++in_ptr);
+ no_bytes = no_bytes << 8;
+ no_bytes = no_bytes | (int) *(++in_ptr);
+ counter -= (3 + no_bytes);
+ if ((counter < 0)
+ || (ret = per_insert_octets_except_unused(no_bytes, &in_ptr,
+ &ptr, &unused, in_unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 40:
+ /* This case implies that next byte,By1,(..,By1,By2,Bin,...)
+ is the desired length of the completed value, maybe needs
+ padding zero bits or removal of trailing zero bits from Bin.
+ By2 is the length of Bin and Bin is the value that will be
+ put into the completed buffer. Each byte in Bin has the value
+ 1 or 0.*/
+ desired_len = (int) *(++in_ptr);
+ no_bytes = (int) *(++in_ptr);
+
+ /* This is the algorithm for need of memory reallocation:
+ Only when padding (cases 40 - 43,45 - 47) more memory may be
+ used than allocated. Therefore one has to keep track of how
+ much of the allocated memory that has been saved, i.e. the
+ difference between the number of parsed bytes of the input buffer
+ and the number of used bytes of the output buffer.
+ If saved memory is less than needed for the padding then we
+ need more memory. */
+ saved_mem = buf_space - counter;
+ pad_bits = desired_len - no_bytes - unused;
+ needed = (pad_bits > 0) ? CEIL(pad_bits,8) : 0;
+ if (saved_mem < needed) {
+ /* Have to allocate more memory */
+ buf_size += needed;
+ buf_space += needed;
+ if (per_realloc_memory(out_binary, buf_size, &ptr) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ }
+
+ counter -= (2 + no_bytes);
+ if ((counter < 0)
+ || (ret = per_insert_octets_as_bits_exact_len(desired_len,
+ no_bytes, &in_ptr, &ptr, &unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 41:
+ /* Same as case 40 apart from By2, the length of Bin, which is in
+ two bytes*/
+ desired_len = (int) *(++in_ptr);
+ no_bytes = (int) *(++in_ptr);
+ no_bytes = no_bytes << 8;
+ no_bytes = no_bytes | (int) *(++in_ptr);
+
+ saved_mem = buf_space - counter;
+ needed = CEIL((desired_len-unused),8) - no_bytes;
+ if (saved_mem < needed) {
+ /* Have to allocate more memory */
+ buf_size += needed;
+ buf_space += needed;
+ if (per_realloc_memory(out_binary, buf_size, &ptr) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ }
+
+ counter -= (3 + no_bytes);
+ if ((counter < 0)
+ || (ret = per_insert_octets_as_bits_exact_len(desired_len,
+ no_bytes, &in_ptr, &ptr, &unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 42:
+ /* Same as case 40 apart from By1, the desired length, which is in
+ two bytes*/
+ desired_len = (int) *(++in_ptr);
+ desired_len = desired_len << 8;
+ desired_len = desired_len | (int) *(++in_ptr);
+ no_bytes = (int) *(++in_ptr);
+
+ saved_mem = buf_space - counter;
+ needed = CEIL((desired_len-unused),8) - no_bytes;
+ if (saved_mem < needed) {
+ /* Have to allocate more memory */
+ buf_size += needed;
+ buf_space += needed;
+ if (per_realloc_memory(out_binary, buf_size, &ptr) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ }
+
+ counter -= (3 + no_bytes);
+ if ((counter < 0)
+ || (ret = per_insert_octets_as_bits_exact_len(desired_len,
+ no_bytes, &in_ptr, &ptr, &unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 43:
+ /* Same as case 40 apart from By1 and By2, the desired length and
+ the length of Bin, which are in two bytes each. */
+ desired_len = (int) *(++in_ptr);
+ desired_len = desired_len << 8;
+ desired_len = desired_len | (int) *(++in_ptr);
+ no_bytes = (int) *(++in_ptr);
+ no_bytes = no_bytes << 8;
+ no_bytes = no_bytes | (int) *(++in_ptr);
+
+ saved_mem = buf_space - counter;
+ needed = CEIL((desired_len-unused),8) - no_bytes;
+ if (saved_mem < needed) {
+ /* Have to allocate more memory */
+ buf_size += needed;
+ buf_space += needed;
+ if (per_realloc_memory(out_binary, buf_size, &ptr) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ }
+
+ counter -= (4 + no_bytes);
+ if ((counter < 0)
+ || (ret = per_insert_octets_as_bits_exact_len(desired_len,
+ no_bytes, &in_ptr, &ptr, &unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 45:
+ /* This case assumes that the following bytes in the incoming buffer
+ (called By1,By2,Bin) is By1, which is the number of bits (n) that
+ will be inserted in the completed buffer. By2 is the number of
+ bytes in Bin. Each bit in the buffer Bin should be inserted from
+ the leftmost until the nth.*/
+ desired_len = (int) *(++in_ptr);
+ no_bytes = (int) *(++in_ptr);
+
+ saved_mem = buf_space - counter;
+ needed = CEIL((desired_len-unused),8) - no_bytes;
+ if (saved_mem < needed) {
+ /* Have to allocate more memory */
+ buf_size += needed;
+ buf_space += needed;
+ if (per_realloc_memory(out_binary, buf_size, &ptr) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ }
+
+ counter -= (2 + no_bytes);
+
+ if ((counter < 0)
+ || (ret = per_insert_bits_as_bits(desired_len, no_bytes,
+ &in_ptr, &ptr, &unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 46:
+ /* Same as case 45 apart from By1, the desired length, which is
+ in two bytes. */
+ desired_len = (int) *(++in_ptr);
+ desired_len = desired_len << 8;
+ desired_len = desired_len | (int) *(++in_ptr);
+ no_bytes = (int) *(++in_ptr);
+
+ saved_mem = buf_space - counter;
+ needed = CEIL((desired_len-unused),8) - no_bytes;
+ if (saved_mem < needed) {
+ /* Have to allocate more memory */
+ buf_size += needed;
+ buf_space += needed;
+ if (per_realloc_memory(out_binary, buf_size, &ptr) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ }
+
+ counter -= (3 + no_bytes);
+ if ((counter < 0)
+ || (ret = per_insert_bits_as_bits(desired_len, no_bytes,
+ &in_ptr, &ptr, &unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ case 47:
+ /* Same as case 45 apart from By1 and By2, the desired length
+ and the length of Bin, which are in two bytes each. */
+ desired_len = (int) *(++in_ptr);
+ desired_len = desired_len << 8;
+ desired_len = desired_len | (int) *(++in_ptr);
+ no_bytes = (int) *(++in_ptr);
+ no_bytes = no_bytes << 8;
+ no_bytes = no_bytes | (int) *(++in_ptr);
+
+ saved_mem = buf_space - counter;
+ needed = CEIL((desired_len-unused),8) - no_bytes;
+ if (saved_mem < needed) {
+ /* Have to allocate more memory */
+ buf_size += needed;
+ buf_space += needed;
+ if (per_realloc_memory(out_binary, buf_size, &ptr) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ }
+
+ counter -= (4 + no_bytes);
+ if ((counter < 0)
+ || (ret = per_insert_bits_as_bits(desired_len, no_bytes,
+ &in_ptr, &ptr, &unused)) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ buf_space -= ret;
+ break;
+
+ default:
+ return ASN1_ERROR;
+ }
+ in_ptr++;
+ }
+ /* The returned buffer must be at least one byte and
+ it must be octet aligned */
+ if ((unused == 8) && (ptr != out_binary->data))
+ return (ptr - out_binary->data);
+ else {
+ ptr++; /* octet align buffer */
+ return (ptr - out_binary->data);
+ }
+}
+
+int per_realloc_memory(ErlNifBinary *binary, int amount, unsigned char **ptr) {
+
+ int i = *ptr - binary->data;
+
+ if (!enif_realloc_binary(binary, amount)) {
+ /*error handling due to memory allocation failure */
+ return ASN1_ERROR;
+ } else {
+ *ptr = binary->data + i;
+ }
+ return ASN1_OK;
+}
+
+int per_insert_most_sign_bits(int no_bits, unsigned char val,
+ unsigned char **output_ptr, int *unused) {
+ unsigned char *ptr = *output_ptr;
+
+ if (no_bits < *unused) {
+ *ptr = *ptr | (val >> (8 - *unused));
+ *unused -= no_bits;
+ } else if (no_bits == *unused) {
+ *ptr = *ptr | (val >> (8 - *unused));
+ *unused = 8;
+ *++ptr = 0x00;
+ } else {
+ *ptr = *ptr | (val >> (8 - *unused));
+ *++ptr = 0x00;
+ *ptr = *ptr | (val << *unused);
+ *unused = 8 - (no_bits - *unused);
+ }
+ *output_ptr = ptr;
+ return ASN1_OK;
+}
+
+int per_insert_least_sign_bits(int no_bits, unsigned char val,
+ unsigned char **output_ptr, int *unused) {
+ unsigned char *ptr = *output_ptr;
+ int ret = 0;
+
+ if (no_bits < *unused) {
+ *ptr = *ptr | (val << (*unused - no_bits));
+ *unused -= no_bits;
+ } else if (no_bits == *unused) {
+ *ptr = *ptr | val;
+ *unused = 8;
+ *++ptr = 0x00;
+ ret++;
+ } else {
+ /* first in the begun byte in the completed buffer insert
+ so many bits that fit, then insert the rest in next byte.*/
+ *ptr = *ptr | (val >> (no_bits - *unused));
+ *++ptr = 0x00;
+ ret++;
+ *ptr = *ptr | (val << (8 - (no_bits - *unused)));
+ *unused = 8 - (no_bits - *unused);
+ }
+ *output_ptr = ptr;
+ return ret;
+}
+
+/* per_pad_bits adds no_bits bits in the buffer that output_ptr
+ points at.
+ */
+int per_pad_bits(int no_bits, unsigned char **output_ptr, int *unused) {
+ unsigned char *ptr = *output_ptr;
+ int ret = 0;
+
+ while (no_bits > 0) {
+ if (*unused == 1) {
+ *unused = 8;
+ *++ptr = 0x00;
+ ret++;
+ } else
+ (*unused)--;
+ no_bits--;
+ }
+ *output_ptr = ptr;
+ return ret;
+}
+
+/* insert_bits_as_bits removes no_bytes bytes from the buffer that in_ptr
+ points at and takes the desired_no leftmost bits from those removed
+ bytes and inserts them in the buffer(output buffer) that ptr points at.
+ The unused parameter tells how many bits that are not set in the
+ actual byte in the output buffer. If desired_no is more bits than the
+ input buffer has in no_bytes bytes, then zero bits is padded.*/
+int per_insert_bits_as_bits(int desired_no, int no_bytes,
+ unsigned char **input_ptr, unsigned char **output_ptr, int *unused) {
+ unsigned char *in_ptr = *input_ptr;
+ unsigned char val;
+ int no_bits, ret, ret2;
+
+ if (desired_no == (no_bytes * 8)) {
+ if (per_insert_octets_unaligned(no_bytes, &in_ptr, output_ptr, *unused)
+ == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ ret = no_bytes;
+ } else if (desired_no < (no_bytes * 8)) {
+ /* printf("per_insert_bits_as_bits 1\n\r"); */
+ if (per_insert_octets_unaligned(desired_no / 8, &in_ptr, output_ptr,
+ *unused) == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ /* printf("per_insert_bits_as_bits 2\n\r"); */
+ val = *++in_ptr;
+ /* printf("val = %d\n\r",(int)val); */
+ no_bits = desired_no % 8;
+ /* printf("no_bits = %d\n\r",no_bits); */
+ per_insert_most_sign_bits(no_bits, val, output_ptr, unused);
+ ret = CEIL(desired_no,8);
+ } else {
+ if (per_insert_octets_unaligned(no_bytes, &in_ptr, output_ptr, *unused)
+ == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ ret2 = per_pad_bits(desired_no - (no_bytes * 8), output_ptr, unused);
+ /* printf("ret2 = %d\n\r",ret2); */
+ ret = CEIL(desired_no,8);
+ /* printf("ret = %d\n\r",ret); */
+ }
+ /* printf("*unused = %d\n\r",*unused); */
+ *input_ptr = in_ptr;
+ return ret;
+}
+
+/* per_insert_octets_as_bits_exact_len */
+int per_insert_octets_as_bits_exact_len(int desired_len, int in_buff_len,
+ unsigned char **in_ptr, unsigned char **ptr, int *unused) {
+ int ret = 0;
+ int ret2 = 0;
+
+ if (desired_len == in_buff_len) {
+ if ((ret = per_insert_octets_as_bits(in_buff_len, in_ptr, ptr, unused))
+ == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ } else if (desired_len > in_buff_len) {
+ if ((ret = per_insert_octets_as_bits(in_buff_len, in_ptr, ptr, unused))
+ == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ /* now pad with zero bits */
+ /* printf("~npad_bits: called with %d bits padding~n~n~r",desired_len - in_buff_len); */
+ if ((ret2 = per_pad_bits(desired_len - in_buff_len, ptr, unused))
+ == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ } else {/* desired_len < no_bits */
+ if ((ret = per_insert_octets_as_bits(desired_len, in_ptr, ptr, unused))
+ == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ /* now remove no_bits - desired_len bytes from in buffer */
+ *in_ptr += (in_buff_len - desired_len);
+ }
+ return (ret + ret2);
+}
+
+/* insert_octets_as_bits takes no_bytes bytes from the buffer that input_ptr
+ points at and inserts the least significant bit of it in the buffer that
+ output_ptr points at. Each byte in the input buffer must be 1 or 0
+ otherwise the function returns ASN1_ERROR. The output buffer is concatenated
+ without alignment.
+ */
+int per_insert_octets_as_bits(int no_bytes, unsigned char **input_ptr,
+ unsigned char **output_ptr, int *unused) {
+ unsigned char *in_ptr = *input_ptr;
+ unsigned char *ptr = *output_ptr;
+ int used_bits = 8 - *unused;
+
+ while (no_bytes > 0) {
+ switch (*++in_ptr) {
+ case 0:
+ if (*unused == 1) {
+ *unused = 8;
+ *++ptr = 0x00;
+ } else
+ (*unused)--;
+ break;
+ case 1:
+ if (*unused == 1) {
+ *ptr = *ptr | 1;
+ *unused = 8;
+ *++ptr = 0x00;
+ } else {
+ *ptr = *ptr | (1 << (*unused - 1));
+ (*unused)--;
+ }
+ break;
+ default:
+ return ASN1_ERROR;
+ }
+ no_bytes--;
+ }
+ *input_ptr = in_ptr;
+ *output_ptr = ptr;
+ return ((used_bits + no_bytes) / 8); /*return number of new bytes
+ in completed buffer */
+}
+
+/* insert_octets inserts bytes from the input buffer, *input_ptr,
+ into the output buffer, *output_ptr. Before the first byte is
+ inserted the input buffer is aligned.
+ */
+int per_insert_octets(int no_bytes, unsigned char **input_ptr,
+ unsigned char **output_ptr, int *unused) {
+ unsigned char *in_ptr = *input_ptr;
+ unsigned char *ptr = *output_ptr;
+ int ret = 0;
+
+ if (*unused != 8) {/* must align before octets are added */
+ *++ptr = 0x00;
+ ret++;
+ *unused = 8;
+ }
+ while (no_bytes > 0) {
+ *ptr = *(++in_ptr);
+ *++ptr = 0x00;
+ /* *unused = *unused - 1; */
+ no_bytes--;
+ }
+ *input_ptr = in_ptr;
+ *output_ptr = ptr;
+ return (ret + no_bytes);
+}
+
+/* per_insert_octets_unaligned inserts bytes from the input buffer, *input_ptr,
+ into the output buffer, *output_ptr.No alignment is done.
+ */
+int per_insert_octets_unaligned(int no_bytes, unsigned char **input_ptr,
+ unsigned char **output_ptr, int unused) {
+ unsigned char *in_ptr = *input_ptr;
+ unsigned char *ptr = *output_ptr;
+ int n = no_bytes;
+ unsigned char val;
+
+ while (n > 0) {
+ if (unused == 8) {
+ *ptr = *++in_ptr;
+ *++ptr = 0x00;
+ } else {
+ val = *++in_ptr;
+ *ptr = *ptr | val >> (8 - unused);
+ *++ptr = 0x00;
+ *ptr = val << unused;
+ }
+ n--;
+ }
+ *input_ptr = in_ptr;
+ *output_ptr = ptr;
+ return no_bytes;
+}
+
+int per_insert_octets_except_unused(int no_bytes, unsigned char **input_ptr,
+ unsigned char **output_ptr, int *unused, int in_unused) {
+ unsigned char *in_ptr = *input_ptr;
+ unsigned char *ptr = *output_ptr;
+ int val, no_bits;
+ int ret = 0;
+
+ if (in_unused == 0) {
+ if ((ret = per_insert_octets_unaligned(no_bytes, &in_ptr, &ptr, *unused))
+ == ASN1_ERROR
+ )
+ return ASN1_ERROR;
+ } else {
+ if ((ret = per_insert_octets_unaligned(no_bytes - 1, &in_ptr, &ptr, *unused))
+ != ASN1_ERROR) {
+ val = (int) *(++in_ptr);
+ no_bits = 8 - in_unused;
+ /* no_bits is always less than *unused since the buffer is
+ octet aligned after insert:octets call, so the following
+ if clasuse is obsolete I think */
+ if (no_bits < *unused) {
+ *ptr = *ptr | (val >> (8 - *unused));
+ *unused = *unused - no_bits;
+ } else if (no_bits == *unused) {
+ *ptr = *ptr | (val >> (8 - *unused));
+ *++ptr = 0x00;
+ ret++;
+ *unused = 8;
+ } else {
+ *ptr = *ptr | (val >> (8 - *unused));
+ *++ptr = 0x00;
+ ret++;
+ *ptr = *ptr | (val << *unused);
+ *unused = 8 - (no_bits - *unused);
+ }
+ } else
+ return ASN1_ERROR;
+ }
+ *input_ptr = in_ptr;
+ *output_ptr = ptr;
+ return ret;
+}
+
+/*
+ *
+ * This section defines functionality for the partial decode of a
+ * BER encoded message
+ *
+ */
+
+/*
+ * int decode(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf,
+ int in_buf_len, unsigned int *err_pos)
+ * term is a pointer to the term which is to be returned to erlang
+ * in_buf is a pointer into the buffer of incoming bytes.
+ * in_buf_len is the length of the incoming buffer.
+ * The function reads the bytes in the incoming buffer and structures
+ * it in a nested way as Erlang terms. The buffer contains data in the
+ * order tag - length - value. Tag, length and value has the following
+ * format:
+ * A tag is normally one byte but may be of any length, if the tag number
+ * is greater than 30. +----------+
+ * |CL|C|NNNNN|
+ * +----------+
+ * If NNNNN is 31 then will the 7 l.s.b of each of the following tag number
+ * bytes contain the tag number. Each tag number byte that is not the last one
+ * has the m.s.b. set to 1.
+ * The length can be short definite length (sdl), long definite length (ldl)
+ * or indefinite length (il).
+ * sdl: +---------+ the L bits is the length
+ * |0|LLLLLLL|
+ * +---------+
+ * ldl: +---------+ +---------+ +---------+ +-----------+
+ * |1|lllllll| |first len| | | |the Nth len|
+ * +---------+ +---------+ +---------+ ... +-----------+
+ * The first byte tells how many len octets will follow, max 127
+ * il: +---------+ +----------------------+ +--------+ +--------+
+ * |1|0000000| |content octets (Value)| |00000000| |00000000|
+ * +---------+ +----------------------+ +--------+ +--------+
+ * The value octets are preceded by one octet and followed by two
+ * exactly as above. The value must be some tag-length-value encoding.
+ *
+ * The function returns a value in Erlang nif term format:
+ * {{TagNo,Value},Rest}
+ * TagNo is an integer ((CL bsl 16) + tag number) which limits the tag number
+ * to 65535.
+ * Value is a binary if the C bit in tag was unset, otherwise (if tag was
+ * constructed) Value is a list, List.
+ * List is like: [{TagNo,Value},{TagNo,Value},...]
+ * Rest is a binary, i.e. the undecoded part of the buffer. Most often Rest
+ * is the empty binary.
+ * If some error occured during the decoding of the in_buf an error is returned.
+ */
+int ber_decode_begin(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf,
+ int in_buf_len, unsigned int *err_pos) {
+ int maybe_ret;
+ int ib_index = 0;
+ unsigned char *rest_data;
+ ERL_NIF_TERM decoded_term, rest;
+
+ if ((maybe_ret = ber_decode(env, &decoded_term, in_buf, &ib_index,
+ in_buf_len)) <= ASN1_ERROR)
+ {
+ *err_pos = ib_index;
+ return maybe_ret;
+ };
+
+ // The remaining binary after one ASN1 segment has been decoded
+ if ((rest_data = enif_make_new_binary(env, in_buf_len - ib_index, &rest))
+ == NULL) {
+ *term = enif_make_atom(env, "could_not_alloc_binary");
+ return ASN1_ERROR;
+ }
+
+ *term = enif_make_tuple2(env, decoded_term, rest);
+ return ASN1_OK;
+}
+
+int ber_decode(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf,
+ int *ib_index, int in_buf_len) {
+ int maybe_ret;
+ int form;
+ ERL_NIF_TERM tag, value;
+
+ /*buffer must hold at least two bytes*/
+ if ((*ib_index + 2) > in_buf_len)
+ return ASN1_VALUE_ERROR;
+ /* "{{TagNo," */
+ if ((form = ber_decode_tag(env, &tag, in_buf, in_buf_len, ib_index))
+ <= ASN1_ERROR
+ )
+ return form; /* 5 bytes */
+ if (*ib_index >= in_buf_len) {
+ return ASN1_TAG_ERROR;
+ }
+ /* buffer must hold at least one byte (0 as length and nothing as
+ value) */
+ /* "{{TagNo,Value}," */
+ if ((maybe_ret = ber_decode_value(env, &value, in_buf, ib_index, form,
+ in_buf_len)) <= ASN1_ERROR
+ )
+ return maybe_ret; /* at least 5 bytes */
+ *term = enif_make_tuple2(env, tag, value);
+ return ASN1_OK;
+}
+
+/*
+ * decode_tag decodes the BER encoded tag in in_buf and creates an
+ * nif term tag
+ */
+int ber_decode_tag(ErlNifEnv* env, ERL_NIF_TERM *tag, unsigned char *in_buf,
+ int in_buf_len, int *ib_index) {
+ int tag_no, tmp_tag, form;
+
+ /* first get the class of tag and bit shift left 16*/
+ tag_no = ((MASK(in_buf[*ib_index],ASN1_CLASS)) << 10);
+
+ form = (MASK(in_buf[*ib_index],ASN1_FORM));
+
+ /* then get the tag number */
+ if ((tmp_tag = (int) INVMASK(in_buf[*ib_index],ASN1_CLASSFORM)) < 31) {
+ *tag = enif_make_uint(env, tag_no + tmp_tag);
+ (*ib_index)++;
+ } else {
+ int n = 0; /* n is used to check that the 64K limit is not
+ exceeded*/
+
+ /* should check that at least three bytes are left in
+ in-buffer,at least two tag byte and at least one length byte */
+ if ((*ib_index + 3) > in_buf_len)
+ return ASN1_VALUE_ERROR;
+ (*ib_index)++;
+ /* The tag is in the following bytes in in_buf as
+ 1ttttttt 1ttttttt ... 0ttttttt, where the t-bits
+ is the tag number*/
+ /* In practice is the tag size limited to 64K, i.e. 16 bits. If
+ the tag is greater then 64K return an error */
+ while (((tmp_tag = (int) in_buf[*ib_index]) >= 128) && n < 2) {
+ /* m.s.b. = 1 */
+ tag_no = tag_no + (MASK(tmp_tag,ASN1_LONG_TAG) << 7);
+ (*ib_index)++;
+ n++;
+ };
+ if ((n == 2) && in_buf[*ib_index] > 3)
+ return ASN1_TAG_ERROR; /* tag number > 64K */
+ tag_no = tag_no + in_buf[*ib_index];
+ (*ib_index)++;
+ *tag = enif_make_uint(env, tag_no);
+ }
+ return form;
+}
+
+/*
+ * ber_decode_value decodes the BER encoded length and value fields in the
+ * in_buf and puts the value part in the decode_buf as an Erlang
+ * nif term into value
+ */
+int ber_decode_value(ErlNifEnv* env, ERL_NIF_TERM *value, unsigned char *in_buf,
+ int *ib_index, int form, int in_buf_len) {
+ int maybe_ret;
+ unsigned int len = 0;
+ unsigned int lenoflen = 0;
+ int indef = 0;
+ unsigned char *tmp_out_buff;
+ ERL_NIF_TERM term = 0, curr_head = 0;
+
+ if (((in_buf[*ib_index]) & 0x80) == ASN1_SHORT_DEFINITE_LENGTH) {
+ len = in_buf[*ib_index];
+ } else if (in_buf[*ib_index] == ASN1_INDEFINITE_LENGTH
+ )
+ indef = 1;
+ else /* long definite length */{
+ lenoflen = (in_buf[*ib_index] & 0x7f); /*length of length */
+ if (lenoflen > (in_buf_len - (*ib_index + 1)))
+ return ASN1_LEN_ERROR;
+ len = 0;
+ while (lenoflen--) {
+ (*ib_index)++;
+ if (!(len < (1 << (sizeof(len) - 1) * 8)))
+ return ASN1_LEN_ERROR; /* length does not fit in 32 bits */
+ len = (len << 8) + in_buf[*ib_index];
+ }
+ }
+ if (len > (in_buf_len - (*ib_index + 1)))
+ return ASN1_VALUE_ERROR;
+ (*ib_index)++;
+ if (indef == 1) { /* in this case it is desireably to check that indefinite length
+ end bytes exist in inbuffer */
+ curr_head = enif_make_list(env, 0);
+ while (!(in_buf[*ib_index] == 0 && in_buf[*ib_index + 1] == 0)) {
+ if (*ib_index >= in_buf_len)
+ return ASN1_INDEF_LEN_ERROR;
+
+ if ((maybe_ret = ber_decode(env, &term, in_buf, ib_index, in_buf_len))
+ <= ASN1_ERROR
+ )
+ return maybe_ret;
+ curr_head = enif_make_list_cell(env, term, curr_head);
+ }
+ enif_make_reverse_list(env, curr_head, value);
+ (*ib_index) += 2; /* skip the indefinite length end bytes */
+ } else if (form == ASN1_CONSTRUCTED)
+ {
+ int end_index = *ib_index + len;
+ if (end_index > in_buf_len)
+ return ASN1_LEN_ERROR;
+ curr_head = enif_make_list(env, 0);
+ while (*ib_index < end_index) {
+
+ if ((maybe_ret = ber_decode(env, &term, in_buf, ib_index,
+ in_buf_len)) <= ASN1_ERROR
+ )
+ return maybe_ret;
+ curr_head = enif_make_list_cell(env, term, curr_head);
+ }
+ enif_make_reverse_list(env, curr_head, value);
+ } else {
+ if ((*ib_index + len) > in_buf_len)
+ return ASN1_LEN_ERROR;
+ tmp_out_buff = enif_make_new_binary(env, len, value);
+ memcpy(tmp_out_buff, in_buf + *ib_index, len);
+ *ib_index = *ib_index + len;
+ }
+ return ASN1_OK;
+}
+
+struct ber_encode_mem_chunk {
+ mem_chunk_t *next;
+ int length;
+ char *top;
+ char *curr;
+};
+
+int ber_encode(ErlNifEnv *env, ERL_NIF_TERM term, mem_chunk_t **curr, unsigned int *count) {
+
+ const ERL_NIF_TERM *tv;
+ unsigned int form;
+ int arity;
+
+ if (!enif_get_tuple(env, term, &arity, &tv))
+ return ASN1_ERROR;
+
+ form = enif_is_list(env, tv[1]) ? ASN1_CONSTRUCTED : ASN1_PRIMITIVE;
+
+ switch (form) {
+ case ASN1_PRIMITIVE: {
+ ErlNifBinary value;
+ if (!enif_inspect_binary(env, tv[1], &value))
+ return ASN1_ERROR;
+
+ if (ber_check_memory(curr, value.size))
+ return ASN1_ERROR;
+ memcpy((*curr)->curr - value.size + 1, value.data, value.size);
+ (*curr)->curr -= value.size;
+ *count += value.size;
+
+ if (ber_encode_length(value.size, curr, count))
+ return ASN1_ERROR;
+
+ break;
+ }
+ case ASN1_CONSTRUCTED: {
+ ERL_NIF_TERM head, tail;
+ unsigned int tmp_cnt;
+
+ if(!enif_make_reverse_list(env, tv[1], &head))
+ return ASN1_ERROR;
+
+ if (!enif_get_list_cell(env, head, &head, &tail)) {
+ if (enif_is_empty_list(env, tv[1])) {
+ *((*curr)->curr) = 0;
+ (*curr)->curr -= 1;
+ (*count)++;
+ break;
+ } else
+ return ASN1_ERROR;
+ }
+
+ do {
+ tmp_cnt = 0;
+ if (ber_encode(env, head, curr, &tmp_cnt)) {
+ return ASN1_ERROR;
+ }
+ *count += tmp_cnt;
+ } while (enif_get_list_cell(env, tail, &head, &tail));
+
+ if (ber_check_memory(curr, *count)) {
+ return ASN1_ERROR;
+ }
+
+ if (ber_encode_length(*count, curr, count)) {
+ return ASN1_ERROR;
+ }
+
+ break;
+ }
+ }
+
+ // We need atleast 5 bytes to encode the next tlv
+ if (ber_check_memory(curr, 3))
+ return ASN1_ERROR;
+
+ if (ber_encode_tag(env, tv[0], form, curr, count))
+ return ASN1_ERROR;
+
+ return ASN1_OK;
+}
+
+int ber_encode_tag(ErlNifEnv *env, ERL_NIF_TERM tag, unsigned int form,
+ mem_chunk_t **curr, unsigned int *count) {
+ unsigned int class_tag_no, head_tag;
+ if (!enif_get_uint(env, tag, &class_tag_no))
+ return ASN1_ERROR;
+
+ head_tag = form | ((class_tag_no & 0x30000) >> 10);
+ class_tag_no = class_tag_no & 0xFFFF;
+
+ if (class_tag_no <= 30) {
+ *(*curr)->curr = head_tag | class_tag_no;
+ (*curr)->curr -= 1;
+ (*count)++;
+ return ASN1_OK;
+ } else {
+ *(*curr)->curr = class_tag_no & 127;
+ class_tag_no = class_tag_no >> 7;
+ (*curr)->curr -= 1;
+ (*count)++;
+
+ while (class_tag_no > 0) {
+ *(*curr)->curr = (class_tag_no & 127) | 0x80;
+ class_tag_no >>= 7;
+ (*curr)->curr -= 1;
+ (*count)++;
+ }
+
+ *(*curr)->curr = head_tag | 0x1F;
+ (*curr)->curr -= 1;
+ (*count)++;
+
+ return ASN1_OK;
+ }
+}
+
+int ber_encode_length(size_t size, mem_chunk_t **curr, unsigned int *count) {
+ if (size < 128) {
+ if (ber_check_memory(curr, 1u))
+ return ASN1_ERROR;
+ *(*curr)->curr = size;
+ (*curr)->curr -= 1;
+ (*count)++;
+ } else {
+ int chunks = size / 256 + 1;
+ if (ber_check_memory(curr, chunks + 1))
+ return ASN1_ERROR;
+
+ while (size > 0)
+ {
+ *(*curr)->curr = size & 0xFF;
+ size >>= 8;
+ (*curr)->curr -= 1;
+ (*count)++;
+ }
+
+ *(*curr)->curr = chunks | 0x80;
+ (*curr)->curr -= 1;
+ (*count)++;
+ }
+ return ASN1_OK;
+}
+
+mem_chunk_t *ber_new_chunk(unsigned int length) {
+ mem_chunk_t *new = enif_alloc(sizeof(mem_chunk_t));
+ if (new == NULL)
+ return NULL;
+ new->next = NULL;
+ new->top = enif_alloc(sizeof(char) * length);
+ if (new->top == NULL) {
+ free(new);
+ return NULL;
+ }
+ new->curr = new->top + length - 1;
+ new->length = length;
+ return new;
+}
+
+void ber_free_chunks(mem_chunk_t *chunk) {
+ mem_chunk_t *curr, *next = chunk;
+ while (next != NULL) {
+ curr = next;
+ next = curr->next;
+ enif_free(curr->top);
+ enif_free(curr);
+ }
+}
+
+int ber_check_memory(mem_chunk_t **curr, unsigned int needed) {
+ mem_chunk_t *new;
+ if ((*curr)->curr-needed >= (*curr)->top)
+ return ASN1_OK;
+
+ if ((new = ber_new_chunk((*curr)->length > needed ? (*curr)->length * 2 : (*curr)->length + needed)) == NULL)
+ return ASN1_ERROR;
+ new->next = *curr;
+ *curr = new;
+ return ASN1_OK;
+}
+
+static ERL_NIF_TERM encode_per_complete(ErlNifEnv* env, int argc,
+ const ERL_NIF_TERM argv[]) {
+ ERL_NIF_TERM err_code;
+ ErlNifBinary in_binary;
+ ErlNifBinary out_binary;
+ int complete_len;
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &in_binary))
+ return enif_make_atom(env, "badarg");
+
+ if (!enif_alloc_binary(in_binary.size, &out_binary))
+ return enif_make_atom(env, "alloc_binary_failed");
+
+ if (in_binary.size == 0)
+ return enif_make_binary(env, &out_binary);
+
+ if ((complete_len = per_complete(&out_binary, in_binary.data,
+ in_binary.size)) <= ASN1_ERROR) {
+ enif_release_binary(&out_binary);
+ if (complete_len == ASN1_ERROR
+ )
+ err_code = enif_make_uint(env, '1');
+ else
+ err_code = enif_make_uint(env, 0);
+ return enif_make_tuple2(env, enif_make_atom(env, "error"), err_code);
+ }
+ if (complete_len < out_binary.size)
+ enif_realloc_binary(&out_binary, complete_len);
+
+ return enif_make_binary(env, &out_binary);
+}
+
+static ERL_NIF_TERM decode_ber_tlv(ErlNifEnv* env, int argc,
+ const ERL_NIF_TERM argv[]) {
+ ErlNifBinary in_binary;
+ ERL_NIF_TERM return_term;
+ unsigned int err_pos = 0, return_code;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &in_binary))
+ return enif_make_badarg(env);
+
+ if ((return_code = ber_decode_begin(env, &return_term, in_binary.data,
+ in_binary.size, &err_pos)) != ASN1_OK
+ )
+ return enif_make_tuple2(env, enif_make_atom(env,"error"), enif_make_tuple2(env,
+ enif_make_int(env, return_code),enif_make_int(env, err_pos)));
+ return return_term;
+}
+
+static ERL_NIF_TERM encode_ber_tlv(ErlNifEnv* env, int argc,
+ const ERL_NIF_TERM argv[]) {
+ ErlNifBinary out_binary;
+ unsigned int length = 0, pos = 0;
+ int encode_err;
+ mem_chunk_t *curr, *top;
+ ERL_NIF_TERM err_code;
+
+ curr = ber_new_chunk(40);
+
+ if ((encode_err = ber_encode(env, argv[0], &curr, &length))
+ <= ASN1_ERROR) {
+ ber_free_chunks(curr);
+ err_code = enif_make_int(env, encode_err);
+ return enif_make_tuple2(env, enif_make_atom(env, "error"), err_code);
+ }
+
+ if (!enif_alloc_binary(length, &out_binary)) {
+ ber_free_chunks(curr);
+ return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_atom(env,"oom"));
+ }
+
+ top = curr;
+
+ while (curr != NULL) {
+ length = curr->length - (curr->curr-curr->top) -1;
+ if (length > 0)
+ memcpy(out_binary.data + pos, curr->curr+1, length);
+ pos += length;
+ curr = curr->next;
+ }
+
+ ber_free_chunks(top);
+
+ return enif_make_binary(env, &out_binary);
+}
+
+static int is_ok_load_info(ErlNifEnv* env, ERL_NIF_TERM load_info) {
+ int i;
+ return enif_get_int(env, load_info, &i) && i == 1;
+}
+
+static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) {
+ if (!is_ok_load_info(env, load_info))
+ return -1;
+ return 0;
+}
+
+static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data,
+ ERL_NIF_TERM load_info) {
+ if (!is_ok_load_info(env, load_info))
+ return -1;
+ return 0;
+}
+
+static void unload(ErlNifEnv* env, void* priv_data) {
+
+}
+
+static ErlNifFunc nif_funcs[] = { { "encode_per_complete", 1,
+ encode_per_complete }, { "decode_ber_tlv", 1, decode_ber_tlv }, {
+ "encode_ber_tlv", 1, encode_ber_tlv } };
+
+ERL_NIF_INIT(asn1rt_nif, nif_funcs, load, NULL, upgrade, unload)
diff --git a/lib/asn1/doc/src/asn1_spec.xmlsrc b/lib/asn1/doc/src/asn1_spec.xmlsrc
index 8d61834da8..07cba17816 100644
--- a/lib/asn1/doc/src/asn1_spec.xmlsrc
+++ b/lib/asn1/doc/src/asn1_spec.xmlsrc
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2009</year>
+ <year>2003</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -43,7 +43,7 @@
<p>So far this functionality is only provided when using the
optimized BER_BIN version, that is when compiling with the
options <c>ber_bin</c> and <c>optimize</c>. It does also work
- using the <c>driver</c> option. We have no intent to make this
+ using the <c>nif</c> option. We have no intent to make this
available on the default BER version, but maybe in the PER_BIN
version (<c>per_bin</c>).
</p>
@@ -661,7 +661,9 @@ ValAction = {'Action',17,{'Button',4711,false}}.
<p>The ASN.1 specs in the test are compiled with the options
<c>ber_bin, optimize, driver</c> and <c>asn1config</c>. If the
<c>driver</c> option had been omitted there should have been
- higher values for <c>decode</c> and <c>decode_part</c>.
+ higher values for <c>decode</c> and <c>decode_part</c>. These tests have
+ not been re-run using nifs, but are expected to perform about 5% better
+ than the linked-in driver.
</p>
<p>The test program runs 10000 decodes on the value, resulting
in a printout with the elapsed time in microseconds for the
diff --git a/lib/asn1/doc/src/asn1_ug.xml b/lib/asn1/doc/src/asn1_ug.xml
index 12d986308f..1b399fb641 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>2010</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -347,7 +347,7 @@ erlc -o ../asnfiles -I ../asnfiles -I /usr/local/standards/asn1 Person.asn
<p>This flag has effect only when used together with one of
<c>per_bin</c> or <c>ber_bin</c> flags. It gives time optimized
code in the generated modules and it uses another runtime module.
- In the <c>per_bin</c> case a linked-in driver is used. The
+ In the <c>per_bin</c> case a nif is used. The
result from an encode is a binary.</p>
<p><em>When this flag is used you cannot use the old format</em><c>{TypeName,Value}</c> when you encode values. Since it is
an unnecessary construct it has been removed in favor of
@@ -362,9 +362,14 @@ erlc -o ../asnfiles -I ../asnfiles -I /usr/local/standards/asn1 Person.asn
</item>
<tag><c>+driver</c></tag>
<item>
- <p>Together with the flags <c>ber_bin</c> and <c>optimize</c>
- you choose to use a linked in driver for considerable faster
- decode.</p>
+ <p>As of R15B this means the same as the <c>nif</c> option. Kept for
+ backwards compatability reasons.</p>
+ </item>
+ <tag><c>+nif</c></tag>
+ <item>
+ <p>Together with the flags <c>ber_bin</c>
+ and <c>optimize</c> you choose to use a nif for considerable
+ faster encode and decode. </p>
</item>
<tag><c>+asn1config</c></tag>
<item>
@@ -492,7 +497,7 @@ asn1ct:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
</row>
<row>
<cell align="left" valign="middle">BER</cell>
- <cell align="left" valign="middle"><em>[ber_bin, optimize, driver]</em></cell>
+ <cell align="left" valign="middle"><em>[ber_bin, optimize, nif]</em></cell>
<cell align="left" valign="middle">EAVF</cell>
<cell align="left" valign="middle">iolist</cell>
<cell align="left" valign="middle">iolist / binary</cell>
@@ -557,7 +562,7 @@ asn1ct:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
</row>
<row>
<cell align="left" valign="middle">DER</cell>
- <cell align="left" valign="middle"><em>[ber_bin, optimize, driver, der]</em></cell>
+ <cell align="left" valign="middle"><em>[ber_bin, optimize, nif, der]</em></cell>
<cell align="left" valign="middle">EAVF</cell>
<cell align="left" valign="middle">iolist</cell>
<cell align="left" valign="middle">binary</cell>
@@ -626,23 +631,24 @@ asn1ct:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
</table>
<p>
- The sole compile options <c>ber</c>, <c>ber_bin</c> and <c>per</c>
- are kept for backwards compatibility and should not be used in
- new code.
+ The compile options <c>ber</c>, <c>per</c> and
+ <c>driver</c> are kept for backwards compatibility and should not be
+ used in new code. The nif implementation which replaces the linked-in
+ driver has been shown to be about 5-15% faster.
</p>
<p>
You are strongly recommended to use the appropriate alternative
of the bold typed options. The <c>optimize</c> and
- <c>driver</c> options does not affect the encode or decode
+ <c>nif</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 chosen parts of encode /
+ <c>nif</c> or <c>per_bin</c> and <c>optimize</c> is
+ combined the C-code nif is used in chosen parts of encode /
decode procedure.
</p>
<table>
<row>
<cell align="left" valign="middle"><em>Compile options, allowed combinations</em></cell>
- <cell align="left" valign="middle"><em>use of linked-in driver</em></cell>
+ <cell align="left" valign="middle"><em>use of nif</em></cell>
</row>
<row>
<cell align="left" valign="middle">[ber]</cell>
@@ -657,7 +663,7 @@ asn1ct:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
<cell align="left" valign="middle">no</cell>
</row>
<row>
- <cell align="left" valign="middle"><em>[ber_bin, optimize, driver]</em></cell>
+ <cell align="left" valign="middle"><em>[ber_bin, optimize, nif]</em></cell>
<cell align="left" valign="middle">yes</cell>
</row>
<row>
@@ -690,12 +696,12 @@ asn1ct:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
<cell align="left" valign="middle">no</cell>
</row>
<row>
- <cell align="left" valign="middle"><em>[ber_bin, optimize, driver, der]</em></cell>
+ <cell align="left" valign="middle"><em>[ber_bin, optimize, nif, der]</em></cell>
<cell align="left" valign="middle">yes</cell>
</row>
- <tcaption>When the ASN1 linked-in driver is used.</tcaption>
+ <tcaption>When the ASN1 nif is used.</tcaption>
</table>
</section>
@@ -712,14 +718,14 @@ asn1rt:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre>
<pre>
'H323-MESSAGES':encode('SomeChoiceType',{call,"octetstring"}).
'H323-MESSAGES':decode('SomeChoiceType',Bytes). </pre>
- <p>The asn1 linked-in driver is enabled in two occasions: encoding of
+ <p>The asn1 nif is enabled in two occasions: encoding of
asn1 values when the asn1 spec is compiled with <c>per_bin</c> and
<c>optimize</c> or decode of encoded asn1 values when the asn1 spec is
- compiled with <c>ber_bin</c>, <c>optimize</c> and <c>driver</c>. In
- those cases the driver will be loaded automatically at the first call
+ compiled with <c>ber_bin</c>, <c>optimize</c> and <c>nif</c>. In
+ those cases the nif will be loaded automatically at the first call
to <c>encode</c>/<c>decode</c>. If one doesn't want the performance
- overhead of the driver being loaded at the first call it is possible
- to load the driver separately by <c>asn1rt:load_driver()</c>. </p>
+ overhead of the nif being loaded at the first call it is possible
+ to load the nif separately by loading the <c>asn1rt_nif</c> module.</p>
<p>By invoking the function <c>info/0</c> in a generated module, one
gets information about which compiler options were used.</p>
</section>
diff --git a/lib/asn1/doc/src/asn1ct.xml b/lib/asn1/doc/src/asn1ct.xml
index 265f8735c2..0b9ec3df7f 100644
--- a/lib/asn1/doc/src/asn1ct.xml
+++ b/lib/asn1/doc/src/asn1ct.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2010</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -52,8 +52,8 @@
<v>Options = [Option| OldOption]</v>
<v>Option = ber_bin | per_bin | uper_bin | der | compact_bit_string |
noobj | {n2n,EnumTypeName} |{outdir,Dir} | {i,IncludeDir} | optimize |
- driver | asn1config | undec_rest | {inline,OutputName} | inline |
- {macro_name_prefix, Prefix} | {record_name_prefix, Prefix} | verbose</v>
+ nif | asn1config | undec_rest | {inline,OutputName} | inline |
+ {macro_name_prefix, Prefix} | {record_name_prefix, Prefix} | verbose | warnings_as_errors</v>
<v>OldOption = ber | per</v>
<v>Reason = term()</v>
<v>Prefix = string()</v>
@@ -212,16 +212,21 @@ Binary = binary()
<c>per_bin</c>
or <c>ber_bin</c> option. It gives time optimized code
generated and it uses another runtime module and
- in the <c>per_bin</c> case a linked-in driver. The result
+ in the <c>per_bin</c> case a nif. The result
in the <c>per_bin</c> case from an encode when compiled
with this option will be a binary.</p>
</item>
<tag><c>driver</c></tag>
<item>
+ <p>As of R15B this means the same as the <c>nif</c> option. Kept for
+ backwards compatability reasons.</p>
+ </item>
+ <tag><c>nif</c></tag>
+ <item>
<p>Option valid together with <c>ber_bin</c> and <c>optimize</c>
- options. It enables the use of a linked-in driver that gives
- considerable faster decode. In <c>ber_bin</c> the driver is
- enabled only by explicit use of the option <c>driver</c>.</p>
+ options. It enables the use of several nifs that gives faster
+ encode and decode. Nifs are only enabled by the explicit use of
+ the option <c>nif</c></p>
</item>
<tag><c>asn1config</c></tag>
<item>
@@ -264,7 +269,11 @@ Binary = binary()
<c>.set.asn</c> are exported, unless a
<c>{export,[atom()]}</c> or <c>{export_all,true}</c> option
are provided. The list of atoms are names of chosen asn1
- specs from the <c>.set.asn</c> file.</p>
+ specs from the <c>.set.asn</c> file. </p>
+ <p>When used together with <c>nif</c> for <c>ber_bin</c>, the
+ asn1 nifs will be used if the <c>asn1rt_nif</c> module is
+ available. If it is not available, a slower erlang fallback
+ will be used.</p>
</item>
<tag><c>inline</c></tag>
<item>
@@ -289,6 +298,10 @@ Binary = binary()
<p>Causes more verbose information from the compiler
describing what it is doing.</p>
</item>
+ <tag><c>warnings_as_errors</c></tag>
+ <item>
+ <p>Causes warnings to be treated as errors.</p>
+ </item>
</taglist>
<p>Any additional option that is applied will be passed to
the final step when the generated .erl file is compiled.
@@ -343,18 +356,6 @@ Binary = binary()
</desc>
</func>
<func>
- <name>validate(Module,Type,Value) -> ok | {error,Reason}</name>
- <fsummary>Validate an ASN.1 value.</fsummary>
- <type>
- <v>Module = Type = atom()</v>
- <v>Value = term()</v>
- </type>
- <desc>
- <p>Validates that <c>Value</c> conforms to <c>Type</c>
- from <c>Module</c>. <em>Not implemented in this version of the ASN.1 application.</em></p>
- </desc>
- </func>
- <func>
<name>value(Module ,Type) -> {ok,Value} | {error,Reason}</name>
<fsummary>Create an ASN.1 value for test purposes.</fsummary>
<type>
diff --git a/lib/asn1/doc/src/asn1rt.xml b/lib/asn1/doc/src/asn1rt.xml
index 1217a07e9b..0c3c257189 100644
--- a/lib/asn1/doc/src/asn1rt.xml
+++ b/lib/asn1/doc/src/asn1rt.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -42,36 +42,6 @@
<funcs>
<func>
- <name>start() -> ok |{error,Reason}</name>
- <fsummary>Starts the asn1 server.</fsummary>
- <type>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Starts the asn1 server that loads the drivers.</p>
- <p>The server schedules a driver that is not blocked by
- another caller. The driver is used by the asn1 application if
- specs are compiled with options <c>[per_bin, optimize]</c> or
- <c>[ber_bin, optimize, driver]</c>. The server will be started
- automatically at encode/decode if it isn't done explicitly. If
- encode/decode with driver is used in test or industrial code
- it is a performance gain to start it explicitly to avoid the
- one time load in run-time.</p>
- </desc>
- </func>
-
- <func>
- <name>stop() -> ok |{error,Reason}</name>
- <fsummary>Stops the asn1 server.</fsummary>
- <type>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Stops the asn1 server and unloads the drivers.</p>
- </desc>
- </func>
-
- <func>
<name>decode(Module,Type,Bytes) -> {ok,Value}|{error,Reason}</name>
<fsummary>Decode from bytes into an ASN.1 value.</fsummary>
<type>
@@ -126,35 +96,23 @@
<func>
<name>load_driver() -> ok | {error,Reason}</name>
- <fsummary>Loads the linked-in driver.</fsummary>
+ <fsummary>Loads the linked-in driver. (deprecated)</fsummary>
<type>
<v>Reason = term()</v>
</type>
<desc>
- <p>This function loads the linked-in driver before the first call
- to encode. If this function is not called the driver will be loaded
- automatically at the first call to encode. If one doesn't want the
- performance cost of a driver load when the application is running,
- this function makes it possible to load the driver in an
- initialization.</p>
- <p>The driver is only used when encoding/decoding ASN.1 files that
- were compiled with the options <c>per_bin</c> and <c>optimize</c>.</p>
+ <p>This function is obsolete and will be removed in R16A</p>
</desc>
</func>
<func>
<name>unload_driver() -> ok | {error,Reason}</name>
- <fsummary>Unloads the linked-in driver.</fsummary>
+ <fsummary>Unloads the linked-in driver. (deprecated)</fsummary>
<type>
<v>Reason = term()</v>
</type>
<desc>
- <p>This function unloads the linked-in driver.
- When the driver has been loaded it remains in the environment until
- it is unloaded. Normally the driver should remain loaded, it is
- crucial for the performance of ASN.1 encoding. </p>
- <p>The driver is only used when ASN.1 modules have been compiled
- with the flags <c>per_bin</c> and <c>optimize</c>.</p>
+ <p>This function is obsolete and will be removed in R16A</p>
</desc>
</func>
@@ -188,19 +146,6 @@
value, to a UTF8 encoded binary.</p>
</desc>
</func>
-
- <func>
- <name>validate(Module,Type,Value) -> ok | {error,Reason}</name>
- <fsummary>Validate an ASN.1 value.</fsummary>
- <type>
- <v>Module = Type = atom()</v>
- <v>Value = term()</v>
- </type>
- <desc>
- <p>Validates that <c>Value</c> conforms to <c>Type</c>
- from <c>Module</c>. <em>Not implemented in this version of the ASN.1 application.</em></p>
- </desc>
- </func>
</funcs>
diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml
index 77769afcd4..52d770c9f6 100644
--- a/lib/asn1/doc/src/notes.xml
+++ b/lib/asn1/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,49 @@
<p>This document describes the changes made to the asn1 application.</p>
+<section><title>Asn1 1.6.18</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Implement or fix -Werror option</p>
+ <p>
+ If -Werror is enabled and there are warnings no output
+ file is written. Also make sure that error/warning
+ reporting is consistent. (Thanks to Tuncer Ayaz)</p>
+ <p>
+ Own Id: OTP-9536</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 1.6.17</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Test cases which started failing when timer:tc was
+ changed to not catch are corrected.</p>
+ <p>
+ Own Id: OTP-9286</p>
+ </item>
+ <item>
+ <p>
+ The bounds checking in the asn1_erl_driver when the
+ length value of a TLV is a Long Definite Length is
+ corrected. Thanks to Vance Shipley.</p>
+ <p>
+ Own Id: OTP-9303</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Asn1 1.6.16</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/asn1/src/Makefile b/lib/asn1/src/Makefile
index 2733cde3f8..3a59773d93 100644
--- a/lib/asn1/src/Makefile
+++ b/lib/asn1/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2009. All Rights Reserved.
+# Copyright Ericsson AB 1997-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -68,7 +68,7 @@ RT_MODULES= \
asn1rt_per_bin_rt2ct \
asn1rt_uper_bin \
asn1rt_check \
- asn1rt_driver_handler
+ asn1rt_nif
# asn1_sup \
# asn1_app \
# asn1_server
diff --git a/lib/asn1/src/asn1.app.src b/lib/asn1/src/asn1.app.src
index abacb0a1e9..09144ba2f7 100644
--- a/lib/asn1/src/asn1.app.src
+++ b/lib/asn1/src/asn1.app.src
@@ -9,12 +9,11 @@
asn1rt_ber_bin,
asn1rt_ber_bin_v2,
asn1rt_check,
- asn1rt_driver_handler
+ asn1rt_nif
]},
{registered, [
asn1_ns,
- asn1db,
- asn1_driver_owner
+ asn1db
]},
{env, []},
{applications, [kernel, stdlib]}
diff --git a/lib/asn1/src/asn1_app.erl b/lib/asn1/src/asn1_app.erl
index 2d3eed1743..9fff96e0bf 100644
--- a/lib/asn1/src/asn1_app.erl
+++ b/lib/asn1/src/asn1_app.erl
@@ -28,7 +28,7 @@
%% {error, Reason}
%%
start(_Type, _StartArgs) ->
- asn1_sup:start_link().
+ {ok, self()}.
%% stop(State)
%%
diff --git a/lib/asn1/src/asn1_server.erl b/lib/asn1/src/asn1_server.erl
deleted file mode 100644
index aeb59d8b0c..0000000000
--- a/lib/asn1/src/asn1_server.erl
+++ /dev/null
@@ -1,107 +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$
-%%
-
-%% Purpose: Provide complete encode/and pre-decode of asn1.
--module(asn1_server).
-
-
-
--behaviour(gen_server).
-
--export([start_link/0,client_port/0]).
-
-%% Internal exports, call-back functions.
--export([init/1,handle_call/3,handle_cast/2,handle_info/2,code_change/3,
- terminate/2]).
-
-
-%% Macros
--define(port_names,
- { asn1_drv01, asn1_drv02, asn1_drv03, asn1_drv04,
- asn1_drv05, asn1_drv06, asn1_drv07, asn1_drv08,
- asn1_drv09, asn1_drv10, asn1_drv11, asn1_drv12,
- asn1_drv13, asn1_drv14, asn1_drv15, asn1_drv16 }).
-%%% --------------------------------------------------------
-%%% Interface Functions.
-%%% --------------------------------------------------------
-
-start_link() ->
- gen_server:start_link({local, asn1_server}, asn1_server, [], []).
-
-init([]) ->
- process_flag(trap_exit, true),
- erl_ddll:start(),
- PrivDir = code:priv_dir(asn1),
- LibDir1 = filename:join([PrivDir, "lib"]),
- case erl_ddll:load_driver(LibDir1, asn1_erl_drv) of
- ok -> ok;
- {error,_} ->
- LibDir2 =
- filename:join(LibDir1,
- erlang:system_info(system_architecture)),
- erl_ddll:load_driver(LibDir2, asn1_erl_drv)
- end,
- open_ports("asn1_erl_drv",size(?port_names)).
-
-open_ports(_,0) ->
- {ok, []};
-open_ports(Cmd,N) ->
- Port = open_port({spawn, Cmd}, []),
- %% check that driver is loaded, linked and working
- case catch port_control(Port, 0, []) of
- {'EXIT', _} ->
- {stop, nodriver};
- _ ->
- register(element(N,?port_names), Port),
- open_ports(Cmd,N-1)
- end.
-
-client_port() ->
- element(erlang:system_info(scheduler_id) rem size(?port_names) + 1,
- ?port_names).
-
-
-%%% --------------------------------------------------------
-%%% The call-back functions.
-%%% --------------------------------------------------------
-
-handle_call(_, _, State) ->
- {noreply, State}.
-
-handle_cast(_, State) ->
- {noreply, State}.
-
-handle_info({'EXIT', Pid, _Reason}, State) when is_pid(Pid) ->
- {noreply, State};
-
-handle_info({'EXIT', Port, Reason}, State) when is_port(Port) ->
- {stop, {port_died, Reason}, State};
-handle_info(_, State) ->
- {noreply, State}.
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-terminate(_Reason, _State) ->
- close_ports(size(?port_names)).
-
-close_ports(0) ->
- ok;
-close_ports(N) ->
- element(N,?port_names) ! {self(), close}, %% almost same as port_close(Name)
- close_ports(N-1).
diff --git a/lib/asn1/src/asn1_sup.erl b/lib/asn1/src/asn1_sup.erl
deleted file mode 100644
index a241dec6f4..0000000000
--- a/lib/asn1/src/asn1_sup.erl
+++ /dev/null
@@ -1,37 +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$
-%%
-
-%% Purpose: Main supervisor in asn1 application.
-
--module(asn1_sup).
-
--behaviour(supervisor).
-
--export([start_link/0, init/1]).
-
-start_link() ->
- supervisor:start_link({local, asn1_sup}, asn1_sup, []).
-
-
-%% init([])
-%% Returns: {ok, {SupFlags, [ChildSpec]}}
-%%
-init([]) ->
- Child = {asn1_server, {asn1_server, start_link, []},
- permanent, 2000, worker, [asn1_server]},
- {ok, {{one_for_all, 10, 3600}, [Child]}}.
diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl
index a167d27f82..85bb5b2f28 100644
--- a/lib/asn1/src/asn1ct.erl
+++ b/lib/asn1/src/asn1ct.erl
@@ -39,7 +39,7 @@
add_tobe_refed_func/1,add_generated_refed_func/1,
maybe_rename_function/3,latest_sindex/0,current_sindex/0,
set_current_sindex/1,next_sindex/0,maybe_saved_sindex/2,
- parse_and_save/2,verbose/3,warning/3,error/3]).
+ parse_and_save/2,verbose/3,warning/3,warning/4,error/3]).
-include("asn1_records.hrl").
-include_lib("stdlib/include/erl_compile.hrl").
@@ -47,6 +47,10 @@
-import(asn1ct_gen_ber_bin_v2,[encode_tag_val/3,decode_class/1]).
+-ifndef(vsn).
+-define(vsn,"0.0.1").
+-endif.
+
-define(unique_names,0).
-define(dupl_uniquedefs,1).
-define(dupl_equaldefs,2).
@@ -81,6 +85,12 @@ compile(File) ->
compile(File,[]).
compile(File,Options) when is_list(Options) ->
+ case lists:member(driver, Options) of %% remove me in R16A!
+ true ->
+ io:format("Warning: driver option is obsolete and will be removed in R16A, use nif instead!");
+ false ->
+ ok
+ end,
Options1 = optimize_ber_bin(Options),
Options2 = includes(File,Options1),
Includes=[I||{i,I}<-Options2],
@@ -825,10 +835,13 @@ generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) ->
case catch specialized_decode_prepare(EncodingRule,M,GenTOrV,Options) of
{error, enoent} -> ok;
{error, Reason} -> warning("Error in configuration "
- "file: ~n~p~n",[Reason],Options);
+ "file: ~n~p~n",[Reason],Options,
+ "Error in configuration file");
{'EXIT',Reason} -> warning("Internal error when "
"analyzing configuration "
- "file: ~n~p~n",[Reason],Options);
+ "file: ~n~p~n",[Reason],Options,
+ "Internal error when "
+ "analyzing configuration");
_ -> ok
end,
@@ -1082,7 +1095,7 @@ get_runtime_mod(Options) ->
ber_bin_v2 -> ["asn1rt_ber_bin_v2.erl"];
uper_bin -> ["asn1rt_uper_bin.erl"]
end,
- RtMod1++["asn1rt_check.erl","asn1rt_driver_handler.erl","asn1rt.erl"].
+ RtMod1++["asn1rt_check.erl","asn1rt.erl"].
erl_compile(OutFile,Options) ->
@@ -2524,14 +2537,14 @@ type_check(#'Externaltypereference'{}) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Report functions.
%%
-%% Errors messages are controlled with the 'errors' compiler option
+%% Error messages are controlled with the 'errors' compiler option
%% Warning messages are controlled with the 'warnings' compiler option
%% Verbose messages are controlled with the 'verbose' compiler option
error(Format, Args, S) ->
case is_error(S) of
true ->
- io:format("Error: " ++ Format, Args);
+ io:format(Format, Args);
false ->
ok
end.
@@ -2544,6 +2557,17 @@ warning(Format, Args, S) ->
ok
end.
+warning(Format, Args, S, Reason) ->
+ case {is_werr(S), is_error(S), is_warning(S)} of
+ {true, true, _} ->
+ io:format(Format, Args),
+ throw({error, Reason});
+ {false, _, true} ->
+ io:format(Format, Args);
+ _ ->
+ ok
+ end.
+
verbose(Format, Args, S) ->
case is_verbose(S) of
true ->
@@ -2566,3 +2590,8 @@ is_verbose(S) when is_record(S, state) ->
is_verbose(S#state.options);
is_verbose(O) ->
lists:member(verbose, O).
+
+is_werr(S) when is_record(S, state) ->
+ is_werr(S#state.options);
+is_werr(O) ->
+ lists:member(warnings_as_errors, O).
diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl
index efd731f052..e318477234 100644
--- a/lib/asn1/src/asn1ct_check.erl
+++ b/lib/asn1/src/asn1ct_check.erl
@@ -2031,7 +2031,7 @@ get_objectset_def2(_S,T = #typedef{typespec=#'ObjectSet'{}},_CField) ->
T;
get_objectset_def2(S,T,_CField) ->
asn1ct:warning("get_objectset_def2: uncontrolled object set structure:~n~p~n",
- [T],S).
+ [T],S,"get_objectset_def2: uncontrolled object set structure").
type_name(S,#type{def=Def}) ->
CurrMod = S#state.mname,
@@ -2705,7 +2705,7 @@ normalize_value(S,Type,{'DEFAULT',Value},NameList) ->
normalize_objectclassfieldvalue(S,Value,NL);
Err ->
asn1ct:warning("could not check default value ~p~nType:~n~p~nNameList:~n~p~n",
- [Value,Type,Err],S),
+ [Value,Type,Err],S,"could not check default value"),
Value
end;
normalize_value(S,Type,Val,NameList) ->
@@ -2791,22 +2791,27 @@ normalize_bitstring(S,Value,Type)->
case catch lists:map(F,RecList) of
{error,Reason} ->
asn1ct:warning("default value not "
- "compatible with type definition ~p~n",
- [Reason],S),
+ "compatible with type definition ~p~n",
+ [Reason],S,
+ "default value not "
+ "compatible with type definition"),
Value;
NewList ->
NewList
end;
_ ->
asn1ct:warning("default value not "
- "compatible with type definition ~p~n",
- [RecList],S),
+ "compatible with type definition ~p~n",
+ [RecList],S,
+ "default value not "
+ "compatible with type definition"),
Value
end;
{Name,String} when is_atom(Name) ->
normalize_bitstring(S,String,Type);
Other ->
- asn1ct:warning("illegal default value ~p~n",[Other],S),
+ asn1ct:warning("illegal default value ~p~n",[Other],S,
+ "illegal default value"),
Value
end.
@@ -2846,12 +2851,14 @@ normalize_octetstring(S,Value,CType) ->
lists:map(fun([])-> ok;
(H)when H > 255->
asn1ct:warning("not legal octet value ~p in OCTET STRING, ~p~n",
- [H,List],S);
+ [H,List],S,
+ "not legal octet value ~p in OCTET STRING");
(_)-> ok
end, List),
List;
Other ->
- asn1ct:warning("unknown default value ~p~n",[Other],S),
+ asn1ct:warning("unknown default value ~p~n",[Other],S,
+ "unknown default value"),
Value
end.
@@ -2908,13 +2915,15 @@ normalize_enumerated(S,{Name,EnumV},CType) when is_atom(Name) ->
normalize_enumerated(S,Value,{CType1,CType2}) when is_list(CType1), is_list(CType2)->
normalize_enumerated(S,Value,CType1++CType2);
normalize_enumerated(S,V,CType) ->
- asn1ct:warning("Enumerated unknown type ~p~n",[CType],S),
+ asn1ct:warning("Enumerated unknown type ~p~n",[CType],S,
+ "Enumerated unknown type"),
V.
normalize_enumerated2(S,V,Enum) ->
case lists:keysearch(V,1,Enum) of
{value,{Val,_}} -> Val;
_ ->
- asn1ct:warning("Enumerated value is not correct ~p~n",[V],S),
+ asn1ct:warning("enumerated value is not correct ~p~n",[V],S,
+ "enumerated value is not correct"),
V
end.
@@ -2925,7 +2934,8 @@ normalize_choice(S,{'CHOICE',{C,V}},CType,NameList) when is_atom(C) ->
{C,normalize_value(S,CT,{'DEFAULT',V},
[Name|NameList])};
Other ->
- asn1ct:warning("Wrong format of type/value ~p/~p~n",[Other,V],S),
+ asn1ct:warning("Wrong format of type/value ~p/~p~n",[Other,V],S,
+ "Wrong format of type/value"),
{C,V}
end;
normalize_choice(S,{'DEFAULT',ValueList},CType,NameList) when is_list(ValueList) ->
@@ -3101,7 +3111,8 @@ normalize_s_of(SorS,S,Value,Type,NameList) when is_list(Value) ->
List when is_list(List) ->
List;
_ ->
- asn1ct:warning("~p could not handle value ~p~n",[SorS,Value],S),
+ asn1ct:warning("~p could not handle value ~p~n",[SorS,Value],S,
+ "could not handle value"),
Value
end;
normalize_s_of(SorS,S,Value,Type,NameList)
@@ -3159,7 +3170,8 @@ get_normalized_value(S,Val,Type,Func,AddArg) ->
V2 = sort_val_if_set(AddArg,NewVal,Type),
call_Func(update_state(S,ExtM),V2,Type,Func,AddArg);
_ ->
- asn1ct:warning("default value not comparable ~p~n",[Val],S),
+ asn1ct:warning("default value not comparable ~p~n",[Val],S,
+ "default value not comparable"),
Val
end.
@@ -5756,7 +5768,8 @@ ascending_order_check1(S,TypeName,
[C1 = #'ComponentType'{tags=[{_,T}|_]},
C2 = #'ComponentType'{tags=[{_,T}|_]}|Rest]) ->
asn1ct:warning("Indistinct tag ~p in SET ~p, components ~p and ~p~n",
- [T,TypeName,C1#'ComponentType'.name,C2#'ComponentType'.name],S),
+ [T,TypeName,C1#'ComponentType'.name,C2#'ComponentType'.name],S,
+ "Indistinct tag in SET"),
ascending_order_check1(S,TypeName,[C2|Rest]);
ascending_order_check1(S,TypeName,
[C1 = #'ComponentType'{tags=[{'UNIVERSAL',T1}|_]},
@@ -5764,9 +5777,10 @@ ascending_order_check1(S,TypeName,
case (decode_type(T1) == decode_type(T2)) of
true ->
asn1ct:warning("Indistinct tags ~p and ~p in"
- " SET ~p, components ~p and ~p~n",
- [T1,T2,TypeName,C1#'ComponentType'.name,
- C2#'ComponentType'.name],S),
+ " SET ~p, components ~p and ~p~n",
+ [T1,T2,TypeName,C1#'ComponentType'.name,
+ C2#'ComponentType'.name],S,
+ "Indistinct tags and in SET"),
ascending_order_check1(S,TypeName,[C2|Rest]);
_ ->
ascending_order_check1(S,TypeName,[C2|Rest])
diff --git a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl
index e3be914af4..243ff234a7 100644
--- a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl
+++ b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl
@@ -877,13 +877,13 @@ gen_dec_choice(Erules,TopType, _ChTag, CompList, Ext) ->
emit([indent(9),"exit({error,{asn1,{invalid_choice_tag,",
{curr,else},"}}})",nl]);
_ ->
- emit([indent(9),"{asn1_ExtAlt, ?RT_BER:encode(",{curr,else},")}",nl])
+ emit([indent(9),"{asn1_ExtAlt, ?RT_BER:encode(",{curr,else},
+ asn1ct_gen:nif_parameter(),")}",nl])
end,
emit([indent(3),"end",nl]),
asn1ct_name:new(tag),
asn1ct_name:new(else).
-
gen_dec_choice_cases(_Erules,_TopType, []) ->
ok;
gen_dec_choice_cases(Erules,TopType, [H|T]) ->
@@ -1227,7 +1227,7 @@ gen_dec_call({typefield,_},_,_,_Cname,Type,BytesVar,Tag,_,_,false,_) ->
emit([nl,indent(6),"begin",nl]),
% emit([indent(9),{curr,opendec}," = ?RT_BER:decode_open_type(",
emit([indent(9),{curr,tmptlv}," = ?RT_BER:decode_open_type(",
- BytesVar,",",{asis,Tag},"),",nl]),
+ BytesVar,",",{asis,Tag},asn1ct_gen:nif_parameter(),"),",nl]),
% emit([indent(9),"{",{curr,tmptlv},",_} = ?RT_BER:decode(",
% {curr,opendec},"),",nl]),
@@ -1242,7 +1242,8 @@ gen_dec_call({typefield,_},_,_,_Cname,Type,BytesVar,Tag,_,_,false,_) ->
emit([indent(9),"end",nl,indent(6),"end",nl]),
[];
gen_dec_call({typefield,_},_,_,Cname,Type,BytesVar,Tag,_,_,_DecObjInf,OptOrMandComp) ->
- emit(["?RT_BER:decode_open_type(",BytesVar,",",{asis,Tag},")"]),
+ emit(["?RT_BER:decode_open_type(",BytesVar,",",{asis,Tag},
+ asn1ct_gen:nif_parameter(),")"]),
RefedFieldName =
% asn1ct_gen:get_constraint(Type#type.constraint,
% tableconstraint_info),
@@ -1250,7 +1251,8 @@ gen_dec_call({typefield,_},_,_,Cname,Type,BytesVar,Tag,_,_,_DecObjInf,OptOrMandC
[{Cname,RefedFieldName,asn1ct_gen:mk_var(asn1ct_name:curr(term)),
asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
gen_dec_call({objectfield,PrimFieldName,PFNList},_,_,Cname,_,BytesVar,Tag,_,_,_,OptOrMandComp) ->
- emit(["?RT_BER:decode_open_type(",BytesVar,",",{asis,Tag},")"]),
+ emit(["?RT_BER:decode_open_type(",BytesVar,",",{asis,Tag},
+ asn1ct_gen:nif_parameter(),")"]),
[{Cname,{PrimFieldName,PFNList},asn1ct_gen:mk_var(asn1ct_name:curr(term)),
asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
gen_dec_call(InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,PrimOptOrMand,
diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl
index d6f23aca06..e07680f10b 100644
--- a/lib/asn1/src/asn1ct_constructed_per.erl
+++ b/lib/asn1/src/asn1ct_constructed_per.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -73,16 +73,23 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) ->
_ ->
ok
end,
- case {Optionals = optionals(to_textual_order(CompList)),CompList} of
- {[],EmptyCL} when EmptyCL == {[],[],[]};EmptyCL == {[],[]};EmptyCL == [] ->
+ case {Optionals = optionals(to_textual_order(CompList)),CompList,
+ is_optimized(Erule)} of
+ {[],EmptyCL,_} when EmptyCL == {[],[],[]};EmptyCL == {[],[]};EmptyCL == [] ->
emit(["%%Variable setting just to eliminate ",
"compiler warning for unused vars!",nl,
"_Val = ",{curr,val},",",nl]);
- {[],_} ->
+ {[],_,_} ->
emit([{next,val}," = ?RT_PER:list_to_record("]),
emit(["'",asn1ct_gen:list2rname(Typename),"'"]),
emit([", ",{curr,val},"),",nl]);
- _ ->
+ {_,_,true} ->
+ gen_fixoptionals(Optionals),
+ FixOpts = param_map(fun(Var) ->
+ {var,Var}
+ end,asn1ct_name:all(fixopt)),
+ emit({"{",{next,val},",Opt} = {",{curr,val},",[",FixOpts,"]},",nl});
+ {_,_,false} ->
Fixoptcall = ",Opt} = ?RT_PER:fixoptionals(",
emit({"{",{next,val},Fixoptcall,
{asis,Optionals},",",length(Optionals),
@@ -255,7 +262,7 @@ gen_decode_constructed(Erules,Typename,D) when is_record(D,type) ->
_ -> false
end
end,
- case lists:any(F,CompList) of
+ case lists:any(F,flat_complist(CompList)) of
true -> % when component relation constraint establish
%% relation from a component to another components
%% subtype component
@@ -439,9 +446,7 @@ gen_encode_sof(Erule,Typename,SeqOrSetOf,D) when is_record(D,type) ->
_->
""
end,
- emit({nl,indent(3),"?RT_PER:encode_length(",
- {asis,SizeConstraint},
- ",length(Val)),",nl}),
+ gen_encode_length(SizeConstraint, is_optimized(Erule)),
emit({indent(3),"'enc_",asn1ct_gen:list2name(Typename),
"_components'(Val",ObjFun,", [])"}),
emit({nl,"].",nl}),
@@ -453,6 +458,42 @@ gen_encode_sof(Erule,Typename,SeqOrSetOf,D) when is_record(D,type) ->
end,
gen_encode_sof_components(Erule,Typename,SeqOrSetOf,NewComponentType).
+
+%% Logic copied from asn1_per_bin_rt2ct:encode_constrained_number
+gen_encode_length({Lb,Ub},true) when Ub =< 65535, Lb >= 0 ->
+ Range = Ub - Lb + 1,
+ V2 = ["(length(Val) - ",Lb,")"],
+ Encode = if
+ Range == 1 ->
+ "[]";
+ Range == 2 ->
+ {"[",V2,"]"};
+ Range =< 4 ->
+ {"[10,2,",V2,"]"};
+ Range =< 8 ->
+ {"[10,3,",V2,"]"};
+ Range =< 16 ->
+ {"[10,4,",V2,"]"};
+ Range =< 32 ->
+ {"[10,5,",V2,"]"};
+ Range =< 64 ->
+ {"[10,6,",V2,"]"};
+ Range =< 128 ->
+ {"[10,7,",V2,"]"};
+ Range =< 255 ->
+ {"[10,8,",V2,"]"};
+ Range =< 256 ->
+ {"[20,1,",V2,"]"};
+ Range =< 65536 ->
+ {"[20,2,<<",V2,":16>>]"};
+ true ->
+ {"?RT_PER:encode_length(",{asis,{Lb,Ub}},",length(Val))"}
+ end,
+ emit({nl,Encode,",",nl});
+gen_encode_length(SizeConstraint,_) ->
+ emit({nl,indent(3),"?RT_PER:encode_length(",
+ {asis,SizeConstraint},",length(Val)),",nl}).
+
gen_decode_sof(Erules,Typename,SeqOrSetOf,D) when is_record(D,type) ->
asn1ct_name:start(),
{_SeqOrSetOf,ComponentType} = D#type.def,
@@ -469,7 +510,8 @@ gen_decode_sof(Erules,Typename,SeqOrSetOf,D) when is_record(D,type) ->
_ ->
""
end,
- emit({nl,"{Num,Bytes1} = ?RT_PER:decode_length(Bytes,",{asis,SizeConstraint},"),",nl}),
+ gen_decode_length(SizeConstraint,
+ is_optimized(Erules)),
emit({"'dec_",asn1ct_gen:list2name(Typename),
"_components'(Num, Bytes1, telltype",ObjFun,", []).",nl}),
NewComponentType =
@@ -480,6 +522,41 @@ gen_decode_sof(Erules,Typename,SeqOrSetOf,D) when is_record(D,type) ->
end,
gen_decode_sof_components(Erules,Typename,SeqOrSetOf,NewComponentType).
+%% Logic copied from asn1_per_bin_rt2ct:decode_constrained_number
+gen_decode_length({Lb,Ub},true) when Ub =< 65535, Lb >= 0 ->
+ Range = Ub - Lb + 1,
+ Call = if
+ Range == 1 ->
+ "{0,Bytes}";
+ Range == 2 ->
+ "?RT_PER:getbits(Bytes,1)";
+ Range =< 4 ->
+ "?RT_PER:getbits(Bytes,2)";
+ Range =< 8 ->
+ "?RT_PER:getbits(Bytes,3)";
+ Range =< 16 ->
+ "?RT_PER:getbits(Bytes,4)";
+ Range =< 32 ->
+ "?RT_PER:getbits(Bytes,5)";
+ Range =< 64 ->
+ "?RT_PER:getbits(Bytes,6)";
+ Range =< 128 ->
+ "?RT_PER:getbits(Bytes,7)";
+ Range =< 255 ->
+ "?RT_PER:getbits(Bytes,8)";
+ Range =< 256 ->
+ "?RT_PER:getoctets(Bytes,1)";
+ Range =< 65536 ->
+ "?RT_PER:getoctets(Bytes,2)";
+ true ->
+ ["exit({not_supported,{integer_range,",Range,"}}"]
+ end,
+ emit({nl,"{Val,Remain} = ",Call,",",nl}),
+ emit({nl,"{Num,Bytes1} = {Val+",Lb,",Remain},",nl});
+gen_decode_length(SizeConstraint,_) ->
+ emit({nl,"{Num,Bytes1} = ?RT_PER:decode_length(Bytes,",
+ {asis,SizeConstraint},"),",nl}).
+
gen_encode_sof_components(Erule,Typename,SeqOrSetOf,Cont) ->
{ObjFun,ObjFun_Var} =
case Cont#type.tablecinf of
@@ -636,6 +713,27 @@ gen_dec_extension_value(_) ->
emit({"{Ext,",{next,bytes},"} = ?RT_PER:getext(",{curr,bytes},")"}),
asn1ct_name:new(bytes).
+gen_fixoptionals([{Pos,Def}|R]) ->
+ asn1ct_name:new(fixopt),
+ emit({{curr,fixopt}," = case element(",{asis,Pos},",",{curr,val},") of",nl,
+ "asn1_DEFAULT -> 0;",nl,
+ {asis,Def}," -> 0;",nl,
+ "_ -> 1",nl,
+ "end,",nl}),
+ gen_fixoptionals(R);
+gen_fixoptionals([Pos|R]) ->
+ gen_fixoptionals([{Pos,asn1_NOVALUE}|R]);
+gen_fixoptionals([]) ->
+ ok.
+
+
+param_map(Fun, [H]) ->
+ [Fun(H)];
+param_map(Fun, [H|T]) ->
+ [Fun(H),","|param_map(Fun,T)].
+
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Produce a list with positions (in the Value record) where
%% there are optional components, start with 2 because first element
@@ -922,7 +1020,7 @@ gen_enc_line(Erule,TopType,Cname,Type,Element, _Pos,DynamicEnc,Ext) ->
end,
case Ext of
{ext,_Ep2,_} ->
- emit(["))"]);
+ emit("))");
_ -> true
end.
gen_dec_components_call(Erule,TopType,{Root1,ExtList,Root2},MaybeComma,DecInfObj,Ext,NumberOfOptionals) ->
@@ -1493,6 +1591,11 @@ emit_extaddgroupTerms(VarSeries,[_|Rest]) ->
emit_extaddgroupTerms(VarSeries,Rest);
emit_extaddgroupTerms(_,[]) ->
ok.
+
+flat_complist({Rl1,El,Rl2}) -> Rl1 ++ El ++ Rl2;
+flat_complist({Rl,El}) -> Rl ++ El;
+flat_complist(CompList) -> CompList.
+
wrap_compList({Root1,Ext,Root2}) ->
{Root1,wrap_extensionAdditionGroups(Ext),Root2};
wrap_compList({Root1,Ext}) ->
diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl
index e49829d82f..0f8833f716 100644
--- a/lib/asn1/src/asn1ct_gen.erl
+++ b/lib/asn1/src/asn1ct_gen.erl
@@ -47,6 +47,7 @@
un_hyphen_var/1]).
-export([gen_encode_constructed/4,
gen_decode_constructed/4]).
+-export([nif_parameter/0]).
%% pgen(Outfile, Erules, Module, TypeOrVal, Options)
%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module
@@ -938,13 +939,13 @@ pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
NoFinalPadding = lists:member(no_final_padding,get(encoding_options)),
Call = case Erules of
per -> "?RT_PER:complete(encode_disp(Type,Data))";
- per_bin -> "?RT_PER:complete(encode_disp(Type,Data))";
+ per_bin -> ["?RT_PER:complete(encode_disp(Type,Data))"];
ber -> "encode_disp(Type,Data)";
ber_bin -> "encode_disp(Type,Data)";
ber_bin_v2 -> "encode_disp(Type,Data)";
uper_bin when NoFinalPadding == true ->
"?RT_PER:complete_NFP(encode_disp(Type,Data))";
- uper_bin -> "?RT_PER:complete(encode_disp(Type,Data))"
+ uper_bin -> ["?RT_PER:complete(encode_disp(Type,Data))"]
end,
EncWrap = case Erules of
ber -> "wrap_encode(Bytes)";
@@ -974,7 +975,7 @@ pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
% case Erules of
% ber_bin_v2 ->
% emit(["decode(Type,Data0) ->",nl]),
-% emit(["{Data,_RestBin} = ?RT_BER:decode(Data0",driver_parameter(),"),",nl]);
+% emit(["{Data,_RestBin} = ?RT_BER:decode(Data0",nif_parameter(),"),",nl]);
% _ ->
% emit(["decode(Type,Data) ->",nl])
% end,
@@ -991,10 +992,10 @@ pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
{ber_bin_v2,false} ->
io_lib:format("~s~s~s~n",
["element(1,?RT_BER:decode(Data",
- driver_parameter(),"))"]);
+ nif_parameter(),"))"]);
{ber_bin_v2,true} ->
emit(["{Data,Rest} = ?RT_BER:decode(Data0",
- driver_parameter(),"),",nl]),
+ nif_parameter(),"),",nl]),
"Data";
_ ->
"Data"
@@ -1130,13 +1131,8 @@ gen_decode_partial_incomplete(Erule) when Erule == ber;Erule==ber_bin;
"Data) of",nl]),
EmitCaseClauses(),
emit(["decode_part(Type,Data0) ->",nl]),
- Driver =
- case lists:member(driver,get(encoding_options)) of
- true ->
- ",driver";
- _ -> ""
- end,
- emit([" case catch decode_inc_disp(Type,element(1,?RT_BER:decode(Data0",Driver,"))) of",nl]),
+ emit([" case catch decode_inc_disp(Type,element(1,"
+ "?RT_BER:decode(Data0",nif_parameter(),"))) of",nl]),
% " {Data,_RestBin} = ?RT_BER:decode(Data0),",nl,
% " case catch decode_inc_disp(Type,Data) of",nl]),
EmitCaseClauses();
@@ -1179,12 +1175,12 @@ gen_partial_inc_dispatcher([],_) ->
emit(["decode_partial_inc_disp(Type,_Data) ->",nl,
" exit({error,{asn1,{undefined_type,Type}}}).",nl]).
-driver_parameter() ->
+nif_parameter() ->
Options = get(encoding_options),
- case lists:member(driver,Options) of
- true ->
- ",driver";
- _ -> ""
+ case {lists:member(driver,Options),lists:member(nif,Options)} of
+ {true,_} -> ",nif";
+ {_,true} -> ",nif";
+ _ -> ""
end.
gen_wrapper() ->
@@ -1525,8 +1521,9 @@ gen_head(Erules,Mod,Hrl) ->
emit({"-module('",Mod,"').",nl}),
put(currmod,Mod),
%emit({"-compile(export_all).",nl}),
- case Hrl of
- 0 -> true;
+ case {Hrl,lists:member(inline,get(encoding_options))} of
+ {0,_} -> true;
+ {_,true} -> true;
_ ->
emit({"-include(\"",Mod,".hrl\").",nl})
end,
diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
index 9ec458e351..781271bae7 100644
--- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
+++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
@@ -416,7 +416,7 @@ gen_decode_selected(Erules,Type,FuncName) ->
end,
emit([" case ?RT_BER:decode_selective(",{asis,Pattern},",Bin) of",nl,
" {ok,Bin2} when is_binary(Bin2) ->",nl,
- " {Tlv,_} = ?RT_BER:decode(Bin2),",nl]),
+ " {Tlv,_} = ?RT_BER:decode(Bin2",asn1ct_gen:nif_parameter(),"),",nl]),
emit("{ok,"),
gen_decode_selected_type(Erules,Type),
emit(["};",nl," Err -> exit({error,{selctive_decode,Err}})",nl,
@@ -708,7 +708,7 @@ gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Form,OptOrMand) ->
'ASN1_OPEN_TYPE' ->
emit(["?RT_BER:decode_open_type_as_binary(",
BytesVar,","]),
- add_func({decode_open_type_as_binary,2});
+ add_func({decode_open_type_as_binary,3});
#'ObjectClassFieldType'{} ->
case asn1ct_gen:get_inner(Att#type.def) of
{fixedtypevaluefield,_,InnerType} ->
@@ -716,7 +716,7 @@ gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Form,OptOrMand) ->
'ASN1_OPEN_TYPE' ->
emit(["?RT_BER:decode_open_type_as_binary(",
BytesVar,","]),
- add_func({decode_open_type_as_binary,2});
+ add_func({decode_open_type_as_binary,3});
Other ->
exit({'can not decode' ,Other})
end;
@@ -728,13 +728,13 @@ gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Form,OptOrMand) ->
{_,#'ObjectClassFieldType'{}} ->
case asn1ct_gen:get_inner(Att#type.def) of
'ASN1_OPEN_TYPE' ->
- emit([{asis,DoTag},")"]);
+ emit([{asis,DoTag},asn1ct_gen:nif_parameter(),")"]);
_ -> ok
end;
{{string,TagStr},'ASN1_OPEN_TYPE'} ->
- emit([TagStr,")"]);
+ emit([TagStr,asn1ct_gen:nif_parameter(),")"]);
{_,'ASN1_OPEN_TYPE'} ->
- emit([{asis,DoTag},")"]);
+ emit([{asis,DoTag},asn1ct_gen:nif_parameter(),")"]);
{{string,TagStr},_} ->
emit([TagStr,")"]);
_ when is_list(DoTag) ->
@@ -1064,7 +1064,7 @@ emit_tlv_format_function() ->
end.
emit_tlv_format_function1() ->
emit(["tlv_format(Bytes) when is_binary(Bytes) ->",nl,
- " {Tlv,_}=?RT_BER:decode(Bytes),",nl,
+ " {Tlv,_}=?RT_BER:decode(Bytes",asn1ct_gen:nif_parameter(),"),",nl,
" Tlv;",nl,
"tlv_format(Bytes) ->",nl,
" Bytes.",nl]).
@@ -1502,13 +1502,14 @@ gen_objset_dec(Erules,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
_ClFields,_NthObj) ->
emit(["'getdec_",ObjSetName,"'(_, _) ->",nl]),
emit([indent(2),"fun(_,Bytes, _RestPrimFieldName) ->",nl]),
+
case Erules of
ber_bin_v2 ->
emit([indent(4),"case Bytes of",nl,
indent(6),"Bin when is_binary(Bin) -> ",nl,
indent(8),"Bin;",nl,
indent(6),"_ ->",nl,
- indent(8),"?RT_BER:encode(Bytes)",nl,
+ indent(8),"?RT_BER:encode(Bytes",driver_parameter(),")",nl,
indent(4),"end",nl]);
_ ->
emit([indent(6),"Len = case Bytes of",nl,indent(9),
@@ -1521,6 +1522,14 @@ gen_objset_dec(Erules,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
gen_objset_dec(_,_,_,[],_,_,_) ->
ok.
+driver_parameter() ->
+ Options = get(encoding_options),
+ case {lists:member(driver,Options),lists:member(nif,Options)} of
+ {true,_} -> ",nif";
+ {_,true} -> ",nif";
+ _ -> ",erlang"
+ end.
+
emit_default_getdec(ObjSetName,UniqueName) ->
emit(["'getdec_",ObjSetName,"'(",{asis,UniqueName},", ErrV) ->",nl]),
emit([indent(2), "fun(C,V,_) -> exit({{component,C},{value,V},{unique_name_and_value,",{asis,UniqueName},", ErrV}}) end"]).
diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl
index 8313cf1b60..b90a0adf81 100644
--- a/lib/asn1/src/asn1ct_gen_per.erl
+++ b/lib/asn1/src/asn1ct_gen_per.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -238,7 +238,8 @@ gen_encode_prim(Erules,D,DoTag,Value) when is_record(D,type) ->
"?RT_PER:complete(enc_~s(~s))",[Tname,Value]);
[#type{def=#'Externaltypereference'{type=Tname}}] ->
io_lib:format(
- "?RT_PER:complete(enc_~s(~s))",[Tname,Value]);
+ "?RT_PER:complete(enc_~s(~s))",
+ [Tname,Value]);
_ -> Value
end,
emit(["?RT_PER:encode_open_type(", {asis,Constraint}, ",",
diff --git a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
index 4f4fcfafc3..1a0a0e211d 100644
--- a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
+++ b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -230,7 +230,8 @@ gen_encode_prim(Erules,D,DoTag,Value) when is_record(D,type) ->
"?RT_PER:complete(enc_~s(~s))",[Tname,Value]);
[#type{def=#'Externaltypereference'{type=Tname}}] ->
io_lib:format(
- "?RT_PER:complete(enc_~s(~s))",[Tname,Value]);
+ "?RT_PER:complete(enc_~s(~s))",
+ [Tname,Value]);
_ -> Value
end,
emit(["?RT_PER:encode_open_type(", {asis,Constraint}, ",",
diff --git a/lib/asn1/src/asn1ct_value.erl b/lib/asn1/src/asn1ct_value.erl
index d9a7e5374a..d099376b1b 100644
--- a/lib/asn1/src/asn1ct_value.erl
+++ b/lib/asn1/src/asn1ct_value.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -435,15 +435,15 @@ get_encoding_rule(M) ->
open_type_value(ber) ->
[4,9,111,112,101,110,95,116,121,112,101];
open_type_value(ber_bin) ->
- [4,9,111,112,101,110,95,116,121,112,101];
-% <<4,9,111,112,101,110,95,116,121,112,101>>;
+% [4,9,111,112,101,110,95,116,121,112,101];
+ <<4,9,111,112,101,110,95,116,121,112,101>>;
open_type_value(ber_bin_v2) ->
- [4,9,111,112,101,110,95,116,121,112,101];
-% <<4,9,111,112,101,110,95,116,121,112,101>>;
+% [4,9,111,112,101,110,95,116,121,112,101];
+ <<4,9,111,112,101,110,95,116,121,112,101>>;
open_type_value(per) ->
"\n\topen_type"; %octet string value "open_type"
open_type_value(per_bin) ->
- "\n\topen_type";
+ <<"\n\topen_type">>;
% <<10,9,111,112,101,110,95,116,121,112,101>>;
open_type_value(_) ->
[4,9,111,112,101,110,95,116,121,112,101].
diff --git a/lib/asn1/src/asn1rt.erl b/lib/asn1/src/asn1rt.erl
index 9ef68efab5..d18f81346a 100644
--- a/lib/asn1/src/asn1rt.erl
+++ b/lib/asn1/src/asn1rt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The 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,12 +21,12 @@
%% Runtime functions for ASN.1 (i.e encode, decode)
--include("asn1_records.hrl").
-
-export([encode/2,encode/3,decode/3,load_driver/0,unload_driver/0,info/1]).
-export([utf8_binary_to_list/1,utf8_list_to_binary/1]).
+-deprecated([load_driver/0,unload_driver/0]).
+
encode(Module,{Type,Term}) ->
encode(Module,Type,Term).
@@ -46,38 +46,12 @@ decode(Module,Type,Bytes) ->
Result
end.
-%% asn1-1.6.8.1
-%% load_driver() ->
-%% asn1rt_driver_handler:load_driver(),
-%% receive
-%% driver_ready ->
-%% ok;
-%% Err={error,_Reason} ->
-%% Err;
-%% Error ->
-%% {error,Error}
-%% end.
-
-%% asn1-1.6.9
- load_driver() ->
- case catch asn1rt_driver_handler:load_driver() of
- ok ->
- ok;
- {error,{already_started,asn1}} ->
- ok;
- Err ->
- {error,Err}
- end.
-
+%% Remove in R16A
+load_driver() ->
+ ok.
unload_driver() ->
- case catch asn1rt_driver_handler:unload_driver() of
- ok ->
- ok;
- Error ->
- {error,Error}
- end.
-
+ ok.
info(Module) ->
case catch apply(Module,info,[]) of
diff --git a/lib/asn1/src/asn1rt_ber_bin_v2.erl b/lib/asn1/src/asn1rt_ber_bin_v2.erl
index a3bb570282..17e66f77c9 100644
--- a/lib/asn1/src/asn1rt_ber_bin_v2.erl
+++ b/lib/asn1/src/asn1rt_ber_bin_v2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The 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,7 +21,7 @@
%% encoding / decoding of BER
--export([decode/1, decode/2, match_tags/2, encode/1]).
+-export([decode/1, decode/2, match_tags/2, encode/1, encode/2]).
-export([fixoptionals/2, cindex/3,
list_to_record/2,
encode_tag_val/1,
@@ -49,11 +49,13 @@
decode_tag_and_length/1]).
-export([encode_open_type/1,encode_open_type/2,
- decode_open_type/2,decode_open_type_as_binary/2]).
+ decode_open_type/2,decode_open_type/3,
+ decode_open_type_as_binary/2,
+ decode_open_type_as_binary/3]).
-export([decode_primitive_incomplete/2,decode_selective/2]).
-
--include("asn1_records.hrl").
+
+-export([is_nif_loadable/0]).
% the encoding of class of tag bits 8 and 7
-define(UNIVERSAL, 0).
@@ -125,15 +127,28 @@
% encode(Tlv) ->
% encode_constructed(Tlv).
-encode([Tlv]) ->
- encode(Tlv);
-encode({TlvTag,TlvVal}) when is_list(TlvVal) ->
+encode(Tlv) ->
+ encode(Tlv,erlang).
+
+encode(Tlv,_) when is_binary(Tlv) ->
+ Tlv;
+encode([Tlv],Method) ->
+ encode(Tlv,Method);
+encode(Tlv, nif) ->
+ case is_nif_loadable() of
+ true ->
+ asn1rt_nif:encode_ber_tlv(Tlv);
+ false ->
+ encode_erl(Tlv)
+ end;
+encode(Tlv, _) ->
+ encode_erl(Tlv).
+
+encode_erl({TlvTag,TlvVal}) when is_list(TlvVal) ->
%% constructed form of value
encode_tlv(TlvTag,TlvVal,?CONSTRUCTED);
-encode({TlvTag,TlvVal}) ->
- encode_tlv(TlvTag,TlvVal,?PRIMITIVE);
-encode(Bin) when is_binary(Bin) ->
- Bin.
+encode_erl({TlvTag,TlvVal}) ->
+ encode_tlv(TlvTag,TlvVal,?PRIMITIVE).
encode_tlv(TlvTag,TlvVal,Form) ->
Tag = encode_tlv_tag(TlvTag,Form),
@@ -152,70 +167,61 @@ encode_tlv_val(Bin) ->
{Bin,size(Bin)}.
encode_tlv_list([Tlv|Tlvs],Acc) ->
- EncTlv = encode(Tlv),
+ EncTlv = encode_erl(Tlv),
encode_tlv_list(Tlvs,[EncTlv|Acc]);
encode_tlv_list([],Acc) ->
Bin=list_to_binary(lists:reverse(Acc)),
{Bin,size(Bin)}.
-%% asn1-1.6.8.1
-%% decode(B,driver) ->
-%% case catch port_control(asn1_driver_port,2,B) of
-%% Bin when is_binary(Bin) ->
-%% binary_to_term(Bin);
-%% List when is_list(List) -> handle_error(List,B);
-%% {'EXIT',{badarg,Reason}} ->
-%% asn1rt_driver_handler:load_driver(),
-%% receive
-%% driver_ready ->
-%% case catch port_control(asn1_driver_port,2,B) of
-%% Bin2 when is_binary(Bin2) -> binary_to_term(Bin2);
-%% List when is_list(List) -> handle_error(List,B);
-%% Error -> exit(Error)
-%% end;
-%% {error,Error} -> % error when loading driver
-%% %% the driver could not be loaded
-%% exit(Error);
-%% Error={port_error,Reason} ->
-%% exit(Error)
-%% end;
-%% {'EXIT',Reason} ->
-%% exit(Reason)
-%% end.
-
-%% asn1-1.6.9
-decode(B,driver) ->
- case catch control(?TLV_DECODE,B) of
- Bin when is_binary(Bin) ->
- binary_to_term(Bin);
- List when is_list(List) -> handle_error(List,B);
- {'EXIT',{badarg,_Reason}} ->
- case asn1rt:load_driver() of
- ok ->
- case control(?TLV_DECODE,B) of
- Bin when is_binary(Bin) -> binary_to_term(Bin);
- List when is_list(List) -> handle_error(List,B)
- end;
- Err ->
- Err
- end
- end.
+decode(B) ->
+ decode(B, erlang).
+%% asn1-1.7
+decode(B, nif) ->
+ case is_nif_loadable() of
+ true ->
+ case asn1rt_nif:decode_ber_tlv(B) of
+ {error, Reason} -> handle_error(Reason, B);
+ Else -> Else
+ end;
+ false ->
+ decode(B)
+ end;
+decode(B,erlang) when is_binary(B) ->
+ decode_primitive(B);
+decode(Tlv,erlang) ->
+ {Tlv,<<>>}.
+
+%% Have to check this since asn1 is not guaranteed to be available
+is_nif_loadable() ->
+ case application:get_env(asn1, nif_loadable) of
+ {ok,R} ->
+ R;
+ undefined ->
+ case catch code:load_file(asn1rt_nif) of
+ {module, asn1rt_nif} ->
+ application:set_env(asn1, nif_loadable, true),
+ true;
+ _Else ->
+ application:set_env(asn1, nif_loadable, false),
+ false
+ end
+ end.
handle_error([],_)->
exit({error,{asn1,{"memory allocation problem"}}});
-handle_error([$1|_],L) -> % error in driver
+handle_error({$1,_},L) -> % error in nif
exit({error,{asn1,L}});
-handle_error([$2|T],L) -> % error in driver due to wrong tag
+handle_error({$2,T},L) -> % error in nif due to wrong tag
exit({error,{asn1,{"bad tag after byte:",error_pos(T),L}}});
-handle_error([$3|T],L) -> % error in driver due to length error
+handle_error({$3,T},L) -> % error in driver due to length error
exit({error,{asn1,{"bad length field after byte:",
error_pos(T),L}}});
-handle_error([$4|T],L) -> % error in driver due to indefinite length error
+handle_error({$4,T},L) -> % error in driver due to indefinite length error
exit({error,{asn1,
{"indefinite length without end bytes after byte:",
error_pos(T),L}}});
-handle_error([$5|T],L) -> % error in driver due to indefinite length error
+handle_error({$5,T},L) -> % error in driver due to indefinite length error
exit({error,{asn1,{"bad encoded value after byte:",
error_pos(T),L}}});
handle_error(ErrL,L) ->
@@ -228,16 +234,6 @@ error_pos([B])->
error_pos([B|Bs]) ->
BS = 8 * length(Bs),
B bsl BS + error_pos(Bs).
-%% asn1-1.6.9
-control(Cmd, Data) ->
- Port = asn1rt_driver_handler:client_port(),
- erlang:port_control(Port, Cmd, Data).
-
-decode(Bin) when is_binary(Bin) ->
- decode_primitive(Bin);
-decode(Tlv) -> % assume it is a tlv
- {Tlv,<<>>}.
-
decode_primitive(Bin) ->
{Form,TagNo,V,Rest} = decode_tag_and_length(Bin),
@@ -796,20 +792,24 @@ encode_open_type(Val,Tag) ->
%% Value = binary with decoded data (which must be decoded again as some type)
%%
decode_open_type(Tlv, TagIn) ->
+ decode_open_type(Tlv, TagIn, erlang).
+decode_open_type(Tlv, TagIn, Method) ->
case match_tags(Tlv,TagIn) of
Bin when is_binary(Bin) ->
- {InnerTlv,_} = decode(Bin),
+ {InnerTlv,_} = decode(Bin,Method),
InnerTlv;
TlvBytes -> TlvBytes
end.
-decode_open_type_as_binary(Tlv,TagIn)->
+decode_open_type_as_binary(Tlv, TagIn) ->
+ decode_open_type_as_binary(Tlv, TagIn, erlang).
+decode_open_type_as_binary(Tlv,TagIn, Method)->
case match_tags(Tlv,TagIn) of
V when is_binary(V) ->
V;
- [Tlv2] -> encode(Tlv2);
- Tlv2 -> encode(Tlv2)
+ [Tlv2] -> encode(Tlv2, Method);
+ Tlv2 -> encode(Tlv2, Method)
end.
%%===============================================================================
@@ -1056,7 +1056,7 @@ encode_real(C,Val, TagIn) when is_tuple(Val); is_list(Val) ->
encode_real(C,Val) ->
- ?RT_COMMON:encode_real(C,Val).
+ asn1rt_ber_bin:encode_real(C,Val).
%%============================================================================
@@ -1081,7 +1081,7 @@ decode_real_notag(Buffer) ->
{_T,_V} ->
exit({error,{asn1,{real_not_in_primitive_form,Buffer}}})
end,
- {Val,_Rest,Len} = ?RT_COMMON:decode_real(Buffer,Len),
+ {Val,_Rest,Len} = asn1rt_ber_bin:decode_real(Buffer,Len),
Val.
%% exit({error,{asn1, {unimplemented,real}}}).
%% decode_real2(Buffer, Form, size(Buffer)).
@@ -1577,14 +1577,12 @@ e_object_identifier(V) when is_tuple(V) ->
e_object_identifier([E1, E2 | Tail]) ->
Head = 40*E1 + E2, % wow!
{H,Lh} = mk_object_val(Head),
- {R,Lr} = enc_obj_id_tail(Tail, [], 0),
+ {R,Lr} = lists:mapfoldl(fun enc_obj_id_tail/2,0,Tail),
{[H|R], Lh+Lr}.
-enc_obj_id_tail([], Ack, Len) ->
- {lists:reverse(Ack), Len};
-enc_obj_id_tail([H|T], Ack, Len) ->
+enc_obj_id_tail(H, Len) ->
{B, L} = mk_object_val(H),
- enc_obj_id_tail(T, [B|Ack], Len+L).
+ {B,Len+L}.
%%%%%%%%%%%
diff --git a/lib/asn1/src/asn1rt_check.erl b/lib/asn1/src/asn1rt_check.erl
index 59a74a7078..d9856901b8 100644
--- a/lib/asn1/src/asn1rt_check.erl
+++ b/lib/asn1/src/asn1rt_check.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The 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,8 +19,6 @@
%%
-module(asn1rt_check).
--include("asn1_records.hrl").
-
-export([check_bool/2,
check_int/3,
check_bitstring/3,
@@ -311,7 +309,7 @@ transform_to_EXTERNAL1990([Data_val_desc,Data_value],Acc) when is_list(Data_valu
Data_val_desc|Acc]));
transform_to_EXTERNAL1990([Data_val_desc,Data_value],Acc)
when is_binary(Data_value)->
- list_to_tuple(lists:reverse([{'octet-aligned',binary_to_list(Data_value)},
+ list_to_tuple(lists:reverse([{'single-ASN1-type',Data_value},
Data_val_desc|Acc]));
transform_to_EXTERNAL1990([Data_value],Acc) when is_list(Data_value)->
list_to_tuple(lists:reverse([{'octet-aligned',Data_value}|Acc])).
diff --git a/lib/asn1/src/asn1rt_driver_handler.erl b/lib/asn1/src/asn1rt_driver_handler.erl
deleted file mode 100644
index 146d0043f9..0000000000
--- a/lib/asn1/src/asn1rt_driver_handler.erl
+++ /dev/null
@@ -1,144 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, 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(asn1rt_driver_handler).
-
--include("asn1_records.hrl").
-
--export([load_driver/0,unload_driver/0,client_port/0]).
-
-%% Internal exports
--export([init/2]).
-
-%% Macros
--define(port_names,
- { asn1_drv01, asn1_drv02, asn1_drv03, asn1_drv04,
- asn1_drv05, asn1_drv06, asn1_drv07, asn1_drv08,
- asn1_drv09, asn1_drv10, asn1_drv11, asn1_drv12,
- asn1_drv13, asn1_drv14, asn1_drv15, asn1_drv16 }).
-
-%%% --------------------------------------------------------
-%%% Interface Functions.
-%%% --------------------------------------------------------
-load_driver() ->
- load_driver(noreason).
-
-load_driver(Reason) ->
- Ref = make_ref(),
- case whereis(asn1_driver_owner) of % to prevent unnecessary spawn
- Pid when is_pid(Pid) ->
- asn1_driver_owner ! {self(),Ref,are_you_ready},
- receive
- {Ref,driver_ready} ->
- ok
- after 10000 ->
- {error,{timeout,waiting_for_drivers}}
- end;
- _ ->
- {_,Mref} = spawn_monitor(asn1rt_driver_handler, init, [self(),Ref]),
- receive
- {'DOWN', Mref, _, _, NewReason} ->
- case NewReason of
- Reason -> {error,Reason};
- _ -> load_driver(NewReason)
- end;
- {Ref,driver_ready} ->
- erlang:demonitor(Mref),
- ok;
- {Ref,Error = {error,_Reason}} ->
- erlang:demonitor(Mref),
- Error
- after 10000 -> %% 10 seconds
- {error,{timeout,waiting_for_drivers}}
- end
- end.
-
-init(FromPid,FromRef) ->
- case catch register(asn1_driver_owner,self()) of
- true -> true;
- _Other -> exit(normal)
- end,
- Dir = filename:join([code:priv_dir(asn1),"lib"]),
- case catch erl_ddll:load_driver(Dir,asn1_erl_drv) of
- ok ->
- Result = open_named_ports(),
- catch (FromPid ! {FromRef,Result}),
- loop(Result);
- {error,Err} -> % if erl_ddll:load_driver fails
- ForErr = erl_ddll:format_error(Err),
- OSDir = filename:join(Dir,erlang:system_info(system_architecture)),
- case catch erl_ddll:load_driver(OSDir,asn1_erl_drv) of
- ok ->
- Result = open_named_ports(),
- catch (FromPid ! {FromRef,Result}),
- loop(Result);
- {error,Err2} ->
-% catch (FromPid ! {FromRef,Error})
- ForErr2 = erl_ddll:format_error(Err2),
- catch (FromPid ! {FromRef,{error,{{Dir,ForErr},{OSDir,ForErr2}}}})
- end
- end.
-
-
-open_named_ports() ->
- open_named_ports(size(?port_names)).
-
-open_named_ports(0) ->
- driver_ready;
-open_named_ports(N) ->
- case catch open_port({spawn,"asn1_erl_drv"},[]) of
- {'EXIT',Reason} ->
- {error,{port_error,Reason}};
- Port ->
- register(element(N,?port_names),Port),
- open_named_ports(N-1)
- end.
-
-loop(Result) ->
- receive
- {_FromPid,_FromRef,unload} ->
- close_ports(size(?port_names)),
- erl_ddll:unload_driver(asn1_erl_drv),
- ok;
- {FromPid,FromRef,are_you_ready} ->
- catch (FromPid ! {FromRef,driver_ready}),
- loop(Result);
- _ ->
- loop(Result)
- end.
-
-unload_driver() ->
- case whereis(asn1_driver_owner) of
- Pid when is_pid(Pid) ->
- Pid ! {self(),make_ref(),unload},
- ok;
- _ ->
- ok
- end.
-
-close_ports(0) ->
- ok;
-close_ports(N) ->
- element(N,?port_names) ! {self(), close}, %% almost same as port_close(Name)
- close_ports(N-1).
-
-client_port() ->
- element(erlang:system_info(scheduler_id) rem size(?port_names) + 1,
- ?port_names).
diff --git a/lib/asn1/src/asn1rt_nif.erl b/lib/asn1/src/asn1rt_nif.erl
new file mode 100644
index 0000000000..de1fb94816
--- /dev/null
+++ b/lib/asn1/src/asn1rt_nif.erl
@@ -0,0 +1,87 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(asn1rt_nif).
+
+%% Nif interface for asn1
+
+-export([encode_per_complete/1,
+ decode_ber_tlv/1,
+ encode_ber_tlv/1]).
+
+-on_load(load_nif/0).
+
+-define(ASN1_NIF_VSN,1).
+
+load_nif() ->
+ LibBaseName = "asn1_erl_nif",
+ PrivDir = code:priv_dir(asn1),
+ 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, ?ASN1_NIF_VSN) of
+ ok -> ok;
+ {error, {load_failed, _}}=Error1 ->
+ ArchLibDir =
+ filename:join([PrivDir, "lib",
+ erlang:system_info(system_architecture)]),
+ Candidate =
+ filelib:wildcard(filename:join([ArchLibDir,LibName ++ "*" ])),
+ case Candidate of
+ [] -> Error1;
+ _ ->
+ ArchLib = filename:join([ArchLibDir, LibName]),
+ erlang:load_nif(ArchLib, ?ASN1_NIF_VSN)
+ end;
+ Error1 -> Error1
+ end,
+ case Status of
+ ok -> ok;
+ {error, {E, Str}} ->
+ error_logger:error_msg("Unable to load asn1 nif library. "
+ "Failed with error:~n\"~p, ~s\"~n",[E,Str]),
+ Status
+ end.
+
+encode_per_complete(_TagValueList) ->
+ erlang:nif_error({nif_not_loaded,module,?MODULE,line,?LINE}).
+
+decode_ber_tlv(_Binary) ->
+ erlang:nif_error({nif_not_loaded,module,?MODULE,line,?LINE}).
+
+encode_ber_tlv(_TagValueList) ->
+ erlang:nif_error({nif_not_loaded,module,?MODULE,line,?LINE}).
diff --git a/lib/asn1/src/asn1rt_per_bin.erl b/lib/asn1/src/asn1rt_per_bin.erl
index 6bbca26209..a124c7553d 100644
--- a/lib/asn1/src/asn1rt_per_bin.erl
+++ b/lib/asn1/src/asn1rt_per_bin.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -57,7 +57,7 @@
encode_NumericString/2, decode_NumericString/2,
encode_ObjectDescriptor/2, decode_ObjectDescriptor/1
]).
--export([complete_bytes/1]).
+-export([complete_bytes/1, getbits/2, getoctets/2]).
-define('16K',16384).
-define('32K',32768).
diff --git a/lib/asn1/src/asn1rt_per_bin_rt2ct.erl b/lib/asn1/src/asn1rt_per_bin_rt2ct.erl
index f4aecf9322..c7ead680ce 100644
--- a/lib/asn1/src/asn1rt_per_bin_rt2ct.erl
+++ b/lib/asn1/src/asn1rt_per_bin_rt2ct.erl
@@ -1734,143 +1734,24 @@ get_constraint(C,Key) ->
-ifdef(nodriver).
complete(L) ->
- case complete1(L) of
- {[],[]} ->
- <<0>>;
- {Acc,[]} ->
- Acc;
- {Acc,Bacc} ->
- [Acc|complete_bytes(Bacc)]
- end.
-
-
-% this function builds the ugly form of lists [E1|E2] to avoid having to reverse it at the end.
-% this is done because it is efficient and that the result always will be sent on a port or
-% converted by means of list_to_binary/1
- complete1(InList) when is_list(InList) ->
- complete1(InList,[],[]);
- complete1(InList) ->
- complete1([InList],[],[]).
-
- complete1([],Acc,Bacc) ->
- {Acc,Bacc};
- complete1([H|T],Acc,Bacc) when is_list(H) ->
- {NewH,NewBacc} = complete1(H,Acc,Bacc),
- complete1(T,NewH,NewBacc);
-
- complete1([{octets,Bin}|T],Acc,[]) ->
- complete1(T,[Acc|Bin],[]);
-
- complete1([{octets,Bin}|T],Acc,Bacc) ->
- complete1(T,[Acc|[complete_bytes(Bacc),Bin]],[]);
-
- complete1([{debug,_}|T], Acc,Bacc) ->
- complete1(T,Acc,Bacc);
-
- complete1([{bits,N,Val}|T],Acc,Bacc) ->
- complete1(T,Acc,complete_update_byte(Bacc,Val,N));
-
- complete1([{bit,Val}|T],Acc,Bacc) ->
- complete1(T,Acc,complete_update_byte(Bacc,Val,1));
-
- complete1([align|T],Acc,[]) ->
- complete1(T,Acc,[]);
- complete1([align|T],Acc,Bacc) ->
- complete1(T,[Acc|complete_bytes(Bacc)],[]);
- complete1([{0,Bin}|T],Acc,[]) when is_binary(Bin) ->
- complete1(T,[Acc|Bin],[]);
- complete1([{Unused,Bin}|T],Acc,[]) when is_integer(Unused),is_binary(Bin) ->
- Size = size(Bin)-1,
- <<Bs:Size/binary,B>> = Bin,
- NumBits = 8-Unused,
- complete1(T,[Acc|Bs],[[B bsr Unused]|NumBits]);
- complete1([{Unused,Bin}|T],Acc,Bacc) when is_integer(Unused),is_binary(Bin) ->
- Size = size(Bin)-1,
- <<Bs:Size/binary,B>> = Bin,
- NumBits = 8 - Unused,
- Bf = complete_bytes(Bacc),
- complete1(T,[Acc|[Bf,Bs]],[[B bsr Unused]|NumBits]).
-
-
- complete_update_byte([],Val,Len) ->
- complete_update_byte([[0]|0],Val,Len);
- complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) when NumBits + Len == 8 ->
- [[0,((Byte bsl Len) + Val) band 255|Bacc]|0];
- complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) when NumBits + Len > 8 ->
- Rem = 8 - NumBits,
- Rest = Len - Rem,
- complete_update_byte([[0,((Byte bsl Rem) + (Val bsr Rest)) band 255 |Bacc]|0],Val,Rest);
- complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) ->
- [[((Byte bsl Len) + Val) band 255|Bacc]|NumBits+Len].
-
-
- complete_bytes([[Byte|Bacc]|0]) ->
- lists:reverse(Bacc);
- complete_bytes([[Byte|Bacc]|NumBytes]) ->
- lists:reverse([(Byte bsl (8-NumBytes)) band 255|Bacc]);
- complete_bytes([]) ->
- [].
+ erlang_complete(L).
-else.
-%% asn1-1.6.8.1_dev
-%% complete(L) ->
-%% case catch port_control(asn1_driver_port,1,L) of
-%% Bin when is_binary(Bin) ->
-%% Bin;
-%% List when is_list(List) -> handle_error(List,L);
-%% {'EXIT',{badarg,Reason}} ->
-%% asn1rt_driver_handler:load_driver(),
-%% receive
-%% driver_ready ->
-%% case catch port_control(asn1_driver_port,1,L) of
-%% Bin2 when is_binary(Bin2) -> Bin2;
-%% List when is_list(List) -> handle_error(List,L);
-%% {'EXIT',Reason2={badarg,_R}} ->
-%% exit({"failed to call driver probably due to bad asn1 value",Reason2});
-%% Reason2 -> exit(Reason2)
-%% end;
-%% {error,Error} -> % error when loading driver
-%% %% the driver could not be loaded
-%% exit(Error);
-%% Error={port_error,Reason} ->
-%% exit(Error)
-%% end;
-%% {'EXIT',Reason} ->
-%% exit(Reason)
-%% end.
-
-%% asn1-1.6.9
+%% asn1-1.7
complete(L) ->
- case catch control(?COMPLETE_ENCODE,L) of
- Bin when is_binary(Bin) ->
- Bin;
- List when is_list(List) -> handle_error(List,L);
- {'EXIT',{badarg,_Reason}} ->
- case asn1rt:load_driver() of
- ok ->
- case control(?COMPLETE_ENCODE,L) of
- Bin when is_binary(Bin) ->Bin;
- List when is_list(List) -> handle_error(List,L)
- end;
- Err ->
- Err
- end
+ case asn1rt_nif:encode_per_complete(L) of
+ {error, Reason} -> handle_error(Reason, L);
+ Else when is_binary(Else) -> Else
end.
-
handle_error([],_)->
exit({error,{asn1,{"memory allocation problem in driver"}}});
-handle_error("1",L) -> % error in complete in driver
+handle_error($1,L) -> % error in complete in driver
exit({error,{asn1,L}});
handle_error(ErrL,L) ->
exit({error,{asn1,ErrL,L}}).
-%% asn1-1.6.9
-control(Cmd, Data) ->
- Port = asn1rt_driver_handler:client_port(),
- erlang:port_control(Port, Cmd, Data).
-
-endif.
diff --git a/lib/asn1/test/Makefile b/lib/asn1/test/Makefile
index 4f3776e478..7ecd544d4b 100644
--- a/lib/asn1/test/Makefile
+++ b/lib/asn1/test/Makefile
@@ -194,7 +194,7 @@ release_tests_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)/asn1_bin_v2_SUITE_data
$(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)
$(INSTALL_DATA) asn1.spec asn1.cover $(INSTALL_PROGS) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -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
diff --git a/lib/asn1/test/asn1.cover b/lib/asn1/test/asn1.cover
index 589a8b7e3d..ad3a0f3db9 100644
--- a/lib/asn1/test/asn1.cover
+++ b/lib/asn1/test/asn1.cover
@@ -1,2 +1,3 @@
{incl_app,asn1,details}.
+{excl_mods, asn1, [asn1rt_nif]}. \ No newline at end of file
diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl
deleted file mode 100644
index d050d8c84b..0000000000
--- a/lib/asn1/test/asn1_SUITE.erl
+++ /dev/null
@@ -1,2489 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, 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 ASN.1 application
-
--module(asn1_SUITE).
--define(PER,'per').
--define(BER,'ber').
--define(ber_driver(Erule,Func),
- case Erule of
- ber_bin_v2 ->
- Func;
- _ -> ok
- end).
--define(per_optimize(Erule),
- case Erule of
- ber_bin_v2 ->[optimize];
- _ -> []
- end).
--define(per_bit_opt(FuncCall),
- case ?BER of
- ber_bin_v2 -> FuncCall;
-% _ -> {skip,"only for bit optimized per_bin"}
- _ -> ok
- end).
--define(uper_bin(FuncCall),
- case ?PER of
- per -> FuncCall;
- _ -> ok
- end).
-
--compile(export_all).
-%%-export([Function/Arity, ...]).
-
--include_lib("test_server/include/test_server.hrl").
-
-%% records used by test-case default
--record('Def1',{ bool0,
- bool1 = asn1_DEFAULT,
- bool2 = asn1_DEFAULT,
- bool3 = asn1_DEFAULT}).
-
-%-record('Def2',{
-%bool10, bool11 = asn1_DEFAULT, bool12 = asn1_DEFAULT, bool13}).
-
-%-record('Def3',{
-%bool30 = asn1_DEFAULT, bool31 = asn1_DEFAULT, bool32 = asn1_DEFAULT, bool33 = asn1_DEFAULT}).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [{group, compile}, parse, default_per, default_ber,
- default_per_opt, per, {group, ber}, testPrim,
- testPrimStrings, testPrimExternal, testChoPrim,
- testChoExtension, testChoExternal, testChoOptional,
- testChoOptionalImplicitTag, testChoRecursive,
- testChoTypeRefCho, testChoTypeRefPrim,
- testChoTypeRefSeq, testChoTypeRefSet, testDef, testOpt,
- testSeqDefault, testSeqExtension, testSeqExternal,
- testSeqOptional, testSeqPrim, testSeqTag,
- testSeqTypeRefCho, testSeqTypeRefPrim,
- testSeqTypeRefSeq, testSeqTypeRefSet, testSeqOf,
- testSeqOfIndefinite, testSeqOfCho, testSeqOfExternal,
- testSetDefault, testSetExtension,
- testExtensionAdditionGroup, testSetExternal,
- testSeqOfTag, testSetOptional, testSetPrim, testSetTag,
- testSetTypeRefCho, testSetTypeRefPrim,
- testSetTypeRefSeq, testSetTypeRefSet, testSetOf,
- testSetOfCho, testSetOfExternal, testSetOfTag,
- testEnumExt, value_test, testSeq2738, constructed,
- ber_decode_error, h323test, testSeqIndefinite,
- testSetIndefinite, testChoiceIndefinite,
- per_GeneralString, per_open_type, testInfObjectClass,
- testParameterizedInfObj, testMergeCompile, testobj,
- testDeepTConstr, testConstraints, testInvokeMod,
- testExport, testImport, testCompactBitString,
- testMegaco, testParamBasic, testMvrasn6,
- testContextSwitchingTypes, testTypeValueNotation,
- testOpenTypeImplicitTag, duplicate_tags, rtUI, testROSE,
- testINSTANCE_OF, testTCAP, testDER, specialized_decodes,
- special_decode_performance, test_driver_load,
- test_ParamTypeInfObj, test_WS_ParamClass,
- test_Defed_ObjectIdentifier, testSelectionType,
- testSSLspecs, testNortel, test_undecoded_rest,
- test_inline, testTcapsystem, testNBAPsystem,
- test_compile_options, testDoubleEllipses,
- test_modified_x420, testX420, test_x691, ticket_6143,
- testExtensionAdditionGroup] ++ common() ++ particular().
-
-groups() ->
- [{option_tests, [],
- [test_compile_options, ticket_6143]},
- {infobj, [],
- [testInfObjectClass, testParameterizedInfObj,
- testMergeCompile, testobj, testDeepTConstr]},
- {performance, [],
- [testTimer_ber, testTimer_ber_opt_driver, testTimer_per,
- testTimer_per_opt, testTimer_uper_bin]},
- {bugs, [],
- [test_ParamTypeInfObj, test_WS_ParamClass,
- test_Defed_ObjectIdentifier]},
- {compile, [],
- [c_syntax, c_string_per, c_string_ber,
- c_implicit_before_choice]},
- {ber, [],
- [ber_choiceinseq, ber_optional, ber_optional_keyed_list,
- ber_other]},
- {app_test, [], [{asn1_app_test, all}]},
- {appup_test, [], [{asn1_appup_test, all}]}].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%all(suite) -> [test_inline,testNBAPsystem,test_compile_options,ticket_6143].
-
-
-init_per_testcase(Func,Config) ->
- %%?line test_server:format("Func: ~p~n",[Func]),
- ?line {ok, _} = file:read_file_info(filename:join([?config(priv_dir,Config)])),
- ?line code:add_patha(?config(priv_dir,Config)),
- Dog=
- case Func of
- testX420 ->
- test_server:timetrap({minutes,60}); % 60 minutes
- _ ->
- test_server:timetrap({minutes,30}) % 60 minutes
- end,
-%% Dog=test_server:timetrap(1800000), % 30 minutes
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Func,Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog).
-
-
-testPrim(suite) -> [];
-testPrim(Config) ->
- ?line testPrim:compile(Config,?BER,[]),
- ?line testPrim_cases(?BER),
- ?line ?ber_driver(?BER,testPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testPrim_cases(?BER)),
- ?line testPrim:compile(Config,?PER,[]),
- ?line testPrim_cases(?PER),
- ?line ?per_bit_opt(testPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testPrim_cases(?PER)),
- ?line ?uper_bin(testPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testPrim_cases(uper_bin)),
- ?line testPrim:compile(Config,?PER,[optimize]),
- ?line testPrim_cases(?PER).
-
-testPrim_cases(Rules) ->
- ?line testPrim:bool(Rules),
- ?line testPrim:int(Rules),
- ?line testPrim:enum(Rules),
- ?line testPrim:obj_id(Rules),
- ?line testPrim:rel_oid(Rules),
- ?line testPrim:null(Rules),
- ?line testPrim:real(Rules).
-
-
-testCompactBitString(suite) -> [];
-testCompactBitString(Config) ->
-
- ?line testCompactBitString:compile(Config,?BER,[compact_bit_string]),
- ?line testCompactBitString:compact_bit_string(?BER),
-
- ?line ?ber_driver(?BER,testCompactBitString:compile(Config,?BER,[compact_bit_string,driver])),
- ?line ?ber_driver(?BER,testCompactBitString:compact_bit_string(?BER)),
-
- ?line testCompactBitString:compile(Config,?PER,[compact_bit_string]),
- ?line testCompactBitString:compact_bit_string(?PER),
- ?line testCompactBitString:bit_string_unnamed(?PER),
-
- ?line ?per_bit_opt(testCompactBitString:compile(Config,?PER,
- [compact_bit_string,optimize])),
- ?line ?per_bit_opt(testCompactBitString:compact_bit_string(?PER)),
- ?line ?per_bit_opt(testCompactBitString:bit_string_unnamed(?PER)),
- ?line ?per_bit_opt(testCompactBitString:ticket_7734(?PER)),
-
- ?line ?uper_bin(testCompactBitString:compile(Config,uper_bin,
- [compact_bit_string])),
- ?line ?uper_bin(testCompactBitString:compact_bit_string(uper_bin)),
- ?line ?uper_bin(testCompactBitString:bit_string_unnamed(uper_bin)),
-
- ?line testCompactBitString:compile(Config,?PER,[optimize,compact_bit_string]),
- ?line testCompactBitString:compact_bit_string(?PER),
- ?line testCompactBitString:bit_string_unnamed(?PER),
-
- ?line testCompactBitString:otp_4869(?PER).
-
-
-testPrimStrings(suite) -> [];
-testPrimStrings(Config) ->
-
- ?line testPrimStrings:compile(Config,?BER,[]),
- ?line testPrimStrings_cases(?BER),
- ?line testPrimStrings:more_strings(?BER), %% these are not implemented in per yet
- ?line ?ber_driver(?BER,testPrimStrings:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testPrimStrings_cases(?BER)),
- ?line ?ber_driver(?BER,testPrimStrings:more_strings(?BER)),
-
- ?line testPrimStrings:compile(Config,?PER,[]),
- ?line testPrimStrings_cases(?PER),
-
- ?line ?per_bit_opt(testPrimStrings:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testPrimStrings_cases(?PER)),
-
- ?line ?uper_bin(testPrimStrings:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testPrimStrings_cases(uper_bin)),
-
- ?line testPrimStrings:compile(Config,?PER,[optimize]),
- ?line testPrimStrings_cases(?PER).
-
-testPrimStrings_cases(Rules) ->
- ?line testPrimStrings:bit_string(Rules),
- ?line testPrimStrings:bit_string_unnamed(Rules),
- ?line testPrimStrings:octet_string(Rules),
- ?line testPrimStrings:numeric_string(Rules),
- ?line testPrimStrings:other_strings(Rules),
- ?line testPrimStrings:universal_string(Rules),
- ?line testPrimStrings:bmp_string(Rules),
- ?line testPrimStrings:times(Rules),
- ?line testPrimStrings:utf8_string(Rules).
-
-
-
-testPrimExternal(suite) -> [];
-testPrimExternal(Config) ->
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testPrimExternal:compile(Config,?BER,[]),
- ?line testPrimExternal_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testPrimExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testPrimExternal_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testPrimExternal:compile(Config,?PER,[]),
- ?line testPrimExternal_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testPrimExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testPrimExternal_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testPrimExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testPrimExternal_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testPrimExternal:compile(Config,?PER,[optimize]),
- ?line testPrimExternal_cases(?PER).
-
-testPrimExternal_cases(Rules) ->
- ?line testPrimExternal:external(Rules).
-
-
-
-
-testChoPrim(suite) -> [];
-testChoPrim(Config) ->
-
- ?line testChoPrim:compile(Config,?BER,[]),
- ?line testChoPrim_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoPrim_cases(?BER)),
-
- ?line testChoPrim:compile(Config,?PER,[]),
- ?line testChoPrim_cases(?PER),
-
- ?line ?per_bit_opt(testChoPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoPrim_cases(?PER)),
-
- ?line ?uper_bin(testChoPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoPrim_cases(uper_bin)),
-
- ?line testChoPrim:compile(Config,?PER,[optimize]),
- ?line testChoPrim_cases(?PER).
-
-testChoPrim_cases(Rules) ->
- ?line testChoPrim:bool(Rules),
- ?line testChoPrim:int(Rules).
-
-
-
-testChoExtension(suite) -> [];
-testChoExtension(Config) ->
-
- ?line testChoExtension:compile(Config,?BER,[]),
- ?line testChoExtension_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoExtension:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoExtension_cases(?BER)),
-
- ?line testChoExtension:compile(Config,?PER,[]),
- ?line testChoExtension_cases(?PER),
-
- ?line ?per_bit_opt(testChoExtension:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoExtension_cases(?PER)),
-
- ?line ?uper_bin(testChoExtension:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoExtension_cases(uper_bin)),
-
- ?line testChoExtension:compile(Config,?PER,[optimize]),
- ?line testChoExtension_cases(?PER).
-
-testChoExtension_cases(Rules) ->
- ?line testChoExtension:extension(Rules).
-
-
-
-testChoExternal(suite) -> [];
-testChoExternal(Config) ->
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testChoExternal:compile(Config,?BER,[]),
- ?line testChoExternal_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoExternal_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testChoExternal:compile(Config,?PER,[]),
- ?line testChoExternal_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoExternal_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoExternal_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testChoExternal:compile(Config,?PER,[optimize]),
- ?line testChoExternal_cases(?PER).
-
-
-testChoExternal_cases(Rules) ->
- ?line testChoExternal:external(Rules).
-
-
-
-testChoOptional(suite) -> [];
-testChoOptional(Config) ->
-
- ?line testChoOptional:compile(Config,?BER,[]),
- ?line testChoOptional_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoOptional:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoOptional_cases(?BER)),
-
- ?line testChoOptional:compile(Config,?PER,[]),
- ?line testChoOptional_cases(?PER),
-
- ?line ?per_bit_opt(testChoOptional:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoOptional_cases(?PER)),
-
- ?line ?uper_bin(testChoOptional:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoOptional_cases(uper_bin)),
-
- ?line testChoOptional:compile(Config,?PER,[optimize]),
- ?line testChoOptional_cases(?PER).
-
-testChoOptional_cases(Rules) ->
- ?line testChoOptional:optional(Rules).
-
-testChoOptionalImplicitTag(suite) -> [];
-testChoOptionalImplicitTag(Config) ->
- %% Only meaningful for ?BER
- ?line testChoOptionalImplicitTag:compile(Config,?BER),
- ?line testChoOptionalImplicitTag:optional(?BER).
-
-
-testChoRecursive(suite) -> [];
-testChoRecursive(Config) ->
-
- ?line testChoRecursive:compile(Config,?BER,[]),
- ?line testChoRecursive_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoRecursive:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoRecursive_cases(?BER)),
-
- ?line testChoRecursive:compile(Config,?PER,[]),
- ?line testChoRecursive_cases(?PER),
-
- ?line ?per_bit_opt(testChoRecursive:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoRecursive_cases(?PER)),
-
- ?line ?uper_bin(testChoRecursive:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoRecursive_cases(uper_bin)),
-
- ?line testChoRecursive:compile(Config,?PER,[optimize]),
- ?line testChoRecursive_cases(?PER).
-
-testChoRecursive_cases(Rules) ->
- ?line testChoRecursive:recursive(Rules).
-
-
-
-testChoTypeRefCho(suite) -> [];
-testChoTypeRefCho(Config) ->
-
- ?line testChoTypeRefCho:compile(Config,?BER,[]),
- ?line testChoTypeRefCho_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoTypeRefCho:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoTypeRefCho_cases(?BER)),
-
- ?line testChoTypeRefCho:compile(Config,?PER,[]),
- ?line testChoTypeRefCho_cases(?PER),
-
- ?line ?per_bit_opt(testChoTypeRefCho:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoTypeRefCho_cases(?PER)),
-
- ?line ?uper_bin(testChoTypeRefCho:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoTypeRefCho_cases(uper_bin)),
-
- ?line testChoTypeRefCho:compile(Config,?PER,[optimize]),
- ?line testChoTypeRefCho_cases(?PER).
-
-testChoTypeRefCho_cases(Rules) ->
- ?line testChoTypeRefCho:choice(Rules).
-
-
-
-testChoTypeRefPrim(suite) -> [];
-testChoTypeRefPrim(Config) ->
-
- ?line testChoTypeRefPrim:compile(Config,?BER,[]),
- ?line testChoTypeRefPrim_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoTypeRefPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoTypeRefPrim_cases(?BER)),
-
- ?line testChoTypeRefPrim:compile(Config,?PER,[]),
- ?line testChoTypeRefPrim_cases(?PER),
-
- ?line ?per_bit_opt(testChoTypeRefPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoTypeRefPrim_cases(?PER)),
-
- ?line ?uper_bin(testChoTypeRefPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoTypeRefPrim_cases(uper_bin)),
-
- ?line testChoTypeRefPrim:compile(Config,?PER,[optimize]),
- ?line testChoTypeRefPrim_cases(?PER).
-
-testChoTypeRefPrim_cases(Rules) ->
- ?line testChoTypeRefPrim:prim(Rules).
-
-
-
-testChoTypeRefSeq(suite) -> [];
-testChoTypeRefSeq(Config) ->
-
- ?line testChoTypeRefSeq:compile(Config,?BER,[]),
- ?line testChoTypeRefSeq_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoTypeRefSeq:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoTypeRefSeq_cases(?BER)),
-
- ?line testChoTypeRefSeq:compile(Config,?PER,[]),
- ?line testChoTypeRefSeq_cases(?PER),
-
- ?line ?per_bit_opt(testChoTypeRefSeq:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoTypeRefSeq_cases(?PER)),
-
- ?line ?uper_bin(testChoTypeRefSeq:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoTypeRefSeq_cases(uper_bin)),
-
- ?line testChoTypeRefSeq:compile(Config,?PER,[optimize]),
- ?line testChoTypeRefSeq_cases(?PER).
-
-testChoTypeRefSeq_cases(Rules) ->
- ?line testChoTypeRefSeq:seq(Rules).
-
-
-
-testChoTypeRefSet(suite) -> [];
-testChoTypeRefSet(Config) ->
-
- ?line testChoTypeRefSet:compile(Config,?BER,[]),
- ?line testChoTypeRefSet_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoTypeRefSet:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoTypeRefSet_cases(?BER)),
-
- ?line testChoTypeRefSet:compile(Config,?PER,[]),
- ?line testChoTypeRefSet_cases(?PER),
-
- ?line ?per_bit_opt(testChoTypeRefSet:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoTypeRefSet_cases(?PER)),
-
- ?line ?uper_bin(testChoTypeRefSet:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoTypeRefSet_cases(uper_bin)),
-
- ?line testChoTypeRefSet:compile(Config,?PER,[optimize]),
- ?line testChoTypeRefSet_cases(?PER).
-
-testChoTypeRefSet_cases(Rules) ->
- ?line testChoTypeRefSet:set(Rules).
-
-
-
-testDef(suite) -> [];
-testDef(Config) ->
-
- ?line testDef:compile(Config,?BER,[]),
- ?line testDef_cases(?BER),
-
- ?line ?ber_driver(?BER,testDef:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testDef_cases(?BER)),
-
- ?line testDef:compile(Config,?PER,[]),
- ?line testDef_cases(?PER),
-
- ?line ?per_bit_opt(testDef:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testDef_cases(?PER)),
-
- ?line ?uper_bin(testDef:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testDef_cases(uper_bin)),
-
- ?line testDef:compile(Config,?PER,[optimize]),
- ?line testDef_cases(?PER).
-
-testDef_cases(Rules) ->
- ?line testDef:main(Rules).
-
-
-
-testOpt(suite) -> [];
-testOpt(Config) ->
-
- ?line testOpt:compile(Config,?BER),
- ?line testOpt_cases(?BER),
-
- ?line testOpt:compile(Config,?PER),
- ?line testOpt_cases(?PER).
-
-testOpt_cases(Rules) ->
- ?line testOpt:main(Rules).
-
-
-testEnumExt(suite) -> [];
-testEnumExt(Config) ->
-
- ?line testEnumExt:compile(Config,?BER,[]),
- ?line testEnumExt:main(?BER),
-
- ?line ?ber_driver(?BER,testEnumExt:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testEnumExt:main(?BER)),
-
- ?line testEnumExt:compile(Config,?PER,[]),
- ?line testEnumExt:main(?PER),
-
- ?line ?per_bit_opt(testEnumExt:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testEnumExt:main(?PER)),
-
- ?line ?uper_bin(testEnumExt:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testEnumExt:main(uper_bin)),
-
- ?line testEnumExt:compile(Config,?PER,[optimize]),
- ?line testEnumExt:main(?PER).
-
-testSeqDefault(doc) -> ["Test of OTP-2523 ENUMERATED with extensionmark."];
-testSeqDefault(suite) -> [];
-testSeqDefault(Config) ->
-
- ?line testSeqDefault:compile(Config,?BER,[]),
- ?line testSeqDefault_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqDefault:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqDefault_cases(?BER)),
-
- ?line testSeqDefault:compile(Config,?PER,[]),
- ?line testSeqDefault_cases(?PER),
-
- ?line ?per_bit_opt(testSeqDefault:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqDefault_cases(?PER)),
-
- ?line ?uper_bin(testSeqDefault:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqDefault_cases(uper_bin)),
-
- ?line testSeqDefault:compile(Config,?PER,[optimize]),
- ?line testSeqDefault_cases(?PER).
-
-testSeqDefault_cases(Rules) ->
- ?line testSeqDefault:main(Rules).
-
-
-
-testSeqExtension(suite) -> [];
-testSeqExtension(Config) ->
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSeqExtension:compile(Config,?BER,[]),
- ?line testSeqExtension_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqExtension:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqExtension_cases(?BER)).
-
-testSeqExtension_cases(Rules) ->
- ?line testSeqExtension:main(Rules).
-
-
-
-testSeqExternal(suite) -> [];
-testSeqExternal(Config) ->
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSeqExternal:compile(Config,?BER,[]),
- ?line testSeqExternal_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqExternal_cases(?BER)).
-
-testSeqExternal_cases(Rules) ->
- ?line testSeqExternal:main(Rules).
-
-
-testSeqOptional(suite) -> [];
-testSeqOptional(Config) ->
-
- ?line testSeqOptional:compile(Config,?BER,[]),
- ?line testSeqOptional_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqOptional:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOptional_cases(?BER)),
-
- ?line testSeqOptional:compile(Config,?PER,[]),
- ?line testSeqOptional_cases(?PER),
-
- ?line ?per_bit_opt(testSeqOptional:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOptional_cases(?PER)),
-
- ?line ?uper_bin(testSeqOptional:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOptional_cases(uper_bin)),
-
- ?line testSeqOptional:compile(Config,?PER,[optimize]),
- ?line testSeqOptional_cases(?PER).
-
-testSeqOptional_cases(Rules) ->
- ?line testSeqOptional:main(Rules).
-
-
-
-testSeqPrim(suite) -> [];
-testSeqPrim(Config) ->
-
- ?line testSeqPrim:compile(Config,?BER,[]),
- ?line testSeqPrim_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqPrim_cases(?BER)),
-
- ?line testSeqPrim:compile(Config,?PER,[]),
- ?line testSeqPrim_cases(?PER),
-
- ?line ?per_bit_opt(testSeqPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqPrim_cases(?PER)),
-
- ?line ?uper_bin(testSeqPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqPrim_cases(uper_bin)),
-
- ?line testSeqPrim:compile(Config,?PER,[optimize]),
- ?line testSeqPrim_cases(?PER).
-
-testSeqPrim_cases(Rules) ->
- ?line testSeqPrim:main(Rules).
-
-
-testSeq2738(doc) -> ["Test of OTP-2738 Detect corrupt optional component."];
-testSeq2738(suite) -> [];
-testSeq2738(Config) ->
-
- ?line testSeq2738:compile(Config,?BER,[]),
- ?line testSeq2738_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeq2738:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeq2738_cases(?BER)),
-
- ?line testSeq2738:compile(Config,?PER,[]),
- ?line testSeq2738_cases(?PER),
-
- ?line ?per_bit_opt(testSeq2738:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeq2738_cases(?PER)),
-
- ?line ?uper_bin(testSeq2738:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeq2738_cases(uper_bin)),
-
- ?line testSeq2738:compile(Config,?PER,[optimize]),
- ?line testSeq2738_cases(?PER).
-
-testSeq2738_cases(Rules) ->
- ?line testSeq2738:main(Rules).
-
-
-testSeqTag(suite) -> [];
-testSeqTag(Config) ->
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSeqTag:compile(Config,?BER,[]),
- ?line testSeqTag_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqTag:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqTag_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testSeqTag:compile(Config,?PER,[]),
- ?line testSeqTag_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqTag:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqTag_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqTag:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqTag_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testSeqTag:compile(Config,?PER,[optimize]),
- ?line testSeqTag_cases(?PER).
-
-testSeqTag_cases(Rules) ->
- ?line testSeqTag:main(Rules).
-
-
-
-
-testSeqTypeRefCho(suite) -> [];
-testSeqTypeRefCho(Config) ->
-
- ?line testSeqTypeRefCho:compile(Config,?BER,[]),
- ?line testSeqTypeRefCho_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqTypeRefCho:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqTypeRefCho_cases(?BER)),
-
- ?line testSeqTypeRefCho:compile(Config,?PER,[]),
- ?line testSeqTypeRefCho_cases(?PER),
-
- ?line ?per_bit_opt(testSeqTypeRefCho:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqTypeRefCho_cases(?PER)),
-
- ?line ?uper_bin(testSeqTypeRefCho:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqTypeRefCho_cases(uper_bin)),
-
- ?line testSeqTypeRefCho:compile(Config,?PER,[optimize]),
- ?line testSeqTypeRefCho_cases(?PER).
-
-testSeqTypeRefCho_cases(Rules) ->
- ?line testSeqTypeRefCho:main(Rules).
-
-
-
-testSeqTypeRefPrim(suite) -> [];
-testSeqTypeRefPrim(Config) ->
-
- ?line testSeqTypeRefPrim:compile(Config,?BER,[]),
- ?line testSeqTypeRefPrim_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqTypeRefPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqTypeRefPrim_cases(?BER)),
-
- ?line testSeqTypeRefPrim:compile(Config,?PER,[]),
- ?line testSeqTypeRefPrim_cases(?PER),
-
- ?line ?per_bit_opt(testSeqTypeRefPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqTypeRefPrim_cases(?PER)),
-
- ?line ?uper_bin(testSeqTypeRefPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqTypeRefPrim_cases(uper_bin)),
-
- ?line testSeqTypeRefPrim:compile(Config,?PER,[optimize]),
- ?line testSeqTypeRefPrim_cases(?PER).
-
-testSeqTypeRefPrim_cases(Rules) ->
- ?line testSeqTypeRefPrim:main(Rules).
-
-
-
-testSeqTypeRefSeq(suite) -> [];
-testSeqTypeRefSeq(Config) ->
-
- ?line testSeqTypeRefSeq:compile(Config,?BER,[]),
- ?line testSeqTypeRefSeq_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqTypeRefSeq:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqTypeRefSeq_cases(?BER)),
-
- ?line testSeqTypeRefSeq:compile(Config,?PER,[]),
- ?line testSeqTypeRefSeq_cases(?PER),
-
- ?line ?per_bit_opt(testSeqTypeRefSeq:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqTypeRefSeq_cases(?PER)),
-
- ?line ?uper_bin(testSeqTypeRefSeq:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqTypeRefSeq_cases(uper_bin)),
-
- ?line testSeqTypeRefSeq:compile(Config,?PER,[optimize]),
- ?line testSeqTypeRefSeq_cases(?PER).
-
-testSeqTypeRefSeq_cases(Rules) ->
- ?line testSeqTypeRefSeq:main(Rules).
-
-
-
-testSeqTypeRefSet(suite) -> [];
-testSeqTypeRefSet(Config) ->
-
- ?line testSeqTypeRefSet:compile(Config,?BER,[]),
- ?line testSeqTypeRefSet_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqTypeRefSet:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqTypeRefSet_cases(?BER)),
-
- ?line testSeqTypeRefSet:compile(Config,?PER,[]),
- ?line testSeqTypeRefSet_cases(?PER),
-
- ?line ?per_bit_opt(testSeqTypeRefSet:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqTypeRefSet_cases(?PER)),
-
- ?line ?uper_bin(testSeqTypeRefSet:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqTypeRefSet_cases(uper_bin)),
-
- ?line testSeqTypeRefSet:compile(Config,?PER,[optimize]),
- ?line testSeqTypeRefSet_cases(?PER).
-
-testSeqTypeRefSet_cases(Rules) ->
- ?line testSeqTypeRefSet:main(Rules).
-
-
-
-
-testSeqOf(suite) -> [];
-testSeqOf(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSeqOf:compile(Config,?BER,[]),
- ?line testSeqOf_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqOf:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOf_cases(?BER)),
-
- ?line testSeqOf:compile(Config,?PER,[]),
- ?line testSeqOf_cases(?PER),
-
- ?line ?per_bit_opt(testSeqOf:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOf_cases(?PER)),
-
- ?line ?uper_bin(testSeqOf:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOf_cases(uper_bin)),
-
- ?line testSeqOf:compile(Config,?PER,[optimize]),
- ?line testSeqOf_cases(?PER).
-
-testSeqOf_cases(Rules) ->
- ?line testSeqOf:main(Rules).
-
-
-
-
-testSeqOfCho(suite) -> [];
-testSeqOfCho(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSeqOfCho:compile(Config,?BER,[]),
- ?line testSeqOfCho_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqOfCho:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOfCho_cases(?BER)),
-
- ?line testSeqOfCho:compile(Config,?PER,[]),
- ?line testSeqOfCho_cases(?PER),
-
- ?line ?per_bit_opt(testSeqOfCho:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOfCho_cases(?PER)),
-
- ?line ?uper_bin(testSeqOfCho:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOfCho_cases(uper_bin)),
-
- ?line testSeqOfCho:compile(Config,?PER,[optimize]),
- ?line testSeqOfCho_cases(?PER).
-
-testSeqOfIndefinite(suite) -> [];
-testSeqOfIndefinite(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSeqOfIndefinite:compile(Config,?BER,[]),
- ?line testSeqOfIndefinite:main(),
-
- ?line ?ber_driver(?BER,testSeqOfIndefinite:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOfIndefinite:main()).
-
-testSeqOfCho_cases(Rules) ->
- ?line testSeqOfCho:main(Rules).
-
-
-testSeqOfExternal(suite) -> [];
-testSeqOfExternal(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSeqOfExternal:compile(Config,?BER,[]),
- ?line testSeqOfExternal_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOfExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOfExternal_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testSeqOfExternal:compile(Config,?PER,[]),
- ?line testSeqOfExternal_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOfExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOfExternal_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOfExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOfExternal_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testSeqOfExternal:compile(Config,?PER,[optimize]),
- ?line testSeqOfExternal_cases(?PER).
-
-testSeqOfExternal_cases(Rules) ->
- ?line testSeqOfExternal:main(Rules).
-
-
-
-testSeqOfTag(suite) -> [];
-testSeqOfTag(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSeqOfTag:compile(Config,?BER,[]),
- ?line testSeqOfTag_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOfTag:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOfTag_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testSeqOfTag:compile(Config,?PER,[]),
- ?line testSeqOfTag_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOfTag:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOfTag_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOfTag:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOfTag_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testSeqOfTag:compile(Config,?PER,[optimize]),
- ?line testSeqOfTag_cases(?PER).
-
-testSeqOfTag_cases(Rules) ->
- ?line testSeqOfTag:main(Rules).
-
-
-
-
-testSetDefault(suite) -> [];
-testSetDefault(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetDefault:compile(Config,?BER,[]),
- ?line testSetDefault_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetDefault:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetDefault_cases(?BER)),
-
- ?line testSetDefault:compile(Config,?PER,[]),
- ?line testSetDefault_cases(?PER),
-
- ?line ?per_bit_opt(testSetDefault:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetDefault_cases(?PER)),
-
- ?line ?uper_bin(testSetDefault:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetDefault_cases(uper_bin)),
-
- ?line testSetDefault:compile(Config,?PER,[optimize]),
- ?line testSetDefault_cases(?PER).
-
-testSetDefault_cases(Rules) ->
- ?line testSetDefault:main(Rules).
-
-
-testParamBasic(suite) -> [];
-testParamBasic(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testParamBasic:compile(Config,?BER,[]),
- ?line testParamBasic_cases(?BER),
-
- ?line ?ber_driver(?BER,testParamBasic:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testParamBasic_cases(?BER)),
-
- ?line testParamBasic:compile(Config,?PER,[]),
- ?line testParamBasic_cases(?PER),
-
- ?line ?per_bit_opt(testParamBasic:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testParamBasic_cases(?PER)),
-
- ?line ?uper_bin(testParamBasic:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testParamBasic_cases(uper_bin)),
-
- ?line testParamBasic:compile(Config,?PER,[optimize]),
- ?line testParamBasic_cases(?PER).
-
-
-testParamBasic_cases(Rules) ->
- ?line testParamBasic:main(Rules).
-
-testSetExtension(suite) -> [];
-testSetExtension(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSetExtension:compile(Config,?BER,[]),
- ?line testSetExtension_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetExtension:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetExtension_cases(?BER)).
-
-testSetExtension_cases(Rules) ->
- ?line testSetExtension:main(Rules).
-
-
-testSetExternal(suite) -> [];
-testSetExternal(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSetExternal:compile(Config,?BER,[]),
- ?line testSetExternal_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetExternal_cases(?BER)).
-
-testSetExternal_cases(Rules) ->
- ?line testSetExternal:main(Rules).
-
-
-testSetOptional(suite) -> [];
-testSetOptional(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetOptional:compile(Config,?BER,[]),
- ?line testSetOptional_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetOptional:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOptional_cases(?BER)),
-
- ?line testSetOptional:compile(Config,?PER,[]),
- ?line testSetOptional_cases(?PER),
-
- ?line ?per_bit_opt(testSetOptional:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOptional_cases(?PER)),
-
- ?line ?uper_bin(testSetOptional:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOptional_cases(uper_bin)),
-
- ?line testSetOptional:compile(Config,?PER,[optimize]),
- ?line testSetOptional_cases(?PER).
-
-testSetOptional_cases(Rules) ->
- ?line ok = testSetOptional:ticket_7533(Rules),
- ?line ok = testSetOptional:main(Rules).
-
-
-
-
-testSetPrim(suite) -> [];
-testSetPrim(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetPrim:compile(Config,?BER,[]),
- ?line testSetPrim_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetPrim_cases(?BER)),
-
- ?line testSetPrim:compile(Config,?PER,[]),
- ?line testSetPrim_cases(?PER),
-
- ?line ?per_bit_opt(testSetPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetPrim_cases(?PER)),
-
- ?line ?uper_bin(testSetPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetPrim_cases(uper_bin)),
-
- ?line testSetPrim:compile(Config,?PER,[optimize]),
- ?line testSetPrim_cases(?PER).
-
-testSetPrim_cases(Rules) ->
- ?line testSetPrim:main(Rules).
-
-
-
-testSetTag(suite) -> [];
-testSetTag(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSetTag:compile(Config,?BER,[]),
- ?line testSetTag_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetTag:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetTag_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testSetTag:compile(Config,?PER,[]),
- ?line testSetTag_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetTag:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetTag_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetTag:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetTag_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testSetTag:compile(Config,?PER,[optimize]),
- ?line testSetTag_cases(?PER).
-
-testSetTag_cases(Rules) ->
- ?line testSetTag:main(Rules).
-
-
-
-testSetTypeRefCho(suite) -> [];
-testSetTypeRefCho(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetTypeRefCho:compile(Config,?BER,[]),
- ?line testSetTypeRefCho_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetTypeRefCho:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetTypeRefCho_cases(?BER)),
-
- ?line testSetTypeRefCho:compile(Config,?PER,[]),
- ?line testSetTypeRefCho_cases(?PER),
-
- ?line ?per_bit_opt(testSetTypeRefCho:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetTypeRefCho_cases(?PER)),
-
- ?line ?uper_bin(testSetTypeRefCho:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetTypeRefCho_cases(uper_bin)),
-
- ?line testSetTypeRefCho:compile(Config,?PER,[optimize]),
- ?line testSetTypeRefCho_cases(?PER).
-
-testSetTypeRefCho_cases(Rules) ->
- ?line testSetTypeRefCho:main(Rules).
-
-
-
-testSetTypeRefPrim(suite) -> [];
-testSetTypeRefPrim(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetTypeRefPrim:compile(Config,?BER,[]),
- ?line testSetTypeRefPrim_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetTypeRefPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetTypeRefPrim_cases(?BER)),
-
- ?line testSetTypeRefPrim:compile(Config,?PER,[]),
- ?line testSetTypeRefPrim_cases(?PER),
-
- ?line ?per_bit_opt(testSetTypeRefPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetTypeRefPrim_cases(?PER)),
-
- ?line ?uper_bin(testSetTypeRefPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetTypeRefPrim_cases(uper_bin)),
-
- ?line testSetTypeRefPrim:compile(Config,?PER,[optimize]),
- ?line testSetTypeRefPrim_cases(?PER).
-
-testSetTypeRefPrim_cases(Rules) ->
- ?line testSetTypeRefPrim:main(Rules).
-
-
-
-testSetTypeRefSeq(suite) -> [];
-testSetTypeRefSeq(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetTypeRefSeq:compile(Config,?BER,[]),
- ?line testSetTypeRefSeq_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetTypeRefSeq:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetTypeRefSeq_cases(?BER)),
-
- ?line testSetTypeRefSeq:compile(Config,?PER,[]),
- ?line testSetTypeRefSeq_cases(?PER),
-
- ?line ?per_bit_opt(testSetTypeRefSeq:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetTypeRefSeq_cases(?PER)),
-
- ?line ?uper_bin(testSetTypeRefSeq:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetTypeRefSeq_cases(uper_bin)),
-
- ?line testSetTypeRefSeq:compile(Config,?PER,[optimize]),
- ?line testSetTypeRefSeq_cases(?PER).
-
-testSetTypeRefSeq_cases(Rules) ->
- ?line testSetTypeRefSeq:main(Rules).
-
-
-
-testSetTypeRefSet(suite) -> [];
-testSetTypeRefSet(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetTypeRefSet:compile(Config,?BER,[]),
- ?line testSetTypeRefSet_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetTypeRefSet:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetTypeRefSet_cases(?BER)),
-
- ?line testSetTypeRefSet:compile(Config,?PER,[]),
- ?line testSetTypeRefSet_cases(?PER),
-
- ?line ?per_bit_opt(testSetTypeRefSet:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetTypeRefSet_cases(?PER)),
-
- ?line ?uper_bin(testSetTypeRefSet:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetTypeRefSet_cases(uper_bin)),
-
- ?line testSetTypeRefSet:compile(Config,?PER,[optimize]),
- ?line testSetTypeRefSet_cases(?PER).
-
-testSetTypeRefSet_cases(Rules) ->
- ?line testSetTypeRefSet:main(Rules).
-
-
-
-testSetOf(suite) -> [];
-testSetOf(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetOf:compile(Config,?BER,[]),
- ?line testSetOf_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetOf:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOf_cases(?BER)),
-
- ?line testSetOf:compile(Config,?PER,[]),
- ?line testSetOf_cases(?PER),
-
- ?line ?per_bit_opt(testSetOf:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOf_cases(?PER)),
-
- ?line ?uper_bin(testSetOf:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOf_cases(uper_bin)),
-
- ?line testSetOf:compile(Config,?PER,[optimize]),
- ?line testSetOf_cases(?PER).
-
-testSetOf_cases(Rules) ->
- ?line testSetOf:main(Rules).
-
-
-
-testSetOfCho(suite) -> [];
-testSetOfCho(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetOfCho:compile(Config,?BER,[]),
- ?line testSetOfCho_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetOfCho:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOfCho_cases(?BER)),
-
- ?line testSetOfCho:compile(Config,?PER,[]),
- ?line testSetOfCho_cases(?PER),
-
- ?line ?per_bit_opt(testSetOfCho:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOfCho_cases(?PER)),
-
- ?line ?uper_bin(testSetOfCho:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOfCho_cases(uper_bin)),
-
- ?line testSetOfCho:compile(Config,?PER,[optimize]),
- ?line testSetOfCho_cases(?PER).
-
-testSetOfCho_cases(Rules) ->
- ?line testSetOfCho:main(Rules).
-
-
-testSetOfExternal(suite) -> [];
-testSetOfExternal(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSetOfExternal:compile(Config,?BER,[]),
- ?line testSetOfExternal_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOfExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOfExternal_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testSetOfExternal:compile(Config,?PER,[]),
- ?line testSetOfExternal_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOfExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOfExternal_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOfExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOfExternal_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testSetOfExternal:compile(Config,?PER,[optimize]),
- ?line testSetOfExternal_cases(?PER).
-
-testSetOfExternal_cases(Rules) ->
- ?line testSetOfExternal:main(Rules).
-
-
-
-
-testSetOfTag(suite) -> [];
-testSetOfTag(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSetOfTag:compile(Config,?BER,[]),
- ?line testSetOfTag_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOfTag:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOfTag_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testSetOfTag:compile(Config,?PER,[]),
- ?line testSetOfTag_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOfTag:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOfTag_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOfTag:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOfTag_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testSetOfTag:compile(Config,?PER,[optimize]),
- ?line testSetOfTag_cases(?PER).
-
-testSetOfTag_cases(Rules) ->
- ?line testSetOfTag:main(Rules).
-
-
-c_syntax(suite) -> [];
-c_syntax(Config) ->
- ?line DataDir% ?line testExternal:compile(Config,?PER),
-% ?line testPrimExternal:compile(Config,?PER),
-% ?line testPrimExternal_cases(?PER).
- = ?config(data_dir,Config),
- ?line _TempDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line {error,_R1} = asn1ct:compile(filename:join(DataDir,"Syntax")),
- ?line {error,_R2} = asn1ct:compile(filename:join(DataDir,"BadTypeEnding")),
- ?line {error,_R3} = asn1ct:compile(filename:join(DataDir,
- "BadValueAssignment1")),
- ?line {error,_R4} = asn1ct:compile(filename:join(DataDir,
- "BadValueAssignment2")),
- ?line {error,_R5} = asn1ct:compile(filename:join(DataDir,
- "BadValueSet")),
- ?line {error,_R6} = asn1ct:compile(filename:join(DataDir,
- "ChoiceBadExtension")),
- ?line {error,_R7} = asn1ct:compile(filename:join(DataDir,
- "EnumerationBadExtension")),
- ?line {error,_R8} = asn1ct:compile(filename:join(DataDir,
- "Example")),
- ?line {error,_R9} = asn1ct:compile(filename:join(DataDir,
- "Export1")),
- ?line {error,_R10} = asn1ct:compile(filename:join(DataDir,
- "MissingEnd")),
- ?line {error,_R11} = asn1ct:compile(filename:join(DataDir,
- "SequenceBadComma")),
- ?line {error,_R12} = asn1ct:compile(filename:join(DataDir,
- "SequenceBadComponentName")),
- ?line {error,_R13} = asn1ct:compile(filename:join(DataDir,
- "SequenceBadComponentType")),
- ?line {error,_R14} = asn1ct:compile(filename:join(DataDir,
- "SeqBadComma")).
-
-
-c_string_per(suite) -> [];
-c_string_per(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line TempDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(filename:join(DataDir,"String"),[?PER,{outdir,TempDir}]).
-
-c_string_ber(suite) -> [];
-c_string_ber(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line TempDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(filename:join(DataDir,"String"),[?BER,{outdir,TempDir}]).
-
-
-c_implicit_before_choice(suite) -> [];
-c_implicit_before_choice(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line TempDir = ?config(priv_dir,Config),
- ?line {error,_R2} = asn1ct:compile(filename:join(DataDir,"CCSNARG3"),[?BER,{outdir,TempDir}]).
-
-parse(suite) -> [];
-parse(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- M1 = test_modules(),
-% M2 = parse_modules(),
- ?line ok = parse1(M1,DataDir,OutDir).
-
-parse1([M|T],DataDir,OutDir) ->
- ?line ok = asn1ct:compile(DataDir ++ M,[abs,{outdir,OutDir}]),
- parse1(T,DataDir,OutDir);
-parse1([],_,_) ->
- ok.
-
-per(suite) -> [];
-per(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = per1(per_modules(),DataDir,OutDir),
- ?line ?per_bit_opt(per1_bit_opt(per_modules(),DataDir,OutDir)),
- ?line ok = per1_opt(per_modules(),DataDir,OutDir).
-
-
-per1([M|T],DataDir,OutDir) ->
- ?line ok = asn1ct:compile(DataDir ++ M,[?PER,{outdir,OutDir}]),
- ?line ok = asn1ct:test(list_to_atom(M)),
- per1(T,DataDir,OutDir);
-per1([],_,_) ->
- ok.
-
-per1_bit_opt([M|T],DataDir,OutDir) ->
- ?line ok = asn1ct:compile(DataDir ++ M,[?PER,optimize,{outdir,OutDir}]),
- ?line ok = asn1ct:test(list_to_atom(M)),
- per1_bit_opt(T,DataDir,OutDir);
-per1_bit_opt([],_,_) ->
- ok.
-
-per1_opt([M|T],DataDir,OutDir) ->
- ?line ok = asn1ct:compile(DataDir ++ M,[?PER,optimized,{outdir,OutDir}]),
- ?line ok = asn1ct:test(list_to_atom(M)),
- per1_opt(T,DataDir,OutDir);
-per1_opt([],_,_) ->
- ok.
-
-
-ber_choiceinseq(suite) ->[];
-ber_choiceinseq(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(filename:join(DataDir,"ChoiceInSeq"),[?BER,{outdir,OutDir}]).
-
-ber_optional(suite) ->[];
-ber_optional(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(filename:join(DataDir,"SOpttest"),[?BER,{outdir,OutDir}]),
- ?line V = {'S',{'A',10,asn1_NOVALUE,asn1_NOVALUE},
- {'B',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE},
- {'C',asn1_NOVALUE,111,asn1_NOVALUE}},
- ?line {ok,B} = asn1_wrapper:encode('SOpttest','S',V),
- ?line Bytes = lists:flatten(B),
- ?line V2 = asn1_wrapper:decode('SOpttest','S',Bytes),
- ?line ok = eq(V,element(2,V2)).
-
-ber_optional_keyed_list(suite) ->[];
-ber_optional_keyed_list(Config) ->
- case ?BER of
- ber_bin_v2 -> ok;
- _ ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(filename:join(DataDir,"SOpttest"),
- [?BER,keyed_list,{outdir,OutDir}]),
- ?line Vrecord = {'S',{'A',10,asn1_NOVALUE,asn1_NOVALUE},
- {'B',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE},
- {'C',asn1_NOVALUE,111,asn1_NOVALUE}},
- ?line V = [ {a,[{scriptKey,10}]},
- {b,[]},
- {c,[{callingPartysCategory,111}]} ],
- ?line {ok,B} = asn1_wrapper:encode('SOpttest','S',V),
- ?line Bytes = lists:flatten(B),
- ?line V2 = asn1_wrapper:decode('SOpttest','S',Bytes),
- ?line ok = eq(Vrecord,element(2,V2))
- end.
-
-
-eq(V,V) ->
- ok.
-
-
-ber_other(suite) ->[];
-ber_other(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = ber1(ber_modules(),DataDir,OutDir).
-
-
-ber1([M|T],DataDir,OutDir) ->
- ?line ok = asn1ct:compile(DataDir ++ M,[?BER,{outdir,OutDir}]),
- ?line ok = asn1ct:test(list_to_atom(M)),
- ber1(T,DataDir,OutDir);
-ber1([],_,_) ->
- ok.
-
-default_per(suite) ->[];
-default_per(Config) ->
- default1(?PER,Config,[]).
-
-default_per_opt(suite) -> [];
-default_per_opt(Config) ->
- ?per_bit_opt(default1(?PER,Config,[optimize])),
- default1(?PER,Config,[optimize]).
-
-default_ber(suite) ->[];
-default_ber(Config) ->
- default1(?BER,Config,[]).
-
-default1(Rule,Config,Options) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(DataDir ++ "Def",[Rule,{outdir,OutDir}]++Options),
- ?line {ok,Bytes1} = asn1_wrapper:encode('Def','Def1',#'Def1'{bool0 = true,
- bool1 = true,
- bool2 = true,
- bool3 = true}),
- ?line {ok,{'Def1',true,true,true,true}} = asn1_wrapper:decode('Def','Def1',lists:flatten(Bytes1)),
-
- ?line {ok,Bytes2} = asn1_wrapper:encode('Def','Def1',#'Def1'{bool0 = true}),
- ?line {ok,{'Def1',true,false,false,false}} = asn1_wrapper:decode('Def','Def1',lists:flatten(Bytes2)),
-
- ?line {ok,Bytes3} = asn1_wrapper:encode('Def','Def1',#'Def1'{bool0 = true,bool2=false}),
- ?line {ok,{'Def1',true,false,false,false}} = asn1_wrapper:decode('Def','Def1',lists:flatten(Bytes3)).
-
-
-value_test(suite) ->[];
-value_test(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(DataDir ++ "ObjIdValues",[?BER,{outdir,OutDir}]),
- ?line {ok,_} = asn1_wrapper:encode('ObjIdValues','ObjIdType','ObjIdValues':'mobileDomainId'()),
- ?line ok = asn1ct:compile(DataDir ++ "ObjIdValues",[?PER,{outdir,OutDir}]),
- ?line {ok,_} = asn1_wrapper:encode('ObjIdValues','ObjIdType','ObjIdValues':'mobileDomainId'()),
- ?line ok = test_bad_values:tests(Config),
- ok.
-
-
-constructed(suite) ->
- [];
-constructed(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(DataDir ++ "Constructed",[?BER,{outdir,OutDir}]),
- ?line {ok,B} = asn1_wrapper:encode('Constructed','S',{'S',false}),
- ?line [40,3,1,1,0] = lists:flatten(B),
- ?line {ok,B1} = asn1_wrapper:encode('Constructed','S2',{'S2',false}),
- ?line [40,5,48,3,1,1,0] = lists:flatten(B1),
- ?line {ok,B2} = asn1_wrapper:encode('Constructed','I',10),
- ?line [136,1,10] = lists:flatten(B2),
- ok.
-
-ber_decode_error(suite) -> [];
-ber_decode_error(Config) ->
- ?line ok = ber_decode_error:compile(Config,?BER,[]),
- ?line ok = ber_decode_error:run([]),
-
- ?line ok = ?ber_driver(?BER,ber_decode_error:compile(Config,?BER,[driver])),
- ?line ok = ?ber_driver(?BER,ber_decode_error:run([driver])),
- ok.
-
-h323test(suite) ->
- [];
-h323test(Config) ->
- ?line ok = h323test:compile(Config,?PER,[]),
- ?line ok = h323test:run(?PER),
- ?line ?per_bit_opt(h323test:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(h323test:run(?PER)),
- ?line ?uper_bin(h323test:compile(Config,uper_bin,[])),
- ?line ?uper_bin(h323test:run(uper_bin)),
- ?line ok = h323test:compile(Config,?PER,[optimize]),
- ?line ok = h323test:run(?PER),
- ok.
-
-per_GeneralString(suite) ->
- [];
-per_GeneralString(Config) ->
- case erlang:module_loaded('MULTIMEDIA-SYSTEM-CONTROL') of
- true ->
- ok;
- false ->
- h323test:compile(Config,?PER,[])
- end,
- UI = [109,64,1,57],
- ?line {ok,_V} = asn1_wrapper:decode('MULTIMEDIA-SYSTEM-CONTROL',
- 'MultimediaSystemControlMessage',UI).
-
-per_open_type(suite) ->
- [];
-per_open_type(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line ok = asn1ct:compile(DataDir ++ "OpenType",[?PER,{outdir,OutDir}]),
- Stype = {'Stype',10,true},
- ?line {ok,Bytes} = asn1_wrapper:encode('OpenType','Ot',Stype),
- ?line {ok,Stype} = asn1_wrapper:decode('OpenType','Ot',Bytes),
-
- ?line ?per_bit_opt(ok = asn1ct:compile(DataDir ++ "OpenType",
- [?PER,optimize,{outdir,OutDir}])),
- ?line ?per_bit_opt({ok,Bytes}=asn1_wrapper:encode('OpenType','Ot',Stype)),
- ?line ?per_bit_opt({ok,Stype}=asn1_wrapper:decode('OpenType','Ot',Bytes)),
-
- ?line ?uper_bin(ok = asn1ct:compile(DataDir ++ "OpenType",
- [uper_bin,{outdir,OutDir}])),
- ?line ?uper_bin({ok,Bytes}=asn1_wrapper:encode('OpenType','Ot',Stype)),
- ?line ?uper_bin({ok,Stype}=asn1_wrapper:decode('OpenType','Ot',Bytes)),
-
- ?line ok = asn1ct:compile(DataDir ++ "OpenType",
- [?PER,optimize,{outdir,OutDir}]),
- ?line {ok,Bytes} = asn1_wrapper:encode('OpenType','Ot',Stype),
- ?line {ok,Stype} = asn1_wrapper:decode('OpenType','Ot',Bytes).
-
-testConstraints(suite) ->
- [];
-testConstraints(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testConstraints:compile(Config,?BER,[]),
- ?line testConstraints:int_constraints(?BER),
-
- ?line ?ber_driver(?BER,testConstraints:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testConstraints:int_constraints(?BER)),
-
- ?line testConstraints:compile(Config,?PER,[]),
- ?line testConstraints:int_constraints(?PER),
- ?line testConstraints:refed_NNL_name(?PER),
-
- ?line ?per_bit_opt(testConstraints:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testConstraints:int_constraints(?PER)),
- ?line ?per_bit_opt(testConstraints:refed_NNL_name(?PER)),
-
- ?line ?uper_bin(testConstraints:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testConstraints:int_constraints(uper_bin)),
- ?line ?uper_bin(testConstraints:refed_NNL_name(uper_bin)),
-
- ?line testConstraints:compile(Config,?PER,[optimize]),
- ?line testConstraints:int_constraints(?PER),
- ?line testConstraints:refed_NNL_name(?PER).
-
-testSeqIndefinite(suite) -> [];
-testSeqIndefinite(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSeqIndefinite:compile(Config,?BER,[]),
- ?line testSeqIndefinite:main(?BER),
-
- ?line ?ber_driver(?BER,testSeqIndefinite:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqIndefinite:main(?BER)).
-
-testSetIndefinite(suite) -> [];
-testSetIndefinite(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetIndefinite:compile(Config,?BER,[]),
- ?line testSetIndefinite:main(?BER),
-
- ?line ?ber_driver(?BER,testSetIndefinite:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetIndefinite:main(?BER)).
-
-testChoiceIndefinite(suite) -> [];
-testChoiceIndefinite(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testChoiceIndefinite:compile(Config,?BER,[]),
- ?line testChoiceIndefinite:main(?BER),
-
- ?line ?ber_driver(?BER,testChoiceIndefinite:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoiceIndefinite:main(?BER)).
-
-testInfObjectClass(suite) ->
- [];
-testInfObjectClass(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testInfObjectClass:compile(Config,?PER,[]),
- ?line testInfObjectClass:main(?PER),
- ?line testInfObj:compile(Config,?PER,[]),
- ?line testInfObj:main(?PER),
-
- ?line ?per_bit_opt(testInfObjectClass:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testInfObjectClass:main(?PER)),
- ?line ?per_bit_opt(testInfObj:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testInfObj:main(?PER)),
-
- ?line ?uper_bin(testInfObjectClass:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testInfObjectClass:main(uper_bin)),
- ?line ?uper_bin(testInfObj:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testInfObj:main(uper_bin)),
-
- ?line testInfObjectClass:compile(Config,?PER,[optimize]),
- ?line testInfObjectClass:main(?PER),
- ?line testInfObj:compile(Config,?PER,[optimize]),
- ?line testInfObj:main(?PER),
-
- ?line testInfObjectClass:compile(Config,?BER,[]),
- ?line testInfObjectClass:main(?BER),
- ?line testInfObj:compile(Config,?BER,[]),
- ?line testInfObj:main(?BER),
-
- ?line ?ber_driver(?BER,testInfObjectClass:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testInfObjectClass:main(?BER)),
- ?line ?ber_driver(?BER,testInfObj:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testInfObj:main(?BER)),
-
- ?line testInfObj:compile_RANAPfiles(Config,?PER,[]),
-
- ?line ?per_bit_opt(testInfObj:compile_RANAPfiles(Config,?PER,[optimize])),
-
- ?line ?uper_bin(testInfObj:compile_RANAPfiles(Config,uper_bin,[])),
-
- ?line testInfObj:compile_RANAPfiles(Config,?PER,[optimize]),
-
- ?line testInfObj:compile_RANAPfiles(Config,?BER,[]).
-
-testParameterizedInfObj(suite) ->
- [];
-testParameterizedInfObj(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testParameterizedInfObj:compile(Config,?PER,[]),
- ?line testParameterizedInfObj:main(?PER),
-
- ?line ?per_bit_opt(testParameterizedInfObj:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testParameterizedInfObj:main(?PER)),
-
- ?line ?uper_bin(testParameterizedInfObj:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testParameterizedInfObj:main(uper_bin)),
-
- ?line testParameterizedInfObj:compile(Config,?PER,[optimize]),
- ?line testParameterizedInfObj:main(?PER),
-
- ?line testParameterizedInfObj:compile(Config,?BER,[]),
- ?line testParameterizedInfObj:main(?BER),
-
- ?line ?ber_driver(?BER,testParameterizedInfObj:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testParameterizedInfObj:main(?BER)).
-
-testMergeCompile(suite) ->
- [];
-testMergeCompile(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testMergeCompile:compile(Config,?PER,[]),
- ?line testMergeCompile:main(?PER),
- ?line testMergeCompile:mvrasn(?PER),
-
- ?line ?per_bit_opt(testMergeCompile:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testMergeCompile:main(?PER)),
- ?line ?per_bit_opt(testMergeCompile:mvrasn(?PER)),
-
- ?line ?uper_bin(testMergeCompile:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testMergeCompile:main(uper_bin)),
- ?line ?uper_bin(testMergeCompile:mvrasn(uper_bin)),
-
- ?line testMergeCompile:compile(Config,?BER,[]),
- ?line testMergeCompile:main(?BER),
- ?line testMergeCompile:mvrasn(?BER),
-
- ?line ?ber_driver(?BER,testMergeCompile:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testMergeCompile:main(?BER)),
- ?line ?ber_driver(?BER,testMergeCompile:mvrasn(?BER)).
-
-testobj(suite) ->
- [];
-testobj(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line ok = testRANAP:compile(Config,?PER,[]),
- ?line ok = testRANAP:testobj(?PER),
- ?line ok = testParameterizedInfObj:ranap(?PER),
-
- ?line ?per_bit_opt(ok = testRANAP:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(ok = testRANAP:testobj(?PER)),
- ?line ?per_bit_opt(ok = testParameterizedInfObj:ranap(?PER)),
-
- ?line ?uper_bin(ok = testRANAP:compile(Config,uper_bin,[])),
- ?line ?uper_bin(ok = testRANAP:testobj(uper_bin)),
- ?line ?uper_bin(ok = testParameterizedInfObj:ranap(uper_bin)),
-
- ?line ok = testRANAP:compile(Config,?PER,[optimize]),
- ?line ok = testRANAP:testobj(?PER),
- ?line ok = testParameterizedInfObj:ranap(?PER),
-
- ?line ok = testRANAP:compile(Config,?BER,[]),
- ?line ok = testRANAP:testobj(?BER),
- ?line ok = testParameterizedInfObj:ranap(?BER),
-
- ?line ?ber_driver(?BER,testRANAP:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testRANAP:testobj(?BER)),
- ?line ?ber_driver(?BER,testParameterizedInfObj:ranap(?BER)).
-
-
-testDeepTConstr(suite) ->
- [];
-testDeepTConstr(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testDeepTConstr:compile(Config,?PER,[]),
- ?line testDeepTConstr:main(?PER),
-
- ?line ?per_bit_opt(testDeepTConstr:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testDeepTConstr:main(?PER)),
-
- ?line ?uper_bin(testDeepTConstr:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testDeepTConstr:main(uper_bin)),
-
- ?line testDeepTConstr:compile(Config,?PER,[optimize]),
- ?line testDeepTConstr:main(?PER),
-
- ?line testDeepTConstr:compile(Config,?BER,[]),
- ?line testDeepTConstr:main(?BER),
-
- ?line ?ber_driver(?BER,testDeepTConstr:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testDeepTConstr:main(?BER)).
-
-testInvokeMod(suite) ->
- [];
-testInvokeMod(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line ok = asn1ct:compile(filename:join(DataDir,"PrimStrings"),[{outdir,OutDir}]),
- ?line {ok,_Result1} = 'PrimStrings':encode('Bs1',[1,0,1,0]),
- ?line ok = asn1ct:compile(filename:join(DataDir,"PrimStrings"),[?PER,{outdir,OutDir}]),
- ?line {ok,_Result2} = 'PrimStrings':encode('Bs1',[1,0,1,0]).
-
-testExport(suite) ->
- [];
-testExport(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line {error,{asn1,_Reason}} = asn1ct:compile(filename:join(DataDir,"IllegalExport"),[{outdir,OutDir}]).
-
-testImport(suite) ->
- [];
-testImport(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line _OutDir = ?config(priv_dir,Config),
- ?line {error,_} = asn1ct:compile(filename:join(DataDir,"ImportsFrom"),[?BER]),
- ok.
-
-testMegaco(suite) ->
- [];
-testMegaco(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
- io:format("Config: ~p~n",[Config]),
- ?line {ok,ModuleName1,ModuleName2} = testMegaco:compile(Config,?BER,[]),
- ?line ok = testMegaco:main(ModuleName1,Config),
- ?line ok = testMegaco:main(ModuleName2,Config),
-
- case ?BER of
- ber_bin_v2 ->
- ?line {ok,ModuleName3,ModuleName4} = testMegaco:compile(Config,?BER,[driver]),
- ?line ok = testMegaco:main(ModuleName3,Config),
- ?line ok = testMegaco:main(ModuleName4,Config);
- _-> ok
- end,
-
- ?line {ok,ModuleName5,ModuleName6} = testMegaco:compile(Config,?PER,[]),
- ?line ok = testMegaco:main(ModuleName5,Config),
- ?line ok = testMegaco:main(ModuleName6,Config),
-
- ?line ?per_bit_opt({ok,ModuleName5,ModuleName6} = testMegaco:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(ok = testMegaco:main(ModuleName5,Config)),
- ?line ?per_bit_opt(ok = testMegaco:main(ModuleName6,Config)),
-
- ?line ?uper_bin({ok,ModuleName5,ModuleName6} = testMegaco:compile(Config,uper_bin,[])),
- ?line ?uper_bin(ok = testMegaco:main(ModuleName5,Config)),
- ?line ?uper_bin(ok = testMegaco:main(ModuleName6,Config)),
-
- ?line {ok,ModuleName7,ModuleName8} = testMegaco:compile(Config,?PER,[optimize]),
- ?line ok = testMegaco:main(ModuleName7,Config),
- ?line ok = testMegaco:main(ModuleName8,Config).
-
-
-testMvrasn6(suite) -> [];
-testMvrasn6(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testMvrasn6:compile(Config,?BER),
- ?line testMvrasn6:main().
-
-testContextSwitchingTypes(suite) -> [];
-testContextSwitchingTypes(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testContextSwitchingTypes:compile(Config,?BER,[]),
- ?line testContextSwitchingTypes:test(),
-
- ?line ?ber_driver(?BER,testContextSwitchingTypes:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testContextSwitchingTypes:test()),
-
- ?line testContextSwitchingTypes:compile(Config,?PER,[]),
- ?line testContextSwitchingTypes:test(),
-
- ?line ?per_bit_opt(testContextSwitchingTypes:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testContextSwitchingTypes:test()),
-
- ?line ?uper_bin(testContextSwitchingTypes:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testContextSwitchingTypes:test()),
-
- ?line testContextSwitchingTypes:compile(Config,?PER,[optimize]),
- ?line testContextSwitchingTypes:test().
-
-testTypeValueNotation(suite) -> [];
-testTypeValueNotation(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- case ?BER of
- Ber when Ber == ber; Ber == ber_bin ->
- ?line testTypeValueNotation:compile(Config,?BER,[]),
- ?line testTypeValueNotation:main(?BER,dummy);
- _ ->
- ok
- end,
-
- ?line ?ber_driver(?BER,testTypeValueNotation:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testTypeValueNotation:main(?BER,optimize)),
-
- case ?BER of
- Ber2 when Ber2 == ber; Ber2 == ber_bin ->
- ?line testTypeValueNotation:compile(Config,?PER,[]),
- ?line testTypeValueNotation:main(?PER,dummy);
- _ ->
- ok
- end,
-
- ?line ?per_bit_opt(testTypeValueNotation:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testTypeValueNotation:main(?PER,optimize)),
-
- ?line ?uper_bin(testTypeValueNotation:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testTypeValueNotation:main(uper_bin,optimize)),
- case ?BER of
- Ber3 when Ber3 == ber; Ber3 == ber_bin ->
- ?line testTypeValueNotation:compile(Config,?PER,[optimize]),
- ?line testTypeValueNotation:main(?PER,optimize);
- _ ->
- ok
- end.
-
-testOpenTypeImplicitTag(suite) -> [];
-testOpenTypeImplicitTag(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testOpenTypeImplicitTag:compile(Config,?BER,[]),
- ?line testOpenTypeImplicitTag:main(?BER),
-
- ?line ?ber_driver(?BER,testOpenTypeImplicitTag:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testOpenTypeImplicitTag:main(?BER)),
-
- ?line testOpenTypeImplicitTag:compile(Config,?PER,[]),
- ?line testOpenTypeImplicitTag:main(?PER),
-
- ?line ?per_bit_opt(testOpenTypeImplicitTag:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testOpenTypeImplicitTag:main(?PER)),
-
- ?line ?uper_bin(testOpenTypeImplicitTag:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testOpenTypeImplicitTag:main(uper_bin)),
-
- ?line testOpenTypeImplicitTag:compile(Config,?PER,[optimize]),
- ?line testOpenTypeImplicitTag:main(?PER).
-
-duplicate_tags(suite) -> [];
-duplicate_tags(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- {error,{asn1,[{error,{type,_,_,'SeqOpt1Imp',{asn1,{duplicates_of_the_tags,_}}}}]}} =
- asn1ct:compile(filename:join(DataDir,"SeqOptional2"),[abs]),
- ok.
-
-rtUI(suite) -> [];
-rtUI(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line ok = asn1ct:compile(filename:join(DataDir,"Prim"),[?BER]),
- ?line {ok,_} = asn1rt:info('Prim'),
-
- ?line ok = asn1ct:compile(filename:join(DataDir,"Prim"),[?PER]),
- ?line {ok,_} = asn1rt:info('Prim'),
-
- ?line ok = asn1rt:load_driver(),
- ?line ok = asn1rt:load_driver(),
- ?line ok = asn1rt:unload_driver().
-
-testROSE(suite) -> [];
-testROSE(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testROSE:compile(Config,?BER,[]),
-
- ?line testROSE:compile(Config,?PER,[]),
- ?line ?per_bit_opt(testROSE:compile(Config,?PER,[optimize])),
- ?line ?uper_bin(testROSE:compile(Config,uper_bin,[])),
- ?line testROSE:compile(Config,?PER,[optimize]).
-
-testINSTANCE_OF(suite) -> [];
-testINSTANCE_OF(Config) ->
- ?line testINSTANCE_OF:compile(Config,?BER,[]),
- ?line testINSTANCE_OF:main(?BER),
-
- ?line ?ber_driver(?BER,testINSTANCE_OF:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testINSTANCE_OF:main(?BER)),
-
- ?line testINSTANCE_OF:compile(Config,?PER,[]),
- ?line testINSTANCE_OF:main(?PER),
-
- ?line ?per_bit_opt(testINSTANCE_OF:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testINSTANCE_OF:main(?PER)),
-
- ?line ?uper_bin(testINSTANCE_OF:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testINSTANCE_OF:main(uper_bin)),
-
- ?line testINSTANCE_OF:compile(Config,?PER,[optimize]),
- ?line testINSTANCE_OF:main(?PER).
-
-testTCAP(suite) -> [];
-testTCAP(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testTCAP:compile(Config,?BER,[]),
- ?line testTCAP:test(?BER,Config),
-
- ?line ?ber_driver(?BER,testTCAP:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testTCAP:test(?BER,Config)),
-
- ?line ?ber_driver(?BER,testTCAP:compile_asn1config(Config,?BER,[asn1config])),
- ?line ?ber_driver(?BER,testTCAP:test_asn1config()).
-
-testDER(suite) ->[];
-testDER(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testDER:compile(Config,?BER,[]),
- ?line testDER:test(),
-
- ?line ?ber_driver(?BER,testDER:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testDER:test()),
-
- ?line testParamBasic:compile_der(Config,?BER),
- ?line testParamBasic_cases(der),
-
-
- ?line testSeqSetDefaultVal:compile(Config,?BER),
- ?line testSeqSetDefaultVal_cases(?BER).
-
-testSeqSetDefaultVal_cases(?BER) ->
- ?line testSeqSetDefaultVal:main(?BER).
-
-
-specialized_decodes(suite) -> [];
-specialized_decodes(Config) ->
- ?line test_partial_incomplete_decode:compile(Config,?BER,[optimize]),
- ?line test_partial_incomplete_decode:test(?BER,Config),
- ?line test_selective_decode:test(?BER,Config).
-
-special_decode_performance(suite) ->[];
-special_decode_performance(Config) ->
- ?line ?ber_driver(?BER,test_special_decode_performance:compile(Config,?BER)),
- ?line ?ber_driver(?BER,test_special_decode_performance:go(all)).
-
-
-test_driver_load(suite) -> [];
-test_driver_load(Config) ->
- ?line test_driver_load:compile(Config,?PER),
- ?line test_driver_load:test(?PER,5).
-
-test_ParamTypeInfObj(suite) -> [];
-test_ParamTypeInfObj(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line ok = asn1ct:compile(filename:join(DataDir,"IN-CS-1-Datatypes"),[ber_bin]).
-
-test_WS_ParamClass(suite) -> [];
-test_WS_ParamClass(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line ok = asn1ct:compile(filename:join(DataDir,"InformationFramework"),
- [ber_bin]).
-
-test_Defed_ObjectIdentifier(suite) -> [];
-test_Defed_ObjectIdentifier(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line ok = asn1ct:compile(filename:join(DataDir,"UsefulDefinitions"),
- [ber_bin]).
-
-testSelectionType(suite) -> [];
-testSelectionType(Config) ->
-
- ?line ok = testSelectionTypes:compile(Config,?BER,[]),
- ?line {ok,_} = testSelectionTypes:test(),
-
- ?line ok = testSelectionTypes:compile(Config,?PER,[]),
- ?line {ok,_} = testSelectionTypes:test().
-
-testSSLspecs(suite) -> [];
-testSSLspecs(Config) ->
-
- ?line ok = testSSLspecs:compile(Config,?BER,
- [optimize,compact_bit_string,der]),
- ?line testSSLspecs:run(?BER),
-
- case code:which(asn1ct) of
- cover_compiled ->
- ok;
- _ ->
- ?line ok = testSSLspecs:compile_inline(Config,?BER),
- ?line ok = testSSLspecs:run_inline(?BER)
- end.
-
-testNortel(suite) -> [];
-testNortel(Config) ->
- ?line DataDir = ?config(data_dir,Config),
-
- ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"),[?BER]),
- ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"),
- [?BER,optimize]),
- ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"),
- [?BER,optimize,driver]),
- ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"),[?PER]),
- ?line ?per_bit_opt(ok = asn1ct:compile(filename:join(DataDir,"Nortel"),
- [?PER,optimize])),
- ?line ?uper_bin(ok = asn1ct:compile(filename:join(DataDir,"Nortel"),[uper_bin])),
- ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"),
- [?PER,optimize]).
-test_undecoded_rest(suite) -> [];
-test_undecoded_rest(Config) ->
-
- ?line ok = test_undecoded_rest:compile(Config,?BER,[]),
- ?line ok = test_undecoded_rest:test([]),
-
- ?line ok = test_undecoded_rest:compile(Config,?BER,[undec_rest]),
- ?line ok = test_undecoded_rest:test(undec_rest),
-
- ?line ok = test_undecoded_rest:compile(Config,?PER,[]),
- ?line ok = test_undecoded_rest:test([]),
-
- ?line ?per_bit_opt(ok = test_undecoded_rest:compile(Config,?PER,[optimize,undec_rest])),
- ?line ?per_bit_opt(ok = test_undecoded_rest:test(undec_rest)),
-
- ?line ?uper_bin(ok = test_undecoded_rest:compile(Config,uper_bin,[undec_rest])),
- ?line ?uper_bin(ok = test_undecoded_rest:test(undec_rest)),
-
- ?line ok = test_undecoded_rest:compile(Config,?PER,[undec_rest]),
- ?line ok = test_undecoded_rest:test(undec_rest).
-
-test_inline(suite) -> [];
-test_inline(Config) ->
- case code:which(asn1ct) of
- cover_compiled ->
- {skip,"Not runnable when cover compiled"};
- _ ->
- ?line ok=test_inline:compile(Config,?BER,[]),
- ?line test_inline:main(?BER),
- ?line test_inline:inline1(Config,?BER,[]),
- ?line test_inline:performance2()
- end.
-
-%test_inline_prf(suite) -> [];
-%test_inline_prf(Config) ->
-% ?line test_inline:performance(Config).
-
-testTcapsystem(suite) -> [];
-testTcapsystem(Config) ->
- ?line ok=testTcapsystem:compile(Config,?BER,[]).
-
-testNBAPsystem(suite) -> [];
-testNBAPsystem(Config) ->
- ?line ok=testNBAPsystem:compile(Config,?PER,?per_optimize(?BER)),
- ?line ok=testNBAPsystem:test(?PER,Config).
-
-test_compile_options(suite) -> [];
-test_compile_options(Config) ->
- case code:which(asn1ct) of
- cover_compiled ->
- {skip,"Not runnable when cover compiled"};
- _ ->
- ?line ok = test_compile_options:wrong_path(Config),
- ?line ok = test_compile_options:path(Config),
- ?line ok = test_compile_options:noobj(Config),
- ?line ok = test_compile_options:record_name_prefix(Config),
- ?line ok = test_compile_options:verbose(Config)
- end.
-testDoubleEllipses(suite) -> [];
-testDoubleEllipses(Config) ->
- ?line testDoubleEllipses:compile(Config,?BER,[]),
- ?line testDoubleEllipses:main(?BER),
- ?line ?ber_driver(?BER,testDoubleEllipses:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testDoubleEllipses:main(?BER)),
- ?line ?per_bit_opt(testDoubleEllipses:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testDoubleEllipses:main(?PER)),
- ?line ?uper_bin(testDoubleEllipses:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testDoubleEllipses:main(uper_bin)),
- ?line testDoubleEllipses:compile(Config,?PER,?per_optimize(?BER)),
- ?line testDoubleEllipses:main(?PER).
-
-test_modified_x420(suite) -> [];
-test_modified_x420(Config) ->
- ?line test_modified_x420:compile(Config),
- ?line test_modified_x420:test_io(Config).
-
-testX420(suite) -> [];
-testX420(Config) ->
- ?line testX420:compile(?BER,[der],Config),
- ?line ok = testX420:ticket7759(?BER,Config),
- ?line testX420:compile(?PER,[],Config).
-
-test_x691(suite) -> [];
-test_x691(Config) ->
- case ?PER of
- per ->
- ?line ok = test_x691:compile(Config,uper_bin,[]),
- ?line true = test_x691:cases(uper_bin,unaligned),
- ?line ok = test_x691:compile(Config,?PER,[]),
- ?line true = test_x691:cases(?PER,aligned),
-%% ?line ok = asn1_test_lib:ticket_7678(Config,[]),
- ?line ok = asn1_test_lib:ticket_7708(Config,[]),
- ?line ok = asn1_test_lib:ticket_7763(Config);
- _ ->
- ?line ok = test_x691:compile(Config,?PER,?per_optimize(?BER)),
- ?line true = test_x691:cases(?PER,aligned)
- end.
-%% ?line ok = asn1_test_lib:ticket_7876(Config,?PER,[]),
-%% ?line ok = asn1_test_lib:ticket_7876(Config,?PER,[compact_bit_string]),
-%% ?line ok = asn1_test_lib:ticket_7876(Config,?PER,[optimize]),
-%% ?line ok = asn1_test_lib:ticket_7876(Config,?PER,[optimize,compact_bit_string]).
-
-
-ticket_6143(suite) -> [];
-ticket_6143(Config) ->
- ?line ok = test_compile_options:ticket_6143(Config).
-
-testExtensionAdditionGroup(suite) -> [];
-testExtensionAdditionGroup(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line PrivDir = ?config(priv_dir,Config),
- ?line Path = code:get_path(),
- ?line code:add_patha(PrivDir),
- DoIt = fun(Erule) ->
- ?line ok = asn1ct:compile(filename:join(DataDir,"Extension-Addition-Group"),[Erule,{outdir,PrivDir}]),
- ?line {ok,_M} = compile:file(filename:join(DataDir,"extensionAdditionGroup"),[{i,PrivDir},{outdir,PrivDir},debug_info]),
- ?line ok = extensionAdditionGroup:run(Erule)
- end,
- ?line [DoIt(Rule)|| Rule <- [per_bin,uper_bin,ber_bin]],
- ?line code:set_path(Path).
-
-
-
-% parse_modules() ->
-% ["ImportsFrom"].
-
-per_modules() ->
- [X || X <- test_modules()].
-ber_modules() ->
- [X || X <- test_modules(),
- X =/= "CommonDataTypes",
- X =/= "DS-EquipmentUser-CommonFunctionOrig-TransmissionPath",
- X =/= "H323-MESSAGES",
- X =/= "H235-SECURITY-MESSAGES",
- X =/= "MULTIMEDIA-SYSTEM-CONTROL"].
-test_modules() ->
- _Modules = [
- "BitStr",
- "CommonDataTypes",
- "Constraints",
- "ContextSwitchingTypes",
- "DS-EquipmentUser-CommonFunctionOrig-TransmissionPath",
- "Enum",
- "From",
- "H235-SECURITY-MESSAGES",
- "H323-MESSAGES",
- %%"MULTIMEDIA-SYSTEM-CONTROL", recursive type , problem for asn1ct:value
- "Import",
- "Int",
- "MAP-commonDataTypes",
-% ambigous tags "MAP-insertSubscriberData-def",
- "Null",
- "Octetstr",
- "One",
- "P-Record",
- "P",
-% "PDUs",
- "Person",
- "PrimStrings",
- "Real",
- "XSeq",
- "XSeqOf",
- "XSet",
- "XSetOf",
- "String",
- "SwCDR",
-% "Syntax",
- "Time"
-% ANY "Tst",
-% "Two",
-% errors that should be detected "UndefType"
-] ++
- [
- "SeqSetLib", % must be compiled before Seq and Set
- "Seq",
- "Set",
- "SetOf",
- "SeqOf",
- "Prim",
- "Cho",
- "Def",
- "Opt",
- "ELDAPv3",
- "LDAP"
- ].
-
-
-%%
-%% %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%
-%%
-%%
-
-common() ->
-[{group, app_test}, {group, appup_test}, testTimer_ber,
- testTimer_ber_bin, testTimer_ber_bin_opt,
- testTimer_ber_bin_opt_driver, testTimer_per,
- testTimer_per_bin, testTimer_per_bin_opt,
- testTimer_uper_bin, testComment, testName2Number].
-
-
-
-testTimer_ber(suite) -> [];
-testTimer_ber(Config) ->
- ?line testTimer:compile(Config,ber,[]),
- ?line testTimer:go(Config,ber).
-
-testTimer_ber_bin(suite) -> [];
-testTimer_ber_bin(Config) ->
- ?line testTimer:compile(Config,ber_bin,[]),
- ?line testTimer:go(Config,ber_bin).
-
-testTimer_ber_bin_opt(suite) -> [];
-testTimer_ber_bin_opt(Config) ->
- ?line testTimer:compile(Config,ber_bin,[optimize]),
- ?line testTimer:go(Config,ber_bin).
-
-testTimer_ber_bin_opt_driver(suite) -> [];
-testTimer_ber_bin_opt_driver(Config) ->
- ?line testTimer:compile(Config,ber_bin,[optimize,driver]),
- ?line testTimer:go(Config,ber_bin).
-
-testTimer_per(suite) -> [];
-testTimer_per(Config) ->
- ?line testTimer:compile(Config,per,[]),
- ?line testTimer:go(Config,per).
-
-testTimer_per_bin(suite) -> [];
-testTimer_per_bin(Config) ->
- ?line testTimer:compile(Config,per_bin,[]),
- ?line testTimer:go(Config,per_bin).
-
-testTimer_per_bin_opt(suite) -> [];
-testTimer_per_bin_opt(Config) ->
- ?line testTimer:compile(Config,per_bin,[optimize]),
- ?line testTimer:go(Config,per_bin).
-
-
-testTimer_uper_bin(suite) -> [];
-testTimer_uper_bin(Config) ->
- ?line ok=testTimer:compile(Config,uper_bin,[]),
- ?line {comment,_} = testTimer:go(Config,uper_bin).
-
-%% Test of multiple-line comment, OTP-8043
-testComment(suite) -> [];
-testComment(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
-
- ?line ok = asn1ct:compile(DataDir ++ "Comment",[{outdir,OutDir}]),
-
- ?line {ok,Enc} = asn1_wrapper:encode('Comment','Seq',{'Seq',12,true}),
- ?line {ok,{'Seq',12,true}} = asn1_wrapper:decode('Comment','Seq',Enc),
- ok.
-
-testName2Number(suite) -> [];
-testName2Number(Config) ->
- DataDir = ?config(data_dir,Config),
- OutDir = ?config(priv_dir,Config),
- N2NOptions = [{n2n,Type}|| Type <-
- ['CauseMisc','CauseProtocol',
- %% 'CauseNetwork',
- 'CauseRadioNetwork',
- 'CauseTransport','CauseNas']],
- ?line ok = asn1ct:compile(DataDir ++ "S1AP-IEs",[{outdir,OutDir}]++N2NOptions),
- ?line true = code:add_patha(OutDir),
-
- ?line 0 = 'S1AP-IEs':name2num_CauseMisc('control-processing-overload'),
- ?line 'unknown-PLMN' = 'S1AP-IEs':num2name_CauseMisc(5),
- ok.
-
-
-particular() ->
- [ticket_7407].
-
-ticket_7407(suite) -> [];
-ticket_7407(Config) ->
- ?line ok = asn1_test_lib:ticket_7407_compile(Config,[]),
- ?line ok = asn1_test_lib:ticket_7407_code(true),
-
- ?line ok = asn1_test_lib:ticket_7407_compile(Config,[no_final_padding]),
- ?line ok = asn1_test_lib:ticket_7407_code(false).
diff --git a/lib/asn1/test/asn1_SUITE.erl.src b/lib/asn1/test/asn1_SUITE.erl.src
index 7201365ea3..124ee2d2bb 100644
--- a/lib/asn1/test/asn1_SUITE.erl.src
+++ b/lib/asn1/test/asn1_SUITE.erl.src
@@ -60,10 +60,10 @@ bool0, bool1 = asn1_DEFAULT, bool2 = asn1_DEFAULT, bool3 = asn1_DEFAULT}).
%-record('Def3',{
%bool30 = asn1_DEFAULT, bool31 = asn1_DEFAULT, bool32 = asn1_DEFAULT, bool33 = asn1_DEFAULT}).
+suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all(suite) -> [compile,parse,default_per,default_ber,default_per_opt,per,
- ber,testPrim,
+all() -> [{group,compile},parse,default_per,default_ber,default_per_opt,per,
+ {group,ber},testPrim,
testPrimStrings, testPrimExternal, testChoPrim,
testChoExtension, testChoExternal, testChoOptional,
testChoOptionalImplicitTag, testChoRecursive,
@@ -99,21 +99,34 @@ all(suite) -> [compile,parse,default_per,default_ber,default_per_opt,per,
testX420, test_x691,ticket_6143, testExtensionAdditionGroup
] ++ common() ++ particular().
-%all(suite) -> [test_inline,testNBAPsystem,test_compile_options,ticket_6143].
+groups() ->
+ [
+ {compile, [],
+ [c_syntax, c_string_per, c_string_ber,
+ c_implicit_before_choice]},
+ {ber, [],
+ [ber_choiceinseq, ber_optional, ber_optional_keyed_list,
+ ber_other]},
+ {app_test, [], [{asn1_app_test, all}]},
+ {appup_test, [], [{asn1_appup_test, all}]}
+ ].
+
+init_per_suite(Config) ->
+ io:format("code:lib_dir(asn1) = ~p~n",[code:lib_dir(asn1)]),
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
-option_tests(suite) ->
- [test_compile_options,ticket_6143].
+end_per_group(_GroupName, Config) ->
+ Config.
-infobj(suite) ->
- [testInfObjectClass, testParameterizedInfObj, testMergeCompile,
- testobj, testDeepTConstr].
-performance(suite) ->
- [testTimer_ber, testTimer_ber_opt_driver,
- testTimer_per, testTimer_per_opt, testTimer_uper_bin].
+%all(suite) -> [test_inline,testNBAPsystem,test_compile_options,ticket_6143].
-bugs(suite) ->
- [test_ParamTypeInfObj, test_WS_ParamClass,test_Defed_ObjectIdentifier].
init_per_testcase(Func,Config) ->
%%?line test_server:format("Func: ~p~n",[Func]),
@@ -129,7 +142,7 @@ init_per_testcase(Func,Config) ->
%% Dog=test_server:timetrap(1800000), % 30 minutes
[{watchdog, Dog}|Config].
-fin_per_testcase(_Func,Config) ->
+end_per_testcase(_Func,Config) ->
Dog=?config(watchdog, Config),
test_server:timetrap_cancel(Dog).
@@ -1371,22 +1384,6 @@ testSetOfTag_cases(Rules) ->
sequence(suite) -> [{sequence,all}].
-compile(suite) -> [c_syntax,c_string_per,c_string_ber,c_implicit_before_choice];
-compile(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line TempDir = ?config(priv_dir,Config),
- ?line True = lists:member(TempDir,code:get_path()),
- ?line test_server:format("~p~n",[True]),
- ?line test_server:format("~p~n",[code:get_path()]),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line {error,_R1} = asn1ct:compile(filename:join(DataDir,"Syntax")),
- ?line ok = asn1ct:compile(filename:join(DataDir,"String"),[?PER,{outdir,TempDir}]),
- test_server:format("first String ok~n"),
- ?line ok = asn1ct:compile(filename:join(DataDir,"String"),[?BER,{outdir,TempDir}]),
- ?line {error,_R2} = asn1ct:compile(filename:join(DataDir,"CCSNARG3"),[?BER,{outdir,TempDir}]),
- ?line {error,_} = asn1ct:compile(filename:join(DataDir,"ImportsFrom"),[?BER,{outdir,TempDir}]),
- ok.
-
c_syntax(suite) -> [];
c_syntax(Config) ->
?line DataDir% ?line testExternal:compile(Config,?PER),
@@ -1490,8 +1487,6 @@ per1_opt([M|T],DataDir,OutDir) ->
per1_opt([],_,_) ->
ok.
-ber(suite) -> [ber_choiceinseq,ber_optional,ber_optional_keyed_list,ber_other].
-
ber_choiceinseq(suite) ->[];
ber_choiceinseq(Config) ->
?line DataDir = ?config(data_dir,Config),
@@ -2041,11 +2036,7 @@ rtUI(Config) ->
?line {ok,_} = asn1rt:info('Prim'),
?line ok = asn1ct:compile(filename:join(DataDir,"Prim"),[?PER]),
- ?line {ok,_} = asn1rt:info('Prim'),
-
- ?line ok = asn1rt:load_driver(),
- ?line ok = asn1rt:load_driver(),
- ?line ok = asn1rt:unload_driver().
+ ?line {ok,_} = asn1rt:info('Prim').
testROSE(suite) -> [];
testROSE(Config) ->
@@ -2241,8 +2232,10 @@ test_compile_options(Config) ->
?line ok = test_compile_options:path(Config),
?line ok = test_compile_options:noobj(Config),
?line ok = test_compile_options:record_name_prefix(Config),
- ?line ok = test_compile_options:verbose(Config)
+ ?line ok = test_compile_options:verbose(Config),
+ ?line ok = test_compile_options:warnings_as_errors(Config)
end.
+
testDoubleEllipses(suite) -> [];
testDoubleEllipses(Config) ->
?line testDoubleEllipses:compile(Config,?BER,[]),
diff --git a/lib/asn1/test/asn1_bin_SUITE.erl b/lib/asn1/test/asn1_bin_SUITE.erl
deleted file mode 100644
index a924aee0db..0000000000
--- a/lib/asn1/test/asn1_bin_SUITE.erl
+++ /dev/null
@@ -1,2382 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, 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 ASN.1 application
-
--module(asn1_bin_SUITE).
--define(PER,'per_bin').
--define(BER,'ber_bin').
--define(ber_driver(Erule,Func),
- case Erule of
- ber_bin_v2 ->
- Func;
- _ -> ok
- end).
--define(per_optimize(Erule),
- case Erule of
- ber_bin_v2 ->[optimize];
- _ -> []
- end).
--define(per_bit_opt(FuncCall),
- case ?BER of
- ber_bin_v2 -> FuncCall;
-% _ -> {skip,"only for bit optimized per_bin"}
- _ -> ok
- end).
--define(uper_bin(FuncCall),
- case ?PER of
- per -> FuncCall;
- _ -> ok
- end).
-
--compile(export_all).
-%%-export([Function/Arity, ...]).
-
--include_lib("test_server/include/test_server.hrl").
-
-%% records used by test-case default
--record('Def1',{bool0, bool1 = asn1_DEFAULT,
- bool2 = asn1_DEFAULT,
- bool3 = asn1_DEFAULT}).
-
-%-record('Def2',{
-%bool10, bool11 = asn1_DEFAULT, bool12 = asn1_DEFAULT, bool13}).
-
-%-record('Def3',{
-%bool30 = asn1_DEFAULT, bool31 = asn1_DEFAULT, bool32 = asn1_DEFAULT, bool33 = asn1_DEFAULT}).
-
-
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [{group, compile}, parse, default_per, default_ber,
- default_per_opt, per, {group, ber}, testPrim,
- testPrimStrings, testPrimExternal, testChoPrim,
- testChoExtension, testChoExternal, testChoOptional,
- testChoOptionalImplicitTag, testChoRecursive,
- testChoTypeRefCho, testChoTypeRefPrim,
- testChoTypeRefSeq, testChoTypeRefSet, testDef, testOpt,
- testSeqDefault, testSeqExtension, testSeqExternal,
- testSeqOptional, testSeqPrim, testSeqTag,
- testSeqTypeRefCho, testSeqTypeRefPrim,
- testSeqTypeRefSeq, testSeqTypeRefSet, testSeqOf,
- testSeqOfIndefinite, testSeqOfCho, testSeqOfExternal,
- testSetDefault, testSetExtension,
- testExtensionAdditionGroup, testSetExternal,
- testSeqOfTag, testSetOptional, testSetPrim, testSetTag,
- testSetTypeRefCho, testSetTypeRefPrim,
- testSetTypeRefSeq, testSetTypeRefSet, testSetOf,
- testSetOfCho, testSetOfExternal, testSetOfTag,
- testEnumExt, value_test, testSeq2738, constructed,
- ber_decode_error, h323test, testSeqIndefinite,
- testSetIndefinite, testChoiceIndefinite,
- per_GeneralString, per_open_type, testInfObjectClass,
- testParameterizedInfObj, testMergeCompile, testobj,
- testDeepTConstr, testConstraints, testInvokeMod,
- testExport, testImport, testCompactBitString,
- testMegaco, testParamBasic, testMvrasn6,
- testContextSwitchingTypes, testTypeValueNotation,
- testOpenTypeImplicitTag, duplicate_tags, rtUI, testROSE,
- testINSTANCE_OF, testTCAP, testDER, specialized_decodes,
- special_decode_performance, test_driver_load,
- test_ParamTypeInfObj, test_WS_ParamClass,
- test_Defed_ObjectIdentifier, testSelectionType,
- testSSLspecs, testNortel, test_undecoded_rest,
- test_inline, testTcapsystem, testNBAPsystem,
- test_compile_options, testDoubleEllipses,
- test_modified_x420, testX420, test_x691, ticket_6143,
- testExtensionAdditionGroup] ++ common() ++ particular().
-
-groups() ->
- [{option_tests, [],
- [test_compile_options, ticket_6143]},
- {infobj, [],
- [testInfObjectClass, testParameterizedInfObj,
- testMergeCompile, testobj, testDeepTConstr]},
- {performance, [],
- [testTimer_ber, testTimer_ber_opt_driver, testTimer_per,
- testTimer_per_opt, testTimer_uper_bin]},
- {bugs, [],
- [test_ParamTypeInfObj, test_WS_ParamClass,
- test_Defed_ObjectIdentifier]},
- {compile, [],
- [c_syntax, c_string_per, c_string_ber,
- c_implicit_before_choice]},
- {ber, [],
- [ber_choiceinseq, ber_optional, ber_optional_keyed_list,
- ber_other]}].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-%all(suite) -> [test_inline,testNBAPsystem,test_compile_options,ticket_6143].
-
-init_per_testcase(Func,Config) ->
- %%?line test_server:format("Func: ~p~n",[Func]),
- ?line {ok, _} = file:read_file_info(filename:join([?config(priv_dir,Config)])),
- ?line code:add_patha(?config(priv_dir,Config)),
- Dog=
- case Func of
- testX420 ->
- test_server:timetrap({minutes,60}); % 60 minutes
- _ ->
- test_server:timetrap({minutes,30}) % 60 minutes
- end,
-%% Dog=test_server:timetrap(1800000), % 30 minutes
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Func,Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog).
-
-
-testPrim(suite) -> [];
-testPrim(Config) ->
- ?line testPrim:compile(Config,?BER,[]),
- ?line testPrim_cases(?BER),
- ?line ?ber_driver(?BER,testPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testPrim_cases(?BER)),
- ?line testPrim:compile(Config,?PER,[]),
- ?line testPrim_cases(?PER),
- ?line ?per_bit_opt(testPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testPrim_cases(?PER)),
- ?line ?uper_bin(testPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testPrim_cases(uper_bin)),
- ?line testPrim:compile(Config,?PER,[optimize]),
- ?line testPrim_cases(?PER).
-
-testPrim_cases(Rules) ->
- ?line testPrim:bool(Rules),
- ?line testPrim:int(Rules),
- ?line testPrim:enum(Rules),
- ?line testPrim:obj_id(Rules),
- ?line testPrim:rel_oid(Rules),
- ?line testPrim:null(Rules),
- ?line testPrim:real(Rules).
-
-
-testCompactBitString(suite) -> [];
-testCompactBitString(Config) ->
-
- ?line testCompactBitString:compile(Config,?BER,[compact_bit_string]),
- ?line testCompactBitString:compact_bit_string(?BER),
-
- ?line ?ber_driver(?BER,testCompactBitString:compile(Config,?BER,[compact_bit_string,driver])),
- ?line ?ber_driver(?BER,testCompactBitString:compact_bit_string(?BER)),
-
- ?line testCompactBitString:compile(Config,?PER,[compact_bit_string]),
- ?line testCompactBitString:compact_bit_string(?PER),
- ?line testCompactBitString:bit_string_unnamed(?PER),
-
- ?line ?per_bit_opt(testCompactBitString:compile(Config,?PER,
- [compact_bit_string,optimize])),
- ?line ?per_bit_opt(testCompactBitString:compact_bit_string(?PER)),
- ?line ?per_bit_opt(testCompactBitString:bit_string_unnamed(?PER)),
- ?line ?per_bit_opt(testCompactBitString:ticket_7734(?PER)),
-
- ?line ?uper_bin(testCompactBitString:compile(Config,uper_bin,
- [compact_bit_string])),
- ?line ?uper_bin(testCompactBitString:compact_bit_string(uper_bin)),
- ?line ?uper_bin(testCompactBitString:bit_string_unnamed(uper_bin)),
-
- ?line testCompactBitString:compile(Config,?PER,[optimize,compact_bit_string]),
- ?line testCompactBitString:compact_bit_string(?PER),
- ?line testCompactBitString:bit_string_unnamed(?PER),
-
- ?line testCompactBitString:otp_4869(?PER).
-
-
-testPrimStrings(suite) -> [];
-testPrimStrings(Config) ->
-
- ?line testPrimStrings:compile(Config,?BER,[]),
- ?line testPrimStrings_cases(?BER),
- ?line testPrimStrings:more_strings(?BER), %% these are not implemented in per yet
- ?line ?ber_driver(?BER,testPrimStrings:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testPrimStrings_cases(?BER)),
- ?line ?ber_driver(?BER,testPrimStrings:more_strings(?BER)),
-
- ?line testPrimStrings:compile(Config,?PER,[]),
- ?line testPrimStrings_cases(?PER),
-
- ?line ?per_bit_opt(testPrimStrings:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testPrimStrings_cases(?PER)),
-
- ?line ?uper_bin(testPrimStrings:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testPrimStrings_cases(uper_bin)),
-
- ?line testPrimStrings:compile(Config,?PER,[optimize]),
- ?line testPrimStrings_cases(?PER).
-
-testPrimStrings_cases(Rules) ->
- ?line testPrimStrings:bit_string(Rules),
- ?line testPrimStrings:bit_string_unnamed(Rules),
- ?line testPrimStrings:octet_string(Rules),
- ?line testPrimStrings:numeric_string(Rules),
- ?line testPrimStrings:other_strings(Rules),
- ?line testPrimStrings:universal_string(Rules),
- ?line testPrimStrings:bmp_string(Rules),
- ?line testPrimStrings:times(Rules),
- ?line testPrimStrings:utf8_string(Rules).
-
-
-
-testPrimExternal(suite) -> [];
-testPrimExternal(Config) ->
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testPrimExternal:compile(Config,?BER,[]),
- ?line testPrimExternal_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testPrimExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testPrimExternal_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testPrimExternal:compile(Config,?PER,[]),
- ?line testPrimExternal_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testPrimExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testPrimExternal_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testPrimExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testPrimExternal_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testPrimExternal:compile(Config,?PER,[optimize]),
- ?line testPrimExternal_cases(?PER).
-
-testPrimExternal_cases(Rules) ->
- ?line testPrimExternal:external(Rules).
-
-
-
-
-testChoPrim(suite) -> [];
-testChoPrim(Config) ->
-
- ?line testChoPrim:compile(Config,?BER,[]),
- ?line testChoPrim_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoPrim_cases(?BER)),
-
- ?line testChoPrim:compile(Config,?PER,[]),
- ?line testChoPrim_cases(?PER),
-
- ?line ?per_bit_opt(testChoPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoPrim_cases(?PER)),
-
- ?line ?uper_bin(testChoPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoPrim_cases(uper_bin)),
-
- ?line testChoPrim:compile(Config,?PER,[optimize]),
- ?line testChoPrim_cases(?PER).
-
-testChoPrim_cases(Rules) ->
- ?line testChoPrim:bool(Rules),
- ?line testChoPrim:int(Rules).
-
-
-
-testChoExtension(suite) -> [];
-testChoExtension(Config) ->
-
- ?line testChoExtension:compile(Config,?BER,[]),
- ?line testChoExtension_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoExtension:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoExtension_cases(?BER)),
-
- ?line testChoExtension:compile(Config,?PER,[]),
- ?line testChoExtension_cases(?PER),
-
- ?line ?per_bit_opt(testChoExtension:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoExtension_cases(?PER)),
-
- ?line ?uper_bin(testChoExtension:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoExtension_cases(uper_bin)),
-
- ?line testChoExtension:compile(Config,?PER,[optimize]),
- ?line testChoExtension_cases(?PER).
-
-testChoExtension_cases(Rules) ->
- ?line testChoExtension:extension(Rules).
-
-
-
-testChoExternal(suite) -> [];
-testChoExternal(Config) ->
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testChoExternal:compile(Config,?BER,[]),
- ?line testChoExternal_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoExternal_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testChoExternal:compile(Config,?PER,[]),
- ?line testChoExternal_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoExternal_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoExternal_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testChoExternal:compile(Config,?PER,[optimize]),
- ?line testChoExternal_cases(?PER).
-
-
-testChoExternal_cases(Rules) ->
- ?line testChoExternal:external(Rules).
-
-
-
-testChoOptional(suite) -> [];
-testChoOptional(Config) ->
-
- ?line testChoOptional:compile(Config,?BER,[]),
- ?line testChoOptional_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoOptional:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoOptional_cases(?BER)),
-
- ?line testChoOptional:compile(Config,?PER,[]),
- ?line testChoOptional_cases(?PER),
-
- ?line ?per_bit_opt(testChoOptional:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoOptional_cases(?PER)),
-
- ?line ?uper_bin(testChoOptional:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoOptional_cases(uper_bin)),
-
- ?line testChoOptional:compile(Config,?PER,[optimize]),
- ?line testChoOptional_cases(?PER).
-
-testChoOptional_cases(Rules) ->
- ?line testChoOptional:optional(Rules).
-
-testChoOptionalImplicitTag(suite) -> [];
-testChoOptionalImplicitTag(Config) ->
- %% Only meaningful for ?BER
- ?line testChoOptionalImplicitTag:compile(Config,?BER),
- ?line testChoOptionalImplicitTag:optional(?BER).
-
-
-testChoRecursive(suite) -> [];
-testChoRecursive(Config) ->
-
- ?line testChoRecursive:compile(Config,?BER,[]),
- ?line testChoRecursive_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoRecursive:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoRecursive_cases(?BER)),
-
- ?line testChoRecursive:compile(Config,?PER,[]),
- ?line testChoRecursive_cases(?PER),
-
- ?line ?per_bit_opt(testChoRecursive:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoRecursive_cases(?PER)),
-
- ?line ?uper_bin(testChoRecursive:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoRecursive_cases(uper_bin)),
-
- ?line testChoRecursive:compile(Config,?PER,[optimize]),
- ?line testChoRecursive_cases(?PER).
-
-testChoRecursive_cases(Rules) ->
- ?line testChoRecursive:recursive(Rules).
-
-
-
-testChoTypeRefCho(suite) -> [];
-testChoTypeRefCho(Config) ->
-
- ?line testChoTypeRefCho:compile(Config,?BER,[]),
- ?line testChoTypeRefCho_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoTypeRefCho:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoTypeRefCho_cases(?BER)),
-
- ?line testChoTypeRefCho:compile(Config,?PER,[]),
- ?line testChoTypeRefCho_cases(?PER),
-
- ?line ?per_bit_opt(testChoTypeRefCho:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoTypeRefCho_cases(?PER)),
-
- ?line ?uper_bin(testChoTypeRefCho:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoTypeRefCho_cases(uper_bin)),
-
- ?line testChoTypeRefCho:compile(Config,?PER,[optimize]),
- ?line testChoTypeRefCho_cases(?PER).
-
-testChoTypeRefCho_cases(Rules) ->
- ?line testChoTypeRefCho:choice(Rules).
-
-
-
-testChoTypeRefPrim(suite) -> [];
-testChoTypeRefPrim(Config) ->
-
- ?line testChoTypeRefPrim:compile(Config,?BER,[]),
- ?line testChoTypeRefPrim_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoTypeRefPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoTypeRefPrim_cases(?BER)),
-
- ?line testChoTypeRefPrim:compile(Config,?PER,[]),
- ?line testChoTypeRefPrim_cases(?PER),
-
- ?line ?per_bit_opt(testChoTypeRefPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoTypeRefPrim_cases(?PER)),
-
- ?line ?uper_bin(testChoTypeRefPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoTypeRefPrim_cases(uper_bin)),
-
- ?line testChoTypeRefPrim:compile(Config,?PER,[optimize]),
- ?line testChoTypeRefPrim_cases(?PER).
-
-testChoTypeRefPrim_cases(Rules) ->
- ?line testChoTypeRefPrim:prim(Rules).
-
-
-
-testChoTypeRefSeq(suite) -> [];
-testChoTypeRefSeq(Config) ->
-
- ?line testChoTypeRefSeq:compile(Config,?BER,[]),
- ?line testChoTypeRefSeq_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoTypeRefSeq:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoTypeRefSeq_cases(?BER)),
-
- ?line testChoTypeRefSeq:compile(Config,?PER,[]),
- ?line testChoTypeRefSeq_cases(?PER),
-
- ?line ?per_bit_opt(testChoTypeRefSeq:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoTypeRefSeq_cases(?PER)),
-
- ?line ?uper_bin(testChoTypeRefSeq:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoTypeRefSeq_cases(uper_bin)),
-
- ?line testChoTypeRefSeq:compile(Config,?PER,[optimize]),
- ?line testChoTypeRefSeq_cases(?PER).
-
-testChoTypeRefSeq_cases(Rules) ->
- ?line testChoTypeRefSeq:seq(Rules).
-
-
-
-testChoTypeRefSet(suite) -> [];
-testChoTypeRefSet(Config) ->
-
- ?line testChoTypeRefSet:compile(Config,?BER,[]),
- ?line testChoTypeRefSet_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoTypeRefSet:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoTypeRefSet_cases(?BER)),
-
- ?line testChoTypeRefSet:compile(Config,?PER,[]),
- ?line testChoTypeRefSet_cases(?PER),
-
- ?line ?per_bit_opt(testChoTypeRefSet:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoTypeRefSet_cases(?PER)),
-
- ?line ?uper_bin(testChoTypeRefSet:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoTypeRefSet_cases(uper_bin)),
-
- ?line testChoTypeRefSet:compile(Config,?PER,[optimize]),
- ?line testChoTypeRefSet_cases(?PER).
-
-testChoTypeRefSet_cases(Rules) ->
- ?line testChoTypeRefSet:set(Rules).
-
-
-
-testDef(suite) -> [];
-testDef(Config) ->
-
- ?line testDef:compile(Config,?BER,[]),
- ?line testDef_cases(?BER),
-
- ?line ?ber_driver(?BER,testDef:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testDef_cases(?BER)),
-
- ?line testDef:compile(Config,?PER,[]),
- ?line testDef_cases(?PER),
-
- ?line ?per_bit_opt(testDef:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testDef_cases(?PER)),
-
- ?line ?uper_bin(testDef:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testDef_cases(uper_bin)),
-
- ?line testDef:compile(Config,?PER,[optimize]),
- ?line testDef_cases(?PER).
-
-testDef_cases(Rules) ->
- ?line testDef:main(Rules).
-
-
-
-testOpt(suite) -> [];
-testOpt(Config) ->
-
- ?line testOpt:compile(Config,?BER),
- ?line testOpt_cases(?BER),
-
- ?line testOpt:compile(Config,?PER),
- ?line testOpt_cases(?PER).
-
-testOpt_cases(Rules) ->
- ?line testOpt:main(Rules).
-
-
-testEnumExt(suite) -> [];
-testEnumExt(Config) ->
-
- ?line testEnumExt:compile(Config,?BER,[]),
- ?line testEnumExt:main(?BER),
-
- ?line ?ber_driver(?BER,testEnumExt:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testEnumExt:main(?BER)),
-
- ?line testEnumExt:compile(Config,?PER,[]),
- ?line testEnumExt:main(?PER),
-
- ?line ?per_bit_opt(testEnumExt:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testEnumExt:main(?PER)),
-
- ?line ?uper_bin(testEnumExt:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testEnumExt:main(uper_bin)),
-
- ?line testEnumExt:compile(Config,?PER,[optimize]),
- ?line testEnumExt:main(?PER).
-
-testSeqDefault(doc) -> ["Test of OTP-2523 ENUMERATED with extensionmark."];
-testSeqDefault(suite) -> [];
-testSeqDefault(Config) ->
-
- ?line testSeqDefault:compile(Config,?BER,[]),
- ?line testSeqDefault_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqDefault:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqDefault_cases(?BER)),
-
- ?line testSeqDefault:compile(Config,?PER,[]),
- ?line testSeqDefault_cases(?PER),
-
- ?line ?per_bit_opt(testSeqDefault:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqDefault_cases(?PER)),
-
- ?line ?uper_bin(testSeqDefault:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqDefault_cases(uper_bin)),
-
- ?line testSeqDefault:compile(Config,?PER,[optimize]),
- ?line testSeqDefault_cases(?PER).
-
-testSeqDefault_cases(Rules) ->
- ?line testSeqDefault:main(Rules).
-
-
-
-testSeqExtension(suite) -> [];
-testSeqExtension(Config) ->
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSeqExtension:compile(Config,?BER,[]),
- ?line testSeqExtension_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqExtension:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqExtension_cases(?BER)).
-
-testSeqExtension_cases(Rules) ->
- ?line testSeqExtension:main(Rules).
-
-
-
-testSeqExternal(suite) -> [];
-testSeqExternal(Config) ->
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSeqExternal:compile(Config,?BER,[]),
- ?line testSeqExternal_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqExternal_cases(?BER)).
-
-testSeqExternal_cases(Rules) ->
- ?line testSeqExternal:main(Rules).
-
-
-testSeqOptional(suite) -> [];
-testSeqOptional(Config) ->
-
- ?line testSeqOptional:compile(Config,?BER,[]),
- ?line testSeqOptional_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqOptional:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOptional_cases(?BER)),
-
- ?line testSeqOptional:compile(Config,?PER,[]),
- ?line testSeqOptional_cases(?PER),
-
- ?line ?per_bit_opt(testSeqOptional:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOptional_cases(?PER)),
-
- ?line ?uper_bin(testSeqOptional:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOptional_cases(uper_bin)),
-
- ?line testSeqOptional:compile(Config,?PER,[optimize]),
- ?line testSeqOptional_cases(?PER).
-
-testSeqOptional_cases(Rules) ->
- ?line testSeqOptional:main(Rules).
-
-
-
-testSeqPrim(suite) -> [];
-testSeqPrim(Config) ->
-
- ?line testSeqPrim:compile(Config,?BER,[]),
- ?line testSeqPrim_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqPrim_cases(?BER)),
-
- ?line testSeqPrim:compile(Config,?PER,[]),
- ?line testSeqPrim_cases(?PER),
-
- ?line ?per_bit_opt(testSeqPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqPrim_cases(?PER)),
-
- ?line ?uper_bin(testSeqPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqPrim_cases(uper_bin)),
-
- ?line testSeqPrim:compile(Config,?PER,[optimize]),
- ?line testSeqPrim_cases(?PER).
-
-testSeqPrim_cases(Rules) ->
- ?line testSeqPrim:main(Rules).
-
-
-testSeq2738(doc) -> ["Test of OTP-2738 Detect corrupt optional component."];
-testSeq2738(suite) -> [];
-testSeq2738(Config) ->
-
- ?line testSeq2738:compile(Config,?BER,[]),
- ?line testSeq2738_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeq2738:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeq2738_cases(?BER)),
-
- ?line testSeq2738:compile(Config,?PER,[]),
- ?line testSeq2738_cases(?PER),
-
- ?line ?per_bit_opt(testSeq2738:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeq2738_cases(?PER)),
-
- ?line ?uper_bin(testSeq2738:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeq2738_cases(uper_bin)),
-
- ?line testSeq2738:compile(Config,?PER,[optimize]),
- ?line testSeq2738_cases(?PER).
-
-testSeq2738_cases(Rules) ->
- ?line testSeq2738:main(Rules).
-
-
-testSeqTag(suite) -> [];
-testSeqTag(Config) ->
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSeqTag:compile(Config,?BER,[]),
- ?line testSeqTag_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqTag:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqTag_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testSeqTag:compile(Config,?PER,[]),
- ?line testSeqTag_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqTag:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqTag_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqTag:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqTag_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testSeqTag:compile(Config,?PER,[optimize]),
- ?line testSeqTag_cases(?PER).
-
-testSeqTag_cases(Rules) ->
- ?line testSeqTag:main(Rules).
-
-
-
-
-testSeqTypeRefCho(suite) -> [];
-testSeqTypeRefCho(Config) ->
-
- ?line testSeqTypeRefCho:compile(Config,?BER,[]),
- ?line testSeqTypeRefCho_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqTypeRefCho:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqTypeRefCho_cases(?BER)),
-
- ?line testSeqTypeRefCho:compile(Config,?PER,[]),
- ?line testSeqTypeRefCho_cases(?PER),
-
- ?line ?per_bit_opt(testSeqTypeRefCho:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqTypeRefCho_cases(?PER)),
-
- ?line ?uper_bin(testSeqTypeRefCho:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqTypeRefCho_cases(uper_bin)),
-
- ?line testSeqTypeRefCho:compile(Config,?PER,[optimize]),
- ?line testSeqTypeRefCho_cases(?PER).
-
-testSeqTypeRefCho_cases(Rules) ->
- ?line testSeqTypeRefCho:main(Rules).
-
-
-
-testSeqTypeRefPrim(suite) -> [];
-testSeqTypeRefPrim(Config) ->
-
- ?line testSeqTypeRefPrim:compile(Config,?BER,[]),
- ?line testSeqTypeRefPrim_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqTypeRefPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqTypeRefPrim_cases(?BER)),
-
- ?line testSeqTypeRefPrim:compile(Config,?PER,[]),
- ?line testSeqTypeRefPrim_cases(?PER),
-
- ?line ?per_bit_opt(testSeqTypeRefPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqTypeRefPrim_cases(?PER)),
-
- ?line ?uper_bin(testSeqTypeRefPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqTypeRefPrim_cases(uper_bin)),
-
- ?line testSeqTypeRefPrim:compile(Config,?PER,[optimize]),
- ?line testSeqTypeRefPrim_cases(?PER).
-
-testSeqTypeRefPrim_cases(Rules) ->
- ?line testSeqTypeRefPrim:main(Rules).
-
-
-
-testSeqTypeRefSeq(suite) -> [];
-testSeqTypeRefSeq(Config) ->
-
- ?line testSeqTypeRefSeq:compile(Config,?BER,[]),
- ?line testSeqTypeRefSeq_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqTypeRefSeq:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqTypeRefSeq_cases(?BER)),
-
- ?line testSeqTypeRefSeq:compile(Config,?PER,[]),
- ?line testSeqTypeRefSeq_cases(?PER),
-
- ?line ?per_bit_opt(testSeqTypeRefSeq:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqTypeRefSeq_cases(?PER)),
-
- ?line ?uper_bin(testSeqTypeRefSeq:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqTypeRefSeq_cases(uper_bin)),
-
- ?line testSeqTypeRefSeq:compile(Config,?PER,[optimize]),
- ?line testSeqTypeRefSeq_cases(?PER).
-
-testSeqTypeRefSeq_cases(Rules) ->
- ?line testSeqTypeRefSeq:main(Rules).
-
-
-
-testSeqTypeRefSet(suite) -> [];
-testSeqTypeRefSet(Config) ->
-
- ?line testSeqTypeRefSet:compile(Config,?BER,[]),
- ?line testSeqTypeRefSet_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqTypeRefSet:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqTypeRefSet_cases(?BER)),
-
- ?line testSeqTypeRefSet:compile(Config,?PER,[]),
- ?line testSeqTypeRefSet_cases(?PER),
-
- ?line ?per_bit_opt(testSeqTypeRefSet:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqTypeRefSet_cases(?PER)),
-
- ?line ?uper_bin(testSeqTypeRefSet:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqTypeRefSet_cases(uper_bin)),
-
- ?line testSeqTypeRefSet:compile(Config,?PER,[optimize]),
- ?line testSeqTypeRefSet_cases(?PER).
-
-testSeqTypeRefSet_cases(Rules) ->
- ?line testSeqTypeRefSet:main(Rules).
-
-
-
-
-testSeqOf(suite) -> [];
-testSeqOf(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSeqOf:compile(Config,?BER,[]),
- ?line testSeqOf_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqOf:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOf_cases(?BER)),
-
- ?line testSeqOf:compile(Config,?PER,[]),
- ?line testSeqOf_cases(?PER),
-
- ?line ?per_bit_opt(testSeqOf:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOf_cases(?PER)),
-
- ?line ?uper_bin(testSeqOf:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOf_cases(uper_bin)),
-
- ?line testSeqOf:compile(Config,?PER,[optimize]),
- ?line testSeqOf_cases(?PER).
-
-testSeqOf_cases(Rules) ->
- ?line testSeqOf:main(Rules).
-
-
-
-
-testSeqOfCho(suite) -> [];
-testSeqOfCho(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSeqOfCho:compile(Config,?BER,[]),
- ?line testSeqOfCho_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqOfCho:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOfCho_cases(?BER)),
-
- ?line testSeqOfCho:compile(Config,?PER,[]),
- ?line testSeqOfCho_cases(?PER),
-
- ?line ?per_bit_opt(testSeqOfCho:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOfCho_cases(?PER)),
-
- ?line ?uper_bin(testSeqOfCho:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOfCho_cases(uper_bin)),
-
- ?line testSeqOfCho:compile(Config,?PER,[optimize]),
- ?line testSeqOfCho_cases(?PER).
-
-testSeqOfIndefinite(suite) -> [];
-testSeqOfIndefinite(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSeqOfIndefinite:compile(Config,?BER,[]),
- ?line testSeqOfIndefinite:main(),
-
- ?line ?ber_driver(?BER,testSeqOfIndefinite:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOfIndefinite:main()).
-
-testSeqOfCho_cases(Rules) ->
- ?line testSeqOfCho:main(Rules).
-
-
-testSeqOfExternal(suite) -> [];
-testSeqOfExternal(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSeqOfExternal:compile(Config,?BER,[]),
- ?line testSeqOfExternal_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOfExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOfExternal_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testSeqOfExternal:compile(Config,?PER,[]),
- ?line testSeqOfExternal_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOfExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOfExternal_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOfExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOfExternal_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testSeqOfExternal:compile(Config,?PER,[optimize]),
- ?line testSeqOfExternal_cases(?PER).
-
-testSeqOfExternal_cases(Rules) ->
- ?line testSeqOfExternal:main(Rules).
-
-
-
-testSeqOfTag(suite) -> [];
-testSeqOfTag(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSeqOfTag:compile(Config,?BER,[]),
- ?line testSeqOfTag_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOfTag:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOfTag_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testSeqOfTag:compile(Config,?PER,[]),
- ?line testSeqOfTag_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOfTag:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOfTag_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOfTag:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOfTag_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testSeqOfTag:compile(Config,?PER,[optimize]),
- ?line testSeqOfTag_cases(?PER).
-
-testSeqOfTag_cases(Rules) ->
- ?line testSeqOfTag:main(Rules).
-
-
-
-
-testSetDefault(suite) -> [];
-testSetDefault(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetDefault:compile(Config,?BER,[]),
- ?line testSetDefault_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetDefault:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetDefault_cases(?BER)),
-
- ?line testSetDefault:compile(Config,?PER,[]),
- ?line testSetDefault_cases(?PER),
-
- ?line ?per_bit_opt(testSetDefault:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetDefault_cases(?PER)),
-
- ?line ?uper_bin(testSetDefault:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetDefault_cases(uper_bin)),
-
- ?line testSetDefault:compile(Config,?PER,[optimize]),
- ?line testSetDefault_cases(?PER).
-
-testSetDefault_cases(Rules) ->
- ?line testSetDefault:main(Rules).
-
-
-testParamBasic(suite) -> [];
-testParamBasic(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testParamBasic:compile(Config,?BER,[]),
- ?line testParamBasic_cases(?BER),
-
- ?line ?ber_driver(?BER,testParamBasic:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testParamBasic_cases(?BER)),
-
- ?line testParamBasic:compile(Config,?PER,[]),
- ?line testParamBasic_cases(?PER),
-
- ?line ?per_bit_opt(testParamBasic:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testParamBasic_cases(?PER)),
-
- ?line ?uper_bin(testParamBasic:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testParamBasic_cases(uper_bin)),
-
- ?line testParamBasic:compile(Config,?PER,[optimize]),
- ?line testParamBasic_cases(?PER).
-
-
-testParamBasic_cases(Rules) ->
- ?line testParamBasic:main(Rules).
-
-testSetExtension(suite) -> [];
-testSetExtension(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSetExtension:compile(Config,?BER,[]),
- ?line testSetExtension_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetExtension:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetExtension_cases(?BER)).
-
-testSetExtension_cases(Rules) ->
- ?line testSetExtension:main(Rules).
-
-
-testSetExternal(suite) -> [];
-testSetExternal(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSetExternal:compile(Config,?BER,[]),
- ?line testSetExternal_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetExternal_cases(?BER)).
-
-testSetExternal_cases(Rules) ->
- ?line testSetExternal:main(Rules).
-
-
-testSetOptional(suite) -> [];
-testSetOptional(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetOptional:compile(Config,?BER,[]),
- ?line testSetOptional_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetOptional:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOptional_cases(?BER)),
-
- ?line testSetOptional:compile(Config,?PER,[]),
- ?line testSetOptional_cases(?PER),
-
- ?line ?per_bit_opt(testSetOptional:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOptional_cases(?PER)),
-
- ?line ?uper_bin(testSetOptional:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOptional_cases(uper_bin)),
-
- ?line testSetOptional:compile(Config,?PER,[optimize]),
- ?line testSetOptional_cases(?PER).
-
-testSetOptional_cases(Rules) ->
- ?line ok = testSetOptional:ticket_7533(Rules),
- ?line ok = testSetOptional:main(Rules).
-
-
-
-
-testSetPrim(suite) -> [];
-testSetPrim(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetPrim:compile(Config,?BER,[]),
- ?line testSetPrim_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetPrim_cases(?BER)),
-
- ?line testSetPrim:compile(Config,?PER,[]),
- ?line testSetPrim_cases(?PER),
-
- ?line ?per_bit_opt(testSetPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetPrim_cases(?PER)),
-
- ?line ?uper_bin(testSetPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetPrim_cases(uper_bin)),
-
- ?line testSetPrim:compile(Config,?PER,[optimize]),
- ?line testSetPrim_cases(?PER).
-
-testSetPrim_cases(Rules) ->
- ?line testSetPrim:main(Rules).
-
-
-
-testSetTag(suite) -> [];
-testSetTag(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSetTag:compile(Config,?BER,[]),
- ?line testSetTag_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetTag:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetTag_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testSetTag:compile(Config,?PER,[]),
- ?line testSetTag_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetTag:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetTag_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetTag:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetTag_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testSetTag:compile(Config,?PER,[optimize]),
- ?line testSetTag_cases(?PER).
-
-testSetTag_cases(Rules) ->
- ?line testSetTag:main(Rules).
-
-
-
-testSetTypeRefCho(suite) -> [];
-testSetTypeRefCho(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetTypeRefCho:compile(Config,?BER,[]),
- ?line testSetTypeRefCho_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetTypeRefCho:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetTypeRefCho_cases(?BER)),
-
- ?line testSetTypeRefCho:compile(Config,?PER,[]),
- ?line testSetTypeRefCho_cases(?PER),
-
- ?line ?per_bit_opt(testSetTypeRefCho:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetTypeRefCho_cases(?PER)),
-
- ?line ?uper_bin(testSetTypeRefCho:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetTypeRefCho_cases(uper_bin)),
-
- ?line testSetTypeRefCho:compile(Config,?PER,[optimize]),
- ?line testSetTypeRefCho_cases(?PER).
-
-testSetTypeRefCho_cases(Rules) ->
- ?line testSetTypeRefCho:main(Rules).
-
-
-
-testSetTypeRefPrim(suite) -> [];
-testSetTypeRefPrim(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetTypeRefPrim:compile(Config,?BER,[]),
- ?line testSetTypeRefPrim_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetTypeRefPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetTypeRefPrim_cases(?BER)),
-
- ?line testSetTypeRefPrim:compile(Config,?PER,[]),
- ?line testSetTypeRefPrim_cases(?PER),
-
- ?line ?per_bit_opt(testSetTypeRefPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetTypeRefPrim_cases(?PER)),
-
- ?line ?uper_bin(testSetTypeRefPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetTypeRefPrim_cases(uper_bin)),
-
- ?line testSetTypeRefPrim:compile(Config,?PER,[optimize]),
- ?line testSetTypeRefPrim_cases(?PER).
-
-testSetTypeRefPrim_cases(Rules) ->
- ?line testSetTypeRefPrim:main(Rules).
-
-
-
-testSetTypeRefSeq(suite) -> [];
-testSetTypeRefSeq(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetTypeRefSeq:compile(Config,?BER,[]),
- ?line testSetTypeRefSeq_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetTypeRefSeq:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetTypeRefSeq_cases(?BER)),
-
- ?line testSetTypeRefSeq:compile(Config,?PER,[]),
- ?line testSetTypeRefSeq_cases(?PER),
-
- ?line ?per_bit_opt(testSetTypeRefSeq:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetTypeRefSeq_cases(?PER)),
-
- ?line ?uper_bin(testSetTypeRefSeq:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetTypeRefSeq_cases(uper_bin)),
-
- ?line testSetTypeRefSeq:compile(Config,?PER,[optimize]),
- ?line testSetTypeRefSeq_cases(?PER).
-
-testSetTypeRefSeq_cases(Rules) ->
- ?line testSetTypeRefSeq:main(Rules).
-
-
-
-testSetTypeRefSet(suite) -> [];
-testSetTypeRefSet(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetTypeRefSet:compile(Config,?BER,[]),
- ?line testSetTypeRefSet_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetTypeRefSet:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetTypeRefSet_cases(?BER)),
-
- ?line testSetTypeRefSet:compile(Config,?PER,[]),
- ?line testSetTypeRefSet_cases(?PER),
-
- ?line ?per_bit_opt(testSetTypeRefSet:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetTypeRefSet_cases(?PER)),
-
- ?line ?uper_bin(testSetTypeRefSet:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetTypeRefSet_cases(uper_bin)),
-
- ?line testSetTypeRefSet:compile(Config,?PER,[optimize]),
- ?line testSetTypeRefSet_cases(?PER).
-
-testSetTypeRefSet_cases(Rules) ->
- ?line testSetTypeRefSet:main(Rules).
-
-
-
-testSetOf(suite) -> [];
-testSetOf(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetOf:compile(Config,?BER,[]),
- ?line testSetOf_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetOf:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOf_cases(?BER)),
-
- ?line testSetOf:compile(Config,?PER,[]),
- ?line testSetOf_cases(?PER),
-
- ?line ?per_bit_opt(testSetOf:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOf_cases(?PER)),
-
- ?line ?uper_bin(testSetOf:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOf_cases(uper_bin)),
-
- ?line testSetOf:compile(Config,?PER,[optimize]),
- ?line testSetOf_cases(?PER).
-
-testSetOf_cases(Rules) ->
- ?line testSetOf:main(Rules).
-
-
-
-testSetOfCho(suite) -> [];
-testSetOfCho(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetOfCho:compile(Config,?BER,[]),
- ?line testSetOfCho_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetOfCho:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOfCho_cases(?BER)),
-
- ?line testSetOfCho:compile(Config,?PER,[]),
- ?line testSetOfCho_cases(?PER),
-
- ?line ?per_bit_opt(testSetOfCho:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOfCho_cases(?PER)),
-
- ?line ?uper_bin(testSetOfCho:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOfCho_cases(uper_bin)),
-
- ?line testSetOfCho:compile(Config,?PER,[optimize]),
- ?line testSetOfCho_cases(?PER).
-
-testSetOfCho_cases(Rules) ->
- ?line testSetOfCho:main(Rules).
-
-
-testSetOfExternal(suite) -> [];
-testSetOfExternal(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSetOfExternal:compile(Config,?BER,[]),
- ?line testSetOfExternal_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOfExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOfExternal_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testSetOfExternal:compile(Config,?PER,[]),
- ?line testSetOfExternal_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOfExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOfExternal_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOfExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOfExternal_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testSetOfExternal:compile(Config,?PER,[optimize]),
- ?line testSetOfExternal_cases(?PER).
-
-testSetOfExternal_cases(Rules) ->
- ?line testSetOfExternal:main(Rules).
-
-
-
-
-testSetOfTag(suite) -> [];
-testSetOfTag(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSetOfTag:compile(Config,?BER,[]),
- ?line testSetOfTag_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOfTag:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOfTag_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testSetOfTag:compile(Config,?PER,[]),
- ?line testSetOfTag_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOfTag:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOfTag_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOfTag:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOfTag_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testSetOfTag:compile(Config,?PER,[optimize]),
- ?line testSetOfTag_cases(?PER).
-
-testSetOfTag_cases(Rules) ->
- ?line testSetOfTag:main(Rules).
-
-
-c_syntax(suite) -> [];
-c_syntax(Config) ->
- ?line DataDir% ?line testExternal:compile(Config,?PER),
-% ?line testPrimExternal:compile(Config,?PER),
-% ?line testPrimExternal_cases(?PER).
- = ?config(data_dir,Config),
- ?line _TempDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line {error,_R1} = asn1ct:compile(filename:join(DataDir,"Syntax")),
- ?line {error,_R2} = asn1ct:compile(filename:join(DataDir,"BadTypeEnding")),
- ?line {error,_R3} = asn1ct:compile(filename:join(DataDir,
- "BadValueAssignment1")),
- ?line {error,_R4} = asn1ct:compile(filename:join(DataDir,
- "BadValueAssignment2")),
- ?line {error,_R5} = asn1ct:compile(filename:join(DataDir,
- "BadValueSet")),
- ?line {error,_R6} = asn1ct:compile(filename:join(DataDir,
- "ChoiceBadExtension")),
- ?line {error,_R7} = asn1ct:compile(filename:join(DataDir,
- "EnumerationBadExtension")),
- ?line {error,_R8} = asn1ct:compile(filename:join(DataDir,
- "Example")),
- ?line {error,_R9} = asn1ct:compile(filename:join(DataDir,
- "Export1")),
- ?line {error,_R10} = asn1ct:compile(filename:join(DataDir,
- "MissingEnd")),
- ?line {error,_R11} = asn1ct:compile(filename:join(DataDir,
- "SequenceBadComma")),
- ?line {error,_R12} = asn1ct:compile(filename:join(DataDir,
- "SequenceBadComponentName")),
- ?line {error,_R13} = asn1ct:compile(filename:join(DataDir,
- "SequenceBadComponentType")),
- ?line {error,_R14} = asn1ct:compile(filename:join(DataDir,
- "SeqBadComma")).
-
-
-c_string_per(suite) -> [];
-c_string_per(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line TempDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(filename:join(DataDir,"String"),[?PER,{outdir,TempDir}]).
-
-c_string_ber(suite) -> [];
-c_string_ber(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line TempDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(filename:join(DataDir,"String"),[?BER,{outdir,TempDir}]).
-
-
-c_implicit_before_choice(suite) -> [];
-c_implicit_before_choice(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line TempDir = ?config(priv_dir,Config),
- ?line {error,_R2} = asn1ct:compile(filename:join(DataDir,"CCSNARG3"),[?BER,{outdir,TempDir}]).
-
-parse(suite) -> [];
-parse(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- M1 = test_modules(),
-% M2 = parse_modules(),
- ?line ok = parse1(M1,DataDir,OutDir).
-
-parse1([M|T],DataDir,OutDir) ->
- ?line ok = asn1ct:compile(DataDir ++ M,[abs,{outdir,OutDir}]),
- parse1(T,DataDir,OutDir);
-parse1([],_,_) ->
- ok.
-
-per(suite) -> [];
-per(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = per1(per_modules(),DataDir,OutDir),
- ?line ?per_bit_opt(per1_bit_opt(per_modules(),DataDir,OutDir)),
- ?line ok = per1_opt(per_modules(),DataDir,OutDir).
-
-
-per1([M|T],DataDir,OutDir) ->
- ?line ok = asn1ct:compile(DataDir ++ M,[?PER,{outdir,OutDir}]),
- ?line ok = asn1ct:test(list_to_atom(M)),
- per1(T,DataDir,OutDir);
-per1([],_,_) ->
- ok.
-
-per1_bit_opt([M|T],DataDir,OutDir) ->
- ?line ok = asn1ct:compile(DataDir ++ M,[?PER,optimize,{outdir,OutDir}]),
- ?line ok = asn1ct:test(list_to_atom(M)),
- per1_bit_opt(T,DataDir,OutDir);
-per1_bit_opt([],_,_) ->
- ok.
-
-per1_opt([M|T],DataDir,OutDir) ->
- ?line ok = asn1ct:compile(DataDir ++ M,[?PER,optimized,{outdir,OutDir}]),
- ?line ok = asn1ct:test(list_to_atom(M)),
- per1_opt(T,DataDir,OutDir);
-per1_opt([],_,_) ->
- ok.
-
-
-ber_choiceinseq(suite) ->[];
-ber_choiceinseq(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(filename:join(DataDir,"ChoiceInSeq"),[?BER,{outdir,OutDir}]).
-
-ber_optional(suite) ->[];
-ber_optional(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(filename:join(DataDir,"SOpttest"),[?BER,{outdir,OutDir}]),
- ?line V = {'S',{'A',10,asn1_NOVALUE,asn1_NOVALUE},
- {'B',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE},
- {'C',asn1_NOVALUE,111,asn1_NOVALUE}},
- ?line {ok,B} = asn1_wrapper:encode('SOpttest','S',V),
- ?line Bytes = lists:flatten(B),
- ?line V2 = asn1_wrapper:decode('SOpttest','S',Bytes),
- ?line ok = eq(V,element(2,V2)).
-
-ber_optional_keyed_list(suite) ->[];
-ber_optional_keyed_list(Config) ->
- case ?BER of
- ber_bin_v2 -> ok;
- _ ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(filename:join(DataDir,"SOpttest"),
- [?BER,keyed_list,{outdir,OutDir}]),
- ?line Vrecord = {'S',{'A',10,asn1_NOVALUE,asn1_NOVALUE},
- {'B',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE},
- {'C',asn1_NOVALUE,111,asn1_NOVALUE}},
- ?line V = [ {a,[{scriptKey,10}]},
- {b,[]},
- {c,[{callingPartysCategory,111}]} ],
- ?line {ok,B} = asn1_wrapper:encode('SOpttest','S',V),
- ?line Bytes = lists:flatten(B),
- ?line V2 = asn1_wrapper:decode('SOpttest','S',Bytes),
- ?line ok = eq(Vrecord,element(2,V2))
- end.
-
-
-eq(V,V) ->
- ok.
-
-
-ber_other(suite) ->[];
-ber_other(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = ber1(ber_modules(),DataDir,OutDir).
-
-
-ber1([M|T],DataDir,OutDir) ->
- ?line ok = asn1ct:compile(DataDir ++ M,[?BER,{outdir,OutDir}]),
- ?line ok = asn1ct:test(list_to_atom(M)),
- ber1(T,DataDir,OutDir);
-ber1([],_,_) ->
- ok.
-
-default_per(suite) ->[];
-default_per(Config) ->
- default1(?PER,Config,[]).
-
-default_per_opt(suite) -> [];
-default_per_opt(Config) ->
- ?per_bit_opt(default1(?PER,Config,[optimize])),
- default1(?PER,Config,[optimize]).
-
-default_ber(suite) ->[];
-default_ber(Config) ->
- default1(?BER,Config,[]).
-
-default1(Rule,Config,Options) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(DataDir ++ "Def",[Rule,{outdir,OutDir}]++Options),
- ?line {ok,Bytes1} = asn1_wrapper:encode('Def','Def1',#'Def1'{bool0 = true,
- bool1 = true,
- bool2 = true,
- bool3 = true}),
- ?line {ok,{'Def1',true,true,true,true}} = asn1_wrapper:decode('Def','Def1',lists:flatten(Bytes1)),
-
- ?line {ok,Bytes2} = asn1_wrapper:encode('Def','Def1',#'Def1'{bool0 = true}),
- ?line {ok,{'Def1',true,false,false,false}} = asn1_wrapper:decode('Def','Def1',lists:flatten(Bytes2)),
-
- ?line {ok,Bytes3} = asn1_wrapper:encode('Def','Def1',#'Def1'{bool0 = true,bool2=false}),
- ?line {ok,{'Def1',true,false,false,false}} = asn1_wrapper:decode('Def','Def1',lists:flatten(Bytes3)).
-
-
-value_test(suite) ->[];
-value_test(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(DataDir ++ "ObjIdValues",[?BER,{outdir,OutDir}]),
- ?line {ok,_} = asn1_wrapper:encode('ObjIdValues','ObjIdType','ObjIdValues':'mobileDomainId'()),
- ?line ok = asn1ct:compile(DataDir ++ "ObjIdValues",[?PER,{outdir,OutDir}]),
- ?line {ok,_} = asn1_wrapper:encode('ObjIdValues','ObjIdType','ObjIdValues':'mobileDomainId'()),
- ?line ok = test_bad_values:tests(Config),
- ok.
-
-
-constructed(suite) ->
- [];
-constructed(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(DataDir ++ "Constructed",[?BER,{outdir,OutDir}]),
- ?line {ok,B} = asn1_wrapper:encode('Constructed','S',{'S',false}),
- ?line [40,3,1,1,0] = lists:flatten(B),
- ?line {ok,B1} = asn1_wrapper:encode('Constructed','S2',{'S2',false}),
- ?line [40,5,48,3,1,1,0] = lists:flatten(B1),
- ?line {ok,B2} = asn1_wrapper:encode('Constructed','I',10),
- ?line [136,1,10] = lists:flatten(B2),
- ok.
-
-ber_decode_error(suite) -> [];
-ber_decode_error(Config) ->
- ?line ok = ber_decode_error:compile(Config,?BER,[]),
- ?line ok = ber_decode_error:run([]),
-
- ?line ok = ?ber_driver(?BER,ber_decode_error:compile(Config,?BER,[driver])),
- ?line ok = ?ber_driver(?BER,ber_decode_error:run([driver])),
- ok.
-
-h323test(suite) ->
- [];
-h323test(Config) ->
- ?line ok = h323test:compile(Config,?PER,[]),
- ?line ok = h323test:run(?PER),
- ?line ?per_bit_opt(h323test:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(h323test:run(?PER)),
- ?line ?uper_bin(h323test:compile(Config,uper_bin,[])),
- ?line ?uper_bin(h323test:run(uper_bin)),
- ?line ok = h323test:compile(Config,?PER,[optimize]),
- ?line ok = h323test:run(?PER),
- ok.
-
-per_GeneralString(suite) ->
- [];
-per_GeneralString(Config) ->
- case erlang:module_loaded('MULTIMEDIA-SYSTEM-CONTROL') of
- true ->
- ok;
- false ->
- h323test:compile(Config,?PER,[])
- end,
- UI = [109,64,1,57],
- ?line {ok,_V} = asn1_wrapper:decode('MULTIMEDIA-SYSTEM-CONTROL',
- 'MultimediaSystemControlMessage',UI).
-
-per_open_type(suite) ->
- [];
-per_open_type(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line ok = asn1ct:compile(DataDir ++ "OpenType",[?PER,{outdir,OutDir}]),
- Stype = {'Stype',10,true},
- ?line {ok,Bytes} = asn1_wrapper:encode('OpenType','Ot',Stype),
- ?line {ok,Stype} = asn1_wrapper:decode('OpenType','Ot',Bytes),
-
- ?line ?per_bit_opt(ok = asn1ct:compile(DataDir ++ "OpenType",
- [?PER,optimize,{outdir,OutDir}])),
- ?line ?per_bit_opt({ok,Bytes}=asn1_wrapper:encode('OpenType','Ot',Stype)),
- ?line ?per_bit_opt({ok,Stype}=asn1_wrapper:decode('OpenType','Ot',Bytes)),
-
- ?line ?uper_bin(ok = asn1ct:compile(DataDir ++ "OpenType",
- [uper_bin,{outdir,OutDir}])),
- ?line ?uper_bin({ok,Bytes}=asn1_wrapper:encode('OpenType','Ot',Stype)),
- ?line ?uper_bin({ok,Stype}=asn1_wrapper:decode('OpenType','Ot',Bytes)),
-
- ?line ok = asn1ct:compile(DataDir ++ "OpenType",
- [?PER,optimize,{outdir,OutDir}]),
- ?line {ok,Bytes} = asn1_wrapper:encode('OpenType','Ot',Stype),
- ?line {ok,Stype} = asn1_wrapper:decode('OpenType','Ot',Bytes).
-
-testConstraints(suite) ->
- [];
-testConstraints(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testConstraints:compile(Config,?BER,[]),
- ?line testConstraints:int_constraints(?BER),
-
- ?line ?ber_driver(?BER,testConstraints:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testConstraints:int_constraints(?BER)),
-
- ?line testConstraints:compile(Config,?PER,[]),
- ?line testConstraints:int_constraints(?PER),
- ?line testConstraints:refed_NNL_name(?PER),
-
- ?line ?per_bit_opt(testConstraints:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testConstraints:int_constraints(?PER)),
- ?line ?per_bit_opt(testConstraints:refed_NNL_name(?PER)),
-
- ?line ?uper_bin(testConstraints:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testConstraints:int_constraints(uper_bin)),
- ?line ?uper_bin(testConstraints:refed_NNL_name(uper_bin)),
-
- ?line testConstraints:compile(Config,?PER,[optimize]),
- ?line testConstraints:int_constraints(?PER),
- ?line testConstraints:refed_NNL_name(?PER).
-
-testSeqIndefinite(suite) -> [];
-testSeqIndefinite(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSeqIndefinite:compile(Config,?BER,[]),
- ?line testSeqIndefinite:main(?BER),
-
- ?line ?ber_driver(?BER,testSeqIndefinite:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqIndefinite:main(?BER)).
-
-testSetIndefinite(suite) -> [];
-testSetIndefinite(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetIndefinite:compile(Config,?BER,[]),
- ?line testSetIndefinite:main(?BER),
-
- ?line ?ber_driver(?BER,testSetIndefinite:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetIndefinite:main(?BER)).
-
-testChoiceIndefinite(suite) -> [];
-testChoiceIndefinite(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testChoiceIndefinite:compile(Config,?BER,[]),
- ?line testChoiceIndefinite:main(?BER),
-
- ?line ?ber_driver(?BER,testChoiceIndefinite:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoiceIndefinite:main(?BER)).
-
-testInfObjectClass(suite) ->
- [];
-testInfObjectClass(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testInfObjectClass:compile(Config,?PER,[]),
- ?line testInfObjectClass:main(?PER),
- ?line testInfObj:compile(Config,?PER,[]),
- ?line testInfObj:main(?PER),
-
- ?line ?per_bit_opt(testInfObjectClass:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testInfObjectClass:main(?PER)),
- ?line ?per_bit_opt(testInfObj:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testInfObj:main(?PER)),
-
- ?line ?uper_bin(testInfObjectClass:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testInfObjectClass:main(uper_bin)),
- ?line ?uper_bin(testInfObj:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testInfObj:main(uper_bin)),
-
- ?line testInfObjectClass:compile(Config,?PER,[optimize]),
- ?line testInfObjectClass:main(?PER),
- ?line testInfObj:compile(Config,?PER,[optimize]),
- ?line testInfObj:main(?PER),
-
- ?line testInfObjectClass:compile(Config,?BER,[]),
- ?line testInfObjectClass:main(?BER),
- ?line testInfObj:compile(Config,?BER,[]),
- ?line testInfObj:main(?BER),
-
- ?line ?ber_driver(?BER,testInfObjectClass:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testInfObjectClass:main(?BER)),
- ?line ?ber_driver(?BER,testInfObj:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testInfObj:main(?BER)),
-
- ?line testInfObj:compile_RANAPfiles(Config,?PER,[]),
-
- ?line ?per_bit_opt(testInfObj:compile_RANAPfiles(Config,?PER,[optimize])),
-
- ?line ?uper_bin(testInfObj:compile_RANAPfiles(Config,uper_bin,[])),
-
- ?line testInfObj:compile_RANAPfiles(Config,?PER,[optimize]),
-
- ?line testInfObj:compile_RANAPfiles(Config,?BER,[]).
-
-testParameterizedInfObj(suite) ->
- [];
-testParameterizedInfObj(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testParameterizedInfObj:compile(Config,?PER,[]),
- ?line testParameterizedInfObj:main(?PER),
-
- ?line ?per_bit_opt(testParameterizedInfObj:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testParameterizedInfObj:main(?PER)),
-
- ?line ?uper_bin(testParameterizedInfObj:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testParameterizedInfObj:main(uper_bin)),
-
- ?line testParameterizedInfObj:compile(Config,?PER,[optimize]),
- ?line testParameterizedInfObj:main(?PER),
-
- ?line testParameterizedInfObj:compile(Config,?BER,[]),
- ?line testParameterizedInfObj:main(?BER),
-
- ?line ?ber_driver(?BER,testParameterizedInfObj:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testParameterizedInfObj:main(?BER)).
-
-testMergeCompile(suite) ->
- [];
-testMergeCompile(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testMergeCompile:compile(Config,?PER,[]),
- ?line testMergeCompile:main(?PER),
- ?line testMergeCompile:mvrasn(?PER),
-
- ?line ?per_bit_opt(testMergeCompile:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testMergeCompile:main(?PER)),
- ?line ?per_bit_opt(testMergeCompile:mvrasn(?PER)),
-
- ?line ?uper_bin(testMergeCompile:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testMergeCompile:main(uper_bin)),
- ?line ?uper_bin(testMergeCompile:mvrasn(uper_bin)),
-
- ?line testMergeCompile:compile(Config,?BER,[]),
- ?line testMergeCompile:main(?BER),
- ?line testMergeCompile:mvrasn(?BER),
-
- ?line ?ber_driver(?BER,testMergeCompile:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testMergeCompile:main(?BER)),
- ?line ?ber_driver(?BER,testMergeCompile:mvrasn(?BER)).
-
-testobj(suite) ->
- [];
-testobj(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line ok = testRANAP:compile(Config,?PER,[]),
- ?line ok = testRANAP:testobj(?PER),
- ?line ok = testParameterizedInfObj:ranap(?PER),
-
- ?line ?per_bit_opt(ok = testRANAP:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(ok = testRANAP:testobj(?PER)),
- ?line ?per_bit_opt(ok = testParameterizedInfObj:ranap(?PER)),
-
- ?line ?uper_bin(ok = testRANAP:compile(Config,uper_bin,[])),
- ?line ?uper_bin(ok = testRANAP:testobj(uper_bin)),
- ?line ?uper_bin(ok = testParameterizedInfObj:ranap(uper_bin)),
-
- ?line ok = testRANAP:compile(Config,?PER,[optimize]),
- ?line ok = testRANAP:testobj(?PER),
- ?line ok = testParameterizedInfObj:ranap(?PER),
-
- ?line ok = testRANAP:compile(Config,?BER,[]),
- ?line ok = testRANAP:testobj(?BER),
- ?line ok = testParameterizedInfObj:ranap(?BER),
-
- ?line ?ber_driver(?BER,testRANAP:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testRANAP:testobj(?BER)),
- ?line ?ber_driver(?BER,testParameterizedInfObj:ranap(?BER)).
-
-
-testDeepTConstr(suite) ->
- [];
-testDeepTConstr(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testDeepTConstr:compile(Config,?PER,[]),
- ?line testDeepTConstr:main(?PER),
-
- ?line ?per_bit_opt(testDeepTConstr:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testDeepTConstr:main(?PER)),
-
- ?line ?uper_bin(testDeepTConstr:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testDeepTConstr:main(uper_bin)),
-
- ?line testDeepTConstr:compile(Config,?PER,[optimize]),
- ?line testDeepTConstr:main(?PER),
-
- ?line testDeepTConstr:compile(Config,?BER,[]),
- ?line testDeepTConstr:main(?BER),
-
- ?line ?ber_driver(?BER,testDeepTConstr:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testDeepTConstr:main(?BER)).
-
-testInvokeMod(suite) ->
- [];
-testInvokeMod(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line ok = asn1ct:compile(filename:join(DataDir,"PrimStrings"),[{outdir,OutDir}]),
- ?line {ok,_Result1} = 'PrimStrings':encode('Bs1',[1,0,1,0]),
- ?line ok = asn1ct:compile(filename:join(DataDir,"PrimStrings"),[?PER,{outdir,OutDir}]),
- ?line {ok,_Result2} = 'PrimStrings':encode('Bs1',[1,0,1,0]).
-
-testExport(suite) ->
- [];
-testExport(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line {error,{asn1,_Reason}} = asn1ct:compile(filename:join(DataDir,"IllegalExport"),[{outdir,OutDir}]).
-
-testImport(suite) ->
- [];
-testImport(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line _OutDir = ?config(priv_dir,Config),
- ?line {error,_} = asn1ct:compile(filename:join(DataDir,"ImportsFrom"),[?BER]),
- ok.
-
-testMegaco(suite) ->
- [];
-testMegaco(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
- io:format("Config: ~p~n",[Config]),
- ?line {ok,ModuleName1,ModuleName2} = testMegaco:compile(Config,?BER,[]),
- ?line ok = testMegaco:main(ModuleName1,Config),
- ?line ok = testMegaco:main(ModuleName2,Config),
-
- case ?BER of
- ber_bin_v2 ->
- ?line {ok,ModuleName3,ModuleName4} = testMegaco:compile(Config,?BER,[driver]),
- ?line ok = testMegaco:main(ModuleName3,Config),
- ?line ok = testMegaco:main(ModuleName4,Config);
- _-> ok
- end,
-
- ?line {ok,ModuleName5,ModuleName6} = testMegaco:compile(Config,?PER,[]),
- ?line ok = testMegaco:main(ModuleName5,Config),
- ?line ok = testMegaco:main(ModuleName6,Config),
-
- ?line ?per_bit_opt({ok,ModuleName5,ModuleName6} = testMegaco:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(ok = testMegaco:main(ModuleName5,Config)),
- ?line ?per_bit_opt(ok = testMegaco:main(ModuleName6,Config)),
-
- ?line ?uper_bin({ok,ModuleName5,ModuleName6} = testMegaco:compile(Config,uper_bin,[])),
- ?line ?uper_bin(ok = testMegaco:main(ModuleName5,Config)),
- ?line ?uper_bin(ok = testMegaco:main(ModuleName6,Config)),
-
- ?line {ok,ModuleName7,ModuleName8} = testMegaco:compile(Config,?PER,[optimize]),
- ?line ok = testMegaco:main(ModuleName7,Config),
- ?line ok = testMegaco:main(ModuleName8,Config).
-
-
-testMvrasn6(suite) -> [];
-testMvrasn6(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testMvrasn6:compile(Config,?BER),
- ?line testMvrasn6:main().
-
-testContextSwitchingTypes(suite) -> [];
-testContextSwitchingTypes(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testContextSwitchingTypes:compile(Config,?BER,[]),
- ?line testContextSwitchingTypes:test(),
-
- ?line ?ber_driver(?BER,testContextSwitchingTypes:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testContextSwitchingTypes:test()),
-
- ?line testContextSwitchingTypes:compile(Config,?PER,[]),
- ?line testContextSwitchingTypes:test(),
-
- ?line ?per_bit_opt(testContextSwitchingTypes:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testContextSwitchingTypes:test()),
-
- ?line ?uper_bin(testContextSwitchingTypes:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testContextSwitchingTypes:test()),
-
- ?line testContextSwitchingTypes:compile(Config,?PER,[optimize]),
- ?line testContextSwitchingTypes:test().
-
-testTypeValueNotation(suite) -> [];
-testTypeValueNotation(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- case ?BER of
- Ber when Ber == ber; Ber == ber_bin ->
- ?line testTypeValueNotation:compile(Config,?BER,[]),
- ?line testTypeValueNotation:main(?BER,dummy);
- _ ->
- ok
- end,
-
- ?line ?ber_driver(?BER,testTypeValueNotation:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testTypeValueNotation:main(?BER,optimize)),
-
- case ?BER of
- Ber2 when Ber2 == ber; Ber2 == ber_bin ->
- ?line testTypeValueNotation:compile(Config,?PER,[]),
- ?line testTypeValueNotation:main(?PER,dummy);
- _ ->
- ok
- end,
-
- ?line ?per_bit_opt(testTypeValueNotation:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testTypeValueNotation:main(?PER,optimize)),
-
- ?line ?uper_bin(testTypeValueNotation:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testTypeValueNotation:main(uper_bin,optimize)),
- case ?BER of
- Ber3 when Ber3 == ber; Ber3 == ber_bin ->
- ?line testTypeValueNotation:compile(Config,?PER,[optimize]),
- ?line testTypeValueNotation:main(?PER,optimize);
- _ ->
- ok
- end.
-
-testOpenTypeImplicitTag(suite) -> [];
-testOpenTypeImplicitTag(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testOpenTypeImplicitTag:compile(Config,?BER,[]),
- ?line testOpenTypeImplicitTag:main(?BER),
-
- ?line ?ber_driver(?BER,testOpenTypeImplicitTag:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testOpenTypeImplicitTag:main(?BER)),
-
- ?line testOpenTypeImplicitTag:compile(Config,?PER,[]),
- ?line testOpenTypeImplicitTag:main(?PER),
-
- ?line ?per_bit_opt(testOpenTypeImplicitTag:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testOpenTypeImplicitTag:main(?PER)),
-
- ?line ?uper_bin(testOpenTypeImplicitTag:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testOpenTypeImplicitTag:main(uper_bin)),
-
- ?line testOpenTypeImplicitTag:compile(Config,?PER,[optimize]),
- ?line testOpenTypeImplicitTag:main(?PER).
-
-duplicate_tags(suite) -> [];
-duplicate_tags(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- {error,{asn1,[{error,{type,_,_,'SeqOpt1Imp',{asn1,{duplicates_of_the_tags,_}}}}]}} =
- asn1ct:compile(filename:join(DataDir,"SeqOptional2"),[abs]),
- ok.
-
-rtUI(suite) -> [];
-rtUI(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line ok = asn1ct:compile(filename:join(DataDir,"Prim"),[?BER]),
- ?line {ok,_} = asn1rt:info('Prim'),
-
- ?line ok = asn1ct:compile(filename:join(DataDir,"Prim"),[?PER]),
- ?line {ok,_} = asn1rt:info('Prim'),
-
- ?line ok = asn1rt:load_driver(),
- ?line ok = asn1rt:load_driver(),
- ?line ok = asn1rt:unload_driver().
-
-testROSE(suite) -> [];
-testROSE(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testROSE:compile(Config,?BER,[]),
-
- ?line testROSE:compile(Config,?PER,[]),
- ?line ?per_bit_opt(testROSE:compile(Config,?PER,[optimize])),
- ?line ?uper_bin(testROSE:compile(Config,uper_bin,[])),
- ?line testROSE:compile(Config,?PER,[optimize]).
-
-testINSTANCE_OF(suite) -> [];
-testINSTANCE_OF(Config) ->
- ?line testINSTANCE_OF:compile(Config,?BER,[]),
- ?line testINSTANCE_OF:main(?BER),
-
- ?line ?ber_driver(?BER,testINSTANCE_OF:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testINSTANCE_OF:main(?BER)),
-
- ?line testINSTANCE_OF:compile(Config,?PER,[]),
- ?line testINSTANCE_OF:main(?PER),
-
- ?line ?per_bit_opt(testINSTANCE_OF:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testINSTANCE_OF:main(?PER)),
-
- ?line ?uper_bin(testINSTANCE_OF:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testINSTANCE_OF:main(uper_bin)),
-
- ?line testINSTANCE_OF:compile(Config,?PER,[optimize]),
- ?line testINSTANCE_OF:main(?PER).
-
-testTCAP(suite) -> [];
-testTCAP(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testTCAP:compile(Config,?BER,[]),
- ?line testTCAP:test(?BER,Config),
-
- ?line ?ber_driver(?BER,testTCAP:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testTCAP:test(?BER,Config)),
-
- ?line ?ber_driver(?BER,testTCAP:compile_asn1config(Config,?BER,[asn1config])),
- ?line ?ber_driver(?BER,testTCAP:test_asn1config()).
-
-testDER(suite) ->[];
-testDER(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testDER:compile(Config,?BER,[]),
- ?line testDER:test(),
-
- ?line ?ber_driver(?BER,testDER:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testDER:test()),
-
- ?line testParamBasic:compile_der(Config,?BER),
- ?line testParamBasic_cases(der),
-
-
- ?line testSeqSetDefaultVal:compile(Config,?BER),
- ?line testSeqSetDefaultVal_cases(?BER).
-
-testSeqSetDefaultVal_cases(?BER) ->
- ?line testSeqSetDefaultVal:main(?BER).
-
-
-specialized_decodes(suite) -> [];
-specialized_decodes(Config) ->
- ?line test_partial_incomplete_decode:compile(Config,?BER,[optimize]),
- ?line test_partial_incomplete_decode:test(?BER,Config),
- ?line test_selective_decode:test(?BER,Config).
-
-special_decode_performance(suite) ->[];
-special_decode_performance(Config) ->
- ?line ?ber_driver(?BER,test_special_decode_performance:compile(Config,?BER)),
- ?line ?ber_driver(?BER,test_special_decode_performance:go(all)).
-
-
-test_driver_load(suite) -> [];
-test_driver_load(Config) ->
- ?line test_driver_load:compile(Config,?PER),
- ?line test_driver_load:test(?PER,5).
-
-test_ParamTypeInfObj(suite) -> [];
-test_ParamTypeInfObj(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line ok = asn1ct:compile(filename:join(DataDir,"IN-CS-1-Datatypes"),[ber_bin]).
-
-test_WS_ParamClass(suite) -> [];
-test_WS_ParamClass(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line ok = asn1ct:compile(filename:join(DataDir,"InformationFramework"),
- [ber_bin]).
-
-test_Defed_ObjectIdentifier(suite) -> [];
-test_Defed_ObjectIdentifier(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line ok = asn1ct:compile(filename:join(DataDir,"UsefulDefinitions"),
- [ber_bin]).
-
-testSelectionType(suite) -> [];
-testSelectionType(Config) ->
-
- ?line ok = testSelectionTypes:compile(Config,?BER,[]),
- ?line {ok,_} = testSelectionTypes:test(),
-
- ?line ok = testSelectionTypes:compile(Config,?PER,[]),
- ?line {ok,_} = testSelectionTypes:test().
-
-testSSLspecs(suite) -> [];
-testSSLspecs(Config) ->
-
- ?line ok = testSSLspecs:compile(Config,?BER,
- [optimize,compact_bit_string,der]),
- ?line testSSLspecs:run(?BER),
-
- case code:which(asn1ct) of
- cover_compiled ->
- ok;
- _ ->
- ?line ok = testSSLspecs:compile_inline(Config,?BER),
- ?line ok = testSSLspecs:run_inline(?BER)
- end.
-
-testNortel(suite) -> [];
-testNortel(Config) ->
- ?line DataDir = ?config(data_dir,Config),
-
- ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"),[?BER]),
- ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"),
- [?BER,optimize]),
- ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"),
- [?BER,optimize,driver]),
- ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"),[?PER]),
- ?line ?per_bit_opt(ok = asn1ct:compile(filename:join(DataDir,"Nortel"),
- [?PER,optimize])),
- ?line ?uper_bin(ok = asn1ct:compile(filename:join(DataDir,"Nortel"),[uper_bin])),
- ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"),
- [?PER,optimize]).
-test_undecoded_rest(suite) -> [];
-test_undecoded_rest(Config) ->
-
- ?line ok = test_undecoded_rest:compile(Config,?BER,[]),
- ?line ok = test_undecoded_rest:test([]),
-
- ?line ok = test_undecoded_rest:compile(Config,?BER,[undec_rest]),
- ?line ok = test_undecoded_rest:test(undec_rest),
-
- ?line ok = test_undecoded_rest:compile(Config,?PER,[]),
- ?line ok = test_undecoded_rest:test([]),
-
- ?line ?per_bit_opt(ok = test_undecoded_rest:compile(Config,?PER,[optimize,undec_rest])),
- ?line ?per_bit_opt(ok = test_undecoded_rest:test(undec_rest)),
-
- ?line ?uper_bin(ok = test_undecoded_rest:compile(Config,uper_bin,[undec_rest])),
- ?line ?uper_bin(ok = test_undecoded_rest:test(undec_rest)),
-
- ?line ok = test_undecoded_rest:compile(Config,?PER,[undec_rest]),
- ?line ok = test_undecoded_rest:test(undec_rest).
-
-test_inline(suite) -> [];
-test_inline(Config) ->
- case code:which(asn1ct) of
- cover_compiled ->
- {skip,"Not runnable when cover compiled"};
- _ ->
- ?line ok=test_inline:compile(Config,?BER,[]),
- ?line test_inline:main(?BER),
- ?line test_inline:inline1(Config,?BER,[]),
- ?line test_inline:performance2()
- end.
-
-%test_inline_prf(suite) -> [];
-%test_inline_prf(Config) ->
-% ?line test_inline:performance(Config).
-
-testTcapsystem(suite) -> [];
-testTcapsystem(Config) ->
- ?line ok=testTcapsystem:compile(Config,?BER,[]).
-
-testNBAPsystem(suite) -> [];
-testNBAPsystem(Config) ->
- ?line ok=testNBAPsystem:compile(Config,?PER,?per_optimize(?BER)),
- ?line ok=testNBAPsystem:test(?PER,Config).
-
-test_compile_options(suite) -> [];
-test_compile_options(Config) ->
- case code:which(asn1ct) of
- cover_compiled ->
- {skip,"Not runnable when cover compiled"};
- _ ->
- ?line ok = test_compile_options:wrong_path(Config),
- ?line ok = test_compile_options:path(Config),
- ?line ok = test_compile_options:noobj(Config),
- ?line ok = test_compile_options:record_name_prefix(Config),
- ?line ok = test_compile_options:verbose(Config)
- end.
-testDoubleEllipses(suite) -> [];
-testDoubleEllipses(Config) ->
- ?line testDoubleEllipses:compile(Config,?BER,[]),
- ?line testDoubleEllipses:main(?BER),
- ?line ?ber_driver(?BER,testDoubleEllipses:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testDoubleEllipses:main(?BER)),
- ?line ?per_bit_opt(testDoubleEllipses:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testDoubleEllipses:main(?PER)),
- ?line ?uper_bin(testDoubleEllipses:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testDoubleEllipses:main(uper_bin)),
- ?line testDoubleEllipses:compile(Config,?PER,?per_optimize(?BER)),
- ?line testDoubleEllipses:main(?PER).
-
-test_modified_x420(suite) -> [];
-test_modified_x420(Config) ->
- ?line test_modified_x420:compile(Config),
- ?line test_modified_x420:test_io(Config).
-
-testX420(suite) -> [];
-testX420(Config) ->
- ?line testX420:compile(?BER,[der],Config),
- ?line ok = testX420:ticket7759(?BER,Config),
- ?line testX420:compile(?PER,[],Config).
-
-test_x691(suite) -> [];
-test_x691(Config) ->
- case ?PER of
- per ->
- ?line ok = test_x691:compile(Config,uper_bin,[]),
- ?line true = test_x691:cases(uper_bin,unaligned),
- ?line ok = test_x691:compile(Config,?PER,[]),
- ?line true = test_x691:cases(?PER,aligned),
-%% ?line ok = asn1_test_lib:ticket_7678(Config,[]),
- ?line ok = asn1_test_lib:ticket_7708(Config,[]),
- ?line ok = asn1_test_lib:ticket_7763(Config);
- _ ->
- ?line ok = test_x691:compile(Config,?PER,?per_optimize(?BER)),
- ?line true = test_x691:cases(?PER,aligned)
- end.
-%% ?line ok = asn1_test_lib:ticket_7876(Config,?PER,[]),
-%% ?line ok = asn1_test_lib:ticket_7876(Config,?PER,[compact_bit_string]),
-%% ?line ok = asn1_test_lib:ticket_7876(Config,?PER,[optimize]),
-%% ?line ok = asn1_test_lib:ticket_7876(Config,?PER,[optimize,compact_bit_string]).
-
-
-ticket_6143(suite) -> [];
-ticket_6143(Config) ->
- ?line ok = test_compile_options:ticket_6143(Config).
-
-testExtensionAdditionGroup(suite) -> [];
-testExtensionAdditionGroup(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line PrivDir = ?config(priv_dir,Config),
- ?line Path = code:get_path(),
- ?line code:add_patha(PrivDir),
- DoIt = fun(Erule) ->
- ?line ok = asn1ct:compile(filename:join(DataDir,"Extension-Addition-Group"),[Erule,{outdir,PrivDir}]),
- ?line {ok,_M} = compile:file(filename:join(DataDir,"extensionAdditionGroup"),[{i,PrivDir},{outdir,PrivDir},debug_info]),
- ?line ok = extensionAdditionGroup:run(Erule)
- end,
- ?line [DoIt(Rule)|| Rule <- [per_bin,uper_bin,ber_bin]],
- ?line code:set_path(Path).
-
-
-
-% parse_modules() ->
-% ["ImportsFrom"].
-
-per_modules() ->
- [X || X <- test_modules()].
-ber_modules() ->
- [X || X <- test_modules(),
- X =/= "CommonDataTypes",
- X =/= "DS-EquipmentUser-CommonFunctionOrig-TransmissionPath",
- X =/= "H323-MESSAGES",
- X =/= "H235-SECURITY-MESSAGES",
- X =/= "MULTIMEDIA-SYSTEM-CONTROL"].
-test_modules() ->
- _Modules = [
- "BitStr",
- "CommonDataTypes",
- "Constraints",
- "ContextSwitchingTypes",
- "DS-EquipmentUser-CommonFunctionOrig-TransmissionPath",
- "Enum",
- "From",
- "H235-SECURITY-MESSAGES",
- "H323-MESSAGES",
- %%"MULTIMEDIA-SYSTEM-CONTROL", recursive type , problem for asn1ct:value
- "Import",
- "Int",
- "MAP-commonDataTypes",
-% ambigous tags "MAP-insertSubscriberData-def",
- "Null",
- "Octetstr",
- "One",
- "P-Record",
- "P",
-% "PDUs",
- "Person",
- "PrimStrings",
- "Real",
- "XSeq",
- "XSeqOf",
- "XSet",
- "XSetOf",
- "String",
- "SwCDR",
-% "Syntax",
- "Time"
-% ANY "Tst",
-% "Two",
-% errors that should be detected "UndefType"
-] ++
- [
- "SeqSetLib", % must be compiled before Seq and Set
- "Seq",
- "Set",
- "SetOf",
- "SeqOf",
- "Prim",
- "Cho",
- "Def",
- "Opt",
- "ELDAPv3",
- "LDAP"
- ].
-
-
-common() ->
-[].
-
-particular() ->
-[].
diff --git a/lib/asn1/test/asn1_bin_v2_SUITE.erl b/lib/asn1/test/asn1_bin_v2_SUITE.erl
deleted file mode 100644
index 2273ca9918..0000000000
--- a/lib/asn1/test/asn1_bin_v2_SUITE.erl
+++ /dev/null
@@ -1,2474 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, 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 ASN.1 application
-
--module(asn1_bin_v2_SUITE).
--define(PER,'per_bin').
--define(BER,'ber_bin_v2').
--define(ber_driver(Erule,Func),
- case Erule of
- ber_bin_v2 ->
- Func;
- _ -> ok
- end).
--define(per_optimize(Erule),
- case Erule of
- ber_bin_v2 ->[optimize];
- _ -> []
- end).
--define(per_bit_opt(FuncCall),
- case ?BER of
- ber_bin_v2 -> FuncCall;
-% _ -> {skip,"only for bit optimized per_bin"}
- _ -> ok
- end).
--define(uper_bin(FuncCall),
- case ?PER of
- per -> FuncCall;
- _ -> ok
- end).
-
--compile(export_all).
-%%-export([Function/Arity, ...]).
-
--include_lib("test_server/include/test_server.hrl").
-
-%% records used by test-case default
--record('Def1',{
-bool0, bool1 = asn1_DEFAULT, bool2 = asn1_DEFAULT, bool3 = asn1_DEFAULT}).
-
-%-record('Def2',{
-%bool10, bool11 = asn1_DEFAULT, bool12 = asn1_DEFAULT, bool13}).
-
-%-record('Def3',{
-%bool30 = asn1_DEFAULT, bool31 = asn1_DEFAULT, bool32 = asn1_DEFAULT, bool33 = asn1_DEFAULT}).
-
-
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [{group, compile}, parse, default_per, default_ber,
- default_per_opt, per, {group, ber}, testPrim,
- testPrimStrings, testPrimExternal, testChoPrim,
- testChoExtension, testChoExternal, testChoOptional,
- testChoOptionalImplicitTag, testChoRecursive,
- testChoTypeRefCho, testChoTypeRefPrim,
- testChoTypeRefSeq, testChoTypeRefSet, testDef, testOpt,
- testSeqDefault, testSeqExtension, testSeqExternal,
- testSeqOptional, testSeqPrim, testSeqTag,
- testSeqTypeRefCho, testSeqTypeRefPrim,
- testSeqTypeRefSeq, testSeqTypeRefSet, testSeqOf,
- testSeqOfIndefinite, testSeqOfCho, testSeqOfExternal,
- testSetDefault, testSetExtension,
- testExtensionAdditionGroup, testSetExternal,
- testSeqOfTag, testSetOptional, testSetPrim, testSetTag,
- testSetTypeRefCho, testSetTypeRefPrim,
- testSetTypeRefSeq, testSetTypeRefSet, testSetOf,
- testSetOfCho, testSetOfExternal, testSetOfTag,
- testEnumExt, value_test, testSeq2738, constructed,
- ber_decode_error, h323test, testSeqIndefinite,
- testSetIndefinite, testChoiceIndefinite,
- per_GeneralString, per_open_type, testInfObjectClass,
- testParameterizedInfObj, testMergeCompile, testobj,
- testDeepTConstr, testConstraints, testInvokeMod,
- testExport, testImport, testCompactBitString,
- testMegaco, testParamBasic, testMvrasn6,
- testContextSwitchingTypes, testTypeValueNotation,
- testOpenTypeImplicitTag, duplicate_tags, rtUI, testROSE,
- testINSTANCE_OF, testTCAP, testDER, specialized_decodes,
- special_decode_performance, test_driver_load,
- test_ParamTypeInfObj, test_WS_ParamClass,
- test_Defed_ObjectIdentifier, testSelectionType,
- testSSLspecs, testNortel, test_undecoded_rest,
- test_inline, testTcapsystem, testNBAPsystem,
- test_compile_options, testDoubleEllipses,
- test_modified_x420, testX420, test_x691, ticket_6143,
- testExtensionAdditionGroup] ++ common() ++ particular().
-
-groups() ->
- [{option_tests, [],
- [test_compile_options, ticket_6143]},
- {infobj, [],
- [testInfObjectClass, testParameterizedInfObj,
- testMergeCompile, testobj, testDeepTConstr]},
- {performance, [],
- [testTimer_ber, testTimer_ber_opt_driver, testTimer_per,
- testTimer_per_opt, testTimer_uper_bin]},
- {bugs, [],
- [test_ParamTypeInfObj, test_WS_ParamClass,
- test_Defed_ObjectIdentifier]},
- {compile, [],
- [c_syntax, c_string_per, c_string_ber,
- c_implicit_before_choice]},
- {ber, [],
- [ber_choiceinseq, ber_optional, ber_optional_keyed_list,
- ber_other]}].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-%all(suite) -> [test_inline,testNBAPsystem,test_compile_options,ticket_6143].
-
-init_per_testcase(Func,Config) ->
- %%?line test_server:format("Func: ~p~n",[Func]),
- ?line {ok, _} = file:read_file_info(filename:join([?config(priv_dir,Config)])),
- ?line code:add_patha(?config(priv_dir,Config)),
- Dog=
- case Func of
- testX420 ->
- test_server:timetrap({minutes,60}); % 60 minutes
- _ ->
- test_server:timetrap({minutes,30}) % 60 minutes
- end,
- %% Dog=test_server:timetrap(1800000), % 30 minutes
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Func,Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog).
-
-
-testPrim(suite) -> [];
-testPrim(Config) ->
- ?line testPrim:compile(Config,?BER,[]),
- ?line testPrim_cases(?BER),
- ?line ?ber_driver(?BER,testPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testPrim_cases(?BER)),
- ?line testPrim:compile(Config,?PER,[]),
- ?line testPrim_cases(?PER),
- ?line ?per_bit_opt(testPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testPrim_cases(?PER)),
- ?line ?uper_bin(testPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testPrim_cases(uper_bin)),
- ?line testPrim:compile(Config,?PER,[optimize]),
- ?line testPrim_cases(?PER).
-
-testPrim_cases(Rules) ->
- ?line testPrim:bool(Rules),
- ?line testPrim:int(Rules),
- ?line testPrim:enum(Rules),
- ?line testPrim:obj_id(Rules),
- ?line testPrim:rel_oid(Rules),
- ?line testPrim:null(Rules),
- ?line testPrim:real(Rules).
-
-
-testCompactBitString(suite) -> [];
-testCompactBitString(Config) ->
-
- ?line testCompactBitString:compile(Config,?BER,[compact_bit_string]),
- ?line testCompactBitString:compact_bit_string(?BER),
-
- ?line ?ber_driver(?BER,testCompactBitString:compile(Config,?BER,[compact_bit_string,driver])),
- ?line ?ber_driver(?BER,testCompactBitString:compact_bit_string(?BER)),
-
- ?line testCompactBitString:compile(Config,?PER,[compact_bit_string]),
- ?line testCompactBitString:compact_bit_string(?PER),
- ?line testCompactBitString:bit_string_unnamed(?PER),
-
- ?line ?per_bit_opt(testCompactBitString:compile(Config,?PER,
- [compact_bit_string,optimize])),
- ?line ?per_bit_opt(testCompactBitString:compact_bit_string(?PER)),
- ?line ?per_bit_opt(testCompactBitString:bit_string_unnamed(?PER)),
- ?line ?per_bit_opt(testCompactBitString:ticket_7734(?PER)),
-
- ?line ?uper_bin(testCompactBitString:compile(Config,uper_bin,
- [compact_bit_string])),
- ?line ?uper_bin(testCompactBitString:compact_bit_string(uper_bin)),
- ?line ?uper_bin(testCompactBitString:bit_string_unnamed(uper_bin)),
-
- ?line testCompactBitString:compile(Config,?PER,[optimize,compact_bit_string]),
- ?line testCompactBitString:compact_bit_string(?PER),
- ?line testCompactBitString:bit_string_unnamed(?PER),
-
- ?line testCompactBitString:otp_4869(?PER).
-
-
-testPrimStrings(suite) -> [];
-testPrimStrings(Config) ->
-
- ?line testPrimStrings:compile(Config,?BER,[]),
- ?line testPrimStrings_cases(?BER),
- ?line testPrimStrings:more_strings(?BER), %% these are not implemented in per yet
- ?line ?ber_driver(?BER,testPrimStrings:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testPrimStrings_cases(?BER)),
- ?line ?ber_driver(?BER,testPrimStrings:more_strings(?BER)),
-
- ?line testPrimStrings:compile(Config,?PER,[]),
- ?line testPrimStrings_cases(?PER),
-
- ?line ?per_bit_opt(testPrimStrings:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testPrimStrings_cases(?PER)),
-
- ?line ?uper_bin(testPrimStrings:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testPrimStrings_cases(uper_bin)),
-
- ?line testPrimStrings:compile(Config,?PER,[optimize]),
- ?line testPrimStrings_cases(?PER).
-
-testPrimStrings_cases(Rules) ->
- ?line testPrimStrings:bit_string(Rules),
- ?line testPrimStrings:bit_string_unnamed(Rules),
- ?line testPrimStrings:octet_string(Rules),
- ?line testPrimStrings:numeric_string(Rules),
- ?line testPrimStrings:other_strings(Rules),
- ?line testPrimStrings:universal_string(Rules),
- ?line testPrimStrings:bmp_string(Rules),
- ?line testPrimStrings:times(Rules),
- ?line testPrimStrings:utf8_string(Rules).
-
-
-
-testPrimExternal(suite) -> [];
-testPrimExternal(Config) ->
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testPrimExternal:compile(Config,?BER,[]),
- ?line testPrimExternal_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testPrimExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testPrimExternal_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testPrimExternal:compile(Config,?PER,[]),
- ?line testPrimExternal_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testPrimExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testPrimExternal_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testPrimExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testPrimExternal_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testPrimExternal:compile(Config,?PER,[optimize]),
- ?line testPrimExternal_cases(?PER).
-
-testPrimExternal_cases(Rules) ->
- ?line testPrimExternal:external(Rules).
-
-
-
-
-testChoPrim(suite) -> [];
-testChoPrim(Config) ->
-
- ?line testChoPrim:compile(Config,?BER,[]),
- ?line testChoPrim_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoPrim_cases(?BER)),
-
- ?line testChoPrim:compile(Config,?PER,[]),
- ?line testChoPrim_cases(?PER),
-
- ?line ?per_bit_opt(testChoPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoPrim_cases(?PER)),
-
- ?line ?uper_bin(testChoPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoPrim_cases(uper_bin)),
-
- ?line testChoPrim:compile(Config,?PER,[optimize]),
- ?line testChoPrim_cases(?PER).
-
-testChoPrim_cases(Rules) ->
- ?line testChoPrim:bool(Rules),
- ?line testChoPrim:int(Rules).
-
-
-
-testChoExtension(suite) -> [];
-testChoExtension(Config) ->
-
- ?line testChoExtension:compile(Config,?BER,[]),
- ?line testChoExtension_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoExtension:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoExtension_cases(?BER)),
-
- ?line testChoExtension:compile(Config,?PER,[]),
- ?line testChoExtension_cases(?PER),
-
- ?line ?per_bit_opt(testChoExtension:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoExtension_cases(?PER)),
-
- ?line ?uper_bin(testChoExtension:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoExtension_cases(uper_bin)),
-
- ?line testChoExtension:compile(Config,?PER,[optimize]),
- ?line testChoExtension_cases(?PER).
-
-testChoExtension_cases(Rules) ->
- ?line testChoExtension:extension(Rules).
-
-
-
-testChoExternal(suite) -> [];
-testChoExternal(Config) ->
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testChoExternal:compile(Config,?BER,[]),
- ?line testChoExternal_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoExternal_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testChoExternal:compile(Config,?PER,[]),
- ?line testChoExternal_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoExternal_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoExternal_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testChoExternal:compile(Config,?PER,[optimize]),
- ?line testChoExternal_cases(?PER).
-
-
-testChoExternal_cases(Rules) ->
- ?line testChoExternal:external(Rules).
-
-
-
-testChoOptional(suite) -> [];
-testChoOptional(Config) ->
-
- ?line testChoOptional:compile(Config,?BER,[]),
- ?line testChoOptional_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoOptional:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoOptional_cases(?BER)),
-
- ?line testChoOptional:compile(Config,?PER,[]),
- ?line testChoOptional_cases(?PER),
-
- ?line ?per_bit_opt(testChoOptional:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoOptional_cases(?PER)),
-
- ?line ?uper_bin(testChoOptional:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoOptional_cases(uper_bin)),
-
- ?line testChoOptional:compile(Config,?PER,[optimize]),
- ?line testChoOptional_cases(?PER).
-
-testChoOptional_cases(Rules) ->
- ?line testChoOptional:optional(Rules).
-
-testChoOptionalImplicitTag(suite) -> [];
-testChoOptionalImplicitTag(Config) ->
- %% Only meaningful for ?BER
- ?line testChoOptionalImplicitTag:compile(Config,?BER),
- ?line testChoOptionalImplicitTag:optional(?BER).
-
-
-testChoRecursive(suite) -> [];
-testChoRecursive(Config) ->
-
- ?line testChoRecursive:compile(Config,?BER,[]),
- ?line testChoRecursive_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoRecursive:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoRecursive_cases(?BER)),
-
- ?line testChoRecursive:compile(Config,?PER,[]),
- ?line testChoRecursive_cases(?PER),
-
- ?line ?per_bit_opt(testChoRecursive:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoRecursive_cases(?PER)),
-
- ?line ?uper_bin(testChoRecursive:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoRecursive_cases(uper_bin)),
-
- ?line testChoRecursive:compile(Config,?PER,[optimize]),
- ?line testChoRecursive_cases(?PER).
-
-testChoRecursive_cases(Rules) ->
- ?line testChoRecursive:recursive(Rules).
-
-
-
-testChoTypeRefCho(suite) -> [];
-testChoTypeRefCho(Config) ->
-
- ?line testChoTypeRefCho:compile(Config,?BER,[]),
- ?line testChoTypeRefCho_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoTypeRefCho:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoTypeRefCho_cases(?BER)),
-
- ?line testChoTypeRefCho:compile(Config,?PER,[]),
- ?line testChoTypeRefCho_cases(?PER),
-
- ?line ?per_bit_opt(testChoTypeRefCho:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoTypeRefCho_cases(?PER)),
-
- ?line ?uper_bin(testChoTypeRefCho:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoTypeRefCho_cases(uper_bin)),
-
- ?line testChoTypeRefCho:compile(Config,?PER,[optimize]),
- ?line testChoTypeRefCho_cases(?PER).
-
-testChoTypeRefCho_cases(Rules) ->
- ?line testChoTypeRefCho:choice(Rules).
-
-
-
-testChoTypeRefPrim(suite) -> [];
-testChoTypeRefPrim(Config) ->
-
- ?line testChoTypeRefPrim:compile(Config,?BER,[]),
- ?line testChoTypeRefPrim_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoTypeRefPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoTypeRefPrim_cases(?BER)),
-
- ?line testChoTypeRefPrim:compile(Config,?PER,[]),
- ?line testChoTypeRefPrim_cases(?PER),
-
- ?line ?per_bit_opt(testChoTypeRefPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoTypeRefPrim_cases(?PER)),
-
- ?line ?uper_bin(testChoTypeRefPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoTypeRefPrim_cases(uper_bin)),
-
- ?line testChoTypeRefPrim:compile(Config,?PER,[optimize]),
- ?line testChoTypeRefPrim_cases(?PER).
-
-testChoTypeRefPrim_cases(Rules) ->
- ?line testChoTypeRefPrim:prim(Rules).
-
-
-
-testChoTypeRefSeq(suite) -> [];
-testChoTypeRefSeq(Config) ->
-
- ?line testChoTypeRefSeq:compile(Config,?BER,[]),
- ?line testChoTypeRefSeq_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoTypeRefSeq:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoTypeRefSeq_cases(?BER)),
-
- ?line testChoTypeRefSeq:compile(Config,?PER,[]),
- ?line testChoTypeRefSeq_cases(?PER),
-
- ?line ?per_bit_opt(testChoTypeRefSeq:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoTypeRefSeq_cases(?PER)),
-
- ?line ?uper_bin(testChoTypeRefSeq:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoTypeRefSeq_cases(uper_bin)),
-
- ?line testChoTypeRefSeq:compile(Config,?PER,[optimize]),
- ?line testChoTypeRefSeq_cases(?PER).
-
-testChoTypeRefSeq_cases(Rules) ->
- ?line testChoTypeRefSeq:seq(Rules).
-
-
-
-testChoTypeRefSet(suite) -> [];
-testChoTypeRefSet(Config) ->
-
- ?line testChoTypeRefSet:compile(Config,?BER,[]),
- ?line testChoTypeRefSet_cases(?BER),
-
- ?line ?ber_driver(?BER,testChoTypeRefSet:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoTypeRefSet_cases(?BER)),
-
- ?line testChoTypeRefSet:compile(Config,?PER,[]),
- ?line testChoTypeRefSet_cases(?PER),
-
- ?line ?per_bit_opt(testChoTypeRefSet:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testChoTypeRefSet_cases(?PER)),
-
- ?line ?uper_bin(testChoTypeRefSet:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testChoTypeRefSet_cases(uper_bin)),
-
- ?line testChoTypeRefSet:compile(Config,?PER,[optimize]),
- ?line testChoTypeRefSet_cases(?PER).
-
-testChoTypeRefSet_cases(Rules) ->
- ?line testChoTypeRefSet:set(Rules).
-
-
-
-testDef(suite) -> [];
-testDef(Config) ->
-
- ?line testDef:compile(Config,?BER,[]),
- ?line testDef_cases(?BER),
-
- ?line ?ber_driver(?BER,testDef:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testDef_cases(?BER)),
-
- ?line testDef:compile(Config,?PER,[]),
- ?line testDef_cases(?PER),
-
- ?line ?per_bit_opt(testDef:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testDef_cases(?PER)),
-
- ?line ?uper_bin(testDef:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testDef_cases(uper_bin)),
-
- ?line testDef:compile(Config,?PER,[optimize]),
- ?line testDef_cases(?PER).
-
-testDef_cases(Rules) ->
- ?line testDef:main(Rules).
-
-
-
-testOpt(suite) -> [];
-testOpt(Config) ->
-
- ?line testOpt:compile(Config,?BER),
- ?line testOpt_cases(?BER),
-
- ?line testOpt:compile(Config,?PER),
- ?line testOpt_cases(?PER).
-
-testOpt_cases(Rules) ->
- ?line testOpt:main(Rules).
-
-
-testEnumExt(suite) -> [];
-testEnumExt(Config) ->
-
- ?line testEnumExt:compile(Config,?BER,[]),
- ?line testEnumExt:main(?BER),
-
- ?line ?ber_driver(?BER,testEnumExt:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testEnumExt:main(?BER)),
-
- ?line testEnumExt:compile(Config,?PER,[]),
- ?line testEnumExt:main(?PER),
-
- ?line ?per_bit_opt(testEnumExt:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testEnumExt:main(?PER)),
-
- ?line ?uper_bin(testEnumExt:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testEnumExt:main(uper_bin)),
-
- ?line testEnumExt:compile(Config,?PER,[optimize]),
- ?line testEnumExt:main(?PER).
-
-testSeqDefault(doc) -> ["Test of OTP-2523 ENUMERATED with extensionmark."];
-testSeqDefault(suite) -> [];
-testSeqDefault(Config) ->
-
- ?line testSeqDefault:compile(Config,?BER,[]),
- ?line testSeqDefault_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqDefault:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqDefault_cases(?BER)),
-
- ?line testSeqDefault:compile(Config,?PER,[]),
- ?line testSeqDefault_cases(?PER),
-
- ?line ?per_bit_opt(testSeqDefault:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqDefault_cases(?PER)),
-
- ?line ?uper_bin(testSeqDefault:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqDefault_cases(uper_bin)),
-
- ?line testSeqDefault:compile(Config,?PER,[optimize]),
- ?line testSeqDefault_cases(?PER).
-
-testSeqDefault_cases(Rules) ->
- ?line testSeqDefault:main(Rules).
-
-
-
-testSeqExtension(suite) -> [];
-testSeqExtension(Config) ->
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSeqExtension:compile(Config,?BER,[]),
- ?line testSeqExtension_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqExtension:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqExtension_cases(?BER)).
-
-testSeqExtension_cases(Rules) ->
- ?line testSeqExtension:main(Rules).
-
-
-
-testSeqExternal(suite) -> [];
-testSeqExternal(Config) ->
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSeqExternal:compile(Config,?BER,[]),
- ?line testSeqExternal_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqExternal_cases(?BER)).
-
-testSeqExternal_cases(Rules) ->
- ?line testSeqExternal:main(Rules).
-
-
-testSeqOptional(suite) -> [];
-testSeqOptional(Config) ->
-
- ?line testSeqOptional:compile(Config,?BER,[]),
- ?line testSeqOptional_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqOptional:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOptional_cases(?BER)),
-
- ?line testSeqOptional:compile(Config,?PER,[]),
- ?line testSeqOptional_cases(?PER),
-
- ?line ?per_bit_opt(testSeqOptional:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOptional_cases(?PER)),
-
- ?line ?uper_bin(testSeqOptional:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOptional_cases(uper_bin)),
-
- ?line testSeqOptional:compile(Config,?PER,[optimize]),
- ?line testSeqOptional_cases(?PER).
-
-testSeqOptional_cases(Rules) ->
- ?line testSeqOptional:main(Rules).
-
-
-
-testSeqPrim(suite) -> [];
-testSeqPrim(Config) ->
-
- ?line testSeqPrim:compile(Config,?BER,[]),
- ?line testSeqPrim_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqPrim_cases(?BER)),
-
- ?line testSeqPrim:compile(Config,?PER,[]),
- ?line testSeqPrim_cases(?PER),
-
- ?line ?per_bit_opt(testSeqPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqPrim_cases(?PER)),
-
- ?line ?uper_bin(testSeqPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqPrim_cases(uper_bin)),
-
- ?line testSeqPrim:compile(Config,?PER,[optimize]),
- ?line testSeqPrim_cases(?PER).
-
-testSeqPrim_cases(Rules) ->
- ?line testSeqPrim:main(Rules).
-
-
-testSeq2738(doc) -> ["Test of OTP-2738 Detect corrupt optional component."];
-testSeq2738(suite) -> [];
-testSeq2738(Config) ->
-
- ?line testSeq2738:compile(Config,?BER,[]),
- ?line testSeq2738_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeq2738:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeq2738_cases(?BER)),
-
- ?line testSeq2738:compile(Config,?PER,[]),
- ?line testSeq2738_cases(?PER),
-
- ?line ?per_bit_opt(testSeq2738:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeq2738_cases(?PER)),
-
- ?line ?uper_bin(testSeq2738:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeq2738_cases(uper_bin)),
-
- ?line testSeq2738:compile(Config,?PER,[optimize]),
- ?line testSeq2738_cases(?PER).
-
-testSeq2738_cases(Rules) ->
- ?line testSeq2738:main(Rules).
-
-
-testSeqTag(suite) -> [];
-testSeqTag(Config) ->
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSeqTag:compile(Config,?BER,[]),
- ?line testSeqTag_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqTag:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqTag_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testSeqTag:compile(Config,?PER,[]),
- ?line testSeqTag_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqTag:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqTag_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqTag:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqTag_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testSeqTag:compile(Config,?PER,[optimize]),
- ?line testSeqTag_cases(?PER).
-
-testSeqTag_cases(Rules) ->
- ?line testSeqTag:main(Rules).
-
-
-
-
-testSeqTypeRefCho(suite) -> [];
-testSeqTypeRefCho(Config) ->
-
- ?line testSeqTypeRefCho:compile(Config,?BER,[]),
- ?line testSeqTypeRefCho_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqTypeRefCho:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqTypeRefCho_cases(?BER)),
-
- ?line testSeqTypeRefCho:compile(Config,?PER,[]),
- ?line testSeqTypeRefCho_cases(?PER),
-
- ?line ?per_bit_opt(testSeqTypeRefCho:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqTypeRefCho_cases(?PER)),
-
- ?line ?uper_bin(testSeqTypeRefCho:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqTypeRefCho_cases(uper_bin)),
-
- ?line testSeqTypeRefCho:compile(Config,?PER,[optimize]),
- ?line testSeqTypeRefCho_cases(?PER).
-
-testSeqTypeRefCho_cases(Rules) ->
- ?line testSeqTypeRefCho:main(Rules).
-
-
-
-testSeqTypeRefPrim(suite) -> [];
-testSeqTypeRefPrim(Config) ->
-
- ?line testSeqTypeRefPrim:compile(Config,?BER,[]),
- ?line testSeqTypeRefPrim_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqTypeRefPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqTypeRefPrim_cases(?BER)),
-
- ?line testSeqTypeRefPrim:compile(Config,?PER,[]),
- ?line testSeqTypeRefPrim_cases(?PER),
-
- ?line ?per_bit_opt(testSeqTypeRefPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqTypeRefPrim_cases(?PER)),
-
- ?line ?uper_bin(testSeqTypeRefPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqTypeRefPrim_cases(uper_bin)),
-
- ?line testSeqTypeRefPrim:compile(Config,?PER,[optimize]),
- ?line testSeqTypeRefPrim_cases(?PER).
-
-testSeqTypeRefPrim_cases(Rules) ->
- ?line testSeqTypeRefPrim:main(Rules).
-
-
-
-testSeqTypeRefSeq(suite) -> [];
-testSeqTypeRefSeq(Config) ->
-
- ?line testSeqTypeRefSeq:compile(Config,?BER,[]),
- ?line testSeqTypeRefSeq_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqTypeRefSeq:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqTypeRefSeq_cases(?BER)),
-
- ?line testSeqTypeRefSeq:compile(Config,?PER,[]),
- ?line testSeqTypeRefSeq_cases(?PER),
-
- ?line ?per_bit_opt(testSeqTypeRefSeq:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqTypeRefSeq_cases(?PER)),
-
- ?line ?uper_bin(testSeqTypeRefSeq:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqTypeRefSeq_cases(uper_bin)),
-
- ?line testSeqTypeRefSeq:compile(Config,?PER,[optimize]),
- ?line testSeqTypeRefSeq_cases(?PER).
-
-testSeqTypeRefSeq_cases(Rules) ->
- ?line testSeqTypeRefSeq:main(Rules).
-
-
-
-testSeqTypeRefSet(suite) -> [];
-testSeqTypeRefSet(Config) ->
-
- ?line testSeqTypeRefSet:compile(Config,?BER,[]),
- ?line testSeqTypeRefSet_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqTypeRefSet:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqTypeRefSet_cases(?BER)),
-
- ?line testSeqTypeRefSet:compile(Config,?PER,[]),
- ?line testSeqTypeRefSet_cases(?PER),
-
- ?line ?per_bit_opt(testSeqTypeRefSet:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqTypeRefSet_cases(?PER)),
-
- ?line ?uper_bin(testSeqTypeRefSet:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqTypeRefSet_cases(uper_bin)),
-
- ?line testSeqTypeRefSet:compile(Config,?PER,[optimize]),
- ?line testSeqTypeRefSet_cases(?PER).
-
-testSeqTypeRefSet_cases(Rules) ->
- ?line testSeqTypeRefSet:main(Rules).
-
-
-
-
-testSeqOf(suite) -> [];
-testSeqOf(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSeqOf:compile(Config,?BER,[]),
- ?line testSeqOf_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqOf:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOf_cases(?BER)),
-
- ?line testSeqOf:compile(Config,?PER,[]),
- ?line testSeqOf_cases(?PER),
-
- ?line ?per_bit_opt(testSeqOf:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOf_cases(?PER)),
-
- ?line ?uper_bin(testSeqOf:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOf_cases(uper_bin)),
-
- ?line testSeqOf:compile(Config,?PER,[optimize]),
- ?line testSeqOf_cases(?PER).
-
-testSeqOf_cases(Rules) ->
- ?line testSeqOf:main(Rules).
-
-
-
-
-testSeqOfCho(suite) -> [];
-testSeqOfCho(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSeqOfCho:compile(Config,?BER,[]),
- ?line testSeqOfCho_cases(?BER),
-
- ?line ?ber_driver(?BER,testSeqOfCho:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOfCho_cases(?BER)),
-
- ?line testSeqOfCho:compile(Config,?PER,[]),
- ?line testSeqOfCho_cases(?PER),
-
- ?line ?per_bit_opt(testSeqOfCho:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOfCho_cases(?PER)),
-
- ?line ?uper_bin(testSeqOfCho:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOfCho_cases(uper_bin)),
-
- ?line testSeqOfCho:compile(Config,?PER,[optimize]),
- ?line testSeqOfCho_cases(?PER).
-
-testSeqOfIndefinite(suite) -> [];
-testSeqOfIndefinite(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSeqOfIndefinite:compile(Config,?BER,[]),
- ?line testSeqOfIndefinite:main(),
-
- ?line ?ber_driver(?BER,testSeqOfIndefinite:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOfIndefinite:main()).
-
-testSeqOfCho_cases(Rules) ->
- ?line testSeqOfCho:main(Rules).
-
-
-testSeqOfExternal(suite) -> [];
-testSeqOfExternal(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSeqOfExternal:compile(Config,?BER,[]),
- ?line testSeqOfExternal_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOfExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOfExternal_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testSeqOfExternal:compile(Config,?PER,[]),
- ?line testSeqOfExternal_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOfExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOfExternal_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOfExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOfExternal_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testSeqOfExternal:compile(Config,?PER,[optimize]),
- ?line testSeqOfExternal_cases(?PER).
-
-testSeqOfExternal_cases(Rules) ->
- ?line testSeqOfExternal:main(Rules).
-
-
-
-testSeqOfTag(suite) -> [];
-testSeqOfTag(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSeqOfTag:compile(Config,?BER,[]),
- ?line testSeqOfTag_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOfTag:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqOfTag_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testSeqOfTag:compile(Config,?PER,[]),
- ?line testSeqOfTag_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOfTag:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSeqOfTag_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOfTag:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSeqOfTag_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testSeqOfTag:compile(Config,?PER,[optimize]),
- ?line testSeqOfTag_cases(?PER).
-
-testSeqOfTag_cases(Rules) ->
- ?line testSeqOfTag:main(Rules).
-
-
-
-
-testSetDefault(suite) -> [];
-testSetDefault(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetDefault:compile(Config,?BER,[]),
- ?line testSetDefault_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetDefault:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetDefault_cases(?BER)),
-
- ?line testSetDefault:compile(Config,?PER,[]),
- ?line testSetDefault_cases(?PER),
-
- ?line ?per_bit_opt(testSetDefault:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetDefault_cases(?PER)),
-
- ?line ?uper_bin(testSetDefault:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetDefault_cases(uper_bin)),
-
- ?line testSetDefault:compile(Config,?PER,[optimize]),
- ?line testSetDefault_cases(?PER).
-
-testSetDefault_cases(Rules) ->
- ?line testSetDefault:main(Rules).
-
-
-testParamBasic(suite) -> [];
-testParamBasic(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testParamBasic:compile(Config,?BER,[]),
- ?line testParamBasic_cases(?BER),
-
- ?line ?ber_driver(?BER,testParamBasic:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testParamBasic_cases(?BER)),
-
- ?line testParamBasic:compile(Config,?PER,[]),
- ?line testParamBasic_cases(?PER),
-
- ?line ?per_bit_opt(testParamBasic:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testParamBasic_cases(?PER)),
-
- ?line ?uper_bin(testParamBasic:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testParamBasic_cases(uper_bin)),
-
- ?line testParamBasic:compile(Config,?PER,[optimize]),
- ?line testParamBasic_cases(?PER).
-
-
-testParamBasic_cases(Rules) ->
- ?line testParamBasic:main(Rules).
-
-testSetExtension(suite) -> [];
-testSetExtension(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSetExtension:compile(Config,?BER,[]),
- ?line testSetExtension_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetExtension:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetExtension_cases(?BER)).
-
-testSetExtension_cases(Rules) ->
- ?line testSetExtension:main(Rules).
-
-
-testSetExternal(suite) -> [];
-testSetExternal(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSetExternal:compile(Config,?BER,[]),
- ?line testSetExternal_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetExternal_cases(?BER)).
-
-testSetExternal_cases(Rules) ->
- ?line testSetExternal:main(Rules).
-
-
-testSetOptional(suite) -> [];
-testSetOptional(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetOptional:compile(Config,?BER,[]),
- ?line testSetOptional_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetOptional:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOptional_cases(?BER)),
-
- ?line testSetOptional:compile(Config,?PER,[]),
- ?line testSetOptional_cases(?PER),
-
- ?line ?per_bit_opt(testSetOptional:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOptional_cases(?PER)),
-
- ?line ?uper_bin(testSetOptional:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOptional_cases(uper_bin)),
-
- ?line testSetOptional:compile(Config,?PER,[optimize]),
- ?line testSetOptional_cases(?PER).
-
-testSetOptional_cases(Rules) ->
- ?line ok = testSetOptional:ticket_7533(Rules),
- ?line ok = testSetOptional:main(Rules).
-
-
-
-
-testSetPrim(suite) -> [];
-testSetPrim(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetPrim:compile(Config,?BER,[]),
- ?line testSetPrim_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetPrim_cases(?BER)),
-
- ?line testSetPrim:compile(Config,?PER,[]),
- ?line testSetPrim_cases(?PER),
-
- ?line ?per_bit_opt(testSetPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetPrim_cases(?PER)),
-
- ?line ?uper_bin(testSetPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetPrim_cases(uper_bin)),
-
- ?line testSetPrim:compile(Config,?PER,[optimize]),
- ?line testSetPrim_cases(?PER).
-
-testSetPrim_cases(Rules) ->
- ?line testSetPrim:main(Rules).
-
-
-
-testSetTag(suite) -> [];
-testSetTag(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSetTag:compile(Config,?BER,[]),
- ?line testSetTag_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetTag:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetTag_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testSetTag:compile(Config,?PER,[]),
- ?line testSetTag_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetTag:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetTag_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetTag:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetTag_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testSetTag:compile(Config,?PER,[optimize]),
- ?line testSetTag_cases(?PER).
-
-testSetTag_cases(Rules) ->
- ?line testSetTag:main(Rules).
-
-
-
-testSetTypeRefCho(suite) -> [];
-testSetTypeRefCho(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetTypeRefCho:compile(Config,?BER,[]),
- ?line testSetTypeRefCho_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetTypeRefCho:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetTypeRefCho_cases(?BER)),
-
- ?line testSetTypeRefCho:compile(Config,?PER,[]),
- ?line testSetTypeRefCho_cases(?PER),
-
- ?line ?per_bit_opt(testSetTypeRefCho:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetTypeRefCho_cases(?PER)),
-
- ?line ?uper_bin(testSetTypeRefCho:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetTypeRefCho_cases(uper_bin)),
-
- ?line testSetTypeRefCho:compile(Config,?PER,[optimize]),
- ?line testSetTypeRefCho_cases(?PER).
-
-testSetTypeRefCho_cases(Rules) ->
- ?line testSetTypeRefCho:main(Rules).
-
-
-
-testSetTypeRefPrim(suite) -> [];
-testSetTypeRefPrim(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetTypeRefPrim:compile(Config,?BER,[]),
- ?line testSetTypeRefPrim_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetTypeRefPrim:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetTypeRefPrim_cases(?BER)),
-
- ?line testSetTypeRefPrim:compile(Config,?PER,[]),
- ?line testSetTypeRefPrim_cases(?PER),
-
- ?line ?per_bit_opt(testSetTypeRefPrim:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetTypeRefPrim_cases(?PER)),
-
- ?line ?uper_bin(testSetTypeRefPrim:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetTypeRefPrim_cases(uper_bin)),
-
- ?line testSetTypeRefPrim:compile(Config,?PER,[optimize]),
- ?line testSetTypeRefPrim_cases(?PER).
-
-testSetTypeRefPrim_cases(Rules) ->
- ?line testSetTypeRefPrim:main(Rules).
-
-
-
-testSetTypeRefSeq(suite) -> [];
-testSetTypeRefSeq(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetTypeRefSeq:compile(Config,?BER,[]),
- ?line testSetTypeRefSeq_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetTypeRefSeq:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetTypeRefSeq_cases(?BER)),
-
- ?line testSetTypeRefSeq:compile(Config,?PER,[]),
- ?line testSetTypeRefSeq_cases(?PER),
-
- ?line ?per_bit_opt(testSetTypeRefSeq:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetTypeRefSeq_cases(?PER)),
-
- ?line ?uper_bin(testSetTypeRefSeq:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetTypeRefSeq_cases(uper_bin)),
-
- ?line testSetTypeRefSeq:compile(Config,?PER,[optimize]),
- ?line testSetTypeRefSeq_cases(?PER).
-
-testSetTypeRefSeq_cases(Rules) ->
- ?line testSetTypeRefSeq:main(Rules).
-
-
-
-testSetTypeRefSet(suite) -> [];
-testSetTypeRefSet(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetTypeRefSet:compile(Config,?BER,[]),
- ?line testSetTypeRefSet_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetTypeRefSet:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetTypeRefSet_cases(?BER)),
-
- ?line testSetTypeRefSet:compile(Config,?PER,[]),
- ?line testSetTypeRefSet_cases(?PER),
-
- ?line ?per_bit_opt(testSetTypeRefSet:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetTypeRefSet_cases(?PER)),
-
- ?line ?uper_bin(testSetTypeRefSet:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetTypeRefSet_cases(uper_bin)),
-
- ?line testSetTypeRefSet:compile(Config,?PER,[optimize]),
- ?line testSetTypeRefSet_cases(?PER).
-
-testSetTypeRefSet_cases(Rules) ->
- ?line testSetTypeRefSet:main(Rules).
-
-
-
-testSetOf(suite) -> [];
-testSetOf(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetOf:compile(Config,?BER,[]),
- ?line testSetOf_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetOf:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOf_cases(?BER)),
-
- ?line testSetOf:compile(Config,?PER,[]),
- ?line testSetOf_cases(?PER),
-
- ?line ?per_bit_opt(testSetOf:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOf_cases(?PER)),
-
- ?line ?uper_bin(testSetOf:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOf_cases(uper_bin)),
-
- ?line testSetOf:compile(Config,?PER,[optimize]),
- ?line testSetOf_cases(?PER).
-
-testSetOf_cases(Rules) ->
- ?line testSetOf:main(Rules).
-
-
-
-testSetOfCho(suite) -> [];
-testSetOfCho(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetOfCho:compile(Config,?BER,[]),
- ?line testSetOfCho_cases(?BER),
-
- ?line ?ber_driver(?BER,testSetOfCho:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOfCho_cases(?BER)),
-
- ?line testSetOfCho:compile(Config,?PER,[]),
- ?line testSetOfCho_cases(?PER),
-
- ?line ?per_bit_opt(testSetOfCho:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOfCho_cases(?PER)),
-
- ?line ?uper_bin(testSetOfCho:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOfCho_cases(uper_bin)),
-
- ?line testSetOfCho:compile(Config,?PER,[optimize]),
- ?line testSetOfCho_cases(?PER).
-
-testSetOfCho_cases(Rules) ->
- ?line testSetOfCho:main(Rules).
-
-
-testSetOfExternal(suite) -> [];
-testSetOfExternal(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSetOfExternal:compile(Config,?BER,[]),
- ?line testSetOfExternal_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOfExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOfExternal_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testSetOfExternal:compile(Config,?PER,[]),
- ?line testSetOfExternal_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOfExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOfExternal_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOfExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOfExternal_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testSetOfExternal:compile(Config,?PER,[optimize]),
- ?line testSetOfExternal_cases(?PER).
-
-testSetOfExternal_cases(Rules) ->
- ?line testSetOfExternal:main(Rules).
-
-
-
-
-testSetOfTag(suite) -> [];
-testSetOfTag(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testExternal:compile(Config,?BER,[]),
- ?line testSetOfTag:compile(Config,?BER,[]),
- ?line testSetOfTag_cases(?BER),
-
- ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOfTag:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetOfTag_cases(?BER)),
-
- ?line testExternal:compile(Config,?PER,[]),
- ?line testSetOfTag:compile(Config,?PER,[]),
- ?line testSetOfTag_cases(?PER),
-
- ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOfTag:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testSetOfTag_cases(?PER)),
-
- ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOfTag:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testSetOfTag_cases(uper_bin)),
-
- ?line testExternal:compile(Config,?PER,[optimize]),
- ?line testSetOfTag:compile(Config,?PER,[optimize]),
- ?line testSetOfTag_cases(?PER).
-
-testSetOfTag_cases(Rules) ->
- ?line testSetOfTag:main(Rules).
-
-
-c_syntax(suite) -> [];
-c_syntax(Config) ->
- ?line DataDir% ?line testExternal:compile(Config,?PER),
-% ?line testPrimExternal:compile(Config,?PER),
-% ?line testPrimExternal_cases(?PER).
- = ?config(data_dir,Config),
- ?line _TempDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line {error,_R1} = asn1ct:compile(filename:join(DataDir,"Syntax")),
- ?line {error,_R2} = asn1ct:compile(filename:join(DataDir,"BadTypeEnding")),
- ?line {error,_R3} = asn1ct:compile(filename:join(DataDir,
- "BadValueAssignment1")),
- ?line {error,_R4} = asn1ct:compile(filename:join(DataDir,
- "BadValueAssignment2")),
- ?line {error,_R5} = asn1ct:compile(filename:join(DataDir,
- "BadValueSet")),
- ?line {error,_R6} = asn1ct:compile(filename:join(DataDir,
- "ChoiceBadExtension")),
- ?line {error,_R7} = asn1ct:compile(filename:join(DataDir,
- "EnumerationBadExtension")),
- ?line {error,_R8} = asn1ct:compile(filename:join(DataDir,
- "Example")),
- ?line {error,_R9} = asn1ct:compile(filename:join(DataDir,
- "Export1")),
- ?line {error,_R10} = asn1ct:compile(filename:join(DataDir,
- "MissingEnd")),
- ?line {error,_R11} = asn1ct:compile(filename:join(DataDir,
- "SequenceBadComma")),
- ?line {error,_R12} = asn1ct:compile(filename:join(DataDir,
- "SequenceBadComponentName")),
- ?line {error,_R13} = asn1ct:compile(filename:join(DataDir,
- "SequenceBadComponentType")),
- ?line {error,_R14} = asn1ct:compile(filename:join(DataDir,
- "SeqBadComma")).
-
-
-c_string_per(suite) -> [];
-c_string_per(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line TempDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(filename:join(DataDir,"String"),[?PER,{outdir,TempDir}]).
-
-c_string_ber(suite) -> [];
-c_string_ber(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line TempDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(filename:join(DataDir,"String"),[?BER,{outdir,TempDir}]).
-
-
-c_implicit_before_choice(suite) -> [];
-c_implicit_before_choice(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line TempDir = ?config(priv_dir,Config),
- ?line {error,_R2} = asn1ct:compile(filename:join(DataDir,"CCSNARG3"),[?BER,{outdir,TempDir}]).
-
-parse(suite) -> [];
-parse(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- M1 = test_modules(),
-% M2 = parse_modules(),
- ?line ok = parse1(M1,DataDir,OutDir).
-
-parse1([M|T],DataDir,OutDir) ->
- ?line ok = asn1ct:compile(DataDir ++ M,[abs,{outdir,OutDir}]),
- parse1(T,DataDir,OutDir);
-parse1([],_,_) ->
- ok.
-
-per(suite) -> [];
-per(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = per1(per_modules(),DataDir,OutDir),
- ?line ?per_bit_opt(per1_bit_opt(per_modules(),DataDir,OutDir)),
- ?line ok = per1_opt(per_modules(),DataDir,OutDir).
-
-
-per1([M|T],DataDir,OutDir) ->
- ?line ok = asn1ct:compile(DataDir ++ M,[?PER,{outdir,OutDir}]),
- ?line ok = asn1ct:test(list_to_atom(M)),
- per1(T,DataDir,OutDir);
-per1([],_,_) ->
- ok.
-
-per1_bit_opt([M|T],DataDir,OutDir) ->
- ?line ok = asn1ct:compile(DataDir ++ M,[?PER,optimize,{outdir,OutDir}]),
- ?line ok = asn1ct:test(list_to_atom(M)),
- per1_bit_opt(T,DataDir,OutDir);
-per1_bit_opt([],_,_) ->
- ok.
-
-per1_opt([M|T],DataDir,OutDir) ->
- ?line ok = asn1ct:compile(DataDir ++ M,[?PER,optimized,{outdir,OutDir}]),
- ?line ok = asn1ct:test(list_to_atom(M)),
- per1_opt(T,DataDir,OutDir);
-per1_opt([],_,_) ->
- ok.
-
-
-ber_choiceinseq(suite) ->[];
-ber_choiceinseq(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(filename:join(DataDir,"ChoiceInSeq"),[?BER,{outdir,OutDir}]).
-
-ber_optional(suite) ->[];
-ber_optional(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(filename:join(DataDir,"SOpttest"),[?BER,{outdir,OutDir}]),
- ?line V = {'S',{'A',10,asn1_NOVALUE,asn1_NOVALUE},
- {'B',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE},
- {'C',asn1_NOVALUE,111,asn1_NOVALUE}},
- ?line {ok,B} = asn1_wrapper:encode('SOpttest','S',V),
- ?line Bytes = lists:flatten(B),
- ?line V2 = asn1_wrapper:decode('SOpttest','S',Bytes),
- ?line ok = eq(V,element(2,V2)).
-
-ber_optional_keyed_list(suite) ->[];
-ber_optional_keyed_list(Config) ->
- case ?BER of
- ber_bin_v2 -> ok;
- _ ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(filename:join(DataDir,"SOpttest"),
- [?BER,keyed_list,{outdir,OutDir}]),
- ?line Vrecord = {'S',{'A',10,asn1_NOVALUE,asn1_NOVALUE},
- {'B',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE},
- {'C',asn1_NOVALUE,111,asn1_NOVALUE}},
- ?line V = [ {a,[{scriptKey,10}]},
- {b,[]},
- {c,[{callingPartysCategory,111}]} ],
- ?line {ok,B} = asn1_wrapper:encode('SOpttest','S',V),
- ?line Bytes = lists:flatten(B),
- ?line V2 = asn1_wrapper:decode('SOpttest','S',Bytes),
- ?line ok = eq(Vrecord,element(2,V2))
- end.
-
-
-eq(V,V) ->
- ok.
-
-
-ber_other(suite) ->[];
-ber_other(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = ber1(ber_modules(),DataDir,OutDir).
-
-
-ber1([M|T],DataDir,OutDir) ->
- ?line ok = asn1ct:compile(DataDir ++ M,[?BER,{outdir,OutDir}]),
- ?line ok = asn1ct:test(list_to_atom(M)),
- ber1(T,DataDir,OutDir);
-ber1([],_,_) ->
- ok.
-
-default_per(suite) ->[];
-default_per(Config) ->
- default1(?PER,Config,[]).
-
-default_per_opt(suite) -> [];
-default_per_opt(Config) ->
- ?per_bit_opt(default1(?PER,Config,[optimize])),
- default1(?PER,Config,[optimize]).
-
-default_ber(suite) ->[];
-default_ber(Config) ->
- default1(?BER,Config,[]).
-
-default1(Rule,Config,Options) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(DataDir ++ "Def",[Rule,{outdir,OutDir}]++Options),
- ?line {ok,Bytes1} = asn1_wrapper:encode('Def','Def1',#'Def1'{bool0 = true,
- bool1 = true,
- bool2 = true,
- bool3 = true}),
- ?line {ok,{'Def1',true,true,true,true}} = asn1_wrapper:decode('Def','Def1',lists:flatten(Bytes1)),
-
- ?line {ok,Bytes2} = asn1_wrapper:encode('Def','Def1',#'Def1'{bool0 = true}),
- ?line {ok,{'Def1',true,false,false,false}} = asn1_wrapper:decode('Def','Def1',lists:flatten(Bytes2)),
-
- ?line {ok,Bytes3} = asn1_wrapper:encode('Def','Def1',#'Def1'{bool0 = true,bool2=false}),
- ?line {ok,{'Def1',true,false,false,false}} = asn1_wrapper:decode('Def','Def1',lists:flatten(Bytes3)).
-
-
-value_test(suite) ->[];
-value_test(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(DataDir ++ "ObjIdValues",[?BER,{outdir,OutDir}]),
- ?line {ok,_} = asn1_wrapper:encode('ObjIdValues','ObjIdType','ObjIdValues':'mobileDomainId'()),
- ?line ok = asn1ct:compile(DataDir ++ "ObjIdValues",[?PER,{outdir,OutDir}]),
- ?line {ok,_} = asn1_wrapper:encode('ObjIdValues','ObjIdType','ObjIdValues':'mobileDomainId'()),
- ?line ok = test_bad_values:tests(Config),
- ok.
-
-
-constructed(suite) ->
- [];
-constructed(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
- ?line ok = asn1ct:compile(DataDir ++ "Constructed",[?BER,{outdir,OutDir}]),
- ?line {ok,B} = asn1_wrapper:encode('Constructed','S',{'S',false}),
- ?line [40,3,1,1,0] = lists:flatten(B),
- ?line {ok,B1} = asn1_wrapper:encode('Constructed','S2',{'S2',false}),
- ?line [40,5,48,3,1,1,0] = lists:flatten(B1),
- ?line {ok,B2} = asn1_wrapper:encode('Constructed','I',10),
- ?line [136,1,10] = lists:flatten(B2),
- ok.
-
-ber_decode_error(suite) -> [];
-ber_decode_error(Config) ->
- ?line ok = ber_decode_error:compile(Config,?BER,[]),
- ?line ok = ber_decode_error:run([]),
-
- ?line ok = ?ber_driver(?BER,ber_decode_error:compile(Config,?BER,[driver])),
- ?line ok = ?ber_driver(?BER,ber_decode_error:run([driver])),
- ok.
-
-h323test(suite) ->
- [];
-h323test(Config) ->
- ?line ok = h323test:compile(Config,?PER,[]),
- ?line ok = h323test:run(?PER),
- ?line ?per_bit_opt(h323test:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(h323test:run(?PER)),
- ?line ?uper_bin(h323test:compile(Config,uper_bin,[])),
- ?line ?uper_bin(h323test:run(uper_bin)),
- ?line ok = h323test:compile(Config,?PER,[optimize]),
- ?line ok = h323test:run(?PER),
- ok.
-
-per_GeneralString(suite) ->
- [];
-per_GeneralString(Config) ->
- case erlang:module_loaded('MULTIMEDIA-SYSTEM-CONTROL') of
- true ->
- ok;
- false ->
- h323test:compile(Config,?PER,[])
- end,
- UI = [109,64,1,57],
- ?line {ok,_V} = asn1_wrapper:decode('MULTIMEDIA-SYSTEM-CONTROL',
- 'MultimediaSystemControlMessage',UI).
-
-per_open_type(suite) ->
- [];
-per_open_type(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line ok = asn1ct:compile(DataDir ++ "OpenType",[?PER,{outdir,OutDir}]),
- Stype = {'Stype',10,true},
- ?line {ok,Bytes} = asn1_wrapper:encode('OpenType','Ot',Stype),
- ?line {ok,Stype} = asn1_wrapper:decode('OpenType','Ot',Bytes),
-
- ?line ?per_bit_opt(ok = asn1ct:compile(DataDir ++ "OpenType",
- [?PER,optimize,{outdir,OutDir}])),
- ?line ?per_bit_opt({ok,Bytes}=asn1_wrapper:encode('OpenType','Ot',Stype)),
- ?line ?per_bit_opt({ok,Stype}=asn1_wrapper:decode('OpenType','Ot',Bytes)),
-
- ?line ?uper_bin(ok = asn1ct:compile(DataDir ++ "OpenType",
- [uper_bin,{outdir,OutDir}])),
- ?line ?uper_bin({ok,Bytes}=asn1_wrapper:encode('OpenType','Ot',Stype)),
- ?line ?uper_bin({ok,Stype}=asn1_wrapper:decode('OpenType','Ot',Bytes)),
-
- ?line ok = asn1ct:compile(DataDir ++ "OpenType",
- [?PER,optimize,{outdir,OutDir}]),
- ?line {ok,Bytes} = asn1_wrapper:encode('OpenType','Ot',Stype),
- ?line {ok,Stype} = asn1_wrapper:decode('OpenType','Ot',Bytes).
-
-testConstraints(suite) ->
- [];
-testConstraints(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testConstraints:compile(Config,?BER,[]),
- ?line testConstraints:int_constraints(?BER),
-
- ?line ?ber_driver(?BER,testConstraints:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testConstraints:int_constraints(?BER)),
-
- ?line testConstraints:compile(Config,?PER,[]),
- ?line testConstraints:int_constraints(?PER),
- ?line testConstraints:refed_NNL_name(?PER),
-
- ?line ?per_bit_opt(testConstraints:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testConstraints:int_constraints(?PER)),
- ?line ?per_bit_opt(testConstraints:refed_NNL_name(?PER)),
-
- ?line ?uper_bin(testConstraints:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testConstraints:int_constraints(uper_bin)),
- ?line ?uper_bin(testConstraints:refed_NNL_name(uper_bin)),
-
- ?line testConstraints:compile(Config,?PER,[optimize]),
- ?line testConstraints:int_constraints(?PER),
- ?line testConstraints:refed_NNL_name(?PER).
-
-testSeqIndefinite(suite) -> [];
-testSeqIndefinite(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSeqIndefinite:compile(Config,?BER,[]),
- ?line testSeqIndefinite:main(?BER),
-
- ?line ?ber_driver(?BER,testSeqIndefinite:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSeqIndefinite:main(?BER)).
-
-testSetIndefinite(suite) -> [];
-testSetIndefinite(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testSetIndefinite:compile(Config,?BER,[]),
- ?line testSetIndefinite:main(?BER),
-
- ?line ?ber_driver(?BER,testSetIndefinite:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testSetIndefinite:main(?BER)).
-
-testChoiceIndefinite(suite) -> [];
-testChoiceIndefinite(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testChoiceIndefinite:compile(Config,?BER,[]),
- ?line testChoiceIndefinite:main(?BER),
-
- ?line ?ber_driver(?BER,testChoiceIndefinite:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testChoiceIndefinite:main(?BER)).
-
-testInfObjectClass(suite) ->
- [];
-testInfObjectClass(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testInfObjectClass:compile(Config,?PER,[]),
- ?line testInfObjectClass:main(?PER),
- ?line testInfObj:compile(Config,?PER,[]),
- ?line testInfObj:main(?PER),
-
- ?line ?per_bit_opt(testInfObjectClass:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testInfObjectClass:main(?PER)),
- ?line ?per_bit_opt(testInfObj:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testInfObj:main(?PER)),
-
- ?line ?uper_bin(testInfObjectClass:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testInfObjectClass:main(uper_bin)),
- ?line ?uper_bin(testInfObj:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testInfObj:main(uper_bin)),
-
- ?line testInfObjectClass:compile(Config,?PER,[optimize]),
- ?line testInfObjectClass:main(?PER),
- ?line testInfObj:compile(Config,?PER,[optimize]),
- ?line testInfObj:main(?PER),
-
- ?line testInfObjectClass:compile(Config,?BER,[]),
- ?line testInfObjectClass:main(?BER),
- ?line testInfObj:compile(Config,?BER,[]),
- ?line testInfObj:main(?BER),
-
- ?line ?ber_driver(?BER,testInfObjectClass:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testInfObjectClass:main(?BER)),
- ?line ?ber_driver(?BER,testInfObj:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testInfObj:main(?BER)),
-
- ?line testInfObj:compile_RANAPfiles(Config,?PER,[]),
-
- ?line ?per_bit_opt(testInfObj:compile_RANAPfiles(Config,?PER,[optimize])),
-
- ?line ?uper_bin(testInfObj:compile_RANAPfiles(Config,uper_bin,[])),
-
- ?line testInfObj:compile_RANAPfiles(Config,?PER,[optimize]),
-
- ?line testInfObj:compile_RANAPfiles(Config,?BER,[]).
-
-testParameterizedInfObj(suite) ->
- [];
-testParameterizedInfObj(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testParameterizedInfObj:compile(Config,?PER,[]),
- ?line testParameterizedInfObj:main(?PER),
-
- ?line ?per_bit_opt(testParameterizedInfObj:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testParameterizedInfObj:main(?PER)),
-
- ?line ?uper_bin(testParameterizedInfObj:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testParameterizedInfObj:main(uper_bin)),
-
- ?line testParameterizedInfObj:compile(Config,?PER,[optimize]),
- ?line testParameterizedInfObj:main(?PER),
-
- ?line testParameterizedInfObj:compile(Config,?BER,[]),
- ?line testParameterizedInfObj:main(?BER),
-
- ?line ?ber_driver(?BER,testParameterizedInfObj:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testParameterizedInfObj:main(?BER)).
-
-testMergeCompile(suite) ->
- [];
-testMergeCompile(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testMergeCompile:compile(Config,?PER,[]),
- ?line testMergeCompile:main(?PER),
- ?line testMergeCompile:mvrasn(?PER),
-
- ?line ?per_bit_opt(testMergeCompile:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testMergeCompile:main(?PER)),
- ?line ?per_bit_opt(testMergeCompile:mvrasn(?PER)),
-
- ?line ?uper_bin(testMergeCompile:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testMergeCompile:main(uper_bin)),
- ?line ?uper_bin(testMergeCompile:mvrasn(uper_bin)),
-
- ?line testMergeCompile:compile(Config,?BER,[]),
- ?line testMergeCompile:main(?BER),
- ?line testMergeCompile:mvrasn(?BER),
-
- ?line ?ber_driver(?BER,testMergeCompile:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testMergeCompile:main(?BER)),
- ?line ?ber_driver(?BER,testMergeCompile:mvrasn(?BER)).
-
-testobj(suite) ->
- [];
-testobj(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line ok = testRANAP:compile(Config,?PER,[]),
- ?line ok = testRANAP:testobj(?PER),
- ?line ok = testParameterizedInfObj:ranap(?PER),
-
- ?line ?per_bit_opt(ok = testRANAP:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(ok = testRANAP:testobj(?PER)),
- ?line ?per_bit_opt(ok = testParameterizedInfObj:ranap(?PER)),
-
- ?line ?uper_bin(ok = testRANAP:compile(Config,uper_bin,[])),
- ?line ?uper_bin(ok = testRANAP:testobj(uper_bin)),
- ?line ?uper_bin(ok = testParameterizedInfObj:ranap(uper_bin)),
-
- ?line ok = testRANAP:compile(Config,?PER,[optimize]),
- ?line ok = testRANAP:testobj(?PER),
- ?line ok = testParameterizedInfObj:ranap(?PER),
-
- ?line ok = testRANAP:compile(Config,?BER,[]),
- ?line ok = testRANAP:testobj(?BER),
- ?line ok = testParameterizedInfObj:ranap(?BER),
-
- ?line ?ber_driver(?BER,testRANAP:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testRANAP:testobj(?BER)),
- ?line ?ber_driver(?BER,testParameterizedInfObj:ranap(?BER)).
-
-
-testDeepTConstr(suite) ->
- [];
-testDeepTConstr(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testDeepTConstr:compile(Config,?PER,[]),
- ?line testDeepTConstr:main(?PER),
-
- ?line ?per_bit_opt(testDeepTConstr:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testDeepTConstr:main(?PER)),
-
- ?line ?uper_bin(testDeepTConstr:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testDeepTConstr:main(uper_bin)),
-
- ?line testDeepTConstr:compile(Config,?PER,[optimize]),
- ?line testDeepTConstr:main(?PER),
-
- ?line testDeepTConstr:compile(Config,?BER,[]),
- ?line testDeepTConstr:main(?BER),
-
- ?line ?ber_driver(?BER,testDeepTConstr:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testDeepTConstr:main(?BER)).
-
-testInvokeMod(suite) ->
- [];
-testInvokeMod(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line ok = asn1ct:compile(filename:join(DataDir,"PrimStrings"),[{outdir,OutDir}]),
- ?line {ok,_Result1} = 'PrimStrings':encode('Bs1',[1,0,1,0]),
- ?line ok = asn1ct:compile(filename:join(DataDir,"PrimStrings"),[?PER,{outdir,OutDir}]),
- ?line {ok,_Result2} = 'PrimStrings':encode('Bs1',[1,0,1,0]).
-
-testExport(suite) ->
- [];
-testExport(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line {error,{asn1,_Reason}} = asn1ct:compile(filename:join(DataDir,"IllegalExport"),[{outdir,OutDir}]).
-
-testImport(suite) ->
- [];
-testImport(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line _OutDir = ?config(priv_dir,Config),
- ?line {error,_} = asn1ct:compile(filename:join(DataDir,"ImportsFrom"),[?BER]),
- ok.
-
-testMegaco(suite) ->
- [];
-testMegaco(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
- io:format("Config: ~p~n",[Config]),
- ?line {ok,ModuleName1,ModuleName2} = testMegaco:compile(Config,?BER,[]),
- ?line ok = testMegaco:main(ModuleName1,Config),
- ?line ok = testMegaco:main(ModuleName2,Config),
-
- case ?BER of
- ber_bin_v2 ->
- ?line {ok,ModuleName3,ModuleName4} = testMegaco:compile(Config,?BER,[driver]),
- ?line ok = testMegaco:main(ModuleName3,Config),
- ?line ok = testMegaco:main(ModuleName4,Config);
- _-> ok
- end,
-
- ?line {ok,ModuleName5,ModuleName6} = testMegaco:compile(Config,?PER,[]),
- ?line ok = testMegaco:main(ModuleName5,Config),
- ?line ok = testMegaco:main(ModuleName6,Config),
-
- ?line ?per_bit_opt({ok,ModuleName5,ModuleName6} = testMegaco:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(ok = testMegaco:main(ModuleName5,Config)),
- ?line ?per_bit_opt(ok = testMegaco:main(ModuleName6,Config)),
-
- ?line ?uper_bin({ok,ModuleName5,ModuleName6} = testMegaco:compile(Config,uper_bin,[])),
- ?line ?uper_bin(ok = testMegaco:main(ModuleName5,Config)),
- ?line ?uper_bin(ok = testMegaco:main(ModuleName6,Config)),
-
- ?line {ok,ModuleName7,ModuleName8} = testMegaco:compile(Config,?PER,[optimize]),
- ?line ok = testMegaco:main(ModuleName7,Config),
- ?line ok = testMegaco:main(ModuleName8,Config).
-
-
-testMvrasn6(suite) -> [];
-testMvrasn6(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testMvrasn6:compile(Config,?BER),
- ?line testMvrasn6:main().
-
-testContextSwitchingTypes(suite) -> [];
-testContextSwitchingTypes(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testContextSwitchingTypes:compile(Config,?BER,[]),
- ?line testContextSwitchingTypes:test(),
-
- ?line ?ber_driver(?BER,testContextSwitchingTypes:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testContextSwitchingTypes:test()),
-
- ?line testContextSwitchingTypes:compile(Config,?PER,[]),
- ?line testContextSwitchingTypes:test(),
-
- ?line ?per_bit_opt(testContextSwitchingTypes:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testContextSwitchingTypes:test()),
-
- ?line ?uper_bin(testContextSwitchingTypes:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testContextSwitchingTypes:test()),
-
- ?line testContextSwitchingTypes:compile(Config,?PER,[optimize]),
- ?line testContextSwitchingTypes:test().
-
-testTypeValueNotation(suite) -> [];
-testTypeValueNotation(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- case ?BER of
- Ber when Ber == ber; Ber == ber_bin ->
- ?line testTypeValueNotation:compile(Config,?BER,[]),
- ?line testTypeValueNotation:main(?BER,dummy);
- _ ->
- ok
- end,
-
- ?line ?ber_driver(?BER,testTypeValueNotation:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testTypeValueNotation:main(?BER,optimize)),
-
- case ?BER of
- Ber2 when Ber2 == ber; Ber2 == ber_bin ->
- ?line testTypeValueNotation:compile(Config,?PER,[]),
- ?line testTypeValueNotation:main(?PER,dummy);
- _ ->
- ok
- end,
-
- ?line ?per_bit_opt(testTypeValueNotation:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testTypeValueNotation:main(?PER,optimize)),
-
- ?line ?uper_bin(testTypeValueNotation:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testTypeValueNotation:main(uper_bin,optimize)),
- case ?BER of
- Ber3 when Ber3 == ber; Ber3 == ber_bin ->
- ?line testTypeValueNotation:compile(Config,?PER,[optimize]),
- ?line testTypeValueNotation:main(?PER,optimize);
- _ ->
- ok
- end.
-
-testOpenTypeImplicitTag(suite) -> [];
-testOpenTypeImplicitTag(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testOpenTypeImplicitTag:compile(Config,?BER,[]),
- ?line testOpenTypeImplicitTag:main(?BER),
-
- ?line ?ber_driver(?BER,testOpenTypeImplicitTag:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testOpenTypeImplicitTag:main(?BER)),
-
- ?line testOpenTypeImplicitTag:compile(Config,?PER,[]),
- ?line testOpenTypeImplicitTag:main(?PER),
-
- ?line ?per_bit_opt(testOpenTypeImplicitTag:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testOpenTypeImplicitTag:main(?PER)),
-
- ?line ?uper_bin(testOpenTypeImplicitTag:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testOpenTypeImplicitTag:main(uper_bin)),
-
- ?line testOpenTypeImplicitTag:compile(Config,?PER,[optimize]),
- ?line testOpenTypeImplicitTag:main(?PER).
-
-duplicate_tags(suite) -> [];
-duplicate_tags(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- {error,{asn1,[{error,{type,_,_,'SeqOpt1Imp',{asn1,{duplicates_of_the_tags,_}}}}]}} =
- asn1ct:compile(filename:join(DataDir,"SeqOptional2"),[abs]),
- ok.
-
-rtUI(suite) -> [];
-rtUI(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line ok = asn1ct:compile(filename:join(DataDir,"Prim"),[?BER]),
- ?line {ok,_} = asn1rt:info('Prim'),
-
- ?line ok = asn1ct:compile(filename:join(DataDir,"Prim"),[?PER]),
- ?line {ok,_} = asn1rt:info('Prim'),
-
- ?line ok = asn1rt:load_driver(),
- ?line ok = asn1rt:load_driver(),
- ?line ok = asn1rt:unload_driver().
-
-testROSE(suite) -> [];
-testROSE(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testROSE:compile(Config,?BER,[]),
-
- ?line testROSE:compile(Config,?PER,[]),
- ?line ?per_bit_opt(testROSE:compile(Config,?PER,[optimize])),
- ?line ?uper_bin(testROSE:compile(Config,uper_bin,[])),
- ?line testROSE:compile(Config,?PER,[optimize]).
-
-testINSTANCE_OF(suite) -> [];
-testINSTANCE_OF(Config) ->
- ?line testINSTANCE_OF:compile(Config,?BER,[]),
- ?line testINSTANCE_OF:main(?BER),
-
- ?line ?ber_driver(?BER,testINSTANCE_OF:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testINSTANCE_OF:main(?BER)),
-
- ?line testINSTANCE_OF:compile(Config,?PER,[]),
- ?line testINSTANCE_OF:main(?PER),
-
- ?line ?per_bit_opt(testINSTANCE_OF:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testINSTANCE_OF:main(?PER)),
-
- ?line ?uper_bin(testINSTANCE_OF:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testINSTANCE_OF:main(uper_bin)),
-
- ?line testINSTANCE_OF:compile(Config,?PER,[optimize]),
- ?line testINSTANCE_OF:main(?PER).
-
-testTCAP(suite) -> [];
-testTCAP(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testTCAP:compile(Config,?BER,[]),
- ?line testTCAP:test(?BER,Config),
-
- ?line ?ber_driver(?BER,testTCAP:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testTCAP:test(?BER,Config)),
-
- ?line ?ber_driver(?BER,testTCAP:compile_asn1config(Config,?BER,[asn1config])),
- ?line ?ber_driver(?BER,testTCAP:test_asn1config()).
-
-testDER(suite) ->[];
-testDER(Config) ->
- ?line true = code:add_patha(?config(priv_dir,Config)),
-
- ?line testDER:compile(Config,?BER,[]),
- ?line testDER:test(),
-
- ?line ?ber_driver(?BER,testDER:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testDER:test()),
-
- ?line testParamBasic:compile_der(Config,?BER),
- ?line testParamBasic_cases(der),
-
-
- ?line testSeqSetDefaultVal:compile(Config,?BER),
- ?line testSeqSetDefaultVal_cases(?BER).
-
-testSeqSetDefaultVal_cases(?BER) ->
- ?line testSeqSetDefaultVal:main(?BER).
-
-
-specialized_decodes(suite) -> [];
-specialized_decodes(Config) ->
- ?line test_partial_incomplete_decode:compile(Config,?BER,[optimize]),
- ?line test_partial_incomplete_decode:test(?BER,Config),
- ?line test_selective_decode:test(?BER,Config).
-
-special_decode_performance(suite) ->[];
-special_decode_performance(Config) ->
- ?line ?ber_driver(?BER,test_special_decode_performance:compile(Config,?BER)),
- ?line ?ber_driver(?BER,test_special_decode_performance:go(all)).
-
-
-test_driver_load(suite) -> [];
-test_driver_load(Config) ->
- ?line test_driver_load:compile(Config,?PER),
- ?line test_driver_load:test(?PER,5).
-
-test_ParamTypeInfObj(suite) -> [];
-test_ParamTypeInfObj(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line ok = asn1ct:compile(filename:join(DataDir,"IN-CS-1-Datatypes"),[ber_bin]).
-
-test_WS_ParamClass(suite) -> [];
-test_WS_ParamClass(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line ok = asn1ct:compile(filename:join(DataDir,"InformationFramework"),
- [ber_bin]).
-
-test_Defed_ObjectIdentifier(suite) -> [];
-test_Defed_ObjectIdentifier(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line ok = asn1ct:compile(filename:join(DataDir,"UsefulDefinitions"),
- [ber_bin]).
-
-testSelectionType(suite) -> [];
-testSelectionType(Config) ->
-
- ?line ok = testSelectionTypes:compile(Config,?BER,[]),
- ?line {ok,_} = testSelectionTypes:test(),
-
- ?line ok = testSelectionTypes:compile(Config,?PER,[]),
- ?line {ok,_} = testSelectionTypes:test().
-
-testSSLspecs(suite) -> [];
-testSSLspecs(Config) ->
-
- ?line ok = testSSLspecs:compile(Config,?BER,
- [optimize,compact_bit_string,der]),
- ?line testSSLspecs:run(?BER),
-
- case code:which(asn1ct) of
- cover_compiled ->
- ok;
- _ ->
- ?line ok = testSSLspecs:compile_inline(Config,?BER),
- ?line ok = testSSLspecs:run_inline(?BER)
- end.
-
-testNortel(suite) -> [];
-testNortel(Config) ->
- ?line DataDir = ?config(data_dir,Config),
-
- ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"),[?BER]),
- ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"),
- [?BER,optimize]),
- ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"),
- [?BER,optimize,driver]),
- ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"),[?PER]),
- ?line ?per_bit_opt(ok = asn1ct:compile(filename:join(DataDir,"Nortel"),
- [?PER,optimize])),
- ?line ?uper_bin(ok = asn1ct:compile(filename:join(DataDir,"Nortel"),[uper_bin])),
- ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"),
- [?PER,optimize]).
-test_undecoded_rest(suite) -> [];
-test_undecoded_rest(Config) ->
-
- ?line ok = test_undecoded_rest:compile(Config,?BER,[]),
- ?line ok = test_undecoded_rest:test([]),
-
- ?line ok = test_undecoded_rest:compile(Config,?BER,[undec_rest]),
- ?line ok = test_undecoded_rest:test(undec_rest),
-
- ?line ok = test_undecoded_rest:compile(Config,?PER,[]),
- ?line ok = test_undecoded_rest:test([]),
-
- ?line ?per_bit_opt(ok = test_undecoded_rest:compile(Config,?PER,[optimize,undec_rest])),
- ?line ?per_bit_opt(ok = test_undecoded_rest:test(undec_rest)),
-
- ?line ?uper_bin(ok = test_undecoded_rest:compile(Config,uper_bin,[undec_rest])),
- ?line ?uper_bin(ok = test_undecoded_rest:test(undec_rest)),
-
- ?line ok = test_undecoded_rest:compile(Config,?PER,[undec_rest]),
- ?line ok = test_undecoded_rest:test(undec_rest).
-
-test_inline(suite) -> [];
-test_inline(Config) ->
- case code:which(asn1ct) of
- cover_compiled ->
- {skip,"Not runnable when cover compiled"};
- _ ->
- ?line ok=test_inline:compile(Config,?BER,[]),
- ?line test_inline:main(?BER),
- ?line test_inline:inline1(Config,?BER,[]),
- ?line test_inline:performance2()
- end.
-
-%test_inline_prf(suite) -> [];
-%test_inline_prf(Config) ->
-% ?line test_inline:performance(Config).
-
-testTcapsystem(suite) -> [];
-testTcapsystem(Config) ->
- ?line ok=testTcapsystem:compile(Config,?BER,[]).
-
-testNBAPsystem(suite) -> [];
-testNBAPsystem(Config) ->
- ?line ok=testNBAPsystem:compile(Config,?PER,?per_optimize(?BER)),
- ?line ok=testNBAPsystem:test(?PER,Config).
-
-test_compile_options(suite) -> [];
-test_compile_options(Config) ->
- case code:which(asn1ct) of
- cover_compiled ->
- {skip,"Not runnable when cover compiled"};
- _ ->
- ?line ok = test_compile_options:wrong_path(Config),
- ?line ok = test_compile_options:path(Config),
- ?line ok = test_compile_options:noobj(Config),
- ?line ok = test_compile_options:record_name_prefix(Config),
- ?line ok = test_compile_options:verbose(Config)
- end.
-testDoubleEllipses(suite) -> [];
-testDoubleEllipses(Config) ->
- ?line testDoubleEllipses:compile(Config,?BER,[]),
- ?line testDoubleEllipses:main(?BER),
- ?line ?ber_driver(?BER,testDoubleEllipses:compile(Config,?BER,[driver])),
- ?line ?ber_driver(?BER,testDoubleEllipses:main(?BER)),
- ?line ?per_bit_opt(testDoubleEllipses:compile(Config,?PER,[optimize])),
- ?line ?per_bit_opt(testDoubleEllipses:main(?PER)),
- ?line ?uper_bin(testDoubleEllipses:compile(Config,uper_bin,[])),
- ?line ?uper_bin(testDoubleEllipses:main(uper_bin)),
- ?line testDoubleEllipses:compile(Config,?PER,?per_optimize(?BER)),
- ?line testDoubleEllipses:main(?PER).
-
-test_modified_x420(suite) -> [];
-test_modified_x420(Config) ->
- ?line test_modified_x420:compile(Config),
- ?line test_modified_x420:test_io(Config).
-
-testX420(suite) -> [];
-testX420(Config) ->
- ?line testX420:compile(?BER,[der],Config),
- ?line ok = testX420:ticket7759(?BER,Config),
- ?line testX420:compile(?PER,[],Config).
-
-test_x691(suite) -> [];
-test_x691(Config) ->
- case ?PER of
- per ->
- ?line ok = test_x691:compile(Config,uper_bin,[]),
- ?line true = test_x691:cases(uper_bin,unaligned),
- ?line ok = test_x691:compile(Config,?PER,[]),
- ?line true = test_x691:cases(?PER,aligned),
-%% ?line ok = asn1_test_lib:ticket_7678(Config,[]),
- ?line ok = asn1_test_lib:ticket_7708(Config,[]),
- ?line ok = asn1_test_lib:ticket_7763(Config);
- _ ->
- ?line ok = test_x691:compile(Config,?PER,?per_optimize(?BER)),
- ?line true = test_x691:cases(?PER,aligned)
- end.
-%% ?line ok = asn1_test_lib:ticket_7876(Config,?PER,[]),
-%% ?line ok = asn1_test_lib:ticket_7876(Config,?PER,[compact_bit_string]),
-%% ?line ok = asn1_test_lib:ticket_7876(Config,?PER,[optimize]),
-%% ?line ok = asn1_test_lib:ticket_7876(Config,?PER,[optimize,compact_bit_string]).
-
-
-ticket_6143(suite) -> [];
-ticket_6143(Config) ->
- ?line ok = test_compile_options:ticket_6143(Config).
-
-testExtensionAdditionGroup(suite) -> [];
-testExtensionAdditionGroup(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line PrivDir = ?config(priv_dir,Config),
- ?line Path = code:get_path(),
- ?line code:add_patha(PrivDir),
- DoIt = fun(Erule) ->
- ?line ok = asn1ct:compile(filename:join(DataDir,"Extension-Addition-Group"),[Erule,{outdir,PrivDir}]),
- ?line {ok,_M} = compile:file(filename:join(DataDir,"extensionAdditionGroup"),[{i,PrivDir},{outdir,PrivDir},debug_info]),
- ?line ok = extensionAdditionGroup:run(Erule)
- end,
- ?line [DoIt(Rule)|| Rule <- [per_bin,uper_bin,ber_bin]],
- ?line code:set_path(Path).
-
-
-
-% parse_modules() ->
-% ["ImportsFrom"].
-
-per_modules() ->
- [X || X <- test_modules()].
-ber_modules() ->
- [X || X <- test_modules(),
- X =/= "CommonDataTypes",
- X =/= "DS-EquipmentUser-CommonFunctionOrig-TransmissionPath",
- X =/= "H323-MESSAGES",
- X =/= "H235-SECURITY-MESSAGES",
- X =/= "MULTIMEDIA-SYSTEM-CONTROL"].
-test_modules() ->
- _Modules = [
- "BitStr",
- "CommonDataTypes",
- "Constraints",
- "ContextSwitchingTypes",
- "DS-EquipmentUser-CommonFunctionOrig-TransmissionPath",
- "Enum",
- "From",
- "H235-SECURITY-MESSAGES",
- "H323-MESSAGES",
- %%"MULTIMEDIA-SYSTEM-CONTROL", recursive type , problem for asn1ct:value
- "Import",
- "Int",
- "MAP-commonDataTypes",
-% ambigous tags "MAP-insertSubscriberData-def",
- "Null",
- "Octetstr",
- "One",
- "P-Record",
- "P",
-% "PDUs",
- "Person",
- "PrimStrings",
- "Real",
- "XSeq",
- "XSeqOf",
- "XSet",
- "XSetOf",
- "String",
- "SwCDR",
-% "Syntax",
- "Time"
-% ANY "Tst",
-% "Two",
-% errors that should be detected "UndefType"
-] ++
- [
- "SeqSetLib", % must be compiled before Seq and Set
- "Seq",
- "Set",
- "SetOf",
- "SeqOf",
- "Prim",
- "Cho",
- "Def",
- "Opt",
- "ELDAPv3",
- "LDAP"
- ].
-
-
-common() ->
-[].
-
-particular() ->
-[smp, ticket7904].
-
-
-smp(suite) -> [];
-smp(Config) ->
- case erlang:system_info(smp_support) of
- true ->
- NumOfProcs = erlang:system_info(schedulers),
- io:format("smp starting ~p workers\n",[NumOfProcs]),
-
- ?line Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()},
- ?line ok = testNBAPsystem:compile(Config,per_bin,[optimize]),
-
- Parent = self(),
-
- ?line ok = asn1rt:load_driver(),
-
- smp2(Parent,NumOfProcs,Msg,2),
-
- N = 10000,
-
- ?line {Time1,ok} = timer:tc(?MODULE,smp2,[Parent,NumOfProcs,Msg, N]),
- ?line {Time1S,ok} = timer:tc(?MODULE,sequential,[NumOfProcs * N,Msg]),
-
- ?line ok = testNBAPsystem:compile(Config,ber_bin,[optimize,driver]),
- ?line {Time2,ok} = timer:tc(?MODULE,smp2,[Parent,NumOfProcs,Msg, N]),
-
- ?line {Time2S,ok} = timer:tc(?MODULE,sequential,[NumOfProcs * N,Msg]),
-
- {comment,lists:flatten(io_lib:format("Encode/decode time parallell with ~p cores: ~p [microsecs]~nEncode/decode time sequential: ~p [microsecs]",[NumOfProcs,Time1+Time2,Time1S+Time2S]))};
- false ->
- {skipped,"No smp support"}
- end.
-
-smp2(Parent,NumOfProcs,Msg, N) ->
- Pids = [spawn_link(fun() -> worker(Msg,Parent, N) end)
- || _ <- lists:seq(1,NumOfProcs)],
- ?line ok = wait_pids(Pids).
-
-worker(Msg, Parent, N) ->
- %% io:format("smp worker ~p with ~p worker loops.~n",[self(), N]),
- worker_loop(N, Msg),
- Parent ! self().
-
-worker_loop(0, _Msg) ->
- ok;
-worker_loop(N, Msg) ->
- ?line {ok,B}=asn1_wrapper:encode('NBAP-PDU-Discriptions',
- 'NBAP-PDU',
- Msg),
- ?line {ok,_Msg}=asn1_wrapper:decode('NBAP-PDU-Discriptions',
- 'NBAP-PDU',
- B),
- worker_loop(N - 1, Msg).
-
-
-wait_pids([]) ->
- ok;
-wait_pids(Pids) ->
- receive
- Pid when is_pid(Pid) ->
- ?line true = lists:member(Pid,Pids),
- Others = lists:delete(Pid,Pids),
- io:format("wait_pid got ~p, still waiting for ~p\n",[Pid,Others]),
- wait_pids(Others);
- Err ->
- io:format("Err: ~p~n",[Err]),
- ?line exit(Err)
- end.
-
-sequential(N,Msg) ->
- %%io:format("sequential encode/decode with N = ~p~n",[N]),
- worker_loop(N,Msg).
-
--record('InitiatingMessage',{procedureCode,criticality,value}).
--record('Iu-ReleaseCommand',{first,second}).
-
-ticket7904(suite) -> [];
-ticket7904(Config) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line OutDir = ?config(priv_dir,Config),
-
- ?line ok = asn1ct:compile(DataDir ++
- "RANAPextract1",[per_bin,optimize,{outdir,OutDir}]),
-
- Val1 = #'InitiatingMessage'{procedureCode=1,
- criticality=ignore,
- value=#'Iu-ReleaseCommand'{
- first=13,
- second=true}},
-
- ?line {ok,_} = 'RANAPextract1':encode('InitiatingMessage', Val1),
- asn1rt:unload_driver(),
- ?line {ok,_} = 'RANAPextract1':encode('InitiatingMessage', Val1).
diff --git a/lib/asn1/test/asn1_bin_v2_particular_SUITE.erl.src b/lib/asn1/test/asn1_bin_v2_particular_SUITE.erl.src
index abd21b0d78..4c3c8c7808 100644
--- a/lib/asn1/test/asn1_bin_v2_particular_SUITE.erl.src
+++ b/lib/asn1/test/asn1_bin_v2_particular_SUITE.erl.src
@@ -11,37 +11,219 @@ smp(Config) ->
?line Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()},
?line ok = testNBAPsystem:compile(Config,per_bin,[optimize]),
-
- Parent = self(),
- ?line ok = asn1rt:load_driver(),
-
- smp2(Parent,NumOfProcs,Msg,2),
+ enc_dec(NumOfProcs,Msg,2),
N = 10000,
- ?line {Time1,ok} = timer:tc(?MODULE,smp2,[Parent,NumOfProcs,Msg, N]),
- ?line {Time1S,ok} = timer:tc(?MODULE,sequential,[NumOfProcs * N,Msg]),
+ ?line {Time1,ok} = timer:tc(?MODULE,enc_dec,[NumOfProcs,Msg, N]),
+ ?line {Time1S,ok} = timer:tc(?MODULE,enc_dec,[1, Msg, NumOfProcs * N]),
- ?line ok = testNBAPsystem:compile(Config,ber_bin,[optimize,driver]),
- ?line {Time2,ok} = timer:tc(?MODULE,smp2,[Parent,NumOfProcs,Msg, N]),
+ ?line ok = testNBAPsystem:compile(Config,ber_bin,[optimize,nif]),
+ ?line {Time3,ok} = timer:tc(?MODULE,enc_dec,[NumOfProcs,Msg, N]),
- ?line {Time2S,ok} = timer:tc(?MODULE,sequential,[NumOfProcs * N,Msg]),
+ ?line {Time3S,ok} = timer:tc(?MODULE,enc_dec,[1, Msg, NumOfProcs * N]),
- {comment,lists:flatten(io_lib:format("Encode/decode time parallell with ~p cores: ~p [microsecs]~nEncode/decode time sequential: ~p [microsecs]",[NumOfProcs,Time1+Time2,Time1S+Time2S]))};
+ {comment,lists:flatten(
+ io_lib:format(
+ "Encode/decode time parallell with ~p cores: ~p [microsecs]~n"
+ "Encode/decode time sequential: ~p [microsecs]",
+ [NumOfProcs,Time1+Time3,Time1S+Time3S]))};
false ->
{skipped,"No smp support"}
end.
-smp2(Parent,NumOfProcs,Msg, N) ->
- Pids = [spawn_link(fun() -> worker(Msg,Parent, N) end)
- || _ <- lists:seq(1,NumOfProcs)],
- ?line ok = wait_pids(Pids).
+per_performance(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ NifDir = filename:join(PrivDir,"nif"),
+ ErlDir = filename:join(PrivDir,"erl"),
+ file:make_dir(NifDir),file:make_dir(ErlDir),
+
+ ?line Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()},
+ ?line ok = testNBAPsystem:compile([{priv_dir,NifDir}|Config],per_bin,
+ [optimize]),
+ ?line ok = testNBAPsystem:compile([{priv_dir,ErlDir}|Config],per_bin,
+ []),
+
+ Modules = ['NBAP-CommonDataTypes',
+ 'NBAP-Constants',
+ 'NBAP-Containers',
+ 'NBAP-IEs',
+ 'NBAP-PDU-Contents',
+ 'NBAP-PDU-Discriptions'],
+
+
+ PreNif = fun() ->
+ code:add_patha(NifDir),
+ lists:foreach(fun(M) ->
+ code:purge(M),
+ code:load_file(M)
+ end,Modules)
+ end,
+
+ PreErl = fun() ->
+ code:add_patha(ErlDir),
+ lists:foreach(fun(M) ->
+ code:purge(M),
+ code:load_file(M)
+ end,Modules)
+ end,
+
+ Func = fun() ->
+ element(1,timer:tc(
+ asn1_wrapper,encode,['NBAP-PDU-Discriptions',
+ 'NBAP-PDU',
+ Msg]))
+ end,
+
+ nif_vs_erlang_performance({{{PreNif,Func},{PreErl,Func}},100000,32}).
+
+ber_performance(Config) ->
+
+ ?line Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()},
+ ?line ok = testNBAPsystem:compile(Config,ber_bin,[optimize,nif]),
+
+
+ BerFun = fun() ->
+ {ok,B} = asn1_wrapper:encode('NBAP-PDU-Discriptions',
+ 'NBAP-PDU', Msg),
+ asn1_wrapper:decode(
+ 'NBAP-PDU-Discriptions',
+ 'NBAP-PDU',
+ B)
+ end,
+ nif_vs_erlang_performance({BerFun,100000,32}).
+
+cert_pem_performance(Config) when is_list(Config) ->
+ cert_pem_performance({100000, 32});
+cert_pem_performance({N,S}) ->
+ nif_vs_erlang_performance({fun cert_pem/0,N,S}).
+
+dsa_pem_performance(Config) when is_list(Config) ->
+ cert_pem_performance({100000, 32});
+dsa_pem_performance({N,S}) ->
+ nif_vs_erlang_performance({fun dsa_pem/0,N,S}).
+
+
+nif_vs_erlang_performance({{TC1,TC2},N,Sched}) ->
+ random:seed({123,456,789}),
+ io:format("Running a ~p sample with ~p max procs...~n~n",[N,Sched]),
+
+ {True,False} = exec(TC1,TC2,Sched,N+1),
+
+ io:format("~ndone!~n"),
+
+ io:format("~n"),TStats = print_stats(strip(True,N div 20)),
+ io:format("~n"),FStats = print_stats(strip(False,N div 20)),
+ Str = io_lib:format("~nNifs are ~.3f% faster than erlang!~n",
+ [(element(2,FStats) - element(2,TStats)) /
+ element(2,FStats) * 100]),
+ io:format(Str),
+ {comment, lists:flatten(Str)};
+nif_vs_erlang_performance({T,N,Sched}) ->
+ PTC1 = fun() ->
+ application:set_env(asn1, nif_loadable, true)
+ end,
+ PTC2 = fun() ->
+ application:set_env(asn1, nif_loadable, false)
+ end,
+ TC = fun() ->
+ element(1,timer:tc(T))
+ end,
+ nif_vs_erlang_performance({{{PTC1,TC},{PTC2,TC}},N,Sched}).
+
+
+print_stats(Data) ->
+ Length = length(Data),
+ Mean = lists:sum(Data) / Length,
+ Variance = lists:foldl(fun(N,Acc) -> math:pow(N - Mean, 2)+Acc end, 0, Data),
+ StdDev = math:sqrt(Variance / Length),
+ Median = lists:nth(round(Length/2),Data),
+ Min = lists:min(Data),
+ Max = lists:max(Data),
+ if Length < 20 ->
+ io:format("Data: ~w~n",[Data]);
+ true ->
+ ok
+ end,
+ io:format("Length: ~p~nMean: ~p~nStdDev: ~p~nMedian: ~p~nMin: ~p~nMax: ~p~n",
+ [Length,Mean,StdDev,Median,Min,Max]),
+ {Length,Mean,StdDev,Median,Min,Max}.
+
+collect(Acc) ->
+ receive
+ {Tag,Val} ->
+ Prev = proplists:get_value(Tag,Acc,[]),
+ collect(lists:keystore(Tag,1,Acc,{Tag,[Val|Prev]}))
+ after 100 ->
+ Acc
+ end.
+
+exec(One,Two,Max,N) ->
+ exec(One,Two,Max,N,{[],[]}).
+exec(_,_,_,1,{D1,D2}) ->
+ {lists:flatten(D1),lists:flatten(D2)};
+exec({PreOne,One} = O,{PreTwo,Two} = T,MaxProcs, N, {D1,D2}) ->
+ Num = random:uniform(round(N/2)),
+ if Num rem 3 == 0 ->
+ timer:sleep(Num rem 1000);
+ true ->
+ ok
+ end,
+ Procs = random:uniform(MaxProcs),
+ io:format("\tBatch: ~p items in ~p processes, ~p left~n",[Num,Procs,N-Num]),
+ if Num rem 2 == 1 ->
+ erlang:garbage_collect(),
+ PreOne(),
+ MoreOne = pexec(One, Num, Procs, []),
+ erlang:garbage_collect(),
+ PreTwo(),
+ MoreTwo = pexec(Two, Num, Procs, []);
+ true ->
+ erlang:garbage_collect(),
+ PreTwo(),
+ MoreTwo = pexec(Two, Num, Procs, []),
+ erlang:garbage_collect(),
+ PreOne(),
+ MoreOne = pexec(One, Num, Procs, [])
+ end,
+ exec(O,T,MaxProcs,N-Num,{[MoreOne|D1],
+ [MoreTwo|D2]}).
+
+pexec(_Fun, _, 0, []) ->
+ [];
+pexec(Fun, _, 0, [{Ref,Pid}|Rest]) ->
+ receive
+ {data,D} ->
+ [D|pexec(Fun,0,0,[{Ref,Pid}|Rest])];
+ {'DOWN', Ref, process, Pid, normal} ->
+ pexec(Fun, 0,0,Rest)
+ end;
+pexec(Fun, 0, 1, AccProcs) ->
+ pexec(Fun, 0, 0, AccProcs);
+pexec(Fun, N, 1, AccProcs) ->
+ [Fun()|pexec(Fun, N - 1, 1, AccProcs)];
+pexec(Fun, N, Procs, AccProcs) ->
+ S = self(),
+ Pid = spawn(fun() ->
+ S ! {data,pexec(Fun,N,1,[])}
+ end),
+ Ref = erlang:monitor(process, Pid),
+ pexec(Fun, N, Procs - 1, [{Ref,Pid}|AccProcs]).
-worker(Msg, Parent, N) ->
- %% io:format("smp worker ~p with ~p worker loops.~n",[self(), N]),
- worker_loop(N, Msg),
- Parent ! self().
+strip(Data,Num) ->
+ {_,R} = lists:split(Num,lists:sort(Data)),
+ element(2,lists:split(Num,lists:reverse(R))).
+
+faster(A,B) ->
+ (B - A)/B * 100.
+
+enc_dec(1, Msg, N) ->
+ worker_loop(N, Msg);
+enc_dec(NumOfProcs,Msg, N) ->
+ pforeach(fun(_) ->
+ worker_loop(N, Msg)
+ end, [I || I <- lists:seq(1,NumOfProcs)]).
worker_loop(0, _Msg) ->
ok;
@@ -50,28 +232,24 @@ worker_loop(N, Msg) ->
'NBAP-PDU',
Msg),
?line {ok,_Msg}=asn1_wrapper:decode('NBAP-PDU-Discriptions',
- 'NBAP-PDU',
- B),
+ 'NBAP-PDU',
+ B),
worker_loop(N - 1, Msg).
-wait_pids([]) ->
- ok;
-wait_pids(Pids) ->
+pforeach(Fun, List) ->
+ pforeach(Fun, List, []).
+pforeach(Fun, [], [{Pid,Ref}|Pids]) ->
receive
- Pid when is_pid(Pid) ->
- ?line true = lists:member(Pid,Pids),
- Others = lists:delete(Pid,Pids),
- io:format("wait_pid got ~p, still waiting for ~p\n",[Pid,Others]),
- wait_pids(Others);
- Err ->
- io:format("Err: ~p~n",[Err]),
- ?line exit(Err)
- end.
-
-sequential(N,Msg) ->
- %%io:format("sequential encode/decode with N = ~p~n",[N]),
- worker_loop(N,Msg).
+ {'DOWN', Ref, process, Pid, normal} ->
+ pforeach(Fun, [], Pids)
+ end;
+pforeach(Fun, [H|T], Pids) ->
+ Pid = spawn(fun() -> Fun(H) end),
+ Ref = erlang:monitor(process, Pid),
+ pforeach(Fun, T, [{Pid, Ref}|Pids]);
+pforeach(_Fun,[],[]) ->
+ ok.
-record('InitiatingMessage',{procedureCode,criticality,value}).
-record('Iu-ReleaseCommand',{first,second}).
@@ -93,3 +271,21 @@ ticket7904(Config) ->
?line {ok,_} = 'RANAPextract1':encode('InitiatingMessage', Val1),
asn1rt:unload_driver(),
?line {ok,_} = 'RANAPextract1':encode('InitiatingMessage', Val1).
+
+cert_pem() ->
+ 'OTP-PUB-KEY':decode('Certificate',<<48,130,3,184,48,130,3,33,160,3,2,1,2,2,1,1,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,48,129,131,49,14,48,12,6,3,85,4,3,19,5,111,116,112,67,65,49,19,48,17,6,3,85,4,11,19,10,69,114,108,97,110,103,32,79,84,80,49,20,48,18,6,3,85,4,10,19,11,69,114,105,99,115,115,111,110,32,65,66,49,11,48,9,6,3,85,4,6,19,2,83,69,49,18,48,16,6,3,85,4,7,19,9,83,116,111,99,107,104,111,108,109,49,37,48,35,6,9,42,134,72,134,247,13,1,9,1,22,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,48,30,23,13,48,56,48,49,48,57,48,56,50,57,51,48,90,23,13,49,55,49,49,49,55,48,56,50,57,51,48,90,48,129,132,49,15,48,13,6,3,85,4,3,19,6,99,108,105,101,110,116,49,19,48,17,6,3,85,4,11,19,10,69,114,108,97,110,103,32,79,84,80,49,20,48,18,6,3,85,4,10,19,11,69,114,105,99,115,115,111,110,32,65,66,49,11,48,9,6,3,85,4,6,19,2,83,69,49,18,48,16,6,3,85,4,7,19,9,83,116,111,99,107,104,111,108,109,49,37,48,35,6,9,42,134,72,134,247,13,1,9,1,22,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,48,129,159,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,129,141,0,48,129,137,2,129,129,0,245,56,68,254,220,239,193,190,63,221,182,60,67,77,121,163,214,136,137,183,139,8,166,30,100,27,45,17,126,58,15,173,151,218,75,224,148,14,22,164,10,100,186,183,104,175,197,97,96,182,146,150,106,129,140,100,194,106,90,62,133,233,155,46,155,33,101,220,83,193,182,232,240,99,253,249,114,8,159,172,143,77,179,132,229,205,29,110,185,233,224,52,25,149,249,100,80,229,199,125,23,106,146,233,159,26,13,8,161,206,221,43,240,149,42,45,194,190,85,6,235,152,220,219,160,32,144,67,2,3,1,0,1,163,130,1,55,48,130,1,51,48,9,6,3,85,29,19,4,2,48,0,48,11,6,3,85,29,15,4,4,3,2,5,224,48,29,6,3,85,29,14,4,22,4,20,26,59,44,5,72,211,158,214,23,34,30,241,125,27,123,115,93,163,231,120,48,129,179,6,3,85,29,35,4,129,171,48,129,168,128,20,6,171,128,52,58,164,184,118,178,189,157,46,40,229,109,145,222,125,1,155,161,129,140,164,129,137,48,129,134,49,17,48,15,6,3,85,4,3,19,8,101,114,108,97,110,103,67,65,49,19,48,17,6,3,85,4,11,19,10,69,114,108,97,110,103,32,79,84,80,49,20,48,18,6,3,85,4,10,19,11,69,114,105,99,115,115,111,110,32,65,66,49,18,48,16,6,3,85,4,7,19,9,83,116,111,99,107,104,111,108,109,49,11,48,9,6,3,85,4,6,19,2,83,69,49,37,48,35,6,9,42,134,72,134,247,13,1,9,1,22,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,130,1,1,48,33,6,3,85,29,17,4,26,48,24,129,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,48,33,6,3,85,29,18,4,26,48,24,129,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,3,129,129,0,93,11,112,227,121,15,121,179,247,135,110,216,17,197,84,18,149,166,147,142,190,178,0,209,190,0,142,233,144,100,194,205,220,182,73,204,108,42,95,23,48,63,4,120,239,42,194,25,184,35,117,107,96,229,18,45,76,122,125,40,171,210,132,50,146,178,160,55,17,35,255,208,114,30,47,55,185,154,155,165,204,180,14,143,20,234,6,234,201,225,72,235,5,87,61,255,250,23,217,1,144,246,98,221,223,102,49,168,177,13,70,241,26,27,254,251,217,14,244,18,242,197,151,50,186,214,15,42>>).
+
+dsa_pem() ->
+ 'OTP-PUB-KEY':decode('DSAPrivateKey',<<48,130,1,187,2,1,0,2,129,129,0,183,179,230,217,37,99,144,157,21,228,204,162,207,61,246,144,58,139,139,184,184,43,108,206,0,115,173,208,100,233,201,121,21,90,179,119,53,140,25,52,34,202,121,211,164,107,43,56,68,162,159,51,244,232,138,126,164,109,121,89,237,142,57,28,32,188,44,67,253,111,121,104,40,141,211,255,140,118,37,234,150,201,155,160,16,17,51,59,26,249,41,129,16,211,119,128,95,254,182,235,132,0,92,206,93,77,106,217,201,132,203,4,75,201,246,204,216,162,1,84,79,211,10,21,152,195,103,145,2,21,0,213,30,184,86,247,16,247,69,192,241,35,138,84,57,140,3,71,65,206,233,2,129,129,0,148,179,24,63,74,91,128,25,96,29,5,78,223,246,175,0,121,86,54,178,42,231,98,241,147,180,157,60,149,160,50,243,227,76,175,89,234,203,252,242,76,108,9,204,157,182,59,206,227,127,99,215,42,156,194,78,116,25,7,62,243,169,45,5,101,179,247,127,199,144,135,103,23,42,154,125,231,248,154,101,175,155,101,42,232,41,80,41,47,128,208,11,31,106,63,12,202,207,135,80,200,136,250,171,31,118,52,91,200,138,112,111,179,23,214,123,21,118,194,179,0,185,217,52,197,182,236,13,2,129,128,124,66,0,111,121,139,142,209,95,136,95,237,177,150,248,252,49,135,117,100,155,232,138,244,132,89,40,5,70,125,202,96,78,239,76,37,125,149,82,64,107,54,227,73,25,180,227,41,0,234,73,47,80,242,242,129,250,61,68,62,39,38,156,193,146,40,241,247,106,215,223,202,194,110,130,62,186,90,18,28,196,174,99,47,193,61,130,100,150,25,248,115,164,231,153,99,46,69,66,139,33,187,51,49,35,219,234,29,44,172,166,247,42,16,177,187,9,162,81,243,33,26,100,46,78,57,203,135,2,20,89,128,159,14,187,249,182,172,15,88,162,110,211,71,179,209,29,125,217,38>>),
+ 'OTP-PUB-KEY':decode('SubjectPublicKeyInfo',<<48,130,1,183,48,130,1,44,6,7,42,134,72,206,56,4,1,48,130,1,31,2,129,129,0,183,179,230,217,37,99,144,157,21,228,204,162,207,61,246,144,58,139,139,184,184,43,108,206,0,115,173,208,100,233,201,121,21,90,179,119,53,140,25,52,34,202,121,211,164,107,43,56,68,162,159,51,244,232,138,126,164,109,121,89,237,142,57,28,32,188,44,67,253,111,121,104,40,141,211,255,140,118,37,234,150,201,155,160,16,17,51,59,26,249,41,129,16,211,119,128,95,254,182,235,132,0,92,206,93,77,106,217,201,132,203,4,75,201,246,204,216,162,1,84,79,211,10,21,152,195,103,145,2,21,0,213,30,184,86,247,16,247,69,192,241,35,138,84,57,140,3,71,65,206,233,2,129,129,0,148,179,24,63,74,91,128,25,96,29,5,78,223,246,175,0,121,86,54,178,42,231,98,241,147,180,157,60,149,160,50,243,227,76,175,89,234,203,252,242,76,108,9,204,157,182,59,206,227,127,99,215,42,156,194,78,116,25,7,62,243,169,45,5,101,179,247,127,199,144,135,103,23,42,154,125,231,248,154,101,175,155,101,42,232,41,80,41,47,128,208,11,31,106,63,12,202,207,135,80,200,136,250,171,31,118,52,91,200,138,112,111,179,23,214,123,21,118,194,179,0,185,217,52,197,182,236,13,3,129,132,0,2,129,128,124,66,0,111,121,139,142,209,95,136,95,237,177,150,248,252,49,135,117,100,155,232,138,244,132,89,40,5,70,125,202,96,78,239,76,37,125,149,82,64,107,54,227,73,25,180,227,41,0,234,73,47,80,242,242,129,250,61,68,62,39,38,156,193,146,40,241,247,106,215,223,202,194,110,130,62,186,90,18,28,196,174,99,47,193,61,130,100,150,25,248,115,164,231,153,99,46,69,66,139,33,187,51,49,35,219,234,29,44,172,166,247,42,16,177,187,9,162,81,243,33,26,100,46,78,57,203,135>>),
+ 'OTP-PUB-KEY':decode('DSAParams',<<48,130,1,31,2,129,129,0,183,179,230,217,37,99,144,157,21,228,204,162,207,61,246,144,58,139,139,184,184,43,108,206,0,115,173,208,100,233,201,121,21,90,179,119,53,140,25,52,34,202,121,211,164,107,43,56,68,162,159,51,244,232,138,126,164,109,121,89,237,142,57,28,32,188,44,67,253,111,121,104,40,141,211,255,140,118,37,234,150,201,155,160,16,17,51,59,26,249,41,129,16,211,119,128,95,254,182,235,132,0,92,206,93,77,106,217,201,132,203,4,75,201,246,204,216,162,1,84,79,211,10,21,152,195,103,145,2,21,0,213,30,184,86,247,16,247,69,192,241,35,138,84,57,140,3,71,65,206,233,2,129,129,0,148,179,24,63,74,91,128,25,96,29,5,78,223,246,175,0,121,86,54,178,42,231,98,241,147,180,157,60,149,160,50,243,227,76,175,89,234,203,252,242,76,108,9,204,157,182,59,206,227,127,99,215,42,156,194,78,116,25,7,62,243,169,45,5,101,179,247,127,199,144,135,103,23,42,154,125,231,248,154,101,175,155,101,42,232,41,80,41,47,128,208,11,31,106,63,12,202,207,135,80,200,136,250,171,31,118,52,91,200,138,112,111,179,23,214,123,21,118,194,179,0,185,217,52,197,182,236,13>>),
+ 'OTP-PUB-KEY':decode('DSAPublicKey',<<2,129,128,124,66,0,111,121,139,142,209,95,136,95,237,177,150,248,252,49,135,117,100,155,232,138,244,132,89,40,5,70,125,202,96,78,239,76,37,125,149,82,64,107,54,227,73,25,180,227,41,0,234,73,47,80,242,242,129,250,61,68,62,39,38,156,193,146,40,241,247,106,215,223,202,194,110,130,62,186,90,18,28,196,174,99,47,193,61,130,100,150,25,248,115,164,231,153,99,46,69,66,139,33,187,51,49,35,219,234,29,44,172,166,247,42,16,177,187,9,162,81,243,33,26,100,46,78,57,203,135>>),
+ 'OTP-PUB-KEY':encode('DSAParams',{params,{'Dss-Parms',129000451850199666185842362389296595317127259539517666765336291347244303954511451744518587442120964433734460998523119938005801396466878889993179871123036311260456172022864663021425348874648247531097042575063545128239655736096045972718934778583429973433661785691086624069991876932064334822608460064613803976593,1216700114794736143432235288305776850295620488937,104420402274523493329542694749036577763086597934731674202966304958550599470165597750883637440049774107540742087494301536297571301945349213110548764383811017178451900599240379681904765817950545426764751538502808499880604633364255316249231153053427235538288687666086821781456733226598288985591031656134573747213}}),
+ 'OTP-PUB-KEY':encode(
+ 'SubjectPublicKeyInfo',
+ {'SubjectPublicKeyInfo',
+ {'AlgorithmIdentifier',
+ {1,2,840,10040,4,1},
+ <<48,130,1,31,2,129,129,0,183,179,230,217,37,99,144,157,21,228,204,162,207,61,246,144,58,139,139,184,184,43,108,206,0,115,173,208,100,233,201,121,21,90,179,119,53,140,25,52,34,202,121,211,164,107,43,56,68,162,159,51,244,232,138,126,164,109,121,89,237,142,57,28,32,188,44,67,253,111,121,104,40,141,211,255,140,118,37,234,150,201,155,160,16,17,51,59,26,249,41,129,16,211,119,128,95,254,182,235,132,0,92,206,93,77,106,217,201,132,203,4,75,201,246,204,216,162,1,84,79,211,10,21,152,195,103,145,2,21,0,213,30,184,86,247,16,247,69,192,241,35,138,84,57,140,3,71,65,206,233,2,129,129,0,148,179,24,63,74,91,128,25,96,29,5,78,223,246,175,0,121,86,54,178,42,231,98,241,147,180,157,60,149,160,50,243,227,76,175,89,234,203,252,242,76,108,9,204,157,182,59,206,227,127,99,215,42,156,194,78,116,25,7,62,243,169,45,5,101,179,247,127,199,144,135,103,23,42,154,125,231,248,154,101,175,155,101,42,232,41,80,41,47,128,208,11,31,106,63,12,202,207,135,80,200,136,250,171,31,118,52,91,200,138,112,111,179,23,214,123,21,118,194,179,0,185,217,52,197,182,236,13>>},
+ {0,
+ <<2,129,128,124,66,0,111,121,139,142,209,95,136,95,237,177,150,248,252,49,135,117,100,155,232,138,244,132,89,40,5,70,125,202,96,78,239,76,37,125,149,82,64,107,54,227,73,25,180,227,41,0,234,73,47,80,242,242,129,250,61,68,62,39,38,156,193,146,40,241,247,106,215,223,202,194,110,130,62,186,90,18,28,196,174,99,47,193,61,130,100,150,25,248,115,164,231,153,99,46,69,66,139,33,187,51,49,35,219,234,29,44,172,166,247,42,16,177,187,9,162,81,243,33,26,100,46,78,57,203,135>>}}).
diff --git a/lib/asn1/test/asn1_common_SUITE.erl.src b/lib/asn1/test/asn1_common_SUITE.erl.src
index 2fa2a09f1f..12512606d8 100644
--- a/lib/asn1/test/asn1_common_SUITE.erl.src
+++ b/lib/asn1/test/asn1_common_SUITE.erl.src
@@ -18,15 +18,12 @@
%%
%%
-common() -> [app_test, appup_test,testTimer_ber,testTimer_ber_bin,
+common() -> [{group,app_test}, {group,appup_test},testTimer_ber,testTimer_ber_bin,
testTimer_ber_bin_opt, testTimer_ber_bin_opt_driver, testTimer_per,
testTimer_per_bin, testTimer_per_bin_opt, testTimer_uper_bin,
testComment,testName2Number].
-app_test(suite) -> [{asn1_app_test,all}].
-appup_test(suite) -> [{asn1_appup_test,all}].
-
testTimer_ber(suite) -> [];
testTimer_ber(Config) ->
?line testTimer:compile(Config,ber,[]),
diff --git a/lib/asn1/test/ber_decode_error.erl b/lib/asn1/test/ber_decode_error.erl
index 96d6545636..a566e0b07f 100644
--- a/lib/asn1/test/ber_decode_error.erl
+++ b/lib/asn1/test/ber_decode_error.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -45,6 +45,10 @@ run([]) ->
run([driver]) ->
%% test of OTP-4797, bad indata to driver does not cause an EXIT
?line {error,_Reason} = asn1rt:decode('Constructed','S3',[3,5]),
+ ok;
+run([nif]) ->
+ %% test of OTP-4797, bad indata to driver does not cause an EXIT
+ ?line {error,_Reason} = asn1rt:decode('Constructed','S3',[3,5]),
ok.
diff --git a/lib/asn1/test/testContextSwitchingTypes.erl b/lib/asn1/test/testContextSwitchingTypes.erl
index 260a016c6c..7d05e5c352 100644
--- a/lib/asn1/test/testContextSwitchingTypes.erl
+++ b/lib/asn1/test/testContextSwitchingTypes.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -77,7 +77,7 @@ check_EXTERNAL_DVD(asn1_NOVALUE) ->
ok;
check_EXTERNAL_DVD(DVD) ->
{error,"failed on data-value-descriptor alternative",DVD}.
-check_EXTERNAL_DV(DV) when is_list(DV) ->
+check_EXTERNAL_DV(DV) when is_list(DV);is_binary(DV) ->
ok;
check_EXTERNAL_DV(DV) ->
{error,"failed on data-value alternative",DV}.
diff --git a/lib/asn1/test/testPrim.erl b/lib/asn1/test/testPrim.erl
index 97f99e7b1c..39c1e4d1d8 100644
--- a/lib/asn1/test/testPrim.erl
+++ b/lib/asn1/test/testPrim.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The 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,21 +37,10 @@ compile(Config,Rules,Opt) ->
?line DataDir = ?config(data_dir,Config),
?line OutDir = ?config(priv_dir,Config),
?line true = code:add_patha(?config(priv_dir,Config)),
- case Opt of
- [optimize] ->
- ?line ok = asn1ct:compile(DataDir ++ "Prim",
- [Rules,optimize,{outdir,OutDir}]),
- ?line ok = asn1ct:compile(DataDir ++ "Real",
- [Rules,optimize,{outdir,OutDir}]);
- __ ->
- ?line ok = asn1ct:compile(DataDir ++ "Prim",
- [Rules,{outdir,OutDir}]),
- ?line ok = asn1ct:compile(DataDir ++ "Real",
- [Rules,{outdir,OutDir}])
- end.
-
-
-
+ ?line ok = asn1ct:compile(DataDir ++ "Prim",
+ [Rules,{outdir,OutDir}] ++ Opt),
+ ?line ok = asn1ct:compile(DataDir ++ "Real",
+ [Rules,{outdir,OutDir}] ++ Opt).
bool(Rules) ->
diff --git a/lib/asn1/test/test_compile_options.erl b/lib/asn1/test/test_compile_options.erl
index 5e027cdedb..a622d5bfd2 100644
--- a/lib/asn1/test/test_compile_options.erl
+++ b/lib/asn1/test/test_compile_options.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The 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([wrong_path/1,comp/2,path/1,ticket_6143/1,noobj/1,
- record_name_prefix/1,verbose/1]).
+ record_name_prefix/1,verbose/1,warnings_as_errors/1]).
%% OTP-5689
wrong_path(Config) ->
@@ -141,6 +141,43 @@ verbose(Config) when is_list(Config) ->
?line [] = test_server:capture_get(),
ok.
+warnings_as_errors(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir,Config),
+ Asn1File = filename:join([PrivDir,"WERROR.asn1"]),
+ OutFile = filename:join([PrivDir,"WERROR.erl"]),
+ Opts = [{outdir,PrivDir},noobj,verbose],
+
+ %% Generate WERR.asn to emit warning
+ %% Warning: Wrong format of type/value
+ %% false/{'Externalvaluereference',_,'WERR',noInvokeId}
+ Warn = <<"WERROR DEFINITIONS IMPLICIT TAGS ::=\n"
+ "\n"
+ "BEGIN\n"
+ "\n"
+ "InvokeId ::= CHOICE\n"
+ "{\n"
+ " present INTEGER,\n"
+ " absent NULL\n"
+ "}\n"
+ "\n"
+ "noInvokeId InvokeId ::= absent:NULL\n"
+ "\n"
+ "NoInvokeId InvokeId ::= {noInvokeId}\n"
+ "\n"
+ "END -- end of useful definitions.\n">>,
+ ?line ok = file:write_file(Asn1File, Warn),
+
+ %% Test warnings_as_errors compile
+ ?line false = filelib:is_regular(OutFile),
+ ?line {error, _} = asn1ct:compile(Asn1File, [warnings_as_errors|Opts]),
+ ?line false = filelib:is_regular(OutFile),
+
+ %% Test normal compile
+ ?line ok = asn1ct:compile(Asn1File, Opts),
+ ?line true = filelib:is_regular(OutFile),
+ ?line ok = file:delete(OutFile),
+ ok.
+
outfiles_check(OutDir) ->
outfiles_check(OutDir,outfiles1()).
diff --git a/lib/asn1/test/test_inline.erl b/lib/asn1/test/test_inline.erl
index dfa3c134ae..b7ec0d8921 100644
--- a/lib/asn1/test/test_inline.erl
+++ b/lib/asn1/test/test_inline.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -173,8 +173,8 @@ mi_encdec(N,Val) ->
m_encdec(0,_) ->
ok;
m_encdec(N,Val) ->
- {ok,B}='Mod1':encode('L',Val),
- {ok,_R}='Mod1':decode('L',B),
+ {ok,B}='Mod':encode('L',Val),
+ {ok,_R}='Mod':decode('L',B),
m_encdec(N-1,Val).
diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk
index 7b52e18805..b1132155e6 100644
--- a/lib/asn1/vsn.mk
+++ b/lib/asn1/vsn.mk
@@ -1,2 +1,2 @@
#next version number to use is 1.6.15 | 1.7 | 2.0
-ASN1_VSN = 1.6.16
+ASN1_VSN = 1.6.18
diff --git a/lib/common_test/doc/src/common_test_app.xml b/lib/common_test/doc/src/common_test_app.xml
index 1ee73b890b..f58b2ab0a9 100644
--- a/lib/common_test/doc/src/common_test_app.xml
+++ b/lib/common_test/doc/src/common_test_app.xml
@@ -133,9 +133,15 @@
{require,Name,Required} | {userdata,UserData} |
{silent_connections,Conns} | {stylesheet,CSSFile} |
{ct_hooks, CTHs}</v>
- <v> Time = MilliSec | {seconds,integer()} | {minutes,integer()}
- | {hours,integer()}</v>
+ <v> Time = TimeVal | TimeFunc</v>
+ <v> TimeVal = MilliSec | {seconds,integer()} | {minutes,integer()} |
+ {hours,integer()}</v>
+ <v> TimeFunc = {Mod,Func,Args} | Fun</v>
<v> MilliSec = integer()</v>
+ <v> Mod = atom()</v>
+ <v> Func = atom()</v>
+ <v> Args = list()</v>
+ <v> Fun = fun()</v>
<v> Required = Key | {Key,SubKeys}</v>
<v> Key = atom()</v>
<v> SubKeys = SubKey | [SubKey]</v>
@@ -144,7 +150,7 @@
<v> UserData = term()</v>
<v> Conns = [atom()]</v>
<v> CSSFile = string()</v>
- <v> CTHs = [CTHModule | {CTHModule, CTHInitArgs}]</v>
+ <v> CTHs = [CTHModule | {CTHModule, CTHInitArgs} | {CTHModule, CTHInitArgs, CTHPriority}]</v>
<v> CTHModule = atom()</v>
<v> CTHInitArgs = term()</v>
</type>
@@ -161,7 +167,9 @@
test case is allowed to take (including <c>init_per_testcase/2</c>
and <c>end_per_testcase/2</c>). If the timetrap time is
exceeded, the test case fails with reason
- <c>timetrap_timeout</c>.</p>
+ <c>timetrap_timeout</c>. If a <c>TimeFunc</c> function is specified,
+ it will be called initially and must return a value on
+ <c>TimeVal</c> format.</p>
<p>The <c>require</c> tag specifies configuration variables
that are required by test cases in the suite. If the required
@@ -248,7 +256,7 @@
</type>
<desc>
- <p> MANDATORY (only if one or more groups are defined) </p>
+ <p> OPTIONAL </p>
<p>This function is called before execution of a test case group.
It typically contains initialization which is common for
@@ -279,7 +287,7 @@
</type>
<desc>
- <p> MANDATORY (only if one or more groups are defined) </p>
+ <p> OPTIONAL </p>
<p>This function is called after the execution of a test case group is finished.
It is meant to be used for cleaning up after <c>init_per_group/2</c>.
@@ -296,7 +304,7 @@
</func>
<func>
- <name>Module:init_per_testcase(TestCase, Config) -> NewConfig | {skip,Reason}</name>
+ <name>Module:init_per_testcase(TestCase, Config) -> NewConfig | {fail,Reason} | {skip,Reason}</name>
<fsummary>Test case initialization.</fsummary>
<type>
<v> TestCase = atom()</v>
@@ -311,10 +319,12 @@
<p>This function is called before each test case. The
<c>TestCase</c> argument is the name of the test case, and
- <c>Config</c> is the configuration which can be modified
- here. Whatever is returned from this function is given as
- <c>Config</c> to the test case. If <c>{skip,Reason}</c> is returned,
- the test case will be skipped and <c>Reason</c> printed
+ <c>Config</c> (list of key-value tuples) is the configuration
+ data that can be modified here. The <c>NewConfig</c> list returned
+ from this function is given as <c>Config</c> to the test case.
+ If <c>{fail,Reason}</c> is returned, the test case is
+ marked as failed without being executed. If <c>{skip,Reason}</c> is
+ returned, the test case will be skipped and <c>Reason</c> printed
in the overview log for the suite.</p>
</desc>
</func>
@@ -351,9 +361,15 @@
<v> Info = {timetrap,Time} | {require,Required} |
{require,Name,Required} | {userdata,UserData} |
{silent_connections,Conns}</v>
- <v> Time = MilliSec | {seconds,integer()} | {minutes,integer()}
- | {hours,integer()}</v>
+ <v> Time = TimeVal | TimeFunc</v>
+ <v> TimeVal = MilliSec | {seconds,integer()} | {minutes,integer()} |
+ {hours,integer()}</v>
+ <v> TimeFunc = {Mod,Func,Args} | Fun</v>
<v> MilliSec = integer()</v>
+ <v> Mod = atom()</v>
+ <v> Func = atom()</v>
+ <v> Args = list()</v>
+ <v> Fun = fun()</v>
<v> Required = Key | {Key,SubKeys}</v>
<v> Key = atom()</v>
<v> SubKeys = SubKey | [SubKey]</v>
@@ -376,7 +392,9 @@
exceeded, the test case fails with reason
<c>timetrap_timeout</c>. <c>init_per_testcase/2</c>
and <c>end_per_testcase/2</c> are included in the
- timetrap time.</p>
+ timetrap time. If a <c>TimeFunc</c> function is specified,
+ it will be called before the test case (or <c>init_per_testcase/2</c>)
+ and must return a value on <c>TimeVal</c> format.</p>
<p>The <c>require</c> tag specifies configuration variables
that are required by the test case. If the required
diff --git a/lib/common_test/doc/src/config_file_chapter.xml b/lib/common_test/doc/src/config_file_chapter.xml
index 59151a73ec..6fc6638bf7 100644
--- a/lib/common_test/doc/src/config_file_chapter.xml
+++ b/lib/common_test/doc/src/config_file_chapter.xml
@@ -285,7 +285,7 @@
<c>{ok, Config}</c> - if the configuration variables are read successfully,
</item>
<item>
- <c>{error, Error, ErrorDetails}</c> - if the callback module fails to
+ <c>{error, {Error, ErrorDetails}}</c> - if the callback module fails to
proceed with the given configuration parameters.
</item>
</list>
@@ -422,14 +422,14 @@ stop()->
call(Client, Request)->
case whereis(?REGISTERED_NAME) of
undefined->
- {error, not_started, Request};
+ {error, {not_started, Request}};
Pid->
Pid ! {Client, Request},
receive
Reply->
{ok, Reply}
after 4000->
- {error, timeout, Request}
+ {error, {timeout, Request}}
end
end.
diff --git a/lib/common_test/doc/src/ct_hooks.xml b/lib/common_test/doc/src/ct_hooks.xml
index 7d5c9f4750..f9fc1858d0 100644
--- a/lib/common_test/doc/src/ct_hooks.xml
+++ b/lib/common_test/doc/src/ct_hooks.xml
@@ -81,12 +81,14 @@
<funcs>
<func>
- <name>Module:init(Id, Opts) -&gt; State</name>
+ <name>Module:init(Id, Opts) -&gt; {ok, State} |
+ {ok, State, Priority}</name>
<fsummary>Initiates the Common Test Hook</fsummary>
<type>
<v>Id = reference() | term()</v>
<v>Opts = term()</v>
<v>State = term()</v>
+ <v>Priority = integer()</v>
</type>
<desc>
@@ -103,6 +105,10 @@
if <seealso marker="#Module:id-1">id/1</seealso> is not implemented.
</p>
+ <p><c>Priority</c> is the relative priority of this hook. Hooks with a
+ lower priority will be executed first. If no priority is given,
+ it will be set to 0. </p>
+
<p>For details about when init is called see
<seealso marker="ct_hooks_chapter#scope">scope</seealso>
in the User's Guide.</p>
@@ -296,7 +302,7 @@
<p>Note that it is not possible to add CTH's here right now,
that feature might be added later,
- but it would right now break backwards compatability.</p>
+ but it would right now break backwards compatibility.</p>
</desc>
</func>
diff --git a/lib/common_test/doc/src/ct_hooks_chapter.xml b/lib/common_test/doc/src/ct_hooks_chapter.xml
index fc5ab48e1b..3b9620d0f2 100644
--- a/lib/common_test/doc/src/ct_hooks_chapter.xml
+++ b/lib/common_test/doc/src/ct_hooks_chapter.xml
@@ -94,9 +94,11 @@
<seealso marker="common_test#Module:init_per_group-2">
init_per_group/2</seealso>. <c>CTH</c> in this case can be either
only the module name of the CTH or a tuple with the module name and the
- initial arguments to the CTH. Eg:
+ initial arguments and optionally the hook priority of the CTH. Eg:
<c>{ct_hooks,[my_cth_module]}</c> or
- <c>{ct_hooks,[{my_cth_module,[{debug,true}]}]}</c></p>
+ <c>{ct_hooks,[{my_cth_module,[{debug,true}]}]}</c> or
+ <c>{ct_hooks,[{my_cth_module,[{debug,true}],500}]}</c>
+ </p>
<section>
<title>Overriding CTHs</title>
@@ -109,7 +111,16 @@
<c>id</c> in both places, Common Test knows that this CTH
has already been installed and will not try to install it again.</p>
</section>
-
+
+ <section>
+ <title>CTH Priority</title>
+ <p>By default each CTH installed will be executed in the order which
+ they are installed. This is not always wanted so common_test allows
+ the user to specify a priority for each hook. The priority can either
+ be specified in the CTH <seealso marker="ct_hooks#Module:init-2">init/2
+ </seealso> function or when installing the hook. The priority given at
+ installation will override the priority returned by the CTH. </p>
+ </section>
</section>
<marker id="scope"/>
@@ -331,7 +342,7 @@ id(Opts) ->
%% any common state.
init(Id, Opts) ->
{ok,D} = file:open(Id,[write]),
- #state{ file_handle = D, total = 0, data = [] }.
+ {ok, #state{ file_handle = D, total = 0, data = [] }}.
%% @doc Called before init_per_suite is called.
pre_init_per_suite(Suite,Config,State) ->
@@ -394,6 +405,38 @@ terminate(State) ->
ok.</code>
</section>
+ <marker id="builtin_cths"/>
+ <section>
+ <title>Built-in CTHs</title>
+ <p>Common Test is delivered with a couple of general purpose CTHs that
+ can be enabled by the user to provide some generic testing functionality.
+ Some of these are enabled by default when starting running common_test,
+ they can be disabled by setting <c>enable_builtin_hooks</c> to
+ <c>false</c> on the command line or in the test specification. In the
+ table below there is a list of all current CTHs which are delivered with
+ Common Test.</p>
+
+ <table>
+ <row>
+ <cell><em>CTH Name</em></cell>
+ <cell><em>Is Built-in</em></cell>
+ <cell><em>Description</em></cell>
+ </row>
+ <row>
+ <cell>cth_log_redirect</cell>
+ <cell>yes</cell>
+ <cell>Captures all error_logger and SASL logging events and prints them
+ to the current test case log. If an event can not be associated with a
+ testcase it will be printed in the common test framework log. This will
+ happen for testcases which are run in parallel and events which occur
+ inbetween testcases. You can configure the level of
+ <seealso marker="sasl:sasl_app">SASL</seealso> events report
+ using the normal SASL mechanisms. </cell>
+ </row>
+ </table>
+
+ </section>
+
</chapter>
diff --git a/lib/common_test/doc/src/ct_run.xml b/lib/common_test/doc/src/ct_run.xml
index 1ab563d74f..9045646733 100644
--- a/lib/common_test/doc/src/ct_run.xml
+++ b/lib/common_test/doc/src/ct_run.xml
@@ -83,7 +83,7 @@
<title>Run tests from command line</title>
<pre>
ct_run [-dir TestDir1 TestDir2 .. TestDirN] |
- [-suite Suite1 Suite2 .. SuiteN
+ [[-dir TestDir] -suite Suite1 Suite2 .. SuiteN
[[-group Group1 Group2 .. GroupN] [-case Case1 Case2 .. CaseN]]]
[-step [config | keep_inactive]]
[-config ConfigFile1 ConfigFile2 .. ConfigFileN]
@@ -92,6 +92,7 @@
[-decrypt_key Key] | [-decrypt_file KeyFile]
[-label Label]
[-logdir LogDir]
+ [-logopts LogOpts]
[-silent_connections [ConnType1 ConnType2 .. ConnTypeN]]
[-stylesheet CSSFile]
[-cover CoverCfgFile]
@@ -117,6 +118,7 @@
[-decrypt_key Key] | [-decrypt_file KeyFile]
[-label Label]
[-logdir LogDir]
+ [-logopts LogOpts]
[-allow_user_terms]
[-silent_connections [ConnType1 ConnType2 .. ConnTypeN]]
[-stylesheet CSSFile]
@@ -138,10 +140,11 @@
<pre>
ct_run -vts [-browser Browser]
[-dir TestDir1 TestDir2 .. TestDirN] |
- [-suite Suite [[-group Group] [-case Case]]]
+ [[dir TestDir] -suite Suite [[-group Group] [-case Case]]]
[-config ConfigFile1 ConfigFile2 .. ConfigFileN]
[-userconfig CallbackModule1 ConfigString1 and CallbackModule2
ConfigString2 and .. and CallbackModuleN ConfigStringN]
+ [-logopts LogOpts]
[-decrypt_key Key] | [-decrypt_file KeyFile]
[-include InclDir1 InclDir2 .. InclDirN]
[-no_auto_compile]
diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml
index fef1222fcb..af96ef621f 100644
--- a/lib/common_test/doc/src/notes.xml
+++ b/lib/common_test/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,298 @@
<file>notes.xml</file>
</header>
+<section><title>Common_Test 1.5.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ An error in how comments are colored in the test suite
+ overview html log file has been corrected. As result, a
+ new framework callback function, format_comment/1, has
+ been introduced.</p>
+ <p>
+ Own Id: OTP-9237</p>
+ </item>
+ <item>
+ <p>
+ Automatically generated init- and end-configuration
+ functions for test case groups caused incorrect execution
+ order of test cases. This has been corrected.</p>
+ <p>
+ Own Id: OTP-9369</p>
+ </item>
+ <item>
+ <p>
+ If multiple directories were specified with the 'logdir'
+ flag/option, Common Test would crash. This has been fixed
+ so that an error is properly reported instead.</p>
+ <p>
+ Own Id: OTP-9370</p>
+ </item>
+ <item>
+ <p>
+ If ct:log/2 was called with bad arguments, this could
+ cause the Common Test IO handling process to crash. This
+ fault has been corrected.</p>
+ <p>
+ Own Id: OTP-9371 Aux Id: OTP-8933 </p>
+ </item>
+ <item>
+ <p>
+ A bug has been fixed that made Test Server call the
+ end_tc/3 framework function with an incorrect module name
+ as first argument.</p>
+ <p>
+ Own Id: OTP-9379 Aux Id: seq11863 </p>
+ </item>
+ <item>
+ <p>
+ If a timetrap timeout occured during execution of of a
+ function in a lib module (i.e. a function called directly
+ or indirectly from a test case), the Suite argument in
+ the end_tc/3 framework callback function would not
+ correctly contain the name of the test suite, but the lib
+ module. (This would only happen if the lib module was
+ compiled with ct.hrl included). This error has been
+ solved.</p>
+ <p>
+ Own Id: OTP-9398</p>
+ </item>
+ <item>
+ <p>
+ Corrections of the vts mode. It will now report errors
+ (about e.g. incorrect config files) instead of crashing
+ or hanging. Furthermore, the requirement that the test
+ directory name must have a "_test" suffix has been
+ removed. Also, a workaround has been implemented for the
+ limitation that the file browser (in many web browsers)
+ will only return the basic file name, not the full
+ directory path (which made it impossible to have config
+ files in other directories than the main test directory).</p>
+ <p>
+ Own Id: OTP-9429</p>
+ </item>
+ <item>
+ <p>
+ Add a proplist() type</p>
+ <p>
+ Recently I was adding specs to an API and found that
+ there is no canonical proplist() type defined. (Thanks to
+ Ryan Zezeski)</p>
+ <p>
+ Own Id: OTP-9499</p>
+ </item>
+ <item>
+ <p>
+ It is now possible to use the 'step' flag/option to run
+ the debugger for test suites that contain test case
+ groups. This previously caused Common Test to crash. If
+ 'step config' is specified, breakpoints are now also
+ automatically set on init_per_group and end_per_group.
+ Note that breakpoints are always set automatically on
+ test case functions and this is true also for grouped
+ cases.</p>
+ <p>
+ Own Id: OTP-9518 Aux Id: OTP-8933 </p>
+ </item>
+ <item>
+ <p>
+ The test index page was not refreshed at the start of
+ each test suite which made it impossible to follow test
+ execution by means of refreshing the browser window (no
+ links to follow). This has been fixed.</p>
+ <p>
+ Own Id: OTP-9520 Aux Id: OTP-8933 </p>
+ </item>
+ <item>
+ <p>
+ If a test suite would start with a test case group
+ defined without the init_per_group/2 and end_per_group/2
+ function, init_per_suite/1 would not execute initially
+ and logging of the test run would fail. This error has
+ been fixed.</p>
+ <p>
+ Own Id: OTP-9584</p>
+ </item>
+ <item>
+ <p>
+ The "Missing Suites" link from the top level index page
+ was incorrect and has been fixed.</p>
+ <p>
+ Own Id: OTP-9592</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Various corrections and updates to improve the handling
+ and reporting of errors.</p>
+ <p>
+ Own Id: OTP-8933</p>
+ </item>
+ <item>
+ <p>
+ The dir and suite start option can now be used in
+ combination. E.g. executing my_SUITE in directory
+ my_tests can either be specified as "ct_run -suite
+ my_tests/my_SUITE" or as "ct_run -dir my_tests -suite
+ my_SUITE". Furthermore, the specification:
+ ct:run_test([{suite,["./my_SUITE"]},{testcase,t1}]) is
+ now interpreted as
+ ct:run_test([{suite,"./my_SUITE"},{testcase,t1}]), i.e.
+ only testcase t1 in test suite my_SUITE - not all cases -
+ will be executed.</p>
+ <p>
+ Own Id: OTP-9155</p>
+ </item>
+ <item>
+ <p>
+ A new option, 'logopts', has been introduced, to make it
+ possible to modify some aspects of the logging behaviour
+ in Common Test (or Test Server). For example, whenever an
+ io printout is made, test_server adds newline (\n) to the
+ end of the output string. This may not always be a
+ preferred action and can therefore be disabled by means
+ of "ct_run ... -logopts no_nl" (or ct:run_test([...,
+ {logopts,[no_nl]}])). A new framework callback function,
+ get_logopts/0, has been introduced (see the ct_framework
+ module for details).</p>
+ <p>
+ Own Id: OTP-9372 Aux Id: OTP-9396 </p>
+ </item>
+ <item>
+ <p>
+ A new option, 'logopts', has been introduced, to make it
+ possible to modify some aspects of the logging behaviour
+ in Common Test (or Test Server). For example, if the html
+ version of the test suite source code should not be
+ generated during the test run (and consequently be
+ unavailable in the log file system), the feature may be
+ disabled by means of "ct_run ... -logopts no_src" (or
+ ct:run_test([..., {logopts,[no_src]}])). A new framework
+ callback function, get_logopts/0, has been introduced
+ (see the ct_framework module for details).</p>
+ <p>
+ Own Id: OTP-9396 Aux Id: seq11869, OTP-9372 </p>
+ </item>
+ <item>
+ <p>
+ CT Hooks can now be assigned a priority. The priority of
+ a CTH determines when it should execute in relation to
+ other CTHs. The CTH with the lowest priority will be
+ executed first, CTHs with equal priority will be executed
+ in the order which they were installed.</p>
+ <p>
+ Own Id: OTP-9445</p>
+ </item>
+ <item>
+ <p>
+ It is now possible to use a tuple {M,F,A}, or a fun, as
+ timetrap specification in the suite info function or test
+ case info functions. The function must return a valid
+ timeout value, as documented in the common_test man page
+ and in the User's Guide.</p>
+ <p>
+ Own Id: OTP-9501 Aux Id: seq11894 </p>
+ </item>
+ <item>
+ <p>
+ A new built-in common test hook has been added which
+ captures error_logger and SASL event and prints them in
+ the testcase log. To disable this (and any other built-in
+ hooks) pass 'enable_builtin_hooks false' to common test.</p>
+ <p>
+ Own Id: OTP-9543</p>
+ </item>
+ <item>
+ <p>
+ Common Test now has the possibility to have built-in
+ hooks which are started by default when any test is run.
+ To disable built-in hooks pass 'enable_builtin_hooks
+ false' to common test. See the common test hooks
+ documentation for more details.</p>
+ <p>
+ Own Id: OTP-9564</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Common_Test 1.5.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ It was previously not possible to use timetrap value
+ 'infinity' with ct:timetrap/1. This has been fixed.</p>
+ <p>
+ Own Id: OTP-9159</p>
+ </item>
+ <item>
+ <p>
+ The Common Test VTS mode has been updated to be able to
+ report test results of suites that include test case
+ groups (when it would previously crash).</p>
+ <p>
+ Own Id: OTP-9195</p>
+ </item>
+ <item>
+ <p>
+ Common Test now refreshes the very top level index.html
+ page at the start of each individual test in a test run,
+ so that progress of the ongoing test can be tracked by
+ following the link to its overview page.</p>
+ <p>
+ Own Id: OTP-9210 Aux Id: OTP-9054 </p>
+ </item>
+ <item>
+ <p>
+ A bug that made it impossible to cancel the previous
+ timetrap when calling ct:timetrap/1 has been corrected.</p>
+ <p>
+ Own Id: OTP-9233 Aux Id: OTP-9159 </p>
+ </item>
+ <item>
+ <p>
+ Fix bug which would make cth's to not be removed when out
+ of scope when adding a cth in suite/0 and crashing in
+ pre_init_per_suite.</p>
+ <p>
+ Own Id: OTP-9264</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ It is now possible to return a tuple {fail,Reason} from
+ init_per_testcase/2. The result is that the associated
+ test case gets logged as failed without ever executing.</p>
+ <p>
+ Own Id: OTP-9160 Aux Id: seq11502 </p>
+ </item>
+ <item>
+ <p>
+ Common Test now accepts, but ignores, empty test case
+ group specifications.</p>
+ <p>
+ Own Id: OTP-9161</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Common_Test 1.5.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/common_test/doc/src/run_test_chapter.xml b/lib/common_test/doc/src/run_test_chapter.xml
index e6fb85634f..57059f0ba2 100644
--- a/lib/common_test/doc/src/run_test_chapter.xml
+++ b/lib/common_test/doc/src/run_test_chapter.xml
@@ -128,6 +128,15 @@
<p><c>$ ct_run -suite $SYS1_TEST/setup_SUITE -case start stop</c></p>
<p><c>$ ct_run -suite $SYS1_TEST/setup_SUITE -group installation -case start stop</c></p>
+ <p>It is also possible to combine the <c>dir</c>, <c>suite</c> and <c>group/case</c> flags. E.g, to run
+ <c>x_SUITE</c> and <c>y_SUITE</c> in directory <c>testdir</c>:</p>
+
+ <p><c>$ ct_run -dir ./testdir -suite x_SUITE y_SUITE</c></p>
+
+ <p>This has the same effect as calling:</p>
+
+ <p><c>$ ct_run -suite ./testdir/x_SUITE ./testdir/y_SUITE</c></p>
+
<p>Other flags that may be used with <c>ct_run</c>:</p>
<list>
<item><c><![CDATA[-logdir <dir>]]></c>, specifies where the HTML log files are to be written.</item>
@@ -150,6 +159,8 @@
<seealso marker="event_handler_chapter#event_handling">event handlers</seealso> including start arguments.</item>
<item><c><![CDATA[-ct_hooks <ct_hooks>]]></c>, to install
<seealso marker="ct_hooks_chapter#installing">Common Test Hooks</seealso> including start arguments.</item>
+ <item><c><![CDATA[-enable_builtin_hooks <bool>]]></c>, to enable/disable
+ <seealso marker="ct_hooks_chapter#builtin_cths">Built-in Common Test Hooks</seealso>. Default is <c>true</c>.</item>
<item><c><![CDATA[-include]]></c>, specifies include directories (see above).</item>
<item><c><![CDATA[-no_auto_compile]]></c>, disables the automatic test suite compilation feature (see above).</item>
<item><c><![CDATA[-multiply_timetraps <n>]]></c>, extends <seealso marker="write_test_chapter#timetraps">timetrap
@@ -165,6 +176,8 @@
<item><c><![CDATA[-decrypt_file <key_file>]]></c>, points out a file containing a decryption key for
<seealso marker="config_file_chapter#encrypted_config_files">encrypted configuration files</seealso>.</item>
<item><c><![CDATA[-basic_html]]></c>, switches off html enhancements that might not be compatible with older browsers.</item>
+ <item><c><![CDATA[-logopts <opts>]]></c>, makes it possible to modify aspects of the logging behaviour, see
+ <seealso marker="run_test_chapter#logopts">Log options</seealso> below.</item>
</list>
<note><p>Directories passed to Common Test may have either relative or absolute paths.</p></note>
@@ -322,8 +335,9 @@
are to be executed by Common Test, and those functions only. If
the step option <c>config</c> is specified, breakpoints will
also be initially set on the configuration functions in the suite, i.e.
- <c>init_per_suite/1</c>, <c>end_per_suite/1</c>, <c>init_per_testcase/2</c>
- and <c>end_per_testcase/2</c>.</p>
+ <c>init_per_suite/1</c>, <c>end_per_suite/1</c>,
+ <c>init_per_group/2</c>, <c>end_per_group/2</c>,
+ <c>init_per_testcase/2</c> and <c>end_per_testcase/2</c>.</p>
<p>Common Test enables the Debugger auto attach feature, which means
that for every new interpreted test case function that starts to execute,
a new trace window will automatically pop up. (This is because each test
@@ -450,6 +464,8 @@
{ct_hooks, CTHModules}.
{ct_hooks, NodeRefs, CTHModules}.
+
+ {enable_builtin_hooks, Bool}.
</pre>
<p>Test terms:</p>
<pre>
@@ -488,7 +504,7 @@
LogDir = string()
EventHandlers = atom() | [atom()]
InitArgs = [term()]
- CTHModules = [CTHModule | {CTHModule, CTHInitArgs}]
+ CTHModules = [CTHModule | {CTHModule, CTHInitArgs} | {CTHModule, CTHInitArgs, CTHPriority}]
CTHModule = atom()
CTHInitArgs = term()
DirRef = DirAlias | Dir
@@ -631,7 +647,11 @@
<p>The minor log file contain full details of every single test
case, each one in a separate file. This way the files should
be easy to compare with previous test runs, even if the set of
- test cases change.</p>
+ test cases change. If SASL is running those logs will also be
+ printed there by the
+ <seealso marker="common_test:ct_hooks_chapter#builtin_cths">
+ cth_log_redirect built-in hook</seealso>.
+ </p>
<p>Which information goes where is user configurable via the
test server controller. Three threshold values determine what
@@ -644,6 +664,30 @@
to follow test progress simply by refreshing pages in the HTML browser.
Statistics totals are not presented until a test is complete however.</p>
+ <section>
+ <marker id="logopts"></marker>
+ <title>Log options</title>
+ <p>With the <c>logopts</c> start flag, it's possible to specify
+ options that modify some aspects of the logging behaviour.
+ Currently, the following options are available:</p>
+ <list>
+ <item><c>no_src</c></item>
+ <item><c>no_nl</c></item>
+ </list>
+ <p>With <c>no_src</c>, the html version of the test suite source
+ code will not be generated during the test run (and consequently
+ not be available in the log file system).</p>
+ <p>With <c>no_nl</c>, Common Test will not add a newline character
+ (\n) to the end of an output string that it receives from a call to e.g.
+ <c>io:format/2</c>, and which it prints to the test case log.</p>
+ <p>For example, if a test is started with:</p>
+ <p><c>$ ct_run -suite my_SUITE -logopts no_src</c></p>
+ <p>then printouts during the test made by successive calls to <c>io:format("x")</c>,
+ will appear in the test case log as:</p>
+ <p><c>xxx</c></p>
+ <p>instead of each <c>x</c> printed on a new line, which is the default behaviour.</p>
+ </section>
+
</section>
<section>
diff --git a/lib/common_test/doc/src/write_test_chapter.xml b/lib/common_test/doc/src/write_test_chapter.xml
index 723492d8f3..e35888e68f 100644
--- a/lib/common_test/doc/src/write_test_chapter.xml
+++ b/lib/common_test/doc/src/write_test_chapter.xml
@@ -167,12 +167,16 @@
returning <c>{fail,Reason}</c>, nor will it be able to save data with
<c>{save_config,Data}</c>.</p>
- <p>If <c>init_per_testcase</c> crashes, the test case itself is skipped
+ <p>If <c>init_per_testcase</c> crashes, the test case itself gets skipped
automatically (so called <em>auto skipped</em>). If <c>init_per_testcase</c>
- returns a <c>skip</c> tuple, also then will the test case be skipped (so
- called <em>user skipped</em>). In either event, the <c>end_per_testcase</c> is
- never called.
+ returns a tuple <c>{skip,Reason}</c>, also then the test case gets skipped
+ (so called <em>user skipped</em>). It is also possible, by returning a tuple
+ <c>{fail,Reason}</c> from <c>init_per_testcase</c>, to mark the test case
+ as failed without actually executing it.
</p>
+ <note><p>If <c>init_per_testcase</c> crashes, or returns <c>{skip,Reason}</c>
+ or <c>{fail,Reason}</c>, the <c>end_per_testcase</c> function is not called.
+ </p></note>
<p>If it is determined during execution of <c>end_per_testcase</c> that
the status of a successful test case should be changed to failed,
@@ -276,6 +280,8 @@
the timetrap time is exceeded, the test case fails with
reason <c>timetrap_timeout</c>. Note that <c>init_per_testcase</c>
and <c>end_per_testcase</c> are included in the timetrap time.
+ Please see the <seealso marker="write_test_chapter#timetraps">Timetrap</seealso>
+ section for more details.
</p>
</item>
<tag><em><c>userdata</c></em></tag>
@@ -695,8 +701,8 @@
</section>
<section>
- <title>Timetrap timeouts</title>
<marker id="timetraps"></marker>
+ <title>Timetrap timeouts</title>
<p>The default time limit for a test case is 30 minutes, unless a
<c>timetrap</c> is specified either by the suite info function
or a test case info function. The timetrap timeout value defined
@@ -719,6 +725,13 @@
multipled by <c>multiply_timetraps</c>, and possibly scaled up if
<c>scale_timetraps</c> is enabled, the function <c>ct:sleep/1</c>
may be called.</p>
+ <p>A function (<c>fun</c> or <c>MFA</c>) may be specified as timetrap value
+ in the suite- and test case info function, e.g:</p>
+ <p><c>{timetrap,{test_utils,get_timetrap_value,[?MODULE,system_start]}}</c></p>
+ <p>The function will be called initially by Common Test (before execution
+ of the suite or the test case) and must return a time value such as an
+ integer (millisec), or a <c>{SecMinOrHourTag,Time}</c> tuple. More
+ information can be found in the <c>common_test</c> reference manual.</p>
</section>
<section>
@@ -814,6 +827,3 @@
</list>
</section>
</chapter>
-
-
-
diff --git a/lib/common_test/include/ct.hrl b/lib/common_test/include/ct.hrl
index aa1cc832cf..5a77108e1a 100644
--- a/lib/common_test/include/ct.hrl
+++ b/lib/common_test/include/ct.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
%%
%% The 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,5 +18,4 @@
%%
-include_lib("test_server/include/test_server.hrl").
--compile({parse_transform,ct_line}).
diff --git a/lib/common_test/src/Makefile b/lib/common_test/src/Makefile
index 84b122b5e4..125aa828fb 100644
--- a/lib/common_test/src/Makefile
+++ b/lib/common_test/src/Makefile
@@ -40,7 +40,6 @@ RELSYSDIR = $(RELEASE_PATH)/lib/common_test-$(VSN)
# ----------------------------------------------------
MODULES= \
- ct_line \
ct \
ct_logs \
ct_framework \
@@ -69,9 +68,11 @@ MODULES= \
ct_config_xml \
ct_slave \
ct_hooks\
- ct_hooks_lock
+ ct_hooks_lock\
+ cth_log_redirect
TARGET_MODULES= $(MODULES:%=$(EBIN)/%)
+BEAM_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
ERL_FILES= $(MODULES:=.erl)
HRL_FILES = \
@@ -97,7 +98,7 @@ ERL_COMPILE_FLAGS += -pa ../ebin -I../include -I $(ERL_TOP)/lib/snmp/include/ \
# ----------------------------------------------------
TARGET_FILES = \
$(GEN_ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR)) \
- $(MODULES:%=$(EBIN)/%.$(EMULATOR)) \
+ $(BEAM_FILES) \
$(APP_TARGET) $(APPUP_TARGET)
APP_FILE= common_test.app
diff --git a/lib/common_test/src/common_test.app.src b/lib/common_test/src/common_test.app.src
index b42173f412..57606c01db 100644
--- a/lib/common_test/src/common_test.app.src
+++ b/lib/common_test/src/common_test.app.src
@@ -25,7 +25,6 @@
ct_framework,
ct_ftp,
ct_gen_conn,
- ct_line,
ct_logs,
ct_make,
ct_master,
diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl
index dfec2b7a67..69e15fa246 100644
--- a/lib/common_test/src/ct.erl
+++ b/lib/common_test/src/ct.erl
@@ -148,10 +148,10 @@ run(TestDirs) ->
%%% {auto_compile,Bool} | {multiply_timetraps,M} | {scale_timetraps,Bool} |
%%% {repeat,N} | {duration,DurTime} | {until,StopTime} |
%%% {force_stop,Bool} | {decrypt,DecryptKeyOrFile} |
-%%% {refresh_logs,LogDir} | {basic_html,Bool} |
-%%% {ct_hooks, CTHs}
+%%% {refresh_logs,LogDir} | {logopts,LogOpts} | {basic_html,Bool} |
+%%% {ct_hooks, CTHs} | {enable_builtin_hooks,Bool}
%%% TestDirs = [string()] | string()
-%%% Suites = [string()] | string()
+%%% Suites = [string()] | [atom()] | string() | atom()
%%% Cases = [atom()] | atom()
%%% Groups = [atom()] | atom()
%%% TestSpecs = [string()] | string()
@@ -177,6 +177,8 @@ run(TestDirs) ->
%%% DecryptKeyOrFile = {key,DecryptKey} | {file,DecryptFile}
%%% DecryptKey = string()
%%% DecryptFile = string()
+%%% LogOpts = [LogOpt]
+%%% LogOpt = no_nl | no_src
%%% CTHs = [CTHModule | {CTHModule, CTHInitArgs}]
%%% CTHModule = atom()
%%% CTHInitArgs = term()
@@ -861,6 +863,7 @@ remove_config(Callback, Config) ->
%%%
%%% @doc <p>Use this function to set a new timetrap for the running test case.</p>
timetrap(Time) ->
+ test_server:timetrap_cancel(),
test_server:timetrap(Time).
%%%-----------------------------------------------------------------
diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl
index 6b75937668..fc51aea7f3 100644
--- a/lib/common_test/src/ct_config.erl
+++ b/lib/common_test/src/ct_config.erl
@@ -204,9 +204,9 @@ get_config_file_list(Opts) ->
DefaultConfigs = process_default_configs(Opts),
CfgFiles =
if
- DefaultConfigs == []->
+ DefaultConfigs == [] ->
[];
- true->
+ true ->
[{?ct_config_txt, DefaultConfigs}]
end ++
process_user_configs(Opts, []),
@@ -240,12 +240,12 @@ read_config_files(Opts) ->
end,
ConfigFiles = case lists:keyfind(config, 1, Opts) of
- {config,ConfigLists}->
+ {config,ConfigLists} ->
lists:foldr(fun({Callback,Files}, Acc) ->
AddCallback(Callback,Files)
++ Acc
end,[],ConfigLists);
- false->
+ false ->
[]
end,
read_config_files_int(ConfigFiles, fun store_config/3).
@@ -255,7 +255,9 @@ read_config_files_int([{Callback, File}|Files], FunToSave) ->
{ok, Config} ->
FunToSave(Config, Callback, File),
read_config_files_int(Files, FunToSave);
- {error, ErrorName, ErrorDetail}->
+ {error, {ErrorName, ErrorDetail}} ->
+ {user_error, {ErrorName, File, ErrorDetail}};
+ {error, ErrorName, ErrorDetail} ->
{user_error, {ErrorName, File, ErrorDetail}}
end;
read_config_files_int([], _FunToSave) ->
@@ -283,7 +285,7 @@ rewrite_config(Config, Callback, File) ->
config=File,_='_'}),
Updater = fun({Key, Value}) ->
case keyfindall(Key, #ct_conf.key, OldRows) of
- []->
+ [] ->
ets:insert(?attr_table,
#ct_conf{key=Key,
value=Value,
@@ -453,9 +455,9 @@ update_conf(Name, NewConfig) ->
reload_conf(KeyOrName) ->
case lookup_handler_for_config(KeyOrName) of
- []->
+ [] ->
undefined;
- HandlerList->
+ HandlerList ->
HandlerList2 = lists:usort(HandlerList),
read_config_files_int(HandlerList2, fun rewrite_config/3),
get_config(KeyOrName)
@@ -711,13 +713,13 @@ random_bytes_1(N, Acc) -> random_bytes_1(N-1, [random:uniform(255)|Acc]).
check_callback_load(Callback) ->
case code:is_loaded(Callback) of
- {file, _Filename}->
+ {file, _Filename} ->
check_exports(Callback);
- false->
+ false ->
case code:load_file(Callback) of
- {module, Callback}->
+ {module, Callback} ->
check_exports(Callback);
- {error, Error}->
+ {error, Error} ->
{error, Error}
end
end.
@@ -745,14 +747,14 @@ check_config_files(Configs) ->
end,
Files)
end;
- {error, Why}->
+ {error, Why} ->
{error, {callback, {Callback,Why}}}
end;
({Callback, []}) ->
case check_callback_load(Callback) of
- {ok, Callback}->
+ {ok, Callback} ->
Callback:check_parameter([]);
- {error, Why}->
+ {error, Why} ->
{error, {callback, {Callback,Why}}}
end
end,
@@ -773,15 +775,15 @@ prepare_user_configs([], Acc, _) ->
prepare_config_list(Args) ->
ConfigFiles = case lists:keysearch(ct_config, 1, Args) of
- {value,{ct_config,Files}}->
+ {value,{ct_config,Files}} ->
[{?ct_config_txt,[filename:absname(F) || F <- Files]}];
- false->
+ false ->
[]
end,
UserConfigs = case lists:keysearch(userconfig, 1, Args) of
- {value,{userconfig,UserConfigFiles}}->
+ {value,{userconfig,UserConfigFiles}} ->
prepare_user_configs(UserConfigFiles, [], new);
- false->
+ false ->
[]
end,
ConfigFiles ++ UserConfigs.
diff --git a/lib/common_test/src/ct_config_plain.erl b/lib/common_test/src/ct_config_plain.erl
index 3fbc8af9fb..6698332379 100644
--- a/lib/common_test/src/ct_config_plain.erl
+++ b/lib/common_test/src/ct_config_plain.erl
@@ -29,7 +29,7 @@ read_config(ConfigFile) ->
{ok,Config} ->
{ok, Config};
{error,enoent} ->
- {error, config_file_error, enoent};
+ {error,{config_file_error,file:format_error(enoent)}};
{error,Reason} ->
Key =
case application:get_env(common_test, decrypt) of
@@ -45,23 +45,27 @@ read_config(ConfigFile) ->
end,
case Key of
{error,no_crypt_file} ->
- {error, config_file_error, Reason};
+ {error,{config_file_error,
+ lists:flatten(
+ io_lib:format("~s",[file:format_error(Reason)]))}};
{error,CryptError} ->
- {error, decrypt_file_error, CryptError};
+ {error,{decrypt_file_error,CryptError}};
_ when is_list(Key) ->
- case ct_config:decrypt_config_file(ConfigFile, undefined, {key,Key}) of
+ case ct_config:decrypt_config_file(ConfigFile,
+ undefined,
+ {key,Key}) of
{ok,CfgBin} ->
case read_config_terms(CfgBin) of
{error,ReadFail} ->
- {error, config_file_error, ReadFail};
+ {error,{config_file_error,ReadFail}};
Config ->
- {ok, Config}
+ {ok,Config}
end;
{error,DecryptFail} ->
- {error, decrypt_config_error, DecryptFail}
+ {error,{decrypt_config_error,DecryptFail}}
end;
_ ->
- {error, bad_decrypt_key, Key}
+ {error,{bad_decrypt_key,Key}}
end
end.
@@ -69,9 +73,9 @@ read_config(ConfigFile) ->
check_parameter(File)->
case filelib:is_file(File) of
true->
- {ok, {file, File}};
+ {ok,{file,File}};
false->
- {error, {nofile, File}}
+ {error,{nofile,File}}
end.
read_config_terms(Bin) when is_binary(Bin) ->
diff --git a/lib/common_test/src/ct_config_xml.erl b/lib/common_test/src/ct_config_xml.erl
index 8a6e75e635..794174e663 100644
--- a/lib/common_test/src/ct_config_xml.erl
+++ b/lib/common_test/src/ct_config_xml.erl
@@ -27,30 +27,30 @@
% read config file
read_config(ConfigFile) ->
case catch do_read_xml_config(ConfigFile) of
- {ok, Config}->
- {ok, Config};
- {error, Error, ErroneousString}->
- {error, Error, ErroneousString}
+ {ok,Config} ->
+ {ok,Config};
+ Error = {error,_} ->
+ Error
end.
% check file exists
-check_parameter(File)->
+check_parameter(File) ->
case filelib:is_file(File) of
- true->
- {ok, {file, File}};
- false->
- {error, {nofile, File}}
+ true ->
+ {ok,{file,File}};
+ false ->
+ {error,{nofile,File}}
end.
% actual reading of the config
-do_read_xml_config(ConfigFile)->
+do_read_xml_config(ConfigFile) ->
case catch xmerl_sax_parser:file(ConfigFile,
- [{event_fun, fun event/3},
- {event_state, []}]) of
- {ok, EntityList, _}->
- {ok, lists:reverse(transform_entity_list(EntityList))};
- Oops->
- {error, parsing_failed, Oops}
+ [{event_fun,fun event/3},
+ {event_state,[]}]) of
+ {ok,EntityList,_} ->
+ {ok,lists:reverse(transform_entity_list(EntityList))};
+ Oops ->
+ {error,{parsing_failed,Oops}}
end.
% event callback for xmerl_sax_parser
@@ -92,18 +92,18 @@ tag(_El, State) ->
State.
% transform of the ugly deeply nested entity list to the key-value "tree"
-transform_entity_list(EntityList)->
+transform_entity_list(EntityList) ->
lists:map(fun transform_entity/1, EntityList).
% transform entity from {list(), list()} to {atom(), term()}
transform_entity({Tag, [Value|Rest]}) when
- is_tuple(Value)->
+ is_tuple(Value) ->
{list_to_atom(Tag), transform_entity_list(lists:reverse([Value|Rest]))};
-transform_entity({Tag, String})->
+transform_entity({Tag, String}) ->
case list_to_term(String) of
- {ok, Value}->
+ {ok, Value} ->
{list_to_atom(Tag), Value};
- Error->
+ Error ->
throw(Error)
end.
@@ -111,8 +111,8 @@ transform_entity({Tag, String})->
list_to_term(String) ->
{ok, T, _} = erl_scan:string(String++"."),
case catch erl_parse:parse_term(T) of
- {ok, Term} ->
- {ok, Term};
+ {ok,Term} ->
+ {ok,Term};
Error ->
- {error, Error, String}
+ {error,{Error,String}}
end.
diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl
index 38a2aa53ac..482c5242ce 100644
--- a/lib/common_test/src/ct_framework.erl
+++ b/lib/common_test/src/ct_framework.erl
@@ -24,10 +24,10 @@
-module(ct_framework).
--export([init_tc/3, end_tc/4, get_suite/2, report/2, warn/1]).
--export([error_notification/4]).
+-export([init_tc/3, end_tc/3, end_tc/4, get_suite/2, get_all_cases/1]).
+-export([report/2, warn/1, error_notification/4]).
--export([overview_html_header/1]).
+-export([get_logopts/0, format_comment/1, overview_html_header/1]).
-export([error_in_suite/1, ct_init_per_group/2, ct_end_per_group/2]).
@@ -116,7 +116,7 @@ init_tc1(Mod,Func,[Config0],DoInit) when is_list(Config0) ->
Config = lists:keydelete(watchdog,1,Config1),
if Func /= init_per_suite, DoInit /= true ->
ok;
- true ->
+ true ->
%% delete all default values used in previous suite
ct_config:delete_default_config(suite),
%% release all name -> key bindings (once per suite)
@@ -133,7 +133,7 @@ init_tc1(Mod,Func,[Config0],DoInit) when is_list(Config0) ->
ct_config:delete_default_config(testcase),
case add_defaults(Mod,Func,TestCaseInfo,DoInit) of
Error = {suite0_failed,_} ->
- ct_logs:init_tc(),
+ ct_logs:init_tc(false),
FuncSpec = group_or_func(Func,Config0),
ct_event:notify(#event{name=tc_start,
node=node(),
@@ -143,7 +143,7 @@ init_tc1(Mod,Func,[Config0],DoInit) when is_list(Config0) ->
{SuiteInfo,MergeResult} ->
case MergeResult of
{error,Reason} when DoInit == false ->
- ct_logs:init_tc(),
+ ct_logs:init_tc(false),
FuncSpec = group_or_func(Func,Config0),
ct_event:notify(#event{name=tc_start,
node=node(),
@@ -194,19 +194,24 @@ init_tc2(Mod,Func,SuiteInfo,MergeResult,Config,DoInit) ->
Conns ->
ct_util:silence_connections(Conns)
end,
-
- ct_logs:init_tc(),
+ if Func /= init_per_suite, DoInit /= true ->
+ ct_logs:init_tc(false);
+ true ->
+ ct_logs:init_tc(true)
+ end,
FuncSpec = group_or_func(Func,Config),
ct_event:notify(#event{name=tc_start,
node=node(),
data={Mod,FuncSpec}}),
- case configure(MergedInfo1,MergedInfo1,SuiteInfo,{Func,DoInit},Config) of
+ case catch configure(MergedInfo1,MergedInfo1,SuiteInfo,{Func,DoInit},Config) of
{suite0_failed,Reason} ->
ct_util:set_testdata({curr_tc,{Mod,{suite0_failed,{require,Reason}}}}),
{skip,{require_failed_in_suite0,Reason}};
{error,Reason} ->
{auto_skip,{require_failed,Reason}};
+ {'EXIT',Reason} ->
+ {auto_skip,Reason};
{ok, FinalConfig} ->
case MergeResult of
{error,Reason} ->
@@ -240,28 +245,45 @@ add_defaults(Mod,Func,FuncInfo,DoInit) ->
case (catch Mod:suite()) of
{'EXIT',{undef,_}} ->
SuiteInfo = merge_with_suite_defaults(Mod,[]),
- case add_defaults1(Mod,Func,FuncInfo,SuiteInfo,DoInit) of
+ SuiteInfoNoCTH = [I || I <- SuiteInfo, element(1,I) =/= ct_hooks],
+ case add_defaults1(Mod,Func,FuncInfo,SuiteInfoNoCTH,DoInit) of
Error = {error,_} -> {SuiteInfo,Error};
MergedInfo -> {SuiteInfo,MergedInfo}
end;
- {'EXIT',Reason} ->
+ {'EXIT',Reason} ->
+ ErrStr = io_lib:format("~n*** ERROR *** "
+ "~w:suite/0 failed: ~p~n",
+ [Mod,Reason]),
+ io:format(ErrStr, []),
+ io:format(user, ErrStr, []),
{suite0_failed,{exited,Reason}};
SuiteInfo when is_list(SuiteInfo) ->
case lists:all(fun(E) when is_tuple(E) -> true;
(_) -> false
end, SuiteInfo) of
true ->
- SuiteInfoNoCTH =
- lists:keydelete(ct_hooks,1,SuiteInfo),
- SuiteInfo1 = merge_with_suite_defaults(Mod,SuiteInfoNoCTH),
- case add_defaults1(Mod,Func,FuncInfo,SuiteInfo1,DoInit) of
+ SuiteInfo1 = merge_with_suite_defaults(Mod,SuiteInfo),
+ SuiteInfoNoCTH = [I || I <- SuiteInfo1,
+ element(1,I) =/= ct_hooks],
+ case add_defaults1(Mod,Func,FuncInfo,
+ SuiteInfoNoCTH,DoInit) of
Error = {error,_} -> {SuiteInfo1,Error};
MergedInfo -> {SuiteInfo1,MergedInfo}
end;
false ->
+ ErrStr = io_lib:format("~n*** ERROR *** "
+ "Invalid return value from "
+ "~w:suite/0: ~p~n", [Mod,SuiteInfo]),
+ io:format(ErrStr, []),
+ io:format(user, ErrStr, []),
{suite0_failed,bad_return_value}
end;
- _ ->
+ SuiteInfo ->
+ ErrStr = io_lib:format("~n*** ERROR *** "
+ "Invalid return value from "
+ "~w:suite/0: ~p~n", [Mod,SuiteInfo]),
+ io:format(ErrStr, []),
+ io:format(user, ErrStr, []),
{suite0_failed,bad_return_value}
end.
@@ -434,6 +456,9 @@ try_set_default(Name,Key,Info,Where) ->
%%%
%%% @doc Test server framework callback, called by the test_server
%%% when a test case is finished.
+end_tc(Mod, Fun, Args) ->
+ %% Have to keep end_tc/3 for backwards compatibility issues
+ end_tc(Mod, Fun, Args, '$end_tc_dummy').
end_tc(?MODULE,error_in_suite,_, _) -> % bad start!
ok;
end_tc(Mod,Func,{TCPid,Result,[Args]}, Return) when is_pid(TCPid) ->
@@ -446,7 +471,6 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) ->
{value,{watchdog,Dog}} -> test_server:timetrap_cancel(Dog);
false -> ok
end,
-
%% save the testcase process pid so that it can be used
%% to look up the attached trace window later
case ct_util:get_testdata(interpret) of
@@ -456,7 +480,6 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) ->
_ ->
ok
end,
-
ct_util:delete_testdata(comment),
ct_util:delete_suite_data(last_saved_config),
FuncSpec =
@@ -490,9 +513,9 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) ->
case ct_hooks:end_tc(
Mod, FuncSpec, Args, Result, Return) of
'$ct_no_change' ->
- {FinalResult = ok,Result};
- FinalResult ->
- {FinalResult,FinalResult}
+ {ok,Result};
+ FinalResult1 ->
+ {FinalResult1,FinalResult1}
end,
% send sync notification so that event handlers may print
% in the log file before it gets closed
@@ -633,7 +656,7 @@ error_notification(Mod,Func,_Args,{Error,Loc}) ->
[{?MODULE,error_in_suite}] ->
io:format(user, "Error in suite detected: ~s", [ErrStr]);
- unknown ->
+ R when R == unknown; R == undefined ->
io:format(user, "Error detected: ~s", [ErrStr]);
%% if a function specified by all/0 does not exist, we
@@ -734,7 +757,7 @@ get_suite(Mod, Group={conf,Props,_Init,TCs,_End}) ->
%% (and only) test case so we can report Error properly
[{?MODULE,error_in_suite,[[Error]]}];
[] ->
- {error,{invalid_group_spec,Name}};
+ [];
ConfTests ->
case lists:member(skipped, Props) of
true ->
@@ -762,25 +785,40 @@ get_suite(Mod, Name) ->
%%%-----------------------------------------------------------------
+get_all_cases(Suite) ->
+ case get_suite(Suite, all) of
+ [{?MODULE,error_in_suite,[[{error,_}=Error]]}] ->
+ Error;
+ [{?MODULE,error_in_suite,[[Error]]}] ->
+ {error,Error};
+ Tests ->
+ Cases = get_all_cases1(Suite, Tests),
+ lists:reverse(
+ lists:foldl(fun(TC, TCs) ->
+ case lists:member(TC, TCs) of
+ true -> TCs;
+ false -> [TC | TCs]
+ end
+ end, [], Cases))
+ end.
+
+get_all_cases1(Suite, [{conf,_Props,_Init,GrTests,_End} | Tests]) ->
+ get_all_cases1(Suite, GrTests) ++ get_all_cases1(Suite, Tests);
+
+get_all_cases1(Suite, [Test | Tests]) when is_atom(Test) ->
+ [{Suite,Test} | get_all_cases1(Suite, Tests)];
+
+get_all_cases1(Suite, [Test | Tests]) ->
+ [Test | get_all_cases1(Suite, Tests)];
+
+get_all_cases1(_, []) ->
+ [].
+
+%%%-----------------------------------------------------------------
+
find_groups(Mod, Name, TCs, GroupDefs) ->
Found = find(Mod, Name, TCs, GroupDefs, [], GroupDefs, false),
- Trimmed = trim(Found),
- %% I cannot find a reason to why this function is called,
- %% It deletes any group which is referenced in any other
- %% group. i.e.
- %% groups() ->
- %% [{test, [], [testcase1]},
- %% {testcases, [], [{group, test}]}].
- %% Would be changed to
- %% groups() ->
- %% [{testcases, [], [testcase1]}].
- %% instead of what I believe is correct:
- %% groups() ->
- %% [{test, [], [testcase1]},
- %% {testcases, [], [testcase1]}].
- %% Have to double check with peppe
- delete_subs(Trimmed, Trimmed),
- Trimmed.
+ trim(Found).
find(Mod, all, _TCs, [{Name,Props,Tests} | Gs], Known, Defs, _)
when is_atom(Name), is_list(Props), is_list(Tests) ->
@@ -989,15 +1027,20 @@ make_conf(Mod, Name, Props, TestSpec) ->
_ ->
ok
end,
- {InitConf,EndConf} =
+ {InitConf,EndConf,ExtraProps} =
case erlang:function_exported(Mod,init_per_group,2) of
true ->
- {{Mod,init_per_group},{Mod,end_per_group}};
+ {{Mod,init_per_group},{Mod,end_per_group},[]};
false ->
+ ct_logs:log("TEST INFO", "init_per_group/2 and "
+ "end_per_group/2 missing for group "
+ "~p in ~p, using default.",
+ [Name,Mod]),
{{?MODULE,ct_init_per_group},
- {?MODULE,ct_end_per_group}}
+ {?MODULE,ct_end_per_group},
+ [{suite,Mod}]}
end,
- {conf,[{name,Name}|Props],InitConf,TestSpec,EndConf}.
+ {conf,[{name,Name}|Props++ExtraProps],InitConf,TestSpec,EndConf}.
%%%-----------------------------------------------------------------
@@ -1170,12 +1213,16 @@ error_in_suite(Config) ->
%% if the group config functions are missing in the suite,
%% use these instead
ct_init_per_group(GroupName, Config) ->
- ct_logs:log("WARNING", "init_per_group/2 for ~w missing in suite, using default.",
+ ct:comment(io_lib:format("start of ~p", [GroupName])),
+ ct_logs:log("TEST INFO", "init_per_group/2 for ~w missing "
+ "in suite, using default.",
[GroupName]),
Config.
ct_end_per_group(GroupName, _) ->
- ct_logs:log("WARNING", "end_per_group/2 for ~w missing in suite, using default.",
+ ct:comment(io_lib:format("end of ~p", [GroupName])),
+ ct_logs:log("TEST INFO", "end_per_group/2 for ~w missing "
+ "in suite, using default.",
[GroupName]),
ok.
@@ -1184,6 +1231,13 @@ ct_end_per_group(GroupName, _) ->
%%% @spec report(What,Data) -> ok
report(What,Data) ->
case What of
+ loginfo ->
+ %% logfiles and direcories have been created for a test and the
+ %% top level test index page needs to be refreshed
+ TestName = filename:basename(proplists:get_value(topdir, Data), ".logs"),
+ RunDir = proplists:get_value(rundir, Data),
+ ct_logs:make_all_suites_index({TestName,RunDir}),
+ ok;
tests_start ->
case ct_util:get_testdata(cover) of
undefined ->
@@ -1244,12 +1298,20 @@ report(What,Data) ->
ok;
{end_per_group,_} ->
ok;
+ {ct_init_per_group,_} ->
+ ok;
+ {ct_end_per_group,_} ->
+ ok;
{_,ok} ->
add_to_stats(ok);
{_,{skipped,{failed,{_,init_per_testcase,_}}}} ->
add_to_stats(auto_skipped);
{_,{skipped,{require_failed,_}}} ->
add_to_stats(auto_skipped);
+ {_,{skipped,{timetrap_error,_}}} ->
+ add_to_stats(auto_skipped);
+ {_,{skipped,{invalid_time_format,_}}} ->
+ add_to_stats(auto_skipped);
{_,{skipped,_}} ->
add_to_stats(user_skipped);
{_,{SkipOrFail,_Reason}} ->
@@ -1334,6 +1396,21 @@ add_data_dir(File,Config) when is_list(File) ->
end.
%%%-----------------------------------------------------------------
+%%% @spec get_logopts() -> [LogOpt]
+get_logopts() ->
+ case ct_util:get_testdata(logopts) of
+ undefined ->
+ [];
+ LogOpts ->
+ LogOpts
+ end.
+
+%%%-----------------------------------------------------------------
+%%% @spec format_comment(Comment) -> HtmlComment
+format_comment(Comment) ->
+ "<font color=\"green\">" ++ Comment ++ "</font>".
+
+%%%-----------------------------------------------------------------
%%% @spec overview_html_header(TestName) -> Header
overview_html_header(TestName) ->
TestName1 = lists:flatten(io_lib:format("~p", [TestName])),
diff --git a/lib/common_test/src/ct_hooks.erl b/lib/common_test/src/ct_hooks.erl
index 5eddefffce..ffafc582cf 100644
--- a/lib/common_test/src/ct_hooks.erl
+++ b/lib/common_test/src/ct_hooks.erl
@@ -31,11 +31,17 @@
-export([on_tc_skip/2]).
-export([on_tc_fail/2]).
--type proplist() :: [{atom(),term()}].
-
%% If you change this, remember to update ct_util:look -> stop clause as well.
-define(config_name, ct_hooks).
+%% All of the hooks which are to be started by default. Remove by issuing
+%% -enable_builtin_hooks false to when starting common test.
+-define(BUILTIN_HOOKS,[#ct_hook_config{ module = cth_log_redirect,
+ opts = [],
+ prio = ctfirst }]).
+
+-record(ct_hook_config, {id, module, prio, scope, opts = [], state = []}).
+
%% -------------------------------------------------------------------------
%% API Functions
%% -------------------------------------------------------------------------
@@ -44,7 +50,7 @@
-spec init(State :: term()) -> ok |
{error, Reason :: term()}.
init(Opts) ->
- call([{Hook, call_id, undefined} || Hook <- get_new_hooks(Opts)],
+ call(get_new_hooks(Opts, undefined) ++ get_builtin_hooks(Opts),
ok, init, []).
@@ -52,14 +58,15 @@ init(Opts) ->
-spec terminate(Hooks :: term()) ->
ok.
terminate(Hooks) ->
- call([{HookId, fun call_terminate/3} || {HookId,_,_} <- Hooks],
+ call([{HookId, fun call_terminate/3}
+ || #ct_hook_config{id = HookId} <- Hooks],
ct_hooks_terminate_dummy, terminate, Hooks),
ok.
%% @doc Called as each test case is started. This includes all configuration
%% tests.
-spec init_tc(Mod :: atom(), Func :: atom(), Args :: list()) ->
- NewConfig :: proplist() |
+ NewConfig :: proplists:proplist() |
{skip, Reason :: term()} |
{auto_skip, Reason :: term()} |
{fail, Reason :: term()}.
@@ -68,11 +75,11 @@ init_tc(ct_framework, _Func, Args) ->
init_tc(Mod, init_per_suite, Config) ->
Info = try proplists:get_value(ct_hooks, Mod:suite(),[]) of
List when is_list(List) ->
- [{ct_hooks,List}];
+ [{?config_name,List}];
CTHook when is_atom(CTHook) ->
- [{ct_hooks,[CTHook]}]
+ [{?config_name,[CTHook]}]
catch error:undef ->
- [{ct_hooks,[]}]
+ [{?config_name,[]}]
end,
call(fun call_generic/3, Config ++ Info, [pre_init_per_suite, Mod]);
init_tc(Mod, end_per_suite, Config) ->
@@ -92,7 +99,7 @@ init_tc(_Mod, TC, Config) ->
Args :: list(),
Result :: term(),
Resturn :: term()) ->
- NewConfig :: proplist() |
+ NewConfig :: proplists:proplist() |
{skip, Reason :: term()} |
{auto_skip, Reason :: term()} |
{fail, Reason :: term()} |
@@ -122,45 +129,57 @@ end_tc(_Mod, TC, Config, Result, _Return) ->
call(fun call_generic/3, Result, [post_end_per_testcase, TC, Config],
'$ct_no_change').
-on_tc_skip(How, {_Suite, Case, Reason}) ->
- call(fun call_cleanup/3, {How, Reason}, [on_tc_skip, Case]).
+on_tc_skip(How, {Suite, Case, Reason}) ->
+ call(fun call_cleanup/3, {How, Reason}, [on_tc_skip, Suite, Case]).
-on_tc_fail(_How, {_Suite, Case, Reason}) ->
- call(fun call_cleanup/3, Reason, [on_tc_fail, Case]).
+on_tc_fail(_How, {Suite, Case, Reason}) ->
+ call(fun call_cleanup/3, Reason, [on_tc_fail, Suite, Case]).
%% -------------------------------------------------------------------------
%% Internal Functions
%% -------------------------------------------------------------------------
-call_id(Mod, Config, Meta) when is_atom(Mod) ->
- call_id({Mod, []}, Config, Meta);
-call_id({Mod, Opts}, Config, Scope) ->
+call_id(#ct_hook_config{ module = Mod, opts = Opts} = Hook, Config, Scope) ->
Id = catch_apply(Mod,id,[Opts], make_ref()),
- {Config, {Id, scope(Scope), {Mod, {Id,Opts}}}}.
+ {Config, Hook#ct_hook_config{ id = Id, scope = scope(Scope)}}.
-call_init({Mod,{Id,Opts}},Config,_Meta) ->
- NewState = Mod:init(Id, Opts),
- {Config, {Mod, NewState}}.
-
-call_terminate({Mod, State}, _, _) ->
+call_init(#ct_hook_config{ module = Mod, opts = Opts, id = Id, prio = P} = Hook,
+ Config,_Meta) ->
+ case Mod:init(Id, Opts) of
+ {ok, NewState} when P =:= undefined ->
+ {Config, Hook#ct_hook_config{ state = NewState, prio = 0 } };
+ {ok, NewState} ->
+ {Config, Hook#ct_hook_config{ state = NewState } };
+ {ok, NewState, Prio} when P =:= undefined ->
+ %% Only set prio if not already set when installing hook
+ {Config, Hook#ct_hook_config{ state = NewState, prio = Prio } };
+ {ok, NewState, _} ->
+ {Config, Hook#ct_hook_config{ state = NewState } };
+ NewState -> %% Keep for backward compatability reasons
+ {Config, Hook#ct_hook_config{ state = NewState } }
+ end.
+
+call_terminate(#ct_hook_config{ module = Mod, state = State} = Hook, _, _) ->
catch_apply(Mod,terminate,[State], ok),
- {[],{Mod,State}}.
+ {[],Hook}.
-call_cleanup({Mod, State}, Reason, [Function | Args]) ->
+call_cleanup(#ct_hook_config{ module = Mod, state = State} = Hook,
+ Reason, [Function, _Suite | Args]) ->
NewState = catch_apply(Mod,Function, Args ++ [Reason, State],
State),
- {Reason, {Mod, NewState}}.
+ {Reason, Hook#ct_hook_config{ state = NewState } }.
-call_generic({Mod, State}, Value, [Function | Args]) ->
+call_generic(#ct_hook_config{ module = Mod, state = State} = Hook,
+ Value, [Function | Args]) ->
{NewValue, NewState} = catch_apply(Mod, Function, Args ++ [Value, State],
{Value,State}),
- {NewValue, {Mod, NewState}}.
+ {NewValue, Hook#ct_hook_config{ state = NewState } }.
%% Generic call function
call(Fun, Config, Meta) ->
maybe_lock(),
Hooks = get_hooks(),
- Res = call([{HookId,Fun} || {HookId,_, _} <- Hooks] ++
- get_new_hooks(Config, Fun),
+ Res = call(get_new_hooks(Config, Fun) ++
+ [{HookId,Fun} || #ct_hook_config{id = HookId} <- Hooks],
remove(?config_name,Config), Meta, Hooks),
maybe_unlock(),
Res.
@@ -173,19 +192,20 @@ call(Fun, Config, Meta, NoChangeRet) when is_function(Fun) ->
call([{Hook, call_id, NextFun} | Rest], Config, Meta, Hooks) ->
try
- {Config, {NewId, _, _} = NewHook} = call_id(Hook, Config, Meta),
+ {Config, #ct_hook_config{ id = NewId } = NewHook} =
+ call_id(Hook, Config, Meta),
{NewHooks, NewRest} =
- case lists:keyfind(NewId, 1, Hooks) of
+ case lists:keyfind(NewId, #ct_hook_config.id, Hooks) of
false when NextFun =:= undefined ->
{Hooks ++ [NewHook],
- [{NewId, fun call_init/3} | Rest]};
+ [{NewId, call_init} | Rest]};
ExistingHook when is_tuple(ExistingHook) ->
{Hooks, Rest};
_ ->
{Hooks ++ [NewHook],
- [{NewId, fun call_init/3},{NewId,NextFun} | Rest]}
+ [{NewId, call_init}, {NewId,NextFun} | Rest]}
end,
- call(NewRest, Config, Meta, NewHooks)
+ call(resort(NewRest,NewHooks), Config, Meta, NewHooks)
catch Error:Reason ->
Trace = erlang:get_stacktrace(),
ct_logs:log("Suite Hook","Failed to start a CTH: ~p:~p",
@@ -193,13 +213,16 @@ call([{Hook, call_id, NextFun} | Rest], Config, Meta, Hooks) ->
call([], {fail,"Failed to start CTH"
", see the CT Log for details"}, Meta, Hooks)
end;
+call([{HookId, call_init} | Rest], Config, Meta, Hooks) ->
+ call([{HookId, fun call_init/3} | Rest], Config, Meta, Hooks);
call([{HookId, Fun} | Rest], Config, Meta, Hooks) ->
try
- {_,Scope,ModState} = lists:keyfind(HookId, 1, Hooks),
- {NewConf, NewHookInfo} = Fun(ModState, Config, Meta),
+ Hook = lists:keyfind(HookId, #ct_hook_config.id, Hooks),
+ {NewConf, NewHook} = Fun(Hook, Config, Meta),
NewCalls = get_new_hooks(NewConf, Fun),
- NewHooks = lists:keyreplace(HookId, 1, Hooks, {HookId, Scope, NewHookInfo}),
- call(NewCalls ++ Rest, remove(?config_name, NewConf), Meta,
+ NewHooks = lists:keyreplace(HookId, #ct_hook_config.id, Hooks, NewHook),
+ call(resort(NewCalls ++ Rest,NewHooks), %% Resort if call_init changed prio
+ remove(?config_name, NewConf), Meta,
terminate_if_scope_ends(HookId, Meta, NewHooks))
catch throw:{error_in_cth_call,Reason} ->
call(Rest, {fail, Reason}, Meta,
@@ -229,22 +252,34 @@ scope([post_init_per_suite, SuiteName|_]) ->
scope(init) ->
none.
+terminate_if_scope_ends(HookId, [on_tc_skip,_Suite,{end_per_group,Name}],
+ Hooks) ->
+ terminate_if_scope_ends(HookId, [post_end_per_group, Name], Hooks);
+terminate_if_scope_ends(HookId, [on_tc_skip,Suite,end_per_suite], Hooks) ->
+ terminate_if_scope_ends(HookId, [post_end_per_suite, Suite], Hooks);
terminate_if_scope_ends(HookId, [Function,Tag|T], Hooks) when T =/= [] ->
terminate_if_scope_ends(HookId,[Function,Tag],Hooks);
terminate_if_scope_ends(HookId, Function, Hooks) ->
- case lists:keyfind(HookId, 1, Hooks) of
- {HookId, Function, _ModState} = Hook ->
+ case lists:keyfind(HookId, #ct_hook_config.id, Hooks) of
+ #ct_hook_config{ id = HookId, scope = Function} = Hook ->
terminate([Hook]),
- lists:keydelete(HookId, 1, Hooks);
+ lists:keydelete(HookId, #ct_hook_config.id, Hooks);
_ ->
Hooks
end.
%% Fetch hook functions
get_new_hooks(Config, Fun) ->
- lists:foldl(fun(NewHook, Acc) ->
- [{NewHook, call_id, Fun} | Acc]
- end, [], get_new_hooks(Config)).
+ lists:map(fun(NewHook) when is_atom(NewHook) ->
+ {#ct_hook_config{ module = NewHook }, call_id, Fun};
+ ({NewHook,Opts}) ->
+ {#ct_hook_config{ module = NewHook,
+ opts = Opts}, call_id, Fun};
+ ({NewHook,Opts,Prio}) ->
+ {#ct_hook_config{ module = NewHook,
+ opts = Opts,
+ prio = Prio }, call_id, Fun}
+ end, get_new_hooks(Config)).
get_new_hooks(Config) when is_list(Config) ->
lists:flatmap(fun({?config_name, HookConfigs}) ->
@@ -255,11 +290,63 @@ get_new_hooks(Config) when is_list(Config) ->
get_new_hooks(_Config) ->
[].
+get_builtin_hooks(Opts) ->
+ case proplists:get_value(enable_builtin_hooks,Opts) of
+ false ->
+ [];
+ _Else ->
+ [{HookConf, call_id, undefined} || HookConf <- ?BUILTIN_HOOKS]
+ end.
+
save_suite_data_async(Hooks) ->
ct_util:save_suite_data_async(?config_name, Hooks).
get_hooks() ->
- ct_util:read_suite_data(?config_name).
+ lists:keysort(#ct_hook_config.prio,ct_util:read_suite_data(?config_name)).
+
+%% Sort all calls in this order:
+%% call_id < call_init < ctfirst < Priority 1 < .. < Priority N < ctlast
+%% If Hook Priority is equal, check when it has been installed and
+%% sort on that instead.
+resort(Calls, Hooks) ->
+ lists:sort(
+ fun({_,_,_},_) ->
+ true;
+ (_,{_,_,_}) ->
+ false;
+ ({_,call_init},_) ->
+ true;
+ (_,{_,call_init}) ->
+ false;
+ ({Id1,_},{Id2,_}) ->
+ P1 = (lists:keyfind(Id1, #ct_hook_config.id, Hooks))#ct_hook_config.prio,
+ P2 = (lists:keyfind(Id2, #ct_hook_config.id, Hooks))#ct_hook_config.prio,
+ if
+ P1 == P2 ->
+ %% If priorities are equal, we check the position in the
+ %% hooks list
+ pos(Id1,Hooks) < pos(Id2,Hooks);
+ P1 == ctfirst ->
+ true;
+ P2 == ctfirst ->
+ false;
+ P1 == ctlast ->
+ false;
+ P2 == ctlast ->
+ true;
+ true ->
+ P1 < P2
+ end
+ end,Calls).
+
+pos(Id,Hooks) ->
+ pos(Id,Hooks,0).
+pos(Id,[#ct_hook_config{ id = Id}|_],Num) ->
+ Num;
+pos(Id,[_|Rest],Num) ->
+ pos(Id,Rest,Num+1).
+
+
catch_apply(M,F,A, Default) ->
try
@@ -267,7 +354,7 @@ catch_apply(M,F,A, Default) ->
catch error:Reason ->
case erlang:get_stacktrace() of
%% Return the default if it was the CTH module which did not have the function.
- [{M,F,A}|_] when Reason == undef ->
+ [{M,F,A,_}|_] when Reason == undef ->
Default;
Trace ->
ct_logs:log("Suite Hook","Call to CTH failed: ~p:~p",
diff --git a/lib/common_test/src/ct_line.erl b/lib/common_test/src/ct_line.erl
deleted file mode 100644
index 4af9da5463..0000000000
--- a/lib/common_test/src/ct_line.erl
+++ /dev/null
@@ -1,266 +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%
-%%
-
-%%% @doc Parse transform for inserting line numbers
-
--module(ct_line).
-
--record(vars, {module, % atom() Module name
- vsn, % atom()
-
- init_info=[], % [{M,F,A,C,L}]
-
- function, % atom()
- arity, % int()
- clause, % int()
- lines, % [int()]
- depth, % int()
- is_guard=false % boolean
- }).
-
--export([parse_transform/2,
- line/1]).
-
-line(LOC={{Mod,Func},_Line}) ->
- Lines = case get(test_server_loc) of
- [{{Mod,Func},_}|Ls] ->
- Ls;
- Ls when is_list(Ls) ->
- case length(Ls) of
- 10 ->
- [_|T]=lists:reverse(Ls),
- lists:reverse(T);
- _ ->
- Ls
- end;
- _ ->
- []
- end,
- put(test_server_loc,[LOC|Lines]).
-
-parse_transform(Forms, _Options) ->
- transform(Forms, _Options).
-
-%% forms(Fs) -> lists:map(fun (F) -> form(F) end, Fs).
-
-transform(Forms, _Options)->
- Vars0 = #vars{},
- {ok, MungedForms, _Vars} = transform(Forms, [], Vars0),
- MungedForms.
-
-
-transform([Form|Forms], MungedForms, Vars) ->
- case munge(Form, Vars) of
- ignore ->
- transform(Forms, MungedForms, Vars);
- {MungedForm, Vars2} ->
- transform(Forms, [MungedForm|MungedForms], Vars2)
- end;
-transform([], MungedForms, Vars) ->
- {ok, lists:reverse(MungedForms), Vars}.
-
-%% This code traverses the abstract code, stored as the abstract_code
-%% chunk in the BEAM file, as described in absform(3) for Erlang/OTP R8B
-%% (Vsn=abstract_v2).
-%% The abstract format after preprocessing differs slightly from the abstract
-%% format given eg using epp:parse_form, this has been noted in comments.
-munge(Form={attribute,_,module,Module}, Vars) ->
- Vars2 = Vars#vars{module=Module},
- {Form, Vars2};
-
-munge({function,0,module_info,_Arity,_Clauses}, _Vars) ->
- ignore; % module_info will be added again when the forms are recompiled
-munge({function,Line,Function,Arity,Clauses}, Vars) ->
- Vars2 = Vars#vars{function=Function,
- arity=Arity,
- clause=1,
- lines=[],
- depth=1},
- {MungedClauses, Vars3} = munge_clauses(Clauses, Vars2, []),
- {{function,Line,Function,Arity,MungedClauses}, Vars3};
-munge(Form, Vars) -> % attributes
- {Form, Vars}.
-
-munge_clauses([{clause,Line,Pattern,Guards,Body}|Clauses], Vars, MClauses) ->
- {MungedGuards, _Vars} = munge_exprs(Guards, Vars#vars{is_guard=true},[]),
-
- case Vars#vars.depth of
- 1 -> % function clause
- {MungedBody, Vars2} = munge_body(Body, Vars#vars{depth=2}, []),
- ClauseInfo = {Vars2#vars.module,
- Vars2#vars.function,
- Vars2#vars.arity,
- Vars2#vars.clause,
- length(Vars2#vars.lines)},
- InitInfo = [ClauseInfo | Vars2#vars.init_info],
- Vars3 = Vars2#vars{init_info=InitInfo,
- clause=(Vars2#vars.clause)+1,
- lines=[],
- depth=1},
- munge_clauses(Clauses, Vars3,
- [{clause,Line,Pattern,MungedGuards,MungedBody}|
- MClauses]);
-
- 2 -> % receive-, case- or if clause
- {MungedBody, Vars2} = munge_body(Body, Vars, []),
- munge_clauses(Clauses, Vars2,
- [{clause,Line,Pattern,MungedGuards,MungedBody}|
- MClauses])
- end;
-munge_clauses([], Vars, MungedClauses) ->
- {lists:reverse(MungedClauses), Vars}.
-
-munge_body([Expr|Body], Vars, MungedBody) ->
- %% Here is the place to add a call to cover:bump/6!
- Line = element(2, Expr),
- Lines = Vars#vars.lines,
- case lists:member(Line,Lines) of
- true -> % already a bump at this line!
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- munge_body(Body, Vars2, [MungedExpr|MungedBody]);
- false ->
- Bump = {call, 0, {remote,0,{atom,0,?MODULE},{atom,0,line}},
- [{tuple,0,[{tuple,0,[{atom,0,Vars#vars.module},
- {atom, 0, Vars#vars.function}]},
- {integer, 0, Line}]}]},
- Lines2 = [Line|Lines],
-
- {MungedExpr, Vars2} = munge_expr(Expr, Vars#vars{lines=Lines2}),
- munge_body(Body, Vars2, [MungedExpr,Bump|MungedBody])
- end;
-munge_body([], Vars, MungedBody) ->
- {lists:reverse(MungedBody), Vars}.
-
-munge_expr({match,Line,ExprL,ExprR}, Vars) ->
- {MungedExprL, Vars2} = munge_expr(ExprL, Vars),
- {MungedExprR, Vars3} = munge_expr(ExprR, Vars2),
- {{match,Line,MungedExprL,MungedExprR}, Vars3};
-munge_expr({tuple,Line,Exprs}, Vars) ->
- {MungedExprs, Vars2} = munge_exprs(Exprs, Vars, []),
- {{tuple,Line,MungedExprs}, Vars2};
-munge_expr({record,Line,Expr,Exprs}, Vars) ->
- %% Only for Vsn=raw_abstract_v1
- {MungedExprName, Vars2} = munge_expr(Expr, Vars),
- {MungedExprFields, Vars3} = munge_exprs(Exprs, Vars2, []),
- {{record,Line,MungedExprName,MungedExprFields}, Vars3};
-munge_expr({record_field,Line,ExprL,ExprR}, Vars) ->
- %% Only for Vsn=raw_abstract_v1
- {MungedExprL, Vars2} = munge_expr(ExprL, Vars),
- {MungedExprR, Vars3} = munge_expr(ExprR, Vars2),
- {{record_field,Line,MungedExprL,MungedExprR}, Vars3};
-munge_expr({cons,Line,ExprH,ExprT}, Vars) ->
- {MungedExprH, Vars2} = munge_expr(ExprH, Vars),
- {MungedExprT, Vars3} = munge_expr(ExprT, Vars2),
- {{cons,Line,MungedExprH,MungedExprT}, Vars3};
-munge_expr({op,Line,Op,ExprL,ExprR}, Vars) ->
- {MungedExprL, Vars2} = munge_expr(ExprL, Vars),
- {MungedExprR, Vars3} = munge_expr(ExprR, Vars2),
- {{op,Line,Op,MungedExprL,MungedExprR}, Vars3};
-munge_expr({op,Line,Op,Expr}, Vars) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- {{op,Line,Op,MungedExpr}, Vars2};
-munge_expr({'catch',Line,Expr}, Vars) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- {{'catch',Line,MungedExpr}, Vars2};
-munge_expr({call,Line1,{remote,Line2,ExprM,ExprF},Exprs},
- Vars) when Vars#vars.is_guard==false->
- {MungedExprM, Vars2} = munge_expr(ExprM, Vars),
- {MungedExprF, Vars3} = munge_expr(ExprF, Vars2),
- {MungedExprs, Vars4} = munge_exprs(Exprs, Vars3, []),
- {{call,Line1,{remote,Line2,MungedExprM,MungedExprF},MungedExprs}, Vars4};
-munge_expr({call,Line1,{remote,_Line2,_ExprM,ExprF},Exprs},
- Vars) when Vars#vars.is_guard==true ->
- %% Difference in abstract format after preprocessing: BIF calls in guards
- %% are translated to {remote,...} (which is not allowed as source form)
- %% NOT NECESSARY FOR Vsn=raw_abstract_v1
- munge_expr({call,Line1,ExprF,Exprs}, Vars);
-munge_expr({call,Line,Expr,Exprs}, Vars) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- {MungedExprs, Vars3} = munge_exprs(Exprs, Vars2, []),
- {{call,Line,MungedExpr,MungedExprs}, Vars3};
-munge_expr({lc,Line,Expr,LC}, Vars) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- {MungedLC, Vars3} = munge_lc(LC, Vars2, []),
- {{lc,Line,MungedExpr,MungedLC}, Vars3};
-munge_expr({block,Line,Body}, Vars) ->
- {MungedBody, Vars2} = munge_body(Body, Vars, []),
- {{block,Line,MungedBody}, Vars2};
-munge_expr({'if',Line,Clauses}, Vars) ->
- {MungedClauses,Vars2} = munge_clauses(Clauses, Vars, []),
- {{'if',Line,MungedClauses}, Vars2};
-munge_expr({'case',Line,Expr,Clauses}, Vars) ->
- {MungedExpr,Vars2} = munge_expr(Expr,Vars),
- {MungedClauses,Vars3} = munge_clauses(Clauses, Vars2, []),
- {{'case',Line,MungedExpr,MungedClauses}, Vars3};
-munge_expr({'receive',Line,Clauses}, Vars) ->
- {MungedClauses,Vars2} = munge_clauses(Clauses, Vars, []),
- {{'receive',Line,MungedClauses}, Vars2};
-munge_expr({'receive',Line,Clauses,Expr,Body}, Vars) ->
- {MungedClauses,Vars2} = munge_clauses(Clauses, Vars, []),
- {MungedExpr, Vars3} = munge_expr(Expr, Vars2),
- {MungedBody, Vars4} = munge_body(Body, Vars3, []),
- {{'receive',Line,MungedClauses,MungedExpr,MungedBody}, Vars4};
-munge_expr({'try',Line,Exprs,Clauses,CatchClauses}, Vars) ->
- {MungedExprs, Vars1} = munge_exprs(Exprs, Vars, []),
- {MungedClauses, Vars2} = munge_clauses(Clauses, Vars1, []),
- {MungedCatchClauses, Vars3} = munge_clauses(CatchClauses, Vars2, []),
- {{'try',Line,MungedExprs,MungedClauses,MungedCatchClauses}, Vars3};
-%% Difference in abstract format after preprocessing: Funs get an extra
-%% element Extra.
-%% NOT NECESSARY FOR Vsn=raw_abstract_v1
-munge_expr({'fun',Line,{function,Name,Arity},_Extra}, Vars) ->
- {{'fun',Line,{function,Name,Arity}}, Vars};
-munge_expr({'fun',Line,{clauses,Clauses},_Extra}, Vars) ->
- {MungedClauses,Vars2}=munge_clauses(Clauses, Vars, []),
- {{'fun',Line,{clauses,MungedClauses}}, Vars2};
-munge_expr({'fun',Line,{clauses,Clauses}}, Vars) ->
- %% Only for Vsn=raw_abstract_v1
- {MungedClauses,Vars2}=munge_clauses(Clauses, Vars, []),
- {{'fun',Line,{clauses,MungedClauses}}, Vars2};
-munge_expr(Form, Vars) -> % var|char|integer|float|string|atom|nil|bin|eof
- {Form, Vars}.
-
-munge_exprs([Expr|Exprs], Vars, MungedExprs) when Vars#vars.is_guard==true,
- is_list(Expr) ->
- {MungedExpr, _Vars} = munge_exprs(Expr, Vars, []),
- munge_exprs(Exprs, Vars, [MungedExpr|MungedExprs]);
-munge_exprs([Expr|Exprs], Vars, MungedExprs) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- munge_exprs(Exprs, Vars2, [MungedExpr|MungedExprs]);
-munge_exprs([], Vars, MungedExprs) ->
- {lists:reverse(MungedExprs), Vars}.
-
-munge_lc([{generate,Line,Pattern,Expr}|LC], Vars, MungedLC) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- munge_lc(LC, Vars2, [{generate,Line,Pattern,MungedExpr}|MungedLC]);
-munge_lc([Expr|LC], Vars, MungedLC) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- munge_lc(LC, Vars2, [MungedExpr|MungedLC]);
-munge_lc([], Vars, MungedLC) ->
- {lists:reverse(MungedLC), Vars}.
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl
index f8ace73cbf..c1523509a5 100644
--- a/lib/common_test/src/ct_logs.erl
+++ b/lib/common_test/src/ct_logs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
%%
%% The 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,7 +28,7 @@
-module(ct_logs).
--export([init/1,close/1,init_tc/0,end_tc/1]).
+-export([init/1,close/2,init_tc/1,end_tc/1]).
-export([get_log_dir/0,log/3,start_log/1,cont_log/2,end_log/0]).
-export([set_stylesheet/2,clear_stylesheet/1]).
-export([add_external_logs/1,add_link/3]).
@@ -36,7 +36,7 @@
-export([make_all_suites_index/1,make_all_runs_index/1]).
%% Logging stuff directly from testcase
--export([tc_log/3,tc_print/3,tc_pal/3,
+-export([tc_log/3,tc_print/3,tc_pal/3,ct_log/3,
basic_html/0]).
%% Simulate logger process for use without ct environment running
@@ -97,11 +97,11 @@ logdir_node_prefix() ->
logdir_prefix()++"."++atom_to_list(node()).
%%%-----------------------------------------------------------------
-%%% @spec close(How) -> ok
+%%% @spec close(Info, StartDir) -> ok
%%%
%%% @doc Create index pages with test results and close the CT Log
%%% (tool-internal use only).
-close(How) ->
+close(Info, StartDir) ->
make_last_run_index(),
ct_event:notify(#event{name=stop_logging,node=node(),data=[]}),
@@ -118,20 +118,35 @@ close(How) ->
ok
end,
- if How == clean ->
+ if Info == clean ->
case cleanup() of
ok ->
ok;
Error ->
io:format("Warning! Cleanup failed: ~p~n", [Error])
- end;
+ end,
+ make_all_suites_index(stop),
+ make_all_runs_index(stop);
true ->
- file:set_cwd("..")
- end,
-
- make_all_suites_index(stop),
- make_all_runs_index(stop),
-
+ file:set_cwd(".."),
+ make_all_suites_index(stop),
+ make_all_runs_index(stop),
+ case ct_util:get_profile_data(browser, StartDir) of
+ undefined ->
+ ok;
+ BrowserData ->
+ case {proplists:get_value(prog, BrowserData),
+ proplists:get_value(args, BrowserData),
+ proplists:get_value(page, BrowserData)} of
+ {Prog,Args,Page} when is_list(Args),
+ is_list(Page) ->
+ URL = "\"file://" ++ ?abs(Page) ++ "\"",
+ ct_util:open_url(Prog, Args, URL);
+ _ ->
+ ok
+ end
+ end
+ end,
ok.
%%%-----------------------------------------------------------------
@@ -182,15 +197,14 @@ cast(Msg) ->
?MODULE ! Msg
end.
-
%%%-----------------------------------------------------------------
-%%% @spec init_tc() -> ok
+%%% @spec init_tc(RefreshLog) -> ok
%%%
%%% @doc Test case initiation (tool-internal use only).
%%%
%%% <p>This function is called by ct_framework:init_tc/3</p>
-init_tc() ->
- call({init_tc,self(),group_leader()}),
+init_tc(RefreshLog) ->
+ call({init_tc,self(),group_leader(),RefreshLog}),
ok.
%%%-----------------------------------------------------------------
@@ -360,6 +374,23 @@ tc_pal(Category,Format,Args) ->
ok.
+%%%-----------------------------------------------------------------
+%%% @spec tc_pal(Category,Format,Args) -> ok
+%%% Category = atom()
+%%% Format = string()
+%%% Args = list()
+%%%
+%%% @doc Print and log to the ct framework log
+%%%
+%%% <p>This function is called by internal ct functions to
+%%% force logging to the ct framework log</p>
+ct_log(Category,Format,Args) ->
+ cast({ct_log,[{div_header(Category),[]},
+ {Format,Args},
+ {div_footer(),[]}]}),
+ ok.
+
+
%%%=================================================================
%%% Internal functions
int_header() ->
@@ -427,8 +458,8 @@ logger(Parent,Mode) ->
file:make_dir(Dir),
ct_event:notify(#event{name=start_logging,node=node(),
data=?abs(Dir)}),
- make_all_suites_index(start),
make_all_runs_index(start),
+ make_all_suites_index(start),
case Mode of
interactive -> interactive_link();
_ -> ok
@@ -469,8 +500,8 @@ logger_loop(State) ->
[Str,Args]),
%% stop the testcase, we need
%% to see the fault
- exit(Pid,logging_failed),
- ok;
+ exit(Pid,{log_printout_error,Str,Args}),
+ [];
IoStr when IoList == [] ->
[IoStr];
IoStr ->
@@ -490,10 +521,15 @@ logger_loop(State) ->
[begin io:format(Fd,Str,Args),io:nl(Fd) end || {Str,Args} <- List],
logger_loop(State#logger_state{tc_groupleaders=TCGLs})
end;
- {{init_tc,TCPid,GL},From} ->
+ {{init_tc,TCPid,GL,RefreshLog},From} ->
print_style(GL, State#logger_state.stylesheet),
set_evmgr_gl(GL),
TCGLs = add_tc_gl(TCPid,GL,State),
+ if not RefreshLog ->
+ ok;
+ true ->
+ make_last_run_index(State#logger_state.start_time)
+ end,
return(From,ok),
logger_loop(State#logger_state{tc_groupleaders=TCGLs});
{{end_tc,TCPid},From} ->
@@ -516,7 +552,12 @@ logger_loop(State) ->
{clear_stylesheet,_} when State#logger_state.stylesheet == undefined ->
logger_loop(State);
{clear_stylesheet,_} ->
- logger_loop(State#logger_state{stylesheet=undefined});
+ logger_loop(State#logger_state{stylesheet=undefined});
+ {ct_log, List} ->
+ Fd = State#logger_state.ct_log_fd,
+ [begin io:format(Fd,Str,Args),io:nl(Fd) end ||
+ {Str,Args} <- List],
+ logger_loop(State);
stop ->
io:format(State#logger_state.ct_log_fd,
int_header()++int_footer(),
@@ -796,24 +837,30 @@ make_one_index_entry(SuiteName, LogDir, Label, All, Missing) ->
{Succ,Fail,UserSkip,AutoSkip} ->
NotBuilt = not_built(SuiteName, LogDir, All, Missing),
NewResult = make_one_index_entry1(SuiteName, LogDir, Label, Succ, Fail,
- UserSkip, AutoSkip, NotBuilt, All),
+ UserSkip, AutoSkip, NotBuilt, All,
+ normal),
{NewResult,Succ,Fail,UserSkip,AutoSkip,NotBuilt};
error ->
error
end.
make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip,
- NotBuilt, All) ->
+ NotBuilt, All, Mode) ->
LogFile = filename:join(Link, ?suitelog_name ++ ".html"),
- CrashDumpName = SuiteName ++ "_erl_crash.dump",
- CrashDumpLink =
- case filelib:is_file(CrashDumpName) of
- true ->
- ["&nbsp;<A HREF=\"", CrashDumpName,
- "\">(CrashDump)</A>"];
- false ->
- ""
- end,
+ CrashDumpLink = case Mode of
+ cached ->
+ "";
+ normal ->
+ CrashDumpName = SuiteName ++ "_erl_crash.dump",
+ case filelib:is_file(CrashDumpName) of
+ true ->
+ ["&nbsp;<A HREF=\"", CrashDumpName,
+ "\">(CrashDump)</A>"];
+ false ->
+ ""
+ end
+ end,
+ CtRunDir = filename:dirname(filename:dirname(Link)),
{Lbl,Timestamp,Node,AllInfo} =
case All of
{true,OldRuns} ->
@@ -823,7 +870,6 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip,
_ -> NodeOrDate
end,
N = ["<TD ALIGN=right><FONT SIZE=-1>",Node1,"</FONT></TD>\n"],
- CtRunDir = filename:dirname(filename:dirname(Link)),
L = ["<TD ALIGN=center><FONT SIZE=-1><B>",Label,"</FONT></B></TD>\n"],
T = ["<TD><FONT SIZE=-1>",timestamp(CtRunDir),"</FONT></TD>\n"],
CtLogFile = filename:join(CtRunDir,?ct_log_name),
@@ -842,7 +888,7 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip,
if NotBuilt == 0 ->
["<TD ALIGN=right>",integer_to_list(NotBuilt),"</TD>\n"];
true ->
- ["<TD ALIGN=right><A HREF=\"",?ct_log_name,"\">",
+ ["<TD ALIGN=right><A HREF=\"",filename:join(CtRunDir,?ct_log_name),"\">",
integer_to_list(NotBuilt),"</A></TD>\n"]
end,
FailStr =
@@ -975,9 +1021,13 @@ index_header(Label, StartTime) ->
"<th>Missing<br>Suites</th>\n"
"\n"]].
+
all_suites_index_header() ->
{ok,Cwd} = file:get_cwd(),
- LogDir = filename:basename(Cwd),
+ all_suites_index_header(Cwd).
+
+all_suites_index_header(IndexDir) ->
+ LogDir = filename:basename(IndexDir),
AllRuns = "All test runs in \"" ++ LogDir ++ "\"",
[header("Test Results") |
["<CENTER>\n",
@@ -1414,15 +1464,72 @@ timestamp(Dir) ->
[S,Min,H,D,M,Y] = [list_to_integer(N) || N <- lists:sublist(TsR,6)],
format_time({{Y,M,D},{H,Min,S}}).
-make_all_suites_index(When) ->
+%% ----------------------------- NOTE --------------------------------------
+%% The top level index file is generated based on the file contents under
+%% logdir. This takes place initially when the test run starts (When = start)
+%% and an update takes place at the end of the test run, or when the user
+%% requests an explicit refresh (When = refresh).
+%% The index file needs to be updated also at the start of each individual
+%% test (in order for the user to be able to track test progress by refreshing
+%% the browser). Since it would be too expensive to generate a new file from
+%% scratch every time (by reading the data from disk), a copy of the dir tree
+%% is cached as a result of the first index file creation. This copy is then
+%% used for all top level index page updates that occur during the test run.
+%% This means that any changes to the dir tree under logdir during the test
+%% run will not show until after the final refresh.
+%% -------------------------------------------------------------------------
+
+%% Creates the top level index file. When == start | refresh.
+%% A copy of the dir tree under logdir is cached as a result.
+make_all_suites_index(When) when is_atom(When) ->
AbsIndexName = ?abs(?index_name),
notify_and_lock_file(AbsIndexName),
LogDirs = filelib:wildcard(logdir_prefix()++".*/*"++?logdir_ext),
- Sorted = sort_logdirs(LogDirs,[]),
- Result = make_all_suites_index1(When,Sorted),
+ Sorted = sort_logdirs(LogDirs, []),
+ Result = make_all_suites_index1(When, AbsIndexName, Sorted),
notify_and_unlock_file(AbsIndexName),
- Result.
-
+ Result;
+
+%% This updates the top level index file using cached data from
+%% the initial index file creation.
+make_all_suites_index(NewTestData = {_TestName,DirName}) ->
+ %% AllLogDirs = [{TestName,Label,Missing,{LastLogDir,Summary},OldDirs}|...]
+ {AbsIndexName,LogDirData} = ct_util:get_testdata(test_index),
+
+ CtRunDirPos = length(filename:split(AbsIndexName)),
+ CtRunDir = filename:join(lists:sublist(filename:split(DirName),
+ CtRunDirPos)),
+
+ Label = case read_totals_file(filename:join(CtRunDir, ?totals_name)) of
+ {_,"-",_,_} -> "...";
+ {_,Lbl,_,_} -> Lbl;
+ _ -> "..."
+ end,
+ notify_and_lock_file(AbsIndexName),
+ Result =
+ case catch make_all_suites_ix_cached(AbsIndexName,
+ NewTestData,
+ Label,
+ LogDirData) of
+ {'EXIT',Reason} ->
+ io:put_chars("CRASHED while updating " ++ AbsIndexName ++ "!\n"),
+ io:format("~p~n", [Reason]),
+ {error,Reason};
+ {error,Reason} ->
+ io:put_chars("FAILED while updating " ++ AbsIndexName ++ "\n"),
+ io:format("~p~n", [Reason]),
+ {error,Reason};
+ ok ->
+ ok;
+ Err ->
+ io:format("Unknown internal error while updating ~s. "
+ "Please report.\n(Err: ~p, ID: 1)",
+ [AbsIndexName,Err]),
+ {error, Err}
+ end,
+ notify_and_unlock_file(AbsIndexName),
+ Result.
+
sort_logdirs([Dir|Dirs],Groups) ->
TestName = filename:rootname(filename:basename(Dir)),
case filelib:wildcard(filename:join(Dir,"run.*")) of
@@ -1448,13 +1555,12 @@ sort_each_group([{Test,IxDirs}|Groups]) ->
sort_each_group([]) ->
[].
-make_all_suites_index1(When,AllSuitesLogDirs) ->
+make_all_suites_index1(When, AbsIndexName, AllLogDirs) ->
IndexName = ?index_name,
- AbsIndexName = ?abs(IndexName),
if When == start -> ok;
true -> io:put_chars("Updating " ++ AbsIndexName ++ "... ")
end,
- case catch make_all_suites_index2(IndexName,AllSuitesLogDirs) of
+ case catch make_all_suites_index2(IndexName, AllLogDirs) of
{'EXIT', Reason} ->
io:put_chars("CRASHED while updating " ++ AbsIndexName ++ "!\n"),
io:format("~p~n", [Reason]),
@@ -1463,11 +1569,16 @@ make_all_suites_index1(When,AllSuitesLogDirs) ->
io:put_chars("FAILED while updating " ++ AbsIndexName ++ "\n"),
io:format("~p~n", [Reason]),
{error, Reason};
- ok ->
- if When == start -> ok;
- true -> io:put_chars("done\n")
- end,
- ok;
+ {ok,CacheData} ->
+ case When of
+ start ->
+ ct_util:set_testdata_async({test_index,{AbsIndexName,
+ CacheData}}),
+ ok;
+ _ ->
+ io:put_chars("done\n"),
+ ok
+ end;
Err ->
io:format("Unknown internal error while updating ~s. "
"Please report.\n(Err: ~p, ID: 1)",
@@ -1475,56 +1586,124 @@ make_all_suites_index1(When,AllSuitesLogDirs) ->
{error, Err}
end.
-make_all_suites_index2(IndexName,AllSuitesLogDirs) ->
- {ok,Index0,_Totals} = make_all_suites_index3(AllSuitesLogDirs,
- all_suites_index_header(),
- 0, 0, 0, 0, 0, []),
+make_all_suites_index2(IndexName, AllTestLogDirs) ->
+ {ok,Index0,_Totals,CacheData} =
+ make_all_suites_index3(AllTestLogDirs,
+ all_suites_index_header(),
+ 0, 0, 0, 0, 0, [], []),
Index = [Index0|index_footer()],
case force_write_file(IndexName, Index) of
ok ->
- ok;
+ {ok,CacheData};
{error, Reason} ->
{error,{index_write_error, Reason}}
end.
-make_all_suites_index3([{SuiteName,[LastLogDir|OldDirs]}|Rest],
+make_all_suites_index3([{TestName,[LastLogDir|OldDirs]}|Rest],
Result, TotSucc, TotFail, UserSkip, AutoSkip, TotNotBuilt,
- Labels) ->
+ Labels, CacheData) ->
[EntryDir|_] = filename:split(LastLogDir),
Missing =
- case file:read_file(filename:join(EntryDir,?missing_suites_info)) of
+ case file:read_file(filename:join(EntryDir, ?missing_suites_info)) of
{ok,Bin} -> binary_to_term(Bin);
_ -> []
end,
{Label,Labels1} =
case proplists:get_value(EntryDir, Labels) of
undefined ->
- case read_totals_file(filename:join(EntryDir,?totals_name)) of
+ case read_totals_file(filename:join(EntryDir, ?totals_name)) of
{_,Lbl,_,_} -> {Lbl,[{EntryDir,Lbl}|Labels]};
_ -> {"-",[{EntryDir,"-"}|Labels]}
end;
Lbl ->
{Lbl,Labels}
end,
- case make_one_index_entry(SuiteName, LastLogDir, Label, {true,OldDirs}, Missing) of
+ case make_one_index_entry(TestName, LastLogDir, Label, {true,OldDirs}, Missing) of
{Result1,Succ,Fail,USkip,ASkip,NotBuilt} ->
%% for backwards compatibility
AutoSkip1 = case catch AutoSkip+ASkip of
{'EXIT',_} -> undefined;
Res -> Res
end,
+ IxEntry = {TestName,Label,Missing,
+ {LastLogDir,{Succ,Fail,USkip,ASkip}},OldDirs},
make_all_suites_index3(Rest, [Result|Result1], TotSucc+Succ,
TotFail+Fail, UserSkip+USkip, AutoSkip1,
- TotNotBuilt+NotBuilt,Labels1);
+ TotNotBuilt+NotBuilt, Labels1,
+ [IxEntry|CacheData]);
error ->
+ IxEntry = {TestName,Label,Missing,{LastLogDir,error},OldDirs},
make_all_suites_index3(Rest, Result, TotSucc, TotFail,
- UserSkip, AutoSkip, TotNotBuilt,Labels1)
+ UserSkip, AutoSkip, TotNotBuilt, Labels1,
+ [IxEntry|CacheData])
end;
make_all_suites_index3([], Result, TotSucc, TotFail, UserSkip, AutoSkip,
- TotNotBuilt,_) ->
+ TotNotBuilt, _, CacheData) ->
{ok, [Result|total_row(TotSucc, TotFail, UserSkip, AutoSkip, TotNotBuilt,true)],
- {TotSucc,TotFail,UserSkip,AutoSkip,TotNotBuilt}}.
+ {TotSucc,TotFail,UserSkip,AutoSkip,TotNotBuilt}, lists:reverse(CacheData)}.
+
+make_all_suites_ix_cached(AbsIndexName, NewTestData, Label, AllTestLogDirs) ->
+ AllTestLogDirs1 = insert_new_test_data(NewTestData, Label, AllTestLogDirs),
+ IndexDir = filename:dirname(AbsIndexName),
+ Index0 = make_all_suites_ix_cached1(AllTestLogDirs1,
+ all_suites_index_header(IndexDir),
+ 0, 0, 0, 0, 0),
+ Index = [Index0|index_footer()],
+ case force_write_file(AbsIndexName, Index) of
+ ok ->
+ ok;
+ {error, Reason} ->
+ {error,{index_write_error, Reason}}
+ end.
+
+insert_new_test_data({NewTestName,NewTestDir}, NewLabel, AllTestLogDirs) ->
+ AllTestLogDirs1 =
+ case lists:keysearch(NewTestName, 1, AllTestLogDirs) of
+ {value,{_,_,_,{LastLogDir,_},OldDirs}} ->
+ [{NewTestName,NewLabel,[],{NewTestDir,{0,0,0,0}},
+ [LastLogDir|OldDirs]} |
+ lists:keydelete(NewTestName, 1, AllTestLogDirs)];
+ false ->
+ [{NewTestName,NewLabel,[],{NewTestDir,{0,0,0,0}},[]} |
+ AllTestLogDirs]
+ end,
+ lists:keysort(1, AllTestLogDirs1).
+
+make_all_suites_ix_cached1([{TestName,Label,Missing,LastLogDirData,OldDirs}|Rest],
+ Result, TotSucc, TotFail, UserSkip, AutoSkip,
+ TotNotBuilt) ->
+
+ case make_one_ix_entry_cached(TestName, LastLogDirData,
+ Label, {true,OldDirs}, Missing) of
+ {Result1,Succ,Fail,USkip,ASkip,NotBuilt} ->
+ %% for backwards compatibility
+ AutoSkip1 = case catch AutoSkip+ASkip of
+ {'EXIT',_} -> undefined;
+ Res -> Res
+ end,
+ make_all_suites_ix_cached1(Rest, [Result|Result1], TotSucc+Succ,
+ TotFail+Fail, UserSkip+USkip, AutoSkip1,
+ TotNotBuilt+NotBuilt);
+ error ->
+ make_all_suites_ix_cached1(Rest, Result, TotSucc, TotFail,
+ UserSkip, AutoSkip, TotNotBuilt)
+ end;
+make_all_suites_ix_cached1([], Result, TotSucc, TotFail, UserSkip, AutoSkip,
+ TotNotBuilt) ->
+ [Result|total_row(TotSucc, TotFail, UserSkip, AutoSkip, TotNotBuilt, true)].
+
+make_one_ix_entry_cached(TestName, {LogDir,Summary}, Label, All, Missing) ->
+ case Summary of
+ {Succ,Fail,UserSkip,AutoSkip} ->
+ NotBuilt = not_built(TestName, LogDir, All, Missing),
+ NewResult = make_one_index_entry1(TestName, LogDir, Label,
+ Succ, Fail, UserSkip, AutoSkip,
+ NotBuilt, All, cached),
+ {NewResult,Succ,Fail,UserSkip,AutoSkip,NotBuilt};
+ error ->
+ error
+ end.
%%-----------------------------------------------------------------
%% Remove log files.
diff --git a/lib/common_test/src/ct_make.erl b/lib/common_test/src/ct_make.erl
index 233e45248e..40e9e99f37 100644
--- a/lib/common_test/src/ct_make.erl
+++ b/lib/common_test/src/ct_make.erl
@@ -177,7 +177,7 @@ members([],_MakefileMods,I,Rest) ->
{I,Rest}.
-%% Any flags that are not recognixed as make flags are passed directly
+%% Any flags that are not recognised as make flags are passed directly
%% to the compiler.
%% So for example make:all([load,debug_info]) will make everything
%% with the debug_info flag and load it.
diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index 7bd7dc7d66..0a9bb5af67 100644
--- a/lib/common_test/src/ct_run.erl
+++ b/lib/common_test/src/ct_run.erl
@@ -33,7 +33,7 @@
%% Exported for VTS
--export([run_make/3,do_run/3,tests/1,tests/2,tests/3]).
+-export([run_make/3,do_run/4,tests/1,tests/2,tests/3]).
%% Misc internal functions
@@ -46,15 +46,18 @@
-define(testdir(Name, Suite), ct_util:get_testdir(Name, Suite)).
-record(opts, {label,
+ profile,
vts,
shell,
cover,
coverspec,
step,
logdir,
+ logopts = [],
config = [],
event_handlers = [],
ct_hooks = [],
+ enable_builtin_hooks = true,
include = [],
silent_connections,
stylesheet,
@@ -156,15 +159,19 @@ script_start(Args) ->
end,
stop_trace(Tracing),
timer:sleep(1000),
+ io:nl(),
Res.
script_start1(Parent, Args) ->
%% read general start flags
Label = get_start_opt(label, fun([Lbl]) -> Lbl end, Args),
+ Profile = get_start_opt(profile, fun([Prof]) -> Prof end, Args),
Vts = get_start_opt(vts, true, Args),
Shell = get_start_opt(shell, true, Args),
Cover = get_start_opt(cover, fun([CoverFile]) -> ?abs(CoverFile) end, Args),
LogDir = get_start_opt(logdir, fun([LogD]) -> LogD end, Args),
+ LogOpts = get_start_opt(logopts, fun(Os) -> [list_to_atom(O) || O <- Os] end,
+ [], Args),
MultTT = get_start_opt(multiply_timetraps,
fun([MT]) -> list_to_integer(MT) end, 1, Args),
ScaleTT = get_start_opt(scale_timetraps,
@@ -173,6 +180,10 @@ script_start1(Parent, Args) ->
end, false, Args),
EvHandlers = event_handler_args2opts(Args),
CTHooks = ct_hooks_args2opts(Args),
+ EnableBuiltinHooks = get_start_opt(enable_builtin_hooks,
+ fun([CT]) -> list_to_atom(CT);
+ ([]) -> true
+ end, true, Args),
%% check flags and set corresponding application env variables
@@ -234,9 +245,12 @@ script_start1(Parent, Args) ->
application:set_env(common_test, basic_html, true)
end,
- StartOpts = #opts{label = Label, vts = Vts, shell = Shell, cover = Cover,
- logdir = LogDir, event_handlers = EvHandlers,
+ StartOpts = #opts{label = Label, profile = Profile,
+ vts = Vts, shell = Shell, cover = Cover,
+ logdir = LogDir, logopts = LogOpts,
+ event_handlers = EvHandlers,
ct_hooks = CTHooks,
+ enable_builtin_hooks = EnableBuiltinHooks,
include = IncludeDirs,
silent_connections = SilentConns,
stylesheet = Stylesheet,
@@ -262,15 +276,15 @@ run_or_refresh(StartOpts = #opts{logdir = LogDir}, Args) ->
%% give the shell time to print version etc
timer:sleep(500),
io:nl(),
- case catch ct_logs:make_all_suites_index(refresh) of
- {'EXIT',ASReason} ->
+ case catch ct_logs:make_all_runs_index(refresh) of
+ {'EXIT',ARReason} ->
file:set_cwd(Cwd),
- {error,{all_suites_index,ASReason}};
+ {error,{all_runs_index,ARReason}};
_ ->
- case catch ct_logs:make_all_runs_index(refresh) of
- {'EXIT',ARReason} ->
+ case catch ct_logs:make_all_suites_index(refresh) of
+ {'EXIT',ASReason} ->
file:set_cwd(Cwd),
- {error,{all_runs_index,ARReason}};
+ {error,{all_suites_index,ASReason}};
_ ->
file:set_cwd(Cwd),
io:format("Logs in ~s refreshed!~n~n", [LogDir1]),
@@ -297,9 +311,15 @@ script_start2(StartOpts = #opts{vts = undefined,
Label = choose_val(StartOpts#opts.label,
SpecStartOpts#opts.label),
+ Profile = choose_val(StartOpts#opts.profile,
+ SpecStartOpts#opts.profile),
+
LogDir = choose_val(StartOpts#opts.logdir,
SpecStartOpts#opts.logdir),
+ AllLogOpts = merge_vals([StartOpts#opts.logopts,
+ SpecStartOpts#opts.logopts]),
+
Cover = choose_val(StartOpts#opts.cover,
SpecStartOpts#opts.cover),
MultTT = choose_val(StartOpts#opts.multiply_timetraps,
@@ -311,18 +331,27 @@ script_start2(StartOpts = #opts{vts = undefined,
AllCTHooks = merge_vals(
[StartOpts#opts.ct_hooks,
SpecStartOpts#opts.ct_hooks]),
+
+ EnableBuiltinHooks =
+ choose_val(
+ StartOpts#opts.enable_builtin_hooks,
+ SpecStartOpts#opts.enable_builtin_hooks),
AllInclude = merge_vals([StartOpts#opts.include,
SpecStartOpts#opts.include]),
application:set_env(common_test, include, AllInclude),
{TS,StartOpts#opts{label = Label,
+ profile = Profile,
testspecs = Specs,
cover = Cover,
logdir = LogDir,
+ logopts = AllLogOpts,
config = SpecStartOpts#opts.config,
event_handlers = AllEvHs,
ct_hooks = AllCTHooks,
+ enable_builtin_hooks =
+ EnableBuiltinHooks,
include = AllInclude,
multiply_timetraps = MultTT,
scale_timetraps = ScaleTT}}
@@ -339,9 +368,7 @@ script_start2(StartOpts = #opts{vts = undefined,
{[],_} ->
{error,no_testspec_specified};
{undefined,_} -> % no testspec used
- case check_and_install_configfiles(InitConfig, TheLogDir,
- Opts#opts.event_handlers,
- Opts#opts.ct_hooks) of
+ case check_and_install_configfiles(InitConfig, TheLogDir, Opts) of
ok -> % go on read tests from start flags
script_start3(Opts#opts{config=InitConfig,
logdir=TheLogDir}, Args);
@@ -351,9 +378,7 @@ script_start2(StartOpts = #opts{vts = undefined,
{_,_} -> % testspec used
%% merge config from start flags with config from testspec
AllConfig = merge_vals([InitConfig, Opts#opts.config]),
- case check_and_install_configfiles(AllConfig, TheLogDir,
- Opts#opts.event_handlers,
- Opts#opts.ct_hooks) of
+ case check_and_install_configfiles(AllConfig, TheLogDir, Opts) of
ok -> % read tests from spec
{Run,Skip} = ct_testspec:prepare_tests(Terms, node()),
do_run(Run, Skip, Opts#opts{config=AllConfig,
@@ -367,9 +392,7 @@ script_start2(StartOpts, Args) ->
%% read config/userconfig from start flags
InitConfig = ct_config:prepare_config_list(Args),
LogDir = which(logdir, StartOpts#opts.logdir),
- case check_and_install_configfiles(InitConfig, LogDir,
- StartOpts#opts.event_handlers,
- StartOpts#opts.ct_hooks) of
+ case check_and_install_configfiles(InitConfig, LogDir, StartOpts) of
ok -> % go on read tests from start flags
script_start3(StartOpts#opts{config=InitConfig,
logdir=LogDir}, Args);
@@ -377,12 +400,17 @@ script_start2(StartOpts, Args) ->
Error
end.
-check_and_install_configfiles(Configs, LogDir, EvHandlers, CTHooks) ->
+check_and_install_configfiles(
+ Configs, LogDir, #opts{
+ event_handlers = EvHandlers,
+ ct_hooks = CTHooks,
+ enable_builtin_hooks = EnableBuiltinHooks} ) ->
case ct_config:check_config_files(Configs) of
false ->
install([{config,Configs},
{event_handler,EvHandlers},
- {ct_hooks,CTHooks}], LogDir);
+ {ct_hooks,CTHooks},
+ {enable_builtin_hooks,EnableBuiltinHooks}], LogDir);
{value,{error,{nofile,File}}} ->
{error,{cant_read_config_file,File}};
{value,{error,{wrong_config,Message}}}->
@@ -392,50 +420,72 @@ check_and_install_configfiles(Configs, LogDir, EvHandlers, CTHooks) ->
end.
script_start3(StartOpts, Args) ->
- case proplists:get_value(dir, Args) of
- [] ->
+ StartOpts1 = get_start_opt(step,
+ fun(Step) ->
+ StartOpts#opts{step = Step,
+ cover = undefined}
+ end, StartOpts, Args),
+ case {proplists:get_value(dir, Args),
+ proplists:get_value(suite, Args),
+ groups_and_cases(proplists:get_value(group, Args),
+ proplists:get_value(testcase, Args))} of
+ %% flag specified without data
+ {_,_,Error={error,_}} ->
+ Error;
+ {_,[],_} ->
+ {error,no_suite_specified};
+ {[],_,_} ->
{error,no_dir_specified};
- Dirs when is_list(Dirs) ->
+
+ {Dirs,undefined,[]} when is_list(Dirs) ->
script_start4(StartOpts#opts{tests = tests(Dirs)}, Args);
- undefined ->
- case proplists:get_value(suite, Args) of
- [] ->
- {error,no_suite_specified};
- Suites when is_list(Suites) ->
- StartOpts1 =
- get_start_opt(step,
- fun(Step) ->
- StartOpts#opts{step = Step,
- cover = undefined}
- end, StartOpts, Args),
- DirMods = [suite_to_test(S) || S <- Suites],
- case groups_and_cases(proplists:get_value(group, Args),
- proplists:get_value(testcase, Args)) of
- Error = {error,_} ->
- Error;
- [] when DirMods =/= [] ->
- Ts = tests(DirMods),
- script_start4(StartOpts1#opts{tests = Ts}, Args);
- GroupsAndCases when length(DirMods) == 1 ->
- Ts = tests(DirMods, GroupsAndCases),
- script_start4(StartOpts1#opts{tests = Ts}, Args);
- [_,_|_] when length(DirMods) > 1 ->
- {error,multiple_suites_and_cases};
- _ ->
- {error,incorrect_suite_option}
- end;
- undefined ->
- if StartOpts#opts.vts ; StartOpts#opts.shell ->
- script_start4(StartOpts#opts{tests = []}, Args);
- true ->
- script_usage(),
- {error,incorrect_usage}
- end
+
+ {undefined,Suites,[]} when is_list(Suites) ->
+ Ts = tests([suite_to_test(S) || S <- Suites]),
+ script_start4(StartOpts1#opts{tests = Ts}, Args);
+
+ {undefined,Suite,GsAndCs} when is_list(Suite) ->
+ case [suite_to_test(S) || S <- Suite] of
+ DirMods = [_] ->
+ Ts = tests(DirMods, GsAndCs),
+ script_start4(StartOpts1#opts{tests = Ts}, Args);
+ [_,_|_] ->
+ {error,multiple_suites_and_cases};
+ _ ->
+ {error,incorrect_start_options}
+ end;
+
+ {[_,_|_],Suite,[]} when is_list(Suite) ->
+ {error,multiple_dirs_and_suites};
+
+ {[Dir],Suite,GsAndCs} when is_list(Dir), is_list(Suite) ->
+ case [suite_to_test(Dir,S) || S <- Suite] of
+ DirMods when GsAndCs == [] ->
+ Ts = tests(DirMods),
+ script_start4(StartOpts1#opts{tests = Ts}, Args);
+ DirMods = [_] when GsAndCs /= [] ->
+ Ts = tests(DirMods, GsAndCs),
+ script_start4(StartOpts1#opts{tests = Ts}, Args);
+ [_,_|_] when GsAndCs /= [] ->
+ {error,multiple_suites_and_cases};
+ _ ->
+ {error,incorrect_start_options}
+ end;
+
+ {undefined,undefined,GsAndCs} when GsAndCs /= [] ->
+ {error,incorrect_start_options};
+
+ {undefined,undefined,_} ->
+ if StartOpts#opts.vts ; StartOpts#opts.shell ->
+ script_start4(StartOpts#opts{tests = []}, Args);
+ true ->
+ script_usage(),
+ {error,missing_start_options}
end
end.
script_start4(#opts{vts = true, config = Config, event_handlers = EvHandlers,
- tests = Tests, logdir = LogDir}, _Args) ->
+ tests = Tests, logdir = LogDir, logopts = LogOpts}, _Args) ->
ConfigFiles =
lists:foldl(fun({ct_config_plain,CfgFiles}, AllFiles) when
is_list(hd(CfgFiles)) ->
@@ -446,25 +496,32 @@ script_start4(#opts{vts = true, config = Config, event_handlers = EvHandlers,
(_, AllFiles) ->
AllFiles
end, [], Config),
- vts:init_data(ConfigFiles, EvHandlers, ?abs(LogDir), Tests);
+ vts:init_data(ConfigFiles, EvHandlers, ?abs(LogDir), LogOpts, Tests);
-script_start4(#opts{label = Label, shell = true, config = Config,
+script_start4(#opts{label = Label, profile = Profile,
+ shell = true, config = Config,
event_handlers = EvHandlers,
ct_hooks = CTHooks,
+ logopts = LogOpts,
+ enable_builtin_hooks = EnableBuiltinHooks,
logdir = LogDir, testspecs = Specs}, _Args) ->
%% label - used by ct_logs
application:set_env(common_test, test_label, Label),
- InstallOpts = [{config,Config},{event_handler,EvHandlers},
- {ct_hooks, CTHooks}],
+ %% profile - used in ct_util
+ application:set_env(common_test, profile, Profile),
+
if Config == [] ->
ok;
true ->
io:format("\nInstalling: ~p\n\n", [Config])
end,
- case install(InstallOpts) of
+ case install([{config,Config},{event_handler,EvHandlers},
+ {ct_hooks, CTHooks},
+ {enable_builtin_hooks,EnableBuiltinHooks}]) of
ok ->
ct_util:start(interactive, LogDir),
+ ct_util:set_testdata({logopts, LogOpts}),
log_ts_names(Specs),
io:nl(),
ok;
@@ -505,6 +562,7 @@ script_usage() ->
"\n\t[-decrypt_key Key] | [-decrypt_file KeyFile]"
"\n\t[-dir TestDir1 TestDir2 .. TestDirN] |"
"\n\t[-suite Suite [-case Case]]"
+ "\n\t[-logopts LogOpt1 LogOpt2 .. LogOptN]"
"\n\t[-include InclDir1 InclDir2 .. InclDirN]"
"\n\t[-no_auto_compile]"
"\n\t[-multiply_timetraps N]"
@@ -522,6 +580,7 @@ script_usage() ->
"\n\t[-stylesheet CSSFile]"
"\n\t[-cover CoverCfgFile]"
"\n\t[-event_handler EvHandler1 EvHandler2 .. EvHandlerN]"
+ "\n\t[-logopts LogOpt1 LogOpt2 .. LogOptN]"
"\n\t[-ct_hooks CTHook1 CTHook2 .. CTHookN]"
"\n\t[-include InclDir1 InclDir2 .. InclDirN]"
"\n\t[-no_auto_compile]"
@@ -541,6 +600,7 @@ script_usage() ->
"\n\t[-stylesheet CSSFile]"
"\n\t[-cover CoverCfgFile]"
"\n\t[-event_handler EvHandler1 EvHandler2 .. EvHandlerN]"
+ "\n\t[-logopts LogOpt1 LogOpt2 .. LogOptN]"
"\n\t[-ct_hooks CTHook1 CTHook2 .. CTHookN]"
"\n\t[-include InclDir1 InclDir2 .. InclDirN]"
"\n\t[-no_auto_compile]"
@@ -619,6 +679,16 @@ run_test(StartOpt) when is_tuple(StartOpt) ->
run_test([StartOpt]);
run_test(StartOpts) when is_list(StartOpts) ->
+ CTPid = spawn(fun() -> run_test1(StartOpts) end),
+ Ref = monitor(process, CTPid),
+ receive
+ {'DOWN',Ref,process,CTPid,{user_error,Error}} ->
+ Error;
+ {'DOWN',Ref,process,CTPid,Other} ->
+ Other
+ end.
+
+run_test1(StartOpts) when is_list(StartOpts) ->
case proplists:get_value(refresh_logs, StartOpts) of
undefined ->
Tracing = start_trace(StartOpts),
@@ -627,7 +697,7 @@ run_test(StartOpts) when is_list(StartOpts) ->
Res =
case ct_repeat:loop_test(func, StartOpts) of
false ->
- case catch run_test1(StartOpts) of
+ case catch run_test2(StartOpts) of
{'EXIT',Reason} ->
file:set_cwd(Cwd),
{error,Reason};
@@ -638,20 +708,27 @@ run_test(StartOpts) when is_list(StartOpts) ->
Result
end,
stop_trace(Tracing),
- Res;
+ exit(Res);
RefreshDir ->
refresh_logs(?abs(RefreshDir)),
- ok
+ exit(done)
end.
-run_test1(StartOpts) ->
+run_test2(StartOpts) ->
%% label
Label = get_start_opt(label, fun(Lbl) when is_list(Lbl) -> Lbl;
(Lbl) when is_atom(Lbl) -> atom_to_list(Lbl)
end, StartOpts),
+ %% profile
+ Profile = get_start_opt(profile, fun(Prof) when is_list(Prof) -> Prof;
+ (Prof) when is_atom(Prof) -> atom_to_list(Prof)
+ end, StartOpts),
%% logdir
LogDir = get_start_opt(logdir, fun(LD) when is_list(LD) -> LD end,
StartOpts),
+ %% logopts
+ LogOpts = get_start_opt(logopts, value, [], StartOpts),
+
%% config & userconfig
CfgFiles = ct_config:get_config_file_list(StartOpts),
@@ -682,6 +759,11 @@ run_test1(StartOpts) ->
%% CT Hooks
CTHooks = get_start_opt(ct_hooks, value, [], StartOpts),
+ EnableBuiltinHooks = get_start_opt(enable_builtin_hooks,
+ fun(EBH) when EBH == true;
+ EBH == false ->
+ EBH
+ end, true, StartOpts),
%% silent connections
SilentConns = get_start_opt(silent_connections,
@@ -750,10 +832,12 @@ run_test1(StartOpts) ->
%% stepped execution
Step = get_start_opt(step, value, StartOpts),
- Opts = #opts{label = Label,
- cover = Cover, step = Step, logdir = LogDir, config = CfgFiles,
+ Opts = #opts{label = Label, profile = Profile,
+ cover = Cover, step = Step, logdir = LogDir,
+ logopts = LogOpts, config = CfgFiles,
event_handlers = EvHandlers,
ct_hooks = CTHooks,
+ enable_builtin_hooks = EnableBuiltinHooks,
include = Include,
silent_connections = SilentConns,
stylesheet = Stylesheet,
@@ -792,8 +876,12 @@ run_spec_file(Relaxed,
SpecOpts = get_data_for_node(TS, node()),
Label = choose_val(Opts#opts.label,
SpecOpts#opts.label),
+ Profile = choose_val(Opts#opts.profile,
+ SpecOpts#opts.profile),
LogDir = choose_val(Opts#opts.logdir,
SpecOpts#opts.logdir),
+ AllLogOpts = merge_vals([Opts#opts.logopts,
+ SpecOpts#opts.logopts]),
AllConfig = merge_vals([CfgFiles, SpecOpts#opts.config]),
Cover = choose_val(Opts#opts.cover,
SpecOpts#opts.cover),
@@ -808,24 +896,29 @@ run_spec_file(Relaxed,
AllCTHooks = merge_vals([Opts#opts.ct_hooks,
SpecOpts#opts.ct_hooks]),
+ EnableBuiltinHooks = choose_val(Opts#opts.enable_builtin_hooks,
+ SpecOpts#opts.enable_builtin_hooks),
application:set_env(common_test, include, AllInclude),
- case check_and_install_configfiles(AllConfig,
- which(logdir,LogDir),
- AllEvHs,
- AllCTHooks) of
+ Opts1 = Opts#opts{label = Label,
+ profile = Profile,
+ cover = Cover,
+ logdir = which(logdir, LogDir),
+ logopts = AllLogOpts,
+ config = AllConfig,
+ event_handlers = AllEvHs,
+ include = AllInclude,
+ testspecs = AbsSpecs,
+ multiply_timetraps = MultTT,
+ scale_timetraps = ScaleTT,
+ ct_hooks = AllCTHooks,
+ enable_builtin_hooks = EnableBuiltinHooks
+ },
+
+ case check_and_install_configfiles(AllConfig,Opts1#opts.logdir,
+ Opts1) of
ok ->
- Opts1 = Opts#opts{label = Label,
- cover = Cover,
- logdir = which(logdir, LogDir),
- config = AllConfig,
- event_handlers = AllEvHs,
- include = AllInclude,
- testspecs = AbsSpecs,
- multiply_timetraps = MultTT,
- scale_timetraps = ScaleTT,
- ct_hooks = AllCTHooks},
{Run,Skip} = ct_testspec:prepare_tests(TS, node()),
reformat_result(catch do_run(Run, Skip, Opts1, StartOpts));
{error,GCFReason} ->
@@ -834,13 +927,10 @@ run_spec_file(Relaxed,
end.
run_prepared(Run, Skip, Opts = #opts{logdir = LogDir,
- config = CfgFiles,
- event_handlers = EvHandlers,
- ct_hooks = CTHooks},
+ config = CfgFiles },
StartOpts) ->
LogDir1 = which(logdir, LogDir),
- case check_and_install_configfiles(CfgFiles, LogDir1,
- EvHandlers, CTHooks) of
+ case check_and_install_configfiles(CfgFiles, LogDir1, Opts) of
ok ->
reformat_result(catch do_run(Run, Skip, Opts#opts{logdir = LogDir1},
StartOpts));
@@ -872,7 +962,8 @@ check_config_file(Callback, File)->
run_dir(Opts = #opts{logdir = LogDir,
config = CfgFiles,
event_handlers = EvHandlers,
- ct_hooks = CTHook }, StartOpts) ->
+ ct_hooks = CTHook,
+ enable_builtin_hooks = EnableBuiltinHooks }, StartOpts) ->
LogDir1 = which(logdir, LogDir),
Opts1 = Opts#opts{logdir = LogDir1},
AbsCfgFiles =
@@ -895,71 +986,107 @@ run_dir(Opts = #opts{logdir = LogDir,
end, CfgFiles),
case install([{config,AbsCfgFiles},
{event_handler,EvHandlers},
- {ct_hooks, CTHook}], LogDir1) of
+ {ct_hooks, CTHook},
+ {enable_builtin_hooks,EnableBuiltinHooks}], LogDir1) of
ok -> ok;
{error,IReason} -> exit(IReason)
end,
- case lists:keysearch(dir, 1, StartOpts) of
- {value,{_,Dirs=[Dir|_]}} when not is_integer(Dir),
- length(Dirs)>1 ->
- %% multiple dirs (no suite)
- reformat_result(catch do_run(tests(Dirs), [], Opts1, StartOpts));
- false -> % no dir
- %% fun for converting suite name to {Dir,Mod} tuple
- S2M = fun(S) when is_list(S) ->
- {filename:dirname(S),
- list_to_atom(filename:rootname(filename:basename(S)))};
- (A) ->
- {".",A}
- end,
- case lists:keysearch(suite, 1, StartOpts) of
- {value,{_,Suite}} when is_integer(hd(Suite)) ; is_atom(Suite) ->
- {Dir,Mod} = S2M(Suite),
- case groups_and_cases(proplists:get_value(group, StartOpts),
- proplists:get_value(testcase, StartOpts)) of
- Error = {error,_} ->
- exit(Error);
+ case {proplists:get_value(dir, StartOpts),
+ proplists:get_value(suite, StartOpts),
+ groups_and_cases(proplists:get_value(group, StartOpts),
+ proplists:get_value(testcase, StartOpts))} of
+ %% flag specified without data
+ {_,_,Error={error,_}} ->
+ Error;
+ {_,[],_} ->
+ {error,no_suite_specified};
+ {[],_,_} ->
+ {error,no_dir_specified};
+
+ {Dirs=[Hd|_],undefined,[]} when is_list(Dirs), not is_integer(Hd) ->
+ Dirs1 = [if is_atom(D) -> atom_to_list(D);
+ true -> D end || D <- Dirs],
+ reformat_result(catch do_run(tests(Dirs1), [], Opts1, StartOpts));
+
+ {Dir=[Hd|_],undefined,[]} when is_list(Dir) and is_integer(Hd) ->
+ reformat_result(catch do_run(tests(Dir), [], Opts1, StartOpts));
+
+ {Dir,undefined,[]} when is_atom(Dir) and (Dir /= undefined) ->
+ reformat_result(catch do_run(tests(atom_to_list(Dir)),
+ [], Opts1, StartOpts));
+
+ {undefined,Suites=[Hd|_],[]} when not is_integer(Hd) ->
+ Suites1 = [suite_to_test(S) || S <- Suites],
+ reformat_result(catch do_run(tests(Suites1), [], Opts1, StartOpts));
+
+ {undefined,Suite,[]} when is_atom(Suite) and
+ (Suite /= undefined) ->
+ {Dir,Mod} = suite_to_test(Suite),
+ reformat_result(catch do_run(tests(Dir, Mod), [], Opts1, StartOpts));
+
+ {undefined,Suite,GsAndCs} when is_atom(Suite) and
+ (Suite /= undefined) ->
+ {Dir,Mod} = suite_to_test(Suite),
+ reformat_result(catch do_run(tests(Dir, Mod, GsAndCs),
+ [], Opts1, StartOpts));
+
+ {undefined,[Hd,_|_],_GsAndCs} when not is_integer(Hd) ->
+ exit(multiple_suites_and_cases);
+
+ {undefined,Suite=[Hd|Tl],GsAndCs} when is_integer(Hd) ;
+ (is_list(Hd) and (Tl == [])) ;
+ (is_atom(Hd) and (Tl == [])) ->
+ {Dir,Mod} = suite_to_test(Suite),
+ reformat_result(catch do_run(tests(Dir, Mod, GsAndCs),
+ [], Opts1, StartOpts));
+
+ {[Hd,_|_],_Suites,[]} when is_list(Hd) ; not is_integer(Hd) ->
+ exit(multiple_dirs_and_suites);
+
+ {undefined,undefined,GsAndCs} when GsAndCs /= [] ->
+ exit(incorrect_start_options);
+
+ {Dir,Suite,GsAndCs} when is_integer(hd(Dir)) ;
+ (is_atom(Dir) and (Dir /= undefined)) ;
+ ((length(Dir) == 1) and is_atom(hd(Dir))) ;
+ ((length(Dir) == 1) and is_list(hd(Dir))) ->
+ Dir1 = if is_atom(Dir) -> atom_to_list(Dir);
+ true -> Dir end,
+ if Suite == undefined ->
+ exit(incorrect_start_options);
+
+ is_integer(hd(Suite)) ;
+ (is_atom(Suite) and (Suite /= undefined)) ;
+ ((length(Suite) == 1) and is_atom(hd(Suite))) ;
+ ((length(Suite) == 1) and is_list(hd(Suite))) ->
+ {Dir2,Mod} = suite_to_test(Dir1, Suite),
+ case GsAndCs of
[] ->
- reformat_result(catch do_run(tests(Dir, listify(Mod)),
+ reformat_result(catch do_run(tests(Dir2, Mod),
[], Opts1, StartOpts));
- GsAndCs ->
- reformat_result(catch do_run(tests(Dir, Mod, GsAndCs),
+ _ ->
+ reformat_result(catch do_run(tests(Dir2, Mod, GsAndCs),
[], Opts1, StartOpts))
end;
- {value,{_,Suites}} ->
- reformat_result(catch do_run(tests(lists:map(S2M, Suites)),
- [], Opts1, StartOpts));
- _ ->
- exit(no_tests_specified)
- end;
- {value,{_,Dir}} ->
- case lists:keysearch(suite, 1, StartOpts) of
- {value,{_,Suite}} when is_integer(hd(Suite)) ; is_atom(Suite) ->
- Mod = if is_atom(Suite) -> Suite;
- true -> list_to_atom(Suite)
- end,
- 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)),
+
+ is_list(Suite) -> % multiple suites
+ case [suite_to_test(Dir1, S) || S <- Suite] of
+ [_,_|_] when GsAndCs /= [] ->
+ exit(multiple_suites_and_cases);
+ [{Dir2,Mod}] when GsAndCs /= [] ->
+ reformat_result(catch do_run(tests(Dir2, Mod, GsAndCs),
[], Opts1, StartOpts));
- GsAndCs ->
- reformat_result(catch do_run(tests(Dir, Mod, GsAndCs),
+ DirMods ->
+ reformat_result(catch do_run(tests(DirMods),
[], Opts1, StartOpts))
- end;
- {value,{_,Suites=[Suite|_]}} when is_list(Suite) ->
- Mods = lists:map(fun(Str) -> list_to_atom(Str) end, Suites),
- reformat_result(catch do_run(tests(delistify(Dir), Mods),
- [], Opts1, StartOpts));
- {value,{_,Suites}} ->
- reformat_result(catch do_run(tests(delistify(Dir), Suites),
- [], Opts1, StartOpts));
- false -> % no suite, only dir
- reformat_result(catch do_run(tests(listify(Dir)),
- [], Opts1, StartOpts))
- end
+ end
+ end;
+
+ {undefined,undefined,[]} ->
+ exit(no_test_specified);
+
+ {Dir,Suite,GsAndCs} ->
+ exit({incorrect_start_options,{Dir,Suite,GsAndCs}})
end.
%%%-----------------------------------------------------------------
@@ -970,19 +1097,38 @@ run_dir(Opts = #opts{logdir = LogDir,
%%% the same as those used in test specification files.
%%% @equiv ct:run_testspec/1
%%%-----------------------------------------------------------------
-
run_testspec(TestSpec) ->
+ CTPid = spawn(fun() -> run_testspec1(TestSpec) end),
+ Ref = monitor(process, CTPid),
+ receive
+ {'DOWN',Ref,process,CTPid,{user_error,Error}} ->
+ Error;
+ {'DOWN',Ref,process,CTPid,Other} ->
+ Other
+ end.
+
+run_testspec1(TestSpec) ->
{ok,Cwd} = file:get_cwd(),
io:format("~nCommon Test starting (cwd is ~s)~n~n", [Cwd]),
- case catch run_testspec1(TestSpec) of
+ case catch run_testspec2(TestSpec) of
{'EXIT',Reason} ->
file:set_cwd(Cwd),
- {error,Reason};
+ exit({error,Reason});
Result ->
- Result
+ exit(Result)
end.
-run_testspec1(TestSpec) ->
+run_testspec2(File) when is_list(File), is_integer(hd(File)) ->
+ case file:read_file_info(File) of
+ {ok,_} ->
+ exit("Bad argument, "
+ "use ct:run_test([{spec," ++ File ++ "}])");
+ _ ->
+ exit("Bad argument, list of tuples expected, "
+ "use ct:run_test/1 for test specification files")
+ end;
+
+run_testspec2(TestSpec) ->
case catch ct_testspec:collect_tests_from_list(TestSpec, false) of
{E,CTReason} when E == error ; E == 'EXIT' ->
exit(CTReason);
@@ -999,9 +1145,8 @@ run_testspec1(TestSpec) ->
end,
application:set_env(common_test, include, AllInclude),
LogDir1 = which(logdir,Opts#opts.logdir),
- case check_and_install_configfiles(Opts#opts.config, LogDir1,
- Opts#opts.event_handlers,
- Opts#opts.ct_hooks) of
+ case check_and_install_configfiles(
+ Opts#opts.config, LogDir1, Opts) of
ok ->
Opts1 = Opts#opts{testspecs = [],
logdir = LogDir1,
@@ -1014,20 +1159,28 @@ run_testspec1(TestSpec) ->
end.
get_data_for_node(#testspec{label = Labels,
+ profile = Profiles,
logdir = LogDirs,
+ logopts = LogOptsList,
cover = CoverFs,
config = Cfgs,
userconfig = UsrCfgs,
event_handler = EvHs,
ct_hooks = CTHooks,
+ enable_builtin_hooks = EnableBuiltinHooks,
include = Incl,
multiply_timetraps = MTs,
scale_timetraps = STs}, Node) ->
Label = proplists:get_value(Node, Labels),
+ Profile = proplists:get_value(Node, Profiles),
LogDir = case proplists:get_value(Node, LogDirs) of
undefined -> ".";
Dir -> Dir
end,
+ LogOpts = case proplists:get_value(Node, LogOptsList) of
+ undefined -> [];
+ LOs -> LOs
+ end,
Cover = proplists:get_value(Node, CoverFs),
MT = proplists:get_value(Node, MTs),
ST = proplists:get_value(Node, STs),
@@ -1037,11 +1190,14 @@ get_data_for_node(#testspec{label = Labels,
FiltCTHooks = [Hook || {N,Hook} <- CTHooks, N==Node],
Include = [I || {N,I} <- Incl, N==Node],
#opts{label = Label,
+ profile = Profile,
logdir = LogDir,
+ logopts = LogOpts,
cover = Cover,
config = ConfigFiles,
event_handlers = EvHandlers,
ct_hooks = FiltCTHooks,
+ enable_builtin_hooks = EnableBuiltinHooks,
include = Include,
multiply_timetraps = MT,
scale_timetraps = ST}.
@@ -1111,13 +1267,31 @@ run(TestDirs) ->
install([]),
reformat_result(catch do_run(tests(TestDirs), [])).
+reformat_result({'EXIT',{user_error,Reason}}) ->
+ {error,Reason};
reformat_result({user_error,Reason}) ->
{error,Reason};
reformat_result(Result) ->
Result.
-suite_to_test(Suite) ->
- {filename:dirname(Suite),list_to_atom(filename:rootname(filename:basename(Suite)))}.
+suite_to_test(Suite) when is_atom(Suite) ->
+ suite_to_test(atom_to_list(Suite));
+
+suite_to_test(Suite) when is_list(Suite) ->
+ {filename:dirname(Suite),
+ list_to_atom(filename:rootname(filename:basename(Suite)))}.
+
+suite_to_test(Dir, Suite) when is_atom(Suite) ->
+ suite_to_test(Dir, atom_to_list(Suite));
+
+suite_to_test(Dir, Suite) when is_list(Suite) ->
+ case filename:dirname(Suite) of
+ "." ->
+ {Dir,list_to_atom(filename:rootname(Suite))};
+ DirName -> % ignore Dir
+ File = filename:basename(Suite),
+ {DirName,list_to_atom(filename:rootname(File))}
+ end.
groups_and_cases(Gs, Cs) when ((Gs == undefined) or (Gs == [])) and
((Cs == undefined) or (Cs == [])) ->
@@ -1151,9 +1325,11 @@ tests(TestDirs) when is_list(TestDirs), is_list(hd(TestDirs)) ->
[{?testdir(TestDir,all),all,all} || TestDir <- TestDirs].
do_run(Tests, Misc) when is_list(Misc) ->
- do_run(Tests, Misc, ".").
+ do_run(Tests, Misc, ".", []).
-do_run(Tests, Misc, LogDir) when is_list(Misc) ->
+do_run(Tests, Misc, LogDir, LogOpts) when is_list(Misc),
+ is_list(LogDir),
+ is_list(LogOpts) ->
Opts =
case proplists:get_value(step, Misc) of
undefined ->
@@ -1168,11 +1344,10 @@ do_run(Tests, Misc, LogDir) when is_list(Misc) ->
CoverFile ->
Opts#opts{cover = CoverFile}
end,
- do_run(Tests, [], Opts1#opts{logdir = LogDir}, []).
-
-do_run(Tests, Skip, Opts, Args) ->
- #opts{label = Label, cover = Cover} = Opts,
+ do_run(Tests, [], Opts1#opts{logdir = LogDir}, []);
+do_run(Tests, Skip, Opts, Args) when is_record(Opts, opts) ->
+ #opts{label = Label, profile = Profile, cover = Cover} = Opts,
%% label - used by ct_logs
TestLabel =
if Label == undefined -> undefined;
@@ -1182,6 +1357,15 @@ do_run(Tests, Skip, Opts, Args) ->
end,
application:set_env(common_test, test_label, TestLabel),
+ %% profile - used in ct_util
+ TestProfile =
+ if Profile == undefined -> undefined;
+ is_atom(Profile) -> atom_to_list(Profile);
+ is_list(Profile) -> Profile;
+ true -> undefined
+ end,
+ application:set_env(common_test, profile, TestProfile),
+
case code:which(test_server) of
non_existing ->
exit({error,no_path_to_test_server});
@@ -1216,6 +1400,8 @@ do_run(Tests, Skip, Opts, Args) ->
_Pid ->
%% save stylesheet info
ct_util:set_testdata({stylesheet,Opts#opts.stylesheet}),
+ %% save logopts
+ ct_util:set_testdata({logopts,Opts#opts.logopts}),
%% enable silent connections
case Opts#opts.silent_connections of
[] ->
@@ -1983,7 +2169,14 @@ maybe_interpret1(Suite, Cases, StepOpts) when is_list(Cases) ->
maybe_interpret2(Suite, Cases, StepOpts) ->
set_break_on_config(Suite, StepOpts),
- [i:ib(Suite, Case, 1) || Case <- Cases],
+ [begin try i:ib(Suite, Case, 1) of
+ _ -> ok
+ catch
+ _:_Error ->
+ io:format(user, "Invalid breakpoint: ~w:~w/1~n",
+ [Suite,Case])
+ end
+ end || Case <- Cases, is_atom(Case)],
test_server_ctrl:multiply_timetraps(infinity),
WinOp = case lists:member(keep_inactive, ensure_atom(StepOpts)) of
true -> no_kill;
@@ -1996,10 +2189,18 @@ maybe_interpret2(Suite, Cases, StepOpts) ->
set_break_on_config(Suite, StepOpts) ->
case lists:member(config, ensure_atom(StepOpts)) of
true ->
- i:ib(Suite, init_per_suite, 1),
- i:ib(Suite, init_per_testcase, 2),
- i:ib(Suite, end_per_testcase, 2),
- i:ib(Suite, end_per_suite, 1);
+ SetBPIfExists = fun(F,A) ->
+ case erlang:function_exported(Suite, F, A) of
+ true -> i:ib(Suite, F, A);
+ false -> ok
+ end
+ end,
+ SetBPIfExists(init_per_suite, 1),
+ SetBPIfExists(init_per_group, 2),
+ SetBPIfExists(init_per_testcase, 2),
+ SetBPIfExists(end_per_testcase, 2),
+ SetBPIfExists(end_per_group, 2),
+ SetBPIfExists(end_per_suite, 1);
false ->
ok
end.
@@ -2053,6 +2254,15 @@ get_start_opt(Key, IfExists, Args) ->
get_start_opt(Key, IfExists, undefined, Args).
get_start_opt(Key, IfExists, IfNotExists, Args) ->
+ try try_get_start_opt(Key, IfExists, IfNotExists, Args) of
+ Result ->
+ Result
+ catch
+ error:_ ->
+ exit({user_error,{bad_argument,Key}})
+ end.
+
+try_get_start_opt(Key, IfExists, IfNotExists, Args) ->
case lists:keysearch(Key, 1, Args) of
{value,{Key,Val}} when is_function(IfExists) ->
IfExists(Val);
@@ -2065,18 +2275,27 @@ get_start_opt(Key, IfExists, IfNotExists, Args) ->
end.
ct_hooks_args2opts(Args) ->
- ct_hooks_args2opts(
- proplists:get_value(ct_hooks, Args, []),[]).
+ lists:foldl(fun({ct_hooks,Hooks}, Acc) ->
+ ct_hooks_args2opts(Hooks,Acc);
+ (_,Acc) ->
+ Acc
+ end,[],Args).
+ct_hooks_args2opts([CTH,Arg,Prio,"and"| Rest],Acc) ->
+ ct_hooks_args2opts(Rest,[{list_to_atom(CTH),
+ parse_cth_args(Arg),
+ parse_cth_args(Prio)}|Acc]);
ct_hooks_args2opts([CTH,Arg,"and"| Rest],Acc) ->
ct_hooks_args2opts(Rest,[{list_to_atom(CTH),
- parse_cth_args(Arg)}|Acc]);
+ parse_cth_args(Arg)}|Acc]);
ct_hooks_args2opts([CTH], Acc) ->
ct_hooks_args2opts([CTH,"and"],Acc);
ct_hooks_args2opts([CTH, "and" | Rest], Acc) ->
ct_hooks_args2opts(Rest,[list_to_atom(CTH)|Acc]);
ct_hooks_args2opts([CTH, Args], Acc) ->
ct_hooks_args2opts([CTH, Args, "and"],Acc);
+ct_hooks_args2opts([CTH, Args, Prio], Acc) ->
+ ct_hooks_args2opts([CTH, Args, Prio, "and"],Acc);
ct_hooks_args2opts([],Acc) ->
lists:reverse(Acc).
@@ -2218,12 +2437,21 @@ opts2args(EnvStartOpts) ->
end, EHs),
[_LastAnd|StrsR] = lists:reverse(lists:flatten(Strs)),
[{event_handler_init,lists:reverse(StrsR)}];
+ ({logopts,LOs}) when is_list(LOs) ->
+ [{logopts,[atom_to_list(LO) || LO <- LOs]}];
({ct_hooks,[]}) ->
[];
({ct_hooks,CTHs}) when is_list(CTHs) ->
io:format(user,"ct_hooks: ~p",[CTHs]),
Strs = lists:flatmap(
- fun({CTH,Arg}) ->
+ fun({CTH,Arg,Prio}) ->
+ [atom_to_list(CTH),
+ lists:flatten(
+ io_lib:format("~p",[Arg])),
+ lists:flatten(
+ io_lib:format("~p",[Prio])),
+ "and"];
+ ({CTH,Arg}) ->
[atom_to_list(CTH),
lists:flatten(
io_lib:format("~p",[Arg])),
@@ -2274,32 +2502,31 @@ is_suite(ModOrFile) when is_list(ModOrFile) ->
end.
get_all_testcases(Suite) ->
- %%! this needs to be updated to handle testcase groups later!!
- case catch Suite:all() of
- {'EXIT',Why} ->
- {error,Why};
- {skip,_} ->
- [];
- Cases ->
- AllCases =
- lists:foldl(fun({sequence,SeqName}, All) ->
- case catch Suite:sequences() of
- {'EXIT',_} ->
- All;
- Seqs ->
- case proplists:get_value(SeqName, Seqs) of
- undefined ->
- All;
- SeqCases ->
- lists:reverse(SeqCases) ++ All
- end
- end;
- (Case,All) ->
- [Case|All]
- end, [], Cases),
- lists:reverse(AllCases)
+ try ct_framework:get_all_cases(Suite) of
+ {error,_Reason} = Error ->
+ Error;
+ SuiteCases ->
+ Cases = [C || {_S,C} <- SuiteCases],
+ try Suite:sequences() of
+ [] ->
+ Cases;
+ Seqs ->
+ TCs1 = lists:flatten([TCs || {_,TCs} <- Seqs]),
+ lists:reverse(
+ lists:foldl(fun(TC, Acc) ->
+ case lists:member(TC, Acc) of
+ true -> Acc;
+ false -> [TC | Acc]
+ end
+ end, [], Cases ++ TCs1))
+ catch
+ _:_ ->
+ Cases
+ end
+ catch
+ _:Error ->
+ {error,Error}
end.
-
%% Internal tracing support. If {ct_trace,TraceSpec} is present, the
%% TraceSpec file will be consulted and dbg used to trace function
@@ -2320,8 +2547,8 @@ start_trace(Args) ->
false
end;
{_,Error} ->
- io:format("Warning! Tracing not started. Reason: ~p~n~n",
- [Error]),
+ io:format("Warning! Tracing not started. Reason: ~s~n~n",
+ [file:format_error(Error)]),
false
end;
false ->
diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl
index c6f5fd7df4..71a784870c 100644
--- a/lib/common_test/src/ct_telnet.erl
+++ b/lib/common_test/src/ct_telnet.erl
@@ -245,7 +245,6 @@ cmdf(Connection,CmdFormat,Args) ->
%%% Data = [string()]
%%% @doc Send a telnet command and wait for prompt
%%% (uses a format string and list of arguments to build the command).
-%%%-----------------------------------------------------------------
cmdf(Connection,CmdFormat,Args,Timeout) when is_list(Args) ->
Cmd = lists:flatten(io_lib:format(CmdFormat,Args)),
cmd(Connection,Cmd,Timeout).
@@ -360,15 +359,15 @@ expect(Connection,Patterns) ->
%%% will also be a <code>HaltReason</code> returned.</p>
%%%
%%% <p><underline>Examples:</underline><br/>
-%%% <code>expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],
-%%% [sequence,{halt,[{nnn,"NNN"}]}]).</code><br/> will try to match
+%%% <code>expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],</code>
+%%% <code>[sequence,{halt,[{nnn,"NNN"}]}]).</code><br/> will try to match
%%% "ABC" first and then "XYZ", but if "NNN" appears the function will
%%% return <code>{error,{nnn,["NNN"]}}</code>. If both "ABC" and "XYZ"
%%% are matched, the function will return
%%% <code>{ok,[AbcMatch,XyzMatch]}</code>.</p>
%%%
-%%% <p><code>expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],
-%%% [{repeat,2},{halt,[{nnn,"NNN"}]}]).</code><br/> will try to match
+%%% <p><code>expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],</code>
+%%% <code>[{repeat,2},{halt,[{nnn,"NNN"}]}]).</code><br/> will try to match
%%% "ABC" or "XYZ" twice. If "NNN" appears the function will return
%%% with <code>HaltReason = {nnn,["NNN"]}</code>.</p>
%%%
diff --git a/lib/common_test/src/ct_testspec.erl b/lib/common_test/src/ct_testspec.erl
index d845358bb2..317910d5c8 100644
--- a/lib/common_test/src/ct_testspec.erl
+++ b/lib/common_test/src/ct_testspec.erl
@@ -249,11 +249,15 @@ collect_tests_from_file1([Spec|Specs],TestSpec,Relaxed) ->
SpecDir = filename:dirname(filename:absname(Spec)),
case file:consult(Spec) of
{ok,Terms} ->
- TestSpec1 = collect_tests(Terms,TestSpec#testspec{spec_dir=SpecDir},
+ TestSpec1 = collect_tests(Terms,
+ TestSpec#testspec{spec_dir=SpecDir},
Relaxed),
collect_tests_from_file1(Specs,TestSpec1,Relaxed);
{error,Reason} ->
- throw({error,{Spec,Reason}})
+ ReasonStr =
+ lists:flatten(io_lib:format("~s",
+ [file:format_error(Reason)])),
+ throw({error,{Spec,ReasonStr}})
end;
collect_tests_from_file1([],TS=#testspec{config=Cfgs,event_handler=EvHs,
include=Incl,tests=Tests},_) ->
@@ -481,6 +485,26 @@ add_tests([{logdir,Node,Dir}|Ts],Spec) ->
add_tests([{logdir,Dir}|Ts],Spec) ->
add_tests([{logdir,all_nodes,Dir}|Ts],Spec);
+%% --- logopts ---
+add_tests([{logopts,all_nodes,Opts}|Ts],Spec) ->
+ LogOpts = Spec#testspec.logopts,
+ Tests = [{logopts,N,Opts} ||
+ N <- list_nodes(Spec),
+ lists:keymember(ref2node(N,Spec#testspec.nodes),1,
+ LogOpts) == false],
+ add_tests(Tests++Ts,Spec);
+add_tests([{logopts,Nodes,Opts}|Ts],Spec) when is_list(Nodes) ->
+ Ts1 = separate(Nodes,logopts,[Opts],Ts,Spec#testspec.nodes),
+ add_tests(Ts1,Spec);
+add_tests([{logopts,Node,Opts}|Ts],Spec) ->
+ LogOpts = Spec#testspec.logopts,
+ LogOpts1 = [{ref2node(Node,Spec#testspec.nodes),Opts} |
+ lists:keydelete(ref2node(Node,Spec#testspec.nodes),
+ 1,LogOpts)],
+ add_tests(Ts,Spec#testspec{logopts=LogOpts1});
+add_tests([{logopts,Opts}|Ts],Spec) ->
+ add_tests([{logopts,all_nodes,Opts}|Ts],Spec);
+
%% --- label ---
add_tests([{label,all_nodes,Lbl}|Ts],Spec) ->
Labels = Spec#testspec.label,
@@ -646,6 +670,10 @@ add_tests([{ct_hooks, _Node, []}|Ts], Spec) ->
add_tests([{ct_hooks, Hooks}|Ts], Spec) ->
add_tests([{ct_hooks, all_nodes, Hooks}|Ts], Spec);
+%% -- enable_builtin_hooks --
+add_tests([{enable_builtin_hooks,Bool}|Ts],Spec) ->
+ add_tests(Ts, Spec#testspec{ enable_builtin_hooks = Bool });
+
%% --- include ---
add_tests([{include,all_nodes,InclDirs}|Ts],Spec) ->
Tests = lists:map(fun(N) -> {include,N,InclDirs} end, list_nodes(Spec)),
@@ -1097,6 +1125,8 @@ valid_terms() ->
{merge_tests,1},
{logdir,2},
{logdir,3},
+ {logopts,2},
+ {logopts,3},
{label,2},
{label,3},
{event_handler,2},
@@ -1104,6 +1134,7 @@ valid_terms() ->
{event_handler,4},
{ct_hooks,2},
{ct_hooks,3},
+ {enable_builtin_hooks,1},
{multiply_timetraps,2},
{multiply_timetraps,3},
{scale_timetraps,2},
diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl
index 115207beed..3b6ad6f98d 100644
--- a/lib/common_test/src/ct_util.erl
+++ b/lib/common_test/src/ct_util.erl
@@ -37,7 +37,7 @@
read_suite_data/1,
delete_suite_data/0, delete_suite_data/1, match_delete_suite_data/1,
delete_testdata/0, delete_testdata/1, set_testdata/1, get_testdata/1,
- update_testdata/2]).
+ set_testdata_async/1, update_testdata/2]).
-export([override_silence_all_connections/0, override_silence_connections/1,
get_overridden_silenced_connections/0,
@@ -47,7 +47,7 @@
-export([get_mode/0, create_table/3, read_opts/0]).
--export([set_cwd/1, reset_cwd/0]).
+-export([set_cwd/1, reset_cwd/0, get_start_dir/0]).
-export([parse_table/1]).
@@ -61,6 +61,9 @@
-export([warn_duplicates/1]).
+-export([get_profile_data/0, get_profile_data/1,
+ get_profile_data/2, open_url/3]).
+
-include("ct_event.hrl").
-include("ct_util.hrl").
@@ -96,7 +99,8 @@ start(Mode,LogDir) ->
Pid = spawn_link(fun() -> do_start(S,Mode,LogDir) end),
receive
{Pid,started} -> Pid;
- {Pid,Error} -> exit(Error)
+ {Pid,Error} -> exit(Error);
+ {_Ref,{Pid,Error}} -> exit(Error)
end;
Pid ->
case get_mode() of
@@ -120,13 +124,15 @@ do_start(Parent,Mode,LogDir) ->
ok -> ok;
E -> exit(E)
end,
+ DoExit = fun(Reason) -> file:set_cwd(StartDir), exit(Reason) end,
Opts = case read_opts() of
{ok,Opts1} ->
Opts1;
Error ->
Parent ! {self(),Error},
- exit(Error)
+ DoExit(Error)
end,
+
%% start an event manager (if not already started by master)
case ct_event:start_link() of
{error,{already_started,_}} ->
@@ -139,16 +145,23 @@ do_start(Parent,Mode,LogDir) ->
ct_event:add_handler([{vts,VtsPid}])
end
end,
+
%% start ct_config server
- ct_config:start(Mode),
+ try ct_config:start(Mode) of
+ _ -> ok
+ catch
+ _Class:CfgError ->
+ DoExit(CfgError)
+ end,
+
%% add user event handlers
case lists:keysearch(event_handler,1,Opts) of
{value,{_,Handlers}} ->
Add = fun({H,Args}) ->
case catch gen_event:add_handler(?CT_EVMGR_REF,H,Args) of
ok -> ok;
- {'EXIT',Why} -> exit(Why);
- Other -> exit({event_handler,Other})
+ {'EXIT',Why} -> DoExit(Why);
+ Other -> DoExit({event_handler,Other})
end
end,
case catch lists:foreach(Add,Handlers) of
@@ -162,21 +175,24 @@ do_start(Parent,Mode,LogDir) ->
end,
{StartTime,TestLogDir} = ct_logs:init(Mode),
- %% Initiate ct_hooks
- case catch ct_hooks:init(Opts) of
- ok ->
- ok;
- {_,CTHReason} ->
- ct_logs:tc_print('Suite Callback',CTHReason,[]),
- Parent ! {self(), CTHReason},
- self() ! {{stop,normal},{self(),make_ref()}}
- end,
-
ct_event:notify(#event{name=test_start,
node=node(),
data={StartTime,
lists:flatten(TestLogDir)}}),
- Parent ! {self(),started},
+ %% Initialize ct_hooks
+ try ct_hooks:init(Opts) of
+ ok ->
+ Parent ! {self(),started};
+ {fail,CTHReason} ->
+ ct_logs:tc_print('Suite Callback',CTHReason,[]),
+ self() ! {{stop,{self(),{user_error,CTHReason}}},
+ {Parent,make_ref()}}
+ catch
+ _:CTHReason ->
+ ct_logs:tc_print('Suite Callback',CTHReason,[]),
+ self() ! {{stop,{self(),{user_error,CTHReason}}},
+ {Parent,make_ref()}}
+ end,
loop(Mode,[],StartDir).
create_table(TableName,KeyPos) ->
@@ -232,6 +248,9 @@ update_testdata(Key, Fun) ->
set_testdata(TestData) ->
call({set_testdata, TestData}).
+set_testdata_async(TestData) ->
+ cast({set_testdata, TestData}).
+
get_testdata(Key) ->
call({get_testdata, Key}).
@@ -241,6 +260,9 @@ set_cwd(Dir) ->
reset_cwd() ->
call(reset_cwd).
+get_start_dir() ->
+ call(get_start_dir).
+
loop(Mode,TestData,StartDir) ->
receive
{update_last_run_index,From} ->
@@ -317,7 +339,10 @@ loop(Mode,TestData,StartDir) ->
{reset_cwd,From} ->
return(From,file:set_cwd(StartDir)),
loop(From,TestData,StartDir);
- {{stop,How},From} ->
+ {get_start_dir,From} ->
+ return(From,StartDir),
+ loop(From,TestData,StartDir);
+ {{stop,Info},From} ->
Time = calendar:local_time(),
ct_event:sync_notify(#event{name=test_done,
node=node(),
@@ -330,11 +355,11 @@ loop(Mode,TestData,StartDir) ->
ets:delete(?conn_table),
ets:delete(?board_table),
ets:delete(?suite_table),
- ct_logs:close(How),
+ ct_logs:close(Info, StartDir),
ct_event:stop(),
ct_config:stop(),
file:set_cwd(StartDir),
- return(From,ok);
+ return(From, Info);
{Ref, _Msg} when is_reference(Ref) ->
%% This clause is used when doing cast operations.
loop(Mode,TestData,StartDir);
@@ -537,16 +562,16 @@ reset_silent_connections() ->
%%%-----------------------------------------------------------------
-%%% @spec stop(How) -> ok
+%%% @spec stop(Info) -> ok
%%%
%%% @doc Stop the ct_util_server and close all existing connections
%%% (tool-internal use only).
%%%
%%% @see ct
-stop(How) ->
+stop(Info) ->
case whereis(ct_util_server) of
undefined -> ok;
- _ -> call({stop,How})
+ _ -> call({stop,Info})
end.
%%%-----------------------------------------------------------------
@@ -725,6 +750,79 @@ warn_duplicates(Suites) ->
lists:foreach(Warn, Suites),
ok.
+%%%-----------------------------------------------------------------
+%%% @spec
+%%%
+%%% @doc
+get_profile_data() ->
+ get_profile_data(all).
+
+get_profile_data(KeyOrStartDir) ->
+ if is_atom(KeyOrStartDir) ->
+ get_profile_data(KeyOrStartDir, get_start_dir());
+ is_list(KeyOrStartDir) ->
+ get_profile_data(all, KeyOrStartDir)
+ end.
+
+get_profile_data(Key, StartDir) ->
+ Profile = case application:get_env(common_test, profile) of
+ {ok,undefined} -> default;
+ {ok,Prof} -> Prof;
+ _ -> default
+ end,
+ get_profile_data(Profile, Key, StartDir).
+
+get_profile_data(Profile, Key, StartDir) ->
+ File = case Profile of
+ default ->
+ ?ct_profile_file;
+ _ when is_list(Profile) ->
+ ?ct_profile_file ++ "." ++ Profile;
+ _ when is_atom(Profile) ->
+ ?ct_profile_file ++ "." ++ atom_to_list(Profile)
+ end,
+ FullNameWD = filename:join(StartDir, File),
+ {WhichFile,Result} =
+ case file:consult(FullNameWD) of
+ {error,enoent} ->
+ case init:get_argument(home) of
+ {ok,[[HomeDir]]} ->
+ FullNameHome = filename:join(HomeDir, File),
+ {FullNameHome,file:consult(FullNameHome)};
+ _ ->
+ {File,{error,enoent}}
+ end;
+ Consulted ->
+ {FullNameWD,Consulted}
+ end,
+ case Result of
+ {error,enoent} when Profile /= default ->
+ io:format(user, "~nERROR! Missing profile file ~p~n", [File]),
+ undefined;
+ {error,enoent} when Profile == default ->
+ undefined;
+ {error,Reason} ->
+ io:format(user,"~nERROR! Error in profile file ~p: ~p~n",
+ [WhichFile,Reason]),
+ undefined;
+ {ok,Data} ->
+ Data1 = case Data of
+ [List] when is_list(List) ->
+ List;
+ _ when is_list(Data) ->
+ Data;
+ _ ->
+ io:format(user,
+ "~nERROR! Invalid profile data in ~p~n",
+ [WhichFile]),
+ []
+ end,
+ if Key == all ->
+ Data1;
+ true ->
+ proplists:get_value(Key, Data)
+ end
+ end.
%%%-----------------------------------------------------------------
%%% Internal functions
@@ -797,3 +895,28 @@ abs_name2([H|T],Acc) ->
abs_name2(T,[H|Acc]);
abs_name2([],Acc) ->
filename:join(lists:reverse(Acc)).
+
+open_url(iexplore, Args, URL) ->
+ {ok,R} = win32reg:open([read]),
+ ok = win32reg:change_key(R,"applications\\iexplore.exe\\shell\\open\\command"),
+ case win32reg:values(R) of
+ {ok, Paths} ->
+ Path = proplists:get_value(default, Paths),
+ [Cmd | _] = string:tokens(Path, "%"),
+ Cmd1 = Cmd ++ " " ++ Args ++ " " ++ URL,
+ io:format(user, "~nOpening ~s with command:~n ~s~n", [URL,Cmd1]),
+ open_port({spawn,Cmd1}, []);
+ _ ->
+ io:format("~nNo path to iexplore.exe~n",[])
+ end,
+ win32reg:close(R),
+ ok;
+
+open_url(Prog, Args, URL) ->
+ ProgStr = if is_atom(Prog) -> atom_to_list(Prog);
+ is_list(Prog) -> Prog
+ end,
+ Cmd = ProgStr ++ " " ++ Args ++ " " ++ URL,
+ io:format(user, "~nOpening ~s with command:~n ~s~n", [URL,Cmd]),
+ open_port({spawn,Cmd},[]),
+ ok.
diff --git a/lib/common_test/src/ct_util.hrl b/lib/common_test/src/ct_util.hrl
index 556f88c84d..bde832811a 100644
--- a/lib/common_test/src/ct_util.hrl
+++ b/lib/common_test/src/ct_util.hrl
@@ -31,12 +31,15 @@
nodes=[],
init=[],
label=[],
+ profile=[],
logdir=["."],
+ logopts=[],
cover=[],
config=[],
userconfig=[],
event_handler=[],
ct_hooks=[],
+ enable_builtin_hooks=true,
include=[],
multiply_timetraps=[],
scale_timetraps=[],
@@ -58,3 +61,5 @@
-define(missing_suites_info, "missing_suites.info").
-define(ct_config_txt, ct_config_plain).
+
+-define(ct_profile_file, ".common_test").
diff --git a/lib/common_test/src/cth_log_redirect.erl b/lib/common_test/src/cth_log_redirect.erl
new file mode 100644
index 0000000000..14663b7738
--- /dev/null
+++ b/lib/common_test/src/cth_log_redirect.erl
@@ -0,0 +1,111 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(cth_log_redirect).
+
+%%% @doc Common Test Framework functions handling test specifications.
+%%%
+%%% <p>This module redirects sasl and error logger info to common test log.</p>
+%%% @end
+
+
+%% CTH Callbacks
+-export([id/1, init/2, post_init_per_group/4, pre_end_per_group/3,
+ post_end_per_testcase/4]).
+
+%% Event handler Callbacks
+-export([init/1,
+ handle_event/2, handle_call/2, handle_info/2,
+ terminate/2]).
+
+id(_Opts) ->
+ ?MODULE.
+
+init(?MODULE, _Opts) ->
+ error_logger:add_report_handler(?MODULE),
+ tc_log.
+
+post_init_per_group(Group, Config, Result, tc_log) ->
+ case lists:member(parallel,proplists:get_value(
+ tc_group_properties,Config,[])) of
+ true ->
+ {Result, {set_log_func(ct_log),Group}};
+ false ->
+ {Result, tc_log}
+ end;
+post_init_per_group(_Group, _Config, Result, State) ->
+ {Result, State}.
+
+post_end_per_testcase(_TC, _Config, Result, State) ->
+ %% Make sure that the event queue is flushed
+ %% before ending this test case.
+ gen_event:call(error_logger, ?MODULE, flush),
+ {Result, State}.
+
+pre_end_per_group(Group, Config, {ct_log, Group}) ->
+ {Config, set_log_func(tc_log)};
+pre_end_per_group(_Group, Config, State) ->
+ {Config, State}.
+
+
+%% Copied and modified from sasl_report_tty_h.erl
+init(_Type) ->
+ {ok, tc_log}.
+
+handle_event({_Type, GL, _Msg}, State) when node(GL) /= node() ->
+ {ok, State};
+handle_event(Event, LogFunc) ->
+ case lists:keyfind(sasl, 1, application:which_applications()) of
+ false ->
+ sasl_not_started;
+ _Else ->
+ {ok, ErrLogType} = application:get_env(sasl, errlog_type),
+ SReport = sasl_report:format_report(group_leader(), ErrLogType,
+ tag_event(Event)),
+ if is_list(SReport) ->
+ ct_logs:LogFunc(sasl, SReport, []);
+ true -> %% Report is an atom if no logging is to be done
+ ignore
+ end
+ end,
+ EReport = error_logger_tty_h:write_event(
+ tag_event(Event),io_lib),
+ if is_list(EReport) ->
+ ct_logs:LogFunc(error_logger, EReport, []);
+ true -> %% Report is an atom if no logging is to be done
+ ignore
+ end,
+ {ok, LogFunc}.
+
+
+handle_info(_,State) -> {ok, State}.
+
+handle_call(flush,State) ->
+ {ok, ok, State};
+handle_call({set_logfunc,NewLogFunc},_) ->
+ {ok, NewLogFunc, NewLogFunc};
+handle_call(_Query, _State) -> {error, bad_query}.
+
+terminate(_Reason, _Type) ->
+ [].
+
+tag_event(Event) ->
+ {calendar:local_time(), Event}.
+
+set_log_func(Func) ->
+ gen_event:call(error_logger, ?MODULE, {set_logfunc, Func}).
diff --git a/lib/common_test/src/vts.erl b/lib/common_test/src/vts.erl
index 2ee982d726..cc8a932887 100644
--- a/lib/common_test/src/vts.erl
+++ b/lib/common_test/src/vts.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
%%
%% The 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,7 +20,7 @@
-module(vts).
-export([start/0,
- init_data/4,
+ init_data/5,
stop/0,
report/2]).
@@ -32,6 +32,7 @@
menu_frame/2,
welcome_frame/2,
config_frame/2,
+ browse_config_file/2,
add_config_file/2,
remove_config_file/2,
run_frame/2,
@@ -56,7 +57,7 @@
-record(state,{tests=[],config=[],event_handler=[],test_runner,
running=0,reload_results=false,start_dir,current_log_dir,
- total=0,ok=0,fail=0,skip=0,testruns=[]}).
+ logopts=[],total=0,ok=0,fail=0,skip=0,testruns=[]}).
%%%-----------------------------------------------------------------
@@ -65,8 +66,8 @@ start() ->
webtool:start(),
webtool:start_tools([],"app=vts").
-init_data(ConfigFiles,EvHandlers,LogDir,Tests) ->
- call({init_data,ConfigFiles,EvHandlers,LogDir,Tests}).
+init_data(ConfigFiles,EvHandlers,LogDir,LogOpts,Tests) ->
+ call({init_data,ConfigFiles,EvHandlers,LogDir,LogOpts,Tests}).
stop() ->
webtool:stop_tools([],"app=vts"),
@@ -119,6 +120,8 @@ menu_frame(_Env,_Input) ->
call(menu_frame).
config_frame(_Env,_Input) ->
call(config_frame).
+browse_config_file(_Env,Input) ->
+ call({browse_config_file,Input}).
add_config_file(_Env,Input) ->
call({add_config_file,Input}).
remove_config_file(_Env,Input) ->
@@ -160,10 +163,11 @@ init(Parent) ->
loop(State) ->
receive
- {{init_data,Config,EvHandlers,LogDir,Tests},From} ->
+ {{init_data,Config,EvHandlers,LogDir,LogOpts,Tests},From} ->
%% ct:pal("State#state.current_log_dir=~p", [State#state.current_log_dir]),
NewState = State#state{config=Config,event_handler=EvHandlers,
- current_log_dir=LogDir,tests=Tests},
+ current_log_dir=LogDir,
+ logopts=LogOpts,tests=Tests},
ct_install(NewState),
return(From,ok),
loop(NewState);
@@ -182,6 +186,9 @@ loop(State) ->
{config_frame,From} ->
return(From,config_frame1(State)),
loop(State);
+ {{browse_config_file,_Input},From} ->
+ return(From,ok),
+ loop(State);
{{add_config_file,Input},From} ->
{Return,State1} = add_config_file1(Input,State),
ct_install(State1),
@@ -241,10 +248,12 @@ loop(State) ->
return(From,ok);
{'EXIT',Pid,Reason} ->
case State#state.test_runner of
- Pid -> io:format("ERROR: test runner crashed: ~p\n",[Reason]);
- _ -> ignore
- end,
- loop(State);
+ Pid ->
+ io:format("Test run error: ~p\n",[Reason]),
+ loop(State);
+ _ ->
+ loop(State)
+ end;
{{test_info,_Type,_Data},From} ->
return(From,ok),
loop(State)
@@ -270,10 +279,11 @@ return({To,Ref},Result) ->
To ! {Ref, Result}.
-run_test1(State=#state{tests=Tests,current_log_dir=LogDir}) ->
+run_test1(State=#state{tests=Tests,current_log_dir=LogDir,
+ logopts=LogOpts}) ->
Self=self(),
RunTest = fun() ->
- case ct_run:do_run(Tests,[],LogDir) of
+ case ct_run:do_run(Tests,[],LogDir,LogOpts) of
{error,_Reason} ->
aborted();
_ ->
@@ -281,20 +291,19 @@ run_test1(State=#state{tests=Tests,current_log_dir=LogDir}) ->
end,
unlink(Self)
end,
-
Pid = spawn_link(RunTest),
-
- Total =
+ {Total,Tests1} =
receive
{{test_info,start_info,{_,_,Cases}},From} ->
return(From,ok),
- Cases;
+ {Cases,Tests};
EXIT = {'EXIT',_,_} ->
- self() ! EXIT
+ self() ! EXIT,
+ {0,[]}
after 30000 ->
- 0
+ {0,[]}
end,
- State#state{test_runner=Pid,running=length(Tests),
+ State#state{test_runner=Pid,running=length(Tests1),
total=Total,ok=0,fail=0,skip=0,testruns=[]}.
@@ -358,22 +367,32 @@ config_frame1(State) ->
config_body(State) ->
Entry = [input("TYPE=file NAME=browse SIZE=40"),
input("TYPE=hidden NAME=file")],
+ BrowseForm =
+ form(
+ "NAME=read_file_form METHOD=post ACTION=\"./browse_config_file\"",
+ table(
+ "BORDER=0",
+ [tr(td("1. Locate config file")),
+ tr(td(Entry))])),
AddForm =
form(
- "NAME=read_file_form METHOD=post ACTION=\"./add_config_file\"",
+ "NAME=add_file_form METHOD=post ACTION=\"./add_config_file\"",
table(
"BORDER=0",
- [tr(
- [td(Entry),
+ [tr(td("2. Paste full config file name here")),
+ tr(
+ [td(input("TYPE=text NAME=file SIZE=40")),
td("ALIGN=center",
input("TYPE=submit onClick=\"file.value=browse.value;\""
" VALUE=\"Add\""))])])),
+
{Text,RemoveForm} =
case State#state.config of
[] ->
- T = "To be able to run any tests, one or more configuration "
- "files must be added. Enter the name of the configuration "
- "file below and click the \"Add\" button.",
+ T = "Before running the tests, one or more configuration "
+ "files may be added. Locate the config file, copy its "
+ "full name, paste this into the text field below, then "
+ "click the \"Add\" button.",
R = "",
{T,R};
Files ->
@@ -396,20 +415,24 @@ config_body(State) ->
input("TYPE=submit VALUE=\"Remove\"")))])),
{T,R}
end,
-
+
[h1("ALIGN=center","Config"),
table(
- "WIDTH=600 ALIGN=center CELLPADDING=5",
+ "WIDTH=450 ALIGN=center CELLPADDING=5",
[tr(td(["BGCOLOR=",?INFO_BG_COLOR],Text)),
- tr(td("ALIGN=center",AddForm)),
- tr(td("ALIGN=center",RemoveForm))])].
-
+ tr(td("")),
+ tr(td("")),
+ tr(td("ALIGN=left",BrowseForm)),
+ tr(td("ALIGN=left",AddForm)),
+ tr(td("ALIGN=left",RemoveForm))])].
add_config_file1(Input,State) ->
State1 =
case get_input_data(Input,"file") of
- "" -> State;
- File -> State#state{config=[File|State#state.config]}
+ "" ->
+ State;
+ File ->
+ State#state{config=[File|State#state.config]}
end,
Return = config_frame1(State1),
{Return,State1}.
@@ -429,10 +452,17 @@ run_body(#state{running=Running}) when Running>0 ->
[h1("ALIGN=center","Run Test"),
p(["Test are ongoing: ",href("./result_frameset","Results")])];
run_body(State) ->
- ConfigList = ul([li(File) || File <- State#state.config]),
+ ConfigList =
+ case State#state.config of
+ [] ->
+ ul(["none"]);
+ CfgFiles ->
+ ul([li(File) || File <- CfgFiles])
+ end,
ConfigFiles = [h3("Config Files"),
ConfigList],
-
+ {ok,CWD} = file:get_cwd(),
+ CurrWD = [h3("Current Working Directory"), ul(CWD)],
AddDirForm =
form(
"NAME=add_dir_form METHOD=post ACTION=\"./add_test_dir\"",
@@ -444,7 +474,6 @@ run_body(State) ->
td("ALIGN=center",
input("TYPE=submit onClick=\"dir.value=browse.value;\""
" VALUE=\"Add Test Dir\""))])])),
-
{LoadedTestsTable,Submit} =
case create_testdir_entries(State#state.tests,1) of
[] -> {"",""};
@@ -456,22 +485,20 @@ run_body(State) ->
{table("CELLPADDING=5",[Heading,TestDirs]),
submit_button()}
end,
-
- %% It should be ok to have no config-file!
Body =
- %% case State#state.config of %% [] -> %% p("ALIGN=center",
- %% href("./config_frame","Please select one or
- %% more config files")); %% _ ->
table(
- "WIDTH=100%",
- [tr(td(ConfigFiles)),
+ "WIDTH=450 ALIGN=center",
+ [tr(td("")),
+ tr(td("")),
+ tr(td(ConfigFiles)),
+ tr(td("")),
+ tr(td(CurrWD)),
tr(td("")),
tr(td(AddDirForm)),
tr(td("")),
tr(td(LoadedTestsTable)),
- tr(td(Submit))]),
- %% end,
-
+ tr(td(Submit))
+ ]),
[h1("ALIGN=center","Run Test"), Body].
create_testdir_entries([{Dir,Suite,Case}|Tests],N) ->
@@ -480,7 +507,7 @@ create_testdir_entries([],_N) ->
[].
testdir_entry(Dir,Suite,Case,N) ->
- NStr = integer_to_list(N),
+ NStr = vts_integer_to_list(N),
tr([td(delete_button(NStr)),
td(Dir),
td(suite_select(Dir,Suite,NStr)),
@@ -558,18 +585,17 @@ options([Element|Elements],Selected,N,Func) ->
options([],_Selected,_N,_Func) ->
[].
-add_test_dir1(Input,State) ->
+add_test_dir1(Input, State) ->
State1 =
case get_input_data(Input,"dir") of
"" -> State;
Dir0 ->
Dir = case ct_util:is_test_dir(Dir0) of
- true ->
- Dir0;
- false -> filename:join(Dir0,"test")
+ true -> Dir0;
+ false -> ct_util:get_testdir(Dir0, all)
end,
case filelib:is_dir(Dir) of
- true ->
+ true ->
Test = ct_run:tests(Dir),
State#state{tests=State#state.tests++Test};
false ->
@@ -579,8 +605,6 @@ add_test_dir1(Input,State) ->
Return = run_frame1(State1),
{Return,State1}.
-
-
remove_test_dir1(Input,State) ->
N = list_to_integer(get_input_data(Input,"dir")),
State1 = State#state{tests=delete_test(N,State#state.tests)},
@@ -643,6 +667,9 @@ result_frameset2(State) ->
"./redirect_to_result_log_frame";
{_Dir,0} ->
filename:join(["/log_dir","index.html"]);
+ {_Dir,_} when State#state.testruns == [] ->
+ %% crash before first test
+ "./no_result_log_frame";
{_Dir,_} ->
{_,CurrentLog} = hd(State#state.testruns),
CurrentLog
@@ -691,11 +718,11 @@ result_summary_frame1(State) ->
result_summary_body(State) ->
N = State#state.ok + State#state.fail + State#state.skip,
[h2("Result Summary"),
- p([b(integer_to_list(N))," cases executed (of ",
- b(integer_to_list(State#state.total)),")"]),
- p([green([b(integer_to_list(State#state.ok))," successful"]),br(),
- red([b(integer_to_list(State#state.fail))," failed"]),br(),
- orange([b(integer_to_list(State#state.skip))," skipped"])]),
+ p([b(vts_integer_to_list(N))," cases executed (of ",
+ b(vts_integer_to_list(State#state.total)),")"]),
+ p([green([b(vts_integer_to_list(State#state.ok))," successful"]),br(),
+ red([b(vts_integer_to_list(State#state.fail))," failed"]),br(),
+ orange([b(vts_integer_to_list(State#state.skip))," skipped"])]),
executed_test_list(State)].
executed_test_list(#state{testruns=[]}) ->
@@ -735,6 +762,14 @@ report1(tc_done,{_Suite,init_per_suite,_},State) ->
State;
report1(tc_done,{_Suite,end_per_suite,_},State) ->
State;
+report1(tc_done,{_Suite,init_per_group,_},State) ->
+ State;
+report1(tc_done,{_Suite,end_per_group,_},State) ->
+ State;
+report1(tc_done,{_Suite,ct_init_per_group,_},State) ->
+ State;
+report1(tc_done,{_Suite,ct_end_per_group,_},State) ->
+ State;
report1(tc_done,{_Suite,_Case,ok},State) ->
State#state{ok=State#state.ok+1};
report1(tc_done,{_Suite,_Case,{failed,_Reason}},State) ->
@@ -742,7 +777,11 @@ report1(tc_done,{_Suite,_Case,{failed,_Reason}},State) ->
report1(tc_done,{_Suite,_Case,{skipped,_Reason}},State) ->
State#state{skip=State#state.skip+1};
report1(tc_user_skip,{_Suite,_Case,_Reason},State) ->
- State#state{skip=State#state.skip+1}.
+ State#state{skip=State#state.skip+1};
+report1(tc_auto_skip,{_Suite,_Case,_Reason},State) ->
+ State#state{skip=State#state.skip+1};
+report1(loginfo,_,State) ->
+ State.
get_test_log(TestName,LogDir) ->
[Log] =
@@ -842,6 +881,8 @@ h2(Text) ->
["<H2>",Text,"</H2>\n"].
h3(Text) ->
["<H3>",Text,"</H3>\n"].
+%%h4(Text) ->
+%% ["<H4>",Text,"</H4>\n"].
font(Args,Text) ->
["<FONT ",Args,">\n",Text,"\n</FONT>\n"].
p(Text) ->
@@ -882,3 +923,7 @@ get_input_data(Input,Key)->
parse(Input) ->
httpd:parse_query(Input).
+vts_integer_to_list(X) when is_atom(X) ->
+ atom_to_list(X);
+vts_integer_to_list(X) when is_integer(X) ->
+ integer_to_list(X).
diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile
index 115565aaa0..b7b099069c 100644
--- a/lib/common_test/test/Makefile
+++ b/lib/common_test/test/Makefile
@@ -96,7 +96,7 @@ release_tests_spec:
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(ERL_FILES) $(COVERFILE) $(RELSYSDIR)
$(INSTALL_DATA) common_test.spec $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/common_test/test/ct_config_SUITE.erl b/lib/common_test/test/ct_config_SUITE.erl
index b6b50f33e0..8ce75f582a 100644
--- a/lib/common_test/test/ct_config_SUITE.erl
+++ b/lib/common_test/test/ct_config_SUITE.erl
@@ -174,7 +174,8 @@ run_test(Name, Config, CTConfig, SuiteNames)->
TestEvents = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(Name,
reformat_events(TestEvents, ?eh),
- ?config(config_dir, Config)),
+ ?config(config_dir, Config),
+ Opts),
ExpEvents = events_to_check(Name),
ok = ct_test_support:verify_events(ExpEvents, TestEvents, Config).
diff --git a/lib/common_test/test/ct_error_SUITE.erl b/lib/common_test/test/ct_error_SUITE.erl
index ad6cf1ba8f..c1a455c6d8 100644
--- a/lib/common_test/test/ct_error_SUITE.erl
+++ b/lib/common_test/test/ct_error_SUITE.erl
@@ -60,7 +60,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[cfg_error, lib_error, no_compile, timetrap_end_conf,
- timetrap_normal, timetrap_extended].
+ timetrap_normal, timetrap_extended, timetrap_parallel,
+ timetrap_fun].
groups() ->
[].
@@ -102,8 +103,9 @@ cfg_error(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(cfg_error,
- reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(cfg_error),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -120,8 +122,9 @@ lib_error(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(lib_error,
- reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(lib_error),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -138,8 +141,9 @@ no_compile(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(no_compile,
- reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(no_compile),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -156,7 +160,8 @@ timetrap_end_conf(Config) when is_list(Config) ->
ct_test_support:log_events(timetrap_end_conf,
reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(timetrap_end_conf),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -176,7 +181,8 @@ timetrap_normal(Config) when is_list(Config) ->
ct_test_support:log_events(timetrap_normal,
reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(timetrap_normal),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -198,12 +204,53 @@ timetrap_extended(Config) when is_list(Config) ->
ct_test_support:log_events(timetrap_extended,
reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(timetrap_extended),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
%%%-----------------------------------------------------------------
+%%%
+timetrap_parallel(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Join = fun(D, S) -> filename:join(D, "error/test/"++S) end,
+ Suite = Join(DataDir, "timetrap_3_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite}], Config),
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(timetrap_parallel,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+
+ TestEvents = events_to_check(timetrap_parallel),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+timetrap_fun(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Join = fun(D, S) -> filename:join(D, "error/test/"++S) end,
+ Suites = [Join(DataDir, "timetrap_4_SUITE"),
+ Join(DataDir, "timetrap_5_SUITE"),
+ Join(DataDir, "timetrap_6_SUITE"),
+ Join(DataDir, "timetrap_7_SUITE")],
+ {Opts,ERPid} = setup([{suite,Suites}], Config),
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(timetrap_fun,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+
+ TestEvents = events_to_check(timetrap_fun),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+
+%%%-----------------------------------------------------------------
%%% HELP FUNCTIONS
%%%-----------------------------------------------------------------
@@ -236,7 +283,7 @@ test_events(cfg_error) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
- {?eh,start_info,{14,14,42}},
+ {?eh,start_info,{14,14,45}},
{?eh,tc_start,{cfg_error_1_SUITE,init_per_suite}},
{?eh,tc_done,
@@ -256,41 +303,21 @@ test_events(cfg_error) ->
{?eh,tc_start,{cfg_error_2_SUITE,init_per_suite}},
{?eh,tc_done,
{cfg_error_2_SUITE,init_per_suite,
- {failed,{error,{{badmatch,[1,2]},
- [{cfg_error_2_SUITE,init_per_suite,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}]}}}}},
+ {failed,{error,{{badmatch,[1,2]},'_'}}}}},
{?eh,tc_auto_skip,
{cfg_error_2_SUITE,tc1,
{failed,{cfg_error_2_SUITE,init_per_suite,
- {'EXIT',{{badmatch,[1,2]},
- [{cfg_error_2_SUITE,init_per_suite,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}]}}}}}},
+ {'EXIT',{{badmatch,[1,2]},'_'}}}}}},
{?eh,test_stats,{0,0,{0,3}}},
{?eh,tc_auto_skip,
{cfg_error_2_SUITE,tc2,
{failed,{cfg_error_2_SUITE,init_per_suite,
- {'EXIT',{{badmatch,[1,2]},
- [{cfg_error_2_SUITE,init_per_suite,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}]}}}}}},
+ {'EXIT',{{badmatch,[1,2]},'_'}}}}}},
{?eh,test_stats,{0,0,{0,4}}},
{?eh,tc_auto_skip,
{cfg_error_2_SUITE,end_per_suite,
{failed,{cfg_error_2_SUITE,init_per_suite,
- {'EXIT',{{badmatch,[1,2]},
- [{cfg_error_2_SUITE,init_per_suite,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}]}}}}}},
+ {'EXIT',{{badmatch,[1,2]},'_'}}}}}},
{?eh,tc_start,{cfg_error_3_SUITE,init_per_suite}},
{?eh,tc_done,
@@ -349,12 +376,7 @@ test_events(cfg_error) ->
{?eh,tc_done,{cfg_error_6_SUITE,{end_per_group,g1,[]},ok}}],
{?eh,tc_start,{cfg_error_6_SUITE,end_per_suite}},
{?eh,tc_done,{cfg_error_6_SUITE,end_per_suite,
- {failed,{error,{{badmatch,[1,2]},
- [{cfg_error_6_SUITE,end_per_suite,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}]}}}}},
+ {failed,{error,{{badmatch,[1,2]},'_'}}}}},
{?eh,tc_start,{cfg_error_7_SUITE,init_per_suite}},
{?eh,tc_done,{cfg_error_7_SUITE,init_per_suite,ok}},
@@ -403,34 +425,16 @@ test_events(cfg_error) ->
[{?eh,tc_start,{cfg_error_8_SUITE,{init_per_group,g3,[]}}},
{?eh,tc_done,
{cfg_error_8_SUITE,{init_per_group,g3,[]},
- {failed,{error,{{badmatch,42},
- [{cfg_error_8_SUITE,init_per_group,2},
- {cfg_error_8_SUITE,init_per_group,2},
- {test_server,my_apply,3},
- {test_server,ts_tc,3},
- {test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}},
+ {failed,{error,{{badmatch,42},'_'}}}}},
{?eh,tc_auto_skip,
{cfg_error_8_SUITE,tc1,
{failed,{cfg_error_8_SUITE,init_per_group,
- {'EXIT',{{badmatch,42},
- [{cfg_error_8_SUITE,init_per_group,2},
- {cfg_error_8_SUITE,init_per_group,2},
- {test_server,my_apply,3},
- {test_server,ts_tc,3},
- {test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}}},
+ {'EXIT',{{badmatch,42},'_'}}}}}},
{?eh,test_stats,{4,0,{0,13}}},
{?eh,tc_auto_skip,
{cfg_error_8_SUITE,end_per_group,
{failed,{cfg_error_8_SUITE,init_per_group,
- {'EXIT',{{badmatch,42},
- [{cfg_error_8_SUITE,init_per_group,2},
- {cfg_error_8_SUITE,init_per_group,2},
- {test_server,my_apply,3},
- {test_server,ts_tc,3},
- {test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}}}],
+ {'EXIT',{{badmatch,42},'_'}}}}}}],
[{?eh,tc_start,{cfg_error_8_SUITE,{init_per_group,g4,[]}}},
{?eh,tc_done,{cfg_error_8_SUITE,{init_per_group,g4,[]},ok}},
@@ -499,12 +503,7 @@ test_events(cfg_error) ->
{?eh,tc_start,{cfg_error_9_SUITE,tc3}},
{?eh,tc_done,{cfg_error_9_SUITE,tc3,
{skipped,{failed,{cfg_error_9_SUITE,init_per_testcase,
- {{badmatch,undefined},
- [{cfg_error_9_SUITE,init_per_testcase,2},
- {test_server,my_apply,3},
- {test_server,init_per_testcase,3},
- {test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}}},
+ {{badmatch,undefined},'_'}}}}}},
{?eh,test_stats,{9,0,{0,17}}},
{?eh,tc_start,{cfg_error_9_SUITE,tc4}},
{?eh,tc_done,
@@ -520,16 +519,19 @@ test_events(cfg_error) ->
%%! end_tc failes the testcase
{?eh,tc_done,{cfg_error_9_SUITE,tc6,ok}},
{?eh,test_stats,{9,2,{0,18}}},
+ {?eh,tc_start,{cfg_error_9_SUITE,tc7}},
+ {?eh,tc_done,{cfg_error_9_SUITE,tc7,{failed,{error,tc7_should_be_failed}}}},
+ {ct_test_support_eh,test_stats,{9,3,{0,18}}},
{?eh,tc_start,{cfg_error_9_SUITE,tc11}},
{?eh,tc_done,{cfg_error_9_SUITE,tc11,
{failed,{cfg_error_9_SUITE,end_per_testcase,
{'EXIT',warning_should_be_printed}}}}},
- {?eh,test_stats,{10,2,{0,18}}},
+ {?eh,test_stats,{10,3,{0,18}}},
{?eh,tc_start,{cfg_error_9_SUITE,tc12}},
{?eh,tc_done,{cfg_error_9_SUITE,tc12,
{failed,{cfg_error_9_SUITE,end_per_testcase,
{timetrap_timeout,2000}}}}},
- {?eh,test_stats,{11,2,{0,18}}},
+ {?eh,test_stats,{11,3,{0,18}}},
{?eh,tc_start,{cfg_error_9_SUITE,tc13}},
{?eh,tc_done,{cfg_error_9_SUITE,tc13,
{failed,{cfg_error_9_SUITE,end_per_testcase,
@@ -538,13 +540,18 @@ test_events(cfg_error) ->
{test_server,my_apply,3},
{test_server,do_end_per_testcase,4},
{test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}}},
- {?eh,test_stats,{12,2,{0,18}}},
+ {test_server,run_test_case_eval,9}]}}}}}},
+ {?eh,test_stats,{12,3,{0,18}}},
{?eh,tc_start,{cfg_error_9_SUITE,tc14}},
{?eh,tc_done,
{cfg_error_9_SUITE,tc14,{failed,{error,tc14_should_be_failed}}}},
- {?eh,test_stats,{12,3,{0,18}}},
-
+ {?eh,tc_start,{cfg_error_9_SUITE,tc15}},
+ {?eh,tc_done,
+ {cfg_error_9_SUITE,tc15,{failed,{error,this_error_must_show}}}},
+ {?eh,tc_start,{cfg_error_9_SUITE,tc16}},
+ {?eh,tc_done,
+ {cfg_error_9_SUITE,tc16,{failed,{error,this_error_must_show}}}},
+ {?eh,test_stats,{12,6,{0,18}}},
{?eh,tc_start,{cfg_error_9_SUITE,end_per_suite}},
{?eh,tc_done,{cfg_error_9_SUITE,end_per_suite,ok}},
@@ -554,7 +561,7 @@ test_events(cfg_error) ->
{?eh,tc_auto_skip,{cfg_error_10_SUITE,tc1,
{failed,{cfg_error_10_SUITE,init_per_suite,
{failed,fail_init_per_suite}}}}},
- {?eh,test_stats,{12,3,{0,19}}},
+ {?eh,test_stats,{12,6,{0,19}}},
{?eh,tc_auto_skip,{cfg_error_10_SUITE,end_per_suite,
{failed,{cfg_error_10_SUITE,init_per_suite,
{failed,fail_init_per_suite}}}}},
@@ -563,40 +570,40 @@ test_events(cfg_error) ->
{?eh,tc_start,{cfg_error_11_SUITE,tc1}},
{?eh,tc_done,{cfg_error_11_SUITE,tc1,
{skipped,{config_name_already_in_use,[dummy0]}}}},
- {?eh,test_stats,{12,3,{1,19}}},
+ {?eh,test_stats,{12,6,{1,19}}},
{?eh,tc_start,{cfg_error_11_SUITE,tc2}},
{?eh,tc_done,{cfg_error_11_SUITE,tc2,ok}},
- {?eh,test_stats,{13,3,{1,19}}},
+ {?eh,test_stats,{13,6,{1,19}}},
{?eh,tc_start,{cfg_error_11_SUITE,end_per_suite}},
{?eh,tc_done,{cfg_error_11_SUITE,end_per_suite,ok}},
{?eh,tc_start,{cfg_error_12_SUITE,tc1}},
{?eh,tc_done,{cfg_error_12_SUITE,tc1,{failed,{timetrap_timeout,500}}}},
- {?eh,test_stats,{13,4,{1,19}}},
+ {?eh,test_stats,{13,7,{1,19}}},
{?eh,tc_start,{cfg_error_12_SUITE,tc2}},
{?eh,tc_done,{cfg_error_12_SUITE,tc2,{failed,
{cfg_error_12_SUITE,end_per_testcase,
{timetrap_timeout,500}}}}},
- {?eh,test_stats,{14,4,{1,19}}},
+ {?eh,test_stats,{14,7,{1,19}}},
{?eh,tc_start,{cfg_error_12_SUITE,tc3}},
{?eh,tc_done,{cfg_error_12_SUITE,tc3,ok}},
- {?eh,test_stats,{15,4,{1,19}}},
+ {?eh,test_stats,{15,7,{1,19}}},
{?eh,tc_start,{cfg_error_12_SUITE,tc4}},
{?eh,tc_done,{cfg_error_12_SUITE,tc4,{failed,
{cfg_error_12_SUITE,end_per_testcase,
{timetrap_timeout,500}}}}},
- {?eh,test_stats,{16,4,{1,19}}},
+ {?eh,test_stats,{16,7,{1,19}}},
{?eh,tc_start,{cfg_error_13_SUITE,init_per_suite}},
{?eh,tc_done,{cfg_error_13_SUITE,init_per_suite,ok}},
{?eh,tc_start,{cfg_error_13_SUITE,tc1}},
{?eh,tc_done,{cfg_error_13_SUITE,tc1,ok}},
- {?eh,test_stats,{17,4,{1,19}}},
+ {?eh,test_stats,{17,7,{1,19}}},
{?eh,tc_start,{cfg_error_13_SUITE,end_per_suite}},
{?eh,tc_done,{cfg_error_13_SUITE,end_per_suite,ok}},
{?eh,tc_start,{cfg_error_14_SUITE,init_per_suite}},
{?eh,tc_done,{cfg_error_14_SUITE,init_per_suite,ok}},
{?eh,tc_start,{cfg_error_14_SUITE,tc1}},
{?eh,tc_done,{cfg_error_14_SUITE,tc1,ok}},
- {?eh,test_stats,{18,4,{1,19}}},
+ {?eh,test_stats,{18,7,{1,19}}},
{?eh,tc_start,{cfg_error_14_SUITE,end_per_suite}},
{?eh,tc_done,{cfg_error_14_SUITE,end_per_suite,
{comment,
@@ -616,13 +623,7 @@ test_events(lib_error) ->
{?eh,tc_done,
{lib_error_1_SUITE,lines_error,{failed,
{error,
- {{badmatch,[1,2]},
- [{lib_lines,do_error,0},
- {lib_error_1_SUITE,lines_error,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}]}}}}},
+ {{badmatch,[1,2]},'_'}}}}},
{?eh,test_stats,{0,1,{0,0}}},
{?eh,tc_start,{lib_error_1_SUITE,lines_exit}},
{?eh,tc_done,
@@ -630,7 +631,7 @@ test_events(lib_error) ->
{?eh,test_stats,{0,2,{0,0}}},
{?eh,tc_start,{lib_error_1_SUITE,lines_hang}},
{?eh,tc_done,
- {lib_lines,do_hang,{failed,{timetrap_timeout,3000}}}},
+ {lib_error_1_SUITE,lines_hang,{failed,{timetrap_timeout,3000}}}},
{?eh,test_stats,{0,3,{0,0}}},
{?eh,tc_start,{lib_error_1_SUITE,lines_throw}},
{?eh,tc_done,
@@ -641,13 +642,7 @@ test_events(lib_error) ->
{?eh,tc_done,
{lib_error_1_SUITE,no_lines_error,{failed,
{error,
- {{badmatch,[1,2]},
- [{lib_no_lines,do_error,0},
- {lib_error_1_SUITE,no_lines_error,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}]}}}}},
+ {{badmatch,[1,2]},'_'}}}}},
{?eh,test_stats,{0,5,{0,0}}},
{?eh,tc_start,{lib_error_1_SUITE,no_lines_exit}},
{?eh,tc_done,
@@ -729,7 +724,7 @@ test_events(timetrap_normal) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
- {?eh,start_info,{1,1,3}},
+ {?eh,start_info,{1,1,4}},
{?eh,tc_start,{timetrap_2_SUITE,init_per_suite}},
{?eh,tc_done,{timetrap_2_SUITE,init_per_suite,ok}},
{?eh,tc_start,{timetrap_2_SUITE,tc0}},
@@ -744,6 +739,9 @@ test_events(timetrap_normal) ->
{?eh,tc_done,
{timetrap_2_SUITE,tc2,{failed,{timetrap_timeout,500}}}},
{?eh,test_stats,{0,3,{0,0}}},
+ {?eh,tc_start,{timetrap_2_SUITE,tc3}},
+ {?eh,tc_done,{timetrap_2_SUITE,tc3,ok}},
+ {?eh,test_stats,{1,3,{0,0}}},
{?eh,tc_start,{timetrap_2_SUITE,end_per_suite}},
{?eh,tc_done,{timetrap_2_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
@@ -754,7 +752,7 @@ test_events(timetrap_extended) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
- {?eh,start_info,{1,1,3}},
+ {?eh,start_info,{1,1,4}},
{?eh,tc_start,{timetrap_2_SUITE,init_per_suite}},
{?eh,tc_done,{timetrap_2_SUITE,init_per_suite,ok}},
{?eh,tc_start,{timetrap_2_SUITE,tc0}},
@@ -769,8 +767,134 @@ test_events(timetrap_extended) ->
{?eh,tc_done,
{timetrap_2_SUITE,tc2,{failed,{timetrap_timeout,1000}}}},
{?eh,test_stats,{0,3,{0,0}}},
+ {?eh,tc_start,{timetrap_2_SUITE,tc3}},
+ {?eh,tc_done,{timetrap_2_SUITE,tc3,ok}},
+ {?eh,test_stats,{1,3,{0,0}}},
{?eh,tc_start,{timetrap_2_SUITE,end_per_suite}},
{?eh,tc_done,{timetrap_2_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]}
+ ];
+
+test_events(timetrap_parallel) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,8}},
+ {?eh,tc_done,{timetrap_3_SUITE,init_per_suite,ok}},
+ {parallel,
+ [{?eh,tc_start,
+ {timetrap_3_SUITE,{init_per_group,g1,[parallel]}}},
+ {?eh,tc_done,
+ {timetrap_3_SUITE,{init_per_group,g1,[parallel]},ok}},
+ {?eh,tc_start,{timetrap_3_SUITE,tc0}},
+ {?eh,tc_start,{timetrap_3_SUITE,tc1}},
+ {?eh,tc_start,{timetrap_3_SUITE,tc2}},
+ {?eh,tc_start,{timetrap_3_SUITE,tc3}},
+ {?eh,tc_start,{timetrap_3_SUITE,tc4}},
+ {?eh,tc_start,{timetrap_3_SUITE,tc5}},
+ {?eh,tc_start,{timetrap_3_SUITE,tc6}},
+ {?eh,tc_start,{timetrap_3_SUITE,tc7}},
+ {?eh,tc_done,
+ {timetrap_3_SUITE,tc5,ok}},
+ {?eh,tc_done,
+ {timetrap_3_SUITE,tc1,{failed,{timetrap_timeout,500}}}},
+ {?eh,tc_done,
+ {timetrap_3_SUITE,tc2,{failed,{timetrap_timeout,1000}}}},
+ {?eh,tc_done,
+ {timetrap_3_SUITE,tc6,{failed,{timetrap_timeout,1000}}}},
+ {?eh,tc_done,
+ {timetrap_3_SUITE,tc7,{failed,{timetrap_timeout,1500}}}},
+ {?eh,tc_done,
+ {timetrap_3_SUITE,tc0,{failed,{timetrap_timeout,2000}}}},
+ {?eh,tc_done,
+ {timetrap_3_SUITE,tc4,{failed,{timetrap_timeout,2000}}}},
+ {?eh,tc_done,
+ {timetrap_3_SUITE,tc3,{failed,{timetrap_timeout,3000}}}},
+ {?eh,test_stats,{1,7,{0,0}}},
+ {?eh,tc_start,
+ {timetrap_3_SUITE,{end_per_group,g1,[parallel]}}},
+ {?eh,tc_done,
+ {timetrap_3_SUITE,{end_per_group,g1,[parallel]},ok}}]},
+ {?eh,tc_done,{timetrap_3_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(timetrap_fun) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,start_info,{4,4,17}},
+ {?eh,tc_done,{timetrap_4_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{timetrap_4_SUITE,tc0}},
+ {?eh,tc_done,
+ {timetrap_4_SUITE,tc0,{failed,{timetrap_timeout,1000}}}},
+ {?eh,tc_start,{timetrap_4_SUITE,tc1}},
+ {?eh,tc_done,
+ {timetrap_4_SUITE,tc1,{failed,{timetrap_timeout,2000}}}},
+ {?eh,tc_start,{timetrap_4_SUITE,tc2}},
+ {?eh,tc_done,
+ {timetrap_4_SUITE,tc2,{failed,{timetrap_timeout,500}}}},
+ {?eh,tc_start,{timetrap_4_SUITE,tc3}},
+ {?eh,tc_done,
+ {timetrap_4_SUITE,tc3,{failed,{timetrap_timeout,1000}}}},
+ {?eh,test_stats,{0,4,{0,0}}},
+ {?eh,tc_done,{timetrap_4_SUITE,end_per_suite,ok}},
+
+ {?eh,tc_done,{timetrap_5_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc0}},
+ {?eh,tc_done,
+ {timetrap_5_SUITE,tc0,{failed,{timetrap_timeout,1000}}}},
+ {?eh,test_stats,{0,5,{0,0}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc1}},
+ {?eh,tc_done,
+ {timetrap_5_SUITE,tc1,{skipped,{timetrap_error,kaboom}}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc2}},
+ {?eh,tc_done,
+ {timetrap_5_SUITE,tc2,{skipped,{timetrap_error,kaboom}}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc3}},
+ {?eh,tc_done,
+ {timetrap_5_SUITE,tc3,
+ {skipped,{invalid_time_format,{timetrap_utils,timetrap_val,[5000]}}}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc4}},
+ {?eh,tc_done,
+ {timetrap_5_SUITE,tc4,{skipped,{invalid_time_format,'_'}}}},
+ {?eh,test_stats,{0,5,{0,4}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc5}},
+ {?eh,tc_done,
+ {timetrap_5_SUITE,tc5,{failed,{timetrap_timeout,1000}}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc6}},
+ {?eh,tc_done,
+ {timetrap_5_SUITE,tc6,{failed,{timetrap_timeout,1000}}}},
+ {?eh,tc_start,{timetrap_5_SUITE,tc7}},
+ {?eh,tc_done,
+ {timetrap_5_SUITE,tc7,{failed,{timetrap_timeout,1000}}}},
+ {?eh,test_stats,{0,8,{0,4}}},
+ {?eh,tc_done,{timetrap_5_SUITE,end_per_suite,ok}},
+
+ {?eh,tc_start,{timetrap_6_SUITE,init_per_suite}},
+ {?eh,tc_done,
+ {timetrap_6_SUITE,init_per_suite,{skipped,{timetrap_error,kaboom}}}},
+ {?eh,tc_auto_skip,
+ {timetrap_6_SUITE,tc0,{fw_auto_skip,{timetrap_error,kaboom}}}},
+ {?eh,test_stats,{0,8,{0,5}}},
+ {?eh,tc_auto_skip,
+ {timetrap_6_SUITE,end_per_suite,{fw_auto_skip,{timetrap_error,kaboom}}}},
+
+ {?eh,tc_done,{timetrap_7_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{timetrap_7_SUITE,tc0}},
+ {?eh,tc_done,
+ {timetrap_7_SUITE,tc0,{failed,{timetrap_timeout,1000}}}},
+ {?eh,tc_start,{timetrap_7_SUITE,tc1}},
+ {?eh,tc_done,
+ {timetrap_7_SUITE,tc1,{failed,{timetrap_timeout,2000}}}},
+ {?eh,tc_start,{timetrap_7_SUITE,tc2}},
+ {?eh,tc_done,
+ {timetrap_7_SUITE,tc2,{failed,{timetrap_timeout,500}}}},
+ {?eh,tc_start,{timetrap_7_SUITE,tc3}},
+ {?eh,tc_done,
+ {timetrap_7_SUITE,tc3,{failed,{timetrap_timeout,1000}}}},
+ {?eh,test_stats,{0,12,{0,5}}},
+ {?eh,tc_done,{timetrap_7_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
].
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl
index d73287ad62..f292985c0c 100644
--- a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -76,13 +76,15 @@ init_per_testcase(tc1, Config) ->
Config;
init_per_testcase(tc2, Config) ->
ct:comment("init_per_testcase(tc2) timeout"),
- timer:sleep(5000),
+ ct:sleep(5000),
Config;
init_per_testcase(tc3, Config) ->
badmatch = ?config(void, Config),
Config;
init_per_testcase(tc4, _) ->
ok;
+init_per_testcase(tc7, _) ->
+ {fail,tc7_should_be_failed};
init_per_testcase(_, Config) ->
Config.
@@ -94,22 +96,20 @@ init_per_testcase(_, Config) ->
%%--------------------------------------------------------------------
end_per_testcase(tc11, _Config) ->
ct:comment("A warning should be printed"),
- exit(warning_should_be_printed),
- done;
+ exit(warning_should_be_printed);
end_per_testcase(tc12, _Config) ->
ct:comment("A warning should be printed"),
- timer:sleep(5000),
- done;
+ ct:sleep(5000);
end_per_testcase(tc13, Config) ->
ct:comment("A warning should be printed"),
- badmatch = ?config(void, Config),
- done;
+ badmatch = ?config(void, Config);
end_per_testcase(tc14, Config) ->
ok = ?config(tc_status, Config),
{fail,tc14_should_be_failed};
end_per_testcase(tc15, Config) ->
- {failed,byebye} = ?config(tc_status, Config),
- ok;
+ exit(kaboom);
+end_per_testcase(tc16, Config) ->
+ ct:sleep(5000);
end_per_testcase(_TestCase, _Config) ->
done.
@@ -136,8 +136,8 @@ groups() ->
%% Reason = term()
%%--------------------------------------------------------------------
all() ->
- [tc1,tc2,tc3,tc4,tc5,tc6,
- tc11,tc12,tc13,tc14].
+ [tc1,tc2,tc3,tc4,tc5,tc6,tc7,
+ tc11,tc12,tc13,tc14,tc15,tc16].
tc1(_) ->
fini.
@@ -171,6 +171,11 @@ tc6(_) ->
ct:comment("This one should succeed but then get failed by end_tc!"),
fini.
+tc7(_) ->
+ ct:comment("This one should get failed by iptc!"),
+ fini.
+
+
tc11(_) ->
fini.
tc12(_) ->
@@ -182,4 +187,6 @@ tc14(_) ->
ct:comment("This one should be failed by eptc"),
yes.
tc15(_) ->
- exit(byebye).
+ exit(this_error_must_show).
+tc16(_) ->
+ exit(this_error_must_show).
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_2_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_2_SUITE.erl
index 99bb400137..a77d06815e 100644
--- a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_2_SUITE.erl
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_2_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -77,8 +77,8 @@ init_per_testcase(tc1, Config) ->
ct:timetrap({seconds,1}),
Config;
-init_per_testcase(tc3, Config) ->
- ct:timetrap({seconds,1}),
+init_per_testcase(tc2, Config) ->
+ ct:timetrap(250),
Config;
init_per_testcase(_TestCase, Config) ->
@@ -90,7 +90,7 @@ init_per_testcase(_TestCase, Config) ->
%% TestCase = atom()
%% Config0 = Config1 = [tuple()]
%%--------------------------------------------------------------------
-end_per_testcase(_, Config) ->
+end_per_testcase(_, _Config) ->
ok.
%%--------------------------------------------------------------------
@@ -116,7 +116,7 @@ groups() ->
%% Reason = term()
%%--------------------------------------------------------------------
all() ->
- [tc0,tc1,tc2].
+ [tc0,tc1,tc2,tc3].
tc0(_) ->
N = list_to_integer(ct:get_config(multiply)),
@@ -131,8 +131,24 @@ tc1(_) ->
ok.
tc2(_) ->
+ ct:timetrap(500),
N = list_to_integer(ct:get_config(multiply)),
ct:comment(io_lib:format("TO after ~w sec", [0.5*N])),
- ct:timetrap(500),
ct:sleep(2000),
ok.
+
+tc3() ->
+ [{timetrap,{seconds,2}}].
+
+tc3(_) ->
+ T0 = now(),
+ ct:timetrap(infinity),
+ N = list_to_integer(ct:get_config(multiply)),
+ ct:comment(io_lib:format("Sleeping for ~w sec...", [4*N])),
+ ct:sleep(4000),
+ Diff = timer:now_diff(now(), T0),
+ if ((Diff < (N*4000000)) or (Diff > (N*4500000))) ->
+ exit(not_expected);
+ true ->
+ ok
+ end.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_3_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_3_SUITE.erl
new file mode 100644
index 0000000000..8271b23afe
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_3_SUITE.erl
@@ -0,0 +1,146 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(timetrap_3_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-define(TO, 3).
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,?TO}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: 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
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[parallel],[tc0,tc1,tc2,tc3,tc4,tc5,tc6,tc7]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [{group,g1}].
+
+tc0() ->
+ [{timetrap,2000}].
+tc0(_) ->
+ ct:comment("TO after 2 sec"),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc1() ->
+ [{timetrap,500}].
+tc1(_) ->
+ ct:comment("TO after 1/2 sec"),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc2() ->
+ [{timetrap,1000}].
+tc2(_) ->
+ ct:comment("TO after 1 sec"),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc3(_) ->
+ ct:comment(io_lib:format("TO after ~w sec", [?TO])),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc4() ->
+ [{timetrap,2000}].
+tc4(_) ->
+ ct:comment(io_lib:format("TO after 2 sec", [])),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc5() ->
+ [{timetrap,2000}].
+tc5(_) ->
+ ct:comment("No timeout"),
+ ct:sleep({seconds,1}),
+ ok.
+
+tc6() ->
+ [{timetrap,1000}].
+tc6(_) ->
+ ct:comment("TO after 1 sec"),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc7() ->
+ [{timetrap,1500}].
+tc7(_) ->
+ ct:comment("TO after 1 1/2 sec"),
+ ct:sleep({seconds,5}),
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_4_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_4_SUITE.erl
new file mode 100644
index 0000000000..d902454f09
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_4_SUITE.erl
@@ -0,0 +1,135 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(timetrap_4_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-define(TO, 1).
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{timetrap_utils,timetrap_val,[{seconds,?TO}]}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: 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
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc0,tc1,tc2,tc3].
+
+tc0(_) ->
+ ct:comment(io_lib:format("TO after ~w sec", [?TO])),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc1() ->
+ [{timetrap,{timetrap_utils,timetrap_val,[2000]}}].
+tc1(_) ->
+ ct:comment("TO after 2 sec"),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc2() ->
+ [{timetrap,fun() -> timetrap_utils:timetrap_val(500) end}].
+tc2(_) ->
+ ct:comment("TO after 0.5 sec"),
+ ct:sleep(1000),
+ ok.
+
+tc3(_) ->
+ ct:comment(io_lib:format("TO after ~w sec", [?TO])),
+ ct:sleep({seconds,5}),
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_5_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_5_SUITE.erl
new file mode 100644
index 0000000000..c5d4b5062e
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_5_SUITE.erl
@@ -0,0 +1,155 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(timetrap_5_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-define(TO, 1).
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap, fun() -> timetrap_utils:timetrap_val({seconds,?TO}) end}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: 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
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc0,tc1,tc2,tc3,tc4,tc5,tc6,tc7].
+
+tc0(_) ->
+ ct:comment(io_lib:format("TO after ~w sec", [?TO])),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc1() ->
+ [{timetrap,{timetrap_utils,timetrap_exit,[kaboom]}}].
+tc1(_) ->
+ exit(this_should_not_execute).
+
+tc2() ->
+ [{timetrap,fun() -> exit(kaboom) end}].
+tc2(_) ->
+ exit(this_should_not_execute).
+
+tc3() ->
+ [{timetrap,{timetrap_utils,timetrap_err_mfa,[]}}].
+tc3(_) ->
+ exit(this_should_not_execute).
+
+tc4() ->
+ [{timetrap,fun() -> timetrap_utils:timetrap_err_fun() end}].
+tc4(_) ->
+ exit(this_should_not_execute).
+
+tc5() ->
+ [{timetrap,{timetrap_utils,timetrap_timeout,[{seconds,40},
+ {seconds,1}]}}].
+tc5(_) ->
+ ct:comment("TO after 40+1 sec"),
+ ct:sleep({seconds,42}),
+ ok.
+
+tc6() ->
+ [{timetrap,fun() -> ct:sleep(6000), 1000 end}].
+tc6(_) ->
+ ct:comment("TO after 6+1 sec"),
+ ct:sleep({seconds,10}).
+
+tc7(_) ->
+ ct:comment(io_lib:format("TO after ~w sec", [?TO])),
+ ct:sleep({seconds,5}),
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_6_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_6_SUITE.erl
new file mode 100644
index 0000000000..90467ff752
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_6_SUITE.erl
@@ -0,0 +1,114 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(timetrap_6_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-define(TO, 1).
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap, fun() -> exit(kaboom) end}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: 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
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc0].
+
+tc0(_) ->
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_7_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_7_SUITE.erl
new file mode 100644
index 0000000000..b25b7770a7
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_7_SUITE.erl
@@ -0,0 +1,137 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(timetrap_7_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-define(TO, 1).
+-define(HANG, 6).
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{timetrap_utils,timetrap_timeout,[{seconds,?HANG},
+ {seconds,?TO}]}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: 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
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc0,tc1,tc2,tc3].
+
+tc0(_) ->
+ ct:comment(io_lib:format("TO after ~w+~w sec", [?HANG,?TO])),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc1() ->
+ [{timetrap,{timetrap_utils,timetrap_val,[2000]}}].
+tc1(_) ->
+ ct:comment("TO after 2 sec"),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc2() ->
+ [{timetrap,fun() -> timetrap_utils:timetrap_val(500) end}].
+tc2(_) ->
+ ct:comment("TO after 0.5 sec"),
+ ct:sleep(1000),
+ ok.
+
+tc3(_) ->
+ ct:comment(io_lib:format("TO after ~w+~w sec", [?HANG,?TO])),
+ ct:sleep({seconds,5}),
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_utils.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_utils.erl
new file mode 100644
index 0000000000..fcde6cd701
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_utils.erl
@@ -0,0 +1,43 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(timetrap_utils).
+
+-export([timetrap_val/1,
+ timetrap_err_fun/0,
+ timetrap_err_mfa/0,
+ timetrap_exit/1,
+ timetrap_timeout/2]).
+
+timetrap_val(Val) ->
+ Val.
+
+timetrap_err_fun() ->
+ fun() -> 5000 end.
+
+timetrap_err_mfa() ->
+ {?MODULE,timetrap_val,[5000]}.
+
+timetrap_exit(Reason) ->
+ exit(Reason).
+
+timetrap_timeout(Sleep, Val) ->
+ ct:sleep(Sleep),
+ Val.
+
diff --git a/lib/common_test/test/ct_event_handler_SUITE.erl b/lib/common_test/test/ct_event_handler_SUITE.erl
index 5ef04c0e75..b534a7141d 100644
--- a/lib/common_test/test/ct_event_handler_SUITE.erl
+++ b/lib/common_test/test/ct_event_handler_SUITE.erl
@@ -102,8 +102,9 @@ start_stop(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(start_stop,
- ct_test_support:reformat(Events, eh_A),
- ?config(priv_dir, Config)),
+ ct_test_support:reformat(Events, eh_A),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents =
[{eh_A,start_logging,{'DEF','RUNDIR'}},
@@ -148,8 +149,9 @@ results(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(results,
- ct_test_support:reformat(Events, eh_A),
- ?config(priv_dir, Config)),
+ ct_test_support:reformat(Events, eh_A),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents =
[{eh_A,start_logging,{'DEF','RUNDIR'}},
diff --git a/lib/common_test/test/ct_groups_test_1_SUITE.erl b/lib/common_test/test/ct_groups_test_1_SUITE.erl
index 7775d8a55d..e520a72227 100644
--- a/lib/common_test/test/ct_groups_test_1_SUITE.erl
+++ b/lib/common_test/test/ct_groups_test_1_SUITE.erl
@@ -89,8 +89,9 @@ groups_suite_1(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(groups_suite_1,
- reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(groups_suite_1),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -109,8 +110,9 @@ groups_suite_2(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(groups_suite_2,
- reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(groups_suite_2),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -130,8 +132,9 @@ groups_suites_1(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(groups_suites_1,
- reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(groups_suites_1),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -150,8 +153,9 @@ groups_dir_1(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(groups_dir_1,
- reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(groups_dir_1),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -170,8 +174,9 @@ groups_dirs_1(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(groups_dirs_1,
- reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(groups_dirs_1),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
diff --git a/lib/common_test/test/ct_groups_test_2_SUITE.erl b/lib/common_test/test/ct_groups_test_2_SUITE.erl
index 2ae63f4f99..940d791b15 100644
--- a/lib/common_test/test/ct_groups_test_2_SUITE.erl
+++ b/lib/common_test/test/ct_groups_test_2_SUITE.erl
@@ -59,7 +59,7 @@ end_per_testcase(TestCase, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [missing_conf, repeat_1].
+ [missing_conf, repeat_1, empty_group].
groups() ->
[].
@@ -83,13 +83,14 @@ missing_conf(Config) when is_list(Config) ->
Suite = filename:join(DataDir, "groups_1/missing_conf_SUITE"),
- {Opts,ERPid} = setup({suite,Suite}, Config),
+ {Opts,ERPid} = setup([{suite,Suite}], Config),
ok = ct_test_support:run(Opts, Config),
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(missing_conf_SUITE,
- reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(missing_conf),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -102,18 +103,41 @@ repeat_1(Config) when is_list(Config) ->
Suite = filename:join(DataDir, "groups_1/repeat_1_SUITE"),
- {Opts,ERPid} = setup({suite,Suite}, Config),
+ {Opts,ERPid} = setup([{suite,Suite}], Config),
ok = ct_test_support:run(Opts, Config),
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(repeat_1,
reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(repeat_1),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
%%%-----------------------------------------------------------------
+%%%
+
+empty_group(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ Suite = filename:join(DataDir, "groups_2/groups_22_SUITE"),
+
+ {Opts,ERPid} = setup([{suite,Suite},
+ {group,[test_group_8,test_group_9,test_group_10]}],
+ Config),
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(empty_group,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+
+ TestEvents = events_to_check(empty_group),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+%%%-----------------------------------------------------------------
%%% HELP FUNCTIONS
%%%-----------------------------------------------------------------
@@ -121,7 +145,7 @@ 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 ++ [Test,{event_handler,{?eh,EvHArgs}}],
+ Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}} | Test],
ERPid = ct_test_support:start_event_receiver(Config),
{Opts,ERPid}.
@@ -149,16 +173,14 @@ test_events(missing_conf) ->
{?eh,start_info,{1,1,2}},
{?eh,tc_start,{ct_framework,ct_init_per_group}},
{?eh,tc_done,{ct_framework,ct_init_per_group,ok}},
- {?eh,test_stats,{1,0,{0,0}}},
{?eh,tc_start,{missing_conf_SUITE,tc1}},
{?eh,tc_done,{missing_conf_SUITE,tc1,ok}},
- {?eh,test_stats,{2,0,{0,0}}},
+ {?eh,test_stats,{1,0,{0,0}}},
{?eh,tc_start,{missing_conf_SUITE,tc2}},
{?eh,tc_done,{missing_conf_SUITE,tc2,ok}},
- {?eh,test_stats,{3,0,{0,0}}},
+ {?eh,test_stats,{2,0,{0,0}}},
{?eh,tc_start,{ct_framework,ct_end_per_group}},
{?eh,tc_done,{ct_framework,ct_end_per_group,ok}},
- {?eh,test_stats,{4,0,{0,0}}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]}
];
@@ -256,4 +278,27 @@ test_events(repeat_1) ->
{?eh,tc_done,{repeat_1_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]}
+ ];
+
+test_events(empty_group) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,1}},
+ {?eh,tc_start,{groups_22_SUITE,init_per_suite}},
+ {?eh,tc_done,{groups_22_SUITE,init_per_suite,ok}},
+ [{?eh,tc_start,
+ {groups_22_SUITE,{init_per_group,test_group_8,[]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,{init_per_group,test_group_8,[]},ok}},
+ {?eh,tc_start,{groups_22_SUITE,testcase_8}},
+ {?eh,tc_done,{groups_22_SUITE,testcase_8,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,
+ {groups_22_SUITE,{end_per_group,test_group_8,[]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,{end_per_group,test_group_8,[]},ok}}],
+ {?eh,tc_start,{groups_22_SUITE,end_per_suite}},
+ {?eh,tc_done,{groups_22_SUITE,end_per_suite,init}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
].
diff --git a/lib/common_test/test/ct_groups_test_2_SUITE_data/groups_2/groups_22_SUITE.erl b/lib/common_test/test/ct_groups_test_2_SUITE_data/groups_2/groups_22_SUITE.erl
index cd517876df..154c676d7e 100644
--- a/lib/common_test/test/ct_groups_test_2_SUITE_data/groups_2/groups_22_SUITE.erl
+++ b/lib/common_test/test/ct_groups_test_2_SUITE_data/groups_2/groups_22_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
%%
%% The 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,27 +31,33 @@ suite() ->
groups() ->
[
- {test_group_1a, [shuffle], [testcase_1a,testcase_1b,testcase_1c]},
+ {test_group_1a, [shuffle], [testcase_1a,testcase_1b,testcase_1c]},
- {test_group_1b, [parallel], [testcase_1a,testcase_1b]},
+ {test_group_1b, [parallel], [testcase_1a,testcase_1b]},
- {test_group_2, [parallel], [testcase_2a,
+ {test_group_2, [parallel], [testcase_2a,
- {test_group_3, [{repeat,1}],
- [testcase_3a, testcase_3b]},
+ {test_group_3, [{repeat,1}],
+ [testcase_3a, testcase_3b]},
- testcase_2b]},
+ testcase_2b]},
- {test_group_4, [{test_group_5, [parallel], [testcase_5a,
+ {test_group_4, [{test_group_5, [parallel], [testcase_5a,
- {group, test_group_6},
+ {group, test_group_6},
- testcase_5b]}]},
+ testcase_5b]}]},
- {test_group_6, [parallel], [{group, test_group_7}]},
+ {test_group_6, [parallel], [{group, test_group_7}]},
- {test_group_7, [sequence], [testcase_7a,testcase_7b]}
- ].
+ {test_group_7, [sequence], [testcase_7a,testcase_7b]},
+
+ {test_group_8, [], [{group, test_group_9}, testcase_8]},
+
+ {test_group_9, [], []},
+
+ {test_group_10, [], [{group, test_group_9}]}
+ ].
all() ->
[{group, test_group_1a},
@@ -60,7 +66,10 @@ all() ->
testcase_2,
{group, test_group_2},
testcase_3,
- {group, test_group_4}].
+ {group, test_group_4},
+ {group, test_group_8},
+ {group, test_group_9},
+ {group, test_group_10}].
%% this func only for internal test purposes
grs_and_tcs() ->
@@ -68,7 +77,9 @@ grs_and_tcs() ->
test_group_1a, test_group_1b,
test_group_2, test_group_3,
test_group_4, test_group_5,
- test_group_6, test_group_7
+ test_group_6, test_group_7,
+ test_group_8, test_group_9,
+ test_group_10
],
[
testcase_1a, testcase_1b, testcase_1c,
@@ -78,7 +89,8 @@ grs_and_tcs() ->
testcase_3a, testcase_3b,
testcase_3,
testcase_5a, testcase_5b,
- testcase_7a, testcase_7b
+ testcase_7a, testcase_7b,
+ testcase_8
]}.
%%--------------------------------------------------------------------
@@ -107,7 +119,10 @@ init_per_group(Group, Config) ->
{test_group_4,[{name,test_group_4}]} -> ok;
{test_group_5,[{name,test_group_5},parallel]} -> "parallel";
{test_group_6,[{name,test_group_6},parallel]} -> "parallel";
- {test_group_7,[{name,test_group_7},sequence]} -> "sequence"
+ {test_group_7,[{name,test_group_7},sequence]} -> "sequence";
+ {test_group_8,[{name,test_group_8}]} -> ok;
+ {test_group_9,[{name,test_group_9}]} -> ok;
+ {test_group_10,[{name,test_group_10}]} -> ok
end,
{Grs,_} = grs_and_tcs(),
case lists:member(Group, Grs) of
@@ -312,3 +327,7 @@ testcase_7b(Config) ->
undefined = ?config(testcase_7a,Config),
testcase_7b = ?config(testcase_7b,Config),
ok.
+testcase_8() ->
+ [].
+testcase_8(_Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_hooks_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE.erl
index 64f4e277ff..5c99f0f9f7 100644
--- a/lib/common_test/test/ct_hooks_SUITE.erl
+++ b/lib/common_test/test/ct_hooks_SUITE.erl
@@ -79,10 +79,11 @@ all(suite) ->
scope_per_suite_cth, scope_per_group_cth, scope_suite_cth,
scope_per_suite_state_cth, scope_per_group_state_cth,
scope_suite_state_cth,
- fail_pre_suite_cth, fail_post_suite_cth, skip_pre_suite_cth,
+ fail_pre_suite_cth, double_fail_pre_suite_cth,
+ fail_post_suite_cth, skip_pre_suite_cth,
skip_post_suite_cth, recover_post_suite_cth, update_config_cth,
state_update_cth, options_cth, same_id_cth,
- fail_n_skip_with_minimal_cth
+ fail_n_skip_with_minimal_cth, prio_cth
]
)
.
@@ -167,6 +168,11 @@ fail_pre_suite_cth(Config) when is_list(Config) ->
do_test(fail_pre_suite_cth, "ct_cth_empty_SUITE.erl",
[fail_pre_suite_cth],Config).
+double_fail_pre_suite_cth(Config) when is_list(Config) ->
+ do_test(double_fail_pre_suite_cth, "{ct_scope_suite_crash_in_cth_SUITE.erl,"
+ "ct_scope_suite_cth_SUITE.erl}",
+ [],Config).
+
fail_post_suite_cth(Config) when is_list(Config) ->
do_test(fail_post_suite_cth, "ct_cth_empty_SUITE.erl",
[fail_post_suite_cth],Config).
@@ -203,6 +209,11 @@ fail_n_skip_with_minimal_cth(Config) when is_list(Config) ->
do_test(fail_n_skip_with_minimal_cth, "ct_cth_fail_one_skip_one_SUITE.erl",
[minimal_terminate_cth],Config).
+prio_cth(Config) when is_list(Config) ->
+ do_test(prio_cth, "ct_cth_prio_SUITE.erl",
+ [{empty_cth,[1000],1000},{empty_cth,[900],900},
+ {prio_cth,[1100,100],100},{prio_cth,[1100]}],Config).
+
%%%-----------------------------------------------------------------
%%% HELP FUNCTIONS
%%%-----------------------------------------------------------------
@@ -225,8 +236,9 @@ do_test(Tag, SuiteWildCard, CTHs, Config, Res, EC) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(Tag,
- reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(Tag, EC),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -259,9 +271,9 @@ events_to_check(Test, N) ->
test_events(one_empty_cth) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,cth,{empty_cth,id,[[]]}},
{?eh,cth,{empty_cth,init,[{'_','_','_'},[]]}},
- {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}},
{?eh,cth,{empty_cth,pre_init_per_suite,
[ct_cth_empty_SUITE,'$proplist',[]]}},
@@ -287,11 +299,11 @@ test_events(one_empty_cth) ->
test_events(two_empty_cth) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,cth,{'_',id,[[]]}},
- {?eh,cth,{'_',init,['_',[]]}},
{?eh,cth,{'_',id,[[]]}},
{?eh,cth,{'_',init,['_',[]]}},
- {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{'_',init,['_',[]]}},
{?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}},
{?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}},
{?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}},
@@ -329,8 +341,8 @@ test_events(faulty_cth_no_init) ->
test_events(faulty_cth_id_no_init) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
- {?eh,cth,{'_',id,[[]]}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{'_',id,[[]]}},
{negative,{?eh,tc_start,'_'},
{?eh,test_done,{'DEF','STOP_TIME'}}},
{?eh,stop_logging,[]}
@@ -339,9 +351,9 @@ test_events(faulty_cth_id_no_init) ->
test_events(minimal_cth) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{negative,{?eh,cth,{'_',id,['_',[]]}},
{?eh,cth,{'_',init,['_',[]]}}},
- {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}},
{?eh,tc_done,{ct_cth_empty_SUITE,init_per_suite,ok}},
@@ -357,11 +369,11 @@ test_events(minimal_cth) ->
test_events(minimal_and_maximal_cth) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{'_',id,[[]]}},
{negative,{?eh,cth,{'_',id,['_',[]]}},
{?eh,cth,{'_',init,['_',[]]}}},
- {?eh,cth,{'_',id,[[]]}},
{?eh,cth,{'_',init,['_',[]]}},
- {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}},
{?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}},
{?eh,cth,{'_',post_init_per_suite,[ct_cth_empty_SUITE,'$proplist','$proplist',[]]}},
@@ -387,8 +399,8 @@ test_events(faulty_cth_undef) ->
{failed,FailReasonStr}},
[
{?eh,start_logging,{'DEF','RUNDIR'}},
- {?eh,cth,{'_',init,['_',[]]}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{'_',init,['_',[]]}},
{?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}},
{?eh,tc_done,{ct_cth_empty_SUITE,init_per_suite,
{failed, {error,FailReasonStr}}}},
@@ -433,15 +445,15 @@ test_events(faulty_cth_exit_in_init_scope_suite) ->
test_events(faulty_cth_exit_in_init) ->
[{?eh,start_logging,{'DEF','RUNDIR'}},
- {?eh,cth,{empty_cth,init,['_',[]]}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{empty_cth,init,['_',[]]}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]}];
test_events(faulty_cth_exit_in_id) ->
[{?eh,start_logging,{'DEF','RUNDIR'}},
- {?eh,cth,{empty_cth,id,[[]]}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{empty_cth,id,[[]]}},
{negative, {?eh,tc_start,'_'},
{?eh,test_done,{'DEF','STOP_TIME'}}},
{?eh,stop_logging,[]}];
@@ -609,9 +621,8 @@ test_events(scope_per_group_state_cth) ->
test_events(fail_pre_suite_cth) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
- {?eh,cth,{'_',init,['_',[]]}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
-
+ {?eh,cth,{'_',init,['_',[]]}},
{?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}},
{?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}},
@@ -646,11 +657,28 @@ test_events(fail_pre_suite_cth) ->
{?eh,stop_logging,[]}
];
-test_events(fail_post_suite_cth) ->
+test_events(double_fail_pre_suite_cth) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,tc_start,{'_',init_per_suite}},
+ {?eh,cth,{'_',init,['_',[]]}},
+ {?eh,cth,{'_',pre_init_per_suite,['_','$proplist',[]]}},
+ {?eh,cth,{'_',post_init_per_suite,['_','$proplist',
+ {fail,"Test failure"},[]]}},
+ {?eh,cth, {empty_cth,terminate,[[]]}},
+
+ {?eh,tc_start,{'_',init_per_suite}},
{?eh,cth,{'_',init,['_',[]]}},
+ {?eh,cth, {empty_cth,terminate,[[]]}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(fail_post_suite_cth) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{'_',init,['_',[]]}},
{?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}},
{?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}},
{?eh,cth,{'_',post_init_per_suite,[ct_cth_empty_SUITE,'$proplist','$proplist',[]]}},
@@ -676,8 +704,8 @@ test_events(fail_post_suite_cth) ->
test_events(skip_pre_suite_cth) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
- {?eh,cth,{'_',init,['_',[]]}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{'_',init,['_',[]]}},
{?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}},
{?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}},
{?eh,cth,{'_',post_init_per_suite,[ct_cth_empty_SUITE,'$proplist',{skip,"Test skip"},[]]}},
@@ -699,8 +727,8 @@ test_events(skip_pre_suite_cth) ->
test_events(skip_post_suite_cth) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
- {?eh,cth,{'_',init,['_',[]]}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{'_',init,['_',[]]}},
{?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}},
{?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}},
@@ -724,8 +752,8 @@ test_events(recover_post_suite_cth) ->
Suite = ct_cth_fail_per_suite_SUITE,
[
{?eh,start_logging,'_'},
- {?eh,cth,{'_',init,['_',[]]}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{'_',init,['_',[]]}},
{?eh,tc_start,{Suite,init_per_suite}},
{?eh,cth,{'_',pre_init_per_suite,[Suite,'$proplist','$proplist']}},
{?eh,cth,{'_',post_init_per_suite,[Suite,contains([tc_status]),
@@ -753,8 +781,8 @@ test_events(recover_post_suite_cth) ->
test_events(update_config_cth) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
- {?eh,cth,{'_',init,['_',[]]}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{'_',init,['_',[]]}},
{?eh,tc_start,{ct_update_config_SUITE,init_per_suite}},
{?eh,cth,{'_',pre_init_per_suite,
@@ -864,9 +892,9 @@ test_events(update_config_cth) ->
test_events(state_update_cth) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,cth,{'_',init,['_',[]]}},
{?eh,cth,{'_',init,['_',[]]}},
- {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,tc_start,{'_',init_per_suite}},
{?eh,tc_done,{'_',end_per_suite,ok}},
@@ -902,8 +930,8 @@ test_events(state_update_cth) ->
test_events(options_cth) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
- {?eh,cth,{empty_cth,init,['_',[test]]}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{empty_cth,init,['_',[test]]}},
{?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}},
{?eh,cth,{empty_cth,pre_init_per_suite,
[ct_cth_empty_SUITE,'$proplist',[test]]}},
@@ -929,10 +957,10 @@ test_events(options_cth) ->
test_events(same_id_cth) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,cth,{'_',id,[[]]}},
- {?eh,cth,{'_',init,[same_id_cth,[]]}},
{?eh,cth,{'_',id,[[]]}},
- {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{'_',init,[same_id_cth,[]]}},
{?eh,tc_start,{ct_cth_empty_SUITE,init_per_suite}},
{?eh,cth,{'_',pre_init_per_suite,[ct_cth_empty_SUITE,'$proplist',[]]}},
{negative,
@@ -969,8 +997,8 @@ test_events(same_id_cth) ->
test_events(fail_n_skip_with_minimal_cth) ->
[{?eh,start_logging,{'DEF','RUNDIR'}},
- {?eh,cth,{'_',init,['_',[]]}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,cth,{'_',init,['_',[]]}},
{?eh,tc_start,{'_',init_per_suite}},
{?eh,tc_done,{'_',end_per_suite,ok}},
@@ -978,6 +1006,73 @@ test_events(fail_n_skip_with_minimal_cth) ->
{?eh,stop_logging,[]}
];
+test_events(prio_cth) ->
+
+ GenPre = fun(Func,States) ->
+ [{?eh,cth,{'_',Func,['_','_',State]}} ||
+ State <- States]
+ end,
+
+ GenPost = fun(Func,States) ->
+ [{?eh,cth,{'_',Func,['_','_','_',State]}} ||
+ State <- States]
+ end,
+
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}] ++
+
+ [{?eh,tc_start,{ct_cth_prio_SUITE,init_per_suite}}] ++
+ GenPre(pre_init_per_suite,
+ [[1100,100],[800],[900],[1000],[1200,1050],[1100],[1200]]) ++
+ GenPost(post_init_per_suite,
+ [[1100,100],[600,200],[600,600],[700],[800],[900],[1000],
+ [1200,1050],[1100],[1200]]) ++
+ [{?eh,tc_done,{ct_cth_prio_SUITE,init_per_suite,ok}},
+
+
+ [{?eh,tc_start,{ct_cth_prio_SUITE,{init_per_group,'_',[]}}}] ++
+ GenPre(pre_init_per_group,
+ [[1100,100],[600,200],[600,600],[700],[800],
+ [900],[1000],[1200,1050],[1100],[1200]]) ++
+ GenPost(post_init_per_group,
+ [[1100,100],[600,200],[600,600],[600],[700],[800],
+ [900],[900,900],[500,900],[1000],[1200,1050],
+ [1100],[1200]]) ++
+ [{?eh,tc_done,{ct_cth_prio_SUITE,{init_per_group,'_',[]},ok}}] ++
+
+ [{?eh,tc_start,{ct_cth_prio_SUITE,test_case}}] ++
+ GenPre(pre_init_per_testcase,
+ [[1100,100],[600,200],[600,600],[600],[700],[800],
+ [900],[900,900],[500,900],[1000],[1200,1050],
+ [1100],[1200]]) ++
+ GenPost(post_end_per_testcase,
+ [[1100,100],[600,200],[600,600],[600],[700],[800],
+ [900],[900,900],[500,900],[1000],[1200,1050],
+ [1100],[1200]]) ++
+ [{?eh,tc_done,{ct_cth_prio_SUITE,test_case,ok}},
+
+ {?eh,tc_start,{ct_cth_prio_SUITE,{end_per_group,'_',[]}}}] ++
+ GenPre(pre_end_per_group,
+ [[1100,100],[600,200],[600,600],[600],[700],[800],
+ [900],[900,900],[500,900],[1000],[1200,1050],
+ [1100],[1200]]) ++
+ GenPost(post_end_per_group,
+ [[1100,100],[600,200],[600,600],[600],[700],[800],
+ [900],[900,900],[500,900],[1000],[1200,1050],
+ [1100],[1200]]) ++
+ [{?eh,tc_done,{ct_cth_prio_SUITE,{end_per_group,'_',[]},ok}}],
+
+ {?eh,tc_start,{ct_cth_prio_SUITE,end_per_suite}}] ++
+ GenPre(pre_end_per_suite,
+ [[1100,100],[600,200],[600,600],[700],[800],[900],[1000],
+ [1200,1050],[1100],[1200]]) ++
+ GenPost(post_end_per_suite,
+ [[1100,100],[600,200],[600,600],[700],[800],[900],[1000],
+ [1200,1050],[1100],[1200]]) ++
+ [{?eh,tc_done,{ct_cth_prio_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
test_events(ok) ->
ok.
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_prio_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_prio_SUITE.erl
new file mode 100644
index 0000000000..d564398cd0
--- /dev/null
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_cth_prio_SUITE.erl
@@ -0,0 +1,62 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(ct_cth_prio_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include("ct.hrl").
+
+suite() ->
+ ([{timetrap, {minutes, 10}},
+ {ct_hooks, [{empty_cth,[800],800},
+ {prio_cth,[1200]},{prio_cth,[1200,1050],1050}]}]).
+
+%% Test server callback functions
+init_per_suite(Config) ->
+ [{ct_hooks, [{empty_cth,[700],700},
+ {prio_cth,[600,600]},
+ {prio_cth,[600,200],200}]}|Config].
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_G, Config) ->
+ [{ct_hooks, [{empty_cth,[600],600},
+ {prio_cth,[900,900]},{prio_cth,[500,900],900}]}|Config].
+
+end_per_group(_G, _Config) ->
+ ok.
+
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+all() ->
+ [{group,test_group}].
+
+groups() ->
+ [{test_group,[],[test_case]}].
+
+%% Test cases starts here.
+test_case(Config) when is_list(Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_suite_crash_in_cth_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_suite_crash_in_cth_SUITE.erl
new file mode 100644
index 0000000000..5aa6b0132d
--- /dev/null
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_suite_crash_in_cth_SUITE.erl
@@ -0,0 +1,50 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(ct_scope_suite_crash_in_cth_SUITE).
+
+-suite_defaults([{timetrap, {minutes, 10}}]).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include("ct.hrl").
+
+%% Test server callback functions
+suite() ->
+ [{ct_hooks,[fail_pre_suite_cth]}].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+all() ->
+ [test_case].
+
+%% Test cases starts here.
+test_case(Config) when is_list(Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl
index ebebfd18a9..7befcfa57c 100644
--- a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl
@@ -59,8 +59,7 @@
-include_lib("common_test/src/ct_util.hrl").
-include_lib("common_test/include/ct_event.hrl").
--type proplist() :: list({atom(),term()}).
--type config() :: proplist().
+-type config() :: proplists:proplist().
-type reason() :: term().
-type skip_or_fail() :: {skip, reason()} |
{auto_skip, reason()} |
@@ -71,17 +70,17 @@
%% @doc Always called before any other callback function. Use this to initiate
%% any common state. It should return an state for this CTH.
--spec init(Id :: term(), Opts :: proplist()) ->
- State :: #state{}.
+-spec init(Id :: term(), Opts :: proplists:proplist()) ->
+ {ok, State :: #state{}}.
init(Id, Opts) ->
gen_event:notify(?CT_EVMGR_REF, #event{ name = cth, node = node(),
data = {?MODULE, init, [Id, Opts]}}),
- Opts.
+ {ok,Opts}.
%% @doc The ID is used to uniquly identify an CTH instance, if two CTH's
%% return the same ID the seconds CTH is ignored. This function should NOT
%% have any side effects as it might be called multiple times by common test.
--spec id(Opts :: proplist()) ->
+-spec id(Opts :: proplists:proplist()) ->
Id :: term().
id(Opts) ->
gen_event:notify(?CT_EVMGR_REF, #event{ name = cth, node = node(),
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/prio_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/prio_cth.erl
new file mode 100644
index 0000000000..82511ab0d3
--- /dev/null
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/prio_cth.erl
@@ -0,0 +1,74 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(prio_cth).
+
+
+-include_lib("common_test/src/ct_util.hrl").
+
+
+%% CT Hooks
+-compile(export_all).
+
+id(Opts) ->
+ empty_cth:id(Opts).
+
+init(Id, Opts) ->
+ {ok, [Prio|_] = State} = empty_cth:init(Id, Opts),
+ {ok, State, Prio}.
+
+pre_init_per_suite(Suite, Config, State) ->
+ empty_cth:pre_init_per_suite(Suite,Config,State).
+
+post_init_per_suite(Suite,Config,Return,State) ->
+ empty_cth:post_init_per_suite(Suite,Config,Return,State).
+
+pre_end_per_suite(Suite,Config,State) ->
+ empty_cth:pre_end_per_suite(Suite,Config,State).
+
+post_end_per_suite(Suite,Config,Return,State) ->
+ empty_cth:post_end_per_suite(Suite,Config,Return,State).
+
+pre_init_per_group(Group,Config,State) ->
+ empty_cth:pre_init_per_group(Group,Config,State).
+
+post_init_per_group(Group,Config,Return,State) ->
+ empty_cth:post_init_per_group(Group,Config,Return,State).
+
+pre_end_per_group(Group,Config,State) ->
+ empty_cth:pre_end_per_group(Group,Config,State).
+
+post_end_per_group(Group,Config,Return,State) ->
+ empty_cth:post_end_per_group(Group,Config,Return,State).
+
+pre_init_per_testcase(TC,Config,State) ->
+ empty_cth:pre_init_per_testcase(TC,Config,State).
+
+post_end_per_testcase(TC,Config,Return,State) ->
+ empty_cth:post_end_per_testcase(TC,Config,Return,State).
+
+on_tc_fail(TC, Reason, State) ->
+ empty_cth:on_tc_fail(TC,Reason,State).
+
+on_tc_skip(TC, Reason, State) ->
+ empty_cth:on_tc_skip(TC,Reason,State).
+
+terminate(State) ->
+ empty_cth:terminate(State).
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/state_update_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/state_update_cth.erl
index 35c990c0be..9da48d3a4c 100644
--- a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/state_update_cth.erl
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/state_update_cth.erl
@@ -29,7 +29,7 @@
init(Id, Opts) ->
State = empty_cth:init(Id, Opts),
- [init|State].
+ {ok, [init|State]}.
pre_init_per_suite(Suite, Config, State) ->
empty_cth:pre_init_per_suite(Suite,Config,State),
diff --git a/lib/common_test/test/ct_master_SUITE.erl b/lib/common_test/test/ct_master_SUITE.erl
index e89b6f7de6..1471cc1e0c 100644
--- a/lib/common_test/test/ct_master_SUITE.erl
+++ b/lib/common_test/test/ct_master_SUITE.erl
@@ -119,8 +119,9 @@ ct_master_test(Config) when is_list(Config)->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(groups_suite_1,
- reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ reformat(Events, ?eh),
+ PrivDir, []),
+
find_events(NodeNames, [{tc_start,{master_SUITE,init_per_suite}},
{tc_start,{master_SUITE,first_testcase}},
{tc_start,{master_SUITE,second_testcase}},
@@ -174,7 +175,7 @@ make_spec(DataDir, FileName, NodeNames, Suites, Config)->
ct_test_support:write_testspec(N++Include++EH++C++S++LD++NS, FileName).
-get_log_dir({win32,_},PrivDir, NodeName)->
+get_log_dir({win32,_}, _PrivDir, NodeName)->
case filelib:is_dir(?TEMP_DIR) of
false ->
file:make_dir(?TEMP_DIR);
diff --git a/lib/common_test/test/ct_misc_1_SUITE.erl b/lib/common_test/test/ct_misc_1_SUITE.erl
index a8bd2c2189..cb17af9ab5 100644
--- a/lib/common_test/test/ct_misc_1_SUITE.erl
+++ b/lib/common_test/test/ct_misc_1_SUITE.erl
@@ -111,7 +111,8 @@ beam_me_up(Config) when is_list(Config) ->
ct_test_support:log_events(beam_me_up,
reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(beam_me_up, 1),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
diff --git a/lib/common_test/test/ct_repeat_1_SUITE.erl b/lib/common_test/test/ct_repeat_1_SUITE.erl
index e674315526..090002d0c2 100644
--- a/lib/common_test/test/ct_repeat_1_SUITE.erl
+++ b/lib/common_test/test/ct_repeat_1_SUITE.erl
@@ -159,7 +159,8 @@ execute(TestCase, SuiteName, Group, Config) ->
ct_test_support:log_events(TestCase,
reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(TestCase),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -559,13 +560,7 @@ test_events(repeat_cs_until_any_fail) ->
{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}]}}}}},
+ {{badmatch,2},'_'}}}}},
{?eh,test_stats,{5,2,{0,0}}},
{?eh,tc_start,{repeat_1_SUITE,tc_fail_2}},
{?eh,tc_done,
diff --git a/lib/common_test/test/ct_sequence_1_SUITE.erl b/lib/common_test/test/ct_sequence_1_SUITE.erl
index c7650b169c..5facf90656 100644
--- a/lib/common_test/test/ct_sequence_1_SUITE.erl
+++ b/lib/common_test/test/ct_sequence_1_SUITE.erl
@@ -132,7 +132,8 @@ execute(TestCase, SuiteName, Group, Config) ->
ct_test_support:log_events(TestCase,
reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(TestCase),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
diff --git a/lib/common_test/test/ct_skip_SUITE.erl b/lib/common_test/test/ct_skip_SUITE.erl
index 62c5f10b7c..b8be55f43a 100644
--- a/lib/common_test/test/ct_skip_SUITE.erl
+++ b/lib/common_test/test/ct_skip_SUITE.erl
@@ -99,8 +99,9 @@ auto_skip(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(auto_skip,
- reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(auto_skip),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -122,8 +123,9 @@ user_skip(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(user_skip,
- reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(user_skip),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -195,7 +197,7 @@ test_events(auto_skip) ->
{?eh,tc_done,
{auto_skip_3_SUITE,tc1,
{skipped,{failed,{auto_skip_3_SUITE,init_per_testcase,
- {init_per_testcase,tc1,failed}}}}}},
+ {{init_per_testcase,tc1,failed},'_'}}}}}},
{?eh,test_stats,{0,0,{0,4}}},
{?eh,tc_start,{auto_skip_3_SUITE,tc2}},
{?eh,tc_done,{auto_skip_3_SUITE,tc2,ok}},
@@ -362,12 +364,7 @@ test_events(auto_skip) ->
{?eh,tc_done,
{auto_skip_9_SUITE,tc8,
{skipped,{failed,{auto_skip_9_SUITE,init_per_testcase,
- {{badmatch,undefined},
- [{auto_skip_9_SUITE,init_per_testcase,2},
- {test_server,my_apply,3},
- {test_server,init_per_testcase,3},
- {test_server,run_test_case_eval1,6},
- {test_server,run_test_case_eval,8}]}}}}}},
+ {{badmatch,undefined},'_'}}}}}},
{?eh,tc_start,
{auto_skip_9_SUITE,{end_per_group,g5,[parallel]}}},
{?eh,tc_done,
diff --git a/lib/common_test/test/ct_smoke_test_SUITE.erl b/lib/common_test/test/ct_smoke_test_SUITE.erl
index c3d49a5afa..49b38361e2 100644
--- a/lib/common_test/test/ct_smoke_test_SUITE.erl
+++ b/lib/common_test/test/ct_smoke_test_SUITE.erl
@@ -175,8 +175,9 @@ dir1(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(dir1,
- ct_test_support:reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(dir1),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -204,8 +205,9 @@ dir2(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(dir2,
- ct_test_support:reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(dir2),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -234,8 +236,9 @@ dir1_2(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(dir1_2,
- ct_test_support:reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(dir1_2),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -264,8 +267,8 @@ suite11(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(suite11,
- ct_test_support:reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config), Opts),
TestEvents = events_to_check(suite11),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -293,8 +296,8 @@ suite21(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(suite21,
- ct_test_support:reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config), Opts),
TestEvents = events_to_check(suite21),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -324,8 +327,8 @@ suite11_21(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(suite11_21,
- ct_test_support:reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config), Opts),
TestEvents = events_to_check(suite11_21),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -355,8 +358,8 @@ tc111(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(tc111,
- ct_test_support:reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config), Opts),
TestEvents = events_to_check(tc111),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -385,8 +388,8 @@ tc211(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(tc211,
- ct_test_support:reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config), Opts),
TestEvents = events_to_check(tc211),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -416,8 +419,8 @@ tc111_112(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(tc111_112,
- ct_test_support:reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config), Opts),
TestEvents = events_to_check(tc111_112),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
diff --git a/lib/common_test/test/ct_test_server_if_1_SUITE.erl b/lib/common_test/test/ct_test_server_if_1_SUITE.erl
index 9d3e6a9e59..4471915e69 100644
--- a/lib/common_test/test/ct_test_server_if_1_SUITE.erl
+++ b/lib/common_test/test/ct_test_server_if_1_SUITE.erl
@@ -98,8 +98,9 @@ ts_if_1(Config) when is_list(Config) ->
Events = ct_test_support:get_events(ERPid, Config),
ct_test_support:log_events(ts_if_1,
- reformat(Events, ?eh),
- PrivDir),
+ reformat(Events, ?eh),
+ PrivDir,
+ Opts),
TestEvents = events_to_check(ts_if_1),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
diff --git a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl
index 47cea190dd..bda7d91161 100644
--- a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl
+++ b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl
@@ -143,7 +143,7 @@ tc1(_) ->
exit(should_have_been_skipped).
tc2(_) ->
- exit(should_have_been_skipped).
+ timeout_in_end_per_testcase.
tc3(_) ->
timer:sleep(5000).
diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl
index b4f1a0e71f..6df02d12b7 100644
--- a/lib/common_test/test/ct_test_support.erl
+++ b/lib/common_test/test/ct_test_support.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The 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,8 +23,8 @@
%%%
-module(ct_test_support).
--include_lib("test_server/include/test_server.hrl").
-include_lib("common_test/include/ct_event.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([init_per_suite/1, init_per_suite/2, end_per_suite/1,
init_per_testcase/2, end_per_testcase/2,
@@ -32,7 +32,8 @@
run/2, run/4, get_opts/1, wait_for_ct_stop/1]).
-export([handle_event/2, start_event_receiver/1, get_events/2,
- verify_events/3, reformat/2, log_events/3]).
+ verify_events/3, reformat/2, log_events/4,
+ join_abs_dirs/2]).
-include_lib("kernel/include/file.hrl").
@@ -45,9 +46,10 @@ init_per_suite(Config) ->
init_per_suite(Config, Level) ->
case os:type() of
{win32, _} ->
- %% Extend timeout for windows as starting node
+ %% Extend timeout to 1 hour for windows as starting node
%% can take a long time there
- test_server:timetrap( 120000 * test_server:timetrap_scale_factor());
+ test_server:timetrap( 60*60*1000 *
+ test_server:timetrap_scale_factor());
_ ->
ok
end,
@@ -63,7 +65,6 @@ init_per_suite(Config, Level) ->
start_slave(Config,Level) ->
[_,Host] = string:tokens(atom_to_list(node()), "@"),
-
test_server:format(0, "Trying to start ~s~n", ["ct@"++Host]),
case slave:start(Host, ct, []) of
{error,Reason} ->
@@ -72,18 +73,19 @@ start_slave(Config,Level) ->
test_server:format(0, "Node ~p started~n", [CTNode]),
IsCover = test_server:is_cover(),
if IsCover ->
- cover:start(CTNode);
- true->
- ok
+ cover:start(CTNode);
+ true->
+ ok
end,
- DataDir = ?config(data_dir, Config),
- PrivDir = ?config(priv_dir, Config),
+
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
%% PrivDir as well as directory of Test Server suites
%% have to be in code path on Common Test node.
[_ | Parts] = lists:reverse(filename:split(DataDir)),
TSDir = filename:join(lists:reverse(Parts)),
- AddPathDirs = case ?config(path_dirs, Config) of
+ AddPathDirs = case proplists:get_value(path_dirs, Config) of
undefined -> [];
Ds -> Ds
end,
@@ -110,8 +112,8 @@ start_slave(Config,Level) ->
%%% end_per_suite/1
end_per_suite(Config) ->
- CTNode = ?config(ct_node, Config),
- PrivDir = ?config(priv_dir, Config),
+ CTNode = proplists:get_value(ct_node, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
true = rpc:call(CTNode, code, del_path, [filename:join(PrivDir,"")]),
cover:stop(CTNode),
slave:stop(CTNode),
@@ -121,7 +123,9 @@ end_per_suite(Config) ->
%%% init_per_testcase/2
init_per_testcase(_TestCase, Config) ->
- {_,{_,LogDir}} = lists:keysearch(logdir, 1, get_opts(Config)),
+ Opts = get_opts(Config),
+ NetDir = proplists:get_value(net_dir, Opts),
+ LogDir = join_abs_dirs(NetDir, proplists:get_value(logdir, Opts)),
case lists:keysearch(master, 1, Config) of
false->
test_server:format("See Common Test logs here:\n\n"
@@ -139,7 +143,7 @@ init_per_testcase(_TestCase, Config) ->
%%% end_per_testcase/2
end_per_testcase(_TestCase, Config) ->
- CTNode = ?config(ct_node, Config),
+ CTNode = proplists:get_value(ct_node, Config),
case wait_for_ct_stop(CTNode) of
%% Common test was not stopped to we restart node.
false ->
@@ -169,7 +173,7 @@ write_testspec(TestSpec, TSFile) ->
%%%
get_opts(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
TempDir = case os:getenv("TMP") of
false ->
case os:getenv("TEMP") of
@@ -195,20 +199,48 @@ get_opts(Config) ->
_ ->
TempDir
end,
- InitOpts = ?config(ct_opts, Config),
- [{logdir,LogDir} | InitOpts].
+
+ %% Copy test variables to app environment on new node
+ CtTestVars =
+ case init:get_argument(ct_test_vars) of
+ {ok,[Vars]} ->
+ [begin {ok,Ts,_} = erl_scan:string(Str++"."),
+ {ok,Expr} = erl_parse:parse_term(Ts),
+ Expr
+ end || Str <- Vars];
+ _ ->
+ []
+ end,
+ %% test_server:format("Test variables added to Config: ~p\n\n",
+ %% [CtTestVars]),
+ InitOpts =
+ case proplists:get_value(ct_opts, Config) of
+ undefined -> [];
+ CtOpts -> CtOpts
+ end,
+ [{logdir,LogDir} | InitOpts ++ CtTestVars].
%%%-----------------------------------------------------------------
%%%
run(Opts, Config) ->
- CTNode = ?config(ct_node, Config),
- Level = ?config(trace_level, Config),
+ CTNode = proplists:get_value(ct_node, Config),
+ Level = proplists:get_value(trace_level, Config),
%% use ct interface
test_server:format(Level, "~n[RUN #1] Calling ct:run_test(~p) on ~p~n",
[Opts, CTNode]),
Result1 = rpc:call(CTNode, ct, run_test, [Opts]),
+ case rpc:call(CTNode, erlang, whereis, [ct_util_server]) of
+ undefined ->
+ ok;
+ _ ->
+ test_server:format(Level,
+ "ct_util_server not stopped on ~p yet, waiting 5 s...~n",
+ [CTNode]),
+ timer:sleep(5000),
+ undefined = rpc:call(CTNode, erlang, whereis, [ct_util_server])
+ end,
%% use run_test interface (simulated)
test_server:format(Level, "Saving start opts on ~p: ~p~n", [CTNode,Opts]),
rpc:call(CTNode, application, set_env, [common_test, run_test_start_opts, Opts]),
@@ -224,8 +256,8 @@ run(Opts, Config) ->
end.
run(M, F, A, Config) ->
- CTNode = ?config(ct_node, Config),
- Level = ?config(trace_level, Config),
+ CTNode = proplists:get_value(ct_node, Config),
+ Level = proplists:get_value(trace_level, Config),
test_server:format(Level, "~nCalling ~w:~w(~p) on ~p~n",
[M, F, A, CTNode]),
rpc:call(CTNode, M, F, A).
@@ -261,11 +293,11 @@ handle_event(EH, Event) ->
ok.
start_event_receiver(Config) ->
- CTNode = ?config(ct_node, Config),
+ CTNode = proplists:get_value(ct_node, Config),
spawn_link(CTNode, fun() -> er() end).
get_events(_, Config) ->
- CTNode = ?config(ct_node, Config),
+ CTNode = proplists:get_value(ct_node, Config),
{event_receiver,CTNode} ! {self(),get_events},
Events = receive {event_receiver,Evs} -> Evs end,
{event_receiver,CTNode} ! stop,
@@ -288,7 +320,7 @@ er_loop(Evs) ->
end.
verify_events(TEvs, Evs, Config) ->
- Node = ?config(ct_node, Config),
+ Node = proplists:get_value(ct_node, Config),
case catch verify_events1(TEvs, Evs, Node, Config) of
{'EXIT',Reason} ->
Reason;
@@ -349,10 +381,15 @@ locate(TEvs, Node, Evs, Config) when is_list(TEvs) ->
data={M,{init_per_group,GroupName,Props}}}},
{TEH,#event{name=tc_done,
node=Node,
- data={M,{init_per_group,GroupName,Props},R}}} | Evs1] ->
- test_server:format("Found ~p!", [InitStart]),
- test_server:format("Found ~p!", [InitDone]),
- verify_events1(TEvs1, Evs1, Node, Config);
+ data={M,{init_per_group,GroupName,Props},Res}}} | Evs1] ->
+ case result_match(R, Res) of
+ false ->
+ nomatch;
+ true ->
+ test_server:format("Found ~p!", [InitStart]),
+ test_server:format("Found ~p!", [InitDone]),
+ verify_events1(TEvs1, Evs1, Node, Config)
+ end;
_ ->
nomatch
end;
@@ -384,9 +421,11 @@ locate({parallel,TEvs}, Node, Evs, Config) ->
EvProps},EvR}}})
when TEH == EH, EvNode == Node, EvM == M,
EvGroupName == GroupName,
- EvProps == Props,
- EvR == R ->
- false;
+ EvProps == Props ->
+ case result_match(R, EvR) of
+ true -> false;
+ false -> true
+ end;
({EH,#event{name=stop_logging,
node=EvNode,data=_}})
when EH == TEH, EvNode == Node ->
@@ -466,7 +505,7 @@ locate({parallel,TEvs}, Node, Evs, Config) ->
node=EvNode,
data={Mod,Func,Result}}} <- Done,
EH == TEH, EvNode == Node, Mod == M,
- Func == F, Result == R] of
+ Func == F, result_match(R, Result)] of
[TcDone|_] ->
test_server:format("Found ~p!", [TEv]),
{lists:delete(TcDone, Done),RemEvs,RemSize};
@@ -509,8 +548,13 @@ locate({parallel,TEvs}, Node, Evs, Config) ->
data={Mod,{end_per_group,
EvGName,EvProps},Res}}}) when
EH == TEH, EvNode == Node, Mod == M,
- EvGName == GroupName, EvProps == Props, Res == R ->
- false;
+ EvGName == GroupName, EvProps == Props ->
+ case result_match(R, Res) of
+ true ->
+ false;
+ false ->
+ true
+ end;
({EH,#event{name=stop_logging,
node=EvNode,data=_}}) when
EH == TEH, EvNode == Node ->
@@ -603,23 +647,29 @@ locate({shuffle,TEvs}, Node, Evs, Config) ->
data={M,{init_per_group,GroupName,EvProps}}}},
{TEH,#event{name=tc_done,
node=Node,
- data={M,{init_per_group,GroupName,EvProps},R}}} | Es] ->
- case proplists:get_value(shuffle, Props) of
- '_' ->
- case proplists:get_value(shuffle, EvProps) of
- false ->
- exit({no_shuffle_prop_found,{M,init_per_group,
- GroupName,EvProps}});
+ data={M,{init_per_group,GroupName,EvProps},Res}}} | Es] ->
+ case result_match(R, Res) of
+ true ->
+ case proplists:get_value(shuffle, Props) of
+ '_' ->
+ case proplists:get_value(shuffle, EvProps) of
+ false ->
+ exit({no_shuffle_prop_found,
+ {M,init_per_group,
+ GroupName,EvProps}});
+ _ ->
+ PropsCmp = proplists:delete(shuffle, EvProps),
+ PropsCmp = proplists:delete(shuffle, Props)
+ end;
_ ->
- PropsCmp = proplists:delete(shuffle, EvProps),
- PropsCmp = proplists:delete(shuffle, Props)
- end;
- _ ->
- Props = EvProps
- end,
- test_server:format("Found ~p!", [InitStart]),
- test_server:format("Found ~p!", [InitDone]),
- {TEs,Es};
+ Props = EvProps
+ end,
+ test_server:format("Found ~p!", [InitStart]),
+ test_server:format("Found ~p!", [InitDone]),
+ {TEs,Es};
+ false ->
+ nomatch
+ end;
_ ->
nomatch
end;
@@ -670,7 +720,7 @@ locate({shuffle,TEvs}, Node, Evs, Config) ->
node=EvNode,
data={Mod,Func,Result}}} <- Done,
EH == TEH, EvNode == Node, Mod == M,
- Func == F, Result == R] of
+ Func == F, result_match(R, Result)] of
[TcDone|_] ->
test_server:format("Found ~p!", [TEv]),
{lists:delete(TcDone, Done),RemEvs,RemSize};
@@ -726,8 +776,13 @@ locate({shuffle,TEvs}, Node, Evs, Config) ->
data={Mod,{end_per_group,
EvGName,_},Res}}}) when
EH == TEH, EvNode == Node, Mod == M,
- EvGName == GroupName, Res == R ->
- false;
+ EvGName == GroupName ->
+ case result_match(R, Res) of
+ true ->
+ false;
+ false ->
+ true
+ end;
({EH,#event{name=stop_logging,
node=EvNode,data=_}}) when
EH == TEH, EvNode == Node ->
@@ -864,25 +919,34 @@ locate({TEH,Name,{'DEF','STOP_TIME'}}, Node, [Ev|Evs], Config) ->
nomatch
end;
-%% to match variable data as a result of a failed test case
-locate({TEH,tc_done,{Mod,Func,{failed,{error,{Slogan,'_'}}}}}, Node, [Ev|Evs], Config) ->
+%% to match variable data as a result of an aborted test case
+locate({TEH,tc_done,{undefined,undefined,{testcase_aborted,
+ {abort_current_testcase,Func},'_'}}},
+ Node, [Ev|Evs], Config) ->
case Ev of
- {TEH,#event{name=tc_done, node=Node,
- data={Mod,Func,{failed,{error,{Slogan,_}}}}}} ->
+ {TEH,#event{name=tc_done, node=Node,
+ data={undefined,undefined,
+ {testcase_aborted,{abort_current_testcase,Func},_}}}} ->
{Config,Evs};
_ ->
nomatch
end;
-%% to match variable data as a result of an aborted test case
-locate({TEH,tc_done,{undefined,undefined,{testcase_aborted,
- {abort_current_testcase,Func},'_'}}},
- Node, [Ev|Evs], Config) ->
+%% to match variable data as a result of a failed test case
+locate({TEH,tc_done,{Mod,Func,R={SkipOrFail,{_ErrInd,ErrInfo}}}},
+ Node, [Ev|Evs], Config) when ((SkipOrFail == skipped) or
+ (SkipOrFail == failed)) and
+ ((size(ErrInfo) == 2) or
+ (size(ErrInfo) == 3)) ->
case Ev of
{TEH,#event{name=tc_done, node=Node,
- data={undefined,undefined,
- {testcase_aborted,{abort_current_testcase,Func},_}}}} ->
- {Config,Evs};
+ data={Mod,Func,Result}}} ->
+ case result_match(R, Result) of
+ true ->
+ {Config,Evs};
+ false ->
+ nomatch
+ end;
_ ->
nomatch
end;
@@ -931,14 +995,27 @@ match_data(Tuple1,Tuple2) when is_tuple(Tuple1),is_tuple(Tuple2) ->
match_data([],[]) ->
match.
-log_events(TC, Events, PrivDir) ->
- LogFile = filename:join(PrivDir, atom_to_list(TC)++".events"),
+result_match({SkipOrFail,{ErrorInd,{Why,'_'}}},
+ {SkipOrFail,{ErrorInd,{Why,_Stack}}}) ->
+ true;
+result_match({SkipOrFail,{ErrorInd,{EMod,EFunc,{Why,'_'}}}},
+ {SkipOrFail,{ErrorInd,{EMod,EFunc,{Why,_Stack}}}}) ->
+ true;
+result_match(Result, Result) ->
+ true;
+result_match(_, _) ->
+ false.
+
+log_events(TC, Events, EvLogDir, Opts) ->
+ LogFile = filename:join(EvLogDir, atom_to_list(TC)++".events"),
{ok,Dev} = file:open(LogFile, [write]),
io:format(Dev, "[~n", []),
log_events1(Events, Dev, " "),
file:close(Dev),
+ FullLogFile = join_abs_dirs(proplists:get_value(net_dir, Opts),
+ LogFile),
io:format("Events written to logfile: <a href=\"file://~s\">~s</a>~n",
- [LogFile,LogFile]),
+ [FullLogFile,FullLogFile]),
io:format(user, "Events written to logfile: ~p~n", [LogFile]).
log_events1(Evs, Dev, "") ->
@@ -1024,13 +1101,25 @@ reformat([], _EH) ->
%%%-----------------------------------------------------------------
%%% MISC HELP FUNCTIONS
+join_abs_dirs(undefined, Dir2) ->
+ Dir2;
+join_abs_dirs(Dir1, Dir2) ->
+ case filename:pathtype(Dir2) of
+ relative ->
+ filename:join(Dir1, Dir2);
+ _ ->
+ [_Abs|Parts] = filename:split(Dir2),
+ filename:join(Dir1, filename:join(Parts))
+ end.
+
create_tmp_logdir(Tmp) ->
LogDir = filename:join(Tmp,"ct"),
file:make_dir(LogDir),
LogDir.
delete_old_logs({win32,_}, Config) ->
- case {?config(priv_dir, Config),?config(logdir, get_opts(Config))} of
+ case {proplists:get_value(priv_dir, Config),
+ proplists:get_value(logdir, get_opts(Config))} of
{LogDir,LogDir} ->
ignore;
{_,LogDir} -> % using tmp for logs
@@ -1042,7 +1131,8 @@ delete_old_logs(_, Config) ->
false ->
ignore;
_ ->
- catch delete_dirs(?config(logdir, get_opts(Config)))
+ catch delete_dirs(proplists:get_value(logdir,
+ get_opts(Config)))
end.
delete_dirs(LogDir) ->
diff --git a/lib/common_test/test/ct_testspec_1_SUITE.erl b/lib/common_test/test/ct_testspec_1_SUITE.erl
index 616c2db869..b6dcf63fdf 100644
--- a/lib/common_test/test/ct_testspec_1_SUITE.erl
+++ b/lib/common_test/test/ct_testspec_1_SUITE.erl
@@ -612,6 +612,12 @@ setup_and_execute(TCName, TestSpec, Config) ->
false -> [{spec,SpecFile},{label,TCName}]
end,
{Opts,ERPid} = setup(TestTerms, Config),
+
+ FullSpecFile = ct_test_support:join_abs_dirs(?config(net_dir, Opts),
+ SpecFile),
+ io:format("~nTest spec created here~n~n<a href=\"file://~s\">~s</a>~n",
+ [FullSpecFile,FullSpecFile]),
+
ok = ct_test_support:run(Opts, Config),
TestSpec1 = [{logdir,proplists:get_value(logdir,Opts)},
{label,proplists:get_value(label,TestTerms)} | TestSpec],
@@ -620,7 +626,8 @@ setup_and_execute(TCName, TestSpec, Config) ->
ct_test_support:log_events(TCName,
reformat(Events, ?eh),
- ?config(priv_dir, Config)),
+ ?config(priv_dir, Config),
+ Opts),
TestEvents = events_to_check(TCName),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
@@ -631,8 +638,6 @@ create_spec_file(SpecDir, TCName, TestSpec) ->
{ok,Dev} = file:open(FileName, [write]),
[io:format(Dev, "~p.~n", [Term]) || Term <- TestSpec],
file:close(Dev),
- io:format("~nTest spec created here~n~n<a href=\"file://~s\">~s</a>~n",
- [FileName,FileName]),
FileName.
setup(Test, Config) when is_tuple(Test) ->
@@ -791,7 +796,9 @@ test_events(skip_group) ->
{?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_1a,[]},'_'}},
{?eh,tc_user_skip, {groups_11_SUITE,{group,test_group_1b},"SKIPPED!"}},
- {?eh,test_stats,{2,0,{1,0}}},
+ {?eh,tc_user_skip, {groups_11_SUITE,{group,test_group_2},"SKIPPED!"}},
+ %%! But not test_group_7 since it's a sub-group!
+ {?eh,test_stats,{2,0,{2,0}}},
{negative,{?eh,tc_user_skip,'_'},{?eh,stop_logging,'_'}}
];
@@ -1188,10 +1195,9 @@ test_events(sub_skipped_by_top) ->
{?eh,tc_start,{groups_12_SUITE,init_per_suite}},
{?eh,tc_user_skip,{groups_12_SUITE,{group,test_group_4},"SKIPPED!"}},
+ {?eh,tc_user_skip,{groups_12_SUITE,{group,test_group_4},"SKIPPED!"}},
- {negative,
- {?eh,tc_user_skip,{groups_12_SUITE,{group,test_group_4},"SKIPPED!"}},
- {?eh,tc_done,{groups_12_SUITE,end_per_suite,'_'}}},
+ {?eh,tc_done,{groups_12_SUITE,end_per_suite,'_'}},
{negative,{?eh,tc_start,'_'},{?eh,stop_logging,'_'}}
];
diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk
index 8a4853e070..4782a32933 100644
--- a/lib/common_test/vsn.mk
+++ b/lib/common_test/vsn.mk
@@ -1,3 +1,3 @@
-COMMON_TEST_VSN = 1.5.3
+COMMON_TEST_VSN = 1.5.5
diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml
index f2af932aef..522c1dc411 100644
--- a/lib/compiler/doc/src/compile.xml
+++ b/lib/compiler/doc/src/compile.xml
@@ -68,7 +68,7 @@
to be an error if the module name in the source code is
not the same as the basename of the output file.</p>
- <p>Here follows first all elements of <c>Options</c> that in
+ <p><marker id="type-option"/>Here follows first all elements of <c>Options</c> that in
some way control the behavior of the compiler.</p>
<taglist>
<tag><c>basic_validation</c></tag>
@@ -395,6 +395,14 @@ module.beam: module.erl \
<code>-compile({no_auto_import,[error/1]}).</code>
</item>
+ <tag><c>no_line_info</c></tag>
+
+ <item>
+ <p>Omit line number information in order to produce a slightly
+ smaller output file.
+ </p>
+ </item>
+
</taglist>
<p>If warnings are turned on (the <c>report_warnings</c> option
diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml
index 25a6db4ce0..740cbcf8eb 100644
--- a/lib/compiler/doc/src/notes.xml
+++ b/lib/compiler/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,58 @@
<p>This document describes the changes made to the Compiler
application.</p>
+<section><title>Compiler 4.7.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Compiler options given in the source code using a
+ <c>-compile()</c> attribute used to be included twice in
+ <c>Mod:module_info(compile)</c>. They are now only
+ included once at the beginning of the list of options.</p>
+ <p>
+ Own Id: OTP-9534</p>
+ </item>
+ <item>
+ <p>
+ beam_disasm: Handle stripped BEAM files</p>
+ <p>
+ beam_disasm:file/1 would crash if asked to disassemble a
+ stripped BEAM file without an "Attr" chunk. (Thanks to
+ Haitao Li)</p>
+ <p>
+ Own Id: OTP-9571</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 4.7.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ If a variable is matched out in binary matching and used
+ as the size for a binary element, it would seem to be
+ unbound if used in a subsequent match operation. (Thanks
+ to Bernard Duggan.)</p>
+ <p>
+ Own Id: OTP-9134</p>
+ </item>
+ <item>
+ <p>Eliminate incorrect warning in
+ <c>sys_core_fold</c></p>
+ <p>
+ Own Id: OTP-9152</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Compiler 4.7.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/compiler/src/beam_asm.erl b/lib/compiler/src/beam_asm.erl
index 89d64834cf..6e63c4d0f2 100644
--- a/lib/compiler/src/beam_asm.erl
+++ b/lib/compiler/src/beam_asm.erl
@@ -23,7 +23,7 @@
-export([module/4]).
-export([encode/2]).
--import(lists, [map/2,member/2,keymember/3,duplicate/2]).
+-import(lists, [map/2,member/2,keymember/3,duplicate/2,splitwith/2]).
-include("beam_opcodes.hrl").
module(Code, Abst, SourceFile, Opts) ->
@@ -31,22 +31,20 @@ module(Code, Abst, SourceFile, Opts) ->
assemble({Mod,Exp,Attr0,Asm0,NumLabels}, Abst, SourceFile, Opts) ->
{1,Dict0} = beam_dict:atom(Mod, beam_dict:new()),
+ {0,Dict1} = beam_dict:fname(atom_to_list(Mod) ++ ".erl", Dict0),
NumFuncs = length(Asm0),
{Asm,Attr} = on_load(Asm0, Attr0),
- {Code,Dict1} = assemble_1(Asm, Exp, Dict0, []),
- build_file(Code, Attr, Dict1, NumLabels, NumFuncs, Abst, SourceFile, Opts).
+ {Code,Dict2} = assemble_1(Asm, Exp, Dict1, []),
+ build_file(Code, Attr, Dict2, NumLabels, NumFuncs, Abst, SourceFile, Opts).
on_load(Fs0, Attr0) ->
case proplists:get_value(on_load, Attr0) of
undefined ->
{Fs0,Attr0};
[{Name,0}] ->
- Fs = map(fun({function,N,0,Entry,Asm0}) when N =:= Name ->
- [{label,_}=L,
- {func_info,_,_,_}=Fi,
- {label,_}=E|Asm1] = Asm0,
- Asm = [L,Fi,E,on_load|Asm1],
- {function,N,0,Entry,Asm};
+ Fs = map(fun({function,N,0,Entry,Is0}) when N =:= Name ->
+ Is = insert_on_load_instruction(Is0, Entry),
+ {function,N,0,Entry,Is};
(F) ->
F
end, Fs0),
@@ -54,6 +52,13 @@ on_load(Fs0, Attr0) ->
{Fs,Attr}
end.
+insert_on_load_instruction(Is0, Entry) ->
+ {Bef,[{label,Entry}=El|Is]} =
+ splitwith(fun({label,L}) when L =:= Entry -> false;
+ (_) -> true
+ end, Is0),
+ Bef ++ [El,on_load|Is].
+
assemble_1([{function,Name,Arity,Entry,Asm}|T], Exp, Dict0, Acc) ->
Dict1 = case member({Name,Arity}, Exp) of
true ->
@@ -132,7 +137,10 @@ build_file(Code, Attr, Dict, NumLabels, NumFuncs, Abst, SourceFile, Opts) ->
LitTab = iolist_to_binary(zlib:compress(LitTab2)),
chunk(<<"LitT">>, <<(byte_size(LitTab2)):32>>, LitTab)
end,
+
+ %% Create the line chunk.
+ LineChunk = chunk(<<"Line">>, build_line_table(Dict)),
%% Create the attributes and compile info chunks.
@@ -150,8 +158,11 @@ build_file(Code, Attr, Dict, NumLabels, NumFuncs, Abst, SourceFile, Opts) ->
%% Create IFF chunk.
Chunks = case member(slim, Opts) of
- true -> [Essentials,AttrChunk,AbstChunk];
- false -> [Essentials,LocChunk,AttrChunk,CompileChunk,AbstChunk]
+ true ->
+ [Essentials,AttrChunk,AbstChunk];
+ false ->
+ [Essentials,LocChunk,AttrChunk,
+ CompileChunk,AbstChunk,LineChunk]
end,
build_form(<<"BEAM">>, Chunks).
@@ -201,6 +212,31 @@ build_attributes(Opts, SourceFile, Attr, Essentials) ->
Compile = [{options,Opts},{version,?COMPILER_VSN}|Misc],
{term_to_binary(calc_vsn(Attr, Essentials)),term_to_binary(Compile)}.
+build_line_table(Dict) ->
+ {NumLineInstrs,NumFnames0,Fnames0,NumLines,Lines0} =
+ beam_dict:line_table(Dict),
+ NumFnames = NumFnames0 - 1,
+ [_|Fnames1] = Fnames0,
+ Fnames2 = [unicode:characters_to_binary(F) || F <- Fnames1],
+ Fnames = << <<(byte_size(F)):16,F/binary>> || F <- Fnames2 >>,
+ Lines1 = encode_line_items(Lines0, 0),
+ Lines = iolist_to_binary(Lines1),
+ Ver = 0,
+ Bits = 0,
+ <<Ver:32,Bits:32,NumLineInstrs:32,NumLines:32,NumFnames:32,
+ Lines/binary,Fnames/binary>>.
+
+%% encode_line_items([{FnameIndex,Line}], PrevFnameIndex)
+%% Encode the line items compactly. Tag the FnameIndex with
+%% an 'a' tag (atom) and only include it when it has changed.
+%% Tag the line numbers with an 'i' (integer) tag.
+
+encode_line_items([{F,L}|T], F) ->
+ [encode(?tag_i, L)|encode_line_items(T, F)];
+encode_line_items([{F,L}|T], _) ->
+ [encode(?tag_a, F),encode(?tag_i, L)|encode_line_items(T, F)];
+encode_line_items([], _) -> [].
+
%%
%% If the attributes contains no 'vsn' attribute, we'll insert one
%% with an MD5 "checksum" calculated on the code as its value.
@@ -243,6 +279,9 @@ bif_type(_, 2) -> bif2.
make_op({'%',_}, Dict) ->
{[],Dict};
+make_op({line,Location}, Dict0) ->
+ {Index,Dict} = beam_dict:line(Location, Dict0),
+ encode_op(line, [Index], Dict);
make_op({bif, Bif, {f,_}, [], Dest}, Dict) ->
%% BIFs without arguments cannot fail.
encode_op(bif0, [{extfunc, erlang, Bif, 0}, Dest], Dict);
diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl
index c45874597a..432d1e7eea 100644
--- a/lib/compiler/src/beam_block.erl
+++ b/lib/compiler/src/beam_block.erl
@@ -36,13 +36,14 @@ function({function,Name,Arity,CLabel,Is0}, Lc0) ->
%% Collect basic blocks and optimize them.
Is2 = blockify(Is1),
- Is3 = move_allocates(Is2),
- Is4 = beam_utils:live_opt(Is3),
- Is5 = opt_blocks(Is4),
- Is6 = beam_utils:delete_live_annos(Is5),
+ Is3 = embed_lines(Is2),
+ Is4 = move_allocates(Is3),
+ Is5 = beam_utils:live_opt(Is4),
+ Is6 = opt_blocks(Is5),
+ Is7 = beam_utils:delete_live_annos(Is6),
%% Optimize bit syntax.
- {Is,Lc} = bsm_opt(Is6, Lc0),
+ {Is,Lc} = bsm_opt(Is7, Lc0),
%% Done.
{{function,Name,Arity,CLabel,Is},Lc}
@@ -148,6 +149,24 @@ collect(remove_message) -> {set,[],[],remove_message};
collect({'catch',R,L}) -> {set,[R],[],{'catch',L}};
collect(_) -> error.
+%% embed_lines([Instruction]) -> [Instruction]
+%% Combine blocks that would be split by line/1 instructions.
+%% Also move a line instruction before a block into the block,
+%% but leave the line/1 instruction after a block outside.
+
+embed_lines(Is) ->
+ embed_lines(reverse(Is), []).
+
+embed_lines([{block,B2},{line,_}=Line,{block,B1}|T], Acc) ->
+ B = {block,B1++[{set,[],[],Line}]++B2},
+ embed_lines([B|T], Acc);
+embed_lines([{block,B1},{line,_}=Line|T], Acc) ->
+ B = {block,[{set,[],[],Line}|B1]},
+ embed_lines([B|T], Acc);
+embed_lines([I|Is], Acc) ->
+ embed_lines(Is, [I|Acc]);
+embed_lines([], Acc) -> Acc.
+
opt_blocks([{block,Bl0}|Is]) ->
%% The live annotation at the beginning is not useful.
[{'%live',_}|Bl] = Bl0,
@@ -225,10 +244,12 @@ opt([{set,[Dst],As,{bif,Bif,Fail}}=I1,
RevBif -> [{set,[Dst],As,{bif,RevBif,Fail}}|opt(Is)]
end;
opt([{set,[X],[X],move}|Is]) -> opt(Is);
-opt([{set,[D1],[{integer,Idx1},Reg],{bif,element,{f,0}}}=I1,
+opt([{set,_,_,{line,_}}=Line1,
+ {set,[D1],[{integer,Idx1},Reg],{bif,element,{f,0}}}=I1,
+ {set,_,_,{line,_}}=Line2,
{set,[D2],[{integer,Idx2},Reg],{bif,element,{f,0}}}=I2|Is])
when Idx1 < Idx2, D1 =/= D2, D1 =/= Reg, D2 =/= Reg ->
- opt([I2,I1|Is]);
+ opt([Line2,I2,Line1,I1|Is]);
opt([{set,Ds0,Ss,Op}|Is0]) ->
{Ds,Is} = opt_moves(Ds0, Is0),
[{set,Ds,Ss,Op}|opt(Is)];
diff --git a/lib/compiler/src/beam_bsm.erl b/lib/compiler/src/beam_bsm.erl
index 2a36fda1ea..1217f7f777 100644
--- a/lib/compiler/src/beam_bsm.erl
+++ b/lib/compiler/src/beam_bsm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The 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,7 +20,7 @@
-module(beam_bsm).
-export([module/2,format_error/1]).
--import(lists, [member/2,foldl/3,reverse/1,sort/1,all/2]).
+-import(lists, [member/2,foldl/3,reverse/1,sort/1,all/2,dropwhile/2]).
%%%
%%% We optimize bit syntax matching where the tail end of a binary is
@@ -376,6 +376,8 @@ btb_reaches_match_2([{func_info,_,_,Arity}=I|_], Regs0, D) ->
[] -> D;
_ -> {binary_used_in,I}
end;
+btb_reaches_match_2([{line,_}|Is], Regs, D) ->
+ btb_reaches_match_1(Is, Regs, D);
btb_reaches_match_2([I|_], Regs, _) ->
btb_error({btb_context_regs(Regs),I,not_handled}).
@@ -580,7 +582,10 @@ btb_index(Fs) ->
btb_index_1(Fs, []).
btb_index_1([{function,_,_,Entry,Is0}|Fs], Acc0) ->
- [{label,_},{func_info,_,_,_},{label,Entry}|Is] = Is0,
+ [{label,Entry}|Is] =
+ dropwhile(fun({label,L}) when L =:= Entry -> false;
+ (_) -> true
+ end, Is0),
Acc = btb_index_2(Is, Entry, false, Acc0),
btb_index_1(Fs, Acc);
btb_index_1([], Acc) -> gb_trees:from_orddict(sort(Acc)).
@@ -651,10 +656,8 @@ add_warning(Term, Anno, Ws) ->
warning_translate_label(Term, D) when is_tuple(Term) ->
case element(1, Term) of
{label,F} ->
- case gb_trees:lookup(F, D) of
- none -> Term;
- {value,FA} -> setelement(1, Term, FA)
- end;
+ FA = gb_trees:get(F, D),
+ setelement(1, Term, FA);
_ -> Term
end;
warning_translate_label(Term, _) -> Term.
diff --git a/lib/compiler/src/beam_clean.erl b/lib/compiler/src/beam_clean.erl
index 64c93e11f7..a7994ab3b3 100644
--- a/lib/compiler/src/beam_clean.erl
+++ b/lib/compiler/src/beam_clean.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
%%
%% The 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,9 +23,9 @@
-export([module/2]).
-export([bs_clean_saves/1]).
-export([clean_labels/1]).
--import(lists, [map/2,foldl/3,reverse/1]).
+-import(lists, [map/2,foldl/3,reverse/1,filter/2]).
-module({Mod,Exp,Attr,Fs0,_}, _Opt) ->
+module({Mod,Exp,Attr,Fs0,_}, Opts) ->
Order = [Lbl || {function,_,_,Lbl,_} <- Fs0],
All = foldl(fun({function,_,_,Lbl,_}=Func,D) -> dict:store(Lbl, Func, D) end,
dict:new(), Fs0),
@@ -33,7 +33,8 @@ module({Mod,Exp,Attr,Fs0,_}, _Opt) ->
Used = find_all_used(WorkList, All, sets:from_list(WorkList)),
Fs1 = remove_unused(Order, Used, All),
{Fs2,Lc} = clean_labels(Fs1),
- Fs = bs_fix(Fs2),
+ Fs3 = bs_fix(Fs2),
+ Fs = maybe_remove_lines(Fs3, Opts),
{ok,{Mod,Exp,Attr,Fs,Lc}}.
%% Remove all bs_save2/2 instructions not referenced by a bs_restore2/2.
@@ -375,3 +376,20 @@ bs_clean_saves_1([{bs_save2,_,{_,_}=SavePoint}=I|Is], Needed, Acc) ->
bs_clean_saves_1([I|Is], Needed, Acc) ->
bs_clean_saves_1(Is, Needed, [I|Acc]);
bs_clean_saves_1([], _, Acc) -> reverse(Acc).
+
+%%%
+%%% Remove line instructions if requested.
+%%%
+
+maybe_remove_lines(Fs, Opts) ->
+ case proplists:get_bool(no_line_info, Opts) of
+ false -> Fs;
+ true -> remove_lines(Fs)
+ end.
+
+remove_lines([{function,N,A,Lbl,Is0}|T]) ->
+ Is = filter(fun({line,_}) -> false;
+ (_) -> true
+ end, Is0),
+ [{function,N,A,Lbl,Is}|remove_lines(T)];
+remove_lines([]) -> [].
diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl
index bb93110176..9f81a6ab43 100644
--- a/lib/compiler/src/beam_dead.erl
+++ b/lib/compiler/src/beam_dead.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -144,9 +144,9 @@ function({function,Name,Arity,CLabel,Is0}, Lc0) ->
%% Initialize label information with the code
%% for the func_info label. Without it, a register
%% may seem to be live when it is not.
- [{label,L},{func_info,_,_,_}=FI|_] = Is1,
+ [{label,L}|FiIs] = Is1,
D0 = beam_utils:empty_label_index(),
- D = beam_utils:index_label(L, [FI], D0),
+ D = beam_utils:index_label(L, FiIs, D0),
%% Optimize away dead code.
{Is2,Lc} = forward(Is1, Lc0),
@@ -162,14 +162,11 @@ function({function,Name,Arity,CLabel,Is0}, Lc0) ->
%% We must split the basic block when we encounter instructions with labels,
%% such as catches and BIFs. All labels must be visible outside the blocks.
-%% Also remove empty blocks.
split_blocks({function,Name,Arity,CLabel,Is0}) ->
Is = split_blocks(Is0, []),
{function,Name,Arity,CLabel,Is}.
-split_blocks([{block,[]}|Is], Acc) ->
- split_blocks(Is, Acc);
split_blocks([{block,Bl}|Is], Acc0) ->
Acc = split_block(Bl, [], Acc0),
split_blocks(Is, Acc);
@@ -188,6 +185,8 @@ split_block([{set,[R],As,{alloc,Live,{gc_bif,N,{f,Lbl}=Fail}}}|Is], Bl, Acc)
split_block(Is, [], [{gc_bif,N,Fail,Live,As,R}|make_block(Bl, Acc)]);
split_block([{set,[R],[],{'catch',L}}|Is], Bl, Acc) ->
split_block(Is, [], [{'catch',R,L}|make_block(Bl, Acc)]);
+split_block([{set,[],[],{line,_}=Line}|Is], Bl, Acc) ->
+ split_block(Is, [], [Line|make_block(Bl, Acc)]);
split_block([I|Is], Bl, Acc) ->
split_block(Is, [I|Bl], Acc);
split_block([], Bl, Acc) -> make_block(Bl, Acc).
@@ -246,30 +245,24 @@ forward([{select_val,Reg,_,{list,List}}=I|Is], D0, Lc, Acc) ->
D = update_value_dict(List, Reg, D0),
forward(Is, D, Lc, [I|Acc]);
forward([{label,Lbl}=LblI,{block,[{set,[Dst],[Lit],move}|BlkIs]}=Blk|Is], D, Lc, Acc) ->
+ %% Assumption: The target labels in a select_val/3 instruction
+ %% cannot be reached in any other way than through the select_val/3
+ %% instruction (i.e. there can be no fallthrough to such label and
+ %% it cannot be referenced by, for example, a jump/1 instruction).
Block = case gb_trees:lookup({Lbl,Dst}, D) of
- {value,Lit} ->
- %% The move instruction seems to be redundant, but also make
- %% sure that the instruction preceeding the label
- %% cannot fall through to the move instruction.
- case is_unreachable_after(Acc) of
- false -> Blk; %Must keep move instruction.
- true -> {block,BlkIs} %Safe to remove move instruction.
- end;
- _ -> Blk %Keep move instruction.
+ {value,Lit} -> {block,BlkIs}; %Safe to remove move instruction.
+ _ -> Blk %Must keep move instruction.
end,
forward([Block|Is], D, Lc, [LblI|Acc]);
forward([{label,Lbl}=LblI|[{move,Lit,Dst}|Is1]=Is0], D, Lc, Acc) ->
+ %% Assumption: The target labels in a select_val/3 instruction
+ %% cannot be reached in any other way than through the select_val/3
+ %% instruction (i.e. there can be no fallthrough to such label and
+ %% it cannot be referenced by, for example, a jump/1 instruction).
Is = case gb_trees:lookup({Lbl,Dst}, D) of
- {value,Lit} ->
- %% The move instruction seems to be redundant, but also make
- %% sure that the instruction preceeding the label
- %% cannot fall through to the move instruction.
- case is_unreachable_after(Acc) of
- false -> Is0; %Must keep move instruction.
- true -> Is1 %Safe to remove move instruction.
- end;
- _ -> Is0 %Keep move instruction.
- end,
+ {value,Lit} -> Is1; %Safe to remove move instruction.
+ _ -> Is0 %Keep move instruction.
+ end,
forward(Is, D, Lc, [LblI|Acc]);
forward([{test,is_eq_exact,_,[Dst,Src]}=I,
{block,[{set,[Dst],[Src],move}|Bl]}|Is], D, Lc, Acc) ->
@@ -299,16 +292,12 @@ update_value_dict([Lit,{f,Lbl}|T], Reg, D0) ->
Key = {Lbl,Reg},
D = case gb_trees:lookup(Key, D0) of
none -> gb_trees:insert(Key, Lit, D0); %New.
- {value,Lit} -> D0; %Already correct.
{value,inconsistent} -> D0; %Inconsistent.
{value,_} -> gb_trees:update(Key, inconsistent, D0)
end,
update_value_dict(T, Reg, D);
update_value_dict([], _, D) -> D.
-is_unreachable_after([I|_]) ->
- beam_jump:is_unreachable_after(I).
-
%%%
%%% Scan instructions in reverse execution order and remove dead code.
%%%
@@ -419,7 +408,7 @@ backward([{test,Op,{f,To0},Live,Ops0,Dst}|Is], D, Acc) ->
end,
I = {test,Op,{f,To},Live,Ops0,Dst},
backward(Is, D, [I|Acc]);
-backward([{kill,_}=I|Is], D, [Exit|_]=Acc) ->
+backward([{kill,_}=I|Is], D, [{line,_},Exit|_]=Acc) ->
case beam_jump:is_exit_instruction(Exit) of
false -> backward(Is, D, [I|Acc]);
true -> backward(Is, D, Acc)
@@ -484,7 +473,7 @@ shortcut_fail_label(To0, Reg, Val, D) ->
shortcut_boolean_label(To0, Reg, Bool0, D) when is_boolean(Bool0) ->
case beam_utils:code_at(To0, D) of
- [{bif,'not',_,[Reg],Reg},{jump,{f,To}}|_] ->
+ [{line,_},{bif,'not',_,[Reg],Reg},{jump,{f,To}}|_] ->
Bool = not Bool0,
{shortcut_select_label(To, Reg, Bool, D),Bool};
_ ->
@@ -602,16 +591,11 @@ count_bits_matched([{test,_,_,_}|Is], SavePoint, Bits) ->
count_bits_matched([{bs_save2,Reg,SavePoint}|_], {Reg,SavePoint}, Bits) ->
%% The save point we are looking for - we are done.
Bits;
-count_bits_matched([{bs_save2,_,_}|Is], SavePoint, Bits) ->
- %% Another save point - keep counting.
- count_bits_matched(Is, SavePoint, Bits);
count_bits_matched([_|_], _, Bits) -> Bits.
shortcut_bs_pos_used(To, Reg, D) ->
shortcut_bs_pos_used_1(beam_utils:code_at(To, D), Reg, D).
-shortcut_bs_pos_used_1([{bs_restore2,Reg,_}|_], Reg, _) ->
- false;
shortcut_bs_pos_used_1([{bs_context_to_binary,Reg}|_], Reg, _) ->
false;
shortcut_bs_pos_used_1(Is, Reg, D) ->
diff --git a/lib/compiler/src/beam_dict.erl b/lib/compiler/src/beam_dict.erl
index a503fcab38..ee76623976 100644
--- a/lib/compiler/src/beam_dict.erl
+++ b/lib/compiler/src/beam_dict.erl
@@ -22,9 +22,10 @@
-export([new/0,opcode/2,highest_opcode/1,
atom/2,local/4,export/4,import/4,
- string/2,lambda/5,literal/2,
+ string/2,lambda/5,literal/2,line/2,fname/2,
atom_table/1,local_table/1,export_table/1,import_table/1,
- string_table/1,lambda_table/1,literal_table/1]).
+ string_table/1,lambda_table/1,literal_table/1,
+ line_table/1]).
-type label() :: non_neg_integer().
@@ -36,7 +37,9 @@
strings = <<>> :: binary(), %String pool
lambdas = [], %[{...}]
literals = dict:new() :: dict(), %Format: {Literal,Number}
- next_atom = 1 :: pos_integer(),
+ fnames = gb_trees:empty() :: gb_tree(), %{Name,Index}
+ lines = gb_trees:empty() :: gb_tree(), %{{Fname,Line},Index}
+ num_lines = 0 :: non_neg_integer(), %Number of line instructions
next_import = 0 :: non_neg_integer(),
string_offset = 0 :: non_neg_integer(),
next_literal = 0 :: non_neg_integer(),
@@ -66,13 +69,14 @@ highest_opcode(#asm{highest_opcode=Op}) -> Op.
%% atom(Atom, Dict) -> {Index,Dict'}
-spec atom(atom(), bdict()) -> {pos_integer(), bdict()}.
-atom(Atom, #asm{atoms=Atoms0,next_atom=NextIndex}=Dict) when is_atom(Atom) ->
+atom(Atom, #asm{atoms=Atoms0}=Dict) when is_atom(Atom) ->
case gb_trees:lookup(Atom, Atoms0) of
{value,Index} ->
{Index,Dict};
none ->
+ NextIndex = gb_trees:size(Atoms0) + 1,
Atoms = gb_trees:insert(Atom, NextIndex, Atoms0),
- {NextIndex,Dict#asm{atoms=Atoms,next_atom=NextIndex+1}}
+ {NextIndex,Dict#asm{atoms=Atoms}}
end.
%% Remembers an exported function.
@@ -139,7 +143,7 @@ lambda(Lbl, Index, OldUniq, NumFree, #asm{lambdas=Lambdas0}=Dict) ->
Lambdas = [{Lbl,{OldIndex,Lbl,Index,NumFree,OldUniq}}|Lambdas0],
{OldIndex,Dict#asm{lambdas=Lambdas}}.
-%% Returns the index for a literal (adding it to the atom table if necessary).
+%% Returns the index for a literal (adding it to the literal table if necessary).
%% literal(Literal, Dict) -> {Index,Dict'}
-spec literal(term(), bdict()) -> {non_neg_integer(), bdict()}.
@@ -152,18 +156,49 @@ literal(Lit, #asm{literals=Tab0,next_literal=NextIndex}=Dict) ->
{NextIndex,Dict#asm{literals=Tab,next_literal=NextIndex+1}}
end.
+%% Returns the index for a line instruction (adding information
+%% to the location information table).
+-spec line(list(), bdict()) -> {non_neg_integer(), bdict()}.
+
+line([], #asm{num_lines=N}=Dict) ->
+ %% No location available. Return the special pre-defined
+ %% index 0.
+ {0,Dict#asm{num_lines=N+1}};
+line([{location,Name,Line}], #asm{lines=Lines0,num_lines=N}=Dict0) ->
+ {FnameIndex,Dict1} = fname(Name, Dict0),
+ case gb_trees:lookup({FnameIndex,Line}, Lines0) of
+ {value,Index} ->
+ {Index,Dict1#asm{num_lines=N+1}};
+ none ->
+ Index = gb_trees:size(Lines0) + 1,
+ Lines = gb_trees:insert({FnameIndex,Line}, Index, Lines0),
+ Dict = Dict1#asm{lines=Lines,num_lines=N+1},
+ {Index,Dict}
+ end.
+
+fname(Name, #asm{fnames=Fnames0}=Dict) ->
+ case gb_trees:lookup(Name, Fnames0) of
+ {value,Index} ->
+ {Index,Dict};
+ none ->
+ Index = gb_trees:size(Fnames0),
+ Fnames = gb_trees:insert(Name, Index, Fnames0),
+ {Index,Dict#asm{fnames=Fnames}}
+ end.
+
%% Returns the atom table.
%% atom_table(Dict) -> {LastIndex,[Length,AtomString...]}
-spec atom_table(bdict()) -> {non_neg_integer(), [[non_neg_integer(),...]]}.
-atom_table(#asm{atoms=Atoms,next_atom=NumAtoms}) ->
+atom_table(#asm{atoms=Atoms}) ->
+ NumAtoms = gb_trees:size(Atoms),
Sorted = lists:keysort(2, gb_trees:to_list(Atoms)),
Fun = fun({A,_}) ->
L = atom_to_list(A),
[length(L)|L]
end,
AtomTab = lists:map(Fun, Sorted),
- {NumAtoms-1,AtomTab}.
+ {NumAtoms,AtomTab}.
%% Returns the table of local functions.
%% local_table(Dict) -> {NumLocals, [{Function, Arity, Label}...]}
@@ -218,6 +253,21 @@ literal_table(#asm{literals=Tab,next_literal=NumLiterals}) ->
my_term_to_binary(Term) ->
term_to_binary(Term, [{minor_version,1}]).
+%% Return the line table.
+-spec line_table(bdict()) ->
+ {non_neg_integer(), %Number of line instructions.
+ non_neg_integer(),[string()],
+ non_neg_integer(),[{non_neg_integer(),non_neg_integer()}]}.
+
+line_table(#asm{fnames=Fnames0,lines=Lines0,num_lines=NumLineInstrs}) ->
+ NumFnames = gb_trees:size(Fnames0),
+ Fnames1 = lists:keysort(2, gb_trees:to_list(Fnames0)),
+ Fnames = [Name || {Name,_} <- Fnames1],
+ NumLines = gb_trees:size(Lines0),
+ Lines1 = lists:keysort(2, gb_trees:to_list(Lines0)),
+ Lines = [L || {L,_} <- Lines1],
+ {NumLineInstrs,NumFnames,Fnames,NumLines,Lines}.
+
%% Search for binary string Str in the binary string pool Pool.
%% old_string(Str, Pool) -> none | Index
-spec old_string(binary(), binary()) -> 'none' | pos_integer().
diff --git a/lib/compiler/src/beam_disasm.erl b/lib/compiler/src/beam_disasm.erl
index 017ca129b0..7103d2390f 100644
--- a/lib/compiler/src/beam_disasm.erl
+++ b/lib/compiler/src/beam_disasm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -204,7 +204,7 @@ process_chunks(F) ->
optional_chunk(F, ChunkTag) ->
case beam_lib:chunks(F, [ChunkTag]) of
{ok,{_Module,[{ChunkTag,Chunk}]}} -> Chunk;
- {error,beam_lib,{missing_chunk,_,ChunkTag}} -> none
+ {error,beam_lib,{missing_chunk,_,_}} -> none
end.
%%-----------------------------------------------------------------------
@@ -296,6 +296,8 @@ get_function_chunks(Code) ->
labels_r([], R) -> {R, []};
labels_r([{label,_}=I|Is], R) ->
labels_r(Is, [I|R]);
+labels_r([{line,_}=I|Is], R) ->
+ labels_r(Is, [I|R]);
labels_r(Is, R) -> {R, Is}.
get_funs({[],[]}) -> [];
@@ -335,20 +337,17 @@ local_labels(Funs) ->
local_labels_1(function__code(F), R)
end, [], Funs)).
-%% The first clause below attempts to provide some (limited form of)
-%% backwards compatibility; it is not needed for .beam files generated
-%% by the R8 compiler. The clause should one fine day be taken out.
-local_labels_1([{label,_}|[{label,_}|_]=Code], R) ->
- local_labels_1(Code, R);
-local_labels_1([{label,_},{func_info,{atom,M},{atom,F},A}|Code], R)
- when is_atom(M), is_atom(F) ->
- local_labels_2(Code, R, M, F, A);
-local_labels_1(Code, _) ->
- ?exit({'local_labels: no label in code',Code}).
+local_labels_1(Code0, R) ->
+ Code1 = lists:dropwhile(fun({label,_}) -> true;
+ ({line,_}) -> true;
+ ({func_info,_,_,_}) -> false
+ end, Code0),
+ [{func_info,{atom,M},{atom,F},A}|Code] = Code1,
+ local_labels_2(Code, R, {M,F,A}).
-local_labels_2([{label,[{u,L}]}|Code], R, M, F, A) ->
- local_labels_2(Code, [{L,{M,F,A}}|R], M, F, A);
-local_labels_2(_, R, _, _, _) -> R.
+local_labels_2([{label,[{u,L}]}|Code], R, MFA) ->
+ local_labels_2(Code, [{L,MFA}|R], MFA);
+local_labels_2(_, R, _) -> R.
%%-----------------------------------------------------------------------
%% Disassembles a single BEAM instruction; most instructions are handled
@@ -1105,6 +1104,12 @@ resolve_inst({recv_set,[Lbl]},_,_,_) ->
{recv_set,Lbl};
%%
+%% R15A.
+%%
+resolve_inst({line,[Index]},_,_,_) ->
+ {line,resolve_arg(Index)};
+
+%%
%% Catches instructions that are not yet handled.
%%
resolve_inst(X,_,_,_) -> ?exit({resolve_inst,X}).
diff --git a/lib/compiler/src/beam_jump.erl b/lib/compiler/src/beam_jump.erl
index 3cab55c4cb..537f8ca81b 100644
--- a/lib/compiler/src/beam_jump.erl
+++ b/lib/compiler/src/beam_jump.erl
@@ -169,7 +169,7 @@ share_1([{label,L}=Lbl|Is], Dict0, Seq, Acc) ->
share_1(Is, Dict0, [], [Lbl,{jump,{f,Label}}|Acc])
end;
share_1([{func_info,_,_,_}=I|Is], _, [], Acc) ->
- Is++[I|Acc];
+ reverse(Is, [I|Acc]);
share_1([I|Is], Dict, Seq, Acc) ->
case is_unreachable_after(I) of
false ->
@@ -206,25 +206,35 @@ is_label(_) -> false.
move(Is) ->
move_1(Is, [], []).
-move_1([I|Is], End, Acc) ->
+move_1([I|Is], End0, Acc0) ->
case is_exit_instruction(I) of
- false -> move_1(Is, End, [I|Acc]);
- true -> move_2(I, Is, End, Acc)
+ false ->
+ move_1(Is, End0, [I|Acc0]);
+ true ->
+ case extract_seq(Acc0, [I|End0]) of
+ no ->
+ move_1(Is, End0, [I|Acc0]);
+ {yes,End,Acc} ->
+ move_1(Is, End, Acc)
+ end
end;
-move_1([], End, Acc) ->
- reverse(Acc, reverse(End)).
-
-move_2(Exit, Is, End, [{block,_},{label,_},{func_info,_,_,_}|_]=Acc) ->
- move_1(Is, End, [Exit|Acc]);
-move_2(Exit, Is, End, [{block,_}=Blk,{label,_}=Lbl,Unreachable|More]) ->
- move_1([Unreachable|Is], [Exit,Blk,Lbl|End], More);
-move_2(Exit, Is, End, [{bs_context_to_binary,_}=Bs,{label,_}=Lbl,
- Unreachable|More]) ->
- move_1([Unreachable|Is], [Exit,Bs,Lbl|End], More);
-move_2(Exit, Is, End, [{label,_}=Lbl,Unreachable|More]) ->
- move_1([Unreachable|Is], [Exit,Lbl|End], More);
-move_2(Exit, Is, End, Acc) ->
- move_1(Is, End, [Exit|Acc]).
+move_1([], End, Acc) -> reverse(Acc, End).
+
+extract_seq([{line,_}=Line|Is], Acc) ->
+ extract_seq(Is, [Line|Acc]);
+extract_seq([{block,_}=Bl|Is], Acc) ->
+ extract_seq_1(Is, [Bl|Acc]);
+extract_seq([{label,_}|_]=Is, Acc) ->
+ extract_seq_1(Is, Acc);
+extract_seq(_, _) -> no.
+
+extract_seq_1([{line,_}=Line|Is], Acc) ->
+ extract_seq_1(Is, [Line|Acc]);
+extract_seq_1([{label,_},{func_info,_,_,_}|_], _) ->
+ no;
+extract_seq_1([{label,_}=Lbl|Is], Acc) ->
+ {yes,[Lbl|Acc],Is};
+extract_seq_1(_, _) -> no.
%%%
%%% (3) (4) (5) (6) Jump and unreachable code optimizations.
@@ -454,6 +464,7 @@ is_label_used_in_2({set,_,_,Info}, Lbl) ->
{put_tuple,_} -> false;
{get_tuple_element,_} -> false;
{set_tuple_element,_} -> false;
+ {line,_} -> false;
_ when is_atom(Info) -> false
end.
@@ -487,6 +498,8 @@ rem_unused([], _, Acc) -> reverse(Acc).
initial_labels(Is) ->
initial_labels(Is, []).
+initial_labels([{line,_}|Is], Acc) ->
+ initial_labels(Is, Acc);
initial_labels([{label,Lbl}|Is], Acc) ->
initial_labels(Is, [Lbl|Acc]);
initial_labels([{func_info,_,_,_},{label,Lbl}|_], Acc) ->
diff --git a/lib/compiler/src/beam_listing.erl b/lib/compiler/src/beam_listing.erl
index be7b14c3dd..2941f6135c 100644
--- a/lib/compiler/src/beam_listing.erl
+++ b/lib/compiler/src/beam_listing.erl
@@ -61,7 +61,7 @@ print_op(Stream, Label) when element(1, Label) == label ->
print_op(Stream, Op) ->
io:format(Stream, " ~p.\n", [Op]).
-function(File, {function,Name,Arity,Args,Body,Vdb}) ->
+function(File, {function,Name,Arity,Args,Body,Vdb,_Anno}) ->
io:nl(File),
io:format(File, "function ~p/~p.\n", [Name,Arity]),
io:format(File, " ~p.\n", [Args]),
diff --git a/lib/compiler/src/beam_receive.erl b/lib/compiler/src/beam_receive.erl
index 9ed44ad5d7..c483d85a97 100644
--- a/lib/compiler/src/beam_receive.erl
+++ b/lib/compiler/src/beam_receive.erl
@@ -175,6 +175,8 @@ opt_update_regs({label,Lbl}, R, L) ->
end;
opt_update_regs({try_end,_}, R, L) ->
{R,L};
+opt_update_regs({line,_}, R, L) ->
+ {R,L};
opt_update_regs(_I, _R, L) ->
%% Unrecognized instruction. Abort the search.
{regs_init(),L}.
diff --git a/lib/compiler/src/beam_trim.erl b/lib/compiler/src/beam_trim.erl
index 790aba0a9a..25e6ffbb73 100644
--- a/lib/compiler/src/beam_trim.erl
+++ b/lib/compiler/src/beam_trim.erl
@@ -222,7 +222,9 @@ remap([{call_last,Ar,Name,N}|Is], Map, Acc) ->
reverse(Acc, [I|Is]);
remap([{call_ext_last,Ar,Name,N}|Is], Map, Acc) ->
I = {call_ext_last,Ar,Name,Map({frame_size,N})},
- reverse(Acc, [I|Is]).
+ reverse(Acc, [I|Is]);
+remap([{line,_}=I|Is], Map, Acc) ->
+ remap(Is, Map, [I|Acc]).
remap_block([{set,Ds0,Ss0,Info}|Is], Map, Acc) ->
Ds = [Map(D) || D <- Ds0],
@@ -230,14 +232,15 @@ remap_block([{set,Ds0,Ss0,Info}|Is], Map, Acc) ->
remap_block(Is, Map, [{set,Ds,Ss,Info}|Acc]);
remap_block([], _, Acc) -> reverse(Acc).
-safe_labels([{label,L},{badmatch,{Tag,_}}|Is], Acc) when Tag =/= y ->
+safe_labels([{label,L},{line,_},{badmatch,{Tag,_}}|Is], Acc) when Tag =/= y ->
safe_labels(Is, [L|Acc]);
-safe_labels([{label,L},{case_end,{Tag,_}}|Is], Acc) when Tag =/= y ->
+safe_labels([{label,L},{line,_},{case_end,{Tag,_}}|Is], Acc) when Tag =/= y ->
safe_labels(Is, [L|Acc]);
-safe_labels([{label,L},if_end|Is], Acc) ->
+safe_labels([{label,L},{line,_},if_end|Is], Acc) ->
safe_labels(Is, [L|Acc]);
safe_labels([{label,L},
{block,[{set,[{x,0}],[{Tag,_}],move}]},
+ {line,_},
{call_ext,1,{extfunc,erlang,error,1}}|Is], Acc) when Tag =/= y ->
safe_labels(Is, [L|Acc]);
safe_labels([_|Is], Acc) ->
@@ -321,6 +324,8 @@ frame_size([{make_fun2,_,_,_,_}|Is], Safe) ->
frame_size([{deallocate,N}|_], _) -> N;
frame_size([{call_last,_,_,N}|_], _) -> N;
frame_size([{call_ext_last,_,_,N}|_], _) -> N;
+frame_size([{line,_}|Is], Safe) ->
+ frame_size(Is, Safe);
frame_size([_|_], _) -> throw(not_possible).
frame_size_branch(0, Is, Safe) ->
diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl
index f83f73b224..7fdb8d072a 100644
--- a/lib/compiler/src/beam_type.erl
+++ b/lib/compiler/src/beam_type.erl
@@ -400,6 +400,7 @@ update({call_ext,3,{extfunc,erlang,setelement,3}}, Ts0) ->
update({call,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts);
update({call_ext,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts);
update({make_fun2,_,_,_,_}, Ts) -> tdb_kill_xregs(Ts);
+update({line,_}, Ts) -> Ts;
%% The instruction is unknown. Kill all information.
update(_I, _Ts) -> tdb_new().
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl
index 45cdf8a659..f281ad5eac 100644
--- a/lib/compiler/src/beam_utils.erl
+++ b/lib/compiler/src/beam_utils.erl
@@ -26,7 +26,7 @@
code_at/2,bif_to_test/3,is_pure_test/1,
live_opt/1,delete_live_annos/1,combine_heap_needs/2]).
--import(lists, [member/2,sort/1,reverse/1]).
+-import(lists, [member/2,sort/1,reverse/1,splitwith/2]).
-record(live,
{bl, %Block check fun.
@@ -195,10 +195,14 @@ is_pure_test({test,Op,_,Ops}) ->
%% Also insert {'%live',Live} annotations at the beginning
%% and end of each block.
%%
-live_opt([{label,Fail}=I1,
- {func_info,_,_,Live}=I2|Is]) ->
+live_opt(Is0) ->
+ {[{label,Fail}|_]=Bef,[Fi|Is]} =
+ splitwith(fun({func_info,_,_,_}) -> false;
+ (_) -> true
+ end, Is0),
+ {func_info,_,_,Live} = Fi,
D = gb_trees:insert(Fail, live_call(Live), gb_trees:empty()),
- [I1,I2|live_opt(reverse(Is), 0, D, [])].
+ Bef ++ [Fi|live_opt(reverse(Is), 0, D, [])].
%% delete_live_annos([Instruction]) -> [Instruction].
@@ -499,6 +503,8 @@ check_liveness(R, [{loop_rec,{f,_},{x,0}}|_], St) ->
end;
check_liveness(R, [{loop_rec_end,{f,Fail}}|_], St) ->
check_liveness_at(R, Fail, St);
+check_liveness(R, [{line,_}|Is], St) ->
+ check_liveness(R, Is, St);
check_liveness(_R, Is, St) when is_list(Is) ->
%% case Is of
%% [I|_] ->
@@ -799,6 +805,8 @@ live_opt([{wait,_}=I|Is], Regs, D, Acc) ->
live_opt(Is, Regs, D, [I|Acc]);
live_opt([{wait_timeout,_,{Tag,_}}=I|Is], Regs, D, Acc) when Tag =/= x ->
live_opt(Is, Regs, D, [I|Acc]);
+live_opt([{line,_}=I|Is], Regs, D, Acc) ->
+ live_opt(Is, Regs, D, [I|Acc]);
%% The following instructions can occur if the "compilation" has been
%% started from a .S file using the 'asm' option.
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index fb267b35b6..fe3b1680d9 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -166,12 +166,17 @@ validate(Module, Fs) ->
Ft = index_bs_start_match(Fs, []),
validate_0(Module, Fs, Ft).
-index_bs_start_match([{function,_,_,Entry,Code}|Fs], Acc0) ->
+index_bs_start_match([{function,_,_,Entry,Code0}|Fs], Acc0) ->
+ Code = dropwhile(fun({label,L}) when L =:= Entry -> false;
+ (_) -> true
+ end, Code0),
case Code of
- [_,_,{label,Entry}|Is] ->
+ [{label,Entry}|Is] ->
Acc = index_bs_start_match_1(Is, Entry, Acc0),
index_bs_start_match(Fs, Acc);
_ ->
+ %% Something serious is wrong. Ignore it for now.
+ %% It will be detected and diagnosed later.
index_bs_start_match(Fs, Acc0)
end;
index_bs_start_match([], Acc) ->
@@ -292,6 +297,8 @@ labels(Is) ->
labels_1([{label,L}|Is], R) ->
labels_1(Is, [L|R]);
+labels_1([{line,_}|Is], R) ->
+ labels_1(Is, R);
labels_1(Is, R) ->
{lists:reverse(R),Is}.
@@ -433,6 +440,8 @@ valfun_1(remove_message, Vst) ->
Vst;
valfun_1({'%',_}, Vst) ->
Vst;
+valfun_1({line,_}, Vst) ->
+ Vst;
%% Exception generating calls
valfun_1({call_ext,Live,Func}=I, Vst) ->
case return_type(Func, Vst) of
@@ -870,6 +879,8 @@ val_dsetel({set_tuple_element,_,_,_}, #vst{current=#st{setelem=false}}) ->
error(illegal_context_for_set_tuple_element);
val_dsetel({set_tuple_element,_,_,_}, #vst{current=#st{setelem=true}}=Vst) ->
Vst;
+val_dsetel({line,_}, Vst) ->
+ Vst;
val_dsetel(_, #vst{current=#st{setelem=true}=St}=Vst) ->
Vst#vst{current=St#st{setelem=false}};
val_dsetel(_, Vst) -> Vst.
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index ce8a5bf864..bfa7c6cedd 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -113,7 +113,7 @@ noenv_forms(Forms, Opt) when is_atom(Opt) ->
noenv_output_generated(Opts) ->
{_,Passes} = passes(file, expand_opts(Opts)),
- any(fun ({save_binary,_F}) -> true;
+ any(fun ({save_binary,_T,_F}) -> true;
(_Other) -> false
end, Passes).
@@ -122,6 +122,7 @@ noenv_output_generated(Opts) ->
%%
-define(pass(P), {P,fun P/1}).
+-define(pass(P,T), {P,fun T/1,fun P/1}).
env_default_opts() ->
Key = "ERL_COMPILER_OPTIONS",
@@ -171,9 +172,9 @@ expand_opt(report, Os) ->
expand_opt(return, Os) ->
[return_errors,return_warnings|Os];
expand_opt(r12, Os) ->
- [no_recv_opt|Os];
+ [no_recv_opt,no_line_info|Os];
expand_opt(r13, Os) ->
- [no_recv_opt|Os];
+ [no_recv_opt,no_line_info|Os];
expand_opt({debug_info_key,_}=O, Os) ->
[encrypt_debug_info,O|Os];
expand_opt(no_float_opt, Os) ->
@@ -304,7 +305,7 @@ run_tc({Name,Fun}, St) ->
Val.
comp_ret_ok(#compile{code=Code,warnings=Warn0,module=Mod,options=Opts}=St) ->
- case member(warnings_as_errors, Opts) andalso length(Warn0) > 0 of
+ case werror(St) of
true ->
case member(report_warnings, Opts) of
true ->
@@ -339,6 +340,11 @@ comp_ret_err(#compile{warnings=Warn0,errors=Err0,options=Opts}=St) ->
false -> error
end.
+not_werror(St) -> not werror(St).
+
+werror(#compile{options=Opts,warnings=Ws}) ->
+ Ws =/= [] andalso member(warnings_as_errors, Opts).
+
%% messages_per_file([{File,[Message]}]) -> [{File,[Message]}]
messages_per_file(Ms) ->
T = lists:sort([{File,M} || {File,Messages} <- Ms, M <- Messages]),
@@ -373,7 +379,7 @@ passes(Type, Opts) ->
%% insert a first pass to remove the file (unless the
%% source file is a BEAM file).
{Ext,case last(Passes) of
- {save_binary,_Fun} ->
+ {save_binary,_TestFun,_Fun} ->
case Passes of
[{read_beam_file,_}|_] ->
%% The BEAM is both input and output.
@@ -655,7 +661,7 @@ asm_passes() ->
binary_passes() ->
[{native_compile,fun test_native/1,fun native_compile/1},
- {unless,binary,?pass(save_binary)}].
+ {unless,binary,?pass(save_binary,not_werror)}].
%%%
%%% Compiler passes.
@@ -1379,28 +1385,34 @@ report_errors(#compile{options=Opts,errors=Errors}) ->
end.
report_warnings(#compile{options=Opts,warnings=Ws0}) ->
- case member(report_warnings, Opts) of
+ Werror = member(warnings_as_errors, Opts),
+ P = case Werror of
+ true -> "";
+ false -> "Warning: "
+ end,
+ ReportWerror = Werror andalso member(report_errors, Opts),
+ case member(report_warnings, Opts) orelse ReportWerror of
true ->
- Ws1 = flatmap(fun({{F,_L},Eds}) -> format_message(F, Eds);
- ({F,Eds}) -> format_message(F, Eds) end,
+ Ws1 = flatmap(fun({{F,_L},Eds}) -> format_message(F, P, Eds);
+ ({F,Eds}) -> format_message(F, P, Eds) end,
Ws0),
Ws = lists:sort(Ws1),
foreach(fun({_,Str}) -> io:put_chars(Str) end, Ws);
false -> ok
end.
-format_message(F, [{{Line,Column}=Loc,Mod,E}|Es]) ->
- M = {{F,Loc},io_lib:format("~s:~w:~w Warning: ~s\n",
- [F,Line,Column,Mod:format_error(E)])},
- [M|format_message(F, Es)];
-format_message(F, [{Line,Mod,E}|Es]) ->
- M = {{F,{Line,0}},io_lib:format("~s:~w: Warning: ~s\n",
- [F,Line,Mod:format_error(E)])},
- [M|format_message(F, Es)];
-format_message(F, [{Mod,E}|Es]) ->
- M = {none,io_lib:format("~s: Warning: ~s\n", [F,Mod:format_error(E)])},
- [M|format_message(F, Es)];
-format_message(_, []) -> [].
+format_message(F, P, [{{Line,Column}=Loc,Mod,E}|Es]) ->
+ M = {{F,Loc},io_lib:format("~s:~w:~w ~s~s\n",
+ [F,Line,Column,P,Mod:format_error(E)])},
+ [M|format_message(F, P, Es)];
+format_message(F, P, [{Line,Mod,E}|Es]) ->
+ M = {{F,{Line,0}},io_lib:format("~s:~w: ~s~s\n",
+ [F,Line,P,Mod:format_error(E)])},
+ [M|format_message(F, P, Es)];
+format_message(F, P, [{Mod,E}|Es]) ->
+ M = {none,io_lib:format("~s: ~s~s\n", [F,P,Mod:format_error(E)])},
+ [M|format_message(F, P, Es)];
+format_message(_, _, []) -> [].
%% list_errors(File, ErrorDescriptors) -> ok
@@ -1426,6 +1438,8 @@ iofile(File) when is_atom(File) ->
iofile(File) ->
{filename:dirname(File), filename:basename(File, ".erl")}.
+erlfile(".", Base, Suffix) ->
+ Base ++ Suffix;
erlfile(Dir, Base, Suffix) ->
filename:join(Dir, Base ++ Suffix).
@@ -1498,6 +1512,8 @@ restore_expand_module([{attribute,Line,opaque,[Type]}|Fs]) ->
[{attribute,Line,opaque,Type}|restore_expand_module(Fs)];
restore_expand_module([{attribute,Line,spec,[Arg]}|Fs]) ->
[{attribute,Line,spec,Arg}|restore_expand_module(Fs)];
+restore_expand_module([{attribute,Line,callback,[Arg]}|Fs]) ->
+ [{attribute,Line,callback,Arg}|restore_expand_module(Fs)];
restore_expand_module([F|Fs]) ->
[F|restore_expand_module(Fs)];
restore_expand_module([]) -> [].
diff --git a/lib/compiler/src/erl_bifs.erl b/lib/compiler/src/erl_bifs.erl
index f8128702dd..2514c06360 100644
--- a/lib/compiler/src/erl_bifs.erl
+++ b/lib/compiler/src/erl_bifs.erl
@@ -72,7 +72,6 @@ is_pure(erlang, binary_to_list, 1) -> true;
is_pure(erlang, binary_to_list, 3) -> true;
is_pure(erlang, bit_size, 1) -> true;
is_pure(erlang, byte_size, 1) -> true;
-is_pure(erlang, concat_binary, 1) -> true;
is_pure(erlang, element, 2) -> true;
is_pure(erlang, float, 1) -> true;
is_pure(erlang, float_to_list, 1) -> true;
diff --git a/lib/compiler/src/genop.tab b/lib/compiler/src/genop.tab
index 63527bda8f..39c1e8297f 100644
--- a/lib/compiler/src/genop.tab
+++ b/lib/compiler/src/genop.tab
@@ -280,3 +280,7 @@ BEAM_FORMAT_NUMBER=0
150: recv_mark/1
151: recv_set/1
152: gc_bif3/7
+
+# R15A
+
+153: line/1
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index 96015fbe58..6ea67741fa 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -460,7 +460,8 @@ eval_binary(#c_binary{anno=Anno,segments=Ss}=Bin) ->
Bin;
throw:{badarg,Warning} ->
add_warning(Bin, Warning),
- #c_call{module=#c_literal{val=erlang},
+ #c_call{anno=Anno,
+ module=#c_literal{val=erlang},
name=#c_literal{val=error},
args=[#c_literal{val=badarg}]}
end.
@@ -658,36 +659,34 @@ call_0(Call, M, N, As0, Sub) ->
%% We inline some very common higher order list operations.
%% We use the same evaluation order as the library function.
-call_1(_Call, lists, all, [Arg1,Arg2], Sub) ->
+call_1(#c_call{anno=Anno}, lists, all, [Arg1,Arg2], Sub) ->
Loop = #c_var{name={'lists^all',1}},
F = #c_var{name='F'},
Xs = #c_var{name='Xs'},
X = #c_var{name='X'},
Err1 = #c_tuple{es=[#c_literal{val='case_clause'}, X]},
CC1 = #c_clause{pats=[#c_literal{val=true}], guard=#c_literal{val=true},
- body=#c_apply{op=Loop, args=[Xs]}},
+ body=#c_apply{anno=Anno, op=Loop, args=[Xs]}},
CC2 = #c_clause{pats=[#c_literal{val=false}], guard=#c_literal{val=true},
body=#c_literal{val=false}},
CC3 = #c_clause{pats=[X], guard=#c_literal{val=true},
- body=#c_primop{name=#c_literal{val='match_fail'},
- args=[Err1]}},
+ body=match_fail(Anno, Err1)},
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
- body=#c_case{arg=#c_apply{op=F, args=[X]},
+ body=#c_case{arg=#c_apply{anno=Anno, op=F, args=[X]},
clauses = [CC1, CC2, CC3]}},
C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
body=#c_literal{val=true}},
Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=#c_primop{name=#c_literal{val='match_fail'},
- args=[Err2]}},
+ body=match_fail(Anno, Err2)},
Fun = #c_fun{vars=[Xs],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
expr(#c_let{vars=[F, L], arg=#c_values{es=[Arg1, Arg2]},
body=#c_letrec{defs=[{Loop,Fun}],
- body=#c_apply{op=Loop, args=[L]}}},
+ body=#c_apply{anno=Anno, op=Loop, args=[L]}}},
Sub);
-call_1(_Call, lists, any, [Arg1,Arg2], Sub) ->
+call_1(#c_call{anno=Anno}, lists, any, [Arg1,Arg2], Sub) ->
Loop = #c_var{name={'lists^any',1}},
F = #c_var{name='F'},
Xs = #c_var{name='Xs'},
@@ -696,72 +695,71 @@ call_1(_Call, lists, any, [Arg1,Arg2], Sub) ->
CC1 = #c_clause{pats=[#c_literal{val=true}], guard=#c_literal{val=true},
body=#c_literal{val=true}},
CC2 = #c_clause{pats=[#c_literal{val=false}], guard=#c_literal{val=true},
- body=#c_apply{op=Loop, args=[Xs]}},
+ body=#c_apply{anno=Anno, op=Loop, args=[Xs]}},
CC3 = #c_clause{pats=[X], guard=#c_literal{val=true},
- body=#c_primop{name=#c_literal{val='match_fail'},
- args=[Err1]}},
+ body=match_fail(Anno, Err1)},
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
- body=#c_case{arg=#c_apply{op=F, args=[X]},
+ body=#c_case{arg=#c_apply{anno=Anno, op=F, args=[X]},
clauses = [CC1, CC2, CC3]}},
C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
body=#c_literal{val=false}},
Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=#c_primop{name=#c_literal{val='match_fail'},
- args=[Err2]}},
+ body=match_fail(Anno, Err2)},
Fun = #c_fun{vars=[Xs],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
expr(#c_let{vars=[F, L], arg=#c_values{es=[Arg1, Arg2]},
body=#c_letrec{defs=[{Loop,Fun}],
- body=#c_apply{op=Loop, args=[L]}}},
+ body=#c_apply{anno=Anno, op=Loop, args=[L]}}},
Sub);
-call_1(_Call, lists, foreach, [Arg1,Arg2], Sub) ->
+call_1(#c_call{anno=Anno}, lists, foreach, [Arg1,Arg2], Sub) ->
Loop = #c_var{name={'lists^foreach',1}},
F = #c_var{name='F'},
Xs = #c_var{name='Xs'},
X = #c_var{name='X'},
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
- body=#c_seq{arg=#c_apply{op=F, args=[X]},
- body=#c_apply{op=Loop, args=[Xs]}}},
+ body=#c_seq{arg=#c_apply{anno=Anno, op=F, args=[X]},
+ body=#c_apply{anno=Anno, op=Loop, args=[Xs]}}},
C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
body=#c_literal{val=ok}},
Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=#c_primop{name=#c_literal{val='match_fail'},
- args=[Err]}},
+ body=match_fail(Anno, Err)},
Fun = #c_fun{vars=[Xs],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
expr(#c_let{vars=[F, L], arg=#c_values{es=[Arg1, Arg2]},
body=#c_letrec{defs=[{Loop,Fun}],
- body=#c_apply{op=Loop, args=[L]}}},
+ body=#c_apply{anno=Anno, op=Loop, args=[L]}}},
Sub);
-call_1(_Call, lists, map, [Arg1,Arg2], Sub) ->
+call_1(#c_call{anno=Anno}, lists, map, [Arg1,Arg2], Sub) ->
Loop = #c_var{name={'lists^map',1}},
F = #c_var{name='F'},
Xs = #c_var{name='Xs'},
X = #c_var{name='X'},
H = #c_var{name='H'},
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
- body=#c_let{vars=[H], arg=#c_apply{op=F, args=[X]},
+ body=#c_let{vars=[H], arg=#c_apply{anno=Anno,
+ op=F,
+ args=[X]},
body=#c_cons{hd=H,
- tl=#c_apply{op=Loop,
+ tl=#c_apply{anno=Anno,
+ op=Loop,
args=[Xs]}}}},
C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
body=#c_literal{val=[]}},
Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=#c_primop{name=#c_literal{val='match_fail'},
- args=[Err]}},
+ body=match_fail(Anno, Err)},
Fun = #c_fun{vars=[Xs],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
expr(#c_let{vars=[F, L], arg=#c_values{es=[Arg1, Arg2]},
body=#c_letrec{defs=[{Loop,Fun}],
- body=#c_apply{op=Loop, args=[L]}}},
+ body=#c_apply{anno=Anno, op=Loop, args=[L]}}},
Sub);
-call_1(_Call, lists, flatmap, [Arg1,Arg2], Sub) ->
+call_1(#c_call{anno=Anno}, lists, flatmap, [Arg1,Arg2], Sub) ->
Loop = #c_var{name={'lists^flatmap',1}},
F = #c_var{name='F'},
Xs = #c_var{name='Xs'},
@@ -769,26 +767,27 @@ call_1(_Call, lists, flatmap, [Arg1,Arg2], Sub) ->
H = #c_var{name='H'},
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
body=#c_let{vars=[H],
- arg=#c_apply{op=F, args=[X]},
- body=#c_call{module=#c_literal{val=erlang},
+ arg=#c_apply{anno=Anno, op=F, args=[X]},
+ body=#c_call{anno=Anno,
+ module=#c_literal{val=erlang},
name=#c_literal{val='++'},
args=[H,
- #c_apply{op=Loop,
+ #c_apply{anno=Anno,
+ op=Loop,
args=[Xs]}]}}},
C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
body=#c_literal{val=[]}},
Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=#c_primop{name=#c_literal{val='match_fail'},
- args=[Err]}},
+ body=match_fail(Anno, Err)},
Fun = #c_fun{vars=[Xs],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
expr(#c_let{vars=[F, L], arg=#c_values{es=[Arg1, Arg2]},
body=#c_letrec{defs=[{Loop,Fun}],
- body=#c_apply{op=Loop, args=[L]}}},
+ body=#c_apply{anno=Anno, op=Loop, args=[L]}}},
Sub);
-call_1(_Call, lists, filter, [Arg1,Arg2], Sub) ->
+call_1(#c_call{anno=Anno}, lists, filter, [Arg1,Arg2], Sub) ->
Loop = #c_var{name={'lists^filter',1}},
F = #c_var{name='F'},
Xs = #c_var{name='Xs'},
@@ -800,72 +799,75 @@ call_1(_Call, lists, filter, [Arg1,Arg2], Sub) ->
CC2 = #c_clause{pats=[#c_literal{val=false}], guard=#c_literal{val=true},
body=Xs},
CC3 = #c_clause{pats=[X], guard=#c_literal{val=true},
- body=#c_primop{name=#c_literal{val='match_fail'},
- args=[Err1]}},
+ body=match_fail(Anno, Err1)},
Case = #c_case{arg=B, clauses = [CC1, CC2, CC3]},
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
body=#c_let{vars=[B],
- arg=#c_apply{op=F, args=[X]},
+ arg=#c_apply{anno=Anno, op=F, args=[X]},
body=#c_let{vars=[Xs],
- arg=#c_apply{op=Loop,
+ arg=#c_apply{anno=Anno,
+ op=Loop,
args=[Xs]},
body=Case}}},
C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
body=#c_literal{val=[]}},
Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=#c_primop{name=#c_literal{val='match_fail'},
- args=[Err2]}},
+ body=match_fail(Anno, Err2)},
Fun = #c_fun{vars=[Xs],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
expr(#c_let{vars=[F, L], arg=#c_values{es=[Arg1, Arg2]},
body=#c_letrec{defs=[{Loop,Fun}],
- body=#c_apply{op=Loop, args=[L]}}},
+ body=#c_apply{anno=Anno, op=Loop, args=[L]}}},
Sub);
-call_1(_Call, lists, foldl, [Arg1,Arg2,Arg3], Sub) ->
+call_1(#c_call{anno=Anno}, lists, foldl, [Arg1,Arg2,Arg3], Sub) ->
Loop = #c_var{name={'lists^foldl',2}},
F = #c_var{name='F'},
Xs = #c_var{name='Xs'},
X = #c_var{name='X'},
A = #c_var{name='A'},
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
- body=#c_apply{op=Loop,
- args=[Xs, #c_apply{op=F, args=[X, A]}]}},
+ body=#c_apply{anno=Anno,
+ op=Loop,
+ args=[Xs, #c_apply{anno=Anno,
+ op=F,
+ args=[X, A]}]}},
C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true}, body=A},
Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=#c_primop{name=#c_literal{val='match_fail'},
- args=[Err]}},
+ body=match_fail(Anno, Err)},
Fun = #c_fun{vars=[Xs, A],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
expr(#c_let{vars=[F, A, L], arg=#c_values{es=[Arg1, Arg2, Arg3]},
body=#c_letrec{defs=[{Loop,Fun}],
- body=#c_apply{op=Loop, args=[L, A]}}},
+ body=#c_apply{anno=Anno, op=Loop, args=[L, A]}}},
Sub);
-call_1(_Call, lists, foldr, [Arg1,Arg2,Arg3], Sub) ->
+call_1(#c_call{anno=Anno}, lists, foldr, [Arg1,Arg2,Arg3], Sub) ->
Loop = #c_var{name={'lists^foldr',2}},
F = #c_var{name='F'},
Xs = #c_var{name='Xs'},
X = #c_var{name='X'},
A = #c_var{name='A'},
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
- body=#c_apply{op=F, args=[X, #c_apply{op=Loop,
- args=[Xs, A]}]}},
+ body=#c_apply{anno=Anno,
+ op=F,
+ args=[X, #c_apply{anno=Anno,
+ op=Loop,
+ args=[Xs, A]}]}},
C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true}, body=A},
Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=#c_primop{name=#c_literal{val='match_fail'},
- args=[Err]}},
+ body=match_fail(Anno, Err)},
Fun = #c_fun{vars=[Xs, A],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
expr(#c_let{vars=[F, A, L], arg=#c_values{es=[Arg1, Arg2, Arg3]},
body=#c_letrec{defs=[{Loop,Fun}],
- body=#c_apply{op=Loop, args=[L, A]}}},
+ body=#c_apply{anno=Anno, op=Loop, args=[L, A]}}},
Sub);
-call_1(_Call, lists, mapfoldl, [Arg1,Arg2,Arg3], Sub) ->
+call_1(#c_call{anno=Anno}, lists, mapfoldl, [Arg1,Arg2,Arg3], Sub) ->
Loop = #c_var{name={'lists^mapfoldl',2}},
F = #c_var{name='F'},
Xs = #c_var{name='Xs'},
@@ -876,15 +878,16 @@ call_1(_Call, lists, mapfoldl, [Arg1,Arg2,Arg3], Sub) ->
C1 = #c_clause{pats=[P], guard=#c_literal{val=true}, body=E},
Err = #c_tuple{es=[#c_literal{val='badmatch'}, X]},
C2 = #c_clause{pats=[X], guard=#c_literal{val=true},
- body=#c_primop{name=#c_literal{val='match_fail'},
- args=[Err]}},
+ body=match_fail(Anno, Err)},
#c_case{arg=A, clauses=[C1, C2]}
end,
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
- body=Match(#c_apply{op=F, args=[X, Avar]},
+ body=Match(#c_apply{anno=Anno, op=F, args=[X, Avar]},
#c_tuple{es=[X, Avar]},
%%% Tuple passing version
- Match(#c_apply{op=Loop, args=[Xs, Avar]},
+ Match(#c_apply{anno=Anno,
+ op=Loop,
+ args=[Xs, Avar]},
#c_tuple{es=[Xs, Avar]},
#c_tuple{es=[#c_cons{hd=X, tl=Xs}, Avar]})
%%% Multiple-value version
@@ -902,22 +905,23 @@ call_1(_Call, lists, mapfoldl, [Arg1,Arg2,Arg3], Sub) ->
%%% body=#c_values{es=[#c_literal{val=[]}, A]}},
Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=#c_primop{name=#c_literal{val='match_fail'},
- args=[Err]}},
+ body=match_fail(Anno, Err)},
Fun = #c_fun{vars=[Xs, Avar],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
expr(#c_let{vars=[F, Avar, L], arg=#c_values{es=[Arg1, Arg2, Arg3]},
body=#c_letrec{defs=[{Loop,Fun}],
%%% Tuple passing version
- body=#c_apply{op=Loop, args=[L, Avar]}}},
+ body=#c_apply{anno=Anno,
+ op=Loop,
+ args=[L, Avar]}}},
%%% Multiple-value version
%%% body=#c_let{vars=[Xs, A],
%%% arg=#c_apply{op=Loop,
%%% args=[L, A]},
%%% body=#c_tuple{es=[Xs, A]}}}},
Sub);
-call_1(_Call, lists, mapfoldr, [Arg1,Arg2,Arg3], Sub) ->
+call_1(#c_call{anno=Anno}, lists, mapfoldr, [Arg1,Arg2,Arg3], Sub) ->
Loop = #c_var{name={'lists^mapfoldr',2}},
F = #c_var{name='F'},
Xs = #c_var{name='Xs'},
@@ -928,15 +932,16 @@ call_1(_Call, lists, mapfoldr, [Arg1,Arg2,Arg3], Sub) ->
C1 = #c_clause{pats=[P], guard=#c_literal{val=true}, body=E},
Err = #c_tuple{es=[#c_literal{val='badmatch'}, X]},
C2 = #c_clause{pats=[X], guard=#c_literal{val=true},
- body=#c_primop{name=#c_literal{val='match_fail'},
- args=[Err]}},
+ body=match_fail(Anno, Err)},
#c_case{arg=A, clauses=[C1, C2]}
end,
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
%%% Tuple passing version
- body=Match(#c_apply{op=Loop, args=[Xs, Avar]},
+ body=Match(#c_apply{anno=Anno,
+ op=Loop,
+ args=[Xs, Avar]},
#c_tuple{es=[Xs, Avar]},
- Match(#c_apply{op=F, args=[X, Avar]},
+ Match(#c_apply{anno=Anno, op=F, args=[X, Avar]},
#c_tuple{es=[X, Avar]},
#c_tuple{es=[#c_cons{hd=X, tl=Xs}, Avar]}))
%%% Multiple-value version
@@ -955,15 +960,16 @@ call_1(_Call, lists, mapfoldr, [Arg1,Arg2,Arg3], Sub) ->
%%% body=#c_values{es=[#c_literal{val=[]}, A]}},
Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=#c_primop{name=#c_literal{val='match_fail'},
- args=[Err]}},
+ body=match_fail(Anno, Err)},
Fun = #c_fun{vars=[Xs, Avar],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
expr(#c_let{vars=[F, Avar, L], arg=#c_values{es=[Arg1, Arg2, Arg3]},
body=#c_letrec{defs=[{Loop,Fun}],
%%% Tuple passing version
- body=#c_apply{op=Loop, args=[L, Avar]}}},
+ body=#c_apply{anno=Anno,
+ op=Loop,
+ args=[L, Avar]}}},
%%% Multiple-value version
%%% body=#c_let{vars=[Xs, A],
%%% arg=#c_apply{op=Loop,
@@ -973,6 +979,11 @@ call_1(_Call, lists, mapfoldr, [Arg1,Arg2,Arg3], Sub) ->
call_1(#c_call{module=M, name=N}=Call, _, _, As, Sub) ->
call_0(Call, M, N, As, Sub).
+match_fail(Anno, Arg) ->
+ #c_primop{anno=Anno,
+ name=#c_literal{val='match_fail'},
+ args=[Arg]}.
+
%% fold_call(Call, Mod, Name, Args, Sub) -> Expr.
%% Try to safely evaluate the call. Just try to evaluate arguments,
%% do the call and convert return values to literals. If this
@@ -1280,9 +1291,9 @@ eval_setelement_2(Pos, [H|T], NewVal) when Pos > 1 ->
%%
eval_failure(Call, Reason) ->
add_warning(Call, {eval_failure,Reason}),
- #c_call{module=#c_literal{val=erlang},
- name=#c_literal{val=error},
- args=[#c_literal{val=Reason}]}.
+ Call#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=error},
+ args=[#c_literal{val=Reason}]}.
%% simplify_apply(Call0, Mod, Func, Args) -> Call
%% Simplify an apply/3 to a call if the number of arguments
@@ -1742,23 +1753,24 @@ opt_bool_clauses([_|_], _, _) ->
opt_bool_not(#c_case{arg=Arg,clauses=Cs0}=Case0) ->
case Arg of
- #c_call{module=#c_literal{val=erlang},
+ #c_call{anno=Anno,module=#c_literal{val=erlang},
name=#c_literal{val='not'},
args=[Expr]} ->
- Cs = opt_bool_not(Expr, Cs0),
+ Cs = opt_bool_not(Anno, Expr, Cs0),
Case = Case0#c_case{arg=Expr,clauses=Cs},
opt_bool_not(Case);
_ ->
opt_bool_case_redundant(Case0)
end.
-opt_bool_not(Expr, Cs) ->
+opt_bool_not(Anno, Expr, Cs) ->
Tail = case is_bool_expr(Expr) of
false ->
[#c_clause{anno=[compiler_generated],
pats=[#c_var{name=cor_variable}],
guard=#c_literal{val=true},
- body=#c_call{module=#c_literal{val=erlang},
+ body=#c_call{anno=Anno,
+ module=#c_literal{val=erlang},
name=#c_literal{val=error},
args=[#c_literal{val=badarg}]}}];
true -> []
@@ -1957,13 +1969,25 @@ case_tuple_pat([#c_tuple{es=Ps}], Arity) when length(Ps) =:= Arity ->
case_tuple_pat([#c_literal{val=T}], Arity) when tuple_size(T) =:= Arity ->
Ps = [#c_literal{val=E} || E <- tuple_to_list(T)],
{ok,Ps,[]};
-case_tuple_pat([#c_var{anno=A}=V], Arity) ->
- Vars = make_vars(A, 1, Arity),
- {ok,Vars,[{V,#c_tuple{es=Vars}}]};
+case_tuple_pat([#c_var{anno=Anno0}=V], Arity) ->
+ Vars = make_vars(Anno0, 1, Arity),
+
+ %% If the entire case statement is evaluated in an effect
+ %% context (e.g. "case {A,B} of ... end, ok"), there will
+ %% be a warning that a term is constructed but never used.
+ %% To avoid that warning, we must annotate the tuple as
+ %% compiler generated.
+
+ Anno = [compiler_generated|Anno0],
+ {ok,Vars,[{V,#c_tuple{anno=Anno,es=Vars}}]};
case_tuple_pat([#c_alias{var=V,pat=P}], Arity) ->
case case_tuple_pat([P], Arity) of
- {ok,Ps,Avs} -> {ok,Ps,[{V,#c_tuple{es=unalias_pat_list(Ps)}}|Avs]};
- error -> error
+ {ok,Ps,Avs} ->
+ Anno0 = core_lib:get_anno(P),
+ Anno = [compiler_generated|Anno0],
+ {ok,Ps,[{V,#c_tuple{anno=Anno,es=unalias_pat_list(Ps)}}|Avs]};
+ error ->
+ error
end;
case_tuple_pat(_, _) -> error.
diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl
index 480954adac..0fa1fea09f 100644
--- a/lib/compiler/src/sys_pre_expand.erl
+++ b/lib/compiler/src/sys_pre_expand.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,7 @@
mod_imports, %Module Imports
compile=[], %Compile flags
attributes=[], %Attributes
+ callbacks=[], %Callbacks
defined=[], %Defined functions
vcount=0, %Variable counter
func=[], %Current function
@@ -172,10 +173,41 @@ define_functions(Forms, #expand{defined=Predef}=St) ->
end, Predef, Forms),
St#expand{defined=ordsets:from_list(Fs)}.
-module_attrs(St) ->
- {[{attribute,Line,Name,Val} || {Name,Line,Val} <- St#expand.attributes],St}.
+module_attrs(#expand{attributes=Attributes}=St) ->
+ Attrs = [{attribute,Line,Name,Val} || {Name,Line,Val} <- Attributes],
+ Callbacks = [Callback || {_,_,callback,_}=Callback <- Attrs],
+ {Attrs,St#expand{callbacks=Callbacks}}.
module_predef_funcs(St) ->
+ {Mpf1,St1}=module_predef_func_beh_info(St),
+ {Mpf2,St2}=module_predef_funcs_mod_info(St1),
+ {Mpf1++Mpf2,St2}.
+
+module_predef_func_beh_info(#expand{callbacks=[]}=St) ->
+ {[], St};
+module_predef_func_beh_info(#expand{callbacks=Callbacks,defined=Defined,
+ exports=Exports}=St) ->
+ PreDef=[{behaviour_info,1}],
+ PreExp=PreDef,
+ {[gen_beh_info(Callbacks)],
+ St#expand{defined=union(from_list(PreDef), Defined),
+ exports=union(from_list(PreExp), Exports)}}.
+
+gen_beh_info(Callbacks) ->
+ List = make_list(Callbacks),
+ {function,0,behaviour_info,1,
+ [{clause,0,[{atom,0,callbacks}],[],
+ [List]}]}.
+
+make_list([]) -> {nil,0};
+make_list([{_,_,_,[{{Name,Arity},_}]}|Rest]) ->
+ {cons,0,
+ {tuple,0,
+ [{atom,0,Name},
+ {integer,0,Arity}]},
+ make_list(Rest)}.
+
+module_predef_funcs_mod_info(St) ->
PreDef = [{module_info,0},{module_info,1}],
PreExp = PreDef,
{[{function,0,module_info,0,
@@ -223,10 +255,8 @@ attribute(export, Es, _L, St) ->
St#expand{exports=union(from_list(Es), St#expand.exports)};
attribute(import, Is, _L, St) ->
import(Is, St);
-attribute(compile, C, _L, St) when is_list(C) ->
- St#expand{compile=St#expand.compile ++ C};
-attribute(compile, C, _L, St) ->
- St#expand{compile=St#expand.compile ++ [C]};
+attribute(compile, _C, _L, St) ->
+ St;
attribute(Name, Val, Line, St) when is_list(Val) ->
St#expand{attributes=St#expand.attributes ++ [{Name,Line,Val}]};
attribute(Name, Val, Line, St) ->
diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl
index 55e3c58d2a..e7dae67085 100644
--- a/lib/compiler/src/v3_codegen.erl
+++ b/lib/compiler/src/v3_codegen.erl
@@ -79,9 +79,10 @@ module({Mod,Exp,Attr,Forms}, Options) ->
functions(Forms, AtomMod) ->
mapfoldl(fun (F, St) -> function(F, AtomMod, St) end, #cg{lcount=1}, Forms).
-function({function,Name,Arity,Asm0,Vb,Vdb}, AtomMod, St0) ->
+function({function,Name,Arity,Asm0,Vb,Vdb,Anno}, AtomMod, St0) ->
try
- {Asm,EntryLabel,St} = cg_fun(Vb, Asm0, Vdb, AtomMod, {Name,Arity}, St0),
+ {Asm,EntryLabel,St} = cg_fun(Vb, Asm0, Vdb, AtomMod,
+ {Name,Arity}, Anno, St0),
Func = {function,Name,Arity,EntryLabel,Asm},
{Func,St}
catch
@@ -93,7 +94,7 @@ function({function,Name,Arity,Asm0,Vb,Vdb}, AtomMod, St0) ->
%% cg_fun([Lkexpr], [HeadVar], Vdb, State) -> {[Ainstr],State}
-cg_fun(Les, Hvs, Vdb, AtomMod, NameArity, St0) ->
+cg_fun(Les, Hvs, Vdb, AtomMod, NameArity, Anno, St0) ->
{Fi,St1} = new_label(St0), %FuncInfo label
{Fl,St2} = local_func_label(NameArity, St1),
@@ -129,7 +130,7 @@ cg_fun(Les, Hvs, Vdb, AtomMod, NameArity, St0) ->
ultimate_failure=UltimateMatchFail,
is_top_block=true}),
{Name,Arity} = NameArity,
- Asm = [{label,Fi},{func_info,AtomMod,{atom,Name},Arity},
+ Asm = [{label,Fi},line(Anno),{func_info,AtomMod,{atom,Name},Arity},
{label,Fl}|B++[{label,UltimateMatchFail},if_end]],
{Asm,Fl,St}.
@@ -307,23 +308,23 @@ match_fail_cg({badmatch,Term}, Le, Vdb, Bef, St) ->
R = cg_reg_arg(Term, Bef),
Int0 = clear_dead(Bef, Le#l.i, Vdb),
{Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
- {Sis ++ [{badmatch,R}],
+ {Sis ++ [line(Le),{badmatch,R}],
Int#sr{reg=clear_regs(Int0#sr.reg)},St};
match_fail_cg({case_clause,Reason}, Le, Vdb, Bef, St) ->
R = cg_reg_arg(Reason, Bef),
Int0 = clear_dead(Bef, Le#l.i, Vdb),
{Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
- {Sis++[{case_end,R}],
+ {Sis++[line(Le),{case_end,R}],
Int#sr{reg=clear_regs(Bef#sr.reg)},St};
match_fail_cg(if_clause, Le, Vdb, Bef, St) ->
Int0 = clear_dead(Bef, Le#l.i, Vdb),
{Sis,Int1} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
- {Sis++[if_end],Int1#sr{reg=clear_regs(Int1#sr.reg)},St};
+ {Sis++[line(Le),if_end],Int1#sr{reg=clear_regs(Int1#sr.reg)},St};
match_fail_cg({try_clause,Reason}, Le, Vdb, Bef, St) ->
R = cg_reg_arg(Reason, Bef),
Int0 = clear_dead(Bef, Le#l.i, Vdb),
{Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
- {Sis ++ [{try_case_end,R}],
+ {Sis ++ [line(Le),{try_case_end,R}],
Int#sr{reg=clear_regs(Int0#sr.reg)},St}.
%% bsm_rename_ctx([Clause], Var) -> [Clause]
@@ -1047,7 +1048,7 @@ call_cg({var,_V} = Var, As, Rs, Le, Vdb, Bef, St0) ->
%% Build complete code and final stack/register state.
Arity = length(As),
{Frees,Aft} = free_dead(clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb)),
- {Sis ++ Frees ++ [{call_fun,Arity}],Aft,
+ {Sis ++ Frees ++ [line(Le),{call_fun,Arity}],Aft,
need_stack_frame(St0)};
call_cg({remote,Mod,Name}, As, Rs, Le, Vdb, Bef, St0)
when element(1, Mod) =:= var;
@@ -1057,11 +1058,10 @@ call_cg({remote,Mod,Name}, As, Rs, Le, Vdb, Bef, St0)
Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
%% Build complete code and final stack/register state.
Arity = length(As),
- Call = {apply,Arity},
St = need_stack_frame(St0),
%%{Call,St1} = build_call(Func, Arity, St0),
{Frees,Aft} = free_dead(clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb)),
- {Sis ++ Frees ++ [Call],Aft,St};
+ {Sis ++ Frees ++ [line(Le),{apply,Arity}],Aft,St};
call_cg(Func, As, Rs, Le, Vdb, Bef, St0) ->
case St0 of
#cg{bfail=Fail} when Fail =/= 0 ->
@@ -1091,7 +1091,7 @@ call_cg(Func, As, Rs, Le, Vdb, Bef, St0) ->
Arity = length(As),
{Call,St1} = build_call(Func, Arity, St0),
{Frees,Aft} = free_dead(clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb)),
- {Sis ++ Frees ++ Call,Aft,St1}
+ {Sis ++ Frees ++ [line(Le)|Call],Aft,St1}
end.
build_call({remote,{atom,erlang},{atom,'!'}}, 2, St0) ->
@@ -1118,7 +1118,7 @@ enter_cg({var,_V} = Var, As, Le, Vdb, Bef, St0) ->
{Sis,Int} = cg_setup_call(As++[Var], Bef, Le#l.i, Vdb),
%% Build complete code and final stack/register state.
Arity = length(As),
- {Sis ++ [{call_fun,Arity},return],
+ {Sis ++ [line(Le),{call_fun,Arity},return],
clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
need_stack_frame(St0)};
enter_cg({remote,Mod,Name}, As, Le, Vdb, Bef, St0)
@@ -1127,9 +1127,8 @@ enter_cg({remote,Mod,Name}, As, Le, Vdb, Bef, St0)
{Sis,Int} = cg_setup_call(As++[Mod,Name], Bef, Le#l.i, Vdb),
%% Build complete code and final stack/register state.
Arity = length(As),
- Call = {apply_only,Arity},
St = need_stack_frame(St0),
- {Sis ++ [Call],
+ {Sis ++ [line(Le),{apply_only,Arity}],
clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
St};
enter_cg(Func, As, Le, Vdb, Bef, St0) ->
@@ -1137,7 +1136,8 @@ enter_cg(Func, As, Le, Vdb, Bef, St0) ->
%% Build complete code and final stack/register state.
Arity = length(As),
{Call,St1} = build_enter(Func, Arity, St0),
- {Sis ++ Call,
+ Line = enter_line(Func, Arity, Le),
+ {Sis ++ Line ++ Call,
clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
St1}.
@@ -1153,6 +1153,23 @@ build_enter(Name, Arity, St0) when is_atom(Name) ->
{Lbl,St1} = local_func_label(Name, Arity, St0),
{[{call_only,Arity,{f,Lbl}}],St1}.
+enter_line({remote,{atom,Mod},{atom,Name}}, Arity, Le) ->
+ case erl_bifs:is_safe(Mod, Name, Arity) of
+ false ->
+ %% Tail-recursive call, possibly to a BIF.
+ %% We'll need a line instruction in case the
+ %% BIF call fails.
+ [line(Le)];
+ true ->
+ %% Call to a safe BIF. Since it cannot fail,
+ %% we don't need any line instruction here.
+ []
+ end;
+enter_line(_, _, _) ->
+ %% Tail-recursive call to a local function. A line
+ %% instruction will not be useful.
+ [].
+
%% local_func_label(Name, Arity, State) -> {Label,State'}
%% local_func_label({Name,Arity}, State) -> {Label,State'}
%% Get the function entry label for a local function.
@@ -1226,9 +1243,10 @@ bif_cg(Bif, As, [{var,V}], Le, Vdb, Bef, St0) ->
%% Currently, we are somewhat pessimistic in
%% that we save any variable that will be live after this BIF call.
+ MayFail = not erl_bifs:is_safe(erlang, Bif, length(As)),
{Sis,Int0} = case St0#cg.in_catch andalso
St0#cg.bfail =:= 0 andalso
- not erl_bifs:is_safe(erlang, Bif, length(As)) of
+ MayFail of
true -> adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb);
false -> {[],Bef}
end,
@@ -1237,7 +1255,14 @@ bif_cg(Bif, As, [{var,V}], Le, Vdb, Bef, St0) ->
Int = Int1#sr{reg=Reg},
Dst = fetch_reg(V, Reg),
BifFail = {f,St0#cg.bfail},
- {Sis++[{bif,Bif,BifFail,Ars,Dst}],
+ %% We need a line instructions for BIFs that may fail in a body.
+ Line = case BifFail of
+ {f,0} when MayFail ->
+ [line(Le)];
+ _ ->
+ []
+ end,
+ {Sis++Line++[{bif,Bif,BifFail,Ars,Dst}],
clear_dead(Int, Le#l.i, Vdb), St0}.
@@ -1266,7 +1291,11 @@ gc_bif_cg(Bif, As, [{var,V}], Le, Vdb, Bef, St0) ->
Int = Int1#sr{reg=Reg},
Dst = fetch_reg(V, Reg),
BifFail = {f,St0#cg.bfail},
- {Sis++[{gc_bif,Bif,BifFail,max_reg(Bef#sr.reg),Ars,Dst}],
+ Line = case BifFail of
+ {f,0} -> [line(Le)];
+ {f,_} -> []
+ end,
+ {Sis++Line++[{gc_bif,Bif,BifFail,max_reg(Bef#sr.reg),Ars,Dst}],
clear_dead(Int, Le#l.i, Vdb), St0}.
%% recv_loop_cg(TimeOut, ReceiveVar, ReceiveMatch, TimeOutExprs,
@@ -1284,7 +1313,7 @@ recv_loop_cg(Te, Rvar, Rm, Tes, Rs, Le, Vdb, Bef, St0) ->
{Wis,Taft,St6} = cg_recv_wait(Te, Tes, Le#l.i, Int1, St5),
Int2 = sr_merge(Raft, Taft), %Merge stack/registers
Reg = load_vars(Rs, Int2#sr.reg),
- {Sis ++ Ris ++ [{label,Tl}] ++ Wis ++ [{label,Bl}],
+ {Sis ++ [line(Le)] ++ Ris ++ [{label,Tl}] ++ Wis ++ [{label,Bl}],
clear_dead(Int2#sr{reg=Reg}, Le#l.i, Vdb),
St6#cg{break=St0#cg.break,recv=St0#cg.recv}}.
@@ -1463,12 +1492,13 @@ cg_binary([{bs_put_binary,Fail,{atom,all},U,_Flags,Src}|PutCode],
{bs_append,Fail,Target,0,MaxRegs,U,Src,BinFlags,Target}
end] ++ PutCode,
cg_bin_opt(Code);
-cg_binary(PutCode, Target, Temp, Fail, MaxRegs, _Anno) ->
+cg_binary(PutCode, Target, Temp, Fail, MaxRegs, Anno) ->
+ Line = line(Anno),
Live = cg_live(Target, MaxRegs),
{InitOp,SzCode} = cg_binary_size(PutCode, Target, Temp, Fail, Live),
- Code = SzCode ++ [{InitOp,Fail,Target,0,MaxRegs,
- {field_flags,[]},Target}|PutCode],
+ Code = [Line|SzCode] ++ [{InitOp,Fail,Target,0,MaxRegs,
+ {field_flags,[]},Target}|PutCode],
cg_bin_opt(Code).
cg_live({x,X}, MaxRegs) when X =:= MaxRegs -> MaxRegs+1;
@@ -2052,6 +2082,38 @@ drop_catch(Tag, [Other|Stk]) -> [Other|drop_catch(Tag, Stk)].
new_label(#cg{lcount=Next}=St) ->
{Next,St#cg{lcount=Next+1}}.
+%% line(Le) -> {line,[] | {location,File,Line}}
+%% Create a line instruction, containing information about
+%% the current filename and line number. A line information
+%% instruction should be placed before any operation that could
+%% cause an exception.
+
+line(#l{a=Anno}) ->
+ line(Anno);
+line([Line,{file,Name}]) when is_integer(Line) ->
+ line_1(Name, Line);
+line([_|_]=A) ->
+ {Name,Line} = find_loc(A, no_file, 0),
+ line_1(Name, Line);
+line([]) ->
+ {line,[]}.
+
+line_1(no_file, _) ->
+ {line,[]};
+line_1(_, 0) ->
+ %% Missing line number or line number 0.
+ {line,[]};
+line_1(Name, Line) ->
+ {line,[{location,Name,abs(Line)}]}.
+
+find_loc([Line|T], File, _) when is_integer(Line) ->
+ find_loc(T, File, Line);
+find_loc([{file,File}|T], _, Line) ->
+ find_loc(T, File, Line);
+find_loc([_|T], File, Line) ->
+ find_loc(T, File, Line);
+find_loc([], File, Line) -> {File,Line}.
+
flatmapfoldl(F, Accu0, [Hd|Tail]) ->
{R,Accu1} = F(Hd, Accu0),
{Rs,Accu2} = flatmapfoldl(F, Accu1, Tail),
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index e1a593fffa..6f3590b156 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -180,7 +180,7 @@ body(Cs0, Name, Arity, St0) ->
{Args,St1} = new_vars(Anno, Arity, St0),
{Cs1,St2} = clauses(Cs0, St1),
{Ps,St3} = new_vars(Arity, St2), %Need new variables here
- Fc = function_clause(Ps, {Name,Arity}),
+ Fc = function_clause(Ps, Anno, {Name,Arity}),
{#ifun{anno=#a{anno=Anno},id=[],vars=Args,clauses=Cs1,fc=Fc},St3}.
%% clause(Clause, State) -> {Cclause,State} | noclause.
@@ -507,15 +507,15 @@ expr({block,_,Es0}, St0) ->
{E1,Es1 ++ Eps,St2};
expr({'if',L,Cs0}, St0) ->
{Cs1,St1} = clauses(Cs0, St0),
- Fc = fail_clause([], #c_literal{val=if_clause}),
Lanno = lineno_anno(L, St1),
+ Fc = fail_clause([], Lanno, #c_literal{val=if_clause}),
{#icase{anno=#a{anno=Lanno},args=[],clauses=Cs1,fc=Fc},[],St1};
expr({'case',L,E0,Cs0}, St0) ->
{E1,Eps,St1} = novars(E0, St0),
{Cs1,St2} = clauses(Cs0, St1),
{Fpat,St3} = new_var(St2),
- Fc = fail_clause([Fpat], c_tuple([#c_literal{val=case_clause},Fpat])),
- Lanno = lineno_anno(L, St3),
+ Lanno = lineno_anno(L, St2),
+ Fc = fail_clause([Fpat], Lanno, c_tuple([#c_literal{val=case_clause},Fpat])),
{#icase{anno=#a{anno=Lanno},args=[E1],clauses=Cs1,fc=Fc},Eps,St3};
expr({'receive',L,Cs0}, St0) ->
{Cs1,St1} = clauses(Cs0, St0),
@@ -541,9 +541,10 @@ expr({'try',L,Es0,Cs0,Ecs,[]}, St0) ->
{V,St2} = new_var(St1), %This name should be arbitrary
{Cs1,St3} = clauses(Cs0, St2),
{Fpat,St4} = new_var(St3),
- Fc = fail_clause([Fpat], c_tuple([#c_literal{val=try_clause},Fpat])),
+ Lanno = lineno_anno(L, St4),
+ Fc = fail_clause([Fpat], Lanno,
+ c_tuple([#c_literal{val=try_clause},Fpat])),
{Evs,Hs,St5} = try_exception(Ecs, St4),
- Lanno = lineno_anno(L, St1),
{#itry{anno=#a{anno=lineno_anno(L, St5)},args=Es1,
vars=[V],body=[#icase{anno=#a{anno=Lanno},args=[V],clauses=Cs1,fc=Fc}],
evars=Evs,handler=Hs},
@@ -607,8 +608,8 @@ expr({match,L,P0,E0}, St0) ->
Thrown
end,
{Fpat,St4} = new_var(St3),
- Fc = fail_clause([Fpat], c_tuple([#c_literal{val=badmatch},Fpat])),
Lanno = lineno_anno(L, St4),
+ Fc = fail_clause([Fpat], Lanno, c_tuple([#c_literal{val=badmatch},Fpat])),
case P2 of
nomatch ->
St = add_warning(L, nomatch, St4),
@@ -828,8 +829,9 @@ fun_tq({_,_,Name}=Id, Cs0, L, St0) ->
{Cs1,St1} = clauses(Cs0, St0),
{Args,St2} = new_vars(Arity, St1),
{Ps,St3} = new_vars(Arity, St2), %Need new variables here
- Fc = function_clause(Ps, {Name,Arity}),
- Fun = #ifun{anno=#a{anno=lineno_anno(L, St3)},
+ Anno = lineno_anno(L, St3),
+ Fc = function_clause(Ps, Anno, {Name,Arity}),
+ Fun = #ifun{anno=#a{anno=Anno},
id=[{id,Id}], %We KNOW!
vars=Args,clauses=Cs1,fc=Fc},
{Fun,[],St3}.
@@ -929,7 +931,7 @@ lc_tq(Line, E, [{b_generate,Lg,P,G}|Qs0], Mc, St0) ->
[],St};
lc_tq(Line, E, [Fil0|Qs0], Mc, St0) ->
%% Special case sequences guard tests.
- LA = lineno_anno(Line, St0),
+ LA = lineno_anno(element(2, Fil0), St0),
LAnno = #a{anno=LA},
case is_guard_test(Fil0) of
true ->
@@ -945,7 +947,8 @@ lc_tq(Line, E, [Fil0|Qs0], Mc, St0) ->
false ->
{Lc,Lps,St1} = lc_tq(Line, E, Qs0, Mc, St0),
{Fpat,St2} = new_var(St1),
- Fc = fail_clause([Fpat], c_tuple([#c_literal{val=case_clause},Fpat])),
+ Fc = fail_clause([Fpat], LA,
+ c_tuple([#c_literal{val=case_clause},Fpat])),
%% Do a novars little optimisation here.
{Filc,Fps,St3} = novars(Fil0, St2),
{#icase{anno=LAnno,
@@ -1072,7 +1075,7 @@ bc_tq1(Line, E, [{b_generate,Lg,P,G}|Qs0], AccExpr, St0) ->
[],St};
bc_tq1(Line, E, [Fil0|Qs0], AccVar, St0) ->
%% Special case sequences guard tests.
- LA = lineno_anno(Line, St0),
+ LA = lineno_anno(element(2, Fil0), St0),
LAnno = #a{anno=LA},
case is_guard_test(Fil0) of
true ->
@@ -1089,7 +1092,8 @@ bc_tq1(Line, E, [Fil0|Qs0], AccVar, St0) ->
false ->
{Bc,Bps,St1} = bc_tq1(Line, E, Qs0, AccVar, St0),
{Fpat,St2} = new_var(St1),
- Fc = fail_clause([Fpat], c_tuple([#c_literal{val=case_clause},Fpat])),
+ Fc = fail_clause([Fpat], LA,
+ c_tuple([#c_literal{val=case_clause},Fpat])),
%% Do a novars little optimisation here.
{Filc,Fps,St} = novars(Fil0, St2),
{#icase{anno=LAnno,
@@ -1562,17 +1566,11 @@ new_vars_1(N, Anno, St0, Vs) when N > 0 ->
new_vars_1(N-1, Anno, St1, [V|Vs]);
new_vars_1(0, _, St, Vs) -> {Vs,St}.
-function_clause(Ps, Name) ->
- function_clause(Ps, [], Name).
-
function_clause(Ps, LineAnno, Name) ->
- FcAnno = [{function_name,Name}],
+ FcAnno = [{function_name,Name}|LineAnno],
fail_clause(Ps, FcAnno,
ann_c_tuple(LineAnno, [#c_literal{val=function_clause}|Ps])).
-fail_clause(Pats, Arg) ->
- fail_clause(Pats, [], Arg).
-
fail_clause(Pats, Anno, Arg) ->
#iclause{anno=#a{anno=[compiler_generated]},
pats=Pats,guard=[],
diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl
index 3b33a08cf7..4e06b464a4 100644
--- a/lib/compiler/src/v3_kernel.erl
+++ b/lib/compiler/src/v3_kernel.erl
@@ -247,7 +247,7 @@ expr(#c_var{anno=A,name={_Name,Arity}}=Fname, Sub, St) ->
%% instead of one for each occurrence as done now.
Vs = [#c_var{name=list_to_atom("V" ++ integer_to_list(V))} ||
V <- integers(1, Arity)],
- Fun = #c_fun{anno=A,vars=Vs,body=#c_apply{op=Fname,args=Vs}},
+ Fun = #c_fun{anno=A,vars=Vs,body=#c_apply{anno=A,op=Fname,args=Vs}},
expr(Fun, Sub, St);
expr(#c_var{anno=A,name=V}, Sub, St) ->
{#k_var{anno=A,name=get_vsub(V, Sub)},[],St};
@@ -291,7 +291,7 @@ expr(#c_binary{anno=A,segments=Cv}, Sub, St0) ->
Erl = #c_literal{val=erlang},
Name = #c_literal{val=error},
Args = [#c_literal{val=badarg}],
- Error = #c_call{module=Erl,name=Name,args=Args},
+ Error = #c_call{anno=A,module=Erl,name=Name,args=Args},
expr(Error, Sub, St0)
end;
expr(#c_fun{anno=A,vars=Cvs,body=Cb}, Sub0, #kern{ff=OldFF,func=Func}=St0) ->
@@ -1167,9 +1167,7 @@ select_bin_int_1(_, _, _, _) -> throw(not_possible).
select_assert_match_possible(Sz, Val, Fs) ->
EmptyBindings = erl_eval:new_bindings(),
- MatchFun = fun({integer,_,_}, NewV, Bs) when NewV =:= Val ->
- {match,Bs}
- end,
+ MatchFun = match_fun(Val),
EvalFun = fun({integer,_,S}, B) -> {value,S,B} end,
Expr = [{bin_element,0,{integer,0,Val},{integer,0,Sz},[{unit,1}|Fs]}],
{value,Bin,EmptyBindings} = eval_bits:expr_grp(Expr, EmptyBindings, EvalFun),
@@ -1184,6 +1182,11 @@ select_assert_match_possible(Sz, Val, Fs) ->
throw(not_possible)
end.
+match_fun(Val) ->
+ fun(match, {{integer,_,_},NewV,Bs}) when NewV =:= Val ->
+ {match,Bs}
+ end.
+
select_utf8(Val0) ->
try
Bin = <<Val0/utf8>>,
diff --git a/lib/compiler/src/v3_life.erl b/lib/compiler/src/v3_life.erl
index a7a4d4dc91..a1d92af9f8 100644
--- a/lib/compiler/src/v3_life.erl
+++ b/lib/compiler/src/v3_life.erl
@@ -65,7 +65,7 @@ functions([], Acc) -> reverse(Acc).
%% function(Kfunc) -> Func.
-function(#k_fdef{func=F,arity=Ar,vars=Vs,body=Kb}) ->
+function(#k_fdef{anno=#k{a=Anno},func=F,arity=Ar,vars=Vs,body=Kb}) ->
try
As = var_list(Vs),
Vdb0 = foldl(fun ({var,N}, Vdb) -> new_var(N, 0, Vdb) end, [], As),
@@ -80,7 +80,7 @@ function(#k_fdef{func=F,arity=Ar,vars=Vs,body=Kb}) ->
put(guard_refc, 0),
{B1,_,Vdb1} = body(B0, 1, Vdb0),
erase(guard_refc),
- {function,F,Ar,As,B1,Vdb1}
+ {function,F,Ar,As,B1,Vdb1,Anno}
catch
Class:Error ->
Stack = erlang:get_stacktrace(),
diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile
index 934bf39393..b90adaf917 100644
--- a/lib/compiler/test/Makefile
+++ b/lib/compiler/test/Makefile
@@ -9,6 +9,7 @@ MODULES= \
andor_SUITE \
apply_SUITE \
beam_validator_SUITE \
+ beam_disasm_SUITE \
bs_bincomp_SUITE \
bs_bit_binaries_SUITE \
bs_construct_SUITE \
@@ -157,7 +158,7 @@ release_tests_spec: make_emakefile
$(EMAKEFILE) $(ERL_FILES) $(CORE_FILES) $(RELSYSDIR)
$(INSTALL_DATA) $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) \
$(INLINE_ERL_FILES) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/compiler/test/andor_SUITE.erl b/lib/compiler/test/andor_SUITE.erl
index cab22e03d0..f7388f1614 100644
--- a/lib/compiler/test/andor_SUITE.erl
+++ b/lib/compiler/test/andor_SUITE.erl
@@ -28,7 +28,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(andor_SUITE),
+ test_lib:recompile(?MODULE),
[t_case, t_and_or, t_andalso, t_orelse, inside, overlap,
combined, in_case, before_and_inside_if].
diff --git a/lib/compiler/test/apply_SUITE.erl b/lib/compiler/test/apply_SUITE.erl
index c517c4465e..25f8a8dfb5 100644
--- a/lib/compiler/test/apply_SUITE.erl
+++ b/lib/compiler/test/apply_SUITE.erl
@@ -28,7 +28,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(apply_SUITE),
+ test_lib:recompile(?MODULE),
[mfa, fun_apply].
groups() ->
diff --git a/lib/compiler/test/beam_disasm_SUITE.erl b/lib/compiler/test/beam_disasm_SUITE.erl
new file mode 100644
index 0000000000..44574ae64a
--- /dev/null
+++ b/lib/compiler/test/beam_disasm_SUITE.erl
@@ -0,0 +1,65 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(beam_disasm_SUITE).
+
+-include_lib("test_server/include/test_server.hrl").
+
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_group/2,end_per_group/2]).
+
+-export([stripped/1]).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [stripped].
+
+groups() ->
+ [].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+stripped(doc) ->
+ ["Check that stripped beam files can be disassembled"];
+stripped(Config) when is_list(Config) ->
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line SrcName = filename:join(PrivDir, "tmp.erl"),
+ ?line BeamName = filename:join(PrivDir, "tmp.beam"),
+ Prog = <<"-module(tmp).\n-export([tmp/0]).\ntmp()->ok.\n">>,
+ ?line ok = file:write_file(SrcName, Prog),
+ ?line {ok, tmp} =
+ compile:file(SrcName, [{outdir, PrivDir}]),
+ ?line {beam_file, tmp, _, Attr, CompileInfo, [_|_]} =
+ beam_disasm:file(BeamName),
+ ?line true = is_list(Attr),
+ ?line true = is_list(CompileInfo),
+ ?line {ok, {tmp, _}} = beam_lib:strip(BeamName),
+ ?line {beam_file, tmp, _, none, none, [_|_]} =
+ beam_disasm:file(BeamName),
+ ok.
diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl
index fc88ebeb41..556dc54a8f 100644
--- a/lib/compiler/test/beam_validator_SUITE.erl
+++ b/lib/compiler/test/beam_validator_SUITE.erl
@@ -46,7 +46,7 @@ end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(beam_validator_SUITE),
+ test_lib:recompile(?MODULE),
[beam_files, compiler_bug, stupid_but_valid, xrange,
yrange, stack, call_last, merge_undefined, uninit,
unsafe_catch, dead_code, mult_labels,
diff --git a/lib/compiler/test/bs_bincomp_SUITE.erl b/lib/compiler/test/bs_bincomp_SUITE.erl
index 30c04f80cf..d39e340429 100644
--- a/lib/compiler/test/bs_bincomp_SUITE.erl
+++ b/lib/compiler/test/bs_bincomp_SUITE.erl
@@ -32,7 +32,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(bs_bincomp_SUITE),
+ test_lib:recompile(?MODULE),
[byte_aligned, bit_aligned, extended_byte_aligned,
extended_bit_aligned, mixed, filters, trim_coverage,
nomatch, sizes, tail].
diff --git a/lib/compiler/test/bs_bit_binaries_SUITE.erl b/lib/compiler/test/bs_bit_binaries_SUITE.erl
index 8be0c4196a..30276f1259 100644
--- a/lib/compiler/test/bs_bit_binaries_SUITE.erl
+++ b/lib/compiler/test/bs_bit_binaries_SUITE.erl
@@ -33,7 +33,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(bs_bit_binaries_SUITE),
+ test_lib:recompile(?MODULE),
[misc, horrid_match, test_bitstr, test_bit_size,
asymmetric_tests, big_asymmetric_tests,
binary_to_and_from_list, big_binary_to_and_from_list,
diff --git a/lib/compiler/test/bs_construct_SUITE.erl b/lib/compiler/test/bs_construct_SUITE.erl
index c430b12b70..31c7890f26 100644
--- a/lib/compiler/test/bs_construct_SUITE.erl
+++ b/lib/compiler/test/bs_construct_SUITE.erl
@@ -35,7 +35,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(bs_construct_SUITE),
+ test_lib:recompile(?MODULE),
[two, test1, fail, float_bin, in_guard, in_catch,
nasty_literals, side_effect, opt, otp_7556, float_arith,
otp_8054].
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index 9184e14cb2..f8c71a0257 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -35,7 +35,7 @@
match_string/1,zero_width/1,bad_size/1,haystack/1,
cover_beam_bool/1]).
--export([coverage_id/1]).
+-export([coverage_id/1,coverage_external_ignore/2]).
-include_lib("test_server/include/test_server.hrl").
@@ -43,7 +43,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(bs_match_SUITE),
+ test_lib:recompile(?MODULE),
[fun_shadow, int_float, otp_5269, null_fields, wiger,
bin_tail, save_restore, shadowed_size_var,
partitioned_bs_match, function_clause, unit,
@@ -585,13 +585,17 @@ coverage(Config) when is_list(Config) ->
A+B
end, 0, [a,b,c])),
+ ?line {<<42.0:64/float>>,float} = coverage_build(<<>>, <<42>>, float),
?line {<<>>,not_a_tuple} = coverage_build(<<>>, <<>>, not_a_tuple),
?line {<<16#76,"abc",16#A9,"abc">>,{x,42,43}} =
coverage_build(<<>>, <<16#7,16#A>>, {x,y,z}),
+ ?line [<<2>>,<<1>>] = coverage_bc(<<1,2>>, []),
+
?line {x,<<"abc">>,z} = coverage_setelement(<<2,"abc">>, {x,y,z}),
?line [42] = coverage_apply(<<42>>, [coverage_id]),
+ ?line 42 = coverage_external(<<42>>),
?line do_coverage_bin_to_term_list([]),
?line do_coverage_bin_to_term_list([lists:seq(0, 10),{a,b,c},<<23:42>>]),
@@ -608,6 +612,10 @@ coverage_fold(Fun, Acc, <<H,T/binary>>) ->
coverage_fold(Fun, Fun(IdFun(H), IdFun(Acc)), T);
coverage_fold(Fun, Acc, <<>>) when is_function(Fun, 2) -> Acc.
+coverage_build(Acc0, <<H,T/binary>>, float) ->
+ Float = id(<<H:64/float>>),
+ Acc = <<Acc0/binary,Float/binary>>,
+ coverage_build(Acc, T, float);
coverage_build(Acc0, <<H,T/binary>>, Tuple0) ->
Str = id(<<H:(id(4)),(H-1):4,"abc">>),
Acc = id(<<Acc0/bitstring,Str/bitstring>>),
@@ -618,6 +626,11 @@ coverage_build(Acc0, <<H,T/binary>>, Tuple0) ->
end;
coverage_build(Acc, <<>>, Tuple) -> {Acc,Tuple}.
+coverage_bc(<<H,T/binary>>, Acc) ->
+ B = << <<C:8>> || C <- [H] >>,
+ coverage_bc(T, [B|Acc]);
+coverage_bc(<<>>, Acc) -> Acc.
+
coverage_setelement(<<H,T1/binary>>, Tuple) when element(1, Tuple) =:= x ->
setelement(H, Tuple, T1).
@@ -625,6 +638,13 @@ coverage_apply(<<H,T/binary>>, [F|Fs]) ->
[?MODULE:F(H)|coverage_apply(T, Fs)];
coverage_apply(<<>>, []) -> [].
+coverage_external(<<H,T/binary>>) ->
+ ?MODULE:coverage_external_ignore(T, T),
+ H.
+
+coverage_external_ignore(_, _) ->
+ ok.
+
coverage_id(I) -> id(I).
do_coverage_bin_to_term_list(L) ->
@@ -1008,8 +1028,8 @@ haystack_2(Haystack) ->
fc({'EXIT',{function_clause,_}}) -> ok;
fc({'EXIT',{{case_clause,_},_}}) when ?MODULE =:= bs_match_inline_SUITE -> ok.
-fc(Name, Args, {'EXIT',{function_clause,[{?MODULE,Name,Args}|_]}}) -> ok;
-fc(Name, Args, {'EXIT',{function_clause,[{?MODULE,Name,Arity}|_]}})
+fc(Name, Args, {'EXIT',{function_clause,[{?MODULE,Name,Args,_}|_]}}) -> ok;
+fc(Name, Args, {'EXIT',{function_clause,[{?MODULE,Name,Arity,_}|_]}})
when length(Args) =:= Arity ->
true = test_server:is_native(?MODULE);
fc(_, Args, {'EXIT',{{case_clause,ActualArgs},_}})
diff --git a/lib/compiler/test/bs_utf_SUITE.erl b/lib/compiler/test/bs_utf_SUITE.erl
index d37943ce3a..f30a4d3fef 100644
--- a/lib/compiler/test/bs_utf_SUITE.erl
+++ b/lib/compiler/test/bs_utf_SUITE.erl
@@ -30,7 +30,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(bs_utf_SUITE),
+ test_lib:recompile(?MODULE),
[utf8_roundtrip, unused_utf_char, utf16_roundtrip,
utf32_roundtrip, guard, extreme_tripping, literals,
coverage].
diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl
index ba225b66d0..1343fbd1c9 100644
--- a/lib/compiler/test/compilation_SUITE.erl
+++ b/lib/compiler/test/compilation_SUITE.erl
@@ -27,7 +27,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(compilation_SUITE),
+ test_lib:recompile(?MODULE),
[self_compile_old_inliner, self_compile, compiler_1,
compiler_3, compiler_5, beam_compiler_1,
beam_compiler_2, beam_compiler_3, beam_compiler_4,
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index 037c078fd0..8c6a623dfb 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -40,7 +40,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
-spec all() -> all_return_type().
all() ->
- test_lib:recompile(compile_SUITE),
+ test_lib:recompile(?MODULE),
[app_test, file_1, module_mismatch, big_file, outdir,
binary, makedep, cond_and_ifdef, listings, listings_big,
other_output, package_forms, encrypted_abstr,
@@ -82,6 +82,7 @@ file_1(Config) when is_list(Config) ->
?line {ok,simple} = compile:file(Simple, [native,report]), %Smoke test.
?line {ok,simple} = compile:file(Target, [native,from_beam]), %Smoke test.
?line {ok,simple} = compile:file(Simple, [debug_info]),
+ ?line {ok,simple} = compile:file(Simple, [no_line_info]), %Coverage
?line ok = file:set_cwd(Cwd),
?line true = exists(Target),
?line passed = run(Target, test, []),
diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl
index 21a5f65dee..26173c62b8 100644
--- a/lib/compiler/test/core_SUITE.erl
+++ b/lib/compiler/test/core_SUITE.erl
@@ -40,7 +40,7 @@ end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(core_SUITE),
+ test_lib:recompile(?MODULE),
[dehydrated_itracer, nested_tries].
groups() ->
diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl
index 710751b09d..ac14d36e82 100644
--- a/lib/compiler/test/core_fold_SUITE.erl
+++ b/lib/compiler/test/core_fold_SUITE.erl
@@ -30,7 +30,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(core_fold_SUITE),
+ test_lib:recompile(?MODULE),
[t_element, setelement, t_length, append, t_apply, bifs,
eq, nested_call_in_case, coverage].
diff --git a/lib/compiler/test/error_SUITE.erl b/lib/compiler/test/error_SUITE.erl
index c9823665b4..eb5e50818e 100644
--- a/lib/compiler/test/error_SUITE.erl
+++ b/lib/compiler/test/error_SUITE.erl
@@ -27,7 +27,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(error_SUITE),
+ test_lib:recompile(?MODULE),
[head_mismatch_line, warnings_as_errors, bif_clashes].
groups() ->
@@ -183,23 +183,47 @@ get_compilation_errors(Config, Filename) ->
E.
warnings_as_errors(Config) when is_list(Config) ->
- Ts = [{warnings_as_errors,
+ ?line TestFile = test_filename(Config),
+ ?line BeamFile = filename:rootname(TestFile, ".erl") ++ ".beam",
+ ?line OutDir = ?config(priv_dir, Config),
+
+ Ts1 = [{warnings_as_errors,
<<"
t() ->
A = unused,
ok.
">>,
- [export_all,warnings_as_errors],
- {error,
- [],
- [{3,erl_lint,{unused_var,'A'}}]} }],
- ?line [] = run(Config, Ts),
+ [warnings_as_errors, export_all, {outdir, OutDir}],
+ {error,
+ [],
+ [{3,erl_lint,{unused_var,'A'}}]} }],
+ ?line [] = run(Ts1, TestFile, write_beam),
+ ?line false = filelib:is_regular(BeamFile),
+
+ Ts2 = [{warning_unused_var,
+ <<"
+ t() ->
+ A = unused,
+ ok.
+ ">>,
+ [return_warnings, export_all, {outdir, OutDir}],
+ {warning,
+ [{3,erl_lint,{unused_var,'A'}}]} }],
+
+ ?line [] = run(Ts2, TestFile, write_beam),
+ ?line true = filelib:is_regular(BeamFile),
+ ?line ok = file:delete(BeamFile),
+
ok.
run(Config, Tests) ->
+ ?line File = test_filename(Config),
+ run(Tests, File, dont_write_beam).
+
+run(Tests, File, WriteBeam) ->
F = fun({N,P,Ws,E}, BadL) ->
- case catch run_test(Config, P, Ws) of
+ case catch run_test(P, File, Ws, WriteBeam) of
E ->
BadL;
Bad ->
@@ -211,8 +235,12 @@ run(Config, Tests) ->
lists:foldl(F, [], Tests).
run2(Config, Tests) ->
+ ?line File = test_filename(Config),
+ run2(Tests, File, dont_write_beam).
+
+run2(Tests, File, WriteBeam) ->
F = fun({N,P,Ws,E}, BadL) ->
- case catch filter(run_test(Config, P, Ws)) of
+ case catch filter(run_test(P, File, Ws, WriteBeam)) of
E ->
BadL;
Bad ->
@@ -231,12 +259,19 @@ filter(X) ->
%% Compiles a test module and returns the list of errors and warnings.
-run_test(Conf, Test0, Warnings) ->
- Filename = 'errors_test.erl',
- ?line DataDir = ?config(priv_dir, Conf),
+test_filename(Conf) ->
+ Filename = "errors_test.erl",
+ DataDir = ?config(priv_dir, Conf),
+ filename:join(DataDir, Filename).
+
+run_test(Test0, File, Warnings, WriteBeam) ->
?line Test = ["-module(errors_test). ", Test0],
- ?line File = filename:join(DataDir, Filename),
- ?line Opts = [binary,return_errors|Warnings],
+ ?line Opts = case WriteBeam of
+ dont_write_beam ->
+ [binary,return_errors|Warnings];
+ write_beam ->
+ [return_errors|Warnings]
+ end,
?line ok = file:write_file(File, Test),
%% Compile once just to print all errors and warnings.
@@ -252,6 +287,10 @@ run_test(Conf, Test0, Warnings) ->
%io:format("compile:file(~s,~p) ->~n~p~n",
% [File,Opts,Ws]),
[];
+ {ok,errors_test,[{_File,Ws}]} ->
+ {warning,Ws};
+ {ok,errors_test,[]} ->
+ [];
{error,[{XFile,Es}],Ws} = _ZZ when is_list(XFile) ->
%io:format("compile:file(~s,~p) ->~n~p~n",
% [File,Opts,_ZZ]),
diff --git a/lib/compiler/test/float_SUITE.erl b/lib/compiler/test/float_SUITE.erl
index 6738265776..afc04fd440 100644
--- a/lib/compiler/test/float_SUITE.erl
+++ b/lib/compiler/test/float_SUITE.erl
@@ -26,7 +26,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(float_SUITE),
+ test_lib:recompile(?MODULE),
[pending, bif_calls, math_functions,
mixed_float_and_int].
diff --git a/lib/compiler/test/fun_SUITE.erl b/lib/compiler/test/fun_SUITE.erl
index aa9be83c82..368a5815bf 100644
--- a/lib/compiler/test/fun_SUITE.erl
+++ b/lib/compiler/test/fun_SUITE.erl
@@ -27,7 +27,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(fun_SUITE),
+ test_lib:recompile(?MODULE),
[test1, overwritten_fun, otp_7202, bif_fun].
groups() ->
diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl
index 482564a32b..40711783ed 100644
--- a/lib/compiler/test/guard_SUITE.erl
+++ b/lib/compiler/test/guard_SUITE.erl
@@ -32,19 +32,21 @@
t_is_boolean/1,is_function_2/1,
tricky/1,rel_ops/1,literal_type_tests/1,
basic_andalso_orelse/1,traverse_dcd/1,
- check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1]).
+ check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1,
+ bad_constants/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(guard_SUITE),
+ test_lib:recompile(?MODULE),
[misc, const_cond, basic_not, complex_not, nested_nots,
semicolon, complex_semicolon, comma, or_guard,
more_or_guards, complex_or_guards, and_guard, xor_guard,
more_xor_guards, build_in_guard, old_guard_tests, gbif,
t_is_boolean, is_function_2, tricky, rel_ops,
literal_type_tests, basic_andalso_orelse, traverse_dcd,
- check_qlc_hrl, andalso_semi, t_tuple_size, binary_part].
+ check_qlc_hrl, andalso_semi, t_tuple_size, binary_part,
+ bad_constants].
groups() ->
[].
@@ -1517,8 +1519,27 @@ bptest(B,A,C) when erlang:binary_part(B,{A,C}) =:= <<3,3>> ->
bptest(_,_,_) ->
error.
-
-
+-define(FAILING(C),
+ if
+ C -> ?t:fail(should_fail);
+ true -> ok
+ end,
+ if
+ true, C -> ?t:fail(should_fail);
+ true -> ok
+ end).
+
+bad_constants(Config) when is_list(Config) ->
+ ?line ?FAILING(false),
+ ?line ?FAILING([]),
+ ?line ?FAILING([a]),
+ ?line ?FAILING([Config]),
+ ?line ?FAILING({a,b}),
+ ?line ?FAILING({a,Config}),
+ ?line ?FAILING(<<1>>),
+ ?line ?FAILING(42),
+ ?line ?FAILING(3.14),
+ ok.
%% Call this function to turn off constant propagation.
id(I) -> I.
diff --git a/lib/compiler/test/inline_SUITE.erl b/lib/compiler/test/inline_SUITE.erl
index 7b9600c2f6..086fba2649 100644
--- a/lib/compiler/test/inline_SUITE.erl
+++ b/lib/compiler/test/inline_SUITE.erl
@@ -31,7 +31,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(inline_SUITE),
+ test_lib:recompile(?MODULE),
[attribute, bsdecode, bsdes, barnes2, decode1, smith,
itracer, pseudoknot, lists, really_inlined, otp_7223,
coverage].
@@ -263,7 +263,8 @@ my_apply(M, F, A, Init) ->
really_inlined(Config) when is_list(Config) ->
%% Make sure that badarg/2 really gets inlined.
- {'EXIT',{badarg,[{?MODULE,fail_me_now,[]}|_]}} = (catch fail_me_now()),
+ {'EXIT',{badarg,[{?MODULE,fail_me_now,[],_}|_]}} =
+ (catch fail_me_now()),
ok.
fail_me_now() ->
diff --git a/lib/compiler/test/lc_SUITE.erl b/lib/compiler/test/lc_SUITE.erl
index bcdcf2fd9f..f5948504b3 100644
--- a/lib/compiler/test/lc_SUITE.erl
+++ b/lib/compiler/test/lc_SUITE.erl
@@ -30,7 +30,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(lc_SUITE),
+ test_lib:recompile(?MODULE),
[basic, deeply_nested, no_generator, empty_generator].
groups() ->
@@ -179,8 +179,8 @@ empty_generator(Config) when is_list(Config) ->
id(I) -> I.
-fc(Args, {'EXIT',{function_clause,[{?MODULE,_,Args}|_]}}) -> ok;
-fc(Args, {'EXIT',{function_clause,[{?MODULE,_,Arity}|_]}})
+fc(Args, {'EXIT',{function_clause,[{?MODULE,_,Args,_}|_]}}) -> ok;
+fc(Args, {'EXIT',{function_clause,[{?MODULE,_,Arity,_}|_]}})
when length(Args) =:= Arity ->
true = test_server:is_native(?MODULE);
fc(Args, {'EXIT',{{case_clause,ActualArgs},_}})
diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl
index 04879300d1..9406d7de8f 100644
--- a/lib/compiler/test/match_SUITE.erl
+++ b/lib/compiler/test/match_SUITE.erl
@@ -22,16 +22,16 @@
init_per_group/2,end_per_group/2,
pmatch/1,mixed/1,aliases/1,match_in_call/1,
untuplify/1,shortcut_boolean/1,letify_guard/1,
- selectify/1,underscore/1]).
+ selectify/1,underscore/1,coverage/1]).
-include_lib("test_server/include/test_server.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(match_SUITE),
+ test_lib:recompile(?MODULE),
[pmatch, mixed, aliases, match_in_call, untuplify,
- shortcut_boolean, letify_guard, selectify, underscore].
+ shortcut_boolean, letify_guard, selectify, underscore, coverage].
groups() ->
[].
@@ -398,4 +398,18 @@ underscore(Config) when is_list(Config) ->
_ = is_list(Config),
ok.
+coverage(Config) when is_list(Config) ->
+ %% Cover beam_dead.
+ ok = coverage_1(x, a),
+ ok = coverage_1(x, b).
+
+coverage_1(B, Tag) ->
+ case Tag of
+ a -> coverage_2(1, a, B);
+ b -> coverage_2(2, b, B)
+ end.
+
+coverage_2(1, a, x) -> ok;
+coverage_2(2, b, x) -> ok.
+
id(I) -> I.
diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl
index f1f9b17084..9b414cade6 100644
--- a/lib/compiler/test/misc_SUITE.erl
+++ b/lib/compiler/test/misc_SUITE.erl
@@ -56,7 +56,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
-spec all() -> misc_SUITE_test_cases().
all() ->
- test_lib:recompile(misc_SUITE),
+ test_lib:recompile(?MODULE),
[tobias, empty_string, md5, silly_coverage,
confused_literals, integer_encoding, override_bif].
@@ -179,7 +179,7 @@ silly_coverage(Config) when is_list(Config) ->
?line expect_error(fun() -> v3_life:module(BadKernel, []) end),
%% v3_codegen
- CodegenInput = {?MODULE,[{foo,0}],[],[{function,foo,0,[a|b],a,b}]},
+ CodegenInput = {?MODULE,[{foo,0}],[],[{function,foo,0,[a|b],a,b,[]}]},
?line expect_error(fun() -> v3_codegen:module(CodegenInput, []) end),
%% beam_block
@@ -187,7 +187,7 @@ silly_coverage(Config) when is_list(Config) ->
[{function,foo,0,2,
[{label,1},
{func_info,{atom,?MODULE},{atom,foo},0},
- {label,2}|non_proper_list],99}]},
+ {label,2}|non_proper_list]}],99},
?line expect_error(fun() -> beam_block:module(BlockInput, []) end),
%% beam_bool
diff --git a/lib/compiler/test/num_bif_SUITE.erl b/lib/compiler/test/num_bif_SUITE.erl
index 0a4750dc08..3479cf5425 100644
--- a/lib/compiler/test/num_bif_SUITE.erl
+++ b/lib/compiler/test/num_bif_SUITE.erl
@@ -40,7 +40,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(num_bif_SUITE),
+ test_lib:recompile(?MODULE),
[t_abs, t_float, t_float_to_list, t_integer_to_list,
{group, t_list_to_float}, t_list_to_integer, t_round,
t_trunc].
diff --git a/lib/compiler/test/pmod_SUITE.erl b/lib/compiler/test/pmod_SUITE.erl
index 4c68d777ca..9a317b5762 100644
--- a/lib/compiler/test/pmod_SUITE.erl
+++ b/lib/compiler/test/pmod_SUITE.erl
@@ -28,7 +28,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(pmod_SUITE),
+ test_lib:recompile(?MODULE),
[basic, otp_8447].
groups() ->
diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl
index 75e8045693..2a67615e5e 100644
--- a/lib/compiler/test/receive_SUITE.erl
+++ b/lib/compiler/test/receive_SUITE.erl
@@ -39,7 +39,7 @@ end_per_testcase(_Case, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(receive_SUITE),
+ test_lib:recompile(?MODULE),
[recv, coverage, otp_7980, ref_opt, export].
groups() ->
diff --git a/lib/compiler/test/record_SUITE.erl b/lib/compiler/test/record_SUITE.erl
index 65b96590ed..363422ec7e 100644
--- a/lib/compiler/test/record_SUITE.erl
+++ b/lib/compiler/test/record_SUITE.erl
@@ -26,7 +26,8 @@
init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
errors/1,record_test_2/1,record_test_3/1,record_access_in_guards/1,
- guard_opt/1,eval_once/1,foobar/1,missing_test_heap/1, nested_access/1]).
+ guard_opt/1,eval_once/1,foobar/1,missing_test_heap/1,
+ nested_access/1,coverage/1]).
init_per_testcase(_Case, Config) ->
?line Dog = test_server:timetrap(test_server:minutes(2)),
@@ -40,10 +41,10 @@ end_per_testcase(_Case, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(record_SUITE),
+ test_lib:recompile(?MODULE),
[errors, record_test_2, record_test_3,
record_access_in_guards, guard_opt, eval_once, foobar,
- missing_test_heap, nested_access].
+ missing_test_heap, nested_access, coverage].
groups() ->
[].
@@ -568,4 +569,18 @@ nested_access(Config) when is_list(Config) ->
?line N2a = N2b,
ok.
+-record(rr, {a,b,c}).
+
+coverage(Config) when is_list(Config) ->
+ %% There should only remain one record test in the code below.
+ R0 = id(#rr{a=1,b=2,c=3}),
+ B = R0#rr.b, %Test the record here.
+ R = R0#rr{c=42}, %No need to test here.
+ if
+ B > R#rr.a -> %No need to test here.
+ ok
+ end,
+ #rr{a=1,b=2,c=42} = id(R), %Test for correctness.
+ ok.
+
id(I) -> I.
diff --git a/lib/compiler/test/trycatch_SUITE.erl b/lib/compiler/test/trycatch_SUITE.erl
index 92a79d3cba..760cf17225 100644
--- a/lib/compiler/test/trycatch_SUITE.erl
+++ b/lib/compiler/test/trycatch_SUITE.erl
@@ -31,7 +31,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(trycatch_SUITE),
+ test_lib:recompile(?MODULE),
[basic, lean_throw, try_of, try_after, catch_oops,
after_oops, eclectic, rethrow, nested_of, nested_catch,
nested_after, nested_horrid, last_call_optimization,
@@ -314,19 +314,19 @@ eclectic(Conf) when is_list(Conf) ->
V = {make_ref(),3.1415926535,[[]|{}]},
?line {{value,{value,V},V},V} =
eclectic_1({foo,{value,{value,V}}}, undefined, {value,V}),
- ?line {{'EXIT',{V,[{?MODULE,foo,1}|_]}},V} =
+ ?line {{'EXIT',{V,[{?MODULE,foo,1,_}|_]}},V} =
eclectic_1({catch_foo,{error,V}}, undefined, {value,V}),
?line {{error,{exit,V},{'EXIT',V}},V} =
eclectic_1({foo,{error,{exit,V}}}, error, {value,V}),
?line {{value,{value,V},V},
- {'EXIT',{badarith,[{?MODULE,my_add,2}|_]}}} =
+ {'EXIT',{badarith,[{?MODULE,my_add,2,_}|_]}}} =
eclectic_1({foo,{value,{value,V}}}, undefined, {'add',{0,a}}),
?line {{'EXIT',V},V} =
eclectic_1({catch_foo,{exit,V}}, undefined, {throw,V}),
- ?line {{error,{'div',{1,0}},{'EXIT',{badarith,[{?MODULE,my_div,2}|_]}}},
+ ?line {{error,{'div',{1,0}},{'EXIT',{badarith,[{?MODULE,my_div,2,_}|_]}}},
{'EXIT',V}} =
eclectic_1({foo,{error,{'div',{1,0}}}}, error, {exit,V}),
- ?line {{{error,V},{'EXIT',{V,[{?MODULE,foo,1}|_]}}},
+ ?line {{{error,V},{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},
{'EXIT',V}} =
eclectic_1({catch_foo,{throw,{error,V}}}, undefined, {exit,V}),
%%
@@ -336,15 +336,15 @@ eclectic(Conf) when is_list(Conf) ->
eclectic_2({throw,{value,V}}, throw, {value,V}),
?line {{caught,{'EXIT',V}},undefined} =
eclectic_2({value,{value,V}}, undefined, {exit,V}),
- ?line {{caught,{'EXIT',{V,[{?MODULE,foo,1}|_]}}},undefined} =
+ ?line {{caught,{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},undefined} =
eclectic_2({error,{value,V}}, throw, {error,V}),
- ?line {{caught,{'EXIT',{badarg,[{erlang,abs,[V]}|_]}}},V} =
+ ?line {{caught,{'EXIT',{badarg,[{erlang,abs,[V],_}|_]}}},V} =
eclectic_2({value,{'abs',V}}, undefined, {value,V}),
- ?line {{caught,{'EXIT',{badarith,[{?MODULE,my_add,2}|_]}}},V} =
+ ?line {{caught,{'EXIT',{badarith,[{?MODULE,my_add,2,_}|_]}}},V} =
eclectic_2({exit,{'add',{0,a}}}, exit, {value,V}),
?line {{caught,{'EXIT',V}},undefined} =
eclectic_2({value,{error,V}}, undefined, {exit,V}),
- ?line {{caught,{'EXIT',{V,[{?MODULE,foo,1}|_]}}},undefined} =
+ ?line {{caught,{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},undefined} =
eclectic_2({throw,{'div',{1,0}}}, throw, {error,V}),
ok.
diff --git a/lib/compiler/test/warnings_SUITE.erl b/lib/compiler/test/warnings_SUITE.erl
index 8cc3ca4199..f6a572abfa 100644
--- a/lib/compiler/test/warnings_SUITE.erl
+++ b/lib/compiler/test/warnings_SUITE.erl
@@ -54,7 +54,7 @@ end_per_testcase(_Case, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(warnings_SUITE),
+ test_lib:recompile(?MODULE),
[pattern, pattern2, pattern3, pattern4, guard,
bad_arith, bool_cases, bad_apply, files, effect,
bin_opt_info, bin_construction].
@@ -453,6 +453,16 @@ effect(Config) when is_list(Config) ->
true -> ok
end,
ok.
+
+ m8(A, B) ->
+ case {A,B} of
+ V -> V
+ end,
+ ok.
+
+ m9(Bs) ->
+ [{B,ok} = {B,foo:bar(B)} || B <- Bs],
+ ok.
">>,
[],
{warnings,[{5,sys_core_fold,{no_effect,{erlang,is_integer,1}}},
diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk
index e46096a6df..04290c0a7f 100644
--- a/lib/compiler/vsn.mk
+++ b/lib/compiler/vsn.mk
@@ -1 +1 @@
-COMPILER_VSN = 4.7.3
+COMPILER_VSN = 4.7.5
diff --git a/lib/cosEvent/doc/src/CosEventChannelAdmin_ConsumerAdmin.xml b/lib/cosEvent/doc/src/CosEventChannelAdmin_ConsumerAdmin.xml
index 95941fefdd..2318ccb6d2 100644
--- a/lib/cosEvent/doc/src/CosEventChannelAdmin_ConsumerAdmin.xml
+++ b/lib/cosEvent/doc/src/CosEventChannelAdmin_ConsumerAdmin.xml
@@ -23,8 +23,7 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosEventChannelAdmin_&shy;ConsumerAdmin</title>
- <shorttitle>..._ConsumerAdmin</shorttitle>
+ <title>CosEventChannelAdmin_ConsumerAdmin</title>
<prepared></prepared>
<responsible></responsible>
<docno></docno>
diff --git a/lib/cosEvent/doc/src/CosEventChannelAdmin_EventChannel.xml b/lib/cosEvent/doc/src/CosEventChannelAdmin_EventChannel.xml
index 51f9f11613..4495fd4450 100644
--- a/lib/cosEvent/doc/src/CosEventChannelAdmin_EventChannel.xml
+++ b/lib/cosEvent/doc/src/CosEventChannelAdmin_EventChannel.xml
@@ -23,8 +23,7 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosEventChannelAdmin_&shy;EventChannel</title>
- <shorttitle>..._EventChannel</shorttitle>
+ <title>CosEventChannelAdmin_EventChannel</title>
<prepared></prepared>
<responsible></responsible>
<docno></docno>
diff --git a/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPullConsumer.xml b/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPullConsumer.xml
index 9690c9406d..4cd20ad185 100644
--- a/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPullConsumer.xml
+++ b/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPullConsumer.xml
@@ -23,8 +23,7 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosEventChannelAdmin_&shy;ProxyPullConsumer</title>
- <shorttitle>..._ProxyPullConsumer</shorttitle>
+ <title>CosEventChannelAdmin_ProxyPullConsumer</title>
<prepared></prepared>
<responsible></responsible>
<docno></docno>
diff --git a/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPullSupplier.xml b/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPullSupplier.xml
index fb17c450f4..830c06a87c 100644
--- a/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPullSupplier.xml
+++ b/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPullSupplier.xml
@@ -23,8 +23,7 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosEventChannelAdmin_&shy;ProxyPullSupplier</title>
- <shorttitle>..._ProxyPullSupplier</shorttitle>
+ <title>CosEventChannelAdmin_ProxyPullSupplier</title>
<prepared></prepared>
<responsible></responsible>
<docno></docno>
diff --git a/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPushConsumer.xml b/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPushConsumer.xml
index 21e6cfce6f..2c451acd9c 100644
--- a/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPushConsumer.xml
+++ b/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPushConsumer.xml
@@ -23,8 +23,7 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosEventChannelAdmin_&shy;ProxyPushConsumer</title>
- <shorttitle>..._ProxyPushConsumer</shorttitle>
+ <title>CosEventChannelAdmin_ProxyPushConsumer</title>
<prepared></prepared>
<responsible></responsible>
<docno></docno>
diff --git a/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPushSupplier.xml b/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPushSupplier.xml
index be2dfcafbe..9030c0e735 100644
--- a/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPushSupplier.xml
+++ b/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPushSupplier.xml
@@ -23,8 +23,7 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosEventChannelAdmin_&shy;ProxyPushSupplier</title>
- <shorttitle>..._ProxyPushSupplier</shorttitle>
+ <title>CosEventChannelAdmin_ProxyPushSupplier</title>
<prepared></prepared>
<responsible></responsible>
<docno></docno>
diff --git a/lib/cosEvent/doc/src/CosEventChannelAdmin_SupplierAdmin.xml b/lib/cosEvent/doc/src/CosEventChannelAdmin_SupplierAdmin.xml
index ca301bb860..e68b0854d8 100644
--- a/lib/cosEvent/doc/src/CosEventChannelAdmin_SupplierAdmin.xml
+++ b/lib/cosEvent/doc/src/CosEventChannelAdmin_SupplierAdmin.xml
@@ -23,8 +23,7 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosEventChannelAdmin_&shy;SupplierAdmin</title>
- <shorttitle>..._SupplierAdmin</shorttitle>
+ <title>CosEventChannelAdmin_SupplierAdmin</title>
<prepared></prepared>
<responsible></responsible>
<docno></docno>
diff --git a/lib/cosEvent/doc/src/notes.xml b/lib/cosEvent/doc/src/notes.xml
index 1a5c8afa17..1da5399755 100644
--- a/lib/cosEvent/doc/src/notes.xml
+++ b/lib/cosEvent/doc/src/notes.xml
@@ -22,8 +22,8 @@
</legalnotice>
<title>cosEvent Release Notes</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
<approved></approved>
<checked></checked>
@@ -33,6 +33,23 @@
</header>
<section>
+ <title>cosEvent 2.1.11</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>
+ Removed superfluous usage of shy in the documentation since it can cause problem if
+ a buggy tool is used.</p>
+ <p>
+ Own Id: OTP-9319 Aux Id:</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
<title>cosEvent 2.1.10</title>
<section>
diff --git a/lib/cosEvent/src/Makefile b/lib/cosEvent/src/Makefile
index a62d47ce74..c774d18380 100644
--- a/lib/cosEvent/src/Makefile
+++ b/lib/cosEvent/src/Makefile
@@ -177,16 +177,18 @@ docs:
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
-$(GEN_ERL_FILES1) $(EXTERNAL_GEN_HRL_FILES1): CosEventChannelAdmin.idl
+
+IDL-GENERATED: CosEventChannelAdmin.idl cosEventApp.idl CosEventComm.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosEventChannelAdmin.cfg"}' CosEventChannelAdmin.idl
mv $(GEN_HRL_FILES1) $(EXTERNAL_INC_PATH)
-
-$(GEN_ERL_FILES2) $(GEN_HRL_FILES2): cosEventApp.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"cosEventApp.cfg"}' cosEventApp.idl
-
-$(GEN_ERL_FILES3) $(EXTERNAL_GEN_HRL_FILES3): CosEventComm.idl
erlc $(ERL_IDL_FLAGS) CosEventComm.idl
mv $(GEN_HRL_FILES3) $(EXTERNAL_INC_PATH)
+ >IDL-GENERATED
+
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Target
diff --git a/lib/cosEvent/test/Makefile b/lib/cosEvent/test/Makefile
index c59c7ee315..c3f07c156f 100644
--- a/lib/cosEvent/test/Makefile
+++ b/lib/cosEvent/test/Makefile
@@ -121,17 +121,13 @@ docs:
# Special Targets
# ----------------------------------------------------
-#
-# Each IDL file produces many target files so no pattern
-# rule can be used.
-#
-TGT_COS = \
- $(GEN_HRL_COS:%=$(IDLOUTDIR)/%) \
- $(GEN_MOD_COS:%=$(IDLOUTDIR)/%.erl)
+IDL-GENERATED: event_test_server.idl
+ erlc $(ERL_IDL_FLAGS) -o$(IDLOUTDIR) event_test_server.idl
+ >IDL-GENERATED
+$(GEN_FILES): IDL-GENERATED
-$(TGT_COS): event_test_server.idl
- erlc $(ERL_IDL_FLAGS) -o$(IDLOUTDIR) event_test_server.idl
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Targets
diff --git a/lib/cosEvent/vsn.mk b/lib/cosEvent/vsn.mk
index 38999db5fa..85d3cf552b 100644
--- a/lib/cosEvent/vsn.mk
+++ b/lib/cosEvent/vsn.mk
@@ -1,3 +1,3 @@
-COSEVENT_VSN = 2.1.10
+COSEVENT_VSN = 2.1.11
diff --git a/lib/cosEventDomain/doc/src/CosEventDomainAdmin_EventDomain.xml b/lib/cosEventDomain/doc/src/CosEventDomainAdmin_EventDomain.xml
index cf1cdab966..4941f8652c 100644
--- a/lib/cosEventDomain/doc/src/CosEventDomainAdmin_EventDomain.xml
+++ b/lib/cosEventDomain/doc/src/CosEventDomainAdmin_EventDomain.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2001</year><year>2009</year>
+ <year>2001</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -21,8 +21,7 @@
</legalnotice>
- <title>CosEventDomainAdmin_&shy;EventDomain</title>
- <shorttitle>..._EventDomain</shorttitle>
+ <title>CosEventDomainAdmin_EventDomain</title>
<prepared></prepared>
<docno></docno>
<approved>Niclas Eklund</approved>
diff --git a/lib/cosEventDomain/doc/src/CosEventDomainAdmin_EventDomainFactory.xml b/lib/cosEventDomain/doc/src/CosEventDomainAdmin_EventDomainFactory.xml
index ea605f23a0..5eff7038d9 100644
--- a/lib/cosEventDomain/doc/src/CosEventDomainAdmin_EventDomainFactory.xml
+++ b/lib/cosEventDomain/doc/src/CosEventDomainAdmin_EventDomainFactory.xml
@@ -23,8 +23,7 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosEventDomainAdmin_&shy;EventDomainFactory</title>
- <shorttitle>..._EventChannel</shorttitle>
+ <title>CosEventDomainAdmin_EventDomainFactory</title>
<prepared>Niclas Eklund</prepared>
<responsible>Niclas Eklund</responsible>
<docno></docno>
diff --git a/lib/cosEventDomain/doc/src/notes.xml b/lib/cosEventDomain/doc/src/notes.xml
index 522dcea829..585761ce65 100644
--- a/lib/cosEventDomain/doc/src/notes.xml
+++ b/lib/cosEventDomain/doc/src/notes.xml
@@ -32,6 +32,23 @@
</header>
<section>
+ <title>cosEventDomain 1.1.11</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>
+ Removed superfluous usage of shy in the documentation since it can cause problem if
+ a buggy tool is used.</p>
+ <p>
+ Own Id: OTP-9319 Aux Id:</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
<title>cosEventDomain 1.1.10</title>
<section>
diff --git a/lib/cosEventDomain/src/Makefile b/lib/cosEventDomain/src/Makefile
index 56a67cd225..91bef4e7e6 100644
--- a/lib/cosEventDomain/src/Makefile
+++ b/lib/cosEventDomain/src/Makefile
@@ -150,9 +150,14 @@ docs:
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
-$(GEN_ERL_FILES) $(EXTERNAL_GEN_HRL_FILES): CosEventDomainAdmin.idl
+IDL-GENERATED: CosEventDomainAdmin.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosEventDomainAdmin.cfg"}' CosEventDomainAdmin.idl
mv $(GEN_HRL_FILES) $(EXTERNAL_INC_PATH)
+ >IDL-GENERATED
+
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Target
diff --git a/lib/cosEventDomain/vsn.mk b/lib/cosEventDomain/vsn.mk
index f4a77ab7a8..7df47cef2e 100644
--- a/lib/cosEventDomain/vsn.mk
+++ b/lib/cosEventDomain/vsn.mk
@@ -1,3 +1,3 @@
-COSEVENTDOMAIN_VSN = 1.1.10
+COSEVENTDOMAIN_VSN = 1.1.11
diff --git a/lib/cosFileTransfer/doc/src/CosFileTransfer_Directory.xml b/lib/cosFileTransfer/doc/src/CosFileTransfer_Directory.xml
index af9141b205..7c68768aa9 100644
--- a/lib/cosFileTransfer/doc/src/CosFileTransfer_Directory.xml
+++ b/lib/cosFileTransfer/doc/src/CosFileTransfer_Directory.xml
@@ -23,8 +23,7 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosFileTransfer_&shy;Directory</title>
- <shorttitle>..._Directory</shorttitle>
+ <title>CosFileTransfer_Directory</title>
<prepared></prepared>
<docno></docno>
<checked></checked>
diff --git a/lib/cosFileTransfer/doc/src/CosFileTransfer_File.xml b/lib/cosFileTransfer/doc/src/CosFileTransfer_File.xml
index bef7cb882f..8b317049e2 100644
--- a/lib/cosFileTransfer/doc/src/CosFileTransfer_File.xml
+++ b/lib/cosFileTransfer/doc/src/CosFileTransfer_File.xml
@@ -23,11 +23,10 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosFileTransfer_&shy;File</title>
- <shorttitle>..._File</shorttitle>
+ <title>CosFileTransfer_File</title>
<prepared></prepared>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>2000-11-09</date>
<rev>PA1</rev>
diff --git a/lib/cosFileTransfer/doc/src/CosFileTransfer_FileIterator.xml b/lib/cosFileTransfer/doc/src/CosFileTransfer_FileIterator.xml
index c848a9830d..80cbd1f448 100644
--- a/lib/cosFileTransfer/doc/src/CosFileTransfer_FileIterator.xml
+++ b/lib/cosFileTransfer/doc/src/CosFileTransfer_FileIterator.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2009</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -21,8 +21,7 @@
</legalnotice>
- <title>CosFileTransfer_&shy;FileIterator</title>
- <shorttitle>..._FileIterator</shorttitle>
+ <title>CosFileTransfer_FileIterator</title>
<prepared></prepared>
<docno></docno>
<checked></checked>
diff --git a/lib/cosFileTransfer/doc/src/CosFileTransfer_FileTransferSession.xml b/lib/cosFileTransfer/doc/src/CosFileTransfer_FileTransferSession.xml
index 5f4542058b..918f0bf9f7 100644
--- a/lib/cosFileTransfer/doc/src/CosFileTransfer_FileTransferSession.xml
+++ b/lib/cosFileTransfer/doc/src/CosFileTransfer_FileTransferSession.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2009</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -21,8 +21,7 @@
</legalnotice>
- <title>CosFileTransfer_&shy;FileTransferSession</title>
- <shorttitle>..._FileTransferSession</shorttitle>
+ <title>CosFileTransfer_FileTransferSession</title>
<prepared></prepared>
<docno></docno>
<checked></checked>
@@ -160,7 +159,7 @@
</func>
<func>
<name>insert(FTS, SourceFile, DestinationFile, Offset) -> Return</name>
- <fsummary>Insert the <c>SourceFile</c>into the <c>DestinationFile</c><c>Offset</c>bytes from the start of the file</fsummary>
+ <fsummary>Insert the <c>SourceFile</c>into the <c>DestinationFile</c> <c>Offset</c>bytes from the start of the file</fsummary>
<type>
<v>FTS = SourceFile = DestinationFile = #objref</v>
<v>Offset = long()</v>
@@ -169,7 +168,7 @@
<desc>
<p>This operation behaves almost like the <c>append/3</c> operation. The
difference is that the <c>SourceFile</c> will be inserted into the
- <c>DestinationFile</c><c>Offset</c> bytes from the start of the file.</p>
+ <c>DestinationFile</c> <c>Offset</c> bytes from the start of the file.</p>
<p>Currently, it is not possible to use this operation when the target
object represents FTP.</p>
</desc>
diff --git a/lib/cosFileTransfer/doc/src/CosFileTransfer_VirtualFileSystem.xml b/lib/cosFileTransfer/doc/src/CosFileTransfer_VirtualFileSystem.xml
index 8aa02b2153..7bb6e8d356 100644
--- a/lib/cosFileTransfer/doc/src/CosFileTransfer_VirtualFileSystem.xml
+++ b/lib/cosFileTransfer/doc/src/CosFileTransfer_VirtualFileSystem.xml
@@ -23,8 +23,7 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosFileTransfer_&shy;VirtualFileSystem</title>
- <shorttitle>..._VirtualFileSystem</shorttitle>
+ <title>CosFileTransfer_VirtualFileSystem</title>
<prepared></prepared>
<docno></docno>
<checked></checked>
diff --git a/lib/cosFileTransfer/doc/src/notes.xml b/lib/cosFileTransfer/doc/src/notes.xml
index 48d0c04236..c7a4fd4504 100644
--- a/lib/cosFileTransfer/doc/src/notes.xml
+++ b/lib/cosFileTransfer/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2010</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,6 +30,37 @@
<file>notes.xml</file>
</header>
+ <section><title>cosFileTransfer 1.1.12</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section>
+ <title>cosFileTransfer 1.1.11</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>
+ Removed superfluous usage of shy in the documentation since it can cause problem if
+ a buggy tool is used.</p>
+ <p>
+ Own Id: OTP-9319 Aux Id:</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
<section>
<title>cosFileTransfer 1.1.10</title>
diff --git a/lib/cosFileTransfer/src/CosFileTransfer_FileTransferSession_impl.erl b/lib/cosFileTransfer/src/CosFileTransfer_FileTransferSession_impl.erl
index e222c5b92b..b7643fb30d 100644
--- a/lib/cosFileTransfer/src/CosFileTransfer_FileTransferSession_impl.erl
+++ b/lib/cosFileTransfer/src/CosFileTransfer_FileTransferSession_impl.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -792,7 +792,7 @@ target_FTS_operation(State, _SrcFile, DestFile, Op, Offset) ->
%% Delete the temporary local copy.
delete_tmp_file(TempName,
"Transfer completed but failed to remove temporary local copy."),
- %% Completed the transfer succesfully.
+ %% Completed the transfer successfully.
{reply, ok, State};
{error, epath} ->
delete_tmp_file(TempName,
diff --git a/lib/cosFileTransfer/src/Makefile b/lib/cosFileTransfer/src/Makefile
index 773ed7f6b7..17e82f9bc2 100644
--- a/lib/cosFileTransfer/src/Makefile
+++ b/lib/cosFileTransfer/src/Makefile
@@ -161,9 +161,14 @@ docs:
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
-$(GEN_ERL_FILES) $(GEN_HRL_FILES): CosFileTransfer.idl
+IDL-GENERATED: CosFileTransfer.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosFileTransfer.cfg"}' CosFileTransfer.idl
mv $(LOCAL_HRL_FILES) $(EXTERNAL_INC_PATH)
+ >IDL-GENERATED
+
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Target
diff --git a/lib/cosFileTransfer/test/Makefile b/lib/cosFileTransfer/test/Makefile
index ec7ebcafca..b46fb35356 100644
--- a/lib/cosFileTransfer/test/Makefile
+++ b/lib/cosFileTransfer/test/Makefile
@@ -130,4 +130,4 @@ release_tests_spec: tests
$(INSTALL_DATA) $(IDL_FILES) $(TEST_SPEC_FILE) \
$(COVER_FILE) $(ERL_FILES) $(RELSYSDIR)
$(INSTALL_DATA) $(SUITE_TARGET_FILES) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
diff --git a/lib/cosFileTransfer/vsn.mk b/lib/cosFileTransfer/vsn.mk
index ef8ee53c5e..fe0226e3b3 100644
--- a/lib/cosFileTransfer/vsn.mk
+++ b/lib/cosFileTransfer/vsn.mk
@@ -1 +1 @@
-COSFILETRANSFER_VSN = 1.1.10
+COSFILETRANSFER_VSN = 1.1.12
diff --git a/lib/cosNotification/doc/src/CosNotification_AdminPropertiesAdmin.xml b/lib/cosNotification/doc/src/CosNotification_AdminPropertiesAdmin.xml
index 57015b3621..46c3921b66 100644
--- a/lib/cosNotification/doc/src/CosNotification_AdminPropertiesAdmin.xml
+++ b/lib/cosNotification/doc/src/CosNotification_AdminPropertiesAdmin.xml
@@ -23,10 +23,9 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosNotification_&shy;AdminPropertiesAdmin</title>
- <shorttitle>..._AdminPropertiesAdmin</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosNotification_AdminPropertiesAdmin</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
<approved>Niclas Eklund</approved>
<checked></checked>
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ConsumerAdmin.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ConsumerAdmin.xml
index 671f68d482..96ccdf1d29 100644
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ConsumerAdmin.xml
+++ b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ConsumerAdmin.xml
@@ -23,12 +23,11 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosNotifyChannelAdmin_&shy;ConsumerAdmin</title>
- <shorttitle>..._ConsumerAdmin</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosNotifyChannelAdmin_ConsumerAdmin</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>2000-02-01</date>
<rev>1.0</rev>
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_EventChannel.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_EventChannel.xml
index b6af2e2ca3..1682cf9968 100644
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_EventChannel.xml
+++ b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_EventChannel.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2009</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -21,8 +21,7 @@
</legalnotice>
- <title>CosNotifyChannelAdmin_&shy;EventChannel</title>
- <shorttitle>..._EventChannel</shorttitle>
+ <title>CosNotifyChannelAdmin_EventChannel</title>
<prepared></prepared>
<docno></docno>
<checked></checked>
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_EventChannelFactory.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_EventChannelFactory.xml
index 01976954e7..64e0e4dad8 100644
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_EventChannelFactory.xml
+++ b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_EventChannelFactory.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2009</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -21,8 +21,7 @@
</legalnotice>
- <title>CosNotifyChannelAdmin_&shy;EventChannelFactory</title>
- <shorttitle>..._EventChannelFactory</shorttitle>
+ <title>CosNotifyChannelAdmin_EventChannelFactory</title>
<prepared></prepared>
<docno></docno>
<checked></checked>
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyConsumer.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyConsumer.xml
index 8bc182a50c..7ba74547bb 100644
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyConsumer.xml
+++ b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyConsumer.xml
@@ -23,12 +23,11 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosNotifyChannelAdmin_&shy;ProxyConsumer</title>
- <shorttitle>..._ProxyConsumer</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosNotifyChannelAdmin_ProxyConsumer</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>2000-02-01</date>
<rev>1.0</rev>
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPullConsumer.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPullConsumer.xml
index 43818e5238..d8344e004a 100644
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPullConsumer.xml
+++ b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPullConsumer.xml
@@ -23,12 +23,11 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosNotifyChannelAdmin_&shy;ProxyPullConsumer</title>
- <shorttitle>..._ProxyPullConsumer</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosNotifyChannelAdmin_ProxyPullConsumer</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>2000-02-01</date>
<rev>1.0</rev>
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPullSupplier.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPullSupplier.xml
index 4c0aac7ae6..cc2c17a3ca 100644
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPullSupplier.xml
+++ b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPullSupplier.xml
@@ -23,12 +23,11 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosNotifyChannelAdmin_&shy;ProxyPullSupplier</title>
- <shorttitle>..._ProxyPullSupplier</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosNotifyChannelAdmin_ProxyPullSupplier</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>2000-02-01</date>
<rev>1.0</rev>
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPushConsumer.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPushConsumer.xml
index 697d00ea51..30ba264f74 100644
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPushConsumer.xml
+++ b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPushConsumer.xml
@@ -23,10 +23,9 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosNotifyChannelAdmin_&shy;ProxyPushConsumer</title>
- <shorttitle>..._ProxyPushConsumer</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosNotifyChannelAdmin_ProxyPushConsumer</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
<approved>Niclas Eklund</approved>
<checked></checked>
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPushSupplier.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPushSupplier.xml
index f6fc3a0f7b..d5079a5ae7 100644
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPushSupplier.xml
+++ b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPushSupplier.xml
@@ -23,12 +23,11 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosNotifyChannelAdmin_&shy;ProxyPushSupplier</title>
- <shorttitle>..._ProxyPushSupplier</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosNotifyChannelAdmin_ProxyPushSupplier</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>2000-02-01</date>
<rev>1.0</rev>
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxySupplier.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxySupplier.xml
index 81d4de929a..bdd9213a8b 100644
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxySupplier.xml
+++ b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxySupplier.xml
@@ -23,12 +23,11 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosNotifyChannelAdmin_&shy;ProxySupplier</title>
- <shorttitle>..._ProxySupplier</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosNotifyChannelAdmin_ProxySupplier</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>2000-02-01</date>
<rev>1.0</rev>
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPullConsumer.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPullConsumer.xml
index 4084fd443b..86796a2643 100644
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPullConsumer.xml
+++ b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPullConsumer.xml
@@ -23,12 +23,11 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosNotifyChannelAdmin_&shy;SequenceProxyPullConsumer</title>
- <shorttitle>..._SequenceProxyPullConsumer</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosNotifyChannelAdmin_SequenceProxyPullConsumer</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>2000-02-01</date>
<rev>1.0</rev>
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPullSupplier.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPullSupplier.xml
index 16b093b9aa..c30217362a 100644
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPullSupplier.xml
+++ b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPullSupplier.xml
@@ -23,12 +23,11 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosNotifyChannelAdmin_&shy;SequenceProxyPullSupplier</title>
- <shorttitle>..._SequenceProxyPullSupplier</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosNotifyChannelAdmin_SequenceProxyPullSupplier</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>2000-02-01</date>
<rev>1.0</rev>
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPushConsumer.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPushConsumer.xml
index 964d212715..3f3e187486 100644
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPushConsumer.xml
+++ b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPushConsumer.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2009</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -21,15 +21,14 @@
</legalnotice>
- <title>CosNotifyChannelAdmin_&shy;SequenceProxyPushConsumer</title>
- <shorttitle>..._SequenceProxyPushConsumer</shorttitle>
+ <title>CosNotifyChannelAdmin_SequenceProxyPushConsumer</title>
<prepared></prepared>
<docno></docno>
<checked></checked>
<date>2000-02-01</date>
<rev>1.0</rev>
</header>
- <module>CosNotifyChannelAdmin_&shy;SequenceProxyPushConsumer</module>
+ <module>CosNotifyChannelAdmin_SequenceProxyPushConsumer</module>
<modulesummary>This module implements the OMG CosNotifyChannelAdmin::SequenceProxyPushConsumer interface.</modulesummary>
<description>
<p>To get access to the record definitions for the structures use: <br></br>
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPushSupplier.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPushSupplier.xml
index f8ce2072e1..f85f33de01 100644
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPushSupplier.xml
+++ b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPushSupplier.xml
@@ -23,17 +23,16 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosNotifyChannelAdmin_&shy;SequenceProxyPushSupplier</title>
- <shorttitle>..._SequenceProxyPushSupplier</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosNotifyChannelAdmin_SequenceProxyPushSupplier</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>2000-02-01</date>
<rev>1.0</rev>
</header>
- <module>CosNotifyChannelAdmin_&shy;SequenceProxyPushSupplier</module>
+ <module>CosNotifyChannelAdmin_SequenceProxyPushSupplier</module>
<modulesummary>This module implements the OMG CosNotifyChannelAdmin::SequenceProxyPushSupplier interface.</modulesummary>
<description>
<p>To get access to the record definitions for the structures use: <br></br>
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPullConsumer.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPullConsumer.xml
index 0623d2891b..09546d9584 100644
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPullConsumer.xml
+++ b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPullConsumer.xml
@@ -23,17 +23,16 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosNotifyChannelAdmin_&shy;StructuredProxyPullConsumer</title>
- <shorttitle>..._StructuredProxyPullConsumer</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosNotifyChannelAdmin_StructuredProxyPullConsumer</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>2000-02-01</date>
<rev>1.0</rev>
</header>
- <module>CosNotifyChannelAdmin_&shy;StructuredProxyPullConsumer</module>
+ <module>CosNotifyChannelAdmin_StructuredProxyPullConsumer</module>
<modulesummary>This module implements the OMG CosNotifyChannelAdmin::StructuredProxyPullConsumer interface.</modulesummary>
<description>
<p>To get access to the record definitions for the structures use: <br></br>
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPullSupplier.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPullSupplier.xml
index 0f0bb5d985..d171851014 100644
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPullSupplier.xml
+++ b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPullSupplier.xml
@@ -23,17 +23,16 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosNotifyChannelAdmin_&shy;StructuredProxyPullSupplier</title>
- <shorttitle>..._StructuredProxyPullSupplier</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosNotifyChannelAdmin_StructuredProxyPullSupplier</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>2000-02-01</date>
<rev>1.0</rev>
</header>
- <module>CosNotifyChannelAdmin_&shy;StructuredProxyPullSupplier</module>
+ <module>CosNotifyChannelAdmin_StructuredProxyPullSupplier</module>
<modulesummary>This module implements the OMG CosNotifyChannelAdmin::StructuredProxyPullSupplier interface.</modulesummary>
<description>
<p>To get access to the record definitions for the structures use: <br></br>
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPushConsumer.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPushConsumer.xml
index 7b7a60723e..a055a0ab36 100644
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPushConsumer.xml
+++ b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPushConsumer.xml
@@ -23,17 +23,16 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosNotifyChannelAdmin_&shy;StructuredProxyPushConsumer</title>
- <shorttitle>..._StructuredProxyPushConsumer</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosNotifyChannelAdmin_StructuredProxyPushConsumer</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>2000-02-01</date>
<rev>1.0</rev>
</header>
- <module>CosNotifyChannelAdmin_&shy;StructuredProxyPushConsumer</module>
+ <module>CosNotifyChannelAdmin_StructuredProxyPushConsumer</module>
<modulesummary>This module implements the OMG CosNotifyChannelAdmin::StructuredProxyPushConsumer interface.</modulesummary>
<description>
<p>To get access to the record definitions for the structures use: <br></br>
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPushSupplier.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPushSupplier.xml
index ab0a260a4b..f03322b819 100644
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPushSupplier.xml
+++ b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPushSupplier.xml
@@ -23,17 +23,16 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosNotifyChannelAdmin_&shy;StructuredProxyPushSupplier</title>
- <shorttitle>..._StructuredProxyPushSupplier</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosNotifyChannelAdmin_StructuredProxyPushSupplier</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>2000-02-01</date>
<rev>1.0</rev>
</header>
- <module>CosNotifyChannelAdmin_&shy;StructuredProxyPushSupplier</module>
+ <module>CosNotifyChannelAdmin_StructuredProxyPushSupplier</module>
<modulesummary>This module implements the OMG CosNotifyChannelAdmin::StructuredProxyPushSupplier interface.</modulesummary>
<description>
<p>To get access to the record definitions for the structures use: <br></br>
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SupplierAdmin.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SupplierAdmin.xml
index a567463f7d..5c7408040d 100644
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SupplierAdmin.xml
+++ b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SupplierAdmin.xml
@@ -23,10 +23,9 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosNotifyChannelAdmin_&shy;SupplierAdmin</title>
- <shorttitle>..._SupplierAdmin</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosNotifyChannelAdmin_SupplierAdmin</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
<approved>Niclas Eklund</approved>
<checked></checked>
diff --git a/lib/cosNotification/doc/src/CosNotifyComm_NotifySubscribe.xml b/lib/cosNotification/doc/src/CosNotifyComm_NotifySubscribe.xml
index dd8ef713e8..97b15d958a 100644
--- a/lib/cosNotification/doc/src/CosNotifyComm_NotifySubscribe.xml
+++ b/lib/cosNotification/doc/src/CosNotifyComm_NotifySubscribe.xml
@@ -23,12 +23,11 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosNotifyComm_&shy;NotifySubscribe</title>
- <shorttitle>..._NotifySubscribe</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosNotifyComm_NotifySubscribe</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>2000-02-01</date>
<rev>1.0</rev>
diff --git a/lib/cosNotification/doc/src/ch_BNF.xml b/lib/cosNotification/doc/src/ch_BNF.xml
index 73e91e3cac..f658f606d3 100644
--- a/lib/cosNotification/doc/src/ch_BNF.xml
+++ b/lib/cosNotification/doc/src/ch_BNF.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2009</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -294,7 +294,7 @@ FilterID = 'CosNotifyChannelAdmin_ConsumerAdmin':
</row>
<row>
<cell align="left" valign="middle"><c>in</c></cell>
- <cell align="left" valign="middle"><c>"'Erlang' in $.FunctionalLanguages&shy;StringSeq"</c></cell>
+ <cell align="left" valign="middle"><c>"'Erlang' in $.FunctionalLanguagesStringSeq"</c></cell>
<cell align="left" valign="middle">Returns <c>TRUE</c>if a given element is found in the given sequence. The element must be of a simple type and the same as the sequence is defined to contain.</cell>
</row>
<row>
@@ -394,17 +394,17 @@ Figure 1: The structure of a structured event.</icaption>
</row>
<row>
<cell align="left" valign="middle">type_name</cell>
- <cell align="left" valign="middle">"$.header.fixed_header.event_&shy;type.type_name == 'Type'"</cell>
+ <cell align="left" valign="middle">"$.header.fixed_header.event_type.type_name == 'Type'"</cell>
<cell align="left" valign="middle">"$type_name == 'Type'"</cell>
</row>
<row>
<cell align="left" valign="middle">domain_name</cell>
- <cell align="left" valign="middle">"$.header.fixed_header.event_&shy;type.domain_name == 'Domain'"</cell>
+ <cell align="left" valign="middle">"$.header.fixed_header.event_type.domain_name == 'Domain'"</cell>
<cell align="left" valign="middle">"$domain_name == 'Domain'"</cell>
</row>
<row>
<cell align="left" valign="middle">event_name</cell>
- <cell align="left" valign="middle">"$.header.fixed_header.event_&shy;name == 'Event'"</cell>
+ <cell align="left" valign="middle">"$.header.fixed_header.event_name == 'Event'"</cell>
<cell align="left" valign="middle">"$event_name == 'Event'"</cell>
</row>
<tcaption>Table 2: Fixed Header Constraint Examples</tcaption>
diff --git a/lib/cosNotification/doc/src/notes.xml b/lib/cosNotification/doc/src/notes.xml
index 125e25e67e..a54230c9f7 100644
--- a/lib/cosNotification/doc/src/notes.xml
+++ b/lib/cosNotification/doc/src/notes.xml
@@ -31,6 +31,21 @@
<file>notes.xml</file>
</header>
+ <section><title>cosNotification 1.1.17</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Removed superfluous usage of shy in the documentation since it can cause problem if
+ a buggy tool is used.</p>
+ <p>
+ Own Id: OTP-9319 Aux Id:</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
<section><title>cosNotification 1.1.16</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/cosNotification/src/Makefile b/lib/cosNotification/src/Makefile
index 637c633e52..b976ab94f3 100644
--- a/lib/cosNotification/src/Makefile
+++ b/lib/cosNotification/src/Makefile
@@ -242,20 +242,26 @@ GEN_OE_EVENTCOMM_HRL_FILES = \
oe_CosNotificationComm.hrl \
oe_CosNotificationComm_Event.hrl
-GEN_ERL_FILES = \
+IDL_GEN_ERL_FILES = \
$(GEN_NOTIFICATION_ERL_FILES) \
$(GEN_OE_EVENTCOMM_ERL_FILES) \
$(GEN_NOTIFYCOMM_ERL_FILES) \
$(GEN_NOTIFYFILTER_ERL_FILES) \
- $(GEN_CHANNELADMIN_ERL_FILES) \
- $(GEN_YECC_ERL_FILES)
+ $(GEN_CHANNELADMIN_ERL_FILES)
-GEN_HRL_FILES = \
+IDL_GEN_HRL_FILES = \
$(EXTERNAL_GEN_NOTIFICATION_HRL_FILES) \
$(GEN_OE_EVENTCOMM_HRL_FILES) \
$(EXTERNAL_GEN_NOTIFYCOMM_HRL_FILES) \
$(EXTERNAL_GEN_NOTIFYFILTER_HRL_FILES) \
- $(EXTERNAL_GEN_CHANNELADMIN_HRL_FILES) \
+ $(EXTERNAL_GEN_CHANNELADMIN_HRL_FILES)
+
+GEN_ERL_FILES = \
+ $(IDL_GEN_ERL_FILES) \
+ $(GEN_YECC_ERL_FILES)
+
+GEN_HRL_FILES = \
+ $(IDL_GEN_HRL_FILES) \
$(GEN_YECC_HRL_FILES)
@@ -336,20 +342,23 @@ docs:
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
-$(GEN_NOTIFICATION_ERL_FILES) $(EXTERNAL_GEN_NOTIFICATION_HRL_FILES): CosNotification.idl
+IDL-GENERATED: CosNotification.idl CosNotifyChannelAdmin.idl \
+ CosNotifyFilter.idl cosNotificationAppComm.idl CosNotifyComm.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosNotification.cfg"}' CosNotification.idl
mv $(GEN_NOTIFICATION_HRL_FILES) $(EXTERNAL_INC_PATH)
-$(GEN_CHANNELADMIN_ERL_FILES) $(EXTERNAL_GEN_CHANNELADMIN_HRL_FILES): CosNotifyChannelAdmin.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosNotifyChannelAdmin.cfg"}' CosNotifyChannelAdmin.idl
mv $(GEN_CHANNELADMIN_HRL_FILES) $(EXTERNAL_INC_PATH)
-$(GEN_NOTIFYFILTER_ERL_FILES) $(EXTERNAL_GEN_NOTIFYFILTER_HRL_FILES): CosNotifyFilter.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosNotifyFilter.cfg"}' CosNotifyFilter.idl
mv $(GEN_NOTIFYFILTER_HRL_FILES) $(EXTERNAL_INC_PATH)
-$(GEN_OE_EVENTCOMM_ERL_FILES) $(GEN_OE_EVENTCOMM_HRL_FILES): cosNotificationAppComm.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"cosNotificationComm.cfg"}' cosNotificationAppComm.idl
-$(GEN_NOTIFYCOMM_ERL_FILES) $(EXTERNAL_GEN_NOTIFYCOMM_HRL_FILES): CosNotifyComm.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosNotifyComm.cfg"}' CosNotifyComm.idl
mv $(GEN_NOTIFYCOMM_HRL_FILES) $(EXTERNAL_INC_PATH)
+ >IDL-GENERATED
+
+$(IDL_GEN_ERL_FILES) $(IDL_GEN_HRL_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
+
$(GEN_YECC_ERL_FILES) $(GEN_YECC_HRL_FILES): cosNotification_Grammar.yrl
# ----------------------------------------------------
diff --git a/lib/cosNotification/test/Makefile b/lib/cosNotification/test/Makefile
index 43f73addae..f509370430 100644
--- a/lib/cosNotification/test/Makefile
+++ b/lib/cosNotification/test/Makefile
@@ -161,13 +161,14 @@ docs:
# Special Targets
# ----------------------------------------------------
-TGT_TEST = \
- $(GEN_HRL_FILES:%=$(IDLOUTDIR)/%) \
- $(GEN_MODULES:%=$(IDLOUTDIR)/%.erl)
-
-$(TGT_TEST): notify_test_server.idl
+IDL-GENERATED: notify_test_server.idl
erlc $(ERL_COMPILE_FLAGS) -o$(IDLOUTDIR) \
+'{cfgfile,"notify_test_server.cfg"}' notify_test_server.idl
+ >IDL-GENERATED
+
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Targets
diff --git a/lib/cosNotification/vsn.mk b/lib/cosNotification/vsn.mk
index 6613385579..b32919a2ef 100644
--- a/lib/cosNotification/vsn.mk
+++ b/lib/cosNotification/vsn.mk
@@ -1,2 +1,2 @@
-COSNOTIFICATION_VSN = 1.1.16
+COSNOTIFICATION_VSN = 1.1.17
diff --git a/lib/cosProperty/doc/src/CosPropertyService_PropertiesIterator.xml b/lib/cosProperty/doc/src/CosPropertyService_PropertiesIterator.xml
index 75c7cb38cb..623e121715 100644
--- a/lib/cosProperty/doc/src/CosPropertyService_PropertiesIterator.xml
+++ b/lib/cosProperty/doc/src/CosPropertyService_PropertiesIterator.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2009</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -21,8 +21,7 @@
</legalnotice>
- <title>CosPropertyService_&shy;PropertiesIterator</title>
- <shorttitle>..._PropertiesIterator</shorttitle>
+ <title>CosPropertyService_PropertiesIterator</title>
<prepared></prepared>
<docno></docno>
<checked></checked>
diff --git a/lib/cosProperty/doc/src/CosPropertyService_PropertyNamesIterator.xml b/lib/cosProperty/doc/src/CosPropertyService_PropertyNamesIterator.xml
index 1710769661..9cb5e8f489 100644
--- a/lib/cosProperty/doc/src/CosPropertyService_PropertyNamesIterator.xml
+++ b/lib/cosProperty/doc/src/CosPropertyService_PropertyNamesIterator.xml
@@ -23,12 +23,11 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosPropertyService_&shy;PropertyNamesIterator</title>
- <shorttitle>..._PropertyNamesIterator</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosPropertyService_PropertyNamesIterator</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>2000-07-25</date>
<rev>1.0</rev>
diff --git a/lib/cosProperty/doc/src/CosPropertyService_PropertySet.xml b/lib/cosProperty/doc/src/CosPropertyService_PropertySet.xml
index 2c1671bf77..f9a7c9ca97 100644
--- a/lib/cosProperty/doc/src/CosPropertyService_PropertySet.xml
+++ b/lib/cosProperty/doc/src/CosPropertyService_PropertySet.xml
@@ -23,12 +23,11 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosPropertyService_&shy;PropertySet</title>
- <shorttitle>..._PropertySet</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosPropertyService_PropertySet</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>2000-07-25</date>
<rev>1.0</rev>
diff --git a/lib/cosProperty/doc/src/CosPropertyService_PropertySetDef.xml b/lib/cosProperty/doc/src/CosPropertyService_PropertySetDef.xml
index 7684998428..2dbfd05ba8 100644
--- a/lib/cosProperty/doc/src/CosPropertyService_PropertySetDef.xml
+++ b/lib/cosProperty/doc/src/CosPropertyService_PropertySetDef.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2009</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -21,8 +21,7 @@
</legalnotice>
- <title>CosPropertyService_&shy;PropertySetDef</title>
- <shorttitle>..._PropertySetDef</shorttitle>
+ <title>CosPropertyService_PropertySetDef</title>
<prepared></prepared>
<docno></docno>
<checked></checked>
diff --git a/lib/cosProperty/doc/src/CosPropertyService_PropertySetDefFactory.xml b/lib/cosProperty/doc/src/CosPropertyService_PropertySetDefFactory.xml
index 67aa579e6a..a009e70f68 100644
--- a/lib/cosProperty/doc/src/CosPropertyService_PropertySetDefFactory.xml
+++ b/lib/cosProperty/doc/src/CosPropertyService_PropertySetDefFactory.xml
@@ -23,10 +23,9 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosPropertyService_&shy;PropertySetDefFactory</title>
- <shorttitle>..._PropertySetDefFactory</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosPropertyService_PropertySetDefFactory</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
<approved>Niclas Eklund</approved>
<checked></checked>
diff --git a/lib/cosProperty/doc/src/CosPropertyService_PropertySetFactory.xml b/lib/cosProperty/doc/src/CosPropertyService_PropertySetFactory.xml
index 3fb4822948..62ee2bda4f 100644
--- a/lib/cosProperty/doc/src/CosPropertyService_PropertySetFactory.xml
+++ b/lib/cosProperty/doc/src/CosPropertyService_PropertySetFactory.xml
@@ -23,12 +23,11 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosPropertyService_&shy;PropertySetFactory</title>
- <shorttitle>..._PropertySetFactory</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosPropertyService_PropertySetFactory</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>2000-07-25</date>
<rev>1.0</rev>
diff --git a/lib/cosProperty/doc/src/notes.xml b/lib/cosProperty/doc/src/notes.xml
index 540fdce762..85b2119e9d 100644
--- a/lib/cosProperty/doc/src/notes.xml
+++ b/lib/cosProperty/doc/src/notes.xml
@@ -22,7 +22,7 @@
</legalnotice>
<title>cosProperty Release Notes</title>
- <prepared>Niclas Eklund</prepared>
+ <prepared></prepared>
<docno></docno>
<approved></approved>
<checked></checked>
@@ -32,6 +32,23 @@
</header>
<section>
+ <title>cosProperty 1.1.14</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>
+ Removed superfluous usage of shy in the documentation since it can cause problem if
+ a buggy tool is used.</p>
+ <p>
+ Own Id: OTP-9319 Aux Id:</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
<title>cosProperty 1.1.13</title>
<section>
diff --git a/lib/cosProperty/src/Makefile b/lib/cosProperty/src/Makefile
index 1d2119dfb3..d12554b18d 100644
--- a/lib/cosProperty/src/Makefile
+++ b/lib/cosProperty/src/Makefile
@@ -161,10 +161,14 @@ docs:
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
-$(GEN_ERL_FILES) $(GEN_HRL_FILES): CosProperty.idl
+IDL-GENERATED: CosProperty.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosProperty.cfg"}' CosProperty.idl
mv $(LOCAL_HRL_FILES) $(EXTERNAL_INC_PATH)
+ >IDL-GENERATED
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Target
diff --git a/lib/cosProperty/vsn.mk b/lib/cosProperty/vsn.mk
index deb1eb0450..ecc4a2746c 100644
--- a/lib/cosProperty/vsn.mk
+++ b/lib/cosProperty/vsn.mk
@@ -1,2 +1,2 @@
-COSPROPERTY_VSN = 1.1.13
+COSPROPERTY_VSN = 1.1.14
diff --git a/lib/cosTime/doc/src/CosTimerEvent_TimerEventHandler.xml b/lib/cosTime/doc/src/CosTimerEvent_TimerEventHandler.xml
index 4b2e57642a..2adf318674 100644
--- a/lib/cosTime/doc/src/CosTimerEvent_TimerEventHandler.xml
+++ b/lib/cosTime/doc/src/CosTimerEvent_TimerEventHandler.xml
@@ -23,10 +23,9 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosTimerEvent_&shy;TimerEventHandler</title>
- <shorttitle>..._TimerEventHandler</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosTimerEvent_TimerEventHandler</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
<approved>Niclas Eklund</approved>
<checked></checked>
diff --git a/lib/cosTime/doc/src/CosTimerEvent_TimerEventService.xml b/lib/cosTime/doc/src/CosTimerEvent_TimerEventService.xml
index fb3fe747e5..80f5fd1466 100644
--- a/lib/cosTime/doc/src/CosTimerEvent_TimerEventService.xml
+++ b/lib/cosTime/doc/src/CosTimerEvent_TimerEventService.xml
@@ -23,8 +23,7 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosTimerEvent_&shy;TimerEventService</title>
- <shorttitle>..._TimerEventService</shorttitle>
+ <title>CosTimerEvent_TimerEventService</title>
<prepared>Niclas Eklund</prepared>
<responsible>Niclas Eklund</responsible>
<docno></docno>
diff --git a/lib/cosTime/doc/src/notes.xml b/lib/cosTime/doc/src/notes.xml
index 718ca23bc5..3698e4813e 100644
--- a/lib/cosTime/doc/src/notes.xml
+++ b/lib/cosTime/doc/src/notes.xml
@@ -33,6 +33,23 @@
</header>
<section>
+ <title>cosTime 1.1.11</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>
+ Removed superfluous usage of shy in the documentation since it can cause problem if
+ a buggy tool is used.</p>
+ <p>
+ Own Id: OTP-9319 Aux Id:</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
<title>cosTime 1.1.10</title>
<section>
diff --git a/lib/cosTime/src/Makefile b/lib/cosTime/src/Makefile
index 3b6f7bae2e..1793822fb6 100644
--- a/lib/cosTime/src/Makefile
+++ b/lib/cosTime/src/Makefile
@@ -176,17 +176,18 @@ docs:
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
-$(GEN_TIMEBASE_ERL_FILES) $(EXTERNAL_TIMEBASE_HRL_FILES): TimeBase.idl
+IDL-GENERATED: TimeBase.idl CosTime.idl CosTimerEvent.idl
erlc $(ERL_IDL_FLAGS) TimeBase.idl
mv $(GEN_TIMEBASE_HRL_FILES) $(EXTERNAL_INC_PATH)
-
-$(GEN_COSTIME_ERL_FILES) $(EXTERNAL_COSTIME_HRL_FILES): CosTime.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosTime.cfg"}' CosTime.idl
mv $(GEN_COSTIME_HRL_FILES) $(EXTERNAL_INC_PATH)
-
-$(GEN_COSTIMEREVENT_ERL_FILES) $(EXTERNAL_COSTIMEREVENT_HRL_FILES): CosTimerEvent.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosTimerEvent.cfg"}' CosTimerEvent.idl
mv $(GEN_COSTIMEREVENT_HRL_FILES) $(EXTERNAL_INC_PATH)
+ >IDL-GENERATED
+
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Target
diff --git a/lib/cosTime/vsn.mk b/lib/cosTime/vsn.mk
index ebc5aff1cc..4d982f3013 100644
--- a/lib/cosTime/vsn.mk
+++ b/lib/cosTime/vsn.mk
@@ -1,2 +1,2 @@
-COSTIME_VSN = 1.1.10
+COSTIME_VSN = 1.1.11
diff --git a/lib/cosTransactions/doc/src/CosTransactions_RecoveryCoordinator.xml b/lib/cosTransactions/doc/src/CosTransactions_RecoveryCoordinator.xml
index 4b870f4b90..0222f3be86 100644
--- a/lib/cosTransactions/doc/src/CosTransactions_RecoveryCoordinator.xml
+++ b/lib/cosTransactions/doc/src/CosTransactions_RecoveryCoordinator.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1999</year><year>2009</year>
+ <year>1999</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -21,12 +21,11 @@
</legalnotice>
- <title>CosTransactions_&shy;RecoveryCoordinator</title>
- <shorttitle>..._RecoveryCoordinator</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosTransactions_RecoveryCoordinator</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>1999-04-12</date>
<rev>PA1</rev>
diff --git a/lib/cosTransactions/doc/src/CosTransactions_SubtransactionAwareResource.xml b/lib/cosTransactions/doc/src/CosTransactions_SubtransactionAwareResource.xml
index 2c7b6b5215..5878b41360 100644
--- a/lib/cosTransactions/doc/src/CosTransactions_SubtransactionAwareResource.xml
+++ b/lib/cosTransactions/doc/src/CosTransactions_SubtransactionAwareResource.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1999</year><year>2009</year>
+ <year>1999</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -21,8 +21,7 @@
</legalnotice>
- <title>CosTransactions_&shy;SubtransactionAwareResource</title>
- <shorttitle>..._SubtransactionAwareResource</shorttitle>
+ <title>CosTransactions_SubtransactionAwareResource</title>
<prepared></prepared>
<docno></docno>
<checked></checked>
diff --git a/lib/cosTransactions/doc/src/CosTransactions_TransactionFactory.xml b/lib/cosTransactions/doc/src/CosTransactions_TransactionFactory.xml
index 162e6e8cd1..7e93aa2964 100644
--- a/lib/cosTransactions/doc/src/CosTransactions_TransactionFactory.xml
+++ b/lib/cosTransactions/doc/src/CosTransactions_TransactionFactory.xml
@@ -23,12 +23,11 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>CosTransactions_&shy;TransactionFactory</title>
- <shorttitle>..._TransactionFactory</shorttitle>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
+ <title>CosTransactions_TransactionFactory</title>
+ <prepared></prepared>
+ <responsible></responsible>
<docno></docno>
- <approved>Niclas Eklund</approved>
+ <approved></approved>
<checked></checked>
<date>1999-04-12</date>
<rev>PA1</rev>
diff --git a/lib/cosTransactions/doc/src/notes.xml b/lib/cosTransactions/doc/src/notes.xml
index 7586e3c13f..29addf424d 100644
--- a/lib/cosTransactions/doc/src/notes.xml
+++ b/lib/cosTransactions/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1999</year><year>2010</year>
+ <year>1999</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,6 +33,22 @@
</header>
<section>
+ <title>cosTransactions 1.2.11</title>
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>
+ Removed superfluous usage of shy in the documentation since it can cause problem if
+ a buggy tool is used.</p>
+ <p>
+ Own Id: OTP-9319 Aux Id:</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
<title>cosTransactions 1.2.10</title>
<section>
<title>Improvements and New Features</title>
diff --git a/lib/cosTransactions/src/Makefile b/lib/cosTransactions/src/Makefile
index 7e10ec175b..4b77251c3c 100644
--- a/lib/cosTransactions/src/Makefile
+++ b/lib/cosTransactions/src/Makefile
@@ -155,9 +155,14 @@ docs:
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
-$(GEN_ERL_FILES) $(EXTERNAL_GEN_HRL_FILES): CosTransactions.idl
+IDL-GENERATED: CosTransactions.idl
erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosTransactions.cfg"}' CosTransactions.idl
mv $(GEN_HRL_FILES) $(EXTERNAL_INC_PATH)
+ >IDL-GENERATED
+
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Target
diff --git a/lib/cosTransactions/test/Makefile b/lib/cosTransactions/test/Makefile
index 44c90e8f84..0bc8c007da 100644
--- a/lib/cosTransactions/test/Makefile
+++ b/lib/cosTransactions/test/Makefile
@@ -121,13 +121,14 @@ docs:
# Special Targets
# ----------------------------------------------------
-TGT_TEST = \
- $(GEN_HRL_FILES:%=$(IDLOUTDIR)/%) \
- $(GEN_MODULES:%=$(IDLOUTDIR)/%.erl)
-
-$(TGT_TEST): etrap_test.idl
+IDL-GENERATED: etrap_test.idl
erlc $(ERL_IDL_FLAGS) -o$(IDLOUTDIR) \
+'{cfgfile,"etrap_test.cfg"}' etrap_test.idl
+ >IDL-GENERATED
+
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Targets
diff --git a/lib/cosTransactions/vsn.mk b/lib/cosTransactions/vsn.mk
index 82e46f51dd..3960c58c5b 100644
--- a/lib/cosTransactions/vsn.mk
+++ b/lib/cosTransactions/vsn.mk
@@ -1 +1 @@
-COSTRANSACTIONS_VSN = 1.2.10
+COSTRANSACTIONS_VSN = 1.2.11
diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in
index 040adcfd09..285537643e 100644
--- a/lib/crypto/c_src/Makefile.in
+++ b/lib/crypto/c_src/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2010. All Rights Reserved.
+# Copyright Ericsson AB 1999-2011. All Rights Reserved.
#
# The 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,7 +40,8 @@ CFLAGS = $(DED_CFLAGS)
# From erts/configure
SSL_LIBDIR = @SSL_LIBDIR@
SSL_INCLUDE = @SSL_INCLUDE@
-
+SSL_CRYPTO_LIBNAME = @SSL_CRYPTO_LIBNAME@
+SSL_SSL_LIBNAME = @SSL_SSL_LIBNAME@
INCLUDES = $(SSL_INCLUDE) $(DED_INCLUDES)
@@ -84,23 +85,19 @@ DYNAMIC_CRYPTO_LIB=@SSL_DYNAMIC_ONLY@
ifeq ($(DYNAMIC_CRYPTO_LIB),yes)
SSL_DED_LD_RUNTIME_LIBRARY_PATH = @SSL_DED_LD_RUNTIME_LIBRARY_PATH@
-CRYPTO_LINK_LIB=$(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) -lcrypto
+CRYPTO_LINK_LIB=$(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) -l$(SSL_CRYPTO_LIBNAME) -l$(SSL_SSL_LIBNAME)
else
SSL_DED_LD_RUNTIME_LIBRARY_PATH=
-CRYPTO_LINK_LIB=$(SSL_LIBDIR)/libcrypto.a
+CRYPTO_LINK_LIB=$(SSL_LIBDIR)/lib$(SSL_CRYPTO_LIBNAME).a
endif
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt valgrind: $(OBJDIR) $(LIBDIR) $(NIF_LIB)
-
-$(OBJDIR):
- -@mkdir -p $(OBJDIR)
+_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
-$(LIBDIR):
- -@mkdir -p $(LIBDIR)
+debug opt valgrind: $(NIF_LIB)
$(OBJDIR)/%$(TYPEMARKER).o: %.c
$(INSTALL_DIR) $(OBJDIR)
@@ -112,7 +109,7 @@ $(LIBDIR)/crypto$(TYPEMARKER).so: $(OBJS)
$(LIBDIR)/crypto$(TYPEMARKER).dll: $(OBJS)
$(INSTALL_DIR) $(LIBDIR)
- $(LD) $(LDFLAGS) -o $@ $(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) $(OBJS) -llibeay32
+ $(LD) $(LDFLAGS) -o $@ $(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) $(OBJS) -l$(SSL_CRYPTO_LIBNAME) -l$(SSL_SSL_LIBNAME)
clean:
ifeq ($(findstring win32,$(TARGET)), win32)
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index b8786f6f94..10fe333d18 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -50,6 +50,8 @@
#include <openssl/rc2.h>
#include <openssl/blowfish.h>
#include <openssl/rand.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
#ifdef VALGRIND
# include <valgrind/memcheck.h>
@@ -128,13 +130,21 @@ static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM des_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM des_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM des_ede3_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM strong_rand_mpint_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -197,14 +207,24 @@ static ErlNifFunc nif_funcs[] = {
{"md4_final", 1, md4_final},
{"md5_mac_n", 3, md5_mac_n},
{"sha_mac_n", 3, sha_mac_n},
+ {"hmac_init", 2, hmac_init},
+ {"hmac_update", 2, hmac_update},
+ {"hmac_final", 1, hmac_final},
+ {"hmac_final_n", 2, hmac_final},
{"des_cbc_crypt", 4, des_cbc_crypt},
+ {"des_cfb_crypt", 4, des_cfb_crypt},
{"des_ecb_crypt", 3, des_ecb_crypt},
{"des_ede3_cbc_crypt", 6, des_ede3_cbc_crypt},
+ {"des_ede3_cfb_crypt", 6, des_ede3_cfb_crypt},
{"aes_cfb_128_crypt", 4, aes_cfb_128_crypt},
{"aes_ctr_encrypt", 3, aes_ctr_encrypt},
{"aes_ctr_decrypt", 3, aes_ctr_encrypt},
+ {"aes_ctr_stream_encrypt", 2, aes_ctr_stream_encrypt},
+ {"aes_ctr_stream_decrypt", 2, aes_ctr_stream_encrypt},
{"rand_bytes", 1, rand_bytes_1},
+ {"strong_rand_bytes_nif", 1, strong_rand_bytes_nif},
{"rand_bytes", 3, rand_bytes_3},
+ {"strong_rand_mpint_nif", 3, strong_rand_mpint_nif},
{"rand_uniform_nif", 2, rand_uniform_nif},
{"mod_exp_nif", 3, mod_exp_nif},
{"dss_verify", 4, dss_verify},
@@ -251,6 +271,7 @@ static ERL_NIF_TERM atom_true;
static ERL_NIF_TERM atom_false;
static ERL_NIF_TERM atom_sha;
static ERL_NIF_TERM atom_md5;
+static ERL_NIF_TERM atom_ripemd160;
static ERL_NIF_TERM atom_error;
static ERL_NIF_TERM atom_rsa_pkcs1_padding;
static ERL_NIF_TERM atom_rsa_pkcs1_oaep_padding;
@@ -320,6 +341,7 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
atom_false = enif_make_atom(env,"false");
atom_sha = enif_make_atom(env,"sha");
atom_md5 = enif_make_atom(env,"md5");
+ atom_ripemd160 = enif_make_atom(env,"ripemd160");
atom_error = enif_make_atom(env,"error");
atom_rsa_pkcs1_padding = enif_make_atom(env,"rsa_pkcs1_padding");
atom_rsa_pkcs1_oaep_padding = enif_make_atom(env,"rsa_pkcs1_oaep_padding");
@@ -577,6 +599,84 @@ static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
return ret;
}
+static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type, Key) */
+ ErlNifBinary key;
+ ERL_NIF_TERM ret;
+ unsigned char * ctx_buf;
+ const EVP_MD *md;
+
+ if (argv[0] == atom_sha) md = EVP_sha1();
+ else if (argv[0] == atom_md5) md = EVP_md5();
+ else if (argv[0] == atom_ripemd160) md = EVP_ripemd160();
+ else goto badarg;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[1], &key)) {
+ badarg:
+ return enif_make_badarg(env);
+ }
+
+ ctx_buf = enif_make_new_binary(env, sizeof(HMAC_CTX), &ret);
+ HMAC_CTX_init((HMAC_CTX *) ctx_buf);
+ HMAC_Init((HMAC_CTX *) ctx_buf, key.data, key.size, md);
+
+ return ret;
+}
+
+static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Context, Data) */
+ ErlNifBinary context, data;
+ ERL_NIF_TERM ret;
+ unsigned char * ctx_buf;
+
+ if (!enif_inspect_binary(env, argv[0], &context)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data)
+ || context.size != sizeof(HMAC_CTX)) {
+ return enif_make_badarg(env);
+ }
+
+ ctx_buf = enif_make_new_binary(env, sizeof(HMAC_CTX), &ret);
+ memcpy(ctx_buf, context.data, context.size);
+ HMAC_Update((HMAC_CTX *)ctx_buf, data.data, data.size);
+
+ return ret;
+}
+
+static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Context) or (Context, HashLen) */
+ ErlNifBinary context;
+ ERL_NIF_TERM ret;
+ HMAC_CTX ctx;
+ unsigned char mac_buf[EVP_MAX_MD_SIZE];
+ unsigned char * mac_bin;
+ unsigned int req_len = 0;
+ unsigned int mac_len;
+
+ if (!enif_inspect_binary(env, argv[0], &context)) {
+ return enif_make_badarg(env);
+ }
+ if (argc == 2 && !enif_get_uint(env, argv[1], &req_len)) {
+ return enif_make_badarg(env);
+ }
+
+ if (context.size != sizeof(ctx)) {
+ return enif_make_badarg(env);
+ }
+ memcpy(&ctx, context.data, context.size);
+
+ HMAC_Final(&ctx, mac_buf, &mac_len);
+ HMAC_CTX_cleanup(&ctx);
+
+ if (argc == 2 && req_len < mac_len) {
+ // Only truncate to req_len bytes if asked.
+ mac_len = req_len;
+ }
+ mac_bin = enif_make_new_binary(env, mac_len, &ret);
+ memcpy(mac_bin, mac_buf, mac_len);
+
+ return ret;
+}
+
static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key, Ivec, Text, IsEncrypt) */
ErlNifBinary key, ivec, text;
@@ -597,6 +697,25 @@ static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
return ret;
}
+static ERL_NIF_TERM des_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, Ivec, Text, IsEncrypt) */
+ ErlNifBinary key, ivec, text;
+ DES_key_schedule schedule;
+ DES_cblock ivec_clone; /* writable copy */
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8
+ || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 8
+ || !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
+ return enif_make_badarg(env);
+ }
+ memcpy(&ivec_clone, ivec.data, 8);
+ DES_set_key((const_DES_cblock*)key.data, &schedule);
+ DES_cfb_encrypt(text.data, enif_make_new_binary(env, text.size, &ret),
+ 8, text.size, &schedule, &ivec_clone, (argv[3] == atom_true));
+ return ret;
+}
+
static ERL_NIF_TERM des_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key, Text/Cipher, IsEncrypt) */
ErlNifBinary key, text;
@@ -639,6 +758,31 @@ static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_T
return ret;
}
+static ERL_NIF_TERM des_ede3_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key1, Key2, Key3, IVec, Text/Cipher, IsEncrypt) */
+ ErlNifBinary key1, key2, key3, ivec, text;
+ DES_key_schedule schedule1, schedule2, schedule3;
+ DES_cblock ivec_clone; /* writable copy */
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key1) || key1.size != 8
+ || !enif_inspect_iolist_as_binary(env, argv[1], &key2) || key2.size != 8
+ || !enif_inspect_iolist_as_binary(env, argv[2], &key3) || key3.size != 8
+ || !enif_inspect_binary(env, argv[3], &ivec) || ivec.size != 8
+ || !enif_inspect_iolist_as_binary(env, argv[4], &text)) {
+ return enif_make_badarg(env);
+ }
+
+ memcpy(&ivec_clone, ivec.data, 8);
+ DES_set_key((const_DES_cblock*)key1.data, &schedule1);
+ DES_set_key((const_DES_cblock*)key2.data, &schedule2);
+ DES_set_key((const_DES_cblock*)key3.data, &schedule3);
+ DES_ede3_cfb_encrypt(text.data, enif_make_new_binary(env,text.size,&ret),
+ 8, text.size, &schedule1, &schedule2, &schedule3,
+ &ivec_clone, (argv[5] == atom_true));
+ return ret;
+}
+
static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key, IVec, Data, IsEncrypt) */
ErlNifBinary key, ivec, text;
@@ -691,6 +835,46 @@ static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
return ret;
}
+/* Initializes state for ctr streaming (de)encryption
+*/
+static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* ({Key, IVec, ECount, Num}, Data) */
+ ErlNifBinary key_bin, ivec_bin, text_bin, ecount_bin;
+ AES_KEY aes_key;
+ unsigned int num;
+ ERL_NIF_TERM ret, num2_term, cipher_term, ivec2_term, ecount2_term, new_state_term;
+ int state_arity;
+ const ERL_NIF_TERM *state_term;
+ unsigned char * ivec2_buf;
+ unsigned char * ecount2_buf;
+
+ if (!enif_get_tuple(env, argv[0], &state_arity, &state_term)
+ || state_arity != 4
+ || !enif_inspect_iolist_as_binary(env, state_term[0], &key_bin)
+ || AES_set_encrypt_key(key_bin.data, key_bin.size*8, &aes_key) != 0
+ || !enif_inspect_binary(env, state_term[1], &ivec_bin) || ivec_bin.size != 16
+ || !enif_inspect_binary(env, state_term[2], &ecount_bin) || ecount_bin.size != AES_BLOCK_SIZE
+ || !enif_get_uint(env, state_term[3], &num)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &text_bin)) {
+ return enif_make_badarg(env);
+ }
+
+ ivec2_buf = enif_make_new_binary(env, ivec_bin.size, &ivec2_term);
+ ecount2_buf = enif_make_new_binary(env, ecount_bin.size, &ecount2_term);
+
+ memcpy(ivec2_buf, ivec_bin.data, 16);
+ memcpy(ecount2_buf, ecount_bin.data, ecount_bin.size);
+
+ AES_ctr128_encrypt((unsigned char *) text_bin.data,
+ enif_make_new_binary(env, text_bin.size, &cipher_term),
+ text_bin.size, &aes_key, ivec2_buf, ecount2_buf, &num);
+
+ num2_term = enif_make_uint(env, num);
+ new_state_term = enif_make_tuple4(env, state_term[0], ivec2_term, ecount2_term, num2_term);
+ ret = enif_make_tuple2(env, new_state_term, cipher_term);
+ return ret;
+}
+
static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Bytes) */
unsigned bytes;
@@ -704,6 +888,22 @@ static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
ERL_VALGRIND_MAKE_MEM_DEFINED(data, bytes);
return ret;
}
+static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Bytes) */
+ unsigned bytes;
+ unsigned char* data;
+ ERL_NIF_TERM ret;
+ if (!enif_get_uint(env, argv[0], &bytes)) {
+ return enif_make_badarg(env);
+ }
+ data = enif_make_new_binary(env, bytes, &ret);
+ if ( RAND_bytes(data, bytes) != 1) {
+ return atom_false;
+ }
+ ERL_VALGRIND_MAKE_MEM_DEFINED(data, bytes);
+ return ret;
+}
+
static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Bytes, TopMask, BottomMask) */
unsigned bytes;
@@ -724,6 +924,47 @@ static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
}
return ret;
}
+static ERL_NIF_TERM strong_rand_mpint_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Bytes, TopMask, BottomMask) */
+ unsigned bits;
+ BIGNUM *bn_rand;
+ int top, bottom;
+ unsigned char* data;
+ unsigned dlen;
+ ERL_NIF_TERM ret;
+ if (!enif_get_uint(env, argv[0], &bits)
+ || !enif_get_int(env, argv[1], &top)
+ || !enif_get_int(env, argv[2], &bottom)) {
+ return enif_make_badarg(env);
+ }
+ if (! (top == -1 || top == 0 || top == 1) ) {
+ return enif_make_badarg(env);
+ }
+ if (! (bottom == 0 || bottom == 1) ) {
+ return enif_make_badarg(env);
+ }
+
+ bn_rand = BN_new();
+ if (! bn_rand ) {
+ return enif_make_badarg(env);
+ }
+
+ /* Get a (bits) bit random number */
+ if (!BN_rand(bn_rand, bits, top, bottom)) {
+ ret = atom_false;
+ }
+ else {
+ /* Copy the bignum into an erlang mpint binary. */
+ dlen = BN_num_bytes(bn_rand);
+ data = enif_make_new_binary(env, dlen+4, &ret);
+ put_int32(data, dlen);
+ BN_bn2bin(bn_rand, data+4);
+ ERL_VALGRIND_MAKE_MEM_DEFINED(data+4, dlen);
+ }
+ BN_free(bn_rand);
+
+ return ret;
+}
static int get_bn_from_mpint(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp)
{
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index c407350c47..824be09438 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1999</year><year>2010</year>
+ <year>1999</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -282,6 +282,57 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</desc>
</func>
<func>
+ <name>hmac_init(Type, Key) -> Context</name>
+ <fsummary></fsummary>
+ <type>
+ <v>Type = sha | md5 | ripemd160</v>
+ <v>Key = iolist() | binary()</v>
+ <v>Context = binary()</v>
+ </type>
+ <desc>
+ <p>Initializes the context for streaming HMAC operations. <c>Type</c> determines
+ which hash function to use in the HMAC operation. <c>Key</c> is the authentication
+ key. The key can be any length.</p>
+ </desc>
+ </func>
+ <func>
+ <name>hmac_update(Context, Data) -> NewContext</name>
+ <fsummary></fsummary>
+ <type>
+ <v>Context = NewContext = binary()</v>
+ <v>Data = iolist() | binary()</v>
+ </type>
+ <desc>
+ <p>Updates the HMAC represented by <c>Context</c> using the given <c>Data</c>. <c>Context</c>
+ must have been generated using an HMAC init function (such as
+ <seealso marker="#hmac_init/2">hmac_init</seealso>). <c>Data</c> can be any length. <c>NewContext</c>
+ must be passed into the next call to <c>hmac_update</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>hmac_final(Context) -> Mac</name>
+ <fsummary></fsummary>
+ <type>
+ <v>Context = Mac = binary()</v>
+ </type>
+ <desc>
+ <p>Finalizes the HMAC operation referenced by <c>Context</c>. The size of the resultant MAC is
+ determined by the type of hash function used to generate it.</p>
+ </desc>
+ </func>
+ <func>
+ <name>hmac_final_n(Context, HashLen) -> Mac</name>
+ <fsummary></fsummary>
+ <type>
+ <v>Context = Mac = binary()</v>
+ <v>HashLen = non_neg_integer()</v>
+ </type>
+ <desc>
+ <p>Finalizes the HMAC operation referenced by <c>Context</c>. <c>HashLen</c> must be greater than
+ zero. <c>Mac</c> will be a binary with at most <c>HashLen</c> bytes. Note that if HashLen is greater than the actual number of bytes returned from the underlying hash, the returned hash will have fewer than <c>HashLen</c> bytes.</p>
+ </desc>
+ </func>
+ <func>
<name>sha_mac(Key, Data) -> Mac</name>
<fsummary>Compute an <c>MD5 MAC</c>message authentification code</fsummary>
<type>
@@ -296,7 +347,7 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</func>
<func>
<name>sha_mac_96(Key, Data) -> Mac</name>
- <fsummary>Compute an <c>MD5 MAC</c>message authentification code</fsummary>
+ <fsummary>Compute an <c>SHA MAC</c>message authentification code</fsummary>
<type>
<v>Key = Data = iolist() | binary()</v>
<v>Mac = binary()</v>
@@ -353,6 +404,51 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</desc>
</func>
<func>
+ <name>des_cfb_encrypt(Key, IVec, Text) -> Cipher</name>
+ <fsummary>Encrypt <c>Text</c>according to DES in CFB mode</fsummary>
+ <type>
+ <v>Key = Text = iolist() | binary()</v>
+ <v>IVec = Cipher = binary()</v>
+ </type>
+ <desc>
+ <p>Encrypts <c>Text</c> according to DES in 8-bit CFB
+ mode. <c>Key</c> is the DES key, and <c>IVec</c> is an
+ arbitrary initializing vector. The lengths of <c>Key</c> and
+ <c>IVec</c> must be 64 bits (8 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>des_cfb_decrypt(Key, IVec, Cipher) -> Text</name>
+ <fsummary>Decrypt <c>Cipher</c>according to DES in CFB mode</fsummary>
+ <type>
+ <v>Key = Cipher = iolist() | binary()</v>
+ <v>IVec = Text = binary()</v>
+ </type>
+ <desc>
+ <p>Decrypts <c>Cipher</c> according to DES in 8-bit CFB mode.
+ <c>Key</c> is the DES key, and <c>IVec</c> is an arbitrary
+ initializing vector. <c>Key</c> and <c>IVec</c> must have
+ the same values as those used when encrypting. The lengths of
+ <c>Key</c> and <c>IVec</c> must be 64 bits (8 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>des_cfb_ivec(IVec, Data) -> NextIVec</name>
+ <fsummary>Get <c>IVec</c> to be used in next iteration of
+ <c>des_cfb_[ecrypt|decrypt]</c></fsummary>
+ <type>
+ <v>IVec = iolist() | binary()</v>
+ <v>Data = iolist() | binary()</v>
+ <v>NextIVec = binary()</v>
+ </type>
+ <desc>
+ <p>Returns the <c>IVec</c> to be used in a next iteration of
+ <c>des_cfb_[encrypt|decrypt]</c>. <c>IVec</c> is the vector
+ used in the previous iteration step. <c>Data</c> is the encrypted
+ data from the previous iteration step.</p>
+ </desc>
+ </func>
+ <func>
<name>des3_cbc_encrypt(Key1, Key2, Key3, IVec, Text) -> Cipher</name>
<fsummary>Encrypt <c>Text</c>according to DES3 in CBC mode</fsummary>
<type>
@@ -370,7 +466,7 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</func>
<func>
<name>des3_cbc_decrypt(Key1, Key2, Key3, IVec, Cipher) -> Text</name>
- <fsummary>Decrypt <c>Cipher</c>according to DES in CBC mode</fsummary>
+ <fsummary>Decrypt <c>Cipher</c>according to DES3 in CBC mode</fsummary>
<type>
<v>Key1 = Key2 = Key3 = Cipher = iolist() | binary()</v>
<v>IVec = Text = binary()</v>
@@ -386,6 +482,38 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
<c>Key3</c>, and <c>IVec</c> must be 64 bits (8 bytes).</p>
</desc>
</func>
+ <func>
+ <name>des3_cfb_encrypt(Key1, Key2, Key3, IVec, Text) -> Cipher</name>
+ <fsummary>Encrypt <c>Text</c>according to DES3 in CFB mode</fsummary>
+ <type>
+ <v>Key1 =Key2 = Key3 Text = iolist() | binary()</v>
+ <v>IVec = Cipher = binary()</v>
+ </type>
+ <desc>
+ <p>Encrypts <c>Text</c> according to DES3 in 8-bit CFB
+ mode. <c>Key1</c>, <c>Key2</c>, <c>Key3</c>, are the DES
+ keys, and <c>IVec</c> is an arbitrary initializing
+ vector. The lengths of each of <c>Key1</c>, <c>Key2</c>,
+ <c>Key3</c> and <c>IVec</c> must be 64 bits (8 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>des3_cfb_decrypt(Key1, Key2, Key3, IVec, Cipher) -> Text</name>
+ <fsummary>Decrypt <c>Cipher</c>according to DES3 in CFB mode</fsummary>
+ <type>
+ <v>Key1 = Key2 = Key3 = Cipher = iolist() | binary()</v>
+ <v>IVec = Text = binary()</v>
+ </type>
+ <desc>
+ <p>Decrypts <c>Cipher</c> according to DES3 in 8-bit CFB mode.
+ <c>Key1</c>, <c>Key2</c>, <c>Key3</c> are the DES key, and
+ <c>IVec</c> is an arbitrary initializing vector.
+ <c>Key1</c>, <c>Key2</c>, <c>Key3</c> and <c>IVec</c> must
+ and <c>IVec</c> must have the same values as those used when
+ encrypting. The lengths of <c>Key1</c>, <c>Key2</c>,
+ <c>Key3</c>, and <c>IVec</c> must be 64 bits (8 bytes).</p>
+ </desc>
+ </func>
<func>
<name>des_ecb_encrypt(Key, Text) -> Cipher</name>
@@ -419,16 +547,18 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
<fsummary>Encrypt the first 64 bits of <c>Text</c> using Blowfish in ECB mode</fsummary>
<type>
<v>Key = Text = iolist() | binary()</v>
- <v>IVec = Cipher = binary()</v>
+ <v>Cipher = binary()</v>
</type>
<desc>
<p>Encrypts the first 64 bits of <c>Text</c> using Blowfish in ECB mode. <c>Key</c> is the Blowfish key. The length of <c>Text</c> must be at least 64 bits (8 bytes).</p>
</desc>
+ </func>
+ <func>
<name>blowfish_ecb_decrypt(Key, Text) -> Cipher</name>
<fsummary>Decrypt the first 64 bits of <c>Text</c> using Blowfish in ECB mode</fsummary>
<type>
<v>Key = Text = iolist() | binary()</v>
- <v>IVec = Cipher = binary()</v>
+ <v>Cipher = binary()</v>
</type>
<desc>
<p>Decrypts the first 64 bits of <c>Text</c> using Blowfish in ECB mode. <c>Key</c> is the Blowfish key. The length of <c>Text</c> must be at least 64 bits (8 bytes).</p>
@@ -436,7 +566,7 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</func>
<func>
- <name>blowfish_cbc_encrypt(Key, Text) -> Cipher</name>
+ <name>blowfish_cbc_encrypt(Key, IVec, Text) -> Cipher</name>
<fsummary>Encrypt <c>Text</c> using Blowfish in CBC mode</fsummary>
<type>
<v>Key = Text = iolist() | binary()</v>
@@ -447,7 +577,9 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
arbitrary initializing vector. The length of <c>IVec</c>
must be 64 bits (8 bytes). The length of <c>Text</c> must be a multiple of 64 bits (8 bytes).</p>
</desc>
- <name>blowfish_cbc_decrypt(Key, Text) -> Cipher</name>
+ </func>
+ <func>
+ <name>blowfish_cbc_decrypt(Key, IVec, Text) -> Cipher</name>
<fsummary>Decrypt <c>Text</c> using Blowfish in CBC mode</fsummary>
<type>
<v>Key = Text = iolist() | binary()</v>
@@ -585,6 +717,55 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</desc>
</func>
<func>
+ <name>aes_ctr_stream_init(Key, IVec) -> State</name>
+ <fsummary></fsummary>
+ <type>
+ <v>State = { K, I, E, C }</v>
+ <v>Key = K = iolist()</v>
+ <v>IVec = I = E = binary()</v>
+ <v>C = integer()</v>
+ </type>
+ <desc>
+ <p>Initializes the state for use in streaming AES encryption using Counter mode (CTR).
+ <c>Key</c> is the AES key and must be either 128, 192, or 256 bts long. <c>IVec</c> is
+ an arbitrary initializing vector of 128 bits (16 bytes). This state is for use with
+ <seealso marker="#aes_ctr_stream_encrypt/2">aes_ctr_stream_encrypt</seealso> and
+ <seealso marker="#aes_ctr_stream_decrypt/2">aes_ctr_stream_decrypt</seealso>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>aes_ctr_stream_encrypt(State, Text) -> { NewState, Cipher}</name>
+ <fsummary></fsummary>
+ <type>
+ <v>Text = iolist() | binary()</v>
+ <v>Cipher = binary()</v>
+ </type>
+ <desc>
+ <p>Encrypts <c>Text</c> according to AES in Counter mode (CTR). This function can be
+ used to encrypt a stream of text using a series of calls instead of requiring all
+ text to be in memory. <c>Text</c> can be any number of bytes. State is initialized using
+ <seealso marker="#aes_ctr_stream_init/2">aes_ctr_stream_init</seealso>. <c>NewState</c> is the new streaming
+ encryption state that must be passed to the next call to <c>aes_ctr_stream_encrypt</c>.
+ <c>Cipher</c> is the encrypted cipher text.</p>
+ </desc>
+ </func>
+ <func>
+ <name>aes_ctr_stream_decrypt(State, Cipher) -> { NewState, Text }</name>
+ <fsummary></fsummary>
+ <type>
+ <v>Cipher = iolist() | binary()</v>
+ <v>Text = binary()</v>
+ </type>
+ <desc>
+ <p>Decrypts <c>Cipher</c> according to AES in Counter mode (CTR). This function can be
+ used to decrypt a stream of ciphertext using a series of calls instead of requiring all
+ ciphertext to be in memory. <c>Cipher</c> can be any number of bytes. State is initialized using
+ <seealso marker="#aes_ctr_stream_init/2">aes_ctr_stream_init</seealso>. <c>NewState</c> is the new streaming
+ encryption state that must be passed to the next call to <c>aes_ctr_stream_encrypt</c>.
+ <c>Text</c> is the decrypted data.</p>
+ </desc>
+ </func>
+ <func>
<name>erlint(Mpint) -> N</name>
<name>mpint(N) -> Mpint</name>
<fsummary>Convert between binary multi-precision integer and erlang big integer</fsummary>
@@ -615,6 +796,21 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</desc>
</func>
<func>
+ <name>strong_rand_bytes(N) -> binary()</name>
+ <fsummary>Generate a binary of random bytes</fsummary>
+ <type>
+ <v>N = integer()</v>
+ </type>
+ <desc>
+ <p>Generates N bytes randomly uniform 0..255, and returns the
+ result in a binary. Uses a cryptographically secure prng seeded and
+ periodically mixed with operating system provided entropy. By default
+ this is the <c>RAND_bytes</c> method from OpenSSL.</p>
+ <p>May throw exception <c>low_entropy</c> in case the random generator
+ failed due to lack of secure "randomness".</p>
+ </desc>
+ </func>
+ <func>
<name>rand_uniform(Lo, Hi) -> N</name>
<fsummary>Generate a random number</fsummary>
<type>
@@ -625,7 +821,32 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
<p>Generate a random number <c><![CDATA[N, Lo =< N < Hi.]]></c> Uses the
<c>crypto</c> library pseudo-random number generator. The
arguments (and result) can be either erlang integers or binary
- multi-precision integers.</p>
+ multi-precision integers. <c>Hi</c> must be larger than <c>Lo</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>strong_rand_mpint(N, Top, Bottom) -> Mpint</name>
+ <fsummary>Generate an N bit random number</fsummary>
+ <type>
+ <v>N = non_neg_integer()</v>
+ <v>Top = -1 | 0 | 1</v>
+ <v>Bottom = 0 | 1</v>
+ <v>Mpint = binary()</v>
+ </type>
+ <desc>
+ <p>Generate an N bit random number using OpenSSL's
+ cryptographically strong pseudo random number generator
+ <c>BN_rand</c>.</p>
+ <p>The parameter <c>Top</c> places constraints on the most
+ significant bits of the generated number. If <c>Top</c> is 1, then the
+ two most significant bits will be set to 1, if <c>Top</c> is 0, the
+ most significant bit will be 1, and if <c>Top</c> is -1 then no
+ constraints are applied and thus the generated number may be less than
+ N bits long.</p>
+ <p>If <c>Bottom</c> is 1, then the generated number is
+ constrained to be odd.</p>
+ <p>May throw exception <c>low_entropy</c> in case the random generator
+ failed due to lack of secure "randomness".</p>
</desc>
</func>
<func>
diff --git a/lib/crypto/doc/src/licenses.xml b/lib/crypto/doc/src/licenses.xml
index bae87a373e..0b791acfa2 100644
--- a/lib/crypto/doc/src/licenses.xml
+++ b/lib/crypto/doc/src/licenses.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2009</year>
+ <year>2003</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -37,7 +37,7 @@ This chapter contains in extenso versions
<title>OpenSSL License</title>
<code type="none">
/* ====================================================================
- * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml
index 5e9bda3920..763f79e02d 100644
--- a/lib/crypto/doc/src/notes.xml
+++ b/lib/crypto/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1999</year><year>2010</year>
+ <year>1999</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,6 +30,85 @@
</header>
<p>This document describes the changes made to the Crypto application.</p>
+<section><title>Crypto 2.0.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ <c>crypto:rand_uniform</c> works correctly for negative
+ integers. Fails with <c>badarg</c> exception for invalid
+ ranges (when <c>Hi =&lt; Lo</c>) instead of returning
+ incorrect output.</p>
+ <p>
+ Own Id: OTP-9526</p>
+ </item>
+ <item>
+ <p>
+ Fix win32 OpenSSL static linking (Thanks to Dave
+ Cottlehuber)</p>
+ <p>
+ Own Id: OTP-9532</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 2.0.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Various small documentation fixes (Thanks to Bernard
+ Duggan)</p>
+ <p>
+ Own Id: OTP-9172</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ New <c>crypto</c> support for streaming of AES CTR and
+ HMAC. (Thanks to Travis Jensen)</p>
+ <p>
+ Own Id: OTP-9275</p>
+ </item>
+ <item>
+ <p>
+ Due to standard library DLL mismatches between versions
+ of OpenSSL and Erlang/OTP, OpenSSL is now linked
+ statically to the crypto driver on Windows. This fixes
+ problems starting crypto when running Erlang as a service
+ on all Windows versions.</p>
+ <p>
+ Own Id: OTP-9280</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 2.0.2.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Strengthened random number generation. (Thanks to Geoff Cant)</p>
+ <p>
+ Own Id: OTP-9225</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Crypto 2.0.2.1</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index d6e2e033c0..e3b921f9fa 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
%%
%% The 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,9 +28,12 @@
%-export([sha256/1, sha256_init/0, sha256_update/2, sha256_final/1]).
%-export([sha512/1, sha512_init/0, sha512_update/2, sha512_final/1]).
-export([md5_mac/2, md5_mac_96/2, sha_mac/2, sha_mac_96/2]).
+-export([hmac_init/2, hmac_update/2, hmac_final/1, hmac_final_n/2]).
-export([des_cbc_encrypt/3, des_cbc_decrypt/3, des_cbc_ivec/1]).
-export([des_ecb_encrypt/2, des_ecb_decrypt/2]).
+-export([des_cfb_encrypt/3, des_cfb_decrypt/3, des_cfb_ivec/2]).
-export([des3_cbc_encrypt/5, des3_cbc_decrypt/5]).
+-export([des3_cfb_encrypt/5, des3_cfb_decrypt/5]).
-export([blowfish_ecb_encrypt/2, blowfish_ecb_decrypt/2]).
-export([blowfish_cbc_encrypt/3, blowfish_cbc_decrypt/3]).
-export([blowfish_cfb64_encrypt/3, blowfish_cfb64_decrypt/3]).
@@ -46,12 +49,14 @@
-export([rsa_private_encrypt/3, rsa_public_decrypt/3]).
-export([dh_generate_key/1, dh_generate_key/2, dh_compute_key/3]).
-export([rand_bytes/1, rand_bytes/3, rand_uniform/2]).
+-export([strong_rand_bytes/1, strong_rand_mpint/3]).
-export([mod_exp/3, mpint/1, erlint/1]).
%% -export([idea_cbc_encrypt/3, idea_cbc_decrypt/3]).
-export([aes_cbc_128_encrypt/3, aes_cbc_128_decrypt/3]).
-export([aes_cbc_256_encrypt/3, aes_cbc_256_decrypt/3]).
-export([aes_cbc_ivec/1]).
-export([aes_ctr_encrypt/3, aes_ctr_decrypt/3]).
+-export([aes_ctr_stream_init/2, aes_ctr_stream_encrypt/2, aes_ctr_stream_decrypt/2]).
-export([dh_generate_parameters/2, dh_check/1]). %% Testing see below
@@ -63,11 +68,16 @@
%% sha512, sha512_init, sha512_update, sha512_final,
md5_mac, md5_mac_96,
sha_mac, sha_mac_96,
+ sha_mac_init, sha_mac_update, sha_mac_final,
des_cbc_encrypt, des_cbc_decrypt,
+ des_cfb_encrypt, des_cfb_decrypt,
des_ecb_encrypt, des_ecb_decrypt,
des_ede3_cbc_encrypt, des_ede3_cbc_decrypt,
+ des_ede3_cfb_encrypt, des_ede3_cfb_decrypt,
aes_cfb_128_encrypt, aes_cfb_128_decrypt,
rand_bytes,
+ strong_rand_bytes,
+ strong_rand_mpint,
rand_uniform,
mod_exp,
dss_verify,dss_sign,
@@ -82,6 +92,7 @@
%% idea_cbc_encrypt, idea_cbc_decrypt,
aes_cbc_256_encrypt, aes_cbc_256_decrypt,
aes_ctr_encrypt, aes_ctr_decrypt,
+ aes_ctr_stream_init, aes_ctr_stream_encrypt, aes_ctr_stream_decrypt,
info_lib]).
-type rsa_digest_type() :: 'md5' | 'sha'.
@@ -214,6 +225,19 @@ sha_final(_Context) -> ?nif_stub.
%%
%%
+%% HMAC (multiple hash options)
+%%
+-spec hmac_init(atom(), iodata()) -> binary().
+-spec hmac_update(binary(), iodata()) -> binary().
+-spec hmac_final(binary()) -> binary().
+-spec hmac_final_n(binary(), integer()) -> binary().
+
+hmac_init(_Type, _Key) -> ?nif_stub.
+hmac_update(_Context, _Data) -> ? nif_stub.
+hmac_final(_Context) -> ? nif_stub.
+hmac_final_n(_Context, _HashLen) -> ? nif_stub.
+
+%%
%% MD5_MAC
%%
-spec md5_mac(iodata(), iodata()) -> binary().
@@ -240,7 +264,7 @@ sha_mac_96(Key, Data) ->
sha_mac_n(Key,Data,12).
sha_mac_n(_Key,_Data,_MacSz) -> ?nif_stub.
-
+
%%
%% CRYPTO FUNCTIONS
%%
@@ -274,6 +298,33 @@ des_cbc_ivec(Data) when is_list(Data) ->
des_cbc_ivec(list_to_binary(Data)).
%%
+%% DES - in 8-bits cipher feedback mode (CFB)
+%%
+-spec des_cfb_encrypt(iodata(), binary(), iodata()) -> binary().
+-spec des_cfb_decrypt(iodata(), binary(), iodata()) -> binary().
+
+des_cfb_encrypt(Key, IVec, Data) ->
+ des_cfb_crypt(Key, IVec, Data, true).
+
+des_cfb_decrypt(Key, IVec, Data) ->
+ des_cfb_crypt(Key, IVec, Data, false).
+
+des_cfb_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+
+%%
+%% dec_cfb_ivec(IVec, Data) -> binary()
+%%
+%% Returns the IVec to be used in the next iteration of
+%% des_cfb_[encrypt|decrypt].
+%%
+-spec des_cfb_ivec(iodata(), iodata()) -> binary().
+
+des_cfb_ivec(IVec, Data) ->
+ IVecAndData = list_to_binary([IVec, Data]),
+ {_, NewIVec} = split_binary(IVecAndData, byte_size(IVecAndData) - 8),
+ NewIVec.
+
+%%
%% DES - in electronic codebook mode (ECB)
%%
-spec des_ecb_encrypt(iodata(), iodata()) -> binary().
@@ -306,6 +357,26 @@ des_ede3_cbc_decrypt(Key1, Key2, Key3, IVec, Data) ->
des_ede3_cbc_crypt(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
%%
+%% DES3 - in 8-bits cipher feedback mode (CFB)
+%%
+-spec des3_cfb_encrypt(iodata(), iodata(), iodata(), binary(), iodata()) ->
+ binary().
+-spec des3_cfb_decrypt(iodata(), iodata(), iodata(), binary(), iodata()) ->
+ binary().
+
+des3_cfb_encrypt(Key1, Key2, Key3, IVec, Data) ->
+ des_ede3_cfb_encrypt(Key1, Key2, Key3, IVec, Data).
+des_ede3_cfb_encrypt(Key1, Key2, Key3, IVec, Data) ->
+ des_ede3_cfb_crypt(Key1, Key2, Key3, IVec, Data, true).
+
+des3_cfb_decrypt(Key1, Key2, Key3, IVec, Data) ->
+ des_ede3_cfb_decrypt(Key1, Key2, Key3, IVec, Data).
+des_ede3_cfb_decrypt(Key1, Key2, Key3, IVec, Data) ->
+ des_ede3_cfb_crypt(Key1, Key2, Key3, IVec, Data, false).
+
+des_ede3_cfb_crypt(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+
+%%
%% Blowfish
%%
-spec blowfish_ecb_encrypt(iodata(), iodata()) -> binary().
@@ -361,12 +432,32 @@ aes_cfb_128_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
%% RAND - pseudo random numbers using RN_ functions in crypto lib
%%
-spec rand_bytes(non_neg_integer()) -> binary().
+-spec strong_rand_bytes(non_neg_integer()) -> binary().
-spec rand_uniform(crypto_integer(), crypto_integer()) ->
crypto_integer().
+-spec strong_rand_mpint(Bits::non_neg_integer(),
+ Top::-1..1,
+ Bottom::0..1) -> binary().
rand_bytes(_Bytes) -> ?nif_stub.
+
+strong_rand_bytes(Bytes) ->
+ case strong_rand_bytes_nif(Bytes) of
+ false -> erlang:error(low_entropy);
+ Bin -> Bin
+ end.
+strong_rand_bytes_nif(_Bytes) -> ?nif_stub.
+
rand_bytes(_Bytes, _Topmask, _Bottommask) -> ?nif_stub.
+strong_rand_mpint(Bits, Top, Bottom) ->
+ case strong_rand_mpint_nif(Bits,Top,Bottom) of
+ false -> erlang:error(low_entropy);
+ Bin -> Bin
+ end.
+strong_rand_mpint_nif(_Bits, _Top, _Bottom) -> ?nif_stub.
+
+
rand_uniform(From,To) when is_binary(From), is_binary(To) ->
case rand_uniform_nif(From,To) of
<<Len:32/integer, MSB, Rest/binary>> when MSB > 127 ->
@@ -375,6 +466,13 @@ rand_uniform(From,To) when is_binary(From), is_binary(To) ->
Whatever
end;
rand_uniform(From,To) when is_integer(From),is_integer(To) ->
+ if From < 0 ->
+ rand_uniform_pos(0, To - From) + From;
+ true ->
+ rand_uniform_pos(From, To)
+ end.
+
+rand_uniform_pos(From,To) when From < To ->
BinFrom = mpint(From),
BinTo = mpint(To),
case rand_uniform(BinFrom, BinTo) of
@@ -382,7 +480,9 @@ rand_uniform(From,To) when is_integer(From),is_integer(To) ->
erlint(Result);
Other ->
Other
- end.
+ end;
+rand_uniform_pos(_,_) ->
+ error(badarg).
rand_uniform_nif(_From,_To) -> ?nif_stub.
@@ -556,6 +656,22 @@ aes_ctr_encrypt(_Key, _IVec, _Data) -> ?nif_stub.
aes_ctr_decrypt(_Key, _IVec, _Cipher) -> ?nif_stub.
%%
+%% AES - in counter mode (CTR) with state maintained for multi-call streaming
+%%
+-type ctr_state() :: { iodata(), binary(), binary(), integer() }.
+
+-spec aes_ctr_stream_init(iodata(), binary()) -> ctr_state().
+-spec aes_ctr_stream_encrypt(ctr_state(), binary()) ->
+ { ctr_state(), binary() }.
+-spec aes_ctr_stream_decrypt(ctr_state(), binary()) ->
+ { ctr_state(), binary() }.
+
+aes_ctr_stream_init(Key, IVec) ->
+ {Key, IVec, << 0:128 >>, 0}.
+aes_ctr_stream_encrypt({_Key, _IVec, _ECount, _Num}=_State, _Data) -> ?nif_stub.
+aes_ctr_stream_decrypt({_Key, _IVec, _ECount, _Num}=_State, _Cipher) -> ?nif_stub.
+
+%%
%% XOR - xor to iolists and return a binary
%% NB doesn't check that they are the same size, just concatenates
%% them and sends them to the driver
diff --git a/lib/crypto/test/Makefile b/lib/crypto/test/Makefile
index f4689a23df..3150bd472d 100644
--- a/lib/crypto/test/Makefile
+++ b/lib/crypto/test/Makefile
@@ -77,7 +77,7 @@ release_spec:
release_tests_spec: $(TEST_TARGET)
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) crypto.spec crypto.cover $(RELTEST_FILES) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
release_docs_spec:
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index fe8f8e69a0..53b4c2a7e1 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -31,6 +31,11 @@
md4_update/1,
sha/1,
sha_update/1,
+ hmac_update_sha/1,
+ hmac_update_sha_n/1,
+ hmac_update_md5/1,
+ hmac_update_md5_io/1,
+ hmac_update_md5_n/1,
sha256/1,
sha256_update/1,
sha512/1,
@@ -39,13 +44,19 @@
md5_mac_io/1,
des_cbc/1,
des_cbc_iter/1,
+ des_cfb/1,
+ des_cfb_iter/1,
des_ecb/1,
+ des3_cbc/1,
+ des3_cfb/1,
aes_cfb/1,
aes_cbc/1,
aes_cbc_iter/1,
aes_ctr/1,
+ aes_ctr_stream/1,
mod_exp_test/1,
rand_uniform_test/1,
+ strong_rand_test/1,
rsa_verify_test/1,
dsa_verify_test/1,
rsa_sign_test/1,
@@ -66,9 +77,11 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[link_test, md5, md5_update, md4, md4_update, md5_mac,
md5_mac_io, sha, sha_update,
+ hmac_update_sha, hmac_update_sha_n, hmac_update_md5_n, hmac_update_md5_io, hmac_update_md5,
%% sha256, sha256_update, sha512,sha512_update,
- des_cbc, aes_cfb, aes_cbc,
- aes_cbc_iter, aes_ctr, des_cbc_iter, des_ecb, rand_uniform_test,
+ des_cbc, des_cfb, des3_cbc, des3_cfb, aes_cfb, aes_cbc,
+ aes_cbc_iter, aes_ctr, aes_ctr_stream, des_cbc_iter, des_cfb_iter, des_ecb,
+ rand_uniform_test, strong_rand_test,
rsa_verify_test, dsa_verify_test, rsa_sign_test,
dsa_sign_test, rsa_encrypt_decrypt, dh, exor_test,
rc4_test, rc4_stream_test, mod_exp_test, blowfish_cfb64,
@@ -129,14 +142,15 @@ link_test_2(Drv) ->
Libs = os:cmd(Cmd),
io:format("~p\n", [Libs]),
case string:str(Libs, "libcrypto") of
- 0 -> ok;
- _ ->
+ 0 ->
case ?t:is_commercial() of
true ->
- ?t:fail({libcrypto,not_statically_linked});
+ ?t:fail({libcrypto,statically_linked});
false ->
- {comment,"Not statically linked (OK for open-source platform)"}
- end
+ {comment,"Statically linked (OK for open-source platform)"}
+ end;
+ _ ->
+ ok
end
end.
@@ -283,6 +297,101 @@ sha(Config) when is_list(Config) ->
%%
+hmac_update_sha_n(doc) ->
+ ["Request a larger-than-allowed SHA1 HMAC using hmac_init, hmac_update, and hmac_final_n. "
+ "Expected values for examples are generated using crypto:sha_mac." ];
+hmac_update_sha_n(suite) ->
+ [];
+hmac_update_sha_n(Config) when is_list(Config) ->
+ ?line Key = hexstr2bin("00010203101112132021222330313233"
+ "04050607141516172425262734353637"
+ "08090a0b18191a1b28292a2b38393a3b"
+ "0c0d0e0f1c1d1e1f2c2d2e2f3c3d3e3f"),
+ ?line Data = "Sampl",
+ ?line Data2 = "e #1",
+ ?line Ctx = crypto:hmac_init(sha, Key),
+ ?line Ctx2 = crypto:hmac_update(Ctx, Data),
+ ?line Ctx3 = crypto:hmac_update(Ctx2, Data2),
+ ?line Mac = crypto:hmac_final_n(Ctx3, 1024),
+ ?line Exp = crypto:sha_mac(Key, lists:flatten([Data, Data2])),
+ ?line m(Exp, Mac),
+ ?line m(size(Exp), size(Mac)).
+
+
+hmac_update_sha(doc) ->
+ ["Generate an SHA1 HMAC using hmac_init, hmac_update, and hmac_final. "
+ "Expected values for examples are generated using crypto:sha_mac." ];
+hmac_update_sha(suite) ->
+ [];
+hmac_update_sha(Config) when is_list(Config) ->
+ ?line Key = hexstr2bin("00010203101112132021222330313233"
+ "04050607141516172425262734353637"
+ "08090a0b18191a1b28292a2b38393a3b"
+ "0c0d0e0f1c1d1e1f2c2d2e2f3c3d3e3f"),
+ ?line Data = "Sampl",
+ ?line Data2 = "e #1",
+ ?line Ctx = crypto:hmac_init(sha, Key),
+ ?line Ctx2 = crypto:hmac_update(Ctx, Data),
+ ?line Ctx3 = crypto:hmac_update(Ctx2, Data2),
+ ?line Mac = crypto:hmac_final(Ctx3),
+ ?line Exp = crypto:sha_mac(Key, lists:flatten([Data, Data2])),
+ ?line m(Exp, Mac).
+
+hmac_update_md5(doc) ->
+ ["Generate an MD5 HMAC using hmac_init, hmac_update, and hmac_final. "
+ "Expected values for examples are generated using crypto:md5_mac." ];
+hmac_update_md5(suite) ->
+ [];
+hmac_update_md5(Config) when is_list(Config) ->
+ % ?line Key2 = ["A fine speach", "by a fine man!"],
+ Key2 = "A fine speach by a fine man!",
+ ?line Long1 = "Four score and seven years ago our fathers brought forth on this continent a new nation, conceived in liberty, and dedicated to the proposition that all men are created equal.",
+ ?line Long2 = "Now we are engaged in a great civil war, testing whether that nation, or any nation, so conceived and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this.",
+ ?line Long3 = "But, in a larger sense, we can not dedicate, we can not consecrate, we can not hallow this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us-that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion—that we here highly resolve that these dead shall not have died in vain-that this nation, under God, shall have a new birth of freedom-and that government of the people, by the people, for the people, shall not perish from the earth.",
+ ?line CtxA = crypto:hmac_init(md5, Key2),
+ ?line CtxB = crypto:hmac_update(CtxA, Long1),
+ ?line CtxC = crypto:hmac_update(CtxB, Long2),
+ ?line CtxD = crypto:hmac_update(CtxC, Long3),
+ ?line Mac2 = crypto:hmac_final(CtxD),
+ ?line Exp2 = crypto:md5_mac(Key2, lists:flatten([Long1, Long2, Long3])),
+ ?line m(Exp2, Mac2).
+
+
+hmac_update_md5_io(doc) ->
+ ["Generate an MD5 HMAC using hmac_init, hmac_update, and hmac_final. "
+ "Expected values for examples are generated using crypto:md5_mac." ];
+hmac_update_md5_io(suite) ->
+ [];
+hmac_update_md5_io(Config) when is_list(Config) ->
+ ?line Key = ["A fine speach", "by a fine man!"],
+ ?line Data = "Sampl",
+ ?line Data2 = "e #1",
+ ?line Ctx = crypto:hmac_init(md5, Key),
+ ?line Ctx2 = crypto:hmac_update(Ctx, Data),
+ ?line Ctx3 = crypto:hmac_update(Ctx2, Data2),
+ ?line Mac = crypto:hmac_final(Ctx3),
+ ?line Exp = crypto:md5_mac(Key, lists:flatten([Data, Data2])),
+ ?line m(Exp, Mac).
+
+
+hmac_update_md5_n(doc) ->
+ ["Generate a shortened MD5 HMAC using hmac_init, hmac_update, and hmac_final. "
+ "Expected values for examples are generated using crypto:md5_mac." ];
+hmac_update_md5_n(suite) ->
+ [];
+hmac_update_md5_n(Config) when is_list(Config) ->
+ ?line Key = ["A fine speach", "by a fine man!"],
+ ?line Data = "Sampl",
+ ?line Data2 = "e #1",
+ ?line Ctx = crypto:hmac_init(md5, Key),
+ ?line Ctx2 = crypto:hmac_update(Ctx, Data),
+ ?line Ctx3 = crypto:hmac_update(Ctx2, Data2),
+ ?line Mac = crypto:hmac_final_n(Ctx3, 12),
+ ?line Exp = crypto:md5_mac_96(Key, lists:flatten([Data, Data2])),
+ ?line m(Exp, Mac).
+
+
+%%
%%
sha_update(doc) ->
["Generate SHA message digests by using sha_init, sha_update, and"
@@ -442,6 +551,40 @@ des_cbc_iter(Config) when is_list(Config) ->
%%
%%
+des_cfb(doc) ->
+ "Encrypt and decrypt according to CFB DES. and check the result. "
+ "Example is from FIPS-81.";
+des_cfb(suite) ->
+ [];
+des_cfb(Config) when is_list(Config) ->
+ ?line Key = hexstr2bin("0123456789abcdef"),
+ ?line IVec = hexstr2bin("1234567890abcdef"),
+ ?line Plain = "Now is the",
+ ?line Cipher = crypto:des_cfb_encrypt(Key, IVec, Plain),
+ ?line m(Cipher, hexstr2bin("f31fda07011462ee187f")),
+ ?line m(list_to_binary(Plain),
+ crypto:des_cfb_decrypt(Key, IVec, Cipher)).
+
+%%
+%%
+des_cfb_iter(doc) ->
+ "Encrypt and decrypt according to CFB DES in two steps, and "
+ "check the result. Example is from FIPS-81.";
+des_cfb_iter(suite) ->
+ [];
+des_cfb_iter(Config) when is_list(Config) ->
+ ?line Key = hexstr2bin("0123456789abcdef"),
+ ?line IVec = hexstr2bin("1234567890abcdef"),
+ ?line Plain1 = "Now i",
+ ?line Plain2 = "s the",
+ ?line Cipher1 = crypto:des_cfb_encrypt(Key, IVec, Plain1),
+ ?line IVec2 = crypto:des_cfb_ivec(IVec, Cipher1),
+ ?line Cipher2 = crypto:des_cfb_encrypt(Key, IVec2, Plain2),
+ ?line Cipher = list_to_binary([Cipher1, Cipher2]),
+ ?line m(Cipher, hexstr2bin("f31fda07011462ee187f")).
+
+%%
+%%
des_ecb(doc) ->
"Encrypt and decrypt according to ECB DES and check the result. "
"Example are from FIPS-81.";
@@ -464,6 +607,66 @@ des_ecb(Config) when is_list(Config) ->
%%
%%
+des3_cbc(doc) ->
+ "Encrypt and decrypt according to CBC 3DES, and check the result.";
+des3_cbc(suite) ->
+ [];
+des3_cbc(Config) when is_list(Config) ->
+ ?line Key1 = hexstr2bin("0123456789abcdef"),
+ ?line Key2 = hexstr2bin("fedcba9876543210"),
+ ?line Key3 = hexstr2bin("0f2d4b6987a5c3e1"),
+ ?line IVec = hexstr2bin("1234567890abcdef"),
+ ?line Plain = "Now is the time for all ",
+ ?line Cipher = crypto:des3_cbc_encrypt(Key1, Key2, Key3, IVec, Plain),
+ ?line m(Cipher, hexstr2bin("8a2667ee5577267cd9b1af2c5a0480"
+ "0bac1ae66970fb2b89")),
+ ?line m(list_to_binary(Plain),
+ crypto:des3_cbc_decrypt(Key1, Key2, Key3, IVec, Cipher)),
+ ?line Plain2 = "7654321 Now is the time for " ++ [0, 0, 0, 0],
+ ?line Cipher2 = crypto:des3_cbc_encrypt(Key1, Key2, Key3, IVec, Plain2),
+ ?line m(Cipher2, hexstr2bin("eb33ec6ede2c8e90f6877e77b95d5"
+ "4c83cee22907f7f0041ca1b7abe202bfafe")),
+ ?line m(list_to_binary(Plain2),
+ crypto:des3_cbc_decrypt(Key1, Key2, Key3, IVec, Cipher2)),
+
+ ?line Key = hexstr2bin("0123456789abcdef"),
+ ?line DESCipher = crypto:des3_cbc_encrypt(Key, Key, Key, IVec, Plain),
+ ?line m(DESCipher, hexstr2bin("e5c7cdde872bf27c43e934008c389c"
+ "0f683788499a7c05f6")),
+ ?line m(list_to_binary(Plain),
+ crypto:des3_cbc_decrypt(Key, Key, Key, IVec, DESCipher)),
+ ?line DESCipher2 = crypto:des3_cbc_encrypt(Key, Key, Key, IVec, Plain2),
+ ?line m(DESCipher2, hexstr2bin("b9916b8ee4c3da64b4f44e3cbefb9"
+ "9484521388fa59ae67d58d2e77e86062733")),
+ ?line m(list_to_binary(Plain2),
+ crypto:des3_cbc_decrypt(Key, Key, Key, IVec, DESCipher2)).
+
+%%
+%%
+des3_cfb(doc) ->
+ "Encrypt and decrypt according to CFB 3DES, and check the result.";
+des3_cfb(suite) ->
+ [];
+des3_cfb(Config) when is_list(Config) ->
+ ?line Key1 = hexstr2bin("0123456789abcdef"),
+ ?line Key2 = hexstr2bin("fedcba9876543210"),
+ ?line Key3 = hexstr2bin("0f2d4b6987a5c3e1"),
+ ?line IVec = hexstr2bin("1234567890abcdef"),
+ ?line Plain = "Now is the time for all ",
+ ?line Cipher = crypto:des3_cfb_encrypt(Key1, Key2, Key3, IVec, Plain),
+ ?line m(Cipher, hexstr2bin("fc0ba7a20646ba53cc8bff263f0937"
+ "1deab42a00666db02c")),
+ ?line m(list_to_binary(Plain),
+ crypto:des3_cfb_decrypt(Key1, Key2, Key3, IVec, Cipher)),
+ ?line Plain2 = "7654321 Now is the time for " ++ [0, 0, 0, 0],
+ ?line Cipher2 = crypto:des3_cfb_encrypt(Key1, Key2, Key3, IVec, Plain2),
+ ?line m(Cipher2, hexstr2bin("8582c59ac01897422632c0accb66c"
+ "e413f5efab838fce7e41e2ba67705bad5bc")),
+ ?line m(list_to_binary(Plain2),
+ crypto:des3_cfb_decrypt(Key1, Key2, Key3, IVec, Cipher2)).
+
+%%
+%%
aes_cfb(doc) ->
"Encrypt and decrypt according to AES CFB 128 bit and check "
"the result. Example are from NIST SP 800-38A.";
@@ -671,6 +874,77 @@ aes_ctr_do(Key,{IVec, Plain, Cipher}) ->
?line m(C, hexstr2bin(Cipher)),
?line m(P, crypto:aes_ctr_decrypt(Key, I, C)).
+aes_ctr_stream(doc) -> "CTR Streaming";
+aes_ctr_stream(Config) when is_list(Config) ->
+ %% Sample data from NIST Spec.Publ. 800-38A
+ %% F.5.1 CTR-AES128.Encrypt
+ Key128 = hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"),
+ Samples128 = [{"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", % Input Block
+ ["6bc1bee22e409f", "96e93d7e117393172a"], % Plaintext
+ ["874d6191b620e3261bef6864990db6ce"]}, % Ciphertext
+ {"f0f1f2f3f4f5f6f7f8f9fafbfcfdff00",
+ ["ae2d8a57", "1e03ac9c", "9eb76fac", "45af8e51"],
+ ["9806f66b7970fdff","8617187bb9fffdff"]},
+ {"f0f1f2f3f4f5f6f7f8f9fafbfcfdff01",
+ ["30c81c46a35c", "e411e5fbc119", "1a0a52ef"],
+ ["5ae4df3e","dbd5d3","5e5b4f0902","0db03eab"]},
+ {"f0f1f2f3f4f5f6f7f8f9fafbfcfdff02",
+ ["f69f2445df4f9b17ad2b417be66c3710"],
+ ["1e031dda2fbe","03d1792170a0","f3009cee"]}],
+ lists:foreach(fun(S) -> aes_ctr_stream_do(Key128,S) end, Samples128),
+
+ %% F.5.3 CTR-AES192.Encrypt
+ Key192 = hexstr2bin("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"),
+ Samples192 = [{"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", % Input Block
+ ["6bc1bee22e409f96e93d7e117393172a"], % Plaintext
+ ["1abc9324","17521c","a24f2b04","59fe7e6e0b"]}, % Ciphertext
+ {"f0f1f2f3f4f5f6f7f8f9fafbfcfdff00",
+ ["ae2d8a57", "1e03ac9c9eb76fac", "45af8e51"],
+ ["090339ec0aa6faefd5ccc2c6f4ce8e94"]},
+ {"f0f1f2f3f4f5f6f7f8f9fafbfcfdff01",
+ ["30c81c46a35ce411", "e5fbc1191a0a52ef"],
+ ["1e36b26bd1","ebc670d1bd1d","665620abf7"]},
+ {"f0f1f2f3f4f5f6f7f8f9fafbfcfdff02",
+ ["f69f2445", "df4f9b17ad", "2b417be6", "6c3710"],
+ ["4f78a7f6d2980958","5a97daec58c6b050"]}],
+ lists:foreach(fun(S) -> aes_ctr_stream_do(Key192,S) end, Samples192),
+
+ %% F.5.5 CTR-AES256.Encrypt
+ Key256 = hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
+ Samples256 = [{"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", % Input Block
+ ["6bc1bee22e409f96", "e93d7e117393172a"], % Plaintext
+ ["601ec313775789", "a5b7a7f504bbf3d228"]}, % Ciphertext
+ {"f0f1f2f3f4f5f6f7f8f9fafbfcfdff00",
+ ["ae2d8a571e03ac9c9eb76fac45af8e51"],
+ ["f443e3ca","4d62b59aca84","e990cacaf5c5"]},
+ {"f0f1f2f3f4f5f6f7f8f9fafbfcfdff01",
+ ["30c81c46","a35ce411","e5fbc119","1a0a52ef"],
+ ["2b0930daa23de94ce87017ba2d84988d"]},
+ {"f0f1f2f3f4f5f6f7f8f9fafbfcfdff02",
+ ["f69f2445df4f","9b17ad2b41","7be66c3710"],
+ ["dfc9c5","8db67aada6","13c2dd08","457941a6"]}],
+ lists:foreach(fun(S) -> aes_ctr_stream_do(Key256,S) end, Samples256).
+
+
+aes_ctr_stream_do(Key,{IVec, PlainList, CipherList}) ->
+ ?line I = hexstr2bin(IVec),
+ ?line S = crypto:aes_ctr_stream_init(Key, I),
+ ?line C = aes_ctr_stream_do_iter(
+ S, PlainList, [],
+ fun(S2,P) -> crypto:aes_ctr_stream_encrypt(S2, P) end),
+ ?line m(C, hexstr2bin(lists:flatten(CipherList))),
+ ?line P = aes_ctr_stream_do_iter(
+ S, CipherList, [],
+ fun(S2,C2) -> crypto:aes_ctr_stream_decrypt(S2, C2) end),
+ ?line m(P, hexstr2bin(lists:flatten(PlainList))).
+
+aes_ctr_stream_do_iter(_State, [], Acc, _CipherFun) ->
+ iolist_to_binary(lists:reverse(Acc));
+aes_ctr_stream_do_iter(State, [Plain|Rest], Acc, CipherFun) ->
+ ?line P = hexstr2bin(Plain),
+ ?line {S2, C} = CipherFun(State, P),
+ aes_ctr_stream_do_iter(S2, Rest, [C | Acc], CipherFun).
+
%%
%%
mod_exp_test(doc) ->
@@ -703,10 +977,44 @@ rand_uniform_aux_test(0) ->
rand_uniform_aux_test(N) ->
?line L = N*1000,
?line H = N*100000+1,
+ ?line crypto_rand_uniform(L, H),
+ ?line crypto_rand_uniform(-L, L),
+ ?line crypto_rand_uniform(-H, -L),
+ ?line crypto_rand_uniform(-H, L),
+ ?line rand_uniform_aux_test(N-1).
+
+crypto_rand_uniform(L,H) ->
?line R1 = crypto:rand_uniform(L, H),
?line t(R1 >= L),
- ?line t(R1 < H),
- ?line rand_uniform_aux_test(N-1).
+ ?line t(R1 < H).
+
+
+%%
+%%
+strong_rand_test(doc) ->
+ "strong_rand_mpint and strong_random_bytes testing";
+strong_rand_test(suite) ->
+ [];
+strong_rand_test(Config) when is_list(Config) ->
+ strong_rand_aux_test(180),
+ ?line 10 = byte_size(crypto:strong_rand_bytes(10)).
+
+strong_rand_aux_test(0) ->
+ ?line t(crypto:strong_rand_mpint(0,0,0) =:= <<0,0,0,0>>),
+ ok;
+strong_rand_aux_test(1) ->
+ ?line t(crypto:erlint(crypto:strong_rand_mpint(1,0,1)) =:= 1),
+ ?line strong_rand_aux_test(0);
+strong_rand_aux_test(N) ->
+ ?line t(sru_length(crypto:strong_rand_mpint(N,-1,0)) =< N),
+ ?line t(sru_length(crypto:strong_rand_mpint(N,0,0)) =:= N),
+ ?line t(crypto:erlint(crypto:strong_rand_mpint(N,0,1)) band 1 =:= 1),
+ ?line t(crypto:erlint(crypto:strong_rand_mpint(N,1,0)) bsr (N - 2) =:= 2#11),
+ ?line strong_rand_aux_test(N-1).
+
+sru_length(Mpint) ->
+ I = crypto:erlint(Mpint),
+ length(erlang:integer_to_list(I, 2)).
%%
%%
@@ -1023,8 +1331,8 @@ rc4_test(doc) ->
rc4_test(suite) ->
[];
rc4_test(Config) when is_list(Config) ->
- CT1 = <<"hej p� dig">>,
- R1 = <<71,112,14,44,140,33,212,144,155,47>>,
+ CT1 = <<"Yo baby yo">>,
+ R1 = <<118,122,68,110,157,166,141,212,139,39>>,
K = "apaapa",
R1 = crypto:rc4_encrypt(K, CT1),
CT1 = crypto:rc4_encrypt(K, R1),
@@ -1038,14 +1346,14 @@ rc4_stream_test(doc) ->
rc4_stream_test(suite) ->
[];
rc4_stream_test(Config) when is_list(Config) ->
- CT1 = <<"hej">>,
- CT2 = <<" p� dig">>,
+ CT1 = <<"Yo ">>,
+ CT2 = <<"baby yo">>,
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,
+ <<118,122,68,110,157,166,141,212,139,39>> = R,
ok.
blowfish_cfb64(doc) -> ["Test Blowfish encrypt/decrypt."];
@@ -1097,8 +1405,9 @@ worker_loop(0, _) ->
ok;
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, rc4_stream_test, mod_exp_test },
+ aes_cfb, aes_cbc, des_cbc_iter, rand_uniform_test, strong_rand_test,
+ rsa_verify_test, exor_test, rc4_test, rc4_stream_test, mod_exp_test,
+ hmac_update_md5, hmac_update_sha, aes_ctr_stream },
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 e2d6fd0b37..33fa9b1ec3 100644
--- a/lib/crypto/vsn.mk
+++ b/lib/crypto/vsn.mk
@@ -1 +1 @@
-CRYPTO_VSN = 2.0.2.1
+CRYPTO_VSN = 2.0.4
diff --git a/lib/debugger/doc/src/debugger_chapter.xml b/lib/debugger/doc/src/debugger_chapter.xml
index 1f5d4dd5ff..2d812b0236 100644
--- a/lib/debugger/doc/src/debugger_chapter.xml
+++ b/lib/debugger/doc/src/debugger_chapter.xml
@@ -254,19 +254,17 @@ c_break(Bindings) ->
used, for example, if an error occurs:</p>
<pre>
1> <input>catch a+1.</input>
-{'EXIT',{badarith,[{erlang,'+',[a,1]},
- {erl_eval,do_apply,5},
- {erl_eval,expr,5},
- {shell,exprs,6},
- {shell,eval_exprs,6},
- {shell,eval_loop,3}]}}</pre>
-
- <p>In the case above, the stack trace shows that the function called
- last was <c>erl_eval:eval_op/3</c>. See <em>Erlang Reference
- Manual, Errors and Error handling</em>, for more information
- about stack trace.</p>
-
- <p>Debugger emulates the stack trace by keeping track of recently
+{'EXIT',{badarith,[{erlang,'+',[a,1],[]},
+ {erl_eval,do_apply,5,[{file,"erl_eval.erl"},{line,562}]},
+ {erl_eval,expr,5,[{file,"erl_eval.erl"},{line,359}]},
+ {shell,exprs,7,[{file,"shell.erl"},{line,668}]},
+ {shell,eval_exprs,7,[{file,"shell.erl"},{line,623}]},
+ {shell,eval_loop,3,[{file,"shell.erl"},{line,608}]}]}}</pre>
+
+ <p>See the <em>Erlang Reference Manual, Errors and Error handling</em>,
+ for more information about the stack trace.</p>
+
+ <p>The Debugger emulates the stack trace by keeping track of recently
called interpreted functions. (The real stack trace cannot be
used, as it shows which functions of the Debugger have been
called, rather than which interpreted functions).</p>
@@ -276,17 +274,15 @@ c_break(Bindings) ->
<seealso marker="#attach">the Attach Process window</seealso>.
</p>
- <p>By default, the Debugger saves information about all current
+ <p>By default, the Debugger only saves information about recursive
function calls, that is, function calls that have not yet returned
- a value (option 'Stack On, Tail').</p>
-
- <p>This means, however, that information is saved also for tail
- recursive calls. For example, repeated calls to the <c>loop</c>
- function of an Erlang process. This may consume unnecessary
- amounts of memory for debugged processes with long lifetimes and
- many tail recursive calls. It is therefore possible to set
- the option 'Stack On, no tail', in which case information about
- previous calls are discarded when a tail recursive call is made.
+ a value (option 'Stack On, No Tail').</p>
+
+ <p>Sometimes, however, it can be useful to save all calls, even
+ tail-recursive calls. That can be done with the 'Stack On, Tail'
+ option. Note that this option will consume more memory and slow
+ down execution of interpreted functions when there are many
+ tail-recursive calls.
</p>
<p>It is also possible to turn off the Debugger stack trace
diff --git a/lib/debugger/doc/src/int.xml b/lib/debugger/doc/src/int.xml
index 8b55461a44..c9d815755d 100644
--- a/lib/debugger/doc/src/int.xml
+++ b/lib/debugger/doc/src/int.xml
@@ -284,12 +284,12 @@ spawn(Module, Name, [Pid | Args])
<list>
<item><c>all</c> - save information about all current calls,
that is, function calls that have not yet returned a value.
- This is the default.</item>
+ </item>
<item><c>no_tail</c> - save information about current calls,
but discard previous information when a tail recursive call
is made. This option consumes less memory and may be
necessary to use for processes with long lifetimes and many
- tail recursive calls.</item>
+ tail recursive calls. This is the default.</item>
<item><c>false</c> - do not save any information about current
calls.</item>
</list>
diff --git a/lib/debugger/doc/src/notes.xml b/lib/debugger/doc/src/notes.xml
index 3aa169a135..93e447848a 100644
--- a/lib/debugger/doc/src/notes.xml
+++ b/lib/debugger/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/debugger/src/Makefile b/lib/debugger/src/Makefile
index 8551fe887d..6dc7d0d783 100644
--- a/lib/debugger/src/Makefile
+++ b/lib/debugger/src/Makefile
@@ -44,6 +44,7 @@ MODULES= \
dbg_ieval \
dbg_iload \
dbg_iserver \
+ dbg_istk \
dbg_ui_break \
dbg_ui_break_win \
dbg_ui_edit \
diff --git a/lib/debugger/src/dbg_debugged.erl b/lib/debugger/src/dbg_debugged.erl
index 3732c40c73..18dcd92ff3 100644
--- a/lib/debugger/src/dbg_debugged.erl
+++ b/lib/debugger/src/dbg_debugged.erl
@@ -76,8 +76,8 @@ msg_loop(Meta, Mref, SaveStacktrace) ->
msg_loop(Meta, Mref, SaveStacktrace);
%% Meta needs something evaluated within context of real process
- {sys, Meta, {command, Command, Stacktrace}} ->
- Reply = handle_command(Command, Stacktrace),
+ {sys, Meta, {command,Command}} ->
+ Reply = handle_command(Command),
Meta ! {sys, self(), Reply},
msg_loop(Meta, Mref, SaveStacktrace);
@@ -93,11 +93,12 @@ msg_loop(Meta, Mref, SaveStacktrace) ->
end
end.
-handle_command(Command, Stacktrace) ->
- try reply(Command)
+handle_command(Command) ->
+ try
+ reply(Command)
catch Class:Reason ->
- Stacktrace2 = stacktrace_f(erlang:get_stacktrace()),
- {exception, {Class,Reason,Stacktrace2++Stacktrace}}
+ Stacktrace = stacktrace_f(erlang:get_stacktrace()),
+ {exception,{Class,Reason,Stacktrace}}
end.
reply({apply,M,F,As}) ->
@@ -116,5 +117,5 @@ demonitor(Mref) ->
%% Fix stacktrace - keep all above call to this module.
%%
stacktrace_f([]) -> [];
-stacktrace_f([{?MODULE,_,_}|_]) -> [];
+stacktrace_f([{?MODULE,_,_,_}|_]) -> [];
stacktrace_f([F|S]) -> [F|stacktrace_f(S)].
diff --git a/lib/debugger/src/dbg_icmd.erl b/lib/debugger/src/dbg_icmd.erl
index e9502eaa2b..b230efaa7a 100644
--- a/lib/debugger/src/dbg_icmd.erl
+++ b/lib/debugger/src/dbg_icmd.erl
@@ -273,7 +273,7 @@ handle_int_msg({old_code,Mod}, Status, Bs,
erase([Mod|db]),
put(cache, []);
true ->
- case dbg_ieval:in_use_p(Mod, M) of
+ case dbg_istk:in_use_p(Mod, M) of
true ->
%% A call to Mod is on the stack (or might be),
%% so we must terminate.
@@ -342,11 +342,11 @@ handle_user_msg({set,stack_trace,Flag}, _Status, _Bs, _Ieval) ->
handle_user_msg({get,bindings,From,SP}, _Status, Bs, _Ieval) ->
reply(From, bindings, bindings(Bs, SP));
handle_user_msg({get,stack_frame,From,{Dir,SP}}, _Status, _Bs,_Ieval) ->
- reply(From, stack_frame, dbg_ieval:stack_frame(Dir, SP));
+ reply(From, stack_frame, dbg_istk:stack_frame(Dir, SP));
handle_user_msg({get,messages,From,_}, _Status, _Bs, _Ieval) ->
reply(From, messages, messages());
-handle_user_msg({get,backtrace,From,N}, _Status, _Bs, _Ieval) ->
- reply(From, backtrace, dbg_ieval:backtrace(N)).
+handle_user_msg({get,backtrace,From,N}, _Status, _Bs, Ieval) ->
+ reply(From, backtrace, dbg_istk:backtrace(N, Ieval)).
set_stack_trace(true) ->
set_stack_trace(all);
@@ -366,11 +366,11 @@ reply(From, Tag, Reply) ->
bindings(Bs, nostack) ->
Bs;
bindings(Bs, SP) ->
- case dbg_ieval:stack_level() of
+ case dbg_istk:stack_level() of
Le when SP > Le ->
Bs;
_ ->
- dbg_ieval:bindings(SP)
+ dbg_istk:bindings(SP)
end.
messages() ->
@@ -422,7 +422,7 @@ eval_nonrestricted({From, _Mod, Cmd, _SP}, Bs,
eval_nonrestricted_1({match,_,{var,_,Var},Expr}, Bs, Ieval) ->
{value,Res,Bs2} =
- dbg_ieval:eval_expr(Expr, Bs, Ieval#ieval{last_call=false}),
+ dbg_ieval:eval_expr(Expr, Bs, Ieval#ieval{top=false}),
Bs3 = case lists:keyfind(Var, 1, Bs) of
{Var,_Value} ->
lists:keyreplace(Var, 1, Bs2, {Var,Res});
@@ -437,7 +437,7 @@ eval_nonrestricted_1({var,_,Var}, Bs, _Ieval) ->
{Res,Bs};
eval_nonrestricted_1(Expr, Bs, Ieval) ->
{value,Res,Bs2} =
- dbg_ieval:eval_expr(Expr, Bs, Ieval#ieval{last_call=false}),
+ dbg_ieval:eval_expr(Expr, Bs, Ieval#ieval{top=false}),
{Res,Bs2}.
mark_running(LineNo, Le) ->
diff --git a/lib/debugger/src/dbg_ieval.erl b/lib/debugger/src/dbg_ieval.erl
index 306323f8ea..df725ed9e5 100644
--- a/lib/debugger/src/dbg_ieval.erl
+++ b/lib/debugger/src/dbg_ieval.erl
@@ -20,8 +20,7 @@
-export([eval/3,exit_info/5]).
-export([eval_expr/3]).
--export([check_exit_msg/3,exception/4,in_use_p/2]).
--export([stack_level/0, bindings/1, stack_frame/2, backtrace/1]).
+-export([check_exit_msg/3,exception/4]).
-include("dbg_ieval.hrl").
@@ -71,13 +70,12 @@ exit_info(Int, AttPid, OrigPid, Reason, ExitInfo) ->
case ExitInfo of
{{Mod,Line},Bs,S} ->
- Stack = binary_to_term(S),
- put(stack, Stack),
- Le = stack_level(Stack),
+ dbg_istk:from_external(S),
+ Le = dbg_istk:stack_level(),
dbg_icmd:tell_attached({exit_at, {Mod, Line}, Reason, Le}),
exit_loop(OrigPid, Reason, Bs,#ieval{module=Mod,line=Line});
{} ->
- put(stack, []),
+ dbg_istk:init(),
dbg_icmd:tell_attached({exit_at, null, Reason, 1}),
exit_loop(OrigPid, Reason, erl_eval:new_bindings(),#ieval{})
end.
@@ -142,12 +140,12 @@ check_exit_msg({'DOWN',_,_,_,Reason}, Bs,
undefined when Le =:= 1 -> % died outside interpreted code
{};
undefined when Le > 1 ->
- StackBin = term_to_binary(get(stack)),
- {{Mod, Li}, Bs, StackBin};
+ StackExternal = (dbg_istk:delayed_to_external())(),
+ {{Mod, Li}, Bs, StackExternal};
%% Debugged has terminated due to an exception
- ExitInfo0 ->
- ExitInfo0
+ ExitInfo0 when is_function(ExitInfo0, 0) ->
+ ExitInfo0()
end,
dbg_iserver:cast(get(int), {set_exit_info,self(),ExitInfo}),
@@ -170,30 +168,26 @@ check_exit_msg(_Msg, _Bs, _Ieval) ->
%% and then raise the exception.
%%--------------------------------------------------------------------
exception(Class, Reason, Bs, Ieval) ->
- exception(Class, Reason, fix_stacktrace(1), Bs, Ieval).
-
-exception(Class, Reason, Stacktrace, Bs, #ieval{module=M, line=Line}) ->
- ExitInfo = {{M,Line}, Bs, term_to_binary(get(stack))},
+ exception(Class, Reason, Bs, Ieval, false).
+
+exception(Class, Reason, Bs, Ieval, false) ->
+ do_exception(Class, Reason,
+ dbg_istk:delayed_stacktrace(no_args, Ieval),
+ Bs, Ieval);
+exception(Class, Reason, Bs, Ieval, true) ->
+ do_exception(Class, Reason,
+ dbg_istk:delayed_stacktrace(include_args, Ieval),
+ Bs, Ieval).
+
+do_exception(Class, Reason, Stacktrace, Bs, #ieval{module=M, line=Line}) ->
+ StackFun = dbg_istk:delayed_to_external(),
+ ExitInfo = fun() ->
+ {{M,Line},Bs,StackFun()}
+ end,
put(exit_info, ExitInfo),
put(stacktrace, Stacktrace),
erlang:Class(Reason).
-%%--------------------------------------------------------------------
-%% in_use_p(Mod, Cm) -> boolean()
-%% Mod = Cm = atom()
-%% Returns true if Mod is found on the stack, otherwise false.
-%%--------------------------------------------------------------------
-in_use_p(Mod, Mod) -> true;
-in_use_p(Mod, _Cm) ->
- case get(trace_stack) of
- false -> true;
- _ -> % all | no_tail
- lists:any(fun({_,{M,_,_,_}}) when M =:= Mod -> true;
- (_) -> false
- end,
- get(stack))
- end.
-
%%====================================================================
%% Internal functions
%%====================================================================
@@ -225,7 +219,7 @@ meta(Int, Debugged, M, F, As) ->
put(cache, []),
put(next_break, Status), % break | running (other values later)
put(self, Debugged), % pid() interpreted process
- put(stack, []),
+ dbg_istk:init(),
put(stacktrace, []),
put(trace_stack, dbg_iserver:call(Int, get_stack_trace)),
put(trace, false), % bool() Trace on/off
@@ -243,8 +237,7 @@ meta(Int, Debugged, M, F, As) ->
debugged_cmd(Cmd, Bs, Ieval) ->
Debugged = get(self),
- Stacktrace = fix_stacktrace(2),
- Debugged ! {sys, self(), {command,Cmd,Stacktrace}},
+ Debugged ! {sys, self(), {command,Cmd}},
meta_loop(Debugged, Bs, Ieval).
meta_loop(Debugged, Bs, #ieval{level=Le} = Ieval) ->
@@ -257,12 +250,17 @@ meta_loop(Debugged, Bs, #ieval{level=Le} = Ieval) ->
{value, Val, Bs};
{sys, Debugged, {value,Val,Bs2}} ->
{value, Val, Bs2};
- {sys, Debugged, {exception,{Class,Reason,Stacktrace}}} ->
+ {sys, Debugged, {exception,{Class,Reason,Stk}}} ->
case get(exit_info) of
- %% Error occured outside interpreted code
+ %% Error occurred outside of interpreted code.
undefined ->
- exception(Class,Reason,Stacktrace,Bs,Ieval);
+ MakeStk0 = dbg_istk:delayed_stacktrace(),
+ MakeStk = fun(Depth0) ->
+ Depth = max(0, Depth0 - length(Stk)),
+ Stk ++ MakeStk0(Depth)
+ end,
+ do_exception(Class, Reason, MakeStk, Bs, Ieval);
%% Error must have occured within a re-entry to
%% interpreted code, simply raise the exception
@@ -275,7 +273,7 @@ meta_loop(Debugged, Bs, #ieval{level=Le} = Ieval) ->
%% Reset process dictionary
%% This is really only necessary if the process left
%% interpreted code at a call level > 1
- put(stack, []),
+ dbg_istk:init(),
put(stacktrace, []),
put(exit_info, undefined),
@@ -313,177 +311,6 @@ exit_loop(OrigPid, Reason, Bs, Ieval) ->
exit_loop(OrigPid, Reason, Bs, Ieval)
end.
-%%--Stack emulation---------------------------------------------------
-
-%% We keep track of a call stack that is used for
-%% 1) saving stack frames that can be inspected from an Attached
-%% Process GUI (using dbg_icmd:get(Meta, stack_frame, {Dir, SP})
-%% 2) generate an approximation of regular stacktrace -- sent to
-%% Debugged when it should raise an exception or evaluate a
-%% function (since it might possible raise an exception)
-%%
-%% Stack = [Entry]
-%% Entry = {Le, {MFA, Where, Bs}}
-%% Le = int() % current call level
-%% MFA = {M,F,Args} % called function (or fun)
-%% | {Fun,Args} %
-%% Where = {M,Li} % from where (module+line) function is called
-%% Bs = bindings() % current variable bindings
-%%
-%% How to push depends on the "Stack Trace" option (value saved in
-%% process dictionary item 'trace_stack').
-%% all - everything is pushed
-%% no_tail - tail recursive push
-%% false - nothing is pushed
-%% Whenever a function returns, the corresponding call frame is popped.
-
-push(MFA, Bs, #ieval{level=Le,module=Cm,line=Li,last_call=Lc}) ->
- Entry = {Le, {MFA, {Cm,Li}, Bs}},
- case get(trace_stack) of
- false -> ignore;
- no_tail when Lc ->
- case get(stack) of
- [] -> put(stack, [Entry]);
- [_Entry|Entries] -> put(stack, [Entry|Entries])
- end;
- _ -> % all | no_tail when Lc =:= false
- put(stack, [Entry|get(stack)])
- end.
-
-pop() ->
- case get(trace_stack) of
- false -> ignore;
- _ -> % all � no_tail
- case get(stack) of
- [_Entry|Entries] ->
- put(stack, Entries);
- [] ->
- ignore
- end
- end.
-
-pop(Le) ->
- case get(trace_stack) of
- false -> ignore;
- _ -> % all | no_tail
- put(stack, pop(Le, get(stack)))
- end.
-
-pop(Level, [{Le, _}|Stack]) when Level=<Le ->
- pop(Level, Stack);
-pop(_Level, Stack) ->
- Stack.
-
-
-%% stack_level() -> Le
-%% stack_level(Stack) -> Le
-%% Top call level
-stack_level() ->
- stack_level(get(stack)).
-
-stack_level([]) -> 1;
-stack_level([{Le,_}|_]) -> Le.
-
-%% fix_stacktrace(Start) -> Stacktrace
-%% Start = 1|2
-%% Stacktrace = [{M,F,Args|Arity} | {Fun,Args}]
-%% Convert internal stack format to imitation of regular stacktrace.
-%% Max three elements, no repeated (recursive) calls to the same
-%% function and convert argument lists to arity for all but topmost
-%% entry (and funs).
-%% 'Start' indicates where at get(stack) to start. This somewhat ugly
-%% solution is because fix_stacktrace has two uses: 1) to imitate
-%% the stacktrace in the case of an exception in the interpreted code,
-%% in which case the current call (top of the stack = first of the list)
-%% should be included, and 2) to send a current stacktrace to Debugged
-%% when evaluation passes into non-interpreted code, in which case
-%% the current call should NOT be included (as it is Debugged which
-%% will make the actual function call).
-fix_stacktrace(Start) ->
- case fix_stacktrace2(sublist(get(stack), Start, 3)) of
- [] ->
- [];
- [H|T] ->
- [H|args2arity(T)]
- end.
-
-sublist([], _Start, _Length) ->
- []; % workaround, lists:sublist([],2,3) fails
-sublist(L, Start, Length) ->
- lists:sublist(L, Start, Length).
-
-fix_stacktrace2([{_,{{M,F,As1},_,_}}, {_,{{M,F,As2},_,_}}|_])
- when length(As1) =:= length(As2) ->
- [{M,F,As1}];
-fix_stacktrace2([{_,{{Fun,As1},_,_}}, {_,{{Fun,As2},_,_}}|_])
- when length(As1) =:= length(As2) ->
- [{Fun,As1}];
-fix_stacktrace2([{_,{MFA,_,_}}|Entries]) ->
- [MFA|fix_stacktrace2(Entries)];
-fix_stacktrace2([]) ->
- [].
-
-args2arity([{M,F,As}|Entries]) when is_list(As) ->
- [{M,F,length(As)}|args2arity(Entries)];
-args2arity([Entry|Entries]) ->
- [Entry|args2arity(Entries)];
-args2arity([]) ->
- [].
-
-%% bindings(SP) -> Bs
-%% SP = Le % stack pointer
-%% Return the bindings for the specified call level
-bindings(SP) ->
- bindings(SP, get(stack)).
-
-bindings(SP, [{SP,{_MFA,_Wh,Bs}}|_]) ->
- Bs;
-bindings(SP, [_Entry|Entries]) ->
- bindings(SP, Entries);
-bindings(_SP, []) ->
- erl_eval:new_bindings().
-
-%% stack_frame(Dir, SP) -> {Le, Where, Bs} | top | bottom
-%% Dir = up | down
-%% Where = {Cm, Li}
-%% Cm = Module | undefined % module
-%% Li = int() | -1 % line number
-%% Bs = bindings()
-%% Return stack frame info one step up/down from given stack pointer
-%% up = to lower call levels
-%% down = to higher call levels
-stack_frame(up, SP) ->
- stack_frame(SP, up, get(stack));
-stack_frame(down, SP) ->
- stack_frame(SP, down, lists:reverse(get(stack))).
-
-stack_frame(SP, up, [{Le, {_MFA,Where,Bs}}|_]) when Le<SP ->
- {Le, Where, Bs};
-stack_frame(SP, down, [{Le, {_MFA,Where,Bs}}|_]) when Le>SP ->
- {Le, Where, Bs};
-stack_frame(SP, Dir, [{SP, _}|Stack]) ->
- case Stack of
- [{Le, {_MFA,Where,Bs}}|_] ->
- {Le, Where, Bs};
- [] when Dir =:= up ->
- top;
- [] when Dir =:= down ->
- bottom
- end;
-stack_frame(SP, Dir, [_Entry|Stack]) ->
- stack_frame(SP, Dir, Stack).
-
-%% backtrace(HowMany) -> Backtrace
-%% HowMany = all | int()
-%% Backtrace = {Le, MFA}
-%% Return all/the last N called functions, in reversed call order
-backtrace(HowMany) ->
- Stack = case HowMany of
- all -> get(stack);
- N -> lists:sublist(get(stack), N)
- end,
- [{Le, MFA} || {Le,{MFA,_Wh,_Bs}} <- Stack].
-
%%--Trace function----------------------------------------------------
%%--------------------------------------------------------------------
@@ -558,7 +385,7 @@ format_args1([]) ->
%% Mimic catch behaviour
catch_value(error, Reason) ->
- {'EXIT',{Reason,get(stacktrace)}};
+ {'EXIT',{Reason,get_stacktrace()}};
catch_value(exit, Reason) ->
{'EXIT',Reason};
catch_value(throw, Reason) ->
@@ -570,11 +397,13 @@ catch_value(throw, Reason) ->
%% Top level function of meta evaluator.
%% Return message to be replied to the target process.
%%--------------------------------------------------------------------
-eval_mfa(Debugged, M, F, As, Ieval) ->
+eval_mfa(Debugged, M, F, As, #ieval{level=Le}=Ieval0) ->
Int = get(int),
Bs = erl_eval:new_bindings(),
- try eval_function(M,F,As,Bs,extern,Ieval#ieval{last_call=true}) of
+ Ieval = Ieval0#ieval{level=Le+1,top=true},
+ try do_eval_function(M, F, As, Bs, extern, Ieval) of
{value, Val, _Bs} ->
+ trace(return, {Le,Val}),
{ready, Val}
catch
exit:{Debugged, Reason} ->
@@ -582,76 +411,68 @@ eval_mfa(Debugged, M, F, As, Ieval) ->
exit:{Int, Reason} ->
exit(Reason);
Class:Reason ->
- {exception, {Class, Reason, get(stacktrace)}}
+ {exception, {Class, Reason, get_stacktrace()}}
+ end.
+
+eval_function(Mod, Name, As, Bs, Called, Ieval0, Lc) ->
+ Tail = Lc andalso get(trace_stack) =:= no_tail,
+ case Tail of
+ false ->
+ Ieval = dbg_istk:push(Bs, Ieval0, Lc),
+ {value,Val,_} = do_eval_function(Mod, Name, As, Bs, Called, Ieval),
+ dbg_istk:pop(),
+ trace(return, {Ieval#ieval.level,Val}),
+ {value,Val,Bs};
+ true ->
+ do_eval_function(Mod, Name, As, Bs, Called, Ieval0)
end.
-eval_function(Mod, Fun, As0, Bs0, _Called, Ieval) when is_function(Fun);
- Mod =:= ?MODULE,
- Fun =:= eval_fun ->
- #ieval{level=Le, line=Li, last_call=Lc} = Ieval,
+do_eval_function(Mod, Fun, As0, Bs0, _, Ieval0) when is_function(Fun);
+ Mod =:= ?MODULE,
+ Fun =:= eval_fun ->
+ #ieval{level=Le,line=Li,top=Top} = Ieval0,
case lambda(Fun, As0) of
- {Cs,Module,Name,As,Bs} ->
- push({Module,Name,As}, Bs0, Ieval),
+ {[{clause,Fc,_,_,_}|_]=Cs,Module,Name,As,Bs} ->
+ Ieval = Ieval0#ieval{module=Module,function=Name,
+ arguments=As0,line=Fc},
trace(call_fun, {Le,Li,Name,As}),
- {value, Val, _Bs} =
- fnk_clauses(Cs, Module, Name, As, Bs,
- Ieval#ieval{level=Le+1}),
- pop(),
- trace(return, {Le,Val}),
- {value, Val, Bs0};
+ fnk_clauses(Cs, As, Bs, Ieval);
- not_interpreted when Lc -> % We are leaving interpreted code
+ not_interpreted when Top -> % We are leaving interpreted code
trace(call_fun, {Le,Li,Fun,As0}),
{value, {dbg_apply,erlang,apply,[Fun,As0]}, Bs0};
not_interpreted ->
- push({Fun,As0}, Bs0, Ieval),
trace(call_fun, {Le,Li,Fun,As0}),
- {value, Val, _Bs} =
- debugged_cmd({apply,erlang,apply,[Fun,As0]},Bs0,
- Ieval#ieval{level=Le+1}),
- pop(),
- trace(return, {Le,Val}),
- {value, Val, Bs0};
+ debugged_cmd({apply,erlang,apply,[Fun,As0]}, Bs0, Ieval0);
{error,Reason} ->
%% It's ok not to push anything in this case, the error
%% reason contains information about the culprit
%% ({badarity,{{Mod,Name},As}})
- exception(error, Reason, Bs0, Ieval)
+ exception(error, Reason, Bs0, Ieval0)
end;
%% Common Test adaptation
-eval_function(ct_line, line, As, Bs, extern, #ieval{level=Le}=Ieval) ->
+do_eval_function(ct_line, line, As, Bs, extern, #ieval{level=Le}=Ieval) ->
debugged_cmd({apply,ct_line,line,As}, Bs, Ieval#ieval{level=Le+1}),
{value, ignore, Bs};
-eval_function(Mod, Name, As0, Bs0, Called, Ieval) ->
- #ieval{level=Le, line=Li, last_call=Lc} = Ieval,
-
- push({Mod,Name,As0}, Bs0, Ieval),
+do_eval_function(Mod, Name, As0, Bs0, Called, Ieval0) ->
+ #ieval{level=Le,line=Li,top=Top} = Ieval0,
trace(call, {Called, {Le,Li,Mod,Name,As0}}),
-
+ Ieval = Ieval0#ieval{module=Mod,function=Name,arguments=As0},
case get_function(Mod, Name, As0, Called) of
- Cs when is_list(Cs) ->
- {value, Val, _Bs} =
- fnk_clauses(Cs, Mod, Name, As0, erl_eval:new_bindings(),
- Ieval#ieval{level=Le+1}),
- pop(),
- trace(return, {Le,Val}),
- {value, Val, Bs0};
+ [{clause,FcLine,_,_,_}|_]=Cs ->
+ fnk_clauses(Cs, As0, erl_eval:new_bindings(),
+ Ieval#ieval{line=FcLine});
- not_interpreted when Lc -> % We are leaving interpreted code
+ not_interpreted when Top -> % We are leaving interpreted code
{value, {dbg_apply,Mod,Name,As0}, Bs0};
not_interpreted ->
- {value, Val, _Bs} =
- debugged_cmd({apply,Mod,Name,As0}, Bs0,
- Ieval#ieval{level=Le+1}),
- pop(),
- trace(return, {Le,Val}),
- {value, Val, Bs0};
+ debugged_cmd({apply,Mod,Name,As0}, Bs0, Ieval);
undef ->
- exception(error, undef, Bs0, Ieval)
+ exception(error, undef, Bs0, Ieval, true)
end.
lambda(eval_fun, [Cs,As,Bs,{Mod,Name}=F]) ->
@@ -752,23 +573,21 @@ cached(Key) ->
%% Try to find a matching function clause
%% #ieval.level is set, the other fields must be set in this function
-fnk_clauses([{clause,Line,Pars,Gs,Body}|Cs], M, F, As, Bs0, Ieval) ->
+fnk_clauses([{clause,Line,Pars,Gs,Body}|Cs], As, Bs0, Ieval) ->
case head_match(Pars, As, [], Bs0) of
{match,Bs1} ->
Bs = add_bindings(Bs1, Bs0),
case guard(Gs, Bs) of
true ->
- seq(Body, Bs,
- Ieval#ieval{line=Line,
- module=M,function=F,arguments=As});
+ seq(Body, Bs, Ieval#ieval{line=Line});
false ->
- fnk_clauses(Cs, M, F, As, Bs0, Ieval)
+ fnk_clauses(Cs, As, Bs0, Ieval)
end;
nomatch ->
- fnk_clauses(Cs, M, F, As, Bs0, Ieval)
+ fnk_clauses(Cs, As, Bs0, Ieval)
end;
-fnk_clauses([], _M, _F, _As, Bs, Ieval) ->
- exception(error, function_clause, Bs, Ieval).
+fnk_clauses([], _As, Bs, Ieval) ->
+ exception(error, function_clause, Bs, Ieval, true).
seq([E], Bs0, Ieval) ->
case dbg_icmd:cmd(E, Bs0, Ieval) of
@@ -782,7 +601,7 @@ seq([E|Es], Bs0, Ieval) ->
{skip,Bs} ->
seq(Es, Bs, Ieval);
Bs1 ->
- {value,_,Bs} = expr(E, Bs1, Ieval#ieval{last_call=false}),
+ {value,_,Bs} = expr(E, Bs1, Ieval#ieval{top=false}),
seq(Es, Bs, Ieval)
end;
seq([], Bs, _) ->
@@ -804,10 +623,9 @@ expr({value,Val}, Bs, _Ieval) -> % Special case straight values
%% List
expr({cons,Line,H0,T0}, Bs0, Ieval0) ->
- Ieval = Ieval0#ieval{line=Line},
- Ieval1 = Ieval#ieval{last_call=false},
- {value,H,Bs1} = expr(H0,Bs0,Ieval1),
- {value,T,Bs2} = expr(T0,Bs0,Ieval1),
+ Ieval = Ieval0#ieval{line=Line,top=false},
+ {value,H,Bs1} = expr(H0, Bs0, Ieval),
+ {value,T,Bs2} = expr(T0, Bs0, Ieval),
{value,[H|T],merge_bindings(Bs2, Bs1, Ieval)};
%% Tuple
@@ -821,12 +639,12 @@ expr({block,Line,Es},Bs,Ieval) ->
%% Catch statement
expr({'catch',Line,Expr}, Bs0, Ieval) ->
- try expr(Expr, Bs0, Ieval#ieval{line=Line, last_call=false})
+ try expr(Expr, Bs0, Ieval#ieval{line=Line, top=false})
catch
Class:Reason ->
%% Exception caught, reset exit info
put(exit_info, undefined),
- pop(Ieval#ieval.level),
+ dbg_istk:pop(Ieval#ieval.level),
Value = catch_value(Class, Reason),
trace(return, {Ieval#ieval.level,Value}),
{value, Value, Bs0}
@@ -835,7 +653,7 @@ expr({'catch',Line,Expr}, Bs0, Ieval) ->
%% Try-catch statement
expr({'try',Line,Es,CaseCs,CatchCs,[]}, Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- try seq(Es, Bs0, Ieval#ieval{last_call=false}) of
+ try seq(Es, Bs0, Ieval#ieval{top=false}) of
{value,Val,Bs} = Value ->
case CaseCs of
[] -> Value;
@@ -848,7 +666,7 @@ expr({'try',Line,Es,CaseCs,CatchCs,[]}, Bs0, Ieval0) ->
end;
expr({'try',Line,Es,CaseCs,CatchCs,As}, Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- try seq(Es, Bs0, Ieval#ieval{last_call=false}) of
+ try seq(Es, Bs0, Ieval#ieval{top=false}) of
{value,Val,Bs} = Value ->
case CaseCs of
[] -> Value;
@@ -859,13 +677,13 @@ expr({'try',Line,Es,CaseCs,CatchCs,As}, Bs0, Ieval0) ->
Class:Reason when CatchCs =/= [] ->
catch_clauses({Class,Reason,[]}, CatchCs, Bs0, Ieval)
after
- seq(As, Bs0, Ieval#ieval{last_call=false})
+ seq(As, Bs0, Ieval#ieval{top=false})
end;
%% Case statement
expr({'case',Line,E,Cs}, Bs0, Ieval) ->
{value,Val,Bs} =
- expr(E, Bs0, Ieval#ieval{line=Line, last_call=false}),
+ expr(E, Bs0, Ieval#ieval{line=Line, top=false}),
case_clauses(Val, Cs, Bs, case_clause, Ieval#ieval{line=Line});
%% If statement
@@ -874,20 +692,20 @@ expr({'if',Line,Cs}, Bs, Ieval) ->
%% Andalso/orelse
expr({'andalso',Line,E1,E2}, Bs, Ieval) ->
- case expr(E1, Bs, Ieval#ieval{line=Line, last_call=false}) of
+ case expr(E1, Bs, Ieval#ieval{line=Line, top=false}) of
{value,false,_}=Res ->
Res;
{value,true,_} ->
- expr(E2, Bs, Ieval#ieval{line=Line, last_call=false});
+ expr(E2, Bs, Ieval#ieval{line=Line, top=false});
{value,Val,Bs} ->
exception(error, {badarg,Val}, Bs, Ieval)
end;
expr({'orelse',Line,E1,E2}, Bs, Ieval) ->
- case expr(E1, Bs, Ieval#ieval{line=Line, last_call=false}) of
+ case expr(E1, Bs, Ieval#ieval{line=Line, top=false}) of
{value,true,_}=Res ->
Res;
{value,false,_} ->
- expr(E2, Bs, Ieval#ieval{line=Line, last_call=false});
+ expr(E2, Bs, Ieval#ieval{line=Line, top=false});
{value,Val,_} ->
exception(error, {badarg,Val}, Bs, Ieval)
end;
@@ -895,7 +713,7 @@ expr({'orelse',Line,E1,E2}, Bs, Ieval) ->
%% Matching expression
expr({match,Line,Lhs,Rhs0}, Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- {value,Rhs,Bs1} = expr(Rhs0, Bs0, Ieval#ieval{last_call=false}),
+ {value,Rhs,Bs1} = expr(Rhs0, Bs0, Ieval#ieval{top=false}),
case match(Lhs, Rhs, Bs1) of
{match,Bs} ->
{value,Rhs,Bs};
@@ -951,21 +769,21 @@ expr({make_fun,Line,Name,Cs}, Bs, #ieval{module=Module}=Ieval) ->
{value,Fun,Bs};
%% Common test adaptation
-expr({call_remote,0,ct_line,line,As0}, Bs0, Ieval0) ->
+expr({call_remote,0,ct_line,line,As0,Lc}, Bs0, Ieval0) ->
{As,_Bs} = eval_list(As0, Bs0, Ieval0),
- eval_function(ct_line, line, As, Bs0, extern, Ieval0);
+ eval_function(ct_line, line, As, Bs0, extern, Ieval0, Lc);
%% Local function call
-expr({local_call,Line,F,As0}, Bs0, #ieval{module=M} = Ieval0) ->
+expr({local_call,Line,F,As0,Lc}, Bs0, #ieval{module=M} = Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
{As,Bs} = eval_list(As0, Bs0, Ieval),
- eval_function(M, F, As, Bs, local, Ieval);
+ eval_function(M, F, As, Bs, local, Ieval, Lc);
%% Remote function call
-expr({call_remote,Line,M,F,As0}, Bs0, Ieval0) ->
+expr({call_remote,Line,M,F,As0,Lc}, Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
{As,Bs} = eval_list(As0, Bs0, Ieval),
- eval_function(M, F, As, Bs, extern, Ieval);
+ eval_function(M, F, As, Bs, extern, Ieval, Lc);
%% Emulated semantics of some BIFs
expr({dbg,Line,self,[]}, Bs, #ieval{level=Le}) ->
@@ -975,9 +793,28 @@ expr({dbg,Line,self,[]}, Bs, #ieval{level=Le}) ->
{value,Self,Bs};
expr({dbg,Line,get_stacktrace,[]}, Bs, #ieval{level=Le}) ->
trace(bif, {Le,Line,erlang,get_stacktrace,[]}),
- Stacktrace = get(stacktrace),
+ Stacktrace = get_stacktrace(),
trace(return, {Le,Stacktrace}),
{value,Stacktrace,Bs};
+expr({dbg,Line,raise,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
+ %% Since erlang:get_stacktrace/0 is emulated, we will
+ %% need to emulate erlang:raise/3 too so that we can
+ %% capture the stacktrace.
+ Ieval = Ieval0#ieval{line=Line},
+ {[Class,Reason,Stk0]=As,Bs} = eval_list(As0, Bs0, Ieval),
+ trace(bif, {Le,Line,erlang,raise,As}),
+ try
+ %% Evaluate raise/3 for error checking and
+ %% truncating of the stacktrace to the correct depth.
+ Error = erlang:raise(Class, Reason, Stk0),
+ trace(return, {Le,Error}),
+ {value,Error,Bs}
+ catch
+ _:_ ->
+ Stk = erlang:get_stacktrace(), %Possibly truncated.
+ StkFun = fun(_) -> Stk end,
+ do_exception(Class, Reason, StkFun, Bs, Ieval)
+ end;
expr({dbg,Line,throw,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
{[Term],Bs} = eval_list(As0, Bs0, Ieval),
@@ -988,11 +825,6 @@ expr({dbg,Line,error,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
{[Term],Bs} = eval_list(As0, Bs0, Ieval),
trace(bif, {Le,Line,erlang,error,[Term]}),
exception(error, Term, Bs, Ieval);
-expr({dbg,Line,fault,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
- Ieval = Ieval0#ieval{line=Line},
- {[Term],Bs} = eval_list(As0, Bs0, Ieval),
- trace(bif, {Le,Line,erlang,fault,[Term]}),
- exception(fault, Term, Bs, Ieval);
expr({dbg,Line,exit,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
{[Term],Bs} = eval_list(As0, Bs0, Ieval),
@@ -1001,36 +833,26 @@ expr({dbg,Line,exit,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
%% Call to "safe" BIF, ie a BIF that can be executed in Meta process
expr({safe_bif,Line,M,F,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
- Ieval = Ieval0#ieval{line=Line},
- {As,Bs} = eval_list(As0, Bs0, Ieval),
+ Ieval1 = Ieval0#ieval{line=Line},
+ {As,Bs} = eval_list(As0, Bs0, Ieval1),
trace(bif, {Le,Line,M,F,As}),
- push({M,F,As}, Bs0, Ieval),
+ Ieval2 = dbg_istk:push(Bs0, Ieval1, false),
+ Ieval = Ieval2#ieval{module=M,function=F,arguments=As,line=-1},
{_,Value,_} = Res = safe_bif(M, F, As, Bs, Ieval),
trace(return, {Le,Value}),
- pop(),
+ dbg_istk:pop(),
Res;
%% Call to a BIF that must be evaluated in the correct process
expr({bif,Line,M,F,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
- Ieval = Ieval0#ieval{line=Line},
- {As,Bs} = eval_list(As0, Bs0, Ieval),
+ Ieval1 = Ieval0#ieval{line=Line},
+ {As,Bs} = eval_list(As0, Bs0, Ieval1),
trace(bif, {Le,Line,M,F,As}),
- push({M,F,As}, Bs0, Ieval),
- {_,Value,_} =
- Res = debugged_cmd({apply,M,F,As}, Bs, Ieval#ieval{level=Le+1}),
+ Ieval2 = dbg_istk:push(Bs0, Ieval1, false),
+ Ieval = Ieval2#ieval{module=M,function=F,arguments=As,line=-1},
+ {_,Value,_} = Res = debugged_cmd({apply,M,F,As}, Bs, Ieval),
trace(return, {Le,Value}),
- pop(),
- Res;
-
-%% Call to a BIF that spawns a new process
-expr({spawn_bif,Line,M,F,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
- Ieval = Ieval0#ieval{line=Line},
- {As,Bs} = eval_list(As0, Bs0, Ieval),
- trace(bif, {Le,Line,M,F,As}),
- push({M,F,As}, Bs0, Ieval),
- Res = debugged_cmd({apply,M,F,As}, Bs,Ieval#ieval{level=Le+1}),
- trace(return, {Le,Res}),
- pop(),
+ dbg_istk:pop(),
Res;
%% Call to an operation
@@ -1046,7 +868,7 @@ expr({op,Line,Op,As0}, Bs0, Ieval0) ->
end;
%% apply/2 (fun)
-expr({apply_fun,Line,Fun0,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
+expr({apply_fun,Line,Fun0,As0,Lc}, Bs0, #ieval{level=Le}=Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
FunValue = case expr(Fun0, Bs0, Ieval) of
{value,{dbg_apply,Mx,Fx,Asx},Bsx} ->
@@ -1058,31 +880,20 @@ expr({apply_fun,Line,Fun0,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
case FunValue of
{value,Fun,Bs1} when is_function(Fun) ->
{As,Bs} = eval_list(As0, Bs1, Ieval),
- eval_function(undefined, Fun, As, Bs, extern, Ieval);
+ eval_function(undefined, Fun, As, Bs, extern, Ieval, Lc);
{value,{M,F},Bs1} when is_atom(M), is_atom(F) ->
{As,Bs} = eval_list(As0, Bs1, Ieval),
- eval_function(M, F, As, Bs, extern, Ieval);
+ eval_function(M, F, As, Bs, extern, Ieval, Lc);
{value,BadFun,Bs1} ->
exception(error, {badfun,BadFun}, Bs1, Ieval)
end;
%% apply/3
-expr({apply,Line,As0}, Bs0, Ieval0) ->
+expr({apply,Line,As0,Lc}, Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
{[M,F,As],Bs} = eval_list(As0, Bs0, Ieval),
- eval_function(M, F, As, Bs, extern, Ieval);
+ eval_function(M, F, As, Bs, extern, Ieval, Lc);
-%% Mod:module_info/0,1
-expr({module_info_0,_,Mod}, Bs, _Ieval) ->
- {value,[{compile,module_info(Mod,compile)},
- {attributes,module_info(Mod,attributes)},
- {imports,module_info(Mod,imports)},
- {exports,module_info(Mod,exports)}],Bs};
-expr({module_info_1,Line,Mod,[As0]}, Bs0, Ieval0) ->
- Ieval = Ieval0#ieval{line=Line},
- {value,What,Bs} = expr(As0, Bs0, Ieval),
- {value,module_info(Mod, What),Bs};
-
%% Receive statement
expr({'receive',Line,Cs}, Bs0, #ieval{level=Le}=Ieval) ->
trace(receivex, {Le,false}),
@@ -1091,7 +902,7 @@ expr({'receive',Line,Cs}, Bs0, #ieval{level=Le}=Ieval) ->
%% Receive..after statement
expr({'receive',Line,Cs,To,ToExprs}, Bs0, #ieval{level=Le}=Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- {value,ToVal,ToBs} = expr(To, Bs0, Ieval#ieval{last_call=false}),
+ {value,ToVal,ToBs} = expr(To, Bs0, Ieval#ieval{top=false}),
trace(receivex, {Le,true}),
check_timeoutvalue(ToVal, ToBs, To, Ieval),
{Stamp,_} = statistics(wall_clock),
@@ -1101,7 +912,7 @@ expr({'receive',Line,Cs,To,ToExprs}, Bs0, #ieval{level=Le}=Ieval0) ->
%% Send (!)
expr({send,Line,To0,Msg0}, Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- Ieval1 = Ieval#ieval{last_call=false},
+ Ieval1 = Ieval#ieval{top=false},
{value,To,Bs1} = expr(To0, Bs0, Ieval1),
{value,Msg,Bs2} = expr(Msg0, Bs0, Ieval1),
Bs = merge_bindings(Bs2, Bs1, Ieval),
@@ -1110,10 +921,15 @@ expr({send,Line,To0,Msg0}, Bs0, Ieval0) ->
%% Binary
expr({bin,Line,Fs}, Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- eval_bits:expr_grp(Fs, Bs0,
- fun (E, B) -> expr(E, B, Ieval) end,
- [],
- false);
+ try
+ eval_bits:expr_grp(Fs, Bs0,
+ fun (E, B) -> expr(E, B, Ieval) end,
+ [],
+ false)
+ catch
+ Class:Reason ->
+ exception(Class, Reason, Bs0, Ieval)
+ end;
%% List comprehension
expr({lc,_Line,E,Qs}, Bs, Ieval) ->
@@ -1138,12 +954,12 @@ eval_lc(E, Qs, Bs, Ieval) ->
eval_lc1(E, [{generate,Line,P,L0}|Qs], Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- {value,L1,Bs1} = expr(L0, Bs0, Ieval#ieval{last_call=false}),
+ {value,L1,Bs1} = expr(L0, Bs0, Ieval#ieval{top=false}),
CompFun = fun(NewBs) -> eval_lc1(E, Qs, NewBs, Ieval) end,
eval_generate(L1, P, Bs1, CompFun, Ieval);
eval_lc1(E, [{b_generate,Line,P,L0}|Qs], Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- {value,Bin,_} = expr(L0, Bs0, Ieval#ieval{last_call=false}),
+ {value,Bin,_} = expr(L0, Bs0, Ieval#ieval{top=false}),
CompFun = fun(NewBs) -> eval_lc1(E, Qs, NewBs, Ieval) end,
eval_b_generate(Bin, P, Bs0, CompFun, Ieval);
eval_lc1(E, [{guard,Q}|Qs], Bs0, Ieval) ->
@@ -1152,13 +968,13 @@ eval_lc1(E, [{guard,Q}|Qs], Bs0, Ieval) ->
false -> []
end;
eval_lc1(E, [Q|Qs], Bs0, Ieval) ->
- case expr(Q, Bs0, Ieval#ieval{last_call=false}) of
+ case expr(Q, Bs0, Ieval#ieval{top=false}) of
{value,true,Bs} -> eval_lc1(E, Qs, Bs, Ieval);
{value,false,_Bs} -> [];
{value,V,Bs} -> exception(error, {bad_filter,V}, Bs, Ieval)
end;
eval_lc1(E, [], Bs, Ieval) ->
- {value,V,_} = expr(E, Bs, Ieval#ieval{last_call=false}),
+ {value,V,_} = expr(E, Bs, Ieval#ieval{top=false}),
[V].
%% eval_bc(Expr,[Qualifier],Bindings,IevalState) ->
@@ -1171,12 +987,12 @@ eval_bc(E, Qs, Bs, Ieval) ->
eval_bc1(E, [{generate,Line,P,L0}|Qs], Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- {value,L1,Bs1} = expr(L0, Bs0, Ieval#ieval{last_call=false}),
+ {value,L1,Bs1} = expr(L0, Bs0, Ieval#ieval{top=false}),
CompFun = fun(NewBs) -> eval_bc1(E, Qs, NewBs, Ieval) end,
eval_generate(L1, P, Bs1, CompFun, Ieval);
eval_bc1(E, [{b_generate,Line,P,L0}|Qs], Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line},
- {value,Bin,_} = expr(L0, Bs0, Ieval#ieval{last_call=false}),
+ {value,Bin,_} = expr(L0, Bs0, Ieval#ieval{top=false}),
CompFun = fun(NewBs) -> eval_bc1(E, Qs, NewBs, Ieval) end,
eval_b_generate(Bin, P, Bs0, CompFun, Ieval);
eval_bc1(E, [{guard,Q}|Qs], Bs0, Ieval) ->
@@ -1185,13 +1001,13 @@ eval_bc1(E, [{guard,Q}|Qs], Bs0, Ieval) ->
false -> []
end;
eval_bc1(E, [Q|Qs], Bs0, Ieval) ->
- case expr(Q, Bs0, Ieval#ieval{last_call=false}) of
+ case expr(Q, Bs0, Ieval#ieval{top=false}) of
{value,true,Bs} -> eval_bc1(E, Qs, Bs, Ieval);
{value,false,_Bs} -> [];
{value,V,Bs} -> exception(error, {bad_filter,V}, Bs, Ieval)
end;
eval_bc1(E, [], Bs, Ieval) ->
- {value,V,_} = expr(E, Bs, Ieval#ieval{last_call=false}),
+ {value,V,_} = expr(E, Bs, Ieval#ieval{top=false}),
[V].
eval_generate([V|Rest], P, Bs0, CompFun, Ieval) ->
@@ -1208,7 +1024,7 @@ eval_generate(Term, _P, Bs, _CompFun, Ieval) ->
exception(error, {bad_generator,Term}, Bs, Ieval).
eval_b_generate(<<_/bitstring>>=Bin, P, Bs0, CompFun, Ieval) ->
- Mfun = fun(L, R, Bs) -> match1(L, R, Bs, Bs0) end,
+ Mfun = match_fun(Bs0),
Efun = fun(Exp, Bs) -> expr(Exp, Bs, #ieval{}) end,
case eval_bits:bin_gen(P, Bin, erl_eval:new_bindings(), Bs0, Mfun, Efun) of
{match,Rest,Bs1} ->
@@ -1222,24 +1038,13 @@ eval_b_generate(<<_/bitstring>>=Bin, P, Bs0, CompFun, Ieval) ->
eval_b_generate(Term, _P, Bs, _CompFun, Ieval) ->
exception(error, {bad_generator,Term}, Bs, Ieval).
-module_info(Mod, module) -> Mod;
-module_info(_Mod, compile) -> [];
-module_info(Mod, attributes) ->
- {ok, Attr} = dbg_iserver:call(get(int), {lookup, Mod, attributes}),
- Attr;
-module_info(_Mod, imports) -> [];
-module_info(Mod, exports) ->
- {ok, Exp} = dbg_iserver:call(get(int), {lookup, Mod, exports}),
- Exp;
-module_info(_Mod, functions) -> [].
-
safe_bif(M, F, As, Bs, Ieval) ->
try apply(M, F, As) of
Value ->
{value,Value,Bs}
catch
Class:Reason ->
- exception(Class, Reason, Bs, Ieval)
+ exception(Class, Reason, Bs, Ieval, true)
end.
eval_send(To, Msg, Bs, Ieval) ->
@@ -1408,12 +1213,12 @@ flush_traces(Debugged) ->
%% eval_list(ExpressionList, Bindings, Ieval)
%% Evaluate a list of expressions "in parallel" at the same level.
eval_list(Es, Bs, Ieval) ->
- eval_list(Es, [], Bs, Bs, Ieval).
+ eval_list_1(Es, [], Bs, Bs, Ieval#ieval{top=false}).
-eval_list([E|Es], Vs, BsOrig, Bs0, Ieval) ->
- {value,V,Bs1} = expr(E, BsOrig, Ieval#ieval{last_call=false}),
- eval_list(Es, [V|Vs], BsOrig, merge_bindings(Bs1,Bs0,Ieval), Ieval);
-eval_list([], Vs, _, Bs, _Ieval) ->
+eval_list_1([E|Es], Vs, BsOrig, Bs0, Ieval) ->
+ {value,V,Bs1} = expr(E, BsOrig, Ieval),
+ eval_list_1(Es, [V|Vs], BsOrig, merge_bindings(Bs1, Bs0, Ieval), Ieval);
+eval_list_1([], Vs, _, Bs, _Ieval) ->
{lists:reverse(Vs,[]),Bs}.
%% if_clauses(Clauses, Bindings, Ieval)
@@ -1453,7 +1258,7 @@ catch_clauses(Exception, [{clause,_,[P],G,B}|CatchCs], Bs0, Ieval) ->
true ->
%% Exception caught, reset exit info
put(exit_info, undefined),
- pop(Ieval#ieval.level),
+ dbg_istk:pop(Ieval#ieval.level),
seq(B, Bs, Ieval);
false ->
catch_clauses(Exception, CatchCs, Bs0, Ieval)
@@ -1588,11 +1393,9 @@ match1({cons,_,H,T}, [H1|T1], Bs0, BBs) ->
match1({tuple,_,Elts}, Tuple, Bs, BBs)
when length(Elts) =:= tuple_size(Tuple) ->
match_tuple(Elts, Tuple, 1, Bs, BBs);
-match1({bin,_,Fs}, B, Bs0, BBs0) when is_bitstring(B) ->
- Bs1 = lists:sort(Bs0), %Kludge.
- BBs = lists:sort(BBs0),
- try eval_bits:match_bits(Fs, B, Bs1, BBs,
- fun(L, R, Bs) -> match1(L, R, Bs, BBs) end,
+match1({bin,_,Fs}, B, Bs0, BBs) when is_bitstring(B) ->
+ try eval_bits:match_bits(Fs, B, Bs0, BBs,
+ match_fun(BBs),
fun(E, Bs) -> expr(E, Bs, #ieval{}) end,
false)
catch
@@ -1601,6 +1404,12 @@ match1({bin,_,Fs}, B, Bs0, BBs0) when is_bitstring(B) ->
match1(_,_,_,_) ->
throw(nomatch).
+match_fun(BBs) ->
+ fun(match, {L,R,Bs}) -> match1(L, R, Bs, BBs);
+ (binding, {Name,Bs}) -> binding(Name, Bs);
+ (add_binding, {Name,Val,Bs}) -> add_binding(Name, Val, Bs)
+ end.
+
match_tuple([E|Es], Tuple, I, Bs0, BBs) ->
{match,Bs} = match1(E, element(I, Tuple), Bs0, BBs),
match_tuple(Es, Tuple, I+1, Bs, BBs);
@@ -1731,3 +1540,19 @@ add_binding(N,Val,[B1|Bs]) ->
[B1|add_binding(N,Val,Bs)];
add_binding(N,Val,[]) ->
[{N,Val}].
+
+%% get_stacktrace() -> Stacktrace
+%% Return the latest stacktrace for the process.
+get_stacktrace() ->
+ case get(stacktrace) of
+ MakeStk when is_function(MakeStk, 1) ->
+ %% The stacktrace has not been constructed before.
+ %% Construct it and remember the result.
+ Depth = erlang:system_flag(backtrace_depth, 8),
+ erlang:system_flag(backtrace_depth, Depth),
+ Stk = MakeStk(Depth),
+ put(stacktrace, Stk),
+ Stk;
+ Stk when is_list(Stk) ->
+ Stk
+ end.
diff --git a/lib/debugger/src/dbg_ieval.hrl b/lib/debugger/src/dbg_ieval.hrl
index a344748f48..ea6189ad02 100644
--- a/lib/debugger/src/dbg_ieval.hrl
+++ b/lib/debugger/src/dbg_ieval.hrl
@@ -21,6 +21,8 @@
module, % MFA which called the currently
function, % interpreted function
arguments, %
- last_call = false % True if current expression is
- }). % the VERY last to be evaluated
- % (ie at all, not only in a clause)
+
+ %% True if the current expression is at the top level
+ %% (i.e. the next call will leave interpreted code).
+ top = false
+ }).
diff --git a/lib/debugger/src/dbg_iload.erl b/lib/debugger/src/dbg_iload.erl
index 2ae0c333da..ce5631e45f 100644
--- a/lib/debugger/src/dbg_iload.erl
+++ b/lib/debugger/src/dbg_iload.erl
@@ -62,22 +62,23 @@ load_mod1(Mod, File, Binary, Db) ->
store_module(Mod, File, Binary, Db) ->
{interpreter_module, Exp, Abst, Src, MD5} = binary_to_term(Binary),
Forms = case abstr(Abst) of
- {abstract_v1,Forms0} -> Forms0;
- {abstract_v2,Forms0} -> Forms0;
+ {abstract_v1,_} ->
+ exit({Mod,too_old_beam_file});
+ {abstract_v2,_} ->
+ exit({Mod,too_old_beam_file});
{raw_abstract_v1,Code0} ->
Code = interpret_file_attribute(Code0),
{_,_,Forms0,_} = sys_pre_expand:module(Code, []),
Forms0
end,
dbg_idb:insert(Db, mod_file, File),
- dbg_idb:insert(Db, exports, Exp),
dbg_idb:insert(Db, defs, []),
put(vcount, 0),
put(fun_count, 0),
put(funs, []),
put(mod_md5, MD5),
- Attr = store_forms(Forms, Mod, Db, Exp, []),
+ store_forms(Forms, Mod, Db, Exp),
erase(mod_md5),
erase(current_function),
%% store_funs(Db, Mod),
@@ -85,11 +86,10 @@ store_module(Mod, File, Binary, Db) ->
erase(funs),
erase(fun_count),
- dbg_idb:insert(Db, attributes, Attr),
NewBinary = store_mod_line_no(Mod, Db, binary_to_list(Src)),
dbg_idb:insert(Db, mod_bin, NewBinary),
- dbg_idb:insert(Db, mod_raw, <<Src/binary,0:8>>), %% Add eos
- dbg_idb:insert(Db, module, Mod).
+ dbg_idb:insert(Db, mod_raw, <<Src/binary,0:8>>). %% Add eos
+
%% Adjust line numbers using the file/2 attribute.
%% Also take the absolute value of line numbers.
%% This simple fix will make the marker point at the correct line
@@ -111,27 +111,19 @@ abstr(Term) -> Term.
% store_funs_1(Fs, Db, Mod);
% store_funs_1([], _, _) -> ok.
-store_forms([{function,_,module_info,0,_}|Fs], Mod, Db, Exp, Attr) ->
- Cs = [{clause,0,[],[], [{module_info_0,0,Mod}]}],
- dbg_idb:insert(Db, {Mod,module_info,0,true}, Cs),
- store_forms(Fs, Mod, Db, Exp, Attr);
-store_forms([{function,_,module_info,1,_}|Fs], Mod, Db, Exp, Attr) ->
- Cs = [{clause,0,[{var,0,'What'}],[], [{module_info_1,0,Mod,[{var,0,'What'}]}]}],
- dbg_idb:insert(Db, {Mod,module_info,1,true}, Cs),
- store_forms(Fs, Mod, Db, Exp, Attr);
-store_forms([{function,_,Name,Arity,Cs0}|Fs], Mod, Db, Exp, Attr) ->
+store_forms([{function,_,Name,Arity,Cs0}|Fs], Mod, Db, Exp) ->
FA = {Name,Arity},
put(current_function, FA),
Cs = clauses(Cs0),
Exported = lists:member(FA, Exp),
dbg_idb:insert(Db, {Mod,Name,Arity,Exported}, Cs),
- store_forms(Fs, Mod, Db, Exp, Attr);
-store_forms([{attribute,_,Name,Val}|Fs], Mod, Db, Exp, Attr) ->
- store_forms(Fs, Mod, Db, Exp, [{Name,Val}|Attr]);
-store_forms([F|_], _Mod, _Db, _Exp, _Attr) ->
+ store_forms(Fs, Mod, Db, Exp);
+store_forms([{attribute,_,_Name,_Val}|Fs], Mod, Db, Exp) ->
+ store_forms(Fs, Mod, Db, Exp);
+store_forms([F|_], _Mod, _Db, _Exp) ->
exit({unknown_form,F});
-store_forms([], _, _, _, Attr) ->
- lists:reverse(Attr).
+store_forms([], _, _, _) ->
+ ok.
store_mod_line_no(Mod, Db, Contents) ->
store_mod_line_no(Mod, Db, Contents, 1, 0, []).
@@ -164,14 +156,14 @@ get_nl([],Pos,Head) -> {lists:reverse(Head),[],Pos}.
%%% to interpret.
clauses([C0|Cs]) ->
- C1 = clause(C0),
+ C1 = clause(C0, true),
[C1|clauses(Cs)];
clauses([]) -> [].
-clause({clause,Line,H0,G0,B0}) ->
+clause({clause,Line,H0,G0,B0}, Lc) ->
H1 = head(H0),
G1 = guard(G0),
- B1 = exprs(B0),
+ B1 = exprs(B0, Lc),
{clause,Line,H1,G1,B1}.
head(Ps) -> patterns(Ps).
@@ -219,7 +211,7 @@ pattern({bin,Line,Grp}) ->
{bin,Line,Grp1};
pattern({bin_element,Line,Expr,Size,Type}) ->
Expr1 = pattern(Expr),
- Size1 = expr(Size),
+ Size1 = expr(Size, false),
{bin_element,Line,Expr1,Size1,Type}.
%% These patterns are processed "in parallel" for purposes of variable
@@ -235,8 +227,6 @@ guard([G0|Gs]) ->
[G1|guard(Gs)];
guard([]) -> [].
-and_guard([{atom,_,true}|Gs]) ->
- and_guard(Gs);
and_guard([G0|Gs]) ->
G1 = guard_test(G0),
[G1|and_guard(Gs)];
@@ -244,12 +234,7 @@ and_guard([]) -> [].
guard_test({call,Line,{remote,_,{atom,_,erlang},{atom,_,F}},As0}) ->
As = gexpr_list(As0),
- case map_guard_bif(F, length(As0)) of
- {ok,Name} ->
- {safe_bif,Line,erlang,Name,As};
- error ->
- {safe_bif,Line,erlang,F,As}
- end;
+ {safe_bif,Line,erlang,F,As};
guard_test({op,Line,Op,L0}) ->
true = erl_internal:arith_op(Op, 1) orelse %Assertion.
erl_internal:bool_op(Op, 1),
@@ -266,25 +251,18 @@ guard_test({op,Line,Op,L0,R0}) ->
L1 = gexpr(L0),
R1 = gexpr(R0), %They see the same variables
{safe_bif,Line,erlang,Op,[L1,R1]};
-guard_test({integer,_,_}=I) -> I;
-guard_test({char,_,_}=C) -> C;
-guard_test({float,_,_}=F) -> F;
-guard_test({atom,_,_}=A) -> A;
-guard_test({nil,_}=N) -> N;
-guard_test({var,_,_}=V) ->V. % Boolean var
-
-map_guard_bif(integer, 1) -> {ok,is_integer};
-map_guard_bif(float, 1) -> {ok,is_float};
-map_guard_bif(number, 1) -> {ok,is_number};
-map_guard_bif(atom, 1) -> {ok,is_atom};
-map_guard_bif(list, 1) -> {ok,is_list};
-map_guard_bif(tuple, 1) -> {ok,is_tuple};
-map_guard_bif(pid, 1) -> {ok,is_pid};
-map_guard_bif(reference, 1) -> {ok,is_reference};
-map_guard_bif(port, 1) -> {ok,is_port};
-map_guard_bif(binary, 1) -> {ok,is_binary};
-map_guard_bif(function, 1) -> {ok,is_function};
-map_guard_bif(_, _) -> error.
+guard_test({var,_,_}=V) ->V; % Boolean var
+guard_test({atom,Line,true}) -> {value,Line,true};
+%% All other constants at this level means false.
+guard_test({atom,Line,_}) -> {value,Line,false};
+guard_test({integer,Line,_}) -> {value,Line,false};
+guard_test({char,Line,_}) -> {value,Line,false};
+guard_test({float,Line,_}) -> {value,Line,false};
+guard_test({string,Line,_}) -> {value,Line,false};
+guard_test({nil,Line}) -> {value,Line,false};
+guard_test({cons,Line,_,_}) -> {value,Line,false};
+guard_test({tuple,Line,_}) -> {value,Line,false};
+guard_test({bin,Line,_}) -> {value,Line,false}.
gexpr({var,Line,V}) -> {var,Line,V};
gexpr({integer,Line,I}) -> {value,Line,I};
@@ -341,186 +319,179 @@ gexpr_list([]) -> [].
%% These expressions are processed "sequentially" for purposes of variable
%% definition etc.
-exprs([E0|Es]) ->
- E1 = expr(E0),
- [E1|exprs(Es)];
-exprs([]) -> [].
-
-expr({var,Line,V}) -> {var,Line,V};
-expr({integer,Line,I}) -> {value,Line,I};
-expr({char,Line,I}) -> {value,Line,I};
-expr({float,Line,F}) -> {value,Line,F};
-expr({atom,Line,A}) -> {value,Line,A};
-expr({string,Line,S}) -> {value,Line,S};
-expr({nil,Line}) -> {value,Line,[]};
-expr({cons,Line,H0,T0}) ->
- case {expr(H0),expr(T0)} of
+exprs([E], Lc) ->
+ [expr(E, Lc)];
+exprs([E0|Es], Lc) ->
+ E1 = expr(E0, false),
+ [E1|exprs(Es, Lc)];
+exprs([], _Lc) -> [].
+
+expr({var,Line,V}, _Lc) -> {var,Line,V};
+expr({integer,Line,I}, _Lc) -> {value,Line,I};
+expr({char,Line,I}, _Lc) -> {value,Line,I};
+expr({float,Line,F}, _Lc) -> {value,Line,F};
+expr({atom,Line,A}, _Lc) -> {value,Line,A};
+expr({string,Line,S}, _Lc) -> {value,Line,S};
+expr({nil,Line}, _Lc) -> {value,Line,[]};
+expr({cons,Line,H0,T0}, _Lc) ->
+ case {expr(H0, false),expr(T0, false)} of
{{value,Line,H1},{value,Line,T1}} -> {value,Line,[H1|T1]};
{H1,T1} -> {cons,Line,H1,T1}
end;
-expr({tuple,Line,Es0}) ->
+expr({tuple,Line,Es0}, _Lc) ->
Es1 = expr_list(Es0),
{tuple,Line,Es1};
-expr({block,Line,Es0}) ->
+expr({block,Line,Es0}, Lc) ->
%% Unfold block into a sequence.
- Es1 = exprs(Es0),
+ Es1 = exprs(Es0, Lc),
{block,Line,Es1};
-expr({'if',Line,Cs0}) ->
- Cs1 = icr_clauses(Cs0),
+expr({'if',Line,Cs0}, Lc) ->
+ Cs1 = icr_clauses(Cs0, Lc),
{'if',Line,Cs1};
-expr({'case',Line,E0,Cs0}) ->
- E1 = expr(E0),
- Cs1 = icr_clauses(Cs0),
+expr({'case',Line,E0,Cs0}, Lc) ->
+ E1 = expr(E0, false),
+ Cs1 = icr_clauses(Cs0, Lc),
{'case',Line,E1,Cs1};
-expr({'receive',Line,Cs0}) ->
- Cs1 = icr_clauses(Cs0),
+expr({'receive',Line,Cs0}, Lc) ->
+ Cs1 = icr_clauses(Cs0, Lc),
{'receive',Line,Cs1};
-expr({'receive',Line,Cs0,To0,ToEs0}) ->
- To1 = expr(To0),
- ToEs1 = exprs(ToEs0),
- Cs1 = icr_clauses(Cs0),
+expr({'receive',Line,Cs0,To0,ToEs0}, Lc) ->
+ To1 = expr(To0, false),
+ ToEs1 = exprs(ToEs0, Lc),
+ Cs1 = icr_clauses(Cs0, Lc),
{'receive',Line,Cs1,To1,ToEs1};
-expr({'fun',Line,{clauses,Cs0},{_,_,Name}}) when is_atom(Name) ->
+expr({'fun',Line,{clauses,Cs0},{_,_,Name}}, _Lc) when is_atom(Name) ->
%% New R10B-2 format (abstract_v2).
Cs = fun_clauses(Cs0),
{make_fun,Line,Name,Cs};
-expr({'fun',Line,{clauses,Cs0},{_,_,_,_,Name}}) when is_atom(Name) ->
- %% New R8 format (abstract_v2).
- Cs = fun_clauses(Cs0),
- {make_fun,Line,Name,Cs};
-expr({'fun',Line,{function,F,A},{_Index,_OldUniq,Name}}) ->
+expr({'fun',Line,{function,F,A},{_Index,_OldUniq,Name}}, _Lc) ->
%% New R8 format (abstract_v2).
As = new_vars(A, Line),
- Cs = [{clause,Line,As,[],[{local_call,Line,F,As}]}],
+ Cs = [{clause,Line,As,[],[{local_call,Line,F,As,true}]}],
{make_fun,Line,Name,Cs};
-expr({'fun',_,{clauses,_},{_OldUniq,_Hvss,_Free}}) ->
- %% Old format (abstract_v1).
- exit({?MODULE,old_funs});
-expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,self}},[]}) ->
+expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,self}},[]}, _Lc) ->
{dbg,Line,self,[]};
-expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,get_stacktrace}},[]}) ->
+expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,get_stacktrace}},[]}, _Lc) ->
{dbg,Line,get_stacktrace,[]};
-expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,throw}},[_]=As}) ->
+expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,throw}},[_]=As}, _Lc) ->
{dbg,Line,throw,expr_list(As)};
-expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,error}},[_]=As}) ->
+expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,error}},[_]=As}, _Lc) ->
{dbg,Line,error,expr_list(As)};
-expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,fault}},[_]=As}) ->
- {dbg,Line,fault,expr_list(As)};
-expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,exit}},[_]=As}) ->
+expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,exit}},[_]=As}, _Lc) ->
{dbg,Line,exit,expr_list(As)};
-expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,apply}},[_,_,_]=As0}) ->
+expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,raise}},[_,_,_]=As}, _Lc) ->
+ {dbg,Line,raise,expr_list(As)};
+expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,apply}},[_,_,_]=As0}, Lc) ->
As = expr_list(As0),
- {apply,Line,As};
-expr({call,Line,{remote,_,{atom,_,Mod},{atom,_,Func}},As0}) ->
+ {apply,Line,As,Lc};
+expr({call,Line,{remote,_,{atom,_,Mod},{atom,_,Func}},As0}, Lc) ->
As = expr_list(As0),
case erlang:is_builtin(Mod, Func, length(As)) of
false ->
- {call_remote,Line,Mod,Func,As};
+ {call_remote,Line,Mod,Func,As,Lc};
true ->
- case bif_type(Mod, Func) of
+ case bif_type(Mod, Func, length(As0)) of
safe -> {safe_bif,Line,Mod,Func,As};
- spawn -> {spawn_bif,Line,Mod,Func,As};
unsafe ->{bif,Line,Mod,Func,As}
end
end;
-expr({call,Line,{remote,_,Mod0,Func0},As0}) ->
+expr({call,Line,{remote,_,Mod0,Func0},As0}, Lc) ->
%% New R8 format (abstract_v2).
- Mod = expr(Mod0),
- Func = expr(Func0),
+ Mod = expr(Mod0, false),
+ Func = expr(Func0, false),
As = consify(expr_list(As0)),
- {apply,Line,[Mod,Func,As]};
-expr({call,Line,{atom,_,Func},As0}) ->
+ {apply,Line,[Mod,Func,As],Lc};
+expr({call,Line,{atom,_,Func},As0}, Lc) ->
As = expr_list(As0),
- {local_call,Line,Func,As};
-expr({call,Line,Fun0,As0}) ->
- Fun = expr(Fun0),
+ {local_call,Line,Func,As,Lc};
+expr({call,Line,Fun0,As0}, Lc) ->
+ Fun = expr(Fun0, false),
As = expr_list(As0),
- {apply_fun,Line,Fun,As};
-expr({'catch',Line,E0}) ->
+ {apply_fun,Line,Fun,As,Lc};
+expr({'catch',Line,E0}, _Lc) ->
%% No new variables added.
- E1 = expr(E0),
+ E1 = expr(E0, false),
{'catch',Line,E1};
-expr({'try',Line,Es0,CaseCs0,CatchCs0,As0}) ->
+expr({'try',Line,Es0,CaseCs0,CatchCs0,As0}, Lc) ->
%% No new variables added.
Es = expr_list(Es0),
- CaseCs = icr_clauses(CaseCs0),
- CatchCs = icr_clauses(CatchCs0),
+ CaseCs = icr_clauses(CaseCs0, Lc),
+ CatchCs = icr_clauses(CatchCs0, Lc),
As = expr_list(As0),
{'try',Line,Es,CaseCs,CatchCs,As};
-expr({'query', Line, E0}) ->
- E = expr(E0),
- {'query', Line, E};
-expr({lc,Line,E0,Gs0}) -> %R8.
+expr({lc,Line,E0,Gs0}, _Lc) -> %R8.
Gs = lists:map(fun ({generate,L,P0,Qs}) ->
- {generate,L,expr(P0),expr(Qs)};
+ {generate,L,expr(P0, false),expr(Qs, false)};
({b_generate,L,P0,Qs}) -> %R12.
- {b_generate,L,expr(P0),expr(Qs)};
+ {b_generate,L,expr(P0, false),expr(Qs, false)};
(Expr) ->
- case is_guard_test(Expr) of
- true -> {guard,[[guard_test(Expr)]]};
- false -> expr(Expr)
+ case is_guard(Expr) of
+ true -> {guard,guard([[Expr]])};
+ false -> expr(Expr, false)
end
end, Gs0),
- {lc,Line,expr(E0),Gs};
-expr({bc,Line,E0,Gs0}) -> %R12.
+ {lc,Line,expr(E0, false),Gs};
+expr({bc,Line,E0,Gs0}, _Lc) -> %R12.
Gs = lists:map(fun ({generate,L,P0,Qs}) ->
- {generate,L,expr(P0),expr(Qs)};
+ {generate,L,expr(P0, false),expr(Qs, false)};
({b_generate,L,P0,Qs}) -> %R12.
- {b_generate,L,expr(P0),expr(Qs)};
+ {b_generate,L,expr(P0, false),expr(Qs, false)};
(Expr) ->
- case is_guard_test(Expr) of
- true -> {guard,[[guard_test(Expr)]]};
- false -> expr(Expr)
+ case is_guard(Expr) of
+ true -> {guard,guard([[Expr]])};
+ false -> expr(Expr, false)
end
end, Gs0),
- {bc,Line,expr(E0),Gs};
-expr({match,Line,P0,E0}) ->
- E1 = expr(E0),
+ {bc,Line,expr(E0, false),Gs};
+expr({match,Line,P0,E0}, _Lc) ->
+ E1 = expr(E0, false),
P1 = pattern(P0),
{match,Line,P1,E1};
-expr({op,Line,Op,A0}) ->
- A1 = expr(A0),
+expr({op,Line,Op,A0}, _Lc) ->
+ A1 = expr(A0, false),
{op,Line,Op,[A1]};
-expr({op,Line,'++',L0,R0}) ->
- L1 = expr(L0),
- R1 = expr(R0), %They see the same variables
+expr({op,Line,'++',L0,R0}, _Lc) ->
+ L1 = expr(L0, false),
+ R1 = expr(R0, false), %They see the same variables
{op,Line,append,[L1,R1]};
-expr({op,Line,'--',L0,R0}) ->
- L1 = expr(L0),
- R1 = expr(R0), %They see the same variables
+expr({op,Line,'--',L0,R0}, _Lc) ->
+ L1 = expr(L0, false),
+ R1 = expr(R0, false), %They see the same variables
{op,Line,subtract,[L1,R1]};
-expr({op,Line,'!',L0,R0}) ->
- L1 = expr(L0),
- R1 = expr(R0), %They see the same variables
+expr({op,Line,'!',L0,R0}, _Lc) ->
+ L1 = expr(L0, false),
+ R1 = expr(R0, false), %They see the same variables
{send,Line,L1,R1};
-expr({op,Line,Op,L0,R0}) when Op =:= 'andalso'; Op =:= 'orelse' ->
- L1 = expr(L0),
- R1 = expr(R0), %They see the same variables
+expr({op,Line,Op,L0,R0}, _Lc) when Op =:= 'andalso'; Op =:= 'orelse' ->
+ L1 = expr(L0, false),
+ R1 = expr(R0, false), %They see the same variables
{Op,Line,L1,R1};
-expr({op,Line,Op,L0,R0}) ->
- L1 = expr(L0),
- R1 = expr(R0), %They see the same variables
+expr({op,Line,Op,L0,R0}, _Lc) ->
+ L1 = expr(L0, false),
+ R1 = expr(R0, false), %They see the same variables
{op,Line,Op,[L1,R1]};
-expr({bin,Line,Grp}) ->
+expr({bin,Line,Grp}, _Lc) ->
Grp1 = expr_list(Grp),
{bin,Line,Grp1};
-expr({bin_element,Line,Expr,Size,Type}) ->
- Expr1 = expr(Expr),
- Size1 = expr(Size),
+expr({bin_element,Line,Expr,Size,Type}, _Lc) ->
+ Expr1 = expr(Expr, false),
+ Size1 = expr(Size, false),
{bin_element,Line,Expr1,Size1,Type};
-expr(Other) ->
+expr(Other, _Lc) ->
exit({?MODULE,{unknown_expr,Other}}).
-%% is_guard_test(Expression) -> true | false.
-%% Test if a general expression is a guard test. Cannot use erl_lint
-%% here as sys_pre_expand has transformed source.
+%% is_guard(Expression) -> true | false.
+%% Test if a general expression is a guard test or guard BIF.
+%% Cannot use erl_lint here as sys_pre_expand has transformed source.
-is_guard_test({op,_,Op,L,R}) ->
+is_guard({op,_,Op,L,R}) ->
erl_internal:comp_op(Op, 2) andalso is_gexpr_list([L,R]);
-is_guard_test({call,_,{remote,_,{atom,_,erlang},{atom,_,Test}},As}) ->
- erl_internal:type_test(Test, length(As)) andalso is_gexpr_list(As);
-is_guard_test({atom,_,true}) -> true;
-is_guard_test(_) -> false.
+is_guard({call,_,{remote,_,{atom,_,erlang},{atom,_,Test}},As}) ->
+ Arity = length(As),
+ (erl_internal:guard_bif(Test, Arity) orelse
+ erl_internal:old_type_test(Test, Arity)) andalso is_gexpr_list(As);
+is_guard({atom,_,true}) -> true;
+is_guard(_) -> false.
is_gexpr({var,_,_}) -> true;
is_gexpr({atom,_,_}) -> true;
@@ -555,17 +526,17 @@ consify([]) -> {value,0,[]}.
%% definition etc.
expr_list([E0|Es]) ->
- E1 = expr(E0),
+ E1 = expr(E0, false),
[E1|expr_list(Es)];
expr_list([]) -> [].
-icr_clauses([C0|Cs]) ->
- C1 = clause(C0),
- [C1|icr_clauses(Cs)];
-icr_clauses([]) -> [].
+icr_clauses([C0|Cs], Lc) ->
+ C1 = clause(C0, Lc),
+ [C1|icr_clauses(Cs, Lc)];
+icr_clauses([], _) -> [].
fun_clauses([{clause,L,H,G,B}|Cs]) ->
- [{clause,L,head(H),guard(G),exprs(B)}|fun_clauses(Cs)];
+ [{clause,L,head(H),guard(G),exprs(B, true)}|fun_clauses(Cs)];
fun_clauses([]) -> [].
%% new_var_name() -> VarName.
@@ -585,24 +556,21 @@ new_vars(N, L, Vs) when N > 0 ->
new_vars(N-1, L, [V|Vs]);
new_vars(0, _, Vs) -> Vs.
-bif_type(erlang, Name) -> bif_type(Name);
-bif_type(_, _) -> unsafe.
+bif_type(erlang, Name, Arity) ->
+ case erl_internal:guard_bif(Name, Arity) of
+ true ->
+ %% Guard BIFs are safe (except for self/0, but it is
+ %% handled with a special instruction anyway).
+ safe;
+ false ->
+ bif_type(Name)
+ end;
+bif_type(_, _, _) -> unsafe.
bif_type(register) -> safe;
bif_type(unregister) -> safe;
bif_type(whereis) -> safe;
bif_type(registered) -> safe;
-bif_type(abs) -> safe;
-bif_type(float) -> safe;
-bif_type(trunc) -> safe;
-bif_type(round) -> safe;
-bif_type(math) -> safe;
-bif_type(node) -> safe;
-bif_type(length) -> safe;
-bif_type(hd) -> safe;
-bif_type(tl) -> safe;
-bif_type(size) -> safe;
-bif_type(element) -> safe;
bif_type(setelement) -> safe;
bif_type(atom_to_list) -> safe;
bif_type(list_to_atom) -> safe;
@@ -627,22 +595,14 @@ bif_type(list_to_pid) -> safe;
bif_type(module_loaded) -> safe;
bif_type(binary_to_term) -> safe;
bif_type(term_to_binary) -> safe;
-bif_type(alive) -> safe;
-bif_type(notalive) -> safe;
bif_type(nodes) -> safe;
bif_type(is_alive) -> safe;
bif_type(disconnect_node) -> safe;
bif_type(binary_to_list) -> safe;
bif_type(list_to_binary) -> safe;
bif_type(split_binary) -> safe;
-bif_type(concat_binary) -> safe;
-bif_type(term_to_atom) -> safe;
bif_type(hash) -> safe;
bif_type(pre_loaded) -> safe;
-bif_type(info) -> safe;
bif_type(set_cookie) -> safe;
bif_type(get_cookie) -> safe;
-bif_type(spawn) -> spawn;
-bif_type(spawn_link) -> spawn;
-bif_type(spawn_opt) -> spawn;
bif_type(_) -> unsafe.
diff --git a/lib/debugger/src/dbg_iserver.erl b/lib/debugger/src/dbg_iserver.erl
index 212bc2b8ab..1bb73a43b9 100644
--- a/lib/debugger/src/dbg_iserver.erl
+++ b/lib/debugger/src/dbg_iserver.erl
@@ -97,13 +97,10 @@ ensure_started() ->
%%
%% Key Value
%% --- -----
-%% attributes Attr
-%% exports Exp
%% defs []
%% mod_bin Binary
%% mod_raw Raw Binary
%% mod_file File
-%% module Mod
%% {Mod,Name,Arity,Exported} Cs
%% {'fun',Mod,Index,Uniq} {Name,Arity,Cs}
%% Line {Pos,PosNL}
@@ -117,7 +114,7 @@ init([]) ->
process_flag(trap_exit, true),
global:register_name(?MODULE, self()),
Db = ets:new(?MODULE, [ordered_set, protected]),
- {ok, #state{db=Db, auto=false, stack=all}}.
+ {ok, #state{db=Db, auto=false, stack=no_tail}}.
%% Attaching to a process
handle_call({attached, AttPid, Pid}, _From, State) ->
diff --git a/lib/debugger/src/dbg_istk.erl b/lib/debugger/src/dbg_istk.erl
new file mode 100644
index 0000000000..c6922a80e4
--- /dev/null
+++ b/lib/debugger/src/dbg_istk.erl
@@ -0,0 +1,245 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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_istk).
+-export([init/0,delayed_to_external/0,from_external/1,
+ push/3,pop/0,pop/1,stack_level/0,
+ delayed_stacktrace/0,delayed_stacktrace/2,
+ bindings/1,stack_frame/2,backtrace/2,
+ in_use_p/2]).
+
+-include("dbg_ieval.hrl").
+
+-define(STACK, ?MODULE).
+
+-record(e,
+ {level, %Level
+ mfa, %{Mod,Func,Args|Arity}|{Fun,Args}
+ line, %Line called from
+ bindings,
+ lc %Last call (true|false)
+ }).
+
+init() ->
+ init([]).
+
+delayed_to_external() ->
+ Stack = get(?STACK),
+ fun() -> {stack,term_to_binary(Stack)} end.
+
+from_external({stack,Stk}) ->
+ put(?STACK, binary_to_term(Stk)).
+
+init(Stack) ->
+ put(?STACK, Stack).
+
+%% We keep track of a call stack that is used for
+%% 1) saving stack frames that can be inspected from an Attached
+%% Process GUI (using dbg_icmd:get(Meta, stack_frame, {Dir, SP})
+%% 2) generate an approximation of regular stacktrace -- sent to
+%% Debugged when it should raise an exception or evaluate a
+%% function (since it might possible raise an exception)
+%%
+%% How to push depends on the "Stack Trace" option (value saved in
+%% process dictionary item 'trace_stack').
+%% all - everything is pushed
+%% no_tail - tail recursive push
+%% false - nothing is pushed
+%% Whenever a function returns, the corresponding call frame is popped.
+
+push(Bs, #ieval{level=Le,module=Mod,function=Name,
+ arguments=As,line=Li}=Ieval, Lc) ->
+ Entry = #e{level=Le,mfa={Mod,Name,As},line=Li,bindings=Bs,lc=Lc},
+ case get(trace_stack) of
+ false ->
+ Ieval#ieval{level=Le+1};
+ no_tail when Lc ->
+ Ieval;
+ _ -> % all | no_tail when Lc =:= false
+ put(?STACK, [Entry|get(?STACK)]),
+ Ieval#ieval{level=Le+1}
+ end.
+
+pop() ->
+ case get(trace_stack) of
+ false -> ignore;
+ _ -> % all ¦ no_tail
+ case get(?STACK) of
+ [_Entry|Entries] ->
+ put(?STACK, Entries);
+ [] ->
+ ignore
+ end
+ end.
+
+pop(Le) ->
+ case get(trace_stack) of
+ false -> ignore;
+ _ -> % all | no_tail
+ put(?STACK, pop(Le, get(?STACK)))
+ end.
+
+pop(Level, [#e{level=Le}|Stack]) when Level =< Le ->
+ pop(Level, Stack);
+pop(_Level, Stack) ->
+ Stack.
+
+%% stack_level() -> Le
+%% stack_level(Stack) -> Le
+%% Top call level
+stack_level() ->
+ stack_level(get(?STACK)).
+
+stack_level([]) -> 1;
+stack_level([#e{level=Le}|_]) -> Le.
+
+%% delayed_stacktrace() -> CreateStacktraceFun
+%% delayed_stacktrace(ArgFlag, #ieval{}) -> CreateStacktraceFun
+%% ArgFlag = no_args | include_args
+%% CreateStacktraceFun = fun(NumberOfEntries)
+%%
+%% Return a fun that can convert the internal stack format to
+%% an imitation of the regular stacktrace.
+
+delayed_stacktrace() ->
+ Stack0 = get(?STACK),
+ fun(NumEntries) ->
+ Stack = stacktrace(NumEntries, Stack0, []),
+ [finalize(ArityOnly) || {ArityOnly,_} <- Stack]
+ end.
+
+delayed_stacktrace(include_args, Ieval) ->
+ #ieval{module=Mod,function=Name,arguments=As,line=Li} = Ieval,
+ Stack0 = [#e{mfa={Mod,Name,As},line=Li}|get(?STACK)],
+ fun(NumEntries) ->
+ case stacktrace(NumEntries, Stack0, []) of
+ [] ->
+ [];
+ [{_,WithArgs}|Stack] ->
+ [finalize(WithArgs) |
+ [finalize(ArityOnly) || {ArityOnly,_} <- Stack]]
+ end
+ end;
+delayed_stacktrace(no_args, Ieval) ->
+ #ieval{module=Mod,function=Name,arguments=As,line=Li} = Ieval,
+ Stack0 = [#e{mfa={Mod,Name,As},line=Li}|get(?STACK)],
+ fun(NumEntries) ->
+ Stack = stacktrace(NumEntries, Stack0, []),
+ [finalize(ArityOnly) || {ArityOnly,_} <- Stack]
+ end.
+
+stacktrace(N, [#e{lc=true}|T], Acc) ->
+ stacktrace(N, T, Acc);
+stacktrace(N, [E|T], []) ->
+ stacktrace(N-1, T, [normalize(E)]);
+stacktrace(N, [E|T], [{P,_}|_]=Acc) when N > 0 ->
+ case normalize(E) of
+ {P,_} ->
+ stacktrace(N, T, Acc);
+ New ->
+ stacktrace(N-1, T, [New|Acc])
+ end;
+stacktrace(_, _, Acc) ->
+ lists:reverse(Acc).
+
+normalize(#e{mfa={M,Fun,As},line=Li}) when is_function(Fun) ->
+ Loc = {M,Li},
+ {{Fun,length(As),Loc},{Fun,As,Loc}};
+normalize(#e{mfa={M,F,As},line=Li}) ->
+ Loc = {M,Li},
+ {{M,F,length(As),Loc},{M,F,As,Loc}}.
+
+finalize({M,F,A,Loc}) -> {M,F,A,line(Loc)};
+finalize({Fun,A,Loc}) -> {Fun,A,line(Loc)}.
+
+line({Mod,Line}) when Line > 0 ->
+ [{file,atom_to_list(Mod)++".erl"},{line,Line}];
+line(_) -> [].
+
+%% bindings(SP) -> Bs
+%% SP = Le % stack pointer
+%% Return the bindings for the specified call level
+bindings(SP) ->
+ bindings(SP, get(?STACK)).
+
+bindings(SP, [#e{level=SP,bindings=Bs}|_]) ->
+ Bs;
+bindings(SP, [_Entry|Entries]) ->
+ bindings(SP, Entries);
+bindings(_SP, []) ->
+ erl_eval:new_bindings().
+
+%% stack_frame(Dir, SP) -> {Le, Where, Bs} | top | bottom
+%% Dir = up | down
+%% Where = {Cm, Li}
+%% Cm = Module | undefined % module
+%% Li = int() | -1 % line number
+%% Bs = bindings()
+%% Return stack frame info one step up/down from given stack pointer
+%% up = to lower call levels
+%% down = to higher call levels
+stack_frame(up, SP) ->
+ stack_frame(SP, up, get(?STACK));
+stack_frame(down, SP) ->
+ stack_frame(SP, down, lists:reverse(get(?STACK))).
+
+stack_frame(SP, up, [#e{level=Le,mfa={Cm,_,_},line=Li,bindings=Bs}|_])
+ when Le < SP ->
+ {Le,{Cm,Li},Bs};
+stack_frame(SP, down, [#e{level=Le,mfa={Cm,_,_},line=Li,bindings=Bs}|_])
+ when Le > SP ->
+ {Le,{Cm,Li},Bs};
+stack_frame(SP, Dir, [#e{level=SP}|Stack]) ->
+ case Stack of
+ [#e{level=Le,mfa={Cm,_,_},line=Li,bindings=Bs}|_] ->
+ {Le,{Cm,Li},Bs};
+ [] when Dir =:= up ->
+ top;
+ [] when Dir =:= down ->
+ bottom
+ end;
+stack_frame(SP, Dir, [_Entry|Stack]) ->
+ stack_frame(SP, Dir, Stack).
+
+%% backtrace(HowMany) -> Backtrace
+%% HowMany = all | int()
+%% Backtrace = {Le, MFA}
+%% Return all/the last N called functions, in reversed call order
+backtrace(HowMany, Ieval) ->
+ #ieval{level=Level,module=Mod,function=Name,arguments=As} = Ieval,
+ Stack0 = [#e{level=Level,mfa={Mod,Name,As}}|get(?STACK)],
+ Stack = case HowMany of
+ all -> Stack0;
+ N -> lists:sublist(Stack0, N)
+ end,
+ [{Le,MFA} || #e{level=Le,mfa=MFA} <- Stack].
+
+%%--------------------------------------------------------------------
+%% in_use_p(Mod, Cm) -> boolean()
+%% Mod = Cm = atom()
+%% Returns true if Mod is found on the stack, otherwise false.
+%%--------------------------------------------------------------------
+in_use_p(Mod, Mod) -> true;
+in_use_p(Mod, _Cm) ->
+ case get(trace_stack) of
+ false -> true;
+ _ -> % all | no_tail
+ lists:any(fun(#e{mfa={M,_,_}}) when M =:= Mod -> true;
+ (_) -> false
+ end, get(?STACK))
+ end.
diff --git a/lib/debugger/src/debugger.app.src b/lib/debugger/src/debugger.app.src
index 21cf59a2e1..5538f66260 100644
--- a/lib/debugger/src/debugger.app.src
+++ b/lib/debugger/src/debugger.app.src
@@ -26,6 +26,7 @@
dbg_ieval,
dbg_iload,
dbg_iserver,
+ dbg_istk,
dbg_ui_break,
dbg_ui_break_win,
dbg_ui_edit,
diff --git a/lib/debugger/test/Makefile b/lib/debugger/test/Makefile
index 4409cd2b38..3dfbed31ff 100644
--- a/lib/debugger/test/Makefile
+++ b/lib/debugger/test/Makefile
@@ -43,6 +43,7 @@ MODULES= \
exception_SUITE \
fun_SUITE \
lc_SUITE \
+ line_number_SUITE \
record_SUITE \
trycatch_SUITE \
test_lib \
@@ -100,7 +101,7 @@ release_tests_spec: make_emakefile
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(RELSYSDIR)
$(INSTALL_DATA) debugger.spec debugger.cover $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/debugger/test/bs_construct_SUITE.erl b/lib/debugger/test/bs_construct_SUITE.erl
index 5c7d49e951..187c9f53b0 100644
--- a/lib/debugger/test/bs_construct_SUITE.erl
+++ b/lib/debugger/test/bs_construct_SUITE.erl
@@ -19,18 +19,31 @@
-module(bs_construct_SUITE).
+%% Copied from bs_construct_SUITE in the emulator test suite.
+%% The following test cases have been omitted since they don't
+%% make much sense for the debugger:
+%% bs_add
+%% kostis
+
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
init_per_suite/1,end_per_suite/1,
- test1/1, test2/1, test3/1, test4/1, test5/1, testf/1, not_used/1, in_guard/1,
- coerce_to_float/1]).
+ test1/1, test2/1, test3/1, test4/1, test5/1, testf/1,
+ not_used/1, in_guard/1,
+ mem_leak/1, coerce_to_float/1, bjorn/1,
+ huge_float_field/1, huge_binary/1, system_limit/1, badarg/1,
+ copy_writable_binary/1, dynamic/1,
+ otp_7422/1, zero_width/1]).
-include_lib("test_server/include/test_server.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- cases().
+ [test1, test2, test3, test4, test5, testf, not_used,
+ in_guard, mem_leak, coerce_to_float, bjorn,
+ huge_float_field, huge_binary, system_limit, badarg,
+ copy_writable_binary, dynamic, otp_7422, zero_width].
groups() ->
[].
@@ -41,11 +54,6 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-
-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)),
@@ -75,7 +83,9 @@ r(L) ->
-define(T(B, L), {B, ??B, L}).
-define(N(B), {B, ??B, unknown}).
--define(FAIL(Expr), ?line {'EXIT',{badarg,_}} = (catch Expr)).
+-define(FAIL(Expr), ?line fail_check(catch Expr, ??Expr, [])).
+
+-define(FAIL_VARS(Expr, Vars), ?line fail_check(catch Expr, ??Expr, Vars)).
l(I_13, I_big1) ->
[
@@ -143,7 +153,13 @@ l(I_13, I_big1) ->
native_3798()),
?T(<<32978297842987249827298387697777669766334937:128/native-integer>>,
- native_bignum())
+ native_bignum()),
+
+ %% Unit tests.
+ ?T(<<<<5:3>>/bitstring>>, <<5:3>>),
+ ?T(<<42,<<7:4>>/binary-unit:4>>, <<42,7:4>>),
+ ?T(<<<<344:17>>/binary-unit:17>>, <<344:17>>),
+ ?T(<<<<42,3,7656:16>>/binary-unit:16>>, <<42,3,7656:16>>)
].
@@ -179,7 +195,7 @@ eval_list([{C_bin, Str, Bytes} | Rest], Vars) ->
[{C_bin, E_bin, Str, Bytes} | eval_list(Rest, Vars)]
end.
-one_test({C_bin, E_bin, Str, Bytes}) when list(Bytes) ->
+one_test({C_bin, E_bin, Str, Bytes}) when is_list(Bytes) ->
io:format(" ~s, ~p~n", [Str, Bytes]),
Bin = list_to_binary(Bytes),
if
@@ -222,7 +238,7 @@ one_test({C_bin, E_bin, Str, Result}) ->
ok;
%% For situations where the final bits may not matter, like
%% for floats:
- N when integer(N) ->
+ N when is_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)]),
@@ -248,9 +264,22 @@ equal_lists(A, B, R) ->
false
end.
+fail_check({'EXIT',{badarg,_}}, Str, Vars) ->
+ try evaluate(Str, Vars) of
+ Res ->
+ io:format("Interpreted result: ~p", [Res]),
+ ?t:fail(did_not_fail_in_intepreted_code)
+ catch
+ error:badarg ->
+ ok
+ end;
+fail_check(Res, _, _) ->
+ io:format("Compiled result: ~p", [Res]),
+ ?t:fail(did_not_fail_in_compiled_code).
+
%%% Simple working cases
test1(suite) -> [];
-test1(Config) when list(Config) ->
+test1(Config) when is_list(Config) ->
?line I_13 = i(13),
?line I_big1 = big(1),
?line Vars = [{'I_13', I_13},
@@ -272,7 +301,7 @@ gen_l(N, S, A) ->
[?T(<<A:S/little, A:(N-S)/little>>, comp(N, A, S))].
test2(suite) -> [];
-test2(Config) when list(Config) ->
+test2(Config) when is_list(Config) ->
?line test2(0, 8, 2#10101010101010101),
?line test2(0, 8, 2#1111111111).
@@ -300,7 +329,7 @@ t3() ->
].
test3(suite) -> [];
-test3(Config) when list(Config) ->
+test3(Config) when is_list(Config) ->
?line Vars = [],
?line lists:foreach(fun one_test/1, eval_list(t3(), Vars)).
@@ -311,7 +340,7 @@ gen_u_l(N, S, A) ->
[?N(<<A:S/little, A:(N-S)/little>>)].
test4(suite) -> [];
-test4(Config) when list(Config) ->
+test4(Config) when is_list(Config) ->
?line test4(0, 16, 2#10101010101010101),
?line test4(0, 16, 2#1111111111).
@@ -333,7 +362,7 @@ gen_b(N, S, A) ->
test5(suite) -> [];
test5(doc) -> ["OTP-3995"];
-test5(Config) when list(Config) ->
+test5(Config) when is_list(Config) ->
?line test5(0, 8, <<73>>),
?line test5(0, 8, <<68>>).
@@ -350,40 +379,63 @@ test5(S, A) ->
%%% 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>>),
+testf(Config) when is_list(Config) ->
+ ?line ?FAIL(<<3.14>>),
+ ?line ?FAIL(<<<<1,2>>>>),
+
+ ?line ?FAIL(<<2.71/binary>>),
+ ?line ?FAIL(<<24334/binary>>),
+ ?line ?FAIL(<<24334344294788947129487129487219847/binary>>),
+ BigInt = id(24334344294788947129487129487219847),
+ ?line ?FAIL_VARS(<<BigInt/binary>>, [{'BigInt',BigInt}]),
+ ?line ?FAIL_VARS(<<42,BigInt/binary>>, [{'BigInt',BigInt}]),
+ ?line ?FAIL_VARS(<<BigInt:2/binary>>, [{'BigInt',BigInt}]),
+
+ %% One negative field size, but the sum of field sizes will be 1 byte.
+ %% Make sure that we reject that properly.
+ I_minus_777 = id(-777),
+ I_minus_2047 = id(-2047),
+ ?line ?FAIL_VARS(<<I_minus_777:2048/unit:8,57:I_minus_2047/unit:8>>,
+ ordsets:from_list([{'I_minus_777',I_minus_777},
+ {'I_minus_2047',I_minus_2047}])),
+ ?line ?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)>>),
+ ?line testf_1(-8, <<1,2,3,4,5>>),
+ ?line ?FAIL(<<0:(-(1 bsl 100))>>),
+
+ ?line ?FAIL(<<42:(-16)>>),
+ ?line ?FAIL(<<3.14:(-8)/float>>),
+ ?line ?FAIL(<<<<23,56,0,2>>:(-16)/binary>>),
+ ?line ?FAIL(<<<<23,56,0,2>>:(2.5)/binary>>),
+ ?line ?FAIL(<<<<23,56,0,2>>:(anka)>>),
+ ?line ?FAIL(<<<<23,56,0,2>>:(anka)>>),
+
+ %% Unit failures.
+ ?line ?FAIL(<<<<1:1>>/binary>>),
+ Sz = id(1),
+ ?line ?FAIL_VARS(<<<<1:Sz>>/binary>>, [{'Sz',Sz}]),
+ ?line {'EXIT',{badarg,_}} = (catch <<<<1:(id(1))>>/binary>>),
+ ?line ?FAIL(<<<<7,8,9>>/binary-unit:16>>),
+ ?line ?FAIL(<<<<7,8,9,3:7>>/binary-unit:16>>),
+ ?line ?FAIL(<<<<7,8,9,3:7>>/binary-unit:17>>),
ok.
testf_1(W, B) ->
- ?FAIL(<<42:W>>),
- ?FAIL(<<3.14:W/float>>),
- ?FAIL(<<B:W/binary>>).
+ Vars = [{'W',W}],
+ ?FAIL_VARS(<<42:W>>, Vars),
+ ?FAIL_VARS(<<3.14:W/float>>, Vars),
+ ?FAIL_VARS(<<B:W/binary>>, [{'B',B}|Vars]).
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)),
+ ?line {'EXIT',{badarg,_}} = (catch not_used1(3, "dum")),
+ ?line {'EXIT',{badarg,_}} = (catch not_used2(444, -2)),
+ ?line {'EXIT',{badarg,_}} = (catch not_used2(444, anka)),
+ ?line {'EXIT',{badarg,_}} = (catch not_used3(444)),
ok.
not_used1(I, BinString) ->
@@ -398,7 +450,7 @@ not_used3(I) ->
<<I:(-8)>>,
ok.
-in_guard(Config) when list(Config) ->
+in_guard(Config) when is_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),
@@ -415,6 +467,36 @@ 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.
+mem_leak(doc) -> "Make sure that construction has no memory leak";
+mem_leak(Config) when is_list(Config) ->
+ ?line B = make_bin(16, <<0>>),
+ ?line mem_leak(1024, B),
+ ok.
+
+mem_leak(0, _) -> ok;
+mem_leak(N, B) ->
+ ?line big_bin(B, <<23>>),
+ ?line {'EXIT',{badarg,_}} = (catch big_bin(B, bad)),
+ maybe_gc(),
+ mem_leak(N-1, B).
+
+big_bin(B1, B2) ->
+ <<B1/binary,B1/binary,B1/binary,B1/binary,
+ B1/binary,B1/binary,B1/binary,B1/binary,
+ B1/binary,B1/binary,B1/binary,B1/binary,
+ B1/binary,B1/binary,B1/binary,B1/binary,
+ B2/binary>>.
+
+make_bin(0, Acc) -> Acc;
+make_bin(N, Acc) -> make_bin(N-1, <<Acc/binary,Acc/binary>>).
+
+maybe_gc() ->
+ case erlang:system_info(heap_type) of
+ shared -> erlang:garbage_collect();
+ hybrid -> erlang:garbage_collect();
+ private -> ok
+ end.
+
-define(COF(Int0),
?line (fun(Int) ->
true = <<Int:32/float>> =:= <<(float(Int)):32/float>>,
@@ -431,7 +513,7 @@ in_guard(_, _, _) -> nope.
nonliteral(X) -> X.
-coerce_to_float(Config) when list(Config) ->
+coerce_to_float(Config) when is_list(Config) ->
?COF(0),
?COF(-1),
?COF(1),
@@ -444,3 +526,232 @@ coerce_to_float(Config) when list(Config) ->
?COF64(298748888888888888888888888883478264866528467367364766666666666666663),
?COF64(-367546729879999999999947826486652846736736476555566666663),
ok.
+
+bjorn(Config) when is_list(Config) ->
+ ?line error = bjorn_1(),
+ ok.
+
+bjorn_1() ->
+ Bitstr = <<7:13>>,
+ try
+ do_something()
+ catch
+ throw:blurf ->
+ ignore
+ end,
+ do_more(Bitstr, 13).
+
+do_more(Bin, Sz) ->
+ %% Previous bug in the bs_bits_to_bytes instruction: The exeption code
+ %% was not set - the previous exception (throw:blurf) would be used,
+ %% causing the catch to slip.
+ try <<Bin:Sz/binary>> of
+ _V -> ok
+ catch
+ error:_ ->
+ error
+ end.
+
+do_something() ->
+ throw(blurf).
+
+huge_float_field(Config) when is_list(Config) ->
+ ?line {'EXIT',{badarg,_}} = (catch <<0.0:9/float-unit:8>>),
+ ?line huge_float_check(catch <<0.0:67108865/float-unit:64>>),
+ ?line huge_float_check(catch <<0.0:((1 bsl 26)+1)/float-unit:64>>),
+ ?line huge_float_check(catch <<0.0:(id(67108865))/float-unit:64>>),
+%% ?line huge_float_check(catch <<0.0:((1 bsl 60)+1)/float-unit:64>>),
+ ?line huge_float_check(catch <<3839739387439387383739387987347983:((1 bsl 26)+1)/float-unit:64>>),
+%% ?line huge_float_check(catch <<3839739387439387383739387987347983:((1 bsl 60)+1)/float-unit:64>>),
+ ok.
+
+huge_float_check({'EXIT',{system_limit,_}}) -> ok;
+huge_float_check({'EXIT',{badarg,_}}) -> ok.
+
+huge_binary(Config) when is_list(Config) ->
+ ?line 16777216 = size(<<0:(id(1 bsl 26)),(-1):(id(1 bsl 26))>>),
+ ok.
+
+system_limit(Config) when is_list(Config) ->
+ WordSize = erlang:system_info(wordsize),
+ BitsPerWord = WordSize * 8,
+ ?line {'EXIT',{system_limit,_}} =
+ (catch <<0:(id(0)),42:(id(1 bsl BitsPerWord))>>),
+ ?line {'EXIT',{system_limit,_}} =
+ (catch <<42:(id(1 bsl BitsPerWord)),0:(id(0))>>),
+ ?line {'EXIT',{system_limit,_}} =
+ (catch <<(id(<<>>))/binary,0:(id(1 bsl 100))>>),
+
+ case WordSize of
+ 4 ->
+ system_limit_32();
+ 8 ->
+ ok
+ end.
+
+system_limit_32() ->
+ ?line {'EXIT',{badarg,_}} = (catch <<42:(-1)>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<42:(id(-1))>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<42:(id(-389739873536870912))/unit:8>>),
+ ?line {'EXIT',{system_limit,_}} = (catch <<42:536870912/unit:8>>),
+ ?line {'EXIT',{system_limit,_}} = (catch <<42:(id(536870912))/unit:8>>),
+ ?line {'EXIT',{system_limit,_}} = (catch <<0:(id(8)),42:536870912/unit:8>>),
+ ?line {'EXIT',{system_limit,_}} =
+ (catch <<0:(id(8)),42:(id(536870912))/unit:8>>),
+ ok.
+
+badarg(Config) when is_list(Config) ->
+ %% BEAM will generate a badarg exception for:
+ %% <<0:(id(1 bsl 100)),0:(id(-1))>>
+ %% but the debugger will generate a system_limit exception.
+ %% It does not seems worthwhile to fix the debugger.
+
+ ?line {'EXIT',{badarg,_}} =
+ (catch <<(id(<<>>))/binary,0:(id(-(1 bsl 100)))>>),
+
+ ok.
+
+copy_writable_binary(Config) when is_list(Config) ->
+ ?line [copy_writable_binary_1(I) || I <- lists:seq(0, 256)],
+ ok.
+
+copy_writable_binary_1(_) ->
+ ?line Bin0 = <<(id(<<>>))/binary,0,1,2,3,4,5,6,7>>,
+ ?line SubBin = make_sub_bin(Bin0),
+ ?line id(<<42,34,55,Bin0/binary>>), %Make reallocation likelier.
+ ?line Pid = spawn(fun() ->
+ copy_writable_binary_holder(Bin0, SubBin)
+ end),
+ ?line Tab = ets:new(holder, []),
+ ?line ets:insert(Tab, {17,Bin0}),
+ ?line ets:insert(Tab, {42,SubBin}),
+ ?line id(<<Bin0/binary,0:(64*1024*8)>>),
+ ?line Pid ! self(),
+ ?line [{17,Bin0}] = ets:lookup(Tab, 17),
+ ?line [{42,Bin0}] = ets:lookup(Tab, 42),
+ receive
+ {Pid,Bin0,Bin0} -> ok;
+ Other ->
+ io:format("Unexpected message: ~p", [Other]),
+ ?line ?t:fail()
+ end,
+ ok.
+
+copy_writable_binary_holder(Bin, SubBin) ->
+ receive
+ Pid ->
+ Pid ! {self(),Bin,SubBin}
+ end.
+
+make_sub_bin(Bin0) ->
+ N = bit_size(Bin0),
+ <<_:17,Bin:N/bitstring,_:5>> = <<(-1):17,Bin0/bitstring,(-1):5>>,
+ Bin = Bin0, %Assertion.
+ Bin.
+
+%% Test that different ways of using bit syntax instructions
+%% give the same result.
+
+dynamic(Config) when is_list(Config) ->
+ ?line dynamic_1(fun dynamic_big/5),
+ ?line dynamic_1(fun dynamic_little/5),
+ ok.
+
+dynamic_1(Dynamic) ->
+ <<Lpad:128>> = erlang:md5([0]),
+ <<Rpad:128>> = erlang:md5([1]),
+ <<Int:128>> = erlang:md5([2]),
+ 8385 = dynamic_2(0, {Int,Lpad,Rpad,Dynamic}, 0).
+
+dynamic_2(129, _, Count) -> Count;
+dynamic_2(Bef, Data, Count0) ->
+ Count = dynamic_3(Bef, 128-Bef, Data, Count0),
+ dynamic_2(Bef+1, Data, Count).
+
+dynamic_3(_, -1, _, Count) -> Count;
+dynamic_3(Bef, N, {Int0,Lpad,Rpad,Dynamic}=Data, Count) ->
+ Int1 = Int0 band ((1 bsl (N+3))-1),
+ Dynamic(Bef, N, Int1, Lpad, Rpad),
+ Dynamic(Bef, N, -Int1, Lpad, Rpad),
+
+ %% OTP-7085: Test a small number in a wide field.
+ Int2 = Int0 band 16#FFFFFF,
+ Dynamic(Bef, N, Int2, Lpad, Rpad),
+ Dynamic(Bef, N, -Int2, Lpad, Rpad),
+ dynamic_3(Bef, N-1, Data, Count+1).
+
+dynamic_big(Bef, N, Int, Lpad, Rpad) ->
+ NumBin = id(<<Int:N>>),
+ MaskedInt = Int band ((1 bsl N) - 1),
+ <<MaskedInt:N>> = NumBin,
+
+ %% Construct the binary in two different ways.
+ Bin = id(<<Lpad:Bef,NumBin/bitstring,Rpad:(128-Bef-N)>>),
+ Bin = <<Lpad:Bef,Int:N,Rpad:(128-Bef-N)>>,
+
+ %% Further verify the result by matching.
+ LpadMasked = Lpad band ((1 bsl Bef) - 1),
+ RpadMasked = Rpad band ((1 bsl (128-Bef-N)) - 1),
+ Rbits = (128-Bef-N),
+ <<LpadMasked:Bef,MaskedInt:N,RpadMasked:Rbits>> = id(Bin),
+ ok.
+
+dynamic_little(Bef, N, Int, Lpad, Rpad) ->
+ NumBin = id(<<Int:N/little>>),
+ MaskedInt = Int band ((1 bsl N) - 1),
+ <<MaskedInt:N/little>> = NumBin,
+
+ %% Construct the binary in two different ways.
+ Bin = id(<<Lpad:Bef/little,NumBin/bitstring,Rpad:(128-Bef-N)/little>>),
+ Bin = <<Lpad:Bef/little,Int:N/little,Rpad:(128-Bef-N)/little>>,
+
+ %% Further verify the result by matching.
+ LpadMasked = Lpad band ((1 bsl Bef) - 1),
+ RpadMasked = Rpad band ((1 bsl (128-Bef-N)) - 1),
+ Rbits = (128-Bef-N),
+ <<LpadMasked:Bef/little,MaskedInt:N/little,RpadMasked:Rbits/little>> = id(Bin),
+ ok.
+
+otp_7422(Config) when is_list(Config) ->
+ otp_7422_int(0),
+ otp_7422_bin(0).
+
+otp_7422_int(N) when N < 512 ->
+ T = erlang:make_tuple(N, []),
+ spawn_link(fun() ->
+ id(T),
+ %% A size of field 0 would write one byte beyond
+ %% the current position in the binary. It could
+ %% overwrite the continuation pointer stored on
+ %% the stack if HTOP was equal to E (the stack pointer).
+ id(<<0:(id(0))>>)
+ end),
+ otp_7422_int(N+1);
+otp_7422_int(_) -> ok.
+
+otp_7422_bin(N) when N < 512 ->
+ T = erlang:make_tuple(N, []),
+ Z = id(<<>>),
+ spawn_link(fun() ->
+ id(T),
+ id(<<Z:(id(0))/bits>>)
+ end),
+ otp_7422_bin(N+1);
+otp_7422_bin(_) -> ok.
+
+zero_width(Config) when is_list(Config) ->
+ ?line Z = id(0),
+ Small = id(42),
+ Big = id(1 bsl 128),
+ ?line <<>> = <<Small:Z>>,
+ ?line <<>> = <<Small:0>>,
+ ?line <<>> = <<Big:Z>>,
+ ?line <<>> = <<Big:0>>,
+
+ ?line {'EXIT',{badarg,_}} = (catch <<not_a_number:0>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<(id(not_a_number)):Z>>),
+ ?line {'EXIT',{badarg,_}} = (catch <<(id(not_a_number)):0>>),
+
+ ok.
+
+id(I) -> I.
diff --git a/lib/debugger/test/bs_match_bin_SUITE.erl b/lib/debugger/test/bs_match_bin_SUITE.erl
index b42b84aef2..5a7c30f16b 100644
--- a/lib/debugger/test/bs_match_bin_SUITE.erl
+++ b/lib/debugger/test/bs_match_bin_SUITE.erl
@@ -24,14 +24,14 @@
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
init_per_suite/1,end_per_suite/1,
- byte_split_binary/1,bit_split_binary/1]).
+ byte_split_binary/1,bit_split_binary/1,match_huge_bin/1]).
-include_lib("test_server/include/test_server.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- cases().
+ [byte_split_binary, bit_split_binary, match_huge_bin].
groups() ->
[].
@@ -42,10 +42,6 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-
-cases() ->
- [byte_split_binary, bit_split_binary].
-
init_per_testcase(_Case, Config) ->
test_lib:interpret(?MODULE),
Dog = test_server:timetrap(?t:minutes(1)),
@@ -65,11 +61,12 @@ end_per_suite(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) ->
+byte_split_binary(Config) when is_list(Config) ->
?line L = lists:seq(0, 57),
?line B = mkbin(L),
- ?line byte_split(L, B, size(B)).
+ ?line byte_split(L, B, size(B)),
+ ?line Unaligned = make_unaligned_sub_binary(B),
+ ?line byte_split(L, Unaligned, size(Unaligned)).
byte_split(L, B, Pos) when Pos >= 0 ->
?line Sz1 = Pos,
@@ -78,18 +75,19 @@ byte_split(L, B, Pos) when Pos >= 0 ->
?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.
+byte_split(_, _, _) -> ok.
bit_split_binary(doc) -> "Tries to split a binary at all positions.";
-bit_split_binary(suite) -> [];
-bit_split_binary(Config) when list(Config) ->
+bit_split_binary(Config) when is_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,
+ %%io:format("~p, ~p, ~p", [SkipBef,N,SkipAft]),
+ ?line <<_:SkipBef,OutBin:N/binary-unit:1,_:SkipAft>> = Bin,
?line OutBin = make_bin_from_list(List, N)
end,
?line bit_split_binary1(Fun, erlang:md5(<<1,2,3>>)),
+ ?line bit_split_binary1(Fun,
+ make_unaligned_sub_binary(erlang:md5(<<1,2,3>>))),
ok.
bit_split_binary1(Action, Bin) ->
@@ -99,24 +97,23 @@ bit_split_binary1(Action, Bin) ->
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_binary2(_, _, [], _) -> 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(_, 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(_, 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([_|T], 0) -> bits_to_list(T, 16#80);
bits_to_list([H|_]=List, Mask) ->
[case H band Mask of
0 -> 0;
@@ -124,5 +121,109 @@ bits_to_list([H|_]=List, Mask) ->
end|bits_to_list(List, Mask bsr 1)];
bits_to_list([], _) -> [].
+mkbin(L) when is_list(L) -> list_to_binary(L).
+
+make_unaligned_sub_binary(Bin0) ->
+ Bin1 = <<0:3,Bin0/binary,31:5>>,
+ Sz = size(Bin0),
+ <<0:3,Bin:Sz/binary,31:5>> = id(Bin1),
+ Bin.
+
+id(I) -> I.
+
+match_huge_bin(Config) when is_list(Config) ->
+ ?line Bin = <<0:(1 bsl 27),13:8>>,
+ ?line skip_huge_bin_1(1 bsl 27, Bin),
+ ?line 16777216 = match_huge_bin_1(1 bsl 27, Bin),
+
+ %% Test overflowing the size of a binary field.
+ ?line nomatch = overflow_huge_bin_skip_32(Bin),
+ ?line nomatch = overflow_huge_bin_32(Bin),
+ ?line nomatch = overflow_huge_bin_skip_64(Bin),
+ ?line nomatch = overflow_huge_bin_64(Bin),
+
+ %% Size in variable
+ ?line ok = overflow_huge_bin(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
+ ?line ok = overflow_huge_bin_unit128(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
+
+ ok.
+
+overflow_huge_bin(Bin, [Sz0|Sizes]) ->
+ Sz = id(1 bsl Sz0),
+ case Bin of
+ <<_:Sz/binary-unit:8,0,_/binary>> ->
+ {error,Sz};
+ _ ->
+ case Bin of
+ <<NewBin:Sz/binary-unit:8,0,_/binary>> ->
+ {error,Sz,size(NewBin)};
+ _ ->
+ overflow_huge_bin(Bin, Sizes)
+ end
+ end;
+overflow_huge_bin(_, []) -> ok.
+
+overflow_huge_bin_unit128(Bin, [Sz0|Sizes]) ->
+ Sz = id(1 bsl Sz0),
+ case Bin of
+ <<_:Sz/binary-unit:128,0,_/binary>> ->
+ {error,Sz};
+ _ ->
+ case Bin of
+ <<NewBin:Sz/binary-unit:128,0,_/binary>> ->
+ {error,Sz,size(NewBin)};
+ _ ->
+ overflow_huge_bin_unit128(Bin, Sizes)
+ end
+ end;
+overflow_huge_bin_unit128(_, []) -> ok.
+
+skip_huge_bin_1(I, Bin) ->
+ <<_:I/binary-unit:1,13>> = Bin,
+ ok.
-mkbin(L) when list(L) -> list_to_binary(L).
+match_huge_bin_1(I, Bin) ->
+ case Bin of
+ <<Val:I/binary-unit:1,13>> -> size(Val);
+ _ -> nomatch
+ end.
+
+overflow_huge_bin_skip_32(<<_:4294967296/binary,0,_/binary>>) -> 1; % 1 bsl 32
+overflow_huge_bin_skip_32(<<_:33554432/binary-unit:128,0,_/binary>>) -> 2; % 1 bsl 25
+overflow_huge_bin_skip_32(<<_:67108864/binary-unit:64,0,_/binary>>) -> 3; % 1 bsl 26
+overflow_huge_bin_skip_32(<<_:134217728/binary-unit:32,0,_/binary>>) -> 4; % 1 bsl 27
+overflow_huge_bin_skip_32(<<_:268435456/binary-unit:16,0,_/binary>>) -> 5; % 1 bsl 28
+overflow_huge_bin_skip_32(<<_:536870912/binary-unit:8,0,_/binary>>) -> 6; % 1 bsl 29
+overflow_huge_bin_skip_32(<<_:1073741824/binary-unit:8,0,_/binary>>) -> 7; % 1 bsl 30
+overflow_huge_bin_skip_32(<<_:2147483648/binary-unit:8,0,_/binary>>) -> 8; % 1 bsl 31
+overflow_huge_bin_skip_32(_) -> nomatch.
+
+overflow_huge_bin_32(<<Bin:4294967296/binary,_/binary>>) -> {1,Bin}; % 1 bsl 32
+overflow_huge_bin_32(<<Bin:33554432/binary-unit:128,0,_/binary>>) -> {2,Bin}; % 1 bsl 25
+overflow_huge_bin_32(<<Bin:67108864/binary-unit:128,0,_/binary>>) -> {3,Bin}; % 1 bsl 26
+overflow_huge_bin_32(<<Bin:134217728/binary-unit:128,0,_/binary>>) -> {4,Bin}; % 1 bsl 27
+overflow_huge_bin_32(<<Bin:268435456/binary-unit:128,0,_/binary>>) -> {5,Bin}; % 1 bsl 28
+overflow_huge_bin_32(<<Bin:536870912/binary-unit:128,0,_/binary>>) -> {6,Bin}; % 1 bsl 29
+overflow_huge_bin_32(<<Bin:1073741824/binary-unit:128,0,_/binary>>) -> {7,Bin}; % 1 bsl 30
+overflow_huge_bin_32(<<Bin:2147483648/binary-unit:128,0,_/binary>>) -> {8,Bin}; % 1 bsl 31
+overflow_huge_bin_32(_) -> nomatch.
+
+overflow_huge_bin_skip_64(<<_:18446744073709551616/binary,0,_/binary>>) -> 1; % 1 bsl 64
+overflow_huge_bin_skip_64(<<_:144115188075855872/binary-unit:128,0,_/binary>>) -> 2; % 1 bsl 57
+overflow_huge_bin_skip_64(<<_:288230376151711744/binary-unit:64,0,_/binary>>) -> 3; % 1 bsl 58
+overflow_huge_bin_skip_64(<<_:576460752303423488/binary-unit:32,0,_/binary>>) -> 4; % 1 bsl 59
+overflow_huge_bin_skip_64(<<_:1152921504606846976/binary-unit:16,0,_/binary>>) -> 5; % 1 bsl 60
+overflow_huge_bin_skip_64(<<_:2305843009213693952/binary-unit:8,0,_/binary>>) -> 6; % 1 bsl 61
+overflow_huge_bin_skip_64(<<_:4611686018427387904/binary-unit:8,0,_/binary>>) -> 7; % 1 bsl 62
+overflow_huge_bin_skip_64(<<_:9223372036854775808/binary-unit:8,_/binary>>) -> 8; % 1 bsl 63
+overflow_huge_bin_skip_64(_) -> nomatch.
+
+overflow_huge_bin_64(<<Bin:18446744073709551616/binary,_/binary>>) -> {1,Bin}; % 1 bsl 64
+overflow_huge_bin_64(<<Bin:144115188075855872/binary-unit:128,0,_/binary>>) -> {2,Bin}; % 1 bsl 57
+overflow_huge_bin_64(<<Bin:288230376151711744/binary-unit:128,0,_/binary>>) -> {3,Bin}; % 1 bsl 58
+overflow_huge_bin_64(<<Bin:576460752303423488/binary-unit:128,0,_/binary>>) -> {4,Bin}; % 1 bsl 59
+overflow_huge_bin_64(<<Bin:1152921504606846976/binary-unit:128,0,_/binary>>) -> {5,Bin}; % 1 bsl 60
+overflow_huge_bin_64(<<Bin:2305843009213693952/binary-unit:128,0,_/binary>>) -> {6,Bin}; % 1 bsl 61
+overflow_huge_bin_64(<<Bin:4611686018427387904/binary-unit:128,0,_/binary>>) -> {7,Bin}; % 1 bsl 62
+overflow_huge_bin_64(<<Bin:9223372036854775808/binary-unit:128,0,_/binary>>) -> {8,Bin}; % 1 bsl 63
+overflow_huge_bin_64(_) -> nomatch.
diff --git a/lib/debugger/test/bs_match_int_SUITE.erl b/lib/debugger/test/bs_match_int_SUITE.erl
index 745368fdfc..bff5f8ff65 100644
--- a/lib/debugger/test/bs_match_int_SUITE.erl
+++ b/lib/debugger/test/bs_match_int_SUITE.erl
@@ -19,11 +19,11 @@
-module(bs_match_int_SUITE).
--author('[email protected]').
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
init_per_suite/1,end_per_suite/1,
- integer/1,signed_integer/1,dynamic/1,more_dynamic/1,mml/1]).
+ integer/1,signed_integer/1,dynamic/1,more_dynamic/1,mml/1,
+ match_huge_int/1,bignum/1,unaligned_32_bit/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -32,7 +32,8 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [cases()].
+ [integer, signed_integer, dynamic, more_dynamic, mml,
+ match_huge_int, bignum, unaligned_32_bit].
groups() ->
[].
@@ -43,10 +44,6 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-
-cases() ->
- [integer, signed_integer, dynamic, more_dynamic, mml].
-
init_per_testcase(_Case, Config) ->
test_lib:interpret(?MODULE),
Dog = test_server:timetrap(?t:minutes(4)),
@@ -65,8 +62,7 @@ init_per_suite(Config) when is_list(Config) ->
end_per_suite(Config) when is_list(Config) ->
ok.
-integer(suite) -> [];
-integer(Config) when list(Config) ->
+integer(Config) when is_list(Config) ->
?line 0 = get_int(mkbin([])),
?line 0 = get_int(mkbin([0])),
?line 42 = get_int(mkbin([42])),
@@ -78,22 +74,33 @@ integer(Config) when list(Config) ->
?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 4294967294 = get_int(mkbin([255,255,255,254])),
+ ?line 4294967295 = get_int(mkbin([255,255,255,255])),
?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.
+get_int(Bin) ->
+ I = get_int1(Bin),
+ get_int(Bin, I).
+
+get_int(Bin0, I) when size(Bin0) < 4 ->
+ Bin = <<0,Bin0/binary>>,
+ I = get_int1(Bin),
+ get_int(Bin, I);
+get_int(_, I) -> I.
+
+get_int1(<<I:0>>) -> I;
+get_int1(<<I:8>>) -> I;
+get_int1(<<I:16>>) -> I;
+get_int1(<<I:24>>) -> I;
+get_int1(<<I:32>>) -> I.
cmp128(<<I:128>>, I) -> equal;
-cmp128(_B, _I) -> not_equal.
+cmp128(_, _) -> not_equal.
-signed_integer(suite) -> [];
-signed_integer(Config) when list(Config) ->
+signed_integer(Config) when is_list(Config) ->
?line {no_match,_} = sint(mkbin([])),
?line {no_match,_} = sint(mkbin([1,2,3])),
?line 127 = sint(mkbin([127])),
@@ -113,7 +120,7 @@ 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(Config) when is_list(Config) ->
dynamic(mkbin([255]), 8),
dynamic(mkbin([255,255]), 16),
dynamic(mkbin([255,255,255]), 24),
@@ -124,7 +131,7 @@ 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(_, _) -> ok.
dynamic(Bin, S1, S2, A, B) ->
% io:format("~p ~p ~p ~p\n", [S1,S2,A,B]),
@@ -132,25 +139,24 @@ dynamic(Bin, S1, S2, A, B) ->
<<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])
+ _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) ->
+more_dynamic(Config) when is_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,
+ <<_:SkipBef,Int:N,_:SkipAft>> = Bin,
Int = make_int(List, N, 0)
end,
?line more_dynamic1(Unsigned, funny_binary(42)),
- % Signed big-endian numbers.
+ %% Signed big-endian numbers.
Signed = fun(Bin, List, SkipBef, N) ->
SkipAft = 8*size(Bin) - N - SkipBef,
- <<_I1:SkipBef,Int:N/signed,_I2:SkipAft>> = Bin,
+ <<_:SkipBef,Int:N/signed,_:SkipAft>> = Bin,
case make_signed_int(List, N) of
Int -> ok;
Other ->
@@ -162,18 +168,18 @@ more_dynamic(Config) when list(Config) ->
end,
?line more_dynamic1(Signed, funny_binary(43)),
- % Unsigned little-endian numbers.
+ %% Unsigned little-endian numbers.
UnsLittle = fun(Bin, List, SkipBef, N) ->
SkipAft = 8*size(Bin) - N - SkipBef,
- <<_I1:SkipBef,Int:N/little,_I2:SkipAft>> = Bin,
+ <<_:SkipBef,Int:N/little,_:SkipAft>> = Bin,
Int = make_int(big_to_little(List, N), N, 0)
end,
?line more_dynamic1(UnsLittle, funny_binary(44)),
- % Signed little-endian numbers.
+ %% 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,
+ <<_:SkipBef,Int:N/signed-little,_:SkipAft>> = Bin,
Little = big_to_little(List, N),
Int = make_signed_int(Little, N)
end,
@@ -181,11 +187,6 @@ more_dynamic(Config) when list(Config) ->
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).
@@ -193,7 +194,7 @@ more_dynamic1(Action, Bin) ->
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_dynamic2(_, _, [], _) -> ok.
more_dynamic3(Action, Bin, List, Bef, Aft) when Bef =< Aft ->
%% io:format("~p, ~p", [Bef,Aft-Bef]),
@@ -208,8 +209,8 @@ big_to_little([B0,B1,B2,B3,B4,B5,B6,B7|T], N, Acc) when N >= 8 ->
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) ->
+make_signed_int([0|_]=List, N) -> make_int(List, N, 0);
+make_signed_int([1|_]=List0, N) ->
List1 = reversed_sublist(List0, N, []),
List2 = two_complement_and_reverse(List1, 1, []),
-make_int(List2, length(List2), 0).
@@ -225,7 +226,7 @@ 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([_|T], 0) -> bits_to_list(T, 16#80);
bits_to_list([H|_]=List, Mask) ->
[case H band Mask of
0 -> 0;
@@ -234,11 +235,134 @@ bits_to_list([H|_]=List, Mask) ->
bits_to_list([], _) -> [].
fun_clause({'EXIT',{function_clause,_}}) -> ok.
-mkbin(L) when list(L) -> list_to_binary(L).
+mkbin(L) when is_list(L) -> list_to_binary(L).
+
+funny_binary(N) ->
+ B0 = erlang:md5([N]),
+ {B1,_B2} = split_binary(B0, byte_size(B0) div 3),
+ B1.
-mml(Config) when list(Config) ->
+mml(Config) when is_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.
+mml_choose(<<_A:8,_T/binary>>) -> multi_byte_binary.
+
+match_huge_int(Config) when is_list(Config) ->
+ Sz = 1 bsl 27,
+ ?line Bin = <<0:Sz,13:8>>,
+ ?line skip_huge_int_1(Sz, Bin),
+ ?line 0 = match_huge_int_1(Sz, Bin),
+
+ %% Test overflowing the size of an integer field.
+ ?line nomatch = overflow_huge_int_skip_32(Bin),
+ case erlang:system_info(wordsize) of
+ 4 ->
+ ?line nomatch = overflow_huge_int_32(Bin);
+ 8 ->
+ %% An attempt will be made to allocate heap space for
+ %% the bignum (which will probably fail); only if the
+ %% allocation succeds will the matching fail because
+ %% the binary is too small.
+ ok
+ end,
+ ?line nomatch = overflow_huge_int_skip_64(Bin),
+ ?line nomatch = overflow_huge_int_64(Bin),
+
+ %% Test overflowing the size of an integer field using variables as sizes.
+ ?line Sizes = case erlang:system_info(wordsize) of
+ 4 -> lists:seq(25, 32);
+ 8 -> []
+ end ++ lists:seq(50, 64),
+ ?line ok = overflow_huge_int_unit128(Bin, Sizes),
+
+ ok.
+
+overflow_huge_int_unit128(Bin, [Sz0|Sizes]) ->
+ Sz = id(1 bsl Sz0),
+ case Bin of
+ <<_:Sz/unit:128,0,_/binary>> ->
+ {error,Sz};
+ _ ->
+ case Bin of
+ <<Var:Sz/unit:128,0,_/binary>> ->
+ {error,Sz,Var};
+ _ ->
+ overflow_huge_int_unit128(Bin, Sizes)
+ end
+ end;
+overflow_huge_int_unit128(_, []) -> ok.
+
+match_huge_int_1(I, Bin) ->
+ <<Int:I,13>> = Bin,
+ Int.
+
+skip_huge_int_1(I, Bin) ->
+ <<_:I,13>> = Bin.
+
+overflow_huge_int_skip_32(<<_:4294967296,0,_/binary>>) -> 1; % 1 bsl 32
+overflow_huge_int_skip_32(<<_:33554432/unit:128,0,_/binary>>) -> 2; % 1 bsl 25
+overflow_huge_int_skip_32(<<_:67108864/unit:64,0,_/binary>>) -> 3; % 1 bsl 26
+overflow_huge_int_skip_32(<<_:134217728/unit:32,0,_/binary>>) -> 4; % 1 bsl 27
+overflow_huge_int_skip_32(<<_:268435456/unit:16,0,_/binary>>) -> 5; % 1 bsl 28
+overflow_huge_int_skip_32(<<_:536870912/unit:8,0,_/binary>>) -> 6; % 1 bsl 29
+overflow_huge_int_skip_32(<<_:1073741824/unit:8,0,_/binary>>) -> 7; % 1 bsl 30
+overflow_huge_int_skip_32(<<_:2147483648/unit:8,0,_/binary>>) -> 8; % 1 bsl 31
+overflow_huge_int_skip_32(_) -> nomatch.
+
+overflow_huge_int_32(<<Int:4294967296,_/binary>>) -> {1,Int}; % 1 bsl 32
+overflow_huge_int_32(<<Int:33554432/unit:128,0,_/binary>>) -> {2,Int}; % 1 bsl 25
+overflow_huge_int_32(<<Int:67108864/unit:128,0,_/binary>>) -> {3,Int}; % 1 bsl 26
+overflow_huge_int_32(<<Int:134217728/unit:128,0,_/binary>>) -> {4,Int}; % 1 bsl 27
+overflow_huge_int_32(<<Int:268435456/unit:128,0,_/binary>>) -> {5,Int}; % 1 bsl 28
+overflow_huge_int_32(<<Int:536870912/unit:128,0,_/binary>>) -> {6,Int}; % 1 bsl 29
+overflow_huge_int_32(<<Int:1073741824/unit:128,0,_/binary>>) -> {7,Int}; % 1 bsl 30
+overflow_huge_int_32(<<Int:2147483648/unit:128,0,_/binary>>) -> {8,Int}; % 1 bsl 31
+overflow_huge_int_32(_) -> nomatch.
+
+overflow_huge_int_skip_64(<<_:18446744073709551616,_/binary>>) -> 1; % 1 bsl 64
+overflow_huge_int_skip_64(<<_:144115188075855872/unit:128,0,_/binary>>) -> 2; % 1 bsl 57
+overflow_huge_int_skip_64(<<_:288230376151711744/unit:64,0,_/binary>>) -> 3; % 1 bsl 58
+overflow_huge_int_skip_64(<<_:576460752303423488/unit:32,0,_/binary>>) -> 4; % 1 bsl 59
+overflow_huge_int_skip_64(<<_:1152921504606846976/unit:16,0,_/binary>>) -> 5; % 1 bsl 60
+overflow_huge_int_skip_64(<<_:2305843009213693952/unit:8,0,_/binary>>) -> 6; % 1 bsl 61
+overflow_huge_int_skip_64(<<_:4611686018427387904/unit:8,0,_/binary>>) -> 7; % 1 bsl 62
+overflow_huge_int_skip_64(<<_:9223372036854775808/unit:8,0,_/binary>>) -> 8; % 1 bsl 63
+overflow_huge_int_skip_64(_) -> nomatch.
+
+overflow_huge_int_64(<<Int:18446744073709551616,_/binary>>) -> {1,Int}; % 1 bsl 64
+overflow_huge_int_64(<<Int:144115188075855872/unit:128,0,_/binary>>) -> {2,Int}; % 1 bsl 57
+overflow_huge_int_64(<<Int:288230376151711744/unit:128,0,_/binary>>) -> {3,Int}; % 1 bsl 58
+overflow_huge_int_64(<<Int:576460752303423488/unit:128,0,_/binary>>) -> {4,Int}; % 1 bsl 59
+overflow_huge_int_64(<<Int:1152921504606846976/unit:128,0,_/binary>>) -> {5,Int}; % 1 bsl 60
+overflow_huge_int_64(<<Int:2305843009213693952/unit:128,0,_/binary>>) -> {6,Int}; % 1 bsl 61
+overflow_huge_int_64(<<Int:4611686018427387904/unit:128,0,_/binary>>) -> {7,Int}; % 1 bsl 62
+overflow_huge_int_64(<<Int:9223372036854775808/unit:128,0,_/binary>>) -> {8,Int}; % 1 bsl 63
+overflow_huge_int_64(_) -> nomatch.
+
+bignum(Config) when is_list(Config) ->
+ ?line Bin = id(<<42,0:1024/unit:8,43>>),
+ ?line <<42:1025/little-integer-unit:8,_:8>> = Bin,
+ ?line <<_:8,43:1025/integer-unit:8>> = Bin,
+
+ ?line BignumBin = id(<<0:512/unit:8,258254417031933722623:9/unit:8>>),
+ ?line <<258254417031933722623:(512+9)/unit:8>> = BignumBin,
+ erlang:garbage_collect(), %Search for holes in debug-build.
+ ok.
+
+unaligned_32_bit(Config) when is_list(Config) ->
+ %% There used to be a risk for heap overflow (fixed in R11B-5).
+ ?line L = unaligned_32_bit_1(<<-1:(64*1024)>>),
+ ?line unaligned_32_bit_verify(L, 1638).
+
+unaligned_32_bit_1(<<1:1,U:32,_:7,T/binary>>) ->
+ [U|unaligned_32_bit_1(T)];
+unaligned_32_bit_1(_) ->
+ [].
+
+unaligned_32_bit_verify([], 0) -> ok;
+unaligned_32_bit_verify([4294967295|T], N) when N > 0 ->
+ unaligned_32_bit_verify(T, N-1).
+
+id(I) -> I.
diff --git a/lib/debugger/test/bs_match_misc_SUITE.erl b/lib/debugger/test/bs_match_misc_SUITE.erl
index 53d11ba179..89fce263f5 100644
--- a/lib/debugger/test/bs_match_misc_SUITE.erl
+++ b/lib/debugger/test/bs_match_misc_SUITE.erl
@@ -19,18 +19,24 @@
-module(bs_match_misc_SUITE).
--author('[email protected]').
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
init_per_suite/1,end_per_suite/1,
- bound_var/1,bound_tail/1,t_float/1,little_float/1,sean/1]).
+ bound_var/1,bound_tail/1,t_float/1,little_float/1,sean/1,
+ kenneth/1,encode_binary/1,native/1,happi/1,
+ size_var/1,wiger/1,x0_context/1,huge_float_field/1,
+ writable_binary_matched/1,otp_7198/1,
+ unordered_bindings/1]).
-include_lib("test_server/include/test_server.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- cases().
+ [bound_var, bound_tail, t_float, little_float, sean,
+ kenneth, encode_binary, native, happi, size_var, wiger,
+ x0_context, huge_float_field, writable_binary_matched,
+ otp_7198, unordered_bindings].
groups() ->
[].
@@ -41,9 +47,13 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
+init_per_suite(Config) when is_list(Config) ->
+ ?line test_lib:interpret(?MODULE),
+ ?line true = lists:member(?MODULE, int:interpreted()),
+ Config.
-cases() ->
- [bound_var, bound_tail, t_float, little_float, sean].
+end_per_suite(Config) when is_list(Config) ->
+ ok.
init_per_testcase(_Case, Config) ->
test_lib:interpret(?MODULE),
@@ -55,16 +65,8 @@ end_per_testcase(_Case, Config) ->
?t:timetrap_cancel(Dog),
ok.
-init_per_suite(Config) when is_list(Config) ->
- ?line test_lib:interpret(?MODULE),
- ?line true = lists:member(?MODULE, int:interpreted()),
- Config.
-
-end_per_suite(Config) when is_list(Config) ->
- ok.
-
bound_var(doc) -> "Test matching of bound variables.";
-bound_var(Config) when list(Config) ->
+bound_var(Config) when is_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>>),
@@ -74,7 +76,7 @@ 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) ->
+bound_tail(Config) when is_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>>),
@@ -85,7 +87,7 @@ bound_tail(Config) when list(Config) ->
bound_tail(T, <<_:16,T/binary>>) -> ok;
bound_tail(_, _) -> nope.
-t_float(Config) when list(Config) ->
+t_float(Config) when is_list(Config) ->
F = f1(),
G = f_one(),
@@ -98,6 +100,10 @@ t_float(Config) when list(Config) ->
?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)),
+
+ ?line {'EXIT',{{badmatch,_},_}} = (catch match_float(<<0,0>>, 16, 0)),
+ ?line {'EXIT',{{badmatch,_},_}} = (catch match_float(<<0,0>>, 16#7fffffff, 0)),
+
ok.
@@ -110,7 +116,7 @@ match_float(Bin0, Fsz, I) ->
<<_:I,F:Fsz/float,_:Tsz>> = Bin,
F.
-little_float(Config) when list(Config) ->
+little_float(Config) when is_list(Config) ->
F = f2(),
G = f_one(),
@@ -149,7 +155,7 @@ f2() ->
f_one() ->
1.0.
-sean(Config) when list(Config) ->
+sean(Config) when is_list(Config) ->
?line small = sean1(<<>>),
?line small = sean1(<<1>>),
?line small = sean1(<<1,2>>),
@@ -162,5 +168,414 @@ sean(Config) when list(Config) ->
?line {'EXIT',{function_clause,_}} = (catch sean1(<<4,5,6,7>>)),
ok.
-sean1(<<B/binary>>) when size(B) < 4 -> small;
+sean1(<<B/binary>>) when byte_size(B) < 4 -> small;
sean1(<<1, _B/binary>>) -> large.
+
+kenneth(Config) when is_list(Config) ->
+ {ok,[145,148,113,129,0,0,0,0]} =
+ msisdn_internal_storage(<<145,148,113,129,0,0,0,0>>, []).
+
+msisdn_internal_storage(<<>>,MSISDN) ->
+ {ok,lists:reverse(MSISDN)};
+msisdn_internal_storage(<<2#11111111:8,_Rest/binary>>,MSISDN) ->
+ {ok,lists:reverse(MSISDN)};
+msisdn_internal_storage(<<2#1111:4,DigitN:4,_Rest/binary>>,MSISDN) when
+ DigitN < 10 ->
+ {ok,lists:reverse([(DigitN bor 2#11110000)|MSISDN])};
+msisdn_internal_storage(<<DigitNplus1:4,DigitN:4,Rest/binary>>,MSISDN) when
+ DigitNplus1 < 10,
+ DigitN < 10 ->
+ NewMSISDN=[((DigitNplus1 bsl 4) bor DigitN)|MSISDN],
+ msisdn_internal_storage(Rest,NewMSISDN);
+msisdn_internal_storage(_Rest,_MSISDN) ->
+ {fault}. %% Mandatory IE incorrect
+
+encode_binary(Config) when is_list(Config) ->
+ "C2J2QiSc" = encodeBinary(<<11,98,118,66,36,156>>, []),
+ ok.
+
+encodeBinary(<<>>, Output) ->
+ lists:reverse(Output);
+encodeBinary(<<Data:1/binary>>, Output) ->
+ <<DChar1:6, DChar2:2>> = Data,
+ Char1 = getBase64Char(DChar1),
+ Char2 = getBase64Char(DChar2),
+ Char3 = "=",
+ Char4 = "=",
+ NewOutput = Char4 ++ Char3 ++ Char2 ++ Char1 ++ Output,
+ encodeBinary(<<>>, NewOutput);
+encodeBinary(<<Data:2/binary>>, Output) ->
+ <<DChar1:6, DChar2:6, DChar3:4>> = Data,
+ Char1 = getBase64Char(DChar1),
+ Char2 = getBase64Char(DChar2),
+ Char3 = getBase64Char(DChar3),
+ Char4 = "=",
+ NewOutput = Char4 ++ Char3 ++ Char2 ++ Char1 ++ Output,
+ encodeBinary(<<>>, NewOutput);
+encodeBinary(<<Data:3/binary, Rest/binary>>, Output) ->
+ <<DChar1:6, DChar2:6, DChar3:6, DChar4:6>> = Data,
+ Char1 = getBase64Char(DChar1),
+ Char2 = getBase64Char(DChar2),
+ Char3 = getBase64Char(DChar3),
+ Char4 = getBase64Char(DChar4),
+ NewOutput = Char4 ++ Char3 ++ Char2 ++ Char1 ++ Output,
+ encodeBinary(Rest, NewOutput);
+encodeBinary(_Data, _) ->
+ error.
+
+getBase64Char(0) -> "A";
+getBase64Char(1) -> "B";
+getBase64Char(2) -> "C";
+getBase64Char(3) -> "D";
+getBase64Char(4) -> "E";
+getBase64Char(5) -> "F";
+getBase64Char(6) -> "G";
+getBase64Char(7) -> "H";
+getBase64Char(8) -> "I";
+getBase64Char(9) -> "J";
+getBase64Char(10) -> "K";
+getBase64Char(11) -> "L";
+getBase64Char(12) -> "M";
+getBase64Char(13) -> "N";
+getBase64Char(14) -> "O";
+getBase64Char(15) -> "P";
+getBase64Char(16) -> "Q";
+getBase64Char(17) -> "R";
+getBase64Char(18) -> "S";
+getBase64Char(19) -> "T";
+getBase64Char(20) -> "U";
+getBase64Char(21) -> "V";
+getBase64Char(22) -> "W";
+getBase64Char(23) -> "X";
+getBase64Char(24) -> "Y";
+getBase64Char(25) -> "Z";
+getBase64Char(26) -> "a";
+getBase64Char(27) -> "b";
+getBase64Char(28) -> "c";
+getBase64Char(29) -> "d";
+getBase64Char(30) -> "e";
+getBase64Char(31) -> "f";
+getBase64Char(32) -> "g";
+getBase64Char(33) -> "h";
+getBase64Char(34) -> "i";
+getBase64Char(35) -> "j";
+getBase64Char(36) -> "k";
+getBase64Char(37) -> "l";
+getBase64Char(38) -> "m";
+getBase64Char(39) -> "n";
+getBase64Char(40) -> "o";
+getBase64Char(41) -> "p";
+getBase64Char(42) -> "q";
+getBase64Char(43) -> "r";
+getBase64Char(44) -> "s";
+getBase64Char(45) -> "t";
+getBase64Char(46) -> "u";
+getBase64Char(47) -> "v";
+getBase64Char(48) -> "w";
+getBase64Char(49) -> "x";
+getBase64Char(50) -> "y";
+getBase64Char(51) -> "z";
+getBase64Char(52) -> "0";
+getBase64Char(53) -> "1";
+getBase64Char(54) -> "2";
+getBase64Char(55) -> "3";
+getBase64Char(56) -> "4";
+getBase64Char(57) -> "5";
+getBase64Char(58) -> "6";
+getBase64Char(59) -> "7";
+getBase64Char(60) -> "8";
+getBase64Char(61) -> "9";
+getBase64Char(62) -> "+";
+getBase64Char(63) -> "/";
+getBase64Char(_Else) ->
+ %% This is an illegal input.
+% cgLogEM:log(error, ?MODULE, getBase64Char, [Else],
+% "illegal input",
+% ?LINE, version()),
+ "**".
+
+-define(M(F), <<F>> = <<F>>).
+
+native(Config) when is_list(Config) ->
+ ?line ?M(3.14:64/native-float),
+ ?line ?M(333:16/native),
+ ?line ?M(38658345:32/native),
+ case <<1:16/native>> of
+ <<0,1>> -> native_big();
+ <<1,0>> -> native_little()
+ end.
+
+native_big() ->
+ ?line <<37.33:64/native-float>> = <<37.33:64/big-float>>,
+ ?line <<3974:16/native-integer>> = <<3974:16/big-integer>>,
+ {comment,"Big endian"}.
+
+native_little() ->
+ ?line <<37869.32343:64/native-float>> = <<37869.32343:64/little-float>>,
+ ?line <<7974:16/native-integer>> = <<7974:16/little-integer>>,
+ {comment,"Little endian"}.
+
+happi(Config) when is_list(Config) ->
+ Bin = <<".123">>,
+ ?line <<"123">> = lex_digits1(Bin, 1, []),
+ ?line <<"123">> = lex_digits2(Bin, 1, []),
+ ok.
+
+lex_digits1(<<$., Rest/binary>>,_Val,_Acc) ->
+ Rest;
+lex_digits1(<<N, Rest/binary>>,Val, Acc) when N >= $0 , N =< $9 ->
+ lex_digits1(Rest,Val*10+dec(N),Acc);
+lex_digits1(_Other,_Val,_Acc) ->
+ not_ok.
+
+lex_digits2(<<N, Rest/binary>>,Val, Acc) when N >= $0 , N =< $9 ->
+ lex_digits2(Rest,Val*10+dec(N),Acc);
+lex_digits2(<<$., Rest/binary>>,_Val,_Acc) ->
+ Rest;
+lex_digits2(_Other,_Val,_Acc) ->
+ not_ok.
+
+dec(A) ->
+ A-$0.
+
+size_var(Config) when is_list(Config) ->
+ ?line {<<45>>,<<>>} = split(<<1:16,45>>),
+ ?line {<<45>>,<<46,47>>} = split(<<1:16,45,46,47>>),
+ ?line {<<45,46>>,<<47>>} = split(<<2:16,45,46,47>>),
+
+ ?line {<<45,46,47>>,<<48>>} = split_2(<<16:8,3:16,45,46,47,48>>),
+
+ ?line {<<45,46>>,<<47>>} = split(2, <<2:16,45,46,47>>),
+ ?line {'EXIT',{function_clause,_}} = (catch split(42, <<2:16,45,46,47>>)),
+
+ ?line <<"cdef">> = skip(<<2:8,"abcdef">>),
+
+ ok.
+
+split(<<N:16,B:N/binary,T/binary>>) ->
+ {B,T}.
+
+split(N, <<N:16,B:N/binary,T/binary>>) ->
+ {B,T}.
+
+split_2(<<N0:8,N:N0,B:N/binary,T/binary>>) ->
+ {B,T}.
+
+skip(<<N:8,_:N/binary,T/binary>>) -> T.
+
+wiger(Config) when is_list(Config) ->
+ ?line ok1 = wcheck(<<3>>),
+ ?line ok2 = wcheck(<<1,2,3>>),
+ ?line ok3 = wcheck(<<4>>),
+ ?line {error,<<1,2,3,4>>} = wcheck(<<1,2,3,4>>),
+ ?line {error,<<>>} = wcheck(<<>>),
+ ok.
+
+wcheck(<<A>>) when A==3->
+ ok1;
+wcheck(<<_,_:2/binary>>) ->
+ ok2;
+wcheck(<<_>>) ->
+ ok3;
+wcheck(Other) ->
+ {error,Other}.
+
+%% Test that having the match context in x(0) works.
+
+x0_context(Config) when is_list(Config) ->
+ x0_0([], <<3.0:64/float,42:16,123456:32>>).
+
+x0_0(_, Bin) ->
+ <<3.0:64/float,42:16,_/binary>> = Bin,
+ x0_1([], Bin, 64, 16, 2).
+
+x0_1(_, Bin, FloatSz, IntSz, BinSz) ->
+ <<_:FloatSz/float,42:IntSz,B:BinSz/binary,C:1/binary,D/binary>> = Bin,
+ id({B,C,D}),
+ <<_:FloatSz/float,42:IntSz,B:BinSz/binary,_/binary>> = Bin,
+ x0_2([], Bin).
+
+x0_2(_, Bin) ->
+ <<_:64,0:7,42:9,_/binary>> = Bin,
+ x0_3([], Bin).
+
+x0_3(_, Bin) ->
+ case Bin of
+ <<_:72,7:8,_/binary>> ->
+ ?line ?t:fail();
+ <<_:64,0:16,_/binary>> ->
+ ?line ?t:fail();
+ <<_:64,42:16,123456:32,_/binary>> ->
+ ok
+ end.
+
+
+huge_float_field(Config) when is_list(Config) ->
+ Sz = 1 bsl 27,
+ ?line Bin = <<0:Sz>>,
+
+ ?line nomatch = overflow_huge_float_skip_32(Bin),
+ ?line nomatch = overflow_huge_float_32(Bin),
+
+ ?line ok = overflow_huge_float(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
+ ?line ok = overflow_huge_float_unit128(Bin, lists:seq(25, 32)++lists:seq(50, 64)),
+ ok.
+
+overflow_huge_float_skip_32(<<_:4294967296/float,0,_/binary>>) -> 1; % 1 bsl 32
+overflow_huge_float_skip_32(<<_:33554432/float-unit:128,0,_/binary>>) -> 2; % 1 bsl 25
+overflow_huge_float_skip_32(<<_:67108864/float-unit:64,0,_/binary>>) -> 3; % 1 bsl 26
+overflow_huge_float_skip_32(<<_:134217728/float-unit:32,0,_/binary>>) -> 4; % 1 bsl 27
+overflow_huge_float_skip_32(<<_:268435456/float-unit:16,0,_/binary>>) -> 5; % 1 bsl 28
+overflow_huge_float_skip_32(<<_:536870912/float-unit:8,0,_/binary>>) -> 6; % 1 bsl 29
+overflow_huge_float_skip_32(<<_:1073741824/float-unit:8,0,_/binary>>) -> 7; % 1 bsl 30
+overflow_huge_float_skip_32(<<_:2147483648/float-unit:8,0,_/binary>>) -> 8; % 1 bsl 31
+overflow_huge_float_skip_32(_) -> nomatch.
+
+overflow_huge_float_32(<<F:4294967296/float,_/binary>>) -> {1,F}; % 1 bsl 32
+overflow_huge_float_32(<<F:33554432/float-unit:128,0,_/binary>>) -> {2,F}; % 1 bsl 25
+overflow_huge_float_32(<<F:67108864/float-unit:128,0,_/binary>>) -> {3,F}; % 1 bsl 26
+overflow_huge_float_32(<<F:134217728/float-unit:128,0,_/binary>>) -> {4,F}; % 1 bsl 27
+overflow_huge_float_32(<<F:268435456/float-unit:128,0,_/binary>>) -> {5,F}; % 1 bsl 28
+overflow_huge_float_32(<<F:536870912/float-unit:128,0,_/binary>>) -> {6,F}; % 1 bsl 29
+overflow_huge_float_32(<<F:1073741824/float-unit:128,0,_/binary>>) -> {7,F}; % 1 bsl 30
+overflow_huge_float_32(<<F:2147483648/float-unit:128,0,_/binary>>) -> {8,F}; % 1 bsl 31
+overflow_huge_float_32(_) -> nomatch.
+
+
+overflow_huge_float(Bin, [Sz0|Sizes]) ->
+ Sz = id(1 bsl Sz0),
+ case Bin of
+ <<_:Sz/float-unit:8,0,_/binary>> ->
+ {error,Sz};
+ _ ->
+ case Bin of
+ <<Var:Sz/float-unit:8,0,_/binary>> ->
+ {error,Sz,Var};
+ _ ->
+ overflow_huge_float(Bin, Sizes)
+ end
+ end;
+overflow_huge_float(_, []) -> ok.
+
+overflow_huge_float_unit128(Bin, [Sz0|Sizes]) ->
+ Sz = id(1 bsl Sz0),
+ case Bin of
+ <<_:Sz/float-unit:128,0,_/binary>> ->
+ {error,Sz};
+ _ ->
+ case Bin of
+ <<Var:Sz/float-unit:128,0,_/binary>> ->
+ {error,Sz,Var};
+ _ ->
+ overflow_huge_float_unit128(Bin, Sizes)
+ end
+ end;
+overflow_huge_float_unit128(_, []) -> ok.
+
+
+%%
+%% Test that a writable binary can be safely matched.
+%%
+
+writable_binary_matched(Config) when is_list(Config) ->
+ ?line WritableBin = create_writeable_binary(),
+ ?line writable_binary_matched(WritableBin, WritableBin, 500).
+
+writable_binary_matched(<<0>>, _, N) ->
+ if
+ N =:= 0 -> ok;
+ true ->
+ put(grow_heap, [N|get(grow_heap)]),
+ ?line WritableBin = create_writeable_binary(),
+ ?line writable_binary_matched(WritableBin, WritableBin, N-1)
+ end;
+writable_binary_matched(<<B:8,T/binary>>, WritableBin0, N) ->
+ ?line WritableBin = writable_binary(WritableBin0, B),
+ writable_binary_matched(T, WritableBin, N).
+
+writable_binary(WritableBin0, B) when is_binary(WritableBin0) ->
+ %% Heavy append to force the binary to move.
+ ?line WritableBin = <<WritableBin0/binary,0:(size(WritableBin0))/unit:8,B>>,
+ ?line id(<<(id(0)):128/unit:8>>),
+ WritableBin.
+
+create_writeable_binary() ->
+ <<(id(<<>>))/binary,1,2,3,4,5,6,0>>.
+
+otp_7198(Config) when is_list(Config) ->
+ %% When a match context was reused, and grown at the same time to
+ %% increase the number of saved positions, the thing word was not updated
+ %% to account for the new size. Therefore, if there was a garbage collection,
+ %% the new slots would be included in the garbage collection.
+ ?line [do_otp_7198(FillerSize) || FillerSize <- lists:seq(0, 256)],
+ ok.
+
+do_otp_7198(FillerSize) ->
+ Filler = erlang:make_tuple(FillerSize, 42),
+ {Pid,Ref} = spawn_monitor(fun() -> do_otp_7198_test(Filler) end),
+ receive
+ {'DOWN',Ref,process,Pid,normal} ->
+ ok;
+ {'DOWN',Ref,process,Pid,Reason} ->
+ io:format("unexpected: ~p", [Reason]),
+ ?line ?t:fail()
+ end.
+
+do_otp_7198_test(_) ->
+ [{'KEYWORD',114},
+ {'KEYWORD',101},
+ {'KEYWORD',103},
+ {'KEYWORD',105},
+ {'KEYWORD',111},
+ {'FIELD',110},
+ {'KEYWORD',119},
+ {'KEYWORD',104},
+ {'KEYWORD',97},
+ {'KEYWORD',116},
+ {'KEYWORD',101},
+ {'KEYWORD',118},
+ {'KEYWORD',101},
+ {'KEYWORD',114},
+ '$thats_all_folks$'] = otp_7198_scan(<<"region:whatever">>, []).
+
+
+otp_7198_scan(<<>>, TokAcc) ->
+ lists:reverse(['$thats_all_folks$' | TokAcc]);
+
+otp_7198_scan(<<D, Z, Rest/binary>>, TokAcc) when
+ (D =:= $D orelse D =:= $d) and
+ ((Z =:= $\s) or (Z =:= $() or (Z =:= $))) ->
+ otp_7198_scan(<<Z, Rest/binary>>, ['AND' | TokAcc]);
+
+otp_7198_scan(<<D>>, TokAcc) when
+ (D =:= $D) or (D =:= $d) ->
+ otp_7198_scan(<<>>, ['AND' | TokAcc]);
+
+otp_7198_scan(<<N, Z, Rest/binary>>, TokAcc) when
+ (N =:= $N orelse N =:= $n) and
+ ((Z =:= $\s) or (Z =:= $() or (Z =:= $))) ->
+ otp_7198_scan(<<Z, Rest/binary>>, ['NOT' | TokAcc]);
+
+otp_7198_scan(<<C, Rest/binary>>, TokAcc) when
+ (C >= $A) and (C =< $Z);
+ (C >= $a) and (C =< $z);
+ (C >= $0) and (C =< $9) ->
+ case Rest of
+ <<$:, R/binary>> ->
+ otp_7198_scan(R, [{'FIELD', C} | TokAcc]);
+ _ ->
+ otp_7198_scan(Rest, [{'KEYWORD', C} | TokAcc])
+ end.
+
+unordered_bindings(Config) when is_list(Config) ->
+ {<<1,2,3,4>>,<<42,42>>,<<3,3,3>>} =
+ unordered_bindings(4, 2, 3, <<1,2,3,4, 42,42, 3,3,3, 3>>),
+ ok.
+
+unordered_bindings(CompressedLength, HashSize, PadLength, T) ->
+ <<Content:CompressedLength/binary,Mac:HashSize/binary,
+ Padding:PadLength/binary,PadLength>> = T,
+ {Content,Mac,Padding}.
+
+
+id(I) -> I.
diff --git a/lib/debugger/test/bs_match_tail_SUITE.erl b/lib/debugger/test/bs_match_tail_SUITE.erl
index 961ccbb599..9f7519cf3a 100644
--- a/lib/debugger/test/bs_match_tail_SUITE.erl
+++ b/lib/debugger/test/bs_match_tail_SUITE.erl
@@ -64,7 +64,7 @@ end_per_suite(Config) when is_list(Config) ->
ok.
aligned(doc) -> "Test aligned tails.";
-aligned(Config) when list(Config) ->
+aligned(Config) when is_list(Config) ->
?line Tail1 = mkbin([]),
?line {258,Tail1} = al_get_tail_used(mkbin([1,2])),
?line Tail2 = mkbin(lists:seq(1, 127)),
@@ -84,10 +84,10 @@ aligned(Config) when list(Config) ->
ok.
al_get_tail_used(<<A:16,T/binary>>) -> {A,T}.
-al_get_tail_unused(<<A:16,_T/binary>>) -> A.
+al_get_tail_unused(<<A:16,_/binary>>) -> A.
unaligned(doc) -> "Test that an non-aligned tail cannot be matched out.";
-unaligned(Config) when list(Config) ->
+unaligned(Config) when is_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]))),
@@ -103,11 +103,11 @@ get_dyn_tail_used(Bin, Sz) ->
{A,T}.
get_dyn_tail_unused(Bin, Sz) ->
- <<A:Sz,_T/binary>> = Bin,
+ <<A:Sz,_/binary>> = Bin,
A.
zero_tail(doc) -> "Test that zero tails are tested correctly.";
-zero_tail(Config) when list(Config) ->
+zero_tail(Config) when is_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]))),
@@ -117,4 +117,4 @@ test_zero_tail(<<A:8>>) -> A.
test_zero_tail2(<<_A:4,_B:4>>) -> ok.
-mkbin(L) when list(L) -> list_to_binary(L).
+mkbin(L) when is_list(L) -> list_to_binary(L).
diff --git a/lib/debugger/test/bug_SUITE.erl b/lib/debugger/test/bug_SUITE.erl
index a831897dfb..1a7e876329 100644
--- a/lib/debugger/test/bug_SUITE.erl
+++ b/lib/debugger/test/bug_SUITE.erl
@@ -51,7 +51,7 @@ end_per_group(_GroupName, Config) ->
otp2163(doc) -> ["BIF exit reason"];
otp2163(suite) -> [];
-otp2163(Config) when list(Config) ->
+otp2163(Config) when is_list(Config) ->
?line DataDir = ?config(data_dir, Config),
%% First compile and get the expected results:
@@ -74,7 +74,7 @@ otp2163(Config) when list(Config) ->
otp4845(doc) -> ["BIF not loading and not bug compatible, OTP-4845 OTP-4859"];
otp4845(suite) -> [];
-otp4845(Config) when list(Config) ->
+otp4845(Config) when is_list(Config) ->
?line DataDir = ?config(data_dir, Config),
%% First compile and get the expected results:
diff --git a/lib/debugger/test/exception_SUITE.erl b/lib/debugger/test/exception_SUITE.erl
index 8c864e4b5f..86554ab2d4 100644
--- a/lib/debugger/test/exception_SUITE.erl
+++ b/lib/debugger/test/exception_SUITE.erl
@@ -23,7 +23,8 @@
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
init_per_suite/1,end_per_suite/1,
- badmatch/1,pending_errors/1,nil_arith/1]).
+ badmatch/1,pending_errors/1,nil_arith/1,
+ stacktrace/1,nested_stacktrace/1,raise/1,gunilla/1,per/1]).
-export([bad_guy/2]).
@@ -31,6 +32,19 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
+%% Filler.
+%%
+%%
+%%
+%%
+%% This is line 40.
+even(N) when is_integer(N), N > 1, (N rem 2) == 0 ->
+ odd(N-1)++[N].
+
+odd(N) when is_integer(N), N > 1, (N rem 2) == 1 ->
+ even(N-1)++[N].
+
+
all() ->
cases().
@@ -45,7 +59,8 @@ end_per_group(_GroupName, Config) ->
cases() ->
- [badmatch, pending_errors, nil_arith].
+ [badmatch, pending_errors, nil_arith, stacktrace,
+ nested_stacktrace, raise, gunilla, per].
-define(try_match(E),
catch ?MODULE:bar(),
@@ -69,9 +84,9 @@ init_per_suite(Config) when is_list(Config) ->
end_per_suite(Config) when is_list(Config) ->
ok.
-badmatch(doc) -> "Test that deliberately bad matches are reported correctly.";
-badmatch(suite) -> [];
-badmatch(Config) when list(Config) ->
+%% Test that deliberately bad matches are reported correctly.
+
+badmatch(Config) when is_list(Config) ->
?line ?try_match(a),
?line ?try_match(42),
?line ?try_match({a, b, c}),
@@ -79,11 +94,9 @@ badmatch(Config) when list(Config) ->
?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) ->
+%% Test various exceptions, in the presence of a previous error suppressed
+%% in a guard.
+pending_errors(Config) when is_list(Config) ->
?line pending(e_badmatch, {badmatch, b}),
?line pending(x, function_clause),
?line pending(e_case, {case_clause, xxx}),
@@ -100,7 +113,7 @@ bad_guy(pe_badarith, Other) when Other+1 == 0 -> % badarith (suppressed)
bad_guy(pe_badarg, Other) when length(Other) > 0 -> % badarg (suppressed)
ok;
bad_guy(_, e_case) ->
- case xxx of
+ case id(xxx) of
ok -> ok
end; % case_clause
bad_guy(_, e_if) ->
@@ -121,7 +134,7 @@ bad_guy(_, e_badarg) ->
bad_guy(_, e_badarg_spawn) ->
spawn({}, {}, {}); % badarg
bad_guy(_, e_badmatch) ->
- a = b. % badmatch
+ a = id(b). % badmatch
pending(Arg, Expected) ->
pending(pe_badarith, Arg, Expected),
@@ -155,28 +168,23 @@ pending_exit_message(Args, Expected) ->
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.
+pending({badarg, [{erlang,Bif,BifArgs,_},{?MODULE,Func,Arity,_}|_]},
+ Func, Args, _Code)
+ when is_atom(Bif), is_list(BifArgs), length(Args) == Arity ->
ok;
-pending({undef,[{non_existing_module,foo,[]}|_]}, _, _, _) ->
+pending({undef,[{non_existing_module,foo,[],_}|_]}, _, _, _) ->
ok;
-pending({function_clause,[{?MODULE,Func,Args}|_]}, Func, Args, _Code) ->
+pending({function_clause,[{?MODULE,Func,Args,_}|_]}, Func, Args, _Code) ->
ok;
-pending({Code,[{?MODULE,Func,Arity}|_]}, Func, Args, Code) when length(Args) == Arity -> %Threaded code
+pending({Code,[{?MODULE,Func,Arity,_}|_]}, Func, Args, Code)
+ when length(Args) == Arity ->
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) ->
+pending(Reason, _Function, _Args, _Code) ->
+ test_server:fail({bad_exit_reason,Reason}).
+
+%% Test that doing arithmetics on [] gives a badarith EXIT and not a crash.
+
+nil_arith(Config) when is_list(Config) ->
?line ba_plus_minus_times([], []),
?line ba_plus_minus_times([], 0),
@@ -268,3 +276,199 @@ ba_shift(A, B) ->
ba_bnot(A) ->
io:format("bnot ~p", [A]),
{'EXIT', {badarith, _}} = (catch bnot A).
+
+stacktrace(Conf) when is_list(Conf) ->
+ Tag = make_ref(),
+ ?line {_,Mref} = spawn_monitor(fun() -> exit({Tag,erlang:get_stacktrace()}) end),
+ ?line {Tag,[]} = receive {'DOWN',Mref,_,_,Info} -> Info end,
+ V = [make_ref()|self()],
+ ?line {value2,{caught1,badarg,[{erlang,abs,[V],_}|_]=St1}} =
+ stacktrace_1({'abs',V}, error, {value,V}),
+ ?line St1 = erase(stacktrace1),
+ ?line St1 = erase(stacktrace2),
+ ?line St1 = erlang:get_stacktrace(),
+ ?line {caught2,{error,badarith},[{?MODULE,my_add,2,_}|_]=St2} =
+ stacktrace_1({'div',{1,0}}, error, {'add',{0,a}}),
+ ?line [{?MODULE,my_div,2,_}|_] = erase(stacktrace1),
+ ?line St2 = erase(stacktrace2),
+ ?line St2 = erlang:get_stacktrace(),
+ ?line {caught2,{error,{try_clause,V}},[{?MODULE,stacktrace_1,3,_}|_]=St3} =
+ stacktrace_1({value,V}, error, {value,V}),
+ ?line St3 = erase(stacktrace1),
+ ?line St3 = erase(stacktrace2),
+ ?line St3 = erlang:get_stacktrace(),
+ ?line {caught2,{throw,V},[{?MODULE,foo,1,_}|_]=St4} =
+ stacktrace_1({value,V}, error, {throw,V}),
+ ?line [{?MODULE,stacktrace_1,3,_}|_] = erase(stacktrace1),
+ ?line St4 = erase(stacktrace2),
+ ?line St4 = erlang:get_stacktrace(),
+ ok.
+
+stacktrace_1(X, C1, Y) ->
+ erase(stacktrace1),
+ erase(stacktrace2),
+ try try foo(X) of
+ C1 -> value1
+ catch
+ C1:D1 -> {caught1,D1,erlang:get_stacktrace()}
+ after
+ put(stacktrace1, erlang:get_stacktrace()),
+ foo(Y)
+ end of
+ V2 -> {value2,V2}
+ catch
+ C2:D2 -> {caught2,{C2,D2},erlang:get_stacktrace()}
+ after
+ put(stacktrace2, erlang:get_stacktrace())
+ end.
+
+
+
+nested_stacktrace(Conf) when is_list(Conf) ->
+ V = [{make_ref()}|[self()]],
+ ?line value1 =
+ nested_stacktrace_1({{value,{V,x1}},void,{V,x1}},
+ {void,void,void}),
+ ?line {caught1,
+ [{?MODULE,my_add,2,_}|_],
+ value2,
+ [{?MODULE,my_add,2,_}|_]} =
+ nested_stacktrace_1({{'add',{V,x1}},error,badarith},
+ {{value,{V,x2}},void,{V,x2}}),
+ ?line {caught1,
+ [{?MODULE,my_add,2,_}|_],
+ {caught2,[{erlang,abs,[V],_}|_]},
+ [{erlang,abs,[V],_}|_]} =
+ nested_stacktrace_1({{'add',{V,x1}},error,badarith},
+ {{'abs',V},error,badarg}),
+ ok.
+
+nested_stacktrace_1({X1,C1,V1}, {X2,C2,V2}) ->
+ try foo(X1) of
+ V1 -> value1
+ catch
+ C1:V1 ->
+ S1 = erlang:get_stacktrace(),
+ T2 =
+ try foo(X2) of
+ V2 -> value2
+ catch
+ C2:V2 -> {caught2,erlang:get_stacktrace()}
+ end,
+ {caught1,S1,T2,erlang:get_stacktrace()}
+ end.
+
+
+
+raise(Conf) when is_list(Conf) ->
+ ?line erase(raise),
+ ?line A =
+ try
+ ?line try foo({'div',{1,0}})
+ catch
+ error:badarith ->
+ put(raise, A0 = erlang:get_stacktrace()),
+ ?line erlang:raise(error, badarith, A0)
+ end
+ catch
+ error:badarith ->
+ ?line A1 = erlang:get_stacktrace(),
+ ?line A1 = get(raise)
+ end,
+ ?line A = erlang:get_stacktrace(),
+ ?line A = get(raise),
+ ?line [{?MODULE,my_div,2,_}|_] = A,
+ %%
+ N = 8, % Must be even
+ ?line N = erlang:system_flag(backtrace_depth, N),
+ ?line try even(N)
+ catch error:function_clause -> ok
+ end,
+ ?line B = odd_even(N, []),
+ ?line B = erlang:get_stacktrace(),
+ %%
+ ?line C0 = odd_even(N+1, []),
+ ?line C = lists:sublist(C0, N),
+ ?line try odd(N+1)
+ catch error:function_clause -> ok
+ end,
+ ?line C = erlang:get_stacktrace(),
+ ?line try erlang:raise(error, function_clause, C0)
+ catch error:function_clause -> ok
+ end,
+ ?line C = erlang:get_stacktrace(),
+ ok.
+
+odd_even(N, R) when is_integer(N), N > 1 ->
+ odd_even(N-1,
+ [if (N rem 2) == 0 ->
+ {?MODULE,even,1,[{file,?MODULE_STRING++".erl"},
+ {line,42}]};
+ true ->
+ {?MODULE,odd,1,[{file,?MODULE_STRING++".erl"},
+ {line,45}]}
+ end|R]);
+odd_even(1, R) ->
+ [{?MODULE,odd,[1],[{file,?MODULE_STRING++".erl"},
+ {line,44}]}|R].
+
+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,Stacktrace}}) ->
+ erlang:raise(Class, Reason, Stacktrace).
+%%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).
+
+gunilla(Config) when is_list(Config) ->
+ ?line {throw,kalle} = gunilla_1(),
+ ?line [] = erlang:get_stacktrace(),
+ ok.
+
+gunilla_1() ->
+ try try arne()
+ after
+ pelle
+ end
+ catch
+ C:R ->
+ {C,R}
+ end.
+
+arne() ->
+ %% Empty stack trace used to cause change the error class to 'error'.
+ erlang:raise(throw, kalle, []).
+
+per(Config) when is_list(Config) ->
+ try
+ t1(0,pad,0),
+ t2(0,pad,0)
+ catch
+ error:badarith ->
+ ok
+ end.
+
+t1(_,X,_) ->
+ (1 bsl X) + 1.
+
+t2(_,X,_) ->
+ (X bsl 1) + 1.
+
+id(I) -> I.
diff --git a/lib/debugger/test/guard_SUITE.erl b/lib/debugger/test/guard_SUITE.erl
index 611dcb4dff..bf5fa82749 100644
--- a/lib/debugger/test/guard_SUITE.erl
+++ b/lib/debugger/test/guard_SUITE.erl
@@ -35,7 +35,8 @@
t_is_boolean/1,is_function_2/1,
tricky/1,rel_ops/1,
basic_andalso_orelse/1,traverse_dcd/1,
- check_qlc_hrl/1]).
+ check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1,
+ bad_constants/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -65,7 +66,8 @@ cases() ->
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].
+ check_qlc_hrl, andalso_semi, t_tuple_size, binary_part,
+ bad_constants].
init_per_testcase(_Case, Config) ->
test_lib:interpret(?MODULE),
@@ -294,9 +296,7 @@ try_gbif(Id, X, Y) ->
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
+ {'EXIT', {function_clause,[{?MODULE,guard_bif,[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",
@@ -367,9 +367,8 @@ type_tests(Test, [Type|T], Allowed) ->
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]}|_]}} ->
+ {'EXIT',{function_clause,
+ [{?MODULE,type_test,[Test,Value],_}|_]}} ->
ok;
{'EXIT',Other} ->
?line test_server:fail({unexpected_error_reason,Other});
@@ -1477,7 +1476,207 @@ cqlc(M, F, As, St) ->
St
end.
+%% OTP-7679: Thanks to Hunter Morris.
+andalso_semi(Config) when is_list(Config) ->
+ ?line ok = andalso_semi_foo(0),
+ ?line ok = andalso_semi_foo(1),
+ ?line fc(catch andalso_semi_foo(2)),
+
+ ?line ok = andalso_semi_bar([a,b,c]),
+ ?line ok = andalso_semi_bar(1),
+ ?line fc(catch andalso_semi_bar([a,b])),
+ ok.
+
+andalso_semi_foo(Bar) when is_integer(Bar) andalso Bar =:= 0; Bar =:= 1 ->
+ ok.
+
+andalso_semi_bar(Bar) when is_list(Bar) andalso length(Bar) =:= 3; Bar =:= 1 ->
+ ok.
+
+
+t_tuple_size(Config) when is_list(Config) ->
+ ?line 10 = do_tuple_size({1,2,3,4}),
+ ?line fc(catch do_tuple_size({1,2,3})),
+ ?line fc(catch do_tuple_size(42)),
+ ?line error = ludicrous_tuple_size({a,b,c}),
+ ?line error = ludicrous_tuple_size([a,b,c]),
+
+ ok.
+
+do_tuple_size(T) when tuple_size(T) =:= 4 ->
+ {A,B,C,D} = T,
+ A+B+C+D.
+
+ludicrous_tuple_size(T)
+ when tuple_size(T) =:= 16#7777777777777777777777777777777777 -> ok;
+ludicrous_tuple_size(T)
+ when tuple_size(T) =:= 16#10000000000000000 -> ok;
+ludicrous_tuple_size(T)
+ when tuple_size(T) =:= (1 bsl 64) - 1 -> ok;
+ludicrous_tuple_size(T)
+ when tuple_size(T) =:= 16#FFFFFFFFFFFFFFFF -> ok;
+ludicrous_tuple_size(_) -> error.
+
+%%
+%% The binary_part/2,3 guard BIFs
+%%
+-define(MASK_ERROR(EXPR),mask_error((catch (EXPR)))).
+mask_error({'EXIT',{Err,_}}) ->
+ Err;
+mask_error(Else) ->
+ Else.
+
+binary_part(doc) ->
+ ["Tests the binary_part/2,3 guard (GC) bif's"];
+binary_part(Config) when is_list(Config) ->
+ %% This is more or less a copy of what the guard_SUITE in emulator
+ %% does to cover the guard bif's
+ ?line 1 = bptest(<<1,2,3>>),
+ ?line 2 = bptest(<<2,1,3>>),
+ ?line error = bptest(<<1>>),
+ ?line error = bptest(<<>>),
+ ?line error = bptest(apa),
+ ?line 3 = bptest(<<2,3,3>>),
+ % With one variable (pos)
+ ?line 1 = bptest(<<1,2,3>>,1),
+ ?line 2 = bptest(<<2,1,3>>,1),
+ ?line error = bptest(<<1>>,1),
+ ?line error = bptest(<<>>,1),
+ ?line error = bptest(apa,1),
+ ?line 3 = bptest(<<2,3,3>>,1),
+ % With one variable (length)
+ ?line 1 = bptesty(<<1,2,3>>,1),
+ ?line 2 = bptesty(<<2,1,3>>,1),
+ ?line error = bptesty(<<1>>,1),
+ ?line error = bptesty(<<>>,1),
+ ?line error = bptesty(apa,1),
+ ?line 3 = bptesty(<<2,3,3>>,2),
+ % With one variable (whole tuple)
+ ?line 1 = bptestx(<<1,2,3>>,{1,1}),
+ ?line 2 = bptestx(<<2,1,3>>,{1,1}),
+ ?line error = bptestx(<<1>>,{1,1}),
+ ?line error = bptestx(<<>>,{1,1}),
+ ?line error = bptestx(apa,{1,1}),
+ ?line 3 = bptestx(<<2,3,3>>,{1,2}),
+ % With two variables
+ ?line 1 = bptest(<<1,2,3>>,1,1),
+ ?line 2 = bptest(<<2,1,3>>,1,1),
+ ?line error = bptest(<<1>>,1,1),
+ ?line error = bptest(<<>>,1,1),
+ ?line error = bptest(apa,1,1),
+ ?line 3 = bptest(<<2,3,3>>,1,2),
+ % Direct (autoimported) call, these will be evaluated by the compiler...
+ ?line <<2>> = binary_part(<<1,2,3>>,1,1),
+ ?line <<1>> = binary_part(<<2,1,3>>,1,1),
+ % Compiler warnings due to constant evaluation expected (3)
+ ?line badarg = ?MASK_ERROR(binary_part(<<1>>,1,1)),
+ ?line badarg = ?MASK_ERROR(binary_part(<<>>,1,1)),
+ ?line badarg = ?MASK_ERROR(binary_part(apa,1,1)),
+ ?line <<3,3>> = binary_part(<<2,3,3>>,1,2),
+ % Direct call through apply
+ ?line <<2>> = apply(erlang,binary_part,[<<1,2,3>>,1,1]),
+ ?line <<1>> = apply(erlang,binary_part,[<<2,1,3>>,1,1]),
+ % Compiler warnings due to constant evaluation expected (3)
+ ?line badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<1>>,1,1])),
+ ?line badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<>>,1,1])),
+ ?line badarg = ?MASK_ERROR(apply(erlang,binary_part,[apa,1,1])),
+ ?line <<3,3>> = apply(erlang,binary_part,[<<2,3,3>>,1,2]),
+ % Constant propagation
+ ?line Bin = <<1,2,3>>,
+ ?line ok = if
+ binary_part(Bin,1,1) =:= <<2>> ->
+ ok;
+ %% Compiler warning, clause cannot match (expected)
+ true ->
+ error
+ end,
+ ?line ok = if
+ binary_part(Bin,{1,1}) =:= <<2>> ->
+ ok;
+ %% Compiler warning, clause cannot match (expected)
+ true ->
+ error
+ end,
+ ok.
+
+
+bptest(B) when length(B) =:= 1337 ->
+ 1;
+bptest(B) when binary_part(B,{1,1}) =:= <<2>> ->
+ 1;
+bptest(B) when erlang:binary_part(B,1,1) =:= <<1>> ->
+ 2;
+bptest(B) when erlang:binary_part(B,{1,2}) =:= <<3,3>> ->
+ 3;
+bptest(_) ->
+ error.
+
+bptest(B,A) when length(B) =:= A ->
+ 1;
+bptest(B,A) when binary_part(B,{A,1}) =:= <<2>> ->
+ 1;
+bptest(B,A) when erlang:binary_part(B,A,1) =:= <<1>> ->
+ 2;
+bptest(B,A) when erlang:binary_part(B,{A,2}) =:= <<3,3>> ->
+ 3;
+bptest(_,_) ->
+ error.
+
+bptestx(B,A) when length(B) =:= A ->
+ 1;
+bptestx(B,A) when binary_part(B,A) =:= <<2>> ->
+ 1;
+bptestx(B,A) when erlang:binary_part(B,A) =:= <<1>> ->
+ 2;
+bptestx(B,A) when erlang:binary_part(B,A) =:= <<3,3>> ->
+ 3;
+bptestx(_,_) ->
+ error.
+
+bptesty(B,A) when length(B) =:= A ->
+ 1;
+bptesty(B,A) when binary_part(B,{1,A}) =:= <<2>> ->
+ 1;
+bptesty(B,A) when erlang:binary_part(B,1,A) =:= <<1>> ->
+ 2;
+bptesty(B,A) when erlang:binary_part(B,{1,A}) =:= <<3,3>> ->
+ 3;
+bptesty(_,_) ->
+ error.
+
+bptest(B,A,_C) when length(B) =:= A ->
+ 1;
+bptest(B,A,C) when binary_part(B,{A,C}) =:= <<2>> ->
+ 1;
+bptest(B,A,C) when erlang:binary_part(B,A,C) =:= <<1>> ->
+ 2;
+bptest(B,A,C) when erlang:binary_part(B,{A,C}) =:= <<3,3>> ->
+ 3;
+bptest(_,_,_) ->
+ error.
+
+-define(FAILING(C),
+ if
+ C -> ?t:fail(should_fail);
+ true -> ok
+ end,
+ if
+ true, C -> ?t:fail(should_fail);
+ true -> ok
+ end).
+
+bad_constants(Config) when is_list(Config) ->
+ ?line ?FAILING(false),
+ ?line ?FAILING([]),
+ ?line ?FAILING([a]),
+ ?line ?FAILING([Config]),
+ ?line ?FAILING({a,b}),
+ ?line ?FAILING({a,Config}),
+ ?line ?FAILING(<<1>>),
+ ?line ?FAILING(42),
+ ?line ?FAILING(3.14),
+ ok.
%% Call this function to turn off constant propagation.
id(I) -> I.
@@ -1490,3 +1689,5 @@ check(F, Result) ->
io:format(" Got: ~p\n", [Other]),
test_server:fail()
end.
+
+fc({'EXIT',{function_clause,_}}) -> ok.
diff --git a/lib/debugger/test/int_eval_SUITE.erl b/lib/debugger/test/int_eval_SUITE.erl
index f36ed213d1..4ffcf7888e 100644
--- a/lib/debugger/test/int_eval_SUITE.erl
+++ b/lib/debugger/test/int_eval_SUITE.erl
@@ -28,7 +28,7 @@
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]).
+ interpreted_exit/1, otp_8310/1, stacktrace/1]).
%% Helpers.
-export([applier/3]).
@@ -44,7 +44,7 @@ all() ->
[bifs_outside_erlang, spawning, applying,
catch_and_throw, external_call, test_module_info,
apply_interpreted_fun, apply_uninterpreted_fun,
- interpreted_exit, otp_8310].
+ interpreted_exit, otp_8310, stacktrace].
groups() ->
[].
@@ -191,23 +191,23 @@ apply_interpreted_fun(Config) when is_list(Config) ->
?line {ok,ATerm} = spawn_eval(fun() -> F2() end),
%% Called from uninterpreted code, badarity
- ?line {'EXIT',{{badarity,{F1,[snape]}},[{?MODULE,_,_}|_]}} =
+ ?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,_}|_]}} =
+ ?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,_}|_]}} =
+ ?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,_}|_]}} =
+ ?line {'EXIT',{snape,[{?IM,_FunName,_,_}|_]}} =
spawn_eval(fun() -> ?IM:do_apply(F3, snape) end),
%% Try some more complex funs.
@@ -239,11 +239,11 @@ apply_uninterpreted_fun(Config) when is_list(Config) ->
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,_}|_]}} =
+ ?line {'EXIT',{{badarity,{F1,[]}},[{erlang,apply,_,_}|_]}} =
spawn_eval(fun() -> ?IM:do_apply(F1) end),
%% Error in fun
- ?line {'EXIT',{snape,[{?MODULE,_FunName,_}|_]}} =
+ ?line {'EXIT',{snape,[{?MODULE,_FunName,_,_}|_]}} =
spawn_eval(fun() -> ?IM:do_apply(F1, snape) end),
ok.
@@ -277,6 +277,37 @@ applier(M, F, A) ->
io:format("~p:~p(~p) => ~p\n", [M,F,A,Res]),
Res.
+stacktrace(Config) when is_list(Config) ->
+ ?line {done,Stk} = do_eval(Config, stacktrace),
+ ?line 13 = length(Stk),
+ ?line OldStackTraceFlag = int:stack_trace(),
+ ?line int:stack_trace(no_tail),
+ try
+ ?line Res = spawn_eval(fun() -> stacktrace:stacktrace() end),
+ ?line io:format("\nInterpreted (no_tail):\n~p", [Res]),
+ ?line {done,Stk} = Res
+ after
+ ?line int:stack_trace(OldStackTraceFlag)
+ end,
+ ok.
+
+
+do_eval(Config, Mod) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line ok = file:set_cwd(DataDir),
+
+ ?line {ok,Mod} = compile:file(Mod, [report,debug_info]),
+ ?line {module,Mod} = code:load_file(Mod),
+ ?line CompiledRes = Mod:Mod(),
+ ?line ok = io:format("Compiled:\n~p", [CompiledRes]),
+ io:nl(),
+
+ ?line {module,Mod} = int:i(Mod),
+ ?line IntRes = Mod:Mod(),
+ ?line ok = io:format("Interpreted:\n~p", [IntRes]),
+
+ ?line CompiledRes = IntRes.
+
%%
%% Evaluate in another process, to prevent the test_case process to become
%% interpreted.
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
index 997ee6e17d..90f83e80e8 100644
--- 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
@@ -117,7 +117,7 @@ more_nocatch(Fun) ->
%% External calls.
external_call_test(Data) ->
- {'EXIT',{undef,[{?MODULE,not_exported,[42,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),
@@ -127,7 +127,7 @@ external_call_test(Data) ->
{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]}|_]}} =
+ {'EXIT',{undef,[{?MODULE,not_exported,[7,Data],_}|_]}} =
(catch ?MODULE:not_exported(7, Data)),
{yes,Data} = ?MODULE:i_am_exported(Data),
ok.
diff --git a/lib/debugger/test/int_eval_SUITE_data/stacktrace.erl b/lib/debugger/test/int_eval_SUITE_data/stacktrace.erl
new file mode 100644
index 0000000000..3380178fdc
--- /dev/null
+++ b/lib/debugger/test/int_eval_SUITE_data/stacktrace.erl
@@ -0,0 +1,130 @@
+-module(stacktrace).
+-export([?MODULE/0]).
+
+?MODULE() ->
+ OldDepth = erlang:system_flag(backtrace_depth, 32),
+ done = (catch do_try()),
+ Stk = trim(erlang:get_stacktrace()),
+ erlang:system_flag(backtrace_depth, OldDepth),
+ {done,Stk}.
+
+trim([{int_eval_SUITE,_,_,_}|_]) ->
+ [];
+trim([H|T]) ->
+ [H|trim(T)];
+trim([]) -> [].
+
+do_try() ->
+ try
+ 0 = id(42)
+ catch
+ error:{badmatch,42} ->
+ do_try2() %Tail-recursive
+ end.
+
+do_try2() ->
+ try
+ 0 = id(42)
+ catch
+ error:{badmatch,42} ->
+ do_try3() %Not tail-recursive
+ end,
+ ?LINE.
+
+do_try3() ->
+ try id(42) of
+ 42 -> do_try4() %Tail-recursive
+ catch
+ error:ignore -> %Should never catch
+ ?LINE
+ end.
+
+do_try4() ->
+ try
+ do_recv() %Not tail-recursive
+ catch
+ error:ignore -> %Should never catch
+ ?LINE
+ end.
+
+do_recv() ->
+ self() ! x,
+ receive
+ x -> do_recv2() %Not tail-recursive
+ end,
+ ?LINE.
+
+do_recv2() ->
+ self() ! y,
+ receive
+ y -> do_recv3() %Tail-recursive
+ end.
+
+do_recv3() ->
+ receive
+ after 0 -> do_recv4() %Tail-recursive
+ end.
+
+do_recv4() ->
+ receive
+ after 0 -> do_if(true) %Not tail-recursive
+ end,
+ ?LINE.
+
+do_if(Bool) ->
+ if
+ Bool -> do_if2(Bool) %Tail-recursive
+ end.
+
+do_if2(Bool) ->
+ if
+ Bool -> do_case(Bool) %Not tail-recursive
+ end,
+ ?LINE.
+
+
+do_case(Bool) ->
+ case Bool of
+ true -> do_case2(Bool) %Tail-recursive
+ end.
+
+do_case2(Bool) ->
+ case Bool of
+ true -> do_fun(Bool) %Not tail-recursive
+ end,
+ ?LINE.
+
+do_fun(Bool) ->
+ F = fun(true) ->
+ do_fun2(Bool) %Tail-recursive
+ end,
+ F(Bool). %Tail-recursive
+
+do_fun2(Bool) ->
+ F = fun(true) ->
+ cons(Bool) %Tail-recursive
+ end,
+ F(Bool), %Not tail-recursive
+ ?LINE.
+
+cons(Bool) ->
+ [Bool|tuple()].
+
+tuple() ->
+ {ok,op()}.
+
+op() ->
+ 1 + lc().
+
+lc() ->
+ [done() || true].
+
+done() ->
+ tail(100),
+ throw(done).
+
+tail(0) -> ok;
+tail(N) -> tail(N-1).
+
+id(I) ->
+ I.
diff --git a/lib/debugger/test/lc_SUITE.erl b/lib/debugger/test/lc_SUITE.erl
index 92a03ef58e..2f05eb7fca 100644
--- a/lib/debugger/test/lc_SUITE.erl
+++ b/lib/debugger/test/lc_SUITE.erl
@@ -17,21 +17,22 @@
%% %CopyrightEnd%
%%
-%%
-module(lc_SUITE).
--author('[email protected]').
+%% Copied from lc_SUITE in the compiler application.
+
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
init_per_suite/1,end_per_suite/1,
- basic/1]).
+ basic/1,deeply_nested/1,no_generator/1,
+ empty_generator/1]).
-include_lib("test_server/include/test_server.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- cases().
+ [basic, deeply_nested, no_generator, empty_generator].
groups() ->
[].
@@ -42,10 +43,6 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-
-cases() ->
- [basic].
-
init_per_testcase(_Case, Config) ->
test_lib:interpret(?MODULE),
Dog = test_server:timetrap(?t:minutes(1)),
@@ -64,7 +61,7 @@ init_per_suite(Config) when is_list(Config) ->
end_per_suite(Config) when is_list(Config) ->
ok.
-basic(Config) when list(Config) ->
+basic(Config) when is_list(Config) ->
?line L0 = lists:seq(1, 10),
?line L1 = my_map(fun(X) -> {x,X} end, L0),
?line L1 = [{x,X} || X <- L0],
@@ -73,16 +70,116 @@ basic(Config) when list(Config) ->
?line [4,5,6] = [X || X <- L0, X > 3, X < 7],
?line [] = [X || X <- L0, X > 32, X < 7],
?line [1,3,5,7,9] = [X || X <- L0, odd(X)],
+ ?line [2,4,6,8,10] = [X || X <- L0, not odd(X)],
+ ?line [1,3,5,9] = [X || X <- L0, odd(X), X =/= 7],
+ ?line [2,4,8,10] = [X || X <- L0, not odd(X), X =/= 6],
+
+ %% Append is specially handled.
+ ?line [1,3,5,9,2,4,8,10] = [X || X <- L0, odd(X), X =/= 7] ++
+ [X || X <- L0, not odd(X), X =/= 6],
+
+ %% Guards BIFs are evaluated in guard context. Weird, but true.
+ ?line [{a,b,true},{x,y,true,true}] = [X || X <- tuple_list(), element(3, X)],
+
+ %% Filter expressions with andalso/orelse.
+ ?line "abc123" = alphanum("?abc123.;"),
%% Error cases.
- ?line [] = [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)]),
+ ?line {'EXIT',_} = (catch [X || X <- L1, list_to_atom(X) == dum]),
+ ?line [] = [X || X <- L1, X+1 < 2],
+ ?line {'EXIT',_} = (catch [X || X <- L1, odd(X)]),
+ %% A bad generator has a different exception compared to BEAM.
+ ?line {'EXIT',{{bad_generator,x},_}} = (catch [E || E <- id(x)]),
ok.
+tuple_list() ->
+ [{a,b,true},[a,b,c],glurf,{a,b,false,xx},{a,b},{x,y,true,true},{a,b,d,ddd}].
+
my_map(F, L) ->
[F(X) || X <- L].
odd(X) ->
X rem 2 == 1.
+
+alphanum(Str) ->
+ [C || C <- Str, ((C >= $0) andalso (C =< $9))
+ orelse ((C >= $a) andalso (C =< $z))
+ orelse ((C >= $A) andalso (C =< $Z))].
+
+deeply_nested(Config) when is_list(Config) ->
+ [[99,98,97,96,42,17,1764,12,11,10,9,8,7,6,5,4,3,7,2,1]] = deeply_nested_1(),
+ ok.
+
+deeply_nested_1() ->
+ %% This used to compile really, really SLOW before R11B-1...
+ [[X1,X2,X3,X4,X5,X6,X7(),X8,X9,X10,X11,X12,X13,X14,X15,X16,X17,X18(),X19,X20] ||
+ X1 <- [99],X2 <- [98],X3 <- [97],X4 <- [96],X5 <- [42],X6 <- [17],
+ X7 <- [fun() -> X5*X5 end],X8 <- [12],X9 <- [11],X10 <- [10],
+ X11 <- [9],X12 <- [8],X13 <- [7],X14 <- [6],X15 <- [5],
+ X16 <- [4],X17 <- [3],X18 <- [fun() -> X16+X17 end],X19 <- [2],X20 <- [1]].
+
+no_generator(Config) when is_list(Config) ->
+ ?line Seq = lists:seq(-10, 17),
+ ?line [no_gen_verify(no_gen(A, B), A, B) || A <- Seq, B <- Seq],
+
+ %% Literal expression, for coverage.
+ ?line [a] = [a || true],
+ ?line [a,b,c] = [a || true] ++ [b,c],
+ ok.
+
+no_gen(A, B) ->
+ [{A,B} || A+B =:= 0] ++
+ [{A,B} || A*B =:= 0] ++
+ [{A,B} || A rem B =:= 3] ++
+ [{A,B} || A =:= B] ++
+ [{one_more,A,B} || no_gen_one_more(A, B)] ++
+ [A || A =:= 1] ++
+ [A || A =:= 2] ++
+ [A || A =:= 3] ++
+ [A || A =:= 4] ++
+ [A || A =:= 5] ++
+ [A || A =:= 6] ++
+ [A || A =:= 7] ++
+ [A || A =:= 8] ++
+ [A || A =:= 9] ++
+ [B || B =:= 1] ++
+ [B || B =:= 2] ++
+ [B || B =:= 3] ++
+ [B || B =:= 4] ++
+ [B || B =:= 5] ++
+ [B || B =:= 6] ++
+ [B || B =:= 7] ++
+ [B || B =:= 8] ++
+ [B || B =:= 9].
+
+no_gen_verify(Res, A, B) ->
+ Pair = {A,B},
+ ShouldBe = no_gen_eval(fun() -> A+B =:= 0 end, Pair) ++
+ no_gen_eval(fun() -> A*B =:= 0 end, Pair) ++
+ no_gen_eval(fun() -> B =/= 0 andalso A rem B =:= 3 end, Pair) ++
+ no_gen_eval(fun() -> A =:= B end, Pair) ++
+ no_gen_eval(fun() -> A + 1 =:= B end, {one_more,A,B}) ++
+ no_gen_eval(fun() -> 1 =< A andalso A =< 9 end, A) ++
+ no_gen_eval(fun() -> 1 =< B andalso B =< 9 end, B),
+ case Res of
+ ShouldBe -> ok;
+ _ ->
+ io:format("A = ~p; B = ~p; Expected = ~p, actual = ~p", [A,B,ShouldBe,Res]),
+ ?t:fail()
+ end.
+
+no_gen_eval(Fun, Res) ->
+ case Fun() of
+ true -> [Res];
+ false -> []
+ end.
+
+no_gen_one_more(A, B) -> A + 1 =:= B.
+
+empty_generator(Config) when is_list(Config) ->
+ ?line [] = [X || {X} <- [], (false or (X/0 > 3))],
+ ok.
+
+id(I) -> I.
diff --git a/lib/debugger/test/line_number_SUITE.erl b/lib/debugger/test/line_number_SUITE.erl
new file mode 100644
index 0000000000..d1f56d3493
--- /dev/null
+++ b/lib/debugger/test/line_number_SUITE.erl
@@ -0,0 +1,220 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(line_number_SUITE).
+
+-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
+ init_per_testcase/2,end_per_testcase/2,
+ init_per_suite/1,end_per_suite/1,
+ line_numbers/1]).
+-export([crash/1]).
+
+-include_lib("test_server/include/test_server.hrl").
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ cases().
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+cases() ->
+ [line_numbers].
+
+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_per_suite(Config) when is_list(Config) ->
+ ?line test_lib:interpret(?MODULE),
+ ?line true = lists:member(?MODULE, int:interpreted()),
+ Config.
+
+end_per_suite(Config) when is_list(Config) ->
+ ok.
+
+
+
+
+
+%%
+%% === Make sure that this is always line 70 ===
+%%
+line1(Tag, X) -> %Line 72
+ case Tag of %Line 73
+ a ->
+ Y = X + 1, %Line 75
+ Res = id({ok,Y}), %Line 76
+ ?MODULE:crash({ok,42} = Res); %Line 77
+ b ->
+ x = id(x), %Line 79
+ ok %Line 80
+ end. %Line 81
+
+crash(_) -> %Line 83
+ erlang:error(crash). %Line 84
+
+close_calls(Where) -> %Line 86
+ put(where_to_crash, Where), %Line 87
+ try
+ call1(), %Line 89
+ call2(), %Line 90
+ call3(), %Line 91
+ no_crash %Line 92
+ catch error:crash ->
+ erlang:get_stacktrace() %Line 94
+ end. %Line 95
+
+call1() -> %Line 97
+ maybe_crash(call1), %Line 98
+ ok. %Line 99
+
+call2() -> %Line 101
+ maybe_crash(call2), %Line 102
+ ok. %Line 103
+
+call3() -> %Line 105
+ maybe_crash(call3), %Line 106
+ ok. %Line 107
+
+maybe_crash(Name) -> %Line 109
+ case get(where_to_crash) of %Line 110
+ Name ->
+ erlang:error(crash); %Line 112
+ _ ->
+ ok %Line 114
+ end. %Line 115
+
+build_binary1(Size) -> %Line 117
+ id(42), %Line 118
+ <<0:Size>>. %Line 119
+
+build_binary2(Size, Bin) -> %Line 121
+ id(0), %Line 122
+ <<7:Size,Bin/binary>>. %Line 123
+
+do_call_abs(x, Arg) -> %Line 125
+ abs(Arg). %Line 126
+
+do_call_unsafe_bif(x, Arg) -> %Line 128
+ link(Arg). %Line 129
+
+
+line_numbers(Config) when is_list(Config) ->
+ File = ?MODULE_STRING ++ ".erl",
+ {'EXIT',{{case_clause,bad_tag},
+ [{?MODULE,line1,2,
+ [{file,File},{line,73}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch line1(bad_tag, 0)),
+ {'EXIT',{badarith,
+ [{?MODULE,line1,2,
+ [{file,File},{line,75}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch line1(a, not_an_integer)),
+ {'EXIT',{{badmatch,{ok,1}},
+ [{?MODULE,line1,2,
+ [{file,File},{line,77}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch line1(a, 0)),
+ {'EXIT',{crash,
+ [{?MODULE,crash,1,
+ [{file,File},{line,84}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch line1(a, 41)),
+
+ [{?MODULE,maybe_crash,1,[{file,File},{line,112}]},
+ {?MODULE,call1,0,[{file,File},{line,98}]},
+ {?MODULE,close_calls,1,[{file,File},{line,89}]},
+ {?MODULE,line_numbers,1,[{file,File},{line,_}]}|_] =
+ close_calls(call1),
+ [{?MODULE,maybe_crash,1,[{file,File},{line,112}]},
+ {?MODULE,call2,0,[{file,File},{line,102}]},
+ {?MODULE,close_calls,1,[{file,File},{line,90}]},
+ {?MODULE,line_numbers,1,[{file,File},{line,_}]}|_] =
+ close_calls(call2),
+ [{?MODULE,maybe_crash,1,[{file,File},{line,112}]},
+ {?MODULE,call3,0,[{file,File},{line,106}]},
+ {?MODULE,close_calls,1,[{file,File},{line,91}]},
+ {?MODULE,line_numbers,1,[{file,File},{line,_}]}|_] =
+ close_calls(call3),
+ no_crash = close_calls(other),
+
+ <<0,0>> = build_binary1(16),
+ {'EXIT',{badarg,
+ [{?MODULE,build_binary1,1,
+ [{file,File},{line,119}]},
+ {?MODULE,line_numbers,1,
+ [{file,ModFile},{line,_}]}|_]}} =
+ (catch build_binary1(bad_size)),
+
+ <<7,1,2,3>> = build_binary2(8, <<1,2,3>>),
+ {'EXIT',{badarg,
+ [{?MODULE,build_binary2,2,
+ [{file,File},{line,123}]},
+ {?MODULE,line_numbers,1,
+ [{file,ModFile},{line,_}]}|_]}} =
+ (catch build_binary2(bad_size, <<>>)),
+ {'EXIT',{badarg,
+ [%% Beam has an extra here:
+ %% {erlang,bit_size,[bad_binary],[]}
+ %% Since this is an artifact of the implementation,
+ %% we don't attempt to mimic it in the debugger.
+ {?MODULE,build_binary2,2,
+ [{file,File},{line,123}]},
+ {?MODULE,line_numbers,1,
+ [{file,ModFile},{line,_}]}|_]}} =
+ (catch build_binary2(8, bad_binary)),
+
+ {'EXIT',{function_clause,
+ [{?MODULE,do_call_abs,[y,y],
+ [{file,File},{line,125}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch do_call_abs(y, y)),
+ {'EXIT',{badarg,
+ [{erlang,abs,[[]],[]},
+ {?MODULE,do_call_abs,2,
+ [{file,File},{line,126}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch do_call_abs(x, [])),
+
+ {'EXIT',{badarg,
+ [{erlang,link,[[]],[]},
+ {?MODULE,do_call_unsafe_bif,2,
+ [{file,File},{line,129}]},
+ {?MODULE,line_numbers,1,_}|_]}} =
+ (catch do_call_unsafe_bif(x, [])),
+
+ ok.
+
+id(I) ->
+ I.
diff --git a/lib/debugger/test/test_lib.erl b/lib/debugger/test/test_lib.erl
index 541375e64a..5e4ac7f164 100644
--- a/lib/debugger/test/test_lib.erl
+++ b/lib/debugger/test/test_lib.erl
@@ -22,7 +22,7 @@
-export([interpret/1]).
-interpret(Mod) when atom(Mod) ->
+interpret(Mod) when is_atom(Mod) ->
case lists:member(Mod, int:interpreted()) of
true -> ok;
false -> {module,Mod} = i:ii(Mod)
diff --git a/lib/debugger/test/trycatch_SUITE.erl b/lib/debugger/test/trycatch_SUITE.erl
index a87c5db138..470d46d915 100644
--- a/lib/debugger/test/trycatch_SUITE.erl
+++ b/lib/debugger/test/trycatch_SUITE.erl
@@ -318,17 +318,18 @@ 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} =
+ ?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,_}|_]}}} =
+ ?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}} =
+ ?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}} =
+ ?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} =
@@ -337,15 +338,15 @@ eclectic(Conf) when is_list(Conf) ->
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} =
+ ?line {{caught,{'EXIT',{V,[{?MODULE,foo,_,_}|_]}}},undefined} =
eclectic_2({error,{value,V}}, throw, {error,V}),
- ?line {{caught,{'EXIT',{badarg,[{erlang,abs,[V]}|_]}}},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} =
+ ?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} =
+ ?line {{caught,{'EXIT',{V,[{?MODULE,foo,_,_}|_]}}},undefined} =
eclectic_2({throw,{'div',{1,0}}}, throw, {error,V}),
ok.
diff --git a/lib/dialyzer/doc/manual.txt b/lib/dialyzer/doc/manual.txt
index 1d7a1a6222..d519ac960b 100644
--- a/lib/dialyzer/doc/manual.txt
+++ b/lib/dialyzer/doc/manual.txt
@@ -37,7 +37,7 @@ The parameters are:
The analysis starts from .beam bytecode files.
The files must be compiled with +debug_info.
- Source code:
- The analysis starts from .erl files.
+ The analysis starts from .erl files.
Controlling the discrepancies reported by the Dialyzer
======================================================
@@ -131,7 +131,7 @@ Usage: dialyzer [--help] [--version] [--shell] [--quiet] [--verbose]
[--check_plt] [--no_check_plt] [--plt_info] [--get_warnings]
[--no_native] [--fullpath]
-Options:
+Options:
files_or_dirs (for backwards compatibility also as: -c files_or_dirs)
Use Dialyzer from the command line to detect defects in the
specified files or directories containing .erl or .beam files,
@@ -169,7 +169,7 @@ Options:
--output_plt file
Store the plt at the specified file after building it.
--plt plt
- Use the specified plt as the initial plt (if the plt was built
+ Use the specified plt as the initial plt (if the plt was built
during setup the files will be checked for consistency).
--plts plt*
Merge the specified plts to create the initial plt -- requires
@@ -204,8 +204,8 @@ Options:
--add_to_plt
The plt is extended to also include the files specified with -c and -r.
Use --plt to specify which plt to start from, and --output_plt to
- specify where to put the plt. Note that the analysis might include
- files from the plt if they depend on the new files.
+ specify where to put the plt. Note that the analysis might include
+ files from the plt if they depend on the new files.
This option only works with beam files.
--remove_from_plt
The information from the files specified with -c and -r is removed
@@ -269,13 +269,13 @@ Warning options:
Include warnings about behaviour callbacks which drift from the published
recommended interfaces.
-Wunderspecs ***
- Warn about underspecified functions
+ Warn about underspecified functions
(those whose -spec is strictly more allowing than the success typing).
The following options are also available but their use is not recommended:
(they are mostly for Dialyzer developers and internal debugging)
-Woverspecs ***
- Warn about overspecified functions
+ Warn about overspecified functions
(those whose -spec is strictly less allowing than the success typing).
-Wspecdiffs ***
Warn when the -spec is different than the success typing.
@@ -306,8 +306,8 @@ dialyzer:run(OptList) -> Warnings
Warnings :: [{tag(), id(), msg()}]
tag() :: 'warn_return_no_exit' | 'warn_return_only_exit' | 'warn_not_called'
| 'warn_non_proper_list' | 'warn_fun_app' | 'warn_matching'
- | 'warn_failing_call' | 'warn_contract_types'
- | 'warn_contract_syntax' | 'warn_contract_not_equal'
+ | 'warn_failing_call' | 'warn_contract_types'
+ | 'warn_contract_syntax' | 'warn_contract_not_equal'
| 'warn_contract_subtype' | 'warn_contract_supertype'
id() :: {File :: string(), Line :: integer()}
msg() :: Undefined
@@ -319,24 +319,31 @@ Option :: {files, [Filename :: string()]}
| {from, src_code | byte_code} %% Defaults to byte_code
| {init_plt, FileName :: string()} %% If changed from default
| {plts, [FileName :: string()]} %% If changed from default
- | {include_dirs, [DirName :: string()]}
+ | {include_dirs, [DirName :: string()]}
| {output_file, FileName :: string()}
| {output_plt, FileName :: string()}
| {analysis_type, 'succ_typings' | 'plt_add' |
'plt_build' | 'plt_check' | 'plt_remove'}
| {warnings, [WarnOpts]}
+ | {get_warnings, bool()}
WarnOpts :: no_return
| no_unused
| no_improper_lists
| no_fun_app
| no_match
+ | no_opaque
| no_fail_call
- | unmatched_returns
| error_handling
+ | race_conditions
+ | behaviours
+ | unmatched_returns
+ | overspecs
+ | underspecs
+ | specdiffs
dialyzer:format_warning({tag(), id(), msg()}) -> string()
-
+
Returns a string representation of the warnings as returned by dialyzer:run/1.
dialyzer:plt_info(string()) -> {'ok', [{atom(), any()}]} | {'error', atom()}
@@ -392,7 +399,7 @@ files that depend on these files. Note that this consistency check
will be performed automatically the next time you run Dialyzer with
this plt. The --check_plt option is merely for doing so without doing
any other analysis.
-
+
-----------------------------------------------
--
-- Feedback & bug reports
diff --git a/lib/dialyzer/doc/src/dialyzer.xml b/lib/dialyzer/doc/src/dialyzer.xml
index b6547b11e1..4080dfdf77 100644
--- a/lib/dialyzer/doc/src/dialyzer.xml
+++ b/lib/dialyzer/doc/src/dialyzer.xml
@@ -241,7 +241,7 @@
<item>Include warnings about behaviour callbacks which drift from the
published recommended interfaces.</item>
<tag><c><![CDATA[-Wunderspecs]]></c>***</tag>
- <item>Warn about underspecified functions
+ <item>Warn about underspecified functions
(the -spec is strictly more allowing than the success typing).</item>
</taglist>
<p>The following options are also available but their use is not
@@ -249,7 +249,7 @@
debugging)</p>
<taglist>
<tag><c><![CDATA[-Woverspecs]]></c>***</tag>
- <item>Warn about overspecified functions
+ <item>Warn about overspecified functions
(the -spec is strictly less allowing than the success typing).</item>
<tag><c><![CDATA[-Wspecdiffs]]></c>***</tag>
<item>Warn when the -spec is different than the success typing.</item>
@@ -278,34 +278,34 @@
<desc>
<p>Dialyzer GUI version.</p>
<code type="none"><![CDATA[
-OptList : [Option]
-Option : {files, [Filename : string()]}
- | {files_rec, [DirName : string()]}
- | {defines, [{Macro: atom(), Value : term()}]}
- | {from, src_code | byte_code} %% Defaults to byte_code
- | {init_plt, FileName : string()} %% If changed from default
- | {plts, [FileName :: string()]} %% If changed from default
- | {include_dirs, [DirName : string()]}
- | {output_file, FileName : string()}
- | {output_plt, FileName :: string()}
- | {analysis_type, 'succ_typings' | 'plt_add' | 'plt_build' | 'plt_check' | 'plt_remove'}
- | {warnings, [WarnOpts]}
- | {get_warnings, bool()}
+OptList :: [Option]
+Option :: {files, [Filename :: string()]}
+ | {files_rec, [DirName :: string()]}
+ | {defines, [{Macro: atom(), Value : term()}]}
+ | {from, src_code | byte_code} %% Defaults to byte_code
+ | {init_plt, FileName :: string()} %% If changed from default
+ | {plts, [FileName :: string()]} %% If changed from default
+ | {include_dirs, [DirName :: string()]}
+ | {output_file, FileName :: string()}
+ | {output_plt, FileName :: string()}
+ | {analysis_type, 'succ_typings' | 'plt_add' | 'plt_build' | 'plt_check' | 'plt_remove'}
+ | {warnings, [WarnOpts]}
+ | {get_warnings, bool()}
-WarnOpts : no_return
- | no_unused
- | no_improper_lists
- | no_fun_app
- | no_match
- | no_opaque
- | no_fail_call
- | error_handling
- | race_conditions
- | behaviours
- | unmatched_returns
- | overspecs
- | underspecs
- | specdiffs
+WarnOpts :: no_return
+ | no_unused
+ | no_improper_lists
+ | no_fun_app
+ | no_match
+ | no_opaque
+ | no_fail_call
+ | error_handling
+ | race_conditions
+ | behaviours
+ | unmatched_returns
+ | overspecs
+ | underspecs
+ | specdiffs
]]></code>
</desc>
</func>
@@ -320,12 +320,12 @@ WarnOpts : no_return
<p>Dialyzer command line version.</p>
<code type="none"><![CDATA[
Warnings :: [{Tag, Id, Msg}]
-Tag : 'warn_return_no_exit' | 'warn_return_only_exit'
- | 'warn_not_called' | 'warn_non_proper_list'
- | 'warn_fun_app' | 'warn_matching'
- | 'warn_failing_call' | 'warn_contract_types'
- | 'warn_contract_syntax' | 'warn_contract_not_equal'
- | 'warn_contract_subtype' | 'warn_contract_supertype'
+Tag :: 'warn_return_no_exit' | 'warn_return_only_exit'
+ | 'warn_not_called' | 'warn_non_proper_list'
+ | 'warn_fun_app' | 'warn_matching'
+ | 'warn_failing_call' | 'warn_contract_types'
+ | 'warn_contract_syntax' | 'warn_contract_not_equal'
+ | 'warn_contract_subtype' | 'warn_contract_supertype'
Id = {File :: string(), Line :: integer()}
Msg = msg() -- Undefined
]]></code>
diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml
index f132a50e0d..17291b24f7 100755
--- a/lib/dialyzer/doc/src/notes.xml
+++ b/lib/dialyzer/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2006</year><year>2010</year>
+ <year>2006</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,154 @@
<p>This document describes the changes made to the Dialyzer
application.</p>
+<section><title>Dialyzer 2.4.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Update results of race_SUITE/extract_translations Update
+ results of small_SUITE/flatten Add codec_can and
+ list_to_bitstring tests Fix bug when reporting unused
+ functions Update Dialyzer r9c_suite results Fix dialyzer
+ warning on default clause for binary comprehension
+ (Thanks to Ivan Dubrov)</p>
+ <p>
+ Own Id: OTP-9483</p>
+ </item>
+ <item>
+ <p>
+ Fix server loop detection</p>
+ <p>
+ Dialyzer does not normally emit warnings for functions
+ that implement non-terminating server loops. This
+ detection failed when some of the elements in an SCC
+ terminated normally (being for example list
+ comprehensions or other generic anonymous functions that
+ were included in the SCC). This patch fixes that.</p>
+ <p>
+ Own Id: OTP-9489</p>
+ </item>
+ <item>
+ <p>
+ Add a proplist() type</p>
+ <p>
+ Recently I was adding specs to an API and found that
+ there is no canonical proplist() type defined. (Thanks to
+ Ryan Zezeski)</p>
+ <p>
+ Own Id: OTP-9499</p>
+ </item>
+ <item>
+ <p>
+ Suppress some warnings about generation of non-returning
+ funs</p>
+ <p>
+ No warnings are emitted for funs that are non-returning
+ when the function that generates them has a contract that
+ specifies that it will return such a non-returning fun.</p>
+ <p>
+ Enhance Dialyzer's inference on comparisons</p>
+ <p>
+ This patch makes Dialyzer aware of Erlang's total
+ ordering of terms, enabling discrepancy detection in
+ cases where e.g. integer() &lt; tuple() is treated as a
+ comparison that might also return false (when it is
+ certain to always return true).</p>
+ <p>
+ Minor fix in dead code</p>
+ <p>
+ Fix infinite loop in dataflow</p>
+ <p>
+ Update r9c/{inets,mnesia} results in dialyzer's test
+ suite</p>
+ <p>
+ Add origin information to #fun_var closures</p>
+ <p>
+ (Thanks to Tuncer Ayaz and Maria Christakis)</p>
+ <p>
+ Own Id: OTP-9529</p>
+ </item>
+ <item>
+ <p>
+ Quote atoms if necessary in types</p>
+ <p>
+ Atoms in some occurrences were not correctly quoted when
+ formatted to strings, for instance by the typer program
+ (Thanks to Tomas Abrahamsson)</p>
+ <p>
+ Update Dialyzer's reference results</p>
+ <p>
+ Own Id: OTP-9560</p>
+ </item>
+ <item>
+ <p>
+ Fix typer's crash for nonexisting files Remove unused
+ macro Fix bug in dataflow Decrease tuple arity limit This
+ fixes a memory related crash.</p>
+ <p>
+ Own Id: OTP-9597</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Types for several BIFs have been extended/corrected. Also
+ the types for types for <c>lists:keyfind/3</c>,
+ <c>lists:keysearch/3</c>, and <c>lists:keyemember/3</c>
+ have been corrected. The incorrect/incomplete types could
+ cause false dialyzer warnings.</p>
+ <p>
+ Own Id: OTP-9496</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Dialyzer 2.4.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix the name of an error function(Thanks to Maria
+ christakis)</p>
+ <p>
+ Own Id: OTP-9175</p>
+ </item>
+ <item>
+ <p>
+ Fix crash related with the contract blame assignment
+ patch</p>
+ <p>
+ Own Id: OTP-9219</p>
+ </item>
+ <item>
+ <p>
+ dialyzer/doc: synchronize manual.txt and dialyzer.xml
+ (Thanks to Tuncer Ayaz)</p>
+ <p>
+ Own Id: OTP-9226</p>
+ </item>
+ <item>
+ <p>
+ Simplify Dialyzer's test suite structure</p>
+ <p>
+ *_SUITE.erl files are now automatically generated by the
+ respective data directories by the Makefile.</p>
+ <p>
+ Own Id: OTP-9278</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Dialyzer 2.4.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl
index 7137dbc036..d74c04385b 100644
--- a/lib/dialyzer/src/dialyzer_dataflow.erl
+++ b/lib/dialyzer/src/dialyzer_dataflow.erl
@@ -528,7 +528,7 @@ handle_apply(Tree, Map, State) ->
{CallSitesKnown, FunList} =
case state__lookup_call_site(Tree, State2) of
error -> {false, []};
- {ok, [external]} -> {false, {}};
+ {ok, [external]} -> {false, []};
{ok, List} -> {true, List}
end,
case CallSitesKnown of
@@ -554,7 +554,13 @@ handle_apply(Tree, Map, State) ->
{State3, enter_type(Op, OpType1, Map2), t_none()};
false ->
Map3 = enter_type_lists(Args, NewArgs, Map2),
- {State2, enter_type(Op, OpType1, Map3), t_fun_range(OpType1)}
+ Range0 = t_fun_range(OpType1),
+ Range =
+ case t_is_unit(Range0) of
+ true -> t_none();
+ false -> Range0
+ end,
+ {State2, enter_type(Op, OpType1, Map3), Range}
end
end;
true ->
@@ -1393,10 +1399,14 @@ do_clause(C, Arg, ArgType0, OrigArgType, Map,
true -> Any = t_any(), [Any || _ <- Pats];
false -> t_to_tlist(OrigArgType)
end,
- case bind_pat_vars(Pats, OrigArgTypes, [], Map1, State1) of
- {error, bind, _, _, _} -> {{pattern_match, PatTypes}, false};
- {_, _} -> {{pattern_match_cov, PatTypes}, false}
- end;
+ Tag =
+ case bind_pat_vars(Pats, OrigArgTypes, [], Map1, State1) of
+ {error, bind, _, _, _} -> pattern_match;
+ {error, record, _, _, _} -> record_match;
+ {error, opaque, _, _, _} -> opaque_match;
+ {_, _} -> pattern_match_cov
+ end,
+ {{Tag, PatTypes}, false};
false ->
%% Try to find out if this is a default clause in a list
%% comprehension and supress this. A real Hack(tm)
@@ -1414,6 +1424,17 @@ do_clause(C, Arg, ArgType0, OrigArgType, Map,
false ->
true
end;
+ [Pat0, Pat1] -> % binary comprehension
+ case cerl:is_c_cons(Pat0) of
+ true ->
+ not (cerl:is_c_var(cerl:cons_hd(Pat0)) andalso
+ cerl:is_c_var(cerl:cons_tl(Pat0)) andalso
+ cerl:is_c_var(Pat1) andalso
+ cerl:is_literal(Guard) andalso
+ (cerl:concrete(Guard) =:= true));
+ false ->
+ true
+ end;
_ -> true
end;
false ->
@@ -1425,12 +1446,12 @@ do_clause(C, Arg, ArgType0, OrigArgType, Map,
opaque -> [PatString, format_type(Type, State1),
format_type(OpaqueTerm, State1)]
end,
- FailedMsg = case ErrorType of
- bind -> {pattern_match, PatTypes};
- record -> {record_match, PatTypes};
- opaque -> {opaque_match, PatTypes}
+ FailedTag = case ErrorType of
+ bind -> pattern_match;
+ record -> record_match;
+ opaque -> opaque_match
end,
- {FailedMsg, Force0}
+ {{FailedTag, PatTypes}, Force0}
end,
WarnType = case Msg of
{opaque_match, _} -> ?WARN_OPAQUE;
@@ -2915,7 +2936,7 @@ state__get_warnings(#state{tree_map = TreeMap, fun_tab = FunTab,
{Warn, Msg} =
case dialyzer_callgraph:lookup_name(FunLbl, Callgraph) of
error -> {true, {unused_fun, []}};
- {ok, {_M, F, A}} = MFA ->
+ {ok, {_M, F, A} = MFA} ->
{not sets:is_element(MFA, NoWarnUnused),
{unused_fun, [F, A]}}
end,
@@ -2935,7 +2956,7 @@ state__get_warnings(#state{tree_map = TreeMap, fun_tab = FunTab,
%% Check if the function has a contract that allows this.
Warn =
case Contract of
- none -> true;
+ none -> not parent_allows_this(FunLbl, State);
{value, C} ->
GenRet = dialyzer_contracts:get_contract_return(C),
not t_is_unit(GenRet)
@@ -3423,6 +3444,33 @@ map_pats(Pats) ->
end,
cerl_trees:map(Fun, Pats).
+parent_allows_this(FunLbl, #state{callgraph = Callgraph, plt = Plt} =State) ->
+ case state__is_escaping(FunLbl, State) of
+ false -> false; % if it isn't escaping it can't be a return value
+ true ->
+ case state__lookup_name(FunLbl, State) of
+ {_M, _F, _A} -> false; % if it has a name it is not a fun
+ _ ->
+ case dialyzer_callgraph:in_neighbours(FunLbl, Callgraph) of
+ [Parent] ->
+ case state__lookup_name(Parent, State) of
+ {_M, _F, _A} = PMFA ->
+ case dialyzer_plt:lookup_contract(Plt, PMFA) of
+ none -> false;
+ {value, C} ->
+ GenRet = dialyzer_contracts:get_contract_return(C),
+ case erl_types:t_is_fun(GenRet) of
+ false -> false; % element of structure? far-fetched...
+ true -> t_is_unit(t_fun_range(GenRet))
+ end
+ end;
+ _ -> false % parent should have a name to have a contract
+ end;
+ _ -> false % called in other funs? far-fetched...
+ end
+ end
+ end.
+
classify_returns(Tree) ->
case find_terminals(cerl:fun_body(Tree)) of
{false, false} -> no_match;
diff --git a/lib/dialyzer/src/dialyzer_plt.erl b/lib/dialyzer/src/dialyzer_plt.erl
index 8d62f2c529..6033d7f17c 100644
--- a/lib/dialyzer/src/dialyzer_plt.erl
+++ b/lib/dialyzer/src/dialyzer_plt.erl
@@ -317,7 +317,7 @@ merge_plts_or_report_conflicts(PltFiles, Plts) ->
Msg = io_lib:format("Could not merge PLTs since they are not disjoint\n"
"The following files are included in more than one "
"PLTs:\n~p\n", [ConfFiles]),
- error(Msg)
+ plt_error(Msg)
end.
find_duplicates(List) ->
diff --git a/lib/dialyzer/src/dialyzer_succ_typings.erl b/lib/dialyzer/src/dialyzer_succ_typings.erl
index 24d6013692..dc5a3fed37 100644
--- a/lib/dialyzer/src/dialyzer_succ_typings.erl
+++ b/lib/dialyzer/src/dialyzer_succ_typings.erl
@@ -155,19 +155,31 @@ postprocess_dataflow_warns(RawWarnings, State, WarnAcc) ->
postprocess_dataflow_warns([], _State, WAcc, Acc) ->
{WAcc, lists:reverse(Acc)};
-postprocess_dataflow_warns([{?WARN_CONTRACT_RANGE, {File, CallL}, Msg}|Rest],
+postprocess_dataflow_warns([{?WARN_CONTRACT_RANGE, {CallF, CallL}, Msg}|Rest],
#st{codeserver = Codeserver} = State, WAcc, Acc) ->
{contract_range, [Contract, M, F, A, ArgStrings, CRet]} = Msg,
- {ok, {{File, _ContrL} = FileLine, _C}} =
- dialyzer_codeserver:lookup_mfa_contract({M,F,A}, Codeserver),
- NewMsg =
- {contract_range, [Contract, M, F, ArgStrings, CallL, CRet]},
- W = {?WARN_CONTRACT_RANGE, FileLine, NewMsg},
- Filter =
- fun({?WARN_CONTRACT_TYPES, FL, _}) when FL =:= FileLine -> false;
- (_) -> true
- end,
- postprocess_dataflow_warns(Rest, State, lists:filter(Filter, WAcc), [W|Acc]);
+ case dialyzer_codeserver:lookup_mfa_contract({M,F,A}, Codeserver) of
+ {ok, {{ContrF, _ContrL} = FileLine, _C}} ->
+ case CallF =:= ContrF of
+ true ->
+ NewMsg = {contract_range, [Contract, M, F, ArgStrings, CallL, CRet]},
+ W = {?WARN_CONTRACT_RANGE, FileLine, NewMsg},
+ Filter =
+ fun({?WARN_CONTRACT_TYPES, FL, _}) when FL =:= FileLine -> false;
+ (_) -> true
+ end,
+ FilterWAcc = lists:filter(Filter, WAcc),
+ postprocess_dataflow_warns(Rest, State, FilterWAcc, [W|Acc]);
+ false ->
+ postprocess_dataflow_warns(Rest, State, WAcc, Acc)
+ end;
+ error ->
+ %% The contract is not in a module that is currently under analysis.
+ %% We display the warning in the file/line of the call.
+ NewMsg = {contract_range, [Contract, M, F, ArgStrings, CallL, CRet]},
+ W = {?WARN_CONTRACT_RANGE, {CallF, CallL}, NewMsg},
+ postprocess_dataflow_warns(Rest, State, WAcc, [W|Acc])
+ end;
postprocess_dataflow_warns([W|Rest], State, Wacc, Acc) ->
postprocess_dataflow_warns(Rest, State, Wacc, [W|Acc]).
diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl
index c45615d670..30aec59d22 100644
--- a/lib/dialyzer/src/dialyzer_typesig.erl
+++ b/lib/dialyzer/src/dialyzer_typesig.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -62,7 +62,8 @@
-type dep() :: integer(). %% type variable names used as constraint ids
-type type_var() :: erl_types:erl_type(). %% actually: {'c','var',_,_}
--record(fun_var, {'fun' :: fun((_) -> erl_types:erl_type()), deps :: [dep()]}).
+-record(fun_var, {'fun' :: fun((_) -> erl_types:erl_type()), deps :: [dep()],
+ origin :: integer()}).
-type constr_op() :: 'eq' | 'sub'.
-type fvar_or_type() :: #fun_var{} | erl_types:erl_type().
@@ -121,8 +122,10 @@
-ifdef(DEBUG).
-define(debug(__String, __Args), io:format(__String, __Args)).
+-define(mk_fun_var(Fun, Vars), mk_fun_var(?LINE, Fun, Vars)).
-else.
-define(debug(__String, __Args), ok).
+-define(mk_fun_var(Fun, Vars), mk_fun_var(Fun, Vars)).
-endif.
%% ============================================================================
@@ -218,10 +221,10 @@ traverse(Tree, DefinedVars, State) ->
binary ->
{State1, SegTypes} = traverse_list(cerl:binary_segments(Tree),
DefinedVars, State),
- Type = mk_fun_var(fun(Map) ->
- TmpSegTypes = lookup_type_list(SegTypes, Map),
- t_bitstr_concat(TmpSegTypes)
- end, SegTypes),
+ Type = ?mk_fun_var(fun(Map) ->
+ TmpSegTypes = lookup_type_list(SegTypes, Map),
+ t_bitstr_concat(TmpSegTypes)
+ end, SegTypes),
{state__store_conj(mk_var(Tree), sub, Type, State1), mk_var(Tree)};
bitstr ->
Size = cerl:bitstr_size(Tree),
@@ -236,7 +239,7 @@ traverse(Tree, DefinedVars, State) ->
N when is_integer(N) -> {State1, t_bitstr(0, N)};
any -> % Size is not a literal
{state__store_conj(SizeType, sub, t_non_neg_integer(), State1),
- mk_fun_var(bitstr_constr(SizeType, UnitVal), [SizeType])}
+ ?mk_fun_var(bitstr_constr(SizeType, UnitVal), [SizeType])}
end,
ValTypeConstr =
case cerl:concrete(cerl:bitstr_type(Tree)) of
@@ -250,8 +253,8 @@ traverse(Tree, DefinedVars, State) ->
case state__is_in_match(State1) of
true ->
Flags = cerl:concrete(cerl:bitstr_flags(Tree)),
- mk_fun_var(bitstr_val_constr(SizeType, UnitVal, Flags),
- [SizeType]);
+ ?mk_fun_var(bitstr_val_constr(SizeType, UnitVal, Flags),
+ [SizeType]);
false -> t_integer()
end;
utf8 -> t_integer();
@@ -281,24 +284,24 @@ traverse(Tree, DefinedVars, State) ->
{State, t_cons(HdVar, TlVar)};
false ->
ConsVar = mk_var(Tree),
- ConsType = mk_fun_var(fun(Map) ->
- t_cons(lookup_type(HdVar, Map),
- lookup_type(TlVar, Map))
- end, [HdVar, TlVar]),
- HdType = mk_fun_var(fun(Map) ->
- Cons = lookup_type(ConsVar, Map),
- case t_is_cons(Cons) of
- false -> t_any();
- true -> t_cons_hd(Cons)
- end
- end, [ConsVar]),
- TlType = mk_fun_var(fun(Map) ->
- Cons = lookup_type(ConsVar, Map),
- case t_is_cons(Cons) of
- false -> t_any();
- true -> t_cons_tl(Cons)
- end
- end, [ConsVar]),
+ ConsType = ?mk_fun_var(fun(Map) ->
+ t_cons(lookup_type(HdVar, Map),
+ lookup_type(TlVar, Map))
+ end, [HdVar, TlVar]),
+ HdType = ?mk_fun_var(fun(Map) ->
+ Cons = lookup_type(ConsVar, Map),
+ case t_is_cons(Cons) of
+ false -> t_any();
+ true -> t_cons_hd(Cons)
+ end
+ end, [ConsVar]),
+ TlType = ?mk_fun_var(fun(Map) ->
+ Cons = lookup_type(ConsVar, Map),
+ case t_is_cons(Cons) of
+ false -> t_any();
+ true -> t_cons_tl(Cons)
+ end
+ end, [ConsVar]),
State2 = state__store_conj_lists([HdVar, TlVar, ConsVar], sub,
[HdType, TlType, ConsType],
State1),
@@ -656,25 +659,25 @@ get_plt_constr(MFA, Dst, ArgVars, State) ->
{RetType, ArgCs} =
case PltRes of
none ->
- {mk_fun_var(fun(Map) ->
- ArgTypes = lookup_type_list(ArgVars, Map),
- dialyzer_contracts:get_contract_return(C, ArgTypes)
- end, ArgVars), GenArgs};
+ {?mk_fun_var(fun(Map) ->
+ ArgTypes = lookup_type_list(ArgVars, Map),
+ dialyzer_contracts:get_contract_return(C, ArgTypes)
+ end, ArgVars), GenArgs};
{value, {PltRetType, PltArgTypes}} ->
%% Need to combine the contract with the success typing.
- {mk_fun_var(
- fun(Map) ->
- ArgTypes0 = lookup_type_list(ArgVars, Map),
- ArgTypes = case FunModule =:= Module of
- false ->
- List = lists:zip(PltArgTypes, ArgTypes0),
- [erl_types:t_unopaque_on_mismatch(T1, T2, Opaques)
- || {T1, T2} <- List];
- true -> ArgTypes0
- end,
- CRet = dialyzer_contracts:get_contract_return(C, ArgTypes),
- t_inf(CRet, PltRetType, opaque)
- end, ArgVars),
+ {?mk_fun_var(
+ fun(Map) ->
+ ArgTypes0 = lookup_type_list(ArgVars, Map),
+ ArgTypes = case FunModule =:= Module of
+ false ->
+ List = lists:zip(PltArgTypes, ArgTypes0),
+ [erl_types:t_unopaque_on_mismatch(T1, T2, Opaques)
+ || {T1, T2} <- List];
+ true -> ArgTypes0
+ end,
+ CRet = dialyzer_contracts:get_contract_return(C, ArgTypes),
+ t_inf(CRet, PltRetType, opaque)
+ end, ArgVars),
[t_inf(X, Y, opaque) || {X, Y} <- lists:zip(GenArgs, PltArgTypes)]}
end,
state__store_conj_lists([Dst|ArgVars], sub, [RetType|ArgCs], State)
@@ -766,10 +769,10 @@ handle_clauses_1([Clause|Tail], TopVar, Arg, DefinedVars,
case SubtrTypes =:= overflow of
true -> S;
false ->
- SubtrPatVar = mk_fun_var(fun(Map) ->
- TmpType = lookup_type(Arg, Map),
- t_subtract_list(TmpType, SubtrTypes)
- end, [Arg]),
+ SubtrPatVar = ?mk_fun_var(fun(Map) ->
+ TmpType = lookup_type(Arg, Map),
+ t_subtract_list(TmpType, SubtrTypes)
+ end, [Arg]),
state__store_conj(Arg, sub, SubtrPatVar, S)
end
end,
@@ -1043,10 +1046,10 @@ handle_guard(Guard, DefinedVars, State) ->
get_bif_constr({erlang, Op, 2}, Dst, Args = [Arg1, Arg2], _State)
when Op =:= '+'; Op =:= '-'; Op =:= '*' ->
- ReturnType = mk_fun_var(fun(Map) ->
- TmpArgTypes = lookup_type_list(Args, Map),
- erl_bif_types:type(erlang, Op, 2, TmpArgTypes)
- end, Args),
+ ReturnType = ?mk_fun_var(fun(Map) ->
+ TmpArgTypes = lookup_type_list(Args, Map),
+ erl_bif_types:type(erlang, Op, 2, TmpArgTypes)
+ end, Args),
ArgFun =
fun(A, Pos) ->
F =
@@ -1074,7 +1077,7 @@ get_bif_constr({erlang, Op, 2}, Dst, Args = [Arg1, Arg2], _State)
end
end
end,
- mk_fun_var(F, [Dst, A])
+ ?mk_fun_var(F, [Dst, A])
end,
Arg1FunVar = ArgFun(Arg2, 2),
Arg2FunVar = ArgFun(Arg1, 1),
@@ -1131,12 +1134,12 @@ get_bif_constr({erlang, Op, 2}, Dst, [Arg1, Arg2] = Args, _State)
'>=' -> {ArgFun(Arg1, Arg2, '>='), ArgFun(Arg2, Arg1, '=<')}
end,
DstArgs = [Dst, Arg1, Arg2],
- Arg1Var = mk_fun_var(Arg1Fun, DstArgs),
- Arg2Var = mk_fun_var(Arg2Fun, DstArgs),
- DstVar = mk_fun_var(fun(Map) ->
- TmpArgTypes = lookup_type_list(Args, Map),
- erl_bif_types:type(erlang, Op, 2, TmpArgTypes)
- end, Args),
+ Arg1Var = ?mk_fun_var(Arg1Fun, DstArgs),
+ Arg2Var = ?mk_fun_var(Arg2Fun, DstArgs),
+ DstVar = ?mk_fun_var(fun(Map) ->
+ TmpArgTypes = lookup_type_list(Args, Map),
+ erl_bif_types:type(erlang, Op, 2, TmpArgTypes)
+ end, Args),
mk_conj_constraint_list([mk_constraint(Dst, sub, DstVar),
mk_constraint(Arg1, sub, Arg1Var),
mk_constraint(Arg2, sub, Arg2Var)]);
@@ -1172,13 +1175,13 @@ get_bif_constr({erlang, '++', 2}, Dst, [Hd, Tl] = Args, _State) ->
end
end,
DstL = [Dst],
- HdVar = mk_fun_var(HdFun, DstL),
- TlVar = mk_fun_var(TlFun, DstL),
+ HdVar = ?mk_fun_var(HdFun, DstL),
+ TlVar = ?mk_fun_var(TlFun, DstL),
ArgTypes = erl_bif_types:arg_types(erlang, '++', 2),
- ReturnType = mk_fun_var(fun(Map) ->
- TmpArgTypes = lookup_type_list(Args, Map),
- erl_bif_types:type(erlang, '++', 2, TmpArgTypes)
- end, Args),
+ ReturnType = ?mk_fun_var(fun(Map) ->
+ TmpArgTypes = lookup_type_list(Args, Map),
+ erl_bif_types:type(erlang, '++', 2, TmpArgTypes)
+ end, Args),
Cs = mk_constraints(Args, sub, ArgTypes),
mk_conj_constraint_list([mk_constraint(Dst, sub, ReturnType),
mk_constraint(Hd, sub, HdVar),
@@ -1209,7 +1212,7 @@ get_bif_constr({erlang, is_function, 2}, Dst, [Fun, Arity], _State) ->
false -> t_any()
end
end,
- ArgV = mk_fun_var(ArgFun, [Dst, Arity]),
+ ArgV = ?mk_fun_var(ArgFun, [Dst, Arity]),
mk_conj_constraint_list([mk_constraint(Dst, sub, t_boolean()),
mk_constraint(Arity, sub, t_integer()),
mk_constraint(Fun, sub, ArgV)]);
@@ -1232,12 +1235,12 @@ get_bif_constr({erlang, is_record, 2}, Dst, [Var, Tag] = Args, _State) ->
false -> t_any()
end
end,
- ArgV = mk_fun_var(ArgFun, [Dst]),
+ ArgV = ?mk_fun_var(ArgFun, [Dst]),
DstFun = fun(Map) ->
TmpArgTypes = lookup_type_list(Args, Map),
erl_bif_types:type(erlang, is_record, 2, TmpArgTypes)
end,
- DstV = mk_fun_var(DstFun, Args),
+ DstV = ?mk_fun_var(DstFun, Args),
mk_conj_constraint_list([mk_constraint(Dst, sub, DstV),
mk_constraint(Tag, sub, t_atom()),
mk_constraint(Var, sub, ArgV)]);
@@ -1280,7 +1283,7 @@ get_bif_constr({erlang, is_record, 3}, Dst, [Var, Tag, Arity] = Args, State) ->
false -> t_any()
end
end,
- ArgV = mk_fun_var(ArgFun, [Tag, Arity, Dst]),
+ ArgV = ?mk_fun_var(ArgFun, [Tag, Arity, Dst]),
DstFun = fun(Map) ->
[TmpVar, TmpTag, TmpArity] = TmpArgTypes = lookup_type_list(Args, Map),
TmpArgTypes2 =
@@ -1314,7 +1317,7 @@ get_bif_constr({erlang, is_record, 3}, Dst, [Var, Tag, Arity] = Args, State) ->
end,
erl_bif_types:type(erlang, is_record, 3, TmpArgTypes2)
end,
- DstV = mk_fun_var(DstFun, Args),
+ DstV = ?mk_fun_var(DstFun, Args),
mk_conj_constraint_list([mk_constraint(Dst, sub, DstV),
mk_constraint(Arity, sub, t_integer()),
mk_constraint(Tag, sub, t_atom()),
@@ -1359,9 +1362,9 @@ get_bif_constr({erlang, 'and', 2}, Dst, [Arg1, Arg2] = Args, _State) ->
end
end
end,
- ArgV1 = mk_fun_var(ArgFun(Arg2), [Arg2, Dst]),
- ArgV2 = mk_fun_var(ArgFun(Arg1), [Arg1, Dst]),
- DstV = mk_fun_var(DstFun, Args),
+ ArgV1 = ?mk_fun_var(ArgFun(Arg2), [Arg2, Dst]),
+ ArgV2 = ?mk_fun_var(ArgFun(Arg1), [Arg1, Dst]),
+ DstV = ?mk_fun_var(DstFun, Args),
mk_conj_constraint_list([mk_constraint(Dst, sub, DstV),
mk_constraint(Arg1, sub, ArgV1),
mk_constraint(Arg2, sub, ArgV2)]);
@@ -1403,9 +1406,9 @@ get_bif_constr({erlang, 'or', 2}, Dst, [Arg1, Arg2] = Args, _State) ->
end
end
end,
- ArgV1 = mk_fun_var(ArgFun(Arg2), [Arg2, Dst]),
- ArgV2 = mk_fun_var(ArgFun(Arg1), [Arg1, Dst]),
- DstV = mk_fun_var(DstFun, Args),
+ ArgV1 = ?mk_fun_var(ArgFun(Arg2), [Arg2, Dst]),
+ ArgV2 = ?mk_fun_var(ArgFun(Arg1), [Arg1, Dst]),
+ DstV = ?mk_fun_var(DstFun, Args),
F = fun(A) ->
try [mk_constraint(A, sub, True)]
catch throw:error -> []
@@ -1433,8 +1436,8 @@ get_bif_constr({erlang, 'not', 1}, Dst, [Arg] = Args, _State) ->
end
end
end,
- ArgV = mk_fun_var(Fun(Dst), [Dst]),
- DstV = mk_fun_var(Fun(Arg), Args),
+ ArgV = ?mk_fun_var(Fun(Dst), [Dst]),
+ DstV = ?mk_fun_var(Fun(Arg), Args),
mk_conj_constraint_list([mk_constraint(Arg, sub, ArgV),
mk_constraint(Dst, sub, DstV)]);
get_bif_constr({erlang, '=:=', 2}, Dst, [Arg1, Arg2] = Args, _State) ->
@@ -1467,9 +1470,9 @@ get_bif_constr({erlang, '=:=', 2}, Dst, [Arg1, Arg2] = Args, _State) ->
end
end,
DstArgs = [Dst, Arg1, Arg2],
- ArgV1 = mk_fun_var(ArgFun(Arg1, Arg2), DstArgs),
- ArgV2 = mk_fun_var(ArgFun(Arg2, Arg1), DstArgs),
- DstV = mk_fun_var(DstFun, Args),
+ ArgV1 = ?mk_fun_var(ArgFun(Arg1, Arg2), DstArgs),
+ ArgV2 = ?mk_fun_var(ArgFun(Arg2, Arg1), DstArgs),
+ DstV = ?mk_fun_var(DstFun, Args),
mk_conj_constraint_list([mk_constraint(Dst, sub, DstV),
mk_constraint(Arg1, sub, ArgV1),
mk_constraint(Arg2, sub, ArgV2)]);
@@ -1510,10 +1513,10 @@ get_bif_constr({erlang, '==', 2}, Dst, [Arg1, Arg2] = Args, _State) ->
end
end
end,
- DstV = mk_fun_var(DstFun, Args),
+ DstV = ?mk_fun_var(DstFun, Args),
ArgL = [Arg1, Arg2, Dst],
- ArgV1 = mk_fun_var(ArgFun(Arg2, Arg1), ArgL),
- ArgV2 = mk_fun_var(ArgFun(Arg1, Arg2), ArgL),
+ ArgV1 = ?mk_fun_var(ArgFun(Arg2, Arg1), ArgL),
+ ArgV2 = ?mk_fun_var(ArgFun(Arg1, Arg2), ArgL),
mk_conj_constraint_list([mk_constraint(Dst, sub, DstV),
mk_constraint(Arg1, sub, ArgV1),
mk_constraint(Arg2, sub, ArgV2)]);
@@ -1531,7 +1534,7 @@ get_bif_constr({erlang, element, 2} = _BIF, Dst, Args,
end,
erl_bif_types:type(erlang, element, 2, ATs2)
end,
- ReturnType = mk_fun_var(Fun, Args),
+ ReturnType = ?mk_fun_var(Fun, Args),
ArgTypes = erl_bif_types:arg_types(erlang, element, 2),
Cs = mk_constraints(Args, sub, ArgTypes),
NewCs =
@@ -1553,7 +1556,7 @@ get_bif_constr({M, F, A} = _BIF, Dst, Args, State) ->
false -> T
end
end,
- ReturnType = mk_fun_var(fun(Map) ->
+ ReturnType = ?mk_fun_var(fun(Map) ->
TmpArgTypes0 = lookup_type_list(Args, Map),
TmpArgTypes = [UnopaqueFun(T) || T<- TmpArgTypes0],
erl_bif_types:type(M, F, A, TmpArgTypes)
@@ -1608,7 +1611,7 @@ get_bif_test_constr(Dst, Arg, Type, State) ->
false -> t_any()
end
end,
- ArgV = mk_fun_var(ArgFun, [Dst]),
+ ArgV = ?mk_fun_var(ArgFun, [Dst]),
DstFun = fun(Map) ->
ArgType = lookup_type(Arg, Map),
case t_is_none(t_inf(ArgType, Type)) of
@@ -1633,7 +1636,7 @@ get_bif_test_constr(Dst, Arg, Type, State) ->
end
end
end,
- DstV = mk_fun_var(DstFun, [Arg]),
+ DstV = ?mk_fun_var(DstFun, [Arg]),
mk_conj_constraint_list([mk_constraint(Dst, sub, DstV),
mk_constraint(Arg, sub, ArgV)]).
@@ -1684,11 +1687,14 @@ solve_scc(SCC, Map, State, TryingUnit) ->
true ->
?debug("SCC ~w reached fixpoint\n", [SCC]),
NewTypes = unsafe_lookup_type_list(Funs, Map2),
- case lists:all(fun(T) -> t_is_none(t_fun_range(T)) end, NewTypes)
+ case erl_types:any_none([t_fun_range(T) || T <- NewTypes])
andalso TryingUnit =:= false of
true ->
- UnitTypes = [t_fun(state__fun_arity(F, State), t_unit())
- || F <- Funs],
+ UnitTypes =
+ [case t_is_none(t_fun_range(T)) of
+ false -> T;
+ true -> t_fun(t_fun_args(T), t_unit())
+ end || T <- NewTypes],
Map3 = enter_type_lists(Funs, UnitTypes, Map2),
solve_scc(SCC, Map3, State, true);
false ->
@@ -2320,12 +2326,25 @@ mk_constraint(Lhs, Op, Rhs) ->
constraint_opnd_is_any(#fun_var{}) -> false;
constraint_opnd_is_any(Type) -> t_is_any(Type).
+-ifdef(DEBUG).
+
+-spec mk_fun_var(fun((_) -> erl_types:erl_type()), [erl_types:erl_type()],
+ integer()) -> #fun_var{}.
+
+mk_fun_var(Line, Fun, Types) ->
+ Deps = [t_var_name(Var) || Var <- t_collect_vars(t_product(Types))],
+ #fun_var{'fun' = Fun, deps = ordsets:from_list(Deps), origin = Line}.
+
+-else.
+
-spec mk_fun_var(fun((_) -> erl_types:erl_type()), [erl_types:erl_type()]) -> #fun_var{}.
mk_fun_var(Fun, Types) ->
Deps = [t_var_name(Var) || Var <- t_collect_vars(t_product(Types))],
#fun_var{'fun' = Fun, deps = ordsets:from_list(Deps)}.
+-endif.
+
-spec get_deps(constr()) -> [dep()].
get_deps(#constraint{deps = D}) -> D;
@@ -2676,8 +2695,9 @@ find_constraint(Tuple, [_|Cs]) ->
-endif.
-ifdef(DEBUG).
-format_type(#fun_var{deps = Deps}) ->
- io_lib:format("Fun(~s)", [lists:flatten([format_type(t_var(X))||X<-Deps])]);
+format_type(#fun_var{deps = Deps, origin = Origin}) ->
+ io_lib:format("Fun@L~p(~s)",
+ [Origin, lists:flatten([format_type(t_var(X))||X<-Deps])]);
format_type(Type) ->
case cerl:is_literal(Type) of
true -> io_lib:format("~w", [cerl:concrete(Type)]);
diff --git a/lib/dialyzer/test/Makefile b/lib/dialyzer/test/Makefile
index a8549278a5..47deb17f1d 100644
--- a/lib/dialyzer/test/Makefile
+++ b/lib/dialyzer/test/Makefile
@@ -2,74 +2,33 @@ include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
# ----------------------------------------------------
-# Target Specs
+# Files
# ----------------------------------------------------
-MODULES= \
- callgraph_tests_SUITE \
- opaque_tests_SUITE \
- options1_tests_SUITE \
- options2_tests_SUITE \
- plt_tests_SUITE \
- r9c_tests_SUITE \
- race_tests_SUITE \
- small_tests_SUITE \
- user_tests_SUITE \
- dialyzer_common\
- file_utils
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-INSTALL_PROGS= $(TARGET_FILES)
+AUXILIARY_FILES=\
+ dialyzer.spec\
+ dialyzer_test_constants.hrl\
+ dialyzer_common.erl\
+ file_utils.erl\
+ plt_SUITE.erl
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/dialyzer_test
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-
-ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
-
-EBIN = .
-
-EMAKEFILE=Emakefile
-
-# ----------------------------------------------------
-# 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) $(GEN_FILES)
- rm -f core
-
-docs:
+RELSYSDIR = $(RELEASE_PATH)/dialyzer_test
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-release_spec: opt
+include $(ERL_TOP)/make/otp_release_targets.mk
-release_tests_spec: make_emakefile
+release_tests_spec:
$(INSTALL_DIR) $(RELSYSDIR)
- $(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(RELSYSDIR)
- $(INSTALL_DATA) dialyzer.spec dialyzer_test_constants.hrl $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
+ $(INSTALL_DATA) $(AUXILIARY_FILES) $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
-
-release_docs_spec:
+ cd $(RELSYSDIR);\
+ erl -make;\
+ erl -noshell -run dialyzer_common create_all_suites -s erlang halt
diff --git a/lib/dialyzer/test/README b/lib/dialyzer/test/README
index 07340c7266..41f282a131 100644
--- a/lib/dialyzer/test/README
+++ b/lib/dialyzer/test/README
@@ -2,22 +2,18 @@
To add test cases in any suite:
-------------------------------
- 1) If the test requires dialyzer to analyze a single file place it in the
- suite's 'src' directory. If analysis of more files is needed place them
- all in a new directory in suite's 'src' directory.
+ 1) If the test requires Dialyzer to analyze a single file (TEST.erl) place it
+ in the suite's 'src' directory. If analysis of more files is needed place
+ them all in a new directory (TEST) in suite's 'src' directory.
- 2) Create a file with the same name as the test (if single file, omit the
- extension else directory name) containing the expected result in suite's
- 'result' directory.
-
- 3) Run './remake <suite>', where <suite> is the suite's name omitting
- "_tests_SUITE".
+ 2) Create a file named TEST containing the expected result in suite's 'result'
+ directory.
----------------------
To create a new suite:
----------------------
- 1) Create a directory with the suffix 'tests_SUITE_data'. The name should
+ 1) Create a directory with the suffix '_SUITE_data'. The name should
describe the suite.
2) In the suite's directory create subdirectories 'src' and 'results' as
@@ -28,17 +24,15 @@ To create a new suite:
where:
- List = a list of dialyzer options. Common case will be something
+ List = a list of Dialyzer options. Common case will be something
like [{warnings, Warnings}], where Warnings is a list of valid
'-W' prefixed dialyzer options without the 'W' prefix (e.g.
'-Wfoo' would be declared as [{warnings, [foo]}].
- Limit = the amount of time each test case is allowed to run. Must be
- bigger than the time it takes the most time-consuming test to
- finish.
+ Limit = the amount of time (in minutes) each test case is allowed to
+ run. Must be greater than the time required to complete the most
+ time-consuming test in the suite.
Any of these lines may be missing. Default options list is empty and
default time limit is 1 minute.
3) Add tests as described in previous section.
-
- 4) Add the resulting suite's name in the Makefile's MODULES variable.
diff --git a/lib/dialyzer/test/callgraph_tests_SUITE_data/dialyzer_options b/lib/dialyzer/test/callgraph_SUITE_data/dialyzer_options
index 50991c9bc5..50991c9bc5 100644
--- a/lib/dialyzer/test/callgraph_tests_SUITE_data/dialyzer_options
+++ b/lib/dialyzer/test/callgraph_SUITE_data/dialyzer_options
diff --git a/lib/dialyzer/test/callgraph_tests_SUITE_data/results/test_missing_functions b/lib/dialyzer/test/callgraph_SUITE_data/results/test_missing_functions
index 4150bdb7c0..4150bdb7c0 100644
--- a/lib/dialyzer/test/callgraph_tests_SUITE_data/results/test_missing_functions
+++ b/lib/dialyzer/test/callgraph_SUITE_data/results/test_missing_functions
diff --git a/lib/dialyzer/test/callgraph_SUITE_data/src/test_missing_functions/t1.erl b/lib/dialyzer/test/callgraph_SUITE_data/src/test_missing_functions/t1.erl
new file mode 100644
index 0000000000..05ba9b0f93
--- /dev/null
+++ b/lib/dialyzer/test/callgraph_SUITE_data/src/test_missing_functions/t1.erl
@@ -0,0 +1,16 @@
+%%%-------------------------------------------------------------------
+%%% File : t1.erl
+%%% Author : Tobias Lindahl <[email protected]>
+%%% Description :
+%%%
+%%% Created : 26 Jul 2006 by Tobias Lindahl <[email protected]>
+%%%-------------------------------------------------------------------
+-module(t1).
+
+-export([t1/1, t2/1]).
+
+t1(X) ->
+ t2:t1(X).
+
+t2(X) ->
+ t2:t2(X).
diff --git a/lib/dialyzer/test/callgraph_SUITE_data/src/test_missing_functions/t2.erl b/lib/dialyzer/test/callgraph_SUITE_data/src/test_missing_functions/t2.erl
new file mode 100644
index 0000000000..bf940fd181
--- /dev/null
+++ b/lib/dialyzer/test/callgraph_SUITE_data/src/test_missing_functions/t2.erl
@@ -0,0 +1,16 @@
+%%%-------------------------------------------------------------------
+%%% File : t2.erl
+%%% Author : Tobias Lindahl <[email protected]>
+%%% Description :
+%%%
+%%% Created : 26 Jul 2006 by Tobias Lindahl <[email protected]>
+%%%-------------------------------------------------------------------
+-module(t2).
+
+-export([t1/1]).
+
+t1(X) ->
+ t1:t3(X) + t2(X).
+
+t2(X) ->
+ X + 1.
diff --git a/lib/dialyzer/test/callgraph_tests_SUITE.erl b/lib/dialyzer/test/callgraph_tests_SUITE.erl
deleted file mode 100644
index 6148adf971..0000000000
--- a/lib/dialyzer/test/callgraph_tests_SUITE.erl
+++ /dev/null
@@ -1,52 +0,0 @@
-%% ATTENTION!
-%% This is an automatically generated file. Do not edit.
-%% Use './remake' script to refresh it if needed.
-%% All Dialyzer options should be defined in dialyzer_options
-%% file.
-
--module(callgraph_tests_SUITE).
-
--include("ct.hrl").
--include("dialyzer_test_constants.hrl").
-
--export([suite/0, init_per_suite/0, init_per_suite/1,
- end_per_suite/1, all/0]).
--export([callgraph_tests_SUITE_consistency/1, test_missing_functions/1]).
-
-suite() ->
- [{timetrap, {minutes, 1}}].
-
-init_per_suite() ->
- [{timetrap, ?plt_timeout}].
-init_per_suite(Config) ->
- OutDir = ?config(priv_dir, Config),
- case dialyzer_common:check_plt(OutDir) of
- fail -> {skip, "Plt creation/check failed."};
- ok -> [{dialyzer_options, []}|Config]
- end.
-
-end_per_suite(_Config) ->
- ok.
-
-all() ->
- [callgraph_tests_SUITE_consistency,test_missing_functions].
-
-dialyze(Config, TestCase) ->
- Opts = ?config(dialyzer_options, Config),
- Dir = ?config(data_dir, Config),
- OutDir = ?config(priv_dir, Config),
- dialyzer_common:check(TestCase, Opts, Dir, OutDir).
-
-callgraph_tests_SUITE_consistency(Config) ->
- Dir = ?config(data_dir, Config),
- case dialyzer_common:new_tests(Dir, all()) of
- [] -> ok;
- New -> ct:fail({missing_tests,New})
- end.
-
-test_missing_functions(Config) ->
- case dialyze(Config, test_missing_functions) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
diff --git a/lib/dialyzer/test/callgraph_tests_SUITE_data/src/test_missing_functions/t1.erl b/lib/dialyzer/test/callgraph_tests_SUITE_data/src/test_missing_functions/t1.erl
deleted file mode 100644
index 3b320e1ed4..0000000000
--- a/lib/dialyzer/test/callgraph_tests_SUITE_data/src/test_missing_functions/t1.erl
+++ /dev/null
@@ -1,16 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : t1.erl
-%%% Author : Tobias Lindahl <[email protected]>
-%%% Description :
-%%%
-%%% Created : 26 Jul 2006 by Tobias Lindahl <[email protected]>
-%%%-------------------------------------------------------------------
--module(t1).
-
--export([t1/1, t2/1]).
-
-t1(X) ->
- t2:t1(X).
-
-t2(X) ->
- t2:t2(X).
diff --git a/lib/dialyzer/test/callgraph_tests_SUITE_data/src/test_missing_functions/t2.erl b/lib/dialyzer/test/callgraph_tests_SUITE_data/src/test_missing_functions/t2.erl
deleted file mode 100644
index 5ac8aa328c..0000000000
--- a/lib/dialyzer/test/callgraph_tests_SUITE_data/src/test_missing_functions/t2.erl
+++ /dev/null
@@ -1,16 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : t2.erl
-%%% Author : Tobias Lindahl <[email protected]>
-%%% Description :
-%%%
-%%% Created : 26 Jul 2006 by Tobias Lindahl <[email protected]>
-%%%-------------------------------------------------------------------
--module(t2).
-
--export([t1/1]).
-
-t1(X) ->
- t1:t3(X) + t2(X).
-
-t2(X) ->
- X + 1.
diff --git a/lib/dialyzer/test/dialyzer.spec b/lib/dialyzer/test/dialyzer.spec
index 7499dbad1e..497a502bb8 100644
--- a/lib/dialyzer/test/dialyzer.spec
+++ b/lib/dialyzer/test/dialyzer.spec
@@ -2,4 +2,4 @@
{suites, tests, all}.
-{skip_cases, tests, small_tests_SUITE, cerl_hipeify, "Needs compiler in plt"}. \ No newline at end of file
+{skip_cases, tests, small_SUITE, cerl_hipeify, "Needs compiler in plt"}.
diff --git a/lib/dialyzer/test/dialyzer_common.erl b/lib/dialyzer/test/dialyzer_common.erl
index 5577405483..51766a4604 100644
--- a/lib/dialyzer/test/dialyzer_common.erl
+++ b/lib/dialyzer/test/dialyzer_common.erl
@@ -7,13 +7,13 @@
-module(dialyzer_common).
--export([check_plt/1, check/4, create_suite/1,
- create_all_suites/0, new_tests/2]).
+-export([check_plt/1, check/4, create_all_suites/0, new_tests/2]).
-include_lib("kernel/include/file.hrl").
--define(suite_suffix, "_tests_SUITE").
+-define(suite_suffix, "_SUITE").
-define(data_folder, "_data").
+-define(suite_data, ?suite_suffix ++ ?data_folder).
-define(erlang_extension, ".erl").
-define(output_file_mode, write).
-define(dialyzer_option_file, "dialyzer_options").
@@ -209,7 +209,7 @@ get_suites(Dir) ->
{error, _} -> [];
{ok, Filenames} ->
FullFilenames = [filename:join(Dir, F) || F <-Filenames ],
- Dirs = [suffix(filename:basename(F), "_tests_SUITE_data") ||
+ Dirs = [suffix(filename:basename(F), ?suite_data) ||
F <- FullFilenames,
file_utils:file_type(F) =:= {ok, 'directory'}],
[S || {yes, S} <- Dirs]
@@ -232,7 +232,7 @@ create_suite(SuiteName) ->
generate_suite(SuiteName, OutputFile, OptionsFileN, InputDirN).
generate_suite_dir_from_name(Cwd, SuiteName) ->
- filename:join(Cwd, SuiteName ++ ?suite_suffix ++ ?data_folder).
+ filename:join(Cwd, SuiteName ++ ?suite_data).
generate_suite_file(Cwd, SuiteName) ->
OutputFilename =
@@ -305,7 +305,7 @@ write_header(#suite{suitename = SuiteName, outputfile = OutputFile,
"%% All Dialyzer options should be defined in dialyzer_options\n"
"%% file.\n\n"
"-module(~s).\n\n"
- "-include(\"ct.hrl\").\n"
+ "-include_lib(\"common_test/include/ct.hrl\").\n"
"-include(\"dialyzer_test_constants.hrl\").\n\n"
"-export([suite/0, init_per_suite/0, init_per_suite/1,\n"
" end_per_suite/1, all/0]).\n"
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/dialyzer_options b/lib/dialyzer/test/opaque_SUITE_data/dialyzer_options
index 3ff26b87db..3ff26b87db 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/dialyzer_options
+++ b/lib/dialyzer/test/opaque_SUITE_data/dialyzer_options
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/results/array b/lib/dialyzer/test/opaque_SUITE_data/results/array
index b05d088a03..b05d088a03 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/results/array
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/array
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/results/crash b/lib/dialyzer/test/opaque_SUITE_data/results/crash
index 6bdd934169..6bdd934169 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/results/crash
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/crash
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/results/dict b/lib/dialyzer/test/opaque_SUITE_data/results/dict
index 5c6bf6a927..5c6bf6a927 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/results/dict
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/dict
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/results/ets b/lib/dialyzer/test/opaque_SUITE_data/results/ets
index 5498ba1538..5498ba1538 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/results/ets
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/ets
diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/ewgi b/lib/dialyzer/test/opaque_SUITE_data/results/ewgi
new file mode 100644
index 0000000000..3c8cfb59f8
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/ewgi
@@ -0,0 +1,4 @@
+
+ewgi_api.erl:55: The call gb_trees:to_list({non_neg_integer(),'nil' | {_,_,_,_}}) does not have an opaque term of type gb_tree() as 1st argument
+ewgi_testapp.erl:35: The call ewgi_testapp:htmlise_data("request_data",{non_neg_integer(),'nil' | {_,_,_,_}}) will never return since it differs in the 2nd argument from the success typing arguments: ([95 | 97 | 100 | 101 | 104 | 112 | 113 | 114 | 115 | 116 | 117,...],[{_,_}])
+ewgi_testapp.erl:43: The call gb_trees:to_list(T::{non_neg_integer(),'nil' | {_,_,_,_}}) does not have an opaque term of type gb_tree() as 1st argument
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/results/gb_sets b/lib/dialyzer/test/opaque_SUITE_data/results/gb_sets
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/results/gb_sets
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/gb_sets
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/results/inf_loop1 b/lib/dialyzer/test/opaque_SUITE_data/results/inf_loop1
index eb8f304905..eb8f304905 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/results/inf_loop1
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/inf_loop1
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/results/int b/lib/dialyzer/test/opaque_SUITE_data/results/int
index 3ee4def34b..3ee4def34b 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/results/int
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/int
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/results/mixed_opaque b/lib/dialyzer/test/opaque_SUITE_data/results/mixed_opaque
index ab850b613e..ab850b613e 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/results/mixed_opaque
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/mixed_opaque
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/results/my_digraph b/lib/dialyzer/test/opaque_SUITE_data/results/my_digraph
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/results/my_digraph
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/my_digraph
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/results/my_queue b/lib/dialyzer/test/opaque_SUITE_data/results/my_queue
index 2860b91084..2860b91084 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/results/my_queue
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/my_queue
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/results/opaque b/lib/dialyzer/test/opaque_SUITE_data/results/opaque
index ca76f57b54..ca76f57b54 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/results/opaque
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/opaque
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/results/queue b/lib/dialyzer/test/opaque_SUITE_data/results/queue
index 59ce33f098..59ce33f098 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/results/queue
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/queue
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/results/rec b/lib/dialyzer/test/opaque_SUITE_data/results/rec
index 72736b3b3c..72736b3b3c 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/results/rec
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/rec
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/results/timer b/lib/dialyzer/test/opaque_SUITE_data/results/timer
index e917b76b08..e917b76b08 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/results/timer
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/timer
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/results/union b/lib/dialyzer/test/opaque_SUITE_data/results/union
index 98829b424a..98829b424a 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/results/union
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/union
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/results/wings b/lib/dialyzer/test/opaque_SUITE_data/results/wings
index a9571441f8..a9571441f8 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/results/wings
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/wings
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/array/array_use.erl b/lib/dialyzer/test/opaque_SUITE_data/src/array/array_use.erl
index 1702dc8f03..1702dc8f03 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/array/array_use.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/array/array_use.erl
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/crash/crash_1.erl b/lib/dialyzer/test/opaque_SUITE_data/src/crash/crash_1.erl
index eebeed15af..eebeed15af 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/crash/crash_1.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/crash/crash_1.erl
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/dict/dict_use.erl b/lib/dialyzer/test/opaque_SUITE_data/src/dict/dict_use.erl
new file mode 100644
index 0000000000..8a2cd86f43
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/dict/dict_use.erl
@@ -0,0 +1,82 @@
+-module(dict_use).
+
+-export([ok1/0, ok2/0, ok3/0, ok4/0, ok5/0, ok6/0]).
+-export([middle/0]).
+-export([w1/0, w2/0, w3/0, w4/1, w5/0, w6/0, w7/0, w8/1, w9/0]).
+
+-define(DICT, dict).
+
+%%---------------------------------------------------------------------
+%% Cases that are OK
+%%---------------------------------------------------------------------
+
+ok1() ->
+ dict:new().
+
+ok2() ->
+ case dict:new() of X -> X end.
+
+ok3() ->
+ Dict1 = dict:new(),
+ Dict2 = dict:new(),
+ Dict1 =:= Dict2.
+
+ok4() ->
+ dict:fetch(foo, dict:new()).
+
+ok5() -> % this is OK since some_mod:new/0 might be returning a dict()
+ dict:fetch(foo, some_mod:new()).
+
+ok6() ->
+ dict:store(42, elli, dict:new()).
+
+middle() ->
+ {w1(), w2()}.
+
+%%---------------------------------------------------------------------
+%% Cases that are problematic w.r.t. opaqueness of types
+%%---------------------------------------------------------------------
+
+w1() ->
+ gazonk = dict:new().
+
+w2() ->
+ case dict:new() of
+ [] -> nil;
+ 42 -> weird
+ end.
+
+w3() ->
+ try dict:new() of
+ [] -> nil;
+ 42 -> weird
+ catch
+ _:_ -> exception
+ end.
+
+w4(Dict) when is_list(Dict) ->
+ Dict =:= dict:new();
+w4(Dict) when is_atom(Dict) ->
+ Dict =/= dict:new().
+
+w5() ->
+ case dict:new() of
+ D when length(D) =/= 42 -> weird;
+ D when is_atom(D) -> weirder;
+ D when is_list(D) -> gazonk
+ end.
+
+w6() ->
+ is_list(dict:new()).
+
+w7() ->
+ dict:fetch(foo, [1,2,3]).
+
+w8(Fun) ->
+ dict:merge(Fun, 42, [1,2]).
+
+w9() ->
+ dict:store(42, elli,
+ {dict,0,16,16,8,80,48,
+ {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
+ {{[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]}}}).
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ets/ets_use.erl b/lib/dialyzer/test/opaque_SUITE_data/src/ets/ets_use.erl
new file mode 100644
index 0000000000..d65af0af4e
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/ets/ets_use.erl
@@ -0,0 +1,16 @@
+-module(ets_use).
+-export([t1/0, t2/0]).
+
+t1() ->
+ case n() of
+ T when is_atom(T) -> atm;
+ T when is_integer(T) -> int
+ end.
+
+t2() ->
+ case n() of
+ T when is_integer(T) -> int;
+ T when is_atom(T) -> atm
+ end.
+
+n() -> ets:new(n, [named_table]).
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl
new file mode 100644
index 0000000000..0b98f550f1
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl
@@ -0,0 +1,240 @@
+-ifndef(_EWGI_HRL).
+-define(_EWGI_HRL, 1).
+
+% ``The contents of this file are subject to the Mozilla Public License
+% Version 1.1 (the "License"); you may not use this file except in
+% compliance with the License. You may obtain a copy of the License at
+% http://www.mozilla.org/MPL/
+%
+% Software distributed under the License is distributed on an "AS IS"
+% 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 Original Code is the EWGI reference implementation.
+%
+% The Initial Developer of the Original Code is S.G. Consulting
+% srl. Portions created by S.G. Consulting s.r.l. are Copyright (C)
+% 2007 S.G. Consulting srl. All Rights Reserved.
+%
+% Contributor(s): Filippo Pacini <[email protected]>
+% Hunter Morris <[email protected]>
+
+-define(DEFAULT_CHUNKSIZE, 4096).
+
+-type ewgi_propval() :: atom() | integer() | string() | binary().
+-type ewgi_prop() :: {ewgi_propval(), ewgi_propval()}.
+-type ewgi_proplist() :: [ewgi_prop()].
+
+%% @type bag() = gb_tree()
+-ifdef(HAS_GB_TREE_SPEC).
+-type bag() :: gb_tree().
+-else.
+-type bag() :: {non_neg_integer(), {any(), any(), any(), any()} | 'nil'}.
+-endif.
+
+%%% Note: Dialyzer currently doesn't support recursive types. When it does, this should change:
+%%%-type ewgi_ri_callback() :: fun(('eof' | {data, binary()}) -> iolist() | ewgi_ri_callback()).
+%% @type ewgi_ri_callback() = function()
+-type ewgi_ri_callback() :: fun(('eof' | {data, binary()}) -> iolist() | function()) | iolist().
+
+%% @type ewgi_read_input() = function()
+-type ewgi_read_input() :: fun((ewgi_ri_callback(), integer()) -> ewgi_ri_callback()).
+
+%% @type ewgi_write_error() = function()
+-type ewgi_write_error() :: fun((any()) -> 'ok').
+
+%% @type ewgi_version() = {integer(), integer()}
+-type ewgi_version() :: {integer(), integer()}.
+
+%% @type ewgi_spec() = {'ewgi_spec', function(), function(), string(),
+%% ewgi_version(), bag()}
+
+-type ewgi_spec() :: {'ewgi_spec', ewgi_read_input(),
+ ewgi_write_error(), string(), ewgi_version(),
+ bag()}.
+
+-define(IS_EWGI_SPEC(R), ((element(1, R) =:= 'ewgi_spec')
+ and (size(R) =:= 6))).
+-define(GET_EWGI_READ_INPUT(R), element(2, R)).
+-define(SET_EWGI_READ_INPUT(A, R), setelement(2, R, A)).
+-define(GET_EWGI_WRITE_ERROR(R), element(3, R)).
+-define(SET_EWGI_WRITE_ERROR(A, R), setelement(3, R, A)).
+-define(GET_EWGI_URL_SCHEME(R), element(4, R)).
+-define(SET_EWGI_URL_SCHEME(A, R), setelement(4, R, A)).
+-define(GET_EWGI_VERSION(R), element(5, R)).
+-define(SET_EWGI_VERSION(A, R), setelement(5, R, A)).
+-define(GET_EWGI_DATA(R), element(6, R)).
+-define(SET_EWGI_DATA(A, R), setelement(6, R, A)).
+
+%% @type ewgi_header_val() = string() | 'undefined'
+-type ewgi_header_val() :: string() | 'undefined'.
+
+%% @type ewgi_header_key() = string()
+-type ewgi_header_key() :: string().
+
+%% @type ewgi_http_headers() = {'ewgi_http_headers',
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% bag()}
+
+-type ewgi_http_headers() :: {'ewgi_http_headers', ewgi_header_val(),
+ ewgi_header_val(), ewgi_header_val(),
+ ewgi_header_val(), ewgi_header_val(),
+ ewgi_header_val(), bag()}.
+
+-define(IS_HTTP_HEADERS(R), ((element(1, R) =:= 'ewgi_http_headers')
+ and (size(R) =:= 8))).
+-define(GET_HTTP_ACCEPT(R), element(2, R)).
+-define(SET_HTTP_ACCEPT(A, R), setelement(2, R, A)).
+-define(GET_HTTP_COOKIE(R), element(3, R)).
+-define(SET_HTTP_COOKIE(A, R), setelement(3, R, A)).
+-define(GET_HTTP_HOST(R), element(4, R)).
+-define(SET_HTTP_HOST(A, R), setelement(4, R, A)).
+-define(GET_HTTP_IF_MODIFIED_SINCE(R), element(5, R)).
+-define(SET_HTTP_IF_MODIFIED_SINCE(A, R), setelement(5, R, A)).
+-define(GET_HTTP_USER_AGENT(R), element(6, R)).
+-define(SET_HTTP_USER_AGENT(A, R), setelement(6, R, A)).
+-define(GET_HTTP_X_HTTP_METHOD_OVERRIDE(R), element(7, R)).
+-define(SET_HTTP_X_HTTP_METHOD_OVERRIDE(A, R), setelement(7, R, A)).
+-define(GET_HTTP_OTHER(R), element(8, R)).
+-define(SET_HTTP_OTHER(A, R), setelement(8, R, A)).
+
+%% @type ewgi_request_method() = 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' |
+%% 'DELETE' | 'TRACE' | 'CONNECT' | string()
+-type ewgi_request_method() :: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' |
+ 'DELETE' | 'TRACE' | 'CONNECT' | string().
+
+%% @type ewgi_val() = string() | 'undefined'
+-type ewgi_val() :: string() | 'undefined'.
+
+%% @type ewgi_request() :: {'ewgi_request', ewgi_val(), integer(), ewgi_val(),
+%% ewgi_spec(), ewgi_val(), ewgi_http_headers(),
+%% ewgi_val(), ewgi_val(), ewgi_val(), ewgi_val(),
+%% ewgi_val(), ewgi_val(), ewgi_val(), ewgi_val(),
+%% ewgi_request_method(), ewgi_val(), ewgi_val(),
+%% ewgi_val(), ewgi_val(), ewgi_val()}
+
+-type ewgi_request() :: {'ewgi_request', ewgi_val(),
+ non_neg_integer(), ewgi_val(), ewgi_spec(),
+ ewgi_val(), ewgi_http_headers(), ewgi_val(),
+ ewgi_val(), ewgi_val(), ewgi_val(),
+ ewgi_val(), ewgi_val(), ewgi_val(),
+ ewgi_val(), ewgi_request_method(),
+ ewgi_val(), ewgi_val(), ewgi_val(),
+ ewgi_val(), ewgi_val()}.
+
+-define(IS_EWGI_REQUEST(R), ((element(1, R) =:= 'ewgi_request')
+ and (size(R) =:= 21))).
+-define(GET_AUTH_TYPE(R), element(2, R)).
+-define(SET_AUTH_TYPE(A, R), setelement(2, R, A)).
+-define(GET_CONTENT_LENGTH(R), element(3, R)).
+-define(SET_CONTENT_LENGTH(A, R), setelement(3, R, A)).
+-define(GET_CONTENT_TYPE(R), element(4, R)).
+-define(SET_CONTENT_TYPE(A, R), setelement(4, R, A)).
+-define(GET_EWGI(R), element(5, R)).
+-define(SET_EWGI(A, R), setelement(5, R, A)).
+-define(GET_GATEWAY_INTERFACE(R), element(6, R)).
+-define(SET_GATEWAY_INTERFACE(A, R), setelement(6, R, A)).
+-define(GET_HTTP_HEADERS(R), element(7, R)).
+-define(SET_HTTP_HEADERS(A, R), setelement(7, R, A)).
+-define(GET_PATH_INFO(R), element(8, R)).
+-define(SET_PATH_INFO(A, R), setelement(8, R, A)).
+-define(GET_PATH_TRANSLATED(R), element(9, R)).
+-define(SET_PATH_TRANSLATED(A, R), setelement(9, R, A)).
+-define(GET_QUERY_STRING(R), element(10, R)).
+-define(SET_QUERY_STRING(A, R), setelement(10, R, A)).
+-define(GET_REMOTE_ADDR(R), element(11, R)).
+-define(SET_REMOTE_ADDR(A, R), setelement(11, R, A)).
+-define(GET_REMOTE_HOST(R), element(12, R)).
+-define(SET_REMOTE_HOST(A, R), setelement(12, R, A)).
+-define(GET_REMOTE_IDENT(R), element(13, R)).
+-define(SET_REMOTE_IDENT(A, R), setelement(13, R, A)).
+-define(GET_REMOTE_USER(R), element(14, R)).
+-define(SET_REMOTE_USER(A, R), setelement(14, R, A)).
+-define(GET_REMOTE_USER_DATA(R), element(15, R)).
+-define(SET_REMOTE_USER_DATA(A, R), setelement(15, R, A)).
+-define(GET_REQUEST_METHOD(R), element(16, R)).
+-define(SET_REQUEST_METHOD(A, R), setelement(16, R, A)).
+-define(GET_SCRIPT_NAME(R), element(17, R)).
+-define(SET_SCRIPT_NAME(A, R), setelement(17, R, A)).
+-define(GET_SERVER_NAME(R), element(18, R)).
+-define(SET_SERVER_NAME(A, R), setelement(18, R, A)).
+-define(GET_SERVER_PORT(R), element(19, R)).
+-define(SET_SERVER_PORT(A, R), setelement(19, R, A)).
+-define(GET_SERVER_PROTOCOL(R), element(20, R)).
+-define(SET_SERVER_PROTOCOL(A, R), setelement(20, R, A)).
+-define(GET_SERVER_SOFTWARE(R), element(21, R)).
+-define(SET_SERVER_SOFTWARE(A, R), setelement(21, R, A)).
+
+%%% Note: Dialyzer currently doesn't support recursive types. When it does, this should change:
+%%%-type stream() :: fun(() -> {} | {any(), stream()}).
+%% @type stream() = function()
+-type stream() :: fun(() -> {} | {any(), function()}).
+
+%% @type ewgi_status() = {integer(), string()}
+-type ewgi_status() :: {integer(), string()}.
+
+%% @type ewgi_message_body() = binary() | iolist() | stream()
+-type ewgi_message_body() :: binary() | iolist() | stream().
+
+%% @type ewgi_header_list() = [{ewgi_header_key(), ewgi_header_val()}]
+-type ewgi_header_list() :: [{ewgi_header_key(), ewgi_header_val()}].
+
+%% @type ewgi_response() = {'ewgi_response', ewgi_status(),
+%% [{ewgi_header_key(), ewgi_header_val()}],
+%% ewgi_message_body(), any()}
+
+-type ewgi_response() :: {'ewgi_response', ewgi_status(), ewgi_header_list(), ewgi_message_body(), any()}.
+
+-define(IS_EWGI_RESPONSE(R), ((element(1, R) =:= 'ewgi_response')
+ and (size(R) =:= 5))).
+-define(GET_RESPONSE_STATUS(R), element(2, R)).
+-define(SET_RESPONSE_STATUS(A, R), setelement(2, R, A)).
+-define(GET_RESPONSE_HEADERS(R), element(3, R)).
+-define(SET_RESPONSE_HEADERS(A, R), setelement(3, R, A)).
+-define(GET_RESPONSE_MESSAGE_BODY(R), element(4, R)).
+-define(SET_RESPONSE_MESSAGE_BODY(A, R), setelement(4, R, A)).
+-define(GET_RESPONSE_ERROR(R), element(5, R)).
+-define(SET_RESPONSE_ERROR(A, R), setelement(5, R, A)).
+
+%% @type ewgi_context() = {'ewgi_context', ewgi_request(), ewgi_response()}
+
+-type ewgi_context() :: {'ewgi_context', ewgi_request(), ewgi_response()}.
+
+-define(IS_EWGI_CONTEXT(R), ((element(1, R) =:= 'ewgi_context')
+ and ?IS_EWGI_REQUEST(element(2, R))
+ and ?IS_EWGI_RESPONSE(element(3, R))
+ and (size(R) =:= 3))).
+-define(GET_EWGI_REQUEST(R), element(2, R)).
+-define(SET_EWGI_REQUEST(A, R), setelement(2, R, A)).
+-define(GET_EWGI_RESPONSE(R), element(3, R)).
+-define(SET_EWGI_RESPONSE(A, R), setelement(3, R, A)).
+
+%% @type ewgi_app() = function()
+-type ewgi_app() :: fun((ewgi_context()) -> ewgi_context()).
+
+-ifndef(debug).
+-define(INSPECT_EWGI_RESPONSE(Ctx), Ctx).
+-else.
+-define(INSPECT_EWGI_RESPONSE(Ctx),
+ begin
+ error_logger:info_msg("Inpecting the final ewgi_response()...~n"
+ "Requested Url: ~p~n"
+ "Status: ~p~n"
+ "Headers: ~p~n"
+ "Body: ~p~n",
+ [ewgi_api:path_info(Ctx),
+ ewgi_api:response_status(Ctx),
+ ewgi_api:response_headers(Ctx),
+ ewgi_api:response_message_body(Ctx)]),
+ Ctx
+ end
+ ).
+-endif.
+
+-endif.
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_api.erl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_api.erl
new file mode 100644
index 0000000000..60da757d3b
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_api.erl
@@ -0,0 +1,65 @@
+%%%-------------------------------------------------------------------
+%%% File : ewgi_api.erl
+%%% Authors : Filippo Pacini <[email protected]>
+%%% Hunter Morris <[email protected]>
+%%% License :
+%%% The contents of this file are subject to the Mozilla Public
+%%% License Version 1.1 (the "License"); you may not use this file
+%%% except in compliance with the License. You may obtain a copy of
+%%% the License at http://www.mozilla.org/MPL/
+%%%
+%%% Software distributed under the License is distributed on an "AS IS"
+%%% 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 S.G. Consulting
+%%% srl. Portions created by S.G. Consulting s.r.l. are Copyright (C)
+%%% 2007 S.G. Consulting srl. All Rights Reserved.
+%%%
+%%% @doc
+%%% <p>ewgi API. Defines a low level CGI like API.</p>
+%%%
+%%% @end
+%%%
+%%% Created : 10 Oct 2007 by Filippo Pacini <[email protected]>
+%%%-------------------------------------------------------------------
+-module(ewgi_api).
+
+-include_lib("ewgi.hrl").
+
+-export([get_all_headers/1, get_all_data/1]).
+
+-spec request(ewgi_context()) -> ewgi_request().
+request(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_EWGI_REQUEST(Ctx).
+
+-spec headers(ewgi_context()) -> ewgi_http_headers().
+headers(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_HTTP_HEADERS(request(Ctx)).
+
+get_header_value(Hdr0, Ctx) when is_list(Hdr0), ?IS_EWGI_CONTEXT(Ctx) ->
+ Hdr = string:to_lower(Hdr0),
+ get_header1(Hdr, Ctx).
+
+get_header1("accept", Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_HTTP_ACCEPT(headers(Ctx)).
+
+unzip_header_value([{_,_}|_]=V) ->
+ {_, V1} = lists:unzip(V),
+ string:join(V1, ", ");
+unzip_header_value(V) ->
+ V.
+
+get_all_headers(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ H = headers(Ctx),
+ Other = gb_trees:to_list(?GET_HTTP_OTHER(H)),
+ Acc = [{K, unzip_header_value(V)} || {K, V} <- Other],
+ L = [{"accept", get_header_value("accept", Ctx)}|Acc],
+ lists:filter(fun({_, undefined}) -> false; (_) -> true end, L).
+
+-spec ewgi_spec(ewgi_context()) -> ewgi_spec().
+ewgi_spec(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_EWGI(request(Ctx)).
+
+get_all_data(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_EWGI_DATA(ewgi_spec(Ctx)).
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_testapp.erl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_testapp.erl
new file mode 100644
index 0000000000..59c1ae9206
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_testapp.erl
@@ -0,0 +1,46 @@
+%%%-------------------------------------------------------------------
+%%% File : ewgi_testapp.erl
+%%% Authors : Hunter Morris <[email protected]>
+%%% License :
+%%% The contents of this file are subject to the Mozilla Public
+%%% License Version 1.1 (the "License"); you may not use this file
+%%% except in compliance with the License. You may obtain a copy of
+%%% the License at http://www.mozilla.org/MPL/
+%%%
+%%% Software distributed under the License is distributed on an "AS IS"
+%%% 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 S.G. Consulting
+%%% srl. Portions created by S.G. Consulting s.r.l. are Copyright (C)
+%%% 2007 S.G. Consulting srl. All Rights Reserved.
+%%%
+%%% @doc
+%%% <p>ewgi test applications</p>
+%%%
+%%% @end
+%%%
+%%% Created : 05 July 2009 by Hunter Morris <[email protected]>
+%%%-------------------------------------------------------------------
+-module(ewgi_testapp).
+
+-export([htmlise/1]).
+
+-include_lib("ewgi.hrl").
+
+htmlise(C) ->
+ iolist_to_binary(
+ ["<dl class=\"request\">",
+ io_lib:format("<dt>other http headers</dt><dd>~s</dd>", [htmlise_data("http_headers", ewgi_api:get_all_headers(C))]),
+ io_lib:format("<dt>ewgi extra data</dt><dd>~s</dd>", [htmlise_data("request_data", ewgi_api:get_all_data(C))]),
+ "</dl>"]).
+
+htmlise_data(Name, L) when is_list(L) ->
+ ["<dl class=\"", Name, "\">",
+ [io_lib:format("<dt>~s</dt><dd><pre>~p</pre><dd>", [K, V]) || {K, V} <- L],
+ "</dl>"];
+htmlise_data(Name, T) ->
+ case gb_trees:to_list(T) of
+ [] -> [];
+ L -> htmlise_data(Name, L)
+ end.
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl
new file mode 100644
index 0000000000..5da8ff0ecf
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl
@@ -0,0 +1,241 @@
+-ifndef(_EWGI_HRL).
+-define(_EWGI_HRL, 1).
+
+% ``The contents of this file are subject to the Mozilla Public License
+% Version 1.1 (the "License"); you may not use this file except in
+% compliance with the License. You may obtain a copy of the License at
+% http://www.mozilla.org/MPL/
+%
+% Software distributed under the License is distributed on an "AS IS"
+% 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 Original Code is the EWGI reference implementation.
+%
+% The Initial Developer of the Original Code is S.G. Consulting
+% srl. Portions created by S.G. Consulting s.r.l. are Copyright (C)
+% 2007 S.G. Consulting srl. All Rights Reserved.
+%
+% Contributor(s): Filippo Pacini <[email protected]>
+% Hunter Morris <[email protected]>
+
+-define(DEFAULT_CHUNKSIZE, 4096).
+-define(HAS_GB_TREE_SPEC, true).
+
+-type ewgi_propval() :: atom() | integer() | string() | binary().
+-type ewgi_prop() :: {ewgi_propval(), ewgi_propval()}.
+-type ewgi_proplist() :: [ewgi_prop()].
+
+%% @type bag() = gb_tree()
+-ifdef(HAS_GB_TREE_SPEC).
+-type bag() :: gb_tree().
+-else.
+-type bag() :: {non_neg_integer(), {any(), any(), any(), any()} | 'nil'}.
+-endif.
+
+%%% Note: Dialyzer currently doesn't support recursive types. When it does, this should change:
+%%%-type ewgi_ri_callback() :: fun(('eof' | {data, binary()}) -> iolist() | ewgi_ri_callback()).
+%% @type ewgi_ri_callback() = function()
+-type ewgi_ri_callback() :: fun(('eof' | {data, binary()}) -> iolist() | function()) | iolist().
+
+%% @type ewgi_read_input() = function()
+-type ewgi_read_input() :: fun((ewgi_ri_callback(), integer()) -> ewgi_ri_callback()).
+
+%% @type ewgi_write_error() = function()
+-type ewgi_write_error() :: fun((any()) -> 'ok').
+
+%% @type ewgi_version() = {integer(), integer()}
+-type ewgi_version() :: {integer(), integer()}.
+
+%% @type ewgi_spec() = {'ewgi_spec', function(), function(), string(),
+%% ewgi_version(), bag()}
+
+-type ewgi_spec() :: {'ewgi_spec', ewgi_read_input(),
+ ewgi_write_error(), string(), ewgi_version(),
+ bag()}.
+
+-define(IS_EWGI_SPEC(R), ((element(1, R) =:= 'ewgi_spec')
+ and (size(R) =:= 6))).
+-define(GET_EWGI_READ_INPUT(R), element(2, R)).
+-define(SET_EWGI_READ_INPUT(A, R), setelement(2, R, A)).
+-define(GET_EWGI_WRITE_ERROR(R), element(3, R)).
+-define(SET_EWGI_WRITE_ERROR(A, R), setelement(3, R, A)).
+-define(GET_EWGI_URL_SCHEME(R), element(4, R)).
+-define(SET_EWGI_URL_SCHEME(A, R), setelement(4, R, A)).
+-define(GET_EWGI_VERSION(R), element(5, R)).
+-define(SET_EWGI_VERSION(A, R), setelement(5, R, A)).
+-define(GET_EWGI_DATA(R), element(6, R)).
+-define(SET_EWGI_DATA(A, R), setelement(6, R, A)).
+
+%% @type ewgi_header_val() = string() | 'undefined'
+-type ewgi_header_val() :: string() | 'undefined'.
+
+%% @type ewgi_header_key() = string()
+-type ewgi_header_key() :: string().
+
+%% @type ewgi_http_headers() = {'ewgi_http_headers',
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% bag()}
+
+-type ewgi_http_headers() :: {'ewgi_http_headers', ewgi_header_val(),
+ ewgi_header_val(), ewgi_header_val(),
+ ewgi_header_val(), ewgi_header_val(),
+ ewgi_header_val(), bag()}.
+
+-define(IS_HTTP_HEADERS(R), ((element(1, R) =:= 'ewgi_http_headers')
+ and (size(R) =:= 8))).
+-define(GET_HTTP_ACCEPT(R), element(2, R)).
+-define(SET_HTTP_ACCEPT(A, R), setelement(2, R, A)).
+-define(GET_HTTP_COOKIE(R), element(3, R)).
+-define(SET_HTTP_COOKIE(A, R), setelement(3, R, A)).
+-define(GET_HTTP_HOST(R), element(4, R)).
+-define(SET_HTTP_HOST(A, R), setelement(4, R, A)).
+-define(GET_HTTP_IF_MODIFIED_SINCE(R), element(5, R)).
+-define(SET_HTTP_IF_MODIFIED_SINCE(A, R), setelement(5, R, A)).
+-define(GET_HTTP_USER_AGENT(R), element(6, R)).
+-define(SET_HTTP_USER_AGENT(A, R), setelement(6, R, A)).
+-define(GET_HTTP_X_HTTP_METHOD_OVERRIDE(R), element(7, R)).
+-define(SET_HTTP_X_HTTP_METHOD_OVERRIDE(A, R), setelement(7, R, A)).
+-define(GET_HTTP_OTHER(R), element(8, R)).
+-define(SET_HTTP_OTHER(A, R), setelement(8, R, A)).
+
+%% @type ewgi_request_method() = 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' |
+%% 'DELETE' | 'TRACE' | 'CONNECT' | string()
+-type ewgi_request_method() :: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' |
+ 'DELETE' | 'TRACE' | 'CONNECT' | string().
+
+%% @type ewgi_val() = string() | 'undefined'
+-type ewgi_val() :: string() | 'undefined'.
+
+%% @type ewgi_request() :: {'ewgi_request', ewgi_val(), integer(), ewgi_val(),
+%% ewgi_spec(), ewgi_val(), ewgi_http_headers(),
+%% ewgi_val(), ewgi_val(), ewgi_val(), ewgi_val(),
+%% ewgi_val(), ewgi_val(), ewgi_val(), ewgi_val(),
+%% ewgi_request_method(), ewgi_val(), ewgi_val(),
+%% ewgi_val(), ewgi_val(), ewgi_val()}
+
+-type ewgi_request() :: {'ewgi_request', ewgi_val(),
+ non_neg_integer(), ewgi_val(), ewgi_spec(),
+ ewgi_val(), ewgi_http_headers(), ewgi_val(),
+ ewgi_val(), ewgi_val(), ewgi_val(),
+ ewgi_val(), ewgi_val(), ewgi_val(),
+ ewgi_val(), ewgi_request_method(),
+ ewgi_val(), ewgi_val(), ewgi_val(),
+ ewgi_val(), ewgi_val()}.
+
+-define(IS_EWGI_REQUEST(R), ((element(1, R) =:= 'ewgi_request')
+ and (size(R) =:= 21))).
+-define(GET_AUTH_TYPE(R), element(2, R)).
+-define(SET_AUTH_TYPE(A, R), setelement(2, R, A)).
+-define(GET_CONTENT_LENGTH(R), element(3, R)).
+-define(SET_CONTENT_LENGTH(A, R), setelement(3, R, A)).
+-define(GET_CONTENT_TYPE(R), element(4, R)).
+-define(SET_CONTENT_TYPE(A, R), setelement(4, R, A)).
+-define(GET_EWGI(R), element(5, R)).
+-define(SET_EWGI(A, R), setelement(5, R, A)).
+-define(GET_GATEWAY_INTERFACE(R), element(6, R)).
+-define(SET_GATEWAY_INTERFACE(A, R), setelement(6, R, A)).
+-define(GET_HTTP_HEADERS(R), element(7, R)).
+-define(SET_HTTP_HEADERS(A, R), setelement(7, R, A)).
+-define(GET_PATH_INFO(R), element(8, R)).
+-define(SET_PATH_INFO(A, R), setelement(8, R, A)).
+-define(GET_PATH_TRANSLATED(R), element(9, R)).
+-define(SET_PATH_TRANSLATED(A, R), setelement(9, R, A)).
+-define(GET_QUERY_STRING(R), element(10, R)).
+-define(SET_QUERY_STRING(A, R), setelement(10, R, A)).
+-define(GET_REMOTE_ADDR(R), element(11, R)).
+-define(SET_REMOTE_ADDR(A, R), setelement(11, R, A)).
+-define(GET_REMOTE_HOST(R), element(12, R)).
+-define(SET_REMOTE_HOST(A, R), setelement(12, R, A)).
+-define(GET_REMOTE_IDENT(R), element(13, R)).
+-define(SET_REMOTE_IDENT(A, R), setelement(13, R, A)).
+-define(GET_REMOTE_USER(R), element(14, R)).
+-define(SET_REMOTE_USER(A, R), setelement(14, R, A)).
+-define(GET_REMOTE_USER_DATA(R), element(15, R)).
+-define(SET_REMOTE_USER_DATA(A, R), setelement(15, R, A)).
+-define(GET_REQUEST_METHOD(R), element(16, R)).
+-define(SET_REQUEST_METHOD(A, R), setelement(16, R, A)).
+-define(GET_SCRIPT_NAME(R), element(17, R)).
+-define(SET_SCRIPT_NAME(A, R), setelement(17, R, A)).
+-define(GET_SERVER_NAME(R), element(18, R)).
+-define(SET_SERVER_NAME(A, R), setelement(18, R, A)).
+-define(GET_SERVER_PORT(R), element(19, R)).
+-define(SET_SERVER_PORT(A, R), setelement(19, R, A)).
+-define(GET_SERVER_PROTOCOL(R), element(20, R)).
+-define(SET_SERVER_PROTOCOL(A, R), setelement(20, R, A)).
+-define(GET_SERVER_SOFTWARE(R), element(21, R)).
+-define(SET_SERVER_SOFTWARE(A, R), setelement(21, R, A)).
+
+%%% Note: Dialyzer currently doesn't support recursive types. When it does, this should change:
+%%%-type stream() :: fun(() -> {} | {any(), stream()}).
+%% @type stream() = function()
+-type stream() :: fun(() -> {} | {any(), function()}).
+
+%% @type ewgi_status() = {integer(), string()}
+-type ewgi_status() :: {integer(), string()}.
+
+%% @type ewgi_message_body() = binary() | iolist() | stream()
+-type ewgi_message_body() :: binary() | iolist() | stream().
+
+%% @type ewgi_header_list() = [{ewgi_header_key(), ewgi_header_val()}]
+-type ewgi_header_list() :: [{ewgi_header_key(), ewgi_header_val()}].
+
+%% @type ewgi_response() = {'ewgi_response', ewgi_status(),
+%% [{ewgi_header_key(), ewgi_header_val()}],
+%% ewgi_message_body(), any()}
+
+-type ewgi_response() :: {'ewgi_response', ewgi_status(), ewgi_header_list(), ewgi_message_body(), any()}.
+
+-define(IS_EWGI_RESPONSE(R), ((element(1, R) =:= 'ewgi_response')
+ and (size(R) =:= 5))).
+-define(GET_RESPONSE_STATUS(R), element(2, R)).
+-define(SET_RESPONSE_STATUS(A, R), setelement(2, R, A)).
+-define(GET_RESPONSE_HEADERS(R), element(3, R)).
+-define(SET_RESPONSE_HEADERS(A, R), setelement(3, R, A)).
+-define(GET_RESPONSE_MESSAGE_BODY(R), element(4, R)).
+-define(SET_RESPONSE_MESSAGE_BODY(A, R), setelement(4, R, A)).
+-define(GET_RESPONSE_ERROR(R), element(5, R)).
+-define(SET_RESPONSE_ERROR(A, R), setelement(5, R, A)).
+
+%% @type ewgi_context() = {'ewgi_context', ewgi_request(), ewgi_response()}
+
+-type ewgi_context() :: {'ewgi_context', ewgi_request(), ewgi_response()}.
+
+-define(IS_EWGI_CONTEXT(R), ((element(1, R) =:= 'ewgi_context')
+ and ?IS_EWGI_REQUEST(element(2, R))
+ and ?IS_EWGI_RESPONSE(element(3, R))
+ and (size(R) =:= 3))).
+-define(GET_EWGI_REQUEST(R), element(2, R)).
+-define(SET_EWGI_REQUEST(A, R), setelement(2, R, A)).
+-define(GET_EWGI_RESPONSE(R), element(3, R)).
+-define(SET_EWGI_RESPONSE(A, R), setelement(3, R, A)).
+
+%% @type ewgi_app() = function()
+-type ewgi_app() :: fun((ewgi_context()) -> ewgi_context()).
+
+-ifndef(debug).
+-define(INSPECT_EWGI_RESPONSE(Ctx), Ctx).
+-else.
+-define(INSPECT_EWGI_RESPONSE(Ctx),
+ begin
+ error_logger:info_msg("Inpecting the final ewgi_response()...~n"
+ "Requested Url: ~p~n"
+ "Status: ~p~n"
+ "Headers: ~p~n"
+ "Body: ~p~n",
+ [ewgi_api:path_info(Ctx),
+ ewgi_api:response_status(Ctx),
+ ewgi_api:response_headers(Ctx),
+ ewgi_api:response_message_body(Ctx)]),
+ Ctx
+ end
+ ).
+-endif.
+
+-endif.
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_api.erl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_api.erl
new file mode 100644
index 0000000000..60da757d3b
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_api.erl
@@ -0,0 +1,65 @@
+%%%-------------------------------------------------------------------
+%%% File : ewgi_api.erl
+%%% Authors : Filippo Pacini <[email protected]>
+%%% Hunter Morris <[email protected]>
+%%% License :
+%%% The contents of this file are subject to the Mozilla Public
+%%% License Version 1.1 (the "License"); you may not use this file
+%%% except in compliance with the License. You may obtain a copy of
+%%% the License at http://www.mozilla.org/MPL/
+%%%
+%%% Software distributed under the License is distributed on an "AS IS"
+%%% 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 S.G. Consulting
+%%% srl. Portions created by S.G. Consulting s.r.l. are Copyright (C)
+%%% 2007 S.G. Consulting srl. All Rights Reserved.
+%%%
+%%% @doc
+%%% <p>ewgi API. Defines a low level CGI like API.</p>
+%%%
+%%% @end
+%%%
+%%% Created : 10 Oct 2007 by Filippo Pacini <[email protected]>
+%%%-------------------------------------------------------------------
+-module(ewgi_api).
+
+-include_lib("ewgi.hrl").
+
+-export([get_all_headers/1, get_all_data/1]).
+
+-spec request(ewgi_context()) -> ewgi_request().
+request(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_EWGI_REQUEST(Ctx).
+
+-spec headers(ewgi_context()) -> ewgi_http_headers().
+headers(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_HTTP_HEADERS(request(Ctx)).
+
+get_header_value(Hdr0, Ctx) when is_list(Hdr0), ?IS_EWGI_CONTEXT(Ctx) ->
+ Hdr = string:to_lower(Hdr0),
+ get_header1(Hdr, Ctx).
+
+get_header1("accept", Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_HTTP_ACCEPT(headers(Ctx)).
+
+unzip_header_value([{_,_}|_]=V) ->
+ {_, V1} = lists:unzip(V),
+ string:join(V1, ", ");
+unzip_header_value(V) ->
+ V.
+
+get_all_headers(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ H = headers(Ctx),
+ Other = gb_trees:to_list(?GET_HTTP_OTHER(H)),
+ Acc = [{K, unzip_header_value(V)} || {K, V} <- Other],
+ L = [{"accept", get_header_value("accept", Ctx)}|Acc],
+ lists:filter(fun({_, undefined}) -> false; (_) -> true end, L).
+
+-spec ewgi_spec(ewgi_context()) -> ewgi_spec().
+ewgi_spec(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_EWGI(request(Ctx)).
+
+get_all_data(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_EWGI_DATA(ewgi_spec(Ctx)).
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_testapp.erl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_testapp.erl
new file mode 100644
index 0000000000..59c1ae9206
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_testapp.erl
@@ -0,0 +1,46 @@
+%%%-------------------------------------------------------------------
+%%% File : ewgi_testapp.erl
+%%% Authors : Hunter Morris <[email protected]>
+%%% License :
+%%% The contents of this file are subject to the Mozilla Public
+%%% License Version 1.1 (the "License"); you may not use this file
+%%% except in compliance with the License. You may obtain a copy of
+%%% the License at http://www.mozilla.org/MPL/
+%%%
+%%% Software distributed under the License is distributed on an "AS IS"
+%%% 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 S.G. Consulting
+%%% srl. Portions created by S.G. Consulting s.r.l. are Copyright (C)
+%%% 2007 S.G. Consulting srl. All Rights Reserved.
+%%%
+%%% @doc
+%%% <p>ewgi test applications</p>
+%%%
+%%% @end
+%%%
+%%% Created : 05 July 2009 by Hunter Morris <[email protected]>
+%%%-------------------------------------------------------------------
+-module(ewgi_testapp).
+
+-export([htmlise/1]).
+
+-include_lib("ewgi.hrl").
+
+htmlise(C) ->
+ iolist_to_binary(
+ ["<dl class=\"request\">",
+ io_lib:format("<dt>other http headers</dt><dd>~s</dd>", [htmlise_data("http_headers", ewgi_api:get_all_headers(C))]),
+ io_lib:format("<dt>ewgi extra data</dt><dd>~s</dd>", [htmlise_data("request_data", ewgi_api:get_all_data(C))]),
+ "</dl>"]).
+
+htmlise_data(Name, L) when is_list(L) ->
+ ["<dl class=\"", Name, "\">",
+ [io_lib:format("<dt>~s</dt><dd><pre>~p</pre><dd>", [K, V]) || {K, V} <- L],
+ "</dl>"];
+htmlise_data(Name, T) ->
+ case gb_trees:to_list(T) of
+ [] -> [];
+ L -> htmlise_data(Name, L)
+ end.
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/gb_sets/gb_sets_rec.erl b/lib/dialyzer/test/opaque_SUITE_data/src/gb_sets/gb_sets_rec.erl
index 008b0a486a..008b0a486a 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/gb_sets/gb_sets_rec.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/gb_sets/gb_sets_rec.erl
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/inf_loop1.erl b/lib/dialyzer/test/opaque_SUITE_data/src/inf_loop1.erl
index 0dff16cf14..0dff16cf14 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/inf_loop1.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/inf_loop1.erl
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/int/int_adt.erl b/lib/dialyzer/test/opaque_SUITE_data/src/int/int_adt.erl
index 99f8cbdc4a..99f8cbdc4a 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/int/int_adt.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/int/int_adt.erl
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/int/int_use.erl b/lib/dialyzer/test/opaque_SUITE_data/src/int/int_use.erl
index b4471e1cee..b4471e1cee 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/int/int_use.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/int/int_use.erl
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/mixed_opaque/mixed_opaque_queue_adt.erl b/lib/dialyzer/test/opaque_SUITE_data/src/mixed_opaque/mixed_opaque_queue_adt.erl
index ac59f19cd3..ac59f19cd3 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/mixed_opaque/mixed_opaque_queue_adt.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/mixed_opaque/mixed_opaque_queue_adt.erl
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/mixed_opaque/mixed_opaque_rec_adt.erl b/lib/dialyzer/test/opaque_SUITE_data/src/mixed_opaque/mixed_opaque_rec_adt.erl
index 61bae5110d..61bae5110d 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/mixed_opaque/mixed_opaque_rec_adt.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/mixed_opaque/mixed_opaque_rec_adt.erl
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/mixed_opaque/mixed_opaque_use.erl b/lib/dialyzer/test/opaque_SUITE_data/src/mixed_opaque/mixed_opaque_use.erl
index e82dcd5f38..e82dcd5f38 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/mixed_opaque/mixed_opaque_use.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/mixed_opaque/mixed_opaque_use.erl
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/my_digraph/my_digraph_adt.erl b/lib/dialyzer/test/opaque_SUITE_data/src/my_digraph/my_digraph_adt.erl
new file mode 100644
index 0000000000..82159d6a8d
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/my_digraph/my_digraph_adt.erl
@@ -0,0 +1,51 @@
+-module(my_digraph_adt).
+
+-export([new/0, new/1]).
+
+-record(my_digraph, {vtab = notable,
+ etab = notable,
+ ntab = notable,
+ cyclic = true :: boolean()}).
+
+-opaque my_digraph() :: #my_digraph{}.
+
+-type d_protection() :: 'private' | 'protected'.
+-type d_cyclicity() :: 'acyclic' | 'cyclic'.
+-type d_type() :: d_cyclicity() | d_protection().
+
+-spec new() -> my_digraph().
+new() -> new([]).
+
+-spec new([atom()]) -> my_digraph().
+new(Type) ->
+ try check_type(Type, protected, []) of
+ {Access, Ts} ->
+ V = ets:new(vertices, [set, Access]),
+ E = ets:new(edges, [set, Access]),
+ N = ets:new(neighbours, [bag, Access]),
+ ets:insert(N, [{'$vid', 0}, {'$eid', 0}]),
+ set_type(Ts, #my_digraph{vtab=V, etab=E, ntab=N})
+ catch
+ throw:Error -> throw(Error)
+ end.
+
+-spec check_type([atom()], d_protection(), [{'cyclic', boolean()}]) ->
+ {d_protection(), [{'cyclic', boolean()}]}.
+
+check_type([acyclic|Ts], A, L) ->
+ check_type(Ts, A,[{cyclic,false} | L]);
+check_type([cyclic | Ts], A, L) ->
+ check_type(Ts, A, [{cyclic,true} | L]);
+check_type([protected | Ts], _, L) ->
+ check_type(Ts, protected, L);
+check_type([private | Ts], _, L) ->
+ check_type(Ts, private, L);
+check_type([T | _], _, _) ->
+ throw({error, {unknown_type, T}});
+check_type([], A, L) -> {A, L}.
+
+-spec set_type([{'cyclic', boolean()}], my_digraph()) -> my_digraph().
+
+set_type([{cyclic,V} | Ks], G) ->
+ set_type(Ks, G#my_digraph{cyclic = V});
+set_type([], G) -> G.
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/my_queue/my_queue_adt.erl b/lib/dialyzer/test/opaque_SUITE_data/src/my_queue/my_queue_adt.erl
index 52688062ce..52688062ce 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/my_queue/my_queue_adt.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/my_queue/my_queue_adt.erl
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/my_queue/my_queue_use.erl b/lib/dialyzer/test/opaque_SUITE_data/src/my_queue/my_queue_use.erl
index 98f9972c1e..98f9972c1e 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/my_queue/my_queue_use.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/my_queue/my_queue_use.erl
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/opaque/opaque_adt.erl b/lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_adt.erl
index 3456f0e9c6..3456f0e9c6 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/opaque/opaque_adt.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_adt.erl
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_bug1.erl b/lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_bug1.erl
new file mode 100644
index 0000000000..5a03989853
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_bug1.erl
@@ -0,0 +1,16 @@
+%%---------------------------------------------------------------------
+%% A test for which the analysis went into an infinite loop due to
+%% specialization using structured type instead of the opaque one.
+%%---------------------------------------------------------------------
+
+-module(opaque_bug1).
+
+-export([test/1]).
+
+-record(c, {a::atom()}).
+
+-opaque erl_type() :: 'any' | #c{}.
+
+test(#c{a=foo} = T) -> local(T).
+
+local(#c{a=foo}) -> any.
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/opaque/opaque_bug2.erl b/lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_bug2.erl
index f193a58f59..f193a58f59 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/opaque/opaque_bug2.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_bug2.erl
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/opaque/opaque_bug3.erl b/lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_bug3.erl
index 71da82a1f6..71da82a1f6 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/opaque/opaque_bug3.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_bug3.erl
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/opaque/opaque_bug4.erl b/lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_bug4.erl
index a7ddc80fe8..a7ddc80fe8 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/opaque/opaque_bug4.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/opaque/opaque_bug4.erl
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/queue/queue_use.erl b/lib/dialyzer/test/opaque_SUITE_data/src/queue/queue_use.erl
new file mode 100644
index 0000000000..8d46bdb989
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/queue/queue_use.erl
@@ -0,0 +1,65 @@
+-module(queue_use).
+
+-export([ok1/0, ok2/0]).
+-export([wrong1/0, wrong2/0, wrong3/0, wrong4/0, wrong5/0, wrong6/0, wrong7/0, wrong8/0]).
+
+ok1() ->
+ queue:is_empty(queue:new()).
+
+ok2() ->
+ Q0 = queue:new(),
+ Q1 = queue:in(42, Q0),
+ {{value, 42}, Q2} = queue:out(Q1),
+ queue:is_empty(Q2).
+
+%%--------------------------------------------------
+
+wrong1() ->
+ queue:is_empty({[],[]}).
+
+wrong2() ->
+ Q0 = {[],[]},
+ queue:in(42, Q0).
+
+wrong3() ->
+ Q0 = queue:new(),
+ Q1 = queue:in(42, Q0),
+ {[42],Q2} = Q1,
+ Q2.
+
+wrong4() ->
+ Q0 = queue:new(),
+ Q1 = queue:in(42, Q0),
+ Q1 =:= {[42],[]}.
+
+wrong5() ->
+ {F, _R} = queue:new(),
+ F.
+
+wrong6() ->
+ {{value, 42}, Q2} = queue:out({[42],[]}),
+ Q2.
+
+%%--------------------------------------------------
+
+-record(db, {p, q}).
+
+wrong7() ->
+ add_unique(42, #db{p = [], q = queue:new()}).
+
+add_unique(E, DB) ->
+ case is_in_queue(E, DB) of
+ true -> DB;
+ false -> DB#db{q = queue:in(E, DB#db.q)}
+ end.
+
+is_in_queue(P, #db{q = {L1,L2}}) ->
+ lists:member(P, L1) orelse lists:member(P, L2).
+
+%%--------------------------------------------------
+
+wrong8() ->
+ tuple_queue({42, gazonk}).
+
+tuple_queue({F, Q}) ->
+ queue:in(F, Q).
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/rec/rec_adt.erl b/lib/dialyzer/test/opaque_SUITE_data/src/rec/rec_adt.erl
index f01cc5e519..f01cc5e519 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/rec/rec_adt.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/rec/rec_adt.erl
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/rec/rec_use.erl b/lib/dialyzer/test/opaque_SUITE_data/src/rec/rec_use.erl
index 358e9f918c..358e9f918c 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/rec/rec_use.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/rec/rec_use.erl
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/schuett_bug.erl b/lib/dialyzer/test/opaque_SUITE_data/src/schuett_bug.erl
new file mode 100644
index 0000000000..00c1aa57bf
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/schuett_bug.erl
@@ -0,0 +1,28 @@
+%%---------------------------------------------------------------------------
+%% From: Thorsten Schuett <[email protected]>
+%% Date: 7 July 2010
+%%
+%% When I run dialyzer of R14A on the attached code, it complains about
+%% the new_neighborhood/1 function:
+%% nodelist.erl:12: Invalid type specification for function
+%% nodelist:new_neighborhood/1. The success typing is (_) -> {[any(),...]}
+%%
+%% However, when I change the type nodelist() from opaque to non-opaque
+%% (see comment), dialyzer accepts the code. The types seem to be correct.
+%% The problem seems to be with nested opaque types.
+%%---------------------------------------------------------------------------
+
+-module(schuett_bug).
+
+-export([new_neighborhood/1]).
+
+-export_type([nodelist/0, neighborhood/0]).
+
+-type node_type() :: 'node_type'.
+
+-opaque nodelist() :: [node_type(),...]. % change to -type
+-opaque neighborhood() :: {nodelist()}.
+
+-spec new_neighborhood(Node::node_type()) -> neighborhood().
+new_neighborhood(Node) ->
+ {[Node]}.
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/timer/timer_use.erl b/lib/dialyzer/test/opaque_SUITE_data/src/timer/timer_use.erl
index 9c8ea0af1c..9c8ea0af1c 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/timer/timer_use.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/timer/timer_use.erl
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/union/union_adt.erl b/lib/dialyzer/test/opaque_SUITE_data/src/union/union_adt.erl
index 5ca3202bba..5ca3202bba 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/union/union_adt.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/union/union_adt.erl
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/union/union_use.erl b/lib/dialyzer/test/opaque_SUITE_data/src/union/union_use.erl
index 6a103279cd..6a103279cd 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/union/union_use.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/union/union_use.erl
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings.hrl b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings.hrl
new file mode 100644
index 0000000000..b815be5e1d
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings.hrl
@@ -0,0 +1,204 @@
+%%
+%% wings.hrl --
+%%
+%% Global record definition and defines.
+%%
+%% Copyright (c) 2001-2005 Bjorn Gustavsson
+%%
+%% See the file "license.terms" for information on usage and redistribution
+%% of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+%%
+%% $Id: wings.hrl,v 1.1 2009/01/25 18:55:33 kostis Exp $
+%%
+
+-include("wings_intl.hrl").
+
+-ifdef(NEED_ESDL).
+-include_lib("esdl/include/sdl.hrl").
+-include_lib("esdl/include/sdl_events.hrl").
+-include_lib("esdl/include/sdl_video.hrl").
+-include_lib("esdl/include/sdl_keyboard.hrl").
+-include_lib("esdl/include/sdl_mouse.hrl").
+-include_lib("esdl/src/sdl_util.hrl").
+-define(CTRL_BITS, ?KMOD_CTRL).
+-define(ALT_BITS, ?KMOD_ALT).
+-define(SHIFT_BITS, ?KMOD_SHIFT).
+-define(META_BITS, ?KMOD_META).
+-endif.
+
+-define(WINGS_VERSION, ?wings_version).
+
+-define(CHAR_HEIGHT, wings_text:height()).
+-define(CHAR_WIDTH, wings_text:width()).
+
+-define(LINE_HEIGHT, (?CHAR_HEIGHT+2)).
+-define(GROUND_GRID_SIZE, 1).
+-define(CAMERA_DIST, (8.0*?GROUND_GRID_SIZE)).
+-define(NORMAL_LINEWIDTH, 1.0).
+-define(DEGREE, 176). %Degree character.
+
+-define(HIT_BUF_SIZE, (1024*1024)).
+
+-define(PANE_COLOR, {0.52,0.52,0.52}).
+-define(BEVEL_HIGHLIGHT, {0.9,0.9,0.9}).
+-define(BEVEL_LOWLIGHT, {0.3,0.3,0.3}).
+-define(BEVEL_HIGHLIGHT_MIX, 0.5).
+-define(BEVEL_LOWLIGHT_MIX, 0.5).
+
+-define(SLOW(Cmd), begin wings_io:hourglass(), Cmd end).
+-define(TC(Cmd), wings_util:tc(fun() -> Cmd end, ?MODULE, ?LINE)).
+
+-ifdef(DEBUG).
+-define(ASSERT(E), case E of
+ true -> ok;
+ _ ->
+ erlang:error({assertion_failed,?MODULE,?LINE})
+ end).
+-define(CHECK_ERROR(), wings_gl:check_error(?MODULE, ?LINE)).
+-else.
+-define(ASSERT(E),ok).
+-define(CHECK_ERROR(), ok).
+-endif.
+
+%% Display lists per object.
+%% Important: Plain integers and integers in lists will be assumed to
+%% be display lists. Arbitrary integers must be stored inside a tuple
+%% or record to not be interpreted as a display list.
+-record(dlo,
+ {work=none, %Workmode faces.
+ smooth=none, %Smooth-shaded faces.
+ edges=none, %Edges and wire-frame.
+ vs=none, %Unselected vertices.
+ hard=none, %Hard edges.
+ sel=none, %Selected items.
+ orig_sel=none, %Original selection.
+ normals=none, %Normals.
+ pick=none, %For picking.
+ proxy_faces=none, %Smooth proxy faces.
+ proxy_edges=none, %Smooth proxy edges.
+
+ %% Miscellanous.
+ hilite=none, %Hilite display list.
+ mirror=none, %Virtual mirror data.
+ ns=none, %Normals/positions per face.
+
+ %% Source for display lists.
+ src_we=none, %Source object.
+ src_sel=none, %Source selection.
+ orig_mode=none, %Original selection mode.
+ split=none, %Split data.
+ drag=none, %For dragging.
+ transparent=false, %Object includes transparancy.
+ proxy_data=none, %Data for smooth proxy.
+ open=false, %Open (has hole).
+
+ %% List of display lists known to be needed only based
+ %% on display modes, not whether the lists themselves exist.
+ %% Example: [work,edges]
+ needed=[]
+ }).
+
+%% Main state record containing all objects and other important state.
+-record(st,
+ {shapes, %All visible shapes
+ selmode, %Selection mode:
+ % vertex, edge, face, body
+ sh=false, %Smart highlight active: true|false
+ sel=[], %Current sel: [{Id,GbSet}]
+ ssels=[], %Saved selections:
+ % [{Name,Mode,GbSet}]
+ temp_sel=none, %Selection only temporary?
+
+ mat, %Defined materials (GbTree).
+ pal=[], %Palette
+ file, %Current filename.
+ saved, %True if model has been saved.
+ onext, %Next object id to use.
+ bb=none, %Saved bounding box.
+ edge_loop=none, %Previous edge loop.
+ views={0,{}}, %{Current,TupleOfViews}
+ pst=gb_trees:empty(), %Plugin State Info
+ % gb_tree where key is plugin module
+
+ %% Previous commands.
+ repeatable, %Last repeatable command.
+ ask_args, %Ask arguments.
+ drag_args, %Drag arguments for command.
+ def, %Default operations.
+
+ %% Undo information.
+ top, %Top of stack.
+ bottom, %Bottom of stack.
+ next_is_undo, %State of undo/redo toggle.
+ undone %States that were undone.
+ }).
+
+%% The Winged-Edge data structure.
+%% See http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/model/winged-e.html
+-record(we,
+ {id, %Shape id.
+ perm=0, %Permissions:
+ % 0 - Everything allowed.
+ % 1 - Visible, can't select.
+ % [] or {Mode,GbSet} -
+ % Invisible, can't select.
+ % The GbSet contains the
+ % object's selection.
+ name, %Name.
+ es, %gb_tree containing edges
+ fs, %gb_tree containing faces
+ he, %gb_sets containing hard edges
+ vc, %Connection info (=incident edge)
+ % for vertices.
+ vp, %Vertex positions.
+ pst=gb_trees:empty(), %Plugin State Info,
+ % gb_tree where key is plugin module
+ mat=default, %Materials.
+ next_id, %Next free ID for vertices,
+ % edges, and faces.
+ % (Needed because we never re-use
+ % IDs.)
+ mode, %'vertex'/'material'/'uv'
+ mirror=none, %Mirror: none|Face
+ light=none, %Light data: none|Light
+ has_shape=true %true|false
+ }).
+
+-define(IS_VISIBLE(Perm), (Perm =< 1)).
+-define(IS_NOT_VISIBLE(Perm), (Perm > 1)).
+-define(IS_SELECTABLE(Perm), (Perm == 0)).
+-define(IS_NOT_SELECTABLE(Perm), (Perm =/= 0)).
+
+-define(IS_LIGHT(We), ((We#we.light =/= none) and (not We#we.has_shape))).
+-define(IS_ANY_LIGHT(We), (We#we.light =/= none)).
+-define(HAS_SHAPE(We), (We#we.has_shape)).
+%-define(IS_LIGHT(We), (We#we.light =/= none)).
+%-define(IS_NOT_LIGHT(We), (We#we.light =:= none)).
+
+%% Edge in a winged-edge shape.
+-record(edge,
+ {vs, %Start vertex for edge
+ ve, %End vertex for edge
+ a=none, %Color or UV coordinate.
+ b=none, %Color or UV coordinate.
+ lf, %Left face
+ rf, %Right face
+ ltpr, %Left traversal predecessor
+ ltsu, %Left traversal successor
+ rtpr, %Right traversal predecessor
+ rtsu %Right traversal successor
+ }).
+
+%% The current view/camera.
+-record(view,
+ {origin,
+ distance, % From origo.
+ azimuth,
+ elevation,
+ pan_x, %Panning in X direction.
+ pan_y, %Panning in Y direction.
+ along_axis=none, %Which axis viewed along.
+ fov, %Field of view.
+ hither, %Near clipping plane.
+ yon %Far clipping plane.
+ }).
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_dissolve.erl b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_dissolve.erl
new file mode 100644
index 0000000000..c469f0a45d
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_dissolve.erl
@@ -0,0 +1,375 @@
+%%
+%% wings_dissolve.erl --
+%%
+%% This module implements dissolve of faces.
+%%
+
+-module(wings_dissolve).
+
+-export([faces/2, complement/2]).
+
+-include("wings.hrl").
+
+%% faces([Face], We) -> We'
+%% Dissolve the given faces.
+faces([], We) -> We;
+faces(Faces, #we{fs=Ftab0}=We) ->
+ case gb_sets:is_empty(Faces) of
+ true -> We;
+ false when is_list(Faces) ->
+ Complement = ordsets:subtract(gb_trees:keys(Ftab0),
+ ordsets:from_list(Faces)),
+ dissolve_1(Faces, Complement, We);
+ false ->
+ Complement = ordsets:subtract(gb_trees:keys(Ftab0),
+ gb_sets:to_list(Faces)),
+ dissolve_1(Faces, Complement, We)
+ end.
+
+faces([], _, We) -> We;
+faces(Faces,Complement,We) ->
+ case gb_sets:is_empty(Faces) of
+ true -> We;
+ false -> dissolve_1(Faces, Complement,We)
+ end.
+
+dissolve_1(Faces, Complement, We0) ->
+ We1 = optimistic_dissolve(Faces,Complement,We0#we{vc=undefined}),
+ NewFaces = wings_we:new_items_as_ordset(face, We0, We1),
+ We2 = wings_face:delete_bad_faces(NewFaces, We1),
+ We = wings_we:rebuild(We2),
+ case wings_we:is_consistent(We) of
+ true ->
+ We;
+ false ->
+ io:format("Dissolving would cause an inconsistent object structure.")
+ end.
+
+%% complement([Face], We) -> We'
+%% Dissolve all faces BUT the given faces. Also invalidate the
+%% mirror face if it existed and was dissolved.
+complement(Fs0, #we{fs=Ftab0}=We0) when is_list(Fs0) ->
+ Fs = ordsets:subtract(gb_trees:keys(Ftab0), ordsets:from_list(Fs0)),
+ case faces(Fs, Fs0, We0) of
+ #we{mirror=none}=We -> We;
+ #we{mirror=Face,fs=Ftab}=We ->
+ case gb_trees:is_defined(Face, Ftab) of
+ false -> We;
+ true -> We#we{mirror=none}
+ end
+ end;
+complement(Fs, We) -> complement(gb_sets:to_list(Fs), We).
+
+optimistic_dissolve(Faces0, Compl, We0) ->
+ %% Optimistically assume that we have a simple region without
+ %% any holes.
+ case outer_edge_loop(Faces0, We0) of
+ error ->
+ %% Assumption was wrong. We need to partition the selection
+ %% and dissolve each partition in turn.
+ Parts = wings_sel:face_regions(Faces0, We0),
+ complex_dissolve(Parts, We0);
+ [_|_]=Loop ->
+ %% Assumption was correct.
+ simple_dissolve(Faces0, Compl, Loop, We0)
+ end.
+
+%% simple_dissolve(Faces, Loop, We0) -> We
+%% Dissolve a region of faces with no holes and no
+%% repeated vertices in the outer edge loop.
+
+simple_dissolve(Faces0, Compl, Loop, We0) ->
+ Faces = to_gb_set(Faces0),
+ OldFace = gb_sets:smallest(Faces),
+ Mat = wings_facemat:face(OldFace, We0),
+ We1 = fix_materials(Faces, Compl, We0),
+ #we{es=Etab0,fs=Ftab0,he=Htab0} = We1,
+ {Ftab1,Etab1,Htab} = simple_del(Faces, Ftab0, Etab0, Htab0, We1),
+ {NewFace,We2} = wings_we:new_id(We1),
+ Ftab = gb_trees:insert(NewFace, hd(Loop), Ftab1),
+ Last = lists:last(Loop),
+ Etab = update_outer([Last|Loop], Loop, NewFace, Ftab, Etab1),
+ We = We2#we{es=Etab,fs=Ftab,he=Htab},
+ wings_facemat:assign(Mat, [NewFace], We).
+
+fix_materials(Del,Keep,We) ->
+ case gb_sets:size(Del) < length(Keep) of
+ true ->
+ wings_facemat:delete_faces(Del,We);
+ false ->
+ wings_facemat:keep_faces(Keep,We)
+ end.
+
+to_gb_set(List) when is_list(List) ->
+ gb_sets:from_list(List);
+to_gb_set(S) -> S.
+
+%% Delete faces and inner edges for a simple region.
+simple_del(Faces, Ftab0, Etab0, Htab0, We) ->
+ case {gb_trees:size(Ftab0),gb_sets:size(Faces)} of
+ {AllSz,FaceSz} when AllSz < 2*FaceSz ->
+ %% At least half of the faces are selected.
+ %% It is faster to find the edges for the
+ %% unselected faces.
+ UnselFaces = ordsets:subtract(gb_trees:keys(Ftab0),
+ gb_sets:to_list(Faces)),
+
+ UnselSet = sofs:from_external(UnselFaces, [face]),
+ Ftab1 = sofs:from_external(gb_trees:to_list(Ftab0),
+ [{face,edge}]),
+ Ftab2 = sofs:restriction(Ftab1, UnselSet),
+ Ftab = gb_trees:from_orddict(sofs:to_external(Ftab2)),
+
+ Keep0 = wings_face:to_edges(UnselFaces, We),
+ Keep = sofs:set(Keep0, [edge]),
+ Etab1 = sofs:from_external(gb_trees:to_list(Etab0),
+ [{edge,info}]),
+ Etab2 = sofs:restriction(Etab1, Keep),
+ Etab = gb_trees:from_orddict(sofs:to_external(Etab2)),
+
+ Htab = simple_del_hard(Htab0, sofs:to_external(Keep), undefined),
+ {Ftab,Etab,Htab};
+ {_,_} ->
+ Ftab = lists:foldl(fun(Face, Ft) ->
+ gb_trees:delete(Face, Ft)
+ end, Ftab0, gb_sets:to_list(Faces)),
+ Inner = wings_face:inner_edges(Faces, We),
+ Etab = lists:foldl(fun(Edge, Et) ->
+ gb_trees:delete(Edge, Et)
+ end, Etab0, Inner),
+ Htab = simple_del_hard(Htab0, undefined, Inner),
+ {Ftab,Etab,Htab}
+ end.
+
+simple_del_hard(Htab, Keep, Remove) ->
+ case gb_sets:is_empty(Htab) of
+ true -> Htab;
+ false -> simple_del_hard_1(Htab, Keep, Remove)
+ end.
+
+simple_del_hard_1(Htab, Keep, undefined) ->
+ gb_sets:intersection(Htab, gb_sets:from_ordset(Keep));
+simple_del_hard_1(Htab, undefined, Remove) ->
+ gb_sets:difference(Htab, gb_sets:from_ordset(Remove)).
+
+%% complex([Partition], We0) -> We0
+%% The general dissolve.
+
+complex_dissolve([Faces|T], We0) ->
+ Face = gb_sets:smallest(Faces),
+ Mat = wings_facemat:face(Face, We0),
+ We1 = wings_facemat:delete_faces(Faces, We0),
+ Parts = outer_edge_partition(Faces, We1),
+ We = do_dissolve(Faces, Parts, Mat, We0, We1),
+ complex_dissolve(T, We);
+complex_dissolve([], We) -> We.
+
+do_dissolve(Faces, Ess, Mat, WeOrig, We0) ->
+ We1 = do_dissolve_faces(Faces, We0),
+ Inner = wings_face:inner_edges(Faces, WeOrig),
+ We2 = delete_inner(Inner, We1),
+ #we{he=Htab0} = We = do_dissolve_1(Ess, Mat, We2),
+ Htab = gb_sets:difference(Htab0, gb_sets:from_list(Inner)),
+ We#we{he=Htab}.
+
+do_dissolve_1([EdgeList|Ess], Mat, #we{es=Etab0,fs=Ftab0}=We0) ->
+ {Face,We1} = wings_we:new_id(We0),
+ Ftab = gb_trees:insert(Face, hd(EdgeList), Ftab0),
+ Last = lists:last(EdgeList),
+ Etab = update_outer([Last|EdgeList], EdgeList, Face, Ftab, Etab0),
+ We2 = We1#we{es=Etab,fs=Ftab},
+ We = wings_facemat:assign(Mat, [Face], We2),
+ do_dissolve_1(Ess, Mat, We);
+do_dissolve_1([], _Mat, We) -> We.
+
+do_dissolve_faces(Faces, #we{fs=Ftab0}=We) ->
+ Ftab = lists:foldl(fun(Face, Ft) ->
+ gb_trees:delete(Face, Ft)
+ end, Ftab0, gb_sets:to_list(Faces)),
+ We#we{fs=Ftab}.
+
+delete_inner(Inner, #we{es=Etab0}=We) ->
+ Etab = lists:foldl(fun(Edge, Et) ->
+ gb_trees:delete(Edge, Et)
+ end, Etab0, Inner),
+ We#we{es=Etab}.
+
+update_outer([Pred|[Edge|Succ]=T], More, Face, Ftab, Etab0) ->
+ #edge{rf=Rf} = R0 = gb_trees:get(Edge, Etab0),
+ Rec = case gb_trees:is_defined(Rf, Ftab) of
+ true ->
+ ?ASSERT(false == gb_trees:is_defined(R0#edge.lf, Ftab)),
+ LS = succ(Succ, More),
+ R0#edge{lf=Face,ltpr=Pred,ltsu=LS};
+ false ->
+ ?ASSERT(true == gb_trees:is_defined(R0#edge.lf, Ftab)),
+ RS = succ(Succ, More),
+ R0#edge{rf=Face,rtpr=Pred,rtsu=RS}
+ end,
+ Etab = gb_trees:update(Edge, Rec, Etab0),
+ update_outer(T, More, Face, Ftab, Etab);
+update_outer([_], _More, _Face, _Ftab, Etab) -> Etab.
+
+succ([Succ|_], _More) -> Succ;
+succ([], [Succ|_]) -> Succ.
+
+%% outer_edge_loop(FaceSet,WingedEdge) -> [Edge] | error.
+%% Partition the outer edges of the FaceSet into a single closed loop.
+%% Return 'error' if the faces in FaceSet does not form a
+%% simple region without holes.
+%%
+%% Equvivalent to
+%% case outer_edge_partition(FaceSet,WingedEdge) of
+%% [Loop] -> Loop;
+%% [_|_] -> error
+%% end.
+%% but faster.
+
+outer_edge_loop(Faces, We) ->
+ case lists:sort(collect_outer_edges(Faces, We)) of
+ [] -> error;
+ [{Key,Val}|Es0] ->
+ case any_duplicates(Es0, Key) of
+ false ->
+ Es = gb_trees:from_orddict(Es0),
+ N = gb_trees:size(Es),
+ outer_edge_loop_1(Val, Es, Key, N, []);
+ true -> error
+ end
+ end.
+
+outer_edge_loop_1({Edge,V}, _, V, 0, Acc) ->
+ %% This edge completes the loop, and we have used all possible edges.
+ [Edge|Acc];
+outer_edge_loop_1({_,V}, _, V, _N, _) ->
+ %% Loop is complete, but we haven't used all edges.
+ error;
+outer_edge_loop_1({_,_}, _, _, 0, _) ->
+ %% We have used all possible edges, but somehow the loop
+ %% is not complete. I can't see how this is possible.
+ erlang:error(internal_error);
+outer_edge_loop_1({Edge,Vb}, Es, EndV, N, Acc0) ->
+ Acc = [Edge|Acc0],
+ outer_edge_loop_1(gb_trees:get(Vb, Es), Es, EndV, N-1, Acc).
+
+any_duplicates([{V,_}|_], V) -> true;
+any_duplicates([_], _) -> false;
+any_duplicates([{V,_}|Es], _) -> any_duplicates(Es, V).
+
+%% outer_edge_partition(FaceSet, WingedEdge) -> [[Edge]].
+%% Partition the outer edges of the FaceSet. Each partion
+%% of edges form a closed loop with no repeated vertices.
+%% Outer edges are edges that have one face in FaceSet
+%% and one outside.
+%% It is assumed that FaceSet consists of one region returned by
+%% wings_sel:face_regions/2.
+
+outer_edge_partition(Faces, We) ->
+ F0 = collect_outer_edges(Faces, We),
+ F = gb_trees:from_orddict(wings_util:rel2fam(F0)),
+ partition_edges(F, []).
+
+collect_outer_edges(Faces, We) when is_list(Faces) ->
+ collect_outer_edges_1(Faces, gb_sets:from_list(Faces), We);
+collect_outer_edges(Faces, We) ->
+ collect_outer_edges_1(gb_sets:to_list(Faces), Faces, We).
+
+collect_outer_edges_1(Fs0, Faces0, #we{fs=Ftab}=We) ->
+ case {gb_trees:size(Ftab),gb_sets:size(Faces0)} of
+ {AllSz,FaceSz} when AllSz < 2*FaceSz ->
+ Fs = ordsets:subtract(gb_trees:keys(Ftab), Fs0),
+ Faces = gb_sets:from_ordset(Fs),
+ Coll = collect_outer_edges_a(Faces),
+ wings_face:fold_faces(Coll, [], Fs, We);
+ {_,_} ->
+ Coll = collect_outer_edges_b(Faces0),
+ wings_face:fold_faces(Coll, [], Fs0, We)
+ end.
+
+collect_outer_edges_a(Faces) ->
+ fun(Face, _, Edge, #edge{ve=V,vs=OtherV,lf=Face,rf=Other}, Acc) ->
+ case gb_sets:is_member(Other, Faces) of
+ false -> [{V,{Edge,OtherV}}|Acc];
+ true -> Acc
+ end;
+ (Face, _, Edge, #edge{ve=OtherV,vs=V,rf=Face,lf=Other}, Acc) ->
+ case gb_sets:is_member(Other, Faces) of
+ false -> [{V,{Edge,OtherV}}|Acc];
+ true -> Acc
+ end
+ end.
+
+collect_outer_edges_b(Faces) ->
+ fun(Face, _, Edge, #edge{vs=V,ve=OtherV,lf=Face,rf=Other}, Acc) ->
+ case gb_sets:is_member(Other, Faces) of
+ false -> [{V,{Edge,OtherV}}|Acc];
+ true -> Acc
+ end;
+ (Face, _, Edge, #edge{vs=OtherV,ve=V,rf=Face,lf=Other}, Acc) ->
+ case gb_sets:is_member(Other, Faces) of
+ false -> [{V,{Edge,OtherV}}|Acc];
+ true -> Acc
+ end
+ end.
+
+partition_edges(Es0, Acc) ->
+ case gb_trees:is_empty(Es0) of
+ true -> Acc;
+ false ->
+ {Key,Val,Es1} = gb_trees:take_smallest(Es0),
+ {Cycle,Es} = part_collect_cycle(Key, Val, Es1, []),
+ partition_edges(Es, [Cycle|Acc])
+ end.
+
+%% part_collect_cycle(Vertex, VertexInfo, EdgeInfo, Acc0) ->
+%% none | {[Edge],EdgeInfo}
+%% Collect the cycle starting with Vertex.
+%%
+%% Note: This function can only return 'none' when called
+%% recursively.
+
+part_collect_cycle(_, repeated, _, _) ->
+ %% Repeated vertex - we are not allowed to go this way.
+ %% Can only happen if we were called recursively because
+ %% a fork was encountered.
+ none;
+part_collect_cycle(_Va, [{Edge,Vb}], Es0, Acc0) ->
+ %% Basic case. Only one way to go.
+ Acc = [Edge|Acc0],
+ case gb_trees:lookup(Vb, Es0) of
+ none ->
+ {Acc,Es0};
+ {value,Val} ->
+ Es = gb_trees:delete(Vb, Es0),
+ part_collect_cycle(Vb, Val, Es, Acc)
+ end;
+part_collect_cycle(Va, [Val|More], Es0, []) ->
+ %% No cycle started yet and we have multiple choice of
+ %% edges out from this vertex. It doesn't matter which
+ %% edge we follow, so we'll follow the first one.
+ {Cycle,Es} = part_collect_cycle(Va, [Val], Es0, []),
+ {Cycle,gb_trees:insert(Va, More, Es)};
+part_collect_cycle(Va, Edges, Es0, Acc) ->
+ %% We have a partially collected cycle and we have a
+ %% fork (multiple choice of edges). Here we must choose
+ %% an edge that closes the cycle without passing Va
+ %% again (because repeated vertices are not allowed).
+ Es = gb_trees:insert(Va, repeated, Es0),
+ part_fork(Va, Edges, Es, Acc, []).
+
+part_fork(Va, [Val|More], Es0, Acc, Tried) ->
+ %% Try to complete the cycle by following this edge.
+ case part_collect_cycle(Va, [Val], Es0, Acc) of
+ none ->
+ %% Failure - try the next edge.
+ part_fork(Va, More, Es0, Acc, [Val|Tried]);
+ {Cycle,Es} ->
+ %% Found a cycle. Update the vertex information
+ %% with all edges remaining.
+ {Cycle,gb_trees:update(Va, lists:reverse(Tried, More), Es)}
+ end;
+part_fork(_, [], _, _, _) ->
+ %% None of edges were possible. Can only happen if this function
+ %% was called recursively (i.e. if we hit another fork while
+ %% processing a fork).
+ none.
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_edge.erl b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_edge.erl
index 3483acb711..3483acb711 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_edge.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_edge.erl
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_edge_cmd.erl b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_edge_cmd.erl
new file mode 100644
index 0000000000..91fa5b2a39
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_edge_cmd.erl
@@ -0,0 +1,90 @@
+%%
+%% wings_edge.erl --
+%%
+%% This module contains most edge command and edge utility functions.
+%%
+
+-module(wings_edge_cmd).
+
+-export([loop_cut/1]).
+
+-include("wings.hrl").
+
+%%%
+%%% The Loop Cut command.
+%%%
+
+loop_cut(St0) ->
+ {Sel,St} = wings_sel:fold(fun loop_cut/3, {[],St0}, St0),
+ wings_sel:set(body, Sel, St).
+
+loop_cut(Edges, #we{name=Name,id=Id,fs=Ftab}=We0, {Sel,St0}) ->
+ AdjFaces = wings_face:from_edges(Edges, We0),
+ case loop_cut_partition(AdjFaces, Edges, We0, []) of
+ [_] ->
+ io:format("Edge loop doesn't divide ~p into two parts.", [Name]);
+ Parts0 ->
+ %% We arbitrarily decide that the largest part of the object
+ %% will be left unselected and will keep the name of the object.
+
+ Parts1 = [{gb_trees:size(P),P} || P <- Parts0],
+ Parts2 = lists:reverse(lists:sort(Parts1)),
+ [_|Parts] = [gb_sets:to_list(P) || {_,P} <- Parts2],
+
+ %% Also, this first part will also contain any sub-object
+ %% that was not reachable from any of the edges. Therefore,
+ %% we calculate the first part as the complement of the union
+ %% of all other parts.
+
+ FirstComplement = ordsets:union(Parts),
+ First = ordsets:subtract(gb_trees:keys(Ftab), FirstComplement),
+
+ We = wings_dissolve:complement(First, We0),
+ Shs = St0#st.shapes,
+ St = St0#st{shapes=gb_trees:update(Id, We, Shs)},
+ loop_cut_make_copies(Parts, We0, Sel, St)
+ end.
+
+loop_cut_make_copies([P|Parts], We0, Sel0, #st{onext=Id}=St0) ->
+ Sel = [{Id,gb_sets:singleton(0)}|Sel0],
+ We = wings_dissolve:complement(P, We0),
+ St = wings_shape:insert(We, cut, St0),
+ loop_cut_make_copies(Parts, We0, Sel, St);
+loop_cut_make_copies([], _, Sel, St) -> {Sel,St}.
+
+loop_cut_partition(Faces0, Edges, We, Acc) ->
+ case gb_sets:is_empty(Faces0) of
+ true -> Acc;
+ false ->
+ {AFace,Faces1} = gb_sets:take_smallest(Faces0),
+ Reachable = collect_faces(AFace, Edges, We),
+ Faces = gb_sets:difference(Faces1, Reachable),
+ loop_cut_partition(Faces, Edges, We, [Reachable|Acc])
+ end.
+
+collect_faces(Face, Edges, We) ->
+ collect_faces(gb_sets:singleton(Face), We, Edges, gb_sets:empty()).
+
+collect_faces(Work0, We, Edges, Acc0) ->
+ case gb_sets:is_empty(Work0) of
+ true -> Acc0;
+ false ->
+ {Face,Work1} = gb_sets:take_smallest(Work0),
+ Acc = gb_sets:insert(Face, Acc0),
+ Work = collect_maybe_add(Work1, Face, Edges, We, Acc),
+ collect_faces(Work, We, Edges, Acc)
+ end.
+
+collect_maybe_add(Work, Face, Edges, We, Res) ->
+ wings_face:fold(
+ fun(_, Edge, Rec, A) ->
+ case gb_sets:is_member(Edge, Edges) of
+ true -> A;
+ false ->
+ Of = wings_face:other(Face, Rec),
+ case gb_sets:is_member(Of, Res) of
+ true -> A;
+ false -> gb_sets:add(Of, A)
+ end
+ end
+ end, Work, Face, We).
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_face.erl b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_face.erl
index 487c05aa58..487c05aa58 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_face.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_face.erl
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_facemat.erl b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_facemat.erl
new file mode 100644
index 0000000000..a3fa5e3508
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_facemat.erl
@@ -0,0 +1,299 @@
+%%
+%% wings_facemat.erl --
+%%
+%% This module keeps tracks of the mapping from a face number
+%% to its material name.
+%%
+%% Copyright (c) 2001-2005 Bjorn Gustavsson
+%%
+%% See the file "license.terms" for information on usage and redistribution
+%% of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+%%
+%% $Id: wings_facemat.erl,v 1.1 2009/01/25 18:55:33 kostis Exp $
+%%
+%%
+%%
+
+-module(wings_facemat).
+-export([all/1,face/2,used_materials/1,mat_faces/2,
+ assign/2,assign/3,
+ delete_face/2,delete_faces/2,keep_faces/2,
+ hide_faces/1,show_faces/1,
+ renumber/2,gc/1,merge/1]).
+
+-include("wings.hrl").
+-import(lists, [keysearch/3,reverse/1,reverse/2,sort/1]).
+
+%%%
+%%% API functions for retrieving information.
+%%%
+
+%% all(We) -> [{Face,MaterialName}]
+%% Return materials for all faces as an ordered list.
+all(#we{mat=M}=We) when is_atom(M) ->
+ Vis = visible_faces(We),
+ make_tab(Vis, M);
+all(#we{mat=L}) when is_list(L) ->
+ remove_invisible(L).
+
+%% face(Face, We) -> MaterialName
+%% Return the material for the face Face.
+face(_, #we{mat=M}) when is_atom(M) -> M;
+face(Face, #we{mat=Tab}) ->
+ {value,{_,Mat}} = keysearch(Face, 1, Tab),
+ Mat.
+
+%% used_materials(We) -> [MaterialName]
+%% Return an ordered list of all materials used in the We.
+used_materials(#we{mat=M}) when is_atom(M) -> [M];
+used_materials(#we{mat=L}) when is_list(L) ->
+ used_materials_1(L, []).
+
+%% mat_faces([{Face,Info}], We) -> [{Mat,[{Face,Info}]}]
+%% Group face tab into groups based on material.
+%% Used for displaying objects.
+mat_faces(Ftab, #we{mat=AtomMat}) when is_atom(AtomMat) ->
+ [{AtomMat,Ftab}];
+mat_faces(Ftab, #we{mat=MatTab}) ->
+ mat_faces_1(Ftab, remove_invisible(MatTab), []).
+
+%%%
+%%% API functions for updating material name mapping.
+%%%
+
+%% assign([{Face,MaterialName}], We) -> We'
+%% Assign materials.
+assign([], We) -> We;
+assign([{F,M}|_]=FaceMs, We) when is_atom(M), is_integer(F) ->
+ Tab = ordsets:from_list(FaceMs),
+ assign_face_ms(Tab, We).
+
+%% assign(MaterialName, Faces, We) -> We'
+%% Assign MaterialName to all faces Faces.
+assign(Mat, _, #we{mat=Mat}=We) when is_atom(Mat) -> We;
+assign(Mat, Fs, We) when is_atom(Mat), is_list(Fs) ->
+ assign_1(Mat, Fs, We);
+assign(Mat, Fs, We) when is_atom(Mat) ->
+ assign_1(Mat, gb_sets:to_list(Fs), We).
+
+%% delete_face(Face, We) -> We'
+%% Delete the material name mapping for the face Face.
+delete_face(_, #we{mat=AtomMat}=We) when is_atom(AtomMat) -> We;
+delete_face(Face, #we{mat=MatTab0}=We) ->
+ MatTab = orddict:erase(Face, MatTab0),
+ We#we{mat=MatTab}.
+
+%% delete_face(Faces, We) -> We'
+%% Delete the material name mapping for all faces Faces.
+delete_faces(_, #we{mat=AtomMat}=We) when is_atom(AtomMat) -> We;
+delete_faces(Faces0, #we{mat=MatTab0}=We) when is_list(Faces0) ->
+ Faces = sofs:from_external(Faces0, [face]),
+ MatTab1 = sofs:from_external(MatTab0, [{face,mat}]),
+ MatTab2 = sofs:drestriction(MatTab1, Faces),
+ MatTab = sofs:to_external(MatTab2),
+ We#we{mat=MatTab};
+delete_faces(Faces, We) ->
+ delete_faces(gb_sets:to_list(Faces), We).
+
+%% keep_faces(Faces, We) -> We'
+%% Delete all the other material names mapping for all faces other Faces.
+keep_faces(_, #we{mat=AtomMat}=We) when is_atom(AtomMat) -> We;
+keep_faces([Face], We) ->
+ Mat = face(Face,We),
+ We#we{mat=[{Face,Mat}]};
+keep_faces(Faces0, #we{mat=MatTab0}=We) when is_list(Faces0) ->
+ Faces = sofs:from_external(Faces0, [face]),
+ MatTab1 = sofs:from_external(MatTab0, [{face,mat}]),
+ MatTab2 = sofs:restriction(MatTab1, Faces),
+ MatTab = sofs:to_external(MatTab2),
+ We#we{mat=MatTab};
+keep_faces(Faces, We) ->
+ keep_faces(gb_sets:to_list(Faces), We).
+
+%% hide_faces(We) -> We'
+%% Update the material name mapping in the We to reflect
+%% the newly hidden faces in the face tab.
+hide_faces(#we{mat=M}=We) when is_atom(M) -> We;
+hide_faces(#we{mat=L0,fs=Ftab}=We) ->
+ L = hide_faces_1(L0, Ftab, []),
+ We#we{mat=L}.
+
+%% show_faces(We) -> We'
+%% Update the material name mapping in the We to reflect
+%% that all faces are again visible.
+show_faces(#we{mat=M}=We) when is_atom(M) -> We;
+show_faces(#we{mat=L0}=We) ->
+ L = show_faces_1(L0, []),
+ We#we{mat=L}.
+
+%% renumber(MaterialMapping, FaceOldToNew) -> MaterialMapping.
+%% Renumber face number in material name mapping.
+renumber(Mat, _) when is_atom(Mat) -> Mat;
+renumber(L, Fmap) when is_list(L) -> renumber_1(L, Fmap, []).
+
+%% gc(We) -> We'
+%% Garbage collect the material mapping information, removing
+%% the mapping for any face no longer present in the face table.
+gc(#we{mat=Mat}=We) when is_atom(Mat) -> We;
+gc(#we{mat=Tab0,fs=Ftab}=We) ->
+ Fs = sofs:from_external(gb_trees:keys(Ftab), [face]),
+ Tab1 = sofs:from_external(Tab0, [{face,material}]),
+ Tab2 = sofs:restriction(Tab1, Fs),
+ Tab = sofs:to_external(Tab2),
+ We#we{mat=compress(Tab)}.
+
+%% merge([We]) -> [{Face,MaterialName}] | MaterialName.
+%% Merge materials for several objects.
+merge([#we{mat=M}|Wes]=L) when is_atom(M) ->
+ case merge_all_same(Wes, M) of
+ true -> M;
+ false -> merge_1(L, [])
+ end;
+merge(L) -> merge_1(L, []).
+
+merge_1([#we{mat=M,es=Etab}|T], Acc) when is_atom(M) ->
+ FsM = merge_2(gb_trees:values(Etab), M, []),
+ merge_1(T, [FsM|Acc]);
+merge_1([#we{mat=FsMs}|T], Acc) ->
+ merge_1(T, [FsMs|Acc]);
+merge_1([], Acc) -> lists:merge(Acc).
+
+merge_2([#edge{lf=Lf,rf=Rf}|T], M, Acc) ->
+ merge_2(T, M, [{Lf,M},{Rf,M}|Acc]);
+merge_2([], _, Acc) -> ordsets:from_list(Acc).
+
+merge_all_same([#we{mat=M}|Wes], M) -> merge_all_same(Wes, M);
+merge_all_same([_|_], _) -> false;
+merge_all_same([], _) -> true.
+
+%%%
+%%% Local functions.
+%%%
+
+assign_1(Mat, Fs, #we{fs=Ftab}=We) ->
+ case length(Fs) =:= gb_trees:size(Ftab) of
+ true -> We#we{mat=Mat};
+ false -> assign_2(Mat, Fs, We)
+ end.
+
+assign_2(Mat, Fs0, #we{fs=Ftab,mat=Mat0}=We) when is_atom(Mat0) ->
+ Fs = ordsets:from_list(Fs0),
+ OtherFaces = ordsets:subtract(gb_trees:keys(Ftab), Fs),
+ Tab0 = make_tab(OtherFaces, Mat0),
+ Tab1 = make_tab(Fs, Mat),
+ Tab = lists:merge(Tab0, Tab1),
+ We#we{mat=Tab};
+assign_2(Mat, Fs0, #we{mat=Tab0}=We) when is_list(Tab0) ->
+ Fs = ordsets:from_list(Fs0),
+ Tab1 = make_tab(Fs, Mat),
+ Tab = mat_merge(Tab1, Tab0, []),
+ We#we{mat=Tab}.
+
+assign_face_ms(Tab, #we{fs=Ftab}=We) ->
+ case length(Tab) =:= gb_trees:size(Ftab) of
+ true -> We#we{mat=compress(Tab)};
+ false -> assign_face_ms_1(Tab, We)
+ end.
+
+assign_face_ms_1(Tab1, #we{fs=Ftab,mat=Mat0}=We) when is_atom(Mat0) ->
+ Tab0 = make_tab(gb_trees:keys(Ftab), Mat0),
+ Tab = mat_merge(Tab1, Tab0, []),
+ We#we{mat=Tab};
+assign_face_ms_1(Tab1, #we{mat=Tab0}=We) when is_list(Tab0) ->
+ Tab = mat_merge(Tab1, Tab0, []),
+ We#we{mat=Tab}.
+
+mat_merge([{Fn,_}|_]=Fns, [{Fo,_}=Fold|Fos], Acc) when Fo < Fn ->
+ mat_merge(Fns, Fos, [Fold|Acc]);
+mat_merge([{Fn,_}=Fnew|Fns], [{Fo,_}|_]=Fos, Acc) when Fo > Fn ->
+ mat_merge(Fns, Fos, [Fnew|Acc]);
+mat_merge([Fnew|Fns], [_|Fos], Acc) -> % Equality
+ mat_merge(Fns, Fos, [Fnew|Acc]);
+mat_merge([], Fos, Acc) ->
+ rev_compress(Acc, Fos);
+mat_merge(Fns, [], Acc) ->
+ rev_compress(Acc, Fns).
+
+make_tab(Fs, M) ->
+ make_tab_1(Fs, M, []).
+
+make_tab_1([F|Fs], M, Acc) ->
+ make_tab_1(Fs, M, [{F,M}|Acc]);
+make_tab_1([], _, Acc) -> reverse(Acc).
+
+
+visible_faces(#we{fs=Ftab}) ->
+ visible_faces_1(gb_trees:keys(Ftab)).
+
+visible_faces_1([F|Fs]) when F < 0 ->
+ visible_faces_1(Fs);
+visible_faces_1(Fs) -> Fs.
+
+remove_invisible([{F,_}|Fs]) when F < 0 ->
+ remove_invisible(Fs);
+remove_invisible(Fs) -> Fs.
+
+hide_faces_1([{F,_}=P|Fms], Ftab, Acc) when F < 0 ->
+ hide_faces_1(Fms, Ftab, [P|Acc]);
+hide_faces_1([{F,M}=P|Fms], Ftab, Acc) ->
+ case gb_trees:is_defined(F, Ftab) of
+ false -> hide_faces_1(Fms, Ftab, [{-F-1,M}|Acc]);
+ true -> hide_faces_1(Fms, Ftab, [P|Acc])
+ end;
+hide_faces_1([], _, Acc) -> sort(Acc).
+
+show_faces_1([{F,M}|Fms], Acc) when F < 0 ->
+ show_faces_1(Fms, [{-F-1,M}|Acc]);
+show_faces_1(Fs, Acc) -> sort(Acc++Fs).
+
+renumber_1([{F,M}|T], Fmap, Acc) ->
+ renumber_1(T, Fmap, [{gb_trees:get(F, Fmap),M}|Acc]);
+renumber_1([], _, Acc) -> sort(Acc).
+
+%% rev_compress([{Face,Mat}], [{Face,Mat}]) -> [{Face,Mat}] | Mat.
+%% Reverse just like lists:reverse/2, but if all materials
+%% turns out to be just the same, return that material.
+rev_compress(L, Acc) ->
+ case same_mat(Acc) of
+ [] -> reverse(L, Acc);
+ M -> rev_compress_1(L, M, Acc)
+ end.
+
+rev_compress_1([{_,M}=E|T], M, Acc) ->
+ %% Same material.
+ rev_compress_1(T, M, [E|Acc]);
+rev_compress_1([_|_]=L, _, Acc) ->
+ %% Another material. Finish by using reverse/2.
+ reverse(L, Acc);
+rev_compress_1([], M, _) ->
+ %% All materials turned out to be the same.
+ M.
+
+%% compress(MaterialTab) -> [{Face,Mat}] | Mat.
+%% Compress a face mapping if possible.
+compress(M) when is_atom(M) -> M;
+compress(L) when is_list(L) ->
+ case same_mat(L) of
+ [] -> L;
+ M -> M
+ end.
+
+same_mat([]) -> [];
+same_mat([{_,M}|T]) -> same_mat_1(T, M).
+
+same_mat_1([{_,M}|T], M) -> same_mat_1(T, M);
+same_mat_1([], M) -> M;
+same_mat_1(_, _) -> [].
+
+used_materials_1([{_,M}|T], [M|_]=Acc) ->
+ used_materials_1(T, Acc);
+used_materials_1([{_,M}|T], Acc) ->
+ used_materials_1(T, [M|Acc]);
+used_materials_1([], Acc) ->
+ ordsets:from_list(Acc).
+
+mat_faces_1([{F1,_}|_]=Fs, [{F2,_}|Ms], Acc) when F2 < F1 ->
+ mat_faces_1(Fs, Ms, Acc);
+mat_faces_1([{F,Info}|Fs], [{F,Mat}|Ms], Acc) ->
+ mat_faces_1(Fs, Ms, [{Mat,{F,Info}}|Acc]);
+mat_faces_1([], _, Acc) -> wings_util:rel2fam(Acc).
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_intl.hrl b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_intl.hrl
index ebcb560f27..ebcb560f27 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_intl.hrl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_intl.hrl
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_io.erl b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_io.erl
index 39002c675d..39002c675d 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_io.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_io.erl
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_sel.erl b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_sel.erl
index eef797027e..eef797027e 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_sel.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_sel.erl
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_shape.erl b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_shape.erl
index 0df8ca68eb..0df8ca68eb 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_shape.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_shape.erl
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_util.erl b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_util.erl
new file mode 100644
index 0000000000..8f0da1f5dc
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_util.erl
@@ -0,0 +1,38 @@
+%%
+%% wings_util.erl --
+%%
+%% Various utility functions that not obviously fit somewhere else.
+%%
+
+-module(wings_util).
+
+-export([gb_trees_smallest_key/1, gb_trees_largest_key/1,
+ gb_trees_map/2, rel2fam/1]).
+
+-include("wings.hrl").
+
+rel2fam(Rel) ->
+ sofs:to_external(sofs:relation_to_family(sofs:relation(Rel))).
+
+%% a definition that does not violate the opaqueness of gb_tree()
+gb_trees_smallest_key(Tree) ->
+ {Key, _V} = gb_trees:smallest(Tree),
+ Key.
+
+%% a definition that violates the opaqueness of gb_tree()
+gb_trees_largest_key({_, Tree}) ->
+ largest_key1(Tree).
+
+largest_key1({Key, _Value, _Smaller, nil}) ->
+ Key;
+largest_key1({_Key, _Value, _Smaller, Larger}) ->
+ largest_key1(Larger).
+
+gb_trees_map(F, {Size,Tree}) ->
+ {Size,gb_trees_map_1(F, Tree)}.
+
+gb_trees_map_1(_, nil) -> nil;
+gb_trees_map_1(F, {K,V,Smaller,Larger}) ->
+ {K,F(K, V),
+ gb_trees_map_1(F, Smaller),
+ gb_trees_map_1(F, Larger)}.
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_we.erl b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_we.erl
new file mode 100644
index 0000000000..6a93363445
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_we.erl
@@ -0,0 +1,250 @@
+%%
+%% wings_we.erl --
+%%
+%% This module contains functions to build and manipulate
+%% we records (winged-edged records, the central data structure
+%% in Wings 3D).
+
+-module(wings_we).
+
+-export([rebuild/1, is_consistent/1, is_face_consistent/2, new_id/1,
+ new_items_as_ordset/3, validate_mirror/1, visible/1, visible_edges/1]).
+
+-include("wings.hrl").
+
+%%%
+%%% API.
+%%%
+
+validate_mirror(#we{mirror=none}=We) -> We;
+validate_mirror(#we{fs=Ftab,mirror=Face}=We) ->
+ case gb_trees:is_defined(Face, Ftab) of
+ false -> We#we{mirror=none};
+ true -> We
+ end.
+
+%% rebuild(We) -> We'
+%% Rebuild any missing 'vc' and 'fs' tables. If there are
+%% fewer elements in the 'vc' table than in the 'vp' table,
+%% remove redundant entries in the 'vp' table. Updated id
+%% bounds.
+rebuild(#we{vc=undefined,fs=undefined,es=Etab0}=We0) ->
+ Etab = gb_trees:to_list(Etab0),
+ Ftab = rebuild_ftab(Etab),
+ VctList = rebuild_vct(Etab),
+ We = We0#we{vc=gb_trees:from_orddict(VctList),fs=Ftab},
+ rebuild_1(VctList, We);
+rebuild(#we{vc=undefined,es=Etab}=We) ->
+ VctList = rebuild_vct(gb_trees:to_list(Etab), []),
+ rebuild_1(VctList, We#we{vc=gb_trees:from_orddict(VctList)});
+rebuild(#we{fs=undefined,es=Etab}=We) ->
+ Ftab = rebuild_ftab(gb_trees:to_list(Etab)),
+ rebuild(We#we{fs=Ftab});
+rebuild(We) -> update_id_bounds(We).
+
+%%% Utilities for allocating IDs.
+
+new_id(#we{next_id=Id}=We) ->
+ {Id,We#we{next_id=Id+1}}.
+
+%%% Returns sets of newly created items.
+
+new_items_as_ordset(vertex, #we{next_id=Wid}, #we{next_id=NewWid,vp=Tab}) ->
+ new_items_as_ordset_1(Tab, Wid, NewWid);
+new_items_as_ordset(edge, #we{next_id=Wid}, #we{next_id=NewWid,es=Tab}) ->
+ new_items_as_ordset_1(Tab, Wid, NewWid);
+new_items_as_ordset(face, #we{next_id=Wid}, #we{next_id=NewWid,fs=Tab}) ->
+ new_items_as_ordset_1(Tab, Wid, NewWid).
+
+any_hidden(#we{fs=Ftab}) ->
+ not gb_trees:is_empty(Ftab) andalso
+ wings_util:gb_trees_smallest_key(Ftab) < 0.
+
+%%%
+%%% Local functions.
+%%%
+
+rebuild_1(VctList, #we{vc=Vct,vp=Vtab0}=We) ->
+ case {gb_trees:size(Vct),gb_trees:size(Vtab0)} of
+ {Same,Same} -> rebuild(We);
+ {Sz1,Sz2} when Sz1 < Sz2 ->
+ Vtab = vertex_gc_1(VctList, gb_trees:to_list(Vtab0), []),
+ rebuild(We#we{vp=Vtab})
+ end.
+
+rebuild_vct(Es) ->
+ rebuild_vct(Es, []).
+
+rebuild_vct([{Edge,#edge{vs=Va,ve=Vb}}|Es], Acc0) ->
+ Acc = rebuild_maybe_add(Va, Vb, Edge, Acc0),
+ rebuild_vct(Es, Acc);
+rebuild_vct([], VtoE) ->
+ build_incident_tab(VtoE).
+
+rebuild_ftab(Es) ->
+ rebuild_ftab_1(Es, []).
+
+rebuild_ftab_1([{Edge,#edge{lf=Lf,rf=Rf}}|Es], Acc0) ->
+ Acc = rebuild_maybe_add(Lf, Rf, Edge, Acc0),
+ rebuild_ftab_1(Es, Acc);
+rebuild_ftab_1([], FtoE) ->
+ gb_trees:from_orddict(build_incident_tab(FtoE)).
+
+rebuild_maybe_add(Ka, Kb, E, [_,{Ka,_}|_]=Acc) ->
+ [{Kb,E}|Acc];
+rebuild_maybe_add(Ka, Kb, E, [_,{Kb,_}|_]=Acc) ->
+ [{Ka,E}|Acc];
+rebuild_maybe_add(Ka, Kb, E, [{Ka,_}|_]=Acc) ->
+ [{Kb,E}|Acc];
+rebuild_maybe_add(Ka, Kb, E, [{Kb,_}|_]=Acc) ->
+ [{Ka,E}|Acc];
+rebuild_maybe_add(Ka, Kb, E, Acc) ->
+ [{Ka,E},{Kb,E}|Acc].
+
+vertex_gc_1([{V,_}|Vct], [{V,_}=Vtx|Vpos], Acc) ->
+ vertex_gc_1(Vct, Vpos, [Vtx|Acc]);
+vertex_gc_1([_|_]=Vct, [_|Vpos], Acc) ->
+ vertex_gc_1(Vct, Vpos, Acc);
+vertex_gc_1([], _, Acc) ->
+ gb_trees:from_orddict(lists:reverse(Acc)).
+
+%%%
+%%% Handling of hidden faces.
+%%%
+
+visible(#we{mirror=none,fs=Ftab}) ->
+ visible_2(gb_trees:keys(Ftab));
+visible(#we{mirror=Face,fs=Ftab}) ->
+ visible_2(gb_trees:keys(gb_trees:delete(Face, Ftab))).
+
+visible_2([F|Fs]) when F < 0 -> visible_2(Fs);
+visible_2(Fs) -> Fs.
+
+visible_edges(#we{es=Etab,mirror=Face}=We) ->
+ case any_hidden(We) of
+ false -> gb_trees:keys(Etab);
+ true -> visible_es_1(gb_trees:to_list(Etab), Face, [])
+ end.
+
+visible_es_1([{E,#edge{lf=Lf,rf=Rf}}|Es], Face, Acc) ->
+ if
+ Lf < 0 ->
+ %% Left face hidden.
+ if
+ Rf < 0; Rf =:= Face ->
+ %% Both faces invisible (in some way).
+ visible_es_1(Es, Face, Acc);
+ true ->
+ %% Right face is visible.
+ visible_es_1(Es, Face, [E|Acc])
+ end;
+ Lf =:= Face, Rf < 0 ->
+ %% Left face mirror, right face hidden.
+ visible_es_1(Es, Face, Acc);
+ true ->
+ %% At least one face visible.
+ visible_es_1(Es, Face, [E|Acc])
+ end;
+visible_es_1([], _, Acc) -> ordsets:from_list(Acc).
+
+update_id_bounds(#we{vp=Vtab,es=Etab,fs=Ftab}=We) ->
+ case gb_trees:is_empty(Etab) of
+ true -> We#we{next_id=0};
+ false ->
+ LastId = lists:max([wings_util:gb_trees_largest_key(Vtab),
+ wings_util:gb_trees_largest_key(Etab),
+ wings_util:gb_trees_largest_key(Ftab)]),
+ We#we{next_id=LastId+1}
+ end.
+
+%% build_incident_tab([{Elem,Edge}]) -> [{Elem,Edge}]
+%% Elem = Face or Vertex
+%% Build the table of incident edges for either faces or vertices.
+%% Returns an ordered list where each Elem is unique.
+
+build_incident_tab(ElemToEdgeRel) ->
+ T = ets:new(?MODULE, [ordered_set]),
+ ets:insert(T, ElemToEdgeRel),
+ R = ets:tab2list(T),
+ ets:delete(T),
+ R.
+
+%%%
+%%% Calculate normals.
+%%%
+
+new_items_as_ordset_1(Tab, Wid, NewWid) when NewWid-Wid < 32 ->
+ new_items_as_ordset_2(Wid, NewWid, Tab, []);
+new_items_as_ordset_1(Tab, Wid, _NewWid) ->
+ [Item || Item <- gb_trees:keys(Tab), Item >= Wid].
+
+new_items_as_ordset_2(Wid, NewWid, Tab, Acc) when Wid < NewWid ->
+ case gb_trees:is_defined(Wid, Tab) of
+ true -> new_items_as_ordset_2(Wid+1, NewWid, Tab, [Wid|Acc]);
+ false -> new_items_as_ordset_2(Wid+1, NewWid, Tab, Acc)
+ end;
+new_items_as_ordset_2(_Wid, _NewWid, _Tab, Acc) -> lists:reverse(Acc).
+
+%%%
+%%% Test the consistency of a #we{}.
+%%%
+
+is_consistent(#we{}=We) ->
+ try
+ validate_vertex_tab(We),
+ validate_faces(We)
+ catch error:_ -> false
+ end.
+
+is_face_consistent(Face, #we{fs=Ftab,es=Etab}) ->
+ Edge = gb_trees:get(Face, Ftab),
+ try validate_face(Face, Edge, Etab)
+ catch error:_ -> false
+ end.
+
+validate_faces(#we{fs=Ftab,es=Etab}) ->
+ validate_faces_1(gb_trees:to_list(Ftab), Etab).
+
+validate_faces_1([{Face,Edge}|Fs], Etab) ->
+ validate_face(Face, Edge, Etab),
+ validate_faces_1(Fs, Etab);
+validate_faces_1([], _) -> true.
+
+validate_face(Face, Edge, Etab) ->
+ Ccw = walk_face_ccw(Edge, Etab, Face, Edge, []),
+ Edge = walk_face_cw(Edge, Etab, Face, Ccw),
+ [V|Vs] = lists:sort(Ccw),
+ validate_face_vertices(Vs, V).
+
+validate_face_vertices([V|_], V) ->
+ erlang:error(repeated_vertex);
+validate_face_vertices([_], _) ->
+ true;
+validate_face_vertices([V|Vs], _) ->
+ validate_face_vertices(Vs, V).
+
+walk_face_ccw(LastEdge, _, _, LastEdge, [_|_]=Acc) -> Acc;
+walk_face_ccw(Edge, Etab, Face, LastEdge, Acc) ->
+ case gb_trees:get(Edge, Etab) of
+ #edge{ve=V,lf=Face,ltpr=Next} ->
+ walk_face_ccw(Next, Etab, Face, LastEdge, [V|Acc]);
+ #edge{vs=V,rf=Face,rtpr=Next} ->
+ walk_face_ccw(Next, Etab, Face, LastEdge, [V|Acc])
+ end.
+
+walk_face_cw(Edge, _, _, []) -> Edge;
+walk_face_cw(Edge, Etab, Face, [V|Vs]) ->
+ case gb_trees:get(Edge, Etab) of
+ #edge{vs=V,lf=Face,ltsu=Next} ->
+ walk_face_cw(Next, Etab, Face, Vs);
+ #edge{ve=V,rf=Face,rtsu=Next} ->
+ walk_face_cw(Next, Etab, Face, Vs)
+ end.
+
+validate_vertex_tab(#we{es=Etab,vc=Vct}) ->
+ lists:foreach(fun({V,Edge}) ->
+ case gb_trees:get(Edge, Etab) of
+ #edge{vs=V} -> ok;
+ #edge{ve=V} -> ok
+ end
+ end, gb_trees:to_list(Vct)).
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis1.erl b/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis1.erl
new file mode 100644
index 0000000000..e09ccb80df
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis1.erl
@@ -0,0 +1,14 @@
+-module(zoltan_kis1).
+
+-export([f/0, gen/0]).
+
+-opaque id() :: string().
+
+-spec f() -> integer().
+
+%% BIF and Unification(t_unify) issue
+f() -> erlang:length(gen()).
+
+-spec gen() -> id().
+
+gen() -> "Dummy".
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis2.erl b/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis2.erl
new file mode 100644
index 0000000000..38c6051c58
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis2.erl
@@ -0,0 +1,14 @@
+-module(zoltan_kis2).
+
+-export([get/2]).
+
+-opaque data() :: gb_tree().
+
+-spec get(term(), data()) -> term().
+
+get(Key, Data) ->
+ %% Should unopaque data for remote calls
+ case gb_trees:lookup(Key, Data) of
+ 'none' -> 'undefined';
+ {'value', Val} -> Val
+ end.
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis3.erl b/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis3.erl
new file mode 100644
index 0000000000..b62b9de576
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis3.erl
@@ -0,0 +1,14 @@
+-module(zoltan_kis3).
+
+-export([f/0, gen/0]).
+
+-opaque id() :: string().
+
+-spec f() -> char().
+
+%% List pattern matching issue
+f() -> [H|_T] = gen(), H.
+
+-spec gen() -> id().
+
+gen() -> "Dummy".
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis4.erl b/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis4.erl
new file mode 100644
index 0000000000..026d6f0c77
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis4.erl
@@ -0,0 +1,13 @@
+-module(zoltan_kis4).
+
+-export([f/0, gen/0]).
+
+-export_type([id/0]).
+
+-opaque id() :: string().
+
+-spec f() -> id().
+f() -> "Dummy" = gen(). %% Matching issue
+
+-spec gen() -> id().
+gen() -> "Dummy".
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis5.erl b/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis5.erl
new file mode 100644
index 0000000000..ecf14c91c1
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis5.erl
@@ -0,0 +1,14 @@
+-module(zoltan_kis5).
+
+-export([f/0, gen/0]).
+
+-opaque id() :: string().
+
+-spec f() -> boolean().
+
+%% Equality test issue
+f() -> "Dummy" == gen().
+
+-spec gen() -> id().
+
+gen() -> "Dummy".
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis6.erl b/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis6.erl
index 6f0779d7d1..6f0779d7d1 100644
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis6.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis6.erl
diff --git a/lib/dialyzer/test/opaque_tests_SUITE.erl b/lib/dialyzer/test/opaque_tests_SUITE.erl
deleted file mode 100644
index 6b90e7a646..0000000000
--- a/lib/dialyzer/test/opaque_tests_SUITE.erl
+++ /dev/null
@@ -1,184 +0,0 @@
-%% ATTENTION!
-%% This is an automatically generated file. Do not edit.
-%% Use './remake' script to refresh it if needed.
-%% All Dialyzer options should be defined in dialyzer_options
-%% file.
-
--module(opaque_tests_SUITE).
-
--include("ct.hrl").
--include("dialyzer_test_constants.hrl").
-
--export([suite/0, init_per_suite/0, init_per_suite/1,
- end_per_suite/1, all/0]).
--export([opaque_tests_SUITE_consistency/1, array/1, crash/1, dict/1,
- ets/1, gb_sets/1, inf_loop1/1, int/1, mixed_opaque/1,
- my_digraph/1, my_queue/1, opaque/1, queue/1, rec/1, timer/1,
- union/1, wings/1, zoltan_kis1/1, zoltan_kis2/1, zoltan_kis3/1,
- zoltan_kis4/1, zoltan_kis5/1, zoltan_kis6/1]).
-
-suite() ->
- [{timetrap, {minutes, 1}}].
-
-init_per_suite() ->
- [{timetrap, ?plt_timeout}].
-init_per_suite(Config) ->
- OutDir = ?config(priv_dir, Config),
- case dialyzer_common:check_plt(OutDir) of
- fail -> {skip, "Plt creation/check failed."};
- ok -> [{dialyzer_options, [{warnings,[no_unused,no_return]}]}|Config]
- end.
-
-end_per_suite(_Config) ->
- ok.
-
-all() ->
- [opaque_tests_SUITE_consistency,array,crash,dict,ets,gb_sets,inf_loop1,int,
- mixed_opaque,my_digraph,my_queue,opaque,queue,rec,timer,union,wings,
- zoltan_kis1,zoltan_kis2,zoltan_kis3,zoltan_kis4,zoltan_kis5,zoltan_kis6].
-
-dialyze(Config, TestCase) ->
- Opts = ?config(dialyzer_options, Config),
- Dir = ?config(data_dir, Config),
- OutDir = ?config(priv_dir, Config),
- dialyzer_common:check(TestCase, Opts, Dir, OutDir).
-
-opaque_tests_SUITE_consistency(Config) ->
- Dir = ?config(data_dir, Config),
- case dialyzer_common:new_tests(Dir, all()) of
- [] -> ok;
- New -> ct:fail({missing_tests,New})
- end.
-
-array(Config) ->
- case dialyze(Config, array) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-crash(Config) ->
- case dialyze(Config, crash) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-dict(Config) ->
- case dialyze(Config, dict) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets(Config) ->
- case dialyze(Config, ets) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-gb_sets(Config) ->
- case dialyze(Config, gb_sets) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-inf_loop1(Config) ->
- case dialyze(Config, inf_loop1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-int(Config) ->
- case dialyze(Config, int) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-mixed_opaque(Config) ->
- case dialyze(Config, mixed_opaque) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-my_digraph(Config) ->
- case dialyze(Config, my_digraph) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-my_queue(Config) ->
- case dialyze(Config, my_queue) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-opaque(Config) ->
- case dialyze(Config, opaque) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-queue(Config) ->
- case dialyze(Config, queue) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-rec(Config) ->
- case dialyze(Config, rec) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-timer(Config) ->
- case dialyze(Config, timer) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-union(Config) ->
- case dialyze(Config, union) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-wings(Config) ->
- case dialyze(Config, wings) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-zoltan_kis1(Config) ->
- case dialyze(Config, zoltan_kis1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-zoltan_kis2(Config) ->
- case dialyze(Config, zoltan_kis2) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-zoltan_kis3(Config) ->
- case dialyze(Config, zoltan_kis3) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-zoltan_kis4(Config) ->
- case dialyze(Config, zoltan_kis4) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-zoltan_kis5(Config) ->
- case dialyze(Config, zoltan_kis5) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-zoltan_kis6(Config) ->
- case dialyze(Config, zoltan_kis6) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/dict/dict_use.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/dict/dict_use.erl
deleted file mode 100644
index 2a632a910d..0000000000
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/dict/dict_use.erl
+++ /dev/null
@@ -1,83 +0,0 @@
--module(dict_use).
-
--export([ok1/0, ok2/0, ok3/0, ok4/0, ok5/0, ok6/0]).
--export([middle/0]).
--export([w1/0, w2/0, w3/0, w4/1, w5/0, w6/0, w7/0, w8/1, w9/0]).
-
--define(DICT, dict).
-
-%%---------------------------------------------------------------------
-%% Cases that are OK
-%%---------------------------------------------------------------------
-
-ok1() ->
- dict:new().
-
-ok2() ->
- case dict:new() of X -> X end.
-
-ok3() ->
- Dict1 = dict:new(),
- Dict2 = dict:new(),
- Dict1 =:= Dict2.
-
-ok4() ->
- dict:fetch(foo, dict:new()).
-
-ok5() -> % this is OK since some_mod:new/0 might be returning a dict()
- dict:fetch(foo, some_mod:new()).
-
-ok6() ->
- dict:store(42, elli, dict:new()).
-
-middle() ->
- {w1(), w2()}.
-
-%%---------------------------------------------------------------------
-%% Cases that are problematic w.r.t. opaqueness of types
-%%---------------------------------------------------------------------
-
-w1() ->
- gazonk = dict:new().
-
-w2() ->
- case dict:new() of
- [] -> nil;
- 42 -> weird
- end.
-
-w3() ->
- try dict:new() of
- [] -> nil;
- 42 -> weird
- catch
- _:_ -> exception
- end.
-
-w4(Dict) when is_list(Dict) ->
- Dict =:= dict:new();
-w4(Dict) when is_atom(Dict) ->
- Dict =/= dict:new().
-
-w5() ->
- case dict:new() of
- D when length(D) =/= 42 -> weird;
- D when is_atom(D) -> weirder;
- D when is_list(D) -> gazonk
- end.
-
-w6() ->
- is_list(dict:new()).
-
-w7() ->
- dict:fetch(foo, [1,2,3]).
-
-w8(Fun) ->
- dict:merge(Fun, 42, [1,2]).
-
-w9() ->
- dict:store(42, elli,
- {dict,0,16,16,8,80,48,
- {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
- {{[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]}}}).
-
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/ets/ets_use.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/ets/ets_use.erl
deleted file mode 100644
index 20be9803eb..0000000000
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/ets/ets_use.erl
+++ /dev/null
@@ -1,17 +0,0 @@
--module(ets_use).
--export([t1/0, t2/0]).
-
-t1() ->
- case n() of
- T when is_atom(T) -> atm;
- T when is_integer(T) -> int
- end.
-
-t2() ->
- case n() of
- T when is_integer(T) -> int;
- T when is_atom(T) -> atm
- end.
-
-n() -> ets:new(n, [named_table]).
-
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/my_digraph/my_digraph_adt.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/my_digraph/my_digraph_adt.erl
deleted file mode 100644
index 20c72aa6eb..0000000000
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/my_digraph/my_digraph_adt.erl
+++ /dev/null
@@ -1,51 +0,0 @@
--module(my_digraph_adt).
-
--export([new/0, new/1]).
-
--record(my_digraph, {vtab = notable,
- etab = notable,
- ntab = notable,
- cyclic = true :: boolean()}).
-
--opaque my_digraph() :: #my_digraph{}.
-
--type d_protection() :: 'private' | 'protected'.
--type d_cyclicity() :: 'acyclic' | 'cyclic'.
--type d_type() :: d_cyclicity() | d_protection().
-
--spec new() -> my_digraph().
-new() -> new([]).
-
--spec new([atom()]) -> my_digraph().
-new(Type) ->
- try check_type(Type, protected, []) of
- {Access, Ts} ->
- V = ets:new(vertices, [set, Access]),
- E = ets:new(edges, [set, Access]),
- N = ets:new(neighbours, [bag, Access]),
- ets:insert(N, [{'$vid', 0}, {'$eid', 0}]),
- set_type(Ts, #my_digraph{vtab=V, etab=E, ntab=N})
- catch
- throw:Error -> throw(Error)
- end.
-
--spec check_type([atom()], d_protection(), [{'cyclic', boolean()}]) ->
- {d_protection(), [{'cyclic', boolean()}]}.
-
-check_type([acyclic|Ts], A, L) ->
- check_type(Ts, A,[{cyclic,false} | L]);
-check_type([cyclic | Ts], A, L) ->
- check_type(Ts, A, [{cyclic,true} | L]);
-check_type([protected | Ts], _, L) ->
- check_type(Ts, protected, L);
-check_type([private | Ts], _, L) ->
- check_type(Ts, private, L);
-check_type([T | _], _, _) ->
- throw({error, {unknown_type, T}});
-check_type([], A, L) -> {A, L}.
-
--spec set_type([{'cyclic', boolean()}], my_digraph()) -> my_digraph().
-
-set_type([{cyclic,V} | Ks], G) ->
- set_type(Ks, G#my_digraph{cyclic = V});
-set_type([], G) -> G.
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/opaque/opaque_bug1.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/opaque/opaque_bug1.erl
deleted file mode 100644
index ff0b1d05ab..0000000000
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/opaque/opaque_bug1.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%%---------------------------------------------------------------------
-%% A test for which the analysis went into an infinite loop due to
-%% specialization using structured type instead of the opaque one.
-%%---------------------------------------------------------------------
-
--module(opaque_bug1).
-
--export([test/1]).
-
--record(c, {a::atom()}).
-
--opaque erl_type() :: 'any' | #c{}.
-
-test(#c{a=foo} = T) -> local(T).
-
-local(#c{a=foo}) -> any.
-
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/queue/queue_use.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/queue/queue_use.erl
deleted file mode 100644
index 5682f2281e..0000000000
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/queue/queue_use.erl
+++ /dev/null
@@ -1,66 +0,0 @@
--module(queue_use).
-
--export([ok1/0, ok2/0]).
--export([wrong1/0, wrong2/0, wrong3/0, wrong4/0, wrong5/0, wrong6/0, wrong7/0, wrong8/0]).
-
-ok1() ->
- queue:is_empty(queue:new()).
-
-ok2() ->
- Q0 = queue:new(),
- Q1 = queue:in(42, Q0),
- {{value, 42}, Q2} = queue:out(Q1),
- queue:is_empty(Q2).
-
-%%--------------------------------------------------
-
-wrong1() ->
- queue:is_empty({[],[]}).
-
-wrong2() ->
- Q0 = {[],[]},
- queue:in(42, Q0).
-
-wrong3() ->
- Q0 = queue:new(),
- Q1 = queue:in(42, Q0),
- {[42],Q2} = Q1,
- Q2.
-
-wrong4() ->
- Q0 = queue:new(),
- Q1 = queue:in(42, Q0),
- Q1 =:= {[42],[]}.
-
-wrong5() ->
- {F, _R} = queue:new(),
- F.
-
-wrong6() ->
- {{value, 42}, Q2} = queue:out({[42],[]}),
- Q2.
-
-%%--------------------------------------------------
-
--record(db, {p, q}).
-
-wrong7() ->
- add_unique(42, #db{p = [], q = queue:new()}).
-
-add_unique(E, DB) ->
- case is_in_queue(E, DB) of
- true -> DB;
- false -> DB#db{q = queue:in(E, DB#db.q)}
- end.
-
-is_in_queue(P, #db{q = {L1,L2}}) ->
- lists:member(P, L1) orelse lists:member(P, L2).
-
-%%--------------------------------------------------
-
-wrong8() ->
- tuple_queue({42, gazonk}).
-
-tuple_queue({F, Q}) ->
- queue:in(F, Q).
-
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings.hrl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings.hrl
deleted file mode 100644
index b9339a8eb1..0000000000
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings.hrl
+++ /dev/null
@@ -1,205 +0,0 @@
-%%
-%% wings.hrl --
-%%
-%% Global record definition and defines.
-%%
-%% Copyright (c) 2001-2005 Bjorn Gustavsson
-%%
-%% See the file "license.terms" for information on usage and redistribution
-%% of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-%%
-%% $Id: wings.hrl,v 1.1 2009/01/25 18:55:33 kostis Exp $
-%%
-
--include("wings_intl.hrl").
-
--ifdef(NEED_ESDL).
--include_lib("esdl/include/sdl.hrl").
--include_lib("esdl/include/sdl_events.hrl").
--include_lib("esdl/include/sdl_video.hrl").
--include_lib("esdl/include/sdl_keyboard.hrl").
--include_lib("esdl/include/sdl_mouse.hrl").
--include_lib("esdl/src/sdl_util.hrl").
--define(CTRL_BITS, ?KMOD_CTRL).
--define(ALT_BITS, ?KMOD_ALT).
--define(SHIFT_BITS, ?KMOD_SHIFT).
--define(META_BITS, ?KMOD_META).
--endif.
-
--define(WINGS_VERSION, ?wings_version).
-
--define(CHAR_HEIGHT, wings_text:height()).
--define(CHAR_WIDTH, wings_text:width()).
-
--define(LINE_HEIGHT, (?CHAR_HEIGHT+2)).
--define(GROUND_GRID_SIZE, 1).
--define(CAMERA_DIST, (8.0*?GROUND_GRID_SIZE)).
--define(NORMAL_LINEWIDTH, 1.0).
--define(DEGREE, 176). %Degree character.
-
--define(HIT_BUF_SIZE, (1024*1024)).
-
--define(PANE_COLOR, {0.52,0.52,0.52}).
--define(BEVEL_HIGHLIGHT, {0.9,0.9,0.9}).
--define(BEVEL_LOWLIGHT, {0.3,0.3,0.3}).
--define(BEVEL_HIGHLIGHT_MIX, 0.5).
--define(BEVEL_LOWLIGHT_MIX, 0.5).
-
--define(SLOW(Cmd), begin wings_io:hourglass(), Cmd end).
--define(TC(Cmd), wings_util:tc(fun() -> Cmd end, ?MODULE, ?LINE)).
-
--ifdef(DEBUG).
--define(ASSERT(E), case E of
- true -> ok;
- _ ->
- erlang:error({assertion_failed,?MODULE,?LINE})
- end).
--define(CHECK_ERROR(), wings_gl:check_error(?MODULE, ?LINE)).
--else.
--define(ASSERT(E),ok).
--define(CHECK_ERROR(), ok).
--endif.
-
-%% Display lists per object.
-%% Important: Plain integers and integers in lists will be assumed to
-%% be display lists. Arbitrary integers must be stored inside a tuple
-%% or record to not be interpreted as a display list.
--record(dlo,
- {work=none, %Workmode faces.
- smooth=none, %Smooth-shaded faces.
- edges=none, %Edges and wire-frame.
- vs=none, %Unselected vertices.
- hard=none, %Hard edges.
- sel=none, %Selected items.
- orig_sel=none, %Original selection.
- normals=none, %Normals.
- pick=none, %For picking.
- proxy_faces=none, %Smooth proxy faces.
- proxy_edges=none, %Smooth proxy edges.
-
- %% Miscellanous.
- hilite=none, %Hilite display list.
- mirror=none, %Virtual mirror data.
- ns=none, %Normals/positions per face.
-
- %% Source for display lists.
- src_we=none, %Source object.
- src_sel=none, %Source selection.
- orig_mode=none, %Original selection mode.
- split=none, %Split data.
- drag=none, %For dragging.
- transparent=false, %Object includes transparancy.
- proxy_data=none, %Data for smooth proxy.
- open=false, %Open (has hole).
-
- %% List of display lists known to be needed only based
- %% on display modes, not whether the lists themselves exist.
- %% Example: [work,edges]
- needed=[]
- }).
-
-%% Main state record containing all objects and other important state.
--record(st,
- {shapes, %All visible shapes
- selmode, %Selection mode:
- % vertex, edge, face, body
- sh=false, %Smart highlight active: true|false
- sel=[], %Current sel: [{Id,GbSet}]
- ssels=[], %Saved selections:
- % [{Name,Mode,GbSet}]
- temp_sel=none, %Selection only temporary?
-
- mat, %Defined materials (GbTree).
- pal=[], %Palette
- file, %Current filename.
- saved, %True if model has been saved.
- onext, %Next object id to use.
- bb=none, %Saved bounding box.
- edge_loop=none, %Previous edge loop.
- views={0,{}}, %{Current,TupleOfViews}
- pst=gb_trees:empty(), %Plugin State Info
- % gb_tree where key is plugin module
-
- %% Previous commands.
- repeatable, %Last repeatable command.
- ask_args, %Ask arguments.
- drag_args, %Drag arguments for command.
- def, %Default operations.
-
- %% Undo information.
- top, %Top of stack.
- bottom, %Bottom of stack.
- next_is_undo, %State of undo/redo toggle.
- undone %States that were undone.
- }).
-
-%% The Winged-Edge data structure.
-%% See http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/model/winged-e.html
--record(we,
- {id, %Shape id.
- perm=0, %Permissions:
- % 0 - Everything allowed.
- % 1 - Visible, can't select.
- % [] or {Mode,GbSet} -
- % Invisible, can't select.
- % The GbSet contains the
- % object's selection.
- name, %Name.
- es, %gb_tree containing edges
- fs, %gb_tree containing faces
- he, %gb_sets containing hard edges
- vc, %Connection info (=incident edge)
- % for vertices.
- vp, %Vertex positions.
- pst=gb_trees:empty(), %Plugin State Info,
- % gb_tree where key is plugin module
- mat=default, %Materials.
- next_id, %Next free ID for vertices,
- % edges, and faces.
- % (Needed because we never re-use
- % IDs.)
- mode, %'vertex'/'material'/'uv'
- mirror=none, %Mirror: none|Face
- light=none, %Light data: none|Light
- has_shape=true %true|false
- }).
-
--define(IS_VISIBLE(Perm), (Perm =< 1)).
--define(IS_NOT_VISIBLE(Perm), (Perm > 1)).
--define(IS_SELECTABLE(Perm), (Perm == 0)).
--define(IS_NOT_SELECTABLE(Perm), (Perm =/= 0)).
-
--define(IS_LIGHT(We), ((We#we.light =/= none) and (not We#we.has_shape))).
--define(IS_ANY_LIGHT(We), (We#we.light =/= none)).
--define(HAS_SHAPE(We), (We#we.has_shape)).
-%-define(IS_LIGHT(We), (We#we.light =/= none)).
-%-define(IS_NOT_LIGHT(We), (We#we.light =:= none)).
-
-%% Edge in a winged-edge shape.
--record(edge,
- {vs, %Start vertex for edge
- ve, %End vertex for edge
- a=none, %Color or UV coordinate.
- b=none, %Color or UV coordinate.
- lf, %Left face
- rf, %Right face
- ltpr, %Left traversal predecessor
- ltsu, %Left traversal successor
- rtpr, %Right traversal predecessor
- rtsu %Right traversal successor
- }).
-
-%% The current view/camera.
--record(view,
- {origin,
- distance, % From origo.
- azimuth,
- elevation,
- pan_x, %Panning in X direction.
- pan_y, %Panning in Y direction.
- along_axis=none, %Which axis viewed along.
- fov, %Field of view.
- hither, %Near clipping plane.
- yon %Far clipping plane.
- }).
-
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_dissolve.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_dissolve.erl
deleted file mode 100644
index d7af9bb1d3..0000000000
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_dissolve.erl
+++ /dev/null
@@ -1,375 +0,0 @@
-%%
-%% wings_dissolve.erl --
-%%
-%% This module implements dissolve of faces.
-%%
-
--module(wings_dissolve).
-
--export([faces/2, complement/2]).
-
--include("wings.hrl").
-
-%% faces([Face], We) -> We'
-%% Dissolve the given faces.
-faces([], We) -> We;
-faces(Faces, #we{fs=Ftab0}=We) ->
- case gb_sets:is_empty(Faces) of
- true -> We;
- false when is_list(Faces) ->
- Complement = ordsets:subtract(gb_trees:keys(Ftab0),
- ordsets:from_list(Faces)),
- dissolve_1(Faces, Complement, We);
- false ->
- Complement = ordsets:subtract(gb_trees:keys(Ftab0),
- gb_sets:to_list(Faces)),
- dissolve_1(Faces, Complement, We)
- end.
-
-faces([], _, We) -> We;
-faces(Faces,Complement,We) ->
- case gb_sets:is_empty(Faces) of
- true -> We;
- false -> dissolve_1(Faces, Complement,We)
- end.
-
-dissolve_1(Faces, Complement, We0) ->
- We1 = optimistic_dissolve(Faces,Complement,We0#we{vc=undefined}),
- NewFaces = wings_we:new_items_as_ordset(face, We0, We1),
- We2 = wings_face:delete_bad_faces(NewFaces, We1),
- We = wings_we:rebuild(We2),
- case wings_we:is_consistent(We) of
- true ->
- We;
- false ->
- io:format("Dissolving would cause an inconsistent object structure.")
- end.
-
-%% complement([Face], We) -> We'
-%% Dissolve all faces BUT the given faces. Also invalidate the
-%% mirror face if it existed and was dissolved.
-complement(Fs0, #we{fs=Ftab0}=We0) when is_list(Fs0) ->
- Fs = ordsets:subtract(gb_trees:keys(Ftab0), ordsets:from_list(Fs0)),
- case faces(Fs, Fs0, We0) of
- #we{mirror=none}=We -> We;
- #we{mirror=Face,fs=Ftab}=We ->
- case gb_trees:is_defined(Face, Ftab) of
- false -> We;
- true -> We#we{mirror=none}
- end
- end;
-complement(Fs, We) -> complement(gb_sets:to_list(Fs), We).
-
-optimistic_dissolve(Faces0, Compl, We0) ->
- %% Optimistically assume that we have a simple region without
- %% any holes.
- case outer_edge_loop(Faces0, We0) of
- error ->
- %% Assumption was wrong. We need to partition the selection
- %% and dissolve each partition in turn.
- Parts = wings_sel:face_regions(Faces0, We0),
- complex_dissolve(Parts, We0);
- [_|_]=Loop ->
- %% Assumption was correct.
- simple_dissolve(Faces0, Compl, Loop, We0)
- end.
-
-%% simple_dissolve(Faces, Loop, We0) -> We
-%% Dissolve a region of faces with no holes and no
-%% repeated vertices in the outer edge loop.
-
-simple_dissolve(Faces0, Compl, Loop, We0) ->
- Faces = to_gb_set(Faces0),
- OldFace = gb_sets:smallest(Faces),
- Mat = wings_facemat:face(OldFace, We0),
- We1 = fix_materials(Faces, Compl, We0),
- #we{es=Etab0,fs=Ftab0,he=Htab0} = We1,
- {Ftab1,Etab1,Htab} = simple_del(Faces, Ftab0, Etab0, Htab0, We1),
- {NewFace,We2} = wings_we:new_id(We1),
- Ftab = gb_trees:insert(NewFace, hd(Loop), Ftab1),
- Last = lists:last(Loop),
- Etab = update_outer([Last|Loop], Loop, NewFace, Ftab, Etab1),
- We = We2#we{es=Etab,fs=Ftab,he=Htab},
- wings_facemat:assign(Mat, [NewFace], We).
-
-fix_materials(Del,Keep,We) ->
- case gb_sets:size(Del) < length(Keep) of
- true ->
- wings_facemat:delete_faces(Del,We);
- false ->
- wings_facemat:keep_faces(Keep,We)
- end.
-
-to_gb_set(List) when is_list(List) ->
- gb_sets:from_list(List);
-to_gb_set(S) -> S.
-
-%% Delete faces and inner edges for a simple region.
-simple_del(Faces, Ftab0, Etab0, Htab0, We) ->
- case {gb_trees:size(Ftab0),gb_sets:size(Faces)} of
- {AllSz,FaceSz} when AllSz < 2*FaceSz ->
- %% At least half of the faces are selected.
- %% It is faster to find the edges for the
- %% unselected faces.
- UnselFaces = ordsets:subtract(gb_trees:keys(Ftab0),
- gb_sets:to_list(Faces)),
-
- UnselSet = sofs:from_external(UnselFaces, [face]),
- Ftab1 = sofs:from_external(gb_trees:to_list(Ftab0),
- [{face,edge}]),
- Ftab2 = sofs:restriction(Ftab1, UnselSet),
- Ftab = gb_trees:from_orddict(sofs:to_external(Ftab2)),
-
- Keep0 = wings_face:to_edges(UnselFaces, We),
- Keep = sofs:set(Keep0, [edge]),
- Etab1 = sofs:from_external(gb_trees:to_list(Etab0),
- [{edge,info}]),
- Etab2 = sofs:restriction(Etab1, Keep),
- Etab = gb_trees:from_orddict(sofs:to_external(Etab2)),
-
- Htab = simple_del_hard(Htab0, sofs:to_external(Keep), undefined),
- {Ftab,Etab,Htab};
- {_,_} ->
- Ftab = lists:foldl(fun(Face, Ft) ->
- gb_trees:delete(Face, Ft)
- end, Ftab0, gb_sets:to_list(Faces)),
- Inner = wings_face:inner_edges(Faces, We),
- Etab = lists:foldl(fun(Edge, Et) ->
- gb_trees:delete(Edge, Et)
- end, Etab0, Inner),
- Htab = simple_del_hard(Htab0, undefined, Inner),
- {Ftab,Etab,Htab}
- end.
-
-simple_del_hard(Htab, Keep, Remove) ->
- case gb_sets:is_empty(Htab) of
- true -> Htab;
- false -> simple_del_hard_1(Htab, Keep, Remove)
- end.
-
-simple_del_hard_1(Htab, Keep, undefined) ->
- gb_sets:intersection(Htab, gb_sets:from_ordset(Keep));
-simple_del_hard_1(Htab, undefined, Remove) ->
- gb_sets:difference(Htab, gb_sets:from_ordset(Remove)).
-
-%% complex([Partition], We0) -> We0
-%% The general dissolve.
-
-complex_dissolve([Faces|T], We0) ->
- Face = gb_sets:smallest(Faces),
- Mat = wings_facemat:face(Face, We0),
- We1 = wings_facemat:delete_faces(Faces, We0),
- Parts = outer_edge_partition(Faces, We1),
- We = do_dissolve(Faces, Parts, Mat, We0, We1),
- complex_dissolve(T, We);
-complex_dissolve([], We) -> We.
-
-do_dissolve(Faces, Ess, Mat, WeOrig, We0) ->
- We1 = do_dissolve_faces(Faces, We0),
- Inner = wings_face:inner_edges(Faces, WeOrig),
- We2 = delete_inner(Inner, We1),
- #we{he=Htab0} = We = do_dissolve_1(Ess, Mat, We2),
- Htab = gb_sets:difference(Htab0, gb_sets:from_list(Inner)),
- We#we{he=Htab}.
-
-do_dissolve_1([EdgeList|Ess], Mat, #we{es=Etab0,fs=Ftab0}=We0) ->
- {Face,We1} = wings_we:new_id(We0),
- Ftab = gb_trees:insert(Face, hd(EdgeList), Ftab0),
- Last = lists:last(EdgeList),
- Etab = update_outer([Last|EdgeList], EdgeList, Face, Ftab, Etab0),
- We2 = We1#we{es=Etab,fs=Ftab},
- We = wings_facemat:assign(Mat, [Face], We2),
- do_dissolve_1(Ess, Mat, We);
-do_dissolve_1([], _Mat, We) -> We.
-
-do_dissolve_faces(Faces, #we{fs=Ftab0}=We) ->
- Ftab = lists:foldl(fun(Face, Ft) ->
- gb_trees:delete(Face, Ft)
- end, Ftab0, gb_sets:to_list(Faces)),
- We#we{fs=Ftab}.
-
-delete_inner(Inner, #we{es=Etab0}=We) ->
- Etab = lists:foldl(fun(Edge, Et) ->
- gb_trees:delete(Edge, Et)
- end, Etab0, Inner),
- We#we{es=Etab}.
-
-update_outer([Pred|[Edge|Succ]=T], More, Face, Ftab, Etab0) ->
- #edge{rf=Rf} = R0 = gb_trees:get(Edge, Etab0),
- Rec = case gb_trees:is_defined(Rf, Ftab) of
- true ->
- ?ASSERT(false == gb_trees:is_defined(R0#edge.lf, Ftab)),
- LS = succ(Succ, More),
- R0#edge{lf=Face,ltpr=Pred,ltsu=LS};
- false ->
- ?ASSERT(true == gb_trees:is_defined(R0#edge.lf, Ftab)),
- RS = succ(Succ, More),
- R0#edge{rf=Face,rtpr=Pred,rtsu=RS}
- end,
- Etab = gb_trees:update(Edge, Rec, Etab0),
- update_outer(T, More, Face, Ftab, Etab);
-update_outer([_], _More, _Face, _Ftab, Etab) -> Etab.
-
-succ([Succ|_], _More) -> Succ;
-succ([], [Succ|_]) -> Succ.
-
-%% outer_edge_loop(FaceSet,WingedEdge) -> [Edge] | error.
-%% Partition the outer edges of the FaceSet into a single closed loop.
-%% Return 'error' if the faces in FaceSet does not form a
-%% simple region without holes.
-%%
-%% Equvivalent to
-%% case outer_edge_partition(FaceSet,WingedEdge) of
-%% [Loop] -> Loop;
-%% [_|_] -> error
-%% end.
-%% but faster.
-
-outer_edge_loop(Faces, We) ->
- case lists:sort(collect_outer_edges(Faces, We)) of
- [] -> error;
- [{Key,Val}|Es0] ->
- case any_duplicates(Es0, Key) of
- false ->
- Es = gb_trees:from_orddict(Es0),
- N = gb_trees:size(Es),
- outer_edge_loop_1(Val, Es, Key, N, []);
- true -> error
- end
- end.
-
-outer_edge_loop_1({Edge,V}, _, V, 0, Acc) ->
- %% This edge completes the loop, and we have used all possible edges.
- [Edge|Acc];
-outer_edge_loop_1({_,V}, _, V, _N, _) ->
- %% Loop is complete, but we haven't used all edges.
- error;
-outer_edge_loop_1({_,_}, _, _, 0, _) ->
- %% We have used all possible edges, but somehow the loop
- %% is not complete. I can't see how this is possible.
- erlang:error(internal_error);
-outer_edge_loop_1({Edge,Vb}, Es, EndV, N, Acc0) ->
- Acc = [Edge|Acc0],
- outer_edge_loop_1(gb_trees:get(Vb, Es), Es, EndV, N-1, Acc).
-
-any_duplicates([{V,_}|_], V) -> true;
-any_duplicates([_], _) -> false;
-any_duplicates([{V,_}|Es], _) -> any_duplicates(Es, V).
-
-%% outer_edge_partition(FaceSet, WingedEdge) -> [[Edge]].
-%% Partition the outer edges of the FaceSet. Each partion
-%% of edges form a closed loop with no repeated vertices.
-%% Outer edges are edges that have one face in FaceSet
-%% and one outside.
-%% It is assumed that FaceSet consists of one region returned by
-%% wings_sel:face_regions/2.
-
-outer_edge_partition(Faces, We) ->
- F0 = collect_outer_edges(Faces, We),
- F = gb_trees:from_orddict(wings_util:rel2fam(F0)),
- partition_edges(F, []).
-
-collect_outer_edges(Faces, We) when is_list(Faces) ->
- collect_outer_edges_1(Faces, gb_sets:from_list(Faces), We);
-collect_outer_edges(Faces, We) ->
- collect_outer_edges_1(gb_sets:to_list(Faces), Faces, We).
-
-collect_outer_edges_1(Fs0, Faces0, #we{fs=Ftab}=We) ->
- case {gb_trees:size(Ftab),gb_sets:size(Faces0)} of
- {AllSz,FaceSz} when AllSz < 2*FaceSz ->
- Fs = ordsets:subtract(gb_trees:keys(Ftab), Fs0),
- Faces = gb_sets:from_ordset(Fs),
- Coll = collect_outer_edges_a(Faces),
- wings_face:fold_faces(Coll, [], Fs, We);
- {_,_} ->
- Coll = collect_outer_edges_b(Faces0),
- wings_face:fold_faces(Coll, [], Fs0, We)
- end.
-
-collect_outer_edges_a(Faces) ->
- fun(Face, _, Edge, #edge{ve=V,vs=OtherV,lf=Face,rf=Other}, Acc) ->
- case gb_sets:is_member(Other, Faces) of
- false -> [{V,{Edge,OtherV}}|Acc];
- true -> Acc
- end;
- (Face, _, Edge, #edge{ve=OtherV,vs=V,rf=Face,lf=Other}, Acc) ->
- case gb_sets:is_member(Other, Faces) of
- false -> [{V,{Edge,OtherV}}|Acc];
- true -> Acc
- end
- end.
-
-collect_outer_edges_b(Faces) ->
- fun(Face, _, Edge, #edge{vs=V,ve=OtherV,lf=Face,rf=Other}, Acc) ->
- case gb_sets:is_member(Other, Faces) of
- false -> [{V,{Edge,OtherV}}|Acc];
- true -> Acc
- end;
- (Face, _, Edge, #edge{vs=OtherV,ve=V,rf=Face,lf=Other}, Acc) ->
- case gb_sets:is_member(Other, Faces) of
- false -> [{V,{Edge,OtherV}}|Acc];
- true -> Acc
- end
- end.
-
-partition_edges(Es0, Acc) ->
- case gb_trees:is_empty(Es0) of
- true -> Acc;
- false ->
- {Key,Val,Es1} = gb_trees:take_smallest(Es0),
- {Cycle,Es} = part_collect_cycle(Key, Val, Es1, []),
- partition_edges(Es, [Cycle|Acc])
- end.
-
-%% part_collect_cycle(Vertex, VertexInfo, EdgeInfo, Acc0) ->
-%% none | {[Edge],EdgeInfo}
-%% Collect the cycle starting with Vertex.
-%%
-%% Note: This function can only return 'none' when called
-%% recursively.
-
-part_collect_cycle(_, repeated, _, _) ->
- %% Repeated vertex - we are not allowed to go this way.
- %% Can only happen if we were called recursively because
- %% a fork was encountered.
- none;
-part_collect_cycle(_Va, [{Edge,Vb}], Es0, Acc0) ->
- %% Basic case. Only one way to go.
- Acc = [Edge|Acc0],
- case gb_trees:lookup(Vb, Es0) of
- none ->
- {Acc,Es0};
- {value,Val} ->
- Es = gb_trees:delete(Vb, Es0),
- part_collect_cycle(Vb, Val, Es, Acc)
- end;
-part_collect_cycle(Va, [Val|More], Es0, []) ->
- %% No cycle started yet and we have multiple choice of
- %% edges out from this vertex. It doesn't matter which
- %% edge we follow, so we'll follow the first one.
- {Cycle,Es} = part_collect_cycle(Va, [Val], Es0, []),
- {Cycle,gb_trees:insert(Va, More, Es)};
-part_collect_cycle(Va, Edges, Es0, Acc) ->
- %% We have a partially collected cycle and we have a
- %% fork (multiple choice of edges). Here we must choose
- %% an edge that closes the cycle without passing Va
- %% again (because repeated vertices are not allowed).
- Es = gb_trees:insert(Va, repeated, Es0),
- part_fork(Va, Edges, Es, Acc, []).
-
-part_fork(Va, [Val|More], Es0, Acc, Tried) ->
- %% Try to complete the cycle by following this edge.
- case part_collect_cycle(Va, [Val], Es0, Acc) of
- none ->
- %% Failure - try the next edge.
- part_fork(Va, More, Es0, Acc, [Val|Tried]);
- {Cycle,Es} ->
- %% Found a cycle. Update the vertex information
- %% with all edges remaining.
- {Cycle,gb_trees:update(Va, lists:reverse(Tried, More), Es)}
- end;
-part_fork(_, [], _, _, _) ->
- %% None of edges were possible. Can only happen if this function
- %% was called recursively (i.e. if we hit another fork while
- %% processing a fork).
- none.
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_edge_cmd.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_edge_cmd.erl
deleted file mode 100644
index e478ec245b..0000000000
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_edge_cmd.erl
+++ /dev/null
@@ -1,91 +0,0 @@
-%%
-%% wings_edge.erl --
-%%
-%% This module contains most edge command and edge utility functions.
-%%
-
--module(wings_edge_cmd).
-
--export([loop_cut/1]).
-
--include("wings.hrl").
-
-%%%
-%%% The Loop Cut command.
-%%%
-
-loop_cut(St0) ->
- {Sel,St} = wings_sel:fold(fun loop_cut/3, {[],St0}, St0),
- wings_sel:set(body, Sel, St).
-
-loop_cut(Edges, #we{name=Name,id=Id,fs=Ftab}=We0, {Sel,St0}) ->
- AdjFaces = wings_face:from_edges(Edges, We0),
- case loop_cut_partition(AdjFaces, Edges, We0, []) of
- [_] ->
- io:format("Edge loop doesn't divide ~p into two parts.", [Name]);
- Parts0 ->
- %% We arbitrarily decide that the largest part of the object
- %% will be left unselected and will keep the name of the object.
-
- Parts1 = [{gb_trees:size(P),P} || P <- Parts0],
- Parts2 = lists:reverse(lists:sort(Parts1)),
- [_|Parts] = [gb_sets:to_list(P) || {_,P} <- Parts2],
-
- %% Also, this first part will also contain any sub-object
- %% that was not reachable from any of the edges. Therefore,
- %% we calculate the first part as the complement of the union
- %% of all other parts.
-
- FirstComplement = ordsets:union(Parts),
- First = ordsets:subtract(gb_trees:keys(Ftab), FirstComplement),
-
- We = wings_dissolve:complement(First, We0),
- Shs = St0#st.shapes,
- St = St0#st{shapes=gb_trees:update(Id, We, Shs)},
- loop_cut_make_copies(Parts, We0, Sel, St)
- end.
-
-loop_cut_make_copies([P|Parts], We0, Sel0, #st{onext=Id}=St0) ->
- Sel = [{Id,gb_sets:singleton(0)}|Sel0],
- We = wings_dissolve:complement(P, We0),
- St = wings_shape:insert(We, cut, St0),
- loop_cut_make_copies(Parts, We0, Sel, St);
-loop_cut_make_copies([], _, Sel, St) -> {Sel,St}.
-
-loop_cut_partition(Faces0, Edges, We, Acc) ->
- case gb_sets:is_empty(Faces0) of
- true -> Acc;
- false ->
- {AFace,Faces1} = gb_sets:take_smallest(Faces0),
- Reachable = collect_faces(AFace, Edges, We),
- Faces = gb_sets:difference(Faces1, Reachable),
- loop_cut_partition(Faces, Edges, We, [Reachable|Acc])
- end.
-
-collect_faces(Face, Edges, We) ->
- collect_faces(gb_sets:singleton(Face), We, Edges, gb_sets:empty()).
-
-collect_faces(Work0, We, Edges, Acc0) ->
- case gb_sets:is_empty(Work0) of
- true -> Acc0;
- false ->
- {Face,Work1} = gb_sets:take_smallest(Work0),
- Acc = gb_sets:insert(Face, Acc0),
- Work = collect_maybe_add(Work1, Face, Edges, We, Acc),
- collect_faces(Work, We, Edges, Acc)
- end.
-
-collect_maybe_add(Work, Face, Edges, We, Res) ->
- wings_face:fold(
- fun(_, Edge, Rec, A) ->
- case gb_sets:is_member(Edge, Edges) of
- true -> A;
- false ->
- Of = wings_face:other(Face, Rec),
- case gb_sets:is_member(Of, Res) of
- true -> A;
- false -> gb_sets:add(Of, A)
- end
- end
- end, Work, Face, We).
-
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_facemat.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_facemat.erl
deleted file mode 100644
index 6e018e49b5..0000000000
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_facemat.erl
+++ /dev/null
@@ -1,299 +0,0 @@
-%%
-%% wings_facemat.erl --
-%%
-%% This module keeps tracks of the mapping from a face number
-%% to its material name.
-%%
-%% Copyright (c) 2001-2005 Bjorn Gustavsson
-%%
-%% See the file "license.terms" for information on usage and redistribution
-%% of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-%%
-%% $Id: wings_facemat.erl,v 1.1 2009/01/25 18:55:33 kostis Exp $
-%%
-%%
-%%
-
--module(wings_facemat).
--export([all/1,face/2,used_materials/1,mat_faces/2,
- assign/2,assign/3,
- delete_face/2,delete_faces/2,keep_faces/2,
- hide_faces/1,show_faces/1,
- renumber/2,gc/1,merge/1]).
-
--include("wings.hrl").
--import(lists, [keysearch/3,reverse/1,reverse/2,sort/1]).
-
-%%%
-%%% API functions for retrieving information.
-%%%
-
-%% all(We) -> [{Face,MaterialName}]
-%% Return materials for all faces as an ordered list.
-all(#we{mat=M}=We) when is_atom(M) ->
- Vis = visible_faces(We),
- make_tab(Vis, M);
-all(#we{mat=L}) when is_list(L) ->
- remove_invisible(L).
-
-%% face(Face, We) -> MaterialName
-%% Return the material for the face Face.
-face(_, #we{mat=M}) when is_atom(M) -> M;
-face(Face, #we{mat=Tab}) ->
- {value,{_,Mat}} = keysearch(Face, 1, Tab),
- Mat.
-
-%% used_materials(We) -> [MaterialName]
-%% Return an ordered list of all materials used in the We.
-used_materials(#we{mat=M}) when is_atom(M) -> [M];
-used_materials(#we{mat=L}) when is_list(L) ->
- used_materials_1(L, []).
-
-%% mat_faces([{Face,Info}], We) -> [{Mat,[{Face,Info}]}]
-%% Group face tab into groups based on material.
-%% Used for displaying objects.
-mat_faces(Ftab, #we{mat=AtomMat}) when is_atom(AtomMat) ->
- [{AtomMat,Ftab}];
-mat_faces(Ftab, #we{mat=MatTab}) ->
- mat_faces_1(Ftab, remove_invisible(MatTab), []).
-
-%%%
-%%% API functions for updating material name mapping.
-%%%
-
-%% assign([{Face,MaterialName}], We) -> We'
-%% Assign materials.
-assign([], We) -> We;
-assign([{F,M}|_]=FaceMs, We) when is_atom(M), is_integer(F) ->
- Tab = ordsets:from_list(FaceMs),
- assign_face_ms(Tab, We).
-
-%% assign(MaterialName, Faces, We) -> We'
-%% Assign MaterialName to all faces Faces.
-assign(Mat, _, #we{mat=Mat}=We) when is_atom(Mat) -> We;
-assign(Mat, Fs, We) when is_atom(Mat), is_list(Fs) ->
- assign_1(Mat, Fs, We);
-assign(Mat, Fs, We) when is_atom(Mat) ->
- assign_1(Mat, gb_sets:to_list(Fs), We).
-
-%% delete_face(Face, We) -> We'
-%% Delete the material name mapping for the face Face.
-delete_face(_, #we{mat=AtomMat}=We) when is_atom(AtomMat) -> We;
-delete_face(Face, #we{mat=MatTab0}=We) ->
- MatTab = orddict:erase(Face, MatTab0),
- We#we{mat=MatTab}.
-
-%% delete_face(Faces, We) -> We'
-%% Delete the material name mapping for all faces Faces.
-delete_faces(_, #we{mat=AtomMat}=We) when is_atom(AtomMat) -> We;
-delete_faces(Faces0, #we{mat=MatTab0}=We) when is_list(Faces0) ->
- Faces = sofs:from_external(Faces0, [face]),
- MatTab1 = sofs:from_external(MatTab0, [{face,mat}]),
- MatTab2 = sofs:drestriction(MatTab1, Faces),
- MatTab = sofs:to_external(MatTab2),
- We#we{mat=MatTab};
-delete_faces(Faces, We) ->
- delete_faces(gb_sets:to_list(Faces), We).
-
-%% keep_faces(Faces, We) -> We'
-%% Delete all the other material names mapping for all faces other Faces.
-keep_faces(_, #we{mat=AtomMat}=We) when is_atom(AtomMat) -> We;
-keep_faces([Face], We) ->
- Mat = face(Face,We),
- We#we{mat=[{Face,Mat}]};
-keep_faces(Faces0, #we{mat=MatTab0}=We) when is_list(Faces0) ->
- Faces = sofs:from_external(Faces0, [face]),
- MatTab1 = sofs:from_external(MatTab0, [{face,mat}]),
- MatTab2 = sofs:restriction(MatTab1, Faces),
- MatTab = sofs:to_external(MatTab2),
- We#we{mat=MatTab};
-keep_faces(Faces, We) ->
- keep_faces(gb_sets:to_list(Faces), We).
-
-%% hide_faces(We) -> We'
-%% Update the material name mapping in the We to reflect
-%% the newly hidden faces in the face tab.
-hide_faces(#we{mat=M}=We) when is_atom(M) -> We;
-hide_faces(#we{mat=L0,fs=Ftab}=We) ->
- L = hide_faces_1(L0, Ftab, []),
- We#we{mat=L}.
-
-%% show_faces(We) -> We'
-%% Update the material name mapping in the We to reflect
-%% that all faces are again visible.
-show_faces(#we{mat=M}=We) when is_atom(M) -> We;
-show_faces(#we{mat=L0}=We) ->
- L = show_faces_1(L0, []),
- We#we{mat=L}.
-
-%% renumber(MaterialMapping, FaceOldToNew) -> MaterialMapping.
-%% Renumber face number in material name mapping.
-renumber(Mat, _) when is_atom(Mat) -> Mat;
-renumber(L, Fmap) when is_list(L) -> renumber_1(L, Fmap, []).
-
-%% gc(We) -> We'
-%% Garbage collect the material mapping information, removing
-%% the mapping for any face no longer present in the face table.
-gc(#we{mat=Mat}=We) when is_atom(Mat) -> We;
-gc(#we{mat=Tab0,fs=Ftab}=We) ->
- Fs = sofs:from_external(gb_trees:keys(Ftab), [face]),
- Tab1 = sofs:from_external(Tab0, [{face,material}]),
- Tab2 = sofs:restriction(Tab1, Fs),
- Tab = sofs:to_external(Tab2),
- We#we{mat=compress(Tab)}.
-
-%% merge([We]) -> [{Face,MaterialName}] | MaterialName.
-%% Merge materials for several objects.
-merge([#we{mat=M}|Wes]=L) when is_atom(M) ->
- case merge_all_same(Wes, M) of
- true -> M;
- false -> merge_1(L, [])
- end;
-merge(L) -> merge_1(L, []).
-
-merge_1([#we{mat=M,es=Etab}|T], Acc) when is_atom(M) ->
- FsM = merge_2(gb_trees:values(Etab), M, []),
- merge_1(T, [FsM|Acc]);
-merge_1([#we{mat=FsMs}|T], Acc) ->
- merge_1(T, [FsMs|Acc]);
-merge_1([], Acc) -> lists:merge(Acc).
-
-merge_2([#edge{lf=Lf,rf=Rf}|T], M, Acc) ->
- merge_2(T, M, [{Lf,M},{Rf,M}|Acc]);
-merge_2([], _, Acc) -> ordsets:from_list(Acc).
-
-merge_all_same([#we{mat=M}|Wes], M) -> merge_all_same(Wes, M);
-merge_all_same([_|_], _) -> false;
-merge_all_same([], _) -> true.
-
-%%%
-%%% Local functions.
-%%%
-
-assign_1(Mat, Fs, #we{fs=Ftab}=We) ->
- case length(Fs) =:= gb_trees:size(Ftab) of
- true -> We#we{mat=Mat};
- false -> assign_2(Mat, Fs, We)
- end.
-
-assign_2(Mat, Fs0, #we{fs=Ftab,mat=Mat0}=We) when is_atom(Mat0) ->
- Fs = ordsets:from_list(Fs0),
- OtherFaces = ordsets:subtract(gb_trees:keys(Ftab), Fs),
- Tab0 = make_tab(OtherFaces, Mat0),
- Tab1 = make_tab(Fs, Mat),
- Tab = lists:merge(Tab0, Tab1),
- We#we{mat=Tab};
-assign_2(Mat, Fs0, #we{mat=Tab0}=We) when is_list(Tab0) ->
- Fs = ordsets:from_list(Fs0),
- Tab1 = make_tab(Fs, Mat),
- Tab = mat_merge(Tab1, Tab0, []),
- We#we{mat=Tab}.
-
-assign_face_ms(Tab, #we{fs=Ftab}=We) ->
- case length(Tab) =:= gb_trees:size(Ftab) of
- true -> We#we{mat=compress(Tab)};
- false -> assign_face_ms_1(Tab, We)
- end.
-
-assign_face_ms_1(Tab1, #we{fs=Ftab,mat=Mat0}=We) when is_atom(Mat0) ->
- Tab0 = make_tab(gb_trees:keys(Ftab), Mat0),
- Tab = mat_merge(Tab1, Tab0, []),
- We#we{mat=Tab};
-assign_face_ms_1(Tab1, #we{mat=Tab0}=We) when is_list(Tab0) ->
- Tab = mat_merge(Tab1, Tab0, []),
- We#we{mat=Tab}.
-
-mat_merge([{Fn,_}|_]=Fns, [{Fo,_}=Fold|Fos], Acc) when Fo < Fn ->
- mat_merge(Fns, Fos, [Fold|Acc]);
-mat_merge([{Fn,_}=Fnew|Fns], [{Fo,_}|_]=Fos, Acc) when Fo > Fn ->
- mat_merge(Fns, Fos, [Fnew|Acc]);
-mat_merge([Fnew|Fns], [_|Fos], Acc) -> % Equality
- mat_merge(Fns, Fos, [Fnew|Acc]);
-mat_merge([], Fos, Acc) ->
- rev_compress(Acc, Fos);
-mat_merge(Fns, [], Acc) ->
- rev_compress(Acc, Fns).
-
-make_tab(Fs, M) ->
- make_tab_1(Fs, M, []).
-
-make_tab_1([F|Fs], M, Acc) ->
- make_tab_1(Fs, M, [{F,M}|Acc]);
-make_tab_1([], _, Acc) -> reverse(Acc).
-
-
-visible_faces(#we{fs=Ftab}) ->
- visible_faces_1(gb_trees:keys(Ftab)).
-
-visible_faces_1([F|Fs]) when F < 0 ->
- visible_faces_1(Fs);
-visible_faces_1(Fs) -> Fs.
-
-remove_invisible([{F,_}|Fs]) when F < 0 ->
- remove_invisible(Fs);
-remove_invisible(Fs) -> Fs.
-
-hide_faces_1([{F,_}=P|Fms], Ftab, Acc) when F < 0 ->
- hide_faces_1(Fms, Ftab, [P|Acc]);
-hide_faces_1([{F,M}=P|Fms], Ftab, Acc) ->
- case gb_trees:is_defined(F, Ftab) of
- false -> hide_faces_1(Fms, Ftab, [{-F-1,M}|Acc]);
- true -> hide_faces_1(Fms, Ftab, [P|Acc])
- end;
-hide_faces_1([], _, Acc) -> sort(Acc).
-
-show_faces_1([{F,M}|Fms], Acc) when F < 0 ->
- show_faces_1(Fms, [{-F-1,M}|Acc]);
-show_faces_1(Fs, Acc) -> sort(Acc++Fs).
-
-renumber_1([{F,M}|T], Fmap, Acc) ->
- renumber_1(T, Fmap, [{gb_trees:get(F, Fmap),M}|Acc]);
-renumber_1([], _, Acc) -> sort(Acc).
-
-%% rev_compress([{Face,Mat}], [{Face,Mat}]) -> [{Face,Mat}] | Mat.
-%% Reverse just like lists:reverse/2, but if all materials
-%% turns out to be just the same, return that material.
-rev_compress(L, Acc) ->
- case same_mat(Acc) of
- [] -> reverse(L, Acc);
- M -> rev_compress_1(L, M, Acc)
- end.
-
-rev_compress_1([{_,M}=E|T], M, Acc) ->
- %% Same material.
- rev_compress_1(T, M, [E|Acc]);
-rev_compress_1([_|_]=L, _, Acc) ->
- %% Another material. Finish by using reverse/2.
- reverse(L, Acc);
-rev_compress_1([], M, _) ->
- %% All materials turned out to be the same.
- M.
-
-%% compress(MaterialTab) -> [{Face,Mat}] | Mat.
-%% Compress a face mapping if possible.
-compress(M) when is_atom(M) -> M;
-compress(L) when is_list(L) ->
- case same_mat(L) of
- [] -> L;
- M -> M
- end.
-
-same_mat([]) -> [];
-same_mat([{_,M}|T]) -> same_mat_1(T, M).
-
-same_mat_1([{_,M}|T], M) -> same_mat_1(T, M);
-same_mat_1([], M) -> M;
-same_mat_1(_, _) -> [].
-
-used_materials_1([{_,M}|T], [M|_]=Acc) ->
- used_materials_1(T, Acc);
-used_materials_1([{_,M}|T], Acc) ->
- used_materials_1(T, [M|Acc]);
-used_materials_1([], Acc) ->
- ordsets:from_list(Acc).
-
-mat_faces_1([{F1,_}|_]=Fs, [{F2,_}|Ms], Acc) when F2 < F1 ->
- mat_faces_1(Fs, Ms, Acc);
-mat_faces_1([{F,Info}|Fs], [{F,Mat}|Ms], Acc) ->
- mat_faces_1(Fs, Ms, [{Mat,{F,Info}}|Acc]);
-mat_faces_1([], _, Acc) -> wings_util:rel2fam(Acc).
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_util.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_util.erl
deleted file mode 100644
index 9572e19955..0000000000
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_util.erl
+++ /dev/null
@@ -1,39 +0,0 @@
-%%
-%% wings_util.erl --
-%%
-%% Various utility functions that not obviously fit somewhere else.
-%%
-
--module(wings_util).
-
--export([gb_trees_smallest_key/1, gb_trees_largest_key/1,
- gb_trees_map/2, rel2fam/1]).
-
--include("wings.hrl").
-
-rel2fam(Rel) ->
- sofs:to_external(sofs:relation_to_family(sofs:relation(Rel))).
-
-%% a definition that does not violate the opaqueness of gb_tree()
-gb_trees_smallest_key(Tree) ->
- {Key, _V} = gb_trees:smallest(Tree),
- Key.
-
-%% a definition that violates the opaqueness of gb_tree()
-gb_trees_largest_key({_, Tree}) ->
- largest_key1(Tree).
-
-largest_key1({Key, _Value, _Smaller, nil}) ->
- Key;
-largest_key1({_Key, _Value, _Smaller, Larger}) ->
- largest_key1(Larger).
-
-gb_trees_map(F, {Size,Tree}) ->
- {Size,gb_trees_map_1(F, Tree)}.
-
-gb_trees_map_1(_, nil) -> nil;
-gb_trees_map_1(F, {K,V,Smaller,Larger}) ->
- {K,F(K, V),
- gb_trees_map_1(F, Smaller),
- gb_trees_map_1(F, Larger)}.
-
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_we.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_we.erl
deleted file mode 100644
index d782144def..0000000000
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/wings/wings_we.erl
+++ /dev/null
@@ -1,250 +0,0 @@
-%%
-%% wings_we.erl --
-%%
-%% This module contains functions to build and manipulate
-%% we records (winged-edged records, the central data structure
-%% in Wings 3D).
-
--module(wings_we).
-
--export([rebuild/1, is_consistent/1, is_face_consistent/2, new_id/1,
- new_items_as_ordset/3, validate_mirror/1, visible/1, visible_edges/1]).
-
--include("wings.hrl").
-
-%%%
-%%% API.
-%%%
-
-validate_mirror(#we{mirror=none}=We) -> We;
-validate_mirror(#we{fs=Ftab,mirror=Face}=We) ->
- case gb_trees:is_defined(Face, Ftab) of
- false -> We#we{mirror=none};
- true -> We
- end.
-
-%% rebuild(We) -> We'
-%% Rebuild any missing 'vc' and 'fs' tables. If there are
-%% fewer elements in the 'vc' table than in the 'vp' table,
-%% remove redundant entries in the 'vp' table. Updated id
-%% bounds.
-rebuild(#we{vc=undefined,fs=undefined,es=Etab0}=We0) ->
- Etab = gb_trees:to_list(Etab0),
- Ftab = rebuild_ftab(Etab),
- VctList = rebuild_vct(Etab),
- We = We0#we{vc=gb_trees:from_orddict(VctList),fs=Ftab},
- rebuild_1(VctList, We);
-rebuild(#we{vc=undefined,es=Etab}=We) ->
- VctList = rebuild_vct(gb_trees:to_list(Etab), []),
- rebuild_1(VctList, We#we{vc=gb_trees:from_orddict(VctList)});
-rebuild(#we{fs=undefined,es=Etab}=We) ->
- Ftab = rebuild_ftab(gb_trees:to_list(Etab)),
- rebuild(We#we{fs=Ftab});
-rebuild(We) -> update_id_bounds(We).
-
-%%% Utilities for allocating IDs.
-
-new_id(#we{next_id=Id}=We) ->
- {Id,We#we{next_id=Id+1}}.
-
-%%% Returns sets of newly created items.
-
-new_items_as_ordset(vertex, #we{next_id=Wid}, #we{next_id=NewWid,vp=Tab}) ->
- new_items_as_ordset_1(Tab, Wid, NewWid);
-new_items_as_ordset(edge, #we{next_id=Wid}, #we{next_id=NewWid,es=Tab}) ->
- new_items_as_ordset_1(Tab, Wid, NewWid);
-new_items_as_ordset(face, #we{next_id=Wid}, #we{next_id=NewWid,fs=Tab}) ->
- new_items_as_ordset_1(Tab, Wid, NewWid).
-
-any_hidden(#we{fs=Ftab}) ->
- not gb_trees:is_empty(Ftab) andalso
- wings_util:gb_trees_smallest_key(Ftab) < 0.
-
-%%%
-%%% Local functions.
-%%%
-
-rebuild_1(VctList, #we{vc=Vct,vp=Vtab0}=We) ->
- case {gb_trees:size(Vct),gb_trees:size(Vtab0)} of
- {Same,Same} -> rebuild(We);
- {Sz1,Sz2} when Sz1 < Sz2 ->
- Vtab = vertex_gc_1(VctList, gb_trees:to_list(Vtab0), []),
- rebuild(We#we{vp=Vtab})
- end.
-
-rebuild_vct(Es) ->
- rebuild_vct(Es, []).
-
-rebuild_vct([{Edge,#edge{vs=Va,ve=Vb}}|Es], Acc0) ->
- Acc = rebuild_maybe_add(Va, Vb, Edge, Acc0),
- rebuild_vct(Es, Acc);
-rebuild_vct([], VtoE) ->
- build_incident_tab(VtoE).
-
-rebuild_ftab(Es) ->
- rebuild_ftab_1(Es, []).
-
-rebuild_ftab_1([{Edge,#edge{lf=Lf,rf=Rf}}|Es], Acc0) ->
- Acc = rebuild_maybe_add(Lf, Rf, Edge, Acc0),
- rebuild_ftab_1(Es, Acc);
-rebuild_ftab_1([], FtoE) ->
- gb_trees:from_orddict(build_incident_tab(FtoE)).
-
-rebuild_maybe_add(Ka, Kb, E, [_,{Ka,_}|_]=Acc) ->
- [{Kb,E}|Acc];
-rebuild_maybe_add(Ka, Kb, E, [_,{Kb,_}|_]=Acc) ->
- [{Ka,E}|Acc];
-rebuild_maybe_add(Ka, Kb, E, [{Ka,_}|_]=Acc) ->
- [{Kb,E}|Acc];
-rebuild_maybe_add(Ka, Kb, E, [{Kb,_}|_]=Acc) ->
- [{Ka,E}|Acc];
-rebuild_maybe_add(Ka, Kb, E, Acc) ->
- [{Ka,E},{Kb,E}|Acc].
-
-vertex_gc_1([{V,_}|Vct], [{V,_}=Vtx|Vpos], Acc) ->
- vertex_gc_1(Vct, Vpos, [Vtx|Acc]);
-vertex_gc_1([_|_]=Vct, [_|Vpos], Acc) ->
- vertex_gc_1(Vct, Vpos, Acc);
-vertex_gc_1([], _, Acc) ->
- gb_trees:from_orddict(lists:reverse(Acc)).
-
-%%%
-%%% Handling of hidden faces.
-%%%
-
-visible(#we{mirror=none,fs=Ftab}) ->
- visible_2(gb_trees:keys(Ftab));
-visible(#we{mirror=Face,fs=Ftab}) ->
- visible_2(gb_trees:keys(gb_trees:delete(Face, Ftab))).
-
-visible_2([F|Fs]) when F < 0 -> visible_2(Fs);
-visible_2(Fs) -> Fs.
-
-visible_edges(#we{es=Etab,mirror=Face}=We) ->
- case any_hidden(We) of
- false -> gb_trees:keys(Etab);
- true -> visible_es_1(gb_trees:to_list(Etab), Face, [])
- end.
-
-visible_es_1([{E,#edge{lf=Lf,rf=Rf}}|Es], Face, Acc) ->
- if
- Lf < 0 ->
- %% Left face hidden.
- if
- Rf < 0; Rf =:= Face ->
- %% Both faces invisible (in some way).
- visible_es_1(Es, Face, Acc);
- true ->
- %% Right face is visible.
- visible_es_1(Es, Face, [E|Acc])
- end;
- Lf =:= Face, Rf < 0 ->
- %% Left face mirror, right face hidden.
- visible_es_1(Es, Face, Acc);
- true ->
- %% At least one face visible.
- visible_es_1(Es, Face, [E|Acc])
- end;
-visible_es_1([], _, Acc) -> ordsets:from_list(Acc).
-
-update_id_bounds(#we{vp=Vtab,es=Etab,fs=Ftab}=We) ->
- case gb_trees:is_empty(Etab) of
- true -> We#we{next_id=0};
- false ->
- LastId = lists:max([wings_util:gb_trees_largest_key(Vtab),
- wings_util:gb_trees_largest_key(Etab),
- wings_util:gb_trees_largest_key(Ftab)]),
- We#we{next_id=LastId+1}
- end.
-
-%% build_incident_tab([{Elem,Edge}]) -> [{Elem,Edge}]
-%% Elem = Face or Vertex
-%% Build the table of incident edges for either faces or vertices.
-%% Returns an ordered list where each Elem is unique.
-
-build_incident_tab(ElemToEdgeRel) ->
- T = ets:new(?MODULE, [ordered_set]),
- ets:insert(T, ElemToEdgeRel),
- R = ets:tab2list(T),
- ets:delete(T),
- R.
-
-%%%
-%%% Calculate normals.
-%%%
-
-new_items_as_ordset_1(Tab, Wid, NewWid) when NewWid-Wid < 32 ->
- new_items_as_ordset_2(Wid, NewWid, Tab, []);
-new_items_as_ordset_1(Tab, Wid, _NewWid) ->
- [Item || Item <- gb_trees:keys(Tab), Item >= Wid].
-
-new_items_as_ordset_2(Wid, NewWid, Tab, Acc) when Wid < NewWid ->
- case gb_trees:is_defined(Wid, Tab) of
- true -> new_items_as_ordset_2(Wid+1, NewWid, Tab, [Wid|Acc]);
- false -> new_items_as_ordset_2(Wid+1, NewWid, Tab, Acc)
- end;
-new_items_as_ordset_2(_Wid, _NewWid, _Tab, Acc) -> lists:reverse(Acc).
-
-%%%
-%%% Test the consistency of a #we{}.
-%%%
-
-is_consistent(#we{}=We) ->
- try
- validate_vertex_tab(We),
- validate_faces(We)
- catch error:_ -> false
- end.
-
-is_face_consistent(Face, #we{fs=Ftab,es=Etab}) ->
- Edge = gb_trees:get(Face, Ftab),
- try validate_face(Face, Edge, Etab)
- catch error:_ -> false
- end.
-
-validate_faces(#we{fs=Ftab,es=Etab}) ->
- validate_faces_1(gb_trees:to_list(Ftab), Etab).
-
-validate_faces_1([{Face,Edge}|Fs], Etab) ->
- validate_face(Face, Edge, Etab),
- validate_faces_1(Fs, Etab);
-validate_faces_1([], _) -> true.
-
-validate_face(Face, Edge, Etab) ->
- Ccw = walk_face_ccw(Edge, Etab, Face, Edge, []),
- Edge = walk_face_cw(Edge, Etab, Face, Ccw),
- [V|Vs] = lists:sort(Ccw),
- validate_face_vertices(Vs, V).
-
-validate_face_vertices([V|_], V) ->
- erlang:error(repeated_vertex);
-validate_face_vertices([_], _) ->
- true;
-validate_face_vertices([V|Vs], _) ->
- validate_face_vertices(Vs, V).
-
-walk_face_ccw(LastEdge, _, _, LastEdge, [_|_]=Acc) -> Acc;
-walk_face_ccw(Edge, Etab, Face, LastEdge, Acc) ->
- case gb_trees:get(Edge, Etab) of
- #edge{ve=V,lf=Face,ltpr=Next} ->
- walk_face_ccw(Next, Etab, Face, LastEdge, [V|Acc]);
- #edge{vs=V,rf=Face,rtpr=Next} ->
- walk_face_ccw(Next, Etab, Face, LastEdge, [V|Acc])
- end.
-
-walk_face_cw(Edge, _, _, []) -> Edge;
-walk_face_cw(Edge, Etab, Face, [V|Vs]) ->
- case gb_trees:get(Edge, Etab) of
- #edge{vs=V,lf=Face,ltsu=Next} ->
- walk_face_cw(Next, Etab, Face, Vs);
- #edge{ve=V,rf=Face,rtsu=Next} ->
- walk_face_cw(Next, Etab, Face, Vs)
- end.
-
-validate_vertex_tab(#we{es=Etab,vc=Vct}) ->
- lists:foreach(fun({V,Edge}) ->
- case gb_trees:get(Edge, Etab) of
- #edge{vs=V} -> ok;
- #edge{ve=V} -> ok
- end
- end, gb_trees:to_list(Vct)).
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis1.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis1.erl
deleted file mode 100644
index 82bcf2edcf..0000000000
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis1.erl
+++ /dev/null
@@ -1,14 +0,0 @@
--module(zoltan_kis1).
-
--export([f/0, gen/0]).
-
--opaque id() :: string().
-
--spec f() -> integer().
-
-%BIF and Unification(t_unify) issue
-f() -> erlang:length(gen()).
-
--spec gen() -> id().
-
-gen() -> "Dummy".
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis2.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis2.erl
deleted file mode 100644
index 3a269622fd..0000000000
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis2.erl
+++ /dev/null
@@ -1,14 +0,0 @@
--module(zoltan_kis2).
-
--export([get/2]).
-
--opaque data() :: gb_tree().
-
--spec get(term(), data()) -> term().
-
-get(Key, Data) ->
- %%Should unopaque data for remote calls
- case gb_trees:lookup(Key, Data) of
- 'none' -> 'undefined';
- {'value', Val} -> Val
- end.
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis3.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis3.erl
deleted file mode 100644
index d92c6766ff..0000000000
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis3.erl
+++ /dev/null
@@ -1,14 +0,0 @@
--module(zoltan_kis3).
-
--export([f/0, gen/0]).
-
--opaque id() :: string().
-
--spec f() -> char().
-
-%%List pattern matching issue
-f() -> [H|_T] = gen(), H.
-
--spec gen() -> id().
-
-gen() -> "Dummy".
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis4.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis4.erl
deleted file mode 100644
index aa1a4abcb7..0000000000
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis4.erl
+++ /dev/null
@@ -1,14 +0,0 @@
--module(zoltan_kis4).
-
--export([f/0, gen/0]).
-
--opaque id() :: string().
-
--spec f() -> boolean().
-
-%%Equality test issue
-f() -> "Dummy" == gen().
-
--spec gen() -> id().
-
-gen() -> "Dummy".
diff --git a/lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis5.erl b/lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis5.erl
deleted file mode 100644
index 30cebf806a..0000000000
--- a/lib/dialyzer/test/opaque_tests_SUITE_data/src/zoltan_kis5.erl
+++ /dev/null
@@ -1,14 +0,0 @@
--module(zoltan_kis5).
-
--export([f/0, gen/0]).
-
--opaque id() :: string().
-
--spec f() -> boolean().
-
-%% Equality test issue
-f() -> "Dummy" == gen().
-
--spec gen() -> id().
-
-gen() -> "Dummy".
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/dialyzer_options b/lib/dialyzer/test/options1_SUITE_data/dialyzer_options
index c612e77d3e..c612e77d3e 100644
--- a/lib/dialyzer/test/options1_tests_SUITE_data/dialyzer_options
+++ b/lib/dialyzer/test/options1_SUITE_data/dialyzer_options
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/my_include/CVS/Entries b/lib/dialyzer/test/options1_SUITE_data/my_include/CVS/Entries
index 513d4a315a..513d4a315a 100644
--- a/lib/dialyzer/test/options1_tests_SUITE_data/my_include/CVS/Entries
+++ b/lib/dialyzer/test/options1_SUITE_data/my_include/CVS/Entries
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/my_include/CVS/Repository b/lib/dialyzer/test/options1_SUITE_data/my_include/CVS/Repository
index 1c6511fec3..1c6511fec3 100644
--- a/lib/dialyzer/test/options1_tests_SUITE_data/my_include/CVS/Repository
+++ b/lib/dialyzer/test/options1_SUITE_data/my_include/CVS/Repository
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/my_include/CVS/Root b/lib/dialyzer/test/options1_SUITE_data/my_include/CVS/Root
index f6cdd6158b..f6cdd6158b 100644
--- a/lib/dialyzer/test/options1_tests_SUITE_data/my_include/CVS/Root
+++ b/lib/dialyzer/test/options1_SUITE_data/my_include/CVS/Root
diff --git a/lib/dialyzer/test/options1_SUITE_data/my_include/erl_bits.hrl b/lib/dialyzer/test/options1_SUITE_data/my_include/erl_bits.hrl
new file mode 100644
index 0000000000..45045ebb33
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/my_include/erl_bits.hrl
@@ -0,0 +1,43 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.0, (the "License"); you may not use this file except in
+%% compliance with the License. You may obtain a copy of the License at
+%% http://www.erlang.org/EPL1_0.txt
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% 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 Original Code is Erlang-4.7.3, December, 1998.
+%%
+%% The Initial Developer of the Original Code is Ericsson Telecom
+%% AB. Portions created by Ericsson are Copyright (C), 1998, Ericsson
+%% Telecom AB. All Rights Reserved.
+%%
+%% Contributor(s): ______________________________________.''
+%%
+%% This is an -*- erlang -*- file.
+%% Generic compiler options, passed from the erl_compile module.
+
+-record(bittype, {
+ type, %% integer/float/binary
+ unit, %% element unit
+ sign, %% signed/unsigned
+ endian %% big/little
+ }).
+
+-record(bitdefault, {
+ integer, %% default type for integer
+ float, %% default type for float
+ binary %% default type for binary
+ }).
+
+%%% (From config.hrl in the bitsyntax branch.)
+-define(SYS_ENDIAN, big).
+-define(SIZEOF_CHAR, 1).
+-define(SIZEOF_DOUBLE, 8).
+-define(SIZEOF_FLOAT, 4).
+-define(SIZEOF_INT, 4).
+-define(SIZEOF_LONG, 4).
+-define(SIZEOF_LONG_LONG, 8).
+-define(SIZEOF_SHORT, 2).
diff --git a/lib/dialyzer/test/options1_SUITE_data/my_include/erl_compile.hrl b/lib/dialyzer/test/options1_SUITE_data/my_include/erl_compile.hrl
new file mode 100644
index 0000000000..c10ffa235c
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/my_include/erl_compile.hrl
@@ -0,0 +1,41 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: erl_compile.hrl,v 1.1 2008/12/17 09:53:40 mikpe Exp $
+%%
+
+%% Generic compiler options, passed from the erl_compile module.
+
+-record(options,
+ {includes=[], % Include paths (list of absolute
+ % directory names).
+ outdir=".", % Directory for result (absolute
+ % path).
+ output_type=undefined, % Type of output file (atom).
+ defines=[], % Preprocessor defines. Each
+ % element is an atom (the name to
+ % define), or a {Name, Value}
+ % tuple.
+ warning=1, % Warning level (0 - no
+ % warnings, 1 - standard level,
+ % 2, 3, ... - more warnings).
+ verbose=false, % Verbose (true/false).
+ optimize=999, % Optimize options.
+ specific=[], % Compiler specific options.
+ outfile="", % Name of output file (internal
+ % use in erl_compile.erl).
+ cwd % Current working directory
+ % for erlc.
+ }).
diff --git a/lib/dialyzer/test/options1_SUITE_data/results/compiler b/lib/dialyzer/test/options1_SUITE_data/results/compiler
new file mode 100644
index 0000000000..e82087ae86
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/results/compiler
@@ -0,0 +1,35 @@
+
+beam_asm.erl:32: The pattern {'error', Error} can never match the type <<_:64,_:_*8>>
+beam_bool.erl:193: The pattern {[], _} can never match the type {[{_,_,_,_},...],[any()]}
+beam_bool.erl:510: The pattern [{'set', [Dst], _, _}, {'%live', _}] can never match the type [{_,_,_,_}]
+beam_disasm.erl:537: The variable X can never match since previous clauses completely covered the type 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
+beam_type.erl:284: The pattern <'pi', 0> can never match the type <_,1 | 2>
+beam_validator.erl:396: The pattern <{'jump', {'f', _}}, Vst = {'vst', 'none', _}> can never match the type <_,#vst{current::#st{ct::[]}}>
+beam_validator.erl:690: The pattern <'term', OldT> can never match the type <{'tuple',[any(),...]},_>
+beam_validator.erl:693: Guard test 'or'('false','false') can never succeed
+beam_validator.erl:700: Guard test 'or'('false','false') can never succeed
+beam_validator.erl:702: The pattern <'number', OldT = {Type, _}> can never match the type <{'tuple',[any(),...]},_>
+beam_validator.erl:705: The pattern <'bool', {'atom', A}> can never match the type <{'tuple',[any(),...]},_>
+beam_validator.erl:707: The pattern <{'atom', A}, 'bool'> can never match the type <{'tuple',[any(),...]},_>
+beam_validator.erl:713: Guard test is_integer(Sz::[any(),...]) can never succeed
+beam_validator.erl:727: Function upgrade_bool/1 will never be called
+cerl_inline.erl:190: The pattern 'true' can never match the type 'false'
+cerl_inline.erl:219: The pattern 'true' can never match the type 'false'
+cerl_inline.erl:230: The pattern 'true' can never match the type 'false'
+cerl_inline.erl:2333: The pattern 'true' can never match the type 'false'
+cerl_inline.erl:2355: The pattern 'true' can never match the type 'false'
+cerl_inline.erl:238: The pattern 'true' can never match the type 'false'
+cerl_inline.erl:2436: Function filename/1 will never be called
+cerl_inline.erl:2700: The pattern 'true' can never match the type 'false'
+cerl_inline.erl:2730: The pattern <{F, L, D}, Vs> can never match the type <[1..255,...],[any()]>
+cerl_inline.erl:2738: The pattern <{F, L, D}, Vs> can never match the type <[1..255,...],[any()]>
+cerl_inline.erl:2750: The pattern <{[], L, D}, Vs> can never match the type <[1..255,...],[any()]>
+cerl_inline.erl:2752: The pattern <{[], _L, D}, Vs> can never match the type <[1..255,...],[any()]>
+cerl_inline.erl:2754: The pattern <{F, L, D}, Vs> can never match the type <[1..255,...],[any()]>
+cerl_inline.erl:2756: The pattern <{F, _L, D}, Vs> can never match the type <[1..255,...],[any()]>
+compile.erl:788: The pattern {'error', Es} can never match the type {'ok',<<_:64,_:_*8>>}
+core_lint.erl:473: The pattern <{'c_atom', _, 'all'}, 'binary', _Def, St> can never match the type <_,#c_nil{} | {'c_atom' | 'c_char' | 'c_float' | 'c_int' | 'c_string' | 'c_tuple',_,_} | #c_cons{hd::#c_nil{} | {'c_atom' | 'c_char' | 'c_float' | 'c_int' | 'c_string' | 'c_tuple',_,_} | #c_cons{hd::{_,_} | {_,_,_} | {_,_,_,_},tl::{_,_} | {_,_,_} | {_,_,_,_}},tl::#c_nil{} | {'c_atom' | 'c_char' | 'c_float' | 'c_int' | 'c_string' | 'c_tuple',_,_} | #c_cons{hd::{_,_} | {_,_,_} | {_,_,_,_},tl::{_,_} | {_,_,_} | {_,_,_,_}}},[any()],_>
+core_lint.erl:505: The pattern <_Req, 'unknown', St> can never match the type <non_neg_integer(),non_neg_integer(),_>
+v3_codegen.erl:1569: The call v3_codegen:load_reg_1(V::any(),I::0,Rs::any(),pos_integer()) will never return since it differs in the 4th argument from the success typing arguments: (any(),0,maybe_improper_list(),0)
+v3_codegen.erl:1571: The call v3_codegen:load_reg_1(V::any(),I::0,[],pos_integer()) will never return since it differs in the 4th argument from the success typing arguments: (any(),0,maybe_improper_list(),0)
+v3_core.erl:646: The pattern <Prim = {'iprimop', _, _, _}, St> can never match the type <#c_nil{anno::[any(),...]} | {'c_atom' | 'c_char' | 'c_float' | 'c_int' | 'c_string' | 'c_tuple' | 'c_var' | 'ibinary' | 'icatch' | 'ireceive1',[any(),...] | {_,_,_,_},_} | #c_cons{anno::[any(),...]} | #c_fname{anno::[any(),...]} | #iletrec{anno::{_,_,_,_},defs::[any(),...],body::[any(),...]} | #icase{anno::{_,_,_,_},args::[any()],clauses::[any()],fc::{_,_,_,_,_,_}} | #ireceive2{anno::{_,_,_,_},clauses::[any()],action::[any()]} | #ifun{anno::{_,_,_,_},id::[any(),...],vars::[any()],clauses::[any(),...],fc::{_,_,_,_,_,_}} | #imatch{anno::{_,_,_,_},guard::[],fc::{_,_,_,_,_,_}} | #itry{anno::{_,_,_,_},args::[any()],vars::[any(),...],body::[any(),...],evars::[any(),...],handler::[any(),...]},_>
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_asm.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_asm.erl
new file mode 100644
index 0000000000..e3746f3fb6
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_asm.erl
@@ -0,0 +1,358 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: beam_asm.erl,v 1.1 2008/12/17 09:53:40 mikpe Exp $
+%%
+%% Purpose : Assembler for threaded Beam.
+
+-module(beam_asm).
+
+-export([module/4,format_error/1]).
+-export([encode/2]).
+
+-import(lists, [map/2,member/2,keymember/3,duplicate/2]).
+-include("beam_opcodes.hrl").
+
+-define(bs_aligned, 1).
+
+module(Code, Abst, SourceFile, Opts) ->
+ case assemble(Code, Abst, SourceFile, Opts) of
+ {error, Error} ->
+ {error, [{none, ?MODULE, Error}]};
+ Bin when binary(Bin) ->
+ {ok, Bin}
+ end.
+
+format_error({crashed, Why}) ->
+ io_lib:format("beam_asm_int: EXIT: ~p", [Why]).
+
+assemble({Mod,Exp,Attr,Asm,NumLabels}, Abst, SourceFile, Opts) ->
+ {1,Dict0} = beam_dict:atom(Mod, beam_dict:new()),
+ NumFuncs = length(Asm),
+ {Code,Dict1} = assemble_1(Asm, Exp, Dict0, []),
+ build_file(Code, Attr, Dict1, NumLabels, NumFuncs, Abst, SourceFile, Opts).
+
+assemble_1([{function,Name,Arity,Entry,Asm}|T], Exp, Dict0, Acc) ->
+ Dict1 = case member({Name,Arity}, Exp) of
+ true ->
+ beam_dict:export(Name, Arity, Entry, Dict0);
+ false ->
+ beam_dict:local(Name, Arity, Entry, Dict0)
+ end,
+ {Code, Dict2} = assemble_function(Asm, Acc, Dict1),
+ assemble_1(T, Exp, Dict2, Code);
+assemble_1([], _Exp, Dict0, Acc) ->
+ {IntCodeEnd,Dict1} = make_op(int_code_end, Dict0),
+ {list_to_binary(lists:reverse(Acc, [IntCodeEnd])),Dict1}.
+
+assemble_function([H|T], Acc, Dict0) ->
+ {Code, Dict} = make_op(H, Dict0),
+ assemble_function(T, [Code| Acc], Dict);
+assemble_function([], Code, Dict) ->
+ {Code, Dict}.
+
+build_file(Code, Attr, Dict, NumLabels, NumFuncs, Abst, SourceFile, Opts) ->
+ %% Create the code chunk.
+
+ CodeChunk = chunk(<<"Code">>,
+ <<16:32,
+ (beam_opcodes:format_number()):32,
+ (beam_dict:highest_opcode(Dict)):32,
+ NumLabels:32,
+ NumFuncs:32>>,
+ Code),
+
+ %% Create the atom table chunk.
+
+ {NumAtoms, AtomTab} = beam_dict:atom_table(Dict),
+ AtomChunk = chunk(<<"Atom">>, <<NumAtoms:32>>, AtomTab),
+
+ %% Create the import table chunk.
+
+ {NumImps, ImpTab0} = beam_dict:import_table(Dict),
+ Imp = flatten_imports(ImpTab0),
+ ImportChunk = chunk(<<"ImpT">>, <<NumImps:32>>, Imp),
+
+ %% Create the export table chunk.
+
+ {NumExps, ExpTab0} = beam_dict:export_table(Dict),
+ Exp = flatten_exports(ExpTab0),
+ ExpChunk = chunk(<<"ExpT">>, <<NumExps:32>>, Exp),
+
+ %% Create the local function table chunk.
+
+ {NumLocals, Locals} = beam_dict:local_table(Dict),
+ Loc = flatten_exports(Locals),
+ LocChunk = chunk(<<"LocT">>, <<NumLocals:32>>, Loc),
+
+ %% Create the string table chunk.
+
+ {_,StringTab} = beam_dict:string_table(Dict),
+ StringChunk = chunk(<<"StrT">>, StringTab),
+
+ %% Create the fun table chunk. It is important not to build an empty chunk,
+ %% as that would change the MD5.
+
+ LambdaChunk = case beam_dict:lambda_table(Dict) of
+ {0,[]} -> [];
+ {NumLambdas,LambdaTab} ->
+ chunk(<<"FunT">>, <<NumLambdas:32>>, LambdaTab)
+ end,
+
+ %% Create the attributes and compile info chunks.
+
+ Essentials = [AtomChunk,CodeChunk,StringChunk,ImportChunk,ExpChunk,LambdaChunk],
+ {Attributes,Compile} = build_attributes(Opts, SourceFile, Attr, Essentials),
+ AttrChunk = chunk(<<"Attr">>, Attributes),
+ CompileChunk = chunk(<<"CInf">>, Compile),
+
+ %% Create the abstract code chunk.
+
+ AbstChunk = chunk(<<"Abst">>, Abst),
+
+ %% Create IFF chunk.
+
+ Chunks = case member(slim, Opts) of
+ true -> [Essentials,AttrChunk,CompileChunk,AbstChunk];
+ false -> [Essentials,LocChunk,AttrChunk,CompileChunk,AbstChunk]
+ end,
+ build_form(<<"BEAM">>, Chunks).
+
+%% Build an IFF form.
+
+build_form(Id, Chunks0) when size(Id) == 4, list(Chunks0) ->
+ Chunks = list_to_binary(Chunks0),
+ Size = size(Chunks),
+ 0 = Size rem 4, % Assertion: correct padding?
+ <<"FOR1",(Size+4):32,Id/binary,Chunks/binary>>.
+
+%% Build a correctly padded chunk (with no sub-header).
+
+chunk(Id, Contents) when size(Id) == 4, binary(Contents) ->
+ Size = size(Contents),
+ [<<Id/binary,Size:32>>,Contents|pad(Size)];
+chunk(Id, Contents) when list(Contents) ->
+ chunk(Id, list_to_binary(Contents)).
+
+%% Build a correctly padded chunk (with a sub-header).
+
+chunk(Id, Head, Contents) when size(Id) == 4, is_binary(Head), is_binary(Contents) ->
+ Size = size(Head)+size(Contents),
+ [<<Id/binary,Size:32,Head/binary>>,Contents|pad(Size)];
+chunk(Id, Head, Contents) when list(Contents) ->
+ chunk(Id, Head, list_to_binary(Contents)).
+
+pad(Size) ->
+ case Size rem 4 of
+ 0 -> [];
+ Rem -> duplicate(4 - Rem, 0)
+ end.
+
+flatten_exports(Exps) ->
+ list_to_binary(map(fun({F,A,L}) -> <<F:32,A:32,L:32>> end, Exps)).
+
+flatten_imports(Imps) ->
+ list_to_binary(map(fun({M,F,A}) -> <<M:32,F:32,A:32>> end, Imps)).
+
+build_attributes(Opts, SourceFile, Attr, Essentials) ->
+ Misc = case member(slim, Opts) of
+ false ->
+ {{Y,Mo,D},{H,Mi,S}} = erlang:universaltime(),
+ [{time,{Y,Mo,D,H,Mi,S}},{source,SourceFile}];
+ true -> []
+ end,
+ Compile = [{options,Opts},{version,?COMPILER_VSN}|Misc],
+ {term_to_binary(calc_vsn(Attr, Essentials)),term_to_binary(Compile)}.
+
+%%
+%% If the attributes contains no 'vsn' attribute, we'll insert one
+%% with an MD5 "checksum" calculated on the code as its value.
+%% We'll not change an existing 'vsn' attribute.
+%%
+
+calc_vsn(Attr, Essentials) ->
+ case keymember(vsn, 1, Attr) of
+ true -> Attr;
+ false ->
+ <<Number:128>> = erlang:md5(Essentials),
+ [{vsn,[Number]}|Attr]
+ end.
+
+bif_type('-', 1) -> negate;
+bif_type('+', 2) -> {op, m_plus};
+bif_type('-', 2) -> {op, m_minus};
+bif_type('*', 2) -> {op, m_times};
+bif_type('/', 2) -> {op, m_div};
+bif_type('div', 2) -> {op, int_div};
+bif_type('rem', 2) -> {op, int_rem};
+bif_type('band', 2) -> {op, int_band};
+bif_type('bor', 2) -> {op, int_bor};
+bif_type('bxor', 2) -> {op, int_bxor};
+bif_type('bsl', 2) -> {op, int_bsl};
+bif_type('bsr', 2) -> {op, int_bsr};
+bif_type('bnot', 1) -> {op, int_bnot};
+bif_type(fnegate, 1) -> {op, fnegate};
+bif_type(fadd, 2) -> {op, fadd};
+bif_type(fsub, 2) -> {op, fsub};
+bif_type(fmul, 2) -> {op, fmul};
+bif_type(fdiv, 2) -> {op, fdiv};
+bif_type(_, _) -> bif.
+
+make_op(Comment, Dict) when element(1, Comment) == '%' ->
+ {[],Dict};
+make_op({'%live',_R}, Dict) ->
+ {[],Dict};
+make_op({bif, Bif, nofail, [], Dest}, Dict) ->
+ encode_op(bif0, [{extfunc, erlang, Bif, 0}, Dest], Dict);
+make_op({bif, raise, _Fail, [A1,A2], _Dest}, Dict) ->
+ encode_op(raise, [A1,A2], Dict);
+make_op({bif, Bif, Fail, Args, Dest}, Dict) ->
+ Arity = length(Args),
+ case bif_type(Bif, Arity) of
+ {op, Op} ->
+ make_op(list_to_tuple([Op, Fail|Args++[Dest]]), Dict);
+ negate ->
+ %% Fake negation operator.
+ make_op({m_minus, Fail, {integer,0}, hd(Args), Dest}, Dict);
+ bif ->
+ BifOp = list_to_atom(lists:concat([bif, Arity])),
+ encode_op(BifOp, [Fail, {extfunc, erlang, Bif, Arity}|Args++[Dest]],
+ Dict)
+ end;
+make_op({bs_add=Op,Fail,[Src1,Src2,Unit],Dest}, Dict) ->
+ encode_op(Op, [Fail,Src1,Src2,Unit,Dest], Dict);
+make_op({test,Cond,Fail,Ops}, Dict) when list(Ops) ->
+ encode_op(Cond, [Fail|Ops], Dict);
+make_op({make_fun2,{f,Lbl},Index,OldUniq,NumFree}, Dict0) ->
+ {Fun,Dict} = beam_dict:lambda(Lbl, Index, OldUniq, NumFree, Dict0),
+ make_op({make_fun2,Fun}, Dict);
+make_op(Op, Dict) when atom(Op) ->
+ encode_op(Op, [], Dict);
+make_op({kill,Y}, Dict) ->
+ make_op({init,Y}, Dict);
+make_op({Name,Arg1}, Dict) ->
+ encode_op(Name, [Arg1], Dict);
+make_op({Name,Arg1,Arg2}, Dict) ->
+ encode_op(Name, [Arg1,Arg2], Dict);
+make_op({Name,Arg1,Arg2,Arg3}, Dict) ->
+ encode_op(Name, [Arg1,Arg2,Arg3], Dict);
+make_op({Name,Arg1,Arg2,Arg3,Arg4}, Dict) ->
+ encode_op(Name, [Arg1,Arg2,Arg3,Arg4], Dict);
+make_op({Name,Arg1,Arg2,Arg3,Arg4,Arg5}, Dict) ->
+ encode_op(Name, [Arg1,Arg2,Arg3,Arg4,Arg5], Dict);
+make_op({Name,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6}, Dict) ->
+ encode_op(Name, [Arg1,Arg2,Arg3,Arg4,Arg5,Arg6], Dict).
+
+encode_op(Name, Args, Dict0) when atom(Name) ->
+ {EncArgs,Dict1} = encode_args(Args, Dict0),
+ Op = beam_opcodes:opcode(Name, length(Args)),
+ Dict2 = beam_dict:opcode(Op, Dict1),
+ {list_to_binary([Op|EncArgs]),Dict2}.
+
+encode_args([Arg| T], Dict0) ->
+ {EncArg, Dict1} = encode_arg(Arg, Dict0),
+ {EncTail, Dict2} = encode_args(T, Dict1),
+ {[EncArg| EncTail], Dict2};
+encode_args([], Dict) ->
+ {[], Dict}.
+
+encode_arg({x, X}, Dict) when X >= 0 ->
+ {encode(?tag_x, X), Dict};
+encode_arg({y, Y}, Dict) when Y >= 0 ->
+ {encode(?tag_y, Y), Dict};
+encode_arg({atom, Atom}, Dict0) when atom(Atom) ->
+ {Index, Dict} = beam_dict:atom(Atom, Dict0),
+ {encode(?tag_a, Index), Dict};
+encode_arg({integer, N}, Dict) ->
+ {encode(?tag_i, N), Dict};
+encode_arg(nil, Dict) ->
+ {encode(?tag_a, 0), Dict};
+encode_arg({f, W}, Dict) ->
+ {encode(?tag_f, W), Dict};
+encode_arg({'char', C}, Dict) ->
+ {encode(?tag_h, C), Dict};
+encode_arg({string, String}, Dict0) ->
+ {Offset, Dict} = beam_dict:string(String, Dict0),
+ {encode(?tag_u, Offset), Dict};
+encode_arg({extfunc, M, F, A}, Dict0) ->
+ {Index, Dict} = beam_dict:import(M, F, A, Dict0),
+ {encode(?tag_u, Index), Dict};
+encode_arg({list, List}, Dict0) ->
+ {L, Dict} = encode_list(List, Dict0, []),
+ {[encode(?tag_z, 1), encode(?tag_u, length(List))|L], Dict};
+encode_arg({float, Float}, Dict) when float(Float) ->
+ {[encode(?tag_z, 0)|<<Float:64/float>>], Dict};
+encode_arg({fr,Fr}, Dict) ->
+ {[encode(?tag_z, 2),encode(?tag_u,Fr)], Dict};
+encode_arg({field_flags,Flags0}, Dict) ->
+ Flags = lists:foldl(fun (F, S) -> S bor flag_to_bit(F) end, 0, Flags0),
+ {encode(?tag_u, Flags), Dict};
+encode_arg({alloc,List}, Dict) ->
+ {encode_alloc_list(List),Dict};
+encode_arg(Int, Dict) when is_integer(Int) ->
+ {encode(?tag_u, Int),Dict}.
+
+flag_to_bit(aligned) -> 16#01;
+flag_to_bit(little) -> 16#02;
+flag_to_bit(big) -> 16#00;
+flag_to_bit(signed) -> 16#04;
+flag_to_bit(unsigned)-> 16#00;
+flag_to_bit(exact) -> 16#08;
+flag_to_bit(native) -> 16#10.
+
+encode_list([H|T], _Dict, _Acc) when is_list(H) ->
+ exit({illegal_nested_list,encode_arg,[H|T]});
+encode_list([H|T], Dict0, Acc) ->
+ {Enc,Dict} = encode_arg(H, Dict0),
+ encode_list(T, Dict, [Enc|Acc]);
+encode_list([], Dict, Acc) ->
+ {lists:reverse(Acc), Dict}.
+
+encode_alloc_list(L0) ->
+ L = encode_alloc_list_1(L0),
+ [encode(?tag_z, 3),encode(?tag_u, length(L0))|L].
+
+encode_alloc_list_1([{words,Words}|T]) ->
+ [encode(?tag_u, 0),encode(?tag_u, Words)|encode_alloc_list_1(T)];
+encode_alloc_list_1([{floats,Floats}|T]) ->
+ [encode(?tag_u, 1),encode(?tag_u, Floats)|encode_alloc_list_1(T)];
+encode_alloc_list_1([]) -> [].
+
+encode(Tag, N) when N < 0 ->
+ encode1(Tag, negative_to_bytes(N, []));
+encode(Tag, N) when N < 16 ->
+ (N bsl 4) bor Tag;
+encode(Tag, N) when N < 16#800 ->
+ [((N bsr 3) band 2#11100000) bor Tag bor 2#00001000, N band 16#ff];
+encode(Tag, N) ->
+ encode1(Tag, to_bytes(N, [])).
+
+encode1(Tag, Bytes) ->
+ case length(Bytes) of
+ Num when 2 =< Num, Num =< 8 ->
+ [((Num-2) bsl 5) bor 2#00011000 bor Tag| Bytes];
+ Num when 8 < Num ->
+ [2#11111000 bor Tag, encode(?tag_u, Num-9)| Bytes]
+ end.
+
+to_bytes(0, [B|Acc]) when B < 128 ->
+ [B|Acc];
+to_bytes(N, Acc) ->
+ to_bytes(N bsr 8, [N band 16#ff| Acc]).
+
+negative_to_bytes(-1, [B1, B2|T]) when B1 > 127 ->
+ [B1, B2|T];
+negative_to_bytes(N, Acc) ->
+ negative_to_bytes(N bsr 8, [N band 16#ff|Acc]).
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_block.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_block.erl
new file mode 100644
index 0000000000..0e3589cdf5
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_block.erl
@@ -0,0 +1,601 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: beam_block.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
+%%
+%% Purpose : Partitions assembly instructions into basic blocks and
+%% optimizes them.
+
+-module(beam_block).
+
+-export([module/2]).
+-export([live_at_entry/1]). %Used by beam_type, beam_bool.
+-export([is_killed/2]). %Used by beam_dead, beam_type, beam_bool.
+-export([is_not_used/2]). %Used by beam_bool.
+-export([merge_blocks/2]). %Used by beam_jump.
+-import(lists, [map/2,mapfoldr/3,reverse/1,reverse/2,foldl/3,
+ member/2,sort/1,all/2]).
+-define(MAXREG, 1024).
+
+module({Mod,Exp,Attr,Fs,Lc}, _Opt) ->
+ {ok,{Mod,Exp,Attr,map(fun function/1, Fs),Lc}}.
+
+function({function,Name,Arity,CLabel,Is0}) ->
+ %% Collect basic blocks and optimize them.
+ Is = blockify(Is0),
+
+ %% Done.
+ {function,Name,Arity,CLabel,Is}.
+
+%% blockify(Instructions0) -> Instructions
+%% Collect sequences of instructions to basic blocks and
+%% optimize the contents of the blocks. Also do some simple
+%% optimations on instructions outside the blocks.
+
+blockify(Is) ->
+ blockify(Is, []).
+
+blockify([{loop_rec,{f,Fail},{x,0}},{loop_rec_end,_Lbl},{label,Fail}|Is], Acc) ->
+ %% Useless instruction sequence.
+ blockify(Is, Acc);
+blockify([{test,bs_test_tail,F,[Bits]}|Is],
+ [{test,bs_skip_bits,F,[{integer,I},Unit,_Flags]}|Acc]) ->
+ blockify(Is, [{test,bs_test_tail,F,[Bits+I*Unit]}|Acc]);
+blockify([{test,bs_skip_bits,F,[{integer,I1},Unit1,_]}|Is],
+ [{test,bs_skip_bits,F,[{integer,I2},Unit2,Flags]}|Acc]) ->
+ blockify(Is, [{test,bs_skip_bits,F,
+ [{integer,I1*Unit1+I2*Unit2},1,Flags]}|Acc]);
+blockify([{test,is_atom,{f,Fail},[Reg]}=I|
+ [{select_val,Reg,{f,Fail},
+ {list,[{atom,false},{f,_}=BrFalse,
+ {atom,true}=AtomTrue,{f,_}=BrTrue]}}|Is]=Is0],
+ [{block,Bl}|_]=Acc) ->
+ case is_last_bool(Bl, Reg) of
+ false ->
+ blockify(Is0, [I|Acc]);
+ true ->
+ blockify(Is, [{jump,BrTrue},
+ {test,is_eq_exact,BrFalse,[Reg,AtomTrue]}|Acc])
+ end;
+blockify([{test,is_atom,{f,Fail},[Reg]}=I|
+ [{select_val,Reg,{f,Fail},
+ {list,[{atom,true}=AtomTrue,{f,_}=BrTrue,
+ {atom,false},{f,_}=BrFalse]}}|Is]=Is0],
+ [{block,Bl}|_]=Acc) ->
+ case is_last_bool(Bl, Reg) of
+ false ->
+ blockify(Is0, [I|Acc]);
+ true ->
+ blockify(Is, [{jump,BrTrue},
+ {test,is_eq_exact,BrFalse,[Reg,AtomTrue]}|Acc])
+ end;
+blockify([I|Is0]=IsAll, Acc) ->
+ case is_bs_put(I) of
+ true ->
+ {BsPuts0,Is} = collect_bs_puts(IsAll),
+ BsPuts = opt_bs_puts(BsPuts0),
+ blockify(Is, reverse(BsPuts, Acc));
+ false ->
+ case collect(I) of
+ error -> blockify(Is0, [I|Acc]);
+ Instr when is_tuple(Instr) ->
+ {Block0,Is} = collect_block(IsAll),
+ Block = opt_block(Block0),
+ blockify(Is, [{block,Block}|Acc])
+ end
+ end;
+blockify([], Acc) -> reverse(Acc).
+
+is_last_bool([I,{'%live',_}], Reg) ->
+ is_last_bool([I], Reg);
+is_last_bool([{set,[Reg],As,{bif,N,_}}], Reg) ->
+ Ar = length(As),
+ erl_internal:new_type_test(N, Ar) orelse erl_internal:comp_op(N, Ar)
+ orelse erl_internal:bool_op(N, Ar);
+is_last_bool([_|Is], Reg) -> is_last_bool(Is, Reg);
+is_last_bool([], _) -> false.
+
+collect_block(Is) ->
+ collect_block(Is, []).
+
+collect_block([{allocate_zero,Ns,R},{test_heap,Nh,R}|Is], Acc) ->
+ collect_block(Is, [{allocate,R,{no_opt,Ns,Nh,[]}}|Acc]);
+collect_block([I|Is]=Is0, Acc) ->
+ case collect(I) of
+ error -> {reverse(Acc),Is0};
+ Instr -> collect_block(Is, [Instr|Acc])
+ end;
+collect_block([], Acc) -> {reverse(Acc),[]}.
+
+collect({allocate_zero,N,R}) -> {allocate,R,{zero,N,0,[]}};
+collect({test_heap,N,R}) -> {allocate,R,{nozero,nostack,N,[]}};
+collect({bif,N,nofail,As,D}) -> {set,[D],As,{bif,N}};
+collect({bif,N,F,As,D}) -> {set,[D],As,{bif,N,F}};
+collect({move,S,D}) -> {set,[D],[S],move};
+collect({put_list,S1,S2,D}) -> {set,[D],[S1,S2],put_list};
+collect({put_tuple,A,D}) -> {set,[D],[],{put_tuple,A}};
+collect({put,S}) -> {set,[],[S],put};
+collect({put_string,L,S,D}) -> {set,[D],[],{put_string,L,S}};
+collect({get_tuple_element,S,I,D}) -> {set,[D],[S],{get_tuple_element,I}};
+collect({set_tuple_element,S,D,I}) -> {set,[],[S,D],{set_tuple_element,I}};
+collect({get_list,S,D1,D2}) -> {set,[D1,D2],[S],get_list};
+collect(remove_message) -> {set,[],[],remove_message};
+collect({'catch',R,L}) -> {set,[R],[],{'catch',L}};
+collect({'%live',_}=Live) -> Live;
+collect(_) -> error.
+
+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 = find_fixpoint(fun move_allocates/1, Is0),
+ Is2 = find_fixpoint(fun opt/1, Is1),
+ Is = opt_alloc(Is2),
+ share_floats(Is).
+
+find_fixpoint(OptFun, Is0) ->
+ case OptFun(Is0) of
+ Is0 -> Is0;
+ Is1 -> find_fixpoint(OptFun, Is1)
+ end.
+
+move_allocates([{set,_Ds,_Ss,{set_tuple_element,_}}|_]=Is) -> Is;
+move_allocates([{set,Ds,Ss,_Op}=Set,{allocate,R,Alloc}|Is]) when is_integer(R) ->
+ [{allocate,live_regs(Ds, Ss, R),Alloc},Set|Is];
+move_allocates([{allocate,R1,Alloc1},{allocate,R2,Alloc2}|Is]) ->
+ R1 = R2, % Assertion.
+ move_allocates([{allocate,R1,combine_alloc(Alloc1, Alloc2)}|Is]);
+move_allocates([I|Is]) ->
+ [I|move_allocates(Is)];
+move_allocates([]) -> [].
+
+combine_alloc({_,Ns,Nh1,Init}, {_,nostack,Nh2,[]}) ->
+ {zero,Ns,Nh1+Nh2,Init}.
+
+merge_blocks([{allocate,R,{Attr,Ns,Nh1,Init}}|B1],
+ [{allocate,_,{_,nostack,Nh2,[]}}|B2]) ->
+ Alloc = {allocate,R,{Attr,Ns,Nh1+Nh2,Init}},
+ [Alloc|merge_blocks(B1, B2)];
+merge_blocks(B1, B2) -> merge_blocks_1(B1++[{set,[],[],stop_here}|B2]).
+
+merge_blocks_1([{set,[],_,stop_here}|Is]) -> Is;
+merge_blocks_1([{set,[D],_,move}=I|Is]) ->
+ case is_killed(D, Is) of
+ true -> merge_blocks_1(Is);
+ false -> [I|merge_blocks_1(Is)]
+ end;
+merge_blocks_1([I|Is]) -> [I|merge_blocks_1(Is)].
+
+opt([{set,[Dst],As,{bif,Bif,Fail}}=I1,
+ {set,[Dst],[Dst],{bif,'not',Fail}}=I2|Is]) ->
+ %% Get rid of the 'not' if the operation can be inverted.
+ case inverse_comp_op(Bif) of
+ none -> [I1,I2|opt(Is)];
+ RevBif -> [{set,[Dst],As,{bif,RevBif,Fail}}|opt(Is)]
+ end;
+opt([{set,[X],[X],move}|Is]) -> opt(Is);
+opt([{set,[D1],[{integer,Idx1},Reg],{bif,element,{f,0}}}=I1,
+ {set,[D2],[{integer,Idx2},Reg],{bif,element,{f,0}}}=I2|Is])
+ when Idx1 < Idx2, D1 =/= D2, D1 =/= Reg, D2 =/= Reg ->
+ opt([I2,I1|Is]);
+opt([{set,Ds0,Ss,Op}|Is0]) ->
+ {Ds,Is} = opt_moves(Ds0, Is0),
+ [{set,Ds,Ss,Op}|opt(Is)];
+opt([I|Is]) -> [I|opt(Is)];
+opt([]) -> [].
+
+opt_moves([], Is0) -> {[],Is0};
+opt_moves([D0], Is0) ->
+ {D1,Is1} = opt_move(D0, Is0),
+ {[D1],Is1};
+opt_moves([X0,Y0]=Ds, Is0) ->
+ {X1,Is1} = opt_move(X0, Is0),
+ case opt_move(Y0, Is1) of
+ {Y1,Is2} when X1 =/= Y1 -> {[X1,Y1],Is2};
+ _Other when X1 =/= Y0 -> {[X1,Y0],Is1};
+ _Other -> {Ds,Is0}
+ end.
+
+opt_move(R, [{set,[D],[R],move}|Is]=Is0) ->
+ case is_killed(R, Is) of
+ true -> {D,Is};
+ false -> {R,Is0}
+ end;
+opt_move(R, [I|Is0]) ->
+ case is_transparent(R, I) of
+ true ->
+ {D,Is1} = opt_move(R, Is0),
+ case is_transparent(D, I) of
+ true -> {D,[I|Is1]};
+ false -> {R,[I|Is0]}
+ end;
+ false -> {R,[I|Is0]}
+ end;
+opt_move(R, []) -> {R,[]}.
+
+is_transparent(R, {set,Ds,Ss,_Op}) ->
+ case member(R, Ds) of
+ true -> false;
+ false -> not member(R, Ss)
+ end;
+is_transparent(_, _) -> false.
+
+%% is_killed(Register, [Instruction]) -> true|false
+%% Determine whether a register is killed by the instruction sequence.
+%% If true is returned, it means that the register will not be
+%% referenced in ANY way (not even indirectly by an allocate instruction);
+%% i.e. it is OK to enter the instruction sequence with Register
+%% containing garbage.
+
+is_killed({x,N}=R, [{block,Blk}|Is]) ->
+ case is_killed(R, Blk) of
+ true -> true;
+ false ->
+ %% Before looking beyond the block, we must be
+ %% sure that the register is not referenced by
+ %% any allocate instruction in the block.
+ case all(fun({allocate,Live,_}) when N < Live -> false;
+ (_) -> true
+ end, Blk) of
+ true -> is_killed(R, Is);
+ false -> false
+ end
+ end;
+is_killed(R, [{block,Blk}|Is]) ->
+ case is_killed(R, Blk) of
+ true -> true;
+ false -> is_killed(R, Is)
+ end;
+is_killed(R, [{set,Ds,Ss,_Op}|Is]) ->
+ case member(R, Ss) of
+ true -> false;
+ false ->
+ case member(R, Ds) of
+ true -> true;
+ false -> is_killed(R, Is)
+ end
+ end;
+is_killed(R, [{case_end,Used}|_]) -> R =/= Used;
+is_killed(R, [{badmatch,Used}|_]) -> R =/= Used;
+is_killed(_, [if_end|_]) -> true;
+is_killed(R, [{func_info,_,_,Ar}|_]) ->
+ case R of
+ {x,X} when X < Ar -> false;
+ _ -> true
+ end;
+is_killed(R, [{kill,R}|_]) -> true;
+is_killed(R, [{kill,_}|Is]) -> is_killed(R, Is);
+is_killed(R, [{bs_init2,_,_,_,_,_,Dst}|Is]) ->
+ if
+ R =:= Dst -> true;
+ true -> is_killed(R, Is)
+ end;
+is_killed(R, [{bs_put_string,_,_}|Is]) -> is_killed(R, Is);
+is_killed({x,R}, [{'%live',Live}|_]) when R >= Live -> true;
+is_killed({x,R}, [{'%live',_}|Is]) -> is_killed(R, Is);
+is_killed({x,R}, [{allocate,Live,_}|_]) ->
+ %% Note: To be safe here, we must return either true or false,
+ %% not looking further at the instructions beyond the allocate
+ %% instruction.
+ R >= Live;
+is_killed({x,R}, [{call,Live,_}|_]) when R >= Live -> true;
+is_killed({x,R}, [{call_last,Live,_,_}|_]) when R >= Live -> true;
+is_killed({x,R}, [{call_only,Live,_}|_]) when R >= Live -> true;
+is_killed({x,R}, [{call_ext,Live,_}|_]) when R >= Live -> true;
+is_killed({x,R}, [{call_ext_last,Live,_,_}|_]) when R >= Live -> true;
+is_killed({x,R}, [{call_ext_only,Live,_}|_]) when R >= Live -> true;
+is_killed({x,R}, [return|_]) when R > 0 -> true;
+is_killed(_, _) -> false.
+
+%% is_not_used(Register, [Instruction]) -> true|false
+%% Determine whether a register is used by the instruction sequence.
+%% If true is returned, it means that the register will not be
+%% referenced directly, but it may be referenced by an allocate
+%% instruction (meaning that it is NOT allowed to contain garbage).
+
+is_not_used(R, [{block,Blk}|Is]) ->
+ case is_not_used(R, Blk) of
+ true -> true;
+ false -> is_not_used(R, Is)
+ end;
+is_not_used({x,R}=Reg, [{allocate,Live,_}|Is]) ->
+ if
+ R >= Live -> true;
+ true -> is_not_used(Reg, Is)
+ end;
+is_not_used(R, [{set,Ds,Ss,_Op}|Is]) ->
+ case member(R, Ss) of
+ true -> false;
+ false ->
+ case member(R, Ds) of
+ true -> true;
+ false -> is_not_used(R, Is)
+ end
+ end;
+is_not_used(R, Is) -> is_killed(R, Is).
+
+%% opt_alloc(Instructions) -> Instructions'
+%% Optimises all allocate instructions.
+
+opt_alloc([{allocate,R,{_,Ns,Nh,[]}}|Is]) ->
+ [opt_alloc(Is, Ns, Nh, R)|opt(Is)];
+opt_alloc([I|Is]) -> [I|opt_alloc(Is)];
+opt_alloc([]) -> [].
+
+%% opt_alloc(Instructions, FrameSize, HeapNeed, LivingRegs) -> [Instr]
+%% Generates the optimal sequence of instructions for
+%% allocating and initalizing the stack frame and needed heap.
+
+opt_alloc(_Is, nostack, Nh, LivingRegs) ->
+ {allocate,LivingRegs,{nozero,nostack,Nh,[]}};
+opt_alloc(Is, Ns, Nh, LivingRegs) ->
+ InitRegs = init_yreg(Is, 0),
+ case count_ones(InitRegs) of
+ N when N*2 > Ns ->
+ {allocate,LivingRegs,{nozero,Ns,Nh,gen_init(Ns, InitRegs)}};
+ _ ->
+ {allocate,LivingRegs,{zero,Ns,Nh,[]}}
+ end.
+
+gen_init(Fs, Regs) -> gen_init(Fs, Regs, 0, []).
+
+gen_init(SameFs, _Regs, SameFs, Acc) -> reverse(Acc);
+gen_init(Fs, Regs, Y, Acc) when Regs band 1 == 0 ->
+ gen_init(Fs, Regs bsr 1, Y+1, [{init, {y,Y}}|Acc]);
+gen_init(Fs, Regs, Y, Acc) ->
+ gen_init(Fs, Regs bsr 1, Y+1, Acc).
+
+%% init_yreg(Instructions, RegSet) -> RegSetInitialized
+%% Calculate the set of initialized y registers.
+
+init_yreg([{set,_,_,{bif,_,_}}|_], Reg) -> Reg;
+init_yreg([{set,Ds,_,_}|Is], Reg) -> init_yreg(Is, add_yregs(Ds, Reg));
+init_yreg(_Is, Reg) -> Reg.
+
+add_yregs(Ys, Reg) -> foldl(fun(Y, R0) -> add_yreg(Y, R0) end, Reg, Ys).
+
+add_yreg({y,Y}, Reg) -> Reg bor (1 bsl Y);
+add_yreg(_, Reg) -> Reg.
+
+count_ones(Bits) -> count_ones(Bits, 0).
+count_ones(0, Acc) -> Acc;
+count_ones(Bits, Acc) ->
+ count_ones(Bits bsr 1, Acc + (Bits band 1)).
+
+%% live_at_entry(Is) -> NumberOfRegisters
+%% Calculate the number of register live at the entry to the code
+%% sequence.
+
+live_at_entry([{block,[{allocate,R,_}|_]}|_]) ->
+ R;
+live_at_entry([{label,_}|Is]) ->
+ live_at_entry(Is);
+live_at_entry([{block,Bl}|_]) ->
+ live_at_entry(Bl);
+live_at_entry([{func_info,_,_,Ar}|_]) ->
+ Ar;
+live_at_entry(Is0) ->
+ case reverse(Is0) of
+ [{'%live',Regs}|Is] -> live_at_entry_1(Is, (1 bsl Regs)-1);
+ _ -> unknown
+ end.
+
+live_at_entry_1([{set,Ds,Ss,_}|Is], Rset0) ->
+ Rset = x_live(Ss, x_dead(Ds, Rset0)),
+ live_at_entry_1(Is, Rset);
+live_at_entry_1([{allocate,_,_}|Is], Rset) ->
+ live_at_entry_1(Is, Rset);
+live_at_entry_1([], Rset) -> live_regs_1(0, Rset).
+
+%% Calculate the new number of live registers when we move an allocate
+%% instruction upwards, passing a 'set' instruction.
+
+live_regs(Ds, Ss, Regs0) ->
+ Rset = x_live(Ss, x_dead(Ds, (1 bsl Regs0)-1)),
+ live_regs_1(0, Rset).
+
+live_regs_1(N, 0) -> N;
+live_regs_1(N, Regs) -> live_regs_1(N+1, Regs bsr 1).
+
+x_dead([{x,N}|Rs], Regs) -> x_dead(Rs, Regs band (bnot (1 bsl N)));
+x_dead([_|Rs], Regs) -> x_dead(Rs, Regs);
+x_dead([], Regs) -> Regs.
+
+x_live([{x,N}|Rs], Regs) -> x_live(Rs, Regs bor (1 bsl N));
+x_live([_|Rs], Regs) -> x_live(Rs, Regs);
+x_live([], Regs) -> Regs.
+
+%%
+%% If a floating point literal occurs more than once, move it into
+%% a free register and re-use it.
+%%
+
+share_floats([{allocate,_,_}=Alloc|Is]) ->
+ [Alloc|share_floats(Is)];
+share_floats(Is0) ->
+ All = get_floats(Is0, []),
+ MoreThanOnce0 = more_than_once(sort(All), gb_sets:empty()),
+ case gb_sets:is_empty(MoreThanOnce0) of
+ true -> Is0;
+ false ->
+ MoreThanOnce = gb_sets:to_list(MoreThanOnce0),
+ FreeX = highest_used(Is0, -1) + 1,
+ Regs0 = make_reg_map(MoreThanOnce, FreeX, []),
+ Regs = gb_trees:from_orddict(Regs0),
+ Is = map(fun({set,Ds,[{float,F}],Op}=I) ->
+ case gb_trees:lookup(F, Regs) of
+ none -> I;
+ {value,R} -> {set,Ds,[R],Op}
+ end;
+ (I) -> I
+ end, Is0),
+ [{set,[R],[{float,F}],move} || {F,R} <- Regs0] ++ Is
+ end.
+
+get_floats([{set,_,[{float,F}],_}|Is], Acc) ->
+ get_floats(Is, [F|Acc]);
+get_floats([_|Is], Acc) ->
+ get_floats(Is, Acc);
+get_floats([], Acc) -> Acc.
+
+more_than_once([F,F|Fs], Set) ->
+ more_than_once(Fs, gb_sets:add(F, Set));
+more_than_once([_|Fs], Set) ->
+ more_than_once(Fs, Set);
+more_than_once([], Set) -> Set.
+
+highest_used([{set,Ds,Ss,_}|Is], High) ->
+ highest_used(Is, highest(Ds, highest(Ss, High)));
+highest_used([{'%live',Live}|Is], High) when Live > High ->
+ highest_used(Is, Live);
+highest_used([_|Is], High) ->
+ highest_used(Is, High);
+highest_used([], High) -> High.
+
+highest([{x,R}|Rs], High) when R > High ->
+ highest(Rs, R);
+highest([_|Rs], High) ->
+ highest(Rs, High);
+highest([], High) -> High.
+
+make_reg_map([F|Fs], R, Acc) when R < ?MAXREG ->
+ make_reg_map(Fs, R+1, [{F,{x,R}}|Acc]);
+make_reg_map(_, _, Acc) -> sort(Acc).
+
+%% inverse_comp_op(Op) -> none|RevOp
+
+inverse_comp_op('=:=') -> '=/=';
+inverse_comp_op('=/=') -> '=:=';
+inverse_comp_op('==') -> '/=';
+inverse_comp_op('/=') -> '==';
+inverse_comp_op('>') -> '=<';
+inverse_comp_op('<') -> '>=';
+inverse_comp_op('>=') -> '<';
+inverse_comp_op('=<') -> '>';
+inverse_comp_op(_) -> none.
+
+%%%
+%%% Evaluation of constant bit fields.
+%%%
+
+is_bs_put({bs_put_integer,_,_,_,_,_}) -> true;
+is_bs_put({bs_put_float,_,_,_,_,_}) -> true;
+is_bs_put(_) -> false.
+
+collect_bs_puts(Is) ->
+ collect_bs_puts_1(Is, []).
+
+collect_bs_puts_1([I|Is]=Is0, Acc) ->
+ case is_bs_put(I) of
+ false -> {reverse(Acc),Is0};
+ true -> collect_bs_puts_1(Is, [I|Acc])
+ end;
+collect_bs_puts_1([], Acc) -> {reverse(Acc),[]}.
+
+opt_bs_puts(Is) ->
+ opt_bs_1(Is, []).
+
+opt_bs_1([{bs_put_float,Fail,{integer,Sz},1,Flags0,Src}=I0|Is], Acc) ->
+ case catch eval_put_float(Src, Sz, Flags0) of
+ {'EXIT',_} ->
+ opt_bs_1(Is, [I0|Acc]);
+ <<Int:Sz>> ->
+ Flags = force_big(Flags0),
+ I = {bs_put_integer,Fail,{integer,Sz},1,Flags,{integer,Int}},
+ opt_bs_1([I|Is], Acc)
+ end;
+opt_bs_1([{bs_put_integer,_,{integer,8},1,_,{integer,_}}|_]=IsAll, Acc0) ->
+ {Is,Acc} = bs_collect_string(IsAll, Acc0),
+ opt_bs_1(Is, Acc);
+opt_bs_1([{bs_put_integer,Fail,{integer,Sz},1,F,{integer,N}}=I|Is0], Acc) when Sz > 8 ->
+ case field_endian(F) of
+ big ->
+ case bs_split_int(N, Sz, Fail, Is0) of
+ no_split -> opt_bs_1(Is0, [I|Acc]);
+ Is -> opt_bs_1(Is, Acc)
+ end;
+ little ->
+ case catch <<N:Sz/little>> of
+ {'EXIT',_} ->
+ opt_bs_1(Is0, [I|Acc]);
+ <<Int:Sz>> ->
+ Flags = force_big(F),
+ Is = [{bs_put_integer,Fail,{integer,Sz},1,
+ Flags,{integer,Int}}|Is0],
+ opt_bs_1(Is, Acc)
+ end;
+ native -> opt_bs_1(Is0, [I|Acc])
+ end;
+opt_bs_1([{Op,Fail,{integer,Sz},U,F,Src}|Is], Acc) when U > 1 ->
+ opt_bs_1([{Op,Fail,{integer,U*Sz},1,F,Src}|Is], Acc);
+opt_bs_1([I|Is], Acc) ->
+ opt_bs_1(Is, [I|Acc]);
+opt_bs_1([], Acc) -> reverse(Acc).
+
+eval_put_float(Src, Sz, Flags) ->
+ Val = value(Src),
+ case field_endian(Flags) of
+ little -> <<Val:Sz/little-float-unit:1>>;
+ big -> <<Val:Sz/big-float-unit:1>>
+ %% native intentionally not handled here - we can't optimize it.
+ end.
+
+value({integer,I}) -> I;
+value({float,F}) -> F;
+value({atom,A}) -> A.
+
+bs_collect_string(Is, [{bs_put_string,Len,{string,Str}}|Acc]) ->
+ bs_coll_str_1(Is, Len, reverse(Str), Acc);
+bs_collect_string(Is, Acc) ->
+ bs_coll_str_1(Is, 0, [], Acc).
+
+bs_coll_str_1([{bs_put_integer,_,{integer,Sz},U,_,{integer,V}}|Is],
+ Len, StrAcc, IsAcc) when U*Sz =:= 8 ->
+ Byte = V band 16#FF,
+ bs_coll_str_1(Is, Len+1, [Byte|StrAcc], IsAcc);
+bs_coll_str_1(Is, Len, StrAcc, IsAcc) ->
+ {Is,[{bs_put_string,Len,{string,reverse(StrAcc)}}|IsAcc]}.
+
+field_endian({field_flags,F}) -> field_endian_1(F).
+
+field_endian_1([big=E|_]) -> E;
+field_endian_1([little=E|_]) -> E;
+field_endian_1([native=E|_]) -> E;
+field_endian_1([_|Fs]) -> field_endian_1(Fs).
+
+force_big({field_flags,F}) ->
+ {field_flags,force_big_1(F)}.
+
+force_big_1([big|_]=Fs) -> Fs;
+force_big_1([little|Fs]) -> [big|Fs];
+force_big_1([F|Fs]) -> [F|force_big_1(Fs)].
+
+bs_split_int(0, Sz, _, _) when Sz > 64 ->
+ %% We don't want to split in this case because the
+ %% string will consist of only zeroes.
+ no_split;
+bs_split_int(N, Sz, Fail, Acc) ->
+ FirstByteSz = case Sz rem 8 of
+ 0 -> 8;
+ Rem -> Rem
+ end,
+ bs_split_int_1(N, FirstByteSz, Sz, Fail, Acc).
+
+bs_split_int_1(N, ByteSz, Sz, Fail, Acc) when Sz > 0 ->
+ Mask = (1 bsl ByteSz) - 1,
+ I = {bs_put_integer,Fail,{integer,ByteSz},1,
+ {field_flags,[big]},{integer,N band Mask}},
+ bs_split_int_1(N bsr ByteSz, 8, Sz-ByteSz, Fail, [I|Acc]);
+bs_split_int_1(_, _, _, _, Acc) -> Acc.
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_bool.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_bool.erl
new file mode 100644
index 0000000000..b7b28a41a5
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_bool.erl
@@ -0,0 +1,617 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: beam_bool.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
+%%
+%% Purpose: Optimizes booleans in guards.
+
+-module(beam_bool).
+
+-export([module/2]).
+
+-import(lists, [reverse/1,foldl/3,mapfoldl/3,sort/1,member/2]).
+-define(MAXREG, 1024).
+
+-record(st,
+ {next, %Next label number.
+ ll %Live regs at labels.
+ }).
+
+module({Mod,Exp,Attr,Fs0,Lc}, _Opts) ->
+ %%io:format("~p:\n", [Mod]),
+ {Fs,_} = mapfoldl(fun(Fn, Lbl) -> function(Fn, Lbl) end, 100000000, Fs0),
+ {ok,{Mod,Exp,Attr,Fs,Lc}}.
+
+function({function,Name,Arity,CLabel,Is0}, Lbl0) ->
+ %%io:format("~p/~p:\n", [Name,Arity]),
+ {Is,#st{next=Lbl}} = bool_opt(Is0, Lbl0),
+ {{function,Name,Arity,CLabel,Is},Lbl}.
+
+%%
+%% Optimize boolean expressions that use guard bifs. Rewrite to
+%% use test instructions if possible.
+%%
+
+bool_opt(Asm, Lbl) ->
+ LiveInfo = index_instructions(Asm),
+ bopt(Asm, [], #st{next=Lbl,ll=LiveInfo}).
+
+bopt([{block,Bl0}=Block|
+ [{jump,{f,Succ}},
+ {label,Fail},
+ {block,[{set,[Dst],[{atom,false}],move},{'%live',Live}]},
+ {label,Succ}|Is]=Is0], Acc0, St) ->
+ case split_block(Bl0, Dst, Fail) of
+ failed ->
+ bopt(Is0, [Block|Acc0], St);
+ {Bl,PreBlock} ->
+ Acc1 = case PreBlock of
+ [] -> Acc0;
+ _ -> [{block,PreBlock}|Acc0]
+ end,
+ Acc = [{protected,[Dst],Bl,{Fail,Succ,Live}}|Acc1],
+ bopt(Is, Acc, St)
+ end;
+bopt([{test,is_eq_exact,{f,Fail},[Reg,{atom,true}]}=I|Is], [{block,_}|_]=Acc0, St0) ->
+ case bopt_block(Reg, Fail, Is, Acc0, St0) of
+ failed -> bopt(Is, [I|Acc0], St0);
+ {Acc,St} -> bopt(Is, Acc, St)
+ end;
+bopt([I|Is], Acc, St) ->
+ bopt(Is, [I|Acc], St);
+bopt([], Acc, St) ->
+ {bopt_reverse(Acc, []),St}.
+
+bopt_reverse([{protected,[Dst],Block,{Fail,Succ,Live}}|Is], Acc0) ->
+ Acc = [{block,Block},{jump,{f,Succ}},
+ {label,Fail},
+ {block,[{set,[Dst],[{atom,false}],move},{'%live',Live}]},
+ {label,Succ}|Acc0],
+ bopt_reverse(Is, Acc);
+bopt_reverse([I|Is], Acc) ->
+ bopt_reverse(Is, [I|Acc]);
+bopt_reverse([], Acc) -> Acc.
+
+%% bopt_block(Reg, Fail, OldIs, Accumulator, St) -> failed | {NewAcc,St}
+%% Attempt to optimized a block of guard BIFs followed by a test
+%% instruction.
+bopt_block(Reg, Fail, OldIs, [{block,Bl0}|Acc0], St0) ->
+ case split_block(Bl0, Reg, Fail) of
+ failed ->
+ %% Reason for failure: The block either contained no
+ %% guard BIFs with the failure label Fail, or the final
+ %% instruction in the block did not assign the Reg register.
+
+ %%io:format("split ~p: ~P\n", [Reg,Bl0,20]),
+ failed;
+ {Bl1,BlPre} ->
+ %% The block has been splitted. Bl1 is a non-empty list
+ %% of guard BIF instructions having the failure label Fail.
+ %% BlPre is a (possibly empty list) of instructions preceeding
+ %% Bl1.
+ Acc1 = make_block(BlPre, Acc0),
+ {Bl,Acc} = extend_block(Bl1, Fail, Acc1),
+ case catch bopt_block_1(Bl, Fail, St0) of
+ {'EXIT',_Reason} ->
+ %% Optimization failed for one of the following reasons:
+ %%
+ %% 1. Not possible to rewrite because a boolean value is
+ %% passed to another guard bif, e.g. 'abs(A > B)'
+ %% (in this case, obviously nonsense code). Rare in
+ %% practice.
+ %%
+ %% 2. Not possible to rewrite because we have not seen
+ %% the complete boolan expression (it is spread out
+ %% over several blocks with jumps and labels).
+ %% The 'or' and 'and' instructions need to that fully
+ %% known operands in order to be eliminated.
+ %%
+ %% 3. Other bug or limitation.
+
+ %%io:format("~P\n", [_Reason,20]),
+ failed;
+ {NewCode,St} ->
+ case is_opt_safe(Bl, NewCode, OldIs, St) of
+ false ->
+ %% The optimization is not safe. (A register
+ %% used by the instructions following the
+ %% optimized code is either not assigned a
+ %% value at all or assigned a different value.)
+
+ %%io:format("\nNot safe:\n"),
+ %%io:format("~p\n", [Bl]),
+ %%io:format("~p\n", [reverse(NewCode)]),
+ failed;
+ true -> {NewCode++Acc,St}
+ end
+ end
+ end.
+
+bopt_block_1(Block, Fail, St) ->
+ {Pre0,[{_,Tree}]} = bopt_tree(Block),
+ Pre = update_fail_label(Pre0, Fail, []),
+ bopt_cg(Tree, Fail, make_block(Pre, []), St).
+
+%% is_opt_safe(OriginalCode, OptCode, FollowingCode, State) -> true|false
+%% Comparing the original code to the optimized code, determine
+%% whether the optimized code is guaranteed to work in the same
+%% way as the original code.
+
+is_opt_safe(Bl, NewCode, OldIs, St) ->
+ %% Here are the conditions that must be true for the
+ %% optimization to be safe.
+ %%
+ %% 1. Any register that was assigned a value in the original
+ %% code, but is not in the optimized code, must be guaranteed
+ %% to be KILLED in the following code. (NotSet below.)
+ %%
+ %% 2. Any register that is assigned a value in the optimized
+ %% code must be UNUSED in the following code. (NewDst, Set.)
+ %% (Possible future improvement: Registers that are known
+ %% to be assigned the SAME value in the original and optimized
+ %% code don't need to be unused in the following code.)
+
+ PrevDst = dst_regs(Bl),
+ NewDst = dst_regs(NewCode),
+ NotSet = ordsets:subtract(PrevDst, NewDst),
+
+ %% Note: The following line is an optimization. We don't need
+ %% to test whether variables in NotSet for being unused, because
+ %% they will all be tested for being killed (a stronger condition
+ %% than being unused).
+
+ Set = ordsets:subtract(NewDst, NotSet),
+
+ all_killed(NotSet, OldIs, St) andalso
+ none_used(Set, OldIs, St).
+
+% update_fail_label([{set,_,_,{bif,_,{f,0}}}=I|Is], Fail, Acc) ->
+% update_fail_label(Is, Fail, [I|Acc]);
+update_fail_label([{set,Ds,As,{bif,N,{f,_}}}|Is], Fail, Acc) ->
+ update_fail_label(Is, Fail, [{set,Ds,As,{bif,N,{f,Fail}}}|Acc]);
+update_fail_label([], _, Acc) -> Acc.
+
+make_block([], Acc) -> Acc;
+make_block(Bl, Acc) -> [{block,Bl}|Acc].
+
+extend_block(BlAcc, Fail, [{protected,_,_,_}=Prot|OldAcc]) ->
+ extend_block([Prot|BlAcc], Fail, OldAcc);
+extend_block(BlAcc0, Fail, [{block,Is0}|OldAcc]=OldAcc0) ->
+ case extend_block_1(reverse(Is0), Fail, BlAcc0) of
+ {[],_} -> {BlAcc0,OldAcc0};
+ {BlAcc,[]} -> extend_block(BlAcc, Fail, OldAcc);
+ {BlAcc,Is} -> {BlAcc,[{block,Is}|OldAcc]}
+ end;
+extend_block(BlAcc, _, OldAcc) -> {BlAcc,OldAcc}.
+
+extend_block_1([{set,[_],_,{bif,_,{f,Fail}}}=I|Is], Fail, Acc) ->
+ extend_block_1(Is, Fail, [I|Acc]);
+extend_block_1([{set,[_],As,{bif,Bif,_}}=I|Is]=Is0, Fail, Acc) ->
+ case safe_bool_op(Bif, length(As)) of
+ false -> {Acc,reverse(Is0)};
+ true -> extend_block_1(Is, Fail, [I|Acc])
+ end;
+extend_block_1([_|_]=Is, _, Acc) -> {Acc,reverse(Is)};
+extend_block_1([], _, Acc) -> {Acc,[]}.
+
+split_block(Is0, Dst, Fail) ->
+ case reverse(Is0) of
+ [{'%live',_}|[{set,[Dst],_,_}|_]=Is] ->
+ split_block_1(Is, Fail);
+ [{set,[Dst],_,_}|_]=Is ->
+ split_block_1(Is, Fail);
+ _ -> failed
+ end.
+
+split_block_1(Is, Fail) ->
+ case split_block_2(Is, Fail, []) of
+ {[],_} -> failed;
+ {_,_}=Res -> Res
+ end.
+
+% split_block_2([{set,[_],_,{bif,_,{f,0}}}=I|Is], Fail, Acc) ->
+% split_block_2(Is, Fail, [I|Acc]);
+split_block_2([{set,[_],_,{bif,_,{f,Fail}}}=I|Is], Fail, Acc) ->
+ split_block_2(Is, Fail, [I|Acc]);
+split_block_2([{'%live',_}|Is], Fail, Acc) ->
+ split_block_2(Is, Fail, Acc);
+split_block_2(Is, _, Acc) -> {Acc,reverse(Is)}.
+
+dst_regs(Is) ->
+ dst_regs(Is, []).
+
+dst_regs([{block,Bl}|Is], Acc) ->
+ dst_regs(Bl, dst_regs(Is, Acc));
+dst_regs([{set,[D],_,{bif,_,{f,_}}}|Is], Acc) ->
+ dst_regs(Is, [D|Acc]);
+dst_regs([_|Is], Acc) ->
+ dst_regs(Is, Acc);
+dst_regs([], Acc) -> ordsets:from_list(Acc).
+
+all_killed([R|Rs], OldIs, St) ->
+ case is_killed(R, OldIs, St) of
+ false -> false;
+ true -> all_killed(Rs, OldIs, St)
+ end;
+all_killed([], _, _) -> true.
+
+none_used([R|Rs], OldIs, St) ->
+ case is_not_used(R, OldIs, St) of
+ false -> false;
+ true -> none_used(Rs, OldIs, St)
+ end;
+none_used([], _, _) -> true.
+
+bopt_tree(Block0) ->
+ Block = ssa_block(Block0),
+ Reg = free_variables(Block),
+ %%io:format("~p\n", [Block]),
+ %%io:format("~p\n", [Reg]),
+ Res = bopt_tree_1(Block, Reg, []),
+ %%io:format("~p\n", [Res]),
+ Res.
+
+bopt_tree_1([{set,[Dst],As0,{bif,'not',_}}|Is], Forest0, Pre) ->
+ {[Arg],Forest1} = bopt_bool_args(As0, Forest0),
+ Forest = gb_trees:enter(Dst, {'not',Arg}, Forest1),
+ bopt_tree_1(Is, Forest, Pre);
+bopt_tree_1([{set,[Dst],As0,{bif,'and',_}}|Is], Forest0, Pre) ->
+ {As,Forest1} = bopt_bool_args(As0, Forest0),
+ AndList = make_and_list(As),
+ Forest = gb_trees:enter(Dst, {'and',AndList}, Forest1),
+ bopt_tree_1(Is, Forest, Pre);
+bopt_tree_1([{set,[Dst],[L0,R0],{bif,'or',_}}|Is], Forest0, Pre) ->
+ L = gb_trees:get(L0, Forest0),
+ R = gb_trees:get(R0, Forest0),
+ Forest1 = gb_trees:delete(L0, gb_trees:delete(R0, Forest0)),
+ OrList = make_or_list([L,R]),
+ Forest = gb_trees:enter(Dst, {'or',OrList}, Forest1),
+ bopt_tree_1(Is, Forest, Pre);
+bopt_tree_1([{protected,[Dst],_,_}=Prot|Is], Forest0, Pre) ->
+ Forest = gb_trees:enter(Dst, Prot, Forest0),
+ bopt_tree_1(Is, Forest, Pre);
+bopt_tree_1([{set,[Dst],As,{bif,N,_}}=Bif|Is], Forest0, Pre) ->
+ Ar = length(As),
+ case safe_bool_op(N, Ar) of
+ false ->
+ bopt_good_args(As, Forest0),
+ Forest = gb_trees:enter(Dst, any, Forest0),
+ bopt_tree_1(Is, Forest, [Bif|Pre]);
+ true ->
+ bopt_good_args(As, Forest0),
+ Test = bif_to_test(Dst, N, As),
+ Forest = gb_trees:enter(Dst, Test, Forest0),
+ bopt_tree_1(Is, Forest, Pre)
+ end;
+bopt_tree_1([], Forest, Pre) ->
+ {Pre,[R || {_,V}=R <- gb_trees:to_list(Forest), V =/= any]}.
+
+safe_bool_op(internal_is_record, 3) -> true;
+safe_bool_op(N, Ar) ->
+ erl_internal:new_type_test(N, Ar) orelse erl_internal:comp_op(N, Ar).
+
+bopt_bool_args(As, Forest) ->
+ mapfoldl(fun bopt_bool_arg/2, Forest, As).
+
+bopt_bool_arg({T,_}=R, Forest) when T == x; T == y ->
+ {gb_trees:get(R, Forest),gb_trees:delete(R, Forest)};
+bopt_bool_arg(Term, Forest) ->
+ {Term,Forest}.
+
+bopt_good_args([A|As], Regs) ->
+ bopt_good_arg(A, Regs),
+ bopt_good_args(As, Regs);
+bopt_good_args([], _) -> ok.
+
+bopt_good_arg({x,_}=X, Regs) ->
+ case gb_trees:get(X, Regs) of
+ any -> ok;
+ _Other ->
+ %%io:format("not any: ~p: ~p\n", [X,_Other]),
+ exit(bad_contents)
+ end;
+bopt_good_arg(_, _) -> ok.
+
+bif_to_test(_, N, As) ->
+ bif_to_test(N, As).
+
+bif_to_test(internal_is_record, [_,_,_]=As) ->
+ {test,internal_is_record,fail,As};
+bif_to_test('=:=', As) -> {test,is_eq_exact,fail,As};
+bif_to_test('=/=', As) -> {test,is_ne_exact,fail,As};
+bif_to_test('==', As) -> {test,is_eq,fail,As};
+bif_to_test('/=', As) -> {test,is_ne,fail,As};
+bif_to_test('=<', [L,R]) -> {test,is_ge,fail,[R,L]};
+bif_to_test('>=', As) -> {test,is_ge,fail,As};
+bif_to_test('>', [L,R]) -> {test,is_lt,fail,[R,L]};
+bif_to_test('<', As) -> {test,is_lt,fail,As};
+bif_to_test(Name, [_]=As) ->
+ case erl_internal:new_type_test(Name, 1) of
+ false -> exit({bif_to_test,Name,As,failed});
+ true -> {test,Name,fail,As}
+ end.
+
+make_and_list([{'and',As}|Is]) ->
+ make_and_list(As++Is);
+make_and_list([I|Is]) ->
+ [I|make_and_list(Is)];
+make_and_list([]) -> [].
+
+make_or_list([{'or',As}|Is]) ->
+ make_or_list(As++Is);
+make_or_list([I|Is]) ->
+ [I|make_or_list(Is)];
+make_or_list([]) -> [].
+
+%% Code generation for a boolean tree.
+
+bopt_cg({'not',Arg}, Fail, Acc, St) ->
+ I = bopt_cg_not(Arg),
+ bopt_cg(I, Fail, Acc, St);
+bopt_cg({'and',As}, Fail, Acc, St) ->
+ bopt_cg_and(As, Fail, Acc, St);
+bopt_cg({'or',As}, Fail, Acc, St0) ->
+ {Succ,St} = new_label(St0),
+ bopt_cg_or(As, Succ, Fail, Acc, St);
+bopt_cg({test,is_tuple_element,fail,[Tmp,Tuple,RecordTag]}, Fail, Acc, St) ->
+ {[{test,is_eq_exact,{f,Fail},[Tmp,RecordTag]},
+ {get_tuple_element,Tuple,0,Tmp}|Acc],St};
+bopt_cg({inverted_test,is_tuple_element,fail,[Tmp,Tuple,RecordTag]}, Fail, Acc, St) ->
+ {[{test,is_ne_exact,{f,Fail},[Tmp,RecordTag]},
+ {get_tuple_element,Tuple,0,Tmp}|Acc],St};
+bopt_cg({test,N,fail,As}, Fail, Acc, St) ->
+ Test = {test,N,{f,Fail},As},
+ {[Test|Acc],St};
+bopt_cg({inverted_test,N,fail,As}, Fail, Acc, St0) ->
+ {Lbl,St} = new_label(St0),
+ {[{label,Lbl},{jump,{f,Fail}},{test,N,{f,Lbl},As}|Acc],St};
+bopt_cg({protected,_,Bl0,{_,_,_}}, Fail, Acc, St0) ->
+ {Bl,St} = bopt_block_1(Bl0, Fail, St0),
+ {Bl++Acc,St};
+bopt_cg([_|_]=And, Fail, Acc, St) ->
+ bopt_cg_and(And, Fail, Acc, St).
+
+bopt_cg_not({'and',As0}) ->
+ As = [bopt_cg_not(A) || A <- As0],
+ {'or',As};
+bopt_cg_not({'or',As0}) ->
+ As = [bopt_cg_not(A) || A <- As0],
+ {'and',As};
+bopt_cg_not({test,Test,Fail,As}) ->
+ {inverted_test,Test,Fail,As}.
+
+bopt_cg_and([{atom,false}|_], Fail, _, St) ->
+ {[{jump,{f,Fail}}],St};
+bopt_cg_and([{atom,true}|Is], Fail, Acc, St) ->
+ bopt_cg_and(Is, Fail, Acc, St);
+bopt_cg_and([I|Is], Fail, Acc0, St0) ->
+ {Acc,St} = bopt_cg(I, Fail, Acc0, St0),
+ bopt_cg_and(Is, Fail, Acc, St);
+bopt_cg_and([], _, Acc, St) -> {Acc,St}.
+
+bopt_cg_or([I], Succ, Fail, Acc0, St0) ->
+ {Acc,St} = bopt_cg(I, Fail, Acc0, St0),
+ {[{label,Succ}|Acc],St};
+bopt_cg_or([I|Is], Succ, Fail, Acc0, St0) ->
+ {Lbl,St1} = new_label(St0),
+ {Acc,St} = bopt_cg(I, Lbl, Acc0, St1),
+ bopt_cg_or(Is, Succ, Fail, [{label,Lbl},{jump,{f,Succ}}|Acc], St).
+
+new_label(#st{next=LabelNum}=St) when is_integer(LabelNum) ->
+ {LabelNum,St#st{next=LabelNum+1}}.
+
+free_variables(Is) ->
+ E = gb_sets:empty(),
+ free_vars_1(Is, E, E).
+
+free_vars_1([{set,[Dst],As,{bif,_,_}}|Is], F0, N0) ->
+ F = gb_sets:union(F0, gb_sets:difference(var_list(As), N0)),
+ N = gb_sets:union(N0, var_list([Dst])),
+ free_vars_1(Is, F, N);
+free_vars_1([{protected,_,Pa,_}|Is], F, N) ->
+ free_vars_1(Pa++Is, F, N);
+free_vars_1([], F, _) ->
+ gb_trees:from_orddict([{K,any} || K <- gb_sets:to_list(F)]).
+
+var_list(Is) ->
+ var_list_1(Is, gb_sets:empty()).
+
+var_list_1([{x,_}=X|Is], D) ->
+ var_list_1(Is, gb_sets:add(X, D));
+var_list_1([_|Is], D) ->
+ var_list_1(Is, D);
+var_list_1([], D) -> D.
+
+%%%
+%%% Convert a block to Static Single Assignment (SSA) form.
+%%%
+
+-record(ssa,
+ {live,
+ sub}).
+
+ssa_block(Is0) ->
+ Next = ssa_first_free(Is0, 0),
+ {Is,_} = ssa_block_1(Is0, #ssa{live=Next,sub=gb_trees:empty()}, []),
+ Is.
+
+ssa_block_1([{protected,[_],Pa0,Pb}|Is], Sub0, Acc) ->
+ {Pa,Sub} = ssa_block_1(Pa0, Sub0, []),
+ Dst = ssa_last_target(Pa),
+ ssa_block_1(Is, Sub, [{protected,[Dst],Pa,Pb}|Acc]);
+ssa_block_1([{set,[Dst],As,Bif}|Is], Sub0, Acc0) ->
+ Sub1 = ssa_in_use_list(As, Sub0),
+ Sub = ssa_assign(Dst, Sub1),
+ Acc = [{set,[ssa_sub(Dst, Sub)],ssa_sub_list(As, Sub0),Bif}|Acc0],
+ ssa_block_1(Is, Sub, Acc);
+ssa_block_1([], Sub, Acc) -> {reverse(Acc),Sub}.
+
+ssa_in_use_list(As, Sub) ->
+ foldl(fun ssa_in_use/2, Sub, As).
+
+ssa_in_use({x,_}=R, #ssa{sub=Sub0}=Ssa) ->
+ case gb_trees:is_defined(R, Sub0) of
+ true -> Ssa;
+ false ->
+ Sub = gb_trees:insert(R, R, Sub0),
+ Ssa#ssa{sub=Sub}
+ end;
+ssa_in_use(_, Ssa) -> Ssa.
+
+ssa_assign({x,_}=R, #ssa{sub=Sub0}=Ssa0) ->
+ case gb_trees:is_defined(R, Sub0) of
+ false ->
+ Sub = gb_trees:insert(R, R, Sub0),
+ Ssa0#ssa{sub=Sub};
+ true ->
+ {NewReg,Ssa} = ssa_new_reg(Ssa0),
+ Sub1 = gb_trees:update(R, NewReg, Sub0),
+ Sub = gb_trees:insert(NewReg, NewReg, Sub1),
+ Ssa#ssa{sub=Sub}
+ end;
+ssa_assign(_, Ssa) -> Ssa.
+
+ssa_sub_list(List, Sub) ->
+ [ssa_sub(E, Sub) || E <- List].
+
+ssa_sub(R0, #ssa{sub=Sub}) ->
+ case gb_trees:lookup(R0, Sub) of
+ none -> R0;
+ {value,R} -> R
+ end.
+
+ssa_new_reg(#ssa{live=Reg}=Ssa) ->
+ {{x,Reg},Ssa#ssa{live=Reg+1}}.
+
+ssa_first_free([{protected,Ds,_,_}|Is], Next0) ->
+ Next = ssa_first_free_list(Ds, Next0),
+ ssa_first_free(Is, Next);
+ssa_first_free([{set,[Dst],As,_}|Is], Next0) ->
+ Next = ssa_first_free_list([Dst|As], Next0),
+ ssa_first_free(Is, Next);
+ssa_first_free([], Next) -> Next.
+
+ssa_first_free_list(Regs, Next) ->
+ foldl(fun({x,R}, N) when R >= N -> R+1;
+ (_, N) -> N end, Next, Regs).
+
+ssa_last_target([{set,[Dst],_,_},{'%live',_}]) -> Dst;
+ssa_last_target([{set,[Dst],_,_}]) -> Dst;
+ssa_last_target([_|Is]) -> ssa_last_target(Is).
+
+%% index_instructions(FunctionIs) -> GbTree([{Label,Is}])
+%% Index the instruction sequence so that we can quickly
+%% look up the instruction following a specific label.
+
+index_instructions(Is) ->
+ ii_1(Is, []).
+
+ii_1([{label,Lbl}|Is0], Acc) ->
+ Is = lists:dropwhile(fun({label,_}) -> true;
+ (_) -> false end, Is0),
+ ii_1(Is0, [{Lbl,Is}|Acc]);
+ii_1([_|Is], Acc) ->
+ ii_1(Is, Acc);
+ii_1([], Acc) -> gb_trees:from_orddict(sort(Acc)).
+
+%% is_killed(Register, [Instruction], State) -> true|false
+%% Determine whether a register is killed in the instruction sequence.
+%% The state is used to allow us to determine the kill state
+%% across branches.
+
+is_killed(R, Is, St) ->
+ case is_killed_1(R, Is, St) of
+ false ->
+ %%io:format("nk ~p: ~P\n", [R,Is,15]),
+ false;
+ true -> true
+ end.
+
+is_killed_1(R, [{block,Blk}|Is], St) ->
+ case is_killed_1(R, Blk, St) of
+ true -> true;
+ false -> is_killed_1(R, Is, St)
+ end;
+is_killed_1(R, [{test,_,{f,Fail},As}|Is], St) ->
+ case not member(R, As) andalso is_reg_killed_at(R, Fail, St) of
+ false -> false;
+ true -> is_killed_1(R, Is, St)
+ end;
+is_killed_1(R, [{select_val,R,_,_}|_], _) -> false;
+is_killed_1(R, [{select_val,_,Fail,{list,Branches}}|_], St) ->
+ is_killed_at_all(R, [Fail|Branches], St);
+is_killed_1(R, [{jump,{f,F}}|_], St) ->
+ is_reg_killed_at(R, F, St);
+is_killed_1(Reg, Is, _) ->
+ beam_block:is_killed(Reg, Is).
+
+is_reg_killed_at(R, Lbl, #st{ll=Ll}=St) ->
+ Is = gb_trees:get(Lbl, Ll),
+ is_killed_1(R, Is, St).
+
+is_killed_at_all(R, [{f,Lbl}|T], St) ->
+ case is_reg_killed_at(R, Lbl, St) of
+ false -> false;
+ true -> is_killed_at_all(R, T, St)
+ end;
+is_killed_at_all(R, [_|T], St) ->
+ is_killed_at_all(R, T, St);
+is_killed_at_all(_, [], _) -> true.
+
+%% is_not_used(Register, [Instruction], State) -> true|false
+%% Determine whether a register is never used in the instruction sequence
+%% (it could still referenced by an allocate instruction, meaning that
+%% it MUST be initialized).
+%% The state is used to allow us to determine the usage state
+%% across branches.
+
+is_not_used(R, Is, St) ->
+ case is_not_used_1(R, Is, St) of
+ false ->
+ %%io:format("used ~p: ~P\n", [R,Is,15]),
+ false;
+ true -> true
+ end.
+
+is_not_used_1(R, [{block,Blk}|Is], St) ->
+ case is_not_used_1(R, Blk, St) of
+ true -> true;
+ false -> is_not_used_1(R, Is, St)
+ end;
+is_not_used_1(R, [{test,_,{f,Fail},As}|Is], St) ->
+ case not member(R, As) andalso is_reg_not_used_at(R, Fail, St) of
+ false -> false;
+ true -> is_not_used_1(R, Is, St)
+ end;
+is_not_used_1(R, [{select_val,R,_,_}|_], _) -> false;
+is_not_used_1(R, [{select_val,_,Fail,{list,Branches}}|_], St) ->
+ is_used_at_none(R, [Fail|Branches], St);
+is_not_used_1(R, [{jump,{f,F}}|_], St) ->
+ is_reg_not_used_at(R, F, St);
+is_not_used_1(Reg, Is, _) ->
+ beam_block:is_not_used(Reg, Is).
+
+is_reg_not_used_at(R, Lbl, #st{ll=Ll}=St) ->
+ Is = gb_trees:get(Lbl, Ll),
+ is_not_used_1(R, Is, St).
+
+is_used_at_none(R, [{f,Lbl}|T], St) ->
+ case is_reg_not_used_at(R, Lbl, St) of
+ false -> false;
+ true -> is_used_at_none(R, T, St)
+ end;
+is_used_at_none(R, [_|T], St) ->
+ is_used_at_none(R, T, St);
+is_used_at_none(_, [], _) -> true.
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_clean.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_clean.erl
new file mode 100644
index 0000000000..04225e9bd0
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_clean.erl
@@ -0,0 +1,232 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: beam_clean.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
+%%
+%% Purpose : Clean up, such as removing unused labels and unused functions.
+
+-module(beam_clean).
+
+-export([module/2]).
+-import(lists, [member/2,map/2,foldl/3,mapfoldl/3,reverse/1]).
+
+module({Mod,Exp,Attr,Fs0,_}, _Opt) ->
+ Order = [Lbl || {function,_,_,Lbl,_} <- Fs0],
+ All = foldl(fun({function,_,_,Lbl,_}=Func,D) -> dict:store(Lbl, Func, D) end,
+ dict:new(), Fs0),
+ {WorkList,Used0} = exp_to_labels(Fs0, Exp),
+ Used = find_all_used(WorkList, All, Used0),
+ Fs1 = remove_unused(Order, Used, All),
+ {Fs,Lc} = clean_labels(Fs1),
+ {ok,{Mod,Exp,Attr,Fs,Lc}}.
+
+%% Convert the export list ({Name,Arity} pairs) to a list of entry labels.
+
+exp_to_labels(Fs, Exp) -> exp_to_labels(Fs, Exp, [], sets:new()).
+
+exp_to_labels([{function,Name,Arity,Lbl,_}|Fs], Exp, Acc, Used) ->
+ case member({Name,Arity}, Exp) of
+ true -> exp_to_labels(Fs, Exp, [Lbl|Acc], sets:add_element(Lbl, Used));
+ false -> exp_to_labels(Fs, Exp, Acc, Used)
+ end;
+exp_to_labels([], _, Acc, Used) -> {Acc,Used}.
+
+%% Remove the unused functions.
+
+remove_unused([F|Fs], Used, All) ->
+ case sets:is_element(F, Used) of
+ false -> remove_unused(Fs, Used, All);
+ true -> [dict:fetch(F, All)|remove_unused(Fs, Used, All)]
+ end;
+remove_unused([], _, _) -> [].
+
+%% Find all used functions.
+
+find_all_used([F|Fs0], All, Used0) ->
+ {function,_,_,_,Code} = dict:fetch(F, All),
+ {Fs,Used} = update_work_list(Code, {Fs0,Used0}),
+ find_all_used(Fs, All, Used);
+find_all_used([], _All, Used) -> Used.
+
+update_work_list([{call,_,{f,L}}|Is], Sets) ->
+ update_work_list(Is, add_to_work_list(L, Sets));
+update_work_list([{call_last,_,{f,L},_}|Is], Sets) ->
+ update_work_list(Is, add_to_work_list(L, Sets));
+update_work_list([{call_only,_,{f,L}}|Is], Sets) ->
+ update_work_list(Is, add_to_work_list(L, Sets));
+update_work_list([{make_fun,{f,L},_,_}|Is], Sets) ->
+ update_work_list(Is, add_to_work_list(L, Sets));
+update_work_list([{make_fun2,{f,L},_,_,_}|Is], Sets) ->
+ update_work_list(Is, add_to_work_list(L, Sets));
+update_work_list([_|Is], Sets) ->
+ update_work_list(Is, Sets);
+update_work_list([], Sets) -> Sets.
+
+add_to_work_list(F, {Fs,Used}=Sets) ->
+ case sets:is_element(F, Used) of
+ true -> Sets;
+ false -> {[F|Fs],sets:add_element(F, Used)}
+ end.
+
+
+%%%
+%%% Coalesce adjacent labels. Renumber all labels to eliminate gaps.
+%%% This cleanup will slightly reduce file size and slightly speed up loading.
+%%%
+%%% We also expand internal_is_record/3 to a sequence of instructions. It is done
+%%% here merely because this module will always be called even if optimization
+%%% is turned off. We don't want to do the expansion in beam_asm because we
+%%% want to see the expanded code in a .S file.
+%%%
+
+-record(st, {lmap, %Translation tables for labels.
+ entry, %Number of entry label.
+ lc %Label counter
+ }).
+
+clean_labels(Fs0) ->
+ St0 = #st{lmap=dict:new(),lc=1},
+ {Fs1,#st{lmap=Lmap,lc=Lc}} = mapfoldl(fun function_renumber/2, St0, Fs0),
+ {map(fun(F) -> function_replace(F, Lmap) end, Fs1),Lc}.
+
+function_renumber({function,Name,Arity,_Entry,Asm0}, St0) ->
+ {Asm,St} = renumber_labels(Asm0, [], St0),
+ {{function,Name,Arity,St#st.entry,Asm},St}.
+
+renumber_labels([{bif,internal_is_record,{f,_},
+ [Term,Tag,{integer,Arity}],Dst}|Is], Acc, St) ->
+ ContLabel = 900000000+2*St#st.lc,
+ FailLabel = ContLabel+1,
+ Fail = {f,FailLabel},
+ Tmp = Dst,
+ renumber_labels([{test,is_tuple,Fail,[Term]},
+ {test,test_arity,Fail,[Term,Arity]},
+ {get_tuple_element,Term,0,Tmp},
+ {test,is_eq_exact,Fail,[Tmp,Tag]},
+ {move,{atom,true},Dst},
+ {jump,{f,ContLabel}},
+ {label,FailLabel},
+ {move,{atom,false},Dst},
+ {label,ContLabel}|Is], Acc, St);
+renumber_labels([{test,internal_is_record,{f,_}=Fail,
+ [Term,Tag,{integer,Arity}]}|Is], Acc, St) ->
+ Tmp = {x,1023},
+ case Term of
+ {Reg,_} when Reg == x; Reg == y ->
+ renumber_labels([{test,is_tuple,Fail,[Term]},
+ {test,test_arity,Fail,[Term,Arity]},
+ {get_tuple_element,Term,0,Tmp},
+ {test,is_eq_exact,Fail,[Tmp,Tag]}|Is], Acc, St);
+ _ ->
+ renumber_labels([{jump,Fail}|Is], Acc, St)
+ end;
+renumber_labels([{label,Old}|Is], [{label,New}|_]=Acc, #st{lmap=D0}=St) ->
+ D = dict:store(Old, New, D0),
+ renumber_labels(Is, Acc, St#st{lmap=D});
+renumber_labels([{label,Old}|Is], Acc, St0) ->
+ New = St0#st.lc,
+ D = dict:store(Old, New, St0#st.lmap),
+ renumber_labels(Is, [{label,New}|Acc], St0#st{lmap=D,lc=New+1});
+renumber_labels([{func_info,_,_,_}=Fi|Is], Acc, St0) ->
+ renumber_labels(Is, [Fi|Acc], St0#st{entry=St0#st.lc});
+renumber_labels([I|Is], Acc, St0) ->
+ renumber_labels(Is, [I|Acc], St0);
+renumber_labels([], Acc, St0) -> {Acc,St0}.
+
+function_replace({function,Name,Arity,Entry,Asm0}, Dict) ->
+ Asm = case catch replace(Asm0, [], Dict) of
+ {'EXIT',_}=Reason ->
+ exit(Reason);
+ {error,{undefined_label,Lbl}=Reason} ->
+ io:format("Function ~s/~w refers to undefined label ~w\n",
+ [Name,Arity,Lbl]),
+ exit(Reason);
+ Asm1 when list(Asm1) -> Asm1
+ end,
+ {function,Name,Arity,Entry,Asm}.
+
+replace([{test,Test,{f,Lbl},Ops}|Is], Acc, D) ->
+ replace(Is, [{test,Test,{f,label(Lbl, D)},Ops}|Acc], D);
+replace([{select_val,R,{f,Fail0},{list,Vls0}}|Is], Acc, D) ->
+ Vls1 = map(fun ({f,L}) -> {f,label(L, D)};
+ (Other) -> Other end, Vls0),
+ Fail = label(Fail0, D),
+ case redundant_values(Vls1, Fail, []) of
+ [] ->
+ %% Oops, no choices left. The loader will not accept that.
+ %% Convert to a plain jump.
+ replace(Is, [{jump,{f,Fail}}|Acc], D);
+ Vls ->
+ replace(Is, [{select_val,R,{f,Fail},{list,Vls}}|Acc], D)
+ end;
+replace([{select_tuple_arity,R,{f,Fail},{list,Vls0}}|Is], Acc, D) ->
+ Vls = map(fun ({f,L}) -> {f,label(L, D)};
+ (Other) -> Other end, Vls0),
+ replace(Is, [{select_tuple_arity,R,{f,label(Fail, D)},{list,Vls}}|Acc], D);
+replace([{'try',R,{f,Lbl}}|Is], Acc, D) ->
+ replace(Is, [{'try',R,{f,label(Lbl, D)}}|Acc], D);
+replace([{'catch',R,{f,Lbl}}|Is], Acc, D) ->
+ replace(Is, [{'catch',R,{f,label(Lbl, D)}}|Acc], D);
+replace([{jump,{f,Lbl}}|Is], Acc, D) ->
+ replace(Is, [{jump,{f,label(Lbl, D)}}|Acc], D);
+replace([{loop_rec,{f,Lbl},R}|Is], Acc, D) ->
+ replace(Is, [{loop_rec,{f,label(Lbl, D)},R}|Acc], D);
+replace([{loop_rec_end,{f,Lbl}}|Is], Acc, D) ->
+ replace(Is, [{loop_rec_end,{f,label(Lbl, D)}}|Acc], D);
+replace([{wait,{f,Lbl}}|Is], Acc, D) ->
+ replace(Is, [{wait,{f,label(Lbl, D)}}|Acc], D);
+replace([{wait_timeout,{f,Lbl},To}|Is], Acc, D) ->
+ replace(Is, [{wait_timeout,{f,label(Lbl, D)},To}|Acc], D);
+replace([{bif,Name,{f,Lbl},As,R}|Is], Acc, D) when Lbl =/= 0 ->
+ replace(Is, [{bif,Name,{f,label(Lbl, D)},As,R}|Acc], D);
+replace([{call,Ar,{f,Lbl}}|Is], Acc, D) ->
+ replace(Is, [{call,Ar,{f,label(Lbl,D)}}|Acc], D);
+replace([{call_last,Ar,{f,Lbl},N}|Is], Acc, D) ->
+ replace(Is, [{call_last,Ar,{f,label(Lbl,D)},N}|Acc], D);
+replace([{call_only,Ar,{f,Lbl}}|Is], Acc, D) ->
+ replace(Is, [{call_only,Ar,{f,label(Lbl, D)}}|Acc], D);
+replace([{make_fun,{f,Lbl},U1,U2}|Is], Acc, D) ->
+ replace(Is, [{make_fun,{f,label(Lbl, D)},U1,U2}|Acc], D);
+replace([{make_fun2,{f,Lbl},U1,U2,U3}|Is], Acc, D) ->
+ replace(Is, [{make_fun2,{f,label(Lbl, D)},U1,U2,U3}|Acc], D);
+replace([{bs_init2,{f,Lbl},Sz,Words,R,F,Dst}|Is], Acc, D) when Lbl =/= 0 ->
+ replace(Is, [{bs_init2,{f,label(Lbl, D)},Sz,Words,R,F,Dst}|Acc], D);
+replace([{bs_put_integer,{f,Lbl},Bits,Unit,Fl,Val}|Is], Acc, D) when Lbl =/= 0 ->
+ replace(Is, [{bs_put_integer,{f,label(Lbl, D)},Bits,Unit,Fl,Val}|Acc], D);
+replace([{bs_put_binary,{f,Lbl},Bits,Unit,Fl,Val}|Is], Acc, D) when Lbl =/= 0 ->
+ replace(Is, [{bs_put_binary,{f,label(Lbl, D)},Bits,Unit,Fl,Val}|Acc], D);
+replace([{bs_put_float,{f,Lbl},Bits,Unit,Fl,Val}|Is], Acc, D) when Lbl =/= 0 ->
+ replace(Is, [{bs_put_float,{f,label(Lbl, D)},Bits,Unit,Fl,Val}|Acc], D);
+replace([{bs_final,{f,Lbl},R}|Is], Acc, D) when Lbl =/= 0 ->
+ replace(Is, [{bs_final,{f,label(Lbl, D)},R}|Acc], D);
+replace([{bs_add,{f,Lbl},Src,Dst}|Is], Acc, D) when Lbl =/= 0 ->
+ replace(Is, [{bs_add,{f,label(Lbl, D)},Src,Dst}|Acc], D);
+replace([{bs_bits_to_bytes,{f,Lbl},Bits,Dst}|Is], Acc, D) when Lbl =/= 0 ->
+ replace(Is, [{bs_bits_to_bytes,{f,label(Lbl, D)},Bits,Dst}|Acc], D);
+replace([I|Is], Acc, D) ->
+ replace(Is, [I|Acc], D);
+replace([], Acc, _) -> Acc.
+
+label(Old, D) ->
+ case dict:find(Old, D) of
+ {ok,Val} -> Val;
+ error -> throw({error,{undefined_label,Old}})
+ end.
+
+redundant_values([_,{f,Fail}|Vls], Fail, Acc) ->
+ redundant_values(Vls, Fail, Acc);
+redundant_values([Val,Lbl|Vls], Fail, Acc) ->
+ redundant_values(Vls, Fail, [Lbl,Val|Acc]);
+redundant_values([], _, Acc) -> reverse(Acc).
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_dict.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_dict.erl
new file mode 100644
index 0000000000..08eca2fc00
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_dict.erl
@@ -0,0 +1,196 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: beam_dict.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
+%%
+%% Purpose : Maintain atom, import, and export tables for assembler.
+
+-module(beam_dict).
+
+-export([new/0, opcode/2, highest_opcode/1,
+ atom/2, local/4, export/4, import/4, string/2, lambda/5,
+ atom_table/1, local_table/1, export_table/1, import_table/1,
+ string_table/1,lambda_table/1]).
+
+-record(asm_dict,
+ {atoms = [], % [{Index, Atom}]
+ exports = [], % [{F, A, Label}]
+ locals = [], % [{F, A, Label}]
+ imports = [], % [{Index, {M, F, A}]
+ strings = [], % Deep list of characters
+ lambdas = [], % [{...}]
+ next_atom = 1,
+ next_import = 0,
+ string_offset = 0,
+ highest_opcode = 0
+ }).
+
+new() ->
+ #asm_dict{}.
+
+%% Remembers highest opcode.
+
+opcode(Op, Dict) when Dict#asm_dict.highest_opcode > Op -> Dict;
+opcode(Op, Dict) -> Dict#asm_dict{highest_opcode=Op}.
+
+%% Returns the highest opcode encountered.
+
+highest_opcode(#asm_dict{highest_opcode=Op}) -> Op.
+
+%% Returns the index for an atom (adding it to the atom table if necessary).
+%% atom(Atom, Dict) -> {Index, Dict'}
+
+atom(Atom, Dict) when atom(Atom) ->
+ NextIndex = Dict#asm_dict.next_atom,
+ case lookup_store(Atom, Dict#asm_dict.atoms, NextIndex) of
+ {Index, _, NextIndex} ->
+ {Index, Dict};
+ {Index, Atoms, NewIndex} ->
+ {Index, Dict#asm_dict{atoms=Atoms, next_atom=NewIndex}}
+ end.
+
+%% Remembers an exported function.
+%% export(Func, Arity, Label, Dict) -> Dict'
+
+export(Func, Arity, Label, Dict0) when atom(Func), integer(Arity), integer(Label) ->
+ {Index, Dict1} = atom(Func, Dict0),
+ Dict1#asm_dict{exports = [{Index, Arity, Label}| Dict1#asm_dict.exports]}.
+
+%% Remembers a local function.
+%% local(Func, Arity, Label, Dict) -> Dict'
+
+local(Func, Arity, Label, Dict0) when atom(Func), integer(Arity), integer(Label) ->
+ {Index,Dict1} = atom(Func, Dict0),
+ Dict1#asm_dict{locals = [{Index,Arity,Label}| Dict1#asm_dict.locals]}.
+
+%% Returns the index for an import entry (adding it to the import table if necessary).
+%% import(Mod, Func, Arity, Dict) -> {Index, Dict'}
+
+import(Mod, Func, Arity, Dict) when atom(Mod), atom(Func), integer(Arity) ->
+ NextIndex = Dict#asm_dict.next_import,
+ case lookup_store({Mod, Func, Arity}, Dict#asm_dict.imports, NextIndex) of
+ {Index, _, NextIndex} ->
+ {Index, Dict};
+ {Index, Imports, NewIndex} ->
+ {_, D1} = atom(Mod, Dict#asm_dict{imports=Imports, next_import=NewIndex}),
+ {_, D2} = atom(Func, D1),
+ {Index, D2}
+ end.
+
+%% Returns the index for a string in the string table (adding the string to the
+%% table if necessary).
+%% string(String, Dict) -> {Offset, Dict'}
+
+string(Str, Dict) when list(Str) ->
+ #asm_dict{strings = Strings, string_offset = NextOffset} = Dict,
+ case old_string(Str, Strings) of
+ {true, Offset} ->
+ {Offset, Dict};
+ false ->
+ NewDict = Dict#asm_dict{strings = Strings++Str,
+ string_offset = NextOffset+length(Str)},
+ {NextOffset, NewDict}
+ end.
+
+%% Returns the index for a funentry (adding it to the table if necessary).
+%% lambda(Dict, Lbl, Index, Uniq, NumFree) -> {Index,Dict'}
+
+lambda(Lbl, Index, OldUniq, NumFree, #asm_dict{lambdas=Lambdas0}=Dict) ->
+ OldIndex = length(Lambdas0),
+ Lambdas = [{Lbl,{OldIndex,Lbl,Index,NumFree,OldUniq}}|Lambdas0],
+ {OldIndex,Dict#asm_dict{lambdas=Lambdas}}.
+
+%% Returns the atom table.
+%% atom_table(Dict) -> [Length,AtomString...]
+
+atom_table(#asm_dict{atoms=Atoms, next_atom=NumAtoms}) ->
+ Sorted = lists:sort(Atoms),
+ Fun = fun({_, A}) ->
+ L = atom_to_list(A),
+ [length(L)|L]
+ end,
+ {NumAtoms-1, lists:map(Fun, Sorted)}.
+
+%% Returns the table of local functions.
+%% local_table(Dict) -> {NumLocals, [{Function, Arity, Label}...]}
+
+local_table(#asm_dict{locals = Locals}) ->
+ {length(Locals),Locals}.
+
+%% Returns the export table.
+%% export_table(Dict) -> {NumExports, [{Function, Arity, Label}...]}
+
+export_table(#asm_dict{exports = Exports}) ->
+ {length(Exports), Exports}.
+
+%% Returns the import table.
+%% import_table(Dict) -> {NumImports, [{Module, Function, Arity}...]}
+
+import_table(Dict) ->
+ #asm_dict{imports = Imports, next_import = NumImports} = Dict,
+ Sorted = lists:sort(Imports),
+ Fun = fun({_, {Mod, Func, Arity}}) ->
+ {Atom0, _} = atom(Mod, Dict),
+ {Atom1, _} = atom(Func, Dict),
+ {Atom0, Atom1, Arity}
+ end,
+ {NumImports, lists:map(Fun, Sorted)}.
+
+string_table(#asm_dict{strings = Strings, string_offset = Size}) ->
+ {Size, Strings}.
+
+lambda_table(#asm_dict{locals=Loc0,lambdas=Lambdas0}) ->
+ Lambdas1 = sofs:relation(Lambdas0),
+ Loc = sofs:relation([{Lbl,{F,A}} || {F,A,Lbl} <- Loc0]),
+ Lambdas2 = sofs:relative_product1(Lambdas1, Loc),
+ Lambdas = [<<F:32,A:32,Lbl:32,Index:32,NumFree:32,OldUniq:32>> ||
+ {{_,Lbl,Index,NumFree,OldUniq},{F,A}} <- sofs:to_external(Lambdas2)],
+ {length(Lambdas),Lambdas}.
+
+%%% Local helper functions.
+
+lookup_store(Key, Dict, NextIndex) ->
+ case catch lookup_store1(Key, Dict, NextIndex) of
+ Index when integer(Index) ->
+ {Index, Dict, NextIndex};
+ {Index, NewDict} ->
+ {Index, NewDict, NextIndex+1}
+ end.
+
+lookup_store1(Key, [Pair|Dict], NextIndex) when Key > element(2, Pair) ->
+ {Index, NewDict} = lookup_store1(Key, Dict, NextIndex),
+ {Index, [Pair|NewDict]};
+lookup_store1(Key, [{Index, Key}|_Dict], _NextIndex) ->
+ throw(Index);
+lookup_store1(Key, Dict, NextIndex) ->
+ {NextIndex, [{NextIndex, Key}|Dict]}.
+
+%% Search for string Str in the string pool Pool.
+%% old_string(Str, Pool) -> false | {true, Offset}
+
+old_string(Str, Pool) ->
+ old_string(Str, Pool, 0).
+
+old_string([C|Str], [C|Pool], Index) ->
+ case lists:prefix(Str, Pool) of
+ true ->
+ {true, Index};
+ false ->
+ old_string([C|Str], Pool, Index+1)
+ end;
+old_string(Str, [_|Pool], Index) ->
+ old_string(Str, Pool, Index+1);
+old_string(_Str, [], _Index) ->
+ false.
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_disasm.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_disasm.erl
new file mode 100644
index 0000000000..0108f91b7f
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_disasm.erl
@@ -0,0 +1,964 @@
+%% -*- erlang-indent-level: 4 -*-
+%%=======================================================================
+%% File : beam_disasm.erl
+%% Author : Kostis Sagonas
+%% Description : Disassembles an R5-R10 .beam file into symbolic BEAM code
+%%=======================================================================
+%% $Id: beam_disasm.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
+%%=======================================================================
+%% Notes:
+%% 1. It does NOT work for .beam files of previous BEAM versions.
+%% 2. If handling of new BEAM instructions is needed, this should be
+%% inserted at the end of function resolve_inst().
+%%=======================================================================
+
+-module(beam_disasm).
+
+-export([file/1, format_error/1]).
+
+-author("Kostis Sagonas").
+
+-include("beam_opcodes.hrl").
+
+%%-----------------------------------------------------------------------
+
+-define(NO_DEBUG(Str,Xs),ok).
+-define(DEBUG(Str,Xs),io:format(Str,Xs)).
+-define(exit(Reason),exit({?MODULE,?LINE,Reason})).
+
+%%-----------------------------------------------------------------------
+%% Error information
+
+format_error({error, Module, Error}) ->
+ Module:format_error(Error);
+format_error({internal, Error}) ->
+ io_lib:format("~p: disassembly failed with reason ~P.",
+ [?MODULE, Error, 25]).
+
+%%-----------------------------------------------------------------------
+%% The main exported function
+%% File is either a file name or a binary containing the code.
+%% Returns `{beam_file, [...]}' or `{error, Module, Reason}'.
+%% Call `format_error({error, Module, Reason})' for an error string.
+%%-----------------------------------------------------------------------
+
+file(File) ->
+ case beam_lib:info(File) of
+ Info when list(Info) ->
+ {value,{chunks,Chunks}} = lists:keysearch(chunks,1,Info),
+ case catch process_chunks(File, Chunks) of
+ {'EXIT', Error} ->
+ {error, ?MODULE, {internal, Error}};
+ Result ->
+ Result
+ end;
+ Error ->
+ Error
+ end.
+
+%%-----------------------------------------------------------------------
+%% Interface might need to be revised -- do not depend on it.
+%%-----------------------------------------------------------------------
+
+process_chunks(F,ChunkInfoList) ->
+ {ok,{_,Chunks}} = beam_lib:chunks(F, ["Atom","Code","StrT","ImpT","ExpT"]),
+ [{"Atom",AtomBin},{"Code",CodeBin},{"StrT",StrBin},
+ {"ImpT",ImpBin},{"ExpT",ExpBin}] = Chunks,
+ LambdaBin = optional_chunk(F, "FunT", ChunkInfoList),
+ LocBin = optional_chunk(F, "LocT", ChunkInfoList),
+ AttrBin = optional_chunk(F, "Attr", ChunkInfoList),
+ CompBin = optional_chunk(F, "CInf", ChunkInfoList),
+ Atoms = beam_disasm_atoms(AtomBin),
+ Exports = beam_disasm_exports(ExpBin, Atoms),
+ Imports = beam_disasm_imports(ImpBin, Atoms),
+ LocFuns = beam_disasm_exports(LocBin, Atoms),
+ Lambdas = beam_disasm_lambdas(LambdaBin, Atoms),
+ Str = beam_disasm_strings(StrBin),
+ Str1 = binary_to_list(Str), %% for debugging -- use Str as far as poss.
+ Sym_Code = beam_disasm_code(CodeBin,Atoms,Imports,Str,Lambdas),
+ Attributes = beam_disasm_attributes(AttrBin),
+ CompInfo = beam_disasm_compilation_info(CompBin),
+ All = [{exports,Exports},
+ {imports,Imports},
+ {code,Sym_Code},
+ {atoms,Atoms},
+ {local_funs,LocFuns},
+ {strings,Str1},
+ {attributes,Attributes},
+ {comp_info,CompInfo}],
+ {beam_file,[Item || {_Key,Data}=Item <- All, Data =/= none]}.
+
+%%-----------------------------------------------------------------------
+%% Retrieve an optional chunk or none if the chunk doesn't exist.
+%%-----------------------------------------------------------------------
+
+optional_chunk(F, ChunkTag, ChunkInfo) ->
+ case lists:keymember(ChunkTag, 1, ChunkInfo) of
+ true ->
+ {ok,{_,[{ChunkTag,Chunk}]}} = beam_lib:chunks(F, [ChunkTag]),
+ Chunk;
+ false -> none
+ end.
+
+%%-----------------------------------------------------------------------
+%% UTILITIES -- these actually exist in file "beam_lib"
+%% -- they should be moved into a common utils file.
+%%-----------------------------------------------------------------------
+
+i32([X1,X2,X3,X4]) ->
+ (X1 bsl 24) bor (X2 bsl 16) bor (X3 bsl 8) bor X4.
+
+get_int(B) ->
+ {I, B1} = split_binary(B, 4),
+ {i32(binary_to_list(I)), B1}.
+
+%%-----------------------------------------------------------------------
+%% Disassembles the atom table of a BEAM file.
+%% - atoms are stored in order 1 ... N (N = Num_atoms, in fact),
+%% - each atom name consists of a length byte, followed by that many
+%% bytes of name
+%% (nb: atom names max 255 chars?!)
+%%-----------------------------------------------------------------------
+
+beam_disasm_atoms(AtomTabBin) ->
+ {_NumAtoms,B} = get_int(AtomTabBin),
+ disasm_atoms(B).
+
+disasm_atoms(AtomBin) ->
+ disasm_atoms(binary_to_list(AtomBin),1).
+
+disasm_atoms([Len|Xs],N) ->
+ {AtomName,Rest} = get_atom_name(Len,Xs),
+ [{N,list_to_atom(AtomName)}|disasm_atoms(Rest,N+1)];
+disasm_atoms([],_) ->
+ [].
+
+get_atom_name(Len,Xs) ->
+ get_atom_name(Len,Xs,[]).
+
+get_atom_name(N,[X|Xs],RevName) when N > 0 ->
+ get_atom_name(N-1,Xs,[X|RevName]);
+get_atom_name(0,Xs,RevName) ->
+ { lists:reverse(RevName), Xs }.
+
+%%-----------------------------------------------------------------------
+%% Disassembles the export table of a BEAM file.
+%%-----------------------------------------------------------------------
+
+beam_disasm_exports(none, _) -> none;
+beam_disasm_exports(ExpTabBin, Atoms) ->
+ {_NumAtoms,B} = get_int(ExpTabBin),
+ disasm_exports(B,Atoms).
+
+disasm_exports(Bin,Atoms) ->
+ resolve_exports(collect_exports(binary_to_list(Bin)),Atoms).
+
+collect_exports([F3,F2,F1,F0,A3,A2,A1,A0,L3,L2,L1,L0|Exps]) ->
+ [{i32([F3,F2,F1,F0]), % F = function (atom ID)
+ i32([A3,A2,A1,A0]), % A = arity (int)
+ i32([L3,L2,L1,L0])} % L = label (int)
+ |collect_exports(Exps)];
+collect_exports([]) ->
+ [].
+
+resolve_exports(Exps,Atoms) ->
+ [ {lookup_key(F,Atoms), A, L} || {F,A,L} <- Exps ].
+
+%%-----------------------------------------------------------------------
+%% Disassembles the import table of a BEAM file.
+%%-----------------------------------------------------------------------
+
+beam_disasm_imports(ExpTabBin,Atoms) ->
+ {_NumAtoms,B} = get_int(ExpTabBin),
+ disasm_imports(B,Atoms).
+
+disasm_imports(Bin,Atoms) ->
+ resolve_imports(collect_imports(binary_to_list(Bin)),Atoms).
+
+collect_imports([M3,M2,M1,M0,F3,F2,F1,F0,A3,A2,A1,A0|Exps]) ->
+ [{i32([M3,M2,M1,M0]), % M = module (atom ID)
+ i32([F3,F2,F1,F0]), % F = function (atom ID)
+ i32([A3,A2,A1,A0])} % A = arity (int)
+ |collect_imports(Exps)];
+collect_imports([]) ->
+ [].
+
+resolve_imports(Exps,Atoms) ->
+ [{extfunc,lookup_key(M,Atoms),lookup_key(F,Atoms),A} || {M,F,A} <- Exps ].
+
+%%-----------------------------------------------------------------------
+%% Disassembles the lambda (fun) table of a BEAM file.
+%%-----------------------------------------------------------------------
+
+beam_disasm_lambdas(none, _) -> none;
+beam_disasm_lambdas(<<_:32,Tab/binary>>, Atoms) ->
+ disasm_lambdas(Tab, Atoms, 0).
+
+disasm_lambdas(<<F:32,A:32,Lbl:32,Index:32,NumFree:32,OldUniq:32,More/binary>>,
+ Atoms, OldIndex) ->
+ Info = {lookup_key(F, Atoms),A,Lbl,Index,NumFree,OldUniq},
+ [{OldIndex,Info}|disasm_lambdas(More, Atoms, OldIndex+1)];
+disasm_lambdas(<<>>, _, _) -> [].
+
+%%-----------------------------------------------------------------------
+%% Disassembles the code chunk of a BEAM file:
+%% - The code is first disassembled into a long list of instructions.
+%% - This list is then split into functions and all names are resolved.
+%%-----------------------------------------------------------------------
+
+beam_disasm_code(CodeBin,Atoms,Imports,Str,Lambdas) ->
+ [_SS3,_SS2,_SS1,_SS0, % Sub-Size (length of information before code)
+ _IS3,_IS2,_IS1,_IS0, % Instruction Set Identifier (always 0)
+ _OM3,_OM2,_OM1,_OM0, % Opcode Max
+ _L3,_L2,_L1,_L0,_F3,_F2,_F1,_F0|Code] = binary_to_list(CodeBin),
+ case catch disasm_code(Code, Atoms) of
+ {'EXIT',Rsn} ->
+ ?NO_DEBUG('code disasm failed: ~p~n',[Rsn]),
+ ?exit(Rsn);
+ DisasmCode ->
+ Functions = get_function_chunks(DisasmCode),
+ LocLabels = local_labels(Functions),
+ [resolve_names(F,Imports,Str,LocLabels,Lambdas) || F <- Functions]
+ end.
+
+%%-----------------------------------------------------------------------
+
+disasm_code([B|Bs], Atoms) ->
+ {Instr,RestBs} = disasm_instr(B, Bs, Atoms),
+ [Instr|disasm_code(RestBs, Atoms)];
+disasm_code([], _) -> [].
+
+%%-----------------------------------------------------------------------
+%% Splits the code stream into chunks representing the code of functions.
+%%
+%% NOTE: code actually looks like
+%% label L1: ... label Ln:
+%% func_info ...
+%% label entry:
+%% ...
+%% <on failure, use label Li to show where things died>
+%% ...
+%% So the labels before each func_info should be included as well.
+%% Ideally, only one such label is needed, but the BEAM compiler
+%% before R8 didn't care to remove the redundant ones.
+%%-----------------------------------------------------------------------
+
+get_function_chunks([I|Code]) ->
+ {LastI,RestCode,Labs} = split_head_labels(I,Code,[]),
+ get_funs(LastI,RestCode,Labs,[]);
+get_function_chunks([]) ->
+ ?exit(empty_code_segment).
+
+get_funs(PrevI,[I|Is],RevF,RevFs) ->
+ case I of
+ {func_info,_Info} ->
+ [H|T] = RevF,
+ {Last,Fun,TrailingLabels} = split_head_labels(H,T,[]),
+ get_funs(I, Is, [PrevI|TrailingLabels], add_funs([Last|Fun],RevFs));
+ _ ->
+ get_funs(I, Is, [PrevI|RevF], RevFs)
+ end;
+get_funs(PrevI,[],RevF,RevFs) ->
+ case PrevI of
+ {int_code_end,[]} ->
+ emit_funs(add_fun(RevF,RevFs));
+ _ ->
+ ?DEBUG('warning: code segment did not end with int_code_end~n',[]),
+ emit_funs(add_funs([PrevI|RevF],RevFs))
+ end.
+
+split_head_labels({label,L},[I|Code],Labs) ->
+ split_head_labels(I,Code,[{label,L}|Labs]);
+split_head_labels(I,Code,Labs) ->
+ {I,Code,Labs}.
+
+add_fun([],Fs) ->
+ Fs;
+add_fun(F,Fs) ->
+ add_funs(F,Fs).
+
+add_funs(F,Fs) ->
+ [ lists:reverse(F) | Fs ].
+
+emit_funs(Fs) ->
+ lists:reverse(Fs).
+
+%%-----------------------------------------------------------------------
+%% Collects local labels -- I am not sure this is 100% what is needed.
+%%-----------------------------------------------------------------------
+
+local_labels(Funs) ->
+ [local_label(Fun) || Fun <- Funs].
+
+%% The first clause below attempts to provide some (limited form of)
+%% backwards compatibility; it is not needed for .beam files generated
+%% by the R8 compiler. The clause should one fine day be taken out.
+local_label([{label,_},{label,L}|Code]) ->
+ local_label([{label,L}|Code]);
+local_label([{label,_},
+ {func_info,[M0,F0,{u,A}]},
+ {label,[{u,L1}]}|_]) ->
+ {atom,M} = resolve_arg(M0),
+ {atom,F} = resolve_arg(F0),
+ {L1, {M, F, A}};
+local_label(Code) ->
+ io:format('beam_disasm: no label in ~p~n', [Code]),
+ {-666,{none,none,0}}.
+
+%%-----------------------------------------------------------------------
+%% Disassembles a single BEAM instruction; most instructions are handled
+%% in a generic way; indexing instructions are handled separately.
+%%-----------------------------------------------------------------------
+
+disasm_instr(B, Bs, Atoms) ->
+ {SymOp,Arity} = beam_opcodes:opname(B),
+ case SymOp of
+ select_val ->
+ disasm_select_inst(select_val, Bs, Atoms);
+ select_tuple_arity ->
+ disasm_select_inst(select_tuple_arity, Bs, Atoms);
+ _ ->
+ case catch decode_n_args(Arity, Bs, Atoms) of
+ {'EXIT',Rsn} ->
+ ?NO_DEBUG("decode_n_args(~p,~p) failed~n",[Arity,Bs]),
+ {{'EXIT',{SymOp,Arity,Rsn}},[]};
+ {Args,RestBs} ->
+ ?NO_DEBUG("instr ~p~n",[{SymOp,Args}]),
+ {{SymOp,Args}, RestBs}
+ end
+ end.
+
+%%-----------------------------------------------------------------------
+%% Disassembles a BEAM select_* instruction used for indexing.
+%% Currently handles {select_val,3} and {select_tuple_arity,3} insts.
+%%
+%% The arruments of a "select"-type instruction look as follows:
+%% <reg>, {f,FailLabel}, {list, <num cases>, [<case1> ... <caseN>]}
+%% where each case is of the form [symbol,{f,Label}].
+%%-----------------------------------------------------------------------
+
+disasm_select_inst(Inst, Bs, Atoms) ->
+ {X, Bs1} = decode_arg(Bs, Atoms),
+ {F, Bs2} = decode_arg(Bs1, Atoms),
+ {Z, Bs3} = decode_arg(Bs2, Atoms),
+ {U, Bs4} = decode_arg(Bs3, Atoms),
+ {u,Len} = U,
+ {List, RestBs} = decode_n_args(Len, Bs4, Atoms),
+ {{Inst,[X,F,{Z,U,List}]},RestBs}.
+
+%%-----------------------------------------------------------------------
+%% decode_arg([Byte]) -> { Arg, [Byte] }
+%%
+%% - an arg can have variable length, so we must return arg + remaining bytes
+%% - decodes an argument into its 'raw' form: { Tag, Value }
+%% several types map to a single tag, so the byte code instr must then
+%% assign a type to it
+%%-----------------------------------------------------------------------
+
+decode_arg([B|Bs]) ->
+ Tag = decode_tag(B band 2#111),
+ ?NO_DEBUG('Tag = ~p, B = ~p, Bs = ~p~n',[Tag,B,Bs]),
+ case Tag of
+ z ->
+ decode_z_tagged(Tag, B, Bs);
+ _ ->
+ %% all other cases are handled as if they were integers
+ decode_int(Tag, B, Bs)
+ end.
+
+decode_arg([B|Bs0], Atoms) ->
+ Tag = decode_tag(B band 2#111),
+ ?NO_DEBUG('Tag = ~p, B = ~p, Bs = ~p~n',[Tag,B,Bs]),
+ case Tag of
+ z ->
+ decode_z_tagged(Tag, B, Bs0);
+ a ->
+ %% atom or nil
+ case decode_int(Tag, B, Bs0) of
+ {{a,0},Bs} -> {nil,Bs};
+ {{a,I},Bs} -> {{atom,lookup_key(I, Atoms)},Bs}
+ end;
+ _ ->
+ %% all other cases are handled as if they were integers
+ decode_int(Tag, B, Bs0)
+ end.
+
+%%-----------------------------------------------------------------------
+%% Decodes an integer value. Handles positives, negatives, and bignums.
+%%
+%% Tries to do the opposite of:
+%% beam_asm:encode(1, 5) = [81]
+%% beam_asm:encode(1, 1000) = [105,232]
+%% beam_asm:encode(1, 2047) = [233,255]
+%% beam_asm:encode(1, 2048) = [25,8,0]
+%% beam_asm:encode(1,-1) = [25,255,255]
+%% beam_asm:encode(1,-4294967295) = [121,255,0,0,0,1]
+%% beam_asm:encode(1, 4294967295) = [121,0,255,255,255,255]
+%% beam_asm:encode(1, 429496729501) = [121,99,255,255,255,157]
+%%-----------------------------------------------------------------------
+
+decode_int(Tag,B,Bs) when (B band 16#08) == 0 ->
+ %% N < 16 = 4 bits, NNNN:0:TTT
+ N = B bsr 4,
+ {{Tag,N},Bs};
+decode_int(Tag,B,Bs) when (B band 16#10) == 0 ->
+ %% N < 2048 = 11 bits = 3:8 bits, NNN:01:TTT, NNNNNNNN
+ [B1|Bs1] = Bs,
+ Val0 = B band 2#11100000,
+ N = (Val0 bsl 3) bor B1,
+ ?NO_DEBUG('NNN:01:TTT, NNNNNNNN = ~n~p:01:~p, ~p = ~p~n', [Val0,Tag,B,N]),
+ {{Tag,N},Bs1};
+decode_int(Tag,B,Bs) ->
+ {Len,Bs1} = decode_int_length(B,Bs),
+ {IntBs,RemBs} = take_bytes(Len,Bs1),
+ N = build_arg(IntBs),
+ [F|_] = IntBs,
+ Num = if F > 127, Tag == i -> decode_negative(N,Len);
+ true -> N
+ end,
+ ?NO_DEBUG('Len = ~p, IntBs = ~p, Num = ~p~n', [Len,IntBs,Num]),
+ {{Tag,Num},RemBs}.
+
+decode_int_length(B,Bs) ->
+ %% The following imitates get_erlang_integer() in beam_load.c
+ %% Len is the size of the integer value in bytes
+ case B bsr 5 of
+ 7 ->
+ {Arg,ArgBs} = decode_arg(Bs),
+ case Arg of
+ {u,L} ->
+ {L+9,ArgBs}; % 9 stands for 7+2
+ _ ->
+ ?exit({decode_int,weird_bignum_sublength,Arg})
+ end;
+ L ->
+ {L+2,Bs}
+ end.
+
+decode_negative(N,Len) ->
+ N - (1 bsl (Len*8)). % 8 is number of bits in a byte
+
+%%-----------------------------------------------------------------------
+%% Decodes lists and floating point numbers.
+%%-----------------------------------------------------------------------
+
+decode_z_tagged(Tag,B,Bs) when (B band 16#08) == 0 ->
+ N = B bsr 4,
+ case N of
+ 0 -> % float
+ decode_float(Bs);
+ 1 -> % list
+ {{Tag,N},Bs};
+ 2 -> % fr
+ decode_fr(Bs);
+ 3 -> % allocation list
+ decode_alloc_list(Bs);
+ _ ->
+ ?exit({decode_z_tagged,{invalid_extended_tag,N}})
+ end;
+decode_z_tagged(_,B,_) ->
+ ?exit({decode_z_tagged,{weird_value,B}}).
+
+decode_float(Bs) ->
+ {FL,RestBs} = take_bytes(8,Bs),
+ <<Float:64/float>> = list_to_binary(FL),
+ {{float,Float},RestBs}.
+
+decode_fr(Bs) ->
+ {{u,Fr},RestBs} = decode_arg(Bs),
+ {{fr,Fr},RestBs}.
+
+decode_alloc_list(Bs) ->
+ {{u,N},RestBs} = decode_arg(Bs),
+ decode_alloc_list_1(N, RestBs, []).
+
+decode_alloc_list_1(0, RestBs, Acc) ->
+ {{u,{alloc,lists:reverse(Acc)}},RestBs};
+decode_alloc_list_1(N, Bs0, Acc) ->
+ {{u,Type},Bs1} = decode_arg(Bs0),
+ {{u,Val},Bs} = decode_arg(Bs1),
+ case Type of
+ 0 ->
+ decode_alloc_list_1(N-1, Bs, [{words,Val}|Acc]);
+ 1 ->
+ decode_alloc_list_1(N-1, Bs, [{floats,Val}|Acc])
+ end.
+
+%%-----------------------------------------------------------------------
+%% take N bytes from a stream, return { Taken_bytes, Remaining_bytes }
+%%-----------------------------------------------------------------------
+
+take_bytes(N,Bs) ->
+ take_bytes(N,Bs,[]).
+
+take_bytes(N,[B|Bs],Acc) when N > 0 ->
+ take_bytes(N-1,Bs,[B|Acc]);
+take_bytes(0,Bs,Acc) ->
+ { lists:reverse(Acc), Bs }.
+
+%%-----------------------------------------------------------------------
+%% from a list of bytes Bn,Bn-1,...,B1,B0
+%% build (Bn << 8*n) bor ... bor B1 << 8 bor B0 << 0
+%%-----------------------------------------------------------------------
+
+build_arg(Bs) ->
+ build_arg(Bs,0).
+
+build_arg([B|Bs],N) ->
+ build_arg(Bs, (N bsl 8) bor B);
+build_arg([],N) ->
+ N.
+
+%%-----------------------------------------------------------------------
+%% Decodes a bunch of arguments and returns them in a list
+%%-----------------------------------------------------------------------
+
+decode_n_args(N, Bs, Atoms) when N >= 0 ->
+ decode_n_args(N, [], Bs, Atoms).
+
+decode_n_args(N, Acc, Bs0, Atoms) when N > 0 ->
+ {A1,Bs} = decode_arg(Bs0, Atoms),
+ decode_n_args(N-1, [A1|Acc], Bs, Atoms);
+decode_n_args(0, Acc, Bs, _) ->
+ {lists:reverse(Acc),Bs}.
+
+%%-----------------------------------------------------------------------
+%% Convert a numeric tag value into a symbolic one
+%%-----------------------------------------------------------------------
+
+decode_tag(?tag_u) -> u;
+decode_tag(?tag_i) -> i;
+decode_tag(?tag_a) -> a;
+decode_tag(?tag_x) -> x;
+decode_tag(?tag_y) -> y;
+decode_tag(?tag_f) -> f;
+decode_tag(?tag_h) -> h;
+decode_tag(?tag_z) -> z;
+decode_tag(X) -> ?exit({unknown_tag,X}).
+
+%%-----------------------------------------------------------------------
+%% - replace all references {a,I} with the atom with index I (or {atom,A})
+%% - replace all references to {i,K} in an external call position with
+%% the proper MFA (position in list, first elt = 0, yields MFA to use)
+%% - resolve strings, represented as <offset, length>, into their
+%% actual values by using string table
+%% (note: string table should be passed as a BINARY so that we can
+%% use binary_to_list/3!)
+%% - convert instruction to its readable form ...
+%%
+%% Currently, only the first three are done (systematically, at least).
+%%
+%% Note: It MAY be premature to remove the lists of args, since that
+%% representation means it is simpler to iterate over all args, etc.
+%%-----------------------------------------------------------------------
+
+resolve_names(Fun, Imports, Str, Lbls, Lambdas) ->
+ [resolve_inst(Instr, Imports, Str, Lbls, Lambdas) || Instr <- Fun].
+
+%%
+%% New make_fun2/4 instruction added in August 2001 (R8).
+%% We handle it specially here to avoid adding an argument to
+%% the clause for every instruction.
+%%
+
+resolve_inst({make_fun2,Args},_,_,Lbls,Lambdas) ->
+ [OldIndex] = resolve_args(Args),
+ {value,{OldIndex,{F,A,_Lbl,_Index,NumFree,OldUniq}}} =
+ lists:keysearch(OldIndex, 1, Lambdas),
+ [{_,{M,_,_}}|_] = Lbls, % Slighly kludgy.
+ {make_fun2,{M,F,A},OldIndex,OldUniq,NumFree};
+resolve_inst(Instr, Imports, Str, Lbls, _Lambdas) ->
+ resolve_inst(Instr, Imports, Str, Lbls).
+
+resolve_inst({label,[{u,L}]},_,_,_) ->
+ {label,L};
+resolve_inst({func_info,RawMFA},_,_,_) ->
+ {func_info,resolve_args(RawMFA)};
+% resolve_inst(int_code_end,_,_,_,_) -> % instruction already handled
+% int_code_end; % should not really be handled here
+resolve_inst({call,[{u,N},{f,L}]},_,_,Lbls) ->
+ {call,N,catch lookup_key(L,Lbls)};
+resolve_inst({call_last,[{u,N},{f,L},{u,U}]},_,_,Lbls) ->
+ {call_last,N,catch lookup_key(L,Lbls),U};
+resolve_inst({call_only,[{u,N},{f,L}]},_,_,Lbls) ->
+ {call_only,N,catch lookup_key(L,Lbls)};
+resolve_inst({call_ext,[{u,N},{u,MFAix}]},Imports,_,_) ->
+ {call_ext,N,catch lists:nth(MFAix+1,Imports)};
+resolve_inst({call_ext_last,[{u,N},{u,MFAix},{u,X}]},Imports,_,_) ->
+ {call_ext_last,N,catch lists:nth(MFAix+1,Imports),X};
+resolve_inst({bif0,Args},Imports,_,_) ->
+ [Bif,Reg] = resolve_args(Args),
+ {extfunc,_Mod,BifName,_Arity} = lists:nth(Bif+1,Imports),
+ %?NO_DEBUG('bif0(~p, ~p)~n',[BifName,Reg]),
+ {bif,BifName,nofail,[],Reg};
+resolve_inst({bif1,Args},Imports,_,_) ->
+ [F,Bif,A1,Reg] = resolve_args(Args),
+ {extfunc,_Mod,BifName,_Arity} = lists:nth(Bif+1,Imports),
+ %?NO_DEBUG('bif1(~p, ~p, ~p, ~p, ~p)~n',[Bif,BifName,F,[A1],Reg]),
+ {bif,BifName,F,[A1],Reg};
+resolve_inst({bif2,Args},Imports,_,_) ->
+ [F,Bif,A1,A2,Reg] = resolve_args(Args),
+ {extfunc,_Mod,BifName,_Arity} = lists:nth(Bif+1,Imports),
+ %?NO_DEBUG('bif2(~p, ~p, ~p, ~p, ~p)~n',[Bif,BifName,F,[A1,A2],Reg]),
+ {bif,BifName,F,[A1,A2],Reg};
+resolve_inst({allocate,[{u,X0},{u,X1}]},_,_,_) ->
+ {allocate,X0,X1};
+resolve_inst({allocate_heap,[{u,X0},{u,X1},{u,X2}]},_,_,_) ->
+ {allocate_heap,X0,X1,X2};
+resolve_inst({allocate_zero,[{u,X0},{u,X1}]},_,_,_) ->
+ {allocate_zero,X0,X1};
+resolve_inst({allocate_heap_zero,[{u,X0},{u,X1},{u,X2}]},_,_,_) ->
+ {allocate_heap_zero,X0,X1,X2};
+resolve_inst({test_heap,[{u,X0},{u,X1}]},_,_,_) ->
+ {test_heap,X0,X1};
+resolve_inst({init,[Dst]},_,_,_) ->
+ {init,Dst};
+resolve_inst({deallocate,[{u,L}]},_,_,_) ->
+ {deallocate,L};
+resolve_inst({return,[]},_,_,_) ->
+ return;
+resolve_inst({send,[]},_,_,_) ->
+ send;
+resolve_inst({remove_message,[]},_,_,_) ->
+ remove_message;
+resolve_inst({timeout,[]},_,_,_) ->
+ timeout;
+resolve_inst({loop_rec,[Lbl,Dst]},_,_,_) ->
+ {loop_rec,Lbl,Dst};
+resolve_inst({loop_rec_end,[Lbl]},_,_,_) ->
+ {loop_rec_end,Lbl};
+resolve_inst({wait,[Lbl]},_,_,_) ->
+ {wait,Lbl};
+resolve_inst({wait_timeout,[Lbl,Int]},_,_,_) ->
+ {wait_timeout,Lbl,resolve_arg(Int)};
+resolve_inst({m_plus,Args},_,_,_) ->
+ [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
+ {arithbif,'+',W,[SrcR1,SrcR2],DstR};
+resolve_inst({m_minus,Args},_,_,_) ->
+ [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
+ {arithbif,'-',W,[SrcR1,SrcR2],DstR};
+resolve_inst({m_times,Args},_,_,_) ->
+ [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
+ {arithbif,'*',W,[SrcR1,SrcR2],DstR};
+resolve_inst({m_div,Args},_,_,_) ->
+ [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
+ {arithbif,'/',W,[SrcR1,SrcR2],DstR};
+resolve_inst({int_div,Args},_,_,_) ->
+ [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
+ {arithbif,'div',W,[SrcR1,SrcR2],DstR};
+resolve_inst({int_rem,Args},_,_,_) ->
+ [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
+ {arithbif,'rem',W,[SrcR1,SrcR2],DstR};
+resolve_inst({int_band,Args},_,_,_) ->
+ [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
+ {arithbif,'band',W,[SrcR1,SrcR2],DstR};
+resolve_inst({int_bor,Args},_,_,_) ->
+ [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
+ {arithbif,'bor',W,[SrcR1,SrcR2],DstR};
+resolve_inst({int_bxor,Args},_,_,_) ->
+ [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
+ {arithbif,'bxor',W,[SrcR1,SrcR2],DstR};
+resolve_inst({int_bsl,Args},_,_,_) ->
+ [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
+ {arithbif,'bsl',W,[SrcR1,SrcR2],DstR};
+resolve_inst({int_bsr,Args},_,_,_) ->
+ [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
+ {arithbif,'bsr',W,[SrcR1,SrcR2],DstR};
+resolve_inst({int_bnot,Args},_,_,_) ->
+ [W,SrcR,DstR] = resolve_args(Args),
+ {arithbif,'bnot',W,[SrcR],DstR};
+resolve_inst({is_lt=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({is_ge=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({is_eq=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({is_ne=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({is_eq_exact=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({is_ne_exact=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({is_integer=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({is_float=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({is_number=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({is_atom=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({is_pid=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({is_reference=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({is_port=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({is_nil=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({is_binary=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({is_constant=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({is_list=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({is_nonempty_list=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({is_tuple=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({test_arity=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({select_val,Args},_,_,_) ->
+ [Reg,FLbl,{{z,1},{u,_Len},List0}] = Args,
+ List = resolve_args(List0),
+ {select_val,Reg,FLbl,{list,List}};
+resolve_inst({select_tuple_arity,Args},_,_,_) ->
+ [Reg,FLbl,{{z,1},{u,_Len},List0}] = Args,
+ List = resolve_args(List0),
+ {select_tuple_arity,Reg,FLbl,{list,List}};
+resolve_inst({jump,[Lbl]},_,_,_) ->
+ {jump,Lbl};
+resolve_inst({'catch',[Dst,Lbl]},_,_,_) ->
+ {'catch',Dst,Lbl};
+resolve_inst({catch_end,[Dst]},_,_,_) ->
+ {catch_end,Dst};
+resolve_inst({move,[Src,Dst]},_,_,_) ->
+ {move,resolve_arg(Src),Dst};
+resolve_inst({get_list,[Src,Dst1,Dst2]},_,_,_) ->
+ {get_list,Src,Dst1,Dst2};
+resolve_inst({get_tuple_element,[Src,{u,Off},Dst]},_,_,_) ->
+ {get_tuple_element,resolve_arg(Src),Off,resolve_arg(Dst)};
+resolve_inst({set_tuple_element,[Src,Dst,{u,Off}]},_,_,_) ->
+ {set_tuple_element,resolve_arg(Src),resolve_arg(Dst),Off};
+resolve_inst({put_string,[{u,Len},{u,Off},Dst]},_,Strings,_) ->
+ String = if Len > 0 -> binary_to_list(Strings, Off+1, Off+Len);
+ true -> ""
+ end,
+?NO_DEBUG('put_string(~p, {string,~p}, ~p)~n',[Len,String,Dst]),
+ {put_string,Len,{string,String},Dst};
+resolve_inst({put_list,[Src1,Src2,Dst]},_,_,_) ->
+ {put_list,resolve_arg(Src1),resolve_arg(Src2),Dst};
+resolve_inst({put_tuple,[{u,Arity},Dst]},_,_,_) ->
+ {put_tuple,Arity,Dst};
+resolve_inst({put,[Src]},_,_,_) ->
+ {put,resolve_arg(Src)};
+resolve_inst({badmatch,[X]},_,_,_) ->
+ {badmatch,resolve_arg(X)};
+resolve_inst({if_end,[]},_,_,_) ->
+ if_end;
+resolve_inst({case_end,[X]},_,_,_) ->
+ {case_end,resolve_arg(X)};
+resolve_inst({call_fun,[{u,N}]},_,_,_) ->
+ {call_fun,N};
+resolve_inst({make_fun,Args},_,_,Lbls) ->
+ [{f,L},Magic,FreeVars] = resolve_args(Args),
+ {make_fun,catch lookup_key(L,Lbls),Magic,FreeVars};
+resolve_inst({is_function=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+resolve_inst({call_ext_only,[{u,N},{u,MFAix}]},Imports,_,_) ->
+ {call_ext_only,N,catch lists:nth(MFAix+1,Imports)};
+%%
+%% Instructions for handling binaries added in R7A & R7B
+%%
+resolve_inst({bs_start_match,[F,Reg]},_,_,_) ->
+ {bs_start_match,F,Reg};
+resolve_inst({bs_get_integer=I,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
+ [A2,A5] = resolve_args([Arg2,Arg5]),
+ {test,I,Lbl,[A2,N,decode_field_flags(U),A5]};
+resolve_inst({bs_get_float=I,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
+ [A2,A5] = resolve_args([Arg2,Arg5]),
+ {test,I,Lbl,[A2,N,decode_field_flags(U),A5]};
+resolve_inst({bs_get_binary=I,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
+ [A2,A5] = resolve_args([Arg2,Arg5]),
+ {test,I,Lbl,[A2,N,decode_field_flags(U),A5]};
+resolve_inst({bs_skip_bits,[Lbl,Arg2,{u,N},{u,U}]},_,_,_) ->
+ [A2] = resolve_args([Arg2]),
+ {test,bs_skip_bits,Lbl,[A2,N,decode_field_flags(U)]};
+resolve_inst({bs_test_tail,[F,{u,N}]},_,_,_) ->
+ {test,bs_test_tail,F,[N]};
+resolve_inst({bs_save,[{u,N}]},_,_,_) ->
+ {bs_save,N};
+resolve_inst({bs_restore,[{u,N}]},_,_,_) ->
+ {bs_restore,N};
+resolve_inst({bs_init,[{u,N},{u,U}]},_,_,_) ->
+ {bs_init,N,decode_field_flags(U)};
+resolve_inst({bs_final,[F,X]},_,_,_) ->
+ {bs_final,F,X};
+resolve_inst({bs_put_integer,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
+ [A2,A5] = resolve_args([Arg2,Arg5]),
+ {bs_put_integer,Lbl,A2,N,decode_field_flags(U),A5};
+resolve_inst({bs_put_binary,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
+ [A2,A5] = resolve_args([Arg2,Arg5]),
+ ?NO_DEBUG('bs_put_binary(~p,~p,~p,~p,~p})~n',[Lbl,A2,N,U,A5]),
+ {bs_put_binary,Lbl,A2,N,decode_field_flags(U),A5};
+resolve_inst({bs_put_float,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
+ [A2,A5] = resolve_args([Arg2,Arg5]),
+ ?NO_DEBUG('bs_put_float(~p,~p,~p,~p,~p})~n',[Lbl,A2,N,U,A5]),
+ {bs_put_float,Lbl,A2,N,decode_field_flags(U),A5};
+resolve_inst({bs_put_string,[{u,Len},{u,Off}]},_,Strings,_) ->
+ String = if Len > 0 -> binary_to_list(Strings, Off+1, Off+Len);
+ true -> ""
+ end,
+ ?NO_DEBUG('bs_put_string(~p, {string,~p})~n',[Len,String]),
+ {bs_put_string,Len,{string,String}};
+resolve_inst({bs_need_buf,[{u,N}]},_,_,_) ->
+ {bs_need_buf,N};
+
+%%
+%% Instructions for handling floating point numbers added in June 2001 (R8).
+%%
+resolve_inst({fclearerror,[]},_,_,_) ->
+ fclearerror;
+resolve_inst({fcheckerror,Args},_,_,_) ->
+ [Fail] = resolve_args(Args),
+ {fcheckerror,Fail};
+resolve_inst({fmove,Args},_,_,_) ->
+ [FR,Reg] = resolve_args(Args),
+ {fmove,FR,Reg};
+resolve_inst({fconv,Args},_,_,_) ->
+ [Reg,FR] = resolve_args(Args),
+ {fconv,Reg,FR};
+resolve_inst({fadd=I,Args},_,_,_) ->
+ [F,A1,A2,Reg] = resolve_args(Args),
+ {arithfbif,I,F,[A1,A2],Reg};
+resolve_inst({fsub=I,Args},_,_,_) ->
+ [F,A1,A2,Reg] = resolve_args(Args),
+ {arithfbif,I,F,[A1,A2],Reg};
+resolve_inst({fmul=I,Args},_,_,_) ->
+ [F,A1,A2,Reg] = resolve_args(Args),
+ {arithfbif,I,F,[A1,A2],Reg};
+resolve_inst({fdiv=I,Args},_,_,_) ->
+ [F,A1,A2,Reg] = resolve_args(Args),
+ {arithfbif,I,F,[A1,A2],Reg};
+resolve_inst({fnegate,Args},_,_,_) ->
+ [F,Arg,Reg] = resolve_args(Args),
+ {arithfbif,fnegate,F,[Arg],Reg};
+
+%%
+%% Instructions for try expressions added in January 2003 (R10).
+%%
+
+resolve_inst({'try',[Reg,Lbl]},_,_,_) -> % analogous to 'catch'
+ {'try',Reg,Lbl};
+resolve_inst({try_end,[Reg]},_,_,_) -> % analogous to 'catch_end'
+ {try_end,Reg};
+resolve_inst({try_case,[Reg]},_,_,_) -> % analogous to 'catch_end'
+ {try_case,Reg};
+resolve_inst({try_case_end,[Reg]},_,_,_) ->
+ {try_case_end,Reg};
+resolve_inst({raise,[Reg1,Reg2]},_,_,_) ->
+ {bif,raise,{f,0},[Reg1,Reg2],{x,0}};
+
+%%
+%% New bit syntax instructions added in February 2004 (R10B).
+%%
+
+resolve_inst({bs_init2,[Lbl,Arg2,{u,W},{u,R},{u,F},Arg6]},_,_,_) ->
+ [A2,A6] = resolve_args([Arg2,Arg6]),
+ {bs_init2,Lbl,A2,W,R,decode_field_flags(F),A6};
+resolve_inst({bs_bits_to_bytes,[Lbl,Arg2,Arg3]},_,_,_) ->
+ [A2,A3] = resolve_args([Arg2,Arg3]),
+ {bs_bits_to_bytes,Lbl,A2,A3};
+resolve_inst({bs_add=I,[Lbl,Arg2,Arg3,Arg4,Arg5]},_,_,_) ->
+ [A2,A3,A4,A5] = resolve_args([Arg2,Arg3,Arg4,Arg5]),
+ {I,Lbl,[A2,A3,A4],A5};
+
+%%
+%% New apply instructions added in April 2004 (R10B).
+%%
+resolve_inst({apply,[{u,Arity}]},_,_,_) ->
+ {apply,Arity};
+resolve_inst({apply_last,[{u,Arity},{u,D}]},_,_,_) ->
+ {apply_last,Arity,D};
+
+%%
+%% New test instruction added in April 2004 (R10B).
+%%
+resolve_inst({is_boolean=I,Args0},_,_,_) ->
+ [L|Args] = resolve_args(Args0),
+ {test,I,L,Args};
+
+%%
+%% Catches instructions that are not yet handled.
+%%
+
+resolve_inst(X,_,_,_) -> ?exit({resolve_inst,X}).
+
+%%-----------------------------------------------------------------------
+%% Resolves arguments in a generic way.
+%%-----------------------------------------------------------------------
+
+resolve_args(Args) -> [resolve_arg(A) || A <- Args].
+
+resolve_arg({u,N}) -> N;
+resolve_arg({i,N}) -> {integer,N};
+resolve_arg({atom,Atom}=A) when is_atom(Atom) -> A;
+resolve_arg(nil) -> nil;
+resolve_arg(Arg) -> Arg.
+
+%%-----------------------------------------------------------------------
+%% The purpose of the following is just to add a hook for future changes.
+%% Currently, field flags are numbers 1-2-4-8 and only two of these
+%% numbers (BSF_LITTLE 2 -- BSF_SIGNED 4) have a semantic significance;
+%% others are just hints for speeding up the execution; see "erl_bits.h".
+%%-----------------------------------------------------------------------
+
+decode_field_flags(FF) ->
+ {field_flags,FF}.
+
+%%-----------------------------------------------------------------------
+%% Each string is denoted in the assembled code by its offset into this
+%% binary. This binary contains all strings concatenated together.
+%%-----------------------------------------------------------------------
+
+beam_disasm_strings(Bin) ->
+ Bin.
+
+%%-----------------------------------------------------------------------
+%% Disassembles the attributes of a BEAM file.
+%%-----------------------------------------------------------------------
+
+beam_disasm_attributes(none) -> none;
+beam_disasm_attributes(AttrBin) -> binary_to_term(AttrBin).
+
+%%-----------------------------------------------------------------------
+%% Disassembles the compilation information of a BEAM file.
+%%-----------------------------------------------------------------------
+
+beam_disasm_compilation_info(none) -> none;
+beam_disasm_compilation_info(Bin) -> binary_to_term(Bin).
+
+%%-----------------------------------------------------------------------
+%% Private Utilities
+%%-----------------------------------------------------------------------
+
+%%-----------------------------------------------------------------------
+
+lookup_key(Key,[{Key,Val}|_]) ->
+ Val;
+lookup_key(Key,[_|KVs]) ->
+ lookup_key(Key,KVs);
+lookup_key(Key,[]) ->
+ ?exit({lookup_key,{key_not_found,Key}}).
+
+%%-----------------------------------------------------------------------
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_flatten.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_flatten.erl
new file mode 100644
index 0000000000..5c08c6a797
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_flatten.erl
@@ -0,0 +1,137 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: beam_flatten.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
+%%
+%% Purpose : Converts intermediate assembly code to final format.
+
+-module(beam_flatten).
+
+-export([module/2]).
+-import(lists, [reverse/1,reverse/2,map/2]).
+
+module({Mod,Exp,Attr,Fs,Lc}, _Opt) ->
+ {ok,{Mod,Exp,Attr,map(fun function/1, Fs),Lc}}.
+
+function({function,Name,Arity,CLabel,Is0}) ->
+ Is1 = block(Is0),
+ Is = opt(Is1),
+ {function,Name,Arity,CLabel,Is}.
+
+block(Is) ->
+ block(Is, []).
+
+block([{block,Is0}|Is1], Acc) -> block(Is1, norm_block(Is0, Acc));
+block([I|Is], Acc) -> block(Is, [I|Acc]);
+block([], Acc) -> reverse(Acc).
+
+norm_block([{allocate,R,Alloc}|Is], Acc0) ->
+ case insert_alloc_in_bs_init(Acc0, Alloc) of
+ not_possible ->
+ norm_block(Is, reverse(norm_allocate(Alloc, R), Acc0));
+ Acc ->
+ norm_block(Is, Acc)
+ end;
+norm_block([I|Is], Acc) -> norm_block(Is, [norm(I)|Acc]);
+norm_block([], Acc) -> Acc.
+
+norm({set,[D],As,{bif,N}}) -> {bif,N,nofail,As,D};
+norm({set,[D],As,{bif,N,F}}) -> {bif,N,F,As,D};
+norm({set,[D],[S],move}) -> {move,S,D};
+norm({set,[D],[S],fmove}) -> {fmove,S,D};
+norm({set,[D],[S],fconv}) -> {fconv,S,D};
+norm({set,[D],[S1,S2],put_list}) -> {put_list,S1,S2,D};
+norm({set,[D],[],{put_tuple,A}}) -> {put_tuple,A,D};
+norm({set,[],[S],put}) -> {put,S};
+norm({set,[D],[],{put_string,L,S}}) -> {put_string,L,S,D};
+norm({set,[D],[S],{get_tuple_element,I}}) -> {get_tuple_element,S,I,D};
+norm({set,[],[S,D],{set_tuple_element,I}}) -> {set_tuple_element,S,D,I};
+norm({set,[D1,D2],[S],get_list}) -> {get_list,S,D1,D2};
+norm({set,[],[],remove_message}) -> remove_message;
+norm({set,[],[],fclearerror}) -> fclearerror;
+norm({set,[],[],fcheckerror}) -> {fcheckerror,{f,0}};
+norm({'%',_}=Comment) -> Comment;
+norm({'%live',R}) -> {'%live',R}.
+
+norm_allocate({_Zero,nostack,Nh,[]}, Regs) ->
+ [{test_heap,Nh,Regs}];
+norm_allocate({_Zero,nostack,Nh,Nf,[]}, Regs) ->
+ [{test_heap,alloc_list(Nh, Nf),Regs}];
+norm_allocate({zero,0,Nh,[]}, Regs) ->
+ norm_allocate({nozero,0,Nh,[]}, Regs);
+norm_allocate({zero,0,Nh,Nf,[]}, Regs) ->
+ norm_allocate({nozero,0,Nh,Nf,[]}, Regs);
+norm_allocate({zero,Ns,0,[]}, Regs) ->
+ [{allocate_zero,Ns,Regs}];
+norm_allocate({zero,Ns,Nh,[]}, Regs) ->
+ [{allocate_heap_zero,Ns,Nh,Regs}];
+norm_allocate({nozero,Ns,0,Inits}, Regs) ->
+ [{allocate,Ns,Regs}|Inits];
+norm_allocate({nozero,Ns,Nh,Inits}, Regs) ->
+ [{allocate_heap,Ns,Nh,Regs}|Inits];
+norm_allocate({nozero,Ns,Nh,Floats,Inits}, Regs) ->
+ [{allocate_heap,Ns,alloc_list(Nh, Floats),Regs}|Inits];
+norm_allocate({zero,Ns,Nh,Floats,Inits}, Regs) ->
+ [{allocate_heap_zero,Ns,alloc_list(Nh, Floats),Regs}|Inits].
+
+insert_alloc_in_bs_init([I|_]=Is, Alloc) ->
+ case is_bs_put(I) of
+ false ->
+ not_possible;
+ true ->
+ insert_alloc_1(Is, Alloc, [])
+ end.
+
+insert_alloc_1([{bs_init2,Fail,Bs,Ws,Regs,F,Dst}|Is], {_,nostack,Nh,Nf,[]}, Acc) ->
+ Al = alloc_list(Ws+Nh, Nf),
+ I = {bs_init2,Fail,Bs,Al,Regs,F,Dst},
+ reverse(Acc, [I|Is]);
+insert_alloc_1([I|Is], Alloc, Acc) ->
+ insert_alloc_1(Is, Alloc, [I|Acc]).
+
+is_bs_put({bs_put_integer,_,_,_,_,_}) -> true;
+is_bs_put({bs_put_float,_,_,_,_,_}) -> true;
+is_bs_put({bs_put_binary,_,_,_,_,_}) -> true;
+is_bs_put({bs_put_string,_,_}) -> true;
+is_bs_put(_) -> false.
+
+alloc_list(Words, Floats) ->
+ {alloc,[{words,Words},{floats,Floats}]}.
+
+
+%% opt(Is0) -> Is
+%% Simple peep-hole optimization to move a {move,Any,{x,0}} past
+%% any kill up to the next call instruction.
+
+opt(Is) ->
+ opt_1(Is, []).
+
+opt_1([{move,_,{x,0}}=I|Is0], Acc0) ->
+ case move_past_kill(Is0, I, Acc0) of
+ impossible -> opt_1(Is0, [I|Acc0]);
+ {Is,Acc} -> opt_1(Is, Acc)
+ end;
+opt_1([I|Is], Acc) ->
+ opt_1(Is, [I|Acc]);
+opt_1([], Acc) -> reverse(Acc).
+
+move_past_kill([{'%live',_}|Is], Move, Acc) ->
+ move_past_kill(Is, Move, Acc);
+move_past_kill([{kill,Src}|_], {move,Src,_}, _) ->
+ impossible;
+move_past_kill([{kill,_}=I|Is], Move, Acc) ->
+ move_past_kill(Is, Move, [I|Acc]);
+move_past_kill(Is, Move, Acc) ->
+ {Is,[Move|Acc]}.
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_jump.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_jump.erl
new file mode 100644
index 0000000000..b3c234c7bb
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_jump.erl
@@ -0,0 +1,477 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: beam_jump.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
+%%
+%%% Purpose : Optimise jumps and remove unreachable code.
+
+-module(beam_jump).
+
+-export([module/2,module_labels/1,
+ is_unreachable_after/1,remove_unused_labels/1]).
+
+%%% The following optimisations are done:
+%%%
+%%% (1) This code with two identical instruction sequences
+%%%
+%%% L1: <Instruction sequence>
+%%% L2:
+%%% . . .
+%%% L3: <Instruction sequence>
+%%% L4:
+%%%
+%%% can be replaced with
+%%%
+%%% L1: jump L3
+%%% L2:
+%%% . . .
+%%% L3: <Instruction sequence>
+%%% L4
+%%%
+%%% Note: The instruction sequence must end with an instruction
+%%% such as a jump that never transfers control to the instruction
+%%% following it.
+%%%
+%%% (2) case_end, if_end, and badmatch, and function calls that cause an
+%%% exit (such as calls to exit/1) are moved to the end of the function.
+%%% The purpose is to allow further optimizations at the place from
+%%% which the code was moved.
+%%%
+%%% (3) Any unreachable code is removed. Unreachable code is code after
+%%% jump, call_last and other instructions which never transfer control
+%%% to the following instruction. Code is unreachable up to the next
+%%% *referenced* label. Note that the optimisations below might
+%%% generate more possibilities for removing unreachable code.
+%%%
+%%% (4) This code:
+%%% L1: jump L2
+%%% . . .
+%%% L2: ...
+%%%
+%%% will be changed to
+%%%
+%%% jump L2
+%%% . . .
+%%% L1:
+%%% L2: ...
+%%%
+%%% If the jump is unreachable, it will be removed according to (1).
+%%%
+%%% (5) In
+%%%
+%%% jump L1
+%%% L1:
+%%%
+%%% the jump will be removed.
+%%%
+%%% (6) If test instructions are used to skip a single jump instruction,
+%%% the test is inverted and the jump is eliminated (provided that
+%%% the test can be inverted). Example:
+%%%
+%%% is_eq L1 {x,1} {x,2}
+%%% jump L2
+%%% L1:
+%%%
+%%% will be changed to
+%%%
+%%% is_ne L2 {x,1} {x,2}
+%%%
+%%% (The label L1 will be retained if there were previous references to it.)
+%%%
+%%% (7) Some redundant uses of is_boolean/1 is optimized away.
+%%%
+%%% Terminology note: The optimisation done here is called unreachable-code
+%%% elimination, NOT dead-code elimination. Dead code elimination
+%%% means the removal of instructions that are executed, but have no visible
+%%% effect on the program state.
+%%%
+
+-import(lists, [reverse/1,reverse/2,map/2,mapfoldl/3,foldl/3,
+ last/1,foreach/2,member/2]).
+
+module({Mod,Exp,Attr,Fs0,Lc}, _Opt) ->
+ Fs = map(fun function/1, Fs0),
+ {ok,{Mod,Exp,Attr,Fs,Lc}}.
+
+module_labels({Mod,Exp,Attr,Fs,Lc}) ->
+ {Mod,Exp,Attr,map(fun function_labels/1, Fs),Lc}.
+
+function_labels({function,Name,Arity,CLabel,Asm0}) ->
+ Asm = remove_unused_labels(Asm0),
+ {function,Name,Arity,CLabel,Asm}.
+
+function({function,Name,Arity,CLabel,Asm0}) ->
+ Asm1 = share(Asm0),
+ Asm2 = bopt(Asm1),
+ Asm3 = move(Asm2),
+ Asm4 = opt(Asm3, CLabel),
+ Asm = remove_unused_labels(Asm4),
+ {function,Name,Arity,CLabel,Asm}.
+
+%%%
+%%% (1) We try to share the code for identical code segments by replacing all
+%%% occurrences except the last with jumps to the last occurrence.
+%%%
+
+share(Is) ->
+ share_1(reverse(Is), gb_trees:empty(), [], []).
+
+share_1([{label,_}=Lbl|Is], Dict, [], Acc) ->
+ share_1(Is, Dict, [], [Lbl|Acc]);
+share_1([{label,L}=Lbl|Is], Dict0, Seq, Acc) ->
+ case is_unreachable_after(last(Seq)) of
+ false ->
+ share_1(Is, Dict0, [], [Lbl|Seq ++ Acc]);
+ true ->
+ case gb_trees:lookup(Seq, Dict0) of
+ none ->
+ Dict = gb_trees:insert(Seq, L, Dict0),
+ share_1(Is, Dict, [], [Lbl|Seq ++ Acc]);
+ {value,Label} ->
+ share_1(Is, Dict0, [], [Lbl,{jump,{f,Label}}|Acc])
+ end
+ end;
+share_1([{func_info,_,_,_}=I|Is], _, [], Acc) ->
+ Is++[I|Acc];
+share_1([I|Is], Dict, Seq, Acc) ->
+ case is_unreachable_after(I) of
+ false ->
+ share_1(Is, Dict, [I|Seq], Acc);
+ true ->
+ share_1(Is, Dict, [I], Acc)
+ end.
+
+%%%
+%%% (2) Move short code sequences ending in an instruction that causes an exit
+%%% to the end of the function.
+%%%
+
+move(Is) ->
+ move_1(Is, [], []).
+
+move_1([I|Is], End, Acc) ->
+ case is_exit_instruction(I) of
+ false -> move_1(Is, End, [I|Acc]);
+ true -> move_2(I, Is, End, Acc)
+ end;
+move_1([], End, Acc) ->
+ reverse(Acc, reverse(End)).
+
+move_2(Exit, Is, End, [{block,_},{label,_},{func_info,_,_,_}|_]=Acc) ->
+ move_1(Is, End, [Exit|Acc]);
+move_2(Exit, Is, End, [{kill,_Y}|Acc]) ->
+ move_2(Exit, Is, End, Acc);
+move_2(Exit, Is, End, [{block,_}=Blk,{label,_}=Lbl,Dead|More]=Acc) ->
+ case is_unreachable_after(Dead) of
+ false ->
+ move_1(Is, End, [Exit|Acc]);
+ true ->
+ move_1([Dead|Is], [Exit,Blk,Lbl|End], More)
+ end;
+move_2(Exit, Is, End, [{label,_}=Lbl,Dead|More]=Acc) ->
+ case is_unreachable_after(Dead) of
+ false ->
+ move_1(Is, End, [Exit|Acc]);
+ true ->
+ move_1([Dead|Is], [Exit,Lbl|End], More)
+ end;
+move_2(Exit, Is, End, Acc) ->
+ move_1(Is, End, [Exit|Acc]).
+
+%%%
+%%% (7) Remove redundant is_boolean tests.
+%%%
+
+bopt(Is) ->
+ bopt_1(Is, []).
+
+bopt_1([{test,is_boolean,_,_}=I|Is], Acc0) ->
+ case opt_is_bool(I, Acc0) of
+ no -> bopt_1(Is, [I|Acc0]);
+ yes -> bopt_1(Is, Acc0);
+ {yes,Acc} -> bopt_1(Is, Acc)
+ end;
+bopt_1([I|Is], Acc) -> bopt_1(Is, [I|Acc]);
+bopt_1([], Acc) -> reverse(Acc).
+
+opt_is_bool({test,is_boolean,{f,Lbl},[Reg]}, Acc) ->
+ opt_is_bool_1(Acc, Reg, Lbl).
+
+opt_is_bool_1([{test,is_eq_exact,{f,Lbl},[Reg,{atom,true}]}|_], Reg, Lbl) ->
+ %% Instruction not needed in this context.
+ yes;
+opt_is_bool_1([{test,is_ne_exact,{f,Lbl},[Reg,{atom,true}]}|Acc], Reg, Lbl) ->
+ %% Rewrite to shorter test.
+ {yes,[{test,is_eq_exact,{f,Lbl},[Reg,{atom,false}]}|Acc]};
+opt_is_bool_1([{test,_,{f,Lbl},_}=Test|Acc0], Reg, Lbl) ->
+ case opt_is_bool_1(Acc0, Reg, Lbl) of
+ {yes,Acc} -> {yes,[Test|Acc]};
+ Other -> Other
+ end;
+opt_is_bool_1(_, _, _) -> no.
+
+%%%
+%%% (3) (4) (5) (6) Jump and unreachable code optimizations.
+%%%
+
+-record(st, {fc, %Label for function class errors.
+ entry, %Entry label (must not be moved).
+ mlbl, %Moved labels.
+ labels %Set of referenced labels.
+ }).
+
+opt([{label,Fc}|_]=Is, CLabel) ->
+ Lbls = initial_labels(Is),
+ St = #st{fc=Fc,entry=CLabel,mlbl=dict:new(),labels=Lbls},
+ opt(Is, [], St).
+
+opt([{test,Test0,{f,Lnum}=Lbl,Ops}=I|Is0], Acc, St) ->
+ case Is0 of
+ [{jump,To}|[{label,Lnum}|Is2]=Is1] ->
+ case invert_test(Test0) of
+ not_possible ->
+ opt(Is0, [I|Acc], label_used(Lbl, St));
+ Test ->
+ Is = case is_label_used(Lnum, St) of
+ true -> Is1;
+ false -> Is2
+ end,
+ opt([{test,Test,To,Ops}|Is], Acc, label_used(To, St))
+ end;
+ _Other ->
+ opt(Is0, [I|Acc], label_used(Lbl, St))
+ end;
+opt([{select_val,_R,Fail,{list,Vls}}=I|Is], Acc, St) ->
+ skip_unreachable(Is, [I|Acc], label_used([Fail|Vls], St));
+opt([{select_tuple_arity,_R,Fail,{list,Vls}}=I|Is], Acc, St) ->
+ skip_unreachable(Is, [I|Acc], label_used([Fail|Vls], St));
+opt([{'try',_R,Lbl}=I|Is], Acc, St) ->
+ opt(Is, [I|Acc], label_used(Lbl, St));
+opt([{'catch',_R,Lbl}=I|Is], Acc, St) ->
+ opt(Is, [I|Acc], label_used(Lbl, St));
+opt([{label,L}=I|Is], Acc, #st{entry=L}=St) ->
+ %% NEVER move the entry label.
+ opt(Is, [I|Acc], St);
+opt([{label,L1},{jump,{f,L2}}=I|Is], [Prev|Acc], St0) ->
+ St = St0#st{mlbl=dict:append(L2, L1, St0#st.mlbl)},
+ opt([Prev,I|Is], Acc, label_used({f,L2}, St));
+opt([{label,Lbl}=I|Is], Acc, #st{mlbl=Mlbl}=St0) ->
+ case dict:find(Lbl, Mlbl) of
+ {ok,Lbls} ->
+ %% Essential to remove the list of labels from the dictionary,
+ %% since we will rescan the inserted labels. We MUST rescan.
+ St = St0#st{mlbl=dict:erase(Lbl, Mlbl)},
+ insert_labels([Lbl|Lbls], Is, Acc, St);
+ error -> opt(Is, [I|Acc], St0)
+ end;
+opt([{jump,{f,Lbl}},{label,Lbl}=I|Is], Acc, St) ->
+ opt([I|Is], Acc, St);
+opt([{jump,Lbl}=I|Is], Acc, St) ->
+ skip_unreachable(Is, [I|Acc], label_used(Lbl, St));
+opt([{loop_rec,Lbl,_R}=I|Is], Acc, St) ->
+ opt(Is, [I|Acc], label_used(Lbl, St));
+opt([{bif,_Name,Lbl,_As,_R}=I|Is], Acc, St) ->
+ opt(Is, [I|Acc], label_used(Lbl, St));
+opt([{bs_put_integer,Lbl,_Bits,_Unit,_Fl,_Val}=I|Is], Acc, St) ->
+ opt(Is, [I|Acc], label_used(Lbl, St));
+opt([{bs_put_binary,Lbl,_Bits,_Unit,_Fl,_Val}=I|Is], Acc, St) ->
+ opt(Is, [I|Acc], label_used(Lbl, St));
+opt([{bs_put_float,Lbl,_Bits,_Unit,_Fl,_Val}=I|Is], Acc, St) ->
+ opt(Is, [I|Acc], label_used(Lbl, St));
+opt([{bs_final,Lbl,_R}=I|Is], Acc, St) ->
+ opt(Is, [I|Acc], label_used(Lbl, St));
+opt([{bs_init2,Lbl,_,_,_,_,_}=I|Is], Acc, St) ->
+ opt(Is, [I|Acc], label_used(Lbl, St));
+opt([{bs_add,Lbl,_,_}=I|Is], Acc, St) ->
+ opt(Is, [I|Acc], label_used(Lbl, St));
+opt([{bs_bits_to_bytes,Lbl,_,_}=I|Is], Acc, St) ->
+ opt(Is, [I|Acc], label_used(Lbl, St));
+opt([I|Is], Acc, St) ->
+ case is_unreachable_after(I) of
+ true -> skip_unreachable(Is, [I|Acc], St);
+ false -> opt(Is, [I|Acc], St)
+ end;
+opt([], Acc, #st{fc=Fc,mlbl=Mlbl}) ->
+ Code = reverse(Acc),
+ case dict:find(Fc, Mlbl) of
+ {ok,Lbls} -> insert_fc_labels(Lbls, Mlbl, Code);
+ error -> Code
+ end.
+
+insert_fc_labels([L|Ls], Mlbl, Acc0) ->
+ Acc = [{label,L}|Acc0],
+ case dict:find(L, Mlbl) of
+ error ->
+ insert_fc_labels(Ls, Mlbl, Acc);
+ {ok,Lbls} ->
+ insert_fc_labels(Lbls++Ls, Mlbl, Acc)
+ end;
+insert_fc_labels([], _, Acc) -> Acc.
+
+%% invert_test(Test0) -> not_possible | Test
+
+invert_test(is_ge) -> is_lt;
+invert_test(is_lt) -> is_ge;
+invert_test(is_eq) -> is_ne;
+invert_test(is_ne) -> is_eq;
+invert_test(is_eq_exact) -> is_ne_exact;
+invert_test(is_ne_exact) -> is_eq_exact;
+invert_test(_) -> not_possible.
+
+insert_labels([L|Ls], Is, [{jump,{f,L}}|Acc], St) ->
+ insert_labels(Ls, [{label,L}|Is], Acc, St);
+insert_labels([L|Ls], Is, Acc, St) ->
+ insert_labels(Ls, [{label,L}|Is], Acc, St);
+insert_labels([], Is, Acc, St) ->
+ opt(Is, Acc, St).
+
+%% Skip unreachable code up to the next referenced label.
+
+skip_unreachable([{label,L}|Is], [{jump,{f,L}}|Acc], St) ->
+ opt([{label,L}|Is], Acc, St);
+skip_unreachable([{label,L}|Is], Acc, St) ->
+ case is_label_used(L, St) of
+ true -> opt([{label,L}|Is], Acc, St);
+ false -> skip_unreachable(Is, Acc, St)
+ end;
+skip_unreachable([_|Is], Acc, St) ->
+ skip_unreachable(Is, Acc, St);
+skip_unreachable([], Acc, St) ->
+ opt([], Acc, St).
+
+%% Add one or more label to the set of used labels.
+
+label_used({f,0}, St) -> St;
+label_used({f,L}, St) -> St#st{labels=gb_sets:add(L, St#st.labels)};
+label_used([H|T], St0) -> label_used(T, label_used(H, St0));
+label_used([], St) -> St;
+label_used(_Other, St) -> St.
+
+%% Test if label is used.
+
+is_label_used(L, St) ->
+ gb_sets:is_member(L, St#st.labels).
+
+%% is_unreachable_after(Instruction) -> true|false
+%% Test whether the code after Instruction is unreachable.
+
+is_unreachable_after({func_info,_M,_F,_A}) -> true;
+is_unreachable_after(return) -> true;
+is_unreachable_after({call_ext_last,_Ar,_ExtFunc,_D}) -> true;
+is_unreachable_after({call_ext_only,_Ar,_ExtFunc}) -> true;
+is_unreachable_after({call_last,_Ar,_Lbl,_D}) -> true;
+is_unreachable_after({call_only,_Ar,_Lbl}) -> true;
+is_unreachable_after({apply_last,_Ar,_N}) -> true;
+is_unreachable_after({jump,_Lbl}) -> true;
+is_unreachable_after({select_val,_R,_Lbl,_Cases}) -> true;
+is_unreachable_after({select_tuple_arity,_R,_Lbl,_Cases}) -> true;
+is_unreachable_after({loop_rec_end,_}) -> true;
+is_unreachable_after({wait,_}) -> true;
+is_unreachable_after(I) -> is_exit_instruction(I).
+
+%% is_exit_instruction(Instruction) -> true|false
+%% Test whether the instruction Instruction always
+%% causes an exit/failure.
+
+is_exit_instruction({call_ext,_,{extfunc,M,F,A}}) ->
+ is_exit_instruction_1(M, F, A);
+is_exit_instruction({call_ext_last,_,{extfunc,M,F,A},_}) ->
+ is_exit_instruction_1(M, F, A);
+is_exit_instruction({call_ext_only,_,{extfunc,M,F,A}}) ->
+ is_exit_instruction_1(M, F, A);
+is_exit_instruction(if_end) -> true;
+is_exit_instruction({case_end,_}) -> true;
+is_exit_instruction({try_case_end,_}) -> true;
+is_exit_instruction({badmatch,_}) -> true;
+is_exit_instruction(_) -> false.
+
+is_exit_instruction_1(erlang, exit, 1) -> true;
+is_exit_instruction_1(erlang, throw, 1) -> true;
+is_exit_instruction_1(erlang, error, 1) -> true;
+is_exit_instruction_1(erlang, error, 2) -> true;
+is_exit_instruction_1(erlang, fault, 1) -> true;
+is_exit_instruction_1(erlang, fault, 2) -> true;
+is_exit_instruction_1(_, _, _) -> false.
+
+%% remove_unused_labels(Instructions0) -> Instructions
+%% Remove all unused labels.
+
+remove_unused_labels(Is) ->
+ Used0 = initial_labels(Is),
+ Used = foldl(fun ulbl/2, Used0, Is),
+ rem_unused(Is, Used, []).
+
+rem_unused([{label,Lbl}=I|Is], Used, Acc) ->
+ case gb_sets:is_member(Lbl, Used) of
+ false -> rem_unused(Is, Used, Acc);
+ true -> rem_unused(Is, Used, [I|Acc])
+ end;
+rem_unused([I|Is], Used, Acc) ->
+ rem_unused(Is, Used, [I|Acc]);
+rem_unused([], _, Acc) -> reverse(Acc).
+
+initial_labels(Is) ->
+ initial_labels(Is, []).
+
+initial_labels([{label,Lbl}|Is], Acc) ->
+ initial_labels(Is, [Lbl|Acc]);
+initial_labels([{func_info,_,_,_},{label,Lbl}|_], Acc) ->
+ gb_sets:from_list([Lbl|Acc]).
+
+ulbl({test,_,Fail,_}, Used) ->
+ mark_used(Fail, Used);
+ulbl({select_val,_,Fail,{list,Vls}}, Used) ->
+ mark_used_list(Vls, mark_used(Fail, Used));
+ulbl({select_tuple_arity,_,Fail,{list,Vls}}, Used) ->
+ mark_used_list(Vls, mark_used(Fail, Used));
+ulbl({'try',_,Lbl}, Used) ->
+ mark_used(Lbl, Used);
+ulbl({'catch',_,Lbl}, Used) ->
+ mark_used(Lbl, Used);
+ulbl({jump,Lbl}, Used) ->
+ mark_used(Lbl, Used);
+ulbl({loop_rec,Lbl,_}, Used) ->
+ mark_used(Lbl, Used);
+ulbl({loop_rec_end,Lbl}, Used) ->
+ mark_used(Lbl, Used);
+ulbl({wait,Lbl}, Used) ->
+ mark_used(Lbl, Used);
+ulbl({wait_timeout,Lbl,_To}, Used) ->
+ mark_used(Lbl, Used);
+ulbl({bif,_Name,Lbl,_As,_R}, Used) ->
+ mark_used(Lbl, Used);
+ulbl({bs_init2,Lbl,_,_,_,_,_}, Used) ->
+ mark_used(Lbl, Used);
+ulbl({bs_put_integer,Lbl,_Bits,_Unit,_Fl,_Val}, Used) ->
+ mark_used(Lbl, Used);
+ulbl({bs_put_float,Lbl,_Bits,_Unit,_Fl,_Val}, Used) ->
+ mark_used(Lbl, Used);
+ulbl({bs_put_binary,Lbl,_Bits,_Unit,_Fl,_Val}, Used) ->
+ mark_used(Lbl, Used);
+ulbl({bs_final,Lbl,_}, Used) ->
+ mark_used(Lbl, Used);
+ulbl({bs_add,Lbl,_,_}, Used) ->
+ mark_used(Lbl, Used);
+ulbl({bs_bits_to_bytes,Lbl,_,_}, Used) ->
+ mark_used(Lbl, Used);
+ulbl(_, Used) -> Used.
+
+mark_used({f,0}, Used) -> Used;
+mark_used({f,L}, Used) -> gb_sets:add(L, Used);
+mark_used(_, Used) -> Used.
+
+mark_used_list([H|T], Used) ->
+ mark_used_list(T, mark_used(H, Used));
+mark_used_list([], Used) -> Used.
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_listing.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_listing.erl
new file mode 100644
index 0000000000..5def6816b2
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_listing.erl
@@ -0,0 +1,117 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: beam_listing.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
+%%
+-module(beam_listing).
+
+-export([module/2]).
+
+-include("v3_life.hrl").
+
+-import(lists, [foreach/2]).
+
+module(File, Core) when element(1, Core) == c_module ->
+ %% This is a core module.
+ io:put_chars(File, core_pp:format(Core));
+module(File, Kern) when element(1, Kern) == k_mdef ->
+ %% This is a kernel module.
+ io:put_chars(File, v3_kernel_pp:format(Kern));
+ %%io:put_chars(File, io_lib:format("~p~n", [Kern]));
+module(File, {Mod,Exp,Attr,Kern}) ->
+ %% This is output from beam_life (v3).
+ io:fwrite(File, "~w.~n~p.~n~p.~n", [Mod,Exp,Attr]),
+ foreach(fun (F) -> function(File, F) end, Kern);
+module(Stream, {Mod,Exp,Attr,Code,NumLabels}) ->
+ %% This is output from beam_codegen.
+ io:format(Stream, "{module, ~s}. %% version = ~w\n",
+ [Mod, beam_opcodes:format_number()]),
+ io:format(Stream, "\n{exports, ~p}.\n", [Exp]),
+ io:format(Stream, "\n{attributes, ~p}.\n", [Attr]),
+ io:format(Stream, "\n{labels, ~p}.\n", [NumLabels]),
+ foreach(
+ fun ({function,Name,Arity,Entry,Asm}) ->
+ io:format(Stream, "\n\n{function, ~w, ~w, ~w}.\n",
+ [Name, Arity, Entry]),
+ foreach(fun(Op) -> print_op(Stream, Op) end, Asm) end,
+ Code);
+module(Stream, {Mod,Exp,Inter}) ->
+ %% Other kinds of intermediate formats.
+ io:fwrite(Stream, "~w.~n~p.~n", [Mod,Exp]),
+ foreach(fun (F) -> io:format(Stream, "~p.\n", [F]) end, Inter);
+module(Stream, [_|_]=Fs) ->
+ %% Form-based abstract format.
+ foreach(fun (F) -> io:format(Stream, "~p.\n", [F]) end, Fs).
+
+print_op(Stream, Label) when element(1, Label) == label ->
+ io:format(Stream, " ~p.\n", [Label]);
+print_op(Stream, Op) ->
+ io:format(Stream, " ~p.\n", [Op]).
+
+function(File, {function,Name,Arity,Args,Body,Vdb}) ->
+ io:nl(File),
+ io:format(File, "function ~p/~p.\n", [Name,Arity]),
+ io:format(File, " ~p.\n", [Args]),
+ print_vdb(File, Vdb),
+ put(beam_listing_nl, true),
+ foreach(fun(F) -> format(File, F, []) end, Body),
+ nl(File),
+ erase(beam_listing_nl).
+
+format(File, #l{ke=Ke,i=I,vdb=Vdb}, Ind) ->
+ nl(File),
+ ind_format(File, Ind, "~p ", [I]),
+ print_vdb(File, Vdb),
+ nl(File),
+ format(File, Ke, Ind);
+format(File, Tuple, Ind) when is_tuple(Tuple) ->
+ ind_format(File, Ind, "{", []),
+ format_list(File, tuple_to_list(Tuple), [$\s|Ind]),
+ ind_format(File, Ind, "}", []);
+format(File, List, Ind) when is_list(List) ->
+ ind_format(File, Ind, "[", []),
+ format_list(File, List, [$\s|Ind]),
+ ind_format(File, Ind, "]", []);
+format(File, F, Ind) ->
+ ind_format(File, Ind, "~p", [F]).
+
+format_list(File, [F], Ind) ->
+ format(File, F, Ind);
+format_list(File, [F|Fs], Ind) ->
+ format(File, F, Ind),
+ ind_format(File, Ind, ",", []),
+ format_list(File, Fs, Ind);
+format_list(_, [], _) -> ok.
+
+
+print_vdb(File, [{Var,F,E}|Vs]) ->
+ io:format(File, "~p:~p..~p ", [Var,F,E]),
+ print_vdb(File, Vs);
+print_vdb(_, []) -> ok.
+
+ind_format(File, Ind, Format, Args) ->
+ case get(beam_listing_nl) of
+ true ->
+ put(beam_listing_nl, false),
+ io:put_chars(File, Ind);
+ false -> ok
+ end,
+ io:format(File, Format, Args).
+
+nl(File) ->
+ case put(beam_listing_nl, true) of
+ true -> ok;
+ false -> io:nl(File)
+ end.
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_opcodes.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_opcodes.erl
index a4f5fd34d2..a4f5fd34d2 100644
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_opcodes.erl
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_opcodes.erl
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_opcodes.hrl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_opcodes.hrl
new file mode 100644
index 0000000000..a330a68f37
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_opcodes.hrl
@@ -0,0 +1,11 @@
+%% Warning: Do not edit this file. It was automatically
+%% generated by 'beam_makeops' on Wed Nov 24 17:52:43 2004.
+
+-define(tag_u, 0).
+-define(tag_i, 1).
+-define(tag_a, 2).
+-define(tag_x, 3).
+-define(tag_y, 4).
+-define(tag_f, 5).
+-define(tag_h, 6).
+-define(tag_z, 7).
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_type.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_type.erl
new file mode 100644
index 0000000000..d2ac3fcd99
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_type.erl
@@ -0,0 +1,551 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: beam_type.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
+%%
+%% Purpose : Type-based optimisations.
+
+-module(beam_type).
+
+-export([module/2]).
+
+-import(lists, [map/2,foldl/3,reverse/1,reverse/2,filter/2,member/2]).
+
+module({Mod,Exp,Attr,Fs0,Lc}, Opt) ->
+ AllowFloatOpts = not member(no_float_opt, Opt),
+ Fs = map(fun(F) -> function(F, AllowFloatOpts) end, Fs0),
+ {ok,{Mod,Exp,Attr,Fs,Lc}}.
+
+function({function,Name,Arity,CLabel,Asm0}, AllowFloatOpts) ->
+ Asm = opt(Asm0, AllowFloatOpts, [], tdb_new()),
+ {function,Name,Arity,CLabel,Asm}.
+
+%% opt([Instruction], AllowFloatOpts, Accumulator, TypeDb) -> {[Instruction'],TypeDb'}
+%% Keep track of type information; try to simplify.
+
+opt([{block,Body1}|Is], AllowFloatOpts, [{block,Body0}|Acc], Ts0) ->
+ {Body2,Ts} = simplify(Body1, Ts0, AllowFloatOpts),
+ Body = beam_block:merge_blocks(Body0, Body2),
+ opt(Is, AllowFloatOpts, [{block,Body}|Acc], Ts);
+opt([{block,Body0}|Is], AllowFloatOpts, Acc, Ts0) ->
+ {Body,Ts} = simplify(Body0, Ts0, AllowFloatOpts),
+ opt(Is, AllowFloatOpts, [{block,Body}|Acc], Ts);
+opt([I0|Is], AllowFloatOpts, Acc, Ts0) ->
+ case simplify([I0], Ts0, AllowFloatOpts) of
+ {[],Ts} -> opt(Is, AllowFloatOpts, Acc, Ts);
+ {[I],Ts} -> opt(Is, AllowFloatOpts, [I|Acc], Ts)
+ end;
+opt([], _, Acc, _) -> reverse(Acc).
+
+%% simplify(Instruction, TypeDb, AllowFloatOpts) -> NewInstruction
+%% Simplify an instruction using type information (this is
+%% technically a "strength reduction").
+
+simplify(Is, TypeDb, false) ->
+ simplify(Is, TypeDb, no_float_opt, []);
+simplify(Is, TypeDb, true) ->
+ case are_live_regs_determinable(Is) of
+ false -> simplify(Is, TypeDb, no_float_opt, []);
+ true -> simplify(Is, TypeDb, [], [])
+ end.
+
+simplify([{set,[D],[{integer,Index},Reg],{bif,element,_}}=I0|Is]=Is0, Ts0, Rs0, Acc0) ->
+ I = case max_tuple_size(Reg, Ts0) of
+ Sz when 0 < Index, Index =< Sz ->
+ {set,[D],[Reg],{get_tuple_element,Index-1}};
+ _Other -> I0
+ end,
+ Ts = update(I, Ts0),
+ {Rs,Acc} = flush(Rs0, Is0, Acc0),
+ simplify(Is, Ts, Rs, [I|checkerror(Acc)]);
+simplify([{set,[D0],[A],{bif,'-',{f,0}}}=I|Is]=Is0, Ts0, Rs0, Acc0)
+ when Rs0 =/= no_float_opt ->
+ case tdb_find(A, Ts0) of
+ float ->
+ {Rs1,Acc1} = load_reg(A, Ts0, Rs0, Acc0),
+ {D,Rs} = find_dest(D0, Rs1),
+ Areg = fetch_reg(A, Rs),
+ Acc = [{set,[D],[Areg],{bif,fnegate,{f,0}}}|clearerror(Acc1)],
+ Ts = tdb_update([{D0,float}], Ts0),
+ simplify(Is, Ts, Rs, Acc);
+ _Other ->
+ Ts = update(I, Ts0),
+ {Rs,Acc} = flush(Rs0, Is0, Acc0),
+ simplify(Is, Ts, Rs, [I|checkerror(Acc)])
+ end;
+simplify([{set,[_],[_],{bif,_,{f,0}}}=I|Is]=Is0, Ts0, Rs0, Acc0) ->
+ Ts = update(I, Ts0),
+ {Rs,Acc} = flush(Rs0, Is0, Acc0),
+ simplify(Is, Ts, Rs, [I|checkerror(Acc)]);
+simplify([{set,[D0],[A,B],{bif,Op0,{f,0}}}=I|Is]=Is0, Ts0, Rs0, Acc0)
+ when Rs0 =/= no_float_opt ->
+ case float_op(Op0, A, B, Ts0) of
+ no ->
+ Ts = update(I, Ts0),
+ {Rs,Acc} = flush(Rs0, Is0, Acc0),
+ simplify(Is, Ts, Rs, [I|checkerror(Acc)]);
+ {yes,Op} ->
+ {Rs1,Acc1} = load_reg(A, Ts0, Rs0, Acc0),
+ {Rs2,Acc2} = load_reg(B, Ts0, Rs1, Acc1),
+ {D,Rs} = find_dest(D0, Rs2),
+ Areg = fetch_reg(A, Rs),
+ Breg = fetch_reg(B, Rs),
+ Acc = [{set,[D],[Areg,Breg],{bif,Op,{f,0}}}|clearerror(Acc2)],
+ Ts = tdb_update([{D0,float}], Ts0),
+ simplify(Is, Ts, Rs, Acc)
+ end;
+simplify([{set,[D],[TupleReg],{get_tuple_element,0}}=I|Is0], Ts0, Rs0, Acc0) ->
+ case tdb_find(TupleReg, Ts0) of
+ {tuple,_,[Contents]} ->
+ Ts = tdb_update([{D,Contents}], Ts0),
+ {Rs,Acc} = flush(Rs0, Is0, Acc0),
+ simplify(Is0, Ts, Rs, [{set,[D],[Contents],move}|Acc]);
+ _ ->
+ Ts = update(I, Ts0),
+ {Rs,Acc} = flush(Rs0, Is0, Acc0),
+ simplify(Is0, Ts, Rs, [I|checkerror(Acc)])
+ end;
+simplify([{set,_,_,{'catch',_}}=I|Is]=Is0, _Ts, Rs0, Acc0) ->
+ Acc = flush_all(Rs0, Is0, Acc0),
+ simplify(Is, tdb_new(), Rs0, [I|Acc]);
+simplify([{test,is_tuple,_,[R]}=I|Is], Ts, Rs, Acc) ->
+ case tdb_find(R, Ts) of
+ {tuple,_,_} -> simplify(Is, Ts, Rs, Acc);
+ _ ->
+ simplify(Is, Ts, Rs, [I|Acc])
+ end;
+simplify([{test,test_arity,_,[R,Arity]}=I|Is], Ts0, Rs, Acc) ->
+ case tdb_find(R, Ts0) of
+ {tuple,Arity,_} ->
+ simplify(Is, Ts0, Rs, Acc);
+ _Other ->
+ Ts = update(I, Ts0),
+ simplify(Is, Ts, Rs, [I|Acc])
+ end;
+simplify([{test,is_eq_exact,Fail,[R,{atom,_}=Atom]}=I|Is0], Ts0, Rs0, Acc0) ->
+ Acc1 = case tdb_find(R, Ts0) of
+ {atom,_}=Atom -> Acc0;
+ {atom,_} -> [{jump,Fail}|Acc0];
+ _ -> [I|Acc0]
+ end,
+ Ts = update(I, Ts0),
+ {Rs,Acc} = flush(Rs0, Is0, Acc1),
+ simplify(Is0, Ts, Rs, Acc);
+simplify([I|Is]=Is0, Ts0, Rs0, Acc0) ->
+ Ts = update(I, Ts0),
+ {Rs,Acc} = flush(Rs0, Is0, Acc0),
+ simplify(Is, Ts, Rs, [I|Acc]);
+simplify([], Ts, Rs, Acc) ->
+ Is0 = reverse(flush_all(Rs, [], Acc)),
+ Is1 = opt_fmoves(Is0, []),
+ Is = add_ftest_heap(Is1),
+ {Is,Ts}.
+
+opt_fmoves([{set,[{x,_}=R],[{fr,_}]=Src,fmove}=I1,
+ {set,[{y,_}]=Dst,[{x,_}=R],move}=I2|Is], Acc) ->
+ case beam_block:is_killed(R, Is) of
+ false -> opt_fmoves(Is, [I2,I1|Acc]);
+ true -> opt_fmoves(Is, [{set,Dst,Src,fmove}|Acc])
+ end;
+opt_fmoves([I|Is], Acc) ->
+ opt_fmoves(Is, [I|Acc]);
+opt_fmoves([], Acc) -> reverse(Acc).
+
+clearerror(Is) ->
+ clearerror(Is, Is).
+
+clearerror([{set,[],[],fclearerror}|_], OrigIs) -> OrigIs;
+clearerror([{set,[],[],fcheckerror}|_], OrigIs) -> [{set,[],[],fclearerror}|OrigIs];
+clearerror([_|Is], OrigIs) -> clearerror(Is, OrigIs);
+clearerror([], OrigIs) -> [{set,[],[],fclearerror}|OrigIs].
+
+%% update(Instruction, TypeDb) -> NewTypeDb
+%% Update the type database to account for executing an instruction.
+%%
+%% First the cases for instructions inside basic blocks.
+update({set,[D],[S],move}, Ts0) ->
+ Ops = case tdb_find(S, Ts0) of
+ error -> [{D,kill}];
+ Info -> [{D,Info}]
+ end,
+ tdb_update(Ops, Ts0);
+update({set,[D],[{integer,I},Reg],{bif,element,_}}, Ts0) ->
+ tdb_update([{Reg,{tuple,I,[]}},{D,kill}], Ts0);
+update({set,[D],[_Index,Reg],{bif,element,_}}, Ts0) ->
+ tdb_update([{Reg,{tuple,0,[]}},{D,kill}], Ts0);
+update({set,[D],[S],{get_tuple_element,0}}, Ts) ->
+ tdb_update([{D,{tuple_element,S,0}}], Ts);
+update({set,[D],[S],{bif,float,{f,0}}}, Ts0) ->
+ %% Make sure we reject non-numeric literal argument.
+ case possibly_numeric(S) of
+ true -> tdb_update([{D,float}], Ts0);
+ false -> Ts0
+ end;
+update({set,[D],[S1,S2],{bif,'/',{f,0}}}, Ts0) ->
+ %% Make sure we reject non-numeric literals.
+ case possibly_numeric(S1) andalso possibly_numeric(S2) of
+ true -> tdb_update([{D,float}], Ts0);
+ false -> Ts0
+ end;
+update({set,[D],[S1,S2],{bif,Op,{f,0}}}, Ts0) ->
+ case arith_op(Op) of
+ no ->
+ tdb_update([{D,kill}], Ts0);
+ {yes,_} ->
+ case {tdb_find(S1, Ts0),tdb_find(S2, Ts0)} of
+ {float,_} -> tdb_update([{D,float}], Ts0);
+ {_,float} -> tdb_update([{D,float}], Ts0);
+ {_,_} -> tdb_update([{D,kill}], Ts0)
+ end
+ end;
+update({set,[],_Src,_Op}, Ts0) -> Ts0;
+update({set,[D],_Src,_Op}, Ts0) ->
+ tdb_update([{D,kill}], Ts0);
+update({set,[D1,D2],_Src,_Op}, Ts0) ->
+ tdb_update([{D1,kill},{D2,kill}], Ts0);
+update({allocate,_,_}, Ts) -> Ts;
+update({init,D}, Ts) ->
+ tdb_update([{D,kill}], Ts);
+update({kill,D}, Ts) ->
+ tdb_update([{D,kill}], Ts);
+update({'%live',_}, Ts) -> Ts;
+
+%% Instructions outside of blocks.
+update({test,is_float,_Fail,[Src]}, Ts0) ->
+ tdb_update([{Src,float}], Ts0);
+update({test,test_arity,_Fail,[Src,Arity]}, Ts0) ->
+ tdb_update([{Src,{tuple,Arity,[]}}], Ts0);
+update({test,is_eq_exact,_,[Reg,{atom,_}=Atom]}, Ts) ->
+ case tdb_find(Reg, Ts) of
+ error ->
+ Ts;
+ {tuple_element,TupleReg,0} ->
+ tdb_update([{TupleReg,{tuple,1,[Atom]}}], Ts);
+ _ ->
+ Ts
+ end;
+update({test,_Test,_Fail,_Other}, Ts) -> Ts;
+update({call_ext,1,{extfunc,math,Math,1}}, Ts) ->
+ case is_math_bif(Math, 1) of
+ true -> tdb_update([{{x,0},float}], Ts);
+ false -> tdb_kill_xregs(Ts)
+ end;
+update({call_ext,2,{extfunc,math,Math,2}}, Ts) ->
+ case is_math_bif(Math, 2) of
+ true -> tdb_update([{{x,0},float}], Ts);
+ false -> tdb_kill_xregs(Ts)
+ end;
+update({call_ext,3,{extfunc,erlang,setelement,3}}, Ts0) ->
+ Op = case tdb_find({x,1}, Ts0) of
+ error -> kill;
+ Info -> Info
+ end,
+ Ts1 = tdb_kill_xregs(Ts0),
+ tdb_update([{{x,0},Op}], Ts1);
+update({call,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts);
+update({call_ext,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts);
+update({make_fun2,_,_,_,_}, Ts) -> tdb_kill_xregs(Ts);
+
+%% The instruction is unknown. Kill all information.
+update(_I, _Ts) -> tdb_new().
+
+is_math_bif(cos, 1) -> true;
+is_math_bif(cosh, 1) -> true;
+is_math_bif(sin, 1) -> true;
+is_math_bif(sinh, 1) -> true;
+is_math_bif(tan, 1) -> true;
+is_math_bif(tanh, 1) -> true;
+is_math_bif(acos, 1) -> true;
+is_math_bif(acosh, 1) -> true;
+is_math_bif(asin, 1) -> true;
+is_math_bif(asinh, 1) -> true;
+is_math_bif(atan, 1) -> true;
+is_math_bif(atanh, 1) -> true;
+is_math_bif(erf, 1) -> true;
+is_math_bif(erfc, 1) -> true;
+is_math_bif(exp, 1) -> true;
+is_math_bif(log, 1) -> true;
+is_math_bif(log10, 1) -> true;
+is_math_bif(sqrt, 1) -> true;
+is_math_bif(atan2, 2) -> true;
+is_math_bif(pow, 2) -> true;
+is_math_bif(pi, 0) -> true;
+is_math_bif(_, _) -> false.
+
+%% Reject non-numeric literals.
+possibly_numeric({x,_}) -> true;
+possibly_numeric({y,_}) -> true;
+possibly_numeric({integer,_}) -> true;
+possibly_numeric({float,_}) -> true;
+possibly_numeric(_) -> false.
+
+max_tuple_size(Reg, Ts) ->
+ case tdb_find(Reg, Ts) of
+ {tuple,Sz,_} -> Sz;
+ _Other -> 0
+ end.
+
+float_op('/', A, B, _) ->
+ case possibly_numeric(A) andalso possibly_numeric(B) of
+ true -> {yes,fdiv};
+ false -> no
+ end;
+float_op(Op, {float,_}, B, _) ->
+ case possibly_numeric(B) of
+ true -> arith_op(Op);
+ false -> no
+ end;
+float_op(Op, A, {float,_}, _) ->
+ case possibly_numeric(A) of
+ true -> arith_op(Op);
+ false -> no
+ end;
+float_op(Op, A, B, Ts) ->
+ case {tdb_find(A, Ts),tdb_find(B, Ts)} of
+ {float,_} -> arith_op(Op);
+ {_,float} -> arith_op(Op);
+ {_,_} -> no
+ end.
+
+find_dest(V, Rs0) ->
+ case find_reg(V, Rs0) of
+ {ok,FR} ->
+ {FR,mark(V, Rs0, dirty)};
+ error ->
+ Rs = put_reg(V, Rs0, dirty),
+ {ok,FR} = find_reg(V, Rs),
+ {FR,Rs}
+ end.
+
+load_reg({float,_}=F, _, Rs0, Is0) ->
+ Rs = put_reg(F, Rs0, clean),
+ {ok,FR} = find_reg(F, Rs),
+ Is = [{set,[FR],[F],fmove}|Is0],
+ {Rs,Is};
+load_reg(V, Ts, Rs0, Is0) ->
+ case find_reg(V, Rs0) of
+ {ok,_FR} -> {Rs0,Is0};
+ error ->
+ Rs = put_reg(V, Rs0, clean),
+ {ok,FR} = find_reg(V, Rs),
+ Op = case tdb_find(V, Ts) of
+ float -> fmove;
+ _ -> fconv
+ end,
+ Is = [{set,[FR],[V],Op}|Is0],
+ {Rs,Is}
+ end.
+
+arith_op('+') -> {yes,fadd};
+arith_op('-') -> {yes,fsub};
+arith_op('*') -> {yes,fmul};
+arith_op('/') -> {yes,fdiv};
+arith_op(_) -> no.
+
+flush(no_float_opt, _, Acc) -> {no_float_opt,Acc};
+flush(Rs, [{set,[_],[],{put_tuple,_}}|_]=Is0, Acc0) ->
+ Acc = flush_all(Rs, Is0, Acc0),
+ {[],Acc};
+flush(Rs0, [{set,Ds,Ss,_Op}|_], Acc0) ->
+ Save = gb_sets:from_list(Ss),
+ Acc = save_regs(Rs0, Save, Acc0),
+ Rs1 = foldl(fun(S, A) -> mark(S, A, clean) end, Rs0, Ss),
+ Kill = gb_sets:from_list(Ds),
+ Rs = kill_regs(Rs1, Kill),
+ {Rs,Acc};
+flush(Rs0, Is, Acc0) ->
+ Acc = flush_all(Rs0, Is, Acc0),
+ {[],Acc}.
+
+flush_all(no_float_opt, _, Acc) -> Acc;
+flush_all([{_,{float,_},_}|Rs], Is, Acc) ->
+ flush_all(Rs, Is, Acc);
+flush_all([{I,V,dirty}|Rs], Is, Acc0) ->
+ Acc = checkerror(Acc0),
+ case beam_block:is_killed(V, Is) of
+ true -> flush_all(Rs, Is, Acc);
+ false -> flush_all(Rs, Is, [{set,[V],[{fr,I}],fmove}|Acc])
+ end;
+flush_all([{_,_,clean}|Rs], Is, Acc) -> flush_all(Rs, Is, Acc);
+flush_all([free|Rs], Is, Acc) -> flush_all(Rs, Is, Acc);
+flush_all([], _, Acc) -> Acc.
+
+save_regs(Rs, Save, Acc) ->
+ foldl(fun(R, A) -> save_reg(R, Save, A) end, Acc, Rs).
+
+save_reg({I,V,dirty}, Save, Acc) ->
+ case gb_sets:is_member(V, Save) of
+ true -> [{set,[V],[{fr,I}],fmove}|checkerror(Acc)];
+ false -> Acc
+ end;
+save_reg(_, _, Acc) -> Acc.
+
+kill_regs(Rs, Kill) ->
+ map(fun(R) -> kill_reg(R, Kill) end, Rs).
+
+kill_reg({_,V,_}=R, Kill) ->
+ case gb_sets:is_member(V, Kill) of
+ true -> free;
+ false -> R
+ end;
+kill_reg(R, _) -> R.
+
+mark(V, [{I,V,_}|Rs], Mark) -> [{I,V,Mark}|Rs];
+mark(V, [R|Rs], Mark) -> [R|mark(V, Rs, Mark)];
+mark(_, [], _) -> [].
+
+fetch_reg(V, [{I,V,_}|_]) -> {fr,I};
+fetch_reg(V, [_|SRs]) -> fetch_reg(V, SRs).
+
+find_reg(V, [{I,V,_}|_]) -> {ok,{fr,I}};
+find_reg(V, [_|SRs]) -> find_reg(V, SRs);
+find_reg(_, []) -> error.
+
+put_reg(V, Rs, Dirty) -> put_reg_1(V, Rs, Dirty, 0).
+
+put_reg_1(V, [free|Rs], Dirty, I) -> [{I,V,Dirty}|Rs];
+put_reg_1(V, [R|Rs], Dirty, I) -> [R|put_reg_1(V, Rs, Dirty, I+1)];
+put_reg_1(V, [], Dirty, I) -> [{I,V,Dirty}].
+
+checkerror(Is) ->
+ checkerror_1(Is, Is).
+
+checkerror_1([{set,[],[],fcheckerror}|_], OrigIs) -> OrigIs;
+checkerror_1([{set,[],[],fclearerror}|_], OrigIs) -> OrigIs;
+checkerror_1([{set,_,_,{bif,fadd,_}}|_], OrigIs) -> checkerror_2(OrigIs);
+checkerror_1([{set,_,_,{bif,fsub,_}}|_], OrigIs) -> checkerror_2(OrigIs);
+checkerror_1([{set,_,_,{bif,fmul,_}}|_], OrigIs) -> checkerror_2(OrigIs);
+checkerror_1([{set,_,_,{bif,fdiv,_}}|_], OrigIs) -> checkerror_2(OrigIs);
+checkerror_1([{set,_,_,{bif,fnegate,_}}|_], OrigIs) -> checkerror_2(OrigIs);
+checkerror_1([_|Is], OrigIs) -> checkerror_1(Is, OrigIs);
+checkerror_1([], OrigIs) -> OrigIs.
+
+checkerror_2(OrigIs) -> [{set,[],[],fcheckerror}|OrigIs].
+
+add_ftest_heap(Is) ->
+ add_ftest_heap_1(reverse(Is), 0, []).
+
+add_ftest_heap_1([{set,_,[{fr,_}],fmove}=I|Is], Floats, Acc) ->
+ add_ftest_heap_1(Is, Floats+1, [I|Acc]);
+add_ftest_heap_1([{allocate,_,_}=I|Is], 0, Acc) ->
+ reverse(Is, [I|Acc]);
+add_ftest_heap_1([{allocate,Regs,{Z,Stk,Heap,Inits}}|Is], Floats, Acc) ->
+ reverse(Is, [{allocate,Regs,{Z,Stk,Heap,Floats,Inits}}|Acc]);
+add_ftest_heap_1([I|Is], Floats, Acc) ->
+ add_ftest_heap_1(Is, Floats, [I|Acc]);
+add_ftest_heap_1([], 0, Acc) ->
+ Acc;
+add_ftest_heap_1([], Floats, Is) ->
+ Regs = beam_block:live_at_entry(Is),
+ [{allocate,Regs,{nozero,nostack,0,Floats,[]}}|Is].
+
+are_live_regs_determinable([{allocate,_,_}|_]) -> true;
+are_live_regs_determinable([{'%live',_}|_]) -> true;
+are_live_regs_determinable([_|Is]) -> are_live_regs_determinable(Is);
+are_live_regs_determinable([]) -> false.
+
+
+%%% Routines for maintaining a type database. The type database
+%%% associates type information with registers.
+%%%
+%%% {tuple,Size,First} means that the corresponding register contains a
+%%% tuple with *at least* Size elements. An tuple with unknown
+%%% size is represented as {tuple,0}. First is either [] (meaning that
+%%% the tuple's first element is unknown) or [FirstElement] (the contents
+%%% of the first element).
+%%%
+%%% 'float' means that the register contains a float.
+
+%% tdb_new() -> EmptyDataBase
+%% Creates a new, empty type database.
+
+tdb_new() -> [].
+
+%% tdb_find(Register, Db) -> Information|error
+%% Returns type information or the atom error if there are no type
+%% information available for Register.
+
+tdb_find(Key, [{K,_}|_]) when Key < K -> error;
+tdb_find(Key, [{Key,Info}|_]) -> Info;
+tdb_find(Key, [_|Db]) -> tdb_find(Key, Db);
+tdb_find(_, []) -> error.
+
+%% tdb_update([UpdateOp], Db) -> NewDb
+%% UpdateOp = {Register,kill}|{Register,NewInfo}
+%% Updates a type database. If a 'kill' operation is given, the type
+%% information for that register will be removed from the database.
+%% A kill operation takes precende over other operations for the same
+%% register (i.e. [{{x,0},kill},{{x,0},{tuple,5}}] means that the
+%% the existing type information, if any, will be discarded, and the
+%% the '{tuple,5}' information ignored.
+%%
+%% If NewInfo information is given and there exists information about
+%% the register, the old and new type information will be merged.
+%% For instance, {tuple,5} and {tuple,10} will be merged to produce
+%% {tuple,10}.
+
+tdb_update(Uis0, Ts0) ->
+ Uis1 = filter(fun ({{x,_},_Op}) -> true;
+ ({{y,_},_Op}) -> true;
+ (_) -> false
+ end, Uis0),
+ tdb_update1(lists:sort(Uis1), Ts0).
+
+tdb_update1([{Key,kill}|Ops], [{K,_Old}|_]=Db) when Key < K ->
+ tdb_update1(remove_key(Key, Ops), Db);
+tdb_update1([{Key,_New}=New|Ops], [{K,_Old}|_]=Db) when Key < K ->
+ [New|tdb_update1(Ops, Db)];
+tdb_update1([{Key,kill}|Ops], [{Key,_}|Db]) ->
+ tdb_update1(remove_key(Key, Ops), Db);
+tdb_update1([{Key,NewInfo}|Ops], [{Key,OldInfo}|Db]) ->
+ [{Key,merge_type_info(NewInfo, OldInfo)}|tdb_update1(Ops, Db)];
+tdb_update1([{_,_}|_]=Ops, [Old|Db]) ->
+ [Old|tdb_update1(Ops, Db)];
+tdb_update1([{Key,kill}|Ops], []) ->
+ tdb_update1(remove_key(Key, Ops), []);
+tdb_update1([{_,_}=New|Ops], []) ->
+ [New|tdb_update1(Ops, [])];
+tdb_update1([], Db) -> Db.
+
+%% tdb_kill_xregs(Db) -> NewDb
+%% Kill all information about x registers. Also kill all tuple_element
+%% dependencies from y registers to x registers.
+
+tdb_kill_xregs([{{x,_},_Type}|Db]) -> tdb_kill_xregs(Db);
+tdb_kill_xregs([{{y,_},{tuple_element,{x,_},_}}|Db]) -> tdb_kill_xregs(Db);
+tdb_kill_xregs([Any|Db]) -> [Any|tdb_kill_xregs(Db)];
+tdb_kill_xregs([]) -> [].
+
+remove_key(Key, [{Key,_Op}|Ops]) -> remove_key(Key, Ops);
+remove_key(_, Ops) -> Ops.
+
+merge_type_info(I, I) -> I;
+merge_type_info({tuple,Sz1,Same}, {tuple,Sz2,Same}=Max) when Sz1 < Sz2 ->
+ Max;
+merge_type_info({tuple,Sz1,Same}=Max, {tuple,Sz2,Same}) when Sz1 > Sz2 ->
+ Max;
+merge_type_info({tuple,Sz1,[]}, {tuple,Sz2,First}) ->
+ merge_type_info({tuple,Sz1,First}, {tuple,Sz2,First});
+merge_type_info({tuple,Sz1,First}, {tuple,Sz2,_}) ->
+ merge_type_info({tuple,Sz1,First}, {tuple,Sz2,First});
+merge_type_info(NewType, _) ->
+ verify_type(NewType),
+ NewType.
+
+verify_type({tuple,Sz,[]}) when is_integer(Sz) -> ok;
+verify_type({tuple,Sz,[_]}) when is_integer(Sz) -> ok;
+verify_type({tuple_element,_,_}) -> ok;
+verify_type(float) -> ok;
+verify_type({atom,_}) -> ok.
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_validator.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_validator.erl
new file mode 100644
index 0000000000..87c1c54d0f
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_validator.erl
@@ -0,0 +1,1022 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: beam_validator.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
+
+-module(beam_validator).
+
+-export([file/1,files/1]).
+
+%% Interface for compiler.
+-export([module/2,format_error/1]).
+
+-import(lists, [reverse/1,foldl/3]).
+
+-define(MAXREG, 1024).
+
+-define(DEBUG, 1).
+-undef(DEBUG).
+-ifdef(DEBUG).
+-define(DBG_FORMAT(F, D), (io:format((F), (D)))).
+-else.
+-define(DBG_FORMAT(F, D), ok).
+-endif.
+
+%%%
+%%% API functions.
+%%%
+
+files([F|Fs]) ->
+ ?DBG_FORMAT("# Verifying: ~p~n", [F]),
+ case file(F) of
+ ok -> ok;
+ {error,Es} ->
+ io:format("~p:~n~s~n", [F,format_error(Es)])
+ end,
+ files(Fs);
+files([]) -> ok.
+
+file(Name) when is_list(Name) ->
+ case case filename:extension(Name) of
+ ".S" -> s_file(Name);
+ ".beam" -> beam_file(Name)
+ end of
+ [] -> ok;
+ Es -> {error,Es}
+ end.
+
+%% To be called by the compiler.
+module({Mod,Exp,Attr,Fs,Lc}=Code, _Opts)
+ when is_atom(Mod), is_list(Exp), is_list(Attr), is_integer(Lc) ->
+ case validate(Fs) of
+ [] -> {ok,Code};
+ Es0 ->
+ Es = [{?MODULE,E} || E <- Es0],
+ {error,[{atom_to_list(Mod),Es}]}
+ end.
+
+format_error([]) -> [];
+format_error([{{M,F,A},{I,Off,Desc}}|Es]) ->
+ [io_lib:format(" ~p:~p/~p+~p:~n ~p - ~p~n",
+ [M,F,A,Off,I,Desc])|format_error(Es)];
+format_error({{_M,F,A},{I,Off,Desc}}) ->
+ io_lib:format(
+ "function ~p/~p+~p:~n"
+ " Internal consistency check failed - please report this bug.~n"
+ " Instruction: ~p~n"
+ " Error: ~p:~n", [F,A,Off,I,Desc]).
+
+%%%
+%%% Local functions follow.
+%%%
+
+s_file(Name) ->
+ {ok,Is} = file:consult(Name),
+ Fs = find_functions(Is),
+ validate(Fs).
+
+find_functions(Fs) ->
+ find_functions_1(Fs, none, [], []).
+
+find_functions_1([{function,Name,Arity,Entry}|Is], Func, FuncAcc, Acc0) ->
+ Acc = add_func(Func, FuncAcc, Acc0),
+ find_functions_1(Is, {Name,Arity,Entry}, [], Acc);
+find_functions_1([I|Is], Func, FuncAcc, Acc) ->
+ find_functions_1(Is, Func, [I|FuncAcc], Acc);
+find_functions_1([], Func, FuncAcc, Acc) ->
+ reverse(add_func(Func, FuncAcc, Acc)).
+
+add_func(none, _, Acc) -> Acc;
+add_func({Name,Arity,Entry}, Is, Acc) ->
+ [{function,Name,Arity,Entry,reverse(Is)}|Acc].
+
+beam_file(Name) ->
+ try beam_disasm:file(Name) of
+ {error,beam_lib,Reason} -> [{beam_lib,Reason}];
+ {beam_file,L} ->
+ {value,{code,Code0}} = lists:keysearch(code, 1, L),
+ Code = beam_file_1(Code0, []),
+ validate(Code)
+ catch _:_ -> [disassembly_failed]
+ end.
+
+beam_file_1([F0|Fs], Acc) ->
+ F = conv_func(F0),
+ beam_file_1(Fs, [F|Acc]);
+beam_file_1([], Acc) -> reverse(Acc).
+
+%% Convert from the disassembly format to the internal format
+%% used by the compiler (as passed to the assembler).
+
+conv_func(Is) ->
+ conv_func_1(labels(Is)).
+
+conv_func_1({Ls,[{func_info,[{atom,M},{atom,F},Ar]},
+ {label,Entry}=Le|Is]}) ->
+ %% The entry label gets maybe not correct here
+ {function,F,Ar,Entry,
+ [{label,L}||L<-Ls]++[{func_info,{atom,M},{atom,F},Ar},Le|Is]}.
+
+%%%
+%%% The validator follows.
+%%%
+%%% The purpose of the validator is find errors in the generated code
+%%% that may cause the emulator to crash or behave strangely.
+%%% We don't care about type errors in the user's code that will
+%%% cause a proper exception at run-time.
+%%%
+
+%%% Things currently not checked. XXX
+%%%
+%%% - That floating point registers are initialized before used.
+%%% - That fclearerror and fcheckerror are used properly.
+%%% - Heap allocation for floating point numbers.
+%%% - Heap allocation for binaries.
+%%% - That a catchtag or trytag is not overwritten by the wrong
+%%% type of instruction (such as move/2).
+%%% - Make sure that all catchtags and trytags have been removed
+%%% from the stack at return/tail call.
+%%% - Verify get_list instructions.
+%%%
+
+%% validate([Function]) -> [] | [Error]
+%% A list of functions with their code. The code is in the same
+%% format as used in the compiler and in .S files.
+validate([]) -> [];
+validate([{function,Name,Ar,Entry,Code}|Fs]) ->
+ try validate_1(Code, Name, Ar, Entry) of
+ _ -> validate(Fs)
+ catch
+ Error ->
+ [Error|validate(Fs)];
+ error:Error ->
+ [validate_error(Error, Name, Ar)|validate(Fs)]
+ end.
+
+-ifdef(DEBUG).
+validate_error(Error, Name, Ar) ->
+ exit(validate_error_1(Error, Name, Ar)).
+-else.
+validate_error(Error, Name, Ar) ->
+ validate_error_1(Error, Name, Ar).
+-endif.
+validate_error_1(Error, Name, Ar) ->
+ {{'_',Name,Ar},
+ {internal_error,'_',{Error,erlang:get_stacktrace()}}}.
+
+-record(st, %Emulation state
+ {x=init_regs(0, term), %x register info.
+ y=init_regs(0, initialized), %y register info.
+ numy=none, %Number of y registers.
+ h=0, %Available heap size.
+ ct=[] %List of hot catch/try labels
+ }).
+
+-record(vst, %Validator state
+ {current=none, %Current state
+ branched=gb_trees:empty() %States at jumps
+ }).
+
+-ifdef(DEBUG).
+print_st(#st{x=Xs,y=Ys,numy=NumY,h=H,ct=Ct}) ->
+ io:format(" #st{x=~p~n"
+ " y=~p~n"
+ " numy=~p,h=~p,ct=~w~n",
+ [gb_trees:to_list(Xs),gb_trees:to_list(Ys),NumY,H,Ct]).
+-endif.
+
+validate_1(Is, Name, Arity, Entry) ->
+ validate_2(labels(Is), Name, Arity, Entry).
+
+validate_2({Ls1,[{func_info,{atom,Mod},{atom,Name},Arity}=_F|Is]},
+ Name, Arity, Entry) ->
+ lists:foreach(fun (_L) -> ?DBG_FORMAT(" ~p.~n", [_L]) end, Ls1),
+ ?DBG_FORMAT(" ~p.~n", [_F]),
+ validate_3(labels(Is), Name, Arity, Entry, Mod, Ls1);
+validate_2({Ls1,Is}, Name, Arity, _Entry) ->
+ error({{'_',Name,Arity},{first(Is),length(Ls1),illegal_instruction}}).
+
+validate_3({Ls2,Is}, Name, Arity, Entry, Mod, Ls1) ->
+ lists:foreach(fun (_L) -> ?DBG_FORMAT(" ~p.~n", [_L]) end, Ls2),
+ Offset = 1 + length(Ls2),
+ case lists:member(Entry, Ls2) of
+ true ->
+ St = init_state(Arity),
+ Vst = #vst{current=St,
+ branched=gb_trees_from_list([{L,St} || L <- Ls1])},
+ valfun(Is, {Mod,Name,Arity}, Offset, Vst);
+ false ->
+ error({{Mod,Name,Arity},{first(Is),Offset,no_entry_label}})
+ end.
+
+first([X|_]) -> X;
+first([]) -> [].
+
+labels(Is) ->
+ labels_1(Is, []).
+
+labels_1([{label,L}|Is], R) ->
+ labels_1(Is, [L|R]);
+labels_1(Is, R) ->
+ {lists:reverse(R),Is}.
+
+init_state(Arity) ->
+ Xs = init_regs(Arity, term),
+ Ys = init_regs(0, initialized),
+ #st{x=Xs,y=Ys,numy=none,h=0,ct=[]}.
+
+init_regs(0, _) ->
+ gb_trees:empty();
+init_regs(N, Type) ->
+ gb_trees_from_list([{R,Type} || R <- lists:seq(0, N-1)]).
+
+valfun([], _MFA, _Offset, Vst) -> Vst;
+valfun([I|Is], MFA, Offset, Vst) ->
+ ?DBG_FORMAT(" ~p.\n", [I]),
+ valfun(Is, MFA, Offset+1,
+ try valfun_1(I, Vst)
+ catch Error ->
+ error({MFA,{I,Offset,Error}})
+ end).
+
+%% Instructions that are allowed in dead code or when failing,
+%% that is while the state is undecided in some way.
+valfun_1({label,Lbl}, #vst{current=St0,branched=B}=Vst) ->
+ St = merge_states(Lbl, St0, B),
+ Vst#vst{current=St,branched=gb_trees:enter(Lbl, St, B)};
+valfun_1(_I, #vst{current=none}=Vst) ->
+ %% Ignore instructions after erlang:error/1,2, which
+ %% the original R10B compiler thought would return.
+ ?DBG_FORMAT("Ignoring ~p\n", [_I]),
+ Vst;
+valfun_1({badmatch,Src}, Vst) ->
+ assert_term(Src, Vst),
+ kill_state(Vst);
+valfun_1({case_end,Src}, Vst) ->
+ assert_term(Src, Vst),
+ kill_state(Vst);
+valfun_1(if_end, Vst) ->
+ kill_state(Vst);
+valfun_1({try_case_end,Src}, Vst) ->
+ assert_term(Src, Vst),
+ kill_state(Vst);
+%% Instructions that can not cause exceptions
+valfun_1({move,Src,Dst}, Vst) ->
+ Type = get_term_type(Src, Vst),
+ set_type_reg(Type, Dst, Vst);
+valfun_1({fmove,Src,{fr,_}}, Vst) ->
+ assert_type(float, Src, Vst);
+valfun_1({fmove,{fr,_},Dst}, Vst) ->
+ set_type_reg({float,[]}, Dst, Vst);
+valfun_1({kill,{y,_}=Reg}, Vst) ->
+ set_type_y(initialized, Reg, Vst);
+valfun_1({test_heap,Heap,Live}, Vst) ->
+ test_heap(Heap, Live, Vst);
+valfun_1({bif,_Op,nofail,Src,Dst}, Vst) ->
+ validate_src(Src, Vst),
+ set_type_reg(term, Dst, Vst);
+%% Put instructions.
+valfun_1({put_list,A,B,Dst}, Vst0) ->
+ assert_term(A, Vst0),
+ assert_term(B, Vst0),
+ Vst = eat_heap(2, Vst0),
+ set_type_reg(cons, Dst, Vst);
+valfun_1({put_tuple,Sz,Dst}, Vst0) when is_integer(Sz) ->
+ Vst = eat_heap(1, Vst0),
+ set_type_reg({tuple,Sz}, Dst, Vst);
+valfun_1({put,Src}, Vst) ->
+ assert_term(Src, Vst),
+ eat_heap(1, Vst);
+valfun_1({put_string,Sz,_,Dst}, Vst0) when is_integer(Sz) ->
+ Vst = eat_heap(2*Sz, Vst0),
+ set_type_reg(cons, Dst, Vst);
+%% Allocate and deallocate, et.al
+valfun_1({allocate,Stk,Live}, Vst) ->
+ allocate(false, Stk, 0, Live, Vst);
+valfun_1({allocate_heap,Stk,Heap,Live}, Vst) ->
+ allocate(false, Stk, Heap, Live, Vst);
+valfun_1({allocate_zero,Stk,Live}, Vst) ->
+ allocate(true, Stk, 0, Live, Vst);
+valfun_1({allocate_heap_zero,Stk,Heap,Live}, Vst) ->
+ allocate(true, Stk, Heap, Live, Vst);
+valfun_1({init,{y,_}=Reg}, Vst) ->
+ set_type_y(initialized, Reg, Vst);
+valfun_1({deallocate,StkSize}, #vst{current=#st{numy=StkSize,ct=[]}}=Vst) ->
+ deallocate(Vst);
+valfun_1({deallocate,_}, #vst{current=#st{numy=NumY,ct=[]}}) ->
+ error({allocated,NumY});
+valfun_1({deallocate,_}, #vst{current=#st{ct=Fails}}) ->
+ error({catch_try_stack,Fails});
+%% Catch & try.
+valfun_1({'catch',Dst,{f,Fail}}, Vst0) when Fail /= none ->
+ Vst = #vst{current=#st{ct=Fails}=St} =
+ set_type_y({catchtag,Fail}, Dst, Vst0),
+ Vst#vst{current=St#st{ct=[Fail|Fails]}};
+valfun_1({'try',Dst,{f,Fail}}, Vst0) ->
+ Vst = #vst{current=#st{ct=Fails}=St} =
+ set_type_y({trytag,Fail}, Dst, Vst0),
+ Vst#vst{current=St#st{ct=[Fail|Fails]}};
+%% Do a postponed state branch if necessary and try next set of instructions
+valfun_1(I, #vst{current=#st{ct=[]}}=Vst) ->
+ valfun_2(I, Vst);
+valfun_1(I, #vst{current=#st{ct=Fails}}=Vst0) ->
+ %% Perform a postponed state branch
+ Vst = #vst{current=St} = lists:foldl(fun branch_state/2, Vst0, Fails),
+ valfun_2(I, Vst#vst{current=St#st{ct=[]}}).
+
+%% Instructions that can cause exceptions.
+valfun_2({apply,Live}, Vst) ->
+ call(Live+2, Vst);
+valfun_2({apply_last,Live,_}, Vst) ->
+ tail_call(Live+2, Vst);
+valfun_2({call_fun,Live}, Vst) ->
+ call(Live, Vst);
+valfun_2({call,Live,_}, Vst) ->
+ call(Live, Vst);
+valfun_2({call_ext,Live,Func}, Vst) ->
+ call(Func, Live, Vst);
+valfun_2({call_only,Live,_}, Vst) ->
+ tail_call(Live, Vst);
+valfun_2({call_ext_only,Live,_}, Vst) ->
+ tail_call(Live, Vst);
+valfun_2({call_last,Live,_,_}, Vst) ->
+ tail_call(Live, Vst);
+valfun_2({call_ext_last,Live,_,_}, Vst) ->
+ tail_call(Live, Vst);
+valfun_2({make_fun,_,_,Live}, Vst) ->
+ call(Live, Vst);
+valfun_2({make_fun2,_,_,_,Live}, Vst) ->
+ call(Live, Vst);
+%% Floating point.
+valfun_2({fconv,Src,{fr,_}}, Vst) ->
+ assert_term(Src, Vst);
+valfun_2({bif,fadd,_,[{fr,_},{fr,_}],{fr,_}}, Vst) ->
+ Vst;
+valfun_2({bif,fdiv,_,[{fr,_},{fr,_}],{fr,_}}, Vst) ->
+ Vst;
+valfun_2({bif,fmul,_,[{fr,_},{fr,_}],{fr,_}}, Vst) ->
+ Vst;
+valfun_2({bif,fnegate,_,[{fr,_}],{fr,_}}, Vst) ->
+ Vst;
+valfun_2({bif,fsub,_,[{fr,_},{fr,_}],{fr,_}}, Vst) ->
+ Vst;
+valfun_2(fclearerror, Vst) ->
+ Vst;
+valfun_2({fcheckerror,_}, Vst) ->
+ Vst;
+%% Other BIFs
+valfun_2({bif,element,{f,Fail},[Pos,Tuple],Dst}, Vst0) ->
+ TupleType0 = get_term_type(Tuple, Vst0),
+ PosType = get_term_type(Pos, Vst0),
+ Vst1 = branch_state(Fail, Vst0),
+ TupleType = upgrade_type({tuple,[get_tuple_size(PosType)]}, TupleType0),
+ Vst = set_type(TupleType, Tuple, Vst1),
+ set_type_reg(term, Dst, Vst);
+valfun_2({bif,Op,{f,Fail},Src,Dst}, Vst0) ->
+ validate_src(Src, Vst0),
+ Vst = branch_state(Fail, Vst0),
+ Type = bif_type(Op, Src, Vst),
+ set_type_reg(Type, Dst, Vst);
+valfun_2(return, #vst{current=#st{numy=none}}=Vst) ->
+ kill_state(Vst);
+valfun_2(return, #vst{current=#st{numy=NumY}}) ->
+ error({stack_frame,NumY});
+valfun_2({jump,{f,_}}, #vst{current=none}=Vst) ->
+ %% Must be an unreachable jump which was not optimized away.
+ %% Do nothing.
+ Vst;
+valfun_2({jump,{f,Lbl}}, Vst) ->
+ kill_state(branch_state(Lbl, Vst));
+valfun_2({loop_rec,{f,Fail},Dst}, Vst0) ->
+ Vst = branch_state(Fail, Vst0),
+ set_type_reg(term, Dst, Vst);
+valfun_2(remove_message, Vst) ->
+ Vst;
+valfun_2({wait,_}, Vst) ->
+ kill_state(Vst);
+valfun_2({wait_timeout,_,Src}, Vst) ->
+ assert_term(Src, Vst);
+valfun_2({loop_rec_end,_}, Vst) ->
+ kill_state(Vst);
+valfun_2(timeout, #vst{current=St}=Vst) ->
+ Vst#vst{current=St#st{x=init_regs(0, term)}};
+valfun_2(send, Vst) ->
+ call(2, Vst);
+%% Catch & try.
+valfun_2({catch_end,Reg}, Vst0) ->
+ case get_type(Reg, Vst0) of
+ {catchtag,_} ->
+ Vst = #vst{current=St} = set_type_reg(initialized, Reg, Vst0),
+ Xs = gb_trees_from_list([{0,term}]),
+ Vst#vst{current=St#st{x=Xs}};
+ Type ->
+ error({bad_type,Type})
+ end;
+valfun_2({try_end,Reg}, Vst) ->
+ case get_type(Reg, Vst) of
+ {trytag,_} ->
+ set_type_reg(initialized, Reg, Vst);
+ Type ->
+ error({bad_type,Type})
+ end;
+valfun_2({try_case,Reg}, Vst0) ->
+ case get_type(Reg, Vst0) of
+ {trytag,_} ->
+ Vst = #vst{current=St} = set_type_reg(initialized, Reg, Vst0),
+ Xs = gb_trees_from_list([{0,{atom,[]}},{1,term},{2,term}]),
+ Vst#vst{current=St#st{x=Xs}};
+ Type ->
+ error({bad_type,Type})
+ end;
+valfun_2({set_tuple_element,Src,Tuple,I}, Vst) ->
+ assert_term(Src, Vst),
+ assert_type({tuple_element,I+1}, Tuple, Vst);
+%% Match instructions.
+valfun_2({select_val,Src,{f,Fail},{list,Choices}}, Vst) ->
+ assert_term(Src, Vst),
+ Lbls = [L || {f,L} <- Choices]++[Fail],
+ kill_state(foldl(fun(L, S) -> branch_state(L, S) end, Vst, Lbls));
+valfun_2({select_tuple_arity,Tuple,{f,Fail},{list,Choices}}, Vst) ->
+ assert_type(tuple, Tuple, Vst),
+ kill_state(branch_arities(Choices, Tuple, branch_state(Fail, Vst)));
+valfun_2({get_list,Src,D1,D2}, Vst0) ->
+ assert_term(Src, Vst0),
+ Vst = set_type_reg(term, D1, Vst0),
+ set_type_reg(term, D2, Vst);
+valfun_2({get_tuple_element,Src,I,Dst}, Vst) ->
+ assert_type({tuple_element,I+1}, Src, Vst),
+ set_type_reg(term, Dst, Vst);
+valfun_2({bs_restore,_}, Vst) ->
+ Vst;
+valfun_2({bs_save,_}, Vst) ->
+ Vst;
+valfun_2({bs_start_match,{f,Fail},Src}, Vst) ->
+ assert_term(Src, Vst),
+ branch_state(Fail, Vst);
+valfun_2({test,bs_skip_bits,{f,Fail},[Src,_,_]}, Vst) ->
+ assert_term(Src, Vst),
+ branch_state(Fail, Vst);
+valfun_2({test,_,{f,Fail},[_,_,_,Dst]}, Vst0) ->
+ Vst = branch_state(Fail, Vst0),
+ set_type_reg({integer,[]}, Dst, Vst);
+valfun_2({test,bs_test_tail,{f,Fail},_}, Vst) ->
+ branch_state(Fail, Vst);
+%% Other test instructions.
+valfun_2({test,is_float,{f,Lbl},[Float]}, Vst0) ->
+ assert_term(Float, Vst0),
+ Vst = branch_state(Lbl, Vst0),
+ set_type({float,[]}, Float, Vst);
+valfun_2({test,is_tuple,{f,Lbl},[Tuple]}, Vst0) ->
+ assert_term(Tuple, Vst0),
+ Vst = branch_state(Lbl, Vst0),
+ set_type({tuple,[0]}, Tuple, Vst);
+valfun_2({test,test_arity,{f,Lbl},[Tuple,Sz]}, Vst0) when is_integer(Sz) ->
+ assert_type(tuple, Tuple, Vst0),
+ Vst = branch_state(Lbl, Vst0),
+ set_type_reg({tuple,Sz}, Tuple, Vst);
+valfun_2({test,_Op,{f,Lbl},Src}, Vst) ->
+ validate_src(Src, Vst),
+ branch_state(Lbl, Vst);
+valfun_2({bs_add,{f,Fail},[A,B,_],Dst}, Vst0) ->
+ assert_term(A, Vst0),
+ assert_term(B, Vst0),
+ Vst = branch_state(Fail, Vst0),
+ set_type_reg({integer,[]}, Dst, Vst);
+valfun_2({bs_bits_to_bytes,{f,Fail},Src,Dst}, Vst0) ->
+ assert_term(Src, Vst0),
+ Vst = branch_state(Fail, Vst0),
+ set_type_reg({integer,[]}, Dst, Vst);
+valfun_2({bs_init2,{f,Fail},_,Heap,_,_,Dst}, Vst0) ->
+ Vst1 = heap_alloc(Heap, Vst0),
+ Vst = branch_state(Fail, Vst1),
+ set_type_reg(binary, Dst, Vst);
+valfun_2({bs_put_string,Sz,_}, Vst) when is_integer(Sz) ->
+ Vst;
+valfun_2({bs_put_binary,{f,Fail},_,_,_,Src}, Vst0) ->
+ assert_term(Src, Vst0),
+ branch_state(Fail, Vst0);
+valfun_2({bs_put_float,{f,Fail},_,_,_,Src}, Vst0) ->
+ assert_term(Src, Vst0),
+ branch_state(Fail, Vst0);
+valfun_2({bs_put_integer,{f,Fail},_,_,_,Src}, Vst0) ->
+ assert_term(Src, Vst0),
+ branch_state(Fail, Vst0);
+%% Old bit syntax construction (before R10B).
+valfun_2({bs_init,_,_}, Vst) -> Vst;
+valfun_2({bs_need_buf,_}, Vst) -> Vst;
+valfun_2({bs_final,{f,Fail},Dst}, Vst0) ->
+ Vst = branch_state(Fail, Vst0),
+ set_type_reg(binary, Dst, Vst);
+%% Misc.
+valfun_2({'%live',Live}, Vst) ->
+ verify_live(Live, Vst),
+ Vst;
+valfun_2(_, _) ->
+ error(unknown_instruction).
+
+kill_state(#vst{current=#st{ct=[]}}=Vst) ->
+ Vst#vst{current=none};
+kill_state(#vst{current=#st{ct=Fails}}=Vst0) ->
+ Vst = lists:foldl(fun branch_state/2, Vst0, Fails),
+ Vst#vst{current=none}.
+
+%% A "plain" call.
+%% The stackframe must have a known size and be initialized.
+%% The instruction will return to the instruction following the call.
+call(Live, #vst{current=St}=Vst) ->
+ verify_live(Live, Vst),
+ verify_y_init(Vst),
+ Xs = gb_trees_from_list([{0,term}]),
+ Vst#vst{current=St#st{x=Xs}}.
+
+%% A "plain" call.
+%% The stackframe must have a known size and be initialized.
+%% The instruction will return to the instruction following the call.
+call(Name, Live, #vst{current=St}=Vst) ->
+ verify_live(Live, Vst),
+ case return_type(Name, Vst) of
+ exception ->
+ kill_state(Vst);
+ Type ->
+ verify_y_init(Vst),
+ Xs = gb_trees_from_list([{0,Type}]),
+ Vst#vst{current=St#st{x=Xs}}
+ end.
+
+%% Tail call.
+%% The stackframe must have a known size and be initialized.
+%% Does not return to the instruction following the call.
+tail_call(Live, Vst) ->
+ kill_state(call(Live, Vst)).
+
+allocate(Zero, Stk, Heap, Live, #vst{current=#st{numy=none}=St}=Vst) ->
+ verify_live(Live, Vst),
+ Ys = init_regs(case Zero of
+ true -> Stk;
+ false -> 0
+ end, initialized),
+ Vst#vst{current=St#st{y=Ys,numy=Stk,h=heap_alloc_1(Heap)}};
+allocate(_, _, _, _, #vst{current=#st{numy=Numy}}) ->
+ error({existing_stack_frame,{size,Numy}}).
+
+deallocate(#vst{current=St}=Vst) ->
+ Vst#vst{current=St#st{y=init_regs(0, initialized),numy=none}}.
+
+test_heap(Heap, Live, Vst) ->
+ verify_live(Live, Vst),
+ heap_alloc(Heap, Vst).
+
+heap_alloc(Heap, #vst{current=St}=Vst) ->
+ Vst#vst{current=St#st{h=heap_alloc_1(Heap)}}.
+
+heap_alloc_1({alloc,Alloc}) ->
+ {value,{_,Heap}} = lists:keysearch(words, 1, Alloc),
+ Heap;
+heap_alloc_1(Heap) when is_integer(Heap) -> Heap.
+
+
+set_type(Type, {x,_}=Reg, Vst) -> set_type_reg(Type, Reg, Vst);
+set_type(Type, {y,_}=Reg, Vst) -> set_type_y(Type, Reg, Vst);
+set_type(_, _, #vst{}=Vst) -> Vst.
+
+set_type_reg(Type, {x,X}, #vst{current=#st{x=Xs}=St}=Vst)
+ when 0 =< X, X < ?MAXREG ->
+ Vst#vst{current=St#st{x=gb_trees:enter(X, Type, Xs)}};
+set_type_reg(Type, Reg, Vst) ->
+ set_type_y(Type, Reg, Vst).
+
+set_type_y(Type, {y,Y}=Reg, #vst{current=#st{y=Ys,numy=NumY}=St}=Vst)
+ when is_integer(Y), 0 =< Y, Y < ?MAXREG ->
+ case {Y,NumY} of
+ {_,none} ->
+ error({no_stack_frame,Reg});
+ {_,_} when Y > NumY ->
+ error({y_reg_out_of_range,Reg,NumY});
+ {_,_} ->
+ Vst#vst{current=St#st{y=gb_trees:enter(Y, Type, Ys)}}
+ end;
+set_type_y(Type, Reg, #vst{}) -> error({invalid_store,Reg,Type}).
+
+assert_term(Src, Vst) ->
+ get_term_type(Src, Vst),
+ Vst.
+
+%% The possible types.
+%%
+%% First non-term types:
+%%
+%% initialized Only for Y registers. Means that the Y register
+%% has been initialized with some valid term so that
+%% it is safe to pass to the garbage collector.
+%% NOT safe to use in any other way (will not crash the
+%% emulator, but clearly points to a bug in the compiler).
+%%
+%% {catchtag,Lbl} A special term used within a catch. Must only be used
+%% by the catch instructions; NOT safe to use in other
+%% instructions.
+%%
+%% {trytag,Lbl} A special term used within a try block. Must only be
+%% used by the catch instructions; NOT safe to use in other
+%% instructions.
+%%
+%% exception Can only be used as a type returned by return_type/2
+%% (which gives the type of the value returned by a BIF).
+%% Thus 'exception' is never stored as type descriptor
+%% for a register.
+%%
+%% Normal terms:
+%%
+%% term Any valid Erlang (but not of the special types above).
+%%
+%% bool The atom 'true' or the atom 'false'.
+%%
+%% cons Cons cell: [_|_]
+%%
+%% nil Empty list: []
+%%
+%% {tuple,[Sz]} Tuple. An element has been accessed using
+%% element/2 or setelement/3 so that it is known that
+%% the type is a tuple of size at least Sz.
+%%
+%% {tuple,Sz} Tuple. A test_arity instruction has been seen
+%% so that it is known that the size is exactly Sz.
+%%
+%% {atom,[]} Atom.
+%% {atom,Atom}
+%%
+%% {integer,[]} Integer.
+%% {integer,Integer}
+%%
+%% {float,[]} Float.
+%% {float,Float}
+%%
+%% number Integer or Float of unknown value
+%%
+
+assert_type(WantedType, Term, Vst) ->
+ assert_type(WantedType, get_type(Term, Vst)),
+ Vst.
+
+assert_type(float, {float,_}) -> ok;
+assert_type(tuple, {tuple,_}) -> ok;
+assert_type({tuple_element,I}, {tuple,[Sz]})
+ when 1 =< I, I =< Sz ->
+ ok;
+assert_type({tuple_element,I}, {tuple,Sz})
+ when is_integer(Sz), 1 =< I, I =< Sz ->
+ ok;
+assert_type(Needed, Actual) ->
+ error({bad_type,{needed,Needed},{actual,Actual}}).
+
+%% upgrade_type/2 is used when linear code finds out more and
+%% more information about a type, so the type gets "narrower"
+%% or perhaps inconsistent. In the case of inconsistency
+%% we mostly widen the type to 'term' to make subsequent
+%% code fail if it assumes anything about the type.
+
+upgrade_type(Same, Same) -> Same;
+upgrade_type(term, OldT) -> OldT;
+upgrade_type(NewT, term) -> NewT;
+upgrade_type({Type,New}=NewT, {Type,Old}=OldT)
+ when Type == atom; Type == integer; Type == float ->
+ if New =:= Old -> OldT;
+ New =:= [] -> OldT;
+ Old =:= [] -> NewT;
+ true -> term
+ end;
+upgrade_type({Type,_}=NewT, number)
+ when Type == integer; Type == float ->
+ NewT;
+upgrade_type(number, {Type,_}=OldT)
+ when Type == integer; Type == float ->
+ OldT;
+upgrade_type(bool, {atom,A}) ->
+ upgrade_bool(A);
+upgrade_type({atom,A}, bool) ->
+ upgrade_bool(A);
+upgrade_type({tuple,[Sz]}, {tuple,[OldSz]})
+ when is_integer(Sz) ->
+ {tuple,[max(Sz, OldSz)]};
+upgrade_type({tuple,Sz}=T, {tuple,[_]})
+ when is_integer(Sz) ->
+ %% This also takes care of the user error when a tuple element
+ %% is accesed outside the known exact tuple size; there is
+ %% no more type information, just a runtime error which is not
+ %% our problem.
+ T;
+upgrade_type({tuple,[Sz]}, {tuple,_}=T)
+ when is_integer(Sz) ->
+ %% Same as the previous clause but mirrored.
+ T;
+upgrade_type(_A, _B) ->
+ %%io:format("upgrade_type: ~p ~p\n", [_A,_B]),
+ term.
+
+upgrade_bool([]) -> bool;
+upgrade_bool(true) -> {atom,true};
+upgrade_bool(false) -> {atom,false};
+upgrade_bool(_) -> term.
+
+get_tuple_size({integer,[]}) -> 0;
+get_tuple_size({integer,Sz}) -> Sz;
+get_tuple_size(_) -> 0.
+
+validate_src(Ss, Vst) when is_list(Ss) ->
+ foldl(fun(S, _) -> get_type(S, Vst) end, ok, Ss).
+
+get_term_type(Src, Vst) ->
+ case get_type(Src, Vst) of
+ initialized -> error({not_assigned,Src});
+ exception -> error({exception,Src});
+ {catchtag,_} -> error({catchtag,Src});
+ {trytag,_} -> error({trytag,Src});
+ Type -> Type
+ end.
+
+get_type(nil=T, _) -> T;
+get_type({atom,A}=T, _) when is_atom(A) -> T;
+get_type({float,F}=T, _) when is_float(F) -> T;
+get_type({integer,I}=T, _) when is_integer(I) -> T;
+get_type({x,X}=Reg, #vst{current=#st{x=Xs}}) when is_integer(X) ->
+ case gb_trees:lookup(X, Xs) of
+ {value,Type} -> Type;
+ none -> error({uninitialized_reg,Reg})
+ end;
+get_type({y,Y}=Reg, #vst{current=#st{y=Ys}}) when is_integer(Y) ->
+ case gb_trees:lookup(Y, Ys) of
+ {value,initialized} -> error({unassigned_reg,Reg});
+ {value,Type} -> Type;
+ none -> error({uninitialized_reg,Reg})
+ end;
+get_type(Src, _) -> error({bad_source,Src}).
+
+branch_arities([], _, #vst{}=Vst) -> Vst;
+branch_arities([Sz,{f,L}|T], Tuple, #vst{current=St}=Vst0)
+ when is_integer(Sz) ->
+ Vst1 = set_type_reg({tuple,Sz}, Tuple, Vst0),
+ Vst = branch_state(L, Vst1),
+ branch_arities(T, Tuple, Vst#vst{current=St}).
+
+branch_state(0, #vst{}=Vst) -> Vst;
+branch_state(L, #vst{current=St,branched=B}=Vst) ->
+ Vst#vst{
+ branched=case gb_trees:is_defined(L, B) of
+ false ->
+ gb_trees:insert(L, St#st{ct=[]}, B);
+ true ->
+ MergedSt = merge_states(L, St, B),
+ gb_trees:update(L, MergedSt#st{ct=[]}, B)
+ end}.
+
+%% merge_states/3 is used when there are more than one way to arrive
+%% at this point, and the type states for the different paths has
+%% to be merged. The type states are downgraded to the least common
+%% subset for the subsequent code.
+
+merge_states(0, St, _Branched) -> St;
+merge_states(L, St, Branched) ->
+ case gb_trees:lookup(L, Branched) of
+ none -> St;
+ {value,OtherSt} when St == none -> OtherSt;
+ {value,OtherSt} ->
+ merge_states_1(St, OtherSt)
+ end.
+
+merge_states_1(#st{x=Xs0,y=Ys0,numy=NumY0,h=H0}=St,
+ #st{x=Xs1,y=Ys1,numy=NumY1,h=H1}) ->
+ NumY = merge_stk(NumY0, NumY1),
+ Xs = merge_regs(Xs0, Xs1),
+ Ys = merge_regs(Ys0, Ys1),
+ St#st{x=Xs,y=Ys,numy=NumY,h=min(H0, H1)}.
+
+merge_stk(S, S) -> S;
+merge_stk(_, _) -> undecided.
+
+merge_regs(Rs0, Rs1) ->
+ Rs = merge_regs_1(gb_trees:to_list(Rs0), gb_trees:to_list(Rs1)),
+ gb_trees_from_list(Rs).
+
+merge_regs_1([Same|Rs1], [Same|Rs2]) ->
+ [Same|merge_regs_1(Rs1, Rs2)];
+merge_regs_1([{R1,_}|Rs1], [{R2,_}|_]=Rs2) when R1 < R2 ->
+ merge_regs_1(Rs1, Rs2);
+merge_regs_1([{R1,_}|_]=Rs1, [{R2,_}|Rs2]) when R1 > R2 ->
+ merge_regs_1(Rs1, Rs2);
+merge_regs_1([{R,Type1}|Rs1], [{R,Type2}|Rs2]) ->
+ [{R,merge_types(Type1, Type2)}|merge_regs_1(Rs1, Rs2)];
+merge_regs_1([], []) -> [];
+merge_regs_1([], [_|_]) -> [];
+merge_regs_1([_|_], []) -> [].
+
+merge_types(T, T) -> T;
+merge_types(initialized=I, _) -> I;
+merge_types(_, initialized=I) -> I;
+merge_types({tuple,Same}=T, {tuple,Same}) -> T;
+merge_types({tuple,A}, {tuple,B}) ->
+ {tuple,[min(tuple_sz(A), tuple_sz(B))]};
+merge_types({Type,A}, {Type,B})
+ when Type == atom; Type == integer; Type == float ->
+ if A =:= B -> {Type,A};
+ true -> {Type,[]}
+ end;
+merge_types({Type,_}, number)
+ when Type == integer; Type == float ->
+ number;
+merge_types(number, {Type,_})
+ when Type == integer; Type == float ->
+ number;
+merge_types(bool, {atom,A}) ->
+ merge_bool(A);
+merge_types({atom,A}, bool) ->
+ merge_bool(A);
+merge_types(_, _) -> term.
+
+tuple_sz([Sz]) -> Sz;
+tuple_sz(Sz) -> Sz.
+
+merge_bool([]) -> {atom,[]};
+merge_bool(true) -> bool;
+merge_bool(false) -> bool;
+merge_bool(_) -> {atom,[]}.
+
+verify_y_init(#vst{current=#st{numy=none}}) -> ok;
+verify_y_init(#vst{current=#st{numy=undecided}}) ->
+ error(unknown_size_of_stackframe);
+verify_y_init(#vst{current=#st{y=Ys,numy=NumY}}) ->
+ verify_y_init_1(NumY, Ys).
+
+verify_y_init_1(0, _) -> ok;
+verify_y_init_1(N, Ys) ->
+ Y = N-1,
+ case gb_trees:is_defined(Y, Ys) of
+ false -> error({{y,Y},not_initialized});
+ true -> verify_y_init_1(Y, Ys)
+ end.
+
+verify_live(0, #vst{}) -> ok;
+verify_live(N, #vst{current=#st{x=Xs}}) ->
+ verify_live_1(N, Xs).
+
+verify_live_1(0, _) -> ok;
+verify_live_1(N, Xs) ->
+ X = N-1,
+ case gb_trees:is_defined(X, Xs) of
+ false -> error({{x,X},not_live});
+ true -> verify_live_1(X, Xs)
+ end.
+
+eat_heap(N, #vst{current=#st{h=Heap0}=St}=Vst) ->
+ case Heap0-N of
+ Neg when Neg < 0 ->
+ error({heap_overflow,{left,Heap0},{wanted,N}});
+ Heap ->
+ Vst#vst{current=St#st{h=Heap}}
+ end.
+
+bif_type('-', Src, Vst) ->
+ arith_type(Src, Vst);
+bif_type('+', Src, Vst) ->
+ arith_type(Src, Vst);
+bif_type('*', Src, Vst) ->
+ arith_type(Src, Vst);
+bif_type(abs, [Num], Vst) ->
+ case get_type(Num, Vst) of
+ {float,_}=T -> T;
+ {integer,_}=T -> T;
+ _ -> number
+ end;
+bif_type(float, _, _) -> {float,[]};
+bif_type('/', _, _) -> {float,[]};
+%% Integer operations.
+bif_type('div', [_,_], _) -> {integer,[]};
+bif_type('rem', [_,_], _) -> {integer,[]};
+bif_type(length, [_], _) -> {integer,[]};
+bif_type(size, [_], _) -> {integer,[]};
+bif_type(trunc, [_], _) -> {integer,[]};
+bif_type(round, [_], _) -> {integer,[]};
+bif_type('band', [_,_], _) -> {integer,[]};
+bif_type('bor', [_,_], _) -> {integer,[]};
+bif_type('bxor', [_,_], _) -> {integer,[]};
+bif_type('bnot', [_], _) -> {integer,[]};
+bif_type('bsl', [_,_], _) -> {integer,[]};
+bif_type('bsr', [_,_], _) -> {integer,[]};
+%% Booleans.
+bif_type('==', [_,_], _) -> bool;
+bif_type('/=', [_,_], _) -> bool;
+bif_type('=<', [_,_], _) -> bool;
+bif_type('<', [_,_], _) -> bool;
+bif_type('>=', [_,_], _) -> bool;
+bif_type('>', [_,_], _) -> bool;
+bif_type('=:=', [_,_], _) -> bool;
+bif_type('=/=', [_,_], _) -> bool;
+bif_type('not', [_], _) -> bool;
+bif_type('and', [_,_], _) -> bool;
+bif_type('or', [_,_], _) -> bool;
+bif_type('xor', [_,_], _) -> bool;
+bif_type(is_atom, [_], _) -> bool;
+bif_type(is_boolean, [_], _) -> bool;
+bif_type(is_binary, [_], _) -> bool;
+bif_type(is_constant, [_], _) -> bool;
+bif_type(is_float, [_], _) -> bool;
+bif_type(is_function, [_], _) -> bool;
+bif_type(is_integer, [_], _) -> bool;
+bif_type(is_list, [_], _) -> bool;
+bif_type(is_number, [_], _) -> bool;
+bif_type(is_pid, [_], _) -> bool;
+bif_type(is_port, [_], _) -> bool;
+bif_type(is_reference, [_], _) -> bool;
+bif_type(is_tuple, [_], _) -> bool;
+%% Misc.
+bif_type(node, [], _) -> {atom,[]};
+bif_type(node, [_], _) -> {atom,[]};
+bif_type(hd, [_], _) -> term;
+bif_type(tl, [_], _) -> term;
+bif_type(get, [_], _) -> term;
+bif_type(raise, [_,_], _) -> exception;
+bif_type(_, _, _) -> term.
+
+arith_type([A,B], Vst) ->
+ case {get_type(A, Vst),get_type(B, Vst)} of
+ {{float,_},_} -> {float,[]};
+ {_,{float,_}} -> {float,[]};
+ {_,_} -> number
+ end;
+arith_type(_, _) -> number.
+
+return_type({extfunc,M,F,A}, Vst) ->
+ return_type_1(M, F, A, Vst).
+
+return_type_1(erlang, setelement, 3, Vst) ->
+ Tuple = {x,1},
+ TupleType =
+ case get_type(Tuple, Vst) of
+ {tuple,_}=TT -> TT;
+ _ -> {tuple,[0]}
+ end,
+ case get_type({x,0}, Vst) of
+ {integer,[]} -> TupleType;
+ {integer,I} -> upgrade_type({tuple,[I]}, TupleType);
+ _ -> TupleType
+ end;
+return_type_1(erlang, F, A, _) ->
+ return_type_erl(F, A);
+return_type_1(math, F, A, _) ->
+ return_type_math(F, A);
+return_type_1(_, _, _, _) -> term.
+
+return_type_erl(exit, 1) -> exception;
+return_type_erl(throw, 1) -> exception;
+return_type_erl(fault, 1) -> exception;
+return_type_erl(fault, 2) -> exception;
+return_type_erl(error, 1) -> exception;
+return_type_erl(error, 2) -> exception;
+return_type_erl(_, _) -> term.
+
+return_type_math(cos, 1) -> {float,[]};
+return_type_math(cosh, 1) -> {float,[]};
+return_type_math(sin, 1) -> {float,[]};
+return_type_math(sinh, 1) -> {float,[]};
+return_type_math(tan, 1) -> {float,[]};
+return_type_math(tanh, 1) -> {float,[]};
+return_type_math(acos, 1) -> {float,[]};
+return_type_math(acosh, 1) -> {float,[]};
+return_type_math(asin, 1) -> {float,[]};
+return_type_math(asinh, 1) -> {float,[]};
+return_type_math(atan, 1) -> {float,[]};
+return_type_math(atanh, 1) -> {float,[]};
+return_type_math(erf, 1) -> {float,[]};
+return_type_math(erfc, 1) -> {float,[]};
+return_type_math(exp, 1) -> {float,[]};
+return_type_math(log, 1) -> {float,[]};
+return_type_math(log10, 1) -> {float,[]};
+return_type_math(sqrt, 1) -> {float,[]};
+return_type_math(atan2, 2) -> {float,[]};
+return_type_math(pow, 2) -> {float,[]};
+return_type_math(pi, 0) -> {float,[]};
+return_type_math(_, _) -> term.
+
+min(A, B) when is_integer(A), is_integer(B), A < B -> A;
+min(A, B) when is_integer(A), is_integer(B) -> B.
+
+max(A, B) when is_integer(A), is_integer(B), A > B -> A;
+max(A, B) when is_integer(A), is_integer(B) -> B.
+
+gb_trees_from_list(L) -> gb_trees:from_orddict(orddict:from_list(L)).
+
+-ifdef(DEBUG).
+error(Error) -> exit(Error).
+-else.
+error(Error) -> throw(Error).
+-endif.
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl.erl
new file mode 100644
index 0000000000..e4bdfc7dbe
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl.erl
@@ -0,0 +1,4169 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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 Richard Carlsson.
+%% Copyright (C) 1999-2002 Richard Carlsson.
+%% Portions created by Ericsson are Copyright 2001, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%%
+%% $Id: cerl.erl,v 1.3 2010/03/04 13:54:20 maria Exp $
+
+%% =====================================================================
+%% @doc Core Erlang abstract syntax trees.
+%%
+%% <p> This module defines an abstract data type for representing Core
+%% Erlang source code as syntax trees.</p>
+%%
+%% <p>A recommended starting point for the first-time user is the
+%% documentation of the function <a
+%% href="#type-1"><code>type/1</code></a>.</p>
+%%
+%% <h3><b>NOTES:</b></h3>
+%%
+%% <p>This module deals with the composition and decomposition of
+%% <em>syntactic</em> entities (as opposed to semantic ones); its
+%% purpose is to hide all direct references to the data structures
+%% used to represent these entities. With few exceptions, the
+%% functions in this module perform no semantic interpretation of
+%% their inputs, and in general, the user is assumed to pass
+%% type-correct arguments - if this is not done, the effects are not
+%% defined.</p>
+%%
+%% <p>The internal representations of abstract syntax trees are
+%% subject to change without notice, and should not be documented
+%% outside this module. Furthermore, we do not give any guarantees on
+%% how an abstract syntax tree may or may not be represented, <em>with
+%% the following exceptions</em>: no syntax tree is represented by a
+%% single atom, such as <code>none</code>, by a list constructor
+%% <code>[X | Y]</code>, or by the empty list <code>[]</code>. This
+%% can be relied on when writing functions that operate on syntax
+%% trees.</p>
+%%
+%% @type cerl(). An abstract Core Erlang syntax tree.
+%%
+%% <p>Every abstract syntax tree has a <em>type</em>, given by the
+%% function <a href="#type-1"><code>type/1</code></a>. In addition,
+%% each syntax tree has a list of <em>user annotations</em> (cf. <a
+%% href="#get_ann-1"><code>get_ann/1</code></a>), which are included
+%% in the Core Erlang syntax.</p>
+
+-module(cerl).
+
+-export([abstract/1, add_ann/2, alias_pat/1, alias_var/1,
+ ann_abstract/2, ann_c_alias/3, ann_c_apply/3, ann_c_atom/2,
+ ann_c_call/4, ann_c_case/3, ann_c_catch/2, ann_c_char/2,
+ ann_c_clause/3, ann_c_clause/4, ann_c_cons/3, ann_c_float/2,
+ ann_c_fname/3, ann_c_fun/3, ann_c_int/2, ann_c_let/4,
+ ann_c_letrec/3, ann_c_module/4, ann_c_module/5, ann_c_nil/1,
+ ann_c_cons_skel/3, ann_c_tuple_skel/2, ann_c_primop/3,
+ ann_c_receive/2, ann_c_receive/4, ann_c_seq/3, ann_c_string/2,
+ ann_c_try/6, ann_c_tuple/2, ann_c_values/2, ann_c_var/2,
+ ann_make_data/3, ann_make_list/2, ann_make_list/3,
+ ann_make_data_skel/3, ann_make_tree/3, apply_args/1,
+ apply_arity/1, apply_op/1, atom_lit/1, atom_name/1, atom_val/1,
+ c_alias/2, c_apply/2, c_atom/1, c_call/3, c_case/2, c_catch/1,
+ c_char/1, c_clause/2, c_clause/3, c_cons/2, c_float/1,
+ c_fname/2, c_fun/2, c_int/1, c_let/3, c_letrec/2, c_module/3,
+ c_module/4, c_nil/0, c_cons_skel/2, c_tuple_skel/1, c_primop/2,
+ c_receive/1, c_receive/3, c_seq/2, c_string/1, c_try/5,
+ c_tuple/1, c_values/1, c_var/1, call_args/1, call_arity/1,
+ call_module/1, call_name/1, case_arg/1, case_arity/1,
+ case_clauses/1, catch_body/1, char_lit/1, char_val/1,
+ clause_arity/1, clause_body/1, clause_guard/1, clause_pats/1,
+ clause_vars/1, concrete/1, cons_hd/1, cons_tl/1, copy_ann/2,
+ data_arity/1, data_es/1, data_type/1, float_lit/1, float_val/1,
+ fname_arity/1, fname_id/1, fold_literal/1, from_records/1,
+ fun_arity/1, fun_body/1, fun_vars/1, get_ann/1, int_lit/1,
+ int_val/1, is_c_alias/1, is_c_apply/1, is_c_atom/1,
+ is_c_call/1, is_c_case/1, is_c_catch/1, is_c_char/1,
+ is_c_clause/1, is_c_cons/1, is_c_float/1, is_c_fname/1,
+ is_c_fun/1, is_c_int/1, is_c_let/1, is_c_letrec/1, is_c_list/1,
+ is_c_module/1, is_c_nil/1, is_c_primop/1, is_c_receive/1,
+ is_c_seq/1, is_c_string/1, is_c_try/1, is_c_tuple/1,
+ is_c_values/1, is_c_var/1, is_data/1, is_leaf/1, is_literal/1,
+ is_literal_term/1, is_print_char/1, is_print_string/1,
+ let_arg/1, let_arity/1, let_body/1, let_vars/1, letrec_body/1,
+ letrec_defs/1, letrec_vars/1, list_elements/1, list_length/1,
+ make_data/2, make_list/1, make_list/2, make_data_skel/2,
+ make_tree/2, meta/1, module_attrs/1, module_defs/1,
+ module_exports/1, module_name/1, module_vars/1,
+ pat_list_vars/1, pat_vars/1, primop_args/1, primop_arity/1,
+ primop_name/1, receive_action/1, receive_clauses/1,
+ receive_timeout/1, seq_arg/1, seq_body/1, set_ann/2,
+ string_lit/1, string_val/1, subtrees/1, to_records/1,
+ try_arg/1, try_body/1, try_vars/1, try_evars/1, try_handler/1,
+ tuple_arity/1, tuple_es/1, type/1, unfold_literal/1,
+ update_c_alias/3, update_c_apply/3, update_c_call/4,
+ update_c_case/3, update_c_catch/2, update_c_clause/4,
+ update_c_cons/3, update_c_cons_skel/3, update_c_fname/2,
+ update_c_fname/3, update_c_fun/3, update_c_let/4,
+ update_c_letrec/3, update_c_module/5, update_c_primop/3,
+ update_c_receive/4, update_c_seq/3, update_c_try/6,
+ update_c_tuple/2, update_c_tuple_skel/2, update_c_values/2,
+ update_c_var/2, update_data/3, update_list/2, update_list/3,
+ update_data_skel/3, update_tree/2, update_tree/3,
+ values_arity/1, values_es/1, var_name/1, c_binary/1,
+ update_c_binary/2, ann_c_binary/2, is_c_binary/1,
+ binary_segments/1, c_bitstr/3, c_bitstr/4, c_bitstr/5,
+ update_c_bitstr/5, update_c_bitstr/6, ann_c_bitstr/5,
+ ann_c_bitstr/6, is_c_bitstr/1, bitstr_val/1, bitstr_size/1,
+ bitstr_bitsize/1, bitstr_unit/1, bitstr_type/1,
+ bitstr_flags/1]).
+
+-include("core_parse.hrl").
+
+
+%% =====================================================================
+%% Representation (general)
+%%
+%% All nodes are represented by tuples of arity 2 or (generally)
+%% greater, whose first element is an atom which uniquely identifies the
+%% type of the node, and whose second element is a (proper) list of
+%% annotation terms associated with the node - this is by default empty.
+%%
+%% For most node constructor functions, there are analogous functions
+%% named 'ann_...', taking one extra argument 'As' (always the first
+%% argument), specifying an annotation list at node creation time.
+%% Similarly, there are also functions named 'update_...', taking one
+%% extra argument 'Old', specifying a node from which all fields not
+%% explicitly given as arguments should be copied (generally, this is
+%% the annotation field only).
+%% =====================================================================
+
+%% This defines the general representation of constant literals:
+
+-record(literal, {ann = [], val}).
+
+
+%% @spec type(Node::cerl()) -> atom()
+%%
+%% @doc Returns the type tag of <code>Node</code>. Current node types
+%% are:
+%%
+%% <p><center><table border="1">
+%% <tr>
+%% <td>alias</td>
+%% <td>apply</td>
+%% <td>binary</td>
+%% <td>bitstr</td>
+%% <td>call</td>
+%% <td>case</td>
+%% <td>catch</td>
+%% </tr><tr>
+%% <td>clause</td>
+%% <td>cons</td>
+%% <td>fun</td>
+%% <td>let</td>
+%% <td>letrec</td>
+%% <td>literal</td>
+%% <td>module</td>
+%% </tr><tr>
+%% <td>primop</td>
+%% <td>receive</td>
+%% <td>seq</td>
+%% <td>try</td>
+%% <td>tuple</td>
+%% <td>values</td>
+%% <td>var</td>
+%% </tr>
+%% </table></center></p>
+%%
+%% <p>Note: The name of the primary constructor function for a node
+%% type is always the name of the type itself, prefixed by
+%% "<code>c_</code>"; recognizer predicates are correspondingly
+%% prefixed by "<code>is_c_</code>". Furthermore, to simplify
+%% preservation of annotations (cf. <code>get_ann/1</code>), there are
+%% analogous constructor functions prefixed by "<code>ann_c_</code>"
+%% and "<code>update_c_</code>", for setting the annotation list of
+%% the new node to either a specific value or to the annotations of an
+%% existing node, respectively.</p>
+%%
+%% @see abstract/1
+%% @see c_alias/2
+%% @see c_apply/2
+%% @see c_binary/1
+%% @see c_bitstr/5
+%% @see c_call/3
+%% @see c_case/2
+%% @see c_catch/1
+%% @see c_clause/3
+%% @see c_cons/2
+%% @see c_fun/2
+%% @see c_let/3
+%% @see c_letrec/2
+%% @see c_module/3
+%% @see c_primop/2
+%% @see c_receive/1
+%% @see c_seq/2
+%% @see c_try/3
+%% @see c_tuple/1
+%% @see c_values/1
+%% @see c_var/1
+%% @see get_ann/1
+%% @see to_records/1
+%% @see from_records/1
+%% @see data_type/1
+%% @see subtrees/1
+%% @see meta/1
+
+type(Node) ->
+ element(1, Node).
+
+
+%% @spec is_leaf(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is a leaf node,
+%% otherwise <code>false</code>. The current leaf node types are
+%% <code>literal</code> and <code>var</code>.
+%%
+%% <p>Note: all literals (cf. <code>is_literal/1</code>) are leaf
+%% nodes, even if they represent structured (constant) values such as
+%% <code>{foo, [bar, baz]}</code>. Also note that variables are leaf
+%% nodes but not literals.</p>
+%%
+%% @see type/1
+%% @see is_literal/1
+
+is_leaf(Node) ->
+ case type(Node) of
+ literal -> true;
+ var -> true;
+ _ -> false
+ end.
+
+
+%% @spec get_ann(cerl()) -> [term()]
+%%
+%% @doc Returns the list of user annotations associated with a syntax
+%% tree node. For a newly created node, this is the empty list. The
+%% annotations may be any terms.
+%%
+%% @see set_ann/2
+
+get_ann(Node) ->
+ element(2, Node).
+
+
+%% @spec set_ann(Node::cerl(), Annotations::[term()]) -> cerl()
+%%
+%% @doc Sets the list of user annotations of <code>Node</code> to
+%% <code>Annotations</code>.
+%%
+%% @see get_ann/1
+%% @see add_ann/2
+%% @see copy_ann/2
+
+set_ann(Node, List) ->
+ setelement(2, Node, List).
+
+
+%% @spec add_ann(Annotations::[term()], Node::cerl()) -> cerl()
+%%
+%% @doc Appends <code>Annotations</code> to the list of user
+%% annotations of <code>Node</code>.
+%%
+%% <p>Note: this is equivalent to <code>set_ann(Node, Annotations ++
+%% get_ann(Node))</code>, but potentially more efficient.</p>
+%%
+%% @see get_ann/1
+%% @see set_ann/2
+
+add_ann(Terms, Node) ->
+ set_ann(Node, Terms ++ get_ann(Node)).
+
+
+%% @spec copy_ann(Source::cerl(), Target::cerl()) -> cerl()
+%%
+%% @doc Copies the list of user annotations from <code>Source</code>
+%% to <code>Target</code>.
+%%
+%% <p>Note: this is equivalent to <code>set_ann(Target,
+%% get_ann(Source))</code>, but potentially more efficient.</p>
+%%
+%% @see get_ann/1
+%% @see set_ann/2
+
+copy_ann(Source, Target) ->
+ set_ann(Target, get_ann(Source)).
+
+
+%% @spec abstract(Term::term()) -> cerl()
+%%
+%% @doc Creates a syntax tree corresponding to an Erlang term.
+%% <code>Term</code> must be a literal term, i.e., one that can be
+%% represented as a source code literal. Thus, it may not contain a
+%% process identifier, port, reference, binary or function value as a
+%% subterm.
+%%
+%% <p>Note: This is a constant time operation.</p>
+%%
+%% @see ann_abstract/2
+%% @see concrete/1
+%% @see is_literal/1
+%% @see is_literal_term/1
+
+abstract(T) ->
+ #literal{val = T}.
+
+
+%% @spec ann_abstract(Annotations::[term()], Term::term()) -> cerl()
+%% @see abstract/1
+
+ann_abstract(As, T) ->
+ #literal{val = T, ann = As}.
+
+
+%% @spec is_literal_term(Term::term()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Term</code> can be
+%% represented as a literal, otherwise <code>false</code>. This
+%% function takes time proportional to the size of <code>Term</code>.
+%%
+%% @see abstract/1
+
+is_literal_term(T) when integer(T) -> true;
+is_literal_term(T) when float(T) -> true;
+is_literal_term(T) when atom(T) -> true;
+is_literal_term([]) -> true;
+is_literal_term([H | T]) ->
+ case is_literal_term(H) of
+ true ->
+ is_literal_term(T);
+ false ->
+ false
+ end;
+is_literal_term(T) when tuple(T) ->
+ is_literal_term_list(tuple_to_list(T));
+is_literal_term(_) ->
+ false.
+
+is_literal_term_list([T | Ts]) ->
+ case is_literal_term(T) of
+ true ->
+ is_literal_term_list(Ts);
+ false ->
+ false
+ end;
+is_literal_term_list([]) ->
+ true.
+
+
+%% @spec concrete(Node::cerl()) -> term()
+%%
+%% @doc Returns the Erlang term represented by a syntax tree. An
+%% exception is thrown if <code>Node</code> does not represent a
+%% literal term.
+%%
+%% <p>Note: This is a constant time operation.</p>
+%%
+%% @see abstract/1
+%% @see is_literal/1
+
+%% Because the normal tuple and list constructor operations always
+%% return a literal if the arguments are literals, 'concrete' and
+%% 'is_literal' never need to traverse the structure.
+
+concrete(#literal{val = V}) ->
+ V.
+
+
+%% @spec is_literal(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> represents a
+%% literal term, otherwise <code>false</code>. This function returns
+%% <code>true</code> if and only if the value of
+%% <code>concrete(Node)</code> is defined.
+%%
+%% <p>Note: This is a constant time operation.</p>
+%%
+%% @see abstract/1
+%% @see concrete/1
+%% @see fold_literal/1
+
+is_literal(#literal{}) ->
+ true;
+is_literal(_) ->
+ false.
+
+
+%% @spec fold_literal(Node::cerl()) -> cerl()
+%%
+%% @doc Assures that literals have a compact representation. This is
+%% occasionally useful if <code>c_cons_skel/2</code>,
+%% <code>c_tuple_skel/1</code> or <code>unfold_literal/1</code> were
+%% used in the construction of <code>Node</code>, and you want to revert
+%% to the normal "folded" representation of literals. If
+%% <code>Node</code> represents a tuple or list constructor, its
+%% elements are rewritten recursively, and the node is reconstructed
+%% using <code>c_cons/2</code> or <code>c_tuple/1</code>, respectively;
+%% otherwise, <code>Node</code> is not changed.
+%%
+%% @see is_literal/1
+%% @see c_cons_skel/2
+%% @see c_tuple_skel/1
+%% @see c_cons/2
+%% @see c_tuple/1
+%% @see unfold_literal/1
+
+fold_literal(Node) ->
+ case type(Node) of
+ tuple ->
+ update_c_tuple(Node, fold_literal_list(tuple_es(Node)));
+ cons ->
+ update_c_cons(Node, fold_literal(cons_hd(Node)),
+ fold_literal(cons_tl(Node)));
+ _ ->
+ Node
+ end.
+
+fold_literal_list([E | Es]) ->
+ [fold_literal(E) | fold_literal_list(Es)];
+fold_literal_list([]) ->
+ [].
+
+
+%% @spec unfold_literal(Node::cerl()) -> cerl()
+%%
+%% @doc Assures that literals have a fully expanded representation. If
+%% <code>Node</code> represents a literal tuple or list constructor, its
+%% elements are rewritten recursively, and the node is reconstructed
+%% using <code>c_cons_skel/2</code> or <code>c_tuple_skel/1</code>,
+%% respectively; otherwise, <code>Node</code> is not changed. The {@link
+%% fold_literal/1} can be used to revert to the normal compact
+%% representation.
+%%
+%% @see is_literal/1
+%% @see c_cons_skel/2
+%% @see c_tuple_skel/1
+%% @see c_cons/2
+%% @see c_tuple/1
+%% @see fold_literal/1
+
+unfold_literal(Node) ->
+ case type(Node) of
+ literal ->
+ copy_ann(Node, unfold_concrete(concrete(Node)));
+ _ ->
+ Node
+ end.
+
+unfold_concrete(Val) ->
+ case Val of
+ _ when tuple(Val) ->
+ c_tuple_skel(unfold_concrete_list(tuple_to_list(Val)));
+ [H|T] ->
+ c_cons_skel(unfold_concrete(H), unfold_concrete(T));
+ _ ->
+ abstract(Val)
+ end.
+
+unfold_concrete_list([E | Es]) ->
+ [unfold_concrete(E) | unfold_concrete_list(Es)];
+unfold_concrete_list([]) ->
+ [].
+
+
+%% ---------------------------------------------------------------------
+
+-record(module, {ann = [], name, exports, attrs, defs}).
+
+
+%% @spec c_module(Name::cerl(), Exports, Definitions) -> cerl()
+%%
+%% Exports = [cerl()]
+%% Definitions = [{cerl(), cerl()}]
+%%
+%% @equiv c_module(Name, Exports, [], Definitions)
+
+c_module(Name, Exports, Es) ->
+ #module{name = Name, exports = Exports, attrs = [], defs = Es}.
+
+
+%% @spec c_module(Name::cerl(), Exports, Attributes, Definitions) ->
+%% cerl()
+%%
+%% Exports = [cerl()]
+%% Attributes = [{cerl(), cerl()}]
+%% Definitions = [{cerl(), cerl()}]
+%%
+%% @doc Creates an abstract module definition. The result represents
+%% <pre>
+%% module <em>Name</em> [<em>E1</em>, ..., <em>Ek</em>]
+%% attributes [<em>K1</em> = <em>T1</em>, ...,
+%% <em>Km</em> = <em>Tm</em>]
+%% <em>V1</em> = <em>F1</em>
+%% ...
+%% <em>Vn</em> = <em>Fn</em>
+%% end</pre>
+%%
+%% if <code>Exports</code> = <code>[E1, ..., Ek]</code>,
+%% <code>Attributes</code> = <code>[{K1, T1}, ..., {Km, Tm}]</code>,
+%% and <code>Definitions</code> = <code>[{V1, F1}, ..., {Vn,
+%% Fn}]</code>.
+%%
+%% <p><code>Name</code> and all the <code>Ki</code> must be atom
+%% literals, and all the <code>Ti</code> must be constant literals. All
+%% the <code>Vi</code> and <code>Ei</code> must have type
+%% <code>var</code> and represent function names. All the
+%% <code>Fi</code> must have type <code>'fun'</code>.</p>
+%%
+%% @see c_module/3
+%% @see module_name/1
+%% @see module_exports/1
+%% @see module_attrs/1
+%% @see module_defs/1
+%% @see module_vars/1
+%% @see ann_c_module/4
+%% @see ann_c_module/5
+%% @see update_c_module/5
+%% @see c_atom/1
+%% @see c_var/1
+%% @see c_fun/2
+%% @see is_literal/1
+
+c_module(Name, Exports, Attrs, Es) ->
+ #module{name = Name, exports = Exports, attrs = Attrs, defs = Es}.
+
+
+%% @spec ann_c_module(As::[term()], Name::cerl(), Exports,
+%% Definitions) -> cerl()
+%%
+%% Exports = [cerl()]
+%% Definitions = [{cerl(), cerl()}]
+%%
+%% @see c_module/3
+%% @see ann_c_module/5
+
+ann_c_module(As, Name, Exports, Es) ->
+ #module{name = Name, exports = Exports, attrs = [], defs = Es,
+ ann = As}.
+
+
+%% @spec ann_c_module(As::[term()], Name::cerl(), Exports,
+%% Attributes, Definitions) -> cerl()
+%%
+%% Exports = [cerl()]
+%% Attributes = [{cerl(), cerl()}]
+%% Definitions = [{cerl(), cerl()}]
+%%
+%% @see c_module/4
+%% @see ann_c_module/4
+
+ann_c_module(As, Name, Exports, Attrs, Es) ->
+ #module{name = Name, exports = Exports, attrs = Attrs, defs = Es,
+ ann = As}.
+
+
+%% @spec update_c_module(Old::cerl(), Name::cerl(), Exports,
+%% Attributes, Definitions) -> cerl()
+%%
+%% Exports = [cerl()]
+%% Attributes = [{cerl(), cerl()}]
+%% Definitions = [{cerl(), cerl()}]
+%%
+%% @see c_module/4
+
+update_c_module(Node, Name, Exports, Attrs, Es) ->
+ #module{name = Name, exports = Exports, attrs = Attrs, defs = Es,
+ ann = get_ann(Node)}.
+
+
+%% @spec is_c_module(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% module definition, otherwise <code>false</code>.
+%%
+%% @see type/1
+
+is_c_module(#module{}) ->
+ true;
+is_c_module(_) ->
+ false.
+
+
+%% @spec module_name(Node::cerl()) -> cerl()
+%%
+%% @doc Returns the name subtree of an abstract module definition.
+%%
+%% @see c_module/4
+
+module_name(Node) ->
+ Node#module.name.
+
+
+%% @spec module_exports(Node::cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of exports subtrees of an abstract module
+%% definition.
+%%
+%% @see c_module/4
+
+module_exports(Node) ->
+ Node#module.exports.
+
+
+%% @spec module_attrs(Node::cerl()) -> [{cerl(), cerl()}]
+%%
+%% @doc Returns the list of pairs of attribute key/value subtrees of
+%% an abstract module definition.
+%%
+%% @see c_module/4
+
+module_attrs(Node) ->
+ Node#module.attrs.
+
+
+%% @spec module_defs(Node::cerl()) -> [{cerl(), cerl()}]
+%%
+%% @doc Returns the list of function definitions of an abstract module
+%% definition.
+%%
+%% @see c_module/4
+
+module_defs(Node) ->
+ Node#module.defs.
+
+
+%% @spec module_vars(Node::cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of left-hand side function variable subtrees
+%% of an abstract module definition.
+%%
+%% @see c_module/4
+
+module_vars(Node) ->
+ [F || {F, _} <- module_defs(Node)].
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_int(Value::integer()) -> cerl()
+%%
+%%
+%% @doc Creates an abstract integer literal. The lexical
+%% representation is the canonical decimal numeral of
+%% <code>Value</code>.
+%%
+%% @see ann_c_int/2
+%% @see is_c_int/1
+%% @see int_val/1
+%% @see int_lit/1
+%% @see c_char/1
+
+c_int(Value) ->
+ #literal{val = Value}.
+
+
+%% @spec ann_c_int(As::[term()], Value::integer()) -> cerl()
+%% @see c_int/1
+
+ann_c_int(As, Value) ->
+ #literal{val = Value, ann = As}.
+
+
+%% @spec is_c_int(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> represents an
+%% integer literal, otherwise <code>false</code>.
+%% @see c_int/1
+
+is_c_int(#literal{val = V}) when integer(V) ->
+ true;
+is_c_int(_) ->
+ false.
+
+
+%% @spec int_val(cerl()) -> integer()
+%%
+%% @doc Returns the value represented by an integer literal node.
+%% @see c_int/1
+
+int_val(Node) ->
+ Node#literal.val.
+
+
+%% @spec int_lit(cerl()) -> string()
+%%
+%% @doc Returns the numeral string represented by an integer literal
+%% node.
+%% @see c_int/1
+
+int_lit(Node) ->
+ integer_to_list(int_val(Node)).
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_float(Value::float()) -> cerl()
+%%
+%% @doc Creates an abstract floating-point literal. The lexical
+%% representation is the decimal floating-point numeral of
+%% <code>Value</code>.
+%%
+%% @see ann_c_float/2
+%% @see is_c_float/1
+%% @see float_val/1
+%% @see float_lit/1
+
+%% Note that not all floating-point numerals can be represented with
+%% full precision.
+
+c_float(Value) ->
+ #literal{val = Value}.
+
+
+%% @spec ann_c_float(As::[term()], Value::float()) -> cerl()
+%% @see c_float/1
+
+ann_c_float(As, Value) ->
+ #literal{val = Value, ann = As}.
+
+
+%% @spec is_c_float(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> represents a
+%% floating-point literal, otherwise <code>false</code>.
+%% @see c_float/1
+
+is_c_float(#literal{val = V}) when float(V) ->
+ true;
+is_c_float(_) ->
+ false.
+
+
+%% @spec float_val(cerl()) -> float()
+%%
+%% @doc Returns the value represented by a floating-point literal
+%% node.
+%% @see c_float/1
+
+float_val(Node) ->
+ Node#literal.val.
+
+
+%% @spec float_lit(cerl()) -> string()
+%%
+%% @doc Returns the numeral string represented by a floating-point
+%% literal node.
+%% @see c_float/1
+
+float_lit(Node) ->
+ float_to_list(float_val(Node)).
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_atom(Name) -> cerl()
+%% Name = atom() | string()
+%%
+%% @doc Creates an abstract atom literal. The print name of the atom
+%% is the character sequence represented by <code>Name</code>.
+%%
+%% <p>Note: passing a string as argument to this function causes a
+%% corresponding atom to be created for the internal representation.</p>
+%%
+%% @see ann_c_atom/2
+%% @see is_c_atom/1
+%% @see atom_val/1
+%% @see atom_name/1
+%% @see atom_lit/1
+
+c_atom(Name) when atom(Name) ->
+ #literal{val = Name};
+c_atom(Name) ->
+ #literal{val = list_to_atom(Name)}.
+
+
+%% @spec ann_c_atom(As::[term()], Name) -> cerl()
+%% Name = atom() | string()
+%% @see c_atom/1
+
+ann_c_atom(As, Name) when atom(Name) ->
+ #literal{val = Name, ann = As};
+ann_c_atom(As, Name) ->
+ #literal{val = list_to_atom(Name), ann = As}.
+
+
+%% @spec is_c_atom(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> represents an
+%% atom literal, otherwise <code>false</code>.
+%%
+%% @see c_atom/1
+
+is_c_atom(#literal{val = V}) when atom(V) ->
+ true;
+is_c_atom(_) ->
+ false.
+
+%% @spec atom_val(cerl())-> atom()
+%%
+%% @doc Returns the value represented by an abstract atom.
+%%
+%% @see c_atom/1
+
+atom_val(Node) ->
+ Node#literal.val.
+
+
+%% @spec atom_name(cerl()) -> string()
+%%
+%% @doc Returns the printname of an abstract atom.
+%%
+%% @see c_atom/1
+
+atom_name(Node) ->
+ atom_to_list(atom_val(Node)).
+
+
+%% @spec atom_lit(cerl()) -> string()
+%%
+%% @doc Returns the literal string represented by an abstract
+%% atom. This always includes surrounding single-quote characters.
+%%
+%% <p>Note that an abstract atom may have several literal
+%% representations, and that the representation yielded by this
+%% function is not fixed; e.g.,
+%% <code>atom_lit(c_atom("a\012b"))</code> could yield the string
+%% <code>"\'a\\nb\'"</code>.</p>
+%%
+%% @see c_atom/1
+
+%% TODO: replace the use of the unofficial 'write_string/2'.
+
+atom_lit(Node) ->
+ io_lib:write_string(atom_name(Node), $'). %' stupid Emacs.
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_char(Value) -> cerl()
+%%
+%% Value = char() | integer()
+%%
+%% @doc Creates an abstract character literal. If the local
+%% implementation of Erlang defines <code>char()</code> as a subset of
+%% <code>integer()</code>, this function is equivalent to
+%% <code>c_int/1</code>. Otherwise, if the given value is an integer,
+%% it will be converted to the character with the corresponding
+%% code. The lexical representation of a character is
+%% "<code>$<em>Char</em></code>", where <code>Char</code> is a single
+%% printing character or an escape sequence.
+%%
+%% @see c_int/1
+%% @see c_string/1
+%% @see ann_c_char/2
+%% @see is_c_char/1
+%% @see char_val/1
+%% @see char_lit/1
+%% @see is_print_char/1
+
+c_char(Value) when integer(Value), Value >= 0 ->
+ #literal{val = Value}.
+
+
+%% @spec ann_c_char(As::[term()], Value::char()) -> cerl()
+%% @see c_char/1
+
+ann_c_char(As, Value) ->
+ #literal{val = Value, ann = As}.
+
+
+%% @spec is_c_char(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> may represent a
+%% character literal, otherwise <code>false</code>.
+%%
+%% <p>If the local implementation of Erlang defines
+%% <code>char()</code> as a subset of <code>integer()</code>, then
+%% <code>is_c_int(<em>Node</em>)</code> will also yield
+%% <code>true</code>.</p>
+%%
+%% @see c_char/1
+%% @see is_print_char/1
+
+is_c_char(#literal{val = V}) when integer(V), V >= 0 ->
+ is_char_value(V);
+is_c_char(_) ->
+ false.
+
+
+%% @spec is_print_char(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> may represent a
+%% "printing" character, otherwise <code>false</code>. (Cf.
+%% <code>is_c_char/1</code>.) A "printing" character has either a
+%% given graphical representation, or a "named" escape sequence such
+%% as "<code>\n</code>". Currently, only ISO 8859-1 (Latin-1)
+%% character values are recognized.
+%%
+%% @see c_char/1
+%% @see is_c_char/1
+
+is_print_char(#literal{val = V}) when integer(V), V >= 0 ->
+ is_print_char_value(V);
+is_print_char(_) ->
+ false.
+
+
+%% @spec char_val(cerl()) -> char()
+%%
+%% @doc Returns the value represented by an abstract character literal.
+%%
+%% @see c_char/1
+
+char_val(Node) ->
+ Node#literal.val.
+
+
+%% @spec char_lit(cerl()) -> string()
+%%
+%% @doc Returns the literal string represented by an abstract
+%% character. This includes a leading <code>$</code>
+%% character. Currently, all characters that are not in the set of ISO
+%% 8859-1 (Latin-1) "printing" characters will be escaped.
+%%
+%% @see c_char/1
+
+char_lit(Node) ->
+ io_lib:write_char(char_val(Node)).
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_string(Value::string()) -> cerl()
+%%
+%% @doc Creates an abstract string literal. Equivalent to creating an
+%% abstract list of the corresponding character literals
+%% (cf. <code>is_c_string/1</code>), but is typically more
+%% efficient. The lexical representation of a string is
+%% "<code>"<em>Chars</em>"</code>", where <code>Chars</code> is a
+%% sequence of printing characters or spaces.
+%%
+%% @see c_char/1
+%% @see ann_c_string/2
+%% @see is_c_string/1
+%% @see string_val/1
+%% @see string_lit/1
+%% @see is_print_string/1
+
+c_string(Value) ->
+ #literal{val = Value}.
+
+
+%% @spec ann_c_string(As::[term()], Value::string()) -> cerl()
+%% @see c_string/1
+
+ann_c_string(As, Value) ->
+ #literal{val = Value, ann = As}.
+
+
+%% @spec is_c_string(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> may represent a
+%% string literal, otherwise <code>false</code>. Strings are defined
+%% as lists of characters; see <code>is_c_char/1</code> for details.
+%%
+%% @see c_string/1
+%% @see is_c_char/1
+%% @see is_print_string/1
+
+is_c_string(#literal{val = V}) ->
+ is_char_list(V);
+is_c_string(_) ->
+ false.
+
+
+%% @spec is_print_string(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> may represent a
+%% string literal containing only "printing" characters, otherwise
+%% <code>false</code>. See <code>is_c_string/1</code> and
+%% <code>is_print_char/1</code> for details. Currently, only ISO
+%% 8859-1 (Latin-1) character values are recognized.
+%%
+%% @see c_string/1
+%% @see is_c_string/1
+%% @see is_print_char/1
+
+is_print_string(#literal{val = V}) ->
+ is_print_char_list(V);
+is_print_string(_) ->
+ false.
+
+
+%% @spec string_val(cerl()) -> string()
+%%
+%% @doc Returns the value represented by an abstract string literal.
+%%
+%% @see c_string/1
+
+string_val(Node) ->
+ Node#literal.val.
+
+
+%% @spec string_lit(cerl()) -> string()
+%%
+%% @doc Returns the literal string represented by an abstract string.
+%% This includes surrounding double-quote characters
+%% <code>"..."</code>. Currently, characters that are not in the set
+%% of ISO 8859-1 (Latin-1) "printing" characters will be escaped,
+%% except for spaces.
+%%
+%% @see c_string/1
+
+string_lit(Node) ->
+ io_lib:write_string(string_val(Node)).
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_nil() -> cerl()
+%%
+%% @doc Creates an abstract empty list. The result represents
+%% "<code>[]</code>". The empty list is traditionally called "nil".
+%%
+%% @see ann_c_nil/1
+%% @see is_c_list/1
+%% @see c_cons/2
+
+c_nil() ->
+ #literal{val = []}.
+
+
+%% @spec ann_c_nil(As::[term()]) -> cerl()
+%% @see c_nil/0
+
+ann_c_nil(As) ->
+ #literal{val = [], ann = As}.
+
+
+%% @spec is_c_nil(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% empty list, otherwise <code>false</code>.
+
+is_c_nil(#literal{val = []}) ->
+ true;
+is_c_nil(_) ->
+ false.
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_cons(Head::cerl(), Tail::cerl()) -> cerl()
+%%
+%% @doc Creates an abstract list constructor. The result represents
+%% "<code>[<em>Head</em> | <em>Tail</em>]</code>". Note that if both
+%% <code>Head</code> and <code>Tail</code> have type
+%% <code>literal</code>, then the result will also have type
+%% <code>literal</code>, and annotations on <code>Head</code> and
+%% <code>Tail</code> are lost.
+%%
+%% <p>Recall that in Erlang, the tail element of a list constructor is
+%% not necessarily a list.</p>
+%%
+%% @see ann_c_cons/3
+%% @see update_c_cons/3
+%% @see c_cons_skel/2
+%% @see is_c_cons/1
+%% @see cons_hd/1
+%% @see cons_tl/1
+%% @see is_c_list/1
+%% @see c_nil/0
+%% @see list_elements/1
+%% @see list_length/1
+%% @see make_list/2
+
+-record(cons, {ann = [], hd, tl}).
+
+%% *Always* collapse literals.
+
+c_cons(#literal{val = Head}, #literal{val = Tail}) ->
+ #literal{val = [Head | Tail]};
+c_cons(Head, Tail) ->
+ #cons{hd = Head, tl = Tail}.
+
+
+%% @spec ann_c_cons(As::[term()], Head::cerl(), Tail::cerl()) -> cerl()
+%% @see c_cons/2
+
+ann_c_cons(As, #literal{val = Head}, #literal{val = Tail}) ->
+ #literal{val = [Head | Tail], ann = As};
+ann_c_cons(As, Head, Tail) ->
+ #cons{hd = Head, tl = Tail, ann = As}.
+
+
+%% @spec update_c_cons(Old::cerl(), Head::cerl(), Tail::cerl()) ->
+%% cerl()
+%% @see c_cons/2
+
+update_c_cons(Node, #literal{val = Head}, #literal{val = Tail}) ->
+ #literal{val = [Head | Tail], ann = get_ann(Node)};
+update_c_cons(Node, Head, Tail) ->
+ #cons{hd = Head, tl = Tail, ann = get_ann(Node)}.
+
+
+%% @spec c_cons_skel(Head::cerl(), Tail::cerl()) -> cerl()
+%%
+%% @doc Creates an abstract list constructor skeleton. Does not fold
+%% constant literals, i.e., the result always has type
+%% <code>cons</code>, representing "<code>[<em>Head</em> |
+%% <em>Tail</em>]</code>".
+%%
+%% <p>This function is occasionally useful when it is necessary to have
+%% annotations on the subnodes of a list constructor node, even when the
+%% subnodes are constant literals. Note however that
+%% <code>is_literal/1</code> will yield <code>false</code> and
+%% <code>concrete/1</code> will fail if passed the result from this
+%% function.</p>
+%%
+%% <p><code>fold_literal/1</code> can be used to revert a node to the
+%% normal-form representation.</p>
+%%
+%% @see ann_c_cons_skel/3
+%% @see update_c_cons_skel/3
+%% @see c_cons/2
+%% @see is_c_cons/1
+%% @see is_c_list/1
+%% @see c_nil/0
+%% @see is_literal/1
+%% @see fold_literal/1
+%% @see concrete/1
+
+%% *Never* collapse literals.
+
+c_cons_skel(Head, Tail) ->
+ #cons{hd = Head, tl = Tail}.
+
+
+%% @spec ann_c_cons_skel(As::[term()], Head::cerl(), Tail::cerl()) ->
+%% cerl()
+%% @see c_cons_skel/2
+
+ann_c_cons_skel(As, Head, Tail) ->
+ #cons{hd = Head, tl = Tail, ann = As}.
+
+
+%% @spec update_c_cons_skel(Old::cerl(), Head::cerl(), Tail::cerl()) ->
+%% cerl()
+%% @see c_cons_skel/2
+
+update_c_cons_skel(Node, Head, Tail) ->
+ #cons{hd = Head, tl = Tail, ann = get_ann(Node)}.
+
+
+%% @spec is_c_cons(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% list constructor, otherwise <code>false</code>.
+
+is_c_cons(#cons{}) ->
+ true;
+is_c_cons(#literal{val = [_ | _]}) ->
+ true;
+is_c_cons(_) ->
+ false.
+
+
+%% @spec cons_hd(cerl()) -> cerl()
+%%
+%% @doc Returns the head subtree of an abstract list constructor.
+%%
+%% @see c_cons/2
+
+cons_hd(#cons{hd = Head}) ->
+ Head;
+cons_hd(#literal{val = [Head | _]}) ->
+ #literal{val = Head}.
+
+
+%% @spec cons_tl(cerl()) -> cerl()
+%%
+%% @doc Returns the tail subtree of an abstract list constructor.
+%%
+%% <p>Recall that the tail does not necessarily represent a proper
+%% list.</p>
+%%
+%% @see c_cons/2
+
+cons_tl(#cons{tl = Tail}) ->
+ Tail;
+cons_tl(#literal{val = [_ | Tail]}) ->
+ #literal{val = Tail}.
+
+
+%% @spec is_c_list(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> represents a
+%% proper list, otherwise <code>false</code>. A proper list is either
+%% the empty list <code>[]</code>, or a cons cell <code>[<em>Head</em> |
+%% <em>Tail</em>]</code>, where recursively <code>Tail</code> is a
+%% proper list.
+%%
+%% <p>Note: Because <code>Node</code> is a syntax tree, the actual
+%% run-time values corresponding to its subtrees may often be partially
+%% or completely unknown. Thus, if <code>Node</code> represents e.g.
+%% "<code>[... | Ns]</code>" (where <code>Ns</code> is a variable), then
+%% the function will return <code>false</code>, because it is not known
+%% whether <code>Ns</code> will be bound to a list at run-time. If
+%% <code>Node</code> instead represents e.g. "<code>[1, 2, 3]</code>" or
+%% "<code>[A | []]</code>", then the function will return
+%% <code>true</code>.</p>
+%%
+%% @see c_cons/2
+%% @see c_nil/0
+%% @see list_elements/1
+%% @see list_length/1
+
+is_c_list(#cons{tl = Tail}) ->
+ is_c_list(Tail);
+is_c_list(#literal{val = V}) ->
+ is_proper_list(V);
+is_c_list(_) ->
+ false.
+
+is_proper_list([_ | Tail]) ->
+ is_proper_list(Tail);
+is_proper_list([]) ->
+ true;
+is_proper_list(_) ->
+ false.
+
+%% @spec list_elements(cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of element subtrees of an abstract list.
+%% <code>Node</code> must represent a proper list. E.g., if
+%% <code>Node</code> represents "<code>[<em>X1</em>, <em>X2</em> |
+%% [<em>X3</em>, <em>X4</em> | []]</code>", then
+%% <code>list_elements(Node)</code> yields the list <code>[X1, X2, X3,
+%% X4]</code>.
+%%
+%% @see c_cons/2
+%% @see c_nil/1
+%% @see is_c_list/1
+%% @see list_length/1
+%% @see make_list/2
+
+list_elements(#cons{hd = Head, tl = Tail}) ->
+ [Head | list_elements(Tail)];
+list_elements(#literal{val = V}) ->
+ abstract_list(V).
+
+abstract_list([X | Xs]) ->
+ [abstract(X) | abstract_list(Xs)];
+abstract_list([]) ->
+ [].
+
+
+%% @spec list_length(Node::cerl()) -> integer()
+%%
+%% @doc Returns the number of element subtrees of an abstract list.
+%% <code>Node</code> must represent a proper list. E.g., if
+%% <code>Node</code> represents "<code>[X1 | [X2, X3 | [X4, X5,
+%% X6]]]</code>", then <code>list_length(Node)</code> returns the
+%% integer 6.
+%%
+%% <p>Note: this is equivalent to
+%% <code>length(list_elements(Node))</code>, but potentially more
+%% efficient.</p>
+%%
+%% @see c_cons/2
+%% @see c_nil/1
+%% @see is_c_list/1
+%% @see list_elements/1
+
+list_length(L) ->
+ list_length(L, 0).
+
+list_length(#cons{tl = Tail}, A) ->
+ list_length(Tail, A + 1);
+list_length(#literal{val = V}, A) ->
+ A + length(V).
+
+
+%% @spec make_list(List) -> Node
+%% @equiv make_list(List, none)
+
+make_list(List) ->
+ ann_make_list([], List).
+
+
+%% @spec make_list(List::[cerl()], Tail) -> cerl()
+%%
+%% Tail = cerl() | none
+%%
+%% @doc Creates an abstract list from the elements in <code>List</code>
+%% and the optional <code>Tail</code>. If <code>Tail</code> is
+%% <code>none</code>, the result will represent a nil-terminated list,
+%% otherwise it represents "<code>[... | <em>Tail</em>]</code>".
+%%
+%% @see c_cons/2
+%% @see c_nil/0
+%% @see ann_make_list/3
+%% @see update_list/3
+%% @see list_elements/1
+
+make_list(List, Tail) ->
+ ann_make_list([], List, Tail).
+
+
+%% @spec update_list(Old::cerl(), List::[cerl()]) -> cerl()
+%% @equiv update_list(Old, List, none)
+
+update_list(Node, List) ->
+ ann_make_list(get_ann(Node), List).
+
+
+%% @spec update_list(Old::cerl(), List::[cerl()], Tail) -> cerl()
+%%
+%% Tail = cerl() | none
+%%
+%% @see make_list/2
+%% @see update_list/2
+
+update_list(Node, List, Tail) ->
+ ann_make_list(get_ann(Node), List, Tail).
+
+
+%% @spec ann_make_list(As::[term()], List::[cerl()]) -> cerl()
+%% @equiv ann_make_list(As, List, none)
+
+ann_make_list(As, List) ->
+ ann_make_list(As, List, none).
+
+
+%% @spec ann_make_list(As::[term()], List::[cerl()], Tail) -> cerl()
+%%
+%% Tail = cerl() | none
+%%
+%% @see make_list/2
+%% @see ann_make_list/2
+
+ann_make_list(As, [H | T], Tail) ->
+ ann_c_cons(As, H, make_list(T, Tail)); % `c_cons' folds literals
+ann_make_list(As, [], none) ->
+ ann_c_nil(As);
+ann_make_list(_, [], Node) ->
+ Node.
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_tuple(Elements::[cerl()]) -> cerl()
+%%
+%% @doc Creates an abstract tuple. If <code>Elements</code> is
+%% <code>[E1, ..., En]</code>, the result represents
+%% "<code>{<em>E1</em>, ..., <em>En</em>}</code>". Note that if all
+%% nodes in <code>Elements</code> have type <code>literal</code>, or if
+%% <code>Elements</code> is empty, then the result will also have type
+%% <code>literal</code> and annotations on nodes in
+%% <code>Elements</code> are lost.
+%%
+%% <p>Recall that Erlang has distinct 1-tuples, i.e., <code>{X}</code>
+%% is always distinct from <code>X</code> itself.</p>
+%%
+%% @see ann_c_tuple/2
+%% @see update_c_tuple/2
+%% @see is_c_tuple/1
+%% @see tuple_es/1
+%% @see tuple_arity/1
+%% @see c_tuple_skel/1
+
+-record(tuple, {ann = [], es}).
+
+%% *Always* collapse literals.
+
+c_tuple(Es) ->
+ case is_lit_list(Es) of
+ false ->
+ #tuple{es = Es};
+ true ->
+ #literal{val = list_to_tuple(lit_list_vals(Es))}
+ end.
+
+
+%% @spec ann_c_tuple(As::[term()], Elements::[cerl()]) -> cerl()
+%% @see c_tuple/1
+
+ann_c_tuple(As, Es) ->
+ case is_lit_list(Es) of
+ false ->
+ #tuple{es = Es, ann = As};
+ true ->
+ #literal{val = list_to_tuple(lit_list_vals(Es)), ann = As}
+ end.
+
+
+%% @spec update_c_tuple(Old::cerl(), Elements::[cerl()]) -> cerl()
+%% @see c_tuple/1
+
+update_c_tuple(Node, Es) ->
+ case is_lit_list(Es) of
+ false ->
+ #tuple{es = Es, ann = get_ann(Node)};
+ true ->
+ #literal{val = list_to_tuple(lit_list_vals(Es)),
+ ann = get_ann(Node)}
+ end.
+
+
+%% @spec c_tuple_skel(Elements::[cerl()]) -> cerl()
+%%
+%% @doc Creates an abstract tuple skeleton. Does not fold constant
+%% literals, i.e., the result always has type <code>tuple</code>,
+%% representing "<code>{<em>E1</em>, ..., <em>En</em>}</code>", if
+%% <code>Elements</code> is <code>[E1, ..., En]</code>.
+%%
+%% <p>This function is occasionally useful when it is necessary to have
+%% annotations on the subnodes of a tuple node, even when all the
+%% subnodes are constant literals. Note however that
+%% <code>is_literal/1</code> will yield <code>false</code> and
+%% <code>concrete/1</code> will fail if passed the result from this
+%% function.</p>
+%%
+%% <p><code>fold_literal/1</code> can be used to revert a node to the
+%% normal-form representation.</p>
+%%
+%% @see ann_c_tuple_skel/2
+%% @see update_c_tuple_skel/2
+%% @see c_tuple/1
+%% @see tuple_es/1
+%% @see is_c_tuple/1
+%% @see is_literal/1
+%% @see fold_literal/1
+%% @see concrete/1
+
+%% *Never* collapse literals.
+
+c_tuple_skel(Es) ->
+ #tuple{es = Es}.
+
+
+%% @spec ann_c_tuple_skel(As::[term()], Elements::[cerl()]) -> cerl()
+%% @see c_tuple_skel/1
+
+ann_c_tuple_skel(As, Es) ->
+ #tuple{es = Es, ann = As}.
+
+
+%% @spec update_c_tuple_skel(Old::cerl(), Elements::[cerl()]) -> cerl()
+%% @see c_tuple_skel/1
+
+update_c_tuple_skel(Old, Es) ->
+ #tuple{es = Es, ann = get_ann(Old)}.
+
+
+%% @spec is_c_tuple(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% tuple, otherwise <code>false</code>.
+%%
+%% @see c_tuple/1
+
+is_c_tuple(#tuple{}) ->
+ true;
+is_c_tuple(#literal{val = V}) when tuple(V) ->
+ true;
+is_c_tuple(_) ->
+ false.
+
+
+%% @spec tuple_es(cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of element subtrees of an abstract tuple.
+%%
+%% @see c_tuple/1
+
+tuple_es(#tuple{es = Es}) ->
+ Es;
+tuple_es(#literal{val = V}) ->
+ make_lit_list(tuple_to_list(V)).
+
+
+%% @spec tuple_arity(Node::cerl()) -> integer()
+%%
+%% @doc Returns the number of element subtrees of an abstract tuple.
+%%
+%% <p>Note: this is equivalent to <code>length(tuple_es(Node))</code>,
+%% but potentially more efficient.</p>
+%%
+%% @see tuple_es/1
+%% @see c_tuple/1
+
+tuple_arity(#tuple{es = Es}) ->
+ length(Es);
+tuple_arity(#literal{val = V}) when tuple(V) ->
+ size(V).
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_var(Name::var_name()) -> cerl()
+%%
+%% var_name() = integer() | atom() | {atom(), integer()}
+%%
+%% @doc Creates an abstract variable. A variable is identified by its
+%% name, given by the <code>Name</code> parameter.
+%%
+%% <p>If a name is given by a single atom, it should either be a
+%% "simple" atom which does not need to be single-quoted in Erlang, or
+%% otherwise its print name should correspond to a proper Erlang
+%% variable, i.e., begin with an uppercase character or an
+%% underscore. Names on the form <code>{A, N}</code> represent
+%% function name variables "<code><em>A</em>/<em>N</em></code>"; these
+%% are special variables which may be bound only in the function
+%% definitions of a module or a <code>letrec</code>. They may not be
+%% bound in <code>let</code> expressions and cannot occur in clause
+%% patterns. The atom <code>A</code> in a function name may be any
+%% atom; the integer <code>N</code> must be nonnegative. The functions
+%% <code>c_fname/2</code> etc. are utilities for handling function
+%% name variables.</p>
+%%
+%% <p>When printing variable names, they must have the form of proper
+%% Core Erlang variables and function names. E.g., a name represented
+%% by an integer such as <code>42</code> could be formatted as
+%% "<code>_42</code>", an atom <code>'Xxx'</code> simply as
+%% "<code>Xxx</code>", and an atom <code>foo</code> as
+%% "<code>_foo</code>". However, one must assure that any two valid
+%% distinct names are never mapped to the same strings. Tuples such
+%% as <code>{foo, 2}</code> representing function names can simply by
+%% formatted as "<code>'foo'/2</code>", with no risk of conflicts.</p>
+%%
+%% @see ann_c_var/2
+%% @see update_c_var/2
+%% @see is_c_var/1
+%% @see var_name/1
+%% @see c_fname/2
+%% @see c_module/4
+%% @see c_letrec/2
+
+-record(var, {ann = [], name}).
+
+c_var(Name) ->
+ #var{name = Name}.
+
+
+%% @spec ann_c_var(As::[term()], Name::var_name()) -> cerl()
+%%
+%% @see c_var/1
+
+ann_c_var(As, Name) ->
+ #var{name = Name, ann = As}.
+
+%% @spec update_c_var(Old::cerl(), Name::var_name()) -> cerl()
+%%
+%% @see c_var/1
+
+update_c_var(Node, Name) ->
+ #var{name = Name, ann = get_ann(Node)}.
+
+
+%% @spec is_c_var(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% variable, otherwise <code>false</code>.
+%%
+%% @see c_var/1
+
+is_c_var(#var{}) ->
+ true;
+is_c_var(_) ->
+ false.
+
+
+%% @spec c_fname(Name::atom(), Arity::integer()) -> cerl()
+%% @equiv c_var({Name, Arity})
+%% @see fname_id/1
+%% @see fname_arity/1
+%% @see is_c_fname/1
+%% @see ann_c_fname/3
+%% @see update_c_fname/3
+
+c_fname(Atom, Arity) ->
+ c_var({Atom, Arity}).
+
+
+%% @spec ann_c_fname(As::[term()], Name::atom(), Arity::integer()) ->
+%% cerl()
+%% @equiv ann_c_var(As, {Atom, Arity})
+%% @see c_fname/2
+
+ann_c_fname(As, Atom, Arity) ->
+ ann_c_var(As, {Atom, Arity}).
+
+
+%% @spec update_c_fname(Old::cerl(), Name::atom()) -> cerl()
+%% @doc Like <code>update_c_fname/3</code>, but takes the arity from
+%% <code>Node</code>.
+%% @see update_c_fname/3
+%% @see c_fname/2
+
+update_c_fname(#var{name = {_, Arity}, ann = As}, Atom) ->
+ #var{name = {Atom, Arity}, ann = As}.
+
+
+%% @spec update_c_fname(Old::cerl(), Name::atom(), Arity::integer()) ->
+%% cerl()
+%% @equiv update_c_var(Old, {Atom, Arity})
+%% @see update_c_fname/2
+%% @see c_fname/2
+
+update_c_fname(Node, Atom, Arity) ->
+ update_c_var(Node, {Atom, Arity}).
+
+
+%% @spec is_c_fname(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% function name variable, otherwise <code>false</code>.
+%%
+%% @see c_fname/2
+%% @see c_var/1
+%% @see c_var_name/1
+
+is_c_fname(#var{name = {A, N}}) when atom(A), integer(N), N >= 0 ->
+ true;
+is_c_fname(_) ->
+ false.
+
+
+%% @spec var_name(cerl()) -> var_name()
+%%
+%% @doc Returns the name of an abstract variable.
+%%
+%% @see c_var/1
+
+var_name(Node) ->
+ Node#var.name.
+
+
+%% @spec fname_id(cerl()) -> atom()
+%%
+%% @doc Returns the identifier part of an abstract function name
+%% variable.
+%%
+%% @see fname_arity/1
+%% @see c_fname/2
+
+fname_id(#var{name={A,_}}) ->
+ A.
+
+
+%% @spec fname_arity(cerl()) -> integer()
+%%
+%% @doc Returns the arity part of an abstract function name variable.
+%%
+%% @see fname_id/1
+%% @see c_fname/2
+
+fname_arity(#var{name={_,N}}) ->
+ N.
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_values(Elements::[cerl()]) -> cerl()
+%%
+%% @doc Creates an abstract value list. If <code>Elements</code> is
+%% <code>[E1, ..., En]</code>, the result represents
+%% "<code>&lt;<em>E1</em>, ..., <em>En</em>&gt;</code>".
+%%
+%% @see ann_c_values/2
+%% @see update_c_values/2
+%% @see is_c_values/1
+%% @see values_es/1
+%% @see values_arity/1
+
+-record(values, {ann = [], es}).
+
+c_values(Es) ->
+ #values{es = Es}.
+
+
+%% @spec ann_c_values(As::[term()], Elements::[cerl()]) -> cerl()
+%% @see c_values/1
+
+ann_c_values(As, Es) ->
+ #values{es = Es, ann = As}.
+
+
+%% @spec update_c_values(Old::cerl(), Elements::[cerl()]) -> cerl()
+%% @see c_values/1
+
+update_c_values(Node, Es) ->
+ #values{es = Es, ann = get_ann(Node)}.
+
+
+%% @spec is_c_values(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% value list; otherwise <code>false</code>.
+%%
+%% @see c_values/1
+
+is_c_values(#values{}) ->
+ true;
+is_c_values(_) ->
+ false.
+
+
+%% @spec values_es(cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of element subtrees of an abstract value
+%% list.
+%%
+%% @see c_values/1
+%% @see values_arity/1
+
+values_es(Node) ->
+ Node#values.es.
+
+
+%% @spec values_arity(Node::cerl()) -> integer()
+%%
+%% @doc Returns the number of element subtrees of an abstract value
+%% list.
+%%
+%% <p>Note: This is equivalent to
+%% <code>length(values_es(Node))</code>, but potentially more
+%% efficient.</p>
+%%
+%% @see c_values/1
+%% @see values_es/1
+
+values_arity(Node) ->
+ length(values_es(Node)).
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_binary(Segments::[cerl()]) -> cerl()
+%%
+%% @doc Creates an abstract binary-template. A binary object is a
+%% sequence of 8-bit bytes. It is specified by zero or more bit-string
+%% template <em>segments</em> of arbitrary lengths (in number of bits),
+%% such that the sum of the lengths is evenly divisible by 8. If
+%% <code>Segments</code> is <code>[S1, ..., Sn]</code>, the result
+%% represents "<code>#{<em>S1</em>, ..., <em>Sn</em>}#</code>". All the
+%% <code>Si</code> must have type <code>bitstr</code>.
+%%
+%% @see ann_c_binary/2
+%% @see update_c_binary/2
+%% @see is_c_binary/1
+%% @see binary_segments/1
+%% @see c_bitstr/5
+
+-record(binary, {ann = [], segments}).
+
+c_binary(Segments) ->
+ #binary{segments = Segments}.
+
+
+%% @spec ann_c_binary(As::[term()], Segments::[cerl()]) -> cerl()
+%% @see c_binary/1
+
+ann_c_binary(As, Segments) ->
+ #binary{segments = Segments, ann = As}.
+
+
+%% @spec update_c_binary(Old::cerl(), Segments::[cerl()]) -> cerl()
+%% @see c_binary/1
+
+update_c_binary(Node, Segments) ->
+ #binary{segments = Segments, ann = get_ann(Node)}.
+
+
+%% @spec is_c_binary(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% binary-template; otherwise <code>false</code>.
+%%
+%% @see c_binary/1
+
+is_c_binary(#binary{}) ->
+ true;
+is_c_binary(_) ->
+ false.
+
+
+%% @spec binary_segments(cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of segment subtrees of an abstract
+%% binary-template.
+%%
+%% @see c_binary/1
+%% @see c_bitstr/5
+
+binary_segments(Node) ->
+ Node#binary.segments.
+
+
+%% @spec c_bitstr(Value::cerl(), Size::cerl(), Unit::cerl(),
+%% Type::cerl(), Flags::cerl()) -> cerl()
+%%
+%% @doc Creates an abstract bit-string template. These can only occur as
+%% components of an abstract binary-template (see {@link c_binary/1}).
+%% The result represents "<code>#&lt;<em>Value</em>&gt;(<em>Size</em>,
+%% <em>Unit</em>, <em>Type</em>, <em>Flags</em>)</code>", where
+%% <code>Unit</code> must represent a positive integer constant,
+%% <code>Type</code> must represent a constant atom (one of
+%% <code>'integer'</code>, <code>'float'</code>, or
+%% <code>'binary'</code>), and <code>Flags</code> must represent a
+%% constant list <code>"[<em>F1</em>, ..., <em>Fn</em>]"</code> where
+%% all the <code>Fi</code> are atoms.
+%%
+%% @see c_binary/1
+%% @see ann_c_bitstr/6
+%% @see update_c_bitstr/6
+%% @see is_c_bitstr/1
+%% @see bitstr_val/1
+%% @see bitstr_size/1
+%% @see bitstr_unit/1
+%% @see bitstr_type/1
+%% @see bitstr_flags/1
+
+-record(bitstr, {ann = [], val, size, unit, type, flags}).
+
+c_bitstr(Val, Size, Unit, Type, Flags) ->
+ #bitstr{val = Val, size = Size, unit = Unit, type = Type,
+ flags = Flags}.
+
+
+%% @spec c_bitstr(Value::cerl(), Size::cerl(), Type::cerl(),
+%% Flags::cerl()) -> cerl()
+%% @equiv c_bitstr(Value, Size, abstract(1), Type, Flags)
+
+c_bitstr(Val, Size, Type, Flags) ->
+ c_bitstr(Val, Size, abstract(1), Type, Flags).
+
+
+%% @spec c_bitstr(Value::cerl(), Type::cerl(),
+%% Flags::cerl()) -> cerl()
+%% @equiv c_bitstr(Value, abstract(all), abstract(1), Type, Flags)
+
+c_bitstr(Val, Type, Flags) ->
+ c_bitstr(Val, abstract(all), abstract(1), Type, Flags).
+
+
+%% @spec ann_c_bitstr(As::[term()], Value::cerl(), Size::cerl(),
+%% Unit::cerl(), Type::cerl(), Flags::cerl()) -> cerl()
+%% @see c_bitstr/5
+%% @see ann_c_bitstr/5
+
+ann_c_bitstr(As, Val, Size, Unit, Type, Flags) ->
+ #bitstr{val = Val, size = Size, unit = Unit, type = Type,
+ flags = Flags, ann = As}.
+
+%% @spec ann_c_bitstr(As::[term()], Value::cerl(), Size::cerl(),
+%% Type::cerl(), Flags::cerl()) -> cerl()
+%% @equiv ann_c_bitstr(As, Value, Size, abstract(1), Type, Flags)
+
+ann_c_bitstr(As, Value, Size, Type, Flags) ->
+ ann_c_bitstr(As, Value, Size, abstract(1), Type, Flags).
+
+
+%% @spec update_c_bitstr(Old::cerl(), Value::cerl(), Size::cerl(),
+%% Unit::cerl(), Type::cerl(), Flags::cerl()) -> cerl()
+%% @see c_bitstr/5
+%% @see update_c_bitstr/5
+
+update_c_bitstr(Node, Val, Size, Unit, Type, Flags) ->
+ #bitstr{val = Val, size = Size, unit = Unit, type = Type,
+ flags = Flags, ann = get_ann(Node)}.
+
+
+%% @spec update_c_bitstr(Old::cerl(), Value::cerl(), Size::cerl(),
+%% Type::cerl(), Flags::cerl()) -> cerl()
+%% @equiv update_c_bitstr(Node, Value, Size, abstract(1), Type, Flags)
+
+update_c_bitstr(Node, Value, Size, Type, Flags) ->
+ update_c_bitstr(Node, Value, Size, abstract(1), Type, Flags).
+
+%% @spec is_c_bitstr(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% bit-string template; otherwise <code>false</code>.
+%%
+%% @see c_bitstr/5
+
+is_c_bitstr(#bitstr{}) ->
+ true;
+is_c_bitstr(_) ->
+ false.
+
+
+%% @spec bitstr_val(cerl()) -> cerl()
+%%
+%% @doc Returns the value subtree of an abstract bit-string template.
+%%
+%% @see c_bitstr/5
+
+bitstr_val(Node) ->
+ Node#bitstr.val.
+
+
+%% @spec bitstr_size(cerl()) -> cerl()
+%%
+%% @doc Returns the size subtree of an abstract bit-string template.
+%%
+%% @see c_bitstr/5
+
+bitstr_size(Node) ->
+ Node#bitstr.size.
+
+
+%% @spec bitstr_bitsize(cerl()) -> integer() | any | all
+%%
+%% @doc Returns the total size in bits of an abstract bit-string
+%% template. If the size field is an integer literal, the result is the
+%% product of the size and unit values; if the size field is the atom
+%% literal <code>all</code>, the atom <code>all</code> is returned; in
+%% all other cases, the atom <code>any</code> is returned.
+%%
+%% @see c_bitstr/5
+
+bitstr_bitsize(Node) ->
+ Size = Node#bitstr.size,
+ case is_literal(Size) of
+ true ->
+ case concrete(Size) of
+ all ->
+ all;
+ S when integer(S) ->
+ S*concrete(Node#bitstr.unit);
+ true ->
+ any
+ end;
+ false ->
+ any
+ end.
+
+
+%% @spec bitstr_unit(cerl()) -> cerl()
+%%
+%% @doc Returns the unit subtree of an abstract bit-string template.
+%%
+%% @see c_bitstr/5
+
+bitstr_unit(Node) ->
+ Node#bitstr.unit.
+
+
+%% @spec bitstr_type(cerl()) -> cerl()
+%%
+%% @doc Returns the type subtree of an abstract bit-string template.
+%%
+%% @see c_bitstr/5
+
+bitstr_type(Node) ->
+ Node#bitstr.type.
+
+
+%% @spec bitstr_flags(cerl()) -> cerl()
+%%
+%% @doc Returns the flags subtree of an abstract bit-string template.
+%%
+%% @see c_bitstr/5
+
+bitstr_flags(Node) ->
+ Node#bitstr.flags.
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_fun(Variables::[cerl()], Body::cerl()) -> cerl()
+%%
+%% @doc Creates an abstract fun-expression. If <code>Variables</code>
+%% is <code>[V1, ..., Vn]</code>, the result represents "<code>fun
+%% (<em>V1</em>, ..., <em>Vn</em>) -> <em>Body</em></code>". All the
+%% <code>Vi</code> must have type <code>var</code>.
+%%
+%% @see ann_c_fun/3
+%% @see update_c_fun/3
+%% @see is_c_fun/1
+%% @see fun_vars/1
+%% @see fun_body/1
+%% @see fun_arity/1
+
+-record('fun', {ann = [], vars, body}).
+
+c_fun(Variables, Body) ->
+ #'fun'{vars = Variables, body = Body}.
+
+
+%% @spec ann_c_fun(As::[term()], Variables::[cerl()], Body::cerl()) ->
+%% cerl()
+%% @see c_fun/2
+
+ann_c_fun(As, Variables, Body) ->
+ #'fun'{vars = Variables, body = Body, ann = As}.
+
+
+%% @spec update_c_fun(Old::cerl(), Variables::[cerl()],
+%% Body::cerl()) -> cerl()
+%% @see c_fun/2
+
+update_c_fun(Node, Variables, Body) ->
+ #'fun'{vars = Variables, body = Body, ann = get_ann(Node)}.
+
+
+%% @spec is_c_fun(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% fun-expression, otherwise <code>false</code>.
+%%
+%% @see c_fun/2
+
+is_c_fun(#'fun'{}) ->
+ true; % Now this is fun!
+is_c_fun(_) ->
+ false.
+
+
+%% @spec fun_vars(cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of parameter subtrees of an abstract
+%% fun-expression.
+%%
+%% @see c_fun/2
+%% @see fun_arity/1
+
+fun_vars(Node) ->
+ Node#'fun'.vars.
+
+
+%% @spec fun_body(cerl()) -> cerl()
+%%
+%% @doc Returns the body subtree of an abstract fun-expression.
+%%
+%% @see c_fun/2
+
+fun_body(Node) ->
+ Node#'fun'.body.
+
+
+%% @spec fun_arity(Node::cerl()) -> integer()
+%%
+%% @doc Returns the number of parameter subtrees of an abstract
+%% fun-expression.
+%%
+%% <p>Note: this is equivalent to <code>length(fun_vars(Node))</code>,
+%% but potentially more efficient.</p>
+%%
+%% @see c_fun/2
+%% @see fun_vars/1
+
+fun_arity(Node) ->
+ length(fun_vars(Node)).
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_seq(Argument::cerl(), Body::cerl()) -> cerl()
+%%
+%% @doc Creates an abstract sequencing expression. The result
+%% represents "<code>do <em>Argument</em> <em>Body</em></code>".
+%%
+%% @see ann_c_seq/3
+%% @see update_c_seq/3
+%% @see is_c_seq/1
+%% @see seq_arg/1
+%% @see seq_body/1
+
+-record(seq, {ann = [], arg, body}).
+
+c_seq(Argument, Body) ->
+ #seq{arg = Argument, body = Body}.
+
+
+%% @spec ann_c_seq(As::[term()], Argument::cerl(), Body::cerl()) ->
+%% cerl()
+%% @see c_seq/2
+
+ann_c_seq(As, Argument, Body) ->
+ #seq{arg = Argument, body = Body, ann = As}.
+
+
+%% @spec update_c_seq(Old::cerl(), Argument::cerl(), Body::cerl()) ->
+%% cerl()
+%% @see c_seq/2
+
+update_c_seq(Node, Argument, Body) ->
+ #seq{arg = Argument, body = Body, ann = get_ann(Node)}.
+
+
+%% @spec is_c_seq(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% sequencing expression, otherwise <code>false</code>.
+%%
+%% @see c_seq/2
+
+is_c_seq(#seq{}) ->
+ true;
+is_c_seq(_) ->
+ false.
+
+
+%% @spec seq_arg(cerl()) -> cerl()
+%%
+%% @doc Returns the argument subtree of an abstract sequencing
+%% expression.
+%%
+%% @see c_seq/2
+
+seq_arg(Node) ->
+ Node#seq.arg.
+
+
+%% @spec seq_body(cerl()) -> cerl()
+%%
+%% @doc Returns the body subtree of an abstract sequencing expression.
+%%
+%% @see c_seq/2
+
+seq_body(Node) ->
+ Node#seq.body.
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_let(Variables::[cerl()], Argument::cerl(), Body::cerl()) ->
+%% cerl()
+%%
+%% @doc Creates an abstract let-expression. If <code>Variables</code>
+%% is <code>[V1, ..., Vn]</code>, the result represents "<code>let
+%% &lt;<em>V1</em>, ..., <em>Vn</em>&gt; = <em>Argument</em> in
+%% <em>Body</em></code>". All the <code>Vi</code> must have type
+%% <code>var</code>.
+%%
+%% @see ann_c_let/4
+%% @see update_c_let/4
+%% @see is_c_let/1
+%% @see let_vars/1
+%% @see let_arg/1
+%% @see let_body/1
+%% @see let_arity/1
+
+-record('let', {ann = [], vars, arg, body}).
+
+c_let(Variables, Argument, Body) ->
+ #'let'{vars = Variables, arg = Argument, body = Body}.
+
+
+%% ann_c_let(As, Variables, Argument, Body) -> Node
+%% @see c_let/3
+
+ann_c_let(As, Variables, Argument, Body) ->
+ #'let'{vars = Variables, arg = Argument, body = Body, ann = As}.
+
+
+%% update_c_let(Old, Variables, Argument, Body) -> Node
+%% @see c_let/3
+
+update_c_let(Node, Variables, Argument, Body) ->
+ #'let'{vars = Variables, arg = Argument, body = Body,
+ ann = get_ann(Node)}.
+
+
+%% @spec is_c_let(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% let-expression, otherwise <code>false</code>.
+%%
+%% @see c_let/3
+
+is_c_let(#'let'{}) ->
+ true;
+is_c_let(_) ->
+ false.
+
+
+%% @spec let_vars(cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of left-hand side variables of an abstract
+%% let-expression.
+%%
+%% @see c_let/3
+%% @see let_arity/1
+
+let_vars(Node) ->
+ Node#'let'.vars.
+
+
+%% @spec let_arg(cerl()) -> cerl()
+%%
+%% @doc Returns the argument subtree of an abstract let-expression.
+%%
+%% @see c_let/3
+
+let_arg(Node) ->
+ Node#'let'.arg.
+
+
+%% @spec let_body(cerl()) -> cerl()
+%%
+%% @doc Returns the body subtree of an abstract let-expression.
+%%
+%% @see c_let/3
+
+let_body(Node) ->
+ Node#'let'.body.
+
+
+%% @spec let_arity(Node::cerl()) -> integer()
+%%
+%% @doc Returns the number of left-hand side variables of an abstract
+%% let-expression.
+%%
+%% <p>Note: this is equivalent to <code>length(let_vars(Node))</code>,
+%% but potentially more efficient.</p>
+%%
+%% @see c_let/3
+%% @see let_vars/1
+
+let_arity(Node) ->
+ length(let_vars(Node)).
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_letrec(Definitions::[{cerl(), cerl()}], Body::cerl()) ->
+%% cerl()
+%%
+%% @doc Creates an abstract letrec-expression. If
+%% <code>Definitions</code> is <code>[{V1, F1}, ..., {Vn, Fn}]</code>,
+%% the result represents "<code>letrec <em>V1</em> = <em>F1</em>
+%% ... <em>Vn</em> = <em>Fn</em> in <em>Body</em></code>. All the
+%% <code>Vi</code> must have type <code>var</code> and represent
+%% function names. All the <code>Fi</code> must have type
+%% <code>'fun'</code>.
+%%
+%% @see ann_c_letrec/3
+%% @see update_c_letrec/3
+%% @see is_c_letrec/1
+%% @see letrec_defs/1
+%% @see letrec_body/1
+%% @see letrec_vars/1
+
+-record(letrec, {ann = [], defs, body}).
+
+c_letrec(Defs, Body) ->
+ #letrec{defs = Defs, body = Body}.
+
+
+%% @spec ann_c_letrec(As::[term()], Definitions::[{cerl(), cerl()}],
+%% Body::cerl()) -> cerl()
+%% @see c_letrec/2
+
+ann_c_letrec(As, Defs, Body) ->
+ #letrec{defs = Defs, body = Body, ann = As}.
+
+
+%% @spec update_c_letrec(Old::cerl(),
+%% Definitions::[{cerl(), cerl()}],
+%% Body::cerl()) -> cerl()
+%% @see c_letrec/2
+
+update_c_letrec(Node, Defs, Body) ->
+ #letrec{defs = Defs, body = Body, ann = get_ann(Node)}.
+
+
+%% @spec is_c_letrec(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% letrec-expression, otherwise <code>false</code>.
+%%
+%% @see c_letrec/2
+
+is_c_letrec(#letrec{}) ->
+ true;
+is_c_letrec(_) ->
+ false.
+
+
+%% @spec letrec_defs(Node::cerl()) -> [{cerl(), cerl()}]
+%%
+%% @doc Returns the list of definitions of an abstract
+%% letrec-expression. If <code>Node</code> represents "<code>letrec
+%% <em>V1</em> = <em>F1</em> ... <em>Vn</em> = <em>Fn</em> in
+%% <em>Body</em></code>", the returned value is <code>[{V1, F1}, ...,
+%% {Vn, Fn}]</code>.
+%%
+%% @see c_letrec/2
+
+letrec_defs(Node) ->
+ Node#letrec.defs.
+
+
+%% @spec letrec_body(cerl()) -> cerl()
+%%
+%% @doc Returns the body subtree of an abstract letrec-expression.
+%%
+%% @see c_letrec/2
+
+letrec_body(Node) ->
+ Node#letrec.body.
+
+
+%% @spec letrec_vars(cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of left-hand side function variable subtrees
+%% of a letrec-expression. If <code>Node</code> represents
+%% "<code>letrec <em>V1</em> = <em>F1</em> ... <em>Vn</em> =
+%% <em>Fn</em> in <em>Body</em></code>", the returned value is
+%% <code>[V1, ..., Vn]</code>.
+%%
+%% @see c_letrec/2
+
+letrec_vars(Node) ->
+ [F || {F, _} <- letrec_defs(Node)].
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_case(Argument::cerl(), Clauses::[cerl()]) -> cerl()
+%%
+%% @doc Creates an abstract case-expression. If <code>Clauses</code>
+%% is <code>[C1, ..., Cn]</code>, the result represents "<code>case
+%% <em>Argument</em> of <em>C1</em> ... <em>Cn</em>
+%% end</code>". <code>Clauses</code> must not be empty.
+%%
+%% @see ann_c_case/3
+%% @see update_c_case/3
+%% @see is_c_case/1
+%% @see c_clause/3
+%% @see case_arg/1
+%% @see case_clauses/1
+%% @see case_arity/1
+
+-record('case', {ann = [], arg, clauses}).
+
+c_case(Expr, Clauses) ->
+ #'case'{arg = Expr, clauses = Clauses}.
+
+
+%% @spec ann_c_case(As::[term()], Argument::cerl(),
+%% Clauses::[cerl()]) -> cerl()
+%% @see c_case/2
+
+ann_c_case(As, Expr, Clauses) ->
+ #'case'{arg = Expr, clauses = Clauses, ann = As}.
+
+
+%% @spec update_c_case(Old::cerl(), Argument::cerl(),
+%% Clauses::[cerl()]) -> cerl()
+%% @see c_case/2
+
+update_c_case(Node, Expr, Clauses) ->
+ #'case'{arg = Expr, clauses = Clauses, ann = get_ann(Node)}.
+
+
+%% is_c_case(Node) -> boolean()
+%%
+%% Node = cerl()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% case-expression; otherwise <code>false</code>.
+%%
+%% @see c_case/2
+
+is_c_case(#'case'{}) ->
+ true;
+is_c_case(_) ->
+ false.
+
+
+%% @spec case_arg(cerl()) -> cerl()
+%%
+%% @doc Returns the argument subtree of an abstract case-expression.
+%%
+%% @see c_case/2
+
+case_arg(Node) ->
+ Node#'case'.arg.
+
+
+%% @spec case_clauses(cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of clause subtrees of an abstract
+%% case-expression.
+%%
+%% @see c_case/2
+%% @see case_arity/1
+
+case_clauses(Node) ->
+ Node#'case'.clauses.
+
+
+%% @spec case_arity(Node::cerl()) -> integer()
+%%
+%% @doc Equivalent to
+%% <code>clause_arity(hd(case_clauses(Node)))</code>, but potentially
+%% more efficient.
+%%
+%% @see c_case/2
+%% @see case_clauses/1
+%% @see clause_arity/1
+
+case_arity(Node) ->
+ clause_arity(hd(case_clauses(Node))).
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_clause(Patterns::[cerl()], Body::cerl()) -> cerl()
+%% @equiv c_clause(Patterns, c_atom(true), Body)
+%% @see c_atom/1
+
+c_clause(Patterns, Body) ->
+ c_clause(Patterns, c_atom(true), Body).
+
+
+%% @spec c_clause(Patterns::[cerl()], Guard::cerl(), Body::cerl()) ->
+%% cerl()
+%%
+%% @doc Creates an an abstract clause. If <code>Patterns</code> is
+%% <code>[P1, ..., Pn]</code>, the result represents
+%% "<code>&lt;<em>P1</em>, ..., <em>Pn</em>&gt; when <em>Guard</em> ->
+%% <em>Body</em></code>".
+%%
+%% @see c_clause/2
+%% @see ann_c_clause/4
+%% @see update_c_clause/4
+%% @see is_c_clause/1
+%% @see c_case/2
+%% @see c_receive/3
+%% @see clause_pats/1
+%% @see clause_guard/1
+%% @see clause_body/1
+%% @see clause_arity/1
+%% @see clause_vars/1
+
+-record(clause, {ann = [], pats, guard, body}).
+
+c_clause(Patterns, Guard, Body) ->
+ #clause{pats = Patterns, guard = Guard, body = Body}.
+
+
+%% @spec ann_c_clause(As::[term()], Patterns::[cerl()],
+%% Body::cerl()) -> cerl()
+%% @equiv ann_c_clause(As, Patterns, c_atom(true), Body)
+%% @see c_clause/3
+ann_c_clause(As, Patterns, Body) ->
+ ann_c_clause(As, Patterns, c_atom(true), Body).
+
+
+%% @spec ann_c_clause(As::[term()], Patterns::[cerl()], Guard::cerl(),
+%% Body::cerl()) -> cerl()
+%% @see ann_c_clause/3
+%% @see c_clause/3
+
+ann_c_clause(As, Patterns, Guard, Body) ->
+ #clause{pats = Patterns, guard = Guard, body = Body, ann = As}.
+
+
+%% @spec update_c_clause(Old::cerl(), Patterns::[cerl()],
+%% Guard::cerl(), Body::cerl()) -> cerl()
+%% @see c_clause/3
+
+update_c_clause(Node, Patterns, Guard, Body) ->
+ #clause{pats = Patterns, guard = Guard, body = Body,
+ ann = get_ann(Node)}.
+
+
+%% @spec is_c_clause(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% clause, otherwise <code>false</code>.
+%%
+%% @see c_clause/3
+
+is_c_clause(#clause{}) ->
+ true;
+is_c_clause(_) ->
+ false.
+
+
+%% @spec clause_pats(cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of pattern subtrees of an abstract clause.
+%%
+%% @see c_clause/3
+%% @see clause_arity/1
+
+clause_pats(Node) ->
+ Node#clause.pats.
+
+
+%% @spec clause_guard(cerl()) -> cerl()
+%%
+%% @doc Returns the guard subtree of an abstract clause.
+%%
+%% @see c_clause/3
+
+clause_guard(Node) ->
+ Node#clause.guard.
+
+
+%% @spec clause_body(cerl()) -> cerl()
+%%
+%% @doc Returns the body subtree of an abstract clause.
+%%
+%% @see c_clause/3
+
+clause_body(Node) ->
+ Node#clause.body.
+
+
+%% @spec clause_arity(Node::cerl()) -> integer()
+%%
+%% @doc Returns the number of pattern subtrees of an abstract clause.
+%%
+%% <p>Note: this is equivalent to
+%% <code>length(clause_pats(Node))</code>, but potentially more
+%% efficient.</p>
+%%
+%% @see c_clause/3
+%% @see clause_pats/1
+
+clause_arity(Node) ->
+ length(clause_pats(Node)).
+
+
+%% @spec clause_vars(cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of all abstract variables in the patterns of
+%% an abstract clause. The order of listing is not defined.
+%%
+%% @see c_clause/3
+%% @see pat_list_vars/1
+
+clause_vars(Clause) ->
+ pat_list_vars(clause_pats(Clause)).
+
+
+%% @spec pat_vars(Pattern::cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of all abstract variables in a pattern. An
+%% exception is thrown if <code>Node</code> does not represent a
+%% well-formed Core Erlang clause pattern. The order of listing is not
+%% defined.
+%%
+%% @see pat_list_vars/1
+%% @see clause_vars/1
+
+pat_vars(Node) ->
+ pat_vars(Node, []).
+
+pat_vars(Node, Vs) ->
+ case type(Node) of
+ var ->
+ [Node | Vs];
+ literal ->
+ Vs;
+ cons ->
+ pat_vars(cons_hd(Node), pat_vars(cons_tl(Node), Vs));
+ tuple ->
+ pat_list_vars(tuple_es(Node), Vs);
+ binary ->
+ pat_list_vars(binary_segments(Node), Vs);
+ bitstr ->
+ pat_vars(bitstr_val(Node), Vs);
+ alias ->
+ pat_vars(alias_pat(Node), [alias_var(Node) | Vs])
+ end.
+
+
+%% @spec pat_list_vars(Patterns::[cerl()]) -> [cerl()]
+%%
+%% @doc Returns the list of all abstract variables in the given
+%% patterns. An exception is thrown if some element in
+%% <code>Patterns</code> does not represent a well-formed Core Erlang
+%% clause pattern. The order of listing is not defined.
+%%
+%% @see pat_vars/1
+%% @see clause_vars/1
+
+pat_list_vars(Ps) ->
+ pat_list_vars(Ps, []).
+
+pat_list_vars([P | Ps], Vs) ->
+ pat_list_vars(Ps, pat_vars(P, Vs));
+pat_list_vars([], Vs) ->
+ Vs.
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_alias(Variable::cerl(), Pattern::cerl()) -> cerl()
+%%
+%% @doc Creates an abstract pattern alias. The result represents
+%% "<code><em>Variable</em> = <em>Pattern</em></code>".
+%%
+%% @see ann_c_alias/3
+%% @see update_c_alias/3
+%% @see is_c_alias/1
+%% @see alias_var/1
+%% @see alias_pat/1
+%% @see c_clause/3
+
+-record(alias, {ann = [], var, pat}).
+
+c_alias(Var, Pattern) ->
+ #alias{var = Var, pat = Pattern}.
+
+
+%% @spec ann_c_alias(As::[term()], Variable::cerl(),
+%% Pattern::cerl()) -> cerl()
+%% @see c_alias/2
+
+ann_c_alias(As, Var, Pattern) ->
+ #alias{var = Var, pat = Pattern, ann = As}.
+
+
+%% @spec update_c_alias(Old::cerl(), Variable::cerl(),
+%% Pattern::cerl()) -> cerl()
+%% @see c_alias/2
+
+update_c_alias(Node, Var, Pattern) ->
+ #alias{var = Var, pat = Pattern, ann = get_ann(Node)}.
+
+
+%% @spec is_c_alias(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% pattern alias, otherwise <code>false</code>.
+%%
+%% @see c_alias/2
+
+is_c_alias(#alias{}) ->
+ true;
+is_c_alias(_) ->
+ false.
+
+
+%% @spec alias_var(cerl()) -> cerl()
+%%
+%% @doc Returns the variable subtree of an abstract pattern alias.
+%%
+%% @see c_alias/2
+
+alias_var(Node) ->
+ Node#alias.var.
+
+
+%% @spec alias_pat(cerl()) -> cerl()
+%%
+%% @doc Returns the pattern subtree of an abstract pattern alias.
+%%
+%% @see c_alias/2
+
+alias_pat(Node) ->
+ Node#alias.pat.
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_receive(Clauses::[cerl()]) -> cerl()
+%% @equiv c_receive(Clauses, c_atom(infinity), c_atom(true))
+%% @see c_atom/1
+
+c_receive(Clauses) ->
+ c_receive(Clauses, c_atom(infinity), c_atom(true)).
+
+
+%% @spec c_receive(Clauses::[cerl()], Timeout::cerl(),
+%% Action::cerl()) -> cerl()
+%%
+%% @doc Creates an abstract receive-expression. If
+%% <code>Clauses</code> is <code>[C1, ..., Cn]</code>, the result
+%% represents "<code>receive <em>C1</em> ... <em>Cn</em> after
+%% <em>Timeout</em> -> <em>Action</em> end</code>".
+%%
+%% @see c_receive/1
+%% @see ann_c_receive/4
+%% @see update_c_receive/4
+%% @see is_c_receive/1
+%% @see receive_clauses/1
+%% @see receive_timeout/1
+%% @see receive_action/1
+
+-record('receive', {ann = [], clauses, timeout, action}).
+
+c_receive(Clauses, Timeout, Action) ->
+ #'receive'{clauses = Clauses, timeout = Timeout, action = Action}.
+
+
+%% @spec ann_c_receive(As::[term()], Clauses::[cerl()]) -> cerl()
+%% @equiv ann_c_receive(As, Clauses, c_atom(infinity), c_atom(true))
+%% @see c_receive/3
+%% @see c_atom/1
+
+ann_c_receive(As, Clauses) ->
+ ann_c_receive(As, Clauses, c_atom(infinity), c_atom(true)).
+
+
+%% @spec ann_c_receive(As::[term()], Clauses::[cerl()],
+%% Timeout::cerl(), Action::cerl()) -> cerl()
+%% @see ann_c_receive/2
+%% @see c_receive/3
+
+ann_c_receive(As, Clauses, Timeout, Action) ->
+ #'receive'{clauses = Clauses, timeout = Timeout, action = Action,
+ ann = As}.
+
+
+%% @spec update_c_receive(Old::cerl(), Clauses::[cerl()],
+%% Timeout::cerl(), Action::cerl()) -> cerl()
+%% @see c_receive/3
+
+update_c_receive(Node, Clauses, Timeout, Action) ->
+ #'receive'{clauses = Clauses, timeout = Timeout, action = Action,
+ ann = get_ann(Node)}.
+
+
+%% @spec is_c_receive(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% receive-expression, otherwise <code>false</code>.
+%%
+%% @see c_receive/3
+
+is_c_receive(#'receive'{}) ->
+ true;
+is_c_receive(_) ->
+ false.
+
+
+%% @spec receive_clauses(cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of clause subtrees of an abstract
+%% receive-expression.
+%%
+%% @see c_receive/3
+
+receive_clauses(Node) ->
+ Node#'receive'.clauses.
+
+
+%% @spec receive_timeout(cerl()) -> cerl()
+%%
+%% @doc Returns the timeout subtree of an abstract receive-expression.
+%%
+%% @see c_receive/3
+
+receive_timeout(Node) ->
+ Node#'receive'.timeout.
+
+
+%% @spec receive_action(cerl()) -> cerl()
+%%
+%% @doc Returns the action subtree of an abstract receive-expression.
+%%
+%% @see c_receive/3
+
+receive_action(Node) ->
+ Node#'receive'.action.
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_apply(Operator::cerl(), Arguments::[cerl()]) -> cerl()
+%%
+%% @doc Creates an abstract function application. If
+%% <code>Arguments</code> is <code>[A1, ..., An]</code>, the result
+%% represents "<code>apply <em>Operator</em>(<em>A1</em>, ...,
+%% <em>An</em>)</code>".
+%%
+%% @see ann_c_apply/3
+%% @see update_c_apply/3
+%% @see is_c_apply/1
+%% @see apply_op/1
+%% @see apply_args/1
+%% @see apply_arity/1
+%% @see c_call/3
+%% @see c_primop/2
+
+-record(apply, {ann = [], op, args}).
+
+c_apply(Operator, Arguments) ->
+ #apply{op = Operator, args = Arguments}.
+
+
+%% @spec ann_c_apply(As::[term()], Operator::cerl(),
+%% Arguments::[cerl()]) -> cerl()
+%% @see c_apply/2
+
+ann_c_apply(As, Operator, Arguments) ->
+ #apply{op = Operator, args = Arguments, ann = As}.
+
+
+%% @spec update_c_apply(Old::cerl(), Operator::cerl(),
+%% Arguments::[cerl()]) -> cerl()
+%% @see c_apply/2
+
+update_c_apply(Node, Operator, Arguments) ->
+ #apply{op = Operator, args = Arguments, ann = get_ann(Node)}.
+
+
+%% @spec is_c_apply(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% function application, otherwise <code>false</code>.
+%%
+%% @see c_apply/2
+
+is_c_apply(#apply{}) ->
+ true;
+is_c_apply(_) ->
+ false.
+
+
+%% @spec apply_op(cerl()) -> cerl()
+%%
+%% @doc Returns the operator subtree of an abstract function
+%% application.
+%%
+%% @see c_apply/2
+
+apply_op(Node) ->
+ Node#apply.op.
+
+
+%% @spec apply_args(cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of argument subtrees of an abstract function
+%% application.
+%%
+%% @see c_apply/2
+%% @see apply_arity/1
+
+apply_args(Node) ->
+ Node#apply.args.
+
+
+%% @spec apply_arity(Node::cerl()) -> integer()
+%%
+%% @doc Returns the number of argument subtrees of an abstract
+%% function application.
+%%
+%% <p>Note: this is equivalent to
+%% <code>length(apply_args(Node))</code>, but potentially more
+%% efficient.</p>
+%%
+%% @see c_apply/2
+%% @see apply_args/1
+
+apply_arity(Node) ->
+ length(apply_args(Node)).
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_call(Module::cerl(), Name::cerl(), Arguments::[cerl()]) ->
+%% cerl()
+%%
+%% @doc Creates an abstract inter-module call. If
+%% <code>Arguments</code> is <code>[A1, ..., An]</code>, the result
+%% represents "<code>call <em>Module</em>:<em>Name</em>(<em>A1</em>,
+%% ..., <em>An</em>)</code>".
+%%
+%% @see ann_c_call/4
+%% @see update_c_call/4
+%% @see is_c_call/1
+%% @see call_module/1
+%% @see call_name/1
+%% @see call_args/1
+%% @see call_arity/1
+%% @see c_apply/2
+%% @see c_primop/2
+
+-record(call, {ann = [], module, name, args}).
+
+c_call(Module, Name, Arguments) ->
+ #call{module = Module, name = Name, args = Arguments}.
+
+
+%% @spec ann_c_call(As::[term()], Module::cerl(), Name::cerl(),
+%% Arguments::[cerl()]) -> cerl()
+%% @see c_call/3
+
+ann_c_call(As, Module, Name, Arguments) ->
+ #call{module = Module, name = Name, args = Arguments, ann = As}.
+
+
+%% @spec update_c_call(Old::cerl(), Module::cerl(), Name::cerl(),
+%% Arguments::[cerl()]) -> cerl()
+%% @see c_call/3
+
+update_c_call(Node, Module, Name, Arguments) ->
+ #call{module = Module, name = Name, args = Arguments,
+ ann = get_ann(Node)}.
+
+
+%% @spec is_c_call(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% inter-module call expression; otherwise <code>false</code>.
+%%
+%% @see c_call/3
+
+is_c_call(#call{}) ->
+ true;
+is_c_call(_) ->
+ false.
+
+
+%% @spec call_module(cerl()) -> cerl()
+%%
+%% @doc Returns the module subtree of an abstract inter-module call.
+%%
+%% @see c_call/3
+
+call_module(Node) ->
+ Node#call.module.
+
+
+%% @spec call_name(cerl()) -> cerl()
+%%
+%% @doc Returns the name subtree of an abstract inter-module call.
+%%
+%% @see c_call/3
+
+call_name(Node) ->
+ Node#call.name.
+
+
+%% @spec call_args(cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of argument subtrees of an abstract
+%% inter-module call.
+%%
+%% @see c_call/3
+%% @see call_arity/1
+
+call_args(Node) ->
+ Node#call.args.
+
+
+%% @spec call_arity(Node::cerl()) -> integer()
+%%
+%% @doc Returns the number of argument subtrees of an abstract
+%% inter-module call.
+%%
+%% <p>Note: this is equivalent to
+%% <code>length(call_args(Node))</code>, but potentially more
+%% efficient.</p>
+%%
+%% @see c_call/3
+%% @see call_args/1
+
+call_arity(Node) ->
+ length(call_args(Node)).
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_primop(Name::cerl(), Arguments::[cerl()]) -> cerl()
+%%
+%% @doc Creates an abstract primitive operation call. If
+%% <code>Arguments</code> is <code>[A1, ..., An]</code>, the result
+%% represents "<code>primop <em>Name</em>(<em>A1</em>, ...,
+%% <em>An</em>)</code>". <code>Name</code> must be an atom literal.
+%%
+%% @see ann_c_primop/3
+%% @see update_c_primop/3
+%% @see is_c_primop/1
+%% @see primop_name/1
+%% @see primop_args/1
+%% @see primop_arity/1
+%% @see c_apply/2
+%% @see c_call/3
+
+-record(primop, {ann = [], name, args}).
+
+c_primop(Name, Arguments) ->
+ #primop{name = Name, args = Arguments}.
+
+
+%% @spec ann_c_primop(As::[term()], Name::cerl(),
+%% Arguments::[cerl()]) -> cerl()
+%% @see c_primop/2
+
+ann_c_primop(As, Name, Arguments) ->
+ #primop{name = Name, args = Arguments, ann = As}.
+
+
+%% @spec update_c_primop(Old::cerl(), Name::cerl(),
+%% Arguments::[cerl()]) -> cerl()
+%% @see c_primop/2
+
+update_c_primop(Node, Name, Arguments) ->
+ #primop{name = Name, args = Arguments, ann = get_ann(Node)}.
+
+
+%% @spec is_c_primop(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% primitive operation call, otherwise <code>false</code>.
+%%
+%% @see c_primop/2
+
+is_c_primop(#primop{}) ->
+ true;
+is_c_primop(_) ->
+ false.
+
+
+%% @spec primop_name(cerl()) -> cerl()
+%%
+%% @doc Returns the name subtree of an abstract primitive operation
+%% call.
+%%
+%% @see c_primop/2
+
+primop_name(Node) ->
+ Node#primop.name.
+
+
+%% @spec primop_args(cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of argument subtrees of an abstract primitive
+%% operation call.
+%%
+%% @see c_primop/2
+%% @see primop_arity/1
+
+primop_args(Node) ->
+ Node#primop.args.
+
+
+%% @spec primop_arity(Node::cerl()) -> integer()
+%%
+%% @doc Returns the number of argument subtrees of an abstract
+%% primitive operation call.
+%%
+%% <p>Note: this is equivalent to
+%% <code>length(primop_args(Node))</code>, but potentially more
+%% efficient.</p>
+%%
+%% @see c_primop/2
+%% @see primop_args/1
+
+primop_arity(Node) ->
+ length(primop_args(Node)).
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_try(Argument::cerl(), Variables::[cerl()], Body::cerl(),
+%% ExceptionVars::[cerl()], Handler::cerl()) -> cerl()
+%%
+%% @doc Creates an abstract try-expression. If <code>Variables</code> is
+%% <code>[V1, ..., Vn]</code> and <code>ExceptionVars</code> is
+%% <code>[X1, ..., Xm]</code>, the result represents "<code>try
+%% <em>Argument</em> of &lt;<em>V1</em>, ..., <em>Vn</em>&gt; ->
+%% <em>Body</em> catch &lt;<em>X1</em>, ..., <em>Xm</em>&gt; ->
+%% <em>Handler</em></code>". All the <code>Vi</code> and <code>Xi</code>
+%% must have type <code>var</code>.
+%%
+%% @see ann_c_try/6
+%% @see update_c_try/6
+%% @see is_c_try/1
+%% @see try_arg/1
+%% @see try_vars/1
+%% @see try_body/1
+%% @see c_catch/1
+
+-record('try', {ann = [], arg, vars, body, evars, handler}).
+
+c_try(Expr, Vs, Body, Evs, Handler) ->
+ #'try'{arg = Expr, vars = Vs, body = Body,
+ evars = Evs, handler = Handler}.
+
+
+%% @spec ann_c_try(As::[term()], Expression::cerl(),
+%% Variables::[cerl()], Body::cerl(),
+%% EVars::[cerl()], EBody::[cerl()]) -> cerl()
+%% @see c_try/3
+
+ann_c_try(As, Expr, Vs, Body, Evs, Handler) ->
+ #'try'{arg = Expr, vars = Vs, body = Body,
+ evars = Evs, handler = Handler, ann = As}.
+
+
+%% @spec update_c_try(Old::cerl(), Expression::cerl(),
+%% Variables::[cerl()], Body::cerl(),
+%% EVars::[cerl()], EBody::[cerl()]) -> cerl()
+%% @see c_try/3
+
+update_c_try(Node, Expr, Vs, Body, Evs, Handler) ->
+ #'try'{arg = Expr, vars = Vs, body = Body,
+ evars = Evs, handler = Handler, ann = get_ann(Node)}.
+
+
+%% @spec is_c_try(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% try-expression, otherwise <code>false</code>.
+%%
+%% @see c_try/3
+
+is_c_try(#'try'{}) ->
+ true;
+is_c_try(_) ->
+ false.
+
+
+%% @spec try_arg(cerl()) -> cerl()
+%%
+%% @doc Returns the expression subtree of an abstract try-expression.
+%%
+%% @see c_try/3
+
+try_arg(Node) ->
+ Node#'try'.arg.
+
+
+%% @spec try_vars(cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of success variable subtrees of an abstract
+%% try-expression.
+%%
+%% @see c_try/3
+
+try_vars(Node) ->
+ Node#'try'.vars.
+
+
+%% @spec try_body(cerl()) -> cerl()
+%%
+%% @doc Returns the success body subtree of an abstract try-expression.
+%%
+%% @see c_try/3
+
+try_body(Node) ->
+ Node#'try'.body.
+
+
+%% @spec try_evars(cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of exception variable subtrees of an abstract
+%% try-expression.
+%%
+%% @see c_try/3
+
+try_evars(Node) ->
+ Node#'try'.evars.
+
+
+%% @spec try_handler(cerl()) -> cerl()
+%%
+%% @doc Returns the exception body subtree of an abstract
+%% try-expression.
+%%
+%% @see c_try/3
+
+try_handler(Node) ->
+ Node#'try'.handler.
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec c_catch(Body::cerl()) -> cerl()
+%%
+%% @doc Creates an abstract catch-expression. The result represents
+%% "<code>catch <em>Body</em></code>".
+%%
+%% <p>Note: catch-expressions can be rewritten as try-expressions, and
+%% will eventually be removed from Core Erlang.</p>
+%%
+%% @see ann_c_catch/2
+%% @see update_c_catch/2
+%% @see is_c_catch/1
+%% @see catch_body/1
+%% @see c_try/3
+
+-record('catch', {ann = [], body}).
+
+c_catch(Body) ->
+ #'catch'{body = Body}.
+
+
+%% @spec ann_c_catch(As::[term()], Body::cerl()) -> cerl()
+%% @see c_catch/1
+
+ann_c_catch(As, Body) ->
+ #'catch'{body = Body, ann = As}.
+
+
+%% @spec update_c_catch(Old::cerl(), Body::cerl()) -> cerl()
+%% @see c_catch/1
+
+update_c_catch(Node, Body) ->
+ #'catch'{body = Body, ann = get_ann(Node)}.
+
+
+%% @spec is_c_catch(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
+%% catch-expression, otherwise <code>false</code>.
+%%
+%% @see c_catch/1
+
+is_c_catch(#'catch'{}) ->
+ true;
+is_c_catch(_) ->
+ false.
+
+
+%% @spec catch_body(Node::cerl()) -> cerl()
+%%
+%% @doc Returns the body subtree of an abstract catch-expression.
+%%
+%% @see c_catch/1
+
+catch_body(Node) ->
+ Node#'catch'.body.
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec to_records(Tree::cerl()) -> record(record_types())
+%%
+%% @doc Translates an abstract syntax tree to a corresponding explicit
+%% record representation. The records are defined in the file
+%% "<code>cerl.hrl</code>".
+%%
+%% <p>Note: Compound constant literals are always unfolded in the
+%% record representation.</p>
+%%
+%% @see type/1
+%% @see from_records/1
+
+to_records(Node) ->
+ A = get_ann(Node),
+ case type(Node) of
+ literal ->
+ lit_to_records(concrete(Node), A);
+ binary ->
+ #c_binary{anno = A,
+ segments =
+ list_to_records(binary_segments(Node))};
+ bitstr ->
+ #c_bitstr{anno = A,
+ val = to_records(bitstr_val(Node)),
+ size = to_records(bitstr_size(Node)),
+ unit = to_records(bitstr_unit(Node)),
+ type = to_records(bitstr_type(Node)),
+ flags = to_records(bitstr_flags(Node))};
+ cons ->
+ #c_cons{anno = A,
+ hd = to_records(cons_hd(Node)),
+ tl = to_records(cons_tl(Node))};
+ tuple ->
+ #c_tuple{anno = A,
+ es = list_to_records(tuple_es(Node))};
+ var ->
+ case is_c_fname(Node) of
+ true ->
+ #c_fname{anno = A,
+ id = fname_id(Node),
+ arity = fname_arity(Node)};
+ false ->
+ #c_var{anno = A, name = var_name(Node)}
+ end;
+ values ->
+ #c_values{anno = A,
+ es = list_to_records(values_es(Node))};
+ 'fun' ->
+ #c_fun{anno = A,
+ vars = list_to_records(fun_vars(Node)),
+ body = to_records(fun_body(Node))};
+ seq ->
+ #c_seq{anno = A,
+ arg = to_records(seq_arg(Node)),
+ body = to_records(seq_body(Node))};
+ 'let' ->
+ #c_let{anno = A,
+ vars = list_to_records(let_vars(Node)),
+ arg = to_records(let_arg(Node)),
+ body = to_records(let_body(Node))};
+ letrec ->
+ #c_letrec{anno = A,
+ defs = [#c_def{name = to_records(N),
+ val = to_records(F)}
+ || {N, F} <- letrec_defs(Node)],
+ body = to_records(letrec_body(Node))};
+ 'case' ->
+ #c_case{anno = A,
+ arg = to_records(case_arg(Node)),
+ clauses =
+ list_to_records(case_clauses(Node))};
+ clause ->
+ #c_clause{anno = A,
+ pats = list_to_records(clause_pats(Node)),
+ guard = to_records(clause_guard(Node)),
+ body = to_records(clause_body(Node))};
+ alias ->
+ #c_alias{anno = A,
+ var = to_records(alias_var(Node)),
+ pat = to_records(alias_pat(Node))};
+ 'receive' ->
+ #c_receive{anno = A,
+ clauses =
+ list_to_records(receive_clauses(Node)),
+ timeout =
+ to_records(receive_timeout(Node)),
+ action =
+ to_records(receive_action(Node))};
+ apply ->
+ #c_apply{anno = A,
+ op = to_records(apply_op(Node)),
+ args = list_to_records(apply_args(Node))};
+ call ->
+ #c_call{anno = A,
+ module = to_records(call_module(Node)),
+ name = to_records(call_name(Node)),
+ args = list_to_records(call_args(Node))};
+ primop ->
+ #c_primop{anno = A,
+ name = to_records(primop_name(Node)),
+ args = list_to_records(primop_args(Node))};
+ 'try' ->
+ #c_try{anno = A,
+ arg = to_records(try_arg(Node)),
+ vars = list_to_records(try_vars(Node)),
+ body = to_records(try_body(Node)),
+ evars = list_to_records(try_evars(Node)),
+ handler = to_records(try_handler(Node))};
+ 'catch' ->
+ #c_catch{anno = A,
+ body = to_records(catch_body(Node))};
+ module ->
+ #c_module{anno = A,
+ name = to_records(module_name(Node)),
+ exports = list_to_records(
+ module_exports(Node)),
+ attrs = [#c_def{name = to_records(K),
+ val = to_records(V)}
+ || {K, V} <- module_attrs(Node)],
+ defs = [#c_def{name = to_records(N),
+ val = to_records(F)}
+ || {N, F} <- module_defs(Node)]}
+ end.
+
+list_to_records([T | Ts]) ->
+ [to_records(T) | list_to_records(Ts)];
+list_to_records([]) ->
+ [].
+
+lit_to_records(V, A) when integer(V) ->
+ #c_int{anno = A, val = V};
+lit_to_records(V, A) when float(V) ->
+ #c_float{anno = A, val = V};
+lit_to_records(V, A) when atom(V) ->
+ #c_atom{anno = A, val = V};
+lit_to_records([H | T] = V, A) ->
+ case is_print_char_list(V) of
+ true ->
+ #c_string{anno = A, val = V};
+ false ->
+ #c_cons{anno = A,
+ hd = lit_to_records(H, []),
+ tl = lit_to_records(T, [])}
+ end;
+lit_to_records([], A) ->
+ #c_nil{anno = A};
+lit_to_records(V, A) when tuple(V) ->
+ #c_tuple{anno = A, es = lit_list_to_records(tuple_to_list(V))}.
+
+lit_list_to_records([T | Ts]) ->
+ [lit_to_records(T, []) | lit_list_to_records(Ts)];
+lit_list_to_records([]) ->
+ [].
+
+
+%% @spec from_records(Tree::record(record_types())) -> cerl()
+%%
+%% record_types() = c_alias | c_apply | c_call | c_case | c_catch |
+%% c_clause | c_cons | c_def| c_fun | c_let |
+%% c_letrec |c_lit | c_module | c_primop |
+%% c_receive | c_seq | c_try | c_tuple |
+%% c_values | c_var
+%%
+%% @doc Translates an explicit record representation to a
+%% corresponding abstract syntax tree. The records are defined in the
+%% file "<code>cerl.hrl</code>".
+%%
+%% <p>Note: Compound constant literals are folded, discarding
+%% annotations on subtrees. There are no <code>c_def</code> nodes in
+%% the abstract representation; annotations on <code>c_def</code>
+%% records are discarded.</p>
+%%
+%% @see type/1
+%% @see to_records/1
+
+from_records(#c_int{val = V, anno = As}) ->
+ ann_c_int(As, V);
+from_records(#c_float{val = V, anno = As}) ->
+ ann_c_float(As, V);
+from_records(#c_atom{val = V, anno = As}) ->
+ ann_c_atom(As, V);
+from_records(#c_char{val = V, anno = As}) ->
+ ann_c_char(As, V);
+from_records(#c_string{val = V, anno = As}) ->
+ ann_c_string(As, V);
+from_records(#c_nil{anno = As}) ->
+ ann_c_nil(As);
+from_records(#c_binary{segments = Ss, anno = As}) ->
+ ann_c_binary(As, from_records_list(Ss));
+from_records(#c_bitstr{val = V, size = S, unit = U, type = T,
+ flags = Fs, anno = As}) ->
+ ann_c_bitstr(As, from_records(V), from_records(S), from_records(U),
+ from_records(T), from_records(Fs));
+from_records(#c_cons{hd = H, tl = T, anno = As}) ->
+ ann_c_cons(As, from_records(H), from_records(T));
+from_records(#c_tuple{es = Es, anno = As}) ->
+ ann_c_tuple(As, from_records_list(Es));
+from_records(#c_var{name = Name, anno = As}) ->
+ ann_c_var(As, Name);
+from_records(#c_fname{id = Id, arity = Arity, anno = As}) ->
+ ann_c_fname(As, Id, Arity);
+from_records(#c_values{es = Es, anno = As}) ->
+ ann_c_values(As, from_records_list(Es));
+from_records(#c_fun{vars = Vs, body = B, anno = As}) ->
+ ann_c_fun(As, from_records_list(Vs), from_records(B));
+from_records(#c_seq{arg = A, body = B, anno = As}) ->
+ ann_c_seq(As, from_records(A), from_records(B));
+from_records(#c_let{vars = Vs, arg = A, body = B, anno = As}) ->
+ ann_c_let(As, from_records_list(Vs), from_records(A),
+ from_records(B));
+from_records(#c_letrec{defs = Fs, body = B, anno = As}) ->
+ ann_c_letrec(As, [{from_records(N), from_records(F)}
+ || #c_def{name = N, val = F} <- Fs],
+ from_records(B));
+from_records(#c_case{arg = A, clauses = Cs, anno = As}) ->
+ ann_c_case(As, from_records(A), from_records_list(Cs));
+from_records(#c_clause{pats = Ps, guard = G, body = B, anno = As}) ->
+ ann_c_clause(As, from_records_list(Ps), from_records(G),
+ from_records(B));
+from_records(#c_alias{var = V, pat = P, anno = As}) ->
+ ann_c_alias(As, from_records(V), from_records(P));
+from_records(#c_receive{clauses = Cs, timeout = T, action = A,
+ anno = As}) ->
+ ann_c_receive(As, from_records_list(Cs), from_records(T),
+ from_records(A));
+from_records(#c_apply{op = Op, args = Es, anno = As}) ->
+ ann_c_apply(As, from_records(Op), from_records_list(Es));
+from_records(#c_call{module = M, name = N, args = Es, anno = As}) ->
+ ann_c_call(As, from_records(M), from_records(N),
+ from_records_list(Es));
+from_records(#c_primop{name = N, args = Es, anno = As}) ->
+ ann_c_primop(As, from_records(N), from_records_list(Es));
+from_records(#c_try{arg = E, vars = Vs, body = B,
+ evars = Evs, handler = H, anno = As}) ->
+ ann_c_try(As, from_records(E), from_records_list(Vs),
+ from_records(B), from_records_list(Evs), from_records(H));
+from_records(#c_catch{body = B, anno = As}) ->
+ ann_c_catch(As, from_records(B));
+from_records(#c_module{name = N, exports = Es, attrs = Ds, defs = Fs,
+ anno = As}) ->
+ ann_c_module(As, from_records(N),
+ from_records_list(Es),
+ [{from_records(K), from_records(V)}
+ || #c_def{name = K, val = V} <- Ds],
+ [{from_records(V), from_records(F)}
+ || #c_def{name = V, val = F} <- Fs]).
+
+from_records_list([T | Ts]) ->
+ [from_records(T) | from_records_list(Ts)];
+from_records_list([]) ->
+ [].
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec is_data(Node::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if <code>Node</code> represents a
+%% data constructor, otherwise <code>false</code>. Data constructors
+%% are cons cells, tuples, and atomic literals.
+%%
+%% @see data_type/1
+%% @see data_es/1
+%% @see data_arity/1
+
+is_data(#literal{}) ->
+ true;
+is_data(#cons{}) ->
+ true;
+is_data(#tuple{}) ->
+ true;
+is_data(_) ->
+ false.
+
+
+%% @spec data_type(Node::cerl()) -> dtype()
+%%
+%% dtype() = cons | tuple | {'atomic', Value}
+%% Value = integer() | float() | atom() | []
+%%
+%% @doc Returns a type descriptor for a data constructor
+%% node. (Cf. <code>is_data/1</code>.) This is mainly useful for
+%% comparing types and for constructing new nodes of the same type
+%% (cf. <code>make_data/2</code>). If <code>Node</code> represents an
+%% integer, floating-point number, atom or empty list, the result is
+%% <code>{'atomic', Value}</code>, where <code>Value</code> is the value
+%% of <code>concrete(Node)</code>, otherwise the result is either
+%% <code>cons</code> or <code>tuple</code>.
+%%
+%% <p>Type descriptors can be compared for equality or order (in the
+%% Erlang term order), but remember that floating-point values should
+%% in general never be tested for equality.</p>
+%%
+%% @see is_data/1
+%% @see make_data/2
+%% @see type/1
+%% @see concrete/1
+
+data_type(#literal{val = V}) ->
+ case V of
+ [_ | _] ->
+ cons;
+ _ when tuple(V) ->
+ tuple;
+ _ ->
+ {'atomic', V}
+ end;
+data_type(#cons{}) ->
+ cons;
+data_type(#tuple{}) ->
+ tuple.
+
+
+%% @spec data_es(Node::cerl()) -> [cerl()]
+%%
+%% @doc Returns the list of subtrees of a data constructor node. If
+%% the arity of the constructor is zero, the result is the empty list.
+%%
+%% <p>Note: if <code>data_type(Node)</code> is <code>cons</code>, the
+%% number of subtrees is exactly two. If <code>data_type(Node)</code>
+%% is <code>{'atomic', Value}</code>, the number of subtrees is
+%% zero.</p>
+%%
+%% @see is_data/1
+%% @see data_type/1
+%% @see data_arity/1
+%% @see make_data/2
+
+data_es(#literal{val = V}) ->
+ case V of
+ [Head | Tail] ->
+ [#literal{val = Head}, #literal{val = Tail}];
+ _ when tuple(V) ->
+ make_lit_list(tuple_to_list(V));
+ _ ->
+ []
+ end;
+data_es(#cons{hd = H, tl = T}) ->
+ [H, T];
+data_es(#tuple{es = Es}) ->
+ Es.
+
+
+%% @spec data_arity(Node::cerl()) -> integer()
+%%
+%% @doc Returns the number of subtrees of a data constructor
+%% node. This is equivalent to <code>length(data_es(Node))</code>, but
+%% potentially more efficient.
+%%
+%% @see is_data/1
+%% @see data_es/1
+
+data_arity(#literal{val = V}) ->
+ case V of
+ [_ | _] ->
+ 2;
+ _ when tuple(V) ->
+ size(V);
+ _ ->
+ 0
+ end;
+data_arity(#cons{}) ->
+ 2;
+data_arity(#tuple{es = Es}) ->
+ length(Es).
+
+
+%% @spec make_data(Type::dtype(), Elements::[cerl()]) -> cerl()
+%%
+%% @doc Creates a data constructor node with the specified type and
+%% subtrees. (Cf. <code>data_type/1</code>.) An exception is thrown
+%% if the length of <code>Elements</code> is invalid for the given
+%% <code>Type</code>; see <code>data_es/1</code> for arity constraints
+%% on constructor types.
+%%
+%% @see data_type/1
+%% @see data_es/1
+%% @see ann_make_data/3
+%% @see update_data/3
+%% @see make_data_skel/2
+
+make_data(CType, Es) ->
+ ann_make_data([], CType, Es).
+
+
+%% @spec ann_make_data(As::[term()], Type::dtype(),
+%% Elements::[cerl()]) -> cerl()
+%% @see make_data/2
+
+ann_make_data(As, {'atomic', V}, []) -> #literal{val = V, ann = As};
+ann_make_data(As, cons, [H, T]) -> ann_c_cons(As, H, T);
+ann_make_data(As, tuple, Es) -> ann_c_tuple(As, Es).
+
+
+%% @spec update_data(Old::cerl(), Type::dtype(),
+%% Elements::[cerl()]) -> cerl()
+%% @see make_data/2
+
+update_data(Node, CType, Es) ->
+ ann_make_data(get_ann(Node), CType, Es).
+
+
+%% @spec make_data_skel(Type::dtype(), Elements::[cerl()]) -> cerl()
+%%
+%% @doc Like <code>make_data/2</code>, but analogous to
+%% <code>c_tuple_skel/1</code> and <code>c_cons_skel/2</code>.
+%%
+%% @see ann_make_data_skel/3
+%% @see update_data_skel/3
+%% @see make_data/2
+%% @see c_tuple_skel/1
+%% @see c_cons_skel/2
+
+make_data_skel(CType, Es) ->
+ ann_make_data_skel([], CType, Es).
+
+
+%% @spec ann_make_data_skel(As::[term()], Type::dtype(),
+%% Elements::[cerl()]) -> cerl()
+%% @see make_data_skel/2
+
+ann_make_data_skel(As, {'atomic', V}, []) -> #literal{val = V, ann = As};
+ann_make_data_skel(As, cons, [H, T]) -> ann_c_cons_skel(As, H, T);
+ann_make_data_skel(As, tuple, Es) -> ann_c_tuple_skel(As, Es).
+
+
+%% @spec update_data_skel(Old::cerl(), Type::dtype(),
+%% Elements::[cerl()]) -> cerl()
+%% @see make_data_skel/2
+
+update_data_skel(Node, CType, Es) ->
+ ann_make_data_skel(get_ann(Node), CType, Es).
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec subtrees(Node::cerl()) -> [[cerl()]]
+%%
+%% @doc Returns the grouped list of all subtrees of a node. If
+%% <code>Node</code> is a leaf node (cf. <code>is_leaf/1</code>), this
+%% is the empty list, otherwise the result is always a nonempty list,
+%% containing the lists of subtrees of <code>Node</code>, in
+%% left-to-right order as they occur in the printed program text, and
+%% grouped by category. Often, each group contains only a single
+%% subtree.
+%%
+%% <p>Depending on the type of <code>Node</code>, the size of some
+%% groups may be variable (e.g., the group consisting of all the
+%% elements of a tuple), while others always contain the same number
+%% of elements - usually exactly one (e.g., the group containing the
+%% argument expression of a case-expression). Note, however, that the
+%% exact structure of the returned list (for a given node type) should
+%% in general not be depended upon, since it might be subject to
+%% change without notice.</p>
+%%
+%% <p>The function <code>subtrees/1</code> and the constructor functions
+%% <code>make_tree/2</code> and <code>update_tree/2</code> can be a
+%% great help if one wants to traverse a syntax tree, visiting all its
+%% subtrees, but treat nodes of the tree in a uniform way in most or all
+%% cases. Using these functions makes this simple, and also assures that
+%% your code is not overly sensitive to extensions of the syntax tree
+%% data type, because any node types not explicitly handled by your code
+%% can be left to a default case.</p>
+%%
+%% <p>For example:
+%% <pre>
+%% postorder(F, Tree) ->
+%% F(case subtrees(Tree) of
+%% [] -> Tree;
+%% List -> update_tree(Tree,
+%% [[postorder(F, Subtree)
+%% || Subtree &lt;- Group]
+%% || Group &lt;- List])
+%% end).
+%% </pre>
+%% maps the function <code>F</code> on <code>Tree</code> and all its
+%% subtrees, doing a post-order traversal of the syntax tree. (Note
+%% the use of <code>update_tree/2</code> to preserve annotations.) For
+%% a simple function like:
+%% <pre>
+%% f(Node) ->
+%% case type(Node) of
+%% atom -> atom("a_" ++ atom_name(Node));
+%% _ -> Node
+%% end.
+%% </pre>
+%% the call <code>postorder(fun f/1, Tree)</code> will yield a new
+%% representation of <code>Tree</code> in which all atom names have
+%% been extended with the prefix "a_", but nothing else (including
+%% annotations) has been changed.</p>
+%%
+%% @see is_leaf/1
+%% @see make_tree/2
+%% @see update_tree/2
+
+subtrees(T) ->
+ case is_leaf(T) of
+ true ->
+ [];
+ false ->
+ case type(T) of
+ values ->
+ [values_es(T)];
+ binary ->
+ [binary_segments(T)];
+ bitstr ->
+ [[bitstr_val(T)], [bitstr_size(T)],
+ [bitstr_unit(T)], [bitstr_type(T)],
+ [bitstr_flags(T)]];
+ cons ->
+ [[cons_hd(T)], [cons_tl(T)]];
+ tuple ->
+ [tuple_es(T)];
+ 'let' ->
+ [let_vars(T), [let_arg(T)], [let_body(T)]];
+ seq ->
+ [[seq_arg(T)], [seq_body(T)]];
+ apply ->
+ [[apply_op(T)], apply_args(T)];
+ call ->
+ [[call_module(T)], [call_name(T)],
+ call_args(T)];
+ primop ->
+ [[primop_name(T)], primop_args(T)];
+ 'case' ->
+ [[case_arg(T)], case_clauses(T)];
+ clause ->
+ [clause_pats(T), [clause_guard(T)],
+ [clause_body(T)]];
+ alias ->
+ [[alias_var(T)], [alias_pat(T)]];
+ 'fun' ->
+ [fun_vars(T), [fun_body(T)]];
+ 'receive' ->
+ [receive_clauses(T), [receive_timeout(T)],
+ [receive_action(T)]];
+ 'try' ->
+ [[try_arg(T)], try_vars(T), [try_body(T)],
+ try_evars(T), [try_handler(T)]];
+ 'catch' ->
+ [[catch_body(T)]];
+ letrec ->
+ Es = unfold_tuples(letrec_defs(T)),
+ [Es, [letrec_body(T)]];
+ module ->
+ As = unfold_tuples(module_attrs(T)),
+ Es = unfold_tuples(module_defs(T)),
+ [[module_name(T)], module_exports(T), As, Es]
+ end
+ end.
+
+
+%% @spec update_tree(Old::cerl(), Groups::[[cerl()]]) -> cerl()
+%%
+%% @doc Creates a syntax tree with the given subtrees, and the same
+%% type and annotations as the <code>Old</code> node. This is
+%% equivalent to <code>ann_make_tree(get_ann(Node), type(Node),
+%% Groups)</code>, but potentially more efficient.
+%%
+%% @see update_tree/3
+%% @see ann_make_tree/3
+%% @see get_ann/1
+%% @see type/1
+
+update_tree(Node, Gs) ->
+ ann_make_tree(get_ann(Node), type(Node), Gs).
+
+
+%% @spec update_tree(Old::cerl(), Type::atom(), Groups::[[cerl()]]) ->
+%% cerl()
+%%
+%% @doc Creates a syntax tree with the given type and subtrees, and
+%% the same annotations as the <code>Old</code> node. This is
+%% equivalent to <code>ann_make_tree(get_ann(Node), Type,
+%% Groups)</code>, but potentially more efficient.
+%%
+%% @see update_tree/2
+%% @see ann_make_tree/3
+%% @see get_ann/1
+
+update_tree(Node, Type, Gs) ->
+ ann_make_tree(get_ann(Node), Type, Gs).
+
+
+%% @spec make_tree(Type::atom(), Groups::[[cerl()]]) -> cerl()
+%%
+%% @doc Creates a syntax tree with the given type and subtrees.
+%% <code>Type</code> must be a node type name
+%% (cf. <code>type/1</code>) that does not denote a leaf node type
+%% (cf. <code>is_leaf/1</code>). <code>Groups</code> must be a
+%% <em>nonempty</em> list of groups of syntax trees, representing the
+%% subtrees of a node of the given type, in left-to-right order as
+%% they would occur in the printed program text, grouped by category
+%% as done by <code>subtrees/1</code>.
+%%
+%% <p>The result of <code>ann_make_tree(get_ann(Node), type(Node),
+%% subtrees(Node))</code> (cf. <code>update_tree/2</code>) represents
+%% the same source code text as the original <code>Node</code>,
+%% assuming that <code>subtrees(Node)</code> yields a nonempty
+%% list. However, it does not necessarily have the exact same data
+%% representation as <code>Node</code>.</p>
+%%
+%% @see ann_make_tree/3
+%% @see type/1
+%% @see is_leaf/1
+%% @see subtrees/1
+%% @see update_tree/2
+
+make_tree(Type, Gs) ->
+ ann_make_tree([], Type, Gs).
+
+
+%% @spec ann_make_tree(As::[term()], Type::atom(),
+%% Groups::[[cerl()]]) -> cerl()
+%%
+%% @doc Creates a syntax tree with the given annotations, type and
+%% subtrees. See <code>make_tree/2</code> for details.
+%%
+%% @see make_tree/2
+
+ann_make_tree(As, values, [Es]) -> ann_c_values(As, Es);
+ann_make_tree(As, binary, [Ss]) -> ann_c_binary(As, Ss);
+ann_make_tree(As, bitstr, [[V],[S],[U],[T],[Fs]]) ->
+ ann_c_bitstr(As, V, S, U, T, Fs);
+ann_make_tree(As, cons, [[H], [T]]) -> ann_c_cons(As, H, T);
+ann_make_tree(As, tuple, [Es]) -> ann_c_tuple(As, Es);
+ann_make_tree(As, 'let', [Vs, [A], [B]]) -> ann_c_let(As, Vs, A, B);
+ann_make_tree(As, seq, [[A], [B]]) -> ann_c_seq(As, A, B);
+ann_make_tree(As, apply, [[Op], Es]) -> ann_c_apply(As, Op, Es);
+ann_make_tree(As, call, [[M], [N], Es]) -> ann_c_call(As, M, N, Es);
+ann_make_tree(As, primop, [[N], Es]) -> ann_c_primop(As, N, Es);
+ann_make_tree(As, 'case', [[A], Cs]) -> ann_c_case(As, A, Cs);
+ann_make_tree(As, clause, [Ps, [G], [B]]) -> ann_c_clause(As, Ps, G, B);
+ann_make_tree(As, alias, [[V], [P]]) -> ann_c_alias(As, V, P);
+ann_make_tree(As, 'fun', [Vs, [B]]) -> ann_c_fun(As, Vs, B);
+ann_make_tree(As, 'receive', [Cs, [T], [A]]) ->
+ ann_c_receive(As, Cs, T, A);
+ann_make_tree(As, 'try', [[E], Vs, [B], Evs, [H]]) ->
+ ann_c_try(As, E, Vs, B, Evs, H);
+ann_make_tree(As, 'catch', [[B]]) -> ann_c_catch(As, B);
+ann_make_tree(As, letrec, [Es, [B]]) ->
+ ann_c_letrec(As, fold_tuples(Es), B);
+ann_make_tree(As, module, [[N], Xs, Es, Ds]) ->
+ ann_c_module(As, N, Xs, fold_tuples(Es), fold_tuples(Ds)).
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec meta(Tree::cerl()) -> cerl()
+%%
+%% @doc Creates a meta-representation of a syntax tree. The result
+%% represents an Erlang expression "<code><em>MetaTree</em></code>"
+%% which, if evaluated, will yield a new syntax tree representing the
+%% same source code text as <code>Tree</code> (although the actual
+%% data representation may be different). The expression represented
+%% by <code>MetaTree</code> is <em>implementation independent</em>
+%% with regard to the data structures used by the abstract syntax tree
+%% implementation.
+%%
+%% <p>Any node in <code>Tree</code> whose node type is
+%% <code>var</code> (cf. <code>type/1</code>), and whose list of
+%% annotations (cf. <code>get_ann/1</code>) contains the atom
+%% <code>meta_var</code>, will remain unchanged in the resulting tree,
+%% except that exactly one occurrence of <code>meta_var</code> is
+%% removed from its annotation list.</p>
+%%
+%% <p>The main use of the function <code>meta/1</code> is to transform
+%% a data structure <code>Tree</code>, which represents a piece of
+%% program code, into a form that is <em>representation independent
+%% when printed</em>. E.g., suppose <code>Tree</code> represents a
+%% variable named "V". Then (assuming a function <code>print/1</code>
+%% for printing syntax trees), evaluating
+%% <code>print(abstract(Tree))</code> - simply using
+%% <code>abstract/1</code> to map the actual data structure onto a
+%% syntax tree representation - would output a string that might look
+%% something like "<code>{var, ..., 'V'}</code>", which is obviously
+%% dependent on the implementation of the abstract syntax trees. This
+%% could e.g. be useful for caching a syntax tree in a file. However,
+%% in some situations like in a program generator generator (with two
+%% "generator"), it may be unacceptable. Using
+%% <code>print(meta(Tree))</code> instead would output a
+%% <em>representation independent</em> syntax tree generating
+%% expression; in the above case, something like
+%% "<code>cerl:c_var('V')</code>".</p>
+%%
+%% <p>The implementation tries to generate compact code with respect
+%% to literals and lists.</p>
+%%
+%% @see abstract/1
+%% @see type/1
+%% @see get_ann/1
+
+meta(Node) ->
+ %% First of all we check for metavariables:
+ case type(Node) of
+ var ->
+ case lists:member(meta_var, get_ann(Node)) of
+ false ->
+ meta_0(var, Node);
+ true ->
+ %% A meta-variable: remove the first found
+ %% 'meta_var' annotation, but otherwise leave
+ %% the node unchanged.
+ set_ann(Node, lists:delete(meta_var, get_ann(Node)))
+ end;
+ Type ->
+ meta_0(Type, Node)
+ end.
+
+meta_0(Type, Node) ->
+ case get_ann(Node) of
+ [] ->
+ meta_1(Type, Node);
+ As ->
+ meta_call(set_ann, [meta_1(Type, Node), abstract(As)])
+ end.
+
+meta_1(literal, Node) ->
+ %% We handle atomic literals separately, to get a bit
+ %% more compact code. For the rest, we use 'abstract'.
+ case concrete(Node) of
+ V when atom(V) ->
+ meta_call(c_atom, [Node]);
+ V when integer(V) ->
+ meta_call(c_int, [Node]);
+ V when float(V) ->
+ meta_call(c_float, [Node]);
+ [] ->
+ meta_call(c_nil, []);
+ _ ->
+ meta_call(abstract, [Node])
+ end;
+meta_1(var, Node) ->
+ %% A normal variable or function name.
+ meta_call(c_var, [abstract(var_name(Node))]);
+meta_1(values, Node) ->
+ meta_call(c_values,
+ [make_list(meta_list(values_es(Node)))]);
+meta_1(binary, Node) ->
+ meta_call(c_binary,
+ [make_list(meta_list(binary_segments(Node)))]);
+meta_1(bitstr, Node) ->
+ meta_call(c_bitstr,
+ [meta(bitstr_val(Node)),
+ meta(bitstr_size(Node)),
+ meta(bitstr_unit(Node)),
+ meta(bitstr_type(Node)),
+ meta(bitstr_flags(Node))]);
+meta_1(cons, Node) ->
+ %% The list is split up if some sublist has annotatations. If
+ %% we get exactly one element, we generate a 'c_cons' call
+ %% instead of 'make_list' to reconstruct the node.
+ case split_list(Node) of
+ {[H], none} ->
+ meta_call(c_cons, [meta(H), meta(c_nil())]);
+ {[H], Node1} ->
+ meta_call(c_cons, [meta(H), meta(Node1)]);
+ {L, none} ->
+ meta_call(make_list, [make_list(meta_list(L))]);
+ {L, Node1} ->
+ meta_call(make_list,
+ [make_list(meta_list(L)), meta(Node1)])
+ end;
+meta_1(tuple, Node) ->
+ meta_call(c_tuple,
+ [make_list(meta_list(tuple_es(Node)))]);
+meta_1('let', Node) ->
+ meta_call(c_let,
+ [make_list(meta_list(let_vars(Node))),
+ meta(let_arg(Node)), meta(let_body(Node))]);
+meta_1(seq, Node) ->
+ meta_call(c_seq,
+ [meta(seq_arg(Node)), meta(seq_body(Node))]);
+meta_1(apply, Node) ->
+ meta_call(c_apply,
+ [meta(apply_op(Node)),
+ make_list(meta_list(apply_args(Node)))]);
+meta_1(call, Node) ->
+ meta_call(c_call,
+ [meta(call_module(Node)), meta(call_name(Node)),
+ make_list(meta_list(call_args(Node)))]);
+meta_1(primop, Node) ->
+ meta_call(c_primop,
+ [meta(primop_name(Node)),
+ make_list(meta_list(primop_args(Node)))]);
+meta_1('case', Node) ->
+ meta_call(c_case,
+ [meta(case_arg(Node)),
+ make_list(meta_list(case_clauses(Node)))]);
+meta_1(clause, Node) ->
+ meta_call(c_clause,
+ [make_list(meta_list(clause_pats(Node))),
+ meta(clause_guard(Node)),
+ meta(clause_body(Node))]);
+meta_1(alias, Node) ->
+ meta_call(c_alias,
+ [meta(alias_var(Node)), meta(alias_pat(Node))]);
+meta_1('fun', Node) ->
+ meta_call(c_fun,
+ [make_list(meta_list(fun_vars(Node))),
+ meta(fun_body(Node))]);
+meta_1('receive', Node) ->
+ meta_call(c_receive,
+ [make_list(meta_list(receive_clauses(Node))),
+ meta(receive_timeout(Node)),
+ meta(receive_action(Node))]);
+meta_1('try', Node) ->
+ meta_call(c_try,
+ [meta(try_arg(Node)),
+ make_list(meta_list(try_vars(Node))),
+ meta(try_body(Node)),
+ make_list(meta_list(try_evars(Node))),
+ meta(try_handler(Node))]);
+meta_1('catch', Node) ->
+ meta_call(c_catch, [meta(catch_body(Node))]);
+meta_1(letrec, Node) ->
+ meta_call(c_letrec,
+ [make_list([c_tuple([meta(N), meta(F)])
+ || {N, F} <- letrec_defs(Node)]),
+ meta(letrec_body(Node))]);
+meta_1(module, Node) ->
+ meta_call(c_module,
+ [meta(module_name(Node)),
+ make_list(meta_list(module_exports(Node))),
+ make_list([c_tuple([meta(A), meta(V)])
+ || {A, V} <- module_attrs(Node)]),
+ make_list([c_tuple([meta(N), meta(F)])
+ || {N, F} <- module_defs(Node)])]).
+
+meta_call(F, As) ->
+ c_call(c_atom(?MODULE), c_atom(F), As).
+
+meta_list([T | Ts]) ->
+ [meta(T) | meta_list(Ts)];
+meta_list([]) ->
+ [].
+
+split_list(Node) ->
+ split_list(set_ann(Node, []), []).
+
+split_list(Node, L) ->
+ A = get_ann(Node),
+ case type(Node) of
+ cons when A == [] ->
+ split_list(cons_tl(Node), [cons_hd(Node) | L]);
+ nil when A == [] ->
+ {lists:reverse(L), none};
+ _ ->
+ {lists:reverse(L), Node}
+ end.
+
+
+%% ---------------------------------------------------------------------
+
+%% General utilities
+
+is_lit_list([#literal{} | Es]) ->
+ is_lit_list(Es);
+is_lit_list([_ | _]) ->
+ false;
+is_lit_list([]) ->
+ true.
+
+lit_list_vals([#literal{val = V} | Es]) ->
+ [V | lit_list_vals(Es)];
+lit_list_vals([]) ->
+ [].
+
+make_lit_list([V | Vs]) ->
+ [#literal{val = V} | make_lit_list(Vs)];
+make_lit_list([]) ->
+ [].
+
+%% The following tests are the same as done by 'io_lib:char_list' and
+%% 'io_lib:printable_list', respectively, but for a single character.
+
+is_char_value(V) when V >= $\000, V =< $\377 -> true;
+is_char_value(_) -> false.
+
+is_print_char_value(V) when V >= $\040, V =< $\176 -> true;
+is_print_char_value(V) when V >= $\240, V =< $\377 -> true;
+is_print_char_value(V) when V =:= $\b -> true;
+is_print_char_value(V) when V =:= $\d -> true;
+is_print_char_value(V) when V =:= $\e -> true;
+is_print_char_value(V) when V =:= $\f -> true;
+is_print_char_value(V) when V =:= $\n -> true;
+is_print_char_value(V) when V =:= $\r -> true;
+is_print_char_value(V) when V =:= $\s -> true;
+is_print_char_value(V) when V =:= $\t -> true;
+is_print_char_value(V) when V =:= $\v -> true;
+is_print_char_value(V) when V =:= $\" -> true;
+is_print_char_value(V) when V =:= $\' -> true;
+is_print_char_value(V) when V =:= $\\ -> true;
+is_print_char_value(_) -> false.
+
+is_char_list([V | Vs]) when integer(V) ->
+ case is_char_value(V) of
+ true ->
+ is_char_list(Vs);
+ false ->
+ false
+ end;
+is_char_list([]) ->
+ true;
+is_char_list(_) ->
+ false.
+
+is_print_char_list([V | Vs]) when integer(V) ->
+ case is_print_char_value(V) of
+ true ->
+ is_print_char_list(Vs);
+ false ->
+ false
+ end;
+is_print_char_list([]) ->
+ true;
+is_print_char_list(_) ->
+ false.
+
+unfold_tuples([{X, Y} | Ps]) ->
+ [X, Y | unfold_tuples(Ps)];
+unfold_tuples([]) ->
+ [].
+
+fold_tuples([X, Y | Es]) ->
+ [{X, Y} | fold_tuples(Es)];
+fold_tuples([]) ->
+ [].
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl_clauses.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl_clauses.erl
new file mode 100644
index 0000000000..16e4b37a10
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl_clauses.erl
@@ -0,0 +1,409 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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 Richard Carlsson.
+%% Copyright (C) 1999-2002 Richard Carlsson.
+%% Portions created by Ericsson are Copyright 2001, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%%
+%% $Id: cerl_clauses.erl,v 1.2 2009/09/17 09:46:19 kostis Exp $
+
+%% @doc Utility functions for Core Erlang case/receive clauses.
+%%
+%% <p>Syntax trees are defined in the module <a
+%% href=""><code>cerl</code></a>.</p>
+%%
+%% @type cerl() = cerl:cerl()
+
+-module(cerl_clauses).
+
+-export([any_catchall/1, eval_guard/1, is_catchall/1, match/2,
+ match_list/2, reduce/1, reduce/2]).
+
+-import(cerl, [alias_pat/1, alias_var/1, data_arity/1, data_es/1,
+ data_type/1, clause_guard/1, clause_pats/1, concrete/1,
+ is_data/1, is_c_var/1, let_body/1, letrec_body/1,
+ seq_body/1, try_arg/1, type/1, values_es/1]).
+
+-import(lists, [reverse/1]).
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec is_catchall(Clause::cerl()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if an abstract clause is a
+%% catch-all, otherwise <code>false</code>. A clause is a catch-all if
+%% all its patterns are variables, and its guard expression always
+%% evaluates to <code>true</code>; cf. <code>eval_guard/1</code>.
+%%
+%% <p>Note: <code>Clause</code> must have type
+%% <code>clause</code>.</p>
+%%
+%% @see eval_guard/1
+%% @see any_catchall/1
+
+is_catchall(C) ->
+ case all_vars(clause_pats(C)) of
+ true ->
+ case eval_guard(clause_guard(C)) of
+ {value, true} ->
+ true;
+ _ ->
+ false
+ end;
+ false ->
+ false
+ end.
+
+all_vars([C | Cs]) ->
+ case is_c_var(C) of
+ true ->
+ all_vars(Cs);
+ false ->
+ false
+ end;
+all_vars([]) ->
+ true.
+
+
+%% @spec any_catchall(Clauses::[cerl()]) -> boolean()
+%%
+%% @doc Returns <code>true</code> if any of the abstract clauses in
+%% the list is a catch-all, otherwise <code>false</code>. See
+%% <code>is_catchall/1</code> for details.
+%%
+%% <p>Note: each node in <code>Clauses</code> must have type
+%% <code>clause</code>.</p>
+%%
+%% @see is_catchall/1
+
+any_catchall([C | Cs]) ->
+ case is_catchall(C) of
+ true ->
+ true;
+ false ->
+ any_catchall(Cs)
+ end;
+any_catchall([]) ->
+ false.
+
+
+%% @spec eval_guard(Expr::cerl()) -> none | {value, term()}
+%%
+%% @doc Tries to reduce a guard expression to a single constant value,
+%% if possible. The returned value is <code>{value, Term}</code> if the
+%% guard expression <code>Expr</code> always yields the constant value
+%% <code>Term</code>, and is otherwise <code>none</code>.
+%%
+%% <p>Note that although guard expressions should only yield boolean
+%% values, this function does not guarantee that <code>Term</code> is
+%% either <code>true</code> or <code>false</code>. Also note that only
+%% simple constructs like let-expressions are examined recursively;
+%% general constant folding is not performed.</p>
+%%
+%% @see is_catchall/1
+
+%% This function could possibly be improved further, but constant
+%% folding should in general be performed elsewhere.
+
+eval_guard(E) ->
+ case type(E) of
+ literal ->
+ {value, concrete(E)};
+ values ->
+ case values_es(E) of
+ [E1] ->
+ eval_guard(E1);
+ _ ->
+ none
+ end;
+ 'try' ->
+ eval_guard(try_arg(E));
+ seq ->
+ eval_guard(seq_body(E));
+ 'let' ->
+ eval_guard(let_body(E));
+ 'letrec' ->
+ eval_guard(letrec_body(E));
+ _ ->
+ none
+ end.
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec reduce(Clauses) -> {true, {Clauses, Bindings}}
+%% | {false, Clauses}
+%%
+%% @equiv reduce(Cs, [])
+
+reduce(Cs) ->
+ reduce(Cs, []).
+
+%% @spec reduce(Clauses::[Clause], Exprs::[Expr]) ->
+%% {true, {Clause, Bindings}}
+%% | {false, [Clause]}
+%%
+%% Clause = cerl()
+%% Expr = any | cerl()
+%% Bindings = [{cerl(), cerl()}]
+%%
+%% @doc Selects a single clause, if possible, or otherwise reduces the
+%% list of selectable clauses. The input is a list <code>Clauses</code>
+%% of abstract clauses (i.e., syntax trees of type <code>clause</code>),
+%% and a list of switch expressions <code>Exprs</code>. The function
+%% tries to uniquely select a single clause or discard unselectable
+%% clauses, with respect to the switch expressions. All abstract clauses
+%% in the list must have the same number of patterns. If
+%% <code>Exprs</code> is not the empty list, it must have the same
+%% length as the number of patterns in each clause; see
+%% <code>match_list/2</code> for details.
+%%
+%% <p>A clause can only be selected if its guard expression always
+%% yields the atom <code>true</code>, and a clause whose guard
+%% expression always yields the atom <code>false</code> can never be
+%% selected. Other guard expressions are considered to have unknown
+%% value; cf. <code>eval_guard/1</code>.</p>
+%%
+%% <p>If a particular clause can be selected, the function returns
+%% <code>{true, {Clause, Bindings}}</code>, where <code>Clause</code> is
+%% the selected clause and <code>Bindings</code> is a list of pairs
+%% <code>{Var, SubExpr}</code> associating the variables occurring in
+%% the patterns of <code>Clause</code> with the corresponding
+%% subexpressions in <code>Exprs</code>. The list of bindings is given
+%% in innermost-first order; see the <code>match/2</code> function for
+%% details.</p>
+%%
+%% <p>If no clause could be definitely selected, the function returns
+%% <code>{false, NewClauses}</code>, where <code>NewClauses</code> is
+%% the list of entries in <code>Clauses</code> that remain after
+%% eliminating unselectable clauses, preserving the relative order.</p>
+%%
+%% @see eval_guard/1
+%% @see match/2
+%% @see match_list/2
+
+reduce(Cs, Es) ->
+ reduce(Cs, Es, []).
+
+reduce([C | Cs], Es, Cs1) ->
+ Ps = clause_pats(C),
+ case match_list(Ps, Es) of
+ none ->
+ %% Here, we know that the current clause cannot possibly be
+ %% selected, so we drop it and visit the rest.
+ reduce(Cs, Es, Cs1);
+ {false, _} ->
+ %% We are not sure if this clause might be selected, so we
+ %% save it and visit the rest.
+ reduce(Cs, Es, [C | Cs1]);
+ {true, Bs} ->
+ case eval_guard(clause_guard(C)) of
+ {value, true} when Cs1 == [] ->
+ %% We have a definite match - we return the residual
+ %% expression and signal that a selection has been
+ %% made. All other clauses are dropped.
+ {true, {C, Bs}};
+ {value, true} ->
+ %% Unless one of the previous clauses is selected,
+ %% this clause will definitely be, so we can drop
+ %% the rest.
+ {false, reverse([C | Cs1])};
+ {value, false} ->
+ %% This clause can never be selected, since its
+ %% guard is never 'true', so we drop it.
+ reduce(Cs, Es, Cs1);
+ _ ->
+ %% We are not sure if this clause might be selected
+ %% (or might even cause a crash), so we save it and
+ %% visit the rest.
+ reduce(Cs, Es, [C | Cs1])
+ end
+ end;
+reduce([], _, Cs) ->
+ %% All clauses visited, without a complete match. Signal "not
+ %% reduced" and return the saved clauses, in the correct order.
+ {false, reverse(Cs)}.
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec match(Pattern::cerl(), Expr) ->
+%% none | {true, Bindings} | {false, Bindings}
+%%
+%% Expr = any | cerl()
+%% Bindings = [{cerl(), Expr}]
+%%
+%% @doc Matches a pattern against an expression. The returned value is
+%% <code>none</code> if a match is impossible, <code>{true,
+%% Bindings}</code> if <code>Pattern</code> definitely matches
+%% <code>Expr</code>, and <code>{false, Bindings}</code> if a match is
+%% not definite, but cannot be excluded. <code>Bindings</code> is then
+%% a list of pairs <code>{Var, SubExpr}</code>, associating each
+%% variable in the pattern with either the corresponding subexpression
+%% of <code>Expr</code>, or with the atom <code>any</code> if no
+%% matching subexpression exists. (Recall that variables may not be
+%% repeated in a Core Erlang pattern.) The list of bindings is given
+%% in innermost-first order; this should only be of interest if
+%% <code>Pattern</code> contains one or more alias patterns. If the
+%% returned value is <code>{true, []}</code>, it implies that the
+%% pattern and the expression are syntactically identical.
+%%
+%% <p>Instead of a syntax tree, the atom <code>any</code> can be
+%% passed for <code>Expr</code> (or, more generally, be used for any
+%% subtree of <code>Expr</code>, in as much the abstract syntax tree
+%% implementation allows it); this means that it cannot be decided
+%% whether the pattern will match or not, and the corresponding
+%% variable bindings will all map to <code>any</code>. The typical use
+%% is for producing bindings for <code>receive</code> clauses.</p>
+%%
+%% <p>Note: Binary-syntax patterns are never structurally matched
+%% against binary-syntax expressions by this function.</p>
+%%
+%% <p>Examples:
+%% <ul>
+%% <li>Matching a pattern "<code>{X, Y}</code>" against the
+%% expression "<code>{foo, f(Z)}</code>" yields <code>{true,
+%% Bindings}</code> where <code>Bindings</code> associates
+%% "<code>X</code>" with the subtree "<code>foo</code>" and
+%% "<code>Y</code>" with the subtree "<code>f(Z)</code>".</li>
+%%
+%% <li>Matching pattern "<code>{X, {bar, Y}}</code>" against
+%% expression "<code>{foo, f(Z)}</code>" yields <code>{false,
+%% Bindings}</code> where <code>Bindings</code> associates
+%% "<code>X</code>" with the subtree "<code>foo</code>" and
+%% "<code>Y</code>" with <code>any</code> (because it is not known
+%% if "<code>{foo, Y}</code>" might match the run-time value of
+%% "<code>f(Z)</code>" or not).</li>
+%%
+%% <li>Matching pattern "<code>{foo, bar}</code>" against expression
+%% "<code>{foo, f()}</code>" yields <code>{false, []}</code>,
+%% telling us that there might be a match, but we cannot deduce any
+%% bindings.</li>
+%%
+%% <li>Matching <code>{foo, X = {bar, Y}}</code> against expression
+%% "<code>{foo, {bar, baz}}</code>" yields <code>{true,
+%% Bindings}</code> where <code>Bindings</code> associates
+%% "<code>Y</code>" with "<code>baz</code>", and "<code>X</code>"
+%% with "<code>{bar, baz}</code>".</li>
+%%
+%% <li>Matching a pattern "<code>{X, Y}</code>" against
+%% <code>any</code> yields <code>{false, Bindings}</code> where
+%% <code>Bindings</code> associates both "<code>X</code>" and
+%% "<code>Y</code>" with <code>any</code>.</li>
+%% </ul></p>
+
+match(P, E) ->
+ match(P, E, []).
+
+match(P, E, Bs) ->
+ case type(P) of
+ var ->
+ %% Variables always match, since they cannot have repeated
+ %% occurrences in a pattern.
+ {true, [{P, E} | Bs]};
+ alias ->
+ %% All variables in P1 will be listed before the alias
+ %% variable in the result.
+ match(alias_pat(P), E, [{alias_var(P), E} | Bs]);
+ binary ->
+ %% The most we can do is to say "definitely no match" if a
+ %% binary pattern is matched against non-binary data.
+ if E == any ->
+ {false, Bs};
+ true ->
+ case is_data(E) of
+ true ->
+ none;
+ false ->
+ {false, Bs}
+ end
+ end;
+ _ ->
+ match_1(P, E, Bs)
+ end.
+
+match_1(P, E, Bs) ->
+ case is_data(P) of
+ true when E == any ->
+ %% If we don't know the structure of the value of E at this
+ %% point, we just match the subpatterns against 'any', and
+ %% make sure the result is a "maybe".
+ Ps = data_es(P),
+ Es = lists:duplicate(length(Ps), any),
+ case match_list(Ps, Es, Bs) of
+ {_, Bs1} ->
+ {false, Bs1};
+ none ->
+ none
+ end;
+ true ->
+ %% Test if the expression represents a constructor
+ case is_data(E) of
+ true ->
+ T1 = {data_type(E), data_arity(E)},
+ T2 = {data_type(P), data_arity(P)},
+ %% Note that we must test for exact equality.
+ if T1 =:= T2 ->
+ match_list(data_es(P), data_es(E), Bs);
+ true ->
+ none
+ end;
+ false ->
+ %% We don't know the run-time structure of E, and P
+ %% is not a variable or an alias pattern, so we
+ %% match against 'any' instead.
+ match_1(P, any, Bs)
+ end;
+ false ->
+ %% Strange pattern - give up, but don't say "no match".
+ {false, Bs}
+ end.
+
+
+%% @spec match_list(Patterns::[cerl()], Exprs::[Expr]) ->
+%% none | {true, Bindings} | {false, Bindings}
+%%
+%% Expr = any | cerl()
+%% Bindings = [{cerl(), cerl()}]
+%%
+%% @doc Like <code>match/2</code>, but matching a sequence of patterns
+%% against a sequence of expressions. Passing an empty list for
+%% <code>Exprs</code> is equivalent to passing a list of
+%% <code>any</code> atoms of the same length as <code>Patterns</code>.
+%%
+%% @see match/2
+
+match_list([], []) ->
+ {true, []}; % no patterns always match
+match_list(Ps, []) ->
+ match_list(Ps, lists:duplicate(length(Ps), any), []);
+match_list(Ps, Es) ->
+ match_list(Ps, Es, []).
+
+match_list([P | Ps], [E | Es], Bs) ->
+ case match(P, E, Bs) of
+ {true, Bs1} ->
+ match_list(Ps, Es, Bs1);
+ {false, Bs1} ->
+ %% Make sure "maybe" is preserved
+ case match_list(Ps, Es, Bs1) of
+ {_, Bs2} ->
+ {false, Bs2};
+ none ->
+ none
+ end;
+ none ->
+ none
+ end;
+match_list([], [], Bs) ->
+ {true, Bs}.
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl_inline.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl_inline.erl
new file mode 100644
index 0000000000..cd332279d1
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl_inline.erl
@@ -0,0 +1,2762 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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 Richard Carlsson.
+%% Copyright (C) 1999-2002 Richard Carlsson.
+%% Portions created by Ericsson are Copyright 2001, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%%
+%% $Id: cerl_inline.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
+%%
+%% Core Erlang inliner.
+
+%% =====================================================================
+%%
+%% This is an implementation of the algorithm by Waddell and Dybvig
+%% ("Fast and Effective Procedure Inlining", International Static
+%% Analysis Symposium 1997), adapted to the Core Erlang language.
+%%
+%% Instead of always renaming variables and function variables, this
+%% implementation uses the "no-shadowing strategy" of Peyton Jones and
+%% Marlow ("Secrets of the Glasgow Haskell Compiler Inliner", 1999).
+%%
+%% =====================================================================
+
+%% TODO: inline single-source-reference operands without size limit.
+
+-module(cerl_inline).
+
+-export([core_transform/2, transform/1, transform/2]).
+
+-import(cerl, [abstract/1, alias_pat/1, alias_var/1, apply_args/1,
+ apply_op/1, atom_name/1, atom_val/1, bitstr_val/1,
+ bitstr_size/1, bitstr_unit/1, bitstr_type/1,
+ bitstr_flags/1, binary_segments/1, update_c_alias/3,
+ update_c_apply/3, update_c_binary/2, update_c_bitstr/6,
+ update_c_call/4, update_c_case/3, update_c_catch/2,
+ update_c_clause/4, c_fun/2, c_int/1, c_let/3,
+ update_c_let/4, update_c_letrec/3, update_c_module/5,
+ update_c_primop/3, update_c_receive/4, update_c_seq/3,
+ c_seq/2, update_c_try/6, c_tuple/1, update_c_values/2,
+ c_values/1, c_var/1, call_args/1, call_module/1,
+ call_name/1, case_arity/1, case_arg/1, case_clauses/1,
+ catch_body/1, clause_body/1, clause_guard/1,
+ clause_pats/1, clause_vars/1, concrete/1, cons_hd/1,
+ cons_tl/1, data_arity/1, data_es/1, data_type/1,
+ fun_body/1, fun_vars/1, get_ann/1, int_val/1,
+ is_c_atom/1, is_c_cons/1, is_c_fun/1, is_c_int/1,
+ is_c_list/1, is_c_seq/1, is_c_tuple/1, is_c_var/1,
+ is_data/1, is_literal/1, is_literal_term/1, let_arg/1,
+ let_body/1, let_vars/1, letrec_body/1, letrec_defs/1,
+ list_length/1, list_elements/1, update_data/3,
+ make_list/1, make_data_skel/2, module_attrs/1,
+ module_defs/1, module_exports/1, module_name/1,
+ primop_args/1, primop_name/1, receive_action/1,
+ receive_clauses/1, receive_timeout/1, seq_arg/1,
+ seq_body/1, set_ann/2, try_arg/1, try_body/1, try_vars/1,
+ try_evars/1, try_handler/1, tuple_es/1, tuple_arity/1,
+ type/1, values_es/1, var_name/1]).
+
+-import(lists, [foldl/3, foldr/3, mapfoldl/3, reverse/1]).
+
+%%
+%% Constants
+%%
+
+debug_runtime() -> false.
+debug_counters() -> false.
+
+%% Normal execution times for inlining are between 0.1 and 0.3 seconds
+%% (on the author's current equipment). The default effort limit of 150
+%% is high enough that most normal programs never hit the limit even
+%% once, and for difficult programs, it generally keeps the execution
+%% times below 2-5 seconds. Using an effort counter of 1000 will thus
+%% have no further effect on most programs, but some programs may take
+%% as much as 10 seconds or more. Effort counts larger than 2500 have
+%% never been observed even on very ill-conditioned programs.
+%%
+%% Size limits between 6 and 18 tend to actually shrink the code,
+%% because of the simplifications made possible by inlining. A limit of
+%% 16 seems to be optimal for this purpose, often shrinking the
+%% executable code by up to 10%. Size limits between 18 and 30 generally
+%% give the same code size as if no inlining was done (i.e., code
+%% duplication balances out the simplifications at these levels). A size
+%% limit between 1 and 5 tends to inline small functions and propagate
+%% constants, but does not cause much simplifications do be done, so the
+%% net effect will be a slight increase in code size. For size limits
+%% above 30, the executable code size tends to increase with about 10%
+%% per 100 units, with some variations depending on the sizes of
+%% functions in the source code.
+%%
+%% Typically, about 90% of the maximum speedup achievable is already
+%% reached using a size limit of 30, and 98% is reached at limits around
+%% 100-150; there is rarely any point in letting the code size increase
+%% by more than 10-15%. If too large functions are inlined, cache
+%% effects will slow the program down.
+
+default_effort() -> 150.
+default_size() -> 24.
+
+%% Base costs/weights for different kinds of expressions. If these are
+%% modified, the size limits above may have to be adjusted.
+
+weight(var) -> 0; % We count no cost for variable accesses.
+weight(values) -> 0; % Value aggregates have no cost in themselves.
+weight(literal) -> 1; % We assume efficient handling of constants.
+weight(data) -> 1; % Base cost; add 1 per element.
+weight(element) -> 1; % Cost of storing/fetching an element.
+weight(argument) -> 1; % Cost of passing a function argument.
+weight('fun') -> 6; % Base cost + average number of free vars.
+weight('let') -> 0; % Count no cost for let-bindings.
+weight(letrec) -> 0; % Like a let-binding.
+weight('case') -> 0; % Case switches have no base cost.
+weight(clause) -> 1; % Count one jump at the end of each clause body.
+weight('receive') -> 9; % Initialization/cleanup cost.
+weight('try') -> 1; % Assume efficient implementation.
+weight('catch') -> 1; % See `try'.
+weight(apply) -> 3; % Average base cost: call/return.
+weight(call) -> 3; % Assume remote-calls as efficient as `apply'.
+weight(primop) -> 2; % Assume more efficient than `apply'.
+weight(binary) -> 4; % Initialisation base cost.
+weight(bitstr) -> 3; % Coding/decoding a value; like a primop.
+weight(module) -> 1. % Like a letrec with a constant body
+
+%% These "reference" structures are used for variables and function
+%% variables. They keep track of the variable name, any bound operand,
+%% and the associated store location.
+
+-record(ref, {name, opnd, loc}).
+
+%% Operand structures contain the operand expression, the renaming and
+%% environment, the state location, and the effort counter at the call
+%% site (cf. `visit').
+
+-record(opnd, {expr, ren, env, loc, effort}).
+
+%% Since expressions are only visited in `effect' context when they are
+%% not bound to a referenced variable, only expressions visited in
+%% 'value' context are cached.
+
+-record(cache, {expr, size}).
+
+%% The context flags for an application structure are kept separate from
+%% the structure itself. Note that the original algorithm had exactly
+%% one operand in each application context structure, while we can have
+%% several, or none.
+
+-record(app, {opnds, ctxt, loc}).
+
+
+%%
+%% Interface functions
+%%
+
+%% Use compile option `{core_transform, inline}' to insert this as a
+%% compilation pass.
+
+core_transform(Code, Opts) ->
+ cerl:to_records(transform(cerl:from_records(Code), Opts)).
+
+transform(Tree) ->
+ transform(Tree, []).
+
+transform(Tree, Opts) ->
+ main(Tree, value, Opts).
+
+main(Tree, Ctxt, Opts) ->
+ %% We spawn a new process to do the work, so we don't have to worry
+ %% about cluttering the process dictionary with debugging info, or
+ %% proper deallocation of ets-tables.
+ Opts1 = Opts ++ [{inline_size, default_size()},
+ {inline_effort, default_effort()}],
+ Reply = self(),
+ Pid = spawn_link(fun () -> start(Reply, Tree, Ctxt, Opts1) end),
+ receive
+ {Pid1, Tree1} when Pid1 == Pid ->
+ Tree1
+ end.
+
+start(Reply, Tree, Ctxt, Opts) ->
+ init_debug(),
+ case debug_runtime() of
+ true ->
+ put(inline_start_time,
+ element(1, erlang:statistics(runtime)));
+ _ ->
+ ok
+ end,
+ Size = max(1, proplists:get_value(inline_size, Opts)),
+ Effort = max(1, proplists:get_value(inline_effort, Opts)),
+ case proplists:get_bool(verbose, Opts) of
+ true ->
+ io:fwrite("Inlining: inline_size=~w inline_effort=~w\n",
+ [Size, Effort]);
+ false ->
+ ok
+ end,
+
+ %% Note that the counters of the new state are passive.
+ S = st__new(Effort, Size),
+
+%%% Initialization is not needed at present. Note that the code in
+%%% `inline_init' is not up-to-date with this module.
+%%% {Tree1, S1} = inline_init:init(Tree, S),
+%%% {Tree2, _S2} = i(Tree1, Ctxt, S1),
+ {Tree2, _S2} = i(Tree, Ctxt, S),
+ report_debug(),
+ Reply ! {self(), Tree2}.
+
+init_debug() ->
+ case debug_counters() of
+ true ->
+ put(counter_effort_triggers, 0),
+ put(counter_effort_max, 0),
+ put(counter_size_triggers, 0),
+ put(counter_size_max, 0);
+ _ ->
+ ok
+ end.
+
+report_debug() ->
+ case debug_runtime() of
+ true ->
+ {Time, _} = erlang:statistics(runtime),
+ report("Total run time for inlining: ~.2.0f s.\n",
+ [(Time - get(inline_start_time))/1000]);
+ _ ->
+ ok
+ end,
+ case debug_counters() of
+ true ->
+ counter_stats();
+ _ ->
+ ok
+ end.
+
+counter_stats() ->
+ T1 = get(counter_effort_triggers),
+ T2 = get(counter_size_triggers),
+ E = get(counter_effort_max),
+ S = get(counter_size_max),
+ M1 = io_lib:fwrite("\tNumber of triggered "
+ "effort counters: ~p.\n", [T1]),
+ M2 = io_lib:fwrite("\tNumber of triggered "
+ "size counters: ~p.\n", [T2]),
+ M3 = io_lib:fwrite("\tLargest active effort counter: ~p.\n",
+ [E]),
+ M4 = io_lib:fwrite("\tLargest active size counter: ~p.\n",
+ [S]),
+ report("Counter statistics:\n~s", [[M1, M2, M3, M4]]).
+
+
+%% =====================================================================
+%% The main inlining function
+%%
+%% i(E :: coreErlang(),
+%% Ctxt :: value | effect | #app{}
+%% Ren :: renaming(),
+%% Env :: environment(),
+%% S :: state())
+%% -> {E', S'}
+%%
+%% Note: It is expected that the input source code ('E') does not
+%% contain free variables. If it does, there is a risk of accidental
+%% name capture, in case a generated "new" variable name happens to be
+%% the same as the name of a variable that is free further below in the
+%% tree; the algorithm only consults the current environment to check if
+%% a name already exists.
+%%
+%% The renaming maps names of source-code variable and function
+%% variables to new names as necessary to avoid clashes, according to
+%% the "no-shadowing" strategy. The environment maps *residual-code*
+%% variables and function variables to operands and global information.
+%% Separating the renaming from the environment, and using the
+%% residual-code variables instead of the source-code variables as its
+%% domain, improves the behaviour of the algorithm when code needs to be
+%% traversed more than once.
+%%
+%% Note that there is no such thing as a `test' context for expressions
+%% in (Core) Erlang (see `i_case' below for details).
+
+i(E, Ctxt, S) ->
+ i(E, Ctxt, ren__identity(), env__empty(), S).
+
+i(E, Ctxt, Ren, Env, S0) ->
+ %% Count one unit of effort on each pass.
+ S = count_effort(1, S0),
+ case is_data(E) of
+ true ->
+ i_data(E, Ctxt, Ren, Env, S);
+ false ->
+ case type(E) of
+ var ->
+ i_var(E, Ctxt, Ren, Env, S);
+ values ->
+ i_values(E, Ctxt, Ren, Env, S);
+ 'fun' ->
+ i_fun(E, Ctxt, Ren, Env, S);
+ seq ->
+ i_seq(E, Ctxt, Ren, Env, S);
+ 'let' ->
+ i_let(E, Ctxt, Ren, Env, S);
+ letrec ->
+ i_letrec(E, Ctxt, Ren, Env, S);
+ 'case' ->
+ i_case(E, Ctxt, Ren, Env, S);
+ 'receive' ->
+ i_receive(E, Ctxt, Ren, Env, S);
+ apply ->
+ i_apply(E, Ctxt, Ren, Env, S);
+ call ->
+ i_call(E, Ctxt, Ren, Env, S);
+ primop ->
+ i_primop(E, Ren, Env, S);
+ 'try' ->
+ i_try(E, Ctxt, Ren, Env, S);
+ 'catch' ->
+ i_catch(E, Ctxt, Ren, Env, S);
+ binary ->
+ i_binary(E, Ren, Env, S);
+ module ->
+ i_module(E, Ctxt, Ren, Env, S)
+ end
+ end.
+
+i_data(E, Ctxt, Ren, Env, S) ->
+ case is_literal(E) of
+ true ->
+ %% This is the `(const c)' case of the original algorithm:
+ %% literal terms which (regardless of size) do not need to
+ %% be constructed dynamically at runtime - boldly assuming
+ %% that the compiler/runtime system can handle this.
+ case Ctxt of
+ effect ->
+ %% Reduce useless constants to a simple value.
+ {void(), count_size(weight(literal), S)};
+ _ ->
+ %% (In Erlang, we cannot set all non-`false'
+ %% constants to `true' in a `test' context, like we
+ %% could do in Lisp or C, so the above is the only
+ %% special case to be handled here.)
+ {E, count_size(weight(literal), S)}
+ end;
+ false ->
+ %% Data constructors are like to calls to safe built-in
+ %% functions, for which we can "decide to inline"
+ %% immediately; there is no need to create operand
+ %% structures. In `effect' context, we can simply make a
+ %% sequence of the argument expressions, also visited in
+ %% `effect' context. In all other cases, the arguments are
+ %% visited for value.
+ case Ctxt of
+ effect ->
+ %% Note that this will count the sizes of the
+ %% subexpressions, even though some or all of them
+ %% might be discarded by the sequencing afterwards.
+ {Es1, S1} = mapfoldl(fun (E, S) ->
+ i(E, effect, Ren, Env,
+ S)
+ end,
+ S, data_es(E)),
+ E1 = foldl(fun (E1, E2) -> make_seq(E1, E2) end,
+ void(), Es1),
+ {E1, S1};
+ _ ->
+ {Es1, S1} = mapfoldl(fun (E, S) ->
+ i(E, value, Ren, Env,
+ S)
+ end,
+ S, data_es(E)),
+ %% The total size/cost is the base cost for a data
+ %% constructor plus the cost for storing each
+ %% element.
+ N = weight(data) + length(Es1) * weight(element),
+ S2 = count_size(N, S1),
+ {update_data(E, data_type(E), Es1), S2}
+ end
+ end.
+
+%% This is the `(ref x)' (variable use) case of the original algorithm.
+%% Note that binding occurrences are always handled in the respective
+%% cases of the binding constructs.
+
+i_var(E, Ctxt, Ren, Env, S) ->
+ case Ctxt of
+ effect ->
+ %% Reduce useless variable references to a simple constant.
+ %% This also avoids useless visiting of bound operands.
+ {void(), count_size(weight(literal), S)};
+ _ ->
+ Name = var_name(E),
+ case env__lookup(ren__map(Name, Ren), Env) of
+ {ok, R} ->
+ case R#ref.opnd of
+ undefined ->
+ %% The variable is not associated with an
+ %% argument expression; just residualize it.
+ residualize_var(R, S);
+ Opnd ->
+ i_var_1(R, Opnd, Ctxt, Env, S)
+ end;
+ error ->
+ %% The variable is unbound. (It has not been
+ %% accidentally captured, however, or it would have
+ %% been in the environment.) We leave it as it is,
+ %% without any warning.
+ {E, count_size(weight(var), S)}
+ end
+ end.
+
+%% This first visits the bound operand and then does copy propagation.
+%% Note that we must first set the "inner-pending" flag, and clear the
+%% flag afterwards.
+
+i_var_1(R, Opnd, Ctxt, Env, S) ->
+ %% If the operand is already "inner-pending", it is residualised.
+ %% (In Lisp/C, if the variable might be assigned to, it should also
+ %% be residualised.)
+ L = Opnd#opnd.loc,
+ case st__test_inner_pending(L, S) of
+ true ->
+ residualize_var(R, S);
+ false ->
+ S1 = st__mark_inner_pending(L, S),
+ case catch {ok, visit(Opnd, S1)} of
+ {ok, {E, S2}} ->
+ %% Note that we pass the current environment and
+ %% context to `copy', but not the current renaming.
+ S3 = st__clear_inner_pending(L, S2),
+ copy(R, Opnd, E, Ctxt, Env, S3);
+ {'EXIT', X} ->
+ exit(X);
+ X ->
+ %% If we use destructive update for the
+ %% `inner-pending' flag, we must make sure to clear
+ %% it also if we make a nonlocal return.
+ st__clear_inner_pending(Opnd#opnd.loc, S1),
+ throw(X)
+ end
+ end.
+
+%% A multiple-value aggregate `<e1, ..., en>'. This is very much like a
+%% tuple data constructor `{e1, ..., en}'; cf. `i_data' for details.
+
+i_values(E, Ctxt, Ren, Env, S) ->
+ case values_es(E) of
+ [E1] ->
+ %% Single-value aggregates can be dropped; they are simply
+ %% notation.
+ i(E1, Ctxt, Ren, Env, S);
+ Es ->
+ %% In `effect' context, we can simply make a sequence of the
+ %% argument expressions, also visited in `effect' context.
+ %% In all other cases, the arguments are visited for value.
+ case Ctxt of
+ effect ->
+ {Es1, S1} =
+ mapfoldl(fun (E, S) ->
+ i(E, effect, Ren, Env, S)
+ end,
+ S, Es),
+ E1 = foldl(fun (E1, E2) ->
+ make_seq(E1, E2)
+ end,
+ void(), Es1),
+ {E1, S1}; % drop annotations on E
+ _ ->
+ {Es1, S1} = mapfoldl(fun (E, S) ->
+ i(E, value, Ren, Env,
+ S)
+ end,
+ S, Es),
+ %% Aggregating values does not write them to memory,
+ %% so we count no extra cost per element.
+ S2 = count_size(weight(values), S1),
+ {update_c_values(E, Es1), S2}
+ end
+ end.
+
+%% A let-expression `let <v1,...,vn> = e0 in e1' is semantically
+%% equivalent to a case-expression `case e0 of <v1,...,vn> when 'true'
+%% -> e1 end'. As a special case, `let <v> = e0 in e1' is also
+%% equivalent to `apply fun (v) -> e0 (e1)'. However, for efficiency,
+%% and in order to allow the handling of `case' clauses to introduce new
+%% let-expressions without entering an infinite rewrite loop, we handle
+%% these directly.
+
+%%% %% Rewriting a `let' to an equivalent expression.
+%%% i_let(E, Ctxt, Ren, Env, S) ->
+%%% case let_vars(E) of
+%%% [V] ->
+%%% E1 = update_c_apply(E, c_fun([V], let_body(E)), [let_arg(E)]),
+%%% i(E1, Ctxt, Ren, Env, S);
+%%% Vs ->
+%%% C = c_clause(Vs, abstract(true), let_body(E)),
+%%% E1 = update_c_case(E, let_arg(E), [C]),
+%%% i(E1, Ctxt, Ren, Env, S)
+%%% end.
+
+i_let(E, Ctxt, Ren, Env, S) ->
+ case let_vars(E) of
+ [V] ->
+ i_let_1(V, E, Ctxt, Ren, Env, S);
+ Vs ->
+ %% Visit the argument expression in `value' context, to
+ %% simplify it as far as possible.
+ {A, S1} = i(let_arg(E), value, Ren, Env, S),
+ case get_components(length(Vs), result(A)) of
+ {true, As} ->
+ %% Note that only the components of the result of
+ %% `A' are passed on; any effects are hoisted.
+ {E1, S2} = i_let_2(Vs, As, E, Ctxt, Ren, Env, S1),
+ {hoist_effects(A, E1), S2};
+ false ->
+ %% We cannot do anything with this `let', since the
+ %% variables cannot be matched against the argument
+ %% components. Just visit the variables for renaming
+ %% and visit the body for value (cf. `i_fun').
+ {_, Ren1, Env1, S2} = bind_locals(Vs, Ren, Env, S1),
+ Vs1 = i_params(Vs, Ren1, Env1),
+ %% The body is always visited for value here.
+ {B, S3} = i(let_body(E), value, Ren1, Env1, S2),
+ S4 = count_size(weight('let'), S3),
+ {update_c_let(E, Vs1, A, B), S4}
+ end
+ end.
+
+%% Single-variable `let' binding.
+
+i_let_1(V, E, Ctxt, Ren, Env, S) ->
+ %% Make an operand structure for the argument expression, create a
+ %% local binding from the parameter to the operand structure, and
+ %% visit the body. Finally create necessary bindings and/or set
+ %% flags.
+ {Opnd, S1} = make_opnd(let_arg(E), Ren, Env, S),
+ {[R], Ren1, Env1, S2} = bind_locals([V], [Opnd], Ren, Env, S1),
+ {E1, S3} = i(let_body(E), Ctxt, Ren1, Env1, S2),
+ i_let_3([R], [Opnd], E1, S3).
+
+%% Multi-variable `let' binding.
+
+i_let_2(Vs, As, E, Ctxt, Ren, Env, S) ->
+ %% Make operand structures for the argument components. Note that
+ %% since the argument has already been visited at this point, we use
+ %% the identity renaming for the operands.
+ {Opnds, S1} = mapfoldl(fun (E, S) ->
+ make_opnd(E, ren__identity(), Env, S)
+ end,
+ S, As),
+ %% Create local bindings from the parameters to their respective
+ %% operand structures, and visit the body.
+ {Rs, Ren1, Env1, S2} = bind_locals(Vs, Opnds, Ren, Env, S1),
+ {E1, S3} = i(let_body(E), Ctxt, Ren1, Env1, S2),
+ i_let_3(Rs, Opnds, E1, S3).
+
+i_let_3(Rs, Opnds, E, S) ->
+ %% Create necessary bindings and/or set flags.
+ {E1, S1} = make_let_bindings(Rs, E, S),
+
+ %% We must also create evaluation for effect, for any unused
+ %% operands, as after an application expression.
+ residualize_operands(Opnds, E1, S1).
+
+%% A sequence `do e1 e2', written `(seq e1 e2)' in the original
+%% algorithm, where `e1' is evaluated for effect only (since its value
+%% is not used), and `e2' yields the final value. Note that we use
+%% `make_seq' to recompose the sequence after visiting the parts.
+
+i_seq(E, Ctxt, Ren, Env, S) ->
+ {E1, S1} = i(seq_arg(E), effect, Ren, Env, S),
+ {E2, S2} = i(seq_body(E), Ctxt, Ren, Env, S1),
+ %% A sequence has no cost in itself.
+ {make_seq(E1, E2), S2}.
+
+
+%% The `case' switch of Core Erlang is rather different from the boolean
+%% `(if e1 e2 e3)' case of the original algorithm, but the central idea
+%% is the same: if, given the simplified switch expression (which is
+%% visited in `value' context - a boolean `test' context would not be
+%% generally useful), there is a clause which could definitely be
+%% selected, such that no clause before it can possibly be selected,
+%% then we can eliminate all other clauses. (And even if this is not the
+%% case, some clauses can often be eliminated.) Furthermore, if a clause
+%% can be selected, we can replace the case-expression (including the
+%% switch expression) with the body of the clause and a set of zero or
+%% more let-bindings of subexpressions of the switch expression. (In the
+%% simplest case, the switch expression is evaluated only for effect.)
+
+i_case(E, Ctxt, Ren, Env, S) ->
+ %% First visit the switch expression in `value' context, to simplify
+ %% it as far as possible. Note that only the result part is passed
+ %% on to the clause matching below; any effects are hoisted.
+ {A, S1} = i(case_arg(E), value, Ren, Env, S),
+ A1 = result(A),
+
+ %% Propagating an application context into the branches could cause
+ %% the arguments of the application to be evaluated *after* the
+ %% switch expression, but *before* the body of the selected clause.
+ %% Such interleaving is not allowed in general, and it does not seem
+ %% worthwile to make a more powerful transformation here. Therefore,
+ %% the clause bodies are conservatively visited for value if the
+ %% context is `application'.
+ Ctxt1 = safe_context(Ctxt),
+ {E1, S2} = case get_components(case_arity(E), A1) of
+ {true, As} ->
+ i_case_1(As, E, Ctxt1, Ren, Env, S1);
+ false ->
+ i_case_1([], E, Ctxt1, Ren, Env, S1)
+ end,
+ {hoist_effects(A, E1), S2}.
+
+i_case_1(As, E, Ctxt, Ren, Env, S) ->
+ case i_clauses(As, case_clauses(E), Ctxt, Ren, Env, S) of
+ {false, {As1, Vs, Env1, Cs}, S1} ->
+ %% We still have a list of clauses. Sanity check:
+ if Cs == [] ->
+ report_warning("empty list of clauses "
+ "in residual program!.\n");
+ true ->
+ ok
+ end,
+ {A, S2} = i(c_values(As1), value, ren__identity(), Env1,
+ S1),
+ {E1, S3} = i_case_2(Cs, A, E, S2),
+ i_case_3(Vs, Env1, E1, S3);
+ {true, {_, Vs, Env1, [C]}, S1} ->
+ %% A single clause was selected; we just take the body.
+ i_case_3(Vs, Env1, clause_body(C), S1)
+ end.
+
+%% Check if all clause bodies are actually equivalent expressions that
+%% do not depent on pattern variables (this sometimes occurs as a
+%% consequence of inlining, e.g., all branches might yield 'true'), and
+%% if so, replace the `case' with a sequence, first evaluating the
+%% clause selection for effect, then evaluating one of the clause bodies
+%% for its value. (Unless the switch contains a catch-all clause, the
+%% clause selection must be evaluated for effect, since there is no
+%% guarantee that any of the clauses will actually match. Assuming that
+%% some clause always matches could make an undefined program produce a
+%% value.) This makes the final size less than what was accounted for
+%% when visiting the clauses, but currently we don't try to adjust for
+%% this.
+
+i_case_2(Cs, A, E, S) ->
+ case equivalent_clauses(Cs) of
+ false ->
+ %% Count the base sizes for the remaining clauses; pattern
+ %% and guard sizes are already counted.
+ N = weight('case') + weight(clause) * length(Cs),
+ S1 = count_size(N, S),
+ {update_c_case(E, A, Cs), S1};
+ true ->
+ case cerl_clauses:any_catchall(Cs) of
+ true ->
+ %% We know that some clause must be selected, so we
+ %% can drop all the testing as well.
+ E1 = make_seq(A, clause_body(hd(Cs))),
+ {E1, S};
+ false ->
+ %% The clause selection must be performed for
+ %% effect.
+ E1 = update_c_case(E, A,
+ set_clause_bodies(Cs, void())),
+ {make_seq(E1, clause_body(hd(Cs))), S}
+ end
+ end.
+
+i_case_3(Vs, Env, E, S) ->
+ %% For the variables bound to the switch expression subexpressions,
+ %% make let bindings or create evaluation for effect.
+ Rs = [env__get(var_name(V), Env) || V <- Vs],
+ {E1, S1} = make_let_bindings(Rs, E, S),
+ Opnds = [R#ref.opnd || R <- Rs],
+ residualize_operands(Opnds, E1, S1).
+
+%% This function takes a sequence of switch expressions `Es' (which can
+%% be the empty list if these are unknown) and a list `Cs' of clauses,
+%% and returns `{Match, {As, Vs, Env1, Cs1}, S1}' where `As' is a list
+%% of residual switch expressions, `Vs' the list of variables used in
+%% the templates, `Env1' the environment for the templates, and `Cs1'
+%% the list of residual clauses. `Match' is `true' if some clause could
+%% be shown to definitely match (in this case, `Cs1' contains exactly
+%% one element), and `false' otherwise. `S1' is the new state. The given
+%% `Ctxt' is the context to be used for visiting the body of clauses.
+%%
+%% Visiting a clause basically amounts to extending the environment for
+%% all variables in the pattern, as for a `fun' (cf. `i_fun'),
+%% propagating match information if possible, and visiting the guard and
+%% body in the new environment.
+%%
+%% To make it cheaper to do handle a set of clauses, and to avoid
+%% unnecessarily exceeding the size limit, we avoid visiting the bodies
+%% of clauses which are subsequently removed, by dividing the visiting
+%% of a clause into two stages: first construct the environment(s) and
+%% visit the pattern (for renaming) and the guard (for value), then
+%% reduce the switch as much as possible, and lastly visit the body.
+
+i_clauses(Cs, Ctxt, Ren, Env, S) ->
+ i_clauses([], Cs, Ctxt, Ren, Env, S).
+
+i_clauses(Es, Cs, Ctxt, Ren, Env, S) ->
+ %% Create templates for the switch expressions.
+ {Ts, {Vs, Env0}} = mapfoldl(fun (E, {Vs, Env}) ->
+ {T, Vs1, Env1} =
+ make_template(E, Env),
+ {T, {Vs1 ++ Vs, Env1}}
+ end,
+ {[], Env}, Es),
+
+ %% Make operand structures for the switch subexpression templates
+ %% (found in `Env0') and add proper ref-structure bindings to the
+ %% environment. Since the subexpressions in general can be
+ %% interdependent (Vs is in reverse-dependency order), the
+ %% environment (and renaming) must be created incrementally. Note
+ %% that since the switch expressions have been visited already, the
+ %% identity renaming is used for the operands.
+ Vs1 = lists:reverse(Vs),
+ {Ren1, Env1, S1} =
+ foldl(fun (V, {Ren, Env, S}) ->
+ E = env__get(var_name(V), Env0),
+ {Opnd, S_1} = make_opnd(E, ren__identity(), Env,
+ S),
+ {_, Ren1, Env1, S_2} = bind_locals([V], [Opnd],
+ Ren, Env, S_1),
+ {Ren1, Env1, S_2}
+ end,
+ {Ren, Env, S}, Vs1),
+
+ %% First we visit the head of each individual clause, renaming
+ %% pattern variables, inserting let-bindings in the guard and body,
+ %% and visiting the guard. The information used for visiting the
+ %% clause body will be prefixed to the clause annotations.
+ {Cs1, S2} = mapfoldl(fun (C, S) ->
+ i_clause_head(C, Ts, Ren1, Env1, S)
+ end,
+ S1, Cs),
+
+ %% Now that the clause guards have been reduced as far as possible,
+ %% we can attempt to reduce the clauses.
+ As = [hd(get_ann(T)) || T <- Ts],
+ case cerl_clauses:reduce(Cs1, Ts) of
+ {false, Cs2} ->
+ %% We still have one or more clauses (with associated
+ %% extended environments). Their bodies have not yet been
+ %% visited, so we do that (in the respective safe
+ %% environments, adding the sizes of the visited heads to
+ %% the current size counter) and return the final list of
+ %% clauses.
+ {Cs3, S3} = mapfoldl(
+ fun (C, S) ->
+ i_clause_body(C, Ctxt, S)
+ end,
+ S2, Cs2),
+ {false, {As, Vs1, Env1, Cs3}, S3};
+ {true, {C, _}} ->
+ %% A clause C could be selected (the bindings have already
+ %% been added to the guard/body). Note that since the clause
+ %% head will probably be discarded, its size is not counted.
+ {C1, Ren2, Env2, _} = get_clause_extras(C),
+ {B, S3} = i(clause_body(C), Ctxt, Ren2, Env2, S2),
+ C2 = update_c_clause(C1, clause_pats(C1), clause_guard(C1), B),
+ {true, {As, Vs1, Env1, [C2]}, S3}
+ end.
+
+%% This visits the head of a clause, renames pattern variables, inserts
+%% let-bindings in the guard and body, and does inlining on the guard
+%% expression. Returns a list of pairs `{NewClause, Data}', where `Data'
+%% is `{Renaming, Environment, Size}' used for visiting the body of the
+%% new clause.
+
+i_clause_head(C, Ts, Ren, Env, S) ->
+ %% Match the templates against the (non-renamed) patterns to get the
+ %% available information about matching subexpressions. We don't
+ %% care at this point whether an exact match/nomatch is detected.
+ Ps = clause_pats(C),
+ Bs = case cerl_clauses:match_list(Ps, Ts) of
+ {_, Bs1} -> Bs1;
+ none -> []
+ end,
+
+ %% The patterns must be visited for renaming; cf. `i_pattern'. We
+ %% use a passive size counter for visiting the patterns and the
+ %% guard (cf. `visit'), because we do not know at this stage whether
+ %% the clause will be kept or not; the final value of the counter is
+ %% included in the returned value below.
+ {_, Ren1, Env1, S1} = bind_locals(clause_vars(C), Ren, Env, S),
+ S2 = new_passive_size(get_size_limit(S1), S1),
+ {Ps1, S3} = mapfoldl(fun (P, S) ->
+ i_pattern(P, Ren1, Env1, Ren, Env, S)
+ end,
+ S2, Ps),
+
+ %% Rewrite guard and body and visit the guard for value. Discard the
+ %% latter size count if the guard turns out to be a constant.
+ G = add_match_bindings(Bs, clause_guard(C)),
+ B = add_match_bindings(Bs, clause_body(C)),
+ {G1, S4} = i(G, value, Ren1, Env1, S3),
+ S5 = case is_literal(G1) of
+ true ->
+ revert_size(S3, S4);
+ false ->
+ S4
+ end,
+
+ %% Revert to the size counter we had on entry to this function. The
+ %% environment and renaming, together with the size of the clause
+ %% head, are prefixed to the annotations for later use.
+ Size = get_size_value(S5),
+ C1 = update_c_clause(C, Ps1, G1, B),
+ {set_clause_extras(C1, Ren1, Env1, Size), revert_size(S, S5)}.
+
+add_match_bindings(Bs, E) ->
+ %% Don't waste time if the variables definitely cannot be used.
+ %% (Most guards are simply `true'.)
+ case is_literal(E) of
+ true ->
+ E;
+ false ->
+ Vs = [V || {V, E} <- Bs, E /= any],
+ Es = [hd(get_ann(E)) || {_V, E} <- Bs, E /= any],
+ c_let(Vs, c_values(Es), E)
+ end.
+
+i_clause_body(C0, Ctxt, S) ->
+ {C, Ren, Env, Size} = get_clause_extras(C0),
+ S1 = count_size(Size, S),
+ {B, S2} = i(clause_body(C), Ctxt, Ren, Env, S1),
+ C1 = update_c_clause(C, clause_pats(C), clause_guard(C), B),
+ {C1, S2}.
+
+get_clause_extras(C) ->
+ [{Ren, Env, Size} | As] = get_ann(C),
+ {set_ann(C, As), Ren, Env, Size}.
+
+set_clause_extras(C, Ren, Env, Size) ->
+ As = [{Ren, Env, Size} | get_ann(C)],
+ set_ann(C, As).
+
+%% This is the `(lambda x e)' case of the original algorithm. A
+%% `fun' is like a lambda expression, but with a varying number of
+%% parameters; possibly zero.
+
+i_fun(E, Ctxt, Ren, Env, S) ->
+ case Ctxt of
+ effect ->
+ %% Reduce useless `fun' expressions to a simple constant;
+ %% visiting the body would be a waste of time, and could
+ %% needlessly mark variables as referenced.
+ {void(), count_size(weight(literal), S)};
+ value ->
+ %% Note that the variables are visited as patterns.
+ Vs = fun_vars(E),
+ {_, Ren1, Env1, S1} = bind_locals(Vs, Ren, Env, S),
+ Vs1 = i_params(Vs, Ren1, Env1),
+
+ %% The body is always visited for value.
+ {B, S2} = i(fun_body(E), value, Ren1, Env1, S1),
+
+ %% We don't bother to include the exact number of free
+ %% variables in the cost for creating a fun-value.
+ S3 = count_size(weight('fun'), S2),
+
+ %% Inlining might have duplicated code, so we must remove
+ %% any 'id'-annotations from the original fun-expression.
+ %% (This forces a later stage to invent new id:s.) This is
+ %% necessary as long as fun:s may still need to be
+ %% identified the old way. Function variables that are not
+ %% in application context also have such annotations, but
+ %% the inlining will currently lose all annotations on
+ %% variable references (I think), so that's not a problem.
+ {set_ann(c_fun(Vs1, B), kill_id_anns(get_ann(E))), S3};
+ #app{} ->
+ %% An application of a fun-expression (in the source code)
+ %% is handled by going directly to `inline'; this is never
+ %% residualised, and we don't set up new counters here. Note
+ %% that inlining of copy-propagated fun-expressions is done
+ %% in `copy'; not here.
+ inline(E, Ctxt, Ren, Env, S)
+ end.
+
+%% A `letrec' requires a circular environment, but is otherwise like a
+%% `let', i.e. like a direct lambda application. Note that only
+%% fun-expressions (lambda abstractions) may occur in the right-hand
+%% side of each definition.
+
+i_letrec(E, Ctxt, Ren, Env, S) ->
+ %% Note that we pass an empty list for the auto-referenced
+ %% (exported) functions here.
+ {Es, B, _, S1} = i_letrec(letrec_defs(E), letrec_body(E), [], Ctxt,
+ Ren, Env, S),
+
+ %% If no bindings remain, only the body is returned.
+ case Es of
+ [] ->
+ {B, S1}; % drop annotations on E
+ _ ->
+ S2 = count_size(weight(letrec), S1),
+ {update_c_letrec(E, Es, B), S2}
+ end.
+
+%% The major part of this is shared by letrec-expressions and module
+%% definitions alike.
+
+i_letrec(Es, B, Xs, Ctxt, Ren, Env, S) ->
+ %% First, we create operands with dummy renamings and environments,
+ %% and with fresh store locations for cached expressions and operand
+ %% info.
+ {Opnds, S1} = mapfoldl(fun ({_, E}, S) ->
+ make_opnd(E, undefined, undefined, S)
+ end,
+ S, Es),
+
+ %% Then we make recursive bindings for the definitions.
+ {Rs, Ren1, Env1, S2} = bind_recursive([F || {F, _} <- Es],
+ Opnds, Ren, Env, S1),
+
+ %% For the function variables listed in Xs (none for a
+ %% letrec-expression), we must make sure that the corresponding
+ %% operand expressions are visited and that the definitions are
+ %% marked as referenced; we also need to return the possibly renamed
+ %% function variables.
+ {Xs1, S3} =
+ mapfoldl(
+ fun (X, S) ->
+ Name = ren__map(var_name(X), Ren1),
+ case env__lookup(Name, Env1) of
+ {ok, R} ->
+ S_1 = i_letrec_export(R, S),
+ {ref_to_var(R), S_1};
+ error ->
+ %% We just skip any exports that are not
+ %% actually defined here, and generate a
+ %% warning message.
+ {N, A} = var_name(X),
+ report_warning("export `~w'/~w "
+ "not defined.\n", [N, A]),
+ {X, S}
+ end
+ end,
+ S2, Xs),
+
+ %% At last, we can then visit the body.
+ {B1, S4} = i(B, Ctxt, Ren1, Env1, S3),
+
+ %% Finally, we create new letrec-bindings for any and all
+ %% residualised definitions. All referenced functions should have
+ %% been visited; the call to `visit' below is expected to retreive a
+ %% cached expression.
+ Rs1 = keep_referenced(Rs, S4),
+ {Es1, S5} = mapfoldl(fun (R, S) ->
+ {E_1, S_1} = visit(R#ref.opnd, S),
+ {{ref_to_var(R), E_1}, S_1}
+ end,
+ S4, Rs1),
+ {Es1, B1, Xs1, S5}.
+
+%% This visits the operand for a function definition exported by a
+%% `letrec' (which is really a `module' module definition, since normal
+%% letrecs have no export declarations). Only the updated state is
+%% returned. We must handle the "inner-pending" flag when doing this;
+%% cf. `i_var'.
+
+i_letrec_export(R, S) ->
+ Opnd = R#ref.opnd,
+ S1 = st__mark_inner_pending(Opnd#opnd.loc, S),
+ {_, S2} = visit(Opnd, S1),
+ {_, S3} = residualize_var(R, st__clear_inner_pending(Opnd#opnd.loc,
+ S2)),
+ S3.
+
+%% This is the `(call e1 e2)' case of the original algorithm. The only
+%% difference is that we must handle multiple (or no) operand
+%% expressions.
+
+i_apply(E, Ctxt, Ren, Env, S) ->
+ {Opnds, S1} = mapfoldl(fun (E, S) ->
+ make_opnd(E, Ren, Env, S)
+ end,
+ S, apply_args(E)),
+
+ %% Allocate a new app-context location and set up an application
+ %% context structure containing the surrounding context.
+ {L, S2} = st__new_app_loc(S1),
+ Ctxt1 = #app{opnds = Opnds, ctxt = Ctxt, loc = L},
+
+ %% Visit the operator expression in the new call context.
+ {E1, S3} = i(apply_op(E), Ctxt1, Ren, Env, S2),
+
+ %% Check the "inlined" flag to find out what to do next. (The store
+ %% location could be recycled after the flag has been tested, but
+ %% there is no real advantage to that, because in practice, only
+ %% 4-5% of all created store locations will ever be reused, while
+ %% there will be a noticable overhead for managing the free list.)
+ case st__get_app_inlined(L, S3) of
+ true ->
+ %% The application was inlined, so we have the final
+ %% expression in `E1'. We just have to handle any operands
+ %% that need to be residualized for effect only (i.e., those
+ %% the values of which are not used).
+ residualize_operands(Opnds, E1, S3);
+ false ->
+ %% Otherwise, `E1' is the residual operator expression. We
+ %% make sure all operands are visited, and rebuild the
+ %% application.
+ {Es, S4} = mapfoldl(fun (Opnd, S) ->
+ visit_and_count_size(Opnd, S)
+ end,
+ S3, Opnds),
+ N = apply_size(length(Es)),
+ {update_c_apply(E, E1, Es), count_size(N, S4)}
+ end.
+
+apply_size(A) ->
+ weight(apply) + weight(argument) * A.
+
+%% Since it is not the task of this transformation to handle
+%% cross-module inlining, all inter-module calls are handled by visiting
+%% the components (the module and function name, and the arguments of
+%% the call) for value. In `effect' context, if the function itself is
+%% known to be completely effect free, the call can be discarded and the
+%% arguments evaluated for effect. Otherwise, if all the visited
+%% arguments are to constants, and the function is known to be safe to
+%% execute at compile time, then we try to evaluate the call. If
+%% evaluation completes normally, the call is replaced by the result;
+%% otherwise the call is residualised.
+
+i_call(E, Ctxt, Ren, Env, S) ->
+ {M, S1} = i(call_module(E), value, Ren, Env, S),
+ {F, S2} = i(call_name(E), value, Ren, Env, S1),
+ As = call_args(E),
+ Arity = length(As),
+
+ %% Check if the name of the called function is static. If so,
+ %% discard the size counts performed above, since the values will
+ %% not cause any runtime cost.
+ Static = is_c_atom(M) and is_c_atom(F),
+ S3 = case Static of
+ true ->
+ revert_size(S, S2);
+ false ->
+ S2
+ end,
+ case Ctxt of
+ effect when Static == true ->
+ case is_safe_call(atom_val(M), atom_val(F), Arity) of
+ true ->
+ %% The result will not be used, and the call is
+ %% effect free, so we create a multiple-value
+ %% aggregate containing the (not yet visited)
+ %% arguments and process that instead.
+ i(c_values(As), effect, Ren, Env, S3);
+ false ->
+ %% We are not allowed to simply discard the call,
+ %% but we can try to evaluate it.
+ i_call_1(Static, M, F, Arity, As, E, Ctxt, Ren, Env,
+ S3)
+ end;
+ _ ->
+ i_call_1(Static, M, F, Arity, As, E, Ctxt, Ren, Env, S3)
+ end.
+
+i_call_1(Static, M, F, Arity, As, E, Ctxt, Ren, Env, S) ->
+ %% Visit the arguments for value.
+ {As1, S1} = mapfoldl(fun (X, A) -> i(X, value, Ren, Env, A) end,
+ S, As),
+ case Static of
+ true ->
+ case erl_bifs:is_pure(atom_val(M), atom_val(F), Arity) of
+ true ->
+ %% It is allowed to evaluate this at compile time.
+ case all_static(As1) of
+ true ->
+ i_call_3(M, F, As1, E, Ctxt, Env, S1);
+ false ->
+ %% See if the call can be rewritten instead.
+ i_call_4(M, F, As1, E, Ctxt, Env, S1)
+ end;
+ false ->
+ i_call_2(M, F, As1, E, S1)
+ end;
+ false ->
+ i_call_2(M, F, As1, E, S1)
+ end.
+
+%% Residualise the call.
+
+i_call_2(M, F, As, E, S) ->
+ N = weight(call) + weight(argument) * length(As),
+ {update_c_call(E, M, F, As), count_size(N, S)}.
+
+%% Attempt to evaluate the call to yield a literal; if that fails, try
+%% to rewrite the expression.
+
+i_call_3(M, F, As, E, Ctxt, Env, S) ->
+ %% Note that we extract the results of argument expessions here; the
+ %% expressions could still be sequences with side effects.
+ Vs = [concrete(result(A)) || A <- As],
+ case catch {ok, apply(atom_val(M), atom_val(F), Vs)} of
+ {ok, V} ->
+ %% Evaluation completed normally - try to turn the result
+ %% back into a syntax tree (representing a literal).
+ case is_literal_term(V) of
+ true ->
+ %% Make a sequence of the arguments (as a
+ %% multiple-value aggregate) and the final value.
+ S1 = count_size(weight(values), S),
+ S2 = count_size(weight(literal), S1),
+ {make_seq(c_values(As), abstract(V)), S2};
+ false ->
+ %% The result could not be represented as a literal.
+ i_call_4(M, F, As, E, Ctxt, Env, S)
+ end;
+ _ ->
+ %% The evaluation attempt did not complete normally.
+ i_call_4(M, F, As, E, Ctxt, Env, S)
+ end.
+
+%% Rewrite the expression, if possible, otherwise residualise it.
+
+i_call_4(M, F, As, E, Ctxt, Env, S) ->
+ case reduce_bif_call(atom_val(M), atom_val(F), As, Env) of
+ false ->
+ %% Nothing more to be done - residualise the call.
+ i_call_2(M, F, As, E, S);
+ {true, E1} ->
+ %% We revisit the result, because the rewriting might have
+ %% opened possibilities for further inlining. Since the
+ %% parts have already been visited once, we use the identity
+ %% renaming here.
+ i(E1, Ctxt, ren__identity(), Env, S)
+ end.
+
+%% For now, we assume that primops cannot be evaluated at compile time,
+%% probably being too special. Also, we have no knowledge about their
+%% side effects.
+
+i_primop(E, Ren, Env, S) ->
+ %% Visit the arguments for value.
+ {As, S1} = mapfoldl(fun (E, S) ->
+ i(E, value, Ren, Env, S)
+ end,
+ S, primop_args(E)),
+ N = weight(primop) + weight(argument) * length(As),
+ {update_c_primop(E, primop_name(E), As), count_size(N, S1)}.
+
+%% This is like having an expression with an extra fun-expression
+%% attached for "exceptional cases"; actually, there are exactly two
+%% parameter variables for the body, but they are easiest handled as if
+%% their number might vary, just as for a `fun'.
+
+i_try(E, Ctxt, Ren, Env, S) ->
+ %% The argument expression is evaluated in `value' context, and the
+ %% surrounding context is propagated into both branches. We do not
+ %% try to recognize cases when the protected expression will
+ %% actually raise an exception. Note that the variables are visited
+ %% as patterns.
+ {A, S1} = i(try_arg(E), value, Ren, Env, S),
+ Vs = try_vars(E),
+ {_, Ren1, Env1, S2} = bind_locals(Vs, Ren, Env, S1),
+ Vs1 = i_params(Vs, Ren1, Env1),
+ {B, S3} = i(try_body(E), Ctxt, Ren1, Env1, S2),
+ case is_safe(A) of
+ true ->
+ %% The `try' wrapper can be dropped in this case. Since the
+ %% expressions have been visited already, the identity
+ %% renaming is used when we revisit the new let-expression.
+ i(c_let(Vs1, A, B), Ctxt, ren__identity(), Env, S3);
+ false ->
+ Evs = try_evars(E),
+ {_, Ren2, Env2, S4} = bind_locals(Evs, Ren, Env, S3),
+ Evs1 = i_params(Evs, Ren2, Env2),
+ {H, S5} = i(try_handler(E), Ctxt, Ren2, Env2, S4),
+ S6 = count_size(weight('try'), S5),
+ {update_c_try(E, A, Vs1, B, Evs1, H), S6}
+ end.
+
+%% A special case of try-expressions:
+
+i_catch(E, Ctxt, Ren, Env, S) ->
+ %% We cannot propagate application contexts into the catch.
+ {E1, S1} = i(catch_body(E), safe_context(Ctxt), Ren, Env, S),
+ case is_safe(E1) of
+ true ->
+ %% The `catch' wrapper can be dropped in this case.
+ {E1, S1};
+ false ->
+ S2 = count_size(weight('catch'), S1),
+ {update_c_catch(E, E1), S2}
+ end.
+
+%% A receive-expression is very much like a case-expression, with the
+%% difference that we do not have access to a switch expression, since
+%% the value being switched on is taken from the mailbox. The fact that
+%% the receive-expression may iterate over an arbitrary number of
+%% messages is not of interest to us. All we can do here is to visit its
+%% subexpressions, and possibly eliminate definitely unselectable
+%% clauses.
+
+i_receive(E, Ctxt, Ren, Env, S) ->
+ %% We first visit the expiry expression (for value) and the expiry
+ %% body (in the surrounding context).
+ {T, S1} = i(receive_timeout(E), value, Ren, Env, S),
+ {B, S2} = i(receive_action(E), Ctxt, Ren, Env, S1),
+
+ %% Then we visit the clauses. Note that application contexts may not
+ %% in general be propagated into the branches (and the expiry body),
+ %% because the execution of the `receive' may remove a message from
+ %% the mailbox as a side effect; the situation is thus analogous to
+ %% that in a `case' expression.
+ Ctxt1 = safe_context(Ctxt),
+ case i_clauses(receive_clauses(E), Ctxt1, Ren, Env, S2) of
+ {false, {[], _, _, Cs}, S3} ->
+ %% We still have a list of clauses. If the list is empty,
+ %% and the expiry expression is the integer zero, the
+ %% expression reduces to the expiry body.
+ if Cs == [] ->
+ case is_c_int(T) andalso (int_val(T) == 0) of
+ true ->
+ {B, S3};
+ false ->
+ i_receive_1(E, Cs, T, B, S3)
+ end;
+ true ->
+ i_receive_1(E, Cs, T, B, S3)
+ end;
+ {true, {_, _, _, Cs}, S3} ->
+ %% Cs is a single clause that will always be matched (if a
+ %% message exists), but we must keep the `receive' statement
+ %% in order to fetch the message from the mailbox.
+ i_receive_1(E, Cs, T, B, S3)
+ end.
+
+i_receive_1(E, Cs, T, B, S) ->
+ %% Here, we just add the base sizes for the receive-expression
+ %% itself and for each remaining clause; cf. `case'.
+ N = weight('receive') + weight(clause) * length(Cs),
+ {update_c_receive(E, Cs, T, B), count_size(N, S)}.
+
+%% A module definition is like a `letrec', with some add-ons (export and
+%% attribute declarations) but without an explicit body. Actually, the
+%% exporting of function names has the same effect as if there was a
+%% body consisting of the list of references to the exported functions.
+%% Thus, the exported functions are exactly those which can be
+%% referenced from outside the module.
+
+i_module(E, Ctxt, Ren, Env, S) ->
+ %% Cf. `i_letrec'. Note that we pass a dummy constant value for the
+ %% "body" parameter.
+ {Es, _, Xs1, S1} = i_letrec(module_defs(E), void(),
+ module_exports(E), Ctxt, Ren, Env, S),
+ %% Sanity check:
+ case Es of
+ [] ->
+ report_warning("no function definitions remaining "
+ "in module `~s'.\n",
+ [atom_name(module_name(E))]);
+ _ ->
+ ok
+ end,
+ E1 = update_c_module(E, module_name(E), Xs1, module_attrs(E), Es),
+ {E1, count_size(weight(module), S1)}.
+
+%% Binary-syntax expressions are too complicated to do anything
+%% interesting with here - that is beyond the scope of this program;
+%% also, their construction could have side effects, so even in effect
+%% context we can't remove them. (We don't bother to identify cases of
+%% "safe" unused binaries which could be removed.)
+
+i_binary(E, Ren, Env, S) ->
+ %% Visit the segments for value.
+ {Es, S1} = mapfoldl(fun (E, S) ->
+ i_bitstr(E, Ren, Env, S)
+ end,
+ S, binary_segments(E)),
+ S2 = count_size(weight(binary), S1),
+ {update_c_binary(E, Es), S2}.
+
+i_bitstr(E, Ren, Env, S) ->
+ %% It is not necessary to visit the Unit, Type and Flags fields,
+ %% since these are always literals.
+ {Val, S1} = i(bitstr_val(E), value, Ren, Env, S),
+ {Size, S2} = i(bitstr_size(E), value, Ren, Env, S1),
+ Unit = bitstr_unit(E),
+ Type = bitstr_type(E),
+ Flags = bitstr_flags(E),
+ S3 = count_size(weight(bitstr), S2),
+ {update_c_bitstr(E, Val, Size, Unit, Type, Flags), S3}.
+
+%% This is a simplified version of `i_pattern', for lists of parameter
+%% variables only. It does not modify the state.
+
+i_params([V | Vs], Ren, Env) ->
+ Name = ren__map(var_name(V), Ren),
+ case env__lookup(Name, Env) of
+ {ok, R} ->
+ [ref_to_var(R) | i_params(Vs, Ren, Env)];
+ error ->
+ report_internal_error("variable `~w' not bound "
+ "in pattern.\n", [Name]),
+ exit(error)
+ end;
+i_params([], _, _) ->
+ [].
+
+%% For ordinary patterns, we just visit to rename variables and count
+%% the size/cost. All occurring binding instances of variables should
+%% already have been added to the renaming and environment; however, to
+%% handle the size expressions of binary-syntax patterns, we must pass
+%% the renaming and environment of the containing expression
+
+i_pattern(E, Ren, Env, Ren0, Env0, S) ->
+ case type(E) of
+ var ->
+ %% Count no size.
+ Name = ren__map(var_name(E), Ren),
+ case env__lookup(Name, Env) of
+ {ok, R} ->
+ {ref_to_var(R), S};
+ error ->
+ report_internal_error("variable `~w' not bound "
+ "in pattern.\n", [Name]),
+ exit(error)
+ end;
+ alias ->
+ %% Count no size.
+ V = alias_var(E),
+ Name = ren__map(var_name(V), Ren),
+ case env__lookup(Name, Env) of
+ {ok, R} ->
+ %% Visit the subpattern and recompose.
+ V1 = ref_to_var(R),
+ {P, S1} = i_pattern(alias_pat(E), Ren, Env, Ren0,
+ Env0, S),
+ {update_c_alias(E, V1, P), S1};
+ error ->
+ report_internal_error("variable `~w' not bound "
+ "in pattern.\n", [Name]),
+ exit(error)
+ end;
+ binary ->
+ {Es, S1} = mapfoldl(fun (E, S) ->
+ i_bitstr_pattern(E, Ren, Env,
+ Ren0, Env0, S)
+ end,
+ S, binary_segments(E)),
+ S2 = count_size(weight(binary), S1),
+ {update_c_binary(E, Es), S2};
+ _ ->
+ case is_literal(E) of
+ true ->
+ {E, count_size(weight(literal), S)};
+ false ->
+ {Es1, S1} = mapfoldl(fun (E, S) ->
+ i_pattern(E, Ren, Env,
+ Ren0, Env0,
+ S)
+ end,
+ S, data_es(E)),
+ %% We assume that in general, the elements of the
+ %% constructor will all be fetched.
+ N = weight(data) + length(Es1) * weight(element),
+ S2 = count_size(N, S1),
+ {update_data(E, data_type(E), Es1), S2}
+ end
+ end.
+
+i_bitstr_pattern(E, Ren, Env, Ren0, Env0, S) ->
+ %% It is not necessary to visit the Unit, Type and Flags fields,
+ %% since these are always literals. The Value field is a limited
+ %% pattern - either a literal or an unbound variable. The Size field
+ %% is a limited expression - either a literal or a variable bound in
+ %% the environment of the containing expression.
+ {Val, S1} = i_pattern(bitstr_val(E), Ren, Env, Ren0, Env0, S),
+ {Size, S2} = i(bitstr_size(E), value, Ren0, Env0, S1),
+ Unit = bitstr_unit(E),
+ Type = bitstr_type(E),
+ Flags = bitstr_flags(E),
+ S3 = count_size(weight(bitstr), S2),
+ {update_c_bitstr(E, Val, Size, Unit, Type, Flags), S3}.
+
+
+%% ---------------------------------------------------------------------
+%% Other central inlining functions
+
+%% It is assumed here that `E' is a fun-expression and the context is an
+%% app-structure. If the inlining might be aborted for some reason, a
+%% corresponding catch should have been set up before entering `inline'.
+%%
+%% Note: if the inlined body is a lambda abstraction, and the
+%% surrounding context of the app-context is also an app-context, the
+%% `inlined' flag of the outermost context will be set before that of
+%% the inner context is set. E.g.: `let F = fun (X) -> fun (Y) -> E in
+%% apply apply F(A)(B)' will propagate the body of F, which is a lambda
+%% abstraction, into the outer application context, which will be
+%% inlined to produce expression `E', and the flag of the outer context
+%% will be set. Upon return, the flag of the inner context will also be
+%% set. However, the flags are then tested in innermost-first order.
+%% Thus, if some inlining attempt is aborted, the `inlined' flags of any
+%% nested app-contexts must be cleared.
+%%
+%% This implementation does nothing to handle inlining of calls to
+%% recursive functions in a smart way. This means that as long as the
+%% size and effort counters do not prevent it, the function body will be
+%% inlined (i.e., the first iteration will be unrolled), and the
+%% recursive calls will be residualized.
+
+inline(E, #app{opnds = Opnds, ctxt = Ctxt, loc = L}, Ren, Env, S) ->
+ %% Check that the arities match:
+ Vs = fun_vars(E),
+ if length(Opnds) /= length(Vs) ->
+ report_error("function called with wrong number "
+ "of arguments!\n"),
+ %% TODO: should really just residualise the call...
+ exit(error);
+ true ->
+ ok
+ end,
+ %% Create local bindings for the parameters to their respective
+ %% operand structures from the app-structure, and visit the body in
+ %% the context saved in the structure.
+ {Rs, Ren1, Env1, S1} = bind_locals(Vs, Opnds, Ren, Env, S),
+ {E1, S2} = i(fun_body(E), Ctxt, Ren1, Env1, S1),
+
+ %% Create necessary bindings and/or set flags.
+ {E2, S3} = make_let_bindings(Rs, E1, S2),
+
+ %% Lastly, flag the application as inlined, since the inlining
+ %% attempt was not aborted before we reached this point.
+ {E2, st__set_app_inlined(L, S3)}.
+
+%% For the (possibly renamed) argument variables to an inlined call,
+%% either create `let' bindings for them, if they are still referenced
+%% in the residual expression (in C/Lisp, also if they are assigned to),
+%% or otherwise (if they are not referenced or assigned) mark them for
+%% evaluation for side effects.
+
+make_let_bindings([R | Rs], E, S) ->
+ {E1, S1} = make_let_bindings(Rs, E, S),
+ make_let_binding(R, E1, S1);
+make_let_bindings([], E, S) ->
+ {E, S}.
+
+make_let_binding(R, E, S) ->
+ %% The `referenced' flag is conservatively computed. We therefore
+ %% first check some simple cases where parameter R is definitely not
+ %% referenced in the resulting body E.
+ case is_literal(E) of
+ true ->
+ %% A constant contains no variable references.
+ make_let_binding_1(R, E, S);
+ false ->
+ case is_c_var(E) of
+ true ->
+ case var_name(E) =:= R#ref.name of
+ true ->
+ %% The body is simply the parameter variable
+ %% itself. Visit the operand for value and
+ %% substitute the result for the body.
+ visit_and_count_size(R#ref.opnd, S);
+ false ->
+ %% Not the same variable, so the parameter
+ %% is not referenced at all.
+ make_let_binding_1(R, E, S)
+ end;
+ false ->
+ %% Proceed to check the `referenced' flag.
+ case st__get_var_referenced(R#ref.loc, S) of
+ true ->
+ %% The parameter is probably referenced in
+ %% the residual code (although it might not
+ %% be). Visit the operand for value and
+ %% create a let-binding.
+ {E1, S1} = visit_and_count_size(R#ref.opnd,
+ S),
+ S2 = count_size(weight('let'), S1),
+ {c_let([ref_to_var(R)], E1, E), S2};
+ false ->
+ %% The parameter is definitely not
+ %% referenced.
+ make_let_binding_1(R, E, S)
+ end
+ end
+ end.
+
+%% This marks the operand for evaluation for effect.
+
+make_let_binding_1(R, E, S) ->
+ Opnd = R#ref.opnd,
+ {E, st__set_opnd_effect(Opnd#opnd.loc, S)}.
+
+%% Here, `R' is the ref-structure which is the target of the copy
+%% propagation, and `Opnd' is a visited operand structure, to be
+%% propagated through `R' if possible - if not, `R' is residualised.
+%% `Opnd' is normally the operand that `R' is bound to, and `E' is the
+%% result of visiting `Opnd' for value; we pass this as an argument so
+%% we don't have to fetch it multiple times (because we don't have
+%% constant time access).
+%%
+%% We also pass the environment of the site of the variable reference,
+%% for use when inlining a propagated fun-expression. In the original
+%% algorithm by Waddell, the environment used for inlining such cases is
+%% the identity mapping, because the fun-expression body has already
+%% been visited for value, and their algorithm combines renaming of
+%% source-code variables with the looking up of information about
+%% residual-code variables. We, however, need to check the environment
+%% of the call site when creating new non-shadowed variables, but we
+%% must avoid repeated renaming. We therefore separate the renaming and
+%% the environment (as in the renaming algorithm of Peyton-Jones and
+%% Marlow). This also makes our implementation more general, compared to
+%% the original algorithm, because we do not give up on propagating
+%% variables that were free in the fun-body.
+%%
+%% Example:
+%%
+%% let F = fun (X) -> {'foo', X} in
+%% let G = fun (H) -> apply H(F) % F is free in the fun G
+%% in apply G(fun (F) -> apply F(42))
+%% =>
+%% let F = fun (X) -> {'foo', X} in
+%% apply (fun (H) -> apply H(F))(fun (F) -> apply F(42))
+%% =>
+%% let F = fun (X) -> {'foo', X} in
+%% apply (fun (F) -> apply F(42))(F)
+%% =>
+%% let F = fun (X) -> {'foo', X} in
+%% apply F(42)
+%% =>
+%% apply (fun (X) -> {'foo', X})(2)
+%% =>
+%% {'foo', 42}
+%%
+%% The original algorithm would give up at stage 4, because F was free
+%% in the propagated fun-expression. Our version inlines this example
+%% completely.
+
+copy(R, Opnd, E, Ctxt, Env, S) ->
+ case is_c_var(E) of
+ true ->
+ %% The operand reduces to another variable - get its
+ %% ref-structure and attempt to propagate further.
+ copy_var(env__get(var_name(E), Opnd#opnd.env), Ctxt, Env,
+ S);
+ false ->
+ %% Apart from variables and functional values (the latter
+ %% are handled by `copy_1' below), only constant literals
+ %% are copyable in general; other things, including e.g.
+ %% tuples `{foo, X}', could cause duplication of work, and
+ %% are not copy propagated.
+ case is_literal(E) of
+ true ->
+ {E, count_size(weight(literal), S)};
+ false ->
+ copy_1(R, Opnd, E, Ctxt, Env, S)
+ end
+ end.
+
+copy_var(R, Ctxt, Env, S) ->
+ %% (In Lisp or C, if this other variable might be assigned to, we
+ %% should residualize the "parent" instead, so we don't bypass any
+ %% destructive updates.)
+ case R#ref.opnd of
+ undefined ->
+ %% This variable is not bound to an expression, so just
+ %% residualize it.
+ residualize_var(R, S);
+ Opnd ->
+ %% Note that because operands are always visited before
+ %% copied, all copyable operand expressions will be
+ %% propagated through any number of bindings. If `R' was
+ %% bound to a constant literal, we would never have reached
+ %% this point.
+ case st__lookup_opnd_cache(Opnd#opnd.loc, S) of
+ error ->
+ %% The result for this operand is not yet ready
+ %% (which should mean that it is a recursive
+ %% reference). Thus, we must residualise the
+ %% variable.
+ residualize_var(R, S);
+ {ok, #cache{expr = E1}} ->
+ %% The result for the operand is ready, so we can
+ %% proceed to propagate it.
+ copy_1(R, Opnd, E1, Ctxt, Env, S)
+ end
+ end.
+
+copy_1(R, Opnd, E, Ctxt, Env, S) ->
+ %% Fun-expression (lambdas) are a bit special; they are copyable,
+ %% but should preferably not be duplicated, so they should not be
+ %% copy propagated except into application contexts, where they can
+ %% be inlined.
+ case is_c_fun(E) of
+ true ->
+ case Ctxt of
+ #app{} ->
+ %% First test if the operand is "outer-pending"; if
+ %% so, don't inline.
+ case st__test_outer_pending(Opnd#opnd.loc, S) of
+ false ->
+ copy_inline(R, Opnd, E, Ctxt, Env, S);
+ true ->
+ %% Cyclic reference forced inlining to stop
+ %% (avoiding infinite unfolding).
+ residualize_var(R, S)
+ end;
+ _ ->
+ residualize_var(R, S)
+ end;
+ false ->
+ %% We have no other cases to handle here
+ residualize_var(R, S)
+ end.
+
+%% This inlines a function value that was propagated to an application
+%% context. The inlining is done with an identity renaming (since the
+%% expression is already visited) but in the environment of the call
+%% site (which is OK because of the no-shadowing strategy for renaming,
+%% and because the domain of our environments are the residual-program
+%% variables instead of the source-program variables). Note that we must
+%% first set the "outer-pending" flag, and clear it afterwards.
+
+copy_inline(R, Opnd, E, Ctxt, Env, S) ->
+ S1 = st__mark_outer_pending(Opnd#opnd.loc, S),
+ case catch {ok, copy_inline_1(R, E, Ctxt, Env, S1)} of
+ {ok, {E1, S2}} ->
+ {E1, st__clear_outer_pending(Opnd#opnd.loc, S2)};
+ {'EXIT', X} ->
+ exit(X);
+ X ->
+ %% If we use destructive update for the `outer-pending'
+ %% flag, we must make sure to clear it upon a nonlocal
+ %% return.
+ st__clear_outer_pending(Opnd#opnd.loc, S1),
+ throw(X)
+ end.
+
+%% If the current effort counter was passive, we use a new active effort
+%% counter with the inherited limit for this particular inlining.
+
+copy_inline_1(R, E, Ctxt, Env, S) ->
+ case effort_is_active(S) of
+ true ->
+ copy_inline_2(R, E, Ctxt, Env, S);
+ false ->
+ S1 = new_active_effort(get_effort_limit(S), S),
+ case catch {ok, copy_inline_2(R, E, Ctxt, Env, S1)} of
+ {ok, {E1, S2}} ->
+ %% Revert to the old effort counter.
+ {E1, revert_effort(S, S2)};
+ {counter_exceeded, effort, _} ->
+ %% Aborted this inlining attempt because too much
+ %% effort was spent. Residualize the variable and
+ %% revert to the previous state.
+ residualize_var(R, S);
+ {'EXIT', X} ->
+ exit(X);
+ X ->
+ throw(X)
+ end
+ end.
+
+%% Regardless of whether the current size counter is active or not, we
+%% use a new active size counter for each inlining. If the current
+%% counter was passive, the new counter gets the inherited size limit;
+%% if it was active, the size limit of the new counter will be equal to
+%% the remaining budget of the current counter (which itself is not
+%% affected by the inlining). This distributes the size budget more
+%% evenly over "inlinings within inlinings", so that the whole size
+%% budget is not spent on the first few call sites (in an inlined
+%% function body) forcing the remaining call sites to be residualised.
+
+copy_inline_2(R, E, Ctxt, Env, S) ->
+ Limit = case size_is_active(S) of
+ true ->
+ get_size_limit(S) - get_size_value(S);
+ false ->
+ get_size_limit(S)
+ end,
+ %% Add the cost of the application to the new size limit, so we
+ %% always inline functions that are small enough, even if `Limit' is
+ %% close to zero at this point. (This is an extension to the
+ %% original algorithm.)
+ S1 = new_active_size(Limit + apply_size(length(Ctxt#app.opnds)), S),
+ case catch {ok, inline(E, Ctxt, ren__identity(), Env, S1)} of
+ {ok, {E1, S2}} ->
+ %% Revert to the old size counter.
+ {E1, revert_size(S, S2)};
+ {counter_exceeded, size, S2} ->
+ %% Aborted this inlining attempt because it got too big.
+ %% Residualize the variable and revert to the old size
+ %% counter. (It is important that we do not also revert the
+ %% effort counter here. Because the effort and size counters
+ %% are always set up together, we know that the effort
+ %% counter returned in S2 is the same that was passed to
+ %% `inline'.)
+ S3 = revert_size(S, S2),
+ %% If we use destructive update for the `inlined' flag, we
+ %% must make sure to clear the flags of any nested
+ %% app-contexts upon aborting; see `inline' for details.
+ reset_nested_apps(Ctxt, S3), % for effect
+ residualize_var(R, S3);
+ {'EXIT', X} ->
+ exit(X);
+ X ->
+ throw(X)
+ end.
+
+reset_nested_apps(#app{ctxt = Ctxt, loc = L}, S) ->
+ reset_nested_apps(Ctxt, st__clear_app_inlined(L, S));
+reset_nested_apps(_, S) ->
+ S.
+
+
+%% ---------------------------------------------------------------------
+%% Support functions
+
+new_var(Env) ->
+ Name = env__new_vname(Env),
+ c_var(Name).
+
+residualize_var(R, S) ->
+ S1 = count_size(weight(var), S),
+ {ref_to_var(R), st__set_var_referenced(R#ref.loc, S1)}.
+
+%% This function returns the value-producing subexpression of any
+%% expression. (Except for sequencing expressions, this is the
+%% expression itself.)
+
+result(E) ->
+ case is_c_seq(E) of
+ true ->
+ %% Also see `make_seq', which is used in all places to build
+ %% sequences so that they are always nested in the first
+ %% position.
+ seq_body(E);
+ false ->
+ E
+ end.
+
+%% This function rewrites E to `do A1 E' if A is `do A1 A2', and
+%% otherwise returns E unchanged.
+
+hoist_effects(A, E) ->
+ case type(A) of
+ seq -> make_seq(seq_arg(A), E);
+ _ -> E
+ end.
+
+%% This "build sequencing expression" operation assures that sequences
+%% are always nested in the first position, which makes it easy to find
+%% the actual value-producing expression of a sequence (cf. `result').
+
+make_seq(E1, E2) ->
+ case is_safe(E1) of
+ true ->
+ %% The first expression can safely be dropped.
+ E2;
+ false ->
+ %% If `E1' is a sequence whose final expression has no side
+ %% effects, then we can lose *that* expression when we
+ %% compose the new sequence, since its value will not be
+ %% used.
+ E3 = case is_c_seq(E1) of
+ true ->
+ case is_safe(seq_body(E1)) of
+ true ->
+ %% Drop the final expression.
+ seq_arg(E1);
+ false ->
+ E1
+ end;
+ false ->
+ E1
+ end,
+ case is_c_seq(E2) of
+ true ->
+ %% `E2' is a sequence (E2' E2''), so we must
+ %% rearrange the nesting to ((E1, E2') E2''), to
+ %% preserve the invariant. Annotations on `E2' are
+ %% lost.
+ c_seq(c_seq(E3, seq_arg(E2)), seq_body(E2));
+ false ->
+ c_seq(E3, E2)
+ end
+ end.
+
+%% Currently, safe expressions include variables, lambda expressions,
+%% constructors with safe subexpressions (this includes atoms, integers,
+%% empty lists, etc.), seq-, let- and letrec-expressions with safe
+%% subexpressions, try- and catch-expressions with safe subexpressions
+%% and calls to safe functions with safe argument subexpressions.
+%% Binaries seem too tricky to be considered.
+
+is_safe(E) ->
+ case is_data(E) of
+ true ->
+ is_safe_list(data_es(E));
+ false ->
+ case type(E) of
+ var ->
+ true;
+ 'fun' ->
+ true;
+ values ->
+ is_safe_list(values_es(E));
+ 'seq' ->
+ case is_safe(seq_arg(E)) of
+ true ->
+ is_safe(seq_body(E));
+ false ->
+ false
+ end;
+ 'let' ->
+ case is_safe(let_arg(E)) of
+ true ->
+ is_safe(let_body(E));
+ false ->
+ false
+ end;
+ letrec ->
+ is_safe(letrec_body(E));
+ 'try' ->
+ %% If the argument expression is not safe, it could
+ %% be modifying the state; thus, even if the body is
+ %% safe, the try-expression as a whole would not be.
+ %% If the argument is safe, the handler is not used.
+ case is_safe(try_arg(E)) of
+ true ->
+ is_safe(try_body(E));
+ false ->
+ false
+ end;
+ 'catch' ->
+ is_safe(catch_body(E));
+ call ->
+ M = call_module(E),
+ F = call_name(E),
+ case is_c_atom(M) and is_c_atom(F) of
+ true ->
+ As = call_args(E),
+ case is_safe_list(As) of
+ true ->
+ is_safe_call(atom_val(M),
+ atom_val(F),
+ length(As));
+ false ->
+ false
+ end;
+ false ->
+ false
+ end;
+ _ ->
+ false
+ end
+ end.
+
+is_safe_list([E | Es]) ->
+ case is_safe(E) of
+ true ->
+ is_safe_list(Es);
+ false ->
+ false
+ end;
+is_safe_list([]) ->
+ true.
+
+is_safe_call(M, F, A) ->
+ erl_bifs:is_safe(M, F, A).
+
+%% When setting up local variables, we only create new names if we have
+%% to, according to the "no-shadowing" strategy.
+
+make_locals(Vs, Ren, Env) ->
+ make_locals(Vs, [], Ren, Env).
+
+make_locals([V | Vs], As, Ren, Env) ->
+ Name = var_name(V),
+ case env__is_defined(Name, Env) of
+ false ->
+ %% The variable need not be renamed. Just make sure that the
+ %% renaming will map it to itself.
+ Name1 = Name,
+ Ren1 = ren__add_identity(Name, Ren);
+ true ->
+ %% The variable must be renamed to maintain the no-shadowing
+ %% invariant. Do the right thing for function variables.
+ Name1 = case Name of
+ {A, N} ->
+ env__new_fname(A, N, Env);
+ _ ->
+ env__new_vname(Env)
+ end,
+ Ren1 = ren__add(Name, Name1, Ren)
+ end,
+ %% This temporary binding is added for correct new-key generation.
+ Env1 = env__bind(Name1, dummy, Env),
+ make_locals(Vs, [Name1 | As], Ren1, Env1);
+make_locals([], As, Ren, Env) ->
+ {reverse(As), Ren, Env}.
+
+%% This adds let-bindings for the source code variables in `Es' to the
+%% environment `Env'.
+%%
+%% Note that we always assign a new state location for the
+%% residual-program variable, since we cannot know when a location for a
+%% particular variable in the source code can be reused.
+
+bind_locals(Vs, Ren, Env, S) ->
+ Opnds = lists:duplicate(length(Vs), undefined),
+ bind_locals(Vs, Opnds, Ren, Env, S).
+
+bind_locals(Vs, Opnds, Ren, Env, S) ->
+ {Ns, Ren1, Env1} = make_locals(Vs, Ren, Env),
+ {Rs, Env2, S1} = bind_locals_1(Ns, Opnds, [], Env1, S),
+ {Rs, Ren1, Env2, S1}.
+
+%% Note that the `Vs' are currently not used for anything except the
+%% number of variables. If we were maintaining "source-referenced"
+%% flags, then the flag in the new variable should be initialized to the
+%% current value of the (residual-) referenced-flag of the "parent".
+
+bind_locals_1([N | Ns], [Opnd | Opnds], Rs, Env, S) ->
+ {R, S1} = new_ref(N, Opnd, S),
+ Env1 = env__bind(N, R, Env),
+ bind_locals_1(Ns, Opnds, [R | Rs], Env1, S1);
+bind_locals_1([], [], Rs, Env, S) ->
+ {lists:reverse(Rs), Env, S}.
+
+new_refs(Ns, Opnds, S) ->
+ new_refs(Ns, Opnds, [], S).
+
+new_refs([N | Ns], [Opnd | Opnds], Rs, S) ->
+ {R, S1} = new_ref(N, Opnd, S),
+ new_refs(Ns, Opnds, [R | Rs], S1);
+new_refs([], [], Rs, S) ->
+ {lists:reverse(Rs), S}.
+
+new_ref(N, Opnd, S) ->
+ {L, S1} = st__new_ref_loc(S),
+ {#ref{name = N, opnd = Opnd, loc = L}, S1}.
+
+%% This adds recursive bindings for the source code variables in `Es' to
+%% the environment `Env'. Note that recursive binding of a set of
+%% variables is an atomic operation on the environment - they cannot be
+%% added one at a time.
+
+bind_recursive(Vs, Opnds, Ren, Env, S) ->
+ {Ns, Ren1, Env1} = make_locals(Vs, Ren, Env),
+ {Rs, S1} = new_refs(Ns, Opnds, S),
+
+ %% When this fun-expression is evaluated, it updates the operand
+ %% structure in the ref-structure to contain the recursively defined
+ %% environment and the correct renaming.
+ Fun = fun (R, Env) ->
+ Opnd = R#ref.opnd,
+ R#ref{opnd = Opnd#opnd{ren = Ren1, env = Env}}
+ end,
+ {Rs, Ren1, env__bind_recursive(Ns, Rs, Fun, Env1), S1}.
+
+safe_context(Ctxt) ->
+ case Ctxt of
+ #app{} ->
+ value;
+ _ ->
+ Ctxt
+ end.
+
+%% Note that the name of a variable encodes its type: a "plain" variable
+%% or a function variable. The latter kind also contains an arity number
+%% which should be preserved upon renaming.
+
+ref_to_var(#ref{name = Name}) ->
+ %% If we were maintaining "source-referenced" flags, the annotation
+ %% `add_ann([#source_ref{loc = L}], E)' should also be done here, to
+ %% make the algorithm reapplicable. This is however not necessary
+ %% since there are no destructive variable assignments in Erlang.
+ c_var(Name).
+
+%% Including the effort counter of the call site assures that the cost
+%% of processing an operand via `visit' is charged to the correct
+%% counter. In particular, if the effort counter of the call site was
+%% passive, the operands will also be processed with a passive counter.
+
+make_opnd(E, Ren, Env, S) ->
+ {L, S1} = st__new_opnd_loc(S),
+ C = st__get_effort(S1),
+ Opnd = #opnd{expr = E, ren = Ren, env = Env, loc = L, effort = C},
+ {Opnd, S1}.
+
+keep_referenced(Rs, S) ->
+ [R || R <- Rs, st__get_var_referenced(R#ref.loc, S)].
+
+residualize_operands(Opnds, E, S) ->
+ foldr(fun (Opnd, {E, S}) -> residualize_operand(Opnd, E, S) end,
+ {E, S}, Opnds).
+
+%% This is the only case where an operand expression can be visited in
+%% `effect' context instead of `value' context.
+
+residualize_operand(Opnd, E, S) ->
+ case st__get_opnd_effect(Opnd#opnd.loc, S) of
+ true ->
+ %% The operand has not been visited, so we do that now, but
+ %% in `effect' context. (Waddell's algoritm does some stuff
+ %% here to account specially for the operand size, which
+ %% appears unnecessary.)
+ {E1, S1} = i(Opnd#opnd.expr, effect, Opnd#opnd.ren,
+ Opnd#opnd.env, S),
+ {make_seq(E1, E), S1};
+ false ->
+ {E, S}
+ end.
+
+%% The `visit' function always visits the operand expression in `value'
+%% context (`residualize_operand' visits an unreferenced operand
+%% expression in `effect' context when necessary). A new passive size
+%% counter is used for visiting the operand, the final value of which is
+%% then cached along with the resulting expression.
+%%
+%% Note that the effort counter of the call site, included in the
+%% operand structure, is not a shared object. Thus, the effort budget is
+%% actually reused over all occurrences of the operands of a single
+%% application. This does not appear to be a problem; just a
+%% modification of the algorithm.
+
+visit(Opnd, S) ->
+ {C, S1} = visit_1(Opnd, S),
+ {C#cache.expr, S1}.
+
+visit_and_count_size(Opnd, S) ->
+ {C, S1} = visit_1(Opnd, S),
+ {C#cache.expr, count_size(C#cache.size, S1)}.
+
+visit_1(Opnd, S) ->
+ case st__lookup_opnd_cache(Opnd#opnd.loc, S) of
+ error ->
+ %% Use a new, passive, size counter for visiting operands,
+ %% and use the effort counter of the context of the operand.
+ %% It turns out that if the latter is active, it must be the
+ %% same object as the one currently used, and if it is
+ %% passive, it does not matter if it is the same object as
+ %% any other counter.
+ Effort = Opnd#opnd.effort,
+ Active = counter__is_active(Effort),
+ S1 = case Active of
+ true ->
+ S; % don't change effort counter
+ false ->
+ st__set_effort(Effort, S)
+ end,
+ S2 = new_passive_size(get_size_limit(S1), S1),
+
+ %% Visit the expression and cache the result, along with the
+ %% final value of the size counter.
+ {E, S3} = i(Opnd#opnd.expr, value, Opnd#opnd.ren,
+ Opnd#opnd.env, S2),
+ Size = get_size_value(S3),
+ C = #cache{expr = E, size = Size},
+ S4 = revert_size(S, st__set_opnd_cache(Opnd#opnd.loc, C,
+ S3)),
+ case Active of
+ true ->
+ {C, S4}; % keep using the same effort counter
+ false ->
+ {C, revert_effort(S, S4)}
+ end;
+ {ok, C} ->
+ {C, S}
+ end.
+
+%% Create a pattern matching template for an expression. A template
+%% contains only data constructors (including atomic ones) and
+%% variables, and compound literals are not folded into a single node.
+%% Each node in the template is annotated with the variable which holds
+%% the corresponding subexpression; these are new, unique variables not
+%% existing in the given `Env'. Returns `{Template, Variables, NewEnv}',
+%% where `Variables' is the list of all variables corresponding to nodes
+%% in the template *listed in reverse dependency order*, and `NewEnv' is
+%% `Env' augmented with mappings from the variable names to
+%% subexpressions of `E' (not #ref{} structures!) rewritten so that no
+%% computations are duplicated. `Variables' is guaranteed to be nonempty
+%% - at least the root node will always be bound to a new variable.
+
+make_template(E, Env) ->
+ make_template(E, [], Env).
+
+make_template(E, Vs0, Env0) ->
+ case is_data(E) of
+ true ->
+ {Ts, {Vs1, Env1}} = mapfoldl(
+ fun (E, {Vs0, Env0}) ->
+ {T, Vs1, Env1} =
+ make_template(E, Vs0,
+ Env0),
+ {T, {Vs1, Env1}}
+ end,
+ {Vs0, Env0}, data_es(E)),
+ T = make_data_skel(data_type(E), Ts),
+ E1 = update_data(E, data_type(E),
+ [hd(get_ann(T)) || T <- Ts]),
+ V = new_var(Env1),
+ Env2 = env__bind(var_name(V), E1, Env1),
+ {set_ann(T, [V]), [V | Vs1], Env2};
+ false ->
+ case type(E) of
+ seq ->
+ %% For a sequencing, we can rebind the variable used
+ %% for the body, and pass on the template as it is.
+ {T, Vs1, Env1} = make_template(seq_body(E), Vs0,
+ Env0),
+ V = var_name(hd(get_ann(T))),
+ E1 = update_c_seq(E, seq_arg(E), env__get(V, Env1)),
+ Env2 = env__bind(V, E1, Env1),
+ {T, Vs1, Env2};
+ _ ->
+ V = new_var(Env0),
+ Env1 = env__bind(var_name(V), E, Env0),
+ {set_ann(V, [V]), [V | Vs0], Env1}
+ end
+ end.
+
+%% Two clauses are equivalent if their bodies are equivalent expressions
+%% given that the respective pattern variables are local.
+
+equivalent_clauses([]) ->
+ true;
+equivalent_clauses([C | Cs]) ->
+ Env = cerl_trees:variables(c_values(clause_pats(C))),
+ equivalent_clauses_1(clause_body(C), Cs, Env).
+
+equivalent_clauses_1(E, [C | Cs], Env) ->
+ Env1 = cerl_trees:variables(c_values(clause_pats(C))),
+ case equivalent(E, clause_body(C), ordsets:union(Env, Env1)) of
+ true ->
+ equivalent_clauses_1(E, Cs, Env);
+ false ->
+ false
+ end;
+equivalent_clauses_1(_, [], _Env) ->
+ true.
+
+%% Two expressions are equivalent if and only if they yield the same
+%% value and has the same side effects in the same order. Currently, we
+%% only accept equality between constructors (constants) and nonlocal
+%% variables, since this should cover most cases of interest. If a
+%% variable is locally bound in one expression, it cannot be equivalent
+%% to one with the same name in the other expression, so we need not
+%% keep track of two environments.
+
+equivalent(E1, E2, Env) ->
+ case is_data(E1) of
+ true ->
+ case is_data(E2) of
+ true ->
+ T1 = {data_type(E1), data_arity(E1)},
+ T2 = {data_type(E2), data_arity(E2)},
+ %% Note that we must test for exact equality.
+ if T1 =:= T2 ->
+ equivalent_lists(data_es(E1), data_es(E2),
+ Env);
+ true ->
+ false
+ end;
+ false ->
+ false
+ end;
+ false ->
+ case type(E1) of
+ var ->
+ case is_c_var(E2) of
+ true ->
+ N1 = var_name(E1),
+ N2 = var_name(E2),
+ if N1 =:= N2 ->
+ not ordsets:is_element(N1, Env);
+ true ->
+ false
+ end;
+ false ->
+ false
+ end;
+ _ ->
+ %% Other constructs are not being considered.
+ false
+ end
+ end.
+
+equivalent_lists([E1 | Es1], [E2 | Es2], Env) ->
+ equivalent(E1, E2, Env) and equivalent_lists(Es1, Es2, Env);
+equivalent_lists([], [], _) ->
+ true;
+equivalent_lists(_, _, _) ->
+ false.
+
+%% Return `false' or `{true, EffectExpr, ValueExpr}'. The environment is
+%% passed for new-variable generation.
+
+reduce_bif_call(M, F, As, Env) ->
+ reduce_bif_call_1(M, F, length(As), As, Env).
+
+reduce_bif_call_1(erlang, element, 2, [X, Y], _Env) ->
+ case is_c_int(X) and is_c_tuple(Y) of
+ true ->
+ %% We are free to change the relative evaluation order of
+ %% the elements, so lifting out a particular element is OK.
+ T = list_to_tuple(tuple_es(Y)),
+ N = int_val(X),
+ if integer(N), N > 0, N =< size(T) ->
+ E = element(N, T),
+ Es = tuple_to_list(setelement(N, T, void())),
+ {true, make_seq(c_tuple(Es), E)};
+ true ->
+ false
+ end;
+ false ->
+ false
+ end;
+reduce_bif_call_1(erlang, hd, 1, [X], _Env) ->
+ case is_c_cons(X) of
+ true ->
+ %% Cf. `element/2' above.
+ {true, make_seq(cons_tl(X), cons_hd(X))};
+ false ->
+ false
+ end;
+reduce_bif_call_1(erlang, length, 1, [X], _Env) ->
+ case is_c_list(X) of
+ true ->
+ %% Cf. `erlang:size/1' below.
+ {true, make_seq(X, c_int(list_length(X)))};
+ false ->
+ false
+ end;
+reduce_bif_call_1(erlang, list_to_tuple, 1, [X], _Env) ->
+ case is_c_list(X) of
+ true ->
+ %% This does not actually preserve all the evaluation order
+ %% constraints of the list, but I don't imagine that it will
+ %% be a problem.
+ {true, c_tuple(list_elements(X))};
+ false ->
+ false
+ end;
+reduce_bif_call_1(erlang, setelement, 3, [X, Y, Z], Env) ->
+ case is_c_int(X) and is_c_tuple(Y) of
+ true ->
+ %% Here, unless `Z' is a simple expression, we must bind it
+ %% to a new variable, because in that case, `Z' must be
+ %% evaluated before any part of `Y'.
+ T = list_to_tuple(tuple_es(Y)),
+ N = int_val(X),
+ if integer(N), N > 0, N =< size(T) ->
+ E = element(N, T),
+ case is_simple(Z) of
+ true ->
+ Es = tuple_to_list(setelement(N, T, Z)),
+ {true, make_seq(E, c_tuple(Es))};
+ false ->
+ V = new_var(Env),
+ Es = tuple_to_list(setelement(N, T, V)),
+ E1 = make_seq(E, c_tuple(Es)),
+ {true, c_let([V], Z, E1)}
+ end;
+ true ->
+ false
+ end;
+ false ->
+ false
+ end;
+reduce_bif_call_1(erlang, size, 1, [X], _Env) ->
+ case is_c_tuple(X) of
+ true ->
+ %% Just evaluate the tuple for effect and use the size (the
+ %% arity) as the result.
+ {true, make_seq(X, c_int(tuple_arity(X)))};
+ false ->
+ false
+ end;
+reduce_bif_call_1(erlang, tl, 1, [X], _Env) ->
+ case is_c_cons(X) of
+ true ->
+ %% Cf. `element/2' above.
+ {true, make_seq(cons_hd(X), cons_tl(X))};
+ false ->
+ false
+ end;
+reduce_bif_call_1(erlang, tuple_to_list, 1, [X], _Env) ->
+ case is_c_tuple(X) of
+ true ->
+ %% This actually introduces slightly stronger constraints on
+ %% the evaluation order of the subexpressions.
+ {true, make_list(tuple_es(X))};
+ false ->
+ false
+ end;
+reduce_bif_call_1(_M, _F, _A, _As, _Env) ->
+ false.
+
+effort_is_active(S) ->
+ counter__is_active(st__get_effort(S)).
+
+size_is_active(S) ->
+ counter__is_active(st__get_size(S)).
+
+get_effort_limit(S) ->
+ counter__limit(st__get_effort(S)).
+
+new_active_effort(Limit, S) ->
+ st__set_effort(counter__new_active(Limit), S).
+
+revert_effort(S1, S2) ->
+ st__set_effort(st__get_effort(S1), S2).
+
+new_active_size(Limit, S) ->
+ st__set_size(counter__new_active(Limit), S).
+
+new_passive_size(Limit, S) ->
+ st__set_size(counter__new_passive(Limit), S).
+
+revert_size(S1, S2) ->
+ st__set_size(st__get_size(S1), S2).
+
+count_effort(N, S) ->
+ C = st__get_effort(S),
+ C1 = counter__add(N, C, effort, S),
+ case debug_counters() of
+ true ->
+ case counter__is_active(C1) of
+ true ->
+ V = counter__value(C1),
+ case V > get(counter_effort_max) of
+ true ->
+ put(counter_effort_max, V);
+ false ->
+ ok
+ end;
+ false ->
+ ok
+ end;
+ _ ->
+ ok
+ end,
+ st__set_effort(C1, S).
+
+count_size(N, S) ->
+ C = st__get_size(S),
+ C1 = counter__add(N, C, size, S),
+ case debug_counters() of
+ true ->
+ case counter__is_active(C1) of
+ true ->
+ V = counter__value(C1),
+ case V > get(counter_size_max) of
+ true ->
+ put(counter_size_max, V);
+ false ->
+ ok
+ end;
+ false ->
+ ok
+ end;
+ _ ->
+ ok
+ end,
+ st__set_size(C1, S).
+
+get_size_value(S) ->
+ counter__value(st__get_size(S)).
+
+get_size_limit(S) ->
+ counter__limit(st__get_size(S)).
+
+kill_id_anns([{'id',_} | As]) ->
+ kill_id_anns(As);
+kill_id_anns([A | As]) ->
+ [A | kill_id_anns(As)];
+kill_id_anns([]) ->
+ [].
+
+
+%% =====================================================================
+%% General utilities
+
+max(X, Y) when X > Y -> X;
+max(_, Y) -> Y.
+
+%% The atom `ok', is widely used in Erlang for "void" values.
+
+void() -> abstract(ok).
+
+is_simple(E) ->
+ case type(E) of
+ literal -> true;
+ var -> true;
+ 'fun' -> true;
+ _ -> false
+ end.
+
+get_components(N, E) ->
+ case type(E) of
+ values ->
+ Es = values_es(E),
+ if length(Es) == N ->
+ {true, Es};
+ true ->
+ false
+ end;
+ _ when N == 1 ->
+ {true, [E]};
+ _ ->
+ false
+ end.
+
+all_static([E | Es]) ->
+ case is_literal(result(E)) of
+ true ->
+ all_static(Es);
+ false ->
+ false
+ end;
+all_static([]) ->
+ true.
+
+set_clause_bodies([C | Cs], B) ->
+ [update_c_clause(C, clause_pats(C), clause_guard(C), B)
+ | set_clause_bodies(Cs, B)];
+set_clause_bodies([], _) ->
+ [].
+
+filename([C | T]) when integer(C), C > 0, C =< 255 ->
+ [C | filename(T)];
+filename([H|T]) ->
+ filename(H) ++ filename(T);
+filename([]) ->
+ [];
+filename(N) when atom(N) ->
+ atom_to_list(N);
+filename(N) ->
+ report_error("bad filename: `~P'.", [N, 25]),
+ exit(error).
+
+
+%% =====================================================================
+%% Abstract datatype: renaming()
+
+ren__identity() ->
+ dict:new().
+
+ren__add(X, Y, Ren) ->
+ dict:store(X, Y, Ren).
+
+ren__map(X, Ren) ->
+ case dict:find(X, Ren) of
+ {ok, Y} ->
+ Y;
+ error ->
+ X
+ end.
+
+ren__add_identity(X, Ren) ->
+ dict:erase(X, Ren).
+
+
+%% =====================================================================
+%% Abstract datatype: environment()
+
+env__empty() ->
+ rec_env:empty().
+
+env__bind(Key, Val, Env) ->
+ rec_env:bind(Key, Val, Env).
+
+%% `Es' should have type `[{Key, Val}]', and `Fun' should have type
+%% `(Val, Env) -> T', mapping a value together with the recursive
+%% environment itself to some term `T' to be returned when the entry is
+%% looked up.
+
+env__bind_recursive(Ks, Vs, F, Env) ->
+ rec_env:bind_recursive(Ks, Vs, F, Env).
+
+env__lookup(Key, Env) ->
+ rec_env:lookup(Key, Env).
+
+env__get(Key, Env) ->
+ rec_env:get(Key, Env).
+
+env__is_defined(Key, Env) ->
+ rec_env:is_defined(Key, Env).
+
+env__new_vname(Env) ->
+ rec_env:new_key(Env).
+
+env__new_fname(A, N, Env) ->
+ rec_env:new_key(fun (X) ->
+ S = integer_to_list(X),
+ {list_to_atom(atom_to_list(A) ++ "_" ++ S),
+ N}
+ end, Env).
+
+
+%% =====================================================================
+%% Abstract datatype: state()
+
+-record(state, {free, % next free location
+ size, % size counter
+ effort, % effort counter
+ cache, % operand expression cache
+ var_flags, % flags for variables (#ref-structures)
+ opnd_flags, % flags for operands
+ app_flags}). % flags for #app-structures
+
+%% Note that we do not have a `var_assigned' flag, since there is no
+%% destructive assignment in Erlang. In the original algorithm, the
+%% "residual-referenced"-flags of the previous inlining pass (or
+%% initialization pass) are used as the "source-referenced"-flags for
+%% the subsequent pass. The latter may then be used as a safe
+%% approximation whenever we need to base a decision on whether or not a
+%% particular variable or function variable could be referenced in the
+%% program being generated, and computation of the new
+%% "residual-referenced" flag for that variable is not yet finished. In
+%% the present algorithm, this can only happen in the presence of
+%% variable assignments, which do not exist in Erlang. Therefore, we do
+%% not keep "source-referenced" flags for residual-code references in
+%% our implementation.
+%%
+%% The "inner-pending" flag tells us whether we are already in the
+%% process of visiting a particular operand, and the "outer-pending"
+%% flag whether we are in the process of inlining a propagated
+%% functional value. The "pending flags" are really counters limiting
+%% the number of times an operand may be inlined recursively, causing
+%% loop unrolling; however, unrolling more than one iteration does not
+%% work offhand in the present implementation. (TODO: find out why.)
+%% Note that the initial value must be greater than zero in order for
+%% any inlining at all to be done.
+
+%% Flags are stored in ETS-tables, one table for each class. The second
+%% element in each stored tuple is the key (the "label").
+
+-record(var_flags, {lab, referenced = false}).
+-record(opnd_flags, {lab, inner_pending = 1, outer_pending = 1,
+ effect = false}).
+-record(app_flags, {lab, inlined = false}).
+
+st__new(Effort, Size) ->
+ #state{free = 0,
+ size = counter__new_passive(Size),
+ effort = counter__new_passive(Effort),
+ cache = dict:new(),
+ var_flags = ets:new(var, [set, private, {keypos, 2}]),
+ opnd_flags = ets:new(opnd, [set, private, {keypos, 2}]),
+ app_flags = ets:new(app, [set, private, {keypos, 2}])}.
+
+st__new_loc(S) ->
+ N = S#state.free,
+ {N, S#state{free = N + 1}}.
+
+st__get_effort(S) ->
+ S#state.effort.
+
+st__set_effort(C, S) ->
+ S#state{effort = C}.
+
+st__get_size(S) ->
+ S#state.size.
+
+st__set_size(C, S) ->
+ S#state{size = C}.
+
+st__set_var_referenced(L, S) ->
+ T = S#state.var_flags,
+ [F] = ets:lookup(T, L),
+ ets:insert(T, F#var_flags{referenced = true}),
+ S.
+
+st__get_var_referenced(L, S) ->
+ ets:lookup_element(S#state.var_flags, L, #var_flags.referenced).
+
+st__lookup_opnd_cache(L, S) ->
+ dict:find(L, S#state.cache).
+
+%% Note that setting the cache should only be done once.
+
+st__set_opnd_cache(L, C, S) ->
+ S#state{cache = dict:store(L, C, S#state.cache)}.
+
+st__set_opnd_effect(L, S) ->
+ T = S#state.opnd_flags,
+ [F] = ets:lookup(T, L),
+ ets:insert(T, F#opnd_flags{effect = true}),
+ S.
+
+st__get_opnd_effect(L, S) ->
+ ets:lookup_element(S#state.opnd_flags, L, #opnd_flags.effect).
+
+st__set_app_inlined(L, S) ->
+ T = S#state.app_flags,
+ [F] = ets:lookup(T, L),
+ ets:insert(T, F#app_flags{inlined = true}),
+ S.
+
+st__clear_app_inlined(L, S) ->
+ T = S#state.app_flags,
+ [F] = ets:lookup(T, L),
+ ets:insert(T, F#app_flags{inlined = false}),
+ S.
+
+st__get_app_inlined(L, S) ->
+ ets:lookup_element(S#state.app_flags, L, #app_flags.inlined).
+
+%% The pending-flags are initialized by `st__new_opnd_loc' below.
+
+st__test_inner_pending(L, S) ->
+ T = S#state.opnd_flags,
+ P = ets:lookup_element(T, L, #opnd_flags.inner_pending),
+ P =< 0.
+
+st__mark_inner_pending(L, S) ->
+ ets:update_counter(S#state.opnd_flags, L,
+ {#opnd_flags.inner_pending, -1}),
+ S.
+
+st__clear_inner_pending(L, S) ->
+ ets:update_counter(S#state.opnd_flags, L,
+ {#opnd_flags.inner_pending, 1}),
+ S.
+
+st__test_outer_pending(L, S) ->
+ T = S#state.opnd_flags,
+ P = ets:lookup_element(T, L, #opnd_flags.outer_pending),
+ P =< 0.
+
+st__mark_outer_pending(L, S) ->
+ ets:update_counter(S#state.opnd_flags, L,
+ {#opnd_flags.outer_pending, -1}),
+ S.
+
+st__clear_outer_pending(L, S) ->
+ ets:update_counter(S#state.opnd_flags, L,
+ {#opnd_flags.outer_pending, 1}),
+ S.
+
+st__new_app_loc(S) ->
+ V = {L, _S1} = st__new_loc(S),
+ ets:insert(S#state.app_flags, #app_flags{lab = L}),
+ V.
+
+st__new_ref_loc(S) ->
+ V = {L, _S1} = st__new_loc(S),
+ ets:insert(S#state.var_flags, #var_flags{lab = L}),
+ V.
+
+st__new_opnd_loc(S) ->
+ V = {L, _S1} = st__new_loc(S),
+ ets:insert(S#state.opnd_flags, #opnd_flags{lab = L}),
+ V.
+
+
+%% =====================================================================
+%% Abstract datatype: counter()
+%%
+%% `counter__add' throws `{counter_exceeded, Type, Data}' if the
+%% resulting counter value would exceed the limit for the counter in
+%% question (`Type' and `Data' are given by the user).
+
+-record(counter, {active, value, limit}).
+
+counter__new_passive(Limit) when Limit > 0 ->
+ {0, Limit}.
+
+counter__new_active(Limit) when Limit > 0 ->
+ {Limit, Limit}.
+
+%% Active counters have values > 0 internally; passive counters start at
+%% zero. The 'limit' field is only accessed by the 'counter__limit'
+%% function.
+
+counter__is_active({C, _}) ->
+ C > 0.
+
+counter__limit({_, L}) ->
+ L.
+
+counter__value({N, L}) ->
+ if N > 0 ->
+ L - N;
+ true ->
+ -N
+ end.
+
+counter__add(N, {V, L}, Type, Data) ->
+ N1 = V - N,
+ if V > 0, N1 =< 0 ->
+ case debug_counters() of
+ true ->
+ case Type of
+ effort ->
+ put(counter_effort_triggers,
+ get(counter_effort_triggers) + 1);
+ size ->
+ put(counter_size_triggers,
+ get(counter_size_triggers) + 1)
+ end;
+ _ ->
+ ok
+ end,
+ throw({counter_exceeded, Type, Data});
+ true ->
+ {N1, L}
+ end.
+
+
+%% =====================================================================
+%% Reporting
+
+% report_internal_error(S) ->
+% report_internal_error(S, []).
+
+report_internal_error(S, Vs) ->
+ report_error("internal error: " ++ S, Vs).
+
+report_error(D) ->
+ report_error(D, []).
+
+report_error({F, L, D}, Vs) ->
+ report({F, L, {error, D}}, Vs);
+report_error(D, Vs) ->
+ report({error, D}, Vs).
+
+report_warning(D) ->
+ report_warning(D, []).
+
+report_warning({F, L, D}, Vs) ->
+ report({F, L, {warning, D}}, Vs);
+report_warning(D, Vs) ->
+ report({warning, D}, Vs).
+
+report(D, Vs) ->
+ io:put_chars(format(D, Vs)).
+
+format({error, D}, Vs) ->
+ ["error: ", format(D, Vs)];
+format({warning, D}, Vs) ->
+ ["warning: ", format(D, Vs)];
+format({"", L, D}, Vs) when integer(L), L > 0 ->
+ [io_lib:fwrite("~w: ", [L]), format(D, Vs)];
+format({"", _L, D}, Vs) ->
+ format(D, Vs);
+format({F, L, D}, Vs) when integer(L), L > 0 ->
+ [io_lib:fwrite("~s:~w: ", [filename(F), L]), format(D, Vs)];
+format({F, _L, D}, Vs) ->
+ [io_lib:fwrite("~s: ", [filename(F)]), format(D, Vs)];
+format(S, Vs) when list(S) ->
+ [io_lib:fwrite(S, Vs), $\n].
+
+
+%% =====================================================================
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl_trees.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl_trees.erl
new file mode 100644
index 0000000000..afe7c8708b
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl_trees.erl
@@ -0,0 +1,801 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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 Richard Carlsson.
+%% Copyright (C) 1999-2002 Richard Carlsson.
+%% Portions created by Ericsson are Copyright 2001, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%%
+%% $Id: cerl_trees.erl,v 1.2 2010/06/07 06:32:39 kostis Exp $
+
+%% @doc Basic functions on Core Erlang abstract syntax trees.
+%%
+%% <p>Syntax trees are defined in the module <a
+%% href=""><code>cerl</code></a>.</p>
+%%
+%% @type cerl() = cerl:cerl()
+
+-module(cerl_trees).
+
+-export([depth/1, fold/3, free_variables/1, label/1, label/2, map/2,
+ mapfold/3, size/1, variables/1]).
+
+-import(cerl, [alias_pat/1, alias_var/1, ann_c_alias/3, ann_c_apply/3,
+ ann_c_binary/2, ann_c_bitstr/6, ann_c_call/4,
+ ann_c_case/3, ann_c_catch/2, ann_c_clause/4,
+ ann_c_cons_skel/3, ann_c_fun/3, ann_c_let/4,
+ ann_c_letrec/3, ann_c_module/5, ann_c_primop/3,
+ ann_c_receive/4, ann_c_seq/3, ann_c_try/6,
+ ann_c_tuple_skel/2, ann_c_values/2, apply_args/1,
+ apply_op/1, binary_segments/1, bitstr_val/1,
+ bitstr_size/1, bitstr_unit/1, bitstr_type/1,
+ bitstr_flags/1, call_args/1, call_module/1, call_name/1,
+ case_arg/1, case_clauses/1, catch_body/1, clause_body/1,
+ clause_guard/1, clause_pats/1, clause_vars/1, concrete/1,
+ cons_hd/1, cons_tl/1, fun_body/1, fun_vars/1, get_ann/1,
+ let_arg/1, let_body/1, let_vars/1, letrec_body/1,
+ letrec_defs/1, letrec_vars/1, module_attrs/1,
+ module_defs/1, module_exports/1, module_name/1,
+ module_vars/1, primop_args/1, primop_name/1,
+ receive_action/1, receive_clauses/1, receive_timeout/1,
+ seq_arg/1, seq_body/1, set_ann/2, subtrees/1, try_arg/1,
+ try_body/1, try_vars/1, try_evars/1, try_handler/1,
+ tuple_es/1, type/1, update_c_alias/3, update_c_apply/3,
+ update_c_binary/2, update_c_bitstr/6, update_c_call/4,
+ update_c_case/3, update_c_catch/2, update_c_clause/4,
+ update_c_cons/3, update_c_cons_skel/3, update_c_fun/3,
+ update_c_let/4, update_c_letrec/3, update_c_module/5,
+ update_c_primop/3, update_c_receive/4, update_c_seq/3,
+ update_c_try/6, update_c_tuple/2, update_c_tuple_skel/2,
+ update_c_values/2, values_es/1, var_name/1]).
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec depth(Tree::cerl) -> integer()
+%%
+%% @doc Returns the length of the longest path in the tree. A leaf
+%% node has depth zero, the tree representing "<code>{foo,
+%% bar}</code>" has depth one, etc.
+
+depth(T) ->
+ case subtrees(T) of
+ [] ->
+ 0;
+ Gs ->
+ 1 + lists:foldl(fun (G, A) -> erlang:max(depth_1(G), A) end, 0, Gs)
+ end.
+
+depth_1(Ts) ->
+ lists:foldl(fun (T, A) -> erlang:max(depth(T), A) end, 0, Ts).
+
+%% max(X, Y) when X > Y -> X;
+%% max(_, Y) -> Y.
+
+
+%% @spec size(Tree::cerl()) -> integer()
+%%
+%% @doc Returns the number of nodes in <code>Tree</code>.
+
+size(T) ->
+ fold(fun (_, S) -> S + 1 end, 0, T).
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec map(Function, Tree::cerl()) -> cerl()
+%%
+%% Function = (cerl()) -> cerl()
+%%
+%% @doc Maps a function onto the nodes of a tree. This replaces each
+%% node in the tree by the result of applying the given function on
+%% the original node, bottom-up.
+%%
+%% @see mapfold/3
+
+map(F, T) ->
+ F(map_1(F, T)).
+
+map_1(F, T) ->
+ case type(T) of
+ literal ->
+ case concrete(T) of
+ [_ | _] ->
+ update_c_cons(T, map(F, cons_hd(T)),
+ map(F, cons_tl(T)));
+ V when tuple_size(V) > 0 ->
+ update_c_tuple(T, map_list(F, tuple_es(T)));
+ _ ->
+ T
+ end;
+ var ->
+ T;
+ values ->
+ update_c_values(T, map_list(F, values_es(T)));
+ cons ->
+ update_c_cons_skel(T, map(F, cons_hd(T)),
+ map(F, cons_tl(T)));
+ tuple ->
+ update_c_tuple_skel(T, map_list(F, tuple_es(T)));
+ 'let' ->
+ update_c_let(T, map_list(F, let_vars(T)),
+ map(F, let_arg(T)),
+ map(F, let_body(T)));
+ seq ->
+ update_c_seq(T, map(F, seq_arg(T)),
+ map(F, seq_body(T)));
+ apply ->
+ update_c_apply(T, map(F, apply_op(T)),
+ map_list(F, apply_args(T)));
+ call ->
+ update_c_call(T, map(F, call_module(T)),
+ map(F, call_name(T)),
+ map_list(F, call_args(T)));
+ primop ->
+ update_c_primop(T, map(F, primop_name(T)),
+ map_list(F, primop_args(T)));
+ 'case' ->
+ update_c_case(T, map(F, case_arg(T)),
+ map_list(F, case_clauses(T)));
+ clause ->
+ update_c_clause(T, map_list(F, clause_pats(T)),
+ map(F, clause_guard(T)),
+ map(F, clause_body(T)));
+ alias ->
+ update_c_alias(T, map(F, alias_var(T)),
+ map(F, alias_pat(T)));
+ 'fun' ->
+ update_c_fun(T, map_list(F, fun_vars(T)),
+ map(F, fun_body(T)));
+ 'receive' ->
+ update_c_receive(T, map_list(F, receive_clauses(T)),
+ map(F, receive_timeout(T)),
+ map(F, receive_action(T)));
+ 'try' ->
+ update_c_try(T, map(F, try_arg(T)),
+ map_list(F, try_vars(T)),
+ map(F, try_body(T)),
+ map_list(F, try_evars(T)),
+ map(F, try_handler(T)));
+ 'catch' ->
+ update_c_catch(T, map(F, catch_body(T)));
+ binary ->
+ update_c_binary(T, map_list(F, binary_segments(T)));
+ bitstr ->
+ update_c_bitstr(T, map(F, bitstr_val(T)),
+ map(F, bitstr_size(T)),
+ map(F, bitstr_unit(T)),
+ map(F, bitstr_type(T)),
+ map(F, bitstr_flags(T)));
+ letrec ->
+ update_c_letrec(T, map_pairs(F, letrec_defs(T)),
+ map(F, letrec_body(T)));
+ module ->
+ update_c_module(T, map(F, module_name(T)),
+ map_list(F, module_exports(T)),
+ map_pairs(F, module_attrs(T)),
+ map_pairs(F, module_defs(T)))
+ end.
+
+map_list(F, [T | Ts]) ->
+ [map(F, T) | map_list(F, Ts)];
+map_list(_, []) ->
+ [].
+
+map_pairs(F, [{T1, T2} | Ps]) ->
+ [{map(F, T1), map(F, T2)} | map_pairs(F, Ps)];
+map_pairs(_, []) ->
+ [].
+
+
+%% @spec fold(Function, Unit::term(), Tree::cerl()) -> term()
+%%
+%% Function = (cerl(), term()) -> term()
+%%
+%% @doc Does a fold operation over the nodes of the tree. The result
+%% is the value of <code>Function(X1, Function(X2, ... Function(Xn,
+%% Unit) ... ))</code>, where <code>X1, ..., Xn</code> are the nodes
+%% of <code>Tree</code> in a post-order traversal.
+%%
+%% @see mapfold/3
+
+fold(F, S, T) ->
+ F(T, fold_1(F, S, T)).
+
+fold_1(F, S, T) ->
+ case type(T) of
+ literal ->
+ case concrete(T) of
+ [_ | _] ->
+ fold(F, fold(F, S, cons_hd(T)), cons_tl(T));
+ V when tuple_size(V) > 0 ->
+ fold_list(F, S, tuple_es(T));
+ _ ->
+ S
+ end;
+ var ->
+ S;
+ values ->
+ fold_list(F, S, values_es(T));
+ cons ->
+ fold(F, fold(F, S, cons_hd(T)), cons_tl(T));
+ tuple ->
+ fold_list(F, S, tuple_es(T));
+ 'let' ->
+ fold(F, fold(F, fold_list(F, S, let_vars(T)),
+ let_arg(T)),
+ let_body(T));
+ seq ->
+ fold(F, fold(F, S, seq_arg(T)), seq_body(T));
+ apply ->
+ fold_list(F, fold(F, S, apply_op(T)), apply_args(T));
+ call ->
+ fold_list(F, fold(F, fold(F, S, call_module(T)),
+ call_name(T)),
+ call_args(T));
+ primop ->
+ fold_list(F, fold(F, S, primop_name(T)), primop_args(T));
+ 'case' ->
+ fold_list(F, fold(F, S, case_arg(T)), case_clauses(T));
+ clause ->
+ fold(F, fold(F, fold_list(F, S, clause_pats(T)),
+ clause_guard(T)),
+ clause_body(T));
+ alias ->
+ fold(F, fold(F, S, alias_var(T)), alias_pat(T));
+ 'fun' ->
+ fold(F, fold_list(F, S, fun_vars(T)), fun_body(T));
+ 'receive' ->
+ fold(F, fold(F, fold_list(F, S, receive_clauses(T)),
+ receive_timeout(T)),
+ receive_action(T));
+ 'try' ->
+ fold(F, fold_list(F, fold(F, fold_list(F, fold(F, S, try_arg(T)),
+ try_vars(T)),
+ try_body(T)),
+ try_evars(T)),
+ try_handler(T));
+ 'catch' ->
+ fold(F, S, catch_body(T));
+ binary ->
+ fold_list(F, S, binary_segments(T));
+ bitstr ->
+ fold(F,
+ fold(F,
+ fold(F,
+ fold(F,
+ fold(F, S, bitstr_val(T)),
+ bitstr_size(T)),
+ bitstr_unit(T)),
+ bitstr_type(T)),
+ bitstr_flags(T));
+ letrec ->
+ fold(F, fold_pairs(F, S, letrec_defs(T)), letrec_body(T));
+ module ->
+ fold_pairs(F,
+ fold_pairs(F,
+ fold_list(F,
+ fold(F, S, module_name(T)),
+ module_exports(T)),
+ module_attrs(T)),
+ module_defs(T))
+ end.
+
+fold_list(F, S, [T | Ts]) ->
+ fold_list(F, fold(F, S, T), Ts);
+fold_list(_, S, []) ->
+ S.
+
+fold_pairs(F, S, [{T1, T2} | Ps]) ->
+ fold_pairs(F, fold(F, fold(F, S, T1), T2), Ps);
+fold_pairs(_, S, []) ->
+ S.
+
+
+%% @spec mapfold(Function, Initial::term(), Tree::cerl()) ->
+%% {cerl(), term()}
+%%
+%% Function = (cerl(), term()) -> {cerl(), term()}
+%%
+%% @doc Does a combined map/fold operation on the nodes of the
+%% tree. This is similar to <code>map/2</code>, but also propagates a
+%% value from each application of <code>Function</code> to the next,
+%% starting with the given value <code>Initial</code>, while doing a
+%% post-order traversal of the tree, much like <code>fold/3</code>.
+%%
+%% @see map/2
+%% @see fold/3
+
+mapfold(F, S0, T) ->
+ case type(T) of
+ literal ->
+ case concrete(T) of
+ [_ | _] ->
+ {T1, S1} = mapfold(F, S0, cons_hd(T)),
+ {T2, S2} = mapfold(F, S1, cons_tl(T)),
+ F(update_c_cons(T, T1, T2), S2);
+ V when tuple_size(V) > 0 ->
+ {Ts, S1} = mapfold_list(F, S0, tuple_es(T)),
+ F(update_c_tuple(T, Ts), S1);
+ _ ->
+ F(T, S0)
+ end;
+ var ->
+ F(T, S0);
+ values ->
+ {Ts, S1} = mapfold_list(F, S0, values_es(T)),
+ F(update_c_values(T, Ts), S1);
+ cons ->
+ {T1, S1} = mapfold(F, S0, cons_hd(T)),
+ {T2, S2} = mapfold(F, S1, cons_tl(T)),
+ F(update_c_cons_skel(T, T1, T2), S2);
+ tuple ->
+ {Ts, S1} = mapfold_list(F, S0, tuple_es(T)),
+ F(update_c_tuple_skel(T, Ts), S1);
+ 'let' ->
+ {Vs, S1} = mapfold_list(F, S0, let_vars(T)),
+ {A, S2} = mapfold(F, S1, let_arg(T)),
+ {B, S3} = mapfold(F, S2, let_body(T)),
+ F(update_c_let(T, Vs, A, B), S3);
+ seq ->
+ {A, S1} = mapfold(F, S0, seq_arg(T)),
+ {B, S2} = mapfold(F, S1, seq_body(T)),
+ F(update_c_seq(T, A, B), S2);
+ apply ->
+ {E, S1} = mapfold(F, S0, apply_op(T)),
+ {As, S2} = mapfold_list(F, S1, apply_args(T)),
+ F(update_c_apply(T, E, As), S2);
+ call ->
+ {M, S1} = mapfold(F, S0, call_module(T)),
+ {N, S2} = mapfold(F, S1, call_name(T)),
+ {As, S3} = mapfold_list(F, S2, call_args(T)),
+ F(update_c_call(T, M, N, As), S3);
+ primop ->
+ {N, S1} = mapfold(F, S0, primop_name(T)),
+ {As, S2} = mapfold_list(F, S1, primop_args(T)),
+ F(update_c_primop(T, N, As), S2);
+ 'case' ->
+ {A, S1} = mapfold(F, S0, case_arg(T)),
+ {Cs, S2} = mapfold_list(F, S1, case_clauses(T)),
+ F(update_c_case(T, A, Cs), S2);
+ clause ->
+ {Ps, S1} = mapfold_list(F, S0, clause_pats(T)),
+ {G, S2} = mapfold(F, S1, clause_guard(T)),
+ {B, S3} = mapfold(F, S2, clause_body(T)),
+ F(update_c_clause(T, Ps, G, B), S3);
+ alias ->
+ {V, S1} = mapfold(F, S0, alias_var(T)),
+ {P, S2} = mapfold(F, S1, alias_pat(T)),
+ F(update_c_alias(T, V, P), S2);
+ 'fun' ->
+ {Vs, S1} = mapfold_list(F, S0, fun_vars(T)),
+ {B, S2} = mapfold(F, S1, fun_body(T)),
+ F(update_c_fun(T, Vs, B), S2);
+ 'receive' ->
+ {Cs, S1} = mapfold_list(F, S0, receive_clauses(T)),
+ {E, S2} = mapfold(F, S1, receive_timeout(T)),
+ {A, S3} = mapfold(F, S2, receive_action(T)),
+ F(update_c_receive(T, Cs, E, A), S3);
+ 'try' ->
+ {E, S1} = mapfold(F, S0, try_arg(T)),
+ {Vs, S2} = mapfold_list(F, S1, try_vars(T)),
+ {B, S3} = mapfold(F, S2, try_body(T)),
+ {Evs, S4} = mapfold_list(F, S3, try_evars(T)),
+ {H, S5} = mapfold(F, S4, try_handler(T)),
+ F(update_c_try(T, E, Vs, B, Evs, H), S5);
+ 'catch' ->
+ {B, S1} = mapfold(F, S0, catch_body(T)),
+ F(update_c_catch(T, B), S1);
+ binary ->
+ {Ds, S1} = mapfold_list(F, S0, binary_segments(T)),
+ F(update_c_binary(T, Ds), S1);
+ bitstr ->
+ {Val, S1} = mapfold(F, S0, bitstr_val(T)),
+ {Size, S2} = mapfold(F, S1, bitstr_size(T)),
+ {Unit, S3} = mapfold(F, S2, bitstr_unit(T)),
+ {Type, S4} = mapfold(F, S3, bitstr_type(T)),
+ {Flags, S5} = mapfold(F, S4, bitstr_flags(T)),
+ F(update_c_bitstr(T, Val, Size, Unit, Type, Flags), S5);
+ letrec ->
+ {Ds, S1} = mapfold_pairs(F, S0, letrec_defs(T)),
+ {B, S2} = mapfold(F, S1, letrec_body(T)),
+ F(update_c_letrec(T, Ds, B), S2);
+ module ->
+ {N, S1} = mapfold(F, S0, module_name(T)),
+ {Es, S2} = mapfold_list(F, S1, module_exports(T)),
+ {As, S3} = mapfold_pairs(F, S2, module_attrs(T)),
+ {Ds, S4} = mapfold_pairs(F, S3, module_defs(T)),
+ F(update_c_module(T, N, Es, As, Ds), S4)
+ end.
+
+mapfold_list(F, S0, [T | Ts]) ->
+ {T1, S1} = mapfold(F, S0, T),
+ {Ts1, S2} = mapfold_list(F, S1, Ts),
+ {[T1 | Ts1], S2};
+mapfold_list(_, S, []) ->
+ {[], S}.
+
+mapfold_pairs(F, S0, [{T1, T2} | Ps]) ->
+ {T3, S1} = mapfold(F, S0, T1),
+ {T4, S2} = mapfold(F, S1, T2),
+ {Ps1, S3} = mapfold_pairs(F, S2, Ps),
+ {[{T3, T4} | Ps1], S3};
+mapfold_pairs(_, S, []) ->
+ {[], S}.
+
+
+%% ---------------------------------------------------------------------
+
+%% @spec variables(Tree::cerl()) -> [var_name()]
+%%
+%% var_name() = integer() | atom() | {atom(), integer()}
+%%
+%% @doc Returns an ordered-set list of the names of all variables in
+%% the syntax tree. (This includes function name variables.) An
+%% exception is thrown if <code>Tree</code> does not represent a
+%% well-formed Core Erlang syntax tree.
+%%
+%% @see free_variables/1
+
+variables(T) ->
+ variables(T, false).
+
+
+%% @spec free_variables(Tree::cerl()) -> [var_name()]
+%%
+%% @doc Like <code>variables/1</code>, but only includes variables
+%% that are free in the tree.
+%%
+%% @see variables/1
+
+free_variables(T) ->
+ variables(T, true).
+
+
+%% This is not exported
+
+variables(T, S) ->
+ case type(T) of
+ literal ->
+ [];
+ var ->
+ [var_name(T)];
+ values ->
+ vars_in_list(values_es(T), S);
+ cons ->
+ ordsets:union(variables(cons_hd(T), S),
+ variables(cons_tl(T), S));
+ tuple ->
+ vars_in_list(tuple_es(T), S);
+ 'let' ->
+ Vs = variables(let_body(T), S),
+ Vs1 = var_list_names(let_vars(T)),
+ Vs2 = case S of
+ true ->
+ ordsets:subtract(Vs, Vs1);
+ false ->
+ ordsets:union(Vs, Vs1)
+ end,
+ ordsets:union(variables(let_arg(T), S), Vs2);
+ seq ->
+ ordsets:union(variables(seq_arg(T), S),
+ variables(seq_body(T), S));
+ apply ->
+ ordsets:union(
+ variables(apply_op(T), S),
+ vars_in_list(apply_args(T), S));
+ call ->
+ ordsets:union(variables(call_module(T), S),
+ ordsets:union(
+ variables(call_name(T), S),
+ vars_in_list(call_args(T), S)));
+ primop ->
+ vars_in_list(primop_args(T), S);
+ 'case' ->
+ ordsets:union(variables(case_arg(T), S),
+ vars_in_list(case_clauses(T), S));
+ clause ->
+ Vs = ordsets:union(variables(clause_guard(T), S),
+ variables(clause_body(T), S)),
+ Vs1 = vars_in_list(clause_pats(T), S),
+ case S of
+ true ->
+ ordsets:subtract(Vs, Vs1);
+ false ->
+ ordsets:union(Vs, Vs1)
+ end;
+ alias ->
+ ordsets:add_element(var_name(alias_var(T)),
+ variables(alias_pat(T)));
+ 'fun' ->
+ Vs = variables(fun_body(T), S),
+ Vs1 = var_list_names(fun_vars(T)),
+ case S of
+ true ->
+ ordsets:subtract(Vs, Vs1);
+ false ->
+ ordsets:union(Vs, Vs1)
+ end;
+ 'receive' ->
+ ordsets:union(
+ vars_in_list(receive_clauses(T), S),
+ ordsets:union(variables(receive_timeout(T), S),
+ variables(receive_action(T), S)));
+ 'try' ->
+ Vs = variables(try_body(T), S),
+ Vs1 = var_list_names(try_vars(T)),
+ Vs2 = case S of
+ true ->
+ ordsets:subtract(Vs, Vs1);
+ false ->
+ ordsets:union(Vs, Vs1)
+ end,
+ Vs3 = variables(try_handler(T), S),
+ Vs4 = var_list_names(try_evars(T)),
+ Vs5 = case S of
+ true ->
+ ordsets:subtract(Vs3, Vs4);
+ false ->
+ ordsets:union(Vs3, Vs4)
+ end,
+ ordsets:union(variables(try_arg(T), S),
+ ordsets:union(Vs2, Vs5));
+ 'catch' ->
+ variables(catch_body(T), S);
+ binary ->
+ vars_in_list(binary_segments(T), S);
+ bitstr ->
+ ordsets:union(variables(bitstr_val(T), S),
+ variables(bitstr_size(T), S));
+ letrec ->
+ Vs = vars_in_defs(letrec_defs(T), S),
+ Vs1 = ordsets:union(variables(letrec_body(T), S), Vs),
+ Vs2 = var_list_names(letrec_vars(T)),
+ case S of
+ true ->
+ ordsets:subtract(Vs1, Vs2);
+ false ->
+ ordsets:union(Vs1, Vs2)
+ end;
+ module ->
+ Vs = vars_in_defs(module_defs(T), S),
+ Vs1 = ordsets:union(vars_in_list(module_exports(T), S), Vs),
+ Vs2 = var_list_names(module_vars(T)),
+ case S of
+ true ->
+ ordsets:subtract(Vs1, Vs2);
+ false ->
+ ordsets:union(Vs1, Vs2)
+ end
+ end.
+
+vars_in_list(Ts, S) ->
+ vars_in_list(Ts, S, []).
+
+vars_in_list([T | Ts], S, A) ->
+ vars_in_list(Ts, S, ordsets:union(variables(T, S), A));
+vars_in_list([], _, A) ->
+ A.
+
+%% Note that this function only visits the right-hand side of function
+%% definitions.
+
+vars_in_defs(Ds, S) ->
+ vars_in_defs(Ds, S, []).
+
+vars_in_defs([{_, F} | Ds], S, A) ->
+ vars_in_defs(Ds, S, ordsets:union(variables(F, S), A));
+vars_in_defs([], _, A) ->
+ A.
+
+%% This amounts to insertion sort. Since the lists are generally short,
+%% it is hardly worthwhile to use an asymptotically better sort.
+
+var_list_names(Vs) ->
+ var_list_names(Vs, []).
+
+var_list_names([V | Vs], A) ->
+ var_list_names(Vs, ordsets:add_element(var_name(V), A));
+var_list_names([], A) ->
+ A.
+
+
+%% ---------------------------------------------------------------------
+
+%% label(Tree::cerl()) -> {cerl(), integer()}
+%%
+%% @equiv label(Tree, 0)
+
+label(T) ->
+ label(T, 0).
+
+%% @spec label(Tree::cerl(), N::integer()) -> {cerl(), integer()}
+%%
+%% @doc Labels each expression in the tree. A term <code>{label,
+%% L}</code> is prefixed to the annotation list of each expression node,
+%% where L is a unique number for every node, except for variables (and
+%% function name variables) which get the same label if they represent
+%% the same variable. Constant literal nodes are not labeled.
+%%
+%% <p>The returned value is a tuple <code>{NewTree, Max}</code>, where
+%% <code>NewTree</code> is the labeled tree and <code>Max</code> is 1
+%% plus the largest label value used. All previous annotation terms on
+%% the form <code>{label, X}</code> are deleted.</p>
+%%
+%% <p>The values of L used in the tree is a dense range from
+%% <code>N</code> to <code>Max - 1</code>, where <code>N =&lt; Max
+%% =&lt; N + size(Tree)</code>. Note that it is possible that no
+%% labels are used at all, i.e., <code>N = Max</code>.</p>
+%%
+%% <p>Note: All instances of free variables will be given distinct
+%% labels.</p>
+%%
+%% @see label/1
+%% @see size/1
+
+label(T, N) ->
+ label(T, N, dict:new()).
+
+label(T, N, Env) ->
+ case type(T) of
+ literal ->
+ %% Constant literals are not labeled.
+ {T, N};
+ var ->
+ case dict:find(var_name(T), Env) of
+ {ok, L} ->
+ {As, _} = label_ann(T, L),
+ N1 = N;
+ error ->
+ {As, N1} = label_ann(T, N)
+ end,
+ {set_ann(T, As), N1};
+ values ->
+ {Ts, N1} = label_list(values_es(T), N, Env),
+ {As, N2} = label_ann(T, N1),
+ {ann_c_values(As, Ts), N2};
+ cons ->
+ {T1, N1} = label(cons_hd(T), N, Env),
+ {T2, N2} = label(cons_tl(T), N1, Env),
+ {As, N3} = label_ann(T, N2),
+ {ann_c_cons_skel(As, T1, T2), N3};
+ tuple ->
+ {Ts, N1} = label_list(tuple_es(T), N, Env),
+ {As, N2} = label_ann(T, N1),
+ {ann_c_tuple_skel(As, Ts), N2};
+ 'let' ->
+ {A, N1} = label(let_arg(T), N, Env),
+ {Vs, N2, Env1} = label_vars(let_vars(T), N1, Env),
+ {B, N3} = label(let_body(T), N2, Env1),
+ {As, N4} = label_ann(T, N3),
+ {ann_c_let(As, Vs, A, B), N4};
+ seq ->
+ {A, N1} = label(seq_arg(T), N, Env),
+ {B, N2} = label(seq_body(T), N1, Env),
+ {As, N3} = label_ann(T, N2),
+ {ann_c_seq(As, A, B), N3};
+ apply ->
+ {E, N1} = label(apply_op(T), N, Env),
+ {Es, N2} = label_list(apply_args(T), N1, Env),
+ {As, N3} = label_ann(T, N2),
+ {ann_c_apply(As, E, Es), N3};
+ call ->
+ {M, N1} = label(call_module(T), N, Env),
+ {F, N2} = label(call_name(T), N1, Env),
+ {Es, N3} = label_list(call_args(T), N2, Env),
+ {As, N4} = label_ann(T, N3),
+ {ann_c_call(As, M, F, Es), N4};
+ primop ->
+ {F, N1} = label(primop_name(T), N, Env),
+ {Es, N2} = label_list(primop_args(T), N1, Env),
+ {As, N3} = label_ann(T, N2),
+ {ann_c_primop(As, F, Es), N3};
+ 'case' ->
+ {A, N1} = label(case_arg(T), N, Env),
+ {Cs, N2} = label_list(case_clauses(T), N1, Env),
+ {As, N3} = label_ann(T, N2),
+ {ann_c_case(As, A, Cs), N3};
+ clause ->
+ {_, N1, Env1} = label_vars(clause_vars(T), N, Env),
+ {Ps, N2} = label_list(clause_pats(T), N1, Env1),
+ {G, N3} = label(clause_guard(T), N2, Env1),
+ {B, N4} = label(clause_body(T), N3, Env1),
+ {As, N5} = label_ann(T, N4),
+ {ann_c_clause(As, Ps, G, B), N5};
+ alias ->
+ {V, N1} = label(alias_var(T), N, Env),
+ {P, N2} = label(alias_pat(T), N1, Env),
+ {As, N3} = label_ann(T, N2),
+ {ann_c_alias(As, V, P), N3};
+ 'fun' ->
+ {Vs, N1, Env1} = label_vars(fun_vars(T), N, Env),
+ {B, N2} = label(fun_body(T), N1, Env1),
+ {As, N3} = label_ann(T, N2),
+ {ann_c_fun(As, Vs, B), N3};
+ 'receive' ->
+ {Cs, N1} = label_list(receive_clauses(T), N, Env),
+ {E, N2} = label(receive_timeout(T), N1, Env),
+ {A, N3} = label(receive_action(T), N2, Env),
+ {As, N4} = label_ann(T, N3),
+ {ann_c_receive(As, Cs, E, A), N4};
+ 'try' ->
+ {E, N1} = label(try_arg(T), N, Env),
+ {Vs, N2, Env1} = label_vars(try_vars(T), N1, Env),
+ {B, N3} = label(try_body(T), N2, Env1),
+ {Evs, N4, Env2} = label_vars(try_evars(T), N3, Env),
+ {H, N5} = label(try_handler(T), N4, Env2),
+ {As, N6} = label_ann(T, N5),
+ {ann_c_try(As, E, Vs, B, Evs, H), N6};
+ 'catch' ->
+ {B, N1} = label(catch_body(T), N, Env),
+ {As, N2} = label_ann(T, N1),
+ {ann_c_catch(As, B), N2};
+ binary ->
+ {Ds, N1} = label_list(binary_segments(T), N, Env),
+ {As, N2} = label_ann(T, N1),
+ {ann_c_binary(As, Ds), N2};
+ bitstr ->
+ {Val, N1} = label(bitstr_val(T), N, Env),
+ {Size, N2} = label(bitstr_size(T), N1, Env),
+ {Unit, N3} = label(bitstr_unit(T), N2, Env),
+ {Type, N4} = label(bitstr_type(T), N3, Env),
+ {Flags, N5} = label(bitstr_flags(T), N4, Env),
+ {As, N6} = label_ann(T, N5),
+ {ann_c_bitstr(As, Val, Size, Unit, Type, Flags), N6};
+ letrec ->
+ {_, N1, Env1} = label_vars(letrec_vars(T), N, Env),
+ {Ds, N2} = label_defs(letrec_defs(T), N1, Env1),
+ {B, N3} = label(letrec_body(T), N2, Env1),
+ {As, N4} = label_ann(T, N3),
+ {ann_c_letrec(As, Ds, B), N4};
+ module ->
+ %% The module name is not labeled.
+ {_, N1, Env1} = label_vars(module_vars(T), N, Env),
+ {Ts, N2} = label_defs(module_attrs(T), N1, Env1),
+ {Ds, N3} = label_defs(module_defs(T), N2, Env1),
+ {Es, N4} = label_list(module_exports(T), N3, Env1),
+ {As, N5} = label_ann(T, N4),
+ {ann_c_module(As, module_name(T), Es, Ts, Ds), N5}
+ end.
+
+label_list([T | Ts], N, Env) ->
+ {T1, N1} = label(T, N, Env),
+ {Ts1, N2} = label_list(Ts, N1, Env),
+ {[T1 | Ts1], N2};
+label_list([], N, _Env) ->
+ {[], N}.
+
+label_vars([T | Ts], N, Env) ->
+ Env1 = dict:store(var_name(T), N, Env),
+ {As, N1} = label_ann(T, N),
+ T1 = set_ann(T, As),
+ {Ts1, N2, Env2} = label_vars(Ts, N1, Env1),
+ {[T1 | Ts1], N2, Env2};
+label_vars([], N, Env) ->
+ {[], N, Env}.
+
+label_defs([{F, T} | Ds], N, Env) ->
+ {F1, N1} = label(F, N, Env),
+ {T1, N2} = label(T, N1, Env),
+ {Ds1, N3} = label_defs(Ds, N2, Env),
+ {[{F1, T1} | Ds1], N3};
+label_defs([], N, _Env) ->
+ {[], N}.
+
+label_ann(T, N) ->
+ {[{label, N} | filter_labels(get_ann(T))], N + 1}.
+
+filter_labels([{label, _} | As]) ->
+ filter_labels(As);
+filter_labels([A | As]) ->
+ [A | filter_labels(As)];
+filter_labels([]) ->
+ [].
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/compile.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/compile.erl
new file mode 100644
index 0000000000..2b6d14e300
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/compile.erl
@@ -0,0 +1,1109 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: compile.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
+%%
+%% Purpose: Run the Erlang compiler.
+
+-module(compile).
+-include("erl_compile.hrl").
+-include("core_parse.hrl").
+
+%% High-level interface.
+-export([file/1,file/2,format_error/1,iofile/1]).
+-export([forms/1,forms/2]).
+-export([output_generated/1]).
+-export([options/0]).
+
+%% Erlc interface.
+-export([compile/3,compile_beam/3,compile_asm/3,compile_core/3]).
+
+
+-import(lists, [member/2,reverse/1,keysearch/3,last/1,
+ map/2,flatmap/2,foreach/2,foldr/3,any/2,filter/2]).
+
+%% file(FileName)
+%% file(FileName, Options)
+%% Compile the module in file FileName.
+
+-define(DEFAULT_OPTIONS, [verbose,report_errors,report_warnings]).
+
+-define(pass(P), {P,fun P/1}).
+
+file(File) -> file(File, ?DEFAULT_OPTIONS).
+
+file(File, Opts) when list(Opts) ->
+ do_compile({file,File}, Opts++env_default_opts());
+file(File, Opt) ->
+ file(File, [Opt|?DEFAULT_OPTIONS]).
+
+forms(File) -> forms(File, ?DEFAULT_OPTIONS).
+
+forms(Forms, Opts) when list(Opts) ->
+ do_compile({forms,Forms}, [binary|Opts++env_default_opts()]);
+forms(Forms, Opts) when atom(Opts) ->
+ forms(Forms, [Opts|?DEFAULT_OPTIONS]).
+
+env_default_opts() ->
+ Key = "ERL_COMPILER_OPTIONS",
+ case os:getenv(Key) of
+ false -> [];
+ Str when list(Str) ->
+ case erl_scan:string(Str) of
+ {ok,Tokens,_} ->
+ case erl_parse:parse_term(Tokens ++ [{dot, 1}]) of
+ {ok,List} when list(List) -> List;
+ {ok,Term} -> [Term];
+ {error,_Reason} ->
+ io:format("Ignoring bad term in ~s\n", [Key]),
+ []
+ end;
+ {error, {_,_,_Reason}, _} ->
+ io:format("Ignoring bad term in ~s\n", [Key]),
+ []
+ end
+ end.
+
+do_compile(Input, Opts0) ->
+ Opts = expand_opts(Opts0),
+ Self = self(),
+ Serv = spawn_link(fun() -> internal(Self, Input, Opts) end),
+ receive
+ {Serv,Rep} -> Rep
+ end.
+
+%% Given a list of compilation options, returns true if compile:file/2
+%% would have generated a Beam file, false otherwise (if only a binary or a
+%% listing file would have been generated).
+
+output_generated(Opts) ->
+ any(fun ({save_binary,_F}) -> true;
+ (_Other) -> false
+ end, passes(file, expand_opts(Opts))).
+
+expand_opts(Opts) ->
+ foldr(fun expand_opt/2, [], Opts).
+
+expand_opt(basic_validation, Os) ->
+ [no_code_generation,to_pp,binary|Os];
+expand_opt(strong_validation, Os) ->
+ [no_code_generation,to_kernel,binary|Os];
+expand_opt(report, Os) ->
+ [report_errors,report_warnings|Os];
+expand_opt(return, Os) ->
+ [return_errors,return_warnings|Os];
+expand_opt(r7, Os) ->
+ [no_float_opt,no_new_funs,no_new_binaries,no_new_apply|Os];
+expand_opt(O, Os) -> [O|Os].
+
+filter_opts(Opts0) ->
+ %% Native code generation is not supported if no_new_funs is given.
+ case member(no_new_funs, Opts0) of
+ false -> Opts0;
+ true -> Opts0 -- [native]
+ end.
+
+%% format_error(ErrorDescriptor) -> string()
+
+format_error(no_native_support) ->
+ "this system is not configured for native-code compilation.";
+format_error({native, E}) ->
+ io_lib:fwrite("native-code compilation failed with reason: ~P.",
+ [E, 25]);
+format_error({native_crash, E}) ->
+ io_lib:fwrite("native-code compilation crashed with reason: ~P.",
+ [E, 25]);
+format_error({open,E}) ->
+ io_lib:format("open error '~s'", [file:format_error(E)]);
+format_error({epp,E}) ->
+ epp:format_error(E);
+format_error(write_error) ->
+ "error writing file";
+format_error({rename,S}) ->
+ io_lib:format("error renaming ~s", [S]);
+format_error({parse_transform,M,R}) ->
+ io_lib:format("error in parse transform '~s': ~p", [M, R]);
+format_error({core_transform,M,R}) ->
+ io_lib:format("error in core transform '~s': ~p", [M, R]);
+format_error({crash,Pass,Reason}) ->
+ io_lib:format("internal error in ~p;\ncrash reason: ~p", [Pass,Reason]);
+format_error({bad_return,Pass,Reason}) ->
+ io_lib:format("internal error in ~p;\nbad return value: ~p", [Pass,Reason]).
+
+%% The compile state record.
+-record(compile, {filename="",
+ dir="",
+ base="",
+ ifile="",
+ ofile="",
+ module=[],
+ code=[],
+ core_code=[],
+ abstract_code=[], %Abstract code for debugger.
+ options=[],
+ errors=[],
+ warnings=[]}).
+
+internal(Master, Input, Opts) ->
+ Master ! {self(),
+ case catch internal(Input, Opts) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Other ->
+ Other
+ end}.
+
+internal({forms,Forms}, Opts) ->
+ Ps = passes(forms, Opts),
+ internal_comp(Ps, "", "", #compile{code=Forms,options=Opts});
+internal({file,File}, Opts) ->
+ Ps = passes(file, Opts),
+ Compile = #compile{options=Opts},
+ case member(from_core, Opts) of
+ true -> internal_comp(Ps, File, ".core", Compile);
+ false ->
+ case member(from_beam, Opts) of
+ true ->
+ internal_comp(Ps, File, ".beam", Compile);
+ false ->
+ case member(from_asm, Opts) orelse member(asm, Opts) of
+ true ->
+ internal_comp(Ps, File, ".S", Compile);
+ false ->
+ internal_comp(Ps, File, ".erl", Compile)
+ end
+ end
+ end.
+
+internal_comp(Passes, File, Suffix, St0) ->
+ Dir = filename:dirname(File),
+ Base = filename:basename(File, Suffix),
+ St1 = St0#compile{filename=File, dir=Dir, base=Base,
+ ifile=erlfile(Dir, Base, Suffix),
+ ofile=objfile(Base, St0)},
+ Run = case member(time, St1#compile.options) of
+ true ->
+ io:format("Compiling ~p\n", [File]),
+ fun run_tc/2;
+ false -> fun({_Name,Fun}, St) -> catch Fun(St) end
+ end,
+ case fold_comp(Passes, Run, St1) of
+ {ok,St2} -> comp_ret_ok(St2);
+ {error,St2} -> comp_ret_err(St2)
+ end.
+
+fold_comp([{Name,Test,Pass}|Ps], Run, St) ->
+ case Test(St) of
+ false -> %Pass is not needed.
+ fold_comp(Ps, Run, St);
+ true -> %Run pass in the usual way.
+ fold_comp([{Name,Pass}|Ps], Run, St)
+ end;
+fold_comp([{Name,Pass}|Ps], Run, St0) ->
+ case Run({Name,Pass}, St0) of
+ {ok,St1} -> fold_comp(Ps, Run, St1);
+ {error,St1} -> {error,St1};
+ {'EXIT',Reason} ->
+ Es = [{St0#compile.ifile,[{none,?MODULE,{crash,Name,Reason}}]}],
+ {error,St0#compile{errors=St0#compile.errors ++ Es}};
+ Other ->
+ Es = [{St0#compile.ifile,[{none,?MODULE,{bad_return,Name,Other}}]}],
+ {error,St0#compile{errors=St0#compile.errors ++ Es}}
+ end;
+fold_comp([], _Run, St) -> {ok,St}.
+
+os_process_size() ->
+ case os:type() of
+ {unix, sunos} ->
+ Size = os:cmd("ps -o vsz -p " ++ os:getpid() ++ " | tail -1"),
+ list_to_integer(lib:nonl(Size));
+ _ ->
+ 0
+ end.
+
+run_tc({Name,Fun}, St) ->
+ Before0 = statistics(runtime),
+ Val = (catch Fun(St)),
+ After0 = statistics(runtime),
+ {Before_c, _} = Before0,
+ {After_c, _} = After0,
+ io:format(" ~-30s: ~10.3f s (~w k)\n",
+ [Name, (After_c-Before_c) / 1000, os_process_size()]),
+ Val.
+
+comp_ret_ok(#compile{code=Code,warnings=Warn,module=Mod,options=Opts}=St) ->
+ report_warnings(St),
+ Ret1 = case member(binary, Opts) andalso not member(no_code_generation, Opts) of
+ true -> [Code];
+ false -> []
+ end,
+ Ret2 = case member(return_warnings, Opts) of
+ true -> Ret1 ++ [Warn];
+ false -> Ret1
+ end,
+ list_to_tuple([ok,Mod|Ret2]).
+
+comp_ret_err(St) ->
+ report_errors(St),
+ report_warnings(St),
+ case member(return_errors, St#compile.options) of
+ true -> {error,St#compile.errors,St#compile.warnings};
+ false -> error
+ end.
+
+%% passes(form|file, [Option]) -> [{Name,PassFun}]
+%% Figure out which passes that need to be run.
+
+passes(forms, Opts) ->
+ select_passes(standard_passes(), Opts);
+passes(file, Opts) ->
+ case member(from_beam, Opts) of
+ true ->
+ Ps = [?pass(read_beam_file)|binary_passes()],
+ select_passes(Ps, Opts);
+ false ->
+ Ps = case member(from_asm, Opts) orelse member(asm, Opts) of
+ true ->
+ [?pass(beam_consult_asm)|asm_passes()];
+ false ->
+ case member(from_core, Opts) of
+ true ->
+ [?pass(parse_core)|core_passes()];
+ false ->
+ [?pass(parse_module)|standard_passes()]
+ end
+ end,
+ Fs = select_passes(Ps, Opts),
+
+ %% If the last pass saves the resulting binary to a file,
+ %% insert a first pass to remove the file.
+ case last(Fs) of
+ {save_binary,_Fun} -> [?pass(remove_file)|Fs];
+ _Other -> Fs
+ end
+ end.
+
+%% select_passes([Command], Opts) -> [{Name,Function}]
+%% Interpret the lists of commands to return a pure list of passes.
+%%
+%% Command can be one of:
+%%
+%% {pass,Mod} Will be expanded to a call to the external
+%% function Mod:module(Code, Options). This
+%% function must transform the code and return
+%% {ok,NewCode} or {error,Term}.
+%% Example: {pass,beam_codegen}
+%%
+%% {Name,Fun} Name is an atom giving the name of the pass.
+%% Fun is an 'fun' taking one argument: a compile record.
+%% The fun should return {ok,NewCompileRecord} or
+%% {error,NewCompileRecord}.
+%% Note: ?pass(Name) is equvivalent to {Name,fun Name/1}.
+%% Example: ?pass(parse_module)
+%%
+%% {Name,Test,Fun} Like {Name,Fun} above, but the pass will be run
+%% (and listed by the `time' option) only if Test(St)
+%% returns true.
+%%
+%% {src_listing,Ext} Produces an Erlang source listing with the
+%% the file extension Ext. (Ext should not contain
+%% a period.) No more passes will be run.
+%%
+%% {listing,Ext} Produce an listing of the terms in the internal
+%% representation. The extension of the listing
+%% file will be Ext. (Ext should not contain
+%% a period.) No more passes will be run.
+%%
+%% {done,Ext} End compilation at this point. Produce a listing
+%% as with {listing,Ext}, unless 'binary' is
+%% specified, in which case the current
+%% representation of the code is returned without
+%% creating an output file.
+%%
+%% {iff,Flag,Cmd} If the given Flag is given in the option list,
+%% Cmd will be interpreted as a command.
+%% Otherwise, Cmd will be ignored.
+%% Example: {iff,dcg,{listing,"codegen}}
+%%
+%% {unless,Flag,Cmd} If the given Flag is NOT given in the option list,
+%% Cmd will be interpreted as a command.
+%% Otherwise, Cmd will be ignored.
+%% Example: {unless,no_kernopt,{pass,sys_kernopt}}
+%%
+
+select_passes([{pass,Mod}|Ps], Opts) ->
+ F = fun(St) ->
+ case catch Mod:module(St#compile.code, St#compile.options) of
+ {ok,Code} ->
+ {ok,St#compile{code=Code}};
+ {error,Es} ->
+ {error,St#compile{errors=St#compile.errors ++ Es}}
+ end
+ end,
+ [{Mod,F}|select_passes(Ps, Opts)];
+select_passes([{src_listing,Ext}|_], _Opts) ->
+ [{listing,fun (St) -> src_listing(Ext, St) end}];
+select_passes([{listing,Ext}|_], _Opts) ->
+ [{listing,fun (St) -> listing(Ext, St) end}];
+select_passes([{done,Ext}|_], Opts) ->
+ select_passes([{unless,binary,{listing,Ext}}], Opts);
+select_passes([{iff,Flag,Pass}|Ps], Opts) ->
+ select_cond(Flag, true, Pass, Ps, Opts);
+select_passes([{unless,Flag,Pass}|Ps], Opts) ->
+ select_cond(Flag, false, Pass, Ps, Opts);
+select_passes([{_,Fun}=P|Ps], Opts) when is_function(Fun) ->
+ [P|select_passes(Ps, Opts)];
+select_passes([{_,Test,Fun}=P|Ps], Opts) when is_function(Test),
+ is_function(Fun) ->
+ [P|select_passes(Ps, Opts)];
+select_passes([], _Opts) ->
+ [];
+select_passes([List|Ps], Opts) when is_list(List) ->
+ case select_passes(List, Opts) of
+ [] -> select_passes(Ps, Opts);
+ Nested ->
+ case last(Nested) of
+ {listing,_Fun} -> Nested;
+ _Other -> Nested ++ select_passes(Ps, Opts)
+ end
+ end.
+
+select_cond(Flag, ShouldBe, Pass, Ps, Opts) ->
+ ShouldNotBe = not ShouldBe,
+ case member(Flag, Opts) of
+ ShouldBe -> select_passes([Pass|Ps], Opts);
+ ShouldNotBe -> select_passes(Ps, Opts)
+ end.
+
+%% The standard passes (almost) always run.
+
+standard_passes() ->
+ [?pass(transform_module),
+ {iff,'dpp',{listing,"pp"}},
+ ?pass(lint_module),
+ {iff,'P',{src_listing,"P"}},
+ {iff,'to_pp',{done,"P"}},
+
+ {iff,'dabstr',{listing,"abstr"}},
+ {iff,debug_info,?pass(save_abstract_code)},
+
+ ?pass(expand_module),
+ {iff,'dexp',{listing,"expand"}},
+ {iff,'E',{src_listing,"E"}},
+ {iff,'to_exp',{done,"E"}},
+
+ %% Conversion to Core Erlang.
+ ?pass(core_module),
+ {iff,'dcore',{listing,"core"}},
+ {iff,'to_core0',{done,"core"}}
+ | core_passes()].
+
+core_passes() ->
+ %% Optimization and transforms of Core Erlang code.
+ [{unless,no_copt,
+ [{core_old_inliner,fun test_old_inliner/1,fun core_old_inliner/1},
+ ?pass(core_fold_module),
+ {core_inline_module,fun test_core_inliner/1,fun core_inline_module/1},
+ {core_fold_after_inline,fun test_core_inliner/1,fun core_fold_module/1},
+ ?pass(core_transforms)]},
+ {iff,dcopt,{listing,"copt"}},
+ {iff,'to_core',{done,"core"}}
+ | kernel_passes()].
+
+kernel_passes() ->
+ %% Destructive setelement/3 optimization and core lint.
+ [?pass(core_dsetel_module),
+ {iff,clint,?pass(core_lint_module)},
+ {iff,core,?pass(save_core_code)},
+
+ %% Kernel Erlang and code generation.
+ ?pass(kernel_module),
+ {iff,dkern,{listing,"kernel"}},
+ {iff,'to_kernel',{done,"kernel"}},
+ {pass,v3_life},
+ {iff,dlife,{listing,"life"}},
+ {pass,v3_codegen},
+ {iff,dcg,{listing,"codegen"}}
+ | asm_passes()].
+
+asm_passes() ->
+ %% Assembly level optimisations.
+ [{unless,no_postopt,
+ [{pass,beam_block},
+ {iff,dblk,{listing,"block"}},
+ {unless,no_bopt,{pass,beam_bool}},
+ {iff,dbool,{listing,"bool"}},
+ {unless,no_topt,{pass,beam_type}},
+ {iff,dtype,{listing,"type"}},
+ {pass,beam_dead}, %Must always run since it splits blocks.
+ {iff,ddead,{listing,"dead"}},
+ {unless,no_jopt,{pass,beam_jump}},
+ {iff,djmp,{listing,"jump"}},
+ {pass,beam_clean},
+ {iff,dclean,{listing,"clean"}},
+ {pass,beam_flatten}]},
+
+ %% If post optimizations are turned off, we still coalesce
+ %% adjacent labels and remove unused labels to keep the
+ %% HiPE compiler happy.
+ {iff,no_postopt,
+ [?pass(beam_unused_labels),
+ {pass,beam_clean}]},
+
+ {iff,dopt,{listing,"optimize"}},
+ {iff,'S',{listing,"S"}},
+ {iff,'to_asm',{done,"S"}},
+
+ {pass,beam_validator},
+ ?pass(beam_asm)
+ | binary_passes()].
+
+binary_passes() ->
+ [{native_compile,fun test_native/1,fun native_compile/1},
+ {unless,binary,?pass(save_binary)}].
+
+%%%
+%%% Compiler passes.
+%%%
+
+%% Remove the target file so we don't have an old one if the compilation fail.
+remove_file(St) ->
+ file:delete(St#compile.ofile),
+ {ok,St}.
+
+-record(asm_module, {module,
+ exports,
+ labels,
+ functions=[],
+ cfun,
+ code,
+ attributes=[]}).
+
+preprocess_asm_forms(Forms) ->
+ R = #asm_module{},
+ R1 = collect_asm(Forms, R),
+ {R1#asm_module.module,
+ {R1#asm_module.module,
+ R1#asm_module.exports,
+ R1#asm_module.attributes,
+ R1#asm_module.functions,
+ R1#asm_module.labels}}.
+
+collect_asm([], R) ->
+ case R#asm_module.cfun of
+ undefined ->
+ R;
+ {A,B,C} ->
+ R#asm_module{functions=R#asm_module.functions++
+ [{function,A,B,C,R#asm_module.code}]}
+ end;
+collect_asm([{module,M} | Rest], R) ->
+ collect_asm(Rest, R#asm_module{module=M});
+collect_asm([{exports,M} | Rest], R) ->
+ collect_asm(Rest, R#asm_module{exports=M});
+collect_asm([{labels,M} | Rest], R) ->
+ collect_asm(Rest, R#asm_module{labels=M});
+collect_asm([{function,A,B,C} | Rest], R) ->
+ R1 = case R#asm_module.cfun of
+ undefined ->
+ R;
+ {A0,B0,C0} ->
+ R#asm_module{functions=R#asm_module.functions++
+ [{function,A0,B0,C0,R#asm_module.code}]}
+ end,
+ collect_asm(Rest, R1#asm_module{cfun={A,B,C}, code=[]});
+collect_asm([{attributes, Attr} | Rest], R) ->
+ collect_asm(Rest, R#asm_module{attributes=Attr});
+collect_asm([X | Rest], R) ->
+ collect_asm(Rest, R#asm_module{code=R#asm_module.code++[X]}).
+
+beam_consult_asm(St) ->
+ case file:consult(St#compile.ifile) of
+ {ok, Forms0} ->
+ {Module, Forms} = preprocess_asm_forms(Forms0),
+ {ok,St#compile{module=Module, code=Forms}};
+ {error,E} ->
+ Es = [{St#compile.ifile,[{none,?MODULE,{open,E}}]}],
+ {error,St#compile{errors=St#compile.errors ++ Es}}
+ end.
+
+read_beam_file(St) ->
+ case file:read_file(St#compile.ifile) of
+ {ok,Beam} ->
+ Infile = St#compile.ifile,
+ case is_too_old(Infile) of
+ true ->
+ {ok,St#compile{module=none,code=none}};
+ false ->
+ Mod0 = filename:rootname(filename:basename(Infile)),
+ Mod = list_to_atom(Mod0),
+ {ok,St#compile{module=Mod,code=Beam,ofile=Infile}}
+ end;
+ {error,E} ->
+ Es = [{St#compile.ifile,[{none,?MODULE,{open,E}}]}],
+ {error,St#compile{errors=St#compile.errors ++ Es}}
+ end.
+
+is_too_old(BeamFile) ->
+ case beam_lib:chunks(BeamFile, ["CInf"]) of
+ {ok,{_,[{"CInf",Term0}]}} ->
+ Term = binary_to_term(Term0),
+ Opts = proplists:get_value(options, Term, []),
+ lists:member(no_new_funs, Opts);
+ _ -> false
+ end.
+
+parse_module(St) ->
+ Opts = St#compile.options,
+ Cwd = ".",
+ IncludePath = [Cwd, St#compile.dir|inc_paths(Opts)],
+ Tab = ets:new(compiler__tab, [protected,named_table]),
+ ets:insert(Tab, {compiler_options,Opts}),
+ R = epp:parse_file(St#compile.ifile, IncludePath, pre_defs(Opts)),
+ ets:delete(Tab),
+ case R of
+ {ok,Forms} ->
+ {ok,St#compile{code=Forms}};
+ {error,E} ->
+ Es = [{St#compile.ifile,[{none,?MODULE,{epp,E}}]}],
+ {error,St#compile{errors=St#compile.errors ++ Es}}
+ end.
+
+parse_core(St) ->
+ case file:read_file(St#compile.ifile) of
+ {ok,Bin} ->
+ case core_scan:string(binary_to_list(Bin)) of
+ {ok,Toks,_} ->
+ case core_parse:parse(Toks) of
+ {ok,Mod} ->
+ Name = (Mod#c_module.name)#c_atom.val,
+ {ok,St#compile{module=Name,code=Mod}};
+ {error,E} ->
+ Es = [{St#compile.ifile,[E]}],
+ {error,St#compile{errors=St#compile.errors ++ Es}}
+ end;
+ {error,E,_} ->
+ Es = [{St#compile.ifile,[E]}],
+ {error,St#compile{errors=St#compile.errors ++ Es}}
+ end;
+ {error,E} ->
+ Es = [{St#compile.ifile,[{none,compile,{open,E}}]}],
+ {error,St#compile{errors=St#compile.errors ++ Es}}
+ end.
+
+compile_options([{attribute,_L,compile,C}|Fs]) when is_list(C) ->
+ C ++ compile_options(Fs);
+compile_options([{attribute,_L,compile,C}|Fs]) ->
+ [C|compile_options(Fs)];
+compile_options([_F|Fs]) -> compile_options(Fs);
+compile_options([]) -> [].
+
+transforms(Os) -> [ M || {parse_transform,M} <- Os ].
+
+transform_module(St) ->
+ %% Extract compile options from code into options field.
+ Ts = transforms(St#compile.options ++ compile_options(St#compile.code)),
+ foldl_transform(St, Ts).
+
+foldl_transform(St, [T|Ts]) ->
+ Name = "transform " ++ atom_to_list(T),
+ Fun = fun(S) -> T:parse_transform(S#compile.code, S#compile.options) end,
+ Run = case member(time, St#compile.options) of
+ true -> fun run_tc/2;
+ false -> fun({_Name,F}, S) -> catch F(S) end
+ end,
+ case Run({Name, Fun}, St) of
+ {error,Es,Ws} ->
+ {error,St#compile{warnings=St#compile.warnings ++ Ws,
+ errors=St#compile.errors ++ Es}};
+ {'EXIT',R} ->
+ Es = [{St#compile.ifile,[{none,compile,{parse_transform,T,R}}]}],
+ {error,St#compile{errors=St#compile.errors ++ Es}};
+ Forms ->
+ foldl_transform(St#compile{code=Forms}, Ts)
+ end;
+foldl_transform(St, []) -> {ok,St}.
+
+get_core_transforms(Opts) -> [M || {core_transform,M} <- Opts].
+
+core_transforms(St) ->
+ %% The options field holds the complete list of options at this
+
+ Ts = get_core_transforms(St#compile.options),
+ foldl_core_transforms(St, Ts).
+
+foldl_core_transforms(St, [T|Ts]) ->
+ Name = "core transform " ++ atom_to_list(T),
+ Fun = fun(S) -> T:core_transform(S#compile.code, S#compile.options) end,
+ Run = case member(time, St#compile.options) of
+ true -> fun run_tc/2;
+ false -> fun({_Name,F}, S) -> catch F(S) end
+ end,
+ case Run({Name, Fun}, St) of
+ {'EXIT',R} ->
+ Es = [{St#compile.ifile,[{none,compile,{core_transform,T,R}}]}],
+ {error,St#compile{errors=St#compile.errors ++ Es}};
+ Forms ->
+ foldl_core_transforms(St#compile{code=Forms}, Ts)
+ end;
+foldl_core_transforms(St, []) -> {ok,St}.
+
+%%% Fetches the module name from a list of forms. The module attribute must
+%%% be present.
+get_module([{attribute,_,module,{M,_As}} | _]) -> M;
+get_module([{attribute,_,module,M} | _]) -> M;
+get_module([_ | Rest]) ->
+ get_module(Rest).
+
+%%% A #compile state is returned, where St.base has been filled in
+%%% with the module name from Forms, as a string, in case it wasn't
+%%% set in St (i.e., it was "").
+add_default_base(St, Forms) ->
+ F = St#compile.filename,
+ case F of
+ "" ->
+ M = get_module(Forms),
+ St#compile{base = atom_to_list(M)};
+ _ ->
+ St
+ end.
+
+lint_module(St) ->
+ case erl_lint:module(St#compile.code,
+ St#compile.ifile, St#compile.options) of
+ {ok,Ws} ->
+ %% Insert name of module as base name, if needed. This is
+ %% for compile:forms to work with listing files.
+ St1 = add_default_base(St, St#compile.code),
+ {ok,St1#compile{warnings=St1#compile.warnings ++ Ws}};
+ {error,Es,Ws} ->
+ {error,St#compile{warnings=St#compile.warnings ++ Ws,
+ errors=St#compile.errors ++ Es}}
+ end.
+
+core_lint_module(St) ->
+ case core_lint:module(St#compile.code, St#compile.options) of
+ {ok,Ws} ->
+ {ok,St#compile{warnings=St#compile.warnings ++ Ws}};
+ {error,Es,Ws} ->
+ {error,St#compile{warnings=St#compile.warnings ++ Ws,
+ errors=St#compile.errors ++ Es}}
+ end.
+
+%% expand_module(State) -> State'
+%% Do the common preprocessing of the input forms.
+
+expand_module(#compile{code=Code,options=Opts0}=St0) ->
+ {Mod,Exp,Forms,Opts1} = sys_pre_expand:module(Code, Opts0),
+ Opts2 = expand_opts(Opts1),
+ Opts = filter_opts(Opts2),
+ {ok,St0#compile{module=Mod,options=Opts,code={Mod,Exp,Forms}}}.
+
+core_module(#compile{code=Code0,options=Opts,ifile=File}=St) ->
+ {ok,Code,Ws} = v3_core:module(Code0, Opts),
+ {ok,St#compile{code=Code,warnings=St#compile.warnings ++ [{File,Ws}]}}.
+
+core_fold_module(#compile{code=Code0,options=Opts,ifile=File}=St) ->
+ {ok,Code,Ws} = sys_core_fold:module(Code0, Opts),
+ {ok,St#compile{code=Code,warnings=St#compile.warnings ++ [{File,Ws}]}}.
+
+test_old_inliner(#compile{options=Opts}) ->
+ %% The point of this test is to avoid loading the old inliner
+ %% if we know that it will not be used.
+ case any(fun(no_inline) -> true;
+ (_) -> false
+ end, Opts) of
+ true -> false;
+ false ->
+ any(fun({inline,_}) -> true;
+ (_) -> false
+ end, Opts)
+ end.
+
+test_core_inliner(#compile{options=Opts}) ->
+ case any(fun(no_inline) -> true;
+ (_) -> false
+ end, Opts) of
+ true -> false;
+ false ->
+ any(fun(inline) -> true;
+ (_) -> false
+ end, Opts)
+ end.
+
+core_old_inliner(#compile{code=Code0,options=Opts}=St) ->
+ case catch sys_core_inline:module(Code0, Opts) of
+ {ok,Code} ->
+ {ok,St#compile{code=Code}};
+ {error,Es} ->
+ {error,St#compile{errors=St#compile.errors ++ Es}}
+ end.
+
+core_inline_module(#compile{code=Code0,options=Opts}=St) ->
+ Code = cerl_inline:core_transform(Code0, Opts),
+ {ok,St#compile{code=Code}}.
+
+core_dsetel_module(#compile{code=Code0,options=Opts}=St) ->
+ {ok,Code} = sys_core_dsetel:module(Code0, Opts),
+ {ok,St#compile{code=Code}}.
+
+kernel_module(#compile{code=Code0,options=Opts,ifile=File}=St) ->
+ {ok,Code,Ws} = v3_kernel:module(Code0, Opts),
+ {ok,St#compile{code=Code,warnings=St#compile.warnings ++ [{File,Ws}]}}.
+
+save_abstract_code(St) ->
+ {ok,St#compile{abstract_code=abstract_code(St)}}.
+
+abstract_code(#compile{code=Code}) ->
+ Abstr = {raw_abstract_v1,Code},
+ case catch erlang:term_to_binary(Abstr, [compressed]) of
+ {'EXIT',_} -> term_to_binary(Abstr);
+ Other -> Other
+ end.
+
+save_core_code(St) ->
+ {ok,St#compile{core_code=cerl:from_records(St#compile.code)}}.
+
+beam_unused_labels(#compile{code=Code0}=St) ->
+ Code = beam_jump:module_labels(Code0),
+ {ok,St#compile{code=Code}}.
+
+beam_asm(#compile{ifile=File,code=Code0,abstract_code=Abst,options=Opts0}=St) ->
+ Source = filename:absname(File),
+ Opts = filter(fun is_informative_option/1, Opts0),
+ case beam_asm:module(Code0, Abst, Source, Opts) of
+ {ok,Code} -> {ok,St#compile{code=Code,abstract_code=[]}};
+ {error,Es} -> {error,St#compile{errors=St#compile.errors ++ Es}}
+ end.
+
+test_native(#compile{options=Opts}) ->
+ %% This test must be made late, because the r7 or no_new_funs options
+ %% will turn off the native option.
+ member(native, Opts).
+
+native_compile(#compile{code=none}=St) -> {ok,St};
+native_compile(St) ->
+ case erlang:system_info(hipe_architecture) of
+ undefined ->
+ Ws = [{St#compile.ifile,[{none,compile,no_native_support}]}],
+ {ok,St#compile{warnings=St#compile.warnings ++ Ws}};
+ _ ->
+ native_compile_1(St)
+ end.
+
+native_compile_1(St) ->
+ Opts0 = [no_new_binaries|St#compile.options],
+ IgnoreErrors = member(ignore_native_errors, Opts0),
+ Opts = case keysearch(hipe, 1, Opts0) of
+ {value,{hipe,L}} when list(L) -> L;
+ {value,{hipe,X}} -> [X];
+ _ -> []
+ end,
+ case catch hipe:compile(St#compile.module,
+ St#compile.core_code,
+ St#compile.code,
+ Opts) of
+ {ok, {Type,Bin}} when binary(Bin) ->
+ {ok, embed_native_code(St, {Type,Bin})};
+ {error, R} ->
+ case IgnoreErrors of
+ true ->
+ Ws = [{St#compile.ifile,[{none,?MODULE,{native,R}}]}],
+ {ok,St#compile{warnings=St#compile.warnings ++ Ws}};
+ false ->
+ Es = [{St#compile.ifile,[{none,?MODULE,{native,R}}]}],
+ {error,St#compile{errors=St#compile.errors ++ Es}}
+ end;
+ {'EXIT',R} ->
+ case IgnoreErrors of
+ true ->
+ Ws = [{St#compile.ifile,[{none,?MODULE,{native_crash,R}}]}],
+ {ok,St#compile{warnings=St#compile.warnings ++ Ws}};
+ false ->
+ exit(R)
+ end
+ end.
+
+embed_native_code(St, {Architecture,NativeCode}) ->
+ {ok, _, Chunks0} = beam_lib:all_chunks(St#compile.code),
+ ChunkName = hipe_unified_loader:chunk_name(Architecture),
+ Chunks1 = lists:keydelete(ChunkName, 1, Chunks0),
+ Chunks = Chunks1 ++ [{ChunkName,NativeCode}],
+ {ok, BeamPlusNative} = beam_lib:build_module(Chunks),
+ St#compile{code=BeamPlusNative}.
+
+%% Returns true if the option is informative and therefore should be included
+%% in the option list of the compiled module.
+
+is_informative_option(beam) -> false;
+is_informative_option(report_warnings) -> false;
+is_informative_option(report_errors) -> false;
+is_informative_option(binary) -> false;
+is_informative_option(verbose) -> false;
+is_informative_option(_) -> true.
+
+save_binary(#compile{code=none}=St) -> {ok,St};
+save_binary(St) ->
+ Tfile = tmpfile(St#compile.ofile), %Temp working file
+ case write_binary(Tfile, St#compile.code, St) of
+ ok ->
+ case file:rename(Tfile, St#compile.ofile) of
+ ok ->
+ {ok,St};
+ {error,_Error} ->
+ file:delete(Tfile),
+ Es = [{St#compile.ofile,[{none,?MODULE,{rename,Tfile}}]}],
+ {error,St#compile{errors=St#compile.errors ++ Es}}
+ end;
+ {error,_Error} ->
+ Es = [{Tfile,[{compile,write_error}]}],
+ {error,St#compile{errors=St#compile.errors ++ Es}}
+ end.
+
+write_binary(Name, Bin, St) ->
+ Opts = case member(compressed, St#compile.options) of
+ true -> [compressed];
+ false -> []
+ end,
+ case file:write_file(Name, Bin, Opts) of
+ ok -> ok;
+ {error,_}=Error -> Error
+ end.
+
+%% report_errors(State) -> ok
+%% report_warnings(State) -> ok
+
+report_errors(St) ->
+ case member(report_errors, St#compile.options) of
+ true ->
+ foreach(fun ({{F,_L},Eds}) -> list_errors(F, Eds);
+ ({F,Eds}) -> list_errors(F, Eds) end,
+ St#compile.errors);
+ false -> ok
+ end.
+
+report_warnings(#compile{options=Opts,warnings=Ws0}) ->
+ case member(report_warnings, Opts) of
+ true ->
+ Ws1 = flatmap(fun({{F,_L},Eds}) -> format_message(F, Eds);
+ ({F,Eds}) -> format_message(F, Eds) end,
+ Ws0),
+ Ws = ordsets:from_list(Ws1),
+ foreach(fun({_,Str}) -> io:put_chars(Str) end, Ws);
+ false -> ok
+ end.
+
+format_message(F, [{Line,Mod,E}|Es]) ->
+ M = {Line,io_lib:format("~s:~w: Warning: ~s\n", [F,Line,Mod:format_error(E)])},
+ [M|format_message(F, Es)];
+format_message(F, [{Mod,E}|Es]) ->
+ M = {none,io_lib:format("~s: Warning: ~s\n", [F,Mod:format_error(E)])},
+ [M|format_message(F, Es)];
+format_message(_, []) -> [].
+
+%% list_errors(File, ErrorDescriptors) -> ok
+
+list_errors(F, [{Line,Mod,E}|Es]) ->
+ io:fwrite("~s:~w: ~s\n", [F,Line,Mod:format_error(E)]),
+ list_errors(F, Es);
+list_errors(F, [{Mod,E}|Es]) ->
+ io:fwrite("~s: ~s\n", [F,Mod:format_error(E)]),
+ list_errors(F, Es);
+list_errors(_F, []) -> ok.
+
+%% erlfile(Dir, Base) -> ErlFile
+%% outfile(Base, Extension, Options) -> OutputFile
+%% objfile(Base, Target, Options) -> ObjFile
+%% tmpfile(ObjFile) -> TmpFile
+%% Work out the correct input and output file names.
+
+iofile(File) when atom(File) ->
+ iofile(atom_to_list(File));
+iofile(File) ->
+ {filename:dirname(File), filename:basename(File, ".erl")}.
+
+erlfile(Dir, Base, Suffix) ->
+ filename:join(Dir, Base++Suffix).
+
+outfile(Base, Ext, Opts) when atom(Ext) ->
+ outfile(Base, atom_to_list(Ext), Opts);
+outfile(Base, Ext, Opts) ->
+ Obase = case keysearch(outdir, 1, Opts) of
+ {value, {outdir, Odir}} -> filename:join(Odir, Base);
+ _Other -> Base % Not found or bad format
+ end,
+ Obase++"."++Ext.
+
+objfile(Base, St) ->
+ outfile(Base, "beam", St#compile.options).
+
+tmpfile(Ofile) ->
+ reverse([$#|tl(reverse(Ofile))]).
+
+%% pre_defs(Options)
+%% inc_paths(Options)
+%% Extract the predefined macros and include paths from the option list.
+
+pre_defs([{d,M,V}|Opts]) ->
+ [{M,V}|pre_defs(Opts)];
+pre_defs([{d,M}|Opts]) ->
+ [M|pre_defs(Opts)];
+pre_defs([_|Opts]) ->
+ pre_defs(Opts);
+pre_defs([]) -> [].
+
+inc_paths(Opts) ->
+ [ P || {i,P} <- Opts, list(P) ].
+
+src_listing(Ext, St) ->
+ listing(fun (Lf, {_Mod,_Exp,Fs}) -> do_src_listing(Lf, Fs);
+ (Lf, Fs) -> do_src_listing(Lf, Fs) end,
+ Ext, St).
+
+do_src_listing(Lf, Fs) ->
+ foreach(fun (F) -> io:put_chars(Lf, [erl_pp:form(F),"\n"]) end,
+ Fs).
+
+listing(Ext, St) ->
+ listing(fun(Lf, Fs) -> beam_listing:module(Lf, Fs) end, Ext, St).
+
+listing(LFun, Ext, St) ->
+ Lfile = outfile(St#compile.base, Ext, St#compile.options),
+ case file:open(Lfile, [write,delayed_write]) of
+ {ok,Lf} ->
+ LFun(Lf, St#compile.code),
+ ok = file:close(Lf),
+ {ok,St};
+ {error,_Error} ->
+ Es = [{Lfile,[{none,compile,write_error}]}],
+ {error,St#compile{errors=St#compile.errors ++ Es}}
+ end.
+
+options() ->
+ help(standard_passes()).
+
+help([{iff,Flag,{src_listing,Ext}}|T]) ->
+ io:fwrite("~p - Generate .~s source listing file\n", [Flag,Ext]),
+ help(T);
+help([{iff,Flag,{listing,Ext}}|T]) ->
+ io:fwrite("~p - Generate .~s file\n", [Flag,Ext]),
+ help(T);
+help([{iff,Flag,{Name,Fun}}|T]) when function(Fun) ->
+ io:fwrite("~p - Run ~s\n", [Flag,Name]),
+ help(T);
+help([{iff,_Flag,Action}|T]) ->
+ help(Action),
+ help(T);
+help([{unless,Flag,{pass,Pass}}|T]) ->
+ io:fwrite("~p - Skip the ~s pass\n", [Flag,Pass]),
+ help(T);
+help([{unless,no_postopt=Flag,List}|T]) when list(List) ->
+ %% Hard-coded knowledgde here.
+ io:fwrite("~p - Skip all post optimisation\n", [Flag]),
+ help(List),
+ help(T);
+help([{unless,_Flag,Action}|T]) ->
+ help(Action),
+ help(T);
+help([_|T]) ->
+ help(T);
+help(_) ->
+ ok.
+
+
+%% compile(AbsFileName, Outfilename, Options)
+%% Compile entry point for erl_compile.
+
+compile(File0, _OutFile, Options) ->
+ File = shorten_filename(File0),
+ case file(File, make_erl_options(Options)) of
+ {ok,_Mod} -> ok;
+ Other -> Other
+ end.
+
+compile_beam(File0, _OutFile, Opts) ->
+ File = shorten_filename(File0),
+ case file(File, [from_beam|make_erl_options(Opts)]) of
+ {ok,_Mod} -> ok;
+ Other -> Other
+ end.
+
+compile_asm(File0, _OutFile, Opts) ->
+ File = shorten_filename(File0),
+ case file(File, [asm|make_erl_options(Opts)]) of
+ {ok,_Mod} -> ok;
+ Other -> Other
+ end.
+
+compile_core(File0, _OutFile, Opts) ->
+ File = shorten_filename(File0),
+ case file(File, [from_core|make_erl_options(Opts)]) of
+ {ok,_Mod} -> ok;
+ Other -> Other
+ end.
+
+shorten_filename(Name0) ->
+ {ok,Cwd} = file:get_cwd(),
+ case lists:prefix(Cwd, Name0) of
+ false -> Name0;
+ true ->
+ Name = case lists:nthtail(length(Cwd), Name0) of
+ "/"++N -> N;
+ N -> N
+ end,
+ Name
+ end.
+
+%% Converts generic compiler options to specific options.
+
+make_erl_options(Opts) ->
+
+ %% This way of extracting will work even if the record passed
+ %% has more fields than known during compilation.
+
+ Includes = Opts#options.includes,
+ Defines = Opts#options.defines,
+ Outdir = Opts#options.outdir,
+ Warning = Opts#options.warning,
+ Verbose = Opts#options.verbose,
+ Specific = Opts#options.specific,
+ OutputType = Opts#options.output_type,
+ Cwd = Opts#options.cwd,
+
+ Options =
+ case Verbose of
+ true -> [verbose];
+ false -> []
+ end ++
+ case Warning of
+ 0 -> [];
+ _ -> [report_warnings]
+ end ++
+ map(
+ fun ({Name, Value}) ->
+ {d, Name, Value};
+ (Name) ->
+ {d, Name}
+ end,
+ Defines) ++
+ case OutputType of
+ undefined -> [];
+ jam -> [jam];
+ beam -> [beam];
+ native -> [native]
+ end,
+
+ Options++[report_errors, {cwd, Cwd}, {outdir, Outdir}|
+ map(fun(Dir) -> {i, Dir} end, Includes)]++Specific.
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_lib.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_lib.erl
new file mode 100644
index 0000000000..1fe45d5308
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_lib.erl
@@ -0,0 +1,509 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: core_lib.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
+%%
+%% Purpose: Core Erlang abstract syntax functions.
+
+-module(core_lib).
+
+-export([get_anno/1,set_anno/2]).
+-export([is_atomic/1,is_literal/1,is_literal_list/1,
+ is_simple/1,is_simple_list/1,is_simple_top/1]).
+-export([literal_value/1,make_literal/1]).
+-export([make_values/1]).
+-export([map/2, fold/3, mapfold/3]).
+-export([is_var_used/2]).
+
+%% -compile([export_all]).
+
+-include("core_parse.hrl").
+
+%% get_anno(Core) -> Anno.
+%% set_anno(Core, Anno) -> Core.
+%% Generic get/set annotation.
+
+get_anno(C) -> element(2, C).
+set_anno(C, A) -> setelement(2, C, A).
+
+%% is_atomic(Expr) -> true | false.
+
+is_atomic(#c_char{}) -> true;
+is_atomic(#c_int{}) -> true;
+is_atomic(#c_float{}) -> true;
+is_atomic(#c_atom{}) -> true;
+is_atomic(#c_string{}) -> true;
+is_atomic(#c_nil{}) -> true;
+is_atomic(#c_fname{}) -> true;
+is_atomic(_) -> false.
+
+%% is_literal(Expr) -> true | false.
+
+is_literal(#c_cons{hd=H,tl=T}) ->
+ case is_literal(H) of
+ true -> is_literal(T);
+ false -> false
+ end;
+is_literal(#c_tuple{es=Es}) -> is_literal_list(Es);
+is_literal(#c_binary{segments=Es}) -> is_lit_bin(Es);
+is_literal(E) -> is_atomic(E).
+
+is_literal_list(Es) -> lists:all(fun is_literal/1, Es).
+
+is_lit_bin(Es) ->
+ lists:all(fun (#c_bitstr{val=E,size=S}) ->
+ is_literal(E) and is_literal(S)
+ end, Es).
+
+%% is_simple(Expr) -> true | false.
+
+is_simple(#c_var{}) -> true;
+is_simple(#c_cons{hd=H,tl=T}) ->
+ case is_simple(H) of
+ true -> is_simple(T);
+ false -> false
+ end;
+is_simple(#c_tuple{es=Es}) -> is_simple_list(Es);
+is_simple(#c_binary{segments=Es}) -> is_simp_bin(Es);
+is_simple(E) -> is_atomic(E).
+
+is_simple_list(Es) -> lists:all(fun is_simple/1, Es).
+
+is_simp_bin(Es) ->
+ lists:all(fun (#c_bitstr{val=E,size=S}) ->
+ is_simple(E) and is_simple(S)
+ end, Es).
+
+%% is_simple_top(Expr) -> true | false.
+%% Only check if the top-level is a simple.
+
+is_simple_top(#c_var{}) -> true;
+is_simple_top(#c_cons{}) -> true;
+is_simple_top(#c_tuple{}) -> true;
+is_simple_top(#c_binary{}) -> true;
+is_simple_top(E) -> is_atomic(E).
+
+%% literal_value(LitExpr) -> Value.
+%% Return the value of LitExpr.
+
+literal_value(#c_char{val=C}) -> C;
+literal_value(#c_int{val=I}) -> I;
+literal_value(#c_float{val=F}) -> F;
+literal_value(#c_atom{val=A}) -> A;
+literal_value(#c_string{val=S}) -> S;
+literal_value(#c_nil{}) -> [];
+literal_value(#c_cons{hd=H,tl=T}) ->
+ [literal_value(H)|literal_value(T)];
+literal_value(#c_tuple{es=Es}) ->
+ list_to_tuple(literal_value_list(Es)).
+
+literal_value_list(Vals) -> lists:map(fun literal_value/1, Vals).
+
+%% make_literal(Value) -> LitExpr.
+%% Make a literal expression from an Erlang value.
+
+make_literal(I) when integer(I) -> #c_int{val=I};
+make_literal(F) when float(F) -> #c_float{val=F};
+make_literal(A) when atom(A) -> #c_atom{val=A};
+make_literal([]) -> #c_nil{};
+make_literal([H|T]) ->
+ #c_cons{hd=make_literal(H),tl=make_literal(T)};
+make_literal(T) when tuple(T) ->
+ #c_tuple{es=make_literal_list(tuple_to_list(T))}.
+
+make_literal_list(Vals) -> lists:map(fun make_literal/1, Vals).
+
+%% make_values([CoreExpr] | CoreExpr) -> #c_values{} | CoreExpr.
+%% Make a suitable values structure, expr or values, depending on
+%% Expr.
+
+make_values([E]) -> E;
+make_values([H|_]=Es) -> #c_values{anno=get_anno(H),es=Es};
+make_values([]) -> #c_values{es=[]};
+make_values(E) -> E.
+
+%% map(MapFun, CoreExpr) -> CoreExpr.
+%% This function traverses the core parse format, at each level
+%% applying the submited argument function, assumed to do the real
+%% work.
+%%
+%% The "eager" style, where each component of a construct are
+%% descended to before the construct itself, admits that some
+%% companion functions (the F:s) may be made simpler, since it may be
+%% safely assumed that no lower illegal instanced will be
+%% created/uncovered by actions on the current level.
+
+map(F, #c_tuple{es=Es}=R) ->
+ F(R#c_tuple{es=map_list(F, Es)});
+map(F, #c_cons{hd=Hd, tl=Tl}=R) ->
+ F(R#c_cons{hd=map(F, Hd),
+ tl=map(F, Tl)});
+map(F, #c_values{es=Es}=R) ->
+ F(R#c_values{es=map_list(F, Es)});
+
+map(F, #c_alias{var=Var, pat=Pat}=R) ->
+ F(R#c_alias{var=map(F, Var),
+ pat=map(F, Pat)});
+
+map(F, #c_module{defs=Defs}=R) ->
+ F(R#c_module{defs=map_list(F, Defs)});
+map(F, #c_def{val=Val}=R) ->
+ F(R#c_def{val=map(F, Val)});
+
+map(F, #c_fun{vars=Vars, body=Body}=R) ->
+ F(R#c_fun{vars=map_list(F, Vars),
+ body=map(F, Body)});
+map(F, #c_let{vars=Vs, arg=Arg, body=Body}=R) ->
+ F(R#c_let{vars=map_list(F, Vs),
+ arg=map(F, Arg),
+ body=map(F, Body)});
+map(F, #c_letrec{defs=Fs,body=Body}=R) ->
+ F(R#c_letrec{defs=map_list(F, Fs),
+ body=map(F, Body)});
+map(F, #c_seq{arg=Arg, body=Body}=R) ->
+ F(R#c_seq{arg=map(F, Arg),
+ body=map(F, Body)});
+map(F, #c_case{arg=Arg, clauses=Clauses}=R) ->
+ F(R#c_case{arg=map(F, Arg),
+ clauses=map_list(F, Clauses)});
+map(F, #c_clause{pats=Ps, guard=Guard, body=Body}=R) ->
+ F(R#c_clause{pats=map_list(F, Ps),
+ guard=map(F, Guard),
+ body=map(F, Body)});
+map(F, #c_receive{clauses=Cls, timeout=Tout, action=Act}=R) ->
+ F(R#c_receive{clauses=map_list(F, Cls),
+ timeout=map(F, Tout),
+ action=map(F, Act)});
+map(F, #c_apply{op=Op,args=Args}=R) ->
+ F(R#c_apply{op=map(F, Op),
+ args=map_list(F, Args)});
+map(F, #c_call{module=M,name=N,args=Args}=R) ->
+ F(R#c_call{module=map(F, M),
+ name=map(F, N),
+ args=map_list(F, Args)});
+map(F, #c_primop{name=N,args=Args}=R) ->
+ F(R#c_primop{name=map(F, N),
+ args=map_list(F, Args)});
+map(F, #c_try{arg=Expr,vars=Vars,body=Body,evars=Evars,handler=Handler}=R) ->
+ F(R#c_try{arg=map(F, Expr),
+ vars=map(F, Vars),
+ body=map(F, Body),
+ evars=map(F, Evars),
+ handler=map(F, Handler)});
+map(F, #c_catch{body=Body}=R) ->
+ F(R#c_catch{body=map(F, Body)});
+map(F, T) -> F(T). %Atomic nodes.
+
+map_list(F, L) -> lists:map(fun (E) -> map(F, E) end, L).
+
+%% fold(FoldFun, Accumulator, CoreExpr) -> Accumulator.
+%% This function traverses the core parse format, at each level
+%% applying the submited argument function, assumed to do the real
+%% work, and keeping the accumulated result in the A (accumulator)
+%% argument.
+
+fold(F, Acc, #c_tuple{es=Es}=R) ->
+ F(R, fold_list(F, Acc, Es));
+fold(F, Acc, #c_cons{hd=Hd, tl=Tl}=R) ->
+ F(R, fold(F, fold(F, Acc, Hd), Tl));
+fold(F, Acc, #c_values{es=Es}=R) ->
+ F(R, fold_list(F, Acc, Es));
+
+fold(F, Acc, #c_alias{pat=P,var=V}=R) ->
+ F(R, fold(F, fold(F, Acc, P), V));
+
+fold(F, Acc, #c_module{defs=Defs}=R) ->
+ F(R, fold_list(F, Acc, Defs));
+fold(F, Acc, #c_def{val=Val}=R) ->
+ F(R, fold(F, Acc, Val));
+
+fold(F, Acc, #c_fun{vars=Vars, body=Body}=R) ->
+ F(R, fold(F, fold_list(F, Acc, Vars), Body));
+fold(F, Acc, #c_let{vars=Vs, arg=Arg, body=Body}=R) ->
+ F(R, fold(F, fold(F, fold_list(F, Acc, Vs), Arg), Body));
+fold(F, Acc, #c_letrec{defs=Fs,body=Body}=R) ->
+ F(R, fold(F, fold_list(F, Acc, Fs), Body));
+fold(F, Acc, #c_seq{arg=Arg, body=Body}=R) ->
+ F(R, fold(F, fold(F, Acc, Arg), Body));
+fold(F, Acc, #c_case{arg=Arg, clauses=Clauses}=R) ->
+ F(R, fold_list(F, fold(F, Acc, Arg), Clauses));
+fold(F, Acc, #c_clause{pats=Ps,guard=G,body=B}=R) ->
+ F(R, fold(F, fold(F, fold_list(F, Acc, Ps), G), B));
+fold(F, Acc, #c_receive{clauses=Cl, timeout=Ti, action=Ac}=R) ->
+ F(R, fold_list(F, fold(F, fold(F, Acc, Ac), Ti), Cl));
+fold(F, Acc, #c_apply{op=Op, args=Args}=R) ->
+ F(R, fold_list(F, fold(F, Acc, Op), Args));
+fold(F, Acc, #c_call{module=Mod,name=Name,args=Args}=R) ->
+ F(R, fold_list(F, fold(F, fold(F, Acc, Mod), Name), Args));
+fold(F, Acc, #c_primop{name=Name,args=Args}=R) ->
+ F(R, fold_list(F, fold(F, Acc, Name), Args));
+fold(F, Acc, #c_try{arg=E,vars=Vs,body=Body,evars=Evs,handler=H}=R) ->
+ NewB = fold(F, fold_list(F, fold(F, Acc, E), Vs), Body),
+ F(R, fold(F, fold_list(F, NewB, Evs), H));
+fold(F, Acc, #c_catch{body=Body}=R) ->
+ F(R, fold(F, Acc, Body));
+fold(F, Acc, T) -> %Atomic nodes
+ F(T, Acc).
+
+fold_list(F, Acc, L) ->
+ lists:foldl(fun (E, A) -> fold(F, A, E) end, Acc, L).
+
+%% mapfold(MapfoldFun, Accumulator, CoreExpr) -> {CoreExpr,Accumulator}.
+%% This function traverses the core parse format, at each level
+%% applying the submited argument function, assumed to do the real
+%% work, and keeping the accumulated result in the A (accumulator)
+%% argument.
+
+mapfold(F, Acc0, #c_tuple{es=Es0}=R) ->
+ {Es1,Acc1} = mapfold_list(F, Acc0, Es0),
+ F(R#c_tuple{es=Es1}, Acc1);
+mapfold(F, Acc0, #c_cons{hd=H0,tl=T0}=R) ->
+ {H1,Acc1} = mapfold(F, Acc0, H0),
+ {T1,Acc2} = mapfold(F, Acc1, T0),
+ F(R#c_cons{hd=H1,tl=T1}, Acc2);
+mapfold(F, Acc0, #c_values{es=Es0}=R) ->
+ {Es1,Acc1} = mapfold_list(F, Acc0, Es0),
+ F(R#c_values{es=Es1}, Acc1);
+
+mapfold(F, Acc0, #c_alias{pat=P0,var=V0}=R) ->
+ {P1,Acc1} = mapfold(F, Acc0, P0),
+ {V1,Acc2} = mapfold(F, Acc1, V0),
+ F(R#c_alias{pat=P1,var=V1}, Acc2);
+
+mapfold(F, Acc0, #c_module{defs=D0}=R) ->
+ {D1,Acc1} = mapfold_list(F, Acc0, D0),
+ F(R#c_module{defs=D1}, Acc1);
+mapfold(F, Acc0, #c_def{val=V0}=R) ->
+ {V1,Acc1} = mapfold(F, Acc0, V0),
+ F(R#c_def{val=V1}, Acc1);
+
+mapfold(F, Acc0, #c_fun{vars=Vs0, body=B0}=R) ->
+ {Vs1,Acc1} = mapfold_list(F, Acc0, Vs0),
+ {B1,Acc2} = mapfold(F, Acc1, B0),
+ F(R#c_fun{vars=Vs1,body=B1}, Acc2);
+mapfold(F, Acc0, #c_let{vars=Vs0, arg=A0, body=B0}=R) ->
+ {Vs1,Acc1} = mapfold_list(F, Acc0, Vs0),
+ {A1,Acc2} = mapfold(F, Acc1, A0),
+ {B1,Acc3} = mapfold(F, Acc2, B0),
+ F(R#c_let{vars=Vs1,arg=A1,body=B1}, Acc3);
+mapfold(F, Acc0, #c_letrec{defs=Fs0,body=B0}=R) ->
+ {Fs1,Acc1} = mapfold_list(F, Acc0, Fs0),
+ {B1,Acc2} = mapfold(F, Acc1, B0),
+ F(R#c_letrec{defs=Fs1,body=B1}, Acc2);
+mapfold(F, Acc0, #c_seq{arg=A0, body=B0}=R) ->
+ {A1,Acc1} = mapfold(F, Acc0, A0),
+ {B1,Acc2} = mapfold(F, Acc1, B0),
+ F(R#c_seq{arg=A1,body=B1}, Acc2);
+mapfold(F, Acc0, #c_case{arg=A0,clauses=Cs0}=R) ->
+ {A1,Acc1} = mapfold(F, Acc0, A0),
+ {Cs1,Acc2} = mapfold_list(F, Acc1, Cs0),
+ F(R#c_case{arg=A1,clauses=Cs1}, Acc2);
+mapfold(F, Acc0, #c_clause{pats=Ps0,guard=G0,body=B0}=R) ->
+ {Ps1,Acc1} = mapfold_list(F, Acc0, Ps0),
+ {G1,Acc2} = mapfold(F, Acc1, G0),
+ {B1,Acc3} = mapfold(F, Acc2, B0),
+ F(R#c_clause{pats=Ps1,guard=G1,body=B1}, Acc3);
+mapfold(F, Acc0, #c_receive{clauses=Cs0,timeout=T0,action=A0}=R) ->
+ {T1,Acc1} = mapfold(F, Acc0, T0),
+ {Cs1,Acc2} = mapfold_list(F, Acc1, Cs0),
+ {A1,Acc3} = mapfold(F, Acc2, A0),
+ F(R#c_receive{clauses=Cs1,timeout=T1,action=A1}, Acc3);
+mapfold(F, Acc0, #c_apply{op=Op0, args=As0}=R) ->
+ {Op1,Acc1} = mapfold(F, Acc0, Op0),
+ {As1,Acc2} = mapfold_list(F, Acc1, As0),
+ F(R#c_apply{op=Op1,args=As1}, Acc2);
+mapfold(F, Acc0, #c_call{module=M0,name=N0,args=As0}=R) ->
+ {M1,Acc1} = mapfold(F, Acc0, M0),
+ {N1,Acc2} = mapfold(F, Acc1, N0),
+ {As1,Acc3} = mapfold_list(F, Acc2, As0),
+ F(R#c_call{module=M1,name=N1,args=As1}, Acc3);
+mapfold(F, Acc0, #c_primop{name=N0, args=As0}=R) ->
+ {N1,Acc1} = mapfold(F, Acc0, N0),
+ {As1,Acc2} = mapfold_list(F, Acc1, As0),
+ F(R#c_primop{name=N1,args=As1}, Acc2);
+mapfold(F, Acc0, #c_try{arg=E0,vars=Vs0,body=B0,evars=Evs0,handler=H0}=R) ->
+ {E1,Acc1} = mapfold(F, Acc0, E0),
+ {Vs1,Acc2} = mapfold_list(F, Acc1, Vs0),
+ {B1,Acc3} = mapfold(F, Acc2, B0),
+ {Evs1,Acc4} = mapfold_list(F, Acc3, Evs0),
+ {H1,Acc5} = mapfold(F, Acc4, H0),
+ F(R#c_try{arg=E1,vars=Vs1,body=B1,evars=Evs1,handler=H1}, Acc5);
+mapfold(F, Acc0, #c_catch{body=B0}=R) ->
+ {B1,Acc1} = mapfold(F, Acc0, B0),
+ F(R#c_catch{body=B1}, Acc1);
+mapfold(F, Acc, T) -> %Atomic nodes
+ F(T, Acc).
+
+mapfold_list(F, Acc, L) ->
+ lists:mapfoldl(fun (E, A) -> mapfold(F, A, E) end, Acc, L).
+
+%% is_var_used(VarName, Expr) -> true | false.
+%% Test if the variable VarName is used in Expr.
+
+is_var_used(V, B) -> vu_body(V, B).
+
+vu_body(V, #c_values{es=Es}) ->
+ vu_expr_list(V, Es);
+vu_body(V, Body) ->
+ vu_expr(V, Body).
+
+vu_expr(V, #c_var{name=V2}) -> V =:= V2;
+vu_expr(V, #c_cons{hd=H,tl=T}) ->
+ case vu_expr(V, H) of
+ true -> true;
+ false -> vu_expr(V, T)
+ end;
+vu_expr(V, #c_tuple{es=Es}) ->
+ vu_expr_list(V, Es);
+vu_expr(V, #c_binary{segments=Ss}) ->
+ vu_seg_list(V, Ss);
+vu_expr(V, #c_fun{vars=Vs,body=B}) ->
+ %% Variables in fun shadow previous variables
+ case vu_var_list(V, Vs) of
+ true -> false;
+ false -> vu_body(V, B)
+ end;
+vu_expr(V, #c_let{vars=Vs,arg=Arg,body=B}) ->
+ case vu_body(V, Arg) of
+ true -> true;
+ false ->
+ %% Variables in let shadow previous variables.
+ case vu_var_list(V, Vs) of
+ true -> false;
+ false -> vu_body(V, B)
+ end
+ end;
+vu_expr(V, #c_letrec{defs=Fs,body=B}) ->
+ case lists:any(fun (#c_def{val=Fb}) -> vu_body(V, Fb) end, Fs) of
+ true -> true;
+ false -> vu_body(V, B)
+ end;
+vu_expr(V, #c_seq{arg=Arg,body=B}) ->
+ case vu_expr(V, Arg) of
+ true -> true;
+ false -> vu_body(V, B)
+ end;
+vu_expr(V, #c_case{arg=Arg,clauses=Cs}) ->
+ case vu_expr(V, Arg) of
+ true -> true;
+ false -> vu_clauses(V, Cs)
+ end;
+vu_expr(V, #c_receive{clauses=Cs,timeout=T,action=A}) ->
+ case vu_clauses(V, Cs) of
+ true -> true;
+ false ->
+ case vu_expr(V, T) of
+ true -> true;
+ false -> vu_body(V, A)
+ end
+ end;
+vu_expr(V, #c_apply{op=Op,args=As}) ->
+ vu_expr_list(V, [Op|As]);
+vu_expr(V, #c_call{module=M,name=N,args=As}) ->
+ vu_expr_list(V, [M,N|As]);
+vu_expr(V, #c_primop{args=As}) -> %Name is an atom
+ vu_expr_list(V, As);
+vu_expr(V, #c_catch{body=B}) ->
+ vu_body(V, B);
+vu_expr(V, #c_try{arg=E,vars=Vs,body=B,evars=Evs,handler=H}) ->
+ case vu_body(V, E) of
+ true -> true;
+ false ->
+ %% Variables shadow previous ones.
+ case case vu_var_list(V, Vs) of
+ true -> false;
+ false -> vu_body(V, B)
+ end of
+ true -> true;
+ false ->
+ case vu_var_list(V, Evs) of
+ true -> false;
+ false -> vu_body(V, H)
+ end
+ end
+ end;
+vu_expr(_, _) -> false. %Everything else
+
+vu_expr_list(V, Es) ->
+ lists:any(fun(E) -> vu_expr(V, E) end, Es).
+
+vu_seg_list(V, Ss) ->
+ lists:any(fun (#c_bitstr{val=Val,size=Size}) ->
+ case vu_expr(V, Val) of
+ true -> true;
+ false -> vu_expr(V, Size)
+ end
+ end, Ss).
+
+%% vu_clause(VarName, Clause) -> true | false.
+%% vu_clauses(VarName, [Clause]) -> true | false.
+%% Have to get the pattern results right.
+
+vu_clause(V, #c_clause{pats=Ps,guard=G,body=B}) ->
+ case vu_pattern_list(V, Ps) of
+ {true,_Shad} -> true; %It is used
+ {false,true} -> false; %Shadowed
+ {false,false} -> %Not affected
+ case vu_expr(V, G) of
+ true -> true;
+ false ->vu_body(V, B)
+ end
+ end.
+
+vu_clauses(V, Cs) ->
+ lists:any(fun(C) -> vu_clause(V, C) end, Cs).
+
+%% vu_pattern(VarName, Pattern) -> {Used,Shadow}.
+%% vu_pattern_list(VarName, [Pattern]) -> {Used,Shadow}.
+%% Binaries complicate patterns as a variable can both be properly
+%% used, in a bit segment size, and shadow. They can also do both.
+
+%%vu_pattern(V, Pat) -> vu_pattern(V, Pat, {false,false}).
+
+vu_pattern(V, #c_var{name=V2}, St) ->
+ setelement(2, St, V =:= V2);
+vu_pattern(V, #c_cons{hd=H,tl=T}, St0) ->
+ case vu_pattern(V, H, St0) of
+ {true,true}=St1 -> St1; %Nothing more to know
+ St1 -> vu_pattern(V, T, St1)
+ end;
+vu_pattern(V, #c_tuple{es=Es}, St) ->
+ vu_pattern_list(V, Es, St);
+vu_pattern(V, #c_binary{segments=Ss}, St) ->
+ vu_pat_seg_list(V, Ss, St);
+vu_pattern(V, #c_alias{var=Var,pat=P}, St0) ->
+ case vu_pattern(V, Var, St0) of
+ {true,true}=St1 -> St1;
+ St1 -> vu_pattern(V, P, St1)
+ end;
+vu_pattern(_, _, St) -> St.
+
+vu_pattern_list(V, Ps) -> vu_pattern_list(V, Ps, {false,false}).
+
+vu_pattern_list(V, Ps, St0) ->
+ lists:foldl(fun(P, St) -> vu_pattern(V, P, St) end, St0, Ps).
+
+vu_pat_seg_list(V, Ss, St) ->
+ lists:foldl(fun (#c_bitstr{val=Val,size=Size}, St0) ->
+ case vu_pattern(V, Val, St0) of
+ {true,true}=St1 -> St1;
+ {_Used,Shad} -> {vu_expr(V, Size),Shad}
+ end
+ end, St, Ss).
+
+%% vu_var_list(VarName, [Var]) -> true | false.
+
+vu_var_list(V, Vs) ->
+ lists:any(fun (#c_var{name=V2}) -> V =:= V2 end, Vs).
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_lint.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_lint.erl
new file mode 100644
index 0000000000..773d1e53c8
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_lint.erl
@@ -0,0 +1,515 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: core_lint.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
+%%
+%% Purpose : Do necessary checking of Core Erlang code.
+
+%% Check Core module for errors. Seeing this module is used in the
+%% compiler after optimisations wedone more checking than would be
+%% necessary after just parsing. Don't check all constructs.
+%%
+%% We check the following:
+%%
+%% All referred functions, called and exported, are defined.
+%% Format of export list.
+%% Format of attributes
+%% Used variables are defined.
+%% Variables in let and funs.
+%% Patterns case clauses.
+%% Values only as multiple values/variables/patterns.
+%% Return same number of values as requested
+%% Correct number of arguments
+%%
+%% Checks to add:
+%%
+%% Consistency of values/variables
+%% Consistency of function return values/calls.
+%%
+%% We keep the names defined variables and functions in a ordered list
+%% of variable names and function name/arity pairs.
+
+-module(core_lint).
+
+
+-export([module/1,module/2,format_error/1]).
+
+-import(lists, [reverse/1,all/2,foldl/3]).
+-import(ordsets, [add_element/2,is_element/2,union/2]).
+%-import(ordsets, [subtract/2]).
+
+-include("core_parse.hrl").
+
+%% Define the lint state record.
+
+-record(lint, {module=[], %Current module
+ func=[], %Current function
+ errors=[], %Errors
+ warnings=[]}). %Warnings
+
+%% Keep track of defined
+-record(def, {vars=[],
+ funs=[]}).
+
+%%-deftype retcount() -> any | unknown | int().
+
+%% format_error(Error)
+%% Return a string describing the error.
+
+format_error(invalid_exports) -> "invalid exports";
+format_error(invalid_attributes) -> "invalid attributes";
+format_error({undefined_function,{F,A}}) ->
+ io_lib:format("function ~w/~w undefined", [F,A]);
+format_error({undefined_function,{F1,A1},{F2,A2}}) ->
+ io_lib:format("undefined function ~w/~w in ~w/~w", [F1,A1,F2,A2]);
+format_error({illegal_expr,{F,A}}) ->
+ io_lib:format("illegal expression in ~w/~w", [F,A]);
+format_error({illegal_guard,{F,A}}) ->
+ io_lib:format("illegal guard expression in ~w/~w", [F,A]);
+format_error({illegal_pattern,{F,A}}) ->
+ io_lib:format("illegal pattern in ~w/~w", [F,A]);
+format_error({illegal_try,{F,A}}) ->
+ io_lib:format("illegal try expression in ~w/~w", [F,A]);
+format_error({pattern_mismatch,{F,A}}) ->
+ io_lib:format("pattern count mismatch in ~w/~w", [F,A]);
+format_error({return_mismatch,{F,A}}) ->
+ io_lib:format("return count mismatch in ~w/~w", [F,A]);
+format_error({arg_mismatch,{F,A}}) ->
+ io_lib:format("argument count mismatch in ~w/~w", [F,A]);
+format_error({unbound_var,N,{F,A}}) ->
+ io_lib:format("unbound variable ~s in ~w/~w", [N,F,A]);
+format_error({duplicate_var,N,{F,A}}) ->
+ io_lib:format("duplicate variable ~s in ~w/~w", [N,F,A]);
+format_error({not_var,{F,A}}) ->
+ io_lib:format("expecting variable in ~w/~w", [F,A]);
+format_error({not_pattern,{F,A}}) ->
+ io_lib:format("expecting pattern in ~w/~w", [F,A]);
+format_error({not_bs_pattern,{F,A}}) ->
+ io_lib:format("expecting bit syntax pattern in ~w/~w", [F,A]).
+
+%% module(CoreMod) ->
+%% module(CoreMod, [CompileOption]) ->
+%% {ok,[Warning]} | {error,[Error],[Warning]}
+
+module(M) -> module(M, []).
+
+module(#c_module{name=M,exports=Es,attrs=As,defs=Ds}, _Opts) ->
+ Defined = defined_funcs(Ds),
+ St0 = #lint{module=M#c_atom.val},
+ St1 = check_exports(Es, St0),
+ St2 = check_attrs(As, St1),
+ St3 = module_defs(Ds, Defined, St2),
+ St4 = check_state(Es, Defined, St3),
+ return_status(St4).
+
+%% defined_funcs([FuncDef]) -> [Fname].
+
+defined_funcs(Fs) ->
+ foldl(fun (#c_def{name=#c_fname{id=I,arity=A}}, Def) ->
+ add_element({I,A}, Def)
+ end, [], Fs).
+
+%% return_status(State) ->
+%% {ok,[Warning]} | {error,[Error],[Warning]}
+%% Pack errors and warnings properly and return ok | error.
+
+return_status(St) ->
+ Ws = reverse(St#lint.warnings),
+ case reverse(St#lint.errors) of
+ [] -> {ok,[{St#lint.module,Ws}]};
+ Es -> {error,[{St#lint.module,Es}],[{St#lint.module,Ws}]}
+ end.
+
+%% add_error(ErrorDescriptor, State) -> State'
+%% add_warning(ErrorDescriptor, State) -> State'
+%% Note that we don't use line numbers here.
+
+add_error(E, St) -> St#lint{errors=[{none,core_lint,E}|St#lint.errors]}.
+
+%%add_warning(W, St) -> St#lint{warnings=[{none,core_lint,W}|St#lint.warnings]}.
+
+check_exports(Es, St) ->
+ case all(fun (#c_fname{id=Name,arity=Arity}) when
+ atom(Name), integer(Arity) -> true;
+ (_) -> false
+ end, Es) of
+ true -> St;
+ false -> add_error(invalid_exports, St)
+ end.
+
+check_attrs(As, St) ->
+ case all(fun (#c_def{name=#c_atom{},val=V}) -> core_lib:is_literal(V);
+ (_) -> false
+ end, As) of
+ true -> St;
+ false -> add_error(invalid_attributes, St)
+ end.
+
+check_state(Es, Defined, St) ->
+ foldl(fun (#c_fname{id=N,arity=A}, St1) ->
+ F = {N,A},
+ case is_element(F, Defined) of
+ true -> St1;
+ false -> add_error({undefined_function,F}, St)
+ end
+ end, St, Es).
+% Undef = subtract(Es, Defined),
+% St1 = foldl(fun (F, St) -> add_error({undefined_function,F}, St) end,
+% St0, Undef),
+% St1.
+
+%% module_defs(CoreBody, Defined, State) -> State.
+
+module_defs(B, Def, St) ->
+ %% Set top level function name.
+ foldl(fun (Func, St0) ->
+ #c_fname{id=F,arity=A} = Func#c_def.name,
+ St1 = St0#lint{func={F,A}},
+ function(Func, Def, St1)
+ end, St, B).
+
+%% functions([Fdef], Defined, State) -> State.
+
+functions(Fs, Def, St0) ->
+ foldl(fun (F, St) -> function(F, Def, St) end, St0, Fs).
+
+%% function(CoreFunc, Defined, State) -> State.
+
+function(#c_def{name=#c_fname{},val=B}, Def, St) ->
+ %% Body must be a fun!
+ case B of
+ #c_fun{} -> expr(B, Def, any, St);
+ _ -> add_error({illegal_expr,St#lint.func}, St)
+ end.
+
+%% body(Expr, Defined, RetCount, State) -> State.
+
+body(#c_values{es=Es}, Def, Rt, St) ->
+ return_match(Rt, length(Es), expr_list(Es, Def, St));
+body(E, Def, Rt, St0) ->
+ St1 = expr(E, Def, Rt, St0),
+ case core_lib:is_simple_top(E) of
+ true -> return_match(Rt, 1, St1);
+ false -> St1
+ end.
+
+%% guard(Expr, Defined, State) -> State.
+%% Guards are boolean expressions with test wrapped in a protected.
+
+guard(Expr, Def, St) -> gexpr(Expr, Def, 1, St).
+
+%% guard_list([Expr], Defined, State) -> State.
+
+%% guard_list(Es, Def, St0) ->
+%% foldl(fun (E, St) -> guard(E, Def, St) end, St0, Es).
+
+%% gbody(Expr, Defined, RetCount, State) -> State.
+
+gbody(#c_values{es=Es}, Def, Rt, St) ->
+ return_match(Rt, length(Es), gexpr_list(Es, Def, St));
+gbody(E, Def, Rt, St0) ->
+ St1 = gexpr(E, Def, Rt, St0),
+ case core_lib:is_simple_top(E) of
+ true -> return_match(Rt, 1, St1);
+ false -> St1
+ end.
+
+gexpr(#c_var{name=N}, Def, _Rt, St) -> expr_var(N, Def, St);
+gexpr(#c_int{}, _Def, _Rt, St) -> St;
+gexpr(#c_float{}, _Def, _Rt, St) -> St;
+gexpr(#c_atom{}, _Def, _Rt, St) -> St;
+gexpr(#c_char{}, _Def, _Rt, St) -> St;
+gexpr(#c_string{}, _Def, _Rt, St) -> St;
+gexpr(#c_nil{}, _Def, _Rt, St) -> St;
+gexpr(#c_cons{hd=H,tl=T}, Def, _Rt, St) ->
+ gexpr_list([H,T], Def, St);
+gexpr(#c_tuple{es=Es}, Def, _Rt, St) ->
+ gexpr_list(Es, Def, St);
+gexpr(#c_binary{segments=Ss}, Def, _Rt, St) ->
+ gbitstr_list(Ss, Def, St);
+gexpr(#c_seq{arg=Arg,body=B}, Def, Rt, St0) ->
+ St1 = gexpr(Arg, Def, any, St0), %Ignore values
+ gbody(B, Def, Rt, St1);
+gexpr(#c_let{vars=Vs,arg=Arg,body=B}, Def, Rt, St0) ->
+ St1 = gbody(Arg, Def, let_varcount(Vs), St0), %This is a guard body
+ {Lvs,St2} = variable_list(Vs, St1),
+ gbody(B, union(Lvs, Def), Rt, St2);
+gexpr(#c_call{module=#c_atom{val=erlang},
+ name=#c_atom{},
+ args=As}, Def, 1, St) ->
+ gexpr_list(As, Def, St);
+gexpr(#c_primop{name=N,args=As}, Def, _Rt, St0) when record(N, c_atom) ->
+ gexpr_list(As, Def, St0);
+gexpr(#c_try{arg=E,vars=[#c_var{name=X}],body=#c_var{name=X},
+ evars=[#c_var{},#c_var{},#c_var{}],handler=#c_atom{val=false}},
+ Def, Rt, St) ->
+ gbody(E, Def, Rt, St);
+gexpr(_, _, _, St) ->
+ add_error({illegal_guard,St#lint.func}, St).
+
+%% gexpr_list([Expr], Defined, State) -> State.
+
+gexpr_list(Es, Def, St0) ->
+ foldl(fun (E, St) -> gexpr(E, Def, 1, St) end, St0, Es).
+
+%% gbitstr_list([Elem], Defined, State) -> State.
+
+gbitstr_list(Es, Def, St0) ->
+ foldl(fun (E, St) -> gbitstr(E, Def, St) end, St0, Es).
+
+gbitstr(#c_bitstr{val=V,size=S,unit=U,type=T,flags=Fs}, Def, St0) ->
+ St1 = bit_type(U, T, Fs, St0),
+ gexpr_list([V,S], Def, St1).
+
+%% expr(Expr, Defined, RetCount, State) -> State.
+
+expr(#c_var{name=N}, Def, _Rt, St) -> expr_var(N, Def, St);
+expr(#c_int{}, _Def, _Rt, St) -> St;
+expr(#c_float{}, _Def, _Rt, St) -> St;
+expr(#c_atom{}, _Def, _Rt, St) -> St;
+expr(#c_char{}, _Def, _Rt, St) -> St;
+expr(#c_string{}, _Def, _Rt, St) -> St;
+expr(#c_nil{}, _Def, _Rt, St) -> St;
+expr(#c_cons{hd=H,tl=T}, Def, _Rt, St) ->
+ expr_list([H,T], Def, St);
+expr(#c_tuple{es=Es}, Def, _Rt, St) ->
+ expr_list(Es, Def, St);
+expr(#c_binary{segments=Ss}, Def, _Rt, St) ->
+ bitstr_list(Ss, Def, St);
+expr(#c_fname{id=I,arity=A}, Def, _Rt, St) ->
+ expr_fname({I,A}, Def, St);
+expr(#c_fun{vars=Vs,body=B}, Def, Rt, St0) ->
+ {Vvs,St1} = variable_list(Vs, St0),
+ return_match(Rt, 1, body(B, union(Vvs, Def), any, St1));
+expr(#c_seq{arg=Arg,body=B}, Def, Rt, St0) ->
+ St1 = expr(Arg, Def, any, St0), %Ignore values
+ body(B, Def, Rt, St1);
+expr(#c_let{vars=Vs,arg=Arg,body=B}, Def, Rt, St0) ->
+ St1 = body(Arg, Def, let_varcount(Vs), St0), %This is a body
+ {Lvs,St2} = variable_list(Vs, St1),
+ body(B, union(Lvs, Def), Rt, St2);
+expr(#c_letrec{defs=Fs,body=B}, Def0, Rt, St0) ->
+ Def1 = union(defined_funcs(Fs), Def0), %All defined stuff
+ St1 = functions(Fs, Def1, St0),
+ body(B, Def1, Rt, St1#lint{func=St0#lint.func});
+expr(#c_case{arg=Arg,clauses=Cs}, Def, Rt, St0) ->
+ Pc = case_patcount(Cs),
+ St1 = body(Arg, Def, Pc, St0),
+ clauses(Cs, Def, Pc, Rt, St1);
+expr(#c_receive{clauses=Cs,timeout=T,action=A}, Def, Rt, St0) ->
+ St1 = expr(T, Def, 1, St0),
+ St2 = body(A, Def, Rt, St1),
+ clauses(Cs, Def, 1, Rt, St2);
+expr(#c_apply{op=Op,args=As}, Def, _Rt, St0) ->
+ St1 = apply_op(Op, Def, length(As), St0),
+ expr_list(As, Def, St1);
+expr(#c_call{module=M,name=N,args=As}, Def, _Rt, St0) ->
+ St1 = expr(M, Def, 1, St0),
+ St2 = expr(N, Def, 1, St1),
+ expr_list(As, Def, St2);
+expr(#c_primop{name=N,args=As}, Def, _Rt, St0) when record(N, c_atom) ->
+ expr_list(As, Def, St0);
+expr(#c_catch{body=B}, Def, Rt, St) ->
+ return_match(Rt, 1, body(B, Def, 1, St));
+expr(#c_try{arg=A,vars=Vs,body=B,evars=Evs,handler=H}, Def, Rt, St0) ->
+ St1 = case length(Evs) of
+ 2 -> St0;
+ _ -> add_error({illegal_try,St0#lint.func}, St0)
+ end,
+ St2 = body(A, Def, let_varcount(Vs), St1),
+ {Ns,St3} = variable_list(Vs, St2),
+ St4 = body(B, union(Ns, Def), Rt, St3),
+ {Ens,St5} = variable_list(Evs, St4),
+ body(H, union(Ens, Def), Rt, St5);
+expr(_, _, _, St) ->
+ %%io:fwrite("clint: ~p~n", [Other]),
+ add_error({illegal_expr,St#lint.func}, St).
+
+%% expr_list([Expr], Defined, State) -> State.
+
+expr_list(Es, Def, St0) ->
+ foldl(fun (E, St) -> expr(E, Def, 1, St) end, St0, Es).
+
+%% bitstr_list([Elem], Defined, State) -> State.
+
+bitstr_list(Es, Def, St0) ->
+ foldl(fun (E, St) -> bitstr(E, Def, St) end, St0, Es).
+
+bitstr(#c_bitstr{val=V,size=S,unit=U,type=T,flags=Fs}, Def, St0) ->
+ St1 = bit_type(U, T, Fs, St0),
+ expr_list([V,S], Def, St1).
+
+%% apply_op(Op, Defined, ArgCount, State) -> State.
+%% A apply op is either an fname or an expression.
+
+apply_op(#c_fname{id=I,arity=A}, Def, Ac, St0) ->
+ St1 = expr_fname({I,A}, Def, St0),
+ arg_match(Ac, A, St1);
+apply_op(E, Def, _, St) -> expr(E, Def, 1, St). %Hard to check
+
+%% expr_var(VarName, Defined, State) -> State.
+
+expr_var(N, Def, St) ->
+ case is_element(N, Def) of
+ true -> St;
+ false -> add_error({unbound_var,N,St#lint.func}, St)
+ end.
+
+%% expr_fname(Fname, Defined, State) -> State.
+
+expr_fname(Fname, Def, St) ->
+ case is_element(Fname, Def) of
+ true -> St;
+ false -> add_error({undefined_function,Fname,St#lint.func}, St)
+ end.
+
+%% let_varcount([Var]) -> int().
+
+let_varcount([]) -> any; %Ignore values
+let_varcount(Es) -> length(Es).
+
+%% case_patcount([Clause]) -> int().
+
+case_patcount([#c_clause{pats=Ps}|_]) -> length(Ps).
+
+%% clauses([Clause], Defined, PatCount, RetCount, State) -> State.
+
+clauses(Cs, Def, Pc, Rt, St0) ->
+ foldl(fun (C, St) -> clause(C, Def, Pc, Rt, St) end, St0, Cs).
+
+%% clause(Clause, Defined, PatCount, RetCount, State) -> State.
+
+clause(#c_clause{pats=Ps,guard=G,body=B}, Def0, Pc, Rt, St0) ->
+ St1 = pattern_match(Pc, length(Ps), St0),
+ {Pvs,St2} = pattern_list(Ps, Def0, St1),
+ Def1 = union(Pvs, Def0),
+ St3 = guard(G, Def1, St2),
+ body(B, Def1, Rt, St3).
+
+%% variable(Var, [PatVar], State) -> {[VarName],State}.
+
+variable(#c_var{name=N}, Ps, St) ->
+ case is_element(N, Ps) of
+ true -> {[],add_error({duplicate_var,N,St#lint.func}, St)};
+ false -> {[N],St}
+ end;
+variable(_, Def, St) -> {Def,add_error({not_var,St#lint.func}, St)}.
+
+%% variable_list([Var], State) -> {[Var],State}.
+%% variable_list([Var], [PatVar], State) -> {[Var],State}.
+
+variable_list(Vs, St) -> variable_list(Vs, [], St).
+
+variable_list(Vs, Ps, St) ->
+ foldl(fun (V, {Ps0,St0}) ->
+ {Vvs,St1} = variable(V, Ps0, St0),
+ {union(Vvs, Ps0),St1}
+ end, {Ps,St}, Vs).
+
+%% pattern(Pattern, Defined, State) -> {[PatVar],State}.
+%% pattern(Pattern, Defined, [PatVar], State) -> {[PatVar],State}.
+%% Patterns are complicated by sizes in binaries. These are pure
+%% input variables which create no bindings. We, therefor, need to
+%% carry around the original defined variables to get the correct
+%% handling.
+
+%% pattern(P, Def, St) -> pattern(P, Def, [], St).
+
+pattern(#c_var{name=N}, Def, Ps, St) ->
+ pat_var(N, Def, Ps, St);
+pattern(#c_int{}, _Def, Ps, St) -> {Ps,St};
+pattern(#c_float{}, _Def, Ps, St) -> {Ps,St};
+pattern(#c_atom{}, _Def, Ps, St) -> {Ps,St};
+pattern(#c_char{}, _Def, Ps, St) -> {Ps,St};
+pattern(#c_string{}, _Def, Ps, St) -> {Ps,St};
+pattern(#c_nil{}, _Def, Ps, St) -> {Ps,St};
+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) ->
+ pat_bin(Ss, Def, Ps, St);
+pattern(#c_alias{var=V,pat=P}, Def, Ps, St0) ->
+ {Vvs,St1} = variable(V, Ps, St0),
+ pattern(P, Def, union(Vvs, Ps), St1);
+pattern(_, _, Ps, St) -> {Ps,add_error({not_pattern,St#lint.func}, St)}.
+
+pat_var(N, _Def, Ps, St) ->
+ case is_element(N, Ps) of
+ true -> {Ps,add_error({duplicate_var,N,St#lint.func}, St)};
+ false -> {add_element(N, Ps),St}
+ end.
+
+%% pat_bin_list([Elem], Defined, [PatVar], State) -> {[PatVar],State}.
+
+pat_bin(Es, Def, Ps0, St0) ->
+ foldl(fun (E, {Ps,St}) -> pat_segment(E, Def, Ps, St) end, {Ps0,St0}, Es).
+
+pat_segment(#c_bitstr{val=V,size=S,unit=U,type=T,flags=Fs}, Def, Ps, St0) ->
+ St1 = bit_type(U, T, Fs, St0),
+ St2 = pat_bit_expr(S, T, Def, St1),
+ pattern(V, Def, Ps, St2);
+pat_segment(_, _, Ps, St) ->
+ {Ps,add_error({not_bs_pattern,St#lint.func}, St)}.
+
+%% pat_bit_expr(SizePat, Type, Defined, State) -> State.
+%% Check the Size pattern, this is an input! Be a bit tough here.
+
+pat_bit_expr(#c_int{val=I}, _, _, St) when I >= 0 -> St;
+pat_bit_expr(#c_var{name=N}, _, Def, St) ->
+ expr_var(N, Def, St);
+pat_bit_expr(#c_atom{val=all}, binary, _Def, St) -> St;
+pat_bit_expr(_, _, _, St) ->
+ add_error({illegal_expr,St#lint.func}, St).
+
+bit_type(Unit, Type, Flags, St) ->
+ U = core_lib:literal_value(Unit),
+ T = core_lib:literal_value(Type),
+ Fs = core_lib:literal_value(Flags),
+ case erl_bits:set_bit_type(default, [T,{unit,U}|Fs]) of
+ {ok,_,_} -> St;
+ {error,E} -> add_error({E,St#lint.func}, St)
+ end.
+
+%% pattern_list([Var], Defined, State) -> {[PatVar],State}.
+%% pattern_list([Var], Defined, [PatVar], State) -> {[PatVar],State}.
+
+pattern_list(Pats, Def, St) -> pattern_list(Pats, Def, [], St).
+
+pattern_list(Pats, Def, Ps0, St0) ->
+ foldl(fun (P, {Ps,St}) -> pattern(P, Def, Ps, St) end, {Ps0,St0}, Pats).
+
+%% pattern_match(Required, Supplied, State) -> State.
+%% Check that the required number of patterns match the supplied.
+
+pattern_match(N, N, St) -> St;
+pattern_match(_Req, _Sup, St) ->
+ add_error({pattern_mismatch,St#lint.func}, St).
+
+%% return_match(Required, Supplied, State) -> State.
+%% Check that the required number of return values match the supplied.
+
+return_match(any, _Sup, St) -> St;
+return_match(_Req, unknown, St) -> St;
+return_match(N, N, St) -> St;
+return_match(_Req, _Sup, St) ->
+ add_error({return_mismatch,St#lint.func}, St).
+
+%% arg_match(Required, Supplied, State) -> State.
+
+arg_match(_Req, unknown, St) -> St;
+arg_match(N, N, St) -> St;
+arg_match(_Req, _Sup, St) ->
+ add_error({arg_mismatch,St#lint.func}, St).
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_parse.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_parse.erl
new file mode 100644
index 0000000000..77c33c561b
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_parse.erl
@@ -0,0 +1,4909 @@
+-module(core_parse).
+-define(THIS_MODULE, core_parse).
+-export([parse/1, parse_and_scan/1, format_error/1]).
+
+-export([abstract/1,abstract/2,normalise/1]).
+
+%% The following directive is needed for (significantly) faster compilation
+%% of the generated .erl file by the HiPE compiler. Please do not remove.
+-compile([{hipe,[{regalloc,linear_scan}]}]).
+
+-include("core_parse.hrl").
+
+tok_val(T) -> element(3, T).
+tok_line(T) -> element(2, T).
+
+abstract(T, _N) -> abstract(T).
+
+abstract(Term) -> core_lib:make_literal(Term).
+
+normalise(Core) -> core_lib:literal_value(Core).
+
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: core_parse.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
+%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% The parser generator will insert appropriate declarations before this line.%
+
+parse(Tokens) ->
+ case catch yeccpars1(Tokens, false, 0, [], []) of
+ error ->
+ Errorline =
+ if Tokens == [] -> 0; true -> element(2, hd(Tokens)) end,
+ {error,
+ {Errorline, ?THIS_MODULE, "syntax error at or after this line."}};
+ Other ->
+ Other
+ end.
+
+parse_and_scan({Mod, Fun, Args}) ->
+ case apply(Mod, Fun, Args) of
+ {eof, _} ->
+ {ok, eof};
+ {error, Descriptor, _} ->
+ {error, Descriptor};
+ {ok, Tokens, _} ->
+ yeccpars1(Tokens, {Mod, Fun, Args}, 0, [], [])
+ end.
+
+format_error(Message) ->
+ case io_lib:deep_char_list(Message) of
+ true ->
+ Message;
+ _ ->
+ io_lib:write(Message)
+ end.
+
+% To be used in grammar files to throw an error message to the parser toplevel.
+% Doesn't have to be exported!
+return_error(Line, Message) ->
+ throw({error, {Line, ?THIS_MODULE, Message}}).
+
+
+% Don't change yeccpars1/6 too much, it is called recursively by yeccpars2/8!
+yeccpars1([Token | Tokens], Tokenizer, State, States, Vstack) ->
+ yeccpars2(State, element(1, Token), States, Vstack, Token, Tokens,
+ Tokenizer);
+yeccpars1([], {M, F, A}, State, States, Vstack) ->
+ case catch apply(M, F, A) of
+ {eof, Endline} ->
+ {error, {Endline, ?THIS_MODULE, "end_of_file"}};
+ {error, Descriptor, _Endline} ->
+ {error, Descriptor};
+ {'EXIT', Reason} ->
+ {error, {0, ?THIS_MODULE, Reason}};
+ {ok, Tokens, _Endline} ->
+ case catch yeccpars1(Tokens, {M, F, A}, State, States, Vstack) of
+ error ->
+ Errorline = element(2, hd(Tokens)),
+ {error, {Errorline, ?THIS_MODULE,
+ "syntax error at or after this line."}};
+ Other ->
+ Other
+ end
+ end;
+yeccpars1([], false, State, States, Vstack) ->
+ yeccpars2(State, '$end', States, Vstack, {'$end', 999999}, [], false).
+
+% For internal use only.
+yeccerror(Token) ->
+ {error,
+ {element(2, Token), ?THIS_MODULE,
+ ["syntax error before: ", yecctoken2string(Token)]}}.
+
+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_string(S);
+yecctoken2string({reserved_symbol, _, A}) -> io_lib:format('~w', [A]);
+yecctoken2string({_Cat, _, Val}) -> io_lib:format('~w', [Val]);
+
+yecctoken2string({'dot', _}) -> io_lib:format('~w', ['.']);
+yecctoken2string({'$end', _}) ->
+ [];
+yecctoken2string({Other, _}) when atom(Other) ->
+ io_lib:format('~w', [Other]);
+yecctoken2string(Other) ->
+ io_lib:write(Other).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+yeccpars2(0, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 1, [0 | __Ss], [__T | __Stack]);
+yeccpars2(0, 'module', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 2, [0 | __Ss], [__T | __Stack]);
+yeccpars2(0, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(1, 'module', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 313, [1 | __Ss], [__T | __Stack]);
+yeccpars2(1, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(2, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 4, [2 | __Ss], [__T | __Stack]);
+yeccpars2(2, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(3, '$end', _, __Stack, _, _, _) ->
+ {ok, hd(__Stack)};
+yeccpars2(3, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(4, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 5, [4 | __Ss], [__T | __Stack]);
+yeccpars2(4, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(5, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 11, [5 | __Ss], [__T | __Stack]);
+yeccpars2(5, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 306, [5 | __Ss], [__T | __Stack]);
+yeccpars2(5, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(6, 'attributes', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 7, [6 | __Ss], [__T | __Stack]);
+yeccpars2(6, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(7, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 276, [7 | __Ss], [__T | __Stack]);
+yeccpars2(7, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(8, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 9, [8 | __Ss], [__T | __Stack]);
+yeccpars2(8, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 11, [8 | __Ss], [__T | __Stack]);
+yeccpars2(8, __Cat, __Ss, __Stack, __T, __Ts, __Tzr) ->
+ __Val = [],
+ yeccpars2(13, __Cat, [8 | __Ss], [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(9, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 11, [9 | __Ss], [__T | __Stack]);
+yeccpars2(9, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(10, '=', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 20, [10 | __Ss], [__T | __Stack]);
+yeccpars2(10, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(11, '/', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 18, [11 | __Ss], [__T | __Stack]);
+yeccpars2(11, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(12, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 9, [12 | __Ss], [__T | __Stack]);
+yeccpars2(12, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 11, [12 | __Ss], [__T | __Stack]);
+yeccpars2(12, __Cat, __Ss, __Stack, __T, __Ts, __Tzr) ->
+ __Val = [],
+ yeccpars2(17, __Cat, [12 | __Ss], [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(13, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(module_defs, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(14, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(anno_function_name, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(15, 'end', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 16, [15 | __Ss], [__T | __Stack]);
+yeccpars2(15, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(16, __Cat, __Ss, [__6,__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_module{name = #c_atom{val = tok_val(__2)}, exports = __3, attrs = __4, defs = __5},
+ __Nss = lists:nthtail(5, __Ss),
+ yeccpars2(yeccgoto(module_definition, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(17, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1|__2],
+ __Nss = lists:nthtail(1, __Ss),
+ yeccpars2(yeccgoto(function_definitions, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(18, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 19, [18 | __Ss], [__T | __Stack]);
+yeccpars2(18, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(19, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_fname{id = tok_val(__1), arity = tok_val(__3)},
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(function_name, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(20, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [20 | __Ss], [__T | __Stack]);
+yeccpars2(20, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 21, [20 | __Ss], [__T | __Stack]);
+yeccpars2(20, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(21, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [21 | __Ss], [__T | __Stack]);
+yeccpars2(21, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(22, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_def{name = __1, val = __3},
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(function_definition, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(23, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 25, [23 | __Ss], [__T | __Stack]);
+yeccpars2(23, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(24, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(anno_fun, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(25, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 27, [25 | __Ss], [__T | __Stack]);
+yeccpars2(25, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 26, [25 | __Ss], [__T | __Stack]);
+yeccpars2(25, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [25 | __Ss], [__T | __Stack]);
+yeccpars2(25, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(26, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [26 | __Ss], [__T | __Stack]);
+yeccpars2(26, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(27, '->', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 265, [27 | __Ss], [__T | __Stack]);
+yeccpars2(27, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(28, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 263, [28 | __Ss], [__T | __Stack]);
+yeccpars2(28, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1],
+ yeccpars2(yeccgoto(anno_variables, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(29, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 32, [29 | __Ss], [__T | __Stack]);
+yeccpars2(29, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(30, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_var{name = tok_val(__1)},
+ yeccpars2(yeccgoto(variable, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(31, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(anno_variable, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(32, '->', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 33, [32 | __Ss], [__T | __Stack]);
+yeccpars2(32, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(33, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [33 | __Ss], [__T | __Stack]);
+yeccpars2(33, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(34, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 247, [34 | __Ss], [__T | __Stack]);
+yeccpars2(34, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(35, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [35 | __Ss], [__T | __Stack]);
+yeccpars2(35, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(36, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, '>', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 240, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [36 | __Ss], [__T | __Stack]);
+yeccpars2(36, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(37, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 149, [37 | __Ss], [__T | __Stack]);
+yeccpars2(37, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(38, __Cat, __Ss, [__6,__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_fun{vars = __3, body = __6},
+ __Nss = lists:nthtail(5, __Ss),
+ yeccpars2(yeccgoto(fun_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(39, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(40, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [40 | __Ss], [__T | __Stack]);
+yeccpars2(40, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(41, '/', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 18, [41 | __Ss], [__T | __Stack]);
+yeccpars2(41, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_atom{val = tok_val(__1)},
+ yeccpars2(yeccgoto(atomic_literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(42, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(43, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(44, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [44 | __Ss], [__T | __Stack]);
+yeccpars2(44, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(45, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(46, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [46 | __Ss], [__T | __Stack]);
+yeccpars2(46, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(47, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(48, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [48 | __Ss], [__T | __Stack]);
+yeccpars2(48, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(49, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(50, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_char{val = tok_val(__1)},
+ yeccpars2(yeccgoto(atomic_literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(51, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(52, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [52 | __Ss], [__T | __Stack]);
+yeccpars2(52, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(53, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(anno_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(54, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_float{val = tok_val(__1)},
+ yeccpars2(yeccgoto(atomic_literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(55, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(56, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(57, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_int{val = tok_val(__1)},
+ yeccpars2(yeccgoto(atomic_literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(58, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 83, [58 | __Ss], [__T | __Stack]);
+yeccpars2(58, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 26, [58 | __Ss], [__T | __Stack]);
+yeccpars2(58, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [58 | __Ss], [__T | __Stack]);
+yeccpars2(58, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(59, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(60, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 9, [60 | __Ss], [__T | __Stack]);
+yeccpars2(60, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 11, [60 | __Ss], [__T | __Stack]);
+yeccpars2(60, __Cat, __Ss, __Stack, __T, __Ts, __Tzr) ->
+ __Val = [],
+ yeccpars2(210, __Cat, [60 | __Ss], [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(61, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(62, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_nil{},
+ yeccpars2(yeccgoto(atomic_literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(63, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 208, [63 | __Ss], [__T | __Stack]);
+yeccpars2(63, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(64, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(65, 'after', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 99, [65 | __Ss], [__T | __Stack]);
+yeccpars2(65, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 97, [65 | __Ss], [__T | __Stack]);
+yeccpars2(65, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 96, [65 | __Ss], [__T | __Stack]);
+yeccpars2(65, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [65 | __Ss], [__T | __Stack]);
+yeccpars2(65, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 104, [65 | __Ss], [__T | __Stack]);
+yeccpars2(65, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [65 | __Ss], [__T | __Stack]);
+yeccpars2(65, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [65 | __Ss], [__T | __Stack]);
+yeccpars2(65, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [65 | __Ss], [__T | __Stack]);
+yeccpars2(65, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [65 | __Ss], [__T | __Stack]);
+yeccpars2(65, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 95, [65 | __Ss], [__T | __Stack]);
+yeccpars2(65, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 98, [65 | __Ss], [__T | __Stack]);
+yeccpars2(65, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 114, [65 | __Ss], [__T | __Stack]);
+yeccpars2(65, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(66, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(67, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(68, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(69, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_string{val = tok_val(__1)},
+ yeccpars2(yeccgoto(atomic_literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(70, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [70 | __Ss], [__T | __Stack]);
+yeccpars2(70, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(71, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(72, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(73, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(74, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 77, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [74 | __Ss], [__T | __Stack]);
+yeccpars2(74, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(75, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 79, [75 | __Ss], [__T | __Stack]);
+yeccpars2(75, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1],
+ yeccpars2(yeccgoto(anno_expressions, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(76, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 78, [76 | __Ss], [__T | __Stack]);
+yeccpars2(76, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(77, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_tuple{es = []},
+ __Nss = lists:nthtail(1, __Ss),
+ yeccpars2(yeccgoto(tuple, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(78, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_tuple{es = __2},
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(tuple, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(79, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [79 | __Ss], [__T | __Stack]);
+yeccpars2(79, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(80, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1|__3],
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(anno_expressions, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(81, 'of', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 82, [81 | __Ss], [__T | __Stack]);
+yeccpars2(81, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(82, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 83, [82 | __Ss], [__T | __Stack]);
+yeccpars2(82, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 26, [82 | __Ss], [__T | __Stack]);
+yeccpars2(82, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [82 | __Ss], [__T | __Stack]);
+yeccpars2(82, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(83, '>', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 92, [83 | __Ss], [__T | __Stack]);
+yeccpars2(83, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 26, [83 | __Ss], [__T | __Stack]);
+yeccpars2(83, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [83 | __Ss], [__T | __Stack]);
+yeccpars2(83, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(84, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1],
+ yeccpars2(yeccgoto(let_vars, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(85, '->', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 86, [85 | __Ss], [__T | __Stack]);
+yeccpars2(85, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(86, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [86 | __Ss], [__T | __Stack]);
+yeccpars2(86, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(87, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 88, [87 | __Ss], [__T | __Stack]);
+yeccpars2(87, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(88, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 83, [88 | __Ss], [__T | __Stack]);
+yeccpars2(88, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 26, [88 | __Ss], [__T | __Stack]);
+yeccpars2(88, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [88 | __Ss], [__T | __Stack]);
+yeccpars2(88, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(89, '->', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 90, [89 | __Ss], [__T | __Stack]);
+yeccpars2(89, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(90, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [90 | __Ss], [__T | __Stack]);
+yeccpars2(90, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(91, __Cat, __Ss, [__10,__9,__8,__7,__6,__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = if length(__8) == 2 -> #c_try{arg = __2, vars = __4, body = __6, evars = __8, handler = __10}; true -> return_error(tok_line(__7),"expected 2 exception variables in 'try'") end,
+ __Nss = lists:nthtail(9, __Ss),
+ yeccpars2(yeccgoto(try_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(92, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [],
+ __Nss = lists:nthtail(1, __Ss),
+ yeccpars2(yeccgoto(let_vars, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(93, '>', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 94, [93 | __Ss], [__T | __Stack]);
+yeccpars2(93, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(94, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __2,
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(let_vars, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(95, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 190, [95 | __Ss], [__T | __Stack]);
+yeccpars2(95, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(96, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 97, [96 | __Ss], [__T | __Stack]);
+yeccpars2(96, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [96 | __Ss], [__T | __Stack]);
+yeccpars2(96, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 104, [96 | __Ss], [__T | __Stack]);
+yeccpars2(96, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [96 | __Ss], [__T | __Stack]);
+yeccpars2(96, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [96 | __Ss], [__T | __Stack]);
+yeccpars2(96, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [96 | __Ss], [__T | __Stack]);
+yeccpars2(96, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 115, [96 | __Ss], [__T | __Stack]);
+yeccpars2(96, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [96 | __Ss], [__T | __Stack]);
+yeccpars2(96, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 95, [96 | __Ss], [__T | __Stack]);
+yeccpars2(96, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 98, [96 | __Ss], [__T | __Stack]);
+yeccpars2(96, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 114, [96 | __Ss], [__T | __Stack]);
+yeccpars2(96, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(97, '>', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 182, [97 | __Ss], [__T | __Stack]);
+yeccpars2(97, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [97 | __Ss], [__T | __Stack]);
+yeccpars2(97, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 104, [97 | __Ss], [__T | __Stack]);
+yeccpars2(97, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [97 | __Ss], [__T | __Stack]);
+yeccpars2(97, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [97 | __Ss], [__T | __Stack]);
+yeccpars2(97, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [97 | __Ss], [__T | __Stack]);
+yeccpars2(97, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 115, [97 | __Ss], [__T | __Stack]);
+yeccpars2(97, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [97 | __Ss], [__T | __Stack]);
+yeccpars2(97, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 95, [97 | __Ss], [__T | __Stack]);
+yeccpars2(97, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 98, [97 | __Ss], [__T | __Stack]);
+yeccpars2(97, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 114, [97 | __Ss], [__T | __Stack]);
+yeccpars2(97, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(98, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [98 | __Ss], [__T | __Stack]);
+yeccpars2(98, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 104, [98 | __Ss], [__T | __Stack]);
+yeccpars2(98, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [98 | __Ss], [__T | __Stack]);
+yeccpars2(98, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [98 | __Ss], [__T | __Stack]);
+yeccpars2(98, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [98 | __Ss], [__T | __Stack]);
+yeccpars2(98, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 115, [98 | __Ss], [__T | __Stack]);
+yeccpars2(98, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [98 | __Ss], [__T | __Stack]);
+yeccpars2(98, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 95, [98 | __Ss], [__T | __Stack]);
+yeccpars2(98, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 98, [98 | __Ss], [__T | __Stack]);
+yeccpars2(98, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 114, [98 | __Ss], [__T | __Stack]);
+yeccpars2(98, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 149, [98 | __Ss], [__T | __Stack]);
+yeccpars2(98, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(99, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [99 | __Ss], [__T | __Stack]);
+yeccpars2(99, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(100, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 97, [100 | __Ss], [__T | __Stack]);
+yeccpars2(100, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 96, [100 | __Ss], [__T | __Stack]);
+yeccpars2(100, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [100 | __Ss], [__T | __Stack]);
+yeccpars2(100, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 104, [100 | __Ss], [__T | __Stack]);
+yeccpars2(100, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [100 | __Ss], [__T | __Stack]);
+yeccpars2(100, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [100 | __Ss], [__T | __Stack]);
+yeccpars2(100, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [100 | __Ss], [__T | __Stack]);
+yeccpars2(100, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [100 | __Ss], [__T | __Stack]);
+yeccpars2(100, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 95, [100 | __Ss], [__T | __Stack]);
+yeccpars2(100, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 98, [100 | __Ss], [__T | __Stack]);
+yeccpars2(100, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 114, [100 | __Ss], [__T | __Stack]);
+yeccpars2(100, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1],
+ yeccpars2(yeccgoto(anno_clauses, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(101, 'after', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 99, [101 | __Ss], [__T | __Stack]);
+yeccpars2(101, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(102, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1],
+ yeccpars2(yeccgoto(clause_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(103, '=', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 162, [103 | __Ss], [__T | __Stack]);
+yeccpars2(103, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(anno_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(104, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_atom{val = tok_val(__1)},
+ yeccpars2(yeccgoto(atomic_literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(105, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(atomic_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(106, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(other_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(107, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(other_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(108, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(anno_clause, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(109, 'when', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 164, [109 | __Ss], [__T | __Stack]);
+yeccpars2(109, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(110, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(other_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(111, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(anno_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(112, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = begin
+ {T,A} = __2, #c_receive{clauses = [], timeout = T, action = A}
+ end,
+ __Nss = lists:nthtail(1, __Ss),
+ yeccpars2(yeccgoto(receive_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(113, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(other_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(114, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [114 | __Ss], [__T | __Stack]);
+yeccpars2(114, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 104, [114 | __Ss], [__T | __Stack]);
+yeccpars2(114, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [114 | __Ss], [__T | __Stack]);
+yeccpars2(114, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [114 | __Ss], [__T | __Stack]);
+yeccpars2(114, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [114 | __Ss], [__T | __Stack]);
+yeccpars2(114, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 115, [114 | __Ss], [__T | __Stack]);
+yeccpars2(114, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [114 | __Ss], [__T | __Stack]);
+yeccpars2(114, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 95, [114 | __Ss], [__T | __Stack]);
+yeccpars2(114, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 98, [114 | __Ss], [__T | __Stack]);
+yeccpars2(114, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 114, [114 | __Ss], [__T | __Stack]);
+yeccpars2(114, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 118, [114 | __Ss], [__T | __Stack]);
+yeccpars2(114, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(115, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [115 | __Ss], [__T | __Stack]);
+yeccpars2(115, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 104, [115 | __Ss], [__T | __Stack]);
+yeccpars2(115, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [115 | __Ss], [__T | __Stack]);
+yeccpars2(115, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [115 | __Ss], [__T | __Stack]);
+yeccpars2(115, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [115 | __Ss], [__T | __Stack]);
+yeccpars2(115, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 26, [115 | __Ss], [__T | __Stack]);
+yeccpars2(115, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [115 | __Ss], [__T | __Stack]);
+yeccpars2(115, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 95, [115 | __Ss], [__T | __Stack]);
+yeccpars2(115, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 98, [115 | __Ss], [__T | __Stack]);
+yeccpars2(115, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 114, [115 | __Ss], [__T | __Stack]);
+yeccpars2(115, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(116, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 120, [116 | __Ss], [__T | __Stack]);
+yeccpars2(116, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1],
+ yeccpars2(yeccgoto(anno_patterns, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(117, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 119, [117 | __Ss], [__T | __Stack]);
+yeccpars2(117, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(118, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_tuple{es = []},
+ __Nss = lists:nthtail(1, __Ss),
+ yeccpars2(yeccgoto(tuple_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(119, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_tuple{es = __2},
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(tuple_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(120, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [120 | __Ss], [__T | __Stack]);
+yeccpars2(120, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 104, [120 | __Ss], [__T | __Stack]);
+yeccpars2(120, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [120 | __Ss], [__T | __Stack]);
+yeccpars2(120, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [120 | __Ss], [__T | __Stack]);
+yeccpars2(120, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [120 | __Ss], [__T | __Stack]);
+yeccpars2(120, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 115, [120 | __Ss], [__T | __Stack]);
+yeccpars2(120, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [120 | __Ss], [__T | __Stack]);
+yeccpars2(120, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 95, [120 | __Ss], [__T | __Stack]);
+yeccpars2(120, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 98, [120 | __Ss], [__T | __Stack]);
+yeccpars2(120, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 114, [120 | __Ss], [__T | __Stack]);
+yeccpars2(120, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(121, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1|__3],
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(anno_patterns, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(122, '=', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 162, [122 | __Ss], [__T | __Stack]);
+yeccpars2(122, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(123, '-|', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 159, [123 | __Ss], [__T | __Stack]);
+yeccpars2(123, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(124, '-|', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 125, [124 | __Ss], [__T | __Stack]);
+yeccpars2(124, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(anno_variable, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(125, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 126, [125 | __Ss], [__T | __Stack]);
+yeccpars2(125, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(126, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 129, [126 | __Ss], [__T | __Stack]);
+yeccpars2(126, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 142, [126 | __Ss], [__T | __Stack]);
+yeccpars2(126, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 140, [126 | __Ss], [__T | __Stack]);
+yeccpars2(126, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 131, [126 | __Ss], [__T | __Stack]);
+yeccpars2(126, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 137, [126 | __Ss], [__T | __Stack]);
+yeccpars2(126, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 138, [126 | __Ss], [__T | __Stack]);
+yeccpars2(126, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 133, [126 | __Ss], [__T | __Stack]);
+yeccpars2(126, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 130, [126 | __Ss], [__T | __Stack]);
+yeccpars2(126, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(127, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 128, [127 | __Ss], [__T | __Stack]);
+yeccpars2(127, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(128, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = core_lib:set_anno(__2,__4),
+ __Nss = lists:nthtail(4, __Ss),
+ yeccpars2(yeccgoto(anno_variable, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(129, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 129, [129 | __Ss], [__T | __Stack]);
+yeccpars2(129, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 142, [129 | __Ss], [__T | __Stack]);
+yeccpars2(129, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 140, [129 | __Ss], [__T | __Stack]);
+yeccpars2(129, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 131, [129 | __Ss], [__T | __Stack]);
+yeccpars2(129, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 137, [129 | __Ss], [__T | __Stack]);
+yeccpars2(129, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 138, [129 | __Ss], [__T | __Stack]);
+yeccpars2(129, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 133, [129 | __Ss], [__T | __Stack]);
+yeccpars2(129, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 149, [129 | __Ss], [__T | __Stack]);
+yeccpars2(129, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(130, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [],
+ __Nss = lists:nthtail(1, __Ss),
+ yeccpars2(yeccgoto(annotation, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(131, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = tok_val(__1),
+ yeccpars2(yeccgoto(atomic_constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(132, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(133, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = tok_val(__1),
+ yeccpars2(yeccgoto(atomic_constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(134, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(135, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 147, [135 | __Ss], [__T | __Stack]);
+yeccpars2(135, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1],
+ yeccpars2(yeccgoto(constants, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(136, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 146, [136 | __Ss], [__T | __Stack]);
+yeccpars2(136, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(137, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = tok_val(__1),
+ yeccpars2(yeccgoto(atomic_constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(138, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = tok_val(__1),
+ yeccpars2(yeccgoto(atomic_constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(139, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [],
+ yeccpars2(yeccgoto(atomic_constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(140, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = tok_val(__1),
+ yeccpars2(yeccgoto(atomic_constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(141, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(142, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 129, [142 | __Ss], [__T | __Stack]);
+yeccpars2(142, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 142, [142 | __Ss], [__T | __Stack]);
+yeccpars2(142, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 144, [142 | __Ss], [__T | __Stack]);
+yeccpars2(142, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 140, [142 | __Ss], [__T | __Stack]);
+yeccpars2(142, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 131, [142 | __Ss], [__T | __Stack]);
+yeccpars2(142, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 137, [142 | __Ss], [__T | __Stack]);
+yeccpars2(142, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 138, [142 | __Ss], [__T | __Stack]);
+yeccpars2(142, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 133, [142 | __Ss], [__T | __Stack]);
+yeccpars2(142, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(143, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 145, [143 | __Ss], [__T | __Stack]);
+yeccpars2(143, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(144, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = {},
+ __Nss = lists:nthtail(1, __Ss),
+ yeccpars2(yeccgoto(tuple_constant, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(145, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = list_to_tuple(__2),
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(tuple_constant, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(146, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __2,
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(annotation, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(147, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 129, [147 | __Ss], [__T | __Stack]);
+yeccpars2(147, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 142, [147 | __Ss], [__T | __Stack]);
+yeccpars2(147, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 140, [147 | __Ss], [__T | __Stack]);
+yeccpars2(147, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 131, [147 | __Ss], [__T | __Stack]);
+yeccpars2(147, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 137, [147 | __Ss], [__T | __Stack]);
+yeccpars2(147, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 138, [147 | __Ss], [__T | __Stack]);
+yeccpars2(147, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 133, [147 | __Ss], [__T | __Stack]);
+yeccpars2(147, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(148, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1|__3],
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(constants, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(149, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = {nil,tok_line(__1)},
+ __Nss = lists:nthtail(1, __Ss),
+ yeccpars2(yeccgoto(nil, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(150, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 151, [150 | __Ss], [__T | __Stack]);
+yeccpars2(150, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 154, [150 | __Ss], [__T | __Stack]);
+yeccpars2(150, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 152, [150 | __Ss], [__T | __Stack]);
+yeccpars2(150, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(151, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 129, [151 | __Ss], [__T | __Stack]);
+yeccpars2(151, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 142, [151 | __Ss], [__T | __Stack]);
+yeccpars2(151, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 140, [151 | __Ss], [__T | __Stack]);
+yeccpars2(151, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 131, [151 | __Ss], [__T | __Stack]);
+yeccpars2(151, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 137, [151 | __Ss], [__T | __Stack]);
+yeccpars2(151, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 138, [151 | __Ss], [__T | __Stack]);
+yeccpars2(151, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 133, [151 | __Ss], [__T | __Stack]);
+yeccpars2(151, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(152, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [],
+ yeccpars2(yeccgoto(tail_constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(153, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__2|__3],
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(cons_constant, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(154, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 129, [154 | __Ss], [__T | __Stack]);
+yeccpars2(154, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 142, [154 | __Ss], [__T | __Stack]);
+yeccpars2(154, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 140, [154 | __Ss], [__T | __Stack]);
+yeccpars2(154, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 131, [154 | __Ss], [__T | __Stack]);
+yeccpars2(154, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 137, [154 | __Ss], [__T | __Stack]);
+yeccpars2(154, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 138, [154 | __Ss], [__T | __Stack]);
+yeccpars2(154, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 133, [154 | __Ss], [__T | __Stack]);
+yeccpars2(154, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(155, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 156, [155 | __Ss], [__T | __Stack]);
+yeccpars2(155, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(156, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __2,
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(tail_constant, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(157, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 151, [157 | __Ss], [__T | __Stack]);
+yeccpars2(157, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 154, [157 | __Ss], [__T | __Stack]);
+yeccpars2(157, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 152, [157 | __Ss], [__T | __Stack]);
+yeccpars2(157, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(158, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__2|__3],
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(tail_constant, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(159, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 126, [159 | __Ss], [__T | __Stack]);
+yeccpars2(159, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(160, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 161, [160 | __Ss], [__T | __Stack]);
+yeccpars2(160, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(161, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = core_lib:set_anno(__2,__4),
+ __Nss = lists:nthtail(4, __Ss),
+ yeccpars2(yeccgoto(anno_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(162, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [162 | __Ss], [__T | __Stack]);
+yeccpars2(162, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 104, [162 | __Ss], [__T | __Stack]);
+yeccpars2(162, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [162 | __Ss], [__T | __Stack]);
+yeccpars2(162, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [162 | __Ss], [__T | __Stack]);
+yeccpars2(162, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [162 | __Ss], [__T | __Stack]);
+yeccpars2(162, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 115, [162 | __Ss], [__T | __Stack]);
+yeccpars2(162, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [162 | __Ss], [__T | __Stack]);
+yeccpars2(162, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 95, [162 | __Ss], [__T | __Stack]);
+yeccpars2(162, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 98, [162 | __Ss], [__T | __Stack]);
+yeccpars2(162, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 114, [162 | __Ss], [__T | __Stack]);
+yeccpars2(162, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(163, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_alias{var = __1, pat = __3},
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(other_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(164, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [164 | __Ss], [__T | __Stack]);
+yeccpars2(164, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(165, '->', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 166, [165 | __Ss], [__T | __Stack]);
+yeccpars2(165, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(166, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [166 | __Ss], [__T | __Stack]);
+yeccpars2(166, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(167, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_clause{pats = __1, guard = __3, body = __5},
+ __Nss = lists:nthtail(4, __Ss),
+ yeccpars2(yeccgoto(clause, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(168, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = begin
+ {T,A} = __3, #c_receive{clauses = __2, timeout = T, action = A}
+ end,
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(receive_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(169, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1|__2],
+ __Nss = lists:nthtail(1, __Ss),
+ yeccpars2(yeccgoto(anno_clauses, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(170, '->', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 171, [170 | __Ss], [__T | __Stack]);
+yeccpars2(170, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(171, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [171 | __Ss], [__T | __Stack]);
+yeccpars2(171, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(172, __Cat, __Ss, [__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = {__2,__4},
+ __Nss = lists:nthtail(3, __Ss),
+ yeccpars2(yeccgoto(timeout, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(173, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 174, [173 | __Ss], [__T | __Stack]);
+yeccpars2(173, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 177, [173 | __Ss], [__T | __Stack]);
+yeccpars2(173, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 175, [173 | __Ss], [__T | __Stack]);
+yeccpars2(173, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(174, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [174 | __Ss], [__T | __Stack]);
+yeccpars2(174, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 104, [174 | __Ss], [__T | __Stack]);
+yeccpars2(174, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [174 | __Ss], [__T | __Stack]);
+yeccpars2(174, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [174 | __Ss], [__T | __Stack]);
+yeccpars2(174, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [174 | __Ss], [__T | __Stack]);
+yeccpars2(174, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 115, [174 | __Ss], [__T | __Stack]);
+yeccpars2(174, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [174 | __Ss], [__T | __Stack]);
+yeccpars2(174, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 95, [174 | __Ss], [__T | __Stack]);
+yeccpars2(174, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 98, [174 | __Ss], [__T | __Stack]);
+yeccpars2(174, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 114, [174 | __Ss], [__T | __Stack]);
+yeccpars2(174, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(175, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_nil{},
+ yeccpars2(yeccgoto(tail_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(176, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_cons{hd = __2, tl = __3},
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(cons_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(177, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [177 | __Ss], [__T | __Stack]);
+yeccpars2(177, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 104, [177 | __Ss], [__T | __Stack]);
+yeccpars2(177, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [177 | __Ss], [__T | __Stack]);
+yeccpars2(177, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [177 | __Ss], [__T | __Stack]);
+yeccpars2(177, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [177 | __Ss], [__T | __Stack]);
+yeccpars2(177, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 115, [177 | __Ss], [__T | __Stack]);
+yeccpars2(177, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [177 | __Ss], [__T | __Stack]);
+yeccpars2(177, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 95, [177 | __Ss], [__T | __Stack]);
+yeccpars2(177, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 98, [177 | __Ss], [__T | __Stack]);
+yeccpars2(177, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 114, [177 | __Ss], [__T | __Stack]);
+yeccpars2(177, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(178, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 179, [178 | __Ss], [__T | __Stack]);
+yeccpars2(178, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(179, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __2,
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(tail_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(180, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 174, [180 | __Ss], [__T | __Stack]);
+yeccpars2(180, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 177, [180 | __Ss], [__T | __Stack]);
+yeccpars2(180, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 175, [180 | __Ss], [__T | __Stack]);
+yeccpars2(180, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(181, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_cons{hd = __2, tl = __3},
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(tail_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(182, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [],
+ __Nss = lists:nthtail(1, __Ss),
+ yeccpars2(yeccgoto(clause_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(183, '>', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 184, [183 | __Ss], [__T | __Stack]);
+yeccpars2(183, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(184, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __2,
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(clause_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(185, '-|', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 187, [185 | __Ss], [__T | __Stack]);
+yeccpars2(185, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(186, '-|', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 159, [186 | __Ss], [__T | __Stack]);
+yeccpars2(186, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(anno_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(187, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 126, [187 | __Ss], [__T | __Stack]);
+yeccpars2(187, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(188, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 189, [188 | __Ss], [__T | __Stack]);
+yeccpars2(188, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(189, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = core_lib:set_anno(__2,__4),
+ __Nss = lists:nthtail(4, __Ss),
+ yeccpars2(yeccgoto(anno_clause, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(190, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 191, [190 | __Ss], [__T | __Stack]);
+yeccpars2(190, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 194, [190 | __Ss], [__T | __Stack]);
+yeccpars2(190, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(191, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 200, [191 | __Ss], [__T | __Stack]);
+yeccpars2(191, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(192, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 198, [192 | __Ss], [__T | __Stack]);
+yeccpars2(192, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1],
+ yeccpars2(yeccgoto(segment_patterns, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(193, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 196, [193 | __Ss], [__T | __Stack]);
+yeccpars2(193, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(194, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 195, [194 | __Ss], [__T | __Stack]);
+yeccpars2(194, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(195, __Cat, __Ss, [__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_binary{segments = []},
+ __Nss = lists:nthtail(3, __Ss),
+ yeccpars2(yeccgoto(binary_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(196, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 197, [196 | __Ss], [__T | __Stack]);
+yeccpars2(196, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(197, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_binary{segments = __3},
+ __Nss = lists:nthtail(4, __Ss),
+ yeccpars2(yeccgoto(binary_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(198, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 191, [198 | __Ss], [__T | __Stack]);
+yeccpars2(198, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(199, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1|__3],
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(segment_patterns, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(200, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [200 | __Ss], [__T | __Stack]);
+yeccpars2(200, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 104, [200 | __Ss], [__T | __Stack]);
+yeccpars2(200, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [200 | __Ss], [__T | __Stack]);
+yeccpars2(200, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [200 | __Ss], [__T | __Stack]);
+yeccpars2(200, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [200 | __Ss], [__T | __Stack]);
+yeccpars2(200, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 115, [200 | __Ss], [__T | __Stack]);
+yeccpars2(200, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [200 | __Ss], [__T | __Stack]);
+yeccpars2(200, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 95, [200 | __Ss], [__T | __Stack]);
+yeccpars2(200, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 98, [200 | __Ss], [__T | __Stack]);
+yeccpars2(200, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 114, [200 | __Ss], [__T | __Stack]);
+yeccpars2(200, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(201, '>', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 202, [201 | __Ss], [__T | __Stack]);
+yeccpars2(201, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(202, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 203, [202 | __Ss], [__T | __Stack]);
+yeccpars2(202, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(203, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 205, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [203 | __Ss], [__T | __Stack]);
+yeccpars2(203, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(204, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = case __5 of [S,U,T,Fs] -> #c_bitstr{val = __3, size = S, unit = U, type = T, flags = Fs}; true -> return_error(tok_line(__1),"expected 4 arguments in binary segment") end,
+ __Nss = lists:nthtail(4, __Ss),
+ yeccpars2(yeccgoto(segment_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(205, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [],
+ __Nss = lists:nthtail(1, __Ss),
+ yeccpars2(yeccgoto(arg_list, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(206, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 207, [206 | __Ss], [__T | __Stack]);
+yeccpars2(206, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(207, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __2,
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(arg_list, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(208, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 203, [208 | __Ss], [__T | __Stack]);
+yeccpars2(208, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(209, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = begin
+ Name = #c_atom{val = tok_val(__2)}, #c_primop{name = Name, args = __3}
+ end,
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(primop_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(210, 'in', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 211, [210 | __Ss], [__T | __Stack]);
+yeccpars2(210, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(211, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [211 | __Ss], [__T | __Stack]);
+yeccpars2(211, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(212, __Cat, __Ss, [__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_letrec{defs = __2, body = __4},
+ __Nss = lists:nthtail(3, __Ss),
+ yeccpars2(yeccgoto(letrec_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(213, '=', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 214, [213 | __Ss], [__T | __Stack]);
+yeccpars2(213, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(214, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [214 | __Ss], [__T | __Stack]);
+yeccpars2(214, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(215, 'in', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 216, [215 | __Ss], [__T | __Stack]);
+yeccpars2(215, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(216, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [216 | __Ss], [__T | __Stack]);
+yeccpars2(216, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(217, __Cat, __Ss, [__6,__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_let{vars = __2, arg = __4, body = __6},
+ __Nss = lists:nthtail(5, __Ss),
+ yeccpars2(yeccgoto(let_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(218, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [218 | __Ss], [__T | __Stack]);
+yeccpars2(218, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(219, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_seq{arg = __2, body = __3},
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(sequence, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(220, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_catch{body = __2},
+ __Nss = lists:nthtail(1, __Ss),
+ yeccpars2(yeccgoto(catch_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(221, 'of', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 222, [221 | __Ss], [__T | __Stack]);
+yeccpars2(221, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(222, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 97, [222 | __Ss], [__T | __Stack]);
+yeccpars2(222, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 96, [222 | __Ss], [__T | __Stack]);
+yeccpars2(222, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [222 | __Ss], [__T | __Stack]);
+yeccpars2(222, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 104, [222 | __Ss], [__T | __Stack]);
+yeccpars2(222, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [222 | __Ss], [__T | __Stack]);
+yeccpars2(222, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [222 | __Ss], [__T | __Stack]);
+yeccpars2(222, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [222 | __Ss], [__T | __Stack]);
+yeccpars2(222, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [222 | __Ss], [__T | __Stack]);
+yeccpars2(222, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 95, [222 | __Ss], [__T | __Stack]);
+yeccpars2(222, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 98, [222 | __Ss], [__T | __Stack]);
+yeccpars2(222, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 114, [222 | __Ss], [__T | __Stack]);
+yeccpars2(222, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(223, 'end', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 224, [223 | __Ss], [__T | __Stack]);
+yeccpars2(223, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(224, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_case{arg = __2, clauses = __4},
+ __Nss = lists:nthtail(4, __Ss),
+ yeccpars2(yeccgoto(case_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(225, ':', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 226, [225 | __Ss], [__T | __Stack]);
+yeccpars2(225, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(226, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [226 | __Ss], [__T | __Stack]);
+yeccpars2(226, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(227, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 203, [227 | __Ss], [__T | __Stack]);
+yeccpars2(227, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(228, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_call{module = __2, name = __4, args = __5},
+ __Nss = lists:nthtail(4, __Ss),
+ yeccpars2(yeccgoto(call_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(229, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 203, [229 | __Ss], [__T | __Stack]);
+yeccpars2(229, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(230, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_apply{op = __2, args = __3},
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(application_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(231, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 232, [231 | __Ss], [__T | __Stack]);
+yeccpars2(231, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 235, [231 | __Ss], [__T | __Stack]);
+yeccpars2(231, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 233, [231 | __Ss], [__T | __Stack]);
+yeccpars2(231, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(232, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [232 | __Ss], [__T | __Stack]);
+yeccpars2(232, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(233, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_nil{},
+ yeccpars2(yeccgoto(tail, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(234, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_cons{hd = __2, tl = __3},
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(cons, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(235, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [235 | __Ss], [__T | __Stack]);
+yeccpars2(235, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(236, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 237, [236 | __Ss], [__T | __Stack]);
+yeccpars2(236, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(237, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __2,
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(tail, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(238, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 232, [238 | __Ss], [__T | __Stack]);
+yeccpars2(238, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 235, [238 | __Ss], [__T | __Stack]);
+yeccpars2(238, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 233, [238 | __Ss], [__T | __Stack]);
+yeccpars2(238, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(239, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_cons{hd = __2, tl = __3},
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(tail, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(240, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_values{es = []},
+ __Nss = lists:nthtail(1, __Ss),
+ yeccpars2(yeccgoto(expression, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(241, '>', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 242, [241 | __Ss], [__T | __Stack]);
+yeccpars2(241, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(242, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_values{es = __2},
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(expression, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(243, '-|', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 244, [243 | __Ss], [__T | __Stack]);
+yeccpars2(243, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(244, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 126, [244 | __Ss], [__T | __Stack]);
+yeccpars2(244, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(245, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 246, [245 | __Ss], [__T | __Stack]);
+yeccpars2(245, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(246, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = core_lib:set_anno(__2,__4),
+ __Nss = lists:nthtail(4, __Ss),
+ yeccpars2(yeccgoto(anno_expression, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(247, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 248, [247 | __Ss], [__T | __Stack]);
+yeccpars2(247, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 251, [247 | __Ss], [__T | __Stack]);
+yeccpars2(247, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(248, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 257, [248 | __Ss], [__T | __Stack]);
+yeccpars2(248, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(249, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 255, [249 | __Ss], [__T | __Stack]);
+yeccpars2(249, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1],
+ yeccpars2(yeccgoto(segments, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(250, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 253, [250 | __Ss], [__T | __Stack]);
+yeccpars2(250, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(251, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 252, [251 | __Ss], [__T | __Stack]);
+yeccpars2(251, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(252, __Cat, __Ss, [__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_binary{segments = []},
+ __Nss = lists:nthtail(3, __Ss),
+ yeccpars2(yeccgoto(binary, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(253, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 254, [253 | __Ss], [__T | __Stack]);
+yeccpars2(253, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(254, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_binary{segments = __3},
+ __Nss = lists:nthtail(4, __Ss),
+ yeccpars2(yeccgoto(binary, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(255, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 248, [255 | __Ss], [__T | __Stack]);
+yeccpars2(255, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(256, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1|__3],
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(segments, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(257, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [257 | __Ss], [__T | __Stack]);
+yeccpars2(257, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(258, '>', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 259, [258 | __Ss], [__T | __Stack]);
+yeccpars2(258, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(259, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 260, [259 | __Ss], [__T | __Stack]);
+yeccpars2(259, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(260, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [260 | __Ss], [__T | __Stack]);
+yeccpars2(260, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(261, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 262, [261 | __Ss], [__T | __Stack]);
+yeccpars2(261, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(262, __Cat, __Ss, [__7,__6,__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = case __6 of [S,U,T,Fs] -> #c_bitstr{val = __3, size = S, unit = U, type = T, flags = Fs}; true -> return_error(tok_line(__1),"expected 4 arguments in binary segment") end,
+ __Nss = lists:nthtail(6, __Ss),
+ yeccpars2(yeccgoto(segment, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(263, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 26, [263 | __Ss], [__T | __Stack]);
+yeccpars2(263, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [263 | __Ss], [__T | __Stack]);
+yeccpars2(263, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(264, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1|__3],
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(anno_variables, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(265, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 65, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 48, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 70, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 63, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 44, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 40, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 46, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 60, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 58, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 23, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 52, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 41, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 34, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 37, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 74, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 36, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 35, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 30, [265 | __Ss], [__T | __Stack]);
+yeccpars2(265, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(266, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_fun{vars = [], body = __5},
+ __Nss = lists:nthtail(4, __Ss),
+ yeccpars2(yeccgoto(fun_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(267, '-|', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 125, [267 | __Ss], [__T | __Stack]);
+yeccpars2(267, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(268, '-|', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 269, [268 | __Ss], [__T | __Stack]);
+yeccpars2(268, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(269, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 126, [269 | __Ss], [__T | __Stack]);
+yeccpars2(269, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(270, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 271, [270 | __Ss], [__T | __Stack]);
+yeccpars2(270, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(271, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = core_lib:set_anno(__2,__4),
+ __Nss = lists:nthtail(4, __Ss),
+ yeccpars2(yeccgoto(anno_fun, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(272, '-|', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 273, [272 | __Ss], [__T | __Stack]);
+yeccpars2(272, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(273, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 126, [273 | __Ss], [__T | __Stack]);
+yeccpars2(273, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(274, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 275, [274 | __Ss], [__T | __Stack]);
+yeccpars2(274, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(275, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = core_lib:set_anno(__2,__4),
+ __Nss = lists:nthtail(4, __Ss),
+ yeccpars2(yeccgoto(anno_function_name, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(276, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 278, [276 | __Ss], [__T | __Stack]);
+yeccpars2(276, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 277, [276 | __Ss], [__T | __Stack]);
+yeccpars2(276, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(277, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [],
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(module_attribute, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(278, '=', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 284, [278 | __Ss], [__T | __Stack]);
+yeccpars2(278, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(279, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 282, [279 | __Ss], [__T | __Stack]);
+yeccpars2(279, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1],
+ yeccpars2(yeccgoto(attribute_list, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(280, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 281, [280 | __Ss], [__T | __Stack]);
+yeccpars2(280, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(281, __Cat, __Ss, [__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __3,
+ __Nss = lists:nthtail(3, __Ss),
+ yeccpars2(yeccgoto(module_attribute, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(282, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 278, [282 | __Ss], [__T | __Stack]);
+yeccpars2(282, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(283, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1|__3],
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(attribute_list, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(284, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 285, [284 | __Ss], [__T | __Stack]);
+yeccpars2(284, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 290, [284 | __Ss], [__T | __Stack]);
+yeccpars2(284, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [284 | __Ss], [__T | __Stack]);
+yeccpars2(284, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 104, [284 | __Ss], [__T | __Stack]);
+yeccpars2(284, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [284 | __Ss], [__T | __Stack]);
+yeccpars2(284, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [284 | __Ss], [__T | __Stack]);
+yeccpars2(284, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [284 | __Ss], [__T | __Stack]);
+yeccpars2(284, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(285, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 285, [285 | __Ss], [__T | __Stack]);
+yeccpars2(285, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 290, [285 | __Ss], [__T | __Stack]);
+yeccpars2(285, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [285 | __Ss], [__T | __Stack]);
+yeccpars2(285, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 104, [285 | __Ss], [__T | __Stack]);
+yeccpars2(285, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [285 | __Ss], [__T | __Stack]);
+yeccpars2(285, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [285 | __Ss], [__T | __Stack]);
+yeccpars2(285, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [285 | __Ss], [__T | __Stack]);
+yeccpars2(285, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 149, [285 | __Ss], [__T | __Stack]);
+yeccpars2(285, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(286, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(287, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(288, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_def{name = #c_atom{val = tok_val(__1)}, val = __3},
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(attribute, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(289, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(290, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 285, [290 | __Ss], [__T | __Stack]);
+yeccpars2(290, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 290, [290 | __Ss], [__T | __Stack]);
+yeccpars2(290, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 293, [290 | __Ss], [__T | __Stack]);
+yeccpars2(290, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [290 | __Ss], [__T | __Stack]);
+yeccpars2(290, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 104, [290 | __Ss], [__T | __Stack]);
+yeccpars2(290, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [290 | __Ss], [__T | __Stack]);
+yeccpars2(290, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [290 | __Ss], [__T | __Stack]);
+yeccpars2(290, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [290 | __Ss], [__T | __Stack]);
+yeccpars2(290, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(291, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 295, [291 | __Ss], [__T | __Stack]);
+yeccpars2(291, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1],
+ yeccpars2(yeccgoto(literals, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(292, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 294, [292 | __Ss], [__T | __Stack]);
+yeccpars2(292, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(293, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_tuple{es = []},
+ __Nss = lists:nthtail(1, __Ss),
+ yeccpars2(yeccgoto(tuple_literal, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(294, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_tuple{es = __2},
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(tuple_literal, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(295, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 285, [295 | __Ss], [__T | __Stack]);
+yeccpars2(295, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 290, [295 | __Ss], [__T | __Stack]);
+yeccpars2(295, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [295 | __Ss], [__T | __Stack]);
+yeccpars2(295, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 104, [295 | __Ss], [__T | __Stack]);
+yeccpars2(295, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [295 | __Ss], [__T | __Stack]);
+yeccpars2(295, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [295 | __Ss], [__T | __Stack]);
+yeccpars2(295, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [295 | __Ss], [__T | __Stack]);
+yeccpars2(295, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(296, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1|__3],
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(literals, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(297, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 298, [297 | __Ss], [__T | __Stack]);
+yeccpars2(297, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 301, [297 | __Ss], [__T | __Stack]);
+yeccpars2(297, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 299, [297 | __Ss], [__T | __Stack]);
+yeccpars2(297, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(298, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 285, [298 | __Ss], [__T | __Stack]);
+yeccpars2(298, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 290, [298 | __Ss], [__T | __Stack]);
+yeccpars2(298, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [298 | __Ss], [__T | __Stack]);
+yeccpars2(298, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 104, [298 | __Ss], [__T | __Stack]);
+yeccpars2(298, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [298 | __Ss], [__T | __Stack]);
+yeccpars2(298, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [298 | __Ss], [__T | __Stack]);
+yeccpars2(298, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [298 | __Ss], [__T | __Stack]);
+yeccpars2(298, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(299, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_nil{},
+ yeccpars2(yeccgoto(tail_literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(300, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_cons{hd = __2, tl = __3},
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(cons_literal, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(301, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 285, [301 | __Ss], [__T | __Stack]);
+yeccpars2(301, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 290, [301 | __Ss], [__T | __Stack]);
+yeccpars2(301, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 69, [301 | __Ss], [__T | __Stack]);
+yeccpars2(301, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 104, [301 | __Ss], [__T | __Stack]);
+yeccpars2(301, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 54, [301 | __Ss], [__T | __Stack]);
+yeccpars2(301, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 57, [301 | __Ss], [__T | __Stack]);
+yeccpars2(301, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 50, [301 | __Ss], [__T | __Stack]);
+yeccpars2(301, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(302, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 303, [302 | __Ss], [__T | __Stack]);
+yeccpars2(302, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(303, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __2,
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(tail_literal, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(304, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 298, [304 | __Ss], [__T | __Stack]);
+yeccpars2(304, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 301, [304 | __Ss], [__T | __Stack]);
+yeccpars2(304, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 299, [304 | __Ss], [__T | __Stack]);
+yeccpars2(304, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(305, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_cons{hd = __2, tl = __3},
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(tail_literal, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(306, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [],
+ __Nss = lists:nthtail(1, __Ss),
+ yeccpars2(yeccgoto(module_export, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(307, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 311, [307 | __Ss], [__T | __Stack]);
+yeccpars2(307, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1],
+ yeccpars2(yeccgoto(exported_names, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(308, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 310, [308 | __Ss], [__T | __Stack]);
+yeccpars2(308, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(309, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __1,
+ yeccpars2(yeccgoto(exported_name, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(310, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = __2,
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(module_export, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(311, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 11, [311 | __Ss], [__T | __Stack]);
+yeccpars2(311, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(312, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = [__1|__3],
+ __Nss = lists:nthtail(2, __Ss),
+ yeccpars2(yeccgoto(exported_names, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(313, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 314, [313 | __Ss], [__T | __Stack]);
+yeccpars2(313, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(314, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 5, [314 | __Ss], [__T | __Stack]);
+yeccpars2(314, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(315, 'attributes', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 7, [315 | __Ss], [__T | __Stack]);
+yeccpars2(315, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(316, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 9, [316 | __Ss], [__T | __Stack]);
+yeccpars2(316, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 11, [316 | __Ss], [__T | __Stack]);
+yeccpars2(316, __Cat, __Ss, __Stack, __T, __Ts, __Tzr) ->
+ __Val = [],
+ yeccpars2(13, __Cat, [316 | __Ss], [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(317, 'end', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 318, [317 | __Ss], [__T | __Stack]);
+yeccpars2(317, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(318, '-|', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 319, [318 | __Ss], [__T | __Stack]);
+yeccpars2(318, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(319, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 126, [319 | __Ss], [__T | __Stack]);
+yeccpars2(319, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(320, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
+ yeccpars1(__Ts, __Tzr, 321, [320 | __Ss], [__T | __Stack]);
+yeccpars2(320, _, _, _, __T, _, _) ->
+ yeccerror(__T);
+yeccpars2(321, __Cat, __Ss, [__10,__9,__8,__7,__6,__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
+ __Val = #c_module{anno = __9, name = tok_val(__3), exports = __4, attrs = __5, defs = __6},
+ __Nss = lists:nthtail(9, __Ss),
+ yeccpars2(yeccgoto(module_definition, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
+yeccpars2(__Other, _, _, _, _, _, _) ->
+ exit({parser, __Other, missing_state_in_action_table}).
+
+yeccgoto(anno_clause, 65) ->
+ 100;
+yeccgoto(anno_clause, 100) ->
+ 100;
+yeccgoto(anno_clause, 222) ->
+ 100;
+yeccgoto(anno_clauses, 65) ->
+ 101;
+yeccgoto(anno_clauses, 100) ->
+ 169;
+yeccgoto(anno_clauses, 222) ->
+ 223;
+yeccgoto(anno_expression, 33) ->
+ 38;
+yeccgoto(anno_expression, 36) ->
+ 75;
+yeccgoto(anno_expression, 37) ->
+ 231;
+yeccgoto(anno_expression, 40) ->
+ 229;
+yeccgoto(anno_expression, 44) ->
+ 225;
+yeccgoto(anno_expression, 46) ->
+ 221;
+yeccgoto(anno_expression, 48) ->
+ 220;
+yeccgoto(anno_expression, 52) ->
+ 218;
+yeccgoto(anno_expression, 70) ->
+ 81;
+yeccgoto(anno_expression, 74) ->
+ 75;
+yeccgoto(anno_expression, 79) ->
+ 75;
+yeccgoto(anno_expression, 86) ->
+ 87;
+yeccgoto(anno_expression, 90) ->
+ 91;
+yeccgoto(anno_expression, 99) ->
+ 170;
+yeccgoto(anno_expression, 164) ->
+ 165;
+yeccgoto(anno_expression, 166) ->
+ 167;
+yeccgoto(anno_expression, 171) ->
+ 172;
+yeccgoto(anno_expression, 203) ->
+ 75;
+yeccgoto(anno_expression, 211) ->
+ 212;
+yeccgoto(anno_expression, 214) ->
+ 215;
+yeccgoto(anno_expression, 216) ->
+ 217;
+yeccgoto(anno_expression, 218) ->
+ 219;
+yeccgoto(anno_expression, 226) ->
+ 227;
+yeccgoto(anno_expression, 232) ->
+ 238;
+yeccgoto(anno_expression, 235) ->
+ 236;
+yeccgoto(anno_expression, 257) ->
+ 258;
+yeccgoto(anno_expression, 260) ->
+ 75;
+yeccgoto(anno_expression, 265) ->
+ 266;
+yeccgoto(anno_expressions, 36) ->
+ 241;
+yeccgoto(anno_expressions, 74) ->
+ 76;
+yeccgoto(anno_expressions, 79) ->
+ 80;
+yeccgoto(anno_expressions, 203) ->
+ 206;
+yeccgoto(anno_expressions, 260) ->
+ 261;
+yeccgoto(anno_fun, 20) ->
+ 22;
+yeccgoto(anno_function_name, 8) ->
+ 10;
+yeccgoto(anno_function_name, 12) ->
+ 10;
+yeccgoto(anno_function_name, 60) ->
+ 10;
+yeccgoto(anno_function_name, 316) ->
+ 10;
+yeccgoto(anno_pattern, 65) ->
+ 102;
+yeccgoto(anno_pattern, 96) ->
+ 102;
+yeccgoto(anno_pattern, 97) ->
+ 116;
+yeccgoto(anno_pattern, 98) ->
+ 173;
+yeccgoto(anno_pattern, 100) ->
+ 102;
+yeccgoto(anno_pattern, 114) ->
+ 116;
+yeccgoto(anno_pattern, 120) ->
+ 116;
+yeccgoto(anno_pattern, 162) ->
+ 163;
+yeccgoto(anno_pattern, 174) ->
+ 180;
+yeccgoto(anno_pattern, 177) ->
+ 178;
+yeccgoto(anno_pattern, 200) ->
+ 201;
+yeccgoto(anno_pattern, 222) ->
+ 102;
+yeccgoto(anno_patterns, 97) ->
+ 183;
+yeccgoto(anno_patterns, 114) ->
+ 117;
+yeccgoto(anno_patterns, 120) ->
+ 121;
+yeccgoto(anno_variable, 25) ->
+ 28;
+yeccgoto(anno_variable, 58) ->
+ 84;
+yeccgoto(anno_variable, 65) ->
+ 103;
+yeccgoto(anno_variable, 82) ->
+ 84;
+yeccgoto(anno_variable, 83) ->
+ 28;
+yeccgoto(anno_variable, 88) ->
+ 84;
+yeccgoto(anno_variable, 96) ->
+ 103;
+yeccgoto(anno_variable, 97) ->
+ 103;
+yeccgoto(anno_variable, 98) ->
+ 103;
+yeccgoto(anno_variable, 100) ->
+ 103;
+yeccgoto(anno_variable, 114) ->
+ 103;
+yeccgoto(anno_variable, 115) ->
+ 122;
+yeccgoto(anno_variable, 120) ->
+ 103;
+yeccgoto(anno_variable, 162) ->
+ 103;
+yeccgoto(anno_variable, 174) ->
+ 103;
+yeccgoto(anno_variable, 177) ->
+ 103;
+yeccgoto(anno_variable, 200) ->
+ 103;
+yeccgoto(anno_variable, 222) ->
+ 103;
+yeccgoto(anno_variable, 263) ->
+ 28;
+yeccgoto(anno_variables, 25) ->
+ 29;
+yeccgoto(anno_variables, 83) ->
+ 93;
+yeccgoto(anno_variables, 263) ->
+ 264;
+yeccgoto(annotation, 125) ->
+ 127;
+yeccgoto(annotation, 159) ->
+ 160;
+yeccgoto(annotation, 187) ->
+ 188;
+yeccgoto(annotation, 244) ->
+ 245;
+yeccgoto(annotation, 269) ->
+ 270;
+yeccgoto(annotation, 273) ->
+ 274;
+yeccgoto(annotation, 319) ->
+ 320;
+yeccgoto(application_expr, 33) ->
+ 39;
+yeccgoto(application_expr, 35) ->
+ 39;
+yeccgoto(application_expr, 36) ->
+ 39;
+yeccgoto(application_expr, 37) ->
+ 39;
+yeccgoto(application_expr, 40) ->
+ 39;
+yeccgoto(application_expr, 44) ->
+ 39;
+yeccgoto(application_expr, 46) ->
+ 39;
+yeccgoto(application_expr, 48) ->
+ 39;
+yeccgoto(application_expr, 52) ->
+ 39;
+yeccgoto(application_expr, 70) ->
+ 39;
+yeccgoto(application_expr, 74) ->
+ 39;
+yeccgoto(application_expr, 79) ->
+ 39;
+yeccgoto(application_expr, 86) ->
+ 39;
+yeccgoto(application_expr, 90) ->
+ 39;
+yeccgoto(application_expr, 99) ->
+ 39;
+yeccgoto(application_expr, 164) ->
+ 39;
+yeccgoto(application_expr, 166) ->
+ 39;
+yeccgoto(application_expr, 171) ->
+ 39;
+yeccgoto(application_expr, 203) ->
+ 39;
+yeccgoto(application_expr, 211) ->
+ 39;
+yeccgoto(application_expr, 214) ->
+ 39;
+yeccgoto(application_expr, 216) ->
+ 39;
+yeccgoto(application_expr, 218) ->
+ 39;
+yeccgoto(application_expr, 226) ->
+ 39;
+yeccgoto(application_expr, 232) ->
+ 39;
+yeccgoto(application_expr, 235) ->
+ 39;
+yeccgoto(application_expr, 257) ->
+ 39;
+yeccgoto(application_expr, 260) ->
+ 39;
+yeccgoto(application_expr, 265) ->
+ 39;
+yeccgoto(arg_list, 202) ->
+ 204;
+yeccgoto(arg_list, 208) ->
+ 209;
+yeccgoto(arg_list, 227) ->
+ 228;
+yeccgoto(arg_list, 229) ->
+ 230;
+yeccgoto(atomic_constant, 126) ->
+ 132;
+yeccgoto(atomic_constant, 129) ->
+ 132;
+yeccgoto(atomic_constant, 142) ->
+ 132;
+yeccgoto(atomic_constant, 147) ->
+ 132;
+yeccgoto(atomic_constant, 151) ->
+ 132;
+yeccgoto(atomic_constant, 154) ->
+ 132;
+yeccgoto(atomic_literal, 33) ->
+ 42;
+yeccgoto(atomic_literal, 35) ->
+ 42;
+yeccgoto(atomic_literal, 36) ->
+ 42;
+yeccgoto(atomic_literal, 37) ->
+ 42;
+yeccgoto(atomic_literal, 40) ->
+ 42;
+yeccgoto(atomic_literal, 44) ->
+ 42;
+yeccgoto(atomic_literal, 46) ->
+ 42;
+yeccgoto(atomic_literal, 48) ->
+ 42;
+yeccgoto(atomic_literal, 52) ->
+ 42;
+yeccgoto(atomic_literal, 65) ->
+ 105;
+yeccgoto(atomic_literal, 70) ->
+ 42;
+yeccgoto(atomic_literal, 74) ->
+ 42;
+yeccgoto(atomic_literal, 79) ->
+ 42;
+yeccgoto(atomic_literal, 86) ->
+ 42;
+yeccgoto(atomic_literal, 90) ->
+ 42;
+yeccgoto(atomic_literal, 96) ->
+ 105;
+yeccgoto(atomic_literal, 97) ->
+ 105;
+yeccgoto(atomic_literal, 98) ->
+ 105;
+yeccgoto(atomic_literal, 99) ->
+ 42;
+yeccgoto(atomic_literal, 100) ->
+ 105;
+yeccgoto(atomic_literal, 114) ->
+ 105;
+yeccgoto(atomic_literal, 115) ->
+ 105;
+yeccgoto(atomic_literal, 120) ->
+ 105;
+yeccgoto(atomic_literal, 162) ->
+ 105;
+yeccgoto(atomic_literal, 164) ->
+ 42;
+yeccgoto(atomic_literal, 166) ->
+ 42;
+yeccgoto(atomic_literal, 171) ->
+ 42;
+yeccgoto(atomic_literal, 174) ->
+ 105;
+yeccgoto(atomic_literal, 177) ->
+ 105;
+yeccgoto(atomic_literal, 200) ->
+ 105;
+yeccgoto(atomic_literal, 203) ->
+ 42;
+yeccgoto(atomic_literal, 211) ->
+ 42;
+yeccgoto(atomic_literal, 214) ->
+ 42;
+yeccgoto(atomic_literal, 216) ->
+ 42;
+yeccgoto(atomic_literal, 218) ->
+ 42;
+yeccgoto(atomic_literal, 222) ->
+ 105;
+yeccgoto(atomic_literal, 226) ->
+ 42;
+yeccgoto(atomic_literal, 232) ->
+ 42;
+yeccgoto(atomic_literal, 235) ->
+ 42;
+yeccgoto(atomic_literal, 257) ->
+ 42;
+yeccgoto(atomic_literal, 260) ->
+ 42;
+yeccgoto(atomic_literal, 265) ->
+ 42;
+yeccgoto(atomic_literal, 284) ->
+ 286;
+yeccgoto(atomic_literal, 285) ->
+ 286;
+yeccgoto(atomic_literal, 290) ->
+ 286;
+yeccgoto(atomic_literal, 295) ->
+ 286;
+yeccgoto(atomic_literal, 298) ->
+ 286;
+yeccgoto(atomic_literal, 301) ->
+ 286;
+yeccgoto(atomic_pattern, 65) ->
+ 106;
+yeccgoto(atomic_pattern, 96) ->
+ 106;
+yeccgoto(atomic_pattern, 97) ->
+ 106;
+yeccgoto(atomic_pattern, 98) ->
+ 106;
+yeccgoto(atomic_pattern, 100) ->
+ 106;
+yeccgoto(atomic_pattern, 114) ->
+ 106;
+yeccgoto(atomic_pattern, 115) ->
+ 106;
+yeccgoto(atomic_pattern, 120) ->
+ 106;
+yeccgoto(atomic_pattern, 162) ->
+ 106;
+yeccgoto(atomic_pattern, 174) ->
+ 106;
+yeccgoto(atomic_pattern, 177) ->
+ 106;
+yeccgoto(atomic_pattern, 200) ->
+ 106;
+yeccgoto(atomic_pattern, 222) ->
+ 106;
+yeccgoto(attribute, 276) ->
+ 279;
+yeccgoto(attribute, 282) ->
+ 279;
+yeccgoto(attribute_list, 276) ->
+ 280;
+yeccgoto(attribute_list, 282) ->
+ 283;
+yeccgoto(binary, 33) ->
+ 43;
+yeccgoto(binary, 35) ->
+ 43;
+yeccgoto(binary, 36) ->
+ 43;
+yeccgoto(binary, 37) ->
+ 43;
+yeccgoto(binary, 40) ->
+ 43;
+yeccgoto(binary, 44) ->
+ 43;
+yeccgoto(binary, 46) ->
+ 43;
+yeccgoto(binary, 48) ->
+ 43;
+yeccgoto(binary, 52) ->
+ 43;
+yeccgoto(binary, 70) ->
+ 43;
+yeccgoto(binary, 74) ->
+ 43;
+yeccgoto(binary, 79) ->
+ 43;
+yeccgoto(binary, 86) ->
+ 43;
+yeccgoto(binary, 90) ->
+ 43;
+yeccgoto(binary, 99) ->
+ 43;
+yeccgoto(binary, 164) ->
+ 43;
+yeccgoto(binary, 166) ->
+ 43;
+yeccgoto(binary, 171) ->
+ 43;
+yeccgoto(binary, 203) ->
+ 43;
+yeccgoto(binary, 211) ->
+ 43;
+yeccgoto(binary, 214) ->
+ 43;
+yeccgoto(binary, 216) ->
+ 43;
+yeccgoto(binary, 218) ->
+ 43;
+yeccgoto(binary, 226) ->
+ 43;
+yeccgoto(binary, 232) ->
+ 43;
+yeccgoto(binary, 235) ->
+ 43;
+yeccgoto(binary, 257) ->
+ 43;
+yeccgoto(binary, 260) ->
+ 43;
+yeccgoto(binary, 265) ->
+ 43;
+yeccgoto(binary_pattern, 65) ->
+ 107;
+yeccgoto(binary_pattern, 96) ->
+ 107;
+yeccgoto(binary_pattern, 97) ->
+ 107;
+yeccgoto(binary_pattern, 98) ->
+ 107;
+yeccgoto(binary_pattern, 100) ->
+ 107;
+yeccgoto(binary_pattern, 114) ->
+ 107;
+yeccgoto(binary_pattern, 115) ->
+ 107;
+yeccgoto(binary_pattern, 120) ->
+ 107;
+yeccgoto(binary_pattern, 162) ->
+ 107;
+yeccgoto(binary_pattern, 174) ->
+ 107;
+yeccgoto(binary_pattern, 177) ->
+ 107;
+yeccgoto(binary_pattern, 200) ->
+ 107;
+yeccgoto(binary_pattern, 222) ->
+ 107;
+yeccgoto(call_expr, 33) ->
+ 45;
+yeccgoto(call_expr, 35) ->
+ 45;
+yeccgoto(call_expr, 36) ->
+ 45;
+yeccgoto(call_expr, 37) ->
+ 45;
+yeccgoto(call_expr, 40) ->
+ 45;
+yeccgoto(call_expr, 44) ->
+ 45;
+yeccgoto(call_expr, 46) ->
+ 45;
+yeccgoto(call_expr, 48) ->
+ 45;
+yeccgoto(call_expr, 52) ->
+ 45;
+yeccgoto(call_expr, 70) ->
+ 45;
+yeccgoto(call_expr, 74) ->
+ 45;
+yeccgoto(call_expr, 79) ->
+ 45;
+yeccgoto(call_expr, 86) ->
+ 45;
+yeccgoto(call_expr, 90) ->
+ 45;
+yeccgoto(call_expr, 99) ->
+ 45;
+yeccgoto(call_expr, 164) ->
+ 45;
+yeccgoto(call_expr, 166) ->
+ 45;
+yeccgoto(call_expr, 171) ->
+ 45;
+yeccgoto(call_expr, 203) ->
+ 45;
+yeccgoto(call_expr, 211) ->
+ 45;
+yeccgoto(call_expr, 214) ->
+ 45;
+yeccgoto(call_expr, 216) ->
+ 45;
+yeccgoto(call_expr, 218) ->
+ 45;
+yeccgoto(call_expr, 226) ->
+ 45;
+yeccgoto(call_expr, 232) ->
+ 45;
+yeccgoto(call_expr, 235) ->
+ 45;
+yeccgoto(call_expr, 257) ->
+ 45;
+yeccgoto(call_expr, 260) ->
+ 45;
+yeccgoto(call_expr, 265) ->
+ 45;
+yeccgoto(case_expr, 33) ->
+ 47;
+yeccgoto(case_expr, 35) ->
+ 47;
+yeccgoto(case_expr, 36) ->
+ 47;
+yeccgoto(case_expr, 37) ->
+ 47;
+yeccgoto(case_expr, 40) ->
+ 47;
+yeccgoto(case_expr, 44) ->
+ 47;
+yeccgoto(case_expr, 46) ->
+ 47;
+yeccgoto(case_expr, 48) ->
+ 47;
+yeccgoto(case_expr, 52) ->
+ 47;
+yeccgoto(case_expr, 70) ->
+ 47;
+yeccgoto(case_expr, 74) ->
+ 47;
+yeccgoto(case_expr, 79) ->
+ 47;
+yeccgoto(case_expr, 86) ->
+ 47;
+yeccgoto(case_expr, 90) ->
+ 47;
+yeccgoto(case_expr, 99) ->
+ 47;
+yeccgoto(case_expr, 164) ->
+ 47;
+yeccgoto(case_expr, 166) ->
+ 47;
+yeccgoto(case_expr, 171) ->
+ 47;
+yeccgoto(case_expr, 203) ->
+ 47;
+yeccgoto(case_expr, 211) ->
+ 47;
+yeccgoto(case_expr, 214) ->
+ 47;
+yeccgoto(case_expr, 216) ->
+ 47;
+yeccgoto(case_expr, 218) ->
+ 47;
+yeccgoto(case_expr, 226) ->
+ 47;
+yeccgoto(case_expr, 232) ->
+ 47;
+yeccgoto(case_expr, 235) ->
+ 47;
+yeccgoto(case_expr, 257) ->
+ 47;
+yeccgoto(case_expr, 260) ->
+ 47;
+yeccgoto(case_expr, 265) ->
+ 47;
+yeccgoto(catch_expr, 33) ->
+ 49;
+yeccgoto(catch_expr, 35) ->
+ 49;
+yeccgoto(catch_expr, 36) ->
+ 49;
+yeccgoto(catch_expr, 37) ->
+ 49;
+yeccgoto(catch_expr, 40) ->
+ 49;
+yeccgoto(catch_expr, 44) ->
+ 49;
+yeccgoto(catch_expr, 46) ->
+ 49;
+yeccgoto(catch_expr, 48) ->
+ 49;
+yeccgoto(catch_expr, 52) ->
+ 49;
+yeccgoto(catch_expr, 70) ->
+ 49;
+yeccgoto(catch_expr, 74) ->
+ 49;
+yeccgoto(catch_expr, 79) ->
+ 49;
+yeccgoto(catch_expr, 86) ->
+ 49;
+yeccgoto(catch_expr, 90) ->
+ 49;
+yeccgoto(catch_expr, 99) ->
+ 49;
+yeccgoto(catch_expr, 164) ->
+ 49;
+yeccgoto(catch_expr, 166) ->
+ 49;
+yeccgoto(catch_expr, 171) ->
+ 49;
+yeccgoto(catch_expr, 203) ->
+ 49;
+yeccgoto(catch_expr, 211) ->
+ 49;
+yeccgoto(catch_expr, 214) ->
+ 49;
+yeccgoto(catch_expr, 216) ->
+ 49;
+yeccgoto(catch_expr, 218) ->
+ 49;
+yeccgoto(catch_expr, 226) ->
+ 49;
+yeccgoto(catch_expr, 232) ->
+ 49;
+yeccgoto(catch_expr, 235) ->
+ 49;
+yeccgoto(catch_expr, 257) ->
+ 49;
+yeccgoto(catch_expr, 260) ->
+ 49;
+yeccgoto(catch_expr, 265) ->
+ 49;
+yeccgoto(clause, 65) ->
+ 108;
+yeccgoto(clause, 96) ->
+ 185;
+yeccgoto(clause, 100) ->
+ 108;
+yeccgoto(clause, 222) ->
+ 108;
+yeccgoto(clause_pattern, 65) ->
+ 109;
+yeccgoto(clause_pattern, 96) ->
+ 109;
+yeccgoto(clause_pattern, 100) ->
+ 109;
+yeccgoto(clause_pattern, 222) ->
+ 109;
+yeccgoto(cons, 33) ->
+ 51;
+yeccgoto(cons, 35) ->
+ 51;
+yeccgoto(cons, 36) ->
+ 51;
+yeccgoto(cons, 37) ->
+ 51;
+yeccgoto(cons, 40) ->
+ 51;
+yeccgoto(cons, 44) ->
+ 51;
+yeccgoto(cons, 46) ->
+ 51;
+yeccgoto(cons, 48) ->
+ 51;
+yeccgoto(cons, 52) ->
+ 51;
+yeccgoto(cons, 70) ->
+ 51;
+yeccgoto(cons, 74) ->
+ 51;
+yeccgoto(cons, 79) ->
+ 51;
+yeccgoto(cons, 86) ->
+ 51;
+yeccgoto(cons, 90) ->
+ 51;
+yeccgoto(cons, 99) ->
+ 51;
+yeccgoto(cons, 164) ->
+ 51;
+yeccgoto(cons, 166) ->
+ 51;
+yeccgoto(cons, 171) ->
+ 51;
+yeccgoto(cons, 203) ->
+ 51;
+yeccgoto(cons, 211) ->
+ 51;
+yeccgoto(cons, 214) ->
+ 51;
+yeccgoto(cons, 216) ->
+ 51;
+yeccgoto(cons, 218) ->
+ 51;
+yeccgoto(cons, 226) ->
+ 51;
+yeccgoto(cons, 232) ->
+ 51;
+yeccgoto(cons, 235) ->
+ 51;
+yeccgoto(cons, 257) ->
+ 51;
+yeccgoto(cons, 260) ->
+ 51;
+yeccgoto(cons, 265) ->
+ 51;
+yeccgoto(cons_constant, 126) ->
+ 134;
+yeccgoto(cons_constant, 129) ->
+ 134;
+yeccgoto(cons_constant, 142) ->
+ 134;
+yeccgoto(cons_constant, 147) ->
+ 134;
+yeccgoto(cons_constant, 151) ->
+ 134;
+yeccgoto(cons_constant, 154) ->
+ 134;
+yeccgoto(cons_literal, 284) ->
+ 287;
+yeccgoto(cons_literal, 285) ->
+ 287;
+yeccgoto(cons_literal, 290) ->
+ 287;
+yeccgoto(cons_literal, 295) ->
+ 287;
+yeccgoto(cons_literal, 298) ->
+ 287;
+yeccgoto(cons_literal, 301) ->
+ 287;
+yeccgoto(cons_pattern, 65) ->
+ 110;
+yeccgoto(cons_pattern, 96) ->
+ 110;
+yeccgoto(cons_pattern, 97) ->
+ 110;
+yeccgoto(cons_pattern, 98) ->
+ 110;
+yeccgoto(cons_pattern, 100) ->
+ 110;
+yeccgoto(cons_pattern, 114) ->
+ 110;
+yeccgoto(cons_pattern, 115) ->
+ 110;
+yeccgoto(cons_pattern, 120) ->
+ 110;
+yeccgoto(cons_pattern, 162) ->
+ 110;
+yeccgoto(cons_pattern, 174) ->
+ 110;
+yeccgoto(cons_pattern, 177) ->
+ 110;
+yeccgoto(cons_pattern, 200) ->
+ 110;
+yeccgoto(cons_pattern, 222) ->
+ 110;
+yeccgoto(constant, 126) ->
+ 135;
+yeccgoto(constant, 129) ->
+ 150;
+yeccgoto(constant, 142) ->
+ 135;
+yeccgoto(constant, 147) ->
+ 135;
+yeccgoto(constant, 151) ->
+ 157;
+yeccgoto(constant, 154) ->
+ 155;
+yeccgoto(constants, 126) ->
+ 136;
+yeccgoto(constants, 142) ->
+ 143;
+yeccgoto(constants, 147) ->
+ 148;
+yeccgoto(exported_name, 5) ->
+ 307;
+yeccgoto(exported_name, 311) ->
+ 307;
+yeccgoto(exported_names, 5) ->
+ 308;
+yeccgoto(exported_names, 311) ->
+ 312;
+yeccgoto(expression, 33) ->
+ 53;
+yeccgoto(expression, 35) ->
+ 243;
+yeccgoto(expression, 36) ->
+ 53;
+yeccgoto(expression, 37) ->
+ 53;
+yeccgoto(expression, 40) ->
+ 53;
+yeccgoto(expression, 44) ->
+ 53;
+yeccgoto(expression, 46) ->
+ 53;
+yeccgoto(expression, 48) ->
+ 53;
+yeccgoto(expression, 52) ->
+ 53;
+yeccgoto(expression, 70) ->
+ 53;
+yeccgoto(expression, 74) ->
+ 53;
+yeccgoto(expression, 79) ->
+ 53;
+yeccgoto(expression, 86) ->
+ 53;
+yeccgoto(expression, 90) ->
+ 53;
+yeccgoto(expression, 99) ->
+ 53;
+yeccgoto(expression, 164) ->
+ 53;
+yeccgoto(expression, 166) ->
+ 53;
+yeccgoto(expression, 171) ->
+ 53;
+yeccgoto(expression, 203) ->
+ 53;
+yeccgoto(expression, 211) ->
+ 53;
+yeccgoto(expression, 214) ->
+ 53;
+yeccgoto(expression, 216) ->
+ 53;
+yeccgoto(expression, 218) ->
+ 53;
+yeccgoto(expression, 226) ->
+ 53;
+yeccgoto(expression, 232) ->
+ 53;
+yeccgoto(expression, 235) ->
+ 53;
+yeccgoto(expression, 257) ->
+ 53;
+yeccgoto(expression, 260) ->
+ 53;
+yeccgoto(expression, 265) ->
+ 53;
+yeccgoto(fun_expr, 20) ->
+ 24;
+yeccgoto(fun_expr, 21) ->
+ 268;
+yeccgoto(fun_expr, 33) ->
+ 55;
+yeccgoto(fun_expr, 35) ->
+ 55;
+yeccgoto(fun_expr, 36) ->
+ 55;
+yeccgoto(fun_expr, 37) ->
+ 55;
+yeccgoto(fun_expr, 40) ->
+ 55;
+yeccgoto(fun_expr, 44) ->
+ 55;
+yeccgoto(fun_expr, 46) ->
+ 55;
+yeccgoto(fun_expr, 48) ->
+ 55;
+yeccgoto(fun_expr, 52) ->
+ 55;
+yeccgoto(fun_expr, 70) ->
+ 55;
+yeccgoto(fun_expr, 74) ->
+ 55;
+yeccgoto(fun_expr, 79) ->
+ 55;
+yeccgoto(fun_expr, 86) ->
+ 55;
+yeccgoto(fun_expr, 90) ->
+ 55;
+yeccgoto(fun_expr, 99) ->
+ 55;
+yeccgoto(fun_expr, 164) ->
+ 55;
+yeccgoto(fun_expr, 166) ->
+ 55;
+yeccgoto(fun_expr, 171) ->
+ 55;
+yeccgoto(fun_expr, 203) ->
+ 55;
+yeccgoto(fun_expr, 211) ->
+ 55;
+yeccgoto(fun_expr, 214) ->
+ 55;
+yeccgoto(fun_expr, 216) ->
+ 55;
+yeccgoto(fun_expr, 218) ->
+ 55;
+yeccgoto(fun_expr, 226) ->
+ 55;
+yeccgoto(fun_expr, 232) ->
+ 55;
+yeccgoto(fun_expr, 235) ->
+ 55;
+yeccgoto(fun_expr, 257) ->
+ 55;
+yeccgoto(fun_expr, 260) ->
+ 55;
+yeccgoto(fun_expr, 265) ->
+ 55;
+yeccgoto(function_definition, 8) ->
+ 12;
+yeccgoto(function_definition, 12) ->
+ 12;
+yeccgoto(function_definition, 60) ->
+ 12;
+yeccgoto(function_definition, 316) ->
+ 12;
+yeccgoto(function_definitions, 8) ->
+ 13;
+yeccgoto(function_definitions, 12) ->
+ 17;
+yeccgoto(function_definitions, 60) ->
+ 210;
+yeccgoto(function_definitions, 316) ->
+ 13;
+yeccgoto(function_name, 5) ->
+ 309;
+yeccgoto(function_name, 8) ->
+ 14;
+yeccgoto(function_name, 9) ->
+ 272;
+yeccgoto(function_name, 12) ->
+ 14;
+yeccgoto(function_name, 33) ->
+ 56;
+yeccgoto(function_name, 35) ->
+ 56;
+yeccgoto(function_name, 36) ->
+ 56;
+yeccgoto(function_name, 37) ->
+ 56;
+yeccgoto(function_name, 40) ->
+ 56;
+yeccgoto(function_name, 44) ->
+ 56;
+yeccgoto(function_name, 46) ->
+ 56;
+yeccgoto(function_name, 48) ->
+ 56;
+yeccgoto(function_name, 52) ->
+ 56;
+yeccgoto(function_name, 60) ->
+ 14;
+yeccgoto(function_name, 70) ->
+ 56;
+yeccgoto(function_name, 74) ->
+ 56;
+yeccgoto(function_name, 79) ->
+ 56;
+yeccgoto(function_name, 86) ->
+ 56;
+yeccgoto(function_name, 90) ->
+ 56;
+yeccgoto(function_name, 99) ->
+ 56;
+yeccgoto(function_name, 164) ->
+ 56;
+yeccgoto(function_name, 166) ->
+ 56;
+yeccgoto(function_name, 171) ->
+ 56;
+yeccgoto(function_name, 203) ->
+ 56;
+yeccgoto(function_name, 211) ->
+ 56;
+yeccgoto(function_name, 214) ->
+ 56;
+yeccgoto(function_name, 216) ->
+ 56;
+yeccgoto(function_name, 218) ->
+ 56;
+yeccgoto(function_name, 226) ->
+ 56;
+yeccgoto(function_name, 232) ->
+ 56;
+yeccgoto(function_name, 235) ->
+ 56;
+yeccgoto(function_name, 257) ->
+ 56;
+yeccgoto(function_name, 260) ->
+ 56;
+yeccgoto(function_name, 265) ->
+ 56;
+yeccgoto(function_name, 311) ->
+ 309;
+yeccgoto(function_name, 316) ->
+ 14;
+yeccgoto(let_expr, 33) ->
+ 59;
+yeccgoto(let_expr, 35) ->
+ 59;
+yeccgoto(let_expr, 36) ->
+ 59;
+yeccgoto(let_expr, 37) ->
+ 59;
+yeccgoto(let_expr, 40) ->
+ 59;
+yeccgoto(let_expr, 44) ->
+ 59;
+yeccgoto(let_expr, 46) ->
+ 59;
+yeccgoto(let_expr, 48) ->
+ 59;
+yeccgoto(let_expr, 52) ->
+ 59;
+yeccgoto(let_expr, 70) ->
+ 59;
+yeccgoto(let_expr, 74) ->
+ 59;
+yeccgoto(let_expr, 79) ->
+ 59;
+yeccgoto(let_expr, 86) ->
+ 59;
+yeccgoto(let_expr, 90) ->
+ 59;
+yeccgoto(let_expr, 99) ->
+ 59;
+yeccgoto(let_expr, 164) ->
+ 59;
+yeccgoto(let_expr, 166) ->
+ 59;
+yeccgoto(let_expr, 171) ->
+ 59;
+yeccgoto(let_expr, 203) ->
+ 59;
+yeccgoto(let_expr, 211) ->
+ 59;
+yeccgoto(let_expr, 214) ->
+ 59;
+yeccgoto(let_expr, 216) ->
+ 59;
+yeccgoto(let_expr, 218) ->
+ 59;
+yeccgoto(let_expr, 226) ->
+ 59;
+yeccgoto(let_expr, 232) ->
+ 59;
+yeccgoto(let_expr, 235) ->
+ 59;
+yeccgoto(let_expr, 257) ->
+ 59;
+yeccgoto(let_expr, 260) ->
+ 59;
+yeccgoto(let_expr, 265) ->
+ 59;
+yeccgoto(let_vars, 58) ->
+ 213;
+yeccgoto(let_vars, 82) ->
+ 85;
+yeccgoto(let_vars, 88) ->
+ 89;
+yeccgoto(letrec_expr, 33) ->
+ 61;
+yeccgoto(letrec_expr, 35) ->
+ 61;
+yeccgoto(letrec_expr, 36) ->
+ 61;
+yeccgoto(letrec_expr, 37) ->
+ 61;
+yeccgoto(letrec_expr, 40) ->
+ 61;
+yeccgoto(letrec_expr, 44) ->
+ 61;
+yeccgoto(letrec_expr, 46) ->
+ 61;
+yeccgoto(letrec_expr, 48) ->
+ 61;
+yeccgoto(letrec_expr, 52) ->
+ 61;
+yeccgoto(letrec_expr, 70) ->
+ 61;
+yeccgoto(letrec_expr, 74) ->
+ 61;
+yeccgoto(letrec_expr, 79) ->
+ 61;
+yeccgoto(letrec_expr, 86) ->
+ 61;
+yeccgoto(letrec_expr, 90) ->
+ 61;
+yeccgoto(letrec_expr, 99) ->
+ 61;
+yeccgoto(letrec_expr, 164) ->
+ 61;
+yeccgoto(letrec_expr, 166) ->
+ 61;
+yeccgoto(letrec_expr, 171) ->
+ 61;
+yeccgoto(letrec_expr, 203) ->
+ 61;
+yeccgoto(letrec_expr, 211) ->
+ 61;
+yeccgoto(letrec_expr, 214) ->
+ 61;
+yeccgoto(letrec_expr, 216) ->
+ 61;
+yeccgoto(letrec_expr, 218) ->
+ 61;
+yeccgoto(letrec_expr, 226) ->
+ 61;
+yeccgoto(letrec_expr, 232) ->
+ 61;
+yeccgoto(letrec_expr, 235) ->
+ 61;
+yeccgoto(letrec_expr, 257) ->
+ 61;
+yeccgoto(letrec_expr, 260) ->
+ 61;
+yeccgoto(letrec_expr, 265) ->
+ 61;
+yeccgoto(literal, 284) ->
+ 288;
+yeccgoto(literal, 285) ->
+ 297;
+yeccgoto(literal, 290) ->
+ 291;
+yeccgoto(literal, 295) ->
+ 291;
+yeccgoto(literal, 298) ->
+ 304;
+yeccgoto(literal, 301) ->
+ 302;
+yeccgoto(literals, 290) ->
+ 292;
+yeccgoto(literals, 295) ->
+ 296;
+yeccgoto(module_attribute, 6) ->
+ 8;
+yeccgoto(module_attribute, 315) ->
+ 316;
+yeccgoto(module_definition, 0) ->
+ 3;
+yeccgoto(module_defs, 8) ->
+ 15;
+yeccgoto(module_defs, 316) ->
+ 317;
+yeccgoto(module_export, 4) ->
+ 6;
+yeccgoto(module_export, 314) ->
+ 315;
+yeccgoto(nil, 33) ->
+ 62;
+yeccgoto(nil, 35) ->
+ 62;
+yeccgoto(nil, 36) ->
+ 62;
+yeccgoto(nil, 37) ->
+ 62;
+yeccgoto(nil, 40) ->
+ 62;
+yeccgoto(nil, 44) ->
+ 62;
+yeccgoto(nil, 46) ->
+ 62;
+yeccgoto(nil, 48) ->
+ 62;
+yeccgoto(nil, 52) ->
+ 62;
+yeccgoto(nil, 65) ->
+ 62;
+yeccgoto(nil, 70) ->
+ 62;
+yeccgoto(nil, 74) ->
+ 62;
+yeccgoto(nil, 79) ->
+ 62;
+yeccgoto(nil, 86) ->
+ 62;
+yeccgoto(nil, 90) ->
+ 62;
+yeccgoto(nil, 96) ->
+ 62;
+yeccgoto(nil, 97) ->
+ 62;
+yeccgoto(nil, 98) ->
+ 62;
+yeccgoto(nil, 99) ->
+ 62;
+yeccgoto(nil, 100) ->
+ 62;
+yeccgoto(nil, 114) ->
+ 62;
+yeccgoto(nil, 115) ->
+ 62;
+yeccgoto(nil, 120) ->
+ 62;
+yeccgoto(nil, 126) ->
+ 139;
+yeccgoto(nil, 129) ->
+ 139;
+yeccgoto(nil, 142) ->
+ 139;
+yeccgoto(nil, 147) ->
+ 139;
+yeccgoto(nil, 151) ->
+ 139;
+yeccgoto(nil, 154) ->
+ 139;
+yeccgoto(nil, 162) ->
+ 62;
+yeccgoto(nil, 164) ->
+ 62;
+yeccgoto(nil, 166) ->
+ 62;
+yeccgoto(nil, 171) ->
+ 62;
+yeccgoto(nil, 174) ->
+ 62;
+yeccgoto(nil, 177) ->
+ 62;
+yeccgoto(nil, 200) ->
+ 62;
+yeccgoto(nil, 203) ->
+ 62;
+yeccgoto(nil, 211) ->
+ 62;
+yeccgoto(nil, 214) ->
+ 62;
+yeccgoto(nil, 216) ->
+ 62;
+yeccgoto(nil, 218) ->
+ 62;
+yeccgoto(nil, 222) ->
+ 62;
+yeccgoto(nil, 226) ->
+ 62;
+yeccgoto(nil, 232) ->
+ 62;
+yeccgoto(nil, 235) ->
+ 62;
+yeccgoto(nil, 257) ->
+ 62;
+yeccgoto(nil, 260) ->
+ 62;
+yeccgoto(nil, 265) ->
+ 62;
+yeccgoto(nil, 284) ->
+ 62;
+yeccgoto(nil, 285) ->
+ 62;
+yeccgoto(nil, 290) ->
+ 62;
+yeccgoto(nil, 295) ->
+ 62;
+yeccgoto(nil, 298) ->
+ 62;
+yeccgoto(nil, 301) ->
+ 62;
+yeccgoto(other_pattern, 65) ->
+ 111;
+yeccgoto(other_pattern, 96) ->
+ 186;
+yeccgoto(other_pattern, 97) ->
+ 111;
+yeccgoto(other_pattern, 98) ->
+ 111;
+yeccgoto(other_pattern, 100) ->
+ 111;
+yeccgoto(other_pattern, 114) ->
+ 111;
+yeccgoto(other_pattern, 115) ->
+ 123;
+yeccgoto(other_pattern, 120) ->
+ 111;
+yeccgoto(other_pattern, 162) ->
+ 111;
+yeccgoto(other_pattern, 174) ->
+ 111;
+yeccgoto(other_pattern, 177) ->
+ 111;
+yeccgoto(other_pattern, 200) ->
+ 111;
+yeccgoto(other_pattern, 222) ->
+ 111;
+yeccgoto(primop_expr, 33) ->
+ 64;
+yeccgoto(primop_expr, 35) ->
+ 64;
+yeccgoto(primop_expr, 36) ->
+ 64;
+yeccgoto(primop_expr, 37) ->
+ 64;
+yeccgoto(primop_expr, 40) ->
+ 64;
+yeccgoto(primop_expr, 44) ->
+ 64;
+yeccgoto(primop_expr, 46) ->
+ 64;
+yeccgoto(primop_expr, 48) ->
+ 64;
+yeccgoto(primop_expr, 52) ->
+ 64;
+yeccgoto(primop_expr, 70) ->
+ 64;
+yeccgoto(primop_expr, 74) ->
+ 64;
+yeccgoto(primop_expr, 79) ->
+ 64;
+yeccgoto(primop_expr, 86) ->
+ 64;
+yeccgoto(primop_expr, 90) ->
+ 64;
+yeccgoto(primop_expr, 99) ->
+ 64;
+yeccgoto(primop_expr, 164) ->
+ 64;
+yeccgoto(primop_expr, 166) ->
+ 64;
+yeccgoto(primop_expr, 171) ->
+ 64;
+yeccgoto(primop_expr, 203) ->
+ 64;
+yeccgoto(primop_expr, 211) ->
+ 64;
+yeccgoto(primop_expr, 214) ->
+ 64;
+yeccgoto(primop_expr, 216) ->
+ 64;
+yeccgoto(primop_expr, 218) ->
+ 64;
+yeccgoto(primop_expr, 226) ->
+ 64;
+yeccgoto(primop_expr, 232) ->
+ 64;
+yeccgoto(primop_expr, 235) ->
+ 64;
+yeccgoto(primop_expr, 257) ->
+ 64;
+yeccgoto(primop_expr, 260) ->
+ 64;
+yeccgoto(primop_expr, 265) ->
+ 64;
+yeccgoto(receive_expr, 33) ->
+ 66;
+yeccgoto(receive_expr, 35) ->
+ 66;
+yeccgoto(receive_expr, 36) ->
+ 66;
+yeccgoto(receive_expr, 37) ->
+ 66;
+yeccgoto(receive_expr, 40) ->
+ 66;
+yeccgoto(receive_expr, 44) ->
+ 66;
+yeccgoto(receive_expr, 46) ->
+ 66;
+yeccgoto(receive_expr, 48) ->
+ 66;
+yeccgoto(receive_expr, 52) ->
+ 66;
+yeccgoto(receive_expr, 70) ->
+ 66;
+yeccgoto(receive_expr, 74) ->
+ 66;
+yeccgoto(receive_expr, 79) ->
+ 66;
+yeccgoto(receive_expr, 86) ->
+ 66;
+yeccgoto(receive_expr, 90) ->
+ 66;
+yeccgoto(receive_expr, 99) ->
+ 66;
+yeccgoto(receive_expr, 164) ->
+ 66;
+yeccgoto(receive_expr, 166) ->
+ 66;
+yeccgoto(receive_expr, 171) ->
+ 66;
+yeccgoto(receive_expr, 203) ->
+ 66;
+yeccgoto(receive_expr, 211) ->
+ 66;
+yeccgoto(receive_expr, 214) ->
+ 66;
+yeccgoto(receive_expr, 216) ->
+ 66;
+yeccgoto(receive_expr, 218) ->
+ 66;
+yeccgoto(receive_expr, 226) ->
+ 66;
+yeccgoto(receive_expr, 232) ->
+ 66;
+yeccgoto(receive_expr, 235) ->
+ 66;
+yeccgoto(receive_expr, 257) ->
+ 66;
+yeccgoto(receive_expr, 260) ->
+ 66;
+yeccgoto(receive_expr, 265) ->
+ 66;
+yeccgoto(segment, 247) ->
+ 249;
+yeccgoto(segment, 255) ->
+ 249;
+yeccgoto(segment_pattern, 190) ->
+ 192;
+yeccgoto(segment_pattern, 198) ->
+ 192;
+yeccgoto(segment_patterns, 190) ->
+ 193;
+yeccgoto(segment_patterns, 198) ->
+ 199;
+yeccgoto(segments, 247) ->
+ 250;
+yeccgoto(segments, 255) ->
+ 256;
+yeccgoto(sequence, 33) ->
+ 67;
+yeccgoto(sequence, 35) ->
+ 67;
+yeccgoto(sequence, 36) ->
+ 67;
+yeccgoto(sequence, 37) ->
+ 67;
+yeccgoto(sequence, 40) ->
+ 67;
+yeccgoto(sequence, 44) ->
+ 67;
+yeccgoto(sequence, 46) ->
+ 67;
+yeccgoto(sequence, 48) ->
+ 67;
+yeccgoto(sequence, 52) ->
+ 67;
+yeccgoto(sequence, 70) ->
+ 67;
+yeccgoto(sequence, 74) ->
+ 67;
+yeccgoto(sequence, 79) ->
+ 67;
+yeccgoto(sequence, 86) ->
+ 67;
+yeccgoto(sequence, 90) ->
+ 67;
+yeccgoto(sequence, 99) ->
+ 67;
+yeccgoto(sequence, 164) ->
+ 67;
+yeccgoto(sequence, 166) ->
+ 67;
+yeccgoto(sequence, 171) ->
+ 67;
+yeccgoto(sequence, 203) ->
+ 67;
+yeccgoto(sequence, 211) ->
+ 67;
+yeccgoto(sequence, 214) ->
+ 67;
+yeccgoto(sequence, 216) ->
+ 67;
+yeccgoto(sequence, 218) ->
+ 67;
+yeccgoto(sequence, 226) ->
+ 67;
+yeccgoto(sequence, 232) ->
+ 67;
+yeccgoto(sequence, 235) ->
+ 67;
+yeccgoto(sequence, 257) ->
+ 67;
+yeccgoto(sequence, 260) ->
+ 67;
+yeccgoto(sequence, 265) ->
+ 67;
+yeccgoto(single_expression, 33) ->
+ 68;
+yeccgoto(single_expression, 35) ->
+ 68;
+yeccgoto(single_expression, 36) ->
+ 68;
+yeccgoto(single_expression, 37) ->
+ 68;
+yeccgoto(single_expression, 40) ->
+ 68;
+yeccgoto(single_expression, 44) ->
+ 68;
+yeccgoto(single_expression, 46) ->
+ 68;
+yeccgoto(single_expression, 48) ->
+ 68;
+yeccgoto(single_expression, 52) ->
+ 68;
+yeccgoto(single_expression, 70) ->
+ 68;
+yeccgoto(single_expression, 74) ->
+ 68;
+yeccgoto(single_expression, 79) ->
+ 68;
+yeccgoto(single_expression, 86) ->
+ 68;
+yeccgoto(single_expression, 90) ->
+ 68;
+yeccgoto(single_expression, 99) ->
+ 68;
+yeccgoto(single_expression, 164) ->
+ 68;
+yeccgoto(single_expression, 166) ->
+ 68;
+yeccgoto(single_expression, 171) ->
+ 68;
+yeccgoto(single_expression, 203) ->
+ 68;
+yeccgoto(single_expression, 211) ->
+ 68;
+yeccgoto(single_expression, 214) ->
+ 68;
+yeccgoto(single_expression, 216) ->
+ 68;
+yeccgoto(single_expression, 218) ->
+ 68;
+yeccgoto(single_expression, 226) ->
+ 68;
+yeccgoto(single_expression, 232) ->
+ 68;
+yeccgoto(single_expression, 235) ->
+ 68;
+yeccgoto(single_expression, 257) ->
+ 68;
+yeccgoto(single_expression, 260) ->
+ 68;
+yeccgoto(single_expression, 265) ->
+ 68;
+yeccgoto(tail, 231) ->
+ 234;
+yeccgoto(tail, 238) ->
+ 239;
+yeccgoto(tail_constant, 150) ->
+ 153;
+yeccgoto(tail_constant, 157) ->
+ 158;
+yeccgoto(tail_literal, 297) ->
+ 300;
+yeccgoto(tail_literal, 304) ->
+ 305;
+yeccgoto(tail_pattern, 173) ->
+ 176;
+yeccgoto(tail_pattern, 180) ->
+ 181;
+yeccgoto(timeout, 65) ->
+ 112;
+yeccgoto(timeout, 101) ->
+ 168;
+yeccgoto(try_expr, 33) ->
+ 71;
+yeccgoto(try_expr, 35) ->
+ 71;
+yeccgoto(try_expr, 36) ->
+ 71;
+yeccgoto(try_expr, 37) ->
+ 71;
+yeccgoto(try_expr, 40) ->
+ 71;
+yeccgoto(try_expr, 44) ->
+ 71;
+yeccgoto(try_expr, 46) ->
+ 71;
+yeccgoto(try_expr, 48) ->
+ 71;
+yeccgoto(try_expr, 52) ->
+ 71;
+yeccgoto(try_expr, 70) ->
+ 71;
+yeccgoto(try_expr, 74) ->
+ 71;
+yeccgoto(try_expr, 79) ->
+ 71;
+yeccgoto(try_expr, 86) ->
+ 71;
+yeccgoto(try_expr, 90) ->
+ 71;
+yeccgoto(try_expr, 99) ->
+ 71;
+yeccgoto(try_expr, 164) ->
+ 71;
+yeccgoto(try_expr, 166) ->
+ 71;
+yeccgoto(try_expr, 171) ->
+ 71;
+yeccgoto(try_expr, 203) ->
+ 71;
+yeccgoto(try_expr, 211) ->
+ 71;
+yeccgoto(try_expr, 214) ->
+ 71;
+yeccgoto(try_expr, 216) ->
+ 71;
+yeccgoto(try_expr, 218) ->
+ 71;
+yeccgoto(try_expr, 226) ->
+ 71;
+yeccgoto(try_expr, 232) ->
+ 71;
+yeccgoto(try_expr, 235) ->
+ 71;
+yeccgoto(try_expr, 257) ->
+ 71;
+yeccgoto(try_expr, 260) ->
+ 71;
+yeccgoto(try_expr, 265) ->
+ 71;
+yeccgoto(tuple, 33) ->
+ 72;
+yeccgoto(tuple, 35) ->
+ 72;
+yeccgoto(tuple, 36) ->
+ 72;
+yeccgoto(tuple, 37) ->
+ 72;
+yeccgoto(tuple, 40) ->
+ 72;
+yeccgoto(tuple, 44) ->
+ 72;
+yeccgoto(tuple, 46) ->
+ 72;
+yeccgoto(tuple, 48) ->
+ 72;
+yeccgoto(tuple, 52) ->
+ 72;
+yeccgoto(tuple, 70) ->
+ 72;
+yeccgoto(tuple, 74) ->
+ 72;
+yeccgoto(tuple, 79) ->
+ 72;
+yeccgoto(tuple, 86) ->
+ 72;
+yeccgoto(tuple, 90) ->
+ 72;
+yeccgoto(tuple, 99) ->
+ 72;
+yeccgoto(tuple, 164) ->
+ 72;
+yeccgoto(tuple, 166) ->
+ 72;
+yeccgoto(tuple, 171) ->
+ 72;
+yeccgoto(tuple, 203) ->
+ 72;
+yeccgoto(tuple, 211) ->
+ 72;
+yeccgoto(tuple, 214) ->
+ 72;
+yeccgoto(tuple, 216) ->
+ 72;
+yeccgoto(tuple, 218) ->
+ 72;
+yeccgoto(tuple, 226) ->
+ 72;
+yeccgoto(tuple, 232) ->
+ 72;
+yeccgoto(tuple, 235) ->
+ 72;
+yeccgoto(tuple, 257) ->
+ 72;
+yeccgoto(tuple, 260) ->
+ 72;
+yeccgoto(tuple, 265) ->
+ 72;
+yeccgoto(tuple_constant, 126) ->
+ 141;
+yeccgoto(tuple_constant, 129) ->
+ 141;
+yeccgoto(tuple_constant, 142) ->
+ 141;
+yeccgoto(tuple_constant, 147) ->
+ 141;
+yeccgoto(tuple_constant, 151) ->
+ 141;
+yeccgoto(tuple_constant, 154) ->
+ 141;
+yeccgoto(tuple_literal, 284) ->
+ 289;
+yeccgoto(tuple_literal, 285) ->
+ 289;
+yeccgoto(tuple_literal, 290) ->
+ 289;
+yeccgoto(tuple_literal, 295) ->
+ 289;
+yeccgoto(tuple_literal, 298) ->
+ 289;
+yeccgoto(tuple_literal, 301) ->
+ 289;
+yeccgoto(tuple_pattern, 65) ->
+ 113;
+yeccgoto(tuple_pattern, 96) ->
+ 113;
+yeccgoto(tuple_pattern, 97) ->
+ 113;
+yeccgoto(tuple_pattern, 98) ->
+ 113;
+yeccgoto(tuple_pattern, 100) ->
+ 113;
+yeccgoto(tuple_pattern, 114) ->
+ 113;
+yeccgoto(tuple_pattern, 115) ->
+ 113;
+yeccgoto(tuple_pattern, 120) ->
+ 113;
+yeccgoto(tuple_pattern, 162) ->
+ 113;
+yeccgoto(tuple_pattern, 174) ->
+ 113;
+yeccgoto(tuple_pattern, 177) ->
+ 113;
+yeccgoto(tuple_pattern, 200) ->
+ 113;
+yeccgoto(tuple_pattern, 222) ->
+ 113;
+yeccgoto(variable, 25) ->
+ 31;
+yeccgoto(variable, 26) ->
+ 267;
+yeccgoto(variable, 33) ->
+ 73;
+yeccgoto(variable, 35) ->
+ 73;
+yeccgoto(variable, 36) ->
+ 73;
+yeccgoto(variable, 37) ->
+ 73;
+yeccgoto(variable, 40) ->
+ 73;
+yeccgoto(variable, 44) ->
+ 73;
+yeccgoto(variable, 46) ->
+ 73;
+yeccgoto(variable, 48) ->
+ 73;
+yeccgoto(variable, 52) ->
+ 73;
+yeccgoto(variable, 58) ->
+ 31;
+yeccgoto(variable, 65) ->
+ 31;
+yeccgoto(variable, 70) ->
+ 73;
+yeccgoto(variable, 74) ->
+ 73;
+yeccgoto(variable, 79) ->
+ 73;
+yeccgoto(variable, 82) ->
+ 31;
+yeccgoto(variable, 83) ->
+ 31;
+yeccgoto(variable, 86) ->
+ 73;
+yeccgoto(variable, 88) ->
+ 31;
+yeccgoto(variable, 90) ->
+ 73;
+yeccgoto(variable, 96) ->
+ 124;
+yeccgoto(variable, 97) ->
+ 31;
+yeccgoto(variable, 98) ->
+ 31;
+yeccgoto(variable, 99) ->
+ 73;
+yeccgoto(variable, 100) ->
+ 31;
+yeccgoto(variable, 114) ->
+ 31;
+yeccgoto(variable, 115) ->
+ 124;
+yeccgoto(variable, 120) ->
+ 31;
+yeccgoto(variable, 162) ->
+ 31;
+yeccgoto(variable, 164) ->
+ 73;
+yeccgoto(variable, 166) ->
+ 73;
+yeccgoto(variable, 171) ->
+ 73;
+yeccgoto(variable, 174) ->
+ 31;
+yeccgoto(variable, 177) ->
+ 31;
+yeccgoto(variable, 200) ->
+ 31;
+yeccgoto(variable, 203) ->
+ 73;
+yeccgoto(variable, 211) ->
+ 73;
+yeccgoto(variable, 214) ->
+ 73;
+yeccgoto(variable, 216) ->
+ 73;
+yeccgoto(variable, 218) ->
+ 73;
+yeccgoto(variable, 222) ->
+ 31;
+yeccgoto(variable, 226) ->
+ 73;
+yeccgoto(variable, 232) ->
+ 73;
+yeccgoto(variable, 235) ->
+ 73;
+yeccgoto(variable, 257) ->
+ 73;
+yeccgoto(variable, 260) ->
+ 73;
+yeccgoto(variable, 263) ->
+ 31;
+yeccgoto(variable, 265) ->
+ 73;
+yeccgoto(__Symbol, __State) ->
+ exit({__Symbol, __State, missing_in_goto_table}).
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_parse.hrl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_parse.hrl
new file mode 100644
index 0000000000..3d60360f47
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_parse.hrl
@@ -0,0 +1,111 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: core_parse.hrl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
+%%
+%% Purpose : Core Erlang syntax trees as records.
+
+%% It would be nice to incorporate some generic functions as well but
+%% this could make including this file difficult.
+
+%% Note: the annotation list is *always* the first record field.
+%% Thus it is possible to define the macros:
+%% -define(get_ann(X), element(2, X)).
+%% -define(set_ann(X, Y), setelement(2, X, Y)).
+
+-record(c_int, {anno=[], val}). % val :: integer()
+
+-record(c_float, {anno=[], val}). % val :: float()
+
+-record(c_atom, {anno=[], val}). % val :: atom()
+
+-record(c_char, {anno=[], val}). % val :: char()
+
+-record(c_string, {anno=[], val}). % val :: string()
+
+-record(c_nil, {anno=[]}).
+
+-record(c_binary, {anno=[], segments}). % segments :: [#ce_bitstr{}]
+
+-record(c_bitstr, {anno=[],val, % val :: Tree,
+ size, % size :: Tree,
+ unit, % unit :: integer(),
+ type, % type :: atom(),
+ flags}). % flags :: [atom()],
+
+-record(c_cons, {anno=[], hd, % hd :: Tree,
+ tl}). % tl :: Tree
+
+-record(c_tuple, {anno=[], es}). % es :: [Tree]
+
+-record(c_var, {anno=[], name}). % name :: integer() | atom()
+
+-record(c_fname, {anno=[], id, % id :: atom(),
+ arity}). % arity :: integer()
+
+-record(c_values, {anno=[], es}). % es :: [Tree]
+
+-record(c_fun, {anno=[], vars, % vars :: [Tree],
+ body}). % body :: Tree
+
+-record(c_seq, {anno=[], arg, % arg :: Tree,
+ body}). % body :: Tree
+
+-record(c_let, {anno=[], vars, % vars :: [Tree],
+ arg, % arg :: Tree,
+ body}). % body :: Tree
+
+-record(c_letrec, {anno=[], defs, % defs :: [#ce_def{}],
+ body}). % body :: Tree
+
+-record(c_def, {anno=[], name, % name :: Tree,
+ val}). % val :: Tree,
+
+-record(c_case, {anno=[], arg, % arg :: Tree,
+ clauses}). % clauses :: [Tree]
+
+-record(c_clause, {anno=[], pats, % pats :: [Tree],
+ guard, % guard :: Tree,
+ body}). % body :: Tree
+
+-record(c_alias, {anno=[], var, % var :: Tree,
+ pat}). % pat :: Tree
+
+-record(c_receive, {anno=[], clauses, % clauses :: [Tree],
+ timeout, % timeout :: Tree,
+ action}). % action :: Tree
+
+-record(c_apply, {anno=[], op, % op :: Tree,
+ args}). % args :: [Tree]
+
+-record(c_call, {anno=[], module, % module :: Tree,
+ name, % name :: Tree,
+ args}). % args :: [Tree]
+
+-record(c_primop, {anno=[], name, % name :: Tree,
+ args}). % args :: [Tree]
+
+-record(c_try, {anno=[], arg, % arg :: Tree,
+ vars, % vars :: [Tree],
+ body, % body :: Tree
+ evars, % evars :: [Tree],
+ handler}). % handler :: Tree
+
+-record(c_catch, {anno=[], body}). % body :: Tree
+
+-record(c_module, {anno=[], name, % name :: Tree,
+ exports, % exports :: [Tree],
+ attrs, % attrs :: [#ce_def{}],
+ defs}). % defs :: [#ce_def{}]
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_pp.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_pp.erl
new file mode 100644
index 0000000000..2bfbcb85e2
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_pp.erl
@@ -0,0 +1,430 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: core_pp.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
+%%
+%% Purpose : Core Erlang (naive) prettyprinter
+
+-module(core_pp).
+
+-export([format/1]).
+
+-include("core_parse.hrl").
+
+%% ====================================================================== %%
+%% format(Node) -> Text
+%% Node = coreErlang()
+%% Text = string() | [Text]
+%%
+%% Prettyprint-formats (naively) an abstract Core Erlang syntax
+%% tree.
+
+-record(ctxt, {class = term,
+ indent = 0,
+ item_indent = 2,
+ body_indent = 4,
+ tab_width = 8,
+ line = 0}).
+
+format(Node) -> case catch format(Node, #ctxt{}) of
+ {'EXIT',_} -> io_lib:format("~p",[Node]);
+ Other -> Other
+ end.
+
+maybe_anno(Node, Fun, Ctxt) ->
+ As = core_lib:get_anno(Node),
+ case get_line(As) of
+ none ->
+ maybe_anno(Node, Fun, Ctxt, As);
+ Line ->
+ if Line > Ctxt#ctxt.line ->
+ [io_lib:format("%% Line ~w",[Line]),
+ nl_indent(Ctxt),
+ maybe_anno(Node, Fun, Ctxt#ctxt{line = Line}, As)
+ ];
+ true ->
+ maybe_anno(Node, Fun, Ctxt, As)
+ end
+ end.
+
+maybe_anno(Node, Fun, Ctxt, As) ->
+ case strip_line(As) of
+ [] ->
+ Fun(Node, Ctxt);
+ List ->
+ Ctxt1 = add_indent(Ctxt, 2),
+ Ctxt2 = add_indent(Ctxt1, 3),
+ ["( ",
+ Fun(Node, Ctxt1),
+ nl_indent(Ctxt1),
+ "-| ",format_1(core_lib:make_literal(List), Ctxt2)," )"
+ ]
+ end.
+
+strip_line([A | As]) when integer(A) ->
+ strip_line(As);
+strip_line([A | As]) ->
+ [A | strip_line(As)];
+strip_line([]) ->
+ [].
+
+get_line([L | _As]) when integer(L) ->
+ L;
+get_line([_ | As]) ->
+ get_line(As);
+get_line([]) ->
+ none.
+
+format(Node, Ctxt) ->
+ maybe_anno(Node, fun format_1/2, Ctxt).
+
+format_1(#c_char{val=C}, _) -> io_lib:write_char(C);
+format_1(#c_int{val=I}, _) -> integer_to_list(I);
+format_1(#c_float{val=F}, _) -> float_to_list(F);
+format_1(#c_atom{val=A}, _) -> core_atom(A);
+format_1(#c_nil{}, _) -> "[]";
+format_1(#c_string{val=S}, _) -> io_lib:write_string(S);
+format_1(#c_var{name=V}, _) ->
+ %% Internal variable names may be:
+ %% - atoms representing proper Erlang variable names, or
+ %% any atoms that may be printed without single-quoting
+ %% - nonnegative integers.
+ %% It is important that when printing variables, no two names
+ %% should ever map to the same string.
+ if atom(V) ->
+ S = atom_to_list(V),
+ case S of
+ [C | _] when C >= $A, C =< $Z ->
+ %% Ordinary uppercase-prefixed names are
+ %% printed just as they are.
+ S;
+ [$_ | _] ->
+ %% Already "_"-prefixed names are prefixed
+ %% with "_X", e.g. '_foo' => '_X_foo', to
+ %% avoid generating things like "____foo" upon
+ %% repeated writing and reading of code.
+ %% ("_X_X_X_foo" is better.)
+ [$_, $X | S];
+ _ ->
+ %% Plain atoms are prefixed with a single "_".
+ %% E.g. foo => "_foo".
+ [$_ | S]
+ end;
+ integer(V) ->
+ %% Integers are also simply prefixed with "_".
+ [$_ | integer_to_list(V)]
+ end;
+format_1(#c_binary{segments=Segs}, Ctxt) ->
+ ["#{",
+ format_vseq(Segs, "", ",", add_indent(Ctxt, 2),
+ fun format_bitstr/2),
+ "}#"
+ ];
+format_1(#c_tuple{es=Es}, Ctxt) ->
+ [${,
+ format_hseq(Es, ",", add_indent(Ctxt, 1), fun format/2),
+ $}
+ ];
+format_1(#c_cons{hd=H,tl=T}, Ctxt) ->
+ Txt = ["["|format(H, add_indent(Ctxt, 1))],
+ [Txt|format_list_tail(T, add_indent(Ctxt, width(Txt, Ctxt)))];
+format_1(#c_values{es=Es}, Ctxt) ->
+ format_values(Es, Ctxt);
+format_1(#c_alias{var=V,pat=P}, Ctxt) ->
+ Txt = [format(V, Ctxt)|" = "],
+ [Txt|format(P, add_indent(Ctxt, width(Txt, Ctxt)))];
+format_1(#c_let{vars=Vs,arg=A,body=B}, Ctxt) ->
+ Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.body_indent),
+ ["let ",
+ format_values(Vs, add_indent(Ctxt, 4)),
+ " =",
+ nl_indent(Ctxt1),
+ format(A, Ctxt1),
+ nl_indent(Ctxt),
+ "in "
+ | format(B, add_indent(Ctxt, 4))
+ ];
+format_1(#c_letrec{defs=Fs,body=B}, Ctxt) ->
+ Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.body_indent),
+ ["letrec",
+ nl_indent(Ctxt1),
+ format_funcs(Fs, Ctxt1),
+ nl_indent(Ctxt),
+ "in "
+ | format(B, add_indent(Ctxt, 4))
+ ];
+format_1(#c_seq{arg=A,body=B}, Ctxt) ->
+ Ctxt1 = add_indent(Ctxt, 4),
+ ["do ",
+ format(A, Ctxt1),
+ nl_indent(Ctxt1)
+ | format(B, Ctxt1)
+ ];
+format_1(#c_case{arg=A,clauses=Cs}, Ctxt) ->
+ Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.item_indent),
+ ["case ",
+ format(A, add_indent(Ctxt, 5)),
+ " of",
+ nl_indent(Ctxt1),
+ format_clauses(Cs, Ctxt1),
+ nl_indent(Ctxt)
+ | "end"
+ ];
+format_1(#c_receive{clauses=Cs,timeout=T,action=A}, Ctxt) ->
+ Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.item_indent),
+ ["receive",
+ nl_indent(Ctxt1),
+ format_clauses(Cs, Ctxt1),
+ nl_indent(Ctxt),
+ "after ",
+ format(T, add_indent(Ctxt, 6)),
+ " ->",
+ nl_indent(Ctxt1),
+ format(A, Ctxt1)
+ ];
+format_1(#c_fname{id=I,arity=A}, _) ->
+ [core_atom(I),$/,integer_to_list(A)];
+format_1(#c_fun{vars=Vs,body=B}, Ctxt) ->
+ Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.body_indent),
+ ["fun (",
+ format_hseq(Vs, ",", add_indent(Ctxt, 5), fun format/2),
+ ") ->",
+ nl_indent(Ctxt1)
+ | format(B, Ctxt1)
+ ];
+format_1(#c_apply{op=O,args=As}, Ctxt0) ->
+ Ctxt1 = add_indent(Ctxt0, 6), %"apply "
+ Op = format(O, Ctxt1),
+ Ctxt2 = add_indent(Ctxt0, 4),
+ ["apply ",Op,
+ nl_indent(Ctxt2),
+ $(,format_hseq(As, ", ", add_indent(Ctxt2, 1), fun format/2),$)
+ ];
+format_1(#c_call{module=M,name=N,args=As}, Ctxt0) ->
+ Ctxt1 = add_indent(Ctxt0, 5), %"call "
+ Mod = format(M, Ctxt1),
+ Ctxt2 = add_indent(Ctxt1, width(Mod, Ctxt1)+1),
+ Name = format(N, Ctxt2),
+ Ctxt3 = add_indent(Ctxt0, 4),
+ ["call ",Mod,":",Name,
+ nl_indent(Ctxt3),
+ $(,format_hseq(As, ", ", add_indent(Ctxt3, 1), fun format/2),$)
+ ];
+format_1(#c_primop{name=N,args=As}, Ctxt0) ->
+ Ctxt1 = add_indent(Ctxt0, 7), %"primop "
+ Name = format(N, Ctxt1),
+ Ctxt2 = add_indent(Ctxt0, 4),
+ ["primop ",Name,
+ nl_indent(Ctxt2),
+ $(,format_hseq(As, ", ", add_indent(Ctxt2, 1), fun format/2),$)
+ ];
+format_1(#c_catch{body=B}, Ctxt) ->
+ Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.body_indent),
+ ["catch",
+ nl_indent(Ctxt1),
+ format(B, Ctxt1)
+ ];
+format_1(#c_try{arg=E,vars=Vs,body=B,evars=Evs,handler=H}, Ctxt) ->
+ Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.body_indent),
+ ["try",
+ nl_indent(Ctxt1),
+ format(E, Ctxt1),
+ nl_indent(Ctxt),
+ "of ",
+ format_values(Vs, add_indent(Ctxt, 3)),
+ " ->",
+ nl_indent(Ctxt1),
+ format(B, Ctxt1),
+ nl_indent(Ctxt),
+ "catch ",
+ format_values(Evs, add_indent(Ctxt, 6)),
+ " ->",
+ nl_indent(Ctxt1)
+ | format(H, Ctxt1)
+ ];
+format_1(#c_def{name=N,val=V}, Ctxt) ->
+ Ctxt1 = add_indent(set_class(Ctxt, expr), Ctxt#ctxt.body_indent),
+ [format(N, Ctxt),
+ " =",
+ nl_indent(Ctxt1)
+ | format(V, Ctxt1)
+ ];
+format_1(#c_module{name=N,exports=Es,attrs=As,defs=Ds}, Ctxt) ->
+ Mod = ["module ", format(N, Ctxt)],
+ [Mod," [",
+ format_vseq(Es,
+ "", ",",
+ add_indent(set_class(Ctxt, term), width(Mod, Ctxt)+2),
+ fun format/2),
+ "]",
+ nl_indent(Ctxt),
+ " attributes [",
+ format_vseq(As,
+ "", ",",
+ add_indent(set_class(Ctxt, def), 16),
+ fun format/2),
+ "]",
+ nl_indent(Ctxt),
+ format_funcs(Ds, Ctxt),
+ nl_indent(Ctxt)
+ | "end"
+ ];
+format_1(Type, _) ->
+ ["** Unsupported type: ",
+ io_lib:write(Type)
+ | " **"
+ ].
+
+format_funcs(Fs, Ctxt) ->
+ format_vseq(Fs,
+ "", "",
+ set_class(Ctxt, def),
+ fun format/2).
+
+format_values(Vs, Ctxt) ->
+ [$<,
+ format_hseq(Vs, ",", add_indent(Ctxt, 1), fun format/2),
+ $>].
+
+format_bitstr(#c_bitstr{val=V,size=S,unit=U,type=T,flags=Fs}, Ctxt0) ->
+ Vs = [S, U, T, Fs],
+ Ctxt1 = add_indent(Ctxt0, 2),
+ Val = format(V, Ctxt1),
+ Ctxt2 = add_indent(Ctxt1, width(Val, Ctxt1) + 2),
+ ["#<", Val, ">(", format_hseq(Vs,",", Ctxt2, fun format/2), $)].
+
+format_clauses(Cs, Ctxt) ->
+ format_vseq(Cs, "", "", set_class(Ctxt, clause),
+ fun format_clause/2).
+
+format_clause(Node, Ctxt) ->
+ maybe_anno(Node, fun format_clause_1/2, Ctxt).
+
+format_clause_1(#c_clause{pats=Ps,guard=G,body=B}, Ctxt) ->
+ Ptxt = format_values(Ps, Ctxt),
+ Ctxt2 = add_indent(Ctxt, Ctxt#ctxt.body_indent),
+ [Ptxt,
+ " when ",
+ format_guard(G, add_indent(set_class(Ctxt, expr),
+ width(Ptxt, Ctxt) + 6)),
+ " ->",
+ nl_indent(Ctxt2)
+ | format(B, set_class(Ctxt2, expr))
+ ].
+
+format_guard(Node, Ctxt) ->
+ maybe_anno(Node, fun format_guard_1/2, Ctxt).
+
+format_guard_1(#c_call{module=M,name=N,args=As}, Ctxt0) ->
+ Ctxt1 = add_indent(Ctxt0, 5), %"call "
+ Mod = format(M, Ctxt1),
+ Ctxt2 = add_indent(Ctxt1, width(Mod, Ctxt1)+1),
+ Name = format(N, Ctxt2),
+ Ctxt3 = add_indent(Ctxt0, 4),
+ ["call ",Mod,":",Name,
+ nl_indent(Ctxt3),
+ $(,format_vseq(As, "",",", add_indent(Ctxt3, 1), fun format_guard/2),$)
+ ];
+format_guard_1(E, Ctxt) -> format_1(E, Ctxt). %Anno already done
+
+%% format_hseq([Thing], Separator, Context, Fun) -> Txt.
+%% Format a sequence horizontally on the same line with Separator between.
+
+format_hseq([H], _, Ctxt, Fun) ->
+ Fun(H, Ctxt);
+format_hseq([H|T], Sep, Ctxt, Fun) ->
+ Txt = [Fun(H, Ctxt)|Sep],
+ Ctxt1 = add_indent(Ctxt, width(Txt, Ctxt)),
+ [Txt|format_hseq(T, Sep, Ctxt1, Fun)];
+format_hseq([], _, _, _) -> "".
+
+%% format_vseq([Thing], LinePrefix, LineSuffix, Context, Fun) -> Txt.
+%% Format a sequence vertically in indented lines adding LinePrefix
+%% to the beginning of each line and LineSuffix to the end of each
+%% line. No prefix on the first line or suffix on the last line.
+
+format_vseq([H], _Pre, _Suf, Ctxt, Fun) ->
+ Fun(H, Ctxt);
+format_vseq([H|T], Pre, Suf, Ctxt, Fun) ->
+ [Fun(H, Ctxt),Suf,nl_indent(Ctxt),Pre|
+ format_vseq(T, Pre, Suf, Ctxt, Fun)];
+format_vseq([], _, _, _, _) -> "".
+
+format_list_tail(#c_nil{anno=[]}, _) -> "]";
+format_list_tail(#c_cons{anno=[],hd=H,tl=T}, Ctxt) ->
+ Txt = [$,|format(H, Ctxt)],
+ Ctxt1 = add_indent(Ctxt, width(Txt, Ctxt)),
+ [Txt|format_list_tail(T, Ctxt1)];
+format_list_tail(Tail, Ctxt) ->
+ ["|",format(Tail, add_indent(Ctxt, 1)),"]"].
+
+indent(Ctxt) -> indent(Ctxt#ctxt.indent, Ctxt).
+
+indent(N, _) when N =< 0 -> "";
+indent(N, Ctxt) ->
+ T = Ctxt#ctxt.tab_width,
+ string:chars($\t, N div T, string:chars($\s, N rem T)).
+
+nl_indent(Ctxt) -> [$\n|indent(Ctxt)].
+
+
+unindent(T, Ctxt) ->
+ unindent(T, Ctxt#ctxt.indent, Ctxt, []).
+
+unindent(T, N, _, C) when N =< 0 ->
+ [T|C];
+unindent([$\s|T], N, Ctxt, C) ->
+ unindent(T, N - 1, Ctxt, C);
+unindent([$\t|T], N, Ctxt, C) ->
+ Tab = Ctxt#ctxt.tab_width,
+ if N >= Tab ->
+ unindent(T, N - Tab, Ctxt, C);
+ true ->
+ unindent([string:chars($\s, Tab - N)|T], 0, Ctxt, C)
+ end;
+unindent([L|T], N, Ctxt, C) when list(L) ->
+ unindent(L, N, Ctxt, [T|C]);
+unindent([H|T], _, _, C) ->
+ [H|[T|C]];
+unindent([], N, Ctxt, [H|T]) ->
+ unindent(H, N, Ctxt, T);
+unindent([], _, _, []) -> [].
+
+
+width(Txt, Ctxt) ->
+ case catch width(Txt, 0, Ctxt, []) of
+ {'EXIT',_} -> exit({bad_text,Txt});
+ Other -> Other
+ end.
+
+width([$\t|T], A, Ctxt, C) ->
+ width(T, A + Ctxt#ctxt.tab_width, Ctxt, C);
+width([$\n|T], _, Ctxt, C) ->
+ width(unindent([T|C], Ctxt), Ctxt);
+width([H|T], A, Ctxt, C) when list(H) ->
+ width(H, A, Ctxt, [T|C]);
+width([_|T], A, Ctxt, C) ->
+ width(T, A + 1, Ctxt, C);
+width([], A, Ctxt, [H|T]) ->
+ width(H, A, Ctxt, T);
+width([], A, _, []) -> A.
+
+add_indent(Ctxt, Dx) ->
+ Ctxt#ctxt{indent = Ctxt#ctxt.indent + Dx}.
+
+set_class(Ctxt, Class) ->
+ Ctxt#ctxt{class = Class}.
+
+core_atom(A) -> io_lib:write_string(atom_to_list(A), $').
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_scan.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_scan.erl
new file mode 100644
index 0000000000..a97270b9f3
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_scan.erl
@@ -0,0 +1,495 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: core_scan.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
+%%
+%% Purpose: Scanner for Core Erlang.
+
+%% For handling ISO 8859-1 (Latin-1) we use the following type
+%% information:
+%%
+%% 000 - 037 NUL - US control
+%% 040 - 057 SPC - / punctuation
+%% 060 - 071 0 - 9 digit
+%% 072 - 100 : - @ punctuation
+%% 101 - 132 A - Z uppercase
+%% 133 - 140 [ - ` punctuation
+%% 141 - 172 a - z lowercase
+%% 173 - 176 { - ~ punctuation
+%% 177 DEL control
+%% 200 - 237 control
+%% 240 - 277 NBSP - � punctuation
+%% 300 - 326 � - � uppercase
+%% 327 � punctuation
+%% 330 - 336 � - � uppercase
+%% 337 - 366 � - � lowercase
+%% 367 � punctuation
+%% 370 - 377 � - � lowercase
+%%
+%% Many punctuation characters region have special meaning. Must
+%% watch using � \327, bvery close to x \170
+
+-module(core_scan).
+
+-export([string/1,string/2,tokens/3,format_error/1]).
+
+-import(lists, [reverse/1]).
+
+%% tokens(Continuation, CharList, StartPos) ->
+%% {done, {ok, [Tok], EndPos}, Rest} |
+%% {done, {error,{ErrorPos,core_scan,What}, EndPos}, Rest} |
+%% {more, Continuation'}
+%% This is the main function into the re-entrant scanner. It calls the
+%% re-entrant pre-scanner until this says done, then calls scan/1 on
+%% the result.
+%%
+%% The continuation has the form:
+%% {RestChars,CharsSoFar,CurrentPos,StartPos}
+
+tokens([], Chars, Pos) -> %First call
+ tokens({[],[],Pos,Pos}, Chars, Pos);
+tokens({Chars,SoFar0,Cp,Sp}, MoreChars, _) ->
+ In = Chars ++ MoreChars,
+ case pre_scan(In, SoFar0, Cp) of
+ {done,_,[],Ep} -> %Found nothing
+ {done,{eof,Ep},[]};
+ {done,_,SoFar1,Ep} -> %Got complete tokens
+ Res = case scan(reverse(SoFar1), Sp) of
+ {ok,Toks} -> {ok,Toks,Ep};
+ {error,E} -> {error,E,Ep}
+ end,
+ {done,Res,[]};
+ {more,Rest,SoFar1,Cp1} -> %Missing end token
+ {more,{Rest,SoFar1,Cp1,Sp}};
+ Other -> %An error has occurred
+ {done,Other,[]}
+ end.
+
+%% string([Char]) ->
+%% string([Char], StartPos) ->
+%% {ok, [Tok], EndPos} |
+%% {error,{Pos,core_scan,What}, EndPos}
+
+string(Cs) -> string(Cs, 1).
+
+string(Cs, Sp) ->
+ %% Add an 'eof' to always get correct handling.
+ case string_pre_scan(Cs, [], Sp) of
+ {done,_,SoFar,Ep} -> %Got tokens
+ case scan(reverse(SoFar), Sp) of
+ {ok,Toks} -> {ok,Toks,Ep};
+ {error,E} -> {error,E,Ep}
+ end;
+ Other -> Other %An error has occurred
+ end.
+
+%% string_pre_scan(Cs, SoFar0, StartPos) ->
+%% {done,Rest,SoFar,EndPos} | {error,E,EndPos}.
+
+string_pre_scan(Cs, SoFar0, Sp) ->
+ case pre_scan(Cs, SoFar0, Sp) of
+ {done,Rest,SoFar1,Ep} -> %Got complete tokens
+ {done,Rest,SoFar1,Ep};
+ {more,Rest,SoFar1,Ep} -> %Missing end token
+ string_pre_scan(Rest ++ eof, SoFar1, Ep);
+ Other -> Other %An error has occurred
+ end.
+
+%% format_error(Error)
+%% Return a string describing the error.
+
+format_error({string,Quote,Head}) ->
+ ["unterminated " ++ string_thing(Quote) ++
+ " starting with " ++ io_lib:write_string(Head,Quote)];
+format_error({illegal,Type}) -> io_lib:fwrite("illegal ~w", [Type]);
+format_error(char) -> "unterminated character";
+format_error(scan) -> "premature end";
+format_error({base,Base}) -> io_lib:fwrite("illegal base '~w'", [Base]);
+format_error(float) -> "bad float";
+format_error(Other) -> io_lib:write(Other).
+
+string_thing($') -> "atom";
+string_thing($") -> "string".
+
+%% Re-entrant pre-scanner.
+%%
+%% If the input list of characters is insufficient to build a term the
+%% scanner returns a request for more characters and a continuation to be
+%% used when trying to build a term with more characters. To indicate
+%% end-of-file the input character list should be replaced with 'eof'
+%% as an empty list has meaning.
+%%
+%% When more characters are need inside a comment, string or quoted
+%% atom, which can become rather long, instead of pushing the
+%% characters read so far back onto RestChars to be reread, a special
+%% reentry token is returned indicating the middle of a construct.
+%% The token is the start character as an atom, '%', '"' and '\''.
+
+%% pre_scan([Char], SoFar, StartPos) ->
+%% {done,RestChars,ScannedChars,NewPos} |
+%% {more,RestChars,ScannedChars,NewPos} |
+%% {error,{ErrorPos,core_scan,Description},NewPos}.
+%% Main pre-scan function. It has been split into 2 functions because of
+%% efficiency, with a good indexing compiler it would be unnecessary.
+
+pre_scan([C|Cs], SoFar, Pos) ->
+ pre_scan(C, Cs, SoFar, Pos);
+pre_scan([], SoFar, Pos) ->
+ {more,[],SoFar,Pos};
+pre_scan(eof, SoFar, Pos) ->
+ {done,eof,SoFar,Pos}.
+
+%% pre_scan(Char, [Char], SoFar, Pos)
+
+pre_scan($$, Cs0, SoFar0, Pos) ->
+ case pre_char(Cs0, [$$|SoFar0]) of
+ {Cs,SoFar} ->
+ pre_scan(Cs, SoFar, Pos);
+ more ->
+ {more,[$$|Cs0],SoFar0, Pos};
+ error ->
+ pre_error(char, Pos, Pos)
+ end;
+pre_scan($', Cs, SoFar, Pos) ->
+ pre_string(Cs, $', '\'', Pos, [$'|SoFar], Pos);
+pre_scan({'\'',Sp}, Cs, SoFar, Pos) -> %Re-entering quoted atom
+ pre_string(Cs, $', '\'', Sp, SoFar, Pos);
+pre_scan($", Cs, SoFar, Pos) ->
+ pre_string(Cs, $", '"', Pos, [$"|SoFar], Pos);
+pre_scan({'"',Sp}, Cs, SoFar, Pos) -> %Re-entering string
+ pre_string(Cs, $", '"', Sp, SoFar, Pos);
+pre_scan($%, Cs, SoFar, Pos) ->
+ pre_comment(Cs, SoFar, Pos);
+pre_scan('%', Cs, SoFar, Pos) -> %Re-entering comment
+ pre_comment(Cs, SoFar, Pos);
+pre_scan($\n, Cs, SoFar, Pos) ->
+ pre_scan(Cs, [$\n|SoFar], Pos+1);
+pre_scan(C, Cs, SoFar, Pos) ->
+ pre_scan(Cs, [C|SoFar], Pos).
+
+%% pre_string([Char], Quote, Reent, StartPos, SoFar, Pos)
+
+pre_string([Q|Cs], Q, _, _, SoFar, Pos) ->
+ pre_scan(Cs, [Q|SoFar], Pos);
+pre_string([$\n|Cs], Q, Reent, Sp, SoFar, Pos) ->
+ pre_string(Cs, Q, Reent, Sp, [$\n|SoFar], Pos+1);
+pre_string([$\\|Cs0], Q, Reent, Sp, SoFar0, Pos) ->
+ case pre_escape(Cs0, SoFar0) of
+ {Cs,SoFar} ->
+ pre_string(Cs, Q, Reent, Sp, SoFar, Pos);
+ more ->
+ {more,[{Reent,Sp},$\\|Cs0],SoFar0,Pos};
+ error ->
+ pre_string_error(Q, Sp, SoFar0, Pos)
+ end;
+pre_string([C|Cs], Q, Reent, Sp, SoFar, Pos) ->
+ pre_string(Cs, Q, Reent, Sp, [C|SoFar], Pos);
+pre_string([], _, Reent, Sp, SoFar, Pos) ->
+ {more,[{Reent,Sp}],SoFar,Pos};
+pre_string(eof, Q, _, Sp, SoFar, Pos) ->
+ pre_string_error(Q, Sp, SoFar, Pos).
+
+pre_string_error(Q, Sp, SoFar, Pos) ->
+ S = reverse(string:substr(SoFar, 1, string:chr(SoFar, Q)-1)),
+ pre_error({string,Q,string:substr(S, 1, 16)}, Sp, Pos).
+
+pre_char([C|Cs], SoFar) -> pre_char(C, Cs, SoFar);
+pre_char([], _) -> more;
+pre_char(eof, _) -> error.
+
+pre_char($\\, Cs, SoFar) ->
+ pre_escape(Cs, SoFar);
+pre_char(C, Cs, SoFar) ->
+ {Cs,[C|SoFar]}.
+
+pre_escape([$^|Cs0], SoFar) ->
+ case Cs0 of
+ [C3|Cs] ->
+ {Cs,[C3,$^,$\\|SoFar]};
+ [] -> more;
+ eof -> error
+ end;
+pre_escape([C|Cs], SoFar) ->
+ {Cs,[C,$\\|SoFar]};
+pre_escape([], _) -> more;
+pre_escape(eof, _) -> error.
+
+%% pre_comment([Char], SoFar, Pos)
+%% Comments are replaced by one SPACE.
+
+pre_comment([$\n|Cs], SoFar, Pos) ->
+ pre_scan(Cs, [$\n,$\s|SoFar], Pos+1); %Terminate comment
+pre_comment([_|Cs], SoFar, Pos) ->
+ pre_comment(Cs, SoFar, Pos);
+pre_comment([], SoFar, Pos) ->
+ {more,['%'],SoFar,Pos};
+pre_comment(eof, Sofar, Pos) ->
+ pre_scan(eof, [$\s|Sofar], Pos).
+
+pre_error(E, Epos, Pos) ->
+ {error,{Epos,core_scan,E}, Pos}.
+
+%% scan(CharList, StartPos)
+%% This takes a list of characters and tries to tokenise them.
+%%
+%% The token list is built in reverse order (in a stack) to save appending
+%% and then reversed when all the tokens have been collected. Most tokens
+%% are built in the same way.
+%%
+%% Returns:
+%% {ok,[Tok]}
+%% {error,{ErrorPos,core_scan,What}}
+
+scan(Cs, Pos) ->
+ scan1(Cs, [], Pos).
+
+%% scan1(Characters, TokenStack, Position)
+%% Scan a list of characters into tokens.
+
+scan1([$\n|Cs], Toks, Pos) -> %Skip newline
+ scan1(Cs, Toks, Pos+1);
+scan1([C|Cs], Toks, Pos) when C >= $\000, C =< $\s -> %Skip control chars
+ scan1(Cs, Toks, Pos);
+scan1([C|Cs], Toks, Pos) when C >= $\200, C =< $\240 ->
+ scan1(Cs, Toks, Pos);
+scan1([C|Cs], Toks, Pos) when C >= $a, C =< $z -> %Keywords
+ scan_key_word(C, Cs, Toks, Pos);
+scan1([C|Cs], Toks, Pos) when C >= $�, C =< $�, C /= $� ->
+ scan_key_word(C, Cs, Toks, Pos);
+scan1([C|Cs], Toks, Pos) when C >= $A, C =< $Z -> %Variables
+ scan_variable(C, Cs, Toks, Pos);
+scan1([C|Cs], Toks, Pos) when C >= $�, C =< $�, C /= $� ->
+ scan_variable(C, Cs, Toks, Pos);
+scan1([C|Cs], Toks, Pos) when C >= $0, C =< $9 -> %Numbers
+ scan_number(C, Cs, Toks, Pos);
+scan1([$-,C|Cs], Toks, Pos) when C >= $0, C =< $9 -> %Signed numbers
+ scan_signed_number($-, C, Cs, Toks, Pos);
+scan1([$+,C|Cs], Toks, Pos) when C >= $0, C =< $9 -> %Signed numbers
+ scan_signed_number($+, C, Cs, Toks, Pos);
+scan1([$_|Cs], Toks, Pos) -> %_ variables
+ scan_variable($_, Cs, Toks, Pos);
+scan1([$$|Cs0], Toks, Pos) -> %Character constant
+ {C,Cs,Pos1} = scan_char(Cs0, Pos),
+ scan1(Cs, [{char,Pos,C}|Toks], Pos1);
+scan1([$'|Cs0], Toks, Pos) -> %Atom (always quoted)
+ {S,Cs1,Pos1} = scan_string(Cs0, $', Pos),
+ case catch list_to_atom(S) of
+ A when atom(A) ->
+ scan1(Cs1, [{atom,Pos,A}|Toks], Pos1);
+ _Error -> scan_error({illegal,atom}, Pos)
+ end;
+scan1([$"|Cs0], Toks, Pos) -> %String
+ {S,Cs1,Pos1} = scan_string(Cs0, $", Pos),
+ scan1(Cs1, [{string,Pos,S}|Toks], Pos1);
+%% Punctuation characters and operators, first recognise multiples.
+scan1("->" ++ Cs, Toks, Pos) ->
+ scan1(Cs, [{'->',Pos}|Toks], Pos);
+scan1("-|" ++ Cs, Toks, Pos) ->
+ scan1(Cs, [{'-|',Pos}|Toks], Pos);
+scan1([C|Cs], Toks, Pos) -> %Punctuation character
+ P = list_to_atom([C]),
+ scan1(Cs, [{P,Pos}|Toks], Pos);
+scan1([], Toks0, _) ->
+ Toks = reverse(Toks0),
+ {ok,Toks}.
+
+%% scan_key_word(FirstChar, CharList, Tokens, Pos)
+%% scan_variable(FirstChar, CharList, Tokens, Pos)
+
+scan_key_word(C, Cs0, Toks, Pos) ->
+ {Wcs,Cs} = scan_name(Cs0, []),
+ case catch list_to_atom([C|reverse(Wcs)]) of
+ Name when atom(Name) ->
+ scan1(Cs, [{Name,Pos}|Toks], Pos);
+ _Error -> scan_error({illegal,atom}, Pos)
+ end.
+
+scan_variable(C, Cs0, Toks, Pos) ->
+ {Wcs,Cs} = scan_name(Cs0, []),
+ case catch list_to_atom([C|reverse(Wcs)]) of
+ Name when atom(Name) ->
+ scan1(Cs, [{var,Pos,Name}|Toks], Pos);
+ _Error -> scan_error({illegal,var}, Pos)
+ end.
+
+%% scan_name(Cs) -> lists:splitwith(fun (C) -> name_char(C) end, Cs).
+
+scan_name([C|Cs], Ncs) ->
+ case name_char(C) of
+ true -> scan_name(Cs, [C|Ncs]);
+ false -> {Ncs,[C|Cs]} %Must rebuild here, sigh!
+ end;
+scan_name([], Ncs) ->
+ {Ncs,[]}.
+
+name_char(C) when C >= $a, C =< $z -> true;
+name_char(C) when C >= $�, C =< $�, C /= $� -> true;
+name_char(C) when C >= $A, C =< $Z -> true;
+name_char(C) when C >= $�, C =< $�, C /= $� -> true;
+name_char(C) when C >= $0, C =< $9 -> true;
+name_char($_) -> true;
+name_char($@) -> true;
+name_char(_) -> false.
+
+%% scan_string(CharList, QuoteChar, Pos) -> {StringChars,RestChars,NewPos}.
+
+scan_string(Cs, Q, Pos) ->
+ scan_string(Cs, [], Q, Pos).
+
+scan_string([Q|Cs], Scs, Q, Pos) ->
+ {reverse(Scs),Cs,Pos};
+scan_string([$\n|Cs], Scs, Q, Pos) ->
+ scan_string(Cs, [$\n|Scs], Q, Pos+1);
+scan_string([$\\|Cs0], Scs, Q, Pos) ->
+ {C,Cs,Pos1} = scan_escape(Cs0, Pos),
+ scan_string(Cs, [C|Scs], Q, Pos1);
+scan_string([C|Cs], Scs, Q, Pos) ->
+ scan_string(Cs, [C|Scs], Q, Pos).
+
+%% scan_char(Chars, Pos) -> {Char,RestChars,NewPos}.
+%% Read a single character from a character constant. The pre-scan
+%% phase has checked for errors here.
+
+scan_char([$\\|Cs], Pos) ->
+ scan_escape(Cs, Pos);
+scan_char([$\n|Cs], Pos) -> %Newline
+ {$\n,Cs,Pos+1};
+scan_char([C|Cs], Pos) ->
+ {C,Cs,Pos}.
+
+scan_escape([O1,O2,O3|Cs], Pos) when %\<1-3> octal digits
+ O1 >= $0, O1 =< $7, O2 >= $0, O2 =< $7, O3 >= $0, O3 =< $7 ->
+ Val = (O1*8 + O2)*8 + O3 - 73*$0,
+ {Val,Cs,Pos};
+scan_escape([O1,O2|Cs], Pos) when
+ O1 >= $0, O1 =< $7, O2 >= $0, O2 =< $7 ->
+ Val = (O1*8 + O2) - 9*$0,
+ {Val,Cs,Pos};
+scan_escape([O1|Cs], Pos) when
+ O1 >= $0, O1 =< $7 ->
+ {O1 - $0,Cs,Pos};
+scan_escape([$^,C|Cs], Pos) -> %\^X -> CTL-X
+ Val = C band 31,
+ {Val,Cs,Pos};
+%scan_escape([$\n,C1|Cs],Pos) ->
+% {C1,Cs,Pos+1};
+%scan_escape([C,C1|Cs],Pos) when C >= $\000, C =< $\s ->
+% {C1,Cs,Pos};
+scan_escape([$\n|Cs],Pos) ->
+ {$\n,Cs,Pos+1};
+scan_escape([C0|Cs],Pos) ->
+ C = escape_char(C0),
+ {C,Cs,Pos}.
+
+escape_char($n) -> $\n; %\n = LF
+escape_char($r) -> $\r; %\r = CR
+escape_char($t) -> $\t; %\t = TAB
+escape_char($v) -> $\v; %\v = VT
+escape_char($b) -> $\b; %\b = BS
+escape_char($f) -> $\f; %\f = FF
+escape_char($e) -> $\e; %\e = ESC
+escape_char($s) -> $\s; %\s = SPC
+escape_char($d) -> $\d; %\d = DEL
+escape_char(C) -> C.
+
+%% scan_number(Char, CharList, TokenStack, Pos)
+%% We can handle simple radix notation:
+%% <digit>#<digits> - the digits read in that base
+%% <digits> - the digits in base 10
+%% <digits>.<digits>
+%% <digits>.<digits>E+-<digits>
+%%
+%% Except for explicitly based integers we build a list of all the
+%% characters and then use list_to_integer/1 or list_to_float/1 to
+%% generate the value.
+
+%% SPos == Start position
+%% CPos == Current position
+
+scan_number(C, Cs0, Toks, Pos) ->
+ {Ncs,Cs,Pos1} = scan_integer(Cs0, [C], Pos),
+ scan_after_int(Cs, Ncs, Toks, Pos, Pos1).
+
+scan_signed_number(S, C, Cs0, Toks, Pos) ->
+ {Ncs,Cs,Pos1} = scan_integer(Cs0, [C,S], Pos),
+ scan_after_int(Cs, Ncs, Toks, Pos, Pos1).
+
+scan_integer([C|Cs], Stack, Pos) when C >= $0, C =< $9 ->
+ scan_integer(Cs, [C|Stack], Pos);
+scan_integer(Cs, Stack, Pos) ->
+ {Stack,Cs,Pos}.
+
+scan_after_int([$.,C|Cs0], Ncs0, Toks, SPos, CPos) when C >= $0, C =< $9 ->
+ {Ncs,Cs,CPos1} = scan_integer(Cs0, [C,$.|Ncs0], CPos),
+ scan_after_fraction(Cs, Ncs, Toks, SPos, CPos1);
+scan_after_int([$#|Cs], Ncs, Toks, SPos, CPos) ->
+ case list_to_integer(reverse(Ncs)) of
+ Base when Base >= 2, Base =< 16 ->
+ scan_based_int(Cs, 0, Base, Toks, SPos, CPos);
+ Base ->
+ scan_error({base,Base}, CPos)
+ end;
+scan_after_int(Cs, Ncs, Toks, SPos, CPos) ->
+ N = list_to_integer(reverse(Ncs)),
+ scan1(Cs, [{integer,SPos,N}|Toks], CPos).
+
+scan_based_int([C|Cs], SoFar, Base, Toks, SPos, CPos) when
+ C >= $0, C =< $9, C < Base + $0 ->
+ Next = SoFar * Base + (C - $0),
+ scan_based_int(Cs, Next, Base, Toks, SPos, CPos);
+scan_based_int([C|Cs], SoFar, Base, Toks, SPos, CPos) when
+ C >= $a, C =< $f, C < Base + $a - 10 ->
+ Next = SoFar * Base + (C - $a + 10),
+ scan_based_int(Cs, Next, Base, Toks, SPos, CPos);
+scan_based_int([C|Cs], SoFar, Base, Toks, SPos, CPos) when
+ C >= $A, C =< $F, C < Base + $A - 10 ->
+ Next = SoFar * Base + (C - $A + 10),
+ scan_based_int(Cs, Next, Base, Toks, SPos, CPos);
+scan_based_int(Cs, SoFar, _, Toks, SPos, CPos) ->
+ scan1(Cs, [{integer,SPos,SoFar}|Toks], CPos).
+
+scan_after_fraction([$E|Cs], Ncs, Toks, SPos, CPos) ->
+ scan_exponent(Cs, [$E|Ncs], Toks, SPos, CPos);
+scan_after_fraction([$e|Cs], Ncs, Toks, SPos, CPos) ->
+ scan_exponent(Cs, [$E|Ncs], Toks, SPos, CPos);
+scan_after_fraction(Cs, Ncs, Toks, SPos, CPos) ->
+ case catch list_to_float(reverse(Ncs)) of
+ N when float(N) ->
+ scan1(Cs, [{float,SPos,N}|Toks], CPos);
+ _Error -> scan_error({illegal,float}, SPos)
+ end.
+
+%% scan_exponent(CharList, NumberCharStack, TokenStack, StartPos, CurPos)
+%% Generate an error here if E{+|-} not followed by any digits.
+
+scan_exponent([$+|Cs], Ncs, Toks, SPos, CPos) ->
+ scan_exponent1(Cs, [$+|Ncs], Toks, SPos, CPos);
+scan_exponent([$-|Cs], Ncs, Toks, SPos, CPos) ->
+ scan_exponent1(Cs, [$-|Ncs], Toks, SPos, CPos);
+scan_exponent(Cs, Ncs, Toks, SPos, CPos) ->
+ scan_exponent1(Cs, Ncs, Toks, SPos, CPos).
+
+scan_exponent1([C|Cs0], Ncs0, Toks, SPos, CPos) when C >= $0, C =< $9 ->
+ {Ncs,Cs,CPos1} = scan_integer(Cs0, [C|Ncs0], CPos),
+ case catch list_to_float(reverse(Ncs)) of
+ N when float(N) ->
+ scan1(Cs, [{float,SPos,N}|Toks], CPos1);
+ _Error -> scan_error({illegal,float}, SPos)
+ end;
+scan_exponent1(_, _, _, _, CPos) ->
+ scan_error(float, CPos).
+
+scan_error(In, Pos) ->
+ {error,{Pos,core_scan,In}}.
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/erl_bifs.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/erl_bifs.erl
new file mode 100644
index 0000000000..1dbeefb5ac
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/erl_bifs.erl
@@ -0,0 +1,486 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: erl_bifs.erl,v 1.2 2009/09/17 09:46:19 kostis Exp $
+%%
+%% Purpose: Information about the Erlang built-in functions.
+
+-module(erl_bifs).
+
+-export([is_bif/3, is_guard_bif/3, is_pure/3, is_safe/3]).
+
+
+%% =====================================================================
+%% is_bif(Module, Name, Arity) -> boolean()
+%%
+%% Module = Name = atom()
+%% Arity = integer()
+%%
+%% Returns `true' if the function `Module:Name/Arity' is a Built-In
+%% Function (BIF) of Erlang. BIFs "come with the implementation",
+%% and can be assumed to exist and have the same behaviour in any
+%% later versions of the same implementation of the language. Being
+%% a BIF does *not* imply that the function belongs to the module
+%% `erlang', nor that it is implemented in C or assembler (cf.
+%% `erlang:is_builtin/3'), or that it is auto-imported by the
+%% compiler (cf. `erl_internal:bif/3').
+
+is_bif(erlang, '!', 2) -> true;
+is_bif(erlang, '*', 2) -> true;
+is_bif(erlang, '+', 1) -> true;
+is_bif(erlang, '+', 2) -> true;
+is_bif(erlang, '++', 2) -> true;
+is_bif(erlang, '-', 1) -> true;
+is_bif(erlang, '-', 2) -> true;
+is_bif(erlang, '--', 2) -> true;
+is_bif(erlang, '/', 2) -> true;
+is_bif(erlang, '/=', 2) -> true;
+is_bif(erlang, '<', 2) -> true;
+is_bif(erlang, '=/=', 2) -> true;
+is_bif(erlang, '=:=', 2) -> true;
+is_bif(erlang, '=<', 2) -> true;
+is_bif(erlang, '==', 2) -> true;
+is_bif(erlang, '>', 2) -> true;
+is_bif(erlang, '>=', 2) -> true;
+is_bif(erlang, 'and', 2) -> true;
+is_bif(erlang, 'band', 2) -> true;
+is_bif(erlang, 'bnot', 1) -> true;
+is_bif(erlang, 'bor', 2) -> true;
+is_bif(erlang, 'bsl', 2) -> true;
+is_bif(erlang, 'bsr', 2) -> true;
+is_bif(erlang, 'bxor', 2) -> true;
+is_bif(erlang, 'div', 2) -> true;
+is_bif(erlang, 'not', 1) -> true;
+is_bif(erlang, 'or', 2) -> true;
+is_bif(erlang, 'rem', 2) -> true;
+is_bif(erlang, 'xor', 2) -> true;
+is_bif(erlang, abs, 1) -> true;
+is_bif(erlang, append_element, 2) -> true;
+is_bif(erlang, apply, 2) -> true;
+is_bif(erlang, apply, 3) -> true;
+is_bif(erlang, atom_to_list, 1) -> true;
+is_bif(erlang, binary_to_list, 1) -> true;
+is_bif(erlang, binary_to_list, 3) -> true;
+is_bif(erlang, binary_to_term, 1) -> true;
+is_bif(erlang, cancel_timer, 1) -> true;
+is_bif(erlang, concat_binary, 1) -> true;
+is_bif(erlang, date, 0) -> true;
+is_bif(erlang, demonitor, 1) -> true;
+is_bif(erlang, disconnect_node, 1) -> true;
+is_bif(erlang, display, 1) -> true;
+is_bif(erlang, element, 2) -> true;
+is_bif(erlang, erase, 0) -> true;
+is_bif(erlang, erase, 1) -> true;
+is_bif(erlang, error, 1) -> true;
+is_bif(erlang, error, 2) -> true;
+is_bif(erlang, exit, 1) -> true;
+is_bif(erlang, exit, 2) -> true;
+is_bif(erlang, fault, 1) -> true;
+is_bif(erlang, fault, 2) -> true;
+is_bif(erlang, float, 1) -> true;
+is_bif(erlang, float_to_list, 1) -> true;
+is_bif(erlang, fun_info, 1) -> true;
+is_bif(erlang, fun_info, 2) -> true;
+is_bif(erlang, fun_to_list, 1) -> true;
+is_bif(erlang, get, 0) -> true;
+is_bif(erlang, get, 1) -> true;
+is_bif(erlang, get_cookie, 0) -> true;
+is_bif(erlang, get_keys, 1) -> true;
+is_bif(erlang, group_leader, 0) -> true;
+is_bif(erlang, group_leader, 2) -> true;
+is_bif(erlang, halt, 0) -> false;
+is_bif(erlang, halt, 1) -> false;
+is_bif(erlang, hash, 2) -> false;
+is_bif(erlang, hd, 1) -> true;
+is_bif(erlang, info, 1) -> true;
+is_bif(erlang, integer_to_list, 1) -> true;
+is_bif(erlang, is_alive, 0) -> true;
+is_bif(erlang, is_atom, 1) -> true;
+is_bif(erlang, is_binary, 1) -> true;
+is_bif(erlang, is_boolean, 1) -> true;
+is_bif(erlang, is_builtin, 3) -> true;
+is_bif(erlang, is_constant, 1) -> true;
+is_bif(erlang, is_float, 1) -> true;
+is_bif(erlang, is_function, 1) -> true;
+is_bif(erlang, is_integer, 1) -> true;
+is_bif(erlang, is_list, 1) -> true;
+is_bif(erlang, is_number, 1) -> true;
+is_bif(erlang, is_pid, 1) -> true;
+is_bif(erlang, is_port, 1) -> true;
+is_bif(erlang, is_process_alive, 1) -> true;
+is_bif(erlang, is_record, 3) -> true;
+is_bif(erlang, is_reference, 1) -> true;
+is_bif(erlang, is_tuple, 1) -> true;
+is_bif(erlang, length, 1) -> true;
+is_bif(erlang, link, 1) -> true;
+is_bif(erlang, list_to_atom, 1) -> true;
+is_bif(erlang, list_to_binary, 1) -> true;
+is_bif(erlang, list_to_float, 1) -> true;
+is_bif(erlang, list_to_integer, 1) -> true;
+is_bif(erlang, list_to_pid, 1) -> true;
+is_bif(erlang, list_to_tuple, 1) -> true;
+is_bif(erlang, loaded, 0) -> true;
+is_bif(erlang, localtime, 0) -> true;
+is_bif(erlang, localtime_to_universaltime, 1) -> true;
+is_bif(erlang, make_ref, 0) -> true;
+is_bif(erlang, make_tuple, 2) -> true;
+is_bif(erlang, md5, 1) -> true;
+is_bif(erlang, md5_final, 1) -> true;
+is_bif(erlang, md5_init, 0) -> true;
+is_bif(erlang, md5_update, 2) -> true;
+is_bif(erlang, monitor, 2) -> true;
+is_bif(erlang, monitor_node, 2) -> true;
+is_bif(erlang, node, 0) -> true;
+is_bif(erlang, node, 1) -> true;
+is_bif(erlang, nodes, 0) -> true;
+is_bif(erlang, now, 0) -> true;
+is_bif(erlang, open_port, 2) -> true;
+is_bif(erlang, phash, 2) -> true;
+is_bif(erlang, pid_to_list, 1) -> true;
+is_bif(erlang, port_close, 2) -> true;
+is_bif(erlang, port_command, 2) -> true;
+is_bif(erlang, port_connect, 2) -> true;
+is_bif(erlang, port_control, 3) -> true;
+is_bif(erlang, port_info, 2) -> true;
+is_bif(erlang, port_to_list, 1) -> true;
+is_bif(erlang, ports, 0) -> true;
+is_bif(erlang, pre_loaded, 0) -> true;
+is_bif(erlang, process_display, 2) -> true;
+is_bif(erlang, process_flag, 2) -> true;
+is_bif(erlang, process_flag, 3) -> true;
+is_bif(erlang, process_info, 1) -> true;
+is_bif(erlang, process_info, 2) -> true;
+is_bif(erlang, processes, 0) -> true;
+is_bif(erlang, put, 2) -> true;
+is_bif(erlang, read_timer, 1) -> true;
+is_bif(erlang, ref_to_list, 1) -> true;
+is_bif(erlang, register, 2) -> true;
+is_bif(erlang, registered, 0) -> true;
+is_bif(erlang, resume_process, 1) -> true;
+is_bif(erlang, round, 1) -> true;
+is_bif(erlang, self, 0) -> true;
+is_bif(erlang, send_after, 3) -> true;
+is_bif(erlang, set_cookie, 2) -> true;
+is_bif(erlang, setelement, 3) -> true;
+is_bif(erlang, size, 1) -> true;
+is_bif(erlang, spawn, 1) -> true;
+is_bif(erlang, spawn, 2) -> true;
+is_bif(erlang, spawn, 3) -> true;
+is_bif(erlang, spawn, 4) -> true;
+is_bif(erlang, spawn_link, 1) -> true;
+is_bif(erlang, spawn_link, 2) -> true;
+is_bif(erlang, spawn_link, 3) -> true;
+is_bif(erlang, spawn_link, 4) -> true;
+is_bif(erlang, spawn_opt, 4) -> true;
+is_bif(erlang, split_binary, 2) -> true;
+is_bif(erlang, start_timer, 3) -> true;
+is_bif(erlang, statistics, 1) -> true;
+is_bif(erlang, suspend_process, 1) -> true;
+is_bif(erlang, system_flag, 2) -> true;
+is_bif(erlang, system_info, 1) -> true;
+is_bif(erlang, term_to_binary, 1) -> true;
+is_bif(erlang, term_to_binary, 2) -> true;
+is_bif(erlang, throw, 1) -> true;
+is_bif(erlang, time, 0) -> true;
+is_bif(erlang, tl, 1) -> true;
+is_bif(erlang, trace, 3) -> true;
+is_bif(erlang, trace_info, 2) -> true;
+is_bif(erlang, trace_pattern, 2) -> true;
+is_bif(erlang, trace_pattern, 3) -> true;
+is_bif(erlang, trunc, 1) -> true;
+is_bif(erlang, tuple_to_list, 1) -> true;
+is_bif(erlang, universaltime, 0) -> true;
+is_bif(erlang, universaltime_to_localtime, 1) -> true;
+is_bif(erlang, unlink, 1) -> true;
+is_bif(erlang, unregister, 1) -> true;
+is_bif(erlang, whereis, 1) -> true;
+is_bif(erlang, yield, 0) -> true;
+is_bif(lists, append, 2) -> true;
+is_bif(lists, reverse, 1) -> true;
+is_bif(lists, reverse, 2) -> true;
+is_bif(lists, subtract, 2) -> true;
+is_bif(math, acos, 1) -> true;
+is_bif(math, acosh, 1) -> true;
+is_bif(math, asin, 1) -> true;
+is_bif(math, asinh, 1) -> true;
+is_bif(math, atan, 1) -> true;
+is_bif(math, atan2, 2) -> true;
+is_bif(math, atanh, 1) -> true;
+is_bif(math, cos, 1) -> true;
+is_bif(math, cosh, 1) -> true;
+is_bif(math, erf, 1) -> true;
+is_bif(math, erfc, 1) -> true;
+is_bif(math, exp, 1) -> true;
+is_bif(math, log, 1) -> true;
+is_bif(math, log10, 1) -> true;
+is_bif(math, pow, 2) -> true;
+is_bif(math, sin, 1) -> true;
+is_bif(math, sinh, 1) -> true;
+is_bif(math, sqrt, 1) -> true;
+is_bif(math, tan, 1) -> true;
+is_bif(math, tanh, 1) -> true;
+is_bif(_, _, _) -> false.
+
+
+%% =====================================================================
+%% is_guard_bif(Module, Name, Arity) -> boolean()
+%%
+%% Module = Name = atom()
+%% Arity = integer()
+%%
+%% Returns `true' if the built-in function `Module:Name/Arity' may
+%% be called from a clause guard. Note that such "guard BIFs" are
+%% not necessarily "pure", since some (notably `erlang:self/0') may
+%% depend on the current state, nor "safe", since many guard BIFs
+%% can fail. Also note that even a "pure" function could be
+%% unsuitable for calling from a guard because of its time or space
+%% complexity.
+
+is_guard_bif(erlang, '*', 2) -> true;
+is_guard_bif(erlang, '+', 1) -> true;
+is_guard_bif(erlang, '+', 2) -> true;
+is_guard_bif(erlang, '-', 1) -> true;
+is_guard_bif(erlang, '-', 2) -> true;
+is_guard_bif(erlang, '/', 2) -> true;
+is_guard_bif(erlang, '/=', 2) -> true;
+is_guard_bif(erlang, '<', 2) -> true;
+is_guard_bif(erlang, '=/=', 2) -> true;
+is_guard_bif(erlang, '=:=', 2) -> true;
+is_guard_bif(erlang, '=<', 2) -> true;
+is_guard_bif(erlang, '==', 2) -> true;
+is_guard_bif(erlang, '>', 2) -> true;
+is_guard_bif(erlang, '>=', 2) -> true;
+is_guard_bif(erlang, 'and', 2) -> true;
+is_guard_bif(erlang, 'band', 2) -> true;
+is_guard_bif(erlang, 'bnot', 1) -> true;
+is_guard_bif(erlang, 'bor', 2) -> true;
+is_guard_bif(erlang, 'bsl', 2) -> true;
+is_guard_bif(erlang, 'bsr', 2) -> true;
+is_guard_bif(erlang, 'bxor', 2) -> true;
+is_guard_bif(erlang, 'div', 2) -> true;
+is_guard_bif(erlang, 'not', 1) -> true;
+is_guard_bif(erlang, 'or', 2) -> true;
+is_guard_bif(erlang, 'rem', 2) -> true;
+is_guard_bif(erlang, 'xor', 2) -> true;
+is_guard_bif(erlang, abs, 1) -> true;
+is_guard_bif(erlang, element, 2) -> true;
+is_guard_bif(erlang, error, 1) -> true; % unorthodox
+is_guard_bif(erlang, exit, 1) -> true; % unorthodox
+is_guard_bif(erlang, fault, 1) -> true; % unorthodox
+is_guard_bif(erlang, float, 1) -> true; % (the type coercion function)
+is_guard_bif(erlang, hd, 1) -> true;
+is_guard_bif(erlang, is_atom, 1) -> true;
+is_guard_bif(erlang, is_boolean, 1) -> true;
+is_guard_bif(erlang, is_binary, 1) -> true;
+is_guard_bif(erlang, is_constant, 1) -> true;
+is_guard_bif(erlang, is_float, 1) -> true;
+is_guard_bif(erlang, is_function, 1) -> true;
+is_guard_bif(erlang, is_integer, 1) -> true;
+is_guard_bif(erlang, is_list, 1) -> true;
+is_guard_bif(erlang, is_number, 1) -> true;
+is_guard_bif(erlang, is_pid, 1) -> true;
+is_guard_bif(erlang, is_port, 1) -> true;
+is_guard_bif(erlang, is_reference, 1) -> true;
+is_guard_bif(erlang, is_tuple, 1) -> true;
+is_guard_bif(erlang, length, 1) -> true;
+is_guard_bif(erlang, list_to_atom, 1) -> true; % unorthodox
+is_guard_bif(erlang, node, 0) -> true; % (not pure)
+is_guard_bif(erlang, node, 1) -> true; % (not pure)
+is_guard_bif(erlang, round, 1) -> true;
+is_guard_bif(erlang, self, 0) -> true; % (not pure)
+is_guard_bif(erlang, size, 1) -> true;
+is_guard_bif(erlang, throw, 1) -> true; % unorthodox
+is_guard_bif(erlang, tl, 1) -> true;
+is_guard_bif(erlang, trunc, 1) -> true;
+is_guard_bif(math, acos, 1) -> true; % unorthodox
+is_guard_bif(math, acosh, 1) -> true; % unorthodox
+is_guard_bif(math, asin, 1) -> true; % unorthodox
+is_guard_bif(math, asinh, 1) -> true; % unorthodox
+is_guard_bif(math, atan, 1) -> true; % unorthodox
+is_guard_bif(math, atan2, 2) -> true; % unorthodox
+is_guard_bif(math, atanh, 1) -> true; % unorthodox
+is_guard_bif(math, cos, 1) -> true; % unorthodox
+is_guard_bif(math, cosh, 1) -> true; % unorthodox
+is_guard_bif(math, erf, 1) -> true; % unorthodox
+is_guard_bif(math, erfc, 1) -> true; % unorthodox
+is_guard_bif(math, exp, 1) -> true; % unorthodox
+is_guard_bif(math, log, 1) -> true; % unorthodox
+is_guard_bif(math, log10, 1) -> true; % unorthodox
+is_guard_bif(math, pow, 2) -> true; % unorthodox
+is_guard_bif(math, sin, 1) -> true; % unorthodox
+is_guard_bif(math, sinh, 1) -> true; % unorthodox
+is_guard_bif(math, sqrt, 1) -> true; % unorthodox
+is_guard_bif(math, tan, 1) -> true; % unorthodox
+is_guard_bif(math, tanh, 1) -> true; % unorthodox
+is_guard_bif(_, _, _) -> false.
+
+
+%% =====================================================================
+%% is_pure(Module, Name, Arity) -> boolean()
+%%
+%% Module = Name = atom()
+%% Arity = integer()
+%%
+%% Returns `true' if the function `Module:Name/Arity' does not
+%% affect the state, nor depend on the state, although its
+%% evaluation is not guaranteed to complete normally for all input.
+
+is_pure(erlang, '*', 2) -> true;
+is_pure(erlang, '+', 1) -> true; % (even for non-numbers)
+is_pure(erlang, '+', 2) -> true;
+is_pure(erlang, '++', 2) -> true;
+is_pure(erlang, '-', 1) -> true;
+is_pure(erlang, '-', 2) -> true;
+is_pure(erlang, '--', 2) -> true;
+is_pure(erlang, '/', 2) -> true;
+is_pure(erlang, '/=', 2) -> true;
+is_pure(erlang, '<', 2) -> true;
+is_pure(erlang, '=/=', 2) -> true;
+is_pure(erlang, '=:=', 2) -> true;
+is_pure(erlang, '=<', 2) -> true;
+is_pure(erlang, '==', 2) -> true;
+is_pure(erlang, '>', 2) -> true;
+is_pure(erlang, '>=', 2) -> true;
+is_pure(erlang, 'and', 2) -> true;
+is_pure(erlang, 'band', 2) -> true;
+is_pure(erlang, 'bnot', 1) -> true;
+is_pure(erlang, 'bor', 2) -> true;
+is_pure(erlang, 'bsl', 2) -> true;
+is_pure(erlang, 'bsr', 2) -> true;
+is_pure(erlang, 'bxor', 2) -> true;
+is_pure(erlang, 'div', 2) -> true;
+is_pure(erlang, 'not', 1) -> true;
+is_pure(erlang, 'or', 2) -> true;
+is_pure(erlang, 'rem', 2) -> true;
+is_pure(erlang, 'xor', 2) -> true;
+is_pure(erlang, abs, 1) -> true;
+is_pure(erlang, atom_to_list, 1) -> true;
+is_pure(erlang, binary_to_list, 1) -> true;
+is_pure(erlang, binary_to_list, 3) -> true;
+is_pure(erlang, concat_binary, 1) -> true;
+is_pure(erlang, element, 2) -> true;
+is_pure(erlang, float, 1) -> true;
+is_pure(erlang, float_to_list, 1) -> true;
+is_pure(erlang, hash, 2) -> false;
+is_pure(erlang, hd, 1) -> true;
+is_pure(erlang, integer_to_list, 1) -> true;
+is_pure(erlang, is_atom, 1) -> true;
+is_pure(erlang, is_boolean, 1) -> true;
+is_pure(erlang, is_binary, 1) -> true;
+is_pure(erlang, is_builtin, 3) -> true;
+is_pure(erlang, is_constant, 1) -> true;
+is_pure(erlang, is_float, 1) -> true;
+is_pure(erlang, is_function, 1) -> true;
+is_pure(erlang, is_integer, 1) -> true;
+is_pure(erlang, is_list, 1) -> true;
+is_pure(erlang, is_number, 1) -> true;
+is_pure(erlang, is_pid, 1) -> true;
+is_pure(erlang, is_port, 1) -> true;
+is_pure(erlang, is_record, 3) -> true;
+is_pure(erlang, is_reference, 1) -> true;
+is_pure(erlang, is_tuple, 1) -> true;
+is_pure(erlang, length, 1) -> true;
+is_pure(erlang, list_to_atom, 1) -> true;
+is_pure(erlang, list_to_binary, 1) -> true;
+is_pure(erlang, list_to_float, 1) -> true;
+is_pure(erlang, list_to_integer, 1) -> true;
+is_pure(erlang, list_to_pid, 1) -> true;
+is_pure(erlang, list_to_tuple, 1) -> true;
+is_pure(erlang, phash, 2) -> false;
+is_pure(erlang, pid_to_list, 1) -> true;
+is_pure(erlang, round, 1) -> true;
+is_pure(erlang, setelement, 3) -> true;
+is_pure(erlang, size, 1) -> true;
+is_pure(erlang, split_binary, 2) -> true;
+is_pure(erlang, term_to_binary, 1) -> true;
+is_pure(erlang, tl, 1) -> true;
+is_pure(erlang, trunc, 1) -> true;
+is_pure(erlang, tuple_to_list, 1) -> true;
+is_pure(lists, append, 2) -> true;
+is_pure(lists, subtract, 2) -> true;
+is_pure(math, acos, 1) -> true;
+is_pure(math, acosh, 1) -> true;
+is_pure(math, asin, 1) -> true;
+is_pure(math, asinh, 1) -> true;
+is_pure(math, atan, 1) -> true;
+is_pure(math, atan2, 2) -> true;
+is_pure(math, atanh, 1) -> true;
+is_pure(math, cos, 1) -> true;
+is_pure(math, cosh, 1) -> true;
+is_pure(math, erf, 1) -> true;
+is_pure(math, erfc, 1) -> true;
+is_pure(math, exp, 1) -> true;
+is_pure(math, log, 1) -> true;
+is_pure(math, log10, 1) -> true;
+is_pure(math, pow, 2) -> true;
+is_pure(math, sin, 1) -> true;
+is_pure(math, sinh, 1) -> true;
+is_pure(math, sqrt, 1) -> true;
+is_pure(math, tan, 1) -> true;
+is_pure(math, tanh, 1) -> true;
+is_pure(_, _, _) -> false.
+
+
+%% =====================================================================
+%% is_safe(Module, Name, Arity) -> boolean()
+%%
+%% Module = Name = atom()
+%% Arity = integer()
+%%
+%% Returns `true' if the function `Module:Name/Arity' is completely
+%% effect free, i.e., if its evaluation always completes normally
+%% and does not affect the state (although the value it returns
+%% might depend on the state).
+
+is_safe(erlang, '/=', 2) -> true;
+is_safe(erlang, '<', 2) -> true;
+is_safe(erlang, '=/=', 2) -> true;
+is_safe(erlang, '=:=', 2) -> true;
+is_safe(erlang, '=<', 2) -> true;
+is_safe(erlang, '==', 2) -> true;
+is_safe(erlang, '>', 2) -> true;
+is_safe(erlang, '>=', 2) -> true;
+is_safe(erlang, date, 0) -> true;
+is_safe(erlang, get, 0) -> true;
+is_safe(erlang, get, 1) -> true;
+is_safe(erlang, get_cookie, 0) -> true;
+is_safe(erlang, get_keys, 1) -> true;
+is_safe(erlang, group_leader, 0) -> true;
+is_safe(erlang, is_alive, 0) -> true;
+is_safe(erlang, is_atom, 1) -> true;
+is_safe(erlang, is_boolean, 1) -> true;
+is_safe(erlang, is_binary, 1) -> true;
+is_safe(erlang, is_constant, 1) -> true;
+is_safe(erlang, is_float, 1) -> true;
+is_safe(erlang, is_function, 1) -> true;
+is_safe(erlang, is_integer, 1) -> true;
+is_safe(erlang, is_list, 1) -> true;
+is_safe(erlang, is_number, 1) -> true;
+is_safe(erlang, is_pid, 1) -> true;
+is_safe(erlang, is_port, 1) -> true;
+is_safe(erlang, is_record, 3) -> true;
+is_safe(erlang, is_reference, 1) -> true;
+is_safe(erlang, is_tuple, 1) -> true;
+is_safe(erlang, make_ref, 0) -> true;
+is_safe(erlang, node, 0) -> true;
+is_safe(erlang, nodes, 0) -> true;
+is_safe(erlang, ports, 0) -> true;
+is_safe(erlang, pre_loaded, 0) -> true;
+is_safe(erlang, processes, 0) -> true;
+is_safe(erlang, registered, 0) -> true;
+is_safe(erlang, self, 0) -> true;
+is_safe(erlang, term_to_binary, 1) -> true;
+is_safe(erlang, time, 0) -> true;
+is_safe(_, _, _) -> false.
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/rec_env.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/rec_env.erl
new file mode 100644
index 0000000000..01c2512397
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/rec_env.erl
@@ -0,0 +1,611 @@
+%% =====================================================================
+%% This library is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU Lesser General Public License as
+%% published by the Free Software Foundation; either version 2 of the
+%% License, or (at your option) any later version.
+%%
+%% This library is distributed in the hope that it will be useful, but
+%% WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+%% Lesser General Public License for more details.
+%%
+%% You should have received a copy of the GNU Lesser General Public
+%% License along with this library; if not, write to the Free Software
+%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+%% USA
+%%
+%% $Id: rec_env.erl,v 1.2 2009/09/17 09:46:19 kostis Exp $
+%%
+%% @author Richard Carlsson <[email protected]>
+%% @copyright 1999-2004 Richard Carlsson
+%% @doc Abstract environments, supporting self-referential bindings and
+%% automatic new-key generation.
+
+%% The current implementation is based on Erlang standard library
+%% dictionaries.
+
+%%% -define(DEBUG, true).
+
+-module(rec_env).
+
+-export([bind/3, bind_list/3, bind_recursive/4, delete/2, empty/0,
+ get/2, is_defined/2, is_empty/1, keys/1, lookup/2, new_key/1,
+ new_key/2, new_keys/2, new_keys/3, size/1, to_list/1]).
+
+-ifdef(DEBUG).
+-export([test/1, test_custom/1, test_custom/2]).
+-endif.
+
+-ifdef(DEBUG).
+%% Code for testing:
+%%@hidden
+test(N) ->
+ test_0(integer, N).
+
+%%@hidden
+test_custom(N) ->
+ F = fun (X) -> list_to_atom("X"++integer_to_list(X)) end,
+ test_custom(F, N).
+
+%%@hidden
+test_custom(F, N) ->
+ test_0({custom, F}, N).
+
+test_0(Type, N) ->
+ put(new_key_calls, 0),
+ put(new_key_retries, 0),
+ put(new_key_max, 0),
+ Env = test_1(Type, N, empty()),
+ io:fwrite("\ncalls: ~w.\n", [get(new_key_calls)]),
+ io:fwrite("\nretries: ~w.\n", [get(new_key_retries)]),
+ io:fwrite("\nmax: ~w.\n", [get(new_key_max)]),
+ dict:to_list(element(1,Env)).
+
+test_1(integer = Type, N, Env) when integer(N), N > 0 ->
+ Key = new_key(Env),
+ test_1(Type, N - 1, bind(Key, value, Env));
+test_1({custom, F} = Type, N, Env) when integer(N), N > 0 ->
+ Key = new_key(F, Env),
+ test_1(Type, N - 1, bind(Key, value, Env));
+test_1(_,0, Env) ->
+ Env.
+-endif.
+
+
+%% Representation:
+%%
+%% environment() = [Mapping]
+%%
+%% Mapping = {map, Dict} | {rec, Dict, Dict}
+%% Dict = dict:dictionary()
+%%
+%% An empty environment is a list containing a single `{map, Dict}'
+%% element - empty lists are not valid environments. To find a key in an
+%% environment, it is searched for in each mapping in the list, in
+%% order, until it the key is found in some mapping, or the end of the
+%% list is reached. In a 'rec' mapping, we keep the original dictionary
+%% together with a version where entries may have been deleted - this
+%% makes it possible to garbage collect the entire 'rec' mapping when
+%% all its entries are unused (for example, by being shadowed by later
+%% definitions).
+
+
+
+%% =====================================================================
+%% @type environment(). An abstract environment.
+
+
+%% =====================================================================
+%% @spec empty() -> environment()
+%%
+%% @doc Returns an empty environment.
+
+empty() ->
+ [{map, dict:new()}].
+
+
+%% =====================================================================
+%% @spec is_empty(Env::environment()) -> boolean()
+%%
+%% @doc Returns <code>true</code> if the environment is empty, otherwise
+%% <code>false</code>.
+
+is_empty([{map, Dict} | Es]) ->
+ N = dict:size(Dict),
+ if N /= 0 -> false;
+ Es == [] -> true;
+ true -> is_empty(Es)
+ end;
+is_empty([{rec, Dict, _} | Es]) ->
+ N = dict:size(Dict),
+ if N /= 0 -> false;
+ Es == [] -> true;
+ true -> is_empty(Es)
+ end.
+
+
+%% =====================================================================
+%% @spec size(Env::environment()) -> integer()
+%%
+%% @doc Returns the number of entries in an environment.
+
+%% (The name 'size' cannot be used in local calls, since there exists a
+%% built-in function with the same name.)
+
+size(Env) ->
+ env_size(Env).
+
+env_size([{map, Dict}]) ->
+ dict:size(Dict);
+env_size([{map, Dict} | Env]) ->
+ dict:size(Dict) + env_size(Env);
+env_size([{rec, Dict, _Dict0} | Env]) ->
+ dict:size(Dict) + env_size(Env).
+
+
+%% =====================================================================
+%% @spec is_defined(Key, Env) -> boolean()
+%%
+%% Key = term()
+%% Env = environment()
+%%
+%% @doc Returns <code>true</code> if <code>Key</code> is bound in the
+%% environment, otherwise <code>false</code>.
+
+is_defined(Key, [{map, Dict} | Env]) ->
+ case dict:is_key(Key, Dict) of
+ true ->
+ true;
+ false when Env == [] ->
+ false;
+ false ->
+ is_defined(Key, Env)
+ end;
+is_defined(Key, [{rec, Dict, _Dict0} | Env]) ->
+ case dict:is_key(Key, Dict) of
+ true ->
+ true;
+ false ->
+ is_defined(Key, Env)
+ end.
+
+
+%% =====================================================================
+%% @spec keys(Env::environment()) -> [term()]
+%%
+%% @doc Returns the ordered list of all keys in the environment.
+
+keys(Env) ->
+ lists:sort(keys(Env, [])).
+
+keys([{map, Dict}], S) ->
+ dict:fetch_keys(Dict) ++ S;
+keys([{map, Dict} | Env], S) ->
+ keys(Env, dict:fetch_keys(Dict) ++ S);
+keys([{rec, Dict, _Dict0} | Env], S) ->
+ keys(Env, dict:fetch_keys(Dict) ++ S).
+
+
+%% =====================================================================
+%% @spec to_list(Env) -> [{Key, Value}]
+%%
+%% Env = environment()
+%% Key = term()
+%% Value = term()
+%%
+%% @doc Returns an ordered list of <code>{Key, Value}</code> pairs for
+%% all keys in <code>Env</code>. <code>Value</code> is the same as that
+%% returned by {@link get/2}.
+
+to_list(Env) ->
+ lists:sort(to_list(Env, [])).
+
+to_list([{map, Dict}], S) ->
+ dict:to_list(Dict) ++ S;
+to_list([{map, Dict} | Env], S) ->
+ to_list(Env, dict:to_list(Dict) ++ S);
+to_list([{rec, Dict, _Dict0} | Env], S) ->
+ to_list(Env, dict:to_list(Dict) ++ S).
+
+
+%% =====================================================================
+%% @spec bind(Key, Value, Env) -> environment()
+%%
+%% Key = term()
+%% Value = term()
+%% Env = environment()
+%%
+%% @doc Make a nonrecursive entry. This binds <code>Key</code> to
+%% <code>Value</code>. If the key already existed in the environment,
+%% the old entry is replaced.
+
+%% Note that deletion is done to free old bindings so they can be
+%% garbage collected.
+
+bind(Key, Value, [{map, Dict}]) ->
+ [{map, dict:store(Key, Value, Dict)}];
+bind(Key, Value, [{map, Dict} | Env]) ->
+ [{map, dict:store(Key, Value, Dict)} | delete_any(Key, Env)];
+bind(Key, Value, Env) ->
+ [{map, dict:store(Key, Value, dict:new())} | delete_any(Key, Env)].
+
+
+%% =====================================================================
+%% @spec bind_list(Keys, Values, Env) -> environment()
+%%
+%% Keys = [term()]
+%% Values = [term()]
+%% Env = environment()
+%%
+%% @doc Make N nonrecursive entries. This binds each key in
+%% <code>Keys</code> to the corresponding value in
+%% <code>Values</code>. If some key already existed in the environment,
+%% the previous entry is replaced. If <code>Keys</code> does not have
+%% the same length as <code>Values</code>, an exception is generated.
+
+bind_list(Ks, Vs, [{map, Dict}]) ->
+ [{map, store_list(Ks, Vs, Dict)}];
+bind_list(Ks, Vs, [{map, Dict} | Env]) ->
+ [{map, store_list(Ks, Vs, Dict)} | delete_list(Ks, Env)];
+bind_list(Ks, Vs, Env) ->
+ [{map, store_list(Ks, Vs, dict:new())} | delete_list(Ks, Env)].
+
+store_list([K | Ks], [V | Vs], Dict) ->
+ store_list(Ks, Vs, dict:store(K, V, Dict));
+store_list([], _, Dict) ->
+ Dict.
+
+delete_list([K | Ks], Env) ->
+ delete_list(Ks, delete_any(K, Env));
+delete_list([], Env) ->
+ Env.
+
+%% By not calling `delete' unless we have to, we avoid unnecessary
+%% rewriting of the data.
+
+delete_any(Key, Env) ->
+ case is_defined(Key, Env) of
+ true ->
+ delete(Key, Env);
+ false ->
+ Env
+ end.
+
+%% =====================================================================
+%% @spec delete(Key, Env) -> environment()
+%%
+%% Key = term()
+%% Env = environment()
+%%
+%% @doc Delete an entry. This removes <code>Key</code> from the
+%% environment.
+
+delete(Key, [{map, Dict} = E | Env]) ->
+ case dict:is_key(Key, Dict) of
+ true ->
+ [{map, dict:erase(Key, Dict)} | Env];
+ false ->
+ delete_1(Key, Env, E)
+ end;
+delete(Key, [{rec, Dict, Dict0} = E | Env]) ->
+ case dict:is_key(Key, Dict) of
+ true ->
+ %% The Dict0 component must be preserved as it is until all
+ %% keys in Dict have been deleted.
+ Dict1 = dict:erase(Key, Dict),
+ case dict:size(Dict1) of
+ 0 ->
+ Env; % the whole {rec,...} is now garbage
+ _ ->
+ [{rec, Dict1, Dict0} | Env]
+ end;
+ false ->
+ [E | delete(Key, Env)]
+ end.
+
+%% This is just like above, except we pass on the preceding 'map'
+%% mapping in the list to enable merging when removing 'rec' mappings.
+
+delete_1(Key, [{rec, Dict, Dict0} = E | Env], E1) ->
+ case dict:is_key(Key, Dict) of
+ true ->
+ Dict1 = dict:erase(Key, Dict),
+ case dict:size(Dict1) of
+ 0 ->
+ concat(E1, Env);
+ _ ->
+ [E1, {rec, Dict1, Dict0} | Env]
+ end;
+ false ->
+ [E1, E | delete(Key, Env)]
+ end.
+
+concat({map, D1}, [{map, D2} | Env]) ->
+ [dict:merge(fun (_K, V1, _V2) -> V1 end, D1, D2) | Env];
+concat(E1, Env) ->
+ [E1 | Env].
+
+
+%% =====================================================================
+%% @spec bind_recursive(Keys, Values, Fun, Env) -> NewEnv
+%%
+%% Keys = [term()]
+%% Values = [term()]
+%% Fun = (Value, Env) -> term()
+%% Env = environment()
+%% NewEnv = environment()
+%%
+%% @doc Make N recursive entries. This binds each key in
+%% <code>Keys</code> to the value of <code>Fun(Value, NewEnv)</code> for
+%% the corresponding <code>Value</code>. If <code>Keys</code> does not
+%% have the same length as <code>Values</code>, an exception is
+%% generated. If some key already existed in the environment, the old
+%% entry is replaced.
+%%
+%% <p>Note: the function <code>Fun</code> is evaluated each time one of
+%% the stored keys is looked up, but only then.</p>
+%%
+%% <p>Examples:
+%%<pre>
+%% NewEnv = bind_recursive([foo, bar], [1, 2],
+%% fun (V, E) -> V end,
+%% Env)</pre>
+%%
+%% This does nothing interesting; <code>get(foo, NewEnv)</code> yields
+%% <code>1</code> and <code>get(bar, NewEnv)</code> yields
+%% <code>2</code>, but there is more overhead than if the {@link
+%% bind_list/3} function had been used.
+%%
+%% <pre>
+%% NewEnv = bind_recursive([foo, bar], [1, 2],
+%% fun (V, E) -> {V, E} end,
+%% Env)</pre>
+%%
+%% Here, however, <code>get(foo, NewEnv)</code> will yield <code>{1,
+%% NewEnv}</code> and <code>get(bar, NewEnv)</code> will yield <code>{2,
+%% NewEnv}</code>, i.e., the environment <code>NewEnv</code> contains
+%% recursive bindings.</p>
+
+bind_recursive([], [], _, Env) ->
+ Env;
+bind_recursive(Ks, Vs, F, Env) ->
+ F1 = fun (V) ->
+ fun (Dict) -> F(V, [{rec, Dict, Dict} | Env]) end
+ end,
+ Dict = bind_recursive_1(Ks, Vs, F1, dict:new()),
+ [{rec, Dict, Dict} | Env].
+
+bind_recursive_1([K | Ks], [V | Vs], F, Dict) ->
+ bind_recursive_1(Ks, Vs, F, dict:store(K, F(V), Dict));
+bind_recursive_1([], [], _, Dict) ->
+ Dict.
+
+
+%% =====================================================================
+%% @spec lookup(Key, Env) -> error | {ok, Value}
+%%
+%% Key = term()
+%% Env = environment()
+%% Value = term()
+%%
+%% @doc Returns <code>{ok, Value}</code> if <code>Key</code> is bound to
+%% <code>Value</code> in <code>Env</code>, and <code>error</code>
+%% otherwise.
+
+lookup(Key, [{map, Dict} | Env]) ->
+ case dict:find(Key, Dict) of
+ {ok, _}=Value ->
+ Value;
+ error when Env == [] ->
+ error;
+ error ->
+ lookup(Key, Env)
+ end;
+lookup(Key, [{rec, Dict, Dict0} | Env]) ->
+ case dict:find(Key, Dict) of
+ {ok, F} ->
+ {ok, F(Dict0)};
+ error ->
+ lookup(Key, Env)
+ end.
+
+
+%% =====================================================================
+%% @spec get(Key, Env) -> Value
+%%
+%% Key = term()
+%% Env = environment()
+%% Value = term()
+%%
+%% @doc Returns the value that <code>Key</code> is bound to in
+%% <code>Env</code>. Throws <code>{undefined, Key}</code> if the key
+%% does not exist in <code>Env</code>.
+
+get(Key, Env) ->
+ case lookup(Key, Env) of
+ {ok, Value} -> Value;
+ error -> throw({undefined, Key})
+ end.
+
+
+%% =====================================================================
+%% The key-generating algorithm could possibly be further improved. The
+%% important thing to keep in mind is, that when we need a new key, we
+%% are generally in mid-traversal of a syntax tree, and existing names
+%% in the tree may be closely grouped and evenly distributed or even
+%% forming a compact range (often having been generated by a "gensym",
+%% or by this very algorithm itself). This means that if we generate an
+%% identifier whose value is too close to those already seen (i.e.,
+%% which are in the environment), it is very probable that we will
+%% shadow a not-yet-seen identifier further down in the tree, the result
+%% being that we induce another later renaming, and end up renaming most
+%% of the identifiers, completely contrary to our intention. We need to
+%% generate new identifiers in a way that avoids such systematic
+%% collisions.
+%%
+%% One way of getting a new key to try when the previous attempt failed
+%% is of course to e.g. add one to the last tried value. However, in
+%% general it's a bad idea to try adjacent identifiers: the percentage
+%% of retries will typically increase a lot, so you may lose big on the
+%% extra lookups while gaining only a little from the quicker
+%% computation.
+%%
+%% We want an initial range that is large enough for most typical cases.
+%% If we start with, say, a range of 10, we might quickly use up most of
+%% the values in the range 1-10 (or 1-100) for new top-level variables -
+%% but as we start traversing the syntax tree, it is quite likely that
+%% exactly those variables will be encountered again (this depends on
+%% how the names in the tree were created), and will then need to be
+%% renamed. If we instead begin with a larger range, it is less likely
+%% that any top-level names that we introduce will shadow names that we
+%% will find in the tree. Of course we cannot know how large is large
+%% enough: for any initial range, there is some syntax tree that uses
+%% all the values in that range, and thus any top-level names introduced
+%% will shadow names in the tree. The point is to avoid this happening
+%% all the time - a range of about 1000 seems enough for most programs.
+%%
+%% The following values have been shown to work well:
+
+-define(MINIMUM_RANGE, 1000).
+-define(START_RANGE_FACTOR, 50).
+-define(MAX_RETRIES, 2). % retries before enlarging range
+-define(ENLARGE_FACTOR, 10). % range enlargment factor
+
+-ifdef(DEBUG).
+%% If you want to use these process dictionary counters, make sure to
+%% initialise them to zero before you call any of the key-generating
+%% functions.
+%%
+%% new_key_calls total number of calls
+%% new_key_retries failed key generation attempts
+%% new_key_max maximum generated integer value
+%%
+-define(measure_calls(),
+ put(new_key_calls, 1 + get(new_key_calls))).
+-define(measure_max_key(N),
+ case N > get(new_key_max) of
+ true ->
+ put(new_key_max, N);
+ false ->
+ ok
+ end).
+-define(measure_retries(N),
+ put(new_key_retries, get(new_key_retries) + N)).
+-else.
+-define(measure_calls(), ok).
+-define(measure_max_key(N), ok).
+-define(measure_retries(N), ok).
+-endif.
+
+
+%% =====================================================================
+%% @spec new_key(Env::environment()) -> integer()
+%%
+%% @doc Returns an integer which is not already used as key in the
+%% environment. New integers are generated using an algorithm which
+%% tries to keep the values randomly distributed within a reasonably
+%% small range relative to the number of entries in the environment.
+%%
+%% <p>This function uses the Erlang standard library module
+%% <code>random</code> to generate new keys.</p>
+%%
+%% <p>Note that only the new key is returned; the environment itself is
+%% not updated by this function.</p>
+
+new_key(Env) ->
+ new_key(fun (X) -> X end, Env).
+
+
+%% =====================================================================
+%% @spec new_key(Function, Env) -> term()
+%%
+%% Function = (integer()) -> term()
+%% Env = environment()
+%%
+%% @doc Returns a term which is not already used as key in the
+%% environment. The term is generated by applying <code>Function</code>
+%% to an integer generated as in {@link new_key/1}.
+%%
+%% <p>Note that only the generated term is returned; the environment
+%% itself is not updated by this function.</p>
+
+new_key(F, Env) ->
+ ?measure_calls(),
+ R = start_range(Env),
+%%% io:fwrite("Start range: ~w.\n", [R]),
+ new_key(R, F, Env).
+
+new_key(R, F, Env) ->
+ new_key(generate(R, R), R, 0, F, Env).
+
+new_key(N, R, T, F, Env) when T < ?MAX_RETRIES ->
+ A = F(N),
+ case is_defined(A, Env) of
+ true ->
+%%% io:fwrite("CLASH: ~w.\n", [A]),
+ new_key(generate(N, R), R, T + 1, F, Env);
+ false ->
+ ?measure_max_key(N),
+ ?measure_retries(T),
+%%% io:fwrite("New: ~w.\n", [N]),
+ A
+ end;
+new_key(N, R, _T, F, Env) ->
+ %% Too many retries - enlarge the range and start over.
+ ?measure_retries((_T + 1)),
+ R1 = trunc(R * ?ENLARGE_FACTOR),
+%%% io:fwrite("**NEW RANGE**: ~w.\n", [R1]),
+ new_key(generate(N, R1), R1, 0, F, Env).
+
+start_range(Env) ->
+ max(env_size(Env) * ?START_RANGE_FACTOR, ?MINIMUM_RANGE).
+
+max(X, Y) when X > Y -> X;
+max(_, Y) -> Y.
+
+%% The previous key might or might not be used to compute the next key
+%% to be tried. It is currently not used.
+%%
+%% In order to avoid causing cascading renamings, it is important that
+%% this function does not generate values in order, but
+%% (pseudo-)randomly distributed over the range.
+
+generate(_N, Range) ->
+ random:uniform(Range). % works well
+
+
+%% =====================================================================
+%% @spec new_keys(N, Env) -> [integer()]
+%%
+%% N = integer()
+%% Env = environment()
+%%
+%% @doc Returns a list of <code>N</code> distinct integers that are not
+%% already used as keys in the environment. See {@link new_key/1} for
+%% details.
+
+new_keys(N, Env) when integer(N) ->
+ new_keys(N, fun (X) -> X end, Env).
+
+
+%% =====================================================================
+%% @spec new_keys(N, Function, Env) -> [term()]
+%%
+%% N = integer()
+%% Function = (integer()) -> term()
+%% Env = environment()
+%%
+%% @doc Returns a list of <code>N</code> distinct terms that are not
+%% already used as keys in the environment. See {@link new_key/3} for
+%% details.
+
+new_keys(N, F, Env) when integer(N) ->
+ R = start_range(Env),
+ new_keys(N, [], R, F, Env).
+
+new_keys(N, Ks, R, F, Env) when N > 0 ->
+ Key = new_key(R, F, Env),
+ Env1 = bind(Key, true, Env), % dummy binding
+ new_keys(N - 1, [Key | Ks], R, F, Env1);
+new_keys(0, Ks, _, _, _) ->
+ Ks.
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/sys_expand_pmod.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/sys_expand_pmod.erl
new file mode 100644
index 0000000000..f48cc05b9c
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/sys_expand_pmod.erl
@@ -0,0 +1,425 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: sys_expand_pmod.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
+%%
+-module(sys_expand_pmod).
+
+%% Expand function definition forms of parameterized module. We assume
+%% all record definitions, imports, queries, etc., have been expanded
+%% away. Any calls on the form 'foo(...)' must be calls to local
+%% functions. Auto-generated functions (module_info,...) have not yet
+%% been added to the function definitions, but are listed in 'defined'
+%% and 'exports'. The 'new/N' function is neither added to the
+%% definitions nor to the 'exports'/'defines' lists yet.
+
+-export([forms/4]).
+
+-record(pmod, {parameters, exports, defined, predef}).
+
+%% TODO: more abstract handling of predefined/static functions.
+
+forms(Fs0, Ps, Es0, Ds0) ->
+ PreDef = [{module_info,0},{module_info,1}],
+ forms(Fs0, Ps, Es0, Ds0, PreDef).
+
+forms(Fs0, Ps, Es0, Ds0, PreDef) ->
+ St0 = #pmod{parameters=Ps,exports=Es0,defined=Ds0, predef=PreDef},
+ {Fs1, St1} = forms(Fs0, St0),
+ Es1 = update_function_names(Es0, St1),
+ Ds1 = update_function_names(Ds0, St1),
+ Fs2 = update_forms(Fs1, St1),
+ {Fs2,Es1,Ds1}.
+
+%% This is extremely simplistic for now; all functions get an extra
+%% parameter, whether they need it or not, except for static functions.
+
+update_function_names(Es, St) ->
+ [update_function_name(E, St) || E <- Es].
+
+update_function_name(E={F,A}, St) ->
+ case ordsets:is_element(E, St#pmod.predef) of
+ true -> E;
+ false -> {F, A + 1}
+ end.
+
+update_forms([{function,L,N,A,Cs}|Fs],St) ->
+ [{function,L,N,A+1,Cs}|update_forms(Fs,St)];
+update_forms([F|Fs],St) ->
+ [F|update_forms(Fs,St)];
+update_forms([],_St) ->
+ [].
+
+%% Process the program forms.
+
+forms([F0|Fs0],St0) ->
+ {F1,St1} = form(F0,St0),
+ {Fs1,St2} = forms(Fs0,St1),
+ {[F1|Fs1],St2};
+forms([], St0) ->
+ {[], St0}.
+
+%% Only function definitions are of interest here. State is not updated.
+form({function,Line,Name0,Arity0,Clauses0},St) ->
+ {Name,Arity,Clauses} = function(Name0, Arity0, Clauses0, St),
+ {{function,Line,Name,Arity,Clauses},St};
+%% Pass anything else through
+form(F,St) -> {F,St}.
+
+function(Name, Arity, Clauses0, St) ->
+ Clauses1 = clauses(Clauses0,St),
+ {Name,Arity,Clauses1}.
+
+clauses([C|Cs],St) ->
+ {clause,L,H,G,B} = clause(C,St),
+ T = {tuple,L,[{var,L,V} || V <- ['_'|St#pmod.parameters]]},
+ [{clause,L,H++[{match,L,T,{var,L,'THIS'}}],G,B}|clauses(Cs,St)];
+clauses([],_St) -> [].
+
+clause({clause,Line,H0,G0,B0},St) ->
+ H1 = head(H0,St),
+ G1 = guard(G0,St),
+ B1 = exprs(B0,St),
+ {clause,Line,H1,G1,B1}.
+
+head(Ps,St) -> patterns(Ps,St).
+
+patterns([P0|Ps],St) ->
+ P1 = pattern(P0,St),
+ [P1|patterns(Ps,St)];
+patterns([],_St) -> [].
+
+string_to_conses([], _Line, Tail) ->
+ Tail;
+string_to_conses([E|Rest], Line, Tail) ->
+ {cons, Line, {integer, Line, E}, string_to_conses(Rest, Line, Tail)}.
+
+pattern({var,Line,V},_St) -> {var,Line,V};
+pattern({match,Line,L0,R0},St) ->
+ L1 = pattern(L0,St),
+ R1 = pattern(R0,St),
+ {match,Line,L1,R1};
+pattern({integer,Line,I},_St) -> {integer,Line,I};
+pattern({char,Line,C},_St) -> {char,Line,C};
+pattern({float,Line,F},_St) -> {float,Line,F};
+pattern({atom,Line,A},_St) -> {atom,Line,A};
+pattern({string,Line,S},_St) -> {string,Line,S};
+pattern({nil,Line},_St) -> {nil,Line};
+pattern({cons,Line,H0,T0},St) ->
+ H1 = pattern(H0,St),
+ T1 = pattern(T0,St),
+ {cons,Line,H1,T1};
+pattern({tuple,Line,Ps0},St) ->
+ Ps1 = pattern_list(Ps0,St),
+ {tuple,Line,Ps1};
+pattern({bin,Line,Fs},St) ->
+ Fs2 = pattern_grp(Fs,St),
+ {bin,Line,Fs2};
+pattern({op,_Line,'++',{nil,_},R},St) ->
+ pattern(R,St);
+pattern({op,_Line,'++',{cons,Li,{char,C2,I},T},R},St) ->
+ pattern({cons,Li,{char,C2,I},{op,Li,'++',T,R}},St);
+pattern({op,_Line,'++',{cons,Li,{integer,L2,I},T},R},St) ->
+ pattern({cons,Li,{integer,L2,I},{op,Li,'++',T,R}},St);
+pattern({op,_Line,'++',{string,Li,L},R},St) ->
+ pattern(string_to_conses(L, Li, R),St);
+pattern({op,Line,Op,A},_St) ->
+ {op,Line,Op,A};
+pattern({op,Line,Op,L,R},_St) ->
+ {op,Line,Op,L,R}.
+
+pattern_grp([{bin_element,L1,E1,S1,T1} | Fs],St) ->
+ S2 = case S1 of
+ default ->
+ default;
+ _ ->
+ expr(S1,St)
+ end,
+ T2 = case T1 of
+ default ->
+ default;
+ _ ->
+ bit_types(T1)
+ end,
+ [{bin_element,L1,expr(E1,St),S2,T2} | pattern_grp(Fs,St)];
+pattern_grp([],_St) ->
+ [].
+
+bit_types([]) ->
+ [];
+bit_types([Atom | Rest]) when atom(Atom) ->
+ [Atom | bit_types(Rest)];
+bit_types([{Atom, Integer} | Rest]) when atom(Atom), integer(Integer) ->
+ [{Atom, Integer} | bit_types(Rest)].
+
+pattern_list([P0|Ps],St) ->
+ P1 = pattern(P0,St),
+ [P1|pattern_list(Ps,St)];
+pattern_list([],_St) -> [].
+
+guard([G0|Gs],St) when list(G0) ->
+ [guard0(G0,St) | guard(Gs,St)];
+guard(L,St) ->
+ guard0(L,St).
+
+guard0([G0|Gs],St) ->
+ G1 = guard_test(G0,St),
+ [G1|guard0(Gs,St)];
+guard0([],_St) -> [].
+
+guard_test(Expr={call,Line,{atom,La,F},As0},St) ->
+ case erl_internal:type_test(F, length(As0)) of
+ true ->
+ As1 = gexpr_list(As0,St),
+ {call,Line,{atom,La,F},As1};
+ _ ->
+ gexpr(Expr,St)
+ end;
+guard_test(Any,St) ->
+ gexpr(Any,St).
+
+gexpr({var,L,V},_St) ->
+ {var,L,V};
+% %% alternative implementation of accessing module parameters
+% case index(V,St#pmod.parameters) of
+% N when N > 0 ->
+% {call,L,{remote,L,{atom,L,erlang},{atom,L,element}},
+% [{integer,L,N+1},{var,L,'THIS'}]};
+% _ ->
+% {var,L,V}
+% end;
+gexpr({integer,Line,I},_St) -> {integer,Line,I};
+gexpr({char,Line,C},_St) -> {char,Line,C};
+gexpr({float,Line,F},_St) -> {float,Line,F};
+gexpr({atom,Line,A},_St) -> {atom,Line,A};
+gexpr({string,Line,S},_St) -> {string,Line,S};
+gexpr({nil,Line},_St) -> {nil,Line};
+gexpr({cons,Line,H0,T0},St) ->
+ H1 = gexpr(H0,St),
+ T1 = gexpr(T0,St),
+ {cons,Line,H1,T1};
+gexpr({tuple,Line,Es0},St) ->
+ Es1 = gexpr_list(Es0,St),
+ {tuple,Line,Es1};
+gexpr({call,Line,{atom,La,F},As0},St) ->
+ case erl_internal:guard_bif(F, length(As0)) of
+ true -> As1 = gexpr_list(As0,St),
+ {call,Line,{atom,La,F},As1}
+ end;
+% Pre-expansion generated calls to erlang:is_record/3 must also be handled
+gexpr({call,Line,{remote,La,{atom,Lb,erlang},{atom,Lc,is_record}},As0},St)
+ when length(As0) == 3 ->
+ As1 = gexpr_list(As0,St),
+ {call,Line,{remote,La,{atom,Lb,erlang},{atom,Lc,is_record}},As1};
+% Guard bif's can be remote, but only in the module erlang...
+gexpr({call,Line,{remote,La,{atom,Lb,erlang},{atom,Lc,F}},As0},St) ->
+ case erl_internal:guard_bif(F, length(As0)) or
+ erl_internal:arith_op(F, length(As0)) or
+ erl_internal:comp_op(F, length(As0)) or
+ erl_internal:bool_op(F, length(As0)) of
+ true -> As1 = gexpr_list(As0,St),
+ {call,Line,{remote,La,{atom,Lb,erlang},{atom,Lc,F}},As1}
+ end;
+% Unfortunately, writing calls as {M,F}(...) is also allowed.
+gexpr({call,Line,{tuple,La,[{atom,Lb,erlang},{atom,Lc,F}]},As0},St) ->
+ case erl_internal:guard_bif(F, length(As0)) or
+ erl_internal:arith_op(F, length(As0)) or
+ erl_internal:comp_op(F, length(As0)) or
+ erl_internal:bool_op(F, length(As0)) of
+ true -> As1 = gexpr_list(As0,St),
+ {call,Line,{tuple,La,[{atom,Lb,erlang},{atom,Lc,F}]},As1}
+ end;
+gexpr({bin,Line,Fs},St) ->
+ Fs2 = pattern_grp(Fs,St),
+ {bin,Line,Fs2};
+gexpr({op,Line,Op,A0},St) ->
+ case erl_internal:arith_op(Op, 1) or
+ erl_internal:bool_op(Op, 1) of
+ true -> A1 = gexpr(A0,St),
+ {op,Line,Op,A1}
+ end;
+gexpr({op,Line,Op,L0,R0},St) ->
+ case erl_internal:arith_op(Op, 2) or
+ erl_internal:bool_op(Op, 2) or
+ erl_internal:comp_op(Op, 2) of
+ true ->
+ L1 = gexpr(L0,St),
+ R1 = gexpr(R0,St),
+ {op,Line,Op,L1,R1}
+ end.
+
+gexpr_list([E0|Es],St) ->
+ E1 = gexpr(E0,St),
+ [E1|gexpr_list(Es,St)];
+gexpr_list([],_St) -> [].
+
+exprs([E0|Es],St) ->
+ E1 = expr(E0,St),
+ [E1|exprs(Es,St)];
+exprs([],_St) -> [].
+
+expr({var,L,V},_St) ->
+ {var,L,V};
+% case index(V,St#pmod.parameters) of
+% N when N > 0 ->
+% {call,L,{remote,L,{atom,L,erlang},{atom,L,element}},
+% [{integer,L,N+1},{var,L,'THIS'}]};
+% _ ->
+% {var,L,V}
+% end;
+expr({integer,Line,I},_St) -> {integer,Line,I};
+expr({float,Line,F},_St) -> {float,Line,F};
+expr({atom,Line,A},_St) -> {atom,Line,A};
+expr({string,Line,S},_St) -> {string,Line,S};
+expr({char,Line,C},_St) -> {char,Line,C};
+expr({nil,Line},_St) -> {nil,Line};
+expr({cons,Line,H0,T0},St) ->
+ H1 = expr(H0,St),
+ T1 = expr(T0,St),
+ {cons,Line,H1,T1};
+expr({lc,Line,E0,Qs0},St) ->
+ Qs1 = lc_quals(Qs0,St),
+ E1 = expr(E0,St),
+ {lc,Line,E1,Qs1};
+expr({tuple,Line,Es0},St) ->
+ Es1 = expr_list(Es0,St),
+ {tuple,Line,Es1};
+expr({block,Line,Es0},St) ->
+ Es1 = exprs(Es0,St),
+ {block,Line,Es1};
+expr({'if',Line,Cs0},St) ->
+ Cs1 = icr_clauses(Cs0,St),
+ {'if',Line,Cs1};
+expr({'case',Line,E0,Cs0},St) ->
+ E1 = expr(E0,St),
+ Cs1 = icr_clauses(Cs0,St),
+ {'case',Line,E1,Cs1};
+expr({'receive',Line,Cs0},St) ->
+ Cs1 = icr_clauses(Cs0,St),
+ {'receive',Line,Cs1};
+expr({'receive',Line,Cs0,To0,ToEs0},St) ->
+ To1 = expr(To0,St),
+ ToEs1 = exprs(ToEs0,St),
+ Cs1 = icr_clauses(Cs0,St),
+ {'receive',Line,Cs1,To1,ToEs1};
+expr({'try',Line,Es0,Scs0,Ccs0,As0},St) ->
+ Es1 = exprs(Es0,St),
+ Scs1 = icr_clauses(Scs0,St),
+ Ccs1 = icr_clauses(Ccs0,St),
+ As1 = exprs(As0,St),
+ {'try',Line,Es1,Scs1,Ccs1,As1};
+expr({'fun',Line,Body,Info},St) ->
+ case Body of
+ {clauses,Cs0} ->
+ Cs1 = fun_clauses(Cs0,St),
+ {'fun',Line,{clauses,Cs1},Info};
+ {function,F,A} ->
+ {F1,A1} = update_function_name({F,A},St),
+ if A1 == A ->
+ {'fun',Line,{function,F,A},Info};
+ true ->
+ %% Must rewrite local fun-name to a fun that does a
+ %% call with the extra THIS parameter.
+ As = make_vars(A, Line),
+ As1 = As ++ [{var,Line,'THIS'}],
+ Call = {call,Line,{atom,Line,F1},As1},
+ Cs = [{clause,Line,As,[],[Call]}],
+ {'fun',Line,{clauses,Cs},Info}
+ end;
+ {function,M,F,A} -> %This is an error in lint!
+ {'fun',Line,{function,M,F,A},Info}
+ end;
+expr({call,Lc,{atom,_,new}=Name,As0},#pmod{parameters=Ps}=St)
+ when length(As0) =:= length(Ps) ->
+ %% The new() function does not take a 'THIS' argument (it's static).
+ As1 = expr_list(As0,St),
+ {call,Lc,Name,As1};
+expr({call,Lc,{atom,_,module_info}=Name,As0},St)
+ when length(As0) == 0; length(As0) == 1 ->
+ %% The module_info/0 and module_info/1 functions are also static.
+ As1 = expr_list(As0,St),
+ {call,Lc,Name,As1};
+expr({call,Lc,{atom,Lf,F},As0},St) ->
+ %% Local function call - needs THIS parameter.
+ As1 = expr_list(As0,St),
+ {call,Lc,{atom,Lf,F},As1 ++ [{var,0,'THIS'}]};
+expr({call,Line,F0,As0},St) ->
+ %% Other function call
+ F1 = expr(F0,St),
+ As1 = expr_list(As0,St),
+ {call,Line,F1,As1};
+expr({'catch',Line,E0},St) ->
+ E1 = expr(E0,St),
+ {'catch',Line,E1};
+expr({match,Line,P0,E0},St) ->
+ E1 = expr(E0,St),
+ P1 = pattern(P0,St),
+ {match,Line,P1,E1};
+expr({bin,Line,Fs},St) ->
+ Fs2 = pattern_grp(Fs,St),
+ {bin,Line,Fs2};
+expr({op,Line,Op,A0},St) ->
+ A1 = expr(A0,St),
+ {op,Line,Op,A1};
+expr({op,Line,Op,L0,R0},St) ->
+ L1 = expr(L0,St),
+ R1 = expr(R0,St),
+ {op,Line,Op,L1,R1};
+%% The following are not allowed to occur anywhere!
+expr({remote,Line,M0,F0},St) ->
+ M1 = expr(M0,St),
+ F1 = expr(F0,St),
+ {remote,Line,M1,F1}.
+
+expr_list([E0|Es],St) ->
+ E1 = expr(E0,St),
+ [E1|expr_list(Es,St)];
+expr_list([],_St) -> [].
+
+icr_clauses([C0|Cs],St) ->
+ C1 = clause(C0,St),
+ [C1|icr_clauses(Cs,St)];
+icr_clauses([],_St) -> [].
+
+lc_quals([{generate,Line,P0,E0}|Qs],St) ->
+ E1 = expr(E0,St),
+ P1 = pattern(P0,St),
+ [{generate,Line,P1,E1}|lc_quals(Qs,St)];
+lc_quals([E0|Qs],St) ->
+ E1 = expr(E0,St),
+ [E1|lc_quals(Qs,St)];
+lc_quals([],_St) -> [].
+
+fun_clauses([C0|Cs],St) ->
+ C1 = clause(C0,St),
+ [C1|fun_clauses(Cs,St)];
+fun_clauses([],_St) -> [].
+
+% %% Return index from 1 upwards, or 0 if not in the list.
+%
+% index(X,Ys) -> index(X,Ys,1).
+%
+% index(X,[X|Ys],A) -> A;
+% index(X,[Y|Ys],A) -> index(X,Ys,A+1);
+% index(X,[],A) -> 0.
+
+make_vars(N, L) ->
+ make_vars(1, N, L).
+
+make_vars(N, M, L) when N =< M ->
+ V = list_to_atom("X"++integer_to_list(N)),
+ [{var,L,V} | make_vars(N + 1, M, L)];
+make_vars(_, _, _) ->
+ [].
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/sys_pre_attributes.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/sys_pre_attributes.erl
new file mode 100644
index 0000000000..21d28868f0
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/sys_pre_attributes.erl
@@ -0,0 +1,212 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: sys_pre_attributes.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
+%%
+%% Purpose : Transform Erlang compiler attributes
+
+-module(sys_pre_attributes).
+
+-export([parse_transform/2]).
+
+-define(OPTION_TAG, attributes).
+
+-record(state, {forms,
+ pre_ops = [],
+ post_ops = [],
+ options}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Inserts, deletes and replaces Erlang compiler attributes.
+%%
+%% Valid options are:
+%%
+%% {attribute, insert, AttrName, NewAttrVal}
+%% {attribute, replace, AttrName, NewAttrVal} % replace first occurrence
+%% {attribute, delete, AttrName}
+%%
+%% The transformation is performed in two passes:
+%%
+%% pre_transform
+%% -------------
+%% Searches for attributes in the list of Forms in order to
+%% delete or replace them. 'delete' will delete all occurrences
+%% of attributes with the given name. 'replace' will replace the
+%% first occurrence of the attribute. This pass is will only be
+%% performed if there are replace or delete operations stated
+%% as options.
+%%
+%% post_transform
+%% -------------
+%% Looks up the module attribute and inserts the new attributes
+%% directly after. This pass will only be performed if there are
+%% any attributes left to be inserted after pre_transform. The left
+%% overs will be those replace operations that not has been performed
+%% due to that the pre_transform pass did not find the attribute plus
+%% all insert operations.
+
+parse_transform(Forms, Options) ->
+ S = #state{forms = Forms, options = Options},
+ S2 = init_transform(S),
+ report_verbose("Pre options: ~p~n", [S2#state.pre_ops], S2),
+ report_verbose("Post options: ~p~n", [S2#state.post_ops], S2),
+ S3 = pre_transform(S2),
+ S4 = post_transform(S3),
+ S4#state.forms.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Computes the lists of pre_ops and post_ops that are
+%% used in the real transformation.
+init_transform(S) ->
+ case S#state.options of
+ Options when list(Options) ->
+ init_transform(Options, S);
+ Option ->
+ init_transform([Option], S)
+ end.
+
+init_transform([{attribute, insert, Name, Val} | Tail], S) ->
+ Op = {insert, Name, Val},
+ PostOps = [Op | S#state.post_ops],
+ init_transform(Tail, S#state{post_ops = PostOps});
+init_transform([{attribute, replace, Name, Val} | Tail], S) ->
+ Op = {replace, Name, Val},
+ PreOps = [Op | S#state.pre_ops],
+ PostOps = [Op | S#state.post_ops],
+ init_transform(Tail, S#state{pre_ops = PreOps, post_ops = PostOps});
+init_transform([{attribute, delete, Name} | Tail], S) ->
+ Op = {delete, Name},
+ PreOps = [Op | S#state.pre_ops],
+ init_transform(Tail, S#state{pre_ops = PreOps});
+init_transform([], S) ->
+ S;
+init_transform([_ | T], S) ->
+ init_transform(T, S);
+init_transform(BadOpt, S) ->
+ report_error("Illegal option (ignored): ~p~n", [BadOpt], S),
+ S.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Handle delete and perhaps replace
+
+pre_transform(S) when S#state.pre_ops == [] ->
+ S;
+pre_transform(S) ->
+ pre_transform(S#state.forms, [], S).
+
+pre_transform([H | T], Acc, S) ->
+ case H of
+ {attribute, Line, Name, Val} ->
+ case lists:keysearch(Name, 2, S#state.pre_ops) of
+ false ->
+ pre_transform(T, [H | Acc], S);
+
+ {value, {replace, Name, NewVal}} ->
+ report_warning("Replace attribute ~p: ~p -> ~p~n",
+ [Name, Val, NewVal],
+ S),
+ New = {attribute, Line, Name, NewVal},
+ Pre = lists:keydelete(Name, 2, S#state.pre_ops),
+ Post = lists:keydelete(Name, 2, S#state.post_ops),
+ S2 = S#state{pre_ops = Pre, post_ops = Post},
+ if
+ Pre == [] ->
+ %% No need to search the rest of the Forms
+ Forms = lists:reverse(Acc, [New | T]),
+ S2#state{forms = Forms};
+ true ->
+ pre_transform(T, [New | Acc], S2)
+ end;
+
+ {value, {delete, Name}} ->
+ report_warning("Delete attribute ~p: ~p~n",
+ [Name, Val],
+ S),
+ pre_transform(T, Acc, S)
+ end;
+ _Any ->
+ pre_transform(T, [H | Acc], S)
+ end;
+pre_transform([], Acc, S) ->
+ S#state{forms = lists:reverse(Acc)}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Handle insert and perhaps replace
+
+post_transform(S) when S#state.post_ops == [] ->
+ S;
+post_transform(S) ->
+ post_transform(S#state.forms, [], S).
+
+post_transform([H | T], Acc, S) ->
+ case H of
+ {attribute, Line, module, Val} ->
+ Acc2 = lists:reverse([{attribute, Line, module, Val} | Acc]),
+ Forms = Acc2 ++ attrs(S#state.post_ops, Line, S) ++ T,
+ S#state{forms = Forms, post_ops = []};
+ _Any ->
+ post_transform(T, [H | Acc], S)
+ end;
+post_transform([], Acc, S) ->
+ S#state{forms = lists:reverse(Acc)}.
+
+attrs([{replace, Name, NewVal} | T], Line, S) ->
+ report_verbose("Insert attribute ~p: ~p~n", [Name, NewVal], S),
+ [{attribute, Line, Name, NewVal} | attrs(T, Line, S)];
+attrs([{insert, Name, NewVal} | T], Line, S) ->
+ report_verbose("Insert attribute ~p: ~p~n", [Name, NewVal], S),
+ [{attribute, Line, Name, NewVal} | attrs(T, Line, S)];
+attrs([], _, _) ->
+ [].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Report functions.
+%%
+%% Errors messages are controlled with the 'report_errors' compiler option
+%% Warning messages are controlled with the 'report_warnings' compiler option
+%% Verbose messages are controlled with the 'verbose' compiler option
+
+report_error(Format, Args, S) ->
+ case is_error(S) of
+ true ->
+ io:format("~p: * ERROR * " ++ Format, [?MODULE | Args]);
+ false ->
+ ok
+ end.
+
+report_warning(Format, Args, S) ->
+ case is_warning(S) of
+ true ->
+ io:format("~p: * WARNING * " ++ Format, [?MODULE | Args]);
+ false ->
+ ok
+ end.
+
+report_verbose(Format, Args, S) ->
+ case is_verbose(S) of
+ true ->
+ io:format("~p: " ++ Format, [?MODULE | Args]);
+ false ->
+ ok
+ end.
+
+is_error(S) ->
+ lists:member(report_errors, S#state.options) or is_verbose(S).
+
+is_warning(S) ->
+ lists:member(report_warnings, S#state.options) or is_verbose(S).
+
+is_verbose(S) ->
+ lists:member(verbose, S#state.options).
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/sys_pre_expand.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/sys_pre_expand.erl
new file mode 100644
index 0000000000..08bc6cb147
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/sys_pre_expand.erl
@@ -0,0 +1,1026 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: sys_pre_expand.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
+%%
+%% Purpose : Expand some source Erlang constructions. This is part of the
+%% pre-processing phase.
+
+%% N.B. Although structs (tagged tuples) are not yet allowed in the
+%% language there is code included in pattern/2 and expr/3 (commented out)
+%% that handles them by transforming them to tuples.
+
+-module(sys_pre_expand).
+
+%% Main entry point.
+-export([module/2]).
+
+-import(ordsets, [from_list/1,add_element/2,
+ union/1,union/2,intersection/1,intersection/2,subtract/2]).
+-import(lists, [member/2,map/2,foldl/3,foldr/3,sort/1,reverse/1,duplicate/2]).
+
+-include("../my_include/erl_bits.hrl").
+
+-record(expand, {module=[], %Module name
+ parameters=undefined, %Module parameters
+ package="", %Module package
+ exports=[], %Exports
+ imports=[], %Imports
+ mod_imports, %Module Imports
+ compile=[], %Compile flags
+ records=dict:new(), %Record definitions
+ attributes=[], %Attributes
+ defined=[], %Defined functions
+ vcount=0, %Variable counter
+ func=[], %Current function
+ arity=[], %Arity for current function
+ fcount=0, %Local fun count
+ fun_index=0, %Global index for funs
+ bitdefault,
+ bittypes
+ }).
+
+%% module(Forms, CompileOptions)
+%% {ModuleName,Exports,TransformedForms}
+%% Expand the forms in one module. N.B.: the lists of predefined
+%% exports and imports are really ordsets!
+
+module(Fs, Opts) ->
+ %% Set pre-defined exported functions.
+ PreExp = [{module_info,0},{module_info,1}],
+
+ %% Set pre-defined module imports.
+ PreModImp = [{erlang,erlang},{packages,packages}],
+
+ %% Build initial expand record.
+ St0 = #expand{exports=PreExp,
+ mod_imports=dict:from_list(PreModImp),
+ compile=Opts,
+ defined=PreExp,
+ bitdefault = erl_bits:system_bitdefault(),
+ bittypes = erl_bits:system_bittypes()
+ },
+ %% Expand the functions.
+ {Tfs,St1} = forms(Fs, foldl(fun define_function/2, St0, Fs)),
+ {Efs,St2} = expand_pmod(Tfs, St1),
+ %% Get the correct list of exported functions.
+ Exports = case member(export_all, St2#expand.compile) of
+ true -> St2#expand.defined;
+ false -> St2#expand.exports
+ end,
+ %% Generate all functions from stored info.
+ {Ats,St3} = module_attrs(St2#expand{exports = Exports}),
+ {Mfs,St4} = module_predef_funcs(St3),
+ {St4#expand.module, St4#expand.exports, Ats ++ Efs ++ Mfs,
+ St4#expand.compile}.
+
+expand_pmod(Fs0, St) ->
+ case St#expand.parameters of
+ undefined ->
+ {Fs0,St};
+ Ps ->
+ {Fs1,Xs,Ds} = sys_expand_pmod:forms(Fs0, Ps,
+ St#expand.exports,
+ St#expand.defined),
+ A = length(Ps),
+ Vs = [{var,0,V} || V <- Ps],
+ N = {atom,0,St#expand.module},
+ B = [{tuple,0,[N|Vs]}],
+ F = {function,0,new,A,[{clause,0,Vs,[],B}]},
+ As = St#expand.attributes,
+ {[F|Fs1],St#expand{exports=add_element({new,A}, Xs),
+ defined=add_element({new,A}, Ds),
+ attributes = [{abstract, true} | As]}}
+ end.
+
+%% -type define_function(Form, State) -> State.
+%% Add function to defined if form a function.
+
+define_function({function,_,N,A,_Cs}, St) ->
+ St#expand{defined=add_element({N,A}, St#expand.defined)};
+define_function(_, St) -> St.
+
+module_attrs(St) ->
+ {[{attribute,0,Name,Val} || {Name,Val} <- St#expand.attributes],St}.
+
+module_predef_funcs(St) ->
+ PreDef = [{module_info,0},{module_info,1}],
+ PreExp = PreDef,
+ {[{function,0,module_info,0,
+ [{clause,0,[],[],
+ [{call,0,{remote,0,{atom,0,erlang},{atom,0,get_module_info}},
+ [{atom,0,St#expand.module}]}]}]},
+ {function,0,module_info,1,
+ [{clause,0,[{var,0,'X'}],[],
+ [{call,0,{remote,0,{atom,0,erlang},{atom,0,get_module_info}},
+ [{atom,0,St#expand.module},{var,0,'X'}]}]}]}],
+ St#expand{defined=union(from_list(PreDef), St#expand.defined),
+ exports=union(from_list(PreExp), St#expand.exports)}}.
+
+%% forms(Forms, State) ->
+%% {TransformedForms,State'}
+%% Process the forms. Attributes are lost and just affect the state.
+%% Ignore uninteresting forms like eof and type.
+
+forms([{attribute,_,Name,Val}|Fs0], St0) ->
+ St1 = attribute(Name, Val, St0),
+ forms(Fs0, St1);
+forms([{function,L,N,A,Cs}|Fs0], St0) ->
+ {Ff,St1} = function(L, N, A, Cs, St0),
+ {Fs,St2} = forms(Fs0, St1),
+ {[Ff|Fs],St2};
+forms([_|Fs], St) -> forms(Fs, St);
+forms([], St) -> {[],St}.
+
+%% -type attribute(Attribute, Value, State) ->
+%% State.
+%% Process an attribute, this just affects the state.
+
+attribute(module, {Module, As}, St) ->
+ M = package_to_string(Module),
+ St#expand{module=list_to_atom(M),
+ package = packages:strip_last(M),
+ parameters=As};
+attribute(module, Module, St) ->
+ M = package_to_string(Module),
+ St#expand{module=list_to_atom(M),
+ package = packages:strip_last(M)};
+attribute(export, Es, St) ->
+ St#expand{exports=union(from_list(Es), St#expand.exports)};
+attribute(import, Is, St) ->
+ import(Is, St);
+attribute(compile, C, St) when list(C) ->
+ St#expand{compile=St#expand.compile ++ C};
+attribute(compile, C, St) ->
+ St#expand{compile=St#expand.compile ++ [C]};
+attribute(record, {Name,Defs}, St) ->
+ St#expand{records=dict:store(Name, normalise_fields(Defs),
+ St#expand.records)};
+attribute(file, _File, St) -> St; %This is ignored
+attribute(Name, Val, St) when list(Val) ->
+ St#expand{attributes=St#expand.attributes ++ [{Name,Val}]};
+attribute(Name, Val, St) ->
+ St#expand{attributes=St#expand.attributes ++ [{Name,[Val]}]}.
+
+function(L, N, A, Cs0, St0) ->
+ {Cs,St} = clauses(Cs0, St0#expand{func=N,arity=A,fcount=0}),
+ {{function,L,N,A,Cs},St}.
+
+%% -type clauses([Clause], State) ->
+%% {[TransformedClause],State}.
+%% Expand function clauses.
+
+clauses([{clause,Line,H0,G0,B0}|Cs0], St0) ->
+ {H,Hvs,_Hus,St1} = head(H0, St0),
+ {G,Gvs,_Gus,St2} = guard(G0, Hvs, St1),
+ {B,_Bvs,_Bus,St3} = exprs(B0, union(Hvs, Gvs), St2),
+ {Cs,St4} = clauses(Cs0, St3),
+ {[{clause,Line,H,G,B}|Cs],St4};
+clauses([], St) -> {[],St}.
+
+%% head(HeadPatterns, State) ->
+%% {TransformedPatterns,Variables,UsedVariables,State'}
+
+head(As, St) -> pattern_list(As, St).
+
+%% pattern(Pattern, State) ->
+%% {TransformedPattern,Variables,UsedVariables,State'}
+%% BITS: added used variables for bit patterns with varaible length
+%%
+
+pattern({var,_,'_'}=Var, St) -> %Ignore anonymous variable.
+ {Var,[],[],St};
+pattern({var,_,V}=Var, St) ->
+ {Var,[V],[],St};
+pattern({char,_,_}=Char, St) ->
+ {Char,[],[],St};
+pattern({integer,_,_}=Int, St) ->
+ {Int,[],[],St};
+pattern({float,_,_}=Float, St) ->
+ {Float,[],[],St};
+pattern({atom,_,_}=Atom, St) ->
+ {Atom,[],[],St};
+pattern({string,_,_}=String, St) ->
+ {String,[],[],St};
+pattern({nil,_}=Nil, St) ->
+ {Nil,[],[],St};
+pattern({cons,Line,H,T}, St0) ->
+ {TH,THvs,Hus,St1} = pattern(H, St0),
+ {TT,TTvs,Tus,St2} = pattern(T, St1),
+ {{cons,Line,TH,TT},union(THvs, TTvs),union(Hus,Tus),St2};
+pattern({tuple,Line,Ps}, St0) ->
+ {TPs,TPsvs,Tus,St1} = pattern_list(Ps, St0),
+ {{tuple,Line,TPs},TPsvs,Tus,St1};
+%%pattern({struct,Line,Tag,Ps}, St0) ->
+%% {TPs,TPsvs,St1} = pattern_list(Ps, St0),
+%% {{tuple,Line,[{atom,Line,Tag}|TPs]},TPsvs,St1};
+pattern({record_field,_,_,_}=M, St) ->
+ {expand_package(M, St), [], [], St}; % must be a package name
+pattern({record_index,Line,Name,Field}, St) ->
+ {index_expr(Line, Field, Name, record_fields(Name, St)),[],[],St};
+pattern({record,Line,Name,Pfs}, St0) ->
+ Fs = record_fields(Name, St0),
+ {TMs,TMsvs,Us,St1} = pattern_list(pattern_fields(Fs, Pfs), St0),
+ {{tuple,Line,[{atom,Line,Name}|TMs]},TMsvs,Us,St1};
+pattern({bin,Line,Es0}, St0) ->
+ {Es1,Esvs,Esus,St1} = pattern_bin(Es0, St0),
+ {{bin,Line,Es1},Esvs,Esus,St1};
+pattern({op,_,'++',{nil,_},R}, St) ->
+ pattern(R, St);
+pattern({op,_,'++',{cons,Li,H,T},R}, St) ->
+ pattern({cons,Li,H,{op,Li,'++',T,R}}, St);
+pattern({op,_,'++',{string,Li,L},R}, St) ->
+ pattern(string_to_conses(Li, L, R), St);
+pattern({match,Line,Pat1, Pat2}, St0) ->
+ {TH,Hvt,Hus,St1} = pattern(Pat2, St0),
+ {TT,Tvt,Tus,St2} = pattern(Pat1, St1),
+ {{match,Line,TT,TH}, union(Hvt,Tvt), union(Hus,Tus), St2};
+%% Compile-time pattern expressions, including unary operators.
+pattern({op,Line,Op,A}, St) ->
+ { erl_eval:partial_eval({op,Line,Op,A}), [], [], St};
+pattern({op,Line,Op,L,R}, St) ->
+ { erl_eval:partial_eval({op,Line,Op,L,R}), [], [], St}.
+
+pattern_list([P0|Ps0], St0) ->
+ {P,Pvs,Pus,St1} = pattern(P0, St0),
+ {Ps,Psvs,Psus,St2} = pattern_list(Ps0, St1),
+ {[P|Ps],union(Pvs, Psvs),union(Pus, Psus),St2};
+pattern_list([], St) -> {[],[],[],St}.
+
+%% guard(Guard, VisibleVariables, State) ->
+%% {TransformedGuard,NewVariables,UsedVariables,State'}
+%% Transform a list of guard tests. We KNOW that this has been checked
+%% and what the guards test are. Use expr for transforming the guard
+%% expressions.
+
+guard([G0|Gs0], Vs, St0) ->
+ {G,Hvs,Hus,St1} = guard_tests(G0, Vs, St0),
+ {Gs,Tvs,Tus,St2} = guard(Gs0, Vs, St1),
+ {[G|Gs],union(Hvs, Tvs),union(Hus, Tus),St2};
+guard([], _, St) -> {[],[],[],St}.
+
+guard_tests([Gt0|Gts0], Vs, St0) ->
+ {Gt1,Gvs,Gus,St1} = guard_test(Gt0, Vs, St0),
+ {Gts1,Gsvs,Gsus,St2} = guard_tests(Gts0, union(Gvs, Vs), St1),
+ {[Gt1|Gts1],union(Gvs, Gsvs),union(Gus, Gsus),St2};
+guard_tests([], _, St) -> {[],[],[],St}.
+
+guard_test({call,Line,{atom,_,record},[A,{atom,_,Name}]}, Vs, St) ->
+ record_test_in_guard(Line, A, Name, Vs, St);
+guard_test({call,Line,{atom,Lt,Tname},As}, Vs, St) ->
+ %% XXX This is ugly. We can remove this workaround if/when
+ %% we'll allow 'andalso' in guards. For now, we must have
+ %% different code in guards and in bodies.
+ Test = {remote,Lt,
+ {atom,Lt,erlang},
+ {atom,Lt,normalise_test(Tname, length(As))}},
+ put(sys_pre_expand_in_guard, yes),
+ R = expr({call,Line,Test,As}, Vs, St),
+ erase(sys_pre_expand_in_guard),
+ R;
+guard_test(Test, Vs, St) ->
+ %% XXX See the previous clause.
+ put(sys_pre_expand_in_guard, yes),
+ R = expr(Test, Vs, St),
+ erase(sys_pre_expand_in_guard),
+ R.
+
+%% record_test(Line, Term, Name, Vs, St) -> TransformedExpr
+%% Generate code for is_record/1.
+
+record_test(Line, Term, Name, Vs, St) ->
+ case get(sys_pre_expand_in_guard) of
+ undefined ->
+ record_test_in_body(Line, Term, Name, Vs, St);
+ yes ->
+ record_test_in_guard(Line, Term, Name, Vs, St)
+ end.
+
+record_test_in_guard(Line, Term, Name, Vs, St) ->
+ %% Notes: (1) To keep is_record/3 properly atomic (e.g. when inverted
+ %% using 'not'), we cannot convert it to an instruction
+ %% sequence here. It must remain a single call.
+ %% (2) Later passes assume that the last argument (the size)
+ %% is a literal.
+ %% (3) We don't want calls to erlang:is_record/3 (in the source code)
+ %% confused we the internal instruction. (Reason: (2) above +
+ %% code bloat.)
+ %% (4) Xref may be run on the abstract code, so the name in the
+ %% abstract code must be erlang:is_record/3.
+ %% (5) To achive both (3) and (4) at the same time, set the name
+ %% here to erlang:is_record/3, but mark it as compiler-generated.
+ %% The v3_core pass will change the name to erlang:internal_is_record/3.
+ Fs = record_fields(Name, St),
+ expr({call,-Line,{remote,-Line,{atom,-Line,erlang},{atom,-Line,is_record}},
+ [Term,{atom,Line,Name},{integer,Line,length(Fs)+1}]},
+ Vs, St).
+
+record_test_in_body(Line, Expr, Name, Vs, St0) ->
+ %% As Expr may have side effects, we must evaluate it
+ %% first and bind the value to a new variable.
+ %% We must use also handle the case that Expr does not
+ %% evaluate to a tuple properly.
+ Fs = record_fields(Name, St0),
+ {Var,St} = new_var(Line, St0),
+
+ expr({block,Line,
+ [{match,Line,Var,Expr},
+ {op,Line,
+ 'andalso',
+ {call,Line,{atom,Line,is_tuple},[Var]},
+ {op,Line,'andalso',
+ {op,Line,'=:=',
+ {call,Line,{atom,Line,size},[Var]},
+ {integer,Line,length(Fs)+1}},
+ {op,Line,'=:=',
+ {call,Line,{atom,Line,element},[{integer,Line,1},Var]},
+ {atom,Line,Name}}}}]}, Vs, St).
+
+normalise_test(atom, 1) -> is_atom;
+normalise_test(binary, 1) -> is_binary;
+normalise_test(constant, 1) -> is_constant;
+normalise_test(float, 1) -> is_float;
+normalise_test(function, 1) -> is_function;
+normalise_test(integer, 1) -> is_integer;
+normalise_test(list, 1) -> is_list;
+normalise_test(number, 1) -> is_number;
+normalise_test(pid, 1) -> is_pid;
+normalise_test(port, 1) -> is_port;
+normalise_test(reference, 1) -> is_reference;
+normalise_test(tuple, 1) -> is_tuple;
+normalise_test(Name, _) -> Name.
+
+%% exprs(Expressions, VisibleVariables, State) ->
+%% {TransformedExprs,NewVariables,UsedVariables,State'}
+
+exprs([E0|Es0], Vs, St0) ->
+ {E,Evs,Eus,St1} = expr(E0, Vs, St0),
+ {Es,Esvs,Esus,St2} = exprs(Es0, union(Evs, Vs), St1),
+ {[E|Es],union(Evs, Esvs),union(Eus, Esus),St2};
+exprs([], _, St) -> {[],[],[],St}.
+
+%% expr(Expression, VisibleVariables, State) ->
+%% {TransformedExpression,NewVariables,UsedVariables,State'}
+
+expr({var,_,V}=Var, _Vs, St) ->
+ {Var,[],[V],St};
+expr({char,_,_}=Char, _Vs, St) ->
+ {Char,[],[],St};
+expr({integer,_,_}=Int, _Vs, St) ->
+ {Int,[],[],St};
+expr({float,_,_}=Float, _Vs, St) ->
+ {Float,[],[],St};
+expr({atom,_,_}=Atom, _Vs, St) ->
+ {Atom,[],[],St};
+expr({string,_,_}=String, _Vs, St) ->
+ {String,[],[],St};
+expr({nil,_}=Nil, _Vs, St) ->
+ {Nil,[],[],St};
+expr({cons,Line,H0,T0}, Vs, St0) ->
+ {H,Hvs,Hus,St1} = expr(H0, Vs, St0),
+ {T,Tvs,Tus,St2} = expr(T0, Vs, St1),
+ {{cons,Line,H,T},union(Hvs, Tvs),union(Hus, Tus),St2};
+expr({lc,Line,E0,Qs0}, Vs, St0) ->
+ {E1,Qs1,_,Lvs,Lus,St1} = lc_tq(Line, E0, Qs0, {nil,Line}, Vs, St0),
+ {{lc,Line,E1,Qs1},Lvs,Lus,St1};
+expr({tuple,Line,Es0}, Vs, St0) ->
+ {Es1,Esvs,Esus,St1} = expr_list(Es0, Vs, St0),
+ {{tuple,Line,Es1},Esvs,Esus,St1};
+%%expr({struct,Line,Tag,Es0}, Vs, St0) ->
+%% {Es1,Esvs,Esus,St1} = expr_list(Es0, Vs, St0),
+%% {{tuple,Line,[{atom,Line,Tag}|Es1]},Esvs,Esus,St1};
+expr({record_field,_,_,_}=M, _Vs, St) ->
+ {expand_package(M, St), [], [], St}; % must be a package name
+expr({record_index,Line,Name,F}, Vs, St) ->
+ I = index_expr(Line, F, Name, record_fields(Name, St)),
+ expr(I, Vs, St);
+expr({record,Line,Name,Is}, Vs, St) ->
+ expr({tuple,Line,[{atom,Line,Name}|
+ record_inits(record_fields(Name, St), Is)]},
+ Vs, St);
+expr({record_field,Line,R,Name,F}, Vs, St) ->
+ I = index_expr(Line, F, Name, record_fields(Name, St)),
+ expr({call,Line,{atom,Line,element},[I,R]}, Vs, St);
+expr({record,_,R,Name,Us}, Vs, St0) ->
+ {Ue,St1} = record_update(R, Name, record_fields(Name, St0), Us, St0),
+ expr(Ue, Vs, St1);
+expr({bin,Line,Es0}, Vs, St0) ->
+ {Es1,Esvs,Esus,St1} = expr_bin(Es0, Vs, St0),
+ {{bin,Line,Es1},Esvs,Esus,St1};
+expr({block,Line,Es0}, Vs, St0) ->
+ {Es,Esvs,Esus,St1} = exprs(Es0, Vs, St0),
+ {{block,Line,Es},Esvs,Esus,St1};
+expr({'if',Line,Cs0}, Vs, St0) ->
+ {Cs,Csvss,Csuss,St1} = icr_clauses(Cs0, Vs, St0),
+ All = new_in_all(Vs, Csvss),
+ {{'if',Line,Cs},All,union(Csuss),St1};
+expr({'case',Line,E0,Cs0}, Vs, St0) ->
+ {E,Evs,Eus,St1} = expr(E0, Vs, St0),
+ {Cs,Csvss,Csuss,St2} = icr_clauses(Cs0, union(Evs, Vs), St1),
+ All = new_in_all(Vs, Csvss),
+ {{'case',Line,E,Cs},union(Evs, All),union([Eus|Csuss]),St2};
+expr({'cond',Line,Cs}, Vs, St0) ->
+ {V,St1} = new_var(Line,St0),
+ expr(cond_clauses(Cs,V), Vs, St1);
+expr({'receive',Line,Cs0}, Vs, St0) ->
+ {Cs,Csvss,Csuss,St1} = icr_clauses(Cs0, Vs, St0),
+ All = new_in_all(Vs, Csvss),
+ {{'receive',Line,Cs},All,union(Csuss),St1};
+expr({'receive',Line,Cs0,To0,ToEs0}, Vs, St0) ->
+ {To,Tovs,Tous,St1} = expr(To0, Vs, St0),
+ {ToEs,ToEsvs,_ToEsus,St2} = exprs(ToEs0, Vs, St1),
+ {Cs,Csvss,Csuss,St3} = icr_clauses(Cs0, Vs, St2),
+ All = new_in_all(Vs, [ToEsvs|Csvss]),
+ {{'receive',Line,Cs,To,ToEs},union(Tovs, All),union([Tous|Csuss]),St3};
+expr({'fun',Line,Body}, Vs, St) ->
+ fun_tq(Line, Body, Vs, St);
+%%% expr({call,_,{atom,La,this_module},[]}, _Vs, St) ->
+%%% {{atom,La,St#expand.module}, [], [], St};
+%%% expr({call,_,{atom,La,this_package},[]}, _Vs, St) ->
+%%% {{atom,La,list_to_atom(St#expand.package)}, [], [], St};
+%%% expr({call,_,{atom,La,this_package},[{atom,_,Name}]}, _Vs, St) ->
+%%% M = packages:concat(St#expand.package,Name),
+%%% {{atom,La,list_to_atom(M)}, [], [], St};
+%%% expr({call,Line,{atom,La,this_package},[A]}, Vs, St) ->
+%%% M = {call,Line,{remote,La,{atom,La,packages},{atom,La,concat}},
+%%% [{string,La,St#expand.package}, A]},
+%%% expr({call,Line,{atom,Line,list_to_atom},[M]}, Vs, St);
+expr({call,Line,{atom,_,is_record},[A,{atom,_,Name}]}, Vs, St) ->
+ record_test(Line, A, Name, Vs, St);
+expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,is_record}},
+ [A,{atom,_,Name}]}, Vs, St) ->
+ record_test(Line, A, Name, Vs, St);
+expr({call,Line,{atom,La,N},As0}, Vs, St0) ->
+ {As,Asvs,Asus,St1} = expr_list(As0, Vs, St0),
+ Ar = length(As),
+ case erl_internal:bif(N, Ar) of
+ true ->
+ {{call,Line,{remote,La,{atom,La,erlang},{atom,La,N}},As},
+ Asvs,Asus,St1};
+ false ->
+ case imported(N, Ar, St1) of
+ {yes,Mod} ->
+ {{call,Line,{remote,La,{atom,La,Mod},{atom,La,N}},As},
+ Asvs,Asus,St1};
+ no ->
+ case {N,Ar} of
+ {record_info,2} ->
+ record_info_call(Line, As, St1);
+ _ ->
+ {{call,Line,{atom,La,N},As},Asvs,Asus,St1}
+ end
+ end
+ end;
+expr({call,Line,{record_field,_,_,_}=M,As0}, Vs, St0) ->
+ expr({call,Line,expand_package(M, St0),As0}, Vs, St0);
+expr({call,Line,{remote,Lr,M,F},As0}, Vs, St0) ->
+ M1 = expand_package(M, St0),
+ {[M2,F1|As1],Asvs,Asus,St1} = expr_list([M1,F|As0], Vs, St0),
+ {{call,Line,{remote,Lr,M2,F1},As1},Asvs,Asus,St1};
+expr({call,Line,{tuple,_,[{atom,_,_}=M,{atom,_,_}=F]},As}, Vs, St) ->
+ %% Rewrite {Mod,Function}(Args...) to Mod:Function(Args...).
+ expr({call,Line,{remote,Line,M,F},As}, Vs, St);
+expr({call,Line,F,As0}, Vs, St0) ->
+ {[Fun1|As1],Asvs,Asus,St1} = expr_list([F|As0], Vs, St0),
+ {{call,Line,Fun1,As1},Asvs,Asus,St1};
+expr({'try',Line,Es0,Scs0,Ccs0,As0}, Vs, St0) ->
+ {Es1,Esvs,Esus,St1} = exprs(Es0, Vs, St0),
+ Cvs = union(Esvs, Vs),
+ {Scs1,Scsvss,Scsuss,St2} = icr_clauses(Scs0, Cvs, St1),
+ {Ccs1,Ccsvss,Ccsuss,St3} = icr_clauses(Ccs0, Cvs, St2),
+ Csvss = Scsvss ++ Ccsvss,
+ Csuss = Scsuss ++ Ccsuss,
+ All = new_in_all(Vs, Csvss),
+ {As1,Asvs,Asus,St4} = exprs(As0, Cvs, St3),
+ {{'try',Line,Es1,Scs1,Ccs1,As1}, union([Asvs,Esvs,All]),
+ union([Esus,Asus|Csuss]), St4};
+expr({'catch',Line,E0}, Vs, St0) ->
+ %% Catch exports no new variables.
+ {E,_Evs,Eus,St1} = expr(E0, Vs, St0),
+ {{'catch',Line,E},[],Eus,St1};
+expr({match,Line,P0,E0}, Vs, St0) ->
+ {E,Evs,Eus,St1} = expr(E0, Vs, St0),
+ {P,Pvs,Pus,St2} = pattern(P0, St1),
+ {{match,Line,P,E},
+ union(subtract(Pvs, Vs), Evs),
+ union(intersection(Pvs, Vs), union(Eus,Pus)),St2};
+expr({op,L,'andalso',E1,E2}, Vs, St0) ->
+ {V,St1} = new_var(L,St0),
+ E = make_bool_switch(L,E1,V,
+ make_bool_switch(L,E2,V,{atom,L,true},
+ {atom,L,false}),
+ {atom,L,false}),
+ expr(E, Vs, St1);
+expr({op,L,'orelse',E1,E2}, Vs, St0) ->
+ {V,St1} = new_var(L,St0),
+ E = make_bool_switch(L,E1,V,{atom,L,true},
+ make_bool_switch(L,E2,V,{atom,L,true},
+ {atom,L,false})),
+ expr(E, Vs, St1);
+expr({op,Line,'++',{lc,Ll,E0,Qs0},M0}, Vs, St0) ->
+ {E1,Qs1,M1,Lvs,Lus,St1} = lc_tq(Ll, E0, Qs0, M0, Vs, St0),
+ {{op,Line,'++',{lc,Ll,E1,Qs1},M1},Lvs,Lus,St1};
+expr({op,_,'++',{string,L1,S1},{string,_,S2}}, _Vs, St) ->
+ {{string,L1,S1 ++ S2},[],[],St};
+expr({op,Ll,'++',{string,L1,S1}=Str,R0}, Vs, St0) ->
+ {R1,Rvs,Rus,St1} = expr(R0, Vs, St0),
+ E = case R1 of
+ {string,_,S2} -> {string,L1,S1 ++ S2};
+ _Other when length(S1) < 8 -> string_to_conses(L1, S1, R1);
+ _Other -> {op,Ll,'++',Str,R1}
+ end,
+ {E,Rvs,Rus,St1};
+expr({op,Ll,'++',{cons,Lc,H,T},L2}, Vs, St) ->
+ expr({cons,Ll,H,{op,Lc,'++',T,L2}}, Vs, St);
+expr({op,_,'++',{nil,_},L2}, Vs, St) ->
+ expr(L2, Vs, St);
+expr({op,Line,Op,A0}, Vs, St0) ->
+ {A,Avs,Aus,St1} = expr(A0, Vs, St0),
+ {{op,Line,Op,A},Avs,Aus,St1};
+expr({op,Line,Op,L0,R0}, Vs, St0) ->
+ {L,Lvs,Lus,St1} = expr(L0, Vs, St0),
+ {R,Rvs,Rus,St2} = expr(R0, Vs, St1),
+ {{op,Line,Op,L,R},union(Lvs, Rvs),union(Lus, Rus),St2}.
+
+expr_list([E0|Es0], Vs, St0) ->
+ {E,Evs,Eus,St1} = expr(E0, Vs, St0),
+ {Es,Esvs,Esus,St2} = expr_list(Es0, Vs, St1),
+ {[E|Es],union(Evs, Esvs),union(Eus, Esus),St2};
+expr_list([], _, St) ->
+ {[],[],[],St}.
+
+%% icr_clauses([Clause], [VisibleVariable], State) ->
+%% {[TransformedClause],[[NewVariable]],[[UsedVariable]],State'}
+%% Be very careful here to return the variables that are really used
+%% and really new.
+
+icr_clauses([], _, St) ->
+ {[],[[]],[],St};
+icr_clauses(Clauses, Vs, St) ->
+ icr_clauses2(Clauses, Vs, St).
+
+icr_clauses2([{clause,Line,H0,G0,B0}|Cs0], Vs, St0) ->
+ {H,Hvs,Hus,St1} = head(H0, St0), %Hvs is really used!
+ {G,Gvs,Gus,St2} = guard(G0, union(Hvs, Vs), St1),
+ {B,Bvs,Bus,St3} = exprs(B0, union([Vs,Hvs,Gvs]), St2),
+ New = subtract(union([Hvs,Gvs,Bvs]), Vs), %Really new
+ Used = intersection(union([Hvs,Hus,Gus,Bus]), Vs), %Really used
+ {Cs,Csvs,Csus,St4} = icr_clauses2(Cs0, Vs, St3),
+ {[{clause,Line,H,G,B}|Cs],[New|Csvs],[Used|Csus],St4};
+icr_clauses2([], _, St) ->
+ {[],[],[],St}.
+
+%% lc_tq(Line, Expr, Qualifiers, More, [VisibleVar], State) ->
+%% {TransExpr,[TransQual],TransMore,[NewVar],[UsedVar],State'}
+
+lc_tq(Line, E0, [{generate,Lg,P0,G0}|Qs0], M0, Vs, St0) ->
+ {G1,Gvs,Gus,St1} = expr(G0, Vs, St0),
+ {P1,Pvs,Pus,St2} = pattern(P0, St1),
+ {E1,Qs1,M1,Lvs,Lus,St3} = lc_tq(Line, E0, Qs0, M0, union(Pvs, Vs), St2),
+ {E1,[{generate,Lg,P1,G1}|Qs1],M1,
+ union(Gvs, Lvs),union([Gus,Pus,Lus]),St3};
+lc_tq(Line, E0, [F0|Qs0], M0, Vs, St0) ->
+ %% Allow record/2 and expand out as guard test.
+ case erl_lint:is_guard_test(F0) of
+ true ->
+ {F1,Fvs,_Fus,St1} = guard_tests([F0], Vs, St0),
+ {E1,Qs1,M1,Lvs,Lus,St2} = lc_tq(Line, E0, Qs0, M0, union(Fvs, Vs), St1),
+ {E1,F1++Qs1,M1,Lvs,Lus,St2};
+ false ->
+ {F1,Fvs,_Fus,St1} = expr(F0, Vs, St0),
+ {E1,Qs1,M1,Lvs,Lus,St2} = lc_tq(Line, E0, Qs0, M0, union(Fvs, Vs), St1),
+ {E1,[F1|Qs1],M1,Lvs,Lus,St2}
+ end;
+lc_tq(_Line, E0, [], M0, Vs, St0) ->
+ {E1,Evs,Eus,St1} = expr(E0, Vs, St0),
+ {M1,Mvs,Mus,St2} = expr(M0, Vs, St1),
+ {E1,[],M1,union(Evs, Mvs),union(Eus, Mus),St2}.
+
+%% fun_tq(Line, Body, VisibleVariables, State) ->
+%% {Fun,NewVariables,UsedVariables,State'}
+%% Transform an "explicit" fun {'fun', Line, {clauses, Cs}} into an
+%% extended form {'fun', Line, {clauses, Cs}, Info}, unless it is the
+%% name of a BIF (erl_lint has checked that it is not an import).
+%% Process the body sequence directly to get the new and used variables.
+%% "Implicit" funs {'fun', Line, {function, F, A}} are not changed.
+
+fun_tq(Lf, {function,F,A}, Vs, St0) ->
+ {As,St1} = new_vars(A, Lf, St0),
+ Cs = [{clause,Lf,As,[],[{call,Lf,{atom,Lf,F},As}]}],
+ case erl_internal:bif(F, A) of
+ true ->
+ fun_tq(Lf, {clauses,Cs}, Vs, St1);
+ false ->
+ Index = St0#expand.fun_index,
+ Uniq = erlang:hash(Cs, (1 bsl 27)-1),
+ {Fname,St2} = new_fun_name(St1),
+ {{'fun',Lf,{function,F,A},{Index,Uniq,Fname}},[],[],
+ St2#expand{fun_index=Index+1}}
+ end;
+fun_tq(Lf, {clauses,Cs0}, Vs, St0) ->
+ Uniq = erlang:hash(Cs0, (1 bsl 27)-1),
+ {Cs1,_Hvss,Frees,St1} = fun_clauses(Cs0, Vs, St0),
+ Ufrees = union(Frees),
+ Index = St1#expand.fun_index,
+ {Fname,St2} = new_fun_name(St1),
+ {{'fun',Lf,{clauses,Cs1},{Index,Uniq,Fname}},[],Ufrees,
+ St2#expand{fun_index=Index+1}}.
+
+fun_clauses([{clause,L,H0,G0,B0}|Cs0], Vs, St0) ->
+ {H,Hvs,Hus,St1} = head(H0, St0),
+ {G,Gvs,Gus,St2} = guard(G0, union(Hvs, Vs), St1),
+ {B,Bvs,Bus,St3} = exprs(B0, union([Vs,Hvs,Gvs]), St2),
+ %% Free variables cannot be new anywhere in the clause.
+ Free = subtract(union([Gus,Hus,Bus]), union([Hvs,Gvs,Bvs])),
+ %%io:format(" Gus :~p~n Bvs :~p~n Bus :~p~n Free:~p~n" ,[Gus,Bvs,Bus,Free]),
+ {Cs,Hvss,Frees,St4} = fun_clauses(Cs0, Vs, St3),
+ {[{clause,L,H,G,B}|Cs],[Hvs|Hvss],[Free|Frees],St4};
+fun_clauses([], _, St) -> {[],[],[],St}.
+
+%% new_fun_name(State) -> {FunName,State}.
+
+new_fun_name(#expand{func=F,arity=A,fcount=I}=St) ->
+ Name = "-" ++ atom_to_list(F) ++ "/" ++ integer_to_list(A)
+ ++ "-fun-" ++ integer_to_list(I) ++ "-",
+ {list_to_atom(Name),St#expand{fcount=I+1}}.
+
+
+%% normalise_fields([RecDef]) -> [Field].
+%% Normalise the field definitions to always have a default value. If
+%% none has been given then use 'undefined'.
+
+normalise_fields(Fs) ->
+ map(fun ({record_field,Lf,Field}) ->
+ {record_field,Lf,Field,{atom,Lf,undefined}};
+ (F) -> F end, Fs).
+
+%% record_fields(RecordName, State)
+%% find_field(FieldName, Fields)
+
+record_fields(R, St) -> dict:fetch(R, St#expand.records).
+
+find_field(F, [{record_field,_,{atom,_,F},Val}|_]) -> {ok,Val};
+find_field(F, [_|Fs]) -> find_field(F, Fs);
+find_field(_, []) -> error.
+
+%% field_names(RecFields) -> [Name].
+%% Return a list of the field names structures.
+
+field_names(Fs) ->
+ map(fun ({record_field,_,Field,_Val}) -> Field end, Fs).
+
+%% index_expr(Line, FieldExpr, Name, Fields) -> IndexExpr.
+%% Return an expression which evaluates to the index of a
+%% field. Currently only handle the case where the field is an
+%% atom. This expansion must be passed through expr again.
+
+index_expr(Line, {atom,_,F}, _Name, Fs) ->
+ {integer,Line,index_expr(F, Fs, 2)}.
+
+index_expr(F, [{record_field,_,{atom,_,F},_}|_], I) -> I;
+index_expr(F, [_|Fs], I) ->
+ index_expr(F, Fs, I+1).
+
+%% pattern_fields([RecDefField], [Match]) -> [Pattern].
+%% Build a list of match patterns for the record tuple elements.
+%% This expansion must be passed through pattern again. N.B. We are
+%% scanning the record definition field list!
+
+pattern_fields(Fs, Ms) ->
+ Wildcard = record_wildcard_init(Ms),
+ map(fun ({record_field,L,{atom,_,F},_}) ->
+ case find_field(F, Ms) of
+ {ok,Match} -> Match;
+ error when Wildcard =:= none -> {var,L,'_'};
+ error -> Wildcard
+ end end,
+ Fs).
+
+%% record_inits([RecDefField], [Init]) -> [InitExpr].
+%% Build a list of initialisation expressions for the record tuple
+%% elements. This expansion must be passed through expr
+%% again. N.B. We are scanning the record definition field list!
+
+record_inits(Fs, Is) ->
+ WildcardInit = record_wildcard_init(Is),
+ map(fun ({record_field,_,{atom,_,F},D}) ->
+ case find_field(F, Is) of
+ {ok,Init} -> Init;
+ error when WildcardInit =:= none -> D;
+ error -> WildcardInit
+ end end,
+ Fs).
+
+record_wildcard_init([{record_field,_,{var,_,'_'},D}|_]) -> D;
+record_wildcard_init([_|Is]) -> record_wildcard_init(Is);
+record_wildcard_init([]) -> none.
+
+%% record_update(Record, RecordName, [RecDefField], [Update], State) ->
+%% {Expr,State'}
+%% Build an expression to update fields in a record returning a new
+%% record. Try to be smart and optimise this. This expansion must be
+%% passed through expr again.
+
+record_update(R, Name, Fs, Us0, St0) ->
+ Line = element(2, R),
+ {Pre,Us,St1} = record_exprs(Us0, St0),
+ Nf = length(Fs), %# of record fields
+ Nu = length(Us), %# of update fields
+ Nc = Nf - Nu, %# of copy fields
+
+ %% We need a new variable for the record expression
+ %% to guarantee that it is only evaluated once.
+ {Var,St2} = new_var(Line, St1),
+
+ %% Try to be intelligent about which method of updating record to use.
+ {Update,St} =
+ if
+ Nu == 0 -> {R,St2}; %No fields updated
+ Nu =< Nc -> %Few fields updated
+ {record_setel(Var, Name, Fs, Us), St2};
+ true -> %The wide area inbetween
+ record_match(Var, Name, Fs, Us, St2)
+ end,
+ {{block,element(2, R),Pre ++ [{match,Line,Var,R},Update]},St}.
+
+%% record_match(Record, RecordName, [RecDefField], [Update], State)
+%% Build a 'case' expression to modify record fields.
+
+record_match(R, Name, Fs, Us, St0) ->
+ {Ps,News,St1} = record_upd_fs(Fs, Us, St0),
+ Lr = element(2, hd(Us)),
+ {{'case',Lr,R,
+ [{clause,Lr,[{tuple,Lr,[{atom,Lr,Name}|Ps]}],[],
+ [{tuple,Lr,[{atom,Lr,Name}|News]}]},
+ {clause,Lr,[{var,Lr,'_'}],[],
+ [call_error(Lr, {tuple,Lr,[{atom,Lr,badrecord},{atom,Lr,Name}]})]}
+ ]},
+ St1}.
+
+record_upd_fs([{record_field,Lf,{atom,_La,F},_Val}|Fs], Us, St0) ->
+ {P,St1} = new_var(Lf, St0),
+ {Ps,News,St2} = record_upd_fs(Fs, Us, St1),
+ case find_field(F, Us) of
+ {ok,New} -> {[P|Ps],[New|News],St2};
+ error -> {[P|Ps],[P|News],St2}
+ end;
+record_upd_fs([], _, St) -> {[],[],St}.
+
+%% record_setel(Record, RecordName, [RecDefField], [Update])
+%% Build a nested chain of setelement calls to build the
+%% updated record tuple.
+
+record_setel(R, Name, Fs, Us0) ->
+ Us1 = foldl(fun ({record_field,Lf,Field,Val}, Acc) ->
+ I = index_expr(Lf, Field, Name, Fs),
+ [{I,Lf,Val}|Acc]
+ end, [], Us0),
+ Us = sort(Us1),
+ Lr = element(2, hd(Us)),
+ Wildcards = duplicate(length(Fs), {var,Lr,'_'}),
+ {'case',Lr,R,
+ [{clause,Lr,[{tuple,Lr,[{atom,Lr,Name}|Wildcards]}],[],
+ [foldr(fun ({I,Lf,Val}, Acc) ->
+ {call,Lf,{atom,Lf,setelement},[I,Acc,Val]} end,
+ R, Us)]},
+ {clause,Lr,[{var,Lr,'_'}],[],
+ [call_error(Lr, {tuple,Lr,[{atom,Lr,badrecord},{atom,Lr,Name}]})]}]}.
+
+%% Expand a call to record_info/2. We have checked that it is not
+%% shadowed by an import.
+
+record_info_call(Line, [{atom,_Li,Info},{atom,_Ln,Name}], St) ->
+ case Info of
+ size ->
+ {{integer,Line,1+length(record_fields(Name, St))},[],[],St};
+ fields ->
+ {make_list(field_names(record_fields(Name, St)), Line),
+ [],[],St}
+ end.
+
+%% Break out expressions from an record update list and bind to new
+%% variables. The idea is that we will evaluate all update expressions
+%% before starting to update the record.
+
+record_exprs(Us, St) ->
+ record_exprs(Us, St, [], []).
+
+record_exprs([{record_field,Lf,{atom,_La,_F}=Name,Val}=Field0|Us], St0, Pre, Fs) ->
+ case is_simple_val(Val) of
+ true ->
+ record_exprs(Us, St0, Pre, [Field0|Fs]);
+ false ->
+ {Var,St} = new_var(Lf, St0),
+ Bind = {match,Lf,Var,Val},
+ Field = {record_field,Lf,Name,Var},
+ record_exprs(Us, St, [Bind|Pre], [Field|Fs])
+ end;
+record_exprs([], St, Pre, Fs) ->
+ {reverse(Pre),Fs,St}.
+
+is_simple_val({var,_,_}) -> true;
+is_simple_val({atom,_,_}) -> true;
+is_simple_val({integer,_,_}) -> true;
+is_simple_val({float,_,_}) -> true;
+is_simple_val({nil,_}) -> true;
+is_simple_val(_) -> false.
+
+%% pattern_bin([Element], State) -> {[Element],[Variable],[UsedVar],State}.
+
+pattern_bin(Es0, St) ->
+ Es1 = bin_expand_strings(Es0),
+ foldr(fun (E, Acc) -> pattern_element(E, Acc) end, {[],[],[],St}, Es1).
+
+pattern_element({bin_element,Line,Expr,Size,Type}, {Es,Esvs,Esus,St0}) ->
+ {Expr1,Vs1,Us1,St1} = pattern(Expr, St0),
+ {Size1,Vs2,Us2,St2} = pat_bit_size(Size, St1),
+ {Size2,Type1} = make_bit_type(Line, Size1,Type),
+ {[{bin_element,Line,Expr1,Size2,Type1}|Es],
+ union([Vs1,Vs2,Esvs]),union([Us1,Us2,Esus]),St2}.
+
+pat_bit_size(default, St) -> {default,[],[],St};
+pat_bit_size({atom,_La,all}=All, St) -> {All,[],[],St};
+pat_bit_size({var,_Lv,V}=Var, St) -> {Var,[],[V],St};
+pat_bit_size(Size, St) ->
+ Line = element(2, Size),
+ {value,Sz,_} = erl_eval:expr(Size, erl_eval:new_bindings()),
+ {{integer,Line,Sz},[],[],St}.
+
+make_bit_type(Line, default, Type0) ->
+ case erl_bits:set_bit_type(default, Type0) of
+ {ok,all,Bt} -> {{atom,Line,all},erl_bits:as_list(Bt)};
+ {ok,Size,Bt} -> {{integer,Line,Size},erl_bits:as_list(Bt)}
+ end;
+make_bit_type(_Line, Size, Type0) -> %Integer or 'all'
+ {ok,Size,Bt} = erl_bits:set_bit_type(Size, Type0),
+ {Size,erl_bits:as_list(Bt)}.
+
+%% expr_bin([Element], [VisibleVar], State) ->
+%% {[Element],[NewVar],[UsedVar],State}.
+
+expr_bin(Es0, Vs, St) ->
+ Es1 = bin_expand_strings(Es0),
+ foldr(fun (E, Acc) -> bin_element(E, Vs, Acc) end, {[],[],[],St}, Es1).
+
+bin_element({bin_element,Line,Expr,Size,Type}, Vs, {Es,Esvs,Esus,St0}) ->
+ {Expr1,Vs1,Us1,St1} = expr(Expr, Vs, St0),
+ {Size1,Vs2,Us2,St2} = if Size == default -> {default,[],[],St1};
+ true -> expr(Size, Vs, St1)
+ end,
+ {Size2,Type1} = make_bit_type(Line, Size1, Type),
+ {[{bin_element,Line,Expr1,Size2,Type1}|Es],
+ union([Vs1,Vs2,Esvs]),union([Us1,Us2,Esus]),St2}.
+
+bin_expand_strings(Es) ->
+ foldr(fun ({bin_element,Line,{string,_,S},default,default}, Es1) ->
+ foldr(fun (C, Es2) ->
+ [{bin_element,Line,{char,Line,C},default,default}|Es2]
+ end, Es1, S);
+ (E, Es1) -> [E|Es1]
+ end, [], Es).
+
+%% new_var_name(State) -> {VarName,State}.
+
+new_var_name(St) ->
+ C = St#expand.vcount,
+ {list_to_atom("pre" ++ integer_to_list(C)),St#expand{vcount=C+1}}.
+
+%% new_var(Line, State) -> {Var,State}.
+
+new_var(L, St0) ->
+ {New,St1} = new_var_name(St0),
+ {{var,L,New},St1}.
+
+%% new_vars(Count, Line, State) -> {[Var],State}.
+%% Make Count new variables.
+
+new_vars(N, L, St) -> new_vars(N, L, St, []).
+
+new_vars(N, L, St0, Vs) when N > 0 ->
+ {V,St1} = new_var(L, St0),
+ new_vars(N-1, L, St1, [V|Vs]);
+new_vars(0, _L, St, Vs) -> {Vs,St}.
+
+%% make_list(TermList, Line) -> ConsTerm.
+
+make_list(Ts, Line) ->
+ foldr(fun (H, T) -> {cons,Line,H,T} end, {nil,Line}, Ts).
+
+string_to_conses(Line, Cs, Tail) ->
+ foldr(fun (C, T) -> {cons,Line,{char,Line,C},T} end, Tail, Cs).
+
+
+%% In syntax trees, module/package names are atoms or lists of atoms.
+
+package_to_string(A) when atom(A) -> atom_to_list(A);
+package_to_string(L) when list(L) -> packages:concat(L).
+
+expand_package({atom,L,A} = M, St) ->
+ case dict:find(A, St#expand.mod_imports) of
+ {ok, A1} ->
+ {atom,L,A1};
+ error ->
+ case packages:is_segmented(A) of
+ true ->
+ M;
+ false ->
+ M1 = packages:concat(St#expand.package, A),
+ {atom,L,list_to_atom(M1)}
+ end
+ end;
+expand_package(M, _St) ->
+ case erl_parse:package_segments(M) of
+ error ->
+ M;
+ M1 ->
+ {atom,element(2,M),list_to_atom(package_to_string(M1))}
+ end.
+
+%% Create a case-switch on true/false, generating badarg for all other
+%% values.
+
+make_bool_switch(L, E, V, T, F) ->
+ make_bool_switch_1(L, E, V, [T], [F]).
+
+make_bool_switch_1(L, E, V, T, F) ->
+ case get(sys_pre_expand_in_guard) of
+ undefined -> make_bool_switch_body(L, E, V, T, F);
+ yes -> make_bool_switch_guard(L, E, V, T, F)
+ end.
+
+make_bool_switch_guard(_, E, _, [{atom,_,true}], [{atom,_,false}]) -> E;
+make_bool_switch_guard(L, E, V, T, F) ->
+ NegL = -abs(L),
+ {'case',NegL,E,
+ [{clause,NegL,[{atom,NegL,true}],[],T},
+ {clause,NegL,[{atom,NegL,false}],[],F},
+ {clause,NegL,[V],[],[V]}
+ ]}.
+
+make_bool_switch_body(L, E, V, T, F) ->
+ NegL = -abs(L),
+ {'case',NegL,E,
+ [{clause,NegL,[{atom,NegL,true}],[],T},
+ {clause,NegL,[{atom,NegL,false}],[],F},
+ {clause,NegL,[V],[],
+ [call_error(NegL,{tuple,NegL,[{atom,NegL,badarg},V]})]}
+ ]}.
+
+%% Expand a list of cond-clauses to a sequence of case-switches.
+
+cond_clauses([{clause,L,[],[[E]],B}],V) ->
+ make_bool_switch_1(L,E,V,B,[call_error(L,{atom,L,cond_clause})]);
+cond_clauses([{clause,L,[],[[E]],B} | Cs],V) ->
+ make_bool_switch_1(L,E,V,B,[cond_clauses(Cs,V)]).
+
+%% call_error(Line, Reason) -> Expr.
+%% Build a call to erlang:error/1 with reason Reason.
+
+call_error(L, R) ->
+ {call,L,{remote,L,{atom,L,erlang},{atom,L,error}},[R]}.
+
+%% new_in_all(Before, RegionList) -> NewInAll
+%% Return the variables new in all clauses.
+
+new_in_all(Before, Region) ->
+ InAll = intersection(Region),
+ subtract(InAll, Before).
+
+%% import(Line, Imports, State) ->
+%% State'
+%% imported(Name, Arity, State) ->
+%% {yes,Module} | no
+%% Handle import declarations and est for imported functions. No need to
+%% check when building imports as code is correct.
+
+import({Mod0,Fs}, St) ->
+ Mod = list_to_atom(package_to_string(Mod0)),
+ Mfs = from_list(Fs),
+ St#expand{imports=add_imports(Mod, Mfs, St#expand.imports)};
+import(Mod0, St) ->
+ Mod = package_to_string(Mod0),
+ Key = list_to_atom(packages:last(Mod)),
+ St#expand{mod_imports=dict:store(Key, list_to_atom(Mod),
+ St#expand.mod_imports)}.
+
+add_imports(Mod, [F|Fs], Is) ->
+ add_imports(Mod, Fs, orddict:store(F, Mod, Is));
+add_imports(_, [], Is) -> Is.
+
+imported(F, A, St) ->
+ case orddict:find({F,A}, St#expand.imports) of
+ {ok,Mod} -> {yes,Mod};
+ error -> no
+ end.
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_codegen.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_codegen.erl
new file mode 100644
index 0000000000..6b787e8c95
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_codegen.erl
@@ -0,0 +1,1755 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: v3_codegen.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
+%%
+%% Purpose : Code generator for Beam.
+
+%% The following assumptions have been made:
+%%
+%% 1. Matches, i.e. things with {match,M,Ret} wrappers, only return
+%% values; no variables are exported. If the match would have returned
+%% extra variables then these have been transformed to multiple return
+%% values.
+%%
+%% 2. All BIF's called in guards are gc-safe so there is no need to
+%% put thing on the stack in the guard. While this would in principle
+%% work it would be difficult to keep track of the stack depth when
+%% trimming.
+%%
+%% The code generation uses variable lifetime information added by
+%% the v3_life module to save variables, allocate registers and
+%% move registers to the stack when necessary.
+%%
+%% We try to use a consistent variable name scheme throughout. The
+%% StackReg record is always called Bef,Int<n>,Aft.
+
+-module(v3_codegen).
+
+%% The main interface.
+-export([module/2]).
+
+-import(lists, [member/2,keymember/3,keysort/2,keysearch/3,append/1,
+ map/2,flatmap/2,foldl/3,foldr/3,mapfoldl/3,
+ sort/1,reverse/1,reverse/2]).
+-import(v3_life, [vdb_find/2]).
+
+%%-compile([export_all]).
+
+-include("v3_life.hrl").
+
+%% Main codegen structure.
+-record(cg, {lcount=1, %Label counter
+ mod, %Current module
+ func, %Current function
+ finfo, %Function info label
+ fcode, %Function code label
+ btype, %Type of bif used.
+ bfail, %Fail label of bif
+ break, %Break label
+ recv, %Receive label
+ is_top_block, %Boolean: top block or not
+ functable = [], %Table of local functions:
+ %[{{Name, Arity}, Label}...]
+ in_catch=false, %Inside a catch or not.
+ need_frame, %Need a stack frame.
+ new_funs=true}). %Generate new fun instructions.
+
+%% Stack/register state record.
+-record(sr, {reg=[], %Register table
+ stk=[], %Stack table
+ res=[]}). %Reserved regs: [{reserved,I,V}]
+
+module({Mod,Exp,Attr,Forms}, Options) ->
+ NewFunsFlag = not member(no_new_funs, Options),
+ {Fs,St} = functions(Forms, #cg{mod=Mod,new_funs=NewFunsFlag}),
+ {ok,{Mod,Exp,Attr,Fs,St#cg.lcount}}.
+
+functions(Forms, St0) ->
+ mapfoldl(fun (F, St) -> function(F, St) end, St0#cg{lcount=1}, Forms).
+
+function({function,Name,Arity,As0,Vb,Vdb}, St0) ->
+ %%ok = io:fwrite("cg ~w:~p~n", [?LINE,{Name,Arity}]),
+ St1 = St0#cg{func={Name,Arity}},
+ {Fun,St2} = cg_fun(Vb, As0, Vdb, St1),
+ Func0 = {function,Name,Arity,St2#cg.fcode,Fun},
+ Func = bs_function(Func0),
+ {Func,St2}.
+
+%% cg_fun([Lkexpr], [HeadVar], Vdb, State) -> {[Ainstr],State}
+
+cg_fun(Les, Hvs, Vdb, St0) ->
+ {Name,Arity} = St0#cg.func,
+ {Fi,St1} = new_label(St0), %FuncInfo label
+ {Fl,St2} = local_func_label(Name, Arity, St1),
+ %% Create initial stack/register state, clear unused arguments.
+ Bef = clear_dead(#sr{reg=foldl(fun ({var,V}, Reg) ->
+ put_reg(V, Reg)
+ end, [], Hvs),
+ stk=[]}, 0, Vdb),
+ {B2,_Aft,St3} = cg_list(Les, 0, Vdb, Bef, St2#cg{btype=exit,
+ bfail=Fi,
+ finfo=Fi,
+ fcode=Fl,
+ is_top_block=true}),
+ A = [{label,Fi},{func_info,{atom,St3#cg.mod},{atom,Name},Arity},
+ {label,Fl}|B2],
+ {A,St3}.
+
+%% cg(Lkexpr, Vdb, StackReg, State) -> {[Ainstr],StackReg,State}.
+%% Generate code for a kexpr.
+%% Split function into two steps for clarity, not efficiency.
+
+cg(Le, Vdb, Bef, St) ->
+ cg(Le#l.ke, Le, Vdb, Bef, St).
+
+cg({block,Es}, Le, Vdb, Bef, St) ->
+ block_cg(Es, Le, Vdb, Bef, St);
+cg({match,M,Rs}, Le, Vdb, Bef, St) ->
+ match_cg(M, Rs, Le, Vdb, Bef, St);
+cg({match_fail,F}, Le, Vdb, Bef, St) ->
+ match_fail_cg(F, Le, Vdb, Bef, St);
+cg({call,Func,As,Rs}, Le, Vdb, Bef, St) ->
+ call_cg(Func, As, Rs, Le, Vdb, Bef, St);
+cg({enter,Func,As}, Le, Vdb, Bef, St) ->
+ enter_cg(Func, As, Le, Vdb, Bef, St);
+cg({bif,Bif,As,Rs}, Le, Vdb, Bef, St) ->
+ bif_cg(Bif, As, Rs, Le, Vdb, Bef, St);
+cg({receive_loop,Te,Rvar,Rm,Tes,Rs}, Le, Vdb, Bef, St) ->
+ recv_loop_cg(Te, Rvar, Rm, Tes, Rs, Le, Vdb, Bef, St);
+cg(receive_next, Le, Vdb, Bef, St) ->
+ recv_next_cg(Le, Vdb, Bef, St);
+cg(receive_accept, _Le, _Vdb, Bef, St) -> {[remove_message],Bef,St};
+cg({'try',Ta,Vs,Tb,Evs,Th,Rs}, Le, Vdb, Bef, St) ->
+ try_cg(Ta, Vs, Tb, Evs, Th, Rs, Le, Vdb, Bef, St);
+cg({'catch',Cb,R}, Le, Vdb, Bef, St) ->
+ catch_cg(Cb, R, Le, Vdb, Bef, St);
+cg({set,Var,Con}, Le, Vdb, Bef, St) -> set_cg(Var, Con, Le, Vdb, Bef, St);
+cg({return,Rs}, Le, Vdb, Bef, St) -> return_cg(Rs, Le, Vdb, Bef, St);
+cg({break,Bs}, Le, Vdb, Bef, St) -> break_cg(Bs, Le, Vdb, Bef, St);
+cg({need_heap,0}, _Le, _Vdb, Bef, St) ->
+ {[],Bef,St};
+cg({need_heap,H}, _Le, _Vdb, Bef, St) ->
+ {[{test_heap,H,max_reg(Bef#sr.reg)}],Bef,St}.
+
+%% cg_list([Kexpr], FirstI, Vdb, StackReg, St) -> {[Ainstr],StackReg,St}.
+
+cg_list(Kes, I, Vdb, Bef, St0) ->
+ {Keis,{Aft,St1}} =
+ flatmapfoldl(fun (Ke, {Inta,Sta}) ->
+% ok = io:fwrite(" %% ~p\n", [Inta]),
+% ok = io:fwrite("cgl:~p\n", [Ke]),
+ {Keis,Intb,Stb} = cg(Ke, Vdb, Inta, Sta),
+% ok = io:fwrite(" ~p\n", [Keis]),
+% ok = io:fwrite(" %% ~p\n", [Intb]),
+ {comment(Inta) ++ Keis,{Intb,Stb}}
+ end, {Bef,St0}, need_heap(Kes, I)),
+ {Keis,Aft,St1}.
+
+%% need_heap([Lkexpr], I, BifType) -> [Lkexpr].
+%% Insert need_heap instructions in Kexpr list. Try to be smart and
+%% collect them together as much as possible.
+
+need_heap(Kes0, I) ->
+ {Kes1,{H,F}} = flatmapfoldr(fun (Ke, {H0,F0}) ->
+ {Ns,H1,F1} = need_heap_1(Ke, H0, F0),
+ {[Ke|Ns],{H1,F1}}
+ end, {0,false}, Kes0),
+ %% Prepend need_heap if necessary.
+ Kes2 = need_heap_need(I, H, F) ++ Kes1,
+% ok = io:fwrite("need_heap: ~p~n",
+% [{{H,F},
+% map(fun (#l{ke={match,M,Rs}}) -> match;
+% (Lke) -> Lke#l.ke end, Kes2)}]),
+ Kes2.
+
+need_heap_1(#l{ke={set,_,{binary,_}},i=I}, H, F) ->
+ {need_heap_need(I, H, F),0,false};
+need_heap_1(#l{ke={set,_,Val}}, H, F) ->
+ %% Just pass through adding to needed heap.
+ {[],H + case Val of
+ {cons,_} -> 2;
+ {tuple,Es} -> 1 + length(Es);
+ {string,S} -> 2 * length(S);
+ _Other -> 0
+ end,F};
+need_heap_1(#l{ke={call,_Func,_As,_Rs},i=I}, H, F) ->
+ %% Calls generate a need if necessary and also force one.
+ {need_heap_need(I, H, F),0,true};
+need_heap_1(#l{ke={bif,dsetelement,_As,_Rs},i=I}, H, F) ->
+ {need_heap_need(I, H, F),0,true};
+need_heap_1(#l{ke={bif,{make_fun,_,_,_,_},_As,_Rs},i=I}, H, F) ->
+ {need_heap_need(I, H, F),0,true};
+need_heap_1(#l{ke={bif,_Bif,_As,_Rs}}, H, F) ->
+ {[],H,F};
+need_heap_1(#l{i=I}, H, F) ->
+ %% Others kexprs generate a need if necessary but don't force.
+ {need_heap_need(I, H, F),0,false}.
+
+need_heap_need(_I, 0, false) -> [];
+need_heap_need(I, H, _F) -> [#l{ke={need_heap,H},i=I}].
+
+
+%% match_cg(Match, [Ret], Le, Vdb, StackReg, State) ->
+%% {[Ainstr],StackReg,State}.
+%% Generate code for a match. First save all variables on the stack
+%% that are to survive after the match. We leave saved variables in
+%% their registers as they might actually be in the right place.
+%% Should test this.
+
+match_cg(M, Rs, Le, Vdb, Bef, St0) ->
+ I = Le#l.i,
+ {Sis,Int0} = adjust_stack(Bef, I, I+1, Vdb),
+ {B,St1} = new_label(St0),
+ {Mis,Int1,St2} = match_cg(M, none, Int0, St1#cg{break=B}),
+ %% Put return values in registers.
+ Reg = load_vars(Rs, Int1#sr.reg),
+ {Sis ++ Mis ++ [{label,B}],
+ clear_dead(Int1#sr{reg=Reg}, I, Vdb),
+ St2#cg{break=St1#cg.break}}.
+
+%% match_cg(Match, Fail, StackReg, State) -> {[Ainstr],StackReg,State}.
+%% Generate code for a match tree. N.B. there is no need pass Vdb
+%% down as each level which uses this takes its own internal Vdb not
+%% the outer one.
+
+match_cg(Le, Fail, Bef, St) ->
+ match_cg(Le#l.ke, Le, Fail, Bef, St).
+
+match_cg({alt,F,S}, _Le, Fail, Bef, St0) ->
+ {Tf,St1} = new_label(St0),
+ {Fis,Faft,St2} = match_cg(F, Tf, Bef, St1),
+ {Sis,Saft,St3} = match_cg(S, Fail, Bef, St2),
+ Aft = sr_merge(Faft, Saft),
+ {Fis ++ [{label,Tf}] ++ Sis,Aft,St3};
+match_cg({select,V,Scs}, _Va, Fail, Bef, St) ->
+ match_fmf(fun (S, F, Sta) ->
+ select_cg(S, V, F, Fail, Bef, Sta) end,
+ Fail, St, Scs);
+match_cg({guard,Gcs}, _Le, Fail, Bef, St) ->
+ match_fmf(fun (G, F, Sta) -> guard_clause_cg(G, F, Bef, Sta) end,
+ Fail, St, Gcs);
+match_cg({block,Es}, Le, _Fail, Bef, St) ->
+ %% Must clear registers and stack of dead variables.
+ Int = clear_dead(Bef, Le#l.i, Le#l.vdb),
+ block_cg(Es, Le, Int, St).
+
+%% match_fail_cg(FailReason, Le, Vdb, StackReg, State) ->
+%% {[Ainstr],StackReg,State}.
+%% Generate code for the match_fail "call". N.B. there is no generic
+%% case for when the fail value has been created elsewhere.
+
+match_fail_cg({function_clause,As}, Le, Vdb, Bef, St) ->
+ %% Must have the args in {x,0}, {x,1},...
+ {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
+ {Sis ++ [{jump,{f,St#cg.finfo}}],
+ Int#sr{reg=clear_regs(Int#sr.reg)},St};
+match_fail_cg({badmatch,Term}, Le, Vdb, Bef, St) ->
+ R = cg_reg_arg(Term, Bef),
+ Int0 = clear_dead(Bef, Le#l.i, Vdb),
+ {Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
+ {Sis ++ [{badmatch,R}],
+ Int#sr{reg=clear_regs(Int0#sr.reg)},St};
+match_fail_cg({case_clause,Reason}, Le, Vdb, Bef, St) ->
+ R = cg_reg_arg(Reason, Bef),
+ Int0 = clear_dead(Bef, Le#l.i, Vdb),
+ {Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
+ {Sis++[{case_end,R}],
+ Int#sr{reg=clear_regs(Bef#sr.reg)},St};
+match_fail_cg(if_clause, Le, Vdb, Bef, St) ->
+ Int0 = clear_dead(Bef, Le#l.i, Vdb),
+ {Sis,Int1} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
+ {Sis++[if_end],Int1#sr{reg=clear_regs(Int1#sr.reg)},St};
+match_fail_cg({try_clause,Reason}, Le, Vdb, Bef, St) ->
+ R = cg_reg_arg(Reason, Bef),
+ Int0 = clear_dead(Bef, Le#l.i, Vdb),
+ {Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
+ {Sis ++ [{try_case_end,R}],
+ Int#sr{reg=clear_regs(Int0#sr.reg)},St}.
+
+
+%% block_cg([Kexpr], Le, Vdb, StackReg, St) -> {[Ainstr],StackReg,St}.
+%% block_cg([Kexpr], Le, StackReg, St) -> {[Ainstr],StackReg,St}.
+
+block_cg(Es, Le, _Vdb, Bef, St) ->
+ block_cg(Es, Le, Bef, St).
+
+block_cg(Es, Le, Bef, St0) ->
+ case St0#cg.is_top_block of
+ false ->
+ cg_block(Es, Le#l.i, Le#l.vdb, Bef, St0);
+ true ->
+ {Keis,Aft,St1} = cg_block(Es, Le#l.i, Le#l.vdb, Bef,
+ St0#cg{is_top_block=false,
+ need_frame=false}),
+ top_level_block(Keis, Aft, max_reg(Bef#sr.reg), St1)
+ end.
+
+cg_block([], _I, _Vdb, Bef, St0) ->
+ {[],Bef,St0};
+cg_block(Kes0, I, Vdb, Bef, St0) ->
+ {Kes2,Int1,St1} =
+ case basic_block(Kes0) of
+ {Kes1,LastI,Args,Rest} ->
+ Ke = hd(Kes1),
+ Fb = Ke#l.i,
+ cg_basic_block(Kes1, Fb, LastI, Args, Vdb, Bef, St0);
+ {Kes1,Rest} ->
+ cg_list(Kes1, I, Vdb, Bef, St0)
+ end,
+ {Kes3,Int2,St2} = cg_block(Rest, I, Vdb, Int1, St1),
+ {Kes2 ++ Kes3,Int2,St2}.
+
+basic_block(Kes) -> basic_block(Kes, []).
+
+basic_block([], Acc) -> {reverse(Acc),[]};
+basic_block([Le|Les], Acc) ->
+ case collect_block(Le#l.ke) of
+ include -> basic_block(Les, [Le|Acc]);
+ {block_end,As} -> {reverse(Acc, [Le]),Le#l.i,As,Les};
+ no_block -> {reverse(Acc, [Le]),Les}
+ end.
+
+collect_block({set,_,{binary,_}}) -> no_block;
+collect_block({set,_,_}) -> include;
+collect_block({call,{var,_}=Var,As,_Rs}) -> {block_end,As++[Var]};
+collect_block({call,Func,As,_Rs}) -> {block_end,As++func_vars(Func)};
+collect_block({enter,{var,_}=Var,As})-> {block_end,As++[Var]};
+collect_block({enter,Func,As}) -> {block_end,As++func_vars(Func)};
+collect_block({return,Rs}) -> {block_end,Rs};
+collect_block({break,Bs}) -> {block_end,Bs};
+collect_block({bif,_Bif,_As,_Rs}) -> include;
+collect_block(_) -> no_block.
+
+func_vars({remote,M,F}) when element(1, M) == var;
+ element(1, F) == var ->
+ [M,F];
+func_vars(_) -> [].
+
+%% cg_basic_block([Kexpr], FirstI, LastI, As, Vdb, StackReg, State) ->
+%% {[Ainstr],StackReg,State}.
+
+cg_basic_block(Kes, Fb, Lf, As, Vdb, Bef, St0) ->
+ Res = make_reservation(As, 0),
+ Regs0 = reserve(Res, Bef#sr.reg, Bef#sr.stk),
+ Stk = extend_stack(Bef, Lf, Lf+1, Vdb),
+ Int0 = Bef#sr{reg=Regs0,stk=Stk,res=Res},
+ X0_v0 = x0_vars(As, Fb, Lf, Vdb),
+ {Keis,{Aft,_,St1}} =
+ flatmapfoldl(fun(Ke, St) -> cg_basic_block(Ke, St, Lf, Vdb) end,
+ {Int0,X0_v0,St0}, need_heap(Kes, Fb)),
+ {Keis,Aft,St1}.
+
+cg_basic_block(Ke, {Inta,X0v,Sta}, _Lf, Vdb) when element(1, Ke#l.ke) =:= need_heap ->
+ {Keis,Intb,Stb} = cg(Ke, Vdb, Inta, Sta),
+ {comment(Inta) ++ Keis, {Intb,X0v,Stb}};
+cg_basic_block(Ke, {Inta,X0_v1,Sta}, Lf, Vdb) ->
+ {Sis,Intb} = save_carefully(Inta, Ke#l.i, Lf+1, Vdb),
+ {X0_v2,Intc} = allocate_x0(X0_v1, Ke#l.i, Intb),
+ Intd = reserve(Intc),
+ {Keis,Inte,Stb} = cg(Ke, Vdb, Intd, Sta),
+ {comment(Inta) ++ Sis ++ Keis, {Inte,X0_v2,Stb}}.
+
+make_reservation([], _) -> [];
+make_reservation([{var,V}|As], I) -> [{I,V}|make_reservation(As, I+1)];
+make_reservation([A|As], I) -> [{I,A}|make_reservation(As, I+1)].
+
+reserve(Sr) -> Sr#sr{reg=reserve(Sr#sr.res, Sr#sr.reg, Sr#sr.stk)}.
+
+reserve([{I,V}|Rs], [free|Regs], Stk) -> [{reserved,I,V}|reserve(Rs, Regs, Stk)];
+reserve([{I,V}|Rs], [{I,V}|Regs], Stk) -> [{I,V}|reserve(Rs, Regs, Stk)];
+reserve([{I,V}|Rs], [{I,Var}|Regs], Stk) ->
+ case on_stack(Var, Stk) of
+ true -> [{reserved,I,V}|reserve(Rs, Regs, Stk)];
+ false -> [{I,Var}|reserve(Rs, Regs, Stk)]
+ end;
+reserve([{I,V}|Rs], [{reserved,I,_}|Regs], Stk) ->
+ [{reserved,I,V}|reserve(Rs, Regs, Stk)];
+%reserve([{I,V}|Rs], [Other|Regs], Stk) -> [Other|reserve(Rs, Regs, Stk)];
+reserve([{I,V}|Rs], [], Stk) -> [{reserved,I,V}|reserve(Rs, [], Stk)];
+reserve([], Regs, _) -> Regs.
+
+extend_stack(Bef, Fb, Lf, Vdb) ->
+ Stk0 = clear_dead_stk(Bef#sr.stk, Fb, Vdb),
+ Saves = [V || {V,F,L} <- Vdb,
+ F < Fb,
+ L >= Lf,
+ not on_stack(V, Stk0)],
+ Stk1 = foldl(fun (V, Stk) -> put_stack(V, Stk) end, Stk0, Saves),
+ Bef#sr.stk ++ lists:duplicate(length(Stk1) - length(Bef#sr.stk), free).
+
+save_carefully(Bef, Fb, Lf, Vdb) ->
+ Stk = Bef#sr.stk,
+ %% New variables that are in use but not on stack.
+ New = [ {V,F,L} || {V,F,L} <- Vdb,
+ F < Fb,
+ L >= Lf,
+ not on_stack(V, Stk) ],
+ Saves = [ V || {V,_,_} <- keysort(2, New) ],
+ save_carefully(Saves, Bef, []).
+
+save_carefully([], Bef, Acc) -> {reverse(Acc),Bef};
+save_carefully([V|Vs], Bef, Acc) ->
+ case put_stack_carefully(V, Bef#sr.stk) of
+ error -> {reverse(Acc),Bef};
+ Stk1 ->
+ SrcReg = fetch_reg(V, Bef#sr.reg),
+ Move = {move,SrcReg,fetch_stack(V, Stk1)},
+ {x,_} = SrcReg, %Assertion - must be X register.
+ save_carefully(Vs, Bef#sr{stk=Stk1}, [Move|Acc])
+ end.
+
+x0_vars([], _Fb, _Lf, _Vdb) -> [];
+x0_vars([{var,V}|_], Fb, _Lf, Vdb) ->
+ {V,F,_L} = VFL = vdb_find(V, Vdb),
+ x0_vars1([VFL], Fb, F, Vdb);
+x0_vars([X0|_], Fb, Lf, Vdb) ->
+ x0_vars1([{X0,Lf,Lf}], Fb, Lf, Vdb).
+
+x0_vars1(X0, Fb, Xf, Vdb) ->
+ Vs0 = [VFL || {_V,F,L}=VFL <- Vdb,
+ F >= Fb,
+ L < Xf],
+ Vs1 = keysort(3, Vs0),
+ keysort(2, X0++Vs1).
+
+allocate_x0([], _, Bef) -> {[],Bef#sr{res=[]}};
+allocate_x0([{_,_,L}|Vs], I, Bef) when L =< I ->
+ allocate_x0(Vs, I, Bef);
+allocate_x0([{V,_F,_L}=VFL|Vs], _, Bef) ->
+ {[VFL|Vs],Bef#sr{res=reserve_x0(V, Bef#sr.res)}}.
+
+reserve_x0(V, [_|Res]) -> [{0,V}|Res];
+reserve_x0(V, []) -> [{0,V}].
+
+top_level_block(Keis, Bef, _MaxRegs, St0) when St0#cg.need_frame =:= false,
+ length(Bef#sr.stk) =:= 0 ->
+ %% This block need no stack frame. However, we still need to turn the
+ %% stack frame upside down.
+ MaxY = length(Bef#sr.stk)-1,
+ Keis1 = flatmap(fun (Tuple) when tuple(Tuple) ->
+ [turn_yregs(size(Tuple), Tuple, MaxY)];
+ (Other) ->
+ [Other]
+ end, Keis),
+ {Keis1, Bef, St0#cg{is_top_block=true}};
+top_level_block(Keis, Bef, MaxRegs, St0) ->
+ %% This top block needs an allocate instruction before it, and a
+ %% deallocate instruction before each return.
+ FrameSz = length(Bef#sr.stk),
+ MaxY = FrameSz-1,
+ Keis1 = flatmap(fun ({call_only,Arity,Func}) ->
+ [{call_last,Arity,Func,FrameSz}];
+ ({call_ext_only,Arity,Func}) ->
+ [{call_ext_last,Arity,Func,FrameSz}];
+ ({apply_only,Arity}) ->
+ [{apply_last,Arity,FrameSz}];
+ (return) ->
+ [{deallocate,FrameSz}, return];
+ (Tuple) when tuple(Tuple) ->
+ [turn_yregs(size(Tuple), Tuple, MaxY)];
+ (Other) ->
+ [Other]
+ end, Keis),
+ {[{allocate_zero,FrameSz,MaxRegs}|Keis1], Bef, St0#cg{is_top_block=true}}.
+
+%% turn_yregs(Size, Tuple, MaxY) -> Tuple'
+%% Renumber y register so that {y, 0} becomes {y, FrameSize-1},
+%% {y, FrameSize-1} becomes {y, 0} and so on. This is to make nested
+%% catches work. The code generation algorithm gives a lower register
+%% number to the outer catch, which is wrong.
+
+turn_yregs(0, Tp, _) -> Tp;
+turn_yregs(El, Tp, MaxY) when element(1, element(El, Tp)) == yy ->
+ turn_yregs(El-1, setelement(El, Tp, {y,MaxY-element(2, element(El, Tp))}), MaxY);
+turn_yregs(El, Tp, MaxY) when list(element(El, Tp)) ->
+ New = map(fun ({yy,YY}) -> {y,MaxY-YY};
+ (Other) -> Other end, element(El, Tp)),
+ turn_yregs(El-1, setelement(El, Tp, New), MaxY);
+turn_yregs(El, Tp, MaxY) ->
+ turn_yregs(El-1, Tp, MaxY).
+
+%% select_cg(Sclause, V, TypeFail, ValueFail, StackReg, State) ->
+%% {Is,StackReg,State}.
+%% Selecting type and value needs two failure labels, TypeFail is the
+%% label to jump to of the next type test when this type fails, and
+%% ValueFail is the label when this type is correct but the value is
+%% wrong. These are different as in the second case there is no need
+%% to try the next type, it will always fail.
+
+select_cg(#l{ke={type_clause,cons,[S]}}, {var,V}, Tf, Vf, Bef, St) ->
+ select_cons(S, V, Tf, Vf, Bef, St);
+select_cg(#l{ke={type_clause,nil,[S]}}, {var,V}, Tf, Vf, Bef, St) ->
+ select_nil(S, V, Tf, Vf, Bef, St);
+select_cg(#l{ke={type_clause,binary,[S]}}, {var,V}, Tf, Vf, Bef, St) ->
+ select_binary(S, V, Tf, Vf, Bef, St);
+select_cg(#l{ke={type_clause,bin_seg,S}}, {var,V}, Tf, Vf, Bef, St) ->
+ select_bin_segs(S, V, Tf, Vf, Bef, St);
+select_cg(#l{ke={type_clause,bin_end,[S]}}, {var,V}, Tf, Vf, Bef, St) ->
+ select_bin_end(S, V, Tf, Vf, Bef, St);
+select_cg(#l{ke={type_clause,Type,Scs}}, {var,V}, Tf, Vf, Bef, St0) ->
+ {Vis,{Aft,St1}} =
+ mapfoldl(fun (S, {Int,Sta}) ->
+ {Val,Is,Inta,Stb} = select_val(S, V, Vf, Bef, Sta),
+ {{Is,[Val]},{sr_merge(Int, Inta),Stb}}
+ end, {void,St0}, Scs),
+ OptVls = combine(lists:sort(combine(Vis))),
+ {Vls,Sis,St2} = select_labels(OptVls, St1, [], []),
+ {select_val_cg(Type, fetch_var(V, Bef), Vls, Tf, Vf, Sis), Aft, St2}.
+
+select_val_cg(tuple, R, [Arity,{f,Lbl}], Tf, Vf, [{label,Lbl}|Sis]) ->
+ [{test,is_tuple,{f,Tf},[R]},{test,test_arity,{f,Vf},[R,Arity]}|Sis];
+select_val_cg(tuple, R, Vls, Tf, Vf, Sis) ->
+ [{test,is_tuple,{f,Tf},[R]},{select_tuple_arity,R,{f,Vf},{list,Vls}}|Sis];
+select_val_cg(Type, R, [Val, {f,Lbl}], Fail, Fail, [{label,Lbl}|Sis]) ->
+ [{test,is_eq_exact,{f,Fail},[R,{Type,Val}]}|Sis];
+select_val_cg(Type, R, [Val, {f,Lbl}], Tf, Vf, [{label,Lbl}|Sis]) ->
+ [{test,select_type_test(Type),{f,Tf},[R]},
+ {test,is_eq_exact,{f,Vf},[R,{Type,Val}]}|Sis];
+select_val_cg(Type, R, Vls0, Tf, Vf, Sis) ->
+ Vls1 = map(fun ({f,Lbl}) -> {f,Lbl};
+ (Value) -> {Type,Value}
+ end, Vls0),
+ [{test,select_type_test(Type),{f,Tf},[R]}, {select_val,R,{f,Vf},{list,Vls1}}|Sis].
+
+select_type_test(tuple) -> is_tuple;
+select_type_test(integer) -> is_integer;
+select_type_test(atom) -> is_atom;
+select_type_test(float) -> is_float.
+
+combine([{Is,Vs1}, {Is,Vs2}|Vis]) -> combine([{Is,Vs1 ++ Vs2}|Vis]);
+combine([V|Vis]) -> [V|combine(Vis)];
+combine([]) -> [].
+
+select_labels([{Is,Vs}|Vis], St0, Vls, Sis) ->
+ {Lbl,St1} = new_label(St0),
+ select_labels(Vis, St1, add_vls(Vs, Lbl, Vls), [[{label,Lbl}|Is]|Sis]);
+select_labels([], St, Vls, Sis) ->
+ {Vls,append(Sis),St}.
+
+add_vls([V|Vs], Lbl, Acc) ->
+ add_vls(Vs, Lbl, [V, {f,Lbl}|Acc]);
+add_vls([], _, Acc) -> Acc.
+
+select_cons(#l{ke={val_clause,{cons,Es},B},i=I,vdb=Vdb}, V, Tf, Vf, Bef, St0) ->
+ {Eis,Int,St1} = select_extract_cons(V, Es, I, Vdb, Bef, St0),
+ {Bis,Aft,St2} = match_cg(B, Vf, Int, St1),
+ {[{test,is_nonempty_list,{f,Tf},[fetch_var(V, Bef)]}] ++ Eis ++ Bis,Aft,St2}.
+
+select_nil(#l{ke={val_clause,nil,B}}, V, Tf, Vf, Bef, St0) ->
+ {Bis,Aft,St1} = match_cg(B, Vf, Bef, St0),
+ {[{test,is_nil,{f,Tf},[fetch_var(V, Bef)]}] ++ Bis,Aft,St1}.
+
+select_binary(#l{ke={val_clause,{old_binary,Var},B}}=L,
+ V, Tf, Vf, Bef, St) ->
+ %% Currently handled in the same way as new binaries.
+ select_binary(L#l{ke={val_clause,{binary,Var},B}}, V, Tf, Vf, Bef, St);
+select_binary(#l{ke={val_clause,{binary,{var,Ivar}},B},i=I,vdb=Vdb},
+ V, Tf, Vf, Bef, St0) ->
+ Int0 = clear_dead(Bef, I, Vdb),
+ {Bis,Aft,St1} = match_cg(B, Vf, Int0, St0),
+ {[{test,bs_start_match,{f,Tf},[fetch_var(V, Bef)]},{bs_save,Ivar}|Bis],
+ Aft,St1}.
+
+select_bin_segs(Scs, Ivar, Tf, _Vf, Bef, St) ->
+ match_fmf(fun(S, Fail, Sta) ->
+ select_bin_seg(S, Ivar, Fail, Bef, Sta) end,
+ Tf, St, Scs).
+
+select_bin_seg(#l{ke={val_clause,{bin_seg,Size,U,T,Fs,Es},B},i=I,vdb=Vdb},
+ Ivar, Fail, Bef, St0) ->
+ {Mis,Int,St1} = select_extract_bin(Es, Size, U, T, Fs, Fail,
+ I, Vdb, Bef, St0),
+ {Bis,Aft,St2} = match_cg(B, Fail, Int, St1),
+ {[{bs_restore,Ivar}|Mis] ++ Bis,Aft,St2}.
+
+select_extract_bin([{var,Hd},{var,Tl}], Size0, Unit, Type, Flags, Vf,
+ I, Vdb, Bef, St) ->
+ SizeReg = get_bin_size_reg(Size0, Bef),
+ {Es,Aft} =
+ case vdb_find(Hd, Vdb) of
+ {_,_,Lhd} when Lhd =< I ->
+ {[{test,bs_skip_bits,{f,Vf},[SizeReg,Unit,{field_flags,Flags}]},
+ {bs_save,Tl}],Bef};
+ {_,_,_} ->
+ Reg0 = put_reg(Hd, Bef#sr.reg),
+ Int1 = Bef#sr{reg=Reg0},
+ Rhd = fetch_reg(Hd, Reg0),
+ Name = get_bits_instr(Type),
+ {[{test,Name,{f,Vf},[SizeReg,Unit,{field_flags,Flags},Rhd]},
+ {bs_save,Tl}],Int1}
+ end,
+ {Es,clear_dead(Aft, I, Vdb),St}.
+
+get_bin_size_reg({var,V}, Bef) ->
+ fetch_var(V, Bef);
+get_bin_size_reg(Literal, _Bef) ->
+ Literal.
+
+select_bin_end(#l{ke={val_clause,bin_end,B}},
+ Ivar, Tf, Vf, Bef, St0) ->
+ {Bis,Aft,St2} = match_cg(B, Vf, Bef, St0),
+ {[{bs_restore,Ivar},{test,bs_test_tail,{f,Tf},[0]}|Bis],Aft,St2}.
+
+get_bits_instr(integer) -> bs_get_integer;
+get_bits_instr(float) -> bs_get_float;
+get_bits_instr(binary) -> bs_get_binary.
+
+select_val(#l{ke={val_clause,{tuple,Es},B},i=I,vdb=Vdb}, V, Vf, Bef, St0) ->
+ {Eis,Int,St1} = select_extract_tuple(V, Es, I, Vdb, Bef, St0),
+ {Bis,Aft,St2} = match_cg(B, Vf, Int, St1),
+ {length(Es),Eis ++ Bis,Aft,St2};
+select_val(#l{ke={val_clause,{_,Val},B}}, _V, Vf, Bef, St0) ->
+ {Bis,Aft,St1} = match_cg(B, Vf, Bef, St0),
+ {Val,Bis,Aft,St1}.
+
+%% select_extract_tuple(Src, [V], I, Vdb, StackReg, State) ->
+%% {[E],StackReg,State}.
+%% Extract tuple elements, but only if they do not immediately die.
+
+select_extract_tuple(Src, Vs, I, Vdb, Bef, St) ->
+ F = fun ({var,V}, {Int0,Elem}) ->
+ case vdb_find(V, Vdb) of
+ {V,_,L} when L =< I -> {[], {Int0,Elem+1}};
+ _Other ->
+ Reg1 = put_reg(V, Int0#sr.reg),
+ Int1 = Int0#sr{reg=Reg1},
+ Rsrc = fetch_var(Src, Int1),
+ {[{get_tuple_element,Rsrc,Elem,fetch_reg(V, Reg1)}],
+ {Int1,Elem+1}}
+ end
+ end,
+ {Es,{Aft,_}} = flatmapfoldl(F, {Bef,0}, Vs),
+ {Es,Aft,St}.
+
+select_extract_cons(Src, [{var,Hd}, {var,Tl}], I, Vdb, Bef, St) ->
+ {Es,Aft} = case {vdb_find(Hd, Vdb), vdb_find(Tl, Vdb)} of
+ {{_,_,Lhd}, {_,_,Ltl}} when Lhd =< I, Ltl =< I ->
+ %% Both head and tail are dead. No need to generate
+ %% any instruction.
+ {[], Bef};
+ _ ->
+ %% At least one of head and tail will be used,
+ %% but we must always fetch both. We will call
+ %% clear_dead/2 to allow reuse of the register
+ %% in case only of them is used.
+
+ Reg0 = put_reg(Tl, put_reg(Hd, Bef#sr.reg)),
+ Int0 = Bef#sr{reg=Reg0},
+ Rsrc = fetch_var(Src, Int0),
+ Rhd = fetch_reg(Hd, Reg0),
+ Rtl = fetch_reg(Tl, Reg0),
+ Int1 = clear_dead(Int0, I, Vdb),
+ {[{get_list,Rsrc,Rhd,Rtl}], Int1}
+ end,
+ {Es,Aft,St}.
+
+
+guard_clause_cg(#l{ke={guard_clause,G,B},vdb=Vdb}, Fail, Bef, St0) ->
+ {Gis,Int,St1} = guard_cg(G, Fail, Vdb, Bef, St0),
+ {Bis,Aft,St2} = match_cg(B, Fail, Int, St1),
+ {Gis ++ Bis,Aft,St2}.
+
+%% guard_cg(Guard, Fail, Vdb, StackReg, State) ->
+%% {[Ainstr],StackReg,State}.
+%% A guard is a boolean expression of tests. Tests return true or
+%% false. A fault in a test causes the test to return false. Tests
+%% never return the boolean, instead we generate jump code to go to
+%% the correct exit point. Primops and tests all go to the next
+%% instruction on success or jump to a failure label.
+
+guard_cg(#l{ke={protected,Ts,Rs},i=I,vdb=Pdb}, Fail, _Vdb, Bef, St) ->
+ protected_cg(Ts, Rs, Fail, I, Pdb, Bef, St);
+guard_cg(#l{ke={block,Ts},i=I,vdb=Bdb}, Fail, _Vdb, Bef, St) ->
+ guard_cg_list(Ts, Fail, I, Bdb, Bef, St);
+guard_cg(#l{ke={test,Test,As},i=I,vdb=_Tdb}, Fail, Vdb, Bef, St) ->
+ test_cg(Test, As, Fail, I, Vdb, Bef, St);
+guard_cg(G, _Fail, Vdb, Bef, St) ->
+ %%ok = io:fwrite("cg ~w: ~p~n", [?LINE,{G,Fail,Vdb,Bef}]),
+ {Gis,Aft,St1} = cg(G, Vdb, Bef, St),
+ %%ok = io:fwrite("cg ~w: ~p~n", [?LINE,{Aft}]),
+ {Gis,Aft,St1}.
+
+%% protected_cg([Kexpr], [Ret], Fail, I, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
+%% Do a protected. Protecteds without return values are just done
+%% for effect, the return value is not checked, success passes on to
+%% the next instruction and failure jumps to Fail. If there are
+%% return values then these must be set to 'false' on failure,
+%% control always passes to the next instruction.
+
+protected_cg(Ts, [], Fail, I, Vdb, Bef, St0) ->
+ %% Protect these calls, revert when done.
+ {Tis,Aft,St1} = guard_cg_list(Ts, Fail, I, Vdb, Bef,
+ St0#cg{btype=fail,bfail=Fail}),
+ {Tis,Aft,St1#cg{btype=St0#cg.btype,bfail=St0#cg.bfail}};
+protected_cg(Ts, Rs, _Fail, I, Vdb, Bef, St0) ->
+ {Pfail,St1} = new_label(St0),
+ {Psucc,St2} = new_label(St1),
+ {Tis,Aft,St3} = guard_cg_list(Ts, Pfail, I, Vdb, Bef,
+ St2#cg{btype=fail,bfail=Pfail}),
+ %%ok = io:fwrite("cg ~w: ~p~n", [?LINE,{Rs,I,Vdb,Aft}]),
+ %% Set return values to false.
+ Mis = map(fun ({var,V}) -> {move,{atom,false},fetch_var(V, Aft)} end, Rs),
+ Live = {'%live',max_reg(Aft#sr.reg)},
+ {Tis ++ [Live,{jump,{f,Psucc}},
+ {label,Pfail}] ++ Mis ++ [Live,{label,Psucc}],
+ Aft,St3#cg{btype=St0#cg.btype,bfail=St0#cg.bfail}}.
+
+%% test_cg(TestName, Args, Fail, I, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
+%% Generate test instruction. Use explicit fail label here.
+
+test_cg(Test, As, Fail, I, Vdb, Bef, St) ->
+ case test_type(Test, length(As)) of
+ {cond_op,Op} ->
+ Ars = cg_reg_args(As, Bef),
+ Int = clear_dead(Bef, I, Vdb),
+ {[{test,Op,{f,Fail},Ars}],
+ clear_dead(Int, I, Vdb),
+ St};
+ {rev_cond_op,Op} ->
+ [S1,S2] = cg_reg_args(As, Bef),
+ Int = clear_dead(Bef, I, Vdb),
+ {[{test,Op,{f,Fail},[S2,S1]}],
+ clear_dead(Int, I, Vdb),
+ St}
+ end.
+
+test_type(is_atom, 1) -> {cond_op,is_atom};
+test_type(is_boolean, 1) -> {cond_op,is_boolean};
+test_type(is_binary, 1) -> {cond_op,is_binary};
+test_type(is_constant, 1) -> {cond_op,is_constant};
+test_type(is_float, 1) -> {cond_op,is_float};
+test_type(is_function, 1) -> {cond_op,is_function};
+test_type(is_integer, 1) -> {cond_op,is_integer};
+test_type(is_list, 1) -> {cond_op,is_list};
+test_type(is_number, 1) -> {cond_op,is_number};
+test_type(is_pid, 1) -> {cond_op,is_pid};
+test_type(is_port, 1) -> {cond_op,is_port};
+test_type(is_reference, 1) -> {cond_op,is_reference};
+test_type(is_tuple, 1) -> {cond_op,is_tuple};
+test_type('=<', 2) -> {rev_cond_op,is_ge};
+test_type('>', 2) -> {rev_cond_op,is_lt};
+test_type('<', 2) -> {cond_op,is_lt};
+test_type('>=', 2) -> {cond_op,is_ge};
+test_type('==', 2) -> {cond_op,is_eq};
+test_type('/=', 2) -> {cond_op,is_ne};
+test_type('=:=', 2) -> {cond_op,is_eq_exact};
+test_type('=/=', 2) -> {cond_op,is_ne_exact};
+test_type(internal_is_record, 3) -> {cond_op,internal_is_record}.
+
+%% guard_cg_list([Kexpr], Fail, I, Vdb, StackReg, St) ->
+%% {[Ainstr],StackReg,St}.
+
+guard_cg_list(Kes, Fail, I, Vdb, Bef, St0) ->
+ {Keis,{Aft,St1}} =
+ flatmapfoldl(fun (Ke, {Inta,Sta}) ->
+ {Keis,Intb,Stb} =
+ guard_cg(Ke, Fail, Vdb, Inta, Sta),
+ {comment(Inta) ++ Keis,{Intb,Stb}}
+ end, {Bef,St0}, need_heap(Kes, I)),
+ {Keis,Aft,St1}.
+
+%% match_fmf(Fun, LastFail, State, [Clause]) -> {Is,Aft,State}.
+%% This is a special flatmapfoldl for match code gen where we
+%% generate a "failure" label for each clause. The last clause uses
+%% an externally generated failure label, LastFail. N.B. We do not
+%% know or care how the failure labels are used.
+
+match_fmf(F, LastFail, St, [H]) ->
+ F(H, LastFail, St);
+match_fmf(F, LastFail, St0, [H|T]) ->
+ {Fail,St1} = new_label(St0),
+ {R,Aft1,St2} = F(H, Fail, St1),
+ {Rs,Aft2,St3} = match_fmf(F, LastFail, St2, T),
+ {R ++ [{label,Fail}] ++ Rs,sr_merge(Aft1, Aft2),St3};
+match_fmf(_, _, St, []) -> {[],void,St}.
+
+%% call_cg(Func, [Arg], [Ret], Le, Vdb, StackReg, State) ->
+%% {[Ainstr],StackReg,State}.
+%% enter_cg(Func, [Arg], Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
+%% Call and enter first put the arguments into registers and save any
+%% other registers, then clean up and compress the stack and set the
+%% frame size. Finally the actual call is made. Call then needs the
+%% return values filled in.
+
+call_cg({var,V}, As, Rs, Le, Vdb, Bef, St0) ->
+ {Sis,Int} = cg_setup_call(As++[{var,V}], Bef, Le#l.i, Vdb),
+ %% Put return values in registers.
+ Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
+ %% Build complete code and final stack/register state.
+ Arity = length(As),
+ {Frees,Aft} = free_dead(clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb)),
+ {comment({call_fun,{var,V},As}) ++ Sis ++ Frees ++ [{call_fun,Arity}],
+ Aft,need_stack_frame(St0)};
+call_cg({remote,Mod,Name}, As, Rs, Le, Vdb, Bef, St0)
+ when element(1, Mod) == var;
+ element(1, Name) == var ->
+ {Sis,Int} = cg_setup_call(As++[Mod,Name], Bef, Le#l.i, Vdb),
+ %% Put return values in registers.
+ Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
+ %% Build complete code and final stack/register state.
+ Arity = length(As),
+ Call = {apply,Arity},
+ St = need_stack_frame(St0),
+ %%{Call,St1} = build_call(Func, Arity, St0),
+ {Frees,Aft} = free_dead(clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb)),
+ {Sis ++ Frees ++ [Call],Aft,St};
+call_cg(Func, As, Rs, Le, Vdb, Bef, St0) ->
+ {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
+ %% Put return values in registers.
+ Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
+ %% Build complete code and final stack/register state.
+ Arity = length(As),
+ {Call,St1} = build_call(Func, Arity, St0),
+ {Frees,Aft} = free_dead(clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb)),
+ {comment({call,Func,As}) ++ Sis ++ Frees ++ Call,Aft,St1}.
+
+build_call({remote,{atom,erlang},{atom,'!'}}, 2, St0) ->
+ {[send],need_stack_frame(St0)};
+build_call({remote,{atom,Mod},{atom,Name}}, Arity, St0) ->
+ {[{call_ext,Arity,{extfunc,Mod,Name,Arity}}],need_stack_frame(St0)};
+build_call(Name, Arity, St0) when atom(Name) ->
+ {Lbl,St1} = local_func_label(Name, Arity, need_stack_frame(St0)),
+ {[{call,Arity,{f,Lbl}}],St1}.
+
+free_dead(#sr{stk=Stk0}=Aft) ->
+ {Instr,Stk} = free_dead(Stk0, 0, [], []),
+ {Instr,Aft#sr{stk=Stk}}.
+
+free_dead([dead|Stk], Y, Instr, StkAcc) ->
+ %% Note: kill/1 is equivalent to init/1 (translated by beam_asm).
+ %% We use kill/1 to help further optimisation passes.
+ free_dead(Stk, Y+1, [{kill,{yy,Y}}|Instr], [free|StkAcc]);
+free_dead([Any|Stk], Y, Instr, StkAcc) ->
+ free_dead(Stk, Y+1, Instr, [Any|StkAcc]);
+free_dead([], _, Instr, StkAcc) -> {Instr,reverse(StkAcc)}.
+
+enter_cg({var,V}, As, Le, Vdb, Bef, St0) ->
+ {Sis,Int} = cg_setup_call(As++[{var,V}], Bef, Le#l.i, Vdb),
+ %% Build complete code and final stack/register state.
+ Arity = length(As),
+ {comment({call_fun,{var,V},As}) ++ Sis ++ [{call_fun,Arity},return],
+ clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
+ need_stack_frame(St0)};
+enter_cg({remote,Mod,Name}=Func, As, Le, Vdb, Bef, St0)
+ when element(1, Mod) == var;
+ element(1, Name) == var ->
+ {Sis,Int} = cg_setup_call(As++[Mod,Name], Bef, Le#l.i, Vdb),
+ %% Build complete code and final stack/register state.
+ Arity = length(As),
+ Call = {apply_only,Arity},
+ St = need_stack_frame(St0),
+ {comment({enter,Func,As}) ++ Sis ++ [Call],
+ clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
+ St};
+enter_cg(Func, As, Le, Vdb, Bef, St0) ->
+ {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
+ %% Build complete code and final stack/register state.
+ Arity = length(As),
+ {Call,St1} = build_enter(Func, Arity, St0),
+ {comment({enter,Func,As}) ++ Sis ++ Call,
+ clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
+ St1}.
+
+build_enter({remote,{atom,erlang},{atom,'!'}}, 2, St0) ->
+ {[send,return],need_stack_frame(St0)};
+build_enter({remote,{atom,Mod},{atom,Name}}, Arity, St0) ->
+ St1 = case trap_bif(Mod, Name, Arity) of
+ true -> need_stack_frame(St0);
+ false -> St0
+ end,
+ {[{call_ext_only,Arity,{extfunc,Mod,Name,Arity}}],St1};
+build_enter(Name, Arity, St0) when is_atom(Name) ->
+ {Lbl,St1} = local_func_label(Name, Arity, St0),
+ {[{call_only,Arity,{f,Lbl}}],St1}.
+
+%% local_func_label(Name, Arity, State) -> {Label,State'}
+%% Get the function entry label for a local function.
+
+local_func_label(Name, Arity, St0) ->
+ Key = {Name,Arity},
+ case keysearch(Key, 1, St0#cg.functable) of
+ {value,{Key,Label}} ->
+ {Label,St0};
+ false ->
+ {Label,St1} = new_label(St0),
+ {Label,St1#cg{functable=[{Key,Label}|St1#cg.functable]}}
+ end.
+
+%% need_stack_frame(State) -> State'
+%% Make a note in the state that this function will need a stack frame.
+
+need_stack_frame(#cg{need_frame=true}=St) -> St;
+need_stack_frame(St) -> St#cg{need_frame=true}.
+
+%% trap_bif(Mod, Name, Arity) -> true|false
+%% Trap bifs that need a stack frame.
+
+trap_bif(erlang, '!', 2) -> true;
+trap_bif(erlang, link, 1) -> true;
+trap_bif(erlang, unlink, 1) -> true;
+trap_bif(erlang, monitor_node, 2) -> true;
+trap_bif(erlang, group_leader, 2) -> true;
+trap_bif(erlang, exit, 2) -> true;
+trap_bif(_, _, _) -> false.
+
+%% bif_cg(Bif, [Arg], [Ret], Le, Vdb, StackReg, State) ->
+%% {[Ainstr],StackReg,State}.
+
+bif_cg(dsetelement, [Index0,Tuple0,New0], _Rs, Le, Vdb, Bef, St0) ->
+ [New,Tuple,{integer,Index1}] = cg_reg_args([New0,Tuple0,Index0], Bef),
+ Index = Index1-1,
+ {[{set_tuple_element,New,Tuple,Index}],
+ clear_dead(Bef, Le#l.i, Vdb), St0};
+bif_cg({make_fun,Func,Arity,Index,Uniq}, As, Rs, Le, Vdb, Bef, St0) ->
+ %% This behaves more like a function call.
+ {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
+ Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
+ {FuncLbl,St1} = local_func_label(Func, Arity, St0),
+ MakeFun = case St0#cg.new_funs of
+ true -> {make_fun2,{f,FuncLbl},Index,Uniq,length(As)};
+ false -> {make_fun,{f,FuncLbl},Uniq,length(As)}
+ end,
+ {comment({make_fun,{Func,Arity,Uniq},As}) ++ Sis ++
+ [MakeFun],
+ clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb),
+ St1};
+bif_cg(Bif, As, [{var,V}], Le, Vdb, Bef, St0) ->
+ Ars = cg_reg_args(As, Bef),
+
+ %% If we are inside a catch, we must save everything that will
+ %% be alive after the catch (because the BIF might fail and there
+ %% will be a jump to the code after the catch).
+ %% Currently, we are somewhat pessimistic in
+ %% that we save any variable that will be live after this BIF call.
+
+ {Sis,Int0} =
+ case St0#cg.in_catch of
+ true -> adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb);
+ false -> {[],Bef}
+ end,
+
+ Int1 = clear_dead(Int0, Le#l.i, Vdb),
+ Reg = put_reg(V, Int1#sr.reg),
+ Int = Int1#sr{reg=Reg},
+ Dst = fetch_reg(V, Reg),
+ {Sis ++ [{bif,Bif,bif_fail(St0#cg.btype, St0#cg.bfail, length(Ars)),Ars,Dst}],
+ clear_dead(Int, Le#l.i, Vdb), St0}.
+
+bif_fail(_, _, 0) -> nofail;
+bif_fail(exit, _, _) -> {f,0};
+bif_fail(fail, Fail, _) -> {f,Fail}.
+
+%% recv_loop_cg(TimeOut, ReceiveVar, ReceiveMatch, TimeOutExprs,
+%% [Ret], Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
+
+recv_loop_cg(Te, Rvar, Rm, Tes, Rs, Le, Vdb, Bef, St0) ->
+ {Sis,Int0} = adjust_stack(Bef, Le#l.i, Le#l.i, Vdb),
+ Int1 = Int0#sr{reg=clear_regs(Int0#sr.reg)},
+ %% Get labels.
+ {Rl,St1} = new_label(St0),
+ {Tl,St2} = new_label(St1),
+ {Bl,St3} = new_label(St2),
+ St4 = St3#cg{break=Bl,recv=Rl}, %Set correct receive labels
+ {Ris,Raft,St5} = cg_recv_mesg(Rvar, Rm, Tl, Int1, St4),
+ {Wis,Taft,St6} = cg_recv_wait(Te, Tes, Le#l.i, Int1, St5),
+ Int2 = sr_merge(Raft, Taft), %Merge stack/registers
+ Reg = load_vars(Rs, Int2#sr.reg),
+ {Sis ++ Ris ++ [{label,Tl}] ++ Wis ++ [{label,Bl}],
+ clear_dead(Int2#sr{reg=Reg}, Le#l.i, Vdb),
+ St6#cg{break=St0#cg.break,recv=St0#cg.recv}}.
+
+%% cg_recv_mesg( ) -> {[Ainstr],Aft,St}.
+
+cg_recv_mesg({var,R}, Rm, Tl, Bef, St0) ->
+ Int0 = Bef#sr{reg=put_reg(R, Bef#sr.reg)},
+ Ret = fetch_reg(R, Int0#sr.reg),
+ %% Int1 = clear_dead(Int0, I, Rm#l.vdb),
+ Int1 = Int0,
+ {Mis,Int2,St1} = match_cg(Rm, none, Int1, St0),
+ {[{'%live',0},{label,St1#cg.recv},{loop_rec,{f,Tl},Ret}|Mis],Int2,St1}.
+
+%% cg_recv_wait(Te, Tes, I, Vdb, Int2, St3) -> {[Ainstr],Aft,St}.
+
+cg_recv_wait({atom,infinity}, Tes, I, Bef, St0) ->
+ %% We know that the 'after' body will never be executed.
+ %% But to keep the stack and register information up to date,
+ %% we will generate the code for the 'after' body, and then discard it.
+ Int1 = clear_dead(Bef, I, Tes#l.vdb),
+ {_,Int2,St1} = cg_block(Tes#l.ke, Tes#l.i, Tes#l.vdb,
+ Int1#sr{reg=clear_regs(Int1#sr.reg)}, St0),
+ {[{wait,{f,St1#cg.recv}}],Int2,St1};
+cg_recv_wait({integer,0}, Tes, _I, Bef, St0) ->
+ {Tis,Int,St1} = cg_block(Tes#l.ke, Tes#l.i, Tes#l.vdb, Bef, St0),
+ {[timeout|Tis],Int,St1};
+cg_recv_wait(Te, Tes, I, Bef, St0) ->
+ Reg = cg_reg_arg(Te, Bef),
+ %% Must have empty registers here! Bug if anything in registers.
+ Int0 = clear_dead(Bef, I, Tes#l.vdb),
+ {Tis,Int,St1} = cg_block(Tes#l.ke, Tes#l.i, Tes#l.vdb,
+ Int0#sr{reg=clear_regs(Int0#sr.reg)}, St0),
+ {[{wait_timeout,{f,St1#cg.recv},Reg},timeout] ++ Tis,Int,St1}.
+
+%% recv_next_cg(Le, Vdb, StackReg, St) -> {[Ainstr],StackReg,St}.
+%% Use adjust stack to clear stack, but only need it for Aft.
+
+recv_next_cg(Le, Vdb, Bef, St) ->
+ {Sis,Aft} = adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb),
+ {[{loop_rec_end,{f,St#cg.recv}}] ++ Sis,Aft,St}. %Joke
+
+%% try_cg(TryBlock, [BodyVar], TryBody, [ExcpVar], TryHandler, [Ret],
+%% Le, Vdb, StackReg, St) -> {[Ainstr],StackReg,St}.
+
+try_cg(Ta, Vs, Tb, Evs, Th, Rs, Le, Vdb, Bef, St0) ->
+ {B,St1} = new_label(St0), %Body label
+ {H,St2} = new_label(St1), %Handler label
+ {E,St3} = new_label(St2), %End label
+ TryTag = Ta#l.i,
+ Int1 = Bef#sr{stk=put_catch(TryTag, Bef#sr.stk)},
+ TryReg = fetch_stack({catch_tag,TryTag}, Int1#sr.stk),
+ {Ais,Int2,St4} = cg(Ta, Vdb, Int1, St3#cg{break=B,in_catch=true}),
+ Int3 = Int2#sr{stk=drop_catch(TryTag, Int2#sr.stk)},
+ St5 = St4#cg{break=E,in_catch=St3#cg.in_catch},
+ {Bis,Baft,St6} = cg(Tb, Vdb, Int3#sr{reg=load_vars(Vs, Int3#sr.reg)}, St5),
+ {His,Haft,St7} = cg(Th, Vdb, Int3#sr{reg=load_vars(Evs, Int3#sr.reg)}, St6),
+ Int4 = sr_merge(Baft, Haft), %Merge stack/registers
+ Aft = Int4#sr{reg=load_vars(Rs, Int4#sr.reg)},
+ {[{'try',TryReg,{f,H}}] ++ Ais ++
+ [{label,B},{try_end,TryReg}] ++ Bis ++
+ [{label,H},{try_case,TryReg}] ++ His ++
+ [{label,E}],
+ clear_dead(Aft, Le#l.i, Vdb),
+ St7#cg{break=St0#cg.break}}.
+
+%% catch_cg(CatchBlock, Ret, Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
+
+catch_cg(C, {var,R}, Le, Vdb, Bef, St0) ->
+ {B,St1} = new_label(St0),
+ CatchTag = Le#l.i,
+ Int1 = Bef#sr{stk=put_catch(CatchTag, Bef#sr.stk)},
+ CatchReg = fetch_stack({catch_tag,CatchTag}, Int1#sr.stk),
+ {Cis,Int2,St2} = cg_block(C, Le#l.i, Le#l.vdb, Int1,
+ St1#cg{break=B,in_catch=true}),
+ Aft = Int2#sr{reg=load_reg(R, 0, Int2#sr.reg),
+ stk=drop_catch(CatchTag, Int2#sr.stk)},
+ {[{'catch',CatchReg,{f,B}}] ++ Cis ++
+ [{label,B},{catch_end,CatchReg}],
+ clear_dead(Aft, Le#l.i, Vdb),
+ St2#cg{break=St1#cg.break,in_catch=St1#cg.in_catch}}.
+
+%% set_cg([Var], Constr, Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
+%% We have to be careful how a 'set' works. First the structure is
+%% built, then it is filled and finally things can be cleared. The
+%% annotation must reflect this and make sure that the return
+%% variable is allocated first.
+%%
+%% put_list for constructing a cons is an atomic instruction
+%% which can safely resuse one of the source registers as target.
+%% Also binaries can reuse a source register as target.
+
+set_cg([{var,R}], {cons,Es}, Le, Vdb, Bef, St) ->
+ [S1,S2] = map(fun ({var,V}) -> fetch_var(V, Bef);
+ (Other) -> Other
+ end, Es),
+ Int0 = clear_dead(Bef, Le#l.i, Vdb),
+ Int1 = Int0#sr{reg=put_reg(R, Int0#sr.reg)},
+ Ret = fetch_reg(R, Int1#sr.reg),
+ {[{put_list,S1,S2,Ret}], Int1, St};
+set_cg([{var,R}], {old_binary,Segs}, Le, Vdb, Bef, St) ->
+ Fail = bif_fail(St#cg.btype, St#cg.bfail, 42),
+ PutCode = cg_bin_put(Segs, Fail, Bef),
+ Code = cg_binary_old(PutCode),
+ Int0 = clear_dead(Bef, Le#l.i, Vdb),
+ Aft = Int0#sr{reg=put_reg(R, Int0#sr.reg)},
+ Ret = fetch_reg(R, Aft#sr.reg),
+ {Code ++ [{bs_final,Fail,Ret}],Aft,St};
+set_cg([{var,R}], {binary,Segs}, Le, Vdb, Bef, #cg{in_catch=InCatch}=St) ->
+ Int0 = Bef#sr{reg=put_reg(R, Bef#sr.reg)},
+ Target = fetch_reg(R, Int0#sr.reg),
+ Fail = bif_fail(St#cg.btype, St#cg.bfail, 42),
+ Temp = find_scratch_reg(Int0#sr.reg),
+ PutCode = cg_bin_put(Segs, Fail, Bef),
+ {Sis,Int1} =
+ case InCatch of
+ true -> adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb);
+ false -> {[],Int0}
+ end,
+ Aft = clear_dead(Int1, Le#l.i, Vdb),
+ Code = cg_binary(PutCode, Target, Temp, Fail, Aft),
+ {Sis++Code,Aft,St};
+set_cg([{var,R}], Con, Le, Vdb, Bef, St) ->
+ %% Find a place for the return register first.
+ Int = Bef#sr{reg=put_reg(R, Bef#sr.reg)},
+ Ret = fetch_reg(R, Int#sr.reg),
+ Ais = case Con of
+ {tuple,Es} ->
+ [{put_tuple,length(Es),Ret}] ++ cg_build_args(Es, Bef);
+ {var,V} -> % Normally removed by kernel optimizer.
+ [{move,fetch_var(V, Int),Ret}];
+ {string,Str} ->
+ [{put_string,length(Str),{string,Str},Ret}];
+ Other ->
+ [{move,Other,Ret}]
+ end,
+ {Ais,clear_dead(Int, Le#l.i, Vdb),St};
+set_cg([], {binary,Segs}, Le, Vdb, Bef, St) ->
+ Fail = bif_fail(St#cg.btype, St#cg.bfail, 42),
+ Target = find_scratch_reg(Bef#sr.reg),
+ Temp = find_scratch_reg(put_reg(Target, Bef#sr.reg)),
+ PutCode = cg_bin_put(Segs, Fail, Bef),
+ Code = cg_binary(PutCode, Target, Temp, Fail, Bef),
+ Aft = clear_dead(Bef, Le#l.i, Vdb),
+ {Code,Aft,St};
+set_cg([], {old_binary,Segs}, Le, Vdb, Bef, St) ->
+ Fail = bif_fail(St#cg.btype, St#cg.bfail, 42),
+ PutCode = cg_bin_put(Segs, Fail, Bef),
+ Ais0 = cg_binary_old(PutCode),
+ Ret = find_scratch_reg(Bef#sr.reg),
+ Ais = Ais0 ++ [{bs_final,Fail,Ret}],
+ {Ais,clear_dead(Bef, Le#l.i, Vdb),St};
+set_cg([], _, Le, Vdb, Bef, St) ->
+ %% This should have been stripped by compiler, just cleanup.
+ {[],clear_dead(Bef, Le#l.i, Vdb), St}.
+
+
+%%%
+%%% Code generation for constructing binaries.
+%%%
+
+cg_binary(PutCode, Target, Temp, Fail, Bef) ->
+ SzCode = cg_binary_size(PutCode, Target, Temp, Fail),
+ MaxRegs = max_reg(Bef#sr.reg),
+ Code = SzCode ++ [{bs_init2,Fail,Target,MaxRegs,{field_flags,[]},Target}|PutCode],
+ cg_bin_opt(Code).
+
+cg_binary_size(PutCode, Target, Temp, Fail) ->
+ Szs = cg_binary_size_1(PutCode, 0, []),
+ cg_binary_size_expr(Szs, Target, Temp, Fail).
+
+cg_binary_size_1([{_Put,_Fail,S,U,_Flags,Src}|T], Bits, Acc) ->
+ cg_binary_size_2(S, U, Src, T, Bits, Acc);
+cg_binary_size_1([], Bits, Acc) ->
+ Bytes = Bits div 8,
+ RemBits = Bits rem 8,
+ Res = sort([{1,{integer,RemBits}},{8,{integer,Bytes}}|Acc]),
+ cg_binary_size_3(Res).
+
+cg_binary_size_2({integer,N}, U, _, Next, Bits, Acc) ->
+ cg_binary_size_1(Next, Bits+N*U, Acc);
+cg_binary_size_2({atom,all}, 8, E, Next, Bits, Acc) ->
+ cg_binary_size_1(Next, Bits, [{8,{size,E}}|Acc]);
+cg_binary_size_2(Reg, 1, _, Next, Bits, Acc) ->
+ cg_binary_size_1(Next, Bits, [{1,Reg}|Acc]);
+cg_binary_size_2(Reg, 8, _, Next, Bits, Acc) ->
+ cg_binary_size_1(Next, Bits, [{8,Reg}|Acc]);
+cg_binary_size_2(Reg, U, _, Next, Bits, Acc) ->
+ cg_binary_size_1(Next, Bits, [{1,{'*',Reg,U}}|Acc]).
+
+cg_binary_size_3([{_,{integer,0}}|T]) ->
+ cg_binary_size_3(T);
+cg_binary_size_3([{U,S1},{U,S2}|T]) ->
+ {L0,Rest} = cg_binary_size_4(T, U, []),
+ L = [S1,S2|L0],
+ [{U,L}|cg_binary_size_3(Rest)];
+cg_binary_size_3([{U,S}|T]) ->
+ [{U,[S]}|cg_binary_size_3(T)];
+cg_binary_size_3([]) -> [].
+
+cg_binary_size_4([{U,S}|T], U, Acc) ->
+ cg_binary_size_4(T, U, [S|Acc]);
+cg_binary_size_4(T, _, Acc) ->
+ {Acc,T}.
+
+%% cg_binary_size_expr/4
+%% Generate code for calculating the resulting size of a binary.
+cg_binary_size_expr(Sizes, Target, Temp, Fail) ->
+ cg_binary_size_expr_1(Sizes, Target, Temp, Fail,
+ [{move,{integer,0},Target}]).
+
+cg_binary_size_expr_1([{1,E0}|T], Target, Temp, Fail, Acc) ->
+ E1 = cg_gen_binsize(E0, Target, Temp, Fail, Acc),
+ E = [{bs_bits_to_bytes,Fail,Target,Target}|E1],
+ cg_binary_size_expr_1(T, Target, Temp, Fail, E);
+cg_binary_size_expr_1([{8,E0}], Target, Temp, Fail, Acc) ->
+ E = cg_gen_binsize(E0, Target, Temp, Fail, Acc),
+ reverse(E);
+cg_binary_size_expr_1([], _, _, _, Acc) -> reverse(Acc).
+
+cg_gen_binsize([{'*',A,B}|T], Target, Temp, Fail, Acc) ->
+ cg_gen_binsize(T, Target, Temp, Fail,
+ [{bs_add,Fail,[Target,A,B],Target}|Acc]);
+cg_gen_binsize([{size,B}|T], Target, Temp, Fail, Acc) ->
+ cg_gen_binsize([Temp|T], Target, Temp, Fail,
+ [{bif,size,Fail,[B],Temp}|Acc]);
+cg_gen_binsize([E0|T], Target, Temp, Fail, Acc) ->
+ cg_gen_binsize(T, Target, Temp, Fail,
+ [{bs_add,Fail,[Target,E0,1],Target}|Acc]);
+cg_gen_binsize([], _, _, _, Acc) -> Acc.
+
+%% cg_bin_opt(Code0) -> Code
+%% Optimize the size calculations for binary construction.
+
+cg_bin_opt([{move,{integer,0},D},{bs_add,_,[D,{integer,_}=S,1],Dst}|Is]) ->
+ cg_bin_opt([{move,S,Dst}|Is]);
+cg_bin_opt([{move,{integer,0},D},{bs_add,Fail,[D,S,U],Dst}|Is]) ->
+ cg_bin_opt([{bs_add,Fail,[{integer,0},S,U],Dst}|Is]);
+cg_bin_opt([{move,{integer,Bytes},D},{bs_init2,Fail,D,Regs0,Flags,D}|Is]) ->
+ Regs = cg_bo_newregs(Regs0, D),
+ cg_bin_opt([{bs_init2,Fail,Bytes,Regs,Flags,D}|Is]);
+cg_bin_opt([{move,Src,D},{bs_init2,Fail,D,Regs0,Flags,D}|Is]) ->
+ Regs = cg_bo_newregs(Regs0, D),
+ cg_bin_opt([{bs_init2,Fail,Src,Regs,Flags,D}|Is]);
+cg_bin_opt([{move,Src,Dst},{bs_bits_to_bytes,Fail,Dst,Dst}|Is]) ->
+ cg_bin_opt([{bs_bits_to_bytes,Fail,Src,Dst}|Is]);
+cg_bin_opt([{move,Src1,Dst},{bs_add,Fail,[Dst,Src2,U],Dst}|Is]) ->
+ cg_bin_opt([{bs_add,Fail,[Src1,Src2,U],Dst}|Is]);
+cg_bin_opt([{bs_bits_to_bytes,Fail,{integer,N},_}|Is0]) when N rem 8 =/= 0 ->
+ case Fail of
+ {f,0} ->
+ Is = [{move,{atom,badarg},{x,0}},
+ {call_ext_only,1,{extfunc,erlang,error,1}}|Is0],
+ cg_bin_opt(Is);
+ _ ->
+ cg_bin_opt([{jump,Fail}|Is0])
+ end;
+cg_bin_opt([I|Is]) ->
+ [I|cg_bin_opt(Is)];
+cg_bin_opt([]) -> [].
+
+cg_bo_newregs(R, {x,X}) when R-1 =:= X -> R-1;
+cg_bo_newregs(R, _) -> R.
+
+%% Common for new and old binary code generation.
+
+cg_bin_put({bin_seg,S0,U,T,Fs,[E0,Next]}, Fail, Bef) ->
+ S1 = case S0 of
+ {var,Sv} -> fetch_var(Sv, Bef);
+ _ -> S0
+ end,
+ E1 = case E0 of
+ {var,V} -> fetch_var(V, Bef);
+ Other -> Other
+ end,
+ Op = case T of
+ integer -> bs_put_integer;
+ binary -> bs_put_binary;
+ float -> bs_put_float
+ end,
+ [{Op,Fail,S1,U,{field_flags,Fs},E1}|cg_bin_put(Next, Fail, Bef)];
+cg_bin_put(bin_end, _, _) -> [].
+
+%% Old style.
+
+cg_binary_old(PutCode) ->
+ [cg_bs_init(PutCode)] ++ need_bin_buf(PutCode).
+
+cg_bs_init(Code) ->
+ {Size,Fs} = foldl(fun ({_,_,{integer,N},U,_,_}, {S,Fs}) ->
+ {S + N*U,Fs};
+ (_, {S,_}) ->
+ {S,[]}
+ end, {0,[exact]}, Code),
+ {bs_init,(Size+7) div 8,{field_flags,Fs}}.
+
+need_bin_buf(Code0) ->
+ {Code1,F,H} = foldr(fun ({_,_,{integer,N},U,_,_}=Bs, {Code,F,H}) ->
+ {[Bs|Code],F,H + N*U};
+ ({_,_,_,_,_,_}=Bs, {Code,F,H}) ->
+ {[Bs|need_bin_buf_need(H, F, Code)],true,0}
+ end, {[],false,0}, Code0),
+ need_bin_buf_need(H, F, Code1).
+
+need_bin_buf_need(0, false, Rest) -> Rest;
+need_bin_buf_need(H, _, Rest) -> [{bs_need_buf,H}|Rest].
+
+cg_build_args(As, Bef) ->
+ map(fun ({var,V}) -> {put,fetch_var(V, Bef)};
+ (Other) -> {put,Other}
+ end, As).
+
+%% return_cg([Val], Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
+%% break_cg([Val], Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
+%% These are very simple, just put return/break values in registers
+%% from 0, then return/break. Use the call setup to clean up stack,
+%% but must clear registers to ensure sr_merge works correctly.
+
+return_cg(Rs, Le, Vdb, Bef, St) ->
+ {Ms,Int} = cg_setup_call(Rs, Bef, Le#l.i, Vdb),
+ {comment({return,Rs}) ++ Ms ++ [return],
+ Int#sr{reg=clear_regs(Int#sr.reg)},St}.
+
+break_cg(Bs, Le, Vdb, Bef, St) ->
+ {Ms,Int} = cg_setup_call(Bs, Bef, Le#l.i, Vdb),
+ {comment({break,Bs}) ++ Ms ++ [{jump,{f,St#cg.break}}],
+ Int#sr{reg=clear_regs(Int#sr.reg)},St}.
+
+%% cg_reg_arg(Arg0, Info) -> Arg
+%% cg_reg_args([Arg0], Info) -> [Arg]
+%% Convert argument[s] into registers. Literal values are returned unchanged.
+
+cg_reg_args(As, Bef) -> [cg_reg_arg(A, Bef) || A <- As].
+
+cg_reg_arg({var,V}, Bef) -> fetch_var(V, Bef);
+cg_reg_arg(Literal, _) -> Literal.
+
+%% cg_setup_call([Arg], Bef, Cur, Vdb) -> {[Instr],Aft}.
+%% Do the complete setup for a call/enter.
+
+cg_setup_call(As, Bef, I, Vdb) ->
+ {Ms,Int0} = cg_call_args(As, Bef, I, Vdb),
+ %% Have set up arguments, can now clean up, compress and save to stack.
+ Int1 = Int0#sr{stk=clear_dead_stk(Int0#sr.stk, I, Vdb),res=[]},
+ {Sis,Int2} = adjust_stack(Int1, I, I+1, Vdb),
+ {Ms ++ Sis ++ [{'%live',length(As)}],Int2}.
+
+%% cg_call_args([Arg], SrState) -> {[Instr],SrState}.
+%% Setup the arguments to a call/enter/bif. Put the arguments into
+%% consecutive registers starting at {x,0} moving any data which
+%% needs to be saved. Return a modified SrState structure with the
+%% new register contents. N.B. the resultant register info will
+%% contain non-variable values when there are non-variable values.
+%%
+%% This routine is complicated by unsaved values in x registers.
+%% We'll move away any unsaved values that are in the registers
+%% to be overwritten by the arguments.
+
+cg_call_args(As, Bef, I, Vdb) ->
+ Regs0 = load_arg_regs(Bef#sr.reg, As),
+ Unsaved = unsaved_registers(Regs0, Bef#sr.stk, I, I+1, Vdb),
+ {UnsavedMoves,Regs} = move_unsaved(Unsaved, Bef#sr.reg, Regs0),
+ Moves0 = gen_moves(As, Bef),
+ Moves = order_moves(Moves0, find_scratch_reg(Regs)),
+ {UnsavedMoves ++ Moves,Bef#sr{reg=Regs}}.
+
+%% load_arg_regs([Reg], Arguments) -> [Reg]
+%% Update the register descriptor to include the arguments (from {x,0}
+%% and upwards). Values in argument register are overwritten.
+%% Values in x registers above the arguments are preserved.
+
+load_arg_regs(Regs, As) -> load_arg_regs(Regs, As, 0).
+
+load_arg_regs([_|Rs], [{var,V}|As], I) -> [{I,V}|load_arg_regs(Rs, As, I+1)];
+load_arg_regs([_|Rs], [A|As], I) -> [{I,A}|load_arg_regs(Rs, As, I+1)];
+load_arg_regs([], [{var,V}|As], I) -> [{I,V}|load_arg_regs([], As, I+1)];
+load_arg_regs([], [A|As], I) -> [{I,A}|load_arg_regs([], As, I+1)];
+load_arg_regs(Rs, [], _) -> Rs.
+
+%% Returns the variables must be saved and are currently in the
+%% x registers that are about to be overwritten by the arguments.
+
+unsaved_registers(Regs, Stk, Fb, Lf, Vdb) ->
+ [V || {V,F,L} <- Vdb,
+ F < Fb,
+ L >= Lf,
+ not on_stack(V, Stk),
+ not in_reg(V, Regs)].
+
+in_reg(V, Regs) -> keymember(V, 2, Regs).
+
+%% Move away unsaved variables from the registers that are to be
+%% overwritten by the arguments.
+move_unsaved(Vs, OrigRegs, NewRegs) ->
+ move_unsaved(Vs, OrigRegs, NewRegs, []).
+
+move_unsaved([V|Vs], OrigRegs, NewRegs0, Acc) ->
+ NewRegs = put_reg(V, NewRegs0),
+ Src = fetch_reg(V, OrigRegs),
+ Dst = fetch_reg(V, NewRegs),
+ move_unsaved(Vs, OrigRegs, NewRegs, [{move,Src,Dst}|Acc]);
+move_unsaved([], _, Regs, Acc) -> {Acc,Regs}.
+
+%% gen_moves(As, Sr)
+%% Generate the basic move instruction to move the arguments
+%% to their proper registers. The list will be sorted on
+%% destinations. (I.e. the move to {x,0} will be first --
+%% see the comment to order_moves/2.)
+
+gen_moves(As, Sr) -> gen_moves(As, Sr, 0, []).
+
+gen_moves([{var,V}|As], Sr, I, Acc) ->
+ case fetch_var(V, Sr) of
+ {x,I} -> gen_moves(As, Sr, I+1, Acc);
+ Reg -> gen_moves(As, Sr, I+1, [{move,Reg,{x,I}}|Acc])
+ end;
+gen_moves([A|As], Sr, I, Acc) ->
+ gen_moves(As, Sr, I+1, [{move,A,{x,I}}|Acc]);
+gen_moves([], _, _, Acc) -> lists:keysort(3, Acc).
+
+%% order_moves([Move], ScratchReg) -> [Move]
+%% Orders move instruction so that source registers are not
+%% destroyed before they are used. If there are cycles
+%% (such as {move,{x,0},{x,1}}, {move,{x,1},{x,1}}),
+%% the scratch register is used to break up the cycle.
+%% If possible, the first move of the input list is placed
+%% last in the result list (to make the move to {x,0} occur
+%% just before the call to allow the Beam loader to coalesce
+%% the instructions).
+
+order_moves(Ms, Scr) -> order_moves(Ms, Scr, []).
+
+order_moves([{move,_,_}=M|Ms0], ScrReg, Acc0) ->
+ {Chain,Ms} = collect_chain(Ms0, [M], ScrReg),
+ Acc = reverse(Chain, Acc0),
+ order_moves(Ms, ScrReg, Acc);
+order_moves([], _, Acc) -> Acc.
+
+collect_chain(Ms, Path, ScrReg) ->
+ collect_chain(Ms, Path, [], ScrReg).
+
+collect_chain([{move,Src,Same}=M|Ms0], [{move,Same,_}|_]=Path, Others, ScrReg) ->
+ case keysearch(Src, 3, Path) of
+ {value,_} -> %We have a cycle.
+ {break_up_cycle(M, Path, ScrReg),reverse(Others, Ms0)};
+ false ->
+ collect_chain(reverse(Others, Ms0), [M|Path], [], ScrReg)
+ end;
+collect_chain([M|Ms], Path, Others, ScrReg) ->
+ collect_chain(Ms, Path, [M|Others], ScrReg);
+collect_chain([], Path, Others, _) ->
+ {Path,Others}.
+
+break_up_cycle({move,Src,_}=M, Path, ScrReg) ->
+ [{move,ScrReg,Src},M|break_up_cycle1(Src, Path, ScrReg)].
+
+break_up_cycle1(Dst, [{move,Src,Dst}|Path], ScrReg) ->
+ [{move,Src,ScrReg}|Path];
+break_up_cycle1(Dst, [M|Path], LastMove) ->
+ [M|break_up_cycle1(Dst, Path, LastMove)].
+
+%% clear_dead(Sr, Until, Vdb) -> Aft.
+%% Remove all variables in Sr which have died AT ALL so far.
+
+clear_dead(Sr, Until, Vdb) ->
+ Sr#sr{reg=clear_dead_reg(Sr, Until, Vdb),
+ stk=clear_dead_stk(Sr#sr.stk, Until, Vdb)}.
+
+clear_dead_reg(Sr, Until, Vdb) ->
+ Reg = map(fun ({I,V}) ->
+ case vdb_find(V, Vdb) of
+ {V,_,L} when L > Until -> {I,V};
+ _ -> free %Remove anything else
+ end;
+ ({reserved,I,V}) -> {reserved,I,V};
+ (free) -> free
+ end, Sr#sr.reg),
+ reserve(Sr#sr.res, Reg, Sr#sr.stk).
+
+clear_dead_stk(Stk, Until, Vdb) ->
+ map(fun ({V}) ->
+ case vdb_find(V, Vdb) of
+ {V,_,L} when L > Until -> {V};
+ _ -> dead %Remove anything else
+ end;
+ (free) -> free;
+ (dead) -> dead
+ end, Stk).
+
+%% sr_merge(Sr1, Sr2) -> Sr.
+%% Merge two stack/register states keeping the longest of both stack
+%% and register. Perform consistency check on both, elements must be
+%% the same. Allow frame size 'void' to make easy creation of
+%% "empty" frame.
+
+sr_merge(#sr{reg=R1,stk=S1,res=[]}, #sr{reg=R2,stk=S2,res=[]}) ->
+ #sr{reg=longest(R1, R2),stk=longest(S1, S2),res=[]};
+sr_merge(void, S2) -> S2#sr{res=[]};
+sr_merge(S1, void) -> S1#sr{res=[]}.
+
+longest([H|T1], [H|T2]) -> [H|longest(T1, T2)];
+longest([dead|T1], [free|T2]) -> [dead|longest(T1, T2)];
+longest([free|T1], [dead|T2]) -> [dead|longest(T1, T2)];
+longest([dead|T1], []) -> [dead|T1];
+longest([], [dead|T2]) -> [dead|T2];
+longest([free|T1], []) -> [free|T1];
+longest([], [free|T2]) -> [free|T2];
+longest([], []) -> [].
+
+%% adjust_stack(Bef, FirstBefore, LastFrom, Vdb) -> {[Ainstr],Aft}.
+%% Do complete stack adjustment by compressing stack and adding
+%% variables to be saved. Try to optimise ordering on stack by
+%% having reverse order to their lifetimes.
+%%
+%% In Beam, there is a fixed stack frame and no need to do stack compression.
+
+adjust_stack(Bef, Fb, Lf, Vdb) ->
+ Stk0 = Bef#sr.stk,
+ {Stk1,Saves} = save_stack(Stk0, Fb, Lf, Vdb),
+ {saves(Saves, Bef#sr.reg, Stk1),
+ Bef#sr{stk=Stk1}}.
+
+%% save_stack(Stack, FirstBefore, LastFrom, Vdb) -> {[SaveVar],NewStack}.
+%% Save variables which are used past current point and which are not
+%% already on the stack.
+
+save_stack(Stk0, Fb, Lf, Vdb) ->
+ %% New variables that are in use but not on stack.
+ New = [ {V,F,L} || {V,F,L} <- Vdb,
+ F < Fb,
+ L >= Lf,
+ not on_stack(V, Stk0) ],
+ %% Add new variables that are not just dropped immediately.
+ %% N.B. foldr works backwards from the end!!
+ Saves = [ V || {V,_,_} <- keysort(3, New) ],
+ Stk1 = foldr(fun (V, Stk) -> put_stack(V, Stk) end, Stk0, Saves),
+ {Stk1,Saves}.
+
+%% saves([SaveVar], Reg, Stk) -> [{move,Reg,Stk}].
+%% Generate move instructions to save variables onto stack. The
+%% stack/reg info used is that after the new stack has been made.
+
+saves(Ss, Reg, Stk) ->
+ Res = map(fun (V) ->
+ {move,fetch_reg(V, Reg),fetch_stack(V, Stk)}
+ end, Ss),
+ Res.
+
+%% comment(C) -> ['%'{C}].
+
+%comment(C) -> [{'%',C}].
+comment(_) -> [].
+
+%% fetch_var(VarName, StkReg) -> r{R} | sp{Sp}.
+%% find_var(VarName, StkReg) -> ok{r{R} | sp{Sp}} | error.
+%% Fetch/find a variable in either the registers or on the
+%% stack. Fetch KNOWS it's there.
+
+fetch_var(V, Sr) ->
+ case find_reg(V, Sr#sr.reg) of
+ {ok,R} -> R;
+ error -> fetch_stack(V, Sr#sr.stk)
+ end.
+
+% find_var(V, Sr) ->
+% case find_reg(V, Sr#sr.reg) of
+% {ok,R} -> {ok,R};
+% error ->
+% case find_stack(V, Sr#sr.stk) of
+% {ok,S} -> {ok,S};
+% error -> error
+% end
+% end.
+
+load_vars(Vs, Regs) ->
+ foldl(fun ({var,V}, Rs) -> put_reg(V, Rs) end, Regs, Vs).
+
+%% put_reg(Val, Regs) -> Regs.
+%% load_reg(Val, Reg, Regs) -> Regs.
+%% free_reg(Val, Regs) -> Regs.
+%% find_reg(Val, Regs) -> ok{r{R}} | error.
+%% fetch_reg(Val, Regs) -> r{R}.
+%% Functions to interface the registers.
+%% put_reg puts a value into a free register,
+%% load_reg loads a value into a fixed register
+%% free_reg frees a register containing a specific value.
+
+% put_regs(Vs, Rs) -> foldl(fun put_reg/2, Rs, Vs).
+
+put_reg(V, Rs) -> put_reg_1(V, Rs, 0).
+
+put_reg_1(V, [free|Rs], I) -> [{I,V}|Rs];
+put_reg_1(V, [{reserved,I,V}|Rs], I) -> [{I,V}|Rs];
+put_reg_1(V, [R|Rs], I) -> [R|put_reg_1(V, Rs, I+1)];
+put_reg_1(V, [], I) -> [{I,V}].
+
+load_reg(V, R, Rs) -> load_reg_1(V, R, Rs, 0).
+
+load_reg_1(V, I, [_|Rs], I) -> [{I,V}|Rs];
+load_reg_1(V, I, [R|Rs], C) -> [R|load_reg_1(V, I, Rs, C+1)];
+load_reg_1(V, I, [], I) -> [{I,V}];
+load_reg_1(V, I, [], C) -> [free|load_reg_1(V, I, [], C+1)].
+
+% free_reg(V, [{I,V}|Rs]) -> [free|Rs];
+% free_reg(V, [R|Rs]) -> [R|free_reg(V, Rs)];
+% free_reg(V, []) -> [].
+
+fetch_reg(V, [{I,V}|_]) -> {x,I};
+fetch_reg(V, [_|SRs]) -> fetch_reg(V, SRs).
+
+find_reg(V, [{I,V}|_]) -> {ok,{x,I}};
+find_reg(V, [_|SRs]) -> find_reg(V, SRs);
+find_reg(_, []) -> error.
+
+%% For the bit syntax, we need a scratch register if we are constructing
+%% a binary that will not be used.
+
+find_scratch_reg(Rs) -> find_scratch_reg(Rs, 0).
+
+find_scratch_reg([free|_], I) -> {x,I};
+find_scratch_reg([_|Rs], I) -> find_scratch_reg(Rs, I+1);
+find_scratch_reg([], I) -> {x,I}.
+
+%%copy_reg(Val, R, Regs) -> load_reg(Val, R, Regs).
+%%move_reg(Val, R, Regs) -> load_reg(Val, R, free_reg(Val, Regs)).
+
+%%clear_regs(Regs) -> map(fun (R) -> free end, Regs).
+clear_regs(_) -> [].
+
+max_reg(Regs) ->
+ foldl(fun ({I,_}, _) -> I;
+ (_, Max) -> Max end,
+ -1, Regs) + 1.
+
+%% put_stack(Val, [{Val}]) -> [{Val}].
+%% fetch_stack(Var, Stk) -> sp{S}.
+%% find_stack(Var, Stk) -> ok{sp{S}} | error.
+%% Functions to interface the stack.
+
+put_stack(Val, []) -> [{Val}];
+put_stack(Val, [dead|Stk]) -> [{Val}|Stk];
+put_stack(Val, [free|Stk]) -> [{Val}|Stk];
+put_stack(Val, [NotFree|Stk]) -> [NotFree|put_stack(Val, Stk)].
+
+put_stack_carefully(Val, Stk0) ->
+ case catch put_stack_carefully1(Val, Stk0) of
+ error -> error;
+ Stk1 when list(Stk1) -> Stk1
+ end.
+
+put_stack_carefully1(_, []) -> throw(error);
+put_stack_carefully1(Val, [dead|Stk]) -> [{Val}|Stk];
+put_stack_carefully1(Val, [free|Stk]) -> [{Val}|Stk];
+put_stack_carefully1(Val, [NotFree|Stk]) ->
+ [NotFree|put_stack_carefully1(Val, Stk)].
+
+fetch_stack(Var, Stk) -> fetch_stack(Var, Stk, 0).
+
+fetch_stack(V, [{V}|_], I) -> {yy,I};
+fetch_stack(V, [_|Stk], I) -> fetch_stack(V, Stk, I+1).
+
+% find_stack(Var, Stk) -> find_stack(Var, Stk, 0).
+
+% find_stack(V, [{V}|Stk], I) -> {ok,{yy,I}};
+% find_stack(V, [O|Stk], I) -> find_stack(V, Stk, I+1);
+% find_stack(V, [], I) -> error.
+
+on_stack(V, Stk) -> keymember(V, 1, Stk).
+
+%% put_catch(CatchTag, Stack) -> Stack'
+%% drop_catch(CatchTag, Stack) -> Stack'
+%% Special interface for putting and removing catch tags, to ensure that
+%% catches nest properly. Also used for try tags.
+
+put_catch(Tag, Stk0) -> put_catch(Tag, reverse(Stk0), []).
+
+put_catch(Tag, [], Stk) ->
+ put_stack({catch_tag,Tag}, Stk);
+put_catch(Tag, [{{catch_tag,_}}|_]=RevStk, Stk) ->
+ reverse(RevStk, put_stack({catch_tag,Tag}, Stk));
+put_catch(Tag, [Other|Stk], Acc) ->
+ put_catch(Tag, Stk, [Other|Acc]).
+
+drop_catch(Tag, [{{catch_tag,Tag}}|Stk]) -> [free|Stk];
+drop_catch(Tag, [Other|Stk]) -> [Other|drop_catch(Tag, Stk)].
+
+%%%
+%%% Finish the code generation for the bit syntax matching.
+%%%
+
+bs_function({function,Name,Arity,CLabel,Asm0}=Func) ->
+ case bs_needed(Asm0, 0, false, []) of
+ {false,[]} -> Func;
+ {true,Dict} ->
+ Asm = bs_replace(Asm0, Dict, []),
+ {function,Name,Arity,CLabel,Asm}
+ end.
+
+%%%
+%%% Pass 1: Found out which bs_restore's that are needed. For now we assume
+%%% that a bs_restore is needed unless it is directly preceeded by a bs_save.
+%%%
+
+bs_needed([{bs_save,Name},{bs_restore,Name}|T], N, _BsUsed, Dict) ->
+ bs_needed(T, N, true, Dict);
+bs_needed([{bs_save,_Name}|T], N, _BsUsed, Dict) ->
+ bs_needed(T, N, true, Dict);
+bs_needed([{bs_restore,Name}|T], N, _BsUsed, Dict) ->
+ case keysearch(Name, 1, Dict) of
+ {value,{Name,_}} -> bs_needed(T, N, true, Dict);
+ false -> bs_needed(T, N+1, true, [{Name,N}|Dict])
+ end;
+bs_needed([{bs_init,_,_}|T], N, _, Dict) ->
+ bs_needed(T, N, true, Dict);
+bs_needed([{bs_init2,_,_,_,_,_}|T], N, _, Dict) ->
+ bs_needed(T, N, true, Dict);
+bs_needed([{bs_start_match,_,_}|T], N, _, Dict) ->
+ bs_needed(T, N, true, Dict);
+bs_needed([_|T], N, BsUsed, Dict) ->
+ bs_needed(T, N, BsUsed, Dict);
+bs_needed([], _, BsUsed, Dict) -> {BsUsed,Dict}.
+
+%%%
+%%% Pass 2: Only needed if there were some bs_* instructions found.
+%%%
+%%% Remove any bs_save with a name that never were found to be restored
+%%% in the first pass.
+%%%
+
+bs_replace([{bs_save,Name}=Save,{bs_restore,Name}|T], Dict, Acc) ->
+ bs_replace([Save|T], Dict, Acc);
+bs_replace([{bs_save,Name}|T], Dict, Acc) ->
+ case keysearch(Name, 1, Dict) of
+ {value,{Name,N}} ->
+ bs_replace(T, Dict, [{bs_save,N}|Acc]);
+ false ->
+ bs_replace(T, Dict, Acc)
+ end;
+bs_replace([{bs_restore,Name}|T], Dict, Acc) ->
+ case keysearch(Name, 1, Dict) of
+ {value,{Name,N}} ->
+ bs_replace(T, Dict, [{bs_restore,N}|Acc]);
+ false ->
+ bs_replace(T, Dict, Acc)
+ end;
+bs_replace([{bs_init2,Fail,Bytes,Regs,Flags,Dst}|T0], Dict, Acc) ->
+ case bs_find_test_heap(T0) of
+ none ->
+ bs_replace(T0, Dict, [{bs_init2,Fail,Bytes,0,Regs,Flags,Dst}|Acc]);
+ {T,Words} ->
+ bs_replace(T, Dict, [{bs_init2,Fail,Bytes,Words,Regs,Flags,Dst}|Acc])
+ end;
+bs_replace([H|T], Dict, Acc) ->
+ bs_replace(T, Dict, [H|Acc]);
+bs_replace([], _, Acc) -> reverse(Acc).
+
+bs_find_test_heap(Is) ->
+ bs_find_test_heap_1(Is, []).
+
+bs_find_test_heap_1([{bs_put_integer,_,_,_,_,_}=I|Is], Acc) ->
+ bs_find_test_heap_1(Is, [I|Acc]);
+bs_find_test_heap_1([{bs_put_float,_,_,_,_,_}=I|Is], Acc) ->
+ bs_find_test_heap_1(Is, [I|Acc]);
+bs_find_test_heap_1([{bs_put_binary,_,_,_,_,_}=I|Is], Acc) ->
+ bs_find_test_heap_1(Is, [I|Acc]);
+bs_find_test_heap_1([{test_heap,Words,_}|Is], Acc) ->
+ {reverse(Acc, Is),Words};
+bs_find_test_heap_1(_, _) -> none.
+
+%% new_label(St) -> {L,St}.
+
+new_label(St) ->
+ L = St#cg.lcount,
+ {L,St#cg{lcount=L+1}}.
+
+flatmapfoldl(F, Accu0, [Hd|Tail]) ->
+ {R,Accu1} = F(Hd, Accu0),
+ {Rs,Accu2} = flatmapfoldl(F, Accu1, Tail),
+ {R++Rs,Accu2};
+flatmapfoldl(_, Accu, []) -> {[],Accu}.
+
+flatmapfoldr(F, Accu0, [Hd|Tail]) ->
+ {Rs,Accu1} = flatmapfoldr(F, Accu0, Tail),
+ {R,Accu2} = F(Hd, Accu1),
+ {R++Rs,Accu2};
+flatmapfoldr(_, Accu, []) -> {[],Accu}.
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_core.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_core.erl
new file mode 100644
index 0000000000..c96837ab5e
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_core.erl
@@ -0,0 +1,1319 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: v3_core.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
+%%
+%% Purpose : Transform normal Erlang to Core Erlang
+
+%% At this stage all preprocessing has been done. All that is left are
+%% "pure" Erlang functions.
+%%
+%% Core transformation is done in three stages:
+%%
+%% 1. Flatten expressions into an internal core form without doing
+%% matching.
+%%
+%% 2. Step "forwards" over the icore code annotating each "top-level"
+%% thing with variable usage. Detect bound variables in matching
+%% and replace with explicit guard test. Annotate "internal-core"
+%% expressions with variables they use and create. Convert matches
+%% to cases when not pure assignments.
+%%
+%% 3. Step "backwards" over icore code using variable usage
+%% annotations to change implicit exported variables to explicit
+%% returns.
+%%
+%% To ensure the evaluation order we ensure that all arguments are
+%% safe. A "safe" is basically a core_lib simple with VERY restricted
+%% binaries.
+%%
+%% We have to be very careful with matches as these create variables.
+%% While we try not to flatten things more than necessary we must make
+%% sure that all matches are at the top level. For this we use the
+%% type "novars" which are non-match expressions. Cases and receives
+%% can also create problems due to exports variables so they are not
+%% "novars" either. I.e. a novars will not export variables.
+%%
+%% Annotations in the #iset, #iletrec, and all other internal records
+%% is kept in a record, #a, not in a list as in proper core. This is
+%% easier and faster and creates no problems as we have complete control
+%% over all annotations.
+%%
+%% On output, the annotation for most Core Erlang terms will contain
+%% the source line number. A few terms will be marked with the atom
+%% atom 'compiler_generated', to indicate that the compiler has generated
+%% them and that no warning should be generated if they are optimized
+%% away.
+%%
+%%
+%% In this translation:
+%%
+%% call ops are safes
+%% call arguments are safes
+%% match arguments are novars
+%% case arguments are novars
+%% receive timeouts are novars
+%% let/set arguments are expressions
+%% fun is not a safe
+
+-module(v3_core).
+
+-export([module/2,format_error/1]).
+
+-import(lists, [map/2,foldl/3,foldr/3,mapfoldl/3,splitwith/2]).
+-import(ordsets, [add_element/2,del_element/2,is_element/2,
+ union/1,union/2,intersection/2,subtract/2]).
+
+-include("core_parse.hrl").
+
+-record(a, {us=[],ns=[],anno=[]}). %Internal annotation
+
+%% Internal core expressions and help functions.
+%% N.B. annotations fields in place as normal Core expressions.
+
+-record(iset, {anno=#a{},var,arg}).
+-record(iletrec, {anno=#a{},defs,body}).
+-record(imatch, {anno=#a{},pat,guard=[],arg,fc}).
+-record(icase, {anno=#a{},args,clauses,fc}).
+-record(iclause, {anno=#a{},pats,pguard=[],guard,body}).
+-record(ifun, {anno=#a{},id,vars,clauses,fc}).
+-record(iapply, {anno=#a{},op,args}).
+-record(icall, {anno=#a{},module,name,args}).
+-record(iprimop, {anno=#a{},name,args}).
+-record(itry, {anno=#a{},args,vars,body,evars,handler}).
+-record(icatch, {anno=#a{},body}).
+-record(ireceive1, {anno=#a{},clauses}).
+-record(ireceive2, {anno=#a{},clauses,timeout,action}).
+-record(iprotect, {anno=#a{},body}).
+-record(ibinary, {anno=#a{},segments}). %Not used in patterns.
+
+-record(core, {vcount=0, %Variable counter
+ fcount=0, %Function counter
+ ws=[]}). %Warnings.
+
+module({Mod,Exp,Forms}, _Opts) ->
+ Cexp = map(fun ({N,A}) -> #c_fname{id=N,arity=A} end, Exp),
+ {Kfs,As,Ws} = foldr(fun form/2, {[],[],[]}, Forms),
+ {ok,#c_module{name=#c_atom{val=Mod},exports=Cexp,attrs=As,defs=Kfs},Ws}.
+
+form({function,_,_,_,_}=F0, {Fs,As,Ws0}) ->
+ {F,Ws} = function(F0, Ws0),
+ {[F|Fs],As,Ws};
+form({attribute,_,_,_}=F, {Fs,As,Ws}) ->
+ {Fs,[attribute(F)|As],Ws}.
+
+attribute({attribute,_,Name,Val}) ->
+ #c_def{name=core_lib:make_literal(Name),
+ val=core_lib:make_literal(Val)}.
+
+function({function,_,Name,Arity,Cs0}, Ws0) ->
+ %%ok = io:fwrite("~p - ", [{Name,Arity}]),
+ St0 = #core{vcount=0,ws=Ws0},
+ {B0,St1} = body(Cs0, Arity, St0),
+ %%ok = io:fwrite("1", []),
+ %%ok = io:fwrite("~w:~p~n", [?LINE,B0]),
+ {B1,St2} = ubody(B0, St1),
+ %%ok = io:fwrite("2", []),
+ %%ok = io:fwrite("~w:~p~n", [?LINE,B1]),
+ {B2,#core{ws=Ws}} = cbody(B1, St2),
+ %%ok = io:fwrite("3~n", []),
+ {#c_def{name=#c_fname{id=Name,arity=Arity},val=B2},Ws}.
+
+body(Cs0, Arity, St0) ->
+ Anno = [element(2, hd(Cs0))],
+ {Args,St1} = new_vars(Anno, Arity, St0),
+ {Cs1,St2} = clauses(Cs0, St1),
+ {Ps,St3} = new_vars(Arity, St2), %Need new variables here
+ Fc = fail_clause(Ps, #c_tuple{es=[#c_atom{val=function_clause}|Ps]}),
+ {#ifun{anno=#a{anno=Anno},id=[],vars=Args,clauses=Cs1,fc=Fc},St3}.
+
+%% clause(Clause, State) -> {Cclause,State} | noclause.
+%% clauses([Clause], State) -> {[Cclause],State}.
+%% Convert clauses. Trap bad pattern aliases and remove clause from
+%% clause list.
+
+clauses([C0|Cs0], St0) ->
+ case clause(C0, St0) of
+ {noclause,St} -> clauses(Cs0, St);
+ {C,St1} ->
+ {Cs,St2} = clauses(Cs0, St1),
+ {[C|Cs],St2}
+ end;
+clauses([], St) -> {[],St}.
+
+clause({clause,Lc,H0,G0,B0}, St0) ->
+ case catch head(H0) of
+ {'EXIT',_}=Exit -> exit(Exit); %Propagate error
+ nomatch ->
+ St = add_warning(Lc, nomatch, St0),
+ {noclause,St}; %Bad pattern
+ H1 ->
+ {G1,St1} = guard(G0, St0),
+ {B1,St2} = exprs(B0, St1),
+ {#iclause{anno=#a{anno=[Lc]},pats=H1,guard=G1,body=B1},St2}
+ end.
+
+%% head([P]) -> [P].
+
+head(Ps) -> pattern_list(Ps).
+
+%% guard([Expr], State) -> {[Cexpr],State}.
+%% Build an explict and/or tree of guard alternatives, then traverse
+%% top-level and/or tree and "protect" inner tests.
+
+guard([], St) -> {[],St};
+guard(Gs0, St) ->
+ Gs = foldr(fun (Gt0, Rhs) ->
+ Gt1 = guard_tests(Gt0),
+ L = element(2, Gt1),
+ {op,L,'or',Gt1,Rhs}
+ end, guard_tests(last(Gs0)), first(Gs0)),
+ gexpr_top(Gs, St).
+
+guard_tests([]) -> [];
+guard_tests(Gs) ->
+ L = element(2, hd(Gs)),
+ {protect,L,foldr(fun (G, Rhs) -> {op,L,'and',G,Rhs} end, last(Gs), first(Gs))}.
+
+%% gexpr_top(Expr, State) -> {Cexpr,State}.
+%% Generate an internal core expression of a guard test. Explicitly
+%% handle outer boolean expressions and "protect" inner tests in a
+%% reasonably smart way.
+
+gexpr_top(E0, St0) ->
+ {E1,Eps0,Bools,St1} = gexpr(E0, [], St0),
+ {E,Eps,St} = force_booleans(Bools, E1, Eps0, St1),
+ {Eps++[E],St}.
+
+%% gexpr(Expr, Bools, State) -> {Cexpr,[PreExp],Bools,State}.
+%% Generate an internal core expression of a guard test.
+
+gexpr({protect,Line,Arg}, Bools0, St0) ->
+ case gexpr(Arg, [], St0) of
+ {E0,[],Bools,St1} ->
+ {E,Eps,St} = force_booleans(Bools, E0, [], St1),
+ {E,Eps,Bools0,St};
+ {E0,Eps0,Bools,St1} ->
+ {E,Eps,St} = force_booleans(Bools, E0, Eps0, St1),
+ {#iprotect{anno=#a{anno=[Line]},body=Eps++[E]},[],Bools0,St}
+ end;
+gexpr({op,Line,Op,L,R}=Call, Bools0, St0) ->
+ case erl_internal:bool_op(Op, 2) of
+ true ->
+ {Le,Lps,Bools1,St1} = gexpr(L, Bools0, St0),
+ {Ll,Llps,St2} = force_safe(Le, St1),
+ {Re,Rps,Bools,St3} = gexpr(R, Bools1, St2),
+ {Rl,Rlps,St4} = force_safe(Re, St3),
+ Anno = [Line],
+ {#icall{anno=#a{anno=Anno}, %Must have an #a{}
+ module=#c_atom{anno=Anno,val=erlang},name=#c_atom{anno=Anno,val=Op},
+ args=[Ll,Rl]},Lps ++ Llps ++ Rps ++ Rlps,Bools,St4};
+ false ->
+ gexpr_test(Call, Bools0, St0)
+ end;
+gexpr({op,Line,Op,A}=Call, Bools0, St0) ->
+ case erl_internal:bool_op(Op, 1) of
+ true ->
+ {Ae,Aps,Bools,St1} = gexpr(A, Bools0, St0),
+ {Al,Alps,St2} = force_safe(Ae, St1),
+ Anno = [Line],
+ {#icall{anno=#a{anno=Anno}, %Must have an #a{}
+ module=#c_atom{anno=Anno,val=erlang},name=#c_atom{anno=Anno,val=Op},
+ args=[Al]},Aps ++ Alps,Bools,St2};
+ false ->
+ gexpr_test(Call, Bools0, St0)
+ end;
+gexpr(E0, Bools, St0) ->
+ gexpr_test(E0, Bools, St0).
+
+%% gexpr_test(Expr, Bools, State) -> {Cexpr,[PreExp],Bools,State}.
+%% Generate a guard test. At this stage we must be sure that we have
+%% a proper boolean value here so wrap things with an true test if we
+%% don't know, i.e. if it is not a comparison or a type test.
+
+gexpr_test({atom,L,true}, Bools, St0) ->
+ {#c_atom{anno=[L],val=true},[],Bools,St0};
+gexpr_test({atom,L,false}, Bools, St0) ->
+ {#c_atom{anno=[L],val=false},[],Bools,St0};
+gexpr_test(E0, Bools0, St0) ->
+ {E1,Eps0,St1} = expr(E0, St0),
+ %% Generate "top-level" test and argument calls.
+ case E1 of
+ #icall{anno=Anno,module=#c_atom{val=erlang},name=#c_atom{val=N},args=As} ->
+ Ar = length(As),
+ case erl_internal:type_test(N, Ar) orelse
+ erl_internal:comp_op(N, Ar) orelse
+ (N == internal_is_record andalso Ar == 3) of
+ true -> {E1,Eps0,Bools0,St1};
+ false ->
+ Lanno = Anno#a.anno,
+ {New,St2} = new_var(Lanno, St1),
+ Bools = [New|Bools0],
+ {#icall{anno=Anno, %Must have an #a{}
+ module=#c_atom{anno=Lanno,val=erlang},
+ name=#c_atom{anno=Lanno,val='=:='},
+ args=[New,#c_atom{anno=Lanno,val=true}]},
+ Eps0 ++ [#iset{anno=Anno,var=New,arg=E1}],Bools,St2}
+ end;
+ _ ->
+ Anno = get_ianno(E1),
+ Lanno = get_lineno_anno(E1),
+ case core_lib:is_simple(E1) of
+ true ->
+ Bools = [E1|Bools0],
+ {#icall{anno=Anno, %Must have an #a{}
+ module=#c_atom{anno=Lanno,val=erlang},
+ name=#c_atom{anno=Lanno,val='=:='},
+ args=[E1,#c_atom{anno=Lanno,val=true}]},Eps0,Bools,St1};
+ false ->
+ {New,St2} = new_var(Lanno, St1),
+ Bools = [New|Bools0],
+ {#icall{anno=Anno, %Must have an #a{}
+ module=#c_atom{anno=Lanno,val=erlang},
+ name=#c_atom{anno=Lanno,val='=:='},
+ args=[New,#c_atom{anno=Lanno,val=true}]},
+ Eps0 ++ [#iset{anno=Anno,var=New,arg=E1}],Bools,St2}
+ end
+ end.
+
+force_booleans([], E, Eps, St) ->
+ {E,Eps,St};
+force_booleans([V|Vs], E0, Eps0, St0) ->
+ {E1,Eps1,St1} = force_safe(E0, St0),
+ Lanno = element(2, V),
+ Anno = #a{anno=Lanno},
+ Call = #icall{anno=Anno,module=#c_atom{anno=Lanno,val=erlang},
+ name=#c_atom{anno=Lanno,val=is_boolean},
+ args=[V]},
+ {New,St} = new_var(Lanno, St1),
+ Iset = #iset{anno=Anno,var=New,arg=Call},
+ Eps = Eps0 ++ Eps1 ++ [Iset],
+ E = #icall{anno=Anno,
+ module=#c_atom{anno=Lanno,val=erlang},name=#c_atom{anno=Lanno,val='and'},
+ args=[E1,New]},
+ force_booleans(Vs, E, Eps, St).
+
+%% exprs([Expr], State) -> {[Cexpr],State}.
+%% Flatten top-level exprs.
+
+exprs([E0|Es0], St0) ->
+ {E1,Eps,St1} = expr(E0, St0),
+ {Es1,St2} = exprs(Es0, St1),
+ {Eps ++ [E1] ++ Es1,St2};
+exprs([], St) -> {[],St}.
+
+%% expr(Expr, State) -> {Cexpr,[PreExp],State}.
+%% Generate an internal core expression.
+
+expr({var,L,V}, St) -> {#c_var{anno=[L],name=V},[],St};
+expr({char,L,C}, St) -> {#c_char{anno=[L],val=C},[],St};
+expr({integer,L,I}, St) -> {#c_int{anno=[L],val=I},[],St};
+expr({float,L,F}, St) -> {#c_float{anno=[L],val=F},[],St};
+expr({atom,L,A}, St) -> {#c_atom{anno=[L],val=A},[],St};
+expr({nil,L}, St) -> {#c_nil{anno=[L]},[],St};
+expr({string,L,S}, St) -> {#c_string{anno=[L],val=S},[],St};
+expr({cons,L,H0,T0}, St0) ->
+ {H1,Hps,St1} = safe(H0, St0),
+ {T1,Tps,St2} = safe(T0, St1),
+ {#c_cons{anno=[L],hd=H1,tl=T1},Hps ++ Tps,St2};
+expr({lc,L,E,Qs}, St) ->
+ lc_tq(L, E, Qs, {nil,L}, St);
+expr({tuple,L,Es0}, St0) ->
+ {Es1,Eps,St1} = safe_list(Es0, St0),
+ {#c_tuple{anno=[L],es=Es1},Eps,St1};
+expr({bin,L,Es0}, St0) ->
+ {Es1,Eps,St1} = expr_bin(Es0, St0),
+ {#ibinary{anno=#a{anno=[L]},segments=Es1},Eps,St1};
+expr({block,_,Es0}, St0) ->
+ %% Inline the block directly.
+ {Es1,St1} = exprs(first(Es0), St0),
+ {E1,Eps,St2} = expr(last(Es0), St1),
+ {E1,Es1 ++ Eps,St2};
+expr({'if',L,Cs0}, St0) ->
+ {Cs1,St1} = clauses(Cs0, St0),
+ Fc = fail_clause([], #c_atom{val=if_clause}),
+ {#icase{anno=#a{anno=[L]},args=[],clauses=Cs1,fc=Fc},[],St1};
+expr({'case',L,E0,Cs0}, St0) ->
+ {E1,Eps,St1} = novars(E0, St0),
+ {Cs1,St2} = clauses(Cs0, St1),
+ {Fpat,St3} = new_var(St2),
+ Fc = fail_clause([Fpat], #c_tuple{es=[#c_atom{val=case_clause},Fpat]}),
+ {#icase{anno=#a{anno=[L]},args=[E1],clauses=Cs1,fc=Fc},Eps,St3};
+expr({'receive',L,Cs0}, St0) ->
+ {Cs1,St1} = clauses(Cs0, St0),
+ {#ireceive1{anno=#a{anno=[L]},clauses=Cs1}, [], St1};
+expr({'receive',L,Cs0,Te0,Tes0}, St0) ->
+ {Te1,Teps,St1} = novars(Te0, St0),
+ {Tes1,St2} = exprs(Tes0, St1),
+ {Cs1,St3} = clauses(Cs0, St2),
+ {#ireceive2{anno=#a{anno=[L]},
+ clauses=Cs1,timeout=Te1,action=Tes1},Teps,St3};
+expr({'try',L,Es0,[],Ecs,[]}, St0) ->
+ %% 'try ... catch ... end'
+ {Es1,St1} = exprs(Es0, St0),
+ {V,St2} = new_var(St1), %This name should be arbitrary
+ {Evs,Hs,St3} = try_exception(Ecs, St2),
+ {#itry{anno=#a{anno=[L]},args=Es1,vars=[V],body=[V],
+ evars=Evs,handler=Hs},
+ [],St3};
+expr({'try',L,Es0,Cs0,Ecs,[]}, St0) ->
+ %% 'try ... of ... catch ... end'
+ {Es1,St1} = exprs(Es0, St0),
+ {V,St2} = new_var(St1), %This name should be arbitrary
+ {Cs1,St3} = clauses(Cs0, St2),
+ {Fpat,St4} = new_var(St3),
+ Fc = fail_clause([Fpat], #c_tuple{es=[#c_atom{val=try_clause},Fpat]}),
+ {Evs,Hs,St5} = try_exception(Ecs, St4),
+ {#itry{anno=#a{anno=[L]},args=Es1,
+ vars=[V],body=[#icase{anno=#a{},args=[V],clauses=Cs1,fc=Fc}],
+ evars=Evs,handler=Hs},
+ [],St5};
+expr({'try',L,Es0,[],[],As0}, St0) ->
+ %% 'try ... after ... end'
+ {Es1,St1} = exprs(Es0, St0),
+ {As1,St2} = exprs(As0, St1),
+ {Evs,Hs,St3} = try_after(As1,St2),
+ {V,St4} = new_var(St3), % (must not exist in As1)
+ %% TODO: this duplicates the 'after'-code; should lift to function.
+ {#itry{anno=#a{anno=[L]},args=Es1,vars=[V],body=As1++[V],
+ evars=Evs,handler=Hs},
+ [],St4};
+expr({'try',L,Es,Cs,Ecs,As}, St0) ->
+ %% 'try ... [of ...] [catch ...] after ... end'
+ expr({'try',L,[{'try',L,Es,Cs,Ecs,[]}],[],[],As}, St0);
+expr({'catch',L,E0}, St0) ->
+ {E1,Eps,St1} = expr(E0, St0),
+ {#icatch{anno=#a{anno=[L]},body=Eps ++ [E1]},[],St1};
+expr({'fun',L,{function,F,A},{_,_,_}=Id}, St) ->
+ {#c_fname{anno=[L,{id,Id}],id=F,arity=A},[],St};
+expr({'fun',L,{clauses,Cs},Id}, St) ->
+ fun_tq(Id, Cs, L, St);
+expr({call,L0,{remote,_,{atom,_,erlang},{atom,_,is_record}},[_,_,_]=As}, St)
+ when L0 < 0 ->
+ %% Compiler-generated erlang:is_record/3 should be converted to
+ %% erlang:internal_is_record/3.
+ L = -L0,
+ expr({call,L,{remote,L,{atom,L,erlang},{atom,L,internal_is_record}},As}, St);
+expr({call,L,{remote,_,M,F},As0}, St0) ->
+ {[M1,F1|As1],Aps,St1} = safe_list([M,F|As0], St0),
+ {#icall{anno=#a{anno=[L]},module=M1,name=F1,args=As1},Aps,St1};
+expr({call,Lc,{atom,Lf,F},As0}, St0) ->
+ {As1,Aps,St1} = safe_list(As0, St0),
+ Op = #c_fname{anno=[Lf],id=F,arity=length(As1)},
+ {#iapply{anno=#a{anno=[Lc]},op=Op,args=As1},Aps,St1};
+expr({call,L,FunExp,As0}, St0) ->
+ {Fun,Fps,St1} = safe(FunExp, St0),
+ {As1,Aps,St2} = safe_list(As0, St1),
+ {#iapply{anno=#a{anno=[L]},op=Fun,args=As1},Fps ++ Aps,St2};
+expr({match,L,P0,E0}, St0) ->
+ %% First fold matches together to create aliases.
+ {P1,E1} = fold_match(E0, P0),
+ {E2,Eps,St1} = novars(E1, St0),
+ P2 = (catch pattern(P1)),
+ {Fpat,St2} = new_var(St1),
+ Fc = fail_clause([Fpat], #c_tuple{es=[#c_atom{val=badmatch},Fpat]}),
+ case P2 of
+ {'EXIT',_}=Exit -> exit(Exit); %Propagate error
+ nomatch ->
+ St = add_warning(L, nomatch, St2),
+ {#icase{anno=#a{anno=[L]},
+ args=[E2],clauses=[],fc=Fc},Eps,St};
+ _Other ->
+ {#imatch{anno=#a{anno=[L]},pat=P2,arg=E2,fc=Fc},Eps,St2}
+ end;
+expr({op,_,'++',{lc,Llc,E,Qs},L2}, St) ->
+ %% Optimise this here because of the list comprehension algorithm.
+ lc_tq(Llc, E, Qs, L2, St);
+expr({op,L,Op,A0}, St0) ->
+ {A1,Aps,St1} = safe(A0, St0),
+ LineAnno = [L],
+ {#icall{anno=#a{anno=LineAnno}, %Must have an #a{}
+ module=#c_atom{anno=LineAnno,val=erlang},
+ name=#c_atom{anno=LineAnno,val=Op},args=[A1]},Aps,St1};
+expr({op,L,Op,L0,R0}, St0) ->
+ {As,Aps,St1} = safe_list([L0,R0], St0),
+ LineAnno = [L],
+ {#icall{anno=#a{anno=LineAnno}, %Must have an #a{}
+ module=#c_atom{anno=LineAnno,val=erlang},
+ name=#c_atom{anno=LineAnno,val=Op},args=As},Aps,St1}.
+
+%% try_exception([ExcpClause], St) -> {[ExcpVar],Handler,St}.
+
+try_exception(Ecs0, St0) ->
+ %% Note that Tag is not needed for rethrow - it is already in Info.
+ {Evs,St1} = new_vars(3, St0), % Tag, Value, Info
+ {Ecs1,St2} = clauses(Ecs0, St1),
+ [_,Value,Info] = Evs,
+ Ec = #iclause{anno=#a{anno=[compiler_generated]},
+ pats=[#c_tuple{es=Evs}],guard=[#c_atom{val=true}],
+ body=[#iprimop{anno=#a{}, %Must have an #a{}
+ name=#c_atom{val=raise},
+ args=[Info,Value]}]},
+ Hs = [#icase{anno=#a{},args=[#c_tuple{es=Evs}],clauses=Ecs1,fc=Ec}],
+ {Evs,Hs,St2}.
+
+try_after(As, St0) ->
+ %% See above.
+ {Evs,St1} = new_vars(3, St0), % Tag, Value, Info
+ [_,Value,Info] = Evs,
+ B = As ++ [#iprimop{anno=#a{}, %Must have an #a{}
+ name=#c_atom{val=raise},
+ args=[Info,Value]}],
+ Ec = #iclause{anno=#a{anno=[compiler_generated]},
+ pats=[#c_tuple{es=Evs}],guard=[#c_atom{val=true}],
+ body=B},
+ Hs = [#icase{anno=#a{},args=[#c_tuple{es=Evs}],clauses=[],fc=Ec}],
+ {Evs,Hs,St1}.
+
+%% expr_bin([ArgExpr], St) -> {[Arg],[PreExpr],St}.
+%% Flatten the arguments of a bin. Do this straight left to right!
+
+expr_bin(Es, St) ->
+ foldr(fun (E, {Ces,Esp,St0}) ->
+ {Ce,Ep,St1} = bitstr(E, St0),
+ {[Ce|Ces],Ep ++ Esp,St1}
+ end, {[],[],St}, Es).
+
+bitstr({bin_element,_,E0,Size0,[Type,{unit,Unit}|Flags]}, St0) ->
+ {E1,Eps,St1} = safe(E0, St0),
+ {Size1,Eps2,St2} = safe(Size0, St1),
+ {#c_bitstr{val=E1,size=Size1,
+ unit=core_lib:make_literal(Unit),
+ type=core_lib:make_literal(Type),
+ flags=core_lib:make_literal(Flags)},
+ Eps ++ Eps2,St2}.
+
+%% fun_tq(Id, [Clauses], Line, State) -> {Fun,[PreExp],State}.
+
+fun_tq(Id, Cs0, L, St0) ->
+ {Cs1,St1} = clauses(Cs0, St0),
+ Arity = length((hd(Cs1))#iclause.pats),
+ {Args,St2} = new_vars(Arity, St1),
+ {Ps,St3} = new_vars(Arity, St2), %Need new variables here
+ Fc = fail_clause(Ps, #c_tuple{es=[#c_atom{val=function_clause}|Ps]}),
+ Fun = #ifun{anno=#a{anno=[L]},
+ id=[{id,Id}], %We KNOW!
+ vars=Args,clauses=Cs1,fc=Fc},
+ {Fun,[],St3}.
+
+%% lc_tq(Line, Exp, [Qualifier], More, State) -> {LetRec,[PreExp],State}.
+%% This TQ from Simon PJ pp 127-138.
+%% This gets a bit messy as we must transform all directly here. We
+%% recognise guard tests and try to fold them together and join to a
+%% preceding generators, this should give us better and more compact
+%% code.
+%% More could be transformed before calling lc_tq.
+
+lc_tq(Line, E, [{generate,Lg,P,G}|Qs0], More, St0) ->
+ {Gs,Qs1} = splitwith(fun is_guard_test/1, Qs0),
+ {Name,St1} = new_fun_name("lc", St0),
+ {Head,St2} = new_var(St1),
+ {Tname,St3} = new_var_name(St2),
+ LA = [Line],
+ LAnno = #a{anno=LA},
+ Tail = #c_var{anno=LA,name=Tname},
+ {Arg,St4} = new_var(St3),
+ NewMore = {call,Lg,{atom,Lg,Name},[{var,Lg,Tname}]},
+ {Guardc,St5} = lc_guard_tests(Gs, St4), %These are always flat!
+ {Lc,Lps,St6} = lc_tq(Line, E, Qs1, NewMore, St5),
+ {Mc,Mps,St7} = expr(More, St6),
+ {Nc,Nps,St8} = expr(NewMore, St7),
+ case catch pattern(P) of
+ {'EXIT',_}=Exit ->
+ St9 = St8,
+ Pc = nomatch,
+ exit(Exit); %Propagate error
+ nomatch ->
+ St9 = add_warning(Line, nomatch, St8),
+ Pc = nomatch;
+ Pc ->
+ St9 = St8
+ end,
+ {Gc,Gps,St10} = safe(G, St9), %Will be a function argument!
+ Fc = fail_clause([Arg], #c_tuple{anno=LA,
+ es=[#c_atom{val=function_clause},Arg]}),
+ Cs0 = [#iclause{anno=#a{anno=[compiler_generated|LA]},
+ pats=[#c_cons{anno=LA,hd=Head,tl=Tail}],
+ guard=[],
+ body=Nps ++ [Nc]},
+ #iclause{anno=LAnno,
+ pats=[#c_nil{anno=LA}],guard=[],
+ body=Mps ++ [Mc]}],
+ Cs = case Pc of
+ nomatch -> Cs0;
+ _ ->
+ [#iclause{anno=LAnno,
+ pats=[#c_cons{anno=LA,hd=Pc,tl=Tail}],
+ guard=Guardc,
+ body=Lps ++ [Lc]}|Cs0]
+ end,
+ Fun = #ifun{anno=LAnno,id=[],vars=[Arg],clauses=Cs,fc=Fc},
+ {#iletrec{anno=LAnno,defs=[{Name,Fun}],
+ body=Gps ++ [#iapply{anno=LAnno,
+ op=#c_fname{anno=LA,id=Name,arity=1},
+ args=[Gc]}]},
+ [],St10};
+lc_tq(Line, E, [Fil0|Qs0], More, St0) ->
+ %% Special case sequences guard tests.
+ LA = [Line],
+ LAnno = #a{anno=LA},
+ case is_guard_test(Fil0) of
+ true ->
+ {Gs0,Qs1} = splitwith(fun is_guard_test/1, Qs0),
+ {Lc,Lps,St1} = lc_tq(Line, E, Qs1, More, St0),
+ {Mc,Mps,St2} = expr(More, St1),
+ {Gs,St3} = lc_guard_tests([Fil0|Gs0], St2), %These are always flat!
+ {#icase{anno=LAnno,
+ args=[],
+ clauses=[#iclause{anno=LAnno,pats=[],
+ guard=Gs,body=Lps ++ [Lc]}],
+ fc=#iclause{anno=LAnno,pats=[],guard=[],body=Mps ++ [Mc]}},
+ [],St3};
+ false ->
+ {Lc,Lps,St1} = lc_tq(Line, E, Qs0, More, St0),
+ {Mc,Mps,St2} = expr(More, St1),
+ {Fpat,St3} = new_var(St2),
+ Fc = fail_clause([Fpat], #c_tuple{es=[#c_atom{val=case_clause},Fpat]}),
+ %% Do a novars little optimisation here.
+ case Fil0 of
+ {op,_,'not',Fil1} ->
+ {Filc,Fps,St4} = novars(Fil1, St3),
+ {#icase{anno=LAnno,
+ args=[Filc],
+ clauses=[#iclause{anno=LAnno,
+ pats=[#c_atom{anno=LA,val=true}],
+ guard=[],
+ body=Mps ++ [Mc]},
+ #iclause{anno=LAnno,
+ pats=[#c_atom{anno=LA,val=false}],
+ guard=[],
+ body=Lps ++ [Lc]}],
+ fc=Fc},
+ Fps,St4};
+ _Other ->
+ {Filc,Fps,St4} = novars(Fil0, St3),
+ {#icase{anno=LAnno,
+ args=[Filc],
+ clauses=[#iclause{anno=LAnno,
+ pats=[#c_atom{anno=LA,val=true}],
+ guard=[],
+ body=Lps ++ [Lc]},
+ #iclause{anno=LAnno,
+ pats=[#c_atom{anno=LA,val=false}],
+ guard=[],
+ body=Mps ++ [Mc]}],
+ fc=Fc},
+ Fps,St4}
+ end
+ end;
+lc_tq(Line, E, [], More, St) ->
+ expr({cons,Line,E,More}, St).
+
+lc_guard_tests([], St) -> {[],St};
+lc_guard_tests(Gs0, St) ->
+ Gs = guard_tests(Gs0),
+ gexpr_top(Gs, St).
+
+%% is_guard_test(Expression) -> true | false.
+%% Test if a general expression is a guard test. Use erl_lint here
+%% as it now allows sys_pre_expand transformed source.
+
+is_guard_test(E) -> erl_lint:is_guard_test(E).
+
+%% novars(Expr, State) -> {Novars,[PreExpr],State}.
+%% Generate a novars expression, basically a call or a safe. At this
+%% level we do not need to do a deep check.
+
+novars(E0, St0) ->
+ {E1,Eps,St1} = expr(E0, St0),
+ {Se,Sps,St2} = force_novars(E1, St1),
+ {Se,Eps ++ Sps,St2}.
+
+force_novars(#iapply{}=App, St) -> {App,[],St};
+force_novars(#icall{}=Call, St) -> {Call,[],St};
+force_novars(#iprimop{}=Prim, St) -> {Prim,[],St};
+force_novars(#ifun{}=Fun, St) -> {Fun,[],St}; %These are novars too
+force_novars(#ibinary{}=Bin, St) -> {Bin,[],St};
+force_novars(Ce, St) ->
+ force_safe(Ce, St).
+
+%% safe(Expr, State) -> {Safe,[PreExpr],State}.
+%% Generate an internal safe expression. These are simples without
+%% binaries which can fail. At this level we do not need to do a
+%% deep check. Must do special things with matches here.
+
+safe(E0, St0) ->
+ {E1,Eps,St1} = expr(E0, St0),
+ {Se,Sps,St2} = force_safe(E1, St1),
+ {Se,Eps ++ Sps,St2}.
+
+safe_list(Es, St) ->
+ foldr(fun (E, {Ces,Esp,St0}) ->
+ {Ce,Ep,St1} = safe(E, St0),
+ {[Ce|Ces],Ep ++ Esp,St1}
+ end, {[],[],St}, Es).
+
+force_safe(#imatch{anno=Anno,pat=P,arg=E,fc=Fc}, St0) ->
+ {Le,Lps,St1} = force_safe(E, St0),
+ {Le,Lps ++ [#imatch{anno=Anno,pat=P,arg=Le,fc=Fc}],St1};
+force_safe(Ce, St0) ->
+ case is_safe(Ce) of
+ true -> {Ce,[],St0};
+ false ->
+ {V,St1} = new_var(St0),
+ {V,[#iset{var=V,arg=Ce}],St1}
+ end.
+
+is_safe(#c_cons{}) -> true;
+is_safe(#c_tuple{}) -> true;
+is_safe(#c_var{}) -> true;
+is_safe(E) -> core_lib:is_atomic(E).
+
+%%% %% variable(Expr, State) -> {Variable,[PreExpr],State}.
+%%% %% force_variable(Expr, State) -> {Variable,[PreExpr],State}.
+%%% %% Generate a variable.
+
+%%% variable(E0, St0) ->
+%%% {E1,Eps,St1} = expr(E0, St0),
+%%% {V,Vps,St2} = force_variable(E1, St1),
+%%% {V,Eps ++ Vps,St2}.
+
+%%% force_variable(#c_var{}=Var, St) -> {Var,[],St};
+%%% force_variable(Ce, St0) ->
+%%% {V,St1} = new_var(St0),
+%%% {V,[#iset{var=V,arg=Ce}],St1}.
+
+%%% %% atomic(Expr, State) -> {Atomic,[PreExpr],State}.
+%%% %% force_atomic(Expr, State) -> {Atomic,[PreExpr],State}.
+
+%%% atomic(E0, St0) ->
+%%% {E1,Eps,St1} = expr(E0, St0),
+%%% {A,Aps,St2} = force_atomic(E1, St1),
+%%% {A,Eps ++ Aps,St2}.
+
+%%% force_atomic(Ce, St0) ->
+%%% case core_lib:is_atomic(Ce) of
+%%% true -> {Ce,[],St0};
+%%% false ->
+%%% {V,St1} = new_var(St0),
+%%% {V,[#iset{var=V,arg=Ce}],St1}
+%%% end.
+
+%% fold_match(MatchExpr, Pat) -> {MatchPat,Expr}.
+%% Fold nested matches into one match with aliased patterns.
+
+fold_match({match,L,P0,E0}, P) ->
+ {P1,E1} = fold_match(E0, P),
+ {{match,L,P0,P1},E1};
+fold_match(E, P) -> {P,E}.
+
+%% pattern(Pattern) -> CorePat.
+%% Transform a pattern by removing line numbers. We also normalise
+%% aliases in patterns to standard form, {alias,Pat,[Var]}.
+
+pattern({var,L,V}) -> #c_var{anno=[L],name=V};
+pattern({char,L,C}) -> #c_char{anno=[L],val=C};
+pattern({integer,L,I}) -> #c_int{anno=[L],val=I};
+pattern({float,L,F}) -> #c_float{anno=[L],val=F};
+pattern({atom,L,A}) -> #c_atom{anno=[L],val=A};
+pattern({string,L,S}) -> #c_string{anno=[L],val=S};
+pattern({nil,L}) -> #c_nil{anno=[L]};
+pattern({cons,L,H,T}) ->
+ #c_cons{anno=[L],hd=pattern(H),tl=pattern(T)};
+pattern({tuple,L,Ps}) ->
+ #c_tuple{anno=[L],es=pattern_list(Ps)};
+pattern({bin,L,Ps}) ->
+ %% We don't create a #ibinary record here, since there is
+ %% no need to hold any used/new annoations in a pattern.
+ #c_binary{anno=[L],segments=pat_bin(Ps)};
+pattern({match,_,P1,P2}) ->
+ pat_alias(pattern(P1), pattern(P2)).
+
+%% bin_pattern_list([BinElement]) -> [BinSeg].
+
+pat_bin(Ps) -> map(fun pat_segment/1, Ps).
+
+pat_segment({bin_element,_,Term,Size,[Type,{unit,Unit}|Flags]}) ->
+ #c_bitstr{val=pattern(Term),size=pattern(Size),
+ unit=core_lib:make_literal(Unit),
+ type=core_lib:make_literal(Type),
+ flags=core_lib:make_literal(Flags)}.
+
+%% pat_alias(CorePat, CorePat) -> AliasPat.
+%% Normalise aliases. Trap bad aliases by throwing 'nomatch'.
+
+pat_alias(#c_var{name=V1}, P2) -> #c_alias{var=#c_var{name=V1},pat=P2};
+pat_alias(P1, #c_var{name=V2}) -> #c_alias{var=#c_var{name=V2},pat=P1};
+pat_alias(#c_cons{}=Cons, #c_string{anno=A,val=[H|T]}=S) ->
+ pat_alias(Cons, #c_cons{anno=A,hd=#c_char{anno=A,val=H},
+ tl=S#c_string{val=T}});
+pat_alias(#c_string{anno=A,val=[H|T]}=S, #c_cons{}=Cons) ->
+ pat_alias(#c_cons{anno=A,hd=#c_char{anno=A,val=H},
+ tl=S#c_string{val=T}}, Cons);
+pat_alias(#c_nil{}=Nil, #c_string{val=[]}) ->
+ Nil;
+pat_alias(#c_string{val=[]}, #c_nil{}=Nil) ->
+ Nil;
+pat_alias(#c_cons{anno=A,hd=H1,tl=T1}, #c_cons{hd=H2,tl=T2}) ->
+ #c_cons{anno=A,hd=pat_alias(H1, H2),tl=pat_alias(T1, T2)};
+pat_alias(#c_tuple{es=Es1}, #c_tuple{es=Es2}) ->
+ #c_tuple{es=pat_alias_list(Es1, Es2)};
+pat_alias(#c_char{val=C}=Char, #c_int{val=C}) ->
+ Char;
+pat_alias(#c_int{val=C}, #c_char{val=C}=Char) ->
+ Char;
+pat_alias(#c_alias{var=V1,pat=P1},
+ #c_alias{var=V2,pat=P2}) ->
+ if V1 == V2 -> pat_alias(P1, P2);
+ true -> #c_alias{var=V1,pat=#c_alias{var=V2,pat=pat_alias(P1, P2)}}
+ end;
+pat_alias(#c_alias{var=V1,pat=P1}, P2) ->
+ #c_alias{var=V1,pat=pat_alias(P1, P2)};
+pat_alias(P1, #c_alias{var=V2,pat=P2}) ->
+ #c_alias{var=V2,pat=pat_alias(P1, P2)};
+pat_alias(P, P) -> P;
+pat_alias(_, _) -> throw(nomatch).
+
+%% pat_alias_list([A1], [A2]) -> [A].
+
+pat_alias_list([A1|A1s], [A2|A2s]) ->
+ [pat_alias(A1, A2)|pat_alias_list(A1s, A2s)];
+pat_alias_list([], []) -> [];
+pat_alias_list(_, _) -> throw(nomatch).
+
+%% pattern_list([P]) -> [P].
+
+pattern_list(Ps) -> map(fun pattern/1, Ps).
+
+%% first([A]) -> [A].
+%% last([A]) -> A.
+
+first([_]) -> [];
+first([H|T]) -> [H|first(T)].
+
+last([L]) -> L;
+last([_|T]) -> last(T).
+
+%% make_vars([Name]) -> [{Var,Name}].
+
+make_vars(Vs) -> [ #c_var{name=V} || V <- Vs ].
+
+%% new_fun_name(Type, State) -> {FunName,State}.
+
+new_fun_name(Type, #core{fcount=C}=St) ->
+ {list_to_atom(Type ++ "$^" ++ integer_to_list(C)),St#core{fcount=C+1}}.
+
+%% new_var_name(State) -> {VarName,State}.
+
+new_var_name(#core{vcount=C}=St) ->
+ {list_to_atom("cor" ++ integer_to_list(C)),St#core{vcount=C + 1}}.
+
+%% new_var(State) -> {{var,Name},State}.
+%% new_var(LineAnno, State) -> {{var,Name},State}.
+
+new_var(St) ->
+ new_var([], St).
+
+new_var(Anno, St0) ->
+ {New,St} = new_var_name(St0),
+ {#c_var{anno=Anno,name=New},St}.
+
+%% new_vars(Count, State) -> {[Var],State}.
+%% new_vars(Anno, Count, State) -> {[Var],State}.
+%% Make Count new variables.
+
+new_vars(N, St) -> new_vars_1(N, [], St, []).
+new_vars(Anno, N, St) -> new_vars_1(N, Anno, St, []).
+
+new_vars_1(N, Anno, St0, Vs) when N > 0 ->
+ {V,St1} = new_var(Anno, St0),
+ new_vars_1(N-1, Anno, St1, [V|Vs]);
+new_vars_1(0, _, St, Vs) -> {Vs,St}.
+
+fail_clause(Pats, A) ->
+ #iclause{anno=#a{anno=[compiler_generated]},
+ pats=Pats,guard=[],
+ body=[#iprimop{anno=#a{},name=#c_atom{val=match_fail},args=[A]}]}.
+
+ubody(B, St) -> uexpr(B, [], St).
+
+%% uclauses([Lclause], [KnownVar], State) -> {[Lclause],State}.
+
+uclauses(Lcs, Ks, St0) ->
+ mapfoldl(fun (Lc, St) -> uclause(Lc, Ks, St) end, St0, Lcs).
+
+%% uclause(Lclause, [KnownVar], State) -> {Lclause,State}.
+
+uclause(Cl0, Ks, St0) ->
+ {Cl1,_Pvs,Used,New,St1} = uclause(Cl0, Ks, Ks, St0),
+ A0 = get_ianno(Cl1),
+ A = A0#a{us=Used,ns=New},
+ {Cl1#iclause{anno=A},St1}.
+
+uclause(#iclause{anno=Anno,pats=Ps0,guard=G0,body=B0}, Pks, Ks0, St0) ->
+ {Ps1,Pg,Pvs,Pus,St1} = upattern_list(Ps0, Pks, St0),
+ Pu = union(Pus, intersection(Pvs, Ks0)),
+ Pn = subtract(Pvs, Pu),
+ Ks1 = union(Pn, Ks0),
+ {G1,St2} = uguard(Pg, G0, Ks1, St1),
+ Gu = used_in_any(G1),
+ Gn = new_in_any(G1),
+ Ks2 = union(Gn, Ks1),
+ {B1,St3} = uexprs(B0, Ks2, St2),
+ Used = intersection(union([Pu,Gu,used_in_any(B1)]), Ks0),
+ New = union([Pn,Gn,new_in_any(B1)]),
+ {#iclause{anno=Anno,pats=Ps1,guard=G1,body=B1},Pvs,Used,New,St3}.
+
+%% uguard([Test], [Kexpr], [KnownVar], State) -> {[Kexpr],State}.
+%% Build a guard expression list by folding in the equality tests.
+
+uguard([], [], _, St) -> {[],St};
+uguard(Pg, [], Ks, St) ->
+ %% No guard, so fold together equality tests.
+ uguard(first(Pg), [last(Pg)], Ks, St);
+uguard(Pg, Gs0, Ks, St0) ->
+ %% Gs0 must contain at least one element here.
+ {Gs3,St5} = foldr(fun (T, {Gs1,St1}) ->
+ {L,St2} = new_var(St1),
+ {R,St3} = new_var(St2),
+ {[#iset{var=L,arg=T}] ++ first(Gs1) ++
+ [#iset{var=R,arg=last(Gs1)},
+ #icall{anno=#a{}, %Must have an #a{}
+ module=#c_atom{val=erlang},
+ name=#c_atom{val='and'},
+ args=[L,R]}],
+ St3}
+ end, {Gs0,St0}, Pg),
+ %%ok = io:fwrite("core ~w: ~p~n", [?LINE,Gs3]),
+ uexprs(Gs3, Ks, St5).
+
+%% uexprs([Kexpr], [KnownVar], State) -> {[Kexpr],State}.
+
+uexprs([#imatch{anno=A,pat=P0,arg=Arg,fc=Fc}|Les], Ks, St0) ->
+ %% Optimise for simple set of unbound variable.
+ case upattern(P0, Ks, St0) of
+ {#c_var{},[],_Pvs,_Pus,_} ->
+ %% Throw our work away and just set to iset.
+ uexprs([#iset{var=P0,arg=Arg}|Les], Ks, St0);
+ _Other ->
+ %% Throw our work away and set to icase.
+ if
+ Les == [] ->
+ %% Need to explicitly return match "value", make
+ %% safe for efficiency.
+ {La,Lps,St1} = force_safe(Arg, St0),
+ Mc = #iclause{anno=A,pats=[P0],guard=[],body=[La]},
+ uexprs(Lps ++ [#icase{anno=A,
+ args=[La],clauses=[Mc],fc=Fc}], Ks, St1);
+ true ->
+ Mc = #iclause{anno=A,pats=[P0],guard=[],body=Les},
+ uexprs([#icase{anno=A,args=[Arg],
+ clauses=[Mc],fc=Fc}], Ks, St0)
+ end
+ end;
+uexprs([Le0|Les0], Ks, St0) ->
+ {Le1,St1} = uexpr(Le0, Ks, St0),
+ {Les1,St2} = uexprs(Les0, union((core_lib:get_anno(Le1))#a.ns, Ks), St1),
+ {[Le1|Les1],St2};
+uexprs([], _, St) -> {[],St}.
+
+uexpr(#iset{anno=A,var=V,arg=A0}, Ks, St0) ->
+ {A1,St1} = uexpr(A0, Ks, St0),
+ {#iset{anno=A#a{us=del_element(V#c_var.name, (core_lib:get_anno(A1))#a.us),
+ ns=add_element(V#c_var.name, (core_lib:get_anno(A1))#a.ns)},
+ var=V,arg=A1},St1};
+%% imatch done in uexprs.
+uexpr(#iletrec{anno=A,defs=Fs0,body=B0}, Ks, St0) ->
+ %%ok = io:fwrite("~w: ~p~n", [?LINE,{Fs0,B0}]),
+ {Fs1,St1} = mapfoldl(fun ({Name,F0}, St0) ->
+ {F1,St1} = uexpr(F0, Ks, St0),
+ {{Name,F1},St1}
+ end, St0, Fs0),
+ {B1,St2} = uexprs(B0, Ks, St1),
+ Used = used_in_any(map(fun ({_,F}) -> F end, Fs1) ++ B1),
+ {#iletrec{anno=A#a{us=Used,ns=[]},defs=Fs1,body=B1},St2};
+uexpr(#icase{anno=A,args=As0,clauses=Cs0,fc=Fc0}, Ks, St0) ->
+ %% As0 will never generate new variables.
+ {As1,St1} = uexpr_list(As0, Ks, St0),
+ {Cs1,St2} = uclauses(Cs0, Ks, St1),
+ {Fc1,St3} = uclause(Fc0, Ks, St2),
+ Used = union(used_in_any(As1), used_in_any(Cs1)),
+ New = new_in_all(Cs1),
+ {#icase{anno=A#a{us=Used,ns=New},args=As1,clauses=Cs1,fc=Fc1},St3};
+uexpr(#ifun{anno=A,id=Id,vars=As,clauses=Cs0,fc=Fc0}, Ks0, St0) ->
+ Avs = lit_list_vars(As),
+ Ks1 = union(Avs, Ks0),
+ {Cs1,St1} = ufun_clauses(Cs0, Ks1, St0),
+ {Fc1,St2} = ufun_clause(Fc0, Ks1, St1),
+ Used = subtract(intersection(used_in_any(Cs1), Ks0), Avs),
+ {#ifun{anno=A#a{us=Used,ns=[]},id=Id,vars=As,clauses=Cs1,fc=Fc1},St2};
+uexpr(#iapply{anno=A,op=Op,args=As}, _, St) ->
+ Used = union(lit_vars(Op), lit_list_vars(As)),
+ {#iapply{anno=A#a{us=Used},op=Op,args=As},St};
+uexpr(#iprimop{anno=A,name=Name,args=As}, _, St) ->
+ Used = lit_list_vars(As),
+ {#iprimop{anno=A#a{us=Used},name=Name,args=As},St};
+uexpr(#icall{anno=A,module=Mod,name=Name,args=As}, _, St) ->
+ Used = union([lit_vars(Mod),lit_vars(Name),lit_list_vars(As)]),
+ {#icall{anno=A#a{us=Used},module=Mod,name=Name,args=As},St};
+uexpr(#itry{anno=A,args=As0,vars=Vs,body=Bs0,evars=Evs,handler=Hs0}, Ks, St0) ->
+ %% Note that we export only from body and exception.
+ {As1,St1} = uexprs(As0, Ks, St0),
+ {Bs1,St2} = uexprs(Bs0, Ks, St1),
+ {Hs1,St3} = uexprs(Hs0, Ks, St2),
+ Used = intersection(used_in_any(Bs1++Hs1++As1), Ks),
+ New = new_in_all(Bs1++Hs1),
+ {#itry{anno=A#a{us=Used,ns=New},
+ args=As1,vars=Vs,body=Bs1,evars=Evs,handler=Hs1},St3};
+uexpr(#icatch{anno=A,body=Es0}, Ks, St0) ->
+ {Es1,St1} = uexprs(Es0, Ks, St0),
+ {#icatch{anno=A#a{us=used_in_any(Es1)},body=Es1},St1};
+uexpr(#ireceive1{anno=A,clauses=Cs0}, Ks, St0) ->
+ {Cs1,St1} = uclauses(Cs0, Ks, St0),
+ {#ireceive1{anno=A#a{us=used_in_any(Cs1),ns=new_in_all(Cs1)},
+ clauses=Cs1},St1};
+uexpr(#ireceive2{anno=A,clauses=Cs0,timeout=Te0,action=Tes0}, Ks, St0) ->
+ %% Te0 will never generate new variables.
+ {Te1,St1} = uexpr(Te0, Ks, St0),
+ {Cs1,St2} = uclauses(Cs0, Ks, St1),
+ {Tes1,St3} = uexprs(Tes0, Ks, St2),
+ Used = union([used_in_any(Cs1),used_in_any(Tes1),
+ (core_lib:get_anno(Te1))#a.us]),
+ New = case Cs1 of
+ [] -> new_in_any(Tes1);
+ _ -> intersection(new_in_all(Cs1), new_in_any(Tes1))
+ end,
+ {#ireceive2{anno=A#a{us=Used,ns=New},
+ clauses=Cs1,timeout=Te1,action=Tes1},St3};
+uexpr(#iprotect{anno=A,body=Es0}, Ks, St0) ->
+ {Es1,St1} = uexprs(Es0, Ks, St0),
+ Used = used_in_any(Es1),
+ {#iprotect{anno=A#a{us=Used},body=Es1},St1}; %No new variables escape!
+uexpr(#ibinary{anno=A,segments=Ss}, _, St) ->
+ Used = bitstr_vars(Ss),
+ {#ibinary{anno=A#a{us=Used},segments=Ss},St};
+uexpr(Lit, _, St) ->
+ true = core_lib:is_simple(Lit), %Sanity check!
+ Vs = lit_vars(Lit),
+ Anno = core_lib:get_anno(Lit),
+ {core_lib:set_anno(Lit, #a{us=Vs,anno=Anno}),St}.
+
+uexpr_list(Les0, Ks, St0) ->
+ mapfoldl(fun (Le, St) -> uexpr(Le, Ks, St) end, St0, Les0).
+
+%% ufun_clauses([Lclause], [KnownVar], State) -> {[Lclause],State}.
+
+ufun_clauses(Lcs, Ks, St0) ->
+ mapfoldl(fun (Lc, St) -> ufun_clause(Lc, Ks, St) end, St0, Lcs).
+
+%% ufun_clause(Lclause, [KnownVar], State) -> {Lclause,State}.
+
+ufun_clause(Cl0, Ks, St0) ->
+ {Cl1,Pvs,Used,_,St1} = uclause(Cl0, [], Ks, St0),
+ A0 = get_ianno(Cl1),
+ A = A0#a{us=subtract(intersection(Used, Ks), Pvs),ns=[]},
+ {Cl1#iclause{anno=A},St1}.
+
+%% upattern(Pat, [KnownVar], State) ->
+%% {Pat,[GuardTest],[NewVar],[UsedVar],State}.
+
+upattern(#c_var{name='_'}, _, St0) ->
+ {New,St1} = new_var_name(St0),
+ {#c_var{name=New},[],[New],[],St1};
+upattern(#c_var{name=V}=Var, Ks, St0) ->
+ case is_element(V, Ks) of
+ true ->
+ {N,St1} = new_var_name(St0),
+ New = #c_var{name=N},
+ Test = #icall{anno=#a{us=add_element(N, [V])},
+ module=#c_atom{val=erlang},
+ name=#c_atom{val='=:='},
+ args=[New,Var]},
+ %% Test doesn't need protecting.
+ {New,[Test],[N],[],St1};
+ false -> {Var,[],[V],[],St0}
+ end;
+upattern(#c_cons{hd=H0,tl=T0}=Cons, Ks, St0) ->
+ {H1,Hg,Hv,Hu,St1} = upattern(H0, Ks, St0),
+ {T1,Tg,Tv,Tu,St2} = upattern(T0, union(Hv, Ks), St1),
+ {Cons#c_cons{hd=H1,tl=T1},Hg ++ Tg,union(Hv, Tv),union(Hu, Tu),St2};
+upattern(#c_tuple{es=Es0}=Tuple, Ks, St0) ->
+ {Es1,Esg,Esv,Eus,St1} = upattern_list(Es0, Ks, St0),
+ {Tuple#c_tuple{es=Es1},Esg,Esv,Eus,St1};
+upattern(#c_binary{segments=Es0}=Bin, Ks, St0) ->
+ {Es1,Esg,Esv,Eus,St1} = upat_bin(Es0, Ks, St0),
+ {Bin#c_binary{segments=Es1},Esg,Esv,Eus,St1};
+upattern(#c_alias{var=V0,pat=P0}=Alias, Ks, St0) ->
+ {V1,Vg,Vv,Vu,St1} = upattern(V0, Ks, St0),
+ {P1,Pg,Pv,Pu,St2} = upattern(P0, union(Vv, Ks), St1),
+ {Alias#c_alias{var=V1,pat=P1},Vg ++ Pg,union(Vv, Pv),union(Vu, Pu),St2};
+upattern(Other, _, St) -> {Other,[],[],[],St}. %Constants
+
+%% upattern_list([Pat], [KnownVar], State) ->
+%% {[Pat],[GuardTest],[NewVar],[UsedVar],State}.
+
+upattern_list([P0|Ps0], Ks, St0) ->
+ {P1,Pg,Pv,Pu,St1} = upattern(P0, Ks, St0),
+ {Ps1,Psg,Psv,Psu,St2} = upattern_list(Ps0, union(Pv, Ks), St1),
+ {[P1|Ps1],Pg ++ Psg,union(Pv, Psv),union(Pu, Psu),St2};
+upattern_list([], _, St) -> {[],[],[],[],St}.
+
+%% upat_bin([Pat], [KnownVar], State) ->
+%% {[Pat],[GuardTest],[NewVar],[UsedVar],State}.
+upat_bin(Es0, Ks, St0) ->
+ upat_bin(Es0, Ks, [], St0).
+
+%% upat_bin([Pat], [KnownVar], [LocalVar], State) ->
+%% {[Pat],[GuardTest],[NewVar],[UsedVar],State}.
+upat_bin([P0|Ps0], Ks, Bs, St0) ->
+ {P1,Pg,Pv,Pu,Bs1,St1} = upat_element(P0, Ks, Bs, St0),
+ {Ps1,Psg,Psv,Psu,St2} = upat_bin(Ps0, union(Pv, Ks), Bs1, St1),
+ {[P1|Ps1],Pg ++ Psg,union(Pv, Psv),union(Pu, Psu),St2};
+upat_bin([], _, _, St) -> {[],[],[],[],St}.
+
+
+%% upat_element(Segment, [KnownVar], [LocalVar], State) ->
+%% {Segment,[GuardTest],[NewVar],[UsedVar],[LocalVar],State}
+upat_element(#c_bitstr{val=H0,size=Sz}=Seg, Ks, Bs, St0) ->
+ {H1,Hg,Hv,[],St1} = upattern(H0, Ks, St0),
+ Bs1 = case H0 of
+ #c_var{name=Hname} ->
+ case H1 of
+ #c_var{name=Hname} ->
+ Bs;
+ #c_var{name=Other} ->
+ [{Hname, Other}|Bs]
+ end;
+ _ ->
+ Bs
+ end,
+ {Sz1, Us} = case Sz of
+ #c_var{name=Vname} ->
+ rename_bitstr_size(Vname, Bs);
+ _Other -> {Sz, []}
+ end,
+ {Seg#c_bitstr{val=H1, size=Sz1},Hg,Hv,Us,Bs1,St1}.
+
+rename_bitstr_size(V, [{V, N}|_]) ->
+ New = #c_var{name=N},
+ {New, [N]};
+rename_bitstr_size(V, [_|Rest]) ->
+ rename_bitstr_size(V, Rest);
+rename_bitstr_size(V, []) ->
+ Old = #c_var{name=V},
+ {Old, [V]}.
+
+used_in_any(Les) ->
+ foldl(fun (Le, Ns) -> union((core_lib:get_anno(Le))#a.us, Ns) end,
+ [], Les).
+
+new_in_any(Les) ->
+ foldl(fun (Le, Ns) -> union((core_lib:get_anno(Le))#a.ns, Ns) end,
+ [], Les).
+
+new_in_all([Le|Les]) ->
+ foldl(fun (L, Ns) -> intersection((core_lib:get_anno(L))#a.ns, Ns) end,
+ (core_lib:get_anno(Le))#a.ns, Les);
+new_in_all([]) -> [].
+
+%% The AfterVars are the variables which are used afterwards. We need
+%% this to work out which variables are actually exported and used
+%% from case/receive. In subblocks/clauses the AfterVars of the block
+%% are just the exported variables.
+
+cbody(B0, St0) ->
+ {B1,_,_,St1} = cexpr(B0, [], St0),
+ {B1,St1}.
+
+%% cclause(Lclause, [AfterVar], State) -> {Cclause,State}.
+%% The AfterVars are the exported variables.
+
+cclause(#iclause{anno=#a{anno=Anno},pats=Ps,guard=G0,body=B0}, Exp, St0) ->
+ {B1,_Us1,St1} = cexprs(B0, Exp, St0),
+ {G1,St2} = cguard(G0, St1),
+ {#c_clause{anno=Anno,pats=Ps,guard=G1,body=B1},St2}.
+
+cclauses(Lcs, Es, St0) ->
+ mapfoldl(fun (Lc, St) -> cclause(Lc, Es, St) end, St0, Lcs).
+
+cguard([], St) -> {#c_atom{val=true},St};
+cguard(Gs, St0) ->
+ {G,_,St1} = cexprs(Gs, [], St0),
+ {G,St1}.
+
+%% cexprs([Lexpr], [AfterVar], State) -> {Cexpr,[AfterVar],State}.
+%% Must be sneaky here at the last expr when combining exports for the
+%% whole sequence and exports for that expr.
+
+cexprs([#iset{var=#c_var{name=Name}=Var}=Iset], As, St) ->
+ %% Make return value explicit, and make Var true top level.
+ cexprs([Iset,Var#c_var{anno=#a{us=[Name]}}], As, St);
+cexprs([Le], As, St0) ->
+ {Ce,Es,Us,St1} = cexpr(Le, As, St0),
+ Exp = make_vars(As), %The export variables
+ if
+ Es == [] -> {core_lib:make_values([Ce|Exp]),union(Us, As),St1};
+ true ->
+ {R,St2} = new_var(St1),
+ {#c_let{anno=get_lineno_anno(Ce),
+ vars=[R|make_vars(Es)],arg=Ce,
+ body=core_lib:make_values([R|Exp])},
+ union(Us, As),St2}
+ end;
+cexprs([#iset{anno=#a{anno=A},var=V,arg=A0}|Les], As0, St0) ->
+ {Ces,As1,St1} = cexprs(Les, As0, St0),
+ {A1,Es,Us,St2} = cexpr(A0, As1, St1),
+ {#c_let{anno=A,vars=[V|make_vars(Es)],arg=A1,body=Ces},
+ union(Us, As1),St2};
+cexprs([Le|Les], As0, St0) ->
+ {Ces,As1,St1} = cexprs(Les, As0, St0),
+ {Ce,Es,Us,St2} = cexpr(Le, As1, St1),
+ if
+ Es == [] ->
+ {#c_seq{arg=Ce,body=Ces},union(Us, As1),St2};
+ true ->
+ {R,St3} = new_var(St2),
+ {#c_let{vars=[R|make_vars(Es)],arg=Ce,body=Ces},
+ union(Us, As1),St3}
+ end.
+
+%% cexpr(Lexpr, [AfterVar], State) -> {Cexpr,[ExpVar],[UsedVar],State}.
+
+cexpr(#iletrec{anno=A,defs=Fs0,body=B0}, As, St0) ->
+ {Fs1,{_,St1}} = mapfoldl(fun ({Name,F0}, {Used,St0}) ->
+ {F1,[],Us,St1} = cexpr(F0, [], St0),
+ {#c_def{name=#c_fname{id=Name,arity=1},
+ val=F1},
+ {union(Us, Used),St1}}
+ end, {[],St0}, Fs0),
+ Exp = intersection(A#a.ns, As),
+ {B1,_Us,St2} = cexprs(B0, Exp, St1),
+ {#c_letrec{anno=A#a.anno,defs=Fs1,body=B1},Exp,A#a.us,St2};
+cexpr(#icase{anno=A,args=Largs,clauses=Lcs,fc=Lfc}, As, St0) ->
+ Exp = intersection(A#a.ns, As), %Exports
+ {Cargs,St1} = foldr(fun (La, {Cas,Sta}) ->
+ {Ca,[],_Us1,Stb} = cexpr(La, As, Sta),
+ {[Ca|Cas],Stb}
+ end, {[],St0}, Largs),
+ {Ccs,St2} = cclauses(Lcs, Exp, St1),
+ {Cfc,St3} = cclause(Lfc, [], St2), %Never exports
+ {#c_case{anno=A#a.anno,
+ arg=core_lib:make_values(Cargs),clauses=Ccs ++ [Cfc]},
+ Exp,A#a.us,St3};
+cexpr(#ireceive1{anno=A,clauses=Lcs}, As, St0) ->
+ Exp = intersection(A#a.ns, As), %Exports
+ {Ccs,St1} = cclauses(Lcs, Exp, St0),
+ {#c_receive{anno=A#a.anno,
+ clauses=Ccs,
+ timeout=#c_atom{val=infinity},action=#c_atom{val=true}},
+ Exp,A#a.us,St1};
+cexpr(#ireceive2{anno=A,clauses=Lcs,timeout=Lto,action=Les}, As, St0) ->
+ Exp = intersection(A#a.ns, As), %Exports
+ {Cto,[],_Us1,St1} = cexpr(Lto, As, St0),
+ {Ccs,St2} = cclauses(Lcs, Exp, St1),
+ {Ces,_Us2,St3} = cexprs(Les, Exp, St2),
+ {#c_receive{anno=A#a.anno,
+ clauses=Ccs,timeout=Cto,action=Ces},
+ Exp,A#a.us,St3};
+cexpr(#itry{anno=A,args=La,vars=Vs,body=Lb,evars=Evs,handler=Lh}, As, St0) ->
+ Exp = intersection(A#a.ns, As), %Exports
+ {Ca,_Us1,St1} = cexprs(La, [], St0),
+ {Cb,_Us2,St2} = cexprs(Lb, Exp, St1),
+ {Ch,_Us3,St3} = cexprs(Lh, Exp, St2),
+ {#c_try{anno=A#a.anno,arg=Ca,vars=Vs,body=Cb,evars=Evs,handler=Ch},
+ Exp,A#a.us,St3};
+cexpr(#icatch{anno=A,body=Les}, _As, St0) ->
+ {Ces,_Us1,St1} = cexprs(Les, [], St0), %Never export!
+ {#c_catch{body=Ces},[],A#a.us,St1};
+cexpr(#ifun{anno=A,id=Id,vars=Args,clauses=Lcs,fc=Lfc}, _As, St0) ->
+ {Ccs,St1} = cclauses(Lcs, [], St0), %NEVER export!
+ {Cfc,St2} = cclause(Lfc, [], St1),
+ Anno = A#a.anno,
+ {#c_fun{anno=Id++Anno,vars=Args,
+ body=#c_case{anno=Anno,
+ arg=core_lib:set_anno(core_lib:make_values(Args), Anno),
+ clauses=Ccs ++ [Cfc]}},
+ [],A#a.us,St2};
+cexpr(#iapply{anno=A,op=Op,args=Args}, _As, St) ->
+ {#c_apply{anno=A#a.anno,op=Op,args=Args},[],A#a.us,St};
+cexpr(#icall{anno=A,module=Mod,name=Name,args=Args}, _As, St) ->
+ {#c_call{anno=A#a.anno,module=Mod,name=Name,args=Args},[],A#a.us,St};
+cexpr(#iprimop{anno=A,name=Name,args=Args}, _As, St) ->
+ {#c_primop{anno=A#a.anno,name=Name,args=Args},[],A#a.us,St};
+cexpr(#iprotect{anno=A,body=Es}, _As, St0) ->
+ {Ce,_,St1} = cexprs(Es, [], St0),
+ V = #c_var{name='Try'}, %The names are arbitrary
+ Vs = [#c_var{name='T'},#c_var{name='R'}],
+ {#c_try{anno=A#a.anno,arg=Ce,vars=[V],body=V,
+ evars=Vs,handler=#c_atom{val=false}},
+ [],A#a.us,St1};
+cexpr(#ibinary{anno=#a{anno=Anno,us=Us},segments=Segs}, _As, St) ->
+ {#c_binary{anno=Anno,segments=Segs},[],Us,St};
+cexpr(Lit, _As, St) ->
+ true = core_lib:is_simple(Lit), %Sanity check!
+ Anno = core_lib:get_anno(Lit),
+ Vs = Anno#a.us,
+ %%Vs = lit_vars(Lit),
+ {core_lib:set_anno(Lit, Anno#a.anno),[],Vs,St}.
+
+%% lit_vars(Literal) -> [Var].
+
+lit_vars(Lit) -> lit_vars(Lit, []).
+
+lit_vars(#c_cons{hd=H,tl=T}, Vs) -> lit_vars(H, lit_vars(T, Vs));
+lit_vars(#c_tuple{es=Es}, Vs) -> lit_list_vars(Es, Vs);
+lit_vars(#c_var{name=V}, Vs) -> add_element(V, Vs);
+lit_vars(_, Vs) -> Vs. %These are atomic
+
+% lit_bin_vars(Segs, Vs) ->
+% foldl(fun (#c_bitstr{val=V,size=S}, Vs0) ->
+% lit_vars(V, lit_vars(S, Vs0))
+% end, Vs, Segs).
+
+lit_list_vars(Ls) -> lit_list_vars(Ls, []).
+
+lit_list_vars(Ls, Vs) ->
+ foldl(fun (L, Vs0) -> lit_vars(L, Vs0) end, Vs, Ls).
+
+bitstr_vars(Segs) ->
+ bitstr_vars(Segs, []).
+
+bitstr_vars(Segs, Vs) ->
+ foldl(fun (#c_bitstr{val=V,size=S}, Vs0) ->
+ lit_vars(V, lit_vars(S, Vs0))
+ end, Vs, Segs).
+
+get_ianno(Ce) ->
+ case core_lib:get_anno(Ce) of
+ #a{}=A -> A;
+ A when is_list(A) -> #a{anno=A}
+ end.
+
+get_lineno_anno(Ce) ->
+ case core_lib:get_anno(Ce) of
+ #a{anno=A} -> A;
+ A when is_list(A) -> A
+ end.
+
+
+%%%
+%%% Handling of warnings.
+%%%
+
+format_error(nomatch) -> "pattern cannot possibly match".
+
+add_warning(Line, Term, #core{ws=Ws}=St) when Line >= 0 ->
+ St#core{ws=[{Line,?MODULE,Term}|Ws]};
+add_warning(_, _, St) -> St.
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_kernel.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_kernel.erl
new file mode 100644
index 0000000000..d7c3e1add9
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_kernel.erl
@@ -0,0 +1,1567 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: v3_kernel.erl,v 1.3 2010/03/04 13:54:20 maria Exp $
+%%
+%% Purpose : Transform Core Erlang to Kernel Erlang
+
+%% Kernel erlang is like Core Erlang with a few significant
+%% differences:
+%%
+%% 1. It is flat! There are no nested calls or sub-blocks.
+%%
+%% 2. All variables are unique in a function. There is no scoping, or
+%% rather the scope is the whole function.
+%%
+%% 3. Pattern matching (in cases and receives) has been compiled.
+%%
+%% 4. The annotations contain variable usages. Seeing we have to work
+%% this out anyway for funs we might as well pass it on for free to
+%% later passes.
+%%
+%% 5. All remote-calls are to statically named m:f/a. Meta-calls are
+%% passed via erlang:apply/3.
+%%
+%% The translation is done in two passes:
+%%
+%% 1. Basic translation, translate variable/function names, flatten
+%% completely, pattern matching compilation.
+%%
+%% 2. Fun-lifting (lambda-lifting), variable usage annotation and
+%% last-call handling.
+%%
+%% All new Kexprs are created in the first pass, they are just
+%% annotated in the second.
+%%
+%% Functions and BIFs
+%%
+%% Functions are "call"ed or "enter"ed if it is a last call, their
+%% return values may be ignored. BIFs are things which are known to
+%% be internal by the compiler and can only be called, their return
+%% values cannot be ignored.
+%%
+%% Letrec's are handled rather naively. All the functions in one
+%% letrec are handled as one block to find the free variables. While
+%% this is not optimal it reflects how letrec's often are used. We
+%% don't have to worry about variable shadowing and nested letrec's as
+%% this is handled in the variable/function name translation. There
+%% is a little bit of trickery to ensure letrec transformations fit
+%% into the scheme of things.
+%%
+%% To ensure unique variable names we use a variable substitution
+%% table and keep the set of all defined variables. The nested
+%% scoping of Core means that we must also nest the substitution
+%% tables, but the defined set must be passed through to match the
+%% flat structure of Kernel and to make sure variables with the same
+%% name from different scopes get different substitutions.
+%%
+%% We also use these substitutions to handle the variable renaming
+%% necessary in pattern matching compilation.
+%%
+%% The pattern matching compilation assumes that the values of
+%% different types don't overlap. This means that as there is no
+%% character type yet in the machine all characters must be converted
+%% to integers!
+
+-module(v3_kernel).
+
+-export([module/2,format_error/1]).
+
+-import(lists, [map/2,foldl/3,foldr/3,mapfoldl/3,splitwith/2,
+ member/2,reverse/1,reverse/2]).
+-import(ordsets, [add_element/2,del_element/2,union/2,union/1,subtract/2]).
+
+-include("core_parse.hrl").
+-include("v3_kernel.hrl").
+
+%% These are not defined in v3_kernel.hrl.
+get_kanno(Kthing) -> element(2, Kthing).
+set_kanno(Kthing, Anno) -> setelement(2, Kthing, Anno).
+
+%% Internal kernel expressions and help functions.
+%% N.B. the annotation field is ALWAYS the first field!
+
+-record(ivalues, {anno=[],args}).
+-record(ifun, {anno=[],vars,body}).
+-record(iset, {anno=[],vars,arg,body}).
+-record(iletrec, {anno=[],defs}).
+-record(ialias, {anno=[],vars,pat}).
+-record(iclause, {anno=[],sub,pats,guard,body}).
+-record(ireceive_accept, {anno=[],arg}).
+-record(ireceive_next, {anno=[],arg}).
+
+%% State record for kernel translator.
+-record(kern, {func, %Current function
+ vcount=0, %Variable counter
+ fcount=0, %Fun counter
+ ds=[], %Defined variables
+ funs=[], %Fun functions
+ free=[], %Free variables
+ ws=[], %Warnings.
+ extinstr=false}). %Generate extended instructions
+
+module(#c_module{anno=A,name=M,exports=Es,attrs=As,defs=Fs}, Options) ->
+ ExtInstr = not member(no_new_apply, Options),
+ {Kfs,St} = mapfoldl(fun function/2, #kern{extinstr=ExtInstr}, Fs),
+ Kes = map(fun (#c_fname{id=N,arity=Ar}) -> {N,Ar} end, Es),
+ Kas = map(fun (#c_def{name=#c_atom{val=N},val=V}) ->
+ {N,core_lib:literal_value(V)} end, As),
+ {ok,#k_mdef{anno=A,name=M#c_atom.val,exports=Kes,attributes=Kas,
+ body=Kfs ++ St#kern.funs},St#kern.ws}.
+
+function(#c_def{anno=Af,name=#c_fname{id=F,arity=Arity},val=Body}, St0) ->
+ %%ok = io:fwrite("kern: ~p~n", [{F,Arity}]),
+ St1 = St0#kern{func={F,Arity},vcount=0,fcount=0,ds=sets:new()},
+ {#ifun{anno=Ab,vars=Kvs,body=B0},[],St2} = expr(Body, new_sub(), St1),
+ {B1,_,St3} = ubody(B0, return, St2),
+ %%B1 = B0, St3 = St2, %Null second pass
+ {#k_fdef{anno=#k{us=[],ns=[],a=Af ++ Ab},
+ func=F,arity=Arity,vars=Kvs,body=B1},St3}.
+
+%% body(Cexpr, Sub, State) -> {Kexpr,[PreKepxr],State}.
+%% Do the main sequence of a body. A body ends in an atomic value or
+%% values. Must check if vector first so do expr.
+
+body(#c_values{anno=A,es=Ces}, Sub, St0) ->
+ %% Do this here even if only in bodies.
+ {Kes,Pe,St1} = atomic_list(Ces, Sub, St0),
+ %%{Kes,Pe,St1} = expr_list(Ces, Sub, St0),
+ {#ivalues{anno=A,args=Kes},Pe,St1};
+body(#ireceive_next{anno=A}, _, St) ->
+ {#k_receive_next{anno=A},[],St};
+body(Ce, Sub, St0) ->
+ expr(Ce, Sub, St0).
+
+%% guard(Cexpr, Sub, State) -> {Kexpr,State}.
+%% We handle guards almost as bodies. The only special thing we
+%% must do is to make the final Kexpr a #k_test{}.
+%% Also, we wrap the entire guard in a try/catch which is
+%% not strictly needed, but makes sure that every 'bif' instruction
+%% will get a proper failure label.
+
+guard(G0, Sub, St0) ->
+ {G1,St1} = wrap_guard(G0, St0),
+ {Ge0,Pre,St2} = expr(G1, Sub, St1),
+ {Ge,St} = gexpr_test(Ge0, St2),
+ {pre_seq(Pre, Ge),St}.
+
+%% Wrap the entire guard in a try/catch if needed.
+
+wrap_guard(#c_try{}=Try, St) -> {Try,St};
+wrap_guard(Core, St0) ->
+ {VarName,St} = new_var_name(St0),
+ Var = #c_var{name=VarName},
+ Try = #c_try{arg=Core,vars=[Var],body=Var,evars=[],handler=#c_atom{val=false}},
+ {Try,St}.
+
+%% gexpr_test(Kexpr, State) -> {Kexpr,State}.
+%% Builds the final boolean test from the last Kexpr in a guard test.
+%% Must enter try blocks and isets and find the last Kexpr in them.
+%% This must end in a recognised BEAM test!
+
+gexpr_test(#k_bif{anno=A,op=#k_remote{mod=#k_atom{val=erlang},
+ name=#k_atom{val=is_boolean},arity=1}=Op,
+ args=Kargs}, St) ->
+ %% XXX Remove this clause in R11. For bootstrap purposes, we must
+ %% recognize erlang:is_boolean/1 here.
+ {#k_test{anno=A,op=Op,args=Kargs},St};
+gexpr_test(#k_bif{anno=A,op=#k_remote{mod=#k_atom{val=erlang},
+ name=#k_atom{val=internal_is_record},arity=3}=Op,
+ args=Kargs}, St) ->
+ {#k_test{anno=A,op=Op,args=Kargs},St};
+gexpr_test(#k_bif{anno=A,op=#k_remote{mod=#k_atom{val=erlang},
+ name=#k_atom{val=F},arity=Ar}=Op,
+ args=Kargs}=Ke, St) ->
+ %% Either convert to test if ok, or add test.
+ %% At this stage, erlang:float/1 is not a type test. (It should
+ %% have been converted to erlang:is_float/1.)
+ case erl_internal:new_type_test(F, Ar) orelse
+ erl_internal:comp_op(F, Ar) of
+ true -> {#k_test{anno=A,op=Op,args=Kargs},St};
+ false -> gexpr_test_add(Ke, St) %Add equality test
+ end;
+gexpr_test(#k_try{arg=B0,vars=[#k_var{name=X}],body=#k_var{name=X},
+ handler=#k_atom{val=false}}=Try, St0) ->
+ {B,St} = gexpr_test(B0, St0),
+ %%ok = io:fwrite("~w: ~p~n", [?LINE,{B0,B}]),
+ {Try#k_try{arg=B},St};
+gexpr_test(#iset{body=B0}=Iset, St0) ->
+ {B1,St1} = gexpr_test(B0, St0),
+ {Iset#iset{body=B1},St1};
+gexpr_test(Ke, St) -> gexpr_test_add(Ke, St). %Add equality test
+
+gexpr_test_add(Ke, St0) ->
+ Test = #k_remote{mod=#k_atom{val='erlang'},
+ name=#k_atom{val='=:='},
+ arity=2},
+ {Ae,Ap,St1} = force_atomic(Ke, St0),
+ {pre_seq(Ap, #k_test{anno=get_kanno(Ke),
+ op=Test,args=[Ae,#k_atom{val='true'}]}),St1}.
+
+%% expr(Cexpr, Sub, State) -> {Kexpr,[PreKexpr],State}.
+%% Convert a Core expression, flattening it at the same time.
+
+expr(#c_var{anno=A,name=V}, Sub, St) ->
+ {#k_var{anno=A,name=get_vsub(V, Sub)},[],St};
+expr(#c_char{anno=A,val=C}, _Sub, St) ->
+ {#k_int{anno=A,val=C},[],St}; %Convert to integers!
+expr(#c_int{anno=A,val=I}, _Sub, St) ->
+ {#k_int{anno=A,val=I},[],St};
+expr(#c_float{anno=A,val=F}, _Sub, St) ->
+ {#k_float{anno=A,val=F},[],St};
+expr(#c_atom{anno=A,val=At}, _Sub, St) ->
+ {#k_atom{anno=A,val=At},[],St};
+expr(#c_string{anno=A,val=S}, _Sub, St) ->
+ {#k_string{anno=A,val=S},[],St};
+expr(#c_nil{anno=A}, _Sub, St) ->
+ {#k_nil{anno=A},[],St};
+expr(#c_cons{anno=A,hd=Ch,tl=Ct}, Sub, St0) ->
+ %% Do cons in two steps, first the expressions left to right, then
+ %% any remaining literals right to left.
+ {Kh0,Hp0,St1} = expr(Ch, Sub, St0),
+ {Kt0,Tp0,St2} = expr(Ct, Sub, St1),
+ {Kt1,Tp1,St3} = force_atomic(Kt0, St2),
+ {Kh1,Hp1,St4} = force_atomic(Kh0, St3),
+ {#k_cons{anno=A,hd=Kh1,tl=Kt1},Hp0 ++ Tp0 ++ Tp1 ++ Hp1,St4};
+expr(#c_tuple{anno=A,es=Ces}, Sub, St0) ->
+ {Kes,Ep,St1} = atomic_list(Ces, Sub, St0),
+ {#k_tuple{anno=A,es=Kes},Ep,St1};
+expr(#c_binary{anno=A,segments=Cv}, Sub, St0) ->
+ case catch atomic_bin(Cv, Sub, St0, 0) of
+ {'EXIT',R} -> exit(R);
+ bad_element_size ->
+ Erl = #c_atom{val=erlang},
+ Name = #c_atom{val=error},
+ Args = [#c_atom{val=badarg}],
+ Fault = #c_call{module=Erl,name=Name,args=Args},
+ expr(Fault, Sub, St0);
+ {Kv,Ep,St1} ->
+ {#k_binary{anno=A,segs=Kv},Ep,St1}
+ end;
+expr(#c_fname{anno=A,arity=Ar}=Fname, Sub, St) ->
+ %% A local in an expression.
+ %% For now, these are wrapped into a fun by reverse
+ %% etha-conversion, but really, there should be exactly one
+ %% such "lambda function" for each escaping local name,
+ %% instead of one for each occurrence as done now.
+ Vs = [#c_var{name=list_to_atom("V" ++ integer_to_list(V))} ||
+ V <- integers(1, Ar)],
+ Fun = #c_fun{anno=A,vars=Vs,body=#c_apply{op=Fname,args=Vs}},
+ expr(Fun, Sub, St);
+expr(#c_fun{anno=A,vars=Cvs,body=Cb}, Sub0, St0) ->
+ {Kvs,Sub1,St1} = pattern_list(Cvs, Sub0, St0),
+ %%ok = io:fwrite("~w: ~p~n", [?LINE,{{Cvs,Sub0,St0},{Kvs,Sub1,St1}}]),
+ {Kb,Pb,St2} = body(Cb, Sub1, St1),
+ {#ifun{anno=A,vars=Kvs,body=pre_seq(Pb, Kb)},[],St2};
+expr(#c_seq{arg=Ca,body=Cb}, Sub, St0) ->
+ {Ka,Pa,St1} = body(Ca, Sub, St0),
+ case is_exit_expr(Ka) of
+ true -> {Ka,Pa,St1};
+ false ->
+ {Kb,Pb,St2} = body(Cb, Sub, St1),
+ {Kb,Pa ++ [Ka] ++ Pb,St2}
+ end;
+expr(#c_let{anno=A,vars=Cvs,arg=Ca,body=Cb}, Sub0, St0) ->
+ %%ok = io:fwrite("~w: ~p~n", [?LINE,{Cvs,Sub0,St0}]),
+ {Ka,Pa,St1} = body(Ca, Sub0, St0),
+ case is_exit_expr(Ka) of
+ true -> {Ka,Pa,St1};
+ false ->
+ {Kps,Sub1,St2} = pattern_list(Cvs, Sub0, St1),
+ %%ok = io:fwrite("~w: ~p~n", [?LINE,{Kps,Sub1,St1,St2}]),
+ %% Break known multiple values into separate sets.
+ Sets = case Ka of
+ #ivalues{args=Kas} ->
+ foldr2(fun (V, Val, Sb) ->
+ [#iset{vars=[V],arg=Val}|Sb] end,
+ [], Kps, Kas);
+ _Other ->
+ [#iset{anno=A,vars=Kps,arg=Ka}]
+ end,
+ {Kb,Pb,St3} = body(Cb, Sub1, St2),
+ {Kb,Pa ++ Sets ++ Pb,St3}
+ end;
+expr(#c_letrec{anno=A,defs=Cfs,body=Cb}, Sub0, St0) ->
+ %% Make new function names and store substitution.
+ {Fs0,{Sub1,St1}} =
+ mapfoldl(fun (#c_def{name=#c_fname{id=F,arity=Ar},val=B}, {Sub,St0}) ->
+ {N,St1} = new_fun_name(atom_to_list(F)
+ ++ "/" ++
+ integer_to_list(Ar),
+ St0),
+ {{N,B},{set_fsub(F, Ar, N, Sub),St1}}
+ end, {Sub0,St0}, Cfs),
+ %% Run translation on functions and body.
+ {Fs1,St2} = mapfoldl(fun ({N,Fd0}, St1) ->
+ {Fd1,[],St2} = expr(Fd0, Sub1, St1),
+ Fd = set_kanno(Fd1, A),
+ {{N,Fd},St2}
+ end, St1, Fs0),
+ {Kb,Pb,St3} = body(Cb, Sub1, St2),
+ {Kb,[#iletrec{anno=A,defs=Fs1}|Pb],St3};
+expr(#c_case{arg=Ca,clauses=Ccs}, Sub, St0) ->
+ {Ka,Pa,St1} = body(Ca, Sub, St0), %This is a body!
+ {Kvs,Pv,St2} = match_vars(Ka, St1), %Must have variables here!
+ {Km,St3} = kmatch(Kvs, Ccs, Sub, St2),
+ Match = flatten_seq(build_match(Kvs, Km)),
+ {last(Match),Pa ++ Pv ++ first(Match),St3};
+expr(#c_receive{anno=A,clauses=Ccs0,timeout=Ce,action=Ca}, Sub, St0) ->
+ {Ke,Pe,St1} = atomic_lit(Ce, Sub, St0), %Force this to be atomic!
+ {Rvar,St2} = new_var(St1),
+ %% Need to massage accept clauses and add reject clause before matching.
+ Ccs1 = map(fun (#c_clause{anno=Banno,body=B0}=C) ->
+ B1 = #c_seq{arg=#ireceive_accept{anno=A},body=B0},
+ C#c_clause{anno=Banno,body=B1}
+ end, Ccs0),
+ {Mpat,St3} = new_var_name(St2),
+ Rc = #c_clause{anno=[compiler_generated|A],
+ pats=[#c_var{name=Mpat}],guard=#c_atom{anno=A,val=true},
+ body=#ireceive_next{anno=A}},
+ {Km,St4} = kmatch([Rvar], Ccs1 ++ [Rc], Sub, add_var_def(Rvar, St3)),
+ {Ka,Pa,St5} = body(Ca, Sub, St4),
+ {#k_receive{anno=A,var=Rvar,body=Km,timeout=Ke,action=pre_seq(Pa, Ka)},
+ Pe,St5};
+expr(#c_apply{anno=A,op=Cop,args=Cargs}, Sub, St) ->
+ c_apply(A, Cop, Cargs, Sub, St);
+expr(#c_call{anno=A,module=M0,name=F0,args=Cargs}, Sub, St0) ->
+ {[M1,F1|Kargs],Ap,St1} = atomic_list([M0,F0|Cargs], Sub, St0),
+ Ar = length(Cargs),
+ case {M1,F1} of
+ {#k_atom{val=Ma},#k_atom{val=Fa}} ->
+ Call = case is_remote_bif(Ma, Fa, Ar) of
+ true ->
+ #k_bif{anno=A,
+ op=#k_remote{mod=M1,name=F1,arity=Ar},
+ args=Kargs};
+ false ->
+ #k_call{anno=A,
+ op=#k_remote{mod=M1,name=F1,arity=Ar},
+ args=Kargs}
+ end,
+ {Call,Ap,St1};
+ _Other when St0#kern.extinstr == false -> %Old explicit apply
+ Call = #c_call{anno=A,
+ module=#c_atom{val=erlang},
+ name=#c_atom{val=apply},
+ args=[M0,F0,make_list(Cargs)]},
+ expr(Call, Sub, St0);
+ _Other -> %New instruction in R10.
+ Call = #k_call{anno=A,
+ op=#k_remote{mod=M1,name=F1,arity=Ar},
+ args=Kargs},
+ {Call,Ap,St1}
+ end;
+expr(#c_primop{anno=A,name=#c_atom{val=match_fail},args=Cargs}, Sub, St0) ->
+ %% This special case will disappear.
+ {Kargs,Ap,St1} = atomic_list(Cargs, Sub, St0),
+ Ar = length(Cargs),
+ Call = #k_call{anno=A,op=#k_internal{name=match_fail,arity=Ar},args=Kargs},
+ {Call,Ap,St1};
+expr(#c_primop{anno=A,name=#c_atom{val=N},args=Cargs}, Sub, St0) ->
+ {Kargs,Ap,St1} = atomic_list(Cargs, Sub, St0),
+ Ar = length(Cargs),
+ {#k_bif{anno=A,op=#k_internal{name=N,arity=Ar},args=Kargs},Ap,St1};
+expr(#c_try{anno=A,arg=Ca,vars=Cvs,body=Cb,evars=Evs,handler=Ch}, Sub0, St0) ->
+ %% The normal try expression. The body and exception handler
+ %% variables behave as let variables.
+ {Ka,Pa,St1} = body(Ca, Sub0, St0),
+ {Kcvs,Sub1,St2} = pattern_list(Cvs, Sub0, St1),
+ {Kb,Pb,St3} = body(Cb, Sub1, St2),
+ {Kevs,Sub2,St4} = pattern_list(Evs, Sub0, St3),
+ {Kh,Ph,St5} = body(Ch, Sub2, St4),
+ {#k_try{anno=A,arg=pre_seq(Pa, Ka),
+ vars=Kcvs,body=pre_seq(Pb, Kb),
+ evars=Kevs,handler=pre_seq(Ph, Kh)},[],St5};
+expr(#c_catch{anno=A,body=Cb}, Sub, St0) ->
+ {Kb,Pb,St1} = body(Cb, Sub, St0),
+ {#k_catch{anno=A,body=pre_seq(Pb, Kb)},[],St1};
+%% Handle internal expressions.
+expr(#ireceive_accept{anno=A}, _Sub, St) -> {#k_receive_accept{anno=A},[],St}.
+
+%% expr_list([Cexpr], Sub, State) -> {[Kexpr],[PreKexpr],State}.
+
+% expr_list(Ces, Sub, St) ->
+% foldr(fun (Ce, {Kes,Esp,St0}) ->
+% {Ke,Ep,St1} = expr(Ce, Sub, St0),
+% {[Ke|Kes],Ep ++ Esp,St1}
+% end, {[],[],St}, Ces).
+
+%% match_vars(Kexpr, State) -> {[Kvar],[PreKexpr],State}.
+%% Force return from body into a list of variables.
+
+match_vars(#ivalues{args=As}, St) ->
+ foldr(fun (Ka, {Vs,Vsp,St0}) ->
+ {V,Vp,St1} = force_variable(Ka, St0),
+ {[V|Vs],Vp ++ Vsp,St1}
+ end, {[],[],St}, As);
+match_vars(Ka, St0) ->
+ {V,Vp,St1} = force_variable(Ka, St0),
+ {[V],Vp,St1}.
+
+%% c_apply(A, Op, [Carg], Sub, State) -> {Kexpr,[PreKexpr],State}.
+%% Transform application, detect which are guaranteed to be bifs.
+
+c_apply(A, #c_fname{anno=Ra,id=F0,arity=Ar}, Cargs, Sub, St0) ->
+ {Kargs,Ap,St1} = atomic_list(Cargs, Sub, St0),
+ F1 = get_fsub(F0, Ar, Sub), %Has it been rewritten
+ {#k_call{anno=A,op=#k_local{anno=Ra,name=F1,arity=Ar},args=Kargs},
+ Ap,St1};
+c_apply(A, Cop, Cargs, Sub, St0) ->
+ {Kop,Op,St1} = variable(Cop, Sub, St0),
+ {Kargs,Ap,St2} = atomic_list(Cargs, Sub, St1),
+ {#k_call{anno=A,op=Kop,args=Kargs},Op ++ Ap,St2}.
+
+flatten_seq(#iset{anno=A,vars=Vs,arg=Arg,body=B}) ->
+ [#iset{anno=A,vars=Vs,arg=Arg}|flatten_seq(B)];
+flatten_seq(Ke) -> [Ke].
+
+pre_seq([#iset{anno=A,vars=Vs,arg=Arg,body=B}|Ps], K) ->
+ B = undefined, %Assertion.
+ #iset{anno=A,vars=Vs,arg=Arg,body=pre_seq(Ps, K)};
+pre_seq([P|Ps], K) ->
+ #iset{vars=[],arg=P,body=pre_seq(Ps, K)};
+pre_seq([], K) -> K.
+
+%% atomic_lit(Cexpr, Sub, State) -> {Katomic,[PreKexpr],State}.
+%% Convert a Core expression making sure the result is an atomic
+%% literal.
+
+atomic_lit(Ce, Sub, St0) ->
+ {Ke,Kp,St1} = expr(Ce, Sub, St0),
+ {Ka,Ap,St2} = force_atomic(Ke, St1),
+ {Ka,Kp ++ Ap,St2}.
+
+force_atomic(Ke, St0) ->
+ case is_atomic(Ke) of
+ true -> {Ke,[],St0};
+ false ->
+ {V,St1} = new_var(St0),
+ {V,[#iset{vars=[V],arg=Ke}],St1}
+ end.
+
+% force_atomic_list(Kes, St) ->
+% foldr(fun (Ka, {As,Asp,St0}) ->
+% {A,Ap,St1} = force_atomic(Ka, St0),
+% {[A|As],Ap ++ Asp,St1}
+% end, {[],[],St}, Kes).
+
+atomic_bin([#c_bitstr{anno=A,val=E0,size=S0,unit=U,type=T,flags=Fs}|Es0],
+ Sub, St0, B0) ->
+ {E,Ap1,St1} = atomic_lit(E0, Sub, St0),
+ {S1,Ap2,St2} = atomic_lit(S0, Sub, St1),
+ validate_bin_element_size(S1),
+ U0 = core_lib:literal_value(U),
+ Fs0 = core_lib:literal_value(Fs),
+ {B1,Fs1} = aligned(B0, S1, U0, Fs0),
+ {Es,Ap3,St3} = atomic_bin(Es0, Sub, St2, B1),
+ {#k_bin_seg{anno=A,size=S1,
+ unit=U0,
+ type=core_lib:literal_value(T),
+ flags=Fs1,
+ seg=E,next=Es},
+ Ap1++Ap2++Ap3,St3};
+atomic_bin([], _Sub, St, _Bits) -> {#k_bin_end{},[],St}.
+
+validate_bin_element_size(#k_var{}) -> ok;
+validate_bin_element_size(#k_int{val=V}) when V >= 0 -> ok;
+validate_bin_element_size(#k_atom{val=all}) -> ok;
+validate_bin_element_size(_) -> throw(bad_element_size).
+
+%% atomic_list([Cexpr], Sub, State) -> {[Kexpr],[PreKexpr],State}.
+
+atomic_list(Ces, Sub, St) ->
+ foldr(fun (Ce, {Kes,Esp,St0}) ->
+ {Ke,Ep,St1} = atomic_lit(Ce, Sub, St0),
+ {[Ke|Kes],Ep ++ Esp,St1}
+ end, {[],[],St}, Ces).
+
+%% is_atomic(Kexpr) -> boolean().
+%% Is a Kexpr atomic? Strings are NOT considered atomic!
+
+is_atomic(#k_int{}) -> true;
+is_atomic(#k_float{}) -> true;
+is_atomic(#k_atom{}) -> true;
+%%is_atomic(#k_char{}) -> true; %No characters
+%%is_atomic(#k_string{}) -> true;
+is_atomic(#k_nil{}) -> true;
+is_atomic(#k_var{}) -> true;
+is_atomic(_) -> false.
+
+%% variable(Cexpr, Sub, State) -> {Kvar,[PreKexpr],State}.
+%% Convert a Core expression making sure the result is a variable.
+
+variable(Ce, Sub, St0) ->
+ {Ke,Kp,St1} = expr(Ce, Sub, St0),
+ {Kv,Vp,St2} = force_variable(Ke, St1),
+ {Kv,Kp ++ Vp,St2}.
+
+force_variable(#k_var{}=Ke, St) -> {Ke,[],St};
+force_variable(Ke, St0) ->
+ {V,St1} = new_var(St0),
+ {V,[#iset{vars=[V],arg=Ke}],St1}.
+
+%% pattern(Cpat, Sub, State) -> {Kpat,Sub,State}.
+%% Convert patterns. Variables shadow so rename variables that are
+%% already defined.
+
+pattern(#c_var{anno=A,name=V}, Sub, St0) ->
+ case sets:is_element(V, St0#kern.ds) of
+ true ->
+ {New,St1} = new_var_name(St0),
+ {#k_var{anno=A,name=New},
+ set_vsub(V, New, Sub),
+ St1#kern{ds=sets:add_element(New, St1#kern.ds)}};
+ false ->
+ {#k_var{anno=A,name=V},Sub,
+ St0#kern{ds=sets:add_element(V, St0#kern.ds)}}
+ end;
+pattern(#c_char{anno=A,val=C}, Sub, St) ->
+ {#k_int{anno=A,val=C},Sub,St}; %Convert to integers!
+pattern(#c_int{anno=A,val=I}, Sub, St) ->
+ {#k_int{anno=A,val=I},Sub,St};
+pattern(#c_float{anno=A,val=F}, Sub, St) ->
+ {#k_float{anno=A,val=F},Sub,St};
+pattern(#c_atom{anno=A,val=At}, Sub, St) ->
+ {#k_atom{anno=A,val=At},Sub,St};
+pattern(#c_string{val=S}, Sub, St) ->
+ L = foldr(fun (C, T) -> #k_cons{hd=#k_int{val=C},tl=T} end,
+ #k_nil{}, S),
+ {L,Sub,St};
+pattern(#c_nil{anno=A}, Sub, St) ->
+ {#k_nil{anno=A},Sub,St};
+pattern(#c_cons{anno=A,hd=Ch,tl=Ct}, Sub0, St0) ->
+ {Kh,Sub1,St1} = pattern(Ch, Sub0, St0),
+ {Kt,Sub2,St2} = pattern(Ct, Sub1, St1),
+ {#k_cons{anno=A,hd=Kh,tl=Kt},Sub2,St2};
+pattern(#c_tuple{anno=A,es=Ces}, Sub0, St0) ->
+ {Kes,Sub1,St1} = pattern_list(Ces, Sub0, St0),
+ {#k_tuple{anno=A,es=Kes},Sub1,St1};
+pattern(#c_binary{anno=A,segments=Cv}, Sub0, St0) ->
+ {Kv,Sub1,St1} = pattern_bin(Cv, Sub0, St0),
+ {#k_binary{anno=A,segs=Kv},Sub1,St1};
+pattern(#c_alias{anno=A,var=Cv,pat=Cp}, Sub0, St0) ->
+ {Cvs,Cpat} = flatten_alias(Cp),
+ {Kvs,Sub1,St1} = pattern_list([Cv|Cvs], Sub0, St0),
+ {Kpat,Sub2,St2} = pattern(Cpat, Sub1, St1),
+ {#ialias{anno=A,vars=Kvs,pat=Kpat},Sub2,St2}.
+
+flatten_alias(#c_alias{var=V,pat=P}) ->
+ {Vs,Pat} = flatten_alias(P),
+ {[V|Vs],Pat};
+flatten_alias(Pat) -> {[],Pat}.
+
+pattern_bin(Es, Sub, St) -> pattern_bin(Es, Sub, St, 0).
+
+pattern_bin([#c_bitstr{anno=A,val=E0,size=S0,unit=U,type=T,flags=Fs}|Es0],
+ Sub0, St0, B0) ->
+ {S1,[],St1} = expr(S0, Sub0, St0),
+ U0 = core_lib:literal_value(U),
+ Fs0 = core_lib:literal_value(Fs),
+ %%ok= io:fwrite("~w: ~p~n", [?LINE,{B0,S1,U0,Fs0}]),
+ {B1,Fs1} = aligned(B0, S1, U0, Fs0),
+ {E,Sub1,St2} = pattern(E0, Sub0, St1),
+ {Es,Sub2,St3} = pattern_bin(Es0, Sub1, St2, B1),
+ {#k_bin_seg{anno=A,size=S1,
+ unit=U0,
+ type=core_lib:literal_value(T),
+ flags=Fs1,
+ seg=E,next=Es},
+ Sub2,St3};
+pattern_bin([], Sub, St, _Bits) -> {#k_bin_end{},Sub,St}.
+
+%% pattern_list([Cexpr], Sub, State) -> {[Kexpr],Sub,State}.
+
+pattern_list(Ces, Sub, St) ->
+ foldr(fun (Ce, {Kes,Sub0,St0}) ->
+ {Ke,Sub1,St1} = pattern(Ce, Sub0, St0),
+ {[Ke|Kes],Sub1,St1}
+ end, {[],Sub,St}, Ces).
+
+%% new_sub() -> Subs.
+%% set_vsub(Name, Sub, Subs) -> Subs.
+%% subst_vsub(Name, Sub, Subs) -> Subs.
+%% get_vsub(Name, Subs) -> SubName.
+%% Add/get substitute Sub for Name to VarSub. Use orddict so we know
+%% the format is a list {Name,Sub} pairs. When adding a new
+%% substitute we fold substitute chains so we never have to search
+%% more than once.
+
+new_sub() -> orddict:new().
+
+get_vsub(V, Vsub) ->
+ case orddict:find(V, Vsub) of
+ {ok,Val} -> Val;
+ error -> V
+ end.
+
+set_vsub(V, S, Vsub) ->
+ orddict:store(V, S, Vsub).
+
+subst_vsub(V, S, Vsub0) ->
+ %% Fold chained substitutions.
+ Vsub1 = orddict:map(fun (_, V1) when V1 =:= V -> S;
+ (_, V1) -> V1
+ end, Vsub0),
+ orddict:store(V, S, Vsub1).
+
+get_fsub(F, A, Fsub) ->
+ case orddict:find({F,A}, Fsub) of
+ {ok,Val} -> Val;
+ error -> F
+ end.
+
+set_fsub(F, A, S, Fsub) ->
+ orddict:store({F,A}, S, Fsub).
+
+new_fun_name(St) ->
+ new_fun_name("anonymous", St).
+
+%% new_fun_name(Type, State) -> {FunName,State}.
+
+new_fun_name(Type, #kern{func={F,Arity},fcount=C}=St) ->
+ Name = "-" ++ atom_to_list(F) ++ "/" ++ integer_to_list(Arity) ++
+ "-" ++ Type ++ "-" ++ integer_to_list(C) ++ "-",
+ {list_to_atom(Name),St#kern{fcount=C+1}}.
+
+%% new_var_name(State) -> {VarName,State}.
+
+new_var_name(#kern{vcount=C}=St) ->
+ {list_to_atom("ker" ++ integer_to_list(C)),St#kern{vcount=C+1}}.
+
+%% new_var(State) -> {#k_var{},State}.
+
+new_var(St0) ->
+ {New,St1} = new_var_name(St0),
+ {#k_var{name=New},St1}.
+
+%% new_vars(Count, State) -> {[#k_var{}],State}.
+%% Make Count new variables.
+
+new_vars(N, St) -> new_vars(N, St, []).
+
+new_vars(N, St0, Vs) when N > 0 ->
+ {V,St1} = new_var(St0),
+ new_vars(N-1, St1, [V|Vs]);
+new_vars(0, St, Vs) -> {Vs,St}.
+
+make_vars(Vs) -> [ #k_var{name=V} || V <- Vs ].
+
+add_var_def(V, St) ->
+ St#kern{ds=sets:add_element(V#k_var.name, St#kern.ds)}.
+
+%%add_vars_def(Vs, St) ->
+%% Ds = foldl(fun (#k_var{name=V}, Ds) -> add_element(V, Ds) end,
+%% St#kern.ds, Vs),
+%% St#kern{ds=Ds}.
+
+%% is_remote_bif(Mod, Name, Arity) -> true | false.
+%% Test if function is really a BIF.
+
+is_remote_bif(erlang, is_boolean, 1) ->
+ %% XXX Remove this clause in R11. For bootstrap purposes, we must
+ %% recognize erlang:is_boolean/1 here.
+ true;
+is_remote_bif(erlang, internal_is_record, 3) -> true;
+is_remote_bif(erlang, get, 1) -> true;
+is_remote_bif(erlang, N, A) ->
+ case erl_internal:guard_bif(N, A) of
+ true -> true;
+ false ->
+ case erl_internal:type_test(N, A) of
+ true -> true;
+ false ->
+ case catch erl_internal:op_type(N, A) of
+ arith -> true;
+ bool -> true;
+ comp -> true;
+ _Other -> false %List, send or not an op
+ end
+ end
+ end;
+is_remote_bif(_, _, _) -> false.
+
+%% bif_vals(Name, Arity) -> integer().
+%% bif_vals(Mod, Name, Arity) -> integer().
+%% Determine how many return values a BIF has. Provision for BIFs to
+%% return multiple values. Only used in bodies where a BIF may be
+%% called for effect only.
+
+bif_vals(dsetelement, 3) -> 0;
+bif_vals(_, _) -> 1.
+
+bif_vals(_, _, _) -> 1.
+
+%% foldr2(Fun, Acc, List1, List2) -> Acc.
+%% Fold over two lists.
+
+foldr2(Fun, Acc0, [E1|L1], [E2|L2]) ->
+ Acc1 = Fun(E1, E2, Acc0),
+ foldr2(Fun, Acc1, L1, L2);
+foldr2(_, Acc, [], []) -> Acc.
+
+%% first([A]) -> [A].
+%% last([A]) -> A.
+
+last([L]) -> L;
+last([_|T]) -> last(T).
+
+first([_]) -> [];
+first([H|T]) -> [H|first(T)].
+
+%% This code implements the algorithm for an optimizing compiler for
+%% pattern matching given "The Implementation of Functional
+%% Programming Languages" by Simon Peyton Jones. The code is much
+%% longer as the meaning of constructors is different from the book.
+%%
+%% In Erlang many constructors can have different values, e.g. 'atom'
+%% or 'integer', whereas in the original algorithm thse would be
+%% different constructors. Our view makes it easier in later passes to
+%% handle indexing over each type.
+%%
+%% Patterns are complicated by having alias variables. The form of a
+%% pattern is Pat | {alias,Pat,[AliasVar]}. This is hidden by access
+%% functions to pattern arguments but the code must be aware of it.
+%%
+%% The compilation proceeds in two steps:
+%%
+%% 1. The patterns in the clauses to converted to lists of kernel
+%% patterns. The Core clause is now hybrid, this is easier to work
+%% with. Remove clauses with trivially false guards, this simplifies
+%% later passes. Add local defined vars and variable subs to each
+%% clause for later use.
+%%
+%% 2. The pattern matching is optimised. Variable substitutions are
+%% added to the VarSub structure and new variables are made visible.
+%% The guard and body are then converted to Kernel form.
+
+%% kmatch([Var], [Clause], Sub, State) -> {Kexpr,[PreExpr],State}.
+
+kmatch(Us, Ccs, Sub, St0) ->
+ {Cs,St1} = match_pre(Ccs, Sub, St0), %Convert clauses
+ %%Def = kernel_match_error, %The strict case
+ %% This should be a kernel expression from the first pass.
+ Def = #k_call{anno=[compiler_generated],
+ op=#k_remote{mod=#k_atom{val=erlang},
+ name=#k_atom{val=exit},
+ arity=1},
+ args=[#k_atom{val=kernel_match_error}]},
+ {Km,St2} = match(Us, Cs, Def, St1), %Do the match.
+ {Km,St2}.
+
+%% match_pre([Cclause], Sub, State) -> {[Clause],State}.
+%% Must be careful not to generate new substitutions here now!
+%% Remove clauses with trivially false guards which will never
+%% succeed.
+
+match_pre(Cs, Sub0, St) ->
+ foldr(fun (#c_clause{anno=A,pats=Ps,guard=G,body=B}, {Cs0,St0}) ->
+ case is_false_guard(G) of
+ true -> {Cs0,St0};
+ false ->
+ {Kps,Sub1,St1} = pattern_list(Ps, Sub0, St0),
+ {[#iclause{anno=A,sub=Sub1,pats=Kps,guard=G,body=B}|
+ Cs0],St1}
+ end
+ end, {[],St}, Cs).
+
+%% match([Var], [Clause], Default, State) -> {MatchExpr,State}.
+
+match([U|Us], Cs, Def, St0) ->
+ %%ok = io:format("match ~p~n", [Cs]),
+ Pcss = partition(Cs),
+ foldr(fun (Pcs, {D,St}) -> match_varcon([U|Us], Pcs, D, St) end,
+ {Def,St0}, Pcss);
+match([], Cs, Def, St) ->
+ match_guard(Cs, Def, St).
+
+%% match_guard([Clause], Default, State) -> {IfExpr,State}.
+%% Build a guard to handle guards. A guard *ALWAYS* fails if no
+%% clause matches, there will be a surrounding 'alt' to catch the
+%% failure. Drop redundant cases, i.e. those after a true guard.
+
+match_guard(Cs0, Def0, St0) ->
+ {Cs1,Def1,St1} = match_guard_1(Cs0, Def0, St0),
+ {build_alt(build_guard(Cs1), Def1),St1}.
+
+match_guard_1([#iclause{anno=A,sub=Sub,guard=G,body=B}|Cs0], Def0, St0) ->
+ case is_true_guard(G) of
+ true ->
+ %% The true clause body becomes the default.
+ {Kb,Pb,St1} = body(B, Sub, St0),
+ Line = get_line(A),
+ St2 = maybe_add_warning(Cs0, Line, St1),
+ St = maybe_add_warning(Def0, Line, St2),
+ {[],pre_seq(Pb, Kb),St};
+ false ->
+ {Kg,St1} = guard(G, Sub, St0),
+ {Kb,Pb,St2} = body(B, Sub, St1),
+ {Cs1,Def1,St3} = match_guard_1(Cs0, Def0, St2),
+ {[#k_guard_clause{guard=Kg,body=pre_seq(Pb, Kb)}|Cs1],
+ Def1,St3}
+ end;
+match_guard_1([], Def, St) -> {[],Def,St}.
+
+maybe_add_warning([C|_], Line, St) ->
+ maybe_add_warning(C, Line, St);
+maybe_add_warning([], _Line, St) -> St;
+maybe_add_warning(fail, _Line, St) -> St;
+maybe_add_warning(Ke, MatchLine, St) ->
+ case get_kanno(Ke) of
+ [compiler_generated|_] -> St;
+ Anno ->
+ Line = get_line(Anno),
+ Warn = case MatchLine of
+ none -> nomatch_shadow;
+ _ -> {nomatch_shadow,MatchLine}
+ end,
+ add_warning(Line, Warn, St)
+ end.
+
+get_line([Line|_]) when is_integer(Line) -> Line;
+get_line([_|T]) -> get_line(T);
+get_line([]) -> none.
+
+
+%% is_true_guard(Guard) -> boolean().
+%% is_false_guard(Guard) -> boolean().
+%% Test if a guard is either trivially true/false. This has probably
+%% already been optimised away, but what the heck!
+
+is_true_guard(G) -> guard_value(G) == true.
+is_false_guard(G) -> guard_value(G) == false.
+
+%% guard_value(Guard) -> true | false | unknown.
+
+guard_value(#c_atom{val=true}) -> true;
+guard_value(#c_atom{val=false}) -> false;
+guard_value(#c_call{module=#c_atom{val=erlang},
+ name=#c_atom{val='not'},
+ args=[A]}) ->
+ case guard_value(A) of
+ true -> false;
+ false -> true;
+ unknown -> unknown
+ end;
+guard_value(#c_call{module=#c_atom{val=erlang},
+ name=#c_atom{val='and'},
+ args=[Ca,Cb]}) ->
+ case guard_value(Ca) of
+ true -> guard_value(Cb);
+ false -> false;
+ unknown ->
+ case guard_value(Cb) of
+ false -> false;
+ _Other -> unknown
+ end
+ end;
+guard_value(#c_call{module=#c_atom{val=erlang},
+ name=#c_atom{val='or'},
+ args=[Ca,Cb]}) ->
+ case guard_value(Ca) of
+ true -> true;
+ false -> guard_value(Cb);
+ unknown ->
+ case guard_value(Cb) of
+ true -> true;
+ _Other -> unknown
+ end
+ end;
+guard_value(#c_try{arg=E,vars=[#c_var{name=X}],body=#c_var{name=X},
+ handler=#c_atom{val=false}}) ->
+ guard_value(E);
+guard_value(_) -> unknown.
+
+%% partition([Clause]) -> [[Clause]].
+%% Partition a list of clauses into groups which either contain
+%% clauses with a variable first argument, or with a "constructor".
+
+partition([C1|Cs]) ->
+ V1 = is_var_clause(C1),
+ {More,Rest} = splitwith(fun (C) -> is_var_clause(C) == V1 end, Cs),
+ [[C1|More]|partition(Rest)];
+partition([]) -> [].
+
+%% match_varcon([Var], [Clause], Def, [Var], Sub, State) ->
+%% {MatchExpr,State}.
+
+match_varcon(Us, [C|_]=Cs, Def, St) ->
+ case is_var_clause(C) of
+ true -> match_var(Us, Cs, Def, St);
+ false -> match_con(Us, Cs, Def, St)
+ end.
+
+%% match_var([Var], [Clause], Def, State) -> {MatchExpr,State}.
+%% Build a call to "select" from a list of clauses all containing a
+%% variable as the first argument. We must rename the variable in
+%% each clause to be the match variable as these clause will share
+%% this variable and may have different names for it. Rename aliases
+%% as well.
+
+match_var([U|Us], Cs0, Def, St) ->
+ Cs1 = map(fun (#iclause{sub=Sub0,pats=[Arg|As]}=C) ->
+ Vs = [arg_arg(Arg)|arg_alias(Arg)],
+ Sub1 = foldl(fun (#k_var{name=V}, Acc) ->
+ subst_vsub(V, U#k_var.name, Acc)
+ end, Sub0, Vs),
+ C#iclause{sub=Sub1,pats=As}
+ end, Cs0),
+ match(Us, Cs1, Def, St).
+
+%% match_con(Variables, [Clause], Default, State) -> {SelectExpr,State}.
+%% Build call to "select" from a list of clauses all containing a
+%% constructor/constant as first argument. Group the constructors
+%% according to type, the order is really irrelevant but tries to be
+%% smart.
+
+match_con([U|Us], Cs, Def, St0) ->
+ %% Extract clauses for different constructors (types).
+ %%ok = io:format("match_con ~p~n", [Cs]),
+ Ttcs = [ {T,Tcs} || T <- [k_cons,k_tuple,k_atom,k_float,k_int,k_nil,
+ k_binary,k_bin_end],
+ begin Tcs = select(T, Cs),
+ Tcs /= []
+ end ] ++ select_bin_con(Cs),
+ %%ok = io:format("ttcs = ~p~n", [Ttcs]),
+ {Scs,St1} =
+ mapfoldl(fun ({T,Tcs}, St) ->
+ {[S|_]=Sc,S1} = match_value([U|Us], T, Tcs, fail, St),
+ %%ok = io:format("match_con type2 ~p~n", [T]),
+ Anno = get_kanno(S),
+ {#k_type_clause{anno=Anno,type=T,values=Sc},S1} end,
+ St0, Ttcs),
+ {build_alt_1st_no_fail(build_select(U, Scs), Def),St1}.
+
+%% select_bin_con([Clause]) -> [{Type,[Clause]}].
+%% Extract clauses for the k_bin_seg constructor. As k_bin_seg
+%% matching can overlap, the k_bin_seg constructors cannot be
+%% reordered, only grouped.
+
+select_bin_con(Cs0) ->
+ Cs1 = lists:filter(fun (C) ->
+ clause_con(C) == k_bin_seg
+ end, Cs0),
+ select_bin_con_1(Cs1).
+
+select_bin_con_1([C1|Cs]) ->
+ Con = clause_con(C1),
+ {More,Rest} = splitwith(fun (C) -> clause_con(C) == Con end, Cs),
+ [{Con,[C1|More]}|select_bin_con_1(Rest)];
+select_bin_con_1([]) -> [].
+
+%% select(Con, [Clause]) -> [Clause].
+
+select(T, Cs) -> [ C || C <- Cs, clause_con(C) == T ].
+
+%% match_value([Var], Con, [Clause], Default, State) -> {SelectExpr,State}.
+%% At this point all the clauses have the same constructor, we must
+%% now separate them according to value.
+
+match_value(_, _, [], _, St) -> {[],St};
+match_value(Us, T, Cs0, Def, St0) ->
+ Css = group_value(T, Cs0),
+ %%ok = io:format("match_value ~p ~p~n", [T, Css]),
+ {Css1,St1} = mapfoldl(fun (Cs, St) ->
+ match_clause(Us, Cs, Def, St) end,
+ St0, Css),
+ {Css1,St1}.
+ %%{#k_select_val{type=T,var=hd(Us),clauses=Css1},St1}.
+
+%% group_value([Clause]) -> [[Clause]].
+%% Group clauses according to value. Here we know that
+%% 1. Some types are singled valued
+%% 2. The clauses in bin_segs cannot be reordered only grouped
+%% 3. Other types are disjoint and can be reordered
+
+group_value(k_cons, Cs) -> [Cs]; %These are single valued
+group_value(k_nil, Cs) -> [Cs];
+group_value(k_binary, Cs) -> [Cs];
+group_value(k_bin_end, Cs) -> [Cs];
+group_value(k_bin_seg, Cs) ->
+ group_bin_seg(Cs);
+group_value(_, Cs) ->
+ %% group_value(Cs).
+ Cd = foldl(fun (C, Gcs0) -> dict:append(clause_val(C), C, Gcs0) end,
+ dict:new(), Cs),
+ dict:fold(fun (_, Vcs, Css) -> [Vcs|Css] end, [], Cd).
+
+group_bin_seg([C1|Cs]) ->
+ V1 = clause_val(C1),
+ {More,Rest} = splitwith(fun (C) -> clause_val(C) == V1 end, Cs),
+ [[C1|More]|group_bin_seg(Rest)];
+group_bin_seg([]) -> [].
+
+%% Profiling shows that this quadratic implementation account for a big amount
+%% of the execution time if there are many values.
+% group_value([C|Cs]) ->
+% V = clause_val(C),
+% Same = [ Cv || Cv <- Cs, clause_val(Cv) == V ], %Same value
+% Rest = [ Cv || Cv <- Cs, clause_val(Cv) /= V ], % and all the rest
+% [[C|Same]|group_value(Rest)];
+% group_value([]) -> [].
+
+%% match_clause([Var], [Clause], Default, State) -> {Clause,State}.
+%% At this point all the clauses have the same "value". Build one
+%% select clause for this value and continue matching. Rename
+%% aliases as well.
+
+match_clause([U|Us], [C|_]=Cs0, Def, St0) ->
+ Anno = get_kanno(C),
+ {Match0,Vs,St1} = get_match(get_con(Cs0), St0),
+ Match = sub_size_var(Match0, Cs0),
+ {Cs1,St2} = new_clauses(Cs0, U, St1),
+ {B,St3} = match(Vs ++ Us, Cs1, Def, St2),
+ {#k_val_clause{anno=Anno,val=Match,body=B},St3}.
+
+sub_size_var(#k_bin_seg{size=#k_var{name=Name}=Kvar}=BinSeg, [#iclause{sub=Sub}|_]) ->
+ BinSeg#k_bin_seg{size=Kvar#k_var{name=get_vsub(Name, Sub)}};
+sub_size_var(K, _) -> K.
+
+get_con([C|_]) -> arg_arg(clause_arg(C)). %Get the constructor
+
+get_match(#k_cons{}, St0) ->
+ {[H,T],St1} = new_vars(2, St0),
+ {#k_cons{hd=H,tl=T},[H,T],St1};
+get_match(#k_binary{}, St0) ->
+ {[V]=Mes,St1} = new_vars(1, St0),
+ {#k_binary{segs=V},Mes,St1};
+get_match(#k_bin_seg{}=Seg, St0) ->
+ {[S,N]=Mes,St1} = new_vars(2, St0),
+ {Seg#k_bin_seg{seg=S,next=N},Mes,St1};
+get_match(#k_tuple{es=Es}, St0) ->
+ {Mes,St1} = new_vars(length(Es), St0),
+ {#k_tuple{es=Mes},Mes,St1};
+get_match(M, St) ->
+ {M,[],St}.
+
+new_clauses(Cs0, U, St) ->
+ Cs1 = map(fun (#iclause{sub=Sub0,pats=[Arg|As]}=C) ->
+ Head = case arg_arg(Arg) of
+ #k_cons{hd=H,tl=T} -> [H,T|As];
+ #k_tuple{es=Es} -> Es ++ As;
+ #k_binary{segs=E} -> [E|As];
+ #k_bin_seg{seg=S,next=N} ->
+ [S,N|As];
+ _Other -> As
+ end,
+ Vs = arg_alias(Arg),
+ Sub1 = foldl(fun (#k_var{name=V}, Acc) ->
+ subst_vsub(V, U#k_var.name, Acc)
+ end, Sub0, Vs),
+ C#iclause{sub=Sub1,pats=Head}
+ end, Cs0),
+ {Cs1,St}.
+
+%% build_guard([GuardClause]) -> GuardExpr.
+
+build_guard([]) -> fail;
+build_guard(Cs) -> #k_guard{clauses=Cs}.
+
+%% build_select(Var, [ConClause]) -> SelectExpr.
+
+build_select(V, [Tc|_]=Tcs) ->
+ Anno = get_kanno(Tc),
+ #k_select{anno=Anno,var=V,types=Tcs}.
+
+%% build_alt(First, Then) -> AltExpr.
+%% Build an alt, attempt some simple optimisation.
+
+build_alt(fail, Then) -> Then;
+build_alt(First,Then) -> build_alt_1st_no_fail(First, Then).
+
+build_alt_1st_no_fail(First, fail) -> First;
+build_alt_1st_no_fail(First, Then) -> #k_alt{first=First,then=Then}.
+
+%% build_match([MatchVar], MatchExpr) -> Kexpr.
+%% Build a match expr if there is a match.
+
+build_match(Us, #k_alt{}=Km) -> #k_match{vars=Us,body=Km};
+build_match(Us, #k_select{}=Km) -> #k_match{vars=Us,body=Km};
+build_match(Us, #k_guard{}=Km) -> #k_match{vars=Us,body=Km};
+build_match(_, Km) -> Km.
+
+%% clause_arg(Clause) -> FirstArg.
+%% clause_con(Clause) -> Constructor.
+%% clause_val(Clause) -> Value.
+%% is_var_clause(Clause) -> boolean().
+
+clause_arg(#iclause{pats=[Arg|_]}) -> Arg.
+
+clause_con(C) -> arg_con(clause_arg(C)).
+
+clause_val(C) -> arg_val(clause_arg(C)).
+
+is_var_clause(C) -> clause_con(C) == k_var.
+
+%% arg_arg(Arg) -> Arg.
+%% arg_alias(Arg) -> Aliases.
+%% arg_con(Arg) -> Constructor.
+%% arg_val(Arg) -> Value.
+%% These are the basic functions for obtaining fields in an argument.
+
+arg_arg(#ialias{pat=Con}) -> Con;
+arg_arg(Con) -> Con.
+
+arg_alias(#ialias{vars=As}) -> As;
+arg_alias(_Con) -> [].
+
+arg_con(Arg) ->
+ case arg_arg(Arg) of
+ #k_int{} -> k_int;
+ #k_float{} -> k_float;
+ #k_atom{} -> k_atom;
+ #k_nil{} -> k_nil;
+ #k_cons{} -> k_cons;
+ #k_tuple{} -> k_tuple;
+ #k_binary{} -> k_binary;
+ #k_bin_end{} -> k_bin_end;
+ #k_bin_seg{} -> k_bin_seg;
+ #k_var{} -> k_var
+ end.
+
+arg_val(Arg) ->
+ case arg_arg(Arg) of
+ #k_int{val=I} -> I;
+ #k_float{val=F} -> F;
+ #k_atom{val=A} -> A;
+ #k_nil{} -> 0;
+ #k_cons{} -> 2;
+ #k_tuple{es=Es} -> length(Es);
+ #k_bin_seg{size=S,unit=U,type=T,flags=Fs} ->
+ {set_kanno(S, []),U,T,Fs};
+ #k_bin_end{} -> 0;
+ #k_binary{} -> 0
+ end.
+
+%% ubody(Expr, Break, State) -> {Expr,[UsedVar],State}.
+%% Tag the body sequence with its used variables. These bodies
+%% either end with a #k_break{}, or with #k_return{} or an expression
+%% which itself can return, #k_enter{}, #k_match{} ... .
+
+ubody(#iset{vars=[],arg=#iletrec{}=Let,body=B0}, Br, St0) ->
+ %% An iletrec{} should never be last.
+ St1 = iletrec_funs(Let, St0),
+ ubody(B0, Br, St1);
+ubody(#iset{anno=A,vars=Vs,arg=E0,body=B0}, Br, St0) ->
+ {E1,Eu,St1} = uexpr(E0, {break,Vs}, St0),
+ {B1,Bu,St2} = ubody(B0, Br, St1),
+ Ns = lit_list_vars(Vs),
+ Used = union(Eu, subtract(Bu, Ns)), %Used external vars
+ {#k_seq{anno=#k{us=Used,ns=Ns,a=A},arg=E1,body=B1},Used,St2};
+ubody(#ivalues{anno=A,args=As}, return, St) ->
+ Au = lit_list_vars(As),
+ {#k_return{anno=#k{us=Au,ns=[],a=A},args=As},Au,St};
+ubody(#ivalues{anno=A,args=As}, {break,_Vbs}, St) ->
+ Au = lit_list_vars(As),
+ {#k_break{anno=#k{us=Au,ns=[],a=A},args=As},Au,St};
+ubody(E, return, St0) ->
+ %% Enterable expressions need no trailing return.
+ case is_enter_expr(E) of
+ true -> uexpr(E, return, St0);
+ false ->
+ {Ea,Pa,St1} = force_atomic(E, St0),
+ ubody(pre_seq(Pa, #ivalues{args=[Ea]}), return, St1)
+ end;
+ubody(E, {break,Rs}, St0) ->
+ %%ok = io:fwrite("ubody ~w:~p~n", [?LINE,{E,Br}]),
+ %% Exiting expressions need no trailing break.
+ case is_exit_expr(E) of
+ true -> uexpr(E, return, St0);
+ false ->
+ {Ea,Pa,St1} = force_atomic(E, St0),
+ ubody(pre_seq(Pa, #ivalues{args=[Ea]}), {break,Rs}, St1)
+ end.
+
+iletrec_funs(#iletrec{defs=Fs}, St0) ->
+ %% Use union of all free variables.
+ %% First just work out free variables for all functions.
+ Free = foldl(fun ({_,#ifun{vars=Vs,body=Fb0}}, Free0) ->
+ {_,Fbu,_} = ubody(Fb0, return, St0),
+ Ns = lit_list_vars(Vs),
+ Free1 = subtract(Fbu, Ns),
+ union(Free1, Free0)
+ end, [], Fs),
+ FreeVs = make_vars(Free),
+ %% Add this free info to State.
+ St1 = foldl(fun ({N,#ifun{vars=Vs}}, Lst) ->
+ store_free(N, length(Vs), FreeVs, Lst)
+ end, St0, Fs),
+ %% Now regenerate local functions to use free variable information.
+ St2 = foldl(fun ({N,#ifun{anno=Fa,vars=Vs,body=Fb0}}, Lst0) ->
+ {Fb1,_,Lst1} = ubody(Fb0, return, Lst0),
+ Arity = length(Vs) + length(FreeVs),
+ Fun = #k_fdef{anno=#k{us=[],ns=[],a=Fa},
+ func=N,arity=Arity,
+ vars=Vs ++ FreeVs,body=Fb1},
+ Lst1#kern{funs=[Fun|Lst1#kern.funs]}
+ end, St1, Fs),
+ St2.
+
+%% is_exit_expr(Kexpr) -> boolean().
+%% Test whether Kexpr always exits and never returns.
+
+is_exit_expr(#k_call{op=#k_remote{mod=erlang,name=throw,arity=1}}) -> true;
+is_exit_expr(#k_call{op=#k_remote{mod=erlang,name=exit,arity=1}}) -> true;
+is_exit_expr(#k_call{op=#k_remote{mod=erlang,name=error,arity=1}}) -> true;
+is_exit_expr(#k_call{op=#k_remote{mod=erlang,name=error,arity=2}}) -> true;
+is_exit_expr(#k_call{op=#k_remote{mod=erlang,name=fault,arity=1}}) -> true;
+is_exit_expr(#k_call{op=#k_remote{mod=erlang,name=fault,arity=2}}) -> true;
+is_exit_expr(#k_call{op=#k_internal{name=match_fail,arity=1}}) -> true;
+is_exit_expr(#k_bif{op=#k_internal{name=rethrow,arity=2}}) -> true;
+is_exit_expr(#k_receive_next{}) -> true;
+is_exit_expr(_) -> false.
+
+%% is_enter_expr(Kexpr) -> boolean().
+%% Test whether Kexpr is "enterable", i.e. can handle return from
+%% within itself without extra #k_return{}.
+
+is_enter_expr(#k_call{}) -> true;
+is_enter_expr(#k_match{}) -> true;
+is_enter_expr(#k_receive{}) -> true;
+is_enter_expr(#k_receive_next{}) -> true;
+%%is_enter_expr(#k_try{}) -> true; %Soon
+is_enter_expr(_) -> false.
+
+%% uguard(Expr, State) -> {Expr,[UsedVar],State}.
+%% Tag the guard sequence with its used variables.
+
+uguard(#k_try{anno=A,arg=B0,vars=[#k_var{name=X}],body=#k_var{name=X},
+ handler=#k_atom{val=false}}=Try, St0) ->
+ {B1,Bu,St1} = uguard(B0, St0),
+ {Try#k_try{anno=#k{us=Bu,ns=[],a=A},arg=B1},Bu,St1};
+uguard(T, St) ->
+ %%ok = io:fwrite("~w: ~p~n", [?LINE,T]),
+ uguard_test(T, St).
+
+%% uguard_test(Expr, State) -> {Test,[UsedVar],State}.
+%% At this stage tests are just expressions which don't return any
+%% values.
+
+uguard_test(T, St) -> uguard_expr(T, [], St).
+
+uguard_expr(#iset{anno=A,vars=Vs,arg=E0,body=B0}, Rs, St0) ->
+ Ns = lit_list_vars(Vs),
+ {E1,Eu,St1} = uguard_expr(E0, Vs, St0),
+ {B1,Bu,St2} = uguard_expr(B0, Rs, St1),
+ Used = union(Eu, subtract(Bu, Ns)),
+ {#k_seq{anno=#k{us=Used,ns=Ns,a=A},arg=E1,body=B1},Used,St2};
+uguard_expr(#k_try{anno=A,arg=B0,vars=[#k_var{name=X}],body=#k_var{name=X},
+ handler=#k_atom{val=false}}=Try, Rs, St0) ->
+ {B1,Bu,St1} = uguard_expr(B0, Rs, St0),
+ {Try#k_try{anno=#k{us=Bu,ns=lit_list_vars(Rs),a=A},arg=B1,ret=Rs},
+ Bu,St1};
+uguard_expr(#k_test{anno=A,op=Op,args=As}=Test, Rs, St) ->
+ [] = Rs, %Sanity check
+ Used = union(op_vars(Op), lit_list_vars(As)),
+ {Test#k_test{anno=#k{us=Used,ns=lit_list_vars(Rs),a=A}},
+ Used,St};
+uguard_expr(#k_bif{anno=A,op=Op,args=As}=Bif, Rs, St) ->
+ Used = union(op_vars(Op), lit_list_vars(As)),
+ {Bif#k_bif{anno=#k{us=Used,ns=lit_list_vars(Rs),a=A},ret=Rs},
+ Used,St};
+uguard_expr(#ivalues{anno=A,args=As}, Rs, St) ->
+ Sets = foldr2(fun (V, Arg, Rhs) ->
+ #iset{anno=A,vars=[V],arg=Arg,body=Rhs}
+ end, #k_atom{val=true}, Rs, As),
+ uguard_expr(Sets, [], St);
+uguard_expr(#k_match{anno=A,vars=Vs,body=B0}, Rs, St0) ->
+ %% Experimental support for andalso/orelse in guards.
+ Br = case Rs of
+ [] -> return;
+ _ -> {break,Rs}
+ end,
+ {B1,Bu,St1} = umatch(B0, Br, St0),
+ {#k_match{anno=#k{us=Bu,ns=lit_list_vars(Rs),a=A},
+ vars=Vs,body=B1,ret=Rs},Bu,St1};
+uguard_expr(Lit, Rs, St) ->
+ %% Transform literals to puts here.
+ Used = lit_vars(Lit),
+ {#k_put{anno=#k{us=Used,ns=lit_list_vars(Rs),a=get_kanno(Lit)},
+ arg=Lit,ret=Rs},Used,St}.
+
+%% uexpr(Expr, Break, State) -> {Expr,[UsedVar],State}.
+%% Tag an expression with its used variables.
+%% Break = return | {break,[RetVar]}.
+
+uexpr(#k_call{anno=A,op=#k_local{name=F,arity=Ar}=Op,args=As0}=Call, Br, St) ->
+ Free = get_free(F, Ar, St),
+ As1 = As0 ++ Free, %Add free variables LAST!
+ Used = lit_list_vars(As1),
+ {case Br of
+ {break,Rs} ->
+ Call#k_call{anno=#k{us=Used,ns=lit_list_vars(Rs),a=A},
+ op=Op#k_local{arity=Ar + length(Free)},
+ args=As1,ret=Rs};
+ return ->
+ #k_enter{anno=#k{us=Used,ns=[],a=A},
+ op=Op#k_local{arity=Ar + length(Free)},
+ args=As1}
+ end,Used,St};
+uexpr(#k_call{anno=A,op=Op,args=As}=Call, {break,Rs}, St) ->
+ Used = union(op_vars(Op), lit_list_vars(As)),
+ {Call#k_call{anno=#k{us=Used,ns=lit_list_vars(Rs),a=A},ret=Rs},
+ Used,St};
+uexpr(#k_call{anno=A,op=Op,args=As}, return, St) ->
+ Used = union(op_vars(Op), lit_list_vars(As)),
+ {#k_enter{anno=#k{us=Used,ns=[],a=A},op=Op,args=As},
+ Used,St};
+uexpr(#k_bif{anno=A,op=Op,args=As}=Bif, {break,Rs}, St0) ->
+ Used = union(op_vars(Op), lit_list_vars(As)),
+ {Brs,St1} = bif_returns(Op, Rs, St0),
+ {Bif#k_bif{anno=#k{us=Used,ns=lit_list_vars(Brs),a=A},ret=Brs},
+ Used,St1};
+uexpr(#k_match{anno=A,vars=Vs,body=B0}, Br, St0) ->
+ Rs = break_rets(Br),
+ {B1,Bu,St1} = umatch(B0, Br, St0),
+ {#k_match{anno=#k{us=Bu,ns=lit_list_vars(Rs),a=A},
+ vars=Vs,body=B1,ret=Rs},Bu,St1};
+uexpr(#k_receive{anno=A,var=V,body=B0,timeout=T,action=A0}, Br, St0) ->
+ Rs = break_rets(Br),
+ Tu = lit_vars(T), %Timeout is atomic
+ {B1,Bu,St1} = umatch(B0, Br, St0),
+ {A1,Au,St2} = ubody(A0, Br, St1),
+ Used = del_element(V#k_var.name, union(Bu, union(Tu, Au))),
+ {#k_receive{anno=#k{us=Used,ns=lit_list_vars(Rs),a=A},
+ var=V,body=B1,timeout=T,action=A1,ret=Rs},
+ Used,St2};
+uexpr(#k_receive_accept{anno=A}, _, St) ->
+ {#k_receive_accept{anno=#k{us=[],ns=[],a=A}},[],St};
+uexpr(#k_receive_next{anno=A}, _, St) ->
+ {#k_receive_next{anno=#k{us=[],ns=[],a=A}},[],St};
+uexpr(#k_try{anno=A,arg=A0,vars=Vs,body=B0,evars=Evs,handler=H0},
+ {break,Rs0}, St0) ->
+ {Avs,St1} = new_vars(length(Vs), St0), %Need dummy names here
+ {A1,Au,St2} = ubody(A0, {break,Avs}, St1), %Must break to clean up here!
+ {B1,Bu,St3} = ubody(B0, {break,Rs0}, St2),
+ {H1,Hu,St4} = ubody(H0, {break,Rs0}, St3),
+ %% Guarantee ONE return variable.
+ NumNew = if
+ Rs0 =:= [] -> 1;
+ true -> 0
+ end,
+ {Ns,St5} = new_vars(NumNew, St4),
+ Rs1 = Rs0 ++ Ns,
+ Used = union([Au,subtract(Bu, lit_list_vars(Vs)),
+ subtract(Hu, lit_list_vars(Evs))]),
+ {#k_try{anno=#k{us=Used,ns=lit_list_vars(Rs1),a=A},
+ arg=A1,vars=Vs,body=B1,evars=Evs,handler=H1,ret=Rs1},
+ Used,St5};
+uexpr(#k_catch{anno=A,body=B0}, {break,Rs0}, St0) ->
+ {Rb,St1} = new_var(St0),
+ {B1,Bu,St2} = ubody(B0, {break,[Rb]}, St1),
+ %% Guarantee ONE return variable.
+ {Ns,St3} = new_vars(1 - length(Rs0), St2),
+ Rs1 = Rs0 ++ Ns,
+ {#k_catch{anno=#k{us=Bu,ns=lit_list_vars(Rs1),a=A},body=B1,ret=Rs1},Bu,St3};
+uexpr(#ifun{anno=A,vars=Vs,body=B0}=IFun, {break,Rs}, St0) ->
+ {B1,Bu,St1} = ubody(B0, return, St0), %Return out of new function
+ Ns = lit_list_vars(Vs),
+ Free = subtract(Bu, Ns), %Free variables in fun
+ Fvs = make_vars(Free),
+ Arity = length(Vs) + length(Free),
+ {{Index,Uniq,Fname}, St3} =
+ case lists:keysearch(id, 1, A) of
+ {value,{id,Id}} ->
+ {Id, St1};
+ false ->
+ %% No id annotation. Must invent one.
+ I = St1#kern.fcount,
+ U = erlang:hash(IFun, (1 bsl 27)-1),
+ {N, St2} = new_fun_name(St1),
+ {{I,U,N}, St2}
+ end,
+ Fun = #k_fdef{anno=#k{us=[],ns=[],a=A},func=Fname,arity=Arity,
+ vars=Vs ++ Fvs,body=B1},
+ {#k_bif{anno=#k{us=Free,ns=lit_list_vars(Rs),a=A},
+ op=#k_internal{name=make_fun,arity=length(Free)+3},
+ args=[#k_atom{val=Fname},#k_int{val=Arity},
+ #k_int{val=Index},#k_int{val=Uniq}|Fvs],
+ ret=Rs},
+% {#k_call{anno=#k{us=Free,ns=lit_list_vars(Rs),a=A},
+% op=#k_internal{name=make_fun,arity=length(Free)+3},
+% args=[#k_atom{val=Fname},#k_int{val=Arity},
+% #k_int{val=Index},#k_int{val=Uniq}|Fvs],
+% ret=Rs},
+ Free,St3#kern{funs=[Fun|St3#kern.funs]}};
+uexpr(Lit, {break,Rs}, St) ->
+ %% Transform literals to puts here.
+ %%ok = io:fwrite("uexpr ~w:~p~n", [?LINE,Lit]),
+ Used = lit_vars(Lit),
+ {#k_put{anno=#k{us=Used,ns=lit_list_vars(Rs),a=get_kanno(Lit)},
+ arg=Lit,ret=Rs},Used,St}.
+
+%% get_free(Name, Arity, State) -> [Free].
+%% store_free(Name, Arity, [Free], State) -> State.
+
+get_free(F, A, St) ->
+ case orddict:find({F,A}, St#kern.free) of
+ {ok,Val} -> Val;
+ error -> []
+ end.
+
+store_free(F, A, Free, St) ->
+ St#kern{free=orddict:store({F,A}, Free, St#kern.free)}.
+
+break_rets({break,Rs}) -> Rs;
+break_rets(return) -> [].
+
+%% bif_returns(Op, [Ret], State) -> {[Ret],State}.
+
+bif_returns(#k_remote{mod=M,name=N,arity=Ar}, Rs, St0) ->
+ %%ok = io:fwrite("uexpr ~w:~p~n", [?LINE,{M,N,Ar,Rs}]),
+ {Ns,St1} = new_vars(bif_vals(M, N, Ar) - length(Rs), St0),
+ {Rs ++ Ns,St1};
+bif_returns(#k_internal{name=N,arity=Ar}, Rs, St0) ->
+ %%ok = io:fwrite("uexpr ~w:~p~n", [?LINE,{N,Ar,Rs}]),
+ {Ns,St1} = new_vars(bif_vals(N, Ar) - length(Rs), St0),
+ {Rs ++ Ns,St1}.
+
+%% umatch(Match, Break, State) -> {Match,[UsedVar],State}.
+%% Tag a match expression with its used variables.
+
+umatch(#k_alt{anno=A,first=F0,then=T0}, Br, St0) ->
+ {F1,Fu,St1} = umatch(F0, Br, St0),
+ {T1,Tu,St2} = umatch(T0, Br, St1),
+ Used = union(Fu, Tu),
+ {#k_alt{anno=#k{us=Used,ns=[],a=A},first=F1,then=T1},
+ Used,St2};
+umatch(#k_select{anno=A,var=V,types=Ts0}, Br, St0) ->
+ {Ts1,Tus,St1} = umatch_list(Ts0, Br, St0),
+ Used = add_element(V#k_var.name, Tus),
+ {#k_select{anno=#k{us=Used,ns=[],a=A},var=V,types=Ts1},Used,St1};
+umatch(#k_type_clause{anno=A,type=T,values=Vs0}, Br, St0) ->
+ {Vs1,Vus,St1} = umatch_list(Vs0, Br, St0),
+ {#k_type_clause{anno=#k{us=Vus,ns=[],a=A},type=T,values=Vs1},Vus,St1};
+umatch(#k_val_clause{anno=A,val=P,body=B0}, Br, St0) ->
+ {U0,Ps} = pat_vars(P),
+ {B1,Bu,St1} = umatch(B0, Br, St0),
+ Used = union(U0, subtract(Bu, Ps)),
+ {#k_val_clause{anno=#k{us=Used,ns=[],a=A},val=P,body=B1},
+ Used,St1};
+umatch(#k_guard{anno=A,clauses=Gs0}, Br, St0) ->
+ {Gs1,Gus,St1} = umatch_list(Gs0, Br, St0),
+ {#k_guard{anno=#k{us=Gus,ns=[],a=A},clauses=Gs1},Gus,St1};
+umatch(#k_guard_clause{anno=A,guard=G0,body=B0}, Br, St0) ->
+ %%ok = io:fwrite("~w: ~p~n", [?LINE,G0]),
+ {G1,Gu,St1} = uguard(G0, St0),
+ %%ok = io:fwrite("~w: ~p~n", [?LINE,G1]),
+ {B1,Bu,St2} = umatch(B0, Br, St1),
+ Used = union(Gu, Bu),
+ {#k_guard_clause{anno=#k{us=Used,ns=[],a=A},guard=G1,body=B1},Used,St2};
+umatch(B0, Br, St0) -> ubody(B0, Br, St0).
+
+umatch_list(Ms0, Br, St) ->
+ foldr(fun (M0, {Ms1,Us,Sta}) ->
+ {M1,Mu,Stb} = umatch(M0, Br, Sta),
+ {[M1|Ms1],union(Mu, Us),Stb}
+ end, {[],[],St}, Ms0).
+
+%% op_vars(Op) -> [VarName].
+
+op_vars(#k_local{}) -> [];
+op_vars(#k_remote{mod=Mod,name=Name}) ->
+ ordsets:from_list([V || #k_var{name=V} <- [Mod,Name]]);
+op_vars(#k_internal{}) -> [];
+op_vars(Atomic) -> lit_vars(Atomic).
+
+%% lit_vars(Literal) -> [VarName].
+%% Return the variables in a literal.
+
+lit_vars(#k_var{name=N}) -> [N];
+lit_vars(#k_int{}) -> [];
+lit_vars(#k_float{}) -> [];
+lit_vars(#k_atom{}) -> [];
+%%lit_vars(#k_char{}) -> [];
+lit_vars(#k_string{}) -> [];
+lit_vars(#k_nil{}) -> [];
+lit_vars(#k_cons{hd=H,tl=T}) ->
+ union(lit_vars(H), lit_vars(T));
+lit_vars(#k_binary{segs=V}) -> lit_vars(V);
+lit_vars(#k_bin_end{}) -> [];
+lit_vars(#k_bin_seg{size=Size,seg=S,next=N}) ->
+ union(lit_vars(Size), union(lit_vars(S), lit_vars(N)));
+lit_vars(#k_tuple{es=Es}) ->
+ lit_list_vars(Es).
+
+lit_list_vars(Ps) ->
+ foldl(fun (P, Vs) -> union(lit_vars(P), Vs) end, [], Ps).
+
+%% pat_vars(Pattern) -> {[UsedVarName],[NewVarName]}.
+%% Return variables in a pattern. All variables are new variables
+%% except those in the size field of binary segments.
+
+pat_vars(#k_var{name=N}) -> {[],[N]};
+%%pat_vars(#k_char{}) -> {[],[]};
+pat_vars(#k_int{}) -> {[],[]};
+pat_vars(#k_float{}) -> {[],[]};
+pat_vars(#k_atom{}) -> {[],[]};
+pat_vars(#k_string{}) -> {[],[]};
+pat_vars(#k_nil{}) -> {[],[]};
+pat_vars(#k_cons{hd=H,tl=T}) ->
+ pat_list_vars([H,T]);
+pat_vars(#k_binary{segs=V}) ->
+ pat_vars(V);
+pat_vars(#k_bin_seg{size=Size,seg=S,next=N}) ->
+ {U1,New} = pat_list_vars([S,N]),
+ {[],U2} = pat_vars(Size),
+ {union(U1, U2),New};
+pat_vars(#k_bin_end{}) -> {[],[]};
+pat_vars(#k_tuple{es=Es}) ->
+ pat_list_vars(Es).
+
+pat_list_vars(Ps) ->
+ foldl(fun (P, {Used0,New0}) ->
+ {Used,New} = pat_vars(P),
+ {union(Used0, Used),union(New0, New)} end,
+ {[],[]}, Ps).
+
+%% aligned(Bits, Size, Unit, Flags) -> {Size,Flags}
+%% Add 'aligned' to the flags if the current field is aligned.
+%% Number of bits correct modulo 8.
+
+aligned(B, S, U, Fs) when B rem 8 =:= 0 ->
+ {incr_bits(B, S, U),[aligned|Fs]};
+aligned(B, S, U, Fs) ->
+ {incr_bits(B, S, U),Fs}.
+
+incr_bits(B, #k_int{val=S}, U) when integer(B) -> B + S*U;
+incr_bits(_, #k_atom{val=all}, _) -> 0; %Always aligned
+incr_bits(B, _, 8) -> B;
+incr_bits(_, _, _) -> unknown.
+
+make_list(Es) ->
+ foldr(fun (E, Acc) -> #c_cons{hd=E,tl=Acc} end, #c_nil{}, Es).
+
+%% List of integers in interval [N,M]. Empty list if N > M.
+
+integers(N, M) when N =< M ->
+ [N|integers(N + 1, M)];
+integers(_, _) -> [].
+
+%%%
+%%% Handling of warnings.
+%%%
+
+format_error({nomatch_shadow,Line}) ->
+ M = io_lib:format("this clause cannot match because a previous clause at line ~p "
+ "always matches", [Line]),
+ lists:flatten(M);
+format_error(nomatch_shadow) ->
+ "this clause cannot match because a previous clause always matches".
+
+add_warning(none, Term, #kern{ws=Ws}=St) ->
+ St#kern{ws=[{?MODULE,Term}|Ws]};
+add_warning(Line, Term, #kern{ws=Ws}=St) when Line >= 0 ->
+ St#kern{ws=[{Line,?MODULE,Term}|Ws]};
+add_warning(_, _, St) -> St.
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_kernel.hrl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_kernel.hrl
new file mode 100644
index 0000000000..6e97d4d66a
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_kernel.hrl
@@ -0,0 +1,77 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: v3_kernel.hrl,v 1.1 2008/12/17 09:53:43 mikpe Exp $
+%%
+
+%% Purpose : Kernel Erlang as records.
+
+%% It would be nice to incorporate some generic functions as well but
+%% this could make including this file difficult.
+%% N.B. the annotation field is ALWAYS the first field!
+
+%% Kernel annotation record.
+-record(k, {us, %Used variables
+ ns, %New variables
+ a}). %Core annotation
+
+%% Literals
+%% NO CHARACTERS YET.
+%%-record(k_char, {anno=[],val}).
+-record(k_int, {anno=[],val}).
+-record(k_float, {anno=[],val}).
+-record(k_atom, {anno=[],val}).
+-record(k_string, {anno=[],val}).
+-record(k_nil, {anno=[]}).
+
+-record(k_tuple, {anno=[],es}).
+-record(k_cons, {anno=[],hd,tl}).
+-record(k_binary, {anno=[],segs}).
+-record(k_bin_seg, {anno=[],size,unit,type,flags,seg,next}).
+-record(k_bin_end, {anno=[]}).
+-record(k_var, {anno=[],name}).
+
+-record(k_local, {anno=[],name,arity}).
+-record(k_remote, {anno=[],mod,name,arity}).
+-record(k_internal, {anno=[],name,arity}).
+
+-record(k_mdef, {anno=[],name,exports,attributes,body}).
+-record(k_fdef, {anno=[],func,arity,vars,body}).
+
+-record(k_seq, {anno=[],arg,body}).
+-record(k_put, {anno=[],arg,ret=[]}).
+-record(k_bif, {anno=[],op,args,ret=[]}).
+-record(k_test, {anno=[],op,args}).
+-record(k_call, {anno=[],op,args,ret=[]}).
+-record(k_enter, {anno=[],op,args}).
+-record(k_receive, {anno=[],var,body,timeout,action,ret=[]}).
+-record(k_receive_accept, {anno=[]}).
+-record(k_receive_next, {anno=[]}).
+-record(k_try, {anno=[],arg,vars,body,evars,handler,ret=[]}).
+-record(k_catch, {anno=[],body,ret=[]}).
+
+-record(k_match, {anno=[],vars,body,ret=[]}).
+-record(k_alt, {anno=[],first,then}).
+-record(k_select, {anno=[],var,types}).
+-record(k_type_clause, {anno=[],type,values}).
+-record(k_val_clause, {anno=[],val,body}).
+-record(k_guard, {anno=[],clauses}).
+-record(k_guard_clause, {anno=[],guard,body}).
+
+-record(k_break, {anno=[],args=[]}).
+-record(k_return, {anno=[],args=[]}).
+
+%%k_get_anno(Thing) -> element(2, Thing).
+%%k_set_anno(Thing, Anno) -> setelement(2, Thing, Anno).
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_kernel_pp.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_kernel_pp.erl
new file mode 100644
index 0000000000..41f59b7a81
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_kernel_pp.erl
@@ -0,0 +1,444 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: v3_kernel_pp.erl,v 1.1 2008/12/17 09:53:43 mikpe Exp $
+%%
+%% Purpose : Kernel Erlang (naive) prettyprinter
+
+-module(v3_kernel_pp).
+
+-include("v3_kernel.hrl").
+
+-export([format/1]).
+
+%% These are "internal" structures in sys_kernel which are here for
+%% debugging purposes.
+-record(iset, {anno=[],vars,arg,body}).
+-record(ifun, {anno=[],vars,body}).
+
+%% ====================================================================== %%
+%% format(Node) -> Text
+%% Node = coreErlang()
+%% Text = string() | [Text]
+%%
+%% Prettyprint-formats (naively) an abstract Core Erlang syntax
+%% tree.
+
+-record(ctxt, {indent = 0,
+ item_indent = 2,
+ body_indent = 2,
+ tab_width = 8}).
+
+canno(Cthing) -> element(2, Cthing).
+
+format(Node) -> format(Node, #ctxt{}).
+
+format(Node, Ctxt) ->
+ case canno(Node) of
+ [] ->
+ format_1(Node, Ctxt);
+ List ->
+ format_anno(List, Ctxt, fun (Ctxt1) -> format_1(Node, Ctxt1) end)
+ end.
+
+format_anno(Anno, Ctxt, ObjFun) ->
+ Ctxt1 = ctxt_bump_indent(Ctxt, 2),
+ ["( ",
+ ObjFun(Ctxt1),
+ nl_indent(Ctxt1),
+ "-| ",io_lib:write(Anno),
+ " )"].
+
+%% format_1(Kexpr, Context) -> string().
+
+format_1(#k_atom{val=A}, _Ctxt) -> core_atom(A);
+%%format_1(#k_char{val=C}, _Ctxt) -> io_lib:write_char(C);
+format_1(#k_float{val=F}, _Ctxt) -> float_to_list(F);
+format_1(#k_int{val=I}, _Ctxt) -> integer_to_list(I);
+format_1(#k_nil{}, _Ctxt) -> "[]";
+format_1(#k_string{val=S}, _Ctxt) -> io_lib:write_string(S);
+format_1(#k_var{name=V}, _Ctxt) ->
+ if atom(V) ->
+ case atom_to_list(V) of
+ [$_|Cs] -> "_X" ++ Cs;
+ [C|Cs] when C >= $A, C =< $Z -> [C|Cs];
+ Cs -> [$_|Cs]
+ end;
+ integer(V) -> [$_|integer_to_list(V)]
+ end;
+format_1(#k_cons{hd=H,tl=T}, Ctxt) ->
+ Txt = ["["|format(H, ctxt_bump_indent(Ctxt, 1))],
+ [Txt|format_list_tail(T, ctxt_bump_indent(Ctxt, width(Txt, Ctxt)))];
+format_1(#k_tuple{es=Es}, Ctxt) ->
+ [${,
+ format_hseq(Es, ",", ctxt_bump_indent(Ctxt, 1), fun format/2),
+ $}
+ ];
+format_1(#k_binary{segs=S}, Ctxt) ->
+ ["#<",format(S, ctxt_bump_indent(Ctxt, 2)),">#"];
+format_1(#k_bin_seg{}=S, Ctxt) ->
+ [format_bin_seg_1(S, Ctxt),
+ format_bin_seg(S#k_bin_seg.next, ctxt_bump_indent(Ctxt, 2))];
+format_1(#k_bin_end{}, _Ctxt) -> "#<>#";
+format_1(#k_local{name=N,arity=A}, Ctxt) ->
+ "local " ++ format_fa_pair({N,A}, Ctxt);
+format_1(#k_remote{mod=M,name=N,arity=A}, _Ctxt) ->
+ %% This is for our internal translator.
+ io_lib:format("remote ~s:~s/~w", [format(M),format(N),A]);
+format_1(#k_internal{name=N,arity=A}, Ctxt) ->
+ "internal " ++ format_fa_pair({N,A}, Ctxt);
+format_1(#k_seq{arg=A,body=B}, Ctxt) ->
+ Ctxt1 = ctxt_bump_indent(Ctxt, 2),
+ ["do",
+ nl_indent(Ctxt1),
+ format(A, Ctxt1),
+ nl_indent(Ctxt),
+ "then",
+ nl_indent(Ctxt)
+ | format(B, Ctxt)
+ ];
+format_1(#k_match{vars=Vs,body=Bs,ret=Rs}, Ctxt) ->
+ Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.item_indent),
+ ["match ",
+ format_hseq(Vs, ",", ctxt_bump_indent(Ctxt, 6), fun format/2),
+ nl_indent(Ctxt1),
+ format(Bs, Ctxt1),
+ nl_indent(Ctxt),
+ "end",
+ format_ret(Rs, Ctxt1)
+ ];
+format_1(#k_alt{first=O,then=T}, Ctxt) ->
+ Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.item_indent),
+ ["alt",
+ nl_indent(Ctxt1),
+ format(O, Ctxt1),
+ nl_indent(Ctxt1),
+ format(T, Ctxt1)];
+format_1(#k_select{var=V,types=Cs}, Ctxt) ->
+ Ctxt1 = ctxt_bump_indent(Ctxt, 2),
+ ["select ",
+ format(V, Ctxt),
+ nl_indent(Ctxt1),
+ format_vseq(Cs, "", "", Ctxt1, fun format/2)
+ ];
+format_1(#k_type_clause{type=T,values=Cs}, Ctxt) ->
+ Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.body_indent),
+ ["type ",
+ io_lib:write(T),
+ nl_indent(Ctxt1),
+ format_vseq(Cs, "", "", Ctxt1, fun format/2)
+ ];
+format_1(#k_val_clause{val=Val,body=B}, Ctxt) ->
+ Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.body_indent),
+ [format(Val, Ctxt),
+ " ->",
+ nl_indent(Ctxt1)
+ | format(B, Ctxt1)
+ ];
+format_1(#k_guard{clauses=Gs}, Ctxt) ->
+ Ctxt1 = ctxt_bump_indent(Ctxt, 5),
+ ["when ",
+ nl_indent(Ctxt1),
+ format_vseq(Gs, "", "", Ctxt1, fun format/2)];
+format_1(#k_guard_clause{guard=G,body=B}, Ctxt) ->
+ Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.body_indent),
+ [format(G, Ctxt),
+ nl_indent(Ctxt),
+ "->",
+ nl_indent(Ctxt1)
+ | format(B, Ctxt1)
+ ];
+format_1(#k_call{op=Op,args=As,ret=Rs}, Ctxt) ->
+ Txt = ["call (",format(Op, ctxt_bump_indent(Ctxt, 6)),$)],
+ Ctxt1 = ctxt_bump_indent(Ctxt, 2),
+ [Txt,format_args(As, Ctxt1),
+ format_ret(Rs, Ctxt1)
+ ];
+format_1(#k_enter{op=Op,args=As}, Ctxt) ->
+ Txt = ["enter (",format(Op, ctxt_bump_indent(Ctxt, 7)),$)],
+ Ctxt1 = ctxt_bump_indent(Ctxt, 2),
+ [Txt,format_args(As, Ctxt1)];
+format_1(#k_bif{op=Op,args=As,ret=Rs}, Ctxt) ->
+ Txt = ["bif (",format(Op, ctxt_bump_indent(Ctxt, 5)),$)],
+ Ctxt1 = ctxt_bump_indent(Ctxt, 2),
+ [Txt,format_args(As, Ctxt1),
+ format_ret(Rs, Ctxt1)
+ ];
+format_1(#k_test{op=Op,args=As}, Ctxt) ->
+ Txt = ["test (",format(Op, ctxt_bump_indent(Ctxt, 6)),$)],
+ Ctxt1 = ctxt_bump_indent(Ctxt, 2),
+ [Txt,format_args(As, Ctxt1)];
+format_1(#k_put{arg=A,ret=Rs}, Ctxt) ->
+ [format(A, Ctxt),
+ format_ret(Rs, ctxt_bump_indent(Ctxt, 1))
+ ];
+format_1(#k_try{arg=A,vars=Vs,body=B,evars=Evs,handler=H,ret=Rs}, Ctxt) ->
+ Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.body_indent),
+ ["try",
+ nl_indent(Ctxt1),
+ format(A, Ctxt1),
+ nl_indent(Ctxt),
+ "of ",
+ format_hseq(Vs, ", ", ctxt_bump_indent(Ctxt, 3), fun format/2),
+ nl_indent(Ctxt1),
+ format(B, Ctxt1),
+ nl_indent(Ctxt),
+ "catch ",
+ format_hseq(Evs, ", ", ctxt_bump_indent(Ctxt, 6), fun format/2),
+ nl_indent(Ctxt1),
+ format(H, Ctxt1),
+ nl_indent(Ctxt),
+ "end",
+ format_ret(Rs, Ctxt1)
+ ];
+format_1(#k_catch{body=B,ret=Rs}, Ctxt) ->
+ Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.body_indent),
+ ["catch",
+ nl_indent(Ctxt1),
+ format(B, Ctxt1),
+ nl_indent(Ctxt),
+ "end",
+ format_ret(Rs, Ctxt1)
+ ];
+format_1(#k_receive{var=V,body=B,timeout=T,action=A,ret=Rs}, Ctxt) ->
+ Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.item_indent),
+ ["receive ",
+ format(V, Ctxt),
+ nl_indent(Ctxt1),
+ format(B, Ctxt1),
+ nl_indent(Ctxt),
+ "after ",
+ format(T, ctxt_bump_indent(Ctxt, 6)),
+ " ->",
+ nl_indent(Ctxt1),
+ format(A, Ctxt1),
+ nl_indent(Ctxt),
+ "end",
+ format_ret(Rs, Ctxt1)
+ ];
+format_1(#k_receive_accept{}, _Ctxt) -> "receive_accept";
+format_1(#k_receive_next{}, _Ctxt) -> "receive_next";
+format_1(#k_break{args=As}, Ctxt) ->
+ ["<",
+ format_hseq(As, ",", ctxt_bump_indent(Ctxt, 1), fun format/2),
+ ">"
+ ];
+format_1(#k_return{args=As}, Ctxt) ->
+ ["<<",
+ format_hseq(As, ",", ctxt_bump_indent(Ctxt, 1), fun format/2),
+ ">>"
+ ];
+format_1(#k_fdef{func=F,arity=A,vars=Vs,body=B}, Ctxt) ->
+ Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.body_indent),
+ ["fdef ",
+ format_fa_pair({F,A}, ctxt_bump_indent(Ctxt, 5)),
+ format_args(Vs, ctxt_bump_indent(Ctxt, 14)),
+ " =",
+ nl_indent(Ctxt1),
+ format(B, Ctxt1)
+ ];
+format_1(#k_mdef{name=N,exports=Es,attributes=As,body=B}, Ctxt) ->
+ ["module ",
+ format(#k_atom{val=N}, ctxt_bump_indent(Ctxt, 7)),
+ nl_indent(Ctxt),
+ "export [",
+ format_vseq(Es,
+ "", ",",
+ ctxt_bump_indent(Ctxt, 8),
+ fun format_fa_pair/2),
+ "]",
+ nl_indent(Ctxt),
+ "attributes [",
+ format_vseq(As,
+ "", ",",
+ ctxt_bump_indent(Ctxt, 12),
+ fun format_attribute/2),
+ "]",
+ nl_indent(Ctxt),
+ format_vseq(B,
+ "", "",
+ Ctxt,
+ fun format/2),
+ nl_indent(Ctxt)
+ | "end"
+ ];
+%% Internal sys_kernel structures.
+format_1(#iset{vars=Vs,arg=A,body=B}, Ctxt) ->
+ Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.body_indent),
+ ["set <",
+ format_hseq(Vs, ", ", ctxt_bump_indent(Ctxt, 5), fun format/2),
+ "> =",
+ nl_indent(Ctxt1),
+ format(A, Ctxt1),
+ nl_indent(Ctxt),
+ "in "
+ | format(B, ctxt_bump_indent(Ctxt, 2))
+ ];
+format_1(#ifun{vars=Vs,body=B}, Ctxt) ->
+ Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.body_indent),
+ ["fun ",
+ format_args(Vs, ctxt_bump_indent(Ctxt, 4)),
+ " ->",
+ nl_indent(Ctxt1)
+ | format(B, Ctxt1)
+ ];
+format_1(Type, _Ctxt) ->
+ ["** Unsupported type: ",
+ io_lib:write(Type)
+ | " **"
+ ].
+
+%% format_ret([RetVar], Context) -> Txt.
+%% Format the return vars of kexpr.
+
+format_ret(Rs, Ctxt) ->
+ [" >> ",
+ "<",
+ format_hseq(Rs, ",", ctxt_bump_indent(Ctxt, 5), fun format/2),
+ ">"].
+
+%% format_args([Arg], Context) -> Txt.
+%% Format arguments.
+
+format_args(As, Ctxt) ->
+ [$(,format_hseq(As, ", ", ctxt_bump_indent(Ctxt, 1), fun format/2),$)].
+
+%% format_hseq([Thing], Separator, Context, Fun) -> Txt.
+%% Format a sequence horizontally.
+
+format_hseq([H], _Sep, Ctxt, Fun) ->
+ Fun(H, Ctxt);
+format_hseq([H|T], Sep, Ctxt, Fun) ->
+ Txt = [Fun(H, Ctxt)|Sep],
+ Ctxt1 = ctxt_bump_indent(Ctxt, width(Txt, Ctxt)),
+ [Txt|format_hseq(T, Sep, Ctxt1, Fun)];
+format_hseq([], _, _, _) -> "".
+
+%% format_vseq([Thing], LinePrefix, LineSuffix, Context, Fun) -> Txt.
+%% Format a sequence vertically.
+
+format_vseq([H], _Pre, _Suf, Ctxt, Fun) ->
+ Fun(H, Ctxt);
+format_vseq([H|T], Pre, Suf, Ctxt, Fun) ->
+ [Fun(H, Ctxt),Suf,nl_indent(Ctxt),Pre|
+ format_vseq(T, Pre, Suf, Ctxt, Fun)];
+format_vseq([], _, _, _, _) -> "".
+
+format_fa_pair({F,A}, _Ctxt) -> [core_atom(F),$/,integer_to_list(A)].
+
+%% format_attribute({Name,Val}, Context) -> Txt.
+
+format_attribute({Name,Val}, Ctxt) when list(Val) ->
+ Txt = format(#k_atom{val=Name}, Ctxt),
+ Ctxt1 = ctxt_bump_indent(Ctxt, width(Txt,Ctxt)+4),
+ [Txt," = ",
+ $[,format_vseq(Val, "", ",", Ctxt1,
+ fun (A, _C) -> io_lib:write(A) end),$]
+ ];
+format_attribute({Name,Val}, Ctxt) ->
+ Txt = format(#k_atom{val=Name}, Ctxt),
+ [Txt," = ",io_lib:write(Val)].
+
+format_list_tail(#k_nil{anno=[]}, _Ctxt) -> "]";
+format_list_tail(#k_cons{anno=[],hd=H,tl=T}, Ctxt) ->
+ Txt = [$,|format(H, Ctxt)],
+ Ctxt1 = ctxt_bump_indent(Ctxt, width(Txt, Ctxt)),
+ [Txt|format_list_tail(T, Ctxt1)];
+format_list_tail(Tail, Ctxt) ->
+ ["|",format(Tail, ctxt_bump_indent(Ctxt, 1)), "]"].
+
+format_bin_seg(#k_bin_end{anno=[]}, _Ctxt) -> "";
+format_bin_seg(#k_bin_seg{anno=[],next=N}=Seg, Ctxt) ->
+ Txt = [$,|format_bin_seg_1(Seg, Ctxt)],
+ [Txt|format_bin_seg(N, ctxt_bump_indent(Ctxt, width(Txt, Ctxt)))];
+format_bin_seg(Seg, Ctxt) ->
+ ["|",format(Seg, ctxt_bump_indent(Ctxt, 2))].
+
+format_bin_seg_1(#k_bin_seg{size=S,unit=U,type=T,flags=Fs,seg=Seg}, Ctxt) ->
+ [format(Seg, Ctxt),
+ ":",format(S, Ctxt),"*",io_lib:write(U),
+ ":",io_lib:write(T),
+ lists:map(fun (F) -> [$-,io_lib:write(F)] end, Fs)
+ ].
+
+% format_bin_elements(#k_binary_cons{hd=H,tl=T,size=S,info=I}, Ctxt) ->
+% A = canno(T),
+% Fe = fun (Eh, Es, Ei, Ct) ->
+% [format(Eh, Ct),":",format(Es, Ct),"/",io_lib:write(Ei)]
+% end,
+% case T of
+% #k_zero_binary{} when A == [] ->
+% Fe(H, S, I, Ctxt);
+% #k_binary_cons{} when A == [] ->
+% Txt = [Fe(H, S, I, Ctxt)|","],
+% Ctxt1 = ctxt_bump_indent(Ctxt, width(Txt, Ctxt)),
+% [Txt|format_bin_elements(T, Ctxt1)];
+% _ ->
+% Txt = [Fe(H, S, I, Ctxt)|"|"],
+% [Txt|format(T, ctxt_bump_indent(Ctxt, width(Txt, Ctxt)))]
+% end.
+
+indent(Ctxt) -> indent(Ctxt#ctxt.indent, Ctxt).
+
+indent(N, _Ctxt) when N =< 0 -> "";
+indent(N, Ctxt) ->
+ T = Ctxt#ctxt.tab_width,
+ string:chars($\t, N div T, string:chars($\s, N rem T)).
+
+nl_indent(Ctxt) -> [$\n|indent(Ctxt)].
+
+
+unindent(T, Ctxt) ->
+ unindent(T, Ctxt#ctxt.indent, Ctxt, []).
+
+unindent(T, N, _Ctxt, C) when N =< 0 ->
+ [T|C];
+unindent([$\s|T], N, Ctxt, C) ->
+ unindent(T, N - 1, Ctxt, C);
+unindent([$\t|T], N, Ctxt, C) ->
+ Tab = Ctxt#ctxt.tab_width,
+ if N >= Tab ->
+ unindent(T, N - Tab, Ctxt, C);
+ true ->
+ unindent([string:chars($\s, Tab - N)|T], 0, Ctxt, C)
+ end;
+unindent([L|T], N, Ctxt, C) when list(L) ->
+ unindent(L, N, Ctxt, [T|C]);
+unindent([H|T], _N, _Ctxt, C) ->
+ [H|[T|C]];
+unindent([], N, Ctxt, [H|T]) ->
+ unindent(H, N, Ctxt, T);
+unindent([], _, _, []) -> [].
+
+
+width(Txt, Ctxt) ->
+ width(Txt, 0, Ctxt, []).
+
+width([$\t|T], A, Ctxt, C) ->
+ width(T, A + Ctxt#ctxt.tab_width, Ctxt, C);
+width([$\n|T], _A, Ctxt, C) ->
+ width(unindent([T|C], Ctxt), Ctxt);
+width([H|T], A, Ctxt, C) when list(H) ->
+ width(H, A, Ctxt, [T|C]);
+width([_|T], A, Ctxt, C) ->
+ width(T, A + 1, Ctxt, C);
+width([], A, Ctxt, [H|T]) ->
+ width(H, A, Ctxt, T);
+width([], A, _, []) -> A.
+
+ctxt_bump_indent(Ctxt, Dx) ->
+ Ctxt#ctxt{indent=Ctxt#ctxt.indent + Dx}.
+
+core_atom(A) -> io_lib:write_string(atom_to_list(A), $').
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_life.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_life.erl
new file mode 100644
index 0000000000..9579b5f46a
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_life.erl
@@ -0,0 +1,448 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: v3_life.erl,v 1.2 2010/03/04 13:54:20 maria Exp $
+%%
+%% Purpose : Convert annotated kernel expressions to annotated beam format.
+
+%% This module creates beam format annotated with variable lifetime
+%% information. Each thing is given an index and for each variable we
+%% store the first and last index for its occurrence. The variable
+%% database, VDB, attached to each thing is only relevant internally
+%% for that thing.
+%%
+%% For nested things like matches the numbering continues locally and
+%% the VDB for that thing refers to the variable usage within that
+%% thing. Variables which live through a such a thing are internally
+%% given a very large last index. Internally the indexes continue
+%% after the index of that thing. This creates no problems as the
+%% internal variable info never escapes and externally we only see
+%% variable which are alive both before or after.
+%%
+%% This means that variables never "escape" from a thing and the only
+%% way to get values from a thing is to "return" them, with 'break' or
+%% 'return'. Externally these values become the return values of the
+%% thing. This is no real limitation as most nested things have
+%% multiple threads so working out a common best variable usage is
+%% difficult.
+
+-module(v3_life).
+
+-export([module/2]).
+
+-export([vdb_find/2]).
+
+-import(lists, [map/2,foldl/3]).
+-import(ordsets, [add_element/2,intersection/2,union/2,union/1]).
+
+-include("v3_kernel.hrl").
+-include("v3_life.hrl").
+
+%% These are not defined in v3_kernel.hrl.
+get_kanno(Kthing) -> element(2, Kthing).
+%%set_kanno(Kthing, Anno) -> setelement(2, Kthing, Anno).
+
+module(#k_mdef{name=M,exports=Es,attributes=As,body=Fs0}, Opts) ->
+ put(?MODULE, Opts),
+ Fs1 = map(fun function/1, Fs0),
+ erase(?MODULE),
+ {ok,{M,Es,As,Fs1}}.
+
+%% function(Kfunc) -> Func.
+
+function(#k_fdef{func=F,arity=Ar,vars=Vs,body=Kb}) ->
+ %%ok = io:fwrite("life ~w: ~p~n", [?LINE,{F,Ar}]),
+ As = var_list(Vs),
+ Vdb0 = foldl(fun ({var,N}, Vdb) -> new_var(N, 0, Vdb) end, [], As),
+ %% Force a top-level match!
+ B0 = case Kb of
+ #k_match{} -> Kb;
+ _ ->
+ Ka = get_kanno(Kb),
+ #k_match{anno=#k{us=Ka#k.us,ns=[],a=Ka#k.a},
+ vars=Vs,body=Kb,ret=[]}
+ end,
+ {B1,_,Vdb1} = body(B0, 1, Vdb0),
+ {function,F,Ar,As,B1,Vdb1}.
+
+%% body(Kbody, I, Vdb) -> {[Expr],MaxI,Vdb}.
+%% Handle a body, need special cases for transforming match_fails.
+%% We KNOW that they only occur last in a body.
+
+body(#k_seq{arg=#k_put{anno=Pa,arg=Arg,ret=[R]},
+ body=#k_enter{anno=Ea,op=#k_internal{name=match_fail,arity=1},
+ args=[R]}},
+ I, Vdb0) ->
+ Vdb1 = use_vars(Pa#k.us, I, Vdb0), %All used here
+ {[match_fail(Arg, I, Pa#k.a ++ Ea#k.a)],I,Vdb1};
+body(#k_enter{anno=Ea,op=#k_internal{name=match_fail,arity=1},args=[Arg]},
+ I, Vdb0) ->
+ Vdb1 = use_vars(Ea#k.us, I, Vdb0),
+ {[match_fail(Arg, I, Ea#k.a)],I,Vdb1};
+body(#k_seq{arg=Ke,body=Kb}, I, Vdb0) ->
+ %%ok = io:fwrite("life ~w:~p~n", [?LINE,{Ke,I,Vdb0}]),
+ A = get_kanno(Ke),
+ Vdb1 = use_vars(A#k.us, I, new_vars(A#k.ns, I, Vdb0)),
+ {Es,MaxI,Vdb2} = body(Kb, I+1, Vdb1),
+ E = expr(Ke, I, Vdb2),
+ {[E|Es],MaxI,Vdb2};
+body(Ke, I, Vdb0) ->
+ %%ok = io:fwrite("life ~w:~p~n", [?LINE,{Ke,I,Vdb0}]),
+ A = get_kanno(Ke),
+ Vdb1 = use_vars(A#k.us, I, new_vars(A#k.ns, I, Vdb0)),
+ E = expr(Ke, I, Vdb1),
+ {[E],I,Vdb1}.
+
+%% guard(Kguard, I, Vdb) -> Guard.
+
+guard(#k_try{anno=A,arg=Ts,vars=[#k_var{name=X}],body=#k_var{name=X},
+ handler=#k_atom{val=false},ret=Rs}, I, Vdb) ->
+ %% Lock variables that are alive before try and used afterwards.
+ %% Don't lock variables that are only used inside the try expression.
+ Pdb0 = vdb_sub(I, I+1, Vdb),
+ {T,MaxI,Pdb1} = guard_body(Ts, I+1, Pdb0),
+ Pdb2 = use_vars(A#k.ns, MaxI+1, Pdb1), %Save "return" values
+ #l{ke={protected,T,var_list(Rs)},i=I,a=A#k.a,vdb=Pdb2};
+guard(#k_seq{}=G, I, Vdb0) ->
+ {Es,_,Vdb1} = guard_body(G, I, Vdb0),
+ #l{ke={block,Es},i=I,vdb=Vdb1,a=[]};
+guard(G, I, Vdb) -> guard_expr(G, I, Vdb).
+
+%% guard_body(Kbody, I, Vdb) -> {[Expr],MaxI,Vdb}.
+
+guard_body(#k_seq{arg=Ke,body=Kb}, I, Vdb0) ->
+ A = get_kanno(Ke),
+ Vdb1 = use_vars(A#k.us, I, new_vars(A#k.ns, I, Vdb0)),
+ {Es,MaxI,Vdb2} = guard_body(Kb, I+1, Vdb1),
+ E = guard_expr(Ke, I, Vdb2),
+ {[E|Es],MaxI,Vdb2};
+guard_body(Ke, I, Vdb0) ->
+ A = get_kanno(Ke),
+ Vdb1 = use_vars(A#k.us, I, new_vars(A#k.ns, I, Vdb0)),
+ E = guard_expr(Ke, I, Vdb1),
+ {[E],I,Vdb1}.
+
+%% guard_expr(Call, I, Vdb) -> Expr
+
+guard_expr(#k_test{anno=A,op=Op,args=As}, I, _Vdb) ->
+ #l{ke={test,test_op(Op),atomic_list(As)},i=I,a=A#k.a};
+guard_expr(#k_bif{anno=A,op=Op,args=As,ret=Rs}, I, _Vdb) ->
+ #l{ke={bif,bif_op(Op),atomic_list(As),var_list(Rs)},i=I,a=A#k.a};
+guard_expr(#k_put{anno=A,arg=Arg,ret=Rs}, I, _Vdb) ->
+ #l{ke={set,var_list(Rs),literal(Arg)},i=I,a=A#k.a};
+guard_expr(#k_match{anno=A,body=Kb,ret=Rs}, I, Vdb) ->
+ %% Experimental support for andalso/orelse in guards.
+ %% Work out imported variables which need to be locked.
+ Mdb = vdb_sub(I, I+1, Vdb),
+ M = match(Kb, A#k.us, I+1, Mdb),
+ #l{ke={match,M,var_list(Rs)},i=I,vdb=use_vars(A#k.us, I+1, Mdb),a=A#k.a};
+guard_expr(G, I, Vdb) -> guard(G, I, Vdb).
+
+%% expr(Kexpr, I, Vdb) -> Expr.
+
+expr(#k_call{anno=A,op=Op,args=As,ret=Rs}, I, _Vdb) ->
+ #l{ke={call,call_op(Op),atomic_list(As),var_list(Rs)},i=I,a=A#k.a};
+expr(#k_enter{anno=A,op=Op,args=As}, I, _Vdb) ->
+ #l{ke={enter,call_op(Op),atomic_list(As)},i=I,a=A#k.a};
+expr(#k_bif{anno=A,op=Op,args=As,ret=Rs}, I, _Vdb) ->
+ Bif = k_bif(A, Op, As, Rs),
+ #l{ke=Bif,i=I,a=A#k.a};
+expr(#k_match{anno=A,body=Kb,ret=Rs}, I, Vdb) ->
+ %% Work out imported variables which need to be locked.
+ Mdb = vdb_sub(I, I+1, Vdb),
+ M = match(Kb, A#k.us, I+1, Mdb),
+ #l{ke={match,M,var_list(Rs)},i=I,vdb=use_vars(A#k.us, I+1, Mdb),a=A#k.a};
+expr(#k_try{anno=A,arg=Ka,vars=Vs,body=Kb,evars=Evs,handler=Kh,ret=Rs}, I, Vdb) ->
+ %% Lock variables that are alive before the catch and used afterwards.
+ %% Don't lock variables that are only used inside the try.
+ Tdb0 = vdb_sub(I, I+1, Vdb),
+ %% This is the tricky bit. Lock variables in Arg that are used in
+ %% the body and handler. Add try tag 'variable'.
+ Ab = get_kanno(Kb),
+ Ah = get_kanno(Kh),
+ Tdb1 = use_vars(Ab#k.us, I+3, use_vars(Ah#k.us, I+3, Tdb0)),
+ Tdb2 = vdb_sub(I, I+2, Tdb1),
+ Vnames = fun (Kvar) -> Kvar#k_var.name end, %Get the variable names
+ {Aes,_,Adb} = body(Ka, I+2, add_var({catch_tag,I+1}, I+1, 1000000, Tdb2)),
+ {Bes,_,Bdb} = body(Kb, I+4, new_vars(map(Vnames, Vs), I+3, Tdb2)),
+ {Hes,_,Hdb} = body(Kh, I+4, new_vars(map(Vnames, Evs), I+3, Tdb2)),
+ #l{ke={'try',#l{ke={block,Aes},i=I+1,vdb=Adb,a=[]},
+ var_list(Vs),#l{ke={block,Bes},i=I+3,vdb=Bdb,a=[]},
+ var_list(Evs),#l{ke={block,Hes},i=I+3,vdb=Hdb,a=[]},
+ var_list(Rs)},
+ i=I,vdb=Tdb1,a=A#k.a};
+expr(#k_catch{anno=A,body=Kb,ret=[R]}, I, Vdb) ->
+ %% Lock variables that are alive before the catch and used afterwards.
+ %% Don't lock variables that are only used inside the catch.
+ %% Add catch tag 'variable'.
+ Cdb0 = vdb_sub(I, I+1, Vdb),
+ {Es,_,Cdb1} = body(Kb, I+1, add_var({catch_tag,I}, I, 1000000, Cdb0)),
+ #l{ke={'catch',Es,variable(R)},i=I,vdb=Cdb1,a=A#k.a};
+expr(#k_receive{anno=A,var=V,body=Kb,timeout=T,action=Ka,ret=Rs}, I, Vdb) ->
+ %% Work out imported variables which need to be locked.
+ Rdb = vdb_sub(I, I+1, Vdb),
+ M = match(Kb, add_element(V#k_var.name, A#k.us), I+1,
+ new_var(V#k_var.name, I, Rdb)),
+ {Tes,_,Adb} = body(Ka, I+1, Rdb),
+ #l{ke={receive_loop,atomic_lit(T),variable(V),M,
+ #l{ke=Tes,i=I+1,vdb=Adb,a=[]},var_list(Rs)},
+ i=I,vdb=use_vars(A#k.us, I+1, Vdb),a=A#k.a};
+expr(#k_receive_accept{anno=A}, I, _Vdb) ->
+ #l{ke=receive_accept,i=I,a=A#k.a};
+expr(#k_receive_next{anno=A}, I, _Vdb) ->
+ #l{ke=receive_next,i=I,a=A#k.a};
+expr(#k_put{anno=A,arg=Arg,ret=Rs}, I, _Vdb) ->
+ #l{ke={set,var_list(Rs),literal(Arg)},i=I,a=A#k.a};
+expr(#k_break{anno=A,args=As}, I, _Vdb) ->
+ #l{ke={break,atomic_list(As)},i=I,a=A#k.a};
+expr(#k_return{anno=A,args=As}, I, _Vdb) ->
+ #l{ke={return,atomic_list(As)},i=I,a=A#k.a}.
+
+%% call_op(Op) -> Op.
+%% bif_op(Op) -> Op.
+%% test_op(Op) -> Op.
+%% Do any necessary name translations here to munge into beam format.
+
+call_op(#k_local{name=N}) -> N;
+call_op(#k_remote{mod=M,name=N}) -> {remote,atomic_lit(M),atomic_lit(N)};
+call_op(Other) -> variable(Other).
+
+bif_op(#k_remote{mod=#k_atom{val=erlang},name=#k_atom{val=N}}) -> N;
+bif_op(#k_internal{name=N}) -> N.
+
+test_op(#k_remote{mod=#k_atom{val=erlang},name=#k_atom{val=N}}) -> N.
+
+%% k_bif(Anno, Op, [Arg], [Ret]) -> Expr.
+%% Build bifs, do special handling of internal some calls.
+
+k_bif(_A, #k_internal{name=dsetelement,arity=3}, As, []) ->
+ {bif,dsetelement,atomic_list(As),[]};
+k_bif(_A, #k_internal{name=make_fun},
+ [#k_atom{val=Fun},#k_int{val=Arity},
+ #k_int{val=Index},#k_int{val=Uniq}|Free],
+ Rs) ->
+ {bif,{make_fun,Fun,Arity,Index,Uniq},var_list(Free),var_list(Rs)};
+k_bif(_A, Op, As, Rs) ->
+ %% The general case.
+ {bif,bif_op(Op),atomic_list(As),var_list(Rs)}.
+
+%% match(Kexpr, [LockVar], I, Vdb) -> Expr.
+%% Convert match tree to old format.
+
+match(#k_alt{anno=A,first=Kf,then=Kt}, Ls, I, Vdb0) ->
+ Vdb1 = use_vars(union(A#k.us, Ls), I, Vdb0),
+ F = match(Kf, Ls, I+1, Vdb1),
+ T = match(Kt, Ls, I+1, Vdb1),
+ #l{ke={alt,F,T},i=I,vdb=Vdb1,a=A#k.a};
+match(#k_select{anno=A,var=V,types=Kts}, Ls0, I, Vdb0) ->
+ Ls1 = add_element(V#k_var.name, Ls0),
+ Vdb1 = use_vars(union(A#k.us, Ls1), I, Vdb0),
+ Ts = map(fun (Tc) -> type_clause(Tc, Ls1, I+1, Vdb1) end, Kts),
+ #l{ke={select,literal(V),Ts},i=I,vdb=Vdb1,a=A#k.a};
+match(#k_guard{anno=A,clauses=Kcs}, Ls, I, Vdb0) ->
+ Vdb1 = use_vars(union(A#k.us, Ls), I, Vdb0),
+ Cs = map(fun (G) -> guard_clause(G, Ls, I+1, Vdb1) end, Kcs),
+ #l{ke={guard,Cs},i=I,vdb=Vdb1,a=A#k.a};
+match(Other, Ls, I, Vdb0) ->
+ Vdb1 = use_vars(Ls, I, Vdb0),
+ {B,_,Vdb2} = body(Other, I+1, Vdb1),
+ #l{ke={block,B},i=I,vdb=Vdb2,a=[]}.
+
+type_clause(#k_type_clause{anno=A,type=T,values=Kvs}, Ls, I, Vdb0) ->
+ %%ok = io:format("life ~w: ~p~n", [?LINE,{T,Kvs}]),
+ Vdb1 = use_vars(union(A#k.us, Ls), I+1, Vdb0),
+ Vs = map(fun (Vc) -> val_clause(Vc, Ls, I+1, Vdb1) end, Kvs),
+ #l{ke={type_clause,type(T),Vs},i=I,vdb=Vdb1,a=A#k.a}.
+
+val_clause(#k_val_clause{anno=A,val=V,body=Kb}, Ls0, I, Vdb0) ->
+ {_Used,New} = match_pat_vars(V),
+ %% Not clear yet how Used should be used.
+ Bus = (get_kanno(Kb))#k.us,
+ %%ok = io:format("Ls0 = ~p, Used=~p\n New=~p, Bus=~p\n", [Ls0,Used,New,Bus]),
+ Ls1 = union(intersection(New, Bus), Ls0), %Lock for safety
+ Vdb1 = use_vars(union(A#k.us, Ls1), I+1, new_vars(New, I, Vdb0)),
+ B = match(Kb, Ls1, I+1, Vdb1),
+ #l{ke={val_clause,literal(V),B},i=I,vdb=use_vars(Bus, I+1, Vdb1),a=A#k.a}.
+
+guard_clause(#k_guard_clause{anno=A,guard=Kg,body=Kb}, Ls, I, Vdb0) ->
+ Vdb1 = use_vars(union(A#k.us, Ls), I+2, Vdb0),
+ Gdb = vdb_sub(I+1, I+2, Vdb1),
+ G = guard(Kg, I+1, Gdb),
+ B = match(Kb, Ls, I+2, Vdb1),
+ #l{ke={guard_clause,G,B},
+ i=I,vdb=use_vars((get_kanno(Kg))#k.us, I+2, Vdb1),
+ a=A#k.a}.
+
+%% match_fail(FailValue, I, Anno) -> Expr.
+%% Generate the correct match_fail instruction. N.B. there is no
+%% generic case for when the fail value has been created elsewhere.
+
+match_fail(#k_tuple{es=[#k_atom{val=function_clause}|As]}, I, A) ->
+ #l{ke={match_fail,{function_clause,literal_list(As)}},i=I,a=A};
+match_fail(#k_tuple{es=[#k_atom{val=badmatch},Val]}, I, A) ->
+ #l{ke={match_fail,{badmatch,literal(Val)}},i=I,a=A};
+match_fail(#k_tuple{es=[#k_atom{val=case_clause},Val]}, I, A) ->
+ #l{ke={match_fail,{case_clause,literal(Val)}},i=I,a=A};
+match_fail(#k_atom{val=if_clause}, I, A) ->
+ #l{ke={match_fail,if_clause},i=I,a=A};
+match_fail(#k_tuple{es=[#k_atom{val=try_clause},Val]}, I, A) ->
+ #l{ke={match_fail,{try_clause,literal(Val)}},i=I,a=A}.
+
+%% type(Ktype) -> Type.
+
+type(k_int) -> integer;
+type(k_char) -> integer; %Hhhmmm???
+type(k_float) -> float;
+type(k_atom) -> atom;
+type(k_nil) -> nil;
+type(k_cons) -> cons;
+type(k_tuple) -> tuple;
+type(k_binary) -> binary;
+type(k_bin_seg) -> bin_seg;
+type(k_bin_end) -> bin_end.
+
+%% variable(Klit) -> Lit.
+%% var_list([Klit]) -> [Lit].
+
+variable(#k_var{name=N}) -> {var,N}.
+
+var_list(Ks) -> map(fun variable/1, Ks).
+
+%% atomic_lit(Klit) -> Lit.
+%% atomic_list([Klit]) -> [Lit].
+
+atomic_lit(#k_var{name=N}) -> {var,N};
+atomic_lit(#k_int{val=I}) -> {integer,I};
+atomic_lit(#k_float{val=F}) -> {float,F};
+atomic_lit(#k_atom{val=N}) -> {atom,N};
+%%atomic_lit(#k_char{val=C}) -> {char,C};
+%%atomic_lit(#k_string{val=S}) -> {string,S};
+atomic_lit(#k_nil{}) -> nil.
+
+atomic_list(Ks) -> map(fun atomic_lit/1, Ks).
+
+%% literal(Klit) -> Lit.
+%% literal_list([Klit]) -> [Lit].
+
+literal(#k_var{name=N}) -> {var,N};
+literal(#k_int{val=I}) -> {integer,I};
+literal(#k_float{val=F}) -> {float,F};
+literal(#k_atom{val=N}) -> {atom,N};
+%%literal(#k_char{val=C}) -> {char,C};
+literal(#k_string{val=S}) -> {string,S};
+literal(#k_nil{}) -> nil;
+literal(#k_cons{hd=H,tl=T}) ->
+ {cons,[literal(H),literal(T)]};
+literal(#k_binary{segs=V}) ->
+ case proplists:get_bool(no_new_binaries, get(?MODULE)) of
+ true ->
+ {old_binary,literal(V)};
+ false ->
+ {binary,literal(V)}
+ end;
+literal(#k_bin_seg{size=S,unit=U,type=T,flags=Fs,seg=Seg,next=N}) ->
+ {bin_seg,literal(S),U,T,Fs,[literal(Seg),literal(N)]};
+literal(#k_bin_end{}) -> bin_end;
+literal(#k_tuple{es=Es}) ->
+ {tuple,literal_list(Es)}.
+
+literal_list(Ks) -> map(fun literal/1, Ks).
+
+%% match_pat_vars(Pattern) -> {[UsedVarName],[NewVarName]}.
+
+match_pat_vars(#k_var{name=N}) -> {[],[N]};
+match_pat_vars(#k_int{}) -> {[],[]};
+match_pat_vars(#k_float{}) -> {[],[]};
+match_pat_vars(#k_atom{}) -> {[],[]};
+%%match_pat_vars(#k_char{}) -> {[],[]};
+match_pat_vars(#k_string{}) -> {[],[]};
+match_pat_vars(#k_nil{}) -> {[],[]};
+match_pat_vars(#k_cons{hd=H,tl=T}) ->
+ match_pat_list_vars([H,T]);
+match_pat_vars(#k_binary{segs=V}) ->
+ match_pat_vars(V);
+match_pat_vars(#k_bin_seg{size=S,seg=Seg,next=N}) ->
+ {U1,New1} = match_pat_vars(Seg),
+ {U2,New2} = match_pat_vars(N),
+ {[],U3} = match_pat_vars(S),
+ {union([U1,U2,U3]),union(New1, New2)};
+match_pat_vars(#k_bin_end{}) -> {[],[]};
+match_pat_vars(#k_tuple{es=Es}) ->
+ match_pat_list_vars(Es).
+
+match_pat_list_vars(Ps) ->
+ foldl(fun (P, {Used0,New0}) ->
+ {Used,New} = match_pat_vars(P),
+ {union(Used0, Used),union(New0, New)} end,
+ {[],[]}, Ps).
+
+%% new_var(VarName, I, Vdb) -> Vdb.
+%% new_vars([VarName], I, Vdb) -> Vdb.
+%% use_var(VarName, I, Vdb) -> Vdb.
+%% use_vars([VarName], I, Vdb) -> Vdb.
+%% add_var(VarName, F, L, Vdb) -> Vdb.
+
+new_var(V, I, Vdb) ->
+ case vdb_find(V, Vdb) of
+ {V,F,L} when I < F -> vdb_store(V, I, L, Vdb);
+ {V,_,_} -> Vdb;
+ error -> vdb_store(V, I, I, Vdb)
+ end.
+
+new_vars(Vs, I, Vdb0) ->
+ foldl(fun (V, Vdb) -> new_var(V, I, Vdb) end, Vdb0, Vs).
+
+use_var(V, I, Vdb) ->
+ case vdb_find(V, Vdb) of
+ {V,F,L} when I > L -> vdb_store(V, F, I, Vdb);
+ {V,_,_} -> Vdb;
+ error -> vdb_store(V, I, I, Vdb)
+ end.
+
+use_vars(Vs, I, Vdb0) ->
+ foldl(fun (V, Vdb) -> use_var(V, I, Vdb) end, Vdb0, Vs).
+
+add_var(V, F, L, Vdb) ->
+ use_var(V, L, new_var(V, F, Vdb)).
+
+vdb_find(V, Vdb) ->
+ %% Peformance note: Profiling shows that this function accounts for
+ %% a lot of the execution time when huge constants terms are built.
+ %% Using the BIF lists:keysearch/3 is a lot faster than the
+ %% original Erlang version.
+ case lists:keysearch(V, 1, Vdb) of
+ {value,Vd} -> Vd;
+ false -> error
+ end.
+
+%vdb_find(V, [{V1,F,L}=Vd|Vdb]) when V < V1 -> error;
+%vdb_find(V, [{V1,F,L}=Vd|Vdb]) when V == V1 -> Vd;
+%vdb_find(V, [{V1,F,L}=Vd|Vdb]) when V > V1 -> vdb_find(V, Vdb);
+%vdb_find(V, []) -> error.
+
+vdb_store(V, F, L, [{V1,_,_}=Vd|Vdb]) when V > V1 ->
+ [Vd|vdb_store(V, F, L, Vdb)];
+vdb_store(V, F, L, [{V1,_,_}=Vd|Vdb]) when V < V1 -> [{V,F,L},Vd|Vdb];
+vdb_store(V, F, L, [{_V1,_,_}|Vdb]) -> [{V,F,L}|Vdb]; %V == V1
+vdb_store(V, F, L, []) -> [{V,F,L}].
+
+%% vdb_sub(Min, Max, Vdb) -> Vdb.
+%% Extract variables which are used before and after Min. Lock
+%% variables alive after Max.
+
+vdb_sub(Min, Max, Vdb) ->
+ [ if L >= Max -> {V,F,1000000};
+ true -> Vd
+ end || {V,F,L}=Vd <- Vdb, F < Min, L >= Min ].
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_life.hrl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_life.hrl
new file mode 100644
index 0000000000..4d183b7234
--- /dev/null
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/v3_life.hrl
@@ -0,0 +1,24 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: v3_life.hrl,v 1.1 2008/12/17 09:53:43 mikpe Exp $
+%%
+%% This record contains variable life-time annotation for a
+%% kernel expression. Added by v3_life, used by v3_codegen.
+
+-record(l, {ke, %Kernel expression
+ i=0, %Op number
+ vdb=[], %Variable database
+ a}). %Core annotation
diff --git a/lib/dialyzer/test/options1_tests_SUITE.erl b/lib/dialyzer/test/options1_tests_SUITE.erl
deleted file mode 100644
index 02cafe6c5f..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE.erl
+++ /dev/null
@@ -1,54 +0,0 @@
-%% ATTENTION!
-%% This is an automatically generated file. Do not edit.
-%% Use './remake' script to refresh it if needed.
-%% All Dialyzer options should be defined in dialyzer_options
-%% file.
-
--module(options1_tests_SUITE).
-
--include("ct.hrl").
--include("dialyzer_test_constants.hrl").
-
--export([suite/0, init_per_suite/0, init_per_suite/1,
- end_per_suite/1, all/0]).
--export([options1_tests_SUITE_consistency/1, compiler/1]).
-
-suite() ->
- [{timetrap, {minutes, 30}}].
-
-init_per_suite() ->
- [{timetrap, ?plt_timeout}].
-init_per_suite(Config) ->
- OutDir = ?config(priv_dir, Config),
- case dialyzer_common:check_plt(OutDir) of
- fail -> {skip, "Plt creation/check failed."};
- ok -> [{dialyzer_options, [{include_dirs,["my_include"]},
- {defines,[{'COMPILER_VSN',42}]},
- {warnings,[no_improper_lists]}]}|Config]
- end.
-
-end_per_suite(_Config) ->
- ok.
-
-all() ->
- [options1_tests_SUITE_consistency,compiler].
-
-dialyze(Config, TestCase) ->
- Opts = ?config(dialyzer_options, Config),
- Dir = ?config(data_dir, Config),
- OutDir = ?config(priv_dir, Config),
- dialyzer_common:check(TestCase, Opts, Dir, OutDir).
-
-options1_tests_SUITE_consistency(Config) ->
- Dir = ?config(data_dir, Config),
- case dialyzer_common:new_tests(Dir, all()) of
- [] -> ok;
- New -> ct:fail({missing_tests,New})
- end.
-
-compiler(Config) ->
- case dialyze(Config, compiler) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/my_include/erl_bits.hrl b/lib/dialyzer/test/options1_tests_SUITE_data/my_include/erl_bits.hrl
deleted file mode 100644
index 96d5cec268..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/my_include/erl_bits.hrl
+++ /dev/null
@@ -1,43 +0,0 @@
-%% ``The contents of this file are subject to the Erlang Public License,
-%% Version 1.0, (the "License"); you may not use this file except in
-%% compliance with the License. You may obtain a copy of the License at
-%% http://www.erlang.org/EPL1_0.txt
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% 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 Original Code is Erlang-4.7.3, December, 1998.
-%%
-%% The Initial Developer of the Original Code is Ericsson Telecom
-%% AB. Portions created by Ericsson are Copyright (C), 1998, Ericsson
-%% Telecom AB. All Rights Reserved.
-%%
-%% Contributor(s): ______________________________________.''
-%%
-%% This is an -*- erlang -*- file.
-%% Generic compiler options, passed from the erl_compile module.
-
--record(bittype, {
- type, %% integer/float/binary
- unit, %% element unit
- sign, %% signed/unsigned
- endian %% big/little
- }).
-
--record(bitdefault, {
- integer, %% default type for integer
- float, %% default type for float
- binary %% default type for binary
- }).
-
-%%% (From config.hrl in the bitsyntax branch.)
--define(SYS_ENDIAN, big).
--define(SIZEOF_CHAR, 1).
--define(SIZEOF_DOUBLE, 8).
--define(SIZEOF_FLOAT, 4).
--define(SIZEOF_INT, 4).
--define(SIZEOF_LONG, 4).
--define(SIZEOF_LONG_LONG, 8).
--define(SIZEOF_SHORT, 2).
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/my_include/erl_compile.hrl b/lib/dialyzer/test/options1_tests_SUITE_data/my_include/erl_compile.hrl
deleted file mode 100644
index ef2b68ac9a..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/my_include/erl_compile.hrl
+++ /dev/null
@@ -1,42 +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: erl_compile.hrl,v 1.1 2008/12/17 09:53:40 mikpe Exp $
-%%
-
-%% Generic compiler options, passed from the erl_compile module.
-
--record(options,
- {includes=[], % Include paths (list of absolute
- % directory names).
- outdir=".", % Directory for result (absolute
- % path).
- output_type=undefined, % Type of output file (atom).
- defines=[], % Preprocessor defines. Each
- % element is an atom (the name to
- % define), or a {Name, Value}
- % tuple.
- warning=1, % Warning level (0 - no
- % warnings, 1 - standard level,
- % 2, 3, ... - more warnings).
- verbose=false, % Verbose (true/false).
- optimize=999, % Optimize options.
- specific=[], % Compiler specific options.
- outfile="", % Name of output file (internal
- % use in erl_compile.erl).
- cwd % Current working directory
- % for erlc.
- }).
-
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/results/compiler b/lib/dialyzer/test/options1_tests_SUITE_data/results/compiler
deleted file mode 100644
index 924ef389df..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/results/compiler
+++ /dev/null
@@ -1,35 +0,0 @@
-
-beam_asm.erl:32: The pattern {'error', Error} can never match the type <<_:64,_:_*8>>
-beam_bool.erl:193: The pattern {[], _} can never match the type {[{_,_,_,_},...],[any()]}
-beam_bool.erl:510: The pattern [{'set', [Dst], _, _}, {'%live', _}] can never match the type [{_,_,_,_}]
-beam_disasm.erl:537: The variable X can never match since previous clauses completely covered the type 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
-beam_type.erl:284: The pattern <'pi', 0> can never match the type <_,1 | 2>
-beam_validator.erl:396: The pattern <{'jump', {'f', _}}, Vst = {'vst', 'none', _}> can never match the type <_,#vst{current::#st{ct::[]}}>
-beam_validator.erl:690: The pattern <'term', OldT> can never match the type <{'tuple',[any(),...]},_>
-beam_validator.erl:692: Clause guard cannot succeed. The pattern <NewT = {Type, New}, OldT = {_, Old}> was matched against the type <{'tuple',[any(),...]},_>
-beam_validator.erl:699: Clause guard cannot succeed. The pattern <NewT = {Type, _}, 'number'> was matched against the type <{'tuple',[any(),...]},_>
-beam_validator.erl:702: The pattern <'number', OldT = {Type, _}> can never match the type <{'tuple',[any(),...]},_>
-beam_validator.erl:705: The pattern <'bool', {'atom', A}> can never match the type <{'tuple',[any(),...]},_>
-beam_validator.erl:707: The pattern <{'atom', A}, 'bool'> can never match the type <{'tuple',[any(),...]},_>
-beam_validator.erl:713: Guard test is_integer(Sz::[any(),...]) can never succeed
-beam_validator.erl:727: Function upgrade_bool/1 will never be called
-cerl_inline.erl:190: The pattern 'true' can never match the type 'false'
-cerl_inline.erl:219: The pattern 'true' can never match the type 'false'
-cerl_inline.erl:230: The pattern 'true' can never match the type 'false'
-cerl_inline.erl:2333: The pattern 'true' can never match the type 'false'
-cerl_inline.erl:2355: The pattern 'true' can never match the type 'false'
-cerl_inline.erl:238: The pattern 'true' can never match the type 'false'
-cerl_inline.erl:2436: Function filename/1 will never be called
-cerl_inline.erl:2700: The pattern 'true' can never match the type 'false'
-cerl_inline.erl:2730: The pattern <{F, L, D}, Vs> can never match the type <[1..255,...],[any()]>
-cerl_inline.erl:2738: The pattern <{F, L, D}, Vs> can never match the type <[1..255,...],[any()]>
-cerl_inline.erl:2750: The pattern <{[], L, D}, Vs> can never match the type <[1..255,...],[any()]>
-cerl_inline.erl:2752: The pattern <{[], _L, D}, Vs> can never match the type <[1..255,...],[any()]>
-cerl_inline.erl:2754: The pattern <{F, L, D}, Vs> can never match the type <[1..255,...],[any()]>
-cerl_inline.erl:2756: The pattern <{F, _L, D}, Vs> can never match the type <[1..255,...],[any()]>
-compile.erl:788: The pattern {'error', Es} can never match the type {'ok',<<_:64,_:_*8>>}
-core_lint.erl:473: The pattern <{'c_atom', _, 'all'}, 'binary', _Def, St> can never match the type <_,#c_nil{} | {'c_atom' | 'c_char' | 'c_float' | 'c_int' | 'c_string' | 'c_tuple',_,_} | #c_cons{hd::#c_nil{} | {'c_atom' | 'c_char' | 'c_float' | 'c_int' | 'c_string' | 'c_tuple',_,_} | #c_cons{hd::{_,_} | {_,_,_} | {_,_,_,_},tl::{_,_} | {_,_,_} | {_,_,_,_}},tl::#c_nil{} | {'c_atom' | 'c_char' | 'c_float' | 'c_int' | 'c_string' | 'c_tuple',_,_} | #c_cons{hd::{_,_} | {_,_,_} | {_,_,_,_},tl::{_,_} | {_,_,_} | {_,_,_,_}}},[any()],_>
-core_lint.erl:505: The pattern <_Req, 'unknown', St> can never match the type <non_neg_integer(),non_neg_integer(),_>
-v3_codegen.erl:1569: The call v3_codegen:load_reg_1(V::any(),I::0,Rs::any(),pos_integer()) will never return since it differs in the 4th argument from the success typing arguments: (any(),0,maybe_improper_list(),0)
-v3_codegen.erl:1571: The call v3_codegen:load_reg_1(V::any(),I::0,[],pos_integer()) will never return since it differs in the 4th argument from the success typing arguments: (any(),0,maybe_improper_list(),0)
-v3_core.erl:646: The pattern <Prim = {'iprimop', _, _, _}, St> can never match the type <#c_nil{anno::[any(),...]} | {'c_atom' | 'c_char' | 'c_float' | 'c_int' | 'c_string' | 'c_tuple' | 'c_var' | 'ibinary' | 'icatch' | 'ireceive1',[any(),...] | {_,_,_,_},_} | #c_cons{anno::[any(),...]} | #c_fname{anno::[any(),...]} | #iletrec{anno::{_,_,_,_},defs::[any(),...],body::[any(),...]} | #icase{anno::{_,_,_,_},args::[any()],clauses::[any()],fc::{_,_,_,_,_,_}} | #ireceive2{anno::{_,_,_,_},clauses::[any()],action::[any()]} | #ifun{anno::{_,_,_,_},id::[any(),...],vars::[any()],clauses::[any(),...],fc::{_,_,_,_,_,_}} | #imatch{anno::{_,_,_,_},guard::[],fc::{_,_,_,_,_,_}} | #itry{anno::{_,_,_,_},args::[any()],vars::[any(),...],body::[any(),...],evars::[any(),...],handler::[any(),...]},_>
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_asm.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_asm.erl
deleted file mode 100644
index c2d9edcaa7..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_asm.erl
+++ /dev/null
@@ -1,358 +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: beam_asm.erl,v 1.1 2008/12/17 09:53:40 mikpe Exp $
-%%
-%% Purpose : Assembler for threaded Beam.
-
--module(beam_asm).
-
--export([module/4,format_error/1]).
--export([encode/2]).
-
--import(lists, [map/2,member/2,keymember/3,duplicate/2]).
--include("beam_opcodes.hrl").
-
--define(bs_aligned, 1).
-
-module(Code, Abst, SourceFile, Opts) ->
- case assemble(Code, Abst, SourceFile, Opts) of
- {error, Error} ->
- {error, [{none, ?MODULE, Error}]};
- Bin when binary(Bin) ->
- {ok, Bin}
- end.
-
-format_error({crashed, Why}) ->
- io_lib:format("beam_asm_int: EXIT: ~p", [Why]).
-
-assemble({Mod,Exp,Attr,Asm,NumLabels}, Abst, SourceFile, Opts) ->
- {1,Dict0} = beam_dict:atom(Mod, beam_dict:new()),
- NumFuncs = length(Asm),
- {Code,Dict1} = assemble_1(Asm, Exp, Dict0, []),
- build_file(Code, Attr, Dict1, NumLabels, NumFuncs, Abst, SourceFile, Opts).
-
-assemble_1([{function,Name,Arity,Entry,Asm}|T], Exp, Dict0, Acc) ->
- Dict1 = case member({Name,Arity}, Exp) of
- true ->
- beam_dict:export(Name, Arity, Entry, Dict0);
- false ->
- beam_dict:local(Name, Arity, Entry, Dict0)
- end,
- {Code, Dict2} = assemble_function(Asm, Acc, Dict1),
- assemble_1(T, Exp, Dict2, Code);
-assemble_1([], _Exp, Dict0, Acc) ->
- {IntCodeEnd,Dict1} = make_op(int_code_end, Dict0),
- {list_to_binary(lists:reverse(Acc, [IntCodeEnd])),Dict1}.
-
-assemble_function([H|T], Acc, Dict0) ->
- {Code, Dict} = make_op(H, Dict0),
- assemble_function(T, [Code| Acc], Dict);
-assemble_function([], Code, Dict) ->
- {Code, Dict}.
-
-build_file(Code, Attr, Dict, NumLabels, NumFuncs, Abst, SourceFile, Opts) ->
- %% Create the code chunk.
-
- CodeChunk = chunk(<<"Code">>,
- <<16:32,
- (beam_opcodes:format_number()):32,
- (beam_dict:highest_opcode(Dict)):32,
- NumLabels:32,
- NumFuncs:32>>,
- Code),
-
- %% Create the atom table chunk.
-
- {NumAtoms, AtomTab} = beam_dict:atom_table(Dict),
- AtomChunk = chunk(<<"Atom">>, <<NumAtoms:32>>, AtomTab),
-
- %% Create the import table chunk.
-
- {NumImps, ImpTab0} = beam_dict:import_table(Dict),
- Imp = flatten_imports(ImpTab0),
- ImportChunk = chunk(<<"ImpT">>, <<NumImps:32>>, Imp),
-
- %% Create the export table chunk.
-
- {NumExps, ExpTab0} = beam_dict:export_table(Dict),
- Exp = flatten_exports(ExpTab0),
- ExpChunk = chunk(<<"ExpT">>, <<NumExps:32>>, Exp),
-
- %% Create the local function table chunk.
-
- {NumLocals, Locals} = beam_dict:local_table(Dict),
- Loc = flatten_exports(Locals),
- LocChunk = chunk(<<"LocT">>, <<NumLocals:32>>, Loc),
-
- %% Create the string table chunk.
-
- {_,StringTab} = beam_dict:string_table(Dict),
- StringChunk = chunk(<<"StrT">>, StringTab),
-
- %% Create the fun table chunk. It is important not to build an empty chunk,
- %% as that would change the MD5.
-
- LambdaChunk = case beam_dict:lambda_table(Dict) of
- {0,[]} -> [];
- {NumLambdas,LambdaTab} ->
- chunk(<<"FunT">>, <<NumLambdas:32>>, LambdaTab)
- end,
-
- %% Create the attributes and compile info chunks.
-
- Essentials = [AtomChunk,CodeChunk,StringChunk,ImportChunk,ExpChunk,LambdaChunk],
- {Attributes,Compile} = build_attributes(Opts, SourceFile, Attr, Essentials),
- AttrChunk = chunk(<<"Attr">>, Attributes),
- CompileChunk = chunk(<<"CInf">>, Compile),
-
- %% Create the abstract code chunk.
-
- AbstChunk = chunk(<<"Abst">>, Abst),
-
- %% Create IFF chunk.
-
- Chunks = case member(slim, Opts) of
- true -> [Essentials,AttrChunk,CompileChunk,AbstChunk];
- false -> [Essentials,LocChunk,AttrChunk,CompileChunk,AbstChunk]
- end,
- build_form(<<"BEAM">>, Chunks).
-
-%% Build an IFF form.
-
-build_form(Id, Chunks0) when size(Id) == 4, list(Chunks0) ->
- Chunks = list_to_binary(Chunks0),
- Size = size(Chunks),
- 0 = Size rem 4, % Assertion: correct padding?
- <<"FOR1",(Size+4):32,Id/binary,Chunks/binary>>.
-
-%% Build a correctly padded chunk (with no sub-header).
-
-chunk(Id, Contents) when size(Id) == 4, binary(Contents) ->
- Size = size(Contents),
- [<<Id/binary,Size:32>>,Contents|pad(Size)];
-chunk(Id, Contents) when list(Contents) ->
- chunk(Id, list_to_binary(Contents)).
-
-%% Build a correctly padded chunk (with a sub-header).
-
-chunk(Id, Head, Contents) when size(Id) == 4, is_binary(Head), is_binary(Contents) ->
- Size = size(Head)+size(Contents),
- [<<Id/binary,Size:32,Head/binary>>,Contents|pad(Size)];
-chunk(Id, Head, Contents) when list(Contents) ->
- chunk(Id, Head, list_to_binary(Contents)).
-
-pad(Size) ->
- case Size rem 4 of
- 0 -> [];
- Rem -> duplicate(4 - Rem, 0)
- end.
-
-flatten_exports(Exps) ->
- list_to_binary(map(fun({F,A,L}) -> <<F:32,A:32,L:32>> end, Exps)).
-
-flatten_imports(Imps) ->
- list_to_binary(map(fun({M,F,A}) -> <<M:32,F:32,A:32>> end, Imps)).
-
-build_attributes(Opts, SourceFile, Attr, Essentials) ->
- Misc = case member(slim, Opts) of
- false ->
- {{Y,Mo,D},{H,Mi,S}} = erlang:universaltime(),
- [{time,{Y,Mo,D,H,Mi,S}},{source,SourceFile}];
- true -> []
- end,
- Compile = [{options,Opts},{version,?COMPILER_VSN}|Misc],
- {term_to_binary(calc_vsn(Attr, Essentials)),term_to_binary(Compile)}.
-
-%%
-%% If the attributes contains no 'vsn' attribute, we'll insert one
-%% with an MD5 "checksum" calculated on the code as its value.
-%% We'll not change an existing 'vsn' attribute.
-%%
-
-calc_vsn(Attr, Essentials) ->
- case keymember(vsn, 1, Attr) of
- true -> Attr;
- false ->
- <<Number:128>> = erlang:md5(Essentials),
- [{vsn,[Number]}|Attr]
- end.
-
-bif_type('-', 1) -> negate;
-bif_type('+', 2) -> {op, m_plus};
-bif_type('-', 2) -> {op, m_minus};
-bif_type('*', 2) -> {op, m_times};
-bif_type('/', 2) -> {op, m_div};
-bif_type('div', 2) -> {op, int_div};
-bif_type('rem', 2) -> {op, int_rem};
-bif_type('band', 2) -> {op, int_band};
-bif_type('bor', 2) -> {op, int_bor};
-bif_type('bxor', 2) -> {op, int_bxor};
-bif_type('bsl', 2) -> {op, int_bsl};
-bif_type('bsr', 2) -> {op, int_bsr};
-bif_type('bnot', 1) -> {op, int_bnot};
-bif_type(fnegate, 1) -> {op, fnegate};
-bif_type(fadd, 2) -> {op, fadd};
-bif_type(fsub, 2) -> {op, fsub};
-bif_type(fmul, 2) -> {op, fmul};
-bif_type(fdiv, 2) -> {op, fdiv};
-bif_type(_, _) -> bif.
-
-make_op(Comment, Dict) when element(1, Comment) == '%' ->
- {[],Dict};
-make_op({'%live',_R}, Dict) ->
- {[],Dict};
-make_op({bif, Bif, nofail, [], Dest}, Dict) ->
- encode_op(bif0, [{extfunc, erlang, Bif, 0}, Dest], Dict);
-make_op({bif, raise, _Fail, [A1,A2], _Dest}, Dict) ->
- encode_op(raise, [A1,A2], Dict);
-make_op({bif, Bif, Fail, Args, Dest}, Dict) ->
- Arity = length(Args),
- case bif_type(Bif, Arity) of
- {op, Op} ->
- make_op(list_to_tuple([Op, Fail|Args++[Dest]]), Dict);
- negate ->
- %% Fake negation operator.
- make_op({m_minus, Fail, {integer,0}, hd(Args), Dest}, Dict);
- bif ->
- BifOp = list_to_atom(lists:concat([bif, Arity])),
- encode_op(BifOp, [Fail, {extfunc, erlang, Bif, Arity}|Args++[Dest]],
- Dict)
- end;
-make_op({bs_add=Op,Fail,[Src1,Src2,Unit],Dest}, Dict) ->
- encode_op(Op, [Fail,Src1,Src2,Unit,Dest], Dict);
-make_op({test,Cond,Fail,Ops}, Dict) when list(Ops) ->
- encode_op(Cond, [Fail|Ops], Dict);
-make_op({make_fun2,{f,Lbl},Index,OldUniq,NumFree}, Dict0) ->
- {Fun,Dict} = beam_dict:lambda(Lbl, Index, OldUniq, NumFree, Dict0),
- make_op({make_fun2,Fun}, Dict);
-make_op(Op, Dict) when atom(Op) ->
- encode_op(Op, [], Dict);
-make_op({kill,Y}, Dict) ->
- make_op({init,Y}, Dict);
-make_op({Name,Arg1}, Dict) ->
- encode_op(Name, [Arg1], Dict);
-make_op({Name,Arg1,Arg2}, Dict) ->
- encode_op(Name, [Arg1,Arg2], Dict);
-make_op({Name,Arg1,Arg2,Arg3}, Dict) ->
- encode_op(Name, [Arg1,Arg2,Arg3], Dict);
-make_op({Name,Arg1,Arg2,Arg3,Arg4}, Dict) ->
- encode_op(Name, [Arg1,Arg2,Arg3,Arg4], Dict);
-make_op({Name,Arg1,Arg2,Arg3,Arg4,Arg5}, Dict) ->
- encode_op(Name, [Arg1,Arg2,Arg3,Arg4,Arg5], Dict);
-make_op({Name,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6}, Dict) ->
- encode_op(Name, [Arg1,Arg2,Arg3,Arg4,Arg5,Arg6], Dict).
-
-encode_op(Name, Args, Dict0) when atom(Name) ->
- {EncArgs,Dict1} = encode_args(Args, Dict0),
- Op = beam_opcodes:opcode(Name, length(Args)),
- Dict2 = beam_dict:opcode(Op, Dict1),
- {list_to_binary([Op|EncArgs]),Dict2}.
-
-encode_args([Arg| T], Dict0) ->
- {EncArg, Dict1} = encode_arg(Arg, Dict0),
- {EncTail, Dict2} = encode_args(T, Dict1),
- {[EncArg| EncTail], Dict2};
-encode_args([], Dict) ->
- {[], Dict}.
-
-encode_arg({x, X}, Dict) when X >= 0 ->
- {encode(?tag_x, X), Dict};
-encode_arg({y, Y}, Dict) when Y >= 0 ->
- {encode(?tag_y, Y), Dict};
-encode_arg({atom, Atom}, Dict0) when atom(Atom) ->
- {Index, Dict} = beam_dict:atom(Atom, Dict0),
- {encode(?tag_a, Index), Dict};
-encode_arg({integer, N}, Dict) ->
- {encode(?tag_i, N), Dict};
-encode_arg(nil, Dict) ->
- {encode(?tag_a, 0), Dict};
-encode_arg({f, W}, Dict) ->
- {encode(?tag_f, W), Dict};
-encode_arg({'char', C}, Dict) ->
- {encode(?tag_h, C), Dict};
-encode_arg({string, String}, Dict0) ->
- {Offset, Dict} = beam_dict:string(String, Dict0),
- {encode(?tag_u, Offset), Dict};
-encode_arg({extfunc, M, F, A}, Dict0) ->
- {Index, Dict} = beam_dict:import(M, F, A, Dict0),
- {encode(?tag_u, Index), Dict};
-encode_arg({list, List}, Dict0) ->
- {L, Dict} = encode_list(List, Dict0, []),
- {[encode(?tag_z, 1), encode(?tag_u, length(List))|L], Dict};
-encode_arg({float, Float}, Dict) when float(Float) ->
- {[encode(?tag_z, 0)|<<Float:64/float>>], Dict};
-encode_arg({fr,Fr}, Dict) ->
- {[encode(?tag_z, 2),encode(?tag_u,Fr)], Dict};
-encode_arg({field_flags,Flags0}, Dict) ->
- Flags = lists:foldl(fun (F, S) -> S bor flag_to_bit(F) end, 0, Flags0),
- {encode(?tag_u, Flags), Dict};
-encode_arg({alloc,List}, Dict) ->
- {encode_alloc_list(List),Dict};
-encode_arg(Int, Dict) when is_integer(Int) ->
- {encode(?tag_u, Int),Dict}.
-
-flag_to_bit(aligned) -> 16#01;
-flag_to_bit(little) -> 16#02;
-flag_to_bit(big) -> 16#00;
-flag_to_bit(signed) -> 16#04;
-flag_to_bit(unsigned)-> 16#00;
-flag_to_bit(exact) -> 16#08;
-flag_to_bit(native) -> 16#10.
-
-encode_list([H|T], _Dict, _Acc) when is_list(H) ->
- exit({illegal_nested_list,encode_arg,[H|T]});
-encode_list([H|T], Dict0, Acc) ->
- {Enc,Dict} = encode_arg(H, Dict0),
- encode_list(T, Dict, [Enc|Acc]);
-encode_list([], Dict, Acc) ->
- {lists:reverse(Acc), Dict}.
-
-encode_alloc_list(L0) ->
- L = encode_alloc_list_1(L0),
- [encode(?tag_z, 3),encode(?tag_u, length(L0))|L].
-
-encode_alloc_list_1([{words,Words}|T]) ->
- [encode(?tag_u, 0),encode(?tag_u, Words)|encode_alloc_list_1(T)];
-encode_alloc_list_1([{floats,Floats}|T]) ->
- [encode(?tag_u, 1),encode(?tag_u, Floats)|encode_alloc_list_1(T)];
-encode_alloc_list_1([]) -> [].
-
-encode(Tag, N) when N < 0 ->
- encode1(Tag, negative_to_bytes(N, []));
-encode(Tag, N) when N < 16 ->
- (N bsl 4) bor Tag;
-encode(Tag, N) when N < 16#800 ->
- [((N bsr 3) band 2#11100000) bor Tag bor 2#00001000, N band 16#ff];
-encode(Tag, N) ->
- encode1(Tag, to_bytes(N, [])).
-
-encode1(Tag, Bytes) ->
- case length(Bytes) of
- Num when 2 =< Num, Num =< 8 ->
- [((Num-2) bsl 5) bor 2#00011000 bor Tag| Bytes];
- Num when 8 < Num ->
- [2#11111000 bor Tag, encode(?tag_u, Num-9)| Bytes]
- end.
-
-to_bytes(0, [B|Acc]) when B < 128 ->
- [B|Acc];
-to_bytes(N, Acc) ->
- to_bytes(N bsr 8, [N band 16#ff| Acc]).
-
-negative_to_bytes(-1, [B1, B2|T]) when B1 > 127 ->
- [B1, B2|T];
-negative_to_bytes(N, Acc) ->
- negative_to_bytes(N bsr 8, [N band 16#ff|Acc]).
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_block.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_block.erl
deleted file mode 100644
index b0dd3e6380..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_block.erl
+++ /dev/null
@@ -1,601 +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: beam_block.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
-%%
-%% Purpose : Partitions assembly instructions into basic blocks and
-%% optimizes them.
-
--module(beam_block).
-
--export([module/2]).
--export([live_at_entry/1]). %Used by beam_type, beam_bool.
--export([is_killed/2]). %Used by beam_dead, beam_type, beam_bool.
--export([is_not_used/2]). %Used by beam_bool.
--export([merge_blocks/2]). %Used by beam_jump.
--import(lists, [map/2,mapfoldr/3,reverse/1,reverse/2,foldl/3,
- member/2,sort/1,all/2]).
--define(MAXREG, 1024).
-
-module({Mod,Exp,Attr,Fs,Lc}, _Opt) ->
- {ok,{Mod,Exp,Attr,map(fun function/1, Fs),Lc}}.
-
-function({function,Name,Arity,CLabel,Is0}) ->
- %% Collect basic blocks and optimize them.
- Is = blockify(Is0),
-
- %% Done.
- {function,Name,Arity,CLabel,Is}.
-
-%% blockify(Instructions0) -> Instructions
-%% Collect sequences of instructions to basic blocks and
-%% optimize the contents of the blocks. Also do some simple
-%% optimations on instructions outside the blocks.
-
-blockify(Is) ->
- blockify(Is, []).
-
-blockify([{loop_rec,{f,Fail},{x,0}},{loop_rec_end,_Lbl},{label,Fail}|Is], Acc) ->
- %% Useless instruction sequence.
- blockify(Is, Acc);
-blockify([{test,bs_test_tail,F,[Bits]}|Is],
- [{test,bs_skip_bits,F,[{integer,I},Unit,_Flags]}|Acc]) ->
- blockify(Is, [{test,bs_test_tail,F,[Bits+I*Unit]}|Acc]);
-blockify([{test,bs_skip_bits,F,[{integer,I1},Unit1,_]}|Is],
- [{test,bs_skip_bits,F,[{integer,I2},Unit2,Flags]}|Acc]) ->
- blockify(Is, [{test,bs_skip_bits,F,
- [{integer,I1*Unit1+I2*Unit2},1,Flags]}|Acc]);
-blockify([{test,is_atom,{f,Fail},[Reg]}=I|
- [{select_val,Reg,{f,Fail},
- {list,[{atom,false},{f,_}=BrFalse,
- {atom,true}=AtomTrue,{f,_}=BrTrue]}}|Is]=Is0],
- [{block,Bl}|_]=Acc) ->
- case is_last_bool(Bl, Reg) of
- false ->
- blockify(Is0, [I|Acc]);
- true ->
- blockify(Is, [{jump,BrTrue},
- {test,is_eq_exact,BrFalse,[Reg,AtomTrue]}|Acc])
- end;
-blockify([{test,is_atom,{f,Fail},[Reg]}=I|
- [{select_val,Reg,{f,Fail},
- {list,[{atom,true}=AtomTrue,{f,_}=BrTrue,
- {atom,false},{f,_}=BrFalse]}}|Is]=Is0],
- [{block,Bl}|_]=Acc) ->
- case is_last_bool(Bl, Reg) of
- false ->
- blockify(Is0, [I|Acc]);
- true ->
- blockify(Is, [{jump,BrTrue},
- {test,is_eq_exact,BrFalse,[Reg,AtomTrue]}|Acc])
- end;
-blockify([I|Is0]=IsAll, Acc) ->
- case is_bs_put(I) of
- true ->
- {BsPuts0,Is} = collect_bs_puts(IsAll),
- BsPuts = opt_bs_puts(BsPuts0),
- blockify(Is, reverse(BsPuts, Acc));
- false ->
- case collect(I) of
- error -> blockify(Is0, [I|Acc]);
- Instr when is_tuple(Instr) ->
- {Block0,Is} = collect_block(IsAll),
- Block = opt_block(Block0),
- blockify(Is, [{block,Block}|Acc])
- end
- end;
-blockify([], Acc) -> reverse(Acc).
-
-is_last_bool([I,{'%live',_}], Reg) ->
- is_last_bool([I], Reg);
-is_last_bool([{set,[Reg],As,{bif,N,_}}], Reg) ->
- Ar = length(As),
- erl_internal:new_type_test(N, Ar) orelse erl_internal:comp_op(N, Ar)
- orelse erl_internal:bool_op(N, Ar);
-is_last_bool([_|Is], Reg) -> is_last_bool(Is, Reg);
-is_last_bool([], _) -> false.
-
-collect_block(Is) ->
- collect_block(Is, []).
-
-collect_block([{allocate_zero,Ns,R},{test_heap,Nh,R}|Is], Acc) ->
- collect_block(Is, [{allocate,R,{no_opt,Ns,Nh,[]}}|Acc]);
-collect_block([I|Is]=Is0, Acc) ->
- case collect(I) of
- error -> {reverse(Acc),Is0};
- Instr -> collect_block(Is, [Instr|Acc])
- end;
-collect_block([], Acc) -> {reverse(Acc),[]}.
-
-collect({allocate_zero,N,R}) -> {allocate,R,{zero,N,0,[]}};
-collect({test_heap,N,R}) -> {allocate,R,{nozero,nostack,N,[]}};
-collect({bif,N,nofail,As,D}) -> {set,[D],As,{bif,N}};
-collect({bif,N,F,As,D}) -> {set,[D],As,{bif,N,F}};
-collect({move,S,D}) -> {set,[D],[S],move};
-collect({put_list,S1,S2,D}) -> {set,[D],[S1,S2],put_list};
-collect({put_tuple,A,D}) -> {set,[D],[],{put_tuple,A}};
-collect({put,S}) -> {set,[],[S],put};
-collect({put_string,L,S,D}) -> {set,[D],[],{put_string,L,S}};
-collect({get_tuple_element,S,I,D}) -> {set,[D],[S],{get_tuple_element,I}};
-collect({set_tuple_element,S,D,I}) -> {set,[],[S,D],{set_tuple_element,I}};
-collect({get_list,S,D1,D2}) -> {set,[D1,D2],[S],get_list};
-collect(remove_message) -> {set,[],[],remove_message};
-collect({'catch',R,L}) -> {set,[R],[],{'catch',L}};
-collect({'%live',_}=Live) -> Live;
-collect(_) -> error.
-
-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 = find_fixpoint(fun move_allocates/1, Is0),
- Is2 = find_fixpoint(fun opt/1, Is1),
- Is = opt_alloc(Is2),
- share_floats(Is).
-
-find_fixpoint(OptFun, Is0) ->
- case OptFun(Is0) of
- Is0 -> Is0;
- Is1 -> find_fixpoint(OptFun, Is1)
- end.
-
-move_allocates([{set,_Ds,_Ss,{set_tuple_element,_}}|_]=Is) -> Is;
-move_allocates([{set,Ds,Ss,_Op}=Set,{allocate,R,Alloc}|Is]) when is_integer(R) ->
- [{allocate,live_regs(Ds, Ss, R),Alloc},Set|Is];
-move_allocates([{allocate,R1,Alloc1},{allocate,R2,Alloc2}|Is]) ->
- R1 = R2, % Assertion.
- move_allocates([{allocate,R1,combine_alloc(Alloc1, Alloc2)}|Is]);
-move_allocates([I|Is]) ->
- [I|move_allocates(Is)];
-move_allocates([]) -> [].
-
-combine_alloc({_,Ns,Nh1,Init}, {_,nostack,Nh2,[]}) ->
- {zero,Ns,Nh1+Nh2,Init}.
-
-merge_blocks([{allocate,R,{Attr,Ns,Nh1,Init}}|B1],
- [{allocate,_,{_,nostack,Nh2,[]}}|B2]) ->
- Alloc = {allocate,R,{Attr,Ns,Nh1+Nh2,Init}},
- [Alloc|merge_blocks(B1, B2)];
-merge_blocks(B1, B2) -> merge_blocks_1(B1++[{set,[],[],stop_here}|B2]).
-
-merge_blocks_1([{set,[],_,stop_here}|Is]) -> Is;
-merge_blocks_1([{set,[D],_,move}=I|Is]) ->
- case is_killed(D, Is) of
- true -> merge_blocks_1(Is);
- false -> [I|merge_blocks_1(Is)]
- end;
-merge_blocks_1([I|Is]) -> [I|merge_blocks_1(Is)].
-
-opt([{set,[Dst],As,{bif,Bif,Fail}}=I1,
- {set,[Dst],[Dst],{bif,'not',Fail}}=I2|Is]) ->
- %% Get rid of the 'not' if the operation can be inverted.
- case inverse_comp_op(Bif) of
- none -> [I1,I2|opt(Is)];
- RevBif -> [{set,[Dst],As,{bif,RevBif,Fail}}|opt(Is)]
- end;
-opt([{set,[X],[X],move}|Is]) -> opt(Is);
-opt([{set,[D1],[{integer,Idx1},Reg],{bif,element,{f,0}}}=I1,
- {set,[D2],[{integer,Idx2},Reg],{bif,element,{f,0}}}=I2|Is])
- when Idx1 < Idx2, D1 =/= D2, D1 =/= Reg, D2 =/= Reg ->
- opt([I2,I1|Is]);
-opt([{set,Ds0,Ss,Op}|Is0]) ->
- {Ds,Is} = opt_moves(Ds0, Is0),
- [{set,Ds,Ss,Op}|opt(Is)];
-opt([I|Is]) -> [I|opt(Is)];
-opt([]) -> [].
-
-opt_moves([], Is0) -> {[],Is0};
-opt_moves([D0], Is0) ->
- {D1,Is1} = opt_move(D0, Is0),
- {[D1],Is1};
-opt_moves([X0,Y0]=Ds, Is0) ->
- {X1,Is1} = opt_move(X0, Is0),
- case opt_move(Y0, Is1) of
- {Y1,Is2} when X1 =/= Y1 -> {[X1,Y1],Is2};
- _Other when X1 =/= Y0 -> {[X1,Y0],Is1};
- _Other -> {Ds,Is0}
- end.
-
-opt_move(R, [{set,[D],[R],move}|Is]=Is0) ->
- case is_killed(R, Is) of
- true -> {D,Is};
- false -> {R,Is0}
- end;
-opt_move(R, [I|Is0]) ->
- case is_transparent(R, I) of
- true ->
- {D,Is1} = opt_move(R, Is0),
- case is_transparent(D, I) of
- true -> {D,[I|Is1]};
- false -> {R,[I|Is0]}
- end;
- false -> {R,[I|Is0]}
- end;
-opt_move(R, []) -> {R,[]}.
-
-is_transparent(R, {set,Ds,Ss,_Op}) ->
- case member(R, Ds) of
- true -> false;
- false -> not member(R, Ss)
- end;
-is_transparent(_, _) -> false.
-
-%% is_killed(Register, [Instruction]) -> true|false
-%% Determine whether a register is killed by the instruction sequence.
-%% If true is returned, it means that the register will not be
-%% referenced in ANY way (not even indirectly by an allocate instruction);
-%% i.e. it is OK to enter the instruction sequence with Register
-%% containing garbage.
-
-is_killed({x,N}=R, [{block,Blk}|Is]) ->
- case is_killed(R, Blk) of
- true -> true;
- false ->
- %% Before looking beyond the block, we must be
- %% sure that the register is not referenced by
- %% any allocate instruction in the block.
- case all(fun({allocate,Live,_}) when N < Live -> false;
- (_) -> true
- end, Blk) of
- true -> is_killed(R, Is);
- false -> false
- end
- end;
-is_killed(R, [{block,Blk}|Is]) ->
- case is_killed(R, Blk) of
- true -> true;
- false -> is_killed(R, Is)
- end;
-is_killed(R, [{set,Ds,Ss,_Op}|Is]) ->
- case member(R, Ss) of
- true -> false;
- false ->
- case member(R, Ds) of
- true -> true;
- false -> is_killed(R, Is)
- end
- end;
-is_killed(R, [{case_end,Used}|_]) -> R =/= Used;
-is_killed(R, [{badmatch,Used}|_]) -> R =/= Used;
-is_killed(_, [if_end|_]) -> true;
-is_killed(R, [{func_info,_,_,Ar}|_]) ->
- case R of
- {x,X} when X < Ar -> false;
- _ -> true
- end;
-is_killed(R, [{kill,R}|_]) -> true;
-is_killed(R, [{kill,_}|Is]) -> is_killed(R, Is);
-is_killed(R, [{bs_init2,_,_,_,_,_,Dst}|Is]) ->
- if
- R =:= Dst -> true;
- true -> is_killed(R, Is)
- end;
-is_killed(R, [{bs_put_string,_,_}|Is]) -> is_killed(R, Is);
-is_killed({x,R}, [{'%live',Live}|_]) when R >= Live -> true;
-is_killed({x,R}, [{'%live',_}|Is]) -> is_killed(R, Is);
-is_killed({x,R}, [{allocate,Live,_}|_]) ->
- %% Note: To be safe here, we must return either true or false,
- %% not looking further at the instructions beyond the allocate
- %% instruction.
- R >= Live;
-is_killed({x,R}, [{call,Live,_}|_]) when R >= Live -> true;
-is_killed({x,R}, [{call_last,Live,_,_}|_]) when R >= Live -> true;
-is_killed({x,R}, [{call_only,Live,_}|_]) when R >= Live -> true;
-is_killed({x,R}, [{call_ext,Live,_}|_]) when R >= Live -> true;
-is_killed({x,R}, [{call_ext_last,Live,_,_}|_]) when R >= Live -> true;
-is_killed({x,R}, [{call_ext_only,Live,_}|_]) when R >= Live -> true;
-is_killed({x,R}, [return|_]) when R > 0 -> true;
-is_killed(_, _) -> false.
-
-%% is_not_used(Register, [Instruction]) -> true|false
-%% Determine whether a register is used by the instruction sequence.
-%% If true is returned, it means that the register will not be
-%% referenced directly, but it may be referenced by an allocate
-%% instruction (meaning that it is NOT allowed to contain garbage).
-
-is_not_used(R, [{block,Blk}|Is]) ->
- case is_not_used(R, Blk) of
- true -> true;
- false -> is_not_used(R, Is)
- end;
-is_not_used({x,R}=Reg, [{allocate,Live,_}|Is]) ->
- if
- R >= Live -> true;
- true -> is_not_used(Reg, Is)
- end;
-is_not_used(R, [{set,Ds,Ss,_Op}|Is]) ->
- case member(R, Ss) of
- true -> false;
- false ->
- case member(R, Ds) of
- true -> true;
- false -> is_not_used(R, Is)
- end
- end;
-is_not_used(R, Is) -> is_killed(R, Is).
-
-%% opt_alloc(Instructions) -> Instructions'
-%% Optimises all allocate instructions.
-
-opt_alloc([{allocate,R,{_,Ns,Nh,[]}}|Is]) ->
- [opt_alloc(Is, Ns, Nh, R)|opt(Is)];
-opt_alloc([I|Is]) -> [I|opt_alloc(Is)];
-opt_alloc([]) -> [].
-
-%% opt_alloc(Instructions, FrameSize, HeapNeed, LivingRegs) -> [Instr]
-%% Generates the optimal sequence of instructions for
-%% allocating and initalizing the stack frame and needed heap.
-
-opt_alloc(_Is, nostack, Nh, LivingRegs) ->
- {allocate,LivingRegs,{nozero,nostack,Nh,[]}};
-opt_alloc(Is, Ns, Nh, LivingRegs) ->
- InitRegs = init_yreg(Is, 0),
- case count_ones(InitRegs) of
- N when N*2 > Ns ->
- {allocate,LivingRegs,{nozero,Ns,Nh,gen_init(Ns, InitRegs)}};
- _ ->
- {allocate,LivingRegs,{zero,Ns,Nh,[]}}
- end.
-
-gen_init(Fs, Regs) -> gen_init(Fs, Regs, 0, []).
-
-gen_init(SameFs, _Regs, SameFs, Acc) -> reverse(Acc);
-gen_init(Fs, Regs, Y, Acc) when Regs band 1 == 0 ->
- gen_init(Fs, Regs bsr 1, Y+1, [{init, {y,Y}}|Acc]);
-gen_init(Fs, Regs, Y, Acc) ->
- gen_init(Fs, Regs bsr 1, Y+1, Acc).
-
-%% init_yreg(Instructions, RegSet) -> RegSetInitialized
-%% Calculate the set of initialized y registers.
-
-init_yreg([{set,_,_,{bif,_,_}}|_], Reg) -> Reg;
-init_yreg([{set,Ds,_,_}|Is], Reg) -> init_yreg(Is, add_yregs(Ds, Reg));
-init_yreg(_Is, Reg) -> Reg.
-
-add_yregs(Ys, Reg) -> foldl(fun(Y, R0) -> add_yreg(Y, R0) end, Reg, Ys).
-
-add_yreg({y,Y}, Reg) -> Reg bor (1 bsl Y);
-add_yreg(_, Reg) -> Reg.
-
-count_ones(Bits) -> count_ones(Bits, 0).
-count_ones(0, Acc) -> Acc;
-count_ones(Bits, Acc) ->
- count_ones(Bits bsr 1, Acc + (Bits band 1)).
-
-%% live_at_entry(Is) -> NumberOfRegisters
-%% Calculate the number of register live at the entry to the code
-%% sequence.
-
-live_at_entry([{block,[{allocate,R,_}|_]}|_]) ->
- R;
-live_at_entry([{label,_}|Is]) ->
- live_at_entry(Is);
-live_at_entry([{block,Bl}|_]) ->
- live_at_entry(Bl);
-live_at_entry([{func_info,_,_,Ar}|_]) ->
- Ar;
-live_at_entry(Is0) ->
- case reverse(Is0) of
- [{'%live',Regs}|Is] -> live_at_entry_1(Is, (1 bsl Regs)-1);
- _ -> unknown
- end.
-
-live_at_entry_1([{set,Ds,Ss,_}|Is], Rset0) ->
- Rset = x_live(Ss, x_dead(Ds, Rset0)),
- live_at_entry_1(Is, Rset);
-live_at_entry_1([{allocate,_,_}|Is], Rset) ->
- live_at_entry_1(Is, Rset);
-live_at_entry_1([], Rset) -> live_regs_1(0, Rset).
-
-%% Calculate the new number of live registers when we move an allocate
-%% instruction upwards, passing a 'set' instruction.
-
-live_regs(Ds, Ss, Regs0) ->
- Rset = x_live(Ss, x_dead(Ds, (1 bsl Regs0)-1)),
- live_regs_1(0, Rset).
-
-live_regs_1(N, 0) -> N;
-live_regs_1(N, Regs) -> live_regs_1(N+1, Regs bsr 1).
-
-x_dead([{x,N}|Rs], Regs) -> x_dead(Rs, Regs band (bnot (1 bsl N)));
-x_dead([_|Rs], Regs) -> x_dead(Rs, Regs);
-x_dead([], Regs) -> Regs.
-
-x_live([{x,N}|Rs], Regs) -> x_live(Rs, Regs bor (1 bsl N));
-x_live([_|Rs], Regs) -> x_live(Rs, Regs);
-x_live([], Regs) -> Regs.
-
-%%
-%% If a floating point literal occurs more than once, move it into
-%% a free register and re-use it.
-%%
-
-share_floats([{allocate,_,_}=Alloc|Is]) ->
- [Alloc|share_floats(Is)];
-share_floats(Is0) ->
- All = get_floats(Is0, []),
- MoreThanOnce0 = more_than_once(sort(All), gb_sets:empty()),
- case gb_sets:is_empty(MoreThanOnce0) of
- true -> Is0;
- false ->
- MoreThanOnce = gb_sets:to_list(MoreThanOnce0),
- FreeX = highest_used(Is0, -1) + 1,
- Regs0 = make_reg_map(MoreThanOnce, FreeX, []),
- Regs = gb_trees:from_orddict(Regs0),
- Is = map(fun({set,Ds,[{float,F}],Op}=I) ->
- case gb_trees:lookup(F, Regs) of
- none -> I;
- {value,R} -> {set,Ds,[R],Op}
- end;
- (I) -> I
- end, Is0),
- [{set,[R],[{float,F}],move} || {F,R} <- Regs0] ++ Is
- end.
-
-get_floats([{set,_,[{float,F}],_}|Is], Acc) ->
- get_floats(Is, [F|Acc]);
-get_floats([_|Is], Acc) ->
- get_floats(Is, Acc);
-get_floats([], Acc) -> Acc.
-
-more_than_once([F,F|Fs], Set) ->
- more_than_once(Fs, gb_sets:add(F, Set));
-more_than_once([_|Fs], Set) ->
- more_than_once(Fs, Set);
-more_than_once([], Set) -> Set.
-
-highest_used([{set,Ds,Ss,_}|Is], High) ->
- highest_used(Is, highest(Ds, highest(Ss, High)));
-highest_used([{'%live',Live}|Is], High) when Live > High ->
- highest_used(Is, Live);
-highest_used([_|Is], High) ->
- highest_used(Is, High);
-highest_used([], High) -> High.
-
-highest([{x,R}|Rs], High) when R > High ->
- highest(Rs, R);
-highest([_|Rs], High) ->
- highest(Rs, High);
-highest([], High) -> High.
-
-make_reg_map([F|Fs], R, Acc) when R < ?MAXREG ->
- make_reg_map(Fs, R+1, [{F,{x,R}}|Acc]);
-make_reg_map(_, _, Acc) -> sort(Acc).
-
-%% inverse_comp_op(Op) -> none|RevOp
-
-inverse_comp_op('=:=') -> '=/=';
-inverse_comp_op('=/=') -> '=:=';
-inverse_comp_op('==') -> '/=';
-inverse_comp_op('/=') -> '==';
-inverse_comp_op('>') -> '=<';
-inverse_comp_op('<') -> '>=';
-inverse_comp_op('>=') -> '<';
-inverse_comp_op('=<') -> '>';
-inverse_comp_op(_) -> none.
-
-%%%
-%%% Evaluation of constant bit fields.
-%%%
-
-is_bs_put({bs_put_integer,_,_,_,_,_}) -> true;
-is_bs_put({bs_put_float,_,_,_,_,_}) -> true;
-is_bs_put(_) -> false.
-
-collect_bs_puts(Is) ->
- collect_bs_puts_1(Is, []).
-
-collect_bs_puts_1([I|Is]=Is0, Acc) ->
- case is_bs_put(I) of
- false -> {reverse(Acc),Is0};
- true -> collect_bs_puts_1(Is, [I|Acc])
- end;
-collect_bs_puts_1([], Acc) -> {reverse(Acc),[]}.
-
-opt_bs_puts(Is) ->
- opt_bs_1(Is, []).
-
-opt_bs_1([{bs_put_float,Fail,{integer,Sz},1,Flags0,Src}=I0|Is], Acc) ->
- case catch eval_put_float(Src, Sz, Flags0) of
- {'EXIT',_} ->
- opt_bs_1(Is, [I0|Acc]);
- <<Int:Sz>> ->
- Flags = force_big(Flags0),
- I = {bs_put_integer,Fail,{integer,Sz},1,Flags,{integer,Int}},
- opt_bs_1([I|Is], Acc)
- end;
-opt_bs_1([{bs_put_integer,_,{integer,8},1,_,{integer,_}}|_]=IsAll, Acc0) ->
- {Is,Acc} = bs_collect_string(IsAll, Acc0),
- opt_bs_1(Is, Acc);
-opt_bs_1([{bs_put_integer,Fail,{integer,Sz},1,F,{integer,N}}=I|Is0], Acc) when Sz > 8 ->
- case field_endian(F) of
- big ->
- case bs_split_int(N, Sz, Fail, Is0) of
- no_split -> opt_bs_1(Is0, [I|Acc]);
- Is -> opt_bs_1(Is, Acc)
- end;
- little ->
- case catch <<N:Sz/little>> of
- {'EXIT',_} ->
- opt_bs_1(Is0, [I|Acc]);
- <<Int:Sz>> ->
- Flags = force_big(F),
- Is = [{bs_put_integer,Fail,{integer,Sz},1,
- Flags,{integer,Int}}|Is0],
- opt_bs_1(Is, Acc)
- end;
- native -> opt_bs_1(Is0, [I|Acc])
- end;
-opt_bs_1([{Op,Fail,{integer,Sz},U,F,Src}|Is], Acc) when U > 1 ->
- opt_bs_1([{Op,Fail,{integer,U*Sz},1,F,Src}|Is], Acc);
-opt_bs_1([I|Is], Acc) ->
- opt_bs_1(Is, [I|Acc]);
-opt_bs_1([], Acc) -> reverse(Acc).
-
-eval_put_float(Src, Sz, Flags) ->
- Val = value(Src),
- case field_endian(Flags) of
- little -> <<Val:Sz/little-float-unit:1>>;
- big -> <<Val:Sz/big-float-unit:1>>
- %% native intentionally not handled here - we can't optimize it.
- end.
-
-value({integer,I}) -> I;
-value({float,F}) -> F;
-value({atom,A}) -> A.
-
-bs_collect_string(Is, [{bs_put_string,Len,{string,Str}}|Acc]) ->
- bs_coll_str_1(Is, Len, reverse(Str), Acc);
-bs_collect_string(Is, Acc) ->
- bs_coll_str_1(Is, 0, [], Acc).
-
-bs_coll_str_1([{bs_put_integer,_,{integer,Sz},U,_,{integer,V}}|Is],
- Len, StrAcc, IsAcc) when U*Sz =:= 8 ->
- Byte = V band 16#FF,
- bs_coll_str_1(Is, Len+1, [Byte|StrAcc], IsAcc);
-bs_coll_str_1(Is, Len, StrAcc, IsAcc) ->
- {Is,[{bs_put_string,Len,{string,reverse(StrAcc)}}|IsAcc]}.
-
-field_endian({field_flags,F}) -> field_endian_1(F).
-
-field_endian_1([big=E|_]) -> E;
-field_endian_1([little=E|_]) -> E;
-field_endian_1([native=E|_]) -> E;
-field_endian_1([_|Fs]) -> field_endian_1(Fs).
-
-force_big({field_flags,F}) ->
- {field_flags,force_big_1(F)}.
-
-force_big_1([big|_]=Fs) -> Fs;
-force_big_1([little|Fs]) -> [big|Fs];
-force_big_1([F|Fs]) -> [F|force_big_1(Fs)].
-
-bs_split_int(0, Sz, _, _) when Sz > 64 ->
- %% We don't want to split in this case because the
- %% string will consist of only zeroes.
- no_split;
-bs_split_int(N, Sz, Fail, Acc) ->
- FirstByteSz = case Sz rem 8 of
- 0 -> 8;
- Rem -> Rem
- end,
- bs_split_int_1(N, FirstByteSz, Sz, Fail, Acc).
-
-bs_split_int_1(N, ByteSz, Sz, Fail, Acc) when Sz > 0 ->
- Mask = (1 bsl ByteSz) - 1,
- I = {bs_put_integer,Fail,{integer,ByteSz},1,
- {field_flags,[big]},{integer,N band Mask}},
- bs_split_int_1(N bsr ByteSz, 8, Sz-ByteSz, Fail, [I|Acc]);
-bs_split_int_1(_, _, _, _, Acc) -> Acc.
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_bool.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_bool.erl
deleted file mode 100644
index 3180a22433..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_bool.erl
+++ /dev/null
@@ -1,617 +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: beam_bool.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
-%%
-%% Purpose: Optimizes booleans in guards.
-
--module(beam_bool).
-
--export([module/2]).
-
--import(lists, [reverse/1,foldl/3,mapfoldl/3,sort/1,member/2]).
--define(MAXREG, 1024).
-
--record(st,
- {next, %Next label number.
- ll %Live regs at labels.
- }).
-
-module({Mod,Exp,Attr,Fs0,Lc}, _Opts) ->
- %%io:format("~p:\n", [Mod]),
- {Fs,_} = mapfoldl(fun(Fn, Lbl) -> function(Fn, Lbl) end, 100000000, Fs0),
- {ok,{Mod,Exp,Attr,Fs,Lc}}.
-
-function({function,Name,Arity,CLabel,Is0}, Lbl0) ->
- %%io:format("~p/~p:\n", [Name,Arity]),
- {Is,#st{next=Lbl}} = bool_opt(Is0, Lbl0),
- {{function,Name,Arity,CLabel,Is},Lbl}.
-
-%%
-%% Optimize boolean expressions that use guard bifs. Rewrite to
-%% use test instructions if possible.
-%%
-
-bool_opt(Asm, Lbl) ->
- LiveInfo = index_instructions(Asm),
- bopt(Asm, [], #st{next=Lbl,ll=LiveInfo}).
-
-bopt([{block,Bl0}=Block|
- [{jump,{f,Succ}},
- {label,Fail},
- {block,[{set,[Dst],[{atom,false}],move},{'%live',Live}]},
- {label,Succ}|Is]=Is0], Acc0, St) ->
- case split_block(Bl0, Dst, Fail) of
- failed ->
- bopt(Is0, [Block|Acc0], St);
- {Bl,PreBlock} ->
- Acc1 = case PreBlock of
- [] -> Acc0;
- _ -> [{block,PreBlock}|Acc0]
- end,
- Acc = [{protected,[Dst],Bl,{Fail,Succ,Live}}|Acc1],
- bopt(Is, Acc, St)
- end;
-bopt([{test,is_eq_exact,{f,Fail},[Reg,{atom,true}]}=I|Is], [{block,_}|_]=Acc0, St0) ->
- case bopt_block(Reg, Fail, Is, Acc0, St0) of
- failed -> bopt(Is, [I|Acc0], St0);
- {Acc,St} -> bopt(Is, Acc, St)
- end;
-bopt([I|Is], Acc, St) ->
- bopt(Is, [I|Acc], St);
-bopt([], Acc, St) ->
- {bopt_reverse(Acc, []),St}.
-
-bopt_reverse([{protected,[Dst],Block,{Fail,Succ,Live}}|Is], Acc0) ->
- Acc = [{block,Block},{jump,{f,Succ}},
- {label,Fail},
- {block,[{set,[Dst],[{atom,false}],move},{'%live',Live}]},
- {label,Succ}|Acc0],
- bopt_reverse(Is, Acc);
-bopt_reverse([I|Is], Acc) ->
- bopt_reverse(Is, [I|Acc]);
-bopt_reverse([], Acc) -> Acc.
-
-%% bopt_block(Reg, Fail, OldIs, Accumulator, St) -> failed | {NewAcc,St}
-%% Attempt to optimized a block of guard BIFs followed by a test
-%% instruction.
-bopt_block(Reg, Fail, OldIs, [{block,Bl0}|Acc0], St0) ->
- case split_block(Bl0, Reg, Fail) of
- failed ->
- %% Reason for failure: The block either contained no
- %% guard BIFs with the failure label Fail, or the final
- %% instruction in the block did not assign the Reg register.
-
- %%io:format("split ~p: ~P\n", [Reg,Bl0,20]),
- failed;
- {Bl1,BlPre} ->
- %% The block has been splitted. Bl1 is a non-empty list
- %% of guard BIF instructions having the failure label Fail.
- %% BlPre is a (possibly empty list) of instructions preceeding
- %% Bl1.
- Acc1 = make_block(BlPre, Acc0),
- {Bl,Acc} = extend_block(Bl1, Fail, Acc1),
- case catch bopt_block_1(Bl, Fail, St0) of
- {'EXIT',_Reason} ->
- %% Optimization failed for one of the following reasons:
- %%
- %% 1. Not possible to rewrite because a boolean value is
- %% passed to another guard bif, e.g. 'abs(A > B)'
- %% (in this case, obviously nonsense code). Rare in
- %% practice.
- %%
- %% 2. Not possible to rewrite because we have not seen
- %% the complete boolan expression (it is spread out
- %% over several blocks with jumps and labels).
- %% The 'or' and 'and' instructions need to that fully
- %% known operands in order to be eliminated.
- %%
- %% 3. Other bug or limitation.
-
- %%io:format("~P\n", [_Reason,20]),
- failed;
- {NewCode,St} ->
- case is_opt_safe(Bl, NewCode, OldIs, St) of
- false ->
- %% The optimization is not safe. (A register
- %% used by the instructions following the
- %% optimized code is either not assigned a
- %% value at all or assigned a different value.)
-
- %%io:format("\nNot safe:\n"),
- %%io:format("~p\n", [Bl]),
- %%io:format("~p\n", [reverse(NewCode)]),
- failed;
- true -> {NewCode++Acc,St}
- end
- end
- end.
-
-bopt_block_1(Block, Fail, St) ->
- {Pre0,[{_,Tree}]} = bopt_tree(Block),
- Pre = update_fail_label(Pre0, Fail, []),
- bopt_cg(Tree, Fail, make_block(Pre, []), St).
-
-%% is_opt_safe(OriginalCode, OptCode, FollowingCode, State) -> true|false
-%% Comparing the original code to the optimized code, determine
-%% whether the optimized code is guaranteed to work in the same
-%% way as the original code.
-
-is_opt_safe(Bl, NewCode, OldIs, St) ->
- %% Here are the conditions that must be true for the
- %% optimization to be safe.
- %%
- %% 1. Any register that was assigned a value in the original
- %% code, but is not in the optimized code, must be guaranteed
- %% to be KILLED in the following code. (NotSet below.)
- %%
- %% 2. Any register that is assigned a value in the optimized
- %% code must be UNUSED in the following code. (NewDst, Set.)
- %% (Possible future improvement: Registers that are known
- %% to be assigned the SAME value in the original and optimized
- %% code don't need to be unused in the following code.)
-
- PrevDst = dst_regs(Bl),
- NewDst = dst_regs(NewCode),
- NotSet = ordsets:subtract(PrevDst, NewDst),
-
- %% Note: The following line is an optimization. We don't need
- %% to test whether variables in NotSet for being unused, because
- %% they will all be tested for being killed (a stronger condition
- %% than being unused).
-
- Set = ordsets:subtract(NewDst, NotSet),
-
- all_killed(NotSet, OldIs, St) andalso
- none_used(Set, OldIs, St).
-
-% update_fail_label([{set,_,_,{bif,_,{f,0}}}=I|Is], Fail, Acc) ->
-% update_fail_label(Is, Fail, [I|Acc]);
-update_fail_label([{set,Ds,As,{bif,N,{f,_}}}|Is], Fail, Acc) ->
- update_fail_label(Is, Fail, [{set,Ds,As,{bif,N,{f,Fail}}}|Acc]);
-update_fail_label([], _, Acc) -> Acc.
-
-make_block([], Acc) -> Acc;
-make_block(Bl, Acc) -> [{block,Bl}|Acc].
-
-extend_block(BlAcc, Fail, [{protected,_,_,_}=Prot|OldAcc]) ->
- extend_block([Prot|BlAcc], Fail, OldAcc);
-extend_block(BlAcc0, Fail, [{block,Is0}|OldAcc]=OldAcc0) ->
- case extend_block_1(reverse(Is0), Fail, BlAcc0) of
- {[],_} -> {BlAcc0,OldAcc0};
- {BlAcc,[]} -> extend_block(BlAcc, Fail, OldAcc);
- {BlAcc,Is} -> {BlAcc,[{block,Is}|OldAcc]}
- end;
-extend_block(BlAcc, _, OldAcc) -> {BlAcc,OldAcc}.
-
-extend_block_1([{set,[_],_,{bif,_,{f,Fail}}}=I|Is], Fail, Acc) ->
- extend_block_1(Is, Fail, [I|Acc]);
-extend_block_1([{set,[_],As,{bif,Bif,_}}=I|Is]=Is0, Fail, Acc) ->
- case safe_bool_op(Bif, length(As)) of
- false -> {Acc,reverse(Is0)};
- true -> extend_block_1(Is, Fail, [I|Acc])
- end;
-extend_block_1([_|_]=Is, _, Acc) -> {Acc,reverse(Is)};
-extend_block_1([], _, Acc) -> {Acc,[]}.
-
-split_block(Is0, Dst, Fail) ->
- case reverse(Is0) of
- [{'%live',_}|[{set,[Dst],_,_}|_]=Is] ->
- split_block_1(Is, Fail);
- [{set,[Dst],_,_}|_]=Is ->
- split_block_1(Is, Fail);
- _ -> failed
- end.
-
-split_block_1(Is, Fail) ->
- case split_block_2(Is, Fail, []) of
- {[],_} -> failed;
- {_,_}=Res -> Res
- end.
-
-% split_block_2([{set,[_],_,{bif,_,{f,0}}}=I|Is], Fail, Acc) ->
-% split_block_2(Is, Fail, [I|Acc]);
-split_block_2([{set,[_],_,{bif,_,{f,Fail}}}=I|Is], Fail, Acc) ->
- split_block_2(Is, Fail, [I|Acc]);
-split_block_2([{'%live',_}|Is], Fail, Acc) ->
- split_block_2(Is, Fail, Acc);
-split_block_2(Is, _, Acc) -> {Acc,reverse(Is)}.
-
-dst_regs(Is) ->
- dst_regs(Is, []).
-
-dst_regs([{block,Bl}|Is], Acc) ->
- dst_regs(Bl, dst_regs(Is, Acc));
-dst_regs([{set,[D],_,{bif,_,{f,_}}}|Is], Acc) ->
- dst_regs(Is, [D|Acc]);
-dst_regs([_|Is], Acc) ->
- dst_regs(Is, Acc);
-dst_regs([], Acc) -> ordsets:from_list(Acc).
-
-all_killed([R|Rs], OldIs, St) ->
- case is_killed(R, OldIs, St) of
- false -> false;
- true -> all_killed(Rs, OldIs, St)
- end;
-all_killed([], _, _) -> true.
-
-none_used([R|Rs], OldIs, St) ->
- case is_not_used(R, OldIs, St) of
- false -> false;
- true -> none_used(Rs, OldIs, St)
- end;
-none_used([], _, _) -> true.
-
-bopt_tree(Block0) ->
- Block = ssa_block(Block0),
- Reg = free_variables(Block),
- %%io:format("~p\n", [Block]),
- %%io:format("~p\n", [Reg]),
- Res = bopt_tree_1(Block, Reg, []),
- %%io:format("~p\n", [Res]),
- Res.
-
-bopt_tree_1([{set,[Dst],As0,{bif,'not',_}}|Is], Forest0, Pre) ->
- {[Arg],Forest1} = bopt_bool_args(As0, Forest0),
- Forest = gb_trees:enter(Dst, {'not',Arg}, Forest1),
- bopt_tree_1(Is, Forest, Pre);
-bopt_tree_1([{set,[Dst],As0,{bif,'and',_}}|Is], Forest0, Pre) ->
- {As,Forest1} = bopt_bool_args(As0, Forest0),
- AndList = make_and_list(As),
- Forest = gb_trees:enter(Dst, {'and',AndList}, Forest1),
- bopt_tree_1(Is, Forest, Pre);
-bopt_tree_1([{set,[Dst],[L0,R0],{bif,'or',_}}|Is], Forest0, Pre) ->
- L = gb_trees:get(L0, Forest0),
- R = gb_trees:get(R0, Forest0),
- Forest1 = gb_trees:delete(L0, gb_trees:delete(R0, Forest0)),
- OrList = make_or_list([L,R]),
- Forest = gb_trees:enter(Dst, {'or',OrList}, Forest1),
- bopt_tree_1(Is, Forest, Pre);
-bopt_tree_1([{protected,[Dst],_,_}=Prot|Is], Forest0, Pre) ->
- Forest = gb_trees:enter(Dst, Prot, Forest0),
- bopt_tree_1(Is, Forest, Pre);
-bopt_tree_1([{set,[Dst],As,{bif,N,_}}=Bif|Is], Forest0, Pre) ->
- Ar = length(As),
- case safe_bool_op(N, Ar) of
- false ->
- bopt_good_args(As, Forest0),
- Forest = gb_trees:enter(Dst, any, Forest0),
- bopt_tree_1(Is, Forest, [Bif|Pre]);
- true ->
- bopt_good_args(As, Forest0),
- Test = bif_to_test(Dst, N, As),
- Forest = gb_trees:enter(Dst, Test, Forest0),
- bopt_tree_1(Is, Forest, Pre)
- end;
-bopt_tree_1([], Forest, Pre) ->
- {Pre,[R || {_,V}=R <- gb_trees:to_list(Forest), V =/= any]}.
-
-safe_bool_op(internal_is_record, 3) -> true;
-safe_bool_op(N, Ar) ->
- erl_internal:new_type_test(N, Ar) orelse erl_internal:comp_op(N, Ar).
-
-bopt_bool_args(As, Forest) ->
- mapfoldl(fun bopt_bool_arg/2, Forest, As).
-
-bopt_bool_arg({T,_}=R, Forest) when T == x; T == y ->
- {gb_trees:get(R, Forest),gb_trees:delete(R, Forest)};
-bopt_bool_arg(Term, Forest) ->
- {Term,Forest}.
-
-bopt_good_args([A|As], Regs) ->
- bopt_good_arg(A, Regs),
- bopt_good_args(As, Regs);
-bopt_good_args([], _) -> ok.
-
-bopt_good_arg({x,_}=X, Regs) ->
- case gb_trees:get(X, Regs) of
- any -> ok;
- _Other ->
- %%io:format("not any: ~p: ~p\n", [X,_Other]),
- exit(bad_contents)
- end;
-bopt_good_arg(_, _) -> ok.
-
-bif_to_test(_, N, As) ->
- bif_to_test(N, As).
-
-bif_to_test(internal_is_record, [_,_,_]=As) ->
- {test,internal_is_record,fail,As};
-bif_to_test('=:=', As) -> {test,is_eq_exact,fail,As};
-bif_to_test('=/=', As) -> {test,is_ne_exact,fail,As};
-bif_to_test('==', As) -> {test,is_eq,fail,As};
-bif_to_test('/=', As) -> {test,is_ne,fail,As};
-bif_to_test('=<', [L,R]) -> {test,is_ge,fail,[R,L]};
-bif_to_test('>=', As) -> {test,is_ge,fail,As};
-bif_to_test('>', [L,R]) -> {test,is_lt,fail,[R,L]};
-bif_to_test('<', As) -> {test,is_lt,fail,As};
-bif_to_test(Name, [_]=As) ->
- case erl_internal:new_type_test(Name, 1) of
- false -> exit({bif_to_test,Name,As,failed});
- true -> {test,Name,fail,As}
- end.
-
-make_and_list([{'and',As}|Is]) ->
- make_and_list(As++Is);
-make_and_list([I|Is]) ->
- [I|make_and_list(Is)];
-make_and_list([]) -> [].
-
-make_or_list([{'or',As}|Is]) ->
- make_or_list(As++Is);
-make_or_list([I|Is]) ->
- [I|make_or_list(Is)];
-make_or_list([]) -> [].
-
-%% Code generation for a boolean tree.
-
-bopt_cg({'not',Arg}, Fail, Acc, St) ->
- I = bopt_cg_not(Arg),
- bopt_cg(I, Fail, Acc, St);
-bopt_cg({'and',As}, Fail, Acc, St) ->
- bopt_cg_and(As, Fail, Acc, St);
-bopt_cg({'or',As}, Fail, Acc, St0) ->
- {Succ,St} = new_label(St0),
- bopt_cg_or(As, Succ, Fail, Acc, St);
-bopt_cg({test,is_tuple_element,fail,[Tmp,Tuple,RecordTag]}, Fail, Acc, St) ->
- {[{test,is_eq_exact,{f,Fail},[Tmp,RecordTag]},
- {get_tuple_element,Tuple,0,Tmp}|Acc],St};
-bopt_cg({inverted_test,is_tuple_element,fail,[Tmp,Tuple,RecordTag]}, Fail, Acc, St) ->
- {[{test,is_ne_exact,{f,Fail},[Tmp,RecordTag]},
- {get_tuple_element,Tuple,0,Tmp}|Acc],St};
-bopt_cg({test,N,fail,As}, Fail, Acc, St) ->
- Test = {test,N,{f,Fail},As},
- {[Test|Acc],St};
-bopt_cg({inverted_test,N,fail,As}, Fail, Acc, St0) ->
- {Lbl,St} = new_label(St0),
- {[{label,Lbl},{jump,{f,Fail}},{test,N,{f,Lbl},As}|Acc],St};
-bopt_cg({protected,_,Bl0,{_,_,_}}, Fail, Acc, St0) ->
- {Bl,St} = bopt_block_1(Bl0, Fail, St0),
- {Bl++Acc,St};
-bopt_cg([_|_]=And, Fail, Acc, St) ->
- bopt_cg_and(And, Fail, Acc, St).
-
-bopt_cg_not({'and',As0}) ->
- As = [bopt_cg_not(A) || A <- As0],
- {'or',As};
-bopt_cg_not({'or',As0}) ->
- As = [bopt_cg_not(A) || A <- As0],
- {'and',As};
-bopt_cg_not({test,Test,Fail,As}) ->
- {inverted_test,Test,Fail,As}.
-
-bopt_cg_and([{atom,false}|_], Fail, _, St) ->
- {[{jump,{f,Fail}}],St};
-bopt_cg_and([{atom,true}|Is], Fail, Acc, St) ->
- bopt_cg_and(Is, Fail, Acc, St);
-bopt_cg_and([I|Is], Fail, Acc0, St0) ->
- {Acc,St} = bopt_cg(I, Fail, Acc0, St0),
- bopt_cg_and(Is, Fail, Acc, St);
-bopt_cg_and([], _, Acc, St) -> {Acc,St}.
-
-bopt_cg_or([I], Succ, Fail, Acc0, St0) ->
- {Acc,St} = bopt_cg(I, Fail, Acc0, St0),
- {[{label,Succ}|Acc],St};
-bopt_cg_or([I|Is], Succ, Fail, Acc0, St0) ->
- {Lbl,St1} = new_label(St0),
- {Acc,St} = bopt_cg(I, Lbl, Acc0, St1),
- bopt_cg_or(Is, Succ, Fail, [{label,Lbl},{jump,{f,Succ}}|Acc], St).
-
-new_label(#st{next=LabelNum}=St) when is_integer(LabelNum) ->
- {LabelNum,St#st{next=LabelNum+1}}.
-
-free_variables(Is) ->
- E = gb_sets:empty(),
- free_vars_1(Is, E, E).
-
-free_vars_1([{set,[Dst],As,{bif,_,_}}|Is], F0, N0) ->
- F = gb_sets:union(F0, gb_sets:difference(var_list(As), N0)),
- N = gb_sets:union(N0, var_list([Dst])),
- free_vars_1(Is, F, N);
-free_vars_1([{protected,_,Pa,_}|Is], F, N) ->
- free_vars_1(Pa++Is, F, N);
-free_vars_1([], F, _) ->
- gb_trees:from_orddict([{K,any} || K <- gb_sets:to_list(F)]).
-
-var_list(Is) ->
- var_list_1(Is, gb_sets:empty()).
-
-var_list_1([{x,_}=X|Is], D) ->
- var_list_1(Is, gb_sets:add(X, D));
-var_list_1([_|Is], D) ->
- var_list_1(Is, D);
-var_list_1([], D) -> D.
-
-%%%
-%%% Convert a block to Static Single Assignment (SSA) form.
-%%%
-
--record(ssa,
- {live,
- sub}).
-
-ssa_block(Is0) ->
- Next = ssa_first_free(Is0, 0),
- {Is,_} = ssa_block_1(Is0, #ssa{live=Next,sub=gb_trees:empty()}, []),
- Is.
-
-ssa_block_1([{protected,[_],Pa0,Pb}|Is], Sub0, Acc) ->
- {Pa,Sub} = ssa_block_1(Pa0, Sub0, []),
- Dst = ssa_last_target(Pa),
- ssa_block_1(Is, Sub, [{protected,[Dst],Pa,Pb}|Acc]);
-ssa_block_1([{set,[Dst],As,Bif}|Is], Sub0, Acc0) ->
- Sub1 = ssa_in_use_list(As, Sub0),
- Sub = ssa_assign(Dst, Sub1),
- Acc = [{set,[ssa_sub(Dst, Sub)],ssa_sub_list(As, Sub0),Bif}|Acc0],
- ssa_block_1(Is, Sub, Acc);
-ssa_block_1([], Sub, Acc) -> {reverse(Acc),Sub}.
-
-ssa_in_use_list(As, Sub) ->
- foldl(fun ssa_in_use/2, Sub, As).
-
-ssa_in_use({x,_}=R, #ssa{sub=Sub0}=Ssa) ->
- case gb_trees:is_defined(R, Sub0) of
- true -> Ssa;
- false ->
- Sub = gb_trees:insert(R, R, Sub0),
- Ssa#ssa{sub=Sub}
- end;
-ssa_in_use(_, Ssa) -> Ssa.
-
-ssa_assign({x,_}=R, #ssa{sub=Sub0}=Ssa0) ->
- case gb_trees:is_defined(R, Sub0) of
- false ->
- Sub = gb_trees:insert(R, R, Sub0),
- Ssa0#ssa{sub=Sub};
- true ->
- {NewReg,Ssa} = ssa_new_reg(Ssa0),
- Sub1 = gb_trees:update(R, NewReg, Sub0),
- Sub = gb_trees:insert(NewReg, NewReg, Sub1),
- Ssa#ssa{sub=Sub}
- end;
-ssa_assign(_, Ssa) -> Ssa.
-
-ssa_sub_list(List, Sub) ->
- [ssa_sub(E, Sub) || E <- List].
-
-ssa_sub(R0, #ssa{sub=Sub}) ->
- case gb_trees:lookup(R0, Sub) of
- none -> R0;
- {value,R} -> R
- end.
-
-ssa_new_reg(#ssa{live=Reg}=Ssa) ->
- {{x,Reg},Ssa#ssa{live=Reg+1}}.
-
-ssa_first_free([{protected,Ds,_,_}|Is], Next0) ->
- Next = ssa_first_free_list(Ds, Next0),
- ssa_first_free(Is, Next);
-ssa_first_free([{set,[Dst],As,_}|Is], Next0) ->
- Next = ssa_first_free_list([Dst|As], Next0),
- ssa_first_free(Is, Next);
-ssa_first_free([], Next) -> Next.
-
-ssa_first_free_list(Regs, Next) ->
- foldl(fun({x,R}, N) when R >= N -> R+1;
- (_, N) -> N end, Next, Regs).
-
-ssa_last_target([{set,[Dst],_,_},{'%live',_}]) -> Dst;
-ssa_last_target([{set,[Dst],_,_}]) -> Dst;
-ssa_last_target([_|Is]) -> ssa_last_target(Is).
-
-%% index_instructions(FunctionIs) -> GbTree([{Label,Is}])
-%% Index the instruction sequence so that we can quickly
-%% look up the instruction following a specific label.
-
-index_instructions(Is) ->
- ii_1(Is, []).
-
-ii_1([{label,Lbl}|Is0], Acc) ->
- Is = lists:dropwhile(fun({label,_}) -> true;
- (_) -> false end, Is0),
- ii_1(Is0, [{Lbl,Is}|Acc]);
-ii_1([_|Is], Acc) ->
- ii_1(Is, Acc);
-ii_1([], Acc) -> gb_trees:from_orddict(sort(Acc)).
-
-%% is_killed(Register, [Instruction], State) -> true|false
-%% Determine whether a register is killed in the instruction sequence.
-%% The state is used to allow us to determine the kill state
-%% across branches.
-
-is_killed(R, Is, St) ->
- case is_killed_1(R, Is, St) of
- false ->
- %%io:format("nk ~p: ~P\n", [R,Is,15]),
- false;
- true -> true
- end.
-
-is_killed_1(R, [{block,Blk}|Is], St) ->
- case is_killed_1(R, Blk, St) of
- true -> true;
- false -> is_killed_1(R, Is, St)
- end;
-is_killed_1(R, [{test,_,{f,Fail},As}|Is], St) ->
- case not member(R, As) andalso is_reg_killed_at(R, Fail, St) of
- false -> false;
- true -> is_killed_1(R, Is, St)
- end;
-is_killed_1(R, [{select_val,R,_,_}|_], _) -> false;
-is_killed_1(R, [{select_val,_,Fail,{list,Branches}}|_], St) ->
- is_killed_at_all(R, [Fail|Branches], St);
-is_killed_1(R, [{jump,{f,F}}|_], St) ->
- is_reg_killed_at(R, F, St);
-is_killed_1(Reg, Is, _) ->
- beam_block:is_killed(Reg, Is).
-
-is_reg_killed_at(R, Lbl, #st{ll=Ll}=St) ->
- Is = gb_trees:get(Lbl, Ll),
- is_killed_1(R, Is, St).
-
-is_killed_at_all(R, [{f,Lbl}|T], St) ->
- case is_reg_killed_at(R, Lbl, St) of
- false -> false;
- true -> is_killed_at_all(R, T, St)
- end;
-is_killed_at_all(R, [_|T], St) ->
- is_killed_at_all(R, T, St);
-is_killed_at_all(_, [], _) -> true.
-
-%% is_not_used(Register, [Instruction], State) -> true|false
-%% Determine whether a register is never used in the instruction sequence
-%% (it could still referenced by an allocate instruction, meaning that
-%% it MUST be initialized).
-%% The state is used to allow us to determine the usage state
-%% across branches.
-
-is_not_used(R, Is, St) ->
- case is_not_used_1(R, Is, St) of
- false ->
- %%io:format("used ~p: ~P\n", [R,Is,15]),
- false;
- true -> true
- end.
-
-is_not_used_1(R, [{block,Blk}|Is], St) ->
- case is_not_used_1(R, Blk, St) of
- true -> true;
- false -> is_not_used_1(R, Is, St)
- end;
-is_not_used_1(R, [{test,_,{f,Fail},As}|Is], St) ->
- case not member(R, As) andalso is_reg_not_used_at(R, Fail, St) of
- false -> false;
- true -> is_not_used_1(R, Is, St)
- end;
-is_not_used_1(R, [{select_val,R,_,_}|_], _) -> false;
-is_not_used_1(R, [{select_val,_,Fail,{list,Branches}}|_], St) ->
- is_used_at_none(R, [Fail|Branches], St);
-is_not_used_1(R, [{jump,{f,F}}|_], St) ->
- is_reg_not_used_at(R, F, St);
-is_not_used_1(Reg, Is, _) ->
- beam_block:is_not_used(Reg, Is).
-
-is_reg_not_used_at(R, Lbl, #st{ll=Ll}=St) ->
- Is = gb_trees:get(Lbl, Ll),
- is_not_used_1(R, Is, St).
-
-is_used_at_none(R, [{f,Lbl}|T], St) ->
- case is_reg_not_used_at(R, Lbl, St) of
- false -> false;
- true -> is_used_at_none(R, T, St)
- end;
-is_used_at_none(R, [_|T], St) ->
- is_used_at_none(R, T, St);
-is_used_at_none(_, [], _) -> true.
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_clean.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_clean.erl
deleted file mode 100644
index d47ae9c896..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_clean.erl
+++ /dev/null
@@ -1,232 +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: beam_clean.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
-%%
-%% Purpose : Clean up, such as removing unused labels and unused functions.
-
--module(beam_clean).
-
--export([module/2]).
--import(lists, [member/2,map/2,foldl/3,mapfoldl/3,reverse/1]).
-
-module({Mod,Exp,Attr,Fs0,_}, _Opt) ->
- Order = [Lbl || {function,_,_,Lbl,_} <- Fs0],
- All = foldl(fun({function,_,_,Lbl,_}=Func,D) -> dict:store(Lbl, Func, D) end,
- dict:new(), Fs0),
- {WorkList,Used0} = exp_to_labels(Fs0, Exp),
- Used = find_all_used(WorkList, All, Used0),
- Fs1 = remove_unused(Order, Used, All),
- {Fs,Lc} = clean_labels(Fs1),
- {ok,{Mod,Exp,Attr,Fs,Lc}}.
-
-%% Convert the export list ({Name,Arity} pairs) to a list of entry labels.
-
-exp_to_labels(Fs, Exp) -> exp_to_labels(Fs, Exp, [], sets:new()).
-
-exp_to_labels([{function,Name,Arity,Lbl,_}|Fs], Exp, Acc, Used) ->
- case member({Name,Arity}, Exp) of
- true -> exp_to_labels(Fs, Exp, [Lbl|Acc], sets:add_element(Lbl, Used));
- false -> exp_to_labels(Fs, Exp, Acc, Used)
- end;
-exp_to_labels([], _, Acc, Used) -> {Acc,Used}.
-
-%% Remove the unused functions.
-
-remove_unused([F|Fs], Used, All) ->
- case sets:is_element(F, Used) of
- false -> remove_unused(Fs, Used, All);
- true -> [dict:fetch(F, All)|remove_unused(Fs, Used, All)]
- end;
-remove_unused([], _, _) -> [].
-
-%% Find all used functions.
-
-find_all_used([F|Fs0], All, Used0) ->
- {function,_,_,_,Code} = dict:fetch(F, All),
- {Fs,Used} = update_work_list(Code, {Fs0,Used0}),
- find_all_used(Fs, All, Used);
-find_all_used([], _All, Used) -> Used.
-
-update_work_list([{call,_,{f,L}}|Is], Sets) ->
- update_work_list(Is, add_to_work_list(L, Sets));
-update_work_list([{call_last,_,{f,L},_}|Is], Sets) ->
- update_work_list(Is, add_to_work_list(L, Sets));
-update_work_list([{call_only,_,{f,L}}|Is], Sets) ->
- update_work_list(Is, add_to_work_list(L, Sets));
-update_work_list([{make_fun,{f,L},_,_}|Is], Sets) ->
- update_work_list(Is, add_to_work_list(L, Sets));
-update_work_list([{make_fun2,{f,L},_,_,_}|Is], Sets) ->
- update_work_list(Is, add_to_work_list(L, Sets));
-update_work_list([_|Is], Sets) ->
- update_work_list(Is, Sets);
-update_work_list([], Sets) -> Sets.
-
-add_to_work_list(F, {Fs,Used}=Sets) ->
- case sets:is_element(F, Used) of
- true -> Sets;
- false -> {[F|Fs],sets:add_element(F, Used)}
- end.
-
-
-%%%
-%%% Coalesce adjacent labels. Renumber all labels to eliminate gaps.
-%%% This cleanup will slightly reduce file size and slightly speed up loading.
-%%%
-%%% We also expand internal_is_record/3 to a sequence of instructions. It is done
-%%% here merely because this module will always be called even if optimization
-%%% is turned off. We don't want to do the expansion in beam_asm because we
-%%% want to see the expanded code in a .S file.
-%%%
-
--record(st, {lmap, %Translation tables for labels.
- entry, %Number of entry label.
- lc %Label counter
- }).
-
-clean_labels(Fs0) ->
- St0 = #st{lmap=dict:new(),lc=1},
- {Fs1,#st{lmap=Lmap,lc=Lc}} = mapfoldl(fun function_renumber/2, St0, Fs0),
- {map(fun(F) -> function_replace(F, Lmap) end, Fs1),Lc}.
-
-function_renumber({function,Name,Arity,_Entry,Asm0}, St0) ->
- {Asm,St} = renumber_labels(Asm0, [], St0),
- {{function,Name,Arity,St#st.entry,Asm},St}.
-
-renumber_labels([{bif,internal_is_record,{f,_},
- [Term,Tag,{integer,Arity}],Dst}|Is], Acc, St) ->
- ContLabel = 900000000+2*St#st.lc,
- FailLabel = ContLabel+1,
- Fail = {f,FailLabel},
- Tmp = Dst,
- renumber_labels([{test,is_tuple,Fail,[Term]},
- {test,test_arity,Fail,[Term,Arity]},
- {get_tuple_element,Term,0,Tmp},
- {test,is_eq_exact,Fail,[Tmp,Tag]},
- {move,{atom,true},Dst},
- {jump,{f,ContLabel}},
- {label,FailLabel},
- {move,{atom,false},Dst},
- {label,ContLabel}|Is], Acc, St);
-renumber_labels([{test,internal_is_record,{f,_}=Fail,
- [Term,Tag,{integer,Arity}]}|Is], Acc, St) ->
- Tmp = {x,1023},
- case Term of
- {Reg,_} when Reg == x; Reg == y ->
- renumber_labels([{test,is_tuple,Fail,[Term]},
- {test,test_arity,Fail,[Term,Arity]},
- {get_tuple_element,Term,0,Tmp},
- {test,is_eq_exact,Fail,[Tmp,Tag]}|Is], Acc, St);
- _ ->
- renumber_labels([{jump,Fail}|Is], Acc, St)
- end;
-renumber_labels([{label,Old}|Is], [{label,New}|_]=Acc, #st{lmap=D0}=St) ->
- D = dict:store(Old, New, D0),
- renumber_labels(Is, Acc, St#st{lmap=D});
-renumber_labels([{label,Old}|Is], Acc, St0) ->
- New = St0#st.lc,
- D = dict:store(Old, New, St0#st.lmap),
- renumber_labels(Is, [{label,New}|Acc], St0#st{lmap=D,lc=New+1});
-renumber_labels([{func_info,_,_,_}=Fi|Is], Acc, St0) ->
- renumber_labels(Is, [Fi|Acc], St0#st{entry=St0#st.lc});
-renumber_labels([I|Is], Acc, St0) ->
- renumber_labels(Is, [I|Acc], St0);
-renumber_labels([], Acc, St0) -> {Acc,St0}.
-
-function_replace({function,Name,Arity,Entry,Asm0}, Dict) ->
- Asm = case catch replace(Asm0, [], Dict) of
- {'EXIT',_}=Reason ->
- exit(Reason);
- {error,{undefined_label,Lbl}=Reason} ->
- io:format("Function ~s/~w refers to undefined label ~w\n",
- [Name,Arity,Lbl]),
- exit(Reason);
- Asm1 when list(Asm1) -> Asm1
- end,
- {function,Name,Arity,Entry,Asm}.
-
-replace([{test,Test,{f,Lbl},Ops}|Is], Acc, D) ->
- replace(Is, [{test,Test,{f,label(Lbl, D)},Ops}|Acc], D);
-replace([{select_val,R,{f,Fail0},{list,Vls0}}|Is], Acc, D) ->
- Vls1 = map(fun ({f,L}) -> {f,label(L, D)};
- (Other) -> Other end, Vls0),
- Fail = label(Fail0, D),
- case redundant_values(Vls1, Fail, []) of
- [] ->
- %% Oops, no choices left. The loader will not accept that.
- %% Convert to a plain jump.
- replace(Is, [{jump,{f,Fail}}|Acc], D);
- Vls ->
- replace(Is, [{select_val,R,{f,Fail},{list,Vls}}|Acc], D)
- end;
-replace([{select_tuple_arity,R,{f,Fail},{list,Vls0}}|Is], Acc, D) ->
- Vls = map(fun ({f,L}) -> {f,label(L, D)};
- (Other) -> Other end, Vls0),
- replace(Is, [{select_tuple_arity,R,{f,label(Fail, D)},{list,Vls}}|Acc], D);
-replace([{'try',R,{f,Lbl}}|Is], Acc, D) ->
- replace(Is, [{'try',R,{f,label(Lbl, D)}}|Acc], D);
-replace([{'catch',R,{f,Lbl}}|Is], Acc, D) ->
- replace(Is, [{'catch',R,{f,label(Lbl, D)}}|Acc], D);
-replace([{jump,{f,Lbl}}|Is], Acc, D) ->
- replace(Is, [{jump,{f,label(Lbl, D)}}|Acc], D);
-replace([{loop_rec,{f,Lbl},R}|Is], Acc, D) ->
- replace(Is, [{loop_rec,{f,label(Lbl, D)},R}|Acc], D);
-replace([{loop_rec_end,{f,Lbl}}|Is], Acc, D) ->
- replace(Is, [{loop_rec_end,{f,label(Lbl, D)}}|Acc], D);
-replace([{wait,{f,Lbl}}|Is], Acc, D) ->
- replace(Is, [{wait,{f,label(Lbl, D)}}|Acc], D);
-replace([{wait_timeout,{f,Lbl},To}|Is], Acc, D) ->
- replace(Is, [{wait_timeout,{f,label(Lbl, D)},To}|Acc], D);
-replace([{bif,Name,{f,Lbl},As,R}|Is], Acc, D) when Lbl =/= 0 ->
- replace(Is, [{bif,Name,{f,label(Lbl, D)},As,R}|Acc], D);
-replace([{call,Ar,{f,Lbl}}|Is], Acc, D) ->
- replace(Is, [{call,Ar,{f,label(Lbl,D)}}|Acc], D);
-replace([{call_last,Ar,{f,Lbl},N}|Is], Acc, D) ->
- replace(Is, [{call_last,Ar,{f,label(Lbl,D)},N}|Acc], D);
-replace([{call_only,Ar,{f,Lbl}}|Is], Acc, D) ->
- replace(Is, [{call_only,Ar,{f,label(Lbl, D)}}|Acc], D);
-replace([{make_fun,{f,Lbl},U1,U2}|Is], Acc, D) ->
- replace(Is, [{make_fun,{f,label(Lbl, D)},U1,U2}|Acc], D);
-replace([{make_fun2,{f,Lbl},U1,U2,U3}|Is], Acc, D) ->
- replace(Is, [{make_fun2,{f,label(Lbl, D)},U1,U2,U3}|Acc], D);
-replace([{bs_init2,{f,Lbl},Sz,Words,R,F,Dst}|Is], Acc, D) when Lbl =/= 0 ->
- replace(Is, [{bs_init2,{f,label(Lbl, D)},Sz,Words,R,F,Dst}|Acc], D);
-replace([{bs_put_integer,{f,Lbl},Bits,Unit,Fl,Val}|Is], Acc, D) when Lbl =/= 0 ->
- replace(Is, [{bs_put_integer,{f,label(Lbl, D)},Bits,Unit,Fl,Val}|Acc], D);
-replace([{bs_put_binary,{f,Lbl},Bits,Unit,Fl,Val}|Is], Acc, D) when Lbl =/= 0 ->
- replace(Is, [{bs_put_binary,{f,label(Lbl, D)},Bits,Unit,Fl,Val}|Acc], D);
-replace([{bs_put_float,{f,Lbl},Bits,Unit,Fl,Val}|Is], Acc, D) when Lbl =/= 0 ->
- replace(Is, [{bs_put_float,{f,label(Lbl, D)},Bits,Unit,Fl,Val}|Acc], D);
-replace([{bs_final,{f,Lbl},R}|Is], Acc, D) when Lbl =/= 0 ->
- replace(Is, [{bs_final,{f,label(Lbl, D)},R}|Acc], D);
-replace([{bs_add,{f,Lbl},Src,Dst}|Is], Acc, D) when Lbl =/= 0 ->
- replace(Is, [{bs_add,{f,label(Lbl, D)},Src,Dst}|Acc], D);
-replace([{bs_bits_to_bytes,{f,Lbl},Bits,Dst}|Is], Acc, D) when Lbl =/= 0 ->
- replace(Is, [{bs_bits_to_bytes,{f,label(Lbl, D)},Bits,Dst}|Acc], D);
-replace([I|Is], Acc, D) ->
- replace(Is, [I|Acc], D);
-replace([], Acc, _) -> Acc.
-
-label(Old, D) ->
- case dict:find(Old, D) of
- {ok,Val} -> Val;
- error -> throw({error,{undefined_label,Old}})
- end.
-
-redundant_values([_,{f,Fail}|Vls], Fail, Acc) ->
- redundant_values(Vls, Fail, Acc);
-redundant_values([Val,Lbl|Vls], Fail, Acc) ->
- redundant_values(Vls, Fail, [Lbl,Val|Acc]);
-redundant_values([], _, Acc) -> reverse(Acc).
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_dict.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_dict.erl
deleted file mode 100644
index ddab957704..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_dict.erl
+++ /dev/null
@@ -1,196 +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: beam_dict.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
-%%
-%% Purpose : Maintain atom, import, and export tables for assembler.
-
--module(beam_dict).
-
--export([new/0, opcode/2, highest_opcode/1,
- atom/2, local/4, export/4, import/4, string/2, lambda/5,
- atom_table/1, local_table/1, export_table/1, import_table/1,
- string_table/1,lambda_table/1]).
-
--record(asm_dict,
- {atoms = [], % [{Index, Atom}]
- exports = [], % [{F, A, Label}]
- locals = [], % [{F, A, Label}]
- imports = [], % [{Index, {M, F, A}]
- strings = [], % Deep list of characters
- lambdas = [], % [{...}]
- next_atom = 1,
- next_import = 0,
- string_offset = 0,
- highest_opcode = 0
- }).
-
-new() ->
- #asm_dict{}.
-
-%% Remembers highest opcode.
-
-opcode(Op, Dict) when Dict#asm_dict.highest_opcode > Op -> Dict;
-opcode(Op, Dict) -> Dict#asm_dict{highest_opcode=Op}.
-
-%% Returns the highest opcode encountered.
-
-highest_opcode(#asm_dict{highest_opcode=Op}) -> Op.
-
-%% Returns the index for an atom (adding it to the atom table if necessary).
-%% atom(Atom, Dict) -> {Index, Dict'}
-
-atom(Atom, Dict) when atom(Atom) ->
- NextIndex = Dict#asm_dict.next_atom,
- case lookup_store(Atom, Dict#asm_dict.atoms, NextIndex) of
- {Index, _, NextIndex} ->
- {Index, Dict};
- {Index, Atoms, NewIndex} ->
- {Index, Dict#asm_dict{atoms=Atoms, next_atom=NewIndex}}
- end.
-
-%% Remembers an exported function.
-%% export(Func, Arity, Label, Dict) -> Dict'
-
-export(Func, Arity, Label, Dict0) when atom(Func), integer(Arity), integer(Label) ->
- {Index, Dict1} = atom(Func, Dict0),
- Dict1#asm_dict{exports = [{Index, Arity, Label}| Dict1#asm_dict.exports]}.
-
-%% Remembers a local function.
-%% local(Func, Arity, Label, Dict) -> Dict'
-
-local(Func, Arity, Label, Dict0) when atom(Func), integer(Arity), integer(Label) ->
- {Index,Dict1} = atom(Func, Dict0),
- Dict1#asm_dict{locals = [{Index,Arity,Label}| Dict1#asm_dict.locals]}.
-
-%% Returns the index for an import entry (adding it to the import table if necessary).
-%% import(Mod, Func, Arity, Dict) -> {Index, Dict'}
-
-import(Mod, Func, Arity, Dict) when atom(Mod), atom(Func), integer(Arity) ->
- NextIndex = Dict#asm_dict.next_import,
- case lookup_store({Mod, Func, Arity}, Dict#asm_dict.imports, NextIndex) of
- {Index, _, NextIndex} ->
- {Index, Dict};
- {Index, Imports, NewIndex} ->
- {_, D1} = atom(Mod, Dict#asm_dict{imports=Imports, next_import=NewIndex}),
- {_, D2} = atom(Func, D1),
- {Index, D2}
- end.
-
-%% Returns the index for a string in the string table (adding the string to the
-%% table if necessary).
-%% string(String, Dict) -> {Offset, Dict'}
-
-string(Str, Dict) when list(Str) ->
- #asm_dict{strings = Strings, string_offset = NextOffset} = Dict,
- case old_string(Str, Strings) of
- {true, Offset} ->
- {Offset, Dict};
- false ->
- NewDict = Dict#asm_dict{strings = Strings++Str,
- string_offset = NextOffset+length(Str)},
- {NextOffset, NewDict}
- end.
-
-%% Returns the index for a funentry (adding it to the table if necessary).
-%% lambda(Dict, Lbl, Index, Uniq, NumFree) -> {Index,Dict'}
-
-lambda(Lbl, Index, OldUniq, NumFree, #asm_dict{lambdas=Lambdas0}=Dict) ->
- OldIndex = length(Lambdas0),
- Lambdas = [{Lbl,{OldIndex,Lbl,Index,NumFree,OldUniq}}|Lambdas0],
- {OldIndex,Dict#asm_dict{lambdas=Lambdas}}.
-
-%% Returns the atom table.
-%% atom_table(Dict) -> [Length,AtomString...]
-
-atom_table(#asm_dict{atoms=Atoms, next_atom=NumAtoms}) ->
- Sorted = lists:sort(Atoms),
- Fun = fun({_, A}) ->
- L = atom_to_list(A),
- [length(L)|L]
- end,
- {NumAtoms-1, lists:map(Fun, Sorted)}.
-
-%% Returns the table of local functions.
-%% local_table(Dict) -> {NumLocals, [{Function, Arity, Label}...]}
-
-local_table(#asm_dict{locals = Locals}) ->
- {length(Locals),Locals}.
-
-%% Returns the export table.
-%% export_table(Dict) -> {NumExports, [{Function, Arity, Label}...]}
-
-export_table(#asm_dict{exports = Exports}) ->
- {length(Exports), Exports}.
-
-%% Returns the import table.
-%% import_table(Dict) -> {NumImports, [{Module, Function, Arity}...]}
-
-import_table(Dict) ->
- #asm_dict{imports = Imports, next_import = NumImports} = Dict,
- Sorted = lists:sort(Imports),
- Fun = fun({_, {Mod, Func, Arity}}) ->
- {Atom0, _} = atom(Mod, Dict),
- {Atom1, _} = atom(Func, Dict),
- {Atom0, Atom1, Arity}
- end,
- {NumImports, lists:map(Fun, Sorted)}.
-
-string_table(#asm_dict{strings = Strings, string_offset = Size}) ->
- {Size, Strings}.
-
-lambda_table(#asm_dict{locals=Loc0,lambdas=Lambdas0}) ->
- Lambdas1 = sofs:relation(Lambdas0),
- Loc = sofs:relation([{Lbl,{F,A}} || {F,A,Lbl} <- Loc0]),
- Lambdas2 = sofs:relative_product1(Lambdas1, Loc),
- Lambdas = [<<F:32,A:32,Lbl:32,Index:32,NumFree:32,OldUniq:32>> ||
- {{_,Lbl,Index,NumFree,OldUniq},{F,A}} <- sofs:to_external(Lambdas2)],
- {length(Lambdas),Lambdas}.
-
-%%% Local helper functions.
-
-lookup_store(Key, Dict, NextIndex) ->
- case catch lookup_store1(Key, Dict, NextIndex) of
- Index when integer(Index) ->
- {Index, Dict, NextIndex};
- {Index, NewDict} ->
- {Index, NewDict, NextIndex+1}
- end.
-
-lookup_store1(Key, [Pair|Dict], NextIndex) when Key > element(2, Pair) ->
- {Index, NewDict} = lookup_store1(Key, Dict, NextIndex),
- {Index, [Pair|NewDict]};
-lookup_store1(Key, [{Index, Key}|_Dict], _NextIndex) ->
- throw(Index);
-lookup_store1(Key, Dict, NextIndex) ->
- {NextIndex, [{NextIndex, Key}|Dict]}.
-
-%% Search for string Str in the string pool Pool.
-%% old_string(Str, Pool) -> false | {true, Offset}
-
-old_string(Str, Pool) ->
- old_string(Str, Pool, 0).
-
-old_string([C|Str], [C|Pool], Index) ->
- case lists:prefix(Str, Pool) of
- true ->
- {true, Index};
- false ->
- old_string([C|Str], Pool, Index+1)
- end;
-old_string(Str, [_|Pool], Index) ->
- old_string(Str, Pool, Index+1);
-old_string(_Str, [], _Index) ->
- false.
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_disasm.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_disasm.erl
deleted file mode 100644
index 451b83db66..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_disasm.erl
+++ /dev/null
@@ -1,964 +0,0 @@
-%% -*- erlang-indent-level: 4 -*-
-%%=======================================================================
-%% File : beam_disasm.erl
-%% Author : Kostis Sagonas
-%% Description : Disassembles an R5-R10 .beam file into symbolic BEAM code
-%%=======================================================================
-%% $Id: beam_disasm.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
-%%=======================================================================
-%% Notes:
-%% 1. It does NOT work for .beam files of previous BEAM versions.
-%% 2. If handling of new BEAM instructions is needed, this should be
-%% inserted at the end of function resolve_inst().
-%%=======================================================================
-
--module(beam_disasm).
-
--export([file/1, format_error/1]).
-
--author("Kostis Sagonas").
-
--include("beam_opcodes.hrl").
-
-%%-----------------------------------------------------------------------
-
--define(NO_DEBUG(Str,Xs),ok).
--define(DEBUG(Str,Xs),io:format(Str,Xs)).
--define(exit(Reason),exit({?MODULE,?LINE,Reason})).
-
-%%-----------------------------------------------------------------------
-%% Error information
-
-format_error({error, Module, Error}) ->
- Module:format_error(Error);
-format_error({internal, Error}) ->
- io_lib:format("~p: disassembly failed with reason ~P.",
- [?MODULE, Error, 25]).
-
-%%-----------------------------------------------------------------------
-%% The main exported function
-%% File is either a file name or a binary containing the code.
-%% Returns `{beam_file, [...]}' or `{error, Module, Reason}'.
-%% Call `format_error({error, Module, Reason})' for an error string.
-%%-----------------------------------------------------------------------
-
-file(File) ->
- case beam_lib:info(File) of
- Info when list(Info) ->
- {value,{chunks,Chunks}} = lists:keysearch(chunks,1,Info),
- case catch process_chunks(File, Chunks) of
- {'EXIT', Error} ->
- {error, ?MODULE, {internal, Error}};
- Result ->
- Result
- end;
- Error ->
- Error
- end.
-
-%%-----------------------------------------------------------------------
-%% Interface might need to be revised -- do not depend on it.
-%%-----------------------------------------------------------------------
-
-process_chunks(F,ChunkInfoList) ->
- {ok,{_,Chunks}} = beam_lib:chunks(F, ["Atom","Code","StrT","ImpT","ExpT"]),
- [{"Atom",AtomBin},{"Code",CodeBin},{"StrT",StrBin},
- {"ImpT",ImpBin},{"ExpT",ExpBin}] = Chunks,
- LambdaBin = optional_chunk(F, "FunT", ChunkInfoList),
- LocBin = optional_chunk(F, "LocT", ChunkInfoList),
- AttrBin = optional_chunk(F, "Attr", ChunkInfoList),
- CompBin = optional_chunk(F, "CInf", ChunkInfoList),
- Atoms = beam_disasm_atoms(AtomBin),
- Exports = beam_disasm_exports(ExpBin, Atoms),
- Imports = beam_disasm_imports(ImpBin, Atoms),
- LocFuns = beam_disasm_exports(LocBin, Atoms),
- Lambdas = beam_disasm_lambdas(LambdaBin, Atoms),
- Str = beam_disasm_strings(StrBin),
- Str1 = binary_to_list(Str), %% for debugging -- use Str as far as poss.
- Sym_Code = beam_disasm_code(CodeBin,Atoms,Imports,Str,Lambdas),
- Attributes = beam_disasm_attributes(AttrBin),
- CompInfo = beam_disasm_compilation_info(CompBin),
- All = [{exports,Exports},
- {imports,Imports},
- {code,Sym_Code},
- {atoms,Atoms},
- {local_funs,LocFuns},
- {strings,Str1},
- {attributes,Attributes},
- {comp_info,CompInfo}],
- {beam_file,[Item || {_Key,Data}=Item <- All, Data =/= none]}.
-
-%%-----------------------------------------------------------------------
-%% Retrieve an optional chunk or none if the chunk doesn't exist.
-%%-----------------------------------------------------------------------
-
-optional_chunk(F, ChunkTag, ChunkInfo) ->
- case lists:keymember(ChunkTag, 1, ChunkInfo) of
- true ->
- {ok,{_,[{ChunkTag,Chunk}]}} = beam_lib:chunks(F, [ChunkTag]),
- Chunk;
- false -> none
- end.
-
-%%-----------------------------------------------------------------------
-%% UTILITIES -- these actually exist in file "beam_lib"
-%% -- they should be moved into a common utils file.
-%%-----------------------------------------------------------------------
-
-i32([X1,X2,X3,X4]) ->
- (X1 bsl 24) bor (X2 bsl 16) bor (X3 bsl 8) bor X4.
-
-get_int(B) ->
- {I, B1} = split_binary(B, 4),
- {i32(binary_to_list(I)), B1}.
-
-%%-----------------------------------------------------------------------
-%% Disassembles the atom table of a BEAM file.
-%% - atoms are stored in order 1 ... N (N = Num_atoms, in fact),
-%% - each atom name consists of a length byte, followed by that many
-%% bytes of name
-%% (nb: atom names max 255 chars?!)
-%%-----------------------------------------------------------------------
-
-beam_disasm_atoms(AtomTabBin) ->
- {_NumAtoms,B} = get_int(AtomTabBin),
- disasm_atoms(B).
-
-disasm_atoms(AtomBin) ->
- disasm_atoms(binary_to_list(AtomBin),1).
-
-disasm_atoms([Len|Xs],N) ->
- {AtomName,Rest} = get_atom_name(Len,Xs),
- [{N,list_to_atom(AtomName)}|disasm_atoms(Rest,N+1)];
-disasm_atoms([],_) ->
- [].
-
-get_atom_name(Len,Xs) ->
- get_atom_name(Len,Xs,[]).
-
-get_atom_name(N,[X|Xs],RevName) when N > 0 ->
- get_atom_name(N-1,Xs,[X|RevName]);
-get_atom_name(0,Xs,RevName) ->
- { lists:reverse(RevName), Xs }.
-
-%%-----------------------------------------------------------------------
-%% Disassembles the export table of a BEAM file.
-%%-----------------------------------------------------------------------
-
-beam_disasm_exports(none, _) -> none;
-beam_disasm_exports(ExpTabBin, Atoms) ->
- {_NumAtoms,B} = get_int(ExpTabBin),
- disasm_exports(B,Atoms).
-
-disasm_exports(Bin,Atoms) ->
- resolve_exports(collect_exports(binary_to_list(Bin)),Atoms).
-
-collect_exports([F3,F2,F1,F0,A3,A2,A1,A0,L3,L2,L1,L0|Exps]) ->
- [{i32([F3,F2,F1,F0]), % F = function (atom ID)
- i32([A3,A2,A1,A0]), % A = arity (int)
- i32([L3,L2,L1,L0])} % L = label (int)
- |collect_exports(Exps)];
-collect_exports([]) ->
- [].
-
-resolve_exports(Exps,Atoms) ->
- [ {lookup_key(F,Atoms), A, L} || {F,A,L} <- Exps ].
-
-%%-----------------------------------------------------------------------
-%% Disassembles the import table of a BEAM file.
-%%-----------------------------------------------------------------------
-
-beam_disasm_imports(ExpTabBin,Atoms) ->
- {_NumAtoms,B} = get_int(ExpTabBin),
- disasm_imports(B,Atoms).
-
-disasm_imports(Bin,Atoms) ->
- resolve_imports(collect_imports(binary_to_list(Bin)),Atoms).
-
-collect_imports([M3,M2,M1,M0,F3,F2,F1,F0,A3,A2,A1,A0|Exps]) ->
- [{i32([M3,M2,M1,M0]), % M = module (atom ID)
- i32([F3,F2,F1,F0]), % F = function (atom ID)
- i32([A3,A2,A1,A0])} % A = arity (int)
- |collect_imports(Exps)];
-collect_imports([]) ->
- [].
-
-resolve_imports(Exps,Atoms) ->
- [{extfunc,lookup_key(M,Atoms),lookup_key(F,Atoms),A} || {M,F,A} <- Exps ].
-
-%%-----------------------------------------------------------------------
-%% Disassembles the lambda (fun) table of a BEAM file.
-%%-----------------------------------------------------------------------
-
-beam_disasm_lambdas(none, _) -> none;
-beam_disasm_lambdas(<<_:32,Tab/binary>>, Atoms) ->
- disasm_lambdas(Tab, Atoms, 0).
-
-disasm_lambdas(<<F:32,A:32,Lbl:32,Index:32,NumFree:32,OldUniq:32,More/binary>>,
- Atoms, OldIndex) ->
- Info = {lookup_key(F, Atoms),A,Lbl,Index,NumFree,OldUniq},
- [{OldIndex,Info}|disasm_lambdas(More, Atoms, OldIndex+1)];
-disasm_lambdas(<<>>, _, _) -> [].
-
-%%-----------------------------------------------------------------------
-%% Disassembles the code chunk of a BEAM file:
-%% - The code is first disassembled into a long list of instructions.
-%% - This list is then split into functions and all names are resolved.
-%%-----------------------------------------------------------------------
-
-beam_disasm_code(CodeBin,Atoms,Imports,Str,Lambdas) ->
- [_SS3,_SS2,_SS1,_SS0, % Sub-Size (length of information before code)
- _IS3,_IS2,_IS1,_IS0, % Instruction Set Identifier (always 0)
- _OM3,_OM2,_OM1,_OM0, % Opcode Max
- _L3,_L2,_L1,_L0,_F3,_F2,_F1,_F0|Code] = binary_to_list(CodeBin),
- case catch disasm_code(Code, Atoms) of
- {'EXIT',Rsn} ->
- ?NO_DEBUG('code disasm failed: ~p~n',[Rsn]),
- ?exit(Rsn);
- DisasmCode ->
- Functions = get_function_chunks(DisasmCode),
- LocLabels = local_labels(Functions),
- [resolve_names(F,Imports,Str,LocLabels,Lambdas) || F <- Functions]
- end.
-
-%%-----------------------------------------------------------------------
-
-disasm_code([B|Bs], Atoms) ->
- {Instr,RestBs} = disasm_instr(B, Bs, Atoms),
- [Instr|disasm_code(RestBs, Atoms)];
-disasm_code([], _) -> [].
-
-%%-----------------------------------------------------------------------
-%% Splits the code stream into chunks representing the code of functions.
-%%
-%% NOTE: code actually looks like
-%% label L1: ... label Ln:
-%% func_info ...
-%% label entry:
-%% ...
-%% <on failure, use label Li to show where things died>
-%% ...
-%% So the labels before each func_info should be included as well.
-%% Ideally, only one such label is needed, but the BEAM compiler
-%% before R8 didn't care to remove the redundant ones.
-%%-----------------------------------------------------------------------
-
-get_function_chunks([I|Code]) ->
- {LastI,RestCode,Labs} = split_head_labels(I,Code,[]),
- get_funs(LastI,RestCode,Labs,[]);
-get_function_chunks([]) ->
- ?exit(empty_code_segment).
-
-get_funs(PrevI,[I|Is],RevF,RevFs) ->
- case I of
- {func_info,_Info} ->
- [H|T] = RevF,
- {Last,Fun,TrailingLabels} = split_head_labels(H,T,[]),
- get_funs(I, Is, [PrevI|TrailingLabels], add_funs([Last|Fun],RevFs));
- _ ->
- get_funs(I, Is, [PrevI|RevF], RevFs)
- end;
-get_funs(PrevI,[],RevF,RevFs) ->
- case PrevI of
- {int_code_end,[]} ->
- emit_funs(add_fun(RevF,RevFs));
- _ ->
- ?DEBUG('warning: code segment did not end with int_code_end~n',[]),
- emit_funs(add_funs([PrevI|RevF],RevFs))
- end.
-
-split_head_labels({label,L},[I|Code],Labs) ->
- split_head_labels(I,Code,[{label,L}|Labs]);
-split_head_labels(I,Code,Labs) ->
- {I,Code,Labs}.
-
-add_fun([],Fs) ->
- Fs;
-add_fun(F,Fs) ->
- add_funs(F,Fs).
-
-add_funs(F,Fs) ->
- [ lists:reverse(F) | Fs ].
-
-emit_funs(Fs) ->
- lists:reverse(Fs).
-
-%%-----------------------------------------------------------------------
-%% Collects local labels -- I am not sure this is 100% what is needed.
-%%-----------------------------------------------------------------------
-
-local_labels(Funs) ->
- [local_label(Fun) || Fun <- Funs].
-
-%% The first clause below attempts to provide some (limited form of)
-%% backwards compatibility; it is not needed for .beam files generated
-%% by the R8 compiler. The clause should one fine day be taken out.
-local_label([{label,_},{label,L}|Code]) ->
- local_label([{label,L}|Code]);
-local_label([{label,_},
- {func_info,[M0,F0,{u,A}]},
- {label,[{u,L1}]}|_]) ->
- {atom,M} = resolve_arg(M0),
- {atom,F} = resolve_arg(F0),
- {L1, {M, F, A}};
-local_label(Code) ->
- io:format('beam_disasm: no label in ~p~n', [Code]),
- {-666,{none,none,0}}.
-
-%%-----------------------------------------------------------------------
-%% Disassembles a single BEAM instruction; most instructions are handled
-%% in a generic way; indexing instructions are handled separately.
-%%-----------------------------------------------------------------------
-
-disasm_instr(B, Bs, Atoms) ->
- {SymOp,Arity} = beam_opcodes:opname(B),
- case SymOp of
- select_val ->
- disasm_select_inst(select_val, Bs, Atoms);
- select_tuple_arity ->
- disasm_select_inst(select_tuple_arity, Bs, Atoms);
- _ ->
- case catch decode_n_args(Arity, Bs, Atoms) of
- {'EXIT',Rsn} ->
- ?NO_DEBUG("decode_n_args(~p,~p) failed~n",[Arity,Bs]),
- {{'EXIT',{SymOp,Arity,Rsn}},[]};
- {Args,RestBs} ->
- ?NO_DEBUG("instr ~p~n",[{SymOp,Args}]),
- {{SymOp,Args}, RestBs}
- end
- end.
-
-%%-----------------------------------------------------------------------
-%% Disassembles a BEAM select_* instruction used for indexing.
-%% Currently handles {select_val,3} and {select_tuple_arity,3} insts.
-%%
-%% The arruments of a "select"-type instruction look as follows:
-%% <reg>, {f,FailLabel}, {list, <num cases>, [<case1> ... <caseN>]}
-%% where each case is of the form [symbol,{f,Label}].
-%%-----------------------------------------------------------------------
-
-disasm_select_inst(Inst, Bs, Atoms) ->
- {X, Bs1} = decode_arg(Bs, Atoms),
- {F, Bs2} = decode_arg(Bs1, Atoms),
- {Z, Bs3} = decode_arg(Bs2, Atoms),
- {U, Bs4} = decode_arg(Bs3, Atoms),
- {u,Len} = U,
- {List, RestBs} = decode_n_args(Len, Bs4, Atoms),
- {{Inst,[X,F,{Z,U,List}]},RestBs}.
-
-%%-----------------------------------------------------------------------
-%% decode_arg([Byte]) -> { Arg, [Byte] }
-%%
-%% - an arg can have variable length, so we must return arg + remaining bytes
-%% - decodes an argument into its 'raw' form: { Tag, Value }
-%% several types map to a single tag, so the byte code instr must then
-%% assign a type to it
-%%-----------------------------------------------------------------------
-
-decode_arg([B|Bs]) ->
- Tag = decode_tag(B band 2#111),
- ?NO_DEBUG('Tag = ~p, B = ~p, Bs = ~p~n',[Tag,B,Bs]),
- case Tag of
- z ->
- decode_z_tagged(Tag, B, Bs);
- _ ->
- %% all other cases are handled as if they were integers
- decode_int(Tag, B, Bs)
- end.
-
-decode_arg([B|Bs0], Atoms) ->
- Tag = decode_tag(B band 2#111),
- ?NO_DEBUG('Tag = ~p, B = ~p, Bs = ~p~n',[Tag,B,Bs]),
- case Tag of
- z ->
- decode_z_tagged(Tag, B, Bs0);
- a ->
- %% atom or nil
- case decode_int(Tag, B, Bs0) of
- {{a,0},Bs} -> {nil,Bs};
- {{a,I},Bs} -> {{atom,lookup_key(I, Atoms)},Bs}
- end;
- _ ->
- %% all other cases are handled as if they were integers
- decode_int(Tag, B, Bs0)
- end.
-
-%%-----------------------------------------------------------------------
-%% Decodes an integer value. Handles positives, negatives, and bignums.
-%%
-%% Tries to do the opposite of:
-%% beam_asm:encode(1, 5) = [81]
-%% beam_asm:encode(1, 1000) = [105,232]
-%% beam_asm:encode(1, 2047) = [233,255]
-%% beam_asm:encode(1, 2048) = [25,8,0]
-%% beam_asm:encode(1,-1) = [25,255,255]
-%% beam_asm:encode(1,-4294967295) = [121,255,0,0,0,1]
-%% beam_asm:encode(1, 4294967295) = [121,0,255,255,255,255]
-%% beam_asm:encode(1, 429496729501) = [121,99,255,255,255,157]
-%%-----------------------------------------------------------------------
-
-decode_int(Tag,B,Bs) when (B band 16#08) == 0 ->
- %% N < 16 = 4 bits, NNNN:0:TTT
- N = B bsr 4,
- {{Tag,N},Bs};
-decode_int(Tag,B,Bs) when (B band 16#10) == 0 ->
- %% N < 2048 = 11 bits = 3:8 bits, NNN:01:TTT, NNNNNNNN
- [B1|Bs1] = Bs,
- Val0 = B band 2#11100000,
- N = (Val0 bsl 3) bor B1,
- ?NO_DEBUG('NNN:01:TTT, NNNNNNNN = ~n~p:01:~p, ~p = ~p~n', [Val0,Tag,B,N]),
- {{Tag,N},Bs1};
-decode_int(Tag,B,Bs) ->
- {Len,Bs1} = decode_int_length(B,Bs),
- {IntBs,RemBs} = take_bytes(Len,Bs1),
- N = build_arg(IntBs),
- [F|_] = IntBs,
- Num = if F > 127, Tag == i -> decode_negative(N,Len);
- true -> N
- end,
- ?NO_DEBUG('Len = ~p, IntBs = ~p, Num = ~p~n', [Len,IntBs,Num]),
- {{Tag,Num},RemBs}.
-
-decode_int_length(B,Bs) ->
- %% The following imitates get_erlang_integer() in beam_load.c
- %% Len is the size of the integer value in bytes
- case B bsr 5 of
- 7 ->
- {Arg,ArgBs} = decode_arg(Bs),
- case Arg of
- {u,L} ->
- {L+9,ArgBs}; % 9 stands for 7+2
- _ ->
- ?exit({decode_int,weird_bignum_sublength,Arg})
- end;
- L ->
- {L+2,Bs}
- end.
-
-decode_negative(N,Len) ->
- N - (1 bsl (Len*8)). % 8 is number of bits in a byte
-
-%%-----------------------------------------------------------------------
-%% Decodes lists and floating point numbers.
-%%-----------------------------------------------------------------------
-
-decode_z_tagged(Tag,B,Bs) when (B band 16#08) == 0 ->
- N = B bsr 4,
- case N of
- 0 -> % float
- decode_float(Bs);
- 1 -> % list
- {{Tag,N},Bs};
- 2 -> % fr
- decode_fr(Bs);
- 3 -> % allocation list
- decode_alloc_list(Bs);
- _ ->
- ?exit({decode_z_tagged,{invalid_extended_tag,N}})
- end;
-decode_z_tagged(_,B,_) ->
- ?exit({decode_z_tagged,{weird_value,B}}).
-
-decode_float(Bs) ->
- {FL,RestBs} = take_bytes(8,Bs),
- <<Float:64/float>> = list_to_binary(FL),
- {{float,Float},RestBs}.
-
-decode_fr(Bs) ->
- {{u,Fr},RestBs} = decode_arg(Bs),
- {{fr,Fr},RestBs}.
-
-decode_alloc_list(Bs) ->
- {{u,N},RestBs} = decode_arg(Bs),
- decode_alloc_list_1(N, RestBs, []).
-
-decode_alloc_list_1(0, RestBs, Acc) ->
- {{u,{alloc,lists:reverse(Acc)}},RestBs};
-decode_alloc_list_1(N, Bs0, Acc) ->
- {{u,Type},Bs1} = decode_arg(Bs0),
- {{u,Val},Bs} = decode_arg(Bs1),
- case Type of
- 0 ->
- decode_alloc_list_1(N-1, Bs, [{words,Val}|Acc]);
- 1 ->
- decode_alloc_list_1(N-1, Bs, [{floats,Val}|Acc])
- end.
-
-%%-----------------------------------------------------------------------
-%% take N bytes from a stream, return { Taken_bytes, Remaining_bytes }
-%%-----------------------------------------------------------------------
-
-take_bytes(N,Bs) ->
- take_bytes(N,Bs,[]).
-
-take_bytes(N,[B|Bs],Acc) when N > 0 ->
- take_bytes(N-1,Bs,[B|Acc]);
-take_bytes(0,Bs,Acc) ->
- { lists:reverse(Acc), Bs }.
-
-%%-----------------------------------------------------------------------
-%% from a list of bytes Bn,Bn-1,...,B1,B0
-%% build (Bn << 8*n) bor ... bor B1 << 8 bor B0 << 0
-%%-----------------------------------------------------------------------
-
-build_arg(Bs) ->
- build_arg(Bs,0).
-
-build_arg([B|Bs],N) ->
- build_arg(Bs, (N bsl 8) bor B);
-build_arg([],N) ->
- N.
-
-%%-----------------------------------------------------------------------
-%% Decodes a bunch of arguments and returns them in a list
-%%-----------------------------------------------------------------------
-
-decode_n_args(N, Bs, Atoms) when N >= 0 ->
- decode_n_args(N, [], Bs, Atoms).
-
-decode_n_args(N, Acc, Bs0, Atoms) when N > 0 ->
- {A1,Bs} = decode_arg(Bs0, Atoms),
- decode_n_args(N-1, [A1|Acc], Bs, Atoms);
-decode_n_args(0, Acc, Bs, _) ->
- {lists:reverse(Acc),Bs}.
-
-%%-----------------------------------------------------------------------
-%% Convert a numeric tag value into a symbolic one
-%%-----------------------------------------------------------------------
-
-decode_tag(?tag_u) -> u;
-decode_tag(?tag_i) -> i;
-decode_tag(?tag_a) -> a;
-decode_tag(?tag_x) -> x;
-decode_tag(?tag_y) -> y;
-decode_tag(?tag_f) -> f;
-decode_tag(?tag_h) -> h;
-decode_tag(?tag_z) -> z;
-decode_tag(X) -> ?exit({unknown_tag,X}).
-
-%%-----------------------------------------------------------------------
-%% - replace all references {a,I} with the atom with index I (or {atom,A})
-%% - replace all references to {i,K} in an external call position with
-%% the proper MFA (position in list, first elt = 0, yields MFA to use)
-%% - resolve strings, represented as <offset, length>, into their
-%% actual values by using string table
-%% (note: string table should be passed as a BINARY so that we can
-%% use binary_to_list/3!)
-%% - convert instruction to its readable form ...
-%%
-%% Currently, only the first three are done (systematically, at least).
-%%
-%% Note: It MAY be premature to remove the lists of args, since that
-%% representation means it is simpler to iterate over all args, etc.
-%%-----------------------------------------------------------------------
-
-resolve_names(Fun, Imports, Str, Lbls, Lambdas) ->
- [resolve_inst(Instr, Imports, Str, Lbls, Lambdas) || Instr <- Fun].
-
-%%
-%% New make_fun2/4 instruction added in August 2001 (R8).
-%% We handle it specially here to avoid adding an argument to
-%% the clause for every instruction.
-%%
-
-resolve_inst({make_fun2,Args},_,_,Lbls,Lambdas) ->
- [OldIndex] = resolve_args(Args),
- {value,{OldIndex,{F,A,_Lbl,_Index,NumFree,OldUniq}}} =
- lists:keysearch(OldIndex, 1, Lambdas),
- [{_,{M,_,_}}|_] = Lbls, % Slighly kludgy.
- {make_fun2,{M,F,A},OldIndex,OldUniq,NumFree};
-resolve_inst(Instr, Imports, Str, Lbls, _Lambdas) ->
- resolve_inst(Instr, Imports, Str, Lbls).
-
-resolve_inst({label,[{u,L}]},_,_,_) ->
- {label,L};
-resolve_inst({func_info,RawMFA},_,_,_) ->
- {func_info,resolve_args(RawMFA)};
-% resolve_inst(int_code_end,_,_,_,_) -> % instruction already handled
-% int_code_end; % should not really be handled here
-resolve_inst({call,[{u,N},{f,L}]},_,_,Lbls) ->
- {call,N,catch lookup_key(L,Lbls)};
-resolve_inst({call_last,[{u,N},{f,L},{u,U}]},_,_,Lbls) ->
- {call_last,N,catch lookup_key(L,Lbls),U};
-resolve_inst({call_only,[{u,N},{f,L}]},_,_,Lbls) ->
- {call_only,N,catch lookup_key(L,Lbls)};
-resolve_inst({call_ext,[{u,N},{u,MFAix}]},Imports,_,_) ->
- {call_ext,N,catch lists:nth(MFAix+1,Imports)};
-resolve_inst({call_ext_last,[{u,N},{u,MFAix},{u,X}]},Imports,_,_) ->
- {call_ext_last,N,catch lists:nth(MFAix+1,Imports),X};
-resolve_inst({bif0,Args},Imports,_,_) ->
- [Bif,Reg] = resolve_args(Args),
- {extfunc,_Mod,BifName,_Arity} = lists:nth(Bif+1,Imports),
- %?NO_DEBUG('bif0(~p, ~p)~n',[BifName,Reg]),
- {bif,BifName,nofail,[],Reg};
-resolve_inst({bif1,Args},Imports,_,_) ->
- [F,Bif,A1,Reg] = resolve_args(Args),
- {extfunc,_Mod,BifName,_Arity} = lists:nth(Bif+1,Imports),
- %?NO_DEBUG('bif1(~p, ~p, ~p, ~p, ~p)~n',[Bif,BifName,F,[A1],Reg]),
- {bif,BifName,F,[A1],Reg};
-resolve_inst({bif2,Args},Imports,_,_) ->
- [F,Bif,A1,A2,Reg] = resolve_args(Args),
- {extfunc,_Mod,BifName,_Arity} = lists:nth(Bif+1,Imports),
- %?NO_DEBUG('bif2(~p, ~p, ~p, ~p, ~p)~n',[Bif,BifName,F,[A1,A2],Reg]),
- {bif,BifName,F,[A1,A2],Reg};
-resolve_inst({allocate,[{u,X0},{u,X1}]},_,_,_) ->
- {allocate,X0,X1};
-resolve_inst({allocate_heap,[{u,X0},{u,X1},{u,X2}]},_,_,_) ->
- {allocate_heap,X0,X1,X2};
-resolve_inst({allocate_zero,[{u,X0},{u,X1}]},_,_,_) ->
- {allocate_zero,X0,X1};
-resolve_inst({allocate_heap_zero,[{u,X0},{u,X1},{u,X2}]},_,_,_) ->
- {allocate_heap_zero,X0,X1,X2};
-resolve_inst({test_heap,[{u,X0},{u,X1}]},_,_,_) ->
- {test_heap,X0,X1};
-resolve_inst({init,[Dst]},_,_,_) ->
- {init,Dst};
-resolve_inst({deallocate,[{u,L}]},_,_,_) ->
- {deallocate,L};
-resolve_inst({return,[]},_,_,_) ->
- return;
-resolve_inst({send,[]},_,_,_) ->
- send;
-resolve_inst({remove_message,[]},_,_,_) ->
- remove_message;
-resolve_inst({timeout,[]},_,_,_) ->
- timeout;
-resolve_inst({loop_rec,[Lbl,Dst]},_,_,_) ->
- {loop_rec,Lbl,Dst};
-resolve_inst({loop_rec_end,[Lbl]},_,_,_) ->
- {loop_rec_end,Lbl};
-resolve_inst({wait,[Lbl]},_,_,_) ->
- {wait,Lbl};
-resolve_inst({wait_timeout,[Lbl,Int]},_,_,_) ->
- {wait_timeout,Lbl,resolve_arg(Int)};
-resolve_inst({m_plus,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'+',W,[SrcR1,SrcR2],DstR};
-resolve_inst({m_minus,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'-',W,[SrcR1,SrcR2],DstR};
-resolve_inst({m_times,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'*',W,[SrcR1,SrcR2],DstR};
-resolve_inst({m_div,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'/',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_div,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'div',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_rem,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'rem',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_band,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'band',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_bor,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'bor',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_bxor,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'bxor',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_bsl,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'bsl',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_bsr,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'bsr',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_bnot,Args},_,_,_) ->
- [W,SrcR,DstR] = resolve_args(Args),
- {arithbif,'bnot',W,[SrcR],DstR};
-resolve_inst({is_lt=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({is_ge=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({is_eq=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({is_ne=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({is_eq_exact=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({is_ne_exact=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({is_integer=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({is_float=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({is_number=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({is_atom=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({is_pid=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({is_reference=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({is_port=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({is_nil=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({is_binary=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({is_constant=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({is_list=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({is_nonempty_list=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({is_tuple=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({test_arity=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({select_val,Args},_,_,_) ->
- [Reg,FLbl,{{z,1},{u,_Len},List0}] = Args,
- List = resolve_args(List0),
- {select_val,Reg,FLbl,{list,List}};
-resolve_inst({select_tuple_arity,Args},_,_,_) ->
- [Reg,FLbl,{{z,1},{u,_Len},List0}] = Args,
- List = resolve_args(List0),
- {select_tuple_arity,Reg,FLbl,{list,List}};
-resolve_inst({jump,[Lbl]},_,_,_) ->
- {jump,Lbl};
-resolve_inst({'catch',[Dst,Lbl]},_,_,_) ->
- {'catch',Dst,Lbl};
-resolve_inst({catch_end,[Dst]},_,_,_) ->
- {catch_end,Dst};
-resolve_inst({move,[Src,Dst]},_,_,_) ->
- {move,resolve_arg(Src),Dst};
-resolve_inst({get_list,[Src,Dst1,Dst2]},_,_,_) ->
- {get_list,Src,Dst1,Dst2};
-resolve_inst({get_tuple_element,[Src,{u,Off},Dst]},_,_,_) ->
- {get_tuple_element,resolve_arg(Src),Off,resolve_arg(Dst)};
-resolve_inst({set_tuple_element,[Src,Dst,{u,Off}]},_,_,_) ->
- {set_tuple_element,resolve_arg(Src),resolve_arg(Dst),Off};
-resolve_inst({put_string,[{u,Len},{u,Off},Dst]},_,Strings,_) ->
- String = if Len > 0 -> binary_to_list(Strings, Off+1, Off+Len);
- true -> ""
- end,
-?NO_DEBUG('put_string(~p, {string,~p}, ~p)~n',[Len,String,Dst]),
- {put_string,Len,{string,String},Dst};
-resolve_inst({put_list,[Src1,Src2,Dst]},_,_,_) ->
- {put_list,resolve_arg(Src1),resolve_arg(Src2),Dst};
-resolve_inst({put_tuple,[{u,Arity},Dst]},_,_,_) ->
- {put_tuple,Arity,Dst};
-resolve_inst({put,[Src]},_,_,_) ->
- {put,resolve_arg(Src)};
-resolve_inst({badmatch,[X]},_,_,_) ->
- {badmatch,resolve_arg(X)};
-resolve_inst({if_end,[]},_,_,_) ->
- if_end;
-resolve_inst({case_end,[X]},_,_,_) ->
- {case_end,resolve_arg(X)};
-resolve_inst({call_fun,[{u,N}]},_,_,_) ->
- {call_fun,N};
-resolve_inst({make_fun,Args},_,_,Lbls) ->
- [{f,L},Magic,FreeVars] = resolve_args(Args),
- {make_fun,catch lookup_key(L,Lbls),Magic,FreeVars};
-resolve_inst({is_function=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-resolve_inst({call_ext_only,[{u,N},{u,MFAix}]},Imports,_,_) ->
- {call_ext_only,N,catch lists:nth(MFAix+1,Imports)};
-%%
-%% Instructions for handling binaries added in R7A & R7B
-%%
-resolve_inst({bs_start_match,[F,Reg]},_,_,_) ->
- {bs_start_match,F,Reg};
-resolve_inst({bs_get_integer=I,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
- [A2,A5] = resolve_args([Arg2,Arg5]),
- {test,I,Lbl,[A2,N,decode_field_flags(U),A5]};
-resolve_inst({bs_get_float=I,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
- [A2,A5] = resolve_args([Arg2,Arg5]),
- {test,I,Lbl,[A2,N,decode_field_flags(U),A5]};
-resolve_inst({bs_get_binary=I,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
- [A2,A5] = resolve_args([Arg2,Arg5]),
- {test,I,Lbl,[A2,N,decode_field_flags(U),A5]};
-resolve_inst({bs_skip_bits,[Lbl,Arg2,{u,N},{u,U}]},_,_,_) ->
- [A2] = resolve_args([Arg2]),
- {test,bs_skip_bits,Lbl,[A2,N,decode_field_flags(U)]};
-resolve_inst({bs_test_tail,[F,{u,N}]},_,_,_) ->
- {test,bs_test_tail,F,[N]};
-resolve_inst({bs_save,[{u,N}]},_,_,_) ->
- {bs_save,N};
-resolve_inst({bs_restore,[{u,N}]},_,_,_) ->
- {bs_restore,N};
-resolve_inst({bs_init,[{u,N},{u,U}]},_,_,_) ->
- {bs_init,N,decode_field_flags(U)};
-resolve_inst({bs_final,[F,X]},_,_,_) ->
- {bs_final,F,X};
-resolve_inst({bs_put_integer,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
- [A2,A5] = resolve_args([Arg2,Arg5]),
- {bs_put_integer,Lbl,A2,N,decode_field_flags(U),A5};
-resolve_inst({bs_put_binary,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
- [A2,A5] = resolve_args([Arg2,Arg5]),
- ?NO_DEBUG('bs_put_binary(~p,~p,~p,~p,~p})~n',[Lbl,A2,N,U,A5]),
- {bs_put_binary,Lbl,A2,N,decode_field_flags(U),A5};
-resolve_inst({bs_put_float,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
- [A2,A5] = resolve_args([Arg2,Arg5]),
- ?NO_DEBUG('bs_put_float(~p,~p,~p,~p,~p})~n',[Lbl,A2,N,U,A5]),
- {bs_put_float,Lbl,A2,N,decode_field_flags(U),A5};
-resolve_inst({bs_put_string,[{u,Len},{u,Off}]},_,Strings,_) ->
- String = if Len > 0 -> binary_to_list(Strings, Off+1, Off+Len);
- true -> ""
- end,
- ?NO_DEBUG('bs_put_string(~p, {string,~p})~n',[Len,String]),
- {bs_put_string,Len,{string,String}};
-resolve_inst({bs_need_buf,[{u,N}]},_,_,_) ->
- {bs_need_buf,N};
-
-%%
-%% Instructions for handling floating point numbers added in June 2001 (R8).
-%%
-resolve_inst({fclearerror,[]},_,_,_) ->
- fclearerror;
-resolve_inst({fcheckerror,Args},_,_,_) ->
- [Fail] = resolve_args(Args),
- {fcheckerror,Fail};
-resolve_inst({fmove,Args},_,_,_) ->
- [FR,Reg] = resolve_args(Args),
- {fmove,FR,Reg};
-resolve_inst({fconv,Args},_,_,_) ->
- [Reg,FR] = resolve_args(Args),
- {fconv,Reg,FR};
-resolve_inst({fadd=I,Args},_,_,_) ->
- [F,A1,A2,Reg] = resolve_args(Args),
- {arithfbif,I,F,[A1,A2],Reg};
-resolve_inst({fsub=I,Args},_,_,_) ->
- [F,A1,A2,Reg] = resolve_args(Args),
- {arithfbif,I,F,[A1,A2],Reg};
-resolve_inst({fmul=I,Args},_,_,_) ->
- [F,A1,A2,Reg] = resolve_args(Args),
- {arithfbif,I,F,[A1,A2],Reg};
-resolve_inst({fdiv=I,Args},_,_,_) ->
- [F,A1,A2,Reg] = resolve_args(Args),
- {arithfbif,I,F,[A1,A2],Reg};
-resolve_inst({fnegate,Args},_,_,_) ->
- [F,Arg,Reg] = resolve_args(Args),
- {arithfbif,fnegate,F,[Arg],Reg};
-
-%%
-%% Instructions for try expressions added in January 2003 (R10).
-%%
-
-resolve_inst({'try',[Reg,Lbl]},_,_,_) -> % analogous to 'catch'
- {'try',Reg,Lbl};
-resolve_inst({try_end,[Reg]},_,_,_) -> % analogous to 'catch_end'
- {try_end,Reg};
-resolve_inst({try_case,[Reg]},_,_,_) -> % analogous to 'catch_end'
- {try_case,Reg};
-resolve_inst({try_case_end,[Reg]},_,_,_) ->
- {try_case_end,Reg};
-resolve_inst({raise,[Reg1,Reg2]},_,_,_) ->
- {bif,raise,{f,0},[Reg1,Reg2],{x,0}};
-
-%%
-%% New bit syntax instructions added in February 2004 (R10B).
-%%
-
-resolve_inst({bs_init2,[Lbl,Arg2,{u,W},{u,R},{u,F},Arg6]},_,_,_) ->
- [A2,A6] = resolve_args([Arg2,Arg6]),
- {bs_init2,Lbl,A2,W,R,decode_field_flags(F),A6};
-resolve_inst({bs_bits_to_bytes,[Lbl,Arg2,Arg3]},_,_,_) ->
- [A2,A3] = resolve_args([Arg2,Arg3]),
- {bs_bits_to_bytes,Lbl,A2,A3};
-resolve_inst({bs_add=I,[Lbl,Arg2,Arg3,Arg4,Arg5]},_,_,_) ->
- [A2,A3,A4,A5] = resolve_args([Arg2,Arg3,Arg4,Arg5]),
- {I,Lbl,[A2,A3,A4],A5};
-
-%%
-%% New apply instructions added in April 2004 (R10B).
-%%
-resolve_inst({apply,[{u,Arity}]},_,_,_) ->
- {apply,Arity};
-resolve_inst({apply_last,[{u,Arity},{u,D}]},_,_,_) ->
- {apply_last,Arity,D};
-
-%%
-%% New test instruction added in April 2004 (R10B).
-%%
-resolve_inst({is_boolean=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
-
-%%
-%% Catches instructions that are not yet handled.
-%%
-
-resolve_inst(X,_,_,_) -> ?exit({resolve_inst,X}).
-
-%%-----------------------------------------------------------------------
-%% Resolves arguments in a generic way.
-%%-----------------------------------------------------------------------
-
-resolve_args(Args) -> [resolve_arg(A) || A <- Args].
-
-resolve_arg({u,N}) -> N;
-resolve_arg({i,N}) -> {integer,N};
-resolve_arg({atom,Atom}=A) when is_atom(Atom) -> A;
-resolve_arg(nil) -> nil;
-resolve_arg(Arg) -> Arg.
-
-%%-----------------------------------------------------------------------
-%% The purpose of the following is just to add a hook for future changes.
-%% Currently, field flags are numbers 1-2-4-8 and only two of these
-%% numbers (BSF_LITTLE 2 -- BSF_SIGNED 4) have a semantic significance;
-%% others are just hints for speeding up the execution; see "erl_bits.h".
-%%-----------------------------------------------------------------------
-
-decode_field_flags(FF) ->
- {field_flags,FF}.
-
-%%-----------------------------------------------------------------------
-%% Each string is denoted in the assembled code by its offset into this
-%% binary. This binary contains all strings concatenated together.
-%%-----------------------------------------------------------------------
-
-beam_disasm_strings(Bin) ->
- Bin.
-
-%%-----------------------------------------------------------------------
-%% Disassembles the attributes of a BEAM file.
-%%-----------------------------------------------------------------------
-
-beam_disasm_attributes(none) -> none;
-beam_disasm_attributes(AttrBin) -> binary_to_term(AttrBin).
-
-%%-----------------------------------------------------------------------
-%% Disassembles the compilation information of a BEAM file.
-%%-----------------------------------------------------------------------
-
-beam_disasm_compilation_info(none) -> none;
-beam_disasm_compilation_info(Bin) -> binary_to_term(Bin).
-
-%%-----------------------------------------------------------------------
-%% Private Utilities
-%%-----------------------------------------------------------------------
-
-%%-----------------------------------------------------------------------
-
-lookup_key(Key,[{Key,Val}|_]) ->
- Val;
-lookup_key(Key,[_|KVs]) ->
- lookup_key(Key,KVs);
-lookup_key(Key,[]) ->
- ?exit({lookup_key,{key_not_found,Key}}).
-
-%%-----------------------------------------------------------------------
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_flatten.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_flatten.erl
deleted file mode 100644
index a9958f87cd..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_flatten.erl
+++ /dev/null
@@ -1,137 +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: beam_flatten.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
-%%
-%% Purpose : Converts intermediate assembly code to final format.
-
--module(beam_flatten).
-
--export([module/2]).
--import(lists, [reverse/1,reverse/2,map/2]).
-
-module({Mod,Exp,Attr,Fs,Lc}, _Opt) ->
- {ok,{Mod,Exp,Attr,map(fun function/1, Fs),Lc}}.
-
-function({function,Name,Arity,CLabel,Is0}) ->
- Is1 = block(Is0),
- Is = opt(Is1),
- {function,Name,Arity,CLabel,Is}.
-
-block(Is) ->
- block(Is, []).
-
-block([{block,Is0}|Is1], Acc) -> block(Is1, norm_block(Is0, Acc));
-block([I|Is], Acc) -> block(Is, [I|Acc]);
-block([], Acc) -> reverse(Acc).
-
-norm_block([{allocate,R,Alloc}|Is], Acc0) ->
- case insert_alloc_in_bs_init(Acc0, Alloc) of
- not_possible ->
- norm_block(Is, reverse(norm_allocate(Alloc, R), Acc0));
- Acc ->
- norm_block(Is, Acc)
- end;
-norm_block([I|Is], Acc) -> norm_block(Is, [norm(I)|Acc]);
-norm_block([], Acc) -> Acc.
-
-norm({set,[D],As,{bif,N}}) -> {bif,N,nofail,As,D};
-norm({set,[D],As,{bif,N,F}}) -> {bif,N,F,As,D};
-norm({set,[D],[S],move}) -> {move,S,D};
-norm({set,[D],[S],fmove}) -> {fmove,S,D};
-norm({set,[D],[S],fconv}) -> {fconv,S,D};
-norm({set,[D],[S1,S2],put_list}) -> {put_list,S1,S2,D};
-norm({set,[D],[],{put_tuple,A}}) -> {put_tuple,A,D};
-norm({set,[],[S],put}) -> {put,S};
-norm({set,[D],[],{put_string,L,S}}) -> {put_string,L,S,D};
-norm({set,[D],[S],{get_tuple_element,I}}) -> {get_tuple_element,S,I,D};
-norm({set,[],[S,D],{set_tuple_element,I}}) -> {set_tuple_element,S,D,I};
-norm({set,[D1,D2],[S],get_list}) -> {get_list,S,D1,D2};
-norm({set,[],[],remove_message}) -> remove_message;
-norm({set,[],[],fclearerror}) -> fclearerror;
-norm({set,[],[],fcheckerror}) -> {fcheckerror,{f,0}};
-norm({'%',_}=Comment) -> Comment;
-norm({'%live',R}) -> {'%live',R}.
-
-norm_allocate({_Zero,nostack,Nh,[]}, Regs) ->
- [{test_heap,Nh,Regs}];
-norm_allocate({_Zero,nostack,Nh,Nf,[]}, Regs) ->
- [{test_heap,alloc_list(Nh, Nf),Regs}];
-norm_allocate({zero,0,Nh,[]}, Regs) ->
- norm_allocate({nozero,0,Nh,[]}, Regs);
-norm_allocate({zero,0,Nh,Nf,[]}, Regs) ->
- norm_allocate({nozero,0,Nh,Nf,[]}, Regs);
-norm_allocate({zero,Ns,0,[]}, Regs) ->
- [{allocate_zero,Ns,Regs}];
-norm_allocate({zero,Ns,Nh,[]}, Regs) ->
- [{allocate_heap_zero,Ns,Nh,Regs}];
-norm_allocate({nozero,Ns,0,Inits}, Regs) ->
- [{allocate,Ns,Regs}|Inits];
-norm_allocate({nozero,Ns,Nh,Inits}, Regs) ->
- [{allocate_heap,Ns,Nh,Regs}|Inits];
-norm_allocate({nozero,Ns,Nh,Floats,Inits}, Regs) ->
- [{allocate_heap,Ns,alloc_list(Nh, Floats),Regs}|Inits];
-norm_allocate({zero,Ns,Nh,Floats,Inits}, Regs) ->
- [{allocate_heap_zero,Ns,alloc_list(Nh, Floats),Regs}|Inits].
-
-insert_alloc_in_bs_init([I|_]=Is, Alloc) ->
- case is_bs_put(I) of
- false ->
- not_possible;
- true ->
- insert_alloc_1(Is, Alloc, [])
- end.
-
-insert_alloc_1([{bs_init2,Fail,Bs,Ws,Regs,F,Dst}|Is], {_,nostack,Nh,Nf,[]}, Acc) ->
- Al = alloc_list(Ws+Nh, Nf),
- I = {bs_init2,Fail,Bs,Al,Regs,F,Dst},
- reverse(Acc, [I|Is]);
-insert_alloc_1([I|Is], Alloc, Acc) ->
- insert_alloc_1(Is, Alloc, [I|Acc]).
-
-is_bs_put({bs_put_integer,_,_,_,_,_}) -> true;
-is_bs_put({bs_put_float,_,_,_,_,_}) -> true;
-is_bs_put({bs_put_binary,_,_,_,_,_}) -> true;
-is_bs_put({bs_put_string,_,_}) -> true;
-is_bs_put(_) -> false.
-
-alloc_list(Words, Floats) ->
- {alloc,[{words,Words},{floats,Floats}]}.
-
-
-%% opt(Is0) -> Is
-%% Simple peep-hole optimization to move a {move,Any,{x,0}} past
-%% any kill up to the next call instruction.
-
-opt(Is) ->
- opt_1(Is, []).
-
-opt_1([{move,_,{x,0}}=I|Is0], Acc0) ->
- case move_past_kill(Is0, I, Acc0) of
- impossible -> opt_1(Is0, [I|Acc0]);
- {Is,Acc} -> opt_1(Is, Acc)
- end;
-opt_1([I|Is], Acc) ->
- opt_1(Is, [I|Acc]);
-opt_1([], Acc) -> reverse(Acc).
-
-move_past_kill([{'%live',_}|Is], Move, Acc) ->
- move_past_kill(Is, Move, Acc);
-move_past_kill([{kill,Src}|_], {move,Src,_}, _) ->
- impossible;
-move_past_kill([{kill,_}=I|Is], Move, Acc) ->
- move_past_kill(Is, Move, [I|Acc]);
-move_past_kill(Is, Move, Acc) ->
- {Is,[Move|Acc]}.
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_jump.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_jump.erl
deleted file mode 100644
index fd005898b6..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_jump.erl
+++ /dev/null
@@ -1,477 +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: beam_jump.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
-%%
-%%% Purpose : Optimise jumps and remove unreachable code.
-
--module(beam_jump).
-
--export([module/2,module_labels/1,
- is_unreachable_after/1,remove_unused_labels/1]).
-
-%%% The following optimisations are done:
-%%%
-%%% (1) This code with two identical instruction sequences
-%%%
-%%% L1: <Instruction sequence>
-%%% L2:
-%%% . . .
-%%% L3: <Instruction sequence>
-%%% L4:
-%%%
-%%% can be replaced with
-%%%
-%%% L1: jump L3
-%%% L2:
-%%% . . .
-%%% L3: <Instruction sequence>
-%%% L4
-%%%
-%%% Note: The instruction sequence must end with an instruction
-%%% such as a jump that never transfers control to the instruction
-%%% following it.
-%%%
-%%% (2) case_end, if_end, and badmatch, and function calls that cause an
-%%% exit (such as calls to exit/1) are moved to the end of the function.
-%%% The purpose is to allow further optimizations at the place from
-%%% which the code was moved.
-%%%
-%%% (3) Any unreachable code is removed. Unreachable code is code after
-%%% jump, call_last and other instructions which never transfer control
-%%% to the following instruction. Code is unreachable up to the next
-%%% *referenced* label. Note that the optimisations below might
-%%% generate more possibilities for removing unreachable code.
-%%%
-%%% (4) This code:
-%%% L1: jump L2
-%%% . . .
-%%% L2: ...
-%%%
-%%% will be changed to
-%%%
-%%% jump L2
-%%% . . .
-%%% L1:
-%%% L2: ...
-%%%
-%%% If the jump is unreachable, it will be removed according to (1).
-%%%
-%%% (5) In
-%%%
-%%% jump L1
-%%% L1:
-%%%
-%%% the jump will be removed.
-%%%
-%%% (6) If test instructions are used to skip a single jump instruction,
-%%% the test is inverted and the jump is eliminated (provided that
-%%% the test can be inverted). Example:
-%%%
-%%% is_eq L1 {x,1} {x,2}
-%%% jump L2
-%%% L1:
-%%%
-%%% will be changed to
-%%%
-%%% is_ne L2 {x,1} {x,2}
-%%%
-%%% (The label L1 will be retained if there were previous references to it.)
-%%%
-%%% (7) Some redundant uses of is_boolean/1 is optimized away.
-%%%
-%%% Terminology note: The optimisation done here is called unreachable-code
-%%% elimination, NOT dead-code elimination. Dead code elimination
-%%% means the removal of instructions that are executed, but have no visible
-%%% effect on the program state.
-%%%
-
--import(lists, [reverse/1,reverse/2,map/2,mapfoldl/3,foldl/3,
- last/1,foreach/2,member/2]).
-
-module({Mod,Exp,Attr,Fs0,Lc}, _Opt) ->
- Fs = map(fun function/1, Fs0),
- {ok,{Mod,Exp,Attr,Fs,Lc}}.
-
-module_labels({Mod,Exp,Attr,Fs,Lc}) ->
- {Mod,Exp,Attr,map(fun function_labels/1, Fs),Lc}.
-
-function_labels({function,Name,Arity,CLabel,Asm0}) ->
- Asm = remove_unused_labels(Asm0),
- {function,Name,Arity,CLabel,Asm}.
-
-function({function,Name,Arity,CLabel,Asm0}) ->
- Asm1 = share(Asm0),
- Asm2 = bopt(Asm1),
- Asm3 = move(Asm2),
- Asm4 = opt(Asm3, CLabel),
- Asm = remove_unused_labels(Asm4),
- {function,Name,Arity,CLabel,Asm}.
-
-%%%
-%%% (1) We try to share the code for identical code segments by replacing all
-%%% occurrences except the last with jumps to the last occurrence.
-%%%
-
-share(Is) ->
- share_1(reverse(Is), gb_trees:empty(), [], []).
-
-share_1([{label,_}=Lbl|Is], Dict, [], Acc) ->
- share_1(Is, Dict, [], [Lbl|Acc]);
-share_1([{label,L}=Lbl|Is], Dict0, Seq, Acc) ->
- case is_unreachable_after(last(Seq)) of
- false ->
- share_1(Is, Dict0, [], [Lbl|Seq ++ Acc]);
- true ->
- case gb_trees:lookup(Seq, Dict0) of
- none ->
- Dict = gb_trees:insert(Seq, L, Dict0),
- share_1(Is, Dict, [], [Lbl|Seq ++ Acc]);
- {value,Label} ->
- share_1(Is, Dict0, [], [Lbl,{jump,{f,Label}}|Acc])
- end
- end;
-share_1([{func_info,_,_,_}=I|Is], _, [], Acc) ->
- Is++[I|Acc];
-share_1([I|Is], Dict, Seq, Acc) ->
- case is_unreachable_after(I) of
- false ->
- share_1(Is, Dict, [I|Seq], Acc);
- true ->
- share_1(Is, Dict, [I], Acc)
- end.
-
-%%%
-%%% (2) Move short code sequences ending in an instruction that causes an exit
-%%% to the end of the function.
-%%%
-
-move(Is) ->
- move_1(Is, [], []).
-
-move_1([I|Is], End, Acc) ->
- case is_exit_instruction(I) of
- false -> move_1(Is, End, [I|Acc]);
- true -> move_2(I, Is, End, Acc)
- end;
-move_1([], End, Acc) ->
- reverse(Acc, reverse(End)).
-
-move_2(Exit, Is, End, [{block,_},{label,_},{func_info,_,_,_}|_]=Acc) ->
- move_1(Is, End, [Exit|Acc]);
-move_2(Exit, Is, End, [{kill,_Y}|Acc]) ->
- move_2(Exit, Is, End, Acc);
-move_2(Exit, Is, End, [{block,_}=Blk,{label,_}=Lbl,Dead|More]=Acc) ->
- case is_unreachable_after(Dead) of
- false ->
- move_1(Is, End, [Exit|Acc]);
- true ->
- move_1([Dead|Is], [Exit,Blk,Lbl|End], More)
- end;
-move_2(Exit, Is, End, [{label,_}=Lbl,Dead|More]=Acc) ->
- case is_unreachable_after(Dead) of
- false ->
- move_1(Is, End, [Exit|Acc]);
- true ->
- move_1([Dead|Is], [Exit,Lbl|End], More)
- end;
-move_2(Exit, Is, End, Acc) ->
- move_1(Is, End, [Exit|Acc]).
-
-%%%
-%%% (7) Remove redundant is_boolean tests.
-%%%
-
-bopt(Is) ->
- bopt_1(Is, []).
-
-bopt_1([{test,is_boolean,_,_}=I|Is], Acc0) ->
- case opt_is_bool(I, Acc0) of
- no -> bopt_1(Is, [I|Acc0]);
- yes -> bopt_1(Is, Acc0);
- {yes,Acc} -> bopt_1(Is, Acc)
- end;
-bopt_1([I|Is], Acc) -> bopt_1(Is, [I|Acc]);
-bopt_1([], Acc) -> reverse(Acc).
-
-opt_is_bool({test,is_boolean,{f,Lbl},[Reg]}, Acc) ->
- opt_is_bool_1(Acc, Reg, Lbl).
-
-opt_is_bool_1([{test,is_eq_exact,{f,Lbl},[Reg,{atom,true}]}|_], Reg, Lbl) ->
- %% Instruction not needed in this context.
- yes;
-opt_is_bool_1([{test,is_ne_exact,{f,Lbl},[Reg,{atom,true}]}|Acc], Reg, Lbl) ->
- %% Rewrite to shorter test.
- {yes,[{test,is_eq_exact,{f,Lbl},[Reg,{atom,false}]}|Acc]};
-opt_is_bool_1([{test,_,{f,Lbl},_}=Test|Acc0], Reg, Lbl) ->
- case opt_is_bool_1(Acc0, Reg, Lbl) of
- {yes,Acc} -> {yes,[Test|Acc]};
- Other -> Other
- end;
-opt_is_bool_1(_, _, _) -> no.
-
-%%%
-%%% (3) (4) (5) (6) Jump and unreachable code optimizations.
-%%%
-
--record(st, {fc, %Label for function class errors.
- entry, %Entry label (must not be moved).
- mlbl, %Moved labels.
- labels %Set of referenced labels.
- }).
-
-opt([{label,Fc}|_]=Is, CLabel) ->
- Lbls = initial_labels(Is),
- St = #st{fc=Fc,entry=CLabel,mlbl=dict:new(),labels=Lbls},
- opt(Is, [], St).
-
-opt([{test,Test0,{f,Lnum}=Lbl,Ops}=I|Is0], Acc, St) ->
- case Is0 of
- [{jump,To}|[{label,Lnum}|Is2]=Is1] ->
- case invert_test(Test0) of
- not_possible ->
- opt(Is0, [I|Acc], label_used(Lbl, St));
- Test ->
- Is = case is_label_used(Lnum, St) of
- true -> Is1;
- false -> Is2
- end,
- opt([{test,Test,To,Ops}|Is], Acc, label_used(To, St))
- end;
- _Other ->
- opt(Is0, [I|Acc], label_used(Lbl, St))
- end;
-opt([{select_val,_R,Fail,{list,Vls}}=I|Is], Acc, St) ->
- skip_unreachable(Is, [I|Acc], label_used([Fail|Vls], St));
-opt([{select_tuple_arity,_R,Fail,{list,Vls}}=I|Is], Acc, St) ->
- skip_unreachable(Is, [I|Acc], label_used([Fail|Vls], St));
-opt([{'try',_R,Lbl}=I|Is], Acc, St) ->
- opt(Is, [I|Acc], label_used(Lbl, St));
-opt([{'catch',_R,Lbl}=I|Is], Acc, St) ->
- opt(Is, [I|Acc], label_used(Lbl, St));
-opt([{label,L}=I|Is], Acc, #st{entry=L}=St) ->
- %% NEVER move the entry label.
- opt(Is, [I|Acc], St);
-opt([{label,L1},{jump,{f,L2}}=I|Is], [Prev|Acc], St0) ->
- St = St0#st{mlbl=dict:append(L2, L1, St0#st.mlbl)},
- opt([Prev,I|Is], Acc, label_used({f,L2}, St));
-opt([{label,Lbl}=I|Is], Acc, #st{mlbl=Mlbl}=St0) ->
- case dict:find(Lbl, Mlbl) of
- {ok,Lbls} ->
- %% Essential to remove the list of labels from the dictionary,
- %% since we will rescan the inserted labels. We MUST rescan.
- St = St0#st{mlbl=dict:erase(Lbl, Mlbl)},
- insert_labels([Lbl|Lbls], Is, Acc, St);
- error -> opt(Is, [I|Acc], St0)
- end;
-opt([{jump,{f,Lbl}},{label,Lbl}=I|Is], Acc, St) ->
- opt([I|Is], Acc, St);
-opt([{jump,Lbl}=I|Is], Acc, St) ->
- skip_unreachable(Is, [I|Acc], label_used(Lbl, St));
-opt([{loop_rec,Lbl,_R}=I|Is], Acc, St) ->
- opt(Is, [I|Acc], label_used(Lbl, St));
-opt([{bif,_Name,Lbl,_As,_R}=I|Is], Acc, St) ->
- opt(Is, [I|Acc], label_used(Lbl, St));
-opt([{bs_put_integer,Lbl,_Bits,_Unit,_Fl,_Val}=I|Is], Acc, St) ->
- opt(Is, [I|Acc], label_used(Lbl, St));
-opt([{bs_put_binary,Lbl,_Bits,_Unit,_Fl,_Val}=I|Is], Acc, St) ->
- opt(Is, [I|Acc], label_used(Lbl, St));
-opt([{bs_put_float,Lbl,_Bits,_Unit,_Fl,_Val}=I|Is], Acc, St) ->
- opt(Is, [I|Acc], label_used(Lbl, St));
-opt([{bs_final,Lbl,_R}=I|Is], Acc, St) ->
- opt(Is, [I|Acc], label_used(Lbl, St));
-opt([{bs_init2,Lbl,_,_,_,_,_}=I|Is], Acc, St) ->
- opt(Is, [I|Acc], label_used(Lbl, St));
-opt([{bs_add,Lbl,_,_}=I|Is], Acc, St) ->
- opt(Is, [I|Acc], label_used(Lbl, St));
-opt([{bs_bits_to_bytes,Lbl,_,_}=I|Is], Acc, St) ->
- opt(Is, [I|Acc], label_used(Lbl, St));
-opt([I|Is], Acc, St) ->
- case is_unreachable_after(I) of
- true -> skip_unreachable(Is, [I|Acc], St);
- false -> opt(Is, [I|Acc], St)
- end;
-opt([], Acc, #st{fc=Fc,mlbl=Mlbl}) ->
- Code = reverse(Acc),
- case dict:find(Fc, Mlbl) of
- {ok,Lbls} -> insert_fc_labels(Lbls, Mlbl, Code);
- error -> Code
- end.
-
-insert_fc_labels([L|Ls], Mlbl, Acc0) ->
- Acc = [{label,L}|Acc0],
- case dict:find(L, Mlbl) of
- error ->
- insert_fc_labels(Ls, Mlbl, Acc);
- {ok,Lbls} ->
- insert_fc_labels(Lbls++Ls, Mlbl, Acc)
- end;
-insert_fc_labels([], _, Acc) -> Acc.
-
-%% invert_test(Test0) -> not_possible | Test
-
-invert_test(is_ge) -> is_lt;
-invert_test(is_lt) -> is_ge;
-invert_test(is_eq) -> is_ne;
-invert_test(is_ne) -> is_eq;
-invert_test(is_eq_exact) -> is_ne_exact;
-invert_test(is_ne_exact) -> is_eq_exact;
-invert_test(_) -> not_possible.
-
-insert_labels([L|Ls], Is, [{jump,{f,L}}|Acc], St) ->
- insert_labels(Ls, [{label,L}|Is], Acc, St);
-insert_labels([L|Ls], Is, Acc, St) ->
- insert_labels(Ls, [{label,L}|Is], Acc, St);
-insert_labels([], Is, Acc, St) ->
- opt(Is, Acc, St).
-
-%% Skip unreachable code up to the next referenced label.
-
-skip_unreachable([{label,L}|Is], [{jump,{f,L}}|Acc], St) ->
- opt([{label,L}|Is], Acc, St);
-skip_unreachable([{label,L}|Is], Acc, St) ->
- case is_label_used(L, St) of
- true -> opt([{label,L}|Is], Acc, St);
- false -> skip_unreachable(Is, Acc, St)
- end;
-skip_unreachable([_|Is], Acc, St) ->
- skip_unreachable(Is, Acc, St);
-skip_unreachable([], Acc, St) ->
- opt([], Acc, St).
-
-%% Add one or more label to the set of used labels.
-
-label_used({f,0}, St) -> St;
-label_used({f,L}, St) -> St#st{labels=gb_sets:add(L, St#st.labels)};
-label_used([H|T], St0) -> label_used(T, label_used(H, St0));
-label_used([], St) -> St;
-label_used(_Other, St) -> St.
-
-%% Test if label is used.
-
-is_label_used(L, St) ->
- gb_sets:is_member(L, St#st.labels).
-
-%% is_unreachable_after(Instruction) -> true|false
-%% Test whether the code after Instruction is unreachable.
-
-is_unreachable_after({func_info,_M,_F,_A}) -> true;
-is_unreachable_after(return) -> true;
-is_unreachable_after({call_ext_last,_Ar,_ExtFunc,_D}) -> true;
-is_unreachable_after({call_ext_only,_Ar,_ExtFunc}) -> true;
-is_unreachable_after({call_last,_Ar,_Lbl,_D}) -> true;
-is_unreachable_after({call_only,_Ar,_Lbl}) -> true;
-is_unreachable_after({apply_last,_Ar,_N}) -> true;
-is_unreachable_after({jump,_Lbl}) -> true;
-is_unreachable_after({select_val,_R,_Lbl,_Cases}) -> true;
-is_unreachable_after({select_tuple_arity,_R,_Lbl,_Cases}) -> true;
-is_unreachable_after({loop_rec_end,_}) -> true;
-is_unreachable_after({wait,_}) -> true;
-is_unreachable_after(I) -> is_exit_instruction(I).
-
-%% is_exit_instruction(Instruction) -> true|false
-%% Test whether the instruction Instruction always
-%% causes an exit/failure.
-
-is_exit_instruction({call_ext,_,{extfunc,M,F,A}}) ->
- is_exit_instruction_1(M, F, A);
-is_exit_instruction({call_ext_last,_,{extfunc,M,F,A},_}) ->
- is_exit_instruction_1(M, F, A);
-is_exit_instruction({call_ext_only,_,{extfunc,M,F,A}}) ->
- is_exit_instruction_1(M, F, A);
-is_exit_instruction(if_end) -> true;
-is_exit_instruction({case_end,_}) -> true;
-is_exit_instruction({try_case_end,_}) -> true;
-is_exit_instruction({badmatch,_}) -> true;
-is_exit_instruction(_) -> false.
-
-is_exit_instruction_1(erlang, exit, 1) -> true;
-is_exit_instruction_1(erlang, throw, 1) -> true;
-is_exit_instruction_1(erlang, error, 1) -> true;
-is_exit_instruction_1(erlang, error, 2) -> true;
-is_exit_instruction_1(erlang, fault, 1) -> true;
-is_exit_instruction_1(erlang, fault, 2) -> true;
-is_exit_instruction_1(_, _, _) -> false.
-
-%% remove_unused_labels(Instructions0) -> Instructions
-%% Remove all unused labels.
-
-remove_unused_labels(Is) ->
- Used0 = initial_labels(Is),
- Used = foldl(fun ulbl/2, Used0, Is),
- rem_unused(Is, Used, []).
-
-rem_unused([{label,Lbl}=I|Is], Used, Acc) ->
- case gb_sets:is_member(Lbl, Used) of
- false -> rem_unused(Is, Used, Acc);
- true -> rem_unused(Is, Used, [I|Acc])
- end;
-rem_unused([I|Is], Used, Acc) ->
- rem_unused(Is, Used, [I|Acc]);
-rem_unused([], _, Acc) -> reverse(Acc).
-
-initial_labels(Is) ->
- initial_labels(Is, []).
-
-initial_labels([{label,Lbl}|Is], Acc) ->
- initial_labels(Is, [Lbl|Acc]);
-initial_labels([{func_info,_,_,_},{label,Lbl}|_], Acc) ->
- gb_sets:from_list([Lbl|Acc]).
-
-ulbl({test,_,Fail,_}, Used) ->
- mark_used(Fail, Used);
-ulbl({select_val,_,Fail,{list,Vls}}, Used) ->
- mark_used_list(Vls, mark_used(Fail, Used));
-ulbl({select_tuple_arity,_,Fail,{list,Vls}}, Used) ->
- mark_used_list(Vls, mark_used(Fail, Used));
-ulbl({'try',_,Lbl}, Used) ->
- mark_used(Lbl, Used);
-ulbl({'catch',_,Lbl}, Used) ->
- mark_used(Lbl, Used);
-ulbl({jump,Lbl}, Used) ->
- mark_used(Lbl, Used);
-ulbl({loop_rec,Lbl,_}, Used) ->
- mark_used(Lbl, Used);
-ulbl({loop_rec_end,Lbl}, Used) ->
- mark_used(Lbl, Used);
-ulbl({wait,Lbl}, Used) ->
- mark_used(Lbl, Used);
-ulbl({wait_timeout,Lbl,_To}, Used) ->
- mark_used(Lbl, Used);
-ulbl({bif,_Name,Lbl,_As,_R}, Used) ->
- mark_used(Lbl, Used);
-ulbl({bs_init2,Lbl,_,_,_,_,_}, Used) ->
- mark_used(Lbl, Used);
-ulbl({bs_put_integer,Lbl,_Bits,_Unit,_Fl,_Val}, Used) ->
- mark_used(Lbl, Used);
-ulbl({bs_put_float,Lbl,_Bits,_Unit,_Fl,_Val}, Used) ->
- mark_used(Lbl, Used);
-ulbl({bs_put_binary,Lbl,_Bits,_Unit,_Fl,_Val}, Used) ->
- mark_used(Lbl, Used);
-ulbl({bs_final,Lbl,_}, Used) ->
- mark_used(Lbl, Used);
-ulbl({bs_add,Lbl,_,_}, Used) ->
- mark_used(Lbl, Used);
-ulbl({bs_bits_to_bytes,Lbl,_,_}, Used) ->
- mark_used(Lbl, Used);
-ulbl(_, Used) -> Used.
-
-mark_used({f,0}, Used) -> Used;
-mark_used({f,L}, Used) -> gb_sets:add(L, Used);
-mark_used(_, Used) -> Used.
-
-mark_used_list([H|T], Used) ->
- mark_used_list(T, mark_used(H, Used));
-mark_used_list([], Used) -> Used.
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_listing.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_listing.erl
deleted file mode 100644
index 006b8c551a..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_listing.erl
+++ /dev/null
@@ -1,117 +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: beam_listing.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
-%%
--module(beam_listing).
-
--export([module/2]).
-
--include("v3_life.hrl").
-
--import(lists, [foreach/2]).
-
-module(File, Core) when element(1, Core) == c_module ->
- %% This is a core module.
- io:put_chars(File, core_pp:format(Core));
-module(File, Kern) when element(1, Kern) == k_mdef ->
- %% This is a kernel module.
- io:put_chars(File, v3_kernel_pp:format(Kern));
- %%io:put_chars(File, io_lib:format("~p~n", [Kern]));
-module(File, {Mod,Exp,Attr,Kern}) ->
- %% This is output from beam_life (v3).
- io:fwrite(File, "~w.~n~p.~n~p.~n", [Mod,Exp,Attr]),
- foreach(fun (F) -> function(File, F) end, Kern);
-module(Stream, {Mod,Exp,Attr,Code,NumLabels}) ->
- %% This is output from beam_codegen.
- io:format(Stream, "{module, ~s}. %% version = ~w\n",
- [Mod, beam_opcodes:format_number()]),
- io:format(Stream, "\n{exports, ~p}.\n", [Exp]),
- io:format(Stream, "\n{attributes, ~p}.\n", [Attr]),
- io:format(Stream, "\n{labels, ~p}.\n", [NumLabels]),
- foreach(
- fun ({function,Name,Arity,Entry,Asm}) ->
- io:format(Stream, "\n\n{function, ~w, ~w, ~w}.\n",
- [Name, Arity, Entry]),
- foreach(fun(Op) -> print_op(Stream, Op) end, Asm) end,
- Code);
-module(Stream, {Mod,Exp,Inter}) ->
- %% Other kinds of intermediate formats.
- io:fwrite(Stream, "~w.~n~p.~n", [Mod,Exp]),
- foreach(fun (F) -> io:format(Stream, "~p.\n", [F]) end, Inter);
-module(Stream, [_|_]=Fs) ->
- %% Form-based abstract format.
- foreach(fun (F) -> io:format(Stream, "~p.\n", [F]) end, Fs).
-
-print_op(Stream, Label) when element(1, Label) == label ->
- io:format(Stream, " ~p.\n", [Label]);
-print_op(Stream, Op) ->
- io:format(Stream, " ~p.\n", [Op]).
-
-function(File, {function,Name,Arity,Args,Body,Vdb}) ->
- io:nl(File),
- io:format(File, "function ~p/~p.\n", [Name,Arity]),
- io:format(File, " ~p.\n", [Args]),
- print_vdb(File, Vdb),
- put(beam_listing_nl, true),
- foreach(fun(F) -> format(File, F, []) end, Body),
- nl(File),
- erase(beam_listing_nl).
-
-format(File, #l{ke=Ke,i=I,vdb=Vdb}, Ind) ->
- nl(File),
- ind_format(File, Ind, "~p ", [I]),
- print_vdb(File, Vdb),
- nl(File),
- format(File, Ke, Ind);
-format(File, Tuple, Ind) when is_tuple(Tuple) ->
- ind_format(File, Ind, "{", []),
- format_list(File, tuple_to_list(Tuple), [$\s|Ind]),
- ind_format(File, Ind, "}", []);
-format(File, List, Ind) when is_list(List) ->
- ind_format(File, Ind, "[", []),
- format_list(File, List, [$\s|Ind]),
- ind_format(File, Ind, "]", []);
-format(File, F, Ind) ->
- ind_format(File, Ind, "~p", [F]).
-
-format_list(File, [F], Ind) ->
- format(File, F, Ind);
-format_list(File, [F|Fs], Ind) ->
- format(File, F, Ind),
- ind_format(File, Ind, ",", []),
- format_list(File, Fs, Ind);
-format_list(_, [], _) -> ok.
-
-
-print_vdb(File, [{Var,F,E}|Vs]) ->
- io:format(File, "~p:~p..~p ", [Var,F,E]),
- print_vdb(File, Vs);
-print_vdb(_, []) -> ok.
-
-ind_format(File, Ind, Format, Args) ->
- case get(beam_listing_nl) of
- true ->
- put(beam_listing_nl, false),
- io:put_chars(File, Ind);
- false -> ok
- end,
- io:format(File, Format, Args).
-
-nl(File) ->
- case put(beam_listing_nl, true) of
- true -> ok;
- false -> io:nl(File)
- end.
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_opcodes.hrl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_opcodes.hrl
deleted file mode 100644
index 1ad0887314..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_opcodes.hrl
+++ /dev/null
@@ -1,12 +0,0 @@
-%% Warning: Do not edit this file. It was automatically
-%% generated by 'beam_makeops' on Wed Nov 24 17:52:43 2004.
-
--define(tag_u, 0).
--define(tag_i, 1).
--define(tag_a, 2).
--define(tag_x, 3).
--define(tag_y, 4).
--define(tag_f, 5).
--define(tag_h, 6).
--define(tag_z, 7).
-
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_type.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_type.erl
deleted file mode 100644
index 7d288b249c..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_type.erl
+++ /dev/null
@@ -1,551 +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: beam_type.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
-%%
-%% Purpose : Type-based optimisations.
-
--module(beam_type).
-
--export([module/2]).
-
--import(lists, [map/2,foldl/3,reverse/1,reverse/2,filter/2,member/2]).
-
-module({Mod,Exp,Attr,Fs0,Lc}, Opt) ->
- AllowFloatOpts = not member(no_float_opt, Opt),
- Fs = map(fun(F) -> function(F, AllowFloatOpts) end, Fs0),
- {ok,{Mod,Exp,Attr,Fs,Lc}}.
-
-function({function,Name,Arity,CLabel,Asm0}, AllowFloatOpts) ->
- Asm = opt(Asm0, AllowFloatOpts, [], tdb_new()),
- {function,Name,Arity,CLabel,Asm}.
-
-%% opt([Instruction], AllowFloatOpts, Accumulator, TypeDb) -> {[Instruction'],TypeDb'}
-%% Keep track of type information; try to simplify.
-
-opt([{block,Body1}|Is], AllowFloatOpts, [{block,Body0}|Acc], Ts0) ->
- {Body2,Ts} = simplify(Body1, Ts0, AllowFloatOpts),
- Body = beam_block:merge_blocks(Body0, Body2),
- opt(Is, AllowFloatOpts, [{block,Body}|Acc], Ts);
-opt([{block,Body0}|Is], AllowFloatOpts, Acc, Ts0) ->
- {Body,Ts} = simplify(Body0, Ts0, AllowFloatOpts),
- opt(Is, AllowFloatOpts, [{block,Body}|Acc], Ts);
-opt([I0|Is], AllowFloatOpts, Acc, Ts0) ->
- case simplify([I0], Ts0, AllowFloatOpts) of
- {[],Ts} -> opt(Is, AllowFloatOpts, Acc, Ts);
- {[I],Ts} -> opt(Is, AllowFloatOpts, [I|Acc], Ts)
- end;
-opt([], _, Acc, _) -> reverse(Acc).
-
-%% simplify(Instruction, TypeDb, AllowFloatOpts) -> NewInstruction
-%% Simplify an instruction using type information (this is
-%% technically a "strength reduction").
-
-simplify(Is, TypeDb, false) ->
- simplify(Is, TypeDb, no_float_opt, []);
-simplify(Is, TypeDb, true) ->
- case are_live_regs_determinable(Is) of
- false -> simplify(Is, TypeDb, no_float_opt, []);
- true -> simplify(Is, TypeDb, [], [])
- end.
-
-simplify([{set,[D],[{integer,Index},Reg],{bif,element,_}}=I0|Is]=Is0, Ts0, Rs0, Acc0) ->
- I = case max_tuple_size(Reg, Ts0) of
- Sz when 0 < Index, Index =< Sz ->
- {set,[D],[Reg],{get_tuple_element,Index-1}};
- _Other -> I0
- end,
- Ts = update(I, Ts0),
- {Rs,Acc} = flush(Rs0, Is0, Acc0),
- simplify(Is, Ts, Rs, [I|checkerror(Acc)]);
-simplify([{set,[D0],[A],{bif,'-',{f,0}}}=I|Is]=Is0, Ts0, Rs0, Acc0)
- when Rs0 =/= no_float_opt ->
- case tdb_find(A, Ts0) of
- float ->
- {Rs1,Acc1} = load_reg(A, Ts0, Rs0, Acc0),
- {D,Rs} = find_dest(D0, Rs1),
- Areg = fetch_reg(A, Rs),
- Acc = [{set,[D],[Areg],{bif,fnegate,{f,0}}}|clearerror(Acc1)],
- Ts = tdb_update([{D0,float}], Ts0),
- simplify(Is, Ts, Rs, Acc);
- _Other ->
- Ts = update(I, Ts0),
- {Rs,Acc} = flush(Rs0, Is0, Acc0),
- simplify(Is, Ts, Rs, [I|checkerror(Acc)])
- end;
-simplify([{set,[_],[_],{bif,_,{f,0}}}=I|Is]=Is0, Ts0, Rs0, Acc0) ->
- Ts = update(I, Ts0),
- {Rs,Acc} = flush(Rs0, Is0, Acc0),
- simplify(Is, Ts, Rs, [I|checkerror(Acc)]);
-simplify([{set,[D0],[A,B],{bif,Op0,{f,0}}}=I|Is]=Is0, Ts0, Rs0, Acc0)
- when Rs0 =/= no_float_opt ->
- case float_op(Op0, A, B, Ts0) of
- no ->
- Ts = update(I, Ts0),
- {Rs,Acc} = flush(Rs0, Is0, Acc0),
- simplify(Is, Ts, Rs, [I|checkerror(Acc)]);
- {yes,Op} ->
- {Rs1,Acc1} = load_reg(A, Ts0, Rs0, Acc0),
- {Rs2,Acc2} = load_reg(B, Ts0, Rs1, Acc1),
- {D,Rs} = find_dest(D0, Rs2),
- Areg = fetch_reg(A, Rs),
- Breg = fetch_reg(B, Rs),
- Acc = [{set,[D],[Areg,Breg],{bif,Op,{f,0}}}|clearerror(Acc2)],
- Ts = tdb_update([{D0,float}], Ts0),
- simplify(Is, Ts, Rs, Acc)
- end;
-simplify([{set,[D],[TupleReg],{get_tuple_element,0}}=I|Is0], Ts0, Rs0, Acc0) ->
- case tdb_find(TupleReg, Ts0) of
- {tuple,_,[Contents]} ->
- Ts = tdb_update([{D,Contents}], Ts0),
- {Rs,Acc} = flush(Rs0, Is0, Acc0),
- simplify(Is0, Ts, Rs, [{set,[D],[Contents],move}|Acc]);
- _ ->
- Ts = update(I, Ts0),
- {Rs,Acc} = flush(Rs0, Is0, Acc0),
- simplify(Is0, Ts, Rs, [I|checkerror(Acc)])
- end;
-simplify([{set,_,_,{'catch',_}}=I|Is]=Is0, _Ts, Rs0, Acc0) ->
- Acc = flush_all(Rs0, Is0, Acc0),
- simplify(Is, tdb_new(), Rs0, [I|Acc]);
-simplify([{test,is_tuple,_,[R]}=I|Is], Ts, Rs, Acc) ->
- case tdb_find(R, Ts) of
- {tuple,_,_} -> simplify(Is, Ts, Rs, Acc);
- _ ->
- simplify(Is, Ts, Rs, [I|Acc])
- end;
-simplify([{test,test_arity,_,[R,Arity]}=I|Is], Ts0, Rs, Acc) ->
- case tdb_find(R, Ts0) of
- {tuple,Arity,_} ->
- simplify(Is, Ts0, Rs, Acc);
- _Other ->
- Ts = update(I, Ts0),
- simplify(Is, Ts, Rs, [I|Acc])
- end;
-simplify([{test,is_eq_exact,Fail,[R,{atom,_}=Atom]}=I|Is0], Ts0, Rs0, Acc0) ->
- Acc1 = case tdb_find(R, Ts0) of
- {atom,_}=Atom -> Acc0;
- {atom,_} -> [{jump,Fail}|Acc0];
- _ -> [I|Acc0]
- end,
- Ts = update(I, Ts0),
- {Rs,Acc} = flush(Rs0, Is0, Acc1),
- simplify(Is0, Ts, Rs, Acc);
-simplify([I|Is]=Is0, Ts0, Rs0, Acc0) ->
- Ts = update(I, Ts0),
- {Rs,Acc} = flush(Rs0, Is0, Acc0),
- simplify(Is, Ts, Rs, [I|Acc]);
-simplify([], Ts, Rs, Acc) ->
- Is0 = reverse(flush_all(Rs, [], Acc)),
- Is1 = opt_fmoves(Is0, []),
- Is = add_ftest_heap(Is1),
- {Is,Ts}.
-
-opt_fmoves([{set,[{x,_}=R],[{fr,_}]=Src,fmove}=I1,
- {set,[{y,_}]=Dst,[{x,_}=R],move}=I2|Is], Acc) ->
- case beam_block:is_killed(R, Is) of
- false -> opt_fmoves(Is, [I2,I1|Acc]);
- true -> opt_fmoves(Is, [{set,Dst,Src,fmove}|Acc])
- end;
-opt_fmoves([I|Is], Acc) ->
- opt_fmoves(Is, [I|Acc]);
-opt_fmoves([], Acc) -> reverse(Acc).
-
-clearerror(Is) ->
- clearerror(Is, Is).
-
-clearerror([{set,[],[],fclearerror}|_], OrigIs) -> OrigIs;
-clearerror([{set,[],[],fcheckerror}|_], OrigIs) -> [{set,[],[],fclearerror}|OrigIs];
-clearerror([_|Is], OrigIs) -> clearerror(Is, OrigIs);
-clearerror([], OrigIs) -> [{set,[],[],fclearerror}|OrigIs].
-
-%% update(Instruction, TypeDb) -> NewTypeDb
-%% Update the type database to account for executing an instruction.
-%%
-%% First the cases for instructions inside basic blocks.
-update({set,[D],[S],move}, Ts0) ->
- Ops = case tdb_find(S, Ts0) of
- error -> [{D,kill}];
- Info -> [{D,Info}]
- end,
- tdb_update(Ops, Ts0);
-update({set,[D],[{integer,I},Reg],{bif,element,_}}, Ts0) ->
- tdb_update([{Reg,{tuple,I,[]}},{D,kill}], Ts0);
-update({set,[D],[_Index,Reg],{bif,element,_}}, Ts0) ->
- tdb_update([{Reg,{tuple,0,[]}},{D,kill}], Ts0);
-update({set,[D],[S],{get_tuple_element,0}}, Ts) ->
- tdb_update([{D,{tuple_element,S,0}}], Ts);
-update({set,[D],[S],{bif,float,{f,0}}}, Ts0) ->
- %% Make sure we reject non-numeric literal argument.
- case possibly_numeric(S) of
- true -> tdb_update([{D,float}], Ts0);
- false -> Ts0
- end;
-update({set,[D],[S1,S2],{bif,'/',{f,0}}}, Ts0) ->
- %% Make sure we reject non-numeric literals.
- case possibly_numeric(S1) andalso possibly_numeric(S2) of
- true -> tdb_update([{D,float}], Ts0);
- false -> Ts0
- end;
-update({set,[D],[S1,S2],{bif,Op,{f,0}}}, Ts0) ->
- case arith_op(Op) of
- no ->
- tdb_update([{D,kill}], Ts0);
- {yes,_} ->
- case {tdb_find(S1, Ts0),tdb_find(S2, Ts0)} of
- {float,_} -> tdb_update([{D,float}], Ts0);
- {_,float} -> tdb_update([{D,float}], Ts0);
- {_,_} -> tdb_update([{D,kill}], Ts0)
- end
- end;
-update({set,[],_Src,_Op}, Ts0) -> Ts0;
-update({set,[D],_Src,_Op}, Ts0) ->
- tdb_update([{D,kill}], Ts0);
-update({set,[D1,D2],_Src,_Op}, Ts0) ->
- tdb_update([{D1,kill},{D2,kill}], Ts0);
-update({allocate,_,_}, Ts) -> Ts;
-update({init,D}, Ts) ->
- tdb_update([{D,kill}], Ts);
-update({kill,D}, Ts) ->
- tdb_update([{D,kill}], Ts);
-update({'%live',_}, Ts) -> Ts;
-
-%% Instructions outside of blocks.
-update({test,is_float,_Fail,[Src]}, Ts0) ->
- tdb_update([{Src,float}], Ts0);
-update({test,test_arity,_Fail,[Src,Arity]}, Ts0) ->
- tdb_update([{Src,{tuple,Arity,[]}}], Ts0);
-update({test,is_eq_exact,_,[Reg,{atom,_}=Atom]}, Ts) ->
- case tdb_find(Reg, Ts) of
- error ->
- Ts;
- {tuple_element,TupleReg,0} ->
- tdb_update([{TupleReg,{tuple,1,[Atom]}}], Ts);
- _ ->
- Ts
- end;
-update({test,_Test,_Fail,_Other}, Ts) -> Ts;
-update({call_ext,1,{extfunc,math,Math,1}}, Ts) ->
- case is_math_bif(Math, 1) of
- true -> tdb_update([{{x,0},float}], Ts);
- false -> tdb_kill_xregs(Ts)
- end;
-update({call_ext,2,{extfunc,math,Math,2}}, Ts) ->
- case is_math_bif(Math, 2) of
- true -> tdb_update([{{x,0},float}], Ts);
- false -> tdb_kill_xregs(Ts)
- end;
-update({call_ext,3,{extfunc,erlang,setelement,3}}, Ts0) ->
- Op = case tdb_find({x,1}, Ts0) of
- error -> kill;
- Info -> Info
- end,
- Ts1 = tdb_kill_xregs(Ts0),
- tdb_update([{{x,0},Op}], Ts1);
-update({call,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts);
-update({call_ext,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts);
-update({make_fun2,_,_,_,_}, Ts) -> tdb_kill_xregs(Ts);
-
-%% The instruction is unknown. Kill all information.
-update(_I, _Ts) -> tdb_new().
-
-is_math_bif(cos, 1) -> true;
-is_math_bif(cosh, 1) -> true;
-is_math_bif(sin, 1) -> true;
-is_math_bif(sinh, 1) -> true;
-is_math_bif(tan, 1) -> true;
-is_math_bif(tanh, 1) -> true;
-is_math_bif(acos, 1) -> true;
-is_math_bif(acosh, 1) -> true;
-is_math_bif(asin, 1) -> true;
-is_math_bif(asinh, 1) -> true;
-is_math_bif(atan, 1) -> true;
-is_math_bif(atanh, 1) -> true;
-is_math_bif(erf, 1) -> true;
-is_math_bif(erfc, 1) -> true;
-is_math_bif(exp, 1) -> true;
-is_math_bif(log, 1) -> true;
-is_math_bif(log10, 1) -> true;
-is_math_bif(sqrt, 1) -> true;
-is_math_bif(atan2, 2) -> true;
-is_math_bif(pow, 2) -> true;
-is_math_bif(pi, 0) -> true;
-is_math_bif(_, _) -> false.
-
-%% Reject non-numeric literals.
-possibly_numeric({x,_}) -> true;
-possibly_numeric({y,_}) -> true;
-possibly_numeric({integer,_}) -> true;
-possibly_numeric({float,_}) -> true;
-possibly_numeric(_) -> false.
-
-max_tuple_size(Reg, Ts) ->
- case tdb_find(Reg, Ts) of
- {tuple,Sz,_} -> Sz;
- _Other -> 0
- end.
-
-float_op('/', A, B, _) ->
- case possibly_numeric(A) andalso possibly_numeric(B) of
- true -> {yes,fdiv};
- false -> no
- end;
-float_op(Op, {float,_}, B, _) ->
- case possibly_numeric(B) of
- true -> arith_op(Op);
- false -> no
- end;
-float_op(Op, A, {float,_}, _) ->
- case possibly_numeric(A) of
- true -> arith_op(Op);
- false -> no
- end;
-float_op(Op, A, B, Ts) ->
- case {tdb_find(A, Ts),tdb_find(B, Ts)} of
- {float,_} -> arith_op(Op);
- {_,float} -> arith_op(Op);
- {_,_} -> no
- end.
-
-find_dest(V, Rs0) ->
- case find_reg(V, Rs0) of
- {ok,FR} ->
- {FR,mark(V, Rs0, dirty)};
- error ->
- Rs = put_reg(V, Rs0, dirty),
- {ok,FR} = find_reg(V, Rs),
- {FR,Rs}
- end.
-
-load_reg({float,_}=F, _, Rs0, Is0) ->
- Rs = put_reg(F, Rs0, clean),
- {ok,FR} = find_reg(F, Rs),
- Is = [{set,[FR],[F],fmove}|Is0],
- {Rs,Is};
-load_reg(V, Ts, Rs0, Is0) ->
- case find_reg(V, Rs0) of
- {ok,_FR} -> {Rs0,Is0};
- error ->
- Rs = put_reg(V, Rs0, clean),
- {ok,FR} = find_reg(V, Rs),
- Op = case tdb_find(V, Ts) of
- float -> fmove;
- _ -> fconv
- end,
- Is = [{set,[FR],[V],Op}|Is0],
- {Rs,Is}
- end.
-
-arith_op('+') -> {yes,fadd};
-arith_op('-') -> {yes,fsub};
-arith_op('*') -> {yes,fmul};
-arith_op('/') -> {yes,fdiv};
-arith_op(_) -> no.
-
-flush(no_float_opt, _, Acc) -> {no_float_opt,Acc};
-flush(Rs, [{set,[_],[],{put_tuple,_}}|_]=Is0, Acc0) ->
- Acc = flush_all(Rs, Is0, Acc0),
- {[],Acc};
-flush(Rs0, [{set,Ds,Ss,_Op}|_], Acc0) ->
- Save = gb_sets:from_list(Ss),
- Acc = save_regs(Rs0, Save, Acc0),
- Rs1 = foldl(fun(S, A) -> mark(S, A, clean) end, Rs0, Ss),
- Kill = gb_sets:from_list(Ds),
- Rs = kill_regs(Rs1, Kill),
- {Rs,Acc};
-flush(Rs0, Is, Acc0) ->
- Acc = flush_all(Rs0, Is, Acc0),
- {[],Acc}.
-
-flush_all(no_float_opt, _, Acc) -> Acc;
-flush_all([{_,{float,_},_}|Rs], Is, Acc) ->
- flush_all(Rs, Is, Acc);
-flush_all([{I,V,dirty}|Rs], Is, Acc0) ->
- Acc = checkerror(Acc0),
- case beam_block:is_killed(V, Is) of
- true -> flush_all(Rs, Is, Acc);
- false -> flush_all(Rs, Is, [{set,[V],[{fr,I}],fmove}|Acc])
- end;
-flush_all([{_,_,clean}|Rs], Is, Acc) -> flush_all(Rs, Is, Acc);
-flush_all([free|Rs], Is, Acc) -> flush_all(Rs, Is, Acc);
-flush_all([], _, Acc) -> Acc.
-
-save_regs(Rs, Save, Acc) ->
- foldl(fun(R, A) -> save_reg(R, Save, A) end, Acc, Rs).
-
-save_reg({I,V,dirty}, Save, Acc) ->
- case gb_sets:is_member(V, Save) of
- true -> [{set,[V],[{fr,I}],fmove}|checkerror(Acc)];
- false -> Acc
- end;
-save_reg(_, _, Acc) -> Acc.
-
-kill_regs(Rs, Kill) ->
- map(fun(R) -> kill_reg(R, Kill) end, Rs).
-
-kill_reg({_,V,_}=R, Kill) ->
- case gb_sets:is_member(V, Kill) of
- true -> free;
- false -> R
- end;
-kill_reg(R, _) -> R.
-
-mark(V, [{I,V,_}|Rs], Mark) -> [{I,V,Mark}|Rs];
-mark(V, [R|Rs], Mark) -> [R|mark(V, Rs, Mark)];
-mark(_, [], _) -> [].
-
-fetch_reg(V, [{I,V,_}|_]) -> {fr,I};
-fetch_reg(V, [_|SRs]) -> fetch_reg(V, SRs).
-
-find_reg(V, [{I,V,_}|_]) -> {ok,{fr,I}};
-find_reg(V, [_|SRs]) -> find_reg(V, SRs);
-find_reg(_, []) -> error.
-
-put_reg(V, Rs, Dirty) -> put_reg_1(V, Rs, Dirty, 0).
-
-put_reg_1(V, [free|Rs], Dirty, I) -> [{I,V,Dirty}|Rs];
-put_reg_1(V, [R|Rs], Dirty, I) -> [R|put_reg_1(V, Rs, Dirty, I+1)];
-put_reg_1(V, [], Dirty, I) -> [{I,V,Dirty}].
-
-checkerror(Is) ->
- checkerror_1(Is, Is).
-
-checkerror_1([{set,[],[],fcheckerror}|_], OrigIs) -> OrigIs;
-checkerror_1([{set,[],[],fclearerror}|_], OrigIs) -> OrigIs;
-checkerror_1([{set,_,_,{bif,fadd,_}}|_], OrigIs) -> checkerror_2(OrigIs);
-checkerror_1([{set,_,_,{bif,fsub,_}}|_], OrigIs) -> checkerror_2(OrigIs);
-checkerror_1([{set,_,_,{bif,fmul,_}}|_], OrigIs) -> checkerror_2(OrigIs);
-checkerror_1([{set,_,_,{bif,fdiv,_}}|_], OrigIs) -> checkerror_2(OrigIs);
-checkerror_1([{set,_,_,{bif,fnegate,_}}|_], OrigIs) -> checkerror_2(OrigIs);
-checkerror_1([_|Is], OrigIs) -> checkerror_1(Is, OrigIs);
-checkerror_1([], OrigIs) -> OrigIs.
-
-checkerror_2(OrigIs) -> [{set,[],[],fcheckerror}|OrigIs].
-
-add_ftest_heap(Is) ->
- add_ftest_heap_1(reverse(Is), 0, []).
-
-add_ftest_heap_1([{set,_,[{fr,_}],fmove}=I|Is], Floats, Acc) ->
- add_ftest_heap_1(Is, Floats+1, [I|Acc]);
-add_ftest_heap_1([{allocate,_,_}=I|Is], 0, Acc) ->
- reverse(Is, [I|Acc]);
-add_ftest_heap_1([{allocate,Regs,{Z,Stk,Heap,Inits}}|Is], Floats, Acc) ->
- reverse(Is, [{allocate,Regs,{Z,Stk,Heap,Floats,Inits}}|Acc]);
-add_ftest_heap_1([I|Is], Floats, Acc) ->
- add_ftest_heap_1(Is, Floats, [I|Acc]);
-add_ftest_heap_1([], 0, Acc) ->
- Acc;
-add_ftest_heap_1([], Floats, Is) ->
- Regs = beam_block:live_at_entry(Is),
- [{allocate,Regs,{nozero,nostack,0,Floats,[]}}|Is].
-
-are_live_regs_determinable([{allocate,_,_}|_]) -> true;
-are_live_regs_determinable([{'%live',_}|_]) -> true;
-are_live_regs_determinable([_|Is]) -> are_live_regs_determinable(Is);
-are_live_regs_determinable([]) -> false.
-
-
-%%% Routines for maintaining a type database. The type database
-%%% associates type information with registers.
-%%%
-%%% {tuple,Size,First} means that the corresponding register contains a
-%%% tuple with *at least* Size elements. An tuple with unknown
-%%% size is represented as {tuple,0}. First is either [] (meaning that
-%%% the tuple's first element is unknown) or [FirstElement] (the contents
-%%% of the first element).
-%%%
-%%% 'float' means that the register contains a float.
-
-%% tdb_new() -> EmptyDataBase
-%% Creates a new, empty type database.
-
-tdb_new() -> [].
-
-%% tdb_find(Register, Db) -> Information|error
-%% Returns type information or the atom error if there are no type
-%% information available for Register.
-
-tdb_find(Key, [{K,_}|_]) when Key < K -> error;
-tdb_find(Key, [{Key,Info}|_]) -> Info;
-tdb_find(Key, [_|Db]) -> tdb_find(Key, Db);
-tdb_find(_, []) -> error.
-
-%% tdb_update([UpdateOp], Db) -> NewDb
-%% UpdateOp = {Register,kill}|{Register,NewInfo}
-%% Updates a type database. If a 'kill' operation is given, the type
-%% information for that register will be removed from the database.
-%% A kill operation takes precende over other operations for the same
-%% register (i.e. [{{x,0},kill},{{x,0},{tuple,5}}] means that the
-%% the existing type information, if any, will be discarded, and the
-%% the '{tuple,5}' information ignored.
-%%
-%% If NewInfo information is given and there exists information about
-%% the register, the old and new type information will be merged.
-%% For instance, {tuple,5} and {tuple,10} will be merged to produce
-%% {tuple,10}.
-
-tdb_update(Uis0, Ts0) ->
- Uis1 = filter(fun ({{x,_},_Op}) -> true;
- ({{y,_},_Op}) -> true;
- (_) -> false
- end, Uis0),
- tdb_update1(lists:sort(Uis1), Ts0).
-
-tdb_update1([{Key,kill}|Ops], [{K,_Old}|_]=Db) when Key < K ->
- tdb_update1(remove_key(Key, Ops), Db);
-tdb_update1([{Key,_New}=New|Ops], [{K,_Old}|_]=Db) when Key < K ->
- [New|tdb_update1(Ops, Db)];
-tdb_update1([{Key,kill}|Ops], [{Key,_}|Db]) ->
- tdb_update1(remove_key(Key, Ops), Db);
-tdb_update1([{Key,NewInfo}|Ops], [{Key,OldInfo}|Db]) ->
- [{Key,merge_type_info(NewInfo, OldInfo)}|tdb_update1(Ops, Db)];
-tdb_update1([{_,_}|_]=Ops, [Old|Db]) ->
- [Old|tdb_update1(Ops, Db)];
-tdb_update1([{Key,kill}|Ops], []) ->
- tdb_update1(remove_key(Key, Ops), []);
-tdb_update1([{_,_}=New|Ops], []) ->
- [New|tdb_update1(Ops, [])];
-tdb_update1([], Db) -> Db.
-
-%% tdb_kill_xregs(Db) -> NewDb
-%% Kill all information about x registers. Also kill all tuple_element
-%% dependencies from y registers to x registers.
-
-tdb_kill_xregs([{{x,_},_Type}|Db]) -> tdb_kill_xregs(Db);
-tdb_kill_xregs([{{y,_},{tuple_element,{x,_},_}}|Db]) -> tdb_kill_xregs(Db);
-tdb_kill_xregs([Any|Db]) -> [Any|tdb_kill_xregs(Db)];
-tdb_kill_xregs([]) -> [].
-
-remove_key(Key, [{Key,_Op}|Ops]) -> remove_key(Key, Ops);
-remove_key(_, Ops) -> Ops.
-
-merge_type_info(I, I) -> I;
-merge_type_info({tuple,Sz1,Same}, {tuple,Sz2,Same}=Max) when Sz1 < Sz2 ->
- Max;
-merge_type_info({tuple,Sz1,Same}=Max, {tuple,Sz2,Same}) when Sz1 > Sz2 ->
- Max;
-merge_type_info({tuple,Sz1,[]}, {tuple,Sz2,First}) ->
- merge_type_info({tuple,Sz1,First}, {tuple,Sz2,First});
-merge_type_info({tuple,Sz1,First}, {tuple,Sz2,_}) ->
- merge_type_info({tuple,Sz1,First}, {tuple,Sz2,First});
-merge_type_info(NewType, _) ->
- verify_type(NewType),
- NewType.
-
-verify_type({tuple,Sz,[]}) when is_integer(Sz) -> ok;
-verify_type({tuple,Sz,[_]}) when is_integer(Sz) -> ok;
-verify_type({tuple_element,_,_}) -> ok;
-verify_type(float) -> ok;
-verify_type({atom,_}) -> ok.
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_validator.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_validator.erl
deleted file mode 100644
index a01be447b0..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/beam_validator.erl
+++ /dev/null
@@ -1,1022 +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: beam_validator.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
-
--module(beam_validator).
-
--export([file/1,files/1]).
-
-%% Interface for compiler.
--export([module/2,format_error/1]).
-
--import(lists, [reverse/1,foldl/3]).
-
--define(MAXREG, 1024).
-
--define(DEBUG, 1).
--undef(DEBUG).
--ifdef(DEBUG).
--define(DBG_FORMAT(F, D), (io:format((F), (D)))).
--else.
--define(DBG_FORMAT(F, D), ok).
--endif.
-
-%%%
-%%% API functions.
-%%%
-
-files([F|Fs]) ->
- ?DBG_FORMAT("# Verifying: ~p~n", [F]),
- case file(F) of
- ok -> ok;
- {error,Es} ->
- io:format("~p:~n~s~n", [F,format_error(Es)])
- end,
- files(Fs);
-files([]) -> ok.
-
-file(Name) when is_list(Name) ->
- case case filename:extension(Name) of
- ".S" -> s_file(Name);
- ".beam" -> beam_file(Name)
- end of
- [] -> ok;
- Es -> {error,Es}
- end.
-
-%% To be called by the compiler.
-module({Mod,Exp,Attr,Fs,Lc}=Code, _Opts)
- when is_atom(Mod), is_list(Exp), is_list(Attr), is_integer(Lc) ->
- case validate(Fs) of
- [] -> {ok,Code};
- Es0 ->
- Es = [{?MODULE,E} || E <- Es0],
- {error,[{atom_to_list(Mod),Es}]}
- end.
-
-format_error([]) -> [];
-format_error([{{M,F,A},{I,Off,Desc}}|Es]) ->
- [io_lib:format(" ~p:~p/~p+~p:~n ~p - ~p~n",
- [M,F,A,Off,I,Desc])|format_error(Es)];
-format_error({{_M,F,A},{I,Off,Desc}}) ->
- io_lib:format(
- "function ~p/~p+~p:~n"
- " Internal consistency check failed - please report this bug.~n"
- " Instruction: ~p~n"
- " Error: ~p:~n", [F,A,Off,I,Desc]).
-
-%%%
-%%% Local functions follow.
-%%%
-
-s_file(Name) ->
- {ok,Is} = file:consult(Name),
- Fs = find_functions(Is),
- validate(Fs).
-
-find_functions(Fs) ->
- find_functions_1(Fs, none, [], []).
-
-find_functions_1([{function,Name,Arity,Entry}|Is], Func, FuncAcc, Acc0) ->
- Acc = add_func(Func, FuncAcc, Acc0),
- find_functions_1(Is, {Name,Arity,Entry}, [], Acc);
-find_functions_1([I|Is], Func, FuncAcc, Acc) ->
- find_functions_1(Is, Func, [I|FuncAcc], Acc);
-find_functions_1([], Func, FuncAcc, Acc) ->
- reverse(add_func(Func, FuncAcc, Acc)).
-
-add_func(none, _, Acc) -> Acc;
-add_func({Name,Arity,Entry}, Is, Acc) ->
- [{function,Name,Arity,Entry,reverse(Is)}|Acc].
-
-beam_file(Name) ->
- try beam_disasm:file(Name) of
- {error,beam_lib,Reason} -> [{beam_lib,Reason}];
- {beam_file,L} ->
- {value,{code,Code0}} = lists:keysearch(code, 1, L),
- Code = beam_file_1(Code0, []),
- validate(Code)
- catch _:_ -> [disassembly_failed]
- end.
-
-beam_file_1([F0|Fs], Acc) ->
- F = conv_func(F0),
- beam_file_1(Fs, [F|Acc]);
-beam_file_1([], Acc) -> reverse(Acc).
-
-%% Convert from the disassembly format to the internal format
-%% used by the compiler (as passed to the assembler).
-
-conv_func(Is) ->
- conv_func_1(labels(Is)).
-
-conv_func_1({Ls,[{func_info,[{atom,M},{atom,F},Ar]},
- {label,Entry}=Le|Is]}) ->
- %% The entry label gets maybe not correct here
- {function,F,Ar,Entry,
- [{label,L}||L<-Ls]++[{func_info,{atom,M},{atom,F},Ar},Le|Is]}.
-
-%%%
-%%% The validator follows.
-%%%
-%%% The purpose of the validator is find errors in the generated code
-%%% that may cause the emulator to crash or behave strangely.
-%%% We don't care about type errors in the user's code that will
-%%% cause a proper exception at run-time.
-%%%
-
-%%% Things currently not checked. XXX
-%%%
-%%% - That floating point registers are initialized before used.
-%%% - That fclearerror and fcheckerror are used properly.
-%%% - Heap allocation for floating point numbers.
-%%% - Heap allocation for binaries.
-%%% - That a catchtag or trytag is not overwritten by the wrong
-%%% type of instruction (such as move/2).
-%%% - Make sure that all catchtags and trytags have been removed
-%%% from the stack at return/tail call.
-%%% - Verify get_list instructions.
-%%%
-
-%% validate([Function]) -> [] | [Error]
-%% A list of functions with their code. The code is in the same
-%% format as used in the compiler and in .S files.
-validate([]) -> [];
-validate([{function,Name,Ar,Entry,Code}|Fs]) ->
- try validate_1(Code, Name, Ar, Entry) of
- _ -> validate(Fs)
- catch
- Error ->
- [Error|validate(Fs)];
- error:Error ->
- [validate_error(Error, Name, Ar)|validate(Fs)]
- end.
-
--ifdef(DEBUG).
-validate_error(Error, Name, Ar) ->
- exit(validate_error_1(Error, Name, Ar)).
--else.
-validate_error(Error, Name, Ar) ->
- validate_error_1(Error, Name, Ar).
--endif.
-validate_error_1(Error, Name, Ar) ->
- {{'_',Name,Ar},
- {internal_error,'_',{Error,erlang:get_stacktrace()}}}.
-
--record(st, %Emulation state
- {x=init_regs(0, term), %x register info.
- y=init_regs(0, initialized), %y register info.
- numy=none, %Number of y registers.
- h=0, %Available heap size.
- ct=[] %List of hot catch/try labels
- }).
-
--record(vst, %Validator state
- {current=none, %Current state
- branched=gb_trees:empty() %States at jumps
- }).
-
--ifdef(DEBUG).
-print_st(#st{x=Xs,y=Ys,numy=NumY,h=H,ct=Ct}) ->
- io:format(" #st{x=~p~n"
- " y=~p~n"
- " numy=~p,h=~p,ct=~w~n",
- [gb_trees:to_list(Xs),gb_trees:to_list(Ys),NumY,H,Ct]).
--endif.
-
-validate_1(Is, Name, Arity, Entry) ->
- validate_2(labels(Is), Name, Arity, Entry).
-
-validate_2({Ls1,[{func_info,{atom,Mod},{atom,Name},Arity}=_F|Is]},
- Name, Arity, Entry) ->
- lists:foreach(fun (_L) -> ?DBG_FORMAT(" ~p.~n", [_L]) end, Ls1),
- ?DBG_FORMAT(" ~p.~n", [_F]),
- validate_3(labels(Is), Name, Arity, Entry, Mod, Ls1);
-validate_2({Ls1,Is}, Name, Arity, _Entry) ->
- error({{'_',Name,Arity},{first(Is),length(Ls1),illegal_instruction}}).
-
-validate_3({Ls2,Is}, Name, Arity, Entry, Mod, Ls1) ->
- lists:foreach(fun (_L) -> ?DBG_FORMAT(" ~p.~n", [_L]) end, Ls2),
- Offset = 1 + length(Ls2),
- case lists:member(Entry, Ls2) of
- true ->
- St = init_state(Arity),
- Vst = #vst{current=St,
- branched=gb_trees_from_list([{L,St} || L <- Ls1])},
- valfun(Is, {Mod,Name,Arity}, Offset, Vst);
- false ->
- error({{Mod,Name,Arity},{first(Is),Offset,no_entry_label}})
- end.
-
-first([X|_]) -> X;
-first([]) -> [].
-
-labels(Is) ->
- labels_1(Is, []).
-
-labels_1([{label,L}|Is], R) ->
- labels_1(Is, [L|R]);
-labels_1(Is, R) ->
- {lists:reverse(R),Is}.
-
-init_state(Arity) ->
- Xs = init_regs(Arity, term),
- Ys = init_regs(0, initialized),
- #st{x=Xs,y=Ys,numy=none,h=0,ct=[]}.
-
-init_regs(0, _) ->
- gb_trees:empty();
-init_regs(N, Type) ->
- gb_trees_from_list([{R,Type} || R <- lists:seq(0, N-1)]).
-
-valfun([], _MFA, _Offset, Vst) -> Vst;
-valfun([I|Is], MFA, Offset, Vst) ->
- ?DBG_FORMAT(" ~p.\n", [I]),
- valfun(Is, MFA, Offset+1,
- try valfun_1(I, Vst)
- catch Error ->
- error({MFA,{I,Offset,Error}})
- end).
-
-%% Instructions that are allowed in dead code or when failing,
-%% that is while the state is undecided in some way.
-valfun_1({label,Lbl}, #vst{current=St0,branched=B}=Vst) ->
- St = merge_states(Lbl, St0, B),
- Vst#vst{current=St,branched=gb_trees:enter(Lbl, St, B)};
-valfun_1(_I, #vst{current=none}=Vst) ->
- %% Ignore instructions after erlang:error/1,2, which
- %% the original R10B compiler thought would return.
- ?DBG_FORMAT("Ignoring ~p\n", [_I]),
- Vst;
-valfun_1({badmatch,Src}, Vst) ->
- assert_term(Src, Vst),
- kill_state(Vst);
-valfun_1({case_end,Src}, Vst) ->
- assert_term(Src, Vst),
- kill_state(Vst);
-valfun_1(if_end, Vst) ->
- kill_state(Vst);
-valfun_1({try_case_end,Src}, Vst) ->
- assert_term(Src, Vst),
- kill_state(Vst);
-%% Instructions that can not cause exceptions
-valfun_1({move,Src,Dst}, Vst) ->
- Type = get_term_type(Src, Vst),
- set_type_reg(Type, Dst, Vst);
-valfun_1({fmove,Src,{fr,_}}, Vst) ->
- assert_type(float, Src, Vst);
-valfun_1({fmove,{fr,_},Dst}, Vst) ->
- set_type_reg({float,[]}, Dst, Vst);
-valfun_1({kill,{y,_}=Reg}, Vst) ->
- set_type_y(initialized, Reg, Vst);
-valfun_1({test_heap,Heap,Live}, Vst) ->
- test_heap(Heap, Live, Vst);
-valfun_1({bif,_Op,nofail,Src,Dst}, Vst) ->
- validate_src(Src, Vst),
- set_type_reg(term, Dst, Vst);
-%% Put instructions.
-valfun_1({put_list,A,B,Dst}, Vst0) ->
- assert_term(A, Vst0),
- assert_term(B, Vst0),
- Vst = eat_heap(2, Vst0),
- set_type_reg(cons, Dst, Vst);
-valfun_1({put_tuple,Sz,Dst}, Vst0) when is_integer(Sz) ->
- Vst = eat_heap(1, Vst0),
- set_type_reg({tuple,Sz}, Dst, Vst);
-valfun_1({put,Src}, Vst) ->
- assert_term(Src, Vst),
- eat_heap(1, Vst);
-valfun_1({put_string,Sz,_,Dst}, Vst0) when is_integer(Sz) ->
- Vst = eat_heap(2*Sz, Vst0),
- set_type_reg(cons, Dst, Vst);
-%% Allocate and deallocate, et.al
-valfun_1({allocate,Stk,Live}, Vst) ->
- allocate(false, Stk, 0, Live, Vst);
-valfun_1({allocate_heap,Stk,Heap,Live}, Vst) ->
- allocate(false, Stk, Heap, Live, Vst);
-valfun_1({allocate_zero,Stk,Live}, Vst) ->
- allocate(true, Stk, 0, Live, Vst);
-valfun_1({allocate_heap_zero,Stk,Heap,Live}, Vst) ->
- allocate(true, Stk, Heap, Live, Vst);
-valfun_1({init,{y,_}=Reg}, Vst) ->
- set_type_y(initialized, Reg, Vst);
-valfun_1({deallocate,StkSize}, #vst{current=#st{numy=StkSize,ct=[]}}=Vst) ->
- deallocate(Vst);
-valfun_1({deallocate,_}, #vst{current=#st{numy=NumY,ct=[]}}) ->
- error({allocated,NumY});
-valfun_1({deallocate,_}, #vst{current=#st{ct=Fails}}) ->
- error({catch_try_stack,Fails});
-%% Catch & try.
-valfun_1({'catch',Dst,{f,Fail}}, Vst0) when Fail /= none ->
- Vst = #vst{current=#st{ct=Fails}=St} =
- set_type_y({catchtag,Fail}, Dst, Vst0),
- Vst#vst{current=St#st{ct=[Fail|Fails]}};
-valfun_1({'try',Dst,{f,Fail}}, Vst0) ->
- Vst = #vst{current=#st{ct=Fails}=St} =
- set_type_y({trytag,Fail}, Dst, Vst0),
- Vst#vst{current=St#st{ct=[Fail|Fails]}};
-%% Do a postponed state branch if necessary and try next set of instructions
-valfun_1(I, #vst{current=#st{ct=[]}}=Vst) ->
- valfun_2(I, Vst);
-valfun_1(I, #vst{current=#st{ct=Fails}}=Vst0) ->
- %% Perform a postponed state branch
- Vst = #vst{current=St} = lists:foldl(fun branch_state/2, Vst0, Fails),
- valfun_2(I, Vst#vst{current=St#st{ct=[]}}).
-
-%% Instructions that can cause exceptions.
-valfun_2({apply,Live}, Vst) ->
- call(Live+2, Vst);
-valfun_2({apply_last,Live,_}, Vst) ->
- tail_call(Live+2, Vst);
-valfun_2({call_fun,Live}, Vst) ->
- call(Live, Vst);
-valfun_2({call,Live,_}, Vst) ->
- call(Live, Vst);
-valfun_2({call_ext,Live,Func}, Vst) ->
- call(Func, Live, Vst);
-valfun_2({call_only,Live,_}, Vst) ->
- tail_call(Live, Vst);
-valfun_2({call_ext_only,Live,_}, Vst) ->
- tail_call(Live, Vst);
-valfun_2({call_last,Live,_,_}, Vst) ->
- tail_call(Live, Vst);
-valfun_2({call_ext_last,Live,_,_}, Vst) ->
- tail_call(Live, Vst);
-valfun_2({make_fun,_,_,Live}, Vst) ->
- call(Live, Vst);
-valfun_2({make_fun2,_,_,_,Live}, Vst) ->
- call(Live, Vst);
-%% Floating point.
-valfun_2({fconv,Src,{fr,_}}, Vst) ->
- assert_term(Src, Vst);
-valfun_2({bif,fadd,_,[{fr,_},{fr,_}],{fr,_}}, Vst) ->
- Vst;
-valfun_2({bif,fdiv,_,[{fr,_},{fr,_}],{fr,_}}, Vst) ->
- Vst;
-valfun_2({bif,fmul,_,[{fr,_},{fr,_}],{fr,_}}, Vst) ->
- Vst;
-valfun_2({bif,fnegate,_,[{fr,_}],{fr,_}}, Vst) ->
- Vst;
-valfun_2({bif,fsub,_,[{fr,_},{fr,_}],{fr,_}}, Vst) ->
- Vst;
-valfun_2(fclearerror, Vst) ->
- Vst;
-valfun_2({fcheckerror,_}, Vst) ->
- Vst;
-%% Other BIFs
-valfun_2({bif,element,{f,Fail},[Pos,Tuple],Dst}, Vst0) ->
- TupleType0 = get_term_type(Tuple, Vst0),
- PosType = get_term_type(Pos, Vst0),
- Vst1 = branch_state(Fail, Vst0),
- TupleType = upgrade_type({tuple,[get_tuple_size(PosType)]}, TupleType0),
- Vst = set_type(TupleType, Tuple, Vst1),
- set_type_reg(term, Dst, Vst);
-valfun_2({bif,Op,{f,Fail},Src,Dst}, Vst0) ->
- validate_src(Src, Vst0),
- Vst = branch_state(Fail, Vst0),
- Type = bif_type(Op, Src, Vst),
- set_type_reg(Type, Dst, Vst);
-valfun_2(return, #vst{current=#st{numy=none}}=Vst) ->
- kill_state(Vst);
-valfun_2(return, #vst{current=#st{numy=NumY}}) ->
- error({stack_frame,NumY});
-valfun_2({jump,{f,_}}, #vst{current=none}=Vst) ->
- %% Must be an unreachable jump which was not optimized away.
- %% Do nothing.
- Vst;
-valfun_2({jump,{f,Lbl}}, Vst) ->
- kill_state(branch_state(Lbl, Vst));
-valfun_2({loop_rec,{f,Fail},Dst}, Vst0) ->
- Vst = branch_state(Fail, Vst0),
- set_type_reg(term, Dst, Vst);
-valfun_2(remove_message, Vst) ->
- Vst;
-valfun_2({wait,_}, Vst) ->
- kill_state(Vst);
-valfun_2({wait_timeout,_,Src}, Vst) ->
- assert_term(Src, Vst);
-valfun_2({loop_rec_end,_}, Vst) ->
- kill_state(Vst);
-valfun_2(timeout, #vst{current=St}=Vst) ->
- Vst#vst{current=St#st{x=init_regs(0, term)}};
-valfun_2(send, Vst) ->
- call(2, Vst);
-%% Catch & try.
-valfun_2({catch_end,Reg}, Vst0) ->
- case get_type(Reg, Vst0) of
- {catchtag,_} ->
- Vst = #vst{current=St} = set_type_reg(initialized, Reg, Vst0),
- Xs = gb_trees_from_list([{0,term}]),
- Vst#vst{current=St#st{x=Xs}};
- Type ->
- error({bad_type,Type})
- end;
-valfun_2({try_end,Reg}, Vst) ->
- case get_type(Reg, Vst) of
- {trytag,_} ->
- set_type_reg(initialized, Reg, Vst);
- Type ->
- error({bad_type,Type})
- end;
-valfun_2({try_case,Reg}, Vst0) ->
- case get_type(Reg, Vst0) of
- {trytag,_} ->
- Vst = #vst{current=St} = set_type_reg(initialized, Reg, Vst0),
- Xs = gb_trees_from_list([{0,{atom,[]}},{1,term},{2,term}]),
- Vst#vst{current=St#st{x=Xs}};
- Type ->
- error({bad_type,Type})
- end;
-valfun_2({set_tuple_element,Src,Tuple,I}, Vst) ->
- assert_term(Src, Vst),
- assert_type({tuple_element,I+1}, Tuple, Vst);
-%% Match instructions.
-valfun_2({select_val,Src,{f,Fail},{list,Choices}}, Vst) ->
- assert_term(Src, Vst),
- Lbls = [L || {f,L} <- Choices]++[Fail],
- kill_state(foldl(fun(L, S) -> branch_state(L, S) end, Vst, Lbls));
-valfun_2({select_tuple_arity,Tuple,{f,Fail},{list,Choices}}, Vst) ->
- assert_type(tuple, Tuple, Vst),
- kill_state(branch_arities(Choices, Tuple, branch_state(Fail, Vst)));
-valfun_2({get_list,Src,D1,D2}, Vst0) ->
- assert_term(Src, Vst0),
- Vst = set_type_reg(term, D1, Vst0),
- set_type_reg(term, D2, Vst);
-valfun_2({get_tuple_element,Src,I,Dst}, Vst) ->
- assert_type({tuple_element,I+1}, Src, Vst),
- set_type_reg(term, Dst, Vst);
-valfun_2({bs_restore,_}, Vst) ->
- Vst;
-valfun_2({bs_save,_}, Vst) ->
- Vst;
-valfun_2({bs_start_match,{f,Fail},Src}, Vst) ->
- assert_term(Src, Vst),
- branch_state(Fail, Vst);
-valfun_2({test,bs_skip_bits,{f,Fail},[Src,_,_]}, Vst) ->
- assert_term(Src, Vst),
- branch_state(Fail, Vst);
-valfun_2({test,_,{f,Fail},[_,_,_,Dst]}, Vst0) ->
- Vst = branch_state(Fail, Vst0),
- set_type_reg({integer,[]}, Dst, Vst);
-valfun_2({test,bs_test_tail,{f,Fail},_}, Vst) ->
- branch_state(Fail, Vst);
-%% Other test instructions.
-valfun_2({test,is_float,{f,Lbl},[Float]}, Vst0) ->
- assert_term(Float, Vst0),
- Vst = branch_state(Lbl, Vst0),
- set_type({float,[]}, Float, Vst);
-valfun_2({test,is_tuple,{f,Lbl},[Tuple]}, Vst0) ->
- assert_term(Tuple, Vst0),
- Vst = branch_state(Lbl, Vst0),
- set_type({tuple,[0]}, Tuple, Vst);
-valfun_2({test,test_arity,{f,Lbl},[Tuple,Sz]}, Vst0) when is_integer(Sz) ->
- assert_type(tuple, Tuple, Vst0),
- Vst = branch_state(Lbl, Vst0),
- set_type_reg({tuple,Sz}, Tuple, Vst);
-valfun_2({test,_Op,{f,Lbl},Src}, Vst) ->
- validate_src(Src, Vst),
- branch_state(Lbl, Vst);
-valfun_2({bs_add,{f,Fail},[A,B,_],Dst}, Vst0) ->
- assert_term(A, Vst0),
- assert_term(B, Vst0),
- Vst = branch_state(Fail, Vst0),
- set_type_reg({integer,[]}, Dst, Vst);
-valfun_2({bs_bits_to_bytes,{f,Fail},Src,Dst}, Vst0) ->
- assert_term(Src, Vst0),
- Vst = branch_state(Fail, Vst0),
- set_type_reg({integer,[]}, Dst, Vst);
-valfun_2({bs_init2,{f,Fail},_,Heap,_,_,Dst}, Vst0) ->
- Vst1 = heap_alloc(Heap, Vst0),
- Vst = branch_state(Fail, Vst1),
- set_type_reg(binary, Dst, Vst);
-valfun_2({bs_put_string,Sz,_}, Vst) when is_integer(Sz) ->
- Vst;
-valfun_2({bs_put_binary,{f,Fail},_,_,_,Src}, Vst0) ->
- assert_term(Src, Vst0),
- branch_state(Fail, Vst0);
-valfun_2({bs_put_float,{f,Fail},_,_,_,Src}, Vst0) ->
- assert_term(Src, Vst0),
- branch_state(Fail, Vst0);
-valfun_2({bs_put_integer,{f,Fail},_,_,_,Src}, Vst0) ->
- assert_term(Src, Vst0),
- branch_state(Fail, Vst0);
-%% Old bit syntax construction (before R10B).
-valfun_2({bs_init,_,_}, Vst) -> Vst;
-valfun_2({bs_need_buf,_}, Vst) -> Vst;
-valfun_2({bs_final,{f,Fail},Dst}, Vst0) ->
- Vst = branch_state(Fail, Vst0),
- set_type_reg(binary, Dst, Vst);
-%% Misc.
-valfun_2({'%live',Live}, Vst) ->
- verify_live(Live, Vst),
- Vst;
-valfun_2(_, _) ->
- error(unknown_instruction).
-
-kill_state(#vst{current=#st{ct=[]}}=Vst) ->
- Vst#vst{current=none};
-kill_state(#vst{current=#st{ct=Fails}}=Vst0) ->
- Vst = lists:foldl(fun branch_state/2, Vst0, Fails),
- Vst#vst{current=none}.
-
-%% A "plain" call.
-%% The stackframe must have a known size and be initialized.
-%% The instruction will return to the instruction following the call.
-call(Live, #vst{current=St}=Vst) ->
- verify_live(Live, Vst),
- verify_y_init(Vst),
- Xs = gb_trees_from_list([{0,term}]),
- Vst#vst{current=St#st{x=Xs}}.
-
-%% A "plain" call.
-%% The stackframe must have a known size and be initialized.
-%% The instruction will return to the instruction following the call.
-call(Name, Live, #vst{current=St}=Vst) ->
- verify_live(Live, Vst),
- case return_type(Name, Vst) of
- exception ->
- kill_state(Vst);
- Type ->
- verify_y_init(Vst),
- Xs = gb_trees_from_list([{0,Type}]),
- Vst#vst{current=St#st{x=Xs}}
- end.
-
-%% Tail call.
-%% The stackframe must have a known size and be initialized.
-%% Does not return to the instruction following the call.
-tail_call(Live, Vst) ->
- kill_state(call(Live, Vst)).
-
-allocate(Zero, Stk, Heap, Live, #vst{current=#st{numy=none}=St}=Vst) ->
- verify_live(Live, Vst),
- Ys = init_regs(case Zero of
- true -> Stk;
- false -> 0
- end, initialized),
- Vst#vst{current=St#st{y=Ys,numy=Stk,h=heap_alloc_1(Heap)}};
-allocate(_, _, _, _, #vst{current=#st{numy=Numy}}) ->
- error({existing_stack_frame,{size,Numy}}).
-
-deallocate(#vst{current=St}=Vst) ->
- Vst#vst{current=St#st{y=init_regs(0, initialized),numy=none}}.
-
-test_heap(Heap, Live, Vst) ->
- verify_live(Live, Vst),
- heap_alloc(Heap, Vst).
-
-heap_alloc(Heap, #vst{current=St}=Vst) ->
- Vst#vst{current=St#st{h=heap_alloc_1(Heap)}}.
-
-heap_alloc_1({alloc,Alloc}) ->
- {value,{_,Heap}} = lists:keysearch(words, 1, Alloc),
- Heap;
-heap_alloc_1(Heap) when is_integer(Heap) -> Heap.
-
-
-set_type(Type, {x,_}=Reg, Vst) -> set_type_reg(Type, Reg, Vst);
-set_type(Type, {y,_}=Reg, Vst) -> set_type_y(Type, Reg, Vst);
-set_type(_, _, #vst{}=Vst) -> Vst.
-
-set_type_reg(Type, {x,X}, #vst{current=#st{x=Xs}=St}=Vst)
- when 0 =< X, X < ?MAXREG ->
- Vst#vst{current=St#st{x=gb_trees:enter(X, Type, Xs)}};
-set_type_reg(Type, Reg, Vst) ->
- set_type_y(Type, Reg, Vst).
-
-set_type_y(Type, {y,Y}=Reg, #vst{current=#st{y=Ys,numy=NumY}=St}=Vst)
- when is_integer(Y), 0 =< Y, Y < ?MAXREG ->
- case {Y,NumY} of
- {_,none} ->
- error({no_stack_frame,Reg});
- {_,_} when Y > NumY ->
- error({y_reg_out_of_range,Reg,NumY});
- {_,_} ->
- Vst#vst{current=St#st{y=gb_trees:enter(Y, Type, Ys)}}
- end;
-set_type_y(Type, Reg, #vst{}) -> error({invalid_store,Reg,Type}).
-
-assert_term(Src, Vst) ->
- get_term_type(Src, Vst),
- Vst.
-
-%% The possible types.
-%%
-%% First non-term types:
-%%
-%% initialized Only for Y registers. Means that the Y register
-%% has been initialized with some valid term so that
-%% it is safe to pass to the garbage collector.
-%% NOT safe to use in any other way (will not crash the
-%% emulator, but clearly points to a bug in the compiler).
-%%
-%% {catchtag,Lbl} A special term used within a catch. Must only be used
-%% by the catch instructions; NOT safe to use in other
-%% instructions.
-%%
-%% {trytag,Lbl} A special term used within a try block. Must only be
-%% used by the catch instructions; NOT safe to use in other
-%% instructions.
-%%
-%% exception Can only be used as a type returned by return_type/2
-%% (which gives the type of the value returned by a BIF).
-%% Thus 'exception' is never stored as type descriptor
-%% for a register.
-%%
-%% Normal terms:
-%%
-%% term Any valid Erlang (but not of the special types above).
-%%
-%% bool The atom 'true' or the atom 'false'.
-%%
-%% cons Cons cell: [_|_]
-%%
-%% nil Empty list: []
-%%
-%% {tuple,[Sz]} Tuple. An element has been accessed using
-%% element/2 or setelement/3 so that it is known that
-%% the type is a tuple of size at least Sz.
-%%
-%% {tuple,Sz} Tuple. A test_arity instruction has been seen
-%% so that it is known that the size is exactly Sz.
-%%
-%% {atom,[]} Atom.
-%% {atom,Atom}
-%%
-%% {integer,[]} Integer.
-%% {integer,Integer}
-%%
-%% {float,[]} Float.
-%% {float,Float}
-%%
-%% number Integer or Float of unknown value
-%%
-
-assert_type(WantedType, Term, Vst) ->
- assert_type(WantedType, get_type(Term, Vst)),
- Vst.
-
-assert_type(float, {float,_}) -> ok;
-assert_type(tuple, {tuple,_}) -> ok;
-assert_type({tuple_element,I}, {tuple,[Sz]})
- when 1 =< I, I =< Sz ->
- ok;
-assert_type({tuple_element,I}, {tuple,Sz})
- when is_integer(Sz), 1 =< I, I =< Sz ->
- ok;
-assert_type(Needed, Actual) ->
- error({bad_type,{needed,Needed},{actual,Actual}}).
-
-%% upgrade_type/2 is used when linear code finds out more and
-%% more information about a type, so the type gets "narrower"
-%% or perhaps inconsistent. In the case of inconsistency
-%% we mostly widen the type to 'term' to make subsequent
-%% code fail if it assumes anything about the type.
-
-upgrade_type(Same, Same) -> Same;
-upgrade_type(term, OldT) -> OldT;
-upgrade_type(NewT, term) -> NewT;
-upgrade_type({Type,New}=NewT, {Type,Old}=OldT)
- when Type == atom; Type == integer; Type == float ->
- if New =:= Old -> OldT;
- New =:= [] -> OldT;
- Old =:= [] -> NewT;
- true -> term
- end;
-upgrade_type({Type,_}=NewT, number)
- when Type == integer; Type == float ->
- NewT;
-upgrade_type(number, {Type,_}=OldT)
- when Type == integer; Type == float ->
- OldT;
-upgrade_type(bool, {atom,A}) ->
- upgrade_bool(A);
-upgrade_type({atom,A}, bool) ->
- upgrade_bool(A);
-upgrade_type({tuple,[Sz]}, {tuple,[OldSz]})
- when is_integer(Sz) ->
- {tuple,[max(Sz, OldSz)]};
-upgrade_type({tuple,Sz}=T, {tuple,[_]})
- when is_integer(Sz) ->
- %% This also takes care of the user error when a tuple element
- %% is accesed outside the known exact tuple size; there is
- %% no more type information, just a runtime error which is not
- %% our problem.
- T;
-upgrade_type({tuple,[Sz]}, {tuple,_}=T)
- when is_integer(Sz) ->
- %% Same as the previous clause but mirrored.
- T;
-upgrade_type(_A, _B) ->
- %%io:format("upgrade_type: ~p ~p\n", [_A,_B]),
- term.
-
-upgrade_bool([]) -> bool;
-upgrade_bool(true) -> {atom,true};
-upgrade_bool(false) -> {atom,false};
-upgrade_bool(_) -> term.
-
-get_tuple_size({integer,[]}) -> 0;
-get_tuple_size({integer,Sz}) -> Sz;
-get_tuple_size(_) -> 0.
-
-validate_src(Ss, Vst) when is_list(Ss) ->
- foldl(fun(S, _) -> get_type(S, Vst) end, ok, Ss).
-
-get_term_type(Src, Vst) ->
- case get_type(Src, Vst) of
- initialized -> error({not_assigned,Src});
- exception -> error({exception,Src});
- {catchtag,_} -> error({catchtag,Src});
- {trytag,_} -> error({trytag,Src});
- Type -> Type
- end.
-
-get_type(nil=T, _) -> T;
-get_type({atom,A}=T, _) when is_atom(A) -> T;
-get_type({float,F}=T, _) when is_float(F) -> T;
-get_type({integer,I}=T, _) when is_integer(I) -> T;
-get_type({x,X}=Reg, #vst{current=#st{x=Xs}}) when is_integer(X) ->
- case gb_trees:lookup(X, Xs) of
- {value,Type} -> Type;
- none -> error({uninitialized_reg,Reg})
- end;
-get_type({y,Y}=Reg, #vst{current=#st{y=Ys}}) when is_integer(Y) ->
- case gb_trees:lookup(Y, Ys) of
- {value,initialized} -> error({unassigned_reg,Reg});
- {value,Type} -> Type;
- none -> error({uninitialized_reg,Reg})
- end;
-get_type(Src, _) -> error({bad_source,Src}).
-
-branch_arities([], _, #vst{}=Vst) -> Vst;
-branch_arities([Sz,{f,L}|T], Tuple, #vst{current=St}=Vst0)
- when is_integer(Sz) ->
- Vst1 = set_type_reg({tuple,Sz}, Tuple, Vst0),
- Vst = branch_state(L, Vst1),
- branch_arities(T, Tuple, Vst#vst{current=St}).
-
-branch_state(0, #vst{}=Vst) -> Vst;
-branch_state(L, #vst{current=St,branched=B}=Vst) ->
- Vst#vst{
- branched=case gb_trees:is_defined(L, B) of
- false ->
- gb_trees:insert(L, St#st{ct=[]}, B);
- true ->
- MergedSt = merge_states(L, St, B),
- gb_trees:update(L, MergedSt#st{ct=[]}, B)
- end}.
-
-%% merge_states/3 is used when there are more than one way to arrive
-%% at this point, and the type states for the different paths has
-%% to be merged. The type states are downgraded to the least common
-%% subset for the subsequent code.
-
-merge_states(0, St, _Branched) -> St;
-merge_states(L, St, Branched) ->
- case gb_trees:lookup(L, Branched) of
- none -> St;
- {value,OtherSt} when St == none -> OtherSt;
- {value,OtherSt} ->
- merge_states_1(St, OtherSt)
- end.
-
-merge_states_1(#st{x=Xs0,y=Ys0,numy=NumY0,h=H0}=St,
- #st{x=Xs1,y=Ys1,numy=NumY1,h=H1}) ->
- NumY = merge_stk(NumY0, NumY1),
- Xs = merge_regs(Xs0, Xs1),
- Ys = merge_regs(Ys0, Ys1),
- St#st{x=Xs,y=Ys,numy=NumY,h=min(H0, H1)}.
-
-merge_stk(S, S) -> S;
-merge_stk(_, _) -> undecided.
-
-merge_regs(Rs0, Rs1) ->
- Rs = merge_regs_1(gb_trees:to_list(Rs0), gb_trees:to_list(Rs1)),
- gb_trees_from_list(Rs).
-
-merge_regs_1([Same|Rs1], [Same|Rs2]) ->
- [Same|merge_regs_1(Rs1, Rs2)];
-merge_regs_1([{R1,_}|Rs1], [{R2,_}|_]=Rs2) when R1 < R2 ->
- merge_regs_1(Rs1, Rs2);
-merge_regs_1([{R1,_}|_]=Rs1, [{R2,_}|Rs2]) when R1 > R2 ->
- merge_regs_1(Rs1, Rs2);
-merge_regs_1([{R,Type1}|Rs1], [{R,Type2}|Rs2]) ->
- [{R,merge_types(Type1, Type2)}|merge_regs_1(Rs1, Rs2)];
-merge_regs_1([], []) -> [];
-merge_regs_1([], [_|_]) -> [];
-merge_regs_1([_|_], []) -> [].
-
-merge_types(T, T) -> T;
-merge_types(initialized=I, _) -> I;
-merge_types(_, initialized=I) -> I;
-merge_types({tuple,Same}=T, {tuple,Same}) -> T;
-merge_types({tuple,A}, {tuple,B}) ->
- {tuple,[min(tuple_sz(A), tuple_sz(B))]};
-merge_types({Type,A}, {Type,B})
- when Type == atom; Type == integer; Type == float ->
- if A =:= B -> {Type,A};
- true -> {Type,[]}
- end;
-merge_types({Type,_}, number)
- when Type == integer; Type == float ->
- number;
-merge_types(number, {Type,_})
- when Type == integer; Type == float ->
- number;
-merge_types(bool, {atom,A}) ->
- merge_bool(A);
-merge_types({atom,A}, bool) ->
- merge_bool(A);
-merge_types(_, _) -> term.
-
-tuple_sz([Sz]) -> Sz;
-tuple_sz(Sz) -> Sz.
-
-merge_bool([]) -> {atom,[]};
-merge_bool(true) -> bool;
-merge_bool(false) -> bool;
-merge_bool(_) -> {atom,[]}.
-
-verify_y_init(#vst{current=#st{numy=none}}) -> ok;
-verify_y_init(#vst{current=#st{numy=undecided}}) ->
- error(unknown_size_of_stackframe);
-verify_y_init(#vst{current=#st{y=Ys,numy=NumY}}) ->
- verify_y_init_1(NumY, Ys).
-
-verify_y_init_1(0, _) -> ok;
-verify_y_init_1(N, Ys) ->
- Y = N-1,
- case gb_trees:is_defined(Y, Ys) of
- false -> error({{y,Y},not_initialized});
- true -> verify_y_init_1(Y, Ys)
- end.
-
-verify_live(0, #vst{}) -> ok;
-verify_live(N, #vst{current=#st{x=Xs}}) ->
- verify_live_1(N, Xs).
-
-verify_live_1(0, _) -> ok;
-verify_live_1(N, Xs) ->
- X = N-1,
- case gb_trees:is_defined(X, Xs) of
- false -> error({{x,X},not_live});
- true -> verify_live_1(X, Xs)
- end.
-
-eat_heap(N, #vst{current=#st{h=Heap0}=St}=Vst) ->
- case Heap0-N of
- Neg when Neg < 0 ->
- error({heap_overflow,{left,Heap0},{wanted,N}});
- Heap ->
- Vst#vst{current=St#st{h=Heap}}
- end.
-
-bif_type('-', Src, Vst) ->
- arith_type(Src, Vst);
-bif_type('+', Src, Vst) ->
- arith_type(Src, Vst);
-bif_type('*', Src, Vst) ->
- arith_type(Src, Vst);
-bif_type(abs, [Num], Vst) ->
- case get_type(Num, Vst) of
- {float,_}=T -> T;
- {integer,_}=T -> T;
- _ -> number
- end;
-bif_type(float, _, _) -> {float,[]};
-bif_type('/', _, _) -> {float,[]};
-%% Integer operations.
-bif_type('div', [_,_], _) -> {integer,[]};
-bif_type('rem', [_,_], _) -> {integer,[]};
-bif_type(length, [_], _) -> {integer,[]};
-bif_type(size, [_], _) -> {integer,[]};
-bif_type(trunc, [_], _) -> {integer,[]};
-bif_type(round, [_], _) -> {integer,[]};
-bif_type('band', [_,_], _) -> {integer,[]};
-bif_type('bor', [_,_], _) -> {integer,[]};
-bif_type('bxor', [_,_], _) -> {integer,[]};
-bif_type('bnot', [_], _) -> {integer,[]};
-bif_type('bsl', [_,_], _) -> {integer,[]};
-bif_type('bsr', [_,_], _) -> {integer,[]};
-%% Booleans.
-bif_type('==', [_,_], _) -> bool;
-bif_type('/=', [_,_], _) -> bool;
-bif_type('=<', [_,_], _) -> bool;
-bif_type('<', [_,_], _) -> bool;
-bif_type('>=', [_,_], _) -> bool;
-bif_type('>', [_,_], _) -> bool;
-bif_type('=:=', [_,_], _) -> bool;
-bif_type('=/=', [_,_], _) -> bool;
-bif_type('not', [_], _) -> bool;
-bif_type('and', [_,_], _) -> bool;
-bif_type('or', [_,_], _) -> bool;
-bif_type('xor', [_,_], _) -> bool;
-bif_type(is_atom, [_], _) -> bool;
-bif_type(is_boolean, [_], _) -> bool;
-bif_type(is_binary, [_], _) -> bool;
-bif_type(is_constant, [_], _) -> bool;
-bif_type(is_float, [_], _) -> bool;
-bif_type(is_function, [_], _) -> bool;
-bif_type(is_integer, [_], _) -> bool;
-bif_type(is_list, [_], _) -> bool;
-bif_type(is_number, [_], _) -> bool;
-bif_type(is_pid, [_], _) -> bool;
-bif_type(is_port, [_], _) -> bool;
-bif_type(is_reference, [_], _) -> bool;
-bif_type(is_tuple, [_], _) -> bool;
-%% Misc.
-bif_type(node, [], _) -> {atom,[]};
-bif_type(node, [_], _) -> {atom,[]};
-bif_type(hd, [_], _) -> term;
-bif_type(tl, [_], _) -> term;
-bif_type(get, [_], _) -> term;
-bif_type(raise, [_,_], _) -> exception;
-bif_type(_, _, _) -> term.
-
-arith_type([A,B], Vst) ->
- case {get_type(A, Vst),get_type(B, Vst)} of
- {{float,_},_} -> {float,[]};
- {_,{float,_}} -> {float,[]};
- {_,_} -> number
- end;
-arith_type(_, _) -> number.
-
-return_type({extfunc,M,F,A}, Vst) ->
- return_type_1(M, F, A, Vst).
-
-return_type_1(erlang, setelement, 3, Vst) ->
- Tuple = {x,1},
- TupleType =
- case get_type(Tuple, Vst) of
- {tuple,_}=TT -> TT;
- _ -> {tuple,[0]}
- end,
- case get_type({x,0}, Vst) of
- {integer,[]} -> TupleType;
- {integer,I} -> upgrade_type({tuple,[I]}, TupleType);
- _ -> TupleType
- end;
-return_type_1(erlang, F, A, _) ->
- return_type_erl(F, A);
-return_type_1(math, F, A, _) ->
- return_type_math(F, A);
-return_type_1(_, _, _, _) -> term.
-
-return_type_erl(exit, 1) -> exception;
-return_type_erl(throw, 1) -> exception;
-return_type_erl(fault, 1) -> exception;
-return_type_erl(fault, 2) -> exception;
-return_type_erl(error, 1) -> exception;
-return_type_erl(error, 2) -> exception;
-return_type_erl(_, _) -> term.
-
-return_type_math(cos, 1) -> {float,[]};
-return_type_math(cosh, 1) -> {float,[]};
-return_type_math(sin, 1) -> {float,[]};
-return_type_math(sinh, 1) -> {float,[]};
-return_type_math(tan, 1) -> {float,[]};
-return_type_math(tanh, 1) -> {float,[]};
-return_type_math(acos, 1) -> {float,[]};
-return_type_math(acosh, 1) -> {float,[]};
-return_type_math(asin, 1) -> {float,[]};
-return_type_math(asinh, 1) -> {float,[]};
-return_type_math(atan, 1) -> {float,[]};
-return_type_math(atanh, 1) -> {float,[]};
-return_type_math(erf, 1) -> {float,[]};
-return_type_math(erfc, 1) -> {float,[]};
-return_type_math(exp, 1) -> {float,[]};
-return_type_math(log, 1) -> {float,[]};
-return_type_math(log10, 1) -> {float,[]};
-return_type_math(sqrt, 1) -> {float,[]};
-return_type_math(atan2, 2) -> {float,[]};
-return_type_math(pow, 2) -> {float,[]};
-return_type_math(pi, 0) -> {float,[]};
-return_type_math(_, _) -> term.
-
-min(A, B) when is_integer(A), is_integer(B), A < B -> A;
-min(A, B) when is_integer(A), is_integer(B) -> B.
-
-max(A, B) when is_integer(A), is_integer(B), A > B -> A;
-max(A, B) when is_integer(A), is_integer(B) -> B.
-
-gb_trees_from_list(L) -> gb_trees:from_orddict(orddict:from_list(L)).
-
--ifdef(DEBUG).
-error(Error) -> exit(Error).
--else.
-error(Error) -> throw(Error).
--endif.
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/cerl.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/cerl.erl
deleted file mode 100644
index be9e088276..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/cerl.erl
+++ /dev/null
@@ -1,4169 +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 Richard Carlsson.
-%% Copyright (C) 1999-2002 Richard Carlsson.
-%% Portions created by Ericsson are Copyright 2001, Ericsson Utvecklings
-%% AB. All Rights Reserved.''
-%%
-%% $Id: cerl.erl,v 1.3 2010/03/04 13:54:20 maria Exp $
-
-%% =====================================================================
-%% @doc Core Erlang abstract syntax trees.
-%%
-%% <p> This module defines an abstract data type for representing Core
-%% Erlang source code as syntax trees.</p>
-%%
-%% <p>A recommended starting point for the first-time user is the
-%% documentation of the function <a
-%% href="#type-1"><code>type/1</code></a>.</p>
-%%
-%% <h3><b>NOTES:</b></h3>
-%%
-%% <p>This module deals with the composition and decomposition of
-%% <em>syntactic</em> entities (as opposed to semantic ones); its
-%% purpose is to hide all direct references to the data structures
-%% used to represent these entities. With few exceptions, the
-%% functions in this module perform no semantic interpretation of
-%% their inputs, and in general, the user is assumed to pass
-%% type-correct arguments - if this is not done, the effects are not
-%% defined.</p>
-%%
-%% <p>The internal representations of abstract syntax trees are
-%% subject to change without notice, and should not be documented
-%% outside this module. Furthermore, we do not give any guarantees on
-%% how an abstract syntax tree may or may not be represented, <em>with
-%% the following exceptions</em>: no syntax tree is represented by a
-%% single atom, such as <code>none</code>, by a list constructor
-%% <code>[X | Y]</code>, or by the empty list <code>[]</code>. This
-%% can be relied on when writing functions that operate on syntax
-%% trees.</p>
-%%
-%% @type cerl(). An abstract Core Erlang syntax tree.
-%%
-%% <p>Every abstract syntax tree has a <em>type</em>, given by the
-%% function <a href="#type-1"><code>type/1</code></a>. In addition,
-%% each syntax tree has a list of <em>user annotations</em> (cf. <a
-%% href="#get_ann-1"><code>get_ann/1</code></a>), which are included
-%% in the Core Erlang syntax.</p>
-
--module(cerl).
-
--export([abstract/1, add_ann/2, alias_pat/1, alias_var/1,
- ann_abstract/2, ann_c_alias/3, ann_c_apply/3, ann_c_atom/2,
- ann_c_call/4, ann_c_case/3, ann_c_catch/2, ann_c_char/2,
- ann_c_clause/3, ann_c_clause/4, ann_c_cons/3, ann_c_float/2,
- ann_c_fname/3, ann_c_fun/3, ann_c_int/2, ann_c_let/4,
- ann_c_letrec/3, ann_c_module/4, ann_c_module/5, ann_c_nil/1,
- ann_c_cons_skel/3, ann_c_tuple_skel/2, ann_c_primop/3,
- ann_c_receive/2, ann_c_receive/4, ann_c_seq/3, ann_c_string/2,
- ann_c_try/6, ann_c_tuple/2, ann_c_values/2, ann_c_var/2,
- ann_make_data/3, ann_make_list/2, ann_make_list/3,
- ann_make_data_skel/3, ann_make_tree/3, apply_args/1,
- apply_arity/1, apply_op/1, atom_lit/1, atom_name/1, atom_val/1,
- c_alias/2, c_apply/2, c_atom/1, c_call/3, c_case/2, c_catch/1,
- c_char/1, c_clause/2, c_clause/3, c_cons/2, c_float/1,
- c_fname/2, c_fun/2, c_int/1, c_let/3, c_letrec/2, c_module/3,
- c_module/4, c_nil/0, c_cons_skel/2, c_tuple_skel/1, c_primop/2,
- c_receive/1, c_receive/3, c_seq/2, c_string/1, c_try/5,
- c_tuple/1, c_values/1, c_var/1, call_args/1, call_arity/1,
- call_module/1, call_name/1, case_arg/1, case_arity/1,
- case_clauses/1, catch_body/1, char_lit/1, char_val/1,
- clause_arity/1, clause_body/1, clause_guard/1, clause_pats/1,
- clause_vars/1, concrete/1, cons_hd/1, cons_tl/1, copy_ann/2,
- data_arity/1, data_es/1, data_type/1, float_lit/1, float_val/1,
- fname_arity/1, fname_id/1, fold_literal/1, from_records/1,
- fun_arity/1, fun_body/1, fun_vars/1, get_ann/1, int_lit/1,
- int_val/1, is_c_alias/1, is_c_apply/1, is_c_atom/1,
- is_c_call/1, is_c_case/1, is_c_catch/1, is_c_char/1,
- is_c_clause/1, is_c_cons/1, is_c_float/1, is_c_fname/1,
- is_c_fun/1, is_c_int/1, is_c_let/1, is_c_letrec/1, is_c_list/1,
- is_c_module/1, is_c_nil/1, is_c_primop/1, is_c_receive/1,
- is_c_seq/1, is_c_string/1, is_c_try/1, is_c_tuple/1,
- is_c_values/1, is_c_var/1, is_data/1, is_leaf/1, is_literal/1,
- is_literal_term/1, is_print_char/1, is_print_string/1,
- let_arg/1, let_arity/1, let_body/1, let_vars/1, letrec_body/1,
- letrec_defs/1, letrec_vars/1, list_elements/1, list_length/1,
- make_data/2, make_list/1, make_list/2, make_data_skel/2,
- make_tree/2, meta/1, module_attrs/1, module_defs/1,
- module_exports/1, module_name/1, module_vars/1,
- pat_list_vars/1, pat_vars/1, primop_args/1, primop_arity/1,
- primop_name/1, receive_action/1, receive_clauses/1,
- receive_timeout/1, seq_arg/1, seq_body/1, set_ann/2,
- string_lit/1, string_val/1, subtrees/1, to_records/1,
- try_arg/1, try_body/1, try_vars/1, try_evars/1, try_handler/1,
- tuple_arity/1, tuple_es/1, type/1, unfold_literal/1,
- update_c_alias/3, update_c_apply/3, update_c_call/4,
- update_c_case/3, update_c_catch/2, update_c_clause/4,
- update_c_cons/3, update_c_cons_skel/3, update_c_fname/2,
- update_c_fname/3, update_c_fun/3, update_c_let/4,
- update_c_letrec/3, update_c_module/5, update_c_primop/3,
- update_c_receive/4, update_c_seq/3, update_c_try/6,
- update_c_tuple/2, update_c_tuple_skel/2, update_c_values/2,
- update_c_var/2, update_data/3, update_list/2, update_list/3,
- update_data_skel/3, update_tree/2, update_tree/3,
- values_arity/1, values_es/1, var_name/1, c_binary/1,
- update_c_binary/2, ann_c_binary/2, is_c_binary/1,
- binary_segments/1, c_bitstr/3, c_bitstr/4, c_bitstr/5,
- update_c_bitstr/5, update_c_bitstr/6, ann_c_bitstr/5,
- ann_c_bitstr/6, is_c_bitstr/1, bitstr_val/1, bitstr_size/1,
- bitstr_bitsize/1, bitstr_unit/1, bitstr_type/1,
- bitstr_flags/1]).
-
--include("core_parse.hrl").
-
-
-%% =====================================================================
-%% Representation (general)
-%%
-%% All nodes are represented by tuples of arity 2 or (generally)
-%% greater, whose first element is an atom which uniquely identifies the
-%% type of the node, and whose second element is a (proper) list of
-%% annotation terms associated with the node - this is by default empty.
-%%
-%% For most node constructor functions, there are analogous functions
-%% named 'ann_...', taking one extra argument 'As' (always the first
-%% argument), specifying an annotation list at node creation time.
-%% Similarly, there are also functions named 'update_...', taking one
-%% extra argument 'Old', specifying a node from which all fields not
-%% explicitly given as arguments should be copied (generally, this is
-%% the annotation field only).
-%% =====================================================================
-
-%% This defines the general representation of constant literals:
-
--record(literal, {ann = [], val}).
-
-
-%% @spec type(Node::cerl()) -> atom()
-%%
-%% @doc Returns the type tag of <code>Node</code>. Current node types
-%% are:
-%%
-%% <p><center><table border="1">
-%% <tr>
-%% <td>alias</td>
-%% <td>apply</td>
-%% <td>binary</td>
-%% <td>bitstr</td>
-%% <td>call</td>
-%% <td>case</td>
-%% <td>catch</td>
-%% </tr><tr>
-%% <td>clause</td>
-%% <td>cons</td>
-%% <td>fun</td>
-%% <td>let</td>
-%% <td>letrec</td>
-%% <td>literal</td>
-%% <td>module</td>
-%% </tr><tr>
-%% <td>primop</td>
-%% <td>receive</td>
-%% <td>seq</td>
-%% <td>try</td>
-%% <td>tuple</td>
-%% <td>values</td>
-%% <td>var</td>
-%% </tr>
-%% </table></center></p>
-%%
-%% <p>Note: The name of the primary constructor function for a node
-%% type is always the name of the type itself, prefixed by
-%% "<code>c_</code>"; recognizer predicates are correspondingly
-%% prefixed by "<code>is_c_</code>". Furthermore, to simplify
-%% preservation of annotations (cf. <code>get_ann/1</code>), there are
-%% analogous constructor functions prefixed by "<code>ann_c_</code>"
-%% and "<code>update_c_</code>", for setting the annotation list of
-%% the new node to either a specific value or to the annotations of an
-%% existing node, respectively.</p>
-%%
-%% @see abstract/1
-%% @see c_alias/2
-%% @see c_apply/2
-%% @see c_binary/1
-%% @see c_bitstr/5
-%% @see c_call/3
-%% @see c_case/2
-%% @see c_catch/1
-%% @see c_clause/3
-%% @see c_cons/2
-%% @see c_fun/2
-%% @see c_let/3
-%% @see c_letrec/2
-%% @see c_module/3
-%% @see c_primop/2
-%% @see c_receive/1
-%% @see c_seq/2
-%% @see c_try/3
-%% @see c_tuple/1
-%% @see c_values/1
-%% @see c_var/1
-%% @see get_ann/1
-%% @see to_records/1
-%% @see from_records/1
-%% @see data_type/1
-%% @see subtrees/1
-%% @see meta/1
-
-type(Node) ->
- element(1, Node).
-
-
-%% @spec is_leaf(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is a leaf node,
-%% otherwise <code>false</code>. The current leaf node types are
-%% <code>literal</code> and <code>var</code>.
-%%
-%% <p>Note: all literals (cf. <code>is_literal/1</code>) are leaf
-%% nodes, even if they represent structured (constant) values such as
-%% <code>{foo, [bar, baz]}</code>. Also note that variables are leaf
-%% nodes but not literals.</p>
-%%
-%% @see type/1
-%% @see is_literal/1
-
-is_leaf(Node) ->
- case type(Node) of
- literal -> true;
- var -> true;
- _ -> false
- end.
-
-
-%% @spec get_ann(cerl()) -> [term()]
-%%
-%% @doc Returns the list of user annotations associated with a syntax
-%% tree node. For a newly created node, this is the empty list. The
-%% annotations may be any terms.
-%%
-%% @see set_ann/2
-
-get_ann(Node) ->
- element(2, Node).
-
-
-%% @spec set_ann(Node::cerl(), Annotations::[term()]) -> cerl()
-%%
-%% @doc Sets the list of user annotations of <code>Node</code> to
-%% <code>Annotations</code>.
-%%
-%% @see get_ann/1
-%% @see add_ann/2
-%% @see copy_ann/2
-
-set_ann(Node, List) ->
- setelement(2, Node, List).
-
-
-%% @spec add_ann(Annotations::[term()], Node::cerl()) -> cerl()
-%%
-%% @doc Appends <code>Annotations</code> to the list of user
-%% annotations of <code>Node</code>.
-%%
-%% <p>Note: this is equivalent to <code>set_ann(Node, Annotations ++
-%% get_ann(Node))</code>, but potentially more efficient.</p>
-%%
-%% @see get_ann/1
-%% @see set_ann/2
-
-add_ann(Terms, Node) ->
- set_ann(Node, Terms ++ get_ann(Node)).
-
-
-%% @spec copy_ann(Source::cerl(), Target::cerl()) -> cerl()
-%%
-%% @doc Copies the list of user annotations from <code>Source</code>
-%% to <code>Target</code>.
-%%
-%% <p>Note: this is equivalent to <code>set_ann(Target,
-%% get_ann(Source))</code>, but potentially more efficient.</p>
-%%
-%% @see get_ann/1
-%% @see set_ann/2
-
-copy_ann(Source, Target) ->
- set_ann(Target, get_ann(Source)).
-
-
-%% @spec abstract(Term::term()) -> cerl()
-%%
-%% @doc Creates a syntax tree corresponding to an Erlang term.
-%% <code>Term</code> must be a literal term, i.e., one that can be
-%% represented as a source code literal. Thus, it may not contain a
-%% process identifier, port, reference, binary or function value as a
-%% subterm.
-%%
-%% <p>Note: This is a constant time operation.</p>
-%%
-%% @see ann_abstract/2
-%% @see concrete/1
-%% @see is_literal/1
-%% @see is_literal_term/1
-
-abstract(T) ->
- #literal{val = T}.
-
-
-%% @spec ann_abstract(Annotations::[term()], Term::term()) -> cerl()
-%% @see abstract/1
-
-ann_abstract(As, T) ->
- #literal{val = T, ann = As}.
-
-
-%% @spec is_literal_term(Term::term()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Term</code> can be
-%% represented as a literal, otherwise <code>false</code>. This
-%% function takes time proportional to the size of <code>Term</code>.
-%%
-%% @see abstract/1
-
-is_literal_term(T) when integer(T) -> true;
-is_literal_term(T) when float(T) -> true;
-is_literal_term(T) when atom(T) -> true;
-is_literal_term([]) -> true;
-is_literal_term([H | T]) ->
- case is_literal_term(H) of
- true ->
- is_literal_term(T);
- false ->
- false
- end;
-is_literal_term(T) when tuple(T) ->
- is_literal_term_list(tuple_to_list(T));
-is_literal_term(_) ->
- false.
-
-is_literal_term_list([T | Ts]) ->
- case is_literal_term(T) of
- true ->
- is_literal_term_list(Ts);
- false ->
- false
- end;
-is_literal_term_list([]) ->
- true.
-
-
-%% @spec concrete(Node::cerl()) -> term()
-%%
-%% @doc Returns the Erlang term represented by a syntax tree. An
-%% exception is thrown if <code>Node</code> does not represent a
-%% literal term.
-%%
-%% <p>Note: This is a constant time operation.</p>
-%%
-%% @see abstract/1
-%% @see is_literal/1
-
-%% Because the normal tuple and list constructor operations always
-%% return a literal if the arguments are literals, 'concrete' and
-%% 'is_literal' never need to traverse the structure.
-
-concrete(#literal{val = V}) ->
- V.
-
-
-%% @spec is_literal(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> represents a
-%% literal term, otherwise <code>false</code>. This function returns
-%% <code>true</code> if and only if the value of
-%% <code>concrete(Node)</code> is defined.
-%%
-%% <p>Note: This is a constant time operation.</p>
-%%
-%% @see abstract/1
-%% @see concrete/1
-%% @see fold_literal/1
-
-is_literal(#literal{}) ->
- true;
-is_literal(_) ->
- false.
-
-
-%% @spec fold_literal(Node::cerl()) -> cerl()
-%%
-%% @doc Assures that literals have a compact representation. This is
-%% occasionally useful if <code>c_cons_skel/2</code>,
-%% <code>c_tuple_skel/1</code> or <code>unfold_literal/1</code> were
-%% used in the construction of <code>Node</code>, and you want to revert
-%% to the normal "folded" representation of literals. If
-%% <code>Node</code> represents a tuple or list constructor, its
-%% elements are rewritten recursively, and the node is reconstructed
-%% using <code>c_cons/2</code> or <code>c_tuple/1</code>, respectively;
-%% otherwise, <code>Node</code> is not changed.
-%%
-%% @see is_literal/1
-%% @see c_cons_skel/2
-%% @see c_tuple_skel/1
-%% @see c_cons/2
-%% @see c_tuple/1
-%% @see unfold_literal/1
-
-fold_literal(Node) ->
- case type(Node) of
- tuple ->
- update_c_tuple(Node, fold_literal_list(tuple_es(Node)));
- cons ->
- update_c_cons(Node, fold_literal(cons_hd(Node)),
- fold_literal(cons_tl(Node)));
- _ ->
- Node
- end.
-
-fold_literal_list([E | Es]) ->
- [fold_literal(E) | fold_literal_list(Es)];
-fold_literal_list([]) ->
- [].
-
-
-%% @spec unfold_literal(Node::cerl()) -> cerl()
-%%
-%% @doc Assures that literals have a fully expanded representation. If
-%% <code>Node</code> represents a literal tuple or list constructor, its
-%% elements are rewritten recursively, and the node is reconstructed
-%% using <code>c_cons_skel/2</code> or <code>c_tuple_skel/1</code>,
-%% respectively; otherwise, <code>Node</code> is not changed. The {@link
-%% fold_literal/1} can be used to revert to the normal compact
-%% representation.
-%%
-%% @see is_literal/1
-%% @see c_cons_skel/2
-%% @see c_tuple_skel/1
-%% @see c_cons/2
-%% @see c_tuple/1
-%% @see fold_literal/1
-
-unfold_literal(Node) ->
- case type(Node) of
- literal ->
- copy_ann(Node, unfold_concrete(concrete(Node)));
- _ ->
- Node
- end.
-
-unfold_concrete(Val) ->
- case Val of
- _ when tuple(Val) ->
- c_tuple_skel(unfold_concrete_list(tuple_to_list(Val)));
- [H|T] ->
- c_cons_skel(unfold_concrete(H), unfold_concrete(T));
- _ ->
- abstract(Val)
- end.
-
-unfold_concrete_list([E | Es]) ->
- [unfold_concrete(E) | unfold_concrete_list(Es)];
-unfold_concrete_list([]) ->
- [].
-
-
-%% ---------------------------------------------------------------------
-
--record(module, {ann = [], name, exports, attrs, defs}).
-
-
-%% @spec c_module(Name::cerl(), Exports, Definitions) -> cerl()
-%%
-%% Exports = [cerl()]
-%% Definitions = [{cerl(), cerl()}]
-%%
-%% @equiv c_module(Name, Exports, [], Definitions)
-
-c_module(Name, Exports, Es) ->
- #module{name = Name, exports = Exports, attrs = [], defs = Es}.
-
-
-%% @spec c_module(Name::cerl(), Exports, Attributes, Definitions) ->
-%% cerl()
-%%
-%% Exports = [cerl()]
-%% Attributes = [{cerl(), cerl()}]
-%% Definitions = [{cerl(), cerl()}]
-%%
-%% @doc Creates an abstract module definition. The result represents
-%% <pre>
-%% module <em>Name</em> [<em>E1</em>, ..., <em>Ek</em>]
-%% attributes [<em>K1</em> = <em>T1</em>, ...,
-%% <em>Km</em> = <em>Tm</em>]
-%% <em>V1</em> = <em>F1</em>
-%% ...
-%% <em>Vn</em> = <em>Fn</em>
-%% end</pre>
-%%
-%% if <code>Exports</code> = <code>[E1, ..., Ek]</code>,
-%% <code>Attributes</code> = <code>[{K1, T1}, ..., {Km, Tm}]</code>,
-%% and <code>Definitions</code> = <code>[{V1, F1}, ..., {Vn,
-%% Fn}]</code>.
-%%
-%% <p><code>Name</code> and all the <code>Ki</code> must be atom
-%% literals, and all the <code>Ti</code> must be constant literals. All
-%% the <code>Vi</code> and <code>Ei</code> must have type
-%% <code>var</code> and represent function names. All the
-%% <code>Fi</code> must have type <code>'fun'</code>.</p>
-%%
-%% @see c_module/3
-%% @see module_name/1
-%% @see module_exports/1
-%% @see module_attrs/1
-%% @see module_defs/1
-%% @see module_vars/1
-%% @see ann_c_module/4
-%% @see ann_c_module/5
-%% @see update_c_module/5
-%% @see c_atom/1
-%% @see c_var/1
-%% @see c_fun/2
-%% @see is_literal/1
-
-c_module(Name, Exports, Attrs, Es) ->
- #module{name = Name, exports = Exports, attrs = Attrs, defs = Es}.
-
-
-%% @spec ann_c_module(As::[term()], Name::cerl(), Exports,
-%% Definitions) -> cerl()
-%%
-%% Exports = [cerl()]
-%% Definitions = [{cerl(), cerl()}]
-%%
-%% @see c_module/3
-%% @see ann_c_module/5
-
-ann_c_module(As, Name, Exports, Es) ->
- #module{name = Name, exports = Exports, attrs = [], defs = Es,
- ann = As}.
-
-
-%% @spec ann_c_module(As::[term()], Name::cerl(), Exports,
-%% Attributes, Definitions) -> cerl()
-%%
-%% Exports = [cerl()]
-%% Attributes = [{cerl(), cerl()}]
-%% Definitions = [{cerl(), cerl()}]
-%%
-%% @see c_module/4
-%% @see ann_c_module/4
-
-ann_c_module(As, Name, Exports, Attrs, Es) ->
- #module{name = Name, exports = Exports, attrs = Attrs, defs = Es,
- ann = As}.
-
-
-%% @spec update_c_module(Old::cerl(), Name::cerl(), Exports,
-%% Attributes, Definitions) -> cerl()
-%%
-%% Exports = [cerl()]
-%% Attributes = [{cerl(), cerl()}]
-%% Definitions = [{cerl(), cerl()}]
-%%
-%% @see c_module/4
-
-update_c_module(Node, Name, Exports, Attrs, Es) ->
- #module{name = Name, exports = Exports, attrs = Attrs, defs = Es,
- ann = get_ann(Node)}.
-
-
-%% @spec is_c_module(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% module definition, otherwise <code>false</code>.
-%%
-%% @see type/1
-
-is_c_module(#module{}) ->
- true;
-is_c_module(_) ->
- false.
-
-
-%% @spec module_name(Node::cerl()) -> cerl()
-%%
-%% @doc Returns the name subtree of an abstract module definition.
-%%
-%% @see c_module/4
-
-module_name(Node) ->
- Node#module.name.
-
-
-%% @spec module_exports(Node::cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of exports subtrees of an abstract module
-%% definition.
-%%
-%% @see c_module/4
-
-module_exports(Node) ->
- Node#module.exports.
-
-
-%% @spec module_attrs(Node::cerl()) -> [{cerl(), cerl()}]
-%%
-%% @doc Returns the list of pairs of attribute key/value subtrees of
-%% an abstract module definition.
-%%
-%% @see c_module/4
-
-module_attrs(Node) ->
- Node#module.attrs.
-
-
-%% @spec module_defs(Node::cerl()) -> [{cerl(), cerl()}]
-%%
-%% @doc Returns the list of function definitions of an abstract module
-%% definition.
-%%
-%% @see c_module/4
-
-module_defs(Node) ->
- Node#module.defs.
-
-
-%% @spec module_vars(Node::cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of left-hand side function variable subtrees
-%% of an abstract module definition.
-%%
-%% @see c_module/4
-
-module_vars(Node) ->
- [F || {F, _} <- module_defs(Node)].
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_int(Value::integer()) -> cerl()
-%%
-%%
-%% @doc Creates an abstract integer literal. The lexical
-%% representation is the canonical decimal numeral of
-%% <code>Value</code>.
-%%
-%% @see ann_c_int/2
-%% @see is_c_int/1
-%% @see int_val/1
-%% @see int_lit/1
-%% @see c_char/1
-
-c_int(Value) ->
- #literal{val = Value}.
-
-
-%% @spec ann_c_int(As::[term()], Value::integer()) -> cerl()
-%% @see c_int/1
-
-ann_c_int(As, Value) ->
- #literal{val = Value, ann = As}.
-
-
-%% @spec is_c_int(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> represents an
-%% integer literal, otherwise <code>false</code>.
-%% @see c_int/1
-
-is_c_int(#literal{val = V}) when integer(V) ->
- true;
-is_c_int(_) ->
- false.
-
-
-%% @spec int_val(cerl()) -> integer()
-%%
-%% @doc Returns the value represented by an integer literal node.
-%% @see c_int/1
-
-int_val(Node) ->
- Node#literal.val.
-
-
-%% @spec int_lit(cerl()) -> string()
-%%
-%% @doc Returns the numeral string represented by an integer literal
-%% node.
-%% @see c_int/1
-
-int_lit(Node) ->
- integer_to_list(int_val(Node)).
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_float(Value::float()) -> cerl()
-%%
-%% @doc Creates an abstract floating-point literal. The lexical
-%% representation is the decimal floating-point numeral of
-%% <code>Value</code>.
-%%
-%% @see ann_c_float/2
-%% @see is_c_float/1
-%% @see float_val/1
-%% @see float_lit/1
-
-%% Note that not all floating-point numerals can be represented with
-%% full precision.
-
-c_float(Value) ->
- #literal{val = Value}.
-
-
-%% @spec ann_c_float(As::[term()], Value::float()) -> cerl()
-%% @see c_float/1
-
-ann_c_float(As, Value) ->
- #literal{val = Value, ann = As}.
-
-
-%% @spec is_c_float(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> represents a
-%% floating-point literal, otherwise <code>false</code>.
-%% @see c_float/1
-
-is_c_float(#literal{val = V}) when float(V) ->
- true;
-is_c_float(_) ->
- false.
-
-
-%% @spec float_val(cerl()) -> float()
-%%
-%% @doc Returns the value represented by a floating-point literal
-%% node.
-%% @see c_float/1
-
-float_val(Node) ->
- Node#literal.val.
-
-
-%% @spec float_lit(cerl()) -> string()
-%%
-%% @doc Returns the numeral string represented by a floating-point
-%% literal node.
-%% @see c_float/1
-
-float_lit(Node) ->
- float_to_list(float_val(Node)).
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_atom(Name) -> cerl()
-%% Name = atom() | string()
-%%
-%% @doc Creates an abstract atom literal. The print name of the atom
-%% is the character sequence represented by <code>Name</code>.
-%%
-%% <p>Note: passing a string as argument to this function causes a
-%% corresponding atom to be created for the internal representation.</p>
-%%
-%% @see ann_c_atom/2
-%% @see is_c_atom/1
-%% @see atom_val/1
-%% @see atom_name/1
-%% @see atom_lit/1
-
-c_atom(Name) when atom(Name) ->
- #literal{val = Name};
-c_atom(Name) ->
- #literal{val = list_to_atom(Name)}.
-
-
-%% @spec ann_c_atom(As::[term()], Name) -> cerl()
-%% Name = atom() | string()
-%% @see c_atom/1
-
-ann_c_atom(As, Name) when atom(Name) ->
- #literal{val = Name, ann = As};
-ann_c_atom(As, Name) ->
- #literal{val = list_to_atom(Name), ann = As}.
-
-
-%% @spec is_c_atom(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> represents an
-%% atom literal, otherwise <code>false</code>.
-%%
-%% @see c_atom/1
-
-is_c_atom(#literal{val = V}) when atom(V) ->
- true;
-is_c_atom(_) ->
- false.
-
-%% @spec atom_val(cerl())-> atom()
-%%
-%% @doc Returns the value represented by an abstract atom.
-%%
-%% @see c_atom/1
-
-atom_val(Node) ->
- Node#literal.val.
-
-
-%% @spec atom_name(cerl()) -> string()
-%%
-%% @doc Returns the printname of an abstract atom.
-%%
-%% @see c_atom/1
-
-atom_name(Node) ->
- atom_to_list(atom_val(Node)).
-
-
-%% @spec atom_lit(cerl()) -> string()
-%%
-%% @doc Returns the literal string represented by an abstract
-%% atom. This always includes surrounding single-quote characters.
-%%
-%% <p>Note that an abstract atom may have several literal
-%% representations, and that the representation yielded by this
-%% function is not fixed; e.g.,
-%% <code>atom_lit(c_atom("a\012b"))</code> could yield the string
-%% <code>"\'a\\nb\'"</code>.</p>
-%%
-%% @see c_atom/1
-
-%% TODO: replace the use of the unofficial 'write_string/2'.
-
-atom_lit(Node) ->
- io_lib:write_string(atom_name(Node), $'). %' stupid Emacs.
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_char(Value) -> cerl()
-%%
-%% Value = char() | integer()
-%%
-%% @doc Creates an abstract character literal. If the local
-%% implementation of Erlang defines <code>char()</code> as a subset of
-%% <code>integer()</code>, this function is equivalent to
-%% <code>c_int/1</code>. Otherwise, if the given value is an integer,
-%% it will be converted to the character with the corresponding
-%% code. The lexical representation of a character is
-%% "<code>$<em>Char</em></code>", where <code>Char</code> is a single
-%% printing character or an escape sequence.
-%%
-%% @see c_int/1
-%% @see c_string/1
-%% @see ann_c_char/2
-%% @see is_c_char/1
-%% @see char_val/1
-%% @see char_lit/1
-%% @see is_print_char/1
-
-c_char(Value) when integer(Value), Value >= 0 ->
- #literal{val = Value}.
-
-
-%% @spec ann_c_char(As::[term()], Value::char()) -> cerl()
-%% @see c_char/1
-
-ann_c_char(As, Value) ->
- #literal{val = Value, ann = As}.
-
-
-%% @spec is_c_char(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> may represent a
-%% character literal, otherwise <code>false</code>.
-%%
-%% <p>If the local implementation of Erlang defines
-%% <code>char()</code> as a subset of <code>integer()</code>, then
-%% <code>is_c_int(<em>Node</em>)</code> will also yield
-%% <code>true</code>.</p>
-%%
-%% @see c_char/1
-%% @see is_print_char/1
-
-is_c_char(#literal{val = V}) when integer(V), V >= 0 ->
- is_char_value(V);
-is_c_char(_) ->
- false.
-
-
-%% @spec is_print_char(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> may represent a
-%% "printing" character, otherwise <code>false</code>. (Cf.
-%% <code>is_c_char/1</code>.) A "printing" character has either a
-%% given graphical representation, or a "named" escape sequence such
-%% as "<code>\n</code>". Currently, only ISO 8859-1 (Latin-1)
-%% character values are recognized.
-%%
-%% @see c_char/1
-%% @see is_c_char/1
-
-is_print_char(#literal{val = V}) when integer(V), V >= 0 ->
- is_print_char_value(V);
-is_print_char(_) ->
- false.
-
-
-%% @spec char_val(cerl()) -> char()
-%%
-%% @doc Returns the value represented by an abstract character literal.
-%%
-%% @see c_char/1
-
-char_val(Node) ->
- Node#literal.val.
-
-
-%% @spec char_lit(cerl()) -> string()
-%%
-%% @doc Returns the literal string represented by an abstract
-%% character. This includes a leading <code>$</code>
-%% character. Currently, all characters that are not in the set of ISO
-%% 8859-1 (Latin-1) "printing" characters will be escaped.
-%%
-%% @see c_char/1
-
-char_lit(Node) ->
- io_lib:write_char(char_val(Node)).
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_string(Value::string()) -> cerl()
-%%
-%% @doc Creates an abstract string literal. Equivalent to creating an
-%% abstract list of the corresponding character literals
-%% (cf. <code>is_c_string/1</code>), but is typically more
-%% efficient. The lexical representation of a string is
-%% "<code>"<em>Chars</em>"</code>", where <code>Chars</code> is a
-%% sequence of printing characters or spaces.
-%%
-%% @see c_char/1
-%% @see ann_c_string/2
-%% @see is_c_string/1
-%% @see string_val/1
-%% @see string_lit/1
-%% @see is_print_string/1
-
-c_string(Value) ->
- #literal{val = Value}.
-
-
-%% @spec ann_c_string(As::[term()], Value::string()) -> cerl()
-%% @see c_string/1
-
-ann_c_string(As, Value) ->
- #literal{val = Value, ann = As}.
-
-
-%% @spec is_c_string(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> may represent a
-%% string literal, otherwise <code>false</code>. Strings are defined
-%% as lists of characters; see <code>is_c_char/1</code> for details.
-%%
-%% @see c_string/1
-%% @see is_c_char/1
-%% @see is_print_string/1
-
-is_c_string(#literal{val = V}) ->
- is_char_list(V);
-is_c_string(_) ->
- false.
-
-
-%% @spec is_print_string(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> may represent a
-%% string literal containing only "printing" characters, otherwise
-%% <code>false</code>. See <code>is_c_string/1</code> and
-%% <code>is_print_char/1</code> for details. Currently, only ISO
-%% 8859-1 (Latin-1) character values are recognized.
-%%
-%% @see c_string/1
-%% @see is_c_string/1
-%% @see is_print_char/1
-
-is_print_string(#literal{val = V}) ->
- is_print_char_list(V);
-is_print_string(_) ->
- false.
-
-
-%% @spec string_val(cerl()) -> string()
-%%
-%% @doc Returns the value represented by an abstract string literal.
-%%
-%% @see c_string/1
-
-string_val(Node) ->
- Node#literal.val.
-
-
-%% @spec string_lit(cerl()) -> string()
-%%
-%% @doc Returns the literal string represented by an abstract string.
-%% This includes surrounding double-quote characters
-%% <code>"..."</code>. Currently, characters that are not in the set
-%% of ISO 8859-1 (Latin-1) "printing" characters will be escaped,
-%% except for spaces.
-%%
-%% @see c_string/1
-
-string_lit(Node) ->
- io_lib:write_string(string_val(Node)).
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_nil() -> cerl()
-%%
-%% @doc Creates an abstract empty list. The result represents
-%% "<code>[]</code>". The empty list is traditionally called "nil".
-%%
-%% @see ann_c_nil/1
-%% @see is_c_list/1
-%% @see c_cons/2
-
-c_nil() ->
- #literal{val = []}.
-
-
-%% @spec ann_c_nil(As::[term()]) -> cerl()
-%% @see c_nil/0
-
-ann_c_nil(As) ->
- #literal{val = [], ann = As}.
-
-
-%% @spec is_c_nil(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% empty list, otherwise <code>false</code>.
-
-is_c_nil(#literal{val = []}) ->
- true;
-is_c_nil(_) ->
- false.
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_cons(Head::cerl(), Tail::cerl()) -> cerl()
-%%
-%% @doc Creates an abstract list constructor. The result represents
-%% "<code>[<em>Head</em> | <em>Tail</em>]</code>". Note that if both
-%% <code>Head</code> and <code>Tail</code> have type
-%% <code>literal</code>, then the result will also have type
-%% <code>literal</code>, and annotations on <code>Head</code> and
-%% <code>Tail</code> are lost.
-%%
-%% <p>Recall that in Erlang, the tail element of a list constructor is
-%% not necessarily a list.</p>
-%%
-%% @see ann_c_cons/3
-%% @see update_c_cons/3
-%% @see c_cons_skel/2
-%% @see is_c_cons/1
-%% @see cons_hd/1
-%% @see cons_tl/1
-%% @see is_c_list/1
-%% @see c_nil/0
-%% @see list_elements/1
-%% @see list_length/1
-%% @see make_list/2
-
--record(cons, {ann = [], hd, tl}).
-
-%% *Always* collapse literals.
-
-c_cons(#literal{val = Head}, #literal{val = Tail}) ->
- #literal{val = [Head | Tail]};
-c_cons(Head, Tail) ->
- #cons{hd = Head, tl = Tail}.
-
-
-%% @spec ann_c_cons(As::[term()], Head::cerl(), Tail::cerl()) -> cerl()
-%% @see c_cons/2
-
-ann_c_cons(As, #literal{val = Head}, #literal{val = Tail}) ->
- #literal{val = [Head | Tail], ann = As};
-ann_c_cons(As, Head, Tail) ->
- #cons{hd = Head, tl = Tail, ann = As}.
-
-
-%% @spec update_c_cons(Old::cerl(), Head::cerl(), Tail::cerl()) ->
-%% cerl()
-%% @see c_cons/2
-
-update_c_cons(Node, #literal{val = Head}, #literal{val = Tail}) ->
- #literal{val = [Head | Tail], ann = get_ann(Node)};
-update_c_cons(Node, Head, Tail) ->
- #cons{hd = Head, tl = Tail, ann = get_ann(Node)}.
-
-
-%% @spec c_cons_skel(Head::cerl(), Tail::cerl()) -> cerl()
-%%
-%% @doc Creates an abstract list constructor skeleton. Does not fold
-%% constant literals, i.e., the result always has type
-%% <code>cons</code>, representing "<code>[<em>Head</em> |
-%% <em>Tail</em>]</code>".
-%%
-%% <p>This function is occasionally useful when it is necessary to have
-%% annotations on the subnodes of a list constructor node, even when the
-%% subnodes are constant literals. Note however that
-%% <code>is_literal/1</code> will yield <code>false</code> and
-%% <code>concrete/1</code> will fail if passed the result from this
-%% function.</p>
-%%
-%% <p><code>fold_literal/1</code> can be used to revert a node to the
-%% normal-form representation.</p>
-%%
-%% @see ann_c_cons_skel/3
-%% @see update_c_cons_skel/3
-%% @see c_cons/2
-%% @see is_c_cons/1
-%% @see is_c_list/1
-%% @see c_nil/0
-%% @see is_literal/1
-%% @see fold_literal/1
-%% @see concrete/1
-
-%% *Never* collapse literals.
-
-c_cons_skel(Head, Tail) ->
- #cons{hd = Head, tl = Tail}.
-
-
-%% @spec ann_c_cons_skel(As::[term()], Head::cerl(), Tail::cerl()) ->
-%% cerl()
-%% @see c_cons_skel/2
-
-ann_c_cons_skel(As, Head, Tail) ->
- #cons{hd = Head, tl = Tail, ann = As}.
-
-
-%% @spec update_c_cons_skel(Old::cerl(), Head::cerl(), Tail::cerl()) ->
-%% cerl()
-%% @see c_cons_skel/2
-
-update_c_cons_skel(Node, Head, Tail) ->
- #cons{hd = Head, tl = Tail, ann = get_ann(Node)}.
-
-
-%% @spec is_c_cons(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% list constructor, otherwise <code>false</code>.
-
-is_c_cons(#cons{}) ->
- true;
-is_c_cons(#literal{val = [_ | _]}) ->
- true;
-is_c_cons(_) ->
- false.
-
-
-%% @spec cons_hd(cerl()) -> cerl()
-%%
-%% @doc Returns the head subtree of an abstract list constructor.
-%%
-%% @see c_cons/2
-
-cons_hd(#cons{hd = Head}) ->
- Head;
-cons_hd(#literal{val = [Head | _]}) ->
- #literal{val = Head}.
-
-
-%% @spec cons_tl(cerl()) -> cerl()
-%%
-%% @doc Returns the tail subtree of an abstract list constructor.
-%%
-%% <p>Recall that the tail does not necessarily represent a proper
-%% list.</p>
-%%
-%% @see c_cons/2
-
-cons_tl(#cons{tl = Tail}) ->
- Tail;
-cons_tl(#literal{val = [_ | Tail]}) ->
- #literal{val = Tail}.
-
-
-%% @spec is_c_list(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> represents a
-%% proper list, otherwise <code>false</code>. A proper list is either
-%% the empty list <code>[]</code>, or a cons cell <code>[<em>Head</em> |
-%% <em>Tail</em>]</code>, where recursively <code>Tail</code> is a
-%% proper list.
-%%
-%% <p>Note: Because <code>Node</code> is a syntax tree, the actual
-%% run-time values corresponding to its subtrees may often be partially
-%% or completely unknown. Thus, if <code>Node</code> represents e.g.
-%% "<code>[... | Ns]</code>" (where <code>Ns</code> is a variable), then
-%% the function will return <code>false</code>, because it is not known
-%% whether <code>Ns</code> will be bound to a list at run-time. If
-%% <code>Node</code> instead represents e.g. "<code>[1, 2, 3]</code>" or
-%% "<code>[A | []]</code>", then the function will return
-%% <code>true</code>.</p>
-%%
-%% @see c_cons/2
-%% @see c_nil/0
-%% @see list_elements/1
-%% @see list_length/1
-
-is_c_list(#cons{tl = Tail}) ->
- is_c_list(Tail);
-is_c_list(#literal{val = V}) ->
- is_proper_list(V);
-is_c_list(_) ->
- false.
-
-is_proper_list([_ | Tail]) ->
- is_proper_list(Tail);
-is_proper_list([]) ->
- true;
-is_proper_list(_) ->
- false.
-
-%% @spec list_elements(cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of element subtrees of an abstract list.
-%% <code>Node</code> must represent a proper list. E.g., if
-%% <code>Node</code> represents "<code>[<em>X1</em>, <em>X2</em> |
-%% [<em>X3</em>, <em>X4</em> | []]</code>", then
-%% <code>list_elements(Node)</code> yields the list <code>[X1, X2, X3,
-%% X4]</code>.
-%%
-%% @see c_cons/2
-%% @see c_nil/1
-%% @see is_c_list/1
-%% @see list_length/1
-%% @see make_list/2
-
-list_elements(#cons{hd = Head, tl = Tail}) ->
- [Head | list_elements(Tail)];
-list_elements(#literal{val = V}) ->
- abstract_list(V).
-
-abstract_list([X | Xs]) ->
- [abstract(X) | abstract_list(Xs)];
-abstract_list([]) ->
- [].
-
-
-%% @spec list_length(Node::cerl()) -> integer()
-%%
-%% @doc Returns the number of element subtrees of an abstract list.
-%% <code>Node</code> must represent a proper list. E.g., if
-%% <code>Node</code> represents "<code>[X1 | [X2, X3 | [X4, X5,
-%% X6]]]</code>", then <code>list_length(Node)</code> returns the
-%% integer 6.
-%%
-%% <p>Note: this is equivalent to
-%% <code>length(list_elements(Node))</code>, but potentially more
-%% efficient.</p>
-%%
-%% @see c_cons/2
-%% @see c_nil/1
-%% @see is_c_list/1
-%% @see list_elements/1
-
-list_length(L) ->
- list_length(L, 0).
-
-list_length(#cons{tl = Tail}, A) ->
- list_length(Tail, A + 1);
-list_length(#literal{val = V}, A) ->
- A + length(V).
-
-
-%% @spec make_list(List) -> Node
-%% @equiv make_list(List, none)
-
-make_list(List) ->
- ann_make_list([], List).
-
-
-%% @spec make_list(List::[cerl()], Tail) -> cerl()
-%%
-%% Tail = cerl() | none
-%%
-%% @doc Creates an abstract list from the elements in <code>List</code>
-%% and the optional <code>Tail</code>. If <code>Tail</code> is
-%% <code>none</code>, the result will represent a nil-terminated list,
-%% otherwise it represents "<code>[... | <em>Tail</em>]</code>".
-%%
-%% @see c_cons/2
-%% @see c_nil/0
-%% @see ann_make_list/3
-%% @see update_list/3
-%% @see list_elements/1
-
-make_list(List, Tail) ->
- ann_make_list([], List, Tail).
-
-
-%% @spec update_list(Old::cerl(), List::[cerl()]) -> cerl()
-%% @equiv update_list(Old, List, none)
-
-update_list(Node, List) ->
- ann_make_list(get_ann(Node), List).
-
-
-%% @spec update_list(Old::cerl(), List::[cerl()], Tail) -> cerl()
-%%
-%% Tail = cerl() | none
-%%
-%% @see make_list/2
-%% @see update_list/2
-
-update_list(Node, List, Tail) ->
- ann_make_list(get_ann(Node), List, Tail).
-
-
-%% @spec ann_make_list(As::[term()], List::[cerl()]) -> cerl()
-%% @equiv ann_make_list(As, List, none)
-
-ann_make_list(As, List) ->
- ann_make_list(As, List, none).
-
-
-%% @spec ann_make_list(As::[term()], List::[cerl()], Tail) -> cerl()
-%%
-%% Tail = cerl() | none
-%%
-%% @see make_list/2
-%% @see ann_make_list/2
-
-ann_make_list(As, [H | T], Tail) ->
- ann_c_cons(As, H, make_list(T, Tail)); % `c_cons' folds literals
-ann_make_list(As, [], none) ->
- ann_c_nil(As);
-ann_make_list(_, [], Node) ->
- Node.
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_tuple(Elements::[cerl()]) -> cerl()
-%%
-%% @doc Creates an abstract tuple. If <code>Elements</code> is
-%% <code>[E1, ..., En]</code>, the result represents
-%% "<code>{<em>E1</em>, ..., <em>En</em>}</code>". Note that if all
-%% nodes in <code>Elements</code> have type <code>literal</code>, or if
-%% <code>Elements</code> is empty, then the result will also have type
-%% <code>literal</code> and annotations on nodes in
-%% <code>Elements</code> are lost.
-%%
-%% <p>Recall that Erlang has distinct 1-tuples, i.e., <code>{X}</code>
-%% is always distinct from <code>X</code> itself.</p>
-%%
-%% @see ann_c_tuple/2
-%% @see update_c_tuple/2
-%% @see is_c_tuple/1
-%% @see tuple_es/1
-%% @see tuple_arity/1
-%% @see c_tuple_skel/1
-
--record(tuple, {ann = [], es}).
-
-%% *Always* collapse literals.
-
-c_tuple(Es) ->
- case is_lit_list(Es) of
- false ->
- #tuple{es = Es};
- true ->
- #literal{val = list_to_tuple(lit_list_vals(Es))}
- end.
-
-
-%% @spec ann_c_tuple(As::[term()], Elements::[cerl()]) -> cerl()
-%% @see c_tuple/1
-
-ann_c_tuple(As, Es) ->
- case is_lit_list(Es) of
- false ->
- #tuple{es = Es, ann = As};
- true ->
- #literal{val = list_to_tuple(lit_list_vals(Es)), ann = As}
- end.
-
-
-%% @spec update_c_tuple(Old::cerl(), Elements::[cerl()]) -> cerl()
-%% @see c_tuple/1
-
-update_c_tuple(Node, Es) ->
- case is_lit_list(Es) of
- false ->
- #tuple{es = Es, ann = get_ann(Node)};
- true ->
- #literal{val = list_to_tuple(lit_list_vals(Es)),
- ann = get_ann(Node)}
- end.
-
-
-%% @spec c_tuple_skel(Elements::[cerl()]) -> cerl()
-%%
-%% @doc Creates an abstract tuple skeleton. Does not fold constant
-%% literals, i.e., the result always has type <code>tuple</code>,
-%% representing "<code>{<em>E1</em>, ..., <em>En</em>}</code>", if
-%% <code>Elements</code> is <code>[E1, ..., En]</code>.
-%%
-%% <p>This function is occasionally useful when it is necessary to have
-%% annotations on the subnodes of a tuple node, even when all the
-%% subnodes are constant literals. Note however that
-%% <code>is_literal/1</code> will yield <code>false</code> and
-%% <code>concrete/1</code> will fail if passed the result from this
-%% function.</p>
-%%
-%% <p><code>fold_literal/1</code> can be used to revert a node to the
-%% normal-form representation.</p>
-%%
-%% @see ann_c_tuple_skel/2
-%% @see update_c_tuple_skel/2
-%% @see c_tuple/1
-%% @see tuple_es/1
-%% @see is_c_tuple/1
-%% @see is_literal/1
-%% @see fold_literal/1
-%% @see concrete/1
-
-%% *Never* collapse literals.
-
-c_tuple_skel(Es) ->
- #tuple{es = Es}.
-
-
-%% @spec ann_c_tuple_skel(As::[term()], Elements::[cerl()]) -> cerl()
-%% @see c_tuple_skel/1
-
-ann_c_tuple_skel(As, Es) ->
- #tuple{es = Es, ann = As}.
-
-
-%% @spec update_c_tuple_skel(Old::cerl(), Elements::[cerl()]) -> cerl()
-%% @see c_tuple_skel/1
-
-update_c_tuple_skel(Old, Es) ->
- #tuple{es = Es, ann = get_ann(Old)}.
-
-
-%% @spec is_c_tuple(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% tuple, otherwise <code>false</code>.
-%%
-%% @see c_tuple/1
-
-is_c_tuple(#tuple{}) ->
- true;
-is_c_tuple(#literal{val = V}) when tuple(V) ->
- true;
-is_c_tuple(_) ->
- false.
-
-
-%% @spec tuple_es(cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of element subtrees of an abstract tuple.
-%%
-%% @see c_tuple/1
-
-tuple_es(#tuple{es = Es}) ->
- Es;
-tuple_es(#literal{val = V}) ->
- make_lit_list(tuple_to_list(V)).
-
-
-%% @spec tuple_arity(Node::cerl()) -> integer()
-%%
-%% @doc Returns the number of element subtrees of an abstract tuple.
-%%
-%% <p>Note: this is equivalent to <code>length(tuple_es(Node))</code>,
-%% but potentially more efficient.</p>
-%%
-%% @see tuple_es/1
-%% @see c_tuple/1
-
-tuple_arity(#tuple{es = Es}) ->
- length(Es);
-tuple_arity(#literal{val = V}) when tuple(V) ->
- size(V).
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_var(Name::var_name()) -> cerl()
-%%
-%% var_name() = integer() | atom() | {atom(), integer()}
-%%
-%% @doc Creates an abstract variable. A variable is identified by its
-%% name, given by the <code>Name</code> parameter.
-%%
-%% <p>If a name is given by a single atom, it should either be a
-%% "simple" atom which does not need to be single-quoted in Erlang, or
-%% otherwise its print name should correspond to a proper Erlang
-%% variable, i.e., begin with an uppercase character or an
-%% underscore. Names on the form <code>{A, N}</code> represent
-%% function name variables "<code><em>A</em>/<em>N</em></code>"; these
-%% are special variables which may be bound only in the function
-%% definitions of a module or a <code>letrec</code>. They may not be
-%% bound in <code>let</code> expressions and cannot occur in clause
-%% patterns. The atom <code>A</code> in a function name may be any
-%% atom; the integer <code>N</code> must be nonnegative. The functions
-%% <code>c_fname/2</code> etc. are utilities for handling function
-%% name variables.</p>
-%%
-%% <p>When printing variable names, they must have the form of proper
-%% Core Erlang variables and function names. E.g., a name represented
-%% by an integer such as <code>42</code> could be formatted as
-%% "<code>_42</code>", an atom <code>'Xxx'</code> simply as
-%% "<code>Xxx</code>", and an atom <code>foo</code> as
-%% "<code>_foo</code>". However, one must assure that any two valid
-%% distinct names are never mapped to the same strings. Tuples such
-%% as <code>{foo, 2}</code> representing function names can simply by
-%% formatted as "<code>'foo'/2</code>", with no risk of conflicts.</p>
-%%
-%% @see ann_c_var/2
-%% @see update_c_var/2
-%% @see is_c_var/1
-%% @see var_name/1
-%% @see c_fname/2
-%% @see c_module/4
-%% @see c_letrec/2
-
--record(var, {ann = [], name}).
-
-c_var(Name) ->
- #var{name = Name}.
-
-
-%% @spec ann_c_var(As::[term()], Name::var_name()) -> cerl()
-%%
-%% @see c_var/1
-
-ann_c_var(As, Name) ->
- #var{name = Name, ann = As}.
-
-%% @spec update_c_var(Old::cerl(), Name::var_name()) -> cerl()
-%%
-%% @see c_var/1
-
-update_c_var(Node, Name) ->
- #var{name = Name, ann = get_ann(Node)}.
-
-
-%% @spec is_c_var(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% variable, otherwise <code>false</code>.
-%%
-%% @see c_var/1
-
-is_c_var(#var{}) ->
- true;
-is_c_var(_) ->
- false.
-
-
-%% @spec c_fname(Name::atom(), Arity::integer()) -> cerl()
-%% @equiv c_var({Name, Arity})
-%% @see fname_id/1
-%% @see fname_arity/1
-%% @see is_c_fname/1
-%% @see ann_c_fname/3
-%% @see update_c_fname/3
-
-c_fname(Atom, Arity) ->
- c_var({Atom, Arity}).
-
-
-%% @spec ann_c_fname(As::[term()], Name::atom(), Arity::integer()) ->
-%% cerl()
-%% @equiv ann_c_var(As, {Atom, Arity})
-%% @see c_fname/2
-
-ann_c_fname(As, Atom, Arity) ->
- ann_c_var(As, {Atom, Arity}).
-
-
-%% @spec update_c_fname(Old::cerl(), Name::atom()) -> cerl()
-%% @doc Like <code>update_c_fname/3</code>, but takes the arity from
-%% <code>Node</code>.
-%% @see update_c_fname/3
-%% @see c_fname/2
-
-update_c_fname(#var{name = {_, Arity}, ann = As}, Atom) ->
- #var{name = {Atom, Arity}, ann = As}.
-
-
-%% @spec update_c_fname(Old::cerl(), Name::atom(), Arity::integer()) ->
-%% cerl()
-%% @equiv update_c_var(Old, {Atom, Arity})
-%% @see update_c_fname/2
-%% @see c_fname/2
-
-update_c_fname(Node, Atom, Arity) ->
- update_c_var(Node, {Atom, Arity}).
-
-
-%% @spec is_c_fname(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% function name variable, otherwise <code>false</code>.
-%%
-%% @see c_fname/2
-%% @see c_var/1
-%% @see c_var_name/1
-
-is_c_fname(#var{name = {A, N}}) when atom(A), integer(N), N >= 0 ->
- true;
-is_c_fname(_) ->
- false.
-
-
-%% @spec var_name(cerl()) -> var_name()
-%%
-%% @doc Returns the name of an abstract variable.
-%%
-%% @see c_var/1
-
-var_name(Node) ->
- Node#var.name.
-
-
-%% @spec fname_id(cerl()) -> atom()
-%%
-%% @doc Returns the identifier part of an abstract function name
-%% variable.
-%%
-%% @see fname_arity/1
-%% @see c_fname/2
-
-fname_id(#var{name={A,_}}) ->
- A.
-
-
-%% @spec fname_arity(cerl()) -> integer()
-%%
-%% @doc Returns the arity part of an abstract function name variable.
-%%
-%% @see fname_id/1
-%% @see c_fname/2
-
-fname_arity(#var{name={_,N}}) ->
- N.
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_values(Elements::[cerl()]) -> cerl()
-%%
-%% @doc Creates an abstract value list. If <code>Elements</code> is
-%% <code>[E1, ..., En]</code>, the result represents
-%% "<code>&lt;<em>E1</em>, ..., <em>En</em>&gt;</code>".
-%%
-%% @see ann_c_values/2
-%% @see update_c_values/2
-%% @see is_c_values/1
-%% @see values_es/1
-%% @see values_arity/1
-
--record(values, {ann = [], es}).
-
-c_values(Es) ->
- #values{es = Es}.
-
-
-%% @spec ann_c_values(As::[term()], Elements::[cerl()]) -> cerl()
-%% @see c_values/1
-
-ann_c_values(As, Es) ->
- #values{es = Es, ann = As}.
-
-
-%% @spec update_c_values(Old::cerl(), Elements::[cerl()]) -> cerl()
-%% @see c_values/1
-
-update_c_values(Node, Es) ->
- #values{es = Es, ann = get_ann(Node)}.
-
-
-%% @spec is_c_values(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% value list; otherwise <code>false</code>.
-%%
-%% @see c_values/1
-
-is_c_values(#values{}) ->
- true;
-is_c_values(_) ->
- false.
-
-
-%% @spec values_es(cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of element subtrees of an abstract value
-%% list.
-%%
-%% @see c_values/1
-%% @see values_arity/1
-
-values_es(Node) ->
- Node#values.es.
-
-
-%% @spec values_arity(Node::cerl()) -> integer()
-%%
-%% @doc Returns the number of element subtrees of an abstract value
-%% list.
-%%
-%% <p>Note: This is equivalent to
-%% <code>length(values_es(Node))</code>, but potentially more
-%% efficient.</p>
-%%
-%% @see c_values/1
-%% @see values_es/1
-
-values_arity(Node) ->
- length(values_es(Node)).
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_binary(Segments::[cerl()]) -> cerl()
-%%
-%% @doc Creates an abstract binary-template. A binary object is a
-%% sequence of 8-bit bytes. It is specified by zero or more bit-string
-%% template <em>segments</em> of arbitrary lengths (in number of bits),
-%% such that the sum of the lengths is evenly divisible by 8. If
-%% <code>Segments</code> is <code>[S1, ..., Sn]</code>, the result
-%% represents "<code>#{<em>S1</em>, ..., <em>Sn</em>}#</code>". All the
-%% <code>Si</code> must have type <code>bitstr</code>.
-%%
-%% @see ann_c_binary/2
-%% @see update_c_binary/2
-%% @see is_c_binary/1
-%% @see binary_segments/1
-%% @see c_bitstr/5
-
--record(binary, {ann = [], segments}).
-
-c_binary(Segments) ->
- #binary{segments = Segments}.
-
-
-%% @spec ann_c_binary(As::[term()], Segments::[cerl()]) -> cerl()
-%% @see c_binary/1
-
-ann_c_binary(As, Segments) ->
- #binary{segments = Segments, ann = As}.
-
-
-%% @spec update_c_binary(Old::cerl(), Segments::[cerl()]) -> cerl()
-%% @see c_binary/1
-
-update_c_binary(Node, Segments) ->
- #binary{segments = Segments, ann = get_ann(Node)}.
-
-
-%% @spec is_c_binary(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% binary-template; otherwise <code>false</code>.
-%%
-%% @see c_binary/1
-
-is_c_binary(#binary{}) ->
- true;
-is_c_binary(_) ->
- false.
-
-
-%% @spec binary_segments(cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of segment subtrees of an abstract
-%% binary-template.
-%%
-%% @see c_binary/1
-%% @see c_bitstr/5
-
-binary_segments(Node) ->
- Node#binary.segments.
-
-
-%% @spec c_bitstr(Value::cerl(), Size::cerl(), Unit::cerl(),
-%% Type::cerl(), Flags::cerl()) -> cerl()
-%%
-%% @doc Creates an abstract bit-string template. These can only occur as
-%% components of an abstract binary-template (see {@link c_binary/1}).
-%% The result represents "<code>#&lt;<em>Value</em>&gt;(<em>Size</em>,
-%% <em>Unit</em>, <em>Type</em>, <em>Flags</em>)</code>", where
-%% <code>Unit</code> must represent a positive integer constant,
-%% <code>Type</code> must represent a constant atom (one of
-%% <code>'integer'</code>, <code>'float'</code>, or
-%% <code>'binary'</code>), and <code>Flags</code> must represent a
-%% constant list <code>"[<em>F1</em>, ..., <em>Fn</em>]"</code> where
-%% all the <code>Fi</code> are atoms.
-%%
-%% @see c_binary/1
-%% @see ann_c_bitstr/6
-%% @see update_c_bitstr/6
-%% @see is_c_bitstr/1
-%% @see bitstr_val/1
-%% @see bitstr_size/1
-%% @see bitstr_unit/1
-%% @see bitstr_type/1
-%% @see bitstr_flags/1
-
--record(bitstr, {ann = [], val, size, unit, type, flags}).
-
-c_bitstr(Val, Size, Unit, Type, Flags) ->
- #bitstr{val = Val, size = Size, unit = Unit, type = Type,
- flags = Flags}.
-
-
-%% @spec c_bitstr(Value::cerl(), Size::cerl(), Type::cerl(),
-%% Flags::cerl()) -> cerl()
-%% @equiv c_bitstr(Value, Size, abstract(1), Type, Flags)
-
-c_bitstr(Val, Size, Type, Flags) ->
- c_bitstr(Val, Size, abstract(1), Type, Flags).
-
-
-%% @spec c_bitstr(Value::cerl(), Type::cerl(),
-%% Flags::cerl()) -> cerl()
-%% @equiv c_bitstr(Value, abstract(all), abstract(1), Type, Flags)
-
-c_bitstr(Val, Type, Flags) ->
- c_bitstr(Val, abstract(all), abstract(1), Type, Flags).
-
-
-%% @spec ann_c_bitstr(As::[term()], Value::cerl(), Size::cerl(),
-%% Unit::cerl(), Type::cerl(), Flags::cerl()) -> cerl()
-%% @see c_bitstr/5
-%% @see ann_c_bitstr/5
-
-ann_c_bitstr(As, Val, Size, Unit, Type, Flags) ->
- #bitstr{val = Val, size = Size, unit = Unit, type = Type,
- flags = Flags, ann = As}.
-
-%% @spec ann_c_bitstr(As::[term()], Value::cerl(), Size::cerl(),
-%% Type::cerl(), Flags::cerl()) -> cerl()
-%% @equiv ann_c_bitstr(As, Value, Size, abstract(1), Type, Flags)
-
-ann_c_bitstr(As, Value, Size, Type, Flags) ->
- ann_c_bitstr(As, Value, Size, abstract(1), Type, Flags).
-
-
-%% @spec update_c_bitstr(Old::cerl(), Value::cerl(), Size::cerl(),
-%% Unit::cerl(), Type::cerl(), Flags::cerl()) -> cerl()
-%% @see c_bitstr/5
-%% @see update_c_bitstr/5
-
-update_c_bitstr(Node, Val, Size, Unit, Type, Flags) ->
- #bitstr{val = Val, size = Size, unit = Unit, type = Type,
- flags = Flags, ann = get_ann(Node)}.
-
-
-%% @spec update_c_bitstr(Old::cerl(), Value::cerl(), Size::cerl(),
-%% Type::cerl(), Flags::cerl()) -> cerl()
-%% @equiv update_c_bitstr(Node, Value, Size, abstract(1), Type, Flags)
-
-update_c_bitstr(Node, Value, Size, Type, Flags) ->
- update_c_bitstr(Node, Value, Size, abstract(1), Type, Flags).
-
-%% @spec is_c_bitstr(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% bit-string template; otherwise <code>false</code>.
-%%
-%% @see c_bitstr/5
-
-is_c_bitstr(#bitstr{}) ->
- true;
-is_c_bitstr(_) ->
- false.
-
-
-%% @spec bitstr_val(cerl()) -> cerl()
-%%
-%% @doc Returns the value subtree of an abstract bit-string template.
-%%
-%% @see c_bitstr/5
-
-bitstr_val(Node) ->
- Node#bitstr.val.
-
-
-%% @spec bitstr_size(cerl()) -> cerl()
-%%
-%% @doc Returns the size subtree of an abstract bit-string template.
-%%
-%% @see c_bitstr/5
-
-bitstr_size(Node) ->
- Node#bitstr.size.
-
-
-%% @spec bitstr_bitsize(cerl()) -> integer() | any | all
-%%
-%% @doc Returns the total size in bits of an abstract bit-string
-%% template. If the size field is an integer literal, the result is the
-%% product of the size and unit values; if the size field is the atom
-%% literal <code>all</code>, the atom <code>all</code> is returned; in
-%% all other cases, the atom <code>any</code> is returned.
-%%
-%% @see c_bitstr/5
-
-bitstr_bitsize(Node) ->
- Size = Node#bitstr.size,
- case is_literal(Size) of
- true ->
- case concrete(Size) of
- all ->
- all;
- S when integer(S) ->
- S*concrete(Node#bitstr.unit);
- true ->
- any
- end;
- false ->
- any
- end.
-
-
-%% @spec bitstr_unit(cerl()) -> cerl()
-%%
-%% @doc Returns the unit subtree of an abstract bit-string template.
-%%
-%% @see c_bitstr/5
-
-bitstr_unit(Node) ->
- Node#bitstr.unit.
-
-
-%% @spec bitstr_type(cerl()) -> cerl()
-%%
-%% @doc Returns the type subtree of an abstract bit-string template.
-%%
-%% @see c_bitstr/5
-
-bitstr_type(Node) ->
- Node#bitstr.type.
-
-
-%% @spec bitstr_flags(cerl()) -> cerl()
-%%
-%% @doc Returns the flags subtree of an abstract bit-string template.
-%%
-%% @see c_bitstr/5
-
-bitstr_flags(Node) ->
- Node#bitstr.flags.
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_fun(Variables::[cerl()], Body::cerl()) -> cerl()
-%%
-%% @doc Creates an abstract fun-expression. If <code>Variables</code>
-%% is <code>[V1, ..., Vn]</code>, the result represents "<code>fun
-%% (<em>V1</em>, ..., <em>Vn</em>) -> <em>Body</em></code>". All the
-%% <code>Vi</code> must have type <code>var</code>.
-%%
-%% @see ann_c_fun/3
-%% @see update_c_fun/3
-%% @see is_c_fun/1
-%% @see fun_vars/1
-%% @see fun_body/1
-%% @see fun_arity/1
-
--record('fun', {ann = [], vars, body}).
-
-c_fun(Variables, Body) ->
- #'fun'{vars = Variables, body = Body}.
-
-
-%% @spec ann_c_fun(As::[term()], Variables::[cerl()], Body::cerl()) ->
-%% cerl()
-%% @see c_fun/2
-
-ann_c_fun(As, Variables, Body) ->
- #'fun'{vars = Variables, body = Body, ann = As}.
-
-
-%% @spec update_c_fun(Old::cerl(), Variables::[cerl()],
-%% Body::cerl()) -> cerl()
-%% @see c_fun/2
-
-update_c_fun(Node, Variables, Body) ->
- #'fun'{vars = Variables, body = Body, ann = get_ann(Node)}.
-
-
-%% @spec is_c_fun(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% fun-expression, otherwise <code>false</code>.
-%%
-%% @see c_fun/2
-
-is_c_fun(#'fun'{}) ->
- true; % Now this is fun!
-is_c_fun(_) ->
- false.
-
-
-%% @spec fun_vars(cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of parameter subtrees of an abstract
-%% fun-expression.
-%%
-%% @see c_fun/2
-%% @see fun_arity/1
-
-fun_vars(Node) ->
- Node#'fun'.vars.
-
-
-%% @spec fun_body(cerl()) -> cerl()
-%%
-%% @doc Returns the body subtree of an abstract fun-expression.
-%%
-%% @see c_fun/2
-
-fun_body(Node) ->
- Node#'fun'.body.
-
-
-%% @spec fun_arity(Node::cerl()) -> integer()
-%%
-%% @doc Returns the number of parameter subtrees of an abstract
-%% fun-expression.
-%%
-%% <p>Note: this is equivalent to <code>length(fun_vars(Node))</code>,
-%% but potentially more efficient.</p>
-%%
-%% @see c_fun/2
-%% @see fun_vars/1
-
-fun_arity(Node) ->
- length(fun_vars(Node)).
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_seq(Argument::cerl(), Body::cerl()) -> cerl()
-%%
-%% @doc Creates an abstract sequencing expression. The result
-%% represents "<code>do <em>Argument</em> <em>Body</em></code>".
-%%
-%% @see ann_c_seq/3
-%% @see update_c_seq/3
-%% @see is_c_seq/1
-%% @see seq_arg/1
-%% @see seq_body/1
-
--record(seq, {ann = [], arg, body}).
-
-c_seq(Argument, Body) ->
- #seq{arg = Argument, body = Body}.
-
-
-%% @spec ann_c_seq(As::[term()], Argument::cerl(), Body::cerl()) ->
-%% cerl()
-%% @see c_seq/2
-
-ann_c_seq(As, Argument, Body) ->
- #seq{arg = Argument, body = Body, ann = As}.
-
-
-%% @spec update_c_seq(Old::cerl(), Argument::cerl(), Body::cerl()) ->
-%% cerl()
-%% @see c_seq/2
-
-update_c_seq(Node, Argument, Body) ->
- #seq{arg = Argument, body = Body, ann = get_ann(Node)}.
-
-
-%% @spec is_c_seq(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% sequencing expression, otherwise <code>false</code>.
-%%
-%% @see c_seq/2
-
-is_c_seq(#seq{}) ->
- true;
-is_c_seq(_) ->
- false.
-
-
-%% @spec seq_arg(cerl()) -> cerl()
-%%
-%% @doc Returns the argument subtree of an abstract sequencing
-%% expression.
-%%
-%% @see c_seq/2
-
-seq_arg(Node) ->
- Node#seq.arg.
-
-
-%% @spec seq_body(cerl()) -> cerl()
-%%
-%% @doc Returns the body subtree of an abstract sequencing expression.
-%%
-%% @see c_seq/2
-
-seq_body(Node) ->
- Node#seq.body.
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_let(Variables::[cerl()], Argument::cerl(), Body::cerl()) ->
-%% cerl()
-%%
-%% @doc Creates an abstract let-expression. If <code>Variables</code>
-%% is <code>[V1, ..., Vn]</code>, the result represents "<code>let
-%% &lt;<em>V1</em>, ..., <em>Vn</em>&gt; = <em>Argument</em> in
-%% <em>Body</em></code>". All the <code>Vi</code> must have type
-%% <code>var</code>.
-%%
-%% @see ann_c_let/4
-%% @see update_c_let/4
-%% @see is_c_let/1
-%% @see let_vars/1
-%% @see let_arg/1
-%% @see let_body/1
-%% @see let_arity/1
-
--record('let', {ann = [], vars, arg, body}).
-
-c_let(Variables, Argument, Body) ->
- #'let'{vars = Variables, arg = Argument, body = Body}.
-
-
-%% ann_c_let(As, Variables, Argument, Body) -> Node
-%% @see c_let/3
-
-ann_c_let(As, Variables, Argument, Body) ->
- #'let'{vars = Variables, arg = Argument, body = Body, ann = As}.
-
-
-%% update_c_let(Old, Variables, Argument, Body) -> Node
-%% @see c_let/3
-
-update_c_let(Node, Variables, Argument, Body) ->
- #'let'{vars = Variables, arg = Argument, body = Body,
- ann = get_ann(Node)}.
-
-
-%% @spec is_c_let(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% let-expression, otherwise <code>false</code>.
-%%
-%% @see c_let/3
-
-is_c_let(#'let'{}) ->
- true;
-is_c_let(_) ->
- false.
-
-
-%% @spec let_vars(cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of left-hand side variables of an abstract
-%% let-expression.
-%%
-%% @see c_let/3
-%% @see let_arity/1
-
-let_vars(Node) ->
- Node#'let'.vars.
-
-
-%% @spec let_arg(cerl()) -> cerl()
-%%
-%% @doc Returns the argument subtree of an abstract let-expression.
-%%
-%% @see c_let/3
-
-let_arg(Node) ->
- Node#'let'.arg.
-
-
-%% @spec let_body(cerl()) -> cerl()
-%%
-%% @doc Returns the body subtree of an abstract let-expression.
-%%
-%% @see c_let/3
-
-let_body(Node) ->
- Node#'let'.body.
-
-
-%% @spec let_arity(Node::cerl()) -> integer()
-%%
-%% @doc Returns the number of left-hand side variables of an abstract
-%% let-expression.
-%%
-%% <p>Note: this is equivalent to <code>length(let_vars(Node))</code>,
-%% but potentially more efficient.</p>
-%%
-%% @see c_let/3
-%% @see let_vars/1
-
-let_arity(Node) ->
- length(let_vars(Node)).
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_letrec(Definitions::[{cerl(), cerl()}], Body::cerl()) ->
-%% cerl()
-%%
-%% @doc Creates an abstract letrec-expression. If
-%% <code>Definitions</code> is <code>[{V1, F1}, ..., {Vn, Fn}]</code>,
-%% the result represents "<code>letrec <em>V1</em> = <em>F1</em>
-%% ... <em>Vn</em> = <em>Fn</em> in <em>Body</em></code>. All the
-%% <code>Vi</code> must have type <code>var</code> and represent
-%% function names. All the <code>Fi</code> must have type
-%% <code>'fun'</code>.
-%%
-%% @see ann_c_letrec/3
-%% @see update_c_letrec/3
-%% @see is_c_letrec/1
-%% @see letrec_defs/1
-%% @see letrec_body/1
-%% @see letrec_vars/1
-
--record(letrec, {ann = [], defs, body}).
-
-c_letrec(Defs, Body) ->
- #letrec{defs = Defs, body = Body}.
-
-
-%% @spec ann_c_letrec(As::[term()], Definitions::[{cerl(), cerl()}],
-%% Body::cerl()) -> cerl()
-%% @see c_letrec/2
-
-ann_c_letrec(As, Defs, Body) ->
- #letrec{defs = Defs, body = Body, ann = As}.
-
-
-%% @spec update_c_letrec(Old::cerl(),
-%% Definitions::[{cerl(), cerl()}],
-%% Body::cerl()) -> cerl()
-%% @see c_letrec/2
-
-update_c_letrec(Node, Defs, Body) ->
- #letrec{defs = Defs, body = Body, ann = get_ann(Node)}.
-
-
-%% @spec is_c_letrec(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% letrec-expression, otherwise <code>false</code>.
-%%
-%% @see c_letrec/2
-
-is_c_letrec(#letrec{}) ->
- true;
-is_c_letrec(_) ->
- false.
-
-
-%% @spec letrec_defs(Node::cerl()) -> [{cerl(), cerl()}]
-%%
-%% @doc Returns the list of definitions of an abstract
-%% letrec-expression. If <code>Node</code> represents "<code>letrec
-%% <em>V1</em> = <em>F1</em> ... <em>Vn</em> = <em>Fn</em> in
-%% <em>Body</em></code>", the returned value is <code>[{V1, F1}, ...,
-%% {Vn, Fn}]</code>.
-%%
-%% @see c_letrec/2
-
-letrec_defs(Node) ->
- Node#letrec.defs.
-
-
-%% @spec letrec_body(cerl()) -> cerl()
-%%
-%% @doc Returns the body subtree of an abstract letrec-expression.
-%%
-%% @see c_letrec/2
-
-letrec_body(Node) ->
- Node#letrec.body.
-
-
-%% @spec letrec_vars(cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of left-hand side function variable subtrees
-%% of a letrec-expression. If <code>Node</code> represents
-%% "<code>letrec <em>V1</em> = <em>F1</em> ... <em>Vn</em> =
-%% <em>Fn</em> in <em>Body</em></code>", the returned value is
-%% <code>[V1, ..., Vn]</code>.
-%%
-%% @see c_letrec/2
-
-letrec_vars(Node) ->
- [F || {F, _} <- letrec_defs(Node)].
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_case(Argument::cerl(), Clauses::[cerl()]) -> cerl()
-%%
-%% @doc Creates an abstract case-expression. If <code>Clauses</code>
-%% is <code>[C1, ..., Cn]</code>, the result represents "<code>case
-%% <em>Argument</em> of <em>C1</em> ... <em>Cn</em>
-%% end</code>". <code>Clauses</code> must not be empty.
-%%
-%% @see ann_c_case/3
-%% @see update_c_case/3
-%% @see is_c_case/1
-%% @see c_clause/3
-%% @see case_arg/1
-%% @see case_clauses/1
-%% @see case_arity/1
-
--record('case', {ann = [], arg, clauses}).
-
-c_case(Expr, Clauses) ->
- #'case'{arg = Expr, clauses = Clauses}.
-
-
-%% @spec ann_c_case(As::[term()], Argument::cerl(),
-%% Clauses::[cerl()]) -> cerl()
-%% @see c_case/2
-
-ann_c_case(As, Expr, Clauses) ->
- #'case'{arg = Expr, clauses = Clauses, ann = As}.
-
-
-%% @spec update_c_case(Old::cerl(), Argument::cerl(),
-%% Clauses::[cerl()]) -> cerl()
-%% @see c_case/2
-
-update_c_case(Node, Expr, Clauses) ->
- #'case'{arg = Expr, clauses = Clauses, ann = get_ann(Node)}.
-
-
-%% is_c_case(Node) -> boolean()
-%%
-%% Node = cerl()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% case-expression; otherwise <code>false</code>.
-%%
-%% @see c_case/2
-
-is_c_case(#'case'{}) ->
- true;
-is_c_case(_) ->
- false.
-
-
-%% @spec case_arg(cerl()) -> cerl()
-%%
-%% @doc Returns the argument subtree of an abstract case-expression.
-%%
-%% @see c_case/2
-
-case_arg(Node) ->
- Node#'case'.arg.
-
-
-%% @spec case_clauses(cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of clause subtrees of an abstract
-%% case-expression.
-%%
-%% @see c_case/2
-%% @see case_arity/1
-
-case_clauses(Node) ->
- Node#'case'.clauses.
-
-
-%% @spec case_arity(Node::cerl()) -> integer()
-%%
-%% @doc Equivalent to
-%% <code>clause_arity(hd(case_clauses(Node)))</code>, but potentially
-%% more efficient.
-%%
-%% @see c_case/2
-%% @see case_clauses/1
-%% @see clause_arity/1
-
-case_arity(Node) ->
- clause_arity(hd(case_clauses(Node))).
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_clause(Patterns::[cerl()], Body::cerl()) -> cerl()
-%% @equiv c_clause(Patterns, c_atom(true), Body)
-%% @see c_atom/1
-
-c_clause(Patterns, Body) ->
- c_clause(Patterns, c_atom(true), Body).
-
-
-%% @spec c_clause(Patterns::[cerl()], Guard::cerl(), Body::cerl()) ->
-%% cerl()
-%%
-%% @doc Creates an an abstract clause. If <code>Patterns</code> is
-%% <code>[P1, ..., Pn]</code>, the result represents
-%% "<code>&lt;<em>P1</em>, ..., <em>Pn</em>&gt; when <em>Guard</em> ->
-%% <em>Body</em></code>".
-%%
-%% @see c_clause/2
-%% @see ann_c_clause/4
-%% @see update_c_clause/4
-%% @see is_c_clause/1
-%% @see c_case/2
-%% @see c_receive/3
-%% @see clause_pats/1
-%% @see clause_guard/1
-%% @see clause_body/1
-%% @see clause_arity/1
-%% @see clause_vars/1
-
--record(clause, {ann = [], pats, guard, body}).
-
-c_clause(Patterns, Guard, Body) ->
- #clause{pats = Patterns, guard = Guard, body = Body}.
-
-
-%% @spec ann_c_clause(As::[term()], Patterns::[cerl()],
-%% Body::cerl()) -> cerl()
-%% @equiv ann_c_clause(As, Patterns, c_atom(true), Body)
-%% @see c_clause/3
-ann_c_clause(As, Patterns, Body) ->
- ann_c_clause(As, Patterns, c_atom(true), Body).
-
-
-%% @spec ann_c_clause(As::[term()], Patterns::[cerl()], Guard::cerl(),
-%% Body::cerl()) -> cerl()
-%% @see ann_c_clause/3
-%% @see c_clause/3
-
-ann_c_clause(As, Patterns, Guard, Body) ->
- #clause{pats = Patterns, guard = Guard, body = Body, ann = As}.
-
-
-%% @spec update_c_clause(Old::cerl(), Patterns::[cerl()],
-%% Guard::cerl(), Body::cerl()) -> cerl()
-%% @see c_clause/3
-
-update_c_clause(Node, Patterns, Guard, Body) ->
- #clause{pats = Patterns, guard = Guard, body = Body,
- ann = get_ann(Node)}.
-
-
-%% @spec is_c_clause(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% clause, otherwise <code>false</code>.
-%%
-%% @see c_clause/3
-
-is_c_clause(#clause{}) ->
- true;
-is_c_clause(_) ->
- false.
-
-
-%% @spec clause_pats(cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of pattern subtrees of an abstract clause.
-%%
-%% @see c_clause/3
-%% @see clause_arity/1
-
-clause_pats(Node) ->
- Node#clause.pats.
-
-
-%% @spec clause_guard(cerl()) -> cerl()
-%%
-%% @doc Returns the guard subtree of an abstract clause.
-%%
-%% @see c_clause/3
-
-clause_guard(Node) ->
- Node#clause.guard.
-
-
-%% @spec clause_body(cerl()) -> cerl()
-%%
-%% @doc Returns the body subtree of an abstract clause.
-%%
-%% @see c_clause/3
-
-clause_body(Node) ->
- Node#clause.body.
-
-
-%% @spec clause_arity(Node::cerl()) -> integer()
-%%
-%% @doc Returns the number of pattern subtrees of an abstract clause.
-%%
-%% <p>Note: this is equivalent to
-%% <code>length(clause_pats(Node))</code>, but potentially more
-%% efficient.</p>
-%%
-%% @see c_clause/3
-%% @see clause_pats/1
-
-clause_arity(Node) ->
- length(clause_pats(Node)).
-
-
-%% @spec clause_vars(cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of all abstract variables in the patterns of
-%% an abstract clause. The order of listing is not defined.
-%%
-%% @see c_clause/3
-%% @see pat_list_vars/1
-
-clause_vars(Clause) ->
- pat_list_vars(clause_pats(Clause)).
-
-
-%% @spec pat_vars(Pattern::cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of all abstract variables in a pattern. An
-%% exception is thrown if <code>Node</code> does not represent a
-%% well-formed Core Erlang clause pattern. The order of listing is not
-%% defined.
-%%
-%% @see pat_list_vars/1
-%% @see clause_vars/1
-
-pat_vars(Node) ->
- pat_vars(Node, []).
-
-pat_vars(Node, Vs) ->
- case type(Node) of
- var ->
- [Node | Vs];
- literal ->
- Vs;
- cons ->
- pat_vars(cons_hd(Node), pat_vars(cons_tl(Node), Vs));
- tuple ->
- pat_list_vars(tuple_es(Node), Vs);
- binary ->
- pat_list_vars(binary_segments(Node), Vs);
- bitstr ->
- pat_vars(bitstr_val(Node), Vs);
- alias ->
- pat_vars(alias_pat(Node), [alias_var(Node) | Vs])
- end.
-
-
-%% @spec pat_list_vars(Patterns::[cerl()]) -> [cerl()]
-%%
-%% @doc Returns the list of all abstract variables in the given
-%% patterns. An exception is thrown if some element in
-%% <code>Patterns</code> does not represent a well-formed Core Erlang
-%% clause pattern. The order of listing is not defined.
-%%
-%% @see pat_vars/1
-%% @see clause_vars/1
-
-pat_list_vars(Ps) ->
- pat_list_vars(Ps, []).
-
-pat_list_vars([P | Ps], Vs) ->
- pat_list_vars(Ps, pat_vars(P, Vs));
-pat_list_vars([], Vs) ->
- Vs.
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_alias(Variable::cerl(), Pattern::cerl()) -> cerl()
-%%
-%% @doc Creates an abstract pattern alias. The result represents
-%% "<code><em>Variable</em> = <em>Pattern</em></code>".
-%%
-%% @see ann_c_alias/3
-%% @see update_c_alias/3
-%% @see is_c_alias/1
-%% @see alias_var/1
-%% @see alias_pat/1
-%% @see c_clause/3
-
--record(alias, {ann = [], var, pat}).
-
-c_alias(Var, Pattern) ->
- #alias{var = Var, pat = Pattern}.
-
-
-%% @spec ann_c_alias(As::[term()], Variable::cerl(),
-%% Pattern::cerl()) -> cerl()
-%% @see c_alias/2
-
-ann_c_alias(As, Var, Pattern) ->
- #alias{var = Var, pat = Pattern, ann = As}.
-
-
-%% @spec update_c_alias(Old::cerl(), Variable::cerl(),
-%% Pattern::cerl()) -> cerl()
-%% @see c_alias/2
-
-update_c_alias(Node, Var, Pattern) ->
- #alias{var = Var, pat = Pattern, ann = get_ann(Node)}.
-
-
-%% @spec is_c_alias(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% pattern alias, otherwise <code>false</code>.
-%%
-%% @see c_alias/2
-
-is_c_alias(#alias{}) ->
- true;
-is_c_alias(_) ->
- false.
-
-
-%% @spec alias_var(cerl()) -> cerl()
-%%
-%% @doc Returns the variable subtree of an abstract pattern alias.
-%%
-%% @see c_alias/2
-
-alias_var(Node) ->
- Node#alias.var.
-
-
-%% @spec alias_pat(cerl()) -> cerl()
-%%
-%% @doc Returns the pattern subtree of an abstract pattern alias.
-%%
-%% @see c_alias/2
-
-alias_pat(Node) ->
- Node#alias.pat.
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_receive(Clauses::[cerl()]) -> cerl()
-%% @equiv c_receive(Clauses, c_atom(infinity), c_atom(true))
-%% @see c_atom/1
-
-c_receive(Clauses) ->
- c_receive(Clauses, c_atom(infinity), c_atom(true)).
-
-
-%% @spec c_receive(Clauses::[cerl()], Timeout::cerl(),
-%% Action::cerl()) -> cerl()
-%%
-%% @doc Creates an abstract receive-expression. If
-%% <code>Clauses</code> is <code>[C1, ..., Cn]</code>, the result
-%% represents "<code>receive <em>C1</em> ... <em>Cn</em> after
-%% <em>Timeout</em> -> <em>Action</em> end</code>".
-%%
-%% @see c_receive/1
-%% @see ann_c_receive/4
-%% @see update_c_receive/4
-%% @see is_c_receive/1
-%% @see receive_clauses/1
-%% @see receive_timeout/1
-%% @see receive_action/1
-
--record('receive', {ann = [], clauses, timeout, action}).
-
-c_receive(Clauses, Timeout, Action) ->
- #'receive'{clauses = Clauses, timeout = Timeout, action = Action}.
-
-
-%% @spec ann_c_receive(As::[term()], Clauses::[cerl()]) -> cerl()
-%% @equiv ann_c_receive(As, Clauses, c_atom(infinity), c_atom(true))
-%% @see c_receive/3
-%% @see c_atom/1
-
-ann_c_receive(As, Clauses) ->
- ann_c_receive(As, Clauses, c_atom(infinity), c_atom(true)).
-
-
-%% @spec ann_c_receive(As::[term()], Clauses::[cerl()],
-%% Timeout::cerl(), Action::cerl()) -> cerl()
-%% @see ann_c_receive/2
-%% @see c_receive/3
-
-ann_c_receive(As, Clauses, Timeout, Action) ->
- #'receive'{clauses = Clauses, timeout = Timeout, action = Action,
- ann = As}.
-
-
-%% @spec update_c_receive(Old::cerl(), Clauses::[cerl()],
-%% Timeout::cerl(), Action::cerl()) -> cerl()
-%% @see c_receive/3
-
-update_c_receive(Node, Clauses, Timeout, Action) ->
- #'receive'{clauses = Clauses, timeout = Timeout, action = Action,
- ann = get_ann(Node)}.
-
-
-%% @spec is_c_receive(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% receive-expression, otherwise <code>false</code>.
-%%
-%% @see c_receive/3
-
-is_c_receive(#'receive'{}) ->
- true;
-is_c_receive(_) ->
- false.
-
-
-%% @spec receive_clauses(cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of clause subtrees of an abstract
-%% receive-expression.
-%%
-%% @see c_receive/3
-
-receive_clauses(Node) ->
- Node#'receive'.clauses.
-
-
-%% @spec receive_timeout(cerl()) -> cerl()
-%%
-%% @doc Returns the timeout subtree of an abstract receive-expression.
-%%
-%% @see c_receive/3
-
-receive_timeout(Node) ->
- Node#'receive'.timeout.
-
-
-%% @spec receive_action(cerl()) -> cerl()
-%%
-%% @doc Returns the action subtree of an abstract receive-expression.
-%%
-%% @see c_receive/3
-
-receive_action(Node) ->
- Node#'receive'.action.
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_apply(Operator::cerl(), Arguments::[cerl()]) -> cerl()
-%%
-%% @doc Creates an abstract function application. If
-%% <code>Arguments</code> is <code>[A1, ..., An]</code>, the result
-%% represents "<code>apply <em>Operator</em>(<em>A1</em>, ...,
-%% <em>An</em>)</code>".
-%%
-%% @see ann_c_apply/3
-%% @see update_c_apply/3
-%% @see is_c_apply/1
-%% @see apply_op/1
-%% @see apply_args/1
-%% @see apply_arity/1
-%% @see c_call/3
-%% @see c_primop/2
-
--record(apply, {ann = [], op, args}).
-
-c_apply(Operator, Arguments) ->
- #apply{op = Operator, args = Arguments}.
-
-
-%% @spec ann_c_apply(As::[term()], Operator::cerl(),
-%% Arguments::[cerl()]) -> cerl()
-%% @see c_apply/2
-
-ann_c_apply(As, Operator, Arguments) ->
- #apply{op = Operator, args = Arguments, ann = As}.
-
-
-%% @spec update_c_apply(Old::cerl(), Operator::cerl(),
-%% Arguments::[cerl()]) -> cerl()
-%% @see c_apply/2
-
-update_c_apply(Node, Operator, Arguments) ->
- #apply{op = Operator, args = Arguments, ann = get_ann(Node)}.
-
-
-%% @spec is_c_apply(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% function application, otherwise <code>false</code>.
-%%
-%% @see c_apply/2
-
-is_c_apply(#apply{}) ->
- true;
-is_c_apply(_) ->
- false.
-
-
-%% @spec apply_op(cerl()) -> cerl()
-%%
-%% @doc Returns the operator subtree of an abstract function
-%% application.
-%%
-%% @see c_apply/2
-
-apply_op(Node) ->
- Node#apply.op.
-
-
-%% @spec apply_args(cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of argument subtrees of an abstract function
-%% application.
-%%
-%% @see c_apply/2
-%% @see apply_arity/1
-
-apply_args(Node) ->
- Node#apply.args.
-
-
-%% @spec apply_arity(Node::cerl()) -> integer()
-%%
-%% @doc Returns the number of argument subtrees of an abstract
-%% function application.
-%%
-%% <p>Note: this is equivalent to
-%% <code>length(apply_args(Node))</code>, but potentially more
-%% efficient.</p>
-%%
-%% @see c_apply/2
-%% @see apply_args/1
-
-apply_arity(Node) ->
- length(apply_args(Node)).
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_call(Module::cerl(), Name::cerl(), Arguments::[cerl()]) ->
-%% cerl()
-%%
-%% @doc Creates an abstract inter-module call. If
-%% <code>Arguments</code> is <code>[A1, ..., An]</code>, the result
-%% represents "<code>call <em>Module</em>:<em>Name</em>(<em>A1</em>,
-%% ..., <em>An</em>)</code>".
-%%
-%% @see ann_c_call/4
-%% @see update_c_call/4
-%% @see is_c_call/1
-%% @see call_module/1
-%% @see call_name/1
-%% @see call_args/1
-%% @see call_arity/1
-%% @see c_apply/2
-%% @see c_primop/2
-
--record(call, {ann = [], module, name, args}).
-
-c_call(Module, Name, Arguments) ->
- #call{module = Module, name = Name, args = Arguments}.
-
-
-%% @spec ann_c_call(As::[term()], Module::cerl(), Name::cerl(),
-%% Arguments::[cerl()]) -> cerl()
-%% @see c_call/3
-
-ann_c_call(As, Module, Name, Arguments) ->
- #call{module = Module, name = Name, args = Arguments, ann = As}.
-
-
-%% @spec update_c_call(Old::cerl(), Module::cerl(), Name::cerl(),
-%% Arguments::[cerl()]) -> cerl()
-%% @see c_call/3
-
-update_c_call(Node, Module, Name, Arguments) ->
- #call{module = Module, name = Name, args = Arguments,
- ann = get_ann(Node)}.
-
-
-%% @spec is_c_call(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% inter-module call expression; otherwise <code>false</code>.
-%%
-%% @see c_call/3
-
-is_c_call(#call{}) ->
- true;
-is_c_call(_) ->
- false.
-
-
-%% @spec call_module(cerl()) -> cerl()
-%%
-%% @doc Returns the module subtree of an abstract inter-module call.
-%%
-%% @see c_call/3
-
-call_module(Node) ->
- Node#call.module.
-
-
-%% @spec call_name(cerl()) -> cerl()
-%%
-%% @doc Returns the name subtree of an abstract inter-module call.
-%%
-%% @see c_call/3
-
-call_name(Node) ->
- Node#call.name.
-
-
-%% @spec call_args(cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of argument subtrees of an abstract
-%% inter-module call.
-%%
-%% @see c_call/3
-%% @see call_arity/1
-
-call_args(Node) ->
- Node#call.args.
-
-
-%% @spec call_arity(Node::cerl()) -> integer()
-%%
-%% @doc Returns the number of argument subtrees of an abstract
-%% inter-module call.
-%%
-%% <p>Note: this is equivalent to
-%% <code>length(call_args(Node))</code>, but potentially more
-%% efficient.</p>
-%%
-%% @see c_call/3
-%% @see call_args/1
-
-call_arity(Node) ->
- length(call_args(Node)).
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_primop(Name::cerl(), Arguments::[cerl()]) -> cerl()
-%%
-%% @doc Creates an abstract primitive operation call. If
-%% <code>Arguments</code> is <code>[A1, ..., An]</code>, the result
-%% represents "<code>primop <em>Name</em>(<em>A1</em>, ...,
-%% <em>An</em>)</code>". <code>Name</code> must be an atom literal.
-%%
-%% @see ann_c_primop/3
-%% @see update_c_primop/3
-%% @see is_c_primop/1
-%% @see primop_name/1
-%% @see primop_args/1
-%% @see primop_arity/1
-%% @see c_apply/2
-%% @see c_call/3
-
--record(primop, {ann = [], name, args}).
-
-c_primop(Name, Arguments) ->
- #primop{name = Name, args = Arguments}.
-
-
-%% @spec ann_c_primop(As::[term()], Name::cerl(),
-%% Arguments::[cerl()]) -> cerl()
-%% @see c_primop/2
-
-ann_c_primop(As, Name, Arguments) ->
- #primop{name = Name, args = Arguments, ann = As}.
-
-
-%% @spec update_c_primop(Old::cerl(), Name::cerl(),
-%% Arguments::[cerl()]) -> cerl()
-%% @see c_primop/2
-
-update_c_primop(Node, Name, Arguments) ->
- #primop{name = Name, args = Arguments, ann = get_ann(Node)}.
-
-
-%% @spec is_c_primop(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% primitive operation call, otherwise <code>false</code>.
-%%
-%% @see c_primop/2
-
-is_c_primop(#primop{}) ->
- true;
-is_c_primop(_) ->
- false.
-
-
-%% @spec primop_name(cerl()) -> cerl()
-%%
-%% @doc Returns the name subtree of an abstract primitive operation
-%% call.
-%%
-%% @see c_primop/2
-
-primop_name(Node) ->
- Node#primop.name.
-
-
-%% @spec primop_args(cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of argument subtrees of an abstract primitive
-%% operation call.
-%%
-%% @see c_primop/2
-%% @see primop_arity/1
-
-primop_args(Node) ->
- Node#primop.args.
-
-
-%% @spec primop_arity(Node::cerl()) -> integer()
-%%
-%% @doc Returns the number of argument subtrees of an abstract
-%% primitive operation call.
-%%
-%% <p>Note: this is equivalent to
-%% <code>length(primop_args(Node))</code>, but potentially more
-%% efficient.</p>
-%%
-%% @see c_primop/2
-%% @see primop_args/1
-
-primop_arity(Node) ->
- length(primop_args(Node)).
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_try(Argument::cerl(), Variables::[cerl()], Body::cerl(),
-%% ExceptionVars::[cerl()], Handler::cerl()) -> cerl()
-%%
-%% @doc Creates an abstract try-expression. If <code>Variables</code> is
-%% <code>[V1, ..., Vn]</code> and <code>ExceptionVars</code> is
-%% <code>[X1, ..., Xm]</code>, the result represents "<code>try
-%% <em>Argument</em> of &lt;<em>V1</em>, ..., <em>Vn</em>&gt; ->
-%% <em>Body</em> catch &lt;<em>X1</em>, ..., <em>Xm</em>&gt; ->
-%% <em>Handler</em></code>". All the <code>Vi</code> and <code>Xi</code>
-%% must have type <code>var</code>.
-%%
-%% @see ann_c_try/6
-%% @see update_c_try/6
-%% @see is_c_try/1
-%% @see try_arg/1
-%% @see try_vars/1
-%% @see try_body/1
-%% @see c_catch/1
-
--record('try', {ann = [], arg, vars, body, evars, handler}).
-
-c_try(Expr, Vs, Body, Evs, Handler) ->
- #'try'{arg = Expr, vars = Vs, body = Body,
- evars = Evs, handler = Handler}.
-
-
-%% @spec ann_c_try(As::[term()], Expression::cerl(),
-%% Variables::[cerl()], Body::cerl(),
-%% EVars::[cerl()], EBody::[cerl()]) -> cerl()
-%% @see c_try/3
-
-ann_c_try(As, Expr, Vs, Body, Evs, Handler) ->
- #'try'{arg = Expr, vars = Vs, body = Body,
- evars = Evs, handler = Handler, ann = As}.
-
-
-%% @spec update_c_try(Old::cerl(), Expression::cerl(),
-%% Variables::[cerl()], Body::cerl(),
-%% EVars::[cerl()], EBody::[cerl()]) -> cerl()
-%% @see c_try/3
-
-update_c_try(Node, Expr, Vs, Body, Evs, Handler) ->
- #'try'{arg = Expr, vars = Vs, body = Body,
- evars = Evs, handler = Handler, ann = get_ann(Node)}.
-
-
-%% @spec is_c_try(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% try-expression, otherwise <code>false</code>.
-%%
-%% @see c_try/3
-
-is_c_try(#'try'{}) ->
- true;
-is_c_try(_) ->
- false.
-
-
-%% @spec try_arg(cerl()) -> cerl()
-%%
-%% @doc Returns the expression subtree of an abstract try-expression.
-%%
-%% @see c_try/3
-
-try_arg(Node) ->
- Node#'try'.arg.
-
-
-%% @spec try_vars(cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of success variable subtrees of an abstract
-%% try-expression.
-%%
-%% @see c_try/3
-
-try_vars(Node) ->
- Node#'try'.vars.
-
-
-%% @spec try_body(cerl()) -> cerl()
-%%
-%% @doc Returns the success body subtree of an abstract try-expression.
-%%
-%% @see c_try/3
-
-try_body(Node) ->
- Node#'try'.body.
-
-
-%% @spec try_evars(cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of exception variable subtrees of an abstract
-%% try-expression.
-%%
-%% @see c_try/3
-
-try_evars(Node) ->
- Node#'try'.evars.
-
-
-%% @spec try_handler(cerl()) -> cerl()
-%%
-%% @doc Returns the exception body subtree of an abstract
-%% try-expression.
-%%
-%% @see c_try/3
-
-try_handler(Node) ->
- Node#'try'.handler.
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec c_catch(Body::cerl()) -> cerl()
-%%
-%% @doc Creates an abstract catch-expression. The result represents
-%% "<code>catch <em>Body</em></code>".
-%%
-%% <p>Note: catch-expressions can be rewritten as try-expressions, and
-%% will eventually be removed from Core Erlang.</p>
-%%
-%% @see ann_c_catch/2
-%% @see update_c_catch/2
-%% @see is_c_catch/1
-%% @see catch_body/1
-%% @see c_try/3
-
--record('catch', {ann = [], body}).
-
-c_catch(Body) ->
- #'catch'{body = Body}.
-
-
-%% @spec ann_c_catch(As::[term()], Body::cerl()) -> cerl()
-%% @see c_catch/1
-
-ann_c_catch(As, Body) ->
- #'catch'{body = Body, ann = As}.
-
-
-%% @spec update_c_catch(Old::cerl(), Body::cerl()) -> cerl()
-%% @see c_catch/1
-
-update_c_catch(Node, Body) ->
- #'catch'{body = Body, ann = get_ann(Node)}.
-
-
-%% @spec is_c_catch(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
-%% catch-expression, otherwise <code>false</code>.
-%%
-%% @see c_catch/1
-
-is_c_catch(#'catch'{}) ->
- true;
-is_c_catch(_) ->
- false.
-
-
-%% @spec catch_body(Node::cerl()) -> cerl()
-%%
-%% @doc Returns the body subtree of an abstract catch-expression.
-%%
-%% @see c_catch/1
-
-catch_body(Node) ->
- Node#'catch'.body.
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec to_records(Tree::cerl()) -> record(record_types())
-%%
-%% @doc Translates an abstract syntax tree to a corresponding explicit
-%% record representation. The records are defined in the file
-%% "<code>cerl.hrl</code>".
-%%
-%% <p>Note: Compound constant literals are always unfolded in the
-%% record representation.</p>
-%%
-%% @see type/1
-%% @see from_records/1
-
-to_records(Node) ->
- A = get_ann(Node),
- case type(Node) of
- literal ->
- lit_to_records(concrete(Node), A);
- binary ->
- #c_binary{anno = A,
- segments =
- list_to_records(binary_segments(Node))};
- bitstr ->
- #c_bitstr{anno = A,
- val = to_records(bitstr_val(Node)),
- size = to_records(bitstr_size(Node)),
- unit = to_records(bitstr_unit(Node)),
- type = to_records(bitstr_type(Node)),
- flags = to_records(bitstr_flags(Node))};
- cons ->
- #c_cons{anno = A,
- hd = to_records(cons_hd(Node)),
- tl = to_records(cons_tl(Node))};
- tuple ->
- #c_tuple{anno = A,
- es = list_to_records(tuple_es(Node))};
- var ->
- case is_c_fname(Node) of
- true ->
- #c_fname{anno = A,
- id = fname_id(Node),
- arity = fname_arity(Node)};
- false ->
- #c_var{anno = A, name = var_name(Node)}
- end;
- values ->
- #c_values{anno = A,
- es = list_to_records(values_es(Node))};
- 'fun' ->
- #c_fun{anno = A,
- vars = list_to_records(fun_vars(Node)),
- body = to_records(fun_body(Node))};
- seq ->
- #c_seq{anno = A,
- arg = to_records(seq_arg(Node)),
- body = to_records(seq_body(Node))};
- 'let' ->
- #c_let{anno = A,
- vars = list_to_records(let_vars(Node)),
- arg = to_records(let_arg(Node)),
- body = to_records(let_body(Node))};
- letrec ->
- #c_letrec{anno = A,
- defs = [#c_def{name = to_records(N),
- val = to_records(F)}
- || {N, F} <- letrec_defs(Node)],
- body = to_records(letrec_body(Node))};
- 'case' ->
- #c_case{anno = A,
- arg = to_records(case_arg(Node)),
- clauses =
- list_to_records(case_clauses(Node))};
- clause ->
- #c_clause{anno = A,
- pats = list_to_records(clause_pats(Node)),
- guard = to_records(clause_guard(Node)),
- body = to_records(clause_body(Node))};
- alias ->
- #c_alias{anno = A,
- var = to_records(alias_var(Node)),
- pat = to_records(alias_pat(Node))};
- 'receive' ->
- #c_receive{anno = A,
- clauses =
- list_to_records(receive_clauses(Node)),
- timeout =
- to_records(receive_timeout(Node)),
- action =
- to_records(receive_action(Node))};
- apply ->
- #c_apply{anno = A,
- op = to_records(apply_op(Node)),
- args = list_to_records(apply_args(Node))};
- call ->
- #c_call{anno = A,
- module = to_records(call_module(Node)),
- name = to_records(call_name(Node)),
- args = list_to_records(call_args(Node))};
- primop ->
- #c_primop{anno = A,
- name = to_records(primop_name(Node)),
- args = list_to_records(primop_args(Node))};
- 'try' ->
- #c_try{anno = A,
- arg = to_records(try_arg(Node)),
- vars = list_to_records(try_vars(Node)),
- body = to_records(try_body(Node)),
- evars = list_to_records(try_evars(Node)),
- handler = to_records(try_handler(Node))};
- 'catch' ->
- #c_catch{anno = A,
- body = to_records(catch_body(Node))};
- module ->
- #c_module{anno = A,
- name = to_records(module_name(Node)),
- exports = list_to_records(
- module_exports(Node)),
- attrs = [#c_def{name = to_records(K),
- val = to_records(V)}
- || {K, V} <- module_attrs(Node)],
- defs = [#c_def{name = to_records(N),
- val = to_records(F)}
- || {N, F} <- module_defs(Node)]}
- end.
-
-list_to_records([T | Ts]) ->
- [to_records(T) | list_to_records(Ts)];
-list_to_records([]) ->
- [].
-
-lit_to_records(V, A) when integer(V) ->
- #c_int{anno = A, val = V};
-lit_to_records(V, A) when float(V) ->
- #c_float{anno = A, val = V};
-lit_to_records(V, A) when atom(V) ->
- #c_atom{anno = A, val = V};
-lit_to_records([H | T] = V, A) ->
- case is_print_char_list(V) of
- true ->
- #c_string{anno = A, val = V};
- false ->
- #c_cons{anno = A,
- hd = lit_to_records(H, []),
- tl = lit_to_records(T, [])}
- end;
-lit_to_records([], A) ->
- #c_nil{anno = A};
-lit_to_records(V, A) when tuple(V) ->
- #c_tuple{anno = A, es = lit_list_to_records(tuple_to_list(V))}.
-
-lit_list_to_records([T | Ts]) ->
- [lit_to_records(T, []) | lit_list_to_records(Ts)];
-lit_list_to_records([]) ->
- [].
-
-
-%% @spec from_records(Tree::record(record_types())) -> cerl()
-%%
-%% record_types() = c_alias | c_apply | c_call | c_case | c_catch |
-%% c_clause | c_cons | c_def| c_fun | c_let |
-%% c_letrec |c_lit | c_module | c_primop |
-%% c_receive | c_seq | c_try | c_tuple |
-%% c_values | c_var
-%%
-%% @doc Translates an explicit record representation to a
-%% corresponding abstract syntax tree. The records are defined in the
-%% file "<code>cerl.hrl</code>".
-%%
-%% <p>Note: Compound constant literals are folded, discarding
-%% annotations on subtrees. There are no <code>c_def</code> nodes in
-%% the abstract representation; annotations on <code>c_def</code>
-%% records are discarded.</p>
-%%
-%% @see type/1
-%% @see to_records/1
-
-from_records(#c_int{val = V, anno = As}) ->
- ann_c_int(As, V);
-from_records(#c_float{val = V, anno = As}) ->
- ann_c_float(As, V);
-from_records(#c_atom{val = V, anno = As}) ->
- ann_c_atom(As, V);
-from_records(#c_char{val = V, anno = As}) ->
- ann_c_char(As, V);
-from_records(#c_string{val = V, anno = As}) ->
- ann_c_string(As, V);
-from_records(#c_nil{anno = As}) ->
- ann_c_nil(As);
-from_records(#c_binary{segments = Ss, anno = As}) ->
- ann_c_binary(As, from_records_list(Ss));
-from_records(#c_bitstr{val = V, size = S, unit = U, type = T,
- flags = Fs, anno = As}) ->
- ann_c_bitstr(As, from_records(V), from_records(S), from_records(U),
- from_records(T), from_records(Fs));
-from_records(#c_cons{hd = H, tl = T, anno = As}) ->
- ann_c_cons(As, from_records(H), from_records(T));
-from_records(#c_tuple{es = Es, anno = As}) ->
- ann_c_tuple(As, from_records_list(Es));
-from_records(#c_var{name = Name, anno = As}) ->
- ann_c_var(As, Name);
-from_records(#c_fname{id = Id, arity = Arity, anno = As}) ->
- ann_c_fname(As, Id, Arity);
-from_records(#c_values{es = Es, anno = As}) ->
- ann_c_values(As, from_records_list(Es));
-from_records(#c_fun{vars = Vs, body = B, anno = As}) ->
- ann_c_fun(As, from_records_list(Vs), from_records(B));
-from_records(#c_seq{arg = A, body = B, anno = As}) ->
- ann_c_seq(As, from_records(A), from_records(B));
-from_records(#c_let{vars = Vs, arg = A, body = B, anno = As}) ->
- ann_c_let(As, from_records_list(Vs), from_records(A),
- from_records(B));
-from_records(#c_letrec{defs = Fs, body = B, anno = As}) ->
- ann_c_letrec(As, [{from_records(N), from_records(F)}
- || #c_def{name = N, val = F} <- Fs],
- from_records(B));
-from_records(#c_case{arg = A, clauses = Cs, anno = As}) ->
- ann_c_case(As, from_records(A), from_records_list(Cs));
-from_records(#c_clause{pats = Ps, guard = G, body = B, anno = As}) ->
- ann_c_clause(As, from_records_list(Ps), from_records(G),
- from_records(B));
-from_records(#c_alias{var = V, pat = P, anno = As}) ->
- ann_c_alias(As, from_records(V), from_records(P));
-from_records(#c_receive{clauses = Cs, timeout = T, action = A,
- anno = As}) ->
- ann_c_receive(As, from_records_list(Cs), from_records(T),
- from_records(A));
-from_records(#c_apply{op = Op, args = Es, anno = As}) ->
- ann_c_apply(As, from_records(Op), from_records_list(Es));
-from_records(#c_call{module = M, name = N, args = Es, anno = As}) ->
- ann_c_call(As, from_records(M), from_records(N),
- from_records_list(Es));
-from_records(#c_primop{name = N, args = Es, anno = As}) ->
- ann_c_primop(As, from_records(N), from_records_list(Es));
-from_records(#c_try{arg = E, vars = Vs, body = B,
- evars = Evs, handler = H, anno = As}) ->
- ann_c_try(As, from_records(E), from_records_list(Vs),
- from_records(B), from_records_list(Evs), from_records(H));
-from_records(#c_catch{body = B, anno = As}) ->
- ann_c_catch(As, from_records(B));
-from_records(#c_module{name = N, exports = Es, attrs = Ds, defs = Fs,
- anno = As}) ->
- ann_c_module(As, from_records(N),
- from_records_list(Es),
- [{from_records(K), from_records(V)}
- || #c_def{name = K, val = V} <- Ds],
- [{from_records(V), from_records(F)}
- || #c_def{name = V, val = F} <- Fs]).
-
-from_records_list([T | Ts]) ->
- [from_records(T) | from_records_list(Ts)];
-from_records_list([]) ->
- [].
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec is_data(Node::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if <code>Node</code> represents a
-%% data constructor, otherwise <code>false</code>. Data constructors
-%% are cons cells, tuples, and atomic literals.
-%%
-%% @see data_type/1
-%% @see data_es/1
-%% @see data_arity/1
-
-is_data(#literal{}) ->
- true;
-is_data(#cons{}) ->
- true;
-is_data(#tuple{}) ->
- true;
-is_data(_) ->
- false.
-
-
-%% @spec data_type(Node::cerl()) -> dtype()
-%%
-%% dtype() = cons | tuple | {'atomic', Value}
-%% Value = integer() | float() | atom() | []
-%%
-%% @doc Returns a type descriptor for a data constructor
-%% node. (Cf. <code>is_data/1</code>.) This is mainly useful for
-%% comparing types and for constructing new nodes of the same type
-%% (cf. <code>make_data/2</code>). If <code>Node</code> represents an
-%% integer, floating-point number, atom or empty list, the result is
-%% <code>{'atomic', Value}</code>, where <code>Value</code> is the value
-%% of <code>concrete(Node)</code>, otherwise the result is either
-%% <code>cons</code> or <code>tuple</code>.
-%%
-%% <p>Type descriptors can be compared for equality or order (in the
-%% Erlang term order), but remember that floating-point values should
-%% in general never be tested for equality.</p>
-%%
-%% @see is_data/1
-%% @see make_data/2
-%% @see type/1
-%% @see concrete/1
-
-data_type(#literal{val = V}) ->
- case V of
- [_ | _] ->
- cons;
- _ when tuple(V) ->
- tuple;
- _ ->
- {'atomic', V}
- end;
-data_type(#cons{}) ->
- cons;
-data_type(#tuple{}) ->
- tuple.
-
-
-%% @spec data_es(Node::cerl()) -> [cerl()]
-%%
-%% @doc Returns the list of subtrees of a data constructor node. If
-%% the arity of the constructor is zero, the result is the empty list.
-%%
-%% <p>Note: if <code>data_type(Node)</code> is <code>cons</code>, the
-%% number of subtrees is exactly two. If <code>data_type(Node)</code>
-%% is <code>{'atomic', Value}</code>, the number of subtrees is
-%% zero.</p>
-%%
-%% @see is_data/1
-%% @see data_type/1
-%% @see data_arity/1
-%% @see make_data/2
-
-data_es(#literal{val = V}) ->
- case V of
- [Head | Tail] ->
- [#literal{val = Head}, #literal{val = Tail}];
- _ when tuple(V) ->
- make_lit_list(tuple_to_list(V));
- _ ->
- []
- end;
-data_es(#cons{hd = H, tl = T}) ->
- [H, T];
-data_es(#tuple{es = Es}) ->
- Es.
-
-
-%% @spec data_arity(Node::cerl()) -> integer()
-%%
-%% @doc Returns the number of subtrees of a data constructor
-%% node. This is equivalent to <code>length(data_es(Node))</code>, but
-%% potentially more efficient.
-%%
-%% @see is_data/1
-%% @see data_es/1
-
-data_arity(#literal{val = V}) ->
- case V of
- [_ | _] ->
- 2;
- _ when tuple(V) ->
- size(V);
- _ ->
- 0
- end;
-data_arity(#cons{}) ->
- 2;
-data_arity(#tuple{es = Es}) ->
- length(Es).
-
-
-%% @spec make_data(Type::dtype(), Elements::[cerl()]) -> cerl()
-%%
-%% @doc Creates a data constructor node with the specified type and
-%% subtrees. (Cf. <code>data_type/1</code>.) An exception is thrown
-%% if the length of <code>Elements</code> is invalid for the given
-%% <code>Type</code>; see <code>data_es/1</code> for arity constraints
-%% on constructor types.
-%%
-%% @see data_type/1
-%% @see data_es/1
-%% @see ann_make_data/3
-%% @see update_data/3
-%% @see make_data_skel/2
-
-make_data(CType, Es) ->
- ann_make_data([], CType, Es).
-
-
-%% @spec ann_make_data(As::[term()], Type::dtype(),
-%% Elements::[cerl()]) -> cerl()
-%% @see make_data/2
-
-ann_make_data(As, {'atomic', V}, []) -> #literal{val = V, ann = As};
-ann_make_data(As, cons, [H, T]) -> ann_c_cons(As, H, T);
-ann_make_data(As, tuple, Es) -> ann_c_tuple(As, Es).
-
-
-%% @spec update_data(Old::cerl(), Type::dtype(),
-%% Elements::[cerl()]) -> cerl()
-%% @see make_data/2
-
-update_data(Node, CType, Es) ->
- ann_make_data(get_ann(Node), CType, Es).
-
-
-%% @spec make_data_skel(Type::dtype(), Elements::[cerl()]) -> cerl()
-%%
-%% @doc Like <code>make_data/2</code>, but analogous to
-%% <code>c_tuple_skel/1</code> and <code>c_cons_skel/2</code>.
-%%
-%% @see ann_make_data_skel/3
-%% @see update_data_skel/3
-%% @see make_data/2
-%% @see c_tuple_skel/1
-%% @see c_cons_skel/2
-
-make_data_skel(CType, Es) ->
- ann_make_data_skel([], CType, Es).
-
-
-%% @spec ann_make_data_skel(As::[term()], Type::dtype(),
-%% Elements::[cerl()]) -> cerl()
-%% @see make_data_skel/2
-
-ann_make_data_skel(As, {'atomic', V}, []) -> #literal{val = V, ann = As};
-ann_make_data_skel(As, cons, [H, T]) -> ann_c_cons_skel(As, H, T);
-ann_make_data_skel(As, tuple, Es) -> ann_c_tuple_skel(As, Es).
-
-
-%% @spec update_data_skel(Old::cerl(), Type::dtype(),
-%% Elements::[cerl()]) -> cerl()
-%% @see make_data_skel/2
-
-update_data_skel(Node, CType, Es) ->
- ann_make_data_skel(get_ann(Node), CType, Es).
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec subtrees(Node::cerl()) -> [[cerl()]]
-%%
-%% @doc Returns the grouped list of all subtrees of a node. If
-%% <code>Node</code> is a leaf node (cf. <code>is_leaf/1</code>), this
-%% is the empty list, otherwise the result is always a nonempty list,
-%% containing the lists of subtrees of <code>Node</code>, in
-%% left-to-right order as they occur in the printed program text, and
-%% grouped by category. Often, each group contains only a single
-%% subtree.
-%%
-%% <p>Depending on the type of <code>Node</code>, the size of some
-%% groups may be variable (e.g., the group consisting of all the
-%% elements of a tuple), while others always contain the same number
-%% of elements - usually exactly one (e.g., the group containing the
-%% argument expression of a case-expression). Note, however, that the
-%% exact structure of the returned list (for a given node type) should
-%% in general not be depended upon, since it might be subject to
-%% change without notice.</p>
-%%
-%% <p>The function <code>subtrees/1</code> and the constructor functions
-%% <code>make_tree/2</code> and <code>update_tree/2</code> can be a
-%% great help if one wants to traverse a syntax tree, visiting all its
-%% subtrees, but treat nodes of the tree in a uniform way in most or all
-%% cases. Using these functions makes this simple, and also assures that
-%% your code is not overly sensitive to extensions of the syntax tree
-%% data type, because any node types not explicitly handled by your code
-%% can be left to a default case.</p>
-%%
-%% <p>For example:
-%% <pre>
-%% postorder(F, Tree) ->
-%% F(case subtrees(Tree) of
-%% [] -> Tree;
-%% List -> update_tree(Tree,
-%% [[postorder(F, Subtree)
-%% || Subtree &lt;- Group]
-%% || Group &lt;- List])
-%% end).
-%% </pre>
-%% maps the function <code>F</code> on <code>Tree</code> and all its
-%% subtrees, doing a post-order traversal of the syntax tree. (Note
-%% the use of <code>update_tree/2</code> to preserve annotations.) For
-%% a simple function like:
-%% <pre>
-%% f(Node) ->
-%% case type(Node) of
-%% atom -> atom("a_" ++ atom_name(Node));
-%% _ -> Node
-%% end.
-%% </pre>
-%% the call <code>postorder(fun f/1, Tree)</code> will yield a new
-%% representation of <code>Tree</code> in which all atom names have
-%% been extended with the prefix "a_", but nothing else (including
-%% annotations) has been changed.</p>
-%%
-%% @see is_leaf/1
-%% @see make_tree/2
-%% @see update_tree/2
-
-subtrees(T) ->
- case is_leaf(T) of
- true ->
- [];
- false ->
- case type(T) of
- values ->
- [values_es(T)];
- binary ->
- [binary_segments(T)];
- bitstr ->
- [[bitstr_val(T)], [bitstr_size(T)],
- [bitstr_unit(T)], [bitstr_type(T)],
- [bitstr_flags(T)]];
- cons ->
- [[cons_hd(T)], [cons_tl(T)]];
- tuple ->
- [tuple_es(T)];
- 'let' ->
- [let_vars(T), [let_arg(T)], [let_body(T)]];
- seq ->
- [[seq_arg(T)], [seq_body(T)]];
- apply ->
- [[apply_op(T)], apply_args(T)];
- call ->
- [[call_module(T)], [call_name(T)],
- call_args(T)];
- primop ->
- [[primop_name(T)], primop_args(T)];
- 'case' ->
- [[case_arg(T)], case_clauses(T)];
- clause ->
- [clause_pats(T), [clause_guard(T)],
- [clause_body(T)]];
- alias ->
- [[alias_var(T)], [alias_pat(T)]];
- 'fun' ->
- [fun_vars(T), [fun_body(T)]];
- 'receive' ->
- [receive_clauses(T), [receive_timeout(T)],
- [receive_action(T)]];
- 'try' ->
- [[try_arg(T)], try_vars(T), [try_body(T)],
- try_evars(T), [try_handler(T)]];
- 'catch' ->
- [[catch_body(T)]];
- letrec ->
- Es = unfold_tuples(letrec_defs(T)),
- [Es, [letrec_body(T)]];
- module ->
- As = unfold_tuples(module_attrs(T)),
- Es = unfold_tuples(module_defs(T)),
- [[module_name(T)], module_exports(T), As, Es]
- end
- end.
-
-
-%% @spec update_tree(Old::cerl(), Groups::[[cerl()]]) -> cerl()
-%%
-%% @doc Creates a syntax tree with the given subtrees, and the same
-%% type and annotations as the <code>Old</code> node. This is
-%% equivalent to <code>ann_make_tree(get_ann(Node), type(Node),
-%% Groups)</code>, but potentially more efficient.
-%%
-%% @see update_tree/3
-%% @see ann_make_tree/3
-%% @see get_ann/1
-%% @see type/1
-
-update_tree(Node, Gs) ->
- ann_make_tree(get_ann(Node), type(Node), Gs).
-
-
-%% @spec update_tree(Old::cerl(), Type::atom(), Groups::[[cerl()]]) ->
-%% cerl()
-%%
-%% @doc Creates a syntax tree with the given type and subtrees, and
-%% the same annotations as the <code>Old</code> node. This is
-%% equivalent to <code>ann_make_tree(get_ann(Node), Type,
-%% Groups)</code>, but potentially more efficient.
-%%
-%% @see update_tree/2
-%% @see ann_make_tree/3
-%% @see get_ann/1
-
-update_tree(Node, Type, Gs) ->
- ann_make_tree(get_ann(Node), Type, Gs).
-
-
-%% @spec make_tree(Type::atom(), Groups::[[cerl()]]) -> cerl()
-%%
-%% @doc Creates a syntax tree with the given type and subtrees.
-%% <code>Type</code> must be a node type name
-%% (cf. <code>type/1</code>) that does not denote a leaf node type
-%% (cf. <code>is_leaf/1</code>). <code>Groups</code> must be a
-%% <em>nonempty</em> list of groups of syntax trees, representing the
-%% subtrees of a node of the given type, in left-to-right order as
-%% they would occur in the printed program text, grouped by category
-%% as done by <code>subtrees/1</code>.
-%%
-%% <p>The result of <code>ann_make_tree(get_ann(Node), type(Node),
-%% subtrees(Node))</code> (cf. <code>update_tree/2</code>) represents
-%% the same source code text as the original <code>Node</code>,
-%% assuming that <code>subtrees(Node)</code> yields a nonempty
-%% list. However, it does not necessarily have the exact same data
-%% representation as <code>Node</code>.</p>
-%%
-%% @see ann_make_tree/3
-%% @see type/1
-%% @see is_leaf/1
-%% @see subtrees/1
-%% @see update_tree/2
-
-make_tree(Type, Gs) ->
- ann_make_tree([], Type, Gs).
-
-
-%% @spec ann_make_tree(As::[term()], Type::atom(),
-%% Groups::[[cerl()]]) -> cerl()
-%%
-%% @doc Creates a syntax tree with the given annotations, type and
-%% subtrees. See <code>make_tree/2</code> for details.
-%%
-%% @see make_tree/2
-
-ann_make_tree(As, values, [Es]) -> ann_c_values(As, Es);
-ann_make_tree(As, binary, [Ss]) -> ann_c_binary(As, Ss);
-ann_make_tree(As, bitstr, [[V],[S],[U],[T],[Fs]]) ->
- ann_c_bitstr(As, V, S, U, T, Fs);
-ann_make_tree(As, cons, [[H], [T]]) -> ann_c_cons(As, H, T);
-ann_make_tree(As, tuple, [Es]) -> ann_c_tuple(As, Es);
-ann_make_tree(As, 'let', [Vs, [A], [B]]) -> ann_c_let(As, Vs, A, B);
-ann_make_tree(As, seq, [[A], [B]]) -> ann_c_seq(As, A, B);
-ann_make_tree(As, apply, [[Op], Es]) -> ann_c_apply(As, Op, Es);
-ann_make_tree(As, call, [[M], [N], Es]) -> ann_c_call(As, M, N, Es);
-ann_make_tree(As, primop, [[N], Es]) -> ann_c_primop(As, N, Es);
-ann_make_tree(As, 'case', [[A], Cs]) -> ann_c_case(As, A, Cs);
-ann_make_tree(As, clause, [Ps, [G], [B]]) -> ann_c_clause(As, Ps, G, B);
-ann_make_tree(As, alias, [[V], [P]]) -> ann_c_alias(As, V, P);
-ann_make_tree(As, 'fun', [Vs, [B]]) -> ann_c_fun(As, Vs, B);
-ann_make_tree(As, 'receive', [Cs, [T], [A]]) ->
- ann_c_receive(As, Cs, T, A);
-ann_make_tree(As, 'try', [[E], Vs, [B], Evs, [H]]) ->
- ann_c_try(As, E, Vs, B, Evs, H);
-ann_make_tree(As, 'catch', [[B]]) -> ann_c_catch(As, B);
-ann_make_tree(As, letrec, [Es, [B]]) ->
- ann_c_letrec(As, fold_tuples(Es), B);
-ann_make_tree(As, module, [[N], Xs, Es, Ds]) ->
- ann_c_module(As, N, Xs, fold_tuples(Es), fold_tuples(Ds)).
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec meta(Tree::cerl()) -> cerl()
-%%
-%% @doc Creates a meta-representation of a syntax tree. The result
-%% represents an Erlang expression "<code><em>MetaTree</em></code>"
-%% which, if evaluated, will yield a new syntax tree representing the
-%% same source code text as <code>Tree</code> (although the actual
-%% data representation may be different). The expression represented
-%% by <code>MetaTree</code> is <em>implementation independent</em>
-%% with regard to the data structures used by the abstract syntax tree
-%% implementation.
-%%
-%% <p>Any node in <code>Tree</code> whose node type is
-%% <code>var</code> (cf. <code>type/1</code>), and whose list of
-%% annotations (cf. <code>get_ann/1</code>) contains the atom
-%% <code>meta_var</code>, will remain unchanged in the resulting tree,
-%% except that exactly one occurrence of <code>meta_var</code> is
-%% removed from its annotation list.</p>
-%%
-%% <p>The main use of the function <code>meta/1</code> is to transform
-%% a data structure <code>Tree</code>, which represents a piece of
-%% program code, into a form that is <em>representation independent
-%% when printed</em>. E.g., suppose <code>Tree</code> represents a
-%% variable named "V". Then (assuming a function <code>print/1</code>
-%% for printing syntax trees), evaluating
-%% <code>print(abstract(Tree))</code> - simply using
-%% <code>abstract/1</code> to map the actual data structure onto a
-%% syntax tree representation - would output a string that might look
-%% something like "<code>{var, ..., 'V'}</code>", which is obviously
-%% dependent on the implementation of the abstract syntax trees. This
-%% could e.g. be useful for caching a syntax tree in a file. However,
-%% in some situations like in a program generator generator (with two
-%% "generator"), it may be unacceptable. Using
-%% <code>print(meta(Tree))</code> instead would output a
-%% <em>representation independent</em> syntax tree generating
-%% expression; in the above case, something like
-%% "<code>cerl:c_var('V')</code>".</p>
-%%
-%% <p>The implementation tries to generate compact code with respect
-%% to literals and lists.</p>
-%%
-%% @see abstract/1
-%% @see type/1
-%% @see get_ann/1
-
-meta(Node) ->
- %% First of all we check for metavariables:
- case type(Node) of
- var ->
- case lists:member(meta_var, get_ann(Node)) of
- false ->
- meta_0(var, Node);
- true ->
- %% A meta-variable: remove the first found
- %% 'meta_var' annotation, but otherwise leave
- %% the node unchanged.
- set_ann(Node, lists:delete(meta_var, get_ann(Node)))
- end;
- Type ->
- meta_0(Type, Node)
- end.
-
-meta_0(Type, Node) ->
- case get_ann(Node) of
- [] ->
- meta_1(Type, Node);
- As ->
- meta_call(set_ann, [meta_1(Type, Node), abstract(As)])
- end.
-
-meta_1(literal, Node) ->
- %% We handle atomic literals separately, to get a bit
- %% more compact code. For the rest, we use 'abstract'.
- case concrete(Node) of
- V when atom(V) ->
- meta_call(c_atom, [Node]);
- V when integer(V) ->
- meta_call(c_int, [Node]);
- V when float(V) ->
- meta_call(c_float, [Node]);
- [] ->
- meta_call(c_nil, []);
- _ ->
- meta_call(abstract, [Node])
- end;
-meta_1(var, Node) ->
- %% A normal variable or function name.
- meta_call(c_var, [abstract(var_name(Node))]);
-meta_1(values, Node) ->
- meta_call(c_values,
- [make_list(meta_list(values_es(Node)))]);
-meta_1(binary, Node) ->
- meta_call(c_binary,
- [make_list(meta_list(binary_segments(Node)))]);
-meta_1(bitstr, Node) ->
- meta_call(c_bitstr,
- [meta(bitstr_val(Node)),
- meta(bitstr_size(Node)),
- meta(bitstr_unit(Node)),
- meta(bitstr_type(Node)),
- meta(bitstr_flags(Node))]);
-meta_1(cons, Node) ->
- %% The list is split up if some sublist has annotatations. If
- %% we get exactly one element, we generate a 'c_cons' call
- %% instead of 'make_list' to reconstruct the node.
- case split_list(Node) of
- {[H], none} ->
- meta_call(c_cons, [meta(H), meta(c_nil())]);
- {[H], Node1} ->
- meta_call(c_cons, [meta(H), meta(Node1)]);
- {L, none} ->
- meta_call(make_list, [make_list(meta_list(L))]);
- {L, Node1} ->
- meta_call(make_list,
- [make_list(meta_list(L)), meta(Node1)])
- end;
-meta_1(tuple, Node) ->
- meta_call(c_tuple,
- [make_list(meta_list(tuple_es(Node)))]);
-meta_1('let', Node) ->
- meta_call(c_let,
- [make_list(meta_list(let_vars(Node))),
- meta(let_arg(Node)), meta(let_body(Node))]);
-meta_1(seq, Node) ->
- meta_call(c_seq,
- [meta(seq_arg(Node)), meta(seq_body(Node))]);
-meta_1(apply, Node) ->
- meta_call(c_apply,
- [meta(apply_op(Node)),
- make_list(meta_list(apply_args(Node)))]);
-meta_1(call, Node) ->
- meta_call(c_call,
- [meta(call_module(Node)), meta(call_name(Node)),
- make_list(meta_list(call_args(Node)))]);
-meta_1(primop, Node) ->
- meta_call(c_primop,
- [meta(primop_name(Node)),
- make_list(meta_list(primop_args(Node)))]);
-meta_1('case', Node) ->
- meta_call(c_case,
- [meta(case_arg(Node)),
- make_list(meta_list(case_clauses(Node)))]);
-meta_1(clause, Node) ->
- meta_call(c_clause,
- [make_list(meta_list(clause_pats(Node))),
- meta(clause_guard(Node)),
- meta(clause_body(Node))]);
-meta_1(alias, Node) ->
- meta_call(c_alias,
- [meta(alias_var(Node)), meta(alias_pat(Node))]);
-meta_1('fun', Node) ->
- meta_call(c_fun,
- [make_list(meta_list(fun_vars(Node))),
- meta(fun_body(Node))]);
-meta_1('receive', Node) ->
- meta_call(c_receive,
- [make_list(meta_list(receive_clauses(Node))),
- meta(receive_timeout(Node)),
- meta(receive_action(Node))]);
-meta_1('try', Node) ->
- meta_call(c_try,
- [meta(try_arg(Node)),
- make_list(meta_list(try_vars(Node))),
- meta(try_body(Node)),
- make_list(meta_list(try_evars(Node))),
- meta(try_handler(Node))]);
-meta_1('catch', Node) ->
- meta_call(c_catch, [meta(catch_body(Node))]);
-meta_1(letrec, Node) ->
- meta_call(c_letrec,
- [make_list([c_tuple([meta(N), meta(F)])
- || {N, F} <- letrec_defs(Node)]),
- meta(letrec_body(Node))]);
-meta_1(module, Node) ->
- meta_call(c_module,
- [meta(module_name(Node)),
- make_list(meta_list(module_exports(Node))),
- make_list([c_tuple([meta(A), meta(V)])
- || {A, V} <- module_attrs(Node)]),
- make_list([c_tuple([meta(N), meta(F)])
- || {N, F} <- module_defs(Node)])]).
-
-meta_call(F, As) ->
- c_call(c_atom(?MODULE), c_atom(F), As).
-
-meta_list([T | Ts]) ->
- [meta(T) | meta_list(Ts)];
-meta_list([]) ->
- [].
-
-split_list(Node) ->
- split_list(set_ann(Node, []), []).
-
-split_list(Node, L) ->
- A = get_ann(Node),
- case type(Node) of
- cons when A == [] ->
- split_list(cons_tl(Node), [cons_hd(Node) | L]);
- nil when A == [] ->
- {lists:reverse(L), none};
- _ ->
- {lists:reverse(L), Node}
- end.
-
-
-%% ---------------------------------------------------------------------
-
-%% General utilities
-
-is_lit_list([#literal{} | Es]) ->
- is_lit_list(Es);
-is_lit_list([_ | _]) ->
- false;
-is_lit_list([]) ->
- true.
-
-lit_list_vals([#literal{val = V} | Es]) ->
- [V | lit_list_vals(Es)];
-lit_list_vals([]) ->
- [].
-
-make_lit_list([V | Vs]) ->
- [#literal{val = V} | make_lit_list(Vs)];
-make_lit_list([]) ->
- [].
-
-%% The following tests are the same as done by 'io_lib:char_list' and
-%% 'io_lib:printable_list', respectively, but for a single character.
-
-is_char_value(V) when V >= $\000, V =< $\377 -> true;
-is_char_value(_) -> false.
-
-is_print_char_value(V) when V >= $\040, V =< $\176 -> true;
-is_print_char_value(V) when V >= $\240, V =< $\377 -> true;
-is_print_char_value(V) when V =:= $\b -> true;
-is_print_char_value(V) when V =:= $\d -> true;
-is_print_char_value(V) when V =:= $\e -> true;
-is_print_char_value(V) when V =:= $\f -> true;
-is_print_char_value(V) when V =:= $\n -> true;
-is_print_char_value(V) when V =:= $\r -> true;
-is_print_char_value(V) when V =:= $\s -> true;
-is_print_char_value(V) when V =:= $\t -> true;
-is_print_char_value(V) when V =:= $\v -> true;
-is_print_char_value(V) when V =:= $\" -> true;
-is_print_char_value(V) when V =:= $\' -> true;
-is_print_char_value(V) when V =:= $\\ -> true;
-is_print_char_value(_) -> false.
-
-is_char_list([V | Vs]) when integer(V) ->
- case is_char_value(V) of
- true ->
- is_char_list(Vs);
- false ->
- false
- end;
-is_char_list([]) ->
- true;
-is_char_list(_) ->
- false.
-
-is_print_char_list([V | Vs]) when integer(V) ->
- case is_print_char_value(V) of
- true ->
- is_print_char_list(Vs);
- false ->
- false
- end;
-is_print_char_list([]) ->
- true;
-is_print_char_list(_) ->
- false.
-
-unfold_tuples([{X, Y} | Ps]) ->
- [X, Y | unfold_tuples(Ps)];
-unfold_tuples([]) ->
- [].
-
-fold_tuples([X, Y | Es]) ->
- [{X, Y} | fold_tuples(Es)];
-fold_tuples([]) ->
- [].
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/cerl_clauses.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/cerl_clauses.erl
deleted file mode 100644
index f207178f13..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/cerl_clauses.erl
+++ /dev/null
@@ -1,409 +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 Richard Carlsson.
-%% Copyright (C) 1999-2002 Richard Carlsson.
-%% Portions created by Ericsson are Copyright 2001, Ericsson Utvecklings
-%% AB. All Rights Reserved.''
-%%
-%% $Id: cerl_clauses.erl,v 1.2 2009/09/17 09:46:19 kostis Exp $
-
-%% @doc Utility functions for Core Erlang case/receive clauses.
-%%
-%% <p>Syntax trees are defined in the module <a
-%% href=""><code>cerl</code></a>.</p>
-%%
-%% @type cerl() = cerl:cerl()
-
--module(cerl_clauses).
-
--export([any_catchall/1, eval_guard/1, is_catchall/1, match/2,
- match_list/2, reduce/1, reduce/2]).
-
--import(cerl, [alias_pat/1, alias_var/1, data_arity/1, data_es/1,
- data_type/1, clause_guard/1, clause_pats/1, concrete/1,
- is_data/1, is_c_var/1, let_body/1, letrec_body/1,
- seq_body/1, try_arg/1, type/1, values_es/1]).
-
--import(lists, [reverse/1]).
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec is_catchall(Clause::cerl()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if an abstract clause is a
-%% catch-all, otherwise <code>false</code>. A clause is a catch-all if
-%% all its patterns are variables, and its guard expression always
-%% evaluates to <code>true</code>; cf. <code>eval_guard/1</code>.
-%%
-%% <p>Note: <code>Clause</code> must have type
-%% <code>clause</code>.</p>
-%%
-%% @see eval_guard/1
-%% @see any_catchall/1
-
-is_catchall(C) ->
- case all_vars(clause_pats(C)) of
- true ->
- case eval_guard(clause_guard(C)) of
- {value, true} ->
- true;
- _ ->
- false
- end;
- false ->
- false
- end.
-
-all_vars([C | Cs]) ->
- case is_c_var(C) of
- true ->
- all_vars(Cs);
- false ->
- false
- end;
-all_vars([]) ->
- true.
-
-
-%% @spec any_catchall(Clauses::[cerl()]) -> boolean()
-%%
-%% @doc Returns <code>true</code> if any of the abstract clauses in
-%% the list is a catch-all, otherwise <code>false</code>. See
-%% <code>is_catchall/1</code> for details.
-%%
-%% <p>Note: each node in <code>Clauses</code> must have type
-%% <code>clause</code>.</p>
-%%
-%% @see is_catchall/1
-
-any_catchall([C | Cs]) ->
- case is_catchall(C) of
- true ->
- true;
- false ->
- any_catchall(Cs)
- end;
-any_catchall([]) ->
- false.
-
-
-%% @spec eval_guard(Expr::cerl()) -> none | {value, term()}
-%%
-%% @doc Tries to reduce a guard expression to a single constant value,
-%% if possible. The returned value is <code>{value, Term}</code> if the
-%% guard expression <code>Expr</code> always yields the constant value
-%% <code>Term</code>, and is otherwise <code>none</code>.
-%%
-%% <p>Note that although guard expressions should only yield boolean
-%% values, this function does not guarantee that <code>Term</code> is
-%% either <code>true</code> or <code>false</code>. Also note that only
-%% simple constructs like let-expressions are examined recursively;
-%% general constant folding is not performed.</p>
-%%
-%% @see is_catchall/1
-
-%% This function could possibly be improved further, but constant
-%% folding should in general be performed elsewhere.
-
-eval_guard(E) ->
- case type(E) of
- literal ->
- {value, concrete(E)};
- values ->
- case values_es(E) of
- [E1] ->
- eval_guard(E1);
- _ ->
- none
- end;
- 'try' ->
- eval_guard(try_arg(E));
- seq ->
- eval_guard(seq_body(E));
- 'let' ->
- eval_guard(let_body(E));
- 'letrec' ->
- eval_guard(letrec_body(E));
- _ ->
- none
- end.
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec reduce(Clauses) -> {true, {Clauses, Bindings}}
-%% | {false, Clauses}
-%%
-%% @equiv reduce(Cs, [])
-
-reduce(Cs) ->
- reduce(Cs, []).
-
-%% @spec reduce(Clauses::[Clause], Exprs::[Expr]) ->
-%% {true, {Clause, Bindings}}
-%% | {false, [Clause]}
-%%
-%% Clause = cerl()
-%% Expr = any | cerl()
-%% Bindings = [{cerl(), cerl()}]
-%%
-%% @doc Selects a single clause, if possible, or otherwise reduces the
-%% list of selectable clauses. The input is a list <code>Clauses</code>
-%% of abstract clauses (i.e., syntax trees of type <code>clause</code>),
-%% and a list of switch expressions <code>Exprs</code>. The function
-%% tries to uniquely select a single clause or discard unselectable
-%% clauses, with respect to the switch expressions. All abstract clauses
-%% in the list must have the same number of patterns. If
-%% <code>Exprs</code> is not the empty list, it must have the same
-%% length as the number of patterns in each clause; see
-%% <code>match_list/2</code> for details.
-%%
-%% <p>A clause can only be selected if its guard expression always
-%% yields the atom <code>true</code>, and a clause whose guard
-%% expression always yields the atom <code>false</code> can never be
-%% selected. Other guard expressions are considered to have unknown
-%% value; cf. <code>eval_guard/1</code>.</p>
-%%
-%% <p>If a particular clause can be selected, the function returns
-%% <code>{true, {Clause, Bindings}}</code>, where <code>Clause</code> is
-%% the selected clause and <code>Bindings</code> is a list of pairs
-%% <code>{Var, SubExpr}</code> associating the variables occurring in
-%% the patterns of <code>Clause</code> with the corresponding
-%% subexpressions in <code>Exprs</code>. The list of bindings is given
-%% in innermost-first order; see the <code>match/2</code> function for
-%% details.</p>
-%%
-%% <p>If no clause could be definitely selected, the function returns
-%% <code>{false, NewClauses}</code>, where <code>NewClauses</code> is
-%% the list of entries in <code>Clauses</code> that remain after
-%% eliminating unselectable clauses, preserving the relative order.</p>
-%%
-%% @see eval_guard/1
-%% @see match/2
-%% @see match_list/2
-
-reduce(Cs, Es) ->
- reduce(Cs, Es, []).
-
-reduce([C | Cs], Es, Cs1) ->
- Ps = clause_pats(C),
- case match_list(Ps, Es) of
- none ->
- %% Here, we know that the current clause cannot possibly be
- %% selected, so we drop it and visit the rest.
- reduce(Cs, Es, Cs1);
- {false, _} ->
- %% We are not sure if this clause might be selected, so we
- %% save it and visit the rest.
- reduce(Cs, Es, [C | Cs1]);
- {true, Bs} ->
- case eval_guard(clause_guard(C)) of
- {value, true} when Cs1 == [] ->
- %% We have a definite match - we return the residual
- %% expression and signal that a selection has been
- %% made. All other clauses are dropped.
- {true, {C, Bs}};
- {value, true} ->
- %% Unless one of the previous clauses is selected,
- %% this clause will definitely be, so we can drop
- %% the rest.
- {false, reverse([C | Cs1])};
- {value, false} ->
- %% This clause can never be selected, since its
- %% guard is never 'true', so we drop it.
- reduce(Cs, Es, Cs1);
- _ ->
- %% We are not sure if this clause might be selected
- %% (or might even cause a crash), so we save it and
- %% visit the rest.
- reduce(Cs, Es, [C | Cs1])
- end
- end;
-reduce([], _, Cs) ->
- %% All clauses visited, without a complete match. Signal "not
- %% reduced" and return the saved clauses, in the correct order.
- {false, reverse(Cs)}.
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec match(Pattern::cerl(), Expr) ->
-%% none | {true, Bindings} | {false, Bindings}
-%%
-%% Expr = any | cerl()
-%% Bindings = [{cerl(), Expr}]
-%%
-%% @doc Matches a pattern against an expression. The returned value is
-%% <code>none</code> if a match is impossible, <code>{true,
-%% Bindings}</code> if <code>Pattern</code> definitely matches
-%% <code>Expr</code>, and <code>{false, Bindings}</code> if a match is
-%% not definite, but cannot be excluded. <code>Bindings</code> is then
-%% a list of pairs <code>{Var, SubExpr}</code>, associating each
-%% variable in the pattern with either the corresponding subexpression
-%% of <code>Expr</code>, or with the atom <code>any</code> if no
-%% matching subexpression exists. (Recall that variables may not be
-%% repeated in a Core Erlang pattern.) The list of bindings is given
-%% in innermost-first order; this should only be of interest if
-%% <code>Pattern</code> contains one or more alias patterns. If the
-%% returned value is <code>{true, []}</code>, it implies that the
-%% pattern and the expression are syntactically identical.
-%%
-%% <p>Instead of a syntax tree, the atom <code>any</code> can be
-%% passed for <code>Expr</code> (or, more generally, be used for any
-%% subtree of <code>Expr</code>, in as much the abstract syntax tree
-%% implementation allows it); this means that it cannot be decided
-%% whether the pattern will match or not, and the corresponding
-%% variable bindings will all map to <code>any</code>. The typical use
-%% is for producing bindings for <code>receive</code> clauses.</p>
-%%
-%% <p>Note: Binary-syntax patterns are never structurally matched
-%% against binary-syntax expressions by this function.</p>
-%%
-%% <p>Examples:
-%% <ul>
-%% <li>Matching a pattern "<code>{X, Y}</code>" against the
-%% expression "<code>{foo, f(Z)}</code>" yields <code>{true,
-%% Bindings}</code> where <code>Bindings</code> associates
-%% "<code>X</code>" with the subtree "<code>foo</code>" and
-%% "<code>Y</code>" with the subtree "<code>f(Z)</code>".</li>
-%%
-%% <li>Matching pattern "<code>{X, {bar, Y}}</code>" against
-%% expression "<code>{foo, f(Z)}</code>" yields <code>{false,
-%% Bindings}</code> where <code>Bindings</code> associates
-%% "<code>X</code>" with the subtree "<code>foo</code>" and
-%% "<code>Y</code>" with <code>any</code> (because it is not known
-%% if "<code>{foo, Y}</code>" might match the run-time value of
-%% "<code>f(Z)</code>" or not).</li>
-%%
-%% <li>Matching pattern "<code>{foo, bar}</code>" against expression
-%% "<code>{foo, f()}</code>" yields <code>{false, []}</code>,
-%% telling us that there might be a match, but we cannot deduce any
-%% bindings.</li>
-%%
-%% <li>Matching <code>{foo, X = {bar, Y}}</code> against expression
-%% "<code>{foo, {bar, baz}}</code>" yields <code>{true,
-%% Bindings}</code> where <code>Bindings</code> associates
-%% "<code>Y</code>" with "<code>baz</code>", and "<code>X</code>"
-%% with "<code>{bar, baz}</code>".</li>
-%%
-%% <li>Matching a pattern "<code>{X, Y}</code>" against
-%% <code>any</code> yields <code>{false, Bindings}</code> where
-%% <code>Bindings</code> associates both "<code>X</code>" and
-%% "<code>Y</code>" with <code>any</code>.</li>
-%% </ul></p>
-
-match(P, E) ->
- match(P, E, []).
-
-match(P, E, Bs) ->
- case type(P) of
- var ->
- %% Variables always match, since they cannot have repeated
- %% occurrences in a pattern.
- {true, [{P, E} | Bs]};
- alias ->
- %% All variables in P1 will be listed before the alias
- %% variable in the result.
- match(alias_pat(P), E, [{alias_var(P), E} | Bs]);
- binary ->
- %% The most we can do is to say "definitely no match" if a
- %% binary pattern is matched against non-binary data.
- if E == any ->
- {false, Bs};
- true ->
- case is_data(E) of
- true ->
- none;
- false ->
- {false, Bs}
- end
- end;
- _ ->
- match_1(P, E, Bs)
- end.
-
-match_1(P, E, Bs) ->
- case is_data(P) of
- true when E == any ->
- %% If we don't know the structure of the value of E at this
- %% point, we just match the subpatterns against 'any', and
- %% make sure the result is a "maybe".
- Ps = data_es(P),
- Es = lists:duplicate(length(Ps), any),
- case match_list(Ps, Es, Bs) of
- {_, Bs1} ->
- {false, Bs1};
- none ->
- none
- end;
- true ->
- %% Test if the expression represents a constructor
- case is_data(E) of
- true ->
- T1 = {data_type(E), data_arity(E)},
- T2 = {data_type(P), data_arity(P)},
- %% Note that we must test for exact equality.
- if T1 =:= T2 ->
- match_list(data_es(P), data_es(E), Bs);
- true ->
- none
- end;
- false ->
- %% We don't know the run-time structure of E, and P
- %% is not a variable or an alias pattern, so we
- %% match against 'any' instead.
- match_1(P, any, Bs)
- end;
- false ->
- %% Strange pattern - give up, but don't say "no match".
- {false, Bs}
- end.
-
-
-%% @spec match_list(Patterns::[cerl()], Exprs::[Expr]) ->
-%% none | {true, Bindings} | {false, Bindings}
-%%
-%% Expr = any | cerl()
-%% Bindings = [{cerl(), cerl()}]
-%%
-%% @doc Like <code>match/2</code>, but matching a sequence of patterns
-%% against a sequence of expressions. Passing an empty list for
-%% <code>Exprs</code> is equivalent to passing a list of
-%% <code>any</code> atoms of the same length as <code>Patterns</code>.
-%%
-%% @see match/2
-
-match_list([], []) ->
- {true, []}; % no patterns always match
-match_list(Ps, []) ->
- match_list(Ps, lists:duplicate(length(Ps), any), []);
-match_list(Ps, Es) ->
- match_list(Ps, Es, []).
-
-match_list([P | Ps], [E | Es], Bs) ->
- case match(P, E, Bs) of
- {true, Bs1} ->
- match_list(Ps, Es, Bs1);
- {false, Bs1} ->
- %% Make sure "maybe" is preserved
- case match_list(Ps, Es, Bs1) of
- {_, Bs2} ->
- {false, Bs2};
- none ->
- none
- end;
- none ->
- none
- end;
-match_list([], [], Bs) ->
- {true, Bs}.
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/cerl_inline.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/cerl_inline.erl
deleted file mode 100644
index e040904a19..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/cerl_inline.erl
+++ /dev/null
@@ -1,2762 +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 Richard Carlsson.
-%% Copyright (C) 1999-2002 Richard Carlsson.
-%% Portions created by Ericsson are Copyright 2001, Ericsson Utvecklings
-%% AB. All Rights Reserved.''
-%%
-%% $Id: cerl_inline.erl,v 1.1 2008/12/17 09:53:41 mikpe Exp $
-%%
-%% Core Erlang inliner.
-
-%% =====================================================================
-%%
-%% This is an implementation of the algorithm by Waddell and Dybvig
-%% ("Fast and Effective Procedure Inlining", International Static
-%% Analysis Symposium 1997), adapted to the Core Erlang language.
-%%
-%% Instead of always renaming variables and function variables, this
-%% implementation uses the "no-shadowing strategy" of Peyton Jones and
-%% Marlow ("Secrets of the Glasgow Haskell Compiler Inliner", 1999).
-%%
-%% =====================================================================
-
-%% TODO: inline single-source-reference operands without size limit.
-
--module(cerl_inline).
-
--export([core_transform/2, transform/1, transform/2]).
-
--import(cerl, [abstract/1, alias_pat/1, alias_var/1, apply_args/1,
- apply_op/1, atom_name/1, atom_val/1, bitstr_val/1,
- bitstr_size/1, bitstr_unit/1, bitstr_type/1,
- bitstr_flags/1, binary_segments/1, update_c_alias/3,
- update_c_apply/3, update_c_binary/2, update_c_bitstr/6,
- update_c_call/4, update_c_case/3, update_c_catch/2,
- update_c_clause/4, c_fun/2, c_int/1, c_let/3,
- update_c_let/4, update_c_letrec/3, update_c_module/5,
- update_c_primop/3, update_c_receive/4, update_c_seq/3,
- c_seq/2, update_c_try/6, c_tuple/1, update_c_values/2,
- c_values/1, c_var/1, call_args/1, call_module/1,
- call_name/1, case_arity/1, case_arg/1, case_clauses/1,
- catch_body/1, clause_body/1, clause_guard/1,
- clause_pats/1, clause_vars/1, concrete/1, cons_hd/1,
- cons_tl/1, data_arity/1, data_es/1, data_type/1,
- fun_body/1, fun_vars/1, get_ann/1, int_val/1,
- is_c_atom/1, is_c_cons/1, is_c_fun/1, is_c_int/1,
- is_c_list/1, is_c_seq/1, is_c_tuple/1, is_c_var/1,
- is_data/1, is_literal/1, is_literal_term/1, let_arg/1,
- let_body/1, let_vars/1, letrec_body/1, letrec_defs/1,
- list_length/1, list_elements/1, update_data/3,
- make_list/1, make_data_skel/2, module_attrs/1,
- module_defs/1, module_exports/1, module_name/1,
- primop_args/1, primop_name/1, receive_action/1,
- receive_clauses/1, receive_timeout/1, seq_arg/1,
- seq_body/1, set_ann/2, try_arg/1, try_body/1, try_vars/1,
- try_evars/1, try_handler/1, tuple_es/1, tuple_arity/1,
- type/1, values_es/1, var_name/1]).
-
--import(lists, [foldl/3, foldr/3, mapfoldl/3, reverse/1]).
-
-%%
-%% Constants
-%%
-
-debug_runtime() -> false.
-debug_counters() -> false.
-
-%% Normal execution times for inlining are between 0.1 and 0.3 seconds
-%% (on the author's current equipment). The default effort limit of 150
-%% is high enough that most normal programs never hit the limit even
-%% once, and for difficult programs, it generally keeps the execution
-%% times below 2-5 seconds. Using an effort counter of 1000 will thus
-%% have no further effect on most programs, but some programs may take
-%% as much as 10 seconds or more. Effort counts larger than 2500 have
-%% never been observed even on very ill-conditioned programs.
-%%
-%% Size limits between 6 and 18 tend to actually shrink the code,
-%% because of the simplifications made possible by inlining. A limit of
-%% 16 seems to be optimal for this purpose, often shrinking the
-%% executable code by up to 10%. Size limits between 18 and 30 generally
-%% give the same code size as if no inlining was done (i.e., code
-%% duplication balances out the simplifications at these levels). A size
-%% limit between 1 and 5 tends to inline small functions and propagate
-%% constants, but does not cause much simplifications do be done, so the
-%% net effect will be a slight increase in code size. For size limits
-%% above 30, the executable code size tends to increase with about 10%
-%% per 100 units, with some variations depending on the sizes of
-%% functions in the source code.
-%%
-%% Typically, about 90% of the maximum speedup achievable is already
-%% reached using a size limit of 30, and 98% is reached at limits around
-%% 100-150; there is rarely any point in letting the code size increase
-%% by more than 10-15%. If too large functions are inlined, cache
-%% effects will slow the program down.
-
-default_effort() -> 150.
-default_size() -> 24.
-
-%% Base costs/weights for different kinds of expressions. If these are
-%% modified, the size limits above may have to be adjusted.
-
-weight(var) -> 0; % We count no cost for variable accesses.
-weight(values) -> 0; % Value aggregates have no cost in themselves.
-weight(literal) -> 1; % We assume efficient handling of constants.
-weight(data) -> 1; % Base cost; add 1 per element.
-weight(element) -> 1; % Cost of storing/fetching an element.
-weight(argument) -> 1; % Cost of passing a function argument.
-weight('fun') -> 6; % Base cost + average number of free vars.
-weight('let') -> 0; % Count no cost for let-bindings.
-weight(letrec) -> 0; % Like a let-binding.
-weight('case') -> 0; % Case switches have no base cost.
-weight(clause) -> 1; % Count one jump at the end of each clause body.
-weight('receive') -> 9; % Initialization/cleanup cost.
-weight('try') -> 1; % Assume efficient implementation.
-weight('catch') -> 1; % See `try'.
-weight(apply) -> 3; % Average base cost: call/return.
-weight(call) -> 3; % Assume remote-calls as efficient as `apply'.
-weight(primop) -> 2; % Assume more efficient than `apply'.
-weight(binary) -> 4; % Initialisation base cost.
-weight(bitstr) -> 3; % Coding/decoding a value; like a primop.
-weight(module) -> 1. % Like a letrec with a constant body
-
-%% These "reference" structures are used for variables and function
-%% variables. They keep track of the variable name, any bound operand,
-%% and the associated store location.
-
--record(ref, {name, opnd, loc}).
-
-%% Operand structures contain the operand expression, the renaming and
-%% environment, the state location, and the effort counter at the call
-%% site (cf. `visit').
-
--record(opnd, {expr, ren, env, loc, effort}).
-
-%% Since expressions are only visited in `effect' context when they are
-%% not bound to a referenced variable, only expressions visited in
-%% 'value' context are cached.
-
--record(cache, {expr, size}).
-
-%% The context flags for an application structure are kept separate from
-%% the structure itself. Note that the original algorithm had exactly
-%% one operand in each application context structure, while we can have
-%% several, or none.
-
--record(app, {opnds, ctxt, loc}).
-
-
-%%
-%% Interface functions
-%%
-
-%% Use compile option `{core_transform, inline}' to insert this as a
-%% compilation pass.
-
-core_transform(Code, Opts) ->
- cerl:to_records(transform(cerl:from_records(Code), Opts)).
-
-transform(Tree) ->
- transform(Tree, []).
-
-transform(Tree, Opts) ->
- main(Tree, value, Opts).
-
-main(Tree, Ctxt, Opts) ->
- %% We spawn a new process to do the work, so we don't have to worry
- %% about cluttering the process dictionary with debugging info, or
- %% proper deallocation of ets-tables.
- Opts1 = Opts ++ [{inline_size, default_size()},
- {inline_effort, default_effort()}],
- Reply = self(),
- Pid = spawn_link(fun () -> start(Reply, Tree, Ctxt, Opts1) end),
- receive
- {Pid1, Tree1} when Pid1 == Pid ->
- Tree1
- end.
-
-start(Reply, Tree, Ctxt, Opts) ->
- init_debug(),
- case debug_runtime() of
- true ->
- put(inline_start_time,
- element(1, erlang:statistics(runtime)));
- _ ->
- ok
- end,
- Size = max(1, proplists:get_value(inline_size, Opts)),
- Effort = max(1, proplists:get_value(inline_effort, Opts)),
- case proplists:get_bool(verbose, Opts) of
- true ->
- io:fwrite("Inlining: inline_size=~w inline_effort=~w\n",
- [Size, Effort]);
- false ->
- ok
- end,
-
- %% Note that the counters of the new state are passive.
- S = st__new(Effort, Size),
-
-%%% Initialization is not needed at present. Note that the code in
-%%% `inline_init' is not up-to-date with this module.
-%%% {Tree1, S1} = inline_init:init(Tree, S),
-%%% {Tree2, _S2} = i(Tree1, Ctxt, S1),
- {Tree2, _S2} = i(Tree, Ctxt, S),
- report_debug(),
- Reply ! {self(), Tree2}.
-
-init_debug() ->
- case debug_counters() of
- true ->
- put(counter_effort_triggers, 0),
- put(counter_effort_max, 0),
- put(counter_size_triggers, 0),
- put(counter_size_max, 0);
- _ ->
- ok
- end.
-
-report_debug() ->
- case debug_runtime() of
- true ->
- {Time, _} = erlang:statistics(runtime),
- report("Total run time for inlining: ~.2.0f s.\n",
- [(Time - get(inline_start_time))/1000]);
- _ ->
- ok
- end,
- case debug_counters() of
- true ->
- counter_stats();
- _ ->
- ok
- end.
-
-counter_stats() ->
- T1 = get(counter_effort_triggers),
- T2 = get(counter_size_triggers),
- E = get(counter_effort_max),
- S = get(counter_size_max),
- M1 = io_lib:fwrite("\tNumber of triggered "
- "effort counters: ~p.\n", [T1]),
- M2 = io_lib:fwrite("\tNumber of triggered "
- "size counters: ~p.\n", [T2]),
- M3 = io_lib:fwrite("\tLargest active effort counter: ~p.\n",
- [E]),
- M4 = io_lib:fwrite("\tLargest active size counter: ~p.\n",
- [S]),
- report("Counter statistics:\n~s", [[M1, M2, M3, M4]]).
-
-
-%% =====================================================================
-%% The main inlining function
-%%
-%% i(E :: coreErlang(),
-%% Ctxt :: value | effect | #app{}
-%% Ren :: renaming(),
-%% Env :: environment(),
-%% S :: state())
-%% -> {E', S'}
-%%
-%% Note: It is expected that the input source code ('E') does not
-%% contain free variables. If it does, there is a risk of accidental
-%% name capture, in case a generated "new" variable name happens to be
-%% the same as the name of a variable that is free further below in the
-%% tree; the algorithm only consults the current environment to check if
-%% a name already exists.
-%%
-%% The renaming maps names of source-code variable and function
-%% variables to new names as necessary to avoid clashes, according to
-%% the "no-shadowing" strategy. The environment maps *residual-code*
-%% variables and function variables to operands and global information.
-%% Separating the renaming from the environment, and using the
-%% residual-code variables instead of the source-code variables as its
-%% domain, improves the behaviour of the algorithm when code needs to be
-%% traversed more than once.
-%%
-%% Note that there is no such thing as a `test' context for expressions
-%% in (Core) Erlang (see `i_case' below for details).
-
-i(E, Ctxt, S) ->
- i(E, Ctxt, ren__identity(), env__empty(), S).
-
-i(E, Ctxt, Ren, Env, S0) ->
- %% Count one unit of effort on each pass.
- S = count_effort(1, S0),
- case is_data(E) of
- true ->
- i_data(E, Ctxt, Ren, Env, S);
- false ->
- case type(E) of
- var ->
- i_var(E, Ctxt, Ren, Env, S);
- values ->
- i_values(E, Ctxt, Ren, Env, S);
- 'fun' ->
- i_fun(E, Ctxt, Ren, Env, S);
- seq ->
- i_seq(E, Ctxt, Ren, Env, S);
- 'let' ->
- i_let(E, Ctxt, Ren, Env, S);
- letrec ->
- i_letrec(E, Ctxt, Ren, Env, S);
- 'case' ->
- i_case(E, Ctxt, Ren, Env, S);
- 'receive' ->
- i_receive(E, Ctxt, Ren, Env, S);
- apply ->
- i_apply(E, Ctxt, Ren, Env, S);
- call ->
- i_call(E, Ctxt, Ren, Env, S);
- primop ->
- i_primop(E, Ren, Env, S);
- 'try' ->
- i_try(E, Ctxt, Ren, Env, S);
- 'catch' ->
- i_catch(E, Ctxt, Ren, Env, S);
- binary ->
- i_binary(E, Ren, Env, S);
- module ->
- i_module(E, Ctxt, Ren, Env, S)
- end
- end.
-
-i_data(E, Ctxt, Ren, Env, S) ->
- case is_literal(E) of
- true ->
- %% This is the `(const c)' case of the original algorithm:
- %% literal terms which (regardless of size) do not need to
- %% be constructed dynamically at runtime - boldly assuming
- %% that the compiler/runtime system can handle this.
- case Ctxt of
- effect ->
- %% Reduce useless constants to a simple value.
- {void(), count_size(weight(literal), S)};
- _ ->
- %% (In Erlang, we cannot set all non-`false'
- %% constants to `true' in a `test' context, like we
- %% could do in Lisp or C, so the above is the only
- %% special case to be handled here.)
- {E, count_size(weight(literal), S)}
- end;
- false ->
- %% Data constructors are like to calls to safe built-in
- %% functions, for which we can "decide to inline"
- %% immediately; there is no need to create operand
- %% structures. In `effect' context, we can simply make a
- %% sequence of the argument expressions, also visited in
- %% `effect' context. In all other cases, the arguments are
- %% visited for value.
- case Ctxt of
- effect ->
- %% Note that this will count the sizes of the
- %% subexpressions, even though some or all of them
- %% might be discarded by the sequencing afterwards.
- {Es1, S1} = mapfoldl(fun (E, S) ->
- i(E, effect, Ren, Env,
- S)
- end,
- S, data_es(E)),
- E1 = foldl(fun (E1, E2) -> make_seq(E1, E2) end,
- void(), Es1),
- {E1, S1};
- _ ->
- {Es1, S1} = mapfoldl(fun (E, S) ->
- i(E, value, Ren, Env,
- S)
- end,
- S, data_es(E)),
- %% The total size/cost is the base cost for a data
- %% constructor plus the cost for storing each
- %% element.
- N = weight(data) + length(Es1) * weight(element),
- S2 = count_size(N, S1),
- {update_data(E, data_type(E), Es1), S2}
- end
- end.
-
-%% This is the `(ref x)' (variable use) case of the original algorithm.
-%% Note that binding occurrences are always handled in the respective
-%% cases of the binding constructs.
-
-i_var(E, Ctxt, Ren, Env, S) ->
- case Ctxt of
- effect ->
- %% Reduce useless variable references to a simple constant.
- %% This also avoids useless visiting of bound operands.
- {void(), count_size(weight(literal), S)};
- _ ->
- Name = var_name(E),
- case env__lookup(ren__map(Name, Ren), Env) of
- {ok, R} ->
- case R#ref.opnd of
- undefined ->
- %% The variable is not associated with an
- %% argument expression; just residualize it.
- residualize_var(R, S);
- Opnd ->
- i_var_1(R, Opnd, Ctxt, Env, S)
- end;
- error ->
- %% The variable is unbound. (It has not been
- %% accidentally captured, however, or it would have
- %% been in the environment.) We leave it as it is,
- %% without any warning.
- {E, count_size(weight(var), S)}
- end
- end.
-
-%% This first visits the bound operand and then does copy propagation.
-%% Note that we must first set the "inner-pending" flag, and clear the
-%% flag afterwards.
-
-i_var_1(R, Opnd, Ctxt, Env, S) ->
- %% If the operand is already "inner-pending", it is residualised.
- %% (In Lisp/C, if the variable might be assigned to, it should also
- %% be residualised.)
- L = Opnd#opnd.loc,
- case st__test_inner_pending(L, S) of
- true ->
- residualize_var(R, S);
- false ->
- S1 = st__mark_inner_pending(L, S),
- case catch {ok, visit(Opnd, S1)} of
- {ok, {E, S2}} ->
- %% Note that we pass the current environment and
- %% context to `copy', but not the current renaming.
- S3 = st__clear_inner_pending(L, S2),
- copy(R, Opnd, E, Ctxt, Env, S3);
- {'EXIT', X} ->
- exit(X);
- X ->
- %% If we use destructive update for the
- %% `inner-pending' flag, we must make sure to clear
- %% it also if we make a nonlocal return.
- st__clear_inner_pending(Opnd#opnd.loc, S1),
- throw(X)
- end
- end.
-
-%% A multiple-value aggregate `<e1, ..., en>'. This is very much like a
-%% tuple data constructor `{e1, ..., en}'; cf. `i_data' for details.
-
-i_values(E, Ctxt, Ren, Env, S) ->
- case values_es(E) of
- [E1] ->
- %% Single-value aggregates can be dropped; they are simply
- %% notation.
- i(E1, Ctxt, Ren, Env, S);
- Es ->
- %% In `effect' context, we can simply make a sequence of the
- %% argument expressions, also visited in `effect' context.
- %% In all other cases, the arguments are visited for value.
- case Ctxt of
- effect ->
- {Es1, S1} =
- mapfoldl(fun (E, S) ->
- i(E, effect, Ren, Env, S)
- end,
- S, Es),
- E1 = foldl(fun (E1, E2) ->
- make_seq(E1, E2)
- end,
- void(), Es1),
- {E1, S1}; % drop annotations on E
- _ ->
- {Es1, S1} = mapfoldl(fun (E, S) ->
- i(E, value, Ren, Env,
- S)
- end,
- S, Es),
- %% Aggregating values does not write them to memory,
- %% so we count no extra cost per element.
- S2 = count_size(weight(values), S1),
- {update_c_values(E, Es1), S2}
- end
- end.
-
-%% A let-expression `let <v1,...,vn> = e0 in e1' is semantically
-%% equivalent to a case-expression `case e0 of <v1,...,vn> when 'true'
-%% -> e1 end'. As a special case, `let <v> = e0 in e1' is also
-%% equivalent to `apply fun (v) -> e0 (e1)'. However, for efficiency,
-%% and in order to allow the handling of `case' clauses to introduce new
-%% let-expressions without entering an infinite rewrite loop, we handle
-%% these directly.
-
-%%% %% Rewriting a `let' to an equivalent expression.
-%%% i_let(E, Ctxt, Ren, Env, S) ->
-%%% case let_vars(E) of
-%%% [V] ->
-%%% E1 = update_c_apply(E, c_fun([V], let_body(E)), [let_arg(E)]),
-%%% i(E1, Ctxt, Ren, Env, S);
-%%% Vs ->
-%%% C = c_clause(Vs, abstract(true), let_body(E)),
-%%% E1 = update_c_case(E, let_arg(E), [C]),
-%%% i(E1, Ctxt, Ren, Env, S)
-%%% end.
-
-i_let(E, Ctxt, Ren, Env, S) ->
- case let_vars(E) of
- [V] ->
- i_let_1(V, E, Ctxt, Ren, Env, S);
- Vs ->
- %% Visit the argument expression in `value' context, to
- %% simplify it as far as possible.
- {A, S1} = i(let_arg(E), value, Ren, Env, S),
- case get_components(length(Vs), result(A)) of
- {true, As} ->
- %% Note that only the components of the result of
- %% `A' are passed on; any effects are hoisted.
- {E1, S2} = i_let_2(Vs, As, E, Ctxt, Ren, Env, S1),
- {hoist_effects(A, E1), S2};
- false ->
- %% We cannot do anything with this `let', since the
- %% variables cannot be matched against the argument
- %% components. Just visit the variables for renaming
- %% and visit the body for value (cf. `i_fun').
- {_, Ren1, Env1, S2} = bind_locals(Vs, Ren, Env, S1),
- Vs1 = i_params(Vs, Ren1, Env1),
- %% The body is always visited for value here.
- {B, S3} = i(let_body(E), value, Ren1, Env1, S2),
- S4 = count_size(weight('let'), S3),
- {update_c_let(E, Vs1, A, B), S4}
- end
- end.
-
-%% Single-variable `let' binding.
-
-i_let_1(V, E, Ctxt, Ren, Env, S) ->
- %% Make an operand structure for the argument expression, create a
- %% local binding from the parameter to the operand structure, and
- %% visit the body. Finally create necessary bindings and/or set
- %% flags.
- {Opnd, S1} = make_opnd(let_arg(E), Ren, Env, S),
- {[R], Ren1, Env1, S2} = bind_locals([V], [Opnd], Ren, Env, S1),
- {E1, S3} = i(let_body(E), Ctxt, Ren1, Env1, S2),
- i_let_3([R], [Opnd], E1, S3).
-
-%% Multi-variable `let' binding.
-
-i_let_2(Vs, As, E, Ctxt, Ren, Env, S) ->
- %% Make operand structures for the argument components. Note that
- %% since the argument has already been visited at this point, we use
- %% the identity renaming for the operands.
- {Opnds, S1} = mapfoldl(fun (E, S) ->
- make_opnd(E, ren__identity(), Env, S)
- end,
- S, As),
- %% Create local bindings from the parameters to their respective
- %% operand structures, and visit the body.
- {Rs, Ren1, Env1, S2} = bind_locals(Vs, Opnds, Ren, Env, S1),
- {E1, S3} = i(let_body(E), Ctxt, Ren1, Env1, S2),
- i_let_3(Rs, Opnds, E1, S3).
-
-i_let_3(Rs, Opnds, E, S) ->
- %% Create necessary bindings and/or set flags.
- {E1, S1} = make_let_bindings(Rs, E, S),
-
- %% We must also create evaluation for effect, for any unused
- %% operands, as after an application expression.
- residualize_operands(Opnds, E1, S1).
-
-%% A sequence `do e1 e2', written `(seq e1 e2)' in the original
-%% algorithm, where `e1' is evaluated for effect only (since its value
-%% is not used), and `e2' yields the final value. Note that we use
-%% `make_seq' to recompose the sequence after visiting the parts.
-
-i_seq(E, Ctxt, Ren, Env, S) ->
- {E1, S1} = i(seq_arg(E), effect, Ren, Env, S),
- {E2, S2} = i(seq_body(E), Ctxt, Ren, Env, S1),
- %% A sequence has no cost in itself.
- {make_seq(E1, E2), S2}.
-
-
-%% The `case' switch of Core Erlang is rather different from the boolean
-%% `(if e1 e2 e3)' case of the original algorithm, but the central idea
-%% is the same: if, given the simplified switch expression (which is
-%% visited in `value' context - a boolean `test' context would not be
-%% generally useful), there is a clause which could definitely be
-%% selected, such that no clause before it can possibly be selected,
-%% then we can eliminate all other clauses. (And even if this is not the
-%% case, some clauses can often be eliminated.) Furthermore, if a clause
-%% can be selected, we can replace the case-expression (including the
-%% switch expression) with the body of the clause and a set of zero or
-%% more let-bindings of subexpressions of the switch expression. (In the
-%% simplest case, the switch expression is evaluated only for effect.)
-
-i_case(E, Ctxt, Ren, Env, S) ->
- %% First visit the switch expression in `value' context, to simplify
- %% it as far as possible. Note that only the result part is passed
- %% on to the clause matching below; any effects are hoisted.
- {A, S1} = i(case_arg(E), value, Ren, Env, S),
- A1 = result(A),
-
- %% Propagating an application context into the branches could cause
- %% the arguments of the application to be evaluated *after* the
- %% switch expression, but *before* the body of the selected clause.
- %% Such interleaving is not allowed in general, and it does not seem
- %% worthwile to make a more powerful transformation here. Therefore,
- %% the clause bodies are conservatively visited for value if the
- %% context is `application'.
- Ctxt1 = safe_context(Ctxt),
- {E1, S2} = case get_components(case_arity(E), A1) of
- {true, As} ->
- i_case_1(As, E, Ctxt1, Ren, Env, S1);
- false ->
- i_case_1([], E, Ctxt1, Ren, Env, S1)
- end,
- {hoist_effects(A, E1), S2}.
-
-i_case_1(As, E, Ctxt, Ren, Env, S) ->
- case i_clauses(As, case_clauses(E), Ctxt, Ren, Env, S) of
- {false, {As1, Vs, Env1, Cs}, S1} ->
- %% We still have a list of clauses. Sanity check:
- if Cs == [] ->
- report_warning("empty list of clauses "
- "in residual program!.\n");
- true ->
- ok
- end,
- {A, S2} = i(c_values(As1), value, ren__identity(), Env1,
- S1),
- {E1, S3} = i_case_2(Cs, A, E, S2),
- i_case_3(Vs, Env1, E1, S3);
- {true, {_, Vs, Env1, [C]}, S1} ->
- %% A single clause was selected; we just take the body.
- i_case_3(Vs, Env1, clause_body(C), S1)
- end.
-
-%% Check if all clause bodies are actually equivalent expressions that
-%% do not depent on pattern variables (this sometimes occurs as a
-%% consequence of inlining, e.g., all branches might yield 'true'), and
-%% if so, replace the `case' with a sequence, first evaluating the
-%% clause selection for effect, then evaluating one of the clause bodies
-%% for its value. (Unless the switch contains a catch-all clause, the
-%% clause selection must be evaluated for effect, since there is no
-%% guarantee that any of the clauses will actually match. Assuming that
-%% some clause always matches could make an undefined program produce a
-%% value.) This makes the final size less than what was accounted for
-%% when visiting the clauses, but currently we don't try to adjust for
-%% this.
-
-i_case_2(Cs, A, E, S) ->
- case equivalent_clauses(Cs) of
- false ->
- %% Count the base sizes for the remaining clauses; pattern
- %% and guard sizes are already counted.
- N = weight('case') + weight(clause) * length(Cs),
- S1 = count_size(N, S),
- {update_c_case(E, A, Cs), S1};
- true ->
- case cerl_clauses:any_catchall(Cs) of
- true ->
- %% We know that some clause must be selected, so we
- %% can drop all the testing as well.
- E1 = make_seq(A, clause_body(hd(Cs))),
- {E1, S};
- false ->
- %% The clause selection must be performed for
- %% effect.
- E1 = update_c_case(E, A,
- set_clause_bodies(Cs, void())),
- {make_seq(E1, clause_body(hd(Cs))), S}
- end
- end.
-
-i_case_3(Vs, Env, E, S) ->
- %% For the variables bound to the switch expression subexpressions,
- %% make let bindings or create evaluation for effect.
- Rs = [env__get(var_name(V), Env) || V <- Vs],
- {E1, S1} = make_let_bindings(Rs, E, S),
- Opnds = [R#ref.opnd || R <- Rs],
- residualize_operands(Opnds, E1, S1).
-
-%% This function takes a sequence of switch expressions `Es' (which can
-%% be the empty list if these are unknown) and a list `Cs' of clauses,
-%% and returns `{Match, {As, Vs, Env1, Cs1}, S1}' where `As' is a list
-%% of residual switch expressions, `Vs' the list of variables used in
-%% the templates, `Env1' the environment for the templates, and `Cs1'
-%% the list of residual clauses. `Match' is `true' if some clause could
-%% be shown to definitely match (in this case, `Cs1' contains exactly
-%% one element), and `false' otherwise. `S1' is the new state. The given
-%% `Ctxt' is the context to be used for visiting the body of clauses.
-%%
-%% Visiting a clause basically amounts to extending the environment for
-%% all variables in the pattern, as for a `fun' (cf. `i_fun'),
-%% propagating match information if possible, and visiting the guard and
-%% body in the new environment.
-%%
-%% To make it cheaper to do handle a set of clauses, and to avoid
-%% unnecessarily exceeding the size limit, we avoid visiting the bodies
-%% of clauses which are subsequently removed, by dividing the visiting
-%% of a clause into two stages: first construct the environment(s) and
-%% visit the pattern (for renaming) and the guard (for value), then
-%% reduce the switch as much as possible, and lastly visit the body.
-
-i_clauses(Cs, Ctxt, Ren, Env, S) ->
- i_clauses([], Cs, Ctxt, Ren, Env, S).
-
-i_clauses(Es, Cs, Ctxt, Ren, Env, S) ->
- %% Create templates for the switch expressions.
- {Ts, {Vs, Env0}} = mapfoldl(fun (E, {Vs, Env}) ->
- {T, Vs1, Env1} =
- make_template(E, Env),
- {T, {Vs1 ++ Vs, Env1}}
- end,
- {[], Env}, Es),
-
- %% Make operand structures for the switch subexpression templates
- %% (found in `Env0') and add proper ref-structure bindings to the
- %% environment. Since the subexpressions in general can be
- %% interdependent (Vs is in reverse-dependency order), the
- %% environment (and renaming) must be created incrementally. Note
- %% that since the switch expressions have been visited already, the
- %% identity renaming is used for the operands.
- Vs1 = lists:reverse(Vs),
- {Ren1, Env1, S1} =
- foldl(fun (V, {Ren, Env, S}) ->
- E = env__get(var_name(V), Env0),
- {Opnd, S_1} = make_opnd(E, ren__identity(), Env,
- S),
- {_, Ren1, Env1, S_2} = bind_locals([V], [Opnd],
- Ren, Env, S_1),
- {Ren1, Env1, S_2}
- end,
- {Ren, Env, S}, Vs1),
-
- %% First we visit the head of each individual clause, renaming
- %% pattern variables, inserting let-bindings in the guard and body,
- %% and visiting the guard. The information used for visiting the
- %% clause body will be prefixed to the clause annotations.
- {Cs1, S2} = mapfoldl(fun (C, S) ->
- i_clause_head(C, Ts, Ren1, Env1, S)
- end,
- S1, Cs),
-
- %% Now that the clause guards have been reduced as far as possible,
- %% we can attempt to reduce the clauses.
- As = [hd(get_ann(T)) || T <- Ts],
- case cerl_clauses:reduce(Cs1, Ts) of
- {false, Cs2} ->
- %% We still have one or more clauses (with associated
- %% extended environments). Their bodies have not yet been
- %% visited, so we do that (in the respective safe
- %% environments, adding the sizes of the visited heads to
- %% the current size counter) and return the final list of
- %% clauses.
- {Cs3, S3} = mapfoldl(
- fun (C, S) ->
- i_clause_body(C, Ctxt, S)
- end,
- S2, Cs2),
- {false, {As, Vs1, Env1, Cs3}, S3};
- {true, {C, _}} ->
- %% A clause C could be selected (the bindings have already
- %% been added to the guard/body). Note that since the clause
- %% head will probably be discarded, its size is not counted.
- {C1, Ren2, Env2, _} = get_clause_extras(C),
- {B, S3} = i(clause_body(C), Ctxt, Ren2, Env2, S2),
- C2 = update_c_clause(C1, clause_pats(C1), clause_guard(C1), B),
- {true, {As, Vs1, Env1, [C2]}, S3}
- end.
-
-%% This visits the head of a clause, renames pattern variables, inserts
-%% let-bindings in the guard and body, and does inlining on the guard
-%% expression. Returns a list of pairs `{NewClause, Data}', where `Data'
-%% is `{Renaming, Environment, Size}' used for visiting the body of the
-%% new clause.
-
-i_clause_head(C, Ts, Ren, Env, S) ->
- %% Match the templates against the (non-renamed) patterns to get the
- %% available information about matching subexpressions. We don't
- %% care at this point whether an exact match/nomatch is detected.
- Ps = clause_pats(C),
- Bs = case cerl_clauses:match_list(Ps, Ts) of
- {_, Bs1} -> Bs1;
- none -> []
- end,
-
- %% The patterns must be visited for renaming; cf. `i_pattern'. We
- %% use a passive size counter for visiting the patterns and the
- %% guard (cf. `visit'), because we do not know at this stage whether
- %% the clause will be kept or not; the final value of the counter is
- %% included in the returned value below.
- {_, Ren1, Env1, S1} = bind_locals(clause_vars(C), Ren, Env, S),
- S2 = new_passive_size(get_size_limit(S1), S1),
- {Ps1, S3} = mapfoldl(fun (P, S) ->
- i_pattern(P, Ren1, Env1, Ren, Env, S)
- end,
- S2, Ps),
-
- %% Rewrite guard and body and visit the guard for value. Discard the
- %% latter size count if the guard turns out to be a constant.
- G = add_match_bindings(Bs, clause_guard(C)),
- B = add_match_bindings(Bs, clause_body(C)),
- {G1, S4} = i(G, value, Ren1, Env1, S3),
- S5 = case is_literal(G1) of
- true ->
- revert_size(S3, S4);
- false ->
- S4
- end,
-
- %% Revert to the size counter we had on entry to this function. The
- %% environment and renaming, together with the size of the clause
- %% head, are prefixed to the annotations for later use.
- Size = get_size_value(S5),
- C1 = update_c_clause(C, Ps1, G1, B),
- {set_clause_extras(C1, Ren1, Env1, Size), revert_size(S, S5)}.
-
-add_match_bindings(Bs, E) ->
- %% Don't waste time if the variables definitely cannot be used.
- %% (Most guards are simply `true'.)
- case is_literal(E) of
- true ->
- E;
- false ->
- Vs = [V || {V, E} <- Bs, E /= any],
- Es = [hd(get_ann(E)) || {_V, E} <- Bs, E /= any],
- c_let(Vs, c_values(Es), E)
- end.
-
-i_clause_body(C0, Ctxt, S) ->
- {C, Ren, Env, Size} = get_clause_extras(C0),
- S1 = count_size(Size, S),
- {B, S2} = i(clause_body(C), Ctxt, Ren, Env, S1),
- C1 = update_c_clause(C, clause_pats(C), clause_guard(C), B),
- {C1, S2}.
-
-get_clause_extras(C) ->
- [{Ren, Env, Size} | As] = get_ann(C),
- {set_ann(C, As), Ren, Env, Size}.
-
-set_clause_extras(C, Ren, Env, Size) ->
- As = [{Ren, Env, Size} | get_ann(C)],
- set_ann(C, As).
-
-%% This is the `(lambda x e)' case of the original algorithm. A
-%% `fun' is like a lambda expression, but with a varying number of
-%% parameters; possibly zero.
-
-i_fun(E, Ctxt, Ren, Env, S) ->
- case Ctxt of
- effect ->
- %% Reduce useless `fun' expressions to a simple constant;
- %% visiting the body would be a waste of time, and could
- %% needlessly mark variables as referenced.
- {void(), count_size(weight(literal), S)};
- value ->
- %% Note that the variables are visited as patterns.
- Vs = fun_vars(E),
- {_, Ren1, Env1, S1} = bind_locals(Vs, Ren, Env, S),
- Vs1 = i_params(Vs, Ren1, Env1),
-
- %% The body is always visited for value.
- {B, S2} = i(fun_body(E), value, Ren1, Env1, S1),
-
- %% We don't bother to include the exact number of free
- %% variables in the cost for creating a fun-value.
- S3 = count_size(weight('fun'), S2),
-
- %% Inlining might have duplicated code, so we must remove
- %% any 'id'-annotations from the original fun-expression.
- %% (This forces a later stage to invent new id:s.) This is
- %% necessary as long as fun:s may still need to be
- %% identified the old way. Function variables that are not
- %% in application context also have such annotations, but
- %% the inlining will currently lose all annotations on
- %% variable references (I think), so that's not a problem.
- {set_ann(c_fun(Vs1, B), kill_id_anns(get_ann(E))), S3};
- #app{} ->
- %% An application of a fun-expression (in the source code)
- %% is handled by going directly to `inline'; this is never
- %% residualised, and we don't set up new counters here. Note
- %% that inlining of copy-propagated fun-expressions is done
- %% in `copy'; not here.
- inline(E, Ctxt, Ren, Env, S)
- end.
-
-%% A `letrec' requires a circular environment, but is otherwise like a
-%% `let', i.e. like a direct lambda application. Note that only
-%% fun-expressions (lambda abstractions) may occur in the right-hand
-%% side of each definition.
-
-i_letrec(E, Ctxt, Ren, Env, S) ->
- %% Note that we pass an empty list for the auto-referenced
- %% (exported) functions here.
- {Es, B, _, S1} = i_letrec(letrec_defs(E), letrec_body(E), [], Ctxt,
- Ren, Env, S),
-
- %% If no bindings remain, only the body is returned.
- case Es of
- [] ->
- {B, S1}; % drop annotations on E
- _ ->
- S2 = count_size(weight(letrec), S1),
- {update_c_letrec(E, Es, B), S2}
- end.
-
-%% The major part of this is shared by letrec-expressions and module
-%% definitions alike.
-
-i_letrec(Es, B, Xs, Ctxt, Ren, Env, S) ->
- %% First, we create operands with dummy renamings and environments,
- %% and with fresh store locations for cached expressions and operand
- %% info.
- {Opnds, S1} = mapfoldl(fun ({_, E}, S) ->
- make_opnd(E, undefined, undefined, S)
- end,
- S, Es),
-
- %% Then we make recursive bindings for the definitions.
- {Rs, Ren1, Env1, S2} = bind_recursive([F || {F, _} <- Es],
- Opnds, Ren, Env, S1),
-
- %% For the function variables listed in Xs (none for a
- %% letrec-expression), we must make sure that the corresponding
- %% operand expressions are visited and that the definitions are
- %% marked as referenced; we also need to return the possibly renamed
- %% function variables.
- {Xs1, S3} =
- mapfoldl(
- fun (X, S) ->
- Name = ren__map(var_name(X), Ren1),
- case env__lookup(Name, Env1) of
- {ok, R} ->
- S_1 = i_letrec_export(R, S),
- {ref_to_var(R), S_1};
- error ->
- %% We just skip any exports that are not
- %% actually defined here, and generate a
- %% warning message.
- {N, A} = var_name(X),
- report_warning("export `~w'/~w "
- "not defined.\n", [N, A]),
- {X, S}
- end
- end,
- S2, Xs),
-
- %% At last, we can then visit the body.
- {B1, S4} = i(B, Ctxt, Ren1, Env1, S3),
-
- %% Finally, we create new letrec-bindings for any and all
- %% residualised definitions. All referenced functions should have
- %% been visited; the call to `visit' below is expected to retreive a
- %% cached expression.
- Rs1 = keep_referenced(Rs, S4),
- {Es1, S5} = mapfoldl(fun (R, S) ->
- {E_1, S_1} = visit(R#ref.opnd, S),
- {{ref_to_var(R), E_1}, S_1}
- end,
- S4, Rs1),
- {Es1, B1, Xs1, S5}.
-
-%% This visits the operand for a function definition exported by a
-%% `letrec' (which is really a `module' module definition, since normal
-%% letrecs have no export declarations). Only the updated state is
-%% returned. We must handle the "inner-pending" flag when doing this;
-%% cf. `i_var'.
-
-i_letrec_export(R, S) ->
- Opnd = R#ref.opnd,
- S1 = st__mark_inner_pending(Opnd#opnd.loc, S),
- {_, S2} = visit(Opnd, S1),
- {_, S3} = residualize_var(R, st__clear_inner_pending(Opnd#opnd.loc,
- S2)),
- S3.
-
-%% This is the `(call e1 e2)' case of the original algorithm. The only
-%% difference is that we must handle multiple (or no) operand
-%% expressions.
-
-i_apply(E, Ctxt, Ren, Env, S) ->
- {Opnds, S1} = mapfoldl(fun (E, S) ->
- make_opnd(E, Ren, Env, S)
- end,
- S, apply_args(E)),
-
- %% Allocate a new app-context location and set up an application
- %% context structure containing the surrounding context.
- {L, S2} = st__new_app_loc(S1),
- Ctxt1 = #app{opnds = Opnds, ctxt = Ctxt, loc = L},
-
- %% Visit the operator expression in the new call context.
- {E1, S3} = i(apply_op(E), Ctxt1, Ren, Env, S2),
-
- %% Check the "inlined" flag to find out what to do next. (The store
- %% location could be recycled after the flag has been tested, but
- %% there is no real advantage to that, because in practice, only
- %% 4-5% of all created store locations will ever be reused, while
- %% there will be a noticable overhead for managing the free list.)
- case st__get_app_inlined(L, S3) of
- true ->
- %% The application was inlined, so we have the final
- %% expression in `E1'. We just have to handle any operands
- %% that need to be residualized for effect only (i.e., those
- %% the values of which are not used).
- residualize_operands(Opnds, E1, S3);
- false ->
- %% Otherwise, `E1' is the residual operator expression. We
- %% make sure all operands are visited, and rebuild the
- %% application.
- {Es, S4} = mapfoldl(fun (Opnd, S) ->
- visit_and_count_size(Opnd, S)
- end,
- S3, Opnds),
- N = apply_size(length(Es)),
- {update_c_apply(E, E1, Es), count_size(N, S4)}
- end.
-
-apply_size(A) ->
- weight(apply) + weight(argument) * A.
-
-%% Since it is not the task of this transformation to handle
-%% cross-module inlining, all inter-module calls are handled by visiting
-%% the components (the module and function name, and the arguments of
-%% the call) for value. In `effect' context, if the function itself is
-%% known to be completely effect free, the call can be discarded and the
-%% arguments evaluated for effect. Otherwise, if all the visited
-%% arguments are to constants, and the function is known to be safe to
-%% execute at compile time, then we try to evaluate the call. If
-%% evaluation completes normally, the call is replaced by the result;
-%% otherwise the call is residualised.
-
-i_call(E, Ctxt, Ren, Env, S) ->
- {M, S1} = i(call_module(E), value, Ren, Env, S),
- {F, S2} = i(call_name(E), value, Ren, Env, S1),
- As = call_args(E),
- Arity = length(As),
-
- %% Check if the name of the called function is static. If so,
- %% discard the size counts performed above, since the values will
- %% not cause any runtime cost.
- Static = is_c_atom(M) and is_c_atom(F),
- S3 = case Static of
- true ->
- revert_size(S, S2);
- false ->
- S2
- end,
- case Ctxt of
- effect when Static == true ->
- case is_safe_call(atom_val(M), atom_val(F), Arity) of
- true ->
- %% The result will not be used, and the call is
- %% effect free, so we create a multiple-value
- %% aggregate containing the (not yet visited)
- %% arguments and process that instead.
- i(c_values(As), effect, Ren, Env, S3);
- false ->
- %% We are not allowed to simply discard the call,
- %% but we can try to evaluate it.
- i_call_1(Static, M, F, Arity, As, E, Ctxt, Ren, Env,
- S3)
- end;
- _ ->
- i_call_1(Static, M, F, Arity, As, E, Ctxt, Ren, Env, S3)
- end.
-
-i_call_1(Static, M, F, Arity, As, E, Ctxt, Ren, Env, S) ->
- %% Visit the arguments for value.
- {As1, S1} = mapfoldl(fun (X, A) -> i(X, value, Ren, Env, A) end,
- S, As),
- case Static of
- true ->
- case erl_bifs:is_pure(atom_val(M), atom_val(F), Arity) of
- true ->
- %% It is allowed to evaluate this at compile time.
- case all_static(As1) of
- true ->
- i_call_3(M, F, As1, E, Ctxt, Env, S1);
- false ->
- %% See if the call can be rewritten instead.
- i_call_4(M, F, As1, E, Ctxt, Env, S1)
- end;
- false ->
- i_call_2(M, F, As1, E, S1)
- end;
- false ->
- i_call_2(M, F, As1, E, S1)
- end.
-
-%% Residualise the call.
-
-i_call_2(M, F, As, E, S) ->
- N = weight(call) + weight(argument) * length(As),
- {update_c_call(E, M, F, As), count_size(N, S)}.
-
-%% Attempt to evaluate the call to yield a literal; if that fails, try
-%% to rewrite the expression.
-
-i_call_3(M, F, As, E, Ctxt, Env, S) ->
- %% Note that we extract the results of argument expessions here; the
- %% expressions could still be sequences with side effects.
- Vs = [concrete(result(A)) || A <- As],
- case catch {ok, apply(atom_val(M), atom_val(F), Vs)} of
- {ok, V} ->
- %% Evaluation completed normally - try to turn the result
- %% back into a syntax tree (representing a literal).
- case is_literal_term(V) of
- true ->
- %% Make a sequence of the arguments (as a
- %% multiple-value aggregate) and the final value.
- S1 = count_size(weight(values), S),
- S2 = count_size(weight(literal), S1),
- {make_seq(c_values(As), abstract(V)), S2};
- false ->
- %% The result could not be represented as a literal.
- i_call_4(M, F, As, E, Ctxt, Env, S)
- end;
- _ ->
- %% The evaluation attempt did not complete normally.
- i_call_4(M, F, As, E, Ctxt, Env, S)
- end.
-
-%% Rewrite the expression, if possible, otherwise residualise it.
-
-i_call_4(M, F, As, E, Ctxt, Env, S) ->
- case reduce_bif_call(atom_val(M), atom_val(F), As, Env) of
- false ->
- %% Nothing more to be done - residualise the call.
- i_call_2(M, F, As, E, S);
- {true, E1} ->
- %% We revisit the result, because the rewriting might have
- %% opened possibilities for further inlining. Since the
- %% parts have already been visited once, we use the identity
- %% renaming here.
- i(E1, Ctxt, ren__identity(), Env, S)
- end.
-
-%% For now, we assume that primops cannot be evaluated at compile time,
-%% probably being too special. Also, we have no knowledge about their
-%% side effects.
-
-i_primop(E, Ren, Env, S) ->
- %% Visit the arguments for value.
- {As, S1} = mapfoldl(fun (E, S) ->
- i(E, value, Ren, Env, S)
- end,
- S, primop_args(E)),
- N = weight(primop) + weight(argument) * length(As),
- {update_c_primop(E, primop_name(E), As), count_size(N, S1)}.
-
-%% This is like having an expression with an extra fun-expression
-%% attached for "exceptional cases"; actually, there are exactly two
-%% parameter variables for the body, but they are easiest handled as if
-%% their number might vary, just as for a `fun'.
-
-i_try(E, Ctxt, Ren, Env, S) ->
- %% The argument expression is evaluated in `value' context, and the
- %% surrounding context is propagated into both branches. We do not
- %% try to recognize cases when the protected expression will
- %% actually raise an exception. Note that the variables are visited
- %% as patterns.
- {A, S1} = i(try_arg(E), value, Ren, Env, S),
- Vs = try_vars(E),
- {_, Ren1, Env1, S2} = bind_locals(Vs, Ren, Env, S1),
- Vs1 = i_params(Vs, Ren1, Env1),
- {B, S3} = i(try_body(E), Ctxt, Ren1, Env1, S2),
- case is_safe(A) of
- true ->
- %% The `try' wrapper can be dropped in this case. Since the
- %% expressions have been visited already, the identity
- %% renaming is used when we revisit the new let-expression.
- i(c_let(Vs1, A, B), Ctxt, ren__identity(), Env, S3);
- false ->
- Evs = try_evars(E),
- {_, Ren2, Env2, S4} = bind_locals(Evs, Ren, Env, S3),
- Evs1 = i_params(Evs, Ren2, Env2),
- {H, S5} = i(try_handler(E), Ctxt, Ren2, Env2, S4),
- S6 = count_size(weight('try'), S5),
- {update_c_try(E, A, Vs1, B, Evs1, H), S6}
- end.
-
-%% A special case of try-expressions:
-
-i_catch(E, Ctxt, Ren, Env, S) ->
- %% We cannot propagate application contexts into the catch.
- {E1, S1} = i(catch_body(E), safe_context(Ctxt), Ren, Env, S),
- case is_safe(E1) of
- true ->
- %% The `catch' wrapper can be dropped in this case.
- {E1, S1};
- false ->
- S2 = count_size(weight('catch'), S1),
- {update_c_catch(E, E1), S2}
- end.
-
-%% A receive-expression is very much like a case-expression, with the
-%% difference that we do not have access to a switch expression, since
-%% the value being switched on is taken from the mailbox. The fact that
-%% the receive-expression may iterate over an arbitrary number of
-%% messages is not of interest to us. All we can do here is to visit its
-%% subexpressions, and possibly eliminate definitely unselectable
-%% clauses.
-
-i_receive(E, Ctxt, Ren, Env, S) ->
- %% We first visit the expiry expression (for value) and the expiry
- %% body (in the surrounding context).
- {T, S1} = i(receive_timeout(E), value, Ren, Env, S),
- {B, S2} = i(receive_action(E), Ctxt, Ren, Env, S1),
-
- %% Then we visit the clauses. Note that application contexts may not
- %% in general be propagated into the branches (and the expiry body),
- %% because the execution of the `receive' may remove a message from
- %% the mailbox as a side effect; the situation is thus analogous to
- %% that in a `case' expression.
- Ctxt1 = safe_context(Ctxt),
- case i_clauses(receive_clauses(E), Ctxt1, Ren, Env, S2) of
- {false, {[], _, _, Cs}, S3} ->
- %% We still have a list of clauses. If the list is empty,
- %% and the expiry expression is the integer zero, the
- %% expression reduces to the expiry body.
- if Cs == [] ->
- case is_c_int(T) andalso (int_val(T) == 0) of
- true ->
- {B, S3};
- false ->
- i_receive_1(E, Cs, T, B, S3)
- end;
- true ->
- i_receive_1(E, Cs, T, B, S3)
- end;
- {true, {_, _, _, Cs}, S3} ->
- %% Cs is a single clause that will always be matched (if a
- %% message exists), but we must keep the `receive' statement
- %% in order to fetch the message from the mailbox.
- i_receive_1(E, Cs, T, B, S3)
- end.
-
-i_receive_1(E, Cs, T, B, S) ->
- %% Here, we just add the base sizes for the receive-expression
- %% itself and for each remaining clause; cf. `case'.
- N = weight('receive') + weight(clause) * length(Cs),
- {update_c_receive(E, Cs, T, B), count_size(N, S)}.
-
-%% A module definition is like a `letrec', with some add-ons (export and
-%% attribute declarations) but without an explicit body. Actually, the
-%% exporting of function names has the same effect as if there was a
-%% body consisting of the list of references to the exported functions.
-%% Thus, the exported functions are exactly those which can be
-%% referenced from outside the module.
-
-i_module(E, Ctxt, Ren, Env, S) ->
- %% Cf. `i_letrec'. Note that we pass a dummy constant value for the
- %% "body" parameter.
- {Es, _, Xs1, S1} = i_letrec(module_defs(E), void(),
- module_exports(E), Ctxt, Ren, Env, S),
- %% Sanity check:
- case Es of
- [] ->
- report_warning("no function definitions remaining "
- "in module `~s'.\n",
- [atom_name(module_name(E))]);
- _ ->
- ok
- end,
- E1 = update_c_module(E, module_name(E), Xs1, module_attrs(E), Es),
- {E1, count_size(weight(module), S1)}.
-
-%% Binary-syntax expressions are too complicated to do anything
-%% interesting with here - that is beyond the scope of this program;
-%% also, their construction could have side effects, so even in effect
-%% context we can't remove them. (We don't bother to identify cases of
-%% "safe" unused binaries which could be removed.)
-
-i_binary(E, Ren, Env, S) ->
- %% Visit the segments for value.
- {Es, S1} = mapfoldl(fun (E, S) ->
- i_bitstr(E, Ren, Env, S)
- end,
- S, binary_segments(E)),
- S2 = count_size(weight(binary), S1),
- {update_c_binary(E, Es), S2}.
-
-i_bitstr(E, Ren, Env, S) ->
- %% It is not necessary to visit the Unit, Type and Flags fields,
- %% since these are always literals.
- {Val, S1} = i(bitstr_val(E), value, Ren, Env, S),
- {Size, S2} = i(bitstr_size(E), value, Ren, Env, S1),
- Unit = bitstr_unit(E),
- Type = bitstr_type(E),
- Flags = bitstr_flags(E),
- S3 = count_size(weight(bitstr), S2),
- {update_c_bitstr(E, Val, Size, Unit, Type, Flags), S3}.
-
-%% This is a simplified version of `i_pattern', for lists of parameter
-%% variables only. It does not modify the state.
-
-i_params([V | Vs], Ren, Env) ->
- Name = ren__map(var_name(V), Ren),
- case env__lookup(Name, Env) of
- {ok, R} ->
- [ref_to_var(R) | i_params(Vs, Ren, Env)];
- error ->
- report_internal_error("variable `~w' not bound "
- "in pattern.\n", [Name]),
- exit(error)
- end;
-i_params([], _, _) ->
- [].
-
-%% For ordinary patterns, we just visit to rename variables and count
-%% the size/cost. All occurring binding instances of variables should
-%% already have been added to the renaming and environment; however, to
-%% handle the size expressions of binary-syntax patterns, we must pass
-%% the renaming and environment of the containing expression
-
-i_pattern(E, Ren, Env, Ren0, Env0, S) ->
- case type(E) of
- var ->
- %% Count no size.
- Name = ren__map(var_name(E), Ren),
- case env__lookup(Name, Env) of
- {ok, R} ->
- {ref_to_var(R), S};
- error ->
- report_internal_error("variable `~w' not bound "
- "in pattern.\n", [Name]),
- exit(error)
- end;
- alias ->
- %% Count no size.
- V = alias_var(E),
- Name = ren__map(var_name(V), Ren),
- case env__lookup(Name, Env) of
- {ok, R} ->
- %% Visit the subpattern and recompose.
- V1 = ref_to_var(R),
- {P, S1} = i_pattern(alias_pat(E), Ren, Env, Ren0,
- Env0, S),
- {update_c_alias(E, V1, P), S1};
- error ->
- report_internal_error("variable `~w' not bound "
- "in pattern.\n", [Name]),
- exit(error)
- end;
- binary ->
- {Es, S1} = mapfoldl(fun (E, S) ->
- i_bitstr_pattern(E, Ren, Env,
- Ren0, Env0, S)
- end,
- S, binary_segments(E)),
- S2 = count_size(weight(binary), S1),
- {update_c_binary(E, Es), S2};
- _ ->
- case is_literal(E) of
- true ->
- {E, count_size(weight(literal), S)};
- false ->
- {Es1, S1} = mapfoldl(fun (E, S) ->
- i_pattern(E, Ren, Env,
- Ren0, Env0,
- S)
- end,
- S, data_es(E)),
- %% We assume that in general, the elements of the
- %% constructor will all be fetched.
- N = weight(data) + length(Es1) * weight(element),
- S2 = count_size(N, S1),
- {update_data(E, data_type(E), Es1), S2}
- end
- end.
-
-i_bitstr_pattern(E, Ren, Env, Ren0, Env0, S) ->
- %% It is not necessary to visit the Unit, Type and Flags fields,
- %% since these are always literals. The Value field is a limited
- %% pattern - either a literal or an unbound variable. The Size field
- %% is a limited expression - either a literal or a variable bound in
- %% the environment of the containing expression.
- {Val, S1} = i_pattern(bitstr_val(E), Ren, Env, Ren0, Env0, S),
- {Size, S2} = i(bitstr_size(E), value, Ren0, Env0, S1),
- Unit = bitstr_unit(E),
- Type = bitstr_type(E),
- Flags = bitstr_flags(E),
- S3 = count_size(weight(bitstr), S2),
- {update_c_bitstr(E, Val, Size, Unit, Type, Flags), S3}.
-
-
-%% ---------------------------------------------------------------------
-%% Other central inlining functions
-
-%% It is assumed here that `E' is a fun-expression and the context is an
-%% app-structure. If the inlining might be aborted for some reason, a
-%% corresponding catch should have been set up before entering `inline'.
-%%
-%% Note: if the inlined body is a lambda abstraction, and the
-%% surrounding context of the app-context is also an app-context, the
-%% `inlined' flag of the outermost context will be set before that of
-%% the inner context is set. E.g.: `let F = fun (X) -> fun (Y) -> E in
-%% apply apply F(A)(B)' will propagate the body of F, which is a lambda
-%% abstraction, into the outer application context, which will be
-%% inlined to produce expression `E', and the flag of the outer context
-%% will be set. Upon return, the flag of the inner context will also be
-%% set. However, the flags are then tested in innermost-first order.
-%% Thus, if some inlining attempt is aborted, the `inlined' flags of any
-%% nested app-contexts must be cleared.
-%%
-%% This implementation does nothing to handle inlining of calls to
-%% recursive functions in a smart way. This means that as long as the
-%% size and effort counters do not prevent it, the function body will be
-%% inlined (i.e., the first iteration will be unrolled), and the
-%% recursive calls will be residualized.
-
-inline(E, #app{opnds = Opnds, ctxt = Ctxt, loc = L}, Ren, Env, S) ->
- %% Check that the arities match:
- Vs = fun_vars(E),
- if length(Opnds) /= length(Vs) ->
- report_error("function called with wrong number "
- "of arguments!\n"),
- %% TODO: should really just residualise the call...
- exit(error);
- true ->
- ok
- end,
- %% Create local bindings for the parameters to their respective
- %% operand structures from the app-structure, and visit the body in
- %% the context saved in the structure.
- {Rs, Ren1, Env1, S1} = bind_locals(Vs, Opnds, Ren, Env, S),
- {E1, S2} = i(fun_body(E), Ctxt, Ren1, Env1, S1),
-
- %% Create necessary bindings and/or set flags.
- {E2, S3} = make_let_bindings(Rs, E1, S2),
-
- %% Lastly, flag the application as inlined, since the inlining
- %% attempt was not aborted before we reached this point.
- {E2, st__set_app_inlined(L, S3)}.
-
-%% For the (possibly renamed) argument variables to an inlined call,
-%% either create `let' bindings for them, if they are still referenced
-%% in the residual expression (in C/Lisp, also if they are assigned to),
-%% or otherwise (if they are not referenced or assigned) mark them for
-%% evaluation for side effects.
-
-make_let_bindings([R | Rs], E, S) ->
- {E1, S1} = make_let_bindings(Rs, E, S),
- make_let_binding(R, E1, S1);
-make_let_bindings([], E, S) ->
- {E, S}.
-
-make_let_binding(R, E, S) ->
- %% The `referenced' flag is conservatively computed. We therefore
- %% first check some simple cases where parameter R is definitely not
- %% referenced in the resulting body E.
- case is_literal(E) of
- true ->
- %% A constant contains no variable references.
- make_let_binding_1(R, E, S);
- false ->
- case is_c_var(E) of
- true ->
- case var_name(E) =:= R#ref.name of
- true ->
- %% The body is simply the parameter variable
- %% itself. Visit the operand for value and
- %% substitute the result for the body.
- visit_and_count_size(R#ref.opnd, S);
- false ->
- %% Not the same variable, so the parameter
- %% is not referenced at all.
- make_let_binding_1(R, E, S)
- end;
- false ->
- %% Proceed to check the `referenced' flag.
- case st__get_var_referenced(R#ref.loc, S) of
- true ->
- %% The parameter is probably referenced in
- %% the residual code (although it might not
- %% be). Visit the operand for value and
- %% create a let-binding.
- {E1, S1} = visit_and_count_size(R#ref.opnd,
- S),
- S2 = count_size(weight('let'), S1),
- {c_let([ref_to_var(R)], E1, E), S2};
- false ->
- %% The parameter is definitely not
- %% referenced.
- make_let_binding_1(R, E, S)
- end
- end
- end.
-
-%% This marks the operand for evaluation for effect.
-
-make_let_binding_1(R, E, S) ->
- Opnd = R#ref.opnd,
- {E, st__set_opnd_effect(Opnd#opnd.loc, S)}.
-
-%% Here, `R' is the ref-structure which is the target of the copy
-%% propagation, and `Opnd' is a visited operand structure, to be
-%% propagated through `R' if possible - if not, `R' is residualised.
-%% `Opnd' is normally the operand that `R' is bound to, and `E' is the
-%% result of visiting `Opnd' for value; we pass this as an argument so
-%% we don't have to fetch it multiple times (because we don't have
-%% constant time access).
-%%
-%% We also pass the environment of the site of the variable reference,
-%% for use when inlining a propagated fun-expression. In the original
-%% algorithm by Waddell, the environment used for inlining such cases is
-%% the identity mapping, because the fun-expression body has already
-%% been visited for value, and their algorithm combines renaming of
-%% source-code variables with the looking up of information about
-%% residual-code variables. We, however, need to check the environment
-%% of the call site when creating new non-shadowed variables, but we
-%% must avoid repeated renaming. We therefore separate the renaming and
-%% the environment (as in the renaming algorithm of Peyton-Jones and
-%% Marlow). This also makes our implementation more general, compared to
-%% the original algorithm, because we do not give up on propagating
-%% variables that were free in the fun-body.
-%%
-%% Example:
-%%
-%% let F = fun (X) -> {'foo', X} in
-%% let G = fun (H) -> apply H(F) % F is free in the fun G
-%% in apply G(fun (F) -> apply F(42))
-%% =>
-%% let F = fun (X) -> {'foo', X} in
-%% apply (fun (H) -> apply H(F))(fun (F) -> apply F(42))
-%% =>
-%% let F = fun (X) -> {'foo', X} in
-%% apply (fun (F) -> apply F(42))(F)
-%% =>
-%% let F = fun (X) -> {'foo', X} in
-%% apply F(42)
-%% =>
-%% apply (fun (X) -> {'foo', X})(2)
-%% =>
-%% {'foo', 42}
-%%
-%% The original algorithm would give up at stage 4, because F was free
-%% in the propagated fun-expression. Our version inlines this example
-%% completely.
-
-copy(R, Opnd, E, Ctxt, Env, S) ->
- case is_c_var(E) of
- true ->
- %% The operand reduces to another variable - get its
- %% ref-structure and attempt to propagate further.
- copy_var(env__get(var_name(E), Opnd#opnd.env), Ctxt, Env,
- S);
- false ->
- %% Apart from variables and functional values (the latter
- %% are handled by `copy_1' below), only constant literals
- %% are copyable in general; other things, including e.g.
- %% tuples `{foo, X}', could cause duplication of work, and
- %% are not copy propagated.
- case is_literal(E) of
- true ->
- {E, count_size(weight(literal), S)};
- false ->
- copy_1(R, Opnd, E, Ctxt, Env, S)
- end
- end.
-
-copy_var(R, Ctxt, Env, S) ->
- %% (In Lisp or C, if this other variable might be assigned to, we
- %% should residualize the "parent" instead, so we don't bypass any
- %% destructive updates.)
- case R#ref.opnd of
- undefined ->
- %% This variable is not bound to an expression, so just
- %% residualize it.
- residualize_var(R, S);
- Opnd ->
- %% Note that because operands are always visited before
- %% copied, all copyable operand expressions will be
- %% propagated through any number of bindings. If `R' was
- %% bound to a constant literal, we would never have reached
- %% this point.
- case st__lookup_opnd_cache(Opnd#opnd.loc, S) of
- error ->
- %% The result for this operand is not yet ready
- %% (which should mean that it is a recursive
- %% reference). Thus, we must residualise the
- %% variable.
- residualize_var(R, S);
- {ok, #cache{expr = E1}} ->
- %% The result for the operand is ready, so we can
- %% proceed to propagate it.
- copy_1(R, Opnd, E1, Ctxt, Env, S)
- end
- end.
-
-copy_1(R, Opnd, E, Ctxt, Env, S) ->
- %% Fun-expression (lambdas) are a bit special; they are copyable,
- %% but should preferably not be duplicated, so they should not be
- %% copy propagated except into application contexts, where they can
- %% be inlined.
- case is_c_fun(E) of
- true ->
- case Ctxt of
- #app{} ->
- %% First test if the operand is "outer-pending"; if
- %% so, don't inline.
- case st__test_outer_pending(Opnd#opnd.loc, S) of
- false ->
- copy_inline(R, Opnd, E, Ctxt, Env, S);
- true ->
- %% Cyclic reference forced inlining to stop
- %% (avoiding infinite unfolding).
- residualize_var(R, S)
- end;
- _ ->
- residualize_var(R, S)
- end;
- false ->
- %% We have no other cases to handle here
- residualize_var(R, S)
- end.
-
-%% This inlines a function value that was propagated to an application
-%% context. The inlining is done with an identity renaming (since the
-%% expression is already visited) but in the environment of the call
-%% site (which is OK because of the no-shadowing strategy for renaming,
-%% and because the domain of our environments are the residual-program
-%% variables instead of the source-program variables). Note that we must
-%% first set the "outer-pending" flag, and clear it afterwards.
-
-copy_inline(R, Opnd, E, Ctxt, Env, S) ->
- S1 = st__mark_outer_pending(Opnd#opnd.loc, S),
- case catch {ok, copy_inline_1(R, E, Ctxt, Env, S1)} of
- {ok, {E1, S2}} ->
- {E1, st__clear_outer_pending(Opnd#opnd.loc, S2)};
- {'EXIT', X} ->
- exit(X);
- X ->
- %% If we use destructive update for the `outer-pending'
- %% flag, we must make sure to clear it upon a nonlocal
- %% return.
- st__clear_outer_pending(Opnd#opnd.loc, S1),
- throw(X)
- end.
-
-%% If the current effort counter was passive, we use a new active effort
-%% counter with the inherited limit for this particular inlining.
-
-copy_inline_1(R, E, Ctxt, Env, S) ->
- case effort_is_active(S) of
- true ->
- copy_inline_2(R, E, Ctxt, Env, S);
- false ->
- S1 = new_active_effort(get_effort_limit(S), S),
- case catch {ok, copy_inline_2(R, E, Ctxt, Env, S1)} of
- {ok, {E1, S2}} ->
- %% Revert to the old effort counter.
- {E1, revert_effort(S, S2)};
- {counter_exceeded, effort, _} ->
- %% Aborted this inlining attempt because too much
- %% effort was spent. Residualize the variable and
- %% revert to the previous state.
- residualize_var(R, S);
- {'EXIT', X} ->
- exit(X);
- X ->
- throw(X)
- end
- end.
-
-%% Regardless of whether the current size counter is active or not, we
-%% use a new active size counter for each inlining. If the current
-%% counter was passive, the new counter gets the inherited size limit;
-%% if it was active, the size limit of the new counter will be equal to
-%% the remaining budget of the current counter (which itself is not
-%% affected by the inlining). This distributes the size budget more
-%% evenly over "inlinings within inlinings", so that the whole size
-%% budget is not spent on the first few call sites (in an inlined
-%% function body) forcing the remaining call sites to be residualised.
-
-copy_inline_2(R, E, Ctxt, Env, S) ->
- Limit = case size_is_active(S) of
- true ->
- get_size_limit(S) - get_size_value(S);
- false ->
- get_size_limit(S)
- end,
- %% Add the cost of the application to the new size limit, so we
- %% always inline functions that are small enough, even if `Limit' is
- %% close to zero at this point. (This is an extension to the
- %% original algorithm.)
- S1 = new_active_size(Limit + apply_size(length(Ctxt#app.opnds)), S),
- case catch {ok, inline(E, Ctxt, ren__identity(), Env, S1)} of
- {ok, {E1, S2}} ->
- %% Revert to the old size counter.
- {E1, revert_size(S, S2)};
- {counter_exceeded, size, S2} ->
- %% Aborted this inlining attempt because it got too big.
- %% Residualize the variable and revert to the old size
- %% counter. (It is important that we do not also revert the
- %% effort counter here. Because the effort and size counters
- %% are always set up together, we know that the effort
- %% counter returned in S2 is the same that was passed to
- %% `inline'.)
- S3 = revert_size(S, S2),
- %% If we use destructive update for the `inlined' flag, we
- %% must make sure to clear the flags of any nested
- %% app-contexts upon aborting; see `inline' for details.
- reset_nested_apps(Ctxt, S3), % for effect
- residualize_var(R, S3);
- {'EXIT', X} ->
- exit(X);
- X ->
- throw(X)
- end.
-
-reset_nested_apps(#app{ctxt = Ctxt, loc = L}, S) ->
- reset_nested_apps(Ctxt, st__clear_app_inlined(L, S));
-reset_nested_apps(_, S) ->
- S.
-
-
-%% ---------------------------------------------------------------------
-%% Support functions
-
-new_var(Env) ->
- Name = env__new_vname(Env),
- c_var(Name).
-
-residualize_var(R, S) ->
- S1 = count_size(weight(var), S),
- {ref_to_var(R), st__set_var_referenced(R#ref.loc, S1)}.
-
-%% This function returns the value-producing subexpression of any
-%% expression. (Except for sequencing expressions, this is the
-%% expression itself.)
-
-result(E) ->
- case is_c_seq(E) of
- true ->
- %% Also see `make_seq', which is used in all places to build
- %% sequences so that they are always nested in the first
- %% position.
- seq_body(E);
- false ->
- E
- end.
-
-%% This function rewrites E to `do A1 E' if A is `do A1 A2', and
-%% otherwise returns E unchanged.
-
-hoist_effects(A, E) ->
- case type(A) of
- seq -> make_seq(seq_arg(A), E);
- _ -> E
- end.
-
-%% This "build sequencing expression" operation assures that sequences
-%% are always nested in the first position, which makes it easy to find
-%% the actual value-producing expression of a sequence (cf. `result').
-
-make_seq(E1, E2) ->
- case is_safe(E1) of
- true ->
- %% The first expression can safely be dropped.
- E2;
- false ->
- %% If `E1' is a sequence whose final expression has no side
- %% effects, then we can lose *that* expression when we
- %% compose the new sequence, since its value will not be
- %% used.
- E3 = case is_c_seq(E1) of
- true ->
- case is_safe(seq_body(E1)) of
- true ->
- %% Drop the final expression.
- seq_arg(E1);
- false ->
- E1
- end;
- false ->
- E1
- end,
- case is_c_seq(E2) of
- true ->
- %% `E2' is a sequence (E2' E2''), so we must
- %% rearrange the nesting to ((E1, E2') E2''), to
- %% preserve the invariant. Annotations on `E2' are
- %% lost.
- c_seq(c_seq(E3, seq_arg(E2)), seq_body(E2));
- false ->
- c_seq(E3, E2)
- end
- end.
-
-%% Currently, safe expressions include variables, lambda expressions,
-%% constructors with safe subexpressions (this includes atoms, integers,
-%% empty lists, etc.), seq-, let- and letrec-expressions with safe
-%% subexpressions, try- and catch-expressions with safe subexpressions
-%% and calls to safe functions with safe argument subexpressions.
-%% Binaries seem too tricky to be considered.
-
-is_safe(E) ->
- case is_data(E) of
- true ->
- is_safe_list(data_es(E));
- false ->
- case type(E) of
- var ->
- true;
- 'fun' ->
- true;
- values ->
- is_safe_list(values_es(E));
- 'seq' ->
- case is_safe(seq_arg(E)) of
- true ->
- is_safe(seq_body(E));
- false ->
- false
- end;
- 'let' ->
- case is_safe(let_arg(E)) of
- true ->
- is_safe(let_body(E));
- false ->
- false
- end;
- letrec ->
- is_safe(letrec_body(E));
- 'try' ->
- %% If the argument expression is not safe, it could
- %% be modifying the state; thus, even if the body is
- %% safe, the try-expression as a whole would not be.
- %% If the argument is safe, the handler is not used.
- case is_safe(try_arg(E)) of
- true ->
- is_safe(try_body(E));
- false ->
- false
- end;
- 'catch' ->
- is_safe(catch_body(E));
- call ->
- M = call_module(E),
- F = call_name(E),
- case is_c_atom(M) and is_c_atom(F) of
- true ->
- As = call_args(E),
- case is_safe_list(As) of
- true ->
- is_safe_call(atom_val(M),
- atom_val(F),
- length(As));
- false ->
- false
- end;
- false ->
- false
- end;
- _ ->
- false
- end
- end.
-
-is_safe_list([E | Es]) ->
- case is_safe(E) of
- true ->
- is_safe_list(Es);
- false ->
- false
- end;
-is_safe_list([]) ->
- true.
-
-is_safe_call(M, F, A) ->
- erl_bifs:is_safe(M, F, A).
-
-%% When setting up local variables, we only create new names if we have
-%% to, according to the "no-shadowing" strategy.
-
-make_locals(Vs, Ren, Env) ->
- make_locals(Vs, [], Ren, Env).
-
-make_locals([V | Vs], As, Ren, Env) ->
- Name = var_name(V),
- case env__is_defined(Name, Env) of
- false ->
- %% The variable need not be renamed. Just make sure that the
- %% renaming will map it to itself.
- Name1 = Name,
- Ren1 = ren__add_identity(Name, Ren);
- true ->
- %% The variable must be renamed to maintain the no-shadowing
- %% invariant. Do the right thing for function variables.
- Name1 = case Name of
- {A, N} ->
- env__new_fname(A, N, Env);
- _ ->
- env__new_vname(Env)
- end,
- Ren1 = ren__add(Name, Name1, Ren)
- end,
- %% This temporary binding is added for correct new-key generation.
- Env1 = env__bind(Name1, dummy, Env),
- make_locals(Vs, [Name1 | As], Ren1, Env1);
-make_locals([], As, Ren, Env) ->
- {reverse(As), Ren, Env}.
-
-%% This adds let-bindings for the source code variables in `Es' to the
-%% environment `Env'.
-%%
-%% Note that we always assign a new state location for the
-%% residual-program variable, since we cannot know when a location for a
-%% particular variable in the source code can be reused.
-
-bind_locals(Vs, Ren, Env, S) ->
- Opnds = lists:duplicate(length(Vs), undefined),
- bind_locals(Vs, Opnds, Ren, Env, S).
-
-bind_locals(Vs, Opnds, Ren, Env, S) ->
- {Ns, Ren1, Env1} = make_locals(Vs, Ren, Env),
- {Rs, Env2, S1} = bind_locals_1(Ns, Opnds, [], Env1, S),
- {Rs, Ren1, Env2, S1}.
-
-%% Note that the `Vs' are currently not used for anything except the
-%% number of variables. If we were maintaining "source-referenced"
-%% flags, then the flag in the new variable should be initialized to the
-%% current value of the (residual-) referenced-flag of the "parent".
-
-bind_locals_1([N | Ns], [Opnd | Opnds], Rs, Env, S) ->
- {R, S1} = new_ref(N, Opnd, S),
- Env1 = env__bind(N, R, Env),
- bind_locals_1(Ns, Opnds, [R | Rs], Env1, S1);
-bind_locals_1([], [], Rs, Env, S) ->
- {lists:reverse(Rs), Env, S}.
-
-new_refs(Ns, Opnds, S) ->
- new_refs(Ns, Opnds, [], S).
-
-new_refs([N | Ns], [Opnd | Opnds], Rs, S) ->
- {R, S1} = new_ref(N, Opnd, S),
- new_refs(Ns, Opnds, [R | Rs], S1);
-new_refs([], [], Rs, S) ->
- {lists:reverse(Rs), S}.
-
-new_ref(N, Opnd, S) ->
- {L, S1} = st__new_ref_loc(S),
- {#ref{name = N, opnd = Opnd, loc = L}, S1}.
-
-%% This adds recursive bindings for the source code variables in `Es' to
-%% the environment `Env'. Note that recursive binding of a set of
-%% variables is an atomic operation on the environment - they cannot be
-%% added one at a time.
-
-bind_recursive(Vs, Opnds, Ren, Env, S) ->
- {Ns, Ren1, Env1} = make_locals(Vs, Ren, Env),
- {Rs, S1} = new_refs(Ns, Opnds, S),
-
- %% When this fun-expression is evaluated, it updates the operand
- %% structure in the ref-structure to contain the recursively defined
- %% environment and the correct renaming.
- Fun = fun (R, Env) ->
- Opnd = R#ref.opnd,
- R#ref{opnd = Opnd#opnd{ren = Ren1, env = Env}}
- end,
- {Rs, Ren1, env__bind_recursive(Ns, Rs, Fun, Env1), S1}.
-
-safe_context(Ctxt) ->
- case Ctxt of
- #app{} ->
- value;
- _ ->
- Ctxt
- end.
-
-%% Note that the name of a variable encodes its type: a "plain" variable
-%% or a function variable. The latter kind also contains an arity number
-%% which should be preserved upon renaming.
-
-ref_to_var(#ref{name = Name}) ->
- %% If we were maintaining "source-referenced" flags, the annotation
- %% `add_ann([#source_ref{loc = L}], E)' should also be done here, to
- %% make the algorithm reapplicable. This is however not necessary
- %% since there are no destructive variable assignments in Erlang.
- c_var(Name).
-
-%% Including the effort counter of the call site assures that the cost
-%% of processing an operand via `visit' is charged to the correct
-%% counter. In particular, if the effort counter of the call site was
-%% passive, the operands will also be processed with a passive counter.
-
-make_opnd(E, Ren, Env, S) ->
- {L, S1} = st__new_opnd_loc(S),
- C = st__get_effort(S1),
- Opnd = #opnd{expr = E, ren = Ren, env = Env, loc = L, effort = C},
- {Opnd, S1}.
-
-keep_referenced(Rs, S) ->
- [R || R <- Rs, st__get_var_referenced(R#ref.loc, S)].
-
-residualize_operands(Opnds, E, S) ->
- foldr(fun (Opnd, {E, S}) -> residualize_operand(Opnd, E, S) end,
- {E, S}, Opnds).
-
-%% This is the only case where an operand expression can be visited in
-%% `effect' context instead of `value' context.
-
-residualize_operand(Opnd, E, S) ->
- case st__get_opnd_effect(Opnd#opnd.loc, S) of
- true ->
- %% The operand has not been visited, so we do that now, but
- %% in `effect' context. (Waddell's algoritm does some stuff
- %% here to account specially for the operand size, which
- %% appears unnecessary.)
- {E1, S1} = i(Opnd#opnd.expr, effect, Opnd#opnd.ren,
- Opnd#opnd.env, S),
- {make_seq(E1, E), S1};
- false ->
- {E, S}
- end.
-
-%% The `visit' function always visits the operand expression in `value'
-%% context (`residualize_operand' visits an unreferenced operand
-%% expression in `effect' context when necessary). A new passive size
-%% counter is used for visiting the operand, the final value of which is
-%% then cached along with the resulting expression.
-%%
-%% Note that the effort counter of the call site, included in the
-%% operand structure, is not a shared object. Thus, the effort budget is
-%% actually reused over all occurrences of the operands of a single
-%% application. This does not appear to be a problem; just a
-%% modification of the algorithm.
-
-visit(Opnd, S) ->
- {C, S1} = visit_1(Opnd, S),
- {C#cache.expr, S1}.
-
-visit_and_count_size(Opnd, S) ->
- {C, S1} = visit_1(Opnd, S),
- {C#cache.expr, count_size(C#cache.size, S1)}.
-
-visit_1(Opnd, S) ->
- case st__lookup_opnd_cache(Opnd#opnd.loc, S) of
- error ->
- %% Use a new, passive, size counter for visiting operands,
- %% and use the effort counter of the context of the operand.
- %% It turns out that if the latter is active, it must be the
- %% same object as the one currently used, and if it is
- %% passive, it does not matter if it is the same object as
- %% any other counter.
- Effort = Opnd#opnd.effort,
- Active = counter__is_active(Effort),
- S1 = case Active of
- true ->
- S; % don't change effort counter
- false ->
- st__set_effort(Effort, S)
- end,
- S2 = new_passive_size(get_size_limit(S1), S1),
-
- %% Visit the expression and cache the result, along with the
- %% final value of the size counter.
- {E, S3} = i(Opnd#opnd.expr, value, Opnd#opnd.ren,
- Opnd#opnd.env, S2),
- Size = get_size_value(S3),
- C = #cache{expr = E, size = Size},
- S4 = revert_size(S, st__set_opnd_cache(Opnd#opnd.loc, C,
- S3)),
- case Active of
- true ->
- {C, S4}; % keep using the same effort counter
- false ->
- {C, revert_effort(S, S4)}
- end;
- {ok, C} ->
- {C, S}
- end.
-
-%% Create a pattern matching template for an expression. A template
-%% contains only data constructors (including atomic ones) and
-%% variables, and compound literals are not folded into a single node.
-%% Each node in the template is annotated with the variable which holds
-%% the corresponding subexpression; these are new, unique variables not
-%% existing in the given `Env'. Returns `{Template, Variables, NewEnv}',
-%% where `Variables' is the list of all variables corresponding to nodes
-%% in the template *listed in reverse dependency order*, and `NewEnv' is
-%% `Env' augmented with mappings from the variable names to
-%% subexpressions of `E' (not #ref{} structures!) rewritten so that no
-%% computations are duplicated. `Variables' is guaranteed to be nonempty
-%% - at least the root node will always be bound to a new variable.
-
-make_template(E, Env) ->
- make_template(E, [], Env).
-
-make_template(E, Vs0, Env0) ->
- case is_data(E) of
- true ->
- {Ts, {Vs1, Env1}} = mapfoldl(
- fun (E, {Vs0, Env0}) ->
- {T, Vs1, Env1} =
- make_template(E, Vs0,
- Env0),
- {T, {Vs1, Env1}}
- end,
- {Vs0, Env0}, data_es(E)),
- T = make_data_skel(data_type(E), Ts),
- E1 = update_data(E, data_type(E),
- [hd(get_ann(T)) || T <- Ts]),
- V = new_var(Env1),
- Env2 = env__bind(var_name(V), E1, Env1),
- {set_ann(T, [V]), [V | Vs1], Env2};
- false ->
- case type(E) of
- seq ->
- %% For a sequencing, we can rebind the variable used
- %% for the body, and pass on the template as it is.
- {T, Vs1, Env1} = make_template(seq_body(E), Vs0,
- Env0),
- V = var_name(hd(get_ann(T))),
- E1 = update_c_seq(E, seq_arg(E), env__get(V, Env1)),
- Env2 = env__bind(V, E1, Env1),
- {T, Vs1, Env2};
- _ ->
- V = new_var(Env0),
- Env1 = env__bind(var_name(V), E, Env0),
- {set_ann(V, [V]), [V | Vs0], Env1}
- end
- end.
-
-%% Two clauses are equivalent if their bodies are equivalent expressions
-%% given that the respective pattern variables are local.
-
-equivalent_clauses([]) ->
- true;
-equivalent_clauses([C | Cs]) ->
- Env = cerl_trees:variables(c_values(clause_pats(C))),
- equivalent_clauses_1(clause_body(C), Cs, Env).
-
-equivalent_clauses_1(E, [C | Cs], Env) ->
- Env1 = cerl_trees:variables(c_values(clause_pats(C))),
- case equivalent(E, clause_body(C), ordsets:union(Env, Env1)) of
- true ->
- equivalent_clauses_1(E, Cs, Env);
- false ->
- false
- end;
-equivalent_clauses_1(_, [], _Env) ->
- true.
-
-%% Two expressions are equivalent if and only if they yield the same
-%% value and has the same side effects in the same order. Currently, we
-%% only accept equality between constructors (constants) and nonlocal
-%% variables, since this should cover most cases of interest. If a
-%% variable is locally bound in one expression, it cannot be equivalent
-%% to one with the same name in the other expression, so we need not
-%% keep track of two environments.
-
-equivalent(E1, E2, Env) ->
- case is_data(E1) of
- true ->
- case is_data(E2) of
- true ->
- T1 = {data_type(E1), data_arity(E1)},
- T2 = {data_type(E2), data_arity(E2)},
- %% Note that we must test for exact equality.
- if T1 =:= T2 ->
- equivalent_lists(data_es(E1), data_es(E2),
- Env);
- true ->
- false
- end;
- false ->
- false
- end;
- false ->
- case type(E1) of
- var ->
- case is_c_var(E2) of
- true ->
- N1 = var_name(E1),
- N2 = var_name(E2),
- if N1 =:= N2 ->
- not ordsets:is_element(N1, Env);
- true ->
- false
- end;
- false ->
- false
- end;
- _ ->
- %% Other constructs are not being considered.
- false
- end
- end.
-
-equivalent_lists([E1 | Es1], [E2 | Es2], Env) ->
- equivalent(E1, E2, Env) and equivalent_lists(Es1, Es2, Env);
-equivalent_lists([], [], _) ->
- true;
-equivalent_lists(_, _, _) ->
- false.
-
-%% Return `false' or `{true, EffectExpr, ValueExpr}'. The environment is
-%% passed for new-variable generation.
-
-reduce_bif_call(M, F, As, Env) ->
- reduce_bif_call_1(M, F, length(As), As, Env).
-
-reduce_bif_call_1(erlang, element, 2, [X, Y], _Env) ->
- case is_c_int(X) and is_c_tuple(Y) of
- true ->
- %% We are free to change the relative evaluation order of
- %% the elements, so lifting out a particular element is OK.
- T = list_to_tuple(tuple_es(Y)),
- N = int_val(X),
- if integer(N), N > 0, N =< size(T) ->
- E = element(N, T),
- Es = tuple_to_list(setelement(N, T, void())),
- {true, make_seq(c_tuple(Es), E)};
- true ->
- false
- end;
- false ->
- false
- end;
-reduce_bif_call_1(erlang, hd, 1, [X], _Env) ->
- case is_c_cons(X) of
- true ->
- %% Cf. `element/2' above.
- {true, make_seq(cons_tl(X), cons_hd(X))};
- false ->
- false
- end;
-reduce_bif_call_1(erlang, length, 1, [X], _Env) ->
- case is_c_list(X) of
- true ->
- %% Cf. `erlang:size/1' below.
- {true, make_seq(X, c_int(list_length(X)))};
- false ->
- false
- end;
-reduce_bif_call_1(erlang, list_to_tuple, 1, [X], _Env) ->
- case is_c_list(X) of
- true ->
- %% This does not actually preserve all the evaluation order
- %% constraints of the list, but I don't imagine that it will
- %% be a problem.
- {true, c_tuple(list_elements(X))};
- false ->
- false
- end;
-reduce_bif_call_1(erlang, setelement, 3, [X, Y, Z], Env) ->
- case is_c_int(X) and is_c_tuple(Y) of
- true ->
- %% Here, unless `Z' is a simple expression, we must bind it
- %% to a new variable, because in that case, `Z' must be
- %% evaluated before any part of `Y'.
- T = list_to_tuple(tuple_es(Y)),
- N = int_val(X),
- if integer(N), N > 0, N =< size(T) ->
- E = element(N, T),
- case is_simple(Z) of
- true ->
- Es = tuple_to_list(setelement(N, T, Z)),
- {true, make_seq(E, c_tuple(Es))};
- false ->
- V = new_var(Env),
- Es = tuple_to_list(setelement(N, T, V)),
- E1 = make_seq(E, c_tuple(Es)),
- {true, c_let([V], Z, E1)}
- end;
- true ->
- false
- end;
- false ->
- false
- end;
-reduce_bif_call_1(erlang, size, 1, [X], _Env) ->
- case is_c_tuple(X) of
- true ->
- %% Just evaluate the tuple for effect and use the size (the
- %% arity) as the result.
- {true, make_seq(X, c_int(tuple_arity(X)))};
- false ->
- false
- end;
-reduce_bif_call_1(erlang, tl, 1, [X], _Env) ->
- case is_c_cons(X) of
- true ->
- %% Cf. `element/2' above.
- {true, make_seq(cons_hd(X), cons_tl(X))};
- false ->
- false
- end;
-reduce_bif_call_1(erlang, tuple_to_list, 1, [X], _Env) ->
- case is_c_tuple(X) of
- true ->
- %% This actually introduces slightly stronger constraints on
- %% the evaluation order of the subexpressions.
- {true, make_list(tuple_es(X))};
- false ->
- false
- end;
-reduce_bif_call_1(_M, _F, _A, _As, _Env) ->
- false.
-
-effort_is_active(S) ->
- counter__is_active(st__get_effort(S)).
-
-size_is_active(S) ->
- counter__is_active(st__get_size(S)).
-
-get_effort_limit(S) ->
- counter__limit(st__get_effort(S)).
-
-new_active_effort(Limit, S) ->
- st__set_effort(counter__new_active(Limit), S).
-
-revert_effort(S1, S2) ->
- st__set_effort(st__get_effort(S1), S2).
-
-new_active_size(Limit, S) ->
- st__set_size(counter__new_active(Limit), S).
-
-new_passive_size(Limit, S) ->
- st__set_size(counter__new_passive(Limit), S).
-
-revert_size(S1, S2) ->
- st__set_size(st__get_size(S1), S2).
-
-count_effort(N, S) ->
- C = st__get_effort(S),
- C1 = counter__add(N, C, effort, S),
- case debug_counters() of
- true ->
- case counter__is_active(C1) of
- true ->
- V = counter__value(C1),
- case V > get(counter_effort_max) of
- true ->
- put(counter_effort_max, V);
- false ->
- ok
- end;
- false ->
- ok
- end;
- _ ->
- ok
- end,
- st__set_effort(C1, S).
-
-count_size(N, S) ->
- C = st__get_size(S),
- C1 = counter__add(N, C, size, S),
- case debug_counters() of
- true ->
- case counter__is_active(C1) of
- true ->
- V = counter__value(C1),
- case V > get(counter_size_max) of
- true ->
- put(counter_size_max, V);
- false ->
- ok
- end;
- false ->
- ok
- end;
- _ ->
- ok
- end,
- st__set_size(C1, S).
-
-get_size_value(S) ->
- counter__value(st__get_size(S)).
-
-get_size_limit(S) ->
- counter__limit(st__get_size(S)).
-
-kill_id_anns([{'id',_} | As]) ->
- kill_id_anns(As);
-kill_id_anns([A | As]) ->
- [A | kill_id_anns(As)];
-kill_id_anns([]) ->
- [].
-
-
-%% =====================================================================
-%% General utilities
-
-max(X, Y) when X > Y -> X;
-max(_, Y) -> Y.
-
-%% The atom `ok', is widely used in Erlang for "void" values.
-
-void() -> abstract(ok).
-
-is_simple(E) ->
- case type(E) of
- literal -> true;
- var -> true;
- 'fun' -> true;
- _ -> false
- end.
-
-get_components(N, E) ->
- case type(E) of
- values ->
- Es = values_es(E),
- if length(Es) == N ->
- {true, Es};
- true ->
- false
- end;
- _ when N == 1 ->
- {true, [E]};
- _ ->
- false
- end.
-
-all_static([E | Es]) ->
- case is_literal(result(E)) of
- true ->
- all_static(Es);
- false ->
- false
- end;
-all_static([]) ->
- true.
-
-set_clause_bodies([C | Cs], B) ->
- [update_c_clause(C, clause_pats(C), clause_guard(C), B)
- | set_clause_bodies(Cs, B)];
-set_clause_bodies([], _) ->
- [].
-
-filename([C | T]) when integer(C), C > 0, C =< 255 ->
- [C | filename(T)];
-filename([H|T]) ->
- filename(H) ++ filename(T);
-filename([]) ->
- [];
-filename(N) when atom(N) ->
- atom_to_list(N);
-filename(N) ->
- report_error("bad filename: `~P'.", [N, 25]),
- exit(error).
-
-
-%% =====================================================================
-%% Abstract datatype: renaming()
-
-ren__identity() ->
- dict:new().
-
-ren__add(X, Y, Ren) ->
- dict:store(X, Y, Ren).
-
-ren__map(X, Ren) ->
- case dict:find(X, Ren) of
- {ok, Y} ->
- Y;
- error ->
- X
- end.
-
-ren__add_identity(X, Ren) ->
- dict:erase(X, Ren).
-
-
-%% =====================================================================
-%% Abstract datatype: environment()
-
-env__empty() ->
- rec_env:empty().
-
-env__bind(Key, Val, Env) ->
- rec_env:bind(Key, Val, Env).
-
-%% `Es' should have type `[{Key, Val}]', and `Fun' should have type
-%% `(Val, Env) -> T', mapping a value together with the recursive
-%% environment itself to some term `T' to be returned when the entry is
-%% looked up.
-
-env__bind_recursive(Ks, Vs, F, Env) ->
- rec_env:bind_recursive(Ks, Vs, F, Env).
-
-env__lookup(Key, Env) ->
- rec_env:lookup(Key, Env).
-
-env__get(Key, Env) ->
- rec_env:get(Key, Env).
-
-env__is_defined(Key, Env) ->
- rec_env:is_defined(Key, Env).
-
-env__new_vname(Env) ->
- rec_env:new_key(Env).
-
-env__new_fname(A, N, Env) ->
- rec_env:new_key(fun (X) ->
- S = integer_to_list(X),
- {list_to_atom(atom_to_list(A) ++ "_" ++ S),
- N}
- end, Env).
-
-
-%% =====================================================================
-%% Abstract datatype: state()
-
--record(state, {free, % next free location
- size, % size counter
- effort, % effort counter
- cache, % operand expression cache
- var_flags, % flags for variables (#ref-structures)
- opnd_flags, % flags for operands
- app_flags}). % flags for #app-structures
-
-%% Note that we do not have a `var_assigned' flag, since there is no
-%% destructive assignment in Erlang. In the original algorithm, the
-%% "residual-referenced"-flags of the previous inlining pass (or
-%% initialization pass) are used as the "source-referenced"-flags for
-%% the subsequent pass. The latter may then be used as a safe
-%% approximation whenever we need to base a decision on whether or not a
-%% particular variable or function variable could be referenced in the
-%% program being generated, and computation of the new
-%% "residual-referenced" flag for that variable is not yet finished. In
-%% the present algorithm, this can only happen in the presence of
-%% variable assignments, which do not exist in Erlang. Therefore, we do
-%% not keep "source-referenced" flags for residual-code references in
-%% our implementation.
-%%
-%% The "inner-pending" flag tells us whether we are already in the
-%% process of visiting a particular operand, and the "outer-pending"
-%% flag whether we are in the process of inlining a propagated
-%% functional value. The "pending flags" are really counters limiting
-%% the number of times an operand may be inlined recursively, causing
-%% loop unrolling; however, unrolling more than one iteration does not
-%% work offhand in the present implementation. (TODO: find out why.)
-%% Note that the initial value must be greater than zero in order for
-%% any inlining at all to be done.
-
-%% Flags are stored in ETS-tables, one table for each class. The second
-%% element in each stored tuple is the key (the "label").
-
--record(var_flags, {lab, referenced = false}).
--record(opnd_flags, {lab, inner_pending = 1, outer_pending = 1,
- effect = false}).
--record(app_flags, {lab, inlined = false}).
-
-st__new(Effort, Size) ->
- #state{free = 0,
- size = counter__new_passive(Size),
- effort = counter__new_passive(Effort),
- cache = dict:new(),
- var_flags = ets:new(var, [set, private, {keypos, 2}]),
- opnd_flags = ets:new(opnd, [set, private, {keypos, 2}]),
- app_flags = ets:new(app, [set, private, {keypos, 2}])}.
-
-st__new_loc(S) ->
- N = S#state.free,
- {N, S#state{free = N + 1}}.
-
-st__get_effort(S) ->
- S#state.effort.
-
-st__set_effort(C, S) ->
- S#state{effort = C}.
-
-st__get_size(S) ->
- S#state.size.
-
-st__set_size(C, S) ->
- S#state{size = C}.
-
-st__set_var_referenced(L, S) ->
- T = S#state.var_flags,
- [F] = ets:lookup(T, L),
- ets:insert(T, F#var_flags{referenced = true}),
- S.
-
-st__get_var_referenced(L, S) ->
- ets:lookup_element(S#state.var_flags, L, #var_flags.referenced).
-
-st__lookup_opnd_cache(L, S) ->
- dict:find(L, S#state.cache).
-
-%% Note that setting the cache should only be done once.
-
-st__set_opnd_cache(L, C, S) ->
- S#state{cache = dict:store(L, C, S#state.cache)}.
-
-st__set_opnd_effect(L, S) ->
- T = S#state.opnd_flags,
- [F] = ets:lookup(T, L),
- ets:insert(T, F#opnd_flags{effect = true}),
- S.
-
-st__get_opnd_effect(L, S) ->
- ets:lookup_element(S#state.opnd_flags, L, #opnd_flags.effect).
-
-st__set_app_inlined(L, S) ->
- T = S#state.app_flags,
- [F] = ets:lookup(T, L),
- ets:insert(T, F#app_flags{inlined = true}),
- S.
-
-st__clear_app_inlined(L, S) ->
- T = S#state.app_flags,
- [F] = ets:lookup(T, L),
- ets:insert(T, F#app_flags{inlined = false}),
- S.
-
-st__get_app_inlined(L, S) ->
- ets:lookup_element(S#state.app_flags, L, #app_flags.inlined).
-
-%% The pending-flags are initialized by `st__new_opnd_loc' below.
-
-st__test_inner_pending(L, S) ->
- T = S#state.opnd_flags,
- P = ets:lookup_element(T, L, #opnd_flags.inner_pending),
- P =< 0.
-
-st__mark_inner_pending(L, S) ->
- ets:update_counter(S#state.opnd_flags, L,
- {#opnd_flags.inner_pending, -1}),
- S.
-
-st__clear_inner_pending(L, S) ->
- ets:update_counter(S#state.opnd_flags, L,
- {#opnd_flags.inner_pending, 1}),
- S.
-
-st__test_outer_pending(L, S) ->
- T = S#state.opnd_flags,
- P = ets:lookup_element(T, L, #opnd_flags.outer_pending),
- P =< 0.
-
-st__mark_outer_pending(L, S) ->
- ets:update_counter(S#state.opnd_flags, L,
- {#opnd_flags.outer_pending, -1}),
- S.
-
-st__clear_outer_pending(L, S) ->
- ets:update_counter(S#state.opnd_flags, L,
- {#opnd_flags.outer_pending, 1}),
- S.
-
-st__new_app_loc(S) ->
- V = {L, _S1} = st__new_loc(S),
- ets:insert(S#state.app_flags, #app_flags{lab = L}),
- V.
-
-st__new_ref_loc(S) ->
- V = {L, _S1} = st__new_loc(S),
- ets:insert(S#state.var_flags, #var_flags{lab = L}),
- V.
-
-st__new_opnd_loc(S) ->
- V = {L, _S1} = st__new_loc(S),
- ets:insert(S#state.opnd_flags, #opnd_flags{lab = L}),
- V.
-
-
-%% =====================================================================
-%% Abstract datatype: counter()
-%%
-%% `counter__add' throws `{counter_exceeded, Type, Data}' if the
-%% resulting counter value would exceed the limit for the counter in
-%% question (`Type' and `Data' are given by the user).
-
--record(counter, {active, value, limit}).
-
-counter__new_passive(Limit) when Limit > 0 ->
- {0, Limit}.
-
-counter__new_active(Limit) when Limit > 0 ->
- {Limit, Limit}.
-
-%% Active counters have values > 0 internally; passive counters start at
-%% zero. The 'limit' field is only accessed by the 'counter__limit'
-%% function.
-
-counter__is_active({C, _}) ->
- C > 0.
-
-counter__limit({_, L}) ->
- L.
-
-counter__value({N, L}) ->
- if N > 0 ->
- L - N;
- true ->
- -N
- end.
-
-counter__add(N, {V, L}, Type, Data) ->
- N1 = V - N,
- if V > 0, N1 =< 0 ->
- case debug_counters() of
- true ->
- case Type of
- effort ->
- put(counter_effort_triggers,
- get(counter_effort_triggers) + 1);
- size ->
- put(counter_size_triggers,
- get(counter_size_triggers) + 1)
- end;
- _ ->
- ok
- end,
- throw({counter_exceeded, Type, Data});
- true ->
- {N1, L}
- end.
-
-
-%% =====================================================================
-%% Reporting
-
-% report_internal_error(S) ->
-% report_internal_error(S, []).
-
-report_internal_error(S, Vs) ->
- report_error("internal error: " ++ S, Vs).
-
-report_error(D) ->
- report_error(D, []).
-
-report_error({F, L, D}, Vs) ->
- report({F, L, {error, D}}, Vs);
-report_error(D, Vs) ->
- report({error, D}, Vs).
-
-report_warning(D) ->
- report_warning(D, []).
-
-report_warning({F, L, D}, Vs) ->
- report({F, L, {warning, D}}, Vs);
-report_warning(D, Vs) ->
- report({warning, D}, Vs).
-
-report(D, Vs) ->
- io:put_chars(format(D, Vs)).
-
-format({error, D}, Vs) ->
- ["error: ", format(D, Vs)];
-format({warning, D}, Vs) ->
- ["warning: ", format(D, Vs)];
-format({"", L, D}, Vs) when integer(L), L > 0 ->
- [io_lib:fwrite("~w: ", [L]), format(D, Vs)];
-format({"", _L, D}, Vs) ->
- format(D, Vs);
-format({F, L, D}, Vs) when integer(L), L > 0 ->
- [io_lib:fwrite("~s:~w: ", [filename(F), L]), format(D, Vs)];
-format({F, _L, D}, Vs) ->
- [io_lib:fwrite("~s: ", [filename(F)]), format(D, Vs)];
-format(S, Vs) when list(S) ->
- [io_lib:fwrite(S, Vs), $\n].
-
-
-%% =====================================================================
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/cerl_trees.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/cerl_trees.erl
deleted file mode 100644
index 50384a6ff8..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/cerl_trees.erl
+++ /dev/null
@@ -1,801 +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 Richard Carlsson.
-%% Copyright (C) 1999-2002 Richard Carlsson.
-%% Portions created by Ericsson are Copyright 2001, Ericsson Utvecklings
-%% AB. All Rights Reserved.''
-%%
-%% $Id: cerl_trees.erl,v 1.2 2010/06/07 06:32:39 kostis Exp $
-
-%% @doc Basic functions on Core Erlang abstract syntax trees.
-%%
-%% <p>Syntax trees are defined in the module <a
-%% href=""><code>cerl</code></a>.</p>
-%%
-%% @type cerl() = cerl:cerl()
-
--module(cerl_trees).
-
--export([depth/1, fold/3, free_variables/1, label/1, label/2, map/2,
- mapfold/3, size/1, variables/1]).
-
--import(cerl, [alias_pat/1, alias_var/1, ann_c_alias/3, ann_c_apply/3,
- ann_c_binary/2, ann_c_bitstr/6, ann_c_call/4,
- ann_c_case/3, ann_c_catch/2, ann_c_clause/4,
- ann_c_cons_skel/3, ann_c_fun/3, ann_c_let/4,
- ann_c_letrec/3, ann_c_module/5, ann_c_primop/3,
- ann_c_receive/4, ann_c_seq/3, ann_c_try/6,
- ann_c_tuple_skel/2, ann_c_values/2, apply_args/1,
- apply_op/1, binary_segments/1, bitstr_val/1,
- bitstr_size/1, bitstr_unit/1, bitstr_type/1,
- bitstr_flags/1, call_args/1, call_module/1, call_name/1,
- case_arg/1, case_clauses/1, catch_body/1, clause_body/1,
- clause_guard/1, clause_pats/1, clause_vars/1, concrete/1,
- cons_hd/1, cons_tl/1, fun_body/1, fun_vars/1, get_ann/1,
- let_arg/1, let_body/1, let_vars/1, letrec_body/1,
- letrec_defs/1, letrec_vars/1, module_attrs/1,
- module_defs/1, module_exports/1, module_name/1,
- module_vars/1, primop_args/1, primop_name/1,
- receive_action/1, receive_clauses/1, receive_timeout/1,
- seq_arg/1, seq_body/1, set_ann/2, subtrees/1, try_arg/1,
- try_body/1, try_vars/1, try_evars/1, try_handler/1,
- tuple_es/1, type/1, update_c_alias/3, update_c_apply/3,
- update_c_binary/2, update_c_bitstr/6, update_c_call/4,
- update_c_case/3, update_c_catch/2, update_c_clause/4,
- update_c_cons/3, update_c_cons_skel/3, update_c_fun/3,
- update_c_let/4, update_c_letrec/3, update_c_module/5,
- update_c_primop/3, update_c_receive/4, update_c_seq/3,
- update_c_try/6, update_c_tuple/2, update_c_tuple_skel/2,
- update_c_values/2, values_es/1, var_name/1]).
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec depth(Tree::cerl) -> integer()
-%%
-%% @doc Returns the length of the longest path in the tree. A leaf
-%% node has depth zero, the tree representing "<code>{foo,
-%% bar}</code>" has depth one, etc.
-
-depth(T) ->
- case subtrees(T) of
- [] ->
- 0;
- Gs ->
- 1 + lists:foldl(fun (G, A) -> erlang:max(depth_1(G), A) end, 0, Gs)
- end.
-
-depth_1(Ts) ->
- lists:foldl(fun (T, A) -> erlang:max(depth(T), A) end, 0, Ts).
-
-%% max(X, Y) when X > Y -> X;
-%% max(_, Y) -> Y.
-
-
-%% @spec size(Tree::cerl()) -> integer()
-%%
-%% @doc Returns the number of nodes in <code>Tree</code>.
-
-size(T) ->
- fold(fun (_, S) -> S + 1 end, 0, T).
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec map(Function, Tree::cerl()) -> cerl()
-%%
-%% Function = (cerl()) -> cerl()
-%%
-%% @doc Maps a function onto the nodes of a tree. This replaces each
-%% node in the tree by the result of applying the given function on
-%% the original node, bottom-up.
-%%
-%% @see mapfold/3
-
-map(F, T) ->
- F(map_1(F, T)).
-
-map_1(F, T) ->
- case type(T) of
- literal ->
- case concrete(T) of
- [_ | _] ->
- update_c_cons(T, map(F, cons_hd(T)),
- map(F, cons_tl(T)));
- V when tuple_size(V) > 0 ->
- update_c_tuple(T, map_list(F, tuple_es(T)));
- _ ->
- T
- end;
- var ->
- T;
- values ->
- update_c_values(T, map_list(F, values_es(T)));
- cons ->
- update_c_cons_skel(T, map(F, cons_hd(T)),
- map(F, cons_tl(T)));
- tuple ->
- update_c_tuple_skel(T, map_list(F, tuple_es(T)));
- 'let' ->
- update_c_let(T, map_list(F, let_vars(T)),
- map(F, let_arg(T)),
- map(F, let_body(T)));
- seq ->
- update_c_seq(T, map(F, seq_arg(T)),
- map(F, seq_body(T)));
- apply ->
- update_c_apply(T, map(F, apply_op(T)),
- map_list(F, apply_args(T)));
- call ->
- update_c_call(T, map(F, call_module(T)),
- map(F, call_name(T)),
- map_list(F, call_args(T)));
- primop ->
- update_c_primop(T, map(F, primop_name(T)),
- map_list(F, primop_args(T)));
- 'case' ->
- update_c_case(T, map(F, case_arg(T)),
- map_list(F, case_clauses(T)));
- clause ->
- update_c_clause(T, map_list(F, clause_pats(T)),
- map(F, clause_guard(T)),
- map(F, clause_body(T)));
- alias ->
- update_c_alias(T, map(F, alias_var(T)),
- map(F, alias_pat(T)));
- 'fun' ->
- update_c_fun(T, map_list(F, fun_vars(T)),
- map(F, fun_body(T)));
- 'receive' ->
- update_c_receive(T, map_list(F, receive_clauses(T)),
- map(F, receive_timeout(T)),
- map(F, receive_action(T)));
- 'try' ->
- update_c_try(T, map(F, try_arg(T)),
- map_list(F, try_vars(T)),
- map(F, try_body(T)),
- map_list(F, try_evars(T)),
- map(F, try_handler(T)));
- 'catch' ->
- update_c_catch(T, map(F, catch_body(T)));
- binary ->
- update_c_binary(T, map_list(F, binary_segments(T)));
- bitstr ->
- update_c_bitstr(T, map(F, bitstr_val(T)),
- map(F, bitstr_size(T)),
- map(F, bitstr_unit(T)),
- map(F, bitstr_type(T)),
- map(F, bitstr_flags(T)));
- letrec ->
- update_c_letrec(T, map_pairs(F, letrec_defs(T)),
- map(F, letrec_body(T)));
- module ->
- update_c_module(T, map(F, module_name(T)),
- map_list(F, module_exports(T)),
- map_pairs(F, module_attrs(T)),
- map_pairs(F, module_defs(T)))
- end.
-
-map_list(F, [T | Ts]) ->
- [map(F, T) | map_list(F, Ts)];
-map_list(_, []) ->
- [].
-
-map_pairs(F, [{T1, T2} | Ps]) ->
- [{map(F, T1), map(F, T2)} | map_pairs(F, Ps)];
-map_pairs(_, []) ->
- [].
-
-
-%% @spec fold(Function, Unit::term(), Tree::cerl()) -> term()
-%%
-%% Function = (cerl(), term()) -> term()
-%%
-%% @doc Does a fold operation over the nodes of the tree. The result
-%% is the value of <code>Function(X1, Function(X2, ... Function(Xn,
-%% Unit) ... ))</code>, where <code>X1, ..., Xn</code> are the nodes
-%% of <code>Tree</code> in a post-order traversal.
-%%
-%% @see mapfold/3
-
-fold(F, S, T) ->
- F(T, fold_1(F, S, T)).
-
-fold_1(F, S, T) ->
- case type(T) of
- literal ->
- case concrete(T) of
- [_ | _] ->
- fold(F, fold(F, S, cons_hd(T)), cons_tl(T));
- V when tuple_size(V) > 0 ->
- fold_list(F, S, tuple_es(T));
- _ ->
- S
- end;
- var ->
- S;
- values ->
- fold_list(F, S, values_es(T));
- cons ->
- fold(F, fold(F, S, cons_hd(T)), cons_tl(T));
- tuple ->
- fold_list(F, S, tuple_es(T));
- 'let' ->
- fold(F, fold(F, fold_list(F, S, let_vars(T)),
- let_arg(T)),
- let_body(T));
- seq ->
- fold(F, fold(F, S, seq_arg(T)), seq_body(T));
- apply ->
- fold_list(F, fold(F, S, apply_op(T)), apply_args(T));
- call ->
- fold_list(F, fold(F, fold(F, S, call_module(T)),
- call_name(T)),
- call_args(T));
- primop ->
- fold_list(F, fold(F, S, primop_name(T)), primop_args(T));
- 'case' ->
- fold_list(F, fold(F, S, case_arg(T)), case_clauses(T));
- clause ->
- fold(F, fold(F, fold_list(F, S, clause_pats(T)),
- clause_guard(T)),
- clause_body(T));
- alias ->
- fold(F, fold(F, S, alias_var(T)), alias_pat(T));
- 'fun' ->
- fold(F, fold_list(F, S, fun_vars(T)), fun_body(T));
- 'receive' ->
- fold(F, fold(F, fold_list(F, S, receive_clauses(T)),
- receive_timeout(T)),
- receive_action(T));
- 'try' ->
- fold(F, fold_list(F, fold(F, fold_list(F, fold(F, S, try_arg(T)),
- try_vars(T)),
- try_body(T)),
- try_evars(T)),
- try_handler(T));
- 'catch' ->
- fold(F, S, catch_body(T));
- binary ->
- fold_list(F, S, binary_segments(T));
- bitstr ->
- fold(F,
- fold(F,
- fold(F,
- fold(F,
- fold(F, S, bitstr_val(T)),
- bitstr_size(T)),
- bitstr_unit(T)),
- bitstr_type(T)),
- bitstr_flags(T));
- letrec ->
- fold(F, fold_pairs(F, S, letrec_defs(T)), letrec_body(T));
- module ->
- fold_pairs(F,
- fold_pairs(F,
- fold_list(F,
- fold(F, S, module_name(T)),
- module_exports(T)),
- module_attrs(T)),
- module_defs(T))
- end.
-
-fold_list(F, S, [T | Ts]) ->
- fold_list(F, fold(F, S, T), Ts);
-fold_list(_, S, []) ->
- S.
-
-fold_pairs(F, S, [{T1, T2} | Ps]) ->
- fold_pairs(F, fold(F, fold(F, S, T1), T2), Ps);
-fold_pairs(_, S, []) ->
- S.
-
-
-%% @spec mapfold(Function, Initial::term(), Tree::cerl()) ->
-%% {cerl(), term()}
-%%
-%% Function = (cerl(), term()) -> {cerl(), term()}
-%%
-%% @doc Does a combined map/fold operation on the nodes of the
-%% tree. This is similar to <code>map/2</code>, but also propagates a
-%% value from each application of <code>Function</code> to the next,
-%% starting with the given value <code>Initial</code>, while doing a
-%% post-order traversal of the tree, much like <code>fold/3</code>.
-%%
-%% @see map/2
-%% @see fold/3
-
-mapfold(F, S0, T) ->
- case type(T) of
- literal ->
- case concrete(T) of
- [_ | _] ->
- {T1, S1} = mapfold(F, S0, cons_hd(T)),
- {T2, S2} = mapfold(F, S1, cons_tl(T)),
- F(update_c_cons(T, T1, T2), S2);
- V when tuple_size(V) > 0 ->
- {Ts, S1} = mapfold_list(F, S0, tuple_es(T)),
- F(update_c_tuple(T, Ts), S1);
- _ ->
- F(T, S0)
- end;
- var ->
- F(T, S0);
- values ->
- {Ts, S1} = mapfold_list(F, S0, values_es(T)),
- F(update_c_values(T, Ts), S1);
- cons ->
- {T1, S1} = mapfold(F, S0, cons_hd(T)),
- {T2, S2} = mapfold(F, S1, cons_tl(T)),
- F(update_c_cons_skel(T, T1, T2), S2);
- tuple ->
- {Ts, S1} = mapfold_list(F, S0, tuple_es(T)),
- F(update_c_tuple_skel(T, Ts), S1);
- 'let' ->
- {Vs, S1} = mapfold_list(F, S0, let_vars(T)),
- {A, S2} = mapfold(F, S1, let_arg(T)),
- {B, S3} = mapfold(F, S2, let_body(T)),
- F(update_c_let(T, Vs, A, B), S3);
- seq ->
- {A, S1} = mapfold(F, S0, seq_arg(T)),
- {B, S2} = mapfold(F, S1, seq_body(T)),
- F(update_c_seq(T, A, B), S2);
- apply ->
- {E, S1} = mapfold(F, S0, apply_op(T)),
- {As, S2} = mapfold_list(F, S1, apply_args(T)),
- F(update_c_apply(T, E, As), S2);
- call ->
- {M, S1} = mapfold(F, S0, call_module(T)),
- {N, S2} = mapfold(F, S1, call_name(T)),
- {As, S3} = mapfold_list(F, S2, call_args(T)),
- F(update_c_call(T, M, N, As), S3);
- primop ->
- {N, S1} = mapfold(F, S0, primop_name(T)),
- {As, S2} = mapfold_list(F, S1, primop_args(T)),
- F(update_c_primop(T, N, As), S2);
- 'case' ->
- {A, S1} = mapfold(F, S0, case_arg(T)),
- {Cs, S2} = mapfold_list(F, S1, case_clauses(T)),
- F(update_c_case(T, A, Cs), S2);
- clause ->
- {Ps, S1} = mapfold_list(F, S0, clause_pats(T)),
- {G, S2} = mapfold(F, S1, clause_guard(T)),
- {B, S3} = mapfold(F, S2, clause_body(T)),
- F(update_c_clause(T, Ps, G, B), S3);
- alias ->
- {V, S1} = mapfold(F, S0, alias_var(T)),
- {P, S2} = mapfold(F, S1, alias_pat(T)),
- F(update_c_alias(T, V, P), S2);
- 'fun' ->
- {Vs, S1} = mapfold_list(F, S0, fun_vars(T)),
- {B, S2} = mapfold(F, S1, fun_body(T)),
- F(update_c_fun(T, Vs, B), S2);
- 'receive' ->
- {Cs, S1} = mapfold_list(F, S0, receive_clauses(T)),
- {E, S2} = mapfold(F, S1, receive_timeout(T)),
- {A, S3} = mapfold(F, S2, receive_action(T)),
- F(update_c_receive(T, Cs, E, A), S3);
- 'try' ->
- {E, S1} = mapfold(F, S0, try_arg(T)),
- {Vs, S2} = mapfold_list(F, S1, try_vars(T)),
- {B, S3} = mapfold(F, S2, try_body(T)),
- {Evs, S4} = mapfold_list(F, S3, try_evars(T)),
- {H, S5} = mapfold(F, S4, try_handler(T)),
- F(update_c_try(T, E, Vs, B, Evs, H), S5);
- 'catch' ->
- {B, S1} = mapfold(F, S0, catch_body(T)),
- F(update_c_catch(T, B), S1);
- binary ->
- {Ds, S1} = mapfold_list(F, S0, binary_segments(T)),
- F(update_c_binary(T, Ds), S1);
- bitstr ->
- {Val, S1} = mapfold(F, S0, bitstr_val(T)),
- {Size, S2} = mapfold(F, S1, bitstr_size(T)),
- {Unit, S3} = mapfold(F, S2, bitstr_unit(T)),
- {Type, S4} = mapfold(F, S3, bitstr_type(T)),
- {Flags, S5} = mapfold(F, S4, bitstr_flags(T)),
- F(update_c_bitstr(T, Val, Size, Unit, Type, Flags), S5);
- letrec ->
- {Ds, S1} = mapfold_pairs(F, S0, letrec_defs(T)),
- {B, S2} = mapfold(F, S1, letrec_body(T)),
- F(update_c_letrec(T, Ds, B), S2);
- module ->
- {N, S1} = mapfold(F, S0, module_name(T)),
- {Es, S2} = mapfold_list(F, S1, module_exports(T)),
- {As, S3} = mapfold_pairs(F, S2, module_attrs(T)),
- {Ds, S4} = mapfold_pairs(F, S3, module_defs(T)),
- F(update_c_module(T, N, Es, As, Ds), S4)
- end.
-
-mapfold_list(F, S0, [T | Ts]) ->
- {T1, S1} = mapfold(F, S0, T),
- {Ts1, S2} = mapfold_list(F, S1, Ts),
- {[T1 | Ts1], S2};
-mapfold_list(_, S, []) ->
- {[], S}.
-
-mapfold_pairs(F, S0, [{T1, T2} | Ps]) ->
- {T3, S1} = mapfold(F, S0, T1),
- {T4, S2} = mapfold(F, S1, T2),
- {Ps1, S3} = mapfold_pairs(F, S2, Ps),
- {[{T3, T4} | Ps1], S3};
-mapfold_pairs(_, S, []) ->
- {[], S}.
-
-
-%% ---------------------------------------------------------------------
-
-%% @spec variables(Tree::cerl()) -> [var_name()]
-%%
-%% var_name() = integer() | atom() | {atom(), integer()}
-%%
-%% @doc Returns an ordered-set list of the names of all variables in
-%% the syntax tree. (This includes function name variables.) An
-%% exception is thrown if <code>Tree</code> does not represent a
-%% well-formed Core Erlang syntax tree.
-%%
-%% @see free_variables/1
-
-variables(T) ->
- variables(T, false).
-
-
-%% @spec free_variables(Tree::cerl()) -> [var_name()]
-%%
-%% @doc Like <code>variables/1</code>, but only includes variables
-%% that are free in the tree.
-%%
-%% @see variables/1
-
-free_variables(T) ->
- variables(T, true).
-
-
-%% This is not exported
-
-variables(T, S) ->
- case type(T) of
- literal ->
- [];
- var ->
- [var_name(T)];
- values ->
- vars_in_list(values_es(T), S);
- cons ->
- ordsets:union(variables(cons_hd(T), S),
- variables(cons_tl(T), S));
- tuple ->
- vars_in_list(tuple_es(T), S);
- 'let' ->
- Vs = variables(let_body(T), S),
- Vs1 = var_list_names(let_vars(T)),
- Vs2 = case S of
- true ->
- ordsets:subtract(Vs, Vs1);
- false ->
- ordsets:union(Vs, Vs1)
- end,
- ordsets:union(variables(let_arg(T), S), Vs2);
- seq ->
- ordsets:union(variables(seq_arg(T), S),
- variables(seq_body(T), S));
- apply ->
- ordsets:union(
- variables(apply_op(T), S),
- vars_in_list(apply_args(T), S));
- call ->
- ordsets:union(variables(call_module(T), S),
- ordsets:union(
- variables(call_name(T), S),
- vars_in_list(call_args(T), S)));
- primop ->
- vars_in_list(primop_args(T), S);
- 'case' ->
- ordsets:union(variables(case_arg(T), S),
- vars_in_list(case_clauses(T), S));
- clause ->
- Vs = ordsets:union(variables(clause_guard(T), S),
- variables(clause_body(T), S)),
- Vs1 = vars_in_list(clause_pats(T), S),
- case S of
- true ->
- ordsets:subtract(Vs, Vs1);
- false ->
- ordsets:union(Vs, Vs1)
- end;
- alias ->
- ordsets:add_element(var_name(alias_var(T)),
- variables(alias_pat(T)));
- 'fun' ->
- Vs = variables(fun_body(T), S),
- Vs1 = var_list_names(fun_vars(T)),
- case S of
- true ->
- ordsets:subtract(Vs, Vs1);
- false ->
- ordsets:union(Vs, Vs1)
- end;
- 'receive' ->
- ordsets:union(
- vars_in_list(receive_clauses(T), S),
- ordsets:union(variables(receive_timeout(T), S),
- variables(receive_action(T), S)));
- 'try' ->
- Vs = variables(try_body(T), S),
- Vs1 = var_list_names(try_vars(T)),
- Vs2 = case S of
- true ->
- ordsets:subtract(Vs, Vs1);
- false ->
- ordsets:union(Vs, Vs1)
- end,
- Vs3 = variables(try_handler(T), S),
- Vs4 = var_list_names(try_evars(T)),
- Vs5 = case S of
- true ->
- ordsets:subtract(Vs3, Vs4);
- false ->
- ordsets:union(Vs3, Vs4)
- end,
- ordsets:union(variables(try_arg(T), S),
- ordsets:union(Vs2, Vs5));
- 'catch' ->
- variables(catch_body(T), S);
- binary ->
- vars_in_list(binary_segments(T), S);
- bitstr ->
- ordsets:union(variables(bitstr_val(T), S),
- variables(bitstr_size(T), S));
- letrec ->
- Vs = vars_in_defs(letrec_defs(T), S),
- Vs1 = ordsets:union(variables(letrec_body(T), S), Vs),
- Vs2 = var_list_names(letrec_vars(T)),
- case S of
- true ->
- ordsets:subtract(Vs1, Vs2);
- false ->
- ordsets:union(Vs1, Vs2)
- end;
- module ->
- Vs = vars_in_defs(module_defs(T), S),
- Vs1 = ordsets:union(vars_in_list(module_exports(T), S), Vs),
- Vs2 = var_list_names(module_vars(T)),
- case S of
- true ->
- ordsets:subtract(Vs1, Vs2);
- false ->
- ordsets:union(Vs1, Vs2)
- end
- end.
-
-vars_in_list(Ts, S) ->
- vars_in_list(Ts, S, []).
-
-vars_in_list([T | Ts], S, A) ->
- vars_in_list(Ts, S, ordsets:union(variables(T, S), A));
-vars_in_list([], _, A) ->
- A.
-
-%% Note that this function only visits the right-hand side of function
-%% definitions.
-
-vars_in_defs(Ds, S) ->
- vars_in_defs(Ds, S, []).
-
-vars_in_defs([{_, F} | Ds], S, A) ->
- vars_in_defs(Ds, S, ordsets:union(variables(F, S), A));
-vars_in_defs([], _, A) ->
- A.
-
-%% This amounts to insertion sort. Since the lists are generally short,
-%% it is hardly worthwhile to use an asymptotically better sort.
-
-var_list_names(Vs) ->
- var_list_names(Vs, []).
-
-var_list_names([V | Vs], A) ->
- var_list_names(Vs, ordsets:add_element(var_name(V), A));
-var_list_names([], A) ->
- A.
-
-
-%% ---------------------------------------------------------------------
-
-%% label(Tree::cerl()) -> {cerl(), integer()}
-%%
-%% @equiv label(Tree, 0)
-
-label(T) ->
- label(T, 0).
-
-%% @spec label(Tree::cerl(), N::integer()) -> {cerl(), integer()}
-%%
-%% @doc Labels each expression in the tree. A term <code>{label,
-%% L}</code> is prefixed to the annotation list of each expression node,
-%% where L is a unique number for every node, except for variables (and
-%% function name variables) which get the same label if they represent
-%% the same variable. Constant literal nodes are not labeled.
-%%
-%% <p>The returned value is a tuple <code>{NewTree, Max}</code>, where
-%% <code>NewTree</code> is the labeled tree and <code>Max</code> is 1
-%% plus the largest label value used. All previous annotation terms on
-%% the form <code>{label, X}</code> are deleted.</p>
-%%
-%% <p>The values of L used in the tree is a dense range from
-%% <code>N</code> to <code>Max - 1</code>, where <code>N =&lt; Max
-%% =&lt; N + size(Tree)</code>. Note that it is possible that no
-%% labels are used at all, i.e., <code>N = Max</code>.</p>
-%%
-%% <p>Note: All instances of free variables will be given distinct
-%% labels.</p>
-%%
-%% @see label/1
-%% @see size/1
-
-label(T, N) ->
- label(T, N, dict:new()).
-
-label(T, N, Env) ->
- case type(T) of
- literal ->
- %% Constant literals are not labeled.
- {T, N};
- var ->
- case dict:find(var_name(T), Env) of
- {ok, L} ->
- {As, _} = label_ann(T, L),
- N1 = N;
- error ->
- {As, N1} = label_ann(T, N)
- end,
- {set_ann(T, As), N1};
- values ->
- {Ts, N1} = label_list(values_es(T), N, Env),
- {As, N2} = label_ann(T, N1),
- {ann_c_values(As, Ts), N2};
- cons ->
- {T1, N1} = label(cons_hd(T), N, Env),
- {T2, N2} = label(cons_tl(T), N1, Env),
- {As, N3} = label_ann(T, N2),
- {ann_c_cons_skel(As, T1, T2), N3};
- tuple ->
- {Ts, N1} = label_list(tuple_es(T), N, Env),
- {As, N2} = label_ann(T, N1),
- {ann_c_tuple_skel(As, Ts), N2};
- 'let' ->
- {A, N1} = label(let_arg(T), N, Env),
- {Vs, N2, Env1} = label_vars(let_vars(T), N1, Env),
- {B, N3} = label(let_body(T), N2, Env1),
- {As, N4} = label_ann(T, N3),
- {ann_c_let(As, Vs, A, B), N4};
- seq ->
- {A, N1} = label(seq_arg(T), N, Env),
- {B, N2} = label(seq_body(T), N1, Env),
- {As, N3} = label_ann(T, N2),
- {ann_c_seq(As, A, B), N3};
- apply ->
- {E, N1} = label(apply_op(T), N, Env),
- {Es, N2} = label_list(apply_args(T), N1, Env),
- {As, N3} = label_ann(T, N2),
- {ann_c_apply(As, E, Es), N3};
- call ->
- {M, N1} = label(call_module(T), N, Env),
- {F, N2} = label(call_name(T), N1, Env),
- {Es, N3} = label_list(call_args(T), N2, Env),
- {As, N4} = label_ann(T, N3),
- {ann_c_call(As, M, F, Es), N4};
- primop ->
- {F, N1} = label(primop_name(T), N, Env),
- {Es, N2} = label_list(primop_args(T), N1, Env),
- {As, N3} = label_ann(T, N2),
- {ann_c_primop(As, F, Es), N3};
- 'case' ->
- {A, N1} = label(case_arg(T), N, Env),
- {Cs, N2} = label_list(case_clauses(T), N1, Env),
- {As, N3} = label_ann(T, N2),
- {ann_c_case(As, A, Cs), N3};
- clause ->
- {_, N1, Env1} = label_vars(clause_vars(T), N, Env),
- {Ps, N2} = label_list(clause_pats(T), N1, Env1),
- {G, N3} = label(clause_guard(T), N2, Env1),
- {B, N4} = label(clause_body(T), N3, Env1),
- {As, N5} = label_ann(T, N4),
- {ann_c_clause(As, Ps, G, B), N5};
- alias ->
- {V, N1} = label(alias_var(T), N, Env),
- {P, N2} = label(alias_pat(T), N1, Env),
- {As, N3} = label_ann(T, N2),
- {ann_c_alias(As, V, P), N3};
- 'fun' ->
- {Vs, N1, Env1} = label_vars(fun_vars(T), N, Env),
- {B, N2} = label(fun_body(T), N1, Env1),
- {As, N3} = label_ann(T, N2),
- {ann_c_fun(As, Vs, B), N3};
- 'receive' ->
- {Cs, N1} = label_list(receive_clauses(T), N, Env),
- {E, N2} = label(receive_timeout(T), N1, Env),
- {A, N3} = label(receive_action(T), N2, Env),
- {As, N4} = label_ann(T, N3),
- {ann_c_receive(As, Cs, E, A), N4};
- 'try' ->
- {E, N1} = label(try_arg(T), N, Env),
- {Vs, N2, Env1} = label_vars(try_vars(T), N1, Env),
- {B, N3} = label(try_body(T), N2, Env1),
- {Evs, N4, Env2} = label_vars(try_evars(T), N3, Env),
- {H, N5} = label(try_handler(T), N4, Env2),
- {As, N6} = label_ann(T, N5),
- {ann_c_try(As, E, Vs, B, Evs, H), N6};
- 'catch' ->
- {B, N1} = label(catch_body(T), N, Env),
- {As, N2} = label_ann(T, N1),
- {ann_c_catch(As, B), N2};
- binary ->
- {Ds, N1} = label_list(binary_segments(T), N, Env),
- {As, N2} = label_ann(T, N1),
- {ann_c_binary(As, Ds), N2};
- bitstr ->
- {Val, N1} = label(bitstr_val(T), N, Env),
- {Size, N2} = label(bitstr_size(T), N1, Env),
- {Unit, N3} = label(bitstr_unit(T), N2, Env),
- {Type, N4} = label(bitstr_type(T), N3, Env),
- {Flags, N5} = label(bitstr_flags(T), N4, Env),
- {As, N6} = label_ann(T, N5),
- {ann_c_bitstr(As, Val, Size, Unit, Type, Flags), N6};
- letrec ->
- {_, N1, Env1} = label_vars(letrec_vars(T), N, Env),
- {Ds, N2} = label_defs(letrec_defs(T), N1, Env1),
- {B, N3} = label(letrec_body(T), N2, Env1),
- {As, N4} = label_ann(T, N3),
- {ann_c_letrec(As, Ds, B), N4};
- module ->
- %% The module name is not labeled.
- {_, N1, Env1} = label_vars(module_vars(T), N, Env),
- {Ts, N2} = label_defs(module_attrs(T), N1, Env1),
- {Ds, N3} = label_defs(module_defs(T), N2, Env1),
- {Es, N4} = label_list(module_exports(T), N3, Env1),
- {As, N5} = label_ann(T, N4),
- {ann_c_module(As, module_name(T), Es, Ts, Ds), N5}
- end.
-
-label_list([T | Ts], N, Env) ->
- {T1, N1} = label(T, N, Env),
- {Ts1, N2} = label_list(Ts, N1, Env),
- {[T1 | Ts1], N2};
-label_list([], N, _Env) ->
- {[], N}.
-
-label_vars([T | Ts], N, Env) ->
- Env1 = dict:store(var_name(T), N, Env),
- {As, N1} = label_ann(T, N),
- T1 = set_ann(T, As),
- {Ts1, N2, Env2} = label_vars(Ts, N1, Env1),
- {[T1 | Ts1], N2, Env2};
-label_vars([], N, Env) ->
- {[], N, Env}.
-
-label_defs([{F, T} | Ds], N, Env) ->
- {F1, N1} = label(F, N, Env),
- {T1, N2} = label(T, N1, Env),
- {Ds1, N3} = label_defs(Ds, N2, Env),
- {[{F1, T1} | Ds1], N3};
-label_defs([], N, _Env) ->
- {[], N}.
-
-label_ann(T, N) ->
- {[{label, N} | filter_labels(get_ann(T))], N + 1}.
-
-filter_labels([{label, _} | As]) ->
- filter_labels(As);
-filter_labels([A | As]) ->
- [A | filter_labels(As)];
-filter_labels([]) ->
- [].
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/compile.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/compile.erl
deleted file mode 100644
index 4542bf9eb9..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/compile.erl
+++ /dev/null
@@ -1,1109 +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: compile.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
-%%
-%% Purpose: Run the Erlang compiler.
-
--module(compile).
--include("erl_compile.hrl").
--include("core_parse.hrl").
-
-%% High-level interface.
--export([file/1,file/2,format_error/1,iofile/1]).
--export([forms/1,forms/2]).
--export([output_generated/1]).
--export([options/0]).
-
-%% Erlc interface.
--export([compile/3,compile_beam/3,compile_asm/3,compile_core/3]).
-
-
--import(lists, [member/2,reverse/1,keysearch/3,last/1,
- map/2,flatmap/2,foreach/2,foldr/3,any/2,filter/2]).
-
-%% file(FileName)
-%% file(FileName, Options)
-%% Compile the module in file FileName.
-
--define(DEFAULT_OPTIONS, [verbose,report_errors,report_warnings]).
-
--define(pass(P), {P,fun P/1}).
-
-file(File) -> file(File, ?DEFAULT_OPTIONS).
-
-file(File, Opts) when list(Opts) ->
- do_compile({file,File}, Opts++env_default_opts());
-file(File, Opt) ->
- file(File, [Opt|?DEFAULT_OPTIONS]).
-
-forms(File) -> forms(File, ?DEFAULT_OPTIONS).
-
-forms(Forms, Opts) when list(Opts) ->
- do_compile({forms,Forms}, [binary|Opts++env_default_opts()]);
-forms(Forms, Opts) when atom(Opts) ->
- forms(Forms, [Opts|?DEFAULT_OPTIONS]).
-
-env_default_opts() ->
- Key = "ERL_COMPILER_OPTIONS",
- case os:getenv(Key) of
- false -> [];
- Str when list(Str) ->
- case erl_scan:string(Str) of
- {ok,Tokens,_} ->
- case erl_parse:parse_term(Tokens ++ [{dot, 1}]) of
- {ok,List} when list(List) -> List;
- {ok,Term} -> [Term];
- {error,_Reason} ->
- io:format("Ignoring bad term in ~s\n", [Key]),
- []
- end;
- {error, {_,_,_Reason}, _} ->
- io:format("Ignoring bad term in ~s\n", [Key]),
- []
- end
- end.
-
-do_compile(Input, Opts0) ->
- Opts = expand_opts(Opts0),
- Self = self(),
- Serv = spawn_link(fun() -> internal(Self, Input, Opts) end),
- receive
- {Serv,Rep} -> Rep
- end.
-
-%% Given a list of compilation options, returns true if compile:file/2
-%% would have generated a Beam file, false otherwise (if only a binary or a
-%% listing file would have been generated).
-
-output_generated(Opts) ->
- any(fun ({save_binary,_F}) -> true;
- (_Other) -> false
- end, passes(file, expand_opts(Opts))).
-
-expand_opts(Opts) ->
- foldr(fun expand_opt/2, [], Opts).
-
-expand_opt(basic_validation, Os) ->
- [no_code_generation,to_pp,binary|Os];
-expand_opt(strong_validation, Os) ->
- [no_code_generation,to_kernel,binary|Os];
-expand_opt(report, Os) ->
- [report_errors,report_warnings|Os];
-expand_opt(return, Os) ->
- [return_errors,return_warnings|Os];
-expand_opt(r7, Os) ->
- [no_float_opt,no_new_funs,no_new_binaries,no_new_apply|Os];
-expand_opt(O, Os) -> [O|Os].
-
-filter_opts(Opts0) ->
- %% Native code generation is not supported if no_new_funs is given.
- case member(no_new_funs, Opts0) of
- false -> Opts0;
- true -> Opts0 -- [native]
- end.
-
-%% format_error(ErrorDescriptor) -> string()
-
-format_error(no_native_support) ->
- "this system is not configured for native-code compilation.";
-format_error({native, E}) ->
- io_lib:fwrite("native-code compilation failed with reason: ~P.",
- [E, 25]);
-format_error({native_crash, E}) ->
- io_lib:fwrite("native-code compilation crashed with reason: ~P.",
- [E, 25]);
-format_error({open,E}) ->
- io_lib:format("open error '~s'", [file:format_error(E)]);
-format_error({epp,E}) ->
- epp:format_error(E);
-format_error(write_error) ->
- "error writing file";
-format_error({rename,S}) ->
- io_lib:format("error renaming ~s", [S]);
-format_error({parse_transform,M,R}) ->
- io_lib:format("error in parse transform '~s': ~p", [M, R]);
-format_error({core_transform,M,R}) ->
- io_lib:format("error in core transform '~s': ~p", [M, R]);
-format_error({crash,Pass,Reason}) ->
- io_lib:format("internal error in ~p;\ncrash reason: ~p", [Pass,Reason]);
-format_error({bad_return,Pass,Reason}) ->
- io_lib:format("internal error in ~p;\nbad return value: ~p", [Pass,Reason]).
-
-%% The compile state record.
--record(compile, {filename="",
- dir="",
- base="",
- ifile="",
- ofile="",
- module=[],
- code=[],
- core_code=[],
- abstract_code=[], %Abstract code for debugger.
- options=[],
- errors=[],
- warnings=[]}).
-
-internal(Master, Input, Opts) ->
- Master ! {self(),
- case catch internal(Input, Opts) of
- {'EXIT', Reason} ->
- {error, Reason};
- Other ->
- Other
- end}.
-
-internal({forms,Forms}, Opts) ->
- Ps = passes(forms, Opts),
- internal_comp(Ps, "", "", #compile{code=Forms,options=Opts});
-internal({file,File}, Opts) ->
- Ps = passes(file, Opts),
- Compile = #compile{options=Opts},
- case member(from_core, Opts) of
- true -> internal_comp(Ps, File, ".core", Compile);
- false ->
- case member(from_beam, Opts) of
- true ->
- internal_comp(Ps, File, ".beam", Compile);
- false ->
- case member(from_asm, Opts) orelse member(asm, Opts) of
- true ->
- internal_comp(Ps, File, ".S", Compile);
- false ->
- internal_comp(Ps, File, ".erl", Compile)
- end
- end
- end.
-
-internal_comp(Passes, File, Suffix, St0) ->
- Dir = filename:dirname(File),
- Base = filename:basename(File, Suffix),
- St1 = St0#compile{filename=File, dir=Dir, base=Base,
- ifile=erlfile(Dir, Base, Suffix),
- ofile=objfile(Base, St0)},
- Run = case member(time, St1#compile.options) of
- true ->
- io:format("Compiling ~p\n", [File]),
- fun run_tc/2;
- false -> fun({_Name,Fun}, St) -> catch Fun(St) end
- end,
- case fold_comp(Passes, Run, St1) of
- {ok,St2} -> comp_ret_ok(St2);
- {error,St2} -> comp_ret_err(St2)
- end.
-
-fold_comp([{Name,Test,Pass}|Ps], Run, St) ->
- case Test(St) of
- false -> %Pass is not needed.
- fold_comp(Ps, Run, St);
- true -> %Run pass in the usual way.
- fold_comp([{Name,Pass}|Ps], Run, St)
- end;
-fold_comp([{Name,Pass}|Ps], Run, St0) ->
- case Run({Name,Pass}, St0) of
- {ok,St1} -> fold_comp(Ps, Run, St1);
- {error,St1} -> {error,St1};
- {'EXIT',Reason} ->
- Es = [{St0#compile.ifile,[{none,?MODULE,{crash,Name,Reason}}]}],
- {error,St0#compile{errors=St0#compile.errors ++ Es}};
- Other ->
- Es = [{St0#compile.ifile,[{none,?MODULE,{bad_return,Name,Other}}]}],
- {error,St0#compile{errors=St0#compile.errors ++ Es}}
- end;
-fold_comp([], _Run, St) -> {ok,St}.
-
-os_process_size() ->
- case os:type() of
- {unix, sunos} ->
- Size = os:cmd("ps -o vsz -p " ++ os:getpid() ++ " | tail -1"),
- list_to_integer(lib:nonl(Size));
- _ ->
- 0
- end.
-
-run_tc({Name,Fun}, St) ->
- Before0 = statistics(runtime),
- Val = (catch Fun(St)),
- After0 = statistics(runtime),
- {Before_c, _} = Before0,
- {After_c, _} = After0,
- io:format(" ~-30s: ~10.3f s (~w k)\n",
- [Name, (After_c-Before_c) / 1000, os_process_size()]),
- Val.
-
-comp_ret_ok(#compile{code=Code,warnings=Warn,module=Mod,options=Opts}=St) ->
- report_warnings(St),
- Ret1 = case member(binary, Opts) andalso not member(no_code_generation, Opts) of
- true -> [Code];
- false -> []
- end,
- Ret2 = case member(return_warnings, Opts) of
- true -> Ret1 ++ [Warn];
- false -> Ret1
- end,
- list_to_tuple([ok,Mod|Ret2]).
-
-comp_ret_err(St) ->
- report_errors(St),
- report_warnings(St),
- case member(return_errors, St#compile.options) of
- true -> {error,St#compile.errors,St#compile.warnings};
- false -> error
- end.
-
-%% passes(form|file, [Option]) -> [{Name,PassFun}]
-%% Figure out which passes that need to be run.
-
-passes(forms, Opts) ->
- select_passes(standard_passes(), Opts);
-passes(file, Opts) ->
- case member(from_beam, Opts) of
- true ->
- Ps = [?pass(read_beam_file)|binary_passes()],
- select_passes(Ps, Opts);
- false ->
- Ps = case member(from_asm, Opts) orelse member(asm, Opts) of
- true ->
- [?pass(beam_consult_asm)|asm_passes()];
- false ->
- case member(from_core, Opts) of
- true ->
- [?pass(parse_core)|core_passes()];
- false ->
- [?pass(parse_module)|standard_passes()]
- end
- end,
- Fs = select_passes(Ps, Opts),
-
- %% If the last pass saves the resulting binary to a file,
- %% insert a first pass to remove the file.
- case last(Fs) of
- {save_binary,_Fun} -> [?pass(remove_file)|Fs];
- _Other -> Fs
- end
- end.
-
-%% select_passes([Command], Opts) -> [{Name,Function}]
-%% Interpret the lists of commands to return a pure list of passes.
-%%
-%% Command can be one of:
-%%
-%% {pass,Mod} Will be expanded to a call to the external
-%% function Mod:module(Code, Options). This
-%% function must transform the code and return
-%% {ok,NewCode} or {error,Term}.
-%% Example: {pass,beam_codegen}
-%%
-%% {Name,Fun} Name is an atom giving the name of the pass.
-%% Fun is an 'fun' taking one argument: a compile record.
-%% The fun should return {ok,NewCompileRecord} or
-%% {error,NewCompileRecord}.
-%% Note: ?pass(Name) is equvivalent to {Name,fun Name/1}.
-%% Example: ?pass(parse_module)
-%%
-%% {Name,Test,Fun} Like {Name,Fun} above, but the pass will be run
-%% (and listed by the `time' option) only if Test(St)
-%% returns true.
-%%
-%% {src_listing,Ext} Produces an Erlang source listing with the
-%% the file extension Ext. (Ext should not contain
-%% a period.) No more passes will be run.
-%%
-%% {listing,Ext} Produce an listing of the terms in the internal
-%% representation. The extension of the listing
-%% file will be Ext. (Ext should not contain
-%% a period.) No more passes will be run.
-%%
-%% {done,Ext} End compilation at this point. Produce a listing
-%% as with {listing,Ext}, unless 'binary' is
-%% specified, in which case the current
-%% representation of the code is returned without
-%% creating an output file.
-%%
-%% {iff,Flag,Cmd} If the given Flag is given in the option list,
-%% Cmd will be interpreted as a command.
-%% Otherwise, Cmd will be ignored.
-%% Example: {iff,dcg,{listing,"codegen}}
-%%
-%% {unless,Flag,Cmd} If the given Flag is NOT given in the option list,
-%% Cmd will be interpreted as a command.
-%% Otherwise, Cmd will be ignored.
-%% Example: {unless,no_kernopt,{pass,sys_kernopt}}
-%%
-
-select_passes([{pass,Mod}|Ps], Opts) ->
- F = fun(St) ->
- case catch Mod:module(St#compile.code, St#compile.options) of
- {ok,Code} ->
- {ok,St#compile{code=Code}};
- {error,Es} ->
- {error,St#compile{errors=St#compile.errors ++ Es}}
- end
- end,
- [{Mod,F}|select_passes(Ps, Opts)];
-select_passes([{src_listing,Ext}|_], _Opts) ->
- [{listing,fun (St) -> src_listing(Ext, St) end}];
-select_passes([{listing,Ext}|_], _Opts) ->
- [{listing,fun (St) -> listing(Ext, St) end}];
-select_passes([{done,Ext}|_], Opts) ->
- select_passes([{unless,binary,{listing,Ext}}], Opts);
-select_passes([{iff,Flag,Pass}|Ps], Opts) ->
- select_cond(Flag, true, Pass, Ps, Opts);
-select_passes([{unless,Flag,Pass}|Ps], Opts) ->
- select_cond(Flag, false, Pass, Ps, Opts);
-select_passes([{_,Fun}=P|Ps], Opts) when is_function(Fun) ->
- [P|select_passes(Ps, Opts)];
-select_passes([{_,Test,Fun}=P|Ps], Opts) when is_function(Test),
- is_function(Fun) ->
- [P|select_passes(Ps, Opts)];
-select_passes([], _Opts) ->
- [];
-select_passes([List|Ps], Opts) when is_list(List) ->
- case select_passes(List, Opts) of
- [] -> select_passes(Ps, Opts);
- Nested ->
- case last(Nested) of
- {listing,_Fun} -> Nested;
- _Other -> Nested ++ select_passes(Ps, Opts)
- end
- end.
-
-select_cond(Flag, ShouldBe, Pass, Ps, Opts) ->
- ShouldNotBe = not ShouldBe,
- case member(Flag, Opts) of
- ShouldBe -> select_passes([Pass|Ps], Opts);
- ShouldNotBe -> select_passes(Ps, Opts)
- end.
-
-%% The standard passes (almost) always run.
-
-standard_passes() ->
- [?pass(transform_module),
- {iff,'dpp',{listing,"pp"}},
- ?pass(lint_module),
- {iff,'P',{src_listing,"P"}},
- {iff,'to_pp',{done,"P"}},
-
- {iff,'dabstr',{listing,"abstr"}},
- {iff,debug_info,?pass(save_abstract_code)},
-
- ?pass(expand_module),
- {iff,'dexp',{listing,"expand"}},
- {iff,'E',{src_listing,"E"}},
- {iff,'to_exp',{done,"E"}},
-
- %% Conversion to Core Erlang.
- ?pass(core_module),
- {iff,'dcore',{listing,"core"}},
- {iff,'to_core0',{done,"core"}}
- | core_passes()].
-
-core_passes() ->
- %% Optimization and transforms of Core Erlang code.
- [{unless,no_copt,
- [{core_old_inliner,fun test_old_inliner/1,fun core_old_inliner/1},
- ?pass(core_fold_module),
- {core_inline_module,fun test_core_inliner/1,fun core_inline_module/1},
- {core_fold_after_inline,fun test_core_inliner/1,fun core_fold_module/1},
- ?pass(core_transforms)]},
- {iff,dcopt,{listing,"copt"}},
- {iff,'to_core',{done,"core"}}
- | kernel_passes()].
-
-kernel_passes() ->
- %% Destructive setelement/3 optimization and core lint.
- [?pass(core_dsetel_module),
- {iff,clint,?pass(core_lint_module)},
- {iff,core,?pass(save_core_code)},
-
- %% Kernel Erlang and code generation.
- ?pass(kernel_module),
- {iff,dkern,{listing,"kernel"}},
- {iff,'to_kernel',{done,"kernel"}},
- {pass,v3_life},
- {iff,dlife,{listing,"life"}},
- {pass,v3_codegen},
- {iff,dcg,{listing,"codegen"}}
- | asm_passes()].
-
-asm_passes() ->
- %% Assembly level optimisations.
- [{unless,no_postopt,
- [{pass,beam_block},
- {iff,dblk,{listing,"block"}},
- {unless,no_bopt,{pass,beam_bool}},
- {iff,dbool,{listing,"bool"}},
- {unless,no_topt,{pass,beam_type}},
- {iff,dtype,{listing,"type"}},
- {pass,beam_dead}, %Must always run since it splits blocks.
- {iff,ddead,{listing,"dead"}},
- {unless,no_jopt,{pass,beam_jump}},
- {iff,djmp,{listing,"jump"}},
- {pass,beam_clean},
- {iff,dclean,{listing,"clean"}},
- {pass,beam_flatten}]},
-
- %% If post optimizations are turned off, we still coalesce
- %% adjacent labels and remove unused labels to keep the
- %% HiPE compiler happy.
- {iff,no_postopt,
- [?pass(beam_unused_labels),
- {pass,beam_clean}]},
-
- {iff,dopt,{listing,"optimize"}},
- {iff,'S',{listing,"S"}},
- {iff,'to_asm',{done,"S"}},
-
- {pass,beam_validator},
- ?pass(beam_asm)
- | binary_passes()].
-
-binary_passes() ->
- [{native_compile,fun test_native/1,fun native_compile/1},
- {unless,binary,?pass(save_binary)}].
-
-%%%
-%%% Compiler passes.
-%%%
-
-%% Remove the target file so we don't have an old one if the compilation fail.
-remove_file(St) ->
- file:delete(St#compile.ofile),
- {ok,St}.
-
--record(asm_module, {module,
- exports,
- labels,
- functions=[],
- cfun,
- code,
- attributes=[]}).
-
-preprocess_asm_forms(Forms) ->
- R = #asm_module{},
- R1 = collect_asm(Forms, R),
- {R1#asm_module.module,
- {R1#asm_module.module,
- R1#asm_module.exports,
- R1#asm_module.attributes,
- R1#asm_module.functions,
- R1#asm_module.labels}}.
-
-collect_asm([], R) ->
- case R#asm_module.cfun of
- undefined ->
- R;
- {A,B,C} ->
- R#asm_module{functions=R#asm_module.functions++
- [{function,A,B,C,R#asm_module.code}]}
- end;
-collect_asm([{module,M} | Rest], R) ->
- collect_asm(Rest, R#asm_module{module=M});
-collect_asm([{exports,M} | Rest], R) ->
- collect_asm(Rest, R#asm_module{exports=M});
-collect_asm([{labels,M} | Rest], R) ->
- collect_asm(Rest, R#asm_module{labels=M});
-collect_asm([{function,A,B,C} | Rest], R) ->
- R1 = case R#asm_module.cfun of
- undefined ->
- R;
- {A0,B0,C0} ->
- R#asm_module{functions=R#asm_module.functions++
- [{function,A0,B0,C0,R#asm_module.code}]}
- end,
- collect_asm(Rest, R1#asm_module{cfun={A,B,C}, code=[]});
-collect_asm([{attributes, Attr} | Rest], R) ->
- collect_asm(Rest, R#asm_module{attributes=Attr});
-collect_asm([X | Rest], R) ->
- collect_asm(Rest, R#asm_module{code=R#asm_module.code++[X]}).
-
-beam_consult_asm(St) ->
- case file:consult(St#compile.ifile) of
- {ok, Forms0} ->
- {Module, Forms} = preprocess_asm_forms(Forms0),
- {ok,St#compile{module=Module, code=Forms}};
- {error,E} ->
- Es = [{St#compile.ifile,[{none,?MODULE,{open,E}}]}],
- {error,St#compile{errors=St#compile.errors ++ Es}}
- end.
-
-read_beam_file(St) ->
- case file:read_file(St#compile.ifile) of
- {ok,Beam} ->
- Infile = St#compile.ifile,
- case is_too_old(Infile) of
- true ->
- {ok,St#compile{module=none,code=none}};
- false ->
- Mod0 = filename:rootname(filename:basename(Infile)),
- Mod = list_to_atom(Mod0),
- {ok,St#compile{module=Mod,code=Beam,ofile=Infile}}
- end;
- {error,E} ->
- Es = [{St#compile.ifile,[{none,?MODULE,{open,E}}]}],
- {error,St#compile{errors=St#compile.errors ++ Es}}
- end.
-
-is_too_old(BeamFile) ->
- case beam_lib:chunks(BeamFile, ["CInf"]) of
- {ok,{_,[{"CInf",Term0}]}} ->
- Term = binary_to_term(Term0),
- Opts = proplists:get_value(options, Term, []),
- lists:member(no_new_funs, Opts);
- _ -> false
- end.
-
-parse_module(St) ->
- Opts = St#compile.options,
- Cwd = ".",
- IncludePath = [Cwd, St#compile.dir|inc_paths(Opts)],
- Tab = ets:new(compiler__tab, [protected,named_table]),
- ets:insert(Tab, {compiler_options,Opts}),
- R = epp:parse_file(St#compile.ifile, IncludePath, pre_defs(Opts)),
- ets:delete(Tab),
- case R of
- {ok,Forms} ->
- {ok,St#compile{code=Forms}};
- {error,E} ->
- Es = [{St#compile.ifile,[{none,?MODULE,{epp,E}}]}],
- {error,St#compile{errors=St#compile.errors ++ Es}}
- end.
-
-parse_core(St) ->
- case file:read_file(St#compile.ifile) of
- {ok,Bin} ->
- case core_scan:string(binary_to_list(Bin)) of
- {ok,Toks,_} ->
- case core_parse:parse(Toks) of
- {ok,Mod} ->
- Name = (Mod#c_module.name)#c_atom.val,
- {ok,St#compile{module=Name,code=Mod}};
- {error,E} ->
- Es = [{St#compile.ifile,[E]}],
- {error,St#compile{errors=St#compile.errors ++ Es}}
- end;
- {error,E,_} ->
- Es = [{St#compile.ifile,[E]}],
- {error,St#compile{errors=St#compile.errors ++ Es}}
- end;
- {error,E} ->
- Es = [{St#compile.ifile,[{none,compile,{open,E}}]}],
- {error,St#compile{errors=St#compile.errors ++ Es}}
- end.
-
-compile_options([{attribute,_L,compile,C}|Fs]) when is_list(C) ->
- C ++ compile_options(Fs);
-compile_options([{attribute,_L,compile,C}|Fs]) ->
- [C|compile_options(Fs)];
-compile_options([_F|Fs]) -> compile_options(Fs);
-compile_options([]) -> [].
-
-transforms(Os) -> [ M || {parse_transform,M} <- Os ].
-
-transform_module(St) ->
- %% Extract compile options from code into options field.
- Ts = transforms(St#compile.options ++ compile_options(St#compile.code)),
- foldl_transform(St, Ts).
-
-foldl_transform(St, [T|Ts]) ->
- Name = "transform " ++ atom_to_list(T),
- Fun = fun(S) -> T:parse_transform(S#compile.code, S#compile.options) end,
- Run = case member(time, St#compile.options) of
- true -> fun run_tc/2;
- false -> fun({_Name,F}, S) -> catch F(S) end
- end,
- case Run({Name, Fun}, St) of
- {error,Es,Ws} ->
- {error,St#compile{warnings=St#compile.warnings ++ Ws,
- errors=St#compile.errors ++ Es}};
- {'EXIT',R} ->
- Es = [{St#compile.ifile,[{none,compile,{parse_transform,T,R}}]}],
- {error,St#compile{errors=St#compile.errors ++ Es}};
- Forms ->
- foldl_transform(St#compile{code=Forms}, Ts)
- end;
-foldl_transform(St, []) -> {ok,St}.
-
-get_core_transforms(Opts) -> [M || {core_transform,M} <- Opts].
-
-core_transforms(St) ->
- %% The options field holds the complete list of options at this
-
- Ts = get_core_transforms(St#compile.options),
- foldl_core_transforms(St, Ts).
-
-foldl_core_transforms(St, [T|Ts]) ->
- Name = "core transform " ++ atom_to_list(T),
- Fun = fun(S) -> T:core_transform(S#compile.code, S#compile.options) end,
- Run = case member(time, St#compile.options) of
- true -> fun run_tc/2;
- false -> fun({_Name,F}, S) -> catch F(S) end
- end,
- case Run({Name, Fun}, St) of
- {'EXIT',R} ->
- Es = [{St#compile.ifile,[{none,compile,{core_transform,T,R}}]}],
- {error,St#compile{errors=St#compile.errors ++ Es}};
- Forms ->
- foldl_core_transforms(St#compile{code=Forms}, Ts)
- end;
-foldl_core_transforms(St, []) -> {ok,St}.
-
-%%% Fetches the module name from a list of forms. The module attribute must
-%%% be present.
-get_module([{attribute,_,module,{M,_As}} | _]) -> M;
-get_module([{attribute,_,module,M} | _]) -> M;
-get_module([_ | Rest]) ->
- get_module(Rest).
-
-%%% A #compile state is returned, where St.base has been filled in
-%%% with the module name from Forms, as a string, in case it wasn't
-%%% set in St (i.e., it was "").
-add_default_base(St, Forms) ->
- F = St#compile.filename,
- case F of
- "" ->
- M = get_module(Forms),
- St#compile{base = atom_to_list(M)};
- _ ->
- St
- end.
-
-lint_module(St) ->
- case erl_lint:module(St#compile.code,
- St#compile.ifile, St#compile.options) of
- {ok,Ws} ->
- %% Insert name of module as base name, if needed. This is
- %% for compile:forms to work with listing files.
- St1 = add_default_base(St, St#compile.code),
- {ok,St1#compile{warnings=St1#compile.warnings ++ Ws}};
- {error,Es,Ws} ->
- {error,St#compile{warnings=St#compile.warnings ++ Ws,
- errors=St#compile.errors ++ Es}}
- end.
-
-core_lint_module(St) ->
- case core_lint:module(St#compile.code, St#compile.options) of
- {ok,Ws} ->
- {ok,St#compile{warnings=St#compile.warnings ++ Ws}};
- {error,Es,Ws} ->
- {error,St#compile{warnings=St#compile.warnings ++ Ws,
- errors=St#compile.errors ++ Es}}
- end.
-
-%% expand_module(State) -> State'
-%% Do the common preprocessing of the input forms.
-
-expand_module(#compile{code=Code,options=Opts0}=St0) ->
- {Mod,Exp,Forms,Opts1} = sys_pre_expand:module(Code, Opts0),
- Opts2 = expand_opts(Opts1),
- Opts = filter_opts(Opts2),
- {ok,St0#compile{module=Mod,options=Opts,code={Mod,Exp,Forms}}}.
-
-core_module(#compile{code=Code0,options=Opts,ifile=File}=St) ->
- {ok,Code,Ws} = v3_core:module(Code0, Opts),
- {ok,St#compile{code=Code,warnings=St#compile.warnings ++ [{File,Ws}]}}.
-
-core_fold_module(#compile{code=Code0,options=Opts,ifile=File}=St) ->
- {ok,Code,Ws} = sys_core_fold:module(Code0, Opts),
- {ok,St#compile{code=Code,warnings=St#compile.warnings ++ [{File,Ws}]}}.
-
-test_old_inliner(#compile{options=Opts}) ->
- %% The point of this test is to avoid loading the old inliner
- %% if we know that it will not be used.
- case any(fun(no_inline) -> true;
- (_) -> false
- end, Opts) of
- true -> false;
- false ->
- any(fun({inline,_}) -> true;
- (_) -> false
- end, Opts)
- end.
-
-test_core_inliner(#compile{options=Opts}) ->
- case any(fun(no_inline) -> true;
- (_) -> false
- end, Opts) of
- true -> false;
- false ->
- any(fun(inline) -> true;
- (_) -> false
- end, Opts)
- end.
-
-core_old_inliner(#compile{code=Code0,options=Opts}=St) ->
- case catch sys_core_inline:module(Code0, Opts) of
- {ok,Code} ->
- {ok,St#compile{code=Code}};
- {error,Es} ->
- {error,St#compile{errors=St#compile.errors ++ Es}}
- end.
-
-core_inline_module(#compile{code=Code0,options=Opts}=St) ->
- Code = cerl_inline:core_transform(Code0, Opts),
- {ok,St#compile{code=Code}}.
-
-core_dsetel_module(#compile{code=Code0,options=Opts}=St) ->
- {ok,Code} = sys_core_dsetel:module(Code0, Opts),
- {ok,St#compile{code=Code}}.
-
-kernel_module(#compile{code=Code0,options=Opts,ifile=File}=St) ->
- {ok,Code,Ws} = v3_kernel:module(Code0, Opts),
- {ok,St#compile{code=Code,warnings=St#compile.warnings ++ [{File,Ws}]}}.
-
-save_abstract_code(St) ->
- {ok,St#compile{abstract_code=abstract_code(St)}}.
-
-abstract_code(#compile{code=Code}) ->
- Abstr = {raw_abstract_v1,Code},
- case catch erlang:term_to_binary(Abstr, [compressed]) of
- {'EXIT',_} -> term_to_binary(Abstr);
- Other -> Other
- end.
-
-save_core_code(St) ->
- {ok,St#compile{core_code=cerl:from_records(St#compile.code)}}.
-
-beam_unused_labels(#compile{code=Code0}=St) ->
- Code = beam_jump:module_labels(Code0),
- {ok,St#compile{code=Code}}.
-
-beam_asm(#compile{ifile=File,code=Code0,abstract_code=Abst,options=Opts0}=St) ->
- Source = filename:absname(File),
- Opts = filter(fun is_informative_option/1, Opts0),
- case beam_asm:module(Code0, Abst, Source, Opts) of
- {ok,Code} -> {ok,St#compile{code=Code,abstract_code=[]}};
- {error,Es} -> {error,St#compile{errors=St#compile.errors ++ Es}}
- end.
-
-test_native(#compile{options=Opts}) ->
- %% This test must be made late, because the r7 or no_new_funs options
- %% will turn off the native option.
- member(native, Opts).
-
-native_compile(#compile{code=none}=St) -> {ok,St};
-native_compile(St) ->
- case erlang:system_info(hipe_architecture) of
- undefined ->
- Ws = [{St#compile.ifile,[{none,compile,no_native_support}]}],
- {ok,St#compile{warnings=St#compile.warnings ++ Ws}};
- _ ->
- native_compile_1(St)
- end.
-
-native_compile_1(St) ->
- Opts0 = [no_new_binaries|St#compile.options],
- IgnoreErrors = member(ignore_native_errors, Opts0),
- Opts = case keysearch(hipe, 1, Opts0) of
- {value,{hipe,L}} when list(L) -> L;
- {value,{hipe,X}} -> [X];
- _ -> []
- end,
- case catch hipe:compile(St#compile.module,
- St#compile.core_code,
- St#compile.code,
- Opts) of
- {ok, {Type,Bin}} when binary(Bin) ->
- {ok, embed_native_code(St, {Type,Bin})};
- {error, R} ->
- case IgnoreErrors of
- true ->
- Ws = [{St#compile.ifile,[{none,?MODULE,{native,R}}]}],
- {ok,St#compile{warnings=St#compile.warnings ++ Ws}};
- false ->
- Es = [{St#compile.ifile,[{none,?MODULE,{native,R}}]}],
- {error,St#compile{errors=St#compile.errors ++ Es}}
- end;
- {'EXIT',R} ->
- case IgnoreErrors of
- true ->
- Ws = [{St#compile.ifile,[{none,?MODULE,{native_crash,R}}]}],
- {ok,St#compile{warnings=St#compile.warnings ++ Ws}};
- false ->
- exit(R)
- end
- end.
-
-embed_native_code(St, {Architecture,NativeCode}) ->
- {ok, _, Chunks0} = beam_lib:all_chunks(St#compile.code),
- ChunkName = hipe_unified_loader:chunk_name(Architecture),
- Chunks1 = lists:keydelete(ChunkName, 1, Chunks0),
- Chunks = Chunks1 ++ [{ChunkName,NativeCode}],
- {ok, BeamPlusNative} = beam_lib:build_module(Chunks),
- St#compile{code=BeamPlusNative}.
-
-%% Returns true if the option is informative and therefore should be included
-%% in the option list of the compiled module.
-
-is_informative_option(beam) -> false;
-is_informative_option(report_warnings) -> false;
-is_informative_option(report_errors) -> false;
-is_informative_option(binary) -> false;
-is_informative_option(verbose) -> false;
-is_informative_option(_) -> true.
-
-save_binary(#compile{code=none}=St) -> {ok,St};
-save_binary(St) ->
- Tfile = tmpfile(St#compile.ofile), %Temp working file
- case write_binary(Tfile, St#compile.code, St) of
- ok ->
- case file:rename(Tfile, St#compile.ofile) of
- ok ->
- {ok,St};
- {error,_Error} ->
- file:delete(Tfile),
- Es = [{St#compile.ofile,[{none,?MODULE,{rename,Tfile}}]}],
- {error,St#compile{errors=St#compile.errors ++ Es}}
- end;
- {error,_Error} ->
- Es = [{Tfile,[{compile,write_error}]}],
- {error,St#compile{errors=St#compile.errors ++ Es}}
- end.
-
-write_binary(Name, Bin, St) ->
- Opts = case member(compressed, St#compile.options) of
- true -> [compressed];
- false -> []
- end,
- case file:write_file(Name, Bin, Opts) of
- ok -> ok;
- {error,_}=Error -> Error
- end.
-
-%% report_errors(State) -> ok
-%% report_warnings(State) -> ok
-
-report_errors(St) ->
- case member(report_errors, St#compile.options) of
- true ->
- foreach(fun ({{F,_L},Eds}) -> list_errors(F, Eds);
- ({F,Eds}) -> list_errors(F, Eds) end,
- St#compile.errors);
- false -> ok
- end.
-
-report_warnings(#compile{options=Opts,warnings=Ws0}) ->
- case member(report_warnings, Opts) of
- true ->
- Ws1 = flatmap(fun({{F,_L},Eds}) -> format_message(F, Eds);
- ({F,Eds}) -> format_message(F, Eds) end,
- Ws0),
- Ws = ordsets:from_list(Ws1),
- foreach(fun({_,Str}) -> io:put_chars(Str) end, Ws);
- false -> ok
- end.
-
-format_message(F, [{Line,Mod,E}|Es]) ->
- M = {Line,io_lib:format("~s:~w: Warning: ~s\n", [F,Line,Mod:format_error(E)])},
- [M|format_message(F, Es)];
-format_message(F, [{Mod,E}|Es]) ->
- M = {none,io_lib:format("~s: Warning: ~s\n", [F,Mod:format_error(E)])},
- [M|format_message(F, Es)];
-format_message(_, []) -> [].
-
-%% list_errors(File, ErrorDescriptors) -> ok
-
-list_errors(F, [{Line,Mod,E}|Es]) ->
- io:fwrite("~s:~w: ~s\n", [F,Line,Mod:format_error(E)]),
- list_errors(F, Es);
-list_errors(F, [{Mod,E}|Es]) ->
- io:fwrite("~s: ~s\n", [F,Mod:format_error(E)]),
- list_errors(F, Es);
-list_errors(_F, []) -> ok.
-
-%% erlfile(Dir, Base) -> ErlFile
-%% outfile(Base, Extension, Options) -> OutputFile
-%% objfile(Base, Target, Options) -> ObjFile
-%% tmpfile(ObjFile) -> TmpFile
-%% Work out the correct input and output file names.
-
-iofile(File) when atom(File) ->
- iofile(atom_to_list(File));
-iofile(File) ->
- {filename:dirname(File), filename:basename(File, ".erl")}.
-
-erlfile(Dir, Base, Suffix) ->
- filename:join(Dir, Base++Suffix).
-
-outfile(Base, Ext, Opts) when atom(Ext) ->
- outfile(Base, atom_to_list(Ext), Opts);
-outfile(Base, Ext, Opts) ->
- Obase = case keysearch(outdir, 1, Opts) of
- {value, {outdir, Odir}} -> filename:join(Odir, Base);
- _Other -> Base % Not found or bad format
- end,
- Obase++"."++Ext.
-
-objfile(Base, St) ->
- outfile(Base, "beam", St#compile.options).
-
-tmpfile(Ofile) ->
- reverse([$#|tl(reverse(Ofile))]).
-
-%% pre_defs(Options)
-%% inc_paths(Options)
-%% Extract the predefined macros and include paths from the option list.
-
-pre_defs([{d,M,V}|Opts]) ->
- [{M,V}|pre_defs(Opts)];
-pre_defs([{d,M}|Opts]) ->
- [M|pre_defs(Opts)];
-pre_defs([_|Opts]) ->
- pre_defs(Opts);
-pre_defs([]) -> [].
-
-inc_paths(Opts) ->
- [ P || {i,P} <- Opts, list(P) ].
-
-src_listing(Ext, St) ->
- listing(fun (Lf, {_Mod,_Exp,Fs}) -> do_src_listing(Lf, Fs);
- (Lf, Fs) -> do_src_listing(Lf, Fs) end,
- Ext, St).
-
-do_src_listing(Lf, Fs) ->
- foreach(fun (F) -> io:put_chars(Lf, [erl_pp:form(F),"\n"]) end,
- Fs).
-
-listing(Ext, St) ->
- listing(fun(Lf, Fs) -> beam_listing:module(Lf, Fs) end, Ext, St).
-
-listing(LFun, Ext, St) ->
- Lfile = outfile(St#compile.base, Ext, St#compile.options),
- case file:open(Lfile, [write,delayed_write]) of
- {ok,Lf} ->
- LFun(Lf, St#compile.code),
- ok = file:close(Lf),
- {ok,St};
- {error,_Error} ->
- Es = [{Lfile,[{none,compile,write_error}]}],
- {error,St#compile{errors=St#compile.errors ++ Es}}
- end.
-
-options() ->
- help(standard_passes()).
-
-help([{iff,Flag,{src_listing,Ext}}|T]) ->
- io:fwrite("~p - Generate .~s source listing file\n", [Flag,Ext]),
- help(T);
-help([{iff,Flag,{listing,Ext}}|T]) ->
- io:fwrite("~p - Generate .~s file\n", [Flag,Ext]),
- help(T);
-help([{iff,Flag,{Name,Fun}}|T]) when function(Fun) ->
- io:fwrite("~p - Run ~s\n", [Flag,Name]),
- help(T);
-help([{iff,_Flag,Action}|T]) ->
- help(Action),
- help(T);
-help([{unless,Flag,{pass,Pass}}|T]) ->
- io:fwrite("~p - Skip the ~s pass\n", [Flag,Pass]),
- help(T);
-help([{unless,no_postopt=Flag,List}|T]) when list(List) ->
- %% Hard-coded knowledgde here.
- io:fwrite("~p - Skip all post optimisation\n", [Flag]),
- help(List),
- help(T);
-help([{unless,_Flag,Action}|T]) ->
- help(Action),
- help(T);
-help([_|T]) ->
- help(T);
-help(_) ->
- ok.
-
-
-%% compile(AbsFileName, Outfilename, Options)
-%% Compile entry point for erl_compile.
-
-compile(File0, _OutFile, Options) ->
- File = shorten_filename(File0),
- case file(File, make_erl_options(Options)) of
- {ok,_Mod} -> ok;
- Other -> Other
- end.
-
-compile_beam(File0, _OutFile, Opts) ->
- File = shorten_filename(File0),
- case file(File, [from_beam|make_erl_options(Opts)]) of
- {ok,_Mod} -> ok;
- Other -> Other
- end.
-
-compile_asm(File0, _OutFile, Opts) ->
- File = shorten_filename(File0),
- case file(File, [asm|make_erl_options(Opts)]) of
- {ok,_Mod} -> ok;
- Other -> Other
- end.
-
-compile_core(File0, _OutFile, Opts) ->
- File = shorten_filename(File0),
- case file(File, [from_core|make_erl_options(Opts)]) of
- {ok,_Mod} -> ok;
- Other -> Other
- end.
-
-shorten_filename(Name0) ->
- {ok,Cwd} = file:get_cwd(),
- case lists:prefix(Cwd, Name0) of
- false -> Name0;
- true ->
- Name = case lists:nthtail(length(Cwd), Name0) of
- "/"++N -> N;
- N -> N
- end,
- Name
- end.
-
-%% Converts generic compiler options to specific options.
-
-make_erl_options(Opts) ->
-
- %% This way of extracting will work even if the record passed
- %% has more fields than known during compilation.
-
- Includes = Opts#options.includes,
- Defines = Opts#options.defines,
- Outdir = Opts#options.outdir,
- Warning = Opts#options.warning,
- Verbose = Opts#options.verbose,
- Specific = Opts#options.specific,
- OutputType = Opts#options.output_type,
- Cwd = Opts#options.cwd,
-
- Options =
- case Verbose of
- true -> [verbose];
- false -> []
- end ++
- case Warning of
- 0 -> [];
- _ -> [report_warnings]
- end ++
- map(
- fun ({Name, Value}) ->
- {d, Name, Value};
- (Name) ->
- {d, Name}
- end,
- Defines) ++
- case OutputType of
- undefined -> [];
- jam -> [jam];
- beam -> [beam];
- native -> [native]
- end,
-
- Options++[report_errors, {cwd, Cwd}, {outdir, Outdir}|
- map(fun(Dir) -> {i, Dir} end, Includes)]++Specific.
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_lib.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_lib.erl
deleted file mode 100644
index 3a6158286f..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_lib.erl
+++ /dev/null
@@ -1,509 +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: core_lib.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
-%%
-%% Purpose: Core Erlang abstract syntax functions.
-
--module(core_lib).
-
--export([get_anno/1,set_anno/2]).
--export([is_atomic/1,is_literal/1,is_literal_list/1,
- is_simple/1,is_simple_list/1,is_simple_top/1]).
--export([literal_value/1,make_literal/1]).
--export([make_values/1]).
--export([map/2, fold/3, mapfold/3]).
--export([is_var_used/2]).
-
-%% -compile([export_all]).
-
--include("core_parse.hrl").
-
-%% get_anno(Core) -> Anno.
-%% set_anno(Core, Anno) -> Core.
-%% Generic get/set annotation.
-
-get_anno(C) -> element(2, C).
-set_anno(C, A) -> setelement(2, C, A).
-
-%% is_atomic(Expr) -> true | false.
-
-is_atomic(#c_char{}) -> true;
-is_atomic(#c_int{}) -> true;
-is_atomic(#c_float{}) -> true;
-is_atomic(#c_atom{}) -> true;
-is_atomic(#c_string{}) -> true;
-is_atomic(#c_nil{}) -> true;
-is_atomic(#c_fname{}) -> true;
-is_atomic(_) -> false.
-
-%% is_literal(Expr) -> true | false.
-
-is_literal(#c_cons{hd=H,tl=T}) ->
- case is_literal(H) of
- true -> is_literal(T);
- false -> false
- end;
-is_literal(#c_tuple{es=Es}) -> is_literal_list(Es);
-is_literal(#c_binary{segments=Es}) -> is_lit_bin(Es);
-is_literal(E) -> is_atomic(E).
-
-is_literal_list(Es) -> lists:all(fun is_literal/1, Es).
-
-is_lit_bin(Es) ->
- lists:all(fun (#c_bitstr{val=E,size=S}) ->
- is_literal(E) and is_literal(S)
- end, Es).
-
-%% is_simple(Expr) -> true | false.
-
-is_simple(#c_var{}) -> true;
-is_simple(#c_cons{hd=H,tl=T}) ->
- case is_simple(H) of
- true -> is_simple(T);
- false -> false
- end;
-is_simple(#c_tuple{es=Es}) -> is_simple_list(Es);
-is_simple(#c_binary{segments=Es}) -> is_simp_bin(Es);
-is_simple(E) -> is_atomic(E).
-
-is_simple_list(Es) -> lists:all(fun is_simple/1, Es).
-
-is_simp_bin(Es) ->
- lists:all(fun (#c_bitstr{val=E,size=S}) ->
- is_simple(E) and is_simple(S)
- end, Es).
-
-%% is_simple_top(Expr) -> true | false.
-%% Only check if the top-level is a simple.
-
-is_simple_top(#c_var{}) -> true;
-is_simple_top(#c_cons{}) -> true;
-is_simple_top(#c_tuple{}) -> true;
-is_simple_top(#c_binary{}) -> true;
-is_simple_top(E) -> is_atomic(E).
-
-%% literal_value(LitExpr) -> Value.
-%% Return the value of LitExpr.
-
-literal_value(#c_char{val=C}) -> C;
-literal_value(#c_int{val=I}) -> I;
-literal_value(#c_float{val=F}) -> F;
-literal_value(#c_atom{val=A}) -> A;
-literal_value(#c_string{val=S}) -> S;
-literal_value(#c_nil{}) -> [];
-literal_value(#c_cons{hd=H,tl=T}) ->
- [literal_value(H)|literal_value(T)];
-literal_value(#c_tuple{es=Es}) ->
- list_to_tuple(literal_value_list(Es)).
-
-literal_value_list(Vals) -> lists:map(fun literal_value/1, Vals).
-
-%% make_literal(Value) -> LitExpr.
-%% Make a literal expression from an Erlang value.
-
-make_literal(I) when integer(I) -> #c_int{val=I};
-make_literal(F) when float(F) -> #c_float{val=F};
-make_literal(A) when atom(A) -> #c_atom{val=A};
-make_literal([]) -> #c_nil{};
-make_literal([H|T]) ->
- #c_cons{hd=make_literal(H),tl=make_literal(T)};
-make_literal(T) when tuple(T) ->
- #c_tuple{es=make_literal_list(tuple_to_list(T))}.
-
-make_literal_list(Vals) -> lists:map(fun make_literal/1, Vals).
-
-%% make_values([CoreExpr] | CoreExpr) -> #c_values{} | CoreExpr.
-%% Make a suitable values structure, expr or values, depending on
-%% Expr.
-
-make_values([E]) -> E;
-make_values([H|_]=Es) -> #c_values{anno=get_anno(H),es=Es};
-make_values([]) -> #c_values{es=[]};
-make_values(E) -> E.
-
-%% map(MapFun, CoreExpr) -> CoreExpr.
-%% This function traverses the core parse format, at each level
-%% applying the submited argument function, assumed to do the real
-%% work.
-%%
-%% The "eager" style, where each component of a construct are
-%% descended to before the construct itself, admits that some
-%% companion functions (the F:s) may be made simpler, since it may be
-%% safely assumed that no lower illegal instanced will be
-%% created/uncovered by actions on the current level.
-
-map(F, #c_tuple{es=Es}=R) ->
- F(R#c_tuple{es=map_list(F, Es)});
-map(F, #c_cons{hd=Hd, tl=Tl}=R) ->
- F(R#c_cons{hd=map(F, Hd),
- tl=map(F, Tl)});
-map(F, #c_values{es=Es}=R) ->
- F(R#c_values{es=map_list(F, Es)});
-
-map(F, #c_alias{var=Var, pat=Pat}=R) ->
- F(R#c_alias{var=map(F, Var),
- pat=map(F, Pat)});
-
-map(F, #c_module{defs=Defs}=R) ->
- F(R#c_module{defs=map_list(F, Defs)});
-map(F, #c_def{val=Val}=R) ->
- F(R#c_def{val=map(F, Val)});
-
-map(F, #c_fun{vars=Vars, body=Body}=R) ->
- F(R#c_fun{vars=map_list(F, Vars),
- body=map(F, Body)});
-map(F, #c_let{vars=Vs, arg=Arg, body=Body}=R) ->
- F(R#c_let{vars=map_list(F, Vs),
- arg=map(F, Arg),
- body=map(F, Body)});
-map(F, #c_letrec{defs=Fs,body=Body}=R) ->
- F(R#c_letrec{defs=map_list(F, Fs),
- body=map(F, Body)});
-map(F, #c_seq{arg=Arg, body=Body}=R) ->
- F(R#c_seq{arg=map(F, Arg),
- body=map(F, Body)});
-map(F, #c_case{arg=Arg, clauses=Clauses}=R) ->
- F(R#c_case{arg=map(F, Arg),
- clauses=map_list(F, Clauses)});
-map(F, #c_clause{pats=Ps, guard=Guard, body=Body}=R) ->
- F(R#c_clause{pats=map_list(F, Ps),
- guard=map(F, Guard),
- body=map(F, Body)});
-map(F, #c_receive{clauses=Cls, timeout=Tout, action=Act}=R) ->
- F(R#c_receive{clauses=map_list(F, Cls),
- timeout=map(F, Tout),
- action=map(F, Act)});
-map(F, #c_apply{op=Op,args=Args}=R) ->
- F(R#c_apply{op=map(F, Op),
- args=map_list(F, Args)});
-map(F, #c_call{module=M,name=N,args=Args}=R) ->
- F(R#c_call{module=map(F, M),
- name=map(F, N),
- args=map_list(F, Args)});
-map(F, #c_primop{name=N,args=Args}=R) ->
- F(R#c_primop{name=map(F, N),
- args=map_list(F, Args)});
-map(F, #c_try{arg=Expr,vars=Vars,body=Body,evars=Evars,handler=Handler}=R) ->
- F(R#c_try{arg=map(F, Expr),
- vars=map(F, Vars),
- body=map(F, Body),
- evars=map(F, Evars),
- handler=map(F, Handler)});
-map(F, #c_catch{body=Body}=R) ->
- F(R#c_catch{body=map(F, Body)});
-map(F, T) -> F(T). %Atomic nodes.
-
-map_list(F, L) -> lists:map(fun (E) -> map(F, E) end, L).
-
-%% fold(FoldFun, Accumulator, CoreExpr) -> Accumulator.
-%% This function traverses the core parse format, at each level
-%% applying the submited argument function, assumed to do the real
-%% work, and keeping the accumulated result in the A (accumulator)
-%% argument.
-
-fold(F, Acc, #c_tuple{es=Es}=R) ->
- F(R, fold_list(F, Acc, Es));
-fold(F, Acc, #c_cons{hd=Hd, tl=Tl}=R) ->
- F(R, fold(F, fold(F, Acc, Hd), Tl));
-fold(F, Acc, #c_values{es=Es}=R) ->
- F(R, fold_list(F, Acc, Es));
-
-fold(F, Acc, #c_alias{pat=P,var=V}=R) ->
- F(R, fold(F, fold(F, Acc, P), V));
-
-fold(F, Acc, #c_module{defs=Defs}=R) ->
- F(R, fold_list(F, Acc, Defs));
-fold(F, Acc, #c_def{val=Val}=R) ->
- F(R, fold(F, Acc, Val));
-
-fold(F, Acc, #c_fun{vars=Vars, body=Body}=R) ->
- F(R, fold(F, fold_list(F, Acc, Vars), Body));
-fold(F, Acc, #c_let{vars=Vs, arg=Arg, body=Body}=R) ->
- F(R, fold(F, fold(F, fold_list(F, Acc, Vs), Arg), Body));
-fold(F, Acc, #c_letrec{defs=Fs,body=Body}=R) ->
- F(R, fold(F, fold_list(F, Acc, Fs), Body));
-fold(F, Acc, #c_seq{arg=Arg, body=Body}=R) ->
- F(R, fold(F, fold(F, Acc, Arg), Body));
-fold(F, Acc, #c_case{arg=Arg, clauses=Clauses}=R) ->
- F(R, fold_list(F, fold(F, Acc, Arg), Clauses));
-fold(F, Acc, #c_clause{pats=Ps,guard=G,body=B}=R) ->
- F(R, fold(F, fold(F, fold_list(F, Acc, Ps), G), B));
-fold(F, Acc, #c_receive{clauses=Cl, timeout=Ti, action=Ac}=R) ->
- F(R, fold_list(F, fold(F, fold(F, Acc, Ac), Ti), Cl));
-fold(F, Acc, #c_apply{op=Op, args=Args}=R) ->
- F(R, fold_list(F, fold(F, Acc, Op), Args));
-fold(F, Acc, #c_call{module=Mod,name=Name,args=Args}=R) ->
- F(R, fold_list(F, fold(F, fold(F, Acc, Mod), Name), Args));
-fold(F, Acc, #c_primop{name=Name,args=Args}=R) ->
- F(R, fold_list(F, fold(F, Acc, Name), Args));
-fold(F, Acc, #c_try{arg=E,vars=Vs,body=Body,evars=Evs,handler=H}=R) ->
- NewB = fold(F, fold_list(F, fold(F, Acc, E), Vs), Body),
- F(R, fold(F, fold_list(F, NewB, Evs), H));
-fold(F, Acc, #c_catch{body=Body}=R) ->
- F(R, fold(F, Acc, Body));
-fold(F, Acc, T) -> %Atomic nodes
- F(T, Acc).
-
-fold_list(F, Acc, L) ->
- lists:foldl(fun (E, A) -> fold(F, A, E) end, Acc, L).
-
-%% mapfold(MapfoldFun, Accumulator, CoreExpr) -> {CoreExpr,Accumulator}.
-%% This function traverses the core parse format, at each level
-%% applying the submited argument function, assumed to do the real
-%% work, and keeping the accumulated result in the A (accumulator)
-%% argument.
-
-mapfold(F, Acc0, #c_tuple{es=Es0}=R) ->
- {Es1,Acc1} = mapfold_list(F, Acc0, Es0),
- F(R#c_tuple{es=Es1}, Acc1);
-mapfold(F, Acc0, #c_cons{hd=H0,tl=T0}=R) ->
- {H1,Acc1} = mapfold(F, Acc0, H0),
- {T1,Acc2} = mapfold(F, Acc1, T0),
- F(R#c_cons{hd=H1,tl=T1}, Acc2);
-mapfold(F, Acc0, #c_values{es=Es0}=R) ->
- {Es1,Acc1} = mapfold_list(F, Acc0, Es0),
- F(R#c_values{es=Es1}, Acc1);
-
-mapfold(F, Acc0, #c_alias{pat=P0,var=V0}=R) ->
- {P1,Acc1} = mapfold(F, Acc0, P0),
- {V1,Acc2} = mapfold(F, Acc1, V0),
- F(R#c_alias{pat=P1,var=V1}, Acc2);
-
-mapfold(F, Acc0, #c_module{defs=D0}=R) ->
- {D1,Acc1} = mapfold_list(F, Acc0, D0),
- F(R#c_module{defs=D1}, Acc1);
-mapfold(F, Acc0, #c_def{val=V0}=R) ->
- {V1,Acc1} = mapfold(F, Acc0, V0),
- F(R#c_def{val=V1}, Acc1);
-
-mapfold(F, Acc0, #c_fun{vars=Vs0, body=B0}=R) ->
- {Vs1,Acc1} = mapfold_list(F, Acc0, Vs0),
- {B1,Acc2} = mapfold(F, Acc1, B0),
- F(R#c_fun{vars=Vs1,body=B1}, Acc2);
-mapfold(F, Acc0, #c_let{vars=Vs0, arg=A0, body=B0}=R) ->
- {Vs1,Acc1} = mapfold_list(F, Acc0, Vs0),
- {A1,Acc2} = mapfold(F, Acc1, A0),
- {B1,Acc3} = mapfold(F, Acc2, B0),
- F(R#c_let{vars=Vs1,arg=A1,body=B1}, Acc3);
-mapfold(F, Acc0, #c_letrec{defs=Fs0,body=B0}=R) ->
- {Fs1,Acc1} = mapfold_list(F, Acc0, Fs0),
- {B1,Acc2} = mapfold(F, Acc1, B0),
- F(R#c_letrec{defs=Fs1,body=B1}, Acc2);
-mapfold(F, Acc0, #c_seq{arg=A0, body=B0}=R) ->
- {A1,Acc1} = mapfold(F, Acc0, A0),
- {B1,Acc2} = mapfold(F, Acc1, B0),
- F(R#c_seq{arg=A1,body=B1}, Acc2);
-mapfold(F, Acc0, #c_case{arg=A0,clauses=Cs0}=R) ->
- {A1,Acc1} = mapfold(F, Acc0, A0),
- {Cs1,Acc2} = mapfold_list(F, Acc1, Cs0),
- F(R#c_case{arg=A1,clauses=Cs1}, Acc2);
-mapfold(F, Acc0, #c_clause{pats=Ps0,guard=G0,body=B0}=R) ->
- {Ps1,Acc1} = mapfold_list(F, Acc0, Ps0),
- {G1,Acc2} = mapfold(F, Acc1, G0),
- {B1,Acc3} = mapfold(F, Acc2, B0),
- F(R#c_clause{pats=Ps1,guard=G1,body=B1}, Acc3);
-mapfold(F, Acc0, #c_receive{clauses=Cs0,timeout=T0,action=A0}=R) ->
- {T1,Acc1} = mapfold(F, Acc0, T0),
- {Cs1,Acc2} = mapfold_list(F, Acc1, Cs0),
- {A1,Acc3} = mapfold(F, Acc2, A0),
- F(R#c_receive{clauses=Cs1,timeout=T1,action=A1}, Acc3);
-mapfold(F, Acc0, #c_apply{op=Op0, args=As0}=R) ->
- {Op1,Acc1} = mapfold(F, Acc0, Op0),
- {As1,Acc2} = mapfold_list(F, Acc1, As0),
- F(R#c_apply{op=Op1,args=As1}, Acc2);
-mapfold(F, Acc0, #c_call{module=M0,name=N0,args=As0}=R) ->
- {M1,Acc1} = mapfold(F, Acc0, M0),
- {N1,Acc2} = mapfold(F, Acc1, N0),
- {As1,Acc3} = mapfold_list(F, Acc2, As0),
- F(R#c_call{module=M1,name=N1,args=As1}, Acc3);
-mapfold(F, Acc0, #c_primop{name=N0, args=As0}=R) ->
- {N1,Acc1} = mapfold(F, Acc0, N0),
- {As1,Acc2} = mapfold_list(F, Acc1, As0),
- F(R#c_primop{name=N1,args=As1}, Acc2);
-mapfold(F, Acc0, #c_try{arg=E0,vars=Vs0,body=B0,evars=Evs0,handler=H0}=R) ->
- {E1,Acc1} = mapfold(F, Acc0, E0),
- {Vs1,Acc2} = mapfold_list(F, Acc1, Vs0),
- {B1,Acc3} = mapfold(F, Acc2, B0),
- {Evs1,Acc4} = mapfold_list(F, Acc3, Evs0),
- {H1,Acc5} = mapfold(F, Acc4, H0),
- F(R#c_try{arg=E1,vars=Vs1,body=B1,evars=Evs1,handler=H1}, Acc5);
-mapfold(F, Acc0, #c_catch{body=B0}=R) ->
- {B1,Acc1} = mapfold(F, Acc0, B0),
- F(R#c_catch{body=B1}, Acc1);
-mapfold(F, Acc, T) -> %Atomic nodes
- F(T, Acc).
-
-mapfold_list(F, Acc, L) ->
- lists:mapfoldl(fun (E, A) -> mapfold(F, A, E) end, Acc, L).
-
-%% is_var_used(VarName, Expr) -> true | false.
-%% Test if the variable VarName is used in Expr.
-
-is_var_used(V, B) -> vu_body(V, B).
-
-vu_body(V, #c_values{es=Es}) ->
- vu_expr_list(V, Es);
-vu_body(V, Body) ->
- vu_expr(V, Body).
-
-vu_expr(V, #c_var{name=V2}) -> V =:= V2;
-vu_expr(V, #c_cons{hd=H,tl=T}) ->
- case vu_expr(V, H) of
- true -> true;
- false -> vu_expr(V, T)
- end;
-vu_expr(V, #c_tuple{es=Es}) ->
- vu_expr_list(V, Es);
-vu_expr(V, #c_binary{segments=Ss}) ->
- vu_seg_list(V, Ss);
-vu_expr(V, #c_fun{vars=Vs,body=B}) ->
- %% Variables in fun shadow previous variables
- case vu_var_list(V, Vs) of
- true -> false;
- false -> vu_body(V, B)
- end;
-vu_expr(V, #c_let{vars=Vs,arg=Arg,body=B}) ->
- case vu_body(V, Arg) of
- true -> true;
- false ->
- %% Variables in let shadow previous variables.
- case vu_var_list(V, Vs) of
- true -> false;
- false -> vu_body(V, B)
- end
- end;
-vu_expr(V, #c_letrec{defs=Fs,body=B}) ->
- case lists:any(fun (#c_def{val=Fb}) -> vu_body(V, Fb) end, Fs) of
- true -> true;
- false -> vu_body(V, B)
- end;
-vu_expr(V, #c_seq{arg=Arg,body=B}) ->
- case vu_expr(V, Arg) of
- true -> true;
- false -> vu_body(V, B)
- end;
-vu_expr(V, #c_case{arg=Arg,clauses=Cs}) ->
- case vu_expr(V, Arg) of
- true -> true;
- false -> vu_clauses(V, Cs)
- end;
-vu_expr(V, #c_receive{clauses=Cs,timeout=T,action=A}) ->
- case vu_clauses(V, Cs) of
- true -> true;
- false ->
- case vu_expr(V, T) of
- true -> true;
- false -> vu_body(V, A)
- end
- end;
-vu_expr(V, #c_apply{op=Op,args=As}) ->
- vu_expr_list(V, [Op|As]);
-vu_expr(V, #c_call{module=M,name=N,args=As}) ->
- vu_expr_list(V, [M,N|As]);
-vu_expr(V, #c_primop{args=As}) -> %Name is an atom
- vu_expr_list(V, As);
-vu_expr(V, #c_catch{body=B}) ->
- vu_body(V, B);
-vu_expr(V, #c_try{arg=E,vars=Vs,body=B,evars=Evs,handler=H}) ->
- case vu_body(V, E) of
- true -> true;
- false ->
- %% Variables shadow previous ones.
- case case vu_var_list(V, Vs) of
- true -> false;
- false -> vu_body(V, B)
- end of
- true -> true;
- false ->
- case vu_var_list(V, Evs) of
- true -> false;
- false -> vu_body(V, H)
- end
- end
- end;
-vu_expr(_, _) -> false. %Everything else
-
-vu_expr_list(V, Es) ->
- lists:any(fun(E) -> vu_expr(V, E) end, Es).
-
-vu_seg_list(V, Ss) ->
- lists:any(fun (#c_bitstr{val=Val,size=Size}) ->
- case vu_expr(V, Val) of
- true -> true;
- false -> vu_expr(V, Size)
- end
- end, Ss).
-
-%% vu_clause(VarName, Clause) -> true | false.
-%% vu_clauses(VarName, [Clause]) -> true | false.
-%% Have to get the pattern results right.
-
-vu_clause(V, #c_clause{pats=Ps,guard=G,body=B}) ->
- case vu_pattern_list(V, Ps) of
- {true,_Shad} -> true; %It is used
- {false,true} -> false; %Shadowed
- {false,false} -> %Not affected
- case vu_expr(V, G) of
- true -> true;
- false ->vu_body(V, B)
- end
- end.
-
-vu_clauses(V, Cs) ->
- lists:any(fun(C) -> vu_clause(V, C) end, Cs).
-
-%% vu_pattern(VarName, Pattern) -> {Used,Shadow}.
-%% vu_pattern_list(VarName, [Pattern]) -> {Used,Shadow}.
-%% Binaries complicate patterns as a variable can both be properly
-%% used, in a bit segment size, and shadow. They can also do both.
-
-%%vu_pattern(V, Pat) -> vu_pattern(V, Pat, {false,false}).
-
-vu_pattern(V, #c_var{name=V2}, St) ->
- setelement(2, St, V =:= V2);
-vu_pattern(V, #c_cons{hd=H,tl=T}, St0) ->
- case vu_pattern(V, H, St0) of
- {true,true}=St1 -> St1; %Nothing more to know
- St1 -> vu_pattern(V, T, St1)
- end;
-vu_pattern(V, #c_tuple{es=Es}, St) ->
- vu_pattern_list(V, Es, St);
-vu_pattern(V, #c_binary{segments=Ss}, St) ->
- vu_pat_seg_list(V, Ss, St);
-vu_pattern(V, #c_alias{var=Var,pat=P}, St0) ->
- case vu_pattern(V, Var, St0) of
- {true,true}=St1 -> St1;
- St1 -> vu_pattern(V, P, St1)
- end;
-vu_pattern(_, _, St) -> St.
-
-vu_pattern_list(V, Ps) -> vu_pattern_list(V, Ps, {false,false}).
-
-vu_pattern_list(V, Ps, St0) ->
- lists:foldl(fun(P, St) -> vu_pattern(V, P, St) end, St0, Ps).
-
-vu_pat_seg_list(V, Ss, St) ->
- lists:foldl(fun (#c_bitstr{val=Val,size=Size}, St0) ->
- case vu_pattern(V, Val, St0) of
- {true,true}=St1 -> St1;
- {_Used,Shad} -> {vu_expr(V, Size),Shad}
- end
- end, St, Ss).
-
-%% vu_var_list(VarName, [Var]) -> true | false.
-
-vu_var_list(V, Vs) ->
- lists:any(fun (#c_var{name=V2}) -> V =:= V2 end, Vs).
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_lint.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_lint.erl
deleted file mode 100644
index 2946fcb8c0..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_lint.erl
+++ /dev/null
@@ -1,515 +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: core_lint.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
-%%
-%% Purpose : Do necessary checking of Core Erlang code.
-
-%% Check Core module for errors. Seeing this module is used in the
-%% compiler after optimisations wedone more checking than would be
-%% necessary after just parsing. Don't check all constructs.
-%%
-%% We check the following:
-%%
-%% All referred functions, called and exported, are defined.
-%% Format of export list.
-%% Format of attributes
-%% Used variables are defined.
-%% Variables in let and funs.
-%% Patterns case clauses.
-%% Values only as multiple values/variables/patterns.
-%% Return same number of values as requested
-%% Correct number of arguments
-%%
-%% Checks to add:
-%%
-%% Consistency of values/variables
-%% Consistency of function return values/calls.
-%%
-%% We keep the names defined variables and functions in a ordered list
-%% of variable names and function name/arity pairs.
-
--module(core_lint).
-
-
--export([module/1,module/2,format_error/1]).
-
--import(lists, [reverse/1,all/2,foldl/3]).
--import(ordsets, [add_element/2,is_element/2,union/2]).
-%-import(ordsets, [subtract/2]).
-
--include("core_parse.hrl").
-
-%% Define the lint state record.
-
--record(lint, {module=[], %Current module
- func=[], %Current function
- errors=[], %Errors
- warnings=[]}). %Warnings
-
-%% Keep track of defined
--record(def, {vars=[],
- funs=[]}).
-
-%%-deftype retcount() -> any | unknown | int().
-
-%% format_error(Error)
-%% Return a string describing the error.
-
-format_error(invalid_exports) -> "invalid exports";
-format_error(invalid_attributes) -> "invalid attributes";
-format_error({undefined_function,{F,A}}) ->
- io_lib:format("function ~w/~w undefined", [F,A]);
-format_error({undefined_function,{F1,A1},{F2,A2}}) ->
- io_lib:format("undefined function ~w/~w in ~w/~w", [F1,A1,F2,A2]);
-format_error({illegal_expr,{F,A}}) ->
- io_lib:format("illegal expression in ~w/~w", [F,A]);
-format_error({illegal_guard,{F,A}}) ->
- io_lib:format("illegal guard expression in ~w/~w", [F,A]);
-format_error({illegal_pattern,{F,A}}) ->
- io_lib:format("illegal pattern in ~w/~w", [F,A]);
-format_error({illegal_try,{F,A}}) ->
- io_lib:format("illegal try expression in ~w/~w", [F,A]);
-format_error({pattern_mismatch,{F,A}}) ->
- io_lib:format("pattern count mismatch in ~w/~w", [F,A]);
-format_error({return_mismatch,{F,A}}) ->
- io_lib:format("return count mismatch in ~w/~w", [F,A]);
-format_error({arg_mismatch,{F,A}}) ->
- io_lib:format("argument count mismatch in ~w/~w", [F,A]);
-format_error({unbound_var,N,{F,A}}) ->
- io_lib:format("unbound variable ~s in ~w/~w", [N,F,A]);
-format_error({duplicate_var,N,{F,A}}) ->
- io_lib:format("duplicate variable ~s in ~w/~w", [N,F,A]);
-format_error({not_var,{F,A}}) ->
- io_lib:format("expecting variable in ~w/~w", [F,A]);
-format_error({not_pattern,{F,A}}) ->
- io_lib:format("expecting pattern in ~w/~w", [F,A]);
-format_error({not_bs_pattern,{F,A}}) ->
- io_lib:format("expecting bit syntax pattern in ~w/~w", [F,A]).
-
-%% module(CoreMod) ->
-%% module(CoreMod, [CompileOption]) ->
-%% {ok,[Warning]} | {error,[Error],[Warning]}
-
-module(M) -> module(M, []).
-
-module(#c_module{name=M,exports=Es,attrs=As,defs=Ds}, _Opts) ->
- Defined = defined_funcs(Ds),
- St0 = #lint{module=M#c_atom.val},
- St1 = check_exports(Es, St0),
- St2 = check_attrs(As, St1),
- St3 = module_defs(Ds, Defined, St2),
- St4 = check_state(Es, Defined, St3),
- return_status(St4).
-
-%% defined_funcs([FuncDef]) -> [Fname].
-
-defined_funcs(Fs) ->
- foldl(fun (#c_def{name=#c_fname{id=I,arity=A}}, Def) ->
- add_element({I,A}, Def)
- end, [], Fs).
-
-%% return_status(State) ->
-%% {ok,[Warning]} | {error,[Error],[Warning]}
-%% Pack errors and warnings properly and return ok | error.
-
-return_status(St) ->
- Ws = reverse(St#lint.warnings),
- case reverse(St#lint.errors) of
- [] -> {ok,[{St#lint.module,Ws}]};
- Es -> {error,[{St#lint.module,Es}],[{St#lint.module,Ws}]}
- end.
-
-%% add_error(ErrorDescriptor, State) -> State'
-%% add_warning(ErrorDescriptor, State) -> State'
-%% Note that we don't use line numbers here.
-
-add_error(E, St) -> St#lint{errors=[{none,core_lint,E}|St#lint.errors]}.
-
-%%add_warning(W, St) -> St#lint{warnings=[{none,core_lint,W}|St#lint.warnings]}.
-
-check_exports(Es, St) ->
- case all(fun (#c_fname{id=Name,arity=Arity}) when
- atom(Name), integer(Arity) -> true;
- (_) -> false
- end, Es) of
- true -> St;
- false -> add_error(invalid_exports, St)
- end.
-
-check_attrs(As, St) ->
- case all(fun (#c_def{name=#c_atom{},val=V}) -> core_lib:is_literal(V);
- (_) -> false
- end, As) of
- true -> St;
- false -> add_error(invalid_attributes, St)
- end.
-
-check_state(Es, Defined, St) ->
- foldl(fun (#c_fname{id=N,arity=A}, St1) ->
- F = {N,A},
- case is_element(F, Defined) of
- true -> St1;
- false -> add_error({undefined_function,F}, St)
- end
- end, St, Es).
-% Undef = subtract(Es, Defined),
-% St1 = foldl(fun (F, St) -> add_error({undefined_function,F}, St) end,
-% St0, Undef),
-% St1.
-
-%% module_defs(CoreBody, Defined, State) -> State.
-
-module_defs(B, Def, St) ->
- %% Set top level function name.
- foldl(fun (Func, St0) ->
- #c_fname{id=F,arity=A} = Func#c_def.name,
- St1 = St0#lint{func={F,A}},
- function(Func, Def, St1)
- end, St, B).
-
-%% functions([Fdef], Defined, State) -> State.
-
-functions(Fs, Def, St0) ->
- foldl(fun (F, St) -> function(F, Def, St) end, St0, Fs).
-
-%% function(CoreFunc, Defined, State) -> State.
-
-function(#c_def{name=#c_fname{},val=B}, Def, St) ->
- %% Body must be a fun!
- case B of
- #c_fun{} -> expr(B, Def, any, St);
- _ -> add_error({illegal_expr,St#lint.func}, St)
- end.
-
-%% body(Expr, Defined, RetCount, State) -> State.
-
-body(#c_values{es=Es}, Def, Rt, St) ->
- return_match(Rt, length(Es), expr_list(Es, Def, St));
-body(E, Def, Rt, St0) ->
- St1 = expr(E, Def, Rt, St0),
- case core_lib:is_simple_top(E) of
- true -> return_match(Rt, 1, St1);
- false -> St1
- end.
-
-%% guard(Expr, Defined, State) -> State.
-%% Guards are boolean expressions with test wrapped in a protected.
-
-guard(Expr, Def, St) -> gexpr(Expr, Def, 1, St).
-
-%% guard_list([Expr], Defined, State) -> State.
-
-%% guard_list(Es, Def, St0) ->
-%% foldl(fun (E, St) -> guard(E, Def, St) end, St0, Es).
-
-%% gbody(Expr, Defined, RetCount, State) -> State.
-
-gbody(#c_values{es=Es}, Def, Rt, St) ->
- return_match(Rt, length(Es), gexpr_list(Es, Def, St));
-gbody(E, Def, Rt, St0) ->
- St1 = gexpr(E, Def, Rt, St0),
- case core_lib:is_simple_top(E) of
- true -> return_match(Rt, 1, St1);
- false -> St1
- end.
-
-gexpr(#c_var{name=N}, Def, _Rt, St) -> expr_var(N, Def, St);
-gexpr(#c_int{}, _Def, _Rt, St) -> St;
-gexpr(#c_float{}, _Def, _Rt, St) -> St;
-gexpr(#c_atom{}, _Def, _Rt, St) -> St;
-gexpr(#c_char{}, _Def, _Rt, St) -> St;
-gexpr(#c_string{}, _Def, _Rt, St) -> St;
-gexpr(#c_nil{}, _Def, _Rt, St) -> St;
-gexpr(#c_cons{hd=H,tl=T}, Def, _Rt, St) ->
- gexpr_list([H,T], Def, St);
-gexpr(#c_tuple{es=Es}, Def, _Rt, St) ->
- gexpr_list(Es, Def, St);
-gexpr(#c_binary{segments=Ss}, Def, _Rt, St) ->
- gbitstr_list(Ss, Def, St);
-gexpr(#c_seq{arg=Arg,body=B}, Def, Rt, St0) ->
- St1 = gexpr(Arg, Def, any, St0), %Ignore values
- gbody(B, Def, Rt, St1);
-gexpr(#c_let{vars=Vs,arg=Arg,body=B}, Def, Rt, St0) ->
- St1 = gbody(Arg, Def, let_varcount(Vs), St0), %This is a guard body
- {Lvs,St2} = variable_list(Vs, St1),
- gbody(B, union(Lvs, Def), Rt, St2);
-gexpr(#c_call{module=#c_atom{val=erlang},
- name=#c_atom{},
- args=As}, Def, 1, St) ->
- gexpr_list(As, Def, St);
-gexpr(#c_primop{name=N,args=As}, Def, _Rt, St0) when record(N, c_atom) ->
- gexpr_list(As, Def, St0);
-gexpr(#c_try{arg=E,vars=[#c_var{name=X}],body=#c_var{name=X},
- evars=[#c_var{},#c_var{},#c_var{}],handler=#c_atom{val=false}},
- Def, Rt, St) ->
- gbody(E, Def, Rt, St);
-gexpr(_, _, _, St) ->
- add_error({illegal_guard,St#lint.func}, St).
-
-%% gexpr_list([Expr], Defined, State) -> State.
-
-gexpr_list(Es, Def, St0) ->
- foldl(fun (E, St) -> gexpr(E, Def, 1, St) end, St0, Es).
-
-%% gbitstr_list([Elem], Defined, State) -> State.
-
-gbitstr_list(Es, Def, St0) ->
- foldl(fun (E, St) -> gbitstr(E, Def, St) end, St0, Es).
-
-gbitstr(#c_bitstr{val=V,size=S,unit=U,type=T,flags=Fs}, Def, St0) ->
- St1 = bit_type(U, T, Fs, St0),
- gexpr_list([V,S], Def, St1).
-
-%% expr(Expr, Defined, RetCount, State) -> State.
-
-expr(#c_var{name=N}, Def, _Rt, St) -> expr_var(N, Def, St);
-expr(#c_int{}, _Def, _Rt, St) -> St;
-expr(#c_float{}, _Def, _Rt, St) -> St;
-expr(#c_atom{}, _Def, _Rt, St) -> St;
-expr(#c_char{}, _Def, _Rt, St) -> St;
-expr(#c_string{}, _Def, _Rt, St) -> St;
-expr(#c_nil{}, _Def, _Rt, St) -> St;
-expr(#c_cons{hd=H,tl=T}, Def, _Rt, St) ->
- expr_list([H,T], Def, St);
-expr(#c_tuple{es=Es}, Def, _Rt, St) ->
- expr_list(Es, Def, St);
-expr(#c_binary{segments=Ss}, Def, _Rt, St) ->
- bitstr_list(Ss, Def, St);
-expr(#c_fname{id=I,arity=A}, Def, _Rt, St) ->
- expr_fname({I,A}, Def, St);
-expr(#c_fun{vars=Vs,body=B}, Def, Rt, St0) ->
- {Vvs,St1} = variable_list(Vs, St0),
- return_match(Rt, 1, body(B, union(Vvs, Def), any, St1));
-expr(#c_seq{arg=Arg,body=B}, Def, Rt, St0) ->
- St1 = expr(Arg, Def, any, St0), %Ignore values
- body(B, Def, Rt, St1);
-expr(#c_let{vars=Vs,arg=Arg,body=B}, Def, Rt, St0) ->
- St1 = body(Arg, Def, let_varcount(Vs), St0), %This is a body
- {Lvs,St2} = variable_list(Vs, St1),
- body(B, union(Lvs, Def), Rt, St2);
-expr(#c_letrec{defs=Fs,body=B}, Def0, Rt, St0) ->
- Def1 = union(defined_funcs(Fs), Def0), %All defined stuff
- St1 = functions(Fs, Def1, St0),
- body(B, Def1, Rt, St1#lint{func=St0#lint.func});
-expr(#c_case{arg=Arg,clauses=Cs}, Def, Rt, St0) ->
- Pc = case_patcount(Cs),
- St1 = body(Arg, Def, Pc, St0),
- clauses(Cs, Def, Pc, Rt, St1);
-expr(#c_receive{clauses=Cs,timeout=T,action=A}, Def, Rt, St0) ->
- St1 = expr(T, Def, 1, St0),
- St2 = body(A, Def, Rt, St1),
- clauses(Cs, Def, 1, Rt, St2);
-expr(#c_apply{op=Op,args=As}, Def, _Rt, St0) ->
- St1 = apply_op(Op, Def, length(As), St0),
- expr_list(As, Def, St1);
-expr(#c_call{module=M,name=N,args=As}, Def, _Rt, St0) ->
- St1 = expr(M, Def, 1, St0),
- St2 = expr(N, Def, 1, St1),
- expr_list(As, Def, St2);
-expr(#c_primop{name=N,args=As}, Def, _Rt, St0) when record(N, c_atom) ->
- expr_list(As, Def, St0);
-expr(#c_catch{body=B}, Def, Rt, St) ->
- return_match(Rt, 1, body(B, Def, 1, St));
-expr(#c_try{arg=A,vars=Vs,body=B,evars=Evs,handler=H}, Def, Rt, St0) ->
- St1 = case length(Evs) of
- 2 -> St0;
- _ -> add_error({illegal_try,St0#lint.func}, St0)
- end,
- St2 = body(A, Def, let_varcount(Vs), St1),
- {Ns,St3} = variable_list(Vs, St2),
- St4 = body(B, union(Ns, Def), Rt, St3),
- {Ens,St5} = variable_list(Evs, St4),
- body(H, union(Ens, Def), Rt, St5);
-expr(_, _, _, St) ->
- %%io:fwrite("clint: ~p~n", [Other]),
- add_error({illegal_expr,St#lint.func}, St).
-
-%% expr_list([Expr], Defined, State) -> State.
-
-expr_list(Es, Def, St0) ->
- foldl(fun (E, St) -> expr(E, Def, 1, St) end, St0, Es).
-
-%% bitstr_list([Elem], Defined, State) -> State.
-
-bitstr_list(Es, Def, St0) ->
- foldl(fun (E, St) -> bitstr(E, Def, St) end, St0, Es).
-
-bitstr(#c_bitstr{val=V,size=S,unit=U,type=T,flags=Fs}, Def, St0) ->
- St1 = bit_type(U, T, Fs, St0),
- expr_list([V,S], Def, St1).
-
-%% apply_op(Op, Defined, ArgCount, State) -> State.
-%% A apply op is either an fname or an expression.
-
-apply_op(#c_fname{id=I,arity=A}, Def, Ac, St0) ->
- St1 = expr_fname({I,A}, Def, St0),
- arg_match(Ac, A, St1);
-apply_op(E, Def, _, St) -> expr(E, Def, 1, St). %Hard to check
-
-%% expr_var(VarName, Defined, State) -> State.
-
-expr_var(N, Def, St) ->
- case is_element(N, Def) of
- true -> St;
- false -> add_error({unbound_var,N,St#lint.func}, St)
- end.
-
-%% expr_fname(Fname, Defined, State) -> State.
-
-expr_fname(Fname, Def, St) ->
- case is_element(Fname, Def) of
- true -> St;
- false -> add_error({undefined_function,Fname,St#lint.func}, St)
- end.
-
-%% let_varcount([Var]) -> int().
-
-let_varcount([]) -> any; %Ignore values
-let_varcount(Es) -> length(Es).
-
-%% case_patcount([Clause]) -> int().
-
-case_patcount([#c_clause{pats=Ps}|_]) -> length(Ps).
-
-%% clauses([Clause], Defined, PatCount, RetCount, State) -> State.
-
-clauses(Cs, Def, Pc, Rt, St0) ->
- foldl(fun (C, St) -> clause(C, Def, Pc, Rt, St) end, St0, Cs).
-
-%% clause(Clause, Defined, PatCount, RetCount, State) -> State.
-
-clause(#c_clause{pats=Ps,guard=G,body=B}, Def0, Pc, Rt, St0) ->
- St1 = pattern_match(Pc, length(Ps), St0),
- {Pvs,St2} = pattern_list(Ps, Def0, St1),
- Def1 = union(Pvs, Def0),
- St3 = guard(G, Def1, St2),
- body(B, Def1, Rt, St3).
-
-%% variable(Var, [PatVar], State) -> {[VarName],State}.
-
-variable(#c_var{name=N}, Ps, St) ->
- case is_element(N, Ps) of
- true -> {[],add_error({duplicate_var,N,St#lint.func}, St)};
- false -> {[N],St}
- end;
-variable(_, Def, St) -> {Def,add_error({not_var,St#lint.func}, St)}.
-
-%% variable_list([Var], State) -> {[Var],State}.
-%% variable_list([Var], [PatVar], State) -> {[Var],State}.
-
-variable_list(Vs, St) -> variable_list(Vs, [], St).
-
-variable_list(Vs, Ps, St) ->
- foldl(fun (V, {Ps0,St0}) ->
- {Vvs,St1} = variable(V, Ps0, St0),
- {union(Vvs, Ps0),St1}
- end, {Ps,St}, Vs).
-
-%% pattern(Pattern, Defined, State) -> {[PatVar],State}.
-%% pattern(Pattern, Defined, [PatVar], State) -> {[PatVar],State}.
-%% Patterns are complicated by sizes in binaries. These are pure
-%% input variables which create no bindings. We, therefor, need to
-%% carry around the original defined variables to get the correct
-%% handling.
-
-%% pattern(P, Def, St) -> pattern(P, Def, [], St).
-
-pattern(#c_var{name=N}, Def, Ps, St) ->
- pat_var(N, Def, Ps, St);
-pattern(#c_int{}, _Def, Ps, St) -> {Ps,St};
-pattern(#c_float{}, _Def, Ps, St) -> {Ps,St};
-pattern(#c_atom{}, _Def, Ps, St) -> {Ps,St};
-pattern(#c_char{}, _Def, Ps, St) -> {Ps,St};
-pattern(#c_string{}, _Def, Ps, St) -> {Ps,St};
-pattern(#c_nil{}, _Def, Ps, St) -> {Ps,St};
-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) ->
- pat_bin(Ss, Def, Ps, St);
-pattern(#c_alias{var=V,pat=P}, Def, Ps, St0) ->
- {Vvs,St1} = variable(V, Ps, St0),
- pattern(P, Def, union(Vvs, Ps), St1);
-pattern(_, _, Ps, St) -> {Ps,add_error({not_pattern,St#lint.func}, St)}.
-
-pat_var(N, _Def, Ps, St) ->
- case is_element(N, Ps) of
- true -> {Ps,add_error({duplicate_var,N,St#lint.func}, St)};
- false -> {add_element(N, Ps),St}
- end.
-
-%% pat_bin_list([Elem], Defined, [PatVar], State) -> {[PatVar],State}.
-
-pat_bin(Es, Def, Ps0, St0) ->
- foldl(fun (E, {Ps,St}) -> pat_segment(E, Def, Ps, St) end, {Ps0,St0}, Es).
-
-pat_segment(#c_bitstr{val=V,size=S,unit=U,type=T,flags=Fs}, Def, Ps, St0) ->
- St1 = bit_type(U, T, Fs, St0),
- St2 = pat_bit_expr(S, T, Def, St1),
- pattern(V, Def, Ps, St2);
-pat_segment(_, _, Ps, St) ->
- {Ps,add_error({not_bs_pattern,St#lint.func}, St)}.
-
-%% pat_bit_expr(SizePat, Type, Defined, State) -> State.
-%% Check the Size pattern, this is an input! Be a bit tough here.
-
-pat_bit_expr(#c_int{val=I}, _, _, St) when I >= 0 -> St;
-pat_bit_expr(#c_var{name=N}, _, Def, St) ->
- expr_var(N, Def, St);
-pat_bit_expr(#c_atom{val=all}, binary, _Def, St) -> St;
-pat_bit_expr(_, _, _, St) ->
- add_error({illegal_expr,St#lint.func}, St).
-
-bit_type(Unit, Type, Flags, St) ->
- U = core_lib:literal_value(Unit),
- T = core_lib:literal_value(Type),
- Fs = core_lib:literal_value(Flags),
- case erl_bits:set_bit_type(default, [T,{unit,U}|Fs]) of
- {ok,_,_} -> St;
- {error,E} -> add_error({E,St#lint.func}, St)
- end.
-
-%% pattern_list([Var], Defined, State) -> {[PatVar],State}.
-%% pattern_list([Var], Defined, [PatVar], State) -> {[PatVar],State}.
-
-pattern_list(Pats, Def, St) -> pattern_list(Pats, Def, [], St).
-
-pattern_list(Pats, Def, Ps0, St0) ->
- foldl(fun (P, {Ps,St}) -> pattern(P, Def, Ps, St) end, {Ps0,St0}, Pats).
-
-%% pattern_match(Required, Supplied, State) -> State.
-%% Check that the required number of patterns match the supplied.
-
-pattern_match(N, N, St) -> St;
-pattern_match(_Req, _Sup, St) ->
- add_error({pattern_mismatch,St#lint.func}, St).
-
-%% return_match(Required, Supplied, State) -> State.
-%% Check that the required number of return values match the supplied.
-
-return_match(any, _Sup, St) -> St;
-return_match(_Req, unknown, St) -> St;
-return_match(N, N, St) -> St;
-return_match(_Req, _Sup, St) ->
- add_error({return_mismatch,St#lint.func}, St).
-
-%% arg_match(Required, Supplied, State) -> State.
-
-arg_match(_Req, unknown, St) -> St;
-arg_match(N, N, St) -> St;
-arg_match(_Req, _Sup, St) ->
- add_error({arg_mismatch,St#lint.func}, St).
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_parse.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_parse.erl
deleted file mode 100644
index 942845bef7..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_parse.erl
+++ /dev/null
@@ -1,4911 +0,0 @@
--module(core_parse).
--define(THIS_MODULE, core_parse).
--export([parse/1, parse_and_scan/1, format_error/1]).
-
--export([abstract/1,abstract/2,normalise/1]).
-
-%% The following directive is needed for (significantly) faster compilation
-%% of the generated .erl file by the HiPE compiler. Please do not remove.
--compile([{hipe,[{regalloc,linear_scan}]}]).
-
--include("core_parse.hrl").
-
-tok_val(T) -> element(3, T).
-tok_line(T) -> element(2, T).
-
-abstract(T, _N) -> abstract(T).
-
-abstract(Term) -> core_lib:make_literal(Term).
-
-normalise(Core) -> core_lib:literal_value(Core).
-
-%% ``The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance 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: core_parse.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
-%%
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% The parser generator will insert appropriate declarations before this line.%
-
-parse(Tokens) ->
- case catch yeccpars1(Tokens, false, 0, [], []) of
- error ->
- Errorline =
- if Tokens == [] -> 0; true -> element(2, hd(Tokens)) end,
- {error,
- {Errorline, ?THIS_MODULE, "syntax error at or after this line."}};
- Other ->
- Other
- end.
-
-parse_and_scan({Mod, Fun, Args}) ->
- case apply(Mod, Fun, Args) of
- {eof, _} ->
- {ok, eof};
- {error, Descriptor, _} ->
- {error, Descriptor};
- {ok, Tokens, _} ->
- yeccpars1(Tokens, {Mod, Fun, Args}, 0, [], [])
- end.
-
-format_error(Message) ->
- case io_lib:deep_char_list(Message) of
- true ->
- Message;
- _ ->
- io_lib:write(Message)
- end.
-
-% To be used in grammar files to throw an error message to the parser toplevel.
-% Doesn't have to be exported!
-return_error(Line, Message) ->
- throw({error, {Line, ?THIS_MODULE, Message}}).
-
-
-% Don't change yeccpars1/6 too much, it is called recursively by yeccpars2/8!
-yeccpars1([Token | Tokens], Tokenizer, State, States, Vstack) ->
- yeccpars2(State, element(1, Token), States, Vstack, Token, Tokens,
- Tokenizer);
-yeccpars1([], {M, F, A}, State, States, Vstack) ->
- case catch apply(M, F, A) of
- {eof, Endline} ->
- {error, {Endline, ?THIS_MODULE, "end_of_file"}};
- {error, Descriptor, _Endline} ->
- {error, Descriptor};
- {'EXIT', Reason} ->
- {error, {0, ?THIS_MODULE, Reason}};
- {ok, Tokens, _Endline} ->
- case catch yeccpars1(Tokens, {M, F, A}, State, States, Vstack) of
- error ->
- Errorline = element(2, hd(Tokens)),
- {error, {Errorline, ?THIS_MODULE,
- "syntax error at or after this line."}};
- Other ->
- Other
- end
- end;
-yeccpars1([], false, State, States, Vstack) ->
- yeccpars2(State, '$end', States, Vstack, {'$end', 999999}, [], false).
-
-% For internal use only.
-yeccerror(Token) ->
- {error,
- {element(2, Token), ?THIS_MODULE,
- ["syntax error before: ", yecctoken2string(Token)]}}.
-
-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_string(S);
-yecctoken2string({reserved_symbol, _, A}) -> io_lib:format('~w', [A]);
-yecctoken2string({_Cat, _, Val}) -> io_lib:format('~w', [Val]);
-
-yecctoken2string({'dot', _}) -> io_lib:format('~w', ['.']);
-yecctoken2string({'$end', _}) ->
- [];
-yecctoken2string({Other, _}) when atom(Other) ->
- io_lib:format('~w', [Other]);
-yecctoken2string(Other) ->
- io_lib:write(Other).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-yeccpars2(0, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 1, [0 | __Ss], [__T | __Stack]);
-yeccpars2(0, 'module', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 2, [0 | __Ss], [__T | __Stack]);
-yeccpars2(0, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(1, 'module', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 313, [1 | __Ss], [__T | __Stack]);
-yeccpars2(1, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(2, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 4, [2 | __Ss], [__T | __Stack]);
-yeccpars2(2, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(3, '$end', _, __Stack, _, _, _) ->
- {ok, hd(__Stack)};
-yeccpars2(3, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(4, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 5, [4 | __Ss], [__T | __Stack]);
-yeccpars2(4, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(5, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 11, [5 | __Ss], [__T | __Stack]);
-yeccpars2(5, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 306, [5 | __Ss], [__T | __Stack]);
-yeccpars2(5, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(6, 'attributes', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 7, [6 | __Ss], [__T | __Stack]);
-yeccpars2(6, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(7, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 276, [7 | __Ss], [__T | __Stack]);
-yeccpars2(7, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(8, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 9, [8 | __Ss], [__T | __Stack]);
-yeccpars2(8, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 11, [8 | __Ss], [__T | __Stack]);
-yeccpars2(8, __Cat, __Ss, __Stack, __T, __Ts, __Tzr) ->
- __Val = [],
- yeccpars2(13, __Cat, [8 | __Ss], [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(9, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 11, [9 | __Ss], [__T | __Stack]);
-yeccpars2(9, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(10, '=', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 20, [10 | __Ss], [__T | __Stack]);
-yeccpars2(10, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(11, '/', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 18, [11 | __Ss], [__T | __Stack]);
-yeccpars2(11, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(12, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 9, [12 | __Ss], [__T | __Stack]);
-yeccpars2(12, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 11, [12 | __Ss], [__T | __Stack]);
-yeccpars2(12, __Cat, __Ss, __Stack, __T, __Ts, __Tzr) ->
- __Val = [],
- yeccpars2(17, __Cat, [12 | __Ss], [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(13, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(module_defs, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(14, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(anno_function_name, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(15, 'end', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 16, [15 | __Ss], [__T | __Stack]);
-yeccpars2(15, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(16, __Cat, __Ss, [__6,__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_module{name = #c_atom{val = tok_val(__2)}, exports = __3, attrs = __4, defs = __5},
- __Nss = lists:nthtail(5, __Ss),
- yeccpars2(yeccgoto(module_definition, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(17, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1|__2],
- __Nss = lists:nthtail(1, __Ss),
- yeccpars2(yeccgoto(function_definitions, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(18, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 19, [18 | __Ss], [__T | __Stack]);
-yeccpars2(18, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(19, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_fname{id = tok_val(__1), arity = tok_val(__3)},
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(function_name, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(20, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [20 | __Ss], [__T | __Stack]);
-yeccpars2(20, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 21, [20 | __Ss], [__T | __Stack]);
-yeccpars2(20, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(21, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [21 | __Ss], [__T | __Stack]);
-yeccpars2(21, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(22, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_def{name = __1, val = __3},
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(function_definition, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(23, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 25, [23 | __Ss], [__T | __Stack]);
-yeccpars2(23, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(24, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(anno_fun, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(25, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 27, [25 | __Ss], [__T | __Stack]);
-yeccpars2(25, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 26, [25 | __Ss], [__T | __Stack]);
-yeccpars2(25, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [25 | __Ss], [__T | __Stack]);
-yeccpars2(25, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(26, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [26 | __Ss], [__T | __Stack]);
-yeccpars2(26, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(27, '->', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 265, [27 | __Ss], [__T | __Stack]);
-yeccpars2(27, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(28, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 263, [28 | __Ss], [__T | __Stack]);
-yeccpars2(28, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1],
- yeccpars2(yeccgoto(anno_variables, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(29, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 32, [29 | __Ss], [__T | __Stack]);
-yeccpars2(29, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(30, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_var{name = tok_val(__1)},
- yeccpars2(yeccgoto(variable, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(31, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(anno_variable, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(32, '->', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 33, [32 | __Ss], [__T | __Stack]);
-yeccpars2(32, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(33, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [33 | __Ss], [__T | __Stack]);
-yeccpars2(33, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(34, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 247, [34 | __Ss], [__T | __Stack]);
-yeccpars2(34, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(35, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [35 | __Ss], [__T | __Stack]);
-yeccpars2(35, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(36, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, '>', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 240, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [36 | __Ss], [__T | __Stack]);
-yeccpars2(36, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(37, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 149, [37 | __Ss], [__T | __Stack]);
-yeccpars2(37, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(38, __Cat, __Ss, [__6,__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_fun{vars = __3, body = __6},
- __Nss = lists:nthtail(5, __Ss),
- yeccpars2(yeccgoto(fun_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(39, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(40, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [40 | __Ss], [__T | __Stack]);
-yeccpars2(40, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(41, '/', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 18, [41 | __Ss], [__T | __Stack]);
-yeccpars2(41, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_atom{val = tok_val(__1)},
- yeccpars2(yeccgoto(atomic_literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(42, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(43, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(44, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [44 | __Ss], [__T | __Stack]);
-yeccpars2(44, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(45, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(46, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [46 | __Ss], [__T | __Stack]);
-yeccpars2(46, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(47, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(48, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [48 | __Ss], [__T | __Stack]);
-yeccpars2(48, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(49, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(50, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_char{val = tok_val(__1)},
- yeccpars2(yeccgoto(atomic_literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(51, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(52, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [52 | __Ss], [__T | __Stack]);
-yeccpars2(52, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(53, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(anno_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(54, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_float{val = tok_val(__1)},
- yeccpars2(yeccgoto(atomic_literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(55, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(56, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(57, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_int{val = tok_val(__1)},
- yeccpars2(yeccgoto(atomic_literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(58, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 83, [58 | __Ss], [__T | __Stack]);
-yeccpars2(58, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 26, [58 | __Ss], [__T | __Stack]);
-yeccpars2(58, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [58 | __Ss], [__T | __Stack]);
-yeccpars2(58, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(59, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(60, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 9, [60 | __Ss], [__T | __Stack]);
-yeccpars2(60, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 11, [60 | __Ss], [__T | __Stack]);
-yeccpars2(60, __Cat, __Ss, __Stack, __T, __Ts, __Tzr) ->
- __Val = [],
- yeccpars2(210, __Cat, [60 | __Ss], [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(61, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(62, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_nil{},
- yeccpars2(yeccgoto(atomic_literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(63, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 208, [63 | __Ss], [__T | __Stack]);
-yeccpars2(63, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(64, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(65, 'after', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 99, [65 | __Ss], [__T | __Stack]);
-yeccpars2(65, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 97, [65 | __Ss], [__T | __Stack]);
-yeccpars2(65, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 96, [65 | __Ss], [__T | __Stack]);
-yeccpars2(65, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [65 | __Ss], [__T | __Stack]);
-yeccpars2(65, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 104, [65 | __Ss], [__T | __Stack]);
-yeccpars2(65, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [65 | __Ss], [__T | __Stack]);
-yeccpars2(65, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [65 | __Ss], [__T | __Stack]);
-yeccpars2(65, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [65 | __Ss], [__T | __Stack]);
-yeccpars2(65, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [65 | __Ss], [__T | __Stack]);
-yeccpars2(65, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 95, [65 | __Ss], [__T | __Stack]);
-yeccpars2(65, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 98, [65 | __Ss], [__T | __Stack]);
-yeccpars2(65, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 114, [65 | __Ss], [__T | __Stack]);
-yeccpars2(65, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(66, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(67, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(68, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(69, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_string{val = tok_val(__1)},
- yeccpars2(yeccgoto(atomic_literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(70, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [70 | __Ss], [__T | __Stack]);
-yeccpars2(70, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(71, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(72, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(73, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(single_expression, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(74, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 77, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [74 | __Ss], [__T | __Stack]);
-yeccpars2(74, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(75, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 79, [75 | __Ss], [__T | __Stack]);
-yeccpars2(75, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1],
- yeccpars2(yeccgoto(anno_expressions, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(76, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 78, [76 | __Ss], [__T | __Stack]);
-yeccpars2(76, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(77, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_tuple{es = []},
- __Nss = lists:nthtail(1, __Ss),
- yeccpars2(yeccgoto(tuple, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(78, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_tuple{es = __2},
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(tuple, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(79, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [79 | __Ss], [__T | __Stack]);
-yeccpars2(79, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(80, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1|__3],
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(anno_expressions, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(81, 'of', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 82, [81 | __Ss], [__T | __Stack]);
-yeccpars2(81, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(82, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 83, [82 | __Ss], [__T | __Stack]);
-yeccpars2(82, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 26, [82 | __Ss], [__T | __Stack]);
-yeccpars2(82, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [82 | __Ss], [__T | __Stack]);
-yeccpars2(82, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(83, '>', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 92, [83 | __Ss], [__T | __Stack]);
-yeccpars2(83, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 26, [83 | __Ss], [__T | __Stack]);
-yeccpars2(83, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [83 | __Ss], [__T | __Stack]);
-yeccpars2(83, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(84, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1],
- yeccpars2(yeccgoto(let_vars, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(85, '->', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 86, [85 | __Ss], [__T | __Stack]);
-yeccpars2(85, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(86, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [86 | __Ss], [__T | __Stack]);
-yeccpars2(86, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(87, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 88, [87 | __Ss], [__T | __Stack]);
-yeccpars2(87, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(88, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 83, [88 | __Ss], [__T | __Stack]);
-yeccpars2(88, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 26, [88 | __Ss], [__T | __Stack]);
-yeccpars2(88, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [88 | __Ss], [__T | __Stack]);
-yeccpars2(88, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(89, '->', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 90, [89 | __Ss], [__T | __Stack]);
-yeccpars2(89, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(90, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [90 | __Ss], [__T | __Stack]);
-yeccpars2(90, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(91, __Cat, __Ss, [__10,__9,__8,__7,__6,__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = if length(__8) == 2 -> #c_try{arg = __2, vars = __4, body = __6, evars = __8, handler = __10}; true -> return_error(tok_line(__7),"expected 2 exception variables in 'try'") end,
- __Nss = lists:nthtail(9, __Ss),
- yeccpars2(yeccgoto(try_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(92, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [],
- __Nss = lists:nthtail(1, __Ss),
- yeccpars2(yeccgoto(let_vars, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(93, '>', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 94, [93 | __Ss], [__T | __Stack]);
-yeccpars2(93, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(94, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __2,
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(let_vars, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(95, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 190, [95 | __Ss], [__T | __Stack]);
-yeccpars2(95, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(96, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 97, [96 | __Ss], [__T | __Stack]);
-yeccpars2(96, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [96 | __Ss], [__T | __Stack]);
-yeccpars2(96, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 104, [96 | __Ss], [__T | __Stack]);
-yeccpars2(96, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [96 | __Ss], [__T | __Stack]);
-yeccpars2(96, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [96 | __Ss], [__T | __Stack]);
-yeccpars2(96, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [96 | __Ss], [__T | __Stack]);
-yeccpars2(96, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 115, [96 | __Ss], [__T | __Stack]);
-yeccpars2(96, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [96 | __Ss], [__T | __Stack]);
-yeccpars2(96, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 95, [96 | __Ss], [__T | __Stack]);
-yeccpars2(96, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 98, [96 | __Ss], [__T | __Stack]);
-yeccpars2(96, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 114, [96 | __Ss], [__T | __Stack]);
-yeccpars2(96, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(97, '>', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 182, [97 | __Ss], [__T | __Stack]);
-yeccpars2(97, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [97 | __Ss], [__T | __Stack]);
-yeccpars2(97, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 104, [97 | __Ss], [__T | __Stack]);
-yeccpars2(97, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [97 | __Ss], [__T | __Stack]);
-yeccpars2(97, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [97 | __Ss], [__T | __Stack]);
-yeccpars2(97, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [97 | __Ss], [__T | __Stack]);
-yeccpars2(97, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 115, [97 | __Ss], [__T | __Stack]);
-yeccpars2(97, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [97 | __Ss], [__T | __Stack]);
-yeccpars2(97, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 95, [97 | __Ss], [__T | __Stack]);
-yeccpars2(97, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 98, [97 | __Ss], [__T | __Stack]);
-yeccpars2(97, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 114, [97 | __Ss], [__T | __Stack]);
-yeccpars2(97, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(98, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [98 | __Ss], [__T | __Stack]);
-yeccpars2(98, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 104, [98 | __Ss], [__T | __Stack]);
-yeccpars2(98, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [98 | __Ss], [__T | __Stack]);
-yeccpars2(98, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [98 | __Ss], [__T | __Stack]);
-yeccpars2(98, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [98 | __Ss], [__T | __Stack]);
-yeccpars2(98, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 115, [98 | __Ss], [__T | __Stack]);
-yeccpars2(98, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [98 | __Ss], [__T | __Stack]);
-yeccpars2(98, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 95, [98 | __Ss], [__T | __Stack]);
-yeccpars2(98, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 98, [98 | __Ss], [__T | __Stack]);
-yeccpars2(98, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 114, [98 | __Ss], [__T | __Stack]);
-yeccpars2(98, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 149, [98 | __Ss], [__T | __Stack]);
-yeccpars2(98, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(99, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [99 | __Ss], [__T | __Stack]);
-yeccpars2(99, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(100, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 97, [100 | __Ss], [__T | __Stack]);
-yeccpars2(100, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 96, [100 | __Ss], [__T | __Stack]);
-yeccpars2(100, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [100 | __Ss], [__T | __Stack]);
-yeccpars2(100, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 104, [100 | __Ss], [__T | __Stack]);
-yeccpars2(100, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [100 | __Ss], [__T | __Stack]);
-yeccpars2(100, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [100 | __Ss], [__T | __Stack]);
-yeccpars2(100, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [100 | __Ss], [__T | __Stack]);
-yeccpars2(100, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [100 | __Ss], [__T | __Stack]);
-yeccpars2(100, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 95, [100 | __Ss], [__T | __Stack]);
-yeccpars2(100, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 98, [100 | __Ss], [__T | __Stack]);
-yeccpars2(100, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 114, [100 | __Ss], [__T | __Stack]);
-yeccpars2(100, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1],
- yeccpars2(yeccgoto(anno_clauses, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(101, 'after', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 99, [101 | __Ss], [__T | __Stack]);
-yeccpars2(101, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(102, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1],
- yeccpars2(yeccgoto(clause_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(103, '=', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 162, [103 | __Ss], [__T | __Stack]);
-yeccpars2(103, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(anno_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(104, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_atom{val = tok_val(__1)},
- yeccpars2(yeccgoto(atomic_literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(105, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(atomic_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(106, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(other_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(107, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(other_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(108, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(anno_clause, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(109, 'when', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 164, [109 | __Ss], [__T | __Stack]);
-yeccpars2(109, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(110, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(other_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(111, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(anno_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(112, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = begin
- {T,A} = __2, #c_receive{clauses = [], timeout = T, action = A}
- end,
- __Nss = lists:nthtail(1, __Ss),
- yeccpars2(yeccgoto(receive_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(113, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(other_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(114, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [114 | __Ss], [__T | __Stack]);
-yeccpars2(114, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 104, [114 | __Ss], [__T | __Stack]);
-yeccpars2(114, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [114 | __Ss], [__T | __Stack]);
-yeccpars2(114, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [114 | __Ss], [__T | __Stack]);
-yeccpars2(114, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [114 | __Ss], [__T | __Stack]);
-yeccpars2(114, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 115, [114 | __Ss], [__T | __Stack]);
-yeccpars2(114, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [114 | __Ss], [__T | __Stack]);
-yeccpars2(114, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 95, [114 | __Ss], [__T | __Stack]);
-yeccpars2(114, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 98, [114 | __Ss], [__T | __Stack]);
-yeccpars2(114, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 114, [114 | __Ss], [__T | __Stack]);
-yeccpars2(114, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 118, [114 | __Ss], [__T | __Stack]);
-yeccpars2(114, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(115, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [115 | __Ss], [__T | __Stack]);
-yeccpars2(115, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 104, [115 | __Ss], [__T | __Stack]);
-yeccpars2(115, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [115 | __Ss], [__T | __Stack]);
-yeccpars2(115, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [115 | __Ss], [__T | __Stack]);
-yeccpars2(115, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [115 | __Ss], [__T | __Stack]);
-yeccpars2(115, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 26, [115 | __Ss], [__T | __Stack]);
-yeccpars2(115, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [115 | __Ss], [__T | __Stack]);
-yeccpars2(115, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 95, [115 | __Ss], [__T | __Stack]);
-yeccpars2(115, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 98, [115 | __Ss], [__T | __Stack]);
-yeccpars2(115, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 114, [115 | __Ss], [__T | __Stack]);
-yeccpars2(115, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(116, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 120, [116 | __Ss], [__T | __Stack]);
-yeccpars2(116, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1],
- yeccpars2(yeccgoto(anno_patterns, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(117, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 119, [117 | __Ss], [__T | __Stack]);
-yeccpars2(117, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(118, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_tuple{es = []},
- __Nss = lists:nthtail(1, __Ss),
- yeccpars2(yeccgoto(tuple_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(119, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_tuple{es = __2},
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(tuple_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(120, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [120 | __Ss], [__T | __Stack]);
-yeccpars2(120, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 104, [120 | __Ss], [__T | __Stack]);
-yeccpars2(120, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [120 | __Ss], [__T | __Stack]);
-yeccpars2(120, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [120 | __Ss], [__T | __Stack]);
-yeccpars2(120, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [120 | __Ss], [__T | __Stack]);
-yeccpars2(120, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 115, [120 | __Ss], [__T | __Stack]);
-yeccpars2(120, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [120 | __Ss], [__T | __Stack]);
-yeccpars2(120, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 95, [120 | __Ss], [__T | __Stack]);
-yeccpars2(120, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 98, [120 | __Ss], [__T | __Stack]);
-yeccpars2(120, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 114, [120 | __Ss], [__T | __Stack]);
-yeccpars2(120, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(121, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1|__3],
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(anno_patterns, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(122, '=', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 162, [122 | __Ss], [__T | __Stack]);
-yeccpars2(122, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(123, '-|', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 159, [123 | __Ss], [__T | __Stack]);
-yeccpars2(123, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(124, '-|', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 125, [124 | __Ss], [__T | __Stack]);
-yeccpars2(124, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(anno_variable, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(125, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 126, [125 | __Ss], [__T | __Stack]);
-yeccpars2(125, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(126, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 129, [126 | __Ss], [__T | __Stack]);
-yeccpars2(126, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 142, [126 | __Ss], [__T | __Stack]);
-yeccpars2(126, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 140, [126 | __Ss], [__T | __Stack]);
-yeccpars2(126, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 131, [126 | __Ss], [__T | __Stack]);
-yeccpars2(126, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 137, [126 | __Ss], [__T | __Stack]);
-yeccpars2(126, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 138, [126 | __Ss], [__T | __Stack]);
-yeccpars2(126, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 133, [126 | __Ss], [__T | __Stack]);
-yeccpars2(126, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 130, [126 | __Ss], [__T | __Stack]);
-yeccpars2(126, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(127, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 128, [127 | __Ss], [__T | __Stack]);
-yeccpars2(127, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(128, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = core_lib:set_anno(__2,__4),
- __Nss = lists:nthtail(4, __Ss),
- yeccpars2(yeccgoto(anno_variable, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(129, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 129, [129 | __Ss], [__T | __Stack]);
-yeccpars2(129, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 142, [129 | __Ss], [__T | __Stack]);
-yeccpars2(129, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 140, [129 | __Ss], [__T | __Stack]);
-yeccpars2(129, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 131, [129 | __Ss], [__T | __Stack]);
-yeccpars2(129, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 137, [129 | __Ss], [__T | __Stack]);
-yeccpars2(129, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 138, [129 | __Ss], [__T | __Stack]);
-yeccpars2(129, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 133, [129 | __Ss], [__T | __Stack]);
-yeccpars2(129, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 149, [129 | __Ss], [__T | __Stack]);
-yeccpars2(129, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(130, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [],
- __Nss = lists:nthtail(1, __Ss),
- yeccpars2(yeccgoto(annotation, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(131, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = tok_val(__1),
- yeccpars2(yeccgoto(atomic_constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(132, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(133, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = tok_val(__1),
- yeccpars2(yeccgoto(atomic_constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(134, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(135, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 147, [135 | __Ss], [__T | __Stack]);
-yeccpars2(135, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1],
- yeccpars2(yeccgoto(constants, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(136, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 146, [136 | __Ss], [__T | __Stack]);
-yeccpars2(136, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(137, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = tok_val(__1),
- yeccpars2(yeccgoto(atomic_constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(138, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = tok_val(__1),
- yeccpars2(yeccgoto(atomic_constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(139, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [],
- yeccpars2(yeccgoto(atomic_constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(140, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = tok_val(__1),
- yeccpars2(yeccgoto(atomic_constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(141, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(142, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 129, [142 | __Ss], [__T | __Stack]);
-yeccpars2(142, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 142, [142 | __Ss], [__T | __Stack]);
-yeccpars2(142, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 144, [142 | __Ss], [__T | __Stack]);
-yeccpars2(142, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 140, [142 | __Ss], [__T | __Stack]);
-yeccpars2(142, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 131, [142 | __Ss], [__T | __Stack]);
-yeccpars2(142, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 137, [142 | __Ss], [__T | __Stack]);
-yeccpars2(142, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 138, [142 | __Ss], [__T | __Stack]);
-yeccpars2(142, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 133, [142 | __Ss], [__T | __Stack]);
-yeccpars2(142, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(143, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 145, [143 | __Ss], [__T | __Stack]);
-yeccpars2(143, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(144, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = {},
- __Nss = lists:nthtail(1, __Ss),
- yeccpars2(yeccgoto(tuple_constant, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(145, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = list_to_tuple(__2),
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(tuple_constant, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(146, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __2,
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(annotation, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(147, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 129, [147 | __Ss], [__T | __Stack]);
-yeccpars2(147, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 142, [147 | __Ss], [__T | __Stack]);
-yeccpars2(147, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 140, [147 | __Ss], [__T | __Stack]);
-yeccpars2(147, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 131, [147 | __Ss], [__T | __Stack]);
-yeccpars2(147, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 137, [147 | __Ss], [__T | __Stack]);
-yeccpars2(147, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 138, [147 | __Ss], [__T | __Stack]);
-yeccpars2(147, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 133, [147 | __Ss], [__T | __Stack]);
-yeccpars2(147, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(148, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1|__3],
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(constants, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(149, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = {nil,tok_line(__1)},
- __Nss = lists:nthtail(1, __Ss),
- yeccpars2(yeccgoto(nil, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(150, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 151, [150 | __Ss], [__T | __Stack]);
-yeccpars2(150, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 154, [150 | __Ss], [__T | __Stack]);
-yeccpars2(150, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 152, [150 | __Ss], [__T | __Stack]);
-yeccpars2(150, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(151, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 129, [151 | __Ss], [__T | __Stack]);
-yeccpars2(151, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 142, [151 | __Ss], [__T | __Stack]);
-yeccpars2(151, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 140, [151 | __Ss], [__T | __Stack]);
-yeccpars2(151, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 131, [151 | __Ss], [__T | __Stack]);
-yeccpars2(151, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 137, [151 | __Ss], [__T | __Stack]);
-yeccpars2(151, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 138, [151 | __Ss], [__T | __Stack]);
-yeccpars2(151, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 133, [151 | __Ss], [__T | __Stack]);
-yeccpars2(151, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(152, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [],
- yeccpars2(yeccgoto(tail_constant, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(153, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__2|__3],
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(cons_constant, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(154, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 129, [154 | __Ss], [__T | __Stack]);
-yeccpars2(154, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 142, [154 | __Ss], [__T | __Stack]);
-yeccpars2(154, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 140, [154 | __Ss], [__T | __Stack]);
-yeccpars2(154, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 131, [154 | __Ss], [__T | __Stack]);
-yeccpars2(154, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 137, [154 | __Ss], [__T | __Stack]);
-yeccpars2(154, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 138, [154 | __Ss], [__T | __Stack]);
-yeccpars2(154, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 133, [154 | __Ss], [__T | __Stack]);
-yeccpars2(154, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(155, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 156, [155 | __Ss], [__T | __Stack]);
-yeccpars2(155, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(156, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __2,
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(tail_constant, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(157, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 151, [157 | __Ss], [__T | __Stack]);
-yeccpars2(157, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 154, [157 | __Ss], [__T | __Stack]);
-yeccpars2(157, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 152, [157 | __Ss], [__T | __Stack]);
-yeccpars2(157, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(158, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__2|__3],
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(tail_constant, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(159, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 126, [159 | __Ss], [__T | __Stack]);
-yeccpars2(159, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(160, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 161, [160 | __Ss], [__T | __Stack]);
-yeccpars2(160, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(161, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = core_lib:set_anno(__2,__4),
- __Nss = lists:nthtail(4, __Ss),
- yeccpars2(yeccgoto(anno_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(162, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [162 | __Ss], [__T | __Stack]);
-yeccpars2(162, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 104, [162 | __Ss], [__T | __Stack]);
-yeccpars2(162, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [162 | __Ss], [__T | __Stack]);
-yeccpars2(162, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [162 | __Ss], [__T | __Stack]);
-yeccpars2(162, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [162 | __Ss], [__T | __Stack]);
-yeccpars2(162, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 115, [162 | __Ss], [__T | __Stack]);
-yeccpars2(162, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [162 | __Ss], [__T | __Stack]);
-yeccpars2(162, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 95, [162 | __Ss], [__T | __Stack]);
-yeccpars2(162, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 98, [162 | __Ss], [__T | __Stack]);
-yeccpars2(162, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 114, [162 | __Ss], [__T | __Stack]);
-yeccpars2(162, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(163, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_alias{var = __1, pat = __3},
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(other_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(164, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [164 | __Ss], [__T | __Stack]);
-yeccpars2(164, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(165, '->', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 166, [165 | __Ss], [__T | __Stack]);
-yeccpars2(165, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(166, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [166 | __Ss], [__T | __Stack]);
-yeccpars2(166, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(167, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_clause{pats = __1, guard = __3, body = __5},
- __Nss = lists:nthtail(4, __Ss),
- yeccpars2(yeccgoto(clause, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(168, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = begin
- {T,A} = __3, #c_receive{clauses = __2, timeout = T, action = A}
- end,
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(receive_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(169, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1|__2],
- __Nss = lists:nthtail(1, __Ss),
- yeccpars2(yeccgoto(anno_clauses, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(170, '->', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 171, [170 | __Ss], [__T | __Stack]);
-yeccpars2(170, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(171, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [171 | __Ss], [__T | __Stack]);
-yeccpars2(171, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(172, __Cat, __Ss, [__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = {__2,__4},
- __Nss = lists:nthtail(3, __Ss),
- yeccpars2(yeccgoto(timeout, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(173, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 174, [173 | __Ss], [__T | __Stack]);
-yeccpars2(173, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 177, [173 | __Ss], [__T | __Stack]);
-yeccpars2(173, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 175, [173 | __Ss], [__T | __Stack]);
-yeccpars2(173, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(174, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [174 | __Ss], [__T | __Stack]);
-yeccpars2(174, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 104, [174 | __Ss], [__T | __Stack]);
-yeccpars2(174, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [174 | __Ss], [__T | __Stack]);
-yeccpars2(174, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [174 | __Ss], [__T | __Stack]);
-yeccpars2(174, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [174 | __Ss], [__T | __Stack]);
-yeccpars2(174, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 115, [174 | __Ss], [__T | __Stack]);
-yeccpars2(174, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [174 | __Ss], [__T | __Stack]);
-yeccpars2(174, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 95, [174 | __Ss], [__T | __Stack]);
-yeccpars2(174, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 98, [174 | __Ss], [__T | __Stack]);
-yeccpars2(174, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 114, [174 | __Ss], [__T | __Stack]);
-yeccpars2(174, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(175, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_nil{},
- yeccpars2(yeccgoto(tail_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(176, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_cons{hd = __2, tl = __3},
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(cons_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(177, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [177 | __Ss], [__T | __Stack]);
-yeccpars2(177, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 104, [177 | __Ss], [__T | __Stack]);
-yeccpars2(177, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [177 | __Ss], [__T | __Stack]);
-yeccpars2(177, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [177 | __Ss], [__T | __Stack]);
-yeccpars2(177, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [177 | __Ss], [__T | __Stack]);
-yeccpars2(177, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 115, [177 | __Ss], [__T | __Stack]);
-yeccpars2(177, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [177 | __Ss], [__T | __Stack]);
-yeccpars2(177, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 95, [177 | __Ss], [__T | __Stack]);
-yeccpars2(177, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 98, [177 | __Ss], [__T | __Stack]);
-yeccpars2(177, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 114, [177 | __Ss], [__T | __Stack]);
-yeccpars2(177, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(178, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 179, [178 | __Ss], [__T | __Stack]);
-yeccpars2(178, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(179, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __2,
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(tail_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(180, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 174, [180 | __Ss], [__T | __Stack]);
-yeccpars2(180, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 177, [180 | __Ss], [__T | __Stack]);
-yeccpars2(180, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 175, [180 | __Ss], [__T | __Stack]);
-yeccpars2(180, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(181, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_cons{hd = __2, tl = __3},
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(tail_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(182, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [],
- __Nss = lists:nthtail(1, __Ss),
- yeccpars2(yeccgoto(clause_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(183, '>', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 184, [183 | __Ss], [__T | __Stack]);
-yeccpars2(183, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(184, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __2,
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(clause_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(185, '-|', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 187, [185 | __Ss], [__T | __Stack]);
-yeccpars2(185, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(186, '-|', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 159, [186 | __Ss], [__T | __Stack]);
-yeccpars2(186, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(anno_pattern, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(187, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 126, [187 | __Ss], [__T | __Stack]);
-yeccpars2(187, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(188, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 189, [188 | __Ss], [__T | __Stack]);
-yeccpars2(188, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(189, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = core_lib:set_anno(__2,__4),
- __Nss = lists:nthtail(4, __Ss),
- yeccpars2(yeccgoto(anno_clause, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(190, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 191, [190 | __Ss], [__T | __Stack]);
-yeccpars2(190, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 194, [190 | __Ss], [__T | __Stack]);
-yeccpars2(190, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(191, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 200, [191 | __Ss], [__T | __Stack]);
-yeccpars2(191, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(192, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 198, [192 | __Ss], [__T | __Stack]);
-yeccpars2(192, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1],
- yeccpars2(yeccgoto(segment_patterns, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(193, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 196, [193 | __Ss], [__T | __Stack]);
-yeccpars2(193, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(194, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 195, [194 | __Ss], [__T | __Stack]);
-yeccpars2(194, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(195, __Cat, __Ss, [__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_binary{segments = []},
- __Nss = lists:nthtail(3, __Ss),
- yeccpars2(yeccgoto(binary_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(196, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 197, [196 | __Ss], [__T | __Stack]);
-yeccpars2(196, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(197, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_binary{segments = __3},
- __Nss = lists:nthtail(4, __Ss),
- yeccpars2(yeccgoto(binary_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(198, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 191, [198 | __Ss], [__T | __Stack]);
-yeccpars2(198, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(199, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1|__3],
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(segment_patterns, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(200, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [200 | __Ss], [__T | __Stack]);
-yeccpars2(200, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 104, [200 | __Ss], [__T | __Stack]);
-yeccpars2(200, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [200 | __Ss], [__T | __Stack]);
-yeccpars2(200, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [200 | __Ss], [__T | __Stack]);
-yeccpars2(200, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [200 | __Ss], [__T | __Stack]);
-yeccpars2(200, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 115, [200 | __Ss], [__T | __Stack]);
-yeccpars2(200, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [200 | __Ss], [__T | __Stack]);
-yeccpars2(200, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 95, [200 | __Ss], [__T | __Stack]);
-yeccpars2(200, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 98, [200 | __Ss], [__T | __Stack]);
-yeccpars2(200, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 114, [200 | __Ss], [__T | __Stack]);
-yeccpars2(200, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(201, '>', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 202, [201 | __Ss], [__T | __Stack]);
-yeccpars2(201, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(202, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 203, [202 | __Ss], [__T | __Stack]);
-yeccpars2(202, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(203, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 205, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [203 | __Ss], [__T | __Stack]);
-yeccpars2(203, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(204, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = case __5 of [S,U,T,Fs] -> #c_bitstr{val = __3, size = S, unit = U, type = T, flags = Fs}; true -> return_error(tok_line(__1),"expected 4 arguments in binary segment") end,
- __Nss = lists:nthtail(4, __Ss),
- yeccpars2(yeccgoto(segment_pattern, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(205, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [],
- __Nss = lists:nthtail(1, __Ss),
- yeccpars2(yeccgoto(arg_list, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(206, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 207, [206 | __Ss], [__T | __Stack]);
-yeccpars2(206, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(207, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __2,
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(arg_list, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(208, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 203, [208 | __Ss], [__T | __Stack]);
-yeccpars2(208, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(209, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = begin
- Name = #c_atom{val = tok_val(__2)}, #c_primop{name = Name, args = __3}
- end,
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(primop_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(210, 'in', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 211, [210 | __Ss], [__T | __Stack]);
-yeccpars2(210, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(211, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [211 | __Ss], [__T | __Stack]);
-yeccpars2(211, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(212, __Cat, __Ss, [__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_letrec{defs = __2, body = __4},
- __Nss = lists:nthtail(3, __Ss),
- yeccpars2(yeccgoto(letrec_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(213, '=', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 214, [213 | __Ss], [__T | __Stack]);
-yeccpars2(213, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(214, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [214 | __Ss], [__T | __Stack]);
-yeccpars2(214, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(215, 'in', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 216, [215 | __Ss], [__T | __Stack]);
-yeccpars2(215, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(216, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [216 | __Ss], [__T | __Stack]);
-yeccpars2(216, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(217, __Cat, __Ss, [__6,__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_let{vars = __2, arg = __4, body = __6},
- __Nss = lists:nthtail(5, __Ss),
- yeccpars2(yeccgoto(let_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(218, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [218 | __Ss], [__T | __Stack]);
-yeccpars2(218, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(219, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_seq{arg = __2, body = __3},
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(sequence, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(220, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_catch{body = __2},
- __Nss = lists:nthtail(1, __Ss),
- yeccpars2(yeccgoto(catch_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(221, 'of', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 222, [221 | __Ss], [__T | __Stack]);
-yeccpars2(221, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(222, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 97, [222 | __Ss], [__T | __Stack]);
-yeccpars2(222, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 96, [222 | __Ss], [__T | __Stack]);
-yeccpars2(222, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [222 | __Ss], [__T | __Stack]);
-yeccpars2(222, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 104, [222 | __Ss], [__T | __Stack]);
-yeccpars2(222, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [222 | __Ss], [__T | __Stack]);
-yeccpars2(222, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [222 | __Ss], [__T | __Stack]);
-yeccpars2(222, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [222 | __Ss], [__T | __Stack]);
-yeccpars2(222, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [222 | __Ss], [__T | __Stack]);
-yeccpars2(222, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 95, [222 | __Ss], [__T | __Stack]);
-yeccpars2(222, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 98, [222 | __Ss], [__T | __Stack]);
-yeccpars2(222, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 114, [222 | __Ss], [__T | __Stack]);
-yeccpars2(222, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(223, 'end', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 224, [223 | __Ss], [__T | __Stack]);
-yeccpars2(223, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(224, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_case{arg = __2, clauses = __4},
- __Nss = lists:nthtail(4, __Ss),
- yeccpars2(yeccgoto(case_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(225, ':', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 226, [225 | __Ss], [__T | __Stack]);
-yeccpars2(225, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(226, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [226 | __Ss], [__T | __Stack]);
-yeccpars2(226, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(227, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 203, [227 | __Ss], [__T | __Stack]);
-yeccpars2(227, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(228, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_call{module = __2, name = __4, args = __5},
- __Nss = lists:nthtail(4, __Ss),
- yeccpars2(yeccgoto(call_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(229, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 203, [229 | __Ss], [__T | __Stack]);
-yeccpars2(229, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(230, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_apply{op = __2, args = __3},
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(application_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(231, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 232, [231 | __Ss], [__T | __Stack]);
-yeccpars2(231, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 235, [231 | __Ss], [__T | __Stack]);
-yeccpars2(231, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 233, [231 | __Ss], [__T | __Stack]);
-yeccpars2(231, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(232, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [232 | __Ss], [__T | __Stack]);
-yeccpars2(232, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(233, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_nil{},
- yeccpars2(yeccgoto(tail, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(234, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_cons{hd = __2, tl = __3},
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(cons, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(235, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [235 | __Ss], [__T | __Stack]);
-yeccpars2(235, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(236, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 237, [236 | __Ss], [__T | __Stack]);
-yeccpars2(236, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(237, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __2,
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(tail, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(238, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 232, [238 | __Ss], [__T | __Stack]);
-yeccpars2(238, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 235, [238 | __Ss], [__T | __Stack]);
-yeccpars2(238, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 233, [238 | __Ss], [__T | __Stack]);
-yeccpars2(238, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(239, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_cons{hd = __2, tl = __3},
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(tail, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(240, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_values{es = []},
- __Nss = lists:nthtail(1, __Ss),
- yeccpars2(yeccgoto(expression, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(241, '>', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 242, [241 | __Ss], [__T | __Stack]);
-yeccpars2(241, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(242, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_values{es = __2},
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(expression, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(243, '-|', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 244, [243 | __Ss], [__T | __Stack]);
-yeccpars2(243, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(244, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 126, [244 | __Ss], [__T | __Stack]);
-yeccpars2(244, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(245, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 246, [245 | __Ss], [__T | __Stack]);
-yeccpars2(245, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(246, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = core_lib:set_anno(__2,__4),
- __Nss = lists:nthtail(4, __Ss),
- yeccpars2(yeccgoto(anno_expression, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(247, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 248, [247 | __Ss], [__T | __Stack]);
-yeccpars2(247, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 251, [247 | __Ss], [__T | __Stack]);
-yeccpars2(247, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(248, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 257, [248 | __Ss], [__T | __Stack]);
-yeccpars2(248, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(249, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 255, [249 | __Ss], [__T | __Stack]);
-yeccpars2(249, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1],
- yeccpars2(yeccgoto(segments, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(250, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 253, [250 | __Ss], [__T | __Stack]);
-yeccpars2(250, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(251, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 252, [251 | __Ss], [__T | __Stack]);
-yeccpars2(251, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(252, __Cat, __Ss, [__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_binary{segments = []},
- __Nss = lists:nthtail(3, __Ss),
- yeccpars2(yeccgoto(binary, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(253, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 254, [253 | __Ss], [__T | __Stack]);
-yeccpars2(253, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(254, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_binary{segments = __3},
- __Nss = lists:nthtail(4, __Ss),
- yeccpars2(yeccgoto(binary, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(255, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 248, [255 | __Ss], [__T | __Stack]);
-yeccpars2(255, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(256, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1|__3],
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(segments, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(257, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [257 | __Ss], [__T | __Stack]);
-yeccpars2(257, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(258, '>', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 259, [258 | __Ss], [__T | __Stack]);
-yeccpars2(258, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(259, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 260, [259 | __Ss], [__T | __Stack]);
-yeccpars2(259, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(260, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [260 | __Ss], [__T | __Stack]);
-yeccpars2(260, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(261, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 262, [261 | __Ss], [__T | __Stack]);
-yeccpars2(261, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(262, __Cat, __Ss, [__7,__6,__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = case __6 of [S,U,T,Fs] -> #c_bitstr{val = __3, size = S, unit = U, type = T, flags = Fs}; true -> return_error(tok_line(__1),"expected 4 arguments in binary segment") end,
- __Nss = lists:nthtail(6, __Ss),
- yeccpars2(yeccgoto(segment, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(263, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 26, [263 | __Ss], [__T | __Stack]);
-yeccpars2(263, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [263 | __Ss], [__T | __Stack]);
-yeccpars2(263, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(264, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1|__3],
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(anno_variables, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(265, 'receive', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 65, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, 'catch', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 48, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, 'try', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 70, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, 'primop', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 63, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, 'call', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 44, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, 'apply', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 40, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, 'case', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 46, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, 'letrec', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 60, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, 'let', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 58, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, 'fun', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 23, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, 'do', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 52, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 41, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, '#', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 34, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 37, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 74, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, '<', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 36, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 35, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, 'var', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 30, [265 | __Ss], [__T | __Stack]);
-yeccpars2(265, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(266, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_fun{vars = [], body = __5},
- __Nss = lists:nthtail(4, __Ss),
- yeccpars2(yeccgoto(fun_expr, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(267, '-|', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 125, [267 | __Ss], [__T | __Stack]);
-yeccpars2(267, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(268, '-|', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 269, [268 | __Ss], [__T | __Stack]);
-yeccpars2(268, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(269, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 126, [269 | __Ss], [__T | __Stack]);
-yeccpars2(269, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(270, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 271, [270 | __Ss], [__T | __Stack]);
-yeccpars2(270, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(271, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = core_lib:set_anno(__2,__4),
- __Nss = lists:nthtail(4, __Ss),
- yeccpars2(yeccgoto(anno_fun, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(272, '-|', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 273, [272 | __Ss], [__T | __Stack]);
-yeccpars2(272, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(273, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 126, [273 | __Ss], [__T | __Stack]);
-yeccpars2(273, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(274, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 275, [274 | __Ss], [__T | __Stack]);
-yeccpars2(274, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(275, __Cat, __Ss, [__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = core_lib:set_anno(__2,__4),
- __Nss = lists:nthtail(4, __Ss),
- yeccpars2(yeccgoto(anno_function_name, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(276, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 278, [276 | __Ss], [__T | __Stack]);
-yeccpars2(276, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 277, [276 | __Ss], [__T | __Stack]);
-yeccpars2(276, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(277, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [],
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(module_attribute, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(278, '=', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 284, [278 | __Ss], [__T | __Stack]);
-yeccpars2(278, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(279, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 282, [279 | __Ss], [__T | __Stack]);
-yeccpars2(279, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1],
- yeccpars2(yeccgoto(attribute_list, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(280, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 281, [280 | __Ss], [__T | __Stack]);
-yeccpars2(280, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(281, __Cat, __Ss, [__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __3,
- __Nss = lists:nthtail(3, __Ss),
- yeccpars2(yeccgoto(module_attribute, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(282, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 278, [282 | __Ss], [__T | __Stack]);
-yeccpars2(282, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(283, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1|__3],
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(attribute_list, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(284, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 285, [284 | __Ss], [__T | __Stack]);
-yeccpars2(284, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 290, [284 | __Ss], [__T | __Stack]);
-yeccpars2(284, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [284 | __Ss], [__T | __Stack]);
-yeccpars2(284, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 104, [284 | __Ss], [__T | __Stack]);
-yeccpars2(284, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [284 | __Ss], [__T | __Stack]);
-yeccpars2(284, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [284 | __Ss], [__T | __Stack]);
-yeccpars2(284, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [284 | __Ss], [__T | __Stack]);
-yeccpars2(284, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(285, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 285, [285 | __Ss], [__T | __Stack]);
-yeccpars2(285, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 290, [285 | __Ss], [__T | __Stack]);
-yeccpars2(285, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [285 | __Ss], [__T | __Stack]);
-yeccpars2(285, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 104, [285 | __Ss], [__T | __Stack]);
-yeccpars2(285, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [285 | __Ss], [__T | __Stack]);
-yeccpars2(285, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [285 | __Ss], [__T | __Stack]);
-yeccpars2(285, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [285 | __Ss], [__T | __Stack]);
-yeccpars2(285, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 149, [285 | __Ss], [__T | __Stack]);
-yeccpars2(285, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(286, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(287, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(288, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_def{name = #c_atom{val = tok_val(__1)}, val = __3},
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(attribute, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(289, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(290, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 285, [290 | __Ss], [__T | __Stack]);
-yeccpars2(290, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 290, [290 | __Ss], [__T | __Stack]);
-yeccpars2(290, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 293, [290 | __Ss], [__T | __Stack]);
-yeccpars2(290, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [290 | __Ss], [__T | __Stack]);
-yeccpars2(290, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 104, [290 | __Ss], [__T | __Stack]);
-yeccpars2(290, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [290 | __Ss], [__T | __Stack]);
-yeccpars2(290, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [290 | __Ss], [__T | __Stack]);
-yeccpars2(290, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [290 | __Ss], [__T | __Stack]);
-yeccpars2(290, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(291, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 295, [291 | __Ss], [__T | __Stack]);
-yeccpars2(291, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1],
- yeccpars2(yeccgoto(literals, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(292, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 294, [292 | __Ss], [__T | __Stack]);
-yeccpars2(292, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(293, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_tuple{es = []},
- __Nss = lists:nthtail(1, __Ss),
- yeccpars2(yeccgoto(tuple_literal, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(294, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_tuple{es = __2},
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(tuple_literal, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(295, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 285, [295 | __Ss], [__T | __Stack]);
-yeccpars2(295, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 290, [295 | __Ss], [__T | __Stack]);
-yeccpars2(295, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [295 | __Ss], [__T | __Stack]);
-yeccpars2(295, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 104, [295 | __Ss], [__T | __Stack]);
-yeccpars2(295, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [295 | __Ss], [__T | __Stack]);
-yeccpars2(295, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [295 | __Ss], [__T | __Stack]);
-yeccpars2(295, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [295 | __Ss], [__T | __Stack]);
-yeccpars2(295, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(296, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1|__3],
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(literals, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(297, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 298, [297 | __Ss], [__T | __Stack]);
-yeccpars2(297, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 301, [297 | __Ss], [__T | __Stack]);
-yeccpars2(297, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 299, [297 | __Ss], [__T | __Stack]);
-yeccpars2(297, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(298, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 285, [298 | __Ss], [__T | __Stack]);
-yeccpars2(298, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 290, [298 | __Ss], [__T | __Stack]);
-yeccpars2(298, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [298 | __Ss], [__T | __Stack]);
-yeccpars2(298, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 104, [298 | __Ss], [__T | __Stack]);
-yeccpars2(298, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [298 | __Ss], [__T | __Stack]);
-yeccpars2(298, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [298 | __Ss], [__T | __Stack]);
-yeccpars2(298, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [298 | __Ss], [__T | __Stack]);
-yeccpars2(298, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(299, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_nil{},
- yeccpars2(yeccgoto(tail_literal, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(300, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_cons{hd = __2, tl = __3},
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(cons_literal, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(301, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 285, [301 | __Ss], [__T | __Stack]);
-yeccpars2(301, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 290, [301 | __Ss], [__T | __Stack]);
-yeccpars2(301, 'string', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 69, [301 | __Ss], [__T | __Stack]);
-yeccpars2(301, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 104, [301 | __Ss], [__T | __Stack]);
-yeccpars2(301, 'float', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 54, [301 | __Ss], [__T | __Stack]);
-yeccpars2(301, 'integer', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 57, [301 | __Ss], [__T | __Stack]);
-yeccpars2(301, 'char', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 50, [301 | __Ss], [__T | __Stack]);
-yeccpars2(301, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(302, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 303, [302 | __Ss], [__T | __Stack]);
-yeccpars2(302, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(303, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __2,
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(tail_literal, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(304, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 298, [304 | __Ss], [__T | __Stack]);
-yeccpars2(304, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 301, [304 | __Ss], [__T | __Stack]);
-yeccpars2(304, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 299, [304 | __Ss], [__T | __Stack]);
-yeccpars2(304, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(305, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_cons{hd = __2, tl = __3},
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(tail_literal, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(306, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [],
- __Nss = lists:nthtail(1, __Ss),
- yeccpars2(yeccgoto(module_export, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(307, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 311, [307 | __Ss], [__T | __Stack]);
-yeccpars2(307, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1],
- yeccpars2(yeccgoto(exported_names, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(308, ']', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 310, [308 | __Ss], [__T | __Stack]);
-yeccpars2(308, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(309, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __1,
- yeccpars2(yeccgoto(exported_name, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(310, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = __2,
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(module_export, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(311, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 11, [311 | __Ss], [__T | __Stack]);
-yeccpars2(311, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(312, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = [__1|__3],
- __Nss = lists:nthtail(2, __Ss),
- yeccpars2(yeccgoto(exported_names, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(313, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 314, [313 | __Ss], [__T | __Stack]);
-yeccpars2(313, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(314, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 5, [314 | __Ss], [__T | __Stack]);
-yeccpars2(314, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(315, 'attributes', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 7, [315 | __Ss], [__T | __Stack]);
-yeccpars2(315, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(316, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 9, [316 | __Ss], [__T | __Stack]);
-yeccpars2(316, 'atom', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 11, [316 | __Ss], [__T | __Stack]);
-yeccpars2(316, __Cat, __Ss, __Stack, __T, __Ts, __Tzr) ->
- __Val = [],
- yeccpars2(13, __Cat, [316 | __Ss], [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(317, 'end', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 318, [317 | __Ss], [__T | __Stack]);
-yeccpars2(317, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(318, '-|', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 319, [318 | __Ss], [__T | __Stack]);
-yeccpars2(318, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(319, '[', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 126, [319 | __Ss], [__T | __Stack]);
-yeccpars2(319, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(320, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
- yeccpars1(__Ts, __Tzr, 321, [320 | __Ss], [__T | __Stack]);
-yeccpars2(320, _, _, _, __T, _, _) ->
- yeccerror(__T);
-yeccpars2(321, __Cat, __Ss, [__10,__9,__8,__7,__6,__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
- __Val = #c_module{anno = __9, name = tok_val(__3), exports = __4, attrs = __5, defs = __6},
- __Nss = lists:nthtail(9, __Ss),
- yeccpars2(yeccgoto(module_definition, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
-yeccpars2(__Other, _, _, _, _, _, _) ->
- exit({parser, __Other, missing_state_in_action_table}).
-
-yeccgoto(anno_clause, 65) ->
- 100;
-yeccgoto(anno_clause, 100) ->
- 100;
-yeccgoto(anno_clause, 222) ->
- 100;
-yeccgoto(anno_clauses, 65) ->
- 101;
-yeccgoto(anno_clauses, 100) ->
- 169;
-yeccgoto(anno_clauses, 222) ->
- 223;
-yeccgoto(anno_expression, 33) ->
- 38;
-yeccgoto(anno_expression, 36) ->
- 75;
-yeccgoto(anno_expression, 37) ->
- 231;
-yeccgoto(anno_expression, 40) ->
- 229;
-yeccgoto(anno_expression, 44) ->
- 225;
-yeccgoto(anno_expression, 46) ->
- 221;
-yeccgoto(anno_expression, 48) ->
- 220;
-yeccgoto(anno_expression, 52) ->
- 218;
-yeccgoto(anno_expression, 70) ->
- 81;
-yeccgoto(anno_expression, 74) ->
- 75;
-yeccgoto(anno_expression, 79) ->
- 75;
-yeccgoto(anno_expression, 86) ->
- 87;
-yeccgoto(anno_expression, 90) ->
- 91;
-yeccgoto(anno_expression, 99) ->
- 170;
-yeccgoto(anno_expression, 164) ->
- 165;
-yeccgoto(anno_expression, 166) ->
- 167;
-yeccgoto(anno_expression, 171) ->
- 172;
-yeccgoto(anno_expression, 203) ->
- 75;
-yeccgoto(anno_expression, 211) ->
- 212;
-yeccgoto(anno_expression, 214) ->
- 215;
-yeccgoto(anno_expression, 216) ->
- 217;
-yeccgoto(anno_expression, 218) ->
- 219;
-yeccgoto(anno_expression, 226) ->
- 227;
-yeccgoto(anno_expression, 232) ->
- 238;
-yeccgoto(anno_expression, 235) ->
- 236;
-yeccgoto(anno_expression, 257) ->
- 258;
-yeccgoto(anno_expression, 260) ->
- 75;
-yeccgoto(anno_expression, 265) ->
- 266;
-yeccgoto(anno_expressions, 36) ->
- 241;
-yeccgoto(anno_expressions, 74) ->
- 76;
-yeccgoto(anno_expressions, 79) ->
- 80;
-yeccgoto(anno_expressions, 203) ->
- 206;
-yeccgoto(anno_expressions, 260) ->
- 261;
-yeccgoto(anno_fun, 20) ->
- 22;
-yeccgoto(anno_function_name, 8) ->
- 10;
-yeccgoto(anno_function_name, 12) ->
- 10;
-yeccgoto(anno_function_name, 60) ->
- 10;
-yeccgoto(anno_function_name, 316) ->
- 10;
-yeccgoto(anno_pattern, 65) ->
- 102;
-yeccgoto(anno_pattern, 96) ->
- 102;
-yeccgoto(anno_pattern, 97) ->
- 116;
-yeccgoto(anno_pattern, 98) ->
- 173;
-yeccgoto(anno_pattern, 100) ->
- 102;
-yeccgoto(anno_pattern, 114) ->
- 116;
-yeccgoto(anno_pattern, 120) ->
- 116;
-yeccgoto(anno_pattern, 162) ->
- 163;
-yeccgoto(anno_pattern, 174) ->
- 180;
-yeccgoto(anno_pattern, 177) ->
- 178;
-yeccgoto(anno_pattern, 200) ->
- 201;
-yeccgoto(anno_pattern, 222) ->
- 102;
-yeccgoto(anno_patterns, 97) ->
- 183;
-yeccgoto(anno_patterns, 114) ->
- 117;
-yeccgoto(anno_patterns, 120) ->
- 121;
-yeccgoto(anno_variable, 25) ->
- 28;
-yeccgoto(anno_variable, 58) ->
- 84;
-yeccgoto(anno_variable, 65) ->
- 103;
-yeccgoto(anno_variable, 82) ->
- 84;
-yeccgoto(anno_variable, 83) ->
- 28;
-yeccgoto(anno_variable, 88) ->
- 84;
-yeccgoto(anno_variable, 96) ->
- 103;
-yeccgoto(anno_variable, 97) ->
- 103;
-yeccgoto(anno_variable, 98) ->
- 103;
-yeccgoto(anno_variable, 100) ->
- 103;
-yeccgoto(anno_variable, 114) ->
- 103;
-yeccgoto(anno_variable, 115) ->
- 122;
-yeccgoto(anno_variable, 120) ->
- 103;
-yeccgoto(anno_variable, 162) ->
- 103;
-yeccgoto(anno_variable, 174) ->
- 103;
-yeccgoto(anno_variable, 177) ->
- 103;
-yeccgoto(anno_variable, 200) ->
- 103;
-yeccgoto(anno_variable, 222) ->
- 103;
-yeccgoto(anno_variable, 263) ->
- 28;
-yeccgoto(anno_variables, 25) ->
- 29;
-yeccgoto(anno_variables, 83) ->
- 93;
-yeccgoto(anno_variables, 263) ->
- 264;
-yeccgoto(annotation, 125) ->
- 127;
-yeccgoto(annotation, 159) ->
- 160;
-yeccgoto(annotation, 187) ->
- 188;
-yeccgoto(annotation, 244) ->
- 245;
-yeccgoto(annotation, 269) ->
- 270;
-yeccgoto(annotation, 273) ->
- 274;
-yeccgoto(annotation, 319) ->
- 320;
-yeccgoto(application_expr, 33) ->
- 39;
-yeccgoto(application_expr, 35) ->
- 39;
-yeccgoto(application_expr, 36) ->
- 39;
-yeccgoto(application_expr, 37) ->
- 39;
-yeccgoto(application_expr, 40) ->
- 39;
-yeccgoto(application_expr, 44) ->
- 39;
-yeccgoto(application_expr, 46) ->
- 39;
-yeccgoto(application_expr, 48) ->
- 39;
-yeccgoto(application_expr, 52) ->
- 39;
-yeccgoto(application_expr, 70) ->
- 39;
-yeccgoto(application_expr, 74) ->
- 39;
-yeccgoto(application_expr, 79) ->
- 39;
-yeccgoto(application_expr, 86) ->
- 39;
-yeccgoto(application_expr, 90) ->
- 39;
-yeccgoto(application_expr, 99) ->
- 39;
-yeccgoto(application_expr, 164) ->
- 39;
-yeccgoto(application_expr, 166) ->
- 39;
-yeccgoto(application_expr, 171) ->
- 39;
-yeccgoto(application_expr, 203) ->
- 39;
-yeccgoto(application_expr, 211) ->
- 39;
-yeccgoto(application_expr, 214) ->
- 39;
-yeccgoto(application_expr, 216) ->
- 39;
-yeccgoto(application_expr, 218) ->
- 39;
-yeccgoto(application_expr, 226) ->
- 39;
-yeccgoto(application_expr, 232) ->
- 39;
-yeccgoto(application_expr, 235) ->
- 39;
-yeccgoto(application_expr, 257) ->
- 39;
-yeccgoto(application_expr, 260) ->
- 39;
-yeccgoto(application_expr, 265) ->
- 39;
-yeccgoto(arg_list, 202) ->
- 204;
-yeccgoto(arg_list, 208) ->
- 209;
-yeccgoto(arg_list, 227) ->
- 228;
-yeccgoto(arg_list, 229) ->
- 230;
-yeccgoto(atomic_constant, 126) ->
- 132;
-yeccgoto(atomic_constant, 129) ->
- 132;
-yeccgoto(atomic_constant, 142) ->
- 132;
-yeccgoto(atomic_constant, 147) ->
- 132;
-yeccgoto(atomic_constant, 151) ->
- 132;
-yeccgoto(atomic_constant, 154) ->
- 132;
-yeccgoto(atomic_literal, 33) ->
- 42;
-yeccgoto(atomic_literal, 35) ->
- 42;
-yeccgoto(atomic_literal, 36) ->
- 42;
-yeccgoto(atomic_literal, 37) ->
- 42;
-yeccgoto(atomic_literal, 40) ->
- 42;
-yeccgoto(atomic_literal, 44) ->
- 42;
-yeccgoto(atomic_literal, 46) ->
- 42;
-yeccgoto(atomic_literal, 48) ->
- 42;
-yeccgoto(atomic_literal, 52) ->
- 42;
-yeccgoto(atomic_literal, 65) ->
- 105;
-yeccgoto(atomic_literal, 70) ->
- 42;
-yeccgoto(atomic_literal, 74) ->
- 42;
-yeccgoto(atomic_literal, 79) ->
- 42;
-yeccgoto(atomic_literal, 86) ->
- 42;
-yeccgoto(atomic_literal, 90) ->
- 42;
-yeccgoto(atomic_literal, 96) ->
- 105;
-yeccgoto(atomic_literal, 97) ->
- 105;
-yeccgoto(atomic_literal, 98) ->
- 105;
-yeccgoto(atomic_literal, 99) ->
- 42;
-yeccgoto(atomic_literal, 100) ->
- 105;
-yeccgoto(atomic_literal, 114) ->
- 105;
-yeccgoto(atomic_literal, 115) ->
- 105;
-yeccgoto(atomic_literal, 120) ->
- 105;
-yeccgoto(atomic_literal, 162) ->
- 105;
-yeccgoto(atomic_literal, 164) ->
- 42;
-yeccgoto(atomic_literal, 166) ->
- 42;
-yeccgoto(atomic_literal, 171) ->
- 42;
-yeccgoto(atomic_literal, 174) ->
- 105;
-yeccgoto(atomic_literal, 177) ->
- 105;
-yeccgoto(atomic_literal, 200) ->
- 105;
-yeccgoto(atomic_literal, 203) ->
- 42;
-yeccgoto(atomic_literal, 211) ->
- 42;
-yeccgoto(atomic_literal, 214) ->
- 42;
-yeccgoto(atomic_literal, 216) ->
- 42;
-yeccgoto(atomic_literal, 218) ->
- 42;
-yeccgoto(atomic_literal, 222) ->
- 105;
-yeccgoto(atomic_literal, 226) ->
- 42;
-yeccgoto(atomic_literal, 232) ->
- 42;
-yeccgoto(atomic_literal, 235) ->
- 42;
-yeccgoto(atomic_literal, 257) ->
- 42;
-yeccgoto(atomic_literal, 260) ->
- 42;
-yeccgoto(atomic_literal, 265) ->
- 42;
-yeccgoto(atomic_literal, 284) ->
- 286;
-yeccgoto(atomic_literal, 285) ->
- 286;
-yeccgoto(atomic_literal, 290) ->
- 286;
-yeccgoto(atomic_literal, 295) ->
- 286;
-yeccgoto(atomic_literal, 298) ->
- 286;
-yeccgoto(atomic_literal, 301) ->
- 286;
-yeccgoto(atomic_pattern, 65) ->
- 106;
-yeccgoto(atomic_pattern, 96) ->
- 106;
-yeccgoto(atomic_pattern, 97) ->
- 106;
-yeccgoto(atomic_pattern, 98) ->
- 106;
-yeccgoto(atomic_pattern, 100) ->
- 106;
-yeccgoto(atomic_pattern, 114) ->
- 106;
-yeccgoto(atomic_pattern, 115) ->
- 106;
-yeccgoto(atomic_pattern, 120) ->
- 106;
-yeccgoto(atomic_pattern, 162) ->
- 106;
-yeccgoto(atomic_pattern, 174) ->
- 106;
-yeccgoto(atomic_pattern, 177) ->
- 106;
-yeccgoto(atomic_pattern, 200) ->
- 106;
-yeccgoto(atomic_pattern, 222) ->
- 106;
-yeccgoto(attribute, 276) ->
- 279;
-yeccgoto(attribute, 282) ->
- 279;
-yeccgoto(attribute_list, 276) ->
- 280;
-yeccgoto(attribute_list, 282) ->
- 283;
-yeccgoto(binary, 33) ->
- 43;
-yeccgoto(binary, 35) ->
- 43;
-yeccgoto(binary, 36) ->
- 43;
-yeccgoto(binary, 37) ->
- 43;
-yeccgoto(binary, 40) ->
- 43;
-yeccgoto(binary, 44) ->
- 43;
-yeccgoto(binary, 46) ->
- 43;
-yeccgoto(binary, 48) ->
- 43;
-yeccgoto(binary, 52) ->
- 43;
-yeccgoto(binary, 70) ->
- 43;
-yeccgoto(binary, 74) ->
- 43;
-yeccgoto(binary, 79) ->
- 43;
-yeccgoto(binary, 86) ->
- 43;
-yeccgoto(binary, 90) ->
- 43;
-yeccgoto(binary, 99) ->
- 43;
-yeccgoto(binary, 164) ->
- 43;
-yeccgoto(binary, 166) ->
- 43;
-yeccgoto(binary, 171) ->
- 43;
-yeccgoto(binary, 203) ->
- 43;
-yeccgoto(binary, 211) ->
- 43;
-yeccgoto(binary, 214) ->
- 43;
-yeccgoto(binary, 216) ->
- 43;
-yeccgoto(binary, 218) ->
- 43;
-yeccgoto(binary, 226) ->
- 43;
-yeccgoto(binary, 232) ->
- 43;
-yeccgoto(binary, 235) ->
- 43;
-yeccgoto(binary, 257) ->
- 43;
-yeccgoto(binary, 260) ->
- 43;
-yeccgoto(binary, 265) ->
- 43;
-yeccgoto(binary_pattern, 65) ->
- 107;
-yeccgoto(binary_pattern, 96) ->
- 107;
-yeccgoto(binary_pattern, 97) ->
- 107;
-yeccgoto(binary_pattern, 98) ->
- 107;
-yeccgoto(binary_pattern, 100) ->
- 107;
-yeccgoto(binary_pattern, 114) ->
- 107;
-yeccgoto(binary_pattern, 115) ->
- 107;
-yeccgoto(binary_pattern, 120) ->
- 107;
-yeccgoto(binary_pattern, 162) ->
- 107;
-yeccgoto(binary_pattern, 174) ->
- 107;
-yeccgoto(binary_pattern, 177) ->
- 107;
-yeccgoto(binary_pattern, 200) ->
- 107;
-yeccgoto(binary_pattern, 222) ->
- 107;
-yeccgoto(call_expr, 33) ->
- 45;
-yeccgoto(call_expr, 35) ->
- 45;
-yeccgoto(call_expr, 36) ->
- 45;
-yeccgoto(call_expr, 37) ->
- 45;
-yeccgoto(call_expr, 40) ->
- 45;
-yeccgoto(call_expr, 44) ->
- 45;
-yeccgoto(call_expr, 46) ->
- 45;
-yeccgoto(call_expr, 48) ->
- 45;
-yeccgoto(call_expr, 52) ->
- 45;
-yeccgoto(call_expr, 70) ->
- 45;
-yeccgoto(call_expr, 74) ->
- 45;
-yeccgoto(call_expr, 79) ->
- 45;
-yeccgoto(call_expr, 86) ->
- 45;
-yeccgoto(call_expr, 90) ->
- 45;
-yeccgoto(call_expr, 99) ->
- 45;
-yeccgoto(call_expr, 164) ->
- 45;
-yeccgoto(call_expr, 166) ->
- 45;
-yeccgoto(call_expr, 171) ->
- 45;
-yeccgoto(call_expr, 203) ->
- 45;
-yeccgoto(call_expr, 211) ->
- 45;
-yeccgoto(call_expr, 214) ->
- 45;
-yeccgoto(call_expr, 216) ->
- 45;
-yeccgoto(call_expr, 218) ->
- 45;
-yeccgoto(call_expr, 226) ->
- 45;
-yeccgoto(call_expr, 232) ->
- 45;
-yeccgoto(call_expr, 235) ->
- 45;
-yeccgoto(call_expr, 257) ->
- 45;
-yeccgoto(call_expr, 260) ->
- 45;
-yeccgoto(call_expr, 265) ->
- 45;
-yeccgoto(case_expr, 33) ->
- 47;
-yeccgoto(case_expr, 35) ->
- 47;
-yeccgoto(case_expr, 36) ->
- 47;
-yeccgoto(case_expr, 37) ->
- 47;
-yeccgoto(case_expr, 40) ->
- 47;
-yeccgoto(case_expr, 44) ->
- 47;
-yeccgoto(case_expr, 46) ->
- 47;
-yeccgoto(case_expr, 48) ->
- 47;
-yeccgoto(case_expr, 52) ->
- 47;
-yeccgoto(case_expr, 70) ->
- 47;
-yeccgoto(case_expr, 74) ->
- 47;
-yeccgoto(case_expr, 79) ->
- 47;
-yeccgoto(case_expr, 86) ->
- 47;
-yeccgoto(case_expr, 90) ->
- 47;
-yeccgoto(case_expr, 99) ->
- 47;
-yeccgoto(case_expr, 164) ->
- 47;
-yeccgoto(case_expr, 166) ->
- 47;
-yeccgoto(case_expr, 171) ->
- 47;
-yeccgoto(case_expr, 203) ->
- 47;
-yeccgoto(case_expr, 211) ->
- 47;
-yeccgoto(case_expr, 214) ->
- 47;
-yeccgoto(case_expr, 216) ->
- 47;
-yeccgoto(case_expr, 218) ->
- 47;
-yeccgoto(case_expr, 226) ->
- 47;
-yeccgoto(case_expr, 232) ->
- 47;
-yeccgoto(case_expr, 235) ->
- 47;
-yeccgoto(case_expr, 257) ->
- 47;
-yeccgoto(case_expr, 260) ->
- 47;
-yeccgoto(case_expr, 265) ->
- 47;
-yeccgoto(catch_expr, 33) ->
- 49;
-yeccgoto(catch_expr, 35) ->
- 49;
-yeccgoto(catch_expr, 36) ->
- 49;
-yeccgoto(catch_expr, 37) ->
- 49;
-yeccgoto(catch_expr, 40) ->
- 49;
-yeccgoto(catch_expr, 44) ->
- 49;
-yeccgoto(catch_expr, 46) ->
- 49;
-yeccgoto(catch_expr, 48) ->
- 49;
-yeccgoto(catch_expr, 52) ->
- 49;
-yeccgoto(catch_expr, 70) ->
- 49;
-yeccgoto(catch_expr, 74) ->
- 49;
-yeccgoto(catch_expr, 79) ->
- 49;
-yeccgoto(catch_expr, 86) ->
- 49;
-yeccgoto(catch_expr, 90) ->
- 49;
-yeccgoto(catch_expr, 99) ->
- 49;
-yeccgoto(catch_expr, 164) ->
- 49;
-yeccgoto(catch_expr, 166) ->
- 49;
-yeccgoto(catch_expr, 171) ->
- 49;
-yeccgoto(catch_expr, 203) ->
- 49;
-yeccgoto(catch_expr, 211) ->
- 49;
-yeccgoto(catch_expr, 214) ->
- 49;
-yeccgoto(catch_expr, 216) ->
- 49;
-yeccgoto(catch_expr, 218) ->
- 49;
-yeccgoto(catch_expr, 226) ->
- 49;
-yeccgoto(catch_expr, 232) ->
- 49;
-yeccgoto(catch_expr, 235) ->
- 49;
-yeccgoto(catch_expr, 257) ->
- 49;
-yeccgoto(catch_expr, 260) ->
- 49;
-yeccgoto(catch_expr, 265) ->
- 49;
-yeccgoto(clause, 65) ->
- 108;
-yeccgoto(clause, 96) ->
- 185;
-yeccgoto(clause, 100) ->
- 108;
-yeccgoto(clause, 222) ->
- 108;
-yeccgoto(clause_pattern, 65) ->
- 109;
-yeccgoto(clause_pattern, 96) ->
- 109;
-yeccgoto(clause_pattern, 100) ->
- 109;
-yeccgoto(clause_pattern, 222) ->
- 109;
-yeccgoto(cons, 33) ->
- 51;
-yeccgoto(cons, 35) ->
- 51;
-yeccgoto(cons, 36) ->
- 51;
-yeccgoto(cons, 37) ->
- 51;
-yeccgoto(cons, 40) ->
- 51;
-yeccgoto(cons, 44) ->
- 51;
-yeccgoto(cons, 46) ->
- 51;
-yeccgoto(cons, 48) ->
- 51;
-yeccgoto(cons, 52) ->
- 51;
-yeccgoto(cons, 70) ->
- 51;
-yeccgoto(cons, 74) ->
- 51;
-yeccgoto(cons, 79) ->
- 51;
-yeccgoto(cons, 86) ->
- 51;
-yeccgoto(cons, 90) ->
- 51;
-yeccgoto(cons, 99) ->
- 51;
-yeccgoto(cons, 164) ->
- 51;
-yeccgoto(cons, 166) ->
- 51;
-yeccgoto(cons, 171) ->
- 51;
-yeccgoto(cons, 203) ->
- 51;
-yeccgoto(cons, 211) ->
- 51;
-yeccgoto(cons, 214) ->
- 51;
-yeccgoto(cons, 216) ->
- 51;
-yeccgoto(cons, 218) ->
- 51;
-yeccgoto(cons, 226) ->
- 51;
-yeccgoto(cons, 232) ->
- 51;
-yeccgoto(cons, 235) ->
- 51;
-yeccgoto(cons, 257) ->
- 51;
-yeccgoto(cons, 260) ->
- 51;
-yeccgoto(cons, 265) ->
- 51;
-yeccgoto(cons_constant, 126) ->
- 134;
-yeccgoto(cons_constant, 129) ->
- 134;
-yeccgoto(cons_constant, 142) ->
- 134;
-yeccgoto(cons_constant, 147) ->
- 134;
-yeccgoto(cons_constant, 151) ->
- 134;
-yeccgoto(cons_constant, 154) ->
- 134;
-yeccgoto(cons_literal, 284) ->
- 287;
-yeccgoto(cons_literal, 285) ->
- 287;
-yeccgoto(cons_literal, 290) ->
- 287;
-yeccgoto(cons_literal, 295) ->
- 287;
-yeccgoto(cons_literal, 298) ->
- 287;
-yeccgoto(cons_literal, 301) ->
- 287;
-yeccgoto(cons_pattern, 65) ->
- 110;
-yeccgoto(cons_pattern, 96) ->
- 110;
-yeccgoto(cons_pattern, 97) ->
- 110;
-yeccgoto(cons_pattern, 98) ->
- 110;
-yeccgoto(cons_pattern, 100) ->
- 110;
-yeccgoto(cons_pattern, 114) ->
- 110;
-yeccgoto(cons_pattern, 115) ->
- 110;
-yeccgoto(cons_pattern, 120) ->
- 110;
-yeccgoto(cons_pattern, 162) ->
- 110;
-yeccgoto(cons_pattern, 174) ->
- 110;
-yeccgoto(cons_pattern, 177) ->
- 110;
-yeccgoto(cons_pattern, 200) ->
- 110;
-yeccgoto(cons_pattern, 222) ->
- 110;
-yeccgoto(constant, 126) ->
- 135;
-yeccgoto(constant, 129) ->
- 150;
-yeccgoto(constant, 142) ->
- 135;
-yeccgoto(constant, 147) ->
- 135;
-yeccgoto(constant, 151) ->
- 157;
-yeccgoto(constant, 154) ->
- 155;
-yeccgoto(constants, 126) ->
- 136;
-yeccgoto(constants, 142) ->
- 143;
-yeccgoto(constants, 147) ->
- 148;
-yeccgoto(exported_name, 5) ->
- 307;
-yeccgoto(exported_name, 311) ->
- 307;
-yeccgoto(exported_names, 5) ->
- 308;
-yeccgoto(exported_names, 311) ->
- 312;
-yeccgoto(expression, 33) ->
- 53;
-yeccgoto(expression, 35) ->
- 243;
-yeccgoto(expression, 36) ->
- 53;
-yeccgoto(expression, 37) ->
- 53;
-yeccgoto(expression, 40) ->
- 53;
-yeccgoto(expression, 44) ->
- 53;
-yeccgoto(expression, 46) ->
- 53;
-yeccgoto(expression, 48) ->
- 53;
-yeccgoto(expression, 52) ->
- 53;
-yeccgoto(expression, 70) ->
- 53;
-yeccgoto(expression, 74) ->
- 53;
-yeccgoto(expression, 79) ->
- 53;
-yeccgoto(expression, 86) ->
- 53;
-yeccgoto(expression, 90) ->
- 53;
-yeccgoto(expression, 99) ->
- 53;
-yeccgoto(expression, 164) ->
- 53;
-yeccgoto(expression, 166) ->
- 53;
-yeccgoto(expression, 171) ->
- 53;
-yeccgoto(expression, 203) ->
- 53;
-yeccgoto(expression, 211) ->
- 53;
-yeccgoto(expression, 214) ->
- 53;
-yeccgoto(expression, 216) ->
- 53;
-yeccgoto(expression, 218) ->
- 53;
-yeccgoto(expression, 226) ->
- 53;
-yeccgoto(expression, 232) ->
- 53;
-yeccgoto(expression, 235) ->
- 53;
-yeccgoto(expression, 257) ->
- 53;
-yeccgoto(expression, 260) ->
- 53;
-yeccgoto(expression, 265) ->
- 53;
-yeccgoto(fun_expr, 20) ->
- 24;
-yeccgoto(fun_expr, 21) ->
- 268;
-yeccgoto(fun_expr, 33) ->
- 55;
-yeccgoto(fun_expr, 35) ->
- 55;
-yeccgoto(fun_expr, 36) ->
- 55;
-yeccgoto(fun_expr, 37) ->
- 55;
-yeccgoto(fun_expr, 40) ->
- 55;
-yeccgoto(fun_expr, 44) ->
- 55;
-yeccgoto(fun_expr, 46) ->
- 55;
-yeccgoto(fun_expr, 48) ->
- 55;
-yeccgoto(fun_expr, 52) ->
- 55;
-yeccgoto(fun_expr, 70) ->
- 55;
-yeccgoto(fun_expr, 74) ->
- 55;
-yeccgoto(fun_expr, 79) ->
- 55;
-yeccgoto(fun_expr, 86) ->
- 55;
-yeccgoto(fun_expr, 90) ->
- 55;
-yeccgoto(fun_expr, 99) ->
- 55;
-yeccgoto(fun_expr, 164) ->
- 55;
-yeccgoto(fun_expr, 166) ->
- 55;
-yeccgoto(fun_expr, 171) ->
- 55;
-yeccgoto(fun_expr, 203) ->
- 55;
-yeccgoto(fun_expr, 211) ->
- 55;
-yeccgoto(fun_expr, 214) ->
- 55;
-yeccgoto(fun_expr, 216) ->
- 55;
-yeccgoto(fun_expr, 218) ->
- 55;
-yeccgoto(fun_expr, 226) ->
- 55;
-yeccgoto(fun_expr, 232) ->
- 55;
-yeccgoto(fun_expr, 235) ->
- 55;
-yeccgoto(fun_expr, 257) ->
- 55;
-yeccgoto(fun_expr, 260) ->
- 55;
-yeccgoto(fun_expr, 265) ->
- 55;
-yeccgoto(function_definition, 8) ->
- 12;
-yeccgoto(function_definition, 12) ->
- 12;
-yeccgoto(function_definition, 60) ->
- 12;
-yeccgoto(function_definition, 316) ->
- 12;
-yeccgoto(function_definitions, 8) ->
- 13;
-yeccgoto(function_definitions, 12) ->
- 17;
-yeccgoto(function_definitions, 60) ->
- 210;
-yeccgoto(function_definitions, 316) ->
- 13;
-yeccgoto(function_name, 5) ->
- 309;
-yeccgoto(function_name, 8) ->
- 14;
-yeccgoto(function_name, 9) ->
- 272;
-yeccgoto(function_name, 12) ->
- 14;
-yeccgoto(function_name, 33) ->
- 56;
-yeccgoto(function_name, 35) ->
- 56;
-yeccgoto(function_name, 36) ->
- 56;
-yeccgoto(function_name, 37) ->
- 56;
-yeccgoto(function_name, 40) ->
- 56;
-yeccgoto(function_name, 44) ->
- 56;
-yeccgoto(function_name, 46) ->
- 56;
-yeccgoto(function_name, 48) ->
- 56;
-yeccgoto(function_name, 52) ->
- 56;
-yeccgoto(function_name, 60) ->
- 14;
-yeccgoto(function_name, 70) ->
- 56;
-yeccgoto(function_name, 74) ->
- 56;
-yeccgoto(function_name, 79) ->
- 56;
-yeccgoto(function_name, 86) ->
- 56;
-yeccgoto(function_name, 90) ->
- 56;
-yeccgoto(function_name, 99) ->
- 56;
-yeccgoto(function_name, 164) ->
- 56;
-yeccgoto(function_name, 166) ->
- 56;
-yeccgoto(function_name, 171) ->
- 56;
-yeccgoto(function_name, 203) ->
- 56;
-yeccgoto(function_name, 211) ->
- 56;
-yeccgoto(function_name, 214) ->
- 56;
-yeccgoto(function_name, 216) ->
- 56;
-yeccgoto(function_name, 218) ->
- 56;
-yeccgoto(function_name, 226) ->
- 56;
-yeccgoto(function_name, 232) ->
- 56;
-yeccgoto(function_name, 235) ->
- 56;
-yeccgoto(function_name, 257) ->
- 56;
-yeccgoto(function_name, 260) ->
- 56;
-yeccgoto(function_name, 265) ->
- 56;
-yeccgoto(function_name, 311) ->
- 309;
-yeccgoto(function_name, 316) ->
- 14;
-yeccgoto(let_expr, 33) ->
- 59;
-yeccgoto(let_expr, 35) ->
- 59;
-yeccgoto(let_expr, 36) ->
- 59;
-yeccgoto(let_expr, 37) ->
- 59;
-yeccgoto(let_expr, 40) ->
- 59;
-yeccgoto(let_expr, 44) ->
- 59;
-yeccgoto(let_expr, 46) ->
- 59;
-yeccgoto(let_expr, 48) ->
- 59;
-yeccgoto(let_expr, 52) ->
- 59;
-yeccgoto(let_expr, 70) ->
- 59;
-yeccgoto(let_expr, 74) ->
- 59;
-yeccgoto(let_expr, 79) ->
- 59;
-yeccgoto(let_expr, 86) ->
- 59;
-yeccgoto(let_expr, 90) ->
- 59;
-yeccgoto(let_expr, 99) ->
- 59;
-yeccgoto(let_expr, 164) ->
- 59;
-yeccgoto(let_expr, 166) ->
- 59;
-yeccgoto(let_expr, 171) ->
- 59;
-yeccgoto(let_expr, 203) ->
- 59;
-yeccgoto(let_expr, 211) ->
- 59;
-yeccgoto(let_expr, 214) ->
- 59;
-yeccgoto(let_expr, 216) ->
- 59;
-yeccgoto(let_expr, 218) ->
- 59;
-yeccgoto(let_expr, 226) ->
- 59;
-yeccgoto(let_expr, 232) ->
- 59;
-yeccgoto(let_expr, 235) ->
- 59;
-yeccgoto(let_expr, 257) ->
- 59;
-yeccgoto(let_expr, 260) ->
- 59;
-yeccgoto(let_expr, 265) ->
- 59;
-yeccgoto(let_vars, 58) ->
- 213;
-yeccgoto(let_vars, 82) ->
- 85;
-yeccgoto(let_vars, 88) ->
- 89;
-yeccgoto(letrec_expr, 33) ->
- 61;
-yeccgoto(letrec_expr, 35) ->
- 61;
-yeccgoto(letrec_expr, 36) ->
- 61;
-yeccgoto(letrec_expr, 37) ->
- 61;
-yeccgoto(letrec_expr, 40) ->
- 61;
-yeccgoto(letrec_expr, 44) ->
- 61;
-yeccgoto(letrec_expr, 46) ->
- 61;
-yeccgoto(letrec_expr, 48) ->
- 61;
-yeccgoto(letrec_expr, 52) ->
- 61;
-yeccgoto(letrec_expr, 70) ->
- 61;
-yeccgoto(letrec_expr, 74) ->
- 61;
-yeccgoto(letrec_expr, 79) ->
- 61;
-yeccgoto(letrec_expr, 86) ->
- 61;
-yeccgoto(letrec_expr, 90) ->
- 61;
-yeccgoto(letrec_expr, 99) ->
- 61;
-yeccgoto(letrec_expr, 164) ->
- 61;
-yeccgoto(letrec_expr, 166) ->
- 61;
-yeccgoto(letrec_expr, 171) ->
- 61;
-yeccgoto(letrec_expr, 203) ->
- 61;
-yeccgoto(letrec_expr, 211) ->
- 61;
-yeccgoto(letrec_expr, 214) ->
- 61;
-yeccgoto(letrec_expr, 216) ->
- 61;
-yeccgoto(letrec_expr, 218) ->
- 61;
-yeccgoto(letrec_expr, 226) ->
- 61;
-yeccgoto(letrec_expr, 232) ->
- 61;
-yeccgoto(letrec_expr, 235) ->
- 61;
-yeccgoto(letrec_expr, 257) ->
- 61;
-yeccgoto(letrec_expr, 260) ->
- 61;
-yeccgoto(letrec_expr, 265) ->
- 61;
-yeccgoto(literal, 284) ->
- 288;
-yeccgoto(literal, 285) ->
- 297;
-yeccgoto(literal, 290) ->
- 291;
-yeccgoto(literal, 295) ->
- 291;
-yeccgoto(literal, 298) ->
- 304;
-yeccgoto(literal, 301) ->
- 302;
-yeccgoto(literals, 290) ->
- 292;
-yeccgoto(literals, 295) ->
- 296;
-yeccgoto(module_attribute, 6) ->
- 8;
-yeccgoto(module_attribute, 315) ->
- 316;
-yeccgoto(module_definition, 0) ->
- 3;
-yeccgoto(module_defs, 8) ->
- 15;
-yeccgoto(module_defs, 316) ->
- 317;
-yeccgoto(module_export, 4) ->
- 6;
-yeccgoto(module_export, 314) ->
- 315;
-yeccgoto(nil, 33) ->
- 62;
-yeccgoto(nil, 35) ->
- 62;
-yeccgoto(nil, 36) ->
- 62;
-yeccgoto(nil, 37) ->
- 62;
-yeccgoto(nil, 40) ->
- 62;
-yeccgoto(nil, 44) ->
- 62;
-yeccgoto(nil, 46) ->
- 62;
-yeccgoto(nil, 48) ->
- 62;
-yeccgoto(nil, 52) ->
- 62;
-yeccgoto(nil, 65) ->
- 62;
-yeccgoto(nil, 70) ->
- 62;
-yeccgoto(nil, 74) ->
- 62;
-yeccgoto(nil, 79) ->
- 62;
-yeccgoto(nil, 86) ->
- 62;
-yeccgoto(nil, 90) ->
- 62;
-yeccgoto(nil, 96) ->
- 62;
-yeccgoto(nil, 97) ->
- 62;
-yeccgoto(nil, 98) ->
- 62;
-yeccgoto(nil, 99) ->
- 62;
-yeccgoto(nil, 100) ->
- 62;
-yeccgoto(nil, 114) ->
- 62;
-yeccgoto(nil, 115) ->
- 62;
-yeccgoto(nil, 120) ->
- 62;
-yeccgoto(nil, 126) ->
- 139;
-yeccgoto(nil, 129) ->
- 139;
-yeccgoto(nil, 142) ->
- 139;
-yeccgoto(nil, 147) ->
- 139;
-yeccgoto(nil, 151) ->
- 139;
-yeccgoto(nil, 154) ->
- 139;
-yeccgoto(nil, 162) ->
- 62;
-yeccgoto(nil, 164) ->
- 62;
-yeccgoto(nil, 166) ->
- 62;
-yeccgoto(nil, 171) ->
- 62;
-yeccgoto(nil, 174) ->
- 62;
-yeccgoto(nil, 177) ->
- 62;
-yeccgoto(nil, 200) ->
- 62;
-yeccgoto(nil, 203) ->
- 62;
-yeccgoto(nil, 211) ->
- 62;
-yeccgoto(nil, 214) ->
- 62;
-yeccgoto(nil, 216) ->
- 62;
-yeccgoto(nil, 218) ->
- 62;
-yeccgoto(nil, 222) ->
- 62;
-yeccgoto(nil, 226) ->
- 62;
-yeccgoto(nil, 232) ->
- 62;
-yeccgoto(nil, 235) ->
- 62;
-yeccgoto(nil, 257) ->
- 62;
-yeccgoto(nil, 260) ->
- 62;
-yeccgoto(nil, 265) ->
- 62;
-yeccgoto(nil, 284) ->
- 62;
-yeccgoto(nil, 285) ->
- 62;
-yeccgoto(nil, 290) ->
- 62;
-yeccgoto(nil, 295) ->
- 62;
-yeccgoto(nil, 298) ->
- 62;
-yeccgoto(nil, 301) ->
- 62;
-yeccgoto(other_pattern, 65) ->
- 111;
-yeccgoto(other_pattern, 96) ->
- 186;
-yeccgoto(other_pattern, 97) ->
- 111;
-yeccgoto(other_pattern, 98) ->
- 111;
-yeccgoto(other_pattern, 100) ->
- 111;
-yeccgoto(other_pattern, 114) ->
- 111;
-yeccgoto(other_pattern, 115) ->
- 123;
-yeccgoto(other_pattern, 120) ->
- 111;
-yeccgoto(other_pattern, 162) ->
- 111;
-yeccgoto(other_pattern, 174) ->
- 111;
-yeccgoto(other_pattern, 177) ->
- 111;
-yeccgoto(other_pattern, 200) ->
- 111;
-yeccgoto(other_pattern, 222) ->
- 111;
-yeccgoto(primop_expr, 33) ->
- 64;
-yeccgoto(primop_expr, 35) ->
- 64;
-yeccgoto(primop_expr, 36) ->
- 64;
-yeccgoto(primop_expr, 37) ->
- 64;
-yeccgoto(primop_expr, 40) ->
- 64;
-yeccgoto(primop_expr, 44) ->
- 64;
-yeccgoto(primop_expr, 46) ->
- 64;
-yeccgoto(primop_expr, 48) ->
- 64;
-yeccgoto(primop_expr, 52) ->
- 64;
-yeccgoto(primop_expr, 70) ->
- 64;
-yeccgoto(primop_expr, 74) ->
- 64;
-yeccgoto(primop_expr, 79) ->
- 64;
-yeccgoto(primop_expr, 86) ->
- 64;
-yeccgoto(primop_expr, 90) ->
- 64;
-yeccgoto(primop_expr, 99) ->
- 64;
-yeccgoto(primop_expr, 164) ->
- 64;
-yeccgoto(primop_expr, 166) ->
- 64;
-yeccgoto(primop_expr, 171) ->
- 64;
-yeccgoto(primop_expr, 203) ->
- 64;
-yeccgoto(primop_expr, 211) ->
- 64;
-yeccgoto(primop_expr, 214) ->
- 64;
-yeccgoto(primop_expr, 216) ->
- 64;
-yeccgoto(primop_expr, 218) ->
- 64;
-yeccgoto(primop_expr, 226) ->
- 64;
-yeccgoto(primop_expr, 232) ->
- 64;
-yeccgoto(primop_expr, 235) ->
- 64;
-yeccgoto(primop_expr, 257) ->
- 64;
-yeccgoto(primop_expr, 260) ->
- 64;
-yeccgoto(primop_expr, 265) ->
- 64;
-yeccgoto(receive_expr, 33) ->
- 66;
-yeccgoto(receive_expr, 35) ->
- 66;
-yeccgoto(receive_expr, 36) ->
- 66;
-yeccgoto(receive_expr, 37) ->
- 66;
-yeccgoto(receive_expr, 40) ->
- 66;
-yeccgoto(receive_expr, 44) ->
- 66;
-yeccgoto(receive_expr, 46) ->
- 66;
-yeccgoto(receive_expr, 48) ->
- 66;
-yeccgoto(receive_expr, 52) ->
- 66;
-yeccgoto(receive_expr, 70) ->
- 66;
-yeccgoto(receive_expr, 74) ->
- 66;
-yeccgoto(receive_expr, 79) ->
- 66;
-yeccgoto(receive_expr, 86) ->
- 66;
-yeccgoto(receive_expr, 90) ->
- 66;
-yeccgoto(receive_expr, 99) ->
- 66;
-yeccgoto(receive_expr, 164) ->
- 66;
-yeccgoto(receive_expr, 166) ->
- 66;
-yeccgoto(receive_expr, 171) ->
- 66;
-yeccgoto(receive_expr, 203) ->
- 66;
-yeccgoto(receive_expr, 211) ->
- 66;
-yeccgoto(receive_expr, 214) ->
- 66;
-yeccgoto(receive_expr, 216) ->
- 66;
-yeccgoto(receive_expr, 218) ->
- 66;
-yeccgoto(receive_expr, 226) ->
- 66;
-yeccgoto(receive_expr, 232) ->
- 66;
-yeccgoto(receive_expr, 235) ->
- 66;
-yeccgoto(receive_expr, 257) ->
- 66;
-yeccgoto(receive_expr, 260) ->
- 66;
-yeccgoto(receive_expr, 265) ->
- 66;
-yeccgoto(segment, 247) ->
- 249;
-yeccgoto(segment, 255) ->
- 249;
-yeccgoto(segment_pattern, 190) ->
- 192;
-yeccgoto(segment_pattern, 198) ->
- 192;
-yeccgoto(segment_patterns, 190) ->
- 193;
-yeccgoto(segment_patterns, 198) ->
- 199;
-yeccgoto(segments, 247) ->
- 250;
-yeccgoto(segments, 255) ->
- 256;
-yeccgoto(sequence, 33) ->
- 67;
-yeccgoto(sequence, 35) ->
- 67;
-yeccgoto(sequence, 36) ->
- 67;
-yeccgoto(sequence, 37) ->
- 67;
-yeccgoto(sequence, 40) ->
- 67;
-yeccgoto(sequence, 44) ->
- 67;
-yeccgoto(sequence, 46) ->
- 67;
-yeccgoto(sequence, 48) ->
- 67;
-yeccgoto(sequence, 52) ->
- 67;
-yeccgoto(sequence, 70) ->
- 67;
-yeccgoto(sequence, 74) ->
- 67;
-yeccgoto(sequence, 79) ->
- 67;
-yeccgoto(sequence, 86) ->
- 67;
-yeccgoto(sequence, 90) ->
- 67;
-yeccgoto(sequence, 99) ->
- 67;
-yeccgoto(sequence, 164) ->
- 67;
-yeccgoto(sequence, 166) ->
- 67;
-yeccgoto(sequence, 171) ->
- 67;
-yeccgoto(sequence, 203) ->
- 67;
-yeccgoto(sequence, 211) ->
- 67;
-yeccgoto(sequence, 214) ->
- 67;
-yeccgoto(sequence, 216) ->
- 67;
-yeccgoto(sequence, 218) ->
- 67;
-yeccgoto(sequence, 226) ->
- 67;
-yeccgoto(sequence, 232) ->
- 67;
-yeccgoto(sequence, 235) ->
- 67;
-yeccgoto(sequence, 257) ->
- 67;
-yeccgoto(sequence, 260) ->
- 67;
-yeccgoto(sequence, 265) ->
- 67;
-yeccgoto(single_expression, 33) ->
- 68;
-yeccgoto(single_expression, 35) ->
- 68;
-yeccgoto(single_expression, 36) ->
- 68;
-yeccgoto(single_expression, 37) ->
- 68;
-yeccgoto(single_expression, 40) ->
- 68;
-yeccgoto(single_expression, 44) ->
- 68;
-yeccgoto(single_expression, 46) ->
- 68;
-yeccgoto(single_expression, 48) ->
- 68;
-yeccgoto(single_expression, 52) ->
- 68;
-yeccgoto(single_expression, 70) ->
- 68;
-yeccgoto(single_expression, 74) ->
- 68;
-yeccgoto(single_expression, 79) ->
- 68;
-yeccgoto(single_expression, 86) ->
- 68;
-yeccgoto(single_expression, 90) ->
- 68;
-yeccgoto(single_expression, 99) ->
- 68;
-yeccgoto(single_expression, 164) ->
- 68;
-yeccgoto(single_expression, 166) ->
- 68;
-yeccgoto(single_expression, 171) ->
- 68;
-yeccgoto(single_expression, 203) ->
- 68;
-yeccgoto(single_expression, 211) ->
- 68;
-yeccgoto(single_expression, 214) ->
- 68;
-yeccgoto(single_expression, 216) ->
- 68;
-yeccgoto(single_expression, 218) ->
- 68;
-yeccgoto(single_expression, 226) ->
- 68;
-yeccgoto(single_expression, 232) ->
- 68;
-yeccgoto(single_expression, 235) ->
- 68;
-yeccgoto(single_expression, 257) ->
- 68;
-yeccgoto(single_expression, 260) ->
- 68;
-yeccgoto(single_expression, 265) ->
- 68;
-yeccgoto(tail, 231) ->
- 234;
-yeccgoto(tail, 238) ->
- 239;
-yeccgoto(tail_constant, 150) ->
- 153;
-yeccgoto(tail_constant, 157) ->
- 158;
-yeccgoto(tail_literal, 297) ->
- 300;
-yeccgoto(tail_literal, 304) ->
- 305;
-yeccgoto(tail_pattern, 173) ->
- 176;
-yeccgoto(tail_pattern, 180) ->
- 181;
-yeccgoto(timeout, 65) ->
- 112;
-yeccgoto(timeout, 101) ->
- 168;
-yeccgoto(try_expr, 33) ->
- 71;
-yeccgoto(try_expr, 35) ->
- 71;
-yeccgoto(try_expr, 36) ->
- 71;
-yeccgoto(try_expr, 37) ->
- 71;
-yeccgoto(try_expr, 40) ->
- 71;
-yeccgoto(try_expr, 44) ->
- 71;
-yeccgoto(try_expr, 46) ->
- 71;
-yeccgoto(try_expr, 48) ->
- 71;
-yeccgoto(try_expr, 52) ->
- 71;
-yeccgoto(try_expr, 70) ->
- 71;
-yeccgoto(try_expr, 74) ->
- 71;
-yeccgoto(try_expr, 79) ->
- 71;
-yeccgoto(try_expr, 86) ->
- 71;
-yeccgoto(try_expr, 90) ->
- 71;
-yeccgoto(try_expr, 99) ->
- 71;
-yeccgoto(try_expr, 164) ->
- 71;
-yeccgoto(try_expr, 166) ->
- 71;
-yeccgoto(try_expr, 171) ->
- 71;
-yeccgoto(try_expr, 203) ->
- 71;
-yeccgoto(try_expr, 211) ->
- 71;
-yeccgoto(try_expr, 214) ->
- 71;
-yeccgoto(try_expr, 216) ->
- 71;
-yeccgoto(try_expr, 218) ->
- 71;
-yeccgoto(try_expr, 226) ->
- 71;
-yeccgoto(try_expr, 232) ->
- 71;
-yeccgoto(try_expr, 235) ->
- 71;
-yeccgoto(try_expr, 257) ->
- 71;
-yeccgoto(try_expr, 260) ->
- 71;
-yeccgoto(try_expr, 265) ->
- 71;
-yeccgoto(tuple, 33) ->
- 72;
-yeccgoto(tuple, 35) ->
- 72;
-yeccgoto(tuple, 36) ->
- 72;
-yeccgoto(tuple, 37) ->
- 72;
-yeccgoto(tuple, 40) ->
- 72;
-yeccgoto(tuple, 44) ->
- 72;
-yeccgoto(tuple, 46) ->
- 72;
-yeccgoto(tuple, 48) ->
- 72;
-yeccgoto(tuple, 52) ->
- 72;
-yeccgoto(tuple, 70) ->
- 72;
-yeccgoto(tuple, 74) ->
- 72;
-yeccgoto(tuple, 79) ->
- 72;
-yeccgoto(tuple, 86) ->
- 72;
-yeccgoto(tuple, 90) ->
- 72;
-yeccgoto(tuple, 99) ->
- 72;
-yeccgoto(tuple, 164) ->
- 72;
-yeccgoto(tuple, 166) ->
- 72;
-yeccgoto(tuple, 171) ->
- 72;
-yeccgoto(tuple, 203) ->
- 72;
-yeccgoto(tuple, 211) ->
- 72;
-yeccgoto(tuple, 214) ->
- 72;
-yeccgoto(tuple, 216) ->
- 72;
-yeccgoto(tuple, 218) ->
- 72;
-yeccgoto(tuple, 226) ->
- 72;
-yeccgoto(tuple, 232) ->
- 72;
-yeccgoto(tuple, 235) ->
- 72;
-yeccgoto(tuple, 257) ->
- 72;
-yeccgoto(tuple, 260) ->
- 72;
-yeccgoto(tuple, 265) ->
- 72;
-yeccgoto(tuple_constant, 126) ->
- 141;
-yeccgoto(tuple_constant, 129) ->
- 141;
-yeccgoto(tuple_constant, 142) ->
- 141;
-yeccgoto(tuple_constant, 147) ->
- 141;
-yeccgoto(tuple_constant, 151) ->
- 141;
-yeccgoto(tuple_constant, 154) ->
- 141;
-yeccgoto(tuple_literal, 284) ->
- 289;
-yeccgoto(tuple_literal, 285) ->
- 289;
-yeccgoto(tuple_literal, 290) ->
- 289;
-yeccgoto(tuple_literal, 295) ->
- 289;
-yeccgoto(tuple_literal, 298) ->
- 289;
-yeccgoto(tuple_literal, 301) ->
- 289;
-yeccgoto(tuple_pattern, 65) ->
- 113;
-yeccgoto(tuple_pattern, 96) ->
- 113;
-yeccgoto(tuple_pattern, 97) ->
- 113;
-yeccgoto(tuple_pattern, 98) ->
- 113;
-yeccgoto(tuple_pattern, 100) ->
- 113;
-yeccgoto(tuple_pattern, 114) ->
- 113;
-yeccgoto(tuple_pattern, 115) ->
- 113;
-yeccgoto(tuple_pattern, 120) ->
- 113;
-yeccgoto(tuple_pattern, 162) ->
- 113;
-yeccgoto(tuple_pattern, 174) ->
- 113;
-yeccgoto(tuple_pattern, 177) ->
- 113;
-yeccgoto(tuple_pattern, 200) ->
- 113;
-yeccgoto(tuple_pattern, 222) ->
- 113;
-yeccgoto(variable, 25) ->
- 31;
-yeccgoto(variable, 26) ->
- 267;
-yeccgoto(variable, 33) ->
- 73;
-yeccgoto(variable, 35) ->
- 73;
-yeccgoto(variable, 36) ->
- 73;
-yeccgoto(variable, 37) ->
- 73;
-yeccgoto(variable, 40) ->
- 73;
-yeccgoto(variable, 44) ->
- 73;
-yeccgoto(variable, 46) ->
- 73;
-yeccgoto(variable, 48) ->
- 73;
-yeccgoto(variable, 52) ->
- 73;
-yeccgoto(variable, 58) ->
- 31;
-yeccgoto(variable, 65) ->
- 31;
-yeccgoto(variable, 70) ->
- 73;
-yeccgoto(variable, 74) ->
- 73;
-yeccgoto(variable, 79) ->
- 73;
-yeccgoto(variable, 82) ->
- 31;
-yeccgoto(variable, 83) ->
- 31;
-yeccgoto(variable, 86) ->
- 73;
-yeccgoto(variable, 88) ->
- 31;
-yeccgoto(variable, 90) ->
- 73;
-yeccgoto(variable, 96) ->
- 124;
-yeccgoto(variable, 97) ->
- 31;
-yeccgoto(variable, 98) ->
- 31;
-yeccgoto(variable, 99) ->
- 73;
-yeccgoto(variable, 100) ->
- 31;
-yeccgoto(variable, 114) ->
- 31;
-yeccgoto(variable, 115) ->
- 124;
-yeccgoto(variable, 120) ->
- 31;
-yeccgoto(variable, 162) ->
- 31;
-yeccgoto(variable, 164) ->
- 73;
-yeccgoto(variable, 166) ->
- 73;
-yeccgoto(variable, 171) ->
- 73;
-yeccgoto(variable, 174) ->
- 31;
-yeccgoto(variable, 177) ->
- 31;
-yeccgoto(variable, 200) ->
- 31;
-yeccgoto(variable, 203) ->
- 73;
-yeccgoto(variable, 211) ->
- 73;
-yeccgoto(variable, 214) ->
- 73;
-yeccgoto(variable, 216) ->
- 73;
-yeccgoto(variable, 218) ->
- 73;
-yeccgoto(variable, 222) ->
- 31;
-yeccgoto(variable, 226) ->
- 73;
-yeccgoto(variable, 232) ->
- 73;
-yeccgoto(variable, 235) ->
- 73;
-yeccgoto(variable, 257) ->
- 73;
-yeccgoto(variable, 260) ->
- 73;
-yeccgoto(variable, 263) ->
- 31;
-yeccgoto(variable, 265) ->
- 73;
-yeccgoto(__Symbol, __State) ->
- exit({__Symbol, __State, missing_in_goto_table}).
-
-
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_parse.hrl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_parse.hrl
deleted file mode 100644
index aaf913a15a..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_parse.hrl
+++ /dev/null
@@ -1,111 +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: core_parse.hrl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
-%%
-%% Purpose : Core Erlang syntax trees as records.
-
-%% It would be nice to incorporate some generic functions as well but
-%% this could make including this file difficult.
-
-%% Note: the annotation list is *always* the first record field.
-%% Thus it is possible to define the macros:
-%% -define(get_ann(X), element(2, X)).
-%% -define(set_ann(X, Y), setelement(2, X, Y)).
-
--record(c_int, {anno=[], val}). % val :: integer()
-
--record(c_float, {anno=[], val}). % val :: float()
-
--record(c_atom, {anno=[], val}). % val :: atom()
-
--record(c_char, {anno=[], val}). % val :: char()
-
--record(c_string, {anno=[], val}). % val :: string()
-
--record(c_nil, {anno=[]}).
-
--record(c_binary, {anno=[], segments}). % segments :: [#ce_bitstr{}]
-
--record(c_bitstr, {anno=[],val, % val :: Tree,
- size, % size :: Tree,
- unit, % unit :: integer(),
- type, % type :: atom(),
- flags}). % flags :: [atom()],
-
--record(c_cons, {anno=[], hd, % hd :: Tree,
- tl}). % tl :: Tree
-
--record(c_tuple, {anno=[], es}). % es :: [Tree]
-
--record(c_var, {anno=[], name}). % name :: integer() | atom()
-
--record(c_fname, {anno=[], id, % id :: atom(),
- arity}). % arity :: integer()
-
--record(c_values, {anno=[], es}). % es :: [Tree]
-
--record(c_fun, {anno=[], vars, % vars :: [Tree],
- body}). % body :: Tree
-
--record(c_seq, {anno=[], arg, % arg :: Tree,
- body}). % body :: Tree
-
--record(c_let, {anno=[], vars, % vars :: [Tree],
- arg, % arg :: Tree,
- body}). % body :: Tree
-
--record(c_letrec, {anno=[], defs, % defs :: [#ce_def{}],
- body}). % body :: Tree
-
--record(c_def, {anno=[], name, % name :: Tree,
- val}). % val :: Tree,
-
--record(c_case, {anno=[], arg, % arg :: Tree,
- clauses}). % clauses :: [Tree]
-
--record(c_clause, {anno=[], pats, % pats :: [Tree],
- guard, % guard :: Tree,
- body}). % body :: Tree
-
--record(c_alias, {anno=[], var, % var :: Tree,
- pat}). % pat :: Tree
-
--record(c_receive, {anno=[], clauses, % clauses :: [Tree],
- timeout, % timeout :: Tree,
- action}). % action :: Tree
-
--record(c_apply, {anno=[], op, % op :: Tree,
- args}). % args :: [Tree]
-
--record(c_call, {anno=[], module, % module :: Tree,
- name, % name :: Tree,
- args}). % args :: [Tree]
-
--record(c_primop, {anno=[], name, % name :: Tree,
- args}). % args :: [Tree]
-
--record(c_try, {anno=[], arg, % arg :: Tree,
- vars, % vars :: [Tree],
- body, % body :: Tree
- evars, % evars :: [Tree],
- handler}). % handler :: Tree
-
--record(c_catch, {anno=[], body}). % body :: Tree
-
--record(c_module, {anno=[], name, % name :: Tree,
- exports, % exports :: [Tree],
- attrs, % attrs :: [#ce_def{}],
- defs}). % defs :: [#ce_def{}]
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_pp.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_pp.erl
deleted file mode 100644
index 147a0dba6c..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_pp.erl
+++ /dev/null
@@ -1,430 +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: core_pp.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
-%%
-%% Purpose : Core Erlang (naive) prettyprinter
-
--module(core_pp).
-
--export([format/1]).
-
--include("core_parse.hrl").
-
-%% ====================================================================== %%
-%% format(Node) -> Text
-%% Node = coreErlang()
-%% Text = string() | [Text]
-%%
-%% Prettyprint-formats (naively) an abstract Core Erlang syntax
-%% tree.
-
--record(ctxt, {class = term,
- indent = 0,
- item_indent = 2,
- body_indent = 4,
- tab_width = 8,
- line = 0}).
-
-format(Node) -> case catch format(Node, #ctxt{}) of
- {'EXIT',_} -> io_lib:format("~p",[Node]);
- Other -> Other
- end.
-
-maybe_anno(Node, Fun, Ctxt) ->
- As = core_lib:get_anno(Node),
- case get_line(As) of
- none ->
- maybe_anno(Node, Fun, Ctxt, As);
- Line ->
- if Line > Ctxt#ctxt.line ->
- [io_lib:format("%% Line ~w",[Line]),
- nl_indent(Ctxt),
- maybe_anno(Node, Fun, Ctxt#ctxt{line = Line}, As)
- ];
- true ->
- maybe_anno(Node, Fun, Ctxt, As)
- end
- end.
-
-maybe_anno(Node, Fun, Ctxt, As) ->
- case strip_line(As) of
- [] ->
- Fun(Node, Ctxt);
- List ->
- Ctxt1 = add_indent(Ctxt, 2),
- Ctxt2 = add_indent(Ctxt1, 3),
- ["( ",
- Fun(Node, Ctxt1),
- nl_indent(Ctxt1),
- "-| ",format_1(core_lib:make_literal(List), Ctxt2)," )"
- ]
- end.
-
-strip_line([A | As]) when integer(A) ->
- strip_line(As);
-strip_line([A | As]) ->
- [A | strip_line(As)];
-strip_line([]) ->
- [].
-
-get_line([L | _As]) when integer(L) ->
- L;
-get_line([_ | As]) ->
- get_line(As);
-get_line([]) ->
- none.
-
-format(Node, Ctxt) ->
- maybe_anno(Node, fun format_1/2, Ctxt).
-
-format_1(#c_char{val=C}, _) -> io_lib:write_char(C);
-format_1(#c_int{val=I}, _) -> integer_to_list(I);
-format_1(#c_float{val=F}, _) -> float_to_list(F);
-format_1(#c_atom{val=A}, _) -> core_atom(A);
-format_1(#c_nil{}, _) -> "[]";
-format_1(#c_string{val=S}, _) -> io_lib:write_string(S);
-format_1(#c_var{name=V}, _) ->
- %% Internal variable names may be:
- %% - atoms representing proper Erlang variable names, or
- %% any atoms that may be printed without single-quoting
- %% - nonnegative integers.
- %% It is important that when printing variables, no two names
- %% should ever map to the same string.
- if atom(V) ->
- S = atom_to_list(V),
- case S of
- [C | _] when C >= $A, C =< $Z ->
- %% Ordinary uppercase-prefixed names are
- %% printed just as they are.
- S;
- [$_ | _] ->
- %% Already "_"-prefixed names are prefixed
- %% with "_X", e.g. '_foo' => '_X_foo', to
- %% avoid generating things like "____foo" upon
- %% repeated writing and reading of code.
- %% ("_X_X_X_foo" is better.)
- [$_, $X | S];
- _ ->
- %% Plain atoms are prefixed with a single "_".
- %% E.g. foo => "_foo".
- [$_ | S]
- end;
- integer(V) ->
- %% Integers are also simply prefixed with "_".
- [$_ | integer_to_list(V)]
- end;
-format_1(#c_binary{segments=Segs}, Ctxt) ->
- ["#{",
- format_vseq(Segs, "", ",", add_indent(Ctxt, 2),
- fun format_bitstr/2),
- "}#"
- ];
-format_1(#c_tuple{es=Es}, Ctxt) ->
- [${,
- format_hseq(Es, ",", add_indent(Ctxt, 1), fun format/2),
- $}
- ];
-format_1(#c_cons{hd=H,tl=T}, Ctxt) ->
- Txt = ["["|format(H, add_indent(Ctxt, 1))],
- [Txt|format_list_tail(T, add_indent(Ctxt, width(Txt, Ctxt)))];
-format_1(#c_values{es=Es}, Ctxt) ->
- format_values(Es, Ctxt);
-format_1(#c_alias{var=V,pat=P}, Ctxt) ->
- Txt = [format(V, Ctxt)|" = "],
- [Txt|format(P, add_indent(Ctxt, width(Txt, Ctxt)))];
-format_1(#c_let{vars=Vs,arg=A,body=B}, Ctxt) ->
- Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.body_indent),
- ["let ",
- format_values(Vs, add_indent(Ctxt, 4)),
- " =",
- nl_indent(Ctxt1),
- format(A, Ctxt1),
- nl_indent(Ctxt),
- "in "
- | format(B, add_indent(Ctxt, 4))
- ];
-format_1(#c_letrec{defs=Fs,body=B}, Ctxt) ->
- Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.body_indent),
- ["letrec",
- nl_indent(Ctxt1),
- format_funcs(Fs, Ctxt1),
- nl_indent(Ctxt),
- "in "
- | format(B, add_indent(Ctxt, 4))
- ];
-format_1(#c_seq{arg=A,body=B}, Ctxt) ->
- Ctxt1 = add_indent(Ctxt, 4),
- ["do ",
- format(A, Ctxt1),
- nl_indent(Ctxt1)
- | format(B, Ctxt1)
- ];
-format_1(#c_case{arg=A,clauses=Cs}, Ctxt) ->
- Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.item_indent),
- ["case ",
- format(A, add_indent(Ctxt, 5)),
- " of",
- nl_indent(Ctxt1),
- format_clauses(Cs, Ctxt1),
- nl_indent(Ctxt)
- | "end"
- ];
-format_1(#c_receive{clauses=Cs,timeout=T,action=A}, Ctxt) ->
- Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.item_indent),
- ["receive",
- nl_indent(Ctxt1),
- format_clauses(Cs, Ctxt1),
- nl_indent(Ctxt),
- "after ",
- format(T, add_indent(Ctxt, 6)),
- " ->",
- nl_indent(Ctxt1),
- format(A, Ctxt1)
- ];
-format_1(#c_fname{id=I,arity=A}, _) ->
- [core_atom(I),$/,integer_to_list(A)];
-format_1(#c_fun{vars=Vs,body=B}, Ctxt) ->
- Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.body_indent),
- ["fun (",
- format_hseq(Vs, ",", add_indent(Ctxt, 5), fun format/2),
- ") ->",
- nl_indent(Ctxt1)
- | format(B, Ctxt1)
- ];
-format_1(#c_apply{op=O,args=As}, Ctxt0) ->
- Ctxt1 = add_indent(Ctxt0, 6), %"apply "
- Op = format(O, Ctxt1),
- Ctxt2 = add_indent(Ctxt0, 4),
- ["apply ",Op,
- nl_indent(Ctxt2),
- $(,format_hseq(As, ", ", add_indent(Ctxt2, 1), fun format/2),$)
- ];
-format_1(#c_call{module=M,name=N,args=As}, Ctxt0) ->
- Ctxt1 = add_indent(Ctxt0, 5), %"call "
- Mod = format(M, Ctxt1),
- Ctxt2 = add_indent(Ctxt1, width(Mod, Ctxt1)+1),
- Name = format(N, Ctxt2),
- Ctxt3 = add_indent(Ctxt0, 4),
- ["call ",Mod,":",Name,
- nl_indent(Ctxt3),
- $(,format_hseq(As, ", ", add_indent(Ctxt3, 1), fun format/2),$)
- ];
-format_1(#c_primop{name=N,args=As}, Ctxt0) ->
- Ctxt1 = add_indent(Ctxt0, 7), %"primop "
- Name = format(N, Ctxt1),
- Ctxt2 = add_indent(Ctxt0, 4),
- ["primop ",Name,
- nl_indent(Ctxt2),
- $(,format_hseq(As, ", ", add_indent(Ctxt2, 1), fun format/2),$)
- ];
-format_1(#c_catch{body=B}, Ctxt) ->
- Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.body_indent),
- ["catch",
- nl_indent(Ctxt1),
- format(B, Ctxt1)
- ];
-format_1(#c_try{arg=E,vars=Vs,body=B,evars=Evs,handler=H}, Ctxt) ->
- Ctxt1 = add_indent(Ctxt, Ctxt#ctxt.body_indent),
- ["try",
- nl_indent(Ctxt1),
- format(E, Ctxt1),
- nl_indent(Ctxt),
- "of ",
- format_values(Vs, add_indent(Ctxt, 3)),
- " ->",
- nl_indent(Ctxt1),
- format(B, Ctxt1),
- nl_indent(Ctxt),
- "catch ",
- format_values(Evs, add_indent(Ctxt, 6)),
- " ->",
- nl_indent(Ctxt1)
- | format(H, Ctxt1)
- ];
-format_1(#c_def{name=N,val=V}, Ctxt) ->
- Ctxt1 = add_indent(set_class(Ctxt, expr), Ctxt#ctxt.body_indent),
- [format(N, Ctxt),
- " =",
- nl_indent(Ctxt1)
- | format(V, Ctxt1)
- ];
-format_1(#c_module{name=N,exports=Es,attrs=As,defs=Ds}, Ctxt) ->
- Mod = ["module ", format(N, Ctxt)],
- [Mod," [",
- format_vseq(Es,
- "", ",",
- add_indent(set_class(Ctxt, term), width(Mod, Ctxt)+2),
- fun format/2),
- "]",
- nl_indent(Ctxt),
- " attributes [",
- format_vseq(As,
- "", ",",
- add_indent(set_class(Ctxt, def), 16),
- fun format/2),
- "]",
- nl_indent(Ctxt),
- format_funcs(Ds, Ctxt),
- nl_indent(Ctxt)
- | "end"
- ];
-format_1(Type, _) ->
- ["** Unsupported type: ",
- io_lib:write(Type)
- | " **"
- ].
-
-format_funcs(Fs, Ctxt) ->
- format_vseq(Fs,
- "", "",
- set_class(Ctxt, def),
- fun format/2).
-
-format_values(Vs, Ctxt) ->
- [$<,
- format_hseq(Vs, ",", add_indent(Ctxt, 1), fun format/2),
- $>].
-
-format_bitstr(#c_bitstr{val=V,size=S,unit=U,type=T,flags=Fs}, Ctxt0) ->
- Vs = [S, U, T, Fs],
- Ctxt1 = add_indent(Ctxt0, 2),
- Val = format(V, Ctxt1),
- Ctxt2 = add_indent(Ctxt1, width(Val, Ctxt1) + 2),
- ["#<", Val, ">(", format_hseq(Vs,",", Ctxt2, fun format/2), $)].
-
-format_clauses(Cs, Ctxt) ->
- format_vseq(Cs, "", "", set_class(Ctxt, clause),
- fun format_clause/2).
-
-format_clause(Node, Ctxt) ->
- maybe_anno(Node, fun format_clause_1/2, Ctxt).
-
-format_clause_1(#c_clause{pats=Ps,guard=G,body=B}, Ctxt) ->
- Ptxt = format_values(Ps, Ctxt),
- Ctxt2 = add_indent(Ctxt, Ctxt#ctxt.body_indent),
- [Ptxt,
- " when ",
- format_guard(G, add_indent(set_class(Ctxt, expr),
- width(Ptxt, Ctxt) + 6)),
- " ->",
- nl_indent(Ctxt2)
- | format(B, set_class(Ctxt2, expr))
- ].
-
-format_guard(Node, Ctxt) ->
- maybe_anno(Node, fun format_guard_1/2, Ctxt).
-
-format_guard_1(#c_call{module=M,name=N,args=As}, Ctxt0) ->
- Ctxt1 = add_indent(Ctxt0, 5), %"call "
- Mod = format(M, Ctxt1),
- Ctxt2 = add_indent(Ctxt1, width(Mod, Ctxt1)+1),
- Name = format(N, Ctxt2),
- Ctxt3 = add_indent(Ctxt0, 4),
- ["call ",Mod,":",Name,
- nl_indent(Ctxt3),
- $(,format_vseq(As, "",",", add_indent(Ctxt3, 1), fun format_guard/2),$)
- ];
-format_guard_1(E, Ctxt) -> format_1(E, Ctxt). %Anno already done
-
-%% format_hseq([Thing], Separator, Context, Fun) -> Txt.
-%% Format a sequence horizontally on the same line with Separator between.
-
-format_hseq([H], _, Ctxt, Fun) ->
- Fun(H, Ctxt);
-format_hseq([H|T], Sep, Ctxt, Fun) ->
- Txt = [Fun(H, Ctxt)|Sep],
- Ctxt1 = add_indent(Ctxt, width(Txt, Ctxt)),
- [Txt|format_hseq(T, Sep, Ctxt1, Fun)];
-format_hseq([], _, _, _) -> "".
-
-%% format_vseq([Thing], LinePrefix, LineSuffix, Context, Fun) -> Txt.
-%% Format a sequence vertically in indented lines adding LinePrefix
-%% to the beginning of each line and LineSuffix to the end of each
-%% line. No prefix on the first line or suffix on the last line.
-
-format_vseq([H], _Pre, _Suf, Ctxt, Fun) ->
- Fun(H, Ctxt);
-format_vseq([H|T], Pre, Suf, Ctxt, Fun) ->
- [Fun(H, Ctxt),Suf,nl_indent(Ctxt),Pre|
- format_vseq(T, Pre, Suf, Ctxt, Fun)];
-format_vseq([], _, _, _, _) -> "".
-
-format_list_tail(#c_nil{anno=[]}, _) -> "]";
-format_list_tail(#c_cons{anno=[],hd=H,tl=T}, Ctxt) ->
- Txt = [$,|format(H, Ctxt)],
- Ctxt1 = add_indent(Ctxt, width(Txt, Ctxt)),
- [Txt|format_list_tail(T, Ctxt1)];
-format_list_tail(Tail, Ctxt) ->
- ["|",format(Tail, add_indent(Ctxt, 1)),"]"].
-
-indent(Ctxt) -> indent(Ctxt#ctxt.indent, Ctxt).
-
-indent(N, _) when N =< 0 -> "";
-indent(N, Ctxt) ->
- T = Ctxt#ctxt.tab_width,
- string:chars($\t, N div T, string:chars($\s, N rem T)).
-
-nl_indent(Ctxt) -> [$\n|indent(Ctxt)].
-
-
-unindent(T, Ctxt) ->
- unindent(T, Ctxt#ctxt.indent, Ctxt, []).
-
-unindent(T, N, _, C) when N =< 0 ->
- [T|C];
-unindent([$\s|T], N, Ctxt, C) ->
- unindent(T, N - 1, Ctxt, C);
-unindent([$\t|T], N, Ctxt, C) ->
- Tab = Ctxt#ctxt.tab_width,
- if N >= Tab ->
- unindent(T, N - Tab, Ctxt, C);
- true ->
- unindent([string:chars($\s, Tab - N)|T], 0, Ctxt, C)
- end;
-unindent([L|T], N, Ctxt, C) when list(L) ->
- unindent(L, N, Ctxt, [T|C]);
-unindent([H|T], _, _, C) ->
- [H|[T|C]];
-unindent([], N, Ctxt, [H|T]) ->
- unindent(H, N, Ctxt, T);
-unindent([], _, _, []) -> [].
-
-
-width(Txt, Ctxt) ->
- case catch width(Txt, 0, Ctxt, []) of
- {'EXIT',_} -> exit({bad_text,Txt});
- Other -> Other
- end.
-
-width([$\t|T], A, Ctxt, C) ->
- width(T, A + Ctxt#ctxt.tab_width, Ctxt, C);
-width([$\n|T], _, Ctxt, C) ->
- width(unindent([T|C], Ctxt), Ctxt);
-width([H|T], A, Ctxt, C) when list(H) ->
- width(H, A, Ctxt, [T|C]);
-width([_|T], A, Ctxt, C) ->
- width(T, A + 1, Ctxt, C);
-width([], A, Ctxt, [H|T]) ->
- width(H, A, Ctxt, T);
-width([], A, _, []) -> A.
-
-add_indent(Ctxt, Dx) ->
- Ctxt#ctxt{indent = Ctxt#ctxt.indent + Dx}.
-
-set_class(Ctxt, Class) ->
- Ctxt#ctxt{class = Class}.
-
-core_atom(A) -> io_lib:write_string(atom_to_list(A), $').
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_scan.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_scan.erl
deleted file mode 100644
index f53c3c1631..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_scan.erl
+++ /dev/null
@@ -1,495 +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: core_scan.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
-%%
-%% Purpose: Scanner for Core Erlang.
-
-%% For handling ISO 8859-1 (Latin-1) we use the following type
-%% information:
-%%
-%% 000 - 037 NUL - US control
-%% 040 - 057 SPC - / punctuation
-%% 060 - 071 0 - 9 digit
-%% 072 - 100 : - @ punctuation
-%% 101 - 132 A - Z uppercase
-%% 133 - 140 [ - ` punctuation
-%% 141 - 172 a - z lowercase
-%% 173 - 176 { - ~ punctuation
-%% 177 DEL control
-%% 200 - 237 control
-%% 240 - 277 NBSP - � punctuation
-%% 300 - 326 � - � uppercase
-%% 327 � punctuation
-%% 330 - 336 � - � uppercase
-%% 337 - 366 � - � lowercase
-%% 367 � punctuation
-%% 370 - 377 � - � lowercase
-%%
-%% Many punctuation characters region have special meaning. Must
-%% watch using � \327, bvery close to x \170
-
--module(core_scan).
-
--export([string/1,string/2,tokens/3,format_error/1]).
-
--import(lists, [reverse/1]).
-
-%% tokens(Continuation, CharList, StartPos) ->
-%% {done, {ok, [Tok], EndPos}, Rest} |
-%% {done, {error,{ErrorPos,core_scan,What}, EndPos}, Rest} |
-%% {more, Continuation'}
-%% This is the main function into the re-entrant scanner. It calls the
-%% re-entrant pre-scanner until this says done, then calls scan/1 on
-%% the result.
-%%
-%% The continuation has the form:
-%% {RestChars,CharsSoFar,CurrentPos,StartPos}
-
-tokens([], Chars, Pos) -> %First call
- tokens({[],[],Pos,Pos}, Chars, Pos);
-tokens({Chars,SoFar0,Cp,Sp}, MoreChars, _) ->
- In = Chars ++ MoreChars,
- case pre_scan(In, SoFar0, Cp) of
- {done,_,[],Ep} -> %Found nothing
- {done,{eof,Ep},[]};
- {done,_,SoFar1,Ep} -> %Got complete tokens
- Res = case scan(reverse(SoFar1), Sp) of
- {ok,Toks} -> {ok,Toks,Ep};
- {error,E} -> {error,E,Ep}
- end,
- {done,Res,[]};
- {more,Rest,SoFar1,Cp1} -> %Missing end token
- {more,{Rest,SoFar1,Cp1,Sp}};
- Other -> %An error has occurred
- {done,Other,[]}
- end.
-
-%% string([Char]) ->
-%% string([Char], StartPos) ->
-%% {ok, [Tok], EndPos} |
-%% {error,{Pos,core_scan,What}, EndPos}
-
-string(Cs) -> string(Cs, 1).
-
-string(Cs, Sp) ->
- %% Add an 'eof' to always get correct handling.
- case string_pre_scan(Cs, [], Sp) of
- {done,_,SoFar,Ep} -> %Got tokens
- case scan(reverse(SoFar), Sp) of
- {ok,Toks} -> {ok,Toks,Ep};
- {error,E} -> {error,E,Ep}
- end;
- Other -> Other %An error has occurred
- end.
-
-%% string_pre_scan(Cs, SoFar0, StartPos) ->
-%% {done,Rest,SoFar,EndPos} | {error,E,EndPos}.
-
-string_pre_scan(Cs, SoFar0, Sp) ->
- case pre_scan(Cs, SoFar0, Sp) of
- {done,Rest,SoFar1,Ep} -> %Got complete tokens
- {done,Rest,SoFar1,Ep};
- {more,Rest,SoFar1,Ep} -> %Missing end token
- string_pre_scan(Rest ++ eof, SoFar1, Ep);
- Other -> Other %An error has occurred
- end.
-
-%% format_error(Error)
-%% Return a string describing the error.
-
-format_error({string,Quote,Head}) ->
- ["unterminated " ++ string_thing(Quote) ++
- " starting with " ++ io_lib:write_string(Head,Quote)];
-format_error({illegal,Type}) -> io_lib:fwrite("illegal ~w", [Type]);
-format_error(char) -> "unterminated character";
-format_error(scan) -> "premature end";
-format_error({base,Base}) -> io_lib:fwrite("illegal base '~w'", [Base]);
-format_error(float) -> "bad float";
-format_error(Other) -> io_lib:write(Other).
-
-string_thing($') -> "atom";
-string_thing($") -> "string".
-
-%% Re-entrant pre-scanner.
-%%
-%% If the input list of characters is insufficient to build a term the
-%% scanner returns a request for more characters and a continuation to be
-%% used when trying to build a term with more characters. To indicate
-%% end-of-file the input character list should be replaced with 'eof'
-%% as an empty list has meaning.
-%%
-%% When more characters are need inside a comment, string or quoted
-%% atom, which can become rather long, instead of pushing the
-%% characters read so far back onto RestChars to be reread, a special
-%% reentry token is returned indicating the middle of a construct.
-%% The token is the start character as an atom, '%', '"' and '\''.
-
-%% pre_scan([Char], SoFar, StartPos) ->
-%% {done,RestChars,ScannedChars,NewPos} |
-%% {more,RestChars,ScannedChars,NewPos} |
-%% {error,{ErrorPos,core_scan,Description},NewPos}.
-%% Main pre-scan function. It has been split into 2 functions because of
-%% efficiency, with a good indexing compiler it would be unnecessary.
-
-pre_scan([C|Cs], SoFar, Pos) ->
- pre_scan(C, Cs, SoFar, Pos);
-pre_scan([], SoFar, Pos) ->
- {more,[],SoFar,Pos};
-pre_scan(eof, SoFar, Pos) ->
- {done,eof,SoFar,Pos}.
-
-%% pre_scan(Char, [Char], SoFar, Pos)
-
-pre_scan($$, Cs0, SoFar0, Pos) ->
- case pre_char(Cs0, [$$|SoFar0]) of
- {Cs,SoFar} ->
- pre_scan(Cs, SoFar, Pos);
- more ->
- {more,[$$|Cs0],SoFar0, Pos};
- error ->
- pre_error(char, Pos, Pos)
- end;
-pre_scan($', Cs, SoFar, Pos) ->
- pre_string(Cs, $', '\'', Pos, [$'|SoFar], Pos);
-pre_scan({'\'',Sp}, Cs, SoFar, Pos) -> %Re-entering quoted atom
- pre_string(Cs, $', '\'', Sp, SoFar, Pos);
-pre_scan($", Cs, SoFar, Pos) ->
- pre_string(Cs, $", '"', Pos, [$"|SoFar], Pos);
-pre_scan({'"',Sp}, Cs, SoFar, Pos) -> %Re-entering string
- pre_string(Cs, $", '"', Sp, SoFar, Pos);
-pre_scan($%, Cs, SoFar, Pos) ->
- pre_comment(Cs, SoFar, Pos);
-pre_scan('%', Cs, SoFar, Pos) -> %Re-entering comment
- pre_comment(Cs, SoFar, Pos);
-pre_scan($\n, Cs, SoFar, Pos) ->
- pre_scan(Cs, [$\n|SoFar], Pos+1);
-pre_scan(C, Cs, SoFar, Pos) ->
- pre_scan(Cs, [C|SoFar], Pos).
-
-%% pre_string([Char], Quote, Reent, StartPos, SoFar, Pos)
-
-pre_string([Q|Cs], Q, _, _, SoFar, Pos) ->
- pre_scan(Cs, [Q|SoFar], Pos);
-pre_string([$\n|Cs], Q, Reent, Sp, SoFar, Pos) ->
- pre_string(Cs, Q, Reent, Sp, [$\n|SoFar], Pos+1);
-pre_string([$\\|Cs0], Q, Reent, Sp, SoFar0, Pos) ->
- case pre_escape(Cs0, SoFar0) of
- {Cs,SoFar} ->
- pre_string(Cs, Q, Reent, Sp, SoFar, Pos);
- more ->
- {more,[{Reent,Sp},$\\|Cs0],SoFar0,Pos};
- error ->
- pre_string_error(Q, Sp, SoFar0, Pos)
- end;
-pre_string([C|Cs], Q, Reent, Sp, SoFar, Pos) ->
- pre_string(Cs, Q, Reent, Sp, [C|SoFar], Pos);
-pre_string([], _, Reent, Sp, SoFar, Pos) ->
- {more,[{Reent,Sp}],SoFar,Pos};
-pre_string(eof, Q, _, Sp, SoFar, Pos) ->
- pre_string_error(Q, Sp, SoFar, Pos).
-
-pre_string_error(Q, Sp, SoFar, Pos) ->
- S = reverse(string:substr(SoFar, 1, string:chr(SoFar, Q)-1)),
- pre_error({string,Q,string:substr(S, 1, 16)}, Sp, Pos).
-
-pre_char([C|Cs], SoFar) -> pre_char(C, Cs, SoFar);
-pre_char([], _) -> more;
-pre_char(eof, _) -> error.
-
-pre_char($\\, Cs, SoFar) ->
- pre_escape(Cs, SoFar);
-pre_char(C, Cs, SoFar) ->
- {Cs,[C|SoFar]}.
-
-pre_escape([$^|Cs0], SoFar) ->
- case Cs0 of
- [C3|Cs] ->
- {Cs,[C3,$^,$\\|SoFar]};
- [] -> more;
- eof -> error
- end;
-pre_escape([C|Cs], SoFar) ->
- {Cs,[C,$\\|SoFar]};
-pre_escape([], _) -> more;
-pre_escape(eof, _) -> error.
-
-%% pre_comment([Char], SoFar, Pos)
-%% Comments are replaced by one SPACE.
-
-pre_comment([$\n|Cs], SoFar, Pos) ->
- pre_scan(Cs, [$\n,$\s|SoFar], Pos+1); %Terminate comment
-pre_comment([_|Cs], SoFar, Pos) ->
- pre_comment(Cs, SoFar, Pos);
-pre_comment([], SoFar, Pos) ->
- {more,['%'],SoFar,Pos};
-pre_comment(eof, Sofar, Pos) ->
- pre_scan(eof, [$\s|Sofar], Pos).
-
-pre_error(E, Epos, Pos) ->
- {error,{Epos,core_scan,E}, Pos}.
-
-%% scan(CharList, StartPos)
-%% This takes a list of characters and tries to tokenise them.
-%%
-%% The token list is built in reverse order (in a stack) to save appending
-%% and then reversed when all the tokens have been collected. Most tokens
-%% are built in the same way.
-%%
-%% Returns:
-%% {ok,[Tok]}
-%% {error,{ErrorPos,core_scan,What}}
-
-scan(Cs, Pos) ->
- scan1(Cs, [], Pos).
-
-%% scan1(Characters, TokenStack, Position)
-%% Scan a list of characters into tokens.
-
-scan1([$\n|Cs], Toks, Pos) -> %Skip newline
- scan1(Cs, Toks, Pos+1);
-scan1([C|Cs], Toks, Pos) when C >= $\000, C =< $\s -> %Skip control chars
- scan1(Cs, Toks, Pos);
-scan1([C|Cs], Toks, Pos) when C >= $\200, C =< $\240 ->
- scan1(Cs, Toks, Pos);
-scan1([C|Cs], Toks, Pos) when C >= $a, C =< $z -> %Keywords
- scan_key_word(C, Cs, Toks, Pos);
-scan1([C|Cs], Toks, Pos) when C >= $�, C =< $�, C /= $� ->
- scan_key_word(C, Cs, Toks, Pos);
-scan1([C|Cs], Toks, Pos) when C >= $A, C =< $Z -> %Variables
- scan_variable(C, Cs, Toks, Pos);
-scan1([C|Cs], Toks, Pos) when C >= $�, C =< $�, C /= $� ->
- scan_variable(C, Cs, Toks, Pos);
-scan1([C|Cs], Toks, Pos) when C >= $0, C =< $9 -> %Numbers
- scan_number(C, Cs, Toks, Pos);
-scan1([$-,C|Cs], Toks, Pos) when C >= $0, C =< $9 -> %Signed numbers
- scan_signed_number($-, C, Cs, Toks, Pos);
-scan1([$+,C|Cs], Toks, Pos) when C >= $0, C =< $9 -> %Signed numbers
- scan_signed_number($+, C, Cs, Toks, Pos);
-scan1([$_|Cs], Toks, Pos) -> %_ variables
- scan_variable($_, Cs, Toks, Pos);
-scan1([$$|Cs0], Toks, Pos) -> %Character constant
- {C,Cs,Pos1} = scan_char(Cs0, Pos),
- scan1(Cs, [{char,Pos,C}|Toks], Pos1);
-scan1([$'|Cs0], Toks, Pos) -> %Atom (always quoted)
- {S,Cs1,Pos1} = scan_string(Cs0, $', Pos),
- case catch list_to_atom(S) of
- A when atom(A) ->
- scan1(Cs1, [{atom,Pos,A}|Toks], Pos1);
- _Error -> scan_error({illegal,atom}, Pos)
- end;
-scan1([$"|Cs0], Toks, Pos) -> %String
- {S,Cs1,Pos1} = scan_string(Cs0, $", Pos),
- scan1(Cs1, [{string,Pos,S}|Toks], Pos1);
-%% Punctuation characters and operators, first recognise multiples.
-scan1("->" ++ Cs, Toks, Pos) ->
- scan1(Cs, [{'->',Pos}|Toks], Pos);
-scan1("-|" ++ Cs, Toks, Pos) ->
- scan1(Cs, [{'-|',Pos}|Toks], Pos);
-scan1([C|Cs], Toks, Pos) -> %Punctuation character
- P = list_to_atom([C]),
- scan1(Cs, [{P,Pos}|Toks], Pos);
-scan1([], Toks0, _) ->
- Toks = reverse(Toks0),
- {ok,Toks}.
-
-%% scan_key_word(FirstChar, CharList, Tokens, Pos)
-%% scan_variable(FirstChar, CharList, Tokens, Pos)
-
-scan_key_word(C, Cs0, Toks, Pos) ->
- {Wcs,Cs} = scan_name(Cs0, []),
- case catch list_to_atom([C|reverse(Wcs)]) of
- Name when atom(Name) ->
- scan1(Cs, [{Name,Pos}|Toks], Pos);
- _Error -> scan_error({illegal,atom}, Pos)
- end.
-
-scan_variable(C, Cs0, Toks, Pos) ->
- {Wcs,Cs} = scan_name(Cs0, []),
- case catch list_to_atom([C|reverse(Wcs)]) of
- Name when atom(Name) ->
- scan1(Cs, [{var,Pos,Name}|Toks], Pos);
- _Error -> scan_error({illegal,var}, Pos)
- end.
-
-%% scan_name(Cs) -> lists:splitwith(fun (C) -> name_char(C) end, Cs).
-
-scan_name([C|Cs], Ncs) ->
- case name_char(C) of
- true -> scan_name(Cs, [C|Ncs]);
- false -> {Ncs,[C|Cs]} %Must rebuild here, sigh!
- end;
-scan_name([], Ncs) ->
- {Ncs,[]}.
-
-name_char(C) when C >= $a, C =< $z -> true;
-name_char(C) when C >= $�, C =< $�, C /= $� -> true;
-name_char(C) when C >= $A, C =< $Z -> true;
-name_char(C) when C >= $�, C =< $�, C /= $� -> true;
-name_char(C) when C >= $0, C =< $9 -> true;
-name_char($_) -> true;
-name_char($@) -> true;
-name_char(_) -> false.
-
-%% scan_string(CharList, QuoteChar, Pos) -> {StringChars,RestChars,NewPos}.
-
-scan_string(Cs, Q, Pos) ->
- scan_string(Cs, [], Q, Pos).
-
-scan_string([Q|Cs], Scs, Q, Pos) ->
- {reverse(Scs),Cs,Pos};
-scan_string([$\n|Cs], Scs, Q, Pos) ->
- scan_string(Cs, [$\n|Scs], Q, Pos+1);
-scan_string([$\\|Cs0], Scs, Q, Pos) ->
- {C,Cs,Pos1} = scan_escape(Cs0, Pos),
- scan_string(Cs, [C|Scs], Q, Pos1);
-scan_string([C|Cs], Scs, Q, Pos) ->
- scan_string(Cs, [C|Scs], Q, Pos).
-
-%% scan_char(Chars, Pos) -> {Char,RestChars,NewPos}.
-%% Read a single character from a character constant. The pre-scan
-%% phase has checked for errors here.
-
-scan_char([$\\|Cs], Pos) ->
- scan_escape(Cs, Pos);
-scan_char([$\n|Cs], Pos) -> %Newline
- {$\n,Cs,Pos+1};
-scan_char([C|Cs], Pos) ->
- {C,Cs,Pos}.
-
-scan_escape([O1,O2,O3|Cs], Pos) when %\<1-3> octal digits
- O1 >= $0, O1 =< $7, O2 >= $0, O2 =< $7, O3 >= $0, O3 =< $7 ->
- Val = (O1*8 + O2)*8 + O3 - 73*$0,
- {Val,Cs,Pos};
-scan_escape([O1,O2|Cs], Pos) when
- O1 >= $0, O1 =< $7, O2 >= $0, O2 =< $7 ->
- Val = (O1*8 + O2) - 9*$0,
- {Val,Cs,Pos};
-scan_escape([O1|Cs], Pos) when
- O1 >= $0, O1 =< $7 ->
- {O1 - $0,Cs,Pos};
-scan_escape([$^,C|Cs], Pos) -> %\^X -> CTL-X
- Val = C band 31,
- {Val,Cs,Pos};
-%scan_escape([$\n,C1|Cs],Pos) ->
-% {C1,Cs,Pos+1};
-%scan_escape([C,C1|Cs],Pos) when C >= $\000, C =< $\s ->
-% {C1,Cs,Pos};
-scan_escape([$\n|Cs],Pos) ->
- {$\n,Cs,Pos+1};
-scan_escape([C0|Cs],Pos) ->
- C = escape_char(C0),
- {C,Cs,Pos}.
-
-escape_char($n) -> $\n; %\n = LF
-escape_char($r) -> $\r; %\r = CR
-escape_char($t) -> $\t; %\t = TAB
-escape_char($v) -> $\v; %\v = VT
-escape_char($b) -> $\b; %\b = BS
-escape_char($f) -> $\f; %\f = FF
-escape_char($e) -> $\e; %\e = ESC
-escape_char($s) -> $\s; %\s = SPC
-escape_char($d) -> $\d; %\d = DEL
-escape_char(C) -> C.
-
-%% scan_number(Char, CharList, TokenStack, Pos)
-%% We can handle simple radix notation:
-%% <digit>#<digits> - the digits read in that base
-%% <digits> - the digits in base 10
-%% <digits>.<digits>
-%% <digits>.<digits>E+-<digits>
-%%
-%% Except for explicitly based integers we build a list of all the
-%% characters and then use list_to_integer/1 or list_to_float/1 to
-%% generate the value.
-
-%% SPos == Start position
-%% CPos == Current position
-
-scan_number(C, Cs0, Toks, Pos) ->
- {Ncs,Cs,Pos1} = scan_integer(Cs0, [C], Pos),
- scan_after_int(Cs, Ncs, Toks, Pos, Pos1).
-
-scan_signed_number(S, C, Cs0, Toks, Pos) ->
- {Ncs,Cs,Pos1} = scan_integer(Cs0, [C,S], Pos),
- scan_after_int(Cs, Ncs, Toks, Pos, Pos1).
-
-scan_integer([C|Cs], Stack, Pos) when C >= $0, C =< $9 ->
- scan_integer(Cs, [C|Stack], Pos);
-scan_integer(Cs, Stack, Pos) ->
- {Stack,Cs,Pos}.
-
-scan_after_int([$.,C|Cs0], Ncs0, Toks, SPos, CPos) when C >= $0, C =< $9 ->
- {Ncs,Cs,CPos1} = scan_integer(Cs0, [C,$.|Ncs0], CPos),
- scan_after_fraction(Cs, Ncs, Toks, SPos, CPos1);
-scan_after_int([$#|Cs], Ncs, Toks, SPos, CPos) ->
- case list_to_integer(reverse(Ncs)) of
- Base when Base >= 2, Base =< 16 ->
- scan_based_int(Cs, 0, Base, Toks, SPos, CPos);
- Base ->
- scan_error({base,Base}, CPos)
- end;
-scan_after_int(Cs, Ncs, Toks, SPos, CPos) ->
- N = list_to_integer(reverse(Ncs)),
- scan1(Cs, [{integer,SPos,N}|Toks], CPos).
-
-scan_based_int([C|Cs], SoFar, Base, Toks, SPos, CPos) when
- C >= $0, C =< $9, C < Base + $0 ->
- Next = SoFar * Base + (C - $0),
- scan_based_int(Cs, Next, Base, Toks, SPos, CPos);
-scan_based_int([C|Cs], SoFar, Base, Toks, SPos, CPos) when
- C >= $a, C =< $f, C < Base + $a - 10 ->
- Next = SoFar * Base + (C - $a + 10),
- scan_based_int(Cs, Next, Base, Toks, SPos, CPos);
-scan_based_int([C|Cs], SoFar, Base, Toks, SPos, CPos) when
- C >= $A, C =< $F, C < Base + $A - 10 ->
- Next = SoFar * Base + (C - $A + 10),
- scan_based_int(Cs, Next, Base, Toks, SPos, CPos);
-scan_based_int(Cs, SoFar, _, Toks, SPos, CPos) ->
- scan1(Cs, [{integer,SPos,SoFar}|Toks], CPos).
-
-scan_after_fraction([$E|Cs], Ncs, Toks, SPos, CPos) ->
- scan_exponent(Cs, [$E|Ncs], Toks, SPos, CPos);
-scan_after_fraction([$e|Cs], Ncs, Toks, SPos, CPos) ->
- scan_exponent(Cs, [$E|Ncs], Toks, SPos, CPos);
-scan_after_fraction(Cs, Ncs, Toks, SPos, CPos) ->
- case catch list_to_float(reverse(Ncs)) of
- N when float(N) ->
- scan1(Cs, [{float,SPos,N}|Toks], CPos);
- _Error -> scan_error({illegal,float}, SPos)
- end.
-
-%% scan_exponent(CharList, NumberCharStack, TokenStack, StartPos, CurPos)
-%% Generate an error here if E{+|-} not followed by any digits.
-
-scan_exponent([$+|Cs], Ncs, Toks, SPos, CPos) ->
- scan_exponent1(Cs, [$+|Ncs], Toks, SPos, CPos);
-scan_exponent([$-|Cs], Ncs, Toks, SPos, CPos) ->
- scan_exponent1(Cs, [$-|Ncs], Toks, SPos, CPos);
-scan_exponent(Cs, Ncs, Toks, SPos, CPos) ->
- scan_exponent1(Cs, Ncs, Toks, SPos, CPos).
-
-scan_exponent1([C|Cs0], Ncs0, Toks, SPos, CPos) when C >= $0, C =< $9 ->
- {Ncs,Cs,CPos1} = scan_integer(Cs0, [C|Ncs0], CPos),
- case catch list_to_float(reverse(Ncs)) of
- N when float(N) ->
- scan1(Cs, [{float,SPos,N}|Toks], CPos1);
- _Error -> scan_error({illegal,float}, SPos)
- end;
-scan_exponent1(_, _, _, _, CPos) ->
- scan_error(float, CPos).
-
-scan_error(In, Pos) ->
- {error,{Pos,core_scan,In}}.
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/erl_bifs.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/erl_bifs.erl
deleted file mode 100644
index 088f44f9fd..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/erl_bifs.erl
+++ /dev/null
@@ -1,486 +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: erl_bifs.erl,v 1.2 2009/09/17 09:46:19 kostis Exp $
-%%
-%% Purpose: Information about the Erlang built-in functions.
-
--module(erl_bifs).
-
--export([is_bif/3, is_guard_bif/3, is_pure/3, is_safe/3]).
-
-
-%% =====================================================================
-%% is_bif(Module, Name, Arity) -> boolean()
-%%
-%% Module = Name = atom()
-%% Arity = integer()
-%%
-%% Returns `true' if the function `Module:Name/Arity' is a Built-In
-%% Function (BIF) of Erlang. BIFs "come with the implementation",
-%% and can be assumed to exist and have the same behaviour in any
-%% later versions of the same implementation of the language. Being
-%% a BIF does *not* imply that the function belongs to the module
-%% `erlang', nor that it is implemented in C or assembler (cf.
-%% `erlang:is_builtin/3'), or that it is auto-imported by the
-%% compiler (cf. `erl_internal:bif/3').
-
-is_bif(erlang, '!', 2) -> true;
-is_bif(erlang, '*', 2) -> true;
-is_bif(erlang, '+', 1) -> true;
-is_bif(erlang, '+', 2) -> true;
-is_bif(erlang, '++', 2) -> true;
-is_bif(erlang, '-', 1) -> true;
-is_bif(erlang, '-', 2) -> true;
-is_bif(erlang, '--', 2) -> true;
-is_bif(erlang, '/', 2) -> true;
-is_bif(erlang, '/=', 2) -> true;
-is_bif(erlang, '<', 2) -> true;
-is_bif(erlang, '=/=', 2) -> true;
-is_bif(erlang, '=:=', 2) -> true;
-is_bif(erlang, '=<', 2) -> true;
-is_bif(erlang, '==', 2) -> true;
-is_bif(erlang, '>', 2) -> true;
-is_bif(erlang, '>=', 2) -> true;
-is_bif(erlang, 'and', 2) -> true;
-is_bif(erlang, 'band', 2) -> true;
-is_bif(erlang, 'bnot', 1) -> true;
-is_bif(erlang, 'bor', 2) -> true;
-is_bif(erlang, 'bsl', 2) -> true;
-is_bif(erlang, 'bsr', 2) -> true;
-is_bif(erlang, 'bxor', 2) -> true;
-is_bif(erlang, 'div', 2) -> true;
-is_bif(erlang, 'not', 1) -> true;
-is_bif(erlang, 'or', 2) -> true;
-is_bif(erlang, 'rem', 2) -> true;
-is_bif(erlang, 'xor', 2) -> true;
-is_bif(erlang, abs, 1) -> true;
-is_bif(erlang, append_element, 2) -> true;
-is_bif(erlang, apply, 2) -> true;
-is_bif(erlang, apply, 3) -> true;
-is_bif(erlang, atom_to_list, 1) -> true;
-is_bif(erlang, binary_to_list, 1) -> true;
-is_bif(erlang, binary_to_list, 3) -> true;
-is_bif(erlang, binary_to_term, 1) -> true;
-is_bif(erlang, cancel_timer, 1) -> true;
-is_bif(erlang, concat_binary, 1) -> true;
-is_bif(erlang, date, 0) -> true;
-is_bif(erlang, demonitor, 1) -> true;
-is_bif(erlang, disconnect_node, 1) -> true;
-is_bif(erlang, display, 1) -> true;
-is_bif(erlang, element, 2) -> true;
-is_bif(erlang, erase, 0) -> true;
-is_bif(erlang, erase, 1) -> true;
-is_bif(erlang, error, 1) -> true;
-is_bif(erlang, error, 2) -> true;
-is_bif(erlang, exit, 1) -> true;
-is_bif(erlang, exit, 2) -> true;
-is_bif(erlang, fault, 1) -> true;
-is_bif(erlang, fault, 2) -> true;
-is_bif(erlang, float, 1) -> true;
-is_bif(erlang, float_to_list, 1) -> true;
-is_bif(erlang, fun_info, 1) -> true;
-is_bif(erlang, fun_info, 2) -> true;
-is_bif(erlang, fun_to_list, 1) -> true;
-is_bif(erlang, get, 0) -> true;
-is_bif(erlang, get, 1) -> true;
-is_bif(erlang, get_cookie, 0) -> true;
-is_bif(erlang, get_keys, 1) -> true;
-is_bif(erlang, group_leader, 0) -> true;
-is_bif(erlang, group_leader, 2) -> true;
-is_bif(erlang, halt, 0) -> false;
-is_bif(erlang, halt, 1) -> false;
-is_bif(erlang, hash, 2) -> false;
-is_bif(erlang, hd, 1) -> true;
-is_bif(erlang, info, 1) -> true;
-is_bif(erlang, integer_to_list, 1) -> true;
-is_bif(erlang, is_alive, 0) -> true;
-is_bif(erlang, is_atom, 1) -> true;
-is_bif(erlang, is_binary, 1) -> true;
-is_bif(erlang, is_boolean, 1) -> true;
-is_bif(erlang, is_builtin, 3) -> true;
-is_bif(erlang, is_constant, 1) -> true;
-is_bif(erlang, is_float, 1) -> true;
-is_bif(erlang, is_function, 1) -> true;
-is_bif(erlang, is_integer, 1) -> true;
-is_bif(erlang, is_list, 1) -> true;
-is_bif(erlang, is_number, 1) -> true;
-is_bif(erlang, is_pid, 1) -> true;
-is_bif(erlang, is_port, 1) -> true;
-is_bif(erlang, is_process_alive, 1) -> true;
-is_bif(erlang, is_record, 3) -> true;
-is_bif(erlang, is_reference, 1) -> true;
-is_bif(erlang, is_tuple, 1) -> true;
-is_bif(erlang, length, 1) -> true;
-is_bif(erlang, link, 1) -> true;
-is_bif(erlang, list_to_atom, 1) -> true;
-is_bif(erlang, list_to_binary, 1) -> true;
-is_bif(erlang, list_to_float, 1) -> true;
-is_bif(erlang, list_to_integer, 1) -> true;
-is_bif(erlang, list_to_pid, 1) -> true;
-is_bif(erlang, list_to_tuple, 1) -> true;
-is_bif(erlang, loaded, 0) -> true;
-is_bif(erlang, localtime, 0) -> true;
-is_bif(erlang, localtime_to_universaltime, 1) -> true;
-is_bif(erlang, make_ref, 0) -> true;
-is_bif(erlang, make_tuple, 2) -> true;
-is_bif(erlang, md5, 1) -> true;
-is_bif(erlang, md5_final, 1) -> true;
-is_bif(erlang, md5_init, 0) -> true;
-is_bif(erlang, md5_update, 2) -> true;
-is_bif(erlang, monitor, 2) -> true;
-is_bif(erlang, monitor_node, 2) -> true;
-is_bif(erlang, node, 0) -> true;
-is_bif(erlang, node, 1) -> true;
-is_bif(erlang, nodes, 0) -> true;
-is_bif(erlang, now, 0) -> true;
-is_bif(erlang, open_port, 2) -> true;
-is_bif(erlang, phash, 2) -> true;
-is_bif(erlang, pid_to_list, 1) -> true;
-is_bif(erlang, port_close, 2) -> true;
-is_bif(erlang, port_command, 2) -> true;
-is_bif(erlang, port_connect, 2) -> true;
-is_bif(erlang, port_control, 3) -> true;
-is_bif(erlang, port_info, 2) -> true;
-is_bif(erlang, port_to_list, 1) -> true;
-is_bif(erlang, ports, 0) -> true;
-is_bif(erlang, pre_loaded, 0) -> true;
-is_bif(erlang, process_display, 2) -> true;
-is_bif(erlang, process_flag, 2) -> true;
-is_bif(erlang, process_flag, 3) -> true;
-is_bif(erlang, process_info, 1) -> true;
-is_bif(erlang, process_info, 2) -> true;
-is_bif(erlang, processes, 0) -> true;
-is_bif(erlang, put, 2) -> true;
-is_bif(erlang, read_timer, 1) -> true;
-is_bif(erlang, ref_to_list, 1) -> true;
-is_bif(erlang, register, 2) -> true;
-is_bif(erlang, registered, 0) -> true;
-is_bif(erlang, resume_process, 1) -> true;
-is_bif(erlang, round, 1) -> true;
-is_bif(erlang, self, 0) -> true;
-is_bif(erlang, send_after, 3) -> true;
-is_bif(erlang, set_cookie, 2) -> true;
-is_bif(erlang, setelement, 3) -> true;
-is_bif(erlang, size, 1) -> true;
-is_bif(erlang, spawn, 1) -> true;
-is_bif(erlang, spawn, 2) -> true;
-is_bif(erlang, spawn, 3) -> true;
-is_bif(erlang, spawn, 4) -> true;
-is_bif(erlang, spawn_link, 1) -> true;
-is_bif(erlang, spawn_link, 2) -> true;
-is_bif(erlang, spawn_link, 3) -> true;
-is_bif(erlang, spawn_link, 4) -> true;
-is_bif(erlang, spawn_opt, 4) -> true;
-is_bif(erlang, split_binary, 2) -> true;
-is_bif(erlang, start_timer, 3) -> true;
-is_bif(erlang, statistics, 1) -> true;
-is_bif(erlang, suspend_process, 1) -> true;
-is_bif(erlang, system_flag, 2) -> true;
-is_bif(erlang, system_info, 1) -> true;
-is_bif(erlang, term_to_binary, 1) -> true;
-is_bif(erlang, term_to_binary, 2) -> true;
-is_bif(erlang, throw, 1) -> true;
-is_bif(erlang, time, 0) -> true;
-is_bif(erlang, tl, 1) -> true;
-is_bif(erlang, trace, 3) -> true;
-is_bif(erlang, trace_info, 2) -> true;
-is_bif(erlang, trace_pattern, 2) -> true;
-is_bif(erlang, trace_pattern, 3) -> true;
-is_bif(erlang, trunc, 1) -> true;
-is_bif(erlang, tuple_to_list, 1) -> true;
-is_bif(erlang, universaltime, 0) -> true;
-is_bif(erlang, universaltime_to_localtime, 1) -> true;
-is_bif(erlang, unlink, 1) -> true;
-is_bif(erlang, unregister, 1) -> true;
-is_bif(erlang, whereis, 1) -> true;
-is_bif(erlang, yield, 0) -> true;
-is_bif(lists, append, 2) -> true;
-is_bif(lists, reverse, 1) -> true;
-is_bif(lists, reverse, 2) -> true;
-is_bif(lists, subtract, 2) -> true;
-is_bif(math, acos, 1) -> true;
-is_bif(math, acosh, 1) -> true;
-is_bif(math, asin, 1) -> true;
-is_bif(math, asinh, 1) -> true;
-is_bif(math, atan, 1) -> true;
-is_bif(math, atan2, 2) -> true;
-is_bif(math, atanh, 1) -> true;
-is_bif(math, cos, 1) -> true;
-is_bif(math, cosh, 1) -> true;
-is_bif(math, erf, 1) -> true;
-is_bif(math, erfc, 1) -> true;
-is_bif(math, exp, 1) -> true;
-is_bif(math, log, 1) -> true;
-is_bif(math, log10, 1) -> true;
-is_bif(math, pow, 2) -> true;
-is_bif(math, sin, 1) -> true;
-is_bif(math, sinh, 1) -> true;
-is_bif(math, sqrt, 1) -> true;
-is_bif(math, tan, 1) -> true;
-is_bif(math, tanh, 1) -> true;
-is_bif(_, _, _) -> false.
-
-
-%% =====================================================================
-%% is_guard_bif(Module, Name, Arity) -> boolean()
-%%
-%% Module = Name = atom()
-%% Arity = integer()
-%%
-%% Returns `true' if the built-in function `Module:Name/Arity' may
-%% be called from a clause guard. Note that such "guard BIFs" are
-%% not necessarily "pure", since some (notably `erlang:self/0') may
-%% depend on the current state, nor "safe", since many guard BIFs
-%% can fail. Also note that even a "pure" function could be
-%% unsuitable for calling from a guard because of its time or space
-%% complexity.
-
-is_guard_bif(erlang, '*', 2) -> true;
-is_guard_bif(erlang, '+', 1) -> true;
-is_guard_bif(erlang, '+', 2) -> true;
-is_guard_bif(erlang, '-', 1) -> true;
-is_guard_bif(erlang, '-', 2) -> true;
-is_guard_bif(erlang, '/', 2) -> true;
-is_guard_bif(erlang, '/=', 2) -> true;
-is_guard_bif(erlang, '<', 2) -> true;
-is_guard_bif(erlang, '=/=', 2) -> true;
-is_guard_bif(erlang, '=:=', 2) -> true;
-is_guard_bif(erlang, '=<', 2) -> true;
-is_guard_bif(erlang, '==', 2) -> true;
-is_guard_bif(erlang, '>', 2) -> true;
-is_guard_bif(erlang, '>=', 2) -> true;
-is_guard_bif(erlang, 'and', 2) -> true;
-is_guard_bif(erlang, 'band', 2) -> true;
-is_guard_bif(erlang, 'bnot', 1) -> true;
-is_guard_bif(erlang, 'bor', 2) -> true;
-is_guard_bif(erlang, 'bsl', 2) -> true;
-is_guard_bif(erlang, 'bsr', 2) -> true;
-is_guard_bif(erlang, 'bxor', 2) -> true;
-is_guard_bif(erlang, 'div', 2) -> true;
-is_guard_bif(erlang, 'not', 1) -> true;
-is_guard_bif(erlang, 'or', 2) -> true;
-is_guard_bif(erlang, 'rem', 2) -> true;
-is_guard_bif(erlang, 'xor', 2) -> true;
-is_guard_bif(erlang, abs, 1) -> true;
-is_guard_bif(erlang, element, 2) -> true;
-is_guard_bif(erlang, error, 1) -> true; % unorthodox
-is_guard_bif(erlang, exit, 1) -> true; % unorthodox
-is_guard_bif(erlang, fault, 1) -> true; % unorthodox
-is_guard_bif(erlang, float, 1) -> true; % (the type coercion function)
-is_guard_bif(erlang, hd, 1) -> true;
-is_guard_bif(erlang, is_atom, 1) -> true;
-is_guard_bif(erlang, is_boolean, 1) -> true;
-is_guard_bif(erlang, is_binary, 1) -> true;
-is_guard_bif(erlang, is_constant, 1) -> true;
-is_guard_bif(erlang, is_float, 1) -> true;
-is_guard_bif(erlang, is_function, 1) -> true;
-is_guard_bif(erlang, is_integer, 1) -> true;
-is_guard_bif(erlang, is_list, 1) -> true;
-is_guard_bif(erlang, is_number, 1) -> true;
-is_guard_bif(erlang, is_pid, 1) -> true;
-is_guard_bif(erlang, is_port, 1) -> true;
-is_guard_bif(erlang, is_reference, 1) -> true;
-is_guard_bif(erlang, is_tuple, 1) -> true;
-is_guard_bif(erlang, length, 1) -> true;
-is_guard_bif(erlang, list_to_atom, 1) -> true; % unorthodox
-is_guard_bif(erlang, node, 0) -> true; % (not pure)
-is_guard_bif(erlang, node, 1) -> true; % (not pure)
-is_guard_bif(erlang, round, 1) -> true;
-is_guard_bif(erlang, self, 0) -> true; % (not pure)
-is_guard_bif(erlang, size, 1) -> true;
-is_guard_bif(erlang, throw, 1) -> true; % unorthodox
-is_guard_bif(erlang, tl, 1) -> true;
-is_guard_bif(erlang, trunc, 1) -> true;
-is_guard_bif(math, acos, 1) -> true; % unorthodox
-is_guard_bif(math, acosh, 1) -> true; % unorthodox
-is_guard_bif(math, asin, 1) -> true; % unorthodox
-is_guard_bif(math, asinh, 1) -> true; % unorthodox
-is_guard_bif(math, atan, 1) -> true; % unorthodox
-is_guard_bif(math, atan2, 2) -> true; % unorthodox
-is_guard_bif(math, atanh, 1) -> true; % unorthodox
-is_guard_bif(math, cos, 1) -> true; % unorthodox
-is_guard_bif(math, cosh, 1) -> true; % unorthodox
-is_guard_bif(math, erf, 1) -> true; % unorthodox
-is_guard_bif(math, erfc, 1) -> true; % unorthodox
-is_guard_bif(math, exp, 1) -> true; % unorthodox
-is_guard_bif(math, log, 1) -> true; % unorthodox
-is_guard_bif(math, log10, 1) -> true; % unorthodox
-is_guard_bif(math, pow, 2) -> true; % unorthodox
-is_guard_bif(math, sin, 1) -> true; % unorthodox
-is_guard_bif(math, sinh, 1) -> true; % unorthodox
-is_guard_bif(math, sqrt, 1) -> true; % unorthodox
-is_guard_bif(math, tan, 1) -> true; % unorthodox
-is_guard_bif(math, tanh, 1) -> true; % unorthodox
-is_guard_bif(_, _, _) -> false.
-
-
-%% =====================================================================
-%% is_pure(Module, Name, Arity) -> boolean()
-%%
-%% Module = Name = atom()
-%% Arity = integer()
-%%
-%% Returns `true' if the function `Module:Name/Arity' does not
-%% affect the state, nor depend on the state, although its
-%% evaluation is not guaranteed to complete normally for all input.
-
-is_pure(erlang, '*', 2) -> true;
-is_pure(erlang, '+', 1) -> true; % (even for non-numbers)
-is_pure(erlang, '+', 2) -> true;
-is_pure(erlang, '++', 2) -> true;
-is_pure(erlang, '-', 1) -> true;
-is_pure(erlang, '-', 2) -> true;
-is_pure(erlang, '--', 2) -> true;
-is_pure(erlang, '/', 2) -> true;
-is_pure(erlang, '/=', 2) -> true;
-is_pure(erlang, '<', 2) -> true;
-is_pure(erlang, '=/=', 2) -> true;
-is_pure(erlang, '=:=', 2) -> true;
-is_pure(erlang, '=<', 2) -> true;
-is_pure(erlang, '==', 2) -> true;
-is_pure(erlang, '>', 2) -> true;
-is_pure(erlang, '>=', 2) -> true;
-is_pure(erlang, 'and', 2) -> true;
-is_pure(erlang, 'band', 2) -> true;
-is_pure(erlang, 'bnot', 1) -> true;
-is_pure(erlang, 'bor', 2) -> true;
-is_pure(erlang, 'bsl', 2) -> true;
-is_pure(erlang, 'bsr', 2) -> true;
-is_pure(erlang, 'bxor', 2) -> true;
-is_pure(erlang, 'div', 2) -> true;
-is_pure(erlang, 'not', 1) -> true;
-is_pure(erlang, 'or', 2) -> true;
-is_pure(erlang, 'rem', 2) -> true;
-is_pure(erlang, 'xor', 2) -> true;
-is_pure(erlang, abs, 1) -> true;
-is_pure(erlang, atom_to_list, 1) -> true;
-is_pure(erlang, binary_to_list, 1) -> true;
-is_pure(erlang, binary_to_list, 3) -> true;
-is_pure(erlang, concat_binary, 1) -> true;
-is_pure(erlang, element, 2) -> true;
-is_pure(erlang, float, 1) -> true;
-is_pure(erlang, float_to_list, 1) -> true;
-is_pure(erlang, hash, 2) -> false;
-is_pure(erlang, hd, 1) -> true;
-is_pure(erlang, integer_to_list, 1) -> true;
-is_pure(erlang, is_atom, 1) -> true;
-is_pure(erlang, is_boolean, 1) -> true;
-is_pure(erlang, is_binary, 1) -> true;
-is_pure(erlang, is_builtin, 3) -> true;
-is_pure(erlang, is_constant, 1) -> true;
-is_pure(erlang, is_float, 1) -> true;
-is_pure(erlang, is_function, 1) -> true;
-is_pure(erlang, is_integer, 1) -> true;
-is_pure(erlang, is_list, 1) -> true;
-is_pure(erlang, is_number, 1) -> true;
-is_pure(erlang, is_pid, 1) -> true;
-is_pure(erlang, is_port, 1) -> true;
-is_pure(erlang, is_record, 3) -> true;
-is_pure(erlang, is_reference, 1) -> true;
-is_pure(erlang, is_tuple, 1) -> true;
-is_pure(erlang, length, 1) -> true;
-is_pure(erlang, list_to_atom, 1) -> true;
-is_pure(erlang, list_to_binary, 1) -> true;
-is_pure(erlang, list_to_float, 1) -> true;
-is_pure(erlang, list_to_integer, 1) -> true;
-is_pure(erlang, list_to_pid, 1) -> true;
-is_pure(erlang, list_to_tuple, 1) -> true;
-is_pure(erlang, phash, 2) -> false;
-is_pure(erlang, pid_to_list, 1) -> true;
-is_pure(erlang, round, 1) -> true;
-is_pure(erlang, setelement, 3) -> true;
-is_pure(erlang, size, 1) -> true;
-is_pure(erlang, split_binary, 2) -> true;
-is_pure(erlang, term_to_binary, 1) -> true;
-is_pure(erlang, tl, 1) -> true;
-is_pure(erlang, trunc, 1) -> true;
-is_pure(erlang, tuple_to_list, 1) -> true;
-is_pure(lists, append, 2) -> true;
-is_pure(lists, subtract, 2) -> true;
-is_pure(math, acos, 1) -> true;
-is_pure(math, acosh, 1) -> true;
-is_pure(math, asin, 1) -> true;
-is_pure(math, asinh, 1) -> true;
-is_pure(math, atan, 1) -> true;
-is_pure(math, atan2, 2) -> true;
-is_pure(math, atanh, 1) -> true;
-is_pure(math, cos, 1) -> true;
-is_pure(math, cosh, 1) -> true;
-is_pure(math, erf, 1) -> true;
-is_pure(math, erfc, 1) -> true;
-is_pure(math, exp, 1) -> true;
-is_pure(math, log, 1) -> true;
-is_pure(math, log10, 1) -> true;
-is_pure(math, pow, 2) -> true;
-is_pure(math, sin, 1) -> true;
-is_pure(math, sinh, 1) -> true;
-is_pure(math, sqrt, 1) -> true;
-is_pure(math, tan, 1) -> true;
-is_pure(math, tanh, 1) -> true;
-is_pure(_, _, _) -> false.
-
-
-%% =====================================================================
-%% is_safe(Module, Name, Arity) -> boolean()
-%%
-%% Module = Name = atom()
-%% Arity = integer()
-%%
-%% Returns `true' if the function `Module:Name/Arity' is completely
-%% effect free, i.e., if its evaluation always completes normally
-%% and does not affect the state (although the value it returns
-%% might depend on the state).
-
-is_safe(erlang, '/=', 2) -> true;
-is_safe(erlang, '<', 2) -> true;
-is_safe(erlang, '=/=', 2) -> true;
-is_safe(erlang, '=:=', 2) -> true;
-is_safe(erlang, '=<', 2) -> true;
-is_safe(erlang, '==', 2) -> true;
-is_safe(erlang, '>', 2) -> true;
-is_safe(erlang, '>=', 2) -> true;
-is_safe(erlang, date, 0) -> true;
-is_safe(erlang, get, 0) -> true;
-is_safe(erlang, get, 1) -> true;
-is_safe(erlang, get_cookie, 0) -> true;
-is_safe(erlang, get_keys, 1) -> true;
-is_safe(erlang, group_leader, 0) -> true;
-is_safe(erlang, is_alive, 0) -> true;
-is_safe(erlang, is_atom, 1) -> true;
-is_safe(erlang, is_boolean, 1) -> true;
-is_safe(erlang, is_binary, 1) -> true;
-is_safe(erlang, is_constant, 1) -> true;
-is_safe(erlang, is_float, 1) -> true;
-is_safe(erlang, is_function, 1) -> true;
-is_safe(erlang, is_integer, 1) -> true;
-is_safe(erlang, is_list, 1) -> true;
-is_safe(erlang, is_number, 1) -> true;
-is_safe(erlang, is_pid, 1) -> true;
-is_safe(erlang, is_port, 1) -> true;
-is_safe(erlang, is_record, 3) -> true;
-is_safe(erlang, is_reference, 1) -> true;
-is_safe(erlang, is_tuple, 1) -> true;
-is_safe(erlang, make_ref, 0) -> true;
-is_safe(erlang, node, 0) -> true;
-is_safe(erlang, nodes, 0) -> true;
-is_safe(erlang, ports, 0) -> true;
-is_safe(erlang, pre_loaded, 0) -> true;
-is_safe(erlang, processes, 0) -> true;
-is_safe(erlang, registered, 0) -> true;
-is_safe(erlang, self, 0) -> true;
-is_safe(erlang, term_to_binary, 1) -> true;
-is_safe(erlang, time, 0) -> true;
-is_safe(_, _, _) -> false.
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/rec_env.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/rec_env.erl
deleted file mode 100644
index 0dd31b71ea..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/rec_env.erl
+++ /dev/null
@@ -1,611 +0,0 @@
-%% =====================================================================
-%% This library is free software; you can redistribute it and/or modify
-%% it under the terms of the GNU Lesser General Public License as
-%% published by the Free Software Foundation; either version 2 of the
-%% License, or (at your option) any later version.
-%%
-%% This library is distributed in the hope that it will be useful, but
-%% WITHOUT ANY WARRANTY; without even the implied warranty of
-%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-%% Lesser General Public License for more details.
-%%
-%% You should have received a copy of the GNU Lesser General Public
-%% License along with this library; if not, write to the Free Software
-%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-%% USA
-%%
-%% $Id: rec_env.erl,v 1.2 2009/09/17 09:46:19 kostis Exp $
-%%
-%% @author Richard Carlsson <[email protected]>
-%% @copyright 1999-2004 Richard Carlsson
-%% @doc Abstract environments, supporting self-referential bindings and
-%% automatic new-key generation.
-
-%% The current implementation is based on Erlang standard library
-%% dictionaries.
-
-%%% -define(DEBUG, true).
-
--module(rec_env).
-
--export([bind/3, bind_list/3, bind_recursive/4, delete/2, empty/0,
- get/2, is_defined/2, is_empty/1, keys/1, lookup/2, new_key/1,
- new_key/2, new_keys/2, new_keys/3, size/1, to_list/1]).
-
--ifdef(DEBUG).
--export([test/1, test_custom/1, test_custom/2]).
--endif.
-
--ifdef(DEBUG).
-%% Code for testing:
-%%@hidden
-test(N) ->
- test_0(integer, N).
-
-%%@hidden
-test_custom(N) ->
- F = fun (X) -> list_to_atom("X"++integer_to_list(X)) end,
- test_custom(F, N).
-
-%%@hidden
-test_custom(F, N) ->
- test_0({custom, F}, N).
-
-test_0(Type, N) ->
- put(new_key_calls, 0),
- put(new_key_retries, 0),
- put(new_key_max, 0),
- Env = test_1(Type, N, empty()),
- io:fwrite("\ncalls: ~w.\n", [get(new_key_calls)]),
- io:fwrite("\nretries: ~w.\n", [get(new_key_retries)]),
- io:fwrite("\nmax: ~w.\n", [get(new_key_max)]),
- dict:to_list(element(1,Env)).
-
-test_1(integer = Type, N, Env) when integer(N), N > 0 ->
- Key = new_key(Env),
- test_1(Type, N - 1, bind(Key, value, Env));
-test_1({custom, F} = Type, N, Env) when integer(N), N > 0 ->
- Key = new_key(F, Env),
- test_1(Type, N - 1, bind(Key, value, Env));
-test_1(_,0, Env) ->
- Env.
--endif.
-
-
-%% Representation:
-%%
-%% environment() = [Mapping]
-%%
-%% Mapping = {map, Dict} | {rec, Dict, Dict}
-%% Dict = dict:dictionary()
-%%
-%% An empty environment is a list containing a single `{map, Dict}'
-%% element - empty lists are not valid environments. To find a key in an
-%% environment, it is searched for in each mapping in the list, in
-%% order, until it the key is found in some mapping, or the end of the
-%% list is reached. In a 'rec' mapping, we keep the original dictionary
-%% together with a version where entries may have been deleted - this
-%% makes it possible to garbage collect the entire 'rec' mapping when
-%% all its entries are unused (for example, by being shadowed by later
-%% definitions).
-
-
-
-%% =====================================================================
-%% @type environment(). An abstract environment.
-
-
-%% =====================================================================
-%% @spec empty() -> environment()
-%%
-%% @doc Returns an empty environment.
-
-empty() ->
- [{map, dict:new()}].
-
-
-%% =====================================================================
-%% @spec is_empty(Env::environment()) -> boolean()
-%%
-%% @doc Returns <code>true</code> if the environment is empty, otherwise
-%% <code>false</code>.
-
-is_empty([{map, Dict} | Es]) ->
- N = dict:size(Dict),
- if N /= 0 -> false;
- Es == [] -> true;
- true -> is_empty(Es)
- end;
-is_empty([{rec, Dict, _} | Es]) ->
- N = dict:size(Dict),
- if N /= 0 -> false;
- Es == [] -> true;
- true -> is_empty(Es)
- end.
-
-
-%% =====================================================================
-%% @spec size(Env::environment()) -> integer()
-%%
-%% @doc Returns the number of entries in an environment.
-
-%% (The name 'size' cannot be used in local calls, since there exists a
-%% built-in function with the same name.)
-
-size(Env) ->
- env_size(Env).
-
-env_size([{map, Dict}]) ->
- dict:size(Dict);
-env_size([{map, Dict} | Env]) ->
- dict:size(Dict) + env_size(Env);
-env_size([{rec, Dict, _Dict0} | Env]) ->
- dict:size(Dict) + env_size(Env).
-
-
-%% =====================================================================
-%% @spec is_defined(Key, Env) -> boolean()
-%%
-%% Key = term()
-%% Env = environment()
-%%
-%% @doc Returns <code>true</code> if <code>Key</code> is bound in the
-%% environment, otherwise <code>false</code>.
-
-is_defined(Key, [{map, Dict} | Env]) ->
- case dict:is_key(Key, Dict) of
- true ->
- true;
- false when Env == [] ->
- false;
- false ->
- is_defined(Key, Env)
- end;
-is_defined(Key, [{rec, Dict, _Dict0} | Env]) ->
- case dict:is_key(Key, Dict) of
- true ->
- true;
- false ->
- is_defined(Key, Env)
- end.
-
-
-%% =====================================================================
-%% @spec keys(Env::environment()) -> [term()]
-%%
-%% @doc Returns the ordered list of all keys in the environment.
-
-keys(Env) ->
- lists:sort(keys(Env, [])).
-
-keys([{map, Dict}], S) ->
- dict:fetch_keys(Dict) ++ S;
-keys([{map, Dict} | Env], S) ->
- keys(Env, dict:fetch_keys(Dict) ++ S);
-keys([{rec, Dict, _Dict0} | Env], S) ->
- keys(Env, dict:fetch_keys(Dict) ++ S).
-
-
-%% =====================================================================
-%% @spec to_list(Env) -> [{Key, Value}]
-%%
-%% Env = environment()
-%% Key = term()
-%% Value = term()
-%%
-%% @doc Returns an ordered list of <code>{Key, Value}</code> pairs for
-%% all keys in <code>Env</code>. <code>Value</code> is the same as that
-%% returned by {@link get/2}.
-
-to_list(Env) ->
- lists:sort(to_list(Env, [])).
-
-to_list([{map, Dict}], S) ->
- dict:to_list(Dict) ++ S;
-to_list([{map, Dict} | Env], S) ->
- to_list(Env, dict:to_list(Dict) ++ S);
-to_list([{rec, Dict, _Dict0} | Env], S) ->
- to_list(Env, dict:to_list(Dict) ++ S).
-
-
-%% =====================================================================
-%% @spec bind(Key, Value, Env) -> environment()
-%%
-%% Key = term()
-%% Value = term()
-%% Env = environment()
-%%
-%% @doc Make a nonrecursive entry. This binds <code>Key</code> to
-%% <code>Value</code>. If the key already existed in the environment,
-%% the old entry is replaced.
-
-%% Note that deletion is done to free old bindings so they can be
-%% garbage collected.
-
-bind(Key, Value, [{map, Dict}]) ->
- [{map, dict:store(Key, Value, Dict)}];
-bind(Key, Value, [{map, Dict} | Env]) ->
- [{map, dict:store(Key, Value, Dict)} | delete_any(Key, Env)];
-bind(Key, Value, Env) ->
- [{map, dict:store(Key, Value, dict:new())} | delete_any(Key, Env)].
-
-
-%% =====================================================================
-%% @spec bind_list(Keys, Values, Env) -> environment()
-%%
-%% Keys = [term()]
-%% Values = [term()]
-%% Env = environment()
-%%
-%% @doc Make N nonrecursive entries. This binds each key in
-%% <code>Keys</code> to the corresponding value in
-%% <code>Values</code>. If some key already existed in the environment,
-%% the previous entry is replaced. If <code>Keys</code> does not have
-%% the same length as <code>Values</code>, an exception is generated.
-
-bind_list(Ks, Vs, [{map, Dict}]) ->
- [{map, store_list(Ks, Vs, Dict)}];
-bind_list(Ks, Vs, [{map, Dict} | Env]) ->
- [{map, store_list(Ks, Vs, Dict)} | delete_list(Ks, Env)];
-bind_list(Ks, Vs, Env) ->
- [{map, store_list(Ks, Vs, dict:new())} | delete_list(Ks, Env)].
-
-store_list([K | Ks], [V | Vs], Dict) ->
- store_list(Ks, Vs, dict:store(K, V, Dict));
-store_list([], _, Dict) ->
- Dict.
-
-delete_list([K | Ks], Env) ->
- delete_list(Ks, delete_any(K, Env));
-delete_list([], Env) ->
- Env.
-
-%% By not calling `delete' unless we have to, we avoid unnecessary
-%% rewriting of the data.
-
-delete_any(Key, Env) ->
- case is_defined(Key, Env) of
- true ->
- delete(Key, Env);
- false ->
- Env
- end.
-
-%% =====================================================================
-%% @spec delete(Key, Env) -> environment()
-%%
-%% Key = term()
-%% Env = environment()
-%%
-%% @doc Delete an entry. This removes <code>Key</code> from the
-%% environment.
-
-delete(Key, [{map, Dict} = E | Env]) ->
- case dict:is_key(Key, Dict) of
- true ->
- [{map, dict:erase(Key, Dict)} | Env];
- false ->
- delete_1(Key, Env, E)
- end;
-delete(Key, [{rec, Dict, Dict0} = E | Env]) ->
- case dict:is_key(Key, Dict) of
- true ->
- %% The Dict0 component must be preserved as it is until all
- %% keys in Dict have been deleted.
- Dict1 = dict:erase(Key, Dict),
- case dict:size(Dict1) of
- 0 ->
- Env; % the whole {rec,...} is now garbage
- _ ->
- [{rec, Dict1, Dict0} | Env]
- end;
- false ->
- [E | delete(Key, Env)]
- end.
-
-%% This is just like above, except we pass on the preceding 'map'
-%% mapping in the list to enable merging when removing 'rec' mappings.
-
-delete_1(Key, [{rec, Dict, Dict0} = E | Env], E1) ->
- case dict:is_key(Key, Dict) of
- true ->
- Dict1 = dict:erase(Key, Dict),
- case dict:size(Dict1) of
- 0 ->
- concat(E1, Env);
- _ ->
- [E1, {rec, Dict1, Dict0} | Env]
- end;
- false ->
- [E1, E | delete(Key, Env)]
- end.
-
-concat({map, D1}, [{map, D2} | Env]) ->
- [dict:merge(fun (_K, V1, _V2) -> V1 end, D1, D2) | Env];
-concat(E1, Env) ->
- [E1 | Env].
-
-
-%% =====================================================================
-%% @spec bind_recursive(Keys, Values, Fun, Env) -> NewEnv
-%%
-%% Keys = [term()]
-%% Values = [term()]
-%% Fun = (Value, Env) -> term()
-%% Env = environment()
-%% NewEnv = environment()
-%%
-%% @doc Make N recursive entries. This binds each key in
-%% <code>Keys</code> to the value of <code>Fun(Value, NewEnv)</code> for
-%% the corresponding <code>Value</code>. If <code>Keys</code> does not
-%% have the same length as <code>Values</code>, an exception is
-%% generated. If some key already existed in the environment, the old
-%% entry is replaced.
-%%
-%% <p>Note: the function <code>Fun</code> is evaluated each time one of
-%% the stored keys is looked up, but only then.</p>
-%%
-%% <p>Examples:
-%%<pre>
-%% NewEnv = bind_recursive([foo, bar], [1, 2],
-%% fun (V, E) -> V end,
-%% Env)</pre>
-%%
-%% This does nothing interesting; <code>get(foo, NewEnv)</code> yields
-%% <code>1</code> and <code>get(bar, NewEnv)</code> yields
-%% <code>2</code>, but there is more overhead than if the {@link
-%% bind_list/3} function had been used.
-%%
-%% <pre>
-%% NewEnv = bind_recursive([foo, bar], [1, 2],
-%% fun (V, E) -> {V, E} end,
-%% Env)</pre>
-%%
-%% Here, however, <code>get(foo, NewEnv)</code> will yield <code>{1,
-%% NewEnv}</code> and <code>get(bar, NewEnv)</code> will yield <code>{2,
-%% NewEnv}</code>, i.e., the environment <code>NewEnv</code> contains
-%% recursive bindings.</p>
-
-bind_recursive([], [], _, Env) ->
- Env;
-bind_recursive(Ks, Vs, F, Env) ->
- F1 = fun (V) ->
- fun (Dict) -> F(V, [{rec, Dict, Dict} | Env]) end
- end,
- Dict = bind_recursive_1(Ks, Vs, F1, dict:new()),
- [{rec, Dict, Dict} | Env].
-
-bind_recursive_1([K | Ks], [V | Vs], F, Dict) ->
- bind_recursive_1(Ks, Vs, F, dict:store(K, F(V), Dict));
-bind_recursive_1([], [], _, Dict) ->
- Dict.
-
-
-%% =====================================================================
-%% @spec lookup(Key, Env) -> error | {ok, Value}
-%%
-%% Key = term()
-%% Env = environment()
-%% Value = term()
-%%
-%% @doc Returns <code>{ok, Value}</code> if <code>Key</code> is bound to
-%% <code>Value</code> in <code>Env</code>, and <code>error</code>
-%% otherwise.
-
-lookup(Key, [{map, Dict} | Env]) ->
- case dict:find(Key, Dict) of
- {ok, _}=Value ->
- Value;
- error when Env == [] ->
- error;
- error ->
- lookup(Key, Env)
- end;
-lookup(Key, [{rec, Dict, Dict0} | Env]) ->
- case dict:find(Key, Dict) of
- {ok, F} ->
- {ok, F(Dict0)};
- error ->
- lookup(Key, Env)
- end.
-
-
-%% =====================================================================
-%% @spec get(Key, Env) -> Value
-%%
-%% Key = term()
-%% Env = environment()
-%% Value = term()
-%%
-%% @doc Returns the value that <code>Key</code> is bound to in
-%% <code>Env</code>. Throws <code>{undefined, Key}</code> if the key
-%% does not exist in <code>Env</code>.
-
-get(Key, Env) ->
- case lookup(Key, Env) of
- {ok, Value} -> Value;
- error -> throw({undefined, Key})
- end.
-
-
-%% =====================================================================
-%% The key-generating algorithm could possibly be further improved. The
-%% important thing to keep in mind is, that when we need a new key, we
-%% are generally in mid-traversal of a syntax tree, and existing names
-%% in the tree may be closely grouped and evenly distributed or even
-%% forming a compact range (often having been generated by a "gensym",
-%% or by this very algorithm itself). This means that if we generate an
-%% identifier whose value is too close to those already seen (i.e.,
-%% which are in the environment), it is very probable that we will
-%% shadow a not-yet-seen identifier further down in the tree, the result
-%% being that we induce another later renaming, and end up renaming most
-%% of the identifiers, completely contrary to our intention. We need to
-%% generate new identifiers in a way that avoids such systematic
-%% collisions.
-%%
-%% One way of getting a new key to try when the previous attempt failed
-%% is of course to e.g. add one to the last tried value. However, in
-%% general it's a bad idea to try adjacent identifiers: the percentage
-%% of retries will typically increase a lot, so you may lose big on the
-%% extra lookups while gaining only a little from the quicker
-%% computation.
-%%
-%% We want an initial range that is large enough for most typical cases.
-%% If we start with, say, a range of 10, we might quickly use up most of
-%% the values in the range 1-10 (or 1-100) for new top-level variables -
-%% but as we start traversing the syntax tree, it is quite likely that
-%% exactly those variables will be encountered again (this depends on
-%% how the names in the tree were created), and will then need to be
-%% renamed. If we instead begin with a larger range, it is less likely
-%% that any top-level names that we introduce will shadow names that we
-%% will find in the tree. Of course we cannot know how large is large
-%% enough: for any initial range, there is some syntax tree that uses
-%% all the values in that range, and thus any top-level names introduced
-%% will shadow names in the tree. The point is to avoid this happening
-%% all the time - a range of about 1000 seems enough for most programs.
-%%
-%% The following values have been shown to work well:
-
--define(MINIMUM_RANGE, 1000).
--define(START_RANGE_FACTOR, 50).
--define(MAX_RETRIES, 2). % retries before enlarging range
--define(ENLARGE_FACTOR, 10). % range enlargment factor
-
--ifdef(DEBUG).
-%% If you want to use these process dictionary counters, make sure to
-%% initialise them to zero before you call any of the key-generating
-%% functions.
-%%
-%% new_key_calls total number of calls
-%% new_key_retries failed key generation attempts
-%% new_key_max maximum generated integer value
-%%
--define(measure_calls(),
- put(new_key_calls, 1 + get(new_key_calls))).
--define(measure_max_key(N),
- case N > get(new_key_max) of
- true ->
- put(new_key_max, N);
- false ->
- ok
- end).
--define(measure_retries(N),
- put(new_key_retries, get(new_key_retries) + N)).
--else.
--define(measure_calls(), ok).
--define(measure_max_key(N), ok).
--define(measure_retries(N), ok).
--endif.
-
-
-%% =====================================================================
-%% @spec new_key(Env::environment()) -> integer()
-%%
-%% @doc Returns an integer which is not already used as key in the
-%% environment. New integers are generated using an algorithm which
-%% tries to keep the values randomly distributed within a reasonably
-%% small range relative to the number of entries in the environment.
-%%
-%% <p>This function uses the Erlang standard library module
-%% <code>random</code> to generate new keys.</p>
-%%
-%% <p>Note that only the new key is returned; the environment itself is
-%% not updated by this function.</p>
-
-new_key(Env) ->
- new_key(fun (X) -> X end, Env).
-
-
-%% =====================================================================
-%% @spec new_key(Function, Env) -> term()
-%%
-%% Function = (integer()) -> term()
-%% Env = environment()
-%%
-%% @doc Returns a term which is not already used as key in the
-%% environment. The term is generated by applying <code>Function</code>
-%% to an integer generated as in {@link new_key/1}.
-%%
-%% <p>Note that only the generated term is returned; the environment
-%% itself is not updated by this function.</p>
-
-new_key(F, Env) ->
- ?measure_calls(),
- R = start_range(Env),
-%%% io:fwrite("Start range: ~w.\n", [R]),
- new_key(R, F, Env).
-
-new_key(R, F, Env) ->
- new_key(generate(R, R), R, 0, F, Env).
-
-new_key(N, R, T, F, Env) when T < ?MAX_RETRIES ->
- A = F(N),
- case is_defined(A, Env) of
- true ->
-%%% io:fwrite("CLASH: ~w.\n", [A]),
- new_key(generate(N, R), R, T + 1, F, Env);
- false ->
- ?measure_max_key(N),
- ?measure_retries(T),
-%%% io:fwrite("New: ~w.\n", [N]),
- A
- end;
-new_key(N, R, _T, F, Env) ->
- %% Too many retries - enlarge the range and start over.
- ?measure_retries((_T + 1)),
- R1 = trunc(R * ?ENLARGE_FACTOR),
-%%% io:fwrite("**NEW RANGE**: ~w.\n", [R1]),
- new_key(generate(N, R1), R1, 0, F, Env).
-
-start_range(Env) ->
- max(env_size(Env) * ?START_RANGE_FACTOR, ?MINIMUM_RANGE).
-
-max(X, Y) when X > Y -> X;
-max(_, Y) -> Y.
-
-%% The previous key might or might not be used to compute the next key
-%% to be tried. It is currently not used.
-%%
-%% In order to avoid causing cascading renamings, it is important that
-%% this function does not generate values in order, but
-%% (pseudo-)randomly distributed over the range.
-
-generate(_N, Range) ->
- random:uniform(Range). % works well
-
-
-%% =====================================================================
-%% @spec new_keys(N, Env) -> [integer()]
-%%
-%% N = integer()
-%% Env = environment()
-%%
-%% @doc Returns a list of <code>N</code> distinct integers that are not
-%% already used as keys in the environment. See {@link new_key/1} for
-%% details.
-
-new_keys(N, Env) when integer(N) ->
- new_keys(N, fun (X) -> X end, Env).
-
-
-%% =====================================================================
-%% @spec new_keys(N, Function, Env) -> [term()]
-%%
-%% N = integer()
-%% Function = (integer()) -> term()
-%% Env = environment()
-%%
-%% @doc Returns a list of <code>N</code> distinct terms that are not
-%% already used as keys in the environment. See {@link new_key/3} for
-%% details.
-
-new_keys(N, F, Env) when integer(N) ->
- R = start_range(Env),
- new_keys(N, [], R, F, Env).
-
-new_keys(N, Ks, R, F, Env) when N > 0 ->
- Key = new_key(R, F, Env),
- Env1 = bind(Key, true, Env), % dummy binding
- new_keys(N - 1, [Key | Ks], R, F, Env1);
-new_keys(0, Ks, _, _, _) ->
- Ks.
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/sys_expand_pmod.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/sys_expand_pmod.erl
deleted file mode 100644
index c5052b0e51..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/sys_expand_pmod.erl
+++ /dev/null
@@ -1,425 +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: sys_expand_pmod.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
-%%
--module(sys_expand_pmod).
-
-%% Expand function definition forms of parameterized module. We assume
-%% all record definitions, imports, queries, etc., have been expanded
-%% away. Any calls on the form 'foo(...)' must be calls to local
-%% functions. Auto-generated functions (module_info,...) have not yet
-%% been added to the function definitions, but are listed in 'defined'
-%% and 'exports'. The 'new/N' function is neither added to the
-%% definitions nor to the 'exports'/'defines' lists yet.
-
--export([forms/4]).
-
--record(pmod, {parameters, exports, defined, predef}).
-
-%% TODO: more abstract handling of predefined/static functions.
-
-forms(Fs0, Ps, Es0, Ds0) ->
- PreDef = [{module_info,0},{module_info,1}],
- forms(Fs0, Ps, Es0, Ds0, PreDef).
-
-forms(Fs0, Ps, Es0, Ds0, PreDef) ->
- St0 = #pmod{parameters=Ps,exports=Es0,defined=Ds0, predef=PreDef},
- {Fs1, St1} = forms(Fs0, St0),
- Es1 = update_function_names(Es0, St1),
- Ds1 = update_function_names(Ds0, St1),
- Fs2 = update_forms(Fs1, St1),
- {Fs2,Es1,Ds1}.
-
-%% This is extremely simplistic for now; all functions get an extra
-%% parameter, whether they need it or not, except for static functions.
-
-update_function_names(Es, St) ->
- [update_function_name(E, St) || E <- Es].
-
-update_function_name(E={F,A}, St) ->
- case ordsets:is_element(E, St#pmod.predef) of
- true -> E;
- false -> {F, A + 1}
- end.
-
-update_forms([{function,L,N,A,Cs}|Fs],St) ->
- [{function,L,N,A+1,Cs}|update_forms(Fs,St)];
-update_forms([F|Fs],St) ->
- [F|update_forms(Fs,St)];
-update_forms([],_St) ->
- [].
-
-%% Process the program forms.
-
-forms([F0|Fs0],St0) ->
- {F1,St1} = form(F0,St0),
- {Fs1,St2} = forms(Fs0,St1),
- {[F1|Fs1],St2};
-forms([], St0) ->
- {[], St0}.
-
-%% Only function definitions are of interest here. State is not updated.
-form({function,Line,Name0,Arity0,Clauses0},St) ->
- {Name,Arity,Clauses} = function(Name0, Arity0, Clauses0, St),
- {{function,Line,Name,Arity,Clauses},St};
-%% Pass anything else through
-form(F,St) -> {F,St}.
-
-function(Name, Arity, Clauses0, St) ->
- Clauses1 = clauses(Clauses0,St),
- {Name,Arity,Clauses1}.
-
-clauses([C|Cs],St) ->
- {clause,L,H,G,B} = clause(C,St),
- T = {tuple,L,[{var,L,V} || V <- ['_'|St#pmod.parameters]]},
- [{clause,L,H++[{match,L,T,{var,L,'THIS'}}],G,B}|clauses(Cs,St)];
-clauses([],_St) -> [].
-
-clause({clause,Line,H0,G0,B0},St) ->
- H1 = head(H0,St),
- G1 = guard(G0,St),
- B1 = exprs(B0,St),
- {clause,Line,H1,G1,B1}.
-
-head(Ps,St) -> patterns(Ps,St).
-
-patterns([P0|Ps],St) ->
- P1 = pattern(P0,St),
- [P1|patterns(Ps,St)];
-patterns([],_St) -> [].
-
-string_to_conses([], _Line, Tail) ->
- Tail;
-string_to_conses([E|Rest], Line, Tail) ->
- {cons, Line, {integer, Line, E}, string_to_conses(Rest, Line, Tail)}.
-
-pattern({var,Line,V},_St) -> {var,Line,V};
-pattern({match,Line,L0,R0},St) ->
- L1 = pattern(L0,St),
- R1 = pattern(R0,St),
- {match,Line,L1,R1};
-pattern({integer,Line,I},_St) -> {integer,Line,I};
-pattern({char,Line,C},_St) -> {char,Line,C};
-pattern({float,Line,F},_St) -> {float,Line,F};
-pattern({atom,Line,A},_St) -> {atom,Line,A};
-pattern({string,Line,S},_St) -> {string,Line,S};
-pattern({nil,Line},_St) -> {nil,Line};
-pattern({cons,Line,H0,T0},St) ->
- H1 = pattern(H0,St),
- T1 = pattern(T0,St),
- {cons,Line,H1,T1};
-pattern({tuple,Line,Ps0},St) ->
- Ps1 = pattern_list(Ps0,St),
- {tuple,Line,Ps1};
-pattern({bin,Line,Fs},St) ->
- Fs2 = pattern_grp(Fs,St),
- {bin,Line,Fs2};
-pattern({op,_Line,'++',{nil,_},R},St) ->
- pattern(R,St);
-pattern({op,_Line,'++',{cons,Li,{char,C2,I},T},R},St) ->
- pattern({cons,Li,{char,C2,I},{op,Li,'++',T,R}},St);
-pattern({op,_Line,'++',{cons,Li,{integer,L2,I},T},R},St) ->
- pattern({cons,Li,{integer,L2,I},{op,Li,'++',T,R}},St);
-pattern({op,_Line,'++',{string,Li,L},R},St) ->
- pattern(string_to_conses(L, Li, R),St);
-pattern({op,Line,Op,A},_St) ->
- {op,Line,Op,A};
-pattern({op,Line,Op,L,R},_St) ->
- {op,Line,Op,L,R}.
-
-pattern_grp([{bin_element,L1,E1,S1,T1} | Fs],St) ->
- S2 = case S1 of
- default ->
- default;
- _ ->
- expr(S1,St)
- end,
- T2 = case T1 of
- default ->
- default;
- _ ->
- bit_types(T1)
- end,
- [{bin_element,L1,expr(E1,St),S2,T2} | pattern_grp(Fs,St)];
-pattern_grp([],_St) ->
- [].
-
-bit_types([]) ->
- [];
-bit_types([Atom | Rest]) when atom(Atom) ->
- [Atom | bit_types(Rest)];
-bit_types([{Atom, Integer} | Rest]) when atom(Atom), integer(Integer) ->
- [{Atom, Integer} | bit_types(Rest)].
-
-pattern_list([P0|Ps],St) ->
- P1 = pattern(P0,St),
- [P1|pattern_list(Ps,St)];
-pattern_list([],_St) -> [].
-
-guard([G0|Gs],St) when list(G0) ->
- [guard0(G0,St) | guard(Gs,St)];
-guard(L,St) ->
- guard0(L,St).
-
-guard0([G0|Gs],St) ->
- G1 = guard_test(G0,St),
- [G1|guard0(Gs,St)];
-guard0([],_St) -> [].
-
-guard_test(Expr={call,Line,{atom,La,F},As0},St) ->
- case erl_internal:type_test(F, length(As0)) of
- true ->
- As1 = gexpr_list(As0,St),
- {call,Line,{atom,La,F},As1};
- _ ->
- gexpr(Expr,St)
- end;
-guard_test(Any,St) ->
- gexpr(Any,St).
-
-gexpr({var,L,V},_St) ->
- {var,L,V};
-% %% alternative implementation of accessing module parameters
-% case index(V,St#pmod.parameters) of
-% N when N > 0 ->
-% {call,L,{remote,L,{atom,L,erlang},{atom,L,element}},
-% [{integer,L,N+1},{var,L,'THIS'}]};
-% _ ->
-% {var,L,V}
-% end;
-gexpr({integer,Line,I},_St) -> {integer,Line,I};
-gexpr({char,Line,C},_St) -> {char,Line,C};
-gexpr({float,Line,F},_St) -> {float,Line,F};
-gexpr({atom,Line,A},_St) -> {atom,Line,A};
-gexpr({string,Line,S},_St) -> {string,Line,S};
-gexpr({nil,Line},_St) -> {nil,Line};
-gexpr({cons,Line,H0,T0},St) ->
- H1 = gexpr(H0,St),
- T1 = gexpr(T0,St),
- {cons,Line,H1,T1};
-gexpr({tuple,Line,Es0},St) ->
- Es1 = gexpr_list(Es0,St),
- {tuple,Line,Es1};
-gexpr({call,Line,{atom,La,F},As0},St) ->
- case erl_internal:guard_bif(F, length(As0)) of
- true -> As1 = gexpr_list(As0,St),
- {call,Line,{atom,La,F},As1}
- end;
-% Pre-expansion generated calls to erlang:is_record/3 must also be handled
-gexpr({call,Line,{remote,La,{atom,Lb,erlang},{atom,Lc,is_record}},As0},St)
- when length(As0) == 3 ->
- As1 = gexpr_list(As0,St),
- {call,Line,{remote,La,{atom,Lb,erlang},{atom,Lc,is_record}},As1};
-% Guard bif's can be remote, but only in the module erlang...
-gexpr({call,Line,{remote,La,{atom,Lb,erlang},{atom,Lc,F}},As0},St) ->
- case erl_internal:guard_bif(F, length(As0)) or
- erl_internal:arith_op(F, length(As0)) or
- erl_internal:comp_op(F, length(As0)) or
- erl_internal:bool_op(F, length(As0)) of
- true -> As1 = gexpr_list(As0,St),
- {call,Line,{remote,La,{atom,Lb,erlang},{atom,Lc,F}},As1}
- end;
-% Unfortunately, writing calls as {M,F}(...) is also allowed.
-gexpr({call,Line,{tuple,La,[{atom,Lb,erlang},{atom,Lc,F}]},As0},St) ->
- case erl_internal:guard_bif(F, length(As0)) or
- erl_internal:arith_op(F, length(As0)) or
- erl_internal:comp_op(F, length(As0)) or
- erl_internal:bool_op(F, length(As0)) of
- true -> As1 = gexpr_list(As0,St),
- {call,Line,{tuple,La,[{atom,Lb,erlang},{atom,Lc,F}]},As1}
- end;
-gexpr({bin,Line,Fs},St) ->
- Fs2 = pattern_grp(Fs,St),
- {bin,Line,Fs2};
-gexpr({op,Line,Op,A0},St) ->
- case erl_internal:arith_op(Op, 1) or
- erl_internal:bool_op(Op, 1) of
- true -> A1 = gexpr(A0,St),
- {op,Line,Op,A1}
- end;
-gexpr({op,Line,Op,L0,R0},St) ->
- case erl_internal:arith_op(Op, 2) or
- erl_internal:bool_op(Op, 2) or
- erl_internal:comp_op(Op, 2) of
- true ->
- L1 = gexpr(L0,St),
- R1 = gexpr(R0,St),
- {op,Line,Op,L1,R1}
- end.
-
-gexpr_list([E0|Es],St) ->
- E1 = gexpr(E0,St),
- [E1|gexpr_list(Es,St)];
-gexpr_list([],_St) -> [].
-
-exprs([E0|Es],St) ->
- E1 = expr(E0,St),
- [E1|exprs(Es,St)];
-exprs([],_St) -> [].
-
-expr({var,L,V},_St) ->
- {var,L,V};
-% case index(V,St#pmod.parameters) of
-% N when N > 0 ->
-% {call,L,{remote,L,{atom,L,erlang},{atom,L,element}},
-% [{integer,L,N+1},{var,L,'THIS'}]};
-% _ ->
-% {var,L,V}
-% end;
-expr({integer,Line,I},_St) -> {integer,Line,I};
-expr({float,Line,F},_St) -> {float,Line,F};
-expr({atom,Line,A},_St) -> {atom,Line,A};
-expr({string,Line,S},_St) -> {string,Line,S};
-expr({char,Line,C},_St) -> {char,Line,C};
-expr({nil,Line},_St) -> {nil,Line};
-expr({cons,Line,H0,T0},St) ->
- H1 = expr(H0,St),
- T1 = expr(T0,St),
- {cons,Line,H1,T1};
-expr({lc,Line,E0,Qs0},St) ->
- Qs1 = lc_quals(Qs0,St),
- E1 = expr(E0,St),
- {lc,Line,E1,Qs1};
-expr({tuple,Line,Es0},St) ->
- Es1 = expr_list(Es0,St),
- {tuple,Line,Es1};
-expr({block,Line,Es0},St) ->
- Es1 = exprs(Es0,St),
- {block,Line,Es1};
-expr({'if',Line,Cs0},St) ->
- Cs1 = icr_clauses(Cs0,St),
- {'if',Line,Cs1};
-expr({'case',Line,E0,Cs0},St) ->
- E1 = expr(E0,St),
- Cs1 = icr_clauses(Cs0,St),
- {'case',Line,E1,Cs1};
-expr({'receive',Line,Cs0},St) ->
- Cs1 = icr_clauses(Cs0,St),
- {'receive',Line,Cs1};
-expr({'receive',Line,Cs0,To0,ToEs0},St) ->
- To1 = expr(To0,St),
- ToEs1 = exprs(ToEs0,St),
- Cs1 = icr_clauses(Cs0,St),
- {'receive',Line,Cs1,To1,ToEs1};
-expr({'try',Line,Es0,Scs0,Ccs0,As0},St) ->
- Es1 = exprs(Es0,St),
- Scs1 = icr_clauses(Scs0,St),
- Ccs1 = icr_clauses(Ccs0,St),
- As1 = exprs(As0,St),
- {'try',Line,Es1,Scs1,Ccs1,As1};
-expr({'fun',Line,Body,Info},St) ->
- case Body of
- {clauses,Cs0} ->
- Cs1 = fun_clauses(Cs0,St),
- {'fun',Line,{clauses,Cs1},Info};
- {function,F,A} ->
- {F1,A1} = update_function_name({F,A},St),
- if A1 == A ->
- {'fun',Line,{function,F,A},Info};
- true ->
- %% Must rewrite local fun-name to a fun that does a
- %% call with the extra THIS parameter.
- As = make_vars(A, Line),
- As1 = As ++ [{var,Line,'THIS'}],
- Call = {call,Line,{atom,Line,F1},As1},
- Cs = [{clause,Line,As,[],[Call]}],
- {'fun',Line,{clauses,Cs},Info}
- end;
- {function,M,F,A} -> %This is an error in lint!
- {'fun',Line,{function,M,F,A},Info}
- end;
-expr({call,Lc,{atom,_,new}=Name,As0},#pmod{parameters=Ps}=St)
- when length(As0) =:= length(Ps) ->
- %% The new() function does not take a 'THIS' argument (it's static).
- As1 = expr_list(As0,St),
- {call,Lc,Name,As1};
-expr({call,Lc,{atom,_,module_info}=Name,As0},St)
- when length(As0) == 0; length(As0) == 1 ->
- %% The module_info/0 and module_info/1 functions are also static.
- As1 = expr_list(As0,St),
- {call,Lc,Name,As1};
-expr({call,Lc,{atom,Lf,F},As0},St) ->
- %% Local function call - needs THIS parameter.
- As1 = expr_list(As0,St),
- {call,Lc,{atom,Lf,F},As1 ++ [{var,0,'THIS'}]};
-expr({call,Line,F0,As0},St) ->
- %% Other function call
- F1 = expr(F0,St),
- As1 = expr_list(As0,St),
- {call,Line,F1,As1};
-expr({'catch',Line,E0},St) ->
- E1 = expr(E0,St),
- {'catch',Line,E1};
-expr({match,Line,P0,E0},St) ->
- E1 = expr(E0,St),
- P1 = pattern(P0,St),
- {match,Line,P1,E1};
-expr({bin,Line,Fs},St) ->
- Fs2 = pattern_grp(Fs,St),
- {bin,Line,Fs2};
-expr({op,Line,Op,A0},St) ->
- A1 = expr(A0,St),
- {op,Line,Op,A1};
-expr({op,Line,Op,L0,R0},St) ->
- L1 = expr(L0,St),
- R1 = expr(R0,St),
- {op,Line,Op,L1,R1};
-%% The following are not allowed to occur anywhere!
-expr({remote,Line,M0,F0},St) ->
- M1 = expr(M0,St),
- F1 = expr(F0,St),
- {remote,Line,M1,F1}.
-
-expr_list([E0|Es],St) ->
- E1 = expr(E0,St),
- [E1|expr_list(Es,St)];
-expr_list([],_St) -> [].
-
-icr_clauses([C0|Cs],St) ->
- C1 = clause(C0,St),
- [C1|icr_clauses(Cs,St)];
-icr_clauses([],_St) -> [].
-
-lc_quals([{generate,Line,P0,E0}|Qs],St) ->
- E1 = expr(E0,St),
- P1 = pattern(P0,St),
- [{generate,Line,P1,E1}|lc_quals(Qs,St)];
-lc_quals([E0|Qs],St) ->
- E1 = expr(E0,St),
- [E1|lc_quals(Qs,St)];
-lc_quals([],_St) -> [].
-
-fun_clauses([C0|Cs],St) ->
- C1 = clause(C0,St),
- [C1|fun_clauses(Cs,St)];
-fun_clauses([],_St) -> [].
-
-% %% Return index from 1 upwards, or 0 if not in the list.
-%
-% index(X,Ys) -> index(X,Ys,1).
-%
-% index(X,[X|Ys],A) -> A;
-% index(X,[Y|Ys],A) -> index(X,Ys,A+1);
-% index(X,[],A) -> 0.
-
-make_vars(N, L) ->
- make_vars(1, N, L).
-
-make_vars(N, M, L) when N =< M ->
- V = list_to_atom("X"++integer_to_list(N)),
- [{var,L,V} | make_vars(N + 1, M, L)];
-make_vars(_, _, _) ->
- [].
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/sys_pre_attributes.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/sys_pre_attributes.erl
deleted file mode 100644
index 6e68611c66..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/sys_pre_attributes.erl
+++ /dev/null
@@ -1,212 +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: sys_pre_attributes.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
-%%
-%% Purpose : Transform Erlang compiler attributes
-
--module(sys_pre_attributes).
-
--export([parse_transform/2]).
-
--define(OPTION_TAG, attributes).
-
--record(state, {forms,
- pre_ops = [],
- post_ops = [],
- options}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Inserts, deletes and replaces Erlang compiler attributes.
-%%
-%% Valid options are:
-%%
-%% {attribute, insert, AttrName, NewAttrVal}
-%% {attribute, replace, AttrName, NewAttrVal} % replace first occurrence
-%% {attribute, delete, AttrName}
-%%
-%% The transformation is performed in two passes:
-%%
-%% pre_transform
-%% -------------
-%% Searches for attributes in the list of Forms in order to
-%% delete or replace them. 'delete' will delete all occurrences
-%% of attributes with the given name. 'replace' will replace the
-%% first occurrence of the attribute. This pass is will only be
-%% performed if there are replace or delete operations stated
-%% as options.
-%%
-%% post_transform
-%% -------------
-%% Looks up the module attribute and inserts the new attributes
-%% directly after. This pass will only be performed if there are
-%% any attributes left to be inserted after pre_transform. The left
-%% overs will be those replace operations that not has been performed
-%% due to that the pre_transform pass did not find the attribute plus
-%% all insert operations.
-
-parse_transform(Forms, Options) ->
- S = #state{forms = Forms, options = Options},
- S2 = init_transform(S),
- report_verbose("Pre options: ~p~n", [S2#state.pre_ops], S2),
- report_verbose("Post options: ~p~n", [S2#state.post_ops], S2),
- S3 = pre_transform(S2),
- S4 = post_transform(S3),
- S4#state.forms.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Computes the lists of pre_ops and post_ops that are
-%% used in the real transformation.
-init_transform(S) ->
- case S#state.options of
- Options when list(Options) ->
- init_transform(Options, S);
- Option ->
- init_transform([Option], S)
- end.
-
-init_transform([{attribute, insert, Name, Val} | Tail], S) ->
- Op = {insert, Name, Val},
- PostOps = [Op | S#state.post_ops],
- init_transform(Tail, S#state{post_ops = PostOps});
-init_transform([{attribute, replace, Name, Val} | Tail], S) ->
- Op = {replace, Name, Val},
- PreOps = [Op | S#state.pre_ops],
- PostOps = [Op | S#state.post_ops],
- init_transform(Tail, S#state{pre_ops = PreOps, post_ops = PostOps});
-init_transform([{attribute, delete, Name} | Tail], S) ->
- Op = {delete, Name},
- PreOps = [Op | S#state.pre_ops],
- init_transform(Tail, S#state{pre_ops = PreOps});
-init_transform([], S) ->
- S;
-init_transform([_ | T], S) ->
- init_transform(T, S);
-init_transform(BadOpt, S) ->
- report_error("Illegal option (ignored): ~p~n", [BadOpt], S),
- S.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Handle delete and perhaps replace
-
-pre_transform(S) when S#state.pre_ops == [] ->
- S;
-pre_transform(S) ->
- pre_transform(S#state.forms, [], S).
-
-pre_transform([H | T], Acc, S) ->
- case H of
- {attribute, Line, Name, Val} ->
- case lists:keysearch(Name, 2, S#state.pre_ops) of
- false ->
- pre_transform(T, [H | Acc], S);
-
- {value, {replace, Name, NewVal}} ->
- report_warning("Replace attribute ~p: ~p -> ~p~n",
- [Name, Val, NewVal],
- S),
- New = {attribute, Line, Name, NewVal},
- Pre = lists:keydelete(Name, 2, S#state.pre_ops),
- Post = lists:keydelete(Name, 2, S#state.post_ops),
- S2 = S#state{pre_ops = Pre, post_ops = Post},
- if
- Pre == [] ->
- %% No need to search the rest of the Forms
- Forms = lists:reverse(Acc, [New | T]),
- S2#state{forms = Forms};
- true ->
- pre_transform(T, [New | Acc], S2)
- end;
-
- {value, {delete, Name}} ->
- report_warning("Delete attribute ~p: ~p~n",
- [Name, Val],
- S),
- pre_transform(T, Acc, S)
- end;
- _Any ->
- pre_transform(T, [H | Acc], S)
- end;
-pre_transform([], Acc, S) ->
- S#state{forms = lists:reverse(Acc)}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Handle insert and perhaps replace
-
-post_transform(S) when S#state.post_ops == [] ->
- S;
-post_transform(S) ->
- post_transform(S#state.forms, [], S).
-
-post_transform([H | T], Acc, S) ->
- case H of
- {attribute, Line, module, Val} ->
- Acc2 = lists:reverse([{attribute, Line, module, Val} | Acc]),
- Forms = Acc2 ++ attrs(S#state.post_ops, Line, S) ++ T,
- S#state{forms = Forms, post_ops = []};
- _Any ->
- post_transform(T, [H | Acc], S)
- end;
-post_transform([], Acc, S) ->
- S#state{forms = lists:reverse(Acc)}.
-
-attrs([{replace, Name, NewVal} | T], Line, S) ->
- report_verbose("Insert attribute ~p: ~p~n", [Name, NewVal], S),
- [{attribute, Line, Name, NewVal} | attrs(T, Line, S)];
-attrs([{insert, Name, NewVal} | T], Line, S) ->
- report_verbose("Insert attribute ~p: ~p~n", [Name, NewVal], S),
- [{attribute, Line, Name, NewVal} | attrs(T, Line, S)];
-attrs([], _, _) ->
- [].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Report functions.
-%%
-%% Errors messages are controlled with the 'report_errors' compiler option
-%% Warning messages are controlled with the 'report_warnings' compiler option
-%% Verbose messages are controlled with the 'verbose' compiler option
-
-report_error(Format, Args, S) ->
- case is_error(S) of
- true ->
- io:format("~p: * ERROR * " ++ Format, [?MODULE | Args]);
- false ->
- ok
- end.
-
-report_warning(Format, Args, S) ->
- case is_warning(S) of
- true ->
- io:format("~p: * WARNING * " ++ Format, [?MODULE | Args]);
- false ->
- ok
- end.
-
-report_verbose(Format, Args, S) ->
- case is_verbose(S) of
- true ->
- io:format("~p: " ++ Format, [?MODULE | Args]);
- false ->
- ok
- end.
-
-is_error(S) ->
- lists:member(report_errors, S#state.options) or is_verbose(S).
-
-is_warning(S) ->
- lists:member(report_warnings, S#state.options) or is_verbose(S).
-
-is_verbose(S) ->
- lists:member(verbose, S#state.options).
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/sys_pre_expand.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/sys_pre_expand.erl
deleted file mode 100644
index 5e7c1c8bbd..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/sys_pre_expand.erl
+++ /dev/null
@@ -1,1026 +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: sys_pre_expand.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
-%%
-%% Purpose : Expand some source Erlang constructions. This is part of the
-%% pre-processing phase.
-
-%% N.B. Although structs (tagged tuples) are not yet allowed in the
-%% language there is code included in pattern/2 and expr/3 (commented out)
-%% that handles them by transforming them to tuples.
-
--module(sys_pre_expand).
-
-%% Main entry point.
--export([module/2]).
-
--import(ordsets, [from_list/1,add_element/2,
- union/1,union/2,intersection/1,intersection/2,subtract/2]).
--import(lists, [member/2,map/2,foldl/3,foldr/3,sort/1,reverse/1,duplicate/2]).
-
--include("../my_include/erl_bits.hrl").
-
--record(expand, {module=[], %Module name
- parameters=undefined, %Module parameters
- package="", %Module package
- exports=[], %Exports
- imports=[], %Imports
- mod_imports, %Module Imports
- compile=[], %Compile flags
- records=dict:new(), %Record definitions
- attributes=[], %Attributes
- defined=[], %Defined functions
- vcount=0, %Variable counter
- func=[], %Current function
- arity=[], %Arity for current function
- fcount=0, %Local fun count
- fun_index=0, %Global index for funs
- bitdefault,
- bittypes
- }).
-
-%% module(Forms, CompileOptions)
-%% {ModuleName,Exports,TransformedForms}
-%% Expand the forms in one module. N.B.: the lists of predefined
-%% exports and imports are really ordsets!
-
-module(Fs, Opts) ->
- %% Set pre-defined exported functions.
- PreExp = [{module_info,0},{module_info,1}],
-
- %% Set pre-defined module imports.
- PreModImp = [{erlang,erlang},{packages,packages}],
-
- %% Build initial expand record.
- St0 = #expand{exports=PreExp,
- mod_imports=dict:from_list(PreModImp),
- compile=Opts,
- defined=PreExp,
- bitdefault = erl_bits:system_bitdefault(),
- bittypes = erl_bits:system_bittypes()
- },
- %% Expand the functions.
- {Tfs,St1} = forms(Fs, foldl(fun define_function/2, St0, Fs)),
- {Efs,St2} = expand_pmod(Tfs, St1),
- %% Get the correct list of exported functions.
- Exports = case member(export_all, St2#expand.compile) of
- true -> St2#expand.defined;
- false -> St2#expand.exports
- end,
- %% Generate all functions from stored info.
- {Ats,St3} = module_attrs(St2#expand{exports = Exports}),
- {Mfs,St4} = module_predef_funcs(St3),
- {St4#expand.module, St4#expand.exports, Ats ++ Efs ++ Mfs,
- St4#expand.compile}.
-
-expand_pmod(Fs0, St) ->
- case St#expand.parameters of
- undefined ->
- {Fs0,St};
- Ps ->
- {Fs1,Xs,Ds} = sys_expand_pmod:forms(Fs0, Ps,
- St#expand.exports,
- St#expand.defined),
- A = length(Ps),
- Vs = [{var,0,V} || V <- Ps],
- N = {atom,0,St#expand.module},
- B = [{tuple,0,[N|Vs]}],
- F = {function,0,new,A,[{clause,0,Vs,[],B}]},
- As = St#expand.attributes,
- {[F|Fs1],St#expand{exports=add_element({new,A}, Xs),
- defined=add_element({new,A}, Ds),
- attributes = [{abstract, true} | As]}}
- end.
-
-%% -type define_function(Form, State) -> State.
-%% Add function to defined if form a function.
-
-define_function({function,_,N,A,_Cs}, St) ->
- St#expand{defined=add_element({N,A}, St#expand.defined)};
-define_function(_, St) -> St.
-
-module_attrs(St) ->
- {[{attribute,0,Name,Val} || {Name,Val} <- St#expand.attributes],St}.
-
-module_predef_funcs(St) ->
- PreDef = [{module_info,0},{module_info,1}],
- PreExp = PreDef,
- {[{function,0,module_info,0,
- [{clause,0,[],[],
- [{call,0,{remote,0,{atom,0,erlang},{atom,0,get_module_info}},
- [{atom,0,St#expand.module}]}]}]},
- {function,0,module_info,1,
- [{clause,0,[{var,0,'X'}],[],
- [{call,0,{remote,0,{atom,0,erlang},{atom,0,get_module_info}},
- [{atom,0,St#expand.module},{var,0,'X'}]}]}]}],
- St#expand{defined=union(from_list(PreDef), St#expand.defined),
- exports=union(from_list(PreExp), St#expand.exports)}}.
-
-%% forms(Forms, State) ->
-%% {TransformedForms,State'}
-%% Process the forms. Attributes are lost and just affect the state.
-%% Ignore uninteresting forms like eof and type.
-
-forms([{attribute,_,Name,Val}|Fs0], St0) ->
- St1 = attribute(Name, Val, St0),
- forms(Fs0, St1);
-forms([{function,L,N,A,Cs}|Fs0], St0) ->
- {Ff,St1} = function(L, N, A, Cs, St0),
- {Fs,St2} = forms(Fs0, St1),
- {[Ff|Fs],St2};
-forms([_|Fs], St) -> forms(Fs, St);
-forms([], St) -> {[],St}.
-
-%% -type attribute(Attribute, Value, State) ->
-%% State.
-%% Process an attribute, this just affects the state.
-
-attribute(module, {Module, As}, St) ->
- M = package_to_string(Module),
- St#expand{module=list_to_atom(M),
- package = packages:strip_last(M),
- parameters=As};
-attribute(module, Module, St) ->
- M = package_to_string(Module),
- St#expand{module=list_to_atom(M),
- package = packages:strip_last(M)};
-attribute(export, Es, St) ->
- St#expand{exports=union(from_list(Es), St#expand.exports)};
-attribute(import, Is, St) ->
- import(Is, St);
-attribute(compile, C, St) when list(C) ->
- St#expand{compile=St#expand.compile ++ C};
-attribute(compile, C, St) ->
- St#expand{compile=St#expand.compile ++ [C]};
-attribute(record, {Name,Defs}, St) ->
- St#expand{records=dict:store(Name, normalise_fields(Defs),
- St#expand.records)};
-attribute(file, _File, St) -> St; %This is ignored
-attribute(Name, Val, St) when list(Val) ->
- St#expand{attributes=St#expand.attributes ++ [{Name,Val}]};
-attribute(Name, Val, St) ->
- St#expand{attributes=St#expand.attributes ++ [{Name,[Val]}]}.
-
-function(L, N, A, Cs0, St0) ->
- {Cs,St} = clauses(Cs0, St0#expand{func=N,arity=A,fcount=0}),
- {{function,L,N,A,Cs},St}.
-
-%% -type clauses([Clause], State) ->
-%% {[TransformedClause],State}.
-%% Expand function clauses.
-
-clauses([{clause,Line,H0,G0,B0}|Cs0], St0) ->
- {H,Hvs,_Hus,St1} = head(H0, St0),
- {G,Gvs,_Gus,St2} = guard(G0, Hvs, St1),
- {B,_Bvs,_Bus,St3} = exprs(B0, union(Hvs, Gvs), St2),
- {Cs,St4} = clauses(Cs0, St3),
- {[{clause,Line,H,G,B}|Cs],St4};
-clauses([], St) -> {[],St}.
-
-%% head(HeadPatterns, State) ->
-%% {TransformedPatterns,Variables,UsedVariables,State'}
-
-head(As, St) -> pattern_list(As, St).
-
-%% pattern(Pattern, State) ->
-%% {TransformedPattern,Variables,UsedVariables,State'}
-%% BITS: added used variables for bit patterns with varaible length
-%%
-
-pattern({var,_,'_'}=Var, St) -> %Ignore anonymous variable.
- {Var,[],[],St};
-pattern({var,_,V}=Var, St) ->
- {Var,[V],[],St};
-pattern({char,_,_}=Char, St) ->
- {Char,[],[],St};
-pattern({integer,_,_}=Int, St) ->
- {Int,[],[],St};
-pattern({float,_,_}=Float, St) ->
- {Float,[],[],St};
-pattern({atom,_,_}=Atom, St) ->
- {Atom,[],[],St};
-pattern({string,_,_}=String, St) ->
- {String,[],[],St};
-pattern({nil,_}=Nil, St) ->
- {Nil,[],[],St};
-pattern({cons,Line,H,T}, St0) ->
- {TH,THvs,Hus,St1} = pattern(H, St0),
- {TT,TTvs,Tus,St2} = pattern(T, St1),
- {{cons,Line,TH,TT},union(THvs, TTvs),union(Hus,Tus),St2};
-pattern({tuple,Line,Ps}, St0) ->
- {TPs,TPsvs,Tus,St1} = pattern_list(Ps, St0),
- {{tuple,Line,TPs},TPsvs,Tus,St1};
-%%pattern({struct,Line,Tag,Ps}, St0) ->
-%% {TPs,TPsvs,St1} = pattern_list(Ps, St0),
-%% {{tuple,Line,[{atom,Line,Tag}|TPs]},TPsvs,St1};
-pattern({record_field,_,_,_}=M, St) ->
- {expand_package(M, St), [], [], St}; % must be a package name
-pattern({record_index,Line,Name,Field}, St) ->
- {index_expr(Line, Field, Name, record_fields(Name, St)),[],[],St};
-pattern({record,Line,Name,Pfs}, St0) ->
- Fs = record_fields(Name, St0),
- {TMs,TMsvs,Us,St1} = pattern_list(pattern_fields(Fs, Pfs), St0),
- {{tuple,Line,[{atom,Line,Name}|TMs]},TMsvs,Us,St1};
-pattern({bin,Line,Es0}, St0) ->
- {Es1,Esvs,Esus,St1} = pattern_bin(Es0, St0),
- {{bin,Line,Es1},Esvs,Esus,St1};
-pattern({op,_,'++',{nil,_},R}, St) ->
- pattern(R, St);
-pattern({op,_,'++',{cons,Li,H,T},R}, St) ->
- pattern({cons,Li,H,{op,Li,'++',T,R}}, St);
-pattern({op,_,'++',{string,Li,L},R}, St) ->
- pattern(string_to_conses(Li, L, R), St);
-pattern({match,Line,Pat1, Pat2}, St0) ->
- {TH,Hvt,Hus,St1} = pattern(Pat2, St0),
- {TT,Tvt,Tus,St2} = pattern(Pat1, St1),
- {{match,Line,TT,TH}, union(Hvt,Tvt), union(Hus,Tus), St2};
-%% Compile-time pattern expressions, including unary operators.
-pattern({op,Line,Op,A}, St) ->
- { erl_eval:partial_eval({op,Line,Op,A}), [], [], St};
-pattern({op,Line,Op,L,R}, St) ->
- { erl_eval:partial_eval({op,Line,Op,L,R}), [], [], St}.
-
-pattern_list([P0|Ps0], St0) ->
- {P,Pvs,Pus,St1} = pattern(P0, St0),
- {Ps,Psvs,Psus,St2} = pattern_list(Ps0, St1),
- {[P|Ps],union(Pvs, Psvs),union(Pus, Psus),St2};
-pattern_list([], St) -> {[],[],[],St}.
-
-%% guard(Guard, VisibleVariables, State) ->
-%% {TransformedGuard,NewVariables,UsedVariables,State'}
-%% Transform a list of guard tests. We KNOW that this has been checked
-%% and what the guards test are. Use expr for transforming the guard
-%% expressions.
-
-guard([G0|Gs0], Vs, St0) ->
- {G,Hvs,Hus,St1} = guard_tests(G0, Vs, St0),
- {Gs,Tvs,Tus,St2} = guard(Gs0, Vs, St1),
- {[G|Gs],union(Hvs, Tvs),union(Hus, Tus),St2};
-guard([], _, St) -> {[],[],[],St}.
-
-guard_tests([Gt0|Gts0], Vs, St0) ->
- {Gt1,Gvs,Gus,St1} = guard_test(Gt0, Vs, St0),
- {Gts1,Gsvs,Gsus,St2} = guard_tests(Gts0, union(Gvs, Vs), St1),
- {[Gt1|Gts1],union(Gvs, Gsvs),union(Gus, Gsus),St2};
-guard_tests([], _, St) -> {[],[],[],St}.
-
-guard_test({call,Line,{atom,_,record},[A,{atom,_,Name}]}, Vs, St) ->
- record_test_in_guard(Line, A, Name, Vs, St);
-guard_test({call,Line,{atom,Lt,Tname},As}, Vs, St) ->
- %% XXX This is ugly. We can remove this workaround if/when
- %% we'll allow 'andalso' in guards. For now, we must have
- %% different code in guards and in bodies.
- Test = {remote,Lt,
- {atom,Lt,erlang},
- {atom,Lt,normalise_test(Tname, length(As))}},
- put(sys_pre_expand_in_guard, yes),
- R = expr({call,Line,Test,As}, Vs, St),
- erase(sys_pre_expand_in_guard),
- R;
-guard_test(Test, Vs, St) ->
- %% XXX See the previous clause.
- put(sys_pre_expand_in_guard, yes),
- R = expr(Test, Vs, St),
- erase(sys_pre_expand_in_guard),
- R.
-
-%% record_test(Line, Term, Name, Vs, St) -> TransformedExpr
-%% Generate code for is_record/1.
-
-record_test(Line, Term, Name, Vs, St) ->
- case get(sys_pre_expand_in_guard) of
- undefined ->
- record_test_in_body(Line, Term, Name, Vs, St);
- yes ->
- record_test_in_guard(Line, Term, Name, Vs, St)
- end.
-
-record_test_in_guard(Line, Term, Name, Vs, St) ->
- %% Notes: (1) To keep is_record/3 properly atomic (e.g. when inverted
- %% using 'not'), we cannot convert it to an instruction
- %% sequence here. It must remain a single call.
- %% (2) Later passes assume that the last argument (the size)
- %% is a literal.
- %% (3) We don't want calls to erlang:is_record/3 (in the source code)
- %% confused we the internal instruction. (Reason: (2) above +
- %% code bloat.)
- %% (4) Xref may be run on the abstract code, so the name in the
- %% abstract code must be erlang:is_record/3.
- %% (5) To achive both (3) and (4) at the same time, set the name
- %% here to erlang:is_record/3, but mark it as compiler-generated.
- %% The v3_core pass will change the name to erlang:internal_is_record/3.
- Fs = record_fields(Name, St),
- expr({call,-Line,{remote,-Line,{atom,-Line,erlang},{atom,-Line,is_record}},
- [Term,{atom,Line,Name},{integer,Line,length(Fs)+1}]},
- Vs, St).
-
-record_test_in_body(Line, Expr, Name, Vs, St0) ->
- %% As Expr may have side effects, we must evaluate it
- %% first and bind the value to a new variable.
- %% We must use also handle the case that Expr does not
- %% evaluate to a tuple properly.
- Fs = record_fields(Name, St0),
- {Var,St} = new_var(Line, St0),
-
- expr({block,Line,
- [{match,Line,Var,Expr},
- {op,Line,
- 'andalso',
- {call,Line,{atom,Line,is_tuple},[Var]},
- {op,Line,'andalso',
- {op,Line,'=:=',
- {call,Line,{atom,Line,size},[Var]},
- {integer,Line,length(Fs)+1}},
- {op,Line,'=:=',
- {call,Line,{atom,Line,element},[{integer,Line,1},Var]},
- {atom,Line,Name}}}}]}, Vs, St).
-
-normalise_test(atom, 1) -> is_atom;
-normalise_test(binary, 1) -> is_binary;
-normalise_test(constant, 1) -> is_constant;
-normalise_test(float, 1) -> is_float;
-normalise_test(function, 1) -> is_function;
-normalise_test(integer, 1) -> is_integer;
-normalise_test(list, 1) -> is_list;
-normalise_test(number, 1) -> is_number;
-normalise_test(pid, 1) -> is_pid;
-normalise_test(port, 1) -> is_port;
-normalise_test(reference, 1) -> is_reference;
-normalise_test(tuple, 1) -> is_tuple;
-normalise_test(Name, _) -> Name.
-
-%% exprs(Expressions, VisibleVariables, State) ->
-%% {TransformedExprs,NewVariables,UsedVariables,State'}
-
-exprs([E0|Es0], Vs, St0) ->
- {E,Evs,Eus,St1} = expr(E0, Vs, St0),
- {Es,Esvs,Esus,St2} = exprs(Es0, union(Evs, Vs), St1),
- {[E|Es],union(Evs, Esvs),union(Eus, Esus),St2};
-exprs([], _, St) -> {[],[],[],St}.
-
-%% expr(Expression, VisibleVariables, State) ->
-%% {TransformedExpression,NewVariables,UsedVariables,State'}
-
-expr({var,_,V}=Var, _Vs, St) ->
- {Var,[],[V],St};
-expr({char,_,_}=Char, _Vs, St) ->
- {Char,[],[],St};
-expr({integer,_,_}=Int, _Vs, St) ->
- {Int,[],[],St};
-expr({float,_,_}=Float, _Vs, St) ->
- {Float,[],[],St};
-expr({atom,_,_}=Atom, _Vs, St) ->
- {Atom,[],[],St};
-expr({string,_,_}=String, _Vs, St) ->
- {String,[],[],St};
-expr({nil,_}=Nil, _Vs, St) ->
- {Nil,[],[],St};
-expr({cons,Line,H0,T0}, Vs, St0) ->
- {H,Hvs,Hus,St1} = expr(H0, Vs, St0),
- {T,Tvs,Tus,St2} = expr(T0, Vs, St1),
- {{cons,Line,H,T},union(Hvs, Tvs),union(Hus, Tus),St2};
-expr({lc,Line,E0,Qs0}, Vs, St0) ->
- {E1,Qs1,_,Lvs,Lus,St1} = lc_tq(Line, E0, Qs0, {nil,Line}, Vs, St0),
- {{lc,Line,E1,Qs1},Lvs,Lus,St1};
-expr({tuple,Line,Es0}, Vs, St0) ->
- {Es1,Esvs,Esus,St1} = expr_list(Es0, Vs, St0),
- {{tuple,Line,Es1},Esvs,Esus,St1};
-%%expr({struct,Line,Tag,Es0}, Vs, St0) ->
-%% {Es1,Esvs,Esus,St1} = expr_list(Es0, Vs, St0),
-%% {{tuple,Line,[{atom,Line,Tag}|Es1]},Esvs,Esus,St1};
-expr({record_field,_,_,_}=M, _Vs, St) ->
- {expand_package(M, St), [], [], St}; % must be a package name
-expr({record_index,Line,Name,F}, Vs, St) ->
- I = index_expr(Line, F, Name, record_fields(Name, St)),
- expr(I, Vs, St);
-expr({record,Line,Name,Is}, Vs, St) ->
- expr({tuple,Line,[{atom,Line,Name}|
- record_inits(record_fields(Name, St), Is)]},
- Vs, St);
-expr({record_field,Line,R,Name,F}, Vs, St) ->
- I = index_expr(Line, F, Name, record_fields(Name, St)),
- expr({call,Line,{atom,Line,element},[I,R]}, Vs, St);
-expr({record,_,R,Name,Us}, Vs, St0) ->
- {Ue,St1} = record_update(R, Name, record_fields(Name, St0), Us, St0),
- expr(Ue, Vs, St1);
-expr({bin,Line,Es0}, Vs, St0) ->
- {Es1,Esvs,Esus,St1} = expr_bin(Es0, Vs, St0),
- {{bin,Line,Es1},Esvs,Esus,St1};
-expr({block,Line,Es0}, Vs, St0) ->
- {Es,Esvs,Esus,St1} = exprs(Es0, Vs, St0),
- {{block,Line,Es},Esvs,Esus,St1};
-expr({'if',Line,Cs0}, Vs, St0) ->
- {Cs,Csvss,Csuss,St1} = icr_clauses(Cs0, Vs, St0),
- All = new_in_all(Vs, Csvss),
- {{'if',Line,Cs},All,union(Csuss),St1};
-expr({'case',Line,E0,Cs0}, Vs, St0) ->
- {E,Evs,Eus,St1} = expr(E0, Vs, St0),
- {Cs,Csvss,Csuss,St2} = icr_clauses(Cs0, union(Evs, Vs), St1),
- All = new_in_all(Vs, Csvss),
- {{'case',Line,E,Cs},union(Evs, All),union([Eus|Csuss]),St2};
-expr({'cond',Line,Cs}, Vs, St0) ->
- {V,St1} = new_var(Line,St0),
- expr(cond_clauses(Cs,V), Vs, St1);
-expr({'receive',Line,Cs0}, Vs, St0) ->
- {Cs,Csvss,Csuss,St1} = icr_clauses(Cs0, Vs, St0),
- All = new_in_all(Vs, Csvss),
- {{'receive',Line,Cs},All,union(Csuss),St1};
-expr({'receive',Line,Cs0,To0,ToEs0}, Vs, St0) ->
- {To,Tovs,Tous,St1} = expr(To0, Vs, St0),
- {ToEs,ToEsvs,_ToEsus,St2} = exprs(ToEs0, Vs, St1),
- {Cs,Csvss,Csuss,St3} = icr_clauses(Cs0, Vs, St2),
- All = new_in_all(Vs, [ToEsvs|Csvss]),
- {{'receive',Line,Cs,To,ToEs},union(Tovs, All),union([Tous|Csuss]),St3};
-expr({'fun',Line,Body}, Vs, St) ->
- fun_tq(Line, Body, Vs, St);
-%%% expr({call,_,{atom,La,this_module},[]}, _Vs, St) ->
-%%% {{atom,La,St#expand.module}, [], [], St};
-%%% expr({call,_,{atom,La,this_package},[]}, _Vs, St) ->
-%%% {{atom,La,list_to_atom(St#expand.package)}, [], [], St};
-%%% expr({call,_,{atom,La,this_package},[{atom,_,Name}]}, _Vs, St) ->
-%%% M = packages:concat(St#expand.package,Name),
-%%% {{atom,La,list_to_atom(M)}, [], [], St};
-%%% expr({call,Line,{atom,La,this_package},[A]}, Vs, St) ->
-%%% M = {call,Line,{remote,La,{atom,La,packages},{atom,La,concat}},
-%%% [{string,La,St#expand.package}, A]},
-%%% expr({call,Line,{atom,Line,list_to_atom},[M]}, Vs, St);
-expr({call,Line,{atom,_,is_record},[A,{atom,_,Name}]}, Vs, St) ->
- record_test(Line, A, Name, Vs, St);
-expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,is_record}},
- [A,{atom,_,Name}]}, Vs, St) ->
- record_test(Line, A, Name, Vs, St);
-expr({call,Line,{atom,La,N},As0}, Vs, St0) ->
- {As,Asvs,Asus,St1} = expr_list(As0, Vs, St0),
- Ar = length(As),
- case erl_internal:bif(N, Ar) of
- true ->
- {{call,Line,{remote,La,{atom,La,erlang},{atom,La,N}},As},
- Asvs,Asus,St1};
- false ->
- case imported(N, Ar, St1) of
- {yes,Mod} ->
- {{call,Line,{remote,La,{atom,La,Mod},{atom,La,N}},As},
- Asvs,Asus,St1};
- no ->
- case {N,Ar} of
- {record_info,2} ->
- record_info_call(Line, As, St1);
- _ ->
- {{call,Line,{atom,La,N},As},Asvs,Asus,St1}
- end
- end
- end;
-expr({call,Line,{record_field,_,_,_}=M,As0}, Vs, St0) ->
- expr({call,Line,expand_package(M, St0),As0}, Vs, St0);
-expr({call,Line,{remote,Lr,M,F},As0}, Vs, St0) ->
- M1 = expand_package(M, St0),
- {[M2,F1|As1],Asvs,Asus,St1} = expr_list([M1,F|As0], Vs, St0),
- {{call,Line,{remote,Lr,M2,F1},As1},Asvs,Asus,St1};
-expr({call,Line,{tuple,_,[{atom,_,_}=M,{atom,_,_}=F]},As}, Vs, St) ->
- %% Rewrite {Mod,Function}(Args...) to Mod:Function(Args...).
- expr({call,Line,{remote,Line,M,F},As}, Vs, St);
-expr({call,Line,F,As0}, Vs, St0) ->
- {[Fun1|As1],Asvs,Asus,St1} = expr_list([F|As0], Vs, St0),
- {{call,Line,Fun1,As1},Asvs,Asus,St1};
-expr({'try',Line,Es0,Scs0,Ccs0,As0}, Vs, St0) ->
- {Es1,Esvs,Esus,St1} = exprs(Es0, Vs, St0),
- Cvs = union(Esvs, Vs),
- {Scs1,Scsvss,Scsuss,St2} = icr_clauses(Scs0, Cvs, St1),
- {Ccs1,Ccsvss,Ccsuss,St3} = icr_clauses(Ccs0, Cvs, St2),
- Csvss = Scsvss ++ Ccsvss,
- Csuss = Scsuss ++ Ccsuss,
- All = new_in_all(Vs, Csvss),
- {As1,Asvs,Asus,St4} = exprs(As0, Cvs, St3),
- {{'try',Line,Es1,Scs1,Ccs1,As1}, union([Asvs,Esvs,All]),
- union([Esus,Asus|Csuss]), St4};
-expr({'catch',Line,E0}, Vs, St0) ->
- %% Catch exports no new variables.
- {E,_Evs,Eus,St1} = expr(E0, Vs, St0),
- {{'catch',Line,E},[],Eus,St1};
-expr({match,Line,P0,E0}, Vs, St0) ->
- {E,Evs,Eus,St1} = expr(E0, Vs, St0),
- {P,Pvs,Pus,St2} = pattern(P0, St1),
- {{match,Line,P,E},
- union(subtract(Pvs, Vs), Evs),
- union(intersection(Pvs, Vs), union(Eus,Pus)),St2};
-expr({op,L,'andalso',E1,E2}, Vs, St0) ->
- {V,St1} = new_var(L,St0),
- E = make_bool_switch(L,E1,V,
- make_bool_switch(L,E2,V,{atom,L,true},
- {atom,L,false}),
- {atom,L,false}),
- expr(E, Vs, St1);
-expr({op,L,'orelse',E1,E2}, Vs, St0) ->
- {V,St1} = new_var(L,St0),
- E = make_bool_switch(L,E1,V,{atom,L,true},
- make_bool_switch(L,E2,V,{atom,L,true},
- {atom,L,false})),
- expr(E, Vs, St1);
-expr({op,Line,'++',{lc,Ll,E0,Qs0},M0}, Vs, St0) ->
- {E1,Qs1,M1,Lvs,Lus,St1} = lc_tq(Ll, E0, Qs0, M0, Vs, St0),
- {{op,Line,'++',{lc,Ll,E1,Qs1},M1},Lvs,Lus,St1};
-expr({op,_,'++',{string,L1,S1},{string,_,S2}}, _Vs, St) ->
- {{string,L1,S1 ++ S2},[],[],St};
-expr({op,Ll,'++',{string,L1,S1}=Str,R0}, Vs, St0) ->
- {R1,Rvs,Rus,St1} = expr(R0, Vs, St0),
- E = case R1 of
- {string,_,S2} -> {string,L1,S1 ++ S2};
- _Other when length(S1) < 8 -> string_to_conses(L1, S1, R1);
- _Other -> {op,Ll,'++',Str,R1}
- end,
- {E,Rvs,Rus,St1};
-expr({op,Ll,'++',{cons,Lc,H,T},L2}, Vs, St) ->
- expr({cons,Ll,H,{op,Lc,'++',T,L2}}, Vs, St);
-expr({op,_,'++',{nil,_},L2}, Vs, St) ->
- expr(L2, Vs, St);
-expr({op,Line,Op,A0}, Vs, St0) ->
- {A,Avs,Aus,St1} = expr(A0, Vs, St0),
- {{op,Line,Op,A},Avs,Aus,St1};
-expr({op,Line,Op,L0,R0}, Vs, St0) ->
- {L,Lvs,Lus,St1} = expr(L0, Vs, St0),
- {R,Rvs,Rus,St2} = expr(R0, Vs, St1),
- {{op,Line,Op,L,R},union(Lvs, Rvs),union(Lus, Rus),St2}.
-
-expr_list([E0|Es0], Vs, St0) ->
- {E,Evs,Eus,St1} = expr(E0, Vs, St0),
- {Es,Esvs,Esus,St2} = expr_list(Es0, Vs, St1),
- {[E|Es],union(Evs, Esvs),union(Eus, Esus),St2};
-expr_list([], _, St) ->
- {[],[],[],St}.
-
-%% icr_clauses([Clause], [VisibleVariable], State) ->
-%% {[TransformedClause],[[NewVariable]],[[UsedVariable]],State'}
-%% Be very careful here to return the variables that are really used
-%% and really new.
-
-icr_clauses([], _, St) ->
- {[],[[]],[],St};
-icr_clauses(Clauses, Vs, St) ->
- icr_clauses2(Clauses, Vs, St).
-
-icr_clauses2([{clause,Line,H0,G0,B0}|Cs0], Vs, St0) ->
- {H,Hvs,Hus,St1} = head(H0, St0), %Hvs is really used!
- {G,Gvs,Gus,St2} = guard(G0, union(Hvs, Vs), St1),
- {B,Bvs,Bus,St3} = exprs(B0, union([Vs,Hvs,Gvs]), St2),
- New = subtract(union([Hvs,Gvs,Bvs]), Vs), %Really new
- Used = intersection(union([Hvs,Hus,Gus,Bus]), Vs), %Really used
- {Cs,Csvs,Csus,St4} = icr_clauses2(Cs0, Vs, St3),
- {[{clause,Line,H,G,B}|Cs],[New|Csvs],[Used|Csus],St4};
-icr_clauses2([], _, St) ->
- {[],[],[],St}.
-
-%% lc_tq(Line, Expr, Qualifiers, More, [VisibleVar], State) ->
-%% {TransExpr,[TransQual],TransMore,[NewVar],[UsedVar],State'}
-
-lc_tq(Line, E0, [{generate,Lg,P0,G0}|Qs0], M0, Vs, St0) ->
- {G1,Gvs,Gus,St1} = expr(G0, Vs, St0),
- {P1,Pvs,Pus,St2} = pattern(P0, St1),
- {E1,Qs1,M1,Lvs,Lus,St3} = lc_tq(Line, E0, Qs0, M0, union(Pvs, Vs), St2),
- {E1,[{generate,Lg,P1,G1}|Qs1],M1,
- union(Gvs, Lvs),union([Gus,Pus,Lus]),St3};
-lc_tq(Line, E0, [F0|Qs0], M0, Vs, St0) ->
- %% Allow record/2 and expand out as guard test.
- case erl_lint:is_guard_test(F0) of
- true ->
- {F1,Fvs,_Fus,St1} = guard_tests([F0], Vs, St0),
- {E1,Qs1,M1,Lvs,Lus,St2} = lc_tq(Line, E0, Qs0, M0, union(Fvs, Vs), St1),
- {E1,F1++Qs1,M1,Lvs,Lus,St2};
- false ->
- {F1,Fvs,_Fus,St1} = expr(F0, Vs, St0),
- {E1,Qs1,M1,Lvs,Lus,St2} = lc_tq(Line, E0, Qs0, M0, union(Fvs, Vs), St1),
- {E1,[F1|Qs1],M1,Lvs,Lus,St2}
- end;
-lc_tq(_Line, E0, [], M0, Vs, St0) ->
- {E1,Evs,Eus,St1} = expr(E0, Vs, St0),
- {M1,Mvs,Mus,St2} = expr(M0, Vs, St1),
- {E1,[],M1,union(Evs, Mvs),union(Eus, Mus),St2}.
-
-%% fun_tq(Line, Body, VisibleVariables, State) ->
-%% {Fun,NewVariables,UsedVariables,State'}
-%% Transform an "explicit" fun {'fun', Line, {clauses, Cs}} into an
-%% extended form {'fun', Line, {clauses, Cs}, Info}, unless it is the
-%% name of a BIF (erl_lint has checked that it is not an import).
-%% Process the body sequence directly to get the new and used variables.
-%% "Implicit" funs {'fun', Line, {function, F, A}} are not changed.
-
-fun_tq(Lf, {function,F,A}, Vs, St0) ->
- {As,St1} = new_vars(A, Lf, St0),
- Cs = [{clause,Lf,As,[],[{call,Lf,{atom,Lf,F},As}]}],
- case erl_internal:bif(F, A) of
- true ->
- fun_tq(Lf, {clauses,Cs}, Vs, St1);
- false ->
- Index = St0#expand.fun_index,
- Uniq = erlang:hash(Cs, (1 bsl 27)-1),
- {Fname,St2} = new_fun_name(St1),
- {{'fun',Lf,{function,F,A},{Index,Uniq,Fname}},[],[],
- St2#expand{fun_index=Index+1}}
- end;
-fun_tq(Lf, {clauses,Cs0}, Vs, St0) ->
- Uniq = erlang:hash(Cs0, (1 bsl 27)-1),
- {Cs1,_Hvss,Frees,St1} = fun_clauses(Cs0, Vs, St0),
- Ufrees = union(Frees),
- Index = St1#expand.fun_index,
- {Fname,St2} = new_fun_name(St1),
- {{'fun',Lf,{clauses,Cs1},{Index,Uniq,Fname}},[],Ufrees,
- St2#expand{fun_index=Index+1}}.
-
-fun_clauses([{clause,L,H0,G0,B0}|Cs0], Vs, St0) ->
- {H,Hvs,Hus,St1} = head(H0, St0),
- {G,Gvs,Gus,St2} = guard(G0, union(Hvs, Vs), St1),
- {B,Bvs,Bus,St3} = exprs(B0, union([Vs,Hvs,Gvs]), St2),
- %% Free variables cannot be new anywhere in the clause.
- Free = subtract(union([Gus,Hus,Bus]), union([Hvs,Gvs,Bvs])),
- %%io:format(" Gus :~p~n Bvs :~p~n Bus :~p~n Free:~p~n" ,[Gus,Bvs,Bus,Free]),
- {Cs,Hvss,Frees,St4} = fun_clauses(Cs0, Vs, St3),
- {[{clause,L,H,G,B}|Cs],[Hvs|Hvss],[Free|Frees],St4};
-fun_clauses([], _, St) -> {[],[],[],St}.
-
-%% new_fun_name(State) -> {FunName,State}.
-
-new_fun_name(#expand{func=F,arity=A,fcount=I}=St) ->
- Name = "-" ++ atom_to_list(F) ++ "/" ++ integer_to_list(A)
- ++ "-fun-" ++ integer_to_list(I) ++ "-",
- {list_to_atom(Name),St#expand{fcount=I+1}}.
-
-
-%% normalise_fields([RecDef]) -> [Field].
-%% Normalise the field definitions to always have a default value. If
-%% none has been given then use 'undefined'.
-
-normalise_fields(Fs) ->
- map(fun ({record_field,Lf,Field}) ->
- {record_field,Lf,Field,{atom,Lf,undefined}};
- (F) -> F end, Fs).
-
-%% record_fields(RecordName, State)
-%% find_field(FieldName, Fields)
-
-record_fields(R, St) -> dict:fetch(R, St#expand.records).
-
-find_field(F, [{record_field,_,{atom,_,F},Val}|_]) -> {ok,Val};
-find_field(F, [_|Fs]) -> find_field(F, Fs);
-find_field(_, []) -> error.
-
-%% field_names(RecFields) -> [Name].
-%% Return a list of the field names structures.
-
-field_names(Fs) ->
- map(fun ({record_field,_,Field,_Val}) -> Field end, Fs).
-
-%% index_expr(Line, FieldExpr, Name, Fields) -> IndexExpr.
-%% Return an expression which evaluates to the index of a
-%% field. Currently only handle the case where the field is an
-%% atom. This expansion must be passed through expr again.
-
-index_expr(Line, {atom,_,F}, _Name, Fs) ->
- {integer,Line,index_expr(F, Fs, 2)}.
-
-index_expr(F, [{record_field,_,{atom,_,F},_}|_], I) -> I;
-index_expr(F, [_|Fs], I) ->
- index_expr(F, Fs, I+1).
-
-%% pattern_fields([RecDefField], [Match]) -> [Pattern].
-%% Build a list of match patterns for the record tuple elements.
-%% This expansion must be passed through pattern again. N.B. We are
-%% scanning the record definition field list!
-
-pattern_fields(Fs, Ms) ->
- Wildcard = record_wildcard_init(Ms),
- map(fun ({record_field,L,{atom,_,F},_}) ->
- case find_field(F, Ms) of
- {ok,Match} -> Match;
- error when Wildcard =:= none -> {var,L,'_'};
- error -> Wildcard
- end end,
- Fs).
-
-%% record_inits([RecDefField], [Init]) -> [InitExpr].
-%% Build a list of initialisation expressions for the record tuple
-%% elements. This expansion must be passed through expr
-%% again. N.B. We are scanning the record definition field list!
-
-record_inits(Fs, Is) ->
- WildcardInit = record_wildcard_init(Is),
- map(fun ({record_field,_,{atom,_,F},D}) ->
- case find_field(F, Is) of
- {ok,Init} -> Init;
- error when WildcardInit =:= none -> D;
- error -> WildcardInit
- end end,
- Fs).
-
-record_wildcard_init([{record_field,_,{var,_,'_'},D}|_]) -> D;
-record_wildcard_init([_|Is]) -> record_wildcard_init(Is);
-record_wildcard_init([]) -> none.
-
-%% record_update(Record, RecordName, [RecDefField], [Update], State) ->
-%% {Expr,State'}
-%% Build an expression to update fields in a record returning a new
-%% record. Try to be smart and optimise this. This expansion must be
-%% passed through expr again.
-
-record_update(R, Name, Fs, Us0, St0) ->
- Line = element(2, R),
- {Pre,Us,St1} = record_exprs(Us0, St0),
- Nf = length(Fs), %# of record fields
- Nu = length(Us), %# of update fields
- Nc = Nf - Nu, %# of copy fields
-
- %% We need a new variable for the record expression
- %% to guarantee that it is only evaluated once.
- {Var,St2} = new_var(Line, St1),
-
- %% Try to be intelligent about which method of updating record to use.
- {Update,St} =
- if
- Nu == 0 -> {R,St2}; %No fields updated
- Nu =< Nc -> %Few fields updated
- {record_setel(Var, Name, Fs, Us), St2};
- true -> %The wide area inbetween
- record_match(Var, Name, Fs, Us, St2)
- end,
- {{block,element(2, R),Pre ++ [{match,Line,Var,R},Update]},St}.
-
-%% record_match(Record, RecordName, [RecDefField], [Update], State)
-%% Build a 'case' expression to modify record fields.
-
-record_match(R, Name, Fs, Us, St0) ->
- {Ps,News,St1} = record_upd_fs(Fs, Us, St0),
- Lr = element(2, hd(Us)),
- {{'case',Lr,R,
- [{clause,Lr,[{tuple,Lr,[{atom,Lr,Name}|Ps]}],[],
- [{tuple,Lr,[{atom,Lr,Name}|News]}]},
- {clause,Lr,[{var,Lr,'_'}],[],
- [call_error(Lr, {tuple,Lr,[{atom,Lr,badrecord},{atom,Lr,Name}]})]}
- ]},
- St1}.
-
-record_upd_fs([{record_field,Lf,{atom,_La,F},_Val}|Fs], Us, St0) ->
- {P,St1} = new_var(Lf, St0),
- {Ps,News,St2} = record_upd_fs(Fs, Us, St1),
- case find_field(F, Us) of
- {ok,New} -> {[P|Ps],[New|News],St2};
- error -> {[P|Ps],[P|News],St2}
- end;
-record_upd_fs([], _, St) -> {[],[],St}.
-
-%% record_setel(Record, RecordName, [RecDefField], [Update])
-%% Build a nested chain of setelement calls to build the
-%% updated record tuple.
-
-record_setel(R, Name, Fs, Us0) ->
- Us1 = foldl(fun ({record_field,Lf,Field,Val}, Acc) ->
- I = index_expr(Lf, Field, Name, Fs),
- [{I,Lf,Val}|Acc]
- end, [], Us0),
- Us = sort(Us1),
- Lr = element(2, hd(Us)),
- Wildcards = duplicate(length(Fs), {var,Lr,'_'}),
- {'case',Lr,R,
- [{clause,Lr,[{tuple,Lr,[{atom,Lr,Name}|Wildcards]}],[],
- [foldr(fun ({I,Lf,Val}, Acc) ->
- {call,Lf,{atom,Lf,setelement},[I,Acc,Val]} end,
- R, Us)]},
- {clause,Lr,[{var,Lr,'_'}],[],
- [call_error(Lr, {tuple,Lr,[{atom,Lr,badrecord},{atom,Lr,Name}]})]}]}.
-
-%% Expand a call to record_info/2. We have checked that it is not
-%% shadowed by an import.
-
-record_info_call(Line, [{atom,_Li,Info},{atom,_Ln,Name}], St) ->
- case Info of
- size ->
- {{integer,Line,1+length(record_fields(Name, St))},[],[],St};
- fields ->
- {make_list(field_names(record_fields(Name, St)), Line),
- [],[],St}
- end.
-
-%% Break out expressions from an record update list and bind to new
-%% variables. The idea is that we will evaluate all update expressions
-%% before starting to update the record.
-
-record_exprs(Us, St) ->
- record_exprs(Us, St, [], []).
-
-record_exprs([{record_field,Lf,{atom,_La,_F}=Name,Val}=Field0|Us], St0, Pre, Fs) ->
- case is_simple_val(Val) of
- true ->
- record_exprs(Us, St0, Pre, [Field0|Fs]);
- false ->
- {Var,St} = new_var(Lf, St0),
- Bind = {match,Lf,Var,Val},
- Field = {record_field,Lf,Name,Var},
- record_exprs(Us, St, [Bind|Pre], [Field|Fs])
- end;
-record_exprs([], St, Pre, Fs) ->
- {reverse(Pre),Fs,St}.
-
-is_simple_val({var,_,_}) -> true;
-is_simple_val({atom,_,_}) -> true;
-is_simple_val({integer,_,_}) -> true;
-is_simple_val({float,_,_}) -> true;
-is_simple_val({nil,_}) -> true;
-is_simple_val(_) -> false.
-
-%% pattern_bin([Element], State) -> {[Element],[Variable],[UsedVar],State}.
-
-pattern_bin(Es0, St) ->
- Es1 = bin_expand_strings(Es0),
- foldr(fun (E, Acc) -> pattern_element(E, Acc) end, {[],[],[],St}, Es1).
-
-pattern_element({bin_element,Line,Expr,Size,Type}, {Es,Esvs,Esus,St0}) ->
- {Expr1,Vs1,Us1,St1} = pattern(Expr, St0),
- {Size1,Vs2,Us2,St2} = pat_bit_size(Size, St1),
- {Size2,Type1} = make_bit_type(Line, Size1,Type),
- {[{bin_element,Line,Expr1,Size2,Type1}|Es],
- union([Vs1,Vs2,Esvs]),union([Us1,Us2,Esus]),St2}.
-
-pat_bit_size(default, St) -> {default,[],[],St};
-pat_bit_size({atom,_La,all}=All, St) -> {All,[],[],St};
-pat_bit_size({var,_Lv,V}=Var, St) -> {Var,[],[V],St};
-pat_bit_size(Size, St) ->
- Line = element(2, Size),
- {value,Sz,_} = erl_eval:expr(Size, erl_eval:new_bindings()),
- {{integer,Line,Sz},[],[],St}.
-
-make_bit_type(Line, default, Type0) ->
- case erl_bits:set_bit_type(default, Type0) of
- {ok,all,Bt} -> {{atom,Line,all},erl_bits:as_list(Bt)};
- {ok,Size,Bt} -> {{integer,Line,Size},erl_bits:as_list(Bt)}
- end;
-make_bit_type(_Line, Size, Type0) -> %Integer or 'all'
- {ok,Size,Bt} = erl_bits:set_bit_type(Size, Type0),
- {Size,erl_bits:as_list(Bt)}.
-
-%% expr_bin([Element], [VisibleVar], State) ->
-%% {[Element],[NewVar],[UsedVar],State}.
-
-expr_bin(Es0, Vs, St) ->
- Es1 = bin_expand_strings(Es0),
- foldr(fun (E, Acc) -> bin_element(E, Vs, Acc) end, {[],[],[],St}, Es1).
-
-bin_element({bin_element,Line,Expr,Size,Type}, Vs, {Es,Esvs,Esus,St0}) ->
- {Expr1,Vs1,Us1,St1} = expr(Expr, Vs, St0),
- {Size1,Vs2,Us2,St2} = if Size == default -> {default,[],[],St1};
- true -> expr(Size, Vs, St1)
- end,
- {Size2,Type1} = make_bit_type(Line, Size1, Type),
- {[{bin_element,Line,Expr1,Size2,Type1}|Es],
- union([Vs1,Vs2,Esvs]),union([Us1,Us2,Esus]),St2}.
-
-bin_expand_strings(Es) ->
- foldr(fun ({bin_element,Line,{string,_,S},default,default}, Es1) ->
- foldr(fun (C, Es2) ->
- [{bin_element,Line,{char,Line,C},default,default}|Es2]
- end, Es1, S);
- (E, Es1) -> [E|Es1]
- end, [], Es).
-
-%% new_var_name(State) -> {VarName,State}.
-
-new_var_name(St) ->
- C = St#expand.vcount,
- {list_to_atom("pre" ++ integer_to_list(C)),St#expand{vcount=C+1}}.
-
-%% new_var(Line, State) -> {Var,State}.
-
-new_var(L, St0) ->
- {New,St1} = new_var_name(St0),
- {{var,L,New},St1}.
-
-%% new_vars(Count, Line, State) -> {[Var],State}.
-%% Make Count new variables.
-
-new_vars(N, L, St) -> new_vars(N, L, St, []).
-
-new_vars(N, L, St0, Vs) when N > 0 ->
- {V,St1} = new_var(L, St0),
- new_vars(N-1, L, St1, [V|Vs]);
-new_vars(0, _L, St, Vs) -> {Vs,St}.
-
-%% make_list(TermList, Line) -> ConsTerm.
-
-make_list(Ts, Line) ->
- foldr(fun (H, T) -> {cons,Line,H,T} end, {nil,Line}, Ts).
-
-string_to_conses(Line, Cs, Tail) ->
- foldr(fun (C, T) -> {cons,Line,{char,Line,C},T} end, Tail, Cs).
-
-
-%% In syntax trees, module/package names are atoms or lists of atoms.
-
-package_to_string(A) when atom(A) -> atom_to_list(A);
-package_to_string(L) when list(L) -> packages:concat(L).
-
-expand_package({atom,L,A} = M, St) ->
- case dict:find(A, St#expand.mod_imports) of
- {ok, A1} ->
- {atom,L,A1};
- error ->
- case packages:is_segmented(A) of
- true ->
- M;
- false ->
- M1 = packages:concat(St#expand.package, A),
- {atom,L,list_to_atom(M1)}
- end
- end;
-expand_package(M, _St) ->
- case erl_parse:package_segments(M) of
- error ->
- M;
- M1 ->
- {atom,element(2,M),list_to_atom(package_to_string(M1))}
- end.
-
-%% Create a case-switch on true/false, generating badarg for all other
-%% values.
-
-make_bool_switch(L, E, V, T, F) ->
- make_bool_switch_1(L, E, V, [T], [F]).
-
-make_bool_switch_1(L, E, V, T, F) ->
- case get(sys_pre_expand_in_guard) of
- undefined -> make_bool_switch_body(L, E, V, T, F);
- yes -> make_bool_switch_guard(L, E, V, T, F)
- end.
-
-make_bool_switch_guard(_, E, _, [{atom,_,true}], [{atom,_,false}]) -> E;
-make_bool_switch_guard(L, E, V, T, F) ->
- NegL = -abs(L),
- {'case',NegL,E,
- [{clause,NegL,[{atom,NegL,true}],[],T},
- {clause,NegL,[{atom,NegL,false}],[],F},
- {clause,NegL,[V],[],[V]}
- ]}.
-
-make_bool_switch_body(L, E, V, T, F) ->
- NegL = -abs(L),
- {'case',NegL,E,
- [{clause,NegL,[{atom,NegL,true}],[],T},
- {clause,NegL,[{atom,NegL,false}],[],F},
- {clause,NegL,[V],[],
- [call_error(NegL,{tuple,NegL,[{atom,NegL,badarg},V]})]}
- ]}.
-
-%% Expand a list of cond-clauses to a sequence of case-switches.
-
-cond_clauses([{clause,L,[],[[E]],B}],V) ->
- make_bool_switch_1(L,E,V,B,[call_error(L,{atom,L,cond_clause})]);
-cond_clauses([{clause,L,[],[[E]],B} | Cs],V) ->
- make_bool_switch_1(L,E,V,B,[cond_clauses(Cs,V)]).
-
-%% call_error(Line, Reason) -> Expr.
-%% Build a call to erlang:error/1 with reason Reason.
-
-call_error(L, R) ->
- {call,L,{remote,L,{atom,L,erlang},{atom,L,error}},[R]}.
-
-%% new_in_all(Before, RegionList) -> NewInAll
-%% Return the variables new in all clauses.
-
-new_in_all(Before, Region) ->
- InAll = intersection(Region),
- subtract(InAll, Before).
-
-%% import(Line, Imports, State) ->
-%% State'
-%% imported(Name, Arity, State) ->
-%% {yes,Module} | no
-%% Handle import declarations and est for imported functions. No need to
-%% check when building imports as code is correct.
-
-import({Mod0,Fs}, St) ->
- Mod = list_to_atom(package_to_string(Mod0)),
- Mfs = from_list(Fs),
- St#expand{imports=add_imports(Mod, Mfs, St#expand.imports)};
-import(Mod0, St) ->
- Mod = package_to_string(Mod0),
- Key = list_to_atom(packages:last(Mod)),
- St#expand{mod_imports=dict:store(Key, list_to_atom(Mod),
- St#expand.mod_imports)}.
-
-add_imports(Mod, [F|Fs], Is) ->
- add_imports(Mod, Fs, orddict:store(F, Mod, Is));
-add_imports(_, [], Is) -> Is.
-
-imported(F, A, St) ->
- case orddict:find({F,A}, St#expand.imports) of
- {ok,Mod} -> {yes,Mod};
- error -> no
- end.
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_codegen.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_codegen.erl
deleted file mode 100644
index 2af4d94655..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_codegen.erl
+++ /dev/null
@@ -1,1755 +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: v3_codegen.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
-%%
-%% Purpose : Code generator for Beam.
-
-%% The following assumptions have been made:
-%%
-%% 1. Matches, i.e. things with {match,M,Ret} wrappers, only return
-%% values; no variables are exported. If the match would have returned
-%% extra variables then these have been transformed to multiple return
-%% values.
-%%
-%% 2. All BIF's called in guards are gc-safe so there is no need to
-%% put thing on the stack in the guard. While this would in principle
-%% work it would be difficult to keep track of the stack depth when
-%% trimming.
-%%
-%% The code generation uses variable lifetime information added by
-%% the v3_life module to save variables, allocate registers and
-%% move registers to the stack when necessary.
-%%
-%% We try to use a consistent variable name scheme throughout. The
-%% StackReg record is always called Bef,Int<n>,Aft.
-
--module(v3_codegen).
-
-%% The main interface.
--export([module/2]).
-
--import(lists, [member/2,keymember/3,keysort/2,keysearch/3,append/1,
- map/2,flatmap/2,foldl/3,foldr/3,mapfoldl/3,
- sort/1,reverse/1,reverse/2]).
--import(v3_life, [vdb_find/2]).
-
-%%-compile([export_all]).
-
--include("v3_life.hrl").
-
-%% Main codegen structure.
--record(cg, {lcount=1, %Label counter
- mod, %Current module
- func, %Current function
- finfo, %Function info label
- fcode, %Function code label
- btype, %Type of bif used.
- bfail, %Fail label of bif
- break, %Break label
- recv, %Receive label
- is_top_block, %Boolean: top block or not
- functable = [], %Table of local functions:
- %[{{Name, Arity}, Label}...]
- in_catch=false, %Inside a catch or not.
- need_frame, %Need a stack frame.
- new_funs=true}). %Generate new fun instructions.
-
-%% Stack/register state record.
--record(sr, {reg=[], %Register table
- stk=[], %Stack table
- res=[]}). %Reserved regs: [{reserved,I,V}]
-
-module({Mod,Exp,Attr,Forms}, Options) ->
- NewFunsFlag = not member(no_new_funs, Options),
- {Fs,St} = functions(Forms, #cg{mod=Mod,new_funs=NewFunsFlag}),
- {ok,{Mod,Exp,Attr,Fs,St#cg.lcount}}.
-
-functions(Forms, St0) ->
- mapfoldl(fun (F, St) -> function(F, St) end, St0#cg{lcount=1}, Forms).
-
-function({function,Name,Arity,As0,Vb,Vdb}, St0) ->
- %%ok = io:fwrite("cg ~w:~p~n", [?LINE,{Name,Arity}]),
- St1 = St0#cg{func={Name,Arity}},
- {Fun,St2} = cg_fun(Vb, As0, Vdb, St1),
- Func0 = {function,Name,Arity,St2#cg.fcode,Fun},
- Func = bs_function(Func0),
- {Func,St2}.
-
-%% cg_fun([Lkexpr], [HeadVar], Vdb, State) -> {[Ainstr],State}
-
-cg_fun(Les, Hvs, Vdb, St0) ->
- {Name,Arity} = St0#cg.func,
- {Fi,St1} = new_label(St0), %FuncInfo label
- {Fl,St2} = local_func_label(Name, Arity, St1),
- %% Create initial stack/register state, clear unused arguments.
- Bef = clear_dead(#sr{reg=foldl(fun ({var,V}, Reg) ->
- put_reg(V, Reg)
- end, [], Hvs),
- stk=[]}, 0, Vdb),
- {B2,_Aft,St3} = cg_list(Les, 0, Vdb, Bef, St2#cg{btype=exit,
- bfail=Fi,
- finfo=Fi,
- fcode=Fl,
- is_top_block=true}),
- A = [{label,Fi},{func_info,{atom,St3#cg.mod},{atom,Name},Arity},
- {label,Fl}|B2],
- {A,St3}.
-
-%% cg(Lkexpr, Vdb, StackReg, State) -> {[Ainstr],StackReg,State}.
-%% Generate code for a kexpr.
-%% Split function into two steps for clarity, not efficiency.
-
-cg(Le, Vdb, Bef, St) ->
- cg(Le#l.ke, Le, Vdb, Bef, St).
-
-cg({block,Es}, Le, Vdb, Bef, St) ->
- block_cg(Es, Le, Vdb, Bef, St);
-cg({match,M,Rs}, Le, Vdb, Bef, St) ->
- match_cg(M, Rs, Le, Vdb, Bef, St);
-cg({match_fail,F}, Le, Vdb, Bef, St) ->
- match_fail_cg(F, Le, Vdb, Bef, St);
-cg({call,Func,As,Rs}, Le, Vdb, Bef, St) ->
- call_cg(Func, As, Rs, Le, Vdb, Bef, St);
-cg({enter,Func,As}, Le, Vdb, Bef, St) ->
- enter_cg(Func, As, Le, Vdb, Bef, St);
-cg({bif,Bif,As,Rs}, Le, Vdb, Bef, St) ->
- bif_cg(Bif, As, Rs, Le, Vdb, Bef, St);
-cg({receive_loop,Te,Rvar,Rm,Tes,Rs}, Le, Vdb, Bef, St) ->
- recv_loop_cg(Te, Rvar, Rm, Tes, Rs, Le, Vdb, Bef, St);
-cg(receive_next, Le, Vdb, Bef, St) ->
- recv_next_cg(Le, Vdb, Bef, St);
-cg(receive_accept, _Le, _Vdb, Bef, St) -> {[remove_message],Bef,St};
-cg({'try',Ta,Vs,Tb,Evs,Th,Rs}, Le, Vdb, Bef, St) ->
- try_cg(Ta, Vs, Tb, Evs, Th, Rs, Le, Vdb, Bef, St);
-cg({'catch',Cb,R}, Le, Vdb, Bef, St) ->
- catch_cg(Cb, R, Le, Vdb, Bef, St);
-cg({set,Var,Con}, Le, Vdb, Bef, St) -> set_cg(Var, Con, Le, Vdb, Bef, St);
-cg({return,Rs}, Le, Vdb, Bef, St) -> return_cg(Rs, Le, Vdb, Bef, St);
-cg({break,Bs}, Le, Vdb, Bef, St) -> break_cg(Bs, Le, Vdb, Bef, St);
-cg({need_heap,0}, _Le, _Vdb, Bef, St) ->
- {[],Bef,St};
-cg({need_heap,H}, _Le, _Vdb, Bef, St) ->
- {[{test_heap,H,max_reg(Bef#sr.reg)}],Bef,St}.
-
-%% cg_list([Kexpr], FirstI, Vdb, StackReg, St) -> {[Ainstr],StackReg,St}.
-
-cg_list(Kes, I, Vdb, Bef, St0) ->
- {Keis,{Aft,St1}} =
- flatmapfoldl(fun (Ke, {Inta,Sta}) ->
-% ok = io:fwrite(" %% ~p\n", [Inta]),
-% ok = io:fwrite("cgl:~p\n", [Ke]),
- {Keis,Intb,Stb} = cg(Ke, Vdb, Inta, Sta),
-% ok = io:fwrite(" ~p\n", [Keis]),
-% ok = io:fwrite(" %% ~p\n", [Intb]),
- {comment(Inta) ++ Keis,{Intb,Stb}}
- end, {Bef,St0}, need_heap(Kes, I)),
- {Keis,Aft,St1}.
-
-%% need_heap([Lkexpr], I, BifType) -> [Lkexpr].
-%% Insert need_heap instructions in Kexpr list. Try to be smart and
-%% collect them together as much as possible.
-
-need_heap(Kes0, I) ->
- {Kes1,{H,F}} = flatmapfoldr(fun (Ke, {H0,F0}) ->
- {Ns,H1,F1} = need_heap_1(Ke, H0, F0),
- {[Ke|Ns],{H1,F1}}
- end, {0,false}, Kes0),
- %% Prepend need_heap if necessary.
- Kes2 = need_heap_need(I, H, F) ++ Kes1,
-% ok = io:fwrite("need_heap: ~p~n",
-% [{{H,F},
-% map(fun (#l{ke={match,M,Rs}}) -> match;
-% (Lke) -> Lke#l.ke end, Kes2)}]),
- Kes2.
-
-need_heap_1(#l{ke={set,_,{binary,_}},i=I}, H, F) ->
- {need_heap_need(I, H, F),0,false};
-need_heap_1(#l{ke={set,_,Val}}, H, F) ->
- %% Just pass through adding to needed heap.
- {[],H + case Val of
- {cons,_} -> 2;
- {tuple,Es} -> 1 + length(Es);
- {string,S} -> 2 * length(S);
- _Other -> 0
- end,F};
-need_heap_1(#l{ke={call,_Func,_As,_Rs},i=I}, H, F) ->
- %% Calls generate a need if necessary and also force one.
- {need_heap_need(I, H, F),0,true};
-need_heap_1(#l{ke={bif,dsetelement,_As,_Rs},i=I}, H, F) ->
- {need_heap_need(I, H, F),0,true};
-need_heap_1(#l{ke={bif,{make_fun,_,_,_,_},_As,_Rs},i=I}, H, F) ->
- {need_heap_need(I, H, F),0,true};
-need_heap_1(#l{ke={bif,_Bif,_As,_Rs}}, H, F) ->
- {[],H,F};
-need_heap_1(#l{i=I}, H, F) ->
- %% Others kexprs generate a need if necessary but don't force.
- {need_heap_need(I, H, F),0,false}.
-
-need_heap_need(_I, 0, false) -> [];
-need_heap_need(I, H, _F) -> [#l{ke={need_heap,H},i=I}].
-
-
-%% match_cg(Match, [Ret], Le, Vdb, StackReg, State) ->
-%% {[Ainstr],StackReg,State}.
-%% Generate code for a match. First save all variables on the stack
-%% that are to survive after the match. We leave saved variables in
-%% their registers as they might actually be in the right place.
-%% Should test this.
-
-match_cg(M, Rs, Le, Vdb, Bef, St0) ->
- I = Le#l.i,
- {Sis,Int0} = adjust_stack(Bef, I, I+1, Vdb),
- {B,St1} = new_label(St0),
- {Mis,Int1,St2} = match_cg(M, none, Int0, St1#cg{break=B}),
- %% Put return values in registers.
- Reg = load_vars(Rs, Int1#sr.reg),
- {Sis ++ Mis ++ [{label,B}],
- clear_dead(Int1#sr{reg=Reg}, I, Vdb),
- St2#cg{break=St1#cg.break}}.
-
-%% match_cg(Match, Fail, StackReg, State) -> {[Ainstr],StackReg,State}.
-%% Generate code for a match tree. N.B. there is no need pass Vdb
-%% down as each level which uses this takes its own internal Vdb not
-%% the outer one.
-
-match_cg(Le, Fail, Bef, St) ->
- match_cg(Le#l.ke, Le, Fail, Bef, St).
-
-match_cg({alt,F,S}, _Le, Fail, Bef, St0) ->
- {Tf,St1} = new_label(St0),
- {Fis,Faft,St2} = match_cg(F, Tf, Bef, St1),
- {Sis,Saft,St3} = match_cg(S, Fail, Bef, St2),
- Aft = sr_merge(Faft, Saft),
- {Fis ++ [{label,Tf}] ++ Sis,Aft,St3};
-match_cg({select,V,Scs}, _Va, Fail, Bef, St) ->
- match_fmf(fun (S, F, Sta) ->
- select_cg(S, V, F, Fail, Bef, Sta) end,
- Fail, St, Scs);
-match_cg({guard,Gcs}, _Le, Fail, Bef, St) ->
- match_fmf(fun (G, F, Sta) -> guard_clause_cg(G, F, Bef, Sta) end,
- Fail, St, Gcs);
-match_cg({block,Es}, Le, _Fail, Bef, St) ->
- %% Must clear registers and stack of dead variables.
- Int = clear_dead(Bef, Le#l.i, Le#l.vdb),
- block_cg(Es, Le, Int, St).
-
-%% match_fail_cg(FailReason, Le, Vdb, StackReg, State) ->
-%% {[Ainstr],StackReg,State}.
-%% Generate code for the match_fail "call". N.B. there is no generic
-%% case for when the fail value has been created elsewhere.
-
-match_fail_cg({function_clause,As}, Le, Vdb, Bef, St) ->
- %% Must have the args in {x,0}, {x,1},...
- {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
- {Sis ++ [{jump,{f,St#cg.finfo}}],
- Int#sr{reg=clear_regs(Int#sr.reg)},St};
-match_fail_cg({badmatch,Term}, Le, Vdb, Bef, St) ->
- R = cg_reg_arg(Term, Bef),
- Int0 = clear_dead(Bef, Le#l.i, Vdb),
- {Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
- {Sis ++ [{badmatch,R}],
- Int#sr{reg=clear_regs(Int0#sr.reg)},St};
-match_fail_cg({case_clause,Reason}, Le, Vdb, Bef, St) ->
- R = cg_reg_arg(Reason, Bef),
- Int0 = clear_dead(Bef, Le#l.i, Vdb),
- {Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
- {Sis++[{case_end,R}],
- Int#sr{reg=clear_regs(Bef#sr.reg)},St};
-match_fail_cg(if_clause, Le, Vdb, Bef, St) ->
- Int0 = clear_dead(Bef, Le#l.i, Vdb),
- {Sis,Int1} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
- {Sis++[if_end],Int1#sr{reg=clear_regs(Int1#sr.reg)},St};
-match_fail_cg({try_clause,Reason}, Le, Vdb, Bef, St) ->
- R = cg_reg_arg(Reason, Bef),
- Int0 = clear_dead(Bef, Le#l.i, Vdb),
- {Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
- {Sis ++ [{try_case_end,R}],
- Int#sr{reg=clear_regs(Int0#sr.reg)},St}.
-
-
-%% block_cg([Kexpr], Le, Vdb, StackReg, St) -> {[Ainstr],StackReg,St}.
-%% block_cg([Kexpr], Le, StackReg, St) -> {[Ainstr],StackReg,St}.
-
-block_cg(Es, Le, _Vdb, Bef, St) ->
- block_cg(Es, Le, Bef, St).
-
-block_cg(Es, Le, Bef, St0) ->
- case St0#cg.is_top_block of
- false ->
- cg_block(Es, Le#l.i, Le#l.vdb, Bef, St0);
- true ->
- {Keis,Aft,St1} = cg_block(Es, Le#l.i, Le#l.vdb, Bef,
- St0#cg{is_top_block=false,
- need_frame=false}),
- top_level_block(Keis, Aft, max_reg(Bef#sr.reg), St1)
- end.
-
-cg_block([], _I, _Vdb, Bef, St0) ->
- {[],Bef,St0};
-cg_block(Kes0, I, Vdb, Bef, St0) ->
- {Kes2,Int1,St1} =
- case basic_block(Kes0) of
- {Kes1,LastI,Args,Rest} ->
- Ke = hd(Kes1),
- Fb = Ke#l.i,
- cg_basic_block(Kes1, Fb, LastI, Args, Vdb, Bef, St0);
- {Kes1,Rest} ->
- cg_list(Kes1, I, Vdb, Bef, St0)
- end,
- {Kes3,Int2,St2} = cg_block(Rest, I, Vdb, Int1, St1),
- {Kes2 ++ Kes3,Int2,St2}.
-
-basic_block(Kes) -> basic_block(Kes, []).
-
-basic_block([], Acc) -> {reverse(Acc),[]};
-basic_block([Le|Les], Acc) ->
- case collect_block(Le#l.ke) of
- include -> basic_block(Les, [Le|Acc]);
- {block_end,As} -> {reverse(Acc, [Le]),Le#l.i,As,Les};
- no_block -> {reverse(Acc, [Le]),Les}
- end.
-
-collect_block({set,_,{binary,_}}) -> no_block;
-collect_block({set,_,_}) -> include;
-collect_block({call,{var,_}=Var,As,_Rs}) -> {block_end,As++[Var]};
-collect_block({call,Func,As,_Rs}) -> {block_end,As++func_vars(Func)};
-collect_block({enter,{var,_}=Var,As})-> {block_end,As++[Var]};
-collect_block({enter,Func,As}) -> {block_end,As++func_vars(Func)};
-collect_block({return,Rs}) -> {block_end,Rs};
-collect_block({break,Bs}) -> {block_end,Bs};
-collect_block({bif,_Bif,_As,_Rs}) -> include;
-collect_block(_) -> no_block.
-
-func_vars({remote,M,F}) when element(1, M) == var;
- element(1, F) == var ->
- [M,F];
-func_vars(_) -> [].
-
-%% cg_basic_block([Kexpr], FirstI, LastI, As, Vdb, StackReg, State) ->
-%% {[Ainstr],StackReg,State}.
-
-cg_basic_block(Kes, Fb, Lf, As, Vdb, Bef, St0) ->
- Res = make_reservation(As, 0),
- Regs0 = reserve(Res, Bef#sr.reg, Bef#sr.stk),
- Stk = extend_stack(Bef, Lf, Lf+1, Vdb),
- Int0 = Bef#sr{reg=Regs0,stk=Stk,res=Res},
- X0_v0 = x0_vars(As, Fb, Lf, Vdb),
- {Keis,{Aft,_,St1}} =
- flatmapfoldl(fun(Ke, St) -> cg_basic_block(Ke, St, Lf, Vdb) end,
- {Int0,X0_v0,St0}, need_heap(Kes, Fb)),
- {Keis,Aft,St1}.
-
-cg_basic_block(Ke, {Inta,X0v,Sta}, _Lf, Vdb) when element(1, Ke#l.ke) =:= need_heap ->
- {Keis,Intb,Stb} = cg(Ke, Vdb, Inta, Sta),
- {comment(Inta) ++ Keis, {Intb,X0v,Stb}};
-cg_basic_block(Ke, {Inta,X0_v1,Sta}, Lf, Vdb) ->
- {Sis,Intb} = save_carefully(Inta, Ke#l.i, Lf+1, Vdb),
- {X0_v2,Intc} = allocate_x0(X0_v1, Ke#l.i, Intb),
- Intd = reserve(Intc),
- {Keis,Inte,Stb} = cg(Ke, Vdb, Intd, Sta),
- {comment(Inta) ++ Sis ++ Keis, {Inte,X0_v2,Stb}}.
-
-make_reservation([], _) -> [];
-make_reservation([{var,V}|As], I) -> [{I,V}|make_reservation(As, I+1)];
-make_reservation([A|As], I) -> [{I,A}|make_reservation(As, I+1)].
-
-reserve(Sr) -> Sr#sr{reg=reserve(Sr#sr.res, Sr#sr.reg, Sr#sr.stk)}.
-
-reserve([{I,V}|Rs], [free|Regs], Stk) -> [{reserved,I,V}|reserve(Rs, Regs, Stk)];
-reserve([{I,V}|Rs], [{I,V}|Regs], Stk) -> [{I,V}|reserve(Rs, Regs, Stk)];
-reserve([{I,V}|Rs], [{I,Var}|Regs], Stk) ->
- case on_stack(Var, Stk) of
- true -> [{reserved,I,V}|reserve(Rs, Regs, Stk)];
- false -> [{I,Var}|reserve(Rs, Regs, Stk)]
- end;
-reserve([{I,V}|Rs], [{reserved,I,_}|Regs], Stk) ->
- [{reserved,I,V}|reserve(Rs, Regs, Stk)];
-%reserve([{I,V}|Rs], [Other|Regs], Stk) -> [Other|reserve(Rs, Regs, Stk)];
-reserve([{I,V}|Rs], [], Stk) -> [{reserved,I,V}|reserve(Rs, [], Stk)];
-reserve([], Regs, _) -> Regs.
-
-extend_stack(Bef, Fb, Lf, Vdb) ->
- Stk0 = clear_dead_stk(Bef#sr.stk, Fb, Vdb),
- Saves = [V || {V,F,L} <- Vdb,
- F < Fb,
- L >= Lf,
- not on_stack(V, Stk0)],
- Stk1 = foldl(fun (V, Stk) -> put_stack(V, Stk) end, Stk0, Saves),
- Bef#sr.stk ++ lists:duplicate(length(Stk1) - length(Bef#sr.stk), free).
-
-save_carefully(Bef, Fb, Lf, Vdb) ->
- Stk = Bef#sr.stk,
- %% New variables that are in use but not on stack.
- New = [ {V,F,L} || {V,F,L} <- Vdb,
- F < Fb,
- L >= Lf,
- not on_stack(V, Stk) ],
- Saves = [ V || {V,_,_} <- keysort(2, New) ],
- save_carefully(Saves, Bef, []).
-
-save_carefully([], Bef, Acc) -> {reverse(Acc),Bef};
-save_carefully([V|Vs], Bef, Acc) ->
- case put_stack_carefully(V, Bef#sr.stk) of
- error -> {reverse(Acc),Bef};
- Stk1 ->
- SrcReg = fetch_reg(V, Bef#sr.reg),
- Move = {move,SrcReg,fetch_stack(V, Stk1)},
- {x,_} = SrcReg, %Assertion - must be X register.
- save_carefully(Vs, Bef#sr{stk=Stk1}, [Move|Acc])
- end.
-
-x0_vars([], _Fb, _Lf, _Vdb) -> [];
-x0_vars([{var,V}|_], Fb, _Lf, Vdb) ->
- {V,F,_L} = VFL = vdb_find(V, Vdb),
- x0_vars1([VFL], Fb, F, Vdb);
-x0_vars([X0|_], Fb, Lf, Vdb) ->
- x0_vars1([{X0,Lf,Lf}], Fb, Lf, Vdb).
-
-x0_vars1(X0, Fb, Xf, Vdb) ->
- Vs0 = [VFL || {_V,F,L}=VFL <- Vdb,
- F >= Fb,
- L < Xf],
- Vs1 = keysort(3, Vs0),
- keysort(2, X0++Vs1).
-
-allocate_x0([], _, Bef) -> {[],Bef#sr{res=[]}};
-allocate_x0([{_,_,L}|Vs], I, Bef) when L =< I ->
- allocate_x0(Vs, I, Bef);
-allocate_x0([{V,_F,_L}=VFL|Vs], _, Bef) ->
- {[VFL|Vs],Bef#sr{res=reserve_x0(V, Bef#sr.res)}}.
-
-reserve_x0(V, [_|Res]) -> [{0,V}|Res];
-reserve_x0(V, []) -> [{0,V}].
-
-top_level_block(Keis, Bef, _MaxRegs, St0) when St0#cg.need_frame =:= false,
- length(Bef#sr.stk) =:= 0 ->
- %% This block need no stack frame. However, we still need to turn the
- %% stack frame upside down.
- MaxY = length(Bef#sr.stk)-1,
- Keis1 = flatmap(fun (Tuple) when tuple(Tuple) ->
- [turn_yregs(size(Tuple), Tuple, MaxY)];
- (Other) ->
- [Other]
- end, Keis),
- {Keis1, Bef, St0#cg{is_top_block=true}};
-top_level_block(Keis, Bef, MaxRegs, St0) ->
- %% This top block needs an allocate instruction before it, and a
- %% deallocate instruction before each return.
- FrameSz = length(Bef#sr.stk),
- MaxY = FrameSz-1,
- Keis1 = flatmap(fun ({call_only,Arity,Func}) ->
- [{call_last,Arity,Func,FrameSz}];
- ({call_ext_only,Arity,Func}) ->
- [{call_ext_last,Arity,Func,FrameSz}];
- ({apply_only,Arity}) ->
- [{apply_last,Arity,FrameSz}];
- (return) ->
- [{deallocate,FrameSz}, return];
- (Tuple) when tuple(Tuple) ->
- [turn_yregs(size(Tuple), Tuple, MaxY)];
- (Other) ->
- [Other]
- end, Keis),
- {[{allocate_zero,FrameSz,MaxRegs}|Keis1], Bef, St0#cg{is_top_block=true}}.
-
-%% turn_yregs(Size, Tuple, MaxY) -> Tuple'
-%% Renumber y register so that {y, 0} becomes {y, FrameSize-1},
-%% {y, FrameSize-1} becomes {y, 0} and so on. This is to make nested
-%% catches work. The code generation algorithm gives a lower register
-%% number to the outer catch, which is wrong.
-
-turn_yregs(0, Tp, _) -> Tp;
-turn_yregs(El, Tp, MaxY) when element(1, element(El, Tp)) == yy ->
- turn_yregs(El-1, setelement(El, Tp, {y,MaxY-element(2, element(El, Tp))}), MaxY);
-turn_yregs(El, Tp, MaxY) when list(element(El, Tp)) ->
- New = map(fun ({yy,YY}) -> {y,MaxY-YY};
- (Other) -> Other end, element(El, Tp)),
- turn_yregs(El-1, setelement(El, Tp, New), MaxY);
-turn_yregs(El, Tp, MaxY) ->
- turn_yregs(El-1, Tp, MaxY).
-
-%% select_cg(Sclause, V, TypeFail, ValueFail, StackReg, State) ->
-%% {Is,StackReg,State}.
-%% Selecting type and value needs two failure labels, TypeFail is the
-%% label to jump to of the next type test when this type fails, and
-%% ValueFail is the label when this type is correct but the value is
-%% wrong. These are different as in the second case there is no need
-%% to try the next type, it will always fail.
-
-select_cg(#l{ke={type_clause,cons,[S]}}, {var,V}, Tf, Vf, Bef, St) ->
- select_cons(S, V, Tf, Vf, Bef, St);
-select_cg(#l{ke={type_clause,nil,[S]}}, {var,V}, Tf, Vf, Bef, St) ->
- select_nil(S, V, Tf, Vf, Bef, St);
-select_cg(#l{ke={type_clause,binary,[S]}}, {var,V}, Tf, Vf, Bef, St) ->
- select_binary(S, V, Tf, Vf, Bef, St);
-select_cg(#l{ke={type_clause,bin_seg,S}}, {var,V}, Tf, Vf, Bef, St) ->
- select_bin_segs(S, V, Tf, Vf, Bef, St);
-select_cg(#l{ke={type_clause,bin_end,[S]}}, {var,V}, Tf, Vf, Bef, St) ->
- select_bin_end(S, V, Tf, Vf, Bef, St);
-select_cg(#l{ke={type_clause,Type,Scs}}, {var,V}, Tf, Vf, Bef, St0) ->
- {Vis,{Aft,St1}} =
- mapfoldl(fun (S, {Int,Sta}) ->
- {Val,Is,Inta,Stb} = select_val(S, V, Vf, Bef, Sta),
- {{Is,[Val]},{sr_merge(Int, Inta),Stb}}
- end, {void,St0}, Scs),
- OptVls = combine(lists:sort(combine(Vis))),
- {Vls,Sis,St2} = select_labels(OptVls, St1, [], []),
- {select_val_cg(Type, fetch_var(V, Bef), Vls, Tf, Vf, Sis), Aft, St2}.
-
-select_val_cg(tuple, R, [Arity,{f,Lbl}], Tf, Vf, [{label,Lbl}|Sis]) ->
- [{test,is_tuple,{f,Tf},[R]},{test,test_arity,{f,Vf},[R,Arity]}|Sis];
-select_val_cg(tuple, R, Vls, Tf, Vf, Sis) ->
- [{test,is_tuple,{f,Tf},[R]},{select_tuple_arity,R,{f,Vf},{list,Vls}}|Sis];
-select_val_cg(Type, R, [Val, {f,Lbl}], Fail, Fail, [{label,Lbl}|Sis]) ->
- [{test,is_eq_exact,{f,Fail},[R,{Type,Val}]}|Sis];
-select_val_cg(Type, R, [Val, {f,Lbl}], Tf, Vf, [{label,Lbl}|Sis]) ->
- [{test,select_type_test(Type),{f,Tf},[R]},
- {test,is_eq_exact,{f,Vf},[R,{Type,Val}]}|Sis];
-select_val_cg(Type, R, Vls0, Tf, Vf, Sis) ->
- Vls1 = map(fun ({f,Lbl}) -> {f,Lbl};
- (Value) -> {Type,Value}
- end, Vls0),
- [{test,select_type_test(Type),{f,Tf},[R]}, {select_val,R,{f,Vf},{list,Vls1}}|Sis].
-
-select_type_test(tuple) -> is_tuple;
-select_type_test(integer) -> is_integer;
-select_type_test(atom) -> is_atom;
-select_type_test(float) -> is_float.
-
-combine([{Is,Vs1}, {Is,Vs2}|Vis]) -> combine([{Is,Vs1 ++ Vs2}|Vis]);
-combine([V|Vis]) -> [V|combine(Vis)];
-combine([]) -> [].
-
-select_labels([{Is,Vs}|Vis], St0, Vls, Sis) ->
- {Lbl,St1} = new_label(St0),
- select_labels(Vis, St1, add_vls(Vs, Lbl, Vls), [[{label,Lbl}|Is]|Sis]);
-select_labels([], St, Vls, Sis) ->
- {Vls,append(Sis),St}.
-
-add_vls([V|Vs], Lbl, Acc) ->
- add_vls(Vs, Lbl, [V, {f,Lbl}|Acc]);
-add_vls([], _, Acc) -> Acc.
-
-select_cons(#l{ke={val_clause,{cons,Es},B},i=I,vdb=Vdb}, V, Tf, Vf, Bef, St0) ->
- {Eis,Int,St1} = select_extract_cons(V, Es, I, Vdb, Bef, St0),
- {Bis,Aft,St2} = match_cg(B, Vf, Int, St1),
- {[{test,is_nonempty_list,{f,Tf},[fetch_var(V, Bef)]}] ++ Eis ++ Bis,Aft,St2}.
-
-select_nil(#l{ke={val_clause,nil,B}}, V, Tf, Vf, Bef, St0) ->
- {Bis,Aft,St1} = match_cg(B, Vf, Bef, St0),
- {[{test,is_nil,{f,Tf},[fetch_var(V, Bef)]}] ++ Bis,Aft,St1}.
-
-select_binary(#l{ke={val_clause,{old_binary,Var},B}}=L,
- V, Tf, Vf, Bef, St) ->
- %% Currently handled in the same way as new binaries.
- select_binary(L#l{ke={val_clause,{binary,Var},B}}, V, Tf, Vf, Bef, St);
-select_binary(#l{ke={val_clause,{binary,{var,Ivar}},B},i=I,vdb=Vdb},
- V, Tf, Vf, Bef, St0) ->
- Int0 = clear_dead(Bef, I, Vdb),
- {Bis,Aft,St1} = match_cg(B, Vf, Int0, St0),
- {[{test,bs_start_match,{f,Tf},[fetch_var(V, Bef)]},{bs_save,Ivar}|Bis],
- Aft,St1}.
-
-select_bin_segs(Scs, Ivar, Tf, _Vf, Bef, St) ->
- match_fmf(fun(S, Fail, Sta) ->
- select_bin_seg(S, Ivar, Fail, Bef, Sta) end,
- Tf, St, Scs).
-
-select_bin_seg(#l{ke={val_clause,{bin_seg,Size,U,T,Fs,Es},B},i=I,vdb=Vdb},
- Ivar, Fail, Bef, St0) ->
- {Mis,Int,St1} = select_extract_bin(Es, Size, U, T, Fs, Fail,
- I, Vdb, Bef, St0),
- {Bis,Aft,St2} = match_cg(B, Fail, Int, St1),
- {[{bs_restore,Ivar}|Mis] ++ Bis,Aft,St2}.
-
-select_extract_bin([{var,Hd},{var,Tl}], Size0, Unit, Type, Flags, Vf,
- I, Vdb, Bef, St) ->
- SizeReg = get_bin_size_reg(Size0, Bef),
- {Es,Aft} =
- case vdb_find(Hd, Vdb) of
- {_,_,Lhd} when Lhd =< I ->
- {[{test,bs_skip_bits,{f,Vf},[SizeReg,Unit,{field_flags,Flags}]},
- {bs_save,Tl}],Bef};
- {_,_,_} ->
- Reg0 = put_reg(Hd, Bef#sr.reg),
- Int1 = Bef#sr{reg=Reg0},
- Rhd = fetch_reg(Hd, Reg0),
- Name = get_bits_instr(Type),
- {[{test,Name,{f,Vf},[SizeReg,Unit,{field_flags,Flags},Rhd]},
- {bs_save,Tl}],Int1}
- end,
- {Es,clear_dead(Aft, I, Vdb),St}.
-
-get_bin_size_reg({var,V}, Bef) ->
- fetch_var(V, Bef);
-get_bin_size_reg(Literal, _Bef) ->
- Literal.
-
-select_bin_end(#l{ke={val_clause,bin_end,B}},
- Ivar, Tf, Vf, Bef, St0) ->
- {Bis,Aft,St2} = match_cg(B, Vf, Bef, St0),
- {[{bs_restore,Ivar},{test,bs_test_tail,{f,Tf},[0]}|Bis],Aft,St2}.
-
-get_bits_instr(integer) -> bs_get_integer;
-get_bits_instr(float) -> bs_get_float;
-get_bits_instr(binary) -> bs_get_binary.
-
-select_val(#l{ke={val_clause,{tuple,Es},B},i=I,vdb=Vdb}, V, Vf, Bef, St0) ->
- {Eis,Int,St1} = select_extract_tuple(V, Es, I, Vdb, Bef, St0),
- {Bis,Aft,St2} = match_cg(B, Vf, Int, St1),
- {length(Es),Eis ++ Bis,Aft,St2};
-select_val(#l{ke={val_clause,{_,Val},B}}, _V, Vf, Bef, St0) ->
- {Bis,Aft,St1} = match_cg(B, Vf, Bef, St0),
- {Val,Bis,Aft,St1}.
-
-%% select_extract_tuple(Src, [V], I, Vdb, StackReg, State) ->
-%% {[E],StackReg,State}.
-%% Extract tuple elements, but only if they do not immediately die.
-
-select_extract_tuple(Src, Vs, I, Vdb, Bef, St) ->
- F = fun ({var,V}, {Int0,Elem}) ->
- case vdb_find(V, Vdb) of
- {V,_,L} when L =< I -> {[], {Int0,Elem+1}};
- _Other ->
- Reg1 = put_reg(V, Int0#sr.reg),
- Int1 = Int0#sr{reg=Reg1},
- Rsrc = fetch_var(Src, Int1),
- {[{get_tuple_element,Rsrc,Elem,fetch_reg(V, Reg1)}],
- {Int1,Elem+1}}
- end
- end,
- {Es,{Aft,_}} = flatmapfoldl(F, {Bef,0}, Vs),
- {Es,Aft,St}.
-
-select_extract_cons(Src, [{var,Hd}, {var,Tl}], I, Vdb, Bef, St) ->
- {Es,Aft} = case {vdb_find(Hd, Vdb), vdb_find(Tl, Vdb)} of
- {{_,_,Lhd}, {_,_,Ltl}} when Lhd =< I, Ltl =< I ->
- %% Both head and tail are dead. No need to generate
- %% any instruction.
- {[], Bef};
- _ ->
- %% At least one of head and tail will be used,
- %% but we must always fetch both. We will call
- %% clear_dead/2 to allow reuse of the register
- %% in case only of them is used.
-
- Reg0 = put_reg(Tl, put_reg(Hd, Bef#sr.reg)),
- Int0 = Bef#sr{reg=Reg0},
- Rsrc = fetch_var(Src, Int0),
- Rhd = fetch_reg(Hd, Reg0),
- Rtl = fetch_reg(Tl, Reg0),
- Int1 = clear_dead(Int0, I, Vdb),
- {[{get_list,Rsrc,Rhd,Rtl}], Int1}
- end,
- {Es,Aft,St}.
-
-
-guard_clause_cg(#l{ke={guard_clause,G,B},vdb=Vdb}, Fail, Bef, St0) ->
- {Gis,Int,St1} = guard_cg(G, Fail, Vdb, Bef, St0),
- {Bis,Aft,St2} = match_cg(B, Fail, Int, St1),
- {Gis ++ Bis,Aft,St2}.
-
-%% guard_cg(Guard, Fail, Vdb, StackReg, State) ->
-%% {[Ainstr],StackReg,State}.
-%% A guard is a boolean expression of tests. Tests return true or
-%% false. A fault in a test causes the test to return false. Tests
-%% never return the boolean, instead we generate jump code to go to
-%% the correct exit point. Primops and tests all go to the next
-%% instruction on success or jump to a failure label.
-
-guard_cg(#l{ke={protected,Ts,Rs},i=I,vdb=Pdb}, Fail, _Vdb, Bef, St) ->
- protected_cg(Ts, Rs, Fail, I, Pdb, Bef, St);
-guard_cg(#l{ke={block,Ts},i=I,vdb=Bdb}, Fail, _Vdb, Bef, St) ->
- guard_cg_list(Ts, Fail, I, Bdb, Bef, St);
-guard_cg(#l{ke={test,Test,As},i=I,vdb=_Tdb}, Fail, Vdb, Bef, St) ->
- test_cg(Test, As, Fail, I, Vdb, Bef, St);
-guard_cg(G, _Fail, Vdb, Bef, St) ->
- %%ok = io:fwrite("cg ~w: ~p~n", [?LINE,{G,Fail,Vdb,Bef}]),
- {Gis,Aft,St1} = cg(G, Vdb, Bef, St),
- %%ok = io:fwrite("cg ~w: ~p~n", [?LINE,{Aft}]),
- {Gis,Aft,St1}.
-
-%% protected_cg([Kexpr], [Ret], Fail, I, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
-%% Do a protected. Protecteds without return values are just done
-%% for effect, the return value is not checked, success passes on to
-%% the next instruction and failure jumps to Fail. If there are
-%% return values then these must be set to 'false' on failure,
-%% control always passes to the next instruction.
-
-protected_cg(Ts, [], Fail, I, Vdb, Bef, St0) ->
- %% Protect these calls, revert when done.
- {Tis,Aft,St1} = guard_cg_list(Ts, Fail, I, Vdb, Bef,
- St0#cg{btype=fail,bfail=Fail}),
- {Tis,Aft,St1#cg{btype=St0#cg.btype,bfail=St0#cg.bfail}};
-protected_cg(Ts, Rs, _Fail, I, Vdb, Bef, St0) ->
- {Pfail,St1} = new_label(St0),
- {Psucc,St2} = new_label(St1),
- {Tis,Aft,St3} = guard_cg_list(Ts, Pfail, I, Vdb, Bef,
- St2#cg{btype=fail,bfail=Pfail}),
- %%ok = io:fwrite("cg ~w: ~p~n", [?LINE,{Rs,I,Vdb,Aft}]),
- %% Set return values to false.
- Mis = map(fun ({var,V}) -> {move,{atom,false},fetch_var(V, Aft)} end, Rs),
- Live = {'%live',max_reg(Aft#sr.reg)},
- {Tis ++ [Live,{jump,{f,Psucc}},
- {label,Pfail}] ++ Mis ++ [Live,{label,Psucc}],
- Aft,St3#cg{btype=St0#cg.btype,bfail=St0#cg.bfail}}.
-
-%% test_cg(TestName, Args, Fail, I, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
-%% Generate test instruction. Use explicit fail label here.
-
-test_cg(Test, As, Fail, I, Vdb, Bef, St) ->
- case test_type(Test, length(As)) of
- {cond_op,Op} ->
- Ars = cg_reg_args(As, Bef),
- Int = clear_dead(Bef, I, Vdb),
- {[{test,Op,{f,Fail},Ars}],
- clear_dead(Int, I, Vdb),
- St};
- {rev_cond_op,Op} ->
- [S1,S2] = cg_reg_args(As, Bef),
- Int = clear_dead(Bef, I, Vdb),
- {[{test,Op,{f,Fail},[S2,S1]}],
- clear_dead(Int, I, Vdb),
- St}
- end.
-
-test_type(is_atom, 1) -> {cond_op,is_atom};
-test_type(is_boolean, 1) -> {cond_op,is_boolean};
-test_type(is_binary, 1) -> {cond_op,is_binary};
-test_type(is_constant, 1) -> {cond_op,is_constant};
-test_type(is_float, 1) -> {cond_op,is_float};
-test_type(is_function, 1) -> {cond_op,is_function};
-test_type(is_integer, 1) -> {cond_op,is_integer};
-test_type(is_list, 1) -> {cond_op,is_list};
-test_type(is_number, 1) -> {cond_op,is_number};
-test_type(is_pid, 1) -> {cond_op,is_pid};
-test_type(is_port, 1) -> {cond_op,is_port};
-test_type(is_reference, 1) -> {cond_op,is_reference};
-test_type(is_tuple, 1) -> {cond_op,is_tuple};
-test_type('=<', 2) -> {rev_cond_op,is_ge};
-test_type('>', 2) -> {rev_cond_op,is_lt};
-test_type('<', 2) -> {cond_op,is_lt};
-test_type('>=', 2) -> {cond_op,is_ge};
-test_type('==', 2) -> {cond_op,is_eq};
-test_type('/=', 2) -> {cond_op,is_ne};
-test_type('=:=', 2) -> {cond_op,is_eq_exact};
-test_type('=/=', 2) -> {cond_op,is_ne_exact};
-test_type(internal_is_record, 3) -> {cond_op,internal_is_record}.
-
-%% guard_cg_list([Kexpr], Fail, I, Vdb, StackReg, St) ->
-%% {[Ainstr],StackReg,St}.
-
-guard_cg_list(Kes, Fail, I, Vdb, Bef, St0) ->
- {Keis,{Aft,St1}} =
- flatmapfoldl(fun (Ke, {Inta,Sta}) ->
- {Keis,Intb,Stb} =
- guard_cg(Ke, Fail, Vdb, Inta, Sta),
- {comment(Inta) ++ Keis,{Intb,Stb}}
- end, {Bef,St0}, need_heap(Kes, I)),
- {Keis,Aft,St1}.
-
-%% match_fmf(Fun, LastFail, State, [Clause]) -> {Is,Aft,State}.
-%% This is a special flatmapfoldl for match code gen where we
-%% generate a "failure" label for each clause. The last clause uses
-%% an externally generated failure label, LastFail. N.B. We do not
-%% know or care how the failure labels are used.
-
-match_fmf(F, LastFail, St, [H]) ->
- F(H, LastFail, St);
-match_fmf(F, LastFail, St0, [H|T]) ->
- {Fail,St1} = new_label(St0),
- {R,Aft1,St2} = F(H, Fail, St1),
- {Rs,Aft2,St3} = match_fmf(F, LastFail, St2, T),
- {R ++ [{label,Fail}] ++ Rs,sr_merge(Aft1, Aft2),St3};
-match_fmf(_, _, St, []) -> {[],void,St}.
-
-%% call_cg(Func, [Arg], [Ret], Le, Vdb, StackReg, State) ->
-%% {[Ainstr],StackReg,State}.
-%% enter_cg(Func, [Arg], Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
-%% Call and enter first put the arguments into registers and save any
-%% other registers, then clean up and compress the stack and set the
-%% frame size. Finally the actual call is made. Call then needs the
-%% return values filled in.
-
-call_cg({var,V}, As, Rs, Le, Vdb, Bef, St0) ->
- {Sis,Int} = cg_setup_call(As++[{var,V}], Bef, Le#l.i, Vdb),
- %% Put return values in registers.
- Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
- %% Build complete code and final stack/register state.
- Arity = length(As),
- {Frees,Aft} = free_dead(clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb)),
- {comment({call_fun,{var,V},As}) ++ Sis ++ Frees ++ [{call_fun,Arity}],
- Aft,need_stack_frame(St0)};
-call_cg({remote,Mod,Name}, As, Rs, Le, Vdb, Bef, St0)
- when element(1, Mod) == var;
- element(1, Name) == var ->
- {Sis,Int} = cg_setup_call(As++[Mod,Name], Bef, Le#l.i, Vdb),
- %% Put return values in registers.
- Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
- %% Build complete code and final stack/register state.
- Arity = length(As),
- Call = {apply,Arity},
- St = need_stack_frame(St0),
- %%{Call,St1} = build_call(Func, Arity, St0),
- {Frees,Aft} = free_dead(clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb)),
- {Sis ++ Frees ++ [Call],Aft,St};
-call_cg(Func, As, Rs, Le, Vdb, Bef, St0) ->
- {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
- %% Put return values in registers.
- Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
- %% Build complete code and final stack/register state.
- Arity = length(As),
- {Call,St1} = build_call(Func, Arity, St0),
- {Frees,Aft} = free_dead(clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb)),
- {comment({call,Func,As}) ++ Sis ++ Frees ++ Call,Aft,St1}.
-
-build_call({remote,{atom,erlang},{atom,'!'}}, 2, St0) ->
- {[send],need_stack_frame(St0)};
-build_call({remote,{atom,Mod},{atom,Name}}, Arity, St0) ->
- {[{call_ext,Arity,{extfunc,Mod,Name,Arity}}],need_stack_frame(St0)};
-build_call(Name, Arity, St0) when atom(Name) ->
- {Lbl,St1} = local_func_label(Name, Arity, need_stack_frame(St0)),
- {[{call,Arity,{f,Lbl}}],St1}.
-
-free_dead(#sr{stk=Stk0}=Aft) ->
- {Instr,Stk} = free_dead(Stk0, 0, [], []),
- {Instr,Aft#sr{stk=Stk}}.
-
-free_dead([dead|Stk], Y, Instr, StkAcc) ->
- %% Note: kill/1 is equivalent to init/1 (translated by beam_asm).
- %% We use kill/1 to help further optimisation passes.
- free_dead(Stk, Y+1, [{kill,{yy,Y}}|Instr], [free|StkAcc]);
-free_dead([Any|Stk], Y, Instr, StkAcc) ->
- free_dead(Stk, Y+1, Instr, [Any|StkAcc]);
-free_dead([], _, Instr, StkAcc) -> {Instr,reverse(StkAcc)}.
-
-enter_cg({var,V}, As, Le, Vdb, Bef, St0) ->
- {Sis,Int} = cg_setup_call(As++[{var,V}], Bef, Le#l.i, Vdb),
- %% Build complete code and final stack/register state.
- Arity = length(As),
- {comment({call_fun,{var,V},As}) ++ Sis ++ [{call_fun,Arity},return],
- clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
- need_stack_frame(St0)};
-enter_cg({remote,Mod,Name}=Func, As, Le, Vdb, Bef, St0)
- when element(1, Mod) == var;
- element(1, Name) == var ->
- {Sis,Int} = cg_setup_call(As++[Mod,Name], Bef, Le#l.i, Vdb),
- %% Build complete code and final stack/register state.
- Arity = length(As),
- Call = {apply_only,Arity},
- St = need_stack_frame(St0),
- {comment({enter,Func,As}) ++ Sis ++ [Call],
- clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
- St};
-enter_cg(Func, As, Le, Vdb, Bef, St0) ->
- {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
- %% Build complete code and final stack/register state.
- Arity = length(As),
- {Call,St1} = build_enter(Func, Arity, St0),
- {comment({enter,Func,As}) ++ Sis ++ Call,
- clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
- St1}.
-
-build_enter({remote,{atom,erlang},{atom,'!'}}, 2, St0) ->
- {[send,return],need_stack_frame(St0)};
-build_enter({remote,{atom,Mod},{atom,Name}}, Arity, St0) ->
- St1 = case trap_bif(Mod, Name, Arity) of
- true -> need_stack_frame(St0);
- false -> St0
- end,
- {[{call_ext_only,Arity,{extfunc,Mod,Name,Arity}}],St1};
-build_enter(Name, Arity, St0) when is_atom(Name) ->
- {Lbl,St1} = local_func_label(Name, Arity, St0),
- {[{call_only,Arity,{f,Lbl}}],St1}.
-
-%% local_func_label(Name, Arity, State) -> {Label,State'}
-%% Get the function entry label for a local function.
-
-local_func_label(Name, Arity, St0) ->
- Key = {Name,Arity},
- case keysearch(Key, 1, St0#cg.functable) of
- {value,{Key,Label}} ->
- {Label,St0};
- false ->
- {Label,St1} = new_label(St0),
- {Label,St1#cg{functable=[{Key,Label}|St1#cg.functable]}}
- end.
-
-%% need_stack_frame(State) -> State'
-%% Make a note in the state that this function will need a stack frame.
-
-need_stack_frame(#cg{need_frame=true}=St) -> St;
-need_stack_frame(St) -> St#cg{need_frame=true}.
-
-%% trap_bif(Mod, Name, Arity) -> true|false
-%% Trap bifs that need a stack frame.
-
-trap_bif(erlang, '!', 2) -> true;
-trap_bif(erlang, link, 1) -> true;
-trap_bif(erlang, unlink, 1) -> true;
-trap_bif(erlang, monitor_node, 2) -> true;
-trap_bif(erlang, group_leader, 2) -> true;
-trap_bif(erlang, exit, 2) -> true;
-trap_bif(_, _, _) -> false.
-
-%% bif_cg(Bif, [Arg], [Ret], Le, Vdb, StackReg, State) ->
-%% {[Ainstr],StackReg,State}.
-
-bif_cg(dsetelement, [Index0,Tuple0,New0], _Rs, Le, Vdb, Bef, St0) ->
- [New,Tuple,{integer,Index1}] = cg_reg_args([New0,Tuple0,Index0], Bef),
- Index = Index1-1,
- {[{set_tuple_element,New,Tuple,Index}],
- clear_dead(Bef, Le#l.i, Vdb), St0};
-bif_cg({make_fun,Func,Arity,Index,Uniq}, As, Rs, Le, Vdb, Bef, St0) ->
- %% This behaves more like a function call.
- {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
- Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
- {FuncLbl,St1} = local_func_label(Func, Arity, St0),
- MakeFun = case St0#cg.new_funs of
- true -> {make_fun2,{f,FuncLbl},Index,Uniq,length(As)};
- false -> {make_fun,{f,FuncLbl},Uniq,length(As)}
- end,
- {comment({make_fun,{Func,Arity,Uniq},As}) ++ Sis ++
- [MakeFun],
- clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb),
- St1};
-bif_cg(Bif, As, [{var,V}], Le, Vdb, Bef, St0) ->
- Ars = cg_reg_args(As, Bef),
-
- %% If we are inside a catch, we must save everything that will
- %% be alive after the catch (because the BIF might fail and there
- %% will be a jump to the code after the catch).
- %% Currently, we are somewhat pessimistic in
- %% that we save any variable that will be live after this BIF call.
-
- {Sis,Int0} =
- case St0#cg.in_catch of
- true -> adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb);
- false -> {[],Bef}
- end,
-
- Int1 = clear_dead(Int0, Le#l.i, Vdb),
- Reg = put_reg(V, Int1#sr.reg),
- Int = Int1#sr{reg=Reg},
- Dst = fetch_reg(V, Reg),
- {Sis ++ [{bif,Bif,bif_fail(St0#cg.btype, St0#cg.bfail, length(Ars)),Ars,Dst}],
- clear_dead(Int, Le#l.i, Vdb), St0}.
-
-bif_fail(_, _, 0) -> nofail;
-bif_fail(exit, _, _) -> {f,0};
-bif_fail(fail, Fail, _) -> {f,Fail}.
-
-%% recv_loop_cg(TimeOut, ReceiveVar, ReceiveMatch, TimeOutExprs,
-%% [Ret], Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
-
-recv_loop_cg(Te, Rvar, Rm, Tes, Rs, Le, Vdb, Bef, St0) ->
- {Sis,Int0} = adjust_stack(Bef, Le#l.i, Le#l.i, Vdb),
- Int1 = Int0#sr{reg=clear_regs(Int0#sr.reg)},
- %% Get labels.
- {Rl,St1} = new_label(St0),
- {Tl,St2} = new_label(St1),
- {Bl,St3} = new_label(St2),
- St4 = St3#cg{break=Bl,recv=Rl}, %Set correct receive labels
- {Ris,Raft,St5} = cg_recv_mesg(Rvar, Rm, Tl, Int1, St4),
- {Wis,Taft,St6} = cg_recv_wait(Te, Tes, Le#l.i, Int1, St5),
- Int2 = sr_merge(Raft, Taft), %Merge stack/registers
- Reg = load_vars(Rs, Int2#sr.reg),
- {Sis ++ Ris ++ [{label,Tl}] ++ Wis ++ [{label,Bl}],
- clear_dead(Int2#sr{reg=Reg}, Le#l.i, Vdb),
- St6#cg{break=St0#cg.break,recv=St0#cg.recv}}.
-
-%% cg_recv_mesg( ) -> {[Ainstr],Aft,St}.
-
-cg_recv_mesg({var,R}, Rm, Tl, Bef, St0) ->
- Int0 = Bef#sr{reg=put_reg(R, Bef#sr.reg)},
- Ret = fetch_reg(R, Int0#sr.reg),
- %% Int1 = clear_dead(Int0, I, Rm#l.vdb),
- Int1 = Int0,
- {Mis,Int2,St1} = match_cg(Rm, none, Int1, St0),
- {[{'%live',0},{label,St1#cg.recv},{loop_rec,{f,Tl},Ret}|Mis],Int2,St1}.
-
-%% cg_recv_wait(Te, Tes, I, Vdb, Int2, St3) -> {[Ainstr],Aft,St}.
-
-cg_recv_wait({atom,infinity}, Tes, I, Bef, St0) ->
- %% We know that the 'after' body will never be executed.
- %% But to keep the stack and register information up to date,
- %% we will generate the code for the 'after' body, and then discard it.
- Int1 = clear_dead(Bef, I, Tes#l.vdb),
- {_,Int2,St1} = cg_block(Tes#l.ke, Tes#l.i, Tes#l.vdb,
- Int1#sr{reg=clear_regs(Int1#sr.reg)}, St0),
- {[{wait,{f,St1#cg.recv}}],Int2,St1};
-cg_recv_wait({integer,0}, Tes, _I, Bef, St0) ->
- {Tis,Int,St1} = cg_block(Tes#l.ke, Tes#l.i, Tes#l.vdb, Bef, St0),
- {[timeout|Tis],Int,St1};
-cg_recv_wait(Te, Tes, I, Bef, St0) ->
- Reg = cg_reg_arg(Te, Bef),
- %% Must have empty registers here! Bug if anything in registers.
- Int0 = clear_dead(Bef, I, Tes#l.vdb),
- {Tis,Int,St1} = cg_block(Tes#l.ke, Tes#l.i, Tes#l.vdb,
- Int0#sr{reg=clear_regs(Int0#sr.reg)}, St0),
- {[{wait_timeout,{f,St1#cg.recv},Reg},timeout] ++ Tis,Int,St1}.
-
-%% recv_next_cg(Le, Vdb, StackReg, St) -> {[Ainstr],StackReg,St}.
-%% Use adjust stack to clear stack, but only need it for Aft.
-
-recv_next_cg(Le, Vdb, Bef, St) ->
- {Sis,Aft} = adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb),
- {[{loop_rec_end,{f,St#cg.recv}}] ++ Sis,Aft,St}. %Joke
-
-%% try_cg(TryBlock, [BodyVar], TryBody, [ExcpVar], TryHandler, [Ret],
-%% Le, Vdb, StackReg, St) -> {[Ainstr],StackReg,St}.
-
-try_cg(Ta, Vs, Tb, Evs, Th, Rs, Le, Vdb, Bef, St0) ->
- {B,St1} = new_label(St0), %Body label
- {H,St2} = new_label(St1), %Handler label
- {E,St3} = new_label(St2), %End label
- TryTag = Ta#l.i,
- Int1 = Bef#sr{stk=put_catch(TryTag, Bef#sr.stk)},
- TryReg = fetch_stack({catch_tag,TryTag}, Int1#sr.stk),
- {Ais,Int2,St4} = cg(Ta, Vdb, Int1, St3#cg{break=B,in_catch=true}),
- Int3 = Int2#sr{stk=drop_catch(TryTag, Int2#sr.stk)},
- St5 = St4#cg{break=E,in_catch=St3#cg.in_catch},
- {Bis,Baft,St6} = cg(Tb, Vdb, Int3#sr{reg=load_vars(Vs, Int3#sr.reg)}, St5),
- {His,Haft,St7} = cg(Th, Vdb, Int3#sr{reg=load_vars(Evs, Int3#sr.reg)}, St6),
- Int4 = sr_merge(Baft, Haft), %Merge stack/registers
- Aft = Int4#sr{reg=load_vars(Rs, Int4#sr.reg)},
- {[{'try',TryReg,{f,H}}] ++ Ais ++
- [{label,B},{try_end,TryReg}] ++ Bis ++
- [{label,H},{try_case,TryReg}] ++ His ++
- [{label,E}],
- clear_dead(Aft, Le#l.i, Vdb),
- St7#cg{break=St0#cg.break}}.
-
-%% catch_cg(CatchBlock, Ret, Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
-
-catch_cg(C, {var,R}, Le, Vdb, Bef, St0) ->
- {B,St1} = new_label(St0),
- CatchTag = Le#l.i,
- Int1 = Bef#sr{stk=put_catch(CatchTag, Bef#sr.stk)},
- CatchReg = fetch_stack({catch_tag,CatchTag}, Int1#sr.stk),
- {Cis,Int2,St2} = cg_block(C, Le#l.i, Le#l.vdb, Int1,
- St1#cg{break=B,in_catch=true}),
- Aft = Int2#sr{reg=load_reg(R, 0, Int2#sr.reg),
- stk=drop_catch(CatchTag, Int2#sr.stk)},
- {[{'catch',CatchReg,{f,B}}] ++ Cis ++
- [{label,B},{catch_end,CatchReg}],
- clear_dead(Aft, Le#l.i, Vdb),
- St2#cg{break=St1#cg.break,in_catch=St1#cg.in_catch}}.
-
-%% set_cg([Var], Constr, Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
-%% We have to be careful how a 'set' works. First the structure is
-%% built, then it is filled and finally things can be cleared. The
-%% annotation must reflect this and make sure that the return
-%% variable is allocated first.
-%%
-%% put_list for constructing a cons is an atomic instruction
-%% which can safely resuse one of the source registers as target.
-%% Also binaries can reuse a source register as target.
-
-set_cg([{var,R}], {cons,Es}, Le, Vdb, Bef, St) ->
- [S1,S2] = map(fun ({var,V}) -> fetch_var(V, Bef);
- (Other) -> Other
- end, Es),
- Int0 = clear_dead(Bef, Le#l.i, Vdb),
- Int1 = Int0#sr{reg=put_reg(R, Int0#sr.reg)},
- Ret = fetch_reg(R, Int1#sr.reg),
- {[{put_list,S1,S2,Ret}], Int1, St};
-set_cg([{var,R}], {old_binary,Segs}, Le, Vdb, Bef, St) ->
- Fail = bif_fail(St#cg.btype, St#cg.bfail, 42),
- PutCode = cg_bin_put(Segs, Fail, Bef),
- Code = cg_binary_old(PutCode),
- Int0 = clear_dead(Bef, Le#l.i, Vdb),
- Aft = Int0#sr{reg=put_reg(R, Int0#sr.reg)},
- Ret = fetch_reg(R, Aft#sr.reg),
- {Code ++ [{bs_final,Fail,Ret}],Aft,St};
-set_cg([{var,R}], {binary,Segs}, Le, Vdb, Bef, #cg{in_catch=InCatch}=St) ->
- Int0 = Bef#sr{reg=put_reg(R, Bef#sr.reg)},
- Target = fetch_reg(R, Int0#sr.reg),
- Fail = bif_fail(St#cg.btype, St#cg.bfail, 42),
- Temp = find_scratch_reg(Int0#sr.reg),
- PutCode = cg_bin_put(Segs, Fail, Bef),
- {Sis,Int1} =
- case InCatch of
- true -> adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb);
- false -> {[],Int0}
- end,
- Aft = clear_dead(Int1, Le#l.i, Vdb),
- Code = cg_binary(PutCode, Target, Temp, Fail, Aft),
- {Sis++Code,Aft,St};
-set_cg([{var,R}], Con, Le, Vdb, Bef, St) ->
- %% Find a place for the return register first.
- Int = Bef#sr{reg=put_reg(R, Bef#sr.reg)},
- Ret = fetch_reg(R, Int#sr.reg),
- Ais = case Con of
- {tuple,Es} ->
- [{put_tuple,length(Es),Ret}] ++ cg_build_args(Es, Bef);
- {var,V} -> % Normally removed by kernel optimizer.
- [{move,fetch_var(V, Int),Ret}];
- {string,Str} ->
- [{put_string,length(Str),{string,Str},Ret}];
- Other ->
- [{move,Other,Ret}]
- end,
- {Ais,clear_dead(Int, Le#l.i, Vdb),St};
-set_cg([], {binary,Segs}, Le, Vdb, Bef, St) ->
- Fail = bif_fail(St#cg.btype, St#cg.bfail, 42),
- Target = find_scratch_reg(Bef#sr.reg),
- Temp = find_scratch_reg(put_reg(Target, Bef#sr.reg)),
- PutCode = cg_bin_put(Segs, Fail, Bef),
- Code = cg_binary(PutCode, Target, Temp, Fail, Bef),
- Aft = clear_dead(Bef, Le#l.i, Vdb),
- {Code,Aft,St};
-set_cg([], {old_binary,Segs}, Le, Vdb, Bef, St) ->
- Fail = bif_fail(St#cg.btype, St#cg.bfail, 42),
- PutCode = cg_bin_put(Segs, Fail, Bef),
- Ais0 = cg_binary_old(PutCode),
- Ret = find_scratch_reg(Bef#sr.reg),
- Ais = Ais0 ++ [{bs_final,Fail,Ret}],
- {Ais,clear_dead(Bef, Le#l.i, Vdb),St};
-set_cg([], _, Le, Vdb, Bef, St) ->
- %% This should have been stripped by compiler, just cleanup.
- {[],clear_dead(Bef, Le#l.i, Vdb), St}.
-
-
-%%%
-%%% Code generation for constructing binaries.
-%%%
-
-cg_binary(PutCode, Target, Temp, Fail, Bef) ->
- SzCode = cg_binary_size(PutCode, Target, Temp, Fail),
- MaxRegs = max_reg(Bef#sr.reg),
- Code = SzCode ++ [{bs_init2,Fail,Target,MaxRegs,{field_flags,[]},Target}|PutCode],
- cg_bin_opt(Code).
-
-cg_binary_size(PutCode, Target, Temp, Fail) ->
- Szs = cg_binary_size_1(PutCode, 0, []),
- cg_binary_size_expr(Szs, Target, Temp, Fail).
-
-cg_binary_size_1([{_Put,_Fail,S,U,_Flags,Src}|T], Bits, Acc) ->
- cg_binary_size_2(S, U, Src, T, Bits, Acc);
-cg_binary_size_1([], Bits, Acc) ->
- Bytes = Bits div 8,
- RemBits = Bits rem 8,
- Res = sort([{1,{integer,RemBits}},{8,{integer,Bytes}}|Acc]),
- cg_binary_size_3(Res).
-
-cg_binary_size_2({integer,N}, U, _, Next, Bits, Acc) ->
- cg_binary_size_1(Next, Bits+N*U, Acc);
-cg_binary_size_2({atom,all}, 8, E, Next, Bits, Acc) ->
- cg_binary_size_1(Next, Bits, [{8,{size,E}}|Acc]);
-cg_binary_size_2(Reg, 1, _, Next, Bits, Acc) ->
- cg_binary_size_1(Next, Bits, [{1,Reg}|Acc]);
-cg_binary_size_2(Reg, 8, _, Next, Bits, Acc) ->
- cg_binary_size_1(Next, Bits, [{8,Reg}|Acc]);
-cg_binary_size_2(Reg, U, _, Next, Bits, Acc) ->
- cg_binary_size_1(Next, Bits, [{1,{'*',Reg,U}}|Acc]).
-
-cg_binary_size_3([{_,{integer,0}}|T]) ->
- cg_binary_size_3(T);
-cg_binary_size_3([{U,S1},{U,S2}|T]) ->
- {L0,Rest} = cg_binary_size_4(T, U, []),
- L = [S1,S2|L0],
- [{U,L}|cg_binary_size_3(Rest)];
-cg_binary_size_3([{U,S}|T]) ->
- [{U,[S]}|cg_binary_size_3(T)];
-cg_binary_size_3([]) -> [].
-
-cg_binary_size_4([{U,S}|T], U, Acc) ->
- cg_binary_size_4(T, U, [S|Acc]);
-cg_binary_size_4(T, _, Acc) ->
- {Acc,T}.
-
-%% cg_binary_size_expr/4
-%% Generate code for calculating the resulting size of a binary.
-cg_binary_size_expr(Sizes, Target, Temp, Fail) ->
- cg_binary_size_expr_1(Sizes, Target, Temp, Fail,
- [{move,{integer,0},Target}]).
-
-cg_binary_size_expr_1([{1,E0}|T], Target, Temp, Fail, Acc) ->
- E1 = cg_gen_binsize(E0, Target, Temp, Fail, Acc),
- E = [{bs_bits_to_bytes,Fail,Target,Target}|E1],
- cg_binary_size_expr_1(T, Target, Temp, Fail, E);
-cg_binary_size_expr_1([{8,E0}], Target, Temp, Fail, Acc) ->
- E = cg_gen_binsize(E0, Target, Temp, Fail, Acc),
- reverse(E);
-cg_binary_size_expr_1([], _, _, _, Acc) -> reverse(Acc).
-
-cg_gen_binsize([{'*',A,B}|T], Target, Temp, Fail, Acc) ->
- cg_gen_binsize(T, Target, Temp, Fail,
- [{bs_add,Fail,[Target,A,B],Target}|Acc]);
-cg_gen_binsize([{size,B}|T], Target, Temp, Fail, Acc) ->
- cg_gen_binsize([Temp|T], Target, Temp, Fail,
- [{bif,size,Fail,[B],Temp}|Acc]);
-cg_gen_binsize([E0|T], Target, Temp, Fail, Acc) ->
- cg_gen_binsize(T, Target, Temp, Fail,
- [{bs_add,Fail,[Target,E0,1],Target}|Acc]);
-cg_gen_binsize([], _, _, _, Acc) -> Acc.
-
-%% cg_bin_opt(Code0) -> Code
-%% Optimize the size calculations for binary construction.
-
-cg_bin_opt([{move,{integer,0},D},{bs_add,_,[D,{integer,_}=S,1],Dst}|Is]) ->
- cg_bin_opt([{move,S,Dst}|Is]);
-cg_bin_opt([{move,{integer,0},D},{bs_add,Fail,[D,S,U],Dst}|Is]) ->
- cg_bin_opt([{bs_add,Fail,[{integer,0},S,U],Dst}|Is]);
-cg_bin_opt([{move,{integer,Bytes},D},{bs_init2,Fail,D,Regs0,Flags,D}|Is]) ->
- Regs = cg_bo_newregs(Regs0, D),
- cg_bin_opt([{bs_init2,Fail,Bytes,Regs,Flags,D}|Is]);
-cg_bin_opt([{move,Src,D},{bs_init2,Fail,D,Regs0,Flags,D}|Is]) ->
- Regs = cg_bo_newregs(Regs0, D),
- cg_bin_opt([{bs_init2,Fail,Src,Regs,Flags,D}|Is]);
-cg_bin_opt([{move,Src,Dst},{bs_bits_to_bytes,Fail,Dst,Dst}|Is]) ->
- cg_bin_opt([{bs_bits_to_bytes,Fail,Src,Dst}|Is]);
-cg_bin_opt([{move,Src1,Dst},{bs_add,Fail,[Dst,Src2,U],Dst}|Is]) ->
- cg_bin_opt([{bs_add,Fail,[Src1,Src2,U],Dst}|Is]);
-cg_bin_opt([{bs_bits_to_bytes,Fail,{integer,N},_}|Is0]) when N rem 8 =/= 0 ->
- case Fail of
- {f,0} ->
- Is = [{move,{atom,badarg},{x,0}},
- {call_ext_only,1,{extfunc,erlang,error,1}}|Is0],
- cg_bin_opt(Is);
- _ ->
- cg_bin_opt([{jump,Fail}|Is0])
- end;
-cg_bin_opt([I|Is]) ->
- [I|cg_bin_opt(Is)];
-cg_bin_opt([]) -> [].
-
-cg_bo_newregs(R, {x,X}) when R-1 =:= X -> R-1;
-cg_bo_newregs(R, _) -> R.
-
-%% Common for new and old binary code generation.
-
-cg_bin_put({bin_seg,S0,U,T,Fs,[E0,Next]}, Fail, Bef) ->
- S1 = case S0 of
- {var,Sv} -> fetch_var(Sv, Bef);
- _ -> S0
- end,
- E1 = case E0 of
- {var,V} -> fetch_var(V, Bef);
- Other -> Other
- end,
- Op = case T of
- integer -> bs_put_integer;
- binary -> bs_put_binary;
- float -> bs_put_float
- end,
- [{Op,Fail,S1,U,{field_flags,Fs},E1}|cg_bin_put(Next, Fail, Bef)];
-cg_bin_put(bin_end, _, _) -> [].
-
-%% Old style.
-
-cg_binary_old(PutCode) ->
- [cg_bs_init(PutCode)] ++ need_bin_buf(PutCode).
-
-cg_bs_init(Code) ->
- {Size,Fs} = foldl(fun ({_,_,{integer,N},U,_,_}, {S,Fs}) ->
- {S + N*U,Fs};
- (_, {S,_}) ->
- {S,[]}
- end, {0,[exact]}, Code),
- {bs_init,(Size+7) div 8,{field_flags,Fs}}.
-
-need_bin_buf(Code0) ->
- {Code1,F,H} = foldr(fun ({_,_,{integer,N},U,_,_}=Bs, {Code,F,H}) ->
- {[Bs|Code],F,H + N*U};
- ({_,_,_,_,_,_}=Bs, {Code,F,H}) ->
- {[Bs|need_bin_buf_need(H, F, Code)],true,0}
- end, {[],false,0}, Code0),
- need_bin_buf_need(H, F, Code1).
-
-need_bin_buf_need(0, false, Rest) -> Rest;
-need_bin_buf_need(H, _, Rest) -> [{bs_need_buf,H}|Rest].
-
-cg_build_args(As, Bef) ->
- map(fun ({var,V}) -> {put,fetch_var(V, Bef)};
- (Other) -> {put,Other}
- end, As).
-
-%% return_cg([Val], Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
-%% break_cg([Val], Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
-%% These are very simple, just put return/break values in registers
-%% from 0, then return/break. Use the call setup to clean up stack,
-%% but must clear registers to ensure sr_merge works correctly.
-
-return_cg(Rs, Le, Vdb, Bef, St) ->
- {Ms,Int} = cg_setup_call(Rs, Bef, Le#l.i, Vdb),
- {comment({return,Rs}) ++ Ms ++ [return],
- Int#sr{reg=clear_regs(Int#sr.reg)},St}.
-
-break_cg(Bs, Le, Vdb, Bef, St) ->
- {Ms,Int} = cg_setup_call(Bs, Bef, Le#l.i, Vdb),
- {comment({break,Bs}) ++ Ms ++ [{jump,{f,St#cg.break}}],
- Int#sr{reg=clear_regs(Int#sr.reg)},St}.
-
-%% cg_reg_arg(Arg0, Info) -> Arg
-%% cg_reg_args([Arg0], Info) -> [Arg]
-%% Convert argument[s] into registers. Literal values are returned unchanged.
-
-cg_reg_args(As, Bef) -> [cg_reg_arg(A, Bef) || A <- As].
-
-cg_reg_arg({var,V}, Bef) -> fetch_var(V, Bef);
-cg_reg_arg(Literal, _) -> Literal.
-
-%% cg_setup_call([Arg], Bef, Cur, Vdb) -> {[Instr],Aft}.
-%% Do the complete setup for a call/enter.
-
-cg_setup_call(As, Bef, I, Vdb) ->
- {Ms,Int0} = cg_call_args(As, Bef, I, Vdb),
- %% Have set up arguments, can now clean up, compress and save to stack.
- Int1 = Int0#sr{stk=clear_dead_stk(Int0#sr.stk, I, Vdb),res=[]},
- {Sis,Int2} = adjust_stack(Int1, I, I+1, Vdb),
- {Ms ++ Sis ++ [{'%live',length(As)}],Int2}.
-
-%% cg_call_args([Arg], SrState) -> {[Instr],SrState}.
-%% Setup the arguments to a call/enter/bif. Put the arguments into
-%% consecutive registers starting at {x,0} moving any data which
-%% needs to be saved. Return a modified SrState structure with the
-%% new register contents. N.B. the resultant register info will
-%% contain non-variable values when there are non-variable values.
-%%
-%% This routine is complicated by unsaved values in x registers.
-%% We'll move away any unsaved values that are in the registers
-%% to be overwritten by the arguments.
-
-cg_call_args(As, Bef, I, Vdb) ->
- Regs0 = load_arg_regs(Bef#sr.reg, As),
- Unsaved = unsaved_registers(Regs0, Bef#sr.stk, I, I+1, Vdb),
- {UnsavedMoves,Regs} = move_unsaved(Unsaved, Bef#sr.reg, Regs0),
- Moves0 = gen_moves(As, Bef),
- Moves = order_moves(Moves0, find_scratch_reg(Regs)),
- {UnsavedMoves ++ Moves,Bef#sr{reg=Regs}}.
-
-%% load_arg_regs([Reg], Arguments) -> [Reg]
-%% Update the register descriptor to include the arguments (from {x,0}
-%% and upwards). Values in argument register are overwritten.
-%% Values in x registers above the arguments are preserved.
-
-load_arg_regs(Regs, As) -> load_arg_regs(Regs, As, 0).
-
-load_arg_regs([_|Rs], [{var,V}|As], I) -> [{I,V}|load_arg_regs(Rs, As, I+1)];
-load_arg_regs([_|Rs], [A|As], I) -> [{I,A}|load_arg_regs(Rs, As, I+1)];
-load_arg_regs([], [{var,V}|As], I) -> [{I,V}|load_arg_regs([], As, I+1)];
-load_arg_regs([], [A|As], I) -> [{I,A}|load_arg_regs([], As, I+1)];
-load_arg_regs(Rs, [], _) -> Rs.
-
-%% Returns the variables must be saved and are currently in the
-%% x registers that are about to be overwritten by the arguments.
-
-unsaved_registers(Regs, Stk, Fb, Lf, Vdb) ->
- [V || {V,F,L} <- Vdb,
- F < Fb,
- L >= Lf,
- not on_stack(V, Stk),
- not in_reg(V, Regs)].
-
-in_reg(V, Regs) -> keymember(V, 2, Regs).
-
-%% Move away unsaved variables from the registers that are to be
-%% overwritten by the arguments.
-move_unsaved(Vs, OrigRegs, NewRegs) ->
- move_unsaved(Vs, OrigRegs, NewRegs, []).
-
-move_unsaved([V|Vs], OrigRegs, NewRegs0, Acc) ->
- NewRegs = put_reg(V, NewRegs0),
- Src = fetch_reg(V, OrigRegs),
- Dst = fetch_reg(V, NewRegs),
- move_unsaved(Vs, OrigRegs, NewRegs, [{move,Src,Dst}|Acc]);
-move_unsaved([], _, Regs, Acc) -> {Acc,Regs}.
-
-%% gen_moves(As, Sr)
-%% Generate the basic move instruction to move the arguments
-%% to their proper registers. The list will be sorted on
-%% destinations. (I.e. the move to {x,0} will be first --
-%% see the comment to order_moves/2.)
-
-gen_moves(As, Sr) -> gen_moves(As, Sr, 0, []).
-
-gen_moves([{var,V}|As], Sr, I, Acc) ->
- case fetch_var(V, Sr) of
- {x,I} -> gen_moves(As, Sr, I+1, Acc);
- Reg -> gen_moves(As, Sr, I+1, [{move,Reg,{x,I}}|Acc])
- end;
-gen_moves([A|As], Sr, I, Acc) ->
- gen_moves(As, Sr, I+1, [{move,A,{x,I}}|Acc]);
-gen_moves([], _, _, Acc) -> lists:keysort(3, Acc).
-
-%% order_moves([Move], ScratchReg) -> [Move]
-%% Orders move instruction so that source registers are not
-%% destroyed before they are used. If there are cycles
-%% (such as {move,{x,0},{x,1}}, {move,{x,1},{x,1}}),
-%% the scratch register is used to break up the cycle.
-%% If possible, the first move of the input list is placed
-%% last in the result list (to make the move to {x,0} occur
-%% just before the call to allow the Beam loader to coalesce
-%% the instructions).
-
-order_moves(Ms, Scr) -> order_moves(Ms, Scr, []).
-
-order_moves([{move,_,_}=M|Ms0], ScrReg, Acc0) ->
- {Chain,Ms} = collect_chain(Ms0, [M], ScrReg),
- Acc = reverse(Chain, Acc0),
- order_moves(Ms, ScrReg, Acc);
-order_moves([], _, Acc) -> Acc.
-
-collect_chain(Ms, Path, ScrReg) ->
- collect_chain(Ms, Path, [], ScrReg).
-
-collect_chain([{move,Src,Same}=M|Ms0], [{move,Same,_}|_]=Path, Others, ScrReg) ->
- case keysearch(Src, 3, Path) of
- {value,_} -> %We have a cycle.
- {break_up_cycle(M, Path, ScrReg),reverse(Others, Ms0)};
- false ->
- collect_chain(reverse(Others, Ms0), [M|Path], [], ScrReg)
- end;
-collect_chain([M|Ms], Path, Others, ScrReg) ->
- collect_chain(Ms, Path, [M|Others], ScrReg);
-collect_chain([], Path, Others, _) ->
- {Path,Others}.
-
-break_up_cycle({move,Src,_}=M, Path, ScrReg) ->
- [{move,ScrReg,Src},M|break_up_cycle1(Src, Path, ScrReg)].
-
-break_up_cycle1(Dst, [{move,Src,Dst}|Path], ScrReg) ->
- [{move,Src,ScrReg}|Path];
-break_up_cycle1(Dst, [M|Path], LastMove) ->
- [M|break_up_cycle1(Dst, Path, LastMove)].
-
-%% clear_dead(Sr, Until, Vdb) -> Aft.
-%% Remove all variables in Sr which have died AT ALL so far.
-
-clear_dead(Sr, Until, Vdb) ->
- Sr#sr{reg=clear_dead_reg(Sr, Until, Vdb),
- stk=clear_dead_stk(Sr#sr.stk, Until, Vdb)}.
-
-clear_dead_reg(Sr, Until, Vdb) ->
- Reg = map(fun ({I,V}) ->
- case vdb_find(V, Vdb) of
- {V,_,L} when L > Until -> {I,V};
- _ -> free %Remove anything else
- end;
- ({reserved,I,V}) -> {reserved,I,V};
- (free) -> free
- end, Sr#sr.reg),
- reserve(Sr#sr.res, Reg, Sr#sr.stk).
-
-clear_dead_stk(Stk, Until, Vdb) ->
- map(fun ({V}) ->
- case vdb_find(V, Vdb) of
- {V,_,L} when L > Until -> {V};
- _ -> dead %Remove anything else
- end;
- (free) -> free;
- (dead) -> dead
- end, Stk).
-
-%% sr_merge(Sr1, Sr2) -> Sr.
-%% Merge two stack/register states keeping the longest of both stack
-%% and register. Perform consistency check on both, elements must be
-%% the same. Allow frame size 'void' to make easy creation of
-%% "empty" frame.
-
-sr_merge(#sr{reg=R1,stk=S1,res=[]}, #sr{reg=R2,stk=S2,res=[]}) ->
- #sr{reg=longest(R1, R2),stk=longest(S1, S2),res=[]};
-sr_merge(void, S2) -> S2#sr{res=[]};
-sr_merge(S1, void) -> S1#sr{res=[]}.
-
-longest([H|T1], [H|T2]) -> [H|longest(T1, T2)];
-longest([dead|T1], [free|T2]) -> [dead|longest(T1, T2)];
-longest([free|T1], [dead|T2]) -> [dead|longest(T1, T2)];
-longest([dead|T1], []) -> [dead|T1];
-longest([], [dead|T2]) -> [dead|T2];
-longest([free|T1], []) -> [free|T1];
-longest([], [free|T2]) -> [free|T2];
-longest([], []) -> [].
-
-%% adjust_stack(Bef, FirstBefore, LastFrom, Vdb) -> {[Ainstr],Aft}.
-%% Do complete stack adjustment by compressing stack and adding
-%% variables to be saved. Try to optimise ordering on stack by
-%% having reverse order to their lifetimes.
-%%
-%% In Beam, there is a fixed stack frame and no need to do stack compression.
-
-adjust_stack(Bef, Fb, Lf, Vdb) ->
- Stk0 = Bef#sr.stk,
- {Stk1,Saves} = save_stack(Stk0, Fb, Lf, Vdb),
- {saves(Saves, Bef#sr.reg, Stk1),
- Bef#sr{stk=Stk1}}.
-
-%% save_stack(Stack, FirstBefore, LastFrom, Vdb) -> {[SaveVar],NewStack}.
-%% Save variables which are used past current point and which are not
-%% already on the stack.
-
-save_stack(Stk0, Fb, Lf, Vdb) ->
- %% New variables that are in use but not on stack.
- New = [ {V,F,L} || {V,F,L} <- Vdb,
- F < Fb,
- L >= Lf,
- not on_stack(V, Stk0) ],
- %% Add new variables that are not just dropped immediately.
- %% N.B. foldr works backwards from the end!!
- Saves = [ V || {V,_,_} <- keysort(3, New) ],
- Stk1 = foldr(fun (V, Stk) -> put_stack(V, Stk) end, Stk0, Saves),
- {Stk1,Saves}.
-
-%% saves([SaveVar], Reg, Stk) -> [{move,Reg,Stk}].
-%% Generate move instructions to save variables onto stack. The
-%% stack/reg info used is that after the new stack has been made.
-
-saves(Ss, Reg, Stk) ->
- Res = map(fun (V) ->
- {move,fetch_reg(V, Reg),fetch_stack(V, Stk)}
- end, Ss),
- Res.
-
-%% comment(C) -> ['%'{C}].
-
-%comment(C) -> [{'%',C}].
-comment(_) -> [].
-
-%% fetch_var(VarName, StkReg) -> r{R} | sp{Sp}.
-%% find_var(VarName, StkReg) -> ok{r{R} | sp{Sp}} | error.
-%% Fetch/find a variable in either the registers or on the
-%% stack. Fetch KNOWS it's there.
-
-fetch_var(V, Sr) ->
- case find_reg(V, Sr#sr.reg) of
- {ok,R} -> R;
- error -> fetch_stack(V, Sr#sr.stk)
- end.
-
-% find_var(V, Sr) ->
-% case find_reg(V, Sr#sr.reg) of
-% {ok,R} -> {ok,R};
-% error ->
-% case find_stack(V, Sr#sr.stk) of
-% {ok,S} -> {ok,S};
-% error -> error
-% end
-% end.
-
-load_vars(Vs, Regs) ->
- foldl(fun ({var,V}, Rs) -> put_reg(V, Rs) end, Regs, Vs).
-
-%% put_reg(Val, Regs) -> Regs.
-%% load_reg(Val, Reg, Regs) -> Regs.
-%% free_reg(Val, Regs) -> Regs.
-%% find_reg(Val, Regs) -> ok{r{R}} | error.
-%% fetch_reg(Val, Regs) -> r{R}.
-%% Functions to interface the registers.
-%% put_reg puts a value into a free register,
-%% load_reg loads a value into a fixed register
-%% free_reg frees a register containing a specific value.
-
-% put_regs(Vs, Rs) -> foldl(fun put_reg/2, Rs, Vs).
-
-put_reg(V, Rs) -> put_reg_1(V, Rs, 0).
-
-put_reg_1(V, [free|Rs], I) -> [{I,V}|Rs];
-put_reg_1(V, [{reserved,I,V}|Rs], I) -> [{I,V}|Rs];
-put_reg_1(V, [R|Rs], I) -> [R|put_reg_1(V, Rs, I+1)];
-put_reg_1(V, [], I) -> [{I,V}].
-
-load_reg(V, R, Rs) -> load_reg_1(V, R, Rs, 0).
-
-load_reg_1(V, I, [_|Rs], I) -> [{I,V}|Rs];
-load_reg_1(V, I, [R|Rs], C) -> [R|load_reg_1(V, I, Rs, C+1)];
-load_reg_1(V, I, [], I) -> [{I,V}];
-load_reg_1(V, I, [], C) -> [free|load_reg_1(V, I, [], C+1)].
-
-% free_reg(V, [{I,V}|Rs]) -> [free|Rs];
-% free_reg(V, [R|Rs]) -> [R|free_reg(V, Rs)];
-% free_reg(V, []) -> [].
-
-fetch_reg(V, [{I,V}|_]) -> {x,I};
-fetch_reg(V, [_|SRs]) -> fetch_reg(V, SRs).
-
-find_reg(V, [{I,V}|_]) -> {ok,{x,I}};
-find_reg(V, [_|SRs]) -> find_reg(V, SRs);
-find_reg(_, []) -> error.
-
-%% For the bit syntax, we need a scratch register if we are constructing
-%% a binary that will not be used.
-
-find_scratch_reg(Rs) -> find_scratch_reg(Rs, 0).
-
-find_scratch_reg([free|_], I) -> {x,I};
-find_scratch_reg([_|Rs], I) -> find_scratch_reg(Rs, I+1);
-find_scratch_reg([], I) -> {x,I}.
-
-%%copy_reg(Val, R, Regs) -> load_reg(Val, R, Regs).
-%%move_reg(Val, R, Regs) -> load_reg(Val, R, free_reg(Val, Regs)).
-
-%%clear_regs(Regs) -> map(fun (R) -> free end, Regs).
-clear_regs(_) -> [].
-
-max_reg(Regs) ->
- foldl(fun ({I,_}, _) -> I;
- (_, Max) -> Max end,
- -1, Regs) + 1.
-
-%% put_stack(Val, [{Val}]) -> [{Val}].
-%% fetch_stack(Var, Stk) -> sp{S}.
-%% find_stack(Var, Stk) -> ok{sp{S}} | error.
-%% Functions to interface the stack.
-
-put_stack(Val, []) -> [{Val}];
-put_stack(Val, [dead|Stk]) -> [{Val}|Stk];
-put_stack(Val, [free|Stk]) -> [{Val}|Stk];
-put_stack(Val, [NotFree|Stk]) -> [NotFree|put_stack(Val, Stk)].
-
-put_stack_carefully(Val, Stk0) ->
- case catch put_stack_carefully1(Val, Stk0) of
- error -> error;
- Stk1 when list(Stk1) -> Stk1
- end.
-
-put_stack_carefully1(_, []) -> throw(error);
-put_stack_carefully1(Val, [dead|Stk]) -> [{Val}|Stk];
-put_stack_carefully1(Val, [free|Stk]) -> [{Val}|Stk];
-put_stack_carefully1(Val, [NotFree|Stk]) ->
- [NotFree|put_stack_carefully1(Val, Stk)].
-
-fetch_stack(Var, Stk) -> fetch_stack(Var, Stk, 0).
-
-fetch_stack(V, [{V}|_], I) -> {yy,I};
-fetch_stack(V, [_|Stk], I) -> fetch_stack(V, Stk, I+1).
-
-% find_stack(Var, Stk) -> find_stack(Var, Stk, 0).
-
-% find_stack(V, [{V}|Stk], I) -> {ok,{yy,I}};
-% find_stack(V, [O|Stk], I) -> find_stack(V, Stk, I+1);
-% find_stack(V, [], I) -> error.
-
-on_stack(V, Stk) -> keymember(V, 1, Stk).
-
-%% put_catch(CatchTag, Stack) -> Stack'
-%% drop_catch(CatchTag, Stack) -> Stack'
-%% Special interface for putting and removing catch tags, to ensure that
-%% catches nest properly. Also used for try tags.
-
-put_catch(Tag, Stk0) -> put_catch(Tag, reverse(Stk0), []).
-
-put_catch(Tag, [], Stk) ->
- put_stack({catch_tag,Tag}, Stk);
-put_catch(Tag, [{{catch_tag,_}}|_]=RevStk, Stk) ->
- reverse(RevStk, put_stack({catch_tag,Tag}, Stk));
-put_catch(Tag, [Other|Stk], Acc) ->
- put_catch(Tag, Stk, [Other|Acc]).
-
-drop_catch(Tag, [{{catch_tag,Tag}}|Stk]) -> [free|Stk];
-drop_catch(Tag, [Other|Stk]) -> [Other|drop_catch(Tag, Stk)].
-
-%%%
-%%% Finish the code generation for the bit syntax matching.
-%%%
-
-bs_function({function,Name,Arity,CLabel,Asm0}=Func) ->
- case bs_needed(Asm0, 0, false, []) of
- {false,[]} -> Func;
- {true,Dict} ->
- Asm = bs_replace(Asm0, Dict, []),
- {function,Name,Arity,CLabel,Asm}
- end.
-
-%%%
-%%% Pass 1: Found out which bs_restore's that are needed. For now we assume
-%%% that a bs_restore is needed unless it is directly preceeded by a bs_save.
-%%%
-
-bs_needed([{bs_save,Name},{bs_restore,Name}|T], N, _BsUsed, Dict) ->
- bs_needed(T, N, true, Dict);
-bs_needed([{bs_save,_Name}|T], N, _BsUsed, Dict) ->
- bs_needed(T, N, true, Dict);
-bs_needed([{bs_restore,Name}|T], N, _BsUsed, Dict) ->
- case keysearch(Name, 1, Dict) of
- {value,{Name,_}} -> bs_needed(T, N, true, Dict);
- false -> bs_needed(T, N+1, true, [{Name,N}|Dict])
- end;
-bs_needed([{bs_init,_,_}|T], N, _, Dict) ->
- bs_needed(T, N, true, Dict);
-bs_needed([{bs_init2,_,_,_,_,_}|T], N, _, Dict) ->
- bs_needed(T, N, true, Dict);
-bs_needed([{bs_start_match,_,_}|T], N, _, Dict) ->
- bs_needed(T, N, true, Dict);
-bs_needed([_|T], N, BsUsed, Dict) ->
- bs_needed(T, N, BsUsed, Dict);
-bs_needed([], _, BsUsed, Dict) -> {BsUsed,Dict}.
-
-%%%
-%%% Pass 2: Only needed if there were some bs_* instructions found.
-%%%
-%%% Remove any bs_save with a name that never were found to be restored
-%%% in the first pass.
-%%%
-
-bs_replace([{bs_save,Name}=Save,{bs_restore,Name}|T], Dict, Acc) ->
- bs_replace([Save|T], Dict, Acc);
-bs_replace([{bs_save,Name}|T], Dict, Acc) ->
- case keysearch(Name, 1, Dict) of
- {value,{Name,N}} ->
- bs_replace(T, Dict, [{bs_save,N}|Acc]);
- false ->
- bs_replace(T, Dict, Acc)
- end;
-bs_replace([{bs_restore,Name}|T], Dict, Acc) ->
- case keysearch(Name, 1, Dict) of
- {value,{Name,N}} ->
- bs_replace(T, Dict, [{bs_restore,N}|Acc]);
- false ->
- bs_replace(T, Dict, Acc)
- end;
-bs_replace([{bs_init2,Fail,Bytes,Regs,Flags,Dst}|T0], Dict, Acc) ->
- case bs_find_test_heap(T0) of
- none ->
- bs_replace(T0, Dict, [{bs_init2,Fail,Bytes,0,Regs,Flags,Dst}|Acc]);
- {T,Words} ->
- bs_replace(T, Dict, [{bs_init2,Fail,Bytes,Words,Regs,Flags,Dst}|Acc])
- end;
-bs_replace([H|T], Dict, Acc) ->
- bs_replace(T, Dict, [H|Acc]);
-bs_replace([], _, Acc) -> reverse(Acc).
-
-bs_find_test_heap(Is) ->
- bs_find_test_heap_1(Is, []).
-
-bs_find_test_heap_1([{bs_put_integer,_,_,_,_,_}=I|Is], Acc) ->
- bs_find_test_heap_1(Is, [I|Acc]);
-bs_find_test_heap_1([{bs_put_float,_,_,_,_,_}=I|Is], Acc) ->
- bs_find_test_heap_1(Is, [I|Acc]);
-bs_find_test_heap_1([{bs_put_binary,_,_,_,_,_}=I|Is], Acc) ->
- bs_find_test_heap_1(Is, [I|Acc]);
-bs_find_test_heap_1([{test_heap,Words,_}|Is], Acc) ->
- {reverse(Acc, Is),Words};
-bs_find_test_heap_1(_, _) -> none.
-
-%% new_label(St) -> {L,St}.
-
-new_label(St) ->
- L = St#cg.lcount,
- {L,St#cg{lcount=L+1}}.
-
-flatmapfoldl(F, Accu0, [Hd|Tail]) ->
- {R,Accu1} = F(Hd, Accu0),
- {Rs,Accu2} = flatmapfoldl(F, Accu1, Tail),
- {R++Rs,Accu2};
-flatmapfoldl(_, Accu, []) -> {[],Accu}.
-
-flatmapfoldr(F, Accu0, [Hd|Tail]) ->
- {Rs,Accu1} = flatmapfoldr(F, Accu0, Tail),
- {R,Accu2} = F(Hd, Accu1),
- {R++Rs,Accu2};
-flatmapfoldr(_, Accu, []) -> {[],Accu}.
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_core.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_core.erl
deleted file mode 100644
index b561182932..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_core.erl
+++ /dev/null
@@ -1,1320 +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: v3_core.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
-%%
-%% Purpose : Transform normal Erlang to Core Erlang
-
-%% At this stage all preprocessing has been done. All that is left are
-%% "pure" Erlang functions.
-%%
-%% Core transformation is done in three stages:
-%%
-%% 1. Flatten expressions into an internal core form without doing
-%% matching.
-%%
-%% 2. Step "forwards" over the icore code annotating each "top-level"
-%% thing with variable usage. Detect bound variables in matching
-%% and replace with explicit guard test. Annotate "internal-core"
-%% expressions with variables they use and create. Convert matches
-%% to cases when not pure assignments.
-%%
-%% 3. Step "backwards" over icore code using variable usage
-%% annotations to change implicit exported variables to explicit
-%% returns.
-%%
-%% To ensure the evaluation order we ensure that all arguments are
-%% safe. A "safe" is basically a core_lib simple with VERY restricted
-%% binaries.
-%%
-%% We have to be very careful with matches as these create variables.
-%% While we try not to flatten things more than necessary we must make
-%% sure that all matches are at the top level. For this we use the
-%% type "novars" which are non-match expressions. Cases and receives
-%% can also create problems due to exports variables so they are not
-%% "novars" either. I.e. a novars will not export variables.
-%%
-%% Annotations in the #iset, #iletrec, and all other internal records
-%% is kept in a record, #a, not in a list as in proper core. This is
-%% easier and faster and creates no problems as we have complete control
-%% over all annotations.
-%%
-%% On output, the annotation for most Core Erlang terms will contain
-%% the source line number. A few terms will be marked with the atom
-%% atom 'compiler_generated', to indicate that the compiler has generated
-%% them and that no warning should be generated if they are optimized
-%% away.
-%%
-%%
-%% In this translation:
-%%
-%% call ops are safes
-%% call arguments are safes
-%% match arguments are novars
-%% case arguments are novars
-%% receive timeouts are novars
-%% let/set arguments are expressions
-%% fun is not a safe
-
--module(v3_core).
-
--export([module/2,format_error/1]).
-
--import(lists, [map/2,foldl/3,foldr/3,mapfoldl/3,splitwith/2]).
--import(ordsets, [add_element/2,del_element/2,is_element/2,
- union/1,union/2,intersection/2,subtract/2]).
-
--include("core_parse.hrl").
-
--record(a, {us=[],ns=[],anno=[]}). %Internal annotation
-
-%% Internal core expressions and help functions.
-%% N.B. annotations fields in place as normal Core expressions.
-
--record(iset, {anno=#a{},var,arg}).
--record(iletrec, {anno=#a{},defs,body}).
--record(imatch, {anno=#a{},pat,guard=[],arg,fc}).
--record(icase, {anno=#a{},args,clauses,fc}).
--record(iclause, {anno=#a{},pats,pguard=[],guard,body}).
--record(ifun, {anno=#a{},id,vars,clauses,fc}).
--record(iapply, {anno=#a{},op,args}).
--record(icall, {anno=#a{},module,name,args}).
--record(iprimop, {anno=#a{},name,args}).
--record(itry, {anno=#a{},args,vars,body,evars,handler}).
--record(icatch, {anno=#a{},body}).
--record(ireceive1, {anno=#a{},clauses}).
--record(ireceive2, {anno=#a{},clauses,timeout,action}).
--record(iprotect, {anno=#a{},body}).
--record(ibinary, {anno=#a{},segments}). %Not used in patterns.
-
--record(core, {vcount=0, %Variable counter
- fcount=0, %Function counter
- ws=[]}). %Warnings.
-
-module({Mod,Exp,Forms}, _Opts) ->
- Cexp = map(fun ({N,A}) -> #c_fname{id=N,arity=A} end, Exp),
- {Kfs,As,Ws} = foldr(fun form/2, {[],[],[]}, Forms),
- {ok,#c_module{name=#c_atom{val=Mod},exports=Cexp,attrs=As,defs=Kfs},Ws}.
-
-form({function,_,_,_,_}=F0, {Fs,As,Ws0}) ->
- {F,Ws} = function(F0, Ws0),
- {[F|Fs],As,Ws};
-form({attribute,_,_,_}=F, {Fs,As,Ws}) ->
- {Fs,[attribute(F)|As],Ws}.
-
-attribute({attribute,_,Name,Val}) ->
- #c_def{name=core_lib:make_literal(Name),
- val=core_lib:make_literal(Val)}.
-
-function({function,_,Name,Arity,Cs0}, Ws0) ->
- %%ok = io:fwrite("~p - ", [{Name,Arity}]),
- St0 = #core{vcount=0,ws=Ws0},
- {B0,St1} = body(Cs0, Arity, St0),
- %%ok = io:fwrite("1", []),
- %%ok = io:fwrite("~w:~p~n", [?LINE,B0]),
- {B1,St2} = ubody(B0, St1),
- %%ok = io:fwrite("2", []),
- %%ok = io:fwrite("~w:~p~n", [?LINE,B1]),
- {B2,#core{ws=Ws}} = cbody(B1, St2),
- %%ok = io:fwrite("3~n", []),
- {#c_def{name=#c_fname{id=Name,arity=Arity},val=B2},Ws}.
-
-body(Cs0, Arity, St0) ->
- Anno = [element(2, hd(Cs0))],
- {Args,St1} = new_vars(Anno, Arity, St0),
- {Cs1,St2} = clauses(Cs0, St1),
- {Ps,St3} = new_vars(Arity, St2), %Need new variables here
- Fc = fail_clause(Ps, #c_tuple{es=[#c_atom{val=function_clause}|Ps]}),
- {#ifun{anno=#a{anno=Anno},id=[],vars=Args,clauses=Cs1,fc=Fc},St3}.
-
-%% clause(Clause, State) -> {Cclause,State} | noclause.
-%% clauses([Clause], State) -> {[Cclause],State}.
-%% Convert clauses. Trap bad pattern aliases and remove clause from
-%% clause list.
-
-clauses([C0|Cs0], St0) ->
- case clause(C0, St0) of
- {noclause,St} -> clauses(Cs0, St);
- {C,St1} ->
- {Cs,St2} = clauses(Cs0, St1),
- {[C|Cs],St2}
- end;
-clauses([], St) -> {[],St}.
-
-clause({clause,Lc,H0,G0,B0}, St0) ->
- case catch head(H0) of
- {'EXIT',_}=Exit -> exit(Exit); %Propagate error
- nomatch ->
- St = add_warning(Lc, nomatch, St0),
- {noclause,St}; %Bad pattern
- H1 ->
- {G1,St1} = guard(G0, St0),
- {B1,St2} = exprs(B0, St1),
- {#iclause{anno=#a{anno=[Lc]},pats=H1,guard=G1,body=B1},St2}
- end.
-
-%% head([P]) -> [P].
-
-head(Ps) -> pattern_list(Ps).
-
-%% guard([Expr], State) -> {[Cexpr],State}.
-%% Build an explict and/or tree of guard alternatives, then traverse
-%% top-level and/or tree and "protect" inner tests.
-
-guard([], St) -> {[],St};
-guard(Gs0, St) ->
- Gs = foldr(fun (Gt0, Rhs) ->
- Gt1 = guard_tests(Gt0),
- L = element(2, Gt1),
- {op,L,'or',Gt1,Rhs}
- end, guard_tests(last(Gs0)), first(Gs0)),
- gexpr_top(Gs, St).
-
-guard_tests([]) -> [];
-guard_tests(Gs) ->
- L = element(2, hd(Gs)),
- {protect,L,foldr(fun (G, Rhs) -> {op,L,'and',G,Rhs} end, last(Gs), first(Gs))}.
-
-%% gexpr_top(Expr, State) -> {Cexpr,State}.
-%% Generate an internal core expression of a guard test. Explicitly
-%% handle outer boolean expressions and "protect" inner tests in a
-%% reasonably smart way.
-
-gexpr_top(E0, St0) ->
- {E1,Eps0,Bools,St1} = gexpr(E0, [], St0),
- {E,Eps,St} = force_booleans(Bools, E1, Eps0, St1),
- {Eps++[E],St}.
-
-%% gexpr(Expr, Bools, State) -> {Cexpr,[PreExp],Bools,State}.
-%% Generate an internal core expression of a guard test.
-
-gexpr({protect,Line,Arg}, Bools0, St0) ->
- case gexpr(Arg, [], St0) of
- {E0,[],Bools,St1} ->
- {E,Eps,St} = force_booleans(Bools, E0, [], St1),
- {E,Eps,Bools0,St};
- {E0,Eps0,Bools,St1} ->
- {E,Eps,St} = force_booleans(Bools, E0, Eps0, St1),
- {#iprotect{anno=#a{anno=[Line]},body=Eps++[E]},[],Bools0,St}
- end;
-gexpr({op,Line,Op,L,R}=Call, Bools0, St0) ->
- case erl_internal:bool_op(Op, 2) of
- true ->
- {Le,Lps,Bools1,St1} = gexpr(L, Bools0, St0),
- {Ll,Llps,St2} = force_safe(Le, St1),
- {Re,Rps,Bools,St3} = gexpr(R, Bools1, St2),
- {Rl,Rlps,St4} = force_safe(Re, St3),
- Anno = [Line],
- {#icall{anno=#a{anno=Anno}, %Must have an #a{}
- module=#c_atom{anno=Anno,val=erlang},name=#c_atom{anno=Anno,val=Op},
- args=[Ll,Rl]},Lps ++ Llps ++ Rps ++ Rlps,Bools,St4};
- false ->
- gexpr_test(Call, Bools0, St0)
- end;
-gexpr({op,Line,Op,A}=Call, Bools0, St0) ->
- case erl_internal:bool_op(Op, 1) of
- true ->
- {Ae,Aps,Bools,St1} = gexpr(A, Bools0, St0),
- {Al,Alps,St2} = force_safe(Ae, St1),
- Anno = [Line],
- {#icall{anno=#a{anno=Anno}, %Must have an #a{}
- module=#c_atom{anno=Anno,val=erlang},name=#c_atom{anno=Anno,val=Op},
- args=[Al]},Aps ++ Alps,Bools,St2};
- false ->
- gexpr_test(Call, Bools0, St0)
- end;
-gexpr(E0, Bools, St0) ->
- gexpr_test(E0, Bools, St0).
-
-%% gexpr_test(Expr, Bools, State) -> {Cexpr,[PreExp],Bools,State}.
-%% Generate a guard test. At this stage we must be sure that we have
-%% a proper boolean value here so wrap things with an true test if we
-%% don't know, i.e. if it is not a comparison or a type test.
-
-gexpr_test({atom,L,true}, Bools, St0) ->
- {#c_atom{anno=[L],val=true},[],Bools,St0};
-gexpr_test({atom,L,false}, Bools, St0) ->
- {#c_atom{anno=[L],val=false},[],Bools,St0};
-gexpr_test(E0, Bools0, St0) ->
- {E1,Eps0,St1} = expr(E0, St0),
- %% Generate "top-level" test and argument calls.
- case E1 of
- #icall{anno=Anno,module=#c_atom{val=erlang},name=#c_atom{val=N},args=As} ->
- Ar = length(As),
- case erl_internal:type_test(N, Ar) orelse
- erl_internal:comp_op(N, Ar) orelse
- (N == internal_is_record andalso Ar == 3) of
- true -> {E1,Eps0,Bools0,St1};
- false ->
- Lanno = Anno#a.anno,
- {New,St2} = new_var(Lanno, St1),
- Bools = [New|Bools0],
- {#icall{anno=Anno, %Must have an #a{}
- module=#c_atom{anno=Lanno,val=erlang},
- name=#c_atom{anno=Lanno,val='=:='},
- args=[New,#c_atom{anno=Lanno,val=true}]},
- Eps0 ++ [#iset{anno=Anno,var=New,arg=E1}],Bools,St2}
- end;
- _ ->
- Anno = get_ianno(E1),
- Lanno = get_lineno_anno(E1),
- case core_lib:is_simple(E1) of
- true ->
- Bools = [E1|Bools0],
- {#icall{anno=Anno, %Must have an #a{}
- module=#c_atom{anno=Lanno,val=erlang},
- name=#c_atom{anno=Lanno,val='=:='},
- args=[E1,#c_atom{anno=Lanno,val=true}]},Eps0,Bools,St1};
- false ->
- {New,St2} = new_var(Lanno, St1),
- Bools = [New|Bools0],
- {#icall{anno=Anno, %Must have an #a{}
- module=#c_atom{anno=Lanno,val=erlang},
- name=#c_atom{anno=Lanno,val='=:='},
- args=[New,#c_atom{anno=Lanno,val=true}]},
- Eps0 ++ [#iset{anno=Anno,var=New,arg=E1}],Bools,St2}
- end
- end.
-
-force_booleans([], E, Eps, St) ->
- {E,Eps,St};
-force_booleans([V|Vs], E0, Eps0, St0) ->
- {E1,Eps1,St1} = force_safe(E0, St0),
- Lanno = element(2, V),
- Anno = #a{anno=Lanno},
- Call = #icall{anno=Anno,module=#c_atom{anno=Lanno,val=erlang},
- name=#c_atom{anno=Lanno,val=is_boolean},
- args=[V]},
- {New,St} = new_var(Lanno, St1),
- Iset = #iset{anno=Anno,var=New,arg=Call},
- Eps = Eps0 ++ Eps1 ++ [Iset],
- E = #icall{anno=Anno,
- module=#c_atom{anno=Lanno,val=erlang},name=#c_atom{anno=Lanno,val='and'},
- args=[E1,New]},
- force_booleans(Vs, E, Eps, St).
-
-%% exprs([Expr], State) -> {[Cexpr],State}.
-%% Flatten top-level exprs.
-
-exprs([E0|Es0], St0) ->
- {E1,Eps,St1} = expr(E0, St0),
- {Es1,St2} = exprs(Es0, St1),
- {Eps ++ [E1] ++ Es1,St2};
-exprs([], St) -> {[],St}.
-
-%% expr(Expr, State) -> {Cexpr,[PreExp],State}.
-%% Generate an internal core expression.
-
-expr({var,L,V}, St) -> {#c_var{anno=[L],name=V},[],St};
-expr({char,L,C}, St) -> {#c_char{anno=[L],val=C},[],St};
-expr({integer,L,I}, St) -> {#c_int{anno=[L],val=I},[],St};
-expr({float,L,F}, St) -> {#c_float{anno=[L],val=F},[],St};
-expr({atom,L,A}, St) -> {#c_atom{anno=[L],val=A},[],St};
-expr({nil,L}, St) -> {#c_nil{anno=[L]},[],St};
-expr({string,L,S}, St) -> {#c_string{anno=[L],val=S},[],St};
-expr({cons,L,H0,T0}, St0) ->
- {H1,Hps,St1} = safe(H0, St0),
- {T1,Tps,St2} = safe(T0, St1),
- {#c_cons{anno=[L],hd=H1,tl=T1},Hps ++ Tps,St2};
-expr({lc,L,E,Qs}, St) ->
- lc_tq(L, E, Qs, {nil,L}, St);
-expr({tuple,L,Es0}, St0) ->
- {Es1,Eps,St1} = safe_list(Es0, St0),
- {#c_tuple{anno=[L],es=Es1},Eps,St1};
-expr({bin,L,Es0}, St0) ->
- {Es1,Eps,St1} = expr_bin(Es0, St0),
- {#ibinary{anno=#a{anno=[L]},segments=Es1},Eps,St1};
-expr({block,_,Es0}, St0) ->
- %% Inline the block directly.
- {Es1,St1} = exprs(first(Es0), St0),
- {E1,Eps,St2} = expr(last(Es0), St1),
- {E1,Es1 ++ Eps,St2};
-expr({'if',L,Cs0}, St0) ->
- {Cs1,St1} = clauses(Cs0, St0),
- Fc = fail_clause([], #c_atom{val=if_clause}),
- {#icase{anno=#a{anno=[L]},args=[],clauses=Cs1,fc=Fc},[],St1};
-expr({'case',L,E0,Cs0}, St0) ->
- {E1,Eps,St1} = novars(E0, St0),
- {Cs1,St2} = clauses(Cs0, St1),
- {Fpat,St3} = new_var(St2),
- Fc = fail_clause([Fpat], #c_tuple{es=[#c_atom{val=case_clause},Fpat]}),
- {#icase{anno=#a{anno=[L]},args=[E1],clauses=Cs1,fc=Fc},Eps,St3};
-expr({'receive',L,Cs0}, St0) ->
- {Cs1,St1} = clauses(Cs0, St0),
- {#ireceive1{anno=#a{anno=[L]},clauses=Cs1}, [], St1};
-expr({'receive',L,Cs0,Te0,Tes0}, St0) ->
- {Te1,Teps,St1} = novars(Te0, St0),
- {Tes1,St2} = exprs(Tes0, St1),
- {Cs1,St3} = clauses(Cs0, St2),
- {#ireceive2{anno=#a{anno=[L]},
- clauses=Cs1,timeout=Te1,action=Tes1},Teps,St3};
-expr({'try',L,Es0,[],Ecs,[]}, St0) ->
- %% 'try ... catch ... end'
- {Es1,St1} = exprs(Es0, St0),
- {V,St2} = new_var(St1), %This name should be arbitrary
- {Evs,Hs,St3} = try_exception(Ecs, St2),
- {#itry{anno=#a{anno=[L]},args=Es1,vars=[V],body=[V],
- evars=Evs,handler=Hs},
- [],St3};
-expr({'try',L,Es0,Cs0,Ecs,[]}, St0) ->
- %% 'try ... of ... catch ... end'
- {Es1,St1} = exprs(Es0, St0),
- {V,St2} = new_var(St1), %This name should be arbitrary
- {Cs1,St3} = clauses(Cs0, St2),
- {Fpat,St4} = new_var(St3),
- Fc = fail_clause([Fpat], #c_tuple{es=[#c_atom{val=try_clause},Fpat]}),
- {Evs,Hs,St5} = try_exception(Ecs, St4),
- {#itry{anno=#a{anno=[L]},args=Es1,
- vars=[V],body=[#icase{anno=#a{},args=[V],clauses=Cs1,fc=Fc}],
- evars=Evs,handler=Hs},
- [],St5};
-expr({'try',L,Es0,[],[],As0}, St0) ->
- %% 'try ... after ... end'
- {Es1,St1} = exprs(Es0, St0),
- {As1,St2} = exprs(As0, St1),
- {Evs,Hs,St3} = try_after(As1,St2),
- {V,St4} = new_var(St3), % (must not exist in As1)
- %% TODO: this duplicates the 'after'-code; should lift to function.
- {#itry{anno=#a{anno=[L]},args=Es1,vars=[V],body=As1++[V],
- evars=Evs,handler=Hs},
- [],St4};
-expr({'try',L,Es,Cs,Ecs,As}, St0) ->
- %% 'try ... [of ...] [catch ...] after ... end'
- expr({'try',L,[{'try',L,Es,Cs,Ecs,[]}],[],[],As}, St0);
-expr({'catch',L,E0}, St0) ->
- {E1,Eps,St1} = expr(E0, St0),
- {#icatch{anno=#a{anno=[L]},body=Eps ++ [E1]},[],St1};
-expr({'fun',L,{function,F,A},{_,_,_}=Id}, St) ->
- {#c_fname{anno=[L,{id,Id}],id=F,arity=A},[],St};
-expr({'fun',L,{clauses,Cs},Id}, St) ->
- fun_tq(Id, Cs, L, St);
-expr({call,L0,{remote,_,{atom,_,erlang},{atom,_,is_record}},[_,_,_]=As}, St)
- when L0 < 0 ->
- %% Compiler-generated erlang:is_record/3 should be converted to
- %% erlang:internal_is_record/3.
- L = -L0,
- expr({call,L,{remote,L,{atom,L,erlang},{atom,L,internal_is_record}},As}, St);
-expr({call,L,{remote,_,M,F},As0}, St0) ->
- {[M1,F1|As1],Aps,St1} = safe_list([M,F|As0], St0),
- {#icall{anno=#a{anno=[L]},module=M1,name=F1,args=As1},Aps,St1};
-expr({call,Lc,{atom,Lf,F},As0}, St0) ->
- {As1,Aps,St1} = safe_list(As0, St0),
- Op = #c_fname{anno=[Lf],id=F,arity=length(As1)},
- {#iapply{anno=#a{anno=[Lc]},op=Op,args=As1},Aps,St1};
-expr({call,L,FunExp,As0}, St0) ->
- {Fun,Fps,St1} = safe(FunExp, St0),
- {As1,Aps,St2} = safe_list(As0, St1),
- {#iapply{anno=#a{anno=[L]},op=Fun,args=As1},Fps ++ Aps,St2};
-expr({match,L,P0,E0}, St0) ->
- %% First fold matches together to create aliases.
- {P1,E1} = fold_match(E0, P0),
- {E2,Eps,St1} = novars(E1, St0),
- P2 = (catch pattern(P1)),
- {Fpat,St2} = new_var(St1),
- Fc = fail_clause([Fpat], #c_tuple{es=[#c_atom{val=badmatch},Fpat]}),
- case P2 of
- {'EXIT',_}=Exit -> exit(Exit); %Propagate error
- nomatch ->
- St = add_warning(L, nomatch, St2),
- {#icase{anno=#a{anno=[L]},
- args=[E2],clauses=[],fc=Fc},Eps,St};
- _Other ->
- {#imatch{anno=#a{anno=[L]},pat=P2,arg=E2,fc=Fc},Eps,St2}
- end;
-expr({op,_,'++',{lc,Llc,E,Qs},L2}, St) ->
- %% Optimise this here because of the list comprehension algorithm.
- lc_tq(Llc, E, Qs, L2, St);
-expr({op,L,Op,A0}, St0) ->
- {A1,Aps,St1} = safe(A0, St0),
- LineAnno = [L],
- {#icall{anno=#a{anno=LineAnno}, %Must have an #a{}
- module=#c_atom{anno=LineAnno,val=erlang},
- name=#c_atom{anno=LineAnno,val=Op},args=[A1]},Aps,St1};
-expr({op,L,Op,L0,R0}, St0) ->
- {As,Aps,St1} = safe_list([L0,R0], St0),
- LineAnno = [L],
- {#icall{anno=#a{anno=LineAnno}, %Must have an #a{}
- module=#c_atom{anno=LineAnno,val=erlang},
- name=#c_atom{anno=LineAnno,val=Op},args=As},Aps,St1}.
-
-%% try_exception([ExcpClause], St) -> {[ExcpVar],Handler,St}.
-
-try_exception(Ecs0, St0) ->
- %% Note that Tag is not needed for rethrow - it is already in Info.
- {Evs,St1} = new_vars(3, St0), % Tag, Value, Info
- {Ecs1,St2} = clauses(Ecs0, St1),
- [_,Value,Info] = Evs,
- Ec = #iclause{anno=#a{anno=[compiler_generated]},
- pats=[#c_tuple{es=Evs}],guard=[#c_atom{val=true}],
- body=[#iprimop{anno=#a{}, %Must have an #a{}
- name=#c_atom{val=raise},
- args=[Info,Value]}]},
- Hs = [#icase{anno=#a{},args=[#c_tuple{es=Evs}],clauses=Ecs1,fc=Ec}],
- {Evs,Hs,St2}.
-
-try_after(As, St0) ->
- %% See above.
- {Evs,St1} = new_vars(3, St0), % Tag, Value, Info
- [_,Value,Info] = Evs,
- B = As ++ [#iprimop{anno=#a{}, %Must have an #a{}
- name=#c_atom{val=raise},
- args=[Info,Value]}],
- Ec = #iclause{anno=#a{anno=[compiler_generated]},
- pats=[#c_tuple{es=Evs}],guard=[#c_atom{val=true}],
- body=B},
- Hs = [#icase{anno=#a{},args=[#c_tuple{es=Evs}],clauses=[],fc=Ec}],
- {Evs,Hs,St1}.
-
-%% expr_bin([ArgExpr], St) -> {[Arg],[PreExpr],St}.
-%% Flatten the arguments of a bin. Do this straight left to right!
-
-expr_bin(Es, St) ->
- foldr(fun (E, {Ces,Esp,St0}) ->
- {Ce,Ep,St1} = bitstr(E, St0),
- {[Ce|Ces],Ep ++ Esp,St1}
- end, {[],[],St}, Es).
-
-bitstr({bin_element,_,E0,Size0,[Type,{unit,Unit}|Flags]}, St0) ->
- {E1,Eps,St1} = safe(E0, St0),
- {Size1,Eps2,St2} = safe(Size0, St1),
- {#c_bitstr{val=E1,size=Size1,
- unit=core_lib:make_literal(Unit),
- type=core_lib:make_literal(Type),
- flags=core_lib:make_literal(Flags)},
- Eps ++ Eps2,St2}.
-
-%% fun_tq(Id, [Clauses], Line, State) -> {Fun,[PreExp],State}.
-
-fun_tq(Id, Cs0, L, St0) ->
- {Cs1,St1} = clauses(Cs0, St0),
- Arity = length((hd(Cs1))#iclause.pats),
- {Args,St2} = new_vars(Arity, St1),
- {Ps,St3} = new_vars(Arity, St2), %Need new variables here
- Fc = fail_clause(Ps, #c_tuple{es=[#c_atom{val=function_clause}|Ps]}),
- Fun = #ifun{anno=#a{anno=[L]},
- id=[{id,Id}], %We KNOW!
- vars=Args,clauses=Cs1,fc=Fc},
- {Fun,[],St3}.
-
-%% lc_tq(Line, Exp, [Qualifier], More, State) -> {LetRec,[PreExp],State}.
-%% This TQ from Simon PJ pp 127-138.
-%% This gets a bit messy as we must transform all directly here. We
-%% recognise guard tests and try to fold them together and join to a
-%% preceding generators, this should give us better and more compact
-%% code.
-%% More could be transformed before calling lc_tq.
-
-lc_tq(Line, E, [{generate,Lg,P,G}|Qs0], More, St0) ->
- {Gs,Qs1} = splitwith(fun is_guard_test/1, Qs0),
- {Name,St1} = new_fun_name("lc", St0),
- {Head,St2} = new_var(St1),
- {Tname,St3} = new_var_name(St2),
- LA = [Line],
- LAnno = #a{anno=LA},
- Tail = #c_var{anno=LA,name=Tname},
- {Arg,St4} = new_var(St3),
- NewMore = {call,Lg,{atom,Lg,Name},[{var,Lg,Tname}]},
- {Guardc,St5} = lc_guard_tests(Gs, St4), %These are always flat!
- {Lc,Lps,St6} = lc_tq(Line, E, Qs1, NewMore, St5),
- {Mc,Mps,St7} = expr(More, St6),
- {Nc,Nps,St8} = expr(NewMore, St7),
- case catch pattern(P) of
- {'EXIT',_}=Exit ->
- St9 = St8,
- Pc = nomatch,
- exit(Exit); %Propagate error
- nomatch ->
- St9 = add_warning(Line, nomatch, St8),
- Pc = nomatch;
- Pc ->
- St9 = St8
- end,
- {Gc,Gps,St10} = safe(G, St9), %Will be a function argument!
- Fc = fail_clause([Arg], #c_tuple{anno=LA,
- es=[#c_atom{val=function_clause},Arg]}),
- Cs0 = [#iclause{anno=#a{anno=[compiler_generated|LA]},
- pats=[#c_cons{anno=LA,hd=Head,tl=Tail}],
- guard=[],
- body=Nps ++ [Nc]},
- #iclause{anno=LAnno,
- pats=[#c_nil{anno=LA}],guard=[],
- body=Mps ++ [Mc]}],
- Cs = case Pc of
- nomatch -> Cs0;
- _ ->
- [#iclause{anno=LAnno,
- pats=[#c_cons{anno=LA,hd=Pc,tl=Tail}],
- guard=Guardc,
- body=Lps ++ [Lc]}|Cs0]
- end,
- Fun = #ifun{anno=LAnno,id=[],vars=[Arg],clauses=Cs,fc=Fc},
- {#iletrec{anno=LAnno,defs=[{Name,Fun}],
- body=Gps ++ [#iapply{anno=LAnno,
- op=#c_fname{anno=LA,id=Name,arity=1},
- args=[Gc]}]},
- [],St10};
-lc_tq(Line, E, [Fil0|Qs0], More, St0) ->
- %% Special case sequences guard tests.
- LA = [Line],
- LAnno = #a{anno=LA},
- case is_guard_test(Fil0) of
- true ->
- {Gs0,Qs1} = splitwith(fun is_guard_test/1, Qs0),
- {Lc,Lps,St1} = lc_tq(Line, E, Qs1, More, St0),
- {Mc,Mps,St2} = expr(More, St1),
- {Gs,St3} = lc_guard_tests([Fil0|Gs0], St2), %These are always flat!
- {#icase{anno=LAnno,
- args=[],
- clauses=[#iclause{anno=LAnno,pats=[],
- guard=Gs,body=Lps ++ [Lc]}],
- fc=#iclause{anno=LAnno,pats=[],guard=[],body=Mps ++ [Mc]}},
- [],St3};
- false ->
- {Lc,Lps,St1} = lc_tq(Line, E, Qs0, More, St0),
- {Mc,Mps,St2} = expr(More, St1),
- {Fpat,St3} = new_var(St2),
- Fc = fail_clause([Fpat], #c_tuple{es=[#c_atom{val=case_clause},Fpat]}),
- %% Do a novars little optimisation here.
- case Fil0 of
- {op,_,'not',Fil1} ->
- {Filc,Fps,St4} = novars(Fil1, St3),
- {#icase{anno=LAnno,
- args=[Filc],
- clauses=[#iclause{anno=LAnno,
- pats=[#c_atom{anno=LA,val=true}],
- guard=[],
- body=Mps ++ [Mc]},
- #iclause{anno=LAnno,
- pats=[#c_atom{anno=LA,val=false}],
- guard=[],
- body=Lps ++ [Lc]}],
- fc=Fc},
- Fps,St4};
- _Other ->
- {Filc,Fps,St4} = novars(Fil0, St3),
- {#icase{anno=LAnno,
- args=[Filc],
- clauses=[#iclause{anno=LAnno,
- pats=[#c_atom{anno=LA,val=true}],
- guard=[],
- body=Lps ++ [Lc]},
- #iclause{anno=LAnno,
- pats=[#c_atom{anno=LA,val=false}],
- guard=[],
- body=Mps ++ [Mc]}],
- fc=Fc},
- Fps,St4}
- end
- end;
-lc_tq(Line, E, [], More, St) ->
- expr({cons,Line,E,More}, St).
-
-lc_guard_tests([], St) -> {[],St};
-lc_guard_tests(Gs0, St) ->
- Gs = guard_tests(Gs0),
- gexpr_top(Gs, St).
-
-%% is_guard_test(Expression) -> true | false.
-%% Test if a general expression is a guard test. Use erl_lint here
-%% as it now allows sys_pre_expand transformed source.
-
-is_guard_test(E) -> erl_lint:is_guard_test(E).
-
-%% novars(Expr, State) -> {Novars,[PreExpr],State}.
-%% Generate a novars expression, basically a call or a safe. At this
-%% level we do not need to do a deep check.
-
-novars(E0, St0) ->
- {E1,Eps,St1} = expr(E0, St0),
- {Se,Sps,St2} = force_novars(E1, St1),
- {Se,Eps ++ Sps,St2}.
-
-force_novars(#iapply{}=App, St) -> {App,[],St};
-force_novars(#icall{}=Call, St) -> {Call,[],St};
-force_novars(#iprimop{}=Prim, St) -> {Prim,[],St};
-force_novars(#ifun{}=Fun, St) -> {Fun,[],St}; %These are novars too
-force_novars(#ibinary{}=Bin, St) -> {Bin,[],St};
-force_novars(Ce, St) ->
- force_safe(Ce, St).
-
-%% safe(Expr, State) -> {Safe,[PreExpr],State}.
-%% Generate an internal safe expression. These are simples without
-%% binaries which can fail. At this level we do not need to do a
-%% deep check. Must do special things with matches here.
-
-safe(E0, St0) ->
- {E1,Eps,St1} = expr(E0, St0),
- {Se,Sps,St2} = force_safe(E1, St1),
- {Se,Eps ++ Sps,St2}.
-
-safe_list(Es, St) ->
- foldr(fun (E, {Ces,Esp,St0}) ->
- {Ce,Ep,St1} = safe(E, St0),
- {[Ce|Ces],Ep ++ Esp,St1}
- end, {[],[],St}, Es).
-
-force_safe(#imatch{anno=Anno,pat=P,arg=E,fc=Fc}, St0) ->
- {Le,Lps,St1} = force_safe(E, St0),
- {Le,Lps ++ [#imatch{anno=Anno,pat=P,arg=Le,fc=Fc}],St1};
-force_safe(Ce, St0) ->
- case is_safe(Ce) of
- true -> {Ce,[],St0};
- false ->
- {V,St1} = new_var(St0),
- {V,[#iset{var=V,arg=Ce}],St1}
- end.
-
-is_safe(#c_cons{}) -> true;
-is_safe(#c_tuple{}) -> true;
-is_safe(#c_var{}) -> true;
-is_safe(E) -> core_lib:is_atomic(E).
-
-%%% %% variable(Expr, State) -> {Variable,[PreExpr],State}.
-%%% %% force_variable(Expr, State) -> {Variable,[PreExpr],State}.
-%%% %% Generate a variable.
-
-%%% variable(E0, St0) ->
-%%% {E1,Eps,St1} = expr(E0, St0),
-%%% {V,Vps,St2} = force_variable(E1, St1),
-%%% {V,Eps ++ Vps,St2}.
-
-%%% force_variable(#c_var{}=Var, St) -> {Var,[],St};
-%%% force_variable(Ce, St0) ->
-%%% {V,St1} = new_var(St0),
-%%% {V,[#iset{var=V,arg=Ce}],St1}.
-
-%%% %% atomic(Expr, State) -> {Atomic,[PreExpr],State}.
-%%% %% force_atomic(Expr, State) -> {Atomic,[PreExpr],State}.
-
-%%% atomic(E0, St0) ->
-%%% {E1,Eps,St1} = expr(E0, St0),
-%%% {A,Aps,St2} = force_atomic(E1, St1),
-%%% {A,Eps ++ Aps,St2}.
-
-%%% force_atomic(Ce, St0) ->
-%%% case core_lib:is_atomic(Ce) of
-%%% true -> {Ce,[],St0};
-%%% false ->
-%%% {V,St1} = new_var(St0),
-%%% {V,[#iset{var=V,arg=Ce}],St1}
-%%% end.
-
-%% fold_match(MatchExpr, Pat) -> {MatchPat,Expr}.
-%% Fold nested matches into one match with aliased patterns.
-
-fold_match({match,L,P0,E0}, P) ->
- {P1,E1} = fold_match(E0, P),
- {{match,L,P0,P1},E1};
-fold_match(E, P) -> {P,E}.
-
-%% pattern(Pattern) -> CorePat.
-%% Transform a pattern by removing line numbers. We also normalise
-%% aliases in patterns to standard form, {alias,Pat,[Var]}.
-
-pattern({var,L,V}) -> #c_var{anno=[L],name=V};
-pattern({char,L,C}) -> #c_char{anno=[L],val=C};
-pattern({integer,L,I}) -> #c_int{anno=[L],val=I};
-pattern({float,L,F}) -> #c_float{anno=[L],val=F};
-pattern({atom,L,A}) -> #c_atom{anno=[L],val=A};
-pattern({string,L,S}) -> #c_string{anno=[L],val=S};
-pattern({nil,L}) -> #c_nil{anno=[L]};
-pattern({cons,L,H,T}) ->
- #c_cons{anno=[L],hd=pattern(H),tl=pattern(T)};
-pattern({tuple,L,Ps}) ->
- #c_tuple{anno=[L],es=pattern_list(Ps)};
-pattern({bin,L,Ps}) ->
- %% We don't create a #ibinary record here, since there is
- %% no need to hold any used/new annoations in a pattern.
- #c_binary{anno=[L],segments=pat_bin(Ps)};
-pattern({match,_,P1,P2}) ->
- pat_alias(pattern(P1), pattern(P2)).
-
-%% bin_pattern_list([BinElement]) -> [BinSeg].
-
-pat_bin(Ps) -> map(fun pat_segment/1, Ps).
-
-pat_segment({bin_element,_,Term,Size,[Type,{unit,Unit}|Flags]}) ->
- #c_bitstr{val=pattern(Term),size=pattern(Size),
- unit=core_lib:make_literal(Unit),
- type=core_lib:make_literal(Type),
- flags=core_lib:make_literal(Flags)}.
-
-%% pat_alias(CorePat, CorePat) -> AliasPat.
-%% Normalise aliases. Trap bad aliases by throwing 'nomatch'.
-
-pat_alias(#c_var{name=V1}, P2) -> #c_alias{var=#c_var{name=V1},pat=P2};
-pat_alias(P1, #c_var{name=V2}) -> #c_alias{var=#c_var{name=V2},pat=P1};
-pat_alias(#c_cons{}=Cons, #c_string{anno=A,val=[H|T]}=S) ->
- pat_alias(Cons, #c_cons{anno=A,hd=#c_char{anno=A,val=H},
- tl=S#c_string{val=T}});
-pat_alias(#c_string{anno=A,val=[H|T]}=S, #c_cons{}=Cons) ->
- pat_alias(#c_cons{anno=A,hd=#c_char{anno=A,val=H},
- tl=S#c_string{val=T}}, Cons);
-pat_alias(#c_nil{}=Nil, #c_string{val=[]}) ->
- Nil;
-pat_alias(#c_string{val=[]}, #c_nil{}=Nil) ->
- Nil;
-pat_alias(#c_cons{anno=A,hd=H1,tl=T1}, #c_cons{hd=H2,tl=T2}) ->
- #c_cons{anno=A,hd=pat_alias(H1, H2),tl=pat_alias(T1, T2)};
-pat_alias(#c_tuple{es=Es1}, #c_tuple{es=Es2}) ->
- #c_tuple{es=pat_alias_list(Es1, Es2)};
-pat_alias(#c_char{val=C}=Char, #c_int{val=C}) ->
- Char;
-pat_alias(#c_int{val=C}, #c_char{val=C}=Char) ->
- Char;
-pat_alias(#c_alias{var=V1,pat=P1},
- #c_alias{var=V2,pat=P2}) ->
- if V1 == V2 -> pat_alias(P1, P2);
- true -> #c_alias{var=V1,pat=#c_alias{var=V2,pat=pat_alias(P1, P2)}}
- end;
-pat_alias(#c_alias{var=V1,pat=P1}, P2) ->
- #c_alias{var=V1,pat=pat_alias(P1, P2)};
-pat_alias(P1, #c_alias{var=V2,pat=P2}) ->
- #c_alias{var=V2,pat=pat_alias(P1, P2)};
-pat_alias(P, P) -> P;
-pat_alias(_, _) -> throw(nomatch).
-
-%% pat_alias_list([A1], [A2]) -> [A].
-
-pat_alias_list([A1|A1s], [A2|A2s]) ->
- [pat_alias(A1, A2)|pat_alias_list(A1s, A2s)];
-pat_alias_list([], []) -> [];
-pat_alias_list(_, _) -> throw(nomatch).
-
-%% pattern_list([P]) -> [P].
-
-pattern_list(Ps) -> map(fun pattern/1, Ps).
-
-%% first([A]) -> [A].
-%% last([A]) -> A.
-
-first([_]) -> [];
-first([H|T]) -> [H|first(T)].
-
-last([L]) -> L;
-last([_|T]) -> last(T).
-
-%% make_vars([Name]) -> [{Var,Name}].
-
-make_vars(Vs) -> [ #c_var{name=V} || V <- Vs ].
-
-%% new_fun_name(Type, State) -> {FunName,State}.
-
-new_fun_name(Type, #core{fcount=C}=St) ->
- {list_to_atom(Type ++ "$^" ++ integer_to_list(C)),St#core{fcount=C+1}}.
-
-%% new_var_name(State) -> {VarName,State}.
-
-new_var_name(#core{vcount=C}=St) ->
- {list_to_atom("cor" ++ integer_to_list(C)),St#core{vcount=C + 1}}.
-
-%% new_var(State) -> {{var,Name},State}.
-%% new_var(LineAnno, State) -> {{var,Name},State}.
-
-new_var(St) ->
- new_var([], St).
-
-new_var(Anno, St0) ->
- {New,St} = new_var_name(St0),
- {#c_var{anno=Anno,name=New},St}.
-
-%% new_vars(Count, State) -> {[Var],State}.
-%% new_vars(Anno, Count, State) -> {[Var],State}.
-%% Make Count new variables.
-
-new_vars(N, St) -> new_vars_1(N, [], St, []).
-new_vars(Anno, N, St) -> new_vars_1(N, Anno, St, []).
-
-new_vars_1(N, Anno, St0, Vs) when N > 0 ->
- {V,St1} = new_var(Anno, St0),
- new_vars_1(N-1, Anno, St1, [V|Vs]);
-new_vars_1(0, _, St, Vs) -> {Vs,St}.
-
-fail_clause(Pats, A) ->
- #iclause{anno=#a{anno=[compiler_generated]},
- pats=Pats,guard=[],
- body=[#iprimop{anno=#a{},name=#c_atom{val=match_fail},args=[A]}]}.
-
-ubody(B, St) -> uexpr(B, [], St).
-
-%% uclauses([Lclause], [KnownVar], State) -> {[Lclause],State}.
-
-uclauses(Lcs, Ks, St0) ->
- mapfoldl(fun (Lc, St) -> uclause(Lc, Ks, St) end, St0, Lcs).
-
-%% uclause(Lclause, [KnownVar], State) -> {Lclause,State}.
-
-uclause(Cl0, Ks, St0) ->
- {Cl1,_Pvs,Used,New,St1} = uclause(Cl0, Ks, Ks, St0),
- A0 = get_ianno(Cl1),
- A = A0#a{us=Used,ns=New},
- {Cl1#iclause{anno=A},St1}.
-
-uclause(#iclause{anno=Anno,pats=Ps0,guard=G0,body=B0}, Pks, Ks0, St0) ->
- {Ps1,Pg,Pvs,Pus,St1} = upattern_list(Ps0, Pks, St0),
- Pu = union(Pus, intersection(Pvs, Ks0)),
- Pn = subtract(Pvs, Pu),
- Ks1 = union(Pn, Ks0),
- {G1,St2} = uguard(Pg, G0, Ks1, St1),
- Gu = used_in_any(G1),
- Gn = new_in_any(G1),
- Ks2 = union(Gn, Ks1),
- {B1,St3} = uexprs(B0, Ks2, St2),
- Used = intersection(union([Pu,Gu,used_in_any(B1)]), Ks0),
- New = union([Pn,Gn,new_in_any(B1)]),
- {#iclause{anno=Anno,pats=Ps1,guard=G1,body=B1},Pvs,Used,New,St3}.
-
-%% uguard([Test], [Kexpr], [KnownVar], State) -> {[Kexpr],State}.
-%% Build a guard expression list by folding in the equality tests.
-
-uguard([], [], _, St) -> {[],St};
-uguard(Pg, [], Ks, St) ->
- %% No guard, so fold together equality tests.
- uguard(first(Pg), [last(Pg)], Ks, St);
-uguard(Pg, Gs0, Ks, St0) ->
- %% Gs0 must contain at least one element here.
- {Gs3,St5} = foldr(fun (T, {Gs1,St1}) ->
- {L,St2} = new_var(St1),
- {R,St3} = new_var(St2),
- {[#iset{var=L,arg=T}] ++ first(Gs1) ++
- [#iset{var=R,arg=last(Gs1)},
- #icall{anno=#a{}, %Must have an #a{}
- module=#c_atom{val=erlang},
- name=#c_atom{val='and'},
- args=[L,R]}],
- St3}
- end, {Gs0,St0}, Pg),
- %%ok = io:fwrite("core ~w: ~p~n", [?LINE,Gs3]),
- uexprs(Gs3, Ks, St5).
-
-%% uexprs([Kexpr], [KnownVar], State) -> {[Kexpr],State}.
-
-uexprs([#imatch{anno=A,pat=P0,arg=Arg,fc=Fc}|Les], Ks, St0) ->
- %% Optimise for simple set of unbound variable.
- case upattern(P0, Ks, St0) of
- {#c_var{},[],_Pvs,_Pus,_} ->
- %% Throw our work away and just set to iset.
- uexprs([#iset{var=P0,arg=Arg}|Les], Ks, St0);
- _Other ->
- %% Throw our work away and set to icase.
- if
- Les == [] ->
- %% Need to explicitly return match "value", make
- %% safe for efficiency.
- {La,Lps,St1} = force_safe(Arg, St0),
- Mc = #iclause{anno=A,pats=[P0],guard=[],body=[La]},
- uexprs(Lps ++ [#icase{anno=A,
- args=[La],clauses=[Mc],fc=Fc}], Ks, St1);
- true ->
- Mc = #iclause{anno=A,pats=[P0],guard=[],body=Les},
- uexprs([#icase{anno=A,args=[Arg],
- clauses=[Mc],fc=Fc}], Ks, St0)
- end
- end;
-uexprs([Le0|Les0], Ks, St0) ->
- {Le1,St1} = uexpr(Le0, Ks, St0),
- {Les1,St2} = uexprs(Les0, union((core_lib:get_anno(Le1))#a.ns, Ks), St1),
- {[Le1|Les1],St2};
-uexprs([], _, St) -> {[],St}.
-
-uexpr(#iset{anno=A,var=V,arg=A0}, Ks, St0) ->
- {A1,St1} = uexpr(A0, Ks, St0),
- {#iset{anno=A#a{us=del_element(V#c_var.name, (core_lib:get_anno(A1))#a.us),
- ns=add_element(V#c_var.name, (core_lib:get_anno(A1))#a.ns)},
- var=V,arg=A1},St1};
-%% imatch done in uexprs.
-uexpr(#iletrec{anno=A,defs=Fs0,body=B0}, Ks, St0) ->
- %%ok = io:fwrite("~w: ~p~n", [?LINE,{Fs0,B0}]),
- {Fs1,St1} = mapfoldl(fun ({Name,F0}, St0) ->
- {F1,St1} = uexpr(F0, Ks, St0),
- {{Name,F1},St1}
- end, St0, Fs0),
- {B1,St2} = uexprs(B0, Ks, St1),
- Used = used_in_any(map(fun ({_,F}) -> F end, Fs1) ++ B1),
- {#iletrec{anno=A#a{us=Used,ns=[]},defs=Fs1,body=B1},St2};
-uexpr(#icase{anno=A,args=As0,clauses=Cs0,fc=Fc0}, Ks, St0) ->
- %% As0 will never generate new variables.
- {As1,St1} = uexpr_list(As0, Ks, St0),
- {Cs1,St2} = uclauses(Cs0, Ks, St1),
- {Fc1,St3} = uclause(Fc0, Ks, St2),
- Used = union(used_in_any(As1), used_in_any(Cs1)),
- New = new_in_all(Cs1),
- {#icase{anno=A#a{us=Used,ns=New},args=As1,clauses=Cs1,fc=Fc1},St3};
-uexpr(#ifun{anno=A,id=Id,vars=As,clauses=Cs0,fc=Fc0}, Ks0, St0) ->
- Avs = lit_list_vars(As),
- Ks1 = union(Avs, Ks0),
- {Cs1,St1} = ufun_clauses(Cs0, Ks1, St0),
- {Fc1,St2} = ufun_clause(Fc0, Ks1, St1),
- Used = subtract(intersection(used_in_any(Cs1), Ks0), Avs),
- {#ifun{anno=A#a{us=Used,ns=[]},id=Id,vars=As,clauses=Cs1,fc=Fc1},St2};
-uexpr(#iapply{anno=A,op=Op,args=As}, _, St) ->
- Used = union(lit_vars(Op), lit_list_vars(As)),
- {#iapply{anno=A#a{us=Used},op=Op,args=As},St};
-uexpr(#iprimop{anno=A,name=Name,args=As}, _, St) ->
- Used = lit_list_vars(As),
- {#iprimop{anno=A#a{us=Used},name=Name,args=As},St};
-uexpr(#icall{anno=A,module=Mod,name=Name,args=As}, _, St) ->
- Used = union([lit_vars(Mod),lit_vars(Name),lit_list_vars(As)]),
- {#icall{anno=A#a{us=Used},module=Mod,name=Name,args=As},St};
-uexpr(#itry{anno=A,args=As0,vars=Vs,body=Bs0,evars=Evs,handler=Hs0}, Ks, St0) ->
- %% Note that we export only from body and exception.
- {As1,St1} = uexprs(As0, Ks, St0),
- {Bs1,St2} = uexprs(Bs0, Ks, St1),
- {Hs1,St3} = uexprs(Hs0, Ks, St2),
- Used = intersection(used_in_any(Bs1++Hs1++As1), Ks),
- New = new_in_all(Bs1++Hs1),
- {#itry{anno=A#a{us=Used,ns=New},
- args=As1,vars=Vs,body=Bs1,evars=Evs,handler=Hs1},St3};
-uexpr(#icatch{anno=A,body=Es0}, Ks, St0) ->
- {Es1,St1} = uexprs(Es0, Ks, St0),
- {#icatch{anno=A#a{us=used_in_any(Es1)},body=Es1},St1};
-uexpr(#ireceive1{anno=A,clauses=Cs0}, Ks, St0) ->
- {Cs1,St1} = uclauses(Cs0, Ks, St0),
- {#ireceive1{anno=A#a{us=used_in_any(Cs1),ns=new_in_all(Cs1)},
- clauses=Cs1},St1};
-uexpr(#ireceive2{anno=A,clauses=Cs0,timeout=Te0,action=Tes0}, Ks, St0) ->
- %% Te0 will never generate new variables.
- {Te1,St1} = uexpr(Te0, Ks, St0),
- {Cs1,St2} = uclauses(Cs0, Ks, St1),
- {Tes1,St3} = uexprs(Tes0, Ks, St2),
- Used = union([used_in_any(Cs1),used_in_any(Tes1),
- (core_lib:get_anno(Te1))#a.us]),
- New = case Cs1 of
- [] -> new_in_any(Tes1);
- _ -> intersection(new_in_all(Cs1), new_in_any(Tes1))
- end,
- {#ireceive2{anno=A#a{us=Used,ns=New},
- clauses=Cs1,timeout=Te1,action=Tes1},St3};
-uexpr(#iprotect{anno=A,body=Es0}, Ks, St0) ->
- {Es1,St1} = uexprs(Es0, Ks, St0),
- Used = used_in_any(Es1),
- {#iprotect{anno=A#a{us=Used},body=Es1},St1}; %No new variables escape!
-uexpr(#ibinary{anno=A,segments=Ss}, _, St) ->
- Used = bitstr_vars(Ss),
- {#ibinary{anno=A#a{us=Used},segments=Ss},St};
-uexpr(Lit, _, St) ->
- true = core_lib:is_simple(Lit), %Sanity check!
- Vs = lit_vars(Lit),
- Anno = core_lib:get_anno(Lit),
- {core_lib:set_anno(Lit, #a{us=Vs,anno=Anno}),St}.
-
-uexpr_list(Les0, Ks, St0) ->
- mapfoldl(fun (Le, St) -> uexpr(Le, Ks, St) end, St0, Les0).
-
-%% ufun_clauses([Lclause], [KnownVar], State) -> {[Lclause],State}.
-
-ufun_clauses(Lcs, Ks, St0) ->
- mapfoldl(fun (Lc, St) -> ufun_clause(Lc, Ks, St) end, St0, Lcs).
-
-%% ufun_clause(Lclause, [KnownVar], State) -> {Lclause,State}.
-
-ufun_clause(Cl0, Ks, St0) ->
- {Cl1,Pvs,Used,_,St1} = uclause(Cl0, [], Ks, St0),
- A0 = get_ianno(Cl1),
- A = A0#a{us=subtract(intersection(Used, Ks), Pvs),ns=[]},
- {Cl1#iclause{anno=A},St1}.
-
-%% upattern(Pat, [KnownVar], State) ->
-%% {Pat,[GuardTest],[NewVar],[UsedVar],State}.
-
-upattern(#c_var{name='_'}, _, St0) ->
- {New,St1} = new_var_name(St0),
- {#c_var{name=New},[],[New],[],St1};
-upattern(#c_var{name=V}=Var, Ks, St0) ->
- case is_element(V, Ks) of
- true ->
- {N,St1} = new_var_name(St0),
- New = #c_var{name=N},
- Test = #icall{anno=#a{us=add_element(N, [V])},
- module=#c_atom{val=erlang},
- name=#c_atom{val='=:='},
- args=[New,Var]},
- %% Test doesn't need protecting.
- {New,[Test],[N],[],St1};
- false -> {Var,[],[V],[],St0}
- end;
-upattern(#c_cons{hd=H0,tl=T0}=Cons, Ks, St0) ->
- {H1,Hg,Hv,Hu,St1} = upattern(H0, Ks, St0),
- {T1,Tg,Tv,Tu,St2} = upattern(T0, union(Hv, Ks), St1),
- {Cons#c_cons{hd=H1,tl=T1},Hg ++ Tg,union(Hv, Tv),union(Hu, Tu),St2};
-upattern(#c_tuple{es=Es0}=Tuple, Ks, St0) ->
- {Es1,Esg,Esv,Eus,St1} = upattern_list(Es0, Ks, St0),
- {Tuple#c_tuple{es=Es1},Esg,Esv,Eus,St1};
-upattern(#c_binary{segments=Es0}=Bin, Ks, St0) ->
- {Es1,Esg,Esv,Eus,St1} = upat_bin(Es0, Ks, St0),
- {Bin#c_binary{segments=Es1},Esg,Esv,Eus,St1};
-upattern(#c_alias{var=V0,pat=P0}=Alias, Ks, St0) ->
- {V1,Vg,Vv,Vu,St1} = upattern(V0, Ks, St0),
- {P1,Pg,Pv,Pu,St2} = upattern(P0, union(Vv, Ks), St1),
- {Alias#c_alias{var=V1,pat=P1},Vg ++ Pg,union(Vv, Pv),union(Vu, Pu),St2};
-upattern(Other, _, St) -> {Other,[],[],[],St}. %Constants
-
-%% upattern_list([Pat], [KnownVar], State) ->
-%% {[Pat],[GuardTest],[NewVar],[UsedVar],State}.
-
-upattern_list([P0|Ps0], Ks, St0) ->
- {P1,Pg,Pv,Pu,St1} = upattern(P0, Ks, St0),
- {Ps1,Psg,Psv,Psu,St2} = upattern_list(Ps0, union(Pv, Ks), St1),
- {[P1|Ps1],Pg ++ Psg,union(Pv, Psv),union(Pu, Psu),St2};
-upattern_list([], _, St) -> {[],[],[],[],St}.
-
-%% upat_bin([Pat], [KnownVar], State) ->
-%% {[Pat],[GuardTest],[NewVar],[UsedVar],State}.
-upat_bin(Es0, Ks, St0) ->
- upat_bin(Es0, Ks, [], St0).
-
-%% upat_bin([Pat], [KnownVar], [LocalVar], State) ->
-%% {[Pat],[GuardTest],[NewVar],[UsedVar],State}.
-upat_bin([P0|Ps0], Ks, Bs, St0) ->
- {P1,Pg,Pv,Pu,Bs1,St1} = upat_element(P0, Ks, Bs, St0),
- {Ps1,Psg,Psv,Psu,St2} = upat_bin(Ps0, union(Pv, Ks), Bs1, St1),
- {[P1|Ps1],Pg ++ Psg,union(Pv, Psv),union(Pu, Psu),St2};
-upat_bin([], _, _, St) -> {[],[],[],[],St}.
-
-
-%% upat_element(Segment, [KnownVar], [LocalVar], State) ->
-%% {Segment,[GuardTest],[NewVar],[UsedVar],[LocalVar],State}
-upat_element(#c_bitstr{val=H0,size=Sz}=Seg, Ks, Bs, St0) ->
- {H1,Hg,Hv,[],St1} = upattern(H0, Ks, St0),
- Bs1 = case H0 of
- #c_var{name=Hname} ->
- case H1 of
- #c_var{name=Hname} ->
- Bs;
- #c_var{name=Other} ->
- [{Hname, Other}|Bs]
- end;
- _ ->
- Bs
- end,
- {Sz1, Us} = case Sz of
- #c_var{name=Vname} ->
- rename_bitstr_size(Vname, Bs);
- _Other -> {Sz, []}
- end,
- {Seg#c_bitstr{val=H1, size=Sz1},Hg,Hv,Us,Bs1,St1}.
-
-rename_bitstr_size(V, [{V, N}|_]) ->
- New = #c_var{name=N},
- {New, [N]};
-rename_bitstr_size(V, [_|Rest]) ->
- rename_bitstr_size(V, Rest);
-rename_bitstr_size(V, []) ->
- Old = #c_var{name=V},
- {Old, [V]}.
-
-used_in_any(Les) ->
- foldl(fun (Le, Ns) -> union((core_lib:get_anno(Le))#a.us, Ns) end,
- [], Les).
-
-new_in_any(Les) ->
- foldl(fun (Le, Ns) -> union((core_lib:get_anno(Le))#a.ns, Ns) end,
- [], Les).
-
-new_in_all([Le|Les]) ->
- foldl(fun (L, Ns) -> intersection((core_lib:get_anno(L))#a.ns, Ns) end,
- (core_lib:get_anno(Le))#a.ns, Les);
-new_in_all([]) -> [].
-
-%% The AfterVars are the variables which are used afterwards. We need
-%% this to work out which variables are actually exported and used
-%% from case/receive. In subblocks/clauses the AfterVars of the block
-%% are just the exported variables.
-
-cbody(B0, St0) ->
- {B1,_,_,St1} = cexpr(B0, [], St0),
- {B1,St1}.
-
-%% cclause(Lclause, [AfterVar], State) -> {Cclause,State}.
-%% The AfterVars are the exported variables.
-
-cclause(#iclause{anno=#a{anno=Anno},pats=Ps,guard=G0,body=B0}, Exp, St0) ->
- {B1,_Us1,St1} = cexprs(B0, Exp, St0),
- {G1,St2} = cguard(G0, St1),
- {#c_clause{anno=Anno,pats=Ps,guard=G1,body=B1},St2}.
-
-cclauses(Lcs, Es, St0) ->
- mapfoldl(fun (Lc, St) -> cclause(Lc, Es, St) end, St0, Lcs).
-
-cguard([], St) -> {#c_atom{val=true},St};
-cguard(Gs, St0) ->
- {G,_,St1} = cexprs(Gs, [], St0),
- {G,St1}.
-
-%% cexprs([Lexpr], [AfterVar], State) -> {Cexpr,[AfterVar],State}.
-%% Must be sneaky here at the last expr when combining exports for the
-%% whole sequence and exports for that expr.
-
-cexprs([#iset{var=#c_var{name=Name}=Var}=Iset], As, St) ->
- %% Make return value explicit, and make Var true top level.
- cexprs([Iset,Var#c_var{anno=#a{us=[Name]}}], As, St);
-cexprs([Le], As, St0) ->
- {Ce,Es,Us,St1} = cexpr(Le, As, St0),
- Exp = make_vars(As), %The export variables
- if
- Es == [] -> {core_lib:make_values([Ce|Exp]),union(Us, As),St1};
- true ->
- {R,St2} = new_var(St1),
- {#c_let{anno=get_lineno_anno(Ce),
- vars=[R|make_vars(Es)],arg=Ce,
- body=core_lib:make_values([R|Exp])},
- union(Us, As),St2}
- end;
-cexprs([#iset{anno=#a{anno=A},var=V,arg=A0}|Les], As0, St0) ->
- {Ces,As1,St1} = cexprs(Les, As0, St0),
- {A1,Es,Us,St2} = cexpr(A0, As1, St1),
- {#c_let{anno=A,vars=[V|make_vars(Es)],arg=A1,body=Ces},
- union(Us, As1),St2};
-cexprs([Le|Les], As0, St0) ->
- {Ces,As1,St1} = cexprs(Les, As0, St0),
- {Ce,Es,Us,St2} = cexpr(Le, As1, St1),
- if
- Es == [] ->
- {#c_seq{arg=Ce,body=Ces},union(Us, As1),St2};
- true ->
- {R,St3} = new_var(St2),
- {#c_let{vars=[R|make_vars(Es)],arg=Ce,body=Ces},
- union(Us, As1),St3}
- end.
-
-%% cexpr(Lexpr, [AfterVar], State) -> {Cexpr,[ExpVar],[UsedVar],State}.
-
-cexpr(#iletrec{anno=A,defs=Fs0,body=B0}, As, St0) ->
- {Fs1,{_,St1}} = mapfoldl(fun ({Name,F0}, {Used,St0}) ->
- {F1,[],Us,St1} = cexpr(F0, [], St0),
- {#c_def{name=#c_fname{id=Name,arity=1},
- val=F1},
- {union(Us, Used),St1}}
- end, {[],St0}, Fs0),
- Exp = intersection(A#a.ns, As),
- {B1,_Us,St2} = cexprs(B0, Exp, St1),
- {#c_letrec{anno=A#a.anno,defs=Fs1,body=B1},Exp,A#a.us,St2};
-cexpr(#icase{anno=A,args=Largs,clauses=Lcs,fc=Lfc}, As, St0) ->
- Exp = intersection(A#a.ns, As), %Exports
- {Cargs,St1} = foldr(fun (La, {Cas,Sta}) ->
- {Ca,[],_Us1,Stb} = cexpr(La, As, Sta),
- {[Ca|Cas],Stb}
- end, {[],St0}, Largs),
- {Ccs,St2} = cclauses(Lcs, Exp, St1),
- {Cfc,St3} = cclause(Lfc, [], St2), %Never exports
- {#c_case{anno=A#a.anno,
- arg=core_lib:make_values(Cargs),clauses=Ccs ++ [Cfc]},
- Exp,A#a.us,St3};
-cexpr(#ireceive1{anno=A,clauses=Lcs}, As, St0) ->
- Exp = intersection(A#a.ns, As), %Exports
- {Ccs,St1} = cclauses(Lcs, Exp, St0),
- {#c_receive{anno=A#a.anno,
- clauses=Ccs,
- timeout=#c_atom{val=infinity},action=#c_atom{val=true}},
- Exp,A#a.us,St1};
-cexpr(#ireceive2{anno=A,clauses=Lcs,timeout=Lto,action=Les}, As, St0) ->
- Exp = intersection(A#a.ns, As), %Exports
- {Cto,[],_Us1,St1} = cexpr(Lto, As, St0),
- {Ccs,St2} = cclauses(Lcs, Exp, St1),
- {Ces,_Us2,St3} = cexprs(Les, Exp, St2),
- {#c_receive{anno=A#a.anno,
- clauses=Ccs,timeout=Cto,action=Ces},
- Exp,A#a.us,St3};
-cexpr(#itry{anno=A,args=La,vars=Vs,body=Lb,evars=Evs,handler=Lh}, As, St0) ->
- Exp = intersection(A#a.ns, As), %Exports
- {Ca,_Us1,St1} = cexprs(La, [], St0),
- {Cb,_Us2,St2} = cexprs(Lb, Exp, St1),
- {Ch,_Us3,St3} = cexprs(Lh, Exp, St2),
- {#c_try{anno=A#a.anno,arg=Ca,vars=Vs,body=Cb,evars=Evs,handler=Ch},
- Exp,A#a.us,St3};
-cexpr(#icatch{anno=A,body=Les}, _As, St0) ->
- {Ces,_Us1,St1} = cexprs(Les, [], St0), %Never export!
- {#c_catch{body=Ces},[],A#a.us,St1};
-cexpr(#ifun{anno=A,id=Id,vars=Args,clauses=Lcs,fc=Lfc}, _As, St0) ->
- {Ccs,St1} = cclauses(Lcs, [], St0), %NEVER export!
- {Cfc,St2} = cclause(Lfc, [], St1),
- Anno = A#a.anno,
- {#c_fun{anno=Id++Anno,vars=Args,
- body=#c_case{anno=Anno,
- arg=core_lib:set_anno(core_lib:make_values(Args), Anno),
- clauses=Ccs ++ [Cfc]}},
- [],A#a.us,St2};
-cexpr(#iapply{anno=A,op=Op,args=Args}, _As, St) ->
- {#c_apply{anno=A#a.anno,op=Op,args=Args},[],A#a.us,St};
-cexpr(#icall{anno=A,module=Mod,name=Name,args=Args}, _As, St) ->
- {#c_call{anno=A#a.anno,module=Mod,name=Name,args=Args},[],A#a.us,St};
-cexpr(#iprimop{anno=A,name=Name,args=Args}, _As, St) ->
- {#c_primop{anno=A#a.anno,name=Name,args=Args},[],A#a.us,St};
-cexpr(#iprotect{anno=A,body=Es}, _As, St0) ->
- {Ce,_,St1} = cexprs(Es, [], St0),
- V = #c_var{name='Try'}, %The names are arbitrary
- Vs = [#c_var{name='T'},#c_var{name='R'}],
- {#c_try{anno=A#a.anno,arg=Ce,vars=[V],body=V,
- evars=Vs,handler=#c_atom{val=false}},
- [],A#a.us,St1};
-cexpr(#ibinary{anno=#a{anno=Anno,us=Us},segments=Segs}, _As, St) ->
- {#c_binary{anno=Anno,segments=Segs},[],Us,St};
-cexpr(Lit, _As, St) ->
- true = core_lib:is_simple(Lit), %Sanity check!
- Anno = core_lib:get_anno(Lit),
- Vs = Anno#a.us,
- %%Vs = lit_vars(Lit),
- {core_lib:set_anno(Lit, Anno#a.anno),[],Vs,St}.
-
-%% lit_vars(Literal) -> [Var].
-
-lit_vars(Lit) -> lit_vars(Lit, []).
-
-lit_vars(#c_cons{hd=H,tl=T}, Vs) -> lit_vars(H, lit_vars(T, Vs));
-lit_vars(#c_tuple{es=Es}, Vs) -> lit_list_vars(Es, Vs);
-lit_vars(#c_var{name=V}, Vs) -> add_element(V, Vs);
-lit_vars(_, Vs) -> Vs. %These are atomic
-
-% lit_bin_vars(Segs, Vs) ->
-% foldl(fun (#c_bitstr{val=V,size=S}, Vs0) ->
-% lit_vars(V, lit_vars(S, Vs0))
-% end, Vs, Segs).
-
-lit_list_vars(Ls) -> lit_list_vars(Ls, []).
-
-lit_list_vars(Ls, Vs) ->
- foldl(fun (L, Vs0) -> lit_vars(L, Vs0) end, Vs, Ls).
-
-bitstr_vars(Segs) ->
- bitstr_vars(Segs, []).
-
-bitstr_vars(Segs, Vs) ->
- foldl(fun (#c_bitstr{val=V,size=S}, Vs0) ->
- lit_vars(V, lit_vars(S, Vs0))
- end, Vs, Segs).
-
-get_ianno(Ce) ->
- case core_lib:get_anno(Ce) of
- #a{}=A -> A;
- A when is_list(A) -> #a{anno=A}
- end.
-
-get_lineno_anno(Ce) ->
- case core_lib:get_anno(Ce) of
- #a{anno=A} -> A;
- A when is_list(A) -> A
- end.
-
-
-%%%
-%%% Handling of warnings.
-%%%
-
-format_error(nomatch) -> "pattern cannot possibly match".
-
-add_warning(Line, Term, #core{ws=Ws}=St) when Line >= 0 ->
- St#core{ws=[{Line,?MODULE,Term}|Ws]};
-add_warning(_, _, St) -> St.
-
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_kernel.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_kernel.erl
deleted file mode 100644
index 2d600fabc4..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_kernel.erl
+++ /dev/null
@@ -1,1568 +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: v3_kernel.erl,v 1.3 2010/03/04 13:54:20 maria Exp $
-%%
-%% Purpose : Transform Core Erlang to Kernel Erlang
-
-%% Kernel erlang is like Core Erlang with a few significant
-%% differences:
-%%
-%% 1. It is flat! There are no nested calls or sub-blocks.
-%%
-%% 2. All variables are unique in a function. There is no scoping, or
-%% rather the scope is the whole function.
-%%
-%% 3. Pattern matching (in cases and receives) has been compiled.
-%%
-%% 4. The annotations contain variable usages. Seeing we have to work
-%% this out anyway for funs we might as well pass it on for free to
-%% later passes.
-%%
-%% 5. All remote-calls are to statically named m:f/a. Meta-calls are
-%% passed via erlang:apply/3.
-%%
-%% The translation is done in two passes:
-%%
-%% 1. Basic translation, translate variable/function names, flatten
-%% completely, pattern matching compilation.
-%%
-%% 2. Fun-lifting (lambda-lifting), variable usage annotation and
-%% last-call handling.
-%%
-%% All new Kexprs are created in the first pass, they are just
-%% annotated in the second.
-%%
-%% Functions and BIFs
-%%
-%% Functions are "call"ed or "enter"ed if it is a last call, their
-%% return values may be ignored. BIFs are things which are known to
-%% be internal by the compiler and can only be called, their return
-%% values cannot be ignored.
-%%
-%% Letrec's are handled rather naively. All the functions in one
-%% letrec are handled as one block to find the free variables. While
-%% this is not optimal it reflects how letrec's often are used. We
-%% don't have to worry about variable shadowing and nested letrec's as
-%% this is handled in the variable/function name translation. There
-%% is a little bit of trickery to ensure letrec transformations fit
-%% into the scheme of things.
-%%
-%% To ensure unique variable names we use a variable substitution
-%% table and keep the set of all defined variables. The nested
-%% scoping of Core means that we must also nest the substitution
-%% tables, but the defined set must be passed through to match the
-%% flat structure of Kernel and to make sure variables with the same
-%% name from different scopes get different substitutions.
-%%
-%% We also use these substitutions to handle the variable renaming
-%% necessary in pattern matching compilation.
-%%
-%% The pattern matching compilation assumes that the values of
-%% different types don't overlap. This means that as there is no
-%% character type yet in the machine all characters must be converted
-%% to integers!
-
--module(v3_kernel).
-
--export([module/2,format_error/1]).
-
--import(lists, [map/2,foldl/3,foldr/3,mapfoldl/3,splitwith/2,
- member/2,reverse/1,reverse/2]).
--import(ordsets, [add_element/2,del_element/2,union/2,union/1,subtract/2]).
-
--include("core_parse.hrl").
--include("v3_kernel.hrl").
-
-%% These are not defined in v3_kernel.hrl.
-get_kanno(Kthing) -> element(2, Kthing).
-set_kanno(Kthing, Anno) -> setelement(2, Kthing, Anno).
-
-%% Internal kernel expressions and help functions.
-%% N.B. the annotation field is ALWAYS the first field!
-
--record(ivalues, {anno=[],args}).
--record(ifun, {anno=[],vars,body}).
--record(iset, {anno=[],vars,arg,body}).
--record(iletrec, {anno=[],defs}).
--record(ialias, {anno=[],vars,pat}).
--record(iclause, {anno=[],sub,pats,guard,body}).
--record(ireceive_accept, {anno=[],arg}).
--record(ireceive_next, {anno=[],arg}).
-
-%% State record for kernel translator.
--record(kern, {func, %Current function
- vcount=0, %Variable counter
- fcount=0, %Fun counter
- ds=[], %Defined variables
- funs=[], %Fun functions
- free=[], %Free variables
- ws=[], %Warnings.
- extinstr=false}). %Generate extended instructions
-
-module(#c_module{anno=A,name=M,exports=Es,attrs=As,defs=Fs}, Options) ->
- ExtInstr = not member(no_new_apply, Options),
- {Kfs,St} = mapfoldl(fun function/2, #kern{extinstr=ExtInstr}, Fs),
- Kes = map(fun (#c_fname{id=N,arity=Ar}) -> {N,Ar} end, Es),
- Kas = map(fun (#c_def{name=#c_atom{val=N},val=V}) ->
- {N,core_lib:literal_value(V)} end, As),
- {ok,#k_mdef{anno=A,name=M#c_atom.val,exports=Kes,attributes=Kas,
- body=Kfs ++ St#kern.funs},St#kern.ws}.
-
-function(#c_def{anno=Af,name=#c_fname{id=F,arity=Arity},val=Body}, St0) ->
- %%ok = io:fwrite("kern: ~p~n", [{F,Arity}]),
- St1 = St0#kern{func={F,Arity},vcount=0,fcount=0,ds=sets:new()},
- {#ifun{anno=Ab,vars=Kvs,body=B0},[],St2} = expr(Body, new_sub(), St1),
- {B1,_,St3} = ubody(B0, return, St2),
- %%B1 = B0, St3 = St2, %Null second pass
- {#k_fdef{anno=#k{us=[],ns=[],a=Af ++ Ab},
- func=F,arity=Arity,vars=Kvs,body=B1},St3}.
-
-%% body(Cexpr, Sub, State) -> {Kexpr,[PreKepxr],State}.
-%% Do the main sequence of a body. A body ends in an atomic value or
-%% values. Must check if vector first so do expr.
-
-body(#c_values{anno=A,es=Ces}, Sub, St0) ->
- %% Do this here even if only in bodies.
- {Kes,Pe,St1} = atomic_list(Ces, Sub, St0),
- %%{Kes,Pe,St1} = expr_list(Ces, Sub, St0),
- {#ivalues{anno=A,args=Kes},Pe,St1};
-body(#ireceive_next{anno=A}, _, St) ->
- {#k_receive_next{anno=A},[],St};
-body(Ce, Sub, St0) ->
- expr(Ce, Sub, St0).
-
-%% guard(Cexpr, Sub, State) -> {Kexpr,State}.
-%% We handle guards almost as bodies. The only special thing we
-%% must do is to make the final Kexpr a #k_test{}.
-%% Also, we wrap the entire guard in a try/catch which is
-%% not strictly needed, but makes sure that every 'bif' instruction
-%% will get a proper failure label.
-
-guard(G0, Sub, St0) ->
- {G1,St1} = wrap_guard(G0, St0),
- {Ge0,Pre,St2} = expr(G1, Sub, St1),
- {Ge,St} = gexpr_test(Ge0, St2),
- {pre_seq(Pre, Ge),St}.
-
-%% Wrap the entire guard in a try/catch if needed.
-
-wrap_guard(#c_try{}=Try, St) -> {Try,St};
-wrap_guard(Core, St0) ->
- {VarName,St} = new_var_name(St0),
- Var = #c_var{name=VarName},
- Try = #c_try{arg=Core,vars=[Var],body=Var,evars=[],handler=#c_atom{val=false}},
- {Try,St}.
-
-%% gexpr_test(Kexpr, State) -> {Kexpr,State}.
-%% Builds the final boolean test from the last Kexpr in a guard test.
-%% Must enter try blocks and isets and find the last Kexpr in them.
-%% This must end in a recognised BEAM test!
-
-gexpr_test(#k_bif{anno=A,op=#k_remote{mod=#k_atom{val=erlang},
- name=#k_atom{val=is_boolean},arity=1}=Op,
- args=Kargs}, St) ->
- %% XXX Remove this clause in R11. For bootstrap purposes, we must
- %% recognize erlang:is_boolean/1 here.
- {#k_test{anno=A,op=Op,args=Kargs},St};
-gexpr_test(#k_bif{anno=A,op=#k_remote{mod=#k_atom{val=erlang},
- name=#k_atom{val=internal_is_record},arity=3}=Op,
- args=Kargs}, St) ->
- {#k_test{anno=A,op=Op,args=Kargs},St};
-gexpr_test(#k_bif{anno=A,op=#k_remote{mod=#k_atom{val=erlang},
- name=#k_atom{val=F},arity=Ar}=Op,
- args=Kargs}=Ke, St) ->
- %% Either convert to test if ok, or add test.
- %% At this stage, erlang:float/1 is not a type test. (It should
- %% have been converted to erlang:is_float/1.)
- case erl_internal:new_type_test(F, Ar) orelse
- erl_internal:comp_op(F, Ar) of
- true -> {#k_test{anno=A,op=Op,args=Kargs},St};
- false -> gexpr_test_add(Ke, St) %Add equality test
- end;
-gexpr_test(#k_try{arg=B0,vars=[#k_var{name=X}],body=#k_var{name=X},
- handler=#k_atom{val=false}}=Try, St0) ->
- {B,St} = gexpr_test(B0, St0),
- %%ok = io:fwrite("~w: ~p~n", [?LINE,{B0,B}]),
- {Try#k_try{arg=B},St};
-gexpr_test(#iset{body=B0}=Iset, St0) ->
- {B1,St1} = gexpr_test(B0, St0),
- {Iset#iset{body=B1},St1};
-gexpr_test(Ke, St) -> gexpr_test_add(Ke, St). %Add equality test
-
-gexpr_test_add(Ke, St0) ->
- Test = #k_remote{mod=#k_atom{val='erlang'},
- name=#k_atom{val='=:='},
- arity=2},
- {Ae,Ap,St1} = force_atomic(Ke, St0),
- {pre_seq(Ap, #k_test{anno=get_kanno(Ke),
- op=Test,args=[Ae,#k_atom{val='true'}]}),St1}.
-
-%% expr(Cexpr, Sub, State) -> {Kexpr,[PreKexpr],State}.
-%% Convert a Core expression, flattening it at the same time.
-
-expr(#c_var{anno=A,name=V}, Sub, St) ->
- {#k_var{anno=A,name=get_vsub(V, Sub)},[],St};
-expr(#c_char{anno=A,val=C}, _Sub, St) ->
- {#k_int{anno=A,val=C},[],St}; %Convert to integers!
-expr(#c_int{anno=A,val=I}, _Sub, St) ->
- {#k_int{anno=A,val=I},[],St};
-expr(#c_float{anno=A,val=F}, _Sub, St) ->
- {#k_float{anno=A,val=F},[],St};
-expr(#c_atom{anno=A,val=At}, _Sub, St) ->
- {#k_atom{anno=A,val=At},[],St};
-expr(#c_string{anno=A,val=S}, _Sub, St) ->
- {#k_string{anno=A,val=S},[],St};
-expr(#c_nil{anno=A}, _Sub, St) ->
- {#k_nil{anno=A},[],St};
-expr(#c_cons{anno=A,hd=Ch,tl=Ct}, Sub, St0) ->
- %% Do cons in two steps, first the expressions left to right, then
- %% any remaining literals right to left.
- {Kh0,Hp0,St1} = expr(Ch, Sub, St0),
- {Kt0,Tp0,St2} = expr(Ct, Sub, St1),
- {Kt1,Tp1,St3} = force_atomic(Kt0, St2),
- {Kh1,Hp1,St4} = force_atomic(Kh0, St3),
- {#k_cons{anno=A,hd=Kh1,tl=Kt1},Hp0 ++ Tp0 ++ Tp1 ++ Hp1,St4};
-expr(#c_tuple{anno=A,es=Ces}, Sub, St0) ->
- {Kes,Ep,St1} = atomic_list(Ces, Sub, St0),
- {#k_tuple{anno=A,es=Kes},Ep,St1};
-expr(#c_binary{anno=A,segments=Cv}, Sub, St0) ->
- case catch atomic_bin(Cv, Sub, St0, 0) of
- {'EXIT',R} -> exit(R);
- bad_element_size ->
- Erl = #c_atom{val=erlang},
- Name = #c_atom{val=error},
- Args = [#c_atom{val=badarg}],
- Fault = #c_call{module=Erl,name=Name,args=Args},
- expr(Fault, Sub, St0);
- {Kv,Ep,St1} ->
- {#k_binary{anno=A,segs=Kv},Ep,St1}
- end;
-expr(#c_fname{anno=A,arity=Ar}=Fname, Sub, St) ->
- %% A local in an expression.
- %% For now, these are wrapped into a fun by reverse
- %% etha-conversion, but really, there should be exactly one
- %% such "lambda function" for each escaping local name,
- %% instead of one for each occurrence as done now.
- Vs = [#c_var{name=list_to_atom("V" ++ integer_to_list(V))} ||
- V <- integers(1, Ar)],
- Fun = #c_fun{anno=A,vars=Vs,body=#c_apply{op=Fname,args=Vs}},
- expr(Fun, Sub, St);
-expr(#c_fun{anno=A,vars=Cvs,body=Cb}, Sub0, St0) ->
- {Kvs,Sub1,St1} = pattern_list(Cvs, Sub0, St0),
- %%ok = io:fwrite("~w: ~p~n", [?LINE,{{Cvs,Sub0,St0},{Kvs,Sub1,St1}}]),
- {Kb,Pb,St2} = body(Cb, Sub1, St1),
- {#ifun{anno=A,vars=Kvs,body=pre_seq(Pb, Kb)},[],St2};
-expr(#c_seq{arg=Ca,body=Cb}, Sub, St0) ->
- {Ka,Pa,St1} = body(Ca, Sub, St0),
- case is_exit_expr(Ka) of
- true -> {Ka,Pa,St1};
- false ->
- {Kb,Pb,St2} = body(Cb, Sub, St1),
- {Kb,Pa ++ [Ka] ++ Pb,St2}
- end;
-expr(#c_let{anno=A,vars=Cvs,arg=Ca,body=Cb}, Sub0, St0) ->
- %%ok = io:fwrite("~w: ~p~n", [?LINE,{Cvs,Sub0,St0}]),
- {Ka,Pa,St1} = body(Ca, Sub0, St0),
- case is_exit_expr(Ka) of
- true -> {Ka,Pa,St1};
- false ->
- {Kps,Sub1,St2} = pattern_list(Cvs, Sub0, St1),
- %%ok = io:fwrite("~w: ~p~n", [?LINE,{Kps,Sub1,St1,St2}]),
- %% Break known multiple values into separate sets.
- Sets = case Ka of
- #ivalues{args=Kas} ->
- foldr2(fun (V, Val, Sb) ->
- [#iset{vars=[V],arg=Val}|Sb] end,
- [], Kps, Kas);
- _Other ->
- [#iset{anno=A,vars=Kps,arg=Ka}]
- end,
- {Kb,Pb,St3} = body(Cb, Sub1, St2),
- {Kb,Pa ++ Sets ++ Pb,St3}
- end;
-expr(#c_letrec{anno=A,defs=Cfs,body=Cb}, Sub0, St0) ->
- %% Make new function names and store substitution.
- {Fs0,{Sub1,St1}} =
- mapfoldl(fun (#c_def{name=#c_fname{id=F,arity=Ar},val=B}, {Sub,St0}) ->
- {N,St1} = new_fun_name(atom_to_list(F)
- ++ "/" ++
- integer_to_list(Ar),
- St0),
- {{N,B},{set_fsub(F, Ar, N, Sub),St1}}
- end, {Sub0,St0}, Cfs),
- %% Run translation on functions and body.
- {Fs1,St2} = mapfoldl(fun ({N,Fd0}, St1) ->
- {Fd1,[],St2} = expr(Fd0, Sub1, St1),
- Fd = set_kanno(Fd1, A),
- {{N,Fd},St2}
- end, St1, Fs0),
- {Kb,Pb,St3} = body(Cb, Sub1, St2),
- {Kb,[#iletrec{anno=A,defs=Fs1}|Pb],St3};
-expr(#c_case{arg=Ca,clauses=Ccs}, Sub, St0) ->
- {Ka,Pa,St1} = body(Ca, Sub, St0), %This is a body!
- {Kvs,Pv,St2} = match_vars(Ka, St1), %Must have variables here!
- {Km,St3} = kmatch(Kvs, Ccs, Sub, St2),
- Match = flatten_seq(build_match(Kvs, Km)),
- {last(Match),Pa ++ Pv ++ first(Match),St3};
-expr(#c_receive{anno=A,clauses=Ccs0,timeout=Ce,action=Ca}, Sub, St0) ->
- {Ke,Pe,St1} = atomic_lit(Ce, Sub, St0), %Force this to be atomic!
- {Rvar,St2} = new_var(St1),
- %% Need to massage accept clauses and add reject clause before matching.
- Ccs1 = map(fun (#c_clause{anno=Banno,body=B0}=C) ->
- B1 = #c_seq{arg=#ireceive_accept{anno=A},body=B0},
- C#c_clause{anno=Banno,body=B1}
- end, Ccs0),
- {Mpat,St3} = new_var_name(St2),
- Rc = #c_clause{anno=[compiler_generated|A],
- pats=[#c_var{name=Mpat}],guard=#c_atom{anno=A,val=true},
- body=#ireceive_next{anno=A}},
- {Km,St4} = kmatch([Rvar], Ccs1 ++ [Rc], Sub, add_var_def(Rvar, St3)),
- {Ka,Pa,St5} = body(Ca, Sub, St4),
- {#k_receive{anno=A,var=Rvar,body=Km,timeout=Ke,action=pre_seq(Pa, Ka)},
- Pe,St5};
-expr(#c_apply{anno=A,op=Cop,args=Cargs}, Sub, St) ->
- c_apply(A, Cop, Cargs, Sub, St);
-expr(#c_call{anno=A,module=M0,name=F0,args=Cargs}, Sub, St0) ->
- {[M1,F1|Kargs],Ap,St1} = atomic_list([M0,F0|Cargs], Sub, St0),
- Ar = length(Cargs),
- case {M1,F1} of
- {#k_atom{val=Ma},#k_atom{val=Fa}} ->
- Call = case is_remote_bif(Ma, Fa, Ar) of
- true ->
- #k_bif{anno=A,
- op=#k_remote{mod=M1,name=F1,arity=Ar},
- args=Kargs};
- false ->
- #k_call{anno=A,
- op=#k_remote{mod=M1,name=F1,arity=Ar},
- args=Kargs}
- end,
- {Call,Ap,St1};
- _Other when St0#kern.extinstr == false -> %Old explicit apply
- Call = #c_call{anno=A,
- module=#c_atom{val=erlang},
- name=#c_atom{val=apply},
- args=[M0,F0,make_list(Cargs)]},
- expr(Call, Sub, St0);
- _Other -> %New instruction in R10.
- Call = #k_call{anno=A,
- op=#k_remote{mod=M1,name=F1,arity=Ar},
- args=Kargs},
- {Call,Ap,St1}
- end;
-expr(#c_primop{anno=A,name=#c_atom{val=match_fail},args=Cargs}, Sub, St0) ->
- %% This special case will disappear.
- {Kargs,Ap,St1} = atomic_list(Cargs, Sub, St0),
- Ar = length(Cargs),
- Call = #k_call{anno=A,op=#k_internal{name=match_fail,arity=Ar},args=Kargs},
- {Call,Ap,St1};
-expr(#c_primop{anno=A,name=#c_atom{val=N},args=Cargs}, Sub, St0) ->
- {Kargs,Ap,St1} = atomic_list(Cargs, Sub, St0),
- Ar = length(Cargs),
- {#k_bif{anno=A,op=#k_internal{name=N,arity=Ar},args=Kargs},Ap,St1};
-expr(#c_try{anno=A,arg=Ca,vars=Cvs,body=Cb,evars=Evs,handler=Ch}, Sub0, St0) ->
- %% The normal try expression. The body and exception handler
- %% variables behave as let variables.
- {Ka,Pa,St1} = body(Ca, Sub0, St0),
- {Kcvs,Sub1,St2} = pattern_list(Cvs, Sub0, St1),
- {Kb,Pb,St3} = body(Cb, Sub1, St2),
- {Kevs,Sub2,St4} = pattern_list(Evs, Sub0, St3),
- {Kh,Ph,St5} = body(Ch, Sub2, St4),
- {#k_try{anno=A,arg=pre_seq(Pa, Ka),
- vars=Kcvs,body=pre_seq(Pb, Kb),
- evars=Kevs,handler=pre_seq(Ph, Kh)},[],St5};
-expr(#c_catch{anno=A,body=Cb}, Sub, St0) ->
- {Kb,Pb,St1} = body(Cb, Sub, St0),
- {#k_catch{anno=A,body=pre_seq(Pb, Kb)},[],St1};
-%% Handle internal expressions.
-expr(#ireceive_accept{anno=A}, _Sub, St) -> {#k_receive_accept{anno=A},[],St}.
-
-%% expr_list([Cexpr], Sub, State) -> {[Kexpr],[PreKexpr],State}.
-
-% expr_list(Ces, Sub, St) ->
-% foldr(fun (Ce, {Kes,Esp,St0}) ->
-% {Ke,Ep,St1} = expr(Ce, Sub, St0),
-% {[Ke|Kes],Ep ++ Esp,St1}
-% end, {[],[],St}, Ces).
-
-%% match_vars(Kexpr, State) -> {[Kvar],[PreKexpr],State}.
-%% Force return from body into a list of variables.
-
-match_vars(#ivalues{args=As}, St) ->
- foldr(fun (Ka, {Vs,Vsp,St0}) ->
- {V,Vp,St1} = force_variable(Ka, St0),
- {[V|Vs],Vp ++ Vsp,St1}
- end, {[],[],St}, As);
-match_vars(Ka, St0) ->
- {V,Vp,St1} = force_variable(Ka, St0),
- {[V],Vp,St1}.
-
-%% c_apply(A, Op, [Carg], Sub, State) -> {Kexpr,[PreKexpr],State}.
-%% Transform application, detect which are guaranteed to be bifs.
-
-c_apply(A, #c_fname{anno=Ra,id=F0,arity=Ar}, Cargs, Sub, St0) ->
- {Kargs,Ap,St1} = atomic_list(Cargs, Sub, St0),
- F1 = get_fsub(F0, Ar, Sub), %Has it been rewritten
- {#k_call{anno=A,op=#k_local{anno=Ra,name=F1,arity=Ar},args=Kargs},
- Ap,St1};
-c_apply(A, Cop, Cargs, Sub, St0) ->
- {Kop,Op,St1} = variable(Cop, Sub, St0),
- {Kargs,Ap,St2} = atomic_list(Cargs, Sub, St1),
- {#k_call{anno=A,op=Kop,args=Kargs},Op ++ Ap,St2}.
-
-flatten_seq(#iset{anno=A,vars=Vs,arg=Arg,body=B}) ->
- [#iset{anno=A,vars=Vs,arg=Arg}|flatten_seq(B)];
-flatten_seq(Ke) -> [Ke].
-
-pre_seq([#iset{anno=A,vars=Vs,arg=Arg,body=B}|Ps], K) ->
- B = undefined, %Assertion.
- #iset{anno=A,vars=Vs,arg=Arg,body=pre_seq(Ps, K)};
-pre_seq([P|Ps], K) ->
- #iset{vars=[],arg=P,body=pre_seq(Ps, K)};
-pre_seq([], K) -> K.
-
-%% atomic_lit(Cexpr, Sub, State) -> {Katomic,[PreKexpr],State}.
-%% Convert a Core expression making sure the result is an atomic
-%% literal.
-
-atomic_lit(Ce, Sub, St0) ->
- {Ke,Kp,St1} = expr(Ce, Sub, St0),
- {Ka,Ap,St2} = force_atomic(Ke, St1),
- {Ka,Kp ++ Ap,St2}.
-
-force_atomic(Ke, St0) ->
- case is_atomic(Ke) of
- true -> {Ke,[],St0};
- false ->
- {V,St1} = new_var(St0),
- {V,[#iset{vars=[V],arg=Ke}],St1}
- end.
-
-% force_atomic_list(Kes, St) ->
-% foldr(fun (Ka, {As,Asp,St0}) ->
-% {A,Ap,St1} = force_atomic(Ka, St0),
-% {[A|As],Ap ++ Asp,St1}
-% end, {[],[],St}, Kes).
-
-atomic_bin([#c_bitstr{anno=A,val=E0,size=S0,unit=U,type=T,flags=Fs}|Es0],
- Sub, St0, B0) ->
- {E,Ap1,St1} = atomic_lit(E0, Sub, St0),
- {S1,Ap2,St2} = atomic_lit(S0, Sub, St1),
- validate_bin_element_size(S1),
- U0 = core_lib:literal_value(U),
- Fs0 = core_lib:literal_value(Fs),
- {B1,Fs1} = aligned(B0, S1, U0, Fs0),
- {Es,Ap3,St3} = atomic_bin(Es0, Sub, St2, B1),
- {#k_bin_seg{anno=A,size=S1,
- unit=U0,
- type=core_lib:literal_value(T),
- flags=Fs1,
- seg=E,next=Es},
- Ap1++Ap2++Ap3,St3};
-atomic_bin([], _Sub, St, _Bits) -> {#k_bin_end{},[],St}.
-
-validate_bin_element_size(#k_var{}) -> ok;
-validate_bin_element_size(#k_int{val=V}) when V >= 0 -> ok;
-validate_bin_element_size(#k_atom{val=all}) -> ok;
-validate_bin_element_size(_) -> throw(bad_element_size).
-
-%% atomic_list([Cexpr], Sub, State) -> {[Kexpr],[PreKexpr],State}.
-
-atomic_list(Ces, Sub, St) ->
- foldr(fun (Ce, {Kes,Esp,St0}) ->
- {Ke,Ep,St1} = atomic_lit(Ce, Sub, St0),
- {[Ke|Kes],Ep ++ Esp,St1}
- end, {[],[],St}, Ces).
-
-%% is_atomic(Kexpr) -> boolean().
-%% Is a Kexpr atomic? Strings are NOT considered atomic!
-
-is_atomic(#k_int{}) -> true;
-is_atomic(#k_float{}) -> true;
-is_atomic(#k_atom{}) -> true;
-%%is_atomic(#k_char{}) -> true; %No characters
-%%is_atomic(#k_string{}) -> true;
-is_atomic(#k_nil{}) -> true;
-is_atomic(#k_var{}) -> true;
-is_atomic(_) -> false.
-
-%% variable(Cexpr, Sub, State) -> {Kvar,[PreKexpr],State}.
-%% Convert a Core expression making sure the result is a variable.
-
-variable(Ce, Sub, St0) ->
- {Ke,Kp,St1} = expr(Ce, Sub, St0),
- {Kv,Vp,St2} = force_variable(Ke, St1),
- {Kv,Kp ++ Vp,St2}.
-
-force_variable(#k_var{}=Ke, St) -> {Ke,[],St};
-force_variable(Ke, St0) ->
- {V,St1} = new_var(St0),
- {V,[#iset{vars=[V],arg=Ke}],St1}.
-
-%% pattern(Cpat, Sub, State) -> {Kpat,Sub,State}.
-%% Convert patterns. Variables shadow so rename variables that are
-%% already defined.
-
-pattern(#c_var{anno=A,name=V}, Sub, St0) ->
- case sets:is_element(V, St0#kern.ds) of
- true ->
- {New,St1} = new_var_name(St0),
- {#k_var{anno=A,name=New},
- set_vsub(V, New, Sub),
- St1#kern{ds=sets:add_element(New, St1#kern.ds)}};
- false ->
- {#k_var{anno=A,name=V},Sub,
- St0#kern{ds=sets:add_element(V, St0#kern.ds)}}
- end;
-pattern(#c_char{anno=A,val=C}, Sub, St) ->
- {#k_int{anno=A,val=C},Sub,St}; %Convert to integers!
-pattern(#c_int{anno=A,val=I}, Sub, St) ->
- {#k_int{anno=A,val=I},Sub,St};
-pattern(#c_float{anno=A,val=F}, Sub, St) ->
- {#k_float{anno=A,val=F},Sub,St};
-pattern(#c_atom{anno=A,val=At}, Sub, St) ->
- {#k_atom{anno=A,val=At},Sub,St};
-pattern(#c_string{val=S}, Sub, St) ->
- L = foldr(fun (C, T) -> #k_cons{hd=#k_int{val=C},tl=T} end,
- #k_nil{}, S),
- {L,Sub,St};
-pattern(#c_nil{anno=A}, Sub, St) ->
- {#k_nil{anno=A},Sub,St};
-pattern(#c_cons{anno=A,hd=Ch,tl=Ct}, Sub0, St0) ->
- {Kh,Sub1,St1} = pattern(Ch, Sub0, St0),
- {Kt,Sub2,St2} = pattern(Ct, Sub1, St1),
- {#k_cons{anno=A,hd=Kh,tl=Kt},Sub2,St2};
-pattern(#c_tuple{anno=A,es=Ces}, Sub0, St0) ->
- {Kes,Sub1,St1} = pattern_list(Ces, Sub0, St0),
- {#k_tuple{anno=A,es=Kes},Sub1,St1};
-pattern(#c_binary{anno=A,segments=Cv}, Sub0, St0) ->
- {Kv,Sub1,St1} = pattern_bin(Cv, Sub0, St0),
- {#k_binary{anno=A,segs=Kv},Sub1,St1};
-pattern(#c_alias{anno=A,var=Cv,pat=Cp}, Sub0, St0) ->
- {Cvs,Cpat} = flatten_alias(Cp),
- {Kvs,Sub1,St1} = pattern_list([Cv|Cvs], Sub0, St0),
- {Kpat,Sub2,St2} = pattern(Cpat, Sub1, St1),
- {#ialias{anno=A,vars=Kvs,pat=Kpat},Sub2,St2}.
-
-flatten_alias(#c_alias{var=V,pat=P}) ->
- {Vs,Pat} = flatten_alias(P),
- {[V|Vs],Pat};
-flatten_alias(Pat) -> {[],Pat}.
-
-pattern_bin(Es, Sub, St) -> pattern_bin(Es, Sub, St, 0).
-
-pattern_bin([#c_bitstr{anno=A,val=E0,size=S0,unit=U,type=T,flags=Fs}|Es0],
- Sub0, St0, B0) ->
- {S1,[],St1} = expr(S0, Sub0, St0),
- U0 = core_lib:literal_value(U),
- Fs0 = core_lib:literal_value(Fs),
- %%ok= io:fwrite("~w: ~p~n", [?LINE,{B0,S1,U0,Fs0}]),
- {B1,Fs1} = aligned(B0, S1, U0, Fs0),
- {E,Sub1,St2} = pattern(E0, Sub0, St1),
- {Es,Sub2,St3} = pattern_bin(Es0, Sub1, St2, B1),
- {#k_bin_seg{anno=A,size=S1,
- unit=U0,
- type=core_lib:literal_value(T),
- flags=Fs1,
- seg=E,next=Es},
- Sub2,St3};
-pattern_bin([], Sub, St, _Bits) -> {#k_bin_end{},Sub,St}.
-
-%% pattern_list([Cexpr], Sub, State) -> {[Kexpr],Sub,State}.
-
-pattern_list(Ces, Sub, St) ->
- foldr(fun (Ce, {Kes,Sub0,St0}) ->
- {Ke,Sub1,St1} = pattern(Ce, Sub0, St0),
- {[Ke|Kes],Sub1,St1}
- end, {[],Sub,St}, Ces).
-
-%% new_sub() -> Subs.
-%% set_vsub(Name, Sub, Subs) -> Subs.
-%% subst_vsub(Name, Sub, Subs) -> Subs.
-%% get_vsub(Name, Subs) -> SubName.
-%% Add/get substitute Sub for Name to VarSub. Use orddict so we know
-%% the format is a list {Name,Sub} pairs. When adding a new
-%% substitute we fold substitute chains so we never have to search
-%% more than once.
-
-new_sub() -> orddict:new().
-
-get_vsub(V, Vsub) ->
- case orddict:find(V, Vsub) of
- {ok,Val} -> Val;
- error -> V
- end.
-
-set_vsub(V, S, Vsub) ->
- orddict:store(V, S, Vsub).
-
-subst_vsub(V, S, Vsub0) ->
- %% Fold chained substitutions.
- Vsub1 = orddict:map(fun (_, V1) when V1 =:= V -> S;
- (_, V1) -> V1
- end, Vsub0),
- orddict:store(V, S, Vsub1).
-
-get_fsub(F, A, Fsub) ->
- case orddict:find({F,A}, Fsub) of
- {ok,Val} -> Val;
- error -> F
- end.
-
-set_fsub(F, A, S, Fsub) ->
- orddict:store({F,A}, S, Fsub).
-
-new_fun_name(St) ->
- new_fun_name("anonymous", St).
-
-%% new_fun_name(Type, State) -> {FunName,State}.
-
-new_fun_name(Type, #kern{func={F,Arity},fcount=C}=St) ->
- Name = "-" ++ atom_to_list(F) ++ "/" ++ integer_to_list(Arity) ++
- "-" ++ Type ++ "-" ++ integer_to_list(C) ++ "-",
- {list_to_atom(Name),St#kern{fcount=C+1}}.
-
-%% new_var_name(State) -> {VarName,State}.
-
-new_var_name(#kern{vcount=C}=St) ->
- {list_to_atom("ker" ++ integer_to_list(C)),St#kern{vcount=C+1}}.
-
-%% new_var(State) -> {#k_var{},State}.
-
-new_var(St0) ->
- {New,St1} = new_var_name(St0),
- {#k_var{name=New},St1}.
-
-%% new_vars(Count, State) -> {[#k_var{}],State}.
-%% Make Count new variables.
-
-new_vars(N, St) -> new_vars(N, St, []).
-
-new_vars(N, St0, Vs) when N > 0 ->
- {V,St1} = new_var(St0),
- new_vars(N-1, St1, [V|Vs]);
-new_vars(0, St, Vs) -> {Vs,St}.
-
-make_vars(Vs) -> [ #k_var{name=V} || V <- Vs ].
-
-add_var_def(V, St) ->
- St#kern{ds=sets:add_element(V#k_var.name, St#kern.ds)}.
-
-%%add_vars_def(Vs, St) ->
-%% Ds = foldl(fun (#k_var{name=V}, Ds) -> add_element(V, Ds) end,
-%% St#kern.ds, Vs),
-%% St#kern{ds=Ds}.
-
-%% is_remote_bif(Mod, Name, Arity) -> true | false.
-%% Test if function is really a BIF.
-
-is_remote_bif(erlang, is_boolean, 1) ->
- %% XXX Remove this clause in R11. For bootstrap purposes, we must
- %% recognize erlang:is_boolean/1 here.
- true;
-is_remote_bif(erlang, internal_is_record, 3) -> true;
-is_remote_bif(erlang, get, 1) -> true;
-is_remote_bif(erlang, N, A) ->
- case erl_internal:guard_bif(N, A) of
- true -> true;
- false ->
- case erl_internal:type_test(N, A) of
- true -> true;
- false ->
- case catch erl_internal:op_type(N, A) of
- arith -> true;
- bool -> true;
- comp -> true;
- _Other -> false %List, send or not an op
- end
- end
- end;
-is_remote_bif(_, _, _) -> false.
-
-%% bif_vals(Name, Arity) -> integer().
-%% bif_vals(Mod, Name, Arity) -> integer().
-%% Determine how many return values a BIF has. Provision for BIFs to
-%% return multiple values. Only used in bodies where a BIF may be
-%% called for effect only.
-
-bif_vals(dsetelement, 3) -> 0;
-bif_vals(_, _) -> 1.
-
-bif_vals(_, _, _) -> 1.
-
-%% foldr2(Fun, Acc, List1, List2) -> Acc.
-%% Fold over two lists.
-
-foldr2(Fun, Acc0, [E1|L1], [E2|L2]) ->
- Acc1 = Fun(E1, E2, Acc0),
- foldr2(Fun, Acc1, L1, L2);
-foldr2(_, Acc, [], []) -> Acc.
-
-%% first([A]) -> [A].
-%% last([A]) -> A.
-
-last([L]) -> L;
-last([_|T]) -> last(T).
-
-first([_]) -> [];
-first([H|T]) -> [H|first(T)].
-
-%% This code implements the algorithm for an optimizing compiler for
-%% pattern matching given "The Implementation of Functional
-%% Programming Languages" by Simon Peyton Jones. The code is much
-%% longer as the meaning of constructors is different from the book.
-%%
-%% In Erlang many constructors can have different values, e.g. 'atom'
-%% or 'integer', whereas in the original algorithm thse would be
-%% different constructors. Our view makes it easier in later passes to
-%% handle indexing over each type.
-%%
-%% Patterns are complicated by having alias variables. The form of a
-%% pattern is Pat | {alias,Pat,[AliasVar]}. This is hidden by access
-%% functions to pattern arguments but the code must be aware of it.
-%%
-%% The compilation proceeds in two steps:
-%%
-%% 1. The patterns in the clauses to converted to lists of kernel
-%% patterns. The Core clause is now hybrid, this is easier to work
-%% with. Remove clauses with trivially false guards, this simplifies
-%% later passes. Add local defined vars and variable subs to each
-%% clause for later use.
-%%
-%% 2. The pattern matching is optimised. Variable substitutions are
-%% added to the VarSub structure and new variables are made visible.
-%% The guard and body are then converted to Kernel form.
-
-%% kmatch([Var], [Clause], Sub, State) -> {Kexpr,[PreExpr],State}.
-
-kmatch(Us, Ccs, Sub, St0) ->
- {Cs,St1} = match_pre(Ccs, Sub, St0), %Convert clauses
- %%Def = kernel_match_error, %The strict case
- %% This should be a kernel expression from the first pass.
- Def = #k_call{anno=[compiler_generated],
- op=#k_remote{mod=#k_atom{val=erlang},
- name=#k_atom{val=exit},
- arity=1},
- args=[#k_atom{val=kernel_match_error}]},
- {Km,St2} = match(Us, Cs, Def, St1), %Do the match.
- {Km,St2}.
-
-%% match_pre([Cclause], Sub, State) -> {[Clause],State}.
-%% Must be careful not to generate new substitutions here now!
-%% Remove clauses with trivially false guards which will never
-%% succeed.
-
-match_pre(Cs, Sub0, St) ->
- foldr(fun (#c_clause{anno=A,pats=Ps,guard=G,body=B}, {Cs0,St0}) ->
- case is_false_guard(G) of
- true -> {Cs0,St0};
- false ->
- {Kps,Sub1,St1} = pattern_list(Ps, Sub0, St0),
- {[#iclause{anno=A,sub=Sub1,pats=Kps,guard=G,body=B}|
- Cs0],St1}
- end
- end, {[],St}, Cs).
-
-%% match([Var], [Clause], Default, State) -> {MatchExpr,State}.
-
-match([U|Us], Cs, Def, St0) ->
- %%ok = io:format("match ~p~n", [Cs]),
- Pcss = partition(Cs),
- foldr(fun (Pcs, {D,St}) -> match_varcon([U|Us], Pcs, D, St) end,
- {Def,St0}, Pcss);
-match([], Cs, Def, St) ->
- match_guard(Cs, Def, St).
-
-%% match_guard([Clause], Default, State) -> {IfExpr,State}.
-%% Build a guard to handle guards. A guard *ALWAYS* fails if no
-%% clause matches, there will be a surrounding 'alt' to catch the
-%% failure. Drop redundant cases, i.e. those after a true guard.
-
-match_guard(Cs0, Def0, St0) ->
- {Cs1,Def1,St1} = match_guard_1(Cs0, Def0, St0),
- {build_alt(build_guard(Cs1), Def1),St1}.
-
-match_guard_1([#iclause{anno=A,sub=Sub,guard=G,body=B}|Cs0], Def0, St0) ->
- case is_true_guard(G) of
- true ->
- %% The true clause body becomes the default.
- {Kb,Pb,St1} = body(B, Sub, St0),
- Line = get_line(A),
- St2 = maybe_add_warning(Cs0, Line, St1),
- St = maybe_add_warning(Def0, Line, St2),
- {[],pre_seq(Pb, Kb),St};
- false ->
- {Kg,St1} = guard(G, Sub, St0),
- {Kb,Pb,St2} = body(B, Sub, St1),
- {Cs1,Def1,St3} = match_guard_1(Cs0, Def0, St2),
- {[#k_guard_clause{guard=Kg,body=pre_seq(Pb, Kb)}|Cs1],
- Def1,St3}
- end;
-match_guard_1([], Def, St) -> {[],Def,St}.
-
-maybe_add_warning([C|_], Line, St) ->
- maybe_add_warning(C, Line, St);
-maybe_add_warning([], _Line, St) -> St;
-maybe_add_warning(fail, _Line, St) -> St;
-maybe_add_warning(Ke, MatchLine, St) ->
- case get_kanno(Ke) of
- [compiler_generated|_] -> St;
- Anno ->
- Line = get_line(Anno),
- Warn = case MatchLine of
- none -> nomatch_shadow;
- _ -> {nomatch_shadow,MatchLine}
- end,
- add_warning(Line, Warn, St)
- end.
-
-get_line([Line|_]) when is_integer(Line) -> Line;
-get_line([_|T]) -> get_line(T);
-get_line([]) -> none.
-
-
-%% is_true_guard(Guard) -> boolean().
-%% is_false_guard(Guard) -> boolean().
-%% Test if a guard is either trivially true/false. This has probably
-%% already been optimised away, but what the heck!
-
-is_true_guard(G) -> guard_value(G) == true.
-is_false_guard(G) -> guard_value(G) == false.
-
-%% guard_value(Guard) -> true | false | unknown.
-
-guard_value(#c_atom{val=true}) -> true;
-guard_value(#c_atom{val=false}) -> false;
-guard_value(#c_call{module=#c_atom{val=erlang},
- name=#c_atom{val='not'},
- args=[A]}) ->
- case guard_value(A) of
- true -> false;
- false -> true;
- unknown -> unknown
- end;
-guard_value(#c_call{module=#c_atom{val=erlang},
- name=#c_atom{val='and'},
- args=[Ca,Cb]}) ->
- case guard_value(Ca) of
- true -> guard_value(Cb);
- false -> false;
- unknown ->
- case guard_value(Cb) of
- false -> false;
- _Other -> unknown
- end
- end;
-guard_value(#c_call{module=#c_atom{val=erlang},
- name=#c_atom{val='or'},
- args=[Ca,Cb]}) ->
- case guard_value(Ca) of
- true -> true;
- false -> guard_value(Cb);
- unknown ->
- case guard_value(Cb) of
- true -> true;
- _Other -> unknown
- end
- end;
-guard_value(#c_try{arg=E,vars=[#c_var{name=X}],body=#c_var{name=X},
- handler=#c_atom{val=false}}) ->
- guard_value(E);
-guard_value(_) -> unknown.
-
-%% partition([Clause]) -> [[Clause]].
-%% Partition a list of clauses into groups which either contain
-%% clauses with a variable first argument, or with a "constructor".
-
-partition([C1|Cs]) ->
- V1 = is_var_clause(C1),
- {More,Rest} = splitwith(fun (C) -> is_var_clause(C) == V1 end, Cs),
- [[C1|More]|partition(Rest)];
-partition([]) -> [].
-
-%% match_varcon([Var], [Clause], Def, [Var], Sub, State) ->
-%% {MatchExpr,State}.
-
-match_varcon(Us, [C|_]=Cs, Def, St) ->
- case is_var_clause(C) of
- true -> match_var(Us, Cs, Def, St);
- false -> match_con(Us, Cs, Def, St)
- end.
-
-%% match_var([Var], [Clause], Def, State) -> {MatchExpr,State}.
-%% Build a call to "select" from a list of clauses all containing a
-%% variable as the first argument. We must rename the variable in
-%% each clause to be the match variable as these clause will share
-%% this variable and may have different names for it. Rename aliases
-%% as well.
-
-match_var([U|Us], Cs0, Def, St) ->
- Cs1 = map(fun (#iclause{sub=Sub0,pats=[Arg|As]}=C) ->
- Vs = [arg_arg(Arg)|arg_alias(Arg)],
- Sub1 = foldl(fun (#k_var{name=V}, Acc) ->
- subst_vsub(V, U#k_var.name, Acc)
- end, Sub0, Vs),
- C#iclause{sub=Sub1,pats=As}
- end, Cs0),
- match(Us, Cs1, Def, St).
-
-%% match_con(Variables, [Clause], Default, State) -> {SelectExpr,State}.
-%% Build call to "select" from a list of clauses all containing a
-%% constructor/constant as first argument. Group the constructors
-%% according to type, the order is really irrelevant but tries to be
-%% smart.
-
-match_con([U|Us], Cs, Def, St0) ->
- %% Extract clauses for different constructors (types).
- %%ok = io:format("match_con ~p~n", [Cs]),
- Ttcs = [ {T,Tcs} || T <- [k_cons,k_tuple,k_atom,k_float,k_int,k_nil,
- k_binary,k_bin_end],
- begin Tcs = select(T, Cs),
- Tcs /= []
- end ] ++ select_bin_con(Cs),
- %%ok = io:format("ttcs = ~p~n", [Ttcs]),
- {Scs,St1} =
- mapfoldl(fun ({T,Tcs}, St) ->
- {[S|_]=Sc,S1} = match_value([U|Us], T, Tcs, fail, St),
- %%ok = io:format("match_con type2 ~p~n", [T]),
- Anno = get_kanno(S),
- {#k_type_clause{anno=Anno,type=T,values=Sc},S1} end,
- St0, Ttcs),
- {build_alt_1st_no_fail(build_select(U, Scs), Def),St1}.
-
-%% select_bin_con([Clause]) -> [{Type,[Clause]}].
-%% Extract clauses for the k_bin_seg constructor. As k_bin_seg
-%% matching can overlap, the k_bin_seg constructors cannot be
-%% reordered, only grouped.
-
-select_bin_con(Cs0) ->
- Cs1 = lists:filter(fun (C) ->
- clause_con(C) == k_bin_seg
- end, Cs0),
- select_bin_con_1(Cs1).
-
-select_bin_con_1([C1|Cs]) ->
- Con = clause_con(C1),
- {More,Rest} = splitwith(fun (C) -> clause_con(C) == Con end, Cs),
- [{Con,[C1|More]}|select_bin_con_1(Rest)];
-select_bin_con_1([]) -> [].
-
-%% select(Con, [Clause]) -> [Clause].
-
-select(T, Cs) -> [ C || C <- Cs, clause_con(C) == T ].
-
-%% match_value([Var], Con, [Clause], Default, State) -> {SelectExpr,State}.
-%% At this point all the clauses have the same constructor, we must
-%% now separate them according to value.
-
-match_value(_, _, [], _, St) -> {[],St};
-match_value(Us, T, Cs0, Def, St0) ->
- Css = group_value(T, Cs0),
- %%ok = io:format("match_value ~p ~p~n", [T, Css]),
- {Css1,St1} = mapfoldl(fun (Cs, St) ->
- match_clause(Us, Cs, Def, St) end,
- St0, Css),
- {Css1,St1}.
- %%{#k_select_val{type=T,var=hd(Us),clauses=Css1},St1}.
-
-%% group_value([Clause]) -> [[Clause]].
-%% Group clauses according to value. Here we know that
-%% 1. Some types are singled valued
-%% 2. The clauses in bin_segs cannot be reordered only grouped
-%% 3. Other types are disjoint and can be reordered
-
-group_value(k_cons, Cs) -> [Cs]; %These are single valued
-group_value(k_nil, Cs) -> [Cs];
-group_value(k_binary, Cs) -> [Cs];
-group_value(k_bin_end, Cs) -> [Cs];
-group_value(k_bin_seg, Cs) ->
- group_bin_seg(Cs);
-group_value(_, Cs) ->
- %% group_value(Cs).
- Cd = foldl(fun (C, Gcs0) -> dict:append(clause_val(C), C, Gcs0) end,
- dict:new(), Cs),
- dict:fold(fun (_, Vcs, Css) -> [Vcs|Css] end, [], Cd).
-
-group_bin_seg([C1|Cs]) ->
- V1 = clause_val(C1),
- {More,Rest} = splitwith(fun (C) -> clause_val(C) == V1 end, Cs),
- [[C1|More]|group_bin_seg(Rest)];
-group_bin_seg([]) -> [].
-
-%% Profiling shows that this quadratic implementation account for a big amount
-%% of the execution time if there are many values.
-% group_value([C|Cs]) ->
-% V = clause_val(C),
-% Same = [ Cv || Cv <- Cs, clause_val(Cv) == V ], %Same value
-% Rest = [ Cv || Cv <- Cs, clause_val(Cv) /= V ], % and all the rest
-% [[C|Same]|group_value(Rest)];
-% group_value([]) -> [].
-
-%% match_clause([Var], [Clause], Default, State) -> {Clause,State}.
-%% At this point all the clauses have the same "value". Build one
-%% select clause for this value and continue matching. Rename
-%% aliases as well.
-
-match_clause([U|Us], [C|_]=Cs0, Def, St0) ->
- Anno = get_kanno(C),
- {Match0,Vs,St1} = get_match(get_con(Cs0), St0),
- Match = sub_size_var(Match0, Cs0),
- {Cs1,St2} = new_clauses(Cs0, U, St1),
- {B,St3} = match(Vs ++ Us, Cs1, Def, St2),
- {#k_val_clause{anno=Anno,val=Match,body=B},St3}.
-
-sub_size_var(#k_bin_seg{size=#k_var{name=Name}=Kvar}=BinSeg, [#iclause{sub=Sub}|_]) ->
- BinSeg#k_bin_seg{size=Kvar#k_var{name=get_vsub(Name, Sub)}};
-sub_size_var(K, _) -> K.
-
-get_con([C|_]) -> arg_arg(clause_arg(C)). %Get the constructor
-
-get_match(#k_cons{}, St0) ->
- {[H,T],St1} = new_vars(2, St0),
- {#k_cons{hd=H,tl=T},[H,T],St1};
-get_match(#k_binary{}, St0) ->
- {[V]=Mes,St1} = new_vars(1, St0),
- {#k_binary{segs=V},Mes,St1};
-get_match(#k_bin_seg{}=Seg, St0) ->
- {[S,N]=Mes,St1} = new_vars(2, St0),
- {Seg#k_bin_seg{seg=S,next=N},Mes,St1};
-get_match(#k_tuple{es=Es}, St0) ->
- {Mes,St1} = new_vars(length(Es), St0),
- {#k_tuple{es=Mes},Mes,St1};
-get_match(M, St) ->
- {M,[],St}.
-
-new_clauses(Cs0, U, St) ->
- Cs1 = map(fun (#iclause{sub=Sub0,pats=[Arg|As]}=C) ->
- Head = case arg_arg(Arg) of
- #k_cons{hd=H,tl=T} -> [H,T|As];
- #k_tuple{es=Es} -> Es ++ As;
- #k_binary{segs=E} -> [E|As];
- #k_bin_seg{seg=S,next=N} ->
- [S,N|As];
- _Other -> As
- end,
- Vs = arg_alias(Arg),
- Sub1 = foldl(fun (#k_var{name=V}, Acc) ->
- subst_vsub(V, U#k_var.name, Acc)
- end, Sub0, Vs),
- C#iclause{sub=Sub1,pats=Head}
- end, Cs0),
- {Cs1,St}.
-
-%% build_guard([GuardClause]) -> GuardExpr.
-
-build_guard([]) -> fail;
-build_guard(Cs) -> #k_guard{clauses=Cs}.
-
-%% build_select(Var, [ConClause]) -> SelectExpr.
-
-build_select(V, [Tc|_]=Tcs) ->
- Anno = get_kanno(Tc),
- #k_select{anno=Anno,var=V,types=Tcs}.
-
-%% build_alt(First, Then) -> AltExpr.
-%% Build an alt, attempt some simple optimisation.
-
-build_alt(fail, Then) -> Then;
-build_alt(First,Then) -> build_alt_1st_no_fail(First, Then).
-
-build_alt_1st_no_fail(First, fail) -> First;
-build_alt_1st_no_fail(First, Then) -> #k_alt{first=First,then=Then}.
-
-%% build_match([MatchVar], MatchExpr) -> Kexpr.
-%% Build a match expr if there is a match.
-
-build_match(Us, #k_alt{}=Km) -> #k_match{vars=Us,body=Km};
-build_match(Us, #k_select{}=Km) -> #k_match{vars=Us,body=Km};
-build_match(Us, #k_guard{}=Km) -> #k_match{vars=Us,body=Km};
-build_match(_, Km) -> Km.
-
-%% clause_arg(Clause) -> FirstArg.
-%% clause_con(Clause) -> Constructor.
-%% clause_val(Clause) -> Value.
-%% is_var_clause(Clause) -> boolean().
-
-clause_arg(#iclause{pats=[Arg|_]}) -> Arg.
-
-clause_con(C) -> arg_con(clause_arg(C)).
-
-clause_val(C) -> arg_val(clause_arg(C)).
-
-is_var_clause(C) -> clause_con(C) == k_var.
-
-%% arg_arg(Arg) -> Arg.
-%% arg_alias(Arg) -> Aliases.
-%% arg_con(Arg) -> Constructor.
-%% arg_val(Arg) -> Value.
-%% These are the basic functions for obtaining fields in an argument.
-
-arg_arg(#ialias{pat=Con}) -> Con;
-arg_arg(Con) -> Con.
-
-arg_alias(#ialias{vars=As}) -> As;
-arg_alias(_Con) -> [].
-
-arg_con(Arg) ->
- case arg_arg(Arg) of
- #k_int{} -> k_int;
- #k_float{} -> k_float;
- #k_atom{} -> k_atom;
- #k_nil{} -> k_nil;
- #k_cons{} -> k_cons;
- #k_tuple{} -> k_tuple;
- #k_binary{} -> k_binary;
- #k_bin_end{} -> k_bin_end;
- #k_bin_seg{} -> k_bin_seg;
- #k_var{} -> k_var
- end.
-
-arg_val(Arg) ->
- case arg_arg(Arg) of
- #k_int{val=I} -> I;
- #k_float{val=F} -> F;
- #k_atom{val=A} -> A;
- #k_nil{} -> 0;
- #k_cons{} -> 2;
- #k_tuple{es=Es} -> length(Es);
- #k_bin_seg{size=S,unit=U,type=T,flags=Fs} ->
- {set_kanno(S, []),U,T,Fs};
- #k_bin_end{} -> 0;
- #k_binary{} -> 0
- end.
-
-%% ubody(Expr, Break, State) -> {Expr,[UsedVar],State}.
-%% Tag the body sequence with its used variables. These bodies
-%% either end with a #k_break{}, or with #k_return{} or an expression
-%% which itself can return, #k_enter{}, #k_match{} ... .
-
-ubody(#iset{vars=[],arg=#iletrec{}=Let,body=B0}, Br, St0) ->
- %% An iletrec{} should never be last.
- St1 = iletrec_funs(Let, St0),
- ubody(B0, Br, St1);
-ubody(#iset{anno=A,vars=Vs,arg=E0,body=B0}, Br, St0) ->
- {E1,Eu,St1} = uexpr(E0, {break,Vs}, St0),
- {B1,Bu,St2} = ubody(B0, Br, St1),
- Ns = lit_list_vars(Vs),
- Used = union(Eu, subtract(Bu, Ns)), %Used external vars
- {#k_seq{anno=#k{us=Used,ns=Ns,a=A},arg=E1,body=B1},Used,St2};
-ubody(#ivalues{anno=A,args=As}, return, St) ->
- Au = lit_list_vars(As),
- {#k_return{anno=#k{us=Au,ns=[],a=A},args=As},Au,St};
-ubody(#ivalues{anno=A,args=As}, {break,_Vbs}, St) ->
- Au = lit_list_vars(As),
- {#k_break{anno=#k{us=Au,ns=[],a=A},args=As},Au,St};
-ubody(E, return, St0) ->
- %% Enterable expressions need no trailing return.
- case is_enter_expr(E) of
- true -> uexpr(E, return, St0);
- false ->
- {Ea,Pa,St1} = force_atomic(E, St0),
- ubody(pre_seq(Pa, #ivalues{args=[Ea]}), return, St1)
- end;
-ubody(E, {break,Rs}, St0) ->
- %%ok = io:fwrite("ubody ~w:~p~n", [?LINE,{E,Br}]),
- %% Exiting expressions need no trailing break.
- case is_exit_expr(E) of
- true -> uexpr(E, return, St0);
- false ->
- {Ea,Pa,St1} = force_atomic(E, St0),
- ubody(pre_seq(Pa, #ivalues{args=[Ea]}), {break,Rs}, St1)
- end.
-
-iletrec_funs(#iletrec{defs=Fs}, St0) ->
- %% Use union of all free variables.
- %% First just work out free variables for all functions.
- Free = foldl(fun ({_,#ifun{vars=Vs,body=Fb0}}, Free0) ->
- {_,Fbu,_} = ubody(Fb0, return, St0),
- Ns = lit_list_vars(Vs),
- Free1 = subtract(Fbu, Ns),
- union(Free1, Free0)
- end, [], Fs),
- FreeVs = make_vars(Free),
- %% Add this free info to State.
- St1 = foldl(fun ({N,#ifun{vars=Vs}}, Lst) ->
- store_free(N, length(Vs), FreeVs, Lst)
- end, St0, Fs),
- %% Now regenerate local functions to use free variable information.
- St2 = foldl(fun ({N,#ifun{anno=Fa,vars=Vs,body=Fb0}}, Lst0) ->
- {Fb1,_,Lst1} = ubody(Fb0, return, Lst0),
- Arity = length(Vs) + length(FreeVs),
- Fun = #k_fdef{anno=#k{us=[],ns=[],a=Fa},
- func=N,arity=Arity,
- vars=Vs ++ FreeVs,body=Fb1},
- Lst1#kern{funs=[Fun|Lst1#kern.funs]}
- end, St1, Fs),
- St2.
-
-%% is_exit_expr(Kexpr) -> boolean().
-%% Test whether Kexpr always exits and never returns.
-
-is_exit_expr(#k_call{op=#k_remote{mod=erlang,name=throw,arity=1}}) -> true;
-is_exit_expr(#k_call{op=#k_remote{mod=erlang,name=exit,arity=1}}) -> true;
-is_exit_expr(#k_call{op=#k_remote{mod=erlang,name=error,arity=1}}) -> true;
-is_exit_expr(#k_call{op=#k_remote{mod=erlang,name=error,arity=2}}) -> true;
-is_exit_expr(#k_call{op=#k_remote{mod=erlang,name=fault,arity=1}}) -> true;
-is_exit_expr(#k_call{op=#k_remote{mod=erlang,name=fault,arity=2}}) -> true;
-is_exit_expr(#k_call{op=#k_internal{name=match_fail,arity=1}}) -> true;
-is_exit_expr(#k_bif{op=#k_internal{name=rethrow,arity=2}}) -> true;
-is_exit_expr(#k_receive_next{}) -> true;
-is_exit_expr(_) -> false.
-
-%% is_enter_expr(Kexpr) -> boolean().
-%% Test whether Kexpr is "enterable", i.e. can handle return from
-%% within itself without extra #k_return{}.
-
-is_enter_expr(#k_call{}) -> true;
-is_enter_expr(#k_match{}) -> true;
-is_enter_expr(#k_receive{}) -> true;
-is_enter_expr(#k_receive_next{}) -> true;
-%%is_enter_expr(#k_try{}) -> true; %Soon
-is_enter_expr(_) -> false.
-
-%% uguard(Expr, State) -> {Expr,[UsedVar],State}.
-%% Tag the guard sequence with its used variables.
-
-uguard(#k_try{anno=A,arg=B0,vars=[#k_var{name=X}],body=#k_var{name=X},
- handler=#k_atom{val=false}}=Try, St0) ->
- {B1,Bu,St1} = uguard(B0, St0),
- {Try#k_try{anno=#k{us=Bu,ns=[],a=A},arg=B1},Bu,St1};
-uguard(T, St) ->
- %%ok = io:fwrite("~w: ~p~n", [?LINE,T]),
- uguard_test(T, St).
-
-%% uguard_test(Expr, State) -> {Test,[UsedVar],State}.
-%% At this stage tests are just expressions which don't return any
-%% values.
-
-uguard_test(T, St) -> uguard_expr(T, [], St).
-
-uguard_expr(#iset{anno=A,vars=Vs,arg=E0,body=B0}, Rs, St0) ->
- Ns = lit_list_vars(Vs),
- {E1,Eu,St1} = uguard_expr(E0, Vs, St0),
- {B1,Bu,St2} = uguard_expr(B0, Rs, St1),
- Used = union(Eu, subtract(Bu, Ns)),
- {#k_seq{anno=#k{us=Used,ns=Ns,a=A},arg=E1,body=B1},Used,St2};
-uguard_expr(#k_try{anno=A,arg=B0,vars=[#k_var{name=X}],body=#k_var{name=X},
- handler=#k_atom{val=false}}=Try, Rs, St0) ->
- {B1,Bu,St1} = uguard_expr(B0, Rs, St0),
- {Try#k_try{anno=#k{us=Bu,ns=lit_list_vars(Rs),a=A},arg=B1,ret=Rs},
- Bu,St1};
-uguard_expr(#k_test{anno=A,op=Op,args=As}=Test, Rs, St) ->
- [] = Rs, %Sanity check
- Used = union(op_vars(Op), lit_list_vars(As)),
- {Test#k_test{anno=#k{us=Used,ns=lit_list_vars(Rs),a=A}},
- Used,St};
-uguard_expr(#k_bif{anno=A,op=Op,args=As}=Bif, Rs, St) ->
- Used = union(op_vars(Op), lit_list_vars(As)),
- {Bif#k_bif{anno=#k{us=Used,ns=lit_list_vars(Rs),a=A},ret=Rs},
- Used,St};
-uguard_expr(#ivalues{anno=A,args=As}, Rs, St) ->
- Sets = foldr2(fun (V, Arg, Rhs) ->
- #iset{anno=A,vars=[V],arg=Arg,body=Rhs}
- end, #k_atom{val=true}, Rs, As),
- uguard_expr(Sets, [], St);
-uguard_expr(#k_match{anno=A,vars=Vs,body=B0}, Rs, St0) ->
- %% Experimental support for andalso/orelse in guards.
- Br = case Rs of
- [] -> return;
- _ -> {break,Rs}
- end,
- {B1,Bu,St1} = umatch(B0, Br, St0),
- {#k_match{anno=#k{us=Bu,ns=lit_list_vars(Rs),a=A},
- vars=Vs,body=B1,ret=Rs},Bu,St1};
-uguard_expr(Lit, Rs, St) ->
- %% Transform literals to puts here.
- Used = lit_vars(Lit),
- {#k_put{anno=#k{us=Used,ns=lit_list_vars(Rs),a=get_kanno(Lit)},
- arg=Lit,ret=Rs},Used,St}.
-
-%% uexpr(Expr, Break, State) -> {Expr,[UsedVar],State}.
-%% Tag an expression with its used variables.
-%% Break = return | {break,[RetVar]}.
-
-uexpr(#k_call{anno=A,op=#k_local{name=F,arity=Ar}=Op,args=As0}=Call, Br, St) ->
- Free = get_free(F, Ar, St),
- As1 = As0 ++ Free, %Add free variables LAST!
- Used = lit_list_vars(As1),
- {case Br of
- {break,Rs} ->
- Call#k_call{anno=#k{us=Used,ns=lit_list_vars(Rs),a=A},
- op=Op#k_local{arity=Ar + length(Free)},
- args=As1,ret=Rs};
- return ->
- #k_enter{anno=#k{us=Used,ns=[],a=A},
- op=Op#k_local{arity=Ar + length(Free)},
- args=As1}
- end,Used,St};
-uexpr(#k_call{anno=A,op=Op,args=As}=Call, {break,Rs}, St) ->
- Used = union(op_vars(Op), lit_list_vars(As)),
- {Call#k_call{anno=#k{us=Used,ns=lit_list_vars(Rs),a=A},ret=Rs},
- Used,St};
-uexpr(#k_call{anno=A,op=Op,args=As}, return, St) ->
- Used = union(op_vars(Op), lit_list_vars(As)),
- {#k_enter{anno=#k{us=Used,ns=[],a=A},op=Op,args=As},
- Used,St};
-uexpr(#k_bif{anno=A,op=Op,args=As}=Bif, {break,Rs}, St0) ->
- Used = union(op_vars(Op), lit_list_vars(As)),
- {Brs,St1} = bif_returns(Op, Rs, St0),
- {Bif#k_bif{anno=#k{us=Used,ns=lit_list_vars(Brs),a=A},ret=Brs},
- Used,St1};
-uexpr(#k_match{anno=A,vars=Vs,body=B0}, Br, St0) ->
- Rs = break_rets(Br),
- {B1,Bu,St1} = umatch(B0, Br, St0),
- {#k_match{anno=#k{us=Bu,ns=lit_list_vars(Rs),a=A},
- vars=Vs,body=B1,ret=Rs},Bu,St1};
-uexpr(#k_receive{anno=A,var=V,body=B0,timeout=T,action=A0}, Br, St0) ->
- Rs = break_rets(Br),
- Tu = lit_vars(T), %Timeout is atomic
- {B1,Bu,St1} = umatch(B0, Br, St0),
- {A1,Au,St2} = ubody(A0, Br, St1),
- Used = del_element(V#k_var.name, union(Bu, union(Tu, Au))),
- {#k_receive{anno=#k{us=Used,ns=lit_list_vars(Rs),a=A},
- var=V,body=B1,timeout=T,action=A1,ret=Rs},
- Used,St2};
-uexpr(#k_receive_accept{anno=A}, _, St) ->
- {#k_receive_accept{anno=#k{us=[],ns=[],a=A}},[],St};
-uexpr(#k_receive_next{anno=A}, _, St) ->
- {#k_receive_next{anno=#k{us=[],ns=[],a=A}},[],St};
-uexpr(#k_try{anno=A,arg=A0,vars=Vs,body=B0,evars=Evs,handler=H0},
- {break,Rs0}, St0) ->
- {Avs,St1} = new_vars(length(Vs), St0), %Need dummy names here
- {A1,Au,St2} = ubody(A0, {break,Avs}, St1), %Must break to clean up here!
- {B1,Bu,St3} = ubody(B0, {break,Rs0}, St2),
- {H1,Hu,St4} = ubody(H0, {break,Rs0}, St3),
- %% Guarantee ONE return variable.
- NumNew = if
- Rs0 =:= [] -> 1;
- true -> 0
- end,
- {Ns,St5} = new_vars(NumNew, St4),
- Rs1 = Rs0 ++ Ns,
- Used = union([Au,subtract(Bu, lit_list_vars(Vs)),
- subtract(Hu, lit_list_vars(Evs))]),
- {#k_try{anno=#k{us=Used,ns=lit_list_vars(Rs1),a=A},
- arg=A1,vars=Vs,body=B1,evars=Evs,handler=H1,ret=Rs1},
- Used,St5};
-uexpr(#k_catch{anno=A,body=B0}, {break,Rs0}, St0) ->
- {Rb,St1} = new_var(St0),
- {B1,Bu,St2} = ubody(B0, {break,[Rb]}, St1),
- %% Guarantee ONE return variable.
- {Ns,St3} = new_vars(1 - length(Rs0), St2),
- Rs1 = Rs0 ++ Ns,
- {#k_catch{anno=#k{us=Bu,ns=lit_list_vars(Rs1),a=A},body=B1,ret=Rs1},Bu,St3};
-uexpr(#ifun{anno=A,vars=Vs,body=B0}=IFun, {break,Rs}, St0) ->
- {B1,Bu,St1} = ubody(B0, return, St0), %Return out of new function
- Ns = lit_list_vars(Vs),
- Free = subtract(Bu, Ns), %Free variables in fun
- Fvs = make_vars(Free),
- Arity = length(Vs) + length(Free),
- {{Index,Uniq,Fname}, St3} =
- case lists:keysearch(id, 1, A) of
- {value,{id,Id}} ->
- {Id, St1};
- false ->
- %% No id annotation. Must invent one.
- I = St1#kern.fcount,
- U = erlang:hash(IFun, (1 bsl 27)-1),
- {N, St2} = new_fun_name(St1),
- {{I,U,N}, St2}
- end,
- Fun = #k_fdef{anno=#k{us=[],ns=[],a=A},func=Fname,arity=Arity,
- vars=Vs ++ Fvs,body=B1},
- {#k_bif{anno=#k{us=Free,ns=lit_list_vars(Rs),a=A},
- op=#k_internal{name=make_fun,arity=length(Free)+3},
- args=[#k_atom{val=Fname},#k_int{val=Arity},
- #k_int{val=Index},#k_int{val=Uniq}|Fvs],
- ret=Rs},
-% {#k_call{anno=#k{us=Free,ns=lit_list_vars(Rs),a=A},
-% op=#k_internal{name=make_fun,arity=length(Free)+3},
-% args=[#k_atom{val=Fname},#k_int{val=Arity},
-% #k_int{val=Index},#k_int{val=Uniq}|Fvs],
-% ret=Rs},
- Free,St3#kern{funs=[Fun|St3#kern.funs]}};
-uexpr(Lit, {break,Rs}, St) ->
- %% Transform literals to puts here.
- %%ok = io:fwrite("uexpr ~w:~p~n", [?LINE,Lit]),
- Used = lit_vars(Lit),
- {#k_put{anno=#k{us=Used,ns=lit_list_vars(Rs),a=get_kanno(Lit)},
- arg=Lit,ret=Rs},Used,St}.
-
-%% get_free(Name, Arity, State) -> [Free].
-%% store_free(Name, Arity, [Free], State) -> State.
-
-get_free(F, A, St) ->
- case orddict:find({F,A}, St#kern.free) of
- {ok,Val} -> Val;
- error -> []
- end.
-
-store_free(F, A, Free, St) ->
- St#kern{free=orddict:store({F,A}, Free, St#kern.free)}.
-
-break_rets({break,Rs}) -> Rs;
-break_rets(return) -> [].
-
-%% bif_returns(Op, [Ret], State) -> {[Ret],State}.
-
-bif_returns(#k_remote{mod=M,name=N,arity=Ar}, Rs, St0) ->
- %%ok = io:fwrite("uexpr ~w:~p~n", [?LINE,{M,N,Ar,Rs}]),
- {Ns,St1} = new_vars(bif_vals(M, N, Ar) - length(Rs), St0),
- {Rs ++ Ns,St1};
-bif_returns(#k_internal{name=N,arity=Ar}, Rs, St0) ->
- %%ok = io:fwrite("uexpr ~w:~p~n", [?LINE,{N,Ar,Rs}]),
- {Ns,St1} = new_vars(bif_vals(N, Ar) - length(Rs), St0),
- {Rs ++ Ns,St1}.
-
-%% umatch(Match, Break, State) -> {Match,[UsedVar],State}.
-%% Tag a match expression with its used variables.
-
-umatch(#k_alt{anno=A,first=F0,then=T0}, Br, St0) ->
- {F1,Fu,St1} = umatch(F0, Br, St0),
- {T1,Tu,St2} = umatch(T0, Br, St1),
- Used = union(Fu, Tu),
- {#k_alt{anno=#k{us=Used,ns=[],a=A},first=F1,then=T1},
- Used,St2};
-umatch(#k_select{anno=A,var=V,types=Ts0}, Br, St0) ->
- {Ts1,Tus,St1} = umatch_list(Ts0, Br, St0),
- Used = add_element(V#k_var.name, Tus),
- {#k_select{anno=#k{us=Used,ns=[],a=A},var=V,types=Ts1},Used,St1};
-umatch(#k_type_clause{anno=A,type=T,values=Vs0}, Br, St0) ->
- {Vs1,Vus,St1} = umatch_list(Vs0, Br, St0),
- {#k_type_clause{anno=#k{us=Vus,ns=[],a=A},type=T,values=Vs1},Vus,St1};
-umatch(#k_val_clause{anno=A,val=P,body=B0}, Br, St0) ->
- {U0,Ps} = pat_vars(P),
- {B1,Bu,St1} = umatch(B0, Br, St0),
- Used = union(U0, subtract(Bu, Ps)),
- {#k_val_clause{anno=#k{us=Used,ns=[],a=A},val=P,body=B1},
- Used,St1};
-umatch(#k_guard{anno=A,clauses=Gs0}, Br, St0) ->
- {Gs1,Gus,St1} = umatch_list(Gs0, Br, St0),
- {#k_guard{anno=#k{us=Gus,ns=[],a=A},clauses=Gs1},Gus,St1};
-umatch(#k_guard_clause{anno=A,guard=G0,body=B0}, Br, St0) ->
- %%ok = io:fwrite("~w: ~p~n", [?LINE,G0]),
- {G1,Gu,St1} = uguard(G0, St0),
- %%ok = io:fwrite("~w: ~p~n", [?LINE,G1]),
- {B1,Bu,St2} = umatch(B0, Br, St1),
- Used = union(Gu, Bu),
- {#k_guard_clause{anno=#k{us=Used,ns=[],a=A},guard=G1,body=B1},Used,St2};
-umatch(B0, Br, St0) -> ubody(B0, Br, St0).
-
-umatch_list(Ms0, Br, St) ->
- foldr(fun (M0, {Ms1,Us,Sta}) ->
- {M1,Mu,Stb} = umatch(M0, Br, Sta),
- {[M1|Ms1],union(Mu, Us),Stb}
- end, {[],[],St}, Ms0).
-
-%% op_vars(Op) -> [VarName].
-
-op_vars(#k_local{}) -> [];
-op_vars(#k_remote{mod=Mod,name=Name}) ->
- ordsets:from_list([V || #k_var{name=V} <- [Mod,Name]]);
-op_vars(#k_internal{}) -> [];
-op_vars(Atomic) -> lit_vars(Atomic).
-
-%% lit_vars(Literal) -> [VarName].
-%% Return the variables in a literal.
-
-lit_vars(#k_var{name=N}) -> [N];
-lit_vars(#k_int{}) -> [];
-lit_vars(#k_float{}) -> [];
-lit_vars(#k_atom{}) -> [];
-%%lit_vars(#k_char{}) -> [];
-lit_vars(#k_string{}) -> [];
-lit_vars(#k_nil{}) -> [];
-lit_vars(#k_cons{hd=H,tl=T}) ->
- union(lit_vars(H), lit_vars(T));
-lit_vars(#k_binary{segs=V}) -> lit_vars(V);
-lit_vars(#k_bin_end{}) -> [];
-lit_vars(#k_bin_seg{size=Size,seg=S,next=N}) ->
- union(lit_vars(Size), union(lit_vars(S), lit_vars(N)));
-lit_vars(#k_tuple{es=Es}) ->
- lit_list_vars(Es).
-
-lit_list_vars(Ps) ->
- foldl(fun (P, Vs) -> union(lit_vars(P), Vs) end, [], Ps).
-
-%% pat_vars(Pattern) -> {[UsedVarName],[NewVarName]}.
-%% Return variables in a pattern. All variables are new variables
-%% except those in the size field of binary segments.
-
-pat_vars(#k_var{name=N}) -> {[],[N]};
-%%pat_vars(#k_char{}) -> {[],[]};
-pat_vars(#k_int{}) -> {[],[]};
-pat_vars(#k_float{}) -> {[],[]};
-pat_vars(#k_atom{}) -> {[],[]};
-pat_vars(#k_string{}) -> {[],[]};
-pat_vars(#k_nil{}) -> {[],[]};
-pat_vars(#k_cons{hd=H,tl=T}) ->
- pat_list_vars([H,T]);
-pat_vars(#k_binary{segs=V}) ->
- pat_vars(V);
-pat_vars(#k_bin_seg{size=Size,seg=S,next=N}) ->
- {U1,New} = pat_list_vars([S,N]),
- {[],U2} = pat_vars(Size),
- {union(U1, U2),New};
-pat_vars(#k_bin_end{}) -> {[],[]};
-pat_vars(#k_tuple{es=Es}) ->
- pat_list_vars(Es).
-
-pat_list_vars(Ps) ->
- foldl(fun (P, {Used0,New0}) ->
- {Used,New} = pat_vars(P),
- {union(Used0, Used),union(New0, New)} end,
- {[],[]}, Ps).
-
-%% aligned(Bits, Size, Unit, Flags) -> {Size,Flags}
-%% Add 'aligned' to the flags if the current field is aligned.
-%% Number of bits correct modulo 8.
-
-aligned(B, S, U, Fs) when B rem 8 =:= 0 ->
- {incr_bits(B, S, U),[aligned|Fs]};
-aligned(B, S, U, Fs) ->
- {incr_bits(B, S, U),Fs}.
-
-incr_bits(B, #k_int{val=S}, U) when integer(B) -> B + S*U;
-incr_bits(_, #k_atom{val=all}, _) -> 0; %Always aligned
-incr_bits(B, _, 8) -> B;
-incr_bits(_, _, _) -> unknown.
-
-make_list(Es) ->
- foldr(fun (E, Acc) -> #c_cons{hd=E,tl=Acc} end, #c_nil{}, Es).
-
-%% List of integers in interval [N,M]. Empty list if N > M.
-
-integers(N, M) when N =< M ->
- [N|integers(N + 1, M)];
-integers(_, _) -> [].
-
-%%%
-%%% Handling of warnings.
-%%%
-
-format_error({nomatch_shadow,Line}) ->
- M = io_lib:format("this clause cannot match because a previous clause at line ~p "
- "always matches", [Line]),
- lists:flatten(M);
-format_error(nomatch_shadow) ->
- "this clause cannot match because a previous clause always matches".
-
-add_warning(none, Term, #kern{ws=Ws}=St) ->
- St#kern{ws=[{?MODULE,Term}|Ws]};
-add_warning(Line, Term, #kern{ws=Ws}=St) when Line >= 0 ->
- St#kern{ws=[{Line,?MODULE,Term}|Ws]};
-add_warning(_, _, St) -> St.
-
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_kernel.hrl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_kernel.hrl
deleted file mode 100644
index 822a9e34e1..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_kernel.hrl
+++ /dev/null
@@ -1,77 +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: v3_kernel.hrl,v 1.1 2008/12/17 09:53:43 mikpe Exp $
-%%
-
-%% Purpose : Kernel Erlang as records.
-
-%% It would be nice to incorporate some generic functions as well but
-%% this could make including this file difficult.
-%% N.B. the annotation field is ALWAYS the first field!
-
-%% Kernel annotation record.
--record(k, {us, %Used variables
- ns, %New variables
- a}). %Core annotation
-
-%% Literals
-%% NO CHARACTERS YET.
-%%-record(k_char, {anno=[],val}).
--record(k_int, {anno=[],val}).
--record(k_float, {anno=[],val}).
--record(k_atom, {anno=[],val}).
--record(k_string, {anno=[],val}).
--record(k_nil, {anno=[]}).
-
--record(k_tuple, {anno=[],es}).
--record(k_cons, {anno=[],hd,tl}).
--record(k_binary, {anno=[],segs}).
--record(k_bin_seg, {anno=[],size,unit,type,flags,seg,next}).
--record(k_bin_end, {anno=[]}).
--record(k_var, {anno=[],name}).
-
--record(k_local, {anno=[],name,arity}).
--record(k_remote, {anno=[],mod,name,arity}).
--record(k_internal, {anno=[],name,arity}).
-
--record(k_mdef, {anno=[],name,exports,attributes,body}).
--record(k_fdef, {anno=[],func,arity,vars,body}).
-
--record(k_seq, {anno=[],arg,body}).
--record(k_put, {anno=[],arg,ret=[]}).
--record(k_bif, {anno=[],op,args,ret=[]}).
--record(k_test, {anno=[],op,args}).
--record(k_call, {anno=[],op,args,ret=[]}).
--record(k_enter, {anno=[],op,args}).
--record(k_receive, {anno=[],var,body,timeout,action,ret=[]}).
--record(k_receive_accept, {anno=[]}).
--record(k_receive_next, {anno=[]}).
--record(k_try, {anno=[],arg,vars,body,evars,handler,ret=[]}).
--record(k_catch, {anno=[],body,ret=[]}).
-
--record(k_match, {anno=[],vars,body,ret=[]}).
--record(k_alt, {anno=[],first,then}).
--record(k_select, {anno=[],var,types}).
--record(k_type_clause, {anno=[],type,values}).
--record(k_val_clause, {anno=[],val,body}).
--record(k_guard, {anno=[],clauses}).
--record(k_guard_clause, {anno=[],guard,body}).
-
--record(k_break, {anno=[],args=[]}).
--record(k_return, {anno=[],args=[]}).
-
-%%k_get_anno(Thing) -> element(2, Thing).
-%%k_set_anno(Thing, Anno) -> setelement(2, Thing, Anno).
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_kernel_pp.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_kernel_pp.erl
deleted file mode 100644
index 92ff173834..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_kernel_pp.erl
+++ /dev/null
@@ -1,444 +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: v3_kernel_pp.erl,v 1.1 2008/12/17 09:53:43 mikpe Exp $
-%%
-%% Purpose : Kernel Erlang (naive) prettyprinter
-
--module(v3_kernel_pp).
-
--include("v3_kernel.hrl").
-
--export([format/1]).
-
-%% These are "internal" structures in sys_kernel which are here for
-%% debugging purposes.
--record(iset, {anno=[],vars,arg,body}).
--record(ifun, {anno=[],vars,body}).
-
-%% ====================================================================== %%
-%% format(Node) -> Text
-%% Node = coreErlang()
-%% Text = string() | [Text]
-%%
-%% Prettyprint-formats (naively) an abstract Core Erlang syntax
-%% tree.
-
--record(ctxt, {indent = 0,
- item_indent = 2,
- body_indent = 2,
- tab_width = 8}).
-
-canno(Cthing) -> element(2, Cthing).
-
-format(Node) -> format(Node, #ctxt{}).
-
-format(Node, Ctxt) ->
- case canno(Node) of
- [] ->
- format_1(Node, Ctxt);
- List ->
- format_anno(List, Ctxt, fun (Ctxt1) -> format_1(Node, Ctxt1) end)
- end.
-
-format_anno(Anno, Ctxt, ObjFun) ->
- Ctxt1 = ctxt_bump_indent(Ctxt, 2),
- ["( ",
- ObjFun(Ctxt1),
- nl_indent(Ctxt1),
- "-| ",io_lib:write(Anno),
- " )"].
-
-%% format_1(Kexpr, Context) -> string().
-
-format_1(#k_atom{val=A}, _Ctxt) -> core_atom(A);
-%%format_1(#k_char{val=C}, _Ctxt) -> io_lib:write_char(C);
-format_1(#k_float{val=F}, _Ctxt) -> float_to_list(F);
-format_1(#k_int{val=I}, _Ctxt) -> integer_to_list(I);
-format_1(#k_nil{}, _Ctxt) -> "[]";
-format_1(#k_string{val=S}, _Ctxt) -> io_lib:write_string(S);
-format_1(#k_var{name=V}, _Ctxt) ->
- if atom(V) ->
- case atom_to_list(V) of
- [$_|Cs] -> "_X" ++ Cs;
- [C|Cs] when C >= $A, C =< $Z -> [C|Cs];
- Cs -> [$_|Cs]
- end;
- integer(V) -> [$_|integer_to_list(V)]
- end;
-format_1(#k_cons{hd=H,tl=T}, Ctxt) ->
- Txt = ["["|format(H, ctxt_bump_indent(Ctxt, 1))],
- [Txt|format_list_tail(T, ctxt_bump_indent(Ctxt, width(Txt, Ctxt)))];
-format_1(#k_tuple{es=Es}, Ctxt) ->
- [${,
- format_hseq(Es, ",", ctxt_bump_indent(Ctxt, 1), fun format/2),
- $}
- ];
-format_1(#k_binary{segs=S}, Ctxt) ->
- ["#<",format(S, ctxt_bump_indent(Ctxt, 2)),">#"];
-format_1(#k_bin_seg{}=S, Ctxt) ->
- [format_bin_seg_1(S, Ctxt),
- format_bin_seg(S#k_bin_seg.next, ctxt_bump_indent(Ctxt, 2))];
-format_1(#k_bin_end{}, _Ctxt) -> "#<>#";
-format_1(#k_local{name=N,arity=A}, Ctxt) ->
- "local " ++ format_fa_pair({N,A}, Ctxt);
-format_1(#k_remote{mod=M,name=N,arity=A}, _Ctxt) ->
- %% This is for our internal translator.
- io_lib:format("remote ~s:~s/~w", [format(M),format(N),A]);
-format_1(#k_internal{name=N,arity=A}, Ctxt) ->
- "internal " ++ format_fa_pair({N,A}, Ctxt);
-format_1(#k_seq{arg=A,body=B}, Ctxt) ->
- Ctxt1 = ctxt_bump_indent(Ctxt, 2),
- ["do",
- nl_indent(Ctxt1),
- format(A, Ctxt1),
- nl_indent(Ctxt),
- "then",
- nl_indent(Ctxt)
- | format(B, Ctxt)
- ];
-format_1(#k_match{vars=Vs,body=Bs,ret=Rs}, Ctxt) ->
- Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.item_indent),
- ["match ",
- format_hseq(Vs, ",", ctxt_bump_indent(Ctxt, 6), fun format/2),
- nl_indent(Ctxt1),
- format(Bs, Ctxt1),
- nl_indent(Ctxt),
- "end",
- format_ret(Rs, Ctxt1)
- ];
-format_1(#k_alt{first=O,then=T}, Ctxt) ->
- Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.item_indent),
- ["alt",
- nl_indent(Ctxt1),
- format(O, Ctxt1),
- nl_indent(Ctxt1),
- format(T, Ctxt1)];
-format_1(#k_select{var=V,types=Cs}, Ctxt) ->
- Ctxt1 = ctxt_bump_indent(Ctxt, 2),
- ["select ",
- format(V, Ctxt),
- nl_indent(Ctxt1),
- format_vseq(Cs, "", "", Ctxt1, fun format/2)
- ];
-format_1(#k_type_clause{type=T,values=Cs}, Ctxt) ->
- Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.body_indent),
- ["type ",
- io_lib:write(T),
- nl_indent(Ctxt1),
- format_vseq(Cs, "", "", Ctxt1, fun format/2)
- ];
-format_1(#k_val_clause{val=Val,body=B}, Ctxt) ->
- Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.body_indent),
- [format(Val, Ctxt),
- " ->",
- nl_indent(Ctxt1)
- | format(B, Ctxt1)
- ];
-format_1(#k_guard{clauses=Gs}, Ctxt) ->
- Ctxt1 = ctxt_bump_indent(Ctxt, 5),
- ["when ",
- nl_indent(Ctxt1),
- format_vseq(Gs, "", "", Ctxt1, fun format/2)];
-format_1(#k_guard_clause{guard=G,body=B}, Ctxt) ->
- Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.body_indent),
- [format(G, Ctxt),
- nl_indent(Ctxt),
- "->",
- nl_indent(Ctxt1)
- | format(B, Ctxt1)
- ];
-format_1(#k_call{op=Op,args=As,ret=Rs}, Ctxt) ->
- Txt = ["call (",format(Op, ctxt_bump_indent(Ctxt, 6)),$)],
- Ctxt1 = ctxt_bump_indent(Ctxt, 2),
- [Txt,format_args(As, Ctxt1),
- format_ret(Rs, Ctxt1)
- ];
-format_1(#k_enter{op=Op,args=As}, Ctxt) ->
- Txt = ["enter (",format(Op, ctxt_bump_indent(Ctxt, 7)),$)],
- Ctxt1 = ctxt_bump_indent(Ctxt, 2),
- [Txt,format_args(As, Ctxt1)];
-format_1(#k_bif{op=Op,args=As,ret=Rs}, Ctxt) ->
- Txt = ["bif (",format(Op, ctxt_bump_indent(Ctxt, 5)),$)],
- Ctxt1 = ctxt_bump_indent(Ctxt, 2),
- [Txt,format_args(As, Ctxt1),
- format_ret(Rs, Ctxt1)
- ];
-format_1(#k_test{op=Op,args=As}, Ctxt) ->
- Txt = ["test (",format(Op, ctxt_bump_indent(Ctxt, 6)),$)],
- Ctxt1 = ctxt_bump_indent(Ctxt, 2),
- [Txt,format_args(As, Ctxt1)];
-format_1(#k_put{arg=A,ret=Rs}, Ctxt) ->
- [format(A, Ctxt),
- format_ret(Rs, ctxt_bump_indent(Ctxt, 1))
- ];
-format_1(#k_try{arg=A,vars=Vs,body=B,evars=Evs,handler=H,ret=Rs}, Ctxt) ->
- Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.body_indent),
- ["try",
- nl_indent(Ctxt1),
- format(A, Ctxt1),
- nl_indent(Ctxt),
- "of ",
- format_hseq(Vs, ", ", ctxt_bump_indent(Ctxt, 3), fun format/2),
- nl_indent(Ctxt1),
- format(B, Ctxt1),
- nl_indent(Ctxt),
- "catch ",
- format_hseq(Evs, ", ", ctxt_bump_indent(Ctxt, 6), fun format/2),
- nl_indent(Ctxt1),
- format(H, Ctxt1),
- nl_indent(Ctxt),
- "end",
- format_ret(Rs, Ctxt1)
- ];
-format_1(#k_catch{body=B,ret=Rs}, Ctxt) ->
- Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.body_indent),
- ["catch",
- nl_indent(Ctxt1),
- format(B, Ctxt1),
- nl_indent(Ctxt),
- "end",
- format_ret(Rs, Ctxt1)
- ];
-format_1(#k_receive{var=V,body=B,timeout=T,action=A,ret=Rs}, Ctxt) ->
- Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.item_indent),
- ["receive ",
- format(V, Ctxt),
- nl_indent(Ctxt1),
- format(B, Ctxt1),
- nl_indent(Ctxt),
- "after ",
- format(T, ctxt_bump_indent(Ctxt, 6)),
- " ->",
- nl_indent(Ctxt1),
- format(A, Ctxt1),
- nl_indent(Ctxt),
- "end",
- format_ret(Rs, Ctxt1)
- ];
-format_1(#k_receive_accept{}, _Ctxt) -> "receive_accept";
-format_1(#k_receive_next{}, _Ctxt) -> "receive_next";
-format_1(#k_break{args=As}, Ctxt) ->
- ["<",
- format_hseq(As, ",", ctxt_bump_indent(Ctxt, 1), fun format/2),
- ">"
- ];
-format_1(#k_return{args=As}, Ctxt) ->
- ["<<",
- format_hseq(As, ",", ctxt_bump_indent(Ctxt, 1), fun format/2),
- ">>"
- ];
-format_1(#k_fdef{func=F,arity=A,vars=Vs,body=B}, Ctxt) ->
- Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.body_indent),
- ["fdef ",
- format_fa_pair({F,A}, ctxt_bump_indent(Ctxt, 5)),
- format_args(Vs, ctxt_bump_indent(Ctxt, 14)),
- " =",
- nl_indent(Ctxt1),
- format(B, Ctxt1)
- ];
-format_1(#k_mdef{name=N,exports=Es,attributes=As,body=B}, Ctxt) ->
- ["module ",
- format(#k_atom{val=N}, ctxt_bump_indent(Ctxt, 7)),
- nl_indent(Ctxt),
- "export [",
- format_vseq(Es,
- "", ",",
- ctxt_bump_indent(Ctxt, 8),
- fun format_fa_pair/2),
- "]",
- nl_indent(Ctxt),
- "attributes [",
- format_vseq(As,
- "", ",",
- ctxt_bump_indent(Ctxt, 12),
- fun format_attribute/2),
- "]",
- nl_indent(Ctxt),
- format_vseq(B,
- "", "",
- Ctxt,
- fun format/2),
- nl_indent(Ctxt)
- | "end"
- ];
-%% Internal sys_kernel structures.
-format_1(#iset{vars=Vs,arg=A,body=B}, Ctxt) ->
- Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.body_indent),
- ["set <",
- format_hseq(Vs, ", ", ctxt_bump_indent(Ctxt, 5), fun format/2),
- "> =",
- nl_indent(Ctxt1),
- format(A, Ctxt1),
- nl_indent(Ctxt),
- "in "
- | format(B, ctxt_bump_indent(Ctxt, 2))
- ];
-format_1(#ifun{vars=Vs,body=B}, Ctxt) ->
- Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.body_indent),
- ["fun ",
- format_args(Vs, ctxt_bump_indent(Ctxt, 4)),
- " ->",
- nl_indent(Ctxt1)
- | format(B, Ctxt1)
- ];
-format_1(Type, _Ctxt) ->
- ["** Unsupported type: ",
- io_lib:write(Type)
- | " **"
- ].
-
-%% format_ret([RetVar], Context) -> Txt.
-%% Format the return vars of kexpr.
-
-format_ret(Rs, Ctxt) ->
- [" >> ",
- "<",
- format_hseq(Rs, ",", ctxt_bump_indent(Ctxt, 5), fun format/2),
- ">"].
-
-%% format_args([Arg], Context) -> Txt.
-%% Format arguments.
-
-format_args(As, Ctxt) ->
- [$(,format_hseq(As, ", ", ctxt_bump_indent(Ctxt, 1), fun format/2),$)].
-
-%% format_hseq([Thing], Separator, Context, Fun) -> Txt.
-%% Format a sequence horizontally.
-
-format_hseq([H], _Sep, Ctxt, Fun) ->
- Fun(H, Ctxt);
-format_hseq([H|T], Sep, Ctxt, Fun) ->
- Txt = [Fun(H, Ctxt)|Sep],
- Ctxt1 = ctxt_bump_indent(Ctxt, width(Txt, Ctxt)),
- [Txt|format_hseq(T, Sep, Ctxt1, Fun)];
-format_hseq([], _, _, _) -> "".
-
-%% format_vseq([Thing], LinePrefix, LineSuffix, Context, Fun) -> Txt.
-%% Format a sequence vertically.
-
-format_vseq([H], _Pre, _Suf, Ctxt, Fun) ->
- Fun(H, Ctxt);
-format_vseq([H|T], Pre, Suf, Ctxt, Fun) ->
- [Fun(H, Ctxt),Suf,nl_indent(Ctxt),Pre|
- format_vseq(T, Pre, Suf, Ctxt, Fun)];
-format_vseq([], _, _, _, _) -> "".
-
-format_fa_pair({F,A}, _Ctxt) -> [core_atom(F),$/,integer_to_list(A)].
-
-%% format_attribute({Name,Val}, Context) -> Txt.
-
-format_attribute({Name,Val}, Ctxt) when list(Val) ->
- Txt = format(#k_atom{val=Name}, Ctxt),
- Ctxt1 = ctxt_bump_indent(Ctxt, width(Txt,Ctxt)+4),
- [Txt," = ",
- $[,format_vseq(Val, "", ",", Ctxt1,
- fun (A, _C) -> io_lib:write(A) end),$]
- ];
-format_attribute({Name,Val}, Ctxt) ->
- Txt = format(#k_atom{val=Name}, Ctxt),
- [Txt," = ",io_lib:write(Val)].
-
-format_list_tail(#k_nil{anno=[]}, _Ctxt) -> "]";
-format_list_tail(#k_cons{anno=[],hd=H,tl=T}, Ctxt) ->
- Txt = [$,|format(H, Ctxt)],
- Ctxt1 = ctxt_bump_indent(Ctxt, width(Txt, Ctxt)),
- [Txt|format_list_tail(T, Ctxt1)];
-format_list_tail(Tail, Ctxt) ->
- ["|",format(Tail, ctxt_bump_indent(Ctxt, 1)), "]"].
-
-format_bin_seg(#k_bin_end{anno=[]}, _Ctxt) -> "";
-format_bin_seg(#k_bin_seg{anno=[],next=N}=Seg, Ctxt) ->
- Txt = [$,|format_bin_seg_1(Seg, Ctxt)],
- [Txt|format_bin_seg(N, ctxt_bump_indent(Ctxt, width(Txt, Ctxt)))];
-format_bin_seg(Seg, Ctxt) ->
- ["|",format(Seg, ctxt_bump_indent(Ctxt, 2))].
-
-format_bin_seg_1(#k_bin_seg{size=S,unit=U,type=T,flags=Fs,seg=Seg}, Ctxt) ->
- [format(Seg, Ctxt),
- ":",format(S, Ctxt),"*",io_lib:write(U),
- ":",io_lib:write(T),
- lists:map(fun (F) -> [$-,io_lib:write(F)] end, Fs)
- ].
-
-% format_bin_elements(#k_binary_cons{hd=H,tl=T,size=S,info=I}, Ctxt) ->
-% A = canno(T),
-% Fe = fun (Eh, Es, Ei, Ct) ->
-% [format(Eh, Ct),":",format(Es, Ct),"/",io_lib:write(Ei)]
-% end,
-% case T of
-% #k_zero_binary{} when A == [] ->
-% Fe(H, S, I, Ctxt);
-% #k_binary_cons{} when A == [] ->
-% Txt = [Fe(H, S, I, Ctxt)|","],
-% Ctxt1 = ctxt_bump_indent(Ctxt, width(Txt, Ctxt)),
-% [Txt|format_bin_elements(T, Ctxt1)];
-% _ ->
-% Txt = [Fe(H, S, I, Ctxt)|"|"],
-% [Txt|format(T, ctxt_bump_indent(Ctxt, width(Txt, Ctxt)))]
-% end.
-
-indent(Ctxt) -> indent(Ctxt#ctxt.indent, Ctxt).
-
-indent(N, _Ctxt) when N =< 0 -> "";
-indent(N, Ctxt) ->
- T = Ctxt#ctxt.tab_width,
- string:chars($\t, N div T, string:chars($\s, N rem T)).
-
-nl_indent(Ctxt) -> [$\n|indent(Ctxt)].
-
-
-unindent(T, Ctxt) ->
- unindent(T, Ctxt#ctxt.indent, Ctxt, []).
-
-unindent(T, N, _Ctxt, C) when N =< 0 ->
- [T|C];
-unindent([$\s|T], N, Ctxt, C) ->
- unindent(T, N - 1, Ctxt, C);
-unindent([$\t|T], N, Ctxt, C) ->
- Tab = Ctxt#ctxt.tab_width,
- if N >= Tab ->
- unindent(T, N - Tab, Ctxt, C);
- true ->
- unindent([string:chars($\s, Tab - N)|T], 0, Ctxt, C)
- end;
-unindent([L|T], N, Ctxt, C) when list(L) ->
- unindent(L, N, Ctxt, [T|C]);
-unindent([H|T], _N, _Ctxt, C) ->
- [H|[T|C]];
-unindent([], N, Ctxt, [H|T]) ->
- unindent(H, N, Ctxt, T);
-unindent([], _, _, []) -> [].
-
-
-width(Txt, Ctxt) ->
- width(Txt, 0, Ctxt, []).
-
-width([$\t|T], A, Ctxt, C) ->
- width(T, A + Ctxt#ctxt.tab_width, Ctxt, C);
-width([$\n|T], _A, Ctxt, C) ->
- width(unindent([T|C], Ctxt), Ctxt);
-width([H|T], A, Ctxt, C) when list(H) ->
- width(H, A, Ctxt, [T|C]);
-width([_|T], A, Ctxt, C) ->
- width(T, A + 1, Ctxt, C);
-width([], A, Ctxt, [H|T]) ->
- width(H, A, Ctxt, T);
-width([], A, _, []) -> A.
-
-ctxt_bump_indent(Ctxt, Dx) ->
- Ctxt#ctxt{indent=Ctxt#ctxt.indent + Dx}.
-
-core_atom(A) -> io_lib:write_string(atom_to_list(A), $').
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_life.erl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_life.erl
deleted file mode 100644
index ff210d83f5..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_life.erl
+++ /dev/null
@@ -1,448 +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: v3_life.erl,v 1.2 2010/03/04 13:54:20 maria Exp $
-%%
-%% Purpose : Convert annotated kernel expressions to annotated beam format.
-
-%% This module creates beam format annotated with variable lifetime
-%% information. Each thing is given an index and for each variable we
-%% store the first and last index for its occurrence. The variable
-%% database, VDB, attached to each thing is only relevant internally
-%% for that thing.
-%%
-%% For nested things like matches the numbering continues locally and
-%% the VDB for that thing refers to the variable usage within that
-%% thing. Variables which live through a such a thing are internally
-%% given a very large last index. Internally the indexes continue
-%% after the index of that thing. This creates no problems as the
-%% internal variable info never escapes and externally we only see
-%% variable which are alive both before or after.
-%%
-%% This means that variables never "escape" from a thing and the only
-%% way to get values from a thing is to "return" them, with 'break' or
-%% 'return'. Externally these values become the return values of the
-%% thing. This is no real limitation as most nested things have
-%% multiple threads so working out a common best variable usage is
-%% difficult.
-
--module(v3_life).
-
--export([module/2]).
-
--export([vdb_find/2]).
-
--import(lists, [map/2,foldl/3]).
--import(ordsets, [add_element/2,intersection/2,union/2,union/1]).
-
--include("v3_kernel.hrl").
--include("v3_life.hrl").
-
-%% These are not defined in v3_kernel.hrl.
-get_kanno(Kthing) -> element(2, Kthing).
-%%set_kanno(Kthing, Anno) -> setelement(2, Kthing, Anno).
-
-module(#k_mdef{name=M,exports=Es,attributes=As,body=Fs0}, Opts) ->
- put(?MODULE, Opts),
- Fs1 = map(fun function/1, Fs0),
- erase(?MODULE),
- {ok,{M,Es,As,Fs1}}.
-
-%% function(Kfunc) -> Func.
-
-function(#k_fdef{func=F,arity=Ar,vars=Vs,body=Kb}) ->
- %%ok = io:fwrite("life ~w: ~p~n", [?LINE,{F,Ar}]),
- As = var_list(Vs),
- Vdb0 = foldl(fun ({var,N}, Vdb) -> new_var(N, 0, Vdb) end, [], As),
- %% Force a top-level match!
- B0 = case Kb of
- #k_match{} -> Kb;
- _ ->
- Ka = get_kanno(Kb),
- #k_match{anno=#k{us=Ka#k.us,ns=[],a=Ka#k.a},
- vars=Vs,body=Kb,ret=[]}
- end,
- {B1,_,Vdb1} = body(B0, 1, Vdb0),
- {function,F,Ar,As,B1,Vdb1}.
-
-%% body(Kbody, I, Vdb) -> {[Expr],MaxI,Vdb}.
-%% Handle a body, need special cases for transforming match_fails.
-%% We KNOW that they only occur last in a body.
-
-body(#k_seq{arg=#k_put{anno=Pa,arg=Arg,ret=[R]},
- body=#k_enter{anno=Ea,op=#k_internal{name=match_fail,arity=1},
- args=[R]}},
- I, Vdb0) ->
- Vdb1 = use_vars(Pa#k.us, I, Vdb0), %All used here
- {[match_fail(Arg, I, Pa#k.a ++ Ea#k.a)],I,Vdb1};
-body(#k_enter{anno=Ea,op=#k_internal{name=match_fail,arity=1},args=[Arg]},
- I, Vdb0) ->
- Vdb1 = use_vars(Ea#k.us, I, Vdb0),
- {[match_fail(Arg, I, Ea#k.a)],I,Vdb1};
-body(#k_seq{arg=Ke,body=Kb}, I, Vdb0) ->
- %%ok = io:fwrite("life ~w:~p~n", [?LINE,{Ke,I,Vdb0}]),
- A = get_kanno(Ke),
- Vdb1 = use_vars(A#k.us, I, new_vars(A#k.ns, I, Vdb0)),
- {Es,MaxI,Vdb2} = body(Kb, I+1, Vdb1),
- E = expr(Ke, I, Vdb2),
- {[E|Es],MaxI,Vdb2};
-body(Ke, I, Vdb0) ->
- %%ok = io:fwrite("life ~w:~p~n", [?LINE,{Ke,I,Vdb0}]),
- A = get_kanno(Ke),
- Vdb1 = use_vars(A#k.us, I, new_vars(A#k.ns, I, Vdb0)),
- E = expr(Ke, I, Vdb1),
- {[E],I,Vdb1}.
-
-%% guard(Kguard, I, Vdb) -> Guard.
-
-guard(#k_try{anno=A,arg=Ts,vars=[#k_var{name=X}],body=#k_var{name=X},
- handler=#k_atom{val=false},ret=Rs}, I, Vdb) ->
- %% Lock variables that are alive before try and used afterwards.
- %% Don't lock variables that are only used inside the try expression.
- Pdb0 = vdb_sub(I, I+1, Vdb),
- {T,MaxI,Pdb1} = guard_body(Ts, I+1, Pdb0),
- Pdb2 = use_vars(A#k.ns, MaxI+1, Pdb1), %Save "return" values
- #l{ke={protected,T,var_list(Rs)},i=I,a=A#k.a,vdb=Pdb2};
-guard(#k_seq{}=G, I, Vdb0) ->
- {Es,_,Vdb1} = guard_body(G, I, Vdb0),
- #l{ke={block,Es},i=I,vdb=Vdb1,a=[]};
-guard(G, I, Vdb) -> guard_expr(G, I, Vdb).
-
-%% guard_body(Kbody, I, Vdb) -> {[Expr],MaxI,Vdb}.
-
-guard_body(#k_seq{arg=Ke,body=Kb}, I, Vdb0) ->
- A = get_kanno(Ke),
- Vdb1 = use_vars(A#k.us, I, new_vars(A#k.ns, I, Vdb0)),
- {Es,MaxI,Vdb2} = guard_body(Kb, I+1, Vdb1),
- E = guard_expr(Ke, I, Vdb2),
- {[E|Es],MaxI,Vdb2};
-guard_body(Ke, I, Vdb0) ->
- A = get_kanno(Ke),
- Vdb1 = use_vars(A#k.us, I, new_vars(A#k.ns, I, Vdb0)),
- E = guard_expr(Ke, I, Vdb1),
- {[E],I,Vdb1}.
-
-%% guard_expr(Call, I, Vdb) -> Expr
-
-guard_expr(#k_test{anno=A,op=Op,args=As}, I, _Vdb) ->
- #l{ke={test,test_op(Op),atomic_list(As)},i=I,a=A#k.a};
-guard_expr(#k_bif{anno=A,op=Op,args=As,ret=Rs}, I, _Vdb) ->
- #l{ke={bif,bif_op(Op),atomic_list(As),var_list(Rs)},i=I,a=A#k.a};
-guard_expr(#k_put{anno=A,arg=Arg,ret=Rs}, I, _Vdb) ->
- #l{ke={set,var_list(Rs),literal(Arg)},i=I,a=A#k.a};
-guard_expr(#k_match{anno=A,body=Kb,ret=Rs}, I, Vdb) ->
- %% Experimental support for andalso/orelse in guards.
- %% Work out imported variables which need to be locked.
- Mdb = vdb_sub(I, I+1, Vdb),
- M = match(Kb, A#k.us, I+1, Mdb),
- #l{ke={match,M,var_list(Rs)},i=I,vdb=use_vars(A#k.us, I+1, Mdb),a=A#k.a};
-guard_expr(G, I, Vdb) -> guard(G, I, Vdb).
-
-%% expr(Kexpr, I, Vdb) -> Expr.
-
-expr(#k_call{anno=A,op=Op,args=As,ret=Rs}, I, _Vdb) ->
- #l{ke={call,call_op(Op),atomic_list(As),var_list(Rs)},i=I,a=A#k.a};
-expr(#k_enter{anno=A,op=Op,args=As}, I, _Vdb) ->
- #l{ke={enter,call_op(Op),atomic_list(As)},i=I,a=A#k.a};
-expr(#k_bif{anno=A,op=Op,args=As,ret=Rs}, I, _Vdb) ->
- Bif = k_bif(A, Op, As, Rs),
- #l{ke=Bif,i=I,a=A#k.a};
-expr(#k_match{anno=A,body=Kb,ret=Rs}, I, Vdb) ->
- %% Work out imported variables which need to be locked.
- Mdb = vdb_sub(I, I+1, Vdb),
- M = match(Kb, A#k.us, I+1, Mdb),
- #l{ke={match,M,var_list(Rs)},i=I,vdb=use_vars(A#k.us, I+1, Mdb),a=A#k.a};
-expr(#k_try{anno=A,arg=Ka,vars=Vs,body=Kb,evars=Evs,handler=Kh,ret=Rs}, I, Vdb) ->
- %% Lock variables that are alive before the catch and used afterwards.
- %% Don't lock variables that are only used inside the try.
- Tdb0 = vdb_sub(I, I+1, Vdb),
- %% This is the tricky bit. Lock variables in Arg that are used in
- %% the body and handler. Add try tag 'variable'.
- Ab = get_kanno(Kb),
- Ah = get_kanno(Kh),
- Tdb1 = use_vars(Ab#k.us, I+3, use_vars(Ah#k.us, I+3, Tdb0)),
- Tdb2 = vdb_sub(I, I+2, Tdb1),
- Vnames = fun (Kvar) -> Kvar#k_var.name end, %Get the variable names
- {Aes,_,Adb} = body(Ka, I+2, add_var({catch_tag,I+1}, I+1, 1000000, Tdb2)),
- {Bes,_,Bdb} = body(Kb, I+4, new_vars(map(Vnames, Vs), I+3, Tdb2)),
- {Hes,_,Hdb} = body(Kh, I+4, new_vars(map(Vnames, Evs), I+3, Tdb2)),
- #l{ke={'try',#l{ke={block,Aes},i=I+1,vdb=Adb,a=[]},
- var_list(Vs),#l{ke={block,Bes},i=I+3,vdb=Bdb,a=[]},
- var_list(Evs),#l{ke={block,Hes},i=I+3,vdb=Hdb,a=[]},
- var_list(Rs)},
- i=I,vdb=Tdb1,a=A#k.a};
-expr(#k_catch{anno=A,body=Kb,ret=[R]}, I, Vdb) ->
- %% Lock variables that are alive before the catch and used afterwards.
- %% Don't lock variables that are only used inside the catch.
- %% Add catch tag 'variable'.
- Cdb0 = vdb_sub(I, I+1, Vdb),
- {Es,_,Cdb1} = body(Kb, I+1, add_var({catch_tag,I}, I, 1000000, Cdb0)),
- #l{ke={'catch',Es,variable(R)},i=I,vdb=Cdb1,a=A#k.a};
-expr(#k_receive{anno=A,var=V,body=Kb,timeout=T,action=Ka,ret=Rs}, I, Vdb) ->
- %% Work out imported variables which need to be locked.
- Rdb = vdb_sub(I, I+1, Vdb),
- M = match(Kb, add_element(V#k_var.name, A#k.us), I+1,
- new_var(V#k_var.name, I, Rdb)),
- {Tes,_,Adb} = body(Ka, I+1, Rdb),
- #l{ke={receive_loop,atomic_lit(T),variable(V),M,
- #l{ke=Tes,i=I+1,vdb=Adb,a=[]},var_list(Rs)},
- i=I,vdb=use_vars(A#k.us, I+1, Vdb),a=A#k.a};
-expr(#k_receive_accept{anno=A}, I, _Vdb) ->
- #l{ke=receive_accept,i=I,a=A#k.a};
-expr(#k_receive_next{anno=A}, I, _Vdb) ->
- #l{ke=receive_next,i=I,a=A#k.a};
-expr(#k_put{anno=A,arg=Arg,ret=Rs}, I, _Vdb) ->
- #l{ke={set,var_list(Rs),literal(Arg)},i=I,a=A#k.a};
-expr(#k_break{anno=A,args=As}, I, _Vdb) ->
- #l{ke={break,atomic_list(As)},i=I,a=A#k.a};
-expr(#k_return{anno=A,args=As}, I, _Vdb) ->
- #l{ke={return,atomic_list(As)},i=I,a=A#k.a}.
-
-%% call_op(Op) -> Op.
-%% bif_op(Op) -> Op.
-%% test_op(Op) -> Op.
-%% Do any necessary name translations here to munge into beam format.
-
-call_op(#k_local{name=N}) -> N;
-call_op(#k_remote{mod=M,name=N}) -> {remote,atomic_lit(M),atomic_lit(N)};
-call_op(Other) -> variable(Other).
-
-bif_op(#k_remote{mod=#k_atom{val=erlang},name=#k_atom{val=N}}) -> N;
-bif_op(#k_internal{name=N}) -> N.
-
-test_op(#k_remote{mod=#k_atom{val=erlang},name=#k_atom{val=N}}) -> N.
-
-%% k_bif(Anno, Op, [Arg], [Ret]) -> Expr.
-%% Build bifs, do special handling of internal some calls.
-
-k_bif(_A, #k_internal{name=dsetelement,arity=3}, As, []) ->
- {bif,dsetelement,atomic_list(As),[]};
-k_bif(_A, #k_internal{name=make_fun},
- [#k_atom{val=Fun},#k_int{val=Arity},
- #k_int{val=Index},#k_int{val=Uniq}|Free],
- Rs) ->
- {bif,{make_fun,Fun,Arity,Index,Uniq},var_list(Free),var_list(Rs)};
-k_bif(_A, Op, As, Rs) ->
- %% The general case.
- {bif,bif_op(Op),atomic_list(As),var_list(Rs)}.
-
-%% match(Kexpr, [LockVar], I, Vdb) -> Expr.
-%% Convert match tree to old format.
-
-match(#k_alt{anno=A,first=Kf,then=Kt}, Ls, I, Vdb0) ->
- Vdb1 = use_vars(union(A#k.us, Ls), I, Vdb0),
- F = match(Kf, Ls, I+1, Vdb1),
- T = match(Kt, Ls, I+1, Vdb1),
- #l{ke={alt,F,T},i=I,vdb=Vdb1,a=A#k.a};
-match(#k_select{anno=A,var=V,types=Kts}, Ls0, I, Vdb0) ->
- Ls1 = add_element(V#k_var.name, Ls0),
- Vdb1 = use_vars(union(A#k.us, Ls1), I, Vdb0),
- Ts = map(fun (Tc) -> type_clause(Tc, Ls1, I+1, Vdb1) end, Kts),
- #l{ke={select,literal(V),Ts},i=I,vdb=Vdb1,a=A#k.a};
-match(#k_guard{anno=A,clauses=Kcs}, Ls, I, Vdb0) ->
- Vdb1 = use_vars(union(A#k.us, Ls), I, Vdb0),
- Cs = map(fun (G) -> guard_clause(G, Ls, I+1, Vdb1) end, Kcs),
- #l{ke={guard,Cs},i=I,vdb=Vdb1,a=A#k.a};
-match(Other, Ls, I, Vdb0) ->
- Vdb1 = use_vars(Ls, I, Vdb0),
- {B,_,Vdb2} = body(Other, I+1, Vdb1),
- #l{ke={block,B},i=I,vdb=Vdb2,a=[]}.
-
-type_clause(#k_type_clause{anno=A,type=T,values=Kvs}, Ls, I, Vdb0) ->
- %%ok = io:format("life ~w: ~p~n", [?LINE,{T,Kvs}]),
- Vdb1 = use_vars(union(A#k.us, Ls), I+1, Vdb0),
- Vs = map(fun (Vc) -> val_clause(Vc, Ls, I+1, Vdb1) end, Kvs),
- #l{ke={type_clause,type(T),Vs},i=I,vdb=Vdb1,a=A#k.a}.
-
-val_clause(#k_val_clause{anno=A,val=V,body=Kb}, Ls0, I, Vdb0) ->
- {_Used,New} = match_pat_vars(V),
- %% Not clear yet how Used should be used.
- Bus = (get_kanno(Kb))#k.us,
- %%ok = io:format("Ls0 = ~p, Used=~p\n New=~p, Bus=~p\n", [Ls0,Used,New,Bus]),
- Ls1 = union(intersection(New, Bus), Ls0), %Lock for safety
- Vdb1 = use_vars(union(A#k.us, Ls1), I+1, new_vars(New, I, Vdb0)),
- B = match(Kb, Ls1, I+1, Vdb1),
- #l{ke={val_clause,literal(V),B},i=I,vdb=use_vars(Bus, I+1, Vdb1),a=A#k.a}.
-
-guard_clause(#k_guard_clause{anno=A,guard=Kg,body=Kb}, Ls, I, Vdb0) ->
- Vdb1 = use_vars(union(A#k.us, Ls), I+2, Vdb0),
- Gdb = vdb_sub(I+1, I+2, Vdb1),
- G = guard(Kg, I+1, Gdb),
- B = match(Kb, Ls, I+2, Vdb1),
- #l{ke={guard_clause,G,B},
- i=I,vdb=use_vars((get_kanno(Kg))#k.us, I+2, Vdb1),
- a=A#k.a}.
-
-%% match_fail(FailValue, I, Anno) -> Expr.
-%% Generate the correct match_fail instruction. N.B. there is no
-%% generic case for when the fail value has been created elsewhere.
-
-match_fail(#k_tuple{es=[#k_atom{val=function_clause}|As]}, I, A) ->
- #l{ke={match_fail,{function_clause,literal_list(As)}},i=I,a=A};
-match_fail(#k_tuple{es=[#k_atom{val=badmatch},Val]}, I, A) ->
- #l{ke={match_fail,{badmatch,literal(Val)}},i=I,a=A};
-match_fail(#k_tuple{es=[#k_atom{val=case_clause},Val]}, I, A) ->
- #l{ke={match_fail,{case_clause,literal(Val)}},i=I,a=A};
-match_fail(#k_atom{val=if_clause}, I, A) ->
- #l{ke={match_fail,if_clause},i=I,a=A};
-match_fail(#k_tuple{es=[#k_atom{val=try_clause},Val]}, I, A) ->
- #l{ke={match_fail,{try_clause,literal(Val)}},i=I,a=A}.
-
-%% type(Ktype) -> Type.
-
-type(k_int) -> integer;
-type(k_char) -> integer; %Hhhmmm???
-type(k_float) -> float;
-type(k_atom) -> atom;
-type(k_nil) -> nil;
-type(k_cons) -> cons;
-type(k_tuple) -> tuple;
-type(k_binary) -> binary;
-type(k_bin_seg) -> bin_seg;
-type(k_bin_end) -> bin_end.
-
-%% variable(Klit) -> Lit.
-%% var_list([Klit]) -> [Lit].
-
-variable(#k_var{name=N}) -> {var,N}.
-
-var_list(Ks) -> map(fun variable/1, Ks).
-
-%% atomic_lit(Klit) -> Lit.
-%% atomic_list([Klit]) -> [Lit].
-
-atomic_lit(#k_var{name=N}) -> {var,N};
-atomic_lit(#k_int{val=I}) -> {integer,I};
-atomic_lit(#k_float{val=F}) -> {float,F};
-atomic_lit(#k_atom{val=N}) -> {atom,N};
-%%atomic_lit(#k_char{val=C}) -> {char,C};
-%%atomic_lit(#k_string{val=S}) -> {string,S};
-atomic_lit(#k_nil{}) -> nil.
-
-atomic_list(Ks) -> map(fun atomic_lit/1, Ks).
-
-%% literal(Klit) -> Lit.
-%% literal_list([Klit]) -> [Lit].
-
-literal(#k_var{name=N}) -> {var,N};
-literal(#k_int{val=I}) -> {integer,I};
-literal(#k_float{val=F}) -> {float,F};
-literal(#k_atom{val=N}) -> {atom,N};
-%%literal(#k_char{val=C}) -> {char,C};
-literal(#k_string{val=S}) -> {string,S};
-literal(#k_nil{}) -> nil;
-literal(#k_cons{hd=H,tl=T}) ->
- {cons,[literal(H),literal(T)]};
-literal(#k_binary{segs=V}) ->
- case proplists:get_bool(no_new_binaries, get(?MODULE)) of
- true ->
- {old_binary,literal(V)};
- false ->
- {binary,literal(V)}
- end;
-literal(#k_bin_seg{size=S,unit=U,type=T,flags=Fs,seg=Seg,next=N}) ->
- {bin_seg,literal(S),U,T,Fs,[literal(Seg),literal(N)]};
-literal(#k_bin_end{}) -> bin_end;
-literal(#k_tuple{es=Es}) ->
- {tuple,literal_list(Es)}.
-
-literal_list(Ks) -> map(fun literal/1, Ks).
-
-%% match_pat_vars(Pattern) -> {[UsedVarName],[NewVarName]}.
-
-match_pat_vars(#k_var{name=N}) -> {[],[N]};
-match_pat_vars(#k_int{}) -> {[],[]};
-match_pat_vars(#k_float{}) -> {[],[]};
-match_pat_vars(#k_atom{}) -> {[],[]};
-%%match_pat_vars(#k_char{}) -> {[],[]};
-match_pat_vars(#k_string{}) -> {[],[]};
-match_pat_vars(#k_nil{}) -> {[],[]};
-match_pat_vars(#k_cons{hd=H,tl=T}) ->
- match_pat_list_vars([H,T]);
-match_pat_vars(#k_binary{segs=V}) ->
- match_pat_vars(V);
-match_pat_vars(#k_bin_seg{size=S,seg=Seg,next=N}) ->
- {U1,New1} = match_pat_vars(Seg),
- {U2,New2} = match_pat_vars(N),
- {[],U3} = match_pat_vars(S),
- {union([U1,U2,U3]),union(New1, New2)};
-match_pat_vars(#k_bin_end{}) -> {[],[]};
-match_pat_vars(#k_tuple{es=Es}) ->
- match_pat_list_vars(Es).
-
-match_pat_list_vars(Ps) ->
- foldl(fun (P, {Used0,New0}) ->
- {Used,New} = match_pat_vars(P),
- {union(Used0, Used),union(New0, New)} end,
- {[],[]}, Ps).
-
-%% new_var(VarName, I, Vdb) -> Vdb.
-%% new_vars([VarName], I, Vdb) -> Vdb.
-%% use_var(VarName, I, Vdb) -> Vdb.
-%% use_vars([VarName], I, Vdb) -> Vdb.
-%% add_var(VarName, F, L, Vdb) -> Vdb.
-
-new_var(V, I, Vdb) ->
- case vdb_find(V, Vdb) of
- {V,F,L} when I < F -> vdb_store(V, I, L, Vdb);
- {V,_,_} -> Vdb;
- error -> vdb_store(V, I, I, Vdb)
- end.
-
-new_vars(Vs, I, Vdb0) ->
- foldl(fun (V, Vdb) -> new_var(V, I, Vdb) end, Vdb0, Vs).
-
-use_var(V, I, Vdb) ->
- case vdb_find(V, Vdb) of
- {V,F,L} when I > L -> vdb_store(V, F, I, Vdb);
- {V,_,_} -> Vdb;
- error -> vdb_store(V, I, I, Vdb)
- end.
-
-use_vars(Vs, I, Vdb0) ->
- foldl(fun (V, Vdb) -> use_var(V, I, Vdb) end, Vdb0, Vs).
-
-add_var(V, F, L, Vdb) ->
- use_var(V, L, new_var(V, F, Vdb)).
-
-vdb_find(V, Vdb) ->
- %% Peformance note: Profiling shows that this function accounts for
- %% a lot of the execution time when huge constants terms are built.
- %% Using the BIF lists:keysearch/3 is a lot faster than the
- %% original Erlang version.
- case lists:keysearch(V, 1, Vdb) of
- {value,Vd} -> Vd;
- false -> error
- end.
-
-%vdb_find(V, [{V1,F,L}=Vd|Vdb]) when V < V1 -> error;
-%vdb_find(V, [{V1,F,L}=Vd|Vdb]) when V == V1 -> Vd;
-%vdb_find(V, [{V1,F,L}=Vd|Vdb]) when V > V1 -> vdb_find(V, Vdb);
-%vdb_find(V, []) -> error.
-
-vdb_store(V, F, L, [{V1,_,_}=Vd|Vdb]) when V > V1 ->
- [Vd|vdb_store(V, F, L, Vdb)];
-vdb_store(V, F, L, [{V1,_,_}=Vd|Vdb]) when V < V1 -> [{V,F,L},Vd|Vdb];
-vdb_store(V, F, L, [{_V1,_,_}|Vdb]) -> [{V,F,L}|Vdb]; %V == V1
-vdb_store(V, F, L, []) -> [{V,F,L}].
-
-%% vdb_sub(Min, Max, Vdb) -> Vdb.
-%% Extract variables which are used before and after Min. Lock
-%% variables alive after Max.
-
-vdb_sub(Min, Max, Vdb) ->
- [ if L >= Max -> {V,F,1000000};
- true -> Vd
- end || {V,F,L}=Vd <- Vdb, F < Min, L >= Min ].
diff --git a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_life.hrl b/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_life.hrl
deleted file mode 100644
index 95adcfcfd8..0000000000
--- a/lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/v3_life.hrl
+++ /dev/null
@@ -1,25 +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: v3_life.hrl,v 1.1 2008/12/17 09:53:43 mikpe Exp $
-%%
-%% This record contains variable life-time annotation for a
-%% kernel expression. Added by v3_life, used by v3_codegen.
-
--record(l, {ke, %Kernel expression
- i=0, %Op number
- vdb=[], %Variable database
- a}). %Core annotation
-
diff --git a/lib/dialyzer/test/options2_tests_SUITE_data/dialyzer_options b/lib/dialyzer/test/options2_SUITE_data/dialyzer_options
index 5db2e50d23..5db2e50d23 100644
--- a/lib/dialyzer/test/options2_tests_SUITE_data/dialyzer_options
+++ b/lib/dialyzer/test/options2_SUITE_data/dialyzer_options
diff --git a/lib/dialyzer/test/options2_tests_SUITE_data/results/kernel b/lib/dialyzer/test/options2_SUITE_data/results/kernel
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/options2_tests_SUITE_data/results/kernel
+++ b/lib/dialyzer/test/options2_SUITE_data/results/kernel
diff --git a/lib/dialyzer/test/options2_SUITE_data/src/kernel/global.erl b/lib/dialyzer/test/options2_SUITE_data/src/kernel/global.erl
new file mode 100644
index 0000000000..4778a39a3c
--- /dev/null
+++ b/lib/dialyzer/test/options2_SUITE_data/src/kernel/global.erl
@@ -0,0 +1,1999 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: global.erl,v 1.4 2009/09/17 09:46:19 kostis Exp $
+%%
+-module(global).
+-behaviour(gen_server).
+
+%% A Global register that allows the global registration of pid's and
+%% name's, that dynamically keeps up to date with the entire network.
+%% global can operate in two modes; in a fully connected network, or
+%% in a non-fully connected network. In the latter case, the name
+%% registration mechanism won't work.
+%%
+
+%% External exports
+-export([start/0, start_link/0, stop/0, sync/0, sync/1,
+ safe_whereis_name/1, whereis_name/1, register_name/2, register_name/3,
+ register_name_external/2, register_name_external/3, unregister_name_external/1,
+ re_register_name/2, re_register_name/3,
+ unregister_name/1, registered_names/0, send/2, node_disconnected/1,
+ set_lock/1, set_lock/2, set_lock/3,
+ del_lock/1, del_lock/2,
+ trans/2, trans/3, trans/4,
+ random_exit_name/3, random_notify_name/3, notify_all_name/3, cnode/3]).
+
+%% Internal exports
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
+ code_change/3, timer/2, sync_init/2, init_locker/5, resolve_it/4,
+ init_the_locker/1]).
+
+-export([info/0]).
+
+
+%-define(PRINT(X), erlang:display(X)).
+-define(PRINT(X), true).
+
+%-define(P2(X), erlang:display(X)).
+%-define(P2(X), erlang:display({cs(),X})).
+-define(P2(X), true).
+
+%-define(P1(X), erlang:display(X)).
+-define(P1(X), true).
+
+%-define(P(X), erlang:display(X)).
+-define(P(X), true).
+
+%-define(FORMAT(S, A), format(S, A)).
+-define(FORMAT(S, A), ok).
+
+%%% In certain places in the server, calling io:format hangs everything,
+%%% so we'd better use erlang:display/1.
+% format(S, A) ->
+% erlang:display({format, cs(), S, A}),
+% % io:format(S, A),
+% ok.
+
+% cs() ->
+% {Big, Small, Tiny} = now(),
+% (Small rem 100) * 100 + (Tiny div 10000).
+
+%% Some notes on the internal structure:
+%% One invariant is that the list of locker processes is keyed; i.e.,
+%% there is only one process per neighboring node.
+%% When an item has been stored in the process dictionary, it is not
+%% necessarily cleared when not in use anymore. In other words, it's
+%% not an error if there is already an item there when one is to be
+%% stored.
+
+
+%% This is the protocol version
+%% Vsn 1 is the original protocol.
+%% Vsn 2 is enhanced with code to take care of registration of names from
+%% non erlang nodes, e.g. c-nodes.
+%% Vsn 3 is enhanced with a tag in the synch messages to distinguish
+%% different synch sessions from each other, see OTP-2766.
+%% Note: This requires also that the ticket OTP-2928 is fixed on the nodes
+%% running vsn 1 or 2; if such nodes will coexist with vsn 3 nodes.
+%% Vsn 4 uses a single, permanent, locker process, but works like vsn 3
+%% when communicating with vsn 3 nodes.
+
+%% -define(vsn, 4). %% Now given in options
+
+%%-----------------------------------------------------------------
+%% connect_all = boolean() - true if we are supposed to set up a
+%% fully connected net
+%% known = [Node] - all nodes known to us
+%% synced = [Node] - all nodes that have the same names as us
+%% lockers = [{Node, MyLockerPid}] - the pid of the locker
+%% process for each Node
+%% syncers = [pid()] - all current syncers processes
+%% node_name = atom() - our node name (can change if distribution
+%% is started/stopped dynamically)
+%%
+%% In addition to these, we keep info about messages arrived in
+%% the process dictionary:
+%% {pre_connect, Node} = {Vsn, InitMsg} - init_connect msgs that
+%% arrived before nodeup
+%% {wait_lock, Node} = {exchange, NameList} | lock_is_set
+%% - see comment below (handle_cast)
+%% {save_ops, Node} = [operation()] - save the ops between
+%% exchange and resolved
+%% {prot_vsn, Node} = Vsn - the exchange protocol version
+%% {sync_tag_my, Node} = My tag, used at synchronization with Node
+%% {sync_tag_his, Node} = The Node's tag, used at synchronization
+%%-----------------------------------------------------------------
+-record(state, {connect_all, known = [], synced = [],
+ lockers = [], syncers = [], node_name = node(),
+ the_locker, the_deleter}).
+
+start() -> gen_server:start({local, global_name_server}, global, [], []).
+start_link() -> gen_server:start_link({local, global_name_server},global,[],[]).
+stop() -> gen_server:call(global_name_server, stop, infinity).
+
+sync() ->
+ case check_sync_nodes() of
+ {error, Error} ->
+ {error, Error};
+ SyncNodes ->
+ gen_server:call(global_name_server, {sync, SyncNodes}, infinity)
+ end.
+sync(Nodes) ->
+ case check_sync_nodes(Nodes) of
+ {error, Error} ->
+ {error, Error};
+ SyncNodes ->
+ gen_server:call(global_name_server, {sync, SyncNodes}, infinity)
+ end.
+
+
+send(Name, Msg) ->
+ case whereis_name(Name) of
+ Pid when pid(Pid) ->
+ Pid ! Msg,
+ Pid;
+ undefined ->
+ exit({badarg, {Name, Msg}})
+ end.
+
+%% See OTP-3737. (safe_whereis_name/1 is in fact not used anywhere in OTP.)
+whereis_name(Name) ->
+ where(Name).
+
+safe_whereis_name(Name) ->
+ gen_server:call(global_name_server, {whereis, Name}, infinity).
+
+
+node_disconnected(Node) ->
+ global_name_server ! {nodedown, Node}.
+
+
+%%-----------------------------------------------------------------
+%% Method = function(Name, Pid1, Pid2) -> Pid | Pid2 | none
+%% Method is called if a name conflict is detected when two nodes
+%% are connecting to each other. It is supposed to return one of
+%% the Pids or 'none'. If a pid is returned, that pid is
+%% registered as Name on all nodes. If 'none' is returned, the
+%% Name is unregistered on all nodes. If anything else is returned,
+%% the Name is unregistered as well.
+%% Method is called once at one of the nodes where the processes reside
+%% only. If different Methods are used for the same name, it is
+%% undefined which one of them is used.
+%% Method is blocking, i.e. when it is called, no calls to whereis/
+%% send is let through until it has returned.
+%%-----------------------------------------------------------------
+register_name(Name, Pid) when pid(Pid) ->
+ register_name(Name, Pid, {global, random_exit_name}).
+register_name(Name, Pid, Method) when pid(Pid) ->
+ trans_all_known(fun(Nodes) ->
+ case where(Name) of
+ undefined ->
+ gen_server:multi_call(Nodes,
+ global_name_server,
+ {register, Name, Pid, Method}),
+ yes;
+ _Pid -> no
+ end
+ end).
+
+unregister_name(Name) ->
+ case where(Name) of
+ undefined ->
+ ok;
+ _ ->
+ trans_all_known(fun(Nodes) ->
+ gen_server:multi_call(Nodes,
+ global_name_server,
+ {unregister, Name}),
+ ok
+ end)
+ end.
+
+re_register_name(Name, Pid) when pid(Pid) ->
+ re_register_name(Name, Pid, {global, random_exit_name}).
+re_register_name(Name, Pid, Method) when pid(Pid) ->
+ trans_all_known(fun(Nodes) ->
+ gen_server:multi_call(Nodes,
+ global_name_server,
+ {register, Name, Pid, Method}),
+ yes
+ end).
+
+%% Returns all globally registered names
+registered_names() -> lists:map(fun({Name, _Pid, _Method}) -> Name end,
+ ets:tab2list(global_names)).
+
+%%-----------------------------------------------------------------
+%% An external node (i.e not an erlang node) (un)registers a name.
+%% If the registered Pid crashes the name is to be removed from global.
+%% If the external node crashes the name is to be removed from global.
+%% If the erlang node which registers the name crashes the name is also to be
+%% removed, because the registered process is not supervised any more,
+%% (i.e there is no link to the registered Pid).
+%%-----------------------------------------------------------------
+register_name_external(Name, Pid) when pid(Pid) ->
+ register_name_external(Name, Pid, {global, random_exit_name}).
+register_name_external(Name, Pid, Method) when pid(Pid) ->
+ trans_all_known(fun(Nodes) ->
+ case where(Name) of
+ undefined ->
+ gen_server:multi_call(Nodes,
+ global_name_server,
+ {register, Name, Pid, Method}),
+ gen_server:multi_call(Nodes,
+ global_name_server,
+ {register_ext, Name, Pid, node()}),
+ yes;
+ _Pid -> no
+ end
+ end).
+
+
+
+
+unregister_name_external(Name) ->
+ case where(Name) of
+ undefined ->
+ ok;
+ _ ->
+ trans_all_known(fun(Nodes) ->
+ gen_server:multi_call(Nodes,
+ global_name_server,
+ {unregister, Name}),
+ gen_server:multi_call(Nodes,
+ global_name_server,
+ {unregister_ext, Name}),
+ ok
+ end)
+ end.
+
+
+
+
+
+%%-----------------------------------------------------------------
+%% Args: Id = id()
+%% Nodes = [node()]
+%% id() = {ResourceId, LockRequesterId}
+%% Retries = infinity | int() > 0
+%% Purpose: Sets a lock on the specified nodes (or all nodes if
+%% none are specified) on ResourceId for LockRequesterId. If there
+%% already exists a lock on ResourceId for another owner
+%% than LockRequesterId, false is returned, otherwise true.
+%% Returns: boolean()
+%%-----------------------------------------------------------------
+set_lock(Id) ->
+ set_lock(Id, [node() | nodes()], infinity, 1).
+set_lock(Id, Nodes) ->
+ set_lock(Id, Nodes, infinity, 1).
+set_lock(Id, Nodes, Retries) when Retries > 0 ->
+ set_lock(Id, Nodes, Retries, 1);
+set_lock(Id, Nodes, infinity) ->
+ set_lock(Id, Nodes, infinity, 1).
+set_lock(_Id, _Nodes, 0, _) -> false;
+set_lock({ResourceId, LockRequesterId}, Nodes, Retries, Times) ->
+ Id = {ResourceId, LockRequesterId},
+ Msg = {set_lock, Id},
+ {Replies, _} =
+ gen_server:multi_call(Nodes, global_name_server, Msg),
+ ?P2({set_lock, node(), self(), {ResourceId, LockRequesterId},
+ Nodes, Retries, Times, Replies, catch erlang:error(kaka)}),
+ ?P({set_lock, node(), ResourceId,
+ {LockRequesterId, node(LockRequesterId)}}),
+ case check_replies(Replies, Id, Nodes) of
+ true -> ?P({set_lock_true, node(), ResourceId}),
+ true;
+ false ->
+ random_sleep(Times),
+ set_lock(Id, Nodes, dec(Retries), Times+1);
+ N when integer(N) ->
+ ?P({sleeping, N}),
+ timer:sleep(N*500),
+ set_lock(Id, Nodes, Retries, Times);
+ Pid when pid(Pid) ->
+ ?P({waiting_for, Pid}),
+ Ref = erlang:monitor(process, Pid),
+ receive
+ {'DOWN', Ref, process, Pid, _Reason} ->
+ ?P({waited_for, Pid, _Reason}),
+ set_lock(Id, Nodes, Retries, Times)
+ end
+ end.
+
+check_replies([{_Node, true} | T], Id, Nodes) ->
+ check_replies(T, Id, Nodes);
+check_replies([{_Node, Status} | _T], Id, Nodes) ->
+ gen_server:multi_call(Nodes, global_name_server, {del_lock, Id}),
+ Status;
+check_replies([], _Id, _Nodes) ->
+ true.
+
+del_lock(Id) ->
+ del_lock(Id, [node() | nodes()]).
+del_lock({ResourceId, LockRequesterId}, Nodes) ->
+ Id = {ResourceId, LockRequesterId},
+ ?P2({del_lock, node(), self(), ResourceId, LockRequesterId, Nodes}),
+ gen_server:multi_call(Nodes, global_name_server, {del_lock, Id}),
+ true.
+
+%%-----------------------------------------------------------------
+%% Args: Id = id()
+%% Fun = fun() | {M,F}
+%% Nodes = [node()]
+%% Retries = infinity | int() > 0
+%% Purpose: Sets a lock on Id (as set_lock), and evaluates
+%% Res = Fun() on success.
+%% Returns: Res | aborted (note, if Retries is infinity, the
+%% transaction won't abort)
+%%-----------------------------------------------------------------
+trans(Id, Fun) -> trans(Id, Fun, [node() | nodes()], infinity).
+trans(Id, Fun, Nodes) -> trans(Id, Fun, Nodes, infinity).
+trans(_Id, _Fun, _Nodes, 0) -> aborted;
+trans(Id, Fun, Nodes, Retries) ->
+ case set_lock(Id, Nodes, Retries) of
+ true ->
+ case catch Fun() of
+ {'EXIT', R} ->
+ del_lock(Id, Nodes),
+ exit(R);
+ Res ->
+ del_lock(Id, Nodes),
+ Res
+ end;
+ false ->
+ aborted
+ end.
+
+%%% Similar to trans(Id, Fun), but always uses global's own lock,
+%%% on all nodes known to global, making sure that no new nodes have
+%%% become known while we got the list of known nodes.
+trans_all_known(F) ->
+ Id = {global, self()},
+ Nodes = [node() | gen_server:call(global_name_server, get_known)],
+ case set_lock(Id, Nodes) of
+ true ->
+ Nodes2 = [node() | gen_server:call(global_name_server, get_known)],
+ case Nodes2 -- Nodes of
+ [] ->
+ case catch F(Nodes2) of
+ {'EXIT', R} ->
+ del_lock(Id, Nodes2),
+ exit(R);
+ Res ->
+ del_lock(Id, Nodes2),
+ Res
+ end;
+ _ ->
+ del_lock(Id, Nodes),
+ trans_all_known(F)
+ end;
+ false ->
+ aborted
+ end.
+
+info() ->
+ gen_server:call(global_name_server, info).
+
+%%%-----------------------------------------------------------------
+%%% Call-back functions from gen_server
+%%%-----------------------------------------------------------------
+init([]) ->
+ process_flag(trap_exit, true),
+ ets:new(global_locks, [set, named_table, protected]),
+ ets:new(global_names, [set, named_table, protected]),
+ ets:new(global_names_ext, [set, named_table, protected]),
+
+ %% multi
+ S = #state{the_locker = start_the_locker(self()),
+ the_deleter = start_the_deleter(self())},
+
+ case init:get_argument(connect_all) of
+ {ok, [["false"]]} ->
+ {ok, S#state{connect_all = false}};
+ _ ->
+ {ok, S#state{connect_all = true}}
+ end.
+
+%%-----------------------------------------------------------------
+%% Connection algorithm
+%% ====================
+%% This alg solves the problem with partitioned nets as well.
+%%
+%% The main idea in the alg is that when two nodes connect, they
+%% try to set a lock in their own partition (i.e. all nodes already
+%% known to them). When the lock is set in each partition, these
+%% two nodes send each other a list with all registered names in
+%% resp partition(*). If no conflict is found, the name tables are
+%% just updated. If a conflict is found, a resolve function is
+%% called once for each conflict. The result of the resolving
+%% is sent to the other node. When the names are exchanged, all
+%% other nodes in each partition are informed of the other nodes,
+%% and they ping each other to form a fully connected net.
+%%
+%% Here's the flow:
+%% Suppose nodes A and B connect, and C is connected to A.
+%%
+%% Node A
+%% ------
+%% << {nodeup, B}
+%% [spawn locker]
+%% B ! {init_connect, MyLocker}
+%% << {init_connect, MyLocker}
+%% [The lockers try to set the lock]
+%% << {lock_is_set, B}
+%% [Now, lock is set in both partitions]
+%% B ! {exchange, Names}
+%% << {exchange, Names}
+%% [solve conflict]
+%% B ! {resolved, Resolved}
+%% << {resolved, Resolved}
+%% C ! {new_nodes, Resolved, [B]}
+%%
+%% Node C
+%% ------
+%% << {new_nodes, ResolvedOps, NewNodes}
+%% [insert Ops]
+%% ping(NewNodes)
+%% << {nodeup, B}
+%% <ignore this one>
+%%
+%% Several things can disturb this picture.
+%%
+%% First, the got_names message may arrive *before* the nodeup
+%% message, due to delay in net_kernel and an optimisation in the
+%% emulator. We handle this by keeping track of these messages in the
+%% pre_connect and lockers variables in our state.
+%%
+%% The most common situation is when a new node connects to an
+%% existing net. In this case there's no need to set the lock on
+%% all nodes in the net, as we know that there won't be any conflict.
+%% This is optimised by sending {first_contact, Node} instead of got_names.
+%% This implies that first_contact may arrive before nodeup as well.
+%%
+%% Of course we must handle that some node goes down during the
+%% connection.
+%%
+%% (*) When this information is being exchanged, no one is allowed
+%% to change the global register table. All calls to register etc
+%% are protected by a lock. If a registered process dies
+%% during this phase, the deregistration is done as soon as possible
+%% on each node (i.e. when the info about the process has arrived).
+%%-----------------------------------------------------------------
+%% Messages in the protocol
+%% ========================
+%% 1. Between connecting nodes (gen_server:casts)
+%% {init_connect, Vsn, Node, InitMsg}
+%% InitMsg = {locker, LockerPid}
+%% {exchange, Node, ListOfNames}
+%% {resolved, Node, Ops, Known}
+%% Known = list of nodes in Node's partition
+%% 2. Between lockers on connecting nodes (!s)
+%% {his_locker, Pid} (from our global)
+%% lockers link to each other
+%% {lock, Bool} loop until both lockers have lock = true,
+%% then send to global {lock_is_set, Node}
+%% 3. From connecting node to other nodes in the partition
+%% {new_nodes, Node, Ops, NewNodes}
+%% 4. sync protocol
+%% {in_sync, Node, IsKnown}
+%% - sent by each node to all new nodes
+%%-----------------------------------------------------------------
+
+handle_call({whereis, Name}, From, S) ->
+ do_whereis(Name, From),
+ {noreply, S};
+
+handle_call({register, Name, Pid, Method}, _From, S) ->
+ ?P2({register, node(), Name}),
+ ins_name(Name, Pid, Method),
+ {reply, yes, S};
+
+handle_call({unregister, Name}, _From, S) ->
+ case ets:lookup(global_names, Name) of
+ [{_, Pid, _}] ->
+ ?P2({unregister, node(), Name, Pid, node(Pid)}),
+ ets:delete(global_names, Name),
+ dounlink(Pid);
+ _ -> ok
+ end,
+ {reply, ok, S};
+
+handle_call({register_ext, Name, Pid, RegNode}, _F, S) ->
+ ins_name_ext(Name, Pid, RegNode),
+ {reply, yes, S};
+
+handle_call({unregister_ext, Name}, _From, S) ->
+ ets:delete(global_names_ext, Name),
+ {reply, ok, S};
+
+
+handle_call({set_lock, Lock}, {Pid, _Tag}, S) ->
+ Reply = handle_set_lock(Lock, Pid),
+ {reply, Reply, S};
+
+handle_call({del_lock, Lock}, {Pid, _Tag}, S) ->
+ handle_del_lock(Lock, Pid),
+ {reply, true, S};
+
+handle_call(get_known, _From, S) ->
+ {reply, S#state.known, S};
+
+%% R7 may call us?
+handle_call(get_known_v2, _From, S) ->
+ {reply, S#state.known, S};
+
+handle_call({sync, Nodes}, From, S) ->
+ %% If we have several global groups, this won't work, since we will
+ %% do start_sync on a nonempty list of nodes even if the system
+ %% is quiet.
+ Pid = start_sync(lists:delete(node(), Nodes) -- S#state.synced, From),
+ {noreply, S#state{syncers = [Pid | S#state.syncers]}};
+
+handle_call(get_protocol_version, _From, S) ->
+ {reply, ?vsn, S};
+
+handle_call(get_names_ext, _From, S) ->
+ {reply, get_names_ext(), S};
+
+handle_call(info, _From, S) ->
+ {reply, S, S};
+
+handle_call(stop, _From, S) ->
+ {stop, normal, stopped, S}.
+
+
+%%=======================================================================================
+%% init_connect
+%%
+%% Vsn 1 is the original protocol.
+%% Vsn 2 is enhanced with code to take care of registration of names from
+%% non erlang nodes, e.g. c-nodes.
+%% Vsn 3 is enhanced with a tag in the synch messages to distinguish
+%% different synch sessions from each other, see OTP-2766.
+%% Note: This requires also that the ticket OTP-2928 is fixed on the nodes
+%% running vsn 1 or 2; if such nodes will coexist with vsn 3 nodes.
+%%=======================================================================================
+handle_cast({init_connect, Vsn, Node, InitMsg}, S) ->
+ ?FORMAT("~p #### init_connect Vsn ~p, Node ~p, InitMsg ~p~n",[node(), Vsn, Node, InitMsg]),
+ case Vsn of
+ %% It is always the responsibility of newer versions to understand
+ %% older versions of the protocol.
+ {HisVsn, HisTag} when HisVsn > ?vsn ->
+ init_connect(?vsn, Node, InitMsg, HisTag, S#state.lockers, S);
+ {HisVsn, HisTag} ->
+ init_connect(HisVsn, Node, InitMsg, HisTag, S#state.lockers, S);
+ %% To be future compatible
+ Tuple when tuple(Tuple) ->
+ List = tuple_to_list(Tuple),
+ [_HisVsn, HisTag | _] = List,
+ %% use own version handling if his is newer.
+ init_connect(?vsn, Node, InitMsg, HisTag, S#state.lockers, S);
+ _ when Vsn < 3 ->
+ init_connect(Vsn, Node, InitMsg, undef, S#state.lockers, S);
+ _ ->
+ Txt = io_lib:format("Illegal global protocol version ~p Node: ~p",[Vsn, Node]),
+ error_logger:info_report(lists:flatten(Txt))
+ end,
+ {noreply, S};
+
+%%=======================================================================================
+%% lock_is_set
+%%
+%% Ok, the lock is now set on both partitions. Send our names to other node.
+%%=======================================================================================
+handle_cast({lock_is_set, Node, MyTag}, S) ->
+ ?FORMAT("~p #### lock_is_set Node ~p~n",[node(), Node]),
+ Sync_tag_my = get({sync_tag_my, Node}),
+ PVsn = get({prot_vsn, Node}),
+ ?P2({lock_is_set, node(), Node, {MyTag, PVsn}, Sync_tag_my}),
+ case {MyTag, PVsn} of
+ {Sync_tag_my, undefined} ->
+ %% Patch for otp-2728, the connection to the Node is flipping up and down
+ %% the messages from the 'older' sync tries can disturb the 'new' sync try
+ %% therefor all messages are discarded if the protocol vsn is not defined.
+ Txt = io_lib:format("undefined global protocol version Node: ~p",[Node]),
+ error_logger:info_report(lists:flatten(Txt)),
+ {noreply, S};
+ {Sync_tag_my, _} ->
+ %% Check that the Node is still not known
+ case lists:member(Node, S#state.known) of
+ false ->
+ ?P2({lset, node(), Node, false}),
+ lock_is_set(Node, S#state.known),
+ {noreply, S};
+ true ->
+ ?P2({lset, node(), Node, true}),
+ erase({wait_lock, Node}),
+ NewS = cancel_locker(Node, S),
+ {noreply, NewS}
+ end;
+ _ ->
+ ?P2({lset, illegal, node(), Node}),
+ %% Illegal tag, delete the locker.
+ erase({wait_lock, Node}),
+ NewS = cancel_locker(Node, S),
+ {noreply, NewS}
+ end;
+
+%%=======================================================================================
+%% exchange
+%%
+%% Here the names are checked to detect name clashes.
+%%=======================================================================================
+%% Vsn 3 of the protocol
+handle_cast({exchange, Node, NameList, NameExtList, MyTag}, S) ->
+ ?FORMAT("~p #### handle_cast 3 lock_is_set exchange ~p~n",
+ [node(),{Node, NameList, NameExtList, MyTag}]),
+ Sync_tag_my = get({sync_tag_my, Node}),
+ PVsn = get({prot_vsn, Node}),
+ case {MyTag, PVsn} of
+ {Sync_tag_my, undefined} ->
+ %% Patch for otp-2728, the connection to the Node is flipping up and down
+ %% the messages from the 'older' sync tries can disturb the 'new' sync try
+ %% therefor all messages are discarded if the protocol vsn is not defined.
+ Txt = lists:flatten(io_lib:format(
+ "undefined global protocol version Node: ~p",[Node])),
+ error_logger:info_report(Txt),
+ {noreply, S};
+ {Sync_tag_my, _} ->
+ exchange(PVsn, Node, {NameList, NameExtList}, S#state.known),
+ {noreply, S};
+ _ ->
+ %% Illegal tag, delete the locker.
+ erase({wait_lock, Node}),
+ NewS = cancel_locker(Node, S),
+ {noreply, NewS}
+ end;
+
+
+
+%%=======================================================================================
+%% resolved
+%%
+%% Here the name clashes are resolved.
+%%=======================================================================================
+%% Vsn 3 of the protocol
+handle_cast({resolved, Node, Resolved, HisKnown, _HisKnown_v2, Names_ext, MyTag}, S) ->
+ ?FORMAT("~p #### 2 resolved ~p~n",[node(),{Node, Resolved, HisKnown, Names_ext}]),
+ Sync_tag_my = get({sync_tag_my, Node}),
+ PVsn = get({prot_vsn, Node}),
+ case {MyTag, PVsn} of
+ {Sync_tag_my, undefined} ->
+ %% Patch for otp-2728, the connection to the Node is flipping up and down
+ %% the messages from the 'older' sync tries can disturb the 'new' sync try
+ %% therefor all messages are discarded if the protocol vsn is not defined.
+ Txt = lists:flatten(io_lib:format(
+ "undefined global protocol version Node: ~p",[Node])),
+ error_logger:info_report(Txt),
+ {noreply, S};
+ {Sync_tag_my, _} ->
+ NewS = resolved(Node, Resolved, {HisKnown, HisKnown}, Names_ext, S),
+ {noreply, NewS};
+ _ ->
+ %% Illegal tag, delete the locker.
+ erase({wait_lock, Node}),
+ NewS = cancel_locker(Node, S),
+ {noreply, NewS}
+ end;
+
+
+
+
+
+
+%%=======================================================================================
+%% new_nodes
+%%
+%% We get to know the other node's known nodes.
+%%=======================================================================================
+%% Vsn 2 and 3 of the protocol
+handle_cast({new_nodes, _Node, Ops, Names_ext, Nodes, _Nodes_v2}, S) ->
+ ?P2({new_nodes, node(), Nodes}),
+ ?FORMAT("~p #### 2 new_nodes ~p~n",[node(),{Ops, Names_ext, Nodes}]),
+ NewS = new_nodes(Ops, Names_ext, Nodes, S),
+ {noreply, NewS};
+
+
+
+
+%%=======================================================================================
+%% in_sync
+%%
+%% We are in sync with this node (from the other node's known world).
+%%=======================================================================================
+handle_cast({in_sync, Node, IsKnown}, S) ->
+ ?FORMAT("~p #### in_sync ~p~n",[node(),{Node, IsKnown}]),
+ lists:foreach(fun(Pid) -> Pid ! {synced, [Node]} end, S#state.syncers),
+ %% moved up:
+ NewS = cancel_locker(Node, S),
+ erase({wait_lock, Node}),
+ erase({pre_connect, Node}),
+ erase({sync_tag_my, Node}),
+ erase({sync_tag_his, Node}),
+ NKnown = case lists:member(Node, Known = NewS#state.known) of
+ false when IsKnown == true ->
+ gen_server:cast({global_name_server, Node},
+ {in_sync, node(), false}),
+ [Node | Known];
+ _ ->
+ Known
+ end,
+ NSynced = case lists:member(Node, Synced = NewS#state.synced) of
+ true -> Synced;
+ false -> [Node | Synced]
+ end,
+ {noreply, NewS#state{known = NKnown, synced = NSynced}};
+
+
+
+
+%% Called when Pid on other node crashed
+handle_cast({async_del_name, Name, Pid}, S) ->
+ ?P2({async_del_name, node(), Name, Pid, node(Pid)}),
+ case ets:lookup(global_names, Name) of
+ [{Name, Pid, _}] ->
+ ets:delete(global_names, Name),
+ dounlink(Pid);
+ _ -> ok
+ end,
+ ets:delete(global_names_ext, Name),
+ {noreply, S};
+
+handle_cast({async_del_lock, _ResourceId, Pid}, S) ->
+ del_locks2(ets:tab2list(global_locks), Pid),
+% ets:match_delete(global_locks, {ResourceId, '_', Pid}),
+ {noreply, S}.
+
+
+handle_info({'EXIT', Deleter, _Reason}=Exit, #state{the_deleter=Deleter}=S) ->
+ {stop, {deleter_died,Exit}, S#state{the_deleter=undefined}};
+handle_info({'EXIT', Pid, _Reason}, #state{the_deleter=Deleter}=S)
+ when pid(Pid) ->
+ ?P2({global, exit, node(), Pid, node(Pid)}),
+ check_exit(Deleter, Pid),
+ Syncers = lists:delete(Pid, S#state.syncers),
+ Lockers = lists:keydelete(Pid, 2, S#state.lockers),
+ ?PRINT({exit, Pid, lockers, node(), S#state.lockers}),
+ {noreply, S#state{syncers = Syncers, lockers = Lockers}};
+
+handle_info({nodedown, Node}, S) when Node == S#state.node_name ->
+ %% Somebody stopped the distribution dynamically - change
+ %% references to old node name (Node) to new node name ('nonode@nohost')
+ {noreply, change_our_node_name(node(), S)};
+
+handle_info({nodedown, Node}, S) ->
+ ?FORMAT("~p #### nodedown 1 ####### Node ~p",[node(),Node]),
+ %% moved up:
+ do_node_down(Node),
+ #state{known = Known, synced = Syncs} = S,
+ NewS = cancel_locker(Node, S),
+
+ erase({wait_lock, Node}),
+ erase({save_ops, Node}),
+ erase({pre_connect, Node}),
+ erase({prot_vsn, Node}),
+ erase({sync_tag_my, Node}),
+ erase({sync_tag_his, Node}),
+ {noreply, NewS#state{known = lists:delete(Node, Known),
+ synced = lists:delete(Node, Syncs)}};
+
+
+
+handle_info({nodeup, Node}, S) when Node == node() ->
+ ?FORMAT("~p #### nodeup S ####### Node ~p~n",[node(), Node]),
+ %% Somebody started the distribution dynamically - change
+ %% references to old node name ('nonode@nohost') to Node.
+ {noreply, change_our_node_name(Node, S)};
+
+handle_info({nodeup, Node}, S) when S#state.connect_all == true ->
+ ?FORMAT("~p #### nodeup 1 ####### Node ~p",[node(),Node]),
+ IsKnown = lists:member(Node, S#state.known) or
+ %% This one is only for double nodeups (shouldn't occur!)
+ lists:keymember(Node, 1, S#state.lockers),
+ case IsKnown of
+ true ->
+ {noreply, S};
+ false ->
+ %% now() is used as a tag to separate different sycnh sessions
+ %% from each others. Global could be confused at bursty nodeups
+ %% because it couldn't separate the messages between the different
+ %% synch sessions started by a nodeup.
+ MyTag = now(),
+ resend_pre_connect(Node),
+
+ %% multi
+ S#state.the_locker ! {nodeup, Node, S#state.known, MyTag, self()},
+
+ Pid = start_locker(Node, S#state.known, MyTag, self(), S#state.the_locker),
+ Ls = S#state.lockers,
+ InitC = {init_connect, {?vsn, MyTag}, node(), {locker, Pid, S#state.known}},
+ ?P2({putting, MyTag}),
+ put({sync_tag_my, Node}, MyTag),
+ gen_server:cast({global_name_server, Node}, InitC),
+ {noreply, S#state{lockers = [{Node, Pid} | Ls]}}
+ end;
+
+
+%% This message is only to test otp-2766 Global may be confused at bursty
+%% nodeup/nodedowns. It's a copy of the complex part of the handling of
+%% the 'nodeup' message.
+handle_info({test_vsn_tag_nodeup, Node}, S) when S#state.connect_all == true,
+ Node == node() ->
+ {noreply, S};
+handle_info({test_vsn_tag_nodeup, Node}, S) when S#state.connect_all == true ->
+ ?FORMAT("~p #### test_nodeup 1 ####### Node ~p~n",[node(), Node]),
+ MyTag = now(),
+ resend_pre_connect(Node),
+ S#state.the_locker ! {nodeup, Node, S#state.known, MyTag, self()},
+ Pid = start_locker(Node, S#state.known, MyTag, self(), S#state.the_locker),
+ Ls = S#state.lockers,
+ InitC = {init_connect, {?vsn, MyTag}, node(), {locker, Pid, S#state.known}},
+ put({sync_tag_my, Node}, MyTag),
+ gen_server:cast({global_name_server, Node}, InitC),
+ ?PRINT({lockers, node(), Ls}),
+ {noreply, S#state{lockers = [{Node, Pid} | Ls]}};
+
+
+handle_info({whereis, Name, From}, S) ->
+ do_whereis(Name, From),
+ {noreply, S};
+
+handle_info(known, S) ->
+ io:format(">>>> ~p~n",[S#state.known]),
+ {noreply, S};
+
+handle_info(_, S) ->
+ {noreply, S}.
+
+
+
+
+%%=======================================================================================
+%%=======================================================================================
+%%=============================== Internal Functions ====================================
+%%=======================================================================================
+%%=======================================================================================
+
+
+
+%%=======================================================================================
+%% Another node wants to synchronize its registered names with us.
+%% Start a locker process. Both nodes must have a lock before they are
+%% allowed to continue.
+%%=======================================================================================
+init_connect(Vsn, Node, InitMsg, HisTag, Lockers, S) ->
+ ?P2({init_connect, node(), Node}),
+ ?FORMAT("~p #### init_connect Vsn, Node, InitMsg ~p~n",[node(),{Vsn, Node, InitMsg}]),
+ %% It is always the responsibility of newer versions to understand
+ %% older versions of the protocol.
+ put({prot_vsn, Node}, Vsn),
+ put({sync_tag_his, Node}, HisTag),
+ if
+ Vsn =< 3 ->
+ case lists:keysearch(Node, 1, Lockers) of
+ {value, {_Node, MyLocker}} ->
+ %% We both have lockers; let them set the lock
+ case InitMsg of
+ {locker, HisLocker, HisKnown} -> %% current version
+ ?PRINT({init_connect1, node(), self(), Node,
+ MyLocker, HisLocker}),
+ MyLocker ! {his_locker, HisLocker, HisKnown};
+
+ {locker, _HisLocker, HisKnown, HisTheLocker} -> %% multi
+ ?PRINT({init_connect1, node(), self(), Node,
+ MyLocker, _HisLocker}),
+ S#state.the_locker ! {his_the_locker, HisTheLocker,
+ HisKnown, S#state.known}
+ end;
+ false ->
+ ?PRINT({init_connect11, node(), self(), Node}),
+ put({pre_connect, Node}, {Vsn, InitMsg, HisTag})
+ end;
+ true -> % Vsn > 3
+ ?P2(vsn4),
+ case lists:keysearch(Node, 1, Lockers) of
+ {value, {_Node, _MyLocker}} ->
+ %% We both have lockers; let them set the lock
+ case InitMsg of
+ {locker, HisLocker, HisKnown} -> %% current version
+ ?PRINT({init_connect1, node(), self(), Node,
+ _MyLocker, HisLocker}),
+ HisLocker ! {his_locker_new, S#state.the_locker,
+ {HisKnown, S#state.known}};
+
+ {locker, _HisLocker, HisKnown, HisTheLocker} -> %% multi
+ ?PRINT({init_connect1, node(), self(), Node,
+ _MyLocker, _HisLocker}),
+ S#state.the_locker ! {his_the_locker, HisTheLocker,
+ HisKnown, S#state.known}
+ end;
+ false ->
+ ?PRINT({init_connect11, node(), self(), Node}),
+ put({pre_connect, Node}, {Vsn, InitMsg, HisTag})
+ end
+ end.
+
+
+
+%%=======================================================================================
+%% In the simple case, we'll get lock_is_set before we get exchange,
+%% but we may get exchange before we get lock_is_set from our locker.
+%% If that's the case, we'll have to remember the exchange info, and
+%% handle it when we get the lock_is_set. We do this by using the
+%% process dictionary - when the lock_is_set msg is received, we store
+%% this info. When exchange is received, we can check the dictionary
+%% if the lock_is_set has been received. If not, we store info about
+%% the exchange instead. In the lock_is_set we must first check if
+%% exchange info is stored, in that case we take care of it.
+%%=======================================================================================
+lock_is_set(Node, Known) ->
+ ?FORMAT("~p #### lock_is_set ~p~n",[node(),{Node, Node, Known}]),
+ PVsn = get({prot_vsn, Node}),
+ case PVsn of
+ _ -> % 3 and higher
+ gen_server:cast({global_name_server, Node},
+ {exchange, node(), get_names(), get_names_ext(),
+ get({sync_tag_his, Node})})
+ end,
+ %% If both have the lock, continue with exchange
+ case get({wait_lock, Node}) of
+ {exchange, NameList, NameExtList} ->
+ %% vsn 2, 3
+ put({wait_lock, Node}, lock_is_set),
+ exchange(PVsn, Node, {NameList, NameExtList}, Known);
+ undefined ->
+ put({wait_lock, Node}, lock_is_set)
+ end.
+
+
+
+%%=======================================================================================
+%% exchange
+%%=======================================================================================
+%% Vsn 3 and higher of the protocol
+exchange(_Vsn, Node, {NameList, NameExtList}, Known) ->
+ ?FORMAT("~p #### 3 lock_is_set exchange ~p~n",[node(),{Node, NameList, NameExtList}]),
+ case erase({wait_lock, Node}) of
+ lock_is_set ->
+ {Ops, Resolved} = exchange_names(NameList, Node, [], []),
+ put({save_ops, Node}, Ops),
+ gen_server:cast({global_name_server, Node},
+ {resolved, node(), Resolved, Known,
+ Known, get_names_ext(), get({sync_tag_his, Node})});
+ undefined ->
+ put({wait_lock, Node}, {exchange, NameList, NameExtList})
+ end.
+
+
+
+
+
+resolved(Node, Resolved, {HisKnown, _HisKnown_v2}, Names_ext, S) ->
+ ?P2({resolved, node(), Node, S#state.known}),
+ ?FORMAT("~p #### 2 resolved ~p~n",[node(),{Node, Resolved, HisKnown, Names_ext}]),
+ erase({prot_vsn, Node}),
+ Ops = erase({save_ops, Node}) ++ Resolved,
+ Known = S#state.known,
+ Synced = S#state.synced,
+ NewNodes = [Node | HisKnown],
+ do_ops(Ops),
+ do_ops_ext(Ops,Names_ext),
+ gen_server:abcast(Known, global_name_server,
+ {new_nodes, node(), Ops, Names_ext, NewNodes, NewNodes}),
+ %% I am synced with Node, but not with HisKnown yet
+ lists:foreach(fun(Pid) -> Pid ! {synced, [Node]} end, S#state.syncers),
+ gen_server:abcast(HisKnown, global_name_server, {in_sync, node(), true}),
+ NewS = lists:foldl(fun(Node1, S1) -> cancel_locker(Node1, S1) end,
+ S,
+ NewNodes),
+ %% See (*) below... we're node b in that description
+ NewKnown = Known ++ (NewNodes -- Known),
+ NewS#state{known = NewKnown, synced = [Node | Synced]}.
+
+
+
+
+new_nodes(Ops, Names_ext, Nodes, S) ->
+ ?FORMAT("~p #### 2 new_nodes ~p~n",[node(),{Ops, Names_ext, Nodes}]),
+ do_ops(Ops),
+ do_ops_ext(Ops,Names_ext),
+ Known = S#state.known,
+ %% (*) This one requires some thought...
+ %% We're node a, other nodes b and c:
+ %% The problem is that {in_sync, a} may arrive before {resolved, [a]} to
+ %% b from c, leading to b sending {new_nodes, [a]} to us (node a).
+ %% Therefore, we make sure we never get duplicates in Known.
+ NewNodes = lists:delete(node(), Nodes -- Known),
+ gen_server:abcast(NewNodes, global_name_server, {in_sync, node(), true}),
+ S#state{known = Known ++ NewNodes}.
+
+
+
+
+
+do_whereis(Name, From) ->
+ case is_lock_set(global) of
+ false ->
+ gen_server:reply(From, where(Name));
+ true ->
+ send_again({whereis, Name, From})
+ end.
+
+terminate(_Reason, _S) ->
+ ets:delete(global_names),
+ ets:delete(global_names_ext),
+ ets:delete(global_locks).
+
+code_change(_OldVsn, S, _Extra) ->
+ {ok, S}.
+
+%% Resend init_connect to ourselves.
+resend_pre_connect(Node) ->
+ case erase({pre_connect, Node}) of
+% {Vsn, InitMsg, undef} ->
+% %% Vsn 1 & 2
+% ?PRINT({resend_pre_connect2, node(), self(), Node}),
+% gen_server:cast(self(), {init_connect, Vsn, Node, InitMsg});
+ {Vsn, InitMsg, HisTag} ->
+ %% Vsn 3
+ ?PRINT({resend_pre_connect3, node(), self(), Node}),
+ gen_server:cast(self(), {init_connect, {Vsn, HisTag}, Node, InitMsg});
+ _ ->
+ ?PRINT({resend_pre_connect0, node(), self(), Node}),
+ ok
+ end.
+
+ins_name(Name, Pid, Method) ->
+ case ets:lookup(global_names, Name) of
+ [{Name, Pid2, _}] ->
+ dounlink(Pid2);
+ [] ->
+ ok
+ end,
+ dolink(Pid),
+ ets:insert(global_names, {Name, Pid, Method}).
+
+ins_name_ext(Name, Pid, RegNode) ->
+ case ets:lookup(global_names_ext, Name) of
+ [{Name, Pid2, _}] ->
+ dounlink(Pid2);
+ [] ->
+ ok
+ end,
+ dolink_ext(Pid, RegNode),
+ ets:insert(global_names_ext, {Name, Pid, RegNode}).
+
+where(Name) ->
+ case ets:lookup(global_names, Name) of
+ [{_, Pid, _}] -> Pid;
+ [] -> undefined
+ end.
+
+handle_set_lock({ResourceId, LockRequesterId}, Pid) ->
+ case ets:lookup(global_locks, ResourceId) of
+ [{ResourceId, LockRequesterId, Pids}] ->
+ case lists:member(Pid, Pids) of
+ true ->
+ true;
+ false ->
+ dolink(Pid),
+ ets:insert(global_locks, {ResourceId, LockRequesterId, [Pid | Pids]}),
+ true
+ end;
+ [{ResourceId, _LockRequesterId2, _Pid2}] ->
+ case ResourceId of
+ global ->
+ ?P({before,
+ LockRequesterId,
+ _LockRequesterId2,
+ S#state.lockers}),
+ false;
+ _ ->
+ false
+ end;
+ [] ->
+ dolink(Pid),
+ ets:insert(global_locks, {ResourceId, LockRequesterId, [Pid]}),
+ true
+ end.
+
+is_lock_set(ResourceId) ->
+ case ets:lookup(global_locks, ResourceId) of
+ [_Lock] -> true;
+ [] -> false
+ end.
+
+handle_del_lock({ResourceId, LockRequesterId}, Pid) ->
+ case ets:lookup(global_locks, ResourceId) of
+ [{ResourceId, LockRequesterId, Pids}] when [Pid] == Pids ->
+ ets:delete(global_locks, ResourceId),
+ dounlink(Pid);
+ [{ResourceId, LockRequesterId, Pids}] ->
+ NewPids = lists:delete(Pid, Pids),
+ ets:insert(global_locks, {ResourceId, LockRequesterId, NewPids}),
+ dounlink(Pid);
+ _ -> ok
+ end.
+
+do_ops(Ops) ->
+ lists:foreach(fun({insert, Item}) -> ets:insert(global_names, Item);
+ ({delete, Name}) ->
+ case ets:lookup(global_names, Name) of
+ [{Name, Pid, _}] ->
+ ?P2({do_ops_delete, node(), Name, Pid, node(Pid)}),
+ ets:delete(global_names, Name),
+ dounlink(Pid);
+ [] ->
+ ok
+ end
+ end, Ops).
+
+%% If a new name, then it must be checked if it is an external name
+%% If delete a name it is always deleted from global_names_ext
+do_ops_ext(Ops, Names_ext) ->
+ lists:foreach(fun({insert, {Name, Pid, _Method}}) ->
+ case lists:keysearch(Name, 1, Names_ext) of
+ {value, {Name, Pid, RegNode}} ->
+ ets:insert(global_names_ext, {Name, Pid, RegNode});
+ _ ->
+ ok
+ end;
+ ({delete, Name}) ->
+ ets:delete(global_names_ext, Name)
+ end, Ops).
+
+%%-----------------------------------------------------------------
+%% A locker is a process spawned by global_name_server when a
+%% nodeup is received from a new node. Its purpose is to try to
+%% set a lock in our partition, i.e. on all nodes known to us.
+%% When the lock is set, it tells global about it, and keeps
+%% the lock set. global sends a cancel message to the locker when
+%% the partitions are connected.
+
+%% Versions: at version 2, the messages exchanged between the lockers
+%% include the known nodes (see OTP-3576). There is no way of knowing
+%% the version number of the other side's locker when sending a message
+%% to it, so we send both version 1 and 2, and flush the version 1 if
+%% we receive version 2.
+%%
+%% Due to a mistake, an intermediate version of the new locking protocol
+%% (using 3-tuples) went out in R7, which only understands itself. This patch
+%% to R7 handles all kinds, which means sending all, and flush the ones we
+%% don't want. (It will remain difficult to make a future version of the
+%% protocol communicate with this one.)
+%%
+%%-----------------------------------------------------------------
+%% (Version 2 in patched R7. No named version in R6 and older - let's call that
+%% version 1.)
+-define(locker_vsn, 2).
+
+%%% multi
+
+-record(multi, {known, others = []}).
+
+start_the_locker(Global) ->
+ spawn_link(?MODULE, init_the_locker, [Global]).
+
+%init_the_locker(Global) ->
+% ok;
+init_the_locker(Global) ->
+ process_flag(trap_exit, true), %needed?
+ loop_the_locker(Global, #multi{}),
+ erlang:error(locker_exited).
+
+remove_node(_Node, []) ->
+ [];
+remove_node(Node, [{Node, _HisTheLocker, _HisKnown, _MyTag} | Rest]) ->
+ Rest;
+remove_node(Node, [E | Rest]) ->
+ [E | remove_node(Node, Rest)].
+
+find_node_tag(_Node, []) ->
+ false;
+find_node_tag(Node, [{Node, _HisTheLocker, _HisKnown, MyTag} | _Rest]) ->
+ {true, MyTag};
+find_node_tag(Node, [_E | Rest]) ->
+ find_node_tag(Node, Rest).
+
+loop_the_locker(Global, S) ->
+ ?P2({others, node(), S#multi.others}),
+% Known = S#multi.known,
+ Timeout = case S#multi.others of
+ [] ->
+ infinity;
+ _ ->
+ 0
+ end,
+ receive
+% {nodeup, Node, Known, Tag, P} ->
+% ?P2({the_locker, nodeup, time(), node(), nodeup, Node, Tag}),
+% loop_the_locker(Global, S);
+ {his_the_locker, HisTheLocker, HisKnown, MyKnown} ->
+ ?P2({his_the_locker, time(), node(), HisTheLocker,
+ node(HisTheLocker)}),
+ receive
+ {nodeup, Node, _Known, MyTag, _P} when node(HisTheLocker) == Node ->
+ ?P2({the_locker, nodeup, node(), Node,
+ node(HisTheLocker), MyTag,
+ process_info(self(), messages)}),
+ Others = S#multi.others,
+ loop_the_locker(Global,
+ S#multi{known=MyKnown,
+ others=[{node(HisTheLocker), HisTheLocker, HisKnown, MyTag} | Others]});
+ {cancel, Node, _Tag} when node(HisTheLocker) == Node ->
+ loop_the_locker(Global, S)
+ after 60000 ->
+ ?P2({nodeupnevercame, node(), node(HisTheLocker)}),
+ error_logger:error_msg("global: nodeup never came ~w ~w~n",
+ [node(), node(HisTheLocker)]),
+ loop_the_locker(Global, S)
+ end;
+ {cancel, Node, undefined} ->
+ ?P2({the_locker, cancel1, undefined, node(), Node}),
+%% If we actually cancel something when a cancel message with the tag
+%% 'undefined' arrives, we may be acting on an old nodedown, to cancel
+%% a new nodeup, so we can't do that.
+% receive
+% {nodeup, Node, _Known, _MyTag, _P} ->
+% ?P2({the_locker, cancelnodeup1, node(), Node}),
+% ok
+% after 0 ->
+% ok
+% end,
+% Others = remove_node(Node, S#multi.others),
+% loop_the_locker(Global, S#multi{others = Others});
+ loop_the_locker(Global, S);
+ {cancel, Node, Tag} ->
+ ?P2({the_locker, cancel1, Tag, node(), Node}),
+ receive
+ {nodeup, Node, _Known, Tag, _P} ->
+ ?P2({the_locker, cancelnodeup2, node(), Node}),
+ ok
+ after 0 ->
+ ok
+ end,
+ Others = remove_node(Node, S#multi.others),
+ loop_the_locker(Global, S#multi{others = Others});
+ {lock_set, _Pid, false, _} ->
+ ?P2({the_locker, spurious, node(), node(_Pid)}),
+ loop_the_locker(Global, S);
+ {lock_set, Pid, true, HisKnown} ->
+ Node = node(Pid),
+ ?P2({the_locker, spontaneous, node(), Node}),
+
+ NewKnown = gen_server:call(global_name_server, get_known),
+
+ Others =
+ case find_node_tag(Node, S#multi.others) of
+ {true, MyTag} ->
+
+ BothsKnown = HisKnown -- (HisKnown -- NewKnown),
+ Known1 = if
+ node() < Node ->
+ [node() | NewKnown];
+ true ->
+ [node() | NewKnown] -- BothsKnown
+ end,
+
+ ?P2({lock1, node()}),
+ LockId = {global, self()},
+ IsLockSet = set_lock(LockId, Known1, 1),
+ Pid ! {lock_set, self(), IsLockSet, NewKnown},
+ ?P2({the_locker, spontaneous, node(), Node, IsLockSet}),
+ case IsLockSet of
+ true ->
+ gen_server:cast(global_name_server,
+ {lock_is_set, Node, MyTag}),
+ ?P1({lock_sync_done, time(), node(),
+ {Pid, node(Pid)}, self()}),
+ %% Wait for global to tell us to remove lock.
+ receive
+ {cancel, Node, _Tag} ->
+ %% All conflicts are resolved,
+ %% remove lock.
+ ?PRINT({node(), self(), locked1}),
+ del_lock(LockId, Known1);
+ {'EXIT', Pid, _} ->
+ ?PRINT({node(), self(), locked2}),
+ %% Other node died;
+ %% remove lock and ignore him.
+ del_lock(LockId, Known1),
+ link(Global)
+ end,
+ remove_node(Node, S#multi.others);
+ false ->
+ S#multi.others
+ end;
+ false ->
+ ?P2({the_locker, spontaneous, node(), Node, not_there}),
+ Pid ! {lock_set, self(), false, NewKnown},
+ S#multi.others
+ end,
+ loop_the_locker(Global, S#multi{others = Others});
+ Other when element(1, Other) /= nodeup ->
+ ?P2({the_locker, other_msg, Other}),
+ loop_the_locker(Global, S)
+ after Timeout ->
+ NewKnown = gen_server:call(global_name_server, get_known),
+ [{Node, HisTheLocker, HisKnown, MyTag} | Rest] = S#multi.others,
+ BothsKnown = HisKnown -- (HisKnown -- NewKnown),
+ Known1 = if
+ node() < Node ->
+ [node() | NewKnown];
+ true ->
+ [node() | NewKnown] -- BothsKnown
+ end,
+ ?P2({picking, node(), Node}),
+ case lists:member(Node, NewKnown) of
+ false ->
+ LockId = {global, self()},
+ ?P2({lock2, node()}),
+ IsLockSet = set_lock(LockId, Known1, 1),
+ Others =
+ case IsLockSet of
+ true ->
+ HisTheLocker ! {lock_set, self(),
+ IsLockSet, NewKnown},
+ %% OTP-4902
+ lock_set_loop(Global, S,
+ Node, MyTag, Rest,
+ Known1,
+ LockId);
+ false ->
+ ?P2({the_locker, not_locked, node(),
+ Node}),
+ S#multi.others
+ end,
+ loop_the_locker(Global, S#multi{known=NewKnown,
+ others = Others});
+ true ->
+ ?P2({is_known, node(), Node}),
+ loop_the_locker(Global, S#multi{known=NewKnown,
+ others = Rest})
+ end
+ end.
+
+lock_set_loop(Global, S, Node, MyTag, Rest, Known1, LockId) ->
+ receive
+ {lock_set, P, true, _} when node(P) == Node ->
+ ?P2({the_locker, both_set, node(), Node}),
+
+ %% do sync
+ gen_server:cast(global_name_server, {lock_is_set, Node, MyTag}),
+ ?P1({lock_sync_done, time(), node(), {Pid, node(Pid)}, self()}),
+
+ %% Wait for global to tell us to remove lock.
+ receive
+ {cancel, Node, _} ->
+ %% All conflicts are resolved, remove lock.
+ ?PRINT({node(), self(), locked1}),
+ del_lock(LockId, Known1);
+ {'EXIT', _Pid, _} ->
+ ?PRINT({node(), self(), locked2}),
+ %% Other node died; remove lock and ignore him.
+ del_lock(LockId, Known1),
+ link(Global)
+ end,
+ Rest;
+ {lock_set, P, false, _} when node(P) == Node ->
+ ?P2({the_locker, not_both_set, node(), Node}),
+ del_lock(LockId, Known1),
+ S#multi.others;
+ {cancel, Node, _} ->
+ ?P2({the_locker, cancel2, node(), Node}),
+ del_lock(LockId, Known1),
+ remove_node(Node, S#multi.others);
+ {'EXIT', _, _} ->
+ ?P2({the_locker, exit, node(), Node}),
+ del_lock(LockId, Known1),
+ S#multi.others
+
+ after
+ %% OTP-4902
+ %% A cyclic deadlock could occur in rare cases where three or
+ %% more nodes waited for a reply from each other.
+ %% Therefore, reject lock_set attempts in this state from
+ %% nodes < this node (its enough if at least one node in
+ %% the cycle rejects and thus breaks the deadlock)
+ 5000 ->
+ reject_lock_set(),
+ lock_set_loop(Global, S, Node, MyTag, Rest, Known1, LockId)
+ end.
+
+reject_lock_set() ->
+ receive
+ {lock_set, P, true, _} when node(P) < node() ->
+ P ! {lock_set, self(), false, []},
+ reject_lock_set()
+ after
+ 0 ->
+ true
+ end.
+
+start_locker(Node, Known, MyTag, Global, TheLocker) ->
+ %% No link here! The del_lock call would delete the link anyway.
+ %% global_name_server has control of these processes anyway...
+ %% When the locker process exits due to being sent the 'cancel' message
+ %% by the server, the server then removes it from its tables.
+ %% When the locker terminates due to other reasons, the server must
+ %% be told, so we make a link to it just before exiting.
+ spawn(?MODULE, init_locker, [Node, Known, MyTag, Global, TheLocker]).
+
+init_locker(Node, Known, MyTag, Global, TheLocker) ->
+ process_flag(trap_exit, true),
+ ?PRINT({init_locker, node(), self(), Node}),
+ ?P1({init_locker, time(), node(), self(), Node}),
+ receive
+ {his_locker, Pid, HisKnown} ->
+ ?PRINT({init_locker, node(), self(), his_locker, Node}),
+ link(Pid),
+ %% If two nodes in a group of nodes first disconnect
+ %% and then reconnect, this causes global to deadlock.
+ %% This because both of the reconnecting nodes
+ %% tries to set lock on the other nodes in the group.
+ %% This is solved by letting only one of the reconneting nodes set the lock.
+ BothsKnown = HisKnown -- (HisKnown -- Known),
+ ?P({loop_locker1, node(), {Pid, node(Pid)}}),
+ Res = loop_locker(Node, Pid, Known, 1, MyTag, BothsKnown, Global),
+ ?P({loop_locker2, node(), {Pid, node(Pid)}}),
+ Res;
+ {his_locker_new, HisTheLocker, {Known1, Known2}} ->
+ %% slide into the vsn 4 stuff
+ ?P2({his_locker_new, node()}),
+ HisTheLocker ! {his_the_locker, TheLocker, Known1, Known2},
+ exit(normal);
+ cancel ->
+ ?PRINT({init_locker, node(), self(), cancel, Node}),
+ exit(normal)
+ end.
+
+loop_locker(Node, Pid, Known0, Try, MyTag, BothsKnown, Global) ->
+ Known = if
+ node() < Node ->
+ [node() | Known0];
+ true ->
+ [node() | Known0] -- BothsKnown
+ end,
+
+ ?PRINT({locking, node(), self(), Known}),
+ LockId = {global, self()},
+ ?P2({lock3, node()}),
+ IsLockSet = set_lock(LockId, Known, 1),
+ ?P({loop_locker, IsLockSet,
+ node(), {Pid, node(Pid)}, self(), Try}),
+ ?P1({loop_locker, time(), IsLockSet,
+ node(), {Pid, node(Pid)}, self(), Try}),
+ ?PRINT({locking1, node(), self(), Known, IsLockSet}),
+ %% Tell other node that we managed to get the lock.
+ Pid ! {lock, ?locker_vsn, IsLockSet, Known},
+ Pid ! {lock, IsLockSet, Known},
+ Pid ! {lock, IsLockSet},
+ %% Wait for other node's result.
+ receive
+ %% R7 patched and later
+ {lock, _LockerVsn, true, _} when IsLockSet == true ->
+ receive
+ {lock, _} ->
+ ok
+ end,
+ receive
+ {lock, _, _} ->
+ ok
+ end,
+ ?PRINT({node(), self(), locked}),
+ %% Now we got the lock in both partitions. Tell
+ %% global, and let him resolve name conflict.
+ ?P1({lock_sync, time(), node(), {Pid, node(Pid)}, self()}),
+ gen_server:cast(global_name_server, {lock_is_set, Node, MyTag}),
+ ?P1({lock_sync_done, time(), node(), {Pid, node(Pid)}, self()}),
+ %% Wait for global to tell us to remove lock.
+ receive
+ cancel ->
+ %% All conflicts are resolved, remove lock.
+ ?PRINT({node(), self(), locked1}),
+ del_lock(LockId, Known);
+ {'EXIT', Pid, _} ->
+ ?PRINT({node(), self(), locked2}),
+ %% Other node died; remove lock and ignore him.
+ del_lock(LockId, Known),
+ link(Global)
+ end;
+ {lock, _LockerVsn, _, HisKnown} ->
+ receive
+ {lock, _} ->
+ ok
+ end,
+ receive
+ {lock, _, _} ->
+ ok
+ end,
+ %% Some of us failed to get the lock; try again
+ ?PRINT({node(), self(), locked0}),
+ d_lock(IsLockSet, LockId, Known),
+ try_again_locker(Node, Pid, Try, MyTag, HisKnown, Global);
+ %% R7 unpatched
+ {lock, true, _} when IsLockSet == true ->
+ ?PRINT({node(), self(), locked}),
+ %% Now we got the lock in both partitions. Tell
+ %% global, and let him resolve name conflict.
+ gen_server:cast(global_name_server, {lock_is_set, Node, MyTag}),
+ %% Wait for global to tell us to remove lock.
+ receive
+ cancel ->
+ %% All conflicts are resolved, remove lock.
+ ?PRINT({node(), self(), locked1}),
+ del_lock(LockId, Known);
+ {'EXIT', Pid, _} ->
+ ?PRINT({node(), self(), locked2}),
+ %% Other node died; remove lock and ignore him.
+ del_lock(LockId, Known),
+ link(Global)
+ end;
+ {lock, _, HisKnown} ->
+ %% Some of us failed to get the lock; try again
+ ?PRINT({node(), self(), locked0}),
+ d_lock(IsLockSet, LockId, Known),
+ try_again_locker(Node, Pid, Try, MyTag, HisKnown, Global);
+ %% R6 and earlier
+ {lock, true} when IsLockSet == true ->
+ ?PRINT({node(), self(), locked}),
+ %% Now we got the lock in both partitions. Tell
+ %% global, and let him resolve name conflict.
+ gen_server:cast(global_name_server, {lock_is_set, Node, MyTag}),
+ %% Wait for global to tell us to remove lock.
+ receive
+ cancel ->
+ %% All conflicts are resolved, remove lock.
+ ?PRINT({node(), self(), locked1}),
+ del_lock(LockId, Known);
+ {'EXIT', Pid, _} ->
+ ?PRINT({node(), self(), locked2}),
+ %% Other node died; remove lock and ignore him.
+ del_lock(LockId, Known),
+ link(Global)
+ end;
+ {lock, _} ->
+ %% Some of us failed to get the lock; try again
+ ?PRINT({node(), self(), locked0}),
+ d_lock(IsLockSet, LockId, Known),
+ try_again_locker(Node, Pid, Try, MyTag, BothsKnown, Global);
+ {'EXIT', Pid, _} ->
+ %% Other node died; remove lock and ignore him.
+ ?PRINT({node(), self(), locked7}),
+ d_lock(IsLockSet, LockId, Known),
+ link(Global);
+ cancel ->
+ ?PRINT({node(), self(), locked8}),
+ d_lock(IsLockSet, LockId, Known)
+ end.
+
+d_lock(true, LockId, Known) -> del_lock(LockId, Known);
+d_lock(false, _, _) -> ok.
+
+try_again_locker(Node, Pid, Try, MyTag, HisKnown, Global) ->
+ ?PRINT({try_again, node(), self(), Node, Pid, Known, Try, MyTag}),
+ ?P1({try_again, time(), node(), self(), Node, Pid, Known, Try, MyTag}),
+ random_sleep(Try),
+ ?P1({try_again2, time(), node(), self(), Node, Pid, Known, Try, MyTag}),
+ NewKnown = gen_server:call(global_name_server, get_known),
+ case lists:member(Node, NewKnown) of
+ false ->
+ BothsKnown1 = HisKnown -- (HisKnown -- NewKnown),
+ ?PRINT({node(), self(), Node, again, notknown}),
+ ?PRINT({bothknown, BothsKnown, BothsKnown1}),
+ loop_locker(Node, Pid, NewKnown, Try+1, MyTag,
+ BothsKnown1, Global);
+ true ->
+ ?PRINT({node(), self(), Node, again, known}),
+ link(Global),
+ %% Node is already handled, we are ready.
+ ok
+ end.
+
+cancel_locker(Node, S) ->
+ %% multi
+ ?P2({cancel, node(), Node, get({sync_tag_my, Node})}),
+ S#state.the_locker ! {cancel, Node, get({sync_tag_my, Node})},
+
+ Lockers = S#state.lockers,
+ case lists:keysearch(Node, 1, Lockers) of
+ {value, {_, Pid}} ->
+ Pid ! cancel,
+ ?PRINT({cancel, Node, lockers, node(), Lockers}),
+ S#state{lockers = lists:keydelete(Node, 1, Lockers)};
+ _ ->
+ S
+ end.
+
+%% A node sent us his names. When a name clash is found, the resolve
+%% function is called from the smaller node => all resolve funcs are called
+%% from the same partition.
+exchange_names([{Name, Pid, Method} |Tail], Node, Ops, Res) ->
+ case ets:lookup(global_names, Name) of
+ [{Name, Pid, _}] ->
+ exchange_names(Tail, Node, Ops, Res);
+ [{Name, Pid2, Method2}] when node() < Node ->
+ %% Name clash! Add the result of resolving to Res(olved).
+ %% We know that node(Pid) /= node(), so we don't
+ %% need to link/unlink to Pid.
+ Node2 = node(Pid2), %%&&&&&& check external node???
+ case rpc:call(Node2, ?MODULE, resolve_it,
+ [Method2, Name, Pid, Pid2]) of
+ Pid ->
+ dounlink(Pid2),
+ ets:insert(global_names, {Name, Pid, Method}),
+ Op = {insert, {Name, Pid, Method}},
+ exchange_names(Tail, Node, [Op | Ops], [Op | Res]);
+ Pid2 ->
+ Op = {insert, {Name, Pid2, Method2}},
+ exchange_names(Tail, Node, Ops, [Op | Res]);
+ none ->
+ dounlink(Pid2),
+ ?P2({unregister, node(), Name, Pid2, node(Pid2)}),
+ ets:delete(global_names, Name),
+ Op = {delete, Name},
+ exchange_names(Tail, Node, [Op | Ops], [Op | Res]);
+ {badrpc, Badrpc} ->
+ error_logger:info_msg("global: badrpc ~w received when "
+ "conflicting name ~w was found",
+ [Badrpc, Name]),
+ dounlink(Pid2),
+ ets:insert(global_names, {Name, Pid, Method}),
+ Op = {insert, {Name, Pid, Method}},
+ exchange_names(Tail, Node, [Op | Ops], [Op | Res]);
+ Else ->
+ error_logger:info_msg("global: Resolve method ~w for "
+ "conflicting name ~w returned ~w~n",
+ [Method, Name, Else]),
+ dounlink(Pid2),
+ ets:delete(global_names, Name),
+ Op = {delete, Name},
+ exchange_names(Tail, Node, [Op | Ops], [Op | Res])
+ end;
+ [{Name, _Pid2, _}] ->
+ %% The other node will solve the conflict.
+ exchange_names(Tail, Node, Ops, Res);
+ _ ->
+ %% Entirely new name.
+ ets:insert(global_names, {Name, Pid, Method}),
+ exchange_names(Tail, Node,
+ [{insert, {Name, Pid, Method}} | Ops], Res)
+ end;
+exchange_names([], _, Ops, Res) ->
+ {Ops, Res}.
+
+resolve_it(Method, Name, Pid1, Pid2) ->
+ catch Method(Name, Pid1, Pid2).
+
+minmax(P1,P2) ->
+ if node(P1) < node(P2) -> {P1, P2}; true -> {P2, P1} end.
+
+random_exit_name(Name, Pid, Pid2) ->
+ {Min, Max} = minmax(Pid, Pid2),
+ error_logger:info_msg("global: Name conflict terminating ~w~n",
+ [{Name, Max}]),
+ exit(Max, kill),
+ Min.
+
+random_notify_name(Name, Pid, Pid2) ->
+ {Min, Max} = minmax(Pid, Pid2),
+ Max ! {global_name_conflict, Name},
+ Min.
+
+notify_all_name(Name, Pid, Pid2) ->
+ Pid ! {global_name_conflict, Name, Pid2},
+ Pid2 ! {global_name_conflict, Name, Pid},
+ none.
+
+cnode(Name, Pid, Pid2) ->
+ {Min, Max} = minmax(Pid, Pid2),
+ error_logger:info_msg("global: Name conflict terminating ~w~n",
+ [{Name, Max}]),
+ Max ! {global_name_conflict, Name},
+ Min.
+
+%% Only link to pids on our own node
+dolink(Pid) when node(Pid) == node() ->
+ link(Pid);
+dolink(_) -> ok.
+
+%% Only link to pids on our own node
+dolink_ext(Pid, RegNode) when RegNode == node() -> link(Pid);
+dolink_ext(_, _) -> ok.
+
+dounlink(Pid) when node(Pid) == node() ->
+ case ets:match(global_names, {'_', Pid, '_'}) of
+ [] ->
+ case is_pid_used(Pid) of
+ false ->
+ unlink(Pid);
+ true -> ok
+ end;
+ _ -> ok
+ end;
+dounlink(_Pid) ->
+ ok.
+
+is_pid_used(Pid) ->
+ is_pid_used(ets:tab2list(global_locks), Pid).
+
+is_pid_used([], _Pid) ->
+ false;
+is_pid_used([{_ResourceId, _LockReqId, Pids} | Tail], Pid) ->
+ case lists:member(Pid, Pids) of
+ true ->
+ true;
+ false ->
+ is_pid_used(Tail, Pid)
+ end.
+
+
+
+%% check_exit/3 removes the Pid from affected tables.
+%% This function needs to abcast the thingie since only the local
+%% server is linked to the registered process (or the owner of the
+%% lock). All the other servers rely on the nodedown mechanism.
+check_exit(Deleter, Pid) ->
+ del_names(Deleter, Pid, ets:tab2list(global_names)),
+ del_locks(ets:tab2list(global_locks), Pid).
+
+del_names(Deleter, Pid, [{Name, Pid, _Method} | Tail]) ->
+ %% First, delete the Pid from the local ets; then send to other nodes
+ ets:delete(global_names, Name),
+ ets:delete(global_names_ext, Name),
+ dounlink(Pid),
+ Deleter ! {delete_name,self(),Name,Pid},
+ del_names(Deleter, Pid, Tail);
+del_names(Deleter, Pid, [_|T]) ->
+ del_names(Deleter, Pid, T);
+del_names(_Deleter, _Pid, []) -> done.
+
+del_locks([{ResourceId, LockReqId, Pids} | Tail], Pid) ->
+ case {lists:member(Pid, Pids), Pids} of
+ {true, [Pid]} ->
+ ets:delete(global_locks, ResourceId),
+ gen_server:abcast(nodes(), global_name_server,
+ {async_del_lock, ResourceId, Pid});
+ {true, _} ->
+ NewPids = lists:delete(Pid, Pids),
+ ets:insert(global_locks, {ResourceId, LockReqId, NewPids}),
+ gen_server:abcast(nodes(), global_name_server,
+ {async_del_lock, ResourceId, Pid});
+ _ ->
+ continue
+ end,
+ del_locks(Tail, Pid);
+del_locks([], _Pid) -> done.
+
+del_locks2([{ResourceId, LockReqId, Pids} | Tail], Pid) ->
+ case {lists:member(Pid, Pids), Pids} of
+ {true, [Pid]} ->
+ ets:delete(global_locks, ResourceId);
+ {true, _} ->
+ NewPids = lists:delete(Pid, Pids),
+ ets:insert(global_locks, {ResourceId, LockReqId, NewPids});
+ _ ->
+ continue
+ end,
+ del_locks2(Tail, Pid);
+del_locks2([], _Pid) ->
+ done.
+
+
+
+%% Unregister all Name/Pid pairs such that node(Pid) == Node
+%% and delete all locks where node(Pid) == Node
+do_node_down(Node) ->
+ do_node_down_names(Node, ets:tab2list(global_names)),
+ do_node_down_names_ext(Node, ets:tab2list(global_names_ext)),
+ do_node_down_locks(Node, ets:tab2list(global_locks)).
+
+do_node_down_names(Node, [{Name, Pid, _Method} | T]) when node(Pid) == Node ->
+ ets:delete(global_names, Name),
+ do_node_down_names(Node, T);
+do_node_down_names(Node, [_|T]) ->
+ do_node_down_names(Node, T);
+do_node_down_names(_, []) -> ok.
+
+%%remove all external names registered on the crashed node
+do_node_down_names_ext(Node, [{Name, _Pid, Node} | T]) ->
+ ets:delete(global_names, Name),
+ ets:delete(global_names_ext, Name),
+ do_node_down_names_ext(Node, T);
+do_node_down_names_ext(Node, [_|T]) ->
+ do_node_down_names_ext(Node, T);
+do_node_down_names_ext(_, []) -> ok.
+
+do_node_down_locks(Node, [{ResourceId, LockReqId, Pids} | T]) ->
+ case do_node_down_locks2(Pids, Node) of
+ [] ->
+ continue;
+ RemovePids ->
+ case Pids -- RemovePids of
+ [] ->
+ ets:delete(global_locks, ResourceId);
+ NewPids ->
+ ets:insert(global_locks, {ResourceId, LockReqId, NewPids})
+ end
+ end,
+ do_node_down_locks(Node, T);
+do_node_down_locks(Node, [_|T]) ->
+ do_node_down_locks(Node, T);
+do_node_down_locks(_, []) -> done.
+
+
+do_node_down_locks2(Pids, Node) ->
+ do_node_down_locks2(Pids, Node, []).
+
+do_node_down_locks2([], _Node, Res) ->
+ Res;
+do_node_down_locks2([Pid | Pids], Node, Res) when node(Pid) == Node ->
+ do_node_down_locks2(Pids, Node, [Pid | Res]);
+do_node_down_locks2([_ | Pids], Node, Res) ->
+ do_node_down_locks2(Pids, Node, Res).
+
+
+get_names() ->
+ ets:tab2list(global_names).
+
+get_names_ext() ->
+ ets:tab2list(global_names_ext).
+
+random_sleep(Times) ->
+ case (Times rem 10) of
+ 0 -> erase(random_seed);
+ _ -> ok
+ end,
+ case get(random_seed) of
+ undefined ->
+ {A1, A2, A3} = now(),
+ random:seed(A1, A2, A3 + erlang:phash(node(), 100000));
+ _ -> ok
+ end,
+ %% First time 1/4 seconds, then doubling each time up to 8 seconds max.
+ Tmax = if Times > 5 -> 8000;
+ true -> ((1 bsl Times) * 1000) div 8
+ end,
+ T = random:uniform(Tmax),
+ ?P({random_sleep, node(), self(), Times, T}),
+ receive after T -> ok end.
+
+dec(infinity) -> infinity;
+dec(N) -> N-1.
+
+send_again(Msg) ->
+ spawn_link(?MODULE, timer, [self(), Msg]).
+
+timer(Pid, Msg) ->
+ random_sleep(5),
+ Pid ! Msg.
+
+change_our_node_name(NewNode, S) ->
+ S#state{node_name = NewNode}.
+
+
+%%-----------------------------------------------------------------
+%% Each sync process corresponds to one call to sync. Each such
+%% process asks the global_name_server on all Nodes if it is in sync
+%% with Nodes. If not, that (other) node spawns a syncer process that
+%% waits for global to get in sync with all Nodes. When it is in
+%% sync, the syncer process tells the original sync process about it.
+%%-----------------------------------------------------------------
+start_sync(Nodes, From) ->
+ spawn_link(?MODULE, sync_init, [Nodes, From]).
+
+sync_init(Nodes, From) ->
+ lists:foreach(fun(Node) -> monitor_node(Node, true) end, Nodes),
+ sync_loop(Nodes, From).
+
+sync_loop([], From) ->
+ gen_server:reply(From, ok);
+sync_loop(Nodes, From) ->
+ receive
+ {nodedown, Node} ->
+ monitor_node(Node, false),
+ sync_loop(lists:delete(Node, Nodes), From);
+ {synced, SNodes} ->
+ lists:foreach(fun(N) -> monitor_node(N, false) end, SNodes),
+ sync_loop(Nodes -- SNodes, From)
+ end.
+
+
+%%%====================================================================================
+%%% Get the current global_groups definition
+%%%====================================================================================
+check_sync_nodes() ->
+ case get_own_nodes() of
+ {ok, all} ->
+ nodes();
+ {ok, NodesNG} ->
+ %% global_groups parameter is defined, we are not allowed to sync
+ %% with nodes not in our own global group.
+ (nodes() -- (nodes() -- NodesNG));
+ {error, Error} ->
+ {error, Error}
+ end.
+
+check_sync_nodes(SyncNodes) ->
+ case get_own_nodes() of
+ {ok, all} ->
+ SyncNodes;
+ {ok, NodesNG} ->
+ %% global_groups parameter is defined, we are not allowed to sync
+ %% with nodes not in our own global group.
+ OwnNodeGroup = (nodes() -- (nodes() -- NodesNG)),
+ IllegalSyncNodes = (SyncNodes -- [node() | OwnNodeGroup]),
+ case IllegalSyncNodes of
+ [] -> SyncNodes;
+ _ -> {error, {"Trying to sync nodes not defined in the own global group",
+ IllegalSyncNodes}}
+ end;
+ {error, Error} ->
+ {error, Error}
+ end.
+
+get_own_nodes() ->
+ case global_group:get_own_nodes_with_errors() of
+ {error, Error} ->
+ {error, {"global_groups definition error", Error}};
+ OkTup ->
+ OkTup
+ end.
+
+
+%%-----------------------------------------------------------------
+%% The deleter process is a satellite process to global_name_server
+%% that does background batch deleting of names when a process
+%% that had globally registered names dies. It is started by and
+%% linked to global_name_server.
+%%-----------------------------------------------------------------
+
+start_the_deleter(Global) ->
+ spawn_link(
+ fun () ->
+ loop_the_deleter(Global)
+ end).
+
+loop_the_deleter(Global) ->
+ Deletions = collect_deletions(Global, []),
+ trans({global, self()},
+ fun() ->
+ lists:map(
+ fun ({Name,Pid}) ->
+ ?P2({delete_name2, Name, Pid, nodes()}),
+ gen_server:abcast(nodes(), global_name_server,
+ {async_del_name, Name, Pid})
+ end, Deletions)
+ end,
+ nodes()),
+ loop_the_deleter(Global).
+
+collect_deletions(Global, Deletions) ->
+ receive
+ {delete_name,Global,Name,Pid} ->
+ ?P2({delete_name, node(), self(), Name, Pid, nodes()}),
+ collect_deletions(Global, [{Name,Pid}|Deletions]);
+ Other ->
+ error_logger:error_msg("The global_name_server deleter process "
+ "received an unexpected message:\n~p\n",
+ [Other]),
+ collect_deletions(Global, Deletions)
+ after case Deletions of
+ [] -> infinity;
+ _ -> 0
+ end ->
+ lists:reverse(Deletions)
+ end.
diff --git a/lib/dialyzer/test/options2_tests_SUITE.erl b/lib/dialyzer/test/options2_tests_SUITE.erl
deleted file mode 100644
index 43b5207744..0000000000
--- a/lib/dialyzer/test/options2_tests_SUITE.erl
+++ /dev/null
@@ -1,52 +0,0 @@
-%% ATTENTION!
-%% This is an automatically generated file. Do not edit.
-%% Use './remake' script to refresh it if needed.
-%% All Dialyzer options should be defined in dialyzer_options
-%% file.
-
--module(options2_tests_SUITE).
-
--include("ct.hrl").
--include("dialyzer_test_constants.hrl").
-
--export([suite/0, init_per_suite/0, init_per_suite/1,
- end_per_suite/1, all/0]).
--export([options2_tests_SUITE_consistency/1, kernel/1]).
-
-suite() ->
- [{timetrap, {minutes, 1}}].
-
-init_per_suite() ->
- [{timetrap, ?plt_timeout}].
-init_per_suite(Config) ->
- OutDir = ?config(priv_dir, Config),
- case dialyzer_common:check_plt(OutDir) of
- fail -> {skip, "Plt creation/check failed."};
- ok -> [{dialyzer_options, [{defines,[{vsn,4}]},{warnings,[no_return]}]}|Config]
- end.
-
-end_per_suite(_Config) ->
- ok.
-
-all() ->
- [options2_tests_SUITE_consistency,kernel].
-
-dialyze(Config, TestCase) ->
- Opts = ?config(dialyzer_options, Config),
- Dir = ?config(data_dir, Config),
- OutDir = ?config(priv_dir, Config),
- dialyzer_common:check(TestCase, Opts, Dir, OutDir).
-
-options2_tests_SUITE_consistency(Config) ->
- Dir = ?config(data_dir, Config),
- case dialyzer_common:new_tests(Dir, all()) of
- [] -> ok;
- New -> ct:fail({missing_tests,New})
- end.
-
-kernel(Config) ->
- case dialyze(Config, kernel) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
diff --git a/lib/dialyzer/test/options2_tests_SUITE_data/src/kernel/global.erl b/lib/dialyzer/test/options2_tests_SUITE_data/src/kernel/global.erl
deleted file mode 100644
index 1f0e01d074..0000000000
--- a/lib/dialyzer/test/options2_tests_SUITE_data/src/kernel/global.erl
+++ /dev/null
@@ -1,1999 +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: global.erl,v 1.4 2009/09/17 09:46:19 kostis Exp $
-%%
--module(global).
--behaviour(gen_server).
-
-%% A Global register that allows the global registration of pid's and
-%% name's, that dynamically keeps up to date with the entire network.
-%% global can operate in two modes; in a fully connected network, or
-%% in a non-fully connected network. In the latter case, the name
-%% registration mechanism won't work.
-%%
-
-%% External exports
--export([start/0, start_link/0, stop/0, sync/0, sync/1,
- safe_whereis_name/1, whereis_name/1, register_name/2, register_name/3,
- register_name_external/2, register_name_external/3, unregister_name_external/1,
- re_register_name/2, re_register_name/3,
- unregister_name/1, registered_names/0, send/2, node_disconnected/1,
- set_lock/1, set_lock/2, set_lock/3,
- del_lock/1, del_lock/2,
- trans/2, trans/3, trans/4,
- random_exit_name/3, random_notify_name/3, notify_all_name/3, cnode/3]).
-
-%% Internal exports
--export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
- code_change/3, timer/2, sync_init/2, init_locker/5, resolve_it/4,
- init_the_locker/1]).
-
--export([info/0]).
-
-
-%-define(PRINT(X), erlang:display(X)).
--define(PRINT(X), true).
-
-%-define(P2(X), erlang:display(X)).
-%-define(P2(X), erlang:display({cs(),X})).
--define(P2(X), true).
-
-%-define(P1(X), erlang:display(X)).
--define(P1(X), true).
-
-%-define(P(X), erlang:display(X)).
--define(P(X), true).
-
-%-define(FORMAT(S, A), format(S, A)).
--define(FORMAT(S, A), ok).
-
-%%% In certain places in the server, calling io:format hangs everything,
-%%% so we'd better use erlang:display/1.
-% format(S, A) ->
-% erlang:display({format, cs(), S, A}),
-% % io:format(S, A),
-% ok.
-
-% cs() ->
-% {Big, Small, Tiny} = now(),
-% (Small rem 100) * 100 + (Tiny div 10000).
-
-%% Some notes on the internal structure:
-%% One invariant is that the list of locker processes is keyed; i.e.,
-%% there is only one process per neighboring node.
-%% When an item has been stored in the process dictionary, it is not
-%% necessarily cleared when not in use anymore. In other words, it's
-%% not an error if there is already an item there when one is to be
-%% stored.
-
-
-%% This is the protocol version
-%% Vsn 1 is the original protocol.
-%% Vsn 2 is enhanced with code to take care of registration of names from
-%% non erlang nodes, e.g. c-nodes.
-%% Vsn 3 is enhanced with a tag in the synch messages to distinguish
-%% different synch sessions from each other, see OTP-2766.
-%% Note: This requires also that the ticket OTP-2928 is fixed on the nodes
-%% running vsn 1 or 2; if such nodes will coexist with vsn 3 nodes.
-%% Vsn 4 uses a single, permanent, locker process, but works like vsn 3
-%% when communicating with vsn 3 nodes.
-
-%% -define(vsn, 4). %% Now given in options
-
-%%-----------------------------------------------------------------
-%% connect_all = boolean() - true if we are supposed to set up a
-%% fully connected net
-%% known = [Node] - all nodes known to us
-%% synced = [Node] - all nodes that have the same names as us
-%% lockers = [{Node, MyLockerPid}] - the pid of the locker
-%% process for each Node
-%% syncers = [pid()] - all current syncers processes
-%% node_name = atom() - our node name (can change if distribution
-%% is started/stopped dynamically)
-%%
-%% In addition to these, we keep info about messages arrived in
-%% the process dictionary:
-%% {pre_connect, Node} = {Vsn, InitMsg} - init_connect msgs that
-%% arrived before nodeup
-%% {wait_lock, Node} = {exchange, NameList} | lock_is_set
-%% - see comment below (handle_cast)
-%% {save_ops, Node} = [operation()] - save the ops between
-%% exchange and resolved
-%% {prot_vsn, Node} = Vsn - the exchange protocol version
-%% {sync_tag_my, Node} = My tag, used at synchronization with Node
-%% {sync_tag_his, Node} = The Node's tag, used at synchronization
-%%-----------------------------------------------------------------
--record(state, {connect_all, known = [], synced = [],
- lockers = [], syncers = [], node_name = node(),
- the_locker, the_deleter}).
-
-start() -> gen_server:start({local, global_name_server}, global, [], []).
-start_link() -> gen_server:start_link({local, global_name_server},global,[],[]).
-stop() -> gen_server:call(global_name_server, stop, infinity).
-
-sync() ->
- case check_sync_nodes() of
- {error, Error} ->
- {error, Error};
- SyncNodes ->
- gen_server:call(global_name_server, {sync, SyncNodes}, infinity)
- end.
-sync(Nodes) ->
- case check_sync_nodes(Nodes) of
- {error, Error} ->
- {error, Error};
- SyncNodes ->
- gen_server:call(global_name_server, {sync, SyncNodes}, infinity)
- end.
-
-
-send(Name, Msg) ->
- case whereis_name(Name) of
- Pid when pid(Pid) ->
- Pid ! Msg,
- Pid;
- undefined ->
- exit({badarg, {Name, Msg}})
- end.
-
-%% See OTP-3737. (safe_whereis_name/1 is in fact not used anywhere in OTP.)
-whereis_name(Name) ->
- where(Name).
-
-safe_whereis_name(Name) ->
- gen_server:call(global_name_server, {whereis, Name}, infinity).
-
-
-node_disconnected(Node) ->
- global_name_server ! {nodedown, Node}.
-
-
-%%-----------------------------------------------------------------
-%% Method = function(Name, Pid1, Pid2) -> Pid | Pid2 | none
-%% Method is called if a name conflict is detected when two nodes
-%% are connecting to each other. It is supposed to return one of
-%% the Pids or 'none'. If a pid is returned, that pid is
-%% registered as Name on all nodes. If 'none' is returned, the
-%% Name is unregistered on all nodes. If anything else is returned,
-%% the Name is unregistered as well.
-%% Method is called once at one of the nodes where the processes reside
-%% only. If different Methods are used for the same name, it is
-%% undefined which one of them is used.
-%% Method is blocking, i.e. when it is called, no calls to whereis/
-%% send is let through until it has returned.
-%%-----------------------------------------------------------------
-register_name(Name, Pid) when pid(Pid) ->
- register_name(Name, Pid, {global, random_exit_name}).
-register_name(Name, Pid, Method) when pid(Pid) ->
- trans_all_known(fun(Nodes) ->
- case where(Name) of
- undefined ->
- gen_server:multi_call(Nodes,
- global_name_server,
- {register, Name, Pid, Method}),
- yes;
- _Pid -> no
- end
- end).
-
-unregister_name(Name) ->
- case where(Name) of
- undefined ->
- ok;
- _ ->
- trans_all_known(fun(Nodes) ->
- gen_server:multi_call(Nodes,
- global_name_server,
- {unregister, Name}),
- ok
- end)
- end.
-
-re_register_name(Name, Pid) when pid(Pid) ->
- re_register_name(Name, Pid, {global, random_exit_name}).
-re_register_name(Name, Pid, Method) when pid(Pid) ->
- trans_all_known(fun(Nodes) ->
- gen_server:multi_call(Nodes,
- global_name_server,
- {register, Name, Pid, Method}),
- yes
- end).
-
-%% Returns all globally registered names
-registered_names() -> lists:map(fun({Name, _Pid, _Method}) -> Name end,
- ets:tab2list(global_names)).
-
-%%-----------------------------------------------------------------
-%% An external node (i.e not an erlang node) (un)registers a name.
-%% If the registered Pid crashes the name is to be removed from global.
-%% If the external node crashes the name is to be removed from global.
-%% If the erlang node which registers the name crashes the name is also to be
-%% removed, because the registered process is not supervised any more,
-%% (i.e there is no link to the registered Pid).
-%%-----------------------------------------------------------------
-register_name_external(Name, Pid) when pid(Pid) ->
- register_name_external(Name, Pid, {global, random_exit_name}).
-register_name_external(Name, Pid, Method) when pid(Pid) ->
- trans_all_known(fun(Nodes) ->
- case where(Name) of
- undefined ->
- gen_server:multi_call(Nodes,
- global_name_server,
- {register, Name, Pid, Method}),
- gen_server:multi_call(Nodes,
- global_name_server,
- {register_ext, Name, Pid, node()}),
- yes;
- _Pid -> no
- end
- end).
-
-
-
-
-unregister_name_external(Name) ->
- case where(Name) of
- undefined ->
- ok;
- _ ->
- trans_all_known(fun(Nodes) ->
- gen_server:multi_call(Nodes,
- global_name_server,
- {unregister, Name}),
- gen_server:multi_call(Nodes,
- global_name_server,
- {unregister_ext, Name}),
- ok
- end)
- end.
-
-
-
-
-
-%%-----------------------------------------------------------------
-%% Args: Id = id()
-%% Nodes = [node()]
-%% id() = {ResourceId, LockRequesterId}
-%% Retries = infinity | int() > 0
-%% Purpose: Sets a lock on the specified nodes (or all nodes if
-%% none are specified) on ResourceId for LockRequesterId. If there
-%% already exists a lock on ResourceId for another owner
-%% than LockRequesterId, false is returned, otherwise true.
-%% Returns: boolean()
-%%-----------------------------------------------------------------
-set_lock(Id) ->
- set_lock(Id, [node() | nodes()], infinity, 1).
-set_lock(Id, Nodes) ->
- set_lock(Id, Nodes, infinity, 1).
-set_lock(Id, Nodes, Retries) when Retries > 0 ->
- set_lock(Id, Nodes, Retries, 1);
-set_lock(Id, Nodes, infinity) ->
- set_lock(Id, Nodes, infinity, 1).
-set_lock(_Id, _Nodes, 0, _) -> false;
-set_lock({ResourceId, LockRequesterId}, Nodes, Retries, Times) ->
- Id = {ResourceId, LockRequesterId},
- Msg = {set_lock, Id},
- {Replies, _} =
- gen_server:multi_call(Nodes, global_name_server, Msg),
- ?P2({set_lock, node(), self(), {ResourceId, LockRequesterId},
- Nodes, Retries, Times, Replies, catch erlang:error(kaka)}),
- ?P({set_lock, node(), ResourceId,
- {LockRequesterId, node(LockRequesterId)}}),
- case check_replies(Replies, Id, Nodes) of
- true -> ?P({set_lock_true, node(), ResourceId}),
- true;
- false ->
- random_sleep(Times),
- set_lock(Id, Nodes, dec(Retries), Times+1);
- N when integer(N) ->
- ?P({sleeping, N}),
- timer:sleep(N*500),
- set_lock(Id, Nodes, Retries, Times);
- Pid when pid(Pid) ->
- ?P({waiting_for, Pid}),
- Ref = erlang:monitor(process, Pid),
- receive
- {'DOWN', Ref, process, Pid, _Reason} ->
- ?P({waited_for, Pid, _Reason}),
- set_lock(Id, Nodes, Retries, Times)
- end
- end.
-
-check_replies([{_Node, true} | T], Id, Nodes) ->
- check_replies(T, Id, Nodes);
-check_replies([{_Node, Status} | _T], Id, Nodes) ->
- gen_server:multi_call(Nodes, global_name_server, {del_lock, Id}),
- Status;
-check_replies([], _Id, _Nodes) ->
- true.
-
-del_lock(Id) ->
- del_lock(Id, [node() | nodes()]).
-del_lock({ResourceId, LockRequesterId}, Nodes) ->
- Id = {ResourceId, LockRequesterId},
- ?P2({del_lock, node(), self(), ResourceId, LockRequesterId, Nodes}),
- gen_server:multi_call(Nodes, global_name_server, {del_lock, Id}),
- true.
-
-%%-----------------------------------------------------------------
-%% Args: Id = id()
-%% Fun = fun() | {M,F}
-%% Nodes = [node()]
-%% Retries = infinity | int() > 0
-%% Purpose: Sets a lock on Id (as set_lock), and evaluates
-%% Res = Fun() on success.
-%% Returns: Res | aborted (note, if Retries is infinity, the
-%% transaction won't abort)
-%%-----------------------------------------------------------------
-trans(Id, Fun) -> trans(Id, Fun, [node() | nodes()], infinity).
-trans(Id, Fun, Nodes) -> trans(Id, Fun, Nodes, infinity).
-trans(_Id, _Fun, _Nodes, 0) -> aborted;
-trans(Id, Fun, Nodes, Retries) ->
- case set_lock(Id, Nodes, Retries) of
- true ->
- case catch Fun() of
- {'EXIT', R} ->
- del_lock(Id, Nodes),
- exit(R);
- Res ->
- del_lock(Id, Nodes),
- Res
- end;
- false ->
- aborted
- end.
-
-%%% Similar to trans(Id, Fun), but always uses global's own lock,
-%%% on all nodes known to global, making sure that no new nodes have
-%%% become known while we got the list of known nodes.
-trans_all_known(F) ->
- Id = {global, self()},
- Nodes = [node() | gen_server:call(global_name_server, get_known)],
- case set_lock(Id, Nodes) of
- true ->
- Nodes2 = [node() | gen_server:call(global_name_server, get_known)],
- case Nodes2 -- Nodes of
- [] ->
- case catch F(Nodes2) of
- {'EXIT', R} ->
- del_lock(Id, Nodes2),
- exit(R);
- Res ->
- del_lock(Id, Nodes2),
- Res
- end;
- _ ->
- del_lock(Id, Nodes),
- trans_all_known(F)
- end;
- false ->
- aborted
- end.
-
-info() ->
- gen_server:call(global_name_server, info).
-
-%%%-----------------------------------------------------------------
-%%% Call-back functions from gen_server
-%%%-----------------------------------------------------------------
-init([]) ->
- process_flag(trap_exit, true),
- ets:new(global_locks, [set, named_table, protected]),
- ets:new(global_names, [set, named_table, protected]),
- ets:new(global_names_ext, [set, named_table, protected]),
-
- %% multi
- S = #state{the_locker = start_the_locker(self()),
- the_deleter = start_the_deleter(self())},
-
- case init:get_argument(connect_all) of
- {ok, [["false"]]} ->
- {ok, S#state{connect_all = false}};
- _ ->
- {ok, S#state{connect_all = true}}
- end.
-
-%%-----------------------------------------------------------------
-%% Connection algorithm
-%% ====================
-%% This alg solves the problem with partitioned nets as well.
-%%
-%% The main idea in the alg is that when two nodes connect, they
-%% try to set a lock in their own partition (i.e. all nodes already
-%% known to them). When the lock is set in each partition, these
-%% two nodes send each other a list with all registered names in
-%% resp partition(*). If no conflict is found, the name tables are
-%% just updated. If a conflict is found, a resolve function is
-%% called once for each conflict. The result of the resolving
-%% is sent to the other node. When the names are exchanged, all
-%% other nodes in each partition are informed of the other nodes,
-%% and they ping each other to form a fully connected net.
-%%
-%% Here's the flow:
-%% Suppose nodes A and B connect, and C is connected to A.
-%%
-%% Node A
-%% ------
-%% << {nodeup, B}
-%% [spawn locker]
-%% B ! {init_connect, MyLocker}
-%% << {init_connect, MyLocker}
-%% [The lockers try to set the lock]
-%% << {lock_is_set, B}
-%% [Now, lock is set in both partitions]
-%% B ! {exchange, Names}
-%% << {exchange, Names}
-%% [solve conflict]
-%% B ! {resolved, Resolved}
-%% << {resolved, Resolved}
-%% C ! {new_nodes, Resolved, [B]}
-%%
-%% Node C
-%% ------
-%% << {new_nodes, ResolvedOps, NewNodes}
-%% [insert Ops]
-%% ping(NewNodes)
-%% << {nodeup, B}
-%% <ignore this one>
-%%
-%% Several things can disturb this picture.
-%%
-%% First, the got_names message may arrive *before* the nodeup
-%% message, due to delay in net_kernel and an optimisation in the
-%% emulator. We handle this by keeping track of these messages in the
-%% pre_connect and lockers variables in our state.
-%%
-%% The most common situation is when a new node connects to an
-%% existing net. In this case there's no need to set the lock on
-%% all nodes in the net, as we know that there won't be any conflict.
-%% This is optimised by sending {first_contact, Node} instead of got_names.
-%% This implies that first_contact may arrive before nodeup as well.
-%%
-%% Of course we must handle that some node goes down during the
-%% connection.
-%%
-%% (*) When this information is being exchanged, no one is allowed
-%% to change the global register table. All calls to register etc
-%% are protected by a lock. If a registered process dies
-%% during this phase, the deregistration is done as soon as possible
-%% on each node (i.e. when the info about the process has arrived).
-%%-----------------------------------------------------------------
-%% Messages in the protocol
-%% ========================
-%% 1. Between connecting nodes (gen_server:casts)
-%% {init_connect, Vsn, Node, InitMsg}
-%% InitMsg = {locker, LockerPid}
-%% {exchange, Node, ListOfNames}
-%% {resolved, Node, Ops, Known}
-%% Known = list of nodes in Node's partition
-%% 2. Between lockers on connecting nodes (!s)
-%% {his_locker, Pid} (from our global)
-%% lockers link to each other
-%% {lock, Bool} loop until both lockers have lock = true,
-%% then send to global {lock_is_set, Node}
-%% 3. From connecting node to other nodes in the partition
-%% {new_nodes, Node, Ops, NewNodes}
-%% 4. sync protocol
-%% {in_sync, Node, IsKnown}
-%% - sent by each node to all new nodes
-%%-----------------------------------------------------------------
-
-handle_call({whereis, Name}, From, S) ->
- do_whereis(Name, From),
- {noreply, S};
-
-handle_call({register, Name, Pid, Method}, _From, S) ->
- ?P2({register, node(), Name}),
- ins_name(Name, Pid, Method),
- {reply, yes, S};
-
-handle_call({unregister, Name}, _From, S) ->
- case ets:lookup(global_names, Name) of
- [{_, Pid, _}] ->
- ?P2({unregister, node(), Name, Pid, node(Pid)}),
- ets:delete(global_names, Name),
- dounlink(Pid);
- _ -> ok
- end,
- {reply, ok, S};
-
-handle_call({register_ext, Name, Pid, RegNode}, _F, S) ->
- ins_name_ext(Name, Pid, RegNode),
- {reply, yes, S};
-
-handle_call({unregister_ext, Name}, _From, S) ->
- ets:delete(global_names_ext, Name),
- {reply, ok, S};
-
-
-handle_call({set_lock, Lock}, {Pid, _Tag}, S) ->
- Reply = handle_set_lock(Lock, Pid),
- {reply, Reply, S};
-
-handle_call({del_lock, Lock}, {Pid, _Tag}, S) ->
- handle_del_lock(Lock, Pid),
- {reply, true, S};
-
-handle_call(get_known, _From, S) ->
- {reply, S#state.known, S};
-
-%% R7 may call us?
-handle_call(get_known_v2, _From, S) ->
- {reply, S#state.known, S};
-
-handle_call({sync, Nodes}, From, S) ->
- %% If we have several global groups, this won't work, since we will
- %% do start_sync on a nonempty list of nodes even if the system
- %% is quiet.
- Pid = start_sync(lists:delete(node(), Nodes) -- S#state.synced, From),
- {noreply, S#state{syncers = [Pid | S#state.syncers]}};
-
-handle_call(get_protocol_version, _From, S) ->
- {reply, ?vsn, S};
-
-handle_call(get_names_ext, _From, S) ->
- {reply, get_names_ext(), S};
-
-handle_call(info, _From, S) ->
- {reply, S, S};
-
-handle_call(stop, _From, S) ->
- {stop, normal, stopped, S}.
-
-
-%%=======================================================================================
-%% init_connect
-%%
-%% Vsn 1 is the original protocol.
-%% Vsn 2 is enhanced with code to take care of registration of names from
-%% non erlang nodes, e.g. c-nodes.
-%% Vsn 3 is enhanced with a tag in the synch messages to distinguish
-%% different synch sessions from each other, see OTP-2766.
-%% Note: This requires also that the ticket OTP-2928 is fixed on the nodes
-%% running vsn 1 or 2; if such nodes will coexist with vsn 3 nodes.
-%%=======================================================================================
-handle_cast({init_connect, Vsn, Node, InitMsg}, S) ->
- ?FORMAT("~p #### init_connect Vsn ~p, Node ~p, InitMsg ~p~n",[node(), Vsn, Node, InitMsg]),
- case Vsn of
- %% It is always the responsibility of newer versions to understand
- %% older versions of the protocol.
- {HisVsn, HisTag} when HisVsn > ?vsn ->
- init_connect(?vsn, Node, InitMsg, HisTag, S#state.lockers, S);
- {HisVsn, HisTag} ->
- init_connect(HisVsn, Node, InitMsg, HisTag, S#state.lockers, S);
- %% To be future compatible
- Tuple when tuple(Tuple) ->
- List = tuple_to_list(Tuple),
- [_HisVsn, HisTag | _] = List,
- %% use own version handling if his is newer.
- init_connect(?vsn, Node, InitMsg, HisTag, S#state.lockers, S);
- _ when Vsn < 3 ->
- init_connect(Vsn, Node, InitMsg, undef, S#state.lockers, S);
- _ ->
- Txt = io_lib:format("Illegal global protocol version ~p Node: ~p",[Vsn, Node]),
- error_logger:info_report(lists:flatten(Txt))
- end,
- {noreply, S};
-
-%%=======================================================================================
-%% lock_is_set
-%%
-%% Ok, the lock is now set on both partitions. Send our names to other node.
-%%=======================================================================================
-handle_cast({lock_is_set, Node, MyTag}, S) ->
- ?FORMAT("~p #### lock_is_set Node ~p~n",[node(), Node]),
- Sync_tag_my = get({sync_tag_my, Node}),
- PVsn = get({prot_vsn, Node}),
- ?P2({lock_is_set, node(), Node, {MyTag, PVsn}, Sync_tag_my}),
- case {MyTag, PVsn} of
- {Sync_tag_my, undefined} ->
- %% Patch for otp-2728, the connection to the Node is flipping up and down
- %% the messages from the 'older' sync tries can disturb the 'new' sync try
- %% therefor all messages are discarded if the protocol vsn is not defined.
- Txt = io_lib:format("undefined global protocol version Node: ~p",[Node]),
- error_logger:info_report(lists:flatten(Txt)),
- {noreply, S};
- {Sync_tag_my, _} ->
- %% Check that the Node is still not known
- case lists:member(Node, S#state.known) of
- false ->
- ?P2({lset, node(), Node, false}),
- lock_is_set(Node, S#state.known),
- {noreply, S};
- true ->
- ?P2({lset, node(), Node, true}),
- erase({wait_lock, Node}),
- NewS = cancel_locker(Node, S),
- {noreply, NewS}
- end;
- _ ->
- ?P2({lset, illegal, node(), Node}),
- %% Illegal tag, delete the locker.
- erase({wait_lock, Node}),
- NewS = cancel_locker(Node, S),
- {noreply, NewS}
- end;
-
-%%=======================================================================================
-%% exchange
-%%
-%% Here the names are checked to detect name clashes.
-%%=======================================================================================
-%% Vsn 3 of the protocol
-handle_cast({exchange, Node, NameList, NameExtList, MyTag}, S) ->
- ?FORMAT("~p #### handle_cast 3 lock_is_set exchange ~p~n",
- [node(),{Node, NameList, NameExtList, MyTag}]),
- Sync_tag_my = get({sync_tag_my, Node}),
- PVsn = get({prot_vsn, Node}),
- case {MyTag, PVsn} of
- {Sync_tag_my, undefined} ->
- %% Patch for otp-2728, the connection to the Node is flipping up and down
- %% the messages from the 'older' sync tries can disturb the 'new' sync try
- %% therefor all messages are discarded if the protocol vsn is not defined.
- Txt = lists:flatten(io_lib:format(
- "undefined global protocol version Node: ~p",[Node])),
- error_logger:info_report(Txt),
- {noreply, S};
- {Sync_tag_my, _} ->
- exchange(PVsn, Node, {NameList, NameExtList}, S#state.known),
- {noreply, S};
- _ ->
- %% Illegal tag, delete the locker.
- erase({wait_lock, Node}),
- NewS = cancel_locker(Node, S),
- {noreply, NewS}
- end;
-
-
-
-%%=======================================================================================
-%% resolved
-%%
-%% Here the name clashes are resolved.
-%%=======================================================================================
-%% Vsn 3 of the protocol
-handle_cast({resolved, Node, Resolved, HisKnown, _HisKnown_v2, Names_ext, MyTag}, S) ->
- ?FORMAT("~p #### 2 resolved ~p~n",[node(),{Node, Resolved, HisKnown, Names_ext}]),
- Sync_tag_my = get({sync_tag_my, Node}),
- PVsn = get({prot_vsn, Node}),
- case {MyTag, PVsn} of
- {Sync_tag_my, undefined} ->
- %% Patch for otp-2728, the connection to the Node is flipping up and down
- %% the messages from the 'older' sync tries can disturb the 'new' sync try
- %% therefor all messages are discarded if the protocol vsn is not defined.
- Txt = lists:flatten(io_lib:format(
- "undefined global protocol version Node: ~p",[Node])),
- error_logger:info_report(Txt),
- {noreply, S};
- {Sync_tag_my, _} ->
- NewS = resolved(Node, Resolved, {HisKnown, HisKnown}, Names_ext, S),
- {noreply, NewS};
- _ ->
- %% Illegal tag, delete the locker.
- erase({wait_lock, Node}),
- NewS = cancel_locker(Node, S),
- {noreply, NewS}
- end;
-
-
-
-
-
-
-%%=======================================================================================
-%% new_nodes
-%%
-%% We get to know the other node's known nodes.
-%%=======================================================================================
-%% Vsn 2 and 3 of the protocol
-handle_cast({new_nodes, _Node, Ops, Names_ext, Nodes, _Nodes_v2}, S) ->
- ?P2({new_nodes, node(), Nodes}),
- ?FORMAT("~p #### 2 new_nodes ~p~n",[node(),{Ops, Names_ext, Nodes}]),
- NewS = new_nodes(Ops, Names_ext, Nodes, S),
- {noreply, NewS};
-
-
-
-
-%%=======================================================================================
-%% in_sync
-%%
-%% We are in sync with this node (from the other node's known world).
-%%=======================================================================================
-handle_cast({in_sync, Node, IsKnown}, S) ->
- ?FORMAT("~p #### in_sync ~p~n",[node(),{Node, IsKnown}]),
- lists:foreach(fun(Pid) -> Pid ! {synced, [Node]} end, S#state.syncers),
- %% moved up:
- NewS = cancel_locker(Node, S),
- erase({wait_lock, Node}),
- erase({pre_connect, Node}),
- erase({sync_tag_my, Node}),
- erase({sync_tag_his, Node}),
- NKnown = case lists:member(Node, Known = NewS#state.known) of
- false when IsKnown == true ->
- gen_server:cast({global_name_server, Node},
- {in_sync, node(), false}),
- [Node | Known];
- _ ->
- Known
- end,
- NSynced = case lists:member(Node, Synced = NewS#state.synced) of
- true -> Synced;
- false -> [Node | Synced]
- end,
- {noreply, NewS#state{known = NKnown, synced = NSynced}};
-
-
-
-
-%% Called when Pid on other node crashed
-handle_cast({async_del_name, Name, Pid}, S) ->
- ?P2({async_del_name, node(), Name, Pid, node(Pid)}),
- case ets:lookup(global_names, Name) of
- [{Name, Pid, _}] ->
- ets:delete(global_names, Name),
- dounlink(Pid);
- _ -> ok
- end,
- ets:delete(global_names_ext, Name),
- {noreply, S};
-
-handle_cast({async_del_lock, _ResourceId, Pid}, S) ->
- del_locks2(ets:tab2list(global_locks), Pid),
-% ets:match_delete(global_locks, {ResourceId, '_', Pid}),
- {noreply, S}.
-
-
-handle_info({'EXIT', Deleter, _Reason}=Exit, #state{the_deleter=Deleter}=S) ->
- {stop, {deleter_died,Exit}, S#state{the_deleter=undefined}};
-handle_info({'EXIT', Pid, _Reason}, #state{the_deleter=Deleter}=S)
- when pid(Pid) ->
- ?P2({global, exit, node(), Pid, node(Pid)}),
- check_exit(Deleter, Pid),
- Syncers = lists:delete(Pid, S#state.syncers),
- Lockers = lists:keydelete(Pid, 2, S#state.lockers),
- ?PRINT({exit, Pid, lockers, node(), S#state.lockers}),
- {noreply, S#state{syncers = Syncers, lockers = Lockers}};
-
-handle_info({nodedown, Node}, S) when Node == S#state.node_name ->
- %% Somebody stopped the distribution dynamically - change
- %% references to old node name (Node) to new node name ('nonode@nohost')
- {noreply, change_our_node_name(node(), S)};
-
-handle_info({nodedown, Node}, S) ->
- ?FORMAT("~p #### nodedown 1 ####### Node ~p",[node(),Node]),
- %% moved up:
- do_node_down(Node),
- #state{known = Known, synced = Syncs} = S,
- NewS = cancel_locker(Node, S),
-
- erase({wait_lock, Node}),
- erase({save_ops, Node}),
- erase({pre_connect, Node}),
- erase({prot_vsn, Node}),
- erase({sync_tag_my, Node}),
- erase({sync_tag_his, Node}),
- {noreply, NewS#state{known = lists:delete(Node, Known),
- synced = lists:delete(Node, Syncs)}};
-
-
-
-handle_info({nodeup, Node}, S) when Node == node() ->
- ?FORMAT("~p #### nodeup S ####### Node ~p~n",[node(), Node]),
- %% Somebody started the distribution dynamically - change
- %% references to old node name ('nonode@nohost') to Node.
- {noreply, change_our_node_name(Node, S)};
-
-handle_info({nodeup, Node}, S) when S#state.connect_all == true ->
- ?FORMAT("~p #### nodeup 1 ####### Node ~p",[node(),Node]),
- IsKnown = lists:member(Node, S#state.known) or
- %% This one is only for double nodeups (shouldn't occur!)
- lists:keymember(Node, 1, S#state.lockers),
- case IsKnown of
- true ->
- {noreply, S};
- false ->
- %% now() is used as a tag to separate different sycnh sessions
- %% from each others. Global could be confused at bursty nodeups
- %% because it couldn't separate the messages between the different
- %% synch sessions started by a nodeup.
- MyTag = now(),
- resend_pre_connect(Node),
-
- %% multi
- S#state.the_locker ! {nodeup, Node, S#state.known, MyTag, self()},
-
- Pid = start_locker(Node, S#state.known, MyTag, self(), S#state.the_locker),
- Ls = S#state.lockers,
- InitC = {init_connect, {?vsn, MyTag}, node(), {locker, Pid, S#state.known}},
- ?P2({putting, MyTag}),
- put({sync_tag_my, Node}, MyTag),
- gen_server:cast({global_name_server, Node}, InitC),
- {noreply, S#state{lockers = [{Node, Pid} | Ls]}}
- end;
-
-
-%% This message is only to test otp-2766 Global may be confused at bursty
-%% nodeup/nodedowns. It's a copy of the complex part of the handling of
-%% the 'nodeup' message.
-handle_info({test_vsn_tag_nodeup, Node}, S) when S#state.connect_all == true,
- Node == node() ->
- {noreply, S};
-handle_info({test_vsn_tag_nodeup, Node}, S) when S#state.connect_all == true ->
- ?FORMAT("~p #### test_nodeup 1 ####### Node ~p~n",[node(), Node]),
- MyTag = now(),
- resend_pre_connect(Node),
- S#state.the_locker ! {nodeup, Node, S#state.known, MyTag, self()},
- Pid = start_locker(Node, S#state.known, MyTag, self(), S#state.the_locker),
- Ls = S#state.lockers,
- InitC = {init_connect, {?vsn, MyTag}, node(), {locker, Pid, S#state.known}},
- put({sync_tag_my, Node}, MyTag),
- gen_server:cast({global_name_server, Node}, InitC),
- ?PRINT({lockers, node(), Ls}),
- {noreply, S#state{lockers = [{Node, Pid} | Ls]}};
-
-
-handle_info({whereis, Name, From}, S) ->
- do_whereis(Name, From),
- {noreply, S};
-
-handle_info(known, S) ->
- io:format(">>>> ~p~n",[S#state.known]),
- {noreply, S};
-
-handle_info(_, S) ->
- {noreply, S}.
-
-
-
-
-%%=======================================================================================
-%%=======================================================================================
-%%=============================== Internal Functions ====================================
-%%=======================================================================================
-%%=======================================================================================
-
-
-
-%%=======================================================================================
-%% Another node wants to synchronize its registered names with us.
-%% Start a locker process. Both nodes must have a lock before they are
-%% allowed to continue.
-%%=======================================================================================
-init_connect(Vsn, Node, InitMsg, HisTag, Lockers, S) ->
- ?P2({init_connect, node(), Node}),
- ?FORMAT("~p #### init_connect Vsn, Node, InitMsg ~p~n",[node(),{Vsn, Node, InitMsg}]),
- %% It is always the responsibility of newer versions to understand
- %% older versions of the protocol.
- put({prot_vsn, Node}, Vsn),
- put({sync_tag_his, Node}, HisTag),
- if
- Vsn =< 3 ->
- case lists:keysearch(Node, 1, Lockers) of
- {value, {_Node, MyLocker}} ->
- %% We both have lockers; let them set the lock
- case InitMsg of
- {locker, HisLocker, HisKnown} -> %% current version
- ?PRINT({init_connect1, node(), self(), Node,
- MyLocker, HisLocker}),
- MyLocker ! {his_locker, HisLocker, HisKnown};
-
- {locker, _HisLocker, HisKnown, HisTheLocker} -> %% multi
- ?PRINT({init_connect1, node(), self(), Node,
- MyLocker, _HisLocker}),
- S#state.the_locker ! {his_the_locker, HisTheLocker,
- HisKnown, S#state.known}
- end;
- false ->
- ?PRINT({init_connect11, node(), self(), Node}),
- put({pre_connect, Node}, {Vsn, InitMsg, HisTag})
- end;
- true -> % Vsn > 3
- ?P2(vsn4),
- case lists:keysearch(Node, 1, Lockers) of
- {value, {_Node, _MyLocker}} ->
- %% We both have lockers; let them set the lock
- case InitMsg of
- {locker, HisLocker, HisKnown} -> %% current version
- ?PRINT({init_connect1, node(), self(), Node,
- _MyLocker, HisLocker}),
- HisLocker ! {his_locker_new, S#state.the_locker,
- {HisKnown, S#state.known}};
-
- {locker, _HisLocker, HisKnown, HisTheLocker} -> %% multi
- ?PRINT({init_connect1, node(), self(), Node,
- _MyLocker, _HisLocker}),
- S#state.the_locker ! {his_the_locker, HisTheLocker,
- HisKnown, S#state.known}
- end;
- false ->
- ?PRINT({init_connect11, node(), self(), Node}),
- put({pre_connect, Node}, {Vsn, InitMsg, HisTag})
- end
- end.
-
-
-
-%%=======================================================================================
-%% In the simple case, we'll get lock_is_set before we get exchange,
-%% but we may get exchange before we get lock_is_set from our locker.
-%% If that's the case, we'll have to remember the exchange info, and
-%% handle it when we get the lock_is_set. We do this by using the
-%% process dictionary - when the lock_is_set msg is received, we store
-%% this info. When exchange is received, we can check the dictionary
-%% if the lock_is_set has been received. If not, we store info about
-%% the exchange instead. In the lock_is_set we must first check if
-%% exchange info is stored, in that case we take care of it.
-%%=======================================================================================
-lock_is_set(Node, Known) ->
- ?FORMAT("~p #### lock_is_set ~p~n",[node(),{Node, Node, Known}]),
- PVsn = get({prot_vsn, Node}),
- case PVsn of
- _ -> % 3 and higher
- gen_server:cast({global_name_server, Node},
- {exchange, node(), get_names(), get_names_ext(),
- get({sync_tag_his, Node})})
- end,
- %% If both have the lock, continue with exchange
- case get({wait_lock, Node}) of
- {exchange, NameList, NameExtList} ->
- %% vsn 2, 3
- put({wait_lock, Node}, lock_is_set),
- exchange(PVsn, Node, {NameList, NameExtList}, Known);
- undefined ->
- put({wait_lock, Node}, lock_is_set)
- end.
-
-
-
-%%=======================================================================================
-%% exchange
-%%=======================================================================================
-%% Vsn 3 and higher of the protocol
-exchange(_Vsn, Node, {NameList, NameExtList}, Known) ->
- ?FORMAT("~p #### 3 lock_is_set exchange ~p~n",[node(),{Node, NameList, NameExtList}]),
- case erase({wait_lock, Node}) of
- lock_is_set ->
- {Ops, Resolved} = exchange_names(NameList, Node, [], []),
- put({save_ops, Node}, Ops),
- gen_server:cast({global_name_server, Node},
- {resolved, node(), Resolved, Known,
- Known, get_names_ext(), get({sync_tag_his, Node})});
- undefined ->
- put({wait_lock, Node}, {exchange, NameList, NameExtList})
- end.
-
-
-
-
-
-resolved(Node, Resolved, {HisKnown, _HisKnown_v2}, Names_ext, S) ->
- ?P2({resolved, node(), Node, S#state.known}),
- ?FORMAT("~p #### 2 resolved ~p~n",[node(),{Node, Resolved, HisKnown, Names_ext}]),
- erase({prot_vsn, Node}),
- Ops = erase({save_ops, Node}) ++ Resolved,
- Known = S#state.known,
- Synced = S#state.synced,
- NewNodes = [Node | HisKnown],
- do_ops(Ops),
- do_ops_ext(Ops,Names_ext),
- gen_server:abcast(Known, global_name_server,
- {new_nodes, node(), Ops, Names_ext, NewNodes, NewNodes}),
- %% I am synced with Node, but not with HisKnown yet
- lists:foreach(fun(Pid) -> Pid ! {synced, [Node]} end, S#state.syncers),
- gen_server:abcast(HisKnown, global_name_server, {in_sync, node(), true}),
- NewS = lists:foldl(fun(Node1, S1) -> cancel_locker(Node1, S1) end,
- S,
- NewNodes),
- %% See (*) below... we're node b in that description
- NewKnown = Known ++ (NewNodes -- Known),
- NewS#state{known = NewKnown, synced = [Node | Synced]}.
-
-
-
-
-new_nodes(Ops, Names_ext, Nodes, S) ->
- ?FORMAT("~p #### 2 new_nodes ~p~n",[node(),{Ops, Names_ext, Nodes}]),
- do_ops(Ops),
- do_ops_ext(Ops,Names_ext),
- Known = S#state.known,
- %% (*) This one requires some thought...
- %% We're node a, other nodes b and c:
- %% The problem is that {in_sync, a} may arrive before {resolved, [a]} to
- %% b from c, leading to b sending {new_nodes, [a]} to us (node a).
- %% Therefore, we make sure we never get duplicates in Known.
- NewNodes = lists:delete(node(), Nodes -- Known),
- gen_server:abcast(NewNodes, global_name_server, {in_sync, node(), true}),
- S#state{known = Known ++ NewNodes}.
-
-
-
-
-
-do_whereis(Name, From) ->
- case is_lock_set(global) of
- false ->
- gen_server:reply(From, where(Name));
- true ->
- send_again({whereis, Name, From})
- end.
-
-terminate(_Reason, _S) ->
- ets:delete(global_names),
- ets:delete(global_names_ext),
- ets:delete(global_locks).
-
-code_change(_OldVsn, S, _Extra) ->
- {ok, S}.
-
-%% Resend init_connect to ourselves.
-resend_pre_connect(Node) ->
- case erase({pre_connect, Node}) of
-% {Vsn, InitMsg, undef} ->
-% %% Vsn 1 & 2
-% ?PRINT({resend_pre_connect2, node(), self(), Node}),
-% gen_server:cast(self(), {init_connect, Vsn, Node, InitMsg});
- {Vsn, InitMsg, HisTag} ->
- %% Vsn 3
- ?PRINT({resend_pre_connect3, node(), self(), Node}),
- gen_server:cast(self(), {init_connect, {Vsn, HisTag}, Node, InitMsg});
- _ ->
- ?PRINT({resend_pre_connect0, node(), self(), Node}),
- ok
- end.
-
-ins_name(Name, Pid, Method) ->
- case ets:lookup(global_names, Name) of
- [{Name, Pid2, _}] ->
- dounlink(Pid2);
- [] ->
- ok
- end,
- dolink(Pid),
- ets:insert(global_names, {Name, Pid, Method}).
-
-ins_name_ext(Name, Pid, RegNode) ->
- case ets:lookup(global_names_ext, Name) of
- [{Name, Pid2, _}] ->
- dounlink(Pid2);
- [] ->
- ok
- end,
- dolink_ext(Pid, RegNode),
- ets:insert(global_names_ext, {Name, Pid, RegNode}).
-
-where(Name) ->
- case ets:lookup(global_names, Name) of
- [{_, Pid, _}] -> Pid;
- [] -> undefined
- end.
-
-handle_set_lock({ResourceId, LockRequesterId}, Pid) ->
- case ets:lookup(global_locks, ResourceId) of
- [{ResourceId, LockRequesterId, Pids}] ->
- case lists:member(Pid, Pids) of
- true ->
- true;
- false ->
- dolink(Pid),
- ets:insert(global_locks, {ResourceId, LockRequesterId, [Pid | Pids]}),
- true
- end;
- [{ResourceId, _LockRequesterId2, _Pid2}] ->
- case ResourceId of
- global ->
- ?P({before,
- LockRequesterId,
- _LockRequesterId2,
- S#state.lockers}),
- false;
- _ ->
- false
- end;
- [] ->
- dolink(Pid),
- ets:insert(global_locks, {ResourceId, LockRequesterId, [Pid]}),
- true
- end.
-
-is_lock_set(ResourceId) ->
- case ets:lookup(global_locks, ResourceId) of
- [_Lock] -> true;
- [] -> false
- end.
-
-handle_del_lock({ResourceId, LockRequesterId}, Pid) ->
- case ets:lookup(global_locks, ResourceId) of
- [{ResourceId, LockRequesterId, Pids}] when [Pid] == Pids ->
- ets:delete(global_locks, ResourceId),
- dounlink(Pid);
- [{ResourceId, LockRequesterId, Pids}] ->
- NewPids = lists:delete(Pid, Pids),
- ets:insert(global_locks, {ResourceId, LockRequesterId, NewPids}),
- dounlink(Pid);
- _ -> ok
- end.
-
-do_ops(Ops) ->
- lists:foreach(fun({insert, Item}) -> ets:insert(global_names, Item);
- ({delete, Name}) ->
- case ets:lookup(global_names, Name) of
- [{Name, Pid, _}] ->
- ?P2({do_ops_delete, node(), Name, Pid, node(Pid)}),
- ets:delete(global_names, Name),
- dounlink(Pid);
- [] ->
- ok
- end
- end, Ops).
-
-%% If a new name, then it must be checked if it is an external name
-%% If delete a name it is always deleted from global_names_ext
-do_ops_ext(Ops, Names_ext) ->
- lists:foreach(fun({insert, {Name, Pid, _Method}}) ->
- case lists:keysearch(Name, 1, Names_ext) of
- {value, {Name, Pid, RegNode}} ->
- ets:insert(global_names_ext, {Name, Pid, RegNode});
- _ ->
- ok
- end;
- ({delete, Name}) ->
- ets:delete(global_names_ext, Name)
- end, Ops).
-
-%%-----------------------------------------------------------------
-%% A locker is a process spawned by global_name_server when a
-%% nodeup is received from a new node. Its purpose is to try to
-%% set a lock in our partition, i.e. on all nodes known to us.
-%% When the lock is set, it tells global about it, and keeps
-%% the lock set. global sends a cancel message to the locker when
-%% the partitions are connected.
-
-%% Versions: at version 2, the messages exchanged between the lockers
-%% include the known nodes (see OTP-3576). There is no way of knowing
-%% the version number of the other side's locker when sending a message
-%% to it, so we send both version 1 and 2, and flush the version 1 if
-%% we receive version 2.
-%%
-%% Due to a mistake, an intermediate version of the new locking protocol
-%% (using 3-tuples) went out in R7, which only understands itself. This patch
-%% to R7 handles all kinds, which means sending all, and flush the ones we
-%% don't want. (It will remain difficult to make a future version of the
-%% protocol communicate with this one.)
-%%
-%%-----------------------------------------------------------------
-%% (Version 2 in patched R7. No named version in R6 and older - let's call that
-%% version 1.)
--define(locker_vsn, 2).
-
-%%% multi
-
--record(multi, {known, others = []}).
-
-start_the_locker(Global) ->
- spawn_link(?MODULE, init_the_locker, [Global]).
-
-%init_the_locker(Global) ->
-% ok;
-init_the_locker(Global) ->
- process_flag(trap_exit, true), %needed?
- loop_the_locker(Global, #multi{}),
- erlang:error(locker_exited).
-
-remove_node(_Node, []) ->
- [];
-remove_node(Node, [{Node, _HisTheLocker, _HisKnown, _MyTag} | Rest]) ->
- Rest;
-remove_node(Node, [E | Rest]) ->
- [E | remove_node(Node, Rest)].
-
-find_node_tag(_Node, []) ->
- false;
-find_node_tag(Node, [{Node, _HisTheLocker, _HisKnown, MyTag} | _Rest]) ->
- {true, MyTag};
-find_node_tag(Node, [_E | Rest]) ->
- find_node_tag(Node, Rest).
-
-loop_the_locker(Global, S) ->
- ?P2({others, node(), S#multi.others}),
-% Known = S#multi.known,
- Timeout = case S#multi.others of
- [] ->
- infinity;
- _ ->
- 0
- end,
- receive
-% {nodeup, Node, Known, Tag, P} ->
-% ?P2({the_locker, nodeup, time(), node(), nodeup, Node, Tag}),
-% loop_the_locker(Global, S);
- {his_the_locker, HisTheLocker, HisKnown, MyKnown} ->
- ?P2({his_the_locker, time(), node(), HisTheLocker,
- node(HisTheLocker)}),
- receive
- {nodeup, Node, _Known, MyTag, _P} when node(HisTheLocker) == Node ->
- ?P2({the_locker, nodeup, node(), Node,
- node(HisTheLocker), MyTag,
- process_info(self(), messages)}),
- Others = S#multi.others,
- loop_the_locker(Global,
- S#multi{known=MyKnown,
- others=[{node(HisTheLocker), HisTheLocker, HisKnown, MyTag} | Others]});
- {cancel, Node, _Tag} when node(HisTheLocker) == Node ->
- loop_the_locker(Global, S)
- after 60000 ->
- ?P2({nodeupnevercame, node(), node(HisTheLocker)}),
- error_logger:error_msg("global: nodeup never came ~w ~w~n",
- [node(), node(HisTheLocker)]),
- loop_the_locker(Global, S)
- end;
- {cancel, Node, undefined} ->
- ?P2({the_locker, cancel1, undefined, node(), Node}),
-%% If we actually cancel something when a cancel message with the tag
-%% 'undefined' arrives, we may be acting on an old nodedown, to cancel
-%% a new nodeup, so we can't do that.
-% receive
-% {nodeup, Node, _Known, _MyTag, _P} ->
-% ?P2({the_locker, cancelnodeup1, node(), Node}),
-% ok
-% after 0 ->
-% ok
-% end,
-% Others = remove_node(Node, S#multi.others),
-% loop_the_locker(Global, S#multi{others = Others});
- loop_the_locker(Global, S);
- {cancel, Node, Tag} ->
- ?P2({the_locker, cancel1, Tag, node(), Node}),
- receive
- {nodeup, Node, _Known, Tag, _P} ->
- ?P2({the_locker, cancelnodeup2, node(), Node}),
- ok
- after 0 ->
- ok
- end,
- Others = remove_node(Node, S#multi.others),
- loop_the_locker(Global, S#multi{others = Others});
- {lock_set, _Pid, false, _} ->
- ?P2({the_locker, spurious, node(), node(_Pid)}),
- loop_the_locker(Global, S);
- {lock_set, Pid, true, HisKnown} ->
- Node = node(Pid),
- ?P2({the_locker, spontaneous, node(), Node}),
-
- NewKnown = gen_server:call(global_name_server, get_known),
-
- Others =
- case find_node_tag(Node, S#multi.others) of
- {true, MyTag} ->
-
- BothsKnown = HisKnown -- (HisKnown -- NewKnown),
- Known1 = if
- node() < Node ->
- [node() | NewKnown];
- true ->
- [node() | NewKnown] -- BothsKnown
- end,
-
- ?P2({lock1, node()}),
- LockId = {global, self()},
- IsLockSet = set_lock(LockId, Known1, 1),
- Pid ! {lock_set, self(), IsLockSet, NewKnown},
- ?P2({the_locker, spontaneous, node(), Node, IsLockSet}),
- case IsLockSet of
- true ->
- gen_server:cast(global_name_server,
- {lock_is_set, Node, MyTag}),
- ?P1({lock_sync_done, time(), node(),
- {Pid, node(Pid)}, self()}),
- %% Wait for global to tell us to remove lock.
- receive
- {cancel, Node, _Tag} ->
- %% All conflicts are resolved,
- %% remove lock.
- ?PRINT({node(), self(), locked1}),
- del_lock(LockId, Known1);
- {'EXIT', Pid, _} ->
- ?PRINT({node(), self(), locked2}),
- %% Other node died;
- %% remove lock and ignore him.
- del_lock(LockId, Known1),
- link(Global)
- end,
- remove_node(Node, S#multi.others);
- false ->
- S#multi.others
- end;
- false ->
- ?P2({the_locker, spontaneous, node(), Node, not_there}),
- Pid ! {lock_set, self(), false, NewKnown},
- S#multi.others
- end,
- loop_the_locker(Global, S#multi{others = Others});
- Other when element(1, Other) /= nodeup ->
- ?P2({the_locker, other_msg, Other}),
- loop_the_locker(Global, S)
- after Timeout ->
- NewKnown = gen_server:call(global_name_server, get_known),
- [{Node, HisTheLocker, HisKnown, MyTag} | Rest] = S#multi.others,
- BothsKnown = HisKnown -- (HisKnown -- NewKnown),
- Known1 = if
- node() < Node ->
- [node() | NewKnown];
- true ->
- [node() | NewKnown] -- BothsKnown
- end,
- ?P2({picking, node(), Node}),
- case lists:member(Node, NewKnown) of
- false ->
- LockId = {global, self()},
- ?P2({lock2, node()}),
- IsLockSet = set_lock(LockId, Known1, 1),
- Others =
- case IsLockSet of
- true ->
- HisTheLocker ! {lock_set, self(),
- IsLockSet, NewKnown},
- %% OTP-4902
- lock_set_loop(Global, S,
- Node, MyTag, Rest,
- Known1,
- LockId);
- false ->
- ?P2({the_locker, not_locked, node(),
- Node}),
- S#multi.others
- end,
- loop_the_locker(Global, S#multi{known=NewKnown,
- others = Others});
- true ->
- ?P2({is_known, node(), Node}),
- loop_the_locker(Global, S#multi{known=NewKnown,
- others = Rest})
- end
- end.
-
-lock_set_loop(Global, S, Node, MyTag, Rest, Known1, LockId) ->
- receive
- {lock_set, P, true, _} when node(P) == Node ->
- ?P2({the_locker, both_set, node(), Node}),
-
- %% do sync
- gen_server:cast(global_name_server, {lock_is_set, Node, MyTag}),
- ?P1({lock_sync_done, time(), node(), {Pid, node(Pid)}, self()}),
-
- %% Wait for global to tell us to remove lock.
- receive
- {cancel, Node, _} ->
- %% All conflicts are resolved, remove lock.
- ?PRINT({node(), self(), locked1}),
- del_lock(LockId, Known1);
- {'EXIT', _Pid, _} ->
- ?PRINT({node(), self(), locked2}),
- %% Other node died; remove lock and ignore him.
- del_lock(LockId, Known1),
- link(Global)
- end,
- Rest;
- {lock_set, P, false, _} when node(P) == Node ->
- ?P2({the_locker, not_both_set, node(), Node}),
- del_lock(LockId, Known1),
- S#multi.others;
- {cancel, Node, _} ->
- ?P2({the_locker, cancel2, node(), Node}),
- del_lock(LockId, Known1),
- remove_node(Node, S#multi.others);
- {'EXIT', _, _} ->
- ?P2({the_locker, exit, node(), Node}),
- del_lock(LockId, Known1),
- S#multi.others
-
- after
- %% OTP-4902
- %% A cyclic deadlock could occur in rare cases where three or
- %% more nodes waited for a reply from each other.
- %% Therefore, reject lock_set attempts in this state from
- %% nodes < this node (its enough if at least one node in
- %% the cycle rejects and thus breaks the deadlock)
- 5000 ->
- reject_lock_set(),
- lock_set_loop(Global, S, Node, MyTag, Rest, Known1, LockId)
- end.
-
-reject_lock_set() ->
- receive
- {lock_set, P, true, _} when node(P) < node() ->
- P ! {lock_set, self(), false, []},
- reject_lock_set()
- after
- 0 ->
- true
- end.
-
-start_locker(Node, Known, MyTag, Global, TheLocker) ->
- %% No link here! The del_lock call would delete the link anyway.
- %% global_name_server has control of these processes anyway...
- %% When the locker process exits due to being sent the 'cancel' message
- %% by the server, the server then removes it from its tables.
- %% When the locker terminates due to other reasons, the server must
- %% be told, so we make a link to it just before exiting.
- spawn(?MODULE, init_locker, [Node, Known, MyTag, Global, TheLocker]).
-
-init_locker(Node, Known, MyTag, Global, TheLocker) ->
- process_flag(trap_exit, true),
- ?PRINT({init_locker, node(), self(), Node}),
- ?P1({init_locker, time(), node(), self(), Node}),
- receive
- {his_locker, Pid, HisKnown} ->
- ?PRINT({init_locker, node(), self(), his_locker, Node}),
- link(Pid),
- %% If two nodes in a group of nodes first disconnect
- %% and then reconnect, this causes global to deadlock.
- %% This because both of the reconnecting nodes
- %% tries to set lock on the other nodes in the group.
- %% This is solved by letting only one of the reconneting nodes set the lock.
- BothsKnown = HisKnown -- (HisKnown -- Known),
- ?P({loop_locker1, node(), {Pid, node(Pid)}}),
- Res = loop_locker(Node, Pid, Known, 1, MyTag, BothsKnown, Global),
- ?P({loop_locker2, node(), {Pid, node(Pid)}}),
- Res;
- {his_locker_new, HisTheLocker, {Known1, Known2}} ->
- %% slide into the vsn 4 stuff
- ?P2({his_locker_new, node()}),
- HisTheLocker ! {his_the_locker, TheLocker, Known1, Known2},
- exit(normal);
- cancel ->
- ?PRINT({init_locker, node(), self(), cancel, Node}),
- exit(normal)
- end.
-
-loop_locker(Node, Pid, Known0, Try, MyTag, BothsKnown, Global) ->
- Known = if
- node() < Node ->
- [node() | Known0];
- true ->
- [node() | Known0] -- BothsKnown
- end,
-
- ?PRINT({locking, node(), self(), Known}),
- LockId = {global, self()},
- ?P2({lock3, node()}),
- IsLockSet = set_lock(LockId, Known, 1),
- ?P({loop_locker, IsLockSet,
- node(), {Pid, node(Pid)}, self(), Try}),
- ?P1({loop_locker, time(), IsLockSet,
- node(), {Pid, node(Pid)}, self(), Try}),
- ?PRINT({locking1, node(), self(), Known, IsLockSet}),
- %% Tell other node that we managed to get the lock.
- Pid ! {lock, ?locker_vsn, IsLockSet, Known},
- Pid ! {lock, IsLockSet, Known},
- Pid ! {lock, IsLockSet},
- %% Wait for other node's result.
- receive
- %% R7 patched and later
- {lock, _LockerVsn, true, _} when IsLockSet == true ->
- receive
- {lock, _} ->
- ok
- end,
- receive
- {lock, _, _} ->
- ok
- end,
- ?PRINT({node(), self(), locked}),
- %% Now we got the lock in both partitions. Tell
- %% global, and let him resolve name conflict.
- ?P1({lock_sync, time(), node(), {Pid, node(Pid)}, self()}),
- gen_server:cast(global_name_server, {lock_is_set, Node, MyTag}),
- ?P1({lock_sync_done, time(), node(), {Pid, node(Pid)}, self()}),
- %% Wait for global to tell us to remove lock.
- receive
- cancel ->
- %% All conflicts are resolved, remove lock.
- ?PRINT({node(), self(), locked1}),
- del_lock(LockId, Known);
- {'EXIT', Pid, _} ->
- ?PRINT({node(), self(), locked2}),
- %% Other node died; remove lock and ignore him.
- del_lock(LockId, Known),
- link(Global)
- end;
- {lock, _LockerVsn, _, HisKnown} ->
- receive
- {lock, _} ->
- ok
- end,
- receive
- {lock, _, _} ->
- ok
- end,
- %% Some of us failed to get the lock; try again
- ?PRINT({node(), self(), locked0}),
- d_lock(IsLockSet, LockId, Known),
- try_again_locker(Node, Pid, Try, MyTag, HisKnown, Global);
- %% R7 unpatched
- {lock, true, _} when IsLockSet == true ->
- ?PRINT({node(), self(), locked}),
- %% Now we got the lock in both partitions. Tell
- %% global, and let him resolve name conflict.
- gen_server:cast(global_name_server, {lock_is_set, Node, MyTag}),
- %% Wait for global to tell us to remove lock.
- receive
- cancel ->
- %% All conflicts are resolved, remove lock.
- ?PRINT({node(), self(), locked1}),
- del_lock(LockId, Known);
- {'EXIT', Pid, _} ->
- ?PRINT({node(), self(), locked2}),
- %% Other node died; remove lock and ignore him.
- del_lock(LockId, Known),
- link(Global)
- end;
- {lock, _, HisKnown} ->
- %% Some of us failed to get the lock; try again
- ?PRINT({node(), self(), locked0}),
- d_lock(IsLockSet, LockId, Known),
- try_again_locker(Node, Pid, Try, MyTag, HisKnown, Global);
- %% R6 and earlier
- {lock, true} when IsLockSet == true ->
- ?PRINT({node(), self(), locked}),
- %% Now we got the lock in both partitions. Tell
- %% global, and let him resolve name conflict.
- gen_server:cast(global_name_server, {lock_is_set, Node, MyTag}),
- %% Wait for global to tell us to remove lock.
- receive
- cancel ->
- %% All conflicts are resolved, remove lock.
- ?PRINT({node(), self(), locked1}),
- del_lock(LockId, Known);
- {'EXIT', Pid, _} ->
- ?PRINT({node(), self(), locked2}),
- %% Other node died; remove lock and ignore him.
- del_lock(LockId, Known),
- link(Global)
- end;
- {lock, _} ->
- %% Some of us failed to get the lock; try again
- ?PRINT({node(), self(), locked0}),
- d_lock(IsLockSet, LockId, Known),
- try_again_locker(Node, Pid, Try, MyTag, BothsKnown, Global);
- {'EXIT', Pid, _} ->
- %% Other node died; remove lock and ignore him.
- ?PRINT({node(), self(), locked7}),
- d_lock(IsLockSet, LockId, Known),
- link(Global);
- cancel ->
- ?PRINT({node(), self(), locked8}),
- d_lock(IsLockSet, LockId, Known)
- end.
-
-d_lock(true, LockId, Known) -> del_lock(LockId, Known);
-d_lock(false, _, _) -> ok.
-
-try_again_locker(Node, Pid, Try, MyTag, HisKnown, Global) ->
- ?PRINT({try_again, node(), self(), Node, Pid, Known, Try, MyTag}),
- ?P1({try_again, time(), node(), self(), Node, Pid, Known, Try, MyTag}),
- random_sleep(Try),
- ?P1({try_again2, time(), node(), self(), Node, Pid, Known, Try, MyTag}),
- NewKnown = gen_server:call(global_name_server, get_known),
- case lists:member(Node, NewKnown) of
- false ->
- BothsKnown1 = HisKnown -- (HisKnown -- NewKnown),
- ?PRINT({node(), self(), Node, again, notknown}),
- ?PRINT({bothknown, BothsKnown, BothsKnown1}),
- loop_locker(Node, Pid, NewKnown, Try+1, MyTag,
- BothsKnown1, Global);
- true ->
- ?PRINT({node(), self(), Node, again, known}),
- link(Global),
- %% Node is already handled, we are ready.
- ok
- end.
-
-cancel_locker(Node, S) ->
- %% multi
- ?P2({cancel, node(), Node, get({sync_tag_my, Node})}),
- S#state.the_locker ! {cancel, Node, get({sync_tag_my, Node})},
-
- Lockers = S#state.lockers,
- case lists:keysearch(Node, 1, Lockers) of
- {value, {_, Pid}} ->
- Pid ! cancel,
- ?PRINT({cancel, Node, lockers, node(), Lockers}),
- S#state{lockers = lists:keydelete(Node, 1, Lockers)};
- _ ->
- S
- end.
-
-%% A node sent us his names. When a name clash is found, the resolve
-%% function is called from the smaller node => all resolve funcs are called
-%% from the same partition.
-exchange_names([{Name, Pid, Method} |Tail], Node, Ops, Res) ->
- case ets:lookup(global_names, Name) of
- [{Name, Pid, _}] ->
- exchange_names(Tail, Node, Ops, Res);
- [{Name, Pid2, Method2}] when node() < Node ->
- %% Name clash! Add the result of resolving to Res(olved).
- %% We know that node(Pid) /= node(), so we don't
- %% need to link/unlink to Pid.
- Node2 = node(Pid2), %%&&&&&& check external node???
- case rpc:call(Node2, ?MODULE, resolve_it,
- [Method2, Name, Pid, Pid2]) of
- Pid ->
- dounlink(Pid2),
- ets:insert(global_names, {Name, Pid, Method}),
- Op = {insert, {Name, Pid, Method}},
- exchange_names(Tail, Node, [Op | Ops], [Op | Res]);
- Pid2 ->
- Op = {insert, {Name, Pid2, Method2}},
- exchange_names(Tail, Node, Ops, [Op | Res]);
- none ->
- dounlink(Pid2),
- ?P2({unregister, node(), Name, Pid2, node(Pid2)}),
- ets:delete(global_names, Name),
- Op = {delete, Name},
- exchange_names(Tail, Node, [Op | Ops], [Op | Res]);
- {badrpc, Badrpc} ->
- error_logger:info_msg("global: badrpc ~w received when "
- "conflicting name ~w was found",
- [Badrpc, Name]),
- dounlink(Pid2),
- ets:insert(global_names, {Name, Pid, Method}),
- Op = {insert, {Name, Pid, Method}},
- exchange_names(Tail, Node, [Op | Ops], [Op | Res]);
- Else ->
- error_logger:info_msg("global: Resolve method ~w for "
- "conflicting name ~w returned ~w~n",
- [Method, Name, Else]),
- dounlink(Pid2),
- ets:delete(global_names, Name),
- Op = {delete, Name},
- exchange_names(Tail, Node, [Op | Ops], [Op | Res])
- end;
- [{Name, _Pid2, _}] ->
- %% The other node will solve the conflict.
- exchange_names(Tail, Node, Ops, Res);
- _ ->
- %% Entirely new name.
- ets:insert(global_names, {Name, Pid, Method}),
- exchange_names(Tail, Node,
- [{insert, {Name, Pid, Method}} | Ops], Res)
- end;
-exchange_names([], _, Ops, Res) ->
- {Ops, Res}.
-
-resolve_it(Method, Name, Pid1, Pid2) ->
- catch Method(Name, Pid1, Pid2).
-
-minmax(P1,P2) ->
- if node(P1) < node(P2) -> {P1, P2}; true -> {P2, P1} end.
-
-random_exit_name(Name, Pid, Pid2) ->
- {Min, Max} = minmax(Pid, Pid2),
- error_logger:info_msg("global: Name conflict terminating ~w~n",
- [{Name, Max}]),
- exit(Max, kill),
- Min.
-
-random_notify_name(Name, Pid, Pid2) ->
- {Min, Max} = minmax(Pid, Pid2),
- Max ! {global_name_conflict, Name},
- Min.
-
-notify_all_name(Name, Pid, Pid2) ->
- Pid ! {global_name_conflict, Name, Pid2},
- Pid2 ! {global_name_conflict, Name, Pid},
- none.
-
-cnode(Name, Pid, Pid2) ->
- {Min, Max} = minmax(Pid, Pid2),
- error_logger:info_msg("global: Name conflict terminating ~w~n",
- [{Name, Max}]),
- Max ! {global_name_conflict, Name},
- Min.
-
-%% Only link to pids on our own node
-dolink(Pid) when node(Pid) == node() ->
- link(Pid);
-dolink(_) -> ok.
-
-%% Only link to pids on our own node
-dolink_ext(Pid, RegNode) when RegNode == node() -> link(Pid);
-dolink_ext(_, _) -> ok.
-
-dounlink(Pid) when node(Pid) == node() ->
- case ets:match(global_names, {'_', Pid, '_'}) of
- [] ->
- case is_pid_used(Pid) of
- false ->
- unlink(Pid);
- true -> ok
- end;
- _ -> ok
- end;
-dounlink(_Pid) ->
- ok.
-
-is_pid_used(Pid) ->
- is_pid_used(ets:tab2list(global_locks), Pid).
-
-is_pid_used([], _Pid) ->
- false;
-is_pid_used([{_ResourceId, _LockReqId, Pids} | Tail], Pid) ->
- case lists:member(Pid, Pids) of
- true ->
- true;
- false ->
- is_pid_used(Tail, Pid)
- end.
-
-
-
-%% check_exit/3 removes the Pid from affected tables.
-%% This function needs to abcast the thingie since only the local
-%% server is linked to the registered process (or the owner of the
-%% lock). All the other servers rely on the nodedown mechanism.
-check_exit(Deleter, Pid) ->
- del_names(Deleter, Pid, ets:tab2list(global_names)),
- del_locks(ets:tab2list(global_locks), Pid).
-
-del_names(Deleter, Pid, [{Name, Pid, _Method} | Tail]) ->
- %% First, delete the Pid from the local ets; then send to other nodes
- ets:delete(global_names, Name),
- ets:delete(global_names_ext, Name),
- dounlink(Pid),
- Deleter ! {delete_name,self(),Name,Pid},
- del_names(Deleter, Pid, Tail);
-del_names(Deleter, Pid, [_|T]) ->
- del_names(Deleter, Pid, T);
-del_names(_Deleter, _Pid, []) -> done.
-
-del_locks([{ResourceId, LockReqId, Pids} | Tail], Pid) ->
- case {lists:member(Pid, Pids), Pids} of
- {true, [Pid]} ->
- ets:delete(global_locks, ResourceId),
- gen_server:abcast(nodes(), global_name_server,
- {async_del_lock, ResourceId, Pid});
- {true, _} ->
- NewPids = lists:delete(Pid, Pids),
- ets:insert(global_locks, {ResourceId, LockReqId, NewPids}),
- gen_server:abcast(nodes(), global_name_server,
- {async_del_lock, ResourceId, Pid});
- _ ->
- continue
- end,
- del_locks(Tail, Pid);
-del_locks([], _Pid) -> done.
-
-del_locks2([{ResourceId, LockReqId, Pids} | Tail], Pid) ->
- case {lists:member(Pid, Pids), Pids} of
- {true, [Pid]} ->
- ets:delete(global_locks, ResourceId);
- {true, _} ->
- NewPids = lists:delete(Pid, Pids),
- ets:insert(global_locks, {ResourceId, LockReqId, NewPids});
- _ ->
- continue
- end,
- del_locks2(Tail, Pid);
-del_locks2([], _Pid) ->
- done.
-
-
-
-%% Unregister all Name/Pid pairs such that node(Pid) == Node
-%% and delete all locks where node(Pid) == Node
-do_node_down(Node) ->
- do_node_down_names(Node, ets:tab2list(global_names)),
- do_node_down_names_ext(Node, ets:tab2list(global_names_ext)),
- do_node_down_locks(Node, ets:tab2list(global_locks)).
-
-do_node_down_names(Node, [{Name, Pid, _Method} | T]) when node(Pid) == Node ->
- ets:delete(global_names, Name),
- do_node_down_names(Node, T);
-do_node_down_names(Node, [_|T]) ->
- do_node_down_names(Node, T);
-do_node_down_names(_, []) -> ok.
-
-%%remove all external names registered on the crashed node
-do_node_down_names_ext(Node, [{Name, _Pid, Node} | T]) ->
- ets:delete(global_names, Name),
- ets:delete(global_names_ext, Name),
- do_node_down_names_ext(Node, T);
-do_node_down_names_ext(Node, [_|T]) ->
- do_node_down_names_ext(Node, T);
-do_node_down_names_ext(_, []) -> ok.
-
-do_node_down_locks(Node, [{ResourceId, LockReqId, Pids} | T]) ->
- case do_node_down_locks2(Pids, Node) of
- [] ->
- continue;
- RemovePids ->
- case Pids -- RemovePids of
- [] ->
- ets:delete(global_locks, ResourceId);
- NewPids ->
- ets:insert(global_locks, {ResourceId, LockReqId, NewPids})
- end
- end,
- do_node_down_locks(Node, T);
-do_node_down_locks(Node, [_|T]) ->
- do_node_down_locks(Node, T);
-do_node_down_locks(_, []) -> done.
-
-
-do_node_down_locks2(Pids, Node) ->
- do_node_down_locks2(Pids, Node, []).
-
-do_node_down_locks2([], _Node, Res) ->
- Res;
-do_node_down_locks2([Pid | Pids], Node, Res) when node(Pid) == Node ->
- do_node_down_locks2(Pids, Node, [Pid | Res]);
-do_node_down_locks2([_ | Pids], Node, Res) ->
- do_node_down_locks2(Pids, Node, Res).
-
-
-get_names() ->
- ets:tab2list(global_names).
-
-get_names_ext() ->
- ets:tab2list(global_names_ext).
-
-random_sleep(Times) ->
- case (Times rem 10) of
- 0 -> erase(random_seed);
- _ -> ok
- end,
- case get(random_seed) of
- undefined ->
- {A1, A2, A3} = now(),
- random:seed(A1, A2, A3 + erlang:phash(node(), 100000));
- _ -> ok
- end,
- %% First time 1/4 seconds, then doubling each time up to 8 seconds max.
- Tmax = if Times > 5 -> 8000;
- true -> ((1 bsl Times) * 1000) div 8
- end,
- T = random:uniform(Tmax),
- ?P({random_sleep, node(), self(), Times, T}),
- receive after T -> ok end.
-
-dec(infinity) -> infinity;
-dec(N) -> N-1.
-
-send_again(Msg) ->
- spawn_link(?MODULE, timer, [self(), Msg]).
-
-timer(Pid, Msg) ->
- random_sleep(5),
- Pid ! Msg.
-
-change_our_node_name(NewNode, S) ->
- S#state{node_name = NewNode}.
-
-
-%%-----------------------------------------------------------------
-%% Each sync process corresponds to one call to sync. Each such
-%% process asks the global_name_server on all Nodes if it is in sync
-%% with Nodes. If not, that (other) node spawns a syncer process that
-%% waits for global to get in sync with all Nodes. When it is in
-%% sync, the syncer process tells the original sync process about it.
-%%-----------------------------------------------------------------
-start_sync(Nodes, From) ->
- spawn_link(?MODULE, sync_init, [Nodes, From]).
-
-sync_init(Nodes, From) ->
- lists:foreach(fun(Node) -> monitor_node(Node, true) end, Nodes),
- sync_loop(Nodes, From).
-
-sync_loop([], From) ->
- gen_server:reply(From, ok);
-sync_loop(Nodes, From) ->
- receive
- {nodedown, Node} ->
- monitor_node(Node, false),
- sync_loop(lists:delete(Node, Nodes), From);
- {synced, SNodes} ->
- lists:foreach(fun(N) -> monitor_node(N, false) end, SNodes),
- sync_loop(Nodes -- SNodes, From)
- end.
-
-
-%%%====================================================================================
-%%% Get the current global_groups definition
-%%%====================================================================================
-check_sync_nodes() ->
- case get_own_nodes() of
- {ok, all} ->
- nodes();
- {ok, NodesNG} ->
- %% global_groups parameter is defined, we are not allowed to sync
- %% with nodes not in our own global group.
- (nodes() -- (nodes() -- NodesNG));
- {error, Error} ->
- {error, Error}
- end.
-
-check_sync_nodes(SyncNodes) ->
- case get_own_nodes() of
- {ok, all} ->
- SyncNodes;
- {ok, NodesNG} ->
- %% global_groups parameter is defined, we are not allowed to sync
- %% with nodes not in our own global group.
- OwnNodeGroup = (nodes() -- (nodes() -- NodesNG)),
- IllegalSyncNodes = (SyncNodes -- [node() | OwnNodeGroup]),
- case IllegalSyncNodes of
- [] -> SyncNodes;
- _ -> {error, {"Trying to sync nodes not defined in the own global group",
- IllegalSyncNodes}}
- end;
- {error, Error} ->
- {error, Error}
- end.
-
-get_own_nodes() ->
- case global_group:get_own_nodes_with_errors() of
- {error, Error} ->
- {error, {"global_groups definition error", Error}};
- OkTup ->
- OkTup
- end.
-
-
-%%-----------------------------------------------------------------
-%% The deleter process is a satellite process to global_name_server
-%% that does background batch deleting of names when a process
-%% that had globally registered names dies. It is started by and
-%% linked to global_name_server.
-%%-----------------------------------------------------------------
-
-start_the_deleter(Global) ->
- spawn_link(
- fun () ->
- loop_the_deleter(Global)
- end).
-
-loop_the_deleter(Global) ->
- Deletions = collect_deletions(Global, []),
- trans({global, self()},
- fun() ->
- lists:map(
- fun ({Name,Pid}) ->
- ?P2({delete_name2, Name, Pid, nodes()}),
- gen_server:abcast(nodes(), global_name_server,
- {async_del_name, Name, Pid})
- end, Deletions)
- end,
- nodes()),
- loop_the_deleter(Global).
-
-collect_deletions(Global, Deletions) ->
- receive
- {delete_name,Global,Name,Pid} ->
- ?P2({delete_name, node(), self(), Name, Pid, nodes()}),
- collect_deletions(Global, [{Name,Pid}|Deletions]);
- Other ->
- error_logger:error_msg("The global_name_server deleter process "
- "received an unexpected message:\n~p\n",
- [Other]),
- collect_deletions(Global, Deletions)
- after case Deletions of
- [] -> infinity;
- _ -> 0
- end ->
- lists:reverse(Deletions)
- end.
diff --git a/lib/dialyzer/test/plt_SUITE.erl b/lib/dialyzer/test/plt_SUITE.erl
new file mode 100644
index 0000000000..aee9f449a6
--- /dev/null
+++ b/lib/dialyzer/test/plt_SUITE.erl
@@ -0,0 +1,21 @@
+%% This suite is the only hand made and simply
+%% checks if we can build a plt.
+
+-module(plt_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+-include("dialyzer_test_constants.hrl").
+
+-export([suite/0, all/0, build_plt/1]).
+
+suite() ->
+ [{timetrap, ?plt_timeout}].
+
+all() -> [build_plt].
+
+build_plt(Config) ->
+ OutDir = ?config(priv_dir, Config),
+ case dialyzer_common:check_plt(OutDir) of
+ ok -> ok;
+ fail -> ct:fail(plt_build_fail)
+ end.
diff --git a/lib/dialyzer/test/plt_tests_SUITE.erl b/lib/dialyzer/test/plt_tests_SUITE.erl
deleted file mode 100644
index bf45020340..0000000000
--- a/lib/dialyzer/test/plt_tests_SUITE.erl
+++ /dev/null
@@ -1,21 +0,0 @@
-%% This suite is the only hand made and simply
-%% checks if we can build a plt.
-
--module(plt_tests_SUITE).
-
--include("ct.hrl").
--include("dialyzer_test_constants.hrl").
-
--export([suite/0, all/0, build_plt/1]).
-
-suite() ->
- [{timetrap, ?plt_timeout}].
-
-all() -> [build_plt].
-
-build_plt(Config) ->
- OutDir = ?config(priv_dir, Config),
- case dialyzer_common:check_plt(OutDir) of
- ok -> ok;
- fail -> ct:fail(plt_build_fail)
- end.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/dialyzer_options b/lib/dialyzer/test/r9c_SUITE_data/dialyzer_options
index e00e23bb66..e00e23bb66 100644
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/dialyzer_options
+++ b/lib/dialyzer/test/r9c_SUITE_data/dialyzer_options
diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/asn1 b/lib/dialyzer/test/r9c_SUITE_data/results/asn1
new file mode 100644
index 0000000000..292275dd6e
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/results/asn1
@@ -0,0 +1,106 @@
+
+asn1ct.erl:1500: The variable Err can never match since previous clauses completely covered the type #type{}
+asn1ct.erl:1596: The variable _ can never match since previous clauses completely covered the type 'ber_bin_v2'
+asn1ct.erl:1673: The pattern 'all' can never match the type 'asn1_module' | 'exclusive_decode' | 'partial_decode'
+asn1ct.erl:672: The pattern <{'false', Result}, _, _> can never match the type <{'true','true'},atom() | binary() | [atom() | [any()] | char()],[any()]>
+asn1ct.erl:909: Guard test is_atom(Ext::[49 | 97 | 98 | 100 | 110 | 115]) can never succeed
+asn1ct_check.erl:1698: The pattern {'error', _} can never match the type [any()]
+asn1ct_check.erl:2733: The pattern {'type', Tag, _, _, _, _} can never match the type 'ASN1_OPEN_TYPE' | {_,_} | {'fixedtypevaluefield',_,_}
+asn1ct_check.erl:2738: The pattern <_S, _> can never match since previous clauses completely covered the type <#state{},#'ObjectClassFieldType'{class::#objectclass{fields::maybe_improper_list() | {_,_,_,_}},fieldname::{_,maybe_improper_list()},type::'ASN1_OPEN_TYPE' | {_,_} | {'fixedtypevaluefield',_,_}}>
+asn1ct_check.erl:2887: The variable Other can never match since previous clauses completely covered the type any()
+asn1ct_check.erl:3188: The pattern <_S, [], B> can never match the type <#state{},{'SingleValue',_},{'ValueRange',_}>
+asn1ct_check.erl:3190: The pattern <_S, A, []> can never match the type <#state{},{'SingleValue',_},{'ValueRange',_}>
+asn1ct_check.erl:3212: The pattern {[], C3} can never match the type {[any(),...],{'ValueRange',{'MIN','MAX'}}}
+asn1ct_check.erl:3225: The pattern {L1, UbNew} can never match the type 'false'
+asn1ct_check.erl:3228: The pattern {L1, LbNew} can never match the type 'false'
+asn1ct_check.erl:3235: The call asn1ct_check:remove_val_from_list(number(),L::[any(),...]) will never return since it differs in the 1st argument from the success typing arguments: ([any()],any())
+asn1ct_check.erl:3240: The call asn1ct_check:remove_val_from_list(number(),L::[any(),...]) will never return since it differs in the 1st argument from the success typing arguments: ([any()],any())
+asn1ct_check.erl:3242: Function remove_val_from_list/2 has no local return
+asn1ct_check.erl:3243: The call lists:member(Val::[any(),...],List::number()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),[any()])
+asn1ct_check.erl:3283: The pattern [] can never match the type [any(),...]
+asn1ct_check.erl:3362: The pattern <_, [], _VR> can never match the type <#state{},[any(),...],[any(),...]>
+asn1ct_check.erl:3364: The pattern <_, _SV, []> can never match the type <#state{},[any(),...],[any(),...]>
+asn1ct_check.erl:4150: The pattern <_, [_]> can never match the type <_,[]>
+asn1ct_check.erl:4314: The pattern <S, Type, {Rlist, ExtList}> can never match the type <#state{},_,[any()]>
+asn1ct_check.erl:4360: The pattern <S, Type, {Rlist, ExtList}> can never match the type <#state{},_,[any()]>
+asn1ct_check.erl:4719: The call asn1ct_check:error({'type',{'asn1',[1..255,...],[any(),...]}}) will never return since it differs in the 1st argument from the success typing arguments: ({'ObjectSet' | 'class' | 'export' | 'ptype' | 'type' | 'value',_,#state{}})
+asn1ct_check.erl:5120: Guard test is_record(Type::{_,_} | {'fixedtypevaluefield',_,_},'type',6) can never succeed
+asn1ct_check.erl:5128: Guard test is_record(Type::{_,_} | {'fixedtypevaluefield',_,_},'type',6) can never succeed
+asn1ct_check.erl:540: The pattern <_S, {'poc', _ObjSet, _Params}> can never match since previous clauses completely covered the type <#state{},_>
+asn1ct_check.erl:5517: The pattern <_, []> can never match the type <_,[{'ABSTRACT-SYNTAX',{_,_,_}} | {'TYPE-IDENTIFIER',{_,_,_}},...]>
+asn1ct_constructed_ber.erl:1075: The pattern {{{'ObjectClassFieldType', _, _, _, {'objectfield', PrimFieldName1, PFNList}}, _}, {'componentrelation', _, _}} can never match the type {#type{},_}
+asn1ct_constructed_ber.erl:695: The pattern {'EXTENSIONMARK', _, _} can never match the type #'ComponentType'{}
+asn1ct_constructed_ber.erl:748: The pattern <Erules, TopType, {CompList, _ExtList}> can never match the type <_,maybe_improper_list(),[#'ComponentType'{typespec::{_,_,_,_,_,_}}]>
+asn1ct_constructed_ber_bin_v2.erl:914: The pattern {{{'ObjectClassFieldType', _, _, _, {'objectfield', PrimFieldName1, PFNList}}, _}, {'componentrelation', _, _}} can never match the type {#type{},_}
+asn1ct_gen.erl:740: The pattern [] can never match the type [any(),...]
+asn1ct_gen_ber.erl:974: The pattern <Erules, [{Name, Def} | Rest]> can never match the type <_,[#typedef{name::atom(),typespec::{_,_,_,_,_,_}}]>
+asn1ct_gen_ber_bin_v2.erl:975: The pattern <Erules, [{Name, Def} | Rest]> can never match the type <_,[#typedef{name::atom(),typespec::{_,_,_,_,_,_}}]>
+asn1ct_gen_per.erl:646: The pattern <Erules, [{Name, Def} | Rest]> can never match the type <_,[#typedef{name::atom()}]>
+asn1ct_gen_per_rt2ct.erl:1189: The pattern <Erules, [{Name, Def} | Rest]> can never match the type <_,[#typedef{name::atom()}]>
+asn1ct_gen_per_rt2ct.erl:563: The pattern <C, ['EXT_MARK' | T], _Count> can never match the type <[{'ValueRange',{_,_}},...],[char() | {'asn1_enum',integer()},...],non_neg_integer()>
+asn1ct_gen_per_rt2ct.erl:580: The pattern <_C, 'EXT_MARK', _Count> can never match the type <[{'ValueRange',{_,_}},...],char(),non_neg_integer()>
+asn1ct_gen_per_rt2ct.erl:583: The pattern <_C, {1, EnumName}, Count> can never match the type <[{'ValueRange',{_,_}},...],char(),non_neg_integer()>
+asn1ct_gen_per_rt2ct.erl:587: The pattern <C, {0, EnumName}, Count> can never match the type <[{'ValueRange',{_,_}},...],char(),non_neg_integer()>
+asn1ct_gen_per_rt2ct.erl:656: The pattern <Type, C> can never match since previous clauses completely covered the type <'bitstring' | 'integer',_>
+asn1ct_parser2.erl:2017: Call to missing or unexported function ordsets:list_to_set/1
+asn1ct_parser2.erl:2497: The variable _ can never match since previous clauses completely covered the type 'ok'
+asn1ct_parser2.erl:2628: The pattern {Rlist, ExtList} can never match the type [{_,_,_},...]
+asn1ct_parser2.erl:2660: Call to missing or unexported function ordsets:list_to_set/1
+asn1ct_parser2.erl:2685: Call to missing or unexported function ordsets:list_to_set/1
+asn1ct_parser2.erl:281: The variable Other can never match since previous clauses completely covered the type [any()]
+asn1ct_parser2.erl:529: The variable _ can never match since previous clauses completely covered the type #constraint{}
+asn1ct_parser2.erl:555: The variable _ can never match since previous clauses completely covered the type #constraint{}
+asn1ct_parser2.erl:796: The variable _ can never match since previous clauses completely covered the type {_,_}
+asn1ct_parser2.erl:814: The variable _ can never match since previous clauses completely covered the type {_,_}
+asn1ct_parser2.erl:831: The variable _ can never match since previous clauses completely covered the type {_,_}
+asn1ct_value.erl:247: The pattern <'undefined', Default> can never match the type <maybe_improper_list(),[1..255,...]>
+asn1rt_ber_bin.erl:1125: Cons will produce an improper list since its 2nd argument is binary() | tuple()
+asn1rt_ber_bin.erl:1276: The pattern <{{_Min1, Max1}, {Min2, Max2}}, BitListVal, _DoTag> can never match since previous clauses completely covered the type <{_,_},maybe_improper_list(),_>
+asn1rt_ber_bin.erl:2057: The call asn1rt_ber_bin:check_if_valid_tag2('false',[],[],OptOrMand::any()) will never return since it differs in the 2nd argument from the success typing arguments: ('false' | {'APPLICATION',_} | {'CONTEXT',_} | {'PRIVATE',_} | {'UNIVERSAL',_},nonempty_maybe_improper_list(),[] | {_,_,_},any())
+asn1rt_ber_bin.erl:969: The pattern {Val01, Buffer01, Rb01} can never match the type {'MINUS-INFINITY' | 'PLUS-INFINITY' | 0,binary()}
+asn1rt_ber_bin.erl:998: The pattern {FirstLen, {Exp, Buffer3}, RemBytes2} can never match the type {1..1114111,{integer(),binary(),number()},number()}
+asn1rt_ber_bin_v2.erl:1230: The pattern <{{_Min1, Max1}, {Min2, Max2}}, BitListVal, TagIn> can never match since previous clauses completely covered the type <{_,_},maybe_improper_list(),_>
+asn1rt_ber_bin_v2.erl:328: The variable _ can never match since previous clauses completely covered the type {{0 | 1,non_neg_integer(),'indefinite' | non_neg_integer(),binary()},binary() | []}
+asn1rt_ber_bin_v2.erl:337: The variable _ can never match since previous clauses completely covered the type {{0 | 1,non_neg_integer(),'indefinite' | non_neg_integer(),binary()},binary() | []}
+asn1rt_ber_bin_v2.erl:392: The variable _ can never match since previous clauses completely covered the type {{0 | 1,non_neg_integer(),'indefinite' | non_neg_integer(),binary()},binary() | []}
+asn1rt_ber_bin_v2.erl:963: Function decode_real/3 has no local return
+asn1rt_check.erl:100: The variable _ can never match since previous clauses completely covered the type [any()]
+asn1rt_check.erl:85: The variable _ can never match since previous clauses completely covered the type [any()]
+asn1rt_driver_handler.erl:32: The pattern 'already_done' can never match the type {'error',_}
+asn1rt_per.erl:1065: The pattern {'BMPString', {'octets', Ol}} can never match the type {_,[{'bits',1 | 2 | 4 | 8 | 16 | 32,_}]}
+asn1rt_per.erl:1066: Function will never be called
+asn1rt_per.erl:1231: The call erlang:'not'('implemented') will never return since it differs in the 1st argument from the success typing arguments: (boolean())
+asn1rt_per.erl:1233: The call erlang:'not'('implemented') will never return since it differs in the 1st argument from the success typing arguments: (boolean())
+asn1rt_per.erl:1235: The call erlang:'not'('implemented') will never return since it differs in the 1st argument from the success typing arguments: (boolean())
+asn1rt_per.erl:1237: The call erlang:'not'('implemented') will never return since it differs in the 1st argument from the success typing arguments: (boolean())
+asn1rt_per.erl:989: The pattern <_C, 'true', _Val> can never match the type <_,'false',_>
+asn1rt_per_bin.erl:1361: The pattern <_, 'true', _> can never match the type <_,'false',_>
+asn1rt_per_bin.erl:1436: The pattern {'BMPString', {'octets', Ol}} can never match the type {'BMPString' | 'IA5String' | 'NumericString' | 'PrintableString' | 'UniversalString' | 'VisibleString',[{'bits',1 | 2 | 4 | 8 | 16 | 32,_}]}
+asn1rt_per_bin.erl:1437: Function will never be called
+asn1rt_per_bin.erl:161: The call asn1rt_per_bin:getbit({0,maybe_improper_list()}) will never return since it differs in the 1st argument from the success typing arguments: (<<_:8,_:_*8>> | {non_neg_integer(),<<_:1,_:_*1>>})
+asn1rt_per_bin.erl:1812: The pattern {Name, Val} can never match since previous clauses completely covered the type any()
+asn1rt_per_bin.erl:2106: Cons will produce an improper list since its 2nd argument is binary()
+asn1rt_per_bin.erl:2111: Cons will produce an improper list since its 2nd argument is binary()
+asn1rt_per_bin.erl:2111: Cons will produce an improper list since its 2nd argument is integer()
+asn1rt_per_bin.erl:2117: Cons will produce an improper list since its 2nd argument is integer()
+asn1rt_per_bin.erl:2121: Cons will produce an improper list since its 2nd argument is 0
+asn1rt_per_bin.erl:2123: Cons will produce an improper list since its 2nd argument is 0
+asn1rt_per_bin.erl:2127: Cons will produce an improper list since its 2nd argument is 0
+asn1rt_per_bin.erl:2129: Cons will produce an improper list since its 2nd argument is integer()
+asn1rt_per_bin.erl:446: The variable _ can never match since previous clauses completely covered the type integer()
+asn1rt_per_bin.erl:467: The variable _ can never match since previous clauses completely covered the type integer()
+asn1rt_per_bin.erl:474: The pattern <{_N, <<_:8/integer-unit:1,Bs/binary-unit:8>>}, C> can never match since previous clauses completely covered the type <{0,_},integer()>
+asn1rt_per_bin.erl:487: The variable _ can never match since previous clauses completely covered the type integer()
+asn1rt_per_bin.erl:498: The variable _ can never match since previous clauses completely covered the type integer()
+asn1rt_per_bin_rt2ct.erl:152: The call asn1rt_per_bin_rt2ct:getbit({0,maybe_improper_list()}) will never return since it differs in the 1st argument from the success typing arguments: (<<_:8,_:_*8>> | {non_neg_integer(),<<_:1,_:_*1>>})
+asn1rt_per_bin_rt2ct.erl:1533: The pattern {'BMPString', {'octets', Ol}} can never match the type {_,[[any(),...]]}
+asn1rt_per_bin_rt2ct.erl:1534: Function will never be called
+asn1rt_per_bin_rt2ct.erl:1875: The pattern {Name, Val} can never match since previous clauses completely covered the type any()
+asn1rt_per_bin_rt2ct.erl:443: The variable _ can never match since previous clauses completely covered the type integer()
+asn1rt_per_bin_rt2ct.erl:464: The variable _ can never match since previous clauses completely covered the type integer()
+asn1rt_per_bin_rt2ct.erl:471: The pattern <{_N, <<_B:8/integer-unit:1,Bs/binary-unit:8>>}, C> can never match since previous clauses completely covered the type <{0,_},integer()>
+asn1rt_per_bin_rt2ct.erl:484: The variable _ can never match since previous clauses completely covered the type integer()
+asn1rt_per_bin_rt2ct.erl:495: The variable _ can never match since previous clauses completely covered the type integer()
+asn1rt_per_v1.erl:1209: The pattern <_, 'true', _> can never match the type <_,'false',_>
+asn1rt_per_v1.erl:1290: The pattern {'BMPString', {'octets', Ol}} can never match the type {'BMPString' | 'IA5String' | 'NumericString' | 'PrintableString' | 'UniversalString' | 'VisibleString',[{'bits',1 | 2 | 4 | 8 | 16 | 32,_}]}
+asn1rt_per_v1.erl:1291: Function will never be called
diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/inets b/lib/dialyzer/test/r9c_SUITE_data/results/inets
new file mode 100644
index 0000000000..0177dcc88c
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/results/inets
@@ -0,0 +1,64 @@
+
+ftp.erl:1243: The pattern {'ok', {N, Bytes}} can never match the type 'eof' | {'error',atom()} | {'ok',binary() | string()}
+ftp.erl:640: The pattern {'closed', _Why} can never match the type 'perm_fname_not_allowed' | 'perm_neg_compl' | 'perm_no_space' | 'pos_compl' | 'pos_interm' | 'pos_interm_acct' | 'trans_neg_compl' | 'trans_no_space' | {'error' | 'perm_fname_not_allowed' | 'perm_neg_compl' | 'perm_no_space' | 'pos_compl' | 'pos_interm' | 'pos_interm_acct' | 'pos_prel' | 'trans_neg_compl' | 'trans_no_space',atom() | [any()] | {'invalid_server_response',[any(),...]}}
+http.erl:117: The pattern {'error', Reason} can never match the type #req_headers{connection::[45 | 97 | 101 | 105 | 107 | 108 | 112 | 118,...],content_length::[48,...],other::[{_,_}]}
+http.erl:138: Function close_session/2 will never be called
+http_lib.erl:286: The call http_lib:close('ip_comm' | {'ssl',_},port() | {'sslsocket',_,_}) will never return since it differs in the 1st argument from the success typing arguments: ('http' | 'https',port() | {'sslsocket',_,pid() | {_,{'config',_,_,_,_,{_,_,_,_}}} | {'sslsocket',_,pid() | {'sslsocket',_,pid() | {_,_,_}}}})
+http_lib.erl:415: The pattern 61 can never match the type 'http_eoh' | binary() | maybe_improper_list(any(),binary() | []) | {'http_error',binary() | string()} | #http_request{method::'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'POST' | 'PUT' | 'TRACE' | binary() | string(),path::'*' | binary() | string() | {'abs_path',binary() | string()} | {'scheme',binary() | string(),binary() | string()} | {'absoluteURI','http' | 'https',binary() | string(),'undefined' | non_neg_integer(),binary() | string()},version::{non_neg_integer(),non_neg_integer()}} | #http_response{version::{non_neg_integer(),non_neg_integer()},status::integer(),phrase::binary() | string()} | {'http_header',integer(),atom() | binary() | string(),_,binary() | string()}
+http_lib.erl:417: The pattern 59 can never match the type 'http_eoh' | binary() | maybe_improper_list(any(),binary() | []) | {'http_error',binary() | string()} | #http_request{method::'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'POST' | 'PUT' | 'TRACE' | binary() | string(),path::'*' | binary() | string() | {'abs_path',binary() | string()} | {'scheme',binary() | string(),binary() | string()} | {'absoluteURI','http' | 'https',binary() | string(),'undefined' | non_neg_integer(),binary() | string()},version::{non_neg_integer(),non_neg_integer()}} | #http_response{version::{non_neg_integer(),non_neg_integer()},status::integer(),phrase::binary() | string()} | {'http_header',integer(),atom() | binary() | string(),_,binary() | string()}
+http_lib.erl:420: The pattern 13 can never match the type 'http_eoh' | binary() | maybe_improper_list(any(),binary() | []) | {'http_error',binary() | string()} | #http_request{method::'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'POST' | 'PUT' | 'TRACE' | binary() | string(),path::'*' | binary() | string() | {'abs_path',binary() | string()} | {'scheme',binary() | string(),binary() | string()} | {'absoluteURI','http' | 'https',binary() | string(),'undefined' | non_neg_integer(),binary() | string()},version::{non_neg_integer(),non_neg_integer()}} | #http_response{version::{non_neg_integer(),non_neg_integer()},status::integer(),phrase::binary() | string()} | {'http_header',integer(),atom() | binary() | string(),_,binary() | string()}
+http_lib.erl:424: The variable _ can never match since previous clauses completely covered the type 'http_eoh' | binary() | maybe_improper_list(any(),binary() | []) | {'http_error',binary() | string()} | #http_request{method::'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'POST' | 'PUT' | 'TRACE' | binary() | string(),path::'*' | binary() | string() | {'abs_path',binary() | string()} | {'scheme',binary() | string(),binary() | string()} | {'absoluteURI','http' | 'https',binary() | string(),'undefined' | non_neg_integer(),binary() | string()},version::{non_neg_integer(),non_neg_integer()}} | #http_response{version::{non_neg_integer(),non_neg_integer()},status::integer(),phrase::binary() | string()} | {'http_header',integer(),atom() | binary() | string(),_,binary() | string()}
+http_lib.erl:428: Function read_chunk_ext_val/6 will never be called
+http_lib.erl:444: The pattern 10 can never match the type 'http_eoh' | binary() | maybe_improper_list(any(),binary() | []) | {'http_error',binary() | string()} | #http_request{method::'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'POST' | 'PUT' | 'TRACE' | binary() | string(),path::'*' | binary() | string() | {'abs_path',binary() | string()} | {'scheme',binary() | string(),binary() | string()} | {'absoluteURI','http' | 'https',binary() | string(),'undefined' | non_neg_integer(),binary() | string()},version::{non_neg_integer(),non_neg_integer()}} | #http_response{version::{non_neg_integer(),non_neg_integer()},status::integer(),phrase::binary() | string()} | {'http_header',integer(),atom() | binary() | string(),_,binary() | string()}
+http_lib.erl:552: Call to missing or unexported function ssl:accept/2
+http_lib.erl:99: Function getHeaderValue/2 will never be called
+httpc_handler.erl:660: Function exit_session_ok/2 has no local return
+httpc_manager.erl:145: The pattern {ErrorReply, State2} can never match the type {{'ok',number()},number(),#state{reqid::number()}}
+httpc_manager.erl:160: The pattern {ErrorReply, State2} can never match the type {{'ok',number()},number(),#state{reqid::number()}}
+httpc_manager.erl:478: The pattern {'error', Reason} can never match the type 'ok' | {number(),#session{clientclose::boolean(),pipeline::[],quelength::1}}
+httpc_manager.erl:490: The pattern {'error', Reason} can never match the type 'ok' | {number(),#session{clientclose::boolean(),pipeline::[],quelength::1}}
+httpd.erl:583: The pattern <{'error', Reason}, _Fd, SoFar> can never match the type <[any()],pid(),[[any(),...]]>
+httpd_acceptor.erl:105: The pattern {'error', Reason} can never match the type {'ok',pid()}
+httpd_acceptor.erl:110: Function handle_connection_err/4 will never be called
+httpd_acceptor.erl:168: Function report_error/2 will never be called
+httpd_acceptor.erl:91: The call httpd_acceptor:handle_error({'EXIT',_},ConfigDb::any(),SocketType::any()) will never return since it differs in the 1st argument from the success typing arguments: ('econnaborted' | 'emfile' | 'esslaccept' | 'timeout' | {'enfile',_},any(),any())
+httpd_manager.erl:885: The pattern {'EXIT', Reason} can never match since previous clauses completely covered the type any()
+httpd_manager.erl:919: Function auth_status/1 will never be called
+httpd_manager.erl:926: Function sec_status/1 will never be called
+httpd_manager.erl:933: Function acceptor_status/1 will never be called
+httpd_request_handler.erl:374: The call httpd_response:send_status(Info::#mod{parsed_header::maybe_improper_list()},417,[32 | 66 | 98 | 100 | 103 | 105 | 111 | 116 | 121,...]) will never return since it differs in the 2nd argument from the success typing arguments: (#mod{socket_type::'ip_comm' | {'ssl',_},socket::port() | {'sslsocket',_,_}},100 | 301 | 304 | 400 | 401 | 403 | 404 | 412 | 414 | 416 | 500 | 501 | 503,any())
+httpd_request_handler.erl:378: The call httpd_response:send_status(Info::#mod{parsed_header::maybe_improper_list()},417,[32 | 77 | 97 | 100 | 101 | 104 | 108 | 110 | 111 | 116 | 119,...]) will never return since it differs in the 2nd argument from the success typing arguments: (#mod{socket_type::'ip_comm' | {'ssl',_},socket::port() | {'sslsocket',_,_}},100 | 301 | 304 | 400 | 401 | 403 | 404 | 412 | 414 | 416 | 500 | 501 | 503,any())
+httpd_request_handler.erl:401: The call httpd_response:send_status(Info::#mod{parsed_header::maybe_improper_list()},417,[32 | 77 | 97 | 100 | 101 | 104 | 108 | 110 | 111 | 116 | 119,...]) will never return since it differs in the 2nd argument from the success typing arguments: (#mod{socket_type::'ip_comm' | {'ssl',_},socket::port() | {'sslsocket',_,_}},100 | 301 | 304 | 400 | 401 | 403 | 404 | 412 | 414 | 416 | 500 | 501 | 503,any())
+httpd_request_handler.erl:489: The variable Other can never match since previous clauses completely covered the type {'error',_} | {'ok','http_eoh' | binary() | maybe_improper_list(any(),binary() | []) | {'http_error',binary() | string()} | {'http_request','DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'POST' | 'PUT' | 'TRACE' | binary() | string(),'*' | binary() | string() | {'abs_path',binary() | [any()]} | {'scheme',binary() | [any()],binary() | [any()]} | {'absoluteURI','http' | 'https',binary() | [any()],'undefined' | non_neg_integer(),binary() | [any()]},{non_neg_integer(),non_neg_integer()}} | {'http_response',{non_neg_integer(),non_neg_integer()},integer(),binary() | string()} | {'http_header',integer(),atom() | binary() | string(),_,binary() | string()}}
+httpd_request_handler.erl:644: The call lists:reverse(Fields0::{'error',_} | {'ok',_}) will never return since it differs in the 1st argument from the success typing arguments: ([any()])
+httpd_request_handler.erl:645: Function will never be called
+httpd_socket.erl:129: Call to missing or unexported function ssl:accept/2
+httpd_socket.erl:49: The pattern {'ok', _} can never match the type {'error',_}
+httpd_sup.erl:63: The variable Else can never match since previous clauses completely covered the type {'error',_} | {'ok',[any()],_,_}
+httpd_sup.erl:88: The pattern {'error', Reason} can never match the type {'ok',_,_}
+httpd_sup.erl:92: The variable Else can never match since previous clauses completely covered the type {'ok',_,_}
+mod_auth.erl:559: The pattern {'error', Reason} can never match the type {_,integer(),maybe_improper_list(),_}
+mod_auth_dets.erl:120: The call lists:foreach(fun((_) -> 'true' | {'error','no_such_group' | 'no_such_group_member'}),{'ok',[any()]}) will never return since it differs in the 2nd argument from the success typing arguments: (fun((_) -> any()),[any()])
+mod_auth_plain.erl:100: The variable _ can never match since previous clauses completely covered the type {'ok',[any()]}
+mod_auth_plain.erl:159: The variable _ can never match since previous clauses completely covered the type [any()]
+mod_auth_plain.erl:83: The variable O can never match since previous clauses completely covered the type [any()]
+mod_cgi.erl:372: The pattern {'http_response', NewAccResponse} can never match the type 'ok'
+mod_dir.erl:101: The call lists:flatten(nonempty_improper_list(atom() | [any()] | char(),atom())) will never return since it differs in the 1st argument from the success typing arguments: ([any()])
+mod_dir.erl:72: The pattern {'error', Reason} can never match the type {'ok',[[[any()] | char()],...]}
+mod_get.erl:135: The pattern <{'enfile', _}, _Info, Path> can never match the type <atom(),#mod{},atom() | binary() | [atom() | [any()] | char()]>
+mod_head.erl:80: The pattern <{'enfile', _}, _Info, Path> can never match the type <atom(),#mod{},atom() | binary() | [atom() | [any()] | char()]>
+mod_htaccess.erl:460: The pattern {'error', BadData} can never match the type {'ok',_}
+mod_include.erl:193: The pattern {_, Name, {[], []}} can never match the type {[any()],[any()],string()}
+mod_include.erl:195: The pattern {_, Name, {PathInfo, []}} can never match the type {[any()],[any()],string()}
+mod_include.erl:197: The pattern {_, Name, {PathInfo, QueryString}} can never match the type {[any()],[any()],string()}
+mod_include.erl:201: The variable Gurka can never match since previous clauses completely covered the type {[any()],[any()],string()}
+mod_include.erl:692: The pattern <{'read', Reason}, Info, Path> can never match the type <{'open',atom()},#mod{},atom() | binary() | [atom() | [any()] | char()]>
+mod_include.erl:706: The pattern <{'enfile', _}, _Info, Path> can never match the type <atom(),#mod{},atom() | binary() | [atom() | [any()] | char()]>
+mod_include.erl:716: Function read_error/3 will never be called
+mod_include.erl:719: Function read_error/4 will never be called
+mod_security_server.erl:386: The variable O can never match since previous clauses completely covered the type [any()]
+mod_security_server.erl:433: The variable Other can never match since previous clauses completely covered the type [any()]
+mod_security_server.erl:585: The variable _ can never match since previous clauses completely covered the type [any()]
+mod_security_server.erl:608: The variable _ can never match since previous clauses completely covered the type [any()]
+mod_security_server.erl:641: The variable _ can never match since previous clauses completely covered the type [any()]
+uri.erl:146: The pattern {'error', Error} can never match since previous clauses completely covered the type {_,{[],[]}}
diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia
new file mode 100644
index 0000000000..2be71ac7d7
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia
@@ -0,0 +1,37 @@
+
+mnesia.erl:1319: Guard test size(Spec::[{_,_,_},...]) can never succeed
+mnesia.erl:1498: The call mnesia:bad_info_reply(Tab::atom(),Item::'type') will never return since it differs in the 2nd argument from the success typing arguments: (atom(),'memory' | 'size')
+mnesia.erl:331: Function mod2abs/1 has no local return
+mnesia_bup.erl:111: The created fun has no local return
+mnesia_bup.erl:574: Function fallback_receiver/2 has no local return
+mnesia_bup.erl:967: Function uninstall_fallback_master/2 has no local return
+mnesia_checkpoint.erl:1014: The variable Error can never match since previous clauses completely covered the type {'ok',#checkpoint_args{nodes::[any()],retainers::[any(),...]}}
+mnesia_checkpoint.erl:894: The call sys:handle_system_msg(Msg::any(),From::any(),'no_parent','mnesia_checkpoint',[],Cp::#checkpoint_args{}) breaks the contract (Msg,From,Parent,Module,Debug,Misc) -> Void when is_subtype(Msg,term()), is_subtype(From,{pid(),Tag::_}), is_subtype(Parent,pid()), is_subtype(Module,module()), is_subtype(Debug,[dbg_opt()]), is_subtype(Misc,term()), is_subtype(Void,term())
+mnesia_controller.erl:1666: The variable Tab can never match since previous clauses completely covered the type [any()]
+mnesia_controller.erl:1679: The pattern {'stop', Reason, Reply, State2} can never match the type {'noreply',_} | {'reply',_,_} | {'stop','shutdown',#state{}}
+mnesia_controller.erl:1685: The pattern {'noreply', State2, _Timeout} can never match the type {'reply',_,_}
+mnesia_event.erl:77: The pattern 'remove_handler' can never match the type {'ok',_}
+mnesia_event.erl:79: The pattern {'swap_handler', Args1, State1, Mod2, Args2} can never match the type {'ok',_}
+mnesia_frag.erl:294: The call mnesia_frag:remote_collect(Ref::reference(),{'error',_},[],OldSelectFun::fun(() -> [any()])) will never return since it differs in the 2nd argument from the success typing arguments: (reference(),'ok',[any()],fun(() -> [any()]))
+mnesia_frag.erl:304: The call mnesia_frag:remote_collect(Ref::reference(),{'error',{'node_not_running',_}},[],OldSelectFun::fun(() -> [any()])) will never return since it differs in the 2nd argument from the success typing arguments: (reference(),'ok',[any()],fun(() -> [any()]))
+mnesia_frag.erl:312: The call mnesia_frag:remote_collect(Ref::reference(),LocalRes::{'error',_},[],OldSelectFun::fun(() -> [any()])) will never return since it differs in the 2nd argument from the success typing arguments: (reference(),'ok',[any()],fun(() -> [any()]))
+mnesia_index.erl:52: The call mnesia_lib:other_val(Var::{_,'commit_work' | 'index' | 'setorbag' | 'storage_type' | {'index',_}},_ReASoN_::any()) will never return since it differs in the 1st argument from the success typing arguments: ({_,'active_replicas' | 'where_to_read' | 'where_to_write'},any())
+mnesia_lib.erl:1028: The pattern {'EXIT', Reason} can never match the type [any()] | {'error',_}
+mnesia_lib.erl:957: The pattern {'ok', {0, _}} can never match the type 'eof' | {'error',atom()} | {'ok',binary() | string()}
+mnesia_lib.erl:959: The pattern {'ok', {_, Bin}} can never match the type 'eof' | {'error',atom()} | {'ok',binary() | string()}
+mnesia_loader.erl:36: The call mnesia_lib:other_val(Var::{_,'access_mode' | 'cstruct' | 'db_nodes' | 'setorbag' | 'snmp' | 'storage_type'},Reason::any()) will never return since it differs in the 1st argument from the success typing arguments: ({_,'active_replicas' | 'where_to_read' | 'where_to_write'},any())
+mnesia_locker.erl:1017: Function system_terminate/4 has no local return
+mnesia_log.erl:707: The test {'error',{[1..255,...],[any(),...]}} | {'ok',_} == atom() can never evaluate to 'true'
+mnesia_log.erl:727: The created fun has no local return
+mnesia_monitor.erl:162: The pattern <[], []> can never match the type <[any(),...],[any(),...]>
+mnesia_monitor.erl:354: The pattern {'error', Reason} can never match the type 'ok'
+mnesia_recover.erl:159: The call mnesia_lib:other_val(Var::'latest_transient_decision' | 'max_wait_for_decision' | 'previous_transient_decisions' | 'recover_nodes',Reason::any()) will never return since it differs in the 1st argument from the success typing arguments: ({_,'active_replicas' | 'where_to_read' | 'where_to_write'},any())
+mnesia_recover.erl:884: The pattern {'stop', Reason, Reply, State2} can never match the type {'noreply',_} | {'stop','shutdown',#state{}}
+mnesia_schema.erl:1088: Guard test Storage::'disc_copies' | 'disc_only_copies' | 'ram_copies' == 'unknown' can never succeed
+mnesia_schema.erl:1258: Guard test FromS::'disc_copies' | 'disc_only_copies' | 'ram_copies' == 'unknown' can never succeed
+mnesia_schema.erl:1639: The pattern {'false', 'mandatory'} can never match the type {'false','optional'}
+mnesia_schema.erl:2434: The variable Reason can never match since previous clauses completely covered the type {'error',_} | {'ok',_}
+mnesia_schema.erl:451: Guard test UseDirAnyway::'false' == 'true' can never succeed
+mnesia_text.erl:180: The variable T can never match since previous clauses completely covered the type {'error',{integer(),atom() | tuple(),_}} | {'ok',_}
+mnesia_tm.erl:1522: Function commit_participant/5 has no local return
+mnesia_tm.erl:2169: Function system_terminate/4 has no local return
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/Makefile b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/Makefile
new file mode 100644
index 0000000000..9dba643327
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/Makefile
@@ -0,0 +1,142 @@
+#
+# Copyright (C) 1997, Ericsson Telecommunications
+# Author: Kenneth Lundin
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+VSN=$(ASN1_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/asn1-$(VSN)
+
+
+
+
+#
+# Common Macros
+#
+# PARSER_SRC = \
+# asn1ct_parser.yrl
+
+# PARSER_MODULE=$(PARSER_SRC:%.yrl=%)
+
+EBIN = ../ebin
+CT_MODULES= \
+ asn1ct \
+ asn1ct_check \
+ asn1_db \
+ asn1ct_pretty_format \
+ asn1ct_gen \
+ asn1ct_gen_per \
+ asn1ct_gen_per_rt2ct \
+ asn1ct_name \
+ asn1ct_constructed_per \
+ asn1ct_constructed_ber \
+ asn1ct_gen_ber \
+ asn1ct_constructed_ber_bin_v2 \
+ asn1ct_gen_ber_bin_v2 \
+ asn1ct_value \
+ asn1ct_tok \
+ asn1ct_parser2
+
+RT_MODULES= \
+ asn1rt \
+ asn1rt_per \
+ asn1rt_per_bin \
+ asn1rt_per_v1 \
+ asn1rt_ber_bin \
+ asn1rt_ber_bin_v2 \
+ asn1rt_per_bin_rt2ct \
+ asn1rt_driver_handler \
+ asn1rt_check
+
+# asn1rt_ber_v1 \
+# asn1rt_ber \
+# the rt module to use is defined in asn1_records.hrl
+# and must be updated when an incompatible change is done in the rt modules
+
+
+MODULES= $(CT_MODULES) $(RT_MODULES)
+
+ERL_FILES = $(MODULES:%=%.erl)
+
+TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+GENERATED_PARSER = $(PARSER_MODULE:%=%.erl)
+
+# internal hrl file
+HRL_FILES = asn1_records.hrl
+
+APP_FILE = asn1.app
+APPUP_FILE = asn1.appup
+
+APP_SRC = $(APP_FILE).src
+APP_TARGET = $(EBIN)/$(APP_FILE)
+
+APPUP_SRC = $(APPUP_FILE).src
+APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
+
+EXAMPLES = \
+ ../examples/P-Record.asn
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ERL_FLAGS +=
+ERL_COMPILE_FLAGS += \
+ -I$(ERL_TOP)/lib/stdlib \
+ +warn_unused_vars
+YRL_FLAGS =
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+
+
+clean:
+ rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(GENERATED_PARSER)
+ rm -f core *~
+
+docs:
+
+
+# ----------------------------------------------------
+# Special Build Targets
+# ----------------------------------------------------
+
+$(EBIN)/asn1ct.$(EMULATOR):asn1ct.erl
+ $(ERLC) -b$(EMULATOR) -o$(EBIN) $(ERL_COMPILE_FLAGS) -Dvsn=\"$(VSN)\" $<
+
+$(APP_TARGET): $(APP_SRC) ../vsn.mk
+ sed -e 's;%VSN%;$(VSN);' $< > $@
+
+$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
+ sed -e 's;%VSN%;$(VSN);' $< > $@
+
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) $(RELSYSDIR)/src
+ $(INSTALL_DATA) $(PARSER_SRC) $(ERL_FILES) $(HRL_FILES) $(APP_SRC) $(APPUP_SRC) $(RELSYSDIR)/src
+ $(INSTALL_DIR) $(RELSYSDIR)/examples
+ $(INSTALL_DATA) $(EXAMPLES) $(RELSYSDIR)/examples
+
+# there are no include files to be used by the user
+#$(INSTALL_DIR) $(RELSYSDIR)/include
+#$(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include
+
+release_docs_spec:
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/Restrictions.txt b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/Restrictions.txt
new file mode 100644
index 0000000000..d1d1855dc9
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/Restrictions.txt
@@ -0,0 +1,55 @@
+The following restrictions apply to this implementation of the ASN.1 compiler:
+
+Supported encoding rules are:
+BER
+PER (aligned)
+
+PER (unaligned) IS NOT SUPPORTED
+
+Supported types are:
+
+INTEGER
+BOOLEAN
+ENUMERATION
+SEQUENCE
+SEQUENCE OF
+SET
+SET OF
+CHOICE
+OBJECT IDENTIFIER
+RestrictedCharacterStringTypes
+UnrestrictedCharacterStringTypes
+
+
+NOT SUPPORTED types are:
+ANY IS (IS NOT IN THE STANDARD ANY MORE)
+ANY DEFINED BY (IS NOT IN THE STANDARD ANY MORE)
+EXTERNAL
+EMBEDDED-PDV
+REAL
+
+The support for value definitions in the ASN.1 notation is very limited.
+
+The support for constraints is limited to:
+SizeConstraint SIZE(X)
+SingleValue (1)
+ValueRange (X..Y)
+PermittedAlpabet FROM
+
+The only supported value-notation for SEQUENCE and SET in Erlang is
+the record variant.
+The list notation with named components used by the old ASN.1 compiler
+was supported in the first versions of this compiler both are no longer
+supported.
+
+The decode functions always return a symbolic value if they can.
+
+
+Files with ASN.1 source must have a suffix .asn1 the suffix .py used by the
+old ASN.1 compiler is supported in this version but will not be supported in the future.
+
+Generated files:
+X.asn1db % the intermediate format of a compiled ASN.1 module
+X.hrl % generated Erlang include file for module X
+X.erl % generated Erlang module with encode decode functions for
+ % ASN.1 module X
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1.app.src b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1.app.src
index 2ec06ff4db..2ec06ff4db 100644
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1.app.src
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1.app.src
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1.appup.src b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1.appup.src
new file mode 100644
index 0000000000..55ef53994a
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1.appup.src
@@ -0,0 +1,162 @@
+{"%VSN%",
+ [
+ {"1.3",
+ [
+ {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
+ {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
+ {load_module, asn1rt, soft_purge, soft_purge, []},
+ {add_module, asn1rt_per_bin},
+ {add_module, asn1rt_check}
+ {add_module, asn1rt_per_bin_rt2ct},
+ {add_module, asn1rt_ber_bin_v2},
+ {add_module, asn1rt_driver_handler}
+ {remove, {asn1rt_ber_v1, soft_purge, soft_purge}},
+ ]
+ },
+ {"1.3.1",
+ [
+ {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
+ {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
+ {load_module, asn1rt, soft_purge, soft_purge, []},
+ {add_module, asn1rt_per_bin},
+ {add_module, asn1rt_check}
+ {add_module, asn1rt_per_bin_rt2ct},
+ {add_module, asn1rt_ber_bin_v2},
+ {add_module, asn1rt_driver_handler}
+ {remove, {asn1rt_ber_v1, soft_purge, soft_purge}},
+ ]
+ },
+ {"1.3.1.1",
+ [
+ {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
+ {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
+ {load_module, asn1rt, soft_purge, soft_purge, []},
+ {add_module, asn1rt_per_bin},
+ {add_module, asn1rt_check}
+ {add_module, asn1rt_per_bin_rt2ct},
+ {add_module, asn1rt_ber_bin_v2},
+ {add_module, asn1rt_driver_handler}
+ {remove, {asn1rt_ber_v1, soft_purge, soft_purge}},
+ ]
+ },
+ {"1.3.2",
+ [
+ {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
+ {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
+ {load_module, asn1rt, soft_purge, soft_purge, []},
+ {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
+ {load_module, asn1rt_check, soft_purge, soft_purge, []},
+ {add_module, asn1rt_per_bin_rt2ct},
+ {add_module, asn1rt_ber_bin_v2},
+ {add_module, asn1rt_driver_handler}
+ {remove, {asn1rt_ber_v1, soft_purge, soft_purge}},
+ ]
+ },
+ {"1.3.3",
+ [
+ {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
+ {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
+ {load_module, asn1rt, soft_purge, soft_purge, []},
+ {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
+ {load_module, asn1rt_check, soft_purge, soft_purge, []},
+ {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []},
+ {add_module, asn1rt_ber_bin_v2},
+ {add_module, asn1rt_driver_handler}
+ {remove, {asn1rt_ber_v1, soft_purge, soft_purge}},
+ ]
+ },
+ {"1.3.3.1",
+ [
+ {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
+ {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
+ {load_module, asn1rt, soft_purge, soft_purge, []},
+ {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
+ {load_module, asn1rt_check, soft_purge, soft_purge, []},
+ {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []},
+ {add_module, asn1rt_ber_bin_v2},
+ {add_module, asn1rt_driver_handler}
+ {remove, {asn1rt_ber_v1, soft_purge, soft_purge}},
+ ]
+ }
+ ],
+ [
+ {"1.3",
+ [
+ {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
+ {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
+ {load_module, asn1rt, soft_purge, soft_purge, []},
+ {add_module, asn1rt_ber_v1},
+ {remove, {asn1rt_per_bin, soft_purge, soft_purge}},
+ {remove, {asn1rt_check, soft_purge, soft_purge}}
+ {remove, {asn1rt_per_bin_rt2ct, soft_purge, soft_purge}},
+ {remove, {asn1rt_ber_bin_v2, soft_purge, soft_purge}},
+ {remove, {asn1rt_driver_handler, soft_purge, soft_purge}}
+ ]
+ },
+ {"1.3.1",
+ [
+ {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
+ {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
+ {load_module, asn1rt, soft_purge, soft_purge, []},
+ {add_module, asn1rt_ber_v1},
+ {remove, {asn1rt_per_bin, soft_purge, soft_purge}},
+ {remove, {asn1rt_check, soft_purge, soft_purge}}
+ {remove, {asn1rt_per_bin_rt2ct, soft_purge, soft_purge}},
+ {remove, {asn1rt_ber_bin_v2, soft_purge, soft_purge}},
+ {remove, {asn1rt_driver_handler, soft_purge, soft_purge}}
+ ]
+ },
+ {"1.3.1.1",
+ [
+ {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
+ {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
+ {load_module, asn1rt, soft_purge, soft_purge, []},
+ {add_module, asn1rt_ber_v1},
+ {remove, {asn1rt_per_bin, soft_purge, soft_purge}},
+ {remove, {asn1rt_check, soft_purge, soft_purge}}
+ {remove, {asn1rt_per_bin_rt2ct, soft_purge, soft_purge}},
+ {remove, {asn1rt_ber_bin_v2, soft_purge, soft_purge}},
+ {remove, {asn1rt_driver_handler, soft_purge, soft_purge}}
+ ]
+ },
+ {"1.3.2",
+ [
+ {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
+ {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
+ {load_module, asn1rt, soft_purge, soft_purge, []},
+ {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
+ {load_module, asn1rt_check, soft_purge, soft_purge, []},
+ {add_module, asn1rt_ber_v1},
+ {remove, {asn1rt_per_bin_rt2ct, soft_purge, soft_purge}},
+ {remove, {asn1rt_ber_bin_v2, soft_purge, soft_purge}},
+ {remove, {asn1rt_driver_handler, soft_purge, soft_purge}}
+ ]
+ },
+ {"1.3.3",
+ [
+ {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
+ {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
+ {load_module, asn1rt, soft_purge, soft_purge, []},
+ {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
+ {load_module, asn1rt_check, soft_purge, soft_purge, []},
+ {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []},
+ {add_module, asn1rt_ber_v1},
+ {remove, {asn1rt_ber_bin_v2, soft_purge, soft_purge}},
+ {remove, {asn1rt_driver_handler, soft_purge, soft_purge}}
+ ]
+ },
+ {"1.3.3.1",
+ [
+ {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
+ {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
+ {load_module, asn1rt, soft_purge, soft_purge, []},
+ {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
+ {load_module, asn1rt_check, soft_purge, soft_purge, []},
+ {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []},
+ {add_module, asn1rt_ber_v1},
+ {remove, {asn1rt_ber_bin_v2, soft_purge, soft_purge}},
+ {remove, {asn1rt_driver_handler, soft_purge, soft_purge}}
+ ]
+ }
+
+ ]}.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1_db.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1_db.erl
new file mode 100644
index 0000000000..d5ddb9582b
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1_db.erl
@@ -0,0 +1,160 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1_db.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
+%%
+-module(asn1_db).
+%-compile(export_all).
+-export([dbnew/1,dbsave/2,dbload/1,dbput/3,dbget/2,dbget_all/1]).
+-export([dbget_all_mod/1,dbstop/0,dbclear/0,dberase_module/1,dbstart/1,stop_server/1]).
+%% internal exports
+-export([dbloop0/1,dbloop/2]).
+
+%% Db stuff
+dbstart(Includes) ->
+ start_server(asn1db, asn1_db, dbloop0, [Includes]).
+
+dbloop0(Includes) ->
+ dbloop(Includes, ets:new(asn1, [set,named_table])).
+
+opentab(Tab,Mod,[]) ->
+ opentab(Tab,Mod,["."]);
+opentab(Tab,Mod,Includes) ->
+ Base = lists:concat([Mod,".asn1db"]),
+ opentab2(Tab,Base,Mod,Includes,ok).
+
+opentab2(_Tab,_Base,_Mod,[],Error) ->
+ Error;
+opentab2(Tab,Base,Mod,[Ih|It],_Error) ->
+ File = filename:join(Ih,Base),
+ case ets:file2tab(File) of
+ {ok,Modtab} ->
+ ets:insert(Tab,{Mod, Modtab}),
+ {ok,Modtab};
+ NewErr ->
+ opentab2(Tab,Base,Mod,It,NewErr)
+ end.
+
+
+dbloop(Includes, Tab) ->
+ receive
+ {From,{set, Mod, K2, V}} ->
+ [{_,Modtab}] = ets:lookup(Tab,Mod),
+ ets:insert(Modtab,{K2, V}),
+ From ! {asn1db, ok},
+ dbloop(Includes, Tab);
+ {From, {get, Mod, K2}} ->
+ Result = case ets:lookup(Tab,Mod) of
+ [] ->
+ opentab(Tab,Mod,Includes);
+ [{_,Modtab}] -> {ok,Modtab}
+ end,
+ case Result of
+ {ok,Newtab} ->
+ From ! {asn1db, lookup(Newtab, K2)};
+ _Error ->
+ From ! {asn1db, undefined}
+ end,
+ dbloop(Includes, Tab);
+ {From, {all_mod, Mod}} ->
+ [{_,Modtab}] = ets:lookup(Tab,Mod),
+ From ! {asn1db, ets:tab2list(Modtab)},
+ dbloop(Includes, Tab);
+ {From, {delete_mod, Mod}} ->
+ [{_,Modtab}] = ets:lookup(Tab,Mod),
+ ets:delete(Modtab),
+ ets:delete(Tab,Mod),
+ From ! {asn1db, ok},
+ dbloop(Includes, Tab);
+ {From, {save, OutFile,Mod}} ->
+ [{_,Mtab}] = ets:lookup(Tab,Mod),
+ {From ! {asn1db, ets:tab2file(Mtab,OutFile)}},
+ dbloop(Includes,Tab);
+ {From, {load, Mod}} ->
+ Result = case ets:lookup(Tab,Mod) of
+ [] ->
+ opentab(Tab,Mod,Includes);
+ [{_,Modtab}] -> {ok,Modtab}
+ end,
+ {From, {asn1db,Result}},
+ dbloop(Includes,Tab);
+ {From, {new, Mod}} ->
+ case ets:lookup(Tab,Mod) of
+ [{_,Modtab}] ->
+ ets:delete(Modtab);
+ _ ->
+ true
+ end,
+ Tabname = list_to_atom(lists:concat(["asn1_",Mod])),
+ ets:new(Tabname, [set,named_table]),
+ ets:insert(Tab,{Mod,Tabname}),
+ From ! {asn1db, ok},
+ dbloop(Includes,Tab);
+ {From, stop} ->
+ From ! {asn1db, ok}; %% nothing to store
+ {From, clear} ->
+ ModTabList = [Mt||{_,Mt} <- ets:tab2list(Tab)],
+ lists:foreach(fun(T) -> ets:delete(T) end,ModTabList),
+ ets:delete(Tab),
+ From ! {asn1db, cleared},
+ dbloop(Includes, ets:new(asn1, [set]))
+ end.
+
+
+%%all(Tab, K) ->
+%% pickup(K, ets:match(Tab, {{K, '$1'}, '$2'})).
+%%pickup(K, []) -> [];
+%%pickup(K, [[V1,V2] |T]) ->
+%% [{{K,V1},V2} | pickup(K, T)].
+
+lookup(Tab, K) ->
+ case ets:lookup(Tab, K) of
+ [] -> undefined;
+ [{K,V}] -> V
+ end.
+
+
+dbnew(Module) -> req({new,Module}).
+dbsave(OutFile,Module) -> req({save,OutFile,Module}).
+dbload(Module) -> req({load,Module}).
+
+dbput(Module,K,V) -> req({set, Module, K, V}).
+dbget(Module,K) -> req({get, Module, K}).
+dbget_all(K) -> req({get_all, K}).
+dbget_all_mod(Mod) -> req({all_mod,Mod}).
+dbstop() -> stop_server(asn1db).
+dbclear() -> req(clear).
+dberase_module({module,M})->
+ req({delete_mod, M}).
+
+req(R) ->
+ asn1db ! {self(), R},
+ receive {asn1db, Reply} -> Reply end.
+
+stop_server(Name) ->
+ stop_server(Name, whereis(Name)).
+stop_server(_, undefined) -> stopped;
+stop_server(Name, _Pid) ->
+ Name ! {self(), stop},
+ receive {Name, _} -> stopped end.
+
+
+start_server(Name,Mod,Fun,Args) ->
+ case whereis(Name) of
+ undefined ->
+ register(Name, spawn(Mod,Fun, Args));
+ _Pid ->
+ already_started
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1_records.hrl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1_records.hrl
new file mode 100644
index 0000000000..6ba4877523
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1_records.hrl
@@ -0,0 +1,96 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1_records.hrl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
+%%
+-define('RT_BER',"asn1rt_ber_v1").
+-define('RT_BER_BIN',"asn1rt_ber_bin").
+-define('RT_PER',"asn1rt_per_v1").
+%% change to this when we have this module -define('RT_PER_BIN',"asn1rt_per_bin").
+-define('RT_PER_BIN',"asn1rt_per_bin").
+
+-record(module,{pos,name,defid,tagdefault='EXPLICIT',exports={exports,[]},imports={imports,[]}, extensiondefault=empty,typeorval}).
+
+-record('SEQUENCE',{pname=false,tablecinf=false,components=[]}).
+-record('SET',{pname=false,sorted=false,tablecinf=false,components=[]}).
+-record('ComponentType',{pos,name,typespec,prop,tags}).
+-record('ObjectClassFieldType',{classname,class,fieldname,type}).
+
+-record(typedef,{checked=false,pos,name,typespec}).
+-record(classdef,{checked=false,pos,name,typespec}).
+-record(valuedef,{checked=false,pos,name,type,value}).
+-record(ptypedef,{checked=false,pos,name,args,typespec}).
+-record(pvaluedef,{checked=false,pos,name,args,type,value}).
+-record(pvaluesetdef,{checked=false,pos,name,args,type,valueset}).
+-record(pobjectdef,{checked=false,pos,name,args,class,def}).
+-record(pobjectsetdef,{checked=false,pos,name,args,class,def}).
+
+-record(typereference,{pos,val}).
+-record(identifier,{pos,val}).
+-record(constraint,{c,e}).
+-record('Constraint',{'SingleValue'=no,'SizeConstraint'=no,'ValueRange'=no,'PermittedAlphabet'=no,
+ 'ContainedSubtype'=no, 'TypeConstraint'=no,'InnerSubtyping'=no,e=no,'Other'=no}).
+-record(simpletableattributes,{objectsetname,c_name,c_index,usedclassfield,
+ uniqueclassfield,valueindex}).
+-record(type,{tag=[],def,constraint=[],tablecinf=[],inlined=no}).
+
+-record(objectclass,{fields=[],syntax}).
+-record('Object',{classname,gen=true,def}).
+-record('ObjectSet',{class,gen=true,uniquefname,set}).
+
+-record(tag,{class,number,type,form=32}). % form = ?CONSTRUCTED
+% This record holds information about allowed constraint types per type
+-record(cmap,{single_value=no,contained_subtype=no,value_range=no,
+ size=no,permitted_alphabet=no,type_constraint=no,
+ inner_subtyping=no}).
+
+
+-record('EXTENSIONMARK',{pos,val}).
+
+% each IMPORT contains a list of 'SymbolsFromModule'
+-record('SymbolsFromModule',{symbols,module,objid}).
+
+% Externaltypereference -> modulename '.' typename
+-record('Externaltypereference',{pos,module,type}).
+% Externalvaluereference -> modulename '.' typename
+-record('Externalvaluereference',{pos,module,value}).
+
+-record(state,{module,mname,type,tname,value,vname,erule,parameters=[],
+ inputmodules,abscomppath=[],recordtopname=[],options}).
+
+%% state record used by backend at partial decode
+%% active is set to 'yes' when a partial decode function is generated.
+%% prefix is set to 'dec-inc-' or 'dec-partial-' is for
+%% incomplete partial decode or partial decode respectively
+%% inc_tag_pattern holds the tags of the significant types/components
+%% for incomplete partial decode.
+%% tag_pattern holds the tags for partial decode.
+%% inc_type_pattern and type_pattern holds the names of the
+%% significant types/components.
+%% func_name holds the name of the function for the toptype.
+%% namelist holds the list of names of types/components that still
+%% haven't been generated.
+%% tobe_refed_funcs is a list of tuples {function names
+%% (Types),namelist of incomplete decode spec}, with function names
+%% that are referenced within other generated partial incomplete
+%% decode functions. They shall be generated as partial incomplete
+%% decode functions.
+
+%% gen_refed_funcs is as list of function names. Unlike
+%% tobe_refed_funcs these have been generated.
+-record(gen_state,{active=false,prefix,inc_tag_pattern,
+ tag_pattern,inc_type_pattern,
+ type_pattern,func_name,namelist,
+ tobe_refed_funcs=[],gen_refed_funcs=[]}).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct.erl
new file mode 100644
index 0000000000..fd36f1657e
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct.erl
@@ -0,0 +1,1904 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1ct.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
+%%
+-module(asn1ct).
+
+%% Compile Time functions for ASN.1 (e.g ASN.1 compiler).
+
+%%-compile(export_all).
+%% Public exports
+-export([compile/1, compile/2]).
+-export([start/0, start/1, stop/0]).
+-export([encode/2, encode/3, decode/3]).
+-export([test/1, test/2, test/3, value/2]).
+%% Application internal exports
+-export([compile_asn/3,compile_asn1/3,compile_py/3,compile/3,value/1,vsn/0,
+ create_ets_table/2,get_name_of_def/1,get_pos_of_def/1]).
+-export([read_config_data/1,get_gen_state_field/1,get_gen_state/0,
+ partial_inc_dec_toptype/1,save_gen_state/1,update_gen_state/2,
+ get_tobe_refed_func/1,reset_gen_state/0,is_function_generated/1,
+ generated_refed_func/1,next_refed_func/0,pop_namelist/0,
+ next_namelist_el/0,update_namelist/1,step_in_constructed/0,
+ add_tobe_refed_func/1,add_generated_refed_func/1]).
+
+-include("asn1_records.hrl").
+-include_lib("stdlib/include/erl_compile.hrl").
+
+-import(asn1ct_gen_ber_bin_v2,[encode_tag_val/3,decode_class/1]).
+
+-define(unique_names,0).
+-define(dupl_uniquedefs,1).
+-define(dupl_equaldefs,2).
+-define(dupl_eqdefs_uniquedefs,?dupl_equaldefs bor ?dupl_uniquedefs).
+
+-define(CONSTRUCTED, 2#00100000).
+
+%% macros used for partial decode commands
+-define(CHOOSEN,choosen).
+-define(SKIP,skip).
+-define(SKIP_OPTIONAL,skip_optional).
+
+%% macros used for partial incomplete decode commands
+-define(MANDATORY,mandatory).
+-define(DEFAULT,default).
+-define(OPTIONAL,opt).
+-define(PARTS,parts).
+-define(UNDECODED,undec).
+-define(ALTERNATIVE,alt).
+-define(ALTERNATIVE_UNDECODED,alt_undec).
+-define(ALTERNATIVE_PARTS,alt_parts).
+%-define(BINARY,bin).
+
+%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% This is the interface to the compiler
+%%
+%%
+
+
+compile(File) ->
+ compile(File,[]).
+
+compile(File,Options) when list(Options) ->
+ Options1 =
+ case {lists:member(optimize,Options),lists:member(ber_bin,Options)} of
+ {true,true} ->
+ [ber_bin_v2|Options--[ber_bin]];
+ _ -> Options
+ end,
+ case (catch input_file_type(File)) of
+ {single_file,PrefixedFile} ->
+ (catch compile1(PrefixedFile,Options1));
+ {multiple_files_file,SetBase,FileName} ->
+ FileList = get_file_list(FileName),
+ (catch compile_set(SetBase,filename:dirname(FileName),
+ FileList,Options1));
+ Err = {input_file_error,_Reason} ->
+ {error,Err}
+ end.
+
+
+compile1(File,Options) when list(Options) ->
+ io:format("Erlang ASN.1 version ~p compiling ~p ~n",[?vsn,File]),
+ io:format("Compiler Options: ~p~n",[Options]),
+ Ext = filename:extension(File),
+ Base = filename:basename(File,Ext),
+ OutFile = outfile(Base,"",Options),
+ DbFile = outfile(Base,"asn1db",Options),
+ Includes = [I || {i,I} <- Options],
+ EncodingRule = get_rule(Options),
+ create_ets_table(asn1_functab,[named_table]),
+ Continue1 = scan({true,true},File,Options),
+ Continue2 = parse(Continue1,File,Options),
+ Continue3 = check(Continue2,File,OutFile,Includes,EncodingRule,
+ DbFile,Options,[]),
+ Continue4 = generate(Continue3,OutFile,EncodingRule,Options),
+ delete_tables([asn1_functab]),
+ compile_erl(Continue4,OutFile,Options).
+
+%%****************************************************************************%%
+%% functions dealing with compiling of several input files to one output file %%
+%%****************************************************************************%%
+compile_set(SetBase,DirName,Files,Options) when list(hd(Files)),list(Options) ->
+ %% case when there are several input files in a list
+ io:format("Erlang ASN.1 version ~p compiling ~p ~n",[?vsn,Files]),
+ io:format("Compiler Options: ~p~n",[Options]),
+ OutFile = outfile(SetBase,"",Options),
+ DbFile = outfile(SetBase,"asn1db",Options),
+ Includes = [I || {i,I} <- Options],
+ EncodingRule = get_rule(Options),
+ create_ets_table(asn1_functab,[named_table]),
+ ScanRes = scan_set(DirName,Files,Options),
+ ParseRes = parse_set(ScanRes,Options),
+ Result =
+ case [X||X <- ParseRes,element(1,X)==true] of
+ [] -> %% all were false, time to quit
+ lists:map(fun(X)->element(2,X) end,ParseRes);
+ ParseRes -> %% all were true, continue with check
+ InputModules =
+ lists:map(
+ fun(F)->
+ E = filename:extension(F),
+ B = filename:basename(F,E),
+ if
+ list(B) -> list_to_atom(B);
+ true -> B
+ end
+ end,
+ Files),
+ check_set(ParseRes,SetBase,OutFile,Includes,
+ EncodingRule,DbFile,Options,InputModules);
+ Other ->
+ {error,{'unexpected error in scan/parse phase',
+ lists:map(fun(X)->element(3,X) end,Other)}}
+ end,
+ delete_tables([asn1_functab]),
+ Result.
+
+check_set(ParseRes,SetBase,OutFile,Includes,EncRule,DbFile,
+ Options,InputModules) ->
+ lists:foreach(fun({_T,M,File})->
+ cmp(M#module.name,File)
+ end,
+ ParseRes),
+ MergedModule = merge_modules(ParseRes,SetBase),
+ SetM = MergedModule#module{name=SetBase},
+ Continue1 = check({true,SetM},SetBase,OutFile,Includes,EncRule,DbFile,
+ Options,InputModules),
+ Continue2 = generate(Continue1,OutFile,EncRule,Options),
+
+ delete_tables([renamed_defs,original_imports,automatic_tags]),
+
+ compile_erl(Continue2,OutFile,Options).
+
+%% merge_modules/2 -> returns a module record where the typeorval lists are merged,
+%% the exports lists are merged, the imports lists are merged when the
+%% elements come from other modules than the merge set, the tagdefault
+%% field gets the shared value if all modules have same tagging scheme,
+%% otherwise a tagging_error exception is thrown,
+%% the extensiondefault ...(not handled yet).
+merge_modules(ParseRes,CommonName) ->
+ ModuleList = lists:map(fun(X)->element(2,X) end,ParseRes),
+ NewModuleList = remove_name_collisions(ModuleList),
+ case ets:info(renamed_defs,size) of
+ 0 -> ets:delete(renamed_defs);
+ _ -> ok
+ end,
+ save_imports(NewModuleList),
+% io:format("~p~n~p~n~p~n~n",[ets:lookup(original_imports,'M1'),ets:lookup(original_imports,'M2'),ets:tab2list(original_imports)]),
+ TypeOrVal = lists:append(lists:map(fun(X)->X#module.typeorval end,
+ NewModuleList)),
+ InputMNameList = lists:map(fun(X)->X#module.name end,
+ NewModuleList),
+ CExports = common_exports(NewModuleList),
+
+ ImportsModuleNameList = lists:map(fun(X)->
+ {X#module.imports,
+ X#module.name} end,
+ NewModuleList),
+ %% ImportsModuleNameList: [{Imports,ModuleName},...]
+ %% Imports is a tuple {imports,[#'SymbolsFromModule'{},...]}
+ CImports = common_imports(ImportsModuleNameList,InputMNameList),
+ TagDefault = check_tagdefault(NewModuleList),
+ #module{name=CommonName,tagdefault=TagDefault,exports=CExports,
+ imports=CImports,typeorval=TypeOrVal}.
+
+%% causes an exit if duplicate definition names exist in a module
+remove_name_collisions(Modules) ->
+ create_ets_table(renamed_defs,[named_table]),
+ %% Name duplicates in the same module is not allowed.
+ lists:foreach(fun exit_if_nameduplicate/1,Modules),
+ %% Then remove duplicates in different modules and return the
+ %% new list of modules.
+ remove_name_collisions2(Modules,[]).
+
+%% For each definition in the first module in module list, find
+%% all definitons with same name and rename both definitions in
+%% the first module and in rest of modules
+remove_name_collisions2([M|Ms],Acc) ->
+ TypeOrVal = M#module.typeorval,
+ MName = M#module.name,
+ %% Test each name in TypeOrVal on all modules in Ms
+ {NewM,NewMs} = remove_name_collisions2(MName,TypeOrVal,Ms,[]),
+ remove_name_collisions2(NewMs,[M#module{typeorval=NewM}|Acc]);
+remove_name_collisions2([],Acc) ->
+ finished_warn_prints(),
+ Acc.
+
+%% For each definition in list of defs find definitions in (rest of)
+%% modules that have same name. If duplicate was found rename def.
+%% Test each name in [T|Ts] on all modules in Ms
+remove_name_collisions2(ModName,[T|Ts],Ms,Acc) ->
+ Name = get_name_of_def(T),
+ case discover_dupl_in_mods(Name,T,Ms,[],?unique_names) of
+ {_,?unique_names} -> % there was no name collision
+ remove_name_collisions2(ModName,Ts,Ms,[T|Acc]);
+ {NewMs,?dupl_uniquedefs} -> % renamed defs in NewMs
+ %% rename T
+ NewT = set_name_of_def(ModName,Name,T), %rename def
+ warn_renamed_def(ModName,get_name_of_def(NewT),Name),
+ ets:insert(renamed_defs,{get_name_of_def(NewT),Name,ModName}),
+ remove_name_collisions2(ModName,Ts,NewMs,[NewT|Acc]);
+ {NewMs,?dupl_equaldefs} -> % name duplicates, but identical defs
+ %% keep name of T
+ warn_kept_def(ModName,Name),
+ remove_name_collisions2(ModName,Ts,NewMs,[T|Acc]);
+ {NewMs,?dupl_eqdefs_uniquedefs} ->
+ %% keep name of T, renamed defs in NewMs
+ warn_kept_def(ModName,Name),
+ remove_name_collisions2(ModName,Ts,NewMs,[T|Acc])
+ end;
+remove_name_collisions2(_,[],Ms,Acc) ->
+ {Acc,Ms}.
+
+%% Name is the name of a definition. If a definition with the same name
+%% is found in the modules Ms the definition will be renamed and returned.
+discover_dupl_in_mods(Name,Def,[M=#module{name=N,typeorval=TorV}|Ms],
+ Acc,AnyRenamed) ->
+ Fun = fun(T,RenamedOrDupl)->
+ case {get_name_of_def(T),compare_defs(Def,T)} of
+ {Name,not_equal} ->
+ %% rename def
+ NewT=set_name_of_def(N,Name,T),
+ warn_renamed_def(N,get_name_of_def(NewT),Name),
+ ets:insert(renamed_defs,{get_name_of_def(NewT),
+ Name,N}),
+ {NewT,?dupl_uniquedefs bor RenamedOrDupl};
+ {Name,equal} ->
+ %% delete def
+ warn_deleted_def(N,Name),
+ {[],?dupl_equaldefs bor RenamedOrDupl};
+ _ ->
+ {T,RenamedOrDupl}
+ end
+ end,
+ {NewTorV,NewAnyRenamed} = lists:mapfoldl(Fun,AnyRenamed,TorV),
+ %% have to flatten the NewTorV to remove any empty list elements
+ discover_dupl_in_mods(Name,Def,Ms,
+ [M#module{typeorval=lists:flatten(NewTorV)}|Acc],
+ NewAnyRenamed);
+discover_dupl_in_mods(_,_,[],Acc,AnyRenamed) ->
+ {Acc,AnyRenamed}.
+
+warn_renamed_def(ModName,NewName,OldName) ->
+ maybe_first_warn_print(),
+ io:format("NOTICE: The ASN.1 definition in module ~p with name ~p has been renamed in generated module. New name is ~p.~n",[ModName,OldName,NewName]).
+
+warn_deleted_def(ModName,DefName) ->
+ maybe_first_warn_print(),
+ io:format("NOTICE: The ASN.1 definition in module ~p with name ~p has been deleted in generated module.~n",[ModName,DefName]).
+
+warn_kept_def(ModName,DefName) ->
+ maybe_first_warn_print(),
+ io:format("NOTICE: The ASN.1 definition in module ~p with name ~p has kept its name due to equal definition as duplicate.~n",[ModName,DefName]).
+
+maybe_first_warn_print() ->
+ case get(warn_duplicate_defs) of
+ undefined ->
+ put(warn_duplicate_defs,true),
+ io:format("~nDue to multiple occurrences of a definition name in "
+ "multi-file compiled files:~n");
+ _ ->
+ ok
+ end.
+finished_warn_prints() ->
+ put(warn_duplicate_defs,undefined).
+
+
+exit_if_nameduplicate(#module{typeorval=TorV}) ->
+ exit_if_nameduplicate(TorV);
+exit_if_nameduplicate([]) ->
+ ok;
+exit_if_nameduplicate([Def|Rest]) ->
+ Name=get_name_of_def(Def),
+ exit_if_nameduplicate2(Name,Rest),
+ exit_if_nameduplicate(Rest).
+
+exit_if_nameduplicate2(Name,Rest) ->
+ Pred=fun(Def)->
+ case get_name_of_def(Def) of
+ Name -> true;
+ _ -> false
+ end
+ end,
+ case lists:any(Pred,Rest) of
+ true ->
+ throw({error,{"more than one definition with same name",Name}});
+ _ ->
+ ok
+ end.
+
+compare_defs(D1,D2) ->
+ compare_defs2(unset_pos(D1),unset_pos(D2)).
+compare_defs2(D,D) ->
+ equal;
+compare_defs2(_,_) ->
+ not_equal.
+
+unset_pos(Def) when record(Def,typedef) ->
+ Def#typedef{pos=undefined};
+unset_pos(Def) when record(Def,classdef) ->
+ Def#classdef{pos=undefined};
+unset_pos(Def) when record(Def,valuedef) ->
+ Def#valuedef{pos=undefined};
+unset_pos(Def) when record(Def,ptypedef) ->
+ Def#ptypedef{pos=undefined};
+unset_pos(Def) when record(Def,pvaluedef) ->
+ Def#pvaluedef{pos=undefined};
+unset_pos(Def) when record(Def,pvaluesetdef) ->
+ Def#pvaluesetdef{pos=undefined};
+unset_pos(Def) when record(Def,pobjectdef) ->
+ Def#pobjectdef{pos=undefined};
+unset_pos(Def) when record(Def,pobjectsetdef) ->
+ Def#pobjectsetdef{pos=undefined}.
+
+get_pos_of_def(#typedef{pos=Pos}) ->
+ Pos;
+get_pos_of_def(#classdef{pos=Pos}) ->
+ Pos;
+get_pos_of_def(#valuedef{pos=Pos}) ->
+ Pos;
+get_pos_of_def(#ptypedef{pos=Pos}) ->
+ Pos;
+get_pos_of_def(#pvaluedef{pos=Pos}) ->
+ Pos;
+get_pos_of_def(#pvaluesetdef{pos=Pos}) ->
+ Pos;
+get_pos_of_def(#pobjectdef{pos=Pos}) ->
+ Pos;
+get_pos_of_def(#pobjectsetdef{pos=Pos}) ->
+ Pos.
+
+
+get_name_of_def(#typedef{name=Name}) ->
+ Name;
+get_name_of_def(#classdef{name=Name}) ->
+ Name;
+get_name_of_def(#valuedef{name=Name}) ->
+ Name;
+get_name_of_def(#ptypedef{name=Name}) ->
+ Name;
+get_name_of_def(#pvaluedef{name=Name}) ->
+ Name;
+get_name_of_def(#pvaluesetdef{name=Name}) ->
+ Name;
+get_name_of_def(#pobjectdef{name=Name}) ->
+ Name;
+get_name_of_def(#pobjectsetdef{name=Name}) ->
+ Name.
+
+set_name_of_def(ModName,Name,OldDef) ->
+ NewName = list_to_atom(lists:concat([Name,ModName])),
+ case OldDef of
+ #typedef{} -> OldDef#typedef{name=NewName};
+ #classdef{} -> OldDef#classdef{name=NewName};
+ #valuedef{} -> OldDef#valuedef{name=NewName};
+ #ptypedef{} -> OldDef#ptypedef{name=NewName};
+ #pvaluedef{} -> OldDef#pvaluedef{name=NewName};
+ #pvaluesetdef{} -> OldDef#pvaluesetdef{name=NewName};
+ #pobjectdef{} -> OldDef#pobjectdef{name=NewName};
+ #pobjectsetdef{} -> OldDef#pobjectsetdef{name=NewName}
+ end.
+
+save_imports(ModuleList)->
+ Fun = fun(M) ->
+ case M#module.imports of
+ {_,[]} -> [];
+ {_,I} ->
+ {M#module.name,I}
+ end
+ end,
+ ImportsList = lists:map(Fun,ModuleList),
+ case lists:flatten(ImportsList) of
+ [] ->
+ ok;
+ ImportsList2 ->
+ create_ets_table(original_imports,[named_table]),
+ ets:insert(original_imports,ImportsList2)
+ end.
+
+
+common_exports(ModuleList) ->
+ %% if all modules exports 'all' then export 'all',
+ %% otherwise export each typeorval name
+ case lists:filter(fun(X)->
+ element(2,X#module.exports) /= all
+ end,
+ ModuleList) of
+ []->
+ {exports,all};
+ ModsWithExpList ->
+ CExports1 =
+ lists:append(lists:map(fun(X)->element(2,X#module.exports) end,
+ ModsWithExpList)),
+ CExports2 = export_all(lists:subtract(ModuleList,ModsWithExpList)),
+ {exports,CExports1++CExports2}
+ end.
+
+export_all([])->[];
+export_all(ModuleList) ->
+ ExpList =
+ lists:map(
+ fun(M)->
+ TorVL=M#module.typeorval,
+ MName = M#module.name,
+ lists:map(
+ fun(Def)->
+ case Def of
+ T when record(T,typedef)->
+ #'Externaltypereference'{pos=0,
+ module=MName,
+ type=T#typedef.name};
+ V when record(V,valuedef) ->
+ #'Externalvaluereference'{pos=0,
+ module=MName,
+ value=V#valuedef.name};
+ C when record(C,classdef) ->
+ #'Externaltypereference'{pos=0,
+ module=MName,
+ type=C#classdef.name};
+ P when record(P,ptypedef) ->
+ #'Externaltypereference'{pos=0,
+ module=MName,
+ type=P#ptypedef.name};
+ PV when record(PV,pvaluesetdef) ->
+ #'Externaltypereference'{pos=0,
+ module=MName,
+ type=PV#pvaluesetdef.name};
+ PO when record(PO,pobjectdef) ->
+ #'Externalvaluereference'{pos=0,
+ module=MName,
+ value=PO#pobjectdef.name}
+ end
+ end,
+ TorVL)
+ end,
+ ModuleList),
+ lists:append(ExpList).
+
+%% common_imports/2
+%% IList is a list of tuples, {Imports,MName}, where Imports is the imports of
+%% the module with name MName.
+%% InputMNameL holds the names of all merged modules.
+%% Returns an import tuple with a list of imports that are external the merged
+%% set of modules.
+common_imports(IList,InputMNameL) ->
+ SetExternalImportsList = remove_in_set_imports(IList,InputMNameL,[]),
+ {imports,remove_import_doubles(SetExternalImportsList)}.
+
+check_tagdefault(ModList) ->
+ case have_same_tagdefault(ModList) of
+ {true,TagDefault} -> TagDefault;
+ {false,TagDefault} ->
+ create_ets_table(automatic_tags,[named_table]),
+ save_automatic_tagged_types(ModList),
+ TagDefault
+ end.
+
+have_same_tagdefault([#module{tagdefault=T}|Ms]) ->
+ have_same_tagdefault(Ms,{true,T}).
+
+have_same_tagdefault([],TagDefault) ->
+ TagDefault;
+have_same_tagdefault([#module{tagdefault=T}|Ms],TDefault={_,T}) ->
+ have_same_tagdefault(Ms,TDefault);
+have_same_tagdefault([#module{tagdefault=T1}|Ms],{_,T2}) ->
+ have_same_tagdefault(Ms,{false,rank_tagdef([T1,T2])}).
+
+rank_tagdef(L) ->
+ case lists:member('EXPLICIT',L) of
+ true -> 'EXPLICIT';
+ _ -> 'IMPLICIT'
+ end.
+
+save_automatic_tagged_types([])->
+ done;
+save_automatic_tagged_types([#module{tagdefault='AUTOMATIC',
+ typeorval=TorV}|Ms]) ->
+ Fun =
+ fun(T) ->
+ ets:insert(automatic_tags,{get_name_of_def(T)})
+ end,
+ lists:foreach(Fun,TorV),
+ save_automatic_tagged_types(Ms);
+save_automatic_tagged_types([_M|Ms]) ->
+ save_automatic_tagged_types(Ms).
+
+%% remove_in_set_imports/3 :
+%% input: list with tuples of each module's imports and module name
+%% respectively.
+%% output: one list with same format but each occured import from a
+%% module in the input set (IMNameL) is removed.
+remove_in_set_imports([{{imports,ImpL},_ModName}|Rest],InputMNameL,Acc) ->
+ NewImpL = remove_in_set_imports1(ImpL,InputMNameL,[]),
+ remove_in_set_imports(Rest,InputMNameL,NewImpL++Acc);
+remove_in_set_imports([],_,Acc) ->
+ lists:reverse(Acc).
+
+remove_in_set_imports1([I|Is],InputMNameL,Acc) ->
+ case I#'SymbolsFromModule'.module of
+ #'Externaltypereference'{type=MName} ->
+ case lists:member(MName,InputMNameL) of
+ true ->
+ remove_in_set_imports1(Is,InputMNameL,Acc);
+ false ->
+ remove_in_set_imports1(Is,InputMNameL,[I|Acc])
+ end;
+ _ ->
+ remove_in_set_imports1(Is,InputMNameL,[I|Acc])
+ end;
+remove_in_set_imports1([],_,Acc) ->
+ lists:reverse(Acc).
+
+remove_import_doubles([]) ->
+ [];
+%% If several modules in the merge set imports symbols from
+%% the same external module it might be doubled.
+%% ImportList has #'SymbolsFromModule' elements
+remove_import_doubles(ImportList) ->
+ MergedImportList =
+ merge_symbols_from_module(ImportList,[]),
+%% io:format("MergedImportList: ~p~n",[MergedImportList]),
+ delete_double_of_symbol(MergedImportList,[]).
+
+merge_symbols_from_module([Imp|Imps],Acc) ->
+ #'Externaltypereference'{type=ModName} = Imp#'SymbolsFromModule'.module,
+ IfromModName =
+ lists:filter(
+ fun(I)->
+ case I#'SymbolsFromModule'.module of
+ #'Externaltypereference'{type=ModName} ->
+ true;
+ #'Externalvaluereference'{value=ModName} ->
+ true;
+ _ -> false
+ end
+ end,
+ Imps),
+ NewImps = lists:subtract(Imps,IfromModName),
+%% io:format("Imp: ~p~nIfromModName: ~p~n",[Imp,IfromModName]),
+ NewImp =
+ Imp#'SymbolsFromModule'{
+ symbols = lists:append(
+ lists:map(fun(SL)->
+ SL#'SymbolsFromModule'.symbols
+ end,[Imp|IfromModName]))},
+ merge_symbols_from_module(NewImps,[NewImp|Acc]);
+merge_symbols_from_module([],Acc) ->
+ lists:reverse(Acc).
+
+delete_double_of_symbol([I|Is],Acc) ->
+ SymL=I#'SymbolsFromModule'.symbols,
+ NewSymL = delete_double_of_symbol1(SymL,[]),
+ delete_double_of_symbol(Is,[I#'SymbolsFromModule'{symbols=NewSymL}|Acc]);
+delete_double_of_symbol([],Acc) ->
+ Acc.
+
+delete_double_of_symbol1([TRef=#'Externaltypereference'{type=TrefName}|Rest],Acc)->
+ NewRest =
+ lists:filter(fun(S)->
+ case S of
+ #'Externaltypereference'{type=TrefName}->
+ false;
+ _ -> true
+ end
+ end,
+ Rest),
+ delete_double_of_symbol1(NewRest,[TRef|Acc]);
+delete_double_of_symbol1([VRef=#'Externalvaluereference'{value=VName}|Rest],Acc) ->
+ NewRest =
+ lists:filter(fun(S)->
+ case S of
+ #'Externalvaluereference'{value=VName}->
+ false;
+ _ -> true
+ end
+ end,
+ Rest),
+ delete_double_of_symbol1(NewRest,[VRef|Acc]);
+delete_double_of_symbol1([TRef={#'Externaltypereference'{type=MRef},
+ #'Externaltypereference'{type=TRef}}|Rest],
+ Acc)->
+ NewRest =
+ lists:filter(
+ fun(S)->
+ case S of
+ {#'Externaltypereference'{type=MRef},
+ #'Externaltypereference'{type=TRef}}->
+ false;
+ _ -> true
+ end
+ end,
+ Rest),
+ delete_double_of_symbol1(NewRest,[TRef|Acc]);
+delete_double_of_symbol1([],Acc) ->
+ Acc.
+
+
+scan_set(DirName,Files,Options) ->
+ lists:map(
+ fun(F)->
+ case scan({true,true},filename:join([DirName,F]),Options) of
+ {false,{error,Reason}} ->
+ throw({error,{'scan error in file:',F,Reason}});
+ {TrueOrFalse,Res} ->
+ {TrueOrFalse,Res,F}
+ end
+ end,
+ Files).
+
+parse_set(ScanRes,Options) ->
+ lists:map(
+ fun({TorF,Toks,F})->
+ case parse({TorF,Toks},F,Options) of
+ {false,{error,Reason}} ->
+ throw({error,{'parse error in file:',F,Reason}});
+ {TrueOrFalse,Res} ->
+ {TrueOrFalse,Res,F}
+ end
+ end,
+ ScanRes).
+
+
+%%***********************************
+
+
+scan({true,_}, File,Options) ->
+ case asn1ct_tok:file(File) of
+ {error,Reason} ->
+ io:format("~p~n",[Reason]),
+ {false,{error,Reason}};
+ Tokens ->
+ case lists:member(ss,Options) of
+ true -> % we terminate after scan
+ {false,Tokens};
+ false -> % continue with next pass
+ {true,Tokens}
+ end
+ end;
+scan({false,Result},_,_) ->
+ Result.
+
+
+parse({true,Tokens},File,Options) ->
+ %Presult = asn1ct_parser2:parse(Tokens),
+ %%case lists:member(p1,Options) of
+ %% true ->
+ %% asn1ct_parser:parse(Tokens);
+ %% _ ->
+ %% asn1ct_parser2:parse(Tokens)
+ %% end,
+ case catch asn1ct_parser2:parse(Tokens) of
+ {error,{{Line,_Mod,Message},_TokTup}} ->
+ if
+ integer(Line) ->
+ BaseName = filename:basename(File),
+ io:format("syntax error at line ~p in module ~s:~n",
+ [Line,BaseName]);
+ true ->
+ io:format("syntax error in module ~p:~n",[File])
+ end,
+ print_error_message(Message),
+ {false,{error,Message}};
+ {error,{Line,_Mod,[Message,Token]}} ->
+ io:format("syntax error: ~p ~p at line ~p~n",
+ [Message,Token,Line]),
+ {false,{error,{Line,[Message,Token]}}};
+ {ok,M} ->
+ case lists:member(sp,Options) of
+ true -> % terminate after parse
+ {false,M};
+ false -> % continue with next pass
+ {true,M}
+ end;
+ OtherError ->
+ io:format("~p~n",[OtherError])
+ end;
+parse({false,Tokens},_,_) ->
+ {false,Tokens}.
+
+check({true,M},File,OutFile,Includes,EncodingRule,DbFile,Options,InputMods) ->
+ cmp(M#module.name,File),
+ start(["."|Includes]),
+ case asn1ct_check:storeindb(M) of
+ ok ->
+ Module = asn1_db:dbget(M#module.name,'MODULE'),
+ State = #state{mname=Module#module.name,
+ module=Module#module{typeorval=[]},
+ erule=EncodingRule,
+ inputmodules=InputMods,
+ options=Options},
+ Check = asn1ct_check:check(State,Module#module.typeorval),
+ case {Check,lists:member(abs,Options)} of
+ {{error,Reason},_} ->
+ {false,{error,Reason}};
+ {{ok,NewTypeOrVal,_},true} ->
+ NewM = Module#module{typeorval=NewTypeOrVal},
+ asn1_db:dbput(NewM#module.name,'MODULE',NewM),
+ pretty2(M#module.name,lists:concat([OutFile,".abs"])),
+ {false,ok};
+ {{ok,NewTypeOrVal,GenTypeOrVal},_} ->
+ NewM = Module#module{typeorval=NewTypeOrVal},
+ asn1_db:dbput(NewM#module.name,'MODULE',NewM),
+ asn1_db:dbsave(DbFile,M#module.name),
+ io:format("--~p--~n",[{generated,DbFile}]),
+ {true,{M,NewM,GenTypeOrVal}}
+ end
+ end;
+check({false,M},_,_,_,_,_,_,_) ->
+ {false,M}.
+
+generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) ->
+ debug_on(Options),
+ case lists:member(compact_bit_string,Options) of
+ true -> put(compact_bit_string,true);
+ _ -> ok
+ end,
+ put(encoding_options,Options),
+ create_ets_table(check_functions,[named_table]),
+
+ %% create decoding function names and taglists for partial decode
+ %% For the time being leave errors unnoticed !!!!!!!!!
+% io:format("Options: ~p~n",[Options]),
+ case catch specialized_decode_prepare(EncodingRule,M,GenTOrV,Options) of
+ {error, enoent} -> ok;
+ {error, Reason} -> io:format("WARNING: Error in configuration"
+ "file: ~n~p~n",[Reason]);
+ {'EXIT',Reason} -> io:format("WARNING: Internal error when "
+ "analyzing configuration"
+ "file: ~n~p~n",[Reason]);
+ _ -> ok
+ end,
+
+ asn1ct_gen:pgen(OutFile,EncodingRule,M#module.name,GenTOrV),
+ debug_off(Options),
+ put(compact_bit_string,false),
+ erase(encoding_options),
+ erase(tlv_format), % used in ber_bin, optimize
+ erase(class_default_type),% used in ber_bin, optimize
+ ets:delete(check_functions),
+ case lists:member(sg,Options) of
+ true -> % terminate here , with .erl file generated
+ {false,true};
+ false ->
+ {true,true}
+ end;
+generate({false,M},_,_,_) ->
+ {false,M}.
+
+compile_erl({true,_},OutFile,Options) ->
+ erl_compile(OutFile,Options);
+compile_erl({false,true},_,_) ->
+ ok;
+compile_erl({false,Result},_,_) ->
+ Result.
+
+input_file_type([]) ->
+ {empty_name,[]};
+input_file_type(File) ->
+ case filename:extension(File) of
+ [] ->
+ case file:read_file_info(lists:concat([File,".asn1"])) of
+ {ok,_FileInfo} ->
+ {single_file, lists:concat([File,".asn1"])};
+ _Error ->
+ case file:read_file_info(lists:concat([File,".asn"])) of
+ {ok,_FileInfo} ->
+ {single_file, lists:concat([File,".asn"])};
+ _Error ->
+ {single_file, lists:concat([File,".py"])}
+ end
+ end;
+ ".asn1config" ->
+ case read_config_file(File,asn1_module) of
+ {ok,Asn1Module} ->
+ put(asn1_config_file,File),
+ input_file_type(Asn1Module);
+ Error ->
+ Error
+ end;
+ Asn1PFix ->
+ Base = filename:basename(File,Asn1PFix),
+ case filename:extension(Base) of
+ [] ->
+ {single_file,File};
+ SetPFix when (SetPFix == ".set") ->
+ {multiple_files_file,
+ filename:basename(Base,SetPFix),
+ File};
+ _Error ->
+ throw({input_file_error,{'Bad input file',File}})
+ end
+ end.
+
+get_file_list(File) ->
+ case file:open(File, [read]) of
+ {error,Reason} ->
+ {error,{File,file:format_error(Reason)}};
+ {ok,Stream} ->
+ get_file_list1(Stream,[])
+ end.
+
+get_file_list1(Stream,Acc) ->
+ Ret = io:get_line(Stream,''),
+ case Ret of
+ eof ->
+ file:close(Stream),
+ lists:reverse(Acc);
+ FileName ->
+ PrefixedNameList =
+ case (catch input_file_type(lists:delete($\n,FileName))) of
+ {empty_name,[]} -> [];
+ {single_file,Name} -> [Name];
+ {multiple_files_file,Name} ->
+ get_file_list(Name);
+ Err = {input_file_error,_Reason} ->
+ throw(Err)
+ end,
+ get_file_list1(Stream,PrefixedNameList++Acc)
+ end.
+
+get_rule(Options) ->
+ case [Rule ||Rule <-[per,ber,ber_bin,ber_bin_v2,per_bin],
+ Opt <- Options,
+ Rule==Opt] of
+ [Rule] ->
+ Rule;
+ [Rule|_] ->
+ Rule;
+ [] ->
+ ber
+ end.
+
+erl_compile(OutFile,Options) ->
+% io:format("Options:~n~p~n",[Options]),
+ case lists:member(noobj,Options) of
+ true ->
+ ok;
+ _ ->
+ ErlOptions = remove_asn_flags(Options),
+ case c:c(OutFile,ErlOptions) of
+ {ok,_Module} ->
+ ok;
+ _ ->
+ {error,'no_compilation'}
+ end
+ end.
+
+remove_asn_flags(Options) ->
+ [X || X <- Options,
+ X /= get_rule(Options),
+ X /= optimize,
+ X /= compact_bit_string,
+ X /= debug,
+ X /= keyed_list].
+
+debug_on(Options) ->
+ case lists:member(debug,Options) of
+ true ->
+ put(asndebug,true);
+ _ ->
+ true
+ end,
+ case lists:member(keyed_list,Options) of
+ true ->
+ put(asn_keyed_list,true);
+ _ ->
+ true
+ end.
+
+
+debug_off(_Options) ->
+ erase(asndebug),
+ erase(asn_keyed_list).
+
+
+outfile(Base, Ext, Opts) when atom(Ext) ->
+ outfile(Base, atom_to_list(Ext), Opts);
+outfile(Base, Ext, Opts) ->
+ Obase = case lists:keysearch(outdir, 1, Opts) of
+ {value, {outdir, Odir}} -> filename:join(Odir, Base);
+ _NotFound -> Base % Not found or bad format
+ end,
+ case Ext of
+ [] ->
+ Obase;
+ _ ->
+ Obase++"."++Ext
+ end.
+
+%% compile(AbsFileName, Options)
+%% Compile entry point for erl_compile.
+
+compile_asn(File,OutFile,Options) ->
+ compile(lists:concat([File,".asn"]),OutFile,Options).
+
+compile_asn1(File,OutFile,Options) ->
+ compile(lists:concat([File,".asn1"]),OutFile,Options).
+
+compile_py(File,OutFile,Options) ->
+ compile(lists:concat([File,".py"]),OutFile,Options).
+
+compile(File, _OutFile, Options) ->
+ case catch compile(File, make_erl_options(Options)) of
+ Exit = {'EXIT',_Reason} ->
+ io:format("~p~n~s~n",[Exit,"error"]),
+ error;
+ {error,_Reason} ->
+ %% case occurs due to error in asn1ct_parser2,asn1ct_check
+%% io:format("~p~n",[_Reason]),
+%% io:format("~p~n~s~n",[_Reason,"error"]),
+ error;
+ ok ->
+ io:format("ok~n"),
+ ok;
+ ParseRes when tuple(ParseRes) ->
+ io:format("~p~n",[ParseRes]),
+ ok;
+ ScanRes when list(ScanRes) ->
+ io:format("~p~n",[ScanRes]),
+ ok;
+ Unknown ->
+ io:format("~p~n~s~n",[Unknown,"error"]),
+ error
+ end.
+
+%% Converts generic compiler options to specific options.
+
+make_erl_options(Opts) ->
+
+ %% This way of extracting will work even if the record passed
+ %% has more fields than known during compilation.
+
+ Includes = Opts#options.includes,
+ Defines = Opts#options.defines,
+ Outdir = Opts#options.outdir,
+%% Warning = Opts#options.warning,
+ Verbose = Opts#options.verbose,
+ Specific = Opts#options.specific,
+ Optimize = Opts#options.optimize,
+ OutputType = Opts#options.output_type,
+ Cwd = Opts#options.cwd,
+
+ Options =
+ case Verbose of
+ true -> [verbose];
+ false -> []
+ end ++
+%%% case Warning of
+%%% 0 -> [];
+%%% _ -> [report_warnings]
+%%% end ++
+ [] ++
+ case Optimize of
+ 1 -> [optimize];
+ 999 -> [];
+ _ -> [{optimize,Optimize}]
+ end ++
+ lists:map(
+ fun ({Name, Value}) ->
+ {d, Name, Value};
+ (Name) ->
+ {d, Name}
+ end,
+ Defines) ++
+ case OutputType of
+ undefined -> [ber]; % temporary default (ber when it's ready)
+ ber -> [ber];
+ ber_bin -> [ber_bin];
+ ber_bin_v2 -> [ber_bin_v2];
+ per -> [per];
+ per_bin -> [per_bin]
+ end,
+
+ Options++[report_errors, {cwd, Cwd}, {outdir, Outdir}|
+ lists:map(fun(Dir) -> {i, Dir} end, Includes)]++Specific.
+
+pretty2(Module,AbsFile) ->
+ start(),
+ {ok,F} = file:open(AbsFile, [write]),
+ M = asn1_db:dbget(Module,'MODULE'),
+ io:format(F,"%%%%%%%%%%%%%%%%%%% ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
+ io:format(F,"~s\n",[asn1ct_pretty_format:term(M#module.defid)]),
+ io:format(F,"~s\n",[asn1ct_pretty_format:term(M#module.tagdefault)]),
+ io:format(F,"~s\n",[asn1ct_pretty_format:term(M#module.exports)]),
+ io:format(F,"~s\n",[asn1ct_pretty_format:term(M#module.imports)]),
+ io:format(F,"~s\n\n",[asn1ct_pretty_format:term(M#module.extensiondefault)]),
+
+ {Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets} = M#module.typeorval,
+ io:format(F,"%%%%%%%%%%%%%%%%%%% TYPES in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
+ lists:foreach(fun(T)-> io:format(F,"~s\n",
+ [asn1ct_pretty_format:term(asn1_db:dbget(Module,T))])
+ end,Types),
+ io:format(F,"%%%%%%%%%%%%%%%%%%% VALUES in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
+ lists:foreach(fun(T)-> io:format(F,"~s\n",
+ [asn1ct_pretty_format:term(asn1_db:dbget(Module,T))])
+ end,Values),
+ io:format(F,"%%%%%%%%%%%%%%%%%%% Parameterized Types in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
+ lists:foreach(fun(T)-> io:format(F,"~s\n",
+ [asn1ct_pretty_format:term(asn1_db:dbget(Module,T))])
+ end,ParameterizedTypes),
+ io:format(F,"%%%%%%%%%%%%%%%%%%% Classes in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
+ lists:foreach(fun(T)-> io:format(F,"~s\n",
+ [asn1ct_pretty_format:term(asn1_db:dbget(Module,T))])
+ end,Classes),
+ io:format(F,"%%%%%%%%%%%%%%%%%%% Objects in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
+ lists:foreach(fun(T)-> io:format(F,"~s\n",
+ [asn1ct_pretty_format:term(asn1_db:dbget(Module,T))])
+ end,Objects),
+ io:format(F,"%%%%%%%%%%%%%%%%%%% Object Sets in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
+ lists:foreach(fun(T)-> io:format(F,"~s\n",
+ [asn1ct_pretty_format:term(asn1_db:dbget(Module,T))])
+ end,ObjectSets).
+start() ->
+ Includes = ["."],
+ start(Includes).
+
+
+start(Includes) when list(Includes) ->
+ asn1_db:dbstart(Includes).
+
+stop() ->
+ save(),
+ asn1_db:stop_server(ns),
+ asn1_db:stop_server(rand),
+ stopped.
+
+save() ->
+ asn1_db:dbstop().
+
+%%clear() ->
+%% asn1_db:dbclear().
+
+encode(Module,Term) ->
+ asn1rt:encode(Module,Term).
+
+encode(Module,Type,Term) when list(Module) ->
+ asn1rt:encode(list_to_atom(Module),Type,Term);
+encode(Module,Type,Term) ->
+ asn1rt:encode(Module,Type,Term).
+
+decode(Module,Type,Bytes) when list(Module) ->
+ asn1rt:decode(list_to_atom(Module),Type,Bytes);
+decode(Module,Type,Bytes) ->
+ asn1rt:decode(Module,Type,Bytes).
+
+
+test(Module) ->
+ start(),
+ M = asn1_db:dbget(Module,'MODULE'),
+ {Types,_Values,_Ptypes,_Classes,_Objects,_ObjectSets} = M#module.typeorval,
+ test_each(Module,Types).
+
+test_each(Module,[Type | Rest]) ->
+ case test(Module,Type) of
+ {ok,_Result} ->
+ test_each(Module,Rest);
+ Error ->
+ Error
+ end;
+test_each(_,[]) ->
+ ok.
+
+test(Module,Type) ->
+ io:format("~p:~p~n",[Module,Type]),
+ case (catch value(Module,Type)) of
+ {ok,Val} ->
+ %% io:format("asn1ct:test/2: ~w~n",[Val]),
+ test(Module,Type,Val);
+ {'EXIT',Reason} ->
+ {error,{asn1,{value,Reason}}}
+ end.
+
+
+test(Module,Type,Value) ->
+ case catch encode(Module,Type,Value) of
+ {ok,Bytes} ->
+ %% io:format("test 1: ~p~n",[{Bytes}]),
+ M = if
+ list(Module) ->
+ list_to_atom(Module);
+ true ->
+ Module
+ end,
+ NewBytes =
+ case M:encoding_rule() of
+ ber ->
+ lists:flatten(Bytes);
+ ber_bin when binary(Bytes) ->
+ Bytes;
+ ber_bin ->
+ list_to_binary(Bytes);
+ ber_bin_v2 when binary(Bytes) ->
+ Bytes;
+ ber_bin_v2 ->
+ list_to_binary(Bytes);
+ per ->
+ lists:flatten(Bytes);
+ per_bin when binary(Bytes) ->
+ Bytes;
+ per_bin ->
+ list_to_binary(Bytes)
+ end,
+ case decode(Module,Type,NewBytes) of
+ {ok,Value} ->
+ {ok,{Module,Type,Value}};
+ {ok,Res} ->
+ {error,{asn1,{encode_decode_mismatch,
+ {{Module,Type,Value},Res}}}};
+ Error ->
+ {error,{asn1,{{decode,
+ {Module,Type,Value},Error}}}}
+ end;
+ Error ->
+ {error,{asn1,{encode,{{Module,Type,Value},Error}}}}
+ end.
+
+value(Module) ->
+ start(),
+ M = asn1_db:dbget(Module,'MODULE'),
+ {Types,_Values,_Ptypes,_Classes,_Objects,_ObjectSets} = M#module.typeorval,
+ lists:map(fun(A) ->value(Module,A) end,Types).
+
+value(Module,Type) ->
+ start(),
+ case catch asn1ct_value:get_type(Module,Type,no) of
+ {error,Reason} ->
+ {error,Reason};
+ {'EXIT',Reason} ->
+ {error,Reason};
+ Result ->
+ {ok,Result}
+ end.
+
+cmp(Module,InFile) ->
+ Base = filename:basename(InFile),
+ Dir = filename:dirname(InFile),
+ Ext = filename:extension(Base),
+ Finfo = file:read_file_info(InFile),
+ Minfo = file:read_file_info(filename:join(Dir,lists:concat([Module,Ext]))),
+ case Finfo of
+ Minfo ->
+ ok;
+ _ ->
+ io:format("asn1error: Modulename and filename must be equal~n",[]),
+ throw(error)
+ end.
+
+vsn() ->
+ ?vsn.
+
+print_error_message([got,H|T]) when list(H) ->
+ io:format(" got:"),
+ print_listing(H,"and"),
+ print_error_message(T);
+print_error_message([expected,H|T]) when list(H) ->
+ io:format(" expected one of:"),
+ print_listing(H,"or"),
+ print_error_message(T);
+print_error_message([H|T]) ->
+ io:format(" ~p",[H]),
+ print_error_message(T);
+print_error_message([]) ->
+ io:format("~n").
+
+print_listing([H1,H2|[]],AndOr) ->
+ io:format(" ~p ~s ~p",[H1,AndOr,H2]);
+print_listing([H1,H2|T],AndOr) ->
+ io:format(" ~p,",[H1]),
+ print_listing([H2|T],AndOr);
+print_listing([H],_AndOr) ->
+ io:format(" ~p",[H]);
+print_listing([],_) ->
+ ok.
+
+
+%% functions to administer ets tables
+
+%% Always creates a new table
+create_ets_table(Name,Options) when atom(Name) ->
+ case ets:info(Name) of
+ undefined ->
+ ets:new(Name,Options);
+ _ ->
+ ets:delete(Name),
+ ets:new(Name,Options)
+ end.
+
+%% Creates a new ets table only if no table exists
+create_if_no_table(Name,Options) ->
+ case ets:info(Name) of
+ undefined ->
+ %% create a new table
+ create_ets_table(Name,Options);
+ _ -> ok
+ end.
+
+
+delete_tables([Table|Ts]) ->
+ case ets:info(Table) of
+ undefined -> ok;
+ _ -> ets:delete(Table)
+ end,
+ delete_tables(Ts);
+delete_tables([]) ->
+ ok.
+
+
+specialized_decode_prepare(Erule,M,TsAndVs,Options) ->
+% Asn1confMember =
+% fun([{asn1config,File}|_],_) ->
+% {true,File};
+% ([],_) -> false;
+% ([_H|T],Fun) ->
+% Fun(T,Fun)
+% end,
+% case Asn1confMember(Options,Asn1confMember) of
+% {true,File} ->
+ case lists:member(asn1config,Options) of
+ true ->
+ partial_decode_prepare(Erule,M,TsAndVs,Options);
+ _ ->
+ ok
+ end.
+%% Reads the configuration file if it exists and stores information
+%% about partial decode and incomplete decode
+partial_decode_prepare(ber_bin_v2,M,TsAndVs,Options) when tuple(TsAndVs) ->
+ %% read configure file
+% Types = element(1,TsAndVs),
+ CfgList = read_config_file(M#module.name),
+ SelectedDecode = get_config_info(CfgList,partial_decode),
+ ExclusiveDecode = get_config_info(CfgList,exclusive_decode),
+ CommandList =
+ create_partial_decode_gen_info(M#module.name,SelectedDecode),
+% io:format("partial_decode = ~p~n",[CommandList]),
+
+ save_config(partial_decode,CommandList),
+ CommandList2 =
+ create_partial_inc_decode_gen_info(M#module.name,ExclusiveDecode),
+% io:format("partial_incomplete_decode = ~p~n",[CommandList2]),
+ Part_inc_tlv_tags = tag_format(ber_bin_v2,Options,CommandList2),
+% io:format("partial_incomplete_decode: tlv_tags = ~p~n",[Part_inc_tlv_tags]),
+ save_config(partial_incomplete_decode,Part_inc_tlv_tags),
+ save_gen_state(ExclusiveDecode,Part_inc_tlv_tags);
+partial_decode_prepare(_,_,_,_) ->
+ ok.
+
+
+
+%% create_partial_inc_decode_gen_info/2
+%%
+%% Creats a list of tags out of the information in TypeNameList that
+%% tells which value will be incomplete decoded, i.e. each end
+%% component/type in TypeNameList. The significant types/components in
+%% the path from the toptype must be specified in the
+%% TypeNameList. Significant elements are all constructed types that
+%% branches the path to the leaf and the leaf it selfs.
+%%
+%% Returns a list of elements, where an element may be one of
+%% mandatory|[opt,Tag]|[bin,Tag]. mandatory correspond to a mandatory
+%% element that shall be decoded as usual. [opt,Tag] matches an
+%% OPTIONAL or DEFAULT element that shall be decoded as
+%% usual. [bin,Tag] corresponds to an element, mandatory, OPTIONAL or
+%% DEFAULT, that shall be left encoded (incomplete decoded).
+create_partial_inc_decode_gen_info(ModName,{Mod,[{Name,L}|Ls]}) when list(L) ->
+ TopTypeName = partial_inc_dec_toptype(L),
+ [{Name,TopTypeName,
+ create_partial_inc_decode_gen_info1(ModName,TopTypeName,{Mod,L})}|
+ create_partial_inc_decode_gen_info(ModName,{Mod,Ls})];
+create_partial_inc_decode_gen_info(_,{_,[]}) ->
+ [];
+create_partial_inc_decode_gen_info(_,[]) ->
+ [].
+
+create_partial_inc_decode_gen_info1(ModName,TopTypeName,{ModName,
+ [_TopType|Rest]}) ->
+ case asn1_db:dbget(ModName,TopTypeName) of
+ #typedef{typespec=TS} ->
+ TagCommand = get_tag_command(TS,?MANDATORY,mandatory),
+ create_pdec_inc_command(ModName,get_components(TS#type.def),
+ Rest,[TagCommand]);
+ _ ->
+ throw({error,{"wrong type list in asn1 config file",
+ TopTypeName}})
+ end;
+create_partial_inc_decode_gen_info1(M1,_,{M2,_}) when M1 /= M2 ->
+ throw({error,{"wrong module name in asn1 config file",
+ M2}});
+create_partial_inc_decode_gen_info1(_,_,TNL) ->
+ throw({error,{"wrong type list in asn1 config file",
+ TNL}}).
+
+%%
+%% Only when there is a 'ComponentType' the config data C1 may be a
+%% list, where the incomplete decode is branched. So, C1 may be a
+%% list, a "binary tuple", a "parts tuple" or an atom. The second
+%% element of a binary tuple and a parts tuple is an atom.
+create_pdec_inc_command(_ModName,_,[],Acc) ->
+ lists:reverse(Acc);
+create_pdec_inc_command(ModName,{Comps1,Comps2},TNL,Acc)
+ when list(Comps1),list(Comps2) ->
+ create_pdec_inc_command(ModName,Comps1 ++ Comps2,TNL,Acc);
+create_pdec_inc_command(ModN,Clist,[CL|_Rest],Acc) when list(CL) ->
+ create_pdec_inc_command(ModN,Clist,CL,Acc);
+create_pdec_inc_command(ModName,
+ CList=[#'ComponentType'{name=Name,typespec=TS,
+ prop=Prop}|Comps],
+ TNL=[C1|Cs],Acc) ->
+ case C1 of
+% Name ->
+% %% In this case C1 is an atom
+% TagCommand = get_tag_command(TS,?MANDATORY,Prop),
+% create_pdec_inc_command(ModName,get_components(TS#type.def),Cs,[TagCommand|Acc]);
+ {Name,undecoded} ->
+ TagCommand = get_tag_command(TS,?UNDECODED,Prop),
+ create_pdec_inc_command(ModName,Comps,Cs,[TagCommand|Acc]);
+ {Name,parts} ->
+ TagCommand = get_tag_command(TS,?PARTS,Prop),
+ create_pdec_inc_command(ModName,Comps,Cs,[TagCommand|Acc]);
+ L when list(L) ->
+ %% This case is only possible as the first element after
+ %% the top type element, when top type is SEGUENCE or SET.
+ %% Follow each element in L. Must note every tag on the
+ %% way until the last command is reached, but it ought to
+ %% be enough to have a "complete" or "complete optional"
+ %% command for each component that is not specified in the
+ %% config file. Then in the TLV decode the components with
+ %% a "complete" command will be decoded by an ordinary TLV
+ %% decode.
+ create_pdec_inc_command(ModName,CList,L,Acc);
+ {Name,RestPartsList} when list(RestPartsList) ->
+ %% Same as previous, but this may occur at any place in
+ %% the structure. The previous is only possible as the
+ %% second element.
+ case get_tag_command(TS,?MANDATORY,Prop) of
+ ?MANDATORY ->
+ InnerDirectives=
+ create_pdec_inc_command(ModName,TS#type.def,
+ RestPartsList,[]),
+ create_pdec_inc_command(ModName,Comps,Cs,
+ [[?MANDATORY,InnerDirectives]|Acc]);
+% create_pdec_inc_command(ModName,Comps,Cs,
+% [InnerDirectives,?MANDATORY|Acc]);
+ [Opt,EncTag] ->
+ InnerDirectives =
+ create_pdec_inc_command(ModName,TS#type.def,
+ RestPartsList,[]),
+ create_pdec_inc_command(ModName,Comps,Cs,
+ [[Opt,EncTag,InnerDirectives]|Acc])
+ end;
+% create_pdec_inc_command(ModName,CList,RestPartsList,Acc);
+%% create_pdec_inc_command(ModName,TS#type.def,RestPartsList,Acc);
+ _ -> %% this component may not be in the config list
+ TagCommand = get_tag_command(TS,?MANDATORY,Prop),
+ create_pdec_inc_command(ModName,Comps,TNL,[TagCommand|Acc])
+ end;
+create_pdec_inc_command(ModName,
+ {'CHOICE',[#'ComponentType'{name=C1,
+ typespec=TS,
+ prop=Prop}|Comps]},
+ [{C1,Directive}|Rest],Acc) ->
+ case Directive of
+ List when list(List) ->
+ [Command,Tag] = get_tag_command(TS,?ALTERNATIVE,Prop),
+ CompAcc = create_pdec_inc_command(ModName,TS#type.def,List,[]),
+ create_pdec_inc_command(ModName,{'CHOICE',Comps},Rest,
+ [[Command,Tag,CompAcc]|Acc]);
+ undecoded ->
+ TagCommand = get_tag_command(TS,?ALTERNATIVE_UNDECODED,Prop),
+ create_pdec_inc_command(ModName,{'CHOICE',Comps},Rest,
+ [TagCommand|Acc]);
+ parts ->
+ TagCommand = get_tag_command(TS,?ALTERNATIVE_PARTS,Prop),
+ create_pdec_inc_command(ModName,{'CHOICE',Comps},Rest,
+ [TagCommand|Acc])
+ end;
+create_pdec_inc_command(ModName,
+ {'CHOICE',[#'ComponentType'{typespec=TS,
+ prop=Prop}|Comps]},
+ TNL,Acc) ->
+ TagCommand = get_tag_command(TS,?ALTERNATIVE,Prop),
+ create_pdec_inc_command(ModName,{'CHOICE',Comps},TNL,[TagCommand|Acc]);
+create_pdec_inc_command(M,{'CHOICE',{Cs1,Cs2}},TNL,Acc)
+ when list(Cs1),list(Cs2) ->
+ create_pdec_inc_command(M,{'CHOICE',Cs1 ++ Cs2},TNL,Acc);
+create_pdec_inc_command(ModName,#'Externaltypereference'{module=M,type=Name},
+ TNL,Acc) ->
+ #type{def=Def} = get_referenced_type(M,Name),
+ create_pdec_inc_command(ModName,get_components(Def),TNL,Acc);
+create_pdec_inc_command(_,_,TNL,_) ->
+ throw({error,{"unexpected error when creating partial "
+ "decode command",TNL}}).
+
+partial_inc_dec_toptype([T|_]) when atom(T) ->
+ T;
+partial_inc_dec_toptype([{T,_}|_]) when atom(T) ->
+ T;
+partial_inc_dec_toptype([L|_]) when list(L) ->
+ partial_inc_dec_toptype(L);
+partial_inc_dec_toptype(_) ->
+ throw({error,{"no top type found for partial incomplete decode"}}).
+
+
+%% Creats a list of tags out of the information in TypeList and Types
+%% that tells which value will be decoded. Each constructed type that
+%% is in the TypeList will get a "choosen" command. Only the last
+%% type/component in the TypeList may be a primitive type. Components
+%% "on the way" to the final element may get the "skip" or the
+%% "skip_optional" command.
+%% CommandList = [Elements]
+%% Elements = {choosen,Tag}|{skip_optional,Tag}|skip
+%% Tag is a binary with the tag BER encoded.
+create_partial_decode_gen_info(ModName,{{_,ModName},TypeList}) ->
+ case TypeList of
+ [TopType|Rest] ->
+ case asn1_db:dbget(ModName,TopType) of
+ #typedef{typespec=TS} ->
+ TagCommand = get_tag_command(TS,?CHOOSEN),
+ create_pdec_command(ModName,get_components(TS#type.def),
+ Rest,[TagCommand]);
+ _ ->
+ throw({error,{"wrong type list in asn1 config file",
+ TypeList}})
+ end;
+ _ ->
+ []
+ end;
+create_partial_decode_gen_info(_,[]) ->
+ [];
+create_partial_decode_gen_info(_M1,{{_,M2},_}) ->
+ throw({error,{"wrong module name in asn1 config file",
+ M2}}).
+
+%% create_pdec_command/4 for each name (type or component) in the
+%% third argument, TypeNameList, a command is created. The command has
+%% information whether the component/type shall be skipped, looked
+%% into or returned. The list of commands is returned.
+create_pdec_command(_ModName,_,[],Acc) ->
+ lists:reverse(Acc);
+create_pdec_command(ModName,[#'ComponentType'{name=C1,typespec=TS}|_Comps],
+ [C1|Cs],Acc) ->
+ %% this component is a constructed type or the last in the
+ %% TypeNameList otherwise the config spec is wrong
+ TagCommand = get_tag_command(TS,?CHOOSEN),
+ create_pdec_command(ModName,get_components(TS#type.def),
+ Cs,[TagCommand|Acc]);
+create_pdec_command(ModName,[#'ComponentType'{typespec=TS,
+ prop=Prop}|Comps],
+ [C2|Cs],Acc) ->
+ TagCommand =
+ case Prop of
+ mandatory ->
+ get_tag_command(TS,?SKIP);
+ _ ->
+ get_tag_command(TS,?SKIP_OPTIONAL)
+ end,
+ create_pdec_command(ModName,Comps,[C2|Cs],[TagCommand|Acc]);
+create_pdec_command(ModName,{'CHOICE',[Comp=#'ComponentType'{name=C1}|_]},TNL=[C1|_Cs],Acc) ->
+ create_pdec_command(ModName,[Comp],TNL,Acc);
+create_pdec_command(ModName,{'CHOICE',[#'ComponentType'{}|Comps]},TNL,Acc) ->
+ create_pdec_command(ModName,{'CHOICE',Comps},TNL,Acc);
+create_pdec_command(ModName,#'Externaltypereference'{module=M,type=C1},
+ TypeNameList,Acc) ->
+ case get_referenced_type(M,C1) of
+ #type{def=Def} ->
+ create_pdec_command(ModName,get_components(Def),TypeNameList,
+ Acc);
+ Err ->
+ throw({error,{"unexpected result when fetching "
+ "referenced element",Err}})
+ end;
+create_pdec_command(ModName,TS=#type{def=Def},[C1|Cs],Acc) ->
+ %% This case when we got the "components" of a SEQUENCE/SET OF
+ case C1 of
+ [1] ->
+ %% A list with an integer is the only valid option in a 'S
+ %% OF', the other valid option would be an empty
+ %% TypeNameList saying that the entire 'S OF' will be
+ %% decoded.
+ TagCommand = get_tag_command(TS,?CHOOSEN),
+ create_pdec_command(ModName,Def,Cs,[TagCommand|Acc]);
+ [N] when integer(N) ->
+ TagCommand = get_tag_command(TS,?SKIP),
+ create_pdec_command(ModName,Def,[[N-1]|Cs],[TagCommand|Acc]);
+ Err ->
+ throw({error,{"unexpected error when creating partial "
+ "decode command",Err}})
+ end;
+create_pdec_command(_,_,TNL,_) ->
+ throw({error,{"unexpected error when creating partial "
+ "decode command",TNL}}).
+
+% get_components({'CHOICE',Components}) ->
+% Components;
+get_components(#'SEQUENCE'{components=Components}) ->
+ Components;
+get_components(#'SET'{components=Components}) ->
+ Components;
+get_components({'SEQUENCE OF',Components}) ->
+ Components;
+get_components({'SET OF',Components}) ->
+ Components;
+get_components(Def) ->
+ Def.
+
+%% get_tag_command(Type,Command)
+
+%% Type is the type that has information about the tag Command tells
+%% what to do with the encoded value with the tag of Type when
+%% decoding.
+get_tag_command(#type{tag=[]},_) ->
+ [];
+get_tag_command(#type{tag=[_Tag]},?SKIP) ->
+ ?SKIP;
+get_tag_command(#type{tag=[Tag]},Command) ->
+ %% encode the tag according to BER
+ [Command,encode_tag_val(decode_class(Tag#tag.class),Tag#tag.form,
+ Tag#tag.number)];
+get_tag_command(T=#type{tag=[Tag|Tags]},Command) ->
+ [get_tag_command(T#type{tag=Tag},Command)|
+ get_tag_command(T#type{tag=Tags},Command)].
+
+%% get_tag_command/3 used by create_pdec_inc_command
+get_tag_command(#type{tag=[]},_,_) ->
+ [];
+get_tag_command(#type{tag=[Tag]},?MANDATORY,Prop) ->
+ case Prop of
+ mandatory ->
+ ?MANDATORY;
+ {'DEFAULT',_} ->
+ [?DEFAULT,encode_tag_val(decode_class(Tag#tag.class),
+ Tag#tag.form,Tag#tag.number)];
+ _ -> [?OPTIONAL,encode_tag_val(decode_class(Tag#tag.class),
+ Tag#tag.form,Tag#tag.number)]
+ end;
+get_tag_command(#type{tag=[Tag]},Command,_) ->
+ [Command,encode_tag_val(decode_class(Tag#tag.class),Tag#tag.form,
+ Tag#tag.number)].
+
+
+get_referenced_type(M,Name) ->
+ case asn1_db:dbget(M,Name) of
+ #typedef{typespec=TS} ->
+ case TS of
+ #type{def=#'Externaltypereference'{module=M2,type=Name2}} ->
+ %% The tags have already been taken care of in the
+ %% first reference where they were gathered in a
+ %% list of tags.
+ get_referenced_type(M2,Name2);
+ #type{} -> TS;
+ _ ->
+ throw({error,{"unexpected element when"
+ " fetching referenced type",TS}})
+ end;
+ T ->
+ throw({error,{"unexpected element when fetching "
+ "referenced type",T}})
+ end.
+
+tag_format(EncRule,_Options,CommandList) ->
+ case EncRule of
+ ber_bin_v2 ->
+ tlv_tags(CommandList);
+ _ ->
+ CommandList
+ end.
+
+tlv_tags([]) ->
+ [];
+tlv_tags([mandatory|Rest]) ->
+ [mandatory|tlv_tags(Rest)];
+tlv_tags([[Command,Tag]|Rest]) when atom(Command),binary(Tag) ->
+ [[Command,tlv_tag(Tag)]|tlv_tags(Rest)];
+tlv_tags([[Command,Directives]|Rest]) when atom(Command),list(Directives) ->
+ [[Command,tlv_tags(Directives)]|tlv_tags(Rest)];
+%% remove all empty lists
+tlv_tags([[]|Rest]) ->
+ tlv_tags(Rest);
+tlv_tags([{Name,TopType,L1}|Rest]) when list(L1),atom(TopType) ->
+ [{Name,TopType,tlv_tags(L1)}|tlv_tags(Rest)];
+tlv_tags([[Command,Tag,L1]|Rest]) when list(L1),binary(Tag) ->
+ [[Command,tlv_tag(Tag),tlv_tags(L1)]|tlv_tags(Rest)];
+tlv_tags([L=[L1|_]|Rest]) when list(L1) ->
+ [tlv_tags(L)|tlv_tags(Rest)].
+
+tlv_tag(<<Cl:2,_:1,TagNo:5>>) when TagNo < 31 ->
+ (Cl bsl 16) + TagNo;
+tlv_tag(<<Cl:2,_:1,31:5,0:1,TagNo:7>>) ->
+ (Cl bsl 16) + TagNo;
+tlv_tag(<<Cl:2,_:1,31:5,Buffer/binary>>) ->
+ TagNo = tlv_tag1(Buffer,0),
+ (Cl bsl 16) + TagNo.
+tlv_tag1(<<0:1,PartialTag:7>>,Acc) ->
+ (Acc bsl 7) bor PartialTag;
+tlv_tag1(<<1:1,PartialTag:7,Buffer/binary>>,Acc) ->
+ tlv_tag1(Buffer,(Acc bsl 7) bor PartialTag).
+
+%% reads the content from the configuration file and returns the
+%% selected part choosen by InfoType. Assumes that the config file
+%% content is an Erlang term.
+read_config_file(ModuleName,InfoType) when atom(InfoType) ->
+ CfgList = read_config_file(ModuleName),
+ get_config_info(CfgList,InfoType).
+
+
+read_config_file(ModuleName) ->
+ case file:consult(lists:concat([ModuleName,'.asn1config'])) of
+% case file:consult(ModuleName) of
+ {ok,CfgList} ->
+ CfgList;
+ {error,enoent} ->
+ Options = get(encoding_options),
+ Includes = [I || {i,I} <- Options],
+ read_config_file1(ModuleName,Includes);
+ {error,Reason} ->
+ file:format_error(Reason),
+ throw({error,{"error reading asn1 config file",Reason}})
+ end.
+read_config_file1(ModuleName,[]) ->
+ case filename:extension(ModuleName) of
+ ".asn1config" ->
+ throw({error,enoent});
+ _ ->
+ read_config_file(lists:concat([ModuleName,".asn1config"]))
+ end;
+read_config_file1(ModuleName,[H|T]) ->
+% File = filename:join([H,lists:concat([ModuleName,'.asn1config'])]),
+ File = filename:join([H,ModuleName]),
+ case file:consult(File) of
+ {ok,CfgList} ->
+ CfgList;
+ {error,enoent} ->
+ read_config_file1(ModuleName,T);
+ {error,Reason} ->
+ file:format_error(Reason),
+ throw({error,{"error reading asn1 config file",Reason}})
+ end.
+
+get_config_info(CfgList,InfoType) ->
+ case InfoType of
+ all ->
+ CfgList;
+ _ ->
+ case lists:keysearch(InfoType,1,CfgList) of
+ {value,{InfoType,Value}} ->
+ Value;
+ false ->
+ []
+ end
+ end.
+
+%% save_config/2 saves the Info with the key Key
+%% Before saving anything check if a table exists
+save_config(Key,Info) ->
+ create_if_no_table(asn1_general,[named_table]),
+ ets:insert(asn1_general,{{asn1_config,Key},Info}).
+
+read_config_data(Key) ->
+ case ets:info(asn1_general) of
+ undefined -> undefined;
+ _ ->
+ case ets:lookup(asn1_general,{asn1_config,Key}) of
+ [{_,Data}] -> Data;
+ Err ->
+ io:format("strange data from config file ~w~n",[Err]),
+ Err
+ end
+ end.
+
+
+%%
+%% Functions to manipulate the gen_state record saved in the
+%% asn1_general ets table.
+%%
+
+%% saves input data in a new gen_state record
+save_gen_state({_,ConfList},PartIncTlvTagList) ->
+ %ConfList=[{FunctionName,PatternList}|Rest]
+ StateRec = #gen_state{inc_tag_pattern=PartIncTlvTagList,
+ inc_type_pattern=ConfList},
+ save_config(gen_state,StateRec);
+save_gen_state(_,_) ->
+%% ok.
+ save_config(gen_state,#gen_state{}).
+
+save_gen_state(GenState) when record(GenState,gen_state) ->
+ save_config(gen_state,GenState).
+
+
+%% get_gen_state_field returns undefined if no gen_state exists or if
+%% Field is undefined or the data at the field.
+get_gen_state_field(Field) ->
+ case read_config_data(gen_state) of
+ undefined ->
+ undefined;
+ GenState ->
+ get_gen_state_field(GenState,Field)
+ end.
+get_gen_state_field(#gen_state{active=Active},active) ->
+ Active;
+get_gen_state_field(_,active) ->
+ false;
+get_gen_state_field(GS,prefix) ->
+ GS#gen_state.prefix;
+get_gen_state_field(GS,inc_tag_pattern) ->
+ GS#gen_state.inc_tag_pattern;
+get_gen_state_field(GS,tag_pattern) ->
+ GS#gen_state.tag_pattern;
+get_gen_state_field(GS,inc_type_pattern) ->
+ GS#gen_state.inc_type_pattern;
+get_gen_state_field(GS,type_pattern) ->
+ GS#gen_state.type_pattern;
+get_gen_state_field(GS,func_name) ->
+ GS#gen_state.func_name;
+get_gen_state_field(GS,namelist) ->
+ GS#gen_state.namelist;
+get_gen_state_field(GS,tobe_refed_funcs) ->
+ GS#gen_state.tobe_refed_funcs;
+get_gen_state_field(GS,gen_refed_funcs) ->
+ GS#gen_state.gen_refed_funcs.
+
+
+get_gen_state() ->
+ read_config_data(gen_state).
+
+
+update_gen_state(Field,Data) ->
+ case get_gen_state() of
+ State when record(State,gen_state) ->
+ update_gen_state(Field,State,Data);
+ _ ->
+ exit({error,{asn1,{internal,
+ "tried to update nonexistent gen_state",Field,Data}}})
+ end.
+update_gen_state(active,State,Data) ->
+ save_gen_state(State#gen_state{active=Data});
+update_gen_state(prefix,State,Data) ->
+ save_gen_state(State#gen_state{prefix=Data});
+update_gen_state(inc_tag_pattern,State,Data) ->
+ save_gen_state(State#gen_state{inc_tag_pattern=Data});
+update_gen_state(tag_pattern,State,Data) ->
+ save_gen_state(State#gen_state{tag_pattern=Data});
+update_gen_state(inc_type_pattern,State,Data) ->
+ save_gen_state(State#gen_state{inc_type_pattern=Data});
+update_gen_state(type_pattern,State,Data) ->
+ save_gen_state(State#gen_state{type_pattern=Data});
+update_gen_state(func_name,State,Data) ->
+ save_gen_state(State#gen_state{func_name=Data});
+update_gen_state(namelist,State,Data) ->
+% SData =
+% case Data of
+% [D] when list(D) -> D;
+% _ -> Data
+% end,
+ save_gen_state(State#gen_state{namelist=Data});
+update_gen_state(tobe_refed_funcs,State,Data) ->
+ save_gen_state(State#gen_state{tobe_refed_funcs=Data});
+update_gen_state(gen_refed_funcs,State,Data) ->
+ save_gen_state(State#gen_state{gen_refed_funcs=Data}).
+
+update_namelist(Name) ->
+ case get_gen_state_field(namelist) of
+ [Name,Rest] -> update_gen_state(namelist,Rest);
+ [Name|Rest] -> update_gen_state(namelist,Rest);
+ [{Name,List}] when list(List) -> update_gen_state(namelist,List);
+ [{Name,Atom}|Rest] when atom(Atom) -> update_gen_state(namelist,Rest);
+ Other -> Other
+ end.
+
+pop_namelist() ->
+ DeepTail = %% removes next element in order
+ fun([[{_,A}]|T],_Fun) when atom(A) -> T;
+ ([{_N,L}|T],_Fun) when list(L) -> [L|T];
+ ([[]|T],Fun) -> Fun(T,Fun);
+ ([L1|L2],Fun) when list(L1) ->
+ case lists:flatten(L1) of
+ [] -> Fun([L2],Fun);
+ _ -> [Fun(L1,Fun)|L2]
+ end;
+ ([_H|T],_Fun) -> T
+ end,
+ {Pop,NewNL} =
+ case get_gen_state_field(namelist) of
+ [] -> {[],[]};
+ L ->
+ {next_namelist_el(L),
+ DeepTail(L,DeepTail)}
+ end,
+ update_gen_state(namelist,NewNL),
+ Pop.
+
+%% next_namelist_el fetches the next type/component name in turn in
+%% the namelist, without changing the namelist.
+next_namelist_el() ->
+ case get_gen_state_field(namelist) of
+ undefined -> undefined;
+ L when list(L) -> next_namelist_el(L)
+ end.
+
+next_namelist_el([]) ->
+ [];
+next_namelist_el([L]) when list(L) ->
+ next_namelist_el(L);
+next_namelist_el([H|_]) when atom(H) ->
+ H;
+next_namelist_el([L|T]) when list(L) ->
+ case next_namelist_el(L) of
+ [] ->
+ next_namelist_el([T]);
+ R ->
+ R
+ end;
+next_namelist_el([H={_,A}|_]) when atom(A) ->
+ H.
+
+%% removes a bracket from the namelist
+step_in_constructed() ->
+ case get_gen_state_field(namelist) of
+ [L] when list(L) ->
+ update_gen_state(namelist,L);
+ _ -> ok
+ end.
+
+is_function_generated(Name) ->
+ case get_gen_state_field(gen_refed_funcs) of
+ L when list(L) ->
+ lists:member(Name,L);
+ _ ->
+ false
+ end.
+
+get_tobe_refed_func(Name) ->
+ case get_gen_state_field(tobe_refed_funcs) of
+ L when list(L) ->
+ case lists:keysearch(Name,1,L) of
+ {_,Element} ->
+ Element;
+ _ ->
+ undefined
+ end;
+ _ ->
+ undefined
+ end.
+
+add_tobe_refed_func(Data) ->
+ L = get_gen_state_field(tobe_refed_funcs),
+ update_gen_state(tobe_refed_funcs,[Data|L]).
+
+%% moves Name from the to be list to the generated list.
+generated_refed_func(Name) ->
+ L = get_gen_state_field(tobe_refed_funcs),
+ NewL = lists:keydelete(Name,1,L),
+ update_gen_state(tobe_refed_funcs,NewL),
+ L2 = get_gen_state_field(gen_refed_funcs),
+ update_gen_state(gen_refed_funcs,[Name|L2]).
+
+add_generated_refed_func(Data) ->
+ L = get_gen_state_field(gen_refed_funcs),
+ update_gen_state(gen_refed_funcs,[Data|L]).
+
+
+next_refed_func() ->
+ case get_gen_state_field(tobe_refed_funcs) of
+ [] ->
+ [];
+ [H|T] ->
+ update_gen_state(tobe_refed_funcs,T),
+ H
+ end.
+
+reset_gen_state() ->
+ save_gen_state(#gen_state{}).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_check.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_check.erl
new file mode 100644
index 0000000000..2f0ada122e
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_check.erl
@@ -0,0 +1,5566 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1ct_check.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
+%%
+-module(asn1ct_check).
+
+%% Main Module for ASN.1 compile time functions
+
+%-compile(export_all).
+-export([check/2,storeindb/1]).
+-include("asn1_records.hrl").
+%%% The tag-number for universal types
+-define(N_BOOLEAN, 1).
+-define(N_INTEGER, 2).
+-define(N_BIT_STRING, 3).
+-define(N_OCTET_STRING, 4).
+-define(N_NULL, 5).
+-define(N_OBJECT_IDENTIFIER, 6).
+-define(N_OBJECT_DESCRIPTOR, 7).
+-define(N_EXTERNAL, 8). % constructed
+-define(N_INSTANCE_OF,8).
+-define(N_REAL, 9).
+-define(N_ENUMERATED, 10).
+-define(N_EMBEDDED_PDV, 11). % constructed
+-define(N_SEQUENCE, 16).
+-define(N_SET, 17).
+-define(N_NumericString, 18).
+-define(N_PrintableString, 19).
+-define(N_TeletexString, 20).
+-define(N_VideotexString, 21).
+-define(N_IA5String, 22).
+-define(N_UTCTime, 23).
+-define(N_GeneralizedTime, 24).
+-define(N_GraphicString, 25).
+-define(N_VisibleString, 26).
+-define(N_GeneralString, 27).
+-define(N_UniversalString, 28).
+-define(N_CHARACTER_STRING, 29). % constructed
+-define(N_BMPString, 30).
+
+-define(TAG_PRIMITIVE(Num),
+ case S#state.erule of
+ ber_bin_v2 ->
+ #tag{class='UNIVERSAL',number=Num,type='IMPLICIT',form=0};
+ _ -> []
+ end).
+-define(TAG_CONSTRUCTED(Num),
+ case S#state.erule of
+ ber_bin_v2 ->
+ #tag{class='UNIVERSAL',number=Num,type='IMPLICIT',form=32};
+ _ -> []
+ end).
+
+-record(newt,{type=unchanged,tag=unchanged,constraint=unchanged,inlined=no}). % used in check_type to update type and tag
+-record(newv,{type=unchanged,value=unchanged}). % used in check_value to update type and value
+
+check(S,{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets}) ->
+ %%Predicates used to filter errors
+ TupleIs = fun({T,_},T) -> true;
+ (_,_) -> false
+ end,
+ IsClass = fun(X) -> TupleIs(X,asn1_class) end,
+ IsObjSet = fun(X) -> TupleIs(X,objectsetdef) end,
+ IsPObjSet = fun(X) -> TupleIs(X,pobjectsetdef) end,
+ IsObject = fun(X) -> TupleIs(X,objectdef) end,
+ IsValueSet = fun(X) -> TupleIs(X,valueset) end,
+ Element2 = fun(X) -> element(2,X) end,
+
+ _Perror = checkp(S,ParameterizedTypes,[]), % must do this before the templates are used
+ Terror = checkt(S,Types,[]),
+
+ %% get parameterized object sets sent to checkt/3
+ %% and update Terror
+
+ {PObjSetNames1,Terror2} = filter_errors(IsPObjSet,Terror),
+
+ Verror = checkv(S,Values ++ ObjectSets,[]), %value sets may be parsed as object sets
+
+ %% get information object classes wrongly sent to checkt/3
+ %% and update Terror2
+
+ {AddClasses,Terror3} = filter_errors(IsClass,Terror2),
+
+ NewClasses = Classes++AddClasses,
+
+ Cerror = checkc(S,NewClasses,[]),
+
+ %% get object sets incorrectly sent to checkv/3
+ %% and update Verror
+
+ {ObjSetNames,Verror2} = filter_errors(IsObjSet,Verror),
+
+ %% get parameterized object sets incorrectly sent to checkv/3
+ %% and update Verror2
+
+ {PObjSetNames,Verror3} = filter_errors(IsPObjSet,Verror2),
+
+ %% get objects incorrectly sent to checkv/3
+ %% and update Verror3
+
+ {ObjectNames,Verror4} = filter_errors(IsObject,Verror3),
+
+ NewObjects = Objects++ObjectNames,
+ NewObjectSets = ObjSetNames ++ PObjSetNames ++ PObjSetNames1,
+
+ %% get value sets
+ %% and update Verror4
+
+ {ValueSetNames,Verror5} = filter_errors(IsValueSet,Verror4),
+
+ asn1ct:create_ets_table(inlined_objects,[named_table]),
+ {Oerror,ExclO,ExclOS} = checko(S,NewObjects ++
+ NewObjectSets,
+ [],[],[]),
+ InlinedObjTuples = ets:tab2list(inlined_objects),
+ InlinedObjects = lists:map(Element2,InlinedObjTuples),
+ ets:delete(inlined_objects),
+
+ Exporterror = check_exports(S,S#state.module),
+ case {Terror3,Verror5,Cerror,Oerror,Exporterror} of
+ {[],[],[],[],[]} ->
+ ContextSwitchTs = context_switch_in_spec(),
+ InstanceOf = instance_of_in_spec(),
+ NewTypes = lists:subtract(Types,AddClasses) ++ ContextSwitchTs
+ ++ InstanceOf,
+ NewValues = lists:subtract(Values,PObjSetNames++ObjectNames++
+ ValueSetNames),
+ {ok,
+ {NewTypes,NewValues,ParameterizedTypes,
+ NewClasses,NewObjects,NewObjectSets},
+ {NewTypes,NewValues,ParameterizedTypes,NewClasses,
+ lists:subtract(NewObjects,ExclO)++InlinedObjects,
+ lists:subtract(NewObjectSets,ExclOS)}};
+ _ ->{error,{asn1,lists:flatten([Terror3,Verror5,Cerror,
+ Oerror,Exporterror])}}
+ end.
+
+context_switch_in_spec() ->
+ L = [{external,'EXTERNAL'},
+ {embedded_pdv,'EMBEDDED PDV'},
+ {character_string,'CHARACTER STRING'}],
+ F = fun({T,TName},Acc) ->
+ case get(T) of
+ generate -> erase(T),
+ [TName|Acc];
+ _ -> Acc
+ end
+ end,
+ lists:foldl(F,[],L).
+
+instance_of_in_spec() ->
+ case get(instance_of) of
+ generate ->
+ erase(instance_of),
+ ['INSTANCE OF'];
+ _ ->
+ []
+ end.
+
+filter_errors(Pred,ErrorList) ->
+ Element2 = fun(X) -> element(2,X) end,
+ RemovedTupleElements = lists:filter(Pred,ErrorList),
+ RemovedNames = lists:map(Element2,RemovedTupleElements),
+ %% remove value set name tuples from Verror
+ RestErrors = lists:subtract(ErrorList,RemovedTupleElements),
+ {RemovedNames,RestErrors}.
+
+
+check_exports(S,Module = #module{}) ->
+ case Module#module.exports of
+ {exports,[]} ->
+ [];
+ {exports,all} ->
+ [];
+ {exports,ExportList} when list(ExportList) ->
+ IsNotDefined =
+ fun(X) ->
+ case catch get_referenced_type(S,X) of
+ {error,{asn1,_}} ->
+ true;
+ _ -> false
+ end
+ end,
+ case lists:filter(IsNotDefined,ExportList) of
+ [] ->
+ [];
+ NoDefExp ->
+ GetName =
+ fun(T = #'Externaltypereference'{type=N})->
+ %%{exported,undefined,entity,N}
+ NewS=S#state{type=T,tname=N},
+ error({export,"exported undefined entity",NewS})
+ end,
+ lists:map(GetName,NoDefExp)
+ end
+ end.
+
+checkt(S,[Name|T],Acc) ->
+ %%io:format("check_typedef:~p~n",[Name]),
+ Result =
+ case asn1_db:dbget(S#state.mname,Name) of
+ undefined ->
+ error({type,{internal_error,'???'},S});
+ Type when record(Type,typedef) ->
+ NewS = S#state{type=Type,tname=Name},
+ case catch(check_type(NewS,Type,Type#typedef.typespec)) of
+ {error,Reason} ->
+ error({type,Reason,NewS});
+ {'EXIT',Reason} ->
+ error({type,{internal_error,Reason},NewS});
+ {asn1_class,_ClassDef} ->
+ {asn1_class,Name};
+ pobjectsetdef ->
+ {pobjectsetdef,Name};
+ pvalueset ->
+ {pvalueset,Name};
+ Ts ->
+ case Type#typedef.checked of
+ true -> % already checked and updated
+ ok;
+ _ ->
+ NewTypeDef = Type#typedef{checked=true,typespec = Ts},
+ %io:format("checkt:dbput:~p, ~p~n",[S#state.mname,NewTypeDef#typedef.name]),
+ asn1_db:dbput(NewS#state.mname,Name,NewTypeDef), % update the type
+ ok
+ end
+ end
+ end,
+ case Result of
+ ok ->
+ checkt(S,T,Acc);
+ _ ->
+ checkt(S,T,[Result|Acc])
+ end;
+checkt(S,[],Acc) ->
+ case check_contextswitchingtypes(S,[]) of
+ [] ->
+ lists:reverse(Acc);
+ L ->
+ checkt(S,L,Acc)
+ end.
+
+check_contextswitchingtypes(S,Acc) ->
+ CSTList=[{external,'EXTERNAL'},
+ {embedded_pdv,'EMBEDDED PDV'},
+ {character_string,'CHARACTER STRING'}],
+ check_contextswitchingtypes(S,CSTList,Acc).
+
+check_contextswitchingtypes(S,[{T,TName}|Ts],Acc) ->
+ case get(T) of
+ unchecked ->
+ put(T,generate),
+ check_contextswitchingtypes(S,Ts,[TName|Acc]);
+ _ ->
+ check_contextswitchingtypes(S,Ts,Acc)
+ end;
+check_contextswitchingtypes(_,[],Acc) ->
+ Acc.
+
+checkv(S,[Name|T],Acc) ->
+ %%io:format("check_valuedef:~p~n",[Name]),
+ Result = case asn1_db:dbget(S#state.mname,Name) of
+ undefined -> error({value,{internal_error,'???'},S});
+ Value when record(Value,valuedef);
+ record(Value,typedef); %Value set may be parsed as object set.
+ record(Value,pvaluedef);
+ record(Value,pvaluesetdef) ->
+ NewS = S#state{value=Value},
+ case catch(check_value(NewS,Value)) of
+ {error,Reason} ->
+ error({value,Reason,NewS});
+ {'EXIT',Reason} ->
+ error({value,{internal_error,Reason},NewS});
+ {pobjectsetdef} ->
+ {pobjectsetdef,Name};
+ {objectsetdef} ->
+ {objectsetdef,Name};
+ {objectdef} ->
+ %% this is an object, save as typedef
+ #valuedef{checked=C,pos=Pos,name=N,type=Type,
+ value=Def}=Value,
+% Currmod = S#state.mname,
+% #type{def=
+% #'Externaltypereference'{module=Mod,
+% type=CName}} = Type,
+ ClassName =
+ Type#type.def,
+% case Mod of
+% Currmod ->
+% {objectclassname,CName};
+% _ ->
+% {objectclassname,Mod,CName}
+% end,
+ NewSpec = #'Object'{classname=ClassName,
+ def=Def},
+ NewDef = #typedef{checked=C,pos=Pos,name=N,
+ typespec=NewSpec},
+ asn1_db:dbput(NewS#state.mname,Name,NewDef),
+ {objectdef,Name};
+ {valueset,VSet} ->
+ Pos = asn1ct:get_pos_of_def(Value),
+ CheckedVSDef = #typedef{checked=true,pos=Pos,
+ name=Name,typespec=VSet},
+ asn1_db:dbput(NewS#state.mname,Name,CheckedVSDef),
+ {valueset,Name};
+ V ->
+ %% update the valuedef
+ asn1_db:dbput(NewS#state.mname,Name,V),
+ ok
+ end
+ end,
+ case Result of
+ ok ->
+ checkv(S,T,Acc);
+ _ ->
+ checkv(S,T,[Result|Acc])
+ end;
+checkv(_S,[],Acc) ->
+ lists:reverse(Acc).
+
+
+checkp(S,[Name|T],Acc) ->
+ %io:format("check_ptypedef:~p~n",[Name]),
+ Result = case asn1_db:dbget(S#state.mname,Name) of
+ undefined ->
+ error({type,{internal_error,'???'},S});
+ Type when record(Type,ptypedef) ->
+ NewS = S#state{type=Type,tname=Name},
+ case catch(check_ptype(NewS,Type,Type#ptypedef.typespec)) of
+ {error,Reason} ->
+ error({type,Reason,NewS});
+ {'EXIT',Reason} ->
+ error({type,{internal_error,Reason},NewS});
+ {asn1_class,_ClassDef} ->
+ {asn1_class,Name};
+ Ts ->
+ NewType = Type#ptypedef{checked=true,typespec = Ts},
+ asn1_db:dbput(NewS#state.mname,Name,NewType), % update the type
+ ok
+ end
+ end,
+ case Result of
+ ok ->
+ checkp(S,T,Acc);
+ _ ->
+ checkp(S,T,[Result|Acc])
+ end;
+checkp(_S,[],Acc) ->
+ lists:reverse(Acc).
+
+
+
+
+checkc(S,[Name|Cs],Acc) ->
+ Result =
+ case asn1_db:dbget(S#state.mname,Name) of
+ undefined ->
+ error({class,{internal_error,'???'},S});
+ Class ->
+ ClassSpec = if
+ record(Class,classdef) ->
+ Class#classdef.typespec;
+ record(Class,typedef) ->
+ Class#typedef.typespec
+ end,
+ NewS = S#state{type=Class,tname=Name},
+ case catch(check_class(NewS,ClassSpec)) of
+ {error,Reason} ->
+ error({class,Reason,NewS});
+ {'EXIT',Reason} ->
+ error({class,{internal_error,Reason},NewS});
+ C ->
+ %% update the classdef
+ NewClass =
+ if
+ record(Class,classdef) ->
+ Class#classdef{checked=true,typespec=C};
+ record(Class,typedef) ->
+ #classdef{checked=true,name=Name,typespec=C}
+ end,
+ asn1_db:dbput(NewS#state.mname,Name,NewClass),
+ ok
+ end
+ end,
+ case Result of
+ ok ->
+ checkc(S,Cs,Acc);
+ _ ->
+ checkc(S,Cs,[Result|Acc])
+ end;
+checkc(_S,[],Acc) ->
+%% include_default_class(S#state.mname),
+ lists:reverse(Acc).
+
+checko(S,[Name|Os],Acc,ExclO,ExclOS) ->
+ Result =
+ case asn1_db:dbget(S#state.mname,Name) of
+ undefined ->
+ error({type,{internal_error,'???'},S});
+ Object when record(Object,typedef) ->
+ NewS = S#state{type=Object,tname=Name},
+ case catch(check_object(NewS,Object,Object#typedef.typespec)) of
+ {error,Reason} ->
+ error({type,Reason,NewS});
+ {'EXIT',Reason} ->
+ error({type,{internal_error,Reason},NewS});
+ {asn1,Reason} ->
+ error({type,Reason,NewS});
+ O ->
+ NewObj = Object#typedef{checked=true,typespec=O},
+ asn1_db:dbput(NewS#state.mname,Name,NewObj),
+ if
+ record(O,'Object') ->
+ case O#'Object'.gen of
+ true ->
+ {ok,ExclO,ExclOS};
+ false ->
+ {ok,[Name|ExclO],ExclOS}
+ end;
+ record(O,'ObjectSet') ->
+ case O#'ObjectSet'.gen of
+ true ->
+ {ok,ExclO,ExclOS};
+ false ->
+ {ok,ExclO,[Name|ExclOS]}
+ end
+ end
+ end;
+ PObject when record(PObject,pobjectdef) ->
+ NewS = S#state{type=PObject,tname=Name},
+ case (catch check_pobject(NewS,PObject)) of
+ {error,Reason} ->
+ error({type,Reason,NewS});
+ {'EXIT',Reason} ->
+ error({type,{internal_error,Reason},NewS});
+ {asn1,Reason} ->
+ error({type,Reason,NewS});
+ PO ->
+ NewPObj = PObject#pobjectdef{def=PO},
+ asn1_db:dbput(NewS#state.mname,Name,NewPObj),
+ {ok,[Name|ExclO],ExclOS}
+ end;
+ PObjSet when record(PObjSet,pvaluesetdef) ->
+ %% this is a parameterized object set. Might be a parameterized
+ %% value set, couldn't it?
+ NewS = S#state{type=PObjSet,tname=Name},
+ case (catch check_pobjectset(NewS,PObjSet)) of
+ {error,Reason} ->
+ error({type,Reason,NewS});
+ {'EXIT',Reason} ->
+ error({type,{internal_error,Reason},NewS});
+ {asn1,Reason} ->
+ error({type,Reason,NewS});
+ POS ->
+ %%NewPObjSet = PObjSet#pvaluesetdef{valueset=POS},
+ asn1_db:dbput(NewS#state.mname,Name,POS),
+ {ok,ExclO,[Name|ExclOS]}
+ end
+ end,
+ case Result of
+ {ok,NewExclO,NewExclOS} ->
+ checko(S,Os,Acc,NewExclO,NewExclOS);
+ _ ->
+ checko(S,Os,[Result|Acc],ExclO,ExclOS)
+ end;
+checko(_S,[],Acc,ExclO,ExclOS) ->
+ {lists:reverse(Acc),lists:reverse(ExclO),lists:reverse(ExclOS)}.
+
+check_class(S,CDef=#classdef{checked=Ch,name=Name,typespec=TS}) ->
+ case Ch of
+ true -> TS;
+ idle -> TS;
+ _ ->
+ NewCDef = CDef#classdef{checked=idle},
+ asn1_db:dbput(S#state.mname,Name,NewCDef),
+ CheckedTS = check_class(S,TS),
+ asn1_db:dbput(S#state.mname,Name,
+ NewCDef#classdef{checked=true,
+ typespec=CheckedTS}),
+ CheckedTS
+ end;
+check_class(S = #state{mname=M,tname=T},ClassSpec)
+ when record(ClassSpec,type) ->
+ Def = ClassSpec#type.def,
+ case Def of
+ #'Externaltypereference'{module=M,type=T} ->
+ #objectclass{fields=Def}; % in case of recursive definitions
+ Tref when record(Tref,'Externaltypereference') ->
+ {_,RefType} = get_referenced_type(S,Tref),
+% case RefType of
+% RefClass when record(RefClass,classdef) ->
+% check_class(S,RefClass#classdef.typespec)
+% end
+ case is_class(S,RefType) of
+ true ->
+ check_class(S,get_class_def(S,RefType));
+ _ ->
+ error({class,{internal_error,RefType},S})
+ end
+ end;
+% check_class(S,{objectclassname,ModuleName,ClassName}) when atom(ModuleName),atom(ClassName) ->
+% 'fix this';
+check_class(S,C) when record(C,objectclass) ->
+ NewFieldSpec = check_class_fields(S,C#objectclass.fields),
+ C#objectclass{fields=NewFieldSpec};
+%check_class(S,{objectclassname,ClassName}) ->
+check_class(S,ClassName) ->
+ {_,Def} = get_referenced_type(S,ClassName),
+ case Def of
+ ClassDef when record(ClassDef,classdef) ->
+ case ClassDef#classdef.checked of
+ true ->
+ ClassDef#classdef.typespec;
+ idle ->
+ ClassDef#classdef.typespec;
+ false ->
+ check_class(S,ClassDef#classdef.typespec)
+ end;
+ TypeDef when record(TypeDef,typedef) ->
+ %% this case may occur when a definition is a reference
+ %% to a class definition.
+ case TypeDef#typedef.typespec of
+ #type{def=Ext} when record(Ext,'Externaltypereference') ->
+ check_class(S,Ext)
+ end
+ end;
+check_class(_S,{poc,_ObjSet,_Params}) ->
+ 'fix this later'.
+
+check_class_fields(S,Fields) ->
+ check_class_fields(S,Fields,[]).
+
+check_class_fields(S,[F|Fields],Acc) ->
+ NewField =
+ case element(1,F) of
+ fixedtypevaluefield ->
+ {_,Name,Type,Unique,OSpec} = F,
+ RefType = check_type(S,#typedef{typespec=Type},Type),
+ {fixedtypevaluefield,Name,RefType,Unique,OSpec};
+ object_or_fixedtypevalue_field ->
+ {_,Name,Type,Unique,OSpec} = F,
+ Cat =
+ case asn1ct_gen:type(asn1ct_gen:get_inner(Type#type.def)) of
+ Def when record(Def,typereference);
+ record(Def,'Externaltypereference') ->
+ {_,D} = get_referenced_type(S,Def),
+ D;
+ {undefined,user} ->
+ %% neither of {primitive,bif} or {constructed,bif}
+%% {_,D} = get_referenced_type(S,#typereference{val=Type#type.def}),
+ {_,D} = get_referenced_type(S,#'Externaltypereference'{module=S#state.mname,type=Type#type.def}),
+ D;
+ _ ->
+ Type
+ end,
+ case Cat of
+ Class when record(Class,classdef) ->
+ {objectfield,Name,Type,Unique,OSpec};
+ _ ->
+ RefType = check_type(S,#typedef{typespec=Type},Type),
+ {fixedtypevaluefield,Name,RefType,Unique,OSpec}
+ end;
+ objectset_or_fixedtypevalueset_field ->
+ {_,Name,Type,OSpec} = F,
+%% RefType = check_type(S,#typedef{typespec=Type},Type),
+ RefType =
+ case (catch check_type(S,#typedef{typespec=Type},Type)) of
+ {asn1_class,_ClassDef} ->
+ case if_current_checked_type(S,Type) of
+ true ->
+ Type#type.def;
+ _ ->
+ check_class(S,Type)
+ end;
+ CheckedType when record(CheckedType,type) ->
+ CheckedType;
+ _ ->
+ error({class,"internal error, check_class_fields",S})
+ end,
+ if
+ record(RefType,'Externaltypereference') ->
+ {objectsetfield,Name,Type,OSpec};
+ record(RefType,classdef) ->
+ {objectsetfield,Name,Type,OSpec};
+ record(RefType,objectclass) ->
+ {objectsetfield,Name,Type,OSpec};
+ true ->
+ {fixedtypevaluesetfield,Name,RefType,OSpec}
+ end;
+ typefield ->
+ case F of
+ {TF,Name,{'DEFAULT',Type}} ->
+ {TF,Name,{'DEFAULT',check_type(S,#typedef{typespec=Type},Type)}};
+ _ -> F
+ end;
+ _ -> F
+ end,
+ check_class_fields(S,Fields,[NewField|Acc]);
+check_class_fields(_S,[],Acc) ->
+ lists:reverse(Acc).
+
+if_current_checked_type(S,#type{def=Def}) ->
+ CurrentCheckedName = S#state.tname,
+ MergedModules = S#state.inputmodules,
+ % CurrentCheckedModule = S#state.mname,
+ case Def of
+ #'Externaltypereference'{module=CurrentCheckedName,
+ type=CurrentCheckedName} ->
+ true;
+ #'Externaltypereference'{module=ModuleName,
+ type=CurrentCheckedName} ->
+ case MergedModules of
+ undefined ->
+ false;
+ _ ->
+ lists:member(ModuleName,MergedModules)
+ end;
+ _ ->
+ false
+ end.
+
+
+
+check_pobject(_S,PObject) when record(PObject,pobjectdef) ->
+ Def = PObject#pobjectdef.def,
+ Def.
+
+
+check_pobjectset(S,PObjSet) ->
+ #pvaluesetdef{pos=Pos,name=Name,args=Args,type=Type,
+ valueset=ValueSet}=PObjSet,
+ {Mod,Def} = get_referenced_type(S,Type#type.def),
+ case Def of
+ #classdef{} ->
+ ClassName = #'Externaltypereference'{module=Mod,
+ type=Def#classdef.name},
+ {valueset,Set} = ValueSet,
+% ObjectSet = #'ObjectSet'{class={objectclassname,ClassName},
+ ObjectSet = #'ObjectSet'{class=ClassName,
+ set=Set},
+ #pobjectsetdef{pos=Pos,name=Name,args=Args,class=Type#type.def,
+ def=ObjectSet};
+ _ ->
+ PObjSet
+ end.
+
+check_object(_S,ObjDef,ObjSpec) when (ObjDef#typedef.checked == true) ->
+ ObjSpec;
+check_object(S,_ObjDef,#'Object'{classname=ClassRef,def=ObjectDef}) ->
+ {_,_ClassDef} = get_referenced_type(S,ClassRef),
+ NewClassRef = check_externaltypereference(S,ClassRef),
+ ClassDef =
+ case _ClassDef#classdef.checked of
+ false ->
+ #classdef{checked=true,
+ typespec=check_class(S,_ClassDef#classdef.typespec)};
+ _ ->
+ _ClassDef
+ end,
+ NewObj =
+ case ObjectDef of
+ Def when tuple(Def), (element(1,Def)==object) ->
+ NewSettingList = check_objectdefn(S,Def,ClassDef),
+ #'Object'{def=NewSettingList};
+% Def when tuple(Def), (element(1,Def)=='ObjectFromObject') ->
+% fixa;
+ {po,{object,DefObj},ArgsList} ->
+ {_,Object} = get_referenced_type(S,DefObj),%DefObj is a
+ %%#'Externalvaluereference' or a #'Externaltypereference'
+ %% Maybe this call should be catched and in case of an exception
+ %% an nonallocated parameterized object should be returned.
+ instantiate_po(S,ClassDef,Object,ArgsList);
+ #'Externalvaluereference'{} ->
+ {_,Object} = get_referenced_type(S,ObjectDef),
+ check_object(S,Object,Object#typedef.typespec);
+ _ ->
+ exit({error,{no_object,ObjectDef},S})
+ end,
+ Gen = gen_incl(S,NewObj#'Object'.def,
+ (ClassDef#classdef.typespec)#objectclass.fields),
+ NewObj#'Object'{classname=NewClassRef,gen=Gen};
+
+%%check_object(S,ObjSetDef,ObjSet=#type{def={pt,ObjSetRef,Args}}) ->
+ %% A parameterized
+
+check_object(S,
+ _ObjSetDef,
+ ObjSet=#'ObjectSet'{class=ClassRef}) ->
+ {_,ClassDef} = get_referenced_type(S,ClassRef),
+ NewClassRef = check_externaltypereference(S,ClassRef),
+ UniqueFieldName =
+ case (catch get_unique_fieldname(ClassDef)) of
+ {error,'__undefined_'} -> {unique,undefined};
+ {asn1,Msg,_} -> error({class,Msg,S});
+ Other -> Other
+ end,
+ NewObjSet=
+ case ObjSet#'ObjectSet'.set of
+ {'SingleValue',Set} when list(Set) ->
+ CheckedSet = check_object_list(S,NewClassRef,Set),
+ NewSet = get_unique_valuelist(S,CheckedSet,UniqueFieldName),
+ ObjSet#'ObjectSet'{uniquefname=UniqueFieldName,
+ set=NewSet};
+ {'SingleValue',{definedvalue,ObjName}} ->
+ {_,ObjDef} = get_referenced_type(S,#identifier{val=ObjName}),
+ #'Object'{def=CheckedObj} =
+ check_object(S,ObjDef,ObjDef#typedef.typespec),
+ NewSet = get_unique_valuelist(S,[{ObjDef#typedef.name,
+ CheckedObj}],
+ UniqueFieldName),
+ ObjSet#'ObjectSet'{uniquefname=UniqueFieldName,
+ set=NewSet};
+ {'SingleValue',#'Externalvaluereference'{value=ObjName}} ->
+ {_,ObjDef} = get_referenced_type(S,#identifier{val=ObjName}),
+ #'Object'{def=CheckedObj} =
+ check_object(S,ObjDef,ObjDef#typedef.typespec),
+ NewSet = get_unique_valuelist(S,[{ObjDef#typedef.name,
+ CheckedObj}],
+ UniqueFieldName),
+ ObjSet#'ObjectSet'{uniquefname=UniqueFieldName,
+ set=NewSet};
+ ['EXTENSIONMARK'] ->
+ ObjSet#'ObjectSet'{uniquefname=UniqueFieldName,
+ set=['EXTENSIONMARK']};
+ Set when list(Set) ->
+ CheckedSet = check_object_list(S,NewClassRef,Set),
+ NewSet = get_unique_valuelist(S,CheckedSet,UniqueFieldName),
+ ObjSet#'ObjectSet'{uniquefname=UniqueFieldName,
+ set=NewSet};
+ {Set,Ext} when list(Set) ->
+ CheckedSet = check_object_list(S,NewClassRef,Set++Ext),
+ NewSet = get_unique_valuelist(S,CheckedSet,UniqueFieldName),
+ ObjSet#'ObjectSet'{uniquefname=UniqueFieldName,
+ set=NewSet++['EXTENSIONMARK']};
+ {{'SingleValue',Set},Ext} ->
+ CheckedSet = check_object_list(S,NewClassRef,
+ merge_sets(Set,Ext)),
+ NewSet = get_unique_valuelist(S,CheckedSet,UniqueFieldName),
+ ObjSet#'ObjectSet'{uniquefname=UniqueFieldName,
+ set=NewSet++['EXTENSIONMARK']};
+ {Type,{'EXCEPT',Exclusion}} when record(Type,type) ->
+ {_,TDef} = get_referenced_type(S,Type#type.def),
+ OS = TDef#typedef.typespec,
+ NewSet = reduce_objectset(OS#'ObjectSet'.set,Exclusion),
+ NewOS = OS#'ObjectSet'{set=NewSet},
+ check_object(S,TDef#typedef{typespec=NewOS},
+ NewOS);
+ #type{def={pt,DefinedObjSet,ParamList}} ->
+ {_,PObjSetDef} = get_referenced_type(S,DefinedObjSet),
+ instantiate_pos(S,ClassDef,PObjSetDef,ParamList);
+ {ObjDef={object,definedsyntax,_ObjFields},_Ext} ->
+ CheckedSet = check_object_list(S,NewClassRef,[ObjDef]),
+ NewSet = get_unique_valuelist(S,CheckedSet,UniqueFieldName),
+ ObjSet#'ObjectSet'{uniquefname=UniqueFieldName,
+ set=NewSet++['EXTENSIONMARK']}
+ end,
+ Gen = gen_incl_set(S,NewObjSet#'ObjectSet'.set,
+ ClassDef),
+ NewObjSet#'ObjectSet'{class=NewClassRef,gen=Gen}.
+
+
+merge_sets(Set,Ext) when list(Set),list(Ext) ->
+ Set ++ Ext;
+merge_sets(Set,Ext) when list(Ext) ->
+ [Set|Ext];
+merge_sets(Set,{'SingleValue',Ext}) when list(Set) ->
+ Set ++ [Ext];
+merge_sets(Set,{'SingleValue',Ext}) ->
+ [Set] ++ [Ext].
+
+reduce_objectset(ObjectSet,Exclusion) ->
+ case Exclusion of
+ {'SingleValue',#'Externalvaluereference'{value=Name}} ->
+ case lists:keysearch(Name,1,ObjectSet) of
+ {value,El} ->
+ lists:subtract(ObjectSet,[El]);
+ _ ->
+ ObjectSet
+ end
+ end.
+
+%% Checks a list of objects or object sets and returns a list of selected
+%% information for the code generation.
+check_object_list(S,ClassRef,ObjectList) ->
+ check_object_list(S,ClassRef,ObjectList,[]).
+
+check_object_list(S,ClassRef,[ObjOrSet|Objs],Acc) ->
+ case ObjOrSet of
+ ObjDef when tuple(ObjDef),(element(1,ObjDef)==object) ->
+ Def =
+ check_object(S,#typedef{typespec=ObjDef},
+% #'Object'{classname={objectclassname,ClassRef},
+ #'Object'{classname=ClassRef,
+ def=ObjDef}),
+ check_object_list(S,ClassRef,Objs,[{no_name,Def#'Object'.def}|Acc]);
+ {'SingleValue',{definedvalue,ObjName}} ->
+ {_,ObjectDef} = get_referenced_type(S,#identifier{val=ObjName}),
+ #'Object'{def=Def} = check_object(S,ObjectDef,ObjectDef#typedef.typespec),
+ check_object_list(S,ClassRef,Objs,[{ObjectDef#typedef.name,Def}|Acc]);
+ {'SingleValue',Ref = #'Externalvaluereference'{}} ->
+ {_,ObjectDef} = get_referenced_type(S,Ref),
+ #'Object'{def=Def} = check_object(S,ObjectDef,ObjectDef#typedef.typespec),
+ check_object_list(S,ClassRef,Objs,[{ObjectDef#typedef.name,Def}|Acc]);
+ ObjRef when record(ObjRef,'Externalvaluereference') ->
+ {_,ObjectDef} = get_referenced_type(S,ObjRef),
+ #'Object'{def=Def} = check_object(S,ObjectDef,ObjectDef#typedef.typespec),
+ check_object_list(S,ClassRef,Objs,
+%% [{ObjRef#'Externalvaluereference'.value,Def}|Acc]);
+ [{ObjectDef#typedef.name,Def}|Acc]);
+ {'ValueFromObject',{_,Object},FieldName} ->
+ {_,Def} = get_referenced_type(S,Object),
+%% TypeOrVal = get_fieldname_element(S,Def,FieldName);%% this must result in an object set
+ TypeDef = get_fieldname_element(S,Def,FieldName),
+ (TypeDef#typedef.typespec)#'ObjectSet'.set;
+ ObjSet when record(ObjSet,type) ->
+ ObjSetDef =
+ case ObjSet#type.def of
+ Ref when record(Ref,typereference);
+ record(Ref,'Externaltypereference') ->
+ {_,D} = get_referenced_type(S,ObjSet#type.def),
+ D;
+ Other ->
+ throw({asn1_error,{'unknown objecset',Other,S}})
+ end,
+ #'ObjectSet'{set=ObjectsInSet} =
+ check_object(S,ObjSetDef,ObjSetDef#typedef.typespec),
+ AccList = transform_set_to_object_list(ObjectsInSet,[]),
+ check_object_list(S,ClassRef,Objs,AccList++Acc);
+ union ->
+ check_object_list(S,ClassRef,Objs,Acc);
+ Other ->
+ exit({error,{'unknown object',Other},S})
+ end;
+%% Finally reverse the accumulated list and if there are any extension
+%% marks in the object set put one indicator of that in the end of the
+%% list.
+check_object_list(_,_,[],Acc) ->
+ lists:reverse(Acc).
+%% case lists:member('EXTENSIONMARK',RevAcc) of
+%% true ->
+%% ExclRevAcc = lists:filter(fun(X)->X /= 'EXTENSIONMARK' end,
+%% RevAcc),
+%% ExclRevAcc ++ ['EXTENSIONMARK'];
+%% false ->
+%% RevAcc
+%% end.
+
+
+%% get_fieldname_element/3
+%% gets the type/value/object/... of the referenced element in FieldName
+%% FieldName is a list and may have more than one element.
+%% Each element in FieldName can be either {typefieldreference,AnyFieldName}
+%% or {valuefieldreference,AnyFieldName}
+%% Def is the def of the first object referenced by FieldName
+get_fieldname_element(S,Def,[{_RefType,FieldName}]) when record(Def,typedef) ->
+ {_,_,ObjComps} = (Def#typedef.typespec)#'Object'.def,
+ case lists:keysearch(FieldName,1,ObjComps) of
+ {value,{_,TDef}} when record(TDef,typedef) ->
+ %% ORec = TDef#typedef.typespec, %% XXX This must be made general
+% case TDef#typedef.typespec of
+% ObjSetRec when record(ObjSetRec,'ObjectSet') ->
+% ObjSet = ObjSetRec#'ObjectSet'.set;
+% ObjRec when record(ObjRec,'Object') ->
+% %% now get the field in ObjRec that RestFName points out
+% %ObjRec
+% TDef
+% end;
+ TDef;
+ {value,{_,VDef}} when record(VDef,valuedef) ->
+ check_value(S,VDef);
+ _ ->
+ throw({assigned_object_error,"not_assigned_object",S})
+ end;
+get_fieldname_element(_S,Def,[{_RefType,_FieldName}|_RestFName])
+ when record(Def,typedef) ->
+ ok.
+
+transform_set_to_object_list([{Name,_UVal,Fields}|Objs],Acc) ->
+ transform_set_to_object_list(Objs,[{Name,{object,generatesyntax,Fields}}|Acc]);
+transform_set_to_object_list(['EXTENSIONMARK'|Objs],Acc) ->
+%% transform_set_to_object_list(Objs,['EXTENSIONMARK'|Acc]);
+ transform_set_to_object_list(Objs,Acc);
+transform_set_to_object_list([],Acc) ->
+ Acc.
+
+get_unique_valuelist(_S,ObjSet,{unique,undefined}) -> % no unique field in object
+ lists:map(fun({N,{_,_,F}})->{N,F};
+ (V={_,_,_}) ->V end, ObjSet);
+get_unique_valuelist(S,ObjSet,UFN) ->
+ get_unique_vlist(S,ObjSet,UFN,[]).
+
+get_unique_vlist(S,[],_,Acc) ->
+ case catch check_uniqueness(Acc) of
+ {asn1_error,_} ->
+% exit({error,Reason,S});
+ error({'ObjectSet',"not unique objects in object set",S});
+ true ->
+ lists:reverse(Acc)
+ end;
+get_unique_vlist(S,[{ObjName,Obj}|Rest],UniqueFieldName,Acc) ->
+ {_,_,Fields} = Obj,
+ VDef = get_unique_value(S,Fields,UniqueFieldName),
+ get_unique_vlist(S,Rest,UniqueFieldName,
+ [{ObjName,VDef#valuedef.value,Fields}|Acc]);
+get_unique_vlist(S,[V={_,_,_}|Rest],UniqueFieldName,Acc) ->
+ get_unique_vlist(S,Rest,UniqueFieldName,[V|Acc]).
+
+get_unique_value(S,Fields,UniqueFieldName) ->
+ Module = S#state.mname,
+ case lists:keysearch(UniqueFieldName,1,Fields) of
+ {value,Field} ->
+ case element(2,Field) of
+ VDef when record(VDef,valuedef) ->
+ VDef;
+ {definedvalue,ValName} ->
+ ValueDef = asn1_db:dbget(Module,ValName),
+ case ValueDef of
+ VDef when record(VDef,valuedef) ->
+ ValueDef;
+ undefined ->
+ #valuedef{value=ValName}
+ end;
+ {'ValueFromObject',Object,Name} ->
+ case Object of
+ {object,Ext} when record(Ext,'Externaltypereference') ->
+ OtherModule = Ext#'Externaltypereference'.module,
+ ExtObjName = Ext#'Externaltypereference'.type,
+ ObjDef = asn1_db:dbget(OtherModule,ExtObjName),
+ ObjSpec = ObjDef#typedef.typespec,
+ get_unique_value(OtherModule,element(3,ObjSpec),Name);
+ {object,{_,_,ObjName}} ->
+ ObjDef = asn1_db:dbget(Module,ObjName),
+ ObjSpec = ObjDef#typedef.typespec,
+ get_unique_value(Module,element(3,ObjSpec),Name);
+ {po,Object,_Params} ->
+ exit({error,{'parameterized object not implemented yet',
+ Object},S})
+ end;
+ Value when atom(Value);number(Value) ->
+ #valuedef{value=Value};
+ {'CHOICE',{_,Value}} when atom(Value);number(Value) ->
+ #valuedef{value=Value}
+ end;
+ false ->
+ exit({error,{'no unique value',Fields,UniqueFieldName},S})
+%% io:format("WARNING: no unique value in object"),
+%% exit(uniqueFieldName)
+ end.
+
+check_uniqueness(NameValueList) ->
+ check_uniqueness1(lists:keysort(2,NameValueList)).
+
+check_uniqueness1([]) ->
+ true;
+check_uniqueness1([_]) ->
+ true;
+check_uniqueness1([{_,N,_},{_,N,_}|_Rest]) ->
+ throw({asn1_error,{'objects in set must have unique values in UNIQUE fields',N}});
+check_uniqueness1([_|Rest]) ->
+ check_uniqueness1(Rest).
+
+%% instantiate_po/4
+%% ClassDef is the class of Object,
+%% Object is the Parameterized object, which is referenced,
+%% ArgsList is the list of actual parameters
+%% returns an #'Object' record.
+instantiate_po(S,_ClassDef,Object,ArgsList) when record(Object,pobjectdef) ->
+ FormalParams = get_pt_args(Object),
+ MatchedArgs = match_args(FormalParams,ArgsList,[]),
+ NewS = S#state{type=Object,parameters=MatchedArgs},
+ check_object(NewS,Object,#'Object'{classname=Object#pobjectdef.class,
+ def=Object#pobjectdef.def}).
+
+%% instantiate_pos/4
+%% ClassDef is the class of ObjectSetDef,
+%% ObjectSetDef is the Parameterized object set, which is referenced
+%% on the right side of the assignment,
+%% ArgsList is the list of actual parameters, i.e. real objects
+instantiate_pos(S,ClassDef,ObjectSetDef,ArgsList) ->
+ ClassName = ClassDef#classdef.name,
+ FormalParams = get_pt_args(ObjectSetDef),
+ Set = case get_pt_spec(ObjectSetDef) of
+ {valueset,_Set} -> _Set;
+ _Set -> _Set
+ end,
+ MatchedArgs = match_args(FormalParams,ArgsList,[]),
+ NewS = S#state{type=ObjectSetDef,parameters=MatchedArgs},
+ check_object(NewS,ObjectSetDef,
+ #'ObjectSet'{class=name2Extref(S#state.mname,ClassName),
+ set=Set}).
+
+
+%% gen_incl -> boolean()
+%% If object with Fields has any of the corresponding class' typefields
+%% then return value is true otherwise it is false.
+%% If an object lacks a typefield but the class has a type field that
+%% is OPTIONAL then we want gen to be true
+gen_incl(S,{_,_,Fields},CFields)->
+ gen_incl1(S,Fields,CFields).
+
+gen_incl1(_,_,[]) ->
+ false;
+gen_incl1(S,Fields,[C|CFields]) ->
+ case element(1,C) of
+ typefield ->
+% case lists:keymember(element(2,C),1,Fields) of
+% true ->
+% true;
+% false ->
+% gen_incl1(S,Fields,CFields)
+% end;
+ true; %% should check that field is OPTIONAL or DEFUALT if
+ %% the object lacks this field
+ objectfield ->
+ case lists:keysearch(element(2,C),1,Fields) of
+ {value,Field} ->
+ Type = element(3,C),
+ {_,ClassDef} = get_referenced_type(S,Type#type.def),
+% {_,ClassFields,_} = ClassDef#classdef.typespec,
+ #objectclass{fields=ClassFields} =
+ ClassDef#classdef.typespec,
+ ObjTDef = element(2,Field),
+ case gen_incl(S,(ObjTDef#typedef.typespec)#'Object'.def,
+ ClassFields) of
+ true ->
+ true;
+ _ ->
+ gen_incl1(S,Fields,CFields)
+ end;
+ _ ->
+ gen_incl1(S,Fields,CFields)
+ end;
+ _ ->
+ gen_incl1(S,Fields,CFields)
+ end.
+
+%% first if no unique field in the class return false.(don't generate code)
+gen_incl_set(S,Fields,ClassDef) ->
+ case catch get_unique_fieldname(ClassDef) of
+ Tuple when tuple(Tuple) ->
+ false;
+ _ ->
+ gen_incl_set1(S,Fields,
+ (ClassDef#classdef.typespec)#objectclass.fields)
+ end.
+
+%% if any of the existing or potentially existing objects has a typefield
+%% then return true.
+gen_incl_set1(_,[],_CFields)->
+ false;
+gen_incl_set1(_,['EXTENSIONMARK'],_) ->
+ true;
+%% Fields are the fields of an object in the object set.
+%% CFields are the fields of the class of the object set.
+gen_incl_set1(S,[Object|Rest],CFields)->
+ Fields = element(size(Object),Object),
+ case gen_incl1(S,Fields,CFields) of
+ true ->
+ true;
+ false ->
+ gen_incl_set1(S,Rest,CFields)
+ end.
+
+check_objectdefn(S,Def,CDef) when record(CDef,classdef) ->
+ WithSyntax = (CDef#classdef.typespec)#objectclass.syntax,
+ ClassFields = (CDef#classdef.typespec)#objectclass.fields,
+ case Def of
+ {object,defaultsyntax,Fields} ->
+ check_defaultfields(S,Fields,ClassFields);
+ {object,definedsyntax,Fields} ->
+ {_,WSSpec} = WithSyntax,
+ NewFields =
+ case catch( convert_definedsyntax(S,Fields,WSSpec,
+ ClassFields,[])) of
+ {asn1,{_ErrorType,ObjToken,ClassToken}} ->
+ throw({asn1,{'match error in object',ObjToken,
+ 'found in object',ClassToken,'found in class'}});
+ Err={asn1,_} -> throw(Err);
+ Err={'EXIT',_} -> throw(Err);
+ DefaultFields when list(DefaultFields) ->
+ DefaultFields
+ end,
+ {object,defaultsyntax,NewFields};
+ {object,_ObjectId} -> % This is a DefinedObject
+ fixa;
+ Other ->
+ exit({error,{objectdefn,Other}})
+ end.
+
+check_defaultfields(S,Fields,ClassFields) ->
+ check_defaultfields(S,Fields,ClassFields,[]).
+
+check_defaultfields(_S,[],_ClassFields,Acc) ->
+ {object,defaultsyntax,lists:reverse(Acc)};
+check_defaultfields(S,[{FName,Spec}|Fields],ClassFields,Acc) ->
+ case lists:keysearch(FName,2,ClassFields) of
+ {value,CField} ->
+ NewField = convert_to_defaultfield(S,FName,Spec,CField),
+ check_defaultfields(S,Fields,ClassFields,[NewField|Acc]);
+ _ ->
+ throw({error,{asn1,{'unvalid field in object',FName}}})
+ end.
+%% {object,defaultsyntax,Fields}.
+
+convert_definedsyntax(_S,[],[],_ClassFields,Acc) ->
+ lists:reverse(Acc);
+convert_definedsyntax(S,Fields,WithSyntax,ClassFields,Acc) ->
+ case match_field(S,Fields,WithSyntax,ClassFields) of
+ {MatchedField,RestFields,RestWS} ->
+ if
+ list(MatchedField) ->
+ convert_definedsyntax(S,RestFields,RestWS,ClassFields,
+ lists:append(MatchedField,Acc));
+ true ->
+ convert_definedsyntax(S,RestFields,RestWS,ClassFields,
+ [MatchedField|Acc])
+ end
+%% throw({error,{asn1,{'unvalid syntax in object',WorS}}})
+ end.
+
+match_field(S,Fields,WithSyntax,ClassFields) ->
+ match_field(S,Fields,WithSyntax,ClassFields,[]).
+
+match_field(S,Fields,[W|Ws],ClassFields,Acc) when list(W) ->
+ case catch(match_optional_field(S,Fields,W,ClassFields,[])) of
+ {'EXIT',_} ->
+ match_field(Fields,Ws,ClassFields,Acc); %% add S
+%% {[Result],RestFields} ->
+%% {Result,RestFields,Ws};
+ {Result,RestFields} when list(Result) ->
+ {Result,RestFields,Ws};
+ _ ->
+ match_field(S,Fields,Ws,ClassFields,Acc)
+ end;
+match_field(S,Fields,WithSyntax,ClassFields,_Acc) ->
+ match_mandatory_field(S,Fields,WithSyntax,ClassFields,[]).
+
+match_optional_field(_S,RestFields,[],_,Ret) ->
+ {Ret,RestFields};
+%% An additional optional field within an optional field
+match_optional_field(S,Fields,[W|Ws],ClassFields,Ret) when list(W) ->
+ case catch match_optional_field(S,Fields,W,ClassFields,[]) of
+ {'EXIT',_} ->
+ {Ret,Fields};
+ {asn1,{optional_matcherror,_,_}} ->
+ {Ret,Fields};
+ {OptionalField,RestFields} ->
+ match_optional_field(S,RestFields,Ws,ClassFields,
+ lists:append(OptionalField,Ret))
+ end;
+%% identify and skip word
+%match_optional_field(S,[#'Externaltypereference'{type=WorS}|Rest],
+match_optional_field(S,[{_,_,WorS}|Rest],
+ [WorS|Ws],ClassFields,Ret) ->
+ match_optional_field(S,Rest,Ws,ClassFields,Ret);
+match_optional_field(S,[],_,ClassFields,Ret) ->
+ match_optional_field(S,[],[],ClassFields,Ret);
+%% identify and skip comma
+match_optional_field(S,[{WorS,_}|Rest],[{WorS,_}|Ws],ClassFields,Ret) ->
+ match_optional_field(S,Rest,Ws,ClassFields,Ret);
+%% identify and save field data
+match_optional_field(S,[Setting|Rest],[{_,W}|Ws],ClassFields,Ret) ->
+ WorS =
+ case Setting of
+ Type when record(Type,type) -> Type;
+%% #'Externalvaluereference'{value=WordOrSetting} -> WordOrSetting;
+ {'ValueFromObject',_,_} -> Setting;
+ {object,_,_} -> Setting;
+ {_,_,WordOrSetting} -> WordOrSetting;
+%% Atom when atom(Atom) -> Atom
+ Other -> Other
+ end,
+ case lists:keysearch(W,2,ClassFields) of
+ false ->
+ throw({asn1,{optional_matcherror,WorS,W}});
+ {value,CField} ->
+ NewField = convert_to_defaultfield(S,W,WorS,CField),
+ match_optional_field(S,Rest,Ws,ClassFields,[NewField|Ret])
+ end;
+match_optional_field(_S,[WorS|_Rest],[W|_Ws],_ClassFields,_Ret) ->
+ throw({asn1,{optional_matcherror,WorS,W}}).
+
+match_mandatory_field(_S,[],[],_,[Acc]) ->
+ {Acc,[],[]};
+match_mandatory_field(_S,[],[],_,Acc) ->
+ {Acc,[],[]};
+match_mandatory_field(S,[],[H|T],CF,Acc) when list(H) ->
+ match_mandatory_field(S,[],T,CF,Acc);
+match_mandatory_field(_S,[],WithSyntax,_,_Acc) ->
+ throw({asn1,{mandatory_matcherror,[],WithSyntax}});
+%match_mandatory_field(_S,Fields,WithSyntax=[W|_Ws],_ClassFields,[Acc]) when list(W) ->
+match_mandatory_field(_S,Fields,WithSyntax=[W|_Ws],_ClassFields,Acc) when list(W), length(Acc) >= 1 ->
+ {Acc,Fields,WithSyntax};
+%% identify and skip word
+match_mandatory_field(S,[{_,_,WorS}|Rest],
+ [WorS|Ws],ClassFields,Acc) ->
+ match_mandatory_field(S,Rest,Ws,ClassFields,Acc);
+%% identify and skip comma
+match_mandatory_field(S,[{WorS,_}|Rest],[{WorS,_}|Ws],ClassFields,Ret) ->
+ match_mandatory_field(S,Rest,Ws,ClassFields,Ret);
+%% identify and save field data
+match_mandatory_field(S,[Setting|Rest],[{_,W}|Ws],ClassFields,Acc) ->
+ WorS =
+ case Setting of
+%% Atom when atom(Atom) -> Atom;
+%% #'Externalvaluereference'{value=WordOrSetting} -> WordOrSetting;
+ {object,_,_} -> Setting;
+ {_,_,WordOrSetting} -> WordOrSetting;
+ Type when record(Type,type) -> Type;
+ Other -> Other
+ end,
+ case lists:keysearch(W,2,ClassFields) of
+ false ->
+ throw({asn1,{mandatory_matcherror,WorS,W}});
+ {value,CField} ->
+ NewField = convert_to_defaultfield(S,W,WorS,CField),
+ match_mandatory_field(S,Rest,Ws,ClassFields,[NewField|Acc])
+ end;
+
+match_mandatory_field(_S,[WorS|_Rest],[W|_Ws],_ClassFields,_Acc) ->
+ throw({asn1,{mandatory_matcherror,WorS,W}}).
+
+%% Converts a field of an object from defined syntax to default syntax
+convert_to_defaultfield(S,ObjFieldName,ObjFieldSetting,CField)->
+ CurrMod = S#state.mname,
+ case element(1,CField) of
+ typefield ->
+ TypeDef=
+ case ObjFieldSetting of
+ TypeRec when record(TypeRec,type) -> TypeRec#type.def;
+ TDef when record(TDef,typedef) ->
+ TDef#typedef{typespec=check_type(S,TDef,
+ TDef#typedef.typespec)};
+ _ -> ObjFieldSetting
+ end,
+ Type =
+ if
+ record(TypeDef,typedef) -> TypeDef;
+ true ->
+ case asn1ct_gen:type(asn1ct_gen:get_inner(TypeDef)) of
+ ERef = #'Externaltypereference'{module=CurrMod} ->
+ {_,T} = get_referenced_type(S,ERef),
+ T#typedef{checked=true,
+ typespec=check_type(S,T,
+ T#typedef.typespec)};
+ ERef = #'Externaltypereference'{module=ExtMod} ->
+ {_,T} = get_referenced_type(S,ERef),
+ #typedef{name=Name} = T,
+ check_type(S,T,T#typedef.typespec),
+ #typedef{checked=true,
+ name={ExtMod,Name},
+ typespec=ERef};
+ Bif when Bif=={primitive,bif};Bif=={constructed,bif} ->
+ T = check_type(S,#typedef{typespec=ObjFieldSetting},
+ ObjFieldSetting),
+ #typedef{checked=true,name=Bif,typespec=T};
+ _ ->
+ {Mod,T} =
+ %% get_referenced_type(S,#typereference{val=ObjFieldSetting}),
+ get_referenced_type(S,#'Externaltypereference'{module=S#state.mname,type=ObjFieldSetting}),
+ case Mod of
+ CurrMod ->
+ T;
+ ExtMod ->
+ #typedef{name=Name} = T,
+ T#typedef{name={ExtMod,Name}}
+ end
+ end
+ end,
+ {ObjFieldName,Type};
+ fixedtypevaluefield ->
+ case ObjFieldName of
+ Val when atom(Val) ->
+ %% ObjFieldSetting can be a value,an objectidentifiervalue,
+ %% an element in an enumeration or namednumberlist etc.
+ ValRef =
+ case ObjFieldSetting of
+ #'Externalvaluereference'{} -> ObjFieldSetting;
+ {'ValueFromObject',{_,ObjRef},FieldName} ->
+ {_,Object} = get_referenced_type(S,ObjRef),
+ ChObject = check_object(S,Object,
+ Object#typedef.typespec),
+ get_fieldname_element(S,Object#typedef{typespec=ChObject},
+ FieldName);
+ #valuedef{} ->
+ ObjFieldSetting;
+ _ ->
+ #identifier{val=ObjFieldSetting}
+ end,
+ case ValRef of
+ #valuedef{} ->
+ {ObjFieldName,check_value(S,ValRef)};
+ _ ->
+ ValDef =
+ case catch get_referenced_type(S,ValRef) of
+ {error,_} ->
+ check_value(S,#valuedef{name=Val,
+ type=element(3,CField),
+ value=ObjFieldSetting});
+ {_,VDef} when record(VDef,valuedef) ->
+ check_value(S,VDef);%% XXX
+ {_,VDef} ->
+ check_value(S,#valuedef{name=Val,
+ type=element(3,CField),
+ value=VDef})
+ end,
+ {ObjFieldName,ValDef}
+ end;
+ Val ->
+ {ObjFieldName,Val}
+ end;
+ fixedtypevaluesetfield ->
+ {ObjFieldName,ObjFieldSetting};
+ objectfield ->
+ ObjectSpec =
+ case ObjFieldSetting of
+ Ref when record(Ref,typereference);record(Ref,identifier);
+ record(Ref,'Externaltypereference');
+ record(Ref,'Externalvaluereference') ->
+ {_,R} = get_referenced_type(S,ObjFieldSetting),
+ R;
+ {'ValueFromObject',{_,ObjRef},FieldName} ->
+ %% This is an ObjectFromObject
+ {_,Object} = get_referenced_type(S,ObjRef),
+ ChObject = check_object(S,Object,
+ Object#typedef.typespec),
+ _ObjFromObj=
+ get_fieldname_element(S,Object#typedef{
+ typespec=ChObject},
+ FieldName);
+ %%ClassName = ObjFromObj#'Object'.classname,
+ %%#typedef{name=,
+ %% typespec=
+ %% ObjFromObj#'Object'{classname=
+ %% {objectclassname,ClassName}}};
+ {object,_,_} ->
+ %% An object defined inlined in another object
+ #type{def=Ref} = element(3,CField),
+% CRef = case Ref of
+% #'Externaltypereference'{module=CurrMod,
+% type=CName} ->
+% CName;
+% #'Externaltypereference'{module=ExtMod,
+% type=CName} ->
+% {ExtMod,CName}
+% end,
+ InlinedObjName=
+ list_to_atom(lists:concat([S#state.tname]++
+ ['_',ObjFieldName])),
+% ObjSpec = #'Object'{classname={objectclassname,CRef},
+ ObjSpec = #'Object'{classname=Ref,
+ def=ObjFieldSetting},
+ CheckedObj=
+ check_object(S,#typedef{typespec=ObjSpec},ObjSpec),
+ InlObj = #typedef{checked=true,name=InlinedObjName,
+ typespec=CheckedObj},
+ asn1ct_gen:insert_once(inlined_objects,{InlinedObjName,
+ InlinedObjName}),
+ asn1_db:dbput(S#state.mname,InlinedObjName,InlObj),
+ InlObj;
+ #type{def=Eref} when record(Eref,'Externaltypereference') ->
+ {_,R} = get_referenced_type(S,Eref),
+ R;
+ _ ->
+%% {_,R} = get_referenced_type(S,#typereference{val=ObjFieldSetting}),
+ {_,R} = get_referenced_type(S,#'Externaltypereference'{module=S#state.mname,type=ObjFieldSetting}),
+ R
+ end,
+ {ObjFieldName,
+ ObjectSpec#typedef{checked=true,
+ typespec=check_object(S,ObjectSpec,
+ ObjectSpec#typedef.typespec)}};
+ variabletypevaluefield ->
+ {ObjFieldName,ObjFieldSetting};
+ variabletypevaluesetfield ->
+ {ObjFieldName,ObjFieldSetting};
+ objectsetfield ->
+ {_,ObjSetSpec} =
+ case ObjFieldSetting of
+ Ref when record(Ref,'Externaltypereference');
+ record(Ref,'Externalvaluereference') ->
+ get_referenced_type(S,ObjFieldSetting);
+ ObjectList when list(ObjectList) ->
+ %% an objctset defined in the object,though maybe
+ %% parsed as a SequenceOfValue
+ %% The ObjectList may be a list of references to
+ %% objects, a ValueFromObject
+ {_,_,Type,_} = CField,
+ ClassDef = Type#type.def,
+ case ClassDef#'Externaltypereference'.module of
+ CurrMod ->
+ ClassDef#'Externaltypereference'.type;
+ ExtMod ->
+ {ExtMod,
+ ClassDef#'Externaltypereference'.type}
+ end,
+ {no_name,
+ #typedef{typespec=
+ #'ObjectSet'{class=
+% {objectclassname,ClassRef},
+ ClassDef,
+ set=ObjectList}}};
+ ObjectSet={'SingleValue',_} ->
+ %% a Union of defined objects
+ {_,_,Type,_} = CField,
+ ClassDef = Type#type.def,
+% ClassRef =
+% case ClassDef#'Externaltypereference'.module of
+% CurrMod ->
+% ClassDef#'Externaltypereference'.type;
+% ExtMod ->
+% {ExtMod,
+% ClassDef#'Externaltypereference'.type}
+% end,
+ {no_name,
+% #typedef{typespec=#'ObjectSet'{class={objectclassname,ClassRef},
+ #typedef{typespec=#'ObjectSet'{class=ClassDef,
+ set=ObjectSet}}};
+ {object,_,[#type{def={'TypeFromObject',
+ {object,RefedObj},
+ FieldName}}]} ->
+ %% This case occurs when an ObjectSetFromObjects
+ %% production is used
+ {M,Def} = get_referenced_type(S,RefedObj),
+ {M,get_fieldname_element(S,Def,FieldName)};
+ #type{def=Eref} when
+ record(Eref,'Externaltypereference') ->
+ get_referenced_type(S,Eref);
+ _ ->
+%% get_referenced_type(S,#typereference{val=ObjFieldSetting})
+ get_referenced_type(S,#'Externaltypereference'{module=S#state.mname,type=ObjFieldSetting})
+ end,
+ {ObjFieldName,
+ ObjSetSpec#typedef{checked=true,
+ typespec=check_object(S,ObjSetSpec,
+ ObjSetSpec#typedef.typespec)}}
+ end.
+
+check_value(OldS,V) when record(V,pvaluesetdef) ->
+ #pvaluesetdef{checked=Checked,type=Type} = V,
+ case Checked of
+ true -> V;
+ {error,_} -> V;
+ false ->
+ case get_referenced_type(OldS,Type#type.def) of
+ {_,Class} when record(Class,classdef) ->
+ throw({pobjectsetdef});
+ _ -> continue
+ end
+ end;
+check_value(_OldS,V) when record(V,pvaluedef) ->
+ %% Fix this case later
+ V;
+check_value(OldS,V) when record(V,typedef) ->
+ %% This case when a value set has been parsed as an object set.
+ %% It may be a value set
+ #typedef{typespec=TS} = V,
+ case TS of
+ #'ObjectSet'{class=ClassRef} ->
+ {_,TSDef} = get_referenced_type(OldS,ClassRef),
+ %%IsObjectSet(TSDef);
+ case TSDef of
+ #classdef{} -> throw({objectsetdef});
+ #typedef{typespec=#type{def=Eref}} when
+ record(Eref,'Externaltypereference') ->
+ %% This case if the class reference is a defined
+ %% reference to class
+ check_value(OldS,V#typedef{typespec=TS#'ObjectSet'{class=Eref}});
+ #typedef{} ->
+ % an ordinary value set with a type in #typedef.typespec
+ ValueSet = TS#'ObjectSet'.set,
+ Type=check_type(OldS,TSDef,TSDef#typedef.typespec),
+ Value = check_value(OldS,#valuedef{type=Type,
+ value=ValueSet}),
+ {valueset,Type#type{constraint=Value#valuedef.value}}
+ end;
+ _ ->
+ throw({objectsetdef})
+ end;
+check_value(S,#valuedef{pos=Pos,name=Name,type=Type,
+ value={valueset,Constr}}) ->
+ NewType = Type#type{constraint=[Constr]},
+ {valueset,
+ check_type(S,#typedef{pos=Pos,name=Name,typespec=NewType},NewType)};
+check_value(OldS=#state{recordtopname=TopName},V) when record(V,valuedef) ->
+ #valuedef{name=Name,checked=Checked,type=Vtype,value=Value} = V,
+ case Checked of
+ true ->
+ V;
+ {error,_} ->
+ V;
+ false ->
+ Def = Vtype#type.def,
+ Constr = Vtype#type.constraint,
+ S = OldS#state{type=Vtype,tname=Def,value=V,vname=Name},
+ NewDef =
+ case Def of
+ Ext when record(Ext,'Externaltypereference') ->
+ RecName = Ext#'Externaltypereference'.type,
+ {_,Type} = get_referenced_type(S,Ext),
+ %% If V isn't a value but an object Type is a #classdef{}
+ case Type of
+ #classdef{} ->
+ throw({objectdef});
+ #typedef{} ->
+ case is_contextswitchtype(Type) of
+ true ->
+ #valuedef{value=CheckedVal}=
+ check_value(S,V#valuedef{type=Type#typedef.typespec}),
+ #newv{value=CheckedVal};
+ _ ->
+ #valuedef{value=CheckedVal}=
+ check_value(S#state{recordtopname=[RecName|TopName]},
+ V#valuedef{type=Type#typedef.typespec}),
+ #newv{value=CheckedVal}
+ end
+ end;
+ 'ANY' ->
+ throw({error,{asn1,{'cant check value of type',Def}}});
+ 'INTEGER' ->
+ validate_integer(S,Value,[],Constr),
+ #newv{value=normalize_value(S,Vtype,Value,[])};
+ {'INTEGER',NamedNumberList} ->
+ validate_integer(S,Value,NamedNumberList,Constr),
+ #newv{value=normalize_value(S,Vtype,Value,[])};
+ {'BIT STRING',NamedNumberList} ->
+ validate_bitstring(S,Value,NamedNumberList,Constr),
+ #newv{value=normalize_value(S,Vtype,Value,[])};
+ 'NULL' ->
+ validate_null(S,Value,Constr),
+ #newv{};
+ 'OBJECT IDENTIFIER' ->
+ validate_objectidentifier(S,Value,Constr),
+ #newv{value = normalize_value(S,Vtype,Value,[])};
+ 'ObjectDescriptor' ->
+ validate_objectdescriptor(S,Value,Constr),
+ #newv{value=normalize_value(S,Vtype,Value,[])};
+ {'ENUMERATED',NamedNumberList} ->
+ validate_enumerated(S,Value,NamedNumberList,Constr),
+ #newv{value=normalize_value(S,Vtype,Value,[])};
+ 'BOOLEAN'->
+ validate_boolean(S,Value,Constr),
+ #newv{value=normalize_value(S,Vtype,Value,[])};
+ 'OCTET STRING' ->
+ validate_octetstring(S,Value,Constr),
+ #newv{value=normalize_value(S,Vtype,Value,[])};
+ 'NumericString' ->
+ validate_restrictedstring(S,Value,Def,Constr),
+ #newv{value=normalize_value(S,Vtype,Value,[])};
+ 'TeletexString' ->
+ validate_restrictedstring(S,Value,Def,Constr),
+ #newv{value=normalize_value(S,Vtype,Value,[])};
+ 'VideotexString' ->
+ validate_restrictedstring(S,Value,Def,Constr),
+ #newv{value=normalize_value(S,Vtype,Value,[])};
+ 'UTCTime' ->
+ #newv{value=normalize_value(S,Vtype,Value,[])};
+% exit({'cant check value of type' ,Def});
+ 'GeneralizedTime' ->
+ #newv{value=normalize_value(S,Vtype,Value,[])};
+% exit({'cant check value of type' ,Def});
+ 'GraphicString' ->
+ validate_restrictedstring(S,Value,Def,Constr),
+ #newv{value=normalize_value(S,Vtype,Value,[])};
+ 'VisibleString' ->
+ validate_restrictedstring(S,Value,Def,Constr),
+ #newv{value=normalize_value(S,Vtype,Value,[])};
+ 'GeneralString' ->
+ validate_restrictedstring(S,Value,Def,Constr),
+ #newv{value=normalize_value(S,Vtype,Value,[])};
+ 'PrintableString' ->
+ validate_restrictedstring(S,Value,Def,Constr),
+ #newv{value=normalize_value(S,Vtype,Value,[])};
+ 'IA5String' ->
+ validate_restrictedstring(S,Value,Def,Constr),
+ #newv{value=normalize_value(S,Vtype,Value,[])};
+ 'BMPString' ->
+ validate_restrictedstring(S,Value,Def,Constr),
+ #newv{value=normalize_value(S,Vtype,Value,[])};
+%% 'UniversalString' -> %added 6/12 -00
+%% #newv{value=validate_restrictedstring(S,Value,Def,Constr)};
+ Seq when record(Seq,'SEQUENCE') ->
+ SeqVal = validate_sequence(S,Value,
+ Seq#'SEQUENCE'.components,
+ Constr),
+ #newv{value=normalize_value(S,Vtype,SeqVal,TopName)};
+ {'SEQUENCE OF',Components} ->
+ validate_sequenceof(S,Value,Components,Constr),
+ #newv{value=normalize_value(S,Vtype,Value,TopName)};
+ {'CHOICE',Components} ->
+ validate_choice(S,Value,Components,Constr),
+ #newv{value=normalize_value(S,Vtype,Value,TopName)};
+ Set when record(Set,'SET') ->
+ validate_set(S,Value,Set#'SET'.components,
+ Constr),
+ #newv{value=normalize_value(S,Vtype,Value,TopName)};
+ {'SET OF',Components} ->
+ validate_setof(S,Value,Components,Constr),
+ #newv{value=normalize_value(S,Vtype,Value,TopName)};
+ Other ->
+ exit({'cant check value of type' ,Other})
+ end,
+ case NewDef#newv.value of
+ unchanged ->
+ V#valuedef{checked=true,value=Value};
+ ok ->
+ V#valuedef{checked=true,value=Value};
+ {error,Reason} ->
+ V#valuedef{checked={error,Reason},value=Value};
+ _V ->
+ V#valuedef{checked=true,value=_V}
+ end
+ end.
+
+is_contextswitchtype(#typedef{name='EXTERNAL'})->
+ true;
+is_contextswitchtype(#typedef{name='EMBEDDED PDV'}) ->
+ true;
+is_contextswitchtype(#typedef{name='CHARACTER STRING'}) ->
+ true;
+is_contextswitchtype(_) ->
+ false.
+
+% validate_integer(S,{identifier,Pos,Id},NamedNumberList,Constr) ->
+% case lists:keysearch(Id,1,NamedNumberList) of
+% {value,_} -> ok;
+% false -> error({value,"unknown NamedNumber",S})
+% end;
+%% This case occurs when there is a valuereference
+validate_integer(S=#state{mname=M},
+ #'Externalvaluereference'{module=M,value=Id},
+ NamedNumberList,_Constr) ->
+ case lists:keysearch(Id,1,NamedNumberList) of
+ {value,_} -> ok;
+ false -> error({value,"unknown NamedNumber",S})
+ end;
+validate_integer(S,Id,NamedNumberList,_Constr) when atom(Id) ->
+ case lists:keysearch(Id,1,NamedNumberList) of
+ {value,_} -> ok;
+ false -> error({value,"unknown NamedNumber",S})
+ end;
+validate_integer(_S,Value,_NamedNumberList,Constr) when integer(Value) ->
+ check_integer_range(Value,Constr).
+
+check_integer_range(Int,Constr) when list(Constr) ->
+ NewConstr = [X || #constraint{c=X} <- Constr],
+ check_constr(Int,NewConstr);
+
+check_integer_range(_Int,_Constr) ->
+ %%io:format("~p~n",[Constr]),
+ ok.
+
+check_constr(Int,[{'ValueRange',Lb,Ub}|T]) when Int >= Lb, Int =< Ub ->
+ check_constr(Int,T);
+check_constr(_Int,[]) ->
+ ok.
+
+validate_bitstring(_S,_Value,_NamedNumberList,_Constr) ->
+ ok.
+
+validate_null(_S,'NULL',_Constr) ->
+ ok.
+
+%%------------
+%% This can be removed when the old parser is removed
+%% The function removes 'space' atoms from the list
+
+is_space_list([H],Acc) ->
+ lists:reverse([H|Acc]);
+is_space_list([H,space|T],Acc) ->
+ is_space_list(T,[H|Acc]);
+is_space_list([],Acc) ->
+ lists:reverse(Acc);
+is_space_list([H|T],Acc) ->
+ is_space_list(T,[H|Acc]).
+
+validate_objectidentifier(S,L,_) ->
+ case is_space_list(L,[]) of
+ NewL when list(NewL) ->
+ case validate_objectidentifier1(S,NewL) of
+ NewL2 when list(NewL2) ->
+ list_to_tuple(NewL2);
+ Other -> Other
+ end;
+ {error,_} ->
+ error({value, "illegal OBJECT IDENTIFIER", S})
+ end.
+
+validate_objectidentifier1(S, [Id|T]) when record(Id,'Externalvaluereference') ->
+ case catch get_referenced_type(S,Id) of
+ {_,V} when record(V,valuedef) ->
+ case check_value(S,V) of
+ #valuedef{type=#type{def='OBJECT IDENTIFIER'},
+ checked=true,value=Value} when tuple(Value) ->
+ validate_objectid(S, T, lists:reverse(tuple_to_list(Value)));
+ _ ->
+ error({value, "illegal OBJECT IDENTIFIER", S})
+ end;
+ _ ->
+ validate_objectid(S, [Id|T], [])
+ end;
+validate_objectidentifier1(S,V) ->
+ validate_objectid(S,V,[]).
+
+validate_objectid(_, [], Acc) ->
+ lists:reverse(Acc);
+validate_objectid(S, [Value|Vrest], Acc) when integer(Value) ->
+ validate_objectid(S, Vrest, [Value|Acc]);
+validate_objectid(S, [{'NamedNumber',_Name,Value}|Vrest], Acc)
+ when integer(Value) ->
+ validate_objectid(S, Vrest, [Value|Acc]);
+validate_objectid(S, [Id|Vrest], Acc)
+ when record(Id,'Externalvaluereference') ->
+ case catch get_referenced_type(S, Id) of
+ {_,V} when record(V,valuedef) ->
+ case check_value(S, V) of
+ #valuedef{checked=true,value=Value} when integer(Value) ->
+ validate_objectid(S, Vrest, [Value|Acc]);
+ _ ->
+ error({value, "illegal OBJECT IDENTIFIER", S})
+ end;
+ _ ->
+ case reserved_objectid(Id#'Externalvaluereference'.value, Acc) of
+ Value when integer(Value) ->
+ validate_objectid(S, Vrest, [Value|Acc]);
+ false ->
+ error({value, "illegal OBJECT IDENTIFIER", S})
+ end
+ end;
+validate_objectid(S, [{Atom,Value}],[]) when atom(Atom),integer(Value) ->
+ %% this case when an OBJECT IDENTIFIER value has been parsed as a
+ %% SEQUENCE value
+ Rec = #'Externalvaluereference'{module=S#state.mname,
+ value=Atom},
+ validate_objectidentifier1(S,[Rec,Value]);
+validate_objectid(S, [{Atom,EVRef}],[])
+ when atom(Atom),record(EVRef,'Externalvaluereference') ->
+ %% this case when an OBJECT IDENTIFIER value has been parsed as a
+ %% SEQUENCE value OTP-4354
+ Rec = #'Externalvaluereference'{module=S#state.mname,
+ value=Atom},
+ validate_objectidentifier1(S,[Rec,EVRef]);
+validate_objectid(S, _V, _Acc) ->
+ error({value, "illegal OBJECT IDENTIFIER",S}).
+
+
+%% ITU-T Rec. X.680 Annex B - D
+reserved_objectid('itu-t',[]) -> 0;
+reserved_objectid('ccitt',[]) -> 0;
+%% arcs below "itu-t"
+reserved_objectid('recommendation',[0]) -> 0;
+reserved_objectid('question',[0]) -> 1;
+reserved_objectid('administration',[0]) -> 2;
+reserved_objectid('network-operator',[0]) -> 3;
+reserved_objectid('identified-organization',[0]) -> 4;
+%% arcs below "recommendation"
+reserved_objectid('a',[0,0]) -> 1;
+reserved_objectid('b',[0,0]) -> 2;
+reserved_objectid('c',[0,0]) -> 3;
+reserved_objectid('d',[0,0]) -> 4;
+reserved_objectid('e',[0,0]) -> 5;
+reserved_objectid('f',[0,0]) -> 6;
+reserved_objectid('g',[0,0]) -> 7;
+reserved_objectid('h',[0,0]) -> 8;
+reserved_objectid('i',[0,0]) -> 9;
+reserved_objectid('j',[0,0]) -> 10;
+reserved_objectid('k',[0,0]) -> 11;
+reserved_objectid('l',[0,0]) -> 12;
+reserved_objectid('m',[0,0]) -> 13;
+reserved_objectid('n',[0,0]) -> 14;
+reserved_objectid('o',[0,0]) -> 15;
+reserved_objectid('p',[0,0]) -> 16;
+reserved_objectid('q',[0,0]) -> 17;
+reserved_objectid('r',[0,0]) -> 18;
+reserved_objectid('s',[0,0]) -> 19;
+reserved_objectid('t',[0,0]) -> 20;
+reserved_objectid('u',[0,0]) -> 21;
+reserved_objectid('v',[0,0]) -> 22;
+reserved_objectid('w',[0,0]) -> 23;
+reserved_objectid('x',[0,0]) -> 24;
+reserved_objectid('y',[0,0]) -> 25;
+reserved_objectid('z',[0,0]) -> 26;
+
+
+reserved_objectid(iso,[]) -> 1;
+%% arcs below "iso", note that number 1 is not used
+reserved_objectid('standard',[1]) -> 0;
+reserved_objectid('member-body',[1]) -> 2;
+reserved_objectid('identified-organization',[1]) -> 3;
+
+reserved_objectid('joint-iso-itu-t',[]) -> 2;
+reserved_objectid('joint-iso-ccitt',[]) -> 2;
+
+reserved_objectid(_,_) -> false.
+
+
+
+
+
+validate_objectdescriptor(_S,_Value,_Constr) ->
+ ok.
+
+validate_enumerated(S,Id,NamedNumberList,_Constr) when atom(Id) ->
+ case lists:keysearch(Id,1,NamedNumberList) of
+ {value,_} -> ok;
+ false -> error({value,"unknown ENUMERATED",S})
+ end;
+validate_enumerated(S,{identifier,_Pos,Id},NamedNumberList,_Constr) ->
+ case lists:keysearch(Id,1,NamedNumberList) of
+ {value,_} -> ok;
+ false -> error({value,"unknown ENUMERATED",S})
+ end;
+validate_enumerated(S,#'Externalvaluereference'{value=Id},
+ NamedNumberList,_Constr) ->
+ case lists:keysearch(Id,1,NamedNumberList) of
+ {value,_} -> ok;
+ false -> error({value,"unknown ENUMERATED",S})
+ end.
+
+validate_boolean(_S,_Value,_Constr) ->
+ ok.
+
+validate_octetstring(_S,_Value,_Constr) ->
+ ok.
+
+validate_restrictedstring(_S,_Value,_Def,_Constr) ->
+ ok.
+
+validate_sequence(S=#state{type=Vtype},Value,_Components,_Constr) ->
+ case Vtype of
+ #type{tag=[{tag,'UNIVERSAL',8,'IMPLICIT',32}]} ->
+ %% this is an 'EXTERNAL' (or INSTANCE OF)
+ case Value of
+ [{identification,_}|_RestVal] ->
+ to_EXTERNAL1990(S,Value);
+ _ ->
+ Value
+ end;
+ _ ->
+ Value
+ end.
+
+validate_sequenceof(_S,_Value,_Components,_Constr) ->
+ ok.
+
+validate_choice(_S,_Value,_Components,_Constr) ->
+ ok.
+
+validate_set(_S,_Value,_Components,_Constr) ->
+ ok.
+
+validate_setof(_S,_Value,_Components,_Constr) ->
+ ok.
+
+to_EXTERNAL1990(S,[{identification,{'CHOICE',{syntax,Stx}}}|Rest]) ->
+ to_EXTERNAL1990(S,Rest,[{'direct-reference',Stx}]);
+to_EXTERNAL1990(S,[{identification,{'CHOICE',{'presentation-context-id',I}}}|Rest]) ->
+ to_EXTERNAL1990(S,Rest,[{'indirect-reference',I}]);
+to_EXTERNAL1990(S,[{identification,{'CHOICE',{'context-negotiation',[{_,PCid},{_,TrStx}]}}}|Rest]) ->
+ to_EXTERNAL1990(S,Rest,[{'indirect-reference',PCid},{'direct-reference',TrStx}]);
+to_EXTERNAL1990(S,_) ->
+ error({value,"illegal value in EXTERNAL type",S}).
+
+to_EXTERNAL1990(S,[V={'data-value-descriptor',_}|Rest],Acc) ->
+ to_EXTERNAL1990(S,Rest,[V|Acc]);
+to_EXTERNAL1990(_S,[{'data-value',Val}],Acc) ->
+ Encoding = {encoding,{'CHOICE',{'octet-aligned',Val}}},
+ lists:reverse([Encoding|Acc]);
+to_EXTERNAL1990(S,_,_) ->
+ error({value,"illegal value in EXTERNAL type",S}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Functions to normalize the default values of SEQUENCE
+%% and SET components into Erlang valid format
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+normalize_value(_,_,mandatory,_) ->
+ mandatory;
+normalize_value(_,_,'OPTIONAL',_) ->
+ 'OPTIONAL';
+normalize_value(S,Type,{'DEFAULT',Value},NameList) ->
+ case catch get_canonic_type(S,Type,NameList) of
+ {'BOOLEAN',CType,_} ->
+ normalize_boolean(S,Value,CType);
+ {'INTEGER',CType,_} ->
+ normalize_integer(S,Value,CType);
+ {'BIT STRING',CType,_} ->
+ normalize_bitstring(S,Value,CType);
+ {'OCTET STRING',CType,_} ->
+ normalize_octetstring(S,Value,CType);
+ {'NULL',_CType,_} ->
+ %%normalize_null(Value);
+ 'NULL';
+ {'OBJECT IDENTIFIER',_,_} ->
+ normalize_objectidentifier(S,Value);
+ {'ObjectDescriptor',_,_} ->
+ normalize_objectdescriptor(Value);
+ {'REAL',_,_} ->
+ normalize_real(Value);
+ {'ENUMERATED',CType,_} ->
+ normalize_enumerated(Value,CType);
+ {'CHOICE',CType,NewNameList} ->
+ normalize_choice(S,Value,CType,NewNameList);
+ {'SEQUENCE',CType,NewNameList} ->
+ normalize_sequence(S,Value,CType,NewNameList);
+ {'SEQUENCE OF',CType,NewNameList} ->
+ normalize_seqof(S,Value,CType,NewNameList);
+ {'SET',CType,NewNameList} ->
+ normalize_set(S,Value,CType,NewNameList);
+ {'SET OF',CType,NewNameList} ->
+ normalize_setof(S,Value,CType,NewNameList);
+ {restrictedstring,CType,_} ->
+ normalize_restrictedstring(S,Value,CType);
+ _ ->
+ io:format("WARNING: could not check default value ~p~n",[Value]),
+ Value
+ end;
+normalize_value(S,Type,Val,NameList) ->
+ normalize_value(S,Type,{'DEFAULT',Val},NameList).
+
+normalize_boolean(S,{Name,Bool},CType) when atom(Name) ->
+ normalize_boolean(S,Bool,CType);
+normalize_boolean(_,true,_) ->
+ true;
+normalize_boolean(_,false,_) ->
+ false;
+normalize_boolean(S,Bool=#'Externalvaluereference'{},CType) ->
+ get_normalized_value(S,Bool,CType,fun normalize_boolean/3,[]);
+normalize_boolean(_,Other,_) ->
+ throw({error,{asn1,{'invalid default value',Other}}}).
+
+normalize_integer(_S,Int,_) when integer(Int) ->
+ Int;
+normalize_integer(_S,{Name,Int},_) when atom(Name),integer(Int) ->
+ Int;
+normalize_integer(S,{Name,Int=#'Externalvaluereference'{}},
+ Type) when atom(Name) ->
+ normalize_integer(S,Int,Type);
+normalize_integer(S,Int=#'Externalvaluereference'{value=Name},Type) ->
+ case Type of
+ NNL when list(NNL) ->
+ case lists:keysearch(Name,1,NNL) of
+ {value,{Name,Val}} ->
+ Val;
+ false ->
+ get_normalized_value(S,Int,Type,
+ fun normalize_integer/3,[])
+ end;
+ _ ->
+ get_normalized_value(S,Int,Type,fun normalize_integer/3,[])
+ end;
+normalize_integer(_,Int,_) ->
+ exit({'Unknown INTEGER value',Int}).
+
+normalize_bitstring(S,Value,Type)->
+ %% There are four different Erlang formats of BIT STRING:
+ %% 1 - a list of ones and zeros.
+ %% 2 - a list of atoms.
+ %% 3 - as an integer, for instance in hexadecimal form.
+ %% 4 - as a tuple {Unused, Binary} where Unused is an integer
+ %% and tells how many bits of Binary are unused.
+ %%
+ %% normalize_bitstring/3 transforms Value according to:
+ %% A to 3,
+ %% B to 1,
+ %% C to 1 or 3
+ %% D to 2,
+ %% Value can be on format:
+ %% A - {hstring, String}, where String is a hexadecimal string.
+ %% B - {bstring, String}, where String is a string on bit format
+ %% C - #'Externalvaluereference'{value=V}, where V is a defined value
+ %% D - list of #'Externalvaluereference', where each value component
+ %% is an identifier corresponing to NamedBits in Type.
+ case Value of
+ {hstring,String} when list(String) ->
+ hstring_to_int(String);
+ {bstring,String} when list(String) ->
+ bstring_to_bitlist(String);
+ Rec when record(Rec,'Externalvaluereference') ->
+ get_normalized_value(S,Value,Type,
+ fun normalize_bitstring/3,[]);
+ RecList when list(RecList) ->
+ case Type of
+ NBL when list(NBL) ->
+ F = fun(#'Externalvaluereference'{value=Name}) ->
+ case lists:keysearch(Name,1,NBL) of
+ {value,{Name,_}} ->
+ Name;
+ Other ->
+ throw({error,Other})
+ end;
+ (Other) ->
+ throw({error,Other})
+ end,
+ case catch lists:map(F,RecList) of
+ {error,Reason} ->
+ io:format("WARNING: default value not "
+ "compatible with type definition ~p~n",
+ [Reason]),
+ Value;
+ NewList ->
+ NewList
+ end;
+ _ ->
+ io:format("WARNING: default value not "
+ "compatible with type definition ~p~n",
+ [RecList]),
+ Value
+ end;
+ {Name,String} when atom(Name) ->
+ normalize_bitstring(S,String,Type);
+ Other ->
+ io:format("WARNING: illegal default value ~p~n",[Other]),
+ Value
+ end.
+
+hstring_to_int(L) when list(L) ->
+ hstring_to_int(L,0).
+hstring_to_int([H|T],Acc) when H >= $A, H =< $F ->
+ hstring_to_int(T,(Acc bsl 4) + (H - $A + 10) ) ;
+hstring_to_int([H|T],Acc) when H >= $0, H =< $9 ->
+ hstring_to_int(T,(Acc bsl 4) + (H - $0));
+hstring_to_int([],Acc) ->
+ Acc.
+
+bstring_to_bitlist([H|T]) when H == $0; H == $1 ->
+ [H - $0 | bstring_to_bitlist(T)];
+bstring_to_bitlist([]) ->
+ [].
+
+%% normalize_octetstring/1 changes representation of input Value to a
+%% list of octets.
+%% Format of Value is one of:
+%% {bstring,String} each element in String corresponds to one bit in an octet
+%% {hstring,String} each element in String corresponds to one byte in an octet
+%% #'Externalvaluereference'
+normalize_octetstring(S,Value,CType) ->
+ case Value of
+ {bstring,String} ->
+ bstring_to_octetlist(String);
+ {hstring,String} ->
+ hstring_to_octetlist(String);
+ Rec when record(Rec,'Externalvaluereference') ->
+ get_normalized_value(S,Value,CType,
+ fun normalize_octetstring/3,[]);
+ {Name,String} when atom(Name) ->
+ normalize_octetstring(S,String,CType);
+ List when list(List) ->
+ %% check if list elements are valid octet values
+ lists:map(fun([])-> ok;
+ (H)when H > 255->
+ io:format("WARNING: not legal octet value ~p in OCTET STRING, ~p~n",[H,List]);
+ (_)-> ok
+ end, List),
+ List;
+ Other ->
+ io:format("WARNING: unknown default value ~p~n",[Other]),
+ Value
+ end.
+
+
+bstring_to_octetlist([]) ->
+ [];
+bstring_to_octetlist([H|T]) when H == $0 ; H == $1 ->
+ bstring_to_octetlist(T,6,[(H - $0) bsl 7]).
+bstring_to_octetlist([H|T],0,[Hacc|Tacc]) when H == $0; H == $1 ->
+ bstring_to_octetlist(T, 7, [0,Hacc + (H -$0)| Tacc]);
+bstring_to_octetlist([H|T],BSL,[Hacc|Tacc]) when H == $0; H == $1 ->
+ bstring_to_octetlist(T, BSL-1, [Hacc + ((H - $0) bsl BSL)| Tacc]);
+bstring_to_octetlist([],7,[0|Acc]) ->
+ lists:reverse(Acc);
+bstring_to_octetlist([],_,Acc) ->
+ lists:reverse(Acc).
+
+hstring_to_octetlist([]) ->
+ [];
+hstring_to_octetlist(L) ->
+ hstring_to_octetlist(L,4,[]).
+hstring_to_octetlist([H|T],0,[Hacc|Tacc]) when H >= $A, H =< $F ->
+ hstring_to_octetlist(T,4,[Hacc + (H - $A + 10)|Tacc]);
+hstring_to_octetlist([H|T],BSL,Acc) when H >= $A, H =< $F ->
+ hstring_to_octetlist(T,0,[(H - $A + 10) bsl BSL|Acc]);
+hstring_to_octetlist([H|T],0,[Hacc|Tacc]) when H >= $0; H =< $9 ->
+ hstring_to_octetlist(T,4,[Hacc + (H - $0)|Tacc]);
+hstring_to_octetlist([H|T],BSL,Acc) when H >= $0; H =< $9 ->
+ hstring_to_octetlist(T,0,[(H - $0) bsl BSL|Acc]);
+hstring_to_octetlist([],_,Acc) ->
+ lists:reverse(Acc).
+
+normalize_objectidentifier(S,Value) ->
+ validate_objectidentifier(S,Value,[]).
+
+normalize_objectdescriptor(Value) ->
+ Value.
+
+normalize_real(Value) ->
+ Value.
+
+normalize_enumerated(#'Externalvaluereference'{value=V},CType)
+ when list(CType) ->
+ normalize_enumerated2(V,CType);
+normalize_enumerated(Value,CType) when atom(Value),list(CType) ->
+ normalize_enumerated2(Value,CType);
+normalize_enumerated({Name,EnumV},CType) when atom(Name) ->
+ normalize_enumerated(EnumV,CType);
+normalize_enumerated(Value,{CType1,CType2}) when list(CType1), list(CType2)->
+ normalize_enumerated(Value,CType1++CType2);
+normalize_enumerated(V,CType) ->
+ io:format("WARNING: Enumerated unknown type ~p~n",[CType]),
+ V.
+normalize_enumerated2(V,Enum) ->
+ case lists:keysearch(V,1,Enum) of
+ {value,{Val,_}} -> Val;
+ _ ->
+ io:format("WARNING: Enumerated value is not correct ~p~n",[V]),
+ V
+ end.
+
+normalize_choice(S,{'CHOICE',{C,V}},CType,NameList) when atom(C) ->
+ Value =
+ case V of
+ Rec when record(Rec,'Externalvaluereference') ->
+ get_normalized_value(S,V,CType,
+ fun normalize_choice/4,
+ [NameList]);
+ _ -> V
+ end,
+ case catch lists:keysearch(C,#'ComponentType'.name,CType) of
+ {value,#'ComponentType'{typespec=CT,name=Name}} ->
+ {C,normalize_value(S,CT,{'DEFAULT',Value},
+ [Name|NameList])};
+ Other ->
+ io:format("WARNING: Wrong format of type/value ~p/~p~n",
+ [Other,Value]),
+ {C,Value}
+ end;
+normalize_choice(S,{'DEFAULT',ValueList},CType,NameList) ->
+ lists:map(fun(X)-> normalize_choice(S,X,CType,NameList) end, ValueList);
+normalize_choice(S,Val=#'Externalvaluereference'{},CType,NameList) ->
+ {_,#valuedef{value=V}}=get_referenced_type(S,Val),
+ normalize_choice(S,{'CHOICE',V},CType,NameList);
+% get_normalized_value(S,Val,CType,fun normalize_choice/4,[NameList]);
+normalize_choice(S,{Name,ChoiceVal},CType,NameList)
+ when atom(Name) ->
+ normalize_choice(S,ChoiceVal,CType,NameList).
+
+normalize_sequence(S,{Name,Value},Components,NameList)
+ when atom(Name),list(Value) ->
+ normalize_sequence(S,Value,Components,NameList);
+normalize_sequence(S,Value,Components,NameList) ->
+ normalized_record('SEQUENCE',S,Value,Components,NameList).
+
+normalize_set(S,{Name,Value},Components,NameList)
+ when atom(Name),list(Value) ->
+ normalized_record('SET',S,Value,Components,NameList);
+normalize_set(S,Value,Components,NameList) ->
+ normalized_record('SET',S,Value,Components,NameList).
+
+normalized_record(SorS,S,Value,Components,NameList) ->
+ NewName = list_to_atom(asn1ct_gen:list2name(NameList)),
+ NoComps = length(Components),
+ case normalize_seq_or_set(SorS,S,Value,Components,NameList,[]) of
+ ListOfVals when length(ListOfVals) == NoComps ->
+ list_to_tuple([NewName|ListOfVals]);
+ _ ->
+ error({type,{illegal,default,value,Value},S})
+ end.
+
+normalize_seq_or_set(SorS,S,[{Cname,V}|Vs],
+ [#'ComponentType'{name=Cname,typespec=TS}|Cs],
+ NameList,Acc) ->
+ NewNameList =
+ case TS#type.def of
+ #'Externaltypereference'{type=TName} ->
+ [TName];
+ _ -> [Cname|NameList]
+ end,
+ NVal = normalize_value(S,TS,{'DEFAULT',V},NewNameList),
+ normalize_seq_or_set(SorS,S,Vs,Cs,NameList,[NVal|Acc]);
+normalize_seq_or_set(SorS,S,Values=[{_Cname1,_V}|_Vs],
+ [#'ComponentType'{prop='OPTIONAL'}|Cs],
+ NameList,Acc) ->
+ normalize_seq_or_set(SorS,S,Values,Cs,NameList,[asn1_NOVALUE|Acc]);
+normalize_seq_or_set(SorS,S,Values=[{_Cname1,_V}|_Vs],
+ [#'ComponentType'{name=Cname2,typespec=TS,
+ prop={'DEFAULT',Value}}|Cs],
+ NameList,Acc) ->
+ NewNameList =
+ case TS#type.def of
+ #'Externaltypereference'{type=TName} ->
+ [TName];
+ _ -> [Cname2|NameList]
+ end,
+ NVal = normalize_value(S,TS,{'DEFAULT',Value},NewNameList),
+ normalize_seq_or_set(SorS,S,Values,Cs,NameList,[NVal|Acc]);
+normalize_seq_or_set(_SorS,_S,[],[],_,Acc) ->
+ lists:reverse(Acc);
+%% If default value is {} ComponentTypes in SEQUENCE are marked DEFAULT
+%% or OPTIONAL (or the type is defined SEQUENCE{}, which is handled by
+%% the previous case).
+normalize_seq_or_set(SorS,S,[],
+ [#'ComponentType'{name=Name,typespec=TS,
+ prop={'DEFAULT',Value}}|Cs],
+ NameList,Acc) ->
+ NewNameList =
+ case TS#type.def of
+ #'Externaltypereference'{type=TName} ->
+ [TName];
+ _ -> [Name|NameList]
+ end,
+ NVal = normalize_value(S,TS,{'DEFAULT',Value},NewNameList),
+ normalize_seq_or_set(SorS,S,[],Cs,NameList,[NVal|Acc]);
+normalize_seq_or_set(SorS,S,[],[#'ComponentType'{prop='OPTIONAL'}|Cs],
+ NameList,Acc) ->
+ normalize_seq_or_set(SorS,S,[],Cs,NameList,[asn1_NOVALUE|Acc]);
+normalize_seq_or_set(SorS,S,Value=#'Externalvaluereference'{},
+ Cs,NameList,Acc) ->
+ get_normalized_value(S,Value,Cs,fun normalize_seq_or_set/6,
+ [SorS,NameList,Acc]);
+normalize_seq_or_set(_SorS,S,V,_,_,_) ->
+ error({type,{illegal,default,value,V},S}).
+
+normalize_seqof(S,Value,Type,NameList) ->
+ normalize_s_of('SEQUENCE OF',S,Value,Type,NameList).
+
+normalize_setof(S,Value,Type,NameList) ->
+ normalize_s_of('SET OF',S,Value,Type,NameList).
+
+normalize_s_of(SorS,S,Value,Type,NameList) when list(Value) ->
+ DefValueList = lists:map(fun(X) -> {'DEFAULT',X} end,Value),
+ Suffix = asn1ct_gen:constructed_suffix(SorS,Type),
+ Def = Type#type.def,
+ InnerType = asn1ct_gen:get_inner(Def),
+ WhatKind = asn1ct_gen:type(InnerType),
+ NewNameList =
+ case WhatKind of
+ {constructed,bif} ->
+ [Suffix|NameList];
+ #'Externaltypereference'{type=Name} ->
+ [Name];
+ _ -> []
+ end,
+ NormFun = fun (X) -> normalize_value(S,Type,X,
+ NewNameList) end,
+ case catch lists:map(NormFun, DefValueList) of
+ List when list(List) ->
+ List;
+ _ ->
+ io:format("WARNING: ~p could not handle value ~p~n",
+ [SorS,Value]),
+ Value
+ end;
+normalize_s_of(SorS,S,Value,Type,NameList)
+ when record(Value,'Externalvaluereference') ->
+ get_normalized_value(S,Value,Type,fun normalize_s_of/5,
+ [SorS,NameList]).
+% case catch get_referenced_type(S,Value) of
+% {_,#valuedef{value=V}} ->
+% normalize_s_of(SorS,S,V,Type);
+% {error,Reason} ->
+% io:format("WARNING: ~p could not handle value ~p~n",
+% [SorS,Value]),
+% Value;
+% {_,NewVal} ->
+% normalize_s_of(SorS,S,NewVal,Type);
+% _ ->
+% io:format("WARNING: ~p could not handle value ~p~n",
+% [SorS,Value]),
+% Value
+% end.
+
+
+%% normalize_restrictedstring handles all format of restricted strings.
+%% tuple case
+normalize_restrictedstring(_S,[Int1,Int2],_) when integer(Int1),integer(Int2) ->
+ {Int1,Int2};
+%% quadruple case
+normalize_restrictedstring(_S,[Int1,Int2,Int3,Int4],_) when integer(Int1),
+ integer(Int2),
+ integer(Int3),
+ integer(Int4) ->
+ {Int1,Int2,Int3,Int4};
+%% character string list case
+normalize_restrictedstring(S,[H|T],CType) when list(H);tuple(H) ->
+ [normalize_restrictedstring(S,H,CType)|normalize_restrictedstring(S,T,CType)];
+%% character sting case
+normalize_restrictedstring(_S,CString,_) when list(CString) ->
+ Fun =
+ fun(X) ->
+ if
+ $X =< 255, $X >= 0 ->
+ ok;
+ true ->
+ io:format("WARNING: illegal character in string"
+ " ~p~n",[X])
+ end
+ end,
+ lists:foreach(Fun,CString),
+ CString;
+%% definedvalue case or argument in a parameterized type
+normalize_restrictedstring(S,ERef,CType) when record(ERef,'Externalvaluereference') ->
+ get_normalized_value(S,ERef,CType,
+ fun normalize_restrictedstring/3,[]);
+%%
+normalize_restrictedstring(S,{Name,Val},CType) when atom(Name) ->
+ normalize_restrictedstring(S,Val,CType).
+
+
+get_normalized_value(S,Val,Type,Func,AddArg) ->
+ case catch get_referenced_type(S,Val) of
+ {_,#valuedef{type=_T,value=V}} ->
+ %% should check that Type and T equals
+ call_Func(S,V,Type,Func,AddArg);
+ {error,_} ->
+ io:format("WARNING: default value not "
+ "comparable ~p~n",[Val]),
+ Val;
+ {_,NewVal} ->
+ call_Func(S,NewVal,Type,Func,AddArg);
+ _ ->
+ io:format("WARNING: default value not "
+ "comparable ~p~n",[Val]),
+ Val
+ end.
+
+call_Func(S,Val,Type,Func,ArgList) ->
+ case ArgList of
+ [] ->
+ Func(S,Val,Type);
+ [LastArg] ->
+ Func(S,Val,Type,LastArg);
+ [Arg1,LastArg1] ->
+ Func(Arg1,S,Val,Type,LastArg1);
+ [Arg1,LastArg1,LastArg2] ->
+ Func(Arg1,S,Val,Type,LastArg1,LastArg2)
+ end.
+
+
+get_canonic_type(S,Type,NameList) ->
+ {InnerType,NewType,NewNameList} =
+ case Type#type.def of
+ Name when atom(Name) ->
+ {Name,Type,NameList};
+ Ref when record(Ref,'Externaltypereference') ->
+ {_,#typedef{name=Name,typespec=RefedType}} =
+ get_referenced_type(S,Ref),
+ get_canonic_type(S,RefedType,[Name]);
+ {Name,T} when atom(Name) ->
+ {Name,T,NameList};
+ Seq when record(Seq,'SEQUENCE') ->
+ {'SEQUENCE',Seq#'SEQUENCE'.components,NameList};
+ Set when record(Set,'SET') ->
+ {'SET',Set#'SET'.components,NameList}
+ end,
+ {asn1ct_gen:unify_if_string(InnerType),NewType,NewNameList}.
+
+
+
+check_ptype(_S,Type,Ts) when record(Ts,type) ->
+ %Tag = Ts#type.tag,
+ %Constr = Ts#type.constraint,
+ Def = Ts#type.def,
+ NewDef=
+ case Def of
+ Seq when record(Seq,'SEQUENCE') ->
+ #newt{type=Seq#'SEQUENCE'{pname=Type#ptypedef.name}};
+ Set when record(Set,'SET') ->
+ #newt{type=Set#'SET'{pname=Type#ptypedef.name}};
+ _Other ->
+ #newt{}
+ end,
+ Ts2 = case NewDef of
+ #newt{type=unchanged} ->
+ Ts;
+ #newt{type=TDef}->
+ Ts#type{def=TDef}
+ end,
+ Ts2.
+
+
+% check_type(S,Type,ObjSpec={{objectclassname,_},_}) ->
+% check_class(S,ObjSpec);
+check_type(_S,Type,Ts) when record(Type,typedef),
+ (Type#typedef.checked==true) ->
+ Ts;
+check_type(_S,Type,Ts) when record(Type,typedef),
+ (Type#typedef.checked==idle) -> % the check is going on
+ Ts;
+check_type(S=#state{recordtopname=TopName},Type,Ts) when record(Ts,type) ->
+ {Def,Tag,Constr} =
+ case match_parameters(Ts#type.def,S#state.parameters) of
+ #type{constraint=_Ctmp,def=Dtmp} ->
+ {Dtmp,Ts#type.tag,Ts#type.constraint};
+ Dtmp ->
+ {Dtmp,Ts#type.tag,Ts#type.constraint}
+ end,
+ TempNewDef = #newt{type=Def,tag=Tag,constraint=Constr},
+ TestFun =
+ fun(Tref) ->
+ {_,MaybeChoice} = get_referenced_type(S,Tref),
+ case catch((MaybeChoice#typedef.typespec)#type.def) of
+ {'CHOICE',_} ->
+ maybe_illicit_implicit_tag(choice,Tag);
+ 'ANY' ->
+ maybe_illicit_implicit_tag(open_type,Tag);
+ 'ANY DEFINED BY' ->
+ maybe_illicit_implicit_tag(open_type,Tag);
+ 'ASN1_OPEN_TYPE' ->
+ maybe_illicit_implicit_tag(open_type,Tag);
+ _ ->
+ Tag
+ end
+ end,
+ NewDef=
+ case Def of
+ Ext when record(Ext,'Externaltypereference') ->
+ {_,RefTypeDef} = get_referenced_type(S,Ext),
+% case RefTypeDef of
+% Class when record(Class,classdef) ->
+% throw({asn1_class,Class});
+% _ -> ok
+% end,
+ case is_class(S,RefTypeDef) of
+ true -> throw({asn1_class,RefTypeDef});
+ _ -> ok
+ end,
+ Ct = TestFun(Ext),
+ RefType =
+%case S#state.erule of
+% ber_bin_v2 ->
+ case RefTypeDef#typedef.checked of
+ true ->
+ RefTypeDef#typedef.typespec;
+ _ ->
+ NewRefTypeDef1 = RefTypeDef#typedef{checked=idle},
+ asn1_db:dbput(S#state.mname,
+ NewRefTypeDef1#typedef.name,NewRefTypeDef1),
+ RefType1 =
+ check_type(S,RefTypeDef,RefTypeDef#typedef.typespec),
+ NewRefTypeDef2 =
+ RefTypeDef#typedef{checked=true,typespec = RefType1},
+ asn1_db:dbput(S#state.mname,
+ NewRefTypeDef2#typedef.name,NewRefTypeDef2),
+ %% update the type and mark as checked
+ RefType1
+ end,
+% _ -> RefTypeDef#typedef.typespec
+% end,
+
+ case asn1ct_gen:prim_bif(asn1ct_gen:get_inner(RefType#type.def)) of
+ true ->
+ %% Here we expand to a built in type and inline it
+ TempNewDef#newt{
+ type=
+ RefType#type.def,
+ tag=
+ merge_tags(Ct,RefType#type.tag),
+ constraint=
+ merge_constraints(check_constraints(S,Constr),
+ RefType#type.constraint)};
+ _ ->
+ %% Here we only expand the tags and keep the ext ref
+
+ TempNewDef#newt{
+ type=
+ check_externaltypereference(S,Ext),
+ tag =
+ case S#state.erule of
+ ber_bin_v2 ->
+ merge_tags(Ct,RefType#type.tag);
+ _ ->
+ Ct
+ end
+ }
+ end;
+ 'ANY' ->
+ Ct=maybe_illicit_implicit_tag(open_type,Tag),
+ TempNewDef#newt{type='ASN1_OPEN_TYPE',tag=Ct};
+ {'ANY_DEFINED_BY',_} ->
+ Ct=maybe_illicit_implicit_tag(open_type,Tag),
+ TempNewDef#newt{type='ASN1_OPEN_TYPE',tag=Ct};
+ 'INTEGER' ->
+ check_integer(S,[],Constr),
+ TempNewDef#newt{tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_INTEGER))};
+
+ {'INTEGER',NamedNumberList} ->
+ TempNewDef#newt{type={'INTEGER',check_integer(S,NamedNumberList,Constr)},
+ tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_INTEGER))};
+ {'BIT STRING',NamedNumberList} ->
+ NewL = check_bitstring(S,NamedNumberList,Constr),
+%% erlang:display({asn1ct_check,NamedNumberList,NewL}),
+ TempNewDef#newt{type={'BIT STRING',NewL},
+ tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_BIT_STRING))};
+ 'NULL' ->
+ TempNewDef#newt{tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_NULL))};
+ 'OBJECT IDENTIFIER' ->
+ check_objectidentifier(S,Constr),
+ TempNewDef#newt{tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_OBJECT_IDENTIFIER))};
+ 'ObjectDescriptor' ->
+ TempNewDef#newt{tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_OBJECT_DESCRIPTOR))};
+ 'EXTERNAL' ->
+%% AssociatedType = asn1_db:dbget(S#state.mname,'EXTERNAL'),
+%% #newt{type=check_type(S,Type,AssociatedType)};
+ put(external,unchecked),
+ TempNewDef#newt{type=
+ #'Externaltypereference'{module=S#state.mname,
+ type='EXTERNAL'},
+ tag=
+ merge_tags(Tag,?TAG_CONSTRUCTED(?N_EXTERNAL))};
+ {'INSTANCE OF',DefinedObjectClass,Constraint} ->
+ %% check that DefinedObjectClass is of TYPE-IDENTIFIER class
+ %% If Constraint is empty make it the general INSTANCE OF type
+ %% If Constraint is not empty make an inlined type
+ %% convert INSTANCE OF to the associated type
+ IOFDef=check_instance_of(S,DefinedObjectClass,Constraint),
+ TempNewDef#newt{type=IOFDef,
+ tag=merge_tags(Tag,?TAG_CONSTRUCTED(?N_INSTANCE_OF))};
+ {'ENUMERATED',NamedNumberList} ->
+ TempNewDef#newt{type=
+ {'ENUMERATED',
+ check_enumerated(S,NamedNumberList,Constr)},
+ tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_ENUMERATED))};
+ 'EMBEDDED PDV' ->
+% AssociatedType = asn1_db:dbget(S#state.mname,'EMBEDDED PDV'),
+% CheckedType = check_type(S,Type,
+% AssociatedType#typedef.typespec),
+ put(embedded_pdv,unchecked),
+ TempNewDef#newt{type=
+ #'Externaltypereference'{module=S#state.mname,
+ type='EMBEDDED PDV'},
+ tag=
+ merge_tags(Tag,?TAG_CONSTRUCTED(?N_EMBEDDED_PDV))};
+ 'BOOLEAN'->
+ check_boolean(S,Constr),
+ TempNewDef#newt{tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_BOOLEAN))};
+ 'OCTET STRING' ->
+ check_octetstring(S,Constr),
+ TempNewDef#newt{tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_OCTET_STRING))};
+ 'NumericString' ->
+ check_restrictedstring(S,Def,Constr),
+ TempNewDef#newt{tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_NumericString))};
+ 'TeletexString' ->
+ check_restrictedstring(S,Def,Constr),
+ TempNewDef#newt{tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_TeletexString))};
+ 'VideotexString' ->
+ check_restrictedstring(S,Def,Constr),
+ TempNewDef#newt{tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_VideotexString))};
+ 'UTCTime' ->
+ TempNewDef#newt{tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_UTCTime))};
+ 'GeneralizedTime' ->
+ TempNewDef#newt{tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_GeneralizedTime))};
+ 'GraphicString' ->
+ check_restrictedstring(S,Def,Constr),
+ TempNewDef#newt{tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_GraphicString))};
+ 'VisibleString' ->
+ check_restrictedstring(S,Def,Constr),
+ TempNewDef#newt{tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_VisibleString))};
+ 'GeneralString' ->
+ check_restrictedstring(S,Def,Constr),
+ TempNewDef#newt{tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_GeneralString))};
+ 'PrintableString' ->
+ check_restrictedstring(S,Def,Constr),
+ TempNewDef#newt{tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_PrintableString))};
+ 'IA5String' ->
+ check_restrictedstring(S,Def,Constr),
+ TempNewDef#newt{tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_IA5String))};
+ 'BMPString' ->
+ check_restrictedstring(S,Def,Constr),
+ TempNewDef#newt{tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_BMPString))};
+ 'UniversalString' ->
+ check_restrictedstring(S,Def,Constr),
+ TempNewDef#newt{tag=
+ merge_tags(Tag,?TAG_PRIMITIVE(?N_UniversalString))};
+ 'CHARACTER STRING' ->
+% AssociatedType = asn1_db:dbget(S#state.mname,
+% 'CHARACTER STRING'),
+% CheckedType = check_type(S,Type,
+% AssociatedType#typedef.typespec),
+ put(character_string,unchecked),
+ TempNewDef#newt{type=
+ #'Externaltypereference'{module=S#state.mname,
+ type='CHARACTER STRING'},
+ tag=
+ merge_tags(Tag,?TAG_CONSTRUCTED(?N_CHARACTER_STRING))};
+ Seq when record(Seq,'SEQUENCE') ->
+ RecordName =
+ case TopName of
+ [] ->
+ [Type#typedef.name];
+ _ ->
+ TopName
+ end,
+ {TableCInf,Components} =
+ check_sequence(S#state{recordtopname=
+ RecordName},
+ Type,Seq#'SEQUENCE'.components),
+ TempNewDef#newt{type=Seq#'SEQUENCE'{tablecinf=TableCInf,
+ components=Components},
+ tag=
+ merge_tags(Tag,?TAG_CONSTRUCTED(?N_SEQUENCE))};
+ {'SEQUENCE OF',Components} ->
+ TempNewDef#newt{type={'SEQUENCE OF',check_sequenceof(S,Type,Components)},
+ tag=
+ merge_tags(Tag,?TAG_CONSTRUCTED(?N_SEQUENCE))};
+ {'CHOICE',Components} ->
+ Ct = maybe_illicit_implicit_tag(choice,Tag),
+ TempNewDef#newt{type={'CHOICE',check_choice(S,Type,Components)},tag=Ct};
+ Set when record(Set,'SET') ->
+ RecordName=
+ case TopName of
+ [] ->
+ [Type#typedef.name];
+ _ ->
+ TopName
+ end,
+ {Sorted,TableCInf,Components} =
+ check_set(S#state{recordtopname=RecordName},
+ Type,Set#'SET'.components),
+ TempNewDef#newt{type=Set#'SET'{sorted=Sorted,
+ tablecinf=TableCInf,
+ components=Components},
+ tag=
+ merge_tags(Tag,?TAG_CONSTRUCTED(?N_SET))};
+ {'SET OF',Components} ->
+ TempNewDef#newt{type={'SET OF',check_setof(S,Type,Components)},
+ tag=
+ merge_tags(Tag,?TAG_CONSTRUCTED(?N_SET))};
+ %% This is a temporary hack until the full Information Obj Spec
+ %% in X.681 is supported
+ {{typereference,_,'TYPE-IDENTIFIER'},[{typefieldreference,_,'Type'}]} ->
+ Ct=maybe_illicit_implicit_tag(open_type,Tag),
+ TempNewDef#newt{type='ASN1_OPEN_TYPE',tag=Ct};
+
+ {#'Externaltypereference'{type='TYPE-IDENTIFIER'},
+ [{typefieldreference,_,'Type'}]} ->
+ Ct=maybe_illicit_implicit_tag(open_type,Tag),
+ TempNewDef#newt{type='ASN1_OPEN_TYPE',tag=Ct};
+
+ {pt,Ptype,ParaList} ->
+ %% Ptype might be a parameterized - type, object set or
+ %% value set. If it isn't a parameterized type notify the
+ %% calling function.
+ {_,Ptypedef} = get_referenced_type(S,Ptype),
+ notify_if_not_ptype(S,Ptypedef),
+ NewParaList = [match_parameters(TmpParam,S#state.parameters)||
+ TmpParam <- ParaList],
+ Instance = instantiate_ptype(S,Ptypedef,NewParaList),
+ TempNewDef#newt{type=Instance#type.def,
+ tag=merge_tags(Tag,Instance#type.tag),
+ constraint=Instance#type.constraint,
+ inlined=yes};
+
+% {ClRef,FieldRefList} when record(ClRef,'Externaltypereference') ->
+ OCFT=#'ObjectClassFieldType'{class=ClRef} ->
+ %% this case occures in a SEQUENCE when
+ %% the type of the component is a ObjectClassFieldType
+ ClassSpec = check_class(S,ClRef),
+ NewTypeDef = maybe_open_type(S,ClassSpec,OCFT,Constr),
+ InnerTag = get_innertag(S,NewTypeDef),
+ MergedTag = merge_tags(Tag,InnerTag),
+ Ct =
+ case is_open_type(NewTypeDef) of
+ true ->
+ maybe_illicit_implicit_tag(open_type,MergedTag);
+ _ ->
+ MergedTag
+ end,
+ TempNewDef#newt{type=NewTypeDef,tag=Ct};
+ {valueset,Vtype} ->
+ TempNewDef#newt{type={valueset,check_type(S,Type,Vtype)}};
+ Other ->
+ exit({'cant check' ,Other})
+ end,
+ Ts2 = case NewDef of
+ #newt{type=unchanged} ->
+ Ts#type{def=Def};
+ #newt{type=TDef}->
+ Ts#type{def=TDef}
+ end,
+ NewTag = case NewDef of
+ #newt{tag=unchanged} ->
+ Tag;
+ #newt{tag=TT} ->
+ TT
+ end,
+ T3 = Ts2#type{tag = lists:map(fun(TempTag = #tag{type={default,TTx}}) ->
+ TempTag#tag{type=TTx};
+ (Else) -> Else end, NewTag)},
+ T4 = case NewDef of
+ #newt{constraint=unchanged} ->
+ T3#type{constraint=Constr};
+ #newt{constraint=NewConstr} ->
+ T3#type{constraint=NewConstr}
+ end,
+ T5 = T4#type{inlined=NewDef#newt.inlined},
+ T5#type{constraint=check_constraints(S,T5#type.constraint)}.
+
+
+get_innertag(_S,#'ObjectClassFieldType'{type=Type}) ->
+ case Type of
+ #type{tag=Tag} -> Tag;
+ {fixedtypevaluefield,_,#type{tag=Tag}} -> Tag;
+ {TypeFieldName,_} when atom(TypeFieldName) -> [];
+ _ -> []
+ end;
+get_innertag(_S,_) ->
+ [].
+
+is_class(_S,#classdef{}) ->
+ true;
+is_class(S,#typedef{typespec=#type{def=Eref}})
+ when record(Eref,'Externaltypereference')->
+ {_,NextDef} = get_referenced_type(S,Eref),
+ is_class(S,NextDef);
+is_class(_,_) ->
+ false.
+
+get_class_def(_S,CD=#classdef{}) ->
+ CD;
+get_class_def(S,#typedef{typespec=#type{def=Eref}})
+ when record(Eref,'Externaltypereference') ->
+ {_,NextDef} = get_referenced_type(S,Eref),
+ get_class_def(S,NextDef).
+
+maybe_illicit_implicit_tag(Kind,Tag) ->
+ case Tag of
+ [#tag{type='IMPLICIT'}|_T] ->
+ throw({error,{asn1,{implicit_tag_before,Kind}}});
+ [ChTag = #tag{type={default,_}}|T] ->
+ case Kind of
+ open_type ->
+ [ChTag#tag{type='EXPLICIT',form=32}|T]; %X.680 30.6c, X.690 8.14.2
+ choice ->
+ [ChTag#tag{type='EXPLICIT',form=32}|T] % X.680 28.6 c, 30.6c
+ end;
+ _ ->
+ Tag % unchanged
+ end.
+
+%% maybe_open_type/2 -> {ClassSpec,FieldRefList} | 'ASN1_OPEN_TYPE'
+%% if the FieldRefList points out a typefield and the class don't have
+%% any UNIQUE field, so that a component relation constraint cannot specify
+%% the type of a typefield, return 'ASN1_OPEN_TYPE', otherwise return
+%% {ClassSpec,FieldRefList}.
+maybe_open_type(S,ClassSpec=#objectclass{fields=Fs},
+ OCFT=#'ObjectClassFieldType'{fieldname=FieldRefList},
+ Constr) ->
+ Type = get_ObjectClassFieldType(S,Fs,FieldRefList),
+ FieldNames=get_referenced_fieldname(FieldRefList),
+ case lists:last(FieldRefList) of
+ {valuefieldreference,_} ->
+ OCFT#'ObjectClassFieldType'{class=ClassSpec,
+ fieldname=FieldNames,
+ type=Type};
+ {typefieldreference,_} ->
+ case {catch get_unique_fieldname(#classdef{typespec=ClassSpec}),
+ asn1ct_gen:get_constraint(Constr,componentrelation)}of
+ {Tuple,_} when tuple(Tuple) ->
+ OCFT#'ObjectClassFieldType'{class=ClassSpec,
+ fieldname=FieldNames,
+ type='ASN1_OPEN_TYPE'};
+ {_,no} ->
+ OCFT#'ObjectClassFieldType'{class=ClassSpec,
+ fieldname=FieldNames,
+ type='ASN1_OPEN_TYPE'};
+ _ ->
+ OCFT#'ObjectClassFieldType'{class=ClassSpec,
+ fieldname=FieldNames,
+ type=Type}
+ end
+ end.
+
+is_open_type(#'ObjectClassFieldType'{type='ASN1_OPEN_TYPE'}) ->
+ true;
+is_open_type(#'ObjectClassFieldType'{}) ->
+ false.
+
+
+notify_if_not_ptype(S,#pvaluesetdef{type=Type}) ->
+ case Type#type.def of
+ Ref when record(Ref,'Externaltypereference') ->
+ case get_referenced_type(S,Ref) of
+ {_,#classdef{}} ->
+ throw(pobjectsetdef);
+ {_,#typedef{}} ->
+ throw(pvalueset)
+ end;
+ T when record(T,type) -> % this must be a value set
+ throw(pvalueset)
+ end;
+notify_if_not_ptype(_S,#ptypedef{}) ->
+ ok.
+
+% fix me
+instantiate_ptype(S,Ptypedef,ParaList) ->
+ #ptypedef{args=Args,typespec=Type} = Ptypedef,
+% Args = get_pt_args(Ptypedef),
+% Type = get_pt_spec(Ptypedef),
+ MatchedArgs = match_args(Args, ParaList, []),
+ NewS = S#state{type=Type,parameters=MatchedArgs,abscomppath=[]},
+ %The abscomppath must be empty since a table constraint in a
+ %parameterized type only can refer to components within the type
+ check_type(NewS, Ptypedef, Type).
+
+get_pt_args(#ptypedef{args=Args}) ->
+ Args;
+get_pt_args(#pvaluesetdef{args=Args}) ->
+ Args;
+get_pt_args(#pvaluedef{args=Args}) ->
+ Args;
+get_pt_args(#pobjectdef{args=Args}) ->
+ Args;
+get_pt_args(#pobjectsetdef{args=Args}) ->
+ Args.
+
+get_pt_spec(#ptypedef{typespec=Type}) ->
+ Type;
+get_pt_spec(#pvaluedef{value=Value}) ->
+ Value;
+get_pt_spec(#pvaluesetdef{valueset=VS}) ->
+ VS;
+get_pt_spec(#pobjectdef{def=Def}) ->
+ Def;
+get_pt_spec(#pobjectsetdef{def=Def}) ->
+ Def.
+
+
+
+match_args([FormArg|Ft], [ActArg|At], Acc) ->
+ match_args(Ft, At, [{FormArg,ActArg}|Acc]);
+match_args([], [], Acc) ->
+ lists:reverse(Acc);
+match_args(_, _, _) ->
+ throw({error,{asn1,{wrong_number_of_arguments}}}).
+
+check_constraints(S,C) when list(C) ->
+ check_constraints(S, C, []);
+check_constraints(S,C) when record(C,constraint) ->
+ check_constraints(S, C#constraint.c, []).
+
+
+resolv_tuple_or_list(S,List) when list(List) ->
+ lists:map(fun(X)->resolv_value(S,X) end, List);
+resolv_tuple_or_list(S,{Lb,Ub}) ->
+ {resolv_value(S,Lb),resolv_value(S,Ub)}.
+
+%%%-----------------------------------------
+%% If the constraint value is a defined value the valuename
+%% is replaced by the actual value
+%%
+resolv_value(S,Val) ->
+ case match_parameters(Val, S#state.parameters) of
+ Id -> % unchanged
+ resolv_value1(S,Id);
+ Other ->
+ resolv_value(S,Other)
+ end.
+
+resolv_value1(S = #state{mname=M,inputmodules=InpMods},
+ V=#'Externalvaluereference'{pos=Pos,module=ExtM,value=Name}) ->
+ case ExtM of
+ M -> resolv_value2(S,M,Name,Pos);
+ _ ->
+ case lists:member(ExtM,InpMods) of
+ true ->
+ resolv_value2(S,M,Name,Pos);
+ false ->
+ V
+ end
+ end;
+resolv_value1(S,{gt,V}) ->
+ case V of
+ Int when integer(Int) ->
+ V + 1;
+ #valuedef{value=Int} ->
+ 1 + resolv_value(S,Int);
+ Other ->
+ throw({error,{asn1,{undefined_type_or_value,Other}}})
+ end;
+resolv_value1(S,{lt,V}) ->
+ case V of
+ Int when integer(Int) ->
+ V - 1;
+ #valuedef{value=Int} ->
+ resolv_value(S,Int) - 1;
+ Other ->
+ throw({error,{asn1,{undefined_type_or_value,Other}}})
+ end;
+resolv_value1(S,{'ValueFromObject',{object,Object},[{valuefieldreference,
+ FieldName}]}) ->
+ %% FieldName can hold either a fixed-type value or a variable-type value
+ %% Object is a DefinedObject, i.e. a #'Externaltypereference'
+ {_,ObjTDef} = get_referenced_type(S,Object),
+ TS = check_object(S,ObjTDef,ObjTDef#typedef.typespec),
+ {_,_,Components} = TS#'Object'.def,
+ case lists:keysearch(FieldName,1,Components) of
+ {value,{_,#valuedef{value=Val}}} ->
+ Val;
+ _ ->
+ error({value,"illegal value in constraint",S})
+ end;
+% resolv_value1(S,{'ValueFromObject',{po,Object,Params},FieldName}) ->
+% %% FieldName can hold either a fixed-type value or a variable-type value
+% %% Object is a ParameterizedObject
+resolv_value1(_,V) ->
+ V.
+
+resolv_value2(S,ModuleName,Name,Pos) ->
+ case asn1_db:dbget(ModuleName,Name) of
+ undefined ->
+ case imported(S,Name) of
+ {ok,Imodule} ->
+ {_,V2} = get_referenced(S,Imodule,Name,Pos),
+ V2#valuedef.value;
+ _ ->
+ throw({error,{asn1,{undefined_type_or_value,Name}}})
+ end;
+ Val ->
+ Val#valuedef.value
+ end.
+
+check_constraints(S,[{'ContainedSubtype',Type} | Rest], Acc) ->
+ {_,CTDef} = get_referenced_type(S,Type#type.def),
+ CType = check_type(S,S#state.tname,CTDef#typedef.typespec),
+ check_constraints(S,Rest,CType#type.constraint ++ Acc);
+check_constraints(S,[C | Rest], Acc) ->
+ check_constraints(S,Rest,[check_constraint(S,C) | Acc]);
+check_constraints(S,[],Acc) ->
+% io:format("Acc: ~p~n",[Acc]),
+ C = constraint_merge(S,lists:reverse(Acc)),
+% io:format("C: ~p~n",[C]),
+ lists:flatten(C).
+
+
+range_check(F={FixV,FixV}) ->
+% FixV;
+ F;
+range_check(VR={Lb,Ub}) when Lb < Ub ->
+ VR;
+range_check(Err={_,_}) ->
+ throw({error,{asn1,{illegal_size_constraint,Err}}});
+range_check(Value) ->
+ Value.
+
+check_constraint(S,Ext) when record(Ext,'Externaltypereference') ->
+ check_externaltypereference(S,Ext);
+
+
+check_constraint(S,{'SizeConstraint',{Lb,Ub}})
+ when list(Lb);tuple(Lb),size(Lb)==2 ->
+ case Lb of
+ #'Externalvaluereference'{} ->
+ check_constraint(S,{'SizeConstraint',{resolv_value(S,Lb),Ub}});
+ _ ->
+ NewLb = range_check(resolv_tuple_or_list(S,Lb)),
+ NewUb = range_check(resolv_tuple_or_list(S,Ub)),
+ {'SizeConstraint',{NewLb,NewUb}}
+ end;
+check_constraint(S,{'SizeConstraint',{Lb,Ub}}) ->
+ case {resolv_value(S,Lb),resolv_value(S,Ub)} of
+ {FixV,FixV} ->
+ {'SizeConstraint',FixV};
+ {Low,High} when Low < High ->
+ {'SizeConstraint',{Low,High}};
+ Err ->
+ throw({error,{asn1,{illegal_size_constraint,Err}}})
+ end;
+check_constraint(S,{'SizeConstraint',Lb}) ->
+ {'SizeConstraint',resolv_value(S,Lb)};
+
+check_constraint(S,{'SingleValue', L}) when list(L) ->
+ F = fun(A) -> resolv_value(S,A) end,
+ {'SingleValue',lists:map(F,L)};
+
+check_constraint(S,{'SingleValue', V}) when integer(V) ->
+ Val = resolv_value(S,V),
+%% [{'SingleValue',Val},{'ValueRange',{Val,Val}}]; % Why adding value range?
+ {'SingleValue',Val};
+check_constraint(S,{'SingleValue', V}) ->
+ {'SingleValue',resolv_value(S,V)};
+
+check_constraint(S,{'ValueRange', {Lb, Ub}}) ->
+ {'ValueRange',{resolv_value(S,Lb),resolv_value(S,Ub)}};
+
+%%check_constraint(S,{'ContainedSubtype',Type}) ->
+%% #typedef{typespec=TSpec} =
+%% check_type(S,S#state.tname,get_referenced_type(S,Type#type.def)),
+%% [C] = TSpec#type.constraint,
+%% C;
+
+check_constraint(S,{valueset,Type}) ->
+ {valueset,check_type(S,S#state.tname,Type)};
+
+check_constraint(S,{simpletable,Type}) ->
+ OSName = (Type#type.def)#'Externaltypereference'.type,
+ C = match_parameters(Type#type.def,S#state.parameters),
+ case C of
+ #'Externaltypereference'{} ->
+ Type#type{def=check_externaltypereference(S,C)},
+ {simpletable,OSName};
+ _ ->
+ check_type(S,S#state.tname,Type),
+ {simpletable,OSName}
+ end;
+
+check_constraint(S,{componentrelation,{objectset,Opos,Objset},Id}) ->
+ %% Objset is an 'Externaltypereference' record, since Objset is
+ %% a DefinedObjectSet.
+ RealObjset = match_parameters(Objset,S#state.parameters),
+ Ext = check_externaltypereference(S,RealObjset),
+ {componentrelation,{objectset,Opos,Ext},Id};
+
+check_constraint(S,Type) when record(Type,type) ->
+ #type{def=Def} = check_type(S,S#state.tname,Type),
+ Def;
+
+check_constraint(S,C) when list(C) ->
+ lists:map(fun(X)->check_constraint(S,X) end,C);
+% else keep the constraint unchanged
+check_constraint(_S,Any) ->
+% io:format("Constraint = ~p~n",[Any]),
+ Any.
+
+%% constraint_merge/2
+%% Compute the intersection of the outermost level of the constraint list.
+%% See Dubuisson second paragraph and fotnote on page 285.
+%% If constraints with extension are included in combined constraints. The
+%% resulting combination will have the extension of the last constraint. Thus,
+%% there will be no extension if the last constraint is without extension.
+%% The rootset of all constraints are considered in the "outermoust
+%% intersection". See section 13.1.2 in Dubuisson.
+constraint_merge(_S,C=[H])when tuple(H) ->
+ C;
+constraint_merge(_S,[]) ->
+ [];
+constraint_merge(S,C) ->
+ %% skip all extension but the last
+ C1 = filter_extensions(C),
+ %% perform all internal level intersections, intersections first
+ %% since they have precedence over unions
+ C2 = lists:map(fun(X)when list(X)->constraint_intersection(S,X);
+ (X) -> X end,
+ C1),
+ %% perform all internal level unions
+ C3 = lists:map(fun(X)when list(X)->constraint_union(S,X);
+ (X) -> X end,
+ C2),
+
+ %% now get intersection of the outermost level
+ %% get the least common single value constraint
+ SVs = get_constraints(C3,'SingleValue'),
+ CombSV = intersection_of_sv(S,SVs),
+ %% get the least common value range constraint
+ VRs = get_constraints(C3,'ValueRange'),
+ CombVR = intersection_of_vr(S,VRs),
+ %% get the least common size constraint
+ SZs = get_constraints(C3,'SizeConstraint'),
+ CombSZ = intersection_of_size(S,SZs),
+ CminusSVs=ordsets:subtract(ordsets:from_list(C3),ordsets:from_list(SVs)),
+ % CminusSVsVRs = ordsets:subtract(ordsets:from_list(CminusSVs),
+% ordsets:from_list(VRs)),
+ RestC = ordsets:subtract(ordsets:from_list(CminusSVs),
+ ordsets:from_list(SZs)),
+ %% get the least common combined constraint. That is the union of each
+ %% deep costraint and merge of single value and value range constraints
+ combine_constraints(S,CombSV,CombVR,CombSZ++RestC).
+
+%% constraint_union(S,C) takes a list of constraints as input and
+%% merge them to a union. Unions are performed when two
+%% constraints is found with an atom union between.
+%% The list may be nested. Fix that later !!!
+constraint_union(_S,[]) ->
+ [];
+constraint_union(_S,C=[_E]) ->
+ C;
+constraint_union(S,C) when list(C) ->
+ case lists:member(union,C) of
+ true ->
+ constraint_union1(S,C,[]);
+ _ ->
+ C
+ end;
+% SV = get_constraints(C,'SingleValue'),
+% SV1 = constraint_union_sv(S,SV),
+% VR = get_constraints(C,'ValueRange'),
+% VR1 = constraint_union_vr(VR),
+% RestC = ordsets:filter(fun({'SingleValue',_})->false;
+% ({'ValueRange',_})->false;
+% (_) -> true end,ordsets:from_list(C)),
+% SV1++VR1++RestC;
+constraint_union(_S,C) ->
+ [C].
+
+constraint_union1(S,[A={'ValueRange',_},union,B={'ValueRange',_}|Rest],Acc) ->
+ AunionB = constraint_union_vr([A,B]),
+ constraint_union1(S,Rest,AunionB++Acc);
+constraint_union1(S,[A={'SingleValue',_},union,B={'SingleValue',_}|Rest],Acc) ->
+ AunionB = constraint_union_sv(S,[A,B]),
+ constraint_union1(S,Rest,AunionB++Acc);
+constraint_union1(S,[A={'SingleValue',_},union,B={'ValueRange',_}|Rest],Acc) ->
+ AunionB = union_sv_vr(S,A,B),
+ constraint_union1(S,Rest,AunionB++Acc);
+constraint_union1(S,[A={'ValueRange',_},union,B={'SingleValue',_}|Rest],Acc) ->
+ AunionB = union_sv_vr(S,B,A),
+ constraint_union1(S,Rest,AunionB++Acc);
+constraint_union1(S,[union|Rest],Acc) -> %skip when unsupported constraints
+ constraint_union1(S,Rest,Acc);
+constraint_union1(S,[A|Rest],Acc) ->
+ constraint_union1(S,Rest,[A|Acc]);
+constraint_union1(_S,[],Acc) ->
+ lists:reverse(Acc).
+
+constraint_union_sv(_S,SV) ->
+ Values=lists:map(fun({_,V})->V end,SV),
+ case ordsets:from_list(Values) of
+ [] -> [];
+ [N] -> [{'SingleValue',N}];
+ L -> [{'SingleValue',L}]
+ end.
+
+%% REMOVE????
+%%constraint_union(S,VR,'ValueRange') ->
+%% constraint_union_vr(VR).
+
+%% constraint_union_vr(VR)
+%% VR = [{'ValueRange',{Lb,Ub}},...]
+%% Lb = 'MIN' | integer()
+%% Ub = 'MAX' | integer()
+%% Returns if possible only one ValueRange tuple with a range that
+%% is a union of all ranges in VR.
+constraint_union_vr(VR) ->
+ %% Sort VR by Lb in first hand and by Ub in second hand
+ Fun=fun({_,{'MIN',_B1}},{_,{A2,_B2}}) when integer(A2)->true;
+ ({_,{A1,_B1}},{_,{'MAX',_B2}}) when integer(A1) -> true;
+ ({_,{A1,_B1}},{_,{A2,_B2}}) when integer(A1),integer(A2),A1<A2 -> true;
+ ({_,{A,B1}},{_,{A,B2}}) when B1=<B2->true;
+ (_,_)->false end,
+ constraint_union_vr(lists:usort(Fun,VR),[]).
+
+constraint_union_vr([],Acc) ->
+ lists:reverse(Acc);
+constraint_union_vr([C|Rest],[]) ->
+ constraint_union_vr(Rest,[C]);
+constraint_union_vr([{_,{Lb,Ub2}}|Rest],[{_,{Lb,_Ub1}}|Acc]) -> %Ub2 > Ub1
+ constraint_union_vr(Rest,[{'ValueRange',{Lb,Ub2}}|Acc]);
+constraint_union_vr([{_,{_,Ub}}|Rest],A=[{_,{_,Ub}}|_Acc]) ->
+ constraint_union_vr(Rest,A);
+constraint_union_vr([{_,{Lb2,Ub2}}|Rest],[{_,{Lb1,Ub1}}|Acc]) when Lb2=<Ub1,
+ Ub2>Ub1->
+ constraint_union_vr(Rest,[{'ValueRange',{Lb1,Ub2}}|Acc]);
+constraint_union_vr([{_,{_,Ub2}}|Rest],A=[{_,{_,Ub1}}|_Acc]) when Ub2=<Ub1->
+ constraint_union_vr(Rest,A);
+constraint_union_vr([VR|Rest],Acc) ->
+ constraint_union_vr(Rest,[VR|Acc]).
+
+union_sv_vr(_S,[],B) ->
+ [B];
+union_sv_vr(_S,A,[]) ->
+ [A];
+union_sv_vr(_S,C1={'SingleValue',SV},C2={'ValueRange',VR={Lb,Ub}})
+ when integer(SV) ->
+ case is_int_in_vr(SV,C2) of
+ true -> [C2];
+ _ ->
+ case VR of
+ {'MIN',Ub} when SV==Ub+1 -> [{'ValueRange',{'MIN',SV}}];
+ {Lb,'MAX'} when SV==Lb-1 -> [{'ValueRange',{SV,'MAX'}}];
+ {Lb,Ub} when SV==Ub+1 -> [{'ValueRange',{Lb,SV}}];
+ {Lb,Ub} when SV==Lb-1 -> [{'ValueRange',{SV,Ub}}];
+ _ ->
+ [C1,C2]
+ end
+ end;
+union_sv_vr(_S,C1={'SingleValue',SV},C2={'ValueRange',{_Lb,_Ub}})
+ when list(SV) ->
+ case lists:filter(fun(X)->is_int_in_vr(X,C2) end,SV) of
+ [] -> [C2];
+ L ->
+ case expand_vr(L,C2) of
+ {[],C3} -> [C3];
+ {L,C2} -> [C1,C2];
+ {[Val],C3} -> [{'SingleValue',Val},C3];
+ {L2,C3} -> [{'SingleValue',L2},C3]
+ end
+ end.
+
+expand_vr(L,VR={_,{Lb,Ub}}) ->
+ case lower_Lb(L,Lb) of
+ false ->
+ case higher_Ub(L,Ub) of
+ false ->
+ {L,VR};
+ {L1,UbNew} ->
+ expand_vr(L1,{'ValueRange',{Lb,UbNew}})
+ end;
+ {L1,LbNew} ->
+ expand_vr(L1,{'ValueRange',{LbNew,Ub}})
+ end.
+
+lower_Lb(_,'MIN') ->
+ false;
+lower_Lb(L,Lb) ->
+ remove_val_from_list(Lb - 1,L).
+
+higher_Ub(_,'MAX') ->
+ false;
+higher_Ub(L,Ub) ->
+ remove_val_from_list(Ub + 1,L).
+
+remove_val_from_list(List,Val) ->
+ case lists:member(Val,List) of
+ true ->
+ {lists:delete(Val,List),Val};
+ false ->
+ false
+ end.
+
+%% get_constraints/2
+%% Arguments are a list of constraints, which has the format {key,value},
+%% and a constraint type
+%% Returns a list of constraints only of the requested type or the atom
+%% 'no' if no such constraints were found
+get_constraints(L=[{CType,_}],CType) ->
+ L;
+get_constraints(C,CType) ->
+ keysearch_allwithkey(CType,1,C).
+
+%% keysearch_allwithkey(Key,Ix,L)
+%% Types:
+%% Key = atom()
+%% Ix = integer()
+%% L = [TwoTuple]
+%% TwoTuple = [{atom(),term()}|...]
+%% Returns a List that contains all
+%% elements from L that has a key Key as element Ix
+keysearch_allwithkey(Key,Ix,L) ->
+ lists:filter(fun(X) when tuple(X) ->
+ case element(Ix,X) of
+ Key -> true;
+ _ -> false
+ end;
+ (_) -> false
+ end, L).
+
+
+%% filter_extensions(C)
+%% takes a list of constraints as input and
+%% returns a list with the intersection of all extension roots
+%% and only the extension of the last constraint kept if any
+%% extension in the last constraint
+filter_extensions([]) ->
+ [];
+filter_extensions(C=[_H]) ->
+ C;
+filter_extensions(C) when list(C) ->
+ filter_extensions(C,[]).
+
+filter_extensions([C],Acc) ->
+ lists:reverse([C|Acc]);
+filter_extensions([{C,_E},H2|T],Acc) when tuple(C) ->
+ filter_extensions([H2|T],[C|Acc]);
+filter_extensions([{'SizeConstraint',{A,_B}},H2|T],Acc)
+ when list(A);tuple(A) ->
+ filter_extensions([H2|T],[{'SizeConstraint',A}|Acc]);
+filter_extensions([H1,H2|T],Acc) ->
+ filter_extensions([H2|T],[H1|Acc]).
+
+%% constraint_intersection(S,C) takes a list of constraints as input and
+%% performs intersections. Intersecions are performed when an
+%% atom intersection is found between two constraints.
+%% The list may be nested. Fix that later !!!
+constraint_intersection(_S,[]) ->
+ [];
+constraint_intersection(_S,C=[_E]) ->
+ C;
+constraint_intersection(S,C) when list(C) ->
+% io:format("constraint_intersection: ~p~n",[C]),
+ case lists:member(intersection,C) of
+ true ->
+ constraint_intersection1(S,C,[]);
+ _ ->
+ C
+ end;
+constraint_intersection(_S,C) ->
+ [C].
+
+constraint_intersection1(S,[A,intersection,B|Rest],Acc) ->
+ AisecB = c_intersect(S,A,B),
+ constraint_intersection1(S,Rest,AisecB++Acc);
+constraint_intersection1(S,[A|Rest],Acc) ->
+ constraint_intersection1(S,Rest,[A|Acc]);
+constraint_intersection1(_,[],Acc) ->
+ lists:reverse(Acc).
+
+c_intersect(S,C1={'SingleValue',_},C2={'SingleValue',_}) ->
+ intersection_of_sv(S,[C1,C2]);
+c_intersect(S,C1={'ValueRange',_},C2={'ValueRange',_}) ->
+ intersection_of_vr(S,[C1,C2]);
+c_intersect(S,C1={'ValueRange',_},C2={'SingleValue',_}) ->
+ intersection_sv_vr(S,[C2],[C1]);
+c_intersect(S,C1={'SingleValue',_},C2={'ValueRange',_}) ->
+ intersection_sv_vr(S,[C1],[C2]);
+c_intersect(_S,C1,C2) ->
+ [C1,C2].
+
+%% combine_constraints(S,SV,VR,CComb)
+%% Types:
+%% S = record(state,S)
+%% SV = [] | [SVC]
+%% VR = [] | [VRC]
+%% CComb = [] | [Lists]
+%% SVC = {'SingleValue',integer()} | {'SingleValue',[integer(),...]}
+%% VRC = {'ValueRange',{Lb,Ub}}
+%% Lists = List of lists containing any constraint combination
+%% Lb = 'MIN' | integer()
+%% Ub = 'MAX' | integer()
+%% Returns a combination of the least common constraint among SV,VR and all
+%% elements in CComb
+combine_constraints(_S,[],VR,CComb) ->
+ VR ++ CComb;
+% combine_combined_cnstr(S,VR,CComb);
+combine_constraints(_S,SV,[],CComb) ->
+ SV ++ CComb;
+% combine_combined_cnstr(S,SV,CComb);
+combine_constraints(S,SV,VR,CComb) ->
+ C=intersection_sv_vr(S,SV,VR),
+ C ++ CComb.
+% combine_combined_cnstr(S,C,CComb).
+
+intersection_sv_vr(_,[],_VR) ->
+ [];
+intersection_sv_vr(_,_SV,[]) ->
+ [];
+intersection_sv_vr(_S,[C1={'SingleValue',SV}],[C2={'ValueRange',{_Lb,_Ub}}])
+ when integer(SV) ->
+ case is_int_in_vr(SV,C2) of
+ true -> [C1];
+ _ -> %%error({type,{"asn1 illegal constraint",C1,C2},S})
+ throw({error,{"asn1 illegal constraint",C1,C2}})
+ end;
+intersection_sv_vr(_S,[C1={'SingleValue',SV}],[C2])
+ when list(SV) ->
+ case lists:filter(fun(X)->is_int_in_vr(X,C2) end,SV) of
+ [] ->
+ %%error({type,{"asn1 illegal constraint",C1,C2},S});
+ throw({error,{"asn1 illegal constraint",C1,C2}});
+ [V] -> [{'SingleValue',V}];
+ L -> [{'SingleValue',L}]
+ end.
+
+
+
+intersection_of_size(_,[]) ->
+ [];
+intersection_of_size(_,C=[_SZ]) ->
+ C;
+intersection_of_size(S,[SZ,SZ|Rest]) ->
+ intersection_of_size(S,[SZ|Rest]);
+intersection_of_size(S,C=[C1={_,Int},{_,Range}|Rest])
+ when integer(Int),tuple(Range) ->
+ case Range of
+ {Lb,Ub} when Int >= Lb,
+ Int =< Ub ->
+ intersection_of_size(S,[C1|Rest]);
+ _ ->
+ throw({error,{asn1,{illegal_size_constraint,C}}})
+ end;
+intersection_of_size(S,[C1={_,Range},C2={_,Int}|Rest])
+ when integer(Int),tuple(Range) ->
+ intersection_of_size(S,[C2,C1|Rest]);
+intersection_of_size(S,[{_,{Lb1,Ub1}},{_,{Lb2,Ub2}}|Rest]) ->
+ Lb=greatest_LB(ordsets:from_list([Lb1,Lb2])),
+ Ub=smallest_UB(ordsets:from_list([Ub1,Ub2])),
+ intersection_of_size(S,[{'SizeConstraint',{Lb,Ub}}|Rest]);
+intersection_of_size(_,SZ) ->
+ throw({error,{asn1,{illegal_size_constraint,SZ}}}).
+
+intersection_of_vr(_,[]) ->
+ [];
+intersection_of_vr(_,VR=[_C]) ->
+ VR;
+intersection_of_vr(S,[{_,{Lb1,Ub1}},{_,{Lb2,Ub2}}|Rest]) ->
+ Lb=greatest_LB(ordsets:from_list([Lb1,Lb2])),
+ Ub=smallest_UB(ordsets:from_list([Ub1,Ub2])),
+ intersection_of_vr(S,[{'ValueRange',{Lb,Ub}}|Rest]);
+intersection_of_vr(_S,VR) ->
+ %%error({type,{asn1,{illegal_value_range_constraint,VR}},S});
+ throw({error,{asn1,{illegal_value_range_constraint,VR}}}).
+
+intersection_of_sv(_,[]) ->
+ [];
+intersection_of_sv(_,SV=[_C]) ->
+ SV;
+intersection_of_sv(S,[SV,SV|Rest]) ->
+ intersection_of_sv(S,[SV|Rest]);
+intersection_of_sv(S,[{_,Int},{_,SV}|Rest]) when integer(Int),
+ list(SV) ->
+ SV2=intersection_of_sv1(S,Int,SV),
+ intersection_of_sv(S,[SV2|Rest]);
+intersection_of_sv(S,[{_,SV},{_,Int}|Rest]) when integer(Int),
+ list(SV) ->
+ SV2=intersection_of_sv1(S,Int,SV),
+ intersection_of_sv(S,[SV2|Rest]);
+intersection_of_sv(S,[{_,SV1},{_,SV2}|Rest]) when list(SV1),
+ list(SV2) ->
+ SV3=common_set(SV1,SV2),
+ intersection_of_sv(S,[SV3|Rest]);
+intersection_of_sv(_S,SV) ->
+ %%error({type,{asn1,{illegal_single_value_constraint,SV}},S}).
+ throw({error,{asn1,{illegal_single_value_constraint,SV}}}).
+
+intersection_of_sv1(_S,Int,SV) when integer(Int),list(SV) ->
+ case lists:member(Int,SV) of
+ true -> {'SingleValue',Int};
+ _ ->
+ %%error({type,{asn1,{illegal_single_value_constraint,Int,SV}},S})
+ throw({error,{asn1,{illegal_single_value_constraint,Int,SV}}})
+ end;
+intersection_of_sv1(_S,SV1,SV2) ->
+ %%error({type,{asn1,{illegal_single_value_constraint,SV1,SV2}},S}).
+ throw({error,{asn1,{illegal_single_value_constraint,SV1,SV2}}}).
+
+greatest_LB([H]) ->
+ H;
+greatest_LB(L) ->
+ greatest_LB1(lists:reverse(L)).
+greatest_LB1(['MIN',H2|_T])->
+ H2;
+greatest_LB1([H|_T]) ->
+ H.
+smallest_UB(L) ->
+ hd(L).
+
+common_set(SV1,SV2) ->
+ lists:filter(fun(X)->lists:member(X,SV1) end,SV2).
+
+is_int_in_vr(Int,{_,{'MIN','MAX'}}) when integer(Int) ->
+ true;
+is_int_in_vr(Int,{_,{'MIN',Ub}}) when integer(Int),Int =< Ub ->
+ true;
+is_int_in_vr(Int,{_,{Lb,'MAX'}}) when integer(Int),Int >= Lb ->
+ true;
+is_int_in_vr(Int,{_,{Lb,Ub}}) when integer(Int),Int >= Lb,Int =< Ub ->
+ true;
+is_int_in_vr(_,_) ->
+ false.
+
+
+
+check_imported(_S,Imodule,Name) ->
+ case asn1_db:dbget(Imodule,'MODULE') of
+ undefined ->
+ io:format("~s.asn1db not found~n",[Imodule]),
+ io:format("Type ~s imported from non existing module ~s~n",[Name,Imodule]);
+ Im when record(Im,module) ->
+ case is_exported(Im,Name) of
+ false ->
+ io:format("Imported type ~s not exported from module ~s~n",[Name,Imodule]);
+ _ ->
+ ok
+ end
+ end,
+ ok.
+
+is_exported(Module,Name) when record(Module,module) ->
+ {exports,Exports} = Module#module.exports,
+ case Exports of
+ all ->
+ true;
+ [] ->
+ false;
+ L when list(L) ->
+ case lists:keysearch(Name,#'Externaltypereference'.type,Exports) of
+ false -> false;
+ _ -> true
+ end
+ end.
+
+
+
+check_externaltypereference(S,Etref=#'Externaltypereference'{module=Emod})->
+ Currmod = S#state.mname,
+ MergedMods = S#state.inputmodules,
+ case Emod of
+ Currmod ->
+ %% reference to current module or to imported reference
+ check_reference(S,Etref);
+ _ ->
+ %% io:format("Type ~s IMPORTED FROM ~s~n",[Etype,Emod]),
+ case lists:member(Emod,MergedMods) of
+ true ->
+ check_reference(S,Etref);
+ false ->
+ Etref
+ end
+ end.
+
+check_reference(S,#'Externaltypereference'{pos=Pos,module=Emod,type=Name}) ->
+ ModName = S#state.mname,
+ case asn1_db:dbget(ModName,Name) of
+ undefined ->
+ case imported(S,Name) of
+ {ok,Imodule} ->
+ check_imported(S,Imodule,Name),
+ #'Externaltypereference'{module=Imodule,type=Name};
+ _ ->
+ %may be a renamed type in multi file compiling!
+ {_,T}=renamed_reference(S,Name,Emod),
+ NewName = asn1ct:get_name_of_def(T),
+ NewPos = asn1ct:get_pos_of_def(T),
+ #'Externaltypereference'{pos=NewPos,
+ module=ModName,
+ type=NewName}
+ end;
+ _ ->
+ %% cannot do check_type here due to recursive definitions, like
+ %% S ::= SEQUENCE {a INTEGER, b S}. This implies that references
+ %% that appear before the definition will be an
+ %% Externaltypereference in the abstract syntax tree
+ #'Externaltypereference'{pos=Pos,module=ModName,type=Name}
+ end.
+
+
+name2Extref(_Mod,Name) when record(Name,'Externaltypereference') ->
+ Name;
+name2Extref(Mod,Name) ->
+ #'Externaltypereference'{module=Mod,type=Name}.
+
+get_referenced_type(S,Ext) when record(Ext,'Externaltypereference') ->
+ case match_parameters(Ext, S#state.parameters) of
+ Ext ->
+ #'Externaltypereference'{pos=Pos,module=Emod,type=Etype} = Ext,
+ case S#state.mname of
+ Emod -> % a local reference in this module
+ get_referenced1(S,Emod,Etype,Pos);
+ _ ->% always when multi file compiling
+ case lists:member(Emod,S#state.inputmodules) of
+ true ->
+ get_referenced1(S,Emod,Etype,Pos);
+ false ->
+ get_referenced(S,Emod,Etype,Pos)
+ end
+ end;
+ Other ->
+ {undefined,Other}
+ end;
+get_referenced_type(S=#state{mname=Emod},
+ ERef=#'Externalvaluereference'{pos=P,module=Emod,
+ value=Eval}) ->
+ case match_parameters(ERef,S#state.parameters) of
+ ERef ->
+ get_referenced1(S,Emod,Eval,P);
+ OtherERef when record(OtherERef,'Externalvaluereference') ->
+ get_referenced_type(S,OtherERef);
+ Value ->
+ {Emod,Value}
+ end;
+get_referenced_type(S,ERef=#'Externalvaluereference'{pos=Pos,module=Emod,
+ value=Eval}) ->
+ case match_parameters(ERef,S#state.parameters) of
+ ERef ->
+ case lists:member(Emod,S#state.inputmodules) of
+ true ->
+ get_referenced1(S,Emod,Eval,Pos);
+ false ->
+ get_referenced(S,Emod,Eval,Pos)
+ end;
+ OtherERef ->
+ get_referenced_type(S,OtherERef)
+ end;
+get_referenced_type(S,#identifier{val=Name,pos=Pos}) ->
+ get_referenced1(S,undefined,Name,Pos);
+get_referenced_type(_S,Type) ->
+ {undefined,Type}.
+
+%% get_referenced/3
+%% The referenced entity Ename may in case of an imported parameterized
+%% type reference imported entities in the other module, which implies that
+%% asn1_db:dbget will fail even though the referenced entity exists. Thus
+%% Emod may be the module that imports the entity Ename and not holds the
+%% data about Ename.
+get_referenced(S,Emod,Ename,Pos) ->
+ case asn1_db:dbget(Emod,Ename) of
+ undefined ->
+ %% May be an imported entity in module Emod
+% throw({error,{asn1,{undefined_type_or_value,{Emod,Ename}}}});
+ NewS = S#state{module=asn1_db:dbget(Emod,'MODULE')},
+ get_imported(NewS,Ename,Emod,Pos);
+ T when record(T,typedef) ->
+ Spec = T#typedef.typespec,
+ case Spec#type.def of
+ Tref when record(Tref,typereference) ->
+ Def = #'Externaltypereference'{module=Emod,
+ type=Tref#typereference.val,
+ pos=Tref#typereference.pos},
+
+
+ {Emod,T#typedef{typespec=Spec#type{def=Def}}};
+ _ ->
+ {Emod,T} % should add check that T is exported here
+ end;
+ V -> {Emod,V}
+ end.
+
+get_referenced1(S,ModuleName,Name,Pos) ->
+ case asn1_db:dbget(S#state.mname,Name) of
+ undefined ->
+ %% ModuleName may be other than S#state.mname when
+ %% multi file compiling is used.
+ get_imported(S,Name,ModuleName,Pos);
+ T ->
+ {S#state.mname,T}
+ end.
+
+get_imported(S,Name,Module,Pos) ->
+ case imported(S,Name) of
+ {ok,Imodule} ->
+ case asn1_db:dbget(Imodule,'MODULE') of
+ undefined ->
+ throw({error,{asn1,{module_not_found,Imodule}}});
+ Im when record(Im,module) ->
+ case is_exported(Im,Name) of
+ false ->
+ throw({error,
+ {asn1,{not_exported,{Im,Name}}}});
+ _ ->
+ get_referenced_type(S,
+ #'Externaltypereference'
+ {module=Imodule,
+ type=Name,pos=Pos})
+ end
+ end;
+ _ ->
+ renamed_reference(S,Name,Module)
+ end.
+
+renamed_reference(S,Name,Module) ->
+ %% first check if there is a renamed type in this module
+ %% second check if any type was imported with this name
+ case ets:info(renamed_defs) of
+ undefined -> throw({error,{asn1,{undefined_type,Name}}});
+ _ ->
+ case ets:match(renamed_defs,{'$1',Name,Module}) of
+ [] ->
+ case ets:info(original_imports) of
+ undefined ->
+ throw({error,{asn1,{undefined_type,Name}}});
+ _ ->
+ case ets:match(original_imports,{Module,'$1'}) of
+ [] ->
+ throw({error,{asn1,{undefined_type,Name}}});
+ [[ImportsList]] ->
+ case get_importmoduleoftype(ImportsList,Name) of
+ undefined ->
+ throw({error,{asn1,{undefined_type,Name}}});
+ NextMod ->
+ renamed_reference(S,Name,NextMod)
+ end
+ end
+ end;
+ [[NewTypeName]] ->
+ get_referenced1(S,Module,NewTypeName,undefined)
+ end
+ end.
+
+get_importmoduleoftype([I|Is],Name) ->
+ Index = #'Externaltypereference'.type,
+ case lists:keysearch(Name,Index,I#'SymbolsFromModule'.symbols) of
+ {value,_Ref} ->
+ (I#'SymbolsFromModule'.module)#'Externaltypereference'.type;
+ _ ->
+ get_importmoduleoftype(Is,Name)
+ end;
+get_importmoduleoftype([],_) ->
+ undefined.
+
+
+match_parameters(Name,[]) ->
+ Name;
+
+match_parameters(#'Externaltypereference'{type=Name},[{#'Externaltypereference'{type=Name},NewName}|_T]) ->
+ NewName;
+match_parameters(#'Externaltypereference'{type=Name},[{{_,#'Externaltypereference'{type=Name}},NewName}|_T]) ->
+ NewName;
+% match_parameters(#'Externaltypereference'{type=Name},[{#typereference{val=Name},NewName}|T]) ->
+% NewName;
+% match_parameters(#'Externaltypereference'{type=Name},[{{_,#typereference{val=Name}},NewName}|T]) ->
+% NewName;
+%match_parameters(#typereference{val=Name},[{#typereference{val=Name},NewName}|T]) ->
+% NewName;
+match_parameters(#'Externalvaluereference'{value=Name},[{#'Externalvaluereference'{value=Name},NewName}|_T]) ->
+ NewName;
+match_parameters(#'Externalvaluereference'{value=Name},[{{_,#'Externalvaluereference'{value=Name}},NewName}|_T]) ->
+ NewName;
+% match_parameters(#identifier{val=Name},[{#identifier{val=Name},NewName}|T]) ->
+% NewName;
+% match_parameters(#identifier{val=Name},[{{_,#identifier{val=Name}},NewName}|T]) ->
+% NewName;
+match_parameters({valueset,#type{def=#'Externaltypereference'{type=Name}}},
+ [{{_,#'Externaltypereference'{type=Name}},{valueset,#type{def=NewName}}}|_T]) ->
+ NewName;
+match_parameters({valueset,#type{def=#'Externaltypereference'{type=Name}}},
+ [{{_,#'Externaltypereference'{type=Name}},NewName}|_T]) ->
+ NewName;
+% match_parameters({valueset,#type{def=#'Externaltypereference'{type=Name}}},
+% [{{_,#typereference{val=Name}},{valueset,#type{def=NewName}}}|T]) ->
+% NewName;
+% match_parameters({valueset,#type{def=#'Externaltypereference'{type=Name}}},
+% [{{_,#typereference{val=Name}},NewName}|T]) ->
+% NewName;
+
+match_parameters(Name, [_H|T]) ->
+ %%io:format("match_parameters(~p,~p)~n",[Name,[H|T]]),
+ match_parameters(Name,T).
+
+imported(S,Name) ->
+ {imports,Ilist} = (S#state.module)#module.imports,
+ imported1(Name,Ilist).
+
+imported1(Name,
+ [#'SymbolsFromModule'{symbols=Symlist,
+ module=#'Externaltypereference'{type=ModuleName}}|T]) ->
+ case lists:keysearch(Name,#'Externaltypereference'.type,Symlist) of
+ {value,_V} ->
+ {ok,ModuleName};
+ _ ->
+ imported1(Name,T)
+ end;
+imported1(_Name,[]) ->
+ false.
+
+
+check_integer(_S,[],_C) ->
+ ok;
+check_integer(S,NamedNumberList,_C) ->
+ case check_unique(NamedNumberList,2) of
+ [] ->
+ check_int(S,NamedNumberList,[]);
+ L when list(L) ->
+ error({type,{duplicates,L},S}),
+ unchanged
+
+ end.
+
+check_int(S,[{'NamedNumber',Id,Num}|T],Acc) when integer(Num) ->
+ check_int(S,T,[{Id,Num}|Acc]);
+check_int(S,[{'NamedNumber',Id,{identifier,_,Name}}|T],Acc) ->
+ Val = dbget_ex(S,S#state.mname,Name),
+ check_int(S,[{'NamedNumber',Id,Val#valuedef.value}|T],Acc);
+check_int(_S,[],Acc) ->
+ lists:keysort(2,Acc).
+
+
+
+check_bitstring(_S,[],_Constr) ->
+ [];
+check_bitstring(S,NamedNumberList,_Constr) ->
+ case check_unique(NamedNumberList,2) of
+ [] ->
+ check_bitstr(S,NamedNumberList,[]);
+ L when list(L) ->
+ error({type,{duplicates,L},S}),
+ unchanged
+ end.
+
+check_bitstr(S,[{'NamedNumber',Id,Num}|T],Acc)when integer(Num) ->
+ check_bitstr(S,T,[{Id,Num}|Acc]);
+check_bitstr(S,[{'NamedNumber',Id,Name}|T],Acc) when atom(Name) ->
+%%check_bitstr(S,[{'NamedNumber',Id,{identifier,_,Name}}|T],Acc) ->
+%% io:format("asn1ct_check:check_bitstr/3 hej hop ~w~n",[Name]),
+ Val = dbget_ex(S,S#state.mname,Name),
+%% io:format("asn1ct_check:check_bitstr/3: ~w~n",[Val]),
+ check_bitstr(S,[{'NamedNumber',Id,Val#valuedef.value}|T],Acc);
+check_bitstr(S,[],Acc) ->
+ case check_unique(Acc,2) of
+ [] ->
+ lists:keysort(2,Acc);
+ L when list(L) ->
+ error({type,{duplicate_values,L},S}),
+ unchanged
+ end.
+
+%%check_bitstring(S,NamedNumberList,Constr) ->
+%% NamedNumberList.
+
+%% Check INSTANCE OF
+%% check that DefinedObjectClass is of TYPE-IDENTIFIER class
+%% If Constraint is empty make it the general INSTANCE OF type
+%% If Constraint is not empty make an inlined type
+%% convert INSTANCE OF to the associated type
+check_instance_of(S,DefinedObjectClass,Constraint) ->
+ check_type_identifier(S,DefinedObjectClass),
+ iof_associated_type(S,Constraint).
+
+
+check_type_identifier(_S,'TYPE-IDENTIFIER') ->
+ ok;
+check_type_identifier(S,Eref=#'Externaltypereference'{}) ->
+ case get_referenced_type(S,Eref) of
+ {_,#classdef{name='TYPE-IDENTIFIER'}} -> ok;
+ {_,TD=#typedef{typespec=#type{def=#'Externaltypereference'{}}}} ->
+ check_type_identifier(S,(TD#typedef.typespec)#type.def);
+ _ ->
+ error({type,{"object set in type INSTANCE OF "
+ "not of class TYPE-IDENTIFIER",Eref},S})
+ end.
+
+iof_associated_type(S,[]) ->
+ %% in this case encode/decode functions for INSTANCE OF must be
+ %% generated
+ case get(instance_of) of
+ undefined ->
+ AssociateSeq = iof_associated_type1(S,[]),
+ Tag =
+ case S#state.erule of
+ ber_bin_v2 ->
+ [?TAG_CONSTRUCTED(?N_INSTANCE_OF)];
+ _ -> []
+ end,
+ TypeDef=#typedef{checked=true,
+ name='INSTANCE OF',
+ typespec=#type{tag=Tag,
+ def=AssociateSeq}},
+ asn1_db:dbput(S#state.mname,'INSTANCE OF',TypeDef),
+ put(instance_of,generate);
+ _ ->
+ ok
+ end,
+ #'Externaltypereference'{module=S#state.mname,type='INSTANCE OF'};
+iof_associated_type(S,C) ->
+ iof_associated_type1(S,C).
+
+iof_associated_type1(S,C) ->
+ {TableCInf,Comp1Cnstr,Comp2Cnstr,Comp2tablecinf}=
+ instance_of_constraints(S,C),
+
+ ModuleName = S#state.mname,
+ Typefield_type=
+ case C of
+ [] -> 'ASN1_OPEN_TYPE';
+ _ -> {typefield,'Type'}
+ end,
+ {ObjIdTag,C1TypeTag}=
+ case S#state.erule of
+ ber_bin_v2 ->
+ {[{'UNIVERSAL',8}],
+ [#tag{class='UNIVERSAL',
+ number=6,
+ type='IMPLICIT',
+ form=0}]};
+ _ -> {[{'UNIVERSAL','INTEGER'}],[]}
+ end,
+ TypeIdentifierRef=#'Externaltypereference'{module=ModuleName,
+ type='TYPE-IDENTIFIER'},
+ ObjectIdentifier =
+ #'ObjectClassFieldType'{classname=TypeIdentifierRef,
+ class=[],
+ fieldname={id,[]},
+ type={fixedtypevaluefield,id,
+ #type{def='OBJECT IDENTIFIER'}}},
+ Typefield =
+ #'ObjectClassFieldType'{classname=TypeIdentifierRef,
+ class=[],
+ fieldname={'Type',[]},
+ type=Typefield_type},
+ IOFComponents =
+ [#'ComponentType'{name='type-id',
+ typespec=#type{tag=C1TypeTag,
+ def=ObjectIdentifier,
+ constraint=Comp1Cnstr},
+ prop=mandatory,
+ tags=ObjIdTag},
+ #'ComponentType'{name=value,
+ typespec=#type{tag=[#tag{class='CONTEXT',
+ number=0,
+ type='EXPLICIT',
+ form=32}],
+ def=Typefield,
+ constraint=Comp2Cnstr,
+ tablecinf=Comp2tablecinf},
+ prop=mandatory,
+ tags=[{'CONTEXT',0}]}],
+ #'SEQUENCE'{tablecinf=TableCInf,
+ components=IOFComponents}.
+
+
+%% returns the leading attribute, the constraint of the components and
+%% the tablecinf value for the second component.
+instance_of_constraints(_,[]) ->
+ {false,[],[],[]};
+instance_of_constraints(S,#constraint{c={simpletable,Type}}) ->
+ #type{def=#'Externaltypereference'{type=Name}} = Type,
+ ModuleName = S#state.mname,
+ ObjectSetRef=#'Externaltypereference'{module=ModuleName,
+ type=Name},
+ CRel=[{componentrelation,{objectset,
+ undefined, %% pos
+ ObjectSetRef},
+ [{innermost,
+ [#'Externalvaluereference'{module=ModuleName,
+ value=type}]}]}],
+ TableCInf=#simpletableattributes{objectsetname=Name,
+ c_name='type-id',
+ c_index=1,
+ usedclassfield=id,
+ uniqueclassfield=id,
+ valueindex=[]},
+ {TableCInf,[{simpletable,Name}],CRel,[{objfun,ObjectSetRef}]}.
+
+%% Check ENUMERATED
+%% ****************************************
+%% Check that all values are unique
+%% assign values to un-numbered identifiers
+%% check that the constraints are allowed and correct
+%% put the updated info back into database
+check_enumerated(_S,[{Name,Number}|Rest],_Constr) when atom(Name), integer(Number)->
+ %% already checked , just return the same list
+ [{Name,Number}|Rest];
+check_enumerated(S,NamedNumberList,_Constr) ->
+ check_enum(S,NamedNumberList,[],[]).
+
+%% identifiers are put in Acc2
+%% returns either [{Name,Number}] or {[{Name,Number}],[{ExtName,ExtNumber}]}
+%% the latter is returned if the ENUMERATION contains EXTENSIONMARK
+check_enum(S,[{'NamedNumber',Id,Num}|T],Acc1,Acc2) when integer(Num) ->
+ check_enum(S,T,[{Id,Num}|Acc1],Acc2);
+check_enum(S,[{'NamedNumber',Id,{identifier,_,Name}}|T],Acc1,Acc2) ->
+ Val = dbget_ex(S,S#state.mname,Name),
+ check_enum(S,[{'NamedNumber',Id,Val#valuedef.value}|T],Acc1,Acc2);
+check_enum(S,['EXTENSIONMARK'|T],Acc1,Acc2) ->
+ NewAcc2 = lists:keysort(2,Acc1),
+ NewList = enum_number(lists:reverse(Acc2),NewAcc2,0,[]),
+ { NewList, check_enum(S,T,[],[])};
+check_enum(S,[Id|T],Acc1,Acc2) when atom(Id) ->
+ check_enum(S,T,Acc1,[Id|Acc2]);
+check_enum(_S,[],Acc1,Acc2) ->
+ NewAcc2 = lists:keysort(2,Acc1),
+ enum_number(lists:reverse(Acc2),NewAcc2,0,[]).
+
+
+% assign numbers to identifiers , numbers from 0 ... but must not
+% be the same as already assigned to NamedNumbers
+enum_number([H|T],[{Id,Num}|T2],Cnt,Acc) when Num > Cnt ->
+ enum_number(T,[{Id,Num}|T2],Cnt+1,[{H,Cnt}|Acc]);
+enum_number([H|T],[{Id,Num}|T2],Cnt,Acc) when Num < Cnt -> % negative Num
+ enum_number(T,T2,Cnt+1,[{H,Cnt},{Id,Num}|Acc]);
+enum_number([],L2,_Cnt,Acc) ->
+ lists:concat([lists:reverse(Acc),L2]);
+enum_number(L,[{Id,Num}|T2],Cnt,Acc) -> % Num == Cnt
+ enum_number(L,T2,Cnt+1,[{Id,Num}|Acc]);
+enum_number([H|T],[],Cnt,Acc) ->
+ enum_number(T,[],Cnt+1,[{H,Cnt}|Acc]).
+
+
+check_boolean(_S,_Constr) ->
+ ok.
+
+check_octetstring(_S,_Constr) ->
+ ok.
+
+% check all aspects of a SEQUENCE
+% - that all component names are unique
+% - that all TAGS are ok (when TAG default is applied)
+% - that each component is of a valid type
+% - that the extension marks are valid
+
+check_sequence(S,Type,Comps) ->
+ Components = expand_components(S,Comps),
+ case check_unique([C||C <- Components ,record(C,'ComponentType')]
+ ,#'ComponentType'.name) of
+ [] ->
+ %% sort_canonical(Components),
+ 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 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
+ end,
+ %% CRelInf is the "leading attribute" information
+ %% necessary for code generating of the look up in the
+ %% object set table,
+ %% i.e. getenc_ObjectSet/getdec_ObjectSet.
+ %% {objfun,ERef} tuple added in NewComps2 in tablecinf
+ %% field in type record of component relation constrained
+ %% type
+% io:format("NewComps: ~p~n",[NewComps]),
+ {CRelInf,NewComps2} = componentrelation_leadingattr(S,NewComps),
+% io:format("CRelInf: ~p~n",[CRelInf]),
+% io:format("NewComps2: ~p~n",[NewComps2]),
+ %% CompListWithTblInf has got a lot unecessary info about
+ %% the involved class removed, as the class of the object
+ %% set.
+ CompListWithTblInf = get_tableconstraint_info(S,Type,NewComps2),
+% io:format("CompListWithTblInf: ~p~n",[CompListWithTblInf]),
+ {CRelInf,CompListWithTblInf};
+ Dupl ->
+ throw({error,{asn1,{duplicate_components,Dupl}}})
+ end.
+
+expand_components(S, [{'COMPONENTS OF',Type}|T]) ->
+ CompList =
+ case get_referenced_type(S,Type#type.def) of
+ {_,#typedef{typespec=#type{def=Seq}}} when record(Seq,'SEQUENCE') ->
+ case Seq#'SEQUENCE'.components of
+ {Root,_Ext} -> Root;
+ Root -> Root
+ end;
+ Err -> throw({error,{asn1,{illegal_COMPONENTS_OF,Err}}})
+ end,
+ expand_components(S,CompList) ++ expand_components(S,T);
+expand_components(S,[H|T]) ->
+ [H|expand_components(S,T)];
+expand_components(_,[]) ->
+ [].
+
+check_unique_sequence_tags(S,[#'ComponentType'{prop=mandatory}|Rest]) ->
+ check_unique_sequence_tags(S,Rest);
+check_unique_sequence_tags(S,[C|Rest]) when record(C,'ComponentType') ->
+ 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,[]) ->
+ true.
+
+check_unique_sequence_tags1(S,[C|Rest],Acc) when record(C,'ComponentType') ->
+ case C#'ComponentType'.prop of
+ mandatory ->
+ check_unique_tags(S,lists:reverse([C|Acc])),
+ check_unique_sequence_tags(S,Rest);
+ _ ->
+ check_unique_sequence_tags1(S,Rest,[C|Acc]) % default or optional
+ end;
+check_unique_sequence_tags1(S,[H|Rest],Acc) ->
+ check_unique_sequence_tags1(S,Rest,[H|Acc]);
+check_unique_sequence_tags1(S,[],Acc) ->
+ check_unique_tags(S,lists:reverse(Acc)).
+
+check_sequenceof(S,Type,Component) when record(Component,type) ->
+ check_type(S,Type,Component).
+
+check_set(S,Type,Components) ->
+ {TableCInf,NewComponents} = check_sequence(S,Type,Components),
+ case lists:member(der,S#state.options) of
+ true when S#state.erule == ber;
+ S#state.erule == ber_bin ->
+ {Sorted,SortedComponents} =
+ sort_components(S#state.tname,
+ (S#state.module)#module.tagdefault,
+ NewComponents),
+ {Sorted,TableCInf,SortedComponents};
+ _ ->
+ {false,TableCInf,NewComponents}
+ end.
+
+sort_components(_TypeName,'AUTOMATIC',Components) ->
+ {true,Components};
+sort_components(TypeName,_TagDefault,Components) ->
+ case untagged_choice(Components) of
+ false ->
+ {true,sort_components1(TypeName,Components,[],[],[],[])};
+ true ->
+ {dynamic,Components} % sort in run-time
+ end.
+
+sort_components1(TypeName,[C=#'ComponentType'{tags=[{'UNIVERSAL',_}|_R]}|Cs],
+ UnivAcc,ApplAcc,ContAcc,PrivAcc) ->
+ sort_components1(TypeName,Cs,[C|UnivAcc],ApplAcc,ContAcc,PrivAcc);
+sort_components1(TypeName,[C=#'ComponentType'{tags=[{'APPLICATION',_}|_R]}|Cs],
+ UnivAcc,ApplAcc,ContAcc,PrivAcc) ->
+ sort_components1(TypeName,Cs,UnivAcc,[C|ApplAcc],ContAcc,PrivAcc);
+sort_components1(TypeName,[C=#'ComponentType'{tags=[{'CONTEXT',_}|_R]}|Cs],
+ UnivAcc,ApplAcc,ContAcc,PrivAcc) ->
+ sort_components1(TypeName,Cs,UnivAcc,ApplAcc,[C|ContAcc],PrivAcc);
+sort_components1(TypeName,[C=#'ComponentType'{tags=[{'PRIVATE',_}|_R]}|Cs],
+ UnivAcc,ApplAcc,ContAcc,PrivAcc) ->
+ sort_components1(TypeName,Cs,UnivAcc,ApplAcc,ContAcc,[C|PrivAcc]);
+sort_components1(TypeName,[],UnivAcc,ApplAcc,ContAcc,PrivAcc) ->
+ I = #'ComponentType'.tags,
+ ascending_order_check(TypeName,sort_universal_type(UnivAcc)) ++
+ ascending_order_check(TypeName,lists:keysort(I,ApplAcc)) ++
+ ascending_order_check(TypeName,lists:keysort(I,ContAcc)) ++
+ ascending_order_check(TypeName,lists:keysort(I,PrivAcc)).
+
+ascending_order_check(TypeName,Components) ->
+ ascending_order_check1(TypeName,Components),
+ Components.
+
+ascending_order_check1(TypeName,
+ [C1 = #'ComponentType'{tags=[{_,T}|_]},
+ C2 = #'ComponentType'{tags=[{_,T}|_]}|Rest]) ->
+ io:format("WARNING: Indistinct tag ~p in SET ~p, components ~p and ~p~n",
+ [T,TypeName,C1#'ComponentType'.name,C2#'ComponentType'.name]),
+ ascending_order_check1(TypeName,[C2|Rest]);
+ascending_order_check1(TypeName,
+ [C1 = #'ComponentType'{tags=[{'UNIVERSAL',T1}|_]},
+ C2 = #'ComponentType'{tags=[{'UNIVERSAL',T2}|_]}|Rest]) ->
+ case (asn1ct_gen_ber:decode_type(T1) == asn1ct_gen_ber:decode_type(T2)) of
+ true ->
+ io:format("WARNING: Indistinct tags ~p and ~p in"
+ " SET ~p, components ~p and ~p~n",
+ [T1,T2,TypeName,C1#'ComponentType'.name,
+ C2#'ComponentType'.name]),
+ ascending_order_check1(TypeName,[C2|Rest]);
+ _ ->
+ ascending_order_check1(TypeName,[C2|Rest])
+ end;
+ascending_order_check1(N,[_|Rest]) ->
+ ascending_order_check1(N,Rest);
+ascending_order_check1(_,[_]) ->
+ ok;
+ascending_order_check1(_,[]) ->
+ ok.
+
+sort_universal_type(Components) ->
+ List = lists:map(fun(C) ->
+ #'ComponentType'{tags=[{_,T}|_]} = C,
+ {asn1ct_gen_ber:decode_type(T),C}
+ end,
+ Components),
+ SortedList = lists:keysort(1,List),
+ lists:map(fun(X)->element(2,X) end,SortedList).
+
+untagged_choice([#'ComponentType'{typespec=#type{tag=[],def={'CHOICE',_}}}|_Rest]) ->
+ true;
+untagged_choice([_|Rest]) ->
+ untagged_choice(Rest);
+untagged_choice([]) ->
+ false.
+
+check_setof(S,Type,Component) when record(Component,type) ->
+ check_type(S,Type,Component).
+
+check_restrictedstring(_S,_Def,_Constr) ->
+ ok.
+
+check_objectidentifier(_S,_Constr) ->
+ ok.
+
+% check all aspects of a CHOICE
+% - that all alternative names are unique
+% - that all TAGS are ok (when TAG default is applied)
+% - that each alternative is of a valid type
+% - that the extension marks are valid
+check_choice(S,Type,Components) when list(Components) ->
+ case check_unique([C||C <- Components,
+ record(C,'ComponentType')],#'ComponentType'.name) of
+ [] ->
+ %% 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;
+%% CompListWithTblInf = get_tableconstraint_info(S,Type,NewComps);
+ Dupl ->
+ throw({error,{asn1,{duplicate_choice_alternatives,Dupl}}})
+ end;
+check_choice(_S,_,[]) ->
+ [].
+
+%% probably dead code that should be removed
+%%maybe_automatic_tags(S,{Rc,Ec}) ->
+%% {maybe_automatic_tags1(S,Rc,0),maybe_automatic_tags1(S,Ec,length(Rc))};
+maybe_automatic_tags(#state{erule=per},C) ->
+ C;
+maybe_automatic_tags(#state{erule=per_bin},C) ->
+ C;
+maybe_automatic_tags(S,C) ->
+ maybe_automatic_tags1(S,C,0).
+
+maybe_automatic_tags1(S,C,TagNo) ->
+ case (S#state.module)#module.tagdefault of
+ 'AUTOMATIC' ->
+ generate_automatic_tags(S,C,TagNo);
+ _ ->
+ %% maybe is the module a multi file module were only some of
+ %% the modules have defaulttag AUTOMATIC TAGS then the names
+ %% of those types are saved in the table automatic_tags
+ Name= S#state.tname,
+ case is_automatic_tagged_in_multi_file(Name) of
+ true ->
+ generate_automatic_tags(S,C,TagNo);
+ false ->
+ C
+ end
+ end.
+
+is_automatic_tagged_in_multi_file(Name) ->
+ case ets:info(automatic_tags) of
+ undefined ->
+ %% this case when not multifile compilation
+ false;
+ _ ->
+ case ets:member(automatic_tags,Name) of
+ true ->
+ true;
+ _ ->
+ false
+ end
+ end.
+
+generate_automatic_tags(_S,C,TagNo) ->
+ case any_manual_tag(C) of
+ true ->
+ C;
+ false ->
+ generate_automatic_tags1(C,TagNo)
+ end.
+
+generate_automatic_tags1([H|T],TagNo) when record(H,'ComponentType') ->
+ #'ComponentType'{typespec=Ts} = H,
+ NewTs = Ts#type{tag=[#tag{class='CONTEXT',
+ number=TagNo,
+ type={default,'IMPLICIT'},
+ form= 0 }]}, % PRIMITIVE
+ [H#'ComponentType'{typespec=NewTs}|generate_automatic_tags1(T,TagNo+1)];
+generate_automatic_tags1([ExtMark|T],TagNo) -> % EXTENSIONMARK
+ [ExtMark | generate_automatic_tags1(T,TagNo)];
+generate_automatic_tags1([],_) ->
+ [].
+
+any_manual_tag([#'ComponentType'{typespec=#type{tag=[]}}|Rest]) ->
+ any_manual_tag(Rest);
+any_manual_tag([{'EXTENSIONMARK',_,_}|Rest]) ->
+ any_manual_tag(Rest);
+any_manual_tag([_|_Rest]) ->
+ true;
+any_manual_tag([]) ->
+ false.
+
+
+check_unique_tags(S,C) ->
+ case (S#state.module)#module.tagdefault of
+ 'AUTOMATIC' ->
+ case any_manual_tag(C) of
+ false -> true;
+ _ -> collect_and_sort_tags(C,[])
+ end;
+ _ ->
+ collect_and_sort_tags(C,[])
+ end.
+
+collect_and_sort_tags([C|Rest],Acc) when record(C,'ComponentType') ->
+ collect_and_sort_tags(Rest,C#'ComponentType'.tags ++ Acc);
+collect_and_sort_tags([_|Rest],Acc) ->
+ collect_and_sort_tags(Rest,Acc);
+collect_and_sort_tags([],Acc) ->
+ {Dupl,_}= lists:mapfoldl(fun(El,El)->{{dup,El},El};(El,_Prev)-> {El,El} end,notag,lists:sort(Acc)),
+ Dupl2 = [Dup|| {dup,Dup} <- Dupl],
+ if
+ length(Dupl2) > 0 ->
+ throw({error,{asn1,{duplicates_of_the_tags,Dupl2}}});
+ true ->
+ true
+ end.
+
+check_unique(L,Pos) ->
+ Slist = lists:keysort(Pos,L),
+ check_unique2(Slist,Pos,[]).
+
+check_unique2([A,B|T],Pos,Acc) when element(Pos,A) == element(Pos,B) ->
+ check_unique2([B|T],Pos,[element(Pos,B)|Acc]);
+check_unique2([_|T],Pos,Acc) ->
+ check_unique2(T,Pos,Acc);
+check_unique2([],_,Acc) ->
+ lists:reverse(Acc).
+
+check_each_component(S,Type,{Rlist,ExtList}) ->
+ {check_each_component(S,Type,Rlist),
+ check_each_component(S,Type,ExtList)};
+check_each_component(S,Type,Components) ->
+ check_each_component(S,Type,Components,[],[],noext).
+
+check_each_component(S = #state{abscomppath=Path,recordtopname=TopName},Type,
+ [C|Ct],Acc,Extacc,Ext) when record(C,'ComponentType') ->
+ #'ComponentType'{name=Cname,typespec=Ts,prop=Prop} = C,
+ NewAbsCPath =
+ case Ts#type.def of
+ #'Externaltypereference'{} -> [];
+ _ -> [Cname|Path]
+ end,
+ CheckedTs = check_type(S#state{abscomppath=NewAbsCPath,
+ recordtopname=[Cname|TopName]},Type,Ts),
+ NewTags = get_taglist(S,CheckedTs),
+
+ NewProp =
+% case lists:member(der,S#state.options) of
+% true ->
+% True ->
+ case normalize_value(S,CheckedTs,Prop,[Cname|TopName]) of
+ mandatory -> mandatory;
+ 'OPTIONAL' -> 'OPTIONAL';
+ DefaultValue -> {'DEFAULT',DefaultValue}
+ end,
+% _ ->
+% Prop
+% end,
+ NewC = C#'ComponentType'{typespec=CheckedTs,prop=NewProp,tags=NewTags},
+ case Ext of
+ noext ->
+ check_each_component(S,Type,Ct,[NewC|Acc],Extacc,Ext);
+ ext ->
+ check_each_component(S,Type,Ct,Acc,[NewC|Extacc],Ext)
+ end;
+check_each_component(S,Type,[_|Ct],Acc,Extacc,noext) -> % skip 'EXTENSIONMARK'
+ check_each_component(S,Type,Ct,Acc,Extacc,ext);
+check_each_component(_S,_,[_C|_Ct],_,_,ext) -> % skip '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,_,[],Acc,_,noext) ->
+ lists:reverse(Acc).
+
+check_each_alternative(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_alternative(S=#state{abscomppath=Path,recordtopname=TopName},Type,[C|Ct],
+ Acc,Extacc,Ext) when record(C,'ComponentType') ->
+ #'ComponentType'{name=Cname,typespec=Ts,prop=_Prop} = C,
+ NewAbsCPath =
+ case Ts#type.def of
+ #'Externaltypereference'{} -> [];
+ _ -> [Cname|Path]
+ end,
+ NewState =
+ S#state{abscomppath=NewAbsCPath,recordtopname=[Cname|TopName]},
+ CheckedTs = check_type(NewState,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_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) ->
+ 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) ->
+% {Cs1,Cs2} =
+ Cs =
+ case CompList of
+ {Components,EComponents} when list(Components) ->
+% {Components,Components};
+ Components ++ EComponents;
+ CompList when list(CompList) ->
+% {CompList,CompList}
+ CompList
+ end,
+% case any_simple_table(S,Cs1,[]) of
+
+ %% get_simple_table_if_used/2 should find out whether there are any
+ %% component relation constraints in the entire tree of Cs1 that
+ %% relates to this level. It returns information about the simple
+ %% table constraint necessary for the the call to
+ %% 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
+ [] -> {false,CompList};
+ STList ->
+% componentrelation_leadingattr(S,Cs1,Cs2,STList,[],[])
+ componentrelation_leadingattr(S,Cs,Cs,STList,[],[])
+ end.
+
+%% 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
+%% field in the SEQUENCE/SET record. The "leading attribute"
+%% information is used to generate the lookup in the object set
+%% table. The other information gathered in the #type.tablecinf field
+%% 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) ->
+ {false,lists:reverse(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) ->
+ {LAAcc,NewC} =
+ case catch componentrelation1(S,C#'ComponentType'.typespec,
+ [C#'ComponentType'.name]) of
+ {'EXIT',_} ->
+ {[],C};
+ {CRI=[{_A1,_B1,_C1,_D1}|_Rest],NewTSpec} ->
+ %% {ObjectSet,AtPath,ClassDef,Path}
+ %% _A1 is a reference to the object set of the
+ %% component relation constraint.
+ %% _B1 is the path of names in the at-list of the
+ %% component relation constraint.
+ %% _C1 is the class definition of the
+ %% ObjectClassFieldType.
+ %% _D1 is the path of components that was traversed to
+ %% find this constraint.
+ case leading_attr_index(S,CompList,CRI,
+ lists:reverse(S#state.abscomppath),[]) of
+ [] ->
+ {[],C};
+ [{ObjSet,Attr,N,ClassDef,_Path,ValueIndex}|_NewRest] ->
+ OS = object_set_mod_name(S,ObjSet),
+ UniqueFieldName =
+ case (catch get_unique_fieldname(#classdef{typespec=ClassDef})) of
+ {error,'__undefined_'} ->
+ no_unique;
+ {asn1,Msg,_} ->
+ error({type,Msg,S});
+ Other -> Other
+ end,
+% UsedFieldName = get_used_fieldname(S,Attr,STList),
+ %% Res should be done differently: even though
+ %% a unique field name exists it is not
+ %% certain that the ObjectClassFieldType of
+ %% the simple table constraint picks that
+ %% class field.
+ Res = #simpletableattributes{objectsetname=OS,
+%% c_name=asn1ct_gen:un_hyphen_var(Attr),
+ c_name=Attr,
+ c_index=N,
+ usedclassfield=UniqueFieldName,
+ uniqueclassfield=UniqueFieldName,
+ valueindex=ValueIndex},
+ {[Res],C#'ComponentType'{typespec=NewTSpec}}
+ end;
+ _ ->
+ %% no constraint was found
+ {[],C}
+ end,
+ componentrelation_leadingattr(S,Cs,CompList,STList,LAAcc++Acc,
+ [NewC|CompAcc]).
+
+object_set_mod_name(_S,ObjSet) when atom(ObjSet) ->
+ ObjSet;
+object_set_mod_name(#state{mname=M},
+ #'Externaltypereference'{module=M,type=T}) ->
+ T;
+object_set_mod_name(S,#'Externaltypereference'{module=M,type=T}) ->
+ case lists:member(M,S#state.inputmodules) of
+ true ->
+ T;
+ false ->
+ {M,T}
+ end.
+
+%% get_used_fieldname gets the used field of the class referenced by
+%% the ObjectClassFieldType construct in the simple table constraint
+%% corresponding to the component relation constraint that depends on
+%% it.
+% get_used_fieldname(_S,CName,[{[CName|_Rest],_,ClFieldName}|_RestSimpleT]) ->
+% ClFieldName;
+% get_used_fieldname(S,CName,[_SimpleTC|Rest]) ->
+% get_used_fieldname(S,CName,Rest);
+% get_used_fieldname(S,_,[]) ->
+% error({type,"Error in Simple table constraint",S}).
+
+%% any_simple_table/3 checks if any of the components on this level is
+%% constrained by a simple table constraint. It returns a list of
+%% tuples with three elements. It is a name path to the place in the
+%% type structure where the constraint is, and the name of the object
+%% set and the referenced field in the class.
+% any_simple_table(S = #state{mname=M,abscomppath=Path},
+% [#'ComponentType'{name=Name,typespec=Type}|Cs],Acc) ->
+% Constraint = Type#type.constraint,
+% case lists:keysearch(simpletable,1,Constraint) of
+% {value,{_,#type{def=Ref}}} ->
+% %% This ObjectClassFieldType, which has a simple table
+% %% constraint, must pick a fixed type value, mustn't it ?
+% {ClassDef,[{_,ClassFieldName}]} = Type#type.def,
+% ST =
+% case Ref of
+% #'Externaltypereference'{module=M,type=ObjSetName} ->
+% {[Name|Path],ObjSetName,ClassFieldName};
+% _ ->
+% {[Name|Path],Ref,ClassFieldName}
+% end,
+% any_simple_table(S,Cs,[ST|Acc]);
+% false ->
+% any_simple_table(S,Cs,Acc)
+% end;
+% any_simple_table(_,[],Acc) ->
+% lists:reverse(Acc);
+% any_simple_table(S,[_|Cs],Acc) ->
+% any_simple_table(S,Cs,Acc).
+
+%% get_simple_table_if_used/2 searches the structure of Cs for any
+%% component relation constraints due to the present level of the
+%% structure. If there are any, the necessary information for code
+%% 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,[],[]),
+ get_simple_table_info(S,Cs,remove_doubles(RefedSimpleTable)).
+
+remove_doubles(L) ->
+ remove_doubles(L,[]).
+remove_doubles([H|T],Acc) ->
+ NewT = remove_doubles1(H,T),
+ remove_doubles(NewT,[H|Acc]);
+remove_doubles([],Acc) ->
+ Acc.
+
+remove_doubles1(El,L) ->
+ case lists:delete(El,L) of
+ L -> L;
+ NewL -> remove_doubles1(El,NewL)
+ end.
+
+%% get_simple_table_info searches the commponents Cs by the path from
+%% an at-list (third argument), and follows into a component of it if
+%% necessary, to get information needed for code generating.
+%%
+%% Returns a list of tuples with three elements. It holds a list of
+%% atoms that is the path, the name of the field of the class that are
+%% referred to in the ObjectClassFieldType, and the name of the unique
+%% field of the class of the ObjectClassFieldType.
+%%
+% %% The level information outermost/innermost must be kept. There are
+% %% at least two possibilities to cover here for an outermost case: 1)
+% %% Both the simple table and the component relation have a common path
+% %% at least one step below the outermost level, i.e. the leading
+% %% information shall be on a sub level. 2) They don't have any common
+% %% path.
+get_simple_table_info(S,Cs,[AtList|Rest]) ->
+%% [get_simple_table_info1(S,Cs,AtList,S#state.abscomppath)|get_simple_table_info(S,Cs,Rest)];
+ [get_simple_table_info1(S,Cs,AtList,[])|get_simple_table_info(S,Cs,Rest)];
+get_simple_table_info(_,_,[]) ->
+ [].
+get_simple_table_info1(S,Cs,[Cname|Cnames],Path) when list(Cs) ->
+ case lists:keysearch(Cname,#'ComponentType'.name,Cs) of
+ {value,C} ->
+ get_simple_table_info1(S,C,Cnames,[Cname|Path]);
+ _ ->
+ error({type,"Missing expected simple table constraint",S})
+ end;
+get_simple_table_info1(S,#'ComponentType'{typespec=TS},[],Path) ->
+ %% In this component there must be a simple table constraint
+ %% o.w. the asn1 code is wrong.
+ #type{def=OCFT,constraint=Cnstr} = TS,
+ case Cnstr of
+ [{simpletable,_OSRef}]�->
+ #'ObjectClassFieldType'{classname=ClRef,
+ class=ObjectClass,
+ fieldname=FieldName} = OCFT,
+% #'ObjectClassFieldType'{ObjectClass,FieldType} = ObjectClassFieldType,
+ ObjectClassFieldName =
+ case FieldName of
+ {LastFieldName,[]} -> LastFieldName;
+ {_FirstFieldName,FieldNames} ->
+ lists:last(FieldNames)
+ end,
+ %%ObjectClassFieldName is the last element in the dotted
+ %%list of the ObjectClassFieldType. The last element may
+ %%be of another class, that is referenced from the class
+ %%of the ObjectClassFieldType
+ ClassDef =
+ case ObjectClass of
+ [] ->
+ {_,CDef}=get_referenced_type(S,ClRef),
+ CDef;
+ _ -> #classdef{typespec=ObjectClass}
+ end,
+ UniqueName =
+ case (catch get_unique_fieldname(ClassDef)) of
+ {error,'__undefined_'} -> no_unique;
+ {asn1,Msg,_} ->
+ error({type,Msg,S});
+ Other -> Other
+ end,
+ {lists:reverse(Path),ObjectClassFieldName,UniqueName};
+ _ ->
+ error({type,{asn1,"missing expected simple table constraint",
+ Cnstr},S})
+ end;
+get_simple_table_info1(S,#'ComponentType'{typespec=TS},Cnames,Path) ->
+ Components = get_atlist_components(TS#type.def),
+ get_simple_table_info1(S,Components,Cnames,Path).
+
+%% any_component_relation searches for all component relation
+%% constraints that refers to the actual level and returns a list of
+%% the "name path" in the at-list to the component relation constraint
+%% that must refer to a simple table constraint. The list is empty if
+%% no component relation constraints were found.
+%%
+%% NamePath has the names of all components that are followed from the
+%% 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,
+ CRelPath =
+ case Type#type.constraint of
+ [{componentrelation,_,AtNotation}] ->
+ %% Found component relation constraint, now check
+ %% whether this constraint is relevant for the level
+ %% where the search started
+ AtNot = extract_at_notation(AtNotation),
+ %% evaluate_atpath returns the relative path to the
+ %% simple table constraint from where the component
+ %% relation is found.
+ evaluate_atpath(S#state.abscomppath,NamePath,CNames,AtNot);
+ _ ->
+ []
+ end,
+ InnerAcc =
+ 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,
+ %% here we are interested in components of an
+ %% SEQUENCE/SET OF as well as SEQUENCE, SET and CHOICE
+ any_component_relation(S,InnerCs,CNames,[CName|NamePath],[]);
+ _ ->
+ []
+ end,
+ any_component_relation(S,Cs,CNames,NamePath,InnerAcc++CRelPath++Acc);
+any_component_relation(_,[],_,_,Acc) ->
+ Acc.
+
+%% evaluate_atpath/4 finds out whether the at notation refers to the
+%% search level. The list of referenced names in the AtNot list shall
+%% begin with a name that exists on the level it refers to. If the
+%% found AtPath is refering to the same sub-branch as the simple table
+%% has, then there shall not be any leading attribute info on this
+%% level.
+evaluate_atpath(_,[],Cnames,{innermost,AtPath=[Ref|_Refs]}) ->
+ %% any innermost constraint found deeper in the structure is
+ %% ignored.
+ case lists:member(Ref,Cnames) of
+ true -> [AtPath];
+ false -> []
+ end;
+%% In this case must check that the AtPath doesn't step any step of
+%% the NamePath, in that case the constraint will be handled in an
+%% inner level.
+evaluate_atpath(TopPath,NamePath,Cnames,{outermost,AtPath=[_Ref|_Refs]}) ->
+ AtPathBelowTop =
+ case TopPath of
+ [] -> AtPath;
+ _ ->
+ case lists:prefix(TopPath,AtPath) of
+ true ->
+ lists:subtract(AtPath,TopPath);
+ _ -> []
+ end
+ end,
+ case {NamePath,AtPathBelowTop} of
+ {[H|_T1],[H|_T2]} -> []; % this must be handled in lower level
+ {_,[]} -> [];% this must be handled in an above level
+ {_,[H|_T]} ->
+ case lists:member(H,Cnames) of
+ true -> [AtPathBelowTop];
+ _ -> error({type,{asn1,"failed to analyze at-path",AtPath}})
+ end
+ end;
+evaluate_atpath(_,_,_,_) ->
+ [].
+
+%% Type may be any of SEQUENCE, SET, CHOICE, SEQUENCE OF, SET OF but
+%% only the three first have valid components.
+get_atlist_components(Def) ->
+ get_components(atlist,Def).
+
+get_components(Def) ->
+ get_components(any,Def).
+
+get_components(_,#'SEQUENCE'{components=Cs}) ->
+ Cs;
+get_components(_,#'SET'{components=Cs}) ->
+ Cs;
+get_components(_,{'CHOICE',Cs}) ->
+ Cs;
+get_components(any,{'SEQUENCE OF',#type{def=Def}}) ->
+ get_components(any,Def);
+get_components(any,{'SET OF',#type{def=Def}}) ->
+ get_components(any,Def);
+get_components(_,_) ->
+ [].
+
+
+extract_at_notation([{Level,[#'Externalvaluereference'{value=Name}|Rest]}]) ->
+ {Level,[Name|extract_at_notation1(Rest)]};
+extract_at_notation(At) ->
+ exit({error,{asn1,{at_notation,At}}}).
+extract_at_notation1([#'Externalvaluereference'{value=Name}|Rest]) ->
+ [Name|extract_at_notation1(Rest)];
+extract_at_notation1([]) ->
+ [].
+
+%% componentrelation1/1 identifies all componentrelation constraints
+%% that exist in C or in the substructure of C. Info about the found
+%% constraints are returned in a list. It is ObjectSet, the reference
+%% to the object set, AttrPath, the name atoms extracted from the
+%% at-list in the component relation constraint, ClassDef, the
+%% objectclass record of the class of the ObjectClassFieldType, Path,
+%% that is the component name "path" from the searched level to this
+%% constraint.
+%%
+%% The function is called with one component of the type in turn and
+%% with the component name in Path at the first call. When called from
+%% within, the name of the inner component is added to Path.
+componentrelation1(S,C = #type{def=Def,constraint=Constraint,tablecinf=TCI},
+ Path) ->
+ Ret =
+ case Constraint of
+ [{componentrelation,{_,_,ObjectSet},AtList}|_Rest] ->
+ [{_,AL=[#'Externalvaluereference'{}|_R1]}|_R2] = AtList,
+ %% Note: if Path is longer than one,i.e. it is within
+ %% an inner type of the actual level, then the only
+ %% relevant at-list is of "outermost" type.
+%% #'ObjectClassFieldType'{class=ClassDef} = Def,
+ ClassDef = get_ObjectClassFieldType_classdef(S,Def),
+ AtPath =
+ lists:map(fun(#'Externalvaluereference'{value=V})->V end,
+ AL),
+ {[{ObjectSet,AtPath,ClassDef,Path}],Def};
+ _Other ->
+ %% check the inner type of component
+ innertype_comprel(S,Def,Path)
+ end,
+ case Ret of
+ nofunobj ->
+ nofunobj; %% ignored by caller
+ {CRelI=[{ObjSet,_,_,_}],NewDef} -> %%
+ TCItmp = lists:subtract(TCI,[{objfun,ObjSet}]),
+ {CRelI,C#type{tablecinf=[{objfun,ObjSet}|TCItmp],def=NewDef}};
+ {CompRelInf,NewDef} -> %% more than one tuple in CompRelInf
+ TCItmp = lists:subtract(TCI,[{objfun,anyset}]),
+ {CompRelInf,C#type{tablecinf=[{objfun,anyset}|TCItmp],def=NewDef}}
+ end.
+
+innertype_comprel(S,{'SEQUENCE OF',Type},Path) ->
+ case innertype_comprel1(S,Type,Path) of
+ nofunobj ->
+ nofunobj;
+ {CompRelInf,NewType} ->
+ {CompRelInf,{'SEQUENCE OF',NewType}}
+ end;
+innertype_comprel(S,{'SET OF',Type},Path) ->
+ case innertype_comprel1(S,Type,Path) of
+ nofunobj ->
+ nofunobj;
+ {CompRelInf,NewType} ->
+ {CompRelInf,{'SET OF',NewType}}
+ end;
+innertype_comprel(S,{'CHOICE',CTypeList},Path) ->
+ case componentlist_comprel(S,CTypeList,[],Path,[]) of
+ nofunobj ->
+ nofunobj;
+ {CompRelInf,NewCs} ->
+ {CompRelInf,{'CHOICE',NewCs}}
+ end;
+innertype_comprel(S,Seq = #'SEQUENCE'{components=Cs},Path) ->
+ case componentlist_comprel(S,Cs,[],Path,[]) of
+ nofunobj ->
+ nofunobj;
+ {CompRelInf,NewCs} ->
+ {CompRelInf,Seq#'SEQUENCE'{components=NewCs}}
+ end;
+innertype_comprel(S,Set = #'SET'{components=Cs},Path) ->
+ case componentlist_comprel(S,Cs,[],Path,[]) of
+ nofunobj ->
+ nofunobj;
+ {CompRelInf,NewCs} ->
+ {CompRelInf,Set#'SET'{components=NewCs}}
+ end;
+innertype_comprel(_,_,_) ->
+ nofunobj.
+
+componentlist_comprel(S,[C = #'ComponentType'{name=Name,typespec=Type}|Cs],
+ Acc,Path,NewCL) ->
+ case catch componentrelation1(S,Type,Path++[Name]) of
+ {'EXIT',_} ->
+ componentlist_comprel(S,Cs,Acc,Path,[C|NewCL]);
+ nofunobj ->
+ componentlist_comprel(S,Cs,Acc,Path,[C|NewCL]);
+ {CRelInf,NewType} ->
+ componentlist_comprel(S,Cs,CRelInf++Acc,Path,
+ [C#'ComponentType'{typespec=NewType}|NewCL])
+ end;
+componentlist_comprel(_,[],Acc,_,NewCL) ->
+ case Acc of
+ [] ->
+ nofunobj;
+ _ ->
+ {Acc,lists:reverse(NewCL)}
+ end.
+
+innertype_comprel1(S,T = #type{def=Def,constraint=Cons,tablecinf=TCI},Path) ->
+ Ret =
+ case Cons of
+ [{componentrelation,{_,_,ObjectSet},AtList}|_Rest] ->
+ %% This AtList must have an "outermost" at sign to be
+ %% relevent here.
+ [{_,AL=[#'Externalvaluereference'{value=_Attr}|_R1]}|_R2]
+ = AtList,
+%% #'ObjectClassFieldType'{class=ClassDef} = Def,
+ ClassDef = get_ObjectClassFieldType_classdef(S,Def),
+ AtPath =
+ lists:map(fun(#'Externalvaluereference'{value=V})->V end,
+ AL),
+ [{ObjectSet,AtPath,ClassDef,Path}];
+ _ ->
+ innertype_comprel(S,Def,Path)
+ end,
+ case Ret of
+ nofunobj -> nofunobj;
+ L = [{ObjSet,_,_,_}] ->
+ TCItmp = lists:subtract(TCI,[{objfun,ObjSet}]),
+ {L,T#type{tablecinf=[{objfun,ObjSet}|TCItmp]}};
+ {CRelInf,NewDef} ->
+ TCItmp = lists:subtract(TCI,[{objfun,anyset}]),
+ {CRelInf,T#type{def=NewDef,tablecinf=[{objfun,anyset}|TCItmp]}}
+ end.
+
+
+%% leading_attr_index counts the index and picks the name of the
+%% component that is at the actual level in the at-list of the
+%% component relation constraint (AttrP). AbsP is the path of
+%% component names from the top type level to the actual level. AttrP
+%% is a list with the atoms from the at-list.
+leading_attr_index(S,Cs,[H={_,AttrP,_,_}|T],AbsP,Acc) ->
+ AttrInfo =
+ case lists:prefix(AbsP,AttrP) of
+ %% why this ?? It is necessary when in same situation as
+ %% TConstrChoice, there is an inner structure with an
+ %% outermost at-list and the "leading attribute" code gen
+ %% may be at a level some steps below the outermost level.
+ true ->
+ RelativAttrP = lists:subtract(AttrP,AbsP),
+ %% The header is used to calculate the index of the
+ %% component and to give the fun, received from the
+ %% object set look up, an unique name. The tail is
+ %% used to match the proper value input to the fun.
+ {hd(RelativAttrP),tl(RelativAttrP)};
+ false ->
+ {hd(AttrP),tl(AttrP)}
+ end,
+ case leading_attr_index1(S,Cs,H,AttrInfo,1) of
+ 0 ->
+ leading_attr_index(S,Cs,T,AbsP,Acc);
+ Res ->
+ leading_attr_index(S,Cs,T,AbsP,[Res|Acc])
+ end;
+leading_attr_index(_,_Cs,[],_,Acc) ->
+ lists:reverse(Acc).
+
+leading_attr_index1(_,[],_,_,_) ->
+ 0;
+leading_attr_index1(S,[C|Cs],Arg={ObjectSet,_,CDef,P},
+ AttrInfo={Attr,SubAttr},N) ->
+ case C#'ComponentType'.name of
+ Attr ->
+ ValueMatch = value_match(S,C,Attr,SubAttr),
+ {ObjectSet,Attr,N,CDef,P,ValueMatch};
+ _ ->
+ leading_attr_index1(S,Cs,Arg,AttrInfo,N+1)
+ end.
+
+%% value_math gathers information for a proper value match in the
+%% generated encode function. For a SEQUENCE or a SET the index of the
+%% component is counted. For a CHOICE the index is 2.
+value_match(S,C,Name,SubAttr) ->
+ value_match(S,C,Name,SubAttr,[]). % C has name Name
+value_match(_S,#'ComponentType'{},_Name,[],Acc) ->
+ Acc;% do not reverse, indexes in reverse order
+value_match(S,#'ComponentType'{typespec=Type},Name,[At|Ats],Acc) ->
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ Components =
+ case get_atlist_components(Type#type.def) of
+ [] -> error({type,{asn1,"element in at list must be a "
+ "SEQUENCE, SET or CHOICE.",Name},S});
+ Comps -> Comps
+ end,
+ {Index,ValueIndex} = component_value_index(S,InnerType,At,Components),
+ value_match(S,lists:nth(Index,Components),At,Ats,[ValueIndex|Acc]).
+
+component_value_index(S,'CHOICE',At,Components) ->
+ {component_index(S,At,Components),2};
+component_value_index(S,_,At,Components) ->
+ %% SEQUENCE or SET
+ Index = component_index(S,At,Components),
+ {Index,{Index+1,At}}.
+
+component_index(S,Name,Components) ->
+ component_index1(S,Name,Components,1).
+component_index1(_S,Name,[#'ComponentType'{name=Name}|_Cs],N) ->
+ N;
+component_index1(S,Name,[_C|Cs],N) ->
+ component_index1(S,Name,Cs,N+1);
+component_index1(S,Name,[],_) ->
+ error({type,{asn1,"component of at-list was not"
+ " found in substructure",Name},S}).
+
+get_unique_fieldname(ClassDef) ->
+%% {_,Fields,_} = ClassDef#classdef.typespec,
+ Fields = (ClassDef#classdef.typespec)#objectclass.fields,
+ get_unique_fieldname(Fields,[]).
+
+get_unique_fieldname([],[]) ->
+ throw({error,'__undefined_'});
+get_unique_fieldname([],[Name]) ->
+ Name;
+get_unique_fieldname([],Acc) ->
+ throw({asn1,'only one UNIQUE field is allowed in CLASS',Acc});
+get_unique_fieldname([{fixedtypevaluefield,Name,_,'UNIQUE',_}|Rest],Acc) ->
+ get_unique_fieldname(Rest,[Name|Acc]);
+get_unique_fieldname([_H|T],Acc) ->
+ get_unique_fieldname(T,Acc).
+
+get_tableconstraint_info(S,Type,{CheckedTs,EComps}) ->
+ {get_tableconstraint_info(S,Type,CheckedTs,[]),
+ get_tableconstraint_info(S,Type,EComps,[])};
+get_tableconstraint_info(S,Type,CheckedTs) ->
+ 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,
+ AccComp =
+ case CheckedTs#type.def of
+ %% ObjectClassFieldType
+ OCFT=#'ObjectClassFieldType'{class=#objectclass{},
+ type=_AType} ->
+% AType = get_ObjectClassFieldType(S,Fields,FieldRef),
+% RefedFieldName =
+% get_referencedclassfield(CheckedTs#type.def),%is probably obsolete
+ NewOCFT =
+ OCFT#'ObjectClassFieldType'{class=[]},
+ C#'ComponentType'{typespec=
+ CheckedTs#type{
+% def=AType,
+ def=NewOCFT
+ }};
+% constraint=[{tableconstraint_info,
+% FieldRef}]}};
+ {'SEQUENCE OF',SOType} when record(SOType,type),
+ (element(1,SOType#type.def)=='CHOICE') ->
+ CTypeList = element(2,SOType#type.def),
+ NewInnerCList =
+ get_tableconstraint_info(S,Type,CTypeList,[]),
+ C#'ComponentType'{typespec=
+ CheckedTs#type{
+ def={'SEQUENCE OF',
+ SOType#type{def={'CHOICE',
+ NewInnerCList}}}}};
+ {'SET OF',SOType} when record(SOType,type),
+ (element(1,SOType#type.def)=='CHOICE') ->
+ CTypeList = element(2,SOType#type.def),
+ NewInnerCList =
+ get_tableconstraint_info(S,Type,CTypeList,[]),
+ C#'ComponentType'{typespec=
+ CheckedTs#type{
+ def={'SET OF',
+ SOType#type{def={'CHOICE',
+ NewInnerCList}}}}};
+ _ ->
+ C
+ end,
+ get_tableconstraint_info(S,Type,Cs,[AccComp|Acc]).
+
+get_referenced_fieldname([{_,FirstFieldname}]) ->
+ {FirstFieldname,[]};
+get_referenced_fieldname([{_,FirstFieldname}|Rest]) ->
+ {FirstFieldname,lists:map(fun(X)->element(2,X) end,Rest)};
+get_referenced_fieldname(Def) ->
+ {no_type,Def}.
+
+%% get_ObjectClassFieldType extracts the type from the chain of
+%% objects that leads to a final type.
+get_ObjectClassFieldType(S,ERef,PrimFieldNameList) when
+ record(ERef,'Externaltypereference') ->
+ {_,Type} = get_referenced_type(S,ERef),
+ ClassSpec = check_class(S,Type),
+ Fields = ClassSpec#objectclass.fields,
+ get_ObjectClassFieldType(S,Fields,PrimFieldNameList);
+get_ObjectClassFieldType(S,Fields,L=[_PrimFieldName1|_Rest]) ->
+ check_PrimitiveFieldNames(S,Fields,L),
+ get_OCFType(S,Fields,L).
+
+check_PrimitiveFieldNames(_S,_Fields,_) ->
+ ok.
+
+%% get_ObjectClassFieldType_classdef gets the def of the class of the
+%% ObjectClassFieldType, i.e. the objectclass record. If the type has
+%% been checked (it may be a field type of an internal SEQUENCE) the
+%% class field = [], then the classdef has to be fetched by help of
+%% the class reference in the classname field.
+get_ObjectClassFieldType_classdef(S,#'ObjectClassFieldType'{classname=Name,
+ class=[]}) ->
+ {_,#classdef{typespec=TS}} = get_referenced_type(S,Name),
+ TS;
+get_ObjectClassFieldType_classdef(_,#'ObjectClassFieldType'{class=Cl}) ->
+ Cl.
+
+get_OCFType(S,Fields,[{_FieldType,PrimFieldName}|Rest]) ->
+ case lists:keysearch(PrimFieldName,2,Fields) of
+ {value,{fixedtypevaluefield,_,Type,_Unique,_OptSpec}} ->
+ {fixedtypevaluefield,PrimFieldName,Type};
+ {value,{objectfield,_,Type,_Unique,_OptSpec}} ->
+ {_,ClassDef} = get_referenced_type(S,Type#type.def),
+ CheckedCDef = check_class(S#state{type=ClassDef,
+ tname=ClassDef#classdef.name},
+ ClassDef#classdef.typespec),
+ get_OCFType(S,CheckedCDef#objectclass.fields,Rest);
+ {value,{objectsetfield,_,Type,_OptSpec}} ->
+ {_,ClassDef} = get_referenced_type(S,Type#type.def),
+ CheckedCDef = check_class(S#state{type=ClassDef,
+ tname=ClassDef#classdef.name},
+ ClassDef#classdef.typespec),
+ get_OCFType(S,CheckedCDef#objectclass.fields,Rest);
+
+ {value,Other} ->
+ {element(1,Other),PrimFieldName};
+ _ ->
+ error({type,"undefined FieldName in ObjectClassFieldType",S})
+ end.
+
+get_taglist(#state{erule=per},_) ->
+ [];
+get_taglist(#state{erule=per_bin},_) ->
+ [];
+get_taglist(S,Ext) when record(Ext,'Externaltypereference') ->
+ {_,T} = get_referenced_type(S,Ext),
+ get_taglist(S,T#typedef.typespec);
+get_taglist(S,Tref) when record(Tref,typereference) ->
+ {_,T} = get_referenced_type(S,Tref),
+ get_taglist(S,T#typedef.typespec);
+get_taglist(S,Type) when record(Type,type) ->
+ case Type#type.tag of
+ [] ->
+ get_taglist(S,Type#type.def);
+ [Tag|_] ->
+% case lists:member(S#state.erule,[ber,ber_bin]) of
+% true ->
+% lists:map(fun(Tx) -> asn1ct_gen:def_to_tag(Tx) end,Type#type.tag);
+% _ ->
+ [asn1ct_gen:def_to_tag(Tag)]
+% end
+ end;
+get_taglist(S,{'CHOICE',{Rc,Ec}}) ->
+ get_taglist(S,{'CHOICE',Rc ++ Ec});
+get_taglist(S,{'CHOICE',Components}) ->
+ get_taglist1(S,Components);
+%% ObjectClassFieldType OTP-4390
+get_taglist(_S,#'ObjectClassFieldType'{type={typefield,_}}) ->
+ [];
+get_taglist(S,#'ObjectClassFieldType'{type={fixedtypevaluefield,_,Type}}) ->
+ get_taglist(S,Type);
+get_taglist(S,{ERef=#'Externaltypereference'{},FieldNameList})
+ when list(FieldNameList) ->
+ case get_ObjectClassFieldType(S,ERef,FieldNameList) of
+ Type when record(Type,type) ->
+ get_taglist(S,Type);
+ {fixedtypevaluefield,_,Type} -> get_taglist(S,Type);
+ {TypeFieldName,_} when atom(TypeFieldName) -> []%should check if allowed
+ end;
+get_taglist(S,{ObjCl,FieldNameList}) when record(ObjCl,objectclass),
+ list(FieldNameList) ->
+ case get_ObjectClassFieldType(S,ObjCl#objectclass.fields,FieldNameList) of
+ Type when record(Type,type) ->
+ get_taglist(S,Type);
+ {fixedtypevaluefield,_,Type} -> get_taglist(S,Type);
+ {TypeFieldName,_} when atom(TypeFieldName) -> []%should check if allowed
+ end;
+get_taglist(S,Def) ->
+ case lists:member(S#state.erule,[ber_bin_v2]) of
+ false ->
+ case Def of
+ 'ASN1_OPEN_TYPE' -> % open_type has no UNIVERSAL tag as such
+ [];
+ _ ->
+ [asn1ct_gen:def_to_tag(Def)]
+ end;
+ _ ->
+ []
+ end.
+
+get_taglist1(S,[#'ComponentType'{name=_Cname,tags=TagL}|Rest]) when list(TagL) ->
+ %% tag_list has been here , just return TagL and continue with next alternative
+ TagL ++ get_taglist1(S,Rest);
+get_taglist1(S,[#'ComponentType'{typespec=Ts,tags=undefined}|Rest]) ->
+ get_taglist(S,Ts) ++ get_taglist1(S,Rest);
+get_taglist1(S,[_H|Rest]) -> % skip EXTENSIONMARK
+ get_taglist1(S,Rest);
+get_taglist1(_S,[]) ->
+ [].
+
+dbget_ex(_S,Module,Key) ->
+ case asn1_db:dbget(Module,Key) of
+ undefined ->
+
+ throw({error,{asn1,{undefined,{Module,Key}}}}); % this is catched on toplevel type or value
+ T -> T
+ end.
+
+merge_tags(T1, T2) when list(T2) ->
+ merge_tags2(T1 ++ T2, []);
+merge_tags(T1, T2) ->
+ merge_tags2(T1 ++ [T2], []).
+
+merge_tags2([T1= #tag{type='IMPLICIT'}, T2 |Rest], Acc) ->
+ merge_tags2([T1#tag{type=T2#tag.type, form=T2#tag.form}|Rest],Acc);
+merge_tags2([T1= #tag{type={default,'IMPLICIT'}}, T2 |Rest], Acc) ->
+ merge_tags2([T1#tag{type=T2#tag.type, form=T2#tag.form}|Rest],Acc);
+merge_tags2([H|T],Acc) ->
+ merge_tags2(T, [H|Acc]);
+merge_tags2([], Acc) ->
+ lists:reverse(Acc).
+
+merge_constraints(C1, []) ->
+ C1;
+merge_constraints([], C2) ->
+ C2;
+merge_constraints(C1, C2) ->
+ {SList,VList,PAList,Rest} = splitlist(C1++C2,[],[],[],[]),
+ SizeC = merge_constraints(SList),
+ ValueC = merge_constraints(VList),
+ PermAlphaC = merge_constraints(PAList),
+ case Rest of
+ [] ->
+ SizeC ++ ValueC ++ PermAlphaC;
+ _ ->
+ throw({error,{asn1,{not_implemented,{merge_constraints,Rest}}}})
+ end.
+
+merge_constraints([]) -> [];
+merge_constraints([C1 = {_,{Low1,High1}},{_,{Low2,High2}}|Rest]) when Low1 >= Low2,
+ High1 =< High2 ->
+ merge_constraints([C1|Rest]);
+merge_constraints([C1={'PermittedAlphabet',_},C2|Rest]) ->
+ [C1|merge_constraints([C2|Rest])];
+merge_constraints([C1 = {_,{_Low1,_High1}},C2 = {_,{_Low2,_High2}}|_Rest]) ->
+ throw({error,asn1,{conflicting_constraints,{C1,C2}}});
+merge_constraints([C]) ->
+ [C].
+
+splitlist([C={'SizeConstraint',_}|Rest],Sacc,Vacc,PAacc,Restacc) ->
+ splitlist(Rest,[C|Sacc],Vacc,PAacc,Restacc);
+splitlist([C={'ValueRange',_}|Rest],Sacc,Vacc,PAacc,Restacc) ->
+ splitlist(Rest,Sacc,[C|Vacc],PAacc,Restacc);
+splitlist([C={'PermittedAlphabet',_}|Rest],Sacc,Vacc,PAacc,Restacc) ->
+ splitlist(Rest,Sacc,Vacc,[C|PAacc],Restacc);
+splitlist([C|Rest],Sacc,Vacc,PAacc,Restacc) ->
+ splitlist(Rest,Sacc,Vacc,PAacc,[C|Restacc]);
+splitlist([],Sacc,Vacc,PAacc,Restacc) ->
+ {lists:reverse(Sacc),
+ lists:reverse(Vacc),
+ lists:reverse(PAacc),
+ lists:reverse(Restacc)}.
+
+
+
+storeindb(M) when record(M,module) ->
+ TVlist = M#module.typeorval,
+ NewM = M#module{typeorval=findtypes_and_values(TVlist)},
+ asn1_db:dbnew(NewM#module.name),
+ asn1_db:dbput(NewM#module.name,'MODULE', NewM),
+ Res = storeindb(NewM#module.name,TVlist,[]),
+ include_default_class(NewM#module.name),
+ include_default_type(NewM#module.name),
+ Res.
+
+storeindb(Module,[H|T],ErrAcc) when record(H,typedef) ->
+ storeindb(Module,H#typedef.name,H,T,ErrAcc);
+storeindb(Module,[H|T],ErrAcc) when record(H,valuedef) ->
+ storeindb(Module,H#valuedef.name,H,T,ErrAcc);
+storeindb(Module,[H|T],ErrAcc) when record(H,ptypedef) ->
+ storeindb(Module,H#ptypedef.name,H,T,ErrAcc);
+storeindb(Module,[H|T],ErrAcc) when record(H,classdef) ->
+ storeindb(Module,H#classdef.name,H,T,ErrAcc);
+storeindb(Module,[H|T],ErrAcc) when record(H,pvaluesetdef) ->
+ storeindb(Module,H#pvaluesetdef.name,H,T,ErrAcc);
+storeindb(Module,[H|T],ErrAcc) when record(H,pobjectdef) ->
+ storeindb(Module,H#pobjectdef.name,H,T,ErrAcc);
+storeindb(Module,[H|T],ErrAcc) when record(H,pvaluedef) ->
+ storeindb(Module,H#pvaluedef.name,H,T,ErrAcc);
+storeindb(_,[],[]) -> ok;
+storeindb(_,[],ErrAcc) ->
+ {error,ErrAcc}.
+
+storeindb(Module,Name,H,T,ErrAcc) ->
+ case asn1_db:dbget(Module,Name) of
+ undefined ->
+ asn1_db:dbput(Module,Name,H),
+ storeindb(Module,T,ErrAcc);
+ _ ->
+ case H of
+ _Type when record(H,typedef) ->
+ error({type,"already defined",
+ #state{mname=Module,type=H,tname=Name}});
+ _Type when record(H,valuedef) ->
+ error({value,"already defined",
+ #state{mname=Module,value=H,vname=Name}});
+ _Type when record(H,ptypedef) ->
+ error({ptype,"already defined",
+ #state{mname=Module,type=H,tname=Name}});
+ _Type when record(H,pobjectdef) ->
+ error({ptype,"already defined",
+ #state{mname=Module,type=H,tname=Name}});
+ _Type when record(H,pvaluesetdef) ->
+ error({ptype,"already defined",
+ #state{mname=Module,type=H,tname=Name}});
+ _Type when record(H,pvaluedef) ->
+ error({ptype,"already defined",
+ #state{mname=Module,type=H,tname=Name}});
+ _Type when record(H,classdef) ->
+ error({class,"already defined",
+ #state{mname=Module,value=H,vname=Name}})
+ end,
+ storeindb(Module,T,[H|ErrAcc])
+ end.
+
+findtypes_and_values(TVList) ->
+ findtypes_and_values(TVList,[],[],[],[],[],[]).%% Types,Values,
+%% Parameterizedtypes,Classes,Objects and ObjectSets
+
+findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
+ when record(H,typedef),record(H#typedef.typespec,'Object') ->
+ findtypes_and_values(T,Tacc,Vacc,Pacc,Cacc,[H#typedef.name|Oacc],OSacc);
+findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
+ when record(H,typedef),record(H#typedef.typespec,'ObjectSet') ->
+ findtypes_and_values(T,Tacc,Vacc,Pacc,Cacc,Oacc,[H#typedef.name|OSacc]);
+findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
+ when record(H,typedef) ->
+ findtypes_and_values(T,[H#typedef.name|Tacc],Vacc,Pacc,Cacc,Oacc,OSacc);
+findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
+ when record(H,valuedef) ->
+ findtypes_and_values(T,Tacc,[H#valuedef.name|Vacc],Pacc,Cacc,Oacc,OSacc);
+findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
+ when record(H,ptypedef) ->
+ findtypes_and_values(T,Tacc,Vacc,[H#ptypedef.name|Pacc],Cacc,Oacc,OSacc);
+findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
+ when record(H,classdef) ->
+ findtypes_and_values(T,Tacc,Vacc,Pacc,[H#classdef.name|Cacc],Oacc,OSacc);
+findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
+ when record(H,pvaluedef) ->
+ findtypes_and_values(T,Tacc,[H#pvaluedef.name|Vacc],Pacc,Cacc,Oacc,OSacc);
+findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
+ when record(H,pvaluesetdef) ->
+ findtypes_and_values(T,Tacc,[H#pvaluesetdef.name|Vacc],Pacc,Cacc,Oacc,OSacc);
+findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
+ when record(H,pobjectdef) ->
+ findtypes_and_values(T,Tacc,Vacc,Pacc,Cacc,[H#pobjectdef.name|Oacc],OSacc);
+findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
+ when record(H,pobjectsetdef) ->
+ findtypes_and_values(T,Tacc,Vacc,Pacc,Cacc,Oacc,[H#pobjectsetdef.name|OSacc]);
+findtypes_and_values([],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc) ->
+ {lists:reverse(Tacc),lists:reverse(Vacc),lists:reverse(Pacc),
+ lists:reverse(Cacc),lists:reverse(Oacc),lists:reverse(OSacc)}.
+
+
+
+error({export,Msg,#state{mname=Mname,type=Ref,tname=Typename}}) ->
+ Pos = Ref#'Externaltypereference'.pos,
+ io:format("asn1error:~p:~p:~p ~p~n",[Pos,Mname,Typename,Msg]),
+ {error,{export,Pos,Mname,Typename,Msg}};
+error({type,Msg,#state{mname=Mname,type=Type,tname=Typename}})
+ when record(Type,typedef) ->
+ io:format("asn1error:~p:~p:~p ~p~n",
+ [Type#typedef.pos,Mname,Typename,Msg]),
+ {error,{type,Type#typedef.pos,Mname,Typename,Msg}};
+error({type,Msg,#state{mname=Mname,type=Type,tname=Typename}})
+ when record(Type,ptypedef) ->
+ io:format("asn1error:~p:~p:~p ~p~n",
+ [Type#ptypedef.pos,Mname,Typename,Msg]),
+ {error,{type,Type#ptypedef.pos,Mname,Typename,Msg}};
+error({type,Msg,#state{mname=Mname,value=Value,vname=Valuename}})
+ when record(Value,valuedef) ->
+ io:format("asn1error:~p:~p:~p ~p~n",[Value#valuedef.pos,Mname,Valuename,Msg]),
+ {error,{type,Value#valuedef.pos,Mname,Valuename,Msg}};
+error({type,Msg,#state{mname=Mname,type=Type,tname=Typename}})
+ when record(Type,pobjectdef) ->
+ io:format("asn1error:~p:~p:~p ~p~n",
+ [Type#pobjectdef.pos,Mname,Typename,Msg]),
+ {error,{type,Type#pobjectdef.pos,Mname,Typename,Msg}};
+error({value,Msg,#state{mname=Mname,value=Value,vname=Valuename}}) ->
+ io:format("asn1error:~p:~p:~p ~p~n",[Value#valuedef.pos,Mname,Valuename,Msg]),
+ {error,{value,Value#valuedef.pos,Mname,Valuename,Msg}};
+error({Other,Msg,#state{mname=Mname,value=#valuedef{pos=Pos},vname=Valuename}}) ->
+ io:format("asn1error:~p:~p:~p ~p~n",[Pos,Mname,Valuename,Msg]),
+ {error,{Other,Pos,Mname,Valuename,Msg}};
+error({Other,Msg,#state{mname=Mname,type=#typedef{pos=Pos},tname=Typename}}) ->
+ io:format("asn1error:~p:~p:~p ~p~n",[Pos,Mname,Typename,Msg]),
+ {error,{Other,Pos,Mname,Typename,Msg}};
+error({Other,Msg,#state{mname=Mname,type=#classdef{pos=Pos},tname=Typename}}) ->
+ io:format("asn1error:~p:~p:~p ~p~n",[Pos,Mname,Typename,Msg]),
+ {error,{Other,Pos,Mname,Typename,Msg}}.
+
+include_default_type(Module) ->
+ NameAbsList = default_type_list(),
+ include_default_type1(Module,NameAbsList).
+
+include_default_type1(_,[]) ->
+ ok;
+include_default_type1(Module,[{Name,TS}|Rest]) ->
+ case asn1_db:dbget(Module,Name) of
+ undefined ->
+ T = #typedef{name=Name,
+ typespec=TS},
+ asn1_db:dbput(Module,Name,T);
+ _ -> ok
+ end,
+ include_default_type1(Module,Rest).
+
+default_type_list() ->
+ %% The EXTERNAL type is represented, according to ASN.1 1997,
+ %% as a SEQUENCE with components: identification, data-value-descriptor
+ %% and data-value.
+ Syntax =
+ #'ComponentType'{name=syntax,
+ typespec=#type{def='OBJECT IDENTIFIER'},
+ prop=mandatory},
+ Presentation_Cid =
+ #'ComponentType'{name='presentation-context-id',
+ typespec=#type{def='INTEGER'},
+ prop=mandatory},
+ Transfer_syntax =
+ #'ComponentType'{name='transfer-syntax',
+ typespec=#type{def='OBJECT IDENTIFIER'},
+ prop=mandatory},
+ Negotiation_items =
+ #type{def=
+ #'SEQUENCE'{components=
+ [Presentation_Cid,
+ Transfer_syntax#'ComponentType'{prop=mandatory}]}},
+ Context_negot =
+ #'ComponentType'{name='context-negotiation',
+ typespec=Negotiation_items,
+ prop=mandatory},
+
+ Data_value_descriptor =
+ #'ComponentType'{name='data-value-descriptor',
+ typespec=#type{def='ObjectDescriptor'},
+ prop='OPTIONAL'},
+ Data_value =
+ #'ComponentType'{name='data-value',
+ typespec=#type{def='OCTET STRING'},
+ prop=mandatory},
+
+ %% The EXTERNAL type is represented, according to ASN.1 1990,
+ %% as a SEQUENCE with components: direct-reference, indirect-reference,
+ %% data-value-descriptor and encoding.
+
+ Direct_reference =
+ #'ComponentType'{name='direct-reference',
+ typespec=#type{def='OBJECT IDENTIFIER'},
+ prop='OPTIONAL'},
+
+ Indirect_reference =
+ #'ComponentType'{name='indirect-reference',
+ typespec=#type{def='INTEGER'},
+ prop='OPTIONAL'},
+
+ Single_ASN1_type =
+ #'ComponentType'{name='single-ASN1-type',
+ typespec=#type{tag=[{tag,'CONTEXT',0,
+ 'EXPLICIT',32}],
+ def='ANY'},
+ prop=mandatory},
+
+ Octet_aligned =
+ #'ComponentType'{name='octet-aligned',
+ typespec=#type{tag=[{tag,'CONTEXT',1,
+ 'IMPLICIT',32}],
+ def='OCTET STRING'},
+ prop=mandatory},
+
+ Arbitrary =
+ #'ComponentType'{name=arbitrary,
+ typespec=#type{tag=[{tag,'CONTEXT',2,
+ 'IMPLICIT',32}],
+ def={'BIT STRING',[]}},
+ prop=mandatory},
+
+ Encoding =
+ #'ComponentType'{name=encoding,
+ typespec=#type{def={'CHOICE',
+ [Single_ASN1_type,Octet_aligned,
+ Arbitrary]}},
+ prop=mandatory},
+
+ EXTERNAL_components1990 =
+ [Direct_reference,Indirect_reference,Data_value_descriptor,Encoding],
+
+ %% The EMBEDDED PDV type is represented by a SEQUENCE type
+ %% with components: identification and data-value
+ Abstract =
+ #'ComponentType'{name=abstract,
+ typespec=#type{def='OBJECT IDENTIFIER'},
+ prop=mandatory},
+ Transfer =
+ #'ComponentType'{name=transfer,
+ typespec=#type{def='OBJECT IDENTIFIER'},
+ prop=mandatory},
+ AbstractTrSeq =
+ #'SEQUENCE'{components=[Abstract,Transfer]},
+ Syntaxes =
+ #'ComponentType'{name=syntaxes,
+ typespec=#type{def=AbstractTrSeq},
+ prop=mandatory},
+ Fixed = #'ComponentType'{name=fixed,
+ typespec=#type{def='NULL'},
+ prop=mandatory},
+ Negotiations =
+ [Syntaxes,Syntax,Presentation_Cid,Context_negot,
+ Transfer_syntax,Fixed],
+ Identification2 =
+ #'ComponentType'{name=identification,
+ typespec=#type{def={'CHOICE',Negotiations}},
+ prop=mandatory},
+ EmbeddedPdv_components =
+ [Identification2,Data_value],
+
+ %% The CHARACTER STRING type is represented by a SEQUENCE type
+ %% with components: identification and string-value
+ String_value =
+ #'ComponentType'{name='string-value',
+ typespec=#type{def='OCTET STRING'},
+ prop=mandatory},
+ CharacterString_components =
+ [Identification2,String_value],
+
+ [{'EXTERNAL',
+ #type{tag=[#tag{class='UNIVERSAL',
+ number=8,
+ type='IMPLICIT',
+ form=32}],
+ def=#'SEQUENCE'{components=
+ EXTERNAL_components1990}}},
+ {'EMBEDDED PDV',
+ #type{tag=[#tag{class='UNIVERSAL',
+ number=11,
+ type='IMPLICIT',
+ form=32}],
+ def=#'SEQUENCE'{components=EmbeddedPdv_components}}},
+ {'CHARACTER STRING',
+ #type{tag=[#tag{class='UNIVERSAL',
+ number=29,
+ type='IMPLICIT',
+ form=32}],
+ def=#'SEQUENCE'{components=CharacterString_components}}}
+ ].
+
+
+include_default_class(Module) ->
+ NameAbsList = default_class_list(),
+ include_default_class1(Module,NameAbsList).
+
+include_default_class1(_,[]) ->
+ ok;
+include_default_class1(Module,[{Name,TS}|_Rest]) ->
+ case asn1_db:dbget(Module,Name) of
+ undefined ->
+ C = #classdef{checked=true,name=Name,
+ typespec=TS},
+ asn1_db:dbput(Module,Name,C);
+ _ -> ok
+ end.
+
+default_class_list() ->
+ [{'TYPE-IDENTIFIER',
+ {objectclass,
+ [{fixedtypevaluefield,
+ id,
+ {type,[],'OBJECT IDENTIFIER',[]},
+ 'UNIQUE',
+ 'MANDATORY'},
+ {typefield,'Type','MANDATORY'}],
+ {'WITH SYNTAX',
+ [{typefieldreference,'Type'},
+ 'IDENTIFIED',
+ 'BY',
+ {valuefieldreference,id}]}}},
+ {'ABSTRACT-SYNTAX',
+ {objectclass,
+ [{fixedtypevaluefield,
+ id,
+ {type,[],'OBJECT IDENTIFIER',[]},
+ 'UNIQUE',
+ 'MANDATORY'},
+ {typefield,'Type','MANDATORY'},
+ {fixedtypevaluefield,
+ property,
+ {type,
+ [],
+ {'BIT STRING',[]},
+ []},
+ undefined,
+ {'DEFAULT',
+ [0,1,0]}}],
+ {'WITH SYNTAX',
+ [{typefieldreference,'Type'},
+ 'IDENTIFIED',
+ 'BY',
+ {valuefieldreference,id},
+ ['HAS',
+ 'PROPERTY',
+ {valuefieldreference,property}]]}}}].
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_constructed_ber.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_constructed_ber.erl
new file mode 100644
index 0000000000..695f648924
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_constructed_ber.erl
@@ -0,0 +1,1468 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1ct_constructed_ber.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
+%%
+-module(asn1ct_constructed_ber).
+
+-export([gen_encode_sequence/3]).
+-export([gen_decode_sequence/3]).
+-export([gen_encode_set/3]).
+-export([gen_decode_set/3]).
+-export([gen_encode_sof/4]).
+-export([gen_decode_sof/4]).
+-export([gen_encode_choice/3]).
+-export([gen_decode_choice/3]).
+
+%%%% Application internal exports
+-export([match_tag/2]).
+
+-include("asn1_records.hrl").
+
+-import(asn1ct_gen, [emit/1,demit/1]).
+
+% the encoding of class of tag bits 8 and 7
+-define(UNIVERSAL, 0).
+-define(APPLICATION, 16#40).
+-define(CONTEXT, 16#80).
+-define(PRIVATE, 16#C0).
+
+% primitive or constructed encoding % bit 6
+-define(PRIMITIVE, 0).
+-define(CONSTRUCTED, 2#00100000).
+
+
+
+
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+%% Encode/decode SEQUENCE
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+
+gen_encode_sequence(Erules,Typename,D) when record(D,type) ->
+ asn1ct_name:start(),
+ asn1ct_name:new(term),
+ asn1ct_name:new(bytes),
+
+ %% if EXTERNAL type the input value must be transformed to
+ %% ASN1 1990 format
+ case Typename of
+ ['EXTERNAL'] ->
+ emit([" NewVal = asn1rt_check:transform_to_EXTERNAL1990(Val),",
+ nl]);
+ _ ->
+ ok
+ end,
+
+ {SeqOrSet,TableConsInfo,CompList} =
+ case D#type.def of
+ #'SEQUENCE'{tablecinf=TCI,components=CL} ->
+ {'SEQUENCE',TCI,CL};
+ #'SET'{tablecinf=TCI,components=CL} ->
+ {'SET',TCI,CL}
+ end,
+ Ext = extensible(CompList),
+ CompList1 = case CompList of
+ {Rl,El} -> Rl ++ El;
+ _ -> CompList
+ end,
+ EncObj =
+ case TableConsInfo of
+ #simpletableattributes{usedclassfield=Used,
+ uniqueclassfield=Unique} when Used /= Unique ->
+ false;
+ %% ObjectSet, name of the object set in constraints
+ %%
+ %%{ObjectSet,AttrN,N,UniqueFieldName}
+ #simpletableattributes{objectsetname=ObjectSet,
+ c_name=AttrN,
+ c_index=N,
+ usedclassfield=UniqueFieldName,
+ uniqueclassfield=UniqueFieldName,
+ valueindex=ValueIndex
+ } ->
+ OSDef =
+ case ObjectSet of
+ {Module,OSName} ->
+ asn1_db:dbget(Module,OSName);
+ OSName ->
+ asn1_db:dbget(get(currmod),OSName)
+ end,
+% io:format("currmod: ~p~nOSName: ~p~nAttrN: ~p~nN: ~p~nUniqueFieldName: ~p~n",
+% [get(currmod),OSName,AttrN,N,UniqueFieldName]),
+ case (OSDef#typedef.typespec)#'ObjectSet'.gen of
+ true ->
+% Val = lists:concat(["?RT_BER:cindex(",
+% N+1,",Val,"]),
+ ObjectEncode =
+ asn1ct_gen:un_hyphen_var(lists:concat(['Obj',
+ AttrN])),
+ emit({ObjectEncode," = ",nl}),
+ emit({" 'getenc_",ObjectSet,"'(",{asis,UniqueFieldName},
+ ", ",nl}),
+% emit({indent(35),"?RT_BER:cindex(",N+1,", Val,",
+% {asis,AttrN},")),",nl}),
+ emit([indent(10+length(atom_to_list(ObjectSet))),
+ "value_match(",{asis,ValueIndex},",",
+ "?RT_BER:cindex(",N+1,",Val,",
+ {asis,AttrN},"))),",nl]),
+ notice_value_match(),
+ {AttrN,ObjectEncode};
+ _ ->
+ false
+ end;
+ _ ->
+ case D#type.tablecinf of
+ [{objfun,_}|_] ->
+ %% when the simpletableattributes was at an
+ %% outer level and the objfun has been passed
+ %% through the function call
+ {"got objfun through args","ObjFun"};
+ _ ->
+ false
+ end
+ end,
+
+ gen_enc_sequence_call(Erules,Typename,CompList1,1,Ext,EncObj),
+
+ MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
+ ++
+ [#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
+ number = asn1ct_gen_ber:decode_type(SeqOrSet),
+ form = ?CONSTRUCTED,
+ type = 'IMPLICIT'}],
+ emit([nl," BytesSoFar = "]),
+ case SeqOrSet of
+ 'SET' when (D#type.def)#'SET'.sorted == dynamic ->
+ emit("?RT_BER:dynamicsort_SET_components(["),
+ mkvlist(asn1ct_name:all(encBytes)),
+ emit(["]),",nl]);
+ _ ->
+ emit("["),
+ mkvlist(asn1ct_name:all(encBytes)),
+ emit(["],",nl])
+ end,
+ emit(" LenSoFar = "),
+ case asn1ct_name:all(encLen) of
+ [] -> emit("0");
+ AllLengths ->
+ mkvplus(AllLengths)
+ end,
+ emit([",",nl]),
+% emit(["{TagBytes,Len} = ?RT_BER:encode_tags(TagIn ++ ",
+ emit([" ?RT_BER:encode_tags(TagIn ++ ",
+ {asis,MyTag},", BytesSoFar, LenSoFar).",nl]).
+
+
+gen_decode_sequence(Erules,Typename,D) when record(D,type) ->
+ asn1ct_name:start(),
+% asn1ct_name:new(term),
+ asn1ct_name:new(tag),
+ #'SEQUENCE'{tablecinf=TableConsInfo,components=CList} = D#type.def,
+ Ext = extensible(CList),
+ CompList = case CList of
+ {Rl,El} -> Rl ++ El;
+ _ -> CList
+ end,
+
+ emit({" %%-------------------------------------------------",nl}),
+ emit({" %% decode tag and length ",nl}),
+ emit({" %%-------------------------------------------------",nl}),
+
+ asn1ct_name:new(rb),
+ MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
+ ++
+ [#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
+ number = asn1ct_gen_ber:decode_type('SEQUENCE'),
+ form = ?CONSTRUCTED,
+ type = 'IMPLICIT'}],
+ emit([" {{_,",asn1ct_gen_ber:unused_var("Len",D#type.def),"},",{next,bytes},",",{curr,rb},
+ "} = ?RT_BER:check_tags(TagIn ++ ",{asis,MyTag},", ",
+ {curr,bytes},", OptOrMand), ",nl]),
+ asn1ct_name:new(bytes),
+ asn1ct_name:new(len),
+
+ case CompList of
+ [] -> true;
+ _ ->
+ emit({"{",{next,bytes},
+ ",RemBytes} = ?RT_BER:split_list(",
+ {curr,bytes},
+ ",", {prev,len},"),",nl}),
+ asn1ct_name:new(bytes)
+ end,
+
+ {DecObjInf,UniqueFName,ValueIndex} =
+ case TableConsInfo of
+ #simpletableattributes{objectsetname=ObjectSet,
+ c_name=AttrN,
+ usedclassfield=UniqueFieldName,
+ uniqueclassfield=UniqueFieldName,
+ valueindex=ValIndex
+ } ->
+ F = fun(#'ComponentType'{typespec=CT})->
+ case {CT#type.constraint,CT#type.tablecinf} of
+ {[],[{objfun,_}|_R]} -> true;
+ _ -> false
+ end
+ end,
+ case lists:any(F,CompList) of
+ %%AttributeName = asn1ct_gen:un_hyphen_var(AttrN),
+ true -> % when component relation constraint establish
+ %% relation from a component to another components
+ %% subtype component
+ {{AttrN,{deep,ObjectSet,UniqueFieldName,
+ ValIndex}},
+ UniqueFieldName,ValIndex};
+ false ->
+ {{AttrN,ObjectSet},UniqueFieldName,ValIndex}
+ end;
+ _ ->
+ {false,false,false}
+ end,
+ case gen_dec_sequence_call(Erules,Typename,CompList,Ext,DecObjInf) of
+ no_terms -> % an empty sequence
+ emit([nl,nl]),
+ demit({"Result = "}), %dbg
+ %% return value as record
+ asn1ct_name:new(rb),
+ emit([" {{'",asn1ct_gen:list2rname(Typename),"'}, ",{curr,bytes},",",nl," "]),
+ asn1ct_gen_ber:add_removed_bytes(),
+ emit(["}.",nl]);
+ {LeadingAttrTerm,PostponedDecArgs} ->
+ emit([com,nl,nl]),
+ case {LeadingAttrTerm,PostponedDecArgs} of
+ {[],[]} ->
+ ok;
+ {_,[]} ->
+ ok;
+ {[{ObjSet,LeadingAttr,Term}],PostponedDecArgs} ->
+ DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])),
+ ValueMatch = value_match(ValueIndex,Term),
+ emit([DecObj," =",nl," 'getdec_",ObjSet,"'(",
+% {asis,UniqueFName},", ",Term,"),",nl}),
+ {asis,UniqueFName},", ",ValueMatch,"),",nl]),
+ gen_dec_postponed_decs(DecObj,PostponedDecArgs)
+ end,
+ demit({"Result = "}), %dbg
+ %% return value as record
+ asn1ct_name:new(rb),
+ asn1ct_name:new(bytes),
+ ExtStatus = case Ext of
+ {ext,_,_} -> ext;
+ noext -> noext
+ end,
+ emit([" {",{next,bytes},",",{curr,rb},"} = ?RT_BER:restbytes2(RemBytes, ",
+ {curr,bytes},",",ExtStatus,"),",nl]),
+ asn1ct_name:new(rb),
+ case Typename of
+ ['EXTERNAL'] ->
+ emit([" OldFormat={'",asn1ct_gen:list2rname(Typename),
+ "', "]),
+ mkvlist(asn1ct_name:all(term)),
+ emit(["},",nl]),
+ emit([" ASN11994Format =",nl,
+ " asn1rt_check:transform_to_EXTERNAL1994",
+ "(OldFormat),",nl]),
+ emit([" {ASN11994Format,",{next,bytes},", "]);
+ _ ->
+ emit([" {{'",asn1ct_gen:list2rname(Typename),"', "]),
+ mkvlist(asn1ct_name:all(term)),
+ emit(["}, ",{next,bytes},", "])
+ end,
+ asn1ct_gen_ber:add_removed_bytes(),
+ emit(["}.",nl])
+ end.
+
+gen_dec_postponed_decs(_,[]) ->
+ emit(nl);
+gen_dec_postponed_decs(DecObj,[{_Cname,{FirstPFN,PFNList},Term,TmpTerm,_Tag,OptOrMand}|Rest]) ->
+% asn1ct_name:new(term),
+ asn1ct_name:new(tmpterm),
+ asn1ct_name:new(reason),
+
+ emit({"{",Term,", _, _} = ",nl}),
+ N = case OptOrMand of
+ mandatory -> 0;
+ 'OPTIONAL' ->
+ emit_opt_or_mand_check(asn1_NOVALUE,TmpTerm),
+ 6;
+ {'DEFAULT',Val} ->
+ emit_opt_or_mand_check(Val,TmpTerm),
+ 6
+ end,
+ emit({indent(N+3),"case (catch ",DecObj,"(",{asis,FirstPFN},
+% ", ",TmpTerm,", ", {asis,Tag},", ",{asis,PFNList},")) of",nl}),
+ ", ",TmpTerm,", [], ",{asis,PFNList},")) of",nl}),
+ emit({indent(N+6),"{'EXIT', ",{curr,reason},"} ->",nl}),
+ emit({indent(N+9),"exit({'Type not compatible with table constraint',",
+ {curr,reason},"});",nl}),
+ emit({indent(N+6),{curr,tmpterm}," ->",nl}),
+ emit({indent(N+9),{curr,tmpterm},nl}),
+
+ case OptOrMand of
+ mandatory -> emit([indent(N+3),"end,",nl]);
+ _ ->
+ emit([indent(N+3),"end",nl,
+ indent(3),"end,",nl])
+ end,
+% emit({indent(3),"end,",nl}),
+ gen_dec_postponed_decs(DecObj,Rest).
+
+
+emit_opt_or_mand_check(Value,TmpTerm) ->
+ emit([indent(3),"case ",TmpTerm," of",nl,
+ indent(6),{asis,Value}," -> {",{asis,Value},",[],[]};",nl,
+ indent(6),"_ ->",nl]).
+
+%%============================================================================
+%% Encode/decode SET
+%%
+%%============================================================================
+
+gen_encode_set(Erules,Typename,D) when record(D,type) ->
+ gen_encode_sequence(Erules,Typename,D).
+
+gen_decode_set(Erules,Typename,D) when record(D,type) ->
+ asn1ct_name:start(),
+ asn1ct_name:new(term),
+ asn1ct_name:new(tag),
+ #'SET'{components=TCompList} = D#type.def,
+ Ext = extensible(TCompList),
+ CompList = case TCompList of
+ {Rl,El} -> Rl ++ El;
+ _ -> TCompList
+ end,
+
+ emit([" %%-------------------------------------------------",nl]),
+ emit([" %% decode tag and length ",nl]),
+ emit([" %%-------------------------------------------------",nl]),
+
+ asn1ct_name:new(rb),
+ MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
+ ++
+ [#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
+ number = asn1ct_gen_ber:decode_type('SET'),
+ form = ?CONSTRUCTED,
+ type = 'IMPLICIT'}],
+ emit([" {{_,Len},",{next,bytes},",",{curr,rb},
+ "} = ?RT_BER:check_tags(TagIn ++ ",{asis,MyTag},", ",
+ {curr,bytes},", OptOrMand), ",nl]),
+ asn1ct_name:new(bytes),
+ asn1ct_name:new(len),
+ asn1ct_name:new(rb),
+
+ emit([" {SetTerm, SetBytes, ",{curr,rb},"} = ?RT_BER:decode_set(0, Len, ",
+ {curr,bytes},", OptOrMand, ",
+ "fun 'dec_",asn1ct_gen:list2name(Typename),"_fun'/2, []),",nl]),
+
+ asn1ct_name:new(rb),
+ emit([" 'dec_",asn1ct_gen:list2name(Typename),"_result'(lists:sort(SetTerm), SetBytes, "]),
+ asn1ct_gen_ber:add_removed_bytes(),
+ emit([").",nl,nl,nl]),
+
+ emit({"%%-------------------------------------------------",nl}),
+ emit({"%% Set loop fun for ",asn1ct_gen:list2name(Typename),nl}),
+ emit({"%%-------------------------------------------------",nl}),
+
+ asn1ct_name:clear(),
+ asn1ct_name:new(term),
+ emit(["'dec_",asn1ct_gen:list2name(Typename),"_fun'(",{curr,bytes},
+ ", OptOrMand) ->",nl]),
+
+ asn1ct_name:new(bytes),
+ gen_dec_set(Erules,Typename,CompList,1,Ext),
+
+ emit([" %% tag not found, if extensionmark we should skip bytes here",nl]),
+ emit([indent(6),"_ -> {[], Bytes,0}",nl]),
+ emit([indent(3),"end.",nl,nl,nl]),
+
+
+ emit({"%%-------------------------------------------------",nl}),
+ emit({"%% Result ",asn1ct_gen:list2name(Typename),nl}),
+ emit({"%%-------------------------------------------------",nl}),
+
+ asn1ct_name:clear(),
+ emit({"'dec_",asn1ct_gen:list2name(Typename),"_result'(",
+ asn1ct_gen_ber:unused_var("TermList",D#type.def),", Bytes, Rb) ->",nl}),
+
+ case gen_dec_set_result(Erules,Typename,CompList) of
+ no_terms ->
+ %% return value as record
+ asn1ct_name:new(rb),
+ emit({" {{'",asn1ct_gen:list2rname(Typename),"'}, Bytes, Rb}.",nl});
+ _ ->
+ emit({nl," case ",{curr,termList}," of",nl}),
+ emit({" [] -> {{'",asn1ct_gen:list2rname(Typename),"', "}),
+ mkvlist(asn1ct_name:all(term)),
+ emit({"}, Bytes, Rb};",nl}),
+ emit({" ExtraAtt -> exit({error,{asn1,{too_many_attributes, ExtraAtt}}})",nl}),
+ emit({" end.",nl}),
+ emit({nl,nl,nl})
+ end.
+
+
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+%% Encode/decode SEQUENCE OF and SET OF
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+
+gen_encode_sof(Erules,Typename,_InnerTypename,D) when record(D,type) ->
+ asn1ct_name:start(),
+ {SeqOrSetOf, Cont} = D#type.def,
+
+ Objfun = case D#type.tablecinf of
+ [{objfun,_}|_R] ->
+ ", ObjFun";
+ _ ->
+ ""
+ end,
+
+ emit({" {EncBytes,EncLen} = 'enc_",asn1ct_gen:list2name(Typename),
+ "_components'(Val",Objfun,",[],0),",nl}),
+
+ MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
+ ++
+ [#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
+ number = asn1ct_gen_ber:decode_type(SeqOrSetOf),
+ form = ?CONSTRUCTED,
+ type = 'IMPLICIT'}],
+% gen_encode_tags(Erules,MyTag,"EncLen","EncBytes"),
+ emit([" ?RT_BER:encode_tags(TagIn ++ ",
+ {asis,MyTag},", EncBytes, EncLen).",nl,nl]),
+
+ gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont).
+% gen_enc_line(Erules,Typename,TypeNameSuffix,Cont,"H",0,
+% mandatory,"{EncBytes,EncLen} = "),
+
+
+gen_decode_sof(Erules,Typename,_InnerTypename,D) when record(D,type) ->
+ asn1ct_name:start(),
+ {SeqOrSetOf, TypeTag, Cont} =
+ case D#type.def of
+ {'SET OF',_Cont} -> {'SET OF','SET',_Cont};
+ {'SEQUENCE OF',_Cont} -> {'SEQUENCE OF','SEQUENCE',_Cont}
+ end,
+ TypeNameSuffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,Cont#type.def),
+
+ emit({" %%-------------------------------------------------",nl}),
+ emit({" %% decode tag and length ",nl}),
+ emit({" %%-------------------------------------------------",nl}),
+
+ asn1ct_name:new(rb),
+ MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
+ ++
+ [#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
+ number = asn1ct_gen_ber:decode_type(TypeTag),
+ form = ?CONSTRUCTED,
+ type = 'IMPLICIT'}],
+ emit([" {{_,Len},",{next,bytes},",",{curr,rb},
+ "} = ?RT_BER:check_tags(TagIn ++ ",{asis,MyTag},", ",
+ {curr,bytes},", OptOrMand), ",nl]),
+
+ emit([" ?RT_BER:decode_components(",{curr,rb}]),
+ InnerType = asn1ct_gen:get_inner(Cont#type.def),
+ ContName = case asn1ct_gen:type(InnerType) of
+ Atom when atom(Atom) -> Atom;
+ _ -> TypeNameSuffix
+ end,
+ emit([", Len, ",{next,bytes},", "]),
+% NewCont =
+% case Cont#type.def of
+% {'ENUMERATED',_,Components}->
+% Cont#type{def={'ENUMERATED',Components}};
+% _ -> Cont
+% end,
+ ObjFun =
+ case D#type.tablecinf of
+ [{objfun,_}|_R] ->
+ ", ObjFun";
+ _ ->
+ []
+ end,
+ gen_dec_line_sof(Erules,Typename,ContName,Cont,ObjFun),
+ emit([", []).",nl,nl,nl]).
+
+
+gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont)
+ when record(Cont,type)->
+
+ {Objfun,ObjFun_novar,EncObj} =
+ case Cont#type.tablecinf of
+ [{objfun,_}|_R] ->
+ {", ObjFun",", _",{no_attr,"ObjFun"}};
+ _ ->
+ {"","",false}
+ end,
+ emit(["'enc_",asn1ct_gen:list2name(Typename),
+ "_components'([]",ObjFun_novar,", AccBytes, AccLen) -> ",nl]),
+
+ case catch lists:member(der,get(encoding_options)) of
+ true ->
+ emit([indent(3),
+ "{?RT_BER:dynamicsort_SETOF(AccBytes),AccLen};",nl,nl]);
+ _ ->
+ emit([indent(3),"{lists:reverse(AccBytes),AccLen};",nl,nl])
+ end,
+ emit(["'enc_",asn1ct_gen:list2name(Typename),
+ "_components'([H|T]",Objfun,",AccBytes, AccLen) ->",nl]),
+ TypeNameSuffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,Cont#type.def),
+ gen_enc_line(Erules,Typename,TypeNameSuffix,Cont,"H",3,
+ mandatory,"{EncBytes,EncLen} = ",EncObj),
+ emit([",",nl]),
+ emit([indent(3),"'enc_",asn1ct_gen:list2name(Typename),
+ "_components'(T",Objfun,","]),
+ emit(["[EncBytes|AccBytes], AccLen + EncLen).",nl,nl]).
+
+%%============================================================================
+%% Encode/decode CHOICE
+%%
+%%============================================================================
+
+gen_encode_choice(Erules,Typename,D) when record(D,type) ->
+ ChoiceTag = D#type.tag,
+ {'CHOICE',CompList} = D#type.def,
+ Ext = extensible(CompList),
+ CompList1 = case CompList of
+ {Rl,El} -> Rl ++ El;
+ _ -> CompList
+ end,
+ gen_enc_choice(Erules,Typename,ChoiceTag,CompList1,Ext),
+ emit({nl,nl}).
+
+gen_decode_choice(Erules,Typename,D) when record(D,type) ->
+ asn1ct_name:start(),
+ asn1ct_name:new(bytes),
+ ChoiceTag = D#type.tag,
+ {'CHOICE',CompList} = D#type.def,
+ Ext = extensible(CompList),
+ CompList1 = case CompList of
+ {Rl,El} -> Rl ++ El;
+ _ -> CompList
+ end,
+ gen_dec_choice(Erules,Typename,ChoiceTag,CompList1,Ext),
+ emit({".",nl}).
+
+
+%%============================================================================
+%% Encode SEQUENCE
+%%
+%%============================================================================
+
+gen_enc_sequence_call(Erules,TopType,[#'ComponentType'{name=Cname,typespec=Type,prop=Prop}|Rest],Pos,Ext,EncObj) ->
+ asn1ct_name:new(encBytes),
+ asn1ct_name:new(encLen),
+ Element =
+ case TopType of
+ ['EXTERNAL'] ->
+ io_lib:format("?RT_BER:cindex(~w,NewVal,~w)",[Pos+1,Cname]);
+ _ ->
+ io_lib:format("?RT_BER:cindex(~w,Val,~w)",[Pos+1,Cname])
+ end,
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ print_attribute_comment(InnerType,Pos,Prop),
+ gen_enc_line(Erules,TopType,Cname,Type,Element,3,Prop,EncObj),
+ case Rest of
+ [] ->
+ emit({com,nl});
+ _ ->
+ emit({com,nl}),
+ gen_enc_sequence_call(Erules,TopType,Rest,Pos+1,Ext,EncObj)
+ end;
+
+gen_enc_sequence_call(_Erules,_TopType,[],_Num,_,_) ->
+ true.
+
+%%============================================================================
+%% Decode SEQUENCE
+%%
+%%============================================================================
+
+gen_dec_sequence_call(Erules,TopType,CompList,Ext,DecObjInf) ->
+ gen_dec_sequence_call1(Erules,TopType, CompList, 1, Ext,DecObjInf,[],[]).
+
+
+gen_dec_sequence_call1(Erules,TopType,[#'ComponentType'{name=Cname,typespec=Type,prop=Prop,tags=Tags}|Rest],Num,Ext,DecObjInf,LeadingAttrAcc,ArgsAcc) ->
+ {LA,PostponedDec} =
+ gen_dec_component(Erules,TopType,Cname,Tags,Type,Num,Prop,
+ Ext,DecObjInf),
+ case Rest of
+ [] ->
+ {LA ++ LeadingAttrAcc,PostponedDec ++ ArgsAcc};
+ _ ->
+ emit({com,nl}),
+% asn1ct_name:new(term),
+ asn1ct_name:new(bytes),
+ gen_dec_sequence_call1(Erules,TopType,Rest,Num+1,Ext,DecObjInf,
+ LA++LeadingAttrAcc,PostponedDec++ArgsAcc)
+ end;
+
+gen_dec_sequence_call1(_Erules,_TopType,[],1,_,_,_,_) ->
+ no_terms.
+%%gen_dec_sequence_call1(Erules,_TopType,[],Num,_) ->
+%% true.
+
+
+
+%%----------------------------
+%%SEQUENCE mandatory
+%%----------------------------
+
+gen_dec_component(Erules,TopType,Cname,CTags,Type,Pos,Prop,Ext,DecObjInf) ->
+ InnerType =
+ case Type#type.def of
+ #'ObjectClassFieldType'{type=OCFTType} -> OCFTType;
+ _ -> asn1ct_gen:get_inner(Type#type.def)
+ end,
+% case asn1ct_gen:get_constraint(Type#type.constraint,
+% tableconstraint_info) of
+% no ->
+% asn1ct_gen:get_inner(Type#type.def);
+% _ ->
+% Type#type.def
+% end,
+ Prop1 = case {Prop,Ext} of
+ {mandatory,{ext,Epos,_}} when Pos >= Epos ->
+ 'OPTIONAL';
+ _ ->
+ Prop
+ end,
+ print_attribute_comment(InnerType,Pos,Prop1),
+ emit(" "),
+
+ case {InnerType,DecObjInf} of
+ {{typefield,_},NotFalse} when NotFalse /= false ->
+ asn1ct_name:new(term),
+ asn1ct_name:new(tmpterm),
+ emit({"{",{curr,tmpterm},", ",{next,bytes},",",{next,rb},"} = "});
+ {{objectfield,_,_},_} ->
+ asn1ct_name:new(term),
+ asn1ct_name:new(tmpterm),
+ emit({"{",{curr,tmpterm},", ",{next,bytes},",",{next,rb},"} = "});
+ _ ->
+ asn1ct_name:new(term),
+ emit({"{",{curr,term},",",{next,bytes},",",{next,rb},"} = "})
+ end,
+ asn1ct_name:new(rb),
+ PostponedDec =
+ gen_dec_line(Erules,TopType,Cname,CTags,Type,Prop1,DecObjInf),
+ asn1ct_name:new(form),
+ PostponedDec.
+
+
+%%-------------------------------------
+%% Decode SET
+%%-------------------------------------
+
+gen_dec_set(Erules,TopType,CompList,Pos,_Ext) ->
+ TagList = get_all_choice_tags(CompList),
+ emit({indent(3),
+ {curr,tagList}," = ",{asis,TagList},",",nl}),
+ emit({indent(3),
+ "case ?RT_BER:check_if_valid_tag(Bytes, ",
+ {curr,tagList},", OptOrMand) of",nl}),
+ asn1ct_name:new(tagList),
+ asn1ct_name:new(rbCho),
+ asn1ct_name:new(choTags),
+ gen_dec_set_cases(Erules,TopType,CompList,TagList,Pos),
+ asn1ct_name:new(tag),
+ asn1ct_name:new(bytes).
+
+
+
+gen_dec_set_cases(_,_,[],_,_) ->
+ ok;
+gen_dec_set_cases(Erules,TopType,[H|T],List,Pos) ->
+ case H of
+ {'EXTENSIONMARK', _, _} ->
+ gen_dec_set_cases(Erules,TopType,T,List,Pos);
+ _ ->
+ Name = H#'ComponentType'.name,
+ Type = H#'ComponentType'.typespec,
+
+ emit({indent(6),"'",Name,"' ->",nl}),
+ case Type#type.def of
+ {'CHOICE',_NewCompList} ->
+ gen_dec_set_cases_choice(Erules,TopType,H,Pos);
+ _ ->
+ gen_dec_set_cases_type(Erules,TopType,H,Pos)
+ end,
+ gen_dec_set_cases(Erules,TopType,T,List,Pos+1)
+ end.
+
+
+
+
+gen_dec_set_cases_choice(_Erules,TopType,H,Pos) ->
+ Cname = H#'ComponentType'.name,
+ Tag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}
+ || X <- (H#'ComponentType'.typespec)#type.tag],
+ asn1ct_name:new(rbCho),
+ emit({indent(9),"{Dec, Rest, ",{curr,rbCho},"} = "}),
+ emit({"'dec_",asn1ct_gen:list2name([Cname|TopType]),
+ "'(Bytes,OptOrMand,",{asis,Tag},"),",nl}),
+ emit([" {{",Pos,",Dec}, Rest, ",{curr,rbCho},"}"]),
+ emit([";",nl,nl]).
+
+
+gen_dec_set_cases_type(Erules,TopType,H,Pos) ->
+ Cname = H#'ComponentType'.name,
+ Type = H#'ComponentType'.typespec,
+ %% always use Prop = mandatory here Prop = H#'ComponentType'.prop,
+
+ asn1ct_name:new(rbCho),
+ emit({indent(9),"{Dec, Rest, ",{curr,rbCho},"} = "}),
+ asn1ct_name:delete(bytes),
+ %% we have already seen the tag so now we must find the value
+ %% that why we always use 'mandatory' here
+ gen_dec_line(Erules,TopType,Cname,[],Type,mandatory,decObjInf),
+ asn1ct_name:new(bytes),
+
+ emit([",",nl]),
+ emit(["{{",Pos,",Dec}, Rest, ",{curr,rbCho},"}"]),
+ emit([";",nl,nl]).
+
+
+%%---------------------------------
+%% Decode SET result
+%%---------------------------------
+
+gen_dec_set_result(Erules,TopType,{CompList,_ExtList}) ->
+ gen_dec_set_result1(Erules,TopType, CompList, 1);
+gen_dec_set_result(Erules,TopType,CompList) ->
+ gen_dec_set_result1(Erules,TopType, CompList, 1).
+
+gen_dec_set_result1(Erules,TopType,
+ [#'ComponentType'{name=Cname,
+ typespec=Type,
+ prop=Prop}|Rest],Num) ->
+ gen_dec_set_component(Erules,TopType,Cname,Type,Num,Prop),
+ case Rest of
+ [] ->
+ true;
+ _ ->
+ gen_dec_set_result1(Erules,TopType,Rest,Num+1)
+ end;
+
+gen_dec_set_result1(_Erules,_TopType,[],1) ->
+ no_terms;
+gen_dec_set_result1(_Erules,_TopType,[],_Num) ->
+ true.
+
+
+gen_dec_set_component(_Erules,_TopType,_Cname,Type,Pos,Prop) ->
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ print_attribute_comment(InnerType,Pos,Prop),
+ emit({" {",{next,term},com,{next,termList},"} =",nl}),
+ emit({" case ",{curr,termList}," of",nl}),
+ emit({" [{",Pos,com,{curr,termTmp},"}|",
+ {curr,rest},"] -> "}),
+ emit({"{",{curr,termTmp},com,
+ {curr,rest},"};",nl}),
+ case Prop of
+ 'OPTIONAL' ->
+ emit([indent(10),"_ -> {asn1_NOVALUE, ",{curr,termList},"}",nl]);
+ {'DEFAULT', DefVal} ->
+ emit([indent(10),
+ "_ -> {",{asis,DefVal},", ",{curr,termList},"}",nl]);
+ mandatory ->
+ emit([indent(10),
+ "_ -> exit({error,{asn1,{mandatory_attribute_no, ",
+ Pos,", missing}}})",nl])
+ end,
+ emit([indent(6),"end,",nl]),
+ asn1ct_name:new(rest),
+ asn1ct_name:new(term),
+ asn1ct_name:new(termList),
+ asn1ct_name:new(termTmp).
+
+
+%%---------------------------------------------
+%% Encode CHOICE
+%%---------------------------------------------
+%% for BER we currently do care (a little) if the choice has an EXTENSIONMARKER
+
+
+gen_enc_choice(Erules,TopType,Tag,CompList,_Ext) ->
+ gen_enc_choice1(Erules,TopType,Tag,CompList,_Ext).
+
+gen_enc_choice1(Erules,TopType,Tag,CompList,_Ext) ->
+ asn1ct_name:clear(),
+ emit({" {EncBytes,EncLen} = case element(1,Val) of",nl}),
+ gen_enc_choice2(Erules,TopType,CompList),
+ emit([nl," end,",nl,nl]),
+ NewTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- Tag],
+% gen_encode_tags(Erules,NewTag,"EncLen","EncBytes").
+ emit(["?RT_BER:encode_tags(TagIn ++",{asis,NewTag},", EncBytes, EncLen).",nl]).
+
+
+
+gen_enc_choice2(Erules,TopType,[H1|T]) when record(H1,'ComponentType') ->
+ Cname = H1#'ComponentType'.name,
+ Type = H1#'ComponentType'.typespec,
+ emit({" ",{asis,Cname}," ->",nl}),
+ {Encobj,Assign} =
+% case asn1ct_gen:get_constraint(Type#type.constraint,
+% tableconstraint_info) of
+ case {Type#type.def,asn1ct_gen:get_constraint(Type#type.constraint,
+ componentrelation)} of
+ {#'ObjectClassFieldType'{},{componentrelation,_,_}} ->
+ asn1ct_name:new(tmpBytes),
+ asn1ct_name:new(encBytes),
+ asn1ct_name:new(encLen),
+ Emit = ["{",{curr,tmpBytes},", _} = "],
+ {{no_attr,"ObjFun"},Emit};
+ _ ->
+ {false,[]}
+ end,
+ gen_enc_line(Erules,TopType,Cname,Type,"element(2,Val)",9,
+ mandatory,Assign,Encobj),
+ case Encobj of
+ false -> ok;
+ _ ->
+ emit({",",nl,indent(9),"{",{curr,encBytes},", ",
+ {curr,encLen},"}"})
+ end,
+ emit({";",nl}),
+ case T of
+ [] ->
+ emit([indent(6), "Else -> ",nl,
+ indent(9),"exit({error,{asn1,{invalid_choice_type,Else}}})"]);
+ _ ->
+ true
+ end,
+ gen_enc_choice2(Erules,TopType,T);
+
+gen_enc_choice2(_,_,[]) ->
+ true.
+
+
+
+
+%%--------------------------------------------
+%% Decode CHOICE
+%%--------------------------------------------
+
+gen_dec_choice(Erules,TopType, ChTag, CompList, Ext) ->
+ asn1ct_name:delete(bytes),
+ Tags = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- ChTag],
+
+ emit([" {{_,Len},",{next,bytes},
+ ", RbExp} = ?RT_BER:check_tags(TagIn++",
+ {asis,Tags},", ",
+ {curr,bytes},", OptOrMand),",nl]),
+ asn1ct_name:new(bytes),
+ asn1ct_name:new(len),
+ gen_dec_choice_indef_funs(Erules),
+ case Erules of
+ ber_bin ->
+ emit([indent(3),"case ",{curr,bytes}," of",nl]);
+ ber ->
+ emit([indent(3),
+ "case (catch ?RT_BER:peek_tag(",{curr,bytes},")) of",nl])
+ end,
+ asn1ct_name:new(tagList),
+ asn1ct_name:new(choTags),
+ gen_dec_choice_cases(Erules,TopType,CompList),
+ case Ext of
+ noext ->
+ emit([indent(6), {curr,else}," -> ",nl]),
+ emit([indent(9),"case OptOrMand of",nl,
+ indent(12),"mandatory ->","exit({error,{asn1,",
+ "{invalid_choice_tag,",{curr,else},"}}});",nl,
+ indent(12),"_ ->","exit({error,{asn1,{no_optional_tag,",
+ {curr,else},"}}})",nl,
+ indent(9),"end",nl]);
+ _ ->
+ emit([indent(6),"_ -> ",nl]),
+ emit([indent(9),"{{asn1_ExtAlt,",{curr,bytes},"},",
+ empty_lb(Erules),", RbExp}",nl])
+ end,
+ emit([indent(3),"end"]),
+ asn1ct_name:new(tag),
+ asn1ct_name:new(else).
+
+gen_dec_choice_indef_funs(Erules) ->
+ emit({indent(3),"IndefEndBytes = fun(indefinite,",indefend_match(Erules,used_var),
+ ")-> R; (_,B)-> B end,",nl}),
+ emit({indent(3),"IndefEndRb = fun(indefinite,",indefend_match(Erules,unused_var),
+ ")-> 2; (_,_)-> 0 end,",nl}).
+
+
+gen_dec_choice_cases(_,_, []) ->
+ ok;
+gen_dec_choice_cases(Erules,TopType, [H|T]) ->
+ asn1ct_name:push(rbCho),
+ Name = H#'ComponentType'.name,
+ emit([nl,"%% '",Name,"'",nl]),
+ Fcases = fun([T1,T2|Tail],Fun) ->
+ emit([indent(6),match_tag(Erules,T1)," ->",nl]),
+ gen_dec_choice_cases_type(Erules,TopType, H),
+ Fun([T2|Tail],Fun);
+ ([T1],_) ->
+ emit([indent(6),match_tag(Erules,T1)," ->",nl]),
+ gen_dec_choice_cases_type(Erules,TopType, H)
+ end,
+ Fcases(H#'ComponentType'.tags,Fcases),
+ asn1ct_name:pop(rbCho),
+ gen_dec_choice_cases(Erules,TopType, T).
+
+
+
+gen_dec_choice_cases_type(Erules,TopType,H) ->
+ Cname = H#'ComponentType'.name,
+ Type = H#'ComponentType'.typespec,
+ Prop = H#'ComponentType'.prop,
+ emit({indent(9),"{Dec, Rest, ",{curr,rbCho},"} = "}),
+ gen_dec_line(Erules,TopType,Cname,[],Type,Prop,false),
+ emit([",",nl,indent(9),"{{",{asis,Cname},
+ ", Dec}, IndefEndBytes(Len,Rest), RbExp + ",
+ {curr,rbCho}," + IndefEndRb(Len,Rest)};",nl,nl]).
+
+encode_tag_val(Erules,{Class,TagNo}) when integer(TagNo) ->
+ Rtmod = rtmod(Erules),
+ Rtmod:encode_tag_val({asn1ct_gen_ber:decode_class(Class),
+ 0,TagNo});
+encode_tag_val(Erules,{Class,TypeName}) ->
+ Rtmod = rtmod(Erules),
+ Rtmod:encode_tag_val({asn1ct_gen_ber:decode_class(Class),
+ 0,asn1ct_gen_ber:decode_type(TypeName)}).
+
+
+match_tag(ber_bin,Arg) ->
+ match_tag_with_bitsyntax(Arg);
+match_tag(Erules,Arg) ->
+ io_lib:format("~p",[encode_tag_val(Erules,Arg)]).
+
+match_tag_with_bitsyntax({Class,TagNo}) when integer(TagNo) ->
+ match_tag_with_bitsyntax1({asn1ct_gen_ber:decode_class(Class),
+ 0,TagNo});
+match_tag_with_bitsyntax({Class,TypeName}) ->
+ match_tag_with_bitsyntax1({asn1ct_gen_ber:decode_class(Class),
+ 0,asn1ct_gen_ber:decode_type(TypeName)}).
+
+match_tag_with_bitsyntax1({Class, _Form, TagNo}) when (TagNo =< 30) ->
+ io_lib:format("<<~p:2,_:1,~p:5,_/binary>>",[Class bsr 6,TagNo]);
+
+match_tag_with_bitsyntax1({Class, _Form, TagNo}) ->
+ {Octets,Len} = mk_object_val(TagNo),
+ OctForm = case Len of
+ 1 -> "~p";
+ 2 -> "~p,~p";
+ 3 -> "~p,~p,~p";
+ 4 -> "~p,~p,~p,~p"
+ end,
+ io_lib:format("<<~p:2,_:1,31:5," ++ OctForm ++ ",_/binary>>",
+ [Class bsr 6] ++ Octets).
+
+%%%%%%%%%%%
+%% mk_object_val(Value) -> {OctetList, Len}
+%% returns a Val as a list of octets, the 8 bit is allways set to one except
+%% for the last octet, where its 0
+%%
+
+
+mk_object_val(Val) when Val =< 127 ->
+ {[255 band Val], 1};
+mk_object_val(Val) ->
+ mk_object_val(Val bsr 7, [Val band 127], 1).
+mk_object_val(0, Ack, Len) ->
+ {Ack, Len};
+mk_object_val(Val, Ack, Len) ->
+ mk_object_val(Val bsr 7, [((Val band 127) bor 128) | Ack], Len + 1).
+
+
+get_all_choice_tags(ComponentTypeList) ->
+ get_all_choice_tags(ComponentTypeList,[]).
+
+get_all_choice_tags([],TagList) ->
+ TagList;
+get_all_choice_tags([H|T],TagList) ->
+ Tags = H#'ComponentType'.tags,
+ get_all_choice_tags(T, TagList ++ [{H#'ComponentType'.name, Tags}]).
+
+
+
+%%---------------------------------------
+%% Generate the encode/decode code
+%%---------------------------------------
+
+gen_enc_line(Erules,TopType,Cname,
+ Type=#type{constraint=[{componentrelation,_,_}],
+ def=#'ObjectClassFieldType'{type={typefield,_}}},
+ Element,Indent,OptOrMand=mandatory,EncObj)
+ when list(Element) ->
+ asn1ct_name:new(tmpBytes),
+ gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,
+ ["{",{curr,tmpBytes},",_} = "],EncObj);
+gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,EncObj)
+ when list(Element) ->
+ gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,
+ ["{",{curr,encBytes},",",{curr,encLen},"} = "],EncObj).
+
+gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,Assign,EncObj)
+ when list(Element) ->
+ IndDeep = indent(Indent),
+
+ Tag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}
+ || X <- Type#type.tag],
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ WhatKind = asn1ct_gen:type(InnerType),
+ emit(IndDeep),
+ emit(Assign),
+ gen_optormand_case(OptOrMand,Erules,TopType,Cname,Type,InnerType,WhatKind,
+ Element),
+ case {Type,asn1ct_gen:get_constraint(Type#type.constraint,
+ componentrelation)} of
+% #type{constraint=[{tableconstraint_info,RefedFieldName}],
+% def={typefield,_}} ->
+ {#type{def=#'ObjectClassFieldType'{type={typefield,_},
+ fieldname=RefedFieldName}},
+ {componentrelation,_,_}} ->
+ {_LeadingAttrName,Fun} = EncObj,
+ case RefedFieldName of
+ {notype,T} ->
+ throw({error,{notype,type_from_object,T}});
+ {Name,RestFieldNames} when atom(Name) ->
+ case OptOrMand of
+ mandatory -> ok;
+ _ ->
+% emit(["{",{curr,tmpBytes},",",{curr,tmpLen},
+ emit(["{",{curr,tmpBytes},", _} = "])
+%% asn1ct_name:new(tmpBytes),
+%% asn1ct_name:new(tmpLen)
+ end,
+ emit({Fun,"(",{asis,Name},", ",Element,", [], ",
+ {asis,RestFieldNames},"),",nl}),
+ emit(IndDeep),
+ case OptOrMand of
+ mandatory ->
+ emit({"{",{curr,encBytes},", ",{curr,encLen},"} = "}),
+ emit({"?RT_BER:encode_open_type(",{curr,tmpBytes},
+ ",",{asis,Tag},")"});
+ _ ->
+% emit({"{",{next,tmpBytes},", _} = "}),
+ emit({"{",{next,tmpBytes},", ",{curr,tmpLen},
+ "} = "}),
+ emit({"?RT_BER:encode_open_type(",{curr,tmpBytes},
+ ",",{asis,Tag},"),",nl}),
+ emit(IndDeep),
+ emit({"{",{next,tmpBytes},", ",{curr,tmpLen},"}"})
+ end;
+ _ ->
+ throw({asn1,{'internal error'}})
+ end;
+% #type{constraint=[{tableconstraint_info,_}],
+% def={objectfield,PrimFieldName1,PFNList}} ->
+ {{#'ObjectClassFieldType'{type={objectfield,PrimFieldName1,
+ PFNList}},_},
+ {componentrelation,_,_}} ->
+ %% this is when the dotted list in the FieldName has more
+ %% than one element
+ {_LeadingAttrName,Fun} = EncObj,
+ emit({"?RT_BER:encode_open_type(",Fun,"(",{asis,PrimFieldName1},
+ ", ",Element,", ",{asis,PFNList},"),",{asis,Tag},")"});
+ _ ->
+ case WhatKind of
+ {primitive,bif} ->
+ EncType =
+ case Type#type.def of
+ #'ObjectClassFieldType'{
+ type={fixedtypevaluefield,
+ _,Btype}} ->
+ Btype;
+ _ ->
+ Type
+ end,
+ asn1ct_gen_ber:gen_encode_prim(ber,EncType,{asis,Tag},
+ Element);
+ {notype,_} ->
+ emit({"'enc_",InnerType,"'(",Element,", ",{asis,Tag},")"});
+ 'ASN1_OPEN_TYPE' ->
+ asn1ct_gen_ber:gen_encode_prim(ber,Type#type{def='ASN1_OPEN_TYPE'},{asis,Tag},Element);
+ _ ->
+ {EncFunName, _, _} =
+ mkfuncname(TopType,Cname,WhatKind,enc),
+ case {WhatKind,Type#type.tablecinf,EncObj} of
+ {{constructed,bif},[{objfun,_}|_R],{_,Fun}} ->
+ emit([EncFunName,"(",Element,", ",{asis,Tag},
+ ", ",Fun,")"]);
+ _ ->
+ emit([EncFunName,"(",Element,", ",{asis,Tag},")"])
+ end
+ end
+ end,
+ case OptOrMand of
+ mandatory -> true;
+ _ ->
+ emit({nl,indent(7),"end"})
+ end.
+
+
+
+gen_optormand_case(mandatory,_,_,_,_,_,_, _) ->
+ ok;
+gen_optormand_case('OPTIONAL',Erules,_,_,_,_,_,Element) ->
+ emit({" case ",Element," of",nl}),
+ emit({indent(9),"asn1_NOVALUE -> {",
+ empty_lb(Erules),",0};",nl}),
+ emit({indent(9),"_ ->",nl,indent(12)});
+gen_optormand_case({'DEFAULT',DefaultValue},Erules,TopType,Cname,Type,
+ InnerType,WhatKind,Element) ->
+ CurrMod = get(currmod),
+ case catch lists:member(der,get(encoding_options)) of
+ true ->
+ emit(" case catch "),
+ asn1ct_gen:gen_check_call(TopType,Cname,Type,InnerType,
+ WhatKind,{asis,DefaultValue},
+ Element),
+ emit({" of",nl}),
+ emit({indent(12),"true -> {[],0};",nl});
+ _ ->
+ emit({" case ",Element," of",nl}),
+ emit({indent(9),"asn1_DEFAULT -> {",
+ empty_lb(Erules),
+ ",0};",nl}),
+ case DefaultValue of
+ #'Externalvaluereference'{module=CurrMod,
+ value=V} ->
+ emit({indent(9),"?",{asis,V}," -> {",
+ empty_lb(Erules),",0};",nl});
+ _ ->
+ emit({indent(9),{asis,
+ DefaultValue}," -> {",
+ empty_lb(Erules),",0};",nl})
+ end
+ end,
+ emit({indent(9),"_ ->",nl,indent(12)}).
+
+
+
+
+gen_dec_line_sof(_Erules,TopType,Cname,Type,ObjFun) ->
+
+ Tag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}
+ || X <- Type#type.tag],
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ WhatKind = asn1ct_gen:type(InnerType),
+ case WhatKind of
+ {primitive,bif} ->
+ asn1ct_name:delete(len),
+
+ asn1ct_name:new(len),
+ emit(["fun(FBytes,_,_)->",nl]),
+ EncType = case Type#type.def of
+ #'ObjectClassFieldType'{
+ type={fixedtypevaluefield,
+ _,Btype}} ->
+ Btype;
+ _ ->
+ Type
+ end,
+ asn1ct_gen_ber:gen_dec_prim(ber,EncType,"FBytes",Tag,
+ [],no_length,?PRIMITIVE,
+ mandatory),
+ emit([nl,"end, []"]);
+ _ ->
+ case ObjFun of
+ [] ->
+ {DecFunName, _, _} =
+ mkfunname(TopType,Cname,WhatKind,dec,3),
+ emit([DecFunName,", ",{asis,Tag}]);
+ _ ->
+ {DecFunName, _, _} =
+ mkfunname(TopType,Cname,WhatKind,dec,4),
+ emit([DecFunName,", ",{asis,Tag},", ObjFun"])
+ end
+ end.
+
+
+gen_dec_line(Erules,TopType,Cname,CTags,Type,OptOrMand,DecObjInf) ->
+ BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
+ Tag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}
+ || X <- Type#type.tag],
+ InnerType =
+ case Type#type.def of
+ #'ObjectClassFieldType'{type=OCFTType} ->
+ OCFTType;
+ _ ->
+ asn1ct_gen:get_inner(Type#type.def)
+ end,
+ PostpDec =
+ case OptOrMand of
+ mandatory ->
+ gen_dec_call(InnerType,Erules,TopType,Cname,Type,
+ BytesVar,Tag,mandatory,", mandatory, ",
+ DecObjInf,OptOrMand);
+ _ -> %optional or default
+ case {CTags,Erules} of
+ {[CTag],ber_bin} ->
+ emit(["case ",{curr,bytes}," of",nl]),
+ emit([match_tag(Erules,CTag)," ->",nl]),
+ PostponedDec =
+ gen_dec_call(InnerType,Erules,TopType,Cname,Type,
+ BytesVar,Tag,mandatory,
+ ", opt_or_default, ",DecObjInf,
+ OptOrMand),
+ emit([";",nl]),
+ emit(["_ ->",nl]),
+ case OptOrMand of
+ {'DEFAULT', Def} ->
+ emit(["{",{asis,Def},",",
+ BytesVar,", 0 }",nl]);
+ 'OPTIONAL' ->
+ emit(["{ asn1_NOVALUE, ",
+ BytesVar,", 0 }",nl])
+ end,
+ emit("end"),
+ PostponedDec;
+ _ ->
+ emit("case (catch "),
+ PostponedDec =
+ gen_dec_call(InnerType,Erules,TopType,Cname,Type,
+ BytesVar,Tag,OptOrMand,
+ ", opt_or_default, ",DecObjInf,
+ OptOrMand),
+ emit([") of",nl]),
+ case OptOrMand of
+ {'DEFAULT', Def} ->
+ emit(["{'EXIT',{error,{asn1,{no_optional_tag,_}}}}",
+ " -> {",{asis,Def},",",
+ BytesVar,", 0 };",nl]);
+ 'OPTIONAL' ->
+ emit(["{'EXIT',{error,{asn1,{no_optional_tag,_}}}}",
+ " -> { asn1_NOVALUE, ",
+ BytesVar,", 0 };",nl])
+ end,
+ asn1ct_name:new(casetmp),
+ emit([{curr,casetmp},"-> ",{curr,casetmp},nl,"end"]),
+ PostponedDec
+ end
+ end,
+ case DecObjInf of
+ {Cname,ObjSet} -> % this must be the component were an object is
+ %% choosen from the object set according to the table
+ %% constraint.
+ {[{ObjSet,Cname,asn1ct_gen:mk_var(asn1ct_name:curr(term))}],
+ PostpDec};
+ _ -> {[],PostpDec}
+ end.
+
+
+gen_dec_call({typefield,_},Erules,_,_,Type,_,Tag,_,_,false,_) ->
+ %% this in case of a choice with typefield components
+ asn1ct_name:new(reason),
+ {FirstPFName,RestPFName} =
+% asn1ct_gen:get_constraint(Type#type.constraint,
+% tableconstraint_info),
+ (Type#type.def)#'ObjectClassFieldType'.fieldname,
+ emit([nl,indent(6),"begin",nl]),
+ emit([indent(9),"{OpenDec,TmpRest,TmpRbCho} =",nl,indent(12),
+ "?RT_BER:decode_open_type(",Erules,",",{curr,bytes},",",
+ {asis,Tag},"),",nl]),
+ emit([indent(9),"case (catch ObjFun(",{asis,FirstPFName},
+ ", OpenDec, [], ",{asis,RestPFName},
+ ")) of", nl]),%% ??? What about Tag
+ emit([indent(12),"{'EXIT',",{curr,reason},"} ->",nl]),
+%% emit({indent(15),"throw({runtime_error,{'Type not ",
+%% "compatible with tableconstraint', OpenDec}});",nl}),
+ emit([indent(15),"exit({'Type not ",
+ "compatible with table constraint', ",{curr,reason},"});",nl]),
+ emit([indent(12),"{TmpDec,_ ,_} ->",nl]),
+ emit([indent(15),"{TmpDec, TmpRest, TmpRbCho}",nl]),
+ emit([indent(9),"end",nl,indent(6),"end",nl]),
+ [];
+gen_dec_call({typefield,_},_Erules,_,Cname,Type,_BytesVar,Tag,_,_,
+ _DecObjInf,OptOrMandComp) ->
+ emit(["?RT_BER:decode_open_type(",{curr,bytes},",",{asis,Tag},")"]),
+ RefedFieldName =
+ (Type#type.def)#'ObjectClassFieldType'.fieldname,
+% asn1ct_gen:get_constraint(Type#type.constraint,
+% tableconstraint_info),
+ [{Cname,RefedFieldName,
+ asn1ct_gen:mk_var(asn1ct_name:curr(term)),
+% asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),[],OptOrMandComp}];
+ asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
+gen_dec_call({objectfield,PrimFieldName,PFNList},_Erules,_,Cname,_,_,Tag,_,_,_,
+ OptOrMandComp) ->
+ emit(["?RT_BER:decode_open_type(",{curr,bytes},",",{asis,Tag},")"]),
+ [{Cname,{PrimFieldName,PFNList},
+ asn1ct_gen:mk_var(asn1ct_name:curr(term)),
+% asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),[],OptOrMandComp}];
+ asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
+gen_dec_call(InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,PrimOptOrMand,
+ OptOrMand,DecObjInf,_) ->
+ WhatKind = asn1ct_gen:type(InnerType),
+ gen_dec_call1(WhatKind,InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,
+ PrimOptOrMand,OptOrMand),
+ case DecObjInf of
+ {Cname,{_,OSet,UniqueFName,ValIndex}} ->
+ Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
+ ValueMatch = value_match(ValIndex,Term),
+ emit({",",nl,"ObjFun = 'getdec_",OSet,"'(",
+% {asis,UniqueFName},", ",{curr,term},")"});
+ {asis,UniqueFName},", ",ValueMatch,")"});
+ _ ->
+ ok
+ end,
+ [].
+gen_dec_call1({primitive,bif},InnerType,Erules,_,_,Type,BytesVar,
+ Tag,OptOrMand,_) ->
+ case InnerType of
+ {fixedtypevaluefield,_,Btype} ->
+ asn1ct_gen_ber:gen_dec_prim(Erules,Btype,BytesVar,Tag,[],no_length,
+ ?PRIMITIVE,OptOrMand);
+ _ ->
+ asn1ct_gen_ber:gen_dec_prim(Erules,Type,BytesVar,Tag,[],no_length,
+ ?PRIMITIVE,OptOrMand)
+ end;
+gen_dec_call1('ASN1_OPEN_TYPE',_InnerType,Erules,_,_,Type,BytesVar,
+ Tag,OptOrMand,_) ->
+ asn1ct_gen_ber:gen_dec_prim(Erules,Type#type{def='ASN1_OPEN_TYPE'},
+ BytesVar,Tag,[],no_length,
+ ?PRIMITIVE,OptOrMand);
+gen_dec_call1(WhatKind,_,_Erules,TopType,Cname,Type,_,Tag,_,OptOrMand) ->
+ {DecFunName,_,_} =
+ mkfuncname(TopType,Cname,WhatKind,dec),
+ case {WhatKind,Type#type.tablecinf} of
+ {{constructed,bif},[{objfun,_}|_R]} ->
+ emit({DecFunName,"(",{curr,bytes},OptOrMand,{asis,Tag},", ObjFun)"});
+ _ ->
+ emit({DecFunName,"(",{curr,bytes},OptOrMand,{asis,Tag},")"})
+ end.
+
+
+%%------------------------------------------------------
+%% General and special help functions (not exported)
+%%------------------------------------------------------
+
+
+indent(N) ->
+ lists:duplicate(N,32). % 32 = space
+
+
+mkvlist([H,T1|T], Sep) -> % Sep is a string e.g ", " or "+ "
+ emit([{var,H},Sep]),
+ mkvlist([T1|T], Sep);
+mkvlist([H|T], Sep) ->
+ emit([{var,H}]),
+ mkvlist(T, Sep);
+mkvlist([], _) ->
+ true.
+
+mkvlist(L) ->
+ mkvlist(L,", ").
+
+mkvplus(L) ->
+ mkvlist(L," + ").
+
+extensible(CompList) when list(CompList) ->
+ noext;
+extensible({RootList,ExtList}) ->
+ {ext,length(RootList)+1,length(ExtList)}.
+
+
+print_attribute_comment(InnerType,Pos,Prop) ->
+ CommentLine = "%%-------------------------------------------------",
+ emit([nl,CommentLine]),
+ case InnerType of
+ {typereference,_,Name} ->
+ emit([nl,"%% attribute number ",Pos," with type ",Name]);
+ {'Externaltypereference',_,XModule,Name} ->
+ emit([nl,"%% attribute number ",Pos," External ",XModule,":",Name]);
+ _ ->
+ emit([nl,"%% attribute number ",Pos," with type ",InnerType])
+ end,
+ case Prop of
+ mandatory ->
+ continue;
+ {'DEFAULT', Def} ->
+ emit([" DEFAULT = ",{asis,Def}]);
+ 'OPTIONAL' ->
+ emit([" OPTIONAL"])
+ end,
+ emit([nl,CommentLine,nl]).
+
+
+mkfuncname(TopType,Cname,WhatKind,DecOrEnc) ->
+ CurrMod = get(currmod),
+ case WhatKind of
+ #'Externaltypereference'{module=CurrMod,type=EType} ->
+ F = lists:concat(["'",DecOrEnc,"_",EType,"'"]),
+ {F, "?MODULE", F};
+ #'Externaltypereference'{module=Mod,type=EType} ->
+ {lists:concat(["'",Mod,"':'",DecOrEnc,"_",EType,"'"]),Mod,
+ lists:concat(["'",DecOrEnc,"_",EType,"'"])};
+ {constructed,bif} ->
+ F = lists:concat(["'",DecOrEnc,"_",asn1ct_gen:list2name([Cname|TopType]),"'"]),
+ {F, "?MODULE", F}
+ end.
+
+mkfunname(TopType,Cname,WhatKind,DecOrEnc,Arity) ->
+ CurrMod = get(currmod),
+ case WhatKind of
+ #'Externaltypereference'{module=CurrMod,type=EType} ->
+ F = lists:concat(["fun '",DecOrEnc,"_",EType,"'/",Arity]),
+ {F, "?MODULE", F};
+ #'Externaltypereference'{module=Mod,type=EType} ->
+ {lists:concat(["{'",Mod,"','",DecOrEnc,"_",EType,"'}"]),Mod,
+ lists:concat(["'",DecOrEnc,"_",EType,"'"])};
+ {constructed,bif} ->
+ F =
+ lists:concat(["fun '",DecOrEnc,"_",
+ asn1ct_gen:list2name([Cname|TopType]),"'/",
+ Arity]),
+ {F, "?MODULE", F}
+ end.
+
+empty_lb(ber) ->
+ "[]";
+empty_lb(ber_bin) ->
+ "<<>>".
+
+rtmod(ber) ->
+ list_to_atom(?RT_BER);
+rtmod(ber_bin) ->
+ list_to_atom(?RT_BER_BIN).
+
+indefend_match(ber,used_var) ->
+ "[0,0|R]";
+indefend_match(ber,unused_var) ->
+ "[0,0|_R]";
+indefend_match(ber_bin,used_var) ->
+ "<<0,0,R/binary>>";
+indefend_match(ber_bin,unused_var) ->
+ "<<0,0,_R/binary>>".
+
+notice_value_match() ->
+ Module = get(currmod),
+ put(value_match,{true,Module}).
+
+value_match(Index,Value) when atom(Value) ->
+ value_match(Index,atom_to_list(Value));
+value_match([],Value) ->
+ Value;
+value_match([{VI,_Cname}|VIs],Value) ->
+ value_match1(Value,VIs,lists:concat(["element(",VI,","]),1).
+value_match1(Value,[],Acc,Depth) ->
+ Acc ++ Value ++ lists:concat(lists:duplicate(Depth,")"));
+value_match1(Value,[{VI,_Cname}|VIs],Acc,Depth) ->
+ value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_constructed_ber_bin_v2.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_constructed_ber_bin_v2.erl
new file mode 100644
index 0000000000..991240731e
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_constructed_ber_bin_v2.erl
@@ -0,0 +1,1357 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1ct_constructed_ber_bin_v2.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
+%%
+-module(asn1ct_constructed_ber_bin_v2).
+
+-export([gen_encode_sequence/3]).
+-export([gen_decode_sequence/3]).
+-export([gen_encode_set/3]).
+-export([gen_decode_set/3]).
+-export([gen_encode_sof/4]).
+-export([gen_decode_sof/4]).
+-export([gen_encode_choice/3]).
+-export([gen_decode_choice/3]).
+
+
+-include("asn1_records.hrl").
+
+-import(asn1ct_gen, [emit/1,demit/1]).
+-import(asn1ct_constructed_ber,[match_tag/2]).
+
+-define(ASN1CT_GEN_BER,asn1ct_gen_ber_bin_v2).
+
+% the encoding of class of tag bits 8 and 7
+-define(UNIVERSAL, 0).
+-define(APPLICATION, 16#40).
+-define(CONTEXT, 16#80).
+-define(PRIVATE, 16#C0).
+
+% primitive or constructed encoding % bit 6
+-define(PRIMITIVE, 0).
+-define(CONSTRUCTED, 2#00100000).
+
+
+
+
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+%% Encode/decode SEQUENCE (and SET)
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+
+gen_encode_sequence(Erules,Typename,D) when record(D,type) ->
+ asn1ct_name:start(),
+ asn1ct_name:new(term),
+ asn1ct_name:new(bytes),
+
+ %% if EXTERNAL type the input value must be transformed to
+ %% ASN1 1990 format
+ ValName =
+ case Typename of
+ ['EXTERNAL'] ->
+ emit([indent(4),
+ "NewVal = asn1rt_check:transform_to_EXTERNAL1990(Val),",
+ nl]),
+ "NewVal";
+ _ ->
+ "Val"
+ end,
+
+ {SeqOrSet,TableConsInfo,CompList} =
+ case D#type.def of
+ #'SEQUENCE'{tablecinf=TCI,components=CL} ->
+ {'SEQUENCE',TCI,CL};
+ #'SET'{tablecinf=TCI,components=CL} ->
+ {'SET',TCI,CL}
+ end,
+ Ext = extensible(CompList),
+ CompList1 = case CompList of
+ {Rl,El} -> Rl ++ El;
+ _ -> CompList
+ end,
+
+%% don't match recordname for now, because of compatibility reasons
+%% emit(["{'",asn1ct_gen:list2rname(Typename),"'"]),
+ emit(["{_"]),
+ case length(CompList1) of
+ 0 ->
+ true;
+ CompListLen ->
+ emit([","]),
+ mkcindexlist([Tc || Tc <- lists:seq(1,CompListLen)])
+ end,
+ emit(["} = ",ValName,",",nl]),
+ EncObj =
+ case TableConsInfo of
+ #simpletableattributes{usedclassfield=Used,
+ uniqueclassfield=Unique} when Used /= Unique ->
+ false;
+ %% ObjectSet, name of the object set in constraints
+ %%
+ #simpletableattributes{objectsetname=ObjectSet,
+ c_name=AttrN,
+ c_index=N,
+ usedclassfield=UniqueFieldName,
+ uniqueclassfield=UniqueFieldName,
+ valueindex=ValueIndex} -> %% N is index of attribute that determines constraint
+ OSDef =
+ case ObjectSet of
+ {Module,OSName} ->
+ asn1_db:dbget(Module,OSName);
+ OSName ->
+ asn1_db:dbget(get(currmod),OSName)
+ end,
+% io:format("currmod: ~p~nOSName: ~p~nAttrN: ~p~nN: ~p~nUniqueFieldName: ~p~n",
+% [get(currmod),OSName,AttrN,N,UniqueFieldName]),
+ case (OSDef#typedef.typespec)#'ObjectSet'.gen of
+ true ->
+ ObjectEncode =
+ asn1ct_gen:un_hyphen_var(lists:concat(['Obj',
+ AttrN])),
+ emit([ObjectEncode," = ",nl]),
+ emit([" 'getenc_",ObjectSet,"'(",{asis,UniqueFieldName},
+ ", ",nl]),
+ ValueMatch = value_match(ValueIndex,
+ lists:concat(["Cindex",N])),
+ emit([indent(35),ValueMatch,"),",nl]),
+ {AttrN,ObjectEncode};
+ _ ->
+ false
+ end;
+ _ ->
+ case D#type.tablecinf of
+ [{objfun,_}|_] ->
+ %% when the simpletableattributes was at an outer
+ %% level and the objfun has been passed through the
+ %% function call
+ {"got objfun through args","ObjFun"};
+ _ ->
+ false
+ end
+ end,
+
+ gen_enc_sequence_call(Erules,Typename,CompList1,1,Ext,EncObj),
+
+ emit([nl," BytesSoFar = "]),
+ case SeqOrSet of
+ 'SET' when (D#type.def)#'SET'.sorted == dynamic ->
+ emit("?RT_BER:dynamicsort_SET_components(["),
+ mkvlist(asn1ct_name:all(encBytes)),
+ emit(["]),",nl]);
+ _ ->
+ emit("["),
+ mkvlist(asn1ct_name:all(encBytes)),
+ emit(["],",nl])
+ end,
+ emit("LenSoFar = "),
+ case asn1ct_name:all(encLen) of
+ [] -> emit("0");
+ AllLengths ->
+ mkvplus(AllLengths)
+ end,
+ emit([",",nl]),
+ emit(["?RT_BER:encode_tags(TagIn, BytesSoFar, LenSoFar)."
+ ,nl]).
+
+gen_decode_sequence(Erules,Typename,D) when record(D,type) ->
+ asn1ct_name:start(),
+ asn1ct_name:new(tag),
+ #'SEQUENCE'{tablecinf=TableConsInfo,components=CList} = D#type.def,
+ Ext = extensible(CList),
+ CompList = case CList of
+ {Rl,El} -> Rl ++ El;
+ _ -> CList
+ end,
+
+ emit([" %%-------------------------------------------------",nl]),
+ emit([" %% decode tag and length ",nl]),
+ emit([" %%-------------------------------------------------",nl]),
+
+ asn1ct_name:new(tlv),
+ case CompList of
+ EmptyCL when EmptyCL == [];EmptyCL == {[],[]}-> % empty sequence
+ true;
+ _ ->
+ emit([{curr,tlv}," = "])
+ end,
+ emit(["?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
+ asn1ct_name:new(tlv),
+ asn1ct_name:new(v),
+
+ {DecObjInf,UniqueFName,ValueIndex} =
+ case TableConsInfo of
+ #simpletableattributes{objectsetname=ObjectSet,
+ c_name=AttrN,
+ usedclassfield=UniqueFieldName,
+ uniqueclassfield=UniqueFieldName,
+ valueindex=ValIndex} ->
+% {ObjectSet,AttrN,_N,UniqueFieldName} ->%% N is index of attribute that determines constraint
+ F = fun(#'ComponentType'{typespec=CT})->
+ case {CT#type.constraint,CT#type.tablecinf} of
+ {[],[{objfun,_}|_]} -> true;
+ _ -> false
+ end
+ end,
+ case lists:any(F,CompList) of
+ true -> % when component relation constraint establish
+ %% relation from a component to another components
+ %% subtype component
+ {{AttrN,{deep,ObjectSet,UniqueFieldName,ValIndex}},
+ UniqueFieldName,ValIndex};
+ false ->
+ {{AttrN,ObjectSet},UniqueFieldName,ValIndex}
+ end;
+ _ ->
+% case D#type.tablecinf of
+% [{objfun,_}|_] ->
+% {{"got objfun through args","ObjFun"},false,false};
+% _ ->
+ {false,false,false}
+% end
+ end,
+ case gen_dec_sequence_call(Erules,Typename,CompList,Ext,DecObjInf) of
+ no_terms -> % an empty sequence
+ emit([nl,nl]),
+ demit(["Result = "]), %dbg
+ %% return value as record
+ asn1ct_name:new(rb),
+ emit([" {'",asn1ct_gen:list2rname(Typename),"'}.",nl,nl]);
+ {LeadingAttrTerm,PostponedDecArgs} ->
+ emit([com,nl,nl]),
+ case {LeadingAttrTerm,PostponedDecArgs} of
+ {[],[]} ->
+ ok;
+ {_,[]} ->
+ ok;
+ {[{ObjSet,LeadingAttr,Term}],PostponedDecArgs} ->
+ DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])),
+ ValueMatch = value_match(ValueIndex,Term),
+ emit([DecObj," =",nl," 'getdec_",ObjSet,"'(",
+ {asis,UniqueFName},", ",ValueMatch,"),",nl]),
+ gen_dec_postponed_decs(DecObj,PostponedDecArgs)
+ end,
+ demit(["Result = "]), %dbg
+ %% return value as record
+ case Ext of
+ {ext,_,_} ->
+ emit(["case ",{prev,tlv}," of [] -> true; _ -> true end, % ... extra fields skipped",nl]);
+ noext ->
+ emit(["case ",{prev,tlv}," of",nl,
+ "[] -> true;",
+ "_ -> exit({error,{asn1, {unexpected,",{prev,tlv},
+ "}}}) % extra fields not allowed",nl,
+ "end,",nl])
+ end,
+ asn1ct_name:new(rb),
+ case Typename of
+ ['EXTERNAL'] ->
+ emit([" OldFormat={'",asn1ct_gen:list2rname(Typename),
+ "', "]),
+ mkvlist(asn1ct_name:all(term)),
+ emit(["},",nl]),
+ emit([" asn1rt_check:transform_to_EXTERNAL1994",
+ "(OldFormat).",nl]);
+ _ ->
+ emit([" {'",asn1ct_gen:list2rname(Typename),"', "]),
+ mkvlist(asn1ct_name:all(term)),
+ emit(["}.",nl,nl])
+ end
+ end.
+
+gen_dec_postponed_decs(_,[]) ->
+ emit(nl);
+gen_dec_postponed_decs(DecObj,[{_Cname,{FirstPFN,PFNList},Term,
+ TmpTerm,_Tag,OptOrMand}|Rest]) ->
+
+ asn1ct_name:new(tmpterm),
+ asn1ct_name:new(reason),
+ asn1ct_name:new(tmptlv),
+
+ emit([Term," = ",nl]),
+ N = case OptOrMand of
+ mandatory -> 0;
+ 'OPTIONAL' ->
+ emit_opt_or_mand_check(asn1_NOVALUE,TmpTerm),
+ 6;
+ {'DEFAULT',Val} ->
+ emit_opt_or_mand_check(Val,TmpTerm),
+ 6
+ end,
+ emit([indent(N+3),"case (catch ",DecObj,"(",{asis,FirstPFN},
+ ", ",TmpTerm,", ",{asis,PFNList},")) of",nl]),
+ emit([indent(N+6),"{'EXIT', ",{curr,reason},"} ->",nl]),
+ emit([indent(N+9),"exit({'Type not compatible with table constraint',",
+ {curr,reason},"});",nl]),
+ emit([indent(N+6),{curr,tmpterm}," ->",nl]),
+ emit([indent(N+9),{curr,tmpterm},nl]),
+
+ case OptOrMand of
+ mandatory -> emit([indent(N+3),"end,",nl]);
+ _ ->
+ emit([indent(N+3),"end",nl,
+ indent(3),"end,",nl])
+ end,
+ gen_dec_postponed_decs(DecObj,Rest).
+
+emit_opt_or_mand_check(Value,TmpTerm) ->
+ emit([indent(3),"case ",TmpTerm," of",nl,
+ indent(6),{asis,Value}," ->",{asis,Value},";",nl,
+ indent(6),"_ ->",nl]).
+
+%%============================================================================
+%% Encode/decode SET
+%%
+%%============================================================================
+
+gen_encode_set(Erules,Typename,D) when record(D,type) ->
+ gen_encode_sequence(Erules,Typename,D).
+
+gen_decode_set(Erules,Typename,D) when record(D,type) ->
+ asn1ct_name:start(),
+ asn1ct_name:new(term),
+ asn1ct_name:new(tag),
+ #'SET'{tablecinf=TableConsInfo,components=TCompList} = D#type.def,
+ Ext = extensible(TCompList),
+ CompList = case TCompList of
+ {Rl,El} -> Rl ++ El;
+ _ -> TCompList
+ end,
+
+ asn1ct_name:clear(),
+ asn1ct_name:new(tlv),
+ case CompList of
+ EmptyCL when EmptyCL == [];EmptyCL == {[],[]}-> % empty sequence
+ true;
+ _ ->
+ emit([{curr,tlv}," = "])
+ end,
+ emit(["?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
+ asn1ct_name:new(v),
+
+
+ {DecObjInf,UniqueFName} =
+ case TableConsInfo of
+ {ObjectSet,AttrN,_N,UniqueFieldName} ->%% N is index of attribute that determines constraint
+ F = fun(#'ComponentType'{typespec=CT})->
+ case {CT#type.constraint,CT#type.tablecinf} of
+ {[],[{objfun,_}|_]} -> true;
+ _ -> false
+ end
+ end,
+ case lists:any(F,CompList) of
+ true -> % when component relation constraint establish
+ %% relation from a component to another components
+ %% subtype component
+ {{AttrN,{deep,ObjectSet,UniqueFieldName}},
+ UniqueFieldName};
+ false ->
+ {{AttrN,ObjectSet},UniqueFieldName}
+ end;
+ _ ->
+ {false,false}
+ end,
+
+ case CompList of
+ [] -> % empty set
+ true;
+ _ ->
+ emit(["SetFun = fun(FunTlv) ->", nl]),
+ emit(["case FunTlv of ",nl]),
+ NextNum = gen_dec_set_cases(Erules,Typename,CompList,1),
+ emit([indent(6), {curr,else}," -> ",nl,
+ indent(9),"{",NextNum,", ",{curr,else},"}",nl]),
+ emit([indent(3),"end",nl]),
+ emit([indent(3),"end,",nl]),
+
+ emit(["PositionList = [SetFun(TempTlv)|| TempTlv <- ",{curr,tlv},"],",nl]),
+ asn1ct_name:new(tlv),
+ emit([{curr,tlv}," = [Stlv || {_,Stlv} <- lists:sort(PositionList)],",nl]),
+ asn1ct_name:new(tlv)
+
+ end,
+ case gen_dec_sequence_call(Erules,Typename,CompList,Ext,DecObjInf) of
+ no_terms -> % an empty sequence
+ emit([nl,nl]),
+ demit(["Result = "]), %dbg
+ %% return value as record
+ emit([" {'",asn1ct_gen:list2rname(Typename),"'}.",nl]);
+ {LeadingAttrTerm,PostponedDecArgs} ->
+ emit([com,nl,nl]),
+ case {LeadingAttrTerm,PostponedDecArgs} of
+ {[],[]} ->
+ ok;
+ {_,[]} ->
+ ok;
+ {[{ObjSet,LeadingAttr,Term}],PostponedDecArgs} ->
+ DecObj = lists:concat(['DecObj',LeadingAttr,Term]),
+ emit([DecObj," =",nl," 'getdec_",ObjSet,"'(",
+ {asis,UniqueFName},", ",Term,"),",nl]),
+ gen_dec_postponed_decs(DecObj,PostponedDecArgs)
+ end,
+ demit(["Result = "]), %dbg
+ %% return value as record
+ case Ext of
+ {ext,_,_} ->
+ emit(["case ",{prev,tlv}," of [] -> true; _ -> true end, % ... extra fields skipped",nl]);
+ noext ->
+ emit(["case ",{prev,tlv}," of",nl,
+ "[] -> true;",
+ "_ -> exit({error,{asn1, {unexpected,",{prev,tlv},
+ "}}}) % extra fields not allowed",nl,
+ "end,",nl])
+ end,
+ emit([" {'",asn1ct_gen:list2rname(Typename),"', "]),
+ mkvlist(asn1ct_name:all(term)),
+ emit(["}.",nl])
+ end.
+
+
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+%% Encode/decode SEQUENCE OF and SET OF
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+
+gen_encode_sof(Erules,Typename,_InnerTypename,D) when record(D,type) ->
+ asn1ct_name:start(),
+ {SeqOrSetOf, Cont} = D#type.def,
+
+ Objfun = case D#type.tablecinf of
+ [{objfun,_}|_R] ->
+ ", ObjFun";
+ _ ->
+ ""
+ end,
+
+ emit([" {EncBytes,EncLen} = 'enc_",asn1ct_gen:list2name(Typename),
+ "_components'(Val",Objfun,",[],0),",nl]),
+
+ emit([" ?RT_BER:encode_tags(TagIn, EncBytes, EncLen).",nl,nl]),
+
+ gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont).
+
+
+gen_decode_sof(Erules,TypeName,_InnerTypeName,D) when record(D,type) ->
+ asn1ct_name:start(),
+ {SeqOrSetOf, _TypeTag, Cont} =
+ case D#type.def of
+ {'SET OF',_Cont} -> {'SET OF','SET',_Cont};
+ {'SEQUENCE OF',_Cont} -> {'SEQUENCE OF','SEQUENCE',_Cont}
+ end,
+ TypeNameSuffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,Cont#type.def),
+
+ emit([" %%-------------------------------------------------",nl]),
+ emit([" %% decode tag and length ",nl]),
+ emit([" %%-------------------------------------------------",nl]),
+
+ asn1ct_name:new(tlv),
+ emit([{curr,tlv},
+ " = ?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
+ asn1ct_name:new(v),
+
+ emit(["["]),
+
+ InnerType = asn1ct_gen:get_inner(Cont#type.def),
+ ContName = case asn1ct_gen:type(InnerType) of
+ Atom when atom(Atom) -> Atom;
+ _ -> TypeNameSuffix
+ end,
+%% fix me
+ ObjFun =
+ case D#type.tablecinf of
+ [{objfun,_}|_R] ->
+ ", ObjFun";
+ _ ->
+ []
+ end,
+ gen_dec_line(Erules,TypeName,ContName,[],Cont,mandatory,ObjFun),
+ %% gen_dec_line_sof(Erules,Typename,ContName,Cont,ObjFun),
+ emit([" || ",{curr,v}," <- ",{curr,tlv},"].",nl,nl,nl]).
+
+
+gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont)
+ when record(Cont,type)->
+
+ {Objfun,Objfun_novar,EncObj} =
+ case Cont#type.tablecinf of
+ [{objfun,_}|_R] ->
+ {", ObjFun",", _",{no_attr,"ObjFun"}};
+ _ ->
+ {"","",false}
+ end,
+ emit(["'enc_",asn1ct_gen:list2name(Typename),
+ "_components'([]",Objfun_novar,", AccBytes, AccLen) -> ",nl]),
+
+ case catch lists:member(der,get(encoding_options)) of
+ true ->
+ emit([indent(3),
+ "{?RT_BER:dynamicsort_SETOF(AccBytes),AccLen};",nl,nl]);
+ _ ->
+ emit([indent(3),"{lists:reverse(AccBytes),AccLen};",nl,nl])
+ end,
+ emit(["'enc_",asn1ct_gen:list2name(Typename),
+ "_components'([H|T]",Objfun,",AccBytes, AccLen) ->",nl]),
+ TypeNameSuffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,Cont#type.def),
+ gen_enc_line(Erules,Typename,TypeNameSuffix,Cont,"H",3,
+ mandatory,"{EncBytes,EncLen} = ",EncObj),
+ emit([",",nl]),
+ emit([indent(3),"'enc_",asn1ct_gen:list2name(Typename),
+ "_components'(T",Objfun,","]),
+ emit(["[EncBytes|AccBytes], AccLen + EncLen).",nl,nl]).
+
+%%============================================================================
+%% Encode/decode CHOICE
+%%
+%%============================================================================
+
+gen_encode_choice(Erules,Typename,D) when record(D,type) ->
+ ChoiceTag = D#type.tag,
+ {'CHOICE',CompList} = D#type.def,
+ Ext = extensible(CompList),
+ CompList1 = case CompList of
+ {Rl,El} -> Rl ++ El;
+ _ -> CompList
+ end,
+ gen_enc_choice(Erules,Typename,ChoiceTag,CompList1,Ext),
+ emit([nl,nl]).
+
+gen_decode_choice(Erules,Typename,D) when record(D,type) ->
+ asn1ct_name:start(),
+ asn1ct_name:new(bytes),
+ ChoiceTag = D#type.tag,
+ {'CHOICE',CompList} = D#type.def,
+ Ext = extensible(CompList),
+ CompList1 = case CompList of
+ {Rl,El} -> Rl ++ El;
+ _ -> CompList
+ end,
+ gen_dec_choice(Erules,Typename,ChoiceTag,CompList1,Ext),
+ emit([".",nl]).
+
+
+%%============================================================================
+%% Encode SEQUENCE
+%%
+%%============================================================================
+
+gen_enc_sequence_call(Erules,TopType,[#'ComponentType'{name=Cname,typespec=Type,prop=Prop}|Rest],Pos,Ext,EncObj) ->
+ asn1ct_name:new(encBytes),
+ asn1ct_name:new(encLen),
+ Element =
+ case TopType of
+ ['EXTERNAL'] ->
+ io_lib:format("Cindex~w",[Pos]);
+ _ ->
+ io_lib:format("Cindex~w",[Pos])
+ end,
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ print_attribute_comment(InnerType,Pos,Cname,Prop),
+ gen_enc_line(Erules,TopType,Cname,Type,Element,3,Prop,EncObj),
+ emit([com,nl]),
+ gen_enc_sequence_call(Erules,TopType,Rest,Pos+1,Ext,EncObj);
+
+gen_enc_sequence_call(_Erules,_TopType,[],_Num,_,_) ->
+ true.
+
+%%============================================================================
+%% Decode SEQUENCE
+%%
+%%============================================================================
+
+gen_dec_sequence_call(Erules,TopType,CompList,Ext,DecObjInf) ->
+ gen_dec_sequence_call1(Erules,TopType, CompList, 1, Ext,DecObjInf,[],[]).
+
+
+gen_dec_sequence_call1(Erules,TopType,[#'ComponentType'{name=Cname,typespec=Type,prop=Prop,tags=Tags}|Rest],Num,Ext,DecObjInf,LeadingAttrAcc,ArgsAcc) ->
+ {LA,PostponedDec} =
+ gen_dec_component(Erules,TopType,Cname,Tags,Type,Num,Prop,
+ Ext,DecObjInf),
+ case Rest of
+ [] ->
+ {LA ++ LeadingAttrAcc,PostponedDec ++ ArgsAcc};
+ _ ->
+ emit([com,nl]),
+ asn1ct_name:new(bytes),
+ gen_dec_sequence_call1(Erules,TopType,Rest,Num+1,Ext,DecObjInf,
+ LA++LeadingAttrAcc,PostponedDec++ArgsAcc)
+ end;
+
+gen_dec_sequence_call1(_Erules,_TopType,[],1,_,_,_,_) ->
+ no_terms.
+
+
+%%----------------------------
+%%SEQUENCE mandatory
+%%----------------------------
+
+gen_dec_component(Erules,TopType,Cname,CTags,Type,Pos,Prop,Ext,DecObjInf) ->
+ InnerType =
+ case Type#type.def of
+ #'ObjectClassFieldType'{type=OCFTType} -> OCFTType;
+ _ -> asn1ct_gen:get_inner(Type#type.def)
+ end,
+% case asn1ct_gen:get_constraint(Type#type.constraint,
+% tableconstraint_info) of
+% no ->
+% asn1ct_gen:get_inner(Type#type.def);
+% _ ->
+% Type#type.def
+% end,
+ Prop1 = case {Prop,Ext} of
+ {mandatory,{ext,Epos,_}} when Pos >= Epos ->
+ 'OPTIONAL';
+ _ ->
+ Prop
+ end,
+ print_attribute_comment(InnerType,Pos,Cname,Prop1),
+ asn1ct_name:new(term),
+ emit_term_tlv(Prop1,InnerType,DecObjInf),
+ asn1ct_name:new(rb),
+ PostponedDec =
+ gen_dec_line(Erules,TopType,Cname,CTags,Type,Prop1,DecObjInf),
+ asn1ct_name:new(v),
+ asn1ct_name:new(tlv),
+ asn1ct_name:new(form),
+ PostponedDec.
+
+
+emit_term_tlv({'DEFAULT',_},InnerType,DecObjInf) ->
+ emit_term_tlv(opt_or_def,InnerType,DecObjInf);
+emit_term_tlv('OPTIONAL',InnerType,DecObjInf) ->
+ emit_term_tlv(opt_or_def,InnerType,DecObjInf);
+emit_term_tlv(Prop,{typefield,_},DecObjInf) ->
+ emit_term_tlv(Prop,type_or_object_field,DecObjInf);
+emit_term_tlv(Prop,{objectfield,_,_},DecObjInf) ->
+ emit_term_tlv(Prop,type_or_object_field,DecObjInf);
+emit_term_tlv(opt_or_def,type_or_object_field,_) ->
+ asn1ct_name:new(tmpterm),
+ emit(["{",{curr,tmpterm},",",{curr,tlv},"} = "]);
+emit_term_tlv(opt_or_def,_,_) ->
+ emit(["{",{curr,term},",",{curr,tlv},"} = "]);
+emit_term_tlv(_,type_or_object_field,false) ->
+ emit(["[",{curr,v},"|",{curr,tlv},"] = ",{prev,tlv},", ",nl,
+ {curr,term}," = "]);
+emit_term_tlv(_,type_or_object_field,_) ->
+ asn1ct_name:new(tmpterm),
+ emit(["[",{curr,v},"|",{curr,tlv},"] = ",{prev,tlv},", ",nl]),
+ emit([nl," ",{curr,tmpterm}," = "]);
+emit_term_tlv(mandatory,_,_) ->
+ emit(["[",{curr,v},"|",{curr,tlv},"] = ",{prev,tlv},", ",nl,
+ {curr,term}," = "]).
+
+
+gen_dec_set_cases(_Erules,_TopType,[],Pos) ->
+ Pos;
+gen_dec_set_cases(Erules,TopType,[Comp|RestComps],Pos) ->
+ Name = Comp#'ComponentType'.name,
+ Type = Comp#'ComponentType'.typespec,
+ CTags = Comp#'ComponentType'.tags,
+
+ emit([indent(6),"%",Name,nl]),
+ Tags = case Type#type.tag of
+ [] -> % this is a choice without explicit tag
+ [(?ASN1CT_GEN_BER:decode_class(T1class) bsl 10) + T1number||
+ {T1class,T1number} <- CTags];
+ [FirstTag|_] ->
+ [(?ASN1CT_GEN_BER:decode_class(FirstTag#tag.class) bsl 10) + FirstTag#tag.number]
+ end,
+% emit([indent(6),"%Tags: ",Tags,nl]),
+% emit([indent(6),"%Type#type.tag: ",Type#type.tag,nl]),
+ CaseFun = fun(TagList=[H|T],Fun,N) ->
+ Semicolon = case TagList of
+ [_Tag1,_|_] -> [";",nl];
+ _ -> ""
+ end,
+ emit(["TTlv = {",H,",_} ->",nl]),
+ emit([indent(4),"{",Pos,", TTlv}",Semicolon]),
+ Fun(T,Fun,N+1);
+ ([],_,0) ->
+ true;
+ ([],_,_) ->
+ emit([";",nl])
+ end,
+ CaseFun(Tags,CaseFun,0),
+%% emit([";",nl]),
+ gen_dec_set_cases(Erules,TopType,RestComps,Pos+1).
+
+
+
+%%---------------------------------------------
+%% Encode CHOICE
+%%---------------------------------------------
+%% for BER we currently do care (a little) if the choice has an EXTENSIONMARKER
+
+
+gen_enc_choice(Erules,TopType,Tag,CompList,_Ext) ->
+ gen_enc_choice1(Erules,TopType,Tag,CompList,_Ext).
+
+gen_enc_choice1(Erules,TopType,_Tag,CompList,_Ext) ->
+ asn1ct_name:clear(),
+ emit([" {EncBytes,EncLen} = case element(1,Val) of",nl]),
+ gen_enc_choice2(Erules,TopType,CompList),
+ emit([nl," end,",nl,nl]),
+
+ emit(["?RT_BER:encode_tags(TagIn, EncBytes, EncLen).",nl]).
+
+
+gen_enc_choice2(Erules,TopType,[H1|T]) when record(H1,'ComponentType') ->
+ Cname = H1#'ComponentType'.name,
+ Type = H1#'ComponentType'.typespec,
+ emit([" ",{asis,Cname}," ->",nl]),
+ {Encobj,Assign} =
+ case {Type#type.def,asn1ct_gen:get_constraint(Type#type.constraint,
+ componentrelation)} of
+ {#'ObjectClassFieldType'{},{componentrelation,_,_}} ->
+ asn1ct_name:new(tmpBytes),
+ asn1ct_name:new(encBytes),
+ asn1ct_name:new(encLen),
+ Emit = ["{",{curr,tmpBytes},", _} = "],
+ {{no_attr,"ObjFun"},Emit};
+ _ ->
+ {false,[]}
+ end,
+% case asn1ct_gen:get_constraint(Type#type.constraint,
+% tableconstraint_info) of
+% no ->
+% {false,[]};
+% _ ->
+% asn1ct_name:new(tmpBytes),
+% asn1ct_name:new(encBytes),
+% asn1ct_name:new(encLen),
+% Emit = ["{",{curr,tmpBytes},", _} = "],
+% {{no_attr,"ObjFun"},Emit}
+% end,
+ gen_enc_line(Erules,TopType,Cname,Type,"element(2,Val)",9,
+ mandatory,Assign,Encobj),
+ case Encobj of
+ false -> ok;
+ _ ->
+ emit([",",nl,indent(9),"{",{curr,encBytes},", ",
+ {curr,encLen},"}"])
+ end,
+ emit([";",nl]),
+ case T of
+ [] ->
+ emit([indent(6), "Else -> ",nl,
+ indent(9),"exit({error,{asn1,{invalid_choice_type,Else}}})"]);
+ _ ->
+ true
+ end,
+ gen_enc_choice2(Erules,TopType,T);
+
+gen_enc_choice2(_Erules,_TopType,[]) ->
+ true.
+
+
+
+
+%%--------------------------------------------
+%% Decode CHOICE
+%%--------------------------------------------
+
+gen_dec_choice(Erules,TopType, _ChTag, CompList, Ext) ->
+ asn1ct_name:clear(),
+ asn1ct_name:new(tlv),
+ emit([{curr,tlv},
+ " = ?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
+ asn1ct_name:new(tlv),
+ asn1ct_name:new(v),
+ emit(["case (case ",{prev,tlv},
+ " of [Ctemp",{prev,tlv},"] -> Ctemp",{prev,tlv},
+ "; _ -> ",{prev,tlv}," end)"," of",nl]),
+ asn1ct_name:new(tagList),
+ asn1ct_name:new(choTags),
+ asn1ct_name:new(res),
+ gen_dec_choice_cases(Erules,TopType,CompList),
+ emit([indent(6), {curr,else}," -> ",nl]),
+ case Ext of
+ noext ->
+ emit([indent(9),"exit({error,{asn1,{invalid_choice_tag,",
+ {curr,else},"}}})",nl]);
+ _ ->
+ emit([indent(9),"{asn1_ExtAlt, ?RT_BER:encode(",{curr,else},")}",nl])
+ end,
+ emit([indent(3),"end",nl]),
+ asn1ct_name:new(tag),
+ asn1ct_name:new(else).
+
+
+gen_dec_choice_cases(_Erules,_TopType, []) ->
+ ok;
+gen_dec_choice_cases(Erules,TopType, [H|T]) ->
+ Cname = H#'ComponentType'.name,
+ Type = H#'ComponentType'.typespec,
+ Prop = H#'ComponentType'.prop,
+ Tags = Type#type.tag,
+ Fcases = fun([{T1class,T1number}|Tail],Fun) ->
+ emit([indent(4),{curr,v}," = {",
+ (?ASN1CT_GEN_BER:decode_class(T1class) bsl 10) +
+ T1number,",_} -> ",nl]),
+ emit([indent(8),"{",{asis,Cname},", "]),
+ gen_dec_line(Erules,TopType,Cname,[],Type,Prop,false),
+ emit(["};",nl,nl]),
+ Fun(Tail,Fun);
+ ([],_) ->
+ ok
+ end,
+ emit([nl,"%% '",Cname,"'",nl]),
+ case {Tags,asn1ct:get_gen_state_field(namelist)} of
+ {[],_} -> % choice without explicit tags
+ Fcases(H#'ComponentType'.tags,Fcases);
+ {[FirstT|_RestT],[{Cname,undecoded}|Names]} ->
+ DecTag=(?ASN1CT_GEN_BER:decode_class(FirstT#tag.class) bsl 10) +
+ FirstT#tag.number,
+ asn1ct:add_generated_refed_func({[Cname|TopType],undecoded,
+ [DecTag],Type}),
+ asn1ct:update_gen_state(namelist,Names),
+ emit([indent(4),{curr,res}," = ",
+ match_tag(ber_bin,{FirstT#tag.class,FirstT#tag.number}),
+ " -> ",nl]),
+ emit([indent(8),"{",{asis,Cname},", {'",
+ asn1ct_gen:list2name([Cname|TopType]),"',",
+ {curr,res},"}};",nl,nl]);
+ {[FirstT|RestT],_} ->
+ emit([indent(4),"{",
+ (?ASN1CT_GEN_BER:decode_class(FirstT#tag.class) bsl 10) +
+ FirstT#tag.number,", ",{curr,v},"} -> ",nl]),
+ emit([indent(8),"{",{asis,Cname},", "]),
+ gen_dec_line(Erules,TopType,Cname,[],Type#type{tag=RestT},Prop,false),
+ emit(["};",nl,nl])
+ end,
+ gen_dec_choice_cases(Erules,TopType, T).
+
+
+
+%%---------------------------------------
+%% Generate the encode/decode code
+%%---------------------------------------
+
+gen_enc_line(Erules,TopType,Cname,
+ Type=#type{constraint=[{componentrelation,_,_}],
+ def=#'ObjectClassFieldType'{type={typefield,_}}},
+ Element,Indent,OptOrMand=mandatory,EncObj)
+ when list(Element) ->
+ asn1ct_name:new(tmpBytes),
+ gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,
+ ["{",{curr,tmpBytes},",_} = "],EncObj);
+gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,EncObj)
+ when list(Element) ->
+ gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,
+ ["{",{curr,encBytes},",",{curr,encLen},"} = "],EncObj).
+
+gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,Assign,EncObj)
+ when list(Element) ->
+ IndDeep = indent(Indent),
+ Tag = lists:reverse([?ASN1CT_GEN_BER:encode_tag_val(
+ ?ASN1CT_GEN_BER:decode_class(X#tag.class),
+ X#tag.form,
+ X#tag.number)
+ || X <- Type#type.tag]),
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ WhatKind = asn1ct_gen:type(InnerType),
+ emit(IndDeep),
+ emit(Assign),
+ gen_optormand_case(OptOrMand,Erules,TopType,Cname,Type,InnerType,WhatKind,
+ Element),
+ case {Type,asn1ct_gen:get_constraint(Type#type.constraint,
+ componentrelation)} of
+% #type{constraint=[{tableconstraint_info,RefedFieldName}],
+% def={typefield,_}} ->
+ {#type{def=#'ObjectClassFieldType'{type={typefield,_},
+ fieldname=RefedFieldName}},
+ {componentrelation,_,_}} ->
+ {_LeadingAttrName,Fun} = EncObj,
+ case RefedFieldName of
+ {notype,T} ->
+ throw({error,{notype,type_from_object,T}});
+ {Name,RestFieldNames} when atom(Name) ->
+ case OptOrMand of
+ mandatory -> ok;
+ _ ->
+% emit(["{",{curr,tmpBytes},",",{curr,tmpLen},
+ emit(["{",{curr,tmpBytes},",_ } = "])
+% "} = "])
+ end,
+ emit([Fun,"(",{asis,Name},", ",Element,", ",
+ {asis,RestFieldNames},"),",nl]),
+ emit(IndDeep),
+ case OptOrMand of
+ mandatory ->
+ emit(["{",{curr,encBytes},",",{curr,encLen},
+ "} = "]),
+ emit(["?RT_BER:encode_open_type(",{curr,tmpBytes},
+ ",",{asis,Tag},")"]);
+ _ ->
+% emit(["{",{next,tmpBytes},", _} = "]),
+ emit(["{",{next,tmpBytes},",",{curr,tmpLen},
+ "} = "]),
+ emit(["?RT_BER:encode_open_type(",{curr,tmpBytes},
+ ",",{asis,Tag},"),",nl]),
+ emit(IndDeep),
+ emit(["{",{next,tmpBytes},", ",{curr,tmpLen},"}"])
+ end;
+ _ ->
+ throw({asn1,{'internal error'}})
+ end;
+ {{#'ObjectClassFieldType'{type={objectfield,PrimFieldName1,
+ PFNList}},_},
+ {componentrelation,_,_}} ->
+ %% this is when the dotted list in the FieldName has more
+ %% than one element
+ {_LeadingAttrName,Fun} = EncObj,
+ emit(["?RT_BER:encode_open_type(",Fun,"(",{asis,PrimFieldName1},
+ ", ",Element,", ",{asis,PFNList},"))"]);
+ _ ->
+ case WhatKind of
+ {primitive,bif} ->
+ EncType =
+ case Type#type.def of
+ #'ObjectClassFieldType'{type={fixedtypevaluefield,_,Btype}} ->
+ Btype;
+ _ ->
+ Type
+ end,
+ ?ASN1CT_GEN_BER:gen_encode_prim(ber,EncType,{asis,Tag},
+ Element);
+ {notype,_} ->
+ emit(["'enc_",InnerType,"'(",Element,", ",{asis,Tag},")"]);
+ 'ASN1_OPEN_TYPE' ->
+ case Type#type.def of
+ #'ObjectClassFieldType'{} -> %Open Type
+ ?ASN1CT_GEN_BER:gen_encode_prim(ber,#type{def='ASN1_OPEN_TYPE'},{asis,Tag},Element);
+ _ ->
+ ?ASN1CT_GEN_BER:gen_encode_prim(ber,Type,
+ {asis,Tag},
+ Element)
+ end;
+ _ ->
+ {EncFunName, _EncMod, _EncFun} =
+ mkfuncname(TopType,Cname,WhatKind,"enc_"),
+ case {WhatKind,Type#type.tablecinf,EncObj} of
+ {{constructed,bif},[{objfun,_}|_R],{_,Fun}} ->
+ emit([EncFunName,"(",Element,", ",{asis,Tag},
+ ", ",Fun,")"]);
+ _ ->
+ emit([EncFunName,"(",Element,", ",{asis,Tag},")"])
+ end
+ end
+ end,
+ case OptOrMand of
+ mandatory -> true;
+ _ ->
+ emit([nl,indent(7),"end"])
+ end.
+
+gen_optormand_case(mandatory,_Erules,_TopType,_Cname,_Type,_InnerType,_WhatKind,
+ _Element) ->
+ ok;
+gen_optormand_case('OPTIONAL',Erules,_TopType,_Cname,_Type,_InnerType,_WhatKind,
+ Element) ->
+ emit([" case ",Element," of",nl]),
+ emit([indent(9),"asn1_NOVALUE -> {",
+ empty_lb(Erules),",0};",nl]),
+ emit([indent(9),"_ ->",nl,indent(12)]);
+gen_optormand_case({'DEFAULT',DefaultValue},Erules,TopType,Cname,Type,
+ InnerType,WhatKind,Element) ->
+ CurrMod = get(currmod),
+ case catch lists:member(der,get(encoding_options)) of
+ true ->
+ emit(" case catch "),
+ asn1ct_gen:gen_check_call(TopType,Cname,Type,InnerType,
+ WhatKind,{asis,DefaultValue},
+ Element),
+ emit([" of",nl]),
+ emit([indent(12),"true -> {[],0};",nl]);
+ _ ->
+ emit([" case ",Element," of",nl]),
+ emit([indent(9),"asn1_DEFAULT -> {",
+ empty_lb(Erules),
+ ",0};",nl]),
+ case DefaultValue of
+ #'Externalvaluereference'{module=CurrMod,
+ value=V} ->
+ emit([indent(9),"?",{asis,V}," -> {",
+ empty_lb(Erules),",0};",nl]);
+ _ ->
+ emit([indent(9),{asis,
+ DefaultValue}," -> {",
+ empty_lb(Erules),",0};",nl])
+ end
+ end,
+ emit([indent(9),"_ ->",nl,indent(12)]).
+
+
+
+gen_dec_line(Erules,TopType,Cname,CTags,Type,OptOrMand,DecObjInf) ->
+ BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(v)),
+ Tag =
+ [(?ASN1CT_GEN_BER:decode_class(X#tag.class) bsl 10) + X#tag.number ||
+ X <- Type#type.tag],
+ ChoiceTags =
+ [(?ASN1CT_GEN_BER:decode_class(Class) bsl 10) + Number||
+ {Class,Number} <- CTags],
+ InnerType =
+ case Type#type.def of
+ #'ObjectClassFieldType'{type=OCFTType} ->
+ OCFTType;
+ _ ->
+ asn1ct_gen:get_inner(Type#type.def)
+ end,
+ PostpDec =
+ case OptOrMand of
+ mandatory ->
+ gen_dec_call(InnerType,Erules,TopType,Cname,Type,
+ BytesVar,Tag,
+ mandatory,", mandatory, ",DecObjInf,OptOrMand);
+ _ -> %optional or default or a mandatory component after an extensionmark
+ {FirstTag,RestTag} =
+ case Tag of
+ [] ->
+ {ChoiceTags,[]};
+ [Ft|Rt] ->
+ {Ft,Rt}
+ end,
+ emit(["case ",{prev,tlv}," of",nl]),
+ PostponedDec =
+ case Tag of
+ [] when length(ChoiceTags) > 0 -> % a choice without explicit tag
+ Fcases =
+ fun(FirstTag1) ->
+ emit(["[",{curr,v}," = {",{asis,FirstTag1},
+ ",_}|Temp",
+ {curr,tlv},
+ "] ->",nl]),
+ emit([indent(4),"{"]),
+ Pdec=
+ gen_dec_call(InnerType,Erules,
+ TopType,Cname,Type,
+ BytesVar,RestTag,
+ mandatory,
+ ", mandatory, ",
+ DecObjInf,OptOrMand),
+
+ emit([", Temp",{curr,tlv},"}"]),
+ emit([";",nl]),
+ Pdec
+ end,
+ hd([Fcases(TmpTag)|| TmpTag <- FirstTag]);
+
+ [] -> % an open type without explicit tag
+ emit(["[",{curr,v},"|Temp",{curr,tlv},"] ->",nl]),
+ emit([indent(4),"{"]),
+ Pdec=
+ gen_dec_call(InnerType,Erules,TopType,Cname,
+ Type,BytesVar,RestTag,mandatory,
+ ", mandatory, ",DecObjInf,
+ OptOrMand),
+
+ emit([", Temp",{curr,tlv},"}"]),
+ emit([";",nl]),
+ Pdec;
+
+ _ ->
+ emit(["[{",{asis,FirstTag},
+ ",",{curr,v},"}|Temp",
+ {curr,tlv},
+ "] ->",nl]),
+ emit([indent(4),"{"]),
+ Pdec=
+ gen_dec_call(InnerType,Erules,TopType,Cname,
+ Type,BytesVar,RestTag,mandatory,
+ ", mandatory, ",DecObjInf,
+ OptOrMand),
+
+ emit([", Temp",{curr,tlv},"}"]),
+ emit([";",nl]),
+ Pdec
+ end,
+
+ emit([indent(4),"_ ->",nl]),
+ case OptOrMand of
+ {'DEFAULT', Def} ->
+ emit([indent(8),"{",{asis,Def},",",{prev,tlv},"}",nl]);
+ 'OPTIONAL' ->
+ emit([indent(8),"{ asn1_NOVALUE, ",{prev,tlv},"}",nl])
+ end,
+ emit(["end"]),
+ PostponedDec
+ end,
+ case DecObjInf of
+ {Cname,ObjSet} -> % this must be the component were an object is
+ %% choosen from the object set according to the table
+ %% constraint.
+ {[{ObjSet,Cname,asn1ct_gen:mk_var(asn1ct_name:curr(term))}],
+ PostpDec};
+ _ -> {[],PostpDec}
+ end.
+
+gen_dec_call({typefield,_},_,_,_Cname,Type,BytesVar,Tag,_,_,false,_) ->
+ %% this in case of a choice with typefield components
+ asn1ct_name:new(reason),
+ asn1ct_name:new(opendec),
+ asn1ct_name:new(tmpterm),
+ asn1ct_name:new(tmptlv),
+
+ {FirstPFName,RestPFName} =
+% asn1ct_gen:get_constraint(Type#type.constraint,
+% tableconstraint_info),
+ (Type#type.def)#'ObjectClassFieldType'.fieldname,
+ emit([nl,indent(6),"begin",nl]),
+% emit([indent(9),{curr,opendec}," = ?RT_BER:decode_open_type(",
+ emit([indent(9),{curr,tmptlv}," = ?RT_BER:decode_open_type(",
+ BytesVar,",",{asis,Tag},"),",nl]),
+% emit([indent(9),"{",{curr,tmptlv},",_} = ?RT_BER:decode(",
+% {curr,opendec},"),",nl]),
+
+ emit([indent(9),"case (catch ObjFun(",{asis,FirstPFName},
+ ", ",{curr,tmptlv},", ",{asis,RestPFName},
+ ")) of", nl]),%% ??? What about Tag
+ emit([indent(12),"{'EXIT',",{curr,reason},"} ->",nl]),
+ emit([indent(15),"exit({'Type not ",
+ "compatible with table constraint', ",{curr,reason},"});",nl]),
+ emit([indent(12),{curr,tmpterm}," ->",nl]),
+ emit([indent(15),{curr,tmpterm},nl]),
+ emit([indent(9),"end",nl,indent(6),"end",nl]),
+ [];
+gen_dec_call({typefield,_},_,_,Cname,Type,BytesVar,Tag,_,_,_DecObjInf,OptOrMandComp) ->
+ emit(["?RT_BER:decode_open_type(",BytesVar,",",{asis,Tag},")"]),
+ RefedFieldName =
+% asn1ct_gen:get_constraint(Type#type.constraint,
+% tableconstraint_info),
+ (Type#type.def)#'ObjectClassFieldType'.fieldname,
+ [{Cname,RefedFieldName,asn1ct_gen:mk_var(asn1ct_name:curr(term)),
+ asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
+gen_dec_call({objectfield,PrimFieldName,PFNList},_,_,Cname,_,BytesVar,Tag,_,_,_,OptOrMandComp) ->
+ emit(["?RT_BER:decode_open_type(",BytesVar,",",{asis,Tag},")"]),
+ [{Cname,{PrimFieldName,PFNList},asn1ct_gen:mk_var(asn1ct_name:curr(term)),
+ asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
+gen_dec_call(InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,PrimOptOrMand,
+ OptOrMand,DecObjInf,_) ->
+ WhatKind = asn1ct_gen:type(InnerType),
+ gen_dec_call1(WhatKind,InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,
+ PrimOptOrMand,OptOrMand),
+ case DecObjInf of
+ {Cname,{_,OSet,UniqueFName,ValIndex}} ->
+ Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
+ ValueMatch = value_match(ValIndex,Term),
+ emit([",",nl,"ObjFun = 'getdec_",OSet,"'(",
+% {asis,UniqueFName},", ",{curr,term},")"]);
+ {asis,UniqueFName},", ",ValueMatch,")"]);
+ _ ->
+ ok
+ end,
+ [].
+gen_dec_call1({primitive,bif},InnerType,Erules,TopType,Cname,Type,BytesVar,
+ Tag,OptOrMand,_) ->
+ case {asn1ct:get_gen_state_field(namelist),InnerType} of
+ {[{Cname,undecoded}|Rest],_} ->
+ asn1ct:add_generated_refed_func({[Cname|TopType],undecoded,
+ Tag,Type}),
+ asn1ct:update_gen_state(namelist,Rest),
+% emit(["?RT_BER:match_tags(",BytesVar,",",{asis,Tag},")"]);
+ emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',",
+ BytesVar,"}"]);
+ {_,{fixedtypevaluefield,_,Btype}} ->
+ ?ASN1CT_GEN_BER:gen_dec_prim(Erules,Btype,BytesVar,Tag,[],
+ ?PRIMITIVE,OptOrMand);
+ _ ->
+ ?ASN1CT_GEN_BER:gen_dec_prim(Erules,Type,BytesVar,Tag,[],
+ ?PRIMITIVE,OptOrMand)
+ end;
+gen_dec_call1('ASN1_OPEN_TYPE',_InnerType,Erules,TopType,Cname,Type,BytesVar,
+ Tag,OptOrMand,_) ->
+ case {asn1ct:get_gen_state_field(namelist),Type#type.def} of
+ {[{Cname,undecoded}|Rest],_} ->
+ asn1ct:add_generated_refed_func({[Cname|TopType],undecoded,
+ Tag,Type}),
+ asn1ct:update_gen_state(namelist,Rest),
+ emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',",
+ BytesVar,"}"]);
+% emit(["?RT_BER:match_tags(",BytesVar,",",{asis,Tag},")"]);
+ {_,#'ObjectClassFieldType'{type=OpenType}} ->
+ ?ASN1CT_GEN_BER:gen_dec_prim(Erules,#type{def=OpenType},
+ BytesVar,Tag,[],
+ ?PRIMITIVE,OptOrMand);
+ _ ->
+ ?ASN1CT_GEN_BER:gen_dec_prim(Erules,Type,BytesVar,Tag,[],
+ ?PRIMITIVE,OptOrMand)
+ end;
+gen_dec_call1(WhatKind,_,_Erules,TopType,Cname,Type,BytesVar,
+ Tag,_,_OptOrMand) ->
+ case asn1ct:get_gen_state_field(namelist) of
+ [{Cname,undecoded}|Rest] ->
+ asn1ct:add_generated_refed_func({[Cname|TopType],undecoded,
+ Tag,Type}),
+ asn1ct:update_gen_state(namelist,Rest),
+ emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',",
+ BytesVar,"}"]);
+ _ ->
+% {DecFunName, _DecMod, _DecFun} =
+% case {asn1ct:get_gen_state_field(namelist),WhatKind} of
+ EmitDecFunCall =
+ fun(FuncName) ->
+ case {WhatKind,Type#type.tablecinf} of
+ {{constructed,bif},[{objfun,_}|_Rest]} ->
+ emit([FuncName,"(",BytesVar,", ",{asis,Tag},
+ ", ObjFun)"]);
+ _ ->
+ emit([FuncName,"(",BytesVar,", ",{asis,Tag},")"])
+ end
+ end,
+ case asn1ct:get_gen_state_field(namelist) of
+ [{Cname,List}|Rest] when list(List) ->
+ case WhatKind of
+ #'Externaltypereference'{} ->
+ %%io:format("gen_dec_call1 1:~n~p~n~n",[WhatKind]),
+ asn1ct:add_tobe_refed_func({WhatKind,List});
+ _ ->
+ %%io:format("gen_dec_call1 2:~n~p~n~n",[[Cname|TopType]]),
+ asn1ct:add_tobe_refed_func({[Cname|TopType],
+ List})
+ end,
+ asn1ct:update_gen_state(namelist,Rest),
+ Prefix=asn1ct:get_gen_state_field(prefix),
+ {DecFunName,_,_}=
+ mkfuncname(TopType,Cname,WhatKind,Prefix),
+ EmitDecFunCall(DecFunName);
+ [{Cname,parts}|Rest] ->
+ asn1ct:update_gen_state(namelist,Rest),
+ asn1ct:get_gen_state_field(prefix),
+ %% This is to prepare SEQUENCE OF value in
+ %% partial incomplete decode for a later
+ %% part-decode, i.e. skip %% the tag.
+ asn1ct:add_generated_refed_func({[Cname|TopType],
+ parts,
+ [],Type}),
+ emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',"]),
+ EmitDecFunCall("?RT_BER:match_tags"),
+ emit("}");
+ _ ->
+ {DecFunName,_,_}=
+ mkfuncname(TopType,Cname,WhatKind,"dec_"),
+ EmitDecFunCall(DecFunName)
+ end
+% case {WhatKind,Type#type.tablecinf} of
+% {{constructed,bif},[{objfun,_}|_Rest]} ->
+% emit([DecFunName,"(",BytesVar,", ",{asis,Tag},
+% ", ObjFun)"]);
+% _ ->
+% emit([DecFunName,"(",BytesVar,", ",{asis,Tag},")"])
+% end
+ end.
+
+
+%%------------------------------------------------------
+%% General and special help functions (not exported)
+%%------------------------------------------------------
+
+
+indent(N) ->
+ lists:duplicate(N,32). % 32 = space
+
+mkcindexlist([H,T1|T], Sep) -> % Sep is a string e.g ", " or "+ "
+ emit(["Cindex",H,Sep]),
+ mkcindexlist([T1|T], Sep);
+mkcindexlist([H|T], Sep) ->
+ emit(["Cindex",H]),
+ mkcindexlist(T, Sep);
+mkcindexlist([], _) ->
+ true.
+
+mkcindexlist(L) ->
+ mkcindexlist(L,", ").
+
+
+mkvlist([H,T1|T], Sep) -> % Sep is a string e.g ", " or "+ "
+ emit([{var,H},Sep]),
+ mkvlist([T1|T], Sep);
+mkvlist([H|T], Sep) ->
+ emit([{var,H}]),
+ mkvlist(T, Sep);
+mkvlist([], _) ->
+ true.
+
+mkvlist(L) ->
+ mkvlist(L,", ").
+
+mkvplus(L) ->
+ mkvlist(L," + ").
+
+extensible(CompList) when list(CompList) ->
+ noext;
+extensible({RootList,ExtList}) ->
+ {ext,length(RootList)+1,length(ExtList)}.
+
+
+print_attribute_comment(InnerType,Pos,Cname,Prop) ->
+ CommentLine = "%%-------------------------------------------------",
+ emit([nl,CommentLine]),
+ case InnerType of
+ {typereference,_,Name} ->
+ emit([nl,"%% attribute ",Cname,"(",Pos,") with type ",Name]);
+ {'Externaltypereference',_,XModule,Name} ->
+ emit([nl,"%% attribute ",Cname,"(",Pos,") External ",XModule,":",Name]);
+ _ ->
+ emit([nl,"%% attribute ",Cname,"(",Pos,") with type ",InnerType])
+ end,
+ case Prop of
+ mandatory ->
+ continue;
+ {'DEFAULT', Def} ->
+ emit([" DEFAULT = ",{asis,Def}]);
+ 'OPTIONAL' ->
+ emit([" OPTIONAL"])
+ end,
+ emit([nl,CommentLine,nl]).
+
+
+
+mkfuncname(TopType,Cname,WhatKind,Prefix) ->
+ CurrMod = get(currmod),
+ case WhatKind of
+ #'Externaltypereference'{module=CurrMod,type=EType} ->
+ F = lists:concat(["'",Prefix,EType,"'"]),
+ {F, "?MODULE", F};
+ #'Externaltypereference'{module=Mod,type=EType} ->
+ {lists:concat(["'",Mod,"':'",Prefix,EType,"'"]),Mod,
+ lists:concat(["'",Prefix,EType,"'"])};
+ {constructed,bif} ->
+ F = lists:concat(["'",Prefix,asn1ct_gen:list2name([Cname|TopType]),"'"]),
+ {F, "?MODULE", F}
+ end.
+
+empty_lb(ber) ->
+ "[]";
+empty_lb(ber_bin) ->
+ "<<>>";
+empty_lb(ber_bin_v2) ->
+ "<<>>".
+
+value_match(Index,Value) when atom(Value) ->
+ value_match(Index,atom_to_list(Value));
+value_match([],Value) ->
+ Value;
+value_match([{VI,_}|VIs],Value) ->
+ value_match1(Value,VIs,lists:concat(["element(",VI,","]),1).
+value_match1(Value,[],Acc,Depth) ->
+ Acc ++ Value ++ lists:concat(lists:duplicate(Depth,")"));
+value_match1(Value,[{VI,_}|VIs],Acc,Depth) ->
+ value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_constructed_per.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_constructed_per.erl
new file mode 100644
index 0000000000..a21c38f8a8
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_constructed_per.erl
@@ -0,0 +1,1234 @@
+% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1ct_constructed_per.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
+%%
+-module(asn1ct_constructed_per).
+
+-export([gen_encode_sequence/3]).
+-export([gen_decode_sequence/3]).
+-export([gen_encode_set/3]).
+-export([gen_decode_set/3]).
+-export([gen_encode_sof/4]).
+-export([gen_decode_sof/4]).
+-export([gen_encode_choice/3]).
+-export([gen_decode_choice/3]).
+
+-include("asn1_records.hrl").
+%-compile(export_all).
+
+-import(asn1ct_gen, [emit/1,demit/1]).
+
+
+%% ENCODE GENERATOR FOR SEQUENCE TYPE ** **********
+
+
+gen_encode_set(Erules,TypeName,D) ->
+ gen_encode_constructed(Erules,TypeName,D).
+
+gen_encode_sequence(Erules,TypeName,D) ->
+ gen_encode_constructed(Erules,TypeName,D).
+
+gen_encode_constructed(Erules,Typename,D) when record(D,type) ->
+ asn1ct_name:start(),
+ asn1ct_name:new(term),
+ asn1ct_name:new(bytes),
+ {CompList,TableConsInfo} =
+ case D#type.def of
+ #'SEQUENCE'{tablecinf=TCI,components=CL} ->
+ {CL,TCI};
+ #'SET'{tablecinf=TCI,components=CL} ->
+ {CL,TCI}
+ end,
+ case Typename of
+ ['EXTERNAL'] ->
+ emit({{var,asn1ct_name:next(val)},
+ " = asn1rt_check:transform_to_EXTERNAL1990(",
+ {var,asn1ct_name:curr(val)},"),",nl}),
+ asn1ct_name:new(val);
+ _ ->
+ ok
+ end,
+ case {Optionals = optionals(CompList),CompList} of
+ {[],EmptyCL} when EmptyCL == {[],[]};EmptyCL == [] ->
+ emit(["%%Variable setting just to eliminate ",
+ "compiler warning for unused vars!",nl,
+ "_Val = ",{var,asn1ct_name:curr(val)},",",nl]);
+ {[],_} ->
+ emit([{var,asn1ct_name:next(val)}," = ?RT_PER:list_to_record("]),
+ emit(["'",asn1ct_gen:list2rname(Typename),"'"]),
+ emit([", ",{var,asn1ct_name:curr(val)},"),",nl]);
+ _ ->
+ Fixoptcall =
+ case Erules of
+ per -> ",Opt} = ?RT_PER:fixoptionals2(";
+ _ -> ",Opt} = ?RT_PER:fixoptionals("
+ end,
+ emit({"{",{var,asn1ct_name:next(val)},Fixoptcall,
+ {asis,Optionals},",",length(Optionals),
+ ",",{var,asn1ct_name:curr(val)},"),",nl})
+ end,
+ asn1ct_name:new(val),
+ Ext = extensible(CompList),
+ case Ext of
+ {ext,_,NumExt} when NumExt > 0 ->
+ emit(["Extensions = ?RT_PER:fixextensions(",{asis,Ext},
+ ", ",{curr,val},"),",nl]);
+ _ -> true
+ end,
+ EncObj =
+ case TableConsInfo of
+ #simpletableattributes{usedclassfield=Used,
+ uniqueclassfield=Unique} when Used /= Unique ->
+ false;
+ %% ObjectSet, name of the object set in constraints
+ %%
+ %%{ObjectSet,AttrN,N,UniqueFieldName} -> %% N is index of attribute that determines constraint
+ #simpletableattributes{objectsetname=ObjectSet,
+ c_name=AttrN,
+ c_index=N,
+ usedclassfield=UniqueFieldName,
+ uniqueclassfield=UniqueFieldName,
+ valueindex=ValueIndex
+ } -> %% N is index of attribute that determines constraint
+ OSDef =
+ case ObjectSet of
+ {Module,OSName} ->
+ asn1_db:dbget(Module,OSName);
+ OSName ->
+ asn1_db:dbget(get(currmod),OSName)
+ end,
+ case (OSDef#typedef.typespec)#'ObjectSet'.gen of
+ true ->
+ ObjectEncode =
+ asn1ct_gen:un_hyphen_var(lists:concat(['Obj',AttrN])),
+ emit([ObjectEncode," = ",nl]),
+ emit([" 'getenc_",ObjectSet,"'(",
+ {asis,UniqueFieldName},", ",nl]),
+ El = make_element(N+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),AttrN),
+ Indent = 12 + length(atom_to_list(ObjectSet)),
+ case ValueIndex of
+ [] ->
+ emit([indent(Indent),El,"),",nl]);
+ _ ->
+ emit([indent(Indent),"value_match(",
+ {asis,ValueIndex},",",El,")),",nl]),
+ notice_value_match()
+ end,
+ {AttrN,ObjectEncode};
+ _ ->
+ false
+ end;
+ _ ->
+ case D#type.tablecinf of
+ [{objfun,_}|_] ->
+ %% when the simpletableattributes was at an outer
+ %% level and the objfun has been passed through the
+ %% function call
+ {"got objfun through args","ObjFun"};
+ _ ->
+ false
+ end
+ end,
+ emit({"[",nl}),
+ MaybeComma1 =
+ case Ext of
+ {ext,_Pos,NumExt2} when NumExt2 > 0 ->
+ emit({"?RT_PER:setext(Extensions =/= [])"}),
+ ", ";
+ {ext,_Pos,_} ->
+ emit({"?RT_PER:setext(false)"}),
+ ", ";
+ _ ->
+ ""
+ end,
+ MaybeComma2 =
+ case optionals(CompList) of
+ [] -> MaybeComma1;
+ _ ->
+ emit(MaybeComma1),
+ emit("Opt"),
+ {",",nl}
+ end,
+ gen_enc_components_call(Typename,CompList,MaybeComma2,EncObj,Ext),
+ emit({"].",nl}).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% generate decode function for SEQUENCE and SET
+%%
+gen_decode_set(Erules,Typename,D) ->
+ gen_decode_constructed(Erules,Typename,D).
+
+gen_decode_sequence(Erules,Typename,D) ->
+ gen_decode_constructed(Erules,Typename,D).
+
+gen_decode_constructed(_Erules,Typename,D) when record(D,type) ->
+ asn1ct_name:start(),
+ {CompList,TableConsInfo} =
+ case D#type.def of
+ #'SEQUENCE'{tablecinf=TCI,components=CL} ->
+ {CL,TCI};
+ #'SET'{tablecinf=TCI,components=CL} ->
+ {CL,TCI}
+ end,
+ Ext = extensible(CompList),
+ MaybeComma1 = case Ext of
+ {ext,_Pos,_NumExt} ->
+ gen_dec_extension_value("Bytes"),
+ {",",nl};
+ _ ->
+ ""
+ end,
+ Optionals = optionals(CompList),
+ MaybeComma2 = case Optionals of
+ [] -> MaybeComma1;
+ _ ->
+ Bcurr = asn1ct_name:curr(bytes),
+ Bnext = asn1ct_name:next(bytes),
+ emit(MaybeComma1),
+ GetoptCall = "} = ?RT_PER:getoptionals2(",
+ emit({"{Opt,",{var,Bnext},GetoptCall,
+ {var,Bcurr},",",{asis,length(Optionals)},")"}),
+ asn1ct_name:new(bytes),
+ ", "
+ end,
+ {DecObjInf,UniqueFName,ValueIndex} =
+ case TableConsInfo of
+%% {ObjectSet,AttrN,N,UniqueFieldName} ->%% N is index of attribute that determines constraint
+ #simpletableattributes{objectsetname=ObjectSet,
+ c_name=AttrN,
+ usedclassfield=UniqueFieldName,
+ uniqueclassfield=UniqueFieldName,
+ valueindex=ValIndex} ->
+%% {AttrN,ObjectSet};
+ F = fun(#'ComponentType'{typespec=CT})->
+ case {CT#type.constraint,CT#type.tablecinf} of
+ {[],[{objfun,_}|_R]} -> true;
+ _ -> false
+ end
+ end,
+ case lists:any(F,CompList) of
+ true -> % when component relation constraint establish
+ %% relation from a component to another components
+ %% subtype component
+ {{AttrN,{deep,ObjectSet,UniqueFieldName,ValIndex}},
+ UniqueFieldName,ValIndex};
+ false ->
+ {{AttrN,ObjectSet},UniqueFieldName,ValIndex}
+ end;
+ _ ->
+ case D#type.tablecinf of
+ [{objfun,_}|_] ->
+ {{"got objfun through args","ObjFun"},false,false};
+ _ ->
+ {false,false,false}
+ end
+ end,
+ {AccTerm,AccBytes} =
+ gen_dec_components_call(Typename,CompList,MaybeComma2,DecObjInf,Ext,length(Optionals)),
+ case asn1ct_name:all(term) of
+ [] -> emit(MaybeComma2); % no components at all
+ _ -> emit({com,nl})
+ end,
+ case {AccTerm,AccBytes} of
+ {[],[]} ->
+ ok;
+ {_,[]} ->
+ ok;
+ {[{ObjSet,LeadingAttr,Term}],ListOfOpenTypes} ->
+ DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])),
+ ValueMatch = value_match(ValueIndex,Term),
+ emit({DecObj," =",nl," 'getdec_",ObjSet,"'(",
+% {asis,UniqueFName},", ",Term,"),",nl}),
+ {asis,UniqueFName},", ",ValueMatch,"),",nl}),
+ gen_dec_listofopentypes(DecObj,ListOfOpenTypes,false)
+ end,
+ %% we don't return named lists any more Cnames = mkcnamelist(CompList),
+ demit({"Result = "}), %dbg
+ %% return value as record
+ case Typename of
+ ['EXTERNAL'] ->
+ emit({" OldFormat={'",asn1ct_gen:list2rname(Typename),
+ "'"}),
+ mkvlist(asn1ct_name:all(term)),
+ emit({"},",nl}),
+ emit({" ASN11994Format =",nl,
+ " asn1rt_check:transform_to_EXTERNAL1994",
+ "(OldFormat),",nl}),
+ emit(" {ASN11994Format,");
+ _ ->
+ emit(["{{'",asn1ct_gen:list2rname(Typename),"'"]),
+ mkvlist(asn1ct_name:all(term)),
+ emit("},")
+ end,
+ emit({{var,asn1ct_name:curr(bytes)},"}"}),
+ emit({".",nl,nl}).
+
+gen_dec_listofopentypes(_,[],_) ->
+ emit(nl);
+gen_dec_listofopentypes(DecObj,[{_Cname,{FirstPFN,PFNList},Term,TmpTerm,Prop}|Rest],_Update) ->
+
+% asn1ct_name:new(term),
+ asn1ct_name:new(tmpterm),
+ asn1ct_name:new(reason),
+
+ emit([Term," = ",nl]),
+
+ N = case Prop of
+ mandatory -> 0;
+ 'OPTIONAL' ->
+ emit_opt_or_mand_check(asn1_NOVALUE,TmpTerm),
+ 6;
+ {'DEFAULT',Val} ->
+ emit_opt_or_mand_check(Val,TmpTerm),
+ 6
+ end,
+
+ emit([indent(N+3),"case (catch ",DecObj,"(",
+ {asis,FirstPFN},", ",TmpTerm,", telltype,",{asis,PFNList},")) of",nl]),
+ emit([indent(N+6),"{'EXIT', ",{curr,reason},"} ->",nl]),
+%% emit({indent(9),"throw({runtime_error,{","'Type not compatible with table constraint'",",",Term,"}});",nl}),
+ emit([indent(N+9),"exit({'Type not compatible with table constraint',",
+ {curr,reason},"});",nl]),
+ emit([indent(N+6),"{",{curr,tmpterm},",_} ->",nl]),
+ emit([indent(N+9),{curr,tmpterm},nl]),
+
+ case Prop of
+ mandatory ->
+ emit([indent(N+3),"end,",nl]);
+ _ ->
+ emit([indent(N+3),"end",nl,
+ indent(3),"end,",nl])
+ end,
+ gen_dec_listofopentypes(DecObj,Rest,true).
+
+
+emit_opt_or_mand_check(Val,Term) ->
+ emit([indent(3),"case ",Term," of",nl,
+ indent(6),{asis,Val}," ->",{asis,Val},";",nl,
+ indent(6),"_ ->",nl]).
+
+%% ENCODE GENERATOR FOR THE CHOICE TYPE *******
+%% assume Val = {Alternative,AltType}
+%% generate
+%%[
+%% ?RT_PER:set_choice(element(1,Val),Altnum,Altlist,ext),
+%%case element(1,Val) of
+%% alt1 ->
+%% encode_alt1(element(2,Val));
+%% alt2 ->
+%% encode_alt2(element(2,Val))
+%%end
+%%].
+
+gen_encode_choice(_Erules,Typename,D) when record(D,type) ->
+ {'CHOICE',CompList} = D#type.def,
+ emit({"[",nl}),
+ Ext = extensible(CompList),
+ gen_enc_choice(Typename,CompList,Ext),
+ emit({nl,"].",nl}).
+
+gen_decode_choice(_Erules,Typename,D) when record(D,type) ->
+ asn1ct_name:start(),
+ asn1ct_name:new(bytes),
+ {'CHOICE',CompList} = D#type.def,
+ Ext = extensible(CompList),
+ gen_dec_choice(Typename,CompList,Ext),
+ emit({".",nl}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Encode generator for SEQUENCE OF type
+
+
+gen_encode_sof(_Erules,Typename,SeqOrSetOf,D) when record(D,type) ->
+ asn1ct_name:start(),
+% Val = [Component]
+% ?RT_PER:encode_length(length(Val)),
+% lists:
+ {_SeqOrSetOf,ComponentType} = D#type.def,
+ emit({"[",nl}),
+ SizeConstraint =
+ case asn1ct_gen:get_constraint(D#type.constraint,
+ 'SizeConstraint') of
+ no -> undefined;
+ Range -> Range
+ end,
+ ObjFun =
+ case D#type.tablecinf of
+ [{objfun,_}|_R] ->
+ ", ObjFun";
+ _->
+ ""
+ end,
+ emit({nl,indent(3),"?RT_PER:encode_length(",
+ {asis,SizeConstraint},
+ ",length(Val)),",nl}),
+ emit({indent(3),"'enc_",asn1ct_gen:list2name(Typename),
+ "_components'(Val",ObjFun,", [])"}),
+ emit({nl,"].",nl}),
+ NewComponentType =
+ case ComponentType#type.def of
+ {'ENUMERATED',_,Component}->
+ ComponentType#type{def={'ENUMERATED',Component}};
+ _ -> ComponentType
+ end,
+ gen_encode_sof_components(Typename,SeqOrSetOf,NewComponentType).
+
+gen_decode_sof(_Erules,Typename,SeqOrSetOf,D) when record(D,type) ->
+ asn1ct_name:start(),
+% Val = [Component]
+% ?RT_PER:encode_length(length(Val)),
+% lists:
+ {_SeqOrSetOf,ComponentType} = D#type.def,
+ SizeConstraint =
+ case asn1ct_gen:get_constraint(D#type.constraint,
+ 'SizeConstraint') of
+ no -> undefined;
+ Range -> Range
+ end,
+ ObjFun =
+ case D#type.tablecinf of
+ [{objfun,_}|_R] ->
+ ", ObjFun";
+ _ ->
+ ""
+ end,
+ emit({nl,"{Num,Bytes1} = ?RT_PER:decode_length(Bytes,",{asis,SizeConstraint},"),",nl}),
+ emit({"'dec_",asn1ct_gen:list2name(Typename),
+ "_components'(Num, Bytes1, telltype",ObjFun,", []).",nl}),
+ NewComponentType =
+ case ComponentType#type.def of
+ {'ENUMERATED',_,Component}->
+ ComponentType#type{def={'ENUMERATED',Component}};
+ _ -> ComponentType
+ end,
+ gen_decode_sof_components(Typename,SeqOrSetOf,NewComponentType).
+
+gen_encode_sof_components(Typename,SeqOrSetOf,Cont) ->
+ {ObjFun,ObjFun_Var} =
+ case Cont#type.tablecinf of
+ [{objfun,_}|_R] ->
+ {", ObjFun",", _"};
+ _ ->
+ {"",""}
+ end,
+ emit({"'enc_",asn1ct_gen:list2name(Typename),"_components'([]",
+ ObjFun_Var,", Acc) -> lists:reverse(Acc);",nl,nl}),
+ emit({"'enc_",asn1ct_gen:list2name(Typename),"_components'([H|T]",
+ ObjFun,", Acc) ->",nl}),
+ emit({"'enc_",asn1ct_gen:list2name(Typename),"_components'(T"}),
+ emit({ObjFun,", ["}),
+ %% the component encoder
+ Constructed_Suffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,
+ Cont#type.def),
+
+ Conttype = asn1ct_gen:get_inner(Cont#type.def),
+ Currmod = get(currmod),
+ Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
+ asn1ct_gen:rt2ct_suffix()])),
+ case asn1ct_gen:type(Conttype) of
+ {primitive,bif} ->
+ gen_encode_prim_wrapper(Ctgenmod,per,Cont,false,"H");
+% Ctgenmod:gen_encode_prim(per,Cont,false,"H");
+ {constructed,bif} ->
+ NewTypename = [Constructed_Suffix|Typename],
+ emit({"'enc_",asn1ct_gen:list2name(NewTypename),"'(H",
+ ObjFun,")",nl,nl});
+ #'Externaltypereference'{module=Currmod,type=Ename} ->
+ emit({"'enc_",Ename,"'(H)",nl,nl});
+ #'Externaltypereference'{module=EMod,type=EType} ->
+ emit({"'",EMod,"':'enc_",EType,"'(H)",nl,nl});
+ _ ->
+ emit({"'enc_",Conttype,"'(H)",nl,nl})
+ end,
+ emit({" | Acc]).",nl}).
+
+gen_decode_sof_components(Typename,SeqOrSetOf,Cont) ->
+ {ObjFun,ObjFun_Var} =
+ case Cont#type.tablecinf of
+ [{objfun,_}|_R] ->
+ {", ObjFun",", _"};
+ _ ->
+ {"",""}
+ end,
+ emit({"'dec_",asn1ct_gen:list2name(Typename),
+ "_components'(0, Bytes, _",ObjFun_Var,", Acc) ->",nl,
+ indent(3),"{lists:reverse(Acc), Bytes};",nl}),
+ emit({"'dec_",asn1ct_gen:list2name(Typename),
+ "_components'(Num, Bytes, _",ObjFun,", Acc) ->",nl}),
+ emit({indent(3),"{Term,Remain} = "}),
+ Constructed_Suffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,
+ Cont#type.def),
+ Conttype = asn1ct_gen:get_inner(Cont#type.def),
+ Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
+ asn1ct_gen:rt2ct_suffix()])),
+ case asn1ct_gen:type(Conttype) of
+ {primitive,bif} ->
+ Ctgenmod:gen_dec_prim(per,Cont,"Bytes"),
+ emit({com,nl});
+ {constructed,bif} ->
+ NewTypename = [Constructed_Suffix|Typename],
+ emit({"'dec_",asn1ct_gen:list2name(NewTypename),
+ "'(Bytes, telltype",ObjFun,"),",nl});
+ #typereference{val=Dname} ->
+ emit({"'dec_",Dname,"'(Bytes,telltype),",nl});
+ #'Externaltypereference'{module=EMod,type=EType} ->
+ emit({"'",EMod,"':'dec_",EType,"'(Bytes,telltype),",nl});
+ _ ->
+ emit({"'dec_",Conttype,"'(Bytes,telltype),",nl})
+ end,
+ emit({indent(3),"'dec_",asn1ct_gen:list2name(Typename),
+ "_components'(Num-1, Remain, telltype",ObjFun,", [Term|Acc]).",nl}).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% General and special help functions (not exported)
+
+mkvlist([H|T]) ->
+ emit(","),
+ mkvlist2([H|T]);
+mkvlist([]) ->
+ true.
+mkvlist2([H,T1|T]) ->
+ emit({{var,H},","}),
+ mkvlist2([T1|T]);
+mkvlist2([H|T]) ->
+ emit({{var,H}}),
+ mkvlist2(T);
+mkvlist2([]) ->
+ true.
+
+extensible(CompList) when list(CompList) ->
+ noext;
+extensible({RootList,ExtList}) ->
+ {ext,length(RootList)+1,length(ExtList)}.
+
+gen_dec_extension_value(_) ->
+ emit({"{Ext,",{next,bytes},"} = ?RT_PER:getext(",{curr,bytes},")"}),
+ asn1ct_name:new(bytes).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Produce a list with positions (in the Value record) where
+%% there are optional components, start with 2 because first element
+%% is the record name
+
+optionals({L,_Ext}) -> optionals(L,[],2);
+optionals(L) -> optionals(L,[],2).
+
+optionals([{'EXTENSIONMARK',_,_}|Rest],Acc,Pos) ->
+ optionals(Rest,Acc,Pos); % optionals in extension are currently not handled
+optionals([#'ComponentType'{prop='OPTIONAL'}|Rest],Acc,Pos) ->
+ optionals(Rest,[Pos|Acc],Pos+1);
+optionals([#'ComponentType'{prop={'DEFAULT',_}}|Rest],Acc,Pos) ->
+ optionals(Rest,[Pos|Acc],Pos+1);
+optionals([#'ComponentType'{}|Rest],Acc,Pos) ->
+ optionals(Rest,Acc,Pos+1);
+optionals([],Acc,_) ->
+ lists:reverse(Acc).
+
+
+gen_enc_components_call(TopType,{CompList,ExtList},MaybeComma,DynamicEnc,Ext) ->
+ %% The type has extensionmarker
+ Rpos = gen_enc_components_call1(TopType,CompList,1,MaybeComma,DynamicEnc,noext),
+ case Ext of
+ {ext,_,ExtNum} when ExtNum > 0 ->
+ emit([nl,
+ ",Extensions",nl]);
+ _ -> true
+ end,
+ %handle extensions
+ gen_enc_components_call1(TopType,ExtList,Rpos,MaybeComma,DynamicEnc,Ext);
+gen_enc_components_call(TopType, CompList, MaybeComma, DynamicEnc, Ext) ->
+ %% The type has no extensionmarker
+ gen_enc_components_call1(TopType,CompList,1,MaybeComma,DynamicEnc,Ext).
+
+gen_enc_components_call1(TopType,
+ [C=#'ComponentType'{name=Cname,typespec=Type,prop=Prop}|Rest],
+ Tpos,
+ MaybeComma, DynamicEnc, Ext) ->
+
+ put(component_type,{true,C}),
+ %% information necessary in asn1ct_gen_per_rt2ct:gen_encode_prim
+
+ Pos = case Ext of
+ noext -> Tpos;
+ {ext,Epos,_Enum} -> Tpos - Epos + 1
+ end,
+ emit(MaybeComma),
+ case Prop of
+ 'OPTIONAL' ->
+ gen_enc_component_optional(TopType,Cname,Type,Tpos,DynamicEnc,Ext);
+ {'DEFAULT',_DefVal} ->
+ gen_enc_component_default(TopType,Cname,Type,Tpos,DynamicEnc,Ext);
+ _ ->
+ case Ext of
+ {ext,ExtPos,_} when Tpos >= ExtPos ->
+ gen_enc_component_optional(TopType,Cname,Type,Tpos,DynamicEnc,Ext);
+ _ ->
+ gen_enc_component_mandatory(TopType,Cname,Type,Tpos,DynamicEnc,Ext)
+ end
+ end,
+
+ erase(component_type),
+
+ case Rest of
+ [] ->
+ Pos+1;
+ _ ->
+ emit({com,nl}),
+ gen_enc_components_call1(TopType,Rest,Tpos+1,"",DynamicEnc,Ext)
+ end;
+gen_enc_components_call1(_TopType,[],Pos,_,_,_) ->
+ Pos.
+
+gen_enc_component_default(TopType,Cname,Type,Pos,DynamicEnc,Ext) ->
+% Element = io_lib:format("?RT_PER:cindex(~w,Val1,~w)",[Pos+1,Cname]),
+ Element = make_element(Pos+1,"Val1",Cname),
+ emit({"case ",Element," of",nl}),
+% case Ext of
+% {ext,ExtPos,_} when Pos >= ExtPos ->
+% emit({"asn1_NOEXTVALUE -> [];",nl});
+% _ ->
+ emit({"asn1_DEFAULT -> [];",nl}),
+% end,
+ 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(TopType,Cname,Type,NextElement, Pos,DynamicEnc,Ext),
+ emit({nl,"end"}).
+
+gen_enc_component_optional(TopType,Cname,Type,Pos,DynamicEnc,Ext) ->
+% Element = io_lib:format("?RT_PER:cindex(~w,Val1,~w)",[Pos+1,Cname]),
+ Element = make_element(Pos+1,"Val1",Cname),
+ emit({"case ",Element," of",nl}),
+% case Ext of
+% {ext,ExtPos,_} when Pos >= ExtPos ->
+% emit({"asn1_NOEXTVALUE -> [];",nl});
+% _ ->
+ emit({"asn1_NOVALUE -> [];",nl}),
+% end,
+ 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(TopType,Cname,Type,NextElement, Pos,DynamicEnc,Ext),
+ emit({nl,"end"}).
+
+gen_enc_component_mandatory(TopType,Cname,Type,Pos,DynamicEnc,Ext) ->
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ emit({nl,"%% attribute number ",Pos," with type ",
+ InnerType,nl}),
+ gen_enc_line(TopType,Cname,Type,[],Pos,DynamicEnc,Ext).
+
+gen_enc_line(TopType, Cname, Type, [], Pos,DynamicEnc,Ext) ->
+% Element = io_lib:format("?RT_PER:cindex(~w,~s,~w)",[Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),Cname]),
+ Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),Cname),
+ gen_enc_line(TopType,Cname,Type,Element, Pos,DynamicEnc,Ext);
+gen_enc_line(TopType,Cname,Type,Element, Pos,DynamicEnc,Ext) ->
+ Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
+ asn1ct_gen:rt2ct_suffix()])),
+ Atype =
+ case Type of
+ #type{def=#'ObjectClassFieldType'{type=InnerType}} ->
+ InnerType;
+ _ ->
+ asn1ct_gen:get_inner(Type#type.def)
+ end,
+% case asn1ct_gen:get_constraint(Type#type.constraint,
+% tableconstraint_info) of
+% no ->
+% asn1ct_gen:get_inner(Type#type.def);
+% _ ->
+% Type#type.def
+% end,
+ case Ext of
+ {ext,Ep1,_} when Pos >= Ep1 ->
+ emit(["?RT_PER:encode_open_type(dummy,?RT_PER:complete("]);
+ _ -> true
+ end,
+ case Atype of
+ {typefield,_} ->
+ case DynamicEnc of
+ {_LeadingAttrName,Fun} ->
+% case asn1ct_gen:get_constraint(Type#type.constraint,
+% componentrelation) of
+ case (Type#type.def)#'ObjectClassFieldType'.fieldname of
+ {notype,T} ->
+ throw({error,{notype,type_from_object,T}});
+ {Name,RestFieldNames} when atom(Name) ->
+ emit({"?RT_PER:encode_open_type([],?RT_PER:complete(",nl}),
+ emit({" ",Fun,"(",{asis,Name},", ",
+ Element,", ",{asis,RestFieldNames},")))"});
+ Other ->
+ throw({asn1,{'internal error',Other}})
+ end
+ end;
+ {objectfield,PrimFieldName1,PFNList} ->
+ case DynamicEnc of
+ {_LeadingAttrName,Fun} ->
+ emit({"?RT_PER:encode_open_type([],"
+ "?RT_PER:complete(",nl}),
+ emit({" ",Fun,"(",{asis,PrimFieldName1},
+ ", ",Element,", ",{asis,PFNList},")))"})
+ end;
+ _ ->
+ CurrMod = get(currmod),
+ case asn1ct_gen:type(Atype) of
+ #'Externaltypereference'{module=Mod,type=EType} when
+ (CurrMod==Mod) ->
+ emit({"'enc_",EType,"'(",Element,")"});
+ #'Externaltypereference'{module=Mod,type=EType} ->
+ emit({"'",Mod,"':'enc_",
+ EType,"'(",Element,")"});
+ #typereference{val=Ename} ->
+ emit({"'enc_",Ename,"'(",Element,")"});
+ {notype,_} ->
+ emit({"'enc_",Atype,"'(",Element,")"});
+ {primitive,bif} ->
+ EncType =
+ case Atype of
+ {fixedtypevaluefield,_,Btype} ->
+ Btype;
+ _ ->
+ Type
+ end,
+ gen_encode_prim_wrapper(Ctgenmod,per,EncType,
+ false,Element);
+% Ctgenmod:gen_encode_prim(per,EncType,
+% false,Element);
+ 'ASN1_OPEN_TYPE' ->
+ case Type#type.def of
+ #'ObjectClassFieldType'{type=OpenType} ->
+ gen_encode_prim_wrapper(Ctgenmod,per,
+ #type{def=OpenType},
+ false,Element);
+ _ ->
+ gen_encode_prim_wrapper(Ctgenmod,per,Type,
+ false,Element)
+ end;
+% Ctgenmod:gen_encode_prim(per,Type,
+% false,Element);
+ {constructed,bif} ->
+ NewTypename = [Cname|TopType],
+ case {Type#type.tablecinf,DynamicEnc} of
+ {[{objfun,_}|_R],{_,EncFun}} ->
+%% emit({"?RT_PER:encode_open_type([],",
+%% "?RT_PER:complete(",nl}),
+ emit({"'enc_",
+ asn1ct_gen:list2name(NewTypename),
+ "'(",Element,", ",EncFun,")"});
+ _ ->
+ emit({"'enc_",
+ asn1ct_gen:list2name(NewTypename),
+ "'(",Element,")"})
+ end
+ end
+ end,
+ case Ext of
+ {ext,Ep2,_} when Pos >= Ep2 ->
+ emit(["))"]);
+ _ -> true
+ end.
+
+gen_dec_components_call(TopType,{CompList,ExtList},MaybeComma,DecInfObj,Ext,NumberOfOptionals) ->
+ %% The type has extensionmarker
+ {Rpos,AccTerm,AccBytes} =
+ gen_dec_components_call1(TopType, CompList, 1, 1, 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(TopType,ExtList,Rpos, 1, "",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),
+ {AccTerm++AccTermE,AccBytes++AccBytesE};
+
+gen_dec_components_call(TopType,CompList,MaybeComma,DecInfObj,Ext,NumberOfOptionals) ->
+ %% The type has no extensionmarker
+ {_,AccTerm,AccBytes} =
+ gen_dec_components_call1(TopType, CompList, 1, 1,MaybeComma,DecInfObj,Ext,[],[],NumberOfOptionals),
+ {AccTerm,AccBytes}.
+
+
+gen_dec_components_call1(TopType,
+ [C=#'ComponentType'{name=Cname,typespec=Type,prop=Prop}|Rest],
+ Tpos,OptPos,MaybeComma,DecInfObj,Ext,AccTerm,AccBytes,NumberOfOptionals) ->
+ Pos = case Ext of
+ noext -> Tpos;
+ {ext,Epos,_Enum} -> Tpos - Epos + 1
+ end,
+ emit(MaybeComma),
+%% asn1ct_name:new(term),
+ InnerType =
+ case Type#type.def of
+ #'ObjectClassFieldType'{type=InType} ->
+ InType;
+ Def ->
+ asn1ct_gen:get_inner(Def)
+ end,
+% case asn1ct_gen:get_constraint(Type#type.constraint,
+% tableconstraint_info) of
+% no ->
+% asn1ct_gen:get_inner(Type#type.def);
+% _ ->
+% Type#type.def
+% end,
+ case InnerType of
+ #'Externaltypereference'{type=T} ->
+ emit({nl,"%% attribute number ",Tpos," with type ",
+ T,nl});
+ IT when tuple(IT) ->
+ emit({nl,"%% attribute number ",Tpos," with type ",
+ element(2,IT),nl});
+ _ ->
+ emit({nl,"%% attribute number ",Tpos," with type ",
+ InnerType,nl})
+ end,
+
+ case InnerType of
+ {typefield,_} ->
+ asn1ct_name:new(term),
+ asn1ct_name:new(tmpterm),
+ emit({"{",{curr,tmpterm},", ",{next,bytes},"} = "});
+ {objectfield,_,_} ->
+ asn1ct_name:new(term),
+ asn1ct_name:new(tmpterm),
+ emit({"{",{curr,tmpterm},", ",{next,bytes},"} = "});
+ _ ->
+ asn1ct_name:new(term),
+ emit({"{",{curr,term},",",{next,bytes},"} = "})
+ end,
+
+ NewOptPos =
+ case {Ext,Prop} of
+ {noext,mandatory} -> OptPos; % generate nothing
+ {noext,_} ->
+ Element = io_lib:format("Opt band (1 bsl ~w)",[NumberOfOptionals - OptPos]),
+ emit({"case ",Element," of",nl}),
+ emit({"_Opt",OptPos," when _Opt",OptPos," > 0 ->"}),
+ OptPos+1;
+ _ ->
+ emit(["case Extensions of",nl]),
+ emit(["_ when size(Extensions) >= ",Pos,",element(",Pos,",Extensions) == 1 ->",nl])
+ end,
+ put(component_type,{true,C}),
+ {TermVar,BytesVar} = gen_dec_line(TopType,Cname,Type,Tpos,DecInfObj,Ext),
+ erase(component_type),
+ case {Ext,Prop} of
+ {noext,mandatory} -> true; % generate nothing
+ {noext,_} ->
+ emit([";",nl,"0 ->"]),
+ gen_dec_component_no_val(TopType,Cname,Type,Prop,Tpos,Ext);
+ _ ->
+ emit([";",nl,"_ ->",nl]),
+ gen_dec_component_no_val(TopType,Cname,Type,Prop,Tpos,Ext)
+ end,
+ case {Ext,Prop} of
+ {noext,mandatory} -> true; % generate nothing
+ {noext,_} ->
+ emit([nl,"end"]);
+ _ ->
+ emit([nl,"end"])
+
+ end,
+ asn1ct_name:new(bytes),
+ case Rest of
+ [] ->
+ {Pos+1,AccTerm++TermVar,AccBytes++BytesVar};
+ _ ->
+ emit({com,nl}),
+ gen_dec_components_call1(TopType,Rest,Tpos+1,NewOptPos,"",DecInfObj,Ext,
+ AccTerm++TermVar,AccBytes++BytesVar,NumberOfOptionals)
+ end;
+
+gen_dec_components_call1(_TopType,[],Pos,_OptPos,_,_,_,AccTerm,AccBytes,_NumberOfOptionals) ->
+ {Pos,AccTerm,AccBytes}.
+
+
+%%gen_dec_component_no_val(TopType,Cname,Type,_,Pos,{ext,Ep,Enum}) when Pos >= Ep ->
+%% emit({"{asn1_NOEXTVALUE,",{curr,bytes},"}",nl});
+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_line(TopType,Cname,Type,Pos,DecInfObj,Ext) ->
+ Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
+ asn1ct_gen:rt2ct_suffix()])),
+ Atype =
+ case Type of
+ #type{def=#'ObjectClassFieldType'{type=InnerType}} ->
+ InnerType;
+ _ ->
+ asn1ct_gen:get_inner(Type#type.def)
+ end,
+% case asn1ct_gen:get_constraint(Type#type.constraint,
+% tableconstraint_info) of
+% no ->
+% asn1ct_gen:get_inner(Type#type.def);
+% _ ->
+% Type#type.def
+% end,
+ BytesVar0 = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
+ BytesVar = case Ext of
+ {ext,Ep,_} when Pos >= Ep ->
+ emit(["begin",nl,"{TmpVal",Pos,",Trem",Pos,
+ "}=?RT_PER:decode_open_type(",
+ {curr,bytes},",[]),",nl,
+ "{TmpValx",Pos,",_}="]),
+ io_lib:format("TmpVal~p",[Pos]);
+ _ -> BytesVar0
+ end,
+ SaveBytes =
+ case Atype of
+ {typefield,_} ->
+ case DecInfObj of
+ false -> % This is in a choice with typefield components
+ {Name,RestFieldNames} =
+ (Type#type.def)#'ObjectClassFieldType'.fieldname,
+% asn1ct_gen:get_constraint(Type#type.constraint,
+% tableconstraint_info),
+ asn1ct_name:new(tmpterm),
+ asn1ct_name:new(reason),
+ emit([indent(2),"{",{curr,tmpterm},", ",{next,bytes},
+ "} = ?RT_PER:decode_open_type(",{curr,bytes},
+ ", []),",nl]),
+ emit([indent(2),"case (catch ObjFun(",
+ {asis,Name},
+ ",",{curr,tmpterm},",telltype,",
+ {asis,RestFieldNames},")) of", nl]),
+ emit([indent(4),"{'EXIT',",{curr,reason},"} ->",nl]),
+ emit([indent(6),"exit({'Type not ",
+ "compatible with table constraint', ",
+ {curr,reason},"});",nl]),
+ asn1ct_name:new(tmpterm),
+ emit([indent(4),"{",{curr,tmpterm},", _} ->",nl]),
+ emit([indent(6),"{",Cname,", {",{curr,tmpterm},", ",
+ {next,bytes},"}}",nl]),
+ emit([indent(2),"end"]),
+ [];
+ {"got objfun through args","ObjFun"} ->
+ %% this is when the generated code gots the
+ %% objfun though arguments on function
+ %% invocation.
+ {Name,RestFieldNames} =
+ (Type#type.def)#'ObjectClassFieldType'.fieldname,
+ emit(["?RT_PER:decode_open_type(",{curr,bytes},
+ ", []),",nl]),
+ emit([{curr,term}," =",nl,
+ " case (catch ObjFun(",{asis,Name},",",
+ {curr,tmpterm},",telltype,",
+ {asis,RestFieldNames},")) of", nl]),
+ emit([" {'EXIT',",{curr,reason},"} ->",nl]),
+ emit([indent(6),"exit({'Type not ",
+ "compatible with table constraint', ",
+ {curr,reason},"});",nl]),
+ asn1ct_name:new(tmpterm),
+ emit([indent(4),"{",{curr,tmpterm},", _} ->",nl]),
+ emit([indent(6),{curr,tmpterm},nl]),
+ emit([indent(2),"end"]),
+ [];
+ _ ->
+ emit({"?RT_PER:decode_open_type(",{curr,bytes},
+ ", [])"}),
+ RefedFieldName =
+ (Type#type.def)#'ObjectClassFieldType'.fieldname,
+% asn1ct_gen:get_constraint(Type#type.constraint,
+% tableconstraint_info),
+ [{Cname,RefedFieldName,
+ asn1ct_gen:mk_var(asn1ct_name:curr(term)),
+ asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
+ get_components_prop()}]
+ end;
+ {objectfield,PrimFieldName1,PFNList} ->
+ emit({"?RT_PER:decode_open_type(",{curr,bytes},", [])"}),
+ [{Cname,{PrimFieldName1,PFNList},
+ asn1ct_gen:mk_var(asn1ct_name:curr(term)),
+ asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
+ get_components_prop()}];
+ _ ->
+ CurrMod = get(currmod),
+ case asn1ct_gen:type(Atype) of
+ #'Externaltypereference'{module=CurrMod,type=EType} ->
+ emit({"'dec_",EType,"'(",BytesVar,",telltype)"});
+ #'Externaltypereference'{module=Mod,type=EType} ->
+ emit({"'",Mod,"':'dec_",EType,"'(",BytesVar,
+ ",telltype)"});
+ {primitive,bif} ->
+ case Atype of
+ {fixedtypevaluefield,_,Btype} ->
+ Ctgenmod:gen_dec_prim(per,Btype,
+ BytesVar);
+ _ ->
+ Ctgenmod:gen_dec_prim(per,Type,
+ BytesVar)
+ end;
+ 'ASN1_OPEN_TYPE' ->
+ case Type#type.def of
+ #'ObjectClassFieldType'{type=OpenType} ->
+ Ctgenmod:gen_dec_prim(per,#type{def=OpenType},
+ BytesVar);
+ _ ->
+ Ctgenmod:gen_dec_prim(per,Type,
+ BytesVar)
+ end;
+ #typereference{val=Dname} ->
+ emit({"'dec_",Dname,"'(",BytesVar,",telltype)"});
+ {notype,_} ->
+ emit({"'dec_",Atype,"'(",BytesVar,",telltype)"});
+ {constructed,bif} ->
+ NewTypename = [Cname|TopType],
+ case Type#type.tablecinf of
+ [{objfun,_}|_R] ->
+ emit({"'dec_",asn1ct_gen:list2name(NewTypename),
+ "'(",BytesVar,", telltype, ObjFun)"});
+ _ ->
+ emit({"'dec_",asn1ct_gen:list2name(NewTypename),
+ "'(",BytesVar,", telltype)"})
+ end
+ end,
+ case DecInfObj of
+ {Cname,{_,OSet,UniqueFName,ValIndex}} ->
+ Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
+ ValueMatch = value_match(ValIndex,Term),
+ emit({",",nl,"ObjFun = 'getdec_",OSet,"'(",
+ {asis,UniqueFName},", ",ValueMatch,")"});
+ _ ->
+ ok
+ end,
+ []
+ end,
+ case Ext of
+ {ext,Ep2,_} when Pos >= Ep2 ->
+ emit([", {TmpValx",Pos,",Trem",Pos,"}",nl,"end"]);
+ _ -> true
+ end,
+ %% Prepare return value
+ case DecInfObj of
+ {Cname,ObjSet} ->
+ {[{ObjSet,Cname,asn1ct_gen:mk_var(asn1ct_name:curr(term))}],
+ SaveBytes};
+ _ ->
+ {[],SaveBytes}
+ end.
+
+gen_enc_choice(TopType,CompList,Ext) ->
+ gen_enc_choice_tag(CompList, [], Ext),
+ emit({com,nl}),
+ emit({"case element(1,Val) of",nl}),
+ gen_enc_choice2(TopType, CompList, Ext),
+ emit({nl,"end"}).
+
+gen_enc_choice_tag({C1,C2},_,_) ->
+ N1 = get_name_list(C1),
+ 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(C,_,_) ->
+ N = get_name_list(C),
+ emit(["?RT_PER:set_choice(element(1,Val),",
+ {asis,N},", ",{asis,length(N)},")"]).
+
+get_name_list(L) ->
+ get_name_list(L,[]).
+
+get_name_list([#'ComponentType'{name=Name}|T], Acc) ->
+ get_name_list(T,[Name|Acc]);
+get_name_list([], Acc) ->
+ lists:reverse(Acc).
+
+%gen_enc_choice_tag([H|T],Acc,Ext) when record(H,'ComponentType') ->
+% gen_enc_choice_tag(T,[H#'ComponentType'.name|Acc],Ext);
+%gen_enc_choice_tag([H|T],Acc,Ext) -> % skip EXTENSIONMARK
+% gen_enc_choice_tag(T,Acc,Ext);
+%gen_enc_choice_tag([],Acc,Ext) ->
+% Length = length(Acc),
+% emit({"?RT_PER:set_choice(element(1,Val),",{asis,Length},",",
+% {asis,lists:reverse(Acc)},",",{asis,Ext},")"}),
+% Length.
+
+gen_enc_choice2(TopType, {L1,L2}, Ext) ->
+ gen_enc_choice2(TopType, L1 ++ L2, 0, Ext);
+gen_enc_choice2(TopType, L, Ext) ->
+ gen_enc_choice2(TopType, L, 0, Ext).
+
+gen_enc_choice2(TopType,[H1,H2|T], Pos, Ext)
+when record(H1,'ComponentType'), record(H2,'ComponentType') ->
+ Cname = H1#'ComponentType'.name,
+ Type = H1#'ComponentType'.typespec,
+ EncObj =
+% case asn1ct_gen:get_constraint(Type#type.constraint,
+% tableconstraint_info) of
+% no ->
+% false;
+% _ ->
+% {no_attr,"ObjFun"}
+% end,
+ case asn1ct_gen:get_constraint(Type#type.constraint,
+ componentrelation) of
+ no -> false;
+ _ -> {no_attr,"ObjFun"}
+ end,
+ emit({{asis,Cname}," ->",nl}),
+ gen_enc_line(TopType,Cname,Type,"element(2,Val)", Pos+1,EncObj,Ext),
+ emit({";",nl}),
+ gen_enc_choice2(TopType,[H2|T], Pos+1, Ext);
+gen_enc_choice2(TopType,[H1|T], Pos, Ext) when record(H1,'ComponentType') ->
+ Cname = H1#'ComponentType'.name,
+ Type = H1#'ComponentType'.typespec,
+ EncObj =
+% case asn1ct_gen:get_constraint(Type#type.constraint,
+% tableconstraint_info) of
+% no ->
+% false;
+% _ ->
+% {no_attr,"ObjFun"}
+% end,
+ case asn1ct_gen:get_constraint(Type#type.constraint,
+ componentrelation) of
+ no -> false;
+ _ -> {no_attr,"ObjFun"}
+ end,
+ emit({{asis,H1#'ComponentType'.name}," ->",nl}),
+ gen_enc_line(TopType,Cname,Type,"element(2,Val)", Pos+1,EncObj,Ext),
+ gen_enc_choice2(TopType,T, Pos+1, Ext);
+gen_enc_choice2(_,[], _, _) ->
+ true.
+
+gen_dec_choice(TopType,CompList,{ext,Pos,NumExt}) ->
+ emit({"{Ext,",{curr,bytes},"} = ?RT_PER:getbit(Bytes),",nl}),
+ asn1ct_name:new(bytes),
+ gen_dec_choice1(TopType,CompList,{ext,Pos,NumExt});
+gen_dec_choice(TopType,CompList,noext) ->
+ gen_dec_choice1(TopType,CompList,noext).
+
+gen_dec_choice1(TopType,CompList,noext) ->
+ emit({"{Choice,",{curr,bytes},
+ "} = ?RT_PER:getchoice(",{prev,bytes},",",
+ length(CompList),", 0),",nl}),
+ emit({"{Cname,{Val,NewBytes}} = case Choice of",nl}),
+ gen_dec_choice2(TopType,CompList,noext),
+ emit({nl,"end,",nl}),
+ emit({nl,"{{Cname,Val},NewBytes}"});
+gen_dec_choice1(TopType,{RootList,ExtList},Ext) ->
+ NewList = RootList ++ ExtList,
+ gen_dec_choice1(TopType, NewList, Ext);
+gen_dec_choice1(TopType,CompList,{ext,ExtPos,ExtNum}) ->
+ emit({"{Choice,",{curr,bytes},
+ "} = ?RT_PER:getchoice(",{prev,bytes},",",
+ length(CompList)-ExtNum,",Ext ),",nl}),
+ emit({"{Cname,{Val,NewBytes}} = case Choice + Ext*",ExtPos-1," of",nl}),
+ gen_dec_choice2(TopType,CompList,{ext,ExtPos,ExtNum}),
+ emit([";",nl,"_ -> {asn1_ExtAlt, ?RT_PER:decode_open_type(",{curr,bytes},",[])}"]),
+ emit({nl,"end,",nl}),
+ emit({nl,"{{Cname,Val},NewBytes}"}).
+
+
+gen_dec_choice2(TopType,L,Ext) ->
+ gen_dec_choice2(TopType,L,0,Ext).
+
+gen_dec_choice2(TopType,[H1,H2|T],Pos,Ext)
+when record(H1,'ComponentType'), record(H2,'ComponentType') ->
+ Cname = H1#'ComponentType'.name,
+ Type = H1#'ComponentType'.typespec,
+ case Type#type.def of
+ #'ObjectClassFieldType'{type={typefield,_}} ->
+ emit({Pos," -> ",nl}),
+ wrap_gen_dec_line(H1,TopType,Cname,Type,Pos+1,false,Ext),
+ emit({";",nl});
+ _ ->
+ emit({Pos," -> {",{asis,Cname},",",nl}),
+ wrap_gen_dec_line(H1,TopType,Cname,Type,Pos+1,false,Ext),
+ emit({"};",nl})
+ end,
+ gen_dec_choice2(TopType,[H2|T],Pos+1,Ext);
+gen_dec_choice2(TopType,[H1,_H2|T],Pos,Ext) when record(H1,'ComponentType') ->
+ gen_dec_choice2(TopType,[H1|T],Pos,Ext); % skip extensionmark
+gen_dec_choice2(TopType,[H1|T],Pos,Ext) when record(H1,'ComponentType') ->
+ Cname = H1#'ComponentType'.name,
+ Type = H1#'ComponentType'.typespec,
+ case Type#type.def of
+ #'ObjectClassFieldType'{type={typefield,_}} ->
+ emit({Pos," -> ",nl}),
+ wrap_gen_dec_line(H1,TopType,Cname,Type,Pos+1,false,Ext);
+ _ ->
+ emit({Pos," -> {",{asis,Cname},",",nl}),
+ wrap_gen_dec_line(H1,TopType,Cname,Type,Pos+1,false,Ext),
+ emit("}")
+ end,
+ gen_dec_choice2(TopType,[T],Pos+1);
+gen_dec_choice2(TopType,[_|T],Pos,Ext) ->
+ gen_dec_choice2(TopType,T,Pos,Ext);% skip extensionmark
+gen_dec_choice2(_,[],Pos,_) ->
+ Pos.
+
+indent(N) ->
+ lists:duplicate(N,32). % 32 = space
+
+gen_encode_prim_wrapper(CtgenMod,Erule,Cont,DoTag,Value) ->
+% put(component_type,true), % add more info in component_type
+ CtgenMod:gen_encode_prim(Erule,Cont,DoTag,Value).
+% erase(component_type).
+
+make_element(I,Val,Cname) ->
+ case lists:member(optimize,get(encoding_options)) of
+ false ->
+ io_lib:format("?RT_PER:cindex(~w,~s,~w)",[I,Val,Cname]);
+ _ ->
+ io_lib:format("element(~w,~s)",[I,Val])
+ end.
+
+wrap_gen_dec_line(C,TopType,Cname,Type,Pos,DIO,Ext) ->
+ put(component_type,{true,C}),
+ gen_dec_line(TopType,Cname,Type,Pos,DIO,Ext),
+ erase(component_type).
+
+get_components_prop() ->
+ case get(component_type) of
+ undefined ->
+ mandatory;
+ {true,#'ComponentType'{prop=Prop}} -> Prop
+ end.
+
+
+value_match(Index,Value) when atom(Value) ->
+ value_match(Index,atom_to_list(Value));
+value_match([],Value) ->
+ Value;
+value_match([{VI,_}|VIs],Value) ->
+ value_match1(Value,VIs,lists:concat(["element(",VI,","]),1).
+value_match1(Value,[],Acc,Depth) ->
+ Acc ++ Value ++ lists:concat(lists:duplicate(Depth,")"));
+value_match1(Value,[{VI,_}|VIs],Acc,Depth) ->
+ value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1).
+
+notice_value_match() ->
+ Module = get(currmod),
+ put(value_match,{true,Module}).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen.erl
new file mode 100644
index 0000000000..5d2f7a13bd
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen.erl
@@ -0,0 +1,1664 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1ct_gen.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
+%%
+-module(asn1ct_gen).
+
+-include("asn1_records.hrl").
+%%-compile(export_all).
+-export([pgen_exports/3,
+ pgen_hrl/4,
+ gen_head/3,
+ demit/1,
+ emit/1,
+ fopen/2,
+ get_inner/1,type/1,def_to_tag/1,prim_bif/1,
+ type_from_object/1,
+ get_typefromobject/1,get_fieldcategory/2,
+ get_classfieldcategory/2,
+ list2name/1,
+ list2rname/1,
+ constructed_suffix/2,
+ unify_if_string/1,
+ gen_check_call/7,
+ get_constraint/2,
+ insert_once/2,
+ rt2ct_suffix/1,rt2ct_suffix/0]).
+-export([pgen/4,pgen_module/5,mk_var/1, un_hyphen_var/1]).
+-export([gen_encode_constructed/4,gen_decode_constructed/4]).
+
+%% pgen(Erules, Module, TypeOrVal)
+%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module
+%% .hrl file is only generated if necessary
+%% Erules = per | ber | ber_bin | per_bin
+%% Module = atom()
+%% TypeOrVal = {TypeList,ValueList}
+%% TypeList = ValueList = [atom()]
+
+pgen(OutFile,Erules,Module,TypeOrVal) ->
+ pgen_module(OutFile,Erules,Module,TypeOrVal,true).
+
+
+pgen_module(OutFile,Erules,Module,TypeOrVal,Indent) ->
+ put(outfile,OutFile),
+ HrlGenerated = asn1ct_gen:pgen_hrl(Erules,Module,TypeOrVal,Indent),
+ asn1ct_name:start(),
+ ErlFile = lists:concat([OutFile,".erl"]),
+ Fid = asn1ct_gen:fopen(ErlFile,write),
+ put(gen_file_out,Fid),
+ asn1ct_gen:gen_head(Erules,Module,HrlGenerated),
+ pgen_exports(Erules,Module,TypeOrVal),
+ pgen_dispatcher(Erules,Module,TypeOrVal),
+ pgen_info(Erules,Module),
+ pgen_typeorval(wrap_ber(Erules),Module,TypeOrVal),
+ pgen_partial_incomplete_decode(Erules),
+% gen_vars(asn1_db:mod_to_vars(Module)),
+% gen_tag_table(AllTypes),
+ file:close(Fid),
+ io:format("--~p--~n",[{generated,ErlFile}]).
+
+
+pgen_typeorval(Erules,Module,{Types,Values,_Ptypes,_Classes,Objects,ObjectSets}) ->
+ pgen_types(Erules,Module,Types),
+ pgen_values(Erules,Module,Values),
+ pgen_objects(Erules,Module,Objects),
+ pgen_objectsets(Erules,Module,ObjectSets),
+ case catch lists:member(der,get(encoding_options)) of
+ true ->
+ pgen_check_defaultval(Erules,Module);
+ _ -> ok
+ end,
+ pgen_partial_decode(Erules,Module).
+
+pgen_values(_,_,[]) ->
+ true;
+pgen_values(Erules,Module,[H|T]) ->
+ Valuedef = asn1_db:dbget(Module,H),
+ gen_value(Valuedef),
+ pgen_values(Erules,Module,T).
+
+pgen_types(_,Module,[]) ->
+ gen_value_match(Module),
+ true;
+pgen_types(Erules,Module,[H|T]) ->
+ Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
+ rt2ct_suffix(Erules)])),
+ asn1ct_name:clear(),
+ Typedef = asn1_db:dbget(Module,H),
+ Rtmod:gen_encode(Erules,Typedef),
+ asn1ct_name:clear(),
+ Rtmod:gen_decode(Erules,Typedef),
+ pgen_types(Erules,Module,T).
+
+pgen_objects(_,_,[]) ->
+ true;
+pgen_objects(Erules,Module,[H|T]) ->
+ Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
+ rt2ct_suffix(Erules)])),
+ asn1ct_name:clear(),
+ Typedef = asn1_db:dbget(Module,H),
+ Rtmod:gen_obj_code(Erules,Module,Typedef),
+ pgen_objects(Erules,Module,T).
+
+pgen_objectsets(_,_,[]) ->
+ true;
+pgen_objectsets(Erules,Module,[H|T]) ->
+ Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
+ rt2ct_suffix(Erules)])),
+ asn1ct_name:clear(),
+ TypeDef = asn1_db:dbget(Module,H),
+ Rtmod:gen_objectset_code(Erules,TypeDef),
+ pgen_objectsets(Erules,Module,T).
+
+pgen_check_defaultval(Erules,Module) ->
+ CheckObjects = ets:tab2list(check_functions),
+ case get(asndebug) of
+ true ->
+ FileName = lists:concat([Module,'.table']),
+ {ok,IoDevice} = file:open(FileName,[write]),
+ Fun =
+ fun(X)->
+ io:format(IoDevice,"~n~n************~n~n~p~n~n*****"
+ "********~n~n",[X])
+ end,
+ lists:foreach(Fun,CheckObjects),
+ file:close(IoDevice);
+ _ -> ok
+ end,
+ gen_check_defaultval(Erules,Module,CheckObjects).
+
+pgen_partial_decode(Erules,Module) ->
+ pgen_partial_inc_dec(Erules,Module),
+ pgen_partial_dec(Erules,Module).
+
+pgen_partial_inc_dec(Erules,Module) ->
+% io:format("Start partial incomplete decode gen?~n"),
+ case asn1ct:get_gen_state_field(inc_type_pattern) of
+ undefined ->
+% io:format("Partial incomplete decode gen not started:�~w~n",[asn1ct:get_gen_state_field(active)]),
+ ok;
+% [] ->
+% ok;
+ ConfList ->
+ PatternLists=lists:map(fun({_,P}) -> P end,ConfList),
+ pgen_partial_inc_dec1(Erules,Module,PatternLists),
+ gen_partial_inc_dec_refed_funcs(Erules)
+ end.
+
+%% pgen_partial_inc_dec1 generates a function of the toptype in each
+%% of the partial incomplete decoded types.
+pgen_partial_inc_dec1(Erules,Module,[P|Ps]) ->
+ Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
+ rt2ct_suffix(Erules)])),
+ TopTypeName = asn1ct:partial_inc_dec_toptype(P),
+ TypeDef=asn1_db:dbget(Module,TopTypeName),
+ asn1ct_name:clear(),
+ asn1ct:update_gen_state(namelist,P),
+ asn1ct:update_gen_state(active,true),
+ asn1ct:update_gen_state(prefix,"dec-inc-"),
+ Rtmod:gen_decode(Erules,TypeDef),
+%% asn1ct:update_gen_state(namelist,tl(P)), %%
+ gen_dec_part_inner_constr(Erules,TypeDef,[TopTypeName]),
+ pgen_partial_inc_dec1(Erules,Module,Ps);
+pgen_partial_inc_dec1(_,_,[]) ->
+ ok.
+
+gen_partial_inc_dec_refed_funcs(Erule) when Erule == ber_bin_v2 ->
+ Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erule),
+ rt2ct_suffix(Erule)])),
+ case asn1ct:next_refed_func() of
+ [] ->
+ ok;
+ {#'Externaltypereference'{module=M,type=Name},Pattern} ->
+ TypeDef = asn1_db:dbget(M,Name),
+ asn1ct:update_gen_state(namelist,Pattern),
+ Rtmod:gen_inc_decode(Erule,TypeDef),
+ gen_dec_part_inner_constr(Erule,TypeDef,[Name]),
+ gen_partial_inc_dec_refed_funcs(Erule);
+ _ ->
+ gen_partial_inc_dec_refed_funcs(Erule)
+ end;
+gen_partial_inc_dec_refed_funcs(_) ->
+ ok.
+
+pgen_partial_dec(_Erules,_Module) ->
+ ok. %%%% implement later
+
+%% generate code for all inner types that are called from the top type
+%% of the partial incomplete decode
+gen_dec_part_inner_constr(Erules,TypeDef,TypeName) ->
+ Def = TypeDef#typedef.typespec,
+ InnerType = asn1ct_gen:get_inner(Def#type.def),
+ case InnerType of
+ 'SET' ->
+ #'SET'{components=Components} = Def#type.def,
+ gen_dec_part_inner_types(Erules,Components,TypeName);
+ %% Continue generate the inner of each component
+ 'SEQUENCE' ->
+ #'SEQUENCE'{components=Components} = Def#type.def,
+ gen_dec_part_inner_types(Erules,Components,TypeName);
+ 'CHOICE' ->
+ {_,Components} = Def#type.def,
+ gen_dec_part_inner_types(Erules,Components,TypeName);
+ 'SEQUENCE OF' ->
+ %% this and next case must be the last component in the
+ %% partial decode chain here. Not likely that this occur.
+ {_,Type} = Def#type.def,
+ NameSuffix = constructed_suffix(InnerType,Type#type.def),
+ Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
+ rt2ct_suffix(Erules)])),
+ asn1ct_name:clear(),
+ Rtmod:gen_decode(Erules,[NameSuffix|TypeName],Type);
+%% gen_types(Erules,[NameSuffix|Typename],Type);
+ 'SET OF' ->
+ {_,Type} = Def#type.def,
+ NameSuffix = constructed_suffix(InnerType,Type#type.def),
+ Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
+ rt2ct_suffix(Erules)])),
+ asn1ct_name:clear(),
+ Rtmod:gen_decode(Erules,[NameSuffix|TypeName],Type);
+ _ ->
+ ok
+ end.
+
+gen_dec_part_inner_types(Erules,[ComponentType|Rest],TypeName) ->
+ Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
+ rt2ct_suffix(Erules)])),
+ asn1ct_name:clear(),
+ Rtmod:gen_decode(Erules,TypeName,ComponentType),
+ gen_dec_part_inner_types(Erules,Rest,TypeName);
+gen_dec_part_inner_types(Erules,{Comps1,Comps2},TypeName)
+ when list(Comps1),list(Comps2) ->
+ gen_dec_part_inner_types(Erules,Comps1 ++ Comps2,TypeName);
+gen_dec_part_inner_types(_,[],_) ->
+ ok.
+
+
+pgen_partial_incomplete_decode(Erule) ->
+ case asn1ct:get_gen_state_field(active) of
+ true ->
+ pgen_partial_incomplete_decode1(Erule),
+ asn1ct:reset_gen_state();
+ _ ->
+ ok
+ end.
+pgen_partial_incomplete_decode1(ber_bin_v2) ->
+ case asn1ct:read_config_data(partial_incomplete_decode) of
+ undefined ->
+ ok;
+ Data ->
+ lists:foreach(fun emit_partial_incomplete_decode/1,Data)
+ end,
+ GeneratedFs= asn1ct:get_gen_state_field(gen_refed_funcs),
+% io:format("GeneratedFs :~n~p~n",[GeneratedFs]),
+ gen_part_decode_funcs(GeneratedFs,0);
+pgen_partial_incomplete_decode1(_) -> ok.
+
+emit_partial_incomplete_decode({FuncName,TopTypeName,Pattern}) ->
+ emit([{asis,FuncName},"(Bytes) ->",nl,
+ " decode_partial_incomplete(",{asis,TopTypeName},",Bytes,",{asis,Pattern},").",nl]);
+emit_partial_incomplete_decode(D) ->
+ throw({error,{asn1,{"bad data in asn1config file",D}}}).
+
+gen_part_decode_funcs([Data={Name,_,_,Type}|GeneratedFs],N) ->
+ InnerType =
+ case Type#type.def of
+ #'ObjectClassFieldType'{type=OCFTType} ->
+ OCFTType;
+ _ ->
+ get_inner(Type#type.def)
+ end,
+ WhatKind = type(InnerType),
+ TypeName=list2name(Name),
+ if
+ N > 0 -> emit([";",nl]);
+ true -> ok
+ end,
+ emit(["decode_inc_disp('",TypeName,"',Data) ->",nl]),
+ gen_part_decode_funcs(WhatKind,TypeName,Data),
+ gen_part_decode_funcs(GeneratedFs,N+1);
+gen_part_decode_funcs([_H|T],N) ->
+ gen_part_decode_funcs(T,N);
+gen_part_decode_funcs([],N) ->
+ if
+ N > 0 ->
+ .emit([".",nl]);
+ true ->
+ ok
+ end.
+
+gen_part_decode_funcs(#'Externaltypereference'{module=M,type=T},
+ _TypeName,Data) ->
+ #typedef{typespec=TS} = asn1_db:dbget(M,T),
+ InnerType =
+ case TS#type.def of
+ #'ObjectClassFieldType'{type=OCFTType} ->
+ OCFTType;
+ _ ->
+ get_inner(TS#type.def)
+ end,
+ WhatKind = type(InnerType),
+ gen_part_decode_funcs(WhatKind,[T],Data);
+gen_part_decode_funcs({constructed,bif},TypeName,
+ {_Name,parts,Tag,_Type}) ->
+ emit([" case Data of",nl,
+ " L when list(L) ->",nl,
+ " 'dec_",TypeName,"'(lists:map(fun(X)->element(1,?RT_BER:decode(X)) end,L),",{asis,Tag},");",nl,
+ " _ ->",nl,
+ " [Res] = 'dec_",TypeName,"'([Data],",{asis,Tag},"),",nl,
+ " Res",nl,
+ " end"]);
+gen_part_decode_funcs(WhatKind,_TypeName,{_Name,parts,_Tag,_Type}) ->
+ throw({error,{asn1,{"only SEQUENCE OF/SET OF may have the partial incomplete directive 'parts'.",WhatKind}}});
+gen_part_decode_funcs({constructed,bif},TypeName,
+ {_Name,undecoded,Tag,_Type}) ->
+ emit([" 'dec_",TypeName,"'(Data,",{asis,Tag},")"]);
+gen_part_decode_funcs({primitive,bif},_TypeName,
+ {_Name,undecoded,Tag,Type}) ->
+ % Argument no 6 is 0, i.e. bit 6 for primitive encoding.
+ asn1ct_gen_ber_bin_v2:gen_dec_prim(ber_bin_v2,Type,"Data",Tag,[],0,", mandatory, ");
+gen_part_decode_funcs(WhatKind,_TypeName,{_,Directive,_,_}) ->
+ throw({error,{asn1,{"Not implemented yet",WhatKind," partial incomplete directive:",Directive}}}).
+
+gen_types(Erules,Tname,{RootList,ExtList}) when list(RootList) ->
+ gen_types(Erules,Tname,RootList),
+ gen_types(Erules,Tname,ExtList);
+gen_types(Erules,Tname,[{'EXTENSIONMARK',_,_}|Rest]) ->
+ gen_types(Erules,Tname,Rest);
+gen_types(Erules,Tname,[ComponentType|Rest]) ->
+ Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
+ rt2ct_suffix(Erules)])),
+ asn1ct_name:clear(),
+ Rtmod:gen_encode(Erules,Tname,ComponentType),
+ asn1ct_name:clear(),
+ Rtmod:gen_decode(Erules,Tname,ComponentType),
+ gen_types(Erules,Tname,Rest);
+gen_types(_,_,[]) ->
+ true;
+gen_types(Erules,Tname,Type) when record(Type,type) ->
+ Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
+ rt2ct_suffix(Erules)])),
+ asn1ct_name:clear(),
+ Rtmod:gen_encode(Erules,Tname,Type),
+ asn1ct_name:clear(),
+ Rtmod:gen_decode(Erules,Tname,Type).
+
+gen_value_match(Module) ->
+ case get(value_match) of
+ {true,Module} ->
+ emit(["value_match([{Index,Cname}|Rest],Value) ->",nl,
+ " Value2 =",nl,
+ " case element(Index,Value) of",nl,
+ " {Cname,Val2} -> Val2;",nl,
+ " X -> X",nl,
+ " end,",nl,
+ " value_match(Rest,Value2);",nl,
+ "value_match([],Value) ->",nl,
+ " Value.",nl]);
+ _ -> ok
+ end,
+ put(value_match,undefined).
+
+gen_check_defaultval(Erules,Module,[{Name,Type}|Rest]) ->
+ gen_check_func(Name,Type),
+ gen_check_defaultval(Erules,Module,Rest);
+gen_check_defaultval(_,_,[]) ->
+ ok.
+
+gen_check_func(Name,FType = #type{def=Def}) ->
+ emit({Name,"(V,asn1_DEFAULT) ->",nl," true;",nl}),
+ emit({Name,"(V,V) ->",nl," true;",nl}),
+ emit({Name,"(V,{_,V}) ->",nl," true;",nl}),
+ case Def of
+ {'SEQUENCE OF',Type} ->
+ gen_check_sof(Name,'SEQOF',Type);
+ {'SET OF',Type} ->
+ gen_check_sof(Name,'SETOF',Type);
+ #'SEQUENCE'{components=Components} ->
+ gen_check_sequence(Name,Components);
+ #'SET'{components=Components} ->
+ gen_check_sequence(Name,Components);
+ {'CHOICE',Components} ->
+ gen_check_choice(Name,Components);
+ #'Externaltypereference'{type=T} ->
+ emit({Name,"(DefaultValue,Value) ->",nl}),
+ emit({" ",list2name([T,check]),"(DefaultValue,Value).",nl});
+ MaybePrim ->
+ InnerType = get_inner(MaybePrim),
+ case type(InnerType) of
+ {primitive,bif} ->
+ emit({Name,"(DefaultValue,Value) ->",nl," "}),
+ gen_prim_check_call(InnerType,"DefaultValue","Value",
+ FType),
+ emit({".",nl,nl});
+ _ ->
+ throw({asn1_error,{unknown,type,MaybePrim}})
+ end
+ end.
+
+gen_check_sof(Name,SOF,Type) ->
+ NewName = list2name([sorted,Name]),
+ emit({Name,"(V1,V2) ->",nl}),
+ emit({" ",NewName,"(lists:sort(V1),lists:sort(V2)).",nl,nl}),
+ emit({NewName,"([],[]) ->",nl," true;",nl}),
+ emit({NewName,"([DV|DVs],[V|Vs]) ->",nl," "}),
+ InnerType = get_inner(Type#type.def),
+ case type(InnerType) of
+ {primitive,bif} ->
+ gen_prim_check_call(InnerType,"DV","V",Type),
+ emit({",",nl});
+ {constructed,bif} ->
+ emit({list2name([SOF,Name]),"(DV, V),",nl});
+ #'Externaltypereference'{type=T} ->
+ emit({list2name([T,check]),"(DV,V),",nl})
+ end,
+ emit({" ",NewName,"(DVs,Vs).",nl,nl}).
+
+gen_check_sequence(Name,Components) ->
+ emit({Name,"(DefaultValue,Value) ->",nl}),
+ gen_check_sequence(Name,Components,1).
+gen_check_sequence(Name,[#'ComponentType'{name=N,typespec=Type}|Cs],Num) ->
+ InnerType = get_inner(Type#type.def),
+% NthDefV = lists:concat(["lists:nth(",Num,",DefaultValue)"]),
+ NthDefV = ["element(",Num+1,",DefaultValue)"],
+% NthV = lists:concat(["lists:nth(",Num,",Value)"]),
+ NthV = ["element(",Num+1,",Value)"],
+ gen_check_func_call(Name,Type,InnerType,NthDefV,NthV,N),
+ case Cs of
+ [] ->
+ emit({".",nl,nl});
+ _ ->
+ emit({",",nl}),
+ gen_check_sequence(Name,Cs,Num+1)
+ end;
+gen_check_sequence(_,[],_) ->
+ ok.
+
+gen_check_choice(Name,CList=[#'ComponentType'{}|_Cs]) ->
+ emit({Name,"({Id,DefaultValue},{Id,Value}) ->",nl}),
+ emit({" case Id of",nl}),
+ gen_check_choice_components(Name,CList,1).
+
+gen_check_choice_components(_,[],_)->
+ ok;
+gen_check_choice_components(Name,[#'ComponentType'{name=N,typespec=Type}|
+ Cs],Num) ->
+ Ind6 = " ",
+ InnerType = get_inner(Type#type.def),
+% DefVal = ["element(2,lists:nth(",Num,",DefaultValue))"],
+ emit({Ind6,N," ->",nl,Ind6}),
+ gen_check_func_call(Name,Type,InnerType,{var,"defaultValue"},
+ {var,"value"},N),
+ case Cs of
+ [] ->
+ emit({nl," end.",nl,nl});
+ _ ->
+ emit({";",nl}),
+ gen_check_choice_components(Name,Cs,Num+1)
+ end.
+
+gen_check_func_call(Name,Type,InnerType,DefVal,Val,N) ->
+ case type(InnerType) of
+ {primitive,bif} ->
+ emit(" "),
+ gen_prim_check_call(InnerType,DefVal,Val,Type);
+ #'Externaltypereference'{type=T} ->
+ emit({" ",list2name([T,check]),"(",DefVal,",",Val,")"});
+ _ ->
+ emit({" ",list2name([N,Name]),"(",DefVal,",",Val,")"})
+ end.
+
+
+%% VARIOUS GENERATOR STUFF
+%% *************************************************
+%%**************************************************
+
+mk_var(X) when atom(X) ->
+ list_to_atom(mk_var(atom_to_list(X)));
+
+mk_var([H|T]) ->
+ [H-32|T].
+
+%% Since hyphens are allowed in ASN.1 names, it may occur in a
+%% variable to. Turn a hyphen into a under-score sign.
+un_hyphen_var(X) when atom(X) ->
+ list_to_atom(un_hyphen_var(atom_to_list(X)));
+un_hyphen_var([45|T]) ->
+ [95|un_hyphen_var(T)];
+un_hyphen_var([H|T]) ->
+ [H|un_hyphen_var(T)];
+un_hyphen_var([]) ->
+ [].
+
+%% Generate value functions ***************
+%% ****************************************
+%% Generates a function 'V'/0 for each Value V defined in the ASN.1 module
+%% the function returns the value in an Erlang representation which can be
+%% used as input to the runtime encode functions
+
+gen_value(Value) when record(Value,valuedef) ->
+%% io:format(" ~w ",[Value#valuedef.name]),
+ emit({"'",Value#valuedef.name,"'() ->",nl}),
+ V = Value#valuedef.value,
+ emit([{asis,V},".",nl,nl]).
+
+gen_encode_constructed(Erules,Typename,InnerType,D) when record(D,type) ->
+
+ Rtmod = list_to_atom(lists:concat(["asn1ct_constructed_",erule(Erules)])),
+ case InnerType of
+ 'SET' ->
+ Rtmod:gen_encode_set(Erules,Typename,D),
+ #'SET'{components=Components} = D#type.def,
+ gen_types(Erules,Typename,Components);
+ 'SEQUENCE' ->
+ Rtmod:gen_encode_sequence(Erules,Typename,D),
+ #'SEQUENCE'{components=Components} = D#type.def,
+ gen_types(Erules,Typename,Components);
+ 'CHOICE' ->
+ Rtmod:gen_encode_choice(Erules,Typename,D),
+ {_,Components} = D#type.def,
+ gen_types(Erules,Typename,Components);
+ 'SEQUENCE OF' ->
+ Rtmod:gen_encode_sof(Erules,Typename,InnerType,D),
+ {_,Type} = D#type.def,
+ NameSuffix = asn1ct_gen:constructed_suffix(InnerType,Type#type.def),
+ gen_types(Erules,[NameSuffix|Typename],Type);
+ 'SET OF' ->
+ Rtmod:gen_encode_sof(Erules,Typename,InnerType,D),
+ {_,Type} = D#type.def,
+ NameSuffix = asn1ct_gen:constructed_suffix(InnerType,Type#type.def),
+ gen_types(Erules,[NameSuffix|Typename],Type);
+ _ ->
+ exit({nyi,InnerType})
+ end;
+gen_encode_constructed(Erules,Typename,InnerType,D)
+ when record(D,typedef) ->
+ gen_encode_constructed(Erules,Typename,InnerType,D#typedef.typespec).
+
+gen_decode_constructed(Erules,Typename,InnerType,D) when record(D,type) ->
+ Rtmod = list_to_atom(lists:concat(["asn1ct_constructed_",erule(Erules)])),
+ asn1ct:step_in_constructed(), %% updates namelist for incomplete
+ %% partial decode
+ case InnerType of
+ 'SET' ->
+ Rtmod:gen_decode_set(Erules,Typename,D);
+ 'SEQUENCE' ->
+ Rtmod:gen_decode_sequence(Erules,Typename,D);
+ 'CHOICE' ->
+ Rtmod:gen_decode_choice(Erules,Typename,D);
+ 'SEQUENCE OF' ->
+ Rtmod:gen_decode_sof(Erules,Typename,InnerType,D);
+ 'SET OF' ->
+ Rtmod:gen_decode_sof(Erules,Typename,InnerType,D);
+ _ ->
+ exit({nyi,InnerType})
+ end;
+
+
+gen_decode_constructed(Erules,Typename,InnerType,D) when record(D,typedef) ->
+ gen_decode_constructed(Erules,Typename,InnerType,D#typedef.typespec).
+
+
+pgen_exports(Erules,_Module,{Types,Values,_,_,Objects,ObjectSets}) ->
+ emit({"-export([encoding_rule/0]).",nl}),
+ case Types of
+ [] -> ok;
+ _ ->
+ emit({"-export([",nl}),
+ case Erules of
+ ber ->
+ gen_exports1(Types,"enc_",2);
+ ber_bin ->
+ gen_exports1(Types,"enc_",2);
+ ber_bin_v2 ->
+ gen_exports1(Types,"enc_",2);
+ _ ->
+ gen_exports1(Types,"enc_",1)
+ end,
+ emit({"-export([",nl}),
+ gen_exports1(Types,"dec_",2),
+ case Erules of
+ ber ->
+ emit({"-export([",nl}),
+ gen_exports1(Types,"dec_",3);
+ ber_bin ->
+ emit({"-export([",nl}),
+ gen_exports1(Types,"dec_",3);
+ ber_bin_v2 ->
+ emit({"-export([",nl}),
+ gen_exports1(Types,"dec_",2);
+ _ -> ok
+ end
+ end,
+ case Values of
+ [] -> ok;
+ _ ->
+ emit({"-export([",nl}),
+ gen_exports1(Values,"",0)
+ end,
+ case Objects of
+ [] -> ok;
+ _ ->
+ case erule(Erules) of
+ per ->
+ emit({"-export([",nl}),
+ gen_exports1(Objects,"enc_",3),
+ emit({"-export([",nl}),
+ gen_exports1(Objects,"dec_",4);
+ ber_bin_v2 ->
+ emit({"-export([",nl}),
+ gen_exports1(Objects,"enc_",3),
+ emit({"-export([",nl}),
+ gen_exports1(Objects,"dec_",3);
+ _ ->
+ emit({"-export([",nl}),
+ gen_exports1(Objects,"enc_",4),
+ emit({"-export([",nl}),
+ gen_exports1(Objects,"dec_",4)
+ end
+ end,
+ case ObjectSets of
+ [] -> ok;
+ _ ->
+ emit({"-export([",nl}),
+ gen_exports1(ObjectSets,"getenc_",2),
+ emit({"-export([",nl}),
+ gen_exports1(ObjectSets,"getdec_",2)
+ end,
+ emit({"-export([info/0]).",nl}),
+ gen_partial_inc_decode_exports(),
+ emit({nl,nl}).
+
+gen_exports1([F1,F2|T],Prefix,Arity) ->
+ emit({"'",Prefix,F1,"'/",Arity,com,nl}),
+ gen_exports1([F2|T],Prefix,Arity);
+gen_exports1([Flast|_T],Prefix,Arity) ->
+ emit({"'",Prefix,Flast,"'/",Arity,nl,"]).",nl,nl}).
+
+gen_partial_inc_decode_exports() ->
+ case {asn1ct:read_config_data(partial_incomplete_decode),
+ asn1ct:get_gen_state_field(inc_type_pattern)} of
+ {undefined,_} ->
+ ok;
+ {_,undefined} ->
+ ok;
+ {Data,_} ->
+ gen_partial_inc_decode_exports(Data),
+ emit("-export([decode_part/2]).")
+ end.
+gen_partial_inc_decode_exports([]) ->
+ ok;
+gen_partial_inc_decode_exports([{Name,_,_}|Rest]) ->
+ emit(["-export([",Name,"/1"]),
+ gen_partial_inc_decode_exports1(Rest);
+gen_partial_inc_decode_exports([_|Rest]) ->
+ gen_partial_inc_decode_exports(Rest).
+
+gen_partial_inc_decode_exports1([]) ->
+ emit(["]).",nl]);
+gen_partial_inc_decode_exports1([{Name,_,_}|Rest]) ->
+ emit([", ",Name,"/1"]),
+ gen_partial_inc_decode_exports1(Rest);
+gen_partial_inc_decode_exports1([_|Rest]) ->
+ gen_partial_inc_decode_exports1(Rest).
+
+pgen_dispatcher(Erules,_Module,{[],_Values,_,_,_Objects,_ObjectSets}) ->
+ emit(["encoding_rule() ->",nl]),
+ emit([{asis,Erules},".",nl,nl]);
+pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
+ emit(["-export([encode/2,decode/2,encode_disp/2,decode_disp/2]).",nl,nl]),
+ emit(["encoding_rule() ->",nl]),
+ emit([" ",{asis,Erules},".",nl,nl]),
+ Call = case Erules of
+ per -> "?RT_PER:complete(encode_disp(Type,Data))";
+ per_bin -> "?RT_PER:complete(encode_disp(Type,Data))";
+ ber -> "encode_disp(Type,Data)";
+ ber_bin -> "encode_disp(Type,Data)";
+ ber_bin_v2 -> "encode_disp(Type,Data)"
+ end,
+ EncWrap = case Erules of
+ ber -> "wrap_encode(Bytes)";
+ _ -> "Bytes"
+ end,
+ emit(["encode(Type,Data) ->",nl,
+ "case catch ",Call," of",nl,
+ " {'EXIT',{error,Reason}} ->",nl,
+ " {error,Reason};",nl,
+ " {'EXIT',Reason} ->",nl,
+ " {error,{asn1,Reason}};",nl,
+ " {Bytes,_Len} ->",nl,
+ " {ok,",EncWrap,"};",nl,
+ " Bytes ->",nl,
+ " {ok,",EncWrap,"}",nl,
+ "end.",nl,nl]),
+
+ case Erules of
+ ber_bin_v2 ->
+ emit(["decode(Type,Data0) ->",nl]),
+ emit(["{Data,_RestBin} = ?RT_BER:decode(Data0",driver_parameter(),"),",nl]);
+ _ ->
+ emit(["decode(Type,Data) ->",nl])
+ end,
+ DecWrap = case Erules of
+ ber -> "wrap_decode(Data)";
+ _ -> "Data"
+ end,
+
+ emit(["case catch decode_disp(Type,",DecWrap,") of",nl,
+ " {'EXIT',{error,Reason}} ->",nl,
+ " {error,Reason};",nl,
+ " {'EXIT',Reason} ->",nl,
+ " {error,{asn1,Reason}};",nl]),
+ case Erules of
+ ber_bin_v2 ->
+ emit([" Result ->",nl,
+ " {ok,Result}",nl]);
+ _ ->
+ emit([" {X,_Rest} ->",nl,
+ " {ok,X};",nl,
+ " {X,_Rest,_Len} ->",nl,
+ " {ok,X}",nl])
+ end,
+ emit(["end.",nl,nl]),
+
+ gen_decode_partial_incomplete(Erules),
+
+ case Types of
+ [] -> ok;
+ _ ->
+ case Erules of
+ ber ->
+ gen_dispatcher(Types,"encode_disp","enc_",",[]"),
+ gen_dispatcher(Types,"decode_disp","dec_",",mandatory");
+ ber_bin ->
+ gen_dispatcher(Types,"encode_disp","enc_",",[]"),
+ gen_dispatcher(Types,"decode_disp","dec_",",mandatory");
+ ber_bin_v2 ->
+ gen_dispatcher(Types,"encode_disp","enc_",""),
+ gen_dispatcher(Types,"decode_disp","dec_",""),
+ gen_partial_inc_dispatcher();
+ _PerOrPer_bin ->
+ gen_dispatcher(Types,"encode_disp","enc_",""),
+ gen_dispatcher(Types,"decode_disp","dec_",",mandatory")
+ end,
+ emit([nl])
+ end,
+ case Erules of
+ ber ->
+ gen_wrapper();
+ _ -> ok
+ end,
+ emit({nl,nl}).
+
+
+gen_decode_partial_incomplete(Erule) when Erule == ber;Erule==ber_bin;
+ Erule==ber_bin_v2 ->
+ case {asn1ct:read_config_data(partial_incomplete_decode),
+ asn1ct:get_gen_state_field(inc_type_pattern)} of
+ {undefined,_} ->
+ ok;
+ {_,undefined} ->
+ ok;
+ _ ->
+ case Erule of
+ ber_bin_v2 ->
+ EmitCaseClauses =
+ fun() ->
+ emit([" {'EXIT',{error,Reason}} ->",nl,
+ " {error,Reason};",nl,
+ " {'EXIT',Reason} ->",nl,
+ " {error,{asn1,Reason}};",nl,
+ " Result ->",nl,
+ " {ok,Result}",nl,
+ " end.",nl,nl])
+ end,
+ emit(["decode_partial_incomplete(Type,Data0,",
+ "Pattern) ->",nl]),
+ emit([" {Data,_RestBin} =",nl,
+ " ?RT_BER:decode_primitive_",
+ "incomplete(Pattern,Data0),",nl,
+ " case catch decode_partial_inc_disp(Type,",
+ "Data) of",nl]),
+ EmitCaseClauses(),
+ emit(["decode_part(Type,Data0) ->",nl,
+ " {Data,_RestBin} = ?RT_BER:decode(Data0),",nl,
+ " case catch decode_inc_disp(Type,Data) of",nl]),
+ EmitCaseClauses();
+ _ -> ok % add later
+ end
+ end;
+gen_decode_partial_incomplete(_Erule) ->
+ ok.
+
+gen_partial_inc_dispatcher() ->
+ case {asn1ct:read_config_data(partial_incomplete_decode),
+ asn1ct:get_gen_state_field(inc_type_pattern)} of
+ {undefined,_} ->
+ ok;
+ {_,undefined} ->
+ ok;
+ {Data,_} ->
+ gen_partial_inc_dispatcher(Data)
+ end.
+gen_partial_inc_dispatcher([{_FuncName,TopType,_Pattern}|Rest]) ->
+ emit(["decode_partial_inc_disp(",{asis,TopType},",Data) ->",nl,
+ " ",{asis,list_to_atom(lists:concat([dec,"-inc-",TopType]))},
+ "(Data);",nl]),
+ gen_partial_inc_dispatcher(Rest);
+gen_partial_inc_dispatcher([]) ->
+ emit(["decode_partial_inc_disp(Type,_Data) ->",nl,
+ " exit({error,{asn1,{undefined_type,Type}}}).",nl]).
+
+driver_parameter() ->
+ Options = get(encoding_options),
+ case lists:member(driver,Options) of
+ true ->
+ ",driver";
+ _ -> ""
+ end.
+
+gen_wrapper() ->
+ emit(["wrap_encode(Bytes) when list(Bytes) ->",nl,
+ " binary_to_list(list_to_binary(Bytes));",nl,
+ "wrap_encode(Bytes) when binary(Bytes) ->",nl,
+ " binary_to_list(Bytes);",nl,
+ "wrap_encode(Bytes) -> Bytes.",nl,nl]),
+ emit(["wrap_decode(Bytes) when list(Bytes) ->",nl,
+ " list_to_binary(Bytes);",nl,
+ "wrap_decode(Bytes) -> Bytes.",nl]).
+
+gen_dispatcher([F1,F2|T],FuncName,Prefix,ExtraArg) ->
+ emit([FuncName,"('",F1,"',Data) -> '",Prefix,F1,"'(Data",ExtraArg,")",";",nl]),
+ gen_dispatcher([F2|T],FuncName,Prefix,ExtraArg);
+gen_dispatcher([Flast|_T],FuncName,Prefix,ExtraArg) ->
+ emit([FuncName,"('",Flast,"',Data) -> '",Prefix,Flast,"'(Data",ExtraArg,")",";",nl]),
+ emit([FuncName,"(","Type",",_Data) -> exit({error,{asn1,{undefined_type,Type}}}).",nl,nl,nl]).
+
+pgen_info(_Erules,Module) ->
+ Options = get(encoding_options),
+ emit({"info() ->",nl,
+ " [{vsn,'",asn1ct:vsn(),"'},",
+ " {module,'",Module,"'},",
+ " {options,",io_lib:format("~p",[Options]),"}].",nl}).
+
+open_hrl(OutFile,Module) ->
+ File = lists:concat([OutFile,".hrl"]),
+ Fid = fopen(File,write),
+ put(gen_file_out,Fid),
+ gen_hrlhead(Module).
+
+%% EMIT functions ************************
+%% ***************************************
+
+ % debug generation
+demit(Term) ->
+ case get(asndebug) of
+ true -> emit(Term);
+ _ ->true
+ end.
+
+ % always generation
+
+emit({external,_M,T}) ->
+ emit(T);
+
+emit({prev,Variable}) when atom(Variable) ->
+ emit({var,asn1ct_name:prev(Variable)});
+
+emit({next,Variable}) when atom(Variable) ->
+ emit({var,asn1ct_name:next(Variable)});
+
+emit({curr,Variable}) when atom(Variable) ->
+ emit({var,asn1ct_name:curr(Variable)});
+
+emit({var,Variable}) when atom(Variable) ->
+ [Head|V] = atom_to_list(Variable),
+ emit([Head-32|V]);
+
+emit({var,Variable}) ->
+ [Head|V] = Variable,
+ emit([Head-32|V]);
+
+emit({asis,What}) ->
+ format(get(gen_file_out),"~w",[What]);
+
+emit(nl) ->
+ nl(get(gen_file_out));
+
+emit(com) ->
+ emit(",");
+
+emit(tab) ->
+ put_chars(get(gen_file_out)," ");
+
+emit(What) when integer(What) ->
+ put_chars(get(gen_file_out),integer_to_list(What));
+
+emit(What) when list(What), integer(hd(What)) ->
+ put_chars(get(gen_file_out),What);
+
+emit(What) when atom(What) ->
+ put_chars(get(gen_file_out),atom_to_list(What));
+
+emit(What) when tuple(What) ->
+ emit_parts(tuple_to_list(What));
+
+emit(What) when list(What) ->
+ emit_parts(What);
+
+emit(X) ->
+ exit({'cant emit ',X}).
+
+emit_parts([]) -> true;
+emit_parts([H|T]) ->
+ emit(H),
+ emit_parts(T).
+
+format(undefined,X,Y) ->
+ io:format(X,Y);
+format(X,Y,Z) ->
+ io:format(X,Y,Z).
+
+nl(undefined) -> io:nl();
+nl(X) -> io:nl(X).
+
+put_chars(undefined,X) ->
+ io:put_chars(X);
+put_chars(Y,X) ->
+ io:put_chars(Y,X).
+
+fopen(F, Mode) ->
+ case file:open(F, [Mode]) of
+ {ok, Fd} ->
+ Fd;
+ {error, Reason} ->
+ io:format("** Can't open file ~p ~n", [F]),
+ exit({error,Reason})
+ end.
+
+pgen_hrl(Erules,Module,TypeOrVal,_Indent) ->
+ put(currmod,Module),
+ {Types,Values,Ptypes,_,_,_} = TypeOrVal,
+ Ret =
+ case pgen_hrltypes(Erules,Module,Ptypes++Types,0) of
+ 0 ->
+ case Values of
+ [] ->
+ 0;
+ _ ->
+ open_hrl(get(outfile),get(currmod)),
+ pgen_macros(Erules,Module,Values),
+ 1
+ end;
+ X ->
+ pgen_macros(Erules,Module,Values),
+ X
+ end,
+ case Ret of
+ 0 ->
+ 0;
+ Y ->
+ Fid = get(gen_file_out),
+ file:close(Fid),
+ io:format("--~p--~n",
+ [{generated,lists:concat([get(outfile),".hrl"])}]),
+ Y
+ end.
+
+pgen_macros(_,_,[]) ->
+ true;
+pgen_macros(Erules,Module,[H|T]) ->
+ Valuedef = asn1_db:dbget(Module,H),
+ gen_macro(Valuedef),
+ pgen_macros(Erules,Module,T).
+
+pgen_hrltypes(_,_,[],NumRecords) ->
+ NumRecords;
+pgen_hrltypes(Erules,Module,[H|T],NumRecords) ->
+% io:format("records = ~p~n",NumRecords),
+ Typedef = asn1_db:dbget(Module,H),
+ AddNumRecords = gen_record(Typedef,NumRecords),
+ pgen_hrltypes(Erules,Module,T,NumRecords+AddNumRecords).
+
+
+%% Generates a macro for value Value defined in the ASN.1 module
+gen_macro(Value) when record(Value,valuedef) ->
+ emit({"-define('",Value#valuedef.name,"', ",
+ {asis,Value#valuedef.value},").",nl}).
+
+%% Generate record functions **************
+%% Generates an Erlang record for each named and unnamed SEQUENCE and SET in the ASN.1
+%% module. If no SEQUENCE or SET is found there is no .hrl file generated
+
+
+gen_record(Tdef,NumRecords) when record(Tdef,typedef) ->
+ Name = [Tdef#typedef.name],
+ Type = Tdef#typedef.typespec,
+ gen_record(type,Name,Type,NumRecords);
+
+gen_record(Tdef,NumRecords) when record(Tdef,ptypedef) ->
+ Name = [Tdef#ptypedef.name],
+ Type = Tdef#ptypedef.typespec,
+ gen_record(ptype,Name,Type,NumRecords).
+
+gen_record(TorPtype,Name,[#'ComponentType'{name=Cname,typespec=Type}|T],Num) ->
+ Num2 = gen_record(TorPtype,[Cname|Name],Type,Num),
+ gen_record(TorPtype,Name,T,Num2);
+gen_record(TorPtype,Name,{Clist1,Clist2},Num) when list(Clist1), list(Clist2) ->
+ gen_record(TorPtype,Name,Clist1++Clist2,Num);
+gen_record(TorPtype,Name,[_|T],Num) -> % skip EXTENSIONMARK
+ gen_record(TorPtype,Name,T,Num);
+gen_record(_TorPtype,_Name,[],Num) ->
+ Num;
+
+gen_record(TorPtype,Name,Type,Num) when record(Type,type) ->
+ Def = Type#type.def,
+ Rec = case Def of
+ Seq when record(Seq,'SEQUENCE') ->
+ case Seq#'SEQUENCE'.pname of
+ false ->
+ {record,Seq#'SEQUENCE'.components};
+ _Pname when TorPtype == type ->
+ false;
+ _ ->
+ {record,Seq#'SEQUENCE'.components}
+ end;
+ Set when record(Set,'SET') ->
+ case Set#'SET'.pname of
+ false ->
+ {record,Set#'SET'.components};
+ _Pname when TorPtype == type ->
+ false;
+ _ ->
+ {record,Set#'SET'.components}
+ end;
+% {'SET',{_,_CompList}} ->
+% {record,_CompList};
+ {'CHOICE',_CompList} -> {inner,Def};
+ {'SEQUENCE OF',_CompList} -> {['SEQOF'|Name],Def};
+ {'SET OF',_CompList} -> {['SETOF'|Name],Def};
+ _ -> false
+ end,
+ case Rec of
+ false -> Num;
+ {record,CompList} ->
+ case Num of
+ 0 -> open_hrl(get(outfile),get(currmod));
+ _ -> true
+ end,
+ emit({"-record('",list2name(Name),"',{",nl}),
+ RootList = case CompList of
+ _ when list(CompList) ->
+ CompList;
+ {_Rl,_} -> _Rl
+ end,
+ gen_record2(Name,'SEQUENCE',RootList),
+ NewCompList =
+ case CompList of
+ {CompList1,[]} ->
+ emit({"}). % with extension mark",nl,nl}),
+ CompList1;
+ {Tr,ExtensionList2} ->
+ case Tr of
+ [] -> true;
+ _ -> emit({",",nl})
+ end,
+ emit({"%% with extensions",nl}),
+ gen_record2(Name, 'SEQUENCE', ExtensionList2,
+ "", ext),
+ emit({"}).",nl,nl}),
+ Tr ++ ExtensionList2;
+ _ ->
+ emit({"}).",nl,nl}),
+ CompList
+ end,
+ gen_record(TorPtype,Name,NewCompList,Num+1);
+ {inner,{'CHOICE', CompList}} ->
+ gen_record(TorPtype,Name,CompList,Num);
+ {NewName,{_, CompList}} ->
+ gen_record(TorPtype,NewName,CompList,Num)
+ end;
+gen_record(_,_,_,NumRecords) -> % skip CLASS etc for now.
+ NumRecords.
+
+gen_head(Erules,Mod,Hrl) ->
+ {Rtmac,Rtmod} = case Erules of
+ per ->
+ emit({"%% Generated by the Erlang ASN.1 PER-"
+ "compiler version:",asn1ct:vsn(),nl}),
+ {"RT_PER",?RT_PER};
+ ber ->
+ emit({"%% Generated by the Erlang ASN.1 BER-"
+ "compiler version:",asn1ct:vsn(),nl}),
+ {"RT_BER",?RT_BER_BIN};
+ per_bin ->
+ emit({"%% Generated by the Erlang ASN.1 BER-"
+ "compiler version, utilizing bit-syntax:",
+ asn1ct:vsn(),nl}),
+ %% temporary code to enable rt2ct optimization
+ Options = get(encoding_options),
+ case lists:member(optimize,Options) of
+ true -> {"RT_PER","asn1rt_per_bin_rt2ct"};
+ _ ->
+ {"RT_PER",?RT_PER_BIN}
+ end;
+ ber_bin ->
+ emit({"%% Generated by the Erlang ASN.1 BER-"
+ "compiler version, utilizing bit-syntax:",
+ asn1ct:vsn(),nl}),
+ {"RT_BER",?RT_BER_BIN};
+ ber_bin_v2 ->
+ emit({"%% Generated by the Erlang ASN.1 BER_V2-"
+ "compiler version, utilizing bit-syntax:",
+ asn1ct:vsn(),nl}),
+ {"RT_BER","asn1rt_ber_bin_v2"}
+ end,
+ emit({"%% Purpose: encoder and decoder to the types in mod ",Mod,nl,nl}),
+ emit({"-module('",Mod,"').",nl}),
+ put(currmod,Mod),
+ %emit({"-compile(export_all).",nl}),
+ case Hrl of
+ 0 -> true;
+ _ ->
+ emit({"-include(\"",Mod,".hrl\").",nl})
+ end,
+ emit(["-define('",Rtmac,"',",Rtmod,").",nl]).
+
+
+gen_hrlhead(Mod) ->
+ emit({"%% Generated by the Erlang ASN.1 compiler version:",asn1ct:vsn(),nl}),
+ emit({"%% Purpose: Erlang record definitions for each named and unnamed",nl}),
+ emit({"%% SEQUENCE and SET, and macro definitions for each value",nl}),
+ emit({"%% definition,in module ",Mod,nl,nl}),
+ emit({nl,nl}).
+
+gen_record2(Name,SeqOrSet,Comps) ->
+ gen_record2(Name,SeqOrSet,Comps,"",noext).
+
+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,
+ emit(Com),
+ emit({asis,Cname}),
+ gen_record_default(H, Extension);
+gen_record2(Name,SeqOrSet,[H|T],Com, Extension) ->
+ #'ComponentType'{name=Cname} = H,
+ emit(Com),
+ emit({asis,Cname}),
+ gen_record_default(H, Extension),
+% emit(", "),
+ gen_record2(Name,SeqOrSet,T,", ", Extension).
+
+%gen_record_default(C, ext) ->
+% emit(" = asn1_NOEXTVALUE");
+gen_record_default(#'ComponentType'{prop='OPTIONAL'}, _)->
+ emit(" = asn1_NOVALUE");
+gen_record_default(#'ComponentType'{prop={'DEFAULT',_}}, _)->
+ emit(" = asn1_DEFAULT");
+gen_record_default(_, _) ->
+ true.
+
+gen_check_call(TopType,Cname,Type,InnerType,WhatKind,DefaultValue,Element) ->
+ case WhatKind of
+ {primitive,bif} ->
+ gen_prim_check_call(InnerType,DefaultValue,Element,Type);
+ #'Externaltypereference'{module=M,type=T} ->
+ %% generate function call
+ Name = list2name([T,check]),
+ emit({"'",Name,"'(",DefaultValue,", ",Element,")"}),
+ %% insert in ets table and do look ahead check
+ Typedef = asn1_db:dbget(M,T),
+ RefType = Typedef#typedef.typespec,
+ InType = asn1ct_gen:get_inner(RefType#type.def),
+ case insert_once(check_functions,{Name,RefType}) of
+ true ->
+ lookahead_innertype([T],InType,RefType);
+% case asn1ct_gen:type(InType) of
+% {constructed,bif} ->
+% lookahead_innertype([T],InType,RefType);
+% #'Externaltypereference'{type=TNew} ->
+% lookahead_innertype([TNew],InType,RefType);
+% _ ->
+% ok
+% end;
+ _ ->
+ ok
+ end;
+ {constructed,bif} ->
+ NameList = [Cname|TopType],
+ Name = list2name(NameList ++ [check]),
+ emit({"'",Name,"'(",DefaultValue,", ",Element,")"}),
+ ets:insert(check_functions,{Name,Type}),
+ %% Must look for check functions in InnerType,
+ %% that may be referenced or internal defined
+ %% constructed types not used elsewhere.
+ lookahead_innertype(NameList,InnerType,Type)
+ end.
+
+gen_prim_check_call(PrimType,DefaultValue,Element,Type) ->
+ case unify_if_string(PrimType) of
+ 'BOOLEAN' ->
+ emit({"asn1rt_check:check_bool(",DefaultValue,", ",
+ Element,")"});
+ 'INTEGER' ->
+ NNL =
+ case Type#type.def of
+ {_,NamedNumberList} -> NamedNumberList;
+ _ -> []
+ end,
+ emit({"asn1rt_check:check_int(",DefaultValue,", ",
+ Element,", ",{asis,NNL},")"});
+ 'BIT STRING' ->
+ {_,NBL} = Type#type.def,
+ emit({"asn1rt_check:check_bitstring(",DefaultValue,", ",
+ Element,", ",{asis,NBL},")"});
+ 'OCTET STRING' ->
+ emit({"asn1rt_check:check_octetstring(",DefaultValue,", ",
+ Element,")"});
+ 'NULL' ->
+ emit({"asn1rt_check:check_null(",DefaultValue,", ",
+ Element,")"});
+ 'OBJECT IDENTIFIER' ->
+ emit({"asn1rt_check:check_objectidentifier(",DefaultValue,
+ ", ",Element,")"});
+ 'ObjectDescriptor' ->
+ emit({"asn1rt_check:check_objectdescriptor(",DefaultValue,
+ ", ",Element,")"});
+ 'REAL' ->
+ emit({"asn1rt_check:check_real(",DefaultValue,
+ ", ",Element,")"});
+ 'ENUMERATED' ->
+ {_,Enumerations} = Type#type.def,
+ emit({"asn1rt_check:check_enum(",DefaultValue,
+ ", ",Element,", ",{asis,Enumerations},")"});
+ restrictedstring ->
+ emit({"asn1rt_check:check_restrictedstring(",DefaultValue,
+ ", ",Element,")"})
+ end.
+
+%% lokahead_innertype/3 traverses Type and checks if check functions
+%% have to be generated, i.e. for all constructed or referenced types.
+lookahead_innertype(Name,'SEQUENCE',Type) ->
+ Components = (Type#type.def)#'SEQUENCE'.components,
+ lookahead_components(Name,Components);
+lookahead_innertype(Name,'SET',Type) ->
+ Components = (Type#type.def)#'SET'.components,
+ lookahead_components(Name,Components);
+lookahead_innertype(Name,'CHOICE',Type) ->
+ {_,Components} = Type#type.def,
+ lookahead_components(Name,Components);
+lookahead_innertype(Name,'SEQUENCE OF',SeqOf) ->
+ lookahead_sof(Name,'SEQOF',SeqOf);
+lookahead_innertype(Name,'SET OF',SeqOf) ->
+ lookahead_sof(Name,'SETOF',SeqOf);
+lookahead_innertype(_Name,#'Externaltypereference'{module=M,type=T},_) ->
+ Typedef = asn1_db:dbget(M,T),
+ RefType = Typedef#typedef.typespec,
+ InType = asn1ct_gen:get_inner(RefType#type.def),
+ case type(InType) of
+ {constructed,bif} ->
+ NewName = list2name([T,check]),
+ case insert_once(check_functions,{NewName,RefType}) of
+ true ->
+ lookahead_innertype([T],InType,RefType);
+ _ ->
+ ok
+ end;
+ #'Externaltypereference'{} ->
+ NewName = list2name([T,check]),
+ case insert_once(check_functions,{NewName,RefType}) of
+ true ->
+ lookahead_innertype([T],InType,RefType);
+ _ ->
+ ok
+ end;
+ _ ->
+ ok
+ end;
+% case insert_once(check_functions,{list2name(Name++[check]),Type}) of
+% true ->
+% InnerType = asn1ct_gen:get_inner(Type#type.def),
+% case asn1ct_gen:type(InnerType) of
+% {constructed,bif} ->
+% lookahead_innertype([T],InnerType,Type);
+% #'Externaltypereference'{type=TNew} ->
+% lookahead_innertype([TNew],InnerType,Type);
+% _ ->
+% ok
+% end;
+% _ ->
+% ok
+% end;
+lookahead_innertype(_,_,_) ->
+ ok.
+
+lookahead_components(_,[]) -> ok;
+lookahead_components(Name,[C|Cs]) ->
+ #'ComponentType'{name=Cname,typespec=Type} = C,
+ InType = asn1ct_gen:get_inner(Type#type.def),
+ case asn1ct_gen:type(InType) of
+ {constructed,bif} ->
+ case insert_once(check_functions,
+ {list2name([Cname|Name] ++ [check]),Type}) of
+ true ->
+ lookahead_innertype([Cname|Name],InType,Type);
+ _ ->
+ ok
+ end;
+ #'Externaltypereference'{module=RefMod,type=RefName} ->
+ Typedef = asn1_db:dbget(RefMod,RefName),
+ RefType = Typedef#typedef.typespec,
+ case insert_once(check_functions,{list2name([RefName,check]),
+ RefType}) of
+ true ->
+ lookahead_innertype([RefName],InType,RefType);
+ _ ->
+ ok
+ end;
+ _ ->
+ ok
+ end,
+ lookahead_components(Name,Cs).
+
+lookahead_sof(Name,SOF,SOFType) ->
+ Type = case SOFType#type.def of
+ {_,_Type} -> _Type;
+ _Type -> _Type
+ end,
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ case asn1ct_gen:type(InnerType) of
+ {constructed,bif} ->
+ %% this is if a constructed type is defined in
+ %% the SEQUENCE OF type
+ NameList = [SOF|Name],
+ insert_once(check_functions,
+ {list2name(NameList ++ [check]),Type}),
+ lookahead_innertype(NameList,InnerType,Type);
+ #'Externaltypereference'{module=M,type=T} ->
+ Typedef = asn1_db:dbget(M,T),
+ RefType = Typedef#typedef.typespec,
+ InType = get_inner(RefType#type.def),
+ case insert_once(check_functions,
+ {list2name([T,check]),RefType}) of
+ true ->
+ lookahead_innertype([T],InType,RefType);
+ _ ->
+ ok
+ end;
+ _ ->
+ ok
+ end.
+
+
+insert_once(Table,Object) ->
+ case ets:lookup(Table,element(1,Object)) of
+ [] ->
+ ets:insert(Table,Object); %returns true
+ _ -> false
+ end.
+
+unify_if_string(PrimType) ->
+ case PrimType of
+ 'NumericString' ->
+ restrictedstring;
+ 'PrintableString' ->
+ restrictedstring;
+ 'TeletexString' ->
+ restrictedstring;
+ 'VideotexString' ->
+ restrictedstring;
+ 'IA5String' ->
+ restrictedstring;
+ 'UTCTime' ->
+ restrictedstring;
+ 'GeneralizedTime' ->
+ restrictedstring;
+ 'GraphicString' ->
+ restrictedstring;
+ 'VisibleString' ->
+ restrictedstring;
+ 'GeneralString' ->
+ restrictedstring;
+ 'UniversalString' ->
+ restrictedstring;
+ 'BMPString' ->
+ restrictedstring;
+ Other -> Other
+ end.
+
+
+
+
+
+get_inner(A) when atom(A) -> A;
+get_inner(Ext) when record(Ext,'Externaltypereference') -> Ext;
+get_inner(Tref) when record(Tref,typereference) -> Tref;
+get_inner({fixedtypevaluefield,_,Type}) ->
+ if
+ record(Type,type) ->
+ get_inner(Type#type.def);
+ true ->
+ get_inner(Type)
+ end;
+get_inner({typefield,TypeName}) ->
+ TypeName;
+get_inner(#'ObjectClassFieldType'{type=Type}) ->
+% get_inner(Type);
+ Type;
+get_inner(T) when tuple(T) ->
+ case element(1,T) of
+ Tuple when tuple(Tuple),element(1,Tuple) == objectclass ->
+ case catch(lists:last(element(2,T))) of
+ {valuefieldreference,FieldName} ->
+ get_fieldtype(element(2,Tuple),FieldName);
+ {typefieldreference,FieldName} ->
+ get_fieldtype(element(2,Tuple),FieldName);
+ {'EXIT',Reason} ->
+ throw({asn1,{'internal error in get_inner/1',Reason}})
+ end;
+ _ -> element(1,T)
+ end.
+
+
+
+
+
+type(X) when record(X,'Externaltypereference') ->
+ X;
+type(X) when record(X,typereference) ->
+ X;
+type('ASN1_OPEN_TYPE') ->
+ 'ASN1_OPEN_TYPE';
+type({fixedtypevaluefield,_Name,Type}) when record(Type,type) ->
+ type(get_inner(Type#type.def));
+type({typefield,_}) ->
+ 'ASN1_OPEN_TYPE';
+type(X) ->
+ %% io:format("asn1_types:type(~p)~n",[X]),
+ case catch type2(X) of
+ {'EXIT',_} ->
+ {notype,X};
+ Normal ->
+ Normal
+ end.
+
+type2(X) ->
+ case prim_bif(X) of
+ true ->
+ {primitive,bif};
+ false ->
+ case construct_bif(X) of
+ true ->
+ {constructed,bif};
+ false ->
+ {undefined,user}
+ end
+ end.
+
+prim_bif(X) ->
+ lists:member(X,['INTEGER' ,
+ 'ENUMERATED',
+ 'OBJECT IDENTIFIER',
+ 'ANY',
+ 'NULL',
+ 'BIT STRING' ,
+ 'OCTET STRING' ,
+ 'ObjectDescriptor',
+ 'NumericString',
+ 'TeletexString',
+ 'VideotexString',
+ 'UTCTime',
+ 'GeneralizedTime',
+ 'GraphicString',
+ 'VisibleString',
+ 'GeneralString',
+ 'PrintableString',
+ 'IA5String',
+ 'UniversalString',
+ 'BMPString',
+ 'ENUMERATED',
+ 'BOOLEAN']).
+
+construct_bif(T) ->
+ lists:member(T,['SEQUENCE' ,
+ 'SEQUENCE OF' ,
+ 'CHOICE' ,
+ 'SET' ,
+ 'SET OF']).
+
+def_to_tag(#tag{class=Class,number=Number}) ->
+ {Class,Number};
+def_to_tag(#'ObjectClassFieldType'{type=Type}) ->
+ case Type of
+ T when tuple(T),element(1,T)==fixedtypevaluefield ->
+ {'UNIVERSAL',get_inner(Type)};
+ _ ->
+ []
+ end;
+def_to_tag(Def) ->
+ {'UNIVERSAL',get_inner(Def)}.
+
+
+%% Information Object Class
+
+type_from_object(X) ->
+ case (catch lists:last(element(2,X))) of
+ {'EXIT',_} ->
+ {notype,X};
+ Normal ->
+ Normal
+ end.
+
+
+get_fieldtype([],_FieldName)->
+ {no_type,no_name};
+get_fieldtype([Field|Rest],FieldName) ->
+ case element(2,Field) of
+ FieldName ->
+ case element(1,Field) of
+ fixedtypevaluefield ->
+ {element(1,Field),FieldName,element(3,Field)};
+ _ ->
+ {element(1,Field),FieldName}
+ end;
+ _ ->
+ get_fieldtype(Rest,FieldName)
+ end.
+
+get_fieldcategory([],_FieldName) ->
+ no_cat;
+get_fieldcategory([Field|Rest],FieldName) ->
+ case element(2,Field) of
+ FieldName ->
+ element(1,Field);
+ _ ->
+ get_fieldcategory(Rest,FieldName)
+ end.
+
+get_typefromobject(Type) when record(Type,type) ->
+ case Type#type.def of
+ {{objectclass,_,_},TypeFrObj} when list(TypeFrObj) ->
+ {_,FieldName} = lists:last(TypeFrObj),
+ FieldName;
+ _ ->
+ {no_field}
+ end.
+
+get_classfieldcategory(Type,FieldName) ->
+ case (catch Type#type.def) of
+ {{obejctclass,Fields,_},_} ->
+ get_fieldcategory(Fields,FieldName);
+ {'EXIT',_} ->
+ no_cat;
+ _ ->
+ no_cat
+ end.
+%% Information Object Class
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Convert a list of name parts to something that can be output by emit
+%%
+%% used to output function names in generated code.
+
+list2name(L) ->
+ NewL = list2name1(L),
+ lists:concat(lists:reverse(NewL)).
+
+list2name1([{ptype,H1},H2|T]) ->
+ [H1,"_",list2name([H2|T])];
+list2name1([H1,H2|T]) ->
+ [H1,"_",list2name([H2|T])];
+list2name1([{ptype,H}|_T]) ->
+ [H];
+list2name1([H|_T]) ->
+ [H];
+list2name1([]) ->
+ [].
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Convert a list of name parts to something that can be output by emit
+%% stops at {ptype,Pname} i.e Pname whill be the first part of the name
+%% used to output record names in generated code.
+
+list2rname(L) ->
+ NewL = list2rname1(L),
+ lists:concat(lists:reverse(NewL)).
+
+list2rname1([{ptype,H1},_H2|_T]) ->
+ [H1];
+list2rname1([H1,H2|T]) ->
+ [H1,"_",list2name([H2|T])];
+list2rname1([{ptype,H}|_T]) ->
+ [H];
+list2rname1([H|_T]) ->
+ [H];
+list2rname1([]) ->
+ [].
+
+
+
+constructed_suffix(_,#'SEQUENCE'{pname=Ptypename}) when Ptypename =/= false ->
+ {ptype, Ptypename};
+constructed_suffix(_,#'SET'{pname=Ptypename}) when Ptypename =/= false ->
+ {ptype,Ptypename};
+constructed_suffix('SEQUENCE OF',_) ->
+ 'SEQOF';
+constructed_suffix('SET OF',_) ->
+ 'SETOF'.
+
+erule(ber) ->
+ ber;
+erule(ber_bin) ->
+ ber;
+erule(ber_bin_v2) ->
+ ber_bin_v2;
+erule(per) ->
+ per;
+erule(per_bin) ->
+ per.
+
+wrap_ber(ber) ->
+ ber_bin;
+wrap_ber(Erule) ->
+ Erule.
+
+rt2ct_suffix() ->
+ Options = get(encoding_options),
+ case {lists:member(optimize,Options),lists:member(per_bin,Options)} of
+ {true,true} -> "_rt2ct";
+ _ -> ""
+ end.
+rt2ct_suffix(per_bin) ->
+ Options = get(encoding_options),
+ case lists:member(optimize,Options) of
+ true -> "_rt2ct";
+ _ -> ""
+ end;
+rt2ct_suffix(_) -> "".
+
+get_constraint(C,Key) ->
+ case lists:keysearch(Key,1,C) of
+ false ->
+ no;
+ {value,{_,V}} ->
+ V;
+ {value,Cnstr} ->
+ Cnstr
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_ber.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_ber.erl
new file mode 100644
index 0000000000..765745dc13
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_ber.erl
@@ -0,0 +1,1525 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1ct_gen_ber.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
+%%
+-module(asn1ct_gen_ber).
+
+%% Generate erlang module which handles (PER) encode and decode for
+%% all types in an ASN.1 module
+
+-include("asn1_records.hrl").
+
+-export([pgen/4]).
+-export([decode_class/1, decode_type/1]).
+-export([add_removed_bytes/0]).
+-export([gen_encode/2,gen_encode/3,gen_decode/2,gen_decode/3]).
+-export([gen_encode_prim/4]).
+-export([gen_dec_prim/8]).
+-export([gen_objectset_code/2, gen_obj_code/3]).
+-export([re_wrap_erule/1]).
+-export([unused_var/2]).
+
+-import(asn1ct_gen, [emit/1,demit/1]).
+
+ % the encoding of class of tag bits 8 and 7
+-define(UNIVERSAL, 0).
+-define(APPLICATION, 16#40).
+-define(CONTEXT, 16#80).
+-define(PRIVATE, 16#C0).
+
+ % primitive or constructed encoding % bit 6
+-define(PRIMITIVE, 0).
+-define(CONSTRUCTED, 2#00100000).
+
+
+-define(T_ObjectDescriptor, ?UNIVERSAL bor ?PRIMITIVE bor 7).
+ % restricted character string types
+-define(T_NumericString, ?UNIVERSAL bor ?PRIMITIVE bor 18). %can be constructed
+-define(T_PrintableString, ?UNIVERSAL bor ?PRIMITIVE bor 19). %can be constructed
+-define(T_TeletexString, ?UNIVERSAL bor ?PRIMITIVE bor 20). %can be constructed
+-define(T_VideotexString, ?UNIVERSAL bor ?PRIMITIVE bor 21). %can be constructed
+-define(T_IA5String, ?UNIVERSAL bor ?PRIMITIVE bor 22). %can be constructed
+-define(T_GraphicString, ?UNIVERSAL bor ?PRIMITIVE bor 25). %can be constructed
+-define(T_VisibleString, ?UNIVERSAL bor ?PRIMITIVE bor 26). %can be constructed
+-define(T_GeneralString, ?UNIVERSAL bor ?PRIMITIVE bor 27). %can be constructed
+
+%% pgen(Erules, Module, TypeOrVal)
+%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module
+%% .hrl file is only generated if necessary
+%% Erules = per | ber
+%% Module = atom()
+%% TypeOrVal = {TypeList,ValueList,PTypeList}
+%% TypeList = ValueList = [atom()]
+
+pgen(OutFile,Erules,Module,TypeOrVal) ->
+ asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,true).
+
+
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+%% Generate ENCODING
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+
+%%===============================================================================
+%% encode #{typedef, {pos, name, typespec}}
+%%===============================================================================
+
+gen_encode(Erules,Type) when record(Type,typedef) ->
+ gen_encode_user(Erules,Type).
+
+%%===============================================================================
+%% encode #{type, {tag, def, constraint}}
+%%===============================================================================
+
+gen_encode(Erules,Typename,Type) when record(Type,type) ->
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ ObjFun =
+ case lists:keysearch(objfun,1,Type#type.tablecinf) of
+ {value,{_,_Name}} ->
+ ", ObjFun";
+ false ->
+ ""
+ end,
+ case asn1ct_gen:type(InnerType) of
+ {constructed,bif} ->
+ emit([nl,nl,nl,"%%================================"]),
+ emit([nl,"%% ",asn1ct_gen:list2name(Typename)]),
+ emit([nl,"%%================================",nl]),
+ case lists:member(InnerType,['SET','SEQUENCE']) of
+ true ->
+ case get(asn_keyed_list) of
+ true ->
+ CompList =
+ case Type#type.def of
+ #'SEQUENCE'{components=Cl} -> Cl;
+ #'SET'{components=Cl} -> Cl
+ end,
+ emit([nl,"'enc_",asn1ct_gen:list2name(Typename),
+ "'(Val, TagIn",ObjFun,
+ ") when list(Val) ->",nl]),
+ emit([" 'enc_",asn1ct_gen:list2name(Typename),
+ "'(?RT_BER:fixoptionals(",
+ {asis,optionals(CompList)},
+ ",Val), TagIn",ObjFun,");",nl,nl]);
+ _ -> true
+ end;
+ _ ->
+ emit([nl,"'enc_",asn1ct_gen:list2name(Typename),
+ "'({'",asn1ct_gen:list2name(Typename),
+ "',Val}, TagIn",ObjFun,") ->",nl]),
+ emit([" 'enc_",asn1ct_gen:list2name(Typename),
+ "'(Val, TagIn",ObjFun,");",nl,nl])
+ end,
+ emit(["'enc_",asn1ct_gen:list2name(Typename),
+ "'(Val, TagIn",ObjFun,") ->",nl," "]),
+ asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
+ _ ->
+ true
+ end;
+
+%%===============================================================================
+%% encode ComponentType
+%%===============================================================================
+
+gen_encode(Erules,Tname,{'ComponentType',_Pos,Cname,Type,_,_}) ->
+ NewTname = [Cname|Tname],
+ %% The tag is set to [] to avoid that it is
+ %% taken into account twice, both as a component/alternative (passed as
+ %% argument to the encode decode function and within the encode decode
+ %% function it self.
+ NewType = Type#type{tag=[]},
+ gen_encode(Erules,NewTname,NewType).
+
+gen_encode_user(Erules,D) when record(D,typedef) ->
+ Typename = [D#typedef.name],
+ Type = D#typedef.typespec,
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ OTag = Type#type.tag,
+ Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
+ emit([nl,nl,"%%================================"]),
+ emit([nl,"%% ",Typename]),
+ emit([nl,"%%================================",nl]),
+ case lists:member(InnerType,['SET','SEQUENCE']) of
+ true ->
+ case get(asn_keyed_list) of
+ true ->
+ CompList =
+ case Type#type.def of
+ #'SEQUENCE'{components=Cl} -> Cl;
+ #'SET'{components=Cl} -> Cl
+ end,
+
+ emit([nl,"'enc_",asn1ct_gen:list2name(Typename),
+ "'(Val, TagIn) when list(Val) ->",nl]),
+ emit([" 'enc_",asn1ct_gen:list2name(Typename),
+ "'(?RT_BER:fixoptionals(",
+ {asis,optionals(CompList)},
+ ",Val), TagIn);",nl,nl]);
+ _ -> true
+ end;
+ _ ->
+ emit({nl,"'enc_",asn1ct_gen:list2name(Typename),
+ "'({'",asn1ct_gen:list2name(Typename),"',Val}, TagIn) ->",nl}),
+ emit({" 'enc_",asn1ct_gen:list2name(Typename),"'(Val, TagIn);",nl,nl})
+ end,
+ emit({"'enc_",asn1ct_gen:list2name(Typename),"'(",
+ unused_var("Val",Type#type.def),", TagIn) ->",nl}),
+ CurrentMod = get(currmod),
+ case asn1ct_gen:type(InnerType) of
+ {constructed,bif} ->
+ asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,D);
+ {primitive,bif} ->
+ asn1ct_gen_ber:gen_encode_prim(ber,Type,["TagIn ++ ",
+ {asis,Tag}],"Val"),
+ emit([".",nl]);
+ #typereference{val=Ename} ->
+ emit([" 'enc_",Ename,"'(Val, TagIn ++ ",{asis,Tag},").",nl]);
+ #'Externaltypereference'{module=CurrentMod,type=Etype} ->
+ emit([" 'enc_",Etype,"'(Val, TagIn ++ ",
+ {asis,Tag},").",nl]);
+ #'Externaltypereference'{module=Emod,type=Etype} ->
+ emit([" '",Emod,"':'enc_",Etype,"'(Val, TagIn ++ ",
+ {asis,Tag},").",nl]);
+ 'ASN1_OPEN_TYPE' ->
+ emit(["%% OPEN TYPE",nl]),
+ asn1ct_gen_ber:gen_encode_prim(ber,
+ Type#type{def='ASN1_OPEN_TYPE'},
+ ["TagIn ++ ",
+ {asis,Tag}],"Val"),
+ emit([".",nl])
+ end.
+
+unused_var(Var,#'SEQUENCE'{components=Cl}) ->
+ unused_var1(Var,Cl);
+unused_var(Var,#'SET'{components=Cl}) ->
+ unused_var1(Var,Cl);
+unused_var(Var,_) ->
+ Var.
+unused_var1(Var,Cs) when Cs == []; Cs == {[],[]} ->
+ lists:concat(["_",Var]);
+unused_var1(Var,_) ->
+ Var.
+
+unused_optormand_var(Var,Def) ->
+ case asn1ct_gen:type(asn1ct_gen:get_inner(Def)) of
+ 'ASN1_OPEN_TYPE' ->
+ lists:concat(["_",Var]);
+ _ ->
+ Var
+ end.
+
+
+gen_encode_prim(_Erules,D,DoTag,Value) when record(D,type) ->
+
+%%% Currently not used for BER (except for BitString) and therefore replaced
+%%% with [] as a placeholder
+ BitStringConstraint = D#type.constraint,
+ Constraint = [],
+ asn1ct_name:new(enumval),
+ case D#type.def of
+ 'BOOLEAN' ->
+ emit_encode_func('boolean',Value,DoTag);
+ 'INTEGER' ->
+ emit_encode_func('integer',Constraint,Value,DoTag);
+ {'INTEGER',NamedNumberList} ->
+ emit_encode_func('integer',Constraint,Value,
+ NamedNumberList,DoTag);
+ {'ENUMERATED',NamedNumberList={_,_}} ->
+
+ emit(["case (case ",Value," of {asn1_enum,_}->",Value,";{_,_}->element(2,",Value,");_->",
+ Value," end) of",nl]),
+ emit_enc_enumerated_cases(NamedNumberList,DoTag);
+ {'ENUMERATED',NamedNumberList} ->
+
+ emit(["case (case ",Value," of {_,_}->element(2,",Value,");_->",
+ Value," end) of",nl]),
+ emit_enc_enumerated_cases(NamedNumberList,DoTag);
+
+ {'BIT STRING',NamedNumberList} ->
+ emit_encode_func('bit_string',BitStringConstraint,Value,
+ NamedNumberList,DoTag);
+ 'ANY' ->
+ emit_encode_func('open_type', Value,DoTag);
+ 'NULL' ->
+ emit_encode_func('null',Value,DoTag);
+ 'OBJECT IDENTIFIER' ->
+ emit_encode_func("object_identifier",Value,DoTag);
+ 'ObjectDescriptor' ->
+ emit_encode_func('restricted_string',Constraint,Value,
+ ?T_ObjectDescriptor,DoTag);
+ 'OCTET STRING' ->
+ emit_encode_func('octet_string',Constraint,Value,DoTag);
+ 'NumericString' ->
+ emit_encode_func('restricted_string',Constraint,Value,
+ ?T_NumericString,DoTag);
+ 'TeletexString' ->
+ emit_encode_func('restricted_string',Constraint,Value,
+ ?T_TeletexString,DoTag);
+ 'VideotexString' ->
+ emit_encode_func('restricted_string',Constraint,Value,
+ ?T_VideotexString,DoTag);
+ 'GraphicString' ->
+ emit_encode_func('restricted_string',Constraint,Value,
+ ?T_GraphicString,DoTag);
+ 'VisibleString' ->
+ emit_encode_func('restricted_string',Constraint,Value,
+ ?T_VisibleString,DoTag);
+ 'GeneralString' ->
+ emit_encode_func('restricted_string',Constraint,Value,
+ ?T_GeneralString,DoTag);
+ 'PrintableString' ->
+ emit_encode_func('restricted_string',Constraint,Value,
+ ?T_PrintableString,DoTag);
+ 'IA5String' ->
+ emit_encode_func('restricted_string',Constraint,Value,
+ ?T_IA5String,DoTag);
+ 'UniversalString' ->
+ emit_encode_func('universal_string',Constraint,Value,DoTag);
+ 'BMPString' ->
+ emit_encode_func('BMP_string',Constraint,Value,DoTag);
+ 'UTCTime' ->
+ emit_encode_func('utc_time',Constraint,Value,DoTag);
+ 'GeneralizedTime' ->
+ emit_encode_func('generalized_time',Constraint,Value,DoTag);
+ 'ASN1_OPEN_TYPE' ->
+ emit_encode_func('open_type', Value,DoTag);
+ XX ->
+ exit({'can not encode' ,XX})
+ end.
+
+
+emit_encode_func(Name,Value,Tags) when atom(Name) ->
+ emit_encode_func(atom_to_list(Name),Value,Tags);
+emit_encode_func(Name,Value,Tags) ->
+ Fname = "?RT_BER:encode_" ++ Name,
+ emit([Fname,"(",Value,", ",Tags,")"]).
+
+emit_encode_func(Name,Constraint,Value,Tags) when atom(Name) ->
+ emit_encode_func(atom_to_list(Name),Constraint,Value,Tags);
+emit_encode_func(Name,Constraint,Value,Tags) ->
+ Fname = "?RT_BER:encode_" ++ Name,
+ emit([Fname,"(",{asis,Constraint},", ",Value,", ",Tags,")"]).
+
+emit_encode_func(Name,Constraint,Value,Asis,Tags) when atom(Name) ->
+ emit_encode_func(atom_to_list(Name),Constraint,Value,Asis,Tags);
+emit_encode_func(Name,Constraint,Value,Asis,Tags) ->
+ Fname = "?RT_BER:encode_" ++ Name,
+ emit([Fname,"(",{asis,Constraint},", ",Value,
+ ", ",{asis,Asis},
+ ", ",Tags,")"]).
+
+emit_enc_enumerated_cases({L1,L2}, Tags) ->
+ emit_enc_enumerated_cases(L1++L2, Tags, ext);
+emit_enc_enumerated_cases(L, Tags) ->
+ emit_enc_enumerated_cases(L, Tags, noext).
+
+emit_enc_enumerated_cases([{EnumName,EnumVal},H2|T], Tags, Ext) ->
+ emit([{asis,EnumName}," -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,");",nl]),
+%% emit(["'",{asis,EnumName},"' -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,");",nl]),
+ emit_enc_enumerated_cases([H2|T], Tags, Ext);
+emit_enc_enumerated_cases([{EnumName,EnumVal}], Tags, Ext) ->
+ emit([{asis,EnumName}," -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,")"]),
+%% emit(["'",{asis,EnumName},"' -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,")"]),
+ case Ext of
+ noext -> emit([";",nl]);
+ ext ->
+ emit([";",nl,"{asn1_enum,",{curr,enumval},"} -> ",
+ "?RT_BER:encode_enumerated(",{curr,enumval},",",Tags,");",nl]),
+ asn1ct_name:new(enumval)
+ end,
+ emit([{curr,enumval}," -> exit({error,{asn1, {enumerated_not_in_range,",{curr, enumval},"}}})"]),
+ emit([nl,"end"]).
+
+
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+%% Generate DECODING
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+
+%%===============================================================================
+%% decode #{typedef, {pos, name, typespec}}
+%%===============================================================================
+
+gen_decode(Erules,Type) when record(Type,typedef) ->
+ D = Type,
+ emit({nl,nl}),
+ emit({"'dec_",Type#typedef.name,"'(Bytes, OptOrMand) ->",nl}),
+ emit({" 'dec_",Type#typedef.name,"'(Bytes, OptOrMand, []).",nl,nl}),
+ emit({"'dec_",Type#typedef.name,"'(Bytes, ",
+ unused_optormand_var("OptOrMand",(Type#typedef.typespec)#type.def),", TagIn) ->",nl}),
+ dbdec(Type#typedef.name),
+ gen_decode_user(Erules,D).
+
+
+%%===============================================================================
+%% decode #{type, {tag, def, constraint}}
+%%===============================================================================
+
+gen_decode(Erules,Tname,Type) when record(Type,type) ->
+ Typename = Tname,
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ case asn1ct_gen:type(InnerType) of
+ {constructed,bif} ->
+ ObjFun =
+ case Type#type.tablecinf of
+ [{objfun,_}|_R] ->
+ ", ObjFun";
+ _ ->
+ ""
+ end,
+ emit({"'dec_",asn1ct_gen:list2name(Typename),"'(Bytes, OptOrMand, TagIn",ObjFun,") ->",nl}),
+ dbdec(Typename),
+ asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,Type);
+ _ ->
+ true
+ end;
+
+
+%%===============================================================================
+%% decode ComponentType
+%%===============================================================================
+
+gen_decode(Erules,Tname,{'ComponentType',_Pos,Cname,Type,_,_}) ->
+ NewTname = [Cname|Tname],
+ %% The tag is set to [] to avoid that it is
+ %% taken into account twice, both as a component/alternative (passed as
+ %% argument to the encode decode function and within the encode decode
+ %% function it self.
+ NewType = Type#type{tag=[]},
+ gen_decode(Erules,NewTname,NewType).
+
+
+gen_decode_user(Erules,D) when record(D,typedef) ->
+ Typename = [D#typedef.name],
+ Def = D#typedef.typespec,
+ InnerType = asn1ct_gen:get_inner(Def#type.def),
+ InnerTag = Def#type.tag ,
+ Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- InnerTag],
+ case asn1ct_gen:type(InnerType) of
+ 'ASN1_OPEN_TYPE' ->
+ BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
+ asn1ct_name:new(len),
+ gen_dec_prim(Erules, Def#type{def='ASN1_OPEN_TYPE'},
+ BytesVar, Tag, "TagIn",no_length,
+ ?PRIMITIVE,"OptOrMand"),
+ emit({".",nl,nl});
+ {primitive,bif} ->
+ BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
+ asn1ct_name:new(len),
+ gen_dec_prim(Erules, Def, BytesVar, Tag, "TagIn",no_length,
+ ?PRIMITIVE,"OptOrMand"),
+ emit({".",nl,nl});
+ {constructed,bif} ->
+ asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,D);
+ TheType ->
+ DecFunName = mkfuncname(TheType,dec),
+ emit({DecFunName,"(",{curr,bytes},
+ ", OptOrMand, TagIn++",{asis,Tag},")"}),
+ emit({".",nl,nl})
+ end.
+
+
+gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Length,_Form,OptOrMand) ->
+ Typename = Att#type.def,
+%% Currently not used for BER replaced with [] as place holder
+%% Constraint = Att#type.constraint,
+%% Constraint = [],
+ Constraint =
+ case get_constraint(Att#type.constraint,'SizeConstraint') of
+ no -> [];
+ Tc -> Tc
+ end,
+ ValueRange =
+ case get_constraint(Att#type.constraint,'ValueRange') of
+ no -> [];
+ Tv -> Tv
+ end,
+ SingleValue =
+ case get_constraint(Att#type.constraint,'SingleValue') of
+ no -> [];
+ Sv -> Sv
+ end,
+ AsBin = case get(binary_strings) of
+ true -> "_as_bin";
+ _ -> ""
+ end,
+ NewTypeName = case Typename of
+ 'ANY' -> 'ASN1_OPEN_TYPE';
+ _ -> Typename
+ end,
+ DoLength =
+ case NewTypeName of
+ 'BOOLEAN'->
+ emit({"?RT_BER:decode_boolean(",BytesVar,","}),
+ false;
+ 'INTEGER' ->
+ emit({"?RT_BER:decode_integer(",BytesVar,",",
+ {asis,int_constr(SingleValue,ValueRange)},","}),
+ false;
+ {'INTEGER',NamedNumberList} ->
+ emit({"?RT_BER:decode_integer(",BytesVar,",",
+ {asis,int_constr(SingleValue,ValueRange)},",",
+ {asis,NamedNumberList},","}),
+ false;
+ {'ENUMERATED',NamedNumberList} ->
+ emit({"?RT_BER:decode_enumerated(",BytesVar,",",
+ {asis,Constraint},",",
+ {asis,NamedNumberList},","}),
+ false;
+ {'BIT STRING',NamedNumberList} ->
+ case get(compact_bit_string) of
+ true ->
+ emit({"?RT_BER:decode_compact_bit_string(",
+ BytesVar,",",{asis,Constraint},",",
+ {asis,NamedNumberList},","});
+ _ ->
+ emit({"?RT_BER:decode_bit_string(",BytesVar,",",
+ {asis,Constraint},",",
+ {asis,NamedNumberList},","})
+ end,
+ true;
+ 'NULL' ->
+ emit({"?RT_BER:decode_null(",BytesVar,","}),
+ false;
+ 'OBJECT IDENTIFIER' ->
+ emit({"?RT_BER:decode_object_identifier(",BytesVar,","}),
+ false;
+ 'ObjectDescriptor' ->
+ emit({"?RT_BER:decode_restricted_string(",
+ BytesVar,",",{asis,Constraint},",",{asis,?T_ObjectDescriptor},","}),
+ true;
+ 'OCTET STRING' ->
+ emit({"?RT_BER:decode_octet_string",AsBin,"(",BytesVar,",",{asis,Constraint},","}),
+ true;
+ 'NumericString' ->
+ emit({"?RT_BER:decode_restricted_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},",",{asis,?T_NumericString},","}),true;
+ 'TeletexString' ->
+ emit({"?RT_BER:decode_restricted_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},",",{asis,?T_TeletexString},","}),
+ true;
+ 'VideotexString' ->
+ emit({"?RT_BER:decode_restricted_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},",",{asis,?T_VideotexString},","}),
+ true;
+ 'GraphicString' ->
+ emit({"?RT_BER:decode_restricted_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},",",{asis,?T_GraphicString},","})
+ ,true;
+ 'VisibleString' ->
+ emit({"?RT_BER:decode_restricted_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},",",{asis,?T_VisibleString},","}),
+ true;
+ 'GeneralString' ->
+ emit({"?RT_BER:decode_restricted_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},",",{asis,?T_GeneralString},","}),
+ true;
+ 'PrintableString' ->
+ emit({"?RT_BER:decode_restricted_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},",",{asis,?T_PrintableString},","}),
+ true;
+ 'IA5String' ->
+ emit({"?RT_BER:decode_restricted_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},",",{asis,?T_IA5String},","}),
+ true;
+ 'UniversalString' ->
+ emit({"?RT_BER:decode_universal_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},","}),
+ true;
+ 'BMPString' ->
+ emit({"?RT_BER:decode_BMP_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},","}),
+ true;
+ 'UTCTime' ->
+ emit({"?RT_BER:decode_utc_time",AsBin,"(",
+ BytesVar,",",{asis,Constraint},","}),
+ true;
+ 'GeneralizedTime' ->
+ emit({"?RT_BER:decode_generalized_time",AsBin,"(",
+ BytesVar,",",{asis,Constraint},","}),
+ true;
+ 'ASN1_OPEN_TYPE' ->
+ emit(["?RT_BER:decode_open_type(",re_wrap_erule(Erules),",",
+ BytesVar,","]),
+ false;
+ Other ->
+ exit({'can not decode' ,Other})
+ end,
+
+ NewLength = case DoLength of
+ true -> [", ", Length];
+ false -> ""
+ end,
+ NewOptOrMand = case OptOrMand of
+ _ when list(OptOrMand) -> OptOrMand;
+ mandatory -> {asis,mandatory};
+ _ -> {asis,opt_or_default}
+ end,
+ case {TagIn,NewTypeName} of
+ {[],'ASN1_OPEN_TYPE'} ->
+ emit([{asis,DoTag},")"]);
+ {_,'ASN1_OPEN_TYPE'} ->
+ emit([TagIn,"++",{asis,DoTag},")"]);
+ {[],_} ->
+ emit([{asis,DoTag},NewLength,", ",NewOptOrMand,")"]);
+ _ when list(TagIn) ->
+ emit([TagIn,"++",{asis,DoTag},NewLength,", ",NewOptOrMand,")"])
+ end.
+
+
+int_constr([],[]) ->
+ [];
+int_constr([],ValueRange) ->
+ ValueRange;
+int_constr(SingleValue,[]) ->
+ SingleValue;
+int_constr(SV,VR) ->
+ [SV,VR].
+
+%% Object code generating for encoding and decoding
+%% ------------------------------------------------
+
+gen_obj_code(Erules,_Module,Obj) when record(Obj,typedef) ->
+ ObjName = Obj#typedef.name,
+ Def = Obj#typedef.typespec,
+ #'Externaltypereference'{module=M,type=ClName} = Def#'Object'.classname,
+ Class = asn1_db:dbget(M,ClName),
+
+ {object,_,Fields} = Def#'Object'.def,
+ emit({nl,nl,nl,"%%================================"}),
+ emit({nl,"%% ",ObjName}),
+ emit({nl,"%%================================",nl}),
+ EncConstructed =
+ gen_encode_objectfields(ClName,get_class_fields(Class),
+ ObjName,Fields,[]),
+ emit(nl),
+ gen_encode_constr_type(Erules,EncConstructed),
+ emit(nl),
+ DecConstructed =
+ gen_decode_objectfields(ClName,get_class_fields(Class),
+ ObjName,Fields,[]),
+ emit(nl),
+ gen_decode_constr_type(Erules,DecConstructed);
+gen_obj_code(_Erules,_Module,Obj) when record(Obj,pobjectdef) ->
+ ok.
+
+
+gen_encode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
+ ObjName,ObjectFields,ConstrAcc) ->
+ EmitFuncClause =
+ fun(Args) ->
+ emit(["'enc_",ObjName,"'(",{asis,Name},
+ ", ",Args,", _RestPrimFieldName) ->",nl])
+ end,
+% emit(["'enc_",ObjName,"'(",{asis,Name},
+% ", Val, TagIn, _RestPrimFieldName) ->",nl]),
+ MaybeConstr=
+ case {get_object_field(Name,ObjectFields),OptOrMand} of
+ {false,'MANDATORY'} -> %% this case is illegal
+ exit({error,{asn1,{"missing mandatory field in object",
+ ObjName}}});
+ {false,'OPTIONAL'} ->
+ EmitFuncClause("_, _"),
+ emit([" {[],0}"]),
+ [];
+ {false,{'DEFAULT',DefaultType}} ->
+ EmitFuncClause("Val, TagIn"),
+ gen_encode_default_call(ClassName,Name,DefaultType);
+ {{Name,TypeSpec},_} ->
+ %% A specified field owerwrites any 'DEFAULT' or
+ %% 'OPTIONAL' field in the class
+ EmitFuncClause("Val, TagIn"),
+ gen_encode_field_call(ObjName,Name,TypeSpec)
+ end,
+ case more_genfields(Rest) of
+ true ->
+ emit([";",nl]);
+ false ->
+ emit([".",nl])
+ end,
+ gen_encode_objectfields(ClassName,Rest,ObjName,ObjectFields,
+ MaybeConstr++ConstrAcc);
+gen_encode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
+ ObjName,ObjectFields,ConstrAcc) ->
+ EmitFuncClause =
+ fun(Args) ->
+ emit(["'enc_",ObjName,"'(",{asis,Name},
+ ", ",Args,") ->",nl])
+ end,
+% emit(["'enc_",ObjName,"'(",{asis,Name},
+% ", Val, TagIn, [H|T]) ->",nl]),
+ case {get_object_field(Name,ObjectFields),OptOrMand} of
+ {false,'MANDATORY'} ->
+ exit({error,{asn1,{"missing mandatory field in object",
+ ObjName}}});
+ {false,'OPTIONAL'} ->
+ EmitFuncClause("_,_,_"),
+ emit([" exit({error,{'use of missing field in object', ",Name,
+ "}})"]);
+ {false,{'DEFAULT',_DefaultObject}} ->
+ exit({error,{asn1,{"not implemented yet",Name}}});
+ {{Name,TypeSpec},_} ->
+ EmitFuncClause(" Val, TagIn, [H|T]"),
+ case TypeSpec#typedef.name of
+ {ExtMod,TypeName} ->
+ emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
+ "'(H, Val, TagIn, T)"});
+ TypeName ->
+ emit({indent(3),"'enc_",TypeName,"'(H, Val, TagIn, T)"})
+ end
+ end,
+ case more_genfields(Rest) of
+ true ->
+ emit([";",nl]);
+ false ->
+ emit([".",nl])
+ end,
+ gen_encode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
+gen_encode_objectfields(ClassName,[_|Cs],O,OF,Acc) ->
+ gen_encode_objectfields(ClassName,Cs,O,OF,Acc);
+gen_encode_objectfields(_,[],_,_,Acc) ->
+ Acc.
+
+
+% gen_encode_objectfields(Class,ObjName,[{FieldName,Type}|Rest],ConstrAcc) ->
+% Fields = Class#objectclass.fields,
+% MaybeConstr=
+% case is_typefield(Fields,FieldName) of
+% true ->
+% Def = Type#typedef.typespec,
+% OTag = Def#type.tag,
+% Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
+% emit({"'enc_",ObjName,"'(",{asis,FieldName},
+% ", Val, TagIn, RestPrimFieldName) ->",nl}),
+% CAcc=
+% case Type#typedef.name of
+% {primitive,bif} ->
+% gen_encode_prim(ber,Def,["TagIn ++ ",{asis,Tag}],
+% "Val"),
+% [];
+% {constructed,bif} ->
+% %%InnerType = asn1ct_gen:get_inner(Def#type.def),
+% %%asn1ct_gen:gen_encode_constructed(ber,[ObjName],
+% %% InnerType,Def);
+% emit({" 'enc_",ObjName,'_',FieldName,
+% "'(Val, TagIn ++ ",{asis,Tag},")"}),
+% [{['enc_',ObjName,'_',FieldName],Def}];
+% {ExtMod,TypeName} ->
+% emit({" '",ExtMod,"':'enc_",TypeName,
+% "'(Val, TagIn ++ ",{asis,Tag},")"}),
+% [];
+% TypeName ->
+% emit({" 'enc_",TypeName,"'(Val, TagIn ++ ",
+% {asis,Tag},")"}),
+% []
+% end,
+% case more_genfields(Fields,Rest) of
+% true ->
+% emit({";",nl});
+% false ->
+% emit({".",nl})
+% end,
+% CAcc;
+% {false,objectfield} ->
+% emit({"'enc_",ObjName,"'(",{asis,FieldName},
+% ", Val, TagIn, [H|T]) ->",nl}),
+% case Type#typedef.name of
+% {ExtMod,TypeName} ->
+% emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
+% "'(H, Val, TagIn, T)"});
+% TypeName ->
+% emit({indent(3),"'enc_",TypeName,"'(H, Val, TagIn, T)"})
+% end,
+% case more_genfields(Fields,Rest) of
+% true ->
+% emit({";",nl});
+% false ->
+% emit({".",nl})
+% end,
+% [];
+% {false,_} -> []
+% end,
+% gen_encode_objectfields(Class,ObjName,Rest,MaybeConstr ++ ConstrAcc);
+% gen_encode_objectfields(C,O,[H|T],Acc) ->
+% gen_encode_objectfields(C,O,T,Acc);
+% gen_encode_objectfields(_,_,[],Acc) ->
+% Acc.
+
+% gen_encode_constr_type([{Name,Def}|Rest]) ->
+% emit({Name,"(Val,TagIn) ->",nl}),
+% InnerType = asn1ct_gen:get_inner(Def#type.def),
+% asn1ct_gen:gen_encode_constructed(ber,Name,InnerType,Def),
+% gen_encode_constr_type(Rest);
+gen_encode_constr_type(Erules,[TypeDef|Rest]) when record(TypeDef,typedef) ->
+ case is_already_generated(enc,TypeDef#typedef.name) of
+ true -> ok;
+ _ -> gen_encode_user(Erules,TypeDef)
+ end,
+ gen_encode_constr_type(Erules,Rest);
+gen_encode_constr_type(_,[]) ->
+ ok.
+
+gen_encode_field_call(ObjName,FieldName,Type) ->
+ Def = Type#typedef.typespec,
+ OTag = Def#type.tag,
+ Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
+ case Type#typedef.name of
+ {primitive,bif} -> %%tag should be the primitive tag
+ gen_encode_prim(ber,Def,["TagIn ++ ",{asis,Tag}],
+ "Val"),
+ [];
+ {constructed,bif} ->
+ emit({" 'enc_",ObjName,'_',FieldName,
+ "'(Val, TagIn ++",{asis,Tag},")"}),
+ [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
+ {ExtMod,TypeName} ->
+ emit({" '",ExtMod,"':'enc_",TypeName,
+ "'(Val, TagIn ++ ",{asis,Tag},")"}),
+ [];
+ TypeName ->
+ emit({" 'enc_",TypeName,"'(Val, TagIn ++ ",{asis,Tag},")"}),
+ []
+ end.
+
+gen_encode_default_call(ClassName,FieldName,Type) ->
+ CurrentMod = get(currmod),
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ OTag = Type#type.tag,
+ Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
+ case asn1ct_gen:type(InnerType) of
+ {constructed,bif} ->
+%% asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
+ emit([" 'enc_",ClassName,'_',FieldName,"'(Bytes, TagIn ++ ",
+ {asis,Tag},")"]),
+ [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
+ typespec=Type}];
+ {primitive,bif} ->
+ gen_encode_prim(ber,Type,["TagIn ++ ",{asis,Tag}],"Val"),
+ [];
+ #'Externaltypereference'{module=CurrentMod,type=Etype} ->
+ emit([" 'enc_",Etype,"'(Val, TagIn ++ ",{asis,Tag},")",nl]),
+ [];
+ #'Externaltypereference'{module=Emod,type=Etype} ->
+ emit([" '",Emod,"':'enc_",Etype,"'(Val, TagIn ++ ",{asis,Tag},")",nl]),
+ []
+ end.
+
+
+
+gen_decode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
+ ObjName,ObjectFields,ConstrAcc) ->
+ EmitFuncClause =
+ fun(Args) ->
+ emit(["'dec_",ObjName,"'(",{asis,Name},
+ ", ",Args,"_) ->",nl])
+ end,
+% emit(["'dec_",ObjName,"'(",{asis,Name},
+% ", Bytes, TagIn, RestPrimFieldName) ->",nl]),
+ MaybeConstr=
+ case {get_object_field(Name,ObjectFields),OptOrMand} of
+ {false,'MANDATORY'} -> %% this case is illegal
+ exit({error,{asn1,{"missing mandatory field in object",
+ ObjName}}});
+ {false,'OPTIONAL'} ->
+ EmitFuncClause("_, _,"),
+ emit([" asn1_NOVALUE"]),
+ [];
+ {false,{'DEFAULT',DefaultType}} ->
+ EmitFuncClause("Bytes, TagIn,"),
+ gen_decode_default_call(ClassName,Name,"Bytes",DefaultType);
+ {{Name,TypeSpec},_} ->
+ %% A specified field owerwrites any 'DEFAULT' or
+ %% 'OPTIONAL' field in the class
+ EmitFuncClause("Bytes, TagIn,"),
+ gen_decode_field_call(ObjName,Name,"Bytes",TypeSpec)
+ end,
+ case more_genfields(Rest) of
+ true ->
+ emit([";",nl]);
+ false ->
+ emit([".",nl])
+ end,
+ gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,MaybeConstr++ConstrAcc);
+gen_decode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
+ ObjName,ObjectFields,ConstrAcc) ->
+ EmitFuncClause =
+ fun(Args) ->
+ emit(["'dec_",ObjName,"'(",{asis,Name},
+ ", ",Args,") ->",nl])
+ end,
+% emit(["'dec_",ObjName,"'(",{asis,Name},
+% ", Bytes,TagIn,[H|T]) ->",nl]),
+ case {get_object_field(Name,ObjectFields),OptOrMand} of
+ {false,'MANDATORY'} ->
+ exit({error,{asn1,{"missing mandatory field in object",
+ ObjName}}});
+ {false,'OPTIONAL'} ->
+ EmitFuncClause("_,_,_"),
+ emit([" exit({error,{'illegal use of missing field in object', ",Name,
+ "}})"]);
+ {false,{'DEFAULT',_DefaultObject}} ->
+ exit({error,{asn1,{"not implemented yet",Name}}});
+ {{Name,TypeSpec},_} ->
+ EmitFuncClause("Bytes,TagIn,[H|T]"),
+ case TypeSpec#typedef.name of
+ {ExtMod,TypeName} ->
+ emit({indent(3),"'",ExtMod,"':'dec_",TypeName,
+ "'(H, Bytes, TagIn, T)"});
+ TypeName ->
+ emit({indent(3),"'dec_",TypeName,"'(H, Bytes, TagIn, T)"})
+ end
+ end,
+ case more_genfields(Rest) of
+ true ->
+ emit([";",nl]);
+ false ->
+ emit([".",nl])
+ end,
+ gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
+gen_decode_objectfields(CN,[_|Cs],O,OF,CAcc) ->
+ gen_decode_objectfields(CN,Cs,O,OF,CAcc);
+gen_decode_objectfields(_,[],_,_,CAcc) ->
+ CAcc.
+
+
+
+% gen_decode_objectfields(Erules,Class,ObjName,[{FieldName,Type}|Rest],ConstrAcc) ->
+% Fields = Class#objectclass.fields,
+% MaybeConstr =
+% case is_typefield(Fields,FieldName) of
+% true ->
+% Def = Type#typedef.typespec,
+% emit({"'dec_",ObjName,"'(",{asis,FieldName},
+% ", Bytes, TagIn, RestPrimFieldName) ->",nl}),
+% OTag = Def#type.tag,
+% Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
+% Prop =
+% case get_optionalityspec(Fields,FieldName) of
+% 'OPTIONAL' -> opt_or_default;
+% {'DEFAULT',_} -> opt_or_default;
+% _ -> mandatory
+% end,
+% CAcc =
+% case Type#typedef.name of
+% {primitive,bif} ->
+% gen_dec_prim(Erules,Def,"Bytes",Tag,"TagIn",no_length,
+% ?PRIMITIVE,Prop),
+% [];
+% {constructed,bif} ->
+% emit({" 'dec_",ObjName,'_',FieldName,"'(Bytes,",
+% {asis,Prop},", TagIn ++ ",{asis,Tag},")"}),
+% [{['dec_',ObjName,'_',FieldName],Def}];
+% {ExtMod,TypeName} ->
+% emit({" '",ExtMod,"':'dec_",TypeName,"'(Bytes, ",
+% {asis,Prop},", TagIn ++ ",{asis,Tag},")"}),
+% [];
+% TypeName ->
+% emit({" 'dec_",TypeName,"'(Bytes, ",{asis,Prop},
+% ", TagIn ++ ",{asis,Tag},")"}),
+% []
+% end,
+% case more_genfields(Fields,Rest) of
+% true ->
+% emit({";",nl});
+% false ->
+% emit({".",nl})
+% end,
+% CAcc;
+% {false,objectfield} ->
+% emit({"'dec_",ObjName,"'(",{asis,FieldName},
+% ", Bytes, TagIn, [H|T]) ->",nl}),
+% case Type#typedef.name of
+% {ExtMod,TypeName} ->
+% emit({indent(3),"'",ExtMod,"':'dec_",TypeName,
+% "'(H, Bytes, TagIn, T)"});
+% TypeName ->
+% emit({indent(3),"'dec_",TypeName,
+% "'(H, Bytes, TagIn, T)"})
+% end,
+% case more_genfields(Fields,Rest) of
+% true ->
+% emit({";",nl});
+% false ->
+% emit({".",nl})
+% end,
+% [];
+% {false,_} ->
+% []
+% end,
+% gen_decode_objectfields(Erules,Class,ObjName,Rest,MaybeConstr ++ ConstrAcc);
+% gen_decode_objectfields(Erules,C,O,[H|T],CAcc) ->
+% gen_decode_objectfields(Erules,C,O,T,CAcc);
+% gen_decode_objectfields(_,_,_,[],CAcc) ->
+% CAcc.
+
+gen_decode_constr_type(Erules,[{Name,Def}|Rest]) ->
+%% emit({Name,"(Bytes, OptOrMand) ->",nl}),
+%% emit({" ",Name,"(Bytes, OptOrMand, []).",nl,nl}),
+ emit({Name,"(Bytes, OptOrMand, TagIn) ->",nl}),
+ InnerType = asn1ct_gen:get_inner(Def#type.def),
+ asn1ct_gen:gen_decode_constructed(ber,Name,InnerType,Def),
+ gen_decode_constr_type(Erules,Rest);
+gen_decode_constr_type(Erules,[TypeDef|Rest]) when record(TypeDef,typedef) ->
+ case is_already_generated(dec,TypeDef#typedef.name) of
+ true -> ok;
+ _ ->
+ gen_decode(Erules,TypeDef)
+ end,
+ gen_decode_constr_type(Erules,Rest);
+gen_decode_constr_type(_,[]) ->
+ ok.
+
+gen_decode_field_call(ObjName,FieldName,Bytes,Type) ->
+ Def = Type#typedef.typespec,
+ OTag = Def#type.tag,
+ Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
+ case Type#typedef.name of
+ {primitive,bif} -> %%tag should be the primitive tag
+ gen_dec_prim(ber,Def,Bytes,Tag,"TagIn",no_length,
+ ?PRIMITIVE,opt_or_default),
+ [];
+ {constructed,bif} ->
+ emit({" 'dec_",ObjName,'_',FieldName,
+ "'(",Bytes,",opt_or_default, TagIn ++ ",{asis,Tag},")"}),
+ [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
+ {ExtMod,TypeName} ->
+ emit({" '",ExtMod,"':'dec_",TypeName,
+ "'(",Bytes,", opt_or_default,TagIn ++ ",{asis,Tag},")"}),
+ [];
+ TypeName ->
+ emit({" 'dec_",TypeName,"'(",Bytes,
+ ", opt_or_default,TagIn ++ ",{asis,Tag},")"}),
+ []
+ end.
+
+gen_decode_default_call(ClassName,FieldName,Bytes,Type) ->
+ CurrentMod = get(currmod),
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ OTag = Type#type.tag,
+ Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
+ case asn1ct_gen:type(InnerType) of
+ {constructed,bif} ->
+ emit([" 'dec_",ClassName,'_',FieldName,"'(",Bytes,
+ ",opt_or_default, TagIn ++ ",{asis,Tag},")"]),
+ [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
+ typespec=Type}];
+ {primitive,bif} ->
+ gen_dec_prim(ber,Type,Bytes,Tag,"TagIn",no_length,
+ ?PRIMITIVE,opt_or_default),
+ [];
+ #'Externaltypereference'{module=CurrentMod,type=Etype} ->
+ emit([" 'dec_",Etype,"'(",Bytes,
+ " ,opt_or_default, TagIn ++ ",{asis,Tag},")",nl]),
+ [];
+ #'Externaltypereference'{module=Emod,type=Etype} ->
+ emit([" '",Emod,"':'dec_",Etype,"'(",Bytes,
+ ", opt_or_defualt, TagIn ++ ",{asis,Tag},")",nl]),
+ []
+ end.
+
+
+more_genfields([]) ->
+ false;
+more_genfields([Field|Fields]) ->
+ case element(1,Field) of
+ typefield ->
+ true;
+ objectfield ->
+ true;
+ _ ->
+ more_genfields(Fields)
+ end.
+
+
+
+%% Object Set code generating for encoding and decoding
+%% ----------------------------------------------------
+gen_objectset_code(Erules,ObjSet) ->
+ ObjSetName = ObjSet#typedef.name,
+ Def = ObjSet#typedef.typespec,
+% {ClassName,ClassDef} = Def#'ObjectSet'.class,
+ #'Externaltypereference'{module=ClassModule,
+ type=ClassName} = Def#'ObjectSet'.class,
+ ClassDef = asn1_db:dbget(ClassModule,ClassName),
+ UniqueFName = Def#'ObjectSet'.uniquefname,
+ Set = Def#'ObjectSet'.set,
+ emit({nl,nl,nl,"%%================================"}),
+ emit({nl,"%% ",ObjSetName}),
+ emit({nl,"%%================================",nl}),
+ case ClassName of
+ {_Module,ExtClassName} ->
+ gen_objset_code(Erules,ObjSetName,UniqueFName,Set,
+ ExtClassName,ClassDef);
+ _ ->
+ gen_objset_code(Erules,ObjSetName,UniqueFName,Set,
+ ClassName,ClassDef)
+ end,
+ emit(nl).
+
+gen_objset_code(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassDef)->
+ ClassFields = (ClassDef#classdef.typespec)#objectclass.fields,
+ InternalFuncs=gen_objset_enc(ObjSetName,UniqueFName,Set,ClassName,ClassFields,1,[]),
+ gen_objset_dec(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassFields,1),
+ gen_internal_funcs(Erules,InternalFuncs).
+
+%% gen_objset_enc iterates over the objects of the object set
+gen_objset_enc(_,{unique,undefined},_,_,_,_,_) ->
+ %% There is no unique field in the class of this object set
+ %% don't bother about the constraint
+ [];
+gen_objset_enc(ObjSName,UniqueName,
+ [{ObjName,Val,Fields},T|Rest],ClName,ClFields,NthObj,Acc)->
+ emit({"'getenc_",ObjSName,"'(",{asis,UniqueName},",",{asis,Val},") ->",nl}),
+ {InternalFunc,NewNthObj}=
+ case ObjName of
+ no_name ->
+ gen_inlined_enc_funs(Fields,ClFields,ObjSName,NthObj);
+ _Other ->
+ emit({" fun 'enc_",ObjName,"'/4"}),
+ {[],NthObj}
+ end,
+ emit({";",nl}),
+ gen_objset_enc(ObjSName,UniqueName,[T|Rest],ClName,ClFields,
+ NewNthObj,InternalFunc ++ Acc);
+gen_objset_enc(ObjSetName,UniqueName,
+ [{ObjName,Val,Fields}],_ClName,ClFields,NthObj,Acc) ->
+ emit({"'getenc_",ObjSetName,"'(",{asis,UniqueName},",",{asis,Val},") ->",nl}),
+ {InternalFunc,_}=
+ case ObjName of
+ no_name ->
+ gen_inlined_enc_funs(Fields,ClFields,ObjSetName,NthObj);
+ _Other ->
+ emit({" fun 'enc_",ObjName,"'/4"}),
+ {[],NthObj}
+ end,
+ emit({".",nl,nl}),
+ InternalFunc ++ Acc;
+%% See X.681 Annex E for the following case
+gen_objset_enc(ObjSetName,_UniqueName,['EXTENSIONMARK'],
+ _ClName,_ClFields,_NthObj,Acc) ->
+ emit({"'getenc_",ObjSetName,"'(_, _) ->",nl}),
+ emit({indent(3),"fun(_Attr, Val, _TagIn, _RestPrimFieldName) ->",nl}),
+ emit({indent(6),"Len = case Val of",nl,indent(9),
+ "Bin when binary(Bin) -> size(Bin);",nl,indent(9),
+ "_ -> length(Val)",nl,indent(6),"end,"}),
+ emit({indent(6),"{Val,Len}",nl}),
+ emit({indent(3),"end.",nl,nl}),
+ Acc;
+gen_objset_enc(_,_,[],_,_,_,Acc) ->
+ Acc.
+
+%% gen_inlined_enc_funs for each object iterates over all fields of a
+%% class, and for each typefield it checks if the object has that
+%% field and emits the proper code.
+gen_inlined_enc_funs(Fields,[{typefield,Name,_}|Rest],ObjSetName,
+ NthObj) ->
+ InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
+ case lists:keysearch(Name,1,Fields) of
+ {value,{_,Type}} when record(Type,type) ->
+ emit({indent(3),"fun(Type, Val, TagIn, _RestPrimFieldName) ->",nl,
+ indent(6),"case Type of",nl}),
+ {Ret,N} = emit_inner_of_fun(Type,InternalDefFunName),
+ gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
+ {value,{_,Type}} when record(Type,typedef) ->
+ emit({indent(3),"fun(Type, Val, TagIn, _RestPrimFieldName) ->",nl,
+ indent(6),"case Type of",nl}),
+ emit({indent(9),{asis,Name}," ->",nl}),
+ {Ret,N} = emit_inner_of_fun(Type,InternalDefFunName),
+ gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
+ false ->
+ gen_inlined_enc_funs(Fields,Rest,ObjSetName,NthObj)
+ end;
+gen_inlined_enc_funs(Fields,[_H|Rest],ObjSetName,NthObj) ->
+ gen_inlined_enc_funs(Fields,Rest,ObjSetName,NthObj);
+gen_inlined_enc_funs(_,[],_,NthObj) ->
+ {[],NthObj}.
+
+gen_inlined_enc_funs1(Fields,[{typefield,Name,_}|Rest],ObjSetName,
+ NthObj,Acc) ->
+ InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
+ {Acc2,NAdd}=
+ case lists:keysearch(Name,1,Fields) of
+ {value,{_,Type}} when record(Type,type) ->
+ emit({";",nl}),
+ {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
+ {Ret++Acc,N};
+ {value,{_,Type}} when record(Type,typedef) ->
+ emit({";",nl,indent(9),{asis,Name}," ->",nl}),
+ {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
+ {Ret++Acc,N};
+ false ->
+ {Acc,0}
+ end,
+ gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+NAdd,Acc2);
+gen_inlined_enc_funs1(Fields,[_H|Rest],ObjSetName,NthObj,Acc)->
+ gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj,Acc);
+gen_inlined_enc_funs1(_,[],_,NthObj,Acc) ->
+ emit({nl,indent(6),"end",nl}),
+ emit({indent(3),"end"}),
+ {Acc,NthObj}.
+
+
+emit_inner_of_fun(TDef = #typedef{name={ExtMod,Name},typespec=Type},
+ InternalDefFunName) ->
+ OTag = Type#type.tag,
+ Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
+ case {ExtMod,Name} of
+ {primitive,bif} ->
+ emit(indent(12)),
+ gen_encode_prim(ber,Type,["TagIn ++ ",{asis,Tag}],"Val"),
+ {[],0};
+ {constructed,bif} ->
+ emit([indent(12),"'enc_",
+ InternalDefFunName,"'(Val,TagIn ++ ",
+ {asis,Tag},")"]),
+ {[TDef#typedef{name=InternalDefFunName}],1};
+ _ ->
+ emit({indent(12),"'",ExtMod,"':'enc_",Name,"'(Val, TagIn ++ ",
+ {asis,Tag},")"}),
+ {[],0}
+ end;
+emit_inner_of_fun(#typedef{name=Name,typespec=Type},_) ->
+ OTag = Type#type.tag,
+ Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
+ emit({indent(12),"'enc_",Name,"'(Val, TagIn ++ ",{asis,Tag},")"}),
+ {[],0};
+emit_inner_of_fun(Type,_) when record(Type,type) ->
+ CurrMod = get(currmod),
+ OTag = Type#type.tag,
+ Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
+ case Type#type.def of
+ Def when atom(Def) ->
+ emit({indent(9),Def," ->",nl,indent(12)}),
+ gen_encode_prim(ber,Type,["TagIn ++ ",{asis,Tag}],"Val");
+ TRef when record(TRef,typereference) ->
+ T = TRef#typereference.val,
+ emit({indent(9),T," ->",nl,indent(12),"'enc_",T,
+ "'(Val, TagIn ++ ",{asis,Tag},")"});
+ #'Externaltypereference'{module=CurrMod,type=T} ->
+ emit({indent(9),T," ->",nl,indent(12),"'enc_",T,
+ "'(Val, TagIn ++ ",{asis,Tag},")"});
+ #'Externaltypereference'{module=ExtMod,type=T} ->
+ emit({indent(9),T," ->",nl,indent(12),ExtMod,":'enc_",
+ T,"'(Val, TagIn ++ ",{asis,Tag},")"})
+ end,
+ {[],0}.
+
+indent(N) ->
+ lists:duplicate(N,32). % 32 = space
+
+
+gen_objset_dec(_,_,{unique,undefined},_,_,_,_) ->
+ %% There is no unique field in the class of this object set
+ %% don't bother about the constraint
+ ok;
+gen_objset_dec(Erules,ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],
+ ClName,ClFields,NthObj)->
+ emit({"'getdec_",ObjSName,"'(",{asis,UniqueName},",",{asis,Val},
+ ") ->",nl}),
+ NewNthObj=
+ case ObjName of
+ no_name ->
+ gen_inlined_dec_funs(Erules,Fields,ClFields,ObjSName,
+ NthObj);
+ _Other ->
+ emit({" fun 'dec_",ObjName,"'/4"}),
+ NthObj
+ end,
+ emit({";",nl}),
+ gen_objset_dec(Erules,ObjSName,UniqueName,[T|Rest],ClName,ClFields,
+ NewNthObj);
+gen_objset_dec(Erules,ObjSetName,UniqueName,[{ObjName,Val,Fields}],_ClName,
+ ClFields,NthObj) ->
+ emit({"'getdec_",ObjSetName,"'(",{asis,UniqueName},",",{asis,Val},") ->",nl}),
+ case ObjName of
+ no_name ->
+ gen_inlined_dec_funs(Erules,Fields,ClFields,ObjSetName,
+ NthObj);
+ _Other ->
+ emit({" fun 'dec_",ObjName,"'/4"})
+ end,
+ emit({".",nl,nl});
+gen_objset_dec(_,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,_ClFields,
+ _NthObj) ->
+ emit({"'getdec_",ObjSetName,"'(_, _) ->",nl}),
+ emit({indent(3),"fun(_, Bytes, _, _) ->",nl}),
+ emit({indent(6),"Len = case Bytes of",nl,indent(9),
+ "Bin when binary(Bin) -> size(Bin);",nl,indent(9),
+ "_ -> length(Bytes)",nl,indent(6),"end,"}),
+ emit({indent(6),"{Bytes,[],Len}",nl}),
+ emit({indent(3),"end.",nl,nl}),
+ ok;
+gen_objset_dec(_,_,_,[],_,_,_) ->
+ ok.
+
+gen_inlined_dec_funs(Erules,Fields,[{typefield,Name,Prop}|Rest],
+ ObjSetName,NthObj) ->
+ DecProp = case Prop of
+ 'OPTIONAL' -> opt_or_default;
+ {'DEFAULT',_} -> opt_or_default;
+ _ -> mandatory
+ end,
+ InternalDefFunName = [NthObj,Name,ObjSetName],
+ case lists:keysearch(Name,1,Fields) of
+ {value,{_,Type}} when record(Type,type) ->
+ emit({indent(3),"fun(Type, Bytes, TagIn, _RestPrimFieldName) ->",
+ nl,indent(6),"case Type of",nl}),
+ N=emit_inner_of_decfun(Erules,Type,DecProp,InternalDefFunName),
+ gen_inlined_dec_funs1(Erules,Fields,Rest,ObjSetName,NthObj+N);
+ {value,{_,Type}} when record(Type,typedef) ->
+ emit({indent(3),"fun(Type, Bytes, TagIn, _RestPrimFieldName) ->",
+ nl,indent(6),"case Type of",nl}),
+ emit({indent(9),{asis,Name}," ->",nl}),
+ N=emit_inner_of_decfun(Erules,Type,DecProp,InternalDefFunName),
+ gen_inlined_dec_funs1(Erules,Fields,Rest,ObjSetName,NthObj+N);
+ false ->
+ gen_inlined_dec_funs(Erules,Fields,Rest,ObjSetName,NthObj)
+ end;
+gen_inlined_dec_funs(Erules,Fields,[_H|Rest],ObjSetName,NthObj) ->
+ gen_inlined_dec_funs(Erules,Fields,Rest,ObjSetName,NthObj);
+gen_inlined_dec_funs(_,_,[],_,NthObj) ->
+ NthObj.
+
+gen_inlined_dec_funs1(Erules,Fields,[{typefield,Name,Prop}|Rest],
+ ObjSetName,NthObj) ->
+ DecProp = case Prop of
+ 'OPTIONAL' -> opt_or_default;
+ {'DEFAULT',_} -> opt_or_default;
+ _ -> mandatory
+ end,
+ InternalDefFunName = [NthObj,Name,ObjSetName],
+ N=
+ case lists:keysearch(Name,1,Fields) of
+ {value,{_,Type}} when record(Type,type) ->
+ emit({";",nl}),
+ emit_inner_of_decfun(Erules,Type,DecProp,InternalDefFunName);
+ {value,{_,Type}} when record(Type,typedef) ->
+ emit({";",nl,indent(9),{asis,Name}," ->",nl}),
+ emit_inner_of_decfun(Erules,Type,DecProp,InternalDefFunName);
+ false ->
+ 0
+ end,
+ gen_inlined_dec_funs1(Erules,Fields,Rest,ObjSetName,NthObj+N);
+gen_inlined_dec_funs1(Erules,Fields,[_H|Rest],ObjSetName,NthObj)->
+ gen_inlined_dec_funs1(Erules,Fields,Rest,ObjSetName,NthObj);
+gen_inlined_dec_funs1(_,_,[],_,NthObj) ->
+ emit({nl,indent(6),"end",nl}),
+ emit({indent(3),"end"}),
+ NthObj.
+
+emit_inner_of_decfun(Erules,#typedef{name={ExtName,Name},typespec=Type},
+ Prop,InternalDefFunName) ->
+ OTag = Type#type.tag,
+ Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
+ case {ExtName,Name} of
+ {primitive,bif} ->
+ emit(indent(12)),
+ gen_dec_prim(Erules,Type,"Bytes",Tag,"TagIn",no_length,
+ ?PRIMITIVE,Prop),
+ 0;
+ {constructed,bif} ->
+ emit({indent(12),"'dec_",
+ asn1ct_gen:list2name(InternalDefFunName),"'(Bytes, ",Prop,
+ ", TagIn ++ ",{asis,Tag},")"}),
+ 1;
+ _ ->
+ emit({indent(12),"'",ExtName,"':'dec_",Name,"'(Bytes, ",Prop,
+ ", TagIn ++ ",{asis,Tag},")"}),
+ 0
+ end;
+emit_inner_of_decfun(_,#typedef{name=Name,typespec=Type},Prop,_) ->
+ OTag = Type#type.tag,
+ Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
+ emit({indent(12),"'dec_",Name,"'(Bytes, ",Prop,", TagIn ++ ",
+ {asis,Tag},")"}),
+ 0;
+emit_inner_of_decfun(Erules,Type,Prop,_) when record(Type,type) ->
+ OTag = Type#type.tag,
+ Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
+ CurrMod = get(currmod),
+ Def = Type#type.def,
+ InnerType = asn1ct_gen:get_inner(Def),
+ WhatKind = asn1ct_gen:type(InnerType),
+ case WhatKind of
+ {primitive,bif} ->
+ emit({indent(9),Def," ->",nl,indent(12)}),
+ gen_dec_prim(Erules,Type,"Bytes",Tag,"TagIn",no_length,
+ ?PRIMITIVE,Prop);
+% TRef when record(TRef,typereference) ->
+% T = TRef#typereference.val,
+% emit({indent(9),T," ->",nl,indent(12),"'dec_",T,"'(Val)"});
+ #'Externaltypereference'{module=CurrMod,type=T} ->
+ emit({indent(9),T," ->",nl,indent(12),"'dec_",T,
+ "'(Bytes, ",Prop,", TagIn ++ ",{asis,Tag},")"});
+ #'Externaltypereference'{module=ExtMod,type=T} ->
+ emit({indent(9),T," ->",nl,indent(12),ExtMod,":'dec_",
+ T,"'(Bytes, ",Prop,", TagIn ++ ",{asis,Tag},")"})
+ end,
+ 0.
+
+
+gen_internal_funcs(_,[]) ->
+ ok;
+gen_internal_funcs(Erules,[TypeDef|Rest]) ->
+ gen_encode_user(Erules,TypeDef),
+ emit({"'dec_",TypeDef#typedef.name,"'(Bytes, ",
+ unused_optormand_var("OptOrMand",(TypeDef#typedef.typespec)#type.def),", TagIn) ->",nl}),
+ gen_decode_user(Erules,TypeDef),
+ gen_internal_funcs(Erules,Rest).
+
+
+dbdec(Type) ->
+ demit({"io:format(\"decoding: ",{asis,Type},"~w~n\",[Bytes]),",nl}).
+
+
+decode_class('UNIVERSAL') ->
+ ?UNIVERSAL;
+decode_class('APPLICATION') ->
+ ?APPLICATION;
+decode_class('CONTEXT') ->
+ ?CONTEXT;
+decode_class('PRIVATE') ->
+ ?PRIVATE.
+
+decode_type('BOOLEAN') -> 1;
+decode_type('INTEGER') -> 2;
+decode_type('BIT STRING') -> 3;
+decode_type('OCTET STRING') -> 4;
+decode_type('NULL') -> 5;
+decode_type('OBJECT IDENTIFIER') -> 6;
+decode_type('OBJECT DESCRIPTOR') -> 7;
+decode_type('EXTERNAL') -> 8;
+decode_type('REAL') -> 9;
+decode_type('ENUMERATED') -> 10;
+decode_type('EMBEDDED_PDV') -> 11;
+decode_type('SEQUENCE') -> 16;
+decode_type('SEQUENCE OF') -> 16;
+decode_type('SET') -> 17;
+decode_type('SET OF') -> 17;
+decode_type('NumericString') -> 18;
+decode_type('PrintableString') -> 19;
+decode_type('TeletexString') -> 20;
+decode_type('VideotexString') -> 21;
+decode_type('IA5String') -> 22;
+decode_type('UTCTime') -> 23;
+decode_type('GeneralizedTime') -> 24;
+decode_type('GraphicString') -> 25;
+decode_type('VisibleString') -> 26;
+decode_type('GeneralString') -> 27;
+decode_type('UniversalString') -> 28;
+decode_type('BMPString') -> 30;
+decode_type('CHOICE') -> 'CHOICE'; % choice gets the tag from the actual alternative
+decode_type(Else) -> exit({error,{asn1,{unrecognized_type,Else}}}).
+
+add_removed_bytes() ->
+ asn1ct_name:delete(rb),
+ add_removed_bytes(asn1ct_name:all(rb)).
+
+add_removed_bytes([H,T1|T]) ->
+ emit({{var,H},"+"}),
+ add_removed_bytes([T1|T]);
+add_removed_bytes([H|T]) ->
+ emit({{var,H}}),
+ add_removed_bytes(T);
+add_removed_bytes([]) ->
+ true.
+
+mkfuncname(WhatKind,DecOrEnc) ->
+ case WhatKind of
+ #'Externaltypereference'{module=Mod,type=EType} ->
+ CurrMod = get(currmod),
+ case CurrMod of
+ Mod ->
+ lists:concat(["'",DecOrEnc,"_",EType,"'"]);
+ _ ->
+% io:format("CurrMod: ~p, Mod: ~p~n",[CurrMod,Mod]),
+ lists:concat(["'",Mod,"':'",DecOrEnc,"_",EType,"'"])
+ end;
+ #'typereference'{val=EType} ->
+ lists:concat(["'",DecOrEnc,"_",EType,"'"]);
+ 'ASN1_OPEN_TYPE' ->
+ lists:concat(["'",DecOrEnc,"_",WhatKind,"'"])
+
+ end.
+
+optionals(L) -> optionals(L,[],1).
+
+optionals([{'EXTENSIONMARK',_,_}|Rest],Acc,Pos) ->
+ optionals(Rest,Acc,Pos); % optionals in extension are currently not handled
+optionals([#'ComponentType'{name=Name,prop='OPTIONAL'}|Rest],Acc,Pos) ->
+ optionals(Rest,[{Name,Pos}|Acc],Pos+1);
+optionals([#'ComponentType'{name=Name,prop={'DEFAULT',_}}|Rest],Acc,Pos) ->
+ optionals(Rest,[{Name,Pos}|Acc],Pos+1);
+optionals([#'ComponentType'{}|Rest],Acc,Pos) ->
+ optionals(Rest,Acc,Pos+1);
+optionals([],Acc,_) ->
+ lists:reverse(Acc).
+
+get_constraint(C,Key) ->
+ case lists:keysearch(Key,1,C) of
+ false ->
+ no;
+ {value,{_,V}} ->
+ V
+ end.
+
+%% if the original option was ber and it has been wrapped to ber_bin
+%% turn it back to ber
+re_wrap_erule(ber_bin) ->
+ case get(encoding_options) of
+ Options when list(Options) ->
+ case lists:member(ber,Options) of
+ true -> ber;
+ _ -> ber_bin
+ end;
+ _ -> ber_bin
+ end;
+re_wrap_erule(Erule) ->
+ Erule.
+
+is_already_generated(Operation,Name) ->
+ case get(class_default_type) of
+ undefined ->
+ put(class_default_type,[{Operation,Name}]),
+ false;
+ GeneratedList ->
+ case lists:member({Operation,Name},GeneratedList) of
+ true ->
+ true;
+ false ->
+ put(class_default_type,[{Operation,Name}|GeneratedList]),
+ false
+ end
+ end.
+
+get_class_fields(#classdef{typespec=ObjClass}) ->
+ ObjClass#objectclass.fields;
+get_class_fields(#objectclass{fields=Fields}) ->
+ Fields;
+get_class_fields(_) ->
+ [].
+
+get_object_field(Name,ObjectFields) ->
+ case lists:keysearch(Name,1,ObjectFields) of
+ {value,Field} -> Field;
+ false -> false
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_ber_bin_v2.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_ber_bin_v2.erl
new file mode 100644
index 0000000000..89530d4017
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_ber_bin_v2.erl
@@ -0,0 +1,1562 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1ct_gen_ber_bin_v2.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
+%%
+-module(asn1ct_gen_ber_bin_v2).
+
+%% Generate erlang module which handles (PER) encode and decode for
+%% all types in an ASN.1 module
+
+-include("asn1_records.hrl").
+
+-export([pgen/4]).
+-export([decode_class/1, decode_type/1]).
+-export([add_removed_bytes/0]).
+-export([gen_encode/2,gen_encode/3,gen_decode/2,gen_decode/3]).
+-export([gen_encode_prim/4]).
+-export([gen_dec_prim/7]).
+-export([gen_objectset_code/2, gen_obj_code/3]).
+-export([encode_tag_val/3]).
+-export([gen_inc_decode/2]).
+
+-import(asn1ct_gen, [emit/1,demit/1]).
+
+ % the encoding of class of tag bits 8 and 7
+-define(UNIVERSAL, 0).
+-define(APPLICATION, 16#40).
+-define(CONTEXT, 16#80).
+-define(PRIVATE, 16#C0).
+
+ % primitive or constructed encoding % bit 6
+-define(PRIMITIVE, 0).
+-define(CONSTRUCTED, 2#00100000).
+
+
+-define(T_ObjectDescriptor, ?UNIVERSAL bor ?PRIMITIVE bor 7).
+ % restricted character string types
+-define(T_NumericString, ?UNIVERSAL bor ?PRIMITIVE bor 18). %can be constructed
+-define(T_PrintableString, ?UNIVERSAL bor ?PRIMITIVE bor 19). %can be constructed
+-define(T_TeletexString, ?UNIVERSAL bor ?PRIMITIVE bor 20). %can be constructed
+-define(T_VideotexString, ?UNIVERSAL bor ?PRIMITIVE bor 21). %can be constructed
+-define(T_IA5String, ?UNIVERSAL bor ?PRIMITIVE bor 22). %can be constructed
+-define(T_GraphicString, ?UNIVERSAL bor ?PRIMITIVE bor 25). %can be constructed
+-define(T_VisibleString, ?UNIVERSAL bor ?PRIMITIVE bor 26). %can be constructed
+-define(T_GeneralString, ?UNIVERSAL bor ?PRIMITIVE bor 27). %can be constructed
+
+%% pgen(Erules, Module, TypeOrVal)
+%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module
+%% .hrl file is only generated if necessary
+%% Erules = per | ber
+%% Module = atom()
+%% TypeOrVal = {TypeList,ValueList,PTypeList}
+%% TypeList = ValueList = [atom()]
+
+pgen(OutFile,Erules,Module,TypeOrVal) ->
+ asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,true).
+
+
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+%% Generate ENCODING
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+
+%%===============================================================================
+%% encode #{typedef, {pos, name, typespec}}
+%%===============================================================================
+
+gen_encode(Erules,Type) when record(Type,typedef) ->
+ gen_encode_user(Erules,Type).
+
+%%===============================================================================
+%% encode #{type, {tag, def, constraint}}
+%%===============================================================================
+
+gen_encode(Erules,Typename,Type) when record(Type,type) ->
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ ObjFun =
+ case lists:keysearch(objfun,1,Type#type.tablecinf) of
+ {value,{_,_Name}} ->
+ ", ObjFun";
+ false ->
+ ""
+ end,
+
+ case asn1ct_gen:type(InnerType) of
+ {constructed,bif} ->
+ emit([nl,nl,nl,"%%================================"]),
+ emit([nl,"%% ",asn1ct_gen:list2name(Typename)]),
+ emit([nl,"%%================================",nl]),
+ case length(Typename) of
+ 1 -> % top level type
+ emit(["'enc_",asn1ct_gen:list2name(Typename),
+ "'(Val",ObjFun,") ->",nl]),
+ emit([" 'enc_",asn1ct_gen:list2name(Typename),
+ "'(Val, ", {asis,lists:reverse(Type#type.tag)},ObjFun,").",nl,nl]);
+ _ -> % embedded type with constructed name
+ true
+ end,
+ case lists:member(InnerType,['SET','SEQUENCE']) of
+ true ->
+ case get(asn_keyed_list) of
+ true ->
+ CompList =
+ case Type#type.def of
+ #'SEQUENCE'{components=Cl} -> Cl;
+ #'SET'{components=Cl} -> Cl
+ end,
+ emit([nl,"'enc_",asn1ct_gen:list2name(Typename),
+ "'(Val, TagIn",ObjFun,
+ ") when list(Val) ->",nl]),
+ emit([" 'enc_",asn1ct_gen:list2name(Typename),
+ "'(?RT_BER:fixoptionals(",
+ {asis,optionals(CompList)},
+ ",Val), TagIn",ObjFun,");",nl,nl]);
+ _ -> true
+ end;
+ _ ->
+ emit([nl,"'enc_",asn1ct_gen:list2name(Typename),
+ "'({'",asn1ct_gen:list2name(Typename),
+ "',Val}, TagIn",ObjFun,") ->",nl]),
+ emit([" 'enc_",asn1ct_gen:list2name(Typename),
+ "'(Val, TagIn",ObjFun,");",nl,nl])
+ end,
+ emit(["'enc_",asn1ct_gen:list2name(Typename),
+ "'(Val, TagIn",ObjFun,") ->",nl," "]),
+ asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
+ _ ->
+ true
+ end;
+
+%%===============================================================================
+%% encode ComponentType
+%%===============================================================================
+
+gen_encode(Erules,Tname,{'ComponentType',_Pos,Cname,Type,_Prop,_Tags}) ->
+ NewTname = [Cname|Tname],
+ %% The tag is set to [] to avoid that it is
+ %% taken into account twice, both as a component/alternative (passed as
+ %% argument to the encode decode function and within the encode decode
+ %% function it self.
+ NewType = Type#type{tag=[]},
+ gen_encode(Erules,NewTname,NewType).
+
+gen_encode_user(Erules,D) when record(D,typedef) ->
+ Typename = [D#typedef.name],
+ Type = D#typedef.typespec,
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ OTag = Type#type.tag,
+ Tag = [encode_tag_val(decode_class(X#tag.class),X#tag.form,X#tag.number)|| X <- OTag],
+ emit([nl,nl,"%%================================"]),
+ emit([nl,"%% ",Typename]),
+ emit([nl,"%%================================",nl]),
+ emit(["'enc_",asn1ct_gen:list2name(Typename),
+ "'(Val",") ->",nl]),
+ emit([" 'enc_",asn1ct_gen:list2name(Typename),
+ "'(Val, ", {asis,lists:reverse(Tag)},").",nl,nl]),
+
+ case lists:member(InnerType,['SET','SEQUENCE']) of
+ true ->
+ case get(asn_keyed_list) of
+ true ->
+ CompList =
+ case Type#type.def of
+ #'SEQUENCE'{components=Cl} -> Cl;
+ #'SET'{components=Cl} -> Cl
+ end,
+
+ emit([nl,"'enc_",asn1ct_gen:list2name(Typename),
+ "'(Val, TagIn) when list(Val) ->",nl]),
+ emit([" 'enc_",asn1ct_gen:list2name(Typename),
+ "'(?RT_BER:fixoptionals(",
+ {asis,optionals(CompList)},
+ ",Val), TagIn);",nl,nl]);
+ _ -> true
+ end;
+ _ ->
+ emit({nl,"'enc_",asn1ct_gen:list2name(Typename),
+ "'({'",asn1ct_gen:list2name(Typename),"',Val}, TagIn) ->",nl}),
+ emit({" 'enc_",asn1ct_gen:list2name(Typename),"'(Val, TagIn);",nl,nl})
+ end,
+ emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val, TagIn) ->",nl}),
+ CurrentMod = get(currmod),
+ case asn1ct_gen:type(InnerType) of
+ {constructed,bif} ->
+ asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,D);
+ {primitive,bif} ->
+ gen_encode_prim(ber,Type,"TagIn","Val"),
+ emit([".",nl]);
+ #typereference{val=Ename} ->
+ emit([" 'enc_",Ename,"'(Val, TagIn).",nl]);
+ #'Externaltypereference'{module=CurrentMod,type=Etype} ->
+ emit([" 'enc_",Etype,"'(Val, TagIn).",nl]);
+ #'Externaltypereference'{module=Emod,type=Etype} ->
+ emit([" '",Emod,"':'enc_",Etype,"'(Val, TagIn).",nl]);
+ 'ASN1_OPEN_TYPE' ->
+ emit(["%% OPEN TYPE",nl]),
+ gen_encode_prim(ber,
+ Type#type{def='ASN1_OPEN_TYPE'},
+ "TagIn","Val"),
+ emit([".",nl])
+ end.
+
+gen_encode_prim(_Erules,D,DoTag,Value) when record(D,type) ->
+
+%%% Constraint is currently not used for BER (except for BitString) and therefore replaced
+%%% with [] as a placeholder
+ BitStringConstraint = D#type.constraint,
+ Constraint = [],
+ asn1ct_name:new(enumval),
+ case D#type.def of
+ 'BOOLEAN' ->
+ emit_encode_func('boolean',Value,DoTag);
+ 'INTEGER' ->
+ emit_encode_func('integer',Constraint,Value,DoTag);
+ {'INTEGER',NamedNumberList} ->
+ emit_encode_func('integer',Constraint,Value,
+ NamedNumberList,DoTag);
+ {'ENUMERATED',NamedNumberList={_,_}} ->
+
+ emit(["case (case ",Value," of {asn1_enum,_}->",Value,";{_,_}->element(2,",Value,");_->",
+ Value," end) of",nl]),
+ emit_enc_enumerated_cases(NamedNumberList,DoTag);
+ {'ENUMERATED',NamedNumberList} ->
+
+ emit(["case (case ",Value," of {_,_}->element(2,",Value,");_->",
+ Value," end) of",nl]),
+ emit_enc_enumerated_cases(NamedNumberList,DoTag);
+
+ {'BIT STRING',NamedNumberList} ->
+ emit_encode_func('bit_string',BitStringConstraint,Value,
+ NamedNumberList,DoTag);
+ 'ANY' ->
+ emit_encode_func('open_type', Value,DoTag);
+ 'NULL' ->
+ emit_encode_func('null',Value,DoTag);
+ 'OBJECT IDENTIFIER' ->
+ emit_encode_func("object_identifier",Value,DoTag);
+ 'ObjectDescriptor' ->
+ emit_encode_func('restricted_string',Constraint,Value,
+ ?T_ObjectDescriptor,DoTag);
+ 'OCTET STRING' ->
+ emit_encode_func('octet_string',Constraint,Value,DoTag);
+ 'NumericString' ->
+ emit_encode_func('restricted_string',Constraint,Value,
+ ?T_NumericString,DoTag);
+ 'TeletexString' ->
+ emit_encode_func('restricted_string',Constraint,Value,
+ ?T_TeletexString,DoTag);
+ 'VideotexString' ->
+ emit_encode_func('restricted_string',Constraint,Value,
+ ?T_VideotexString,DoTag);
+ 'GraphicString' ->
+ emit_encode_func('restricted_string',Constraint,Value,
+ ?T_GraphicString,DoTag);
+ 'VisibleString' ->
+ emit_encode_func('restricted_string',Constraint,Value,
+ ?T_VisibleString,DoTag);
+ 'GeneralString' ->
+ emit_encode_func('restricted_string',Constraint,Value,
+ ?T_GeneralString,DoTag);
+ 'PrintableString' ->
+ emit_encode_func('restricted_string',Constraint,Value,
+ ?T_PrintableString,DoTag);
+ 'IA5String' ->
+ emit_encode_func('restricted_string',Constraint,Value,
+ ?T_IA5String,DoTag);
+ 'UniversalString' ->
+ emit_encode_func('universal_string',Constraint,Value,DoTag);
+ 'BMPString' ->
+ emit_encode_func('BMP_string',Constraint,Value,DoTag);
+ 'UTCTime' ->
+ emit_encode_func('utc_time',Constraint,Value,DoTag);
+ 'GeneralizedTime' ->
+ emit_encode_func('generalized_time',Constraint,Value,DoTag);
+ 'ASN1_OPEN_TYPE' ->
+ emit_encode_func('open_type', Value,DoTag);
+ XX ->
+ exit({'can not encode' ,XX})
+ end.
+
+
+emit_encode_func(Name,Value,Tags) when atom(Name) ->
+ emit_encode_func(atom_to_list(Name),Value,Tags);
+emit_encode_func(Name,Value,Tags) ->
+ Fname = "?RT_BER:encode_" ++ Name,
+ emit([Fname,"(",Value,", ",Tags,")"]).
+
+emit_encode_func(Name,Constraint,Value,Tags) when atom(Name) ->
+ emit_encode_func(atom_to_list(Name),Constraint,Value,Tags);
+emit_encode_func(Name,Constraint,Value,Tags) ->
+ Fname = "?RT_BER:encode_" ++ Name,
+ emit([Fname,"(",{asis,Constraint},", ",Value,", ",Tags,")"]).
+
+emit_encode_func(Name,Constraint,Value,Asis,Tags) when atom(Name) ->
+ emit_encode_func(atom_to_list(Name),Constraint,Value,Asis,Tags);
+emit_encode_func(Name,Constraint,Value,Asis,Tags) ->
+ Fname = "?RT_BER:encode_" ++ Name,
+ emit([Fname,"(",{asis,Constraint},", ",Value,
+ ", ",{asis,Asis},
+ ", ",Tags,")"]).
+
+emit_enc_enumerated_cases({L1,L2}, Tags) ->
+ emit_enc_enumerated_cases(L1++L2, Tags, ext);
+emit_enc_enumerated_cases(L, Tags) ->
+ emit_enc_enumerated_cases(L, Tags, noext).
+
+emit_enc_enumerated_cases([{EnumName,EnumVal},H2|T], Tags, Ext) ->
+ emit([{asis,EnumName}," -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,");",nl]),
+%% emit(["'",{asis,EnumName},"' -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,");",nl]),
+ emit_enc_enumerated_cases([H2|T], Tags, Ext);
+emit_enc_enumerated_cases([{EnumName,EnumVal}], Tags, Ext) ->
+ emit([{asis,EnumName}," -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,")"]),
+%% emit(["'",{asis,EnumName},"' -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,")"]),
+ case Ext of
+ noext -> emit([";",nl]);
+ ext ->
+ emit([";",nl,"{asn1_enum,",{curr,enumval},"} -> ",
+ "?RT_BER:encode_enumerated(",{curr,enumval},",",Tags,");",nl]),
+ asn1ct_name:new(enumval)
+ end,
+ emit([{curr,enumval}," -> exit({error,{asn1, {enumerated_not_in_range,",{curr, enumval},"}}})"]),
+ emit([nl,"end"]).
+
+
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+%% Generate DECODING
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+
+%%===============================================================================
+%% decode #{typedef, {pos, name, typespec}}
+%%===============================================================================
+
+gen_decode(Erules,Type) when record(Type,typedef) ->
+ Def = Type#typedef.typespec,
+ InnerTag = Def#type.tag ,
+
+ Tag = [(decode_class(X#tag.class) bsl 10) + X#tag.number || X <- InnerTag],
+
+ Prefix =
+ case {asn1ct:get_gen_state_field(active),
+ asn1ct:get_gen_state_field(prefix)} of
+ {true,Pref} -> Pref;
+ _ -> "dec_"
+ end,
+ emit({nl,nl}),
+ emit(["'",Prefix,Type#typedef.name,"'(Tlv) ->",nl]),
+ emit([" '",Prefix,Type#typedef.name,"'(Tlv, ",{asis,Tag},").",nl,nl]),
+ emit(["'",Prefix,Type#typedef.name,"'(Tlv, TagIn) ->",nl]),
+ dbdec(Type#typedef.name),
+ gen_decode_user(Erules,Type).
+
+gen_inc_decode(Erules,Type) when record(Type,typedef) ->
+ Prefix = asn1ct:get_gen_state_field(prefix),
+ emit({nl,nl}),
+ emit(["'",Prefix,Type#typedef.name,"'(Tlv, TagIn) ->",nl]),
+ gen_decode_user(Erules,Type).
+
+%%===============================================================================
+%% decode #{type, {tag, def, constraint}}
+%%===============================================================================
+
+%% This gen_decode is called by the gen_decode/3 that decodes
+%% ComponentType and the type of a SEQUENCE OF/SET OF.
+gen_decode(Erules,Tname,Type) when record(Type,type) ->
+ Typename = Tname,
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ Prefix =
+ case asn1ct:get_gen_state_field(active) of
+ true -> "'dec-inc-";
+ _ -> "'dec_"
+ end,
+ case asn1ct_gen:type(InnerType) of
+ {constructed,bif} ->
+ ObjFun =
+ case Type#type.tablecinf of
+ [{objfun,_}|_R] ->
+ ", ObjFun";
+ _ ->
+ ""
+ end,
+ emit([Prefix,asn1ct_gen:list2name(Typename),"'(Tlv, TagIn",ObjFun,") ->",nl]),
+ dbdec(Typename),
+ asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,Type);
+ Rec when record(Rec,'Externaltypereference') ->
+ case {Typename,asn1ct:get_gen_state_field(namelist)} of
+ {[Cname|_],[{Cname,_}|_]} -> %%
+ %% This referenced type must only be generated
+ %% once as incomplete partial decode. Therefore we
+ %% have to check whether this function already is
+ %% generated.
+ case asn1ct:is_function_generated(Typename) of
+ true ->
+ ok;
+ _ ->
+ asn1ct:generated_refed_func(Typename),
+ #'Externaltypereference'{module=M,type=Name}=Rec,
+ TypeDef = asn1_db:dbget(M,Name),
+ gen_decode(Erules,TypeDef)
+ end;
+ _ ->
+ true
+ end;
+ _ ->
+ true
+ end;
+
+
+%%===============================================================================
+%% decode ComponentType
+%%===============================================================================
+
+gen_decode(Erules,Tname,{'ComponentType',_Pos,Cname,Type,_Prop,_Tags}) ->
+ NewTname = [Cname|Tname],
+ %% The tag is set to [] to avoid that it is
+ %% taken into account twice, both as a component/alternative (passed as
+ %% argument to the encode decode function and within the encode decode
+ %% function it self.
+ NewType = Type#type{tag=[]},
+ case {asn1ct:get_gen_state_field(active),
+ asn1ct:get_tobe_refed_func(NewTname)} of
+ {true,{_,NameList}} ->
+ asn1ct:update_gen_state(namelist,NameList),
+ %% remove to gen_refed_funcs list from tobe_refed_funcs later
+ gen_decode(Erules,NewTname,NewType);
+ {No,_} when No == false; No == undefined ->
+ gen_decode(Erules,NewTname,NewType);
+ _ ->
+ ok
+ end.
+
+
+gen_decode_user(Erules,D) when record(D,typedef) ->
+ Typename = [D#typedef.name],
+ Def = D#typedef.typespec,
+ InnerType = asn1ct_gen:get_inner(Def#type.def),
+ BytesVar = "Tlv",
+ case asn1ct_gen:type(InnerType) of
+ 'ASN1_OPEN_TYPE' ->
+ asn1ct_name:new(len),
+ gen_dec_prim(ber, Def#type{def='ASN1_OPEN_TYPE'},
+ BytesVar,{string,"TagIn"}, [] ,
+ ?PRIMITIVE,"OptOrMand"),
+ emit({".",nl,nl});
+ {primitive,bif} ->
+ asn1ct_name:new(len),
+ gen_dec_prim(ber, Def, BytesVar,{string,"TagIn"},[] ,
+ ?PRIMITIVE,"OptOrMand"),
+ emit([".",nl,nl]);
+ {constructed,bif} ->
+ asn1ct:update_namelist(D#typedef.name),
+ asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,D);
+ TheType ->
+ DecFunName = mkfuncname(TheType,dec),
+ emit([DecFunName,"(",BytesVar,
+ ", TagIn)"]),
+ emit([".",nl,nl])
+ end.
+
+
+gen_dec_prim(_Erules,Att,BytesVar,DoTag,_TagIn,_Form,_OptOrMand) ->
+ Typename = Att#type.def,
+%% Currently not used for BER replaced with [] as place holder
+%% Constraint = Att#type.constraint,
+%% Constraint = [],
+ Constraint =
+ case get_constraint(Att#type.constraint,'SizeConstraint') of
+ no -> [];
+ Tc -> Tc
+ end,
+ ValueRange =
+ case get_constraint(Att#type.constraint,'ValueRange') of
+ no -> [];
+ Tv -> Tv
+ end,
+ SingleValue =
+ case get_constraint(Att#type.constraint,'SingleValue') of
+ no -> [];
+ Sv -> Sv
+ end,
+ AsBin = case get(binary_strings) of
+ true -> "_as_bin";
+ _ -> ""
+ end,
+ NewTypeName = case Typename of
+ 'ANY' -> 'ASN1_OPEN_TYPE';
+ _ -> Typename
+ end,
+% DoLength =
+ case NewTypeName of
+ 'BOOLEAN'->
+ emit({"?RT_BER:decode_boolean(",BytesVar,","}),
+ add_func({decode_boolean,2});
+ 'INTEGER' ->
+ emit({"?RT_BER:decode_integer(",BytesVar,",",
+ {asis,int_constr(SingleValue,ValueRange)},","}),
+ add_func({decode_integer,3});
+ {'INTEGER',NamedNumberList} ->
+ emit({"?RT_BER:decode_integer(",BytesVar,",",
+ {asis,int_constr(SingleValue,ValueRange)},",",
+ {asis,NamedNumberList},","}),
+ add_func({decode_integer,4});
+ {'ENUMERATED',NamedNumberList} ->
+ emit({"?RT_BER:decode_enumerated(",BytesVar,",",
+ {asis,Constraint},",",
+ {asis,NamedNumberList},","}),
+ add_func({decode_enumerated,4});
+ {'BIT STRING',NamedNumberList} ->
+ case get(compact_bit_string) of
+ true ->
+ emit({"?RT_BER:decode_compact_bit_string(",
+ BytesVar,",",{asis,Constraint},",",
+ {asis,NamedNumberList},","}),
+ add_func({decode_compact_bit_string,4});
+ _ ->
+ emit({"?RT_BER:decode_bit_string(",BytesVar,",",
+ {asis,Constraint},",",
+ {asis,NamedNumberList},","}),
+ add_func({decode_bit_string,4})
+ end;
+ 'NULL' ->
+ emit({"?RT_BER:decode_null(",BytesVar,","}),
+ add_func({decode_null,2});
+ 'OBJECT IDENTIFIER' ->
+ emit({"?RT_BER:decode_object_identifier(",BytesVar,","}),
+ add_func({decode_object_identifier,2});
+ 'ObjectDescriptor' ->
+ emit({"?RT_BER:decode_restricted_string(",
+ BytesVar,",",{asis,Constraint},",",{asis,?T_ObjectDescriptor},","}),
+ add_func({decode_restricted_string,4});
+ 'OCTET STRING' ->
+ emit({"?RT_BER:decode_octet_string",AsBin,"(",BytesVar,",",{asis,Constraint},","}),
+ add_func({decode_octet_string,3});
+ 'NumericString' ->
+ emit({"?RT_BER:decode_restricted_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},",",{asis,?T_NumericString},","}),
+ add_func({decode_restricted_string,4});
+ 'TeletexString' ->
+ emit({"?RT_BER:decode_restricted_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},",",{asis,?T_TeletexString},","}),
+ add_func({decode_restricted_string,4});
+ 'VideotexString' ->
+ emit({"?RT_BER:decode_restricted_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},",",{asis,?T_VideotexString},","}),
+ add_func({decode_restricted_string,4});
+ 'GraphicString' ->
+ emit({"?RT_BER:decode_restricted_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},",",{asis,?T_GraphicString},","}),
+ add_func({decode_restricted_string,4});
+ 'VisibleString' ->
+ emit({"?RT_BER:decode_restricted_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},",",{asis,?T_VisibleString},","}),
+ add_func({decode_restricted_string,4});
+ 'GeneralString' ->
+ emit({"?RT_BER:decode_restricted_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},",",{asis,?T_GeneralString},","}),
+ add_func({decode_restricted_string,4});
+ 'PrintableString' ->
+ emit({"?RT_BER:decode_restricted_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},",",{asis,?T_PrintableString},","}),
+ add_func({decode_restricted_string,4});
+ 'IA5String' ->
+ emit({"?RT_BER:decode_restricted_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},",",{asis,?T_IA5String},","}),
+ add_func({decode_restricted_string,4}) ;
+ 'UniversalString' ->
+ emit({"?RT_BER:decode_universal_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},","}),
+ add_func({decode_universal_string,3});
+ 'BMPString' ->
+ emit({"?RT_BER:decode_BMP_string",AsBin,"(",
+ BytesVar,",",{asis,Constraint},","}),
+ add_func({decode_BMP_string,3});
+ 'UTCTime' ->
+ emit({"?RT_BER:decode_utc_time",AsBin,"(",
+ BytesVar,",",{asis,Constraint},","}),
+ add_func({decode_utc_time,3});
+ 'GeneralizedTime' ->
+ emit({"?RT_BER:decode_generalized_time",AsBin,"(",
+ BytesVar,",",{asis,Constraint},","}),
+ add_func({decode_generalized_time,3});
+ 'ASN1_OPEN_TYPE' ->
+ emit(["?RT_BER:decode_open_type_as_binary(",
+ BytesVar,","]),
+ add_func({decode_open_type_as_binary,2});
+ Other ->
+ exit({'can not decode' ,Other})
+ end,
+
+ case {DoTag,NewTypeName} of
+ {{string,TagStr},'ASN1_OPEN_TYPE'} ->
+ emit([TagStr,")"]);
+ {_,'ASN1_OPEN_TYPE'} ->
+ emit([{asis,DoTag},")"]);
+ {{string,TagStr},_} ->
+ emit([TagStr,")"]);
+ _ when list(DoTag) ->
+ emit([{asis,DoTag},")"])
+ end.
+
+
+int_constr([],[]) ->
+ [];
+int_constr([],ValueRange) ->
+ ValueRange;
+int_constr(SingleValue,[]) ->
+ SingleValue;
+int_constr(SV,VR) ->
+ [SV,VR].
+
+%% Object code generating for encoding and decoding
+%% ------------------------------------------------
+
+gen_obj_code(Erules,_Module,Obj) when record(Obj,typedef) ->
+ ObjName = Obj#typedef.name,
+ Def = Obj#typedef.typespec,
+ #'Externaltypereference'{module=M,type=ClName} = Def#'Object'.classname,
+ Class = asn1_db:dbget(M,ClName),
+ {object,_,Fields} = Def#'Object'.def,
+ emit({nl,nl,nl,"%%================================"}),
+ emit({nl,"%% ",ObjName}),
+ emit({nl,"%%================================",nl}),
+ EncConstructed =
+ gen_encode_objectfields(ClName,get_class_fields(Class),
+ ObjName,Fields,[]),
+ emit(nl),
+ gen_encode_constr_type(Erules,EncConstructed),
+ emit(nl),
+ DecConstructed =
+ gen_decode_objectfields(ClName,get_class_fields(Class),
+ ObjName,Fields,[]),
+ emit(nl),
+ gen_decode_constr_type(Erules,DecConstructed),
+ emit_tlv_format_function();
+gen_obj_code(_Erules,_Module,Obj) when record(Obj,pobjectdef) ->
+ ok.
+
+gen_encode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
+ ObjName,ObjectFields,ConstrAcc) ->
+ EmitFuncClause =
+ fun(Arg) ->
+ emit(["'enc_",ObjName,"'(",{asis,Name},
+ ", ",Arg,", _RestPrimFieldName) ->",nl])
+ end,
+% emit(["'enc_",ObjName,"'(",{asis,Name},
+% ", Val, RestPrimFieldName) ->",nl]),
+ MaybeConstr=
+ case {get_object_field(Name,ObjectFields),OptOrMand} of
+ {false,'MANDATORY'} -> %% this case is illegal
+ exit({error,{asn1,{"missing mandatory field in object",
+ ObjName}}});
+ {false,'OPTIONAL'} ->
+ EmitFuncClause("_"),
+ emit([" {<<>>,0}"]),
+ [];
+ {false,{'DEFAULT',DefaultType}} ->
+ EmitFuncClause("Val"),
+ gen_encode_default_call(ClassName,Name,DefaultType);
+ {{Name,TypeSpec},_} ->
+ %% A specified field owerwrites any 'DEFAULT' or
+ %% 'OPTIONAL' field in the class
+ EmitFuncClause("Val"),
+ gen_encode_field_call(ObjName,Name,TypeSpec)
+ end,
+ case more_genfields(Rest) of
+ true ->
+ emit([";",nl]);
+ false ->
+ emit([".",nl])
+ end,
+ gen_encode_objectfields(ClassName,Rest,ObjName,ObjectFields,
+ MaybeConstr++ConstrAcc);
+gen_encode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
+ ObjName,ObjectFields,ConstrAcc) ->
+ EmitFuncClause =
+ fun(Args) ->
+ emit(["'enc_",ObjName,"'(",{asis,Name},
+ ", ",Args,") ->",nl])
+ end,
+% emit(["'enc_",ObjName,"'(",{asis,Name},
+% ", Val,[H|T]) ->",nl]),
+ case {get_object_field(Name,ObjectFields),OptOrMand} of
+ {false,'MANDATORY'} ->
+ exit({error,{asn1,{"missing mandatory field in object",
+ ObjName}}});
+ {false,'OPTIONAL'} ->
+ EmitFuncClause("_,_"),
+ emit([" exit({error,{'use of missing field in object', ",Name,
+ "}})"]);
+ {false,{'DEFAULT',_DefaultObject}} ->
+ exit({error,{asn1,{"not implemented yet",Name}}});
+ {{Name,TypeSpec},_} ->
+ EmitFuncClause(" Val, [H|T]"),
+ case TypeSpec#typedef.name of
+ {ExtMod,TypeName} ->
+ emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
+ "'(H, Val, T)"});
+ TypeName ->
+ emit({indent(3),"'enc_",TypeName,"'(H, Val, T)"})
+ end
+ end,
+ case more_genfields(Rest) of
+ true ->
+ emit([";",nl]);
+ false ->
+ emit([".",nl])
+ end,
+ gen_encode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
+
+% gen_encode_objectfields(Class,ObjName,[{FieldName,Type}|Rest],ConstrAcc) ->
+% Fields = Class#objectclass.fields,
+% MaybeConstr=
+% case is_typefield(Fields,FieldName) of
+% true ->
+% Def = Type#typedef.typespec,
+% emit({"'enc_",ObjName,"'(",{asis,FieldName},
+% ", Val, RestPrimFieldName) ->",nl}),
+% CAcc=
+% case Type#typedef.name of
+% {primitive,bif} -> %%tag should be the primitive tag
+% OTag = Def#type.tag,
+% Tag = [encode_tag_val(decode_class(X#tag.class),
+% X#tag.form,X#tag.number)||
+% X <- OTag],
+% gen_encode_prim(ber,Def,{asis,lists:reverse(Tag)},
+% "Val"),
+% [];
+% {constructed,bif} ->
+% emit({" 'enc_",ObjName,'_',FieldName,
+% "'(Val)"}),
+% [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
+% {ExtMod,TypeName} ->
+% emit({" '",ExtMod,"':'enc_",TypeName,
+% "'(Val)"}),
+% [];
+% TypeName ->
+% emit({" 'enc_",TypeName,"'(Val)"}),
+% []
+% end,
+% case more_genfields(Fields,Rest) of
+% true ->
+% emit({";",nl});
+% false ->
+% emit({".",nl})
+% end,
+% CAcc;
+% {false,objectfield} ->
+% emit({"'enc_",ObjName,"'(",{asis,FieldName},
+% ", Val,[H|T]) ->",nl}),
+% case Type#typedef.name of
+% {ExtMod,TypeName} ->
+% emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
+% "'(H, Val, T)"});
+% TypeName ->
+% emit({indent(3),"'enc_",TypeName,"'(H, Val, T)"})
+% end,
+% case more_genfields(Fields,Rest) of
+% true ->
+% emit({";",nl});
+% false ->
+% emit({".",nl})
+% end,
+% [];
+% {false,_} -> []
+% end,
+% gen_encode_objectfields(Class,ObjName,Rest,MaybeConstr ++ ConstrAcc);
+gen_encode_objectfields(ClassName,[_C|Cs],O,OF,Acc) ->
+ gen_encode_objectfields(ClassName,Cs,O,OF,Acc);
+gen_encode_objectfields(_,[],_,_,Acc) ->
+ Acc.
+
+% gen_encode_constr_type(Erules,[{Name,Def}|Rest]) ->
+% emit({Name,"(Val,TagIn) ->",nl}),
+% InnerType = asn1ct_gen:get_inner(Def#type.def),
+% asn1ct_gen:gen_encode_constructed(Erules,Name,InnerType,Def),
+% gen_encode_constr_type(Erules,Rest);
+gen_encode_constr_type(Erules,[TypeDef|Rest]) when record(TypeDef,typedef) ->
+ case is_already_generated(enc,TypeDef#typedef.name) of
+ true -> ok;
+ _ -> gen_encode_user(Erules,TypeDef)
+ end,
+ gen_encode_constr_type(Erules,Rest);
+gen_encode_constr_type(_,[]) ->
+ ok.
+
+gen_encode_field_call(ObjName,FieldName,Type) ->
+ Def = Type#typedef.typespec,
+ OTag = Def#type.tag,
+ Tag = [encode_tag_val(decode_class(X#tag.class),
+ X#tag.form,X#tag.number)||
+ X <- OTag],
+ case Type#typedef.name of
+ {primitive,bif} -> %%tag should be the primitive tag
+% OTag = Def#type.tag,
+% Tag = [encode_tag_val(decode_class(X#tag.class),
+% X#tag.form,X#tag.number)||
+% X <- OTag],
+ gen_encode_prim(ber,Def,{asis,lists:reverse(Tag)},
+ "Val"),
+ [];
+ {constructed,bif} ->
+ emit({" 'enc_",ObjName,'_',FieldName,
+ "'(Val,",{asis,Tag},")"}),
+ [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
+ {ExtMod,TypeName} ->
+ emit({" '",ExtMod,"':'enc_",TypeName,
+ "'(Val,",{asis,Tag},")"}),
+ [];
+ TypeName ->
+ emit({" 'enc_",TypeName,"'(Val,",{asis,Tag},")"}),
+ []
+ end.
+
+gen_encode_default_call(ClassName,FieldName,Type) ->
+ CurrentMod = get(currmod),
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ OTag = Type#type.tag,
+ Tag = [encode_tag_val(decode_class(X#tag.class),X#tag.form,X#tag.number)|| X <- OTag],
+ case asn1ct_gen:type(InnerType) of
+ {constructed,bif} ->
+%% asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
+ emit([" 'enc_",ClassName,'_',FieldName,"'(Bytes)"]),
+ [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
+ typespec=Type}];
+ {primitive,bif} ->
+ gen_encode_prim(ber,Type,{asis,lists:reverse(Tag)},"Val"),
+ [];
+ #'Externaltypereference'{module=CurrentMod,type=Etype} ->
+ emit([" 'enc_",Etype,"'(Val, ",{asis,Tag},")",nl]),
+ [];
+ #'Externaltypereference'{module=Emod,type=Etype} ->
+ emit([" '",Emod,"':'enc_",Etype,"'(Val, ",{asis,Tag},")",nl]),
+ []
+% 'ASN1_OPEN_TYPE' ->
+% emit(["%% OPEN TYPE",nl]),
+% gen_encode_prim(ber,
+% Type#type{def='ASN1_OPEN_TYPE'},
+% "TagIn","Val"),
+% emit([".",nl])
+ end.
+
+%%%%%%%%%%%%%%%%
+
+gen_decode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
+ ObjName,ObjectFields,ConstrAcc) ->
+ EmitFuncClause =
+ fun(Arg) ->
+ emit(["'dec_",ObjName,"'(",{asis,Name},
+ ", ",Arg,",_) ->",nl])
+ end,
+% emit(["'dec_",ObjName,"'(",{asis,Name},
+% ", Bytes, RestPrimFieldName) ->",nl]),
+ MaybeConstr=
+ case {get_object_field(Name,ObjectFields),OptOrMand} of
+ {false,'MANDATORY'} -> %% this case is illegal
+ exit({error,{asn1,{"missing mandatory field in object",
+ ObjName}}});
+ {false,'OPTIONAL'} ->
+ EmitFuncClause(" _"),
+ emit([" asn1_NOVALUE"]),
+ [];
+ {false,{'DEFAULT',DefaultType}} ->
+ EmitFuncClause("Bytes"),
+ emit_tlv_format("Bytes"),
+ gen_decode_default_call(ClassName,Name,"Tlv",DefaultType);
+ {{Name,TypeSpec},_} ->
+ %% A specified field owerwrites any 'DEFAULT' or
+ %% 'OPTIONAL' field in the class
+ EmitFuncClause("Bytes"),
+ emit_tlv_format("Bytes"),
+ gen_decode_field_call(ObjName,Name,"Tlv",TypeSpec)
+ end,
+ case more_genfields(Rest) of
+ true ->
+ emit([";",nl]);
+ false ->
+ emit([".",nl])
+ end,
+ gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,MaybeConstr++ConstrAcc);
+gen_decode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
+ ObjName,ObjectFields,ConstrAcc) ->
+ EmitFuncClause =
+ fun(Args) ->
+ emit(["'dec_",ObjName,"'(",{asis,Name},
+ ", ",Args,") ->",nl])
+ end,
+% emit(["'dec_",ObjName,"'(",{asis,Name},
+% ", Bytes,[H|T]) ->",nl]),
+% emit_tlv_format("Bytes"),
+ case {get_object_field(Name,ObjectFields),OptOrMand} of
+ {false,'MANDATORY'} ->
+ exit({error,{asn1,{"missing mandatory field in object",
+ ObjName}}});
+ {false,'OPTIONAL'} ->
+ EmitFuncClause("_,_"),
+ emit([" exit({error,{'illegal use of missing field in object', ",Name,
+ "}})"]);
+ {false,{'DEFAULT',_DefaultObject}} ->
+ exit({error,{asn1,{"not implemented yet",Name}}});
+ {{Name,TypeSpec},_} ->
+ EmitFuncClause("Bytes,[H|T]"),
+% emit_tlv_format("Bytes"),
+ case TypeSpec#typedef.name of
+ {ExtMod,TypeName} ->
+ emit({indent(3),"'",ExtMod,"':'dec_",TypeName,
+ "'(H, Bytes, T)"});
+ TypeName ->
+ emit({indent(3),"'dec_",TypeName,"'(H, Bytes, T)"})
+ end
+ end,
+ case more_genfields(Rest) of
+ true ->
+ emit([";",nl]);
+ false ->
+ emit([".",nl])
+ end,
+ gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
+gen_decode_objectfields(CN,[_C|Cs],O,OF,CAcc) ->
+ gen_decode_objectfields(CN,Cs,O,OF,CAcc);
+gen_decode_objectfields(_,[],_,_,CAcc) ->
+ CAcc.
+
+emit_tlv_format(Bytes) ->
+ notice_tlv_format_gen(), % notice for generating of tlv_format/1
+ emit([" Tlv = tlv_format(",Bytes,"),",nl]).
+
+notice_tlv_format_gen() ->
+ Module = get(currmod),
+% io:format("Noticed: ~p~n",[Module]),
+ case get(tlv_format) of
+ {done,Module} ->
+ ok;
+ _ -> % true or undefined
+ put(tlv_format,true)
+ end.
+
+emit_tlv_format_function() ->
+ Module = get(currmod),
+% io:format("Tlv formated: ~p",[Module]),
+ case get(tlv_format) of
+ true ->
+% io:format(" YES!~n"),
+ emit_tlv_format_function1(),
+ put(tlv_format,{done,Module});
+ _ ->
+% io:format(" NO!~n"),
+ ok
+ end.
+emit_tlv_format_function1() ->
+ emit(["tlv_format(Bytes) when binary(Bytes) ->",nl,
+ " {Tlv,_}=?RT_BER:decode(Bytes),",nl,
+ " Tlv;",nl,
+ "tlv_format(Bytes) ->",nl,
+ " Bytes.",nl]).
+
+
+gen_decode_constr_type(Erules,[{Name,Def}|Rest]) ->
+ emit([Name,"(Tlv, TagIn) ->",nl]),
+ InnerType = asn1ct_gen:get_inner(Def#type.def),
+ asn1ct_gen:gen_decode_constructed(Erules,Name,InnerType,Def),
+ gen_decode_constr_type(Erules,Rest);
+gen_decode_constr_type(Erules,[TypeDef|Rest]) when record(TypeDef,typedef) ->
+ case is_already_generated(dec,TypeDef#typedef.name) of
+ true -> ok;
+ _ ->
+ gen_decode(Erules,TypeDef)
+ end,
+ gen_decode_constr_type(Erules,Rest);
+gen_decode_constr_type(_,[]) ->
+ ok.
+
+%%%%%%%%%%%
+gen_decode_field_call(ObjName,FieldName,Bytes,Type) ->
+ Def = Type#typedef.typespec,
+ OTag = Def#type.tag,
+ Tag = [(decode_class(X#tag.class) bsl 10) + X#tag.number ||
+ X <- OTag],
+ case Type#typedef.name of
+ {primitive,bif} -> %%tag should be the primitive tag
+ gen_dec_prim(ber,Def,Bytes,Tag,"TagIn",?PRIMITIVE,
+ opt_or_default),
+ [];
+ {constructed,bif} ->
+ emit({" 'dec_",ObjName,'_',FieldName,
+ "'(",Bytes,",",{asis,Tag},")"}),
+ [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
+ {ExtMod,TypeName} ->
+ emit({" '",ExtMod,"':'dec_",TypeName,
+ "'(",Bytes,",",{asis,Tag},")"}),
+ [];
+ TypeName ->
+ emit({" 'dec_",TypeName,"'(",Bytes,",",{asis,Tag},")"}),
+ []
+ end.
+
+gen_decode_default_call(ClassName,FieldName,Bytes,Type) ->
+ CurrentMod = get(currmod),
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ OTag = Type#type.tag,
+ Tag = [(decode_class(X#tag.class) bsl 10) + X#tag.number || X <- OTag],
+ case asn1ct_gen:type(InnerType) of
+ {constructed,bif} ->
+ emit([" 'dec_",ClassName,'_',FieldName,"'(",Bytes,",",
+ {asis,Tag},")"]),
+ [#typedef{name=list_to_atom(lists:concat([ClassName,'_',
+ FieldName])),
+ typespec=Type}];
+ {primitive,bif} ->
+ gen_dec_prim(ber,Type,Bytes,Tag,"TagIn",
+ ?PRIMITIVE,opt_or_default),
+ [];
+ #'Externaltypereference'{module=CurrentMod,type=Etype} ->
+ emit([" 'dec_",Etype,"'(",Bytes, " ,",{asis,Tag},")",nl]),
+ [];
+ #'Externaltypereference'{module=Emod,type=Etype} ->
+ emit([" '",Emod,"':'dec_",Etype,"'(",Bytes,", ",
+ {asis,Tag},")",nl]),
+ []
+% 'ASN1_OPEN_TYPE' ->
+% emit(["%% OPEN TYPE",nl]),
+% gen_encode_prim(ber,
+% Type#type{def='ASN1_OPEN_TYPE'},
+% "TagIn","Val"),
+% emit([".",nl])
+ end.
+%%%%%%%%%%%
+
+is_already_generated(Operation,Name) ->
+ case get(class_default_type) of
+ undefined ->
+ put(class_default_type,[{Operation,Name}]),
+ false;
+ GeneratedList ->
+ case lists:member({Operation,Name},GeneratedList) of
+ true ->
+ true;
+ false ->
+ put(class_default_type,[{Operation,Name}|GeneratedList]),
+ false
+ end
+ end.
+
+more_genfields([]) ->
+ false;
+more_genfields([Field|Fields]) ->
+ case element(1,Field) of
+ typefield ->
+ true;
+ objectfield ->
+ true;
+ _ ->
+ more_genfields(Fields)
+ end.
+
+
+
+
+%% Object Set code generating for encoding and decoding
+%% ----------------------------------------------------
+gen_objectset_code(Erules,ObjSet) ->
+ ObjSetName = ObjSet#typedef.name,
+ Def = ObjSet#typedef.typespec,
+% {ClassName,ClassDef} = Def#'ObjectSet'.class,
+ #'Externaltypereference'{module=ClassModule,
+ type=ClassName} = Def#'ObjectSet'.class,
+ ClassDef = asn1_db:dbget(ClassModule,ClassName),
+ UniqueFName = Def#'ObjectSet'.uniquefname,
+ Set = Def#'ObjectSet'.set,
+ emit({nl,nl,nl,"%%================================"}),
+ emit({nl,"%% ",ObjSetName}),
+ emit({nl,"%%================================",nl}),
+ case ClassName of
+ {_Module,ExtClassName} ->
+ gen_objset_code(Erules,ObjSetName,UniqueFName,Set,ExtClassName,ClassDef);
+ _ ->
+ gen_objset_code(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassDef)
+ end,
+ emit(nl).
+
+gen_objset_code(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassDef)->
+ ClassFields = get_class_fields(ClassDef),
+ InternalFuncs=gen_objset_enc(Erules,ObjSetName,UniqueFName,Set,
+ ClassName,ClassFields,1,[]),
+ gen_objset_dec(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassFields,1),
+ gen_internal_funcs(Erules,InternalFuncs).
+
+%% gen_objset_enc iterates over the objects of the object set
+gen_objset_enc(_,_,{unique,undefined},_,_,_,_,_) ->
+ %% There is no unique field in the class of this object set
+ %% don't bother about the constraint
+ [];
+gen_objset_enc(Erules,ObjSName,UniqueName,
+ [{ObjName,Val,Fields},T|Rest],ClName,ClFields,
+ NthObj,Acc)->
+ emit({"'getenc_",ObjSName,"'(",{asis,UniqueName},",",{asis,Val},
+ ") ->",nl}),
+ {InternalFunc,NewNthObj}=
+ case ObjName of
+ no_name ->
+ gen_inlined_enc_funs(Fields,ClFields,ObjSName,NthObj);
+ _ ->
+ emit({" fun 'enc_",ObjName,"'/3"}),
+ {[],NthObj}
+ end,
+ emit({";",nl}),
+ gen_objset_enc(Erules,ObjSName,UniqueName,[T|Rest],ClName,ClFields,
+ NewNthObj,InternalFunc ++ Acc);
+gen_objset_enc(_,ObjSetName,UniqueName,
+ [{ObjName,Val,Fields}],_ClName,ClFields,NthObj,Acc) ->
+ emit({"'getenc_",ObjSetName,"'(",{asis,UniqueName},",",
+ {asis,Val},") ->",nl}),
+ {InternalFunc,_} =
+ case ObjName of
+ no_name ->
+ gen_inlined_enc_funs(Fields,ClFields,ObjSetName,NthObj);
+ _ ->
+ emit({" fun 'enc_",ObjName,"'/3"}),
+ {[],NthObj}
+ end,
+ emit({".",nl,nl}),
+ InternalFunc ++ Acc;
+%% See X.681 Annex E for the following case
+gen_objset_enc(_,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
+ _ClFields,_NthObj,Acc) ->
+ emit({"'getenc_",ObjSetName,"'(_, _) ->",nl}),
+ emit({indent(3),"fun(_, Val, _RestPrimFieldName) ->",nl}),
+ emit({indent(6),"Len = case Val of",nl,indent(9),
+ "Bin when binary(Bin) -> size(Bin);",nl,indent(9),
+ "_ -> length(Val)",nl,indent(6),"end,"}),
+ emit({indent(6),"{Val,Len}",nl}),
+ emit({indent(3),"end.",nl,nl}),
+ Acc;
+gen_objset_enc(_,_,_,[],_,_,_,Acc) ->
+ Acc.
+
+%% gen_inlined_enc_funs for each object iterates over all fields of a
+%% class, and for each typefield it checks if the object has that
+%% field and emits the proper code.
+gen_inlined_enc_funs(Fields,[{typefield,Name,_}|Rest],
+ ObjSetName,NthObj) ->
+ InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
+ case lists:keysearch(Name,1,Fields) of
+ {value,{_,Type}} when record(Type,type) ->
+ emit({indent(3),"fun(Type, Val, _RestPrimFieldName) ->",nl,
+ indent(6),"case Type of",nl}),
+ {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
+ gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
+ {value,{_,Type}} when record(Type,typedef) ->
+ emit({indent(3),"fun(Type, Val, _RestPrimFieldName) ->",nl,
+ indent(6),"case Type of",nl}),
+ emit({indent(9),{asis,Name}," ->",nl}),
+ {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
+ gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
+ false ->
+ gen_inlined_enc_funs(Fields,Rest,ObjSetName,NthObj)
+ end;
+gen_inlined_enc_funs(Fields,[_|Rest],ObjSetName,NthObj) ->
+ gen_inlined_enc_funs(Fields,Rest,ObjSetName,NthObj);
+gen_inlined_enc_funs(_,[],_,NthObj) ->
+ {[],NthObj}.
+
+gen_inlined_enc_funs1(Fields,[{typefield,Name,_}|Rest],ObjSetName,
+ NthObj,Acc) ->
+ InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
+ {Acc2,NAdd}=
+ case lists:keysearch(Name,1,Fields) of
+ {value,{_,Type}} when record(Type,type) ->
+ emit({";",nl}),
+ {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
+ {Ret++Acc,N};
+ {value,{_,Type}} when record(Type,typedef) ->
+ emit({";",nl,indent(9),{asis,Name}," ->",nl}),
+ {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
+ {Ret++Acc,N};
+ false ->
+ {Acc,0}
+ end,
+ gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+NAdd,Acc2);
+gen_inlined_enc_funs1(Fields,[_|Rest],ObjSetName,NthObj,Acc)->
+ gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj,Acc);
+gen_inlined_enc_funs1(_,[],_,NthObj,Acc) ->
+ emit({nl,indent(6),"end",nl}),
+ emit({indent(3),"end"}),
+ {Acc,NthObj}.
+
+emit_inner_of_fun(TDef=#typedef{name={ExtMod,Name},typespec=Type},
+ InternalDefFunName) ->
+ OTag = Type#type.tag,
+ Tag = [encode_tag_val(decode_class(X#tag.class),X#tag.form,X#tag.number)|| X <- OTag],
+% remove Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
+ case {ExtMod,Name} of
+ {primitive,bif} ->
+ emit(indent(12)),
+ gen_encode_prim(ber,Type,[{asis,lists:reverse(Tag)}],"Val"),
+ {[],0};
+ {constructed,bif} ->
+ emit([indent(12),"'enc_",
+ InternalDefFunName,"'(Val)"]),
+ {[TDef#typedef{name=InternalDefFunName}],1};
+ _ ->
+ emit({indent(12),"'",ExtMod,"':'enc_",Name,"'(Val)"}),
+ {[],0}
+ end;
+emit_inner_of_fun(#typedef{name=Name},_) ->
+% OTag = Type#type.tag,
+% remove Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
+% Tag = [encode_tag_val(decode_class(X#tag.class),X#tag.form,X#tag.number)|| X <- OTag],
+ emit({indent(12),"'enc_",Name,"'(Val)"}),
+ {[],0};
+emit_inner_of_fun(Type,_) when record(Type,type) ->
+ CurrMod = get(currmod),
+% OTag = Type#type.tag,
+% remove Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
+% Tag = [encode_tag_val(decode_class(X#tag.class),X#tag.form,X#tag.number)|| X <- OTag],
+ case Type#type.def of
+ Def when atom(Def) ->
+ OTag = Type#type.tag,
+ Tag = [encode_tag_val(decode_class(X#tag.class),
+ X#tag.form,X#tag.number)||X <- OTag],
+ emit([indent(9),Def," ->",nl,indent(12)]),
+ gen_encode_prim(ber,Type,{asis,lists:reverse(Tag)},"Val");
+ TRef when record(TRef,typereference) ->
+ T = TRef#typereference.val,
+ emit([indent(9),T," ->",nl,indent(12),"'enc_",T,
+ "'(Val)"]);
+ #'Externaltypereference'{module=CurrMod,type=T} ->
+ emit([indent(9),T," ->",nl,indent(12),"'enc_",T,
+ "'(Val)"]);
+ #'Externaltypereference'{module=ExtMod,type=T} ->
+ emit([indent(9),T," ->",nl,indent(12),ExtMod,":'enc_",
+ T,"'(Val)"])
+ end,
+ {[],0}.
+
+indent(N) ->
+ lists:duplicate(N,32). % 32 = space
+
+
+gen_objset_dec(_,_,{unique,undefined},_,_,_,_) ->
+ %% There is no unique field in the class of this object set
+ %% don't bother about the constraint
+ ok;
+gen_objset_dec(Erules,ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],
+ ClName,ClFields,NthObj)->
+ emit(["'getdec_",ObjSName,"'(",{asis,UniqueName},",",
+ {asis,Val},") ->",nl]),
+ NewNthObj=
+ case ObjName of
+ no_name ->
+ gen_inlined_dec_funs(Fields,ClFields,ObjSName,NthObj);
+ _ ->
+ emit([" fun 'dec_",ObjName,"'/3"]),
+ NthObj
+ end,
+ emit([";",nl]),
+ gen_objset_dec(Erules,ObjSName,UniqueName,[T|Rest],ClName,
+ ClFields,NewNthObj);
+gen_objset_dec(_,ObjSetName,UniqueName,[{ObjName,Val,Fields}],
+ _ClName,ClFields,NthObj) ->
+ emit(["'getdec_",ObjSetName,"'(",{asis,UniqueName},",",
+ {asis,Val},") ->",nl]),
+ case ObjName of
+ no_name ->
+ gen_inlined_dec_funs(Fields,ClFields,ObjSetName,NthObj);
+ _ ->
+ emit([" fun 'dec_",ObjName,"'/3"])
+ end,
+ emit([".",nl,nl]),
+ ok;
+gen_objset_dec(Erules,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
+ _ClFields,_NthObj) ->
+ emit(["'getdec_",ObjSetName,"'(_, _) ->",nl]),
+ emit([indent(2),"fun(_,Bytes, _RestPrimFieldName) ->",nl]),
+ case Erules of
+ ber_bin_v2 ->
+ emit([indent(4),"case Bytes of",nl,
+ indent(6),"Bin when binary(Bin) -> ",nl,
+ indent(8),"Bin;",nl,
+ indent(6),"_ ->",nl,
+ indent(8),"?RT_BER:encode(Bytes)",nl,
+ indent(4),"end",nl]);
+ _ ->
+ emit([indent(6),"Len = case Bytes of",nl,indent(9),
+ "Bin when binary(Bin) -> size(Bin);",nl,indent(9),
+ "_ -> length(Bytes)",nl,indent(6),"end,"]),
+ emit([indent(4),"{Bytes,[],Len}",nl])
+ end,
+ emit([indent(2),"end.",nl,nl]),
+ ok;
+gen_objset_dec(_,_,_,[],_,_,_) ->
+ ok.
+
+gen_inlined_dec_funs(Fields,[{typefield,Name,Prop}|Rest],
+ ObjSetName,NthObj) ->
+ DecProp = case Prop of
+ 'OPTIONAL' -> opt_or_default;
+ {'DEFAULT',_} -> opt_or_default;
+ _ -> mandatory
+ end,
+ InternalDefFunName = [NthObj,Name,ObjSetName],
+ case lists:keysearch(Name,1,Fields) of
+ {value,{_,Type}} when record(Type,type) ->
+ emit([indent(3),"fun(Type, Bytes, _RestPrimFieldName) ->",
+ nl,indent(6),"case Type of",nl]),
+ N=emit_inner_of_decfun(Type,DecProp,InternalDefFunName),
+ gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
+ {value,{_,Type}} when record(Type,typedef) ->
+ emit([indent(3),"fun(Type, Bytes, _RestPrimFieldName) ->",
+ nl,indent(6),"case Type of",nl]),
+ emit([indent(9),{asis,Name}," ->",nl]),
+ N=emit_inner_of_decfun(Type,DecProp,InternalDefFunName),
+ gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
+ false ->
+ gen_inlined_dec_funs(Fields,Rest,ObjSetName,NthObj)
+ end;
+gen_inlined_dec_funs(Fields,[_H|Rest],ObjSetName,NthObj) ->
+ gen_inlined_dec_funs(Fields,Rest,ObjSetName,NthObj);
+gen_inlined_dec_funs(_,[],_,NthObj) ->
+ NthObj.
+
+gen_inlined_dec_funs1(Fields,[{typefield,Name,Prop}|Rest],
+ ObjSetName,NthObj) ->
+ DecProp = case Prop of
+ 'OPTIONAL' -> opt_or_default;
+ {'DEFAULT',_} -> opt_or_default;
+ _ -> mandatory
+ end,
+ InternalDefFunName = [NthObj,Name,ObjSetName],
+ N=
+ case lists:keysearch(Name,1,Fields) of
+ {value,{_,Type}} when record(Type,type) ->
+ emit([";",nl]),
+ emit_inner_of_decfun(Type,DecProp,InternalDefFunName);
+ {value,{_,Type}} when record(Type,typedef) ->
+ emit([";",nl,indent(9),{asis,Name}," ->",nl]),
+ emit_inner_of_decfun(Type,DecProp,InternalDefFunName);
+ false ->
+ 0
+ end,
+ gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
+gen_inlined_dec_funs1(Fields,[_|Rest],ObjSetName,NthObj)->
+ gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj);
+gen_inlined_dec_funs1(_,[],_,NthObj) ->
+ emit([nl,indent(6),"end",nl]),
+ emit([indent(3),"end"]),
+ NthObj.
+
+emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type},Prop,
+ InternalDefFunName) ->
+ OTag = Type#type.tag,
+%% Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
+ Tag = [(decode_class(X#tag.class) bsl 10) + X#tag.number || X <- OTag],
+ case {ExtName,Name} of
+ {primitive,bif} ->
+ emit(indent(12)),
+ gen_dec_prim(ber,Type,"Bytes",Tag,"TagIn",
+ ?PRIMITIVE,Prop),
+ 0;
+ {constructed,bif} ->
+ emit([indent(12),"'dec_",
+% asn1ct_gen:list2name(InternalDefFunName),"'(Bytes, ",Prop,
+% ", ",{asis,Tag},")"]),
+ asn1ct_gen:list2name(InternalDefFunName),"'(Bytes, ",
+ {asis,Tag},")"]),
+ 1;
+ _ ->
+ emit([indent(12),"'",ExtName,"':'dec_",Name,"'(Bytes)"]),
+ 0
+ end;
+emit_inner_of_decfun(#typedef{name=Name},_Prop,_) ->
+ emit([indent(12),"'dec_",Name,"'(Bytes)"]),
+ 0;
+emit_inner_of_decfun(Type,Prop,_) when record(Type,type) ->
+ OTag = Type#type.tag,
+%% Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
+ Tag = [(decode_class(X#tag.class) bsl 10) + X#tag.number || X <- OTag],
+ CurrMod = get(currmod),
+ Def = Type#type.def,
+ InnerType = asn1ct_gen:get_inner(Def),
+ WhatKind = asn1ct_gen:type(InnerType),
+ case WhatKind of
+ {primitive,bif} ->
+ emit([indent(9),Def," ->",nl,indent(12)]),
+ gen_dec_prim(ber,Type,"Bytes",Tag,"TagIn",
+ ?PRIMITIVE,Prop);
+ #'Externaltypereference'{module=CurrMod,type=T} ->
+ emit([indent(9),T," ->",nl,indent(12),"'dec_",T,
+% "'(Bytes, ",Prop,")"]);
+ "'(Bytes)"]);
+ #'Externaltypereference'{module=ExtMod,type=T} ->
+ emit([indent(9),T," ->",nl,indent(12),ExtMod,":'dec_",
+% T,"'(Bytes, ",Prop,")"])
+ T,"'(Bytes)"])
+ end,
+ 0.
+
+gen_internal_funcs(_,[]) ->
+ ok;
+gen_internal_funcs(Erules,[TypeDef|Rest]) ->
+ gen_encode_user(Erules,TypeDef),
+ emit([nl,nl,"'dec_",TypeDef#typedef.name,
+% "'(Tlv, OptOrMand, TagIn) ->",nl]),
+ "'(Tlv, TagIn) ->",nl]),
+ gen_decode_user(Erules,TypeDef),
+ gen_internal_funcs(Erules,Rest).
+
+
+dbdec(Type) ->
+ demit({"io:format(\"decoding: ",{asis,Type},"~w~n\",[Bytes]),",nl}).
+
+
+decode_class('UNIVERSAL') ->
+ ?UNIVERSAL;
+decode_class('APPLICATION') ->
+ ?APPLICATION;
+decode_class('CONTEXT') ->
+ ?CONTEXT;
+decode_class('PRIVATE') ->
+ ?PRIVATE.
+
+decode_type('BOOLEAN') -> 1;
+decode_type('INTEGER') -> 2;
+decode_type('BIT STRING') -> 3;
+decode_type('OCTET STRING') -> 4;
+decode_type('NULL') -> 5;
+decode_type('OBJECT IDENTIFIER') -> 6;
+decode_type('OBJECT DESCRIPTOR') -> 7;
+decode_type('EXTERNAL') -> 8;
+decode_type('REAL') -> 9;
+decode_type('ENUMERATED') -> 10;
+decode_type('EMBEDDED_PDV') -> 11;
+decode_type('SEQUENCE') -> 16;
+decode_type('SEQUENCE OF') -> 16;
+decode_type('SET') -> 17;
+decode_type('SET OF') -> 17;
+decode_type('NumericString') -> 18;
+decode_type('PrintableString') -> 19;
+decode_type('TeletexString') -> 20;
+decode_type('VideotexString') -> 21;
+decode_type('IA5String') -> 22;
+decode_type('UTCTime') -> 23;
+decode_type('GeneralizedTime') -> 24;
+decode_type('GraphicString') -> 25;
+decode_type('VisibleString') -> 26;
+decode_type('GeneralString') -> 27;
+decode_type('UniversalString') -> 28;
+decode_type('BMPString') -> 30;
+decode_type('CHOICE') -> 'CHOICE'; % choice gets the tag from the actual alternative
+decode_type(Else) -> exit({error,{asn1,{unrecognized_type,Else}}}).
+
+add_removed_bytes() ->
+ asn1ct_name:delete(rb),
+ add_removed_bytes(asn1ct_name:all(rb)).
+
+add_removed_bytes([H,T1|T]) ->
+ emit({{var,H},"+"}),
+ add_removed_bytes([T1|T]);
+add_removed_bytes([H|T]) ->
+ emit({{var,H}}),
+ add_removed_bytes(T);
+add_removed_bytes([]) ->
+ true.
+
+mkfuncname(WhatKind,DecOrEnc) ->
+ case WhatKind of
+ #'Externaltypereference'{module=Mod,type=EType} ->
+ CurrMod = get(currmod),
+ case CurrMod of
+ Mod ->
+ lists:concat(["'",DecOrEnc,"_",EType,"'"]);
+ _ ->
+% io:format("CurrMod: ~p, Mod: ~p~n",[CurrMod,Mod]),
+ lists:concat(["'",Mod,"':'",DecOrEnc,"_",EType,"'"])
+ end;
+ #'typereference'{val=EType} ->
+ lists:concat(["'",DecOrEnc,"_",EType,"'"]);
+ 'ASN1_OPEN_TYPE' ->
+ lists:concat(["'",DecOrEnc,"_",WhatKind,"'"])
+
+ end.
+
+optionals(L) -> optionals(L,[],1).
+
+optionals([{'EXTENSIONMARK',_,_}|Rest],Acc,Pos) ->
+ optionals(Rest,Acc,Pos); % optionals in extension are currently not handled
+optionals([#'ComponentType'{name=Name,prop='OPTIONAL'}|Rest],Acc,Pos) ->
+ optionals(Rest,[{Name,Pos}|Acc],Pos+1);
+optionals([#'ComponentType'{name=Name,prop={'DEFAULT',_}}|Rest],Acc,Pos) ->
+ optionals(Rest,[{Name,Pos}|Acc],Pos+1);
+optionals([#'ComponentType'{}|Rest],Acc,Pos) ->
+ optionals(Rest,Acc,Pos+1);
+optionals([],Acc,_) ->
+ lists:reverse(Acc).
+
+get_constraint(C,Key) ->
+ case lists:keysearch(Key,1,C) of
+ false ->
+ no;
+ {value,{_,V}} ->
+ V
+ end.
+
+
+get_class_fields(#classdef{typespec=ObjClass}) ->
+ ObjClass#objectclass.fields;
+get_class_fields(#objectclass{fields=Fields}) ->
+ Fields;
+get_class_fields(_) ->
+ [].
+
+get_object_field(Name,ObjectFields) ->
+ case lists:keysearch(Name,1,ObjectFields) of
+ {value,Field} -> Field;
+ false -> false
+ end.
+
+%%encode_tag(TagClass(?UNI, APP etc), Form (?PRIM etx), TagInteger) ->
+%% 8bit Int | binary
+encode_tag_val(Class, Form, TagNo) when (TagNo =< 30) ->
+ <<(Class bsr 6):2,(Form bsr 5):1,TagNo:5>>;
+
+encode_tag_val(Class, Form, TagNo) ->
+ {Octets,_Len} = mk_object_val(TagNo),
+ BinOct = list_to_binary(Octets),
+ <<(Class bsr 6):2, (Form bsr 5):1, 31:5,BinOct/binary>>.
+
+%%%%%%%%%%%
+%% mk_object_val(Value) -> {OctetList, Len}
+%% returns a Val as a list of octets, the 8 bit is allways set to one except
+%% for the last octet, where its 0
+%%
+
+
+mk_object_val(Val) when Val =< 127 ->
+ {[255 band Val], 1};
+mk_object_val(Val) ->
+ mk_object_val(Val bsr 7, [Val band 127], 1).
+mk_object_val(0, Ack, Len) ->
+ {Ack, Len};
+mk_object_val(Val, Ack, Len) ->
+ mk_object_val(Val bsr 7, [((Val band 127) bor 128) | Ack], Len + 1).
+
+add_func(F={_Func,_Arity}) ->
+ ets:insert(asn1_functab,{F}).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_per.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_per.erl
new file mode 100644
index 0000000000..b5c70fd856
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_per.erl
@@ -0,0 +1,1189 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1ct_gen_per.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
+%%
+-module(asn1ct_gen_per).
+
+%% Generate erlang module which handles (PER) encode and decode for
+%% all types in an ASN.1 module
+
+-include("asn1_records.hrl").
+%-compile(export_all).
+
+-export([pgen/4,gen_dec_prim/3,gen_encode_prim/4]).
+-export([gen_obj_code/3,gen_objectset_code/2]).
+-export([gen_decode/2, gen_decode/3]).
+-export([gen_encode/2, gen_encode/3]).
+-export([is_already_generated/2,more_genfields/1,get_class_fields/1,
+ get_object_field/2]).
+
+-import(asn1ct_gen, [emit/1,demit/1]).
+
+%% pgen(Erules, Module, TypeOrVal)
+%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module
+%% .hrl file is only generated if necessary
+%% Erules = per | ber
+%% Module = atom()
+%% TypeOrVal = {TypeList,ValueList}
+%% TypeList = ValueList = [atom()]
+
+pgen(OutFile,Erules,Module,TypeOrVal) ->
+ asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,true).
+
+
+%% Generate ENCODING ******************************
+%%****************************************x
+
+
+gen_encode(Erules,Type) when record(Type,typedef) ->
+ gen_encode_user(Erules,Type).
+%% case Type#typedef.typespec of
+%% Def when record(Def,type) ->
+%% gen_encode_user(Erules,Type);
+%% Def when tuple(Def),(element(1,Def) == 'Object') ->
+%% gen_encode_object(Erules,Type);
+%% Other ->
+%% exit({error,{asn1,{unknown,Other}}})
+%% end.
+
+gen_encode(Erules,Typename,#'ComponentType'{name=Cname,typespec=Type}) ->
+ NewTypename = [Cname|Typename],
+ gen_encode(Erules,NewTypename,Type);
+
+gen_encode(Erules,Typename,Type) when record(Type,type) ->
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ ObjFun =
+ case lists:keysearch(objfun,1,Type#type.tablecinf) of
+ {value,{_,_Name}} ->
+%% lists:concat([", ObjFun",Name]);
+ ", ObjFun";
+ false ->
+ ""
+ end,
+ case asn1ct_gen:type(InnerType) of
+ {constructed,bif} ->
+ case InnerType of
+ 'SET' ->
+ true;
+ 'SEQUENCE' ->
+ true;
+ _ ->
+ emit({nl,"'enc_",asn1ct_gen:list2name(Typename),
+ "'({'",asn1ct_gen:list2name(Typename),
+ "',Val}",ObjFun,") ->",nl}),
+ emit({"'enc_",asn1ct_gen:list2name(Typename),
+ "'(Val",ObjFun,");",nl,nl})
+ end,
+ emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val",ObjFun,
+ ") ->",nl}),
+ asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
+ _ ->
+ true
+ end.
+
+
+gen_encode_user(Erules,D) when record(D,typedef) ->
+ CurrMod = get(currmod),
+ Typename = [D#typedef.name],
+ Def = D#typedef.typespec,
+ InnerType = asn1ct_gen:get_inner(Def#type.def),
+ case InnerType of
+ 'SET' -> true;
+ 'SEQUENCE' -> true;
+ _ ->
+ emit({nl,"'enc_",asn1ct_gen:list2name(Typename),"'({'",asn1ct_gen:list2name(Typename),"',Val}) ->",nl}),
+ emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val);",nl,nl})
+ end,
+ emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val) ->",nl}),
+ case asn1ct_gen:type(InnerType) of
+ {primitive,bif} ->
+ gen_encode_prim(Erules,Def,"false"),
+ emit({".",nl});
+ 'ASN1_OPEN_TYPE' ->
+ gen_encode_prim(Erules,Def#type{def='ASN1_OPEN_TYPE'},"false"),
+ emit({".",nl});
+ {constructed,bif} ->
+ asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,D);
+ #'Externaltypereference'{module=CurrMod,type=Etype} ->
+ emit({"'enc_",Etype,"'(Val).",nl,nl});
+ #'Externaltypereference'{module=Emod,type=Etype} ->
+ emit({"'",Emod,"':'enc_",Etype,"'(Val).",nl,nl});
+ #typereference{val=Ename} ->
+ emit({"'enc_",Ename,"'(Val).",nl,nl});
+ {notype,_} ->
+ emit({"'enc_",InnerType,"'(Val).",nl,nl})
+ end.
+
+
+gen_encode_prim(Erules,D,DoTag) ->
+ Value = case asn1ct_name:active(val) of
+ true ->
+ asn1ct_gen:mk_var(asn1ct_name:curr(val));
+ false ->
+ "Val"
+ end,
+ gen_encode_prim(Erules,D,DoTag,Value).
+
+gen_encode_prim(_Erules,D,_DoTag,Value) when record(D,type) ->
+ Constraint = D#type.constraint,
+ case D#type.def of
+ 'INTEGER' ->
+ emit({"?RT_PER:encode_integer(", %fel
+ {asis,Constraint},",",Value,")"});
+ {'INTEGER',NamedNumberList} ->
+ emit({"?RT_PER:encode_integer(",
+ {asis,Constraint},",",Value,",",
+ {asis,NamedNumberList},")"});
+ {'ENUMERATED',{Nlist1,Nlist2}} ->
+ NewList = lists:concat([[{0,X}||{X,_} <- Nlist1],['EXT_MARK'],[{1,X}||{X,_} <- Nlist2]]),
+ NewC = [{'ValueRange',{0,length(Nlist1)-1}}],
+ emit(["case (case ",Value," of {_,_}->element(2,",Value,");_->",
+ Value," end) of",nl]),
+ emit_enc_enumerated_cases(NewC, NewList++[{asn1_enum,length(Nlist1)-1}], 0);
+ {'ENUMERATED',NamedNumberList} ->
+ NewList = [X||{X,_} <- NamedNumberList],
+ NewC = [{'ValueRange',{0,length(NewList)-1}}],
+ emit(["case (case ",Value," of {_,_}->element(2,",Value,");_->",
+ Value," end) of",nl]),
+ emit_enc_enumerated_cases(NewC, NewList, 0);
+ {'BIT STRING',NamedNumberList} ->
+ emit({"?RT_PER:encode_bit_string(",
+ {asis,Constraint},",",Value,",",
+ {asis,NamedNumberList},")"});
+ 'NULL' ->
+ emit({"?RT_PER:encode_null(",Value,")"});
+ 'OBJECT IDENTIFIER' ->
+ emit({"?RT_PER:encode_object_identifier(",Value,")"});
+ 'ObjectDescriptor' ->
+ emit({"?RT_PER:encode_ObjectDescriptor(",{asis,Constraint},
+ ",",Value,")"});
+ 'BOOLEAN' ->
+ emit({"?RT_PER:encode_boolean(",Value,")"});
+ 'OCTET STRING' ->
+ emit({"?RT_PER:encode_octet_string(",{asis,Constraint},",",Value,")"});
+ 'NumericString' ->
+ emit({"?RT_PER:encode_NumericString(",{asis,Constraint},",",Value,")"});
+ 'TeletexString' ->
+ emit({"?RT_PER:encode_TeletexString(",{asis,Constraint},",",Value,")"});
+ 'VideotexString' ->
+ emit({"?RT_PER:encode_VideotexString(",{asis,Constraint},",",Value,")"});
+ 'UTCTime' ->
+ emit({"?RT_PER:encode_VisibleString(",{asis,Constraint},",",Value,")"});
+ 'GeneralizedTime' ->
+ emit({"?RT_PER:encode_VisibleString(",{asis,Constraint},",",Value,")"});
+ 'GraphicString' ->
+ emit({"?RT_PER:encode_GraphicString(",{asis,Constraint},",",Value,")"});
+ 'VisibleString' ->
+ emit({"?RT_PER:encode_VisibleString(",{asis,Constraint},",",Value,")"});
+ 'GeneralString' ->
+ emit({"?RT_PER:encode_GeneralString(",{asis,Constraint},",",Value,")"});
+ 'PrintableString' ->
+ emit({"?RT_PER:encode_PrintableString(",{asis,Constraint},",",Value,")"});
+ 'IA5String' ->
+ emit({"?RT_PER:encode_IA5String(",{asis,Constraint},",",Value,")"});
+ 'BMPString' ->
+ emit({"?RT_PER:encode_BMPString(",{asis,Constraint},",",Value,")"});
+ 'UniversalString' ->
+ emit({"?RT_PER:encode_UniversalString(",{asis,Constraint},",",Value,")"});
+ 'ANY' ->
+ emit(["?RT_PER:encode_open_type(", {asis,Constraint}, ",",
+ Value, ")"]);
+ 'ASN1_OPEN_TYPE' ->
+ NewValue = case Constraint of
+ [#'Externaltypereference'{type=Tname}] ->
+ io_lib:format(
+ "?RT_PER:complete(enc_~s(~s))",[Tname,Value]);
+ [#type{def=#'Externaltypereference'{type=Tname}}] ->
+ io_lib:format(
+ "?RT_PER:complete(enc_~s(~s))",[Tname,Value]);
+ _ -> Value
+ end,
+ emit(["?RT_PER:encode_open_type(", {asis,Constraint}, ",",
+ NewValue, ")"]);
+ XX ->
+ exit({asn1_error,nyi,XX})
+ end.
+
+emit_enc_enumerated_cases(C, [H], Count) ->
+ emit_enc_enumerated_case(C, H, Count),
+ emit([";",nl,"EnumVal -> exit({error,{asn1, {enumerated_not_in_range, EnumVal}}})"]),
+ emit([nl,"end"]);
+emit_enc_enumerated_cases(C, ['EXT_MARK'|T], _Count) ->
+ emit_enc_enumerated_cases(C, T, 0);
+emit_enc_enumerated_cases(C, [H1,H2|T], Count) ->
+ emit_enc_enumerated_case(C, H1, Count),
+ emit([";",nl]),
+ emit_enc_enumerated_cases(C, [H2|T], Count+1).
+
+
+
+emit_enc_enumerated_case(_C, {asn1_enum,High}, _) ->
+ emit([
+ "{asn1_enum,EnumV} when integer(EnumV), EnumV > ",High," -> ",
+ "[{bit,1},?RT_PER:encode_small_number(EnumV)]"]);
+emit_enc_enumerated_case(_C, 'EXT_MARK', _Count) ->
+ true;
+emit_enc_enumerated_case(_C, {1,EnumName}, Count) ->
+ emit(["'",EnumName,"' -> [{bit,1},?RT_PER:encode_small_number(",Count,")]"]);
+emit_enc_enumerated_case(C, {0,EnumName}, Count) ->
+ emit(["'",EnumName,"' -> [{bit,0},?RT_PER:encode_integer(",{asis,C},", ",Count,")]"]);
+emit_enc_enumerated_case(C, EnumName, Count) ->
+ emit(["'",EnumName,"' -> ?RT_PER:encode_integer(",{asis,C},", ",Count,")"]).
+
+
+%% Object code generating for encoding and decoding
+%% ------------------------------------------------
+
+gen_obj_code(Erules,_Module,Obj) when record(Obj,typedef) ->
+ ObjName = Obj#typedef.name,
+ Def = Obj#typedef.typespec,
+ #'Externaltypereference'{module=Mod,type=ClassName} =
+ Def#'Object'.classname,
+ Class = asn1_db:dbget(Mod,ClassName),
+ {object,_,Fields} = Def#'Object'.def,
+ emit({nl,nl,nl,"%%================================"}),
+ emit({nl,"%% ",ObjName}),
+ emit({nl,"%%================================",nl}),
+ EncConstructed =
+ gen_encode_objectfields(ClassName,get_class_fields(Class),
+ ObjName,Fields,[]),
+ emit(nl),
+ gen_encode_constr_type(Erules,EncConstructed),
+ emit(nl),
+ DecConstructed =
+ gen_decode_objectfields(ClassName,get_class_fields(Class),
+ ObjName,Fields,[]),
+ emit(nl),
+ gen_decode_constr_type(Erules,DecConstructed),
+ emit(nl);
+gen_obj_code(_,_,Obj) when record(Obj,pobjectdef) ->
+ ok.
+
+
+gen_encode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
+ ObjName,ObjectFields,ConstrAcc) ->
+ EmitFuncClause =
+ fun(V) ->
+ emit(["'enc_",ObjName,"'(",{asis,Name},
+ ",",V,",_RestPrimFieldName) ->",nl])
+ end,
+% emit(["'enc_",ObjName,"'(",{asis,Name},
+% ", Val, _RestPrimFieldName) ->",nl]),
+ MaybeConstr =
+ case {get_object_field(Name,ObjectFields),OptOrMand} of
+ {false,'MANDATORY'} -> %% this case is illegal
+ exit({error,{asn1,{"missing mandatory field in object",
+ ObjName}}});
+ {false,'OPTIONAL'} ->
+ EmitFuncClause("_"),
+ emit(" []"),
+ [];
+ {false,{'DEFAULT',DefaultType}} ->
+ EmitFuncClause("Val"),
+ gen_encode_default_call(ClassName,Name,DefaultType);
+ {{Name,TypeSpec},_} ->
+ %% A specified field owerwrites any 'DEFAULT' or
+ %% 'OPTIONAL' field in the class
+ EmitFuncClause("Val"),
+ gen_encode_field_call(ObjName,Name,TypeSpec)
+ end,
+ case more_genfields(Rest) of
+ true ->
+ emit([";",nl]);
+ false ->
+ emit([".",nl])
+ end,
+ gen_encode_objectfields(ClassName,Rest,ObjName,ObjectFields,
+ MaybeConstr++ConstrAcc);
+gen_encode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
+ ObjName,ObjectFields,ConstrAcc) ->
+ EmitFuncClause =
+ fun(Attrs) ->
+ emit(["'enc_",ObjName,"'(",{asis,Name},
+ ",",Attrs,") ->",nl])
+ end,
+% emit(["'enc_",ObjName,"'(",{asis,Name},
+% ", Val,[H|T]) ->",nl]),
+ case {get_object_field(Name,ObjectFields),OptOrMand} of
+ {false,'MANDATORY'} ->
+ exit({error,{asn1,{"missing mandatory field in object",
+ ObjName}}});
+ {false,'OPTIONAL'} ->
+ EmitFuncClause("_,_"),
+ emit([" exit({error,{'use of missing field in object', ",Name,
+ "}})"]);
+ {false,{'DEFAULT',_DefaultObject}} ->
+ exit({error,{asn1,{"not implemented yet",Name}}});
+ {{Name,TypeSpec},_} ->
+ EmitFuncClause("Val,[H|T]"),
+ case TypeSpec#typedef.name of
+ {ExtMod,TypeName} ->
+ emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
+ "'(H, Val, T)"});
+ TypeName ->
+ emit({indent(3),"'enc_",TypeName,"'(H, Val, T)"})
+ end
+ end,
+ case more_genfields(Rest) of
+ true ->
+ emit([";",nl]);
+ false ->
+ emit([".",nl])
+ end,
+ gen_encode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
+gen_encode_objectfields(ClassName,[_C|Cs],O,OF,Acc) ->
+ gen_encode_objectfields(ClassName,Cs,O,OF,Acc);
+gen_encode_objectfields(_,[],_,_,Acc) ->
+ Acc.
+
+
+% gen_encode_objectfields(Class,ObjName,[{FieldName,Type}|Rest],ConstrAcc) ->
+% Fields = Class#objectclass.fields,
+
+% MaybeConstr =
+% case is_typefield(Fields,FieldName) of
+% true ->
+% Def = Type#typedef.typespec,
+% emit({"'enc_",ObjName,"'(",{asis,FieldName},
+% ", Val, Dummy) ->",nl}),
+
+% CAcc =
+% case Type#typedef.name of
+% {primitive,bif} ->
+% gen_encode_prim(per,Def,"false","Val"),
+% [];
+% {constructed,bif} ->
+% emit({" 'enc_",ObjName,'_',FieldName,
+% "'(Val)"}),
+% [{['enc_',ObjName,'_',FieldName],Def}];
+% {ExtMod,TypeName} ->
+% emit({" '",ExtMod,"':'enc_",TypeName,"'(Val)"}),
+% [];
+% TypeName ->
+% emit({" 'enc_",TypeName,"'(Val)"}),
+% []
+% end,
+% case more_genfields(Fields,Rest) of
+% true ->
+% emit({";",nl});
+% false ->
+% emit({".",nl})
+% end,
+% CAcc;
+% {false,objectfield} ->
+% emit({"'enc_",ObjName,"'(",{asis,FieldName},
+% ", Val, [H|T]) ->",nl}),
+% case Type#typedef.name of
+% {ExtMod,TypeName} ->
+% emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
+% "'(H, Val, T)"});
+% TypeName ->
+% emit({indent(3),"'enc_",TypeName,"'(H, Val, T)"})
+% end,
+% case more_genfields(Fields,Rest) of
+% true ->
+% emit({";",nl});
+% false ->
+% emit({".",nl})
+% end,
+% [];
+% {false,_} -> []
+% end,
+% gen_encode_objectfields(Class,ObjName,Rest,MaybeConstr ++ ConstrAcc);
+% gen_encode_objectfields(C,O,[H|T],Acc) ->
+% gen_encode_objectfields(C,O,T,Acc);
+% gen_encode_objectfields(_,_,[],Acc) ->
+% Acc.
+
+% gen_encode_constr_type(Erules,[{Name,Def}|Rest]) ->
+% emit({Name,"(Val) ->",nl}),
+% InnerType = asn1ct_gen:get_inner(Def#type.def),
+% asn1ct_gen:gen_encode_constructed(Erules,Name,InnerType,Def),
+% gen_encode_constr_type(Erules,Rest);
+gen_encode_constr_type(Erules,[TypeDef|Rest]) when record(TypeDef,typedef) ->
+ case is_already_generated(enc,TypeDef#typedef.name) of
+ true -> ok;
+ _ ->
+ Name = lists:concat(["enc_",TypeDef#typedef.name]),
+ emit({Name,"(Val) ->",nl}),
+ Def = TypeDef#typedef.typespec,
+ InnerType = asn1ct_gen:get_inner(Def#type.def),
+ asn1ct_gen:gen_encode_constructed(Erules,Name,InnerType,Def),
+ gen_encode_constr_type(Erules,Rest)
+ end;
+gen_encode_constr_type(_,[]) ->
+ ok.
+
+gen_encode_field_call(ObjName,FieldName,Type) ->
+ Def = Type#typedef.typespec,
+ case Type#typedef.name of
+ {primitive,bif} ->
+ gen_encode_prim(per,Def,"false",
+ "Val"),
+ [];
+ {constructed,bif} ->
+ emit({" 'enc_",ObjName,'_',FieldName,
+ "'(Val)"}),
+ [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
+ {ExtMod,TypeName} ->
+ emit({" '",ExtMod,"':'enc_",TypeName,
+ "'(Val)"}),
+ [];
+ TypeName ->
+ emit({" 'enc_",TypeName,"'(Val)"}),
+ []
+ end.
+
+gen_encode_default_call(ClassName,FieldName,Type) ->
+ CurrentMod = get(currmod),
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ case asn1ct_gen:type(InnerType) of
+ {constructed,bif} ->
+%% asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
+ emit([" 'enc_",ClassName,'_',FieldName,"'(Val)"]),
+ [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
+ typespec=Type}];
+ {primitive,bif} ->
+ gen_encode_prim(per,Type,"false","Val"),
+ [];
+ #'Externaltypereference'{module=CurrentMod,type=Etype} ->
+ emit([" 'enc_",Etype,"'(Val)",nl]),
+ [];
+ #'Externaltypereference'{module=Emod,type=Etype} ->
+ emit([" '",Emod,"':'enc_",Etype,"'(Val)",nl]),
+ []
+ end.
+
+
+gen_decode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
+ ObjName,ObjectFields,ConstrAcc) ->
+ EmitFuncClause =
+ fun(Bytes) ->
+ emit(["'dec_",ObjName,"'(",{asis,Name},",",Bytes,
+ ",_,_RestPrimFieldName) ->",nl])
+ end,
+ MaybeConstr=
+ case {get_object_field(Name,ObjectFields),OptOrMand} of
+ {false,'MANDATORY'} -> %% this case is illegal
+ exit({error,{asn1,{"missing mandatory field in object",
+ ObjName}}});
+ {false,'OPTIONAL'} ->
+ EmitFuncClause("_"),
+ emit([" asn1_NOVALUE"]),
+ [];
+ {false,{'DEFAULT',DefaultType}} ->
+ EmitFuncClause("Bytes"),
+ gen_decode_default_call(ClassName,Name,"Bytes",DefaultType);
+ {{Name,TypeSpec},_} ->
+ %% A specified field owerwrites any 'DEFAULT' or
+ %% 'OPTIONAL' field in the class
+ EmitFuncClause("Bytes"),
+ gen_decode_field_call(ObjName,Name,"Bytes",TypeSpec)
+ end,
+ case more_genfields(Rest) of
+ true ->
+ emit([";",nl]);
+ false ->
+ emit([".",nl])
+ end,
+ gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,MaybeConstr++ConstrAcc);
+gen_decode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
+ ObjName,ObjectFields,ConstrAcc) ->
+ EmitFuncClause =
+ fun(Attrs) ->
+ emit(["'dec_",ObjName,"'(",{asis,Name},
+ ",",Attrs,") ->",nl])
+ end,
+% emit(["'dec_",ObjName,"'(",{asis,Name},
+% ", Bytes,_,[H|T]) ->",nl]),
+ case {get_object_field(Name,ObjectFields),OptOrMand} of
+ {false,'MANDATORY'} ->
+ exit({error,{asn1,{"missing mandatory field in object",
+ ObjName}}});
+ {false,'OPTIONAL'} ->
+ EmitFuncClause("_,_,_"),
+ emit([" exit({error,{'illegal use of missing field in object', ",Name,
+ "}})"]);
+ {false,{'DEFAULT',_DefaultObject}} ->
+ exit({error,{asn1,{"not implemented yet",Name}}});
+ {{Name,TypeSpec},_} ->
+ EmitFuncClause("Bytes,_,[H|T]"),
+ case TypeSpec#typedef.name of
+ {ExtMod,TypeName} ->
+ emit({indent(3),"'",ExtMod,"':'dec_",TypeName,
+ "'(H, Bytes, telltype, T)"});
+ TypeName ->
+ emit({indent(3),"'dec_",TypeName,"'(H, Bytes, telltype, T)"})
+ end
+ end,
+ case more_genfields(Rest) of
+ true ->
+ emit([";",nl]);
+ false ->
+ emit([".",nl])
+ end,
+ gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
+gen_decode_objectfields(CN,[_C|Cs],O,OF,CAcc) ->
+ gen_decode_objectfields(CN,Cs,O,OF,CAcc);
+gen_decode_objectfields(_,[],_,_,CAcc) ->
+ CAcc.
+
+
+% gen_decode_objectfields(Class,ObjName,[{FieldName,Type}|Rest],ConstrAcc) ->
+% Fields = Class#objectclass.fields,
+
+% MaybeConstr =
+% case is_typefield(Fields,FieldName) of
+% true ->
+% Def = Type#typedef.typespec,
+% emit({"'dec_",ObjName,"'(",{asis,FieldName},
+% ", Val, Telltype, RestPrimFieldName) ->",nl}),
+
+% CAcc =
+% case Type#typedef.name of
+% {primitive,bif} ->
+% gen_dec_prim(per,Def,"Val"),
+% [];
+% {constructed,bif} ->
+% emit({" 'dec_",ObjName,'_',FieldName,
+% "'(Val, Telltype)"}),
+% [{['dec_',ObjName,'_',FieldName],Def}];
+% {ExtMod,TypeName} ->
+% emit({" '",ExtMod,"':'dec_",TypeName,
+% "'(Val, Telltype)"}),
+% [];
+% TypeName ->
+% emit({" 'dec_",TypeName,"'(Val, Telltype)"}),
+% []
+% end,
+% case more_genfields(Fields,Rest) of
+% true ->
+% emit({";",nl});
+% false ->
+% emit({".",nl})
+% end,
+% CAcc;
+% {false,objectfield} ->
+% emit({"'dec_",ObjName,"'(",{asis,FieldName},
+% ", Val, Telltype, [H|T]) ->",nl}),
+% case Type#typedef.name of
+% {ExtMod,TypeName} ->
+% emit({indent(3),"'",ExtMod,"':'dec_",TypeName,
+% "'(H, Val, Telltype, T)"});
+% TypeName ->
+% emit({indent(3),"'dec_",TypeName,
+% "'(H, Val, Telltype, T)"})
+% end,
+% case more_genfields(Fields,Rest) of
+% true ->
+% emit({";",nl});
+% false ->
+% emit({".",nl})
+% end,
+% [];
+% {false,_} ->
+% []
+% end,
+% gen_decode_objectfields(Class,ObjName,Rest,MaybeConstr ++ ConstrAcc);
+% gen_decode_objectfields(C,O,[H|T],CAcc) ->
+% gen_decode_objectfields(C,O,T,CAcc);
+% gen_decode_objectfields(_,_,[],CAcc) ->
+% CAcc.
+
+
+gen_decode_field_call(ObjName,FieldName,Bytes,Type) ->
+ Def = Type#typedef.typespec,
+ case Type#typedef.name of
+ {primitive,bif} ->
+ gen_dec_prim(per,Def,Bytes),
+ [];
+ {constructed,bif} ->
+ emit({" 'dec_",ObjName,'_',FieldName,
+ "'(",Bytes,",telltype)"}),
+ [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
+ {ExtMod,TypeName} ->
+ emit({" '",ExtMod,"':'dec_",TypeName,
+ "'(",Bytes,", telltype)"}),
+ [];
+ TypeName ->
+ emit({" 'dec_",TypeName,"'(",Bytes,", telltype)"}),
+ []
+ end.
+
+gen_decode_default_call(ClassName,FieldName,Bytes,Type) ->
+ CurrentMod = get(currmod),
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ case asn1ct_gen:type(InnerType) of
+ {constructed,bif} ->
+ emit([" 'dec_",ClassName,'_',FieldName,"'(",Bytes,", telltype)"]),
+ [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
+ typespec=Type}];
+ {primitive,bif} ->
+ gen_dec_prim(per,Type,Bytes),
+ [];
+ #'Externaltypereference'{module=CurrentMod,type=Etype} ->
+ emit([" 'dec_",Etype,"'(",Bytes,", telltype)",nl]),
+ [];
+ #'Externaltypereference'{module=Emod,type=Etype} ->
+ emit([" '",Emod,"':'dec_",Etype,"'(",Bytes,", telltype)",nl]),
+ []
+ end.
+
+
+gen_decode_constr_type(Erules,[{Name,Def}|Rest]) ->
+ emit({Name,"(Bytes,_) ->",nl}),
+ InnerType = asn1ct_gen:get_inner(Def#type.def),
+ asn1ct_gen:gen_decode_constructed(Erules,Name,InnerType,Def),
+ gen_decode_constr_type(Erules,Rest);
+gen_decode_constr_type(Erules,[TypeDef|Rest]) when record(TypeDef,typedef) ->
+ case is_already_generated(dec,TypeDef#typedef.name) of
+ true -> ok;
+ _ ->
+ gen_decode(Erules,TypeDef)
+ end,
+ gen_decode_constr_type(Erules,Rest);
+gen_decode_constr_type(_,[]) ->
+ ok.
+
+% more_genfields(Fields,[]) ->
+% false;
+% more_genfields(Fields,[{FieldName,_}|T]) ->
+% case is_typefield(Fields,FieldName) of
+% true -> true;
+% {false,objectfield} -> true;
+% {false,_} -> more_genfields(Fields,T)
+% end.
+
+more_genfields([]) ->
+ false;
+more_genfields([Field|Fields]) ->
+ case element(1,Field) of
+ typefield ->
+ true;
+ objectfield ->
+ true;
+ _ ->
+ more_genfields(Fields)
+ end.
+
+% is_typefield(Fields,FieldName) ->
+% case lists:keysearch(FieldName,2,Fields) of
+% {value,Field} ->
+% case element(1,Field) of
+% typefield ->
+% true;
+% Other ->
+% {false,Other}
+% end;
+% _ ->
+% false
+% end.
+%% Object Set code generating for encoding and decoding
+%% ----------------------------------------------------
+gen_objectset_code(Erules,ObjSet) ->
+ ObjSetName = ObjSet#typedef.name,
+ Def = ObjSet#typedef.typespec,
+%% {ClassName,ClassDef} = Def#'ObjectSet'.class,
+ #'Externaltypereference'{module=ClassModule,
+ type=ClassName} = Def#'ObjectSet'.class,
+ ClassDef = asn1_db:dbget(ClassModule,ClassName),
+ UniqueFName = Def#'ObjectSet'.uniquefname,
+ Set = Def#'ObjectSet'.set,
+ emit({nl,nl,nl,"%%================================"}),
+ emit({nl,"%% ",ObjSetName}),
+ emit({nl,"%%================================",nl}),
+ case ClassName of
+ {_Module,ExtClassName} ->
+ gen_objset_code(Erules,ObjSetName,UniqueFName,Set,
+ ExtClassName,ClassDef);
+ _ ->
+ gen_objset_code(Erules,ObjSetName,UniqueFName,Set,
+ ClassName,ClassDef)
+ end,
+ emit(nl).
+
+gen_objset_code(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassDef)->
+ ClassFields = (ClassDef#classdef.typespec)#objectclass.fields,
+ InternalFuncs=
+ gen_objset_enc(ObjSetName,UniqueFName,Set,ClassName,ClassFields,1,[]),
+ gen_objset_dec(ObjSetName,UniqueFName,Set,ClassName,ClassFields,1),
+ gen_internal_funcs(Erules,InternalFuncs).
+
+%% gen_objset_enc iterates over the objects of the object set
+gen_objset_enc(_,{unique,undefined},_,_,_,_,_) ->
+ %% There is no unique field in the class of this object set
+ %% don't bother about the constraint
+ [];
+gen_objset_enc(ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],
+ ClName,ClFields,NthObj,Acc)->
+ emit({"'getenc_",ObjSName,"'(",{asis,UniqueName},",",{asis,Val},
+ ") ->",nl}),
+ {InternalFunc,NewNthObj}=
+ case ObjName of
+ no_name ->
+ gen_inlined_enc_funs(Fields,ClFields,ObjSName,NthObj);
+ _Other ->
+ emit({" fun 'enc_",ObjName,"'/3"}),
+ {[],0}
+ end,
+ emit({";",nl}),
+ gen_objset_enc(ObjSName,UniqueName,[T|Rest],ClName,ClFields,
+ NewNthObj,InternalFunc ++ Acc);
+gen_objset_enc(ObjSetName,UniqueName,
+ [{ObjName,Val,Fields}],_ClName,ClFields,NthObj,Acc) ->
+
+ emit({"'getenc_",ObjSetName,"'(",{asis,UniqueName},",",
+ {asis,Val},") ->",nl}),
+ {InternalFunc,_}=
+ case ObjName of
+ no_name ->
+ gen_inlined_enc_funs(Fields,ClFields,ObjSetName,NthObj);
+ _Other ->
+ emit({" fun 'enc_",ObjName,"'/3"}),
+ {[],NthObj}
+ end,
+ emit({".",nl,nl}),
+ InternalFunc++Acc;
+gen_objset_enc(ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
+ _ClFields,_NthObj,Acc) ->
+ emit({"'getenc_",ObjSetName,"'(_, _) ->",nl}),
+ emit({indent(3),"fun(_, Val, _) ->",nl}),
+ emit({indent(6),"[{octets,Val}]",nl}),
+ emit({indent(3),"end.",nl,nl}),
+ Acc;
+gen_objset_enc(_,_,[],_,_,_,Acc) ->
+ Acc.
+
+%% gen_inlined_enc_funs for each object iterates over all fields of a
+%% class, and for each typefield it checks if the object has that
+%% field and emits the proper code.
+gen_inlined_enc_funs(Fields,[{typefield,Name,_}|Rest],ObjSetName,NthObj) ->
+ InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
+ case lists:keysearch(Name,1,Fields) of
+ {value,{_,Type}} when record(Type,type) ->
+ emit({indent(3),"fun(Type, Val, _) ->",nl,
+ indent(6),"case Type of",nl}),
+ {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
+ gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
+ {value,{_,Type}} when record(Type,typedef) ->
+ emit({indent(3),"fun(Type, Val, _) ->",nl,
+ indent(6),"case Type of",nl}),
+ emit({indent(9),{asis,Name}," ->",nl}),
+ {Ret,N} = emit_inner_of_fun(Type,InternalDefFunName),
+ gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
+ false ->
+ gen_inlined_enc_funs(Fields,Rest,ObjSetName,NthObj)
+ end;
+gen_inlined_enc_funs(Fields,[_H|Rest],ObjSetName,NthObj) ->
+ gen_inlined_enc_funs(Fields,Rest,ObjSetName,NthObj);
+gen_inlined_enc_funs(_,[],_,NthObj) ->
+ {[],NthObj}.
+
+gen_inlined_enc_funs1(Fields,[{typefield,Name,_}|Rest],ObjSetName,
+ NthObj,Acc) ->
+ InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
+ {Acc2,NAdd}=
+ case lists:keysearch(Name,1,Fields) of
+ {value,{_,Type}} when record(Type,type) ->
+ emit({";",nl}),
+ {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
+ {Ret++Acc,N};
+ {value,{_,Type}} when record(Type,typedef) ->
+ emit({";",nl,indent(9),{asis,Name}," ->",nl}),
+ {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
+ {Ret++Acc,N};
+ false ->
+ {Acc,0}
+ end,
+ gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+NAdd,Acc2);
+gen_inlined_enc_funs1(Fields,[_H|Rest],ObjSetName,NthObj,Acc)->
+ gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj,Acc);
+gen_inlined_enc_funs1(_,[],_,NthObj,Acc) ->
+ emit({nl,indent(6),"end",nl}),
+ emit({indent(3),"end"}),
+ {Acc,NthObj}.
+
+emit_inner_of_fun(TDef=#typedef{name={ExtMod,Name},typespec=Type},
+ InternalDefFunName) ->
+ case {ExtMod,Name} of
+ {primitive,bif} ->
+ emit(indent(12)),
+ gen_encode_prim(per,Type,dotag,"Val"),
+ {[],0};
+ {constructed,bif} ->
+ emit([indent(12),"'enc_",
+ InternalDefFunName,"'(Val)"]),
+ {[TDef#typedef{name=InternalDefFunName}],1};
+ _ ->
+ emit({indent(12),"'",ExtMod,"':'enc_",Name,"'(Val)"}),
+ {[],0}
+ end;
+emit_inner_of_fun(#typedef{name=Name},_) ->
+ emit({indent(12),"'enc_",Name,"'(Val)"}),
+ {[],0};
+emit_inner_of_fun(Type,_) when record(Type,type) ->
+ CurrMod = get(currmod),
+ case Type#type.def of
+ Def when atom(Def) ->
+ emit({indent(9),Def," ->",nl,indent(12)}),
+ gen_encode_prim(erules,Type,dotag,"Val");
+ TRef when record(TRef,typereference) ->
+ T = TRef#typereference.val,
+ emit({indent(9),T," ->",nl,indent(12),"'enc_",T,"'(Val)"});
+ #'Externaltypereference'{module=CurrMod,type=T} ->
+ emit({indent(9),T," ->",nl,indent(12),"'enc_",T,"'(Val)"});
+ #'Externaltypereference'{module=ExtMod,type=T} ->
+ emit({indent(9),T," ->",nl,indent(12),ExtMod,":'enc_",
+ T,"'(Val)"})
+ end,
+ {[],0}.
+
+indent(N) ->
+ lists:duplicate(N,32). % 32 = space
+
+
+gen_objset_dec(_,{unique,undefined},_,_,_,_) ->
+ %% There is no unique field in the class of this object set
+ %% don't bother about the constraint
+ ok;
+gen_objset_dec(ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],ClName,
+ ClFields,NthObj)->
+
+ emit({"'getdec_",ObjSName,"'(",{asis,UniqueName},",",{asis,Val},
+ ") ->",nl}),
+ NewNthObj=
+ case ObjName of
+ no_name ->
+ gen_inlined_dec_funs(Fields,ClFields,ObjSName,NthObj);
+ _Other ->
+ emit({" fun 'dec_",ObjName,"'/4"}),
+ NthObj
+ end,
+ emit({";",nl}),
+ gen_objset_dec(ObjSName,UniqueName,[T|Rest],ClName,ClFields,NewNthObj);
+gen_objset_dec(ObjSetName,UniqueName,[{ObjName,Val,Fields}],_ClName,
+ ClFields,NthObj) ->
+
+ emit({"'getdec_",ObjSetName,"'(",{asis,UniqueName},",",{asis,Val},
+ ") ->",nl}),
+ case ObjName of
+ no_name ->
+ gen_inlined_dec_funs(Fields,ClFields,ObjSetName,NthObj);
+ _Other ->
+ emit({" fun 'dec_",ObjName,"'/4"})
+ end,
+ emit({".",nl,nl}),
+ ok;
+gen_objset_dec(ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,_ClFields,
+ _NthObj) ->
+ emit({"'getdec_",ObjSetName,"'(_, _) ->",nl}),
+ emit({indent(3),"fun(Attr1, Bytes, _,_) ->",nl}),
+%% emit({indent(6),"?RT_PER:decode_open_type(Bytes,[])",nl}),
+ emit({indent(6),"{Bytes,Attr1}",nl}),
+ emit({indent(3),"end.",nl,nl}),
+ ok;
+gen_objset_dec(_,_,[],_,_,_) ->
+ ok.
+
+gen_inlined_dec_funs(Fields,[{typefield,Name,_}|Rest],
+ ObjSetName,NthObj) ->
+ InternalDefFunName = [NthObj,Name,ObjSetName],
+ case lists:keysearch(Name,1,Fields) of
+ {value,{_,Type}} when record(Type,type) ->
+ emit({indent(3),"fun(Type, Val, _, _) ->",nl,
+ indent(6),"case Type of",nl}),
+ N=emit_inner_of_decfun(Type,InternalDefFunName),
+ gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
+ {value,{_,Type}} when record(Type,typedef) ->
+ emit({indent(3),"fun(Type, Val, _, _) ->",nl,
+ indent(6),"case Type of",nl}),
+ emit({indent(9),{asis,Name}," ->",nl}),
+ N=emit_inner_of_decfun(Type,InternalDefFunName),
+ gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
+ false ->
+ gen_inlined_dec_funs(Fields,Rest,ObjSetName,NthObj)
+ end;
+gen_inlined_dec_funs(Fields,[_|Rest],ObjSetName,NthObj) ->
+ gen_inlined_dec_funs(Fields,Rest,ObjSetName,NthObj);
+gen_inlined_dec_funs(_,[],_,NthObj) ->
+ NthObj.
+
+gen_inlined_dec_funs1(Fields,[{typefield,Name,_}|Rest],
+ ObjSetName,NthObj) ->
+ InternalDefFunName = [NthObj,Name,ObjSetName],
+ N=case lists:keysearch(Name,1,Fields) of
+ {value,{_,Type}} when record(Type,type) ->
+ emit({";",nl}),
+ emit_inner_of_decfun(Type,InternalDefFunName);
+ {value,{_,Type}} when record(Type,typedef) ->
+ emit({";",nl,indent(9),{asis,Name}," ->",nl}),
+ emit_inner_of_decfun(Type,InternalDefFunName);
+ false ->
+ 0
+ end,
+ gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
+gen_inlined_dec_funs1(Fields,[_|Rest],ObjSetName,NthObj)->
+ gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj);
+gen_inlined_dec_funs1(_,[],_,NthObj) ->
+ emit({nl,indent(6),"end",nl}),
+ emit({indent(3),"end"}),
+ NthObj.
+
+emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type},
+ InternalDefFunName) ->
+ case {ExtName,Name} of
+ {primitive,bif} ->
+ emit(indent(12)),
+ gen_dec_prim(per,Type,"Val"),
+ 0;
+ {constructed,bif} ->
+ emit({indent(12),"'dec_",
+ asn1ct_gen:list2name(InternalDefFunName),"'(Val)"}),
+ 1;
+ _ ->
+ emit({indent(12),"'",ExtName,"':'dec_",Name,"'(Val, telltype)"}),
+ 0
+ end;
+emit_inner_of_decfun(#typedef{name=Name},_) ->
+ emit({indent(12),"'dec_",Name,"'(Val, telltype)"}),
+ 0;
+emit_inner_of_decfun(Type,_) when record(Type,type) ->
+ CurrMod = get(currmod),
+ case Type#type.def of
+ Def when atom(Def) ->
+ emit({indent(9),Def," ->",nl,indent(12)}),
+ gen_dec_prim(erules,Type,"Val");
+ TRef when record(TRef,typereference) ->
+ T = TRef#typereference.val,
+ emit({indent(9),T," ->",nl,indent(12),"'dec_",T,"'(Val)"});
+ #'Externaltypereference'{module=CurrMod,type=T} ->
+ emit({indent(9),T," ->",nl,indent(12),"'dec_",T,"'(Val)"});
+ #'Externaltypereference'{module=ExtMod,type=T} ->
+ emit({indent(9),T," ->",nl,indent(12),ExtMod,":'dec_",
+ T,"'(Val)"})
+ end,
+ 0.
+
+
+gen_internal_funcs(_,[]) ->
+ ok;
+gen_internal_funcs(Erules,[TypeDef|Rest]) ->
+ gen_encode_user(Erules,TypeDef),
+ emit([nl,nl,"'dec_",TypeDef#typedef.name,"'(Bytes) ->",nl]),
+ gen_decode_user(Erules,TypeDef),
+ gen_internal_funcs(Erules,Rest).
+
+
+
+%% DECODING *****************************
+%%***************************************
+
+
+gen_decode(Erules,Type) when record(Type,typedef) ->
+ D = Type,
+ emit({nl,nl}),
+ emit({"'dec_",Type#typedef.name,"'(Bytes,_) ->",nl}),
+ dbdec(Type#typedef.name),
+ gen_decode_user(Erules,D).
+
+gen_decode(Erules,Tname,#'ComponentType'{name=Cname,typespec=Type}) ->
+ NewTname = [Cname|Tname],
+ gen_decode(Erules,NewTname,Type);
+
+gen_decode(Erules,Typename,Type) when record(Type,type) ->
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ case asn1ct_gen:type(InnerType) of
+ {constructed,bif} ->
+ ObjFun =
+ case Type#type.tablecinf of
+ [{objfun,_}|_R] ->
+ ", ObjFun";
+ _ ->
+ ""
+ end,
+ emit({nl,"'dec_",asn1ct_gen:list2name(Typename),
+ "'(Bytes,_",ObjFun,") ->",nl}),
+ dbdec(Typename),
+ asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,Type);
+ _ ->
+ true
+ end.
+
+dbdec(Type) when list(Type)->
+ demit({"io:format(\"decoding: ",asn1ct_gen:list2name(Type),"~w~n\",[Bytes]),",nl});
+dbdec(Type) ->
+ demit({"io:format(\"decoding: ",{asis,Type},"~w~n\",[Bytes]),",nl}).
+
+gen_decode_user(Erules,D) when record(D,typedef) ->
+ CurrMod = get(currmod),
+ Typename = [D#typedef.name],
+ Def = D#typedef.typespec,
+ InnerType = asn1ct_gen:get_inner(Def#type.def),
+ case asn1ct_gen:type(InnerType) of
+ {primitive,bif} ->
+ gen_dec_prim(Erules,Def,"Bytes"),
+ emit({".",nl,nl});
+ 'ASN1_OPEN_TYPE' ->
+ gen_dec_prim(Erules,Def#type{def='ASN1_OPEN_TYPE'},"Bytes"),
+ emit({".",nl,nl});
+ {constructed,bif} ->
+ asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,D);
+ #typereference{val=Dname} ->
+ emit({"'dec_",Dname,"'(Bytes,telltype)"}),
+ emit({".",nl,nl});
+ #'Externaltypereference'{module=CurrMod,type=Etype} ->
+ emit({"'dec_",Etype,"'(Bytes,telltype).",nl,nl});
+ #'Externaltypereference'{module=Emod,type=Etype} ->
+ emit({"'",Emod,"':'dec_",Etype,"'(Bytes,telltype).",nl,nl});
+ Other ->
+ exit({error,{asn1,{unknown,Other}}})
+ end.
+
+
+gen_dec_prim(_Erules,Att,BytesVar) ->
+ Typename = Att#type.def,
+ Constraint = Att#type.constraint,
+ case Typename of
+ 'INTEGER' ->
+ emit({"?RT_PER:decode_integer(",BytesVar,",",
+ {asis,Constraint},")"});
+ {'INTEGER',NamedNumberList} ->
+ emit({"?RT_PER:decode_integer(",BytesVar,",",
+ {asis,Constraint},",",
+ {asis,NamedNumberList},")"});
+ {'BIT STRING',NamedNumberList} ->
+ case get(compact_bit_string) of
+ true ->
+ emit({"?RT_PER:decode_compact_bit_string(",
+ BytesVar,",",{asis,Constraint},",",
+ {asis,NamedNumberList},")"});
+ _ ->
+ emit({"?RT_PER:decode_bit_string(",BytesVar,",",
+ {asis,Constraint},",",
+ {asis,NamedNumberList},")"})
+ end;
+ 'NULL' ->
+ emit({"?RT_PER:decode_null(",
+ BytesVar,")"});
+ 'OBJECT IDENTIFIER' ->
+ emit({"?RT_PER:decode_object_identifier(",
+ BytesVar,")"});
+ 'ObjectDescriptor' ->
+ emit({"?RT_PER:decode_ObjectDescriptor(",
+ BytesVar,")"});
+ {'ENUMERATED',{NamedNumberList1,NamedNumberList2}} ->
+ NewTup = {list_to_tuple([X||{X,_} <- NamedNumberList1]),
+ list_to_tuple([X||{X,_} <- NamedNumberList2])},
+ NewC = [{'ValueRange',{0,size(element(1,NewTup))-1}}],
+ emit({"?RT_PER:decode_enumerated(",BytesVar,",",
+ {asis,NewC},",",
+ {asis,NewTup},")"});
+ {'ENUMERATED',NamedNumberList} ->
+ NewTup = list_to_tuple([X||{X,_} <- NamedNumberList]),
+ NewC = [{'ValueRange',{0,size(NewTup)-1}}],
+ emit({"?RT_PER:decode_enumerated(",BytesVar,",",
+ {asis,NewC},",",
+ {asis,NewTup},")"});
+ 'BOOLEAN'->
+ emit({"?RT_PER:decode_boolean(",BytesVar,")"});
+ 'OCTET STRING' ->
+ emit({"?RT_PER:decode_octet_string(",BytesVar,",",
+ {asis,Constraint},")"});
+ 'NumericString' ->
+ emit({"?RT_PER:decode_NumericString(",BytesVar,",",
+ {asis,Constraint},")"});
+ 'TeletexString' ->
+ emit({"?RT_PER:decode_TeletexString(",BytesVar,",",
+ {asis,Constraint},")"});
+ 'VideotexString' ->
+ emit({"?RT_PER:decode_VideotexString(",BytesVar,",",
+ {asis,Constraint},")"});
+ 'UTCTime' ->
+ emit({"?RT_PER:decode_VisibleString(",BytesVar,",",
+ {asis,Constraint},")"});
+ 'GeneralizedTime' ->
+ emit({"?RT_PER:decode_VisibleString(",BytesVar,",",
+ {asis,Constraint},")"});
+ 'GraphicString' ->
+ emit({"?RT_PER:decode_GraphicString(",BytesVar,",",
+ {asis,Constraint},")"});
+ 'VisibleString' ->
+ emit({"?RT_PER:decode_VisibleString(",BytesVar,",",
+ {asis,Constraint},")"});
+ 'GeneralString' ->
+ emit({"?RT_PER:decode_GeneralString(",BytesVar,",",
+ {asis,Constraint},")"});
+ 'PrintableString' ->
+ emit({"?RT_PER:decode_PrintableString(",BytesVar,",",{asis,Constraint},")"});
+ 'IA5String' ->
+ emit({"?RT_PER:decode_IA5String(",BytesVar,",",{asis,Constraint},")"});
+ 'BMPString' ->
+ emit({"?RT_PER:decode_BMPString(",BytesVar,",",{asis,Constraint},")"});
+ 'UniversalString' ->
+ emit({"?RT_PER:decode_UniversalString(",BytesVar,",",{asis,Constraint},")"});
+ 'ANY' ->
+ emit(["?RT_PER:decode_open_type(",BytesVar,",",
+ {asis,Constraint}, ")"]);
+ 'ASN1_OPEN_TYPE' ->
+ case Constraint of
+ [#'Externaltypereference'{type=Tname}] ->
+ emit(["fun(FBytes) ->",nl,
+ " {XTerm,XBytes} = "]),
+ emit(["?RT_PER:decode_open_type(FBytes,[]),",nl]),
+ emit([" {YTerm,_} = dec_",Tname,"(XTerm,mandatory),",nl]),
+ emit([" {YTerm,XBytes} end(",BytesVar,")"]);
+ [#type{def=#'Externaltypereference'{type=Tname}}] ->
+ emit(["fun(FBytes) ->",nl,
+ " {XTerm,XBytes} = "]),
+ emit(["?RT_PER:decode_open_type(FBytes,[]),",nl]),
+ emit([" {YTerm,_} = dec_",Tname,"(XTerm,mandatory),",nl]),
+ emit([" {YTerm,XBytes} end(",BytesVar,")"]);
+ _ ->
+ emit(["?RT_PER:decode_open_type(",BytesVar,",[])"])
+ end;
+ Other ->
+ exit({'cant decode' ,Other})
+ end.
+
+
+is_already_generated(Operation,Name) ->
+ case get(class_default_type) of
+ undefined ->
+ put(class_default_type,[{Operation,Name}]),
+ false;
+ GeneratedList ->
+ case lists:member({Operation,Name},GeneratedList) of
+ true ->
+ true;
+ false ->
+ put(class_default_type,[{Operation,Name}|GeneratedList]),
+ false
+ end
+ end.
+
+get_class_fields(#classdef{typespec=ObjClass}) ->
+ ObjClass#objectclass.fields;
+get_class_fields(#objectclass{fields=Fields}) ->
+ Fields;
+get_class_fields(_) ->
+ [].
+
+
+get_object_field(Name,ObjectFields) ->
+ case lists:keysearch(Name,1,ObjectFields) of
+ {value,Field} -> Field;
+ false -> false
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_per_rt2ct.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_per_rt2ct.erl
new file mode 100644
index 0000000000..ddfa124048
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_per_rt2ct.erl
@@ -0,0 +1,1811 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1ct_gen_per_rt2ct.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
+%%
+-module(asn1ct_gen_per_rt2ct).
+
+%% Generate erlang module which handles (PER) encode and decode for
+%% all types in an ASN.1 module
+
+-include("asn1_records.hrl").
+%-compile(export_all).
+
+-export([pgen/4,gen_dec_prim/3,gen_encode_prim/4]).
+-export([gen_obj_code/3,gen_objectset_code/2]).
+-export([gen_decode/2, gen_decode/3]).
+-export([gen_encode/2, gen_encode/3]).
+
+-import(asn1ct_gen, [emit/1,demit/1]).
+-import(asn1ct_gen_per, [is_already_generated/2,more_genfields/1,
+ get_class_fields/1,get_object_field/2]).
+
+%% pgen(Erules, Module, TypeOrVal)
+%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module
+%% .hrl file is only generated if necessary
+%% Erules = per | ber
+%% Module = atom()
+%% TypeOrVal = {TypeList,ValueList}
+%% TypeList = ValueList = [atom()]
+
+pgen(OutFile,Erules,Module,TypeOrVal) ->
+ asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,true).
+
+
+%% Generate ENCODING ******************************
+%%****************************************x
+
+
+gen_encode(Erules,Type) when record(Type,typedef) ->
+ gen_encode_user(Erules,Type).
+
+gen_encode(Erules,Typename,#'ComponentType'{name=Cname,typespec=Type}) ->
+ NewTypename = [Cname|Typename],
+ gen_encode(Erules,NewTypename,Type);
+
+gen_encode(Erules,Typename,Type) when record(Type,type) ->
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ ObjFun =
+ case lists:keysearch(objfun,1,Type#type.tablecinf) of
+ {value,{_,_Name}} ->
+ ", ObjFun";
+ false ->
+ ""
+ end,
+ case asn1ct_gen:type(InnerType) of
+ {constructed,bif} ->
+ case InnerType of
+ 'SET' ->
+ true;
+ 'SEQUENCE' ->
+ true;
+ _ ->
+ emit({nl,"'enc_",asn1ct_gen:list2name(Typename),
+ "'({'",asn1ct_gen:list2name(Typename),
+ "',Val}",ObjFun,") ->",nl}),
+ emit({"'enc_",asn1ct_gen:list2name(Typename),
+ "'(Val",ObjFun,");",nl,nl})
+ end,
+ emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val",ObjFun,
+ ") ->",nl}),
+ asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
+ _ ->
+ true
+ end.
+
+
+gen_encode_user(Erules,D) when record(D,typedef) ->
+ CurrMod = get(currmod),
+ Typename = [D#typedef.name],
+ Def = D#typedef.typespec,
+ InnerType = asn1ct_gen:get_inner(Def#type.def),
+ case InnerType of
+ 'SET' -> true;
+ 'SEQUENCE' -> true;
+ _ ->
+ emit({nl,"'enc_",asn1ct_gen:list2name(Typename),"'({'",asn1ct_gen:list2name(Typename),"',Val}) ->",nl}),
+ emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val);",nl,nl})
+ end,
+ emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val) ->",nl}),
+ case asn1ct_gen:type(InnerType) of
+ {primitive,bif} ->
+ gen_encode_prim(Erules,Def,"false"),
+ emit({".",nl});
+ 'ASN1_OPEN_TYPE' ->
+ gen_encode_prim(Erules,Def#type{def='ASN1_OPEN_TYPE'},"false"),
+ emit({".",nl});
+ {constructed,bif} ->
+ asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,D);
+ #'Externaltypereference'{module=CurrMod,type=Etype} ->
+ emit({"'enc_",Etype,"'(Val).",nl,nl});
+ #'Externaltypereference'{module=Emod,type=Etype} ->
+ emit({"'",Emod,"':'enc_",Etype,"'(Val).",nl,nl});
+ #typereference{val=Ename} ->
+ emit({"'enc_",Ename,"'(Val).",nl,nl});
+ {notype,_} ->
+ emit({"'enc_",InnerType,"'(Val).",nl,nl})
+ end.
+
+
+gen_encode_prim(Erules,D,DoTag) ->
+ Value = case asn1ct_name:active(val) of
+ true ->
+ asn1ct_gen:mk_var(asn1ct_name:curr(val));
+ false ->
+ "Val"
+ end,
+ gen_encode_prim(Erules,D,DoTag,Value).
+
+
+
+
+
+gen_encode_prim(_Erules,D,_DoTag,Value) when record(D,type) ->
+ Constraint = D#type.constraint,
+ case D#type.def of
+ 'INTEGER' ->
+ EffectiveConstr = effective_constraint(integer,Constraint),
+ emit([" %%INTEGER with effective constraint: ",
+ {asis,EffectiveConstr},nl]),
+ emit_enc_integer(EffectiveConstr,Value);
+ {'INTEGER',NamedNumberList} ->
+ EffectiveConstr = effective_constraint(integer,Constraint),
+ %% maybe an emit_enc_NNL_integer
+ emit([" %%INTEGER with effective constraint: ",
+ {asis,EffectiveConstr},nl]),
+ emit_enc_integer_NNL(EffectiveConstr,Value,NamedNumberList);
+ {'ENUMERATED',{Nlist1,Nlist2}} ->
+ NewList = lists:concat([[{0,X}||{X,_} <- Nlist1],['EXT_MARK'],[{1,X}||{X,_} <- Nlist2]]),
+ NewC = [{'ValueRange',{0,length(Nlist1)-1}}],
+ emit(["case (case ",Value," of {_,_}->element(2,",Value,");_->",
+ Value," end) of",nl]),
+ emit_enc_enumerated_cases(NewC, NewList++[{asn1_enum,length(Nlist1)-1}], 0);
+ {'ENUMERATED',NamedNumberList} ->
+ NewList = [X||{X,_} <- NamedNumberList],
+ NewC = effective_constraint(integer,
+ [{'ValueRange',
+ {0,length(NewList)-1}}]),
+ NewVal = enc_enum_cases(Value,NewList),
+ emit_enc_integer(NewC,NewVal);
+ {'BIT STRING',NamedNumberList} ->
+ EffectiveC = effective_constraint(bitstring,Constraint),
+ case EffectiveC of
+ 0 -> emit({"[]"});
+ _ ->
+ emit({"?RT_PER:encode_bit_string(",
+ {asis,EffectiveC},",",Value,",",
+ {asis,NamedNumberList},")"})
+ end;
+ 'NULL' ->
+ emit({"?RT_PER:encode_null(",Value,")"});
+ 'OBJECT IDENTIFIER' ->
+ emit({"?RT_PER:encode_object_identifier(",Value,")"});
+ 'ObjectDescriptor' ->
+ emit({"?RT_PER:encode_ObjectDescriptor(",{asis,Constraint},
+ ",",Value,")"});
+ 'BOOLEAN' ->
+% emit({"?RT_PER:encode_boolean(",Value,")"});
+ emit({"case ",Value," of",nl,
+% " true -> {bits,1,1};",nl,
+ " true -> [1];",nl,
+% " false -> {bits,1,0};",nl,
+ " false -> [0];",nl,
+ " _ -> exit({error,{asn1,{encode_boolean,",Value,"}}})",nl,
+ "end"});
+ 'OCTET STRING' ->
+ emit_enc_octet_string(Constraint,Value);
+
+ 'NumericString' ->
+ emit_enc_known_multiplier_string('NumericString',Constraint,Value);
+ 'TeletexString' ->
+ emit({"?RT_PER:encode_TeletexString(",{asis,Constraint},",",Value,")"});
+ 'VideotexString' ->
+ emit({"?RT_PER:encode_VideotexString(",{asis,Constraint},",",Value,")"});
+ 'UTCTime' ->
+ emit_enc_known_multiplier_string('VisibleString',Constraint,Value);
+ 'GeneralizedTime' ->
+ emit_enc_known_multiplier_string('VisibleString',Constraint,Value);
+ 'GraphicString' ->
+ emit({"?RT_PER:encode_GraphicString(",{asis,Constraint},",",Value,")"});
+ 'VisibleString' ->
+ emit_enc_known_multiplier_string('VisibleString',Constraint,Value);
+ 'GeneralString' ->
+ emit({"?RT_PER:encode_GeneralString(",{asis,Constraint},",",Value,")"});
+ 'PrintableString' ->
+ emit_enc_known_multiplier_string('PrintableString',Constraint,Value);
+ 'IA5String' ->
+ emit_enc_known_multiplier_string('IA5String',Constraint,Value);
+ 'BMPString' ->
+ emit_enc_known_multiplier_string('BMPString',Constraint,Value);
+ 'UniversalString' ->
+ emit_enc_known_multiplier_string('UniversalString',Constraint,Value);
+ 'ANY' ->
+ emit(["?RT_PER:encode_open_type(", {asis,Constraint}, ",",
+ Value, ")"]);
+ 'ASN1_OPEN_TYPE' ->
+ NewValue = case Constraint of
+ [#'Externaltypereference'{type=Tname}] ->
+ io_lib:format(
+ "?RT_PER:complete(enc_~s(~s))",[Tname,Value]);
+ [#type{def=#'Externaltypereference'{type=Tname}}] ->
+ io_lib:format(
+ "?RT_PER:complete(enc_~s(~s))",[Tname,Value]);
+ _ -> Value
+ end,
+ emit(["?RT_PER:encode_open_type(", {asis,Constraint}, ",",
+ NewValue, ")"]);
+ XX ->
+ exit({asn1_error,nyi,XX})
+ end.
+
+emit_enc_known_multiplier_string(StringType,C,Value) ->
+ SizeC =
+ case get_constraint(C,'SizeConstraint') of
+ L when list(L) -> {lists:min(L),lists:max(L)};
+ L -> L
+ end,
+ PAlphabC = get_constraint(C,'PermittedAlphabet'),
+ case {StringType,PAlphabC} of
+ {'UniversalString',{_,_}} ->
+ exit({error,{asn1,{'not implemented',"UniversalString with "
+ "PermittedAlphabet constraint"}}});
+ {'BMPString',{_,_}} ->
+ exit({error,{asn1,{'not implemented',"BMPString with "
+ "PermittedAlphabet constraint"}}});
+ _ -> ok
+ end,
+ NumBits = get_NumBits(C,StringType),
+ CharOutTab = get_CharOutTab(C,StringType),
+ %% NunBits and CharOutTab for chars_encode
+ emit_enc_k_m_string(StringType,SizeC,NumBits,CharOutTab,Value).
+
+emit_enc_k_m_string(_StringType,0,_NumBits,_CharOutTab,_Value) ->
+ emit({"[]"});
+emit_enc_k_m_string(StringType,SizeC,NumBits,CharOutTab,Value) ->
+ emit({"?RT_PER:encode_known_multiplier_string(",{asis,StringType},",",
+ {asis,SizeC},",",NumBits,",",{asis,CharOutTab},",",Value,")"}).
+
+emit_dec_known_multiplier_string(StringType,C,BytesVar) ->
+ SizeC = get_constraint(C,'SizeConstraint'),
+ PAlphabC = get_constraint(C,'PermittedAlphabet'),
+ case {StringType,PAlphabC} of
+ {'BMPString',{_,_}} ->
+ exit({error,{asn1,
+ {'not implemented',
+ "BMPString with PermittedAlphabet "
+ "constraint"}}});
+ _ ->
+ ok
+ end,
+ NumBits = get_NumBits(C,StringType),
+ CharInTab = get_CharInTab(C,StringType),
+ case SizeC of
+ 0 ->
+ emit({"{[],",BytesVar,"}"});
+ _ ->
+ emit({"?RT_PER:decode_known_multiplier_string(",
+ {asis,StringType},",",{asis,SizeC},",",NumBits,
+ ",",{asis,CharInTab},",",BytesVar,")"})
+ end.
+
+
+%% copied from run time module
+
+get_CharOutTab(C,StringType) ->
+ get_CharTab(C,StringType,out).
+
+get_CharInTab(C,StringType) ->
+ get_CharTab(C,StringType,in).
+
+get_CharTab(C,StringType,InOut) ->
+ case get_constraint(C,'PermittedAlphabet') of
+ {'SingleValue',Sv} ->
+ get_CharTab2(C,StringType,hd(Sv),lists:max(Sv),Sv,InOut);
+ no ->
+ case StringType of
+ 'IA5String' ->
+ {0,16#7F,notab};
+ 'VisibleString' ->
+ get_CharTab2(C,StringType,16#20,16#7F,notab,InOut);
+ 'PrintableString' ->
+ Chars = lists:sort(
+ " '()+,-./0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
+ get_CharTab2(C,StringType,hd(Chars),lists:max(Chars),Chars,InOut);
+ 'NumericString' ->
+ get_CharTab2(C,StringType,16#20,$9," 0123456789",InOut);
+ 'UniversalString' ->
+ {0,16#FFFFFFFF,notab};
+ 'BMPString' ->
+ {0,16#FFFF,notab}
+ end
+ end.
+
+get_CharTab2(C,StringType,Min,Max,Chars,InOut) ->
+ BitValMax = (1 bsl get_NumBits(C,StringType))-1,
+ if
+ Max =< BitValMax ->
+ {0,Max,notab};
+ true ->
+ case InOut of
+ out ->
+ {Min,Max,create_char_tab(Min,Chars)};
+ in ->
+ {Min,Max,list_to_tuple(Chars)}
+ end
+ end.
+
+create_char_tab(Min,L) ->
+ list_to_tuple(create_char_tab(Min,L,0)).
+create_char_tab(Min,[Min|T],V) ->
+ [V|create_char_tab(Min+1,T,V+1)];
+create_char_tab(_Min,[],_V) ->
+ [];
+create_char_tab(Min,L,V) ->
+ [false|create_char_tab(Min+1,L,V)].
+
+get_NumBits(C,StringType) ->
+ case get_constraint(C,'PermittedAlphabet') of
+ {'SingleValue',Sv} ->
+ charbits(length(Sv),aligned);
+ no ->
+ case StringType of
+ 'IA5String' ->
+ charbits(128,aligned); % 16#00..16#7F
+ 'VisibleString' ->
+ charbits(95,aligned); % 16#20..16#7E
+ 'PrintableString' ->
+ charbits(74,aligned); % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
+ 'NumericString' ->
+ charbits(11,aligned); % $ ,"0123456789"
+ 'UniversalString' ->
+ 32;
+ 'BMPString' ->
+ 16
+ end
+ end.
+
+charbits(NumOfChars,aligned) ->
+ case charbits(NumOfChars) of
+ 1 -> 1;
+ 2 -> 2;
+ B when B =< 4 -> 4;
+ B when B =< 8 -> 8;
+ B when B =< 16 -> 16;
+ B when B =< 32 -> 32
+ end.
+
+charbits(NumOfChars) when NumOfChars =< 2 -> 1;
+charbits(NumOfChars) when NumOfChars =< 4 -> 2;
+charbits(NumOfChars) when NumOfChars =< 8 -> 3;
+charbits(NumOfChars) when NumOfChars =< 16 -> 4;
+charbits(NumOfChars) when NumOfChars =< 32 -> 5;
+charbits(NumOfChars) when NumOfChars =< 64 -> 6;
+charbits(NumOfChars) when NumOfChars =< 128 -> 7;
+charbits(NumOfChars) when NumOfChars =< 256 -> 8;
+charbits(NumOfChars) when NumOfChars =< 512 -> 9;
+charbits(NumOfChars) when NumOfChars =< 1024 -> 10;
+charbits(NumOfChars) when NumOfChars =< 2048 -> 11;
+charbits(NumOfChars) when NumOfChars =< 4096 -> 12;
+charbits(NumOfChars) when NumOfChars =< 8192 -> 13;
+charbits(NumOfChars) when NumOfChars =< 16384 -> 14;
+charbits(NumOfChars) when NumOfChars =< 32768 -> 15;
+charbits(NumOfChars) when NumOfChars =< 65536 -> 16;
+charbits(NumOfChars) when integer(NumOfChars) ->
+ 16 + charbits1(NumOfChars bsr 16).
+
+charbits1(0) ->
+ 0;
+charbits1(NumOfChars) ->
+ 1 + charbits1(NumOfChars bsr 1).
+
+%% copied from run time module
+
+emit_enc_octet_string(Constraint,Value) ->
+ case get_constraint(Constraint,'SizeConstraint') of
+ 0 ->
+ emit({" []"});
+ 1 ->
+ asn1ct_name:new(tmpval),
+ emit({" begin",nl}),
+ emit({" [",{curr,tmpval},"] = ",Value,",",nl}),
+% emit({" {bits,8,",{curr,tmpval},"}",nl}),
+ emit({" [10,8,",{curr,tmpval},"]",nl}),
+ emit(" end");
+ 2 ->
+ asn1ct_name:new(tmpval),
+ emit({" begin",nl}),
+ emit({" [",{curr,tmpval},",",{next,tmpval},"] = ",
+ Value,",",nl}),
+% emit({" [{bits,8,",{curr,tmpval},"},{bits,8,",
+% {next,tmpval},"}]",nl}),
+ emit({" [[10,8,",{curr,tmpval},"],[10,8,",
+ {next,tmpval},"]]",nl}),
+ emit(" end"),
+ asn1ct_name:new(tmpval);
+ Sv when integer(Sv),Sv =< 256 ->
+ asn1ct_name:new(tmpval),
+ emit({" begin",nl}),
+% emit({" case length(",Value,") == ",Sv," of",nl}),
+ emit({" case length(",Value,") of",nl}),
+ emit({" ",{curr,tmpval}," when ",{curr,tmpval}," == ",Sv," -> [2,20,",{curr,tmpval},",",Value,"];",nl}),
+ emit({" _ -> exit({error,{value_out_of_bounds,",Value,"}})",
+ nl," end",nl}),
+ emit(" end");
+ Sv when integer(Sv),Sv =< 65535 ->
+ asn1ct_name:new(tmpval),
+ emit({" begin",nl}),
+% emit({" case length(",Value,") == ",Sv," of",nl}),
+ emit({" case length(",Value,") of",nl}),
+% emit({" true -> [align,{octets,",Value,"}];",nl}),
+ emit({" ",{curr,tmpval}," when ",{curr,tmpval}," == ",Sv," -> [2,21,",{curr,tmpval},",",Value,"];",nl}),
+ emit({" _ -> exit({error,{value_out_of_bounds,",Value,"}})",
+ nl," end",nl}),
+ emit(" end");
+ C ->
+ emit({" ?RT_PER:encode_octet_string(",{asis,C},",false,",Value,")",nl})
+ end.
+
+emit_dec_octet_string(Constraint,BytesVar) ->
+ case get_constraint(Constraint,'SizeConstraint') of
+ 0 ->
+ emit({" {[],",BytesVar,"}",nl});
+ {_,0} ->
+ emit({" {[],",BytesVar,"}",nl});
+ C ->
+ emit({" ?RT_PER:decode_octet_string(",BytesVar,",",
+ {asis,C},",false)",nl})
+ end.
+
+emit_enc_integer_case(Value) ->
+ case get(component_type) of
+ {true,#'ComponentType'{prop=Prop}} ->
+ emit({" begin",nl}),
+ case Prop of
+ Opt when Opt=='OPTIONAL';
+ tuple(Opt),element(1,Opt)=='DEFAULT' ->
+ emit({" case ",Value," of",nl}),
+ ok;
+ _ ->
+ emit({" ",{curr,tmpval},"=",Value,",",nl}),
+ emit({" case ",{curr,tmpval}," of",nl}),
+ asn1ct_name:new(tmpval)
+ end;
+% asn1ct_name:new(tmpval);
+ _ ->
+ emit({" case ",Value," of ",nl})
+ end.
+emit_enc_integer_end_case() ->
+ case get(component_type) of
+ {true,_} ->
+ emit({nl," end"}); % end of begin ... end
+ _ -> ok
+ end.
+
+
+emit_enc_integer_NNL(C,Value,NNL) ->
+ EncVal = enc_integer_NNL_cases(Value,NNL),
+ emit_enc_integer(C,EncVal).
+
+enc_integer_NNL_cases(Value,NNL) ->
+ asn1ct_name:new(tmpval),
+ TmpVal = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)),
+ Cases=enc_integer_NNL_cases1(NNL),
+ lists:flatten(io_lib:format("(case ~s of "++Cases++
+ "~s when atom(~s)->exit({error,{asn1,{namednumber,~s}}});_->~s end)",[Value,TmpVal,TmpVal,TmpVal,Value])).
+
+enc_integer_NNL_cases1([{NNo,No}|Rest]) ->
+ io_lib:format("~w->~w;",[NNo,No])++enc_integer_NNL_cases1(Rest);
+enc_integer_NNL_cases1([]) ->
+ "".
+
+emit_enc_integer([{'SingleValue',Int}],Value) ->
+ asn1ct_name:new(tmpval),
+ emit_enc_integer_case(Value),% emit([" case ",Value," of",nl]),
+ emit([" ",Int," -> [];",nl]),
+ emit([" ",{curr,tmpval}," ->",nl]),
+ emit([" exit({error,{value_out_of_bounds,",{curr,tmpval},"}})",
+ nl," end",nl]),
+ emit_enc_integer_end_case();
+
+emit_enc_integer([{_,{Lb,Ub},_Range,{bits,NoBs}}],Value) -> % Range =< 255
+ asn1ct_name:new(tmpval),
+ emit_enc_integer_case(Value),
+ emit([" ",{curr,tmpval}," when ",{curr,tmpval},"=<",Ub,",",
+ {curr,tmpval},">=",Lb," ->",nl]),
+ emit([" [10,",NoBs,",",{curr,tmpval},"-",Lb,"];",nl]),
+ emit([" ",{curr,tmpval}," ->",nl]),
+ emit([" exit({error,{value_out_of_bounds,",{curr,tmpval},"}})",
+ nl," end",nl]),
+ emit_enc_integer_end_case();
+
+emit_enc_integer([{_,{Lb,Ub},Range,_}],Value) when Range =< 256 ->
+ asn1ct_name:new(tmpval),
+ emit_enc_integer_case(Value),
+ emit([" ",{curr,tmpval}," when ",{curr,tmpval},"=<",Ub,",",
+ {curr,tmpval},">=",Lb," ->",nl]),
+ emit([" [20,1,",{curr,tmpval},"-",Lb,"];",nl]),
+ emit([" ",{curr,tmpval}," ->",nl]),
+ emit([" exit({error,{value_out_of_bounds,",{curr,tmpval},"}})",
+ nl," end",nl]),
+ emit_enc_integer_end_case();
+
+emit_enc_integer([{_,{Lb,Ub},Range,_}],Value) when Range =< 65536 ->
+ asn1ct_name:new(tmpval),
+ emit_enc_integer_case(Value),
+ emit([" ",{curr,tmpval}," when ",{curr,tmpval},"=<",Ub,",",
+ {curr,tmpval},">=",Lb," ->",nl]),
+ emit([" [20,2,<<(",{curr,tmpval},"-",Lb,"):16>>];",nl]),
+ emit([" ",{curr,tmpval}," ->",nl]),
+ emit([" exit({error,{value_out_of_bounds,",{curr,tmpval},"}})",
+ nl," end",nl]),
+ emit_enc_integer_end_case();
+
+
+emit_enc_integer(C,Value) ->
+ emit({" ?RT_PER:encode_integer(",{asis,C},",",Value,")"}).
+
+
+
+
+enc_enum_cases(Value,NewList) ->
+ asn1ct_name:new(tmpval),
+ TmpVal = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)),
+ Cases=enc_enum_cases1(NewList),
+ lists:flatten(io_lib:format("(case ~s of "++Cases++
+ "~s ->exit({error,"
+ "{asn1,{enumerated,~s}}})"
+ " end)",
+ [Value,TmpVal,TmpVal])).
+enc_enum_cases1(NNL) ->
+ enc_enum_cases1(NNL,0).
+enc_enum_cases1([H|T],Index) ->
+ io_lib:format("~w->~w;",[H,Index])++enc_enum_cases1(T,Index+1);
+enc_enum_cases1([],_) ->
+ "".
+
+
+emit_enc_enumerated_cases(C, [H], Count) ->
+ emit_enc_enumerated_case(C, H, Count),
+ emit([";",nl,"EnumVal -> exit({error,{asn1, {enumerated_not_in_range, EnumVal}}})"]),
+ emit([nl,"end"]);
+emit_enc_enumerated_cases(C, ['EXT_MARK'|T], _Count) ->
+ emit_enc_enumerated_cases(C, T, 0);
+emit_enc_enumerated_cases(C, [H1,H2|T], Count) ->
+ emit_enc_enumerated_case(C, H1, Count),
+ emit([";",nl]),
+ emit_enc_enumerated_cases(C, [H2|T], Count+1).
+
+
+%% The function clauses matching on tuples with first element
+%% asn1_enum, 1 or 0 and the atom 'EXT_MARK' are for ENUMERATED
+%% with extension mark.
+emit_enc_enumerated_case(_C, {asn1_enum,High}, _) ->
+ %% ENUMERATED with extensionmark
+ %% value higher than the extension base and not
+ %% present in the extension range.
+ emit(["{asn1_enum,EnumV} when integer(EnumV), EnumV > ",High," -> ",
+ "[1,?RT_PER:encode_small_number(EnumV)]"]);
+emit_enc_enumerated_case(_C, 'EXT_MARK', _Count) ->
+ %% ENUMERATED with extensionmark
+ true;
+emit_enc_enumerated_case(_C, {1,EnumName}, Count) ->
+ %% ENUMERATED with extensionmark
+ %% values higher than extension root
+ emit(["'",EnumName,"' -> [1,?RT_PER:encode_small_number(",Count,")]"]);
+emit_enc_enumerated_case(C, {0,EnumName}, Count) ->
+ %% ENUMERATED with extensionmark
+ %% values within extension root
+ emit(["'",EnumName,"' -> [0,?RT_PER:encode_integer(",{asis,C},", ",Count,")]"]);
+
+%% This clause is invoked in case of an ENUMERATED without extension mark
+emit_enc_enumerated_case(_C, EnumName, Count) ->
+ emit(["'",EnumName,"' -> ",Count]).
+
+
+get_constraint([{Key,V}],Key) ->
+ V;
+get_constraint([],_) ->
+ no;
+get_constraint(C,Key) ->
+ case lists:keysearch(Key,1,C) of
+ false ->
+ no;
+ {value,{_,V}} ->
+ V
+ end.
+
+get_constraints(L=[{Key,_}],Key) ->
+ L;
+get_constraints([],_) ->
+ [];
+get_constraints(C,Key) ->
+ {value,L} = keysearch_allwithkey(Key,1,C,[]),
+ L.
+
+keysearch_allwithkey(Key,Ix,C,Acc) ->
+ case lists:keysearch(Key,Ix,C) of
+ false ->
+ {value,Acc};
+ {value,T} ->
+ RestC = lists:delete(T,C),
+ keysearch_allwithkey(Key,Ix,RestC,[T|Acc])
+ end.
+
+%% effective_constraint(Type,C)
+%% Type = atom()
+%% C = [C1,...]
+%% C1 = {'SingleValue',SV} | {'ValueRange',VR} | {atom(),term()}
+%% SV = integer() | [integer(),...]
+%% VR = {Lb,Ub}
+%% Lb = 'MIN' | integer()
+%% Ub = 'MAX' | integer()
+%% Returns a single value if C only has a single value constraint, and no
+%% value range constraints, that constrains to a single value, otherwise
+%% returns a value range that has the lower bound set to the lowest value
+%% of all single values and lower bound values in C and the upper bound to
+%% the greatest value.
+effective_constraint(integer,[C={{_,_},_}|_Rest]) -> % extension
+ [C]; %% [C|effective_constraint(integer,Rest)]; XXX what is possible ???
+effective_constraint(integer,C) ->
+ SVs = get_constraints(C,'SingleValue'),
+ SV = effective_constr('SingleValue',SVs),
+ VRs = get_constraints(C,'ValueRange'),
+ VR = effective_constr('ValueRange',VRs),
+ CRange = greatest_common_range(SV,VR),
+ pre_encode(integer,CRange);
+effective_constraint(bitstring,C) ->
+% Constr=get_constraints(C,'SizeConstraint'),
+% case Constr of
+% [] -> no;
+% [{'SizeConstraint',Val}] -> Val;
+% Other -> Other
+% end;
+ get_constraint(C,'SizeConstraint');
+effective_constraint(Type,C) ->
+ io:format("Effective constraint for ~p, not implemented yet.~n",[Type]),
+ C.
+
+effective_constr(_,[]) ->
+ [];
+effective_constr('SingleValue',List) ->
+ SVList = lists:flatten(lists:map(fun(X)->element(2,X)end,List)),
+ case lists:usort(SVList) of
+ [N] ->
+ [{'SingleValue',N}];
+ L when list(L) ->
+ [{'ValueRange',{hd(L),lists:last(L)}}]
+ end;
+effective_constr('ValueRange',List) ->
+ LBs = lists:map(fun({_,{Lb,_}})-> Lb end,List),
+ UBs = lists:map(fun({_,{_,Ub}})-> Ub end,List),
+ Lb = least_Lb(LBs),
+ [{'ValueRange',{Lb,lists:max(UBs)}}].
+
+greatest_common_range([],VR) ->
+ VR;
+greatest_common_range(SV,[]) ->
+ SV;
+greatest_common_range([{_,Int}],[{_,{'MIN',Ub}}]) when integer(Int),
+ Int > Ub ->
+ [{'ValueRange',{'MIN',Int}}];
+greatest_common_range([{_,Int}],[{_,{Lb,Ub}}]) when integer(Int),
+ Int < Lb ->
+ [{'ValueRange',{Int,Ub}}];
+greatest_common_range([{_,Int}],VR=[{_,{_Lb,_Ub}}]) when integer(Int) ->
+ VR;
+greatest_common_range([{_,L}],[{_,{Lb,Ub}}]) when list(L) ->
+ Min = least_Lb([Lb|L]),
+ Max = greatest_Ub([Ub|L]),
+ [{'ValueRange',{Min,Max}}].
+
+
+least_Lb(L) ->
+ case lists:member('MIN',L) of
+ true -> 'MIN';
+ _ -> lists:min(L)
+ end.
+
+greatest_Ub(L) ->
+ case lists:member('MAX',L) of
+ true -> 'MAX';
+ _ -> lists:max(L)
+ end.
+
+% effective_constraint1('SingleValue',List) ->
+% SVList = lists:map(fun(X)->element(2,X)end,List),
+% sv_effective_constraint(hd(SVList),tl(SVList));
+% effective_constraint1('ValueRange',List) ->
+% VRList = lists:map(fun(X)->element(2,X)end,List),
+% vr_effective_constraint(lists:map(fun(X)->element(1,X)end,VRList),
+% lists:map(fun(X)->element(2,X)end,VRList)).
+
+%% vr_effective_constraint/2
+%% Gets all LowerEndPoints and UpperEndPoints as arguments
+%% Returns {'ValueRange',{Lb,Ub}} where Lb is the highest value of
+%% the LowerEndPoints and Ub is the lowest value of the UpperEndPoints,
+%% i.e. the intersection of all value ranges.
+% vr_effective_constraint(Mins,Maxs) ->
+% Lb=lists:foldl(fun(X,'MIN') when integer(X) -> X;
+% (X,'MIN') -> 'MIN';
+% (X,AccIn) when integer(X),X >= AccIn -> X;
+% (X,AccIn) -> AccIn
+% end,hd(Mins),tl(Mins)),
+% Ub = lists:min(Maxs),
+% {'ValueRange',{Lb,Ub}}.
+
+
+% sv_effective_constraint(SV,[]) ->
+% {'SingleValue',SV};
+% sv_effective_constraint([],_) ->
+% exit({error,{asn1,{illegal_single_value_constraint}}});
+% sv_effective_constraint(SV,[SV|Rest]) ->
+% sv_effective_constraint(SV,Rest);
+% sv_effective_constraint(Int,[SV|Rest]) when integer(Int),list(SV) ->
+% case lists:member(Int,SV) of
+% true ->
+% sv_effective_constraint(Int,Rest);
+% _ ->
+% exit({error,{asn1,{illegal_single_value_constraint}}})
+% end;
+% sv_effective_constraint(SV,[Int|Rest]) when integer(Int),list(SV) ->
+% case lists:member(Int,SV) of
+% true ->
+% sv_effective_constraint(Int,Rest);
+% _ ->
+% exit({error,{asn1,{illegal_single_value_constraint}}})
+% end;
+% sv_effective_constraint(SV1,[SV2|Rest]) when list(SV1),list(SV2) ->
+% sv_effective_constraint(common_set(SV1,SV2),Rest);
+% sv_effective_constraint(_,_) ->
+% exit({error,{asn1,{illegal_single_value_constraint}}}).
+
+%% common_set/2
+%% Two lists as input
+%% Returns the list with all elements that are common for both
+%% input lists
+% common_set(SV1,SV2) ->
+% lists:filter(fun(X)->lists:member(X,SV1) end,SV2).
+
+
+
+pre_encode(integer,[]) ->
+ [];
+pre_encode(integer,C=[{'SingleValue',_}]) ->
+ C;
+pre_encode(integer,C=[{'ValueRange',VR={Lb,Ub}}]) when integer(Lb),integer(Ub)->
+ Range = Ub-Lb+1,
+ if
+ Range =< 255 ->
+ NoBits = no_bits(Range),
+ [{'ValueRange',VR,Range,{bits,NoBits}}];
+ Range =< 256 ->
+ [{'ValueRange',VR,Range,{octets,1}}];
+ Range =< 65536 ->
+ [{'ValueRange',VR,Range,{octets,2}}];
+ true ->
+ C
+ end;
+pre_encode(integer,C) ->
+ C.
+
+no_bits(2) -> 1;
+no_bits(N) when N=<4 -> 2;
+no_bits(N) when N=<8 -> 3;
+no_bits(N) when N=<16 -> 4;
+no_bits(N) when N=<32 -> 5;
+no_bits(N) when N=<64 -> 6;
+no_bits(N) when N=<128 -> 7;
+no_bits(N) when N=<255 -> 8.
+
+%% Object code generating for encoding and decoding
+%% ------------------------------------------------
+
+gen_obj_code(Erules,_Module,Obj) when record(Obj,typedef) ->
+ ObjName = Obj#typedef.name,
+ Def = Obj#typedef.typespec,
+ #'Externaltypereference'{module=Mod,type=ClassName} =
+ Def#'Object'.classname,
+ Class = asn1_db:dbget(Mod,ClassName),
+ {object,_,Fields} = Def#'Object'.def,
+ emit({nl,nl,nl,"%%================================"}),
+ emit({nl,"%% ",ObjName}),
+ emit({nl,"%%================================",nl}),
+ EncConstructed =
+% gen_encode_objectfields(Class#classdef.typespec,ObjName,Fields,[]),
+ gen_encode_objectfields(ClassName,get_class_fields(Class),
+ ObjName,Fields,[]),
+ emit(nl),
+ gen_encode_constr_type(Erules,EncConstructed),
+ emit(nl),
+ DecConstructed =
+% gen_decode_objectfields(Class#classdef.typespec,ObjName,Fields,[]),
+ gen_decode_objectfields(ClassName,get_class_fields(Class),
+ ObjName,Fields,[]),
+ emit(nl),
+ gen_decode_constr_type(Erules,DecConstructed),
+ emit(nl);
+gen_obj_code(_Erules,_Module,Obj) when record(Obj,pobjectdef) ->
+ ok.
+
+gen_encode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
+ ObjName,ObjectFields,ConstrAcc) ->
+ EmitFuncClause =
+ fun(V) ->
+ emit(["'enc_",ObjName,"'(",{asis,Name},
+ ",",V,",_RestPrimFieldName) ->",nl])
+ end,
+% emit(["'enc_",ObjName,"'(",{asis,Name},
+% ", Val, RestPrimFieldName) ->",nl]),
+ MaybeConstr =
+ case {get_object_field(Name,ObjectFields),OptOrMand} of
+ {false,'MANDATORY'} -> %% this case is illegal
+ exit({error,{asn1,{"missing mandatory field in object",
+ ObjName}}});
+ {false,'OPTIONAL'} ->
+ EmitFuncClause("_"),
+ emit(" <<>>"),
+ [];
+ {false,{'DEFAULT',DefaultType}} ->
+ EmitFuncClause("Val"),
+ gen_encode_default_call(ClassName,Name,DefaultType);
+ {{Name,TypeSpec},_} ->
+ %% A specified field owerwrites any 'DEFAULT' or
+ %% 'OPTIONAL' field in the class
+ EmitFuncClause("Val"),
+ gen_encode_field_call(ObjName,Name,TypeSpec)
+ end,
+ case more_genfields(Rest) of
+ true ->
+ emit([";",nl]);
+ false ->
+ emit([".",nl])
+ end,
+ gen_encode_objectfields(ClassName,Rest,ObjName,ObjectFields,
+ MaybeConstr++ConstrAcc);
+gen_encode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
+ ObjName,ObjectFields,ConstrAcc) ->
+ EmitFuncClause =
+ fun(Attrs) ->
+ emit(["'enc_",ObjName,"'(",{asis,Name},
+ ",",Attrs,") ->",nl])
+ end,
+% emit(["'enc_",ObjName,"'(",{asis,Name},
+% ", Val,[H|T]) ->",nl]),
+ case {get_object_field(Name,ObjectFields),OptOrMand} of
+ {false,'MANDATORY'} ->
+ exit({error,{asn1,{"missing mandatory field in object",
+ ObjName}}});
+ {false,'OPTIONAL'} ->
+ EmitFuncClause("_,_"),
+ emit([" exit({error,{'use of missing field in object', ",Name,
+ "}})"]);
+ {false,{'DEFAULT',_DefaultObject}} ->
+ exit({error,{asn1,{"not implemented yet",Name}}});
+ {{Name,TypeSpec},_} ->
+ EmitFuncClause("Val,[H|T]"),
+ case TypeSpec#typedef.name of
+ {ExtMod,TypeName} ->
+ emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
+ "'(H, Val, T)"});
+ TypeName ->
+ emit({indent(3),"'enc_",TypeName,"'(H, Val, T)"})
+ end
+ end,
+ case more_genfields(Rest) of
+ true ->
+ emit([";",nl]);
+ false ->
+ emit([".",nl])
+ end,
+ gen_encode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
+gen_encode_objectfields(ClassName,[_C|Cs],O,OF,Acc) ->
+ gen_encode_objectfields(ClassName,Cs,O,OF,Acc);
+gen_encode_objectfields(_,[],_,_,Acc) ->
+ Acc.
+
+% gen_encode_objectfields(Class,ObjName,[{FieldName,Type}|Rest],ConstrAcc) ->
+% Fields = Class#objectclass.fields,
+
+% MaybeConstr =
+% case is_typefield(Fields,FieldName) of
+% true ->
+% Def = Type#typedef.typespec,
+% emit({"'enc_",ObjName,"'(",{asis,FieldName},
+% ", Val, Dummy) ->",nl}),
+
+% CAcc =
+% case Type#typedef.name of
+% {primitive,bif} ->
+% gen_encode_prim(per,Def,"false","Val"),
+% [];
+% {constructed,bif} ->
+% emit({" 'enc_",ObjName,'_',FieldName,
+% "'(Val)"}),
+% [{['enc_',ObjName,'_',FieldName],Def}];
+% {ExtMod,TypeName} ->
+% emit({" '",ExtMod,"':'enc_",TypeName,"'(Val)"}),
+% [];
+% TypeName ->
+% emit({" 'enc_",TypeName,"'(Val)"}),
+% []
+% end,
+% case more_genfields(Fields,Rest) of
+% true ->
+% emit({";",nl});
+% false ->
+% emit({".",nl})
+% end,
+% CAcc;
+% {false,objectfield} ->
+% emit({"'enc_",ObjName,"'(",{asis,FieldName},
+% ", Val, [H|T]) ->",nl}),
+% case Type#typedef.name of
+% {ExtMod,TypeName} ->
+% emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
+% "'(H, Val, T)"});
+% TypeName ->
+% emit({indent(3),"'enc_",TypeName,"'(H, Val, T)"})
+% end,
+% case more_genfields(Fields,Rest) of
+% true ->
+% emit({";",nl});
+% false ->
+% emit({".",nl})
+% end,
+% [];
+% {false,_} -> []
+% end,
+% gen_encode_objectfields(Class,ObjName,Rest,MaybeConstr ++ ConstrAcc);
+% gen_encode_objectfields(C,O,[_|T],Acc) ->
+% gen_encode_objectfields(C,O,T,Acc);
+% gen_encode_objectfields(_,_,[],Acc) ->
+% Acc.
+
+gen_encode_constr_type(Erules,[TypeDef|Rest]) when record(TypeDef,typedef) ->
+ case is_already_generated(enc,TypeDef#typedef.name) of
+ true -> ok;
+ _ ->
+ Name = lists:concat(["enc_",TypeDef#typedef.name]),
+ emit({Name,"(Val) ->",nl}),
+ Def = TypeDef#typedef.typespec,
+ InnerType = asn1ct_gen:get_inner(Def#type.def),
+ asn1ct_gen:gen_encode_constructed(Erules,Name,InnerType,Def),
+ gen_encode_constr_type(Erules,Rest)
+ end;
+gen_encode_constr_type(_,[]) ->
+ ok.
+
+gen_encode_field_call(ObjName,FieldName,Type) ->
+ Def = Type#typedef.typespec,
+ case Type#typedef.name of
+ {primitive,bif} ->
+ gen_encode_prim(per,Def,"false",
+ "Val"),
+ [];
+ {constructed,bif} ->
+ emit({" 'enc_",ObjName,'_',FieldName,
+ "'(Val)"}),
+ [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
+ {ExtMod,TypeName} ->
+ emit({" '",ExtMod,"':'enc_",TypeName,
+ "'(Val)"}),
+ [];
+ TypeName ->
+ emit({" 'enc_",TypeName,"'(Val)"}),
+ []
+ end.
+
+gen_encode_default_call(ClassName,FieldName,Type) ->
+ CurrentMod = get(currmod),
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ case asn1ct_gen:type(InnerType) of
+ {constructed,bif} ->
+%% asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
+ emit([" 'enc_",ClassName,'_',FieldName,"'(Val)"]),
+ [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
+ typespec=Type}];
+ {primitive,bif} ->
+ gen_encode_prim(per,Type,"false","Val"),
+ [];
+ #'Externaltypereference'{module=CurrentMod,type=Etype} ->
+ emit([" 'enc_",Etype,"'(Val)",nl]),
+ [];
+ #'Externaltypereference'{module=Emod,type=Etype} ->
+ emit([" '",Emod,"':'enc_",Etype,"'(Val)",nl]),
+ []
+ end.
+
+
+
+gen_decode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
+ ObjName,ObjectFields,ConstrAcc) ->
+ EmitFuncClause =
+ fun(Bytes) ->
+ emit(["'dec_",ObjName,"'(",{asis,Name},",",Bytes,
+ ",_,_RestPrimFieldName) ->",nl])
+ end,
+% emit(["'dec_",ObjName,"'(",{asis,Name},
+% ", Bytes, _, RestPrimFieldName) ->",nl]),
+ MaybeConstr=
+ case {get_object_field(Name,ObjectFields),OptOrMand} of
+ {false,'MANDATORY'} -> %% this case is illegal
+ exit({error,{asn1,{"missing mandatory field in object",
+ ObjName}}});
+ {false,'OPTIONAL'} ->
+ EmitFuncClause("_"),
+ emit([" asn1_NOVALUE"]),
+ [];
+ {false,{'DEFAULT',DefaultType}} ->
+ EmitFuncClause("Bytes"),
+ gen_decode_default_call(ClassName,Name,"Bytes",DefaultType);
+ {{Name,TypeSpec},_} ->
+ %% A specified field owerwrites any 'DEFAULT' or
+ %% 'OPTIONAL' field in the class
+ EmitFuncClause("Bytes"),
+ gen_decode_field_call(ObjName,Name,"Bytes",TypeSpec)
+ end,
+ case more_genfields(Rest) of
+ true ->
+ emit([";",nl]);
+ false ->
+ emit([".",nl])
+ end,
+ gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,MaybeConstr++ConstrAcc);
+gen_decode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
+ ObjName,ObjectFields,ConstrAcc) ->
+ EmitFuncClause =
+ fun(Attrs) ->
+ emit(["'dec_",ObjName,"'(",{asis,Name},
+ ",",Attrs,") ->",nl])
+ end,
+% emit(["'dec_",ObjName,"'(",{asis,Name},
+% ", Bytes,_,[H|T]) ->",nl]),
+ case {get_object_field(Name,ObjectFields),OptOrMand} of
+ {false,'MANDATORY'} ->
+ exit({error,{asn1,{"missing mandatory field in object",
+ ObjName}}});
+ {false,'OPTIONAL'} ->
+ EmitFuncClause("_,_,_"),
+ emit([" exit({error,{'illegal use of missing field in object', ",Name,
+ "}})"]);
+ {false,{'DEFAULT',_DefaultObject}} ->
+ exit({error,{asn1,{"not implemented yet",Name}}});
+ {{Name,TypeSpec},_} ->
+ EmitFuncClause("Bytes,_,[H|T]"),
+ case TypeSpec#typedef.name of
+ {ExtMod,TypeName} ->
+ emit({indent(3),"'",ExtMod,"':'dec_",TypeName,
+ "'(H, Bytes, telltype, T)"});
+ TypeName ->
+ emit({indent(3),"'dec_",TypeName,"'(H, Bytes, telltype, T)"})
+ end
+ end,
+ case more_genfields(Rest) of
+ true ->
+ emit([";",nl]);
+ false ->
+ emit([".",nl])
+ end,
+ gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
+gen_decode_objectfields(CN,[_C|Cs],O,OF,CAcc) ->
+ gen_decode_objectfields(CN,Cs,O,OF,CAcc);
+gen_decode_objectfields(_,[],_,_,CAcc) ->
+ CAcc.
+
+
+gen_decode_field_call(ObjName,FieldName,Bytes,Type) ->
+ Def = Type#typedef.typespec,
+ case Type#typedef.name of
+ {primitive,bif} ->
+ gen_dec_prim(per,Def,Bytes),
+ [];
+ {constructed,bif} ->
+ emit({" 'dec_",ObjName,'_',FieldName,
+ "'(",Bytes,",telltype)"}),
+ [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
+ {ExtMod,TypeName} ->
+ emit({" '",ExtMod,"':'dec_",TypeName,
+ "'(",Bytes,", telltype)"}),
+ [];
+ TypeName ->
+ emit({" 'dec_",TypeName,"'(",Bytes,", telltype)"}),
+ []
+ end.
+
+gen_decode_default_call(ClassName,FieldName,Bytes,Type) ->
+ CurrentMod = get(currmod),
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ case asn1ct_gen:type(InnerType) of
+ {constructed,bif} ->
+ emit([" 'dec_",ClassName,'_',FieldName,"'(",Bytes,", telltype)"]),
+ [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
+ typespec=Type}];
+ {primitive,bif} ->
+ gen_dec_prim(per,Type,Bytes),
+ [];
+ #'Externaltypereference'{module=CurrentMod,type=Etype} ->
+ emit([" 'dec_",Etype,"'(",Bytes,", telltype)",nl]),
+ [];
+ #'Externaltypereference'{module=Emod,type=Etype} ->
+ emit([" '",Emod,"':'dec_",Etype,"'(",Bytes,", telltype)",nl]),
+ []
+ end.
+
+%%%%%%%%%%%%%%%
+
+% gen_decode_objectfields(Class,ObjName,[{FieldName,Type}|Rest],ConstrAcc) ->
+% Fields = Class#objectclass.fields,
+
+% MaybeConstr =
+% case is_typefield(Fields,FieldName) of
+% true ->
+% Def = Type#typedef.typespec,
+% emit({"'dec_",ObjName,"'(",{asis,FieldName},
+% ", Val, Telltype, RestPrimFieldName) ->",nl}),
+
+% CAcc =
+% case Type#typedef.name of
+% {primitive,bif} ->
+% gen_dec_prim(per,Def,"Val"),
+% [];
+% {constructed,bif} ->
+% emit({" 'dec_",ObjName,'_',FieldName,
+% "'(Val, Telltype)"}),
+% [{['dec_',ObjName,'_',FieldName],Def}];
+% {ExtMod,TypeName} ->
+% emit({" '",ExtMod,"':'dec_",TypeName,
+% "'(Val, Telltype)"}),
+% [];
+% TypeName ->
+% emit({" 'dec_",TypeName,"'(Val, Telltype)"}),
+% []
+% end,
+% case more_genfields(Fields,Rest) of
+% true ->
+% emit({";",nl});
+% false ->
+% emit({".",nl})
+% end,
+% CAcc;
+% {false,objectfield} ->
+% emit({"'dec_",ObjName,"'(",{asis,FieldName},
+% ", Val, Telltype, [H|T]) ->",nl}),
+% case Type#typedef.name of
+% {ExtMod,TypeName} ->
+% emit({indent(3),"'",ExtMod,"':'dec_",TypeName,
+% "'(H, Val, Telltype, T)"});
+% TypeName ->
+% emit({indent(3),"'dec_",TypeName,
+% "'(H, Val, Telltype, T)"})
+% end,
+% case more_genfields(Fields,Rest) of
+% true ->
+% emit({";",nl});
+% false ->
+% emit({".",nl})
+% end,
+% [];
+% {false,_} ->
+% []
+% end,
+% gen_decode_objectfields(Class,ObjName,Rest,MaybeConstr ++ ConstrAcc);
+% gen_decode_objectfields(C,O,[_|T],CAcc) ->
+% gen_decode_objectfields(C,O,T,CAcc);
+% gen_decode_objectfields(_,_,[],CAcc) ->
+% CAcc.
+
+gen_decode_constr_type(Erules,[{Name,Def}|Rest]) ->
+ emit({Name,"(Bytes,_) ->",nl}),
+ InnerType = asn1ct_gen:get_inner(Def#type.def),
+ asn1ct_gen:gen_decode_constructed(Erules,Name,InnerType,Def),
+ gen_decode_constr_type(Erules,Rest);
+gen_decode_constr_type(Erules,[TypeDef|Rest]) when record(TypeDef,typedef) ->
+ case is_already_generated(dec,TypeDef#typedef.name) of
+ true -> ok;
+ _ ->
+ gen_decode(Erules,TypeDef)
+ end,
+ gen_decode_constr_type(Erules,Rest);
+gen_decode_constr_type(_,[]) ->
+ ok.
+
+% is_typefield(Fields,FieldName) ->
+% case lists:keysearch(FieldName,2,Fields) of
+% {value,Field} ->
+% case element(1,Field) of
+% typefield ->
+% true;
+% Other ->
+% {false,Other}
+% end;
+% _ ->
+% false
+% end.
+%% Object Set code generating for encoding and decoding
+%% ----------------------------------------------------
+gen_objectset_code(Erules,ObjSet) ->
+ ObjSetName = ObjSet#typedef.name,
+ Def = ObjSet#typedef.typespec,
+%% {ClassName,ClassDef} = Def#'ObjectSet'.class,
+ #'Externaltypereference'{module=ClassModule,
+ type=ClassName} = Def#'ObjectSet'.class,
+ ClassDef = asn1_db:dbget(ClassModule,ClassName),
+ UniqueFName = Def#'ObjectSet'.uniquefname,
+ Set = Def#'ObjectSet'.set,
+ emit({nl,nl,nl,"%%================================"}),
+ emit({nl,"%% ",ObjSetName}),
+ emit({nl,"%%================================",nl}),
+ case ClassName of
+ {_Module,ExtClassName} ->
+ gen_objset_code(Erules,ObjSetName,UniqueFName,Set,
+ ExtClassName,ClassDef);
+ _ ->
+ gen_objset_code(Erules,ObjSetName,UniqueFName,Set,
+ ClassName,ClassDef)
+ end,
+ emit(nl).
+
+gen_objset_code(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassDef)->
+ ClassFields = (ClassDef#classdef.typespec)#objectclass.fields,
+ InternalFuncs=
+ gen_objset_enc(ObjSetName,UniqueFName,Set,ClassName,
+ ClassFields,1,[]),
+ gen_objset_dec(ObjSetName,UniqueFName,Set,ClassName,ClassFields,1),
+ gen_internal_funcs(Erules,InternalFuncs).
+
+gen_objset_enc(_,{unique,undefined},_,_,_,_,_) ->
+ %% There is no unique field in the class of this object set
+ %% don't bother about the constraint
+ [];
+gen_objset_enc(ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],
+ ClName,ClFields,NthObj,Acc)->
+ emit({"'getenc_",ObjSName,"'(",{asis,UniqueName},",",
+ {asis,Val},") ->",nl}),
+ {InternalFunc,NewNthObj}=
+ case ObjName of
+ no_name ->
+ gen_inlined_enc_funs(Fields,ClFields,ObjSName,NthObj);
+ _ ->
+ emit({" fun 'enc_",ObjName,"'/3"}),
+ {[],NthObj}
+ end,
+ emit({";",nl}),
+ gen_objset_enc(ObjSName,UniqueName,[T|Rest],ClName,ClFields,
+ NewNthObj,InternalFunc++Acc);
+gen_objset_enc(ObjSetName,UniqueName,
+ [{ObjName,Val,Fields}],_ClName,ClFields,NthObj,Acc) ->
+
+ emit({"'getenc_",ObjSetName,"'(",{asis,UniqueName},",",
+ {asis,Val},") ->",nl}),
+ {InternalFunc,_}=
+ case ObjName of
+ no_name ->
+ gen_inlined_enc_funs(Fields,ClFields,ObjSetName,NthObj);
+ _ ->
+ emit({" fun 'enc_",ObjName,"'/3"}),
+ {[],NthObj}
+ end,
+ emit({".",nl,nl}),
+ InternalFunc++Acc;
+gen_objset_enc(ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
+ _ClFields,_NthObj,Acc) ->
+ emit({"'getenc_",ObjSetName,"'(_, _) ->",nl}),
+ emit({indent(3),"fun(_, Val, _) ->",nl}),
+ emit({indent(6),"Size = if",nl}),
+ emit({indent(9),"list(Val) -> length(Val);",nl}),
+ emit({indent(9),"true -> size(Val)",nl}),
+ emit({indent(6),"end,",nl}),
+ emit({indent(6),"if",nl}),
+ emit({indent(9),"Size < 256 ->",nl}),
+ emit({indent(12),"[20,Size,Val];",nl}),
+ emit({indent(9),"true ->",nl}),
+ emit({indent(12),"[21,<<Size:16>>,Val]",nl}),
+ emit({indent(6),"end",nl}),
+ emit({indent(3),"end.",nl,nl}),
+ Acc;
+gen_objset_enc(_,_,[],_,_,_,Acc) ->
+ Acc.
+
+%% gen_inlined_enc_funs for each object iterates over all fields of a
+%% class, and for each typefield it checks if the object has that
+%% field and emits the proper code.
+gen_inlined_enc_funs(Fields,[{typefield,Name,_}|Rest],ObjSetName,NthObj) ->
+ InternalDefFunName=asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
+ case lists:keysearch(Name,1,Fields) of
+ {value,{_,Type}} when record(Type,type) ->
+ emit({indent(3),"fun(Type, Val, _) ->",nl,
+ indent(6),"case Type of",nl}),
+ {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
+ gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
+ {value,{_,Type}} when record(Type,typedef) ->
+ emit({indent(3),"fun(Type, Val, _) ->",nl,
+ indent(6),"case Type of",nl}),
+ emit({indent(9),{asis,Name}," ->",nl}),
+ {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
+ gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
+ false ->
+ gen_inlined_enc_funs(Fields,Rest,ObjSetName,NthObj)
+ end;
+gen_inlined_enc_funs(Fields,[_|Rest],ObjSetName,NthObj) ->
+ gen_inlined_enc_funs(Fields,Rest,ObjSetName,NthObj);
+gen_inlined_enc_funs(_,[],_,NthObj) ->
+ {[],NthObj}.
+
+gen_inlined_enc_funs1(Fields,[{typefield,Name,_}|Rest],ObjSetName,
+ NthObj,Acc) ->
+ InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
+ {Acc2,NAdd}=
+ case lists:keysearch(Name,1,Fields) of
+ {value,{_,Type}} when record(Type,type) ->
+ emit({";",nl}),
+ {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
+ {Ret++Acc,N};
+ {value,{_,Type}} when record(Type,typedef) ->
+ emit({";",nl,indent(9),{asis,Name}," ->",nl}),
+ {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
+ {Ret++Acc,N};
+ false ->
+ {Acc,0}
+ end,
+ gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+NAdd,Acc2);
+gen_inlined_enc_funs1(Fields,[_|Rest],ObjSetName,NthObj,Acc)->
+ gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj,Acc);
+gen_inlined_enc_funs1(_,[],_,NthObj,Acc) ->
+ emit({nl,indent(6),"end",nl}),
+ emit({indent(3),"end"}),
+ {Acc,NthObj}.
+
+emit_inner_of_fun(TDef=#typedef{name={ExtMod,Name},typespec=Type},
+ InternalDefFunName) ->
+ case {ExtMod,Name} of
+ {primitive,bif} ->
+ emit(indent(12)),
+ gen_encode_prim(per,Type,dotag,"Val"),
+ {[],0};
+ {constructed,bif} ->
+ emit([indent(12),"'enc_",
+ InternalDefFunName,"'(Val)"]),
+ {[TDef#typedef{name=InternalDefFunName}],1};
+ _ ->
+ emit({indent(12),"'",ExtMod,"':'enc_",Name,"'(Val)"}),
+ {[],0}
+ end;
+emit_inner_of_fun(#typedef{name=Name},_) ->
+ emit({indent(12),"'enc_",Name,"'(Val)"}),
+ {[],0};
+emit_inner_of_fun(Type,_) when record(Type,type) ->
+ CurrMod = get(currmod),
+ case Type#type.def of
+ Def when atom(Def) ->
+ emit({indent(9),Def," ->",nl,indent(12)}),
+ gen_encode_prim(erules,Type,dotag,"Val");
+ TRef when record(TRef,typereference) ->
+ T = TRef#typereference.val,
+ emit({indent(9),T," ->",nl,indent(12),"'enc_",T,"'(Val)"});
+ #'Externaltypereference'{module=CurrMod,type=T} ->
+ emit({indent(9),T," ->",nl,indent(12),"'enc_",T,"'(Val)"});
+ #'Externaltypereference'{module=ExtMod,type=T} ->
+ emit({indent(9),T," ->",nl,indent(12),ExtMod,":'enc_",
+ T,"'(Val)"})
+ end,
+ {[],0}.
+
+indent(N) ->
+ lists:duplicate(N,32). % 32 = space
+
+
+gen_objset_dec(_,{unique,undefined},_,_,_,_) ->
+ %% There is no unique field in the class of this object set
+ %% don't bother about the constraint
+ ok;
+gen_objset_dec(ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],ClName,
+ ClFields,NthObj)->
+
+ emit({"'getdec_",ObjSName,"'(",{asis,UniqueName},",",
+ {asis,Val},") ->",nl}),
+ NewNthObj=
+ case ObjName of
+ no_name ->
+ gen_inlined_dec_funs(Fields,ClFields,ObjSName,NthObj);
+ _ ->
+ emit({" fun 'dec_",ObjName,"'/4"}),
+ NthObj
+ end,
+ emit({";",nl}),
+ gen_objset_dec(ObjSName,UniqueName,[T|Rest],ClName,ClFields,NewNthObj);
+gen_objset_dec(ObjSetName,UniqueName,[{ObjName,Val,Fields}],_ClName,
+ ClFields,NthObj) ->
+
+ emit({"'getdec_",ObjSetName,"'(",{asis,UniqueName},",",
+ {asis,Val},") ->",nl}),
+ case ObjName of
+ no_name ->
+ gen_inlined_dec_funs(Fields,ClFields,ObjSetName,NthObj);
+ _ ->
+ emit({" fun 'dec_",ObjName,"'/4"})
+ end,
+ emit({".",nl,nl}),
+ ok;
+gen_objset_dec(ObjSetName,_,['EXTENSIONMARK'],_ClName,_ClFields,
+ _NthObj) ->
+ emit({"'getdec_",ObjSetName,"'(_, _) ->",nl}),
+ emit({indent(3),"fun(Attr1, Bytes, _, _) ->",nl}),
+ %% emit({indent(6),"?RT_PER:decode_open_type(Bytes,[])",nl}),
+ emit({indent(6),"{Bytes,Attr1}",nl}),
+ emit({indent(3),"end.",nl,nl}),
+ ok;
+gen_objset_dec(_,_,[],_,_,_) ->
+ ok.
+
+gen_inlined_dec_funs(Fields,[{typefield,Name,_}|Rest],
+ ObjSetName,NthObj) ->
+ InternalDefFunName = [NthObj,Name,ObjSetName],
+ case lists:keysearch(Name,1,Fields) of
+ {value,{_,Type}} when record(Type,type) ->
+ emit({indent(3),"fun(Type, Val, _, _) ->",nl,
+ indent(6),"case Type of",nl}),
+ N=emit_inner_of_decfun(Type,InternalDefFunName),
+ gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
+ {value,{_,Type}} when record(Type,typedef) ->
+ emit({indent(3),"fun(Type, Val, _, _) ->",nl,
+ indent(6),"case Type of",nl}),
+ emit({indent(9),{asis,Name}," ->",nl}),
+ N=emit_inner_of_decfun(Type,InternalDefFunName),
+ gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
+ false ->
+ gen_inlined_dec_funs(Fields,Rest,ObjSetName,NthObj)
+ end;
+gen_inlined_dec_funs(Fields,[_|Rest],ObjSetName,NthObj) ->
+ gen_inlined_dec_funs(Fields,Rest,ObjSetName,NthObj);
+gen_inlined_dec_funs(_,[],_,NthObj) ->
+ NthObj.
+
+gen_inlined_dec_funs1(Fields,[{typefield,Name,_}|Rest],
+ ObjSetName,NthObj) ->
+ InternalDefFunName = [NthObj,Name,ObjSetName],
+ N=
+ case lists:keysearch(Name,1,Fields) of
+ {value,{_,Type}} when record(Type,type) ->
+ emit({";",nl}),
+ emit_inner_of_decfun(Type,InternalDefFunName);
+ {value,{_,Type}} when record(Type,typedef) ->
+ emit({";",nl,indent(9),{asis,Name}," ->",nl}),
+ emit_inner_of_decfun(Type,InternalDefFunName);
+ false ->
+ 0
+ end,
+ gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
+gen_inlined_dec_funs1(Fields,[_|Rest],ObjSetName,NthObj)->
+ gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj);
+gen_inlined_dec_funs1(_,[],_,NthObj) ->
+ emit({nl,indent(6),"end",nl}),
+ emit({indent(3),"end"}),
+ NthObj.
+
+emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type},
+ InternalDefFunName) ->
+ case {ExtName,Name} of
+ {primitive,bif} ->
+ emit(indent(12)),
+ gen_dec_prim(per,Type,"Val"),
+ 0;
+ {constructed,bif} ->
+ emit({indent(12),"'dec_",
+ asn1ct_gen:list2name(InternalDefFunName),"'(Val)"}),
+ 1;
+ _ ->
+ emit({indent(12),"'",ExtName,"':'dec_",Name,
+ "'(Val, telltype)"}),
+ 0
+ end;
+emit_inner_of_decfun(#typedef{name=Name},_) ->
+ emit({indent(12),"'dec_",Name,"'(Val, telltype)"}),
+ 0;
+emit_inner_of_decfun(Type,_) when record(Type,type) ->
+ CurrMod = get(currmod),
+ case Type#type.def of
+ Def when atom(Def) ->
+ emit({indent(9),Def," ->",nl,indent(12)}),
+ gen_dec_prim(erules,Type,"Val");
+ TRef when record(TRef,typereference) ->
+ T = TRef#typereference.val,
+ emit({indent(9),T," ->",nl,indent(12),"'dec_",T,"'(Val)"});
+ #'Externaltypereference'{module=CurrMod,type=T} ->
+ emit({indent(9),T," ->",nl,indent(12),"'dec_",T,"'(Val)"});
+ #'Externaltypereference'{module=ExtMod,type=T} ->
+ emit({indent(9),T," ->",nl,indent(12),ExtMod,":'dec_",
+ T,"'(Val)"})
+ end,
+ 0.
+
+
+gen_internal_funcs(_Erules,[]) ->
+ ok;
+gen_internal_funcs(Erules,[TypeDef|Rest]) ->
+ gen_encode_user(Erules,TypeDef),
+ emit([nl,nl,"'dec_",TypeDef#typedef.name,"'(Bytes) ->",nl]),
+ gen_decode_user(Erules,TypeDef),
+ gen_internal_funcs(Erules,Rest).
+
+
+
+%% DECODING *****************************
+%%***************************************
+
+
+gen_decode(Erules,Type) when record(Type,typedef) ->
+ D = Type,
+ emit({nl,nl}),
+ emit({"'dec_",Type#typedef.name,"'(Bytes,_) ->",nl}),
+ dbdec(Type#typedef.name),
+ gen_decode_user(Erules,D).
+
+gen_decode(Erules,Tname,#'ComponentType'{name=Cname,typespec=Type}) ->
+ NewTname = [Cname|Tname],
+ gen_decode(Erules,NewTname,Type);
+
+gen_decode(Erules,Typename,Type) when record(Type,type) ->
+ InnerType = asn1ct_gen:get_inner(Type#type.def),
+ case asn1ct_gen:type(InnerType) of
+ {constructed,bif} ->
+ ObjFun =
+ case Type#type.tablecinf of
+ [{objfun,_}|_R] ->
+ ", ObjFun";
+ _ ->
+ ""
+ end,
+ emit({nl,"'dec_",asn1ct_gen:list2name(Typename),
+ "'(Bytes,_",ObjFun,") ->",nl}),
+ dbdec(Typename),
+ asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,Type);
+ _ ->
+ true
+ end.
+
+dbdec(Type) when list(Type)->
+ demit({"io:format(\"decoding: ",asn1ct_gen:list2name(Type),"~w~n\",[Bytes]),",nl});
+dbdec(Type) ->
+ demit({"io:format(\"decoding: ",{asis,Type},"~w~n\",[Bytes]),",nl}).
+
+gen_decode_user(Erules,D) when record(D,typedef) ->
+ CurrMod = get(currmod),
+ Typename = [D#typedef.name],
+ Def = D#typedef.typespec,
+ InnerType = asn1ct_gen:get_inner(Def#type.def),
+ case asn1ct_gen:type(InnerType) of
+ {primitive,bif} ->
+ gen_dec_prim(Erules,Def,"Bytes"),
+ emit({".",nl,nl});
+ 'ASN1_OPEN_TYPE' ->
+ gen_dec_prim(Erules,Def#type{def='ASN1_OPEN_TYPE'},"Bytes"),
+ emit({".",nl,nl});
+ {constructed,bif} ->
+ asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,D);
+ #typereference{val=Dname} ->
+ emit({"'dec_",Dname,"'(Bytes,telltype)"}),
+ emit({".",nl,nl});
+ #'Externaltypereference'{module=CurrMod,type=Etype} ->
+ emit({"'dec_",Etype,"'(Bytes,telltype).",nl,nl});
+ #'Externaltypereference'{module=Emod,type=Etype} ->
+ emit({"'",Emod,"':'dec_",Etype,"'(Bytes,telltype).",nl,nl});
+ Other ->
+ exit({error,{asn1,{unknown,Other}}})
+ end.
+
+
+
+gen_dec_prim(_Erules,Att,BytesVar) ->
+ Typename = Att#type.def,
+ Constraint = Att#type.constraint,
+ case Typename of
+ 'INTEGER' ->
+ EffectiveConstr = effective_constraint(integer,Constraint),
+ emit_dec_integer(EffectiveConstr,BytesVar);
+% emit({"?RT_PER:decode_integer(",BytesVar,",",
+% {asis,EffectiveConstr},")"});
+ {'INTEGER',NamedNumberList} ->
+ EffectiveConstr = effective_constraint(integer,Constraint),
+ emit_dec_integer(EffectiveConstr,BytesVar,NamedNumberList);
+% emit({"?RT_PER:decode_integer(",BytesVar,",",
+% {asis,EffectiveConstr},",",
+% {asis,NamedNumberList},")"});
+ {'BIT STRING',NamedNumberList} ->
+ case get(compact_bit_string) of
+ true ->
+ emit({"?RT_PER:decode_compact_bit_string(",
+ BytesVar,",",{asis,Constraint},",",
+ {asis,NamedNumberList},")"});
+ _ ->
+ emit({"?RT_PER:decode_bit_string(",BytesVar,",",
+ {asis,Constraint},",",
+ {asis,NamedNumberList},")"})
+ end;
+ 'NULL' ->
+ emit({"?RT_PER:decode_null(",
+ BytesVar,")"});
+ 'OBJECT IDENTIFIER' ->
+ emit({"?RT_PER:decode_object_identifier(",
+ BytesVar,")"});
+ 'ObjectDescriptor' ->
+ emit({"?RT_PER:decode_ObjectDescriptor(",
+ BytesVar,")"});
+ {'ENUMERATED',{NamedNumberList1,NamedNumberList2}} ->
+ NewTup = {list_to_tuple([X||{X,_} <- NamedNumberList1]),
+ list_to_tuple([X||{X,_} <- NamedNumberList2])},
+ NewC = [{'ValueRange',{0,size(element(1,NewTup))-1}}],
+ emit({"?RT_PER:decode_enumerated(",BytesVar,",",
+ {asis,NewC},",",
+ {asis,NewTup},")"});
+ {'ENUMERATED',NamedNumberList} ->
+ %NewTup = list_to_tuple([X||{X,Y} <- NamedNumberList]),
+ NewNNL = [X||{X,_} <- NamedNumberList],
+ NewC = effective_constraint(integer,
+ [{'ValueRange',{0,length(NewNNL)-1}}]),
+ emit_dec_enumerated(BytesVar,NewC,NewNNL);
+% emit({"?RT_PER:decode_enumerated(",BytesVar,",",
+% {asis,NewC},",",
+% {asis,NewTup},")"});
+ 'BOOLEAN'->
+ emit({"?RT_PER:decode_boolean(",BytesVar,")"});
+ 'OCTET STRING' ->
+ emit_dec_octet_string(Constraint,BytesVar);
+% emit({"?RT_PER:decode_octet_string(",BytesVar,",",
+% {asis,Constraint},")"});
+ 'NumericString' ->
+ emit_dec_known_multiplier_string('NumericString',
+ Constraint,BytesVar);
+% emit({"?RT_PER:decode_NumericString(",BytesVar,",",
+% {asis,Constraint},")"});
+ 'TeletexString' ->
+ emit({"?RT_PER:decode_TeletexString(",BytesVar,",",
+ {asis,Constraint},")"});
+ 'VideotexString' ->
+ emit({"?RT_PER:decode_VideotexString(",BytesVar,",",
+ {asis,Constraint},")"});
+ 'UTCTime' ->
+ emit_dec_known_multiplier_string('VisibleString',
+ Constraint,BytesVar);
+% emit({"?RT_PER:decode_VisibleString(",BytesVar,",",
+% {asis,Constraint},")"});
+ 'GeneralizedTime' ->
+ emit_dec_known_multiplier_string('VisibleString',
+ Constraint,BytesVar);
+% emit({"?RT_PER:decode_VisibleString(",BytesVar,",",
+% {asis,Constraint},")"});
+ 'GraphicString' ->
+ emit({"?RT_PER:decode_GraphicString(",BytesVar,",",
+ {asis,Constraint},")"});
+ 'VisibleString' ->
+ emit_dec_known_multiplier_string('VisibleString',
+ Constraint,BytesVar);
+% emit({"?RT_PER:decode_VisibleString(",BytesVar,",",
+% {asis,Constraint},")"});
+ 'GeneralString' ->
+ emit({"?RT_PER:decode_GeneralString(",BytesVar,",",
+ {asis,Constraint},")"});
+ 'PrintableString' ->
+ emit_dec_known_multiplier_string('PrintableString',
+ Constraint,BytesVar);
+% emit({"?RT_PER:decode_PrintableString(",BytesVar,",",{asis,Constraint},")"});
+ 'IA5String' ->
+ emit_dec_known_multiplier_string('IA5String',Constraint,BytesVar);
+% emit({"?RT_PER:decode_IA5String(",BytesVar,",",{asis,Constraint},")"});
+ 'BMPString' ->
+ emit_dec_known_multiplier_string('BMPString',Constraint,BytesVar);
+% emit({"?RT_PER:decode_BMPString(",BytesVar,",",{asis,Constraint},")"});
+ 'UniversalString' ->
+ emit_dec_known_multiplier_string('UniversalString',
+ Constraint,BytesVar);
+% emit({"?RT_PER:decode_UniversalString(",BytesVar,",",{asis,Constraint},")"});
+ 'ANY' ->
+ emit(["?RT_PER:decode_open_type(",BytesVar,",",
+ {asis,Constraint}, ")"]);
+ 'ASN1_OPEN_TYPE' ->
+ case Constraint of
+ [#'Externaltypereference'{type=Tname}] ->
+ emit(["fun(FBytes) ->",nl,
+ " {XTerm,XBytes} = "]),
+ emit(["?RT_PER:decode_open_type(FBytes,[]),",nl]),
+ emit([" {YTerm,_} = dec_",Tname,"(XTerm,mandatory),",nl]),
+ emit([" {YTerm,XBytes} end(",BytesVar,")"]);
+ [#type{def=#'Externaltypereference'{type=Tname}}] ->
+ emit(["fun(FBytes) ->",nl,
+ " {XTerm,XBytes} = "]),
+ emit(["?RT_PER:decode_open_type(FBytes,[]),",nl]),
+ emit([" {YTerm,_} = dec_",Tname,"(XTerm,mandatory),",nl]),
+ emit([" {YTerm,XBytes} end(",BytesVar,")"]);
+ _ ->
+ emit(["?RT_PER:decode_open_type(",BytesVar,",[])"])
+ end;
+ Other ->
+ exit({'cant decode' ,Other})
+ end.
+
+
+emit_dec_integer(C,BytesVar,NNL) ->
+ asn1ct_name:new(tmpterm),
+ asn1ct_name:new(buffer),
+ Tmpterm = asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
+ Buffer = asn1ct_gen:mk_var(asn1ct_name:curr(buffer)),
+ emit({" begin {",{curr,tmpterm},",",{curr,buffer},"} = ",nl}),
+ emit_dec_integer(C,BytesVar),
+ emit({",",nl," case ",Tmpterm," of",nl}),
+ lists:map(fun({Name,Int})->emit({" ",Int," -> {",{asis,Name},",",
+ Buffer,"};",nl});
+ (_)-> exit({error,{asn1,{"error in named number list",NNL}}})
+ end,
+ NNL),
+ emit({" _ -> {",Tmpterm,",",Buffer,"}",nl}),
+ emit({" end",nl}), % end of case
+ emit(" end"). % end of begin
+
+emit_dec_integer([{'SingleValue',Int}],BytesVar) when integer(Int) ->
+ emit(["{",Int,",",BytesVar,"}"]);
+emit_dec_integer([{_,{Lb,_Ub},_Range,{BitsOrOctets,N}}],BytesVar) ->
+ GetBorO =
+ case BitsOrOctets of
+ bits -> "getbits";
+ _ -> "getoctets"
+ end,
+ asn1ct_name:new(tmpterm),
+ asn1ct_name:new(tmpremain),
+ emit({" begin",nl," {",{curr,tmpterm},",",{curr,tmpremain},"}=",
+ "?RT_PER:",GetBorO,"(",BytesVar,",",N,"),",nl}),
+ emit({" {",{curr,tmpterm},"+",Lb,",",{curr,tmpremain},"}",nl,
+ " end"});
+emit_dec_integer([{_,{'MIN',_}}],BytesVar) ->
+ emit({"?RT_PER:decode_unconstrained_number(",BytesVar,")"});
+emit_dec_integer([{_,{Lb,'MAX'}}],BytesVar) ->
+ emit({"?RT_PER:decode_semi_constrained_number(",BytesVar,",",Lb,")"});
+emit_dec_integer([{'ValueRange',VR={Lb,Ub}}],BytesVar) ->
+ Range = Ub-Lb+1,
+ emit({"?RT_PER:decode_constrained_number(",BytesVar,",",
+ {asis,VR},",",Range,")"});
+emit_dec_integer(C=[{Rc,_}],BytesVar) when tuple(Rc) ->
+ emit({"?RT_PER:decode_integer(",BytesVar,",",{asis,C},")"});
+emit_dec_integer(_,BytesVar) ->
+ emit({"?RT_PER:decode_unconstrained_number(",BytesVar,")"}).
+
+
+emit_dec_enumerated(BytesVar,C,NamedNumberList) ->
+ emit_dec_enumerated_begin(),% emits a begin if component
+ asn1ct_name:new(tmpterm),
+ Tmpterm = asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
+ asn1ct_name:new(tmpremain),
+ Tmpremain = asn1ct_gen:mk_var(asn1ct_name:curr(tmpremain)),
+ emit({" {",{curr,tmpterm},",",{curr,tmpremain},"} =",nl}),
+ emit_dec_integer(C,BytesVar),
+ emit({",",nl," case ",Tmpterm," of "}),
+% Cases=lists:flatten(dec_enumerated_cases(NamedNumberList,asn1ct_gen:mk_var(asn1ct_name:curr(tmpremain)),0)),
+ Cases=lists:flatten(dec_enumerated_cases(NamedNumberList,Tmpremain,0)),
+ emit({Cases++"_->exit({error,{asn1,{decode_enumerated,{",Tmpterm,
+ ",",{asis,NamedNumberList},"}}}}) end",nl}),
+ emit_dec_enumerated_end().
+
+emit_dec_enumerated_begin() ->
+ case get(component_type) of
+ {true,_} ->
+ emit({" begin",nl});
+ _ -> ok
+ end.
+
+emit_dec_enumerated_end() ->
+ case get(component_type) of
+ {true,_} ->
+ emit(" end");
+ _ -> ok
+ end.
+
+% dec_enumerated_cases(NNL,Tmpremain,No) ->
+% Cases=dec_enumerated_cases1(NNL,Tmpremain,0),
+% lists:flatten(io_lib:format("(case ~s "++Cases++
+% "~s when atom(~s)->exit({error,{asn1,{namednumber,~s}}});_->~s end)",[Value,"TmpVal","TmpVal","TmpVal",Value])).
+
+dec_enumerated_cases([Name|Rest],Tmpremain,No) ->
+ io_lib:format("~w->{~w,~s};",[No,Name,Tmpremain])++
+ dec_enumerated_cases(Rest,Tmpremain,No+1);
+dec_enumerated_cases([],_,_) ->
+ "".
+
+
+% more_genfields(_Fields,[]) ->
+% false;
+% more_genfields(Fields,[{FieldName,_}|T]) ->
+% case is_typefield(Fields,FieldName) of
+% true -> true;
+% {false,objectfield} -> true;
+% {false,_} -> more_genfields(Fields,T)
+% end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_name.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_name.erl
new file mode 100644
index 0000000000..1c7769998c
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_name.erl
@@ -0,0 +1,225 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1ct_name.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
+%%
+-module(asn1ct_name).
+
+%%-compile(export_all).
+-export([name_server_loop/1,
+ start/0,
+ stop/0,
+ push/1,
+ pop/1,
+ curr/1,
+ clear/0,
+ delete/1,
+ active/1,
+ prev/1,
+ next/1,
+ all/1,
+ new/1]).
+
+start() ->
+ start_server(asn1_ns, asn1ct_name,name_server_loop,[[]]).
+
+stop() -> stop_server(asn1_ns).
+
+name_server_loop(Vars) ->
+%% io:format("name -- ~w~n",[Vars]),
+ receive
+ {From,{current,Variable}} ->
+ From ! {asn1_ns,get_curr(Vars,Variable)},
+ name_server_loop(Vars);
+ {From,{pop,Variable}} ->
+ From ! {asn1_ns,done},
+ name_server_loop(pop_var(Vars,Variable));
+ {From,{push,Variable}} ->
+ From ! {asn1_ns,done},
+ name_server_loop(push_var(Vars,Variable));
+ {From,{delete,Variable}} ->
+ From ! {asn1_ns,done},
+ name_server_loop(delete_var(Vars,Variable));
+ {From,{new,Variable}} ->
+ From ! {asn1_ns,done},
+ name_server_loop(new_var(Vars,Variable));
+ {From,{prev,Variable}} ->
+ From ! {asn1_ns,get_prev(Vars,Variable)},
+ name_server_loop(Vars);
+ {From,{next,Variable}} ->
+ From ! {asn1_ns,get_next(Vars,Variable)},
+ name_server_loop(Vars);
+ {From,stop} ->
+ From ! {asn1_ns,stopped},
+ exit(normal)
+ end.
+
+active(V) ->
+ case curr(V) of
+ nil -> false;
+ _ -> true
+ end.
+
+req(Req) ->
+ asn1_ns ! {self(), Req},
+ receive {asn1_ns, Reply} -> Reply end.
+
+pop(V) -> req({pop,V}).
+push(V) -> req({push,V}).
+clear() -> req(stop), start().
+curr(V) -> req({current,V}).
+new(V) -> req({new,V}).
+delete(V) -> req({delete,V}).
+prev(V) ->
+ case req({prev,V}) of
+ none ->
+ exit('cant get prev of none');
+ Rep -> Rep
+ end.
+
+next(V) ->
+ case req({next,V}) of
+ none ->
+ exit('cant get next of none');
+ Rep -> Rep
+ end.
+
+all(V) ->
+ Curr = curr(V),
+ if Curr == V -> [];
+ true ->
+ lists:reverse(generate(V,last(Curr),[],0))
+ end.
+
+generate(V,Number,Res,Pos) ->
+ Ell = Pos+1,
+ if
+ Ell > Number ->
+ Res;
+ true ->
+ generate(V,Number,[list_to_atom(lists:concat([V,Ell]))|Res],Ell)
+ end.
+
+last(V) ->
+ last2(lists:reverse(atom_to_list(V))).
+
+last2(RevL) ->
+ list_to_integer(lists:reverse(get_digs(RevL))).
+
+
+get_digs([H|T]) ->
+ if
+ H < $9+1,
+ H > $0-1 ->
+ [H|get_digs(T)];
+ true ->
+ []
+ end.
+
+push_var(Vars,Variable) ->
+ case lists:keysearch(Variable,1,Vars) of
+ false ->
+ [{Variable,[0]}|Vars];
+ {value,{Variable,[Digit|Drest]}} ->
+ NewVars = lists:keydelete(Variable,1,Vars),
+ [{Variable,[Digit,Digit|Drest]}|NewVars]
+ end.
+
+pop_var(Vars,Variable) ->
+ case lists:keysearch(Variable,1,Vars) of
+ false ->
+ ok;
+ {value,{Variable,[_Dig]}} ->
+ lists:keydelete(Variable,1,Vars);
+ {value,{Variable,[_Dig|Digits]}} ->
+ NewVars = lists:keydelete(Variable,1,Vars),
+ [{Variable,Digits}|NewVars]
+ end.
+
+get_curr([],Variable) ->
+ Variable;
+get_curr([{Variable,[0|_Drest]}|_Tail],Variable) ->
+ Variable;
+get_curr([{Variable,[Digit|_Drest]}|_Tail],Variable) ->
+ list_to_atom(lists:concat([Variable,integer_to_list(Digit)]));
+
+get_curr([_|Tail],Variable) ->
+ get_curr(Tail,Variable).
+
+new_var(Vars,Variable) ->
+ case lists:keysearch(Variable,1,Vars) of
+ false ->
+ [{Variable,[1]}|Vars];
+ {value,{Variable,[Digit|Drest]}} ->
+ NewVars = lists:keydelete(Variable,1,Vars),
+ [{Variable,[Digit+1|Drest]}|NewVars]
+ end.
+
+delete_var(Vars,Variable) ->
+ case lists:keysearch(Variable,1,Vars) of
+ false ->
+ Vars;
+ {value,{Variable,[N]}} when N =< 1 ->
+ lists:keydelete(Variable,1,Vars);
+ {value,{Variable,[Digit|Drest]}} ->
+ case Digit of
+ 0 ->
+ Vars;
+ _ ->
+ NewVars = lists:keydelete(Variable,1,Vars),
+ [{Variable,[Digit-1|Drest]}|NewVars]
+ end
+ end.
+
+get_prev(Vars,Variable) ->
+ case lists:keysearch(Variable,1,Vars) of
+ false ->
+ none;
+ {value,{Variable,[Digit|_]}} when Digit =< 1 ->
+ Variable;
+ {value,{Variable,[Digit|_]}} when Digit > 1 ->
+ list_to_atom(lists:concat([Variable,
+ integer_to_list(Digit-1)]));
+ _ ->
+ none
+ end.
+
+get_next(Vars,Variable) ->
+ case lists:keysearch(Variable,1,Vars) of
+ false ->
+ list_to_atom(lists:concat([Variable,"1"]));
+ {value,{Variable,[Digit|_]}} when Digit >= 0 ->
+ list_to_atom(lists:concat([Variable,
+ integer_to_list(Digit+1)]));
+ _ ->
+ none
+ end.
+
+
+stop_server(Name) ->
+ stop_server(Name, whereis(Name)).
+stop_server(_Name, undefined) -> stopped;
+stop_server(Name, _Pid) ->
+ Name ! {self(), stop},
+ receive {Name, _} -> stopped end.
+
+
+start_server(Name,Mod,Fun,Args) ->
+ case whereis(Name) of
+ undefined ->
+ register(Name, spawn(Mod,Fun, Args));
+ _Pid ->
+ already_started
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_parser.yrl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_parser.yrl
new file mode 100644
index 0000000000..b2c1d70f6e
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_parser.yrl
@@ -0,0 +1,1162 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1ct_parser.yrl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
+%%
+Nonterminals
+ModuleDefinition ModuleIdentifier DefinitiveIdentifier DefinitiveObjIdComponentList
+DefinitiveObjIdComponent TagDefault ExtensionDefault
+ModuleBody Exports SymbolsExported Imports SymbolsImported
+SymbolsFromModuleList SymbolsFromModule GlobalModuleReference AssignedIdentifier SymbolList
+Symbol Reference AssignmentList Assignment
+ExtensionAndException
+ComponentTypeLists
+Externaltypereference Externalvaluereference DefinedType DefinedValue
+AbsoluteReference ItemSpec ItemId ComponentId TypeAssignment
+ValueAssignment
+% ValueSetTypeAssignment
+ValueSet
+Type BuiltinType NamedType ReferencedType
+Value ValueNotNull BuiltinValue ReferencedValue NamedValue
+% BooleanType
+BooleanValue IntegerType NamedNumberList NamedNumber SignedNumber
+% inlined IntegerValue
+EnumeratedType
+% inlined Enumerations
+Enumeration EnumerationItem
+% inlined EnumeratedValue
+% RealType
+RealValue NumericRealValue SpecialRealValue BitStringType
+% inlined BitStringValue
+IdentifierList
+% OctetStringType
+% inlined OctetStringValue
+% NullType NullValue
+SequenceType ComponentTypeList ComponentType
+% SequenceValue SequenceOfValue
+ComponentValueList SequenceOfType
+SAndSOfValue ValueList SetType
+% SetValue SetOfValue
+SetOfType
+ChoiceType
+% AlternativeTypeList made common with ComponentTypeList
+ChoiceValue
+AnyValue
+AnyDefBy
+SelectionType
+TaggedType Tag ClassNumber Class
+% redundant TaggedValue
+% EmbeddedPDVType EmbeddedPDVValue ExternalType ExternalValue ObjectIdentifierType
+ObjectIdentifierValue ObjIdComponentList ObjIdComponent
+% NameForm NumberForm NameAndNumberForm
+CharacterStringType
+RestrictedCharacterStringValue CharacterStringList
+% CharSyms CharsDefn
+Quadruple
+% Group Plane Row Cell
+Tuple
+% TableColumn TableRow
+% UnrestrictedCharacterString
+CharacterStringValue
+% UnrestrictedCharacterStringValue
+ConstrainedType Constraint ConstraintSpec TypeWithConstraint
+ElementSetSpecs ElementSetSpec
+%GeneralConstraint
+UserDefinedConstraint UserDefinedConstraintParameter
+UserDefinedConstraintParameters
+ExceptionSpec
+ExceptionIdentification
+Unions
+UnionMark
+UElems
+Intersections
+IntersectionElements
+IntersectionMark
+IElems
+Elements
+Elems
+SubTypeElements
+Exclusions
+LowerEndpoint
+UpperEndpoint
+LowerEndValue
+UpperEndValue
+TypeConstraints NamedConstraint PresenceConstraint
+
+ParameterizedTypeAssignment
+ParameterList
+Parameters
+Parameter
+ParameterizedType
+
+% X.681
+ObjectClassAssignment ObjectClass ObjectClassDefn
+FieldSpecs FieldSpec OptionalitySpec WithSyntaxSpec
+TokenOrGroupSpecs TokenOrGroupSpec
+SyntaxList OptionalGroup RequiredToken Word
+TypeOptionalitySpec
+ValueOrObjectOptSpec
+VSetOrOSetOptSpec
+ValueOptionalitySpec
+ObjectOptionalitySpec
+ValueSetOptionalitySpec
+ObjectSetOptionalitySpec
+% X.681 chapter 15
+InformationFromObjects
+ValueFromObject
+%ValueSetFromObjects
+TypeFromObject
+%ObjectFromObject
+%ObjectSetFromObjects
+ReferencedObjects
+FieldName
+PrimitiveFieldName
+
+ObjectAssignment
+ObjectSetAssignment
+ObjectSet
+ObjectSetElements
+Object
+ObjectDefn
+DefaultSyntax
+DefinedSyntax
+FieldSettings
+FieldSetting
+DefinedSyntaxTokens
+DefinedSyntaxToken
+Setting
+DefinedObject
+ObjectFromObject
+ObjectSetFromObjects
+ParameterizedObject
+ExternalObjectReference
+DefinedObjectSet
+DefinedObjectClass
+ExternalObjectClassReference
+
+% X.682
+TableConstraint
+ComponentRelationConstraint
+ComponentIdList
+
+% X.683
+ActualParameter
+.
+
+%UsefulType.
+
+Terminals
+'ABSENT' 'ABSTRACT-SYNTAX' 'ALL' 'ANY'
+'APPLICATION' 'AUTOMATIC' 'BEGIN' 'BIT'
+'BOOLEAN' 'BY' 'CHARACTER' 'CHOICE' 'CLASS' 'COMPONENT'
+'COMPONENTS' 'CONSTRAINED' 'DEFAULT' 'DEFINED' 'DEFINITIONS'
+'EMBEDDED' 'END' 'ENUMERATED' 'EXCEPT' 'EXPLICIT'
+'EXPORTS' 'EXTENSIBILITY' 'EXTERNAL' 'FALSE' 'FROM' 'GeneralizedTime'
+'TYPE-IDENTIFIER'
+'IDENTIFIER' 'IMPLICIT' 'IMPLIED' 'IMPORTS'
+'INCLUDES' 'INSTANCE' 'INTEGER' 'INTERSECTION'
+'MAX' 'MIN' 'MINUS-INFINITY' 'NULL'
+'OBJECT' 'ObjectDescriptor' 'OCTET' 'OF' 'OPTIONAL' 'PDV' 'PLUS-INFINITY'
+'PRESENT' 'PRIVATE' 'REAL' 'SEQUENCE' 'SET' 'SIZE'
+'STRING' 'SYNTAX' 'TAGS' 'TRUE' 'UNION'
+'UNIQUE' 'UNIVERSAL' 'UTCTime' 'WITH'
+'{' '}' '(' ')' '.' '::=' ';' ',' '@' '*' '-' '[' ']'
+'!' '..' '...' '|' '<' ':' '^'
+number identifier typereference restrictedcharacterstringtype
+bstring hstring cstring typefieldreference valuefieldreference
+objectclassreference word.
+
+Rootsymbol ModuleDefinition.
+Endsymbol '$end'.
+
+Left 300 'EXCEPT'.
+Left 200 '^'.
+Left 200 'INTERSECTION'.
+Left 100 '|'.
+Left 100 'UNION'.
+
+
+ModuleDefinition -> ModuleIdentifier
+ 'DEFINITIONS'
+ TagDefault
+ ExtensionDefault
+ '::='
+ 'BEGIN'
+ ModuleBody
+ 'END' :
+ {'ModuleBody',Ex,Im,Types} = '$7',
+ {{typereference,Pos,Name},Defid} = '$1',
+ #module{
+ pos= Pos,
+ name= Name,
+ defid= Defid,
+ tagdefault='$3',
+ extensiondefault='$4',
+ exports=Ex,
+ imports=Im,
+ typeorval=Types}.
+% {module, '$1','$3','$6'}.
+% Results always in a record of type module defined in asn_records.hlr
+
+ModuleIdentifier -> typereference DefinitiveIdentifier :
+ put(asn1_module,'$1'#typereference.val),
+ {'$1','$2'}.
+
+DefinitiveIdentifier -> '{' DefinitiveObjIdComponentList '}' : '$2' .
+DefinitiveIdentifier -> '$empty': [].
+
+DefinitiveObjIdComponentList -> DefinitiveObjIdComponent : ['$1'].
+DefinitiveObjIdComponentList -> DefinitiveObjIdComponent DefinitiveObjIdComponentList : ['$1'|'$2'].
+
+DefinitiveObjIdComponent -> identifier : '$1' . %expanded->
+% DefinitiveObjIdComponent -> NameForm : '$1' .
+DefinitiveObjIdComponent -> number : '$1' . %expanded->
+% DefinitiveObjIdComponent -> DefinitiveNumberForm : 'fix' .
+DefinitiveObjIdComponent -> identifier '(' number ')' : {'$1','$3'} . %expanded->
+% DefinitiveObjIdComponent -> DefinitiveNameAndNumberForm : {'$1','$3'} .
+
+% DefinitiveNumberForm -> number : 'fix' .
+
+% DefinitiveNameAndNumberForm -> identifier '(' DefinitiveNumberForm ')' : 'fix' .
+
+TagDefault -> 'EXPLICIT' 'TAGS' : put(tagdefault,'EXPLICIT'),'EXPLICIT' .
+TagDefault -> 'IMPLICIT' 'TAGS' : put(tagdefault,'IMPLICIT'),'IMPLICIT' .
+TagDefault -> 'AUTOMATIC' 'TAGS' : put(tagdefault,'AUTOMATIC'),'AUTOMATIC' .
+TagDefault -> '$empty': put(tagdefault,'EXPLICIT'),'EXPLICIT'. % because this is the default
+
+ExtensionDefault -> 'EXTENSIBILITY' 'IMPLIED' : 'IMPLIED'.
+ExtensionDefault -> '$empty' : 'false'. % because this is the default
+
+ModuleBody -> Exports Imports AssignmentList : {'ModuleBody','$1','$2','$3'}.
+ModuleBody -> '$empty' : {'ModuleBody',nil,nil,[]}.
+
+Exports -> 'EXPORTS' SymbolList ';' : {exports,'$2'}.
+Exports -> 'EXPORTS' ';' : {exports,[]}.
+Exports -> '$empty' : {exports,all} .
+
+% inlined above SymbolsExported -> SymbolList : '$1'.
+% inlined above SymbolsExported -> '$empty' : [].
+
+Imports -> 'IMPORTS' SymbolsFromModuleList ';' : {imports,'$2'}.
+Imports -> 'IMPORTS' ';' : {imports,[]}.
+Imports -> '$empty' : {imports,[]} .
+
+% inlined above SymbolsImported -> SymbolsFromModuleList : '$1'.
+% inlined above SymbolsImported -> '$empty' : [].
+
+SymbolsFromModuleList -> SymbolsFromModule :['$1'].
+% SymbolsFromModuleList -> SymbolsFromModuleList SymbolsFromModule :$1.%changed
+SymbolsFromModuleList -> SymbolsFromModule SymbolsFromModuleList :['$1'|'$2'].
+
+% expanded SymbolsFromModule -> SymbolList 'FROM' GlobalModuleReference : #'SymbolsFromModule'{symbols = '$1',module='$3'}.
+SymbolsFromModule -> SymbolList 'FROM' typereference : #'SymbolsFromModule'{symbols = '$1',module='$3'}.
+SymbolsFromModule -> SymbolList 'FROM' typereference '{' ValueList '}': #'SymbolsFromModule'{symbols = '$1',module='$3'}.
+%SymbolsFromModule -> SymbolList 'FROM' typereference identifier: #'SymbolsFromModule'{symbols = '$1',module='$3'}.
+%SymbolsFromModule -> SymbolList 'FROM' typereference Externalvaluereference: #'SymbolsFromModule'{symbols = '$1',module='$3'}.
+%SymbolsFromModule -> SymbolList 'FROM' typereference DefinedValue: #'SymbolsFromModule'{symbols = '$1',module='$3'}.
+
+% inlined GlobalModuleReference -> typereference AssignedIdentifier : {'$1','$2'} .
+
+% inlined above AssignedIdentifier -> '{' ValueList '}' : '$2'.
+% replaced AssignedIdentifier -> '{' DefinedValue ObjIdComponentList '}' :{'$2','$3'}.
+% not necessary , replaced by SAndSOfValue AssignedIdentifier -> ObjectIdentifierValue :'$1'.
+% AssignedIdentifier -> DefinedValue : '$1'.
+% inlined AssignedIdentifier -> '$empty' : undefined.
+
+SymbolList -> Symbol : ['$1'].
+SymbolList -> Symbol ',' SymbolList :['$1'|'$3'].
+
+Symbol -> Reference :'$1'.
+% later Symbol -> ParameterizedReference :'$1'.
+
+Reference -> typereference :'$1'.
+Reference -> identifier:'$1'.
+Reference -> typereference '{' '}':'$1'.
+Reference -> Externaltypereference '{' '}':'$1'.
+
+% later Reference -> objectclassreference :'$1'.
+% later Reference -> objectreference :'$1'.
+% later Reference -> objectsetreference :'$1'.
+
+AssignmentList -> Assignment : ['$1'].
+% modified AssignmentList -> AssignmentList Assignment : '$1'.
+AssignmentList -> Assignment AssignmentList : ['$1'|'$2'].
+
+Assignment -> TypeAssignment : '$1'.
+Assignment -> ValueAssignment : '$1'.
+% later Assignment -> ValueSetTypeAssignment : '$1'.
+Assignment -> ObjectClassAssignment : '$1'.
+% later Assignment -> ObjectAssignment : '$1'.
+% combined with ValueAssignment Assignment -> ObjectAssignment : '$1'.
+Assignment -> ObjectSetAssignment : '$1'.
+Assignment -> ParameterizedTypeAssignment : '$1'.
+%Assignment -> ParameterizedValueAssignment : '$1'.
+%Assignment -> ParameterizedValueSetTypeAssignment : '$1'.
+%Assignment -> ParameterizedObjectClassAssignment : '$1'.
+
+ObjectClassAssignment -> typereference '::=' 'CLASS' '{' FieldSpecs '}' :
+%ObjectClassAssignment -> objectclassreference '::=' 'CLASS' '{' FieldSpecs '}' :
+ #typedef{pos=element(2,'$1'),name=element(3,'$1'),typespec={'CLASS','$5',[]}}.
+ObjectClassAssignment -> typereference '::=' 'CLASS' '{' FieldSpecs '}' WithSyntaxSpec :
+%ObjectClassAssignment -> objectclassreference '::=' 'CLASS' '{' FieldSpecs '}' WithSyntaxSpec :
+ #typedef{pos=element(2,'$1'),name=element(3,'$1'),typespec={'CLASS','$5','$7'}}.
+
+FieldSpecs -> FieldSpec : ['$1'].
+FieldSpecs -> FieldSpec ',' FieldSpecs : ['$1'|'$3'].
+
+FieldSpec -> typefieldreference TypeOptionalitySpec : {typefield,'$1','$2'}.
+
+FieldSpec -> valuefieldreference Type 'UNIQUE' ValueOrObjectOptSpec :
+ {fixedtypevaluefield,'$1','$2','UNIQUE','$4'}.
+FieldSpec -> valuefieldreference Type ValueOrObjectOptSpec :
+ {fixedtypevaluefield,'$1','$2',undefined,'$3'}.
+
+FieldSpec -> valuefieldreference typefieldreference ValueOrObjectOptSpec :
+ {variabletypevaluefield, '$1','$2','$3'}.
+
+FieldSpec -> typefieldreference typefieldreference VSetOrOSetOptSpec :
+ {variabletypevaluesetfield, '$1','$2','$3'}.
+
+FieldSpec -> typefieldreference Type VSetOrOSetOptSpec :
+ {fixedtypevaluesetfield, '$1','$2','$3'}.
+
+TypeOptionalitySpec -> 'DEFAULT' Type : {'DEFAULT','$2'}.
+TypeOptionalitySpec -> 'OPTIONAL' : 'OPTIONAL'.
+TypeOptionalitySpec -> '$empty' : 'MANDATORY'.
+
+ValueOrObjectOptSpec -> ValueOptionalitySpec : '$1'.
+ValueOrObjectOptSpec -> ObjectOptionalitySpec : '$1'.
+ValueOrObjectOptSpec -> 'OPTIONAL' : 'OPTIONAL'.
+ValueOrObjectOptSpec -> '$empty' : 'MANDATORY'.
+
+ValueOptionalitySpec -> 'DEFAULT' Value :
+ case '$2' of
+ {identifier,_,Id} -> {'DEFAULT',Id};
+ _ -> {'DEFAULT','$2'}
+ end.
+
+%ObjectOptionalitySpec -> 'DEFAULT' Object :{'DEFAULT','$1'}.
+ObjectOptionalitySpec -> 'DEFAULT' '{' FieldSetting ',' FieldSettings '}' :
+ {'DEFAULT',{object,['$2'|'$4']}}.
+ObjectOptionalitySpec -> 'DEFAULT' '{' FieldSetting '}' :
+ {'DEFAULT',{object, ['$2']}}.
+%ObjectOptionalitySpec -> 'DEFAULT' '{' DefinedSyntaxTokens '}' :
+% {'DEFAULT',{object, '$2'}}.
+ObjectOptionalitySpec -> 'DEFAULT' ObjectFromObject :
+ {'DEFAULT',{object, '$2'}}.
+
+
+VSetOrOSetOptSpec -> ValueSetOptionalitySpec : '$1'.
+%VSetOrOSetOptSpec -> ObjectSetOptionalitySpec : '$1'.
+VSetOrOSetOptSpec -> 'OPTIONAL' : 'OPTIONAL'.
+VSetOrOSetOptSpec -> '$empty' : 'MANDATORY'.
+
+ValueSetOptionalitySpec -> 'DEFAULT' ValueSet : {'DEFAULT','$1'}.
+
+%ObjectSetOptionalitySpec -> 'DEFAULT' ObjectSet : {'DEFAULT','$1'}.
+
+OptionalitySpec -> 'DEFAULT' Type : {'DEFAULT','$2'}.
+OptionalitySpec -> 'DEFAULT' ValueNotNull :
+ case '$2' of
+ {identifier,_,Id} -> {'DEFAULT',Id};
+ _ -> {'DEFAULT','$2'}
+ end.
+OptionalitySpec -> 'OPTIONAL' : 'OPTIONAL'.
+OptionalitySpec -> '$empty' : 'MANDATORY'.
+
+WithSyntaxSpec -> 'WITH' 'SYNTAX' SyntaxList : {'WITH SYNTAX','$3'}.
+
+SyntaxList -> '{' TokenOrGroupSpecs '}' : '$2'.
+SyntaxList -> '{' '}' : [].
+
+TokenOrGroupSpecs -> TokenOrGroupSpec : ['$1'].
+TokenOrGroupSpecs -> TokenOrGroupSpec TokenOrGroupSpecs : ['$1'|'$2'].
+
+TokenOrGroupSpec -> RequiredToken : '$1'.
+TokenOrGroupSpec -> OptionalGroup : '$1'.
+
+OptionalGroup -> '[' TokenOrGroupSpecs ']' : '$2'.
+
+RequiredToken -> typereference : '$1'.
+RequiredToken -> Word : '$1'.
+RequiredToken -> ',' : '$1'.
+RequiredToken -> PrimitiveFieldName : '$1'.
+
+Word -> 'BY' : 'BY'.
+
+ParameterizedTypeAssignment -> typereference ParameterList '::=' Type :
+ #ptypedef{pos=element(2,'$1'),name=element(3,'$1'),
+ args='$2', typespec='$4'}.
+
+ParameterList -> '{' Parameters '}':'$2'.
+
+Parameters -> Parameter: ['$1'].
+Parameters -> Parameter ',' Parameters: ['$1'|'$3'].
+
+Parameter -> typereference: '$1'.
+Parameter -> Value: '$1'.
+Parameter -> Type ':' typereference: {'$1','$3'}.
+Parameter -> Type ':' Value: {'$1','$3'}.
+Parameter -> '{' typereference '}': {objectset,'$2'}.
+
+
+% Externaltypereference -> modulereference '.' typereference : {'$1','$3'} .
+Externaltypereference -> typereference '.' typereference : #'Externaltypereference'{pos=element(2,'$1'),module=element(3,'$1'),type=element(3,'$3')}.
+
+% Externalvaluereference -> modulereference '.' valuereference : {'$1','$3'} .
+% inlined Externalvaluereference -> typereference '.' identifier : #'Externalvaluereference'{pos=element(2,'$1'),module=element(3,'$1'),value=element(3,'$3')}.
+
+
+DefinedType -> Externaltypereference : '$1' .
+DefinedType -> typereference :
+ #'Externaltypereference'{pos='$1'#typereference.pos,
+ module= get(asn1_module),
+ type= '$1'#typereference.val} .
+DefinedType -> typereference ParameterList : {pt,'$1','$2'}.
+DefinedType -> Externaltypereference ParameterList : {pt,'$1','$2'}.
+
+% ActualParameterList -> '{' ActualParameters '}' : '$1'.
+
+% ActualParameters -> ActualParameter : ['$1'].
+% ActualParameters -> ActualParameter ',' ActualParameters : ['$1'|'$3'].
+
+ActualParameter -> Type : '$1'.
+ActualParameter -> ValueNotNull : '$1'.
+ActualParameter -> ValueSet : '$1'.
+% later DefinedType -> ParameterizedType : '$1' .
+% later DefinedType -> ParameterizedValueSetType : '$1' .
+
+% inlined DefinedValue -> Externalvaluereference :'$1'.
+% inlined DefinedValue -> identifier :'$1'.
+% later DefinedValue -> ParameterizedValue :'$1'.
+
+% not referenced yet AbsoluteReference -> '@' GlobalModuleReference '.' ItemSpec :{'$2','$4'}.
+
+% not referenced yet ItemSpec -> typereference :'$1'.
+% not referenced yet ItemSpec -> ItemId '.' ComponentId : {'$1','$3'}.
+
+% not referenced yet ItemId -> ItemSpec : '$1'.
+
+% not referenced yet ComponentId -> identifier :'$1'.
+% not referenced yet ComponentId -> number :'$1'.
+% not referenced yet ComponentId -> '*' :'$1'.
+
+TypeAssignment -> typereference '::=' Type :
+ #typedef{pos=element(2,'$1'),name=element(3,'$1'),typespec='$3'}.
+
+ValueAssignment -> identifier Type '::=' Value :
+ #valuedef{pos=element(2,'$1'),name=element(3,'$1'),type='$2',value='$4'}.
+
+% later ValueSetTypeAssignment -> typereference Type '::=' ValueSet :{'ValueSetTypeAssignment','$1','$2','$4'}.
+
+
+ValueSet -> '{' ElementSetSpec '}' : {valueset,'$2'}.
+
+% record(type,{tag,def,constraint}).
+Type -> BuiltinType :#type{def='$1'}.
+Type -> 'NULL' :#type{def='NULL'}.
+Type -> TaggedType:'$1'.
+Type -> ReferencedType:#type{def='$1'}. % change notag later
+Type -> ConstrainedType:'$1'.
+
+%ANY is here for compatibility with the old ASN.1 standard from 1988
+BuiltinType -> 'ANY' AnyDefBy:
+ case '$2' of
+ [] -> 'ANY';
+ _ -> {'ANY DEFINED BY','$2'}
+ end.
+BuiltinType -> BitStringType :'$1'.
+BuiltinType -> 'BOOLEAN' :element(1,'$1').
+BuiltinType -> CharacterStringType :'$1'.
+BuiltinType -> ChoiceType :'$1'.
+BuiltinType -> 'EMBEDDED' 'PDV' :'EMBEDDED PDV'.
+BuiltinType -> EnumeratedType :'$1'.
+BuiltinType -> 'EXTERNAL' :element(1,'$1').
+% later BuiltinType -> InstanceOfType :'$1'.
+BuiltinType -> IntegerType :'$1'.
+% BuiltinType -> 'NULL' :element(1,'$1').
+% later BuiltinType -> ObjectClassFieldType :'$1'.
+BuiltinType -> 'OBJECT' 'IDENTIFIER' :'OBJECT IDENTIFIER'.
+BuiltinType -> 'OCTET' 'STRING' :'OCTET STRING'.
+BuiltinType -> 'REAL' :element(1,'$1').
+BuiltinType -> SequenceType :'$1'.
+BuiltinType -> SequenceOfType :'$1'.
+BuiltinType -> SetType :'$1'.
+BuiltinType -> SetOfType :'$1'.
+% The so called Useful types
+BuiltinType -> 'GeneralizedTime': 'GeneralizedTime'.
+BuiltinType -> 'UTCTime' :'UTCTime'.
+BuiltinType -> 'ObjectDescriptor' : 'ObjectDescriptor'.
+
+% moved BuiltinType -> TaggedType :'$1'.
+
+
+AnyDefBy -> 'DEFINED' 'BY' identifier: '$3'.
+AnyDefBy -> '$empty': [].
+
+NamedType -> identifier Type :
+%{_,Pos,Val} = '$1',
+%{'NamedType',Pos,{Val,'$2'}}.
+V1 = '$1',
+{'NamedType',V1#identifier.pos,{V1#identifier.val,'$2'}}.
+NamedType -> SelectionType :'$1'.
+
+ReferencedType -> DefinedType : '$1'.
+% redundant ReferencedType -> UsefulType : 'fix'.
+ReferencedType -> SelectionType : '$1'.
+ReferencedType -> TypeFromObject : '$1'.
+% later ReferencedType -> ValueSetFromObjects : 'fix'.
+
+% to much conflicts Value -> AnyValue :'$1'.
+Value -> ValueNotNull : '$1'.
+Value -> 'NULL' :element(1,'$1').
+
+ValueNotNull -> BuiltinValue :'$1'.
+% inlined Value -> DefinedValue :'$1'. % DefinedValue , identifier
+% inlined Externalvaluereference -> Externalvaluereference :'$1'.
+ValueNotNull -> typereference '.' identifier :
+ #'Externalvaluereference'{pos=element(2,'$1'),module=element(3,'$1'),
+ value=element(3,'$3')}.
+ValueNotNull -> identifier :'$1'.
+
+
+%tmp Value -> NamedNumber: '$1'. % not a value but part of ObjIdC
+% redundant BuiltinValue -> BitStringValue :'$1'.
+BuiltinValue -> BooleanValue :'$1'.
+BuiltinValue -> CharacterStringValue :'$1'.
+BuiltinValue -> ChoiceValue :'$1'.
+% BuiltinValue -> EmbeddedPDVValue :'$1'. ==SequenceValue
+% BuiltinValue -> EnumeratedValue :'$1'. identifier
+% BuiltinValue -> ExternalValue :'$1'. ==SequenceValue
+% later BuiltinValue -> InstanceOfValue :'$1'.
+BuiltinValue -> SignedNumber :'$1'.
+% BuiltinValue -> 'NULL' :'$1'.
+% later BuiltinValue -> ObjectClassFieldValue :'$1'.
+% replaced by SAndSOfValue BuiltinValue -> ObjectIdentifierValue :'$1'.
+BuiltinValue -> bstring :element(3,'$1').
+BuiltinValue -> hstring :element(3,'$1').
+% conflict BuiltinValue -> RealValue :'$1'.
+BuiltinValue -> SAndSOfValue :'$1'.
+% replaced BuiltinValue -> SequenceOfValue :'$1'.
+% replaced BuiltinValue -> SequenceValue :'$1'.
+% replaced BuiltinValue -> SetValue :'$1'.
+% replaced BuiltinValue -> SetOfValue :'$1'.
+% conflict redundant BuiltinValue -> TaggedValue :'$1'.
+
+% inlined ReferencedValue -> DefinedValue:'$1'.
+% ReferencedValue -> Externalvaluereference:'$1'.
+% ReferencedValue -> identifier :'$1'.
+% later ReferencedValue -> ValueFromObject:'$1'.
+
+% inlined BooleanType -> BOOLEAN :'BOOLEAN'.
+
+% to much conflicts AnyValue -> Type ':' Value : {'ANYVALUE',{'$1','$3'}}.
+
+BooleanValue -> TRUE :true.
+BooleanValue -> FALSE :false.
+
+IntegerType -> 'INTEGER' : 'INTEGER'.
+IntegerType -> 'INTEGER' '{' NamedNumberList '}' : {'INTEGER','$3'}.
+
+NamedNumberList -> NamedNumber :['$1'].
+% modified NamedNumberList -> NamedNumberList ',' NamedNumber :'fix'.
+NamedNumberList -> NamedNumber ',' NamedNumberList :['$1'|'$3'].
+
+NamedNumber -> identifier '(' SignedNumber ')' : {'NamedNumber',element(3,'$1'),'$3'}.
+NamedNumber -> identifier '(' typereference '.' identifier ')' : {'NamedNumber',element(3,'$1'),{'ExternalValue',element(3,'$3'),element(3,'$5')}}.
+NamedNumber -> identifier '(' identifier ')' : {'NamedNumber',element(3,'$1'),element(3,'$3')}.
+
+%NamedValue -> identifier Value :
+% {'NamedValue',element(2,'$1'),element(3,'$1'),'$2'}.
+
+
+SignedNumber -> number : element(3,'$1').
+SignedNumber -> '-' number : - element(3,'$1').
+
+% inlined IntegerValue -> SignedNumber :'$1'.
+% conflict moved to Value IntegerValue -> identifier:'$1'.
+
+EnumeratedType -> ENUMERATED '{' Enumeration '}' :{'ENUMERATED','$3'}.
+
+% inlined Enumerations -> Enumeration :{'$1','false',[]}.
+% inlined Enumerations -> Enumeration ',' '...' : {'$1','true',[]}.
+% inlined Enumerations -> Enumeration ',' '...' ',' Enumeration : {'$1','true','$5'}.
+
+Enumeration -> EnumerationItem :['$1'].
+% modified Enumeration -> EnumerationItem ',' Enumeration :'fix'.
+Enumeration -> EnumerationItem ',' Enumeration :['$1'|'$3'].
+
+EnumerationItem -> identifier:element(3,'$1').
+EnumerationItem -> NamedNumber :'$1'.
+EnumerationItem -> '...' :'EXTENSIONMARK'.
+
+% conflict moved to Value EnumeratedValue -> identifier:'$1'.
+
+% inlined RealType -> REAL:'REAL'.
+
+RealValue -> NumericRealValue :'$1'.
+RealValue -> SpecialRealValue:'$1'.
+
+% ?? NumericRealValue -> number:'$1'. % number MUST BE '0'
+NumericRealValue -> SAndSOfValue : '$1'. % Value of the associated sequence type
+
+SpecialRealValue -> 'PLUS-INFINITY' :'$1'.
+SpecialRealValue -> 'MINUS-INFINITY' :'$1'.
+
+BitStringType -> 'BIT' 'STRING' :{'BIT STRING',[]}.
+BitStringType -> 'BIT' 'STRING' '{' NamedNumberList '}' :{'BIT STRING','$4'}.
+% NamedBitList replaced by NamedNumberList to reduce the grammar
+% Must check later that all "numbers" are positive
+
+% inlined BitStringValue -> bstring:'$1'.
+% inlined BitStringValue -> hstring:'$1'.
+% redundant use SequenceValue BitStringValue -> '{' IdentifierList '}' :$2.
+% redundant use SequenceValue BitStringValue -> '{' '}' :'fix'.
+
+IdentifierList -> identifier :[element(3,'$1')].
+% modified IdentifierList -> IdentifierList ',' identifier :'$1'.
+IdentifierList -> identifier ',' IdentifierList :[element(3,'$1')|'$3'].
+
+% inlined OctetStringType -> 'OCTET' 'STRING' :'OCTET STRING'.
+
+% inlined OctetStringValue -> bstring:'$1'.
+% inlined OctetStringValue -> hstring:'$1'.
+
+% inlined NullType -> 'NULL':'NULL'.
+
+% inlined NullValue -> NULL:'NULL'.
+
+% result is {'SEQUENCE',Optionals,Extensionmark,Componenttypelist}.
+SequenceType -> SEQUENCE '{' ComponentTypeList '}' :{'SEQUENCE','$3'}.
+% SequenceType -> SEQUENCE '{' ComponentTypeLists '}' :{'SEQUENCE','$3'}.
+% SequenceType -> SEQUENCE '{' ExtensionAndException '}' :{'SEQUENCE','$3'}.
+SequenceType -> SEQUENCE '{' '}' :{'SEQUENCE',[]}.
+
+% result is {RootComponentList,ExtensionAndException,AdditionalComponentTypeList}.
+%ComponentTypeLists -> ComponentTypeList ',' ExtensionAndException :{'$1','$3',[]}.
+%ComponentTypeLists -> ComponentTypeList :{'$1','false',[]}.
+%ComponentTypeLists -> ComponentTypeList ',' ExtensionAndException
+% ',' ComponentTypeList :{'$1','$3', '$5'}.
+%ComponentTypeLists -> ExtensionAndException ',' ComponentTypeList :{[],'$1','$3'}.
+
+ComponentTypeList -> ComponentType :['$1'].
+% modified below ComponentTypeList -> ComponentTypeList ',' ComponentType :'$1'.
+ComponentTypeList -> ComponentType ',' ComponentTypeList :['$1'|'$3'].
+
+% -record('ComponentType',{pos,name,type,attrib}).
+ComponentType -> '...' ExceptionSpec :{'EXTENSIONMARK',element(2,'$1'),'$2'}.
+ComponentType -> NamedType :
+ {'NamedType',Pos,{Name,Type}} = '$1',
+ #'ComponentType'{pos=Pos,name=Name,typespec=Type,prop=mandatory}.
+ComponentType -> NamedType 'OPTIONAL' :
+ {'NamedType',Pos,{Name,Type}} = '$1',
+ #'ComponentType'{pos=Pos,name=Name,typespec=Type,prop='OPTIONAL'}.
+ComponentType -> NamedType 'DEFAULT' Value:
+ {'NamedType',Pos,{Name,Type}} = '$1',
+ #'ComponentType'{pos=Pos,name=Name,typespec=Type,prop={'DEFAULT','$3'}}.
+ComponentType -> 'COMPONENTS' 'OF' Type :{'COMPONENTS OF','$3'}.
+
+% redundant ExtensionAndException -> '...' : extensionmark.
+% ExtensionAndException -> '...' ExceptionSpec : {extensionmark,'$2'}.
+
+% replaced SequenceValue -> '{' ComponentValueList '}':'$2'.
+% replaced SequenceValue -> '{' '}':[].
+
+ValueList -> Value :['$1'].
+ValueList -> NamedNumber :['$1'].
+% modified ValueList -> ValueList ',' Value :'$1'.
+ValueList -> Value ',' ValueList :['$1'|'$3'].
+ValueList -> Value ',' '...' :['$1' |[]].
+ValueList -> Value ValueList : ['$1',space|'$2'].
+ValueList -> NamedNumber ValueList: ['$1',space|'$2'].
+
+%ComponentValueList -> identifier ObjIdComponent:[{'NamedValue','$1','$2'}].
+%ComponentValueList -> NamedValue :['$1'].
+%ComponentValueList -> NamedValue ',' ComponentValueList:['$1'|'$3'].
+%ComponentValueList -> identifier ObjIdComponent ',' ComponentValueList :[{'NamedValue', '$1','$2'}|'$4'].
+
+SequenceOfType -> SEQUENCE OF Type : {'SEQUENCE OF','$3'}.
+
+% replaced SequenceOfValue with SAndSOfValue
+
+SAndSOfValue -> '{' ValueList '}' :'$2'.
+%SAndSOfValue -> '{' ComponentValueList '}' :'$2'.
+SAndSOfValue -> '{' '}' :[].
+
+% save for later SetType ->
+% result is {'SET',Optionals,Extensionmark,Componenttypelist}.
+SetType -> SET '{' ComponentTypeList '}' :{'SET','$3'}.
+% SetType -> SET '{' ExtensionAndException '}' :{'SET','$3'}.
+SetType -> SET '{' '}' :{'SET',[]}.
+
+% replaced SetValue with SAndSOfValue
+
+SetOfType -> SET OF Type : {'SET OF','$3'}.
+
+% replaced SetOfValue with SAndSOfValue
+
+ChoiceType -> 'CHOICE' '{' ComponentTypeList '}' :{'CHOICE','$3'}.
+% AlternativeTypeList is replaced by ComponentTypeList
+ChoiceValue -> identifier ':' Value : {'ChoiceValue',element(3,'$1'),'$3'}.
+% save for later SelectionType ->
+
+TaggedType -> Tag Type : '$2'#type{tag=['$1'#tag{type={default,get(tagdefault)}}]}.
+TaggedType -> Tag IMPLICIT Type :'$3'#type{tag=['$1'#tag{type='IMPLICIT'}]}.
+TaggedType -> Tag EXPLICIT Type :'$3'#type{tag=['$1'#tag{type='EXPLICIT'}]}.
+
+Tag -> '[' Class ClassNumber ']': #tag{class='$2',number='$3'}.
+Tag -> '[' Class typereference '.' identifier ']':
+ #tag{class='$2',number=#'Externalvaluereference'{pos=element(2,'$3'),module=element(3,'$3'),
+ value=element(3,'$5')}}.
+Tag -> '[' Class number ']': #tag{class='$2',number=element(3,'$3')}.
+Tag -> '[' Class identifier ']': #tag{class='$2',number=element(3,'$3')}.
+
+ClassNumber -> number :element(3,'$1').
+% inlined above ClassNumber -> typereference '.' identifier :{'Externalvaluereference',element(3,'$1'),element(3,'$3')}.
+ClassNumber -> identifier :element(3,'$1').
+
+Class -> 'UNIVERSAL' :element(1,'$1').
+Class -> 'APPLICATION' :element(1,'$1').
+Class -> 'PRIVATE' :element(1,'$1').
+Class -> '$empty' :'CONTEXT'.
+
+% conflict redundant TaggedValue -> Value:'$1'.
+
+% inlined EmbeddedPDVType -> 'EMBEDDED' 'PDV' :'EMBEDDED PDV'.
+
+% inlined EmbeddedPDVValue -> SequenceValue:'$1'.
+
+% inlined ExternalType -> 'EXTERNAL' :'EXTERNAL'.
+
+% inlined ExternalValue -> SequenceValue :'$1'.
+
+% inlined ObjectIdentifierType -> 'OBJECT' 'IDENTIFIER' :'OBJECT IDENTIFIER'.
+
+ObjectIdentifierValue -> '{' ObjIdComponentList '}' :'$2'.
+% inlined ObjectIdentifierValue -> SequenceAndSequenceOfValue :'$1'.
+% ObjectIdentifierValue -> '{' identifier ObjIdComponentList '}' :{'ObjectIdentifierValue','$2','$3'}.
+% ObjectIdentifierValue -> '{' typereference '.' identifier ObjIdComponentList '}' :{'ObjectIdentifierValue',{'$2','$4'},'$5'}.
+
+ObjIdComponentList -> Value:'$1'.
+ObjIdComponentList -> Value ObjIdComponentList :['$1'|'$2'].
+%ObjIdComponentList -> DefinedValue:'$1'.
+%ObjIdComponentList -> number:'$1'.
+%ObjIdComponentList -> DefinedValue ObjIdComponentList :['$1'|'$2'].
+%ObjIdComponentList -> number ObjIdComponentList :['$1'|'$2'].
+%ObjIdComponentList -> ObjIdComponent ObjIdComponentList :['$1'|'$2'].
+%ObjIdComponentList -> ObjIdComponent ObjIdComponentList :['$1'|'$2'].
+
+% redundant ObjIdComponent -> NameForm :'$1'. % expanded
+% replaced by 2 ObjIdComponent -> NumberForm :'$1'.
+% ObjIdComponent -> number :'$1'.
+% ObjIdComponent -> DefinedValue :'$1'. % means DefinedValue
+% ObjIdComponent -> NameAndNumberForm :'$1'.
+% ObjIdComponent -> NamedNumber :'$1'.
+% NamedBit replaced by NamedNumber to reduce grammar
+% must check later that "number" is positive
+
+% NameForm -> identifier:'$1'.
+
+% inlined NumberForm -> number :'$1'.
+% inlined NumberForm -> DefinedValue :'$1'.
+
+% replaced by NamedBit NameAndNumberForm -> identifier '(' NumberForm ')'.
+% NameAndNumberForm -> NamedBit:'$1'.
+
+
+CharacterStringType -> restrictedcharacterstringtype :element(3,'$1').
+CharacterStringType -> 'CHARACTER' 'STRING' :'CHARACTER STRING'.
+
+RestrictedCharacterStringValue -> cstring :element(3, '$1').
+% modified below RestrictedCharacterStringValue -> CharacterStringList :'$1'.
+% conflict vs BuiltinValue RestrictedCharacterStringValue -> SequenceAndSequenceOfValue :'$1'.
+RestrictedCharacterStringValue -> Quadruple :'$1'.
+RestrictedCharacterStringValue -> Tuple :'$1'.
+
+% redundant CharacterStringList -> '{' ValueList '}' :'$2'. % modified
+
+% redundant CharSyms -> CharsDefn :'$1'.
+% redundant CharSyms -> CharSyms ',' CharsDefn :['$1'|'$3'].
+
+% redundant CharsDefn -> cstring :'$1'.
+% temporary replaced see below CharsDefn -> DefinedValue :'$1'.
+% redundant CharsDefn -> Value :'$1'.
+
+Quadruple -> '{' number ',' number ',' number ',' number '}' :{'Quadruple','$2','$4','$6','$8'}.
+% {Group,Plane,Row,Cell}
+
+Tuple -> '{' number ',' number '}' :{'Tuple', '$2','$4'}.
+% {TableColumn,TableRow}
+
+% inlined UnrestrictedCharacterString -> 'CHARACTER' 'STRING' :'CHARACTER STRING'.
+
+CharacterStringValue -> RestrictedCharacterStringValue :'$1'.
+% conflict vs BuiltinValue CharacterStringValue -> SequenceValue :'$1'. % UnrestrictedCharacterStringValue
+
+% inlined UsefulType -> typereference :'$1'.
+
+SelectionType -> identifier '<' Type : {'SelectionType',element(3,'$1'),'$3'}.
+
+ConstrainedType -> Type Constraint :
+ '$1'#type{constraint=merge_constraints(['$2'])}.
+ConstrainedType -> Type Constraint Constraint :
+ '$1'#type{constraint=merge_constraints(['$2','$3'])}.
+ConstrainedType -> Type Constraint Constraint Constraint:
+ '$1'#type{constraint=merge_constraints(['$2','$3','$4'])}.
+ConstrainedType -> Type Constraint Constraint Constraint Constraint:
+ '$1'#type{constraint=merge_constraints(['$2','$3','$4','$5'])}.
+%ConstrainedType -> Type Constraint :'$1'#type{constraint='$2'}.
+%ConstrainedType -> Type Constraint :'$1'#type{constraint='$2'}.
+ConstrainedType -> TypeWithConstraint :'$1'.
+
+TypeWithConstraint -> 'SET' Constraint 'OF' Type :
+ #type{def = {'SET OF','$4'},constraint=merge_constraints(['$2'])}.
+TypeWithConstraint -> 'SET' 'SIZE' Constraint 'OF' Type :
+ #type{def = {'SET OF','$5'},constraint = merge_constraints([#constraint{c={'SizeConstraint','$3'#constraint.c}}])}.
+TypeWithConstraint -> 'SEQUENCE' Constraint 'OF' Type :
+ #type{def = {'SEQUENCE OF','$4'},constraint =
+ merge_constraints(['$2'])}.
+TypeWithConstraint -> 'SEQUENCE' 'SIZE' Constraint 'OF' Type :
+ #type{def = {'SEQUENCE OF','$5'},constraint = merge_constraints([#constraint{c={'SizeConstraint','$3'#constraint.c}}])}.
+
+
+Constraint -> '(' ConstraintSpec ExceptionSpec ')' :
+ #constraint{c='$2',e='$3'}.
+
+% inlined Constraint -> SubTypeConstraint :'$1'.
+ConstraintSpec -> ElementSetSpecs :'$1'.
+ConstraintSpec -> UserDefinedConstraint :'$1'.
+ConstraintSpec -> TableConstraint :'$1'.
+
+TableConstraint -> ComponentRelationConstraint : '$1'.
+TableConstraint -> ObjectSet : '$1'.
+%TableConstraint -> '{' typereference '}' :tableconstraint.
+
+ComponentRelationConstraint -> '{' typereference '}' '{' '@' ComponentIdList '}' : componentrelation.
+ComponentRelationConstraint -> '{' typereference '}' '{' '@' '.' ComponentIdList '}' : componentrelation.
+
+ComponentIdList -> identifier: ['$1'].
+ComponentIdList -> identifier '.' ComponentIdList: ['$1'| '$3'].
+
+
+% later ConstraintSpec -> GeneralConstraint :'$1'.
+
+% from X.682
+UserDefinedConstraint -> 'CONSTRAINED' 'BY' '{' '}' : {constrained_by,[]}.
+UserDefinedConstraint -> 'CONSTRAINED' 'BY'
+ '{' UserDefinedConstraintParameters '}' : {constrained_by,'$4'}.
+
+UserDefinedConstraintParameters -> UserDefinedConstraintParameter : ['$1'].
+UserDefinedConstraintParameters ->
+ UserDefinedConstraintParameter ','
+ UserDefinedConstraintParameters: ['$1'|'$3'].
+
+UserDefinedConstraintParameter -> Type '.' ActualParameter : {'$1','$3'}.
+UserDefinedConstraintParameter -> ActualParameter : '$1'.
+
+
+
+ExceptionSpec -> '!' ExceptionIdentification : '$1'.
+ExceptionSpec -> '$empty' : undefined.
+
+ExceptionIdentification -> SignedNumber : '$1'.
+% inlined ExceptionIdentification -> DefinedValue : '$1'.
+ExceptionIdentification -> typereference '.' identifier :
+ #'Externalvaluereference'{pos=element(2,'$1'),module=element(3,'$1'),
+ value=element(3,'$1')}.
+ExceptionIdentification -> identifier :'$1'.
+ExceptionIdentification -> Type ':' Value : {'$1','$3'}.
+
+% inlined SubTypeConstraint -> ElementSetSpec
+
+ElementSetSpecs -> ElementSetSpec : '$1'.
+ElementSetSpecs -> ElementSetSpec ',' '...': {'$1',[]}.
+ElementSetSpecs -> '...' ',' ElementSetSpec : {[],'$3'}.
+ElementSetSpecs -> ElementSetSpec ',' '...' ',' ElementSetSpec : {'$1','$5'}.
+
+ElementSetSpec -> Unions : '$1'.
+ElementSetSpec -> 'ALL' Exclusions : {'ALL','$2'}.
+
+Unions -> Intersections : '$1'.
+Unions -> UElems UnionMark IntersectionElements :
+ case {'$1','$3'} of
+ {{'SingleValue',V1},{'SingleValue',V2}} ->
+ {'SingleValue',ordsets:union(to_set(V1),to_set(V2))}
+ end.
+
+UElems -> Unions :'$1'.
+
+Intersections -> IntersectionElements :'$1'.
+Intersections -> IElems IntersectionMark IntersectionElements :
+ case {'$1','$3'} of
+ {{'SingleValue',V1},{'SingleValue',V2}} ->
+ {'SingleValue',ordsets:intersection(to_set(V1),to_set(V2))};
+ {V1,V2} when list(V1) ->
+ V1 ++ [V2];
+ {V1,V2} ->
+ [V1,V2]
+ end.
+%Intersections -> IElems '^' IntersectionElements :{'INTERSECTION','$1','$3'}.
+%Intersections -> IElems 'INTERSECTION' IntersectionElements :{'INTERSECTION','$1','$3'}.
+
+IElems -> Intersections :'$1'.
+
+IntersectionElements -> Elements :'$1'.
+IntersectionElements -> Elems Exclusions :{'$1','$2'}.
+
+Elems -> Elements :'$1'.
+
+Exclusions -> 'EXCEPT' Elements :{'EXCEPT','$2'}.
+
+IntersectionMark -> 'INTERSECTION':'$1'.
+IntersectionMark -> '^':'$1'.
+UnionMark -> 'UNION':'$1'.
+UnionMark -> '|':'$1'.
+
+
+Elements -> SubTypeElements : '$1'.
+%Elements -> ObjectSetElements : '$1'.
+Elements -> '(' ElementSetSpec ')' : '$2'.
+Elements -> ReferencedType : '$1'.
+
+SubTypeElements -> ValueList : {'SingleValue','$1'}. % NOTE it must be a Value
+% The rule above modifyed only because of conflicts
+SubTypeElements -> 'INCLUDES' Type : {'ContainedSubType','$2'}.
+%not lalr1 if this is activated SubTypeElements -> Type : {'TypeConstraint','$1'}.
+SubTypeElements -> LowerEndpoint '..' UpperEndpoint : {'ValueRange',{'$1','$3'}}.
+SubTypeElements -> 'FROM' Constraint : {'PermittedAlphabet','$2'#constraint.c}.
+SubTypeElements -> 'SIZE' Constraint: {'SizeConstraint','$2'#constraint.c}.
+% later will introduce conflicts related to NULL SubTypeElements -> Type : {'TypeConstraint','$1'}.
+SubTypeElements -> 'WITH' 'COMPONENT' Constraint:{'WITH COMPONENT','$3'}.
+SubTypeElements -> 'WITH' 'COMPONENTS' '{' TypeConstraints '}':{'WITH COMPONENTS',{'FullSpecification','$4'}}.
+SubTypeElements -> 'WITH' 'COMPONENTS' '{' '...' ',' TypeConstraints '}' :{'WITH COMPONENTS',{'PartialSpecification','$3'}}.
+
+% inlined above InnerTypeConstraints ::=
+% inlined above SingleTypeConstraint::= Constraint
+% inlined above MultipleTypeConstraints ::= FullSpecification | PartialSpecification
+% inlined above FullSpecification ::= "{" TypeConstraints "}"
+% inlined above PartialSpecification ::= "{" "..." "," TypeConstraints "}"
+% TypeConstraints -> identifier : [{'NamedConstraint',element(3,'$1'),undefined,undefined}]. % is this really meaningful or allowed
+TypeConstraints -> NamedConstraint : ['$1'].
+TypeConstraints -> NamedConstraint ',' TypeConstraints : ['$1'|'$3'].
+TypeConstraints -> identifier : ['$1'].
+TypeConstraints -> identifier ',' TypeConstraints : ['$1'|'$3'].
+
+NamedConstraint -> identifier Constraint PresenceConstraint :{'NamedConstraint',element(3,'$1'),'$2','$3'}.
+NamedConstraint -> identifier Constraint :{'NamedConstraint',element(3,'$1'),'$2',undefined}.
+NamedConstraint -> identifier PresenceConstraint :{'NamedConstraint',element(3,'$1'),undefined,'$2'}.
+
+PresenceConstraint -> 'PRESENT' : 'PRESENT'.
+PresenceConstraint -> 'ABSENT' : 'ABSENT'.
+PresenceConstraint -> 'OPTIONAL' : 'OPTIONAL'.
+
+
+
+LowerEndpoint -> LowerEndValue :'$1'.
+%LowerEndpoint -> LowerEndValue '<':{gt,'$1'}.
+LowerEndpoint -> LowerEndValue '<':('$1'+1).
+
+UpperEndpoint -> UpperEndValue :'$1'.
+%UpperEndpoint -> '<' UpperEndValue :{lt,'$2'}.
+UpperEndpoint -> '<' UpperEndValue :('$2'-1).
+
+LowerEndValue -> Value :'$1'.
+LowerEndValue -> 'MIN' :'MIN'.
+
+UpperEndValue -> Value :'$1'.
+UpperEndValue -> 'MAX' :'MAX'.
+
+
+% X.681
+
+
+% X.681 chap 15
+
+%TypeFromObject -> ReferencedObjects '.' FieldName : {'$1','$3'}.
+TypeFromObject -> typereference '.' FieldName : {'$1','$3'}.
+
+ReferencedObjects -> typereference : '$1'.
+%ReferencedObjects -> ParameterizedObject
+%ReferencedObjects -> DefinedObjectSet
+%ReferencedObjects -> ParameterizedObjectSet
+
+FieldName -> typefieldreference : ['$1'].
+FieldName -> valuefieldreference : ['$1'].
+FieldName -> FieldName '.' FieldName : ['$1' | '$3'].
+
+PrimitiveFieldName -> typefieldreference : '$1'.
+PrimitiveFieldName -> valuefieldreference : '$1'.
+
+%ObjectSetAssignment -> typereference DefinedObjectClass '::=' ObjectSet: null.
+ObjectSetAssignment -> typereference typereference '::=' ObjectSet :
+ #typedef{pos=element(2,'$1'),name=element(3,'$1'),typespec={'ObjectSet',element(3,'$2'), '$4'}}.
+ObjectSetAssignment -> typereference typereference '.' typereference '::=' ObjectSet.
+
+ObjectSet -> '{' ElementSetSpecs '}' : '$2'.
+ObjectSet -> '{' '...' '}' : ['EXTENSIONMARK'].
+
+%ObjectSetElements -> Object.
+% ObjectSetElements -> identifier : '$1'.
+%ObjectSetElements -> DefinedObjectSet.
+%ObjectSetElements -> ObjectSetFromObjects.
+%ObjectSetElements -> ParameterizedObjectSet.
+
+%ObjectAssignment -> identifier DefinedObjectClass '::=' Object.
+ObjectAssignment -> ValueAssignment.
+%ObjectAssignment -> identifier typereference '::=' Object.
+%ObjectAssignment -> identifier typereference '.' typereference '::=' Object.
+
+%Object -> DefinedObject: '$1'.
+%Object -> ExternalObjectReference: '$1'.%Object -> DefinedObject: '$1'.
+Object -> typereference '.' identifier: '$1'.%Object -> DefinedObject: '$1'.
+Object -> identifier: '$1'.%Object -> DefinedObject: '$1'.
+
+%Object -> ObjectDefn -> DefaultSyntax: '$1'.
+Object -> '{' FieldSetting ',' FieldSettings '}' : ['$2'|'$4'].
+Object -> '{' FieldSetting '}' :['$2'].
+
+%% For User-friendly notation
+%% Object -> ObjectDefn -> DefinedSyntax
+Object -> '{' '}'.
+Object -> '{' DefinedSyntaxTokens '}'.
+
+% later Object -> ParameterizedObject: '$1'. look in x.683
+
+%DefinedObject -> ExternalObjectReference: '$1'.
+%DefinedObject -> identifier: '$1'.
+
+DefinedObjectClass -> typereference.
+%DefinedObjectClass -> objectclassreference.
+DefinedObjectClass -> ExternalObjectClassReference.
+%DefinedObjectClass -> typereference '.' objectclassreference.
+%%DefinedObjectClass -> UsefulObjectClassReference.
+
+ExternalObjectReference -> typereference '.' identifier.
+ExternalObjectClassReference -> typereference '.' typereference.
+%%ExternalObjectClassReference -> typereference '.' objectclassreference.
+
+ObjectDefn -> DefaultSyntax: '$1'.
+%ObjectDefn -> DefinedSyntax: '$1'.
+
+ObjectFromObject -> ReferencedObjects '.' FieldName : {'ObjectFromObject','$1','$3'}.
+
+% later look in x.683 ParameterizedObject ->
+
+%DefaultSyntax -> '{' '}'.
+%DefaultSyntax -> '{' FieldSettings '}': '$2'.
+DefaultSyntax -> '{' FieldSetting ',' FieldSettings '}': '$2'.
+DefaultSyntax -> '{' FieldSetting '}': '$2'.
+
+FieldSetting -> PrimitiveFieldName Setting: {'$1','$2'}.
+
+FieldSettings -> FieldSetting ',' FieldSettings: ['$1'|'$3'].
+FieldSettings -> FieldSetting ',' FieldSettings: ['$1'|'$3'].
+FieldSettings -> FieldSetting: '$1'.
+
+%DefinedSyntax -> '{' '}'.
+DefinedSyntax -> '{' DefinedSyntaxTokens '}': '$2'.
+
+DefinedSyntaxTokens -> DefinedSyntaxToken: '$1'.
+DefinedSyntaxTokens -> DefinedSyntaxToken DefinedSyntaxTokens: ['$1'|'$2'].
+
+% expanded DefinedSyntaxToken -> Literal: '$1'.
+%DefinedSyntaxToken -> typereference: '$1'.
+DefinedSyntaxToken -> word: '$1'.
+DefinedSyntaxToken -> ',': '$1'.
+DefinedSyntaxToken -> Setting: '$1'.
+%DefinedSyntaxToken -> '$empty': nil .
+
+% Setting ::= Type|Value|ValueSet|Object|ObjectSet
+Setting -> Type: '$1'.
+%Setting -> Value: '$1'.
+%Setting -> ValueNotNull: '$1'.
+Setting -> BuiltinValue: '$1'.
+Setting -> ValueSet: '$1'.
+%Setting -> Object: '$1'.
+%Setting -> ExternalObjectReference.
+Setting -> typereference '.' identifier.
+Setting -> identifier.
+Setting -> ObjectDefn.
+
+Setting -> ObjectSet: '$1'.
+
+
+Erlang code.
+%%-author('[email protected]').
+-copyright('Copyright (c) 1991-99 Ericsson Telecom AB').
+-vsn('$Revision: 1.1 $').
+-include("asn1_records.hrl").
+
+to_set(V) when list(V) ->
+ ordsets:list_to_set(V);
+to_set(V) ->
+ ordsets:list_to_set([V]).
+
+merge_constraints({Rlist,ExtList}) -> % extensionmarker in constraint
+ {merge_constraints(Rlist,[],[]),
+ merge_constraints(ExtList,[],[])};
+
+merge_constraints(Clist) ->
+ merge_constraints(Clist, [], []).
+
+merge_constraints([Ch|Ct],Cacc, Eacc) ->
+ NewEacc = case Ch#constraint.e of
+ undefined -> Eacc;
+ E -> [E|Eacc]
+ end,
+ merge_constraints(Ct,[fixup_constraint(Ch#constraint.c)|Cacc],NewEacc);
+
+merge_constraints([],Cacc,[]) ->
+ lists:flatten(Cacc);
+merge_constraints([],Cacc,Eacc) ->
+ lists:flatten(Cacc) ++ [{'Errors',Eacc}].
+
+fixup_constraint(C) ->
+ case C of
+ {'SingleValue',V} when list(V) ->
+ [C,
+ {'ValueRange',{lists:min(V),lists:max(V)}}];
+ {'PermittedAlphabet',{'SingleValue',V}} when list(V) ->
+ V2 = {'SingleValue',
+ ordsets:list_to_set(lists:flatten(V))},
+ {'PermittedAlphabet',V2};
+ {'PermittedAlphabet',{'SingleValue',V}} ->
+ V2 = {'SingleValue',[V]},
+ {'PermittedAlphabet',V2};
+ {'SizeConstraint',Sc} ->
+ {'SizeConstraint',fixup_size_constraint(Sc)};
+
+ List when list(List) ->
+ [fixup_constraint(Xc)||Xc <- List];
+ Other ->
+ Other
+ end.
+
+fixup_size_constraint({'ValueRange',{Lb,Ub}}) ->
+ {Lb,Ub};
+fixup_size_constraint({{'ValueRange',R},[]}) ->
+ {R,[]};
+fixup_size_constraint({[],{'ValueRange',R}}) ->
+ {[],R};
+fixup_size_constraint({{'ValueRange',R1},{'ValueRange',R2}}) ->
+ {R1,R2};
+fixup_size_constraint({'SingleValue',[Sv]}) ->
+ fixup_size_constraint({'SingleValue',Sv});
+fixup_size_constraint({'SingleValue',L}) when list(L) ->
+ ordsets:list_to_set(L);
+fixup_size_constraint({'SingleValue',L}) ->
+ {L,L};
+fixup_size_constraint({C1,C2}) ->
+ {fixup_size_constraint(C1), fixup_size_constraint(C2)}.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_parser2.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_parser2.erl
new file mode 100644
index 0000000000..07dacb73c8
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_parser2.erl
@@ -0,0 +1,2763 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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 2000, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%%
+%% $Id: asn1ct_parser2.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
+%%
+-module(asn1ct_parser2).
+
+-export([parse/1]).
+-include("asn1_records.hrl").
+
+%% parse all types in module
+parse(Tokens) ->
+ case catch parse_ModuleDefinition(Tokens) of
+ {'EXIT',Reason} ->
+ {error,{{undefined,get(asn1_module),
+ [internal,error,'when',parsing,module,definition,Reason]},
+ hd(Tokens)}};
+ {asn1_error,Reason} ->
+ {error,{Reason,hd(Tokens)}};
+ {ModuleDefinition,Rest1} ->
+ {Types,Rest2} = parse_AssignmentList(Rest1),
+ case Rest2 of
+ [{'END',_}|_Rest3] ->
+ {ok,ModuleDefinition#module{typeorval = Types}};
+ _ ->
+ {error,{{get_line(hd(Rest2)),get(asn1_module),
+ [got,get_token(hd(Rest2)),expected,'END']},
+ hd(Rest2)}}
+ end
+ end.
+
+parse_ModuleDefinition([{typereference,L1,ModuleIdentifier}|Rest0]) ->
+ put(asn1_module,ModuleIdentifier),
+ {_DefinitiveIdentifier,Rest02} =
+ case Rest0 of
+ [{'{',_}|_Rest01] ->
+ parse_ObjectIdentifierValue(Rest0);
+ _ ->
+ {[],Rest0}
+ end,
+ Rest = case Rest02 of
+ [{'DEFINITIONS',_}|Rest03] ->
+ Rest03;
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest02)),get(asn1_module),
+ [got,get_token(hd(Rest02)),
+ expected,'DEFINITIONS']}})
+ end,
+ {TagDefault,Rest2} =
+ case Rest of
+ [{'EXPLICIT',_L3},{'TAGS',_L4}|Rest1] ->
+ put(tagdefault,'EXPLICIT'), {'EXPLICIT',Rest1};
+ [{'IMPLICIT',_L3},{'TAGS',_L4}|Rest1] ->
+ put(tagdefault,'IMPLICIT'), {'IMPLICIT',Rest1};
+ [{'AUTOMATIC',_L3},{'TAGS',_L4}|Rest1] ->
+ put(tagdefault,'AUTOMATIC'), {'AUTOMATIC',Rest1};
+ Rest1 ->
+ put(tagdefault,'EXPLICIT'), {'EXPLICIT',Rest1} % The default
+ end,
+ {ExtensionDefault,Rest3} =
+ case Rest2 of
+ [{'EXTENSIBILITY',_L5}, {'IMPLIED',_L6}|Rest21] ->
+ {'IMPLIED',Rest21};
+ _ -> {false,Rest2}
+ end,
+ case Rest3 of
+ [{'::=',_L7}, {'BEGIN',_L8}|Rest4] ->
+ {Exports, Rest5} = parse_Exports(Rest4),
+ {Imports, Rest6} = parse_Imports(Rest5),
+ {#module{ pos = L1,
+ name = ModuleIdentifier,
+ defid = [], % fix this
+ tagdefault = TagDefault,
+ extensiondefault = ExtensionDefault,
+ exports = Exports,
+ imports = Imports},Rest6};
+ _ -> throw({asn1_error,{get_line(hd(Rest3)),get(asn1_module),
+ [got,get_token(hd(Rest3)),expected,"::= BEGIN"]}})
+ end;
+parse_ModuleDefinition(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,typereference]}}).
+
+parse_Exports([{'EXPORTS',_L1},{';',_L2}|Rest]) ->
+ {{exports,[]},Rest};
+parse_Exports([{'EXPORTS',_L1}|Rest]) ->
+ {SymbolList,Rest2} = parse_SymbolList(Rest),
+ case Rest2 of
+ [{';',_}|Rest3] ->
+ {{exports,SymbolList},Rest3};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
+ [got,get_token(hd(Rest2)),expected,';']}})
+ end;
+parse_Exports(Rest) ->
+ {{exports,all},Rest}.
+
+parse_SymbolList(Tokens) ->
+ parse_SymbolList(Tokens,[]).
+
+parse_SymbolList(Tokens,Acc) ->
+ {Symbol,Rest} = parse_Symbol(Tokens),
+ case Rest of
+ [{',',_L1}|Rest2] ->
+ parse_SymbolList(Rest2,[Symbol|Acc]);
+ Rest2 ->
+ {lists:reverse([Symbol|Acc]),Rest2}
+ end.
+
+parse_Symbol(Tokens) ->
+ parse_Reference(Tokens).
+
+parse_Reference([{typereference,L1,TrefName},{'{',_L2},{'}',_L3}|Rest]) ->
+% {Tref,Rest};
+ {tref2Exttref(L1,TrefName),Rest};
+parse_Reference([Tref1 = {typereference,_,_},{'.',_},Tref2 = {typereference,_,_},
+ {'{',_L2},{'}',_L3}|Rest]) ->
+% {{Tref1,Tref2},Rest};
+ {{tref2Exttref(Tref1),tref2Exttref(Tref2)},Rest};
+parse_Reference([Tref = {typereference,_L1,_TrefName}|Rest]) ->
+ {tref2Exttref(Tref),Rest};
+parse_Reference([Vref = {identifier,_L1,_VName}|Rest]) ->
+ {identifier2Extvalueref(Vref),Rest};
+parse_Reference(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,
+ [typereference,identifier]]}}).
+
+parse_Imports([{'IMPORTS',_L1},{';',_L2}|Rest]) ->
+ {{imports,[]},Rest};
+parse_Imports([{'IMPORTS',_L1}|Rest]) ->
+ {SymbolsFromModuleList,Rest2} = parse_SymbolsFromModuleList(Rest),
+ case Rest2 of
+ [{';',_L2}|Rest3] ->
+ {{imports,SymbolsFromModuleList},Rest3};
+ Rest3 ->
+ throw({asn1_error,{get_line(hd(Rest3)),get(asn1_module),
+ [got,get_token(hd(Rest3)),expected,';']}})
+ end;
+parse_Imports(Tokens) ->
+ {{imports,[]},Tokens}.
+
+parse_SymbolsFromModuleList(Tokens) ->
+ parse_SymbolsFromModuleList(Tokens,[]).
+
+parse_SymbolsFromModuleList(Tokens,Acc) ->
+ {SymbolsFromModule,Rest} = parse_SymbolsFromModule(Tokens),
+ case (catch parse_SymbolsFromModule(Rest)) of
+ {Sl,_Rest2} when record(Sl,'SymbolsFromModule') ->
+ parse_SymbolsFromModuleList(Rest,[SymbolsFromModule|Acc]);
+ _ ->
+ {lists:reverse([SymbolsFromModule|Acc]),Rest}
+ end.
+
+parse_SymbolsFromModule(Tokens) ->
+ SetRefModuleName =
+ fun(N) ->
+ fun(X) when record(X,'Externaltypereference')->
+ X#'Externaltypereference'{module=N};
+ (X) when record(X,'Externalvaluereference')->
+ X#'Externalvaluereference'{module=N}
+ end
+ end,
+ {SymbolList,Rest} = parse_SymbolList(Tokens),
+ case Rest of
+ %%How does this case correspond to x.680 ?
+ [{'FROM',_L1},Tref = {typereference,_,_},Ref={identifier,_L2,_Id},C={',',_}|Rest2] ->
+ {#'SymbolsFromModule'{symbols=SymbolList,
+ module=tref2Exttref(Tref)},[Ref,C|Rest2]};
+ %%How does this case correspond to x.680 ?
+ [{'FROM',_L1},Tref = {typereference,_,_},{identifier,_L2,_Id}|Rest2] ->
+ {#'SymbolsFromModule'{symbols=SymbolList,
+ module=tref2Exttref(Tref)},Rest2};
+ [{'FROM',_L1},Tref = {typereference,_,Name},Brace = {'{',_}|Rest2] ->
+ {_ObjIdVal,Rest3} = parse_ObjectIdentifierValue([Brace|Rest2]), % value not used yet, fix me
+ NewSymbolList = lists:map(SetRefModuleName(Name),SymbolList),
+ {#'SymbolsFromModule'{symbols=NewSymbolList,
+ module=tref2Exttref(Tref)},Rest3};
+ [{'FROM',_L1},Tref = {typereference,_,Name}|Rest2] ->
+ NewSymbolList = lists:map(SetRefModuleName(Name),SymbolList),
+ {#'SymbolsFromModule'{symbols=NewSymbolList,
+ module=tref2Exttref(Tref)},Rest2};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest)),get(asn1_module),
+ [got,get_token(hd(Rest)),expected,
+ ['FROM typerefernece identifier ,',
+ 'FROM typereference identifier',
+ 'FROM typereference {',
+ 'FROM typereference']]}})
+ end.
+
+parse_ObjectIdentifierValue([{'{',_}|Rest]) ->
+ parse_ObjectIdentifierValue(Rest,[]).
+
+parse_ObjectIdentifierValue([{number,_,Num}|Rest],Acc) ->
+ parse_ObjectIdentifierValue(Rest,[Num|Acc]);
+parse_ObjectIdentifierValue([{identifier,_,Id},{'(',_}, {number,_,Num}, {')',_}|Rest],Acc) ->
+ parse_ObjectIdentifierValue(Rest,[{'NamedNumber',Id,Num}|Acc]);
+parse_ObjectIdentifierValue([{identifier,_,Id},{'(',_}, {identifier,_,Id2}, {')',_}|Rest],Acc) ->
+ parse_ObjectIdentifierValue(Rest,[{'NamedNumber',Id,Id2}|Acc]);
+parse_ObjectIdentifierValue([{identifier,_,Id},{'(',_}, {typereference,_,Tref},{'.',_},{identifier,_,Id2}, {')',_}|Rest],Acc) ->
+ parse_ObjectIdentifierValue(Rest,[{'NamedNumber',Id,{'ExternalValue',Tref,Id2}}|Acc]);
+parse_ObjectIdentifierValue([Id = {identifier,_,_}|Rest],Acc) ->
+ parse_ObjectIdentifierValue(Rest,[identifier2Extvalueref(Id)|Acc]);
+parse_ObjectIdentifierValue([{'}',_}|Rest],Acc) ->
+ {lists:reverse(Acc),Rest};
+parse_ObjectIdentifierValue([H|_T],_Acc) ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,
+ ['{ some of the following }',number,'identifier ( number )',
+ 'identifier ( identifier )',
+ 'identifier ( typereference.identifier)',identifier]]}}).
+
+parse_AssignmentList(Tokens = [{'END',_}|_Rest]) ->
+ {[],Tokens};
+parse_AssignmentList(Tokens = [{'$end',_}|_Rest]) ->
+ {[],Tokens};
+parse_AssignmentList(Tokens) ->
+ parse_AssignmentList(Tokens,[]).
+
+parse_AssignmentList(Tokens= [{'END',_}|_Rest],Acc) ->
+ {lists:reverse(Acc),Tokens};
+parse_AssignmentList(Tokens= [{'$end',_}|_Rest],Acc) ->
+ {lists:reverse(Acc),Tokens};
+parse_AssignmentList(Tokens,Acc) ->
+ case (catch parse_Assignment(Tokens)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ {asn1_error,R} ->
+% [H|T] = Tokens,
+ throw({error,{R,hd(Tokens)}});
+ {Assignment,Rest} ->
+ parse_AssignmentList(Rest,[Assignment|Acc])
+ end.
+
+parse_Assignment(Tokens) ->
+ Flist = [fun parse_TypeAssignment/1,
+ fun parse_ValueAssignment/1,
+ fun parse_ObjectClassAssignment/1,
+ fun parse_ObjectAssignment/1,
+ fun parse_ObjectSetAssignment/1,
+ fun parse_ParameterizedAssignment/1,
+ fun parse_ValueSetTypeAssignment/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ {asn1_assignment_error,Reason} ->
+ throw({asn1_error,Reason});
+ Result ->
+ Result
+ end.
+
+
+parse_or(Tokens,Flist) ->
+ parse_or(Tokens,Flist,[]).
+
+parse_or(_Tokens,[],ErrList) ->
+ case ErrList of
+ [] ->
+ throw({asn1_error,{parse_or,ErrList}});
+ L when list(L) ->
+%%% throw({asn1_error,{parse_or,hd(lists:reverse(ErrList))}});
+ %% chose to throw 1) the error with the highest line no,
+ %% 2) the last error which is not a asn1_assignment_error or
+ %% 3) the last error.
+ throw(prioritize_error(ErrList));
+ Other ->
+ throw({asn1_error,{parse_or,Other}})
+ end;
+parse_or(Tokens,[Fun|Frest],ErrList) ->
+ case (catch Fun(Tokens)) of
+ Exit = {'EXIT',_Reason} ->
+ parse_or(Tokens,Frest,[Exit|ErrList]);
+ AsnErr = {asn1_error,_} ->
+ parse_or(Tokens,Frest,[AsnErr|ErrList]);
+ AsnAssErr = {asn1_assignment_error,_} ->
+ parse_or(Tokens,Frest,[AsnAssErr|ErrList]);
+ Result = {_,L} when list(L) ->
+ Result;
+% Result ->
+% Result
+ Error ->
+ parse_or(Tokens,Frest,[Error|ErrList])
+ end.
+
+parse_TypeAssignment([{typereference,L1,Tref},{'::=',_}|Rest]) ->
+ {Type,Rest2} = parse_Type(Rest),
+ {#typedef{pos=L1,name=Tref,typespec=Type},Rest2};
+parse_TypeAssignment([H1,H2|_Rest]) ->
+ throw({asn1_assignment_error,{get_line(H1),get(asn1_module),
+ [got,[get_token(H1),get_token(H2)], expected,
+ typereference,'::=']}});
+parse_TypeAssignment([H|_T]) ->
+ throw({asn1_assignment_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,
+ typereference]}}).
+
+parse_Type(Tokens) ->
+ {Tag,Rest3} = case Tokens of
+ [Lbr= {'[',_}|Rest] ->
+ parse_Tag([Lbr|Rest]);
+ Rest-> {[],Rest}
+ end,
+ {Tag2,Rest4} = case Rest3 of
+ [{'IMPLICIT',_}|Rest31] when record(Tag,tag)->
+ {[Tag#tag{type='IMPLICIT'}],Rest31};
+ [{'EXPLICIT',_}|Rest31] when record(Tag,tag)->
+ {[Tag#tag{type='EXPLICIT'}],Rest31};
+ Rest31 when record(Tag,tag) ->
+ {[Tag#tag{type={default,get(tagdefault)}}],Rest31};
+ Rest31 ->
+ {Tag,Rest31}
+ end,
+ Flist = [fun parse_BuiltinType/1,fun parse_ReferencedType/1,fun parse_TypeWithConstraint/1],
+ {Type,Rest5} = case (catch parse_or(Rest4,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_Reason} ->
+ throw(AsnErr);
+ Result ->
+ Result
+ end,
+ case hd(Rest5) of
+ {'(',_} ->
+ {Constraints,Rest6} = parse_Constraints(Rest5),
+ if record(Type,type) ->
+ {Type#type{constraint=merge_constraints(Constraints),
+ tag=Tag2},Rest6};
+ true ->
+ {#type{def=Type,constraint=merge_constraints(Constraints),
+ tag=Tag2},Rest6}
+ end;
+ _ ->
+ if record(Type,type) ->
+ {Type#type{tag=Tag2},Rest5};
+ true ->
+ {#type{def=Type,tag=Tag2},Rest5}
+ end
+ end.
+
+parse_BuiltinType([{'BIT',_},{'STRING',_}|Rest]) ->
+ case Rest of
+ [{'{',_}|Rest2] ->
+ {NamedNumberList,Rest3} = parse_NamedNumberList(Rest2),
+ case Rest3 of
+ [{'}',_}|Rest4] ->
+ {#type{def={'BIT STRING',NamedNumberList}},Rest4};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest3)),get(asn1_module),
+ [got,get_token(hd(Rest3)),expected,'}']}})
+ end;
+ _ ->
+ {{'BIT STRING',[]},Rest}
+ end;
+parse_BuiltinType([{'BOOLEAN',_}|Rest]) ->
+ {#type{def='BOOLEAN'},Rest};
+%% CharacterStringType ::= RestrictedCharacterStringType |
+%% UnrestrictedCharacterStringType
+parse_BuiltinType([{restrictedcharacterstringtype,_,StringName}|Rest]) ->
+ {#type{def=StringName},Rest};
+parse_BuiltinType([{'CHARACTER',_},{'STRING',_}|Rest]) ->
+ {#type{def='CHARACTER STRING'},Rest};
+
+parse_BuiltinType([{'CHOICE',_},{'{',_}|Rest]) ->
+ {AlternativeTypeLists,Rest2} = parse_AlternativeTypeLists(Rest),
+ case Rest2 of
+ [{'}',_}|Rest3] ->
+ {#type{def={'CHOICE',AlternativeTypeLists}},Rest3};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
+ [got,get_token(hd(Rest2)),expected,'}']}})
+ end;
+parse_BuiltinType([{'EMBEDDED',_},{'PDV',_}|Rest]) ->
+ {#type{def='EMBEDDED PDV'},Rest};
+parse_BuiltinType([{'ENUMERATED',_},{'{',_}|Rest]) ->
+ {Enumerations,Rest2} = parse_Enumerations(Rest),
+ case Rest2 of
+ [{'}',_}|Rest3] ->
+ {#type{def={'ENUMERATED',Enumerations}},Rest3};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
+ [got,get_token(hd(Rest2)),expected,'}']}})
+ end;
+parse_BuiltinType([{'EXTERNAL',_}|Rest]) ->
+ {#type{def='EXTERNAL'},Rest};
+
+% InstanceOfType
+parse_BuiltinType([{'INSTANCE',_},{'OF',_}|Rest]) ->
+ {DefinedObjectClass,Rest2} = parse_DefinedObjectClass(Rest),
+ case Rest2 of
+ [{'(',_}|_] ->
+ {Constraint,Rest3} = parse_Constraint(Rest2),
+ {#type{def={'INSTANCE OF',DefinedObjectClass,Constraint}},Rest3};
+ _ ->
+ {#type{def={'INSTANCE OF',DefinedObjectClass,[]}},Rest2}
+ end;
+
+% parse_BuiltinType(Tokens) ->
+
+parse_BuiltinType([{'INTEGER',_}|Rest]) ->
+ case Rest of
+ [{'{',_}|Rest2] ->
+ {NamedNumberList,Rest3} = parse_NamedNumberList(Rest2),
+ case Rest3 of
+ [{'}',_}|Rest4] ->
+ {#type{def={'INTEGER',NamedNumberList}},Rest4};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest3)),get(asn1_module),
+ [got,get_token(hd(Rest3)),expected,'}']}})
+ end;
+ _ ->
+ {#type{def='INTEGER'},Rest}
+ end;
+parse_BuiltinType([{'NULL',_}|Rest]) ->
+ {#type{def='NULL'},Rest};
+
+% ObjectClassFieldType fix me later
+
+parse_BuiltinType([{'OBJECT',_},{'IDENTIFIER',_}|Rest]) ->
+ {#type{def='OBJECT IDENTIFIER'},Rest};
+parse_BuiltinType([{'OCTET',_},{'STRING',_}|Rest]) ->
+ {#type{def='OCTET STRING'},Rest};
+parse_BuiltinType([{'REAL',_}|Rest]) ->
+ {#type{def='REAL'},Rest};
+parse_BuiltinType([{'SEQUENCE',_},{'{',_},{'...',Line},{'}',_}|Rest]) ->
+ {#type{def=#'SEQUENCE'{components=[{'EXTENSIONMARK',Line,undefined}]}},
+ Rest};
+parse_BuiltinType([{'SEQUENCE',_},{'{',_},{'...',Line},{'!',_}|Rest]) ->
+ {ExceptionIdentification,Rest2} = parse_ExceptionIdentification(Rest),
+ case Rest2 of
+ [{'}',_}|Rest3] ->
+ {#type{def=#'SEQUENCE'{components=[{'EXTENSIONMARK',
+ Line,
+ ExceptionIdentification}]}},
+ Rest3};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
+ [got,get_token(hd(Rest2)),expected,'}']}})
+ end;
+parse_BuiltinType([{'SEQUENCE',_},{'{',_}|Rest]) ->
+ {ComponentTypeLists,Rest2} = parse_ComponentTypeLists(Rest),
+ case Rest2 of
+ [{'}',_}|Rest3] ->
+ {#type{def=#'SEQUENCE'{components=ComponentTypeLists}},Rest3};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
+ [got,get_token(hd(Rest2)),expected,'}']}})
+ end;
+parse_BuiltinType([{'SEQUENCE',_},{'OF',_}|Rest]) ->
+ {Type,Rest2} = parse_Type(Rest),
+ {#type{def={'SEQUENCE OF',Type}},Rest2};
+
+
+parse_BuiltinType([{'SET',_},{'{',_},{'...',Line},{'}',_}|Rest]) ->
+ {#type{def=#'SET'{components=[{'EXTENSIONMARK',Line,undefined}]}},Rest};
+parse_BuiltinType([{'SET',_},{'{',_},{'...',Line},{'!',_}|Rest]) ->
+ {ExceptionIdentification,Rest2} = parse_ExceptionIdentification(Rest),
+ case Rest2 of
+ [{'}',_}|Rest3] ->
+ {#type{def=#'SET'{components=
+ [{'EXTENSIONMARK',Line,ExceptionIdentification}]}},
+ Rest3};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
+ [got,get_token(hd(Rest2)),expected,'}']}})
+ end;
+parse_BuiltinType([{'SET',_},{'{',_}|Rest]) ->
+ {ComponentTypeLists,Rest2} = parse_ComponentTypeLists(Rest),
+ case Rest2 of
+ [{'}',_}|Rest3] ->
+ {#type{def=#'SET'{components=ComponentTypeLists}},Rest3};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
+ [got,get_token(hd(Rest2)),expected,'}']}})
+ end;
+parse_BuiltinType([{'SET',_},{'OF',_}|Rest]) ->
+ {Type,Rest2} = parse_Type(Rest),
+ {#type{def={'SET OF',Type}},Rest2};
+
+%% The so called Useful types
+parse_BuiltinType([{'GeneralizedTime',_}|Rest]) ->
+ {#type{def='GeneralizedTime'},Rest};
+parse_BuiltinType([{'UTCTime',_}|Rest]) ->
+ {#type{def='UTCTime'},Rest};
+parse_BuiltinType([{'ObjectDescriptor',_}|Rest]) ->
+ {#type{def='ObjectDescriptor'},Rest};
+
+%% For compatibility with old standard
+parse_BuiltinType([{'ANY',_},{'DEFINED',_},{'BY',_},{identifier,_,Id}|Rest]) ->
+ {#type{def={'ANY_DEFINED_BY',Id}},Rest};
+parse_BuiltinType([{'ANY',_}|Rest]) ->
+ {#type{def='ANY'},Rest};
+
+parse_BuiltinType(Tokens) ->
+ parse_ObjectClassFieldType(Tokens).
+% throw({asn1_error,unhandled_type}).
+
+
+parse_TypeWithConstraint([{'SEQUENCE',_},Lpar = {'(',_}|Rest]) ->
+ {Constraint,Rest2} = parse_Constraint([Lpar|Rest]),
+ case Rest2 of
+ [{'OF',_}|Rest3] ->
+ {Type,Rest4} = parse_Type(Rest3),
+ {#type{def = {'SEQUENCE OF',Type}, constraint = merge_constraints([Constraint])},Rest4};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
+ [got,get_token(hd(Rest2)),expected,'OF']}})
+ end;
+parse_TypeWithConstraint([{'SEQUENCE',_},{'SIZE',_},Lpar = {'(',_}|Rest]) ->
+ {Constraint,Rest2} = parse_Constraint([Lpar|Rest]),
+ Constraint2 =
+ case Constraint of
+ #constraint{c=C} ->
+ Constraint#constraint{c={'SizeConstraint',C}};
+ _ -> Constraint
+ end,
+ case Rest2 of
+ [{'OF',_}|Rest3] ->
+ {Type,Rest4} = parse_Type(Rest3),
+ {#type{def = {'SEQUENCE OF',Type}, constraint = merge_constraints([Constraint2])},Rest4};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
+ [got,get_token(hd(Rest2)),expected,'OF']}})
+ end;
+parse_TypeWithConstraint([{'SET',_},Lpar = {'(',_}|Rest]) ->
+ {Constraint,Rest2} = parse_Constraint([Lpar|Rest]),
+ case Rest2 of
+ [{'OF',_}|Rest3] ->
+ {Type,Rest4} = parse_Type(Rest3),
+ {#type{def = {'SET OF',Type}, constraint = merge_constraints([Constraint])},Rest4};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
+ [got,get_token(hd(Rest2)),expected,'OF']}})
+ end;
+parse_TypeWithConstraint([{'SET',_},{'SIZE',_},Lpar = {'(',_}|Rest]) ->
+ {Constraint,Rest2} = parse_Constraint([Lpar|Rest]),
+ Constraint2 =
+ case Constraint of
+ #constraint{c=C} ->
+ Constraint#constraint{c={'SizeConstraint',C}};
+ _ -> Constraint
+ end,
+ case Rest2 of
+ [{'OF',_}|Rest3] ->
+ {Type,Rest4} = parse_Type(Rest3),
+ {#type{def = {'SET OF',Type}, constraint = merge_constraints([Constraint2])},Rest4};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
+ [got,get_token(hd(Rest2)),expected,'OF']}})
+ end;
+parse_TypeWithConstraint(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,
+ ['SEQUENCE','SEQUENCE SIZE','SET','SET SIZE'],
+ followed,by,a,constraint]}}).
+
+
+%% --------------------------
+
+parse_ReferencedType(Tokens) ->
+ Flist = [fun parse_DefinedType/1,
+ fun parse_SelectionType/1,
+ fun parse_TypeFromObject/1,
+ fun parse_ValueSetFromObjects/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ Result ->
+ Result
+ end.
+
+parse_DefinedType(Tokens=[{typereference,_,_},{'{',_}|_Rest]) ->
+ parse_ParameterizedType(Tokens);
+parse_DefinedType(Tokens=[{typereference,L1,TypeName},
+ T2={typereference,_,_},T3={'{',_}|Rest]) ->
+ case (catch parse_ParameterizedType(Tokens)) of
+ {'EXIT',_Reason} ->
+ Rest2 = [T2,T3|Rest],
+ {#type{def = #'Externaltypereference'{pos=L1,
+ module=get(asn1_module),
+ type=TypeName}},Rest2};
+ {asn1_error,_} ->
+ Rest2 = [T2,T3|Rest],
+ {#type{def = #'Externaltypereference'{pos=L1,
+ module=get(asn1_module),
+ type=TypeName}},Rest2};
+ Result ->
+ Result
+ end;
+parse_DefinedType([{typereference,L1,Module},{'.',_},{typereference,_,TypeName}|Rest]) ->
+ {#type{def = #'Externaltypereference'{pos=L1,module=Module,type=TypeName}},Rest};
+parse_DefinedType([{typereference,L1,TypeName}|Rest]) ->
+ {#type{def = #'Externaltypereference'{pos=L1,module=get(asn1_module),
+ type=TypeName}},Rest};
+parse_DefinedType(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,
+ [typereference,'typereference.typereference',
+ 'typereference typereference']]}}).
+
+parse_SelectionType([{identifier,_,Name},{'<',_}|Rest]) ->
+ {Type,Rest2} = parse_Type(Rest),
+ {{'SelectionType',Name,Type},Rest2};
+parse_SelectionType(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,'identifier <']}}).
+
+
+%% --------------------------
+
+
+%% This should probably be removed very soon
+% parse_ConstrainedType(Tokens) ->
+% case (catch parse_TypeWithConstraint(Tokens)) of
+% {'EXIT',Reason} ->
+% {Type,Rest} = parse_Type(Tokens),
+% {Constraint,Rest2} = parse_Constraint(Rest),
+% {Type#type{constraint=Constraint},Rest2};
+% {asn1_error,Reason2} ->
+% {Type,Rest} = parse_Type(Tokens),
+% {Constraint,Rest2} = parse_Constraint(Rest),
+% {Type#type{constraint=Constraint},Rest2};
+% Result ->
+% Result
+% end.
+
+parse_Constraints(Tokens) ->
+ parse_Constraints(Tokens,[]).
+
+parse_Constraints(Tokens,Acc) ->
+ {Constraint,Rest} = parse_Constraint(Tokens),
+ case Rest of
+ [{'(',_}|_Rest2] ->
+ parse_Constraints(Rest,[Constraint|Acc]);
+ _ ->
+ {lists:reverse([Constraint|Acc]),Rest}
+ end.
+
+parse_Constraint([{'(',_}|Rest]) ->
+ {Constraint,Rest2} = parse_ConstraintSpec(Rest),
+ {Exception,Rest3} = parse_ExceptionSpec(Rest2),
+ case Rest3 of
+ [{')',_}|Rest4] ->
+ {#constraint{c=Constraint,e=Exception},Rest4};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,')']}})
+ end;
+parse_Constraint(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,'(']}}).
+
+parse_ConstraintSpec(Tokens) ->
+ Flist = [fun parse_GeneralConstraint/1,
+ fun parse_SubtypeConstraint/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ {asn1_error,Reason2} ->
+ throw({asn1_error,Reason2});
+ Result ->
+ Result
+ end.
+
+parse_ExceptionSpec([LPar={')',_}|Rest]) ->
+ {undefined,[LPar|Rest]};
+parse_ExceptionSpec([{'!',_}|Rest]) ->
+ parse_ExceptionIdentification(Rest);
+parse_ExceptionSpec(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,[')','!']]}}).
+
+parse_ExceptionIdentification(Tokens) ->
+ Flist = [fun parse_SignedNumber/1,
+ fun parse_DefinedValue/1,
+ fun parse_TypeColonValue/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ {asn1_error,Reason2} ->
+ throw({asn1_error,Reason2});
+ Result ->
+ Result
+ end.
+
+parse_TypeColonValue(Tokens) ->
+ {Type,Rest} = parse_Type(Tokens),
+ case Rest of
+ [{':',_}|Rest2] ->
+ {Value,Rest3} = parse_Value(Rest2),
+ {{Type,Value},Rest3};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,':']}})
+ end.
+
+parse_SubtypeConstraint(Tokens) ->
+ parse_ElementSetSpecs(Tokens).
+
+parse_ElementSetSpecs([{'...',_}|Rest]) ->
+ {Elements,Rest2} = parse_ElementSetSpec(Rest),
+ {{[],Elements},Rest2};
+parse_ElementSetSpecs(Tokens) ->
+ {RootElems,Rest} = parse_ElementSetSpec(Tokens),
+ case Rest of
+ [{',',_},{'...',_},{',',_}|Rest2] ->
+ {AdditionalElems,Rest3} = parse_ElementSetSpec(Rest2),
+ {{RootElems,AdditionalElems},Rest3};
+ [{',',_},{'...',_}|Rest2] ->
+ {{RootElems,[]},Rest2};
+ _ ->
+ {RootElems,Rest}
+ end.
+
+parse_ElementSetSpec([{'ALL',_},{'EXCEPT',_}|Rest]) ->
+ {Exclusions,Rest2} = parse_Elements(Rest),
+ {{'ALL',{'EXCEPT',Exclusions}},Rest2};
+parse_ElementSetSpec(Tokens) ->
+ parse_Unions(Tokens).
+
+
+parse_Unions(Tokens) ->
+ {InterSec,Rest} = parse_Intersections(Tokens),
+ {Unions,Rest2} = parse_UnionsRec(Rest),
+ case {InterSec,Unions} of
+ {InterSec,[]} ->
+ {InterSec,Rest2};
+ {{'SingleValue',V1},{'SingleValue',V2}} ->
+ {{'SingleValue',ordsets:union(to_set(V1),to_set(V2))},Rest2};
+ {V1,V2} when list(V2) ->
+ {[V1] ++ [union|V2],Rest2};
+ {V1,V2} ->
+ {[V1,union,V2],Rest2}
+% Other ->
+% throw(Other)
+ end.
+
+parse_UnionsRec([{'|',_}|Rest]) ->
+ {InterSec,Rest2} = parse_Intersections(Rest),
+ {URec,Rest3} = parse_UnionsRec(Rest2),
+ case {InterSec,URec} of
+ {V1,[]} ->
+ {V1,Rest3};
+ {{'SingleValue',V1},{'SingleValue',V2}} ->
+ {{'SingleValue',ordsets:union(to_set(V1),to_set(V2))},Rest3};
+ {V1,V2} when list(V2) ->
+ {[V1] ++ V2,Rest3};
+ {V1,V2} ->
+ {[V1,V2],Rest3}
+ end;
+parse_UnionsRec([{'UNION',_}|Rest]) ->
+ {InterSec,Rest2} = parse_Intersections(Rest),
+ {URec,Rest3} = parse_UnionsRec(Rest2),
+ case {InterSec,URec} of
+ {V1,[]} ->
+ {V1,Rest3};
+ {{'SingleValue',V1},{'SingleValue',V2}} ->
+ {{'SingleValue',ordsets:union(to_set(V1),to_set(V2))},Rest3};
+ {V1,V2} when list(V2) ->
+ {[V1] ++ V2,Rest3};
+ {V1,V2} ->
+ {[V1,V2],Rest3}
+ end;
+parse_UnionsRec(Tokens) ->
+ {[],Tokens}.
+
+parse_Intersections(Tokens) ->
+ {InterSec,Rest} = parse_IntersectionElements(Tokens),
+ {IRec,Rest2} = parse_IElemsRec(Rest),
+ case {InterSec,IRec} of
+ {V1,[]} ->
+ {V1,Rest2};
+ {{'SingleValue',V1},{'SingleValue',V2}} ->
+ {{'SingleValue',
+ ordsets:intersection(to_set(V1),to_set(V2))},Rest2};
+ {V1,V2} when list(V2) ->
+ {[V1] ++ [intersection|V2],Rest2};
+ {V1,V2} ->
+ {[V1,intersection,V2],Rest2};
+ _ ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,'a Union']}})
+ end.
+
+parse_IElemsRec([{'^',_}|Rest]) ->
+ {InterSec,Rest2} = parse_IntersectionElements(Rest),
+ {IRec,Rest3} = parse_IElemsRec(Rest2),
+ case {InterSec,IRec} of
+ {{'SingleValue',V1},{'SingleValue',V2}} ->
+ {{'SingleValue',
+ ordsets:intersection(to_set(V1),to_set(V2))},Rest3};
+ {V1,[]} ->
+ {V1,Rest3};
+ {V1,V2} when list(V2) ->
+ {[V1] ++ V2,Rest3};
+ {V1,V2} ->
+ {[V1,V2],Rest3};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest)),get(asn1_module),
+ [got,get_token(hd(Rest)),expected,'an Intersection']}})
+ end;
+parse_IElemsRec([{'INTERSECTION',_}|Rest]) ->
+ {InterSec,Rest2} = parse_IntersectionElements(Rest),
+ {IRec,Rest3} = parse_IElemsRec(Rest2),
+ case {InterSec,IRec} of
+ {{'SingleValue',V1},{'SingleValue',V2}} ->
+ {{'SingleValue',
+ ordsets:intersection(to_set(V1),to_set(V2))},Rest3};
+ {V1,[]} ->
+ {V1,Rest3};
+ {V1,V2} when list(V2) ->
+ {[V1] ++ V2,Rest3};
+ {V1,V2} ->
+ {[V1,V2],Rest3};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest)),get(asn1_module),
+ [got,get_token(hd(Rest)),expected,'an Intersection']}})
+ end;
+parse_IElemsRec(Tokens) ->
+ {[],Tokens}.
+
+parse_IntersectionElements(Tokens) ->
+ {InterSec,Rest} = parse_Elements(Tokens),
+ case Rest of
+ [{'EXCEPT',_}|Rest2] ->
+ {Exclusion,Rest3} = parse_Elements(Rest2),
+ {{InterSec,{'EXCEPT',Exclusion}},Rest3};
+ Rest ->
+ {InterSec,Rest}
+ end.
+
+parse_Elements([{'(',_}|Rest]) ->
+ {Elems,Rest2} = parse_ElementSetSpec(Rest),
+ case Rest2 of
+ [{')',_}|Rest3] ->
+ {Elems,Rest3};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,')']}})
+ end;
+parse_Elements(Tokens) ->
+ Flist = [fun parse_SubtypeElements/1,
+ fun parse_ObjectSetElements/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ Err = {asn1_error,_} ->
+ throw(Err);
+ Result ->
+ Result
+ end.
+
+
+
+
+%% --------------------------
+
+parse_DefinedObjectClass([{typereference,_,_ModName},{'.',_},Tr={typereference,_,_ObjClName}|Rest]) ->
+%% {{objectclassname,ModName,ObjClName},Rest};
+% {{objectclassname,tref2Exttref(Tr)},Rest};
+ {tref2Exttref(Tr),Rest};
+parse_DefinedObjectClass([Tr={typereference,_,_ObjClName}|Rest]) ->
+% {{objectclassname,tref2Exttref(Tr)},Rest};
+ {tref2Exttref(Tr),Rest};
+parse_DefinedObjectClass([{'TYPE-IDENTIFIER',_}|Rest]) ->
+ {'TYPE-IDENTIFIER',Rest};
+parse_DefinedObjectClass([{'ABSTRACT-SYNTAX',_}|Rest]) ->
+ {'ABSTRACT-SYNTAX',Rest};
+parse_DefinedObjectClass(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,
+ ['typereference . typereference',
+ typereference,
+ 'TYPE-IDENTIFIER',
+ 'ABSTRACT-SYNTAX']]}}).
+
+parse_ObjectClassAssignment([{typereference,L1,ObjClName},{'::=',_}|Rest]) ->
+ {Type,Rest2} = parse_ObjectClass(Rest),
+ {#classdef{pos=L1,name=ObjClName,typespec=Type},Rest2};
+parse_ObjectClassAssignment(Tokens) ->
+ throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,
+ 'typereference ::=']}}).
+
+parse_ObjectClass(Tokens) ->
+ Flist = [fun parse_DefinedObjectClass/1,
+ fun parse_ObjectClassDefn/1,
+ fun parse_ParameterizedObjectClass/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ {asn1_error,Reason2} ->
+ throw({asn1_error,Reason2});
+ Result ->
+ Result
+ end.
+
+parse_ObjectClassDefn([{'CLASS',_},{'{',_}|Rest]) ->
+ {Type,Rest2} = parse_FieldSpec(Rest),
+ {WithSyntaxSpec,Rest3} = parse_WithSyntaxSpec(Rest2),
+ {#objectclass{fields=Type,syntax=WithSyntaxSpec},Rest3};
+parse_ObjectClassDefn(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,'CLASS {']}}).
+
+parse_FieldSpec(Tokens) ->
+ parse_FieldSpec(Tokens,[]).
+
+parse_FieldSpec(Tokens,Acc) ->
+ Flist = [fun parse_FixedTypeValueFieldSpec/1,
+ fun parse_VariableTypeValueFieldSpec/1,
+ fun parse_ObjectFieldSpec/1,
+ fun parse_FixedTypeValueSetFieldSpec/1,
+ fun parse_VariableTypeValueSetFieldSpec/1,
+ fun parse_TypeFieldSpec/1,
+ fun parse_ObjectSetFieldSpec/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ {Type,[{'}',_}|Rest]} ->
+ {lists:reverse([Type|Acc]),Rest};
+ {Type,[{',',_}|Rest2]} ->
+ parse_FieldSpec(Rest2,[Type|Acc]);
+ {_,[H|_T]} ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,'}']}})
+ end.
+
+parse_PrimitiveFieldName([{typefieldreference,_,FieldName}|Rest]) ->
+ {{typefieldreference,FieldName},Rest};
+parse_PrimitiveFieldName([{valuefieldreference,_,FieldName}|Rest]) ->
+ {{valuefieldreference,FieldName},Rest};
+parse_PrimitiveFieldName(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,
+ [typefieldreference,valuefieldreference]]}}).
+
+parse_FieldName(Tokens) ->
+ {Field,Rest} = parse_PrimitiveFieldName(Tokens),
+ parse_FieldName(Rest,[Field]).
+
+parse_FieldName([{'.',_}|Rest],Acc) ->
+ case (catch parse_PrimitiveFieldName(Rest)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ {FieldName,Rest2} ->
+ parse_FieldName(Rest2,[FieldName|Acc])
+ end;
+parse_FieldName(Tokens,Acc) ->
+ {lists:reverse(Acc),Tokens}.
+
+parse_FixedTypeValueFieldSpec([{valuefieldreference,L1,VFieldName}|Rest]) ->
+ {Type,Rest2} = parse_Type(Rest),
+ {Unique,Rest3} =
+ case Rest2 of
+ [{'UNIQUE',_}|Rest4] ->
+ {'UNIQUE',Rest4};
+ _ ->
+ {undefined,Rest2}
+ end,
+ {OptionalitySpec,Rest5} = parse_ValueOptionalitySpec(Rest3),
+ case Unique of
+ 'UNIQUE' ->
+ case OptionalitySpec of
+ {'DEFAULT',_} ->
+ throw({asn1_error,
+ {L1,get(asn1_module),
+ ['UNIQUE and DEFAULT in same field',VFieldName]}});
+ _ ->
+ {{fixedtypevaluefield,VFieldName,Type,Unique,OptionalitySpec},Rest5}
+ end;
+ _ ->
+ {{object_or_fixedtypevalue_field,VFieldName,Type,Unique,OptionalitySpec},Rest5}
+ end;
+parse_FixedTypeValueFieldSpec(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,valuefieldreference]}}).
+
+parse_VariableTypeValueFieldSpec([{valuefieldreference,_,VFieldName}|Rest]) ->
+ {FieldRef,Rest2} = parse_FieldName(Rest),
+ {OptionalitySpec,Rest3} = parse_ValueOptionalitySpec(Rest2),
+ {{variabletypevaluefield,VFieldName,FieldRef,OptionalitySpec},Rest3};
+parse_VariableTypeValueFieldSpec(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,valuefieldreference]}}).
+
+parse_ObjectFieldSpec([{valuefieldreference,_,VFieldName}|Rest]) ->
+ {Class,Rest2} = parse_DefinedObjectClass(Rest),
+ {OptionalitySpec,Rest3} = parse_ObjectOptionalitySpec(Rest2),
+ {{objectfield,VFieldName,Class,OptionalitySpec},Rest3};
+parse_ObjectFieldSpec(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,valuefieldreference]}}).
+
+parse_TypeFieldSpec([{typefieldreference,_,TFieldName}|Rest]) ->
+ {OptionalitySpec,Rest2} = parse_TypeOptionalitySpec(Rest),
+ {{typefield,TFieldName,OptionalitySpec},Rest2};
+parse_TypeFieldSpec(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,typefieldreference]}}).
+
+parse_FixedTypeValueSetFieldSpec([{typefieldreference,_,TFieldName}|Rest]) ->
+ {Type,Rest2} = parse_Type(Rest),
+ {OptionalitySpec,Rest3} = parse_ValueSetOptionalitySpec(Rest2),
+ {{objectset_or_fixedtypevalueset_field,TFieldName,Type,
+ OptionalitySpec},Rest3};
+parse_FixedTypeValueSetFieldSpec(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,typefieldreference]}}).
+
+parse_VariableTypeValueSetFieldSpec([{typefieldreference,_,TFieldName}|Rest]) ->
+ {FieldRef,Rest2} = parse_FieldName(Rest),
+ {OptionalitySpec,Rest3} = parse_ValueSetOptionalitySpec(Rest2),
+ {{variabletypevaluesetfield,TFieldName,FieldRef,OptionalitySpec},Rest3};
+parse_VariableTypeValueSetFieldSpec(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,typefieldreference]}}).
+
+parse_ObjectSetFieldSpec([{typefieldreference,_,TFieldName}|Rest]) ->
+ {Class,Rest2} = parse_DefinedObjectClass(Rest),
+ {OptionalitySpec,Rest3} = parse_ObjectSetOptionalitySpec(Rest2),
+ {{objectsetfield,TFieldName,Class,OptionalitySpec},Rest3};
+parse_ObjectSetFieldSpec(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,typefieldreference]}}).
+
+parse_ValueOptionalitySpec(Tokens)->
+ case Tokens of
+ [{'OPTIONAL',_}|Rest] -> {'OPTIONAL',Rest};
+ [{'DEFAULT',_}|Rest] ->
+ {Value,Rest2} = parse_Value(Rest),
+ {{'DEFAULT',Value},Rest2};
+ _ -> {'MANDATORY',Tokens}
+ end.
+
+parse_ObjectOptionalitySpec(Tokens) ->
+ case Tokens of
+ [{'OPTIONAL',_}|Rest] -> {'OPTIONAL',Rest};
+ [{'DEFAULT',_}|Rest] ->
+ {Object,Rest2} = parse_Object(Rest),
+ {{'DEFAULT',Object},Rest2};
+ _ -> {'MANDATORY',Tokens}
+ end.
+
+parse_TypeOptionalitySpec(Tokens) ->
+ case Tokens of
+ [{'OPTIONAL',_}|Rest] -> {'OPTIONAL',Rest};
+ [{'DEFAULT',_}|Rest] ->
+ {Type,Rest2} = parse_Type(Rest),
+ {{'DEFAULT',Type},Rest2};
+ _ -> {'MANDATORY',Tokens}
+ end.
+
+parse_ValueSetOptionalitySpec(Tokens) ->
+ case Tokens of
+ [{'OPTIONAL',_}|Rest] -> {'OPTIONAL',Rest};
+ [{'DEFAULT',_}|Rest] ->
+ {ValueSet,Rest2} = parse_ValueSet(Rest),
+ {{'DEFAULT',ValueSet},Rest2};
+ _ -> {'MANDATORY',Tokens}
+ end.
+
+parse_ObjectSetOptionalitySpec(Tokens) ->
+ case Tokens of
+ [{'OPTIONAL',_}|Rest] -> {'OPTIONAL',Rest};
+ [{'DEFAULT',_}|Rest] ->
+ {ObjectSet,Rest2} = parse_ObjectSet(Rest),
+ {{'DEFAULT',ObjectSet},Rest2};
+ _ -> {'MANDATORY',Tokens}
+ end.
+
+parse_WithSyntaxSpec([{'WITH',_},{'SYNTAX',_}|Rest]) ->
+ {SyntaxList,Rest2} = parse_SyntaxList(Rest),
+ {{'WITH SYNTAX',SyntaxList},Rest2};
+parse_WithSyntaxSpec(Tokens) ->
+ {[],Tokens}.
+
+parse_SyntaxList([{'{',_},{'}',_}|Rest]) ->
+ {[],Rest};
+parse_SyntaxList([{'{',_}|Rest]) ->
+ parse_SyntaxList(Rest,[]);
+parse_SyntaxList(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,['{}','{']]}}).
+
+parse_SyntaxList(Tokens,Acc) ->
+ {SyntaxList,Rest} = parse_TokenOrGroupSpec(Tokens),
+ case Rest of
+ [{'}',_}|Rest2] ->
+ {lists:reverse([SyntaxList|Acc]),Rest2};
+ _ ->
+ parse_SyntaxList(Rest,[SyntaxList|Acc])
+ end.
+
+parse_TokenOrGroupSpec(Tokens) ->
+ Flist = [fun parse_RequiredToken/1,
+ fun parse_OptionalGroup/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ Result ->
+ Result
+ end.
+
+parse_RequiredToken([{typereference,L1,WordName}|Rest]) ->
+ case is_word(WordName) of
+ false ->
+ throw({asn1_error,{L1,get(asn1_module),
+ [got,WordName,expected,a,'Word']}});
+ true ->
+ {WordName,Rest}
+ end;
+parse_RequiredToken([{',',L1}|Rest]) ->
+ {{',',L1},Rest};
+parse_RequiredToken([{WordName,L1}|Rest]) ->
+ case is_word(WordName) of
+ false ->
+ throw({asn1_error,{L1,get(asn1_module),
+ [got,WordName,expected,a,'Word']}});
+ true ->
+ {WordName,Rest}
+ end;
+parse_RequiredToken(Tokens) ->
+ parse_PrimitiveFieldName(Tokens).
+
+parse_OptionalGroup([{'[',_}|Rest]) ->
+ {Spec,Rest2} = parse_TokenOrGroupSpec(Rest),
+ {SpecList,Rest3} = parse_OptionalGroup(Rest2,[Spec]),
+ {SpecList,Rest3}.
+
+parse_OptionalGroup([{']',_}|Rest],Acc) ->
+ {lists:reverse(Acc),Rest};
+parse_OptionalGroup(Tokens,Acc) ->
+ {Spec,Rest} = parse_TokenOrGroupSpec(Tokens),
+ parse_OptionalGroup(Rest,[Spec|Acc]).
+
+parse_DefinedObject([Id={identifier,_,_ObjName}|Rest]) ->
+ {{object,identifier2Extvalueref(Id)},Rest};
+parse_DefinedObject([{typereference,L1,ModName},{'.',_},{identifier,_,ObjName}|Rest]) ->
+ {{object, #'Externaltypereference'{pos=L1,module=ModName,type=ObjName}},Rest};
+parse_DefinedObject(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,
+ [identifier,'typereference.identifier']]}}).
+
+parse_ObjectAssignment([{identifier,L1,ObjName}|Rest]) ->
+ {Class,Rest2} = parse_DefinedObjectClass(Rest),
+ case Rest2 of
+ [{'::=',_}|Rest3] ->
+ {Object,Rest4} = parse_Object(Rest3),
+ {#typedef{pos=L1,name=ObjName,
+ typespec=#'Object'{classname=Class,def=Object}},Rest4};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,'::=']}});
+ Other ->
+ throw({asn1_error,{L1,get(asn1_module),
+ [got,Other,expected,'::=']}})
+ end;
+parse_ObjectAssignment(Tokens) ->
+ throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,identifier]}}).
+
+parse_Object(Tokens) ->
+ Flist=[fun parse_ObjectDefn/1,
+ fun parse_ObjectFromObject/1,
+ fun parse_ParameterizedObject/1,
+ fun parse_DefinedObject/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ Result ->
+ Result
+ end.
+
+parse_ObjectDefn(Tokens) ->
+ Flist=[fun parse_DefaultSyntax/1,
+ fun parse_DefinedSyntax/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ Result ->
+ Result
+ end.
+
+parse_DefaultSyntax([{'{',_},{'}',_}|Rest]) ->
+ {{object,defaultsyntax,[]},Rest};
+parse_DefaultSyntax([{'{',_}|Rest]) ->
+ parse_DefaultSyntax(Rest,[]);
+parse_DefaultSyntax(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,['{}','{']]}}).
+
+parse_DefaultSyntax(Tokens,Acc) ->
+ {Setting,Rest} = parse_FieldSetting(Tokens),
+ case Rest of
+ [{',',_}|Rest2] ->
+ parse_DefaultSyntax(Rest2,[Setting|Acc]);
+ [{'}',_}|Rest3] ->
+ {{object,defaultsyntax,lists:reverse([Setting|Acc])},Rest3};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,[',','}']]}})
+ end.
+
+parse_FieldSetting(Tokens) ->
+ {{_,PrimFieldName},Rest} = parse_PrimitiveFieldName(Tokens),
+ {Setting,Rest2} = parse_Setting(Rest),
+ {{PrimFieldName,Setting},Rest2}.
+
+parse_DefinedSyntax([{'{',_}|Rest]) ->
+ parse_DefinedSyntax(Rest,[]).
+
+parse_DefinedSyntax(Tokens,Acc) ->
+ case Tokens of
+ [{'}',_}|Rest2] ->
+ {{object,definedsyntax,lists:reverse(Acc)},Rest2};
+ _ ->
+ {DefSynTok,Rest3} = parse_DefinedSyntaxToken(Tokens),
+ parse_DefinedSyntax(Rest3,[DefSynTok|Acc])
+ end.
+
+parse_DefinedSyntaxToken([{',',L1}|Rest]) ->
+ {{',',L1},Rest};
+parse_DefinedSyntaxToken([{typereference,L1,Name}|Rest]) ->
+ case is_word(Name) of
+ false ->
+ {{setting,L1,Name},Rest};
+ true ->
+ {{word_or_setting,L1,Name},Rest}
+ end;
+parse_DefinedSyntaxToken(Tokens) ->
+ case catch parse_Setting(Tokens) of
+ {asn1_error,_} ->
+ parse_Word(Tokens);
+ {'EXIT',Reason} ->
+ exit(Reason);
+ Result ->
+ Result
+ end.
+
+parse_Word([{Name,Pos}|Rest]) ->
+ case is_word(Name) of
+ false ->
+ throw({asn1_error,{Pos,get(asn1_module),
+ [got,Name, expected,a,'Word']}});
+ true ->
+ {{word_or_setting,Pos,Name},Rest}
+ end.
+
+parse_Setting(Tokens) ->
+ Flist = [fun parse_Type/1,
+ fun parse_Value/1,
+ fun parse_Object/1,
+ fun parse_ObjectSet/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ Result ->
+ Result
+ end.
+
+parse_DefinedObjectSet([{typereference,L1,ModuleName},{'.',_},
+ {typereference,L2,ObjSetName}|Rest]) ->
+ {{objectset,L1,#'Externaltypereference'{pos=L2,module=ModuleName,
+ type=ObjSetName}},Rest};
+parse_DefinedObjectSet([{typereference,L1,ObjSetName}|Rest]) ->
+ {{objectset,L1,#'Externaltypereference'{pos=L1,module=get(asn1_module),
+ type=ObjSetName}},Rest};
+parse_DefinedObjectSet(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,
+ [typereference,'typereference.typereference']]}}).
+
+parse_ObjectSetAssignment([{typereference,L1,ObjSetName}|Rest]) ->
+ {Class,Rest2} = parse_DefinedObjectClass(Rest),
+ case Rest2 of
+ [{'::=',_}|Rest3] ->
+ {ObjectSet,Rest4} = parse_ObjectSet(Rest3),
+ {#typedef{pos=L1,name=ObjSetName,
+ typespec=#'ObjectSet'{class=Class,
+ set=ObjectSet}},Rest4};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,'::=']}})
+%%% Other ->
+%%% throw(Other)
+ end;
+parse_ObjectSetAssignment(Tokens) ->
+ throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,
+ typereference]}}).
+
+parse_ObjectSet([{'{',_}|Rest]) ->
+ {ObjSetSpec,Rest2} = parse_ObjectSetSpec(Rest),
+ case Rest2 of
+ [{'}',_}|Rest3] ->
+ {ObjSetSpec,Rest3};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,'}']}})
+ end;
+parse_ObjectSet(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,'{']}}).
+
+parse_ObjectSetSpec([{'...',_}|Rest]) ->
+ {['EXTENSIONMARK'],Rest};
+parse_ObjectSetSpec(Tokens) ->
+ parse_ElementSetSpecs(Tokens).
+
+parse_ObjectSetElements(Tokens) ->
+ Flist = [fun parse_Object/1,
+ fun parse_DefinedObjectSet/1,
+ fun parse_ObjectSetFromObjects/1,
+ fun parse_ParameterizedObjectSet/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ Result ->
+ Result
+ end.
+
+parse_ObjectClassFieldType(Tokens) ->
+ {Class,Rest} = parse_DefinedObjectClass(Tokens),
+ case Rest of
+ [{'.',_}|Rest2] ->
+ {FieldName,Rest3} = parse_FieldName(Rest2),
+ OCFT = #'ObjectClassFieldType'{
+ classname=Class,
+ class=Class,fieldname=FieldName},
+ {#type{def=OCFT},Rest3};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,'.']}})
+%%% Other ->
+%%% throw(Other)
+ end.
+
+%parse_ObjectClassFieldValue(Tokens) ->
+% Flist = [fun parse_OpenTypeFieldVal/1,
+% fun parse_FixedTypeFieldVal/1],
+% case (catch parse_or(Tokens,Flist)) of
+% {'EXIT',Reason} ->
+% throw(Reason);
+% AsnErr = {asn1_error,_} ->
+% throw(AsnErr);
+% Result ->
+% Result
+% end.
+
+parse_ObjectClassFieldValue(Tokens) ->
+ parse_OpenTypeFieldVal(Tokens).
+
+parse_OpenTypeFieldVal(Tokens) ->
+ {Type,Rest} = parse_Type(Tokens),
+ case Rest of
+ [{':',_}|Rest2] ->
+ {Value,Rest3} = parse_Value(Rest2),
+ {{opentypefieldvalue,Type,Value},Rest3};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,':']}})
+ end.
+
+% parse_FixedTypeFieldVal(Tokens) ->
+% parse_Value(Tokens).
+
+% parse_InformationFromObjects(Tokens) ->
+% Flist = [fun parse_ValueFromObject/1,
+% fun parse_ValueSetFromObjects/1,
+% fun parse_TypeFromObject/1,
+% fun parse_ObjectFromObject/1],
+% case (catch parse_or(Tokens,Flist)) of
+% {'EXIT',Reason} ->
+% throw(Reason);
+% AsnErr = {asn1_error,_} ->
+% throw(AsnErr);
+% Result ->
+% Result
+% end.
+
+parse_ReferencedObjects(Tokens) ->
+ Flist = [fun parse_DefinedObject/1,
+ fun parse_DefinedObjectSet/1,
+ fun parse_ParameterizedObject/1,
+ fun parse_ParameterizedObjectSet/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ Result ->
+ Result
+ end.
+
+parse_ValueFromObject(Tokens) ->
+ {Objects,Rest} = parse_ReferencedObjects(Tokens),
+ case Rest of
+ [{'.',_}|Rest2] ->
+ {Name,Rest3} = parse_FieldName(Rest2),
+ case lists:last(Name) of
+ {valuefieldreference,_} ->
+ {{'ValueFromObject',Objects,Name},Rest3};
+ _ ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,typefieldreference,expected,
+ valuefieldreference]}})
+ end;
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,'.']}})
+%%% Other ->
+%%% throw({asn1_error,{got,Other,expected,'.'}})
+ end.
+
+parse_ValueSetFromObjects(Tokens) ->
+ {Objects,Rest} = parse_ReferencedObjects(Tokens),
+ case Rest of
+ [{'.',_}|Rest2] ->
+ {Name,Rest3} = parse_FieldName(Rest2),
+ case lists:last(Name) of
+ {typefieldreference,_FieldName} ->
+ {{'ValueSetFromObjects',Objects,Name},Rest3};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
+ [got,get_token(hd(Rest2)),expected,
+ typefieldreference]}})
+ end;
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,'.']}})
+%%% Other ->
+%%% throw({asn1_error,{got,Other,expected,'.'}})
+ end.
+
+parse_TypeFromObject(Tokens) ->
+ {Objects,Rest} = parse_ReferencedObjects(Tokens),
+ case Rest of
+ [{'.',_}|Rest2] ->
+ {Name,Rest3} = parse_FieldName(Rest2),
+ case lists:last(Name) of
+ {typefieldreference,_FieldName} ->
+ {{'TypeFromObject',Objects,Name},Rest3};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
+ [got,get_token(hd(Rest2)),expected,
+ typefieldreference]}})
+ end;
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,'.']}})
+%%% Other ->
+%%% throw({asn1_error,{got,Other,expected,'.'}})
+ end.
+
+parse_ObjectFromObject(Tokens) ->
+ {Objects,Rest} = parse_ReferencedObjects(Tokens),
+ case Rest of
+ [{'.',_}|Rest2] ->
+ {Name,Rest3} = parse_FieldName(Rest2),
+ {{'ObjectFromObject',Objects,Name},Rest3};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,'.']}})
+%%% Other ->
+%%% throw({asn1_error,{got,Other,expected,'.'}})
+ end.
+
+parse_ObjectSetFromObjects(Tokens) ->
+ {Objects,Rest} = parse_ReferencedObjects(Tokens),
+ case Rest of
+ [{'.',_}|Rest2] ->
+ {Name,Rest3} = parse_FieldName(Rest2),
+ {{'ObjectSetFromObjects',Objects,Name},Rest3};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,'.']}})
+%%% Other ->
+%%% throw({asn1_error,{got,Other,expected,'.'}})
+ end.
+
+% parse_InstanceOfType([{'INSTANCE',_},{'OF',_}|Rest]) ->
+% {Class,Rest2} = parse_DefinedObjectClass(Rest),
+% {{'InstanceOfType',Class},Rest2}.
+
+% parse_InstanceOfValue(Tokens) ->
+% parse_Value(Tokens).
+
+
+
+%% X.682 constraint specification
+
+parse_GeneralConstraint(Tokens) ->
+ Flist = [fun parse_UserDefinedConstraint/1,
+ fun parse_TableConstraint/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ Result ->
+ Result
+ end.
+
+parse_UserDefinedConstraint([{'CONSTRAINED',_},{'BY',_},{'{',_},{'}',_}|Rest])->
+ {{constrained_by,[]},Rest};
+parse_UserDefinedConstraint([{'CONSTRAINED',_},
+ {'BY',_},
+ {'{',_}|Rest]) ->
+ {Param,Rest2} = parse_UserDefinedConstraintParameter(Rest),
+ case Rest2 of
+ [{'}',_}|Rest3] ->
+ {{constrained_by,Param},Rest3};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,'}']}})
+ end;
+parse_UserDefinedConstraint(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,
+ ['CONSTRAINED BY {}','CONSTRAINED BY {']]}}).
+
+parse_UserDefinedConstraintParameter(Tokens) ->
+ parse_UserDefinedConstraintParameter(Tokens,[]).
+parse_UserDefinedConstraintParameter(Tokens,Acc) ->
+ Flist = [fun parse_GovernorAndActualParameter/1,
+ fun parse_ActualParameter/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ {Result,Rest} ->
+ case Rest of
+ [{',',_}|_Rest2] ->
+ parse_UserDefinedConstraintParameter(Tokens,[Result|Acc]);
+ _ ->
+ {lists:reverse([Result|Acc]),Rest}
+ end
+ end.
+
+parse_GovernorAndActualParameter(Tokens) ->
+ {Governor,Rest} = parse_Governor(Tokens),
+ case Rest of
+ [{':',_}|Rest2] ->
+ {Params,Rest3} = parse_ActualParameter(Rest2),
+ {{'Governor_Params',Governor,Params},Rest3};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,':']}})
+ end.
+
+parse_TableConstraint(Tokens) ->
+ Flist = [fun parse_ComponentRelationConstraint/1,
+ fun parse_SimpleTableConstraint/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ Result ->
+ Result
+ end.
+
+parse_SimpleTableConstraint(Tokens) ->
+ {ObjectSet,Rest} = parse_ObjectSet(Tokens),
+ {{simpletable,ObjectSet},Rest}.
+
+parse_ComponentRelationConstraint([{'{',_}|Rest]) ->
+ {ObjectSet,Rest2} = parse_DefinedObjectSet(Rest),
+ case Rest2 of
+ [{'}',_},{'{',_}|Rest3] ->
+ {AtNot,Rest4} = parse_AtNotationList(Rest3,[]),
+ case Rest4 of
+ [{'}',_}|Rest5] ->
+ {{componentrelation,ObjectSet,AtNot},Rest5};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,'}']}})
+ end;
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,
+ 'ComponentRelationConstraint',ended,with,'}']}})
+%%% Other ->
+%%% throw(Other)
+ end;
+parse_ComponentRelationConstraint(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,'{']}}).
+
+parse_AtNotationList(Tokens,Acc) ->
+ {AtNot,Rest} = parse_AtNotation(Tokens),
+ case Rest of
+ [{',',_}|Rest2] ->
+ parse_AtNotationList(Rest2,[AtNot|Acc]);
+ _ ->
+ {lists:reverse([AtNot|Acc]),Rest}
+ end.
+
+parse_AtNotation([{'@',_},{'.',_}|Rest]) ->
+ {CIdList,Rest2} = parse_ComponentIdList(Rest),
+ {{innermost,CIdList},Rest2};
+parse_AtNotation([{'@',_}|Rest]) ->
+ {CIdList,Rest2} = parse_ComponentIdList(Rest),
+ {{outermost,CIdList},Rest2};
+parse_AtNotation(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,['@','@.']]}}).
+
+parse_ComponentIdList(Tokens) ->
+ parse_ComponentIdList(Tokens,[]).
+
+parse_ComponentIdList([Id = {identifier,_,_},{'.',_}|Rest],Acc) ->
+ parse_ComponentIdList(Rest,[identifier2Extvalueref(Id)|Acc]);
+parse_ComponentIdList([Id = {identifier,_,_}|Rest],Acc) ->
+ {lists:reverse([identifier2Extvalueref(Id)|Acc]),Rest};
+parse_ComponentIdList(Tokens,_) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,
+ [identifier,'identifier.']]}}).
+
+
+
+
+
+% X.683 Parameterization of ASN.1 specifications
+
+parse_Governor(Tokens) ->
+ Flist = [fun parse_Type/1,
+ fun parse_DefinedObjectClass/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ Result ->
+ Result
+ end.
+
+parse_ActualParameter(Tokens) ->
+ Flist = [fun parse_Type/1,
+ fun parse_Value/1,
+ fun parse_ValueSet/1,
+ fun parse_DefinedObjectClass/1,
+ fun parse_Object/1,
+ fun parse_ObjectSet/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ Result ->
+ Result
+ end.
+
+parse_ParameterizedAssignment(Tokens) ->
+ Flist = [fun parse_ParameterizedTypeAssignment/1,
+ fun parse_ParameterizedValueAssignment/1,
+ fun parse_ParameterizedValueSetTypeAssignment/1,
+ fun parse_ParameterizedObjectClassAssignment/1,
+ fun parse_ParameterizedObjectAssignment/1,
+ fun parse_ParameterizedObjectSetAssignment/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ AsnAssErr = {asn1_assignment_error,_} ->
+ throw(AsnAssErr);
+ Result ->
+ Result
+ end.
+
+parse_ParameterizedTypeAssignment([{typereference,L1,Name}|Rest]) ->
+ {ParameterList,Rest2} = parse_ParameterList(Rest),
+ case Rest2 of
+ [{'::=',_}|Rest3] ->
+ {Type,Rest4} = parse_Type(Rest3),
+ {#ptypedef{pos=L1,name=Name,args=ParameterList,typespec=Type},
+ Rest4};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,'::=']}})
+ end;
+parse_ParameterizedTypeAssignment(Tokens) ->
+ throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,
+ typereference]}}).
+
+parse_ParameterizedValueAssignment([{identifier,L1,Name}|Rest]) ->
+ {ParameterList,Rest2} = parse_ParameterList(Rest),
+ {Type,Rest3} = parse_Type(Rest2),
+ case Rest3 of
+ [{'::=',_}|Rest4] ->
+ {Value,Rest5} = parse_Value(Rest4),
+ {#pvaluedef{pos=L1,name=Name,args=ParameterList,type=Type,
+ value=Value},Rest5};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,'::=']}})
+ end;
+parse_ParameterizedValueAssignment(Tokens) ->
+ throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,identifier]}}).
+
+parse_ParameterizedValueSetTypeAssignment([{typereference,L1,Name}|Rest]) ->
+ {ParameterList,Rest2} = parse_ParameterList(Rest),
+ {Type,Rest3} = parse_Type(Rest2),
+ case Rest3 of
+ [{'::=',_}|Rest4] ->
+ {ValueSet,Rest5} = parse_ValueSet(Rest4),
+ {#pvaluesetdef{pos=L1,name=Name,args=ParameterList,
+ type=Type,valueset=ValueSet},Rest5};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,'::=']}})
+ end;
+parse_ParameterizedValueSetTypeAssignment(Tokens) ->
+ throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,
+ typereference]}}).
+
+parse_ParameterizedObjectClassAssignment([{typereference,L1,Name}|Rest]) ->
+ {ParameterList,Rest2} = parse_ParameterList(Rest),
+ case Rest2 of
+ [{'::=',_}|Rest3] ->
+ {Class,Rest4} = parse_ObjectClass(Rest3),
+ {#ptypedef{pos=L1,name=Name,args=ParameterList,typespec=Class},
+ Rest4};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,'::=']}})
+ end;
+parse_ParameterizedObjectClassAssignment(Tokens) ->
+ throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,
+ typereference]}}).
+
+parse_ParameterizedObjectAssignment([{identifier,L1,Name}|Rest]) ->
+ {ParameterList,Rest2} = parse_ParameterList(Rest),
+ {Class,Rest3} = parse_DefinedObjectClass(Rest2),
+ case Rest3 of
+ [{'::=',_}|Rest4] ->
+ {Object,Rest5} = parse_Object(Rest4),
+ {#pobjectdef{pos=L1,name=Name,args=ParameterList,
+ class=Class,def=Object},Rest5};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,'::=']}})
+%%% Other ->
+%%% throw(Other)
+ end;
+parse_ParameterizedObjectAssignment(Tokens) ->
+ throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,identifier]}}).
+
+parse_ParameterizedObjectSetAssignment([{typereference,L1,Name}|Rest]) ->
+ {ParameterList,Rest2} = parse_ParameterList(Rest),
+ {Class,Rest3} = parse_DefinedObjectClass(Rest2),
+ case Rest3 of
+ [{'::=',_}|Rest4] ->
+ {ObjectSet,Rest5} = parse_ObjectSet(Rest4),
+ {#pobjectsetdef{pos=L1,name=Name,args=ParameterList,
+ class=Class,def=ObjectSet},Rest5};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,'::=']}})
+%%% Other ->
+%%% throw(Other)
+ end;
+parse_ParameterizedObjectSetAssignment(Tokens) ->
+ throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,
+ typereference]}}).
+
+parse_ParameterList([{'{',_}|Rest]) ->
+ parse_ParameterList(Rest,[]);
+parse_ParameterList(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,'{']}}).
+
+parse_ParameterList(Tokens,Acc) ->
+ {Parameter,Rest} = parse_Parameter(Tokens),
+ case Rest of
+ [{',',_}|Rest2] ->
+ parse_ParameterList(Rest2,[Parameter|Acc]);
+ [{'}',_}|Rest3] ->
+ {lists:reverse([Parameter|Acc]),Rest3};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,[',','}']]}})
+ end.
+
+parse_Parameter(Tokens) ->
+ Flist = [fun parse_ParamGovAndRef/1,
+ fun parse_Reference/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ Result ->
+ Result
+ end.
+
+parse_ParamGovAndRef(Tokens) ->
+ {ParamGov,Rest} = parse_ParamGovernor(Tokens),
+ case Rest of
+ [{':',_}|Rest2] ->
+ {Ref,Rest3} = parse_Reference(Rest2),
+ {{ParamGov,Ref},Rest3};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,':']}})
+ end.
+
+parse_ParamGovernor(Tokens) ->
+ Flist = [fun parse_Governor/1,
+ fun parse_Reference/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ Result ->
+ Result
+ end.
+
+% parse_ParameterizedReference(Tokens) ->
+% {Ref,Rest} = parse_Reference(Tokens),
+% case Rest of
+% [{'{',_},{'}',_}|Rest2] ->
+% {{ptref,Ref},Rest2};
+% _ ->
+% {{ptref,Ref},Rest}
+% end.
+
+parse_SimpleDefinedType([{typereference,L1,ModuleName},{'.',_},
+ {typereference,_,TypeName}|Rest]) ->
+ {#'Externaltypereference'{pos=L1,module=ModuleName,
+ type=TypeName},Rest};
+parse_SimpleDefinedType([Tref={typereference,_,_}|Rest]) ->
+% {#'Externaltypereference'{pos=L2,module=get(asn1_module),
+% type=TypeName},Rest};
+ {tref2Exttref(Tref),Rest};
+parse_SimpleDefinedType(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,
+ [typereference,'typereference.typereference']]}}).
+
+parse_SimpleDefinedValue([{typereference,L1,ModuleName},{'.',_},
+ {identifier,_,Value}|Rest]) ->
+ {{simpledefinedvalue,#'Externalvaluereference'{pos=L1,module=ModuleName,
+ value=Value}},Rest};
+parse_SimpleDefinedValue([{identifier,L2,Value}|Rest]) ->
+ {{simpledefinedvalue,L2,Value},Rest};
+parse_SimpleDefinedValue(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,
+ ['typereference.identifier',identifier]]}}).
+
+parse_ParameterizedType(Tokens) ->
+ {Type,Rest} = parse_SimpleDefinedType(Tokens),
+ {Params,Rest2} = parse_ActualParameterList(Rest),
+ {{pt,Type,Params},Rest2}.
+
+parse_ParameterizedValue(Tokens) ->
+ {Value,Rest} = parse_SimpleDefinedValue(Tokens),
+ {Params,Rest2} = parse_ActualParameterList(Rest),
+ {{pv,Value,Params},Rest2}.
+
+parse_ParameterizedObjectClass(Tokens) ->
+ {Type,Rest} = parse_DefinedObjectClass(Tokens),
+ {Params,Rest2} = parse_ActualParameterList(Rest),
+ {{poc,Type,Params},Rest2}.
+
+parse_ParameterizedObjectSet(Tokens) ->
+ {ObjectSet,Rest} = parse_DefinedObjectSet(Tokens),
+ {Params,Rest2} = parse_ActualParameterList(Rest),
+ {{pos,ObjectSet,Params},Rest2}.
+
+parse_ParameterizedObject(Tokens) ->
+ {Object,Rest} = parse_DefinedObject(Tokens),
+ {Params,Rest2} = parse_ActualParameterList(Rest),
+ {{po,Object,Params},Rest2}.
+
+parse_ActualParameterList([{'{',_}|Rest]) ->
+ parse_ActualParameterList(Rest,[]);
+parse_ActualParameterList(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,'{']}}).
+
+parse_ActualParameterList(Tokens,Acc) ->
+ {Parameter,Rest} = parse_ActualParameter(Tokens),
+ case Rest of
+ [{',',_}|Rest2] ->
+ parse_ActualParameterList(Rest2,[Parameter|Acc]);
+ [{'}',_}|Rest3] ->
+ {lists:reverse([Parameter|Acc]),Rest3};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,[',','}']]}})
+%%% Other ->
+%%% throw(Other)
+ end.
+
+
+
+
+
+
+
+%-------------------------
+
+is_word(Token) ->
+ case not_allowed_word(Token) of
+ true -> false;
+ _ ->
+ if
+ atom(Token) ->
+ Item = atom_to_list(Token),
+ is_word(Item);
+ list(Token), length(Token) == 1 ->
+ check_one_char_word(Token);
+ list(Token) ->
+ [A|Rest] = Token,
+ case check_first(A) of
+ true ->
+ check_rest(Rest);
+ _ ->
+ false
+ end
+ end
+ end.
+
+not_allowed_word(Name) ->
+ lists:member(Name,["BIT",
+ "BOOLEAN",
+ "CHARACTER",
+ "CHOICE",
+ "EMBEDDED",
+ "END",
+ "ENUMERATED",
+ "EXTERNAL",
+ "FALSE",
+ "INSTANCE",
+ "INTEGER",
+ "INTERSECTION",
+ "MINUS-INFINITY",
+ "NULL",
+ "OBJECT",
+ "OCTET",
+ "PLUS-INFINITY",
+ "REAL",
+ "SEQUENCE",
+ "SET",
+ "TRUE",
+ "UNION"]).
+
+check_one_char_word([A]) when $A =< A, $Z >= A ->
+ true;
+check_one_char_word([_]) ->
+ false. %% unknown item in SyntaxList
+
+check_first(A) when $A =< A, $Z >= A ->
+ true;
+check_first(_) ->
+ false. %% unknown item in SyntaxList
+
+check_rest([R,R|_Rs]) when $- == R ->
+ false; %% two consecutive hyphens are not allowed in a word
+check_rest([R]) when $- == R ->
+ false; %% word cannot end with hyphen
+check_rest([R|Rs]) when $A=<R, $Z>=R; $-==R ->
+ check_rest(Rs);
+check_rest([]) ->
+ true;
+check_rest(_) ->
+ false.
+
+
+to_set(V) when list(V) ->
+ ordsets:list_to_set(V);
+to_set(V) ->
+ ordsets:list_to_set([V]).
+
+
+parse_AlternativeTypeLists(Tokens) ->
+ {AlternativeTypeList,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,
+ case ExtensionAndException of
+ [] ->
+ {AlternativeTypeList,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,
+ {AlternativeTypeList ++ ExtensionAndException ++ ExtensionAddition ++ OptionalExtensionMarker, Rest4}
+ end.
+
+
+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) ->
+ parse_ExtensionAdditionAlternativeList(Tokens,[]).
+
+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_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),
+ {#'ComponentType'{pos=L1,name=Idname,typespec=Type,prop=mandatory},Rest2};
+parse_NamedType(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,identifier]}}).
+
+
+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);
+ _ ->
+ {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,[])
+ 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) ->
+ 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_ComponentTypeList(Tokens) ->
+ parse_ComponentTypeList(Tokens,[]).
+
+parse_ComponentTypeList(Tokens,Acc) ->
+ {ComponentType,Rest} = parse_ComponentType(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};
+ _ ->
+ 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);
+ _ ->
+ 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]);
+ _ ->
+ {lists:reverse([Element|Acc]),Rest0}
+ 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([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),
+ case Rest of
+ [{'OPTIONAL',_}|Rest2] ->
+ {NamedType#'ComponentType'{prop='OPTIONAL'},Rest2};
+ [{'DEFAULT',_}|Rest2] ->
+ {Value,Rest21} = parse_Value(Rest2),
+ {NamedType#'ComponentType'{prop={'DEFAULT',Value}},Rest21};
+ _ ->
+ {NamedType,Rest}
+ end.
+
+
+
+parse_SignedNumber([{number,_,Value}|Rest]) ->
+ {Value,Rest};
+parse_SignedNumber([{'-',_},{number,_,Value}|Rest]) ->
+ {-Value,Rest};
+parse_SignedNumber(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,
+ [number,'-number']]}}).
+
+parse_Enumerations(Tokens=[{identifier,_,_}|_Rest]) ->
+ parse_Enumerations(Tokens,[]);
+parse_Enumerations([H|_T]) ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,identifier]}}).
+
+parse_Enumerations(Tokens = [{identifier,_,_},{'(',_}|_Rest], Acc) ->
+ {NamedNumber,Rest2} = parse_NamedNumber(Tokens),
+ case Rest2 of
+ [{',',_}|Rest3] ->
+ parse_Enumerations(Rest3,[NamedNumber|Acc]);
+ _ ->
+ {lists:reverse([NamedNumber|Acc]),Rest2}
+ end;
+parse_Enumerations([{identifier,_,Id}|Rest], Acc) ->
+ case Rest of
+ [{',',_}|Rest2] ->
+ parse_Enumerations(Rest2,[Id|Acc]);
+ _ ->
+ {lists:reverse([Id|Acc]),Rest}
+ end;
+parse_Enumerations([{'...',_}|Rest], Acc) ->
+ case Rest of
+ [{',',_}|Rest2] ->
+ parse_Enumerations(Rest2,['EXTENSIONMARK'|Acc]);
+ _ ->
+ {lists:reverse(['EXTENSIONMARK'|Acc]),Rest}
+ end;
+parse_Enumerations([H|_T],_) ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,identifier]}}).
+
+parse_NamedNumberList(Tokens) ->
+ parse_NamedNumberList(Tokens,[]).
+
+parse_NamedNumberList(Tokens,Acc) ->
+ {NamedNum,Rest} = parse_NamedNumber(Tokens),
+ case Rest of
+ [{',',_}|Rest2] ->
+ parse_NamedNumberList(Rest2,[NamedNum|Acc]);
+ _ ->
+ {lists:reverse([NamedNum|Acc]),Rest}
+ end.
+
+parse_NamedNumber([{identifier,_,Name},{'(',_}|Rest]) ->
+ Flist = [fun parse_SignedNumber/1,
+ fun parse_DefinedValue/1],
+ case (catch parse_or(Rest,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ {NamedNum,[{')',_}|Rest2]} ->
+ {{'NamedNumber',Name,NamedNum},Rest2};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest)),get(asn1_module),
+ [got,get_token(hd(Rest)),expected,'NamedNumberList']}})
+ end;
+parse_NamedNumber(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,identifier]}}).
+
+
+parse_Tag([{'[',_}|Rest]) ->
+ {Class,Rest2} = parse_Class(Rest),
+ {ClassNumber,Rest3} =
+ case Rest2 of
+ [{number,_,Num}|Rest21] ->
+ {Num,Rest21};
+ _ ->
+ parse_DefinedValue(Rest2)
+ end,
+ case Rest3 of
+ [{']',_}|Rest4] ->
+ {#tag{class=Class,number=ClassNumber},Rest4};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest3)),get(asn1_module),
+ [got,get_token(hd(Rest3)),expected,']']}})
+ end;
+parse_Tag(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,'[']}}).
+
+parse_Class([{'UNIVERSAL',_}|Rest]) ->
+ {'UNIVERSAL',Rest};
+parse_Class([{'APPLICATION',_}|Rest]) ->
+ {'APPLICATION',Rest};
+parse_Class([{'PRIVATE',_}|Rest]) ->
+ {'PRIVATE',Rest};
+parse_Class(Tokens) ->
+ {'CONTEXT',Tokens}.
+
+parse_Value(Tokens) ->
+ Flist = [fun parse_BuiltinValue/1,
+ fun parse_ValueFromObject/1,
+ fun parse_DefinedValue/1],
+
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ Result ->
+ Result
+ end.
+
+parse_BuiltinValue([{bstring,_,Bstr}|Rest]) ->
+ {{bstring,Bstr},Rest};
+parse_BuiltinValue([{hstring,_,Hstr}|Rest]) ->
+ {{hstring,Hstr},Rest};
+parse_BuiltinValue([{'{',_},{'}',_}|Rest]) ->
+ {[],Rest};
+parse_BuiltinValue(Tokens = [{'{',_}|_Rest]) ->
+ Flist = [
+ fun parse_SequenceOfValue/1,
+ fun parse_SequenceValue/1,
+ fun parse_ObjectIdentifierValue/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ Result ->
+ Result
+ end;
+parse_BuiltinValue([{identifier,_,IdName},{':',_}|Rest]) ->
+ {Value,Rest2} = parse_Value(Rest),
+ {{'CHOICE',{IdName,Value}},Rest2};
+parse_BuiltinValue([{'NULL',_}|Rest]) ->
+ {'NULL',Rest};
+parse_BuiltinValue([{'TRUE',_}|Rest]) ->
+ {true,Rest};
+parse_BuiltinValue([{'FALSE',_}|Rest]) ->
+ {false,Rest};
+parse_BuiltinValue([{'PLUS-INFINITY',_}|Rest]) ->
+ {'PLUS-INFINITY',Rest};
+parse_BuiltinValue([{'MINUS-INFINITY',_}|Rest]) ->
+ {'MINUS-INFINITY',Rest};
+parse_BuiltinValue([{cstring,_,Cstr}|Rest]) ->
+ {Cstr,Rest};
+parse_BuiltinValue([{number,_,Num}|Rest]) ->
+ {Num,Rest};
+parse_BuiltinValue([{'-',_},{number,_,Num}|Rest]) ->
+ {- Num,Rest};
+parse_BuiltinValue(Tokens) ->
+ parse_ObjectClassFieldValue(Tokens).
+
+%% Externalvaluereference
+parse_DefinedValue([{typereference,L1,Tname},{'.',_},{identifier,_,Idname}|Rest]) ->
+ {#'Externalvaluereference'{pos=L1,module=Tname,value=Idname},Rest};
+%% valuereference
+parse_DefinedValue([Id = {identifier,_,_}|Rest]) ->
+ {identifier2Extvalueref(Id),Rest};
+%% ParameterizedValue
+parse_DefinedValue(Tokens) ->
+ parse_ParameterizedValue(Tokens).
+
+
+parse_SequenceValue([{'{',_}|Tokens]) ->
+ parse_SequenceValue(Tokens,[]);
+parse_SequenceValue(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,'{']}}).
+
+parse_SequenceValue([{identifier,_,IdName}|Rest],Acc) ->
+ {Value,Rest2} = parse_Value(Rest),
+ case Rest2 of
+ [{',',_}|Rest3] ->
+ parse_SequenceValue(Rest3,[{IdName,Value}|Acc]);
+ [{'}',_}|Rest3] ->
+ {lists:reverse([{IdName,Value}|Acc]),Rest3};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
+ [got,get_token(hd(Rest2)),expected,'}']}})
+ end;
+parse_SequenceValue(Tokens,_Acc) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,identifier]}}).
+
+parse_SequenceOfValue([{'{',_}|Tokens]) ->
+ parse_SequenceOfValue(Tokens,[]);
+parse_SequenceOfValue(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,'{']}}).
+
+parse_SequenceOfValue(Tokens,Acc) ->
+ {Value,Rest2} = parse_Value(Tokens),
+ case Rest2 of
+ [{',',_}|Rest3] ->
+ parse_SequenceOfValue(Rest3,[Value|Acc]);
+ [{'}',_}|Rest3] ->
+ {lists:reverse([Value|Acc]),Rest3};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
+ [got,get_token(hd(Rest2)),expected,'}']}})
+ end.
+
+parse_ValueSetTypeAssignment([{typereference,L1,Name}|Rest]) ->
+ {Type,Rest2} = parse_Type(Rest),
+ case Rest2 of
+ [{'::=',_}|Rest3] ->
+ {ValueSet,Rest4} = parse_ValueSet(Rest3),
+ {#valuedef{pos=L1,name=Name,type=Type,value=ValueSet},Rest4};
+ [H|_T] ->
+ throw({asn1_error,{get_line(L1),get(asn1_module),
+ [got,get_token(H),expected,'::=']}})
+ end;
+parse_ValueSetTypeAssignment(Tokens) ->
+ throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,
+ typereference]}}).
+
+parse_ValueSet([{'{',_}|Rest]) ->
+ {Elems,Rest2} = parse_ElementSetSpecs(Rest),
+ case Rest2 of
+ [{'}',_}|Rest3] ->
+ {{valueset,Elems},Rest3};
+ [H|_T] ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,'}']}})
+ end;
+parse_ValueSet(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,'{']}}).
+
+parse_ValueAssignment([{identifier,L1,IdName}|Rest]) ->
+ {Type,Rest2} = parse_Type(Rest),
+ case Rest2 of
+ [{'::=',_}|Rest3] ->
+ {Value,Rest4} = parse_Value(Rest3),
+ case lookahead_assignment(Rest4) of
+ ok ->
+ {#valuedef{pos=L1,name=IdName,type=Type,value=Value},Rest4};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
+ [got,get_token(hd(Rest2)),expected,'::=']}})
+ end;
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
+ [got,get_token(hd(Rest2)),expected,'::=']}})
+ end;
+parse_ValueAssignment(Tokens) ->
+ throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,identifier]}}).
+
+%% SizeConstraint
+parse_SubtypeElements([{'SIZE',_}|Tokens]) ->
+ {Constraint,Rest} = parse_Constraint(Tokens),
+ {{'SizeConstraint',Constraint#constraint.c},Rest};
+%% PermittedAlphabet
+parse_SubtypeElements([{'FROM',_}|Tokens]) ->
+ {Constraint,Rest} = parse_Constraint(Tokens),
+ {{'PermittedAlphabet',Constraint#constraint.c},Rest};
+%% InnerTypeConstraints
+parse_SubtypeElements([{'WITH',_},{'COMPONENT',_}|Tokens]) ->
+ {Constraint,Rest} = parse_Constraint(Tokens),
+ {{'WITH COMPONENT',Constraint},Rest};
+parse_SubtypeElements([{'WITH',_},{'COMPONENTS',_},{'{',_},{'...',_},{',',_}|Tokens]) ->
+ {Constraint,Rest} = parse_TypeConstraints(Tokens),
+ case Rest of
+ [{'}',_}|Rest2] ->
+ {{'WITH COMPONENTS',{'PartialSpecification',Constraint}},Rest2};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest)),get(asn1_module),
+ [got,get_token(hd(Rest)),expected,'}']}})
+ end;
+parse_SubtypeElements([{'WITH',_},{'COMPONENTS',_},{'{',_}|Tokens]) ->
+ {Constraint,Rest} = parse_TypeConstraints(Tokens),
+ case Rest of
+ [{'}',_}|Rest2] ->
+ {{'WITH COMPONENTS',{'FullSpecification',Constraint}},Rest2};
+ _ ->
+ throw({asn1_error,{get_line(hd(Rest)),get(asn1_module),
+ [got,get_token(hd(Rest)),expected,'}']}})
+ end;
+%% SingleValue
+%% ContainedSubtype
+%% ValueRange
+%% TypeConstraint
+parse_SubtypeElements(Tokens) ->
+ Flist = [fun parse_ContainedSubtype/1,
+ fun parse_Value/1,
+ fun([{'MIN',_}|T]) -> {'MIN',T} end,
+ fun parse_Type/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ {asn1_error,Reason} ->
+ throw(Reason);
+ Result = {Val,_} when record(Val,type) ->
+ Result;
+ {Lower,[{'..',_}|Rest]} ->
+ {Upper,Rest2} = parse_UpperEndpoint(Rest),
+ {{'ValueRange',{Lower,Upper}},Rest2};
+ {Lower,[{'<',_},{'..',_}|Rest]} ->
+ {Upper,Rest2} = parse_UpperEndpoint(Rest),
+ {{'ValueRange',{{gt,Lower},Upper}},Rest2};
+ {Res={'ContainedSubtype',_Type},Rest} ->
+ {Res,Rest};
+ {Value,Rest} ->
+ {{'SingleValue',Value},Rest}
+ end.
+
+parse_ContainedSubtype([{'INCLUDES',_}|Rest]) ->
+ {Type,Rest2} = parse_Type(Rest),
+ {{'ContainedSubtype',Type},Rest2};
+parse_ContainedSubtype(Tokens) ->
+ throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
+ [got,get_token(hd(Tokens)),expected,'INCLUDES']}}).
+%%parse_ContainedSubtype(Tokens) -> %this option is moved to parse_SubtypeElements
+%% parse_Type(Tokens).
+
+parse_UpperEndpoint([{'<',_}|Rest]) ->
+ parse_UpperEndpoint(lt,Rest);
+parse_UpperEndpoint(Tokens) ->
+ parse_UpperEndpoint(false,Tokens).
+
+parse_UpperEndpoint(Lt,Tokens) ->
+ Flist = [ fun([{'MAX',_}|T]) -> {'MAX',T} end,
+ fun parse_Value/1],
+ case (catch parse_or(Tokens,Flist)) of
+ {'EXIT',Reason} ->
+ exit(Reason);
+ AsnErr = {asn1_error,_} ->
+ throw(AsnErr);
+ {Value,Rest2} when Lt == lt ->
+ {{lt,Value},Rest2};
+ {Value,Rest2} ->
+ {Value,Rest2}
+ end.
+
+parse_TypeConstraints(Tokens) ->
+ parse_TypeConstraints(Tokens,[]).
+
+parse_TypeConstraints([{identifier,_,_}|Rest],Acc) ->
+ {ComponentConstraint,Rest2} = parse_ComponentConstraint(Rest),
+ case Rest2 of
+ [{',',_}|Rest3] ->
+ parse_TypeConstraints(Rest3,[ComponentConstraint|Acc]);
+ _ ->
+ {lists:reverse([ComponentConstraint|Acc]),Rest2}
+ end;
+parse_TypeConstraints([H|_T],_) ->
+ throw({asn1_error,{get_line(H),get(asn1_module),
+ [got,get_token(H),expected,identifier]}}).
+
+parse_ComponentConstraint(Tokens = [{'(',_}|_Rest]) ->
+ {ValueConstraint,Rest2} = parse_Constraint(Tokens),
+ {PresenceConstraint,Rest3} = parse_PresenceConstraint(Rest2),
+ {{ValueConstraint,PresenceConstraint},Rest3};
+parse_ComponentConstraint(Tokens) ->
+ {PresenceConstraint,Rest} = parse_PresenceConstraint(Tokens),
+ {{asn1_empty,PresenceConstraint},Rest}.
+
+parse_PresenceConstraint([{'PRESENT',_}|Rest]) ->
+ {'PRESENT',Rest};
+parse_PresenceConstraint([{'ABSENT',_}|Rest]) ->
+ {'ABSENT',Rest};
+parse_PresenceConstraint([{'OPTIONAL',_}|Rest]) ->
+ {'OPTIONAL',Rest};
+parse_PresenceConstraint(Tokens) ->
+ {asn1_empty,Tokens}.
+
+
+merge_constraints({Rlist,ExtList}) -> % extensionmarker in constraint
+ {merge_constraints(Rlist,[],[]),
+ merge_constraints(ExtList,[],[])};
+
+merge_constraints(Clist) ->
+ merge_constraints(Clist, [], []).
+
+merge_constraints([Ch|Ct],Cacc, Eacc) ->
+ NewEacc = case Ch#constraint.e of
+ undefined -> Eacc;
+ E -> [E|Eacc]
+ end,
+ merge_constraints(Ct,[fixup_constraint(Ch#constraint.c)|Cacc],NewEacc);
+
+merge_constraints([],Cacc,[]) ->
+%% lists:flatten(Cacc);
+ lists:reverse(Cacc);
+merge_constraints([],Cacc,Eacc) ->
+%% lists:flatten(Cacc) ++ [{'Errors',Eacc}].
+ lists:reverse(Cacc) ++ [{'Errors',Eacc}].
+
+fixup_constraint(C) ->
+ case C of
+ {'SingleValue',SubType} when element(1,SubType) == 'ContainedSubtype' ->
+ SubType;
+ {'SingleValue',V} when list(V) ->
+ C;
+ %% [C,{'ValueRange',{lists:min(V),lists:max(V)}}];
+ %% bug, turns wrong when an element in V is a reference to a defined value
+ {'PermittedAlphabet',{'SingleValue',V}} when list(V) ->
+ %%sort and remove duplicates
+ V2 = {'SingleValue',
+ ordsets:list_to_set(lists:flatten(V))},
+ {'PermittedAlphabet',V2};
+ {'PermittedAlphabet',{'SingleValue',V}} ->
+ V2 = {'SingleValue',[V]},
+ {'PermittedAlphabet',V2};
+ {'SizeConstraint',Sc} ->
+ {'SizeConstraint',fixup_size_constraint(Sc)};
+
+ List when list(List) -> %% In This case maybe a union or intersection
+ [fixup_constraint(Xc)||Xc <- List];
+ Other ->
+ Other
+ end.
+
+fixup_size_constraint({'ValueRange',{Lb,Ub}}) ->
+ {Lb,Ub};
+fixup_size_constraint({{'ValueRange',R},[]}) ->
+ {R,[]};
+fixup_size_constraint({[],{'ValueRange',R}}) ->
+ {[],R};
+fixup_size_constraint({{'ValueRange',R1},{'ValueRange',R2}}) ->
+ {R1,R2};
+fixup_size_constraint({'SingleValue',[Sv]}) ->
+ fixup_size_constraint({'SingleValue',Sv});
+fixup_size_constraint({'SingleValue',L}) when list(L) ->
+ ordsets:list_to_set(L);
+fixup_size_constraint({'SingleValue',L}) ->
+ {L,L};
+fixup_size_constraint({C1,C2}) ->
+ {fixup_size_constraint(C1), fixup_size_constraint(C2)}.
+
+get_line({_,Pos,Token}) when integer(Pos),atom(Token) ->
+ Pos;
+get_line({Token,Pos}) when integer(Pos),atom(Token) ->
+ Pos;
+get_line(_) ->
+ undefined.
+
+get_token({_,Pos,Token}) when integer(Pos),atom(Token) ->
+ Token;
+get_token({'$end',Pos}) when integer(Pos) ->
+ undefined;
+get_token({Token,Pos}) when integer(Pos),atom(Token) ->
+ Token;
+get_token(_) ->
+ undefined.
+
+prioritize_error(ErrList) ->
+ case lists:keymember(asn1_error,1,ErrList) of
+ false -> % only asn1_assignment_error -> take the last
+ lists:last(ErrList);
+ true -> % contains errors from deeper in a Type
+ NewErrList = [_Err={_,_}|_RestErr] =
+ lists:filter(fun({asn1_error,_})->true;(_)->false end,
+ ErrList),
+ SplitErrs =
+ lists:splitwith(fun({_,X})->
+ case element(1,X) of
+ Int when integer(Int) -> true;
+ _ -> false
+ end
+ end,
+ NewErrList),
+ case SplitErrs of
+ {[],UndefPosErrs} -> % if no error with Positon exists
+ lists:last(UndefPosErrs);
+ {IntPosErrs,_} ->
+ IntPosReasons = lists:map(fun(X)->element(2,X) end,IntPosErrs),
+ SortedReasons = lists:keysort(1,IntPosReasons),
+ {asn1_error,lists:last(SortedReasons)}
+ end
+ end.
+
+%% most_prio_error([H={_,Reason}|T],Atom,Err) when atom(Atom) ->
+%% most_prio_error(T,element(1,Reason),H);
+%% most_prio_error([H={_,Reason}|T],Greatest,Err) ->
+%% case element(1,Reason) of
+%% Pos when integer(Pos),Pos>Greatest ->
+%% most_prio_error(
+
+
+tref2Exttref(#typereference{pos=Pos,val=Name}) ->
+ #'Externaltypereference'{pos=Pos,
+ module=get(asn1_module),
+ type=Name}.
+
+tref2Exttref(Pos,Name) ->
+ #'Externaltypereference'{pos=Pos,
+ module=get(asn1_module),
+ type=Name}.
+
+identifier2Extvalueref(#identifier{pos=Pos,val=Name}) ->
+ #'Externalvaluereference'{pos=Pos,
+ module=get(asn1_module),
+ value=Name}.
+
+%% lookahead_assignment/1 checks that the next sequence of tokens
+%% in Token contain a valid assignment or the
+%% 'END' token. Otherwise an exception is thrown.
+lookahead_assignment([{'END',_}|_Rest]) ->
+ ok;
+lookahead_assignment(Tokens) ->
+ parse_Assignment(Tokens),
+ ok.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_pretty_format.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_pretty_format.erl
new file mode 100644
index 0000000000..99dd246d5c
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_pretty_format.erl
@@ -0,0 +1,197 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1ct_pretty_format.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
+%%
+
+%% usage: pretty_format:term(Term) -> PNF list of characters
+%%
+%% Note: this is usually used in expressions like:
+%% io:format('~s\n',[pretty_format:term(Term)]).
+%%
+%% Uses the following simple heuristics
+%%
+%% 1) Simple tuples are printed across the page
+%% (Simple means *all* the elements are "flat")
+%% 2) The Complex tuple {Arg1, Arg2, Arg3,....} is printed thus:
+%% {Arg1,
+%% Arg2,
+%% Arg3,
+%% ...}
+%% 3) Lists are treated as for tuples
+%% 4) Lists of printable characters are treated as strings
+%%
+%% This method seems to work reasonable well for {Tag, ...} type
+%% data structures
+
+-module(asn1ct_pretty_format).
+
+-export([term/1]).
+
+-import(io_lib, [write/1, write_string/1]).
+
+term(Term) ->
+ element(2, term(Term, 0)).
+
+%%______________________________________________________________________
+%% pretty_format:term(Term, Indent} -> {Indent', Chars}
+%% Format <Term> -- use <Indent> to indent the *next* line
+%% Note: Indent' is a new indentaion level (sometimes printing <Term>
+%% the next line to need an "extra" indent!).
+
+term([], Indent) ->
+ {Indent, [$[,$]]};
+term(L, Indent) when is_list(L) ->
+ case is_string(L) of
+ true ->
+ {Indent, write_string(L)};
+ false ->
+ case complex_list(L) of
+ true ->
+ write_complex_list(L, Indent);
+ false ->
+ write_simple_list(L, Indent)
+ end
+ end;
+term(T, Indent) when is_tuple(T) ->
+ case complex_tuple(T) of
+ true ->
+ write_complex_tuple(T, Indent);
+ false ->
+ write_simple_tuple(T, Indent)
+ end;
+term(A, Indent) ->
+ {Indent, write(A)}.
+
+%%______________________________________________________________________
+%% write_simple_list([H|T], Indent) -> {Indent', Chars}
+
+write_simple_list([H|T], Indent) ->
+ {_, S1} = term(H, Indent),
+ {_, S2} = write_simple_list_tail(T, Indent),
+ {Indent, [$[,S1|S2]}.
+
+write_simple_list_tail([H|T], Indent) ->
+ {_, S1} = term(H, Indent),
+ {_, S2} = write_simple_list_tail(T, Indent),
+ {Indent, [$,,S1| S2]};
+write_simple_list_tail([], Indent) ->
+ {Indent, "]"};
+write_simple_list_tail(Other, Indent) ->
+ {_, S} = term(Other, Indent),
+ {Indent, [$|,S,$]]}.
+
+%%______________________________________________________________________
+%% write_complex_list([H|T], Indent) -> {Indent', Chars}
+
+write_complex_list([H|T], Indent) ->
+ {I1, S1} = term(H, Indent+1),
+ {_, S2} = write_complex_list_tail(T, I1),
+ {Indent, [$[,S1|S2]}.
+
+write_complex_list_tail([H|T], Indent) ->
+ {I1, S1} = term(H, Indent),
+ {_, S2} = write_complex_list_tail(T, I1),
+ {Indent, [$,,nl_indent(Indent),S1,S2]};
+write_complex_list_tail([], Indent) ->
+ {Indent, "]"};
+write_complex_list_tail(Other, Indent) ->$,,
+ {_, S} = term(Other, Indent),
+ {Indent, [$|,S,$]]}.
+
+%%______________________________________________________________________
+%% complex_list(List) -> true | false
+%% returns true if the list is complex otherwise false
+
+complex_list([]) ->
+ false;
+complex_list([H|T]) when is_number(H); is_atom(H) ->
+ complex_list(T);
+complex_list([H|T]) ->
+ case is_string(H) of
+ true ->
+ complex_list(T);
+ false ->
+ true
+ end;
+complex_list(_) -> true.
+
+%%______________________________________________________________________
+%% complex_tuple(Tuple) -> true | false
+%% returns true if the tuple is complex otherwise false
+
+complex_tuple(T) ->
+ complex_list(tuple_to_list(T)).
+
+%%______________________________________________________________________
+%% write_simple_tuple(Tuple, Indent} -> {Indent', Chars}
+
+write_simple_tuple({}, Indent) ->
+ {Indent, "{}"};
+write_simple_tuple(Tuple, Indent) ->
+ {_, S} = write_simple_tuple_args(tuple_to_list(Tuple), Indent),
+ {Indent, [${, S, $}]}.
+
+write_simple_tuple_args([X], Indent) ->
+ term(X, Indent);
+write_simple_tuple_args([H|T], Indent) ->
+ {_, SH} = term(H, Indent),
+ {_, ST} = write_simple_tuple_args(T, Indent),
+ {Indent, [SH, $,, ST]}.
+
+%%______________________________________________________________________
+%% write_complex_tuple(Tuple, Indent} -> {Indent', Chars}
+
+write_complex_tuple(Tuple, Indent) ->
+ [H|T] = tuple_to_list(Tuple),
+ {I1, SH} = term(H, Indent+2),
+ {_, ST} = write_complex_tuple_args(T, I1),
+ {Indent, [${, SH, ST, $}]}.
+
+write_complex_tuple_args([X], Indent) ->
+ {_, S} = term(X, Indent),
+ {Indent, [$,, nl_indent(Indent), S]};
+write_complex_tuple_args([H|T], Indent) ->
+ {I1, SH} = term(H, Indent),
+ {_, ST} = write_complex_tuple_args(T, I1),
+ {Indent, [$,, nl_indent(Indent) , SH, ST]};
+write_complex_tuple_args([], Indent) ->
+ {Indent, []}.
+
+%%______________________________________________________________________
+%% utilities
+
+nl_indent(I) when I >= 0 ->
+ ["\n"|indent(I)];
+nl_indent(_) ->
+ [$\s].
+
+indent(I) when I >= 8 ->
+ [$\t|indent(I-8)];
+indent(I) when I > 0 ->
+ [$\s|indent(I-1)];
+indent(_) ->
+ [].
+
+is_string([9|T]) ->
+ is_string(T);
+is_string([10|T]) ->
+ is_string(T);
+is_string([H|T]) when H >31, H < 127 ->
+ is_string(T);
+is_string([]) ->
+ true;
+is_string(_) ->
+ false.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_tok.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_tok.erl
new file mode 100644
index 0000000000..b5ccc4a5d2
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_tok.erl
@@ -0,0 +1,351 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1ct_tok.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
+%%
+-module(asn1ct_tok).
+
+%% Tokenize ASN.1 code (input to parser generated with yecc)
+
+-export([get_name/2,tokenise/2, file/1]).
+
+
+file(File) ->
+ case file:open(File, [read]) of
+ {error, Reason} ->
+ {error,{File,file:format_error(Reason)}};
+ {ok,Stream} ->
+ process0(Stream)
+ end.
+
+process0(Stream) ->
+ process(Stream,0,[]).
+
+process(Stream,Lno,R) ->
+ process(io:get_line(Stream, ''), Stream,Lno+1,R).
+
+process(eof, Stream,Lno,R) ->
+ file:close(Stream),
+ lists:flatten(lists:reverse([{'$end',Lno}|R]));
+
+
+process(L, Stream,Lno,R) when list(L) ->
+ %%io:format('read:~s',[L]),
+ case catch tokenise(L,Lno) of
+ {'ERR',Reason} ->
+ io:format("Tokeniser error on line: ~w ~w~n",[Lno,Reason]),
+ exit(0);
+ T ->
+ %%io:format('toks:~w~n',[T]),
+ process(Stream,Lno,[T|R])
+ end.
+
+
+tokenise([H|T],Lno) when $a =< H , H =< $z ->
+ {X, T1} = get_name(T, [H]),
+ [{identifier,Lno, list_to_atom(X)}|tokenise(T1,Lno)];
+
+tokenise([$&,H|T],Lno) when $A =< H , H =< $Z ->
+ {Y, T1} = get_name(T, [H]),
+ X = list_to_atom(Y),
+ [{typefieldreference, Lno, X} | tokenise(T1, Lno)];
+
+tokenise([$&,H|T],Lno) when $a =< H , H =< $z ->
+ {Y, T1} = get_name(T, [H]),
+ X = list_to_atom(Y),
+ [{valuefieldreference, Lno, X} | tokenise(T1, Lno)];
+
+tokenise([H|T],Lno) 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)];
+ false ->
+ [{typereference,Lno,X}|tokenise(T1,Lno)];
+ rstrtype ->
+ [{restrictedcharacterstringtype,Lno,X}|tokenise(T1,Lno)]
+ end;
+
+tokenise([$-,H|T],Lno) when $0 =< H , H =< $9 ->
+ {X, T1} = get_number(T, [H]),
+ [{number,Lno,-1 * list_to_integer(X)}|tokenise(T1,Lno)];
+
+tokenise([H|T],Lno) when $0 =< H , H =< $9 ->
+ {X, T1} = get_number(T, [H]),
+ [{number,Lno,list_to_integer(X)}|tokenise(T1,Lno)];
+
+tokenise([$-,$-|T],Lno) ->
+ tokenise(skip_comment(T),Lno);
+tokenise([$:,$:,$=|T],Lno) ->
+ [{'::=',Lno}|tokenise(T,Lno)];
+
+tokenise([$'|T],Lno) ->
+ case catch collect_quoted(T,Lno,[]) of
+ {'ERR',_} ->
+ throw({'ERR','bad_quote'});
+ {Thing, T1} ->
+ [Thing|tokenise(T1,Lno)]
+ end;
+
+tokenise([$"|T],Lno) ->
+ collect_string(T,Lno);
+
+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([$,|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([$.,$.|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([$||T],Lno) ->
+ [{'|',Lno}|tokenise(T,Lno)];
+
+
+tokenise([H|T],Lno) ->
+ case white_space(H) of
+ true ->
+ tokenise(T,Lno);
+ false ->
+ [{list_to_atom([H]),Lno}|tokenise(T,Lno)]
+ end;
+tokenise([],_) ->
+ [].
+
+
+collect_string(L,Lno) ->
+ collect_string(L,Lno,[]).
+
+collect_string([],_,_) ->
+ throw({'ERR','bad_quote found eof'});
+
+collect_string([H|T],Lno,Str) ->
+ case H of
+ $" ->
+ [{cstring,1,lists:reverse(Str)}|tokenise(T,Lno)];
+ Ch ->
+ collect_string(T,Lno,[Ch|Str])
+ end.
+
+
+
+% <name> is letters digits hyphens
+% hypen is not the last character. Hypen hyphen is NOT allowed
+%
+% <identifier> ::= <lowercase> <name>
+
+get_name([$-,Char|T], L) ->
+ case isalnum(Char) of
+ true ->
+ get_name(T,[Char,$-|L]);
+ false ->
+ {lists:reverse(L),[$-,Char|T]}
+ end;
+get_name([$-|T], L) ->
+ {lists:reverse(L),[$-|T]};
+get_name([Char|T], L) ->
+ case isalnum(Char) of
+ true ->
+ get_name(T,[Char|L]);
+ false ->
+ {lists:reverse(L),[Char|T]}
+ end;
+get_name([], L) ->
+ {lists:reverse(L), []}.
+
+
+isalnum(H) when $A =< H , H =< $Z ->
+ true;
+isalnum(H) when $a =< H , H =< $z ->
+ true;
+isalnum(H) when $0 =< H , H =< $9 ->
+ true;
+isalnum(_) ->
+ false.
+
+isdigit(H) when $0 =< H , H =< $9 ->
+ true;
+isdigit(_) ->
+ false.
+
+white_space(9) -> true;
+white_space(10) -> true;
+white_space(13) -> true;
+white_space(32) -> true;
+white_space(_) -> false.
+
+
+get_number([H|T], L) ->
+ case isdigit(H) of
+ true ->
+ get_number(T, [H|L]);
+ false ->
+ {lists:reverse(L), [H|T]}
+ end;
+get_number([], L) ->
+ {lists:reverse(L), []}.
+
+skip_comment([]) ->
+ [];
+skip_comment([$-,$-|T]) ->
+ T;
+skip_comment([_|T]) ->
+ skip_comment(T).
+
+collect_quoted([$',$B|T],Lno, L) ->
+ case check_bin(L) of
+ true ->
+ {{bstring,Lno, lists:reverse(L)}, T};
+ false ->
+ throw({'ERR',{invalid_binary_number, lists:reverse(L)}})
+ end;
+collect_quoted([$',$H|T],Lno, L) ->
+ case check_hex(L) of
+ true ->
+ {{hstring,Lno, lists:reverse(L)}, T};
+ false ->
+ throw({'ERR',{invalid_binary_number, lists:reverse(L)}})
+ end;
+collect_quoted([H|T], Lno, L) ->
+ collect_quoted(T, Lno,[H|L]);
+collect_quoted([], _, _) -> % This should be allowed FIX later
+ throw({'ERR',{eol_in_token}}).
+
+check_bin([$0|T]) ->
+ check_bin(T);
+check_bin([$1|T]) ->
+ check_bin(T);
+check_bin([]) ->
+ true;
+check_bin(_) ->
+ false.
+
+check_hex([H|T]) when $0 =< H , H =< $9 ->
+ check_hex(T);
+check_hex([H|T]) when $A =< H , H =< $F ->
+ check_hex(T);
+check_hex([]) ->
+ true;
+check_hex(_) ->
+ false.
+
+
+%% reserved_word(A) -> true|false|rstrtype
+%% A = atom()
+%% returns true if A is a reserved ASN.1 word
+%% returns false if A is not a reserved word
+%% returns rstrtype if A is a reserved word in the group
+%% RestrictedCharacterStringType
+reserved_word('ABSENT') -> true;
+%reserved_word('ABSTRACT-SYNTAX') -> true; % impl as predef item
+reserved_word('ALL') -> true;
+reserved_word('ANY') -> true;
+reserved_word('APPLICATION') -> true;
+reserved_word('AUTOMATIC') -> true;
+reserved_word('BEGIN') -> true;
+reserved_word('BIT') -> true;
+reserved_word('BMPString') -> rstrtype;
+reserved_word('BOOLEAN') -> true;
+reserved_word('BY') -> true;
+reserved_word('CHARACTER') -> true;
+reserved_word('CHOICE') -> true;
+reserved_word('CLASS') -> true;
+reserved_word('COMPONENT') -> true;
+reserved_word('COMPONENTS') -> true;
+reserved_word('CONSTRAINED') -> true;
+reserved_word('DEFAULT') -> true;
+reserved_word('DEFINED') -> true;
+reserved_word('DEFINITIONS') -> true;
+reserved_word('EMBEDDED') -> true;
+reserved_word('END') -> true;
+reserved_word('ENUMERATED') -> true;
+reserved_word('EXCEPT') -> true;
+reserved_word('EXPLICIT') -> true;
+reserved_word('EXPORTS') -> true;
+reserved_word('EXTERNAL') -> true;
+reserved_word('FALSE') -> true;
+reserved_word('FROM') -> true;
+reserved_word('GeneralizedTime') -> true;
+reserved_word('GeneralString') -> rstrtype;
+reserved_word('GraphicString') -> rstrtype;
+reserved_word('IA5String') -> rstrtype;
+% reserved_word('TYPE-IDENTIFIER') -> true; % impl as predef item
+reserved_word('IDENTIFIER') -> true;
+reserved_word('IMPLICIT') -> true;
+reserved_word('IMPORTS') -> true;
+reserved_word('INCLUDES') -> true;
+reserved_word('INSTANCE') -> true;
+reserved_word('INTEGER') -> true;
+reserved_word('INTERSECTION') -> true;
+reserved_word('ISO646String') -> rstrtype;
+reserved_word('MAX') -> true;
+reserved_word('MIN') -> true;
+reserved_word('MINUS-INFINITY') -> true;
+reserved_word('NULL') -> true;
+reserved_word('NumericString') -> rstrtype;
+reserved_word('OBJECT') -> true;
+reserved_word('ObjectDescriptor') -> true;
+reserved_word('OCTET') -> true;
+reserved_word('OF') -> true;
+reserved_word('OPTIONAL') -> true;
+reserved_word('PDV') -> true;
+reserved_word('PLUS-INFINITY') -> true;
+reserved_word('PRESENT') -> true;
+reserved_word('PrintableString') -> rstrtype;
+reserved_word('PRIVATE') -> true;
+reserved_word('REAL') -> true;
+reserved_word('SEQUENCE') -> true;
+reserved_word('SET') -> true;
+reserved_word('SIZE') -> true;
+reserved_word('STRING') -> true;
+reserved_word('SYNTAX') -> true;
+reserved_word('T61String') -> rstrtype;
+reserved_word('TAGS') -> true;
+reserved_word('TeletexString') -> rstrtype;
+reserved_word('TRUE') -> true;
+reserved_word('UNION') -> true;
+reserved_word('UNIQUE') -> true;
+reserved_word('UNIVERSAL') -> true;
+reserved_word('UniversalString') -> rstrtype;
+reserved_word('UTCTime') -> true;
+reserved_word('VideotexString') -> rstrtype;
+reserved_word('VisibleString') -> rstrtype;
+reserved_word('WITH') -> true;
+reserved_word(_) -> false.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_value.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_value.erl
new file mode 100644
index 0000000000..3d366a1a27
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_value.erl
@@ -0,0 +1,330 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1ct_value.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
+%%
+-module(asn1ct_value).
+
+%% Generate Erlang values for ASN.1 types.
+%% The value is randomized within it's constraints
+
+-include("asn1_records.hrl").
+%-compile(export_all).
+
+-export([get_type/3]).
+
+
+
+%% Generate examples of values ******************************
+%%****************************************x
+
+
+get_type(M,Typename,Tellname) ->
+ case asn1_db:dbget(M,Typename) of
+ undefined ->
+ {asn1_error,{not_found,{M,Typename}}};
+ Tdef when record(Tdef,typedef) ->
+ Type = Tdef#typedef.typespec,
+ get_type(M,[Typename],Type,Tellname);
+ Err ->
+ {asn1_error,{other,Err}}
+ end.
+
+get_type(M,Typename,Type,Tellname) when record(Type,type) ->
+ InnerType = get_inner(Type#type.def),
+ case asn1ct_gen:type(InnerType) of
+ #'Externaltypereference'{module=Emod,type=Etype} ->
+ get_type(Emod,Etype,Tellname);
+ {_,user} ->
+ case Tellname of
+ yes -> {Typename,get_type(M,InnerType,no)};
+ no -> get_type(M,InnerType,no)
+ end;
+ {notype,_} ->
+ true;
+ {primitive,bif} ->
+ get_type_prim(Type);
+ 'ASN1_OPEN_TYPE' ->
+ case Type#type.constraint of
+ [#'Externaltypereference'{type=TrefConstraint}] ->
+ get_type(M,TrefConstraint,no);
+ _ ->
+ "open_type"
+ end;
+ {constructed,bif} ->
+ get_type_constructed(M,Typename,InnerType,Type)
+ end;
+get_type(M,Typename,#'ComponentType'{name = Name,typespec = Type},_) ->
+ get_type(M,[Name|Typename],Type,no);
+get_type(_,_,_,_) -> % 'EXTENSIONMARK'
+ undefined.
+
+get_inner(A) when atom(A) -> A;
+get_inner(Ext) when record(Ext,'Externaltypereference') -> Ext;
+get_inner({typereference,_Pos,Name}) -> Name;
+get_inner(T) when tuple(T) ->
+ case asn1ct_gen:get_inner(T) of
+ {fixedtypevaluefield,_,Type} ->
+ Type#type.def;
+ {typefield,_FieldName} ->
+ 'ASN1_OPEN_TYPE';
+ Other ->
+ Other
+ end.
+%%get_inner(T) when tuple(T) -> element(1,T).
+
+
+
+get_type_constructed(M,Typename,InnerType,D) when record(D,type) ->
+ case InnerType of
+ 'SET' ->
+ get_sequence(M,Typename,D);
+ 'SEQUENCE' ->
+ get_sequence(M,Typename,D);
+ 'CHOICE' ->
+ get_choice(M,Typename,D);
+ 'SEQUENCE OF' ->
+ {_,Type} = D#type.def,
+ NameSuffix = asn1ct_gen:constructed_suffix(InnerType,Type#type.def),
+ get_sequence_of(M,Typename,D,NameSuffix);
+ 'SET OF' ->
+ {_,Type} = D#type.def,
+ NameSuffix = asn1ct_gen:constructed_suffix(InnerType,Type#type.def),
+ get_sequence_of(M,Typename,D,NameSuffix);
+ _ ->
+ exit({nyi,InnerType})
+ end.
+
+get_sequence(M,Typename,Type) ->
+ {_SEQorSET,CompList} =
+ case Type#type.def of
+ #'SEQUENCE'{components=Cl} -> {'SEQUENCE',Cl};
+ #'SET'{components=Cl} -> {'SET',Cl}
+ end,
+ case get_components(M,Typename,CompList) of
+ [] ->
+ {list_to_atom(asn1ct_gen:list2rname(Typename))};
+ C ->
+ list_to_tuple([list_to_atom(asn1ct_gen:list2rname(Typename))|C])
+ end.
+
+get_components(M,Typename,{Root,Ext}) ->
+ get_components(M,Typename,Root++Ext);
+
+%% Should enhance this *** HERE *** with proper handling of extensions
+
+get_components(M,Typename,[H|T]) ->
+ [get_type(M,Typename,H,no)|
+ get_components(M,Typename,T)];
+get_components(_,_,[]) ->
+ [].
+
+get_choice(M,Typename,Type) ->
+ {'CHOICE',TCompList} = Type#type.def,
+ case TCompList of
+ [] ->
+ {asn1_EMPTY,asn1_EMPTY};
+ {CompList,ExtList} -> % Should be enhanced to handle extensions too
+ CList = CompList ++ ExtList,
+ C = lists:nth(random(length(CList)),CList),
+ {C#'ComponentType'.name,get_type(M,Typename,C,no)};
+ CompList when list(CompList) ->
+ C = lists:nth(random(length(CompList)),CompList),
+ {C#'ComponentType'.name,get_type(M,Typename,C,no)}
+ end.
+
+get_sequence_of(M,Typename,Type,TypeSuffix) ->
+ %% should generate length according to constraints later
+ {_,Oftype} = Type#type.def,
+ C = Type#type.constraint,
+ S = size_random(C),
+ NewTypeName = [TypeSuffix|Typename],
+ gen_list(M,NewTypeName,Oftype,no,S).
+
+gen_list(_,_,_,_,0) ->
+ [];
+gen_list(M,Typename,Oftype,Tellname,N) ->
+ [get_type(M,Typename,Oftype,no)|gen_list(M,Typename,Oftype,Tellname,N-1)].
+
+get_type_prim(D) ->
+ C = D#type.constraint,
+ case D#type.def of
+ 'INTEGER' ->
+ i_random(C);
+ {'INTEGER',NamedNumberList} ->
+ NN = [X||{X,_} <- NamedNumberList],
+ case NN of
+ [] ->
+ i_random(C);
+ _ ->
+ lists:nth(random(length(NN)),NN)
+ end;
+ Enum when tuple(Enum),element(1,Enum)=='ENUMERATED' ->
+ NamedNumberList =
+ case Enum of
+ {_,_,NNL} -> NNL;
+ {_,NNL} -> NNL
+ end,
+ NNew=
+ case NamedNumberList of
+ {N1,N2} ->
+ N1 ++ N2;
+ _->
+ NamedNumberList
+ end,
+ NN = [X||{X,_} <- NNew],
+ case NN of
+ [] ->
+ asn1_EMPTY;
+ _ ->
+ lists:nth(random(length(NN)),NN)
+ end;
+ {'BIT STRING',NamedNumberList} ->
+%% io:format("get_type_prim 1: ~w~n",[NamedNumberList]),
+ NN = [X||{X,_} <- NamedNumberList],
+ case NN of
+ [] ->
+ Bl1 =lists:reverse(adjust_list(size_random(C),[1,0,1,1])),
+ lists:reverse(lists:dropwhile(fun(0)->true;(1)->false end,Bl1));
+ _ ->
+%% io:format("get_type_prim 2: ~w~n",[NN]),
+ [lists:nth(random(length(NN)),NN)]
+ end;
+ 'ANY' ->
+ exit({asn1_error,nyi,'ANY'});
+ 'NULL' ->
+ 'NULL';
+ 'OBJECT IDENTIFIER' ->
+ Len = random(3),
+ Olist = [(random(1000)-1)||_X <-lists:seq(1,Len)],
+ list_to_tuple([random(3)-1,random(40)-1|Olist]);
+ 'ObjectDescriptor' ->
+ object_descriptor_nyi;
+ 'BOOLEAN' ->
+ true;
+ 'OCTET STRING' ->
+ adjust_list(size_random(C),c_string(C,"OCTET STRING"));
+ 'NumericString' ->
+ adjust_list(size_random(C),c_string(C,"0123456789"));
+ 'TeletexString' ->
+ adjust_list(size_random(C),c_string(C,"TeletexString"));
+ 'VideotexString' ->
+ adjust_list(size_random(C),c_string(C,"VideotexString"));
+ 'UTCTime' ->
+ "97100211-0500";
+ 'GeneralizedTime' ->
+ "19971002103130.5";
+ 'GraphicString' ->
+ adjust_list(size_random(C),c_string(C,"GraphicString"));
+ 'VisibleString' ->
+ adjust_list(size_random(C),c_string(C,"VisibleString"));
+ 'GeneralString' ->
+ adjust_list(size_random(C),c_string(C,"GeneralString"));
+ 'PrintableString' ->
+ adjust_list(size_random(C),c_string(C,"PrintableString"));
+ 'IA5String' ->
+ adjust_list(size_random(C),c_string(C,"IA5String"));
+ 'BMPString' ->
+ adjust_list(size_random(C),c_string(C,"BMPString"));
+ 'UniversalString' ->
+ adjust_list(size_random(C),c_string(C,"UniversalString"));
+ XX ->
+ exit({asn1_error,nyi,XX})
+ end.
+
+c_string(undefined,Default) ->
+ Default;
+c_string(C,Default) ->
+ case get_constraint(C,'PermittedAlphabet') of
+ {'SingleValue',Sv} when list(Sv) ->
+ Sv;
+ {'SingleValue',V} when integer(V) ->
+ [V];
+ no ->
+ Default
+ end.
+
+random(Upper) ->
+ {A1,A2,A3} = erlang:now(),
+ random:seed(A1,A2,A3),
+ random:uniform(Upper).
+
+size_random(C) ->
+ case get_constraint(C,'SizeConstraint') of
+ no ->
+ c_random({0,5},no);
+ {Lb,Ub} when Ub-Lb =< 4 ->
+ c_random({Lb,Ub},no);
+ {Lb,_} ->
+ c_random({Lb,Lb+4},no);
+ Sv ->
+ c_random(no,Sv)
+ end.
+
+i_random(C) ->
+ c_random(get_constraint(C,'ValueRange'),get_constraint(C,'SingleValue')).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% c_random(Range,SingleValue)
+%% only called from other X_random functions
+
+c_random(VRange,Single) ->
+ case {VRange,Single} of
+ {no,no} ->
+ random(16#fffffff) - (16#fffffff bsr 1);
+ {R,no} ->
+ case R of
+ {Lb,Ub} when integer(Lb),integer(Ub) ->
+ Range = Ub - Lb +1,
+ Lb + (random(Range)-1);
+ {Lb,'MAX'} ->
+ Lb + random(16#fffffff)-1;
+ {'MIN',Ub} ->
+ Ub - random(16#fffffff)-1;
+ {A,{'ASN1_OK',B}} ->
+ Range = B - A +1,
+ A + (random(Range)-1)
+ end;
+ {_,S} when integer(S) ->
+ S;
+ {_,S} when list(S) ->
+ lists:nth(random(length(S)),S)
+%% {S1,S2} ->
+%% io:format("asn1ct_value: hejsan hoppsan~n");
+%% _ ->
+%% io:format("asn1ct_value: hejsan hoppsan 2~n")
+%% io:format("asn1ct_value: c_random/2: S1 = ~w~n"
+%% "S2 = ~w,~n",[S1,S2])
+%% exit(self(),goodbye)
+ end.
+
+adjust_list(Len,Orig) ->
+ adjust_list1(Len,Orig,Orig,[]).
+
+adjust_list1(0,_Orig,[_Oh|_Ot],Acc) ->
+ lists:reverse(Acc);
+adjust_list1(Len,Orig,[],Acc) ->
+ adjust_list1(Len,Orig,Orig,Acc);
+adjust_list1(Len,Orig,[Oh|Ot],Acc) ->
+ adjust_list1(Len-1,Orig,Ot,[Oh|Acc]).
+
+
+get_constraint(C,Key) ->
+ case lists:keysearch(Key,1,C) of
+ false ->
+ no;
+ {value,{_,V}} ->
+ V
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt.erl
new file mode 100644
index 0000000000..efac8daf6b
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt.erl
@@ -0,0 +1,69 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1rt.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
+%%
+-module(asn1rt).
+
+%% Runtime functions for ASN.1 (i.e encode, decode)
+
+-export([encode/2,encode/3,decode/3,load_driver/0,unload_driver/0,info/1]).
+
+encode(Module,{Type,Term}) ->
+ encode(Module,Type,Term).
+
+encode(Module,Type,Term) ->
+ case catch apply(Module,encode,[Type,Term]) of
+ {'EXIT',undef} ->
+ {error,{asn1,{undef,Module,Type}}};
+ Result ->
+ Result
+ end.
+
+decode(Module,Type,Bytes) ->
+ case catch apply(Module,decode,[Type,Bytes]) of
+ {'EXIT',undef} ->
+ {error,{asn1,{undef,Module,Type}}};
+ Result ->
+ Result
+ end.
+
+load_driver() ->
+ asn1rt_driver_handler:load_driver(),
+ receive
+ driver_ready ->
+ ok;
+ Err={error,_Reason} ->
+ Err;
+ Error ->
+ {error,Error}
+ end.
+
+unload_driver() ->
+ case catch asn1rt_driver_handler:unload_driver() of
+ ok ->
+ ok;
+ Error ->
+ {error,Error}
+ end.
+
+
+info(Module) ->
+ case catch apply(Module,info,[]) of
+ {'EXIT',{undef,_Reason}} ->
+ {error,{asn1,{undef,Module,info}}};
+ Result ->
+ {ok,Result}
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_ber_bin.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_ber_bin.erl
new file mode 100644
index 0000000000..6064515a7e
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_ber_bin.erl
@@ -0,0 +1,2310 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1rt_ber_bin.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
+%%
+-module(asn1rt_ber_bin).
+
+%% encoding / decoding of BER
+
+-export([decode/1]).
+-export([fixoptionals/2,split_list/2,cindex/3,restbytes2/3,
+ list_to_record/2,
+ encode_tag_val/1,decode_tag/1,peek_tag/1,
+ check_tags/3, encode_tags/3]).
+-export([encode_boolean/2,decode_boolean/3,
+ encode_integer/3,encode_integer/4,
+ decode_integer/4,decode_integer/5,encode_enumerated/2,
+ encode_enumerated/4,decode_enumerated/5,
+ encode_real/2,decode_real/4,
+ encode_bit_string/4,decode_bit_string/6,
+ decode_compact_bit_string/6,
+ encode_octet_string/3,decode_octet_string/5,
+ encode_null/2,decode_null/3,
+ encode_object_identifier/2,decode_object_identifier/3,
+ encode_restricted_string/4,decode_restricted_string/6,
+ encode_universal_string/3,decode_universal_string/5,
+ encode_BMP_string/3,decode_BMP_string/5,
+ encode_generalized_time/3,decode_generalized_time/5,
+ encode_utc_time/3,decode_utc_time/5,
+ encode_length/1,decode_length/1,
+ check_if_valid_tag/3,
+ decode_tag_and_length/1, decode_components/6,
+ decode_components/7, decode_set/6]).
+
+-export([encode_open_type/1,encode_open_type/2,decode_open_type/1,decode_open_type/2,decode_open_type/3]).
+-export([skipvalue/1, skipvalue/2]).
+
+-include("asn1_records.hrl").
+
+% the encoding of class of tag bits 8 and 7
+-define(UNIVERSAL, 0).
+-define(APPLICATION, 16#40).
+-define(CONTEXT, 16#80).
+-define(PRIVATE, 16#C0).
+
+%%% primitive or constructed encoding % bit 6
+-define(PRIMITIVE, 0).
+-define(CONSTRUCTED, 2#00100000).
+
+%%% The tag-number for universal types
+-define(N_BOOLEAN, 1).
+-define(N_INTEGER, 2).
+-define(N_BIT_STRING, 3).
+-define(N_OCTET_STRING, 4).
+-define(N_NULL, 5).
+-define(N_OBJECT_IDENTIFIER, 6).
+-define(N_OBJECT_DESCRIPTOR, 7).
+-define(N_EXTERNAL, 8).
+-define(N_REAL, 9).
+-define(N_ENUMERATED, 10).
+-define(N_EMBEDDED_PDV, 11).
+-define(N_SEQUENCE, 16).
+-define(N_SET, 17).
+-define(N_NumericString, 18).
+-define(N_PrintableString, 19).
+-define(N_TeletexString, 20).
+-define(N_VideotexString, 21).
+-define(N_IA5String, 22).
+-define(N_UTCTime, 23).
+-define(N_GeneralizedTime, 24).
+-define(N_GraphicString, 25).
+-define(N_VisibleString, 26).
+-define(N_GeneralString, 27).
+-define(N_UniversalString, 28).
+-define(N_BMPString, 30).
+
+
+% the complete tag-word of built-in types
+-define(T_BOOLEAN, ?UNIVERSAL bor ?PRIMITIVE bor 1).
+-define(T_INTEGER, ?UNIVERSAL bor ?PRIMITIVE bor 2).
+-define(T_BIT_STRING, ?UNIVERSAL bor ?PRIMITIVE bor 3). % can be CONSTRUCTED
+-define(T_OCTET_STRING, ?UNIVERSAL bor ?PRIMITIVE bor 4). % can be CONSTRUCTED
+-define(T_NULL, ?UNIVERSAL bor ?PRIMITIVE bor 5).
+-define(T_OBJECT_IDENTIFIER,?UNIVERSAL bor ?PRIMITIVE bor 6).
+-define(T_OBJECT_DESCRIPTOR,?UNIVERSAL bor ?PRIMITIVE bor 7).
+-define(T_EXTERNAL, ?UNIVERSAL bor ?PRIMITIVE bor 8).
+-define(T_REAL, ?UNIVERSAL bor ?PRIMITIVE bor 9).
+-define(T_ENUMERATED, ?UNIVERSAL bor ?PRIMITIVE bor 10).
+-define(T_EMBEDDED_PDV, ?UNIVERSAL bor ?PRIMITIVE bor 11).
+-define(T_SEQUENCE, ?UNIVERSAL bor ?CONSTRUCTED bor 16).
+-define(T_SET, ?UNIVERSAL bor ?CONSTRUCTED bor 17).
+-define(T_NumericString, ?UNIVERSAL bor ?PRIMITIVE bor 18). %can be constructed
+-define(T_PrintableString, ?UNIVERSAL bor ?PRIMITIVE bor 19). %can be constructed
+-define(T_TeletexString, ?UNIVERSAL bor ?PRIMITIVE bor 20). %can be constructed
+-define(T_VideotexString, ?UNIVERSAL bor ?PRIMITIVE bor 21). %can be constructed
+-define(T_IA5String, ?UNIVERSAL bor ?PRIMITIVE bor 22). %can be constructed
+-define(T_UTCTime, ?UNIVERSAL bor ?PRIMITIVE bor 23).
+-define(T_GeneralizedTime, ?UNIVERSAL bor ?PRIMITIVE bor 24).
+-define(T_GraphicString, ?UNIVERSAL bor ?PRIMITIVE bor 25). %can be constructed
+-define(T_VisibleString, ?UNIVERSAL bor ?PRIMITIVE bor 26). %can be constructed
+-define(T_GeneralString, ?UNIVERSAL bor ?PRIMITIVE bor 27). %can be constructed
+-define(T_UniversalString, ?UNIVERSAL bor ?PRIMITIVE bor 28). %can be constructed
+-define(T_BMPString, ?UNIVERSAL bor ?PRIMITIVE bor 30). %can be constructed
+
+
+decode(Bin) ->
+ decode_primitive(Bin).
+
+decode_primitive(Bin) ->
+ {Tlv = {Tag,Len,V},<<>>} = decode_tlv(Bin),
+ case element(2,Tag) of
+ ?CONSTRUCTED ->
+ {Tag,Len,decode_constructed(V)};
+ _ ->
+ Tlv
+ end.
+
+decode_constructed(<<>>) ->
+ [];
+decode_constructed(Bin) ->
+ {Tlv = {Tag,Len,V},Rest} = decode_tlv(Bin),
+ NewTlv =
+ case element(2,Tag) of
+ ?CONSTRUCTED ->
+ {Tag,Len,decode_constructed(V)};
+ _ ->
+ Tlv
+ end,
+ [NewTlv|decode_constructed(Rest)].
+
+decode_tlv(Bin) ->
+ {Tag,Bin1,_Rb1} = decode_tag(Bin),
+ {{Len,Bin2},_Rb2} = decode_length(Bin1),
+ <<V:Len/binary,Bin3/binary>> = Bin2,
+ {{Tag,Len,V},Bin3}.
+
+
+
+%%%%%%%%%%%%%
+% split_list(List,HeadLen) -> {HeadList,TailList}
+%
+% splits List into HeadList (Length=HeadLen) and TailList
+% if HeadLen == indefinite -> return {List,indefinite}
+split_list(List,indefinite) ->
+ {List, indefinite};
+split_list(Bin, Len) when binary(Bin) ->
+ split_binary(Bin,Len);
+split_list(List,Len) ->
+ {lists:sublist(List,Len),lists:nthtail(Len,List)}.
+
+
+%%% new function which fixes a bug regarding indefinite length decoding
+restbytes2(indefinite,<<0,0,RemBytes/binary>>,_) ->
+ {RemBytes,2};
+restbytes2(indefinite,RemBytes,ext) ->
+ skipvalue(indefinite,RemBytes);
+restbytes2(RemBytes,<<>>,_) ->
+ {RemBytes,0};
+restbytes2(_RemBytes,Bytes,noext) ->
+ exit({error,{asn1, {unexpected,Bytes}}});
+restbytes2(RemBytes,_Bytes,ext) ->
+ {RemBytes,0}.
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% skipvalue(Length, Bytes) -> {RemainingBytes, RemovedNumberOfBytes}
+%%
+%% skips the one complete (could be nested) TLV from Bytes
+%% handles both definite and indefinite length encodings
+%%
+
+skipvalue(L, Bytes) ->
+ skipvalue(L, Bytes, 0).
+
+skipvalue(indefinite, Bytes, Rb) ->
+ {_T,Bytes2,R2} = decode_tag(Bytes),
+ {{L,Bytes3},R3} = decode_length(Bytes2),
+ {Bytes4,Rb4} = case L of
+ indefinite ->
+ skipvalue(indefinite,Bytes3,R2+R3);
+ _ ->
+ <<_:L/binary, RestBytes/binary>> = Bytes3,
+ {RestBytes, R2+R3+L}
+ end,
+ case Bytes4 of
+ <<0,0,Bytes5/binary>> ->
+ {Bytes5,Rb+Rb4+2};
+ _ -> skipvalue(indefinite,Bytes4,Rb+Rb4)
+ end;
+skipvalue(L, Bytes, Rb) ->
+% <<Skip:L/binary, RestBytes/binary>> = Bytes,
+ <<_:L/binary, RestBytes/binary>> = Bytes,
+ {RestBytes,Rb+L}.
+
+%%skipvalue(indefinite, Bytes, Rb) ->
+%% {T,Bytes2,R2} = decode_tag(Bytes),
+%% {L,Bytes3,R3} = decode_length(Bytes2),
+%% {Bytes4,Rb4} = case L of
+%% indefinite ->
+%% skipvalue(indefinite,Bytes3,R2+R3);
+%% _ ->
+%% lists:nthtail(L,Bytes3) %% konstigt !?
+%% end,
+%% case Bytes4 of
+%% [0,0|Bytes5] ->
+%% {Bytes5,Rb4+2};
+%% _ -> skipvalue(indefinite,Bytes4,Rb4)
+%% end;
+%%skipvalue(L, Bytes, Rb) ->
+%% {lists:nthtail(L,Bytes),Rb+L}.
+
+skipvalue(Bytes) ->
+ {_T,Bytes2,R2} = decode_tag(Bytes),
+ {{L,Bytes3},R3} = decode_length(Bytes2),
+ skipvalue(L,Bytes3,R2+R3).
+
+
+cindex(Ix,Val,Cname) ->
+ case element(Ix,Val) of
+ {Cname,Val2} -> Val2;
+ X -> X
+ end.
+
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+%% Optionals, preset not filled optionals with asn1_NOVALUE
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+
+% converts a list to a record if necessary
+list_to_record(Name,List) when list(List) ->
+ list_to_tuple([Name|List]);
+list_to_record(_Name,Tuple) when tuple(Tuple) ->
+ Tuple.
+
+
+fixoptionals(OptList,Val) when list(Val) ->
+ fixoptionals(OptList,Val,1,[],[]).
+
+fixoptionals([{Name,Pos}|Ot],[{Name,Val}|Vt],_Opt,Acc1,Acc2) ->
+ fixoptionals(Ot,Vt,Pos+1,[1|Acc1],[{Name,Val}|Acc2]);
+fixoptionals([{_Name,Pos}|Ot],V,Pos,Acc1,Acc2) ->
+ fixoptionals(Ot,V,Pos+1,[0|Acc1],[asn1_NOVALUE|Acc2]);
+fixoptionals(O,[Vh|Vt],Pos,Acc1,Acc2) ->
+ fixoptionals(O,Vt,Pos+1,Acc1,[Vh|Acc2]);
+fixoptionals([],[Vh|Vt],Pos,Acc1,Acc2) ->
+ fixoptionals([],Vt,Pos+1,Acc1,[Vh|Acc2]);
+fixoptionals([],[],_,_Acc1,Acc2) ->
+ % return Val as a record
+ list_to_tuple([asn1_RECORDNAME|lists:reverse(Acc2)]).
+
+
+%%encode_tag(TagClass(?UNI, APP etc), Form (?PRIM etx), TagInteger) ->
+%% 8bit Int | binary
+encode_tag_val({Class, Form, TagNo}) when (TagNo =< 30) ->
+ <<(Class bsr 6):2,(Form bsr 5):1,TagNo:5>>;
+
+encode_tag_val({Class, Form, TagNo}) ->
+ {Octets,_Len} = mk_object_val(TagNo),
+ BinOct = list_to_binary(Octets),
+ <<(Class bsr 6):2, (Form bsr 5):1, 31:5,BinOct/binary>>;
+
+%% asumes whole correct tag bitpattern, multiple of 8
+encode_tag_val(Tag) when (Tag =< 255) -> Tag; %% anv�nds denna funktion??!!
+%% asumes correct bitpattern of 0-5
+encode_tag_val(Tag) -> encode_tag_val2(Tag,[]).
+
+encode_tag_val2(Tag, OctAck) when (Tag =< 255) ->
+ [Tag | OctAck];
+encode_tag_val2(Tag, OctAck) ->
+ encode_tag_val2(Tag bsr 8, [255 band Tag | OctAck]).
+
+
+%%%encode_tag(TagClass(?UNI, APP etc), Form (?PRIM etx), TagInteger) ->
+%%% 8bit Int | [list of octets]
+%encode_tag_val({Class, Form, TagNo}) when (TagNo =< 30) ->
+%%% <<Class:2,Form:1,TagNo:5>>;
+% [Class bor Form bor TagNo];
+%encode_tag_val({Class, Form, TagNo}) ->
+% {Octets,L} = mk_object_val(TagNo),
+% [Class bor Form bor 31 | Octets];
+
+
+%%============================================================================\%% Peek on the initial tag
+%% peek_tag(Bytes) -> TagBytes
+%% interprets the first byte and possible second, third and fourth byte as
+%% a tag and returns all the bytes comprising the tag, the constructed/primitive bit (6:th bit of first byte) is normalised to 0
+%%
+
+peek_tag(<<B7_6:2,_:1,31:5,Buffer/binary>>) ->
+ Bin = peek_tag(Buffer, <<>>),
+ <<B7_6:2,31:6,Bin/binary>>;
+%% single tag (tagno < 31)
+peek_tag(<<B7_6:2,_:1,B4_0:5,_Buffer/binary>>) ->
+ <<B7_6:2,B4_0:6>>.
+
+peek_tag(<<0:1,PartialTag:7,_Buffer/binary>>, TagAck) ->
+ <<TagAck/binary,PartialTag>>;
+peek_tag(<<PartialTag,Buffer/binary>>, TagAck) ->
+ peek_tag(Buffer,<<TagAck/binary,PartialTag>>);
+peek_tag(_,TagAck) ->
+ exit({error,{asn1, {invalid_tag,TagAck}}}).
+%%peek_tag([Tag|Buffer]) when (Tag band 31) == 31 ->
+%% [Tag band 2#11011111 | peek_tag(Buffer,[])];
+%%%% single tag (tagno < 31)
+%%peek_tag([Tag|Buffer]) ->
+%% [Tag band 2#11011111].
+
+%%peek_tag([PartialTag|Buffer], TagAck) when (PartialTag < 128 ) ->
+%% lists:reverse([PartialTag|TagAck]);
+%%peek_tag([PartialTag|Buffer], TagAck) ->
+%% peek_tag(Buffer,[PartialTag|TagAck]);
+%%peek_tag(Buffer,TagAck) ->
+%% exit({error,{asn1, {invalid_tag,lists:reverse(TagAck)}}}).
+
+
+%%===============================================================================
+%% Decode a tag
+%%
+%% decode_tag(OctetListBuffer) -> {{Class, Form, TagNo}, RestOfBuffer, RemovedBytes}
+%%===============================================================================
+
+%% multiple octet tag
+decode_tag(<<Class:2, Form:1, 31:5, Buffer/binary>>) ->
+ {TagNo, Buffer1, RemovedBytes} = decode_tag(Buffer, 0, 1),
+ {{(Class bsl 6), (Form bsl 5), TagNo}, Buffer1, RemovedBytes};
+
+%% single tag (< 31 tags)
+decode_tag(<<Class:2,Form:1,TagNo:5, Buffer/binary>>) ->
+ {{(Class bsl 6), (Form bsl 5), TagNo}, Buffer, 1}.
+
+%% last partial tag
+decode_tag(<<0:1,PartialTag:7, Buffer/binary>>, TagAck, RemovedBytes) ->
+ TagNo = (TagAck bsl 7) bor PartialTag,
+ %%<<TagNo>> = <<TagAck:1, PartialTag:7>>,
+ {TagNo, Buffer, RemovedBytes+1};
+% more tags
+decode_tag(<<_:1,PartialTag:7, Buffer/binary>>, TagAck, RemovedBytes) ->
+ TagAck1 = (TagAck bsl 7) bor PartialTag,
+ %%<<TagAck1:16>> = <<TagAck:1, PartialTag:7,0:8>>,
+ decode_tag(Buffer, TagAck1, RemovedBytes+1).
+
+%%------------------------------------------------------------------
+%% check_tags_i is the same as check_tags except that it stops and
+%% returns the remaining tags not checked when it encounters an
+%% indefinite length field
+%% only called internally within this module
+
+check_tags_i([Tag], Buffer, OptOrMand) -> % optimized very usual case
+ {[],check_one_tag(Tag, Buffer, OptOrMand)};
+check_tags_i(Tags, Buffer, OptOrMand) ->
+ check_tags_i(Tags, Buffer, 0, OptOrMand).
+
+check_tags_i([Tag1,Tag2|TagRest], Buffer, Rb, OptOrMand)
+ when Tag1#tag.type == 'IMPLICIT' ->
+ check_tags_i([Tag1#tag{type=Tag2#tag.type}|TagRest], Buffer, Rb, OptOrMand);
+
+check_tags_i([Tag1|TagRest], Buffer, Rb, OptOrMand) ->
+ {Form_Length,Buffer2,Rb1} = check_one_tag(Tag1, Buffer, OptOrMand),
+ case TagRest of
+ [] -> {TagRest, {Form_Length, Buffer2, Rb + Rb1}};
+ _ ->
+ case Form_Length of
+ {?CONSTRUCTED,_} ->
+ {TagRest, {Form_Length, Buffer2, Rb + Rb1}};
+ _ ->
+ check_tags_i(TagRest, Buffer2, Rb + Rb1, mandatory)
+ end
+ end;
+
+check_tags_i([], Buffer, Rb, _) ->
+ {[],{{0,0},Buffer,Rb}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% This function is called from generated code
+
+check_tags([Tag], Buffer, OptOrMand) -> % optimized very usual case
+ check_one_tag(Tag, Buffer, OptOrMand);
+check_tags(Tags, Buffer, OptOrMand) ->
+ check_tags(Tags, Buffer, 0, OptOrMand).
+
+check_tags([Tag1,Tag2|TagRest], Buffer, Rb, OptOrMand)
+ when Tag1#tag.type == 'IMPLICIT' ->
+ check_tags([Tag1#tag{type=Tag2#tag.type}|TagRest], Buffer, Rb, OptOrMand);
+
+check_tags([Tag1|TagRest], Buffer, Rb, OptOrMand) ->
+ {Form_Length,Buffer2,Rb1} = check_one_tag(Tag1, Buffer, OptOrMand),
+ case TagRest of
+ [] -> {Form_Length, Buffer2, Rb + Rb1};
+ _ -> check_tags(TagRest, Buffer2, Rb + Rb1, mandatory)
+ end;
+
+check_tags([], Buffer, Rb, _) ->
+ {{0,0},Buffer,Rb}.
+
+check_one_tag(Tag=#tag{class=ExpectedClass,number=ExpectedNumber}, Buffer, OptOrMand) ->
+ case catch decode_tag(Buffer) of
+ {'EXIT',_Reason} ->
+ tag_error(no_data,Tag,Buffer,OptOrMand);
+ {{ExpectedClass,Form,ExpectedNumber},Buffer2,Rb} ->
+ {{L,Buffer3},RemBytes2} = decode_length(Buffer2),
+ {{Form,L}, Buffer3, RemBytes2+Rb};
+ {ErrorTag,_,_} ->
+ tag_error(ErrorTag, Tag, Buffer, OptOrMand)
+ end.
+
+tag_error(ErrorTag, Tag, Buffer, OptOrMand) ->
+ case OptOrMand of
+ mandatory ->
+ exit({error,{asn1, {invalid_tag,
+ {ErrorTag, Tag, Buffer}}}});
+ _ ->
+ exit({error,{asn1, {no_optional_tag,
+ {ErrorTag, Tag, Buffer}}}})
+ end.
+%%=======================================================================
+%%
+%% Encode all tags in the list Tags and return a possibly deep list of
+%% bytes with tag and length encoded
+%%
+%% prepend_tags(Tags, BytesSoFar, LenSoFar) -> {Bytes, Len}
+encode_tags(Tags, BytesSoFar, LenSoFar) ->
+ NewTags = encode_tags1(Tags, []),
+ %% NewTags contains the resulting tags in reverse order
+ encode_tags2(NewTags, BytesSoFar, LenSoFar).
+
+%encode_tags2([#tag{class=?UNIVERSAL,number=No}|Trest], BytesSoFar, LenSoFar) ->
+% {Bytes2,L2} = encode_length(LenSoFar),
+% encode_tags2(Trest,[[No|Bytes2],BytesSoFar], LenSoFar + 1 + L2);
+encode_tags2([Tag|Trest], BytesSoFar, LenSoFar) ->
+ {Bytes1,L1} = encode_one_tag(Tag),
+ {Bytes2,L2} = encode_length(LenSoFar),
+ encode_tags2(Trest, [Bytes1,Bytes2|BytesSoFar],
+ LenSoFar + L1 + L2);
+encode_tags2([], BytesSoFar, LenSoFar) ->
+ {BytesSoFar,LenSoFar}.
+
+encode_tags1([Tag1, Tag2| Trest], Acc)
+ when Tag1#tag.type == 'IMPLICIT' ->
+ encode_tags1([Tag1#tag{type=Tag2#tag.type,form=Tag2#tag.form}|Trest],Acc);
+encode_tags1([Tag1 | Trest], Acc) ->
+ encode_tags1(Trest, [Tag1|Acc]);
+encode_tags1([], Acc) ->
+ Acc. % the resulting tags are returned in reverse order
+
+encode_one_tag(Bin) when binary(Bin) ->
+ {Bin,size(Bin)};
+encode_one_tag(#tag{class=Class,number=No,type=Type, form = Form}) ->
+ NewForm = case Type of
+ 'EXPLICIT' ->
+ ?CONSTRUCTED;
+ _ ->
+ Form
+ end,
+ Bytes = encode_tag_val({Class,NewForm,No}),
+ {Bytes,size(Bytes)}.
+
+%%===============================================================================
+%% Change the tag (used when an implicit tagged type has a reference to something else)
+%% The constructed bit in the tag is taken from the tag to be replaced.
+%%
+%% change_tag(NewTag,[Tag,Buffer]) -> [NewTag,Buffer]
+%%===============================================================================
+
+%change_tag({NewClass,NewTagNr}, Buffer) ->
+% {{OldClass, OldForm, OldTagNo}, Buffer1, RemovedBytes} = decode_tag(lists:flatten(Buffer)),
+% [encode_tag_val({NewClass, OldForm, NewTagNr}) | Buffer1].
+
+
+
+
+
+
+
+%%===============================================================================
+%%
+%% This comment is valid for all the encode/decode functions
+%%
+%% C = Constraint -> typically {'ValueRange',LowerBound,UpperBound}
+%% used for PER-coding but not for BER-coding.
+%%
+%% Val = Value. If Val is an atom then it is a symbolic integer value
+%% (i.e the atom must be one of the names in the NamedNumberList).
+%% The NamedNumberList is used to translate the atom to an integer value
+%% before encoding.
+%%
+%%===============================================================================
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_open_type(Value) -> CompleteList
+%% Value = list of bytes of an already encoded value (the list must be flat)
+%% | binary
+
+%% This version does not consider Explicit tagging of the open type. It
+%% is only left because of backward compatibility.
+encode_open_type(Val) when list(Val) ->
+ {Val,size(list_to_binary(Val))};
+encode_open_type(Val) ->
+ {Val, size(Val)}.
+
+%%
+encode_open_type(Val, []) when list(Val) ->
+ {Val,size(list_to_binary(Val))};
+encode_open_type(Val,[]) ->
+ {Val, size(Val)};
+encode_open_type(Val, Tag) when list(Val) ->
+ encode_tags(Tag,Val,size(list_to_binary(Val)));
+encode_open_type(Val,Tag) ->
+ encode_tags(Tag,Val, size(Val)).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% decode_open_type(Buffer) -> Value
+%% Bytes = [byte] with BER encoded data
+%% Value = [byte] with decoded data (which must be decoded again as some type)
+%%
+decode_open_type(Bytes) ->
+ {_Tag, Len, _RemainingBuffer, RemovedBytes} = decode_tag_and_length(Bytes),
+ N = Len + RemovedBytes,
+ <<Val:N/binary, RemainingBytes/binary>> = Bytes,
+ {Val, RemainingBytes, Len + RemovedBytes}.
+
+decode_open_type(Bytes,ExplTag) ->
+ {Tag, Len, RemainingBuffer, RemovedBytes} = decode_tag_and_length(Bytes),
+ case {Tag,ExplTag} of
+ {{Class,Form,No},[#tag{class=Class,number=No,form=Form}]} ->
+ {_Tag2, Len2, _RemainingBuffer2, RemovedBytes2} = decode_tag_and_length(RemainingBuffer),
+ N = Len2 + RemovedBytes2,
+ <<_:RemovedBytes/unit:8,Val:N/binary,RemainingBytes/binary>> = Bytes,
+ {Val, RemainingBytes, N + RemovedBytes};
+ _ ->
+ N = Len + RemovedBytes,
+ <<Val:N/binary, RemainingBytes/binary>> = Bytes,
+ {Val, RemainingBytes, Len + RemovedBytes}
+ end.
+
+decode_open_type(ber_bin,Bytes,ExplTag) ->
+ decode_open_type(Bytes,ExplTag);
+decode_open_type(ber,Bytes,ExplTag) ->
+ {Val,RemBytes,Len}=decode_open_type(Bytes,ExplTag),
+ {binary_to_list(Val),RemBytes,Len}.
+
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+%% Boolean, ITU_T X.690 Chapter 8.2
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+
+%%===============================================================================
+%% encode_boolean(Integer, tag | notag) -> [octet list]
+%%===============================================================================
+
+encode_boolean({Name, Val}, DoTag) when atom(Name) ->
+ dotag(DoTag, ?N_BOOLEAN, encode_boolean(Val));
+encode_boolean(true,[]) ->
+ {[1,1,16#FF],3};
+encode_boolean(false,[]) ->
+ {[1,1,0],3};
+encode_boolean(Val, DoTag) ->
+ dotag(DoTag, ?N_BOOLEAN, encode_boolean(Val)).
+
+%% encode_boolean(Boolean) -> [Len, Boolean] = [1, $FF | 0]
+encode_boolean(true) -> {[16#FF],1};
+encode_boolean(false) -> {[0],1};
+encode_boolean(X) -> exit({error,{asn1, {encode_boolean, X}}}).
+
+
+%%===============================================================================
+%% decode_boolean(BuffList, HasTag, TotalLen) -> {true, Remain, RemovedBytes} |
+%% {false, Remain, RemovedBytes}
+%%===============================================================================
+
+decode_boolean(Buffer, Tags, OptOrMand) ->
+ NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_BOOLEAN}),
+ decode_boolean_notag(Buffer, NewTags, OptOrMand).
+
+decode_boolean_notag(Buffer, Tags, OptOrMand) ->
+ {RestTags, {FormLen,Buffer0,Rb0}} =
+ check_tags_i(Tags, Buffer, OptOrMand),
+ case FormLen of
+ {?CONSTRUCTED,Len} ->
+ {Buffer00,RestBytes} = split_list(Buffer0,Len),
+ {Val,Buffer1,Rb1} = decode_boolean_notag(Buffer00, RestTags, OptOrMand),
+ {Buffer2, Rb2} = restbytes2(RestBytes,Buffer1,noext),
+ {Val, Buffer2, Rb0+Rb1+Rb2};
+ {_,_} ->
+ decode_boolean2(Buffer0, Rb0)
+ end.
+
+decode_boolean2(<<0:8, Buffer/binary>>, RemovedBytes) ->
+ {false, Buffer, RemovedBytes + 1};
+decode_boolean2(<<_:8, Buffer/binary>>, RemovedBytes) ->
+ {true, Buffer, RemovedBytes + 1};
+decode_boolean2(Buffer, _) ->
+ exit({error,{asn1, {decode_boolean, Buffer}}}).
+
+
+
+
+%%===========================================================================
+%% Integer, ITU_T X.690 Chapter 8.3
+
+%% encode_integer(Constraint, Value, Tag) -> [octet list]
+%% encode_integer(Constraint, Name, NamedNumberList, Tag) -> [octet list]
+%% Value = INTEGER | {Name,INTEGER}
+%% Tag = tag | notag
+%%===========================================================================
+
+encode_integer(C, Val, []) when integer(Val) ->
+ {EncVal,Len}=encode_integer(C, Val),
+ dotag_universal(?N_INTEGER,EncVal,Len);
+encode_integer(C, Val, Tag) when integer(Val) ->
+ dotag(Tag, ?N_INTEGER, encode_integer(C, Val));
+encode_integer(C,{Name,Val},Tag) when atom(Name) ->
+ encode_integer(C,Val,Tag);
+encode_integer(_, Val, _) ->
+ exit({error,{asn1, {encode_integer, Val}}}).
+
+
+
+encode_integer(C, Val, NamedNumberList, Tag) when atom(Val) ->
+ case lists:keysearch(Val, 1, NamedNumberList) of
+ {value,{_, NewVal}} ->
+ dotag(Tag, ?N_INTEGER, encode_integer(C, NewVal));
+ _ ->
+ exit({error,{asn1, {encode_integer_namednumber, Val}}})
+ end;
+encode_integer(C,{_,Val},NamedNumberList,Tag) ->
+ encode_integer(C,Val,NamedNumberList,Tag);
+encode_integer(C, Val, _NamedNumberList, Tag) ->
+ dotag(Tag, ?N_INTEGER, encode_integer(C, Val)).
+
+
+
+
+encode_integer(_C, Val) ->
+ Bytes =
+ if
+ Val >= 0 ->
+ encode_integer_pos(Val, []);
+ true ->
+ encode_integer_neg(Val, [])
+ end,
+ {Bytes,length(Bytes)}.
+
+encode_integer_pos(0, L=[B|_Acc]) when B < 128 ->
+ L;
+encode_integer_pos(N, Acc) ->
+ encode_integer_pos((N bsr 8), [N band 16#ff| Acc]).
+
+encode_integer_neg(-1, L=[B1|_T]) when B1 > 127 ->
+ L;
+encode_integer_neg(N, Acc) ->
+ encode_integer_neg(N bsr 8, [N band 16#ff|Acc]).
+
+%%===============================================================================
+%% decode integer
+%% (Buffer, Range, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
+%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
+%%===============================================================================
+
+
+decode_integer(Buffer, Range, Tags, OptOrMand) ->
+ NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_INTEGER}),
+ decode_integer_notag(Buffer, Range, [], NewTags, OptOrMand).
+
+decode_integer(Buffer, Range, NamedNumberList, Tags, OptOrMand) ->
+ NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_INTEGER}),
+ decode_integer_notag(Buffer, Range, NamedNumberList, NewTags, OptOrMand).
+
+decode_integer_notag(Buffer, Range, NamedNumberList, NewTags, OptOrMand) ->
+ {RestTags, {FormLen, Buffer0, Rb0}} =
+ check_tags_i(NewTags, Buffer, OptOrMand),
+% Result = {Val, Buffer2, RemovedBytes} =
+ case FormLen of
+ {?CONSTRUCTED,Len} ->
+ {Buffer00, RestBytes} = split_list(Buffer0,Len),
+ {Val01, Buffer01, Rb01} =
+ decode_integer_notag(Buffer00, Range, NamedNumberList,
+ RestTags, OptOrMand),
+ {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
+ {Val01, Buffer02, Rb0+Rb01+Rb02};
+ {_, Len} ->
+ Result =
+ decode_integer2(Len,Buffer0,Rb0+Len),
+ Result2 = check_integer_constraint(Result,Range),
+ resolve_named_value(Result2,NamedNumberList)
+ end.
+
+resolve_named_value(Result={Val,Buffer,RemBytes},NamedNumberList) ->
+ case NamedNumberList of
+ [] -> Result;
+ _ ->
+ NewVal = case lists:keysearch(Val, 2, NamedNumberList) of
+ {value,{NamedVal, _}} ->
+ NamedVal;
+ _ ->
+ Val
+ end,
+ {NewVal, Buffer, RemBytes}
+ end.
+
+check_integer_constraint(Result={Val, _Buffer,_},Range) ->
+ case Range of
+ [] -> % No length constraint
+ Result;
+ {Lb,Ub} when Val >= Lb, Ub >= Val -> % variable length constraint
+ Result;
+ Val -> % fixed value constraint
+ Result;
+ {_,_} ->
+ exit({error,{asn1,{integer_range,Range,Val}}});
+ SingleValue when integer(SingleValue) ->
+ exit({error,{asn1,{integer_range,Range,Val}}});
+ _ -> % some strange constraint that we don't support yet
+ Result
+ end.
+
+%%============================================================================
+%% Enumerated value, ITU_T X.690 Chapter 8.4
+
+%% encode enumerated value
+%%============================================================================
+encode_enumerated(Val, []) when integer(Val)->
+ {EncVal,Len} = encode_integer(false,Val),
+ dotag_universal(?N_ENUMERATED,EncVal,Len);
+encode_enumerated(Val, DoTag) when integer(Val)->
+ dotag(DoTag, ?N_ENUMERATED, encode_integer(false,Val));
+encode_enumerated({Name,Val}, DoTag) when atom(Name) ->
+ encode_enumerated(Val, DoTag).
+
+%% The encode_enumerated functions below this line can be removed when the
+%% new code generation is stable. (the functions might have to be kept here
+%% a while longer for compatibility reasons)
+
+encode_enumerated(C, Val, {NamedNumberList,ExtList}, DoTag) when atom(Val) ->
+ case catch encode_enumerated(C, Val, NamedNumberList, DoTag) of
+ {'EXIT',_} -> encode_enumerated(C, Val, ExtList, DoTag);
+ Result -> Result
+ end;
+
+encode_enumerated(C, Val, NamedNumberList, DoTag) when atom(Val) ->
+ case lists:keysearch(Val, 1, NamedNumberList) of
+ {value, {_, NewVal}} when DoTag == []->
+ {EncVal,Len} = encode_integer(C,NewVal),
+ dotag_universal(?N_ENUMERATED,EncVal,Len);
+ {value, {_, NewVal}} ->
+ dotag(DoTag, ?N_ENUMERATED, encode_integer(C, NewVal));
+ _ ->
+ exit({error,{asn1, {enumerated_not_in_range, Val}}})
+ end;
+
+encode_enumerated(C, {asn1_enum, Val}, {_,_}, DoTag) when integer(Val) ->
+ dotag(DoTag, ?N_ENUMERATED, encode_integer(C,Val));
+
+encode_enumerated(C, {Name,Val}, NamedNumberList, DoTag) when atom(Name) ->
+ encode_enumerated(C, Val, NamedNumberList, DoTag);
+
+encode_enumerated(_, Val, _, _) ->
+ exit({error,{asn1, {enumerated_not_namednumber, Val}}}).
+
+
+
+%%============================================================================
+%% decode enumerated value
+%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) ->
+%% {Value, RemainingBuffer, RemovedBytes}
+%%===========================================================================
+decode_enumerated(Buffer, Range, NamedNumberList, Tags, OptOrMand) ->
+ NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_ENUMERATED}),
+ decode_enumerated_notag(Buffer, Range, NamedNumberList,
+ NewTags, OptOrMand).
+
+decode_enumerated_notag(Buffer, Range, NNList = {NamedNumberList,ExtList}, Tags, OptOrMand) ->
+ {RestTags, {FormLen, Buffer0, Rb0}} =
+ check_tags_i(Tags, Buffer, OptOrMand),
+
+ case FormLen of
+ {?CONSTRUCTED,Len} ->
+ {Buffer00,RestBytes} = split_list(Buffer0,Len),
+ {Val01, Buffer01, Rb01} =
+ decode_enumerated_notag(Buffer00, Range, NNList, RestTags, OptOrMand),
+ {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
+ {Val01, Buffer02, Rb0+Rb01+Rb02};
+ {_,Len} ->
+ {Val01, Buffer01, Rb01} =
+ decode_integer2(Len, Buffer0, Rb0+Len),
+ case decode_enumerated1(Val01, NamedNumberList) of
+ {asn1_enum,Val01} ->
+ {decode_enumerated1(Val01,ExtList), Buffer01, Rb01};
+ Result01 ->
+ {Result01, Buffer01, Rb01}
+ end
+ end;
+
+decode_enumerated_notag(Buffer, Range, NNList, Tags, OptOrMand) ->
+ {RestTags, {FormLen, Buffer0, Rb0}} =
+ check_tags_i(Tags, Buffer, OptOrMand),
+
+ case FormLen of
+ {?CONSTRUCTED,Len} ->
+ {Buffer00,RestBytes} = split_list(Buffer0,Len),
+ {Val01, Buffer01, Rb01} =
+ decode_enumerated_notag(Buffer00, Range, NNList, RestTags, OptOrMand),
+ {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
+ {Val01, Buffer02, Rb0+Rb01+Rb02};
+ {_,Len} ->
+ {Val01, Buffer02, Rb02} =
+ decode_integer2(Len, Buffer0, Rb0+Len),
+ case decode_enumerated1(Val01, NNList) of
+ {asn1_enum,_} ->
+ exit({error,{asn1, {illegal_enumerated, Val01}}});
+ Result01 ->
+ {Result01, Buffer02, Rb02}
+ end
+ end.
+
+decode_enumerated1(Val, NamedNumberList) ->
+ %% it must be a named integer
+ case lists:keysearch(Val, 2, NamedNumberList) of
+ {value,{NamedVal, _}} ->
+ NamedVal;
+ _ ->
+ {asn1_enum,Val}
+ end.
+
+
+%%============================================================================
+%%
+%% Real value, ITU_T X.690 Chapter 8.5
+%%============================================================================
+%%
+%% encode real value
+%%============================================================================
+
+%% only base 2 internally so far!!
+encode_real(0, DoTag) ->
+ dotag(DoTag, ?N_REAL, {[],0});
+encode_real('PLUS-INFINITY', DoTag) ->
+ dotag(DoTag, ?N_REAL, {[64],1});
+encode_real('MINUS-INFINITY', DoTag) ->
+ dotag(DoTag, ?N_REAL, {[65],1});
+encode_real(Val, DoTag) when tuple(Val)->
+ dotag(DoTag, ?N_REAL, encode_real(Val)).
+
+%%%%%%%%%%%%%%
+%% not optimal efficient..
+%% only base 2 of Mantissa encoding!
+%% only base 2 of ExpBase encoding!
+encode_real({Man, Base, Exp}) ->
+%% io:format("Mantissa: ~w Base: ~w, Exp: ~w~n",[Man, Base, Exp]),
+
+ OctExp = if Exp >= 0 -> list_to_binary(encode_integer_pos(Exp, []));
+ true -> list_to_binary(encode_integer_neg(Exp, []))
+ end,
+%% ok = io:format("OctExp: ~w~n",[OctExp]),
+ SignBit = if Man > 0 -> 0; % bit 7 is pos or neg, no Zeroval
+ true -> 1
+ end,
+%% ok = io:format("SignBitMask: ~w~n",[SignBitMask]),
+ InBase = if Base =:= 2 -> 0; % bit 6,5: only base 2 this far!
+ true ->
+ exit({error,{asn1, {encode_real_non_supported_encodeing, Base}}})
+ end,
+ SFactor = 0, % bit 4,3: no scaling since only base 2
+ OctExpLen = size(OctExp),
+ if OctExpLen > 255 ->
+ exit({error,{asn1, {to_big_exp_in_encode_real, OctExpLen}}});
+ true -> true %% make real assert later..
+ end,
+ {LenCode, EOctets} = case OctExpLen of % bit 2,1
+ 1 -> {0, OctExp};
+ 2 -> {1, OctExp};
+ 3 -> {2, OctExp};
+ _ -> {3, <<OctExpLen, OctExp/binary>>}
+ end,
+ FirstOctet = <<1:1,SignBit:1,InBase:2,SFactor:2,LenCode:2>>,
+ OctMantissa = if Man > 0 -> list_to_binary(minimum_octets(Man));
+ true -> list_to_binary(minimum_octets(-(Man))) % signbit keeps track of sign
+ end,
+ %% ok = io:format("LenMask: ~w EOctets: ~w~nFirstOctet: ~w OctMantissa: ~w OctExpLen: ~w~n", [LenMask, EOctets, FirstOctet, OctMantissa, OctExpLen]),
+ Bin = <<FirstOctet/binary, EOctets/binary, OctMantissa/binary>>,
+ {Bin, size(Bin)}.
+
+
+%encode_real({Man, Base, Exp}) ->
+%% io:format("Mantissa: ~w Base: ~w, Exp: ~w~n",[Man, Base, Exp]),
+
+% OctExp = if Exp >= 0 -> encode_integer_pos(Exp, []);
+% true -> encode_integer_neg(Exp, [])
+% end,
+%% ok = io:format("OctExp: ~w~n",[OctExp]),
+% SignBitMask = if Man > 0 -> 2#00000000; % bit 7 is pos or neg, no Zeroval
+% true -> 2#01000000
+% end,
+%% ok = io:format("SignBitMask: ~w~n",[SignBitMask]),
+% InternalBaseMask = if Base =:= 2 -> 2#00000000; % bit 6,5: only base 2 this far!
+% true ->
+% exit({error,{asn1, {encode_real_non_supported_encodeing, Base}}})
+% end,
+% ScalingFactorMask =2#00000000, % bit 4,3: no scaling since only base 2
+% OctExpLen = length(OctExp),
+% if OctExpLen > 255 ->
+% exit({error,{asn1, {to_big_exp_in_encode_real, OctExpLen}}});
+% true -> true %% make real assert later..
+% end,
+% {LenMask, EOctets} = case OctExpLen of % bit 2,1
+% 1 -> {0, OctExp};
+% 2 -> {1, OctExp};
+% 3 -> {2, OctExp};
+% _ -> {3, [OctExpLen, OctExp]}
+% end,
+% FirstOctet = (SignBitMask bor InternalBaseMask bor
+% ScalingFactorMask bor LenMask bor
+% 2#10000000), % bit set for binary mantissa encoding!
+% OctMantissa = if Man > 0 -> minimum_octets(Man);
+% true -> minimum_octets(-(Man)) % signbit keeps track of sign
+% end,
+%% ok = io:format("LenMask: ~w EOctets: ~w~nFirstOctet: ~w OctMantissa: ~w OctExpLen: ~w~n", [LenMask, EOctets, FirstOctet, OctMantissa, OctExpLen]),
+% {[FirstOctet, EOctets, OctMantissa],
+% length(OctMantissa) +
+% (if OctExpLen > 3 ->
+% OctExpLen + 2;
+% true ->
+% OctExpLen + 1
+% end)
+% }.
+
+
+%%============================================================================
+%% decode real value
+%%
+%% decode_real([OctetBufferList], tuple|value, tag|notag) ->
+%% {{Mantissa, Base, Exp} | realval | PLUS-INFINITY | MINUS-INFINITY | 0,
+%% RestBuff}
+%%
+%% only for base 2 decoding sofar!!
+%%============================================================================
+
+decode_real(Buffer, Form, Tags, OptOrMand) ->
+ NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_REAL}),
+ decode_real_notag(Buffer, Form, NewTags, OptOrMand).
+
+decode_real_notag(Buffer, Form, Tags, OptOrMand) ->
+ {RestTags, {FormLen, Buffer0, Rb0}} =
+ check_tags_i(Tags, Buffer, OptOrMand),
+
+ case FormLen of
+ {?CONSTRUCTED,Len} ->
+ {Buffer00,RestBytes} = split_list(Buffer0,Len),
+ {Val01, Buffer01, Rb01} =
+ decode_real_notag(Buffer00, Form, RestTags, OptOrMand),
+ {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
+ {Val01, Buffer02, Rb0+Rb01+Rb02};
+ {_,Len} ->
+ decode_real2(Buffer0, Form, Len, Rb0)
+ end.
+
+decode_real2(Buffer0, Form, Len, RemBytes1) ->
+ <<First, Buffer2/binary>> = Buffer0,
+ if
+ First =:= 2#01000000 -> {'PLUS-INFINITY', Buffer2};
+ First =:= 2#01000001 -> {'MINUS-INFINITY', Buffer2};
+ First =:= 2#00000000 -> {0, Buffer2};
+ true ->
+ %% have some check here to verify only supported bases (2)
+ <<_B7:1,B6:1,B5_4:2,B3_2:2,B1_0:2>> = <<First>>,
+ Sign = B6,
+ Base =
+ case B5_4 of
+ 0 -> 2; % base 2, only one so far
+ _ -> exit({error,{asn1, {non_supported_base, First}}})
+ end,
+% ScalingFactor =
+ case B3_2 of
+ 0 -> 0; % no scaling so far
+ _ -> exit({error,{asn1, {non_supported_scaling, First}}})
+ end,
+ % ok = io:format("Buffer2: ~w~n",[Buffer2]),
+ {FirstLen, {Exp, Buffer3}, RemBytes2} =
+ case B1_0 of
+ 0 -> {2, decode_integer2(1, Buffer2, RemBytes1), RemBytes1+1};
+ 1 -> {3, decode_integer2(2, Buffer2, RemBytes1), RemBytes1+2};
+ 2 -> {4, decode_integer2(3, Buffer2, RemBytes1), RemBytes1+3};
+ 3 ->
+ <<ExpLen1,RestBuffer/binary>> = Buffer2,
+ { ExpLen1 + 2,
+ decode_integer2(ExpLen1, RestBuffer, RemBytes1),
+ RemBytes1+ExpLen1}
+ end,
+ % io:format("FirstLen: ~w, Exp: ~w, Buffer3: ~w ~n",
+ % [FirstLen, Exp, Buffer3]),
+ Length = Len - FirstLen,
+ <<LongInt:Length/unit:8,RestBuff/binary>> = Buffer3,
+ {{Mantissa, Buffer4}, RemBytes3} =
+ if Sign =:= 0 ->
+ % io:format("sign plus~n"),
+ {{LongInt, RestBuff}, 1 + Length};
+ true ->
+ % io:format("sign minus~n"),
+ {{-LongInt, RestBuff}, 1 + Length}
+ end,
+ % io:format("Form: ~w~n",[Form]),
+ case Form of
+ tuple ->
+ {Val,Buf,_RemB} = Exp,
+ {{Mantissa, Base, {Val,Buf}}, Buffer4, RemBytes2+RemBytes3};
+ _value ->
+ comming
+ end
+ end.
+
+
+%%============================================================================
+%% Bitstring value, ITU_T X.690 Chapter 8.6
+%%
+%% encode bitstring value
+%%
+%% bitstring NamedBitList
+%% Val can be of:
+%% - [identifiers] where only named identifers are set to one,
+%% the Constraint must then have some information of the
+%% bitlength.
+%% - [list of ones and zeroes] all bits
+%% - integer value representing the bitlist
+%% C is constrint Len, only valid when identifiers
+%%============================================================================
+
+encode_bit_string(C,Bin={Unused,BinBits},NamedBitList,DoTag) when integer(Unused), binary(BinBits) ->
+ encode_bin_bit_string(C,Bin,NamedBitList,DoTag);
+encode_bit_string(C, [FirstVal | RestVal], NamedBitList, DoTag) when atom(FirstVal) ->
+ encode_bit_string_named(C, [FirstVal | RestVal], NamedBitList, DoTag);
+
+encode_bit_string(C, [{bit,X} | RestVal], NamedBitList, DoTag) ->
+ encode_bit_string_named(C, [{bit,X} | RestVal], NamedBitList, DoTag);
+
+encode_bit_string(C, [FirstVal| RestVal], NamedBitList, DoTag) when integer(FirstVal) ->
+ encode_bit_string_bits(C, [FirstVal | RestVal], NamedBitList, DoTag);
+
+encode_bit_string(_, 0, _, []) ->
+ {[?N_BIT_STRING,1,0],3};
+
+encode_bit_string(_, 0, _, DoTag) ->
+ dotag(DoTag, ?N_BIT_STRING, {<<0>>,1});
+
+encode_bit_string(_, [], _, []) ->
+ {[?N_BIT_STRING,1,0],3};
+
+encode_bit_string(_, [], _, DoTag) ->
+ dotag(DoTag, ?N_BIT_STRING, {<<0>>,1});
+
+encode_bit_string(C, IntegerVal, NamedBitList, DoTag) when integer(IntegerVal) ->
+ BitListVal = int_to_bitlist(IntegerVal),
+ encode_bit_string_bits(C, BitListVal, NamedBitList, DoTag);
+
+encode_bit_string(C, {Name,BitList}, NamedBitList, DoTag) when atom(Name) ->
+ encode_bit_string(C, BitList, NamedBitList, DoTag).
+
+
+
+int_to_bitlist(0) ->
+ [];
+int_to_bitlist(Int) when integer(Int), Int >= 0 ->
+ [Int band 1 | int_to_bitlist(Int bsr 1)].
+
+
+%%=================================================================
+%% Encode BIT STRING of the form {Unused,BinBits}.
+%% Unused is the number of unused bits in the last byte in BinBits
+%% and BinBits is a binary representing the BIT STRING.
+%%=================================================================
+encode_bin_bit_string(C,{Unused,BinBits},_NamedBitList,DoTag)->
+ case get_constraint(C,'SizeConstraint') of
+ no ->
+ remove_unused_then_dotag(DoTag,?N_BIT_STRING,Unused,BinBits);
+ {_Min,Max} ->
+ BBLen = (size(BinBits)*8)-Unused,
+ if
+ BBLen > Max ->
+ exit({error,{asn1,
+ {bitstring_length,
+ {{was,BBLen},{maximum,Max}}}}});
+ true ->
+ remove_unused_then_dotag(DoTag,?N_BIT_STRING,
+ Unused,BinBits)
+ end;
+ Size ->
+ case ((size(BinBits)*8)-Unused) of
+ BBSize when BBSize =< Size ->
+ remove_unused_then_dotag(DoTag,?N_BIT_STRING,
+ Unused,BinBits);
+ BBSize ->
+ exit({error,{asn1,
+ {bitstring_length,
+ {{was,BBSize},{should_be,Size}}}}})
+ end
+ end.
+
+remove_unused_then_dotag(DoTag,StringType,Unused,BinBits) ->
+ case Unused of
+ 0 when (size(BinBits) == 0),DoTag==[] ->
+ %% time optimization of next case
+ {[StringType,1,0],3};
+ 0 when (size(BinBits) == 0) ->
+ dotag(DoTag,StringType,{<<0>>,1});
+ 0 when DoTag==[]-> % time optimization of next case
+ dotag_universal(StringType,[Unused|BinBits],size(BinBits)+1);
+% {LenEnc,Len} = encode_legth(size(BinBits)+1),
+% {[StringType,LenEnc,[Unused|BinBits]],size(BinBits)+1+Len+1};
+ 0 ->
+ dotag(DoTag,StringType,<<Unused,BinBits/binary>>);
+ Num when DoTag == [] -> % time optimization of next case
+ N = (size(BinBits)-1),
+ <<BBits:N/binary,LastByte>> = BinBits,
+ dotag_universal(StringType,
+ [Unused,BBits,(LastByte bsr Num) bsl Num],
+ size(BinBits)+1);
+% {LenEnc,Len} = encode_legth(size(BinBits)+1),
+% {[StringType,LenEnc,[Unused,BBits,(LastByte bsr Num) bsl Num],
+% 1+Len+size(BinBits)+1};
+ Num ->
+ N = (size(BinBits)-1),
+ <<BBits:N/binary,LastByte>> = BinBits,
+ dotag(DoTag,StringType,{[Unused,binary_to_list(BBits) ++
+ [(LastByte bsr Num) bsl Num]],
+ 1+size(BinBits)})
+ end.
+
+
+%%=================================================================
+%% Encode named bits
+%%=================================================================
+
+encode_bit_string_named(C, [FirstVal | RestVal], NamedBitList, DoTag) ->
+ {Len,Unused,OctetList} =
+ case get_constraint(C,'SizeConstraint') of
+ no ->
+ ToSetPos = get_all_bitposes([FirstVal | RestVal],
+ NamedBitList, []),
+ BitList = make_and_set_list(lists:max(ToSetPos)+1,
+ ToSetPos, 0),
+ encode_bitstring(BitList);
+ {_Min,Max} ->
+ ToSetPos = get_all_bitposes([FirstVal | RestVal],
+ NamedBitList, []),
+ BitList = make_and_set_list(Max, ToSetPos, 0),
+ encode_bitstring(BitList);
+ Size ->
+ ToSetPos = get_all_bitposes([FirstVal | RestVal],
+ NamedBitList, []),
+ BitList = make_and_set_list(Size, ToSetPos, 0),
+ encode_bitstring(BitList)
+ end,
+ case DoTag of
+ [] ->
+ dotag_universal(?N_BIT_STRING,[Unused|OctetList],Len+1);
+% {EncLen,LenLen} = encode_length(Len+1),
+% {[?N_BIT_STRING,EncLen,Unused,OctetList],1+LenLen+Len+1};
+ _ ->
+ dotag(DoTag, ?N_BIT_STRING, {[Unused|OctetList],Len+1})
+ end.
+
+
+%%----------------------------------------
+%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
+%% [sorted_list_of_bitpositions_to_set]
+%%----------------------------------------
+
+get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
+ get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
+get_all_bitposes([Val | Rest], NamedBitList, Ack) when atom(Val) ->
+ case lists:keysearch(Val, 1, NamedBitList) of
+ {value, {_ValName, ValPos}} ->
+ get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
+ _ ->
+ exit({error,{asn1, {bitstring_namedbit, Val}}})
+ end;
+get_all_bitposes([], _NamedBitList, Ack) ->
+ lists:sort(Ack).
+
+
+%%----------------------------------------
+%% make_and_set_list(Len of list to return, [list of positions to set to 1])->
+%% returns list of Len length, with all in SetPos set.
+%% in positioning in list the first element is 0, the second 1 etc.., but
+%% Len will make a list of length Len, not Len + 1.
+%% BitList = make_and_set_list(C, ToSetPos, 0),
+%%----------------------------------------
+
+make_and_set_list(0, [], _) -> [];
+make_and_set_list(0, _, _) ->
+ exit({error,{asn1,bitstring_sizeconstraint}});
+make_and_set_list(Len, [XPos|SetPos], XPos) ->
+ [1 | make_and_set_list(Len - 1, SetPos, XPos + 1)];
+make_and_set_list(Len, [Pos|SetPos], XPos) ->
+ [0 | make_and_set_list(Len - 1, [Pos | SetPos], XPos + 1)];
+make_and_set_list(Len, [], XPos) ->
+ [0 | make_and_set_list(Len - 1, [], XPos + 1)].
+
+
+
+
+
+
+%%=================================================================
+%% Encode bit string for lists of ones and zeroes
+%%=================================================================
+encode_bit_string_bits(C, BitListVal, _NamedBitList, DoTag) when list(BitListVal) ->
+ {Len,Unused,OctetList} =
+ case get_constraint(C,'SizeConstraint') of
+ no ->
+ encode_bitstring(BitListVal);
+ Constr={Min,Max} when integer(Min),integer(Max) ->
+ encode_constr_bit_str_bits(Constr,BitListVal,DoTag);
+ {Constr={_,_},[]} ->
+ %% constraint with extension mark
+ encode_constr_bit_str_bits(Constr,BitListVal,DoTag);
+ Constr={{_,_},{_,_}} ->%{{Min1,Max1},{Min2,Max2}}
+ %% constraint with extension mark
+ encode_constr_bit_str_bits(Constr,BitListVal,DoTag);
+ Size ->
+ case length(BitListVal) of
+ BitSize when BitSize == Size ->
+ encode_bitstring(BitListVal);
+ BitSize when BitSize < Size ->
+ PaddedList =
+ pad_bit_list(Size-BitSize,BitListVal),
+ encode_bitstring(PaddedList);
+ BitSize ->
+ exit({error,
+ {asn1,
+ {bitstring_length,
+ {{was,BitSize},
+ {should_be,Size}}}}})
+ end
+ end,
+ %%add unused byte to the Len
+ case DoTag of
+ [] ->
+ dotag_universal(?N_BIT_STRING,[Unused|OctetList],Len+1);
+% {EncLen,LenLen}=encode_length(Len+1),
+% {[?N_BIT_STRING,EncLen,Unused|OctetList],1+LenLen+Len+1};
+ _ ->
+ dotag(DoTag, ?N_BIT_STRING,
+ {[Unused | OctetList],Len+1})
+ end.
+
+
+encode_constr_bit_str_bits({_Min,Max},BitListVal,_DoTag) ->
+ BitLen = length(BitListVal),
+ if
+ BitLen > Max ->
+ exit({error,{asn1,{bitstring_length,{{was,BitLen},
+ {maximum,Max}}}}});
+ true ->
+ encode_bitstring(BitListVal)
+ end;
+encode_constr_bit_str_bits({{_Min1,Max1},{Min2,Max2}},BitListVal,_DoTag) ->
+ BitLen = length(BitListVal),
+ case BitLen of
+ Len when Len > Max2 ->
+ exit({error,{asn1,{bitstring_length,{{was,BitLen},
+ {maximum,Max2}}}}});
+ Len when Len > Max1, Len < Min2 ->
+ exit({error,{asn1,{bitstring_length,{{was,BitLen},
+ {not_allowed_interval,
+ Max1,Min2}}}}});
+ _ ->
+ encode_bitstring(BitListVal)
+ end.
+
+%% returns a list of length Size + length(BitListVal), with BitListVal
+%% as the most significant elements followed by padded zero elements
+pad_bit_list(Size,BitListVal) ->
+ Tail = lists:duplicate(Size,0),
+ lists:append(BitListVal,Tail).
+
+%%=================================================================
+%% Do the actual encoding
+%% ([bitlist]) -> {ListLen, UnusedBits, OctetList}
+%%=================================================================
+
+encode_bitstring([B8, B7, B6, B5, B4, B3, B2, B1 | Rest]) ->
+ Val = (B8 bsl 7) bor (B7 bsl 6) bor (B6 bsl 5) bor (B5 bsl 4) bor
+ (B4 bsl 3) bor (B3 bsl 2) bor (B2 bsl 1) bor B1,
+ encode_bitstring(Rest, [Val], 1);
+encode_bitstring(Val) ->
+ {Unused, Octet} = unused_bitlist(Val, 7, 0),
+ {1, Unused, [Octet]}.
+
+encode_bitstring([B8, B7, B6, B5, B4, B3, B2, B1 | Rest], Ack, Len) ->
+ Val = (B8 bsl 7) bor (B7 bsl 6) bor (B6 bsl 5) bor (B5 bsl 4) bor
+ (B4 bsl 3) bor (B3 bsl 2) bor (B2 bsl 1) bor B1,
+ encode_bitstring(Rest, [Ack | [Val]], Len + 1);
+%%even multiple of 8 bits..
+encode_bitstring([], Ack, Len) ->
+ {Len, 0, Ack};
+%% unused bits in last octet
+encode_bitstring(Rest, Ack, Len) ->
+% io:format("uneven ~w ~w ~w~n",[Rest, Ack, Len]),
+ {Unused, Val} = unused_bitlist(Rest, 7, 0),
+ {Len + 1, Unused, [Ack | [Val]]}.
+
+%%%%%%%%%%%%%%%%%%
+%% unused_bitlist([list of ones and zeros <= 7], 7, []) ->
+%% {Unused bits, Last octet with bits moved to right}
+unused_bitlist([], Trail, Ack) ->
+ {Trail + 1, Ack};
+unused_bitlist([Bit | Rest], Trail, Ack) ->
+%% io:format("trail Bit: ~w Rest: ~w Trail: ~w Ack:~w~n",[Bit, Rest, Trail, Ack]),
+ unused_bitlist(Rest, Trail - 1, (Bit bsl Trail) bor Ack).
+
+
+%%============================================================================
+%% decode bitstring value
+%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
+%%============================================================================
+
+decode_compact_bit_string(Buffer, Range, NamedNumberList, Tags, LenIn, OptOrMand) ->
+% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_BIT_STRING}),
+ decode_restricted_string(Buffer, Range, ?N_BIT_STRING, Tags, LenIn,
+ NamedNumberList, OptOrMand,bin).
+
+decode_bit_string(Buffer, Range, NamedNumberList, Tags, LenIn, OptOrMand) ->
+% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_BIT_STRING}),
+ decode_restricted_string(Buffer, Range, ?N_BIT_STRING, Tags, LenIn,
+ NamedNumberList, OptOrMand,old).
+
+
+decode_bit_string2(1,<<0 ,Buffer/binary>>,_NamedNumberList,RemovedBytes,BinOrOld) ->
+ case BinOrOld of
+ bin ->
+ {{0,<<>>},Buffer,RemovedBytes};
+ _ ->
+ {[], Buffer, RemovedBytes}
+ end;
+decode_bit_string2(Len,<<Unused,Buffer/binary>>,NamedNumberList,
+ RemovedBytes,BinOrOld) ->
+ L = Len - 1,
+ <<Bits:L/binary,BufferTail/binary>> = Buffer,
+ case NamedNumberList of
+ [] ->
+ case BinOrOld of
+ bin ->
+ {{Unused,Bits},BufferTail,RemovedBytes};
+ _ ->
+ BitString = decode_bitstring2(L, Unused, Buffer),
+ {BitString,BufferTail, RemovedBytes}
+ end;
+ _ ->
+ BitString = decode_bitstring2(L, Unused, Buffer),
+ {decode_bitstring_NNL(BitString,NamedNumberList),
+ BufferTail,
+ RemovedBytes}
+ end.
+
+%%----------------------------------------
+%% Decode the in buffer to bits
+%%----------------------------------------
+decode_bitstring2(1,Unused,<<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,_/binary>>) ->
+ lists:sublist([B7,B6,B5,B4,B3,B2,B1,B0],8-Unused);
+decode_bitstring2(Len, Unused,
+ <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Buffer/binary>>) ->
+ [B7, B6, B5, B4, B3, B2, B1, B0 |
+ decode_bitstring2(Len - 1, Unused, Buffer)].
+
+%%decode_bitstring2(1, Unused, Buffer) ->
+%% make_bits_of_int(hd(Buffer), 128, 8-Unused);
+%%decode_bitstring2(Len, Unused, [BitVal | Buffer]) ->
+%% [B7, B6, B5, B4, B3, B2, B1, B0] = make_bits_of_int(BitVal, 128, 8),
+%% [B7, B6, B5, B4, B3, B2, B1, B0 |
+%% decode_bitstring2(Len - 1, Unused, Buffer)].
+
+
+%%make_bits_of_int(_, _, 0) ->
+%% [];
+%%make_bits_of_int(BitVal, MaskVal, Unused) when Unused > 0 ->
+%% X = case MaskVal band BitVal of
+%% 0 -> 0 ;
+%% _ -> 1
+%% end,
+%% [X | make_bits_of_int(BitVal, MaskVal bsr 1, Unused - 1)].
+
+
+
+%%----------------------------------------
+%% Decode the bitlist to names
+%%----------------------------------------
+
+
+decode_bitstring_NNL(BitList,NamedNumberList) ->
+ decode_bitstring_NNL(BitList,NamedNumberList,0,[]).
+
+
+decode_bitstring_NNL([],_,_No,Result) ->
+ lists:reverse(Result);
+
+decode_bitstring_NNL([B|BitList],[{Name,No}|NamedNumberList],No,Result) ->
+ if
+ B == 0 ->
+ decode_bitstring_NNL(BitList,NamedNumberList,No+1,Result);
+ true ->
+ decode_bitstring_NNL(BitList,NamedNumberList,No+1,[Name|Result])
+ end;
+decode_bitstring_NNL([1|BitList],NamedNumberList,No,Result) ->
+ decode_bitstring_NNL(BitList,NamedNumberList,No+1,[{bit,No}|Result]);
+decode_bitstring_NNL([0|BitList],NamedNumberList,No,Result) ->
+ decode_bitstring_NNL(BitList,NamedNumberList,No+1,Result).
+
+
+%%============================================================================
+%% Octet string, ITU_T X.690 Chapter 8.7
+%%
+%% encode octet string
+%% The OctetList must be a flat list of integers in the range 0..255
+%% the function does not check this because it takes to much time
+%%============================================================================
+encode_octet_string(_C, OctetList, []) when binary(OctetList) ->
+ dotag_universal(?N_OCTET_STRING,OctetList,size(OctetList));
+encode_octet_string(_C, OctetList, DoTag) when binary(OctetList) ->
+ dotag(DoTag, ?N_OCTET_STRING, {OctetList,size(OctetList)});
+encode_octet_string(_C, OctetList, DoTag) when list(OctetList) ->
+ case length(OctetList) of
+ Len when DoTag == [] ->
+ dotag_universal(?N_OCTET_STRING,OctetList,Len);
+ Len ->
+ dotag(DoTag, ?N_OCTET_STRING, {OctetList,Len})
+ end;
+% encode_octet_string(C, OctetList, DoTag) when list(OctetList) ->
+% dotag(DoTag, ?N_OCTET_STRING, {OctetList,length(OctetList)});
+encode_octet_string(C, {Name,OctetList}, DoTag) when atom(Name) ->
+ encode_octet_string(C, OctetList, DoTag).
+
+
+%%============================================================================
+%% decode octet string
+%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
+%%
+%% Octet string is decoded as a restricted string
+%%============================================================================
+decode_octet_string(Buffer, Range, Tags, TotalLen, OptOrMand) ->
+% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_OCTET_STRING}),
+ decode_restricted_string(Buffer, Range, ?N_OCTET_STRING,
+ Tags, TotalLen, [], OptOrMand,old).
+
+%%============================================================================
+%% Null value, ITU_T X.690 Chapter 8.8
+%%
+%% encode NULL value
+%%============================================================================
+
+encode_null(_, []) ->
+ {[?N_NULL,0],2};
+encode_null(_, DoTag) ->
+ dotag(DoTag, ?N_NULL, {[],0}).
+
+%%============================================================================
+%% decode NULL value
+%% (Buffer, HasTag, TotalLen) -> {NULL, Remain, RemovedBytes}
+%%============================================================================
+decode_null(Buffer, Tags, OptOrMand) ->
+ NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_NULL}),
+ decode_null_notag(Buffer, NewTags, OptOrMand).
+
+decode_null_notag(Buffer, Tags, OptOrMand) ->
+ {RestTags, {FormLen, Buffer0, Rb0}} =
+ check_tags_i(Tags, Buffer, OptOrMand),
+
+ case FormLen of
+ {?CONSTRUCTED,Len} ->
+ {_Buffer00,RestBytes} = split_list(Buffer0,Len),
+ {Val01, Buffer01, Rb01} = decode_null_notag(Buffer0, RestTags,
+ OptOrMand),
+ {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
+ {Val01, Buffer02, Rb0+Rb01+Rb02};
+ {_,0} ->
+ {'NULL', Buffer0, Rb0};
+ {_,Len} ->
+ exit({error,{asn1,{invalid_length,'NULL',Len}}})
+ end.
+
+
+%%============================================================================
+%% Object identifier, ITU_T X.690 Chapter 8.19
+%%
+%% encode Object Identifier value
+%%============================================================================
+
+encode_object_identifier({Name,Val}, DoTag) when atom(Name) ->
+ encode_object_identifier(Val, DoTag);
+encode_object_identifier(Val, []) ->
+ {EncVal,Len} = e_object_identifier(Val),
+ dotag_universal(?N_OBJECT_IDENTIFIER,EncVal,Len);
+encode_object_identifier(Val, DoTag) ->
+ dotag(DoTag, ?N_OBJECT_IDENTIFIER, e_object_identifier(Val)).
+
+e_object_identifier({'OBJECT IDENTIFIER', V}) ->
+ e_object_identifier(V);
+e_object_identifier({Cname, V}) when atom(Cname), tuple(V) ->
+ e_object_identifier(tuple_to_list(V));
+e_object_identifier({Cname, V}) when atom(Cname), list(V) ->
+ e_object_identifier(V);
+e_object_identifier(V) when tuple(V) ->
+ e_object_identifier(tuple_to_list(V));
+
+%%%%%%%%%%%%%%%
+%% e_object_identifier([List of Obect Identifiers]) ->
+%% {[Encoded Octetlist of ObjIds], IntLength}
+%%
+e_object_identifier([E1, E2 | Tail]) ->
+ Head = 40*E1 + E2, % wow!
+ {H,Lh} = mk_object_val(Head),
+ {R,Lr} = enc_obj_id_tail(Tail, [], 0),
+ {[H|R], Lh+Lr}.
+
+enc_obj_id_tail([], Ack, Len) ->
+ {lists:reverse(Ack), Len};
+enc_obj_id_tail([H|T], Ack, Len) ->
+ {B, L} = mk_object_val(H),
+ enc_obj_id_tail(T, [B|Ack], Len+L).
+
+%% e_object_identifier([List of Obect Identifiers]) ->
+%% {[Encoded Octetlist of ObjIds], IntLength}
+%%
+%%e_object_identifier([E1, E2 | Tail]) ->
+%% Head = 40*E1 + E2, % wow!
+%% F = fun(Val, AckLen) ->
+%% {L, Ack} = mk_object_val(Val),
+%% {L, Ack + AckLen}
+%% end,
+%% {Octets, Len} = lists:mapfoldl(F, 0, [Head | Tail]).
+
+%%%%%%%%%%%
+%% mk_object_val(Value) -> {OctetList, Len}
+%% returns a Val as a list of octets, the 8 bit is allways set to one except
+%% for the last octet, where its 0
+%%
+
+
+mk_object_val(Val) when Val =< 127 ->
+ {[255 band Val], 1};
+mk_object_val(Val) ->
+ mk_object_val(Val bsr 7, [Val band 127], 1).
+mk_object_val(0, Ack, Len) ->
+ {Ack, Len};
+mk_object_val(Val, Ack, Len) ->
+ mk_object_val(Val bsr 7, [((Val band 127) bor 128) | Ack], Len + 1).
+
+
+
+%%============================================================================
+%% decode Object Identifier value
+%% (Buffer, HasTag, TotalLen) -> {{ObjId}, Remain, RemovedBytes}
+%%============================================================================
+
+decode_object_identifier(Buffer, Tags, OptOrMand) ->
+ NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,
+ number=?N_OBJECT_IDENTIFIER}),
+ decode_object_identifier_notag(Buffer, NewTags, OptOrMand).
+
+decode_object_identifier_notag(Buffer, Tags, OptOrMand) ->
+ {RestTags, {FormLen, Buffer0, Rb0}} =
+ check_tags_i(Tags, Buffer, OptOrMand),
+
+ case FormLen of
+ {?CONSTRUCTED,Len} ->
+ {Buffer00,RestBytes} = split_list(Buffer0,Len),
+ {Val01, Buffer01, Rb01} =
+ decode_object_identifier_notag(Buffer00,
+ RestTags, OptOrMand),
+ {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
+ {Val01, Buffer02, Rb0+Rb01+Rb02};
+ {_,Len} ->
+ {[AddedObjVal|ObjVals],Buffer01} =
+ dec_subidentifiers(Buffer0,0,[],Len),
+ {Val1, Val2} = if
+ AddedObjVal < 40 ->
+ {0, AddedObjVal};
+ AddedObjVal < 80 ->
+ {1, AddedObjVal - 40};
+ true ->
+ {2, AddedObjVal - 80}
+ end,
+ {list_to_tuple([Val1, Val2 | ObjVals]), Buffer01,
+ Rb0+Len}
+ end.
+
+dec_subidentifiers(Buffer,_Av,Al,0) ->
+ {lists:reverse(Al),Buffer};
+dec_subidentifiers(<<1:1,H:7,T/binary>>,Av,Al,Len) ->
+ dec_subidentifiers(T,(Av bsl 7) + H,Al,Len-1);
+dec_subidentifiers(<<H,T/binary>>,Av,Al,Len) ->
+ dec_subidentifiers(T,0,[((Av bsl 7) + H)|Al],Len-1).
+
+
+%%dec_subidentifiers(Buffer,Av,Al,0) ->
+%% {lists:reverse(Al),Buffer};
+%%dec_subidentifiers([H|T],Av,Al,Len) when H >=16#80 ->
+%% dec_subidentifiers(T,(Av bsl 7) + (H band 16#7F),Al,Len-1);
+%%dec_subidentifiers([H|T],Av,Al,Len) ->
+%% dec_subidentifiers(T,0,[(Av bsl 7) + H |Al],Len-1).
+
+
+%%============================================================================
+%% Restricted character string types, ITU_T X.690 Chapter 8.20
+%%
+%% encode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings
+%%============================================================================
+encode_restricted_string(_C, OctetList, StringType, [])
+ when binary(OctetList) ->
+ dotag_universal(StringType,OctetList,size(OctetList));
+encode_restricted_string(_C, OctetList, StringType, DoTag)
+ when binary(OctetList) ->
+ dotag(DoTag, StringType, {OctetList, size(OctetList)});
+encode_restricted_string(_C, OctetList, StringType, [])
+ when list(OctetList) ->
+ dotag_universal(StringType,OctetList,length(OctetList));
+encode_restricted_string(_C, OctetList, StringType, DoTag)
+ when list(OctetList) ->
+ dotag(DoTag, StringType, {OctetList, length(OctetList)});
+encode_restricted_string(C,{Name,OctetL},StringType,DoTag) when atom(Name)->
+ encode_restricted_string(C, OctetL, StringType, DoTag).
+
+%%============================================================================
+%% decode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings
+%% (Buffer, Range, StringType, HasTag, TotalLen) ->
+%% {String, Remain, RemovedBytes}
+%%============================================================================
+
+decode_restricted_string(Buffer, Range, StringType, Tags, LenIn, OptOrMand) ->
+ {Val,Buffer2,Rb} =
+ decode_restricted_string_tag(Buffer, Range, StringType, Tags,
+ LenIn, [], OptOrMand,old),
+ {check_and_convert_restricted_string(Val,StringType,Range,[],old),
+ Buffer2,Rb}.
+
+
+decode_restricted_string(Buffer, Range, StringType, Tags, LenIn, NNList, OptOrMand, BinOrOld ) ->
+ {Val,Buffer2,Rb} =
+ decode_restricted_string_tag(Buffer, Range, StringType, Tags,
+ LenIn, NNList, OptOrMand, BinOrOld),
+ {check_and_convert_restricted_string(Val,StringType,Range,NNList,BinOrOld),
+ Buffer2,Rb}.
+
+decode_restricted_string_tag(Buffer, Range, StringType, TagsIn, LenIn, NNList, OptOrMand, BinOrOld ) ->
+ NewTags = new_tags(TagsIn, #tag{class=?UNIVERSAL,number=StringType}),
+ decode_restricted_string_notag(Buffer, Range, StringType, NewTags,
+ LenIn, NNList, OptOrMand, BinOrOld).
+
+
+
+
+check_and_convert_restricted_string(Val,StringType,Range,NamedNumberList,_BinOrOld) ->
+ {StrLen,NewVal} = case StringType of
+ ?N_BIT_STRING when NamedNumberList /= [] ->
+ {no_check,Val};
+ ?N_BIT_STRING when list(Val) ->
+ {length(Val),Val};
+ ?N_BIT_STRING when tuple(Val) ->
+ {(size(element(2,Val))*8) - element(1,Val),Val};
+ _ when binary(Val) ->
+ {size(Val),binary_to_list(Val)};
+ _ when list(Val) ->
+ {length(Val), Val}
+ end,
+ case Range of
+ _ when StrLen == no_check ->
+ NewVal;
+ [] -> % No length constraint
+ NewVal;
+ {Lb,Ub} when StrLen >= Lb, Ub >= StrLen -> % variable length constraint
+ NewVal;
+ {{Lb,_Ub},[]} when StrLen >= Lb ->
+ NewVal;
+ {{Lb1,Ub1},{Lb2,Ub2}} when StrLen >= Lb1, StrLen =< Ub1;
+ StrLen =< Ub2, StrLen >= Lb2 ->
+ NewVal;
+ StrLen -> % fixed length constraint
+ NewVal;
+ {_,_} ->
+ exit({error,{asn1,{length,Range,Val}}});
+ _Len when integer(_Len) ->
+ exit({error,{asn1,{length,Range,Val}}});
+ _ -> % some strange constraint that we don't support yet
+ NewVal
+ end.
+
+
+%%=============================================================================
+%% Common routines for several string types including bit string
+%% handles indefinite length
+%%=============================================================================
+
+
+decode_restricted_string_notag(Buffer, _Range, StringType, TagsIn,
+ _, NamedNumberList, OptOrMand,BinOrOld) ->
+ %%-----------------------------------------------------------
+ %% Get inner (the implicit tag or no tag) and
+ %% outer (the explicit tag) lengths.
+ %%-----------------------------------------------------------
+ {RestTags, {FormLength={_,_Len01}, Buffer0, Rb0}} =
+ check_tags_i(TagsIn, Buffer, OptOrMand),
+
+ case FormLength of
+ {?CONSTRUCTED,Len} ->
+ {Buffer00, RestBytes} = split_list(Buffer0,Len),
+ {Val01, Buffer01, Rb01} =
+ decode_restricted_parts(Buffer00, RestBytes, [], StringType,
+ RestTags,
+ Len, NamedNumberList,
+ OptOrMand,
+ BinOrOld, 0, []),
+ {Val01, Buffer01, Rb0+Rb01};
+ {_, Len} ->
+ {Val01, Buffer01, Rb01} =
+ decode_restricted(Buffer0, Len, StringType,
+ NamedNumberList, BinOrOld),
+ {Val01, Buffer01, Rb0+Rb01}
+ end.
+
+
+decode_restricted_parts(Buffer, RestBytes, [], StringType, RestTags, Len, NNList,
+ OptOrMand, BinOrOld, AccRb, AccVal) ->
+ DecodeFun = case RestTags of
+ [] -> fun decode_restricted_string_tag/8;
+ _ -> fun decode_restricted_string_notag/8
+ end,
+ {Val, Buffer1, Rb} =
+ DecodeFun(Buffer, [], StringType, RestTags,
+ no_length, NNList,
+ OptOrMand, BinOrOld),
+ {Buffer2,More} =
+ case Buffer1 of
+ <<0,0,Buffer10/binary>> when Len == indefinite ->
+ {Buffer10,false};
+ <<>> ->
+ {RestBytes,false};
+ _ ->
+ {Buffer1,true}
+ end,
+ {NewVal, NewRb} =
+ case StringType of
+ ?N_BIT_STRING when BinOrOld == bin ->
+ {concat_bit_binaries(AccVal, Val), AccRb+Rb};
+ _ when binary(Val),binary(AccVal) ->
+ {<<AccVal/binary,Val/binary>>,AccRb+Rb};
+ _ when binary(Val), AccVal==[] ->
+ {Val,AccRb+Rb};
+ _ ->
+ {AccVal++Val, AccRb+Rb}
+ end,
+ case More of
+ false ->
+ {NewVal, Buffer2, NewRb};
+ true ->
+ decode_restricted_parts(Buffer2, RestBytes, [], StringType, RestTags, Len, NNList,
+ OptOrMand, BinOrOld, NewRb, NewVal)
+ end.
+
+
+
+decode_restricted(Buffer, InnerLen, StringType, NamedNumberList,BinOrOld) ->
+
+ case StringType of
+ ?N_BIT_STRING ->
+ decode_bit_string2(InnerLen,Buffer,NamedNumberList,InnerLen,BinOrOld);
+
+ ?N_UniversalString ->
+ <<PreBuff:InnerLen/binary,RestBuff/binary>> = Buffer,%%added for binary
+ UniString = mk_universal_string(binary_to_list(PreBuff)),
+ {UniString,RestBuff,InnerLen};
+ ?N_BMPString ->
+ <<PreBuff:InnerLen/binary,RestBuff/binary>> = Buffer,%%added for binary
+ BMP = mk_BMP_string(binary_to_list(PreBuff)),
+ {BMP,RestBuff,InnerLen};
+ _ ->
+ <<PreBuff:InnerLen/binary,RestBuff/binary>> = Buffer,%%added for binary
+ {PreBuff, RestBuff, InnerLen}
+ end.
+
+
+
+%%============================================================================
+%% encode Universal string
+%%============================================================================
+
+encode_universal_string(C, {Name, Universal}, DoTag) when atom(Name) ->
+ encode_universal_string(C, Universal, DoTag);
+encode_universal_string(_C, Universal, []) ->
+ OctetList = mk_uni_list(Universal),
+ dotag_universal(?N_UniversalString,OctetList,length(OctetList));
+encode_universal_string(_C, Universal, DoTag) ->
+ OctetList = mk_uni_list(Universal),
+ dotag(DoTag, ?N_UniversalString, {OctetList,length(OctetList)}).
+
+mk_uni_list(In) ->
+ mk_uni_list(In,[]).
+
+mk_uni_list([],List) ->
+ lists:reverse(List);
+mk_uni_list([{A,B,C,D}|T],List) ->
+ mk_uni_list(T,[D,C,B,A|List]);
+mk_uni_list([H|T],List) ->
+ mk_uni_list(T,[H,0,0,0|List]).
+
+%%===========================================================================
+%% decode Universal strings
+%% (Buffer, Range, StringType, HasTag, LenIn) ->
+%% {String, Remain, RemovedBytes}
+%%===========================================================================
+
+decode_universal_string(Buffer, Range, Tags, LenIn, OptOrMand) ->
+% NewTags = new_tags(HasTag, #tag{class=?UNIVERSAL,number=?N_UniversalString}),
+ decode_restricted_string(Buffer, Range, ?N_UniversalString,
+ Tags, LenIn, [], OptOrMand,old).
+
+
+mk_universal_string(In) ->
+ mk_universal_string(In,[]).
+
+mk_universal_string([],Acc) ->
+ lists:reverse(Acc);
+mk_universal_string([0,0,0,D|T],Acc) ->
+ mk_universal_string(T,[D|Acc]);
+mk_universal_string([A,B,C,D|T],Acc) ->
+ mk_universal_string(T,[{A,B,C,D}|Acc]).
+
+
+%%============================================================================
+%% encode BMP string
+%%============================================================================
+
+encode_BMP_string(C, {Name,BMPString}, DoTag) when atom(Name)->
+ encode_BMP_string(C, BMPString, DoTag);
+encode_BMP_string(_C, BMPString, []) ->
+ OctetList = mk_BMP_list(BMPString),
+ dotag_universal(?N_BMPString,OctetList,length(OctetList));
+encode_BMP_string(_C, BMPString, DoTag) ->
+ OctetList = mk_BMP_list(BMPString),
+ dotag(DoTag, ?N_BMPString, {OctetList,length(OctetList)}).
+
+mk_BMP_list(In) ->
+ mk_BMP_list(In,[]).
+
+mk_BMP_list([],List) ->
+ lists:reverse(List);
+mk_BMP_list([{0,0,C,D}|T],List) ->
+ mk_BMP_list(T,[D,C|List]);
+mk_BMP_list([H|T],List) ->
+ mk_BMP_list(T,[H,0|List]).
+
+%%============================================================================
+%% decode (OctetList, Range(ignored), tag|notag) -> {ValList, RestList}
+%% (Buffer, Range, StringType, HasTag, TotalLen) ->
+%% {String, Remain, RemovedBytes}
+%%============================================================================
+decode_BMP_string(Buffer, Range, Tags, LenIn, OptOrMand) ->
+% NewTags = new_tags(HasTag, #tag{class=?UNIVERSAL,number=?N_BMPString}),
+ decode_restricted_string(Buffer, Range, ?N_BMPString,
+ Tags, LenIn, [], OptOrMand,old).
+
+mk_BMP_string(In) ->
+ mk_BMP_string(In,[]).
+
+mk_BMP_string([],US) ->
+ lists:reverse(US);
+mk_BMP_string([0,B|T],US) ->
+ mk_BMP_string(T,[B|US]);
+mk_BMP_string([C,D|T],US) ->
+ mk_BMP_string(T,[{0,0,C,D}|US]).
+
+
+%%============================================================================
+%% Generalized time, ITU_T X.680 Chapter 39
+%%
+%% encode Generalized time
+%%============================================================================
+
+encode_generalized_time(C, {Name,OctetList}, DoTag) when atom(Name) ->
+ encode_generalized_time(C, OctetList, DoTag);
+encode_generalized_time(_C, OctetList, []) ->
+ dotag_universal(?N_GeneralizedTime,OctetList,length(OctetList));
+encode_generalized_time(_C, OctetList, DoTag) ->
+ dotag(DoTag, ?N_GeneralizedTime, {OctetList,length(OctetList)}).
+
+%%============================================================================
+%% decode Generalized time
+%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
+%%============================================================================
+
+decode_generalized_time(Buffer, Range, Tags, TotalLen, OptOrMand) ->
+ NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,
+ number=?N_GeneralizedTime}),
+ decode_generalized_time_notag(Buffer, Range, NewTags, TotalLen, OptOrMand).
+
+decode_generalized_time_notag(Buffer, Range, Tags, TotalLen, OptOrMand) ->
+ {RestTags, {FormLen, Buffer0, Rb0}} =
+ check_tags_i(Tags, Buffer, OptOrMand),
+
+ case FormLen of
+ {?CONSTRUCTED,Len} ->
+ {Buffer00,RestBytes} = split_list(Buffer0,Len),
+ {Val01, Buffer01, Rb01} =
+ decode_generalized_time_notag(Buffer00, Range,
+ RestTags, TotalLen,
+ OptOrMand),
+ {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
+ {Val01, Buffer02, Rb0+Rb01+Rb02};
+ {_,Len} ->
+ <<PreBuff:Len/binary,RestBuff/binary>> = Buffer0,
+ {binary_to_list(PreBuff), RestBuff, Rb0+Len}
+ end.
+
+%%============================================================================
+%% Universal time, ITU_T X.680 Chapter 40
+%%
+%% encode UTC time
+%%============================================================================
+
+encode_utc_time(C, {Name,OctetList}, DoTag) when atom(Name) ->
+ encode_utc_time(C, OctetList, DoTag);
+encode_utc_time(_C, OctetList, []) ->
+ dotag_universal(?N_UTCTime, OctetList,length(OctetList));
+encode_utc_time(_C, OctetList, DoTag) ->
+ dotag(DoTag, ?N_UTCTime, {OctetList,length(OctetList)}).
+
+%%============================================================================
+%% decode UTC time
+%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
+%%============================================================================
+
+decode_utc_time(Buffer, Range, Tags, TotalLen, OptOrMand) ->
+ NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_UTCTime}),
+ decode_utc_time_notag(Buffer, Range, NewTags, TotalLen, OptOrMand).
+
+decode_utc_time_notag(Buffer, Range, Tags, TotalLen, OptOrMand) ->
+ {RestTags, {FormLen, Buffer0, Rb0}} =
+ check_tags_i(Tags, Buffer, OptOrMand),
+
+ case FormLen of
+ {?CONSTRUCTED,Len} ->
+ {Buffer00,RestBytes} = split_list(Buffer0,Len),
+ {Val01, Buffer01, Rb01} =
+ decode_utc_time_notag(Buffer00, Range,
+ RestTags, TotalLen,
+ OptOrMand),
+ {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
+ {Val01, Buffer02, Rb0+Rb01+Rb02};
+ {_,Len} ->
+ <<PreBuff:Len/binary,RestBuff/binary>> = Buffer0,
+ {binary_to_list(PreBuff), RestBuff, Rb0+Len}
+ end.
+
+
+%%============================================================================
+%% Length handling
+%%
+%% Encode length
+%%
+%% encode_length(Int | indefinite) ->
+%% [<127]| [128 + Int (<127),OctetList] | [16#80]
+%%============================================================================
+
+encode_length(indefinite) ->
+ {[16#80],1}; % 128
+encode_length(L) when L =< 16#7F ->
+ {[L],1};
+encode_length(L) ->
+ Oct = minimum_octets(L),
+ Len = length(Oct),
+ if
+ Len =< 126 ->
+ {[ (16#80+Len) | Oct ],Len+1};
+ true ->
+ exit({error,{asn1, to_long_length_oct, Len}})
+ end.
+
+
+%% Val must be >= 0
+minimum_octets(Val) ->
+ minimum_octets(Val,[]).
+
+minimum_octets(0,Acc) ->
+ Acc;
+minimum_octets(Val, Acc) ->
+ minimum_octets((Val bsr 8),[Val band 16#FF | Acc]).
+
+
+%%===========================================================================
+%% Decode length
+%%
+%% decode_length(OctetList) -> {{indefinite, RestOctetsL}, NoRemovedBytes} |
+%% {{Length, RestOctetsL}, NoRemovedBytes}
+%%===========================================================================
+
+decode_length(<<1:1,0:7,T/binary>>) ->
+ {{indefinite, T}, 1};
+decode_length(<<0:1,Length:7,T/binary>>) ->
+ {{Length,T},1};
+decode_length(<<1:1,LL:7,T/binary>>) ->
+ <<Length:LL/unit:8,Rest/binary>> = T,
+ {{Length,Rest}, LL+1}.
+
+%decode_length([128 | T]) ->
+% {{indefinite, T},1};
+%decode_length([H | T]) when H =< 127 ->
+% {{H, T},1};
+%decode_length([H | T]) ->
+% dec_long_length(H band 16#7F, T, 0, 1).
+
+
+%%dec_long_length(0, Buffer, Acc, Len) ->
+%% {{Acc, Buffer},Len};
+%%dec_long_length(Bytes, [H | T], Acc, Len) ->
+%% dec_long_length(Bytes - 1, T, (Acc bsl 8) + H, Len+1).
+
+%%===========================================================================
+%% Decode tag and length
+%%
+%% decode_tag_and_length(Buffer) -> {Tag, Len, RemainingBuffer, RemovedBytes}
+%%
+%%===========================================================================
+
+decode_tag_and_length(Buffer) ->
+ {Tag, Buffer2, RemBytesTag} = decode_tag(Buffer),
+ {{Len, Buffer3}, RemBytesLen} = decode_length(Buffer2),
+ {Tag, Len, Buffer3, RemBytesTag+RemBytesLen}.
+
+
+%%============================================================================
+%% Check if valid tag
+%%
+%% check_if_valid_tag(Tag, List_of_valid_tags, OptOrMand) -> name of the tag
+%%===============================================================================
+
+check_if_valid_tag(<<0,0,_/binary>>,_,_) ->
+ asn1_EOC;
+check_if_valid_tag(<<>>, _, OptOrMand) ->
+ check_if_valid_tag2(false,[],[],OptOrMand);
+check_if_valid_tag(Bytes, ListOfTags, OptOrMand) when binary(Bytes) ->
+ {Tag, _, _} = decode_tag(Bytes),
+ check_if_valid_tag(Tag, ListOfTags, OptOrMand);
+
+%% This alternative should be removed in the near future
+%% Bytes as input should be the only necessary call
+check_if_valid_tag(Tag, ListOfTags, OptOrMand) ->
+ {Class, _Form, TagNo} = Tag,
+ C = code_class(Class),
+ T = case C of
+ 'UNIVERSAL' ->
+ code_type(TagNo);
+ _ ->
+ TagNo
+ end,
+ check_if_valid_tag2({C,T}, ListOfTags, Tag, OptOrMand).
+
+check_if_valid_tag2(_Class_TagNo, [], Tag, mandatory) ->
+ exit({error,{asn1,{invalid_tag,Tag}}});
+check_if_valid_tag2(_Class_TagNo, [], Tag, _) ->
+ exit({error,{asn1,{no_optional_tag,Tag}}});
+
+check_if_valid_tag2(Class_TagNo, [{TagName,TagList}|T], Tag, OptOrMand) ->
+ case check_if_valid_tag_loop(Class_TagNo, TagList) of
+ true ->
+ TagName;
+ false ->
+ check_if_valid_tag2(Class_TagNo, T, Tag, OptOrMand)
+ end.
+
+check_if_valid_tag_loop(_Class_TagNo,[]) ->
+ false;
+check_if_valid_tag_loop(Class_TagNo,[H|T]) ->
+ %% It is not possible to distinguish between SEQUENCE OF and SEQUENCE, and
+ %% between SET OF and SET because both are coded as 16 and 17, respectively.
+ H_without_OF = case H of
+ {C, 'SEQUENCE OF'} ->
+ {C, 'SEQUENCE'};
+ {C, 'SET OF'} ->
+ {C, 'SET'};
+ Else ->
+ Else
+ end,
+
+ case H_without_OF of
+ Class_TagNo ->
+ true;
+ {_,_} ->
+ check_if_valid_tag_loop(Class_TagNo,T);
+ _ ->
+ check_if_valid_tag_loop(Class_TagNo,H),
+ check_if_valid_tag_loop(Class_TagNo,T)
+ end.
+
+
+
+code_class(0) -> 'UNIVERSAL';
+code_class(16#40) -> 'APPLICATION';
+code_class(16#80) -> 'CONTEXT';
+code_class(16#C0) -> 'PRIVATE'.
+
+
+code_type(1) -> 'BOOLEAN';
+code_type(2) -> 'INTEGER';
+code_type(3) -> 'BIT STRING';
+code_type(4) -> 'OCTET STRING';
+code_type(5) -> 'NULL';
+code_type(6) -> 'OBJECT IDENTIFIER';
+code_type(7) -> 'OBJECT DESCRIPTOR';
+code_type(8) -> 'EXTERNAL';
+code_type(9) -> 'REAL';
+code_type(10) -> 'ENUMERATED';
+code_type(11) -> 'EMBEDDED_PDV';
+code_type(16) -> 'SEQUENCE';
+code_type(16) -> 'SEQUENCE OF';
+code_type(17) -> 'SET';
+code_type(17) -> 'SET OF';
+code_type(18) -> 'NumericString';
+code_type(19) -> 'PrintableString';
+code_type(20) -> 'TeletexString';
+code_type(21) -> 'VideotexString';
+code_type(22) -> 'IA5String';
+code_type(23) -> 'UTCTime';
+code_type(24) -> 'GeneralizedTime';
+code_type(25) -> 'GraphicString';
+code_type(26) -> 'VisibleString';
+code_type(27) -> 'GeneralString';
+code_type(28) -> 'UniversalString';
+code_type(30) -> 'BMPString';
+code_type(Else) -> exit({error,{asn1,{unrecognized_type,Else}}}).
+
+%%-------------------------------------------------------------------------
+%% decoding of the components of a SET
+%%-------------------------------------------------------------------------
+
+decode_set(Rb, indefinite, <<0,0,Bytes/binary>>, _OptOrMand, _Fun3, Acc) ->
+ {lists:reverse(Acc),Bytes,Rb+2};
+
+decode_set(Rb, indefinite, Bytes, OptOrMand, Fun3, Acc) ->
+ {Term, Remain, Rb1} = Fun3(Bytes, OptOrMand),
+ decode_set(Rb+Rb1, indefinite, Remain, OptOrMand, Fun3, [Term|Acc]);
+
+decode_set(Rb, Num, Bytes, _OptOrMand, _Fun3, Acc) when Num == 0 ->
+ {lists:reverse(Acc), Bytes, Rb};
+
+decode_set(_, Num, _, _, _, _) when Num < 0 ->
+ exit({error,{asn1,{length_error,'SET'}}});
+
+decode_set(Rb, Num, Bytes, OptOrMand, Fun3, Acc) ->
+ {Term, Remain, Rb1} = Fun3(Bytes, OptOrMand),
+ decode_set(Rb+Rb1, Num-Rb1, Remain, OptOrMand, Fun3, [Term|Acc]).
+
+
+%%-------------------------------------------------------------------------
+%% decoding of SEQUENCE OF and SET OF
+%%-------------------------------------------------------------------------
+
+decode_components(Rb, indefinite, <<0,0,Bytes/binary>>, _Fun3, _TagIn, Acc) ->
+ {lists:reverse(Acc),Bytes,Rb+2};
+
+decode_components(Rb, indefinite, Bytes, Fun3, TagIn, Acc) ->
+ {Term, Remain, Rb1} = Fun3(Bytes, mandatory, TagIn),
+ decode_components(Rb+Rb1, indefinite, Remain, Fun3, TagIn, [Term|Acc]);
+
+decode_components(Rb, Num, Bytes, _Fun3, _TagIn, Acc) when Num == 0 ->
+ {lists:reverse(Acc), Bytes, Rb};
+
+decode_components(_, Num, _, _, _, _) when Num < 0 ->
+ exit({error,{asn1,{length_error,'SET/SEQUENCE OF'}}});
+
+decode_components(Rb, Num, Bytes, Fun3, TagIn, Acc) ->
+ {Term, Remain, Rb1} = Fun3(Bytes, mandatory, TagIn),
+ decode_components(Rb+Rb1, Num-Rb1, Remain, Fun3, TagIn, [Term|Acc]).
+
+%%decode_components(Rb, indefinite, [0,0|Bytes], _Fun3, _TagIn, Acc) ->
+%% {lists:reverse(Acc),Bytes,Rb+2};
+
+decode_components(Rb, indefinite, <<0,0,Bytes/binary>>, _Fun4, _TagIn, _Fun, Acc) ->
+ {lists:reverse(Acc),Bytes,Rb+2};
+
+decode_components(Rb, indefinite, Bytes, _Fun4, TagIn, _Fun, Acc) ->
+ {Term, Remain, Rb1} = _Fun4(Bytes, mandatory, TagIn, _Fun),
+ decode_components(Rb+Rb1, indefinite, Remain, _Fun4, TagIn, _Fun, [Term|Acc]);
+
+decode_components(Rb, Num, Bytes, _Fun4, _TagIn, _Fun, Acc) when Num == 0 ->
+ {lists:reverse(Acc), Bytes, Rb};
+
+decode_components(_, Num, _, _, _, _, _) when Num < 0 ->
+ exit({error,{asn1,{length_error,'SET/SEQUENCE OF'}}});
+
+decode_components(Rb, Num, Bytes, _Fun4, TagIn, _Fun, Acc) ->
+ {Term, Remain, Rb1} = _Fun4(Bytes, mandatory, TagIn, _Fun),
+ decode_components(Rb+Rb1, Num-Rb1, Remain, _Fun4, TagIn, _Fun, [Term|Acc]).
+
+
+
+%%-------------------------------------------------------------------------
+%% INTERNAL HELPER FUNCTIONS (not exported)
+%%-------------------------------------------------------------------------
+
+
+%%==========================================================================
+%% Encode tag
+%%
+%% dotag(tag | notag, TagValpattern | TagValTuple, [Length, Value]) -> [Tag]
+%% TagValPattern is a correct bitpattern for a tag
+%% TagValTuple is a tuple of three bitpatterns, Class, Form and TagNo where
+%% Class = UNIVERSAL | APPLICATION | CONTEXT | PRIVATE
+%% Form = Primitive | Constructed
+%% TagNo = Number of tag
+%%==========================================================================
+
+
+dotag([], Tag, {Bytes,Len}) ->
+ dotag_universal(Tag,Bytes,Len);
+dotag(Tags, Tag, {Bytes,Len}) ->
+ encode_tags(Tags ++ [#tag{class=?UNIVERSAL,number=Tag,form=?PRIMITIVE}],
+ Bytes, Len);
+
+dotag(Tags, Tag, Bytes) ->
+ encode_tags(Tags ++ [#tag{class=?UNIVERSAL,number=Tag,form=?PRIMITIVE}],
+ Bytes, size(Bytes)).
+
+dotag_universal(UniversalTag,Bytes,Len) when Len =< 16#7F->
+ {[UniversalTag,Len,Bytes],2+Len};
+dotag_universal(UniversalTag,Bytes,Len) ->
+ {EncLen,LenLen}=encode_length(Len),
+ {[UniversalTag,EncLen,Bytes],1+LenLen+Len}.
+
+%% decoding postitive integer values.
+decode_integer2(Len,Bin = <<0:1,_:7,_Bs/binary>>,RemovedBytes) ->
+ <<Int:Len/unit:8,Buffer2/binary>> = Bin,
+ {Int,Buffer2,RemovedBytes};
+%% decoding negative integer values.
+decode_integer2(Len,<<1:1,B2:7,Bs/binary>>,RemovedBytes) ->
+ <<N:Len/unit:8,Buffer2/binary>> = <<B2,Bs/binary>>,
+ Int = N - (1 bsl (8 * Len - 1)),
+ {Int,Buffer2,RemovedBytes}.
+
+%%decode_integer2(Len,Buffer,Acc,RemovedBytes) when (hd(Buffer) band 16#FF) =< 16#7F ->
+%% {decode_integer_pos(Buffer, 8 * (Len - 1)),skip(Buffer,Len),RemovedBytes};
+%%decode_integer2(Len,Buffer,Acc,RemovedBytes) ->
+%% {decode_integer_neg(Buffer, 8 * (Len - 1)),skip(Buffer,Len),RemovedBytes}.
+
+%%decode_integer_pos([Byte|Tail], Shift) ->
+%% (Byte bsl Shift) bor decode_integer_pos(Tail, Shift-8);
+%%decode_integer_pos([], _) -> 0.
+
+
+%%decode_integer_neg([Byte|Tail], Shift) ->
+%% (-128 + (Byte band 127) bsl Shift) bor decode_integer_pos(Tail, Shift-8).
+
+
+concat_bit_binaries([],Bin={_,_}) ->
+ Bin;
+concat_bit_binaries({0,B1},{U2,B2}) ->
+ {U2,<<B1/binary,B2/binary>>};
+concat_bit_binaries({U1,B1},{U2,B2}) ->
+ S1 = (size(B1) * 8) - U1,
+ S2 = (size(B2) * 8) - U2,
+ PadBits = 8 - ((S1+S2) rem 8),
+ {PadBits, <<B1:S1/binary-unit:1,B2:S2/binary-unit:1,0:PadBits>>};
+concat_bit_binaries(L1,L2) when list(L1),list(L2) ->
+ %% this case occur when decoding with NNL
+ L1 ++ L2.
+
+
+get_constraint(C,Key) ->
+ case lists:keysearch(Key,1,C) of
+ false ->
+ no;
+ {value,{_,V}} ->
+ V
+ end.
+
+%%skip(Buffer, 0) ->
+%% Buffer;
+%%skip([H | T], Len) ->
+%% skip(T, Len-1).
+
+new_tags([],LastTag) ->
+ [LastTag];
+new_tags(Tags=[#tag{type='IMPLICIT'}],_LastTag) ->
+ Tags;
+new_tags([T1 = #tag{type='IMPLICIT'},#tag{type=T2Type}|Rest],LastTag) ->
+ new_tags([T1#tag{type=T2Type}|Rest],LastTag);
+new_tags(Tags,LastTag) ->
+ case lists:last(Tags) of
+ #tag{type='IMPLICIT'} ->
+ Tags;
+ _ ->
+ Tags ++ [LastTag]
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_ber_bin_v2.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_ber_bin_v2.erl
new file mode 100644
index 0000000000..50a91cf201
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_ber_bin_v2.erl
@@ -0,0 +1,1849 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1rt_ber_bin_v2.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
+%%
+-module(asn1rt_ber_bin_v2).
+
+%% encoding / decoding of BER
+
+-export([decode/1, decode/2, match_tags/2, encode/1]).
+-export([fixoptionals/2, cindex/3,
+ list_to_record/2,
+ encode_tag_val/1,
+ encode_tags/3]).
+-export([encode_boolean/2,decode_boolean/2,
+ encode_integer/3,encode_integer/4,
+ decode_integer/3, decode_integer/4,
+ encode_enumerated/2,
+ encode_enumerated/4,decode_enumerated/4,
+ encode_real/2,decode_real/3,
+ encode_bit_string/4,decode_bit_string/4,
+ decode_compact_bit_string/4,
+ encode_octet_string/3,decode_octet_string/3,
+ encode_null/2,decode_null/2,
+ encode_object_identifier/2,decode_object_identifier/2,
+ encode_restricted_string/4,decode_restricted_string/4,
+ encode_universal_string/3,decode_universal_string/3,
+ encode_BMP_string/3,decode_BMP_string/3,
+ encode_generalized_time/3,decode_generalized_time/3,
+ encode_utc_time/3,decode_utc_time/3,
+ encode_length/1,decode_length/1,
+ decode_tag_and_length/1]).
+
+-export([encode_open_type/1,encode_open_type/2,
+ decode_open_type/2,decode_open_type_as_binary/2]).
+
+-export([decode_primitive_incomplete/2]).
+
+-include("asn1_records.hrl").
+
+% the encoding of class of tag bits 8 and 7
+-define(UNIVERSAL, 0).
+-define(APPLICATION, 16#40).
+-define(CONTEXT, 16#80).
+-define(PRIVATE, 16#C0).
+
+%%% primitive or constructed encoding % bit 6
+-define(PRIMITIVE, 0).
+-define(CONSTRUCTED, 2#00100000).
+
+%%% The tag-number for universal types
+-define(N_BOOLEAN, 1).
+-define(N_INTEGER, 2).
+-define(N_BIT_STRING, 3).
+-define(N_OCTET_STRING, 4).
+-define(N_NULL, 5).
+-define(N_OBJECT_IDENTIFIER, 6).
+-define(N_OBJECT_DESCRIPTOR, 7).
+-define(N_EXTERNAL, 8).
+-define(N_REAL, 9).
+-define(N_ENUMERATED, 10).
+-define(N_EMBEDDED_PDV, 11).
+-define(N_SEQUENCE, 16).
+-define(N_SET, 17).
+-define(N_NumericString, 18).
+-define(N_PrintableString, 19).
+-define(N_TeletexString, 20).
+-define(N_VideotexString, 21).
+-define(N_IA5String, 22).
+-define(N_UTCTime, 23).
+-define(N_GeneralizedTime, 24).
+-define(N_GraphicString, 25).
+-define(N_VisibleString, 26).
+-define(N_GeneralString, 27).
+-define(N_UniversalString, 28).
+-define(N_BMPString, 30).
+
+
+% the complete tag-word of built-in types
+-define(T_BOOLEAN, ?UNIVERSAL bor ?PRIMITIVE bor 1).
+-define(T_INTEGER, ?UNIVERSAL bor ?PRIMITIVE bor 2).
+-define(T_BIT_STRING, ?UNIVERSAL bor ?PRIMITIVE bor 3). % can be CONSTRUCTED
+-define(T_OCTET_STRING, ?UNIVERSAL bor ?PRIMITIVE bor 4). % can be CONSTRUCTED
+-define(T_NULL, ?UNIVERSAL bor ?PRIMITIVE bor 5).
+-define(T_OBJECT_IDENTIFIER,?UNIVERSAL bor ?PRIMITIVE bor 6).
+-define(T_OBJECT_DESCRIPTOR,?UNIVERSAL bor ?PRIMITIVE bor 7).
+-define(T_EXTERNAL, ?UNIVERSAL bor ?PRIMITIVE bor 8).
+-define(T_REAL, ?UNIVERSAL bor ?PRIMITIVE bor 9).
+-define(T_ENUMERATED, ?UNIVERSAL bor ?PRIMITIVE bor 10).
+-define(T_EMBEDDED_PDV, ?UNIVERSAL bor ?PRIMITIVE bor 11).
+-define(T_SEQUENCE, ?UNIVERSAL bor ?CONSTRUCTED bor 16).
+-define(T_SET, ?UNIVERSAL bor ?CONSTRUCTED bor 17).
+-define(T_NumericString, ?UNIVERSAL bor ?PRIMITIVE bor 18). %can be constructed
+-define(T_PrintableString, ?UNIVERSAL bor ?PRIMITIVE bor 19). %can be constructed
+-define(T_TeletexString, ?UNIVERSAL bor ?PRIMITIVE bor 20). %can be constructed
+-define(T_VideotexString, ?UNIVERSAL bor ?PRIMITIVE bor 21). %can be constructed
+-define(T_IA5String, ?UNIVERSAL bor ?PRIMITIVE bor 22). %can be constructed
+-define(T_UTCTime, ?UNIVERSAL bor ?PRIMITIVE bor 23).
+-define(T_GeneralizedTime, ?UNIVERSAL bor ?PRIMITIVE bor 24).
+-define(T_GraphicString, ?UNIVERSAL bor ?PRIMITIVE bor 25). %can be constructed
+-define(T_VisibleString, ?UNIVERSAL bor ?PRIMITIVE bor 26). %can be constructed
+-define(T_GeneralString, ?UNIVERSAL bor ?PRIMITIVE bor 27). %can be constructed
+-define(T_UniversalString, ?UNIVERSAL bor ?PRIMITIVE bor 28). %can be constructed
+-define(T_BMPString, ?UNIVERSAL bor ?PRIMITIVE bor 30). %can be constructed
+
+% encode(Tlv={_Tag={?PRIMITIVE,_},_VList}) ->
+% encode_primitive(Tlv);
+% encode(Tlv) ->
+% encode_constructed(Tlv).
+
+encode([Tlv]) ->
+ encode(Tlv);
+encode({TlvTag,TlvVal}) when list(TlvVal) ->
+ %% constructed form of value
+ encode_tlv(TlvTag,TlvVal,?CONSTRUCTED);
+encode({TlvTag,TlvVal}) ->
+ encode_tlv(TlvTag,TlvVal,?PRIMITIVE);
+encode(Bin) when binary(Bin) ->
+ Bin.
+
+encode_tlv(TlvTag,TlvVal,Form) ->
+ Tag = encode_tlv_tag(TlvTag,Form),
+ {Val,VLen} = encode_tlv_val(TlvVal),
+ {Len,_LLen} = encode_length(VLen),
+ BinLen = list_to_binary(Len),
+ <<Tag/binary,BinLen/binary,Val/binary>>.
+
+encode_tlv_tag(ClassTagNo,Form) ->
+ Class = ClassTagNo bsr 16,
+ case encode_tag_val({Class bsl 6,Form,(ClassTagNo - (Class bsl 16))}) of
+ T when list(T) ->
+ list_to_binary(T);
+ T ->
+ T
+ end.
+
+encode_tlv_val(TlvL) when list(TlvL) ->
+ encode_tlv_list(TlvL,[]);
+encode_tlv_val(Bin) ->
+ {Bin,size(Bin)}.
+
+encode_tlv_list([Tlv|Tlvs],Acc) ->
+ EncTlv = encode(Tlv),
+ encode_tlv_list(Tlvs,[EncTlv|Acc]);
+encode_tlv_list([],Acc) ->
+ Bin=list_to_binary(lists:reverse(Acc)),
+ {Bin,size(Bin)}.
+
+% encode_primitive({{_,ClassTagNo},V}) ->
+% Len = size(V), % not sufficient as length encode
+% Class = ClassTagNo bsr 16,
+% {TagLen,Tag} =
+% case encode_tag_val({Class,?PRIMITIVE,ClassTagNo - Class}) of
+% T when list(T) ->
+% {length(T),list_to_binary(T)};
+% T ->
+% {1,T}
+% end,
+
+
+decode(B,driver) ->
+ case catch port_control(drv_complete,2,B) of
+ Bin when binary(Bin) ->
+ binary_to_term(Bin);
+ List when list(List) -> handle_error(List,B);
+ {'EXIT',{badarg,Reason}} ->
+ asn1rt_driver_handler:load_driver(),
+ receive
+ driver_ready ->
+ case catch port_control(drv_complete,2,B) of
+ Bin2 when binary(Bin2) -> binary_to_term(Bin2);
+ List when list(List) -> handle_error(List,B);
+ Error -> exit(Error)
+ end;
+ {error,Error} -> % error when loading driver
+ %% the driver could not be loaded
+ exit(Error);
+ Error={port_error,Reason} ->
+ exit(Error)
+ end;
+ {'EXIT',Reason} ->
+ exit(Reason)
+ end.
+
+handle_error([],_)->
+ exit({error,{"memory allocation problem"}});
+handle_error([$1|_],L) -> % error in driver
+ exit({error,{asn1_error,L}});
+handle_error([$2|_],L) -> % error in driver due to wrong tag
+ exit({error,{asn1_error,{"bad tag",L}}});
+handle_error([$3|_],L) -> % error in driver due to length error
+ exit({error,{asn1_error,{"bad length field",L}}});
+handle_error([$4|_],L) -> % error in driver due to indefinite length error
+ exit({error,{asn1_error,{"indefinite length without end bytes",L}}});
+handle_error(ErrL,L) ->
+ exit({error,{unknown_error,ErrL,L}}).
+
+
+decode(Bin) when binary(Bin) ->
+ decode_primitive(Bin);
+decode(Tlv) -> % assume it is a tlv
+ {Tlv,<<>>}.
+
+
+decode_primitive(Bin) ->
+ {{Form,TagNo,Len,V},Rest} = decode_tlv(Bin),
+ case Form of
+ 1 when Len == indefinite -> % constructed
+ {Vlist,Rest2} = decode_constructed_indefinite(V,[]),
+ {{TagNo,Vlist},Rest2};
+ 1 -> % constructed
+ {{TagNo,decode_constructed(V)},Rest};
+ 0 -> % primitive
+ {{TagNo,V},Rest}
+ end.
+
+decode_constructed(<<>>) ->
+ [];
+decode_constructed(Bin) ->
+ {Tlv,Rest} = decode_primitive(Bin),
+ [Tlv|decode_constructed(Rest)].
+
+decode_constructed_indefinite(<<0,0,Rest/binary>>,Acc) ->
+ {lists:reverse(Acc),Rest};
+decode_constructed_indefinite(Bin,Acc) ->
+ {Tlv,Rest} = decode_primitive(Bin),
+ decode_constructed_indefinite(Rest, [Tlv|Acc]).
+
+decode_tlv(Bin) ->
+ {Form,TagNo,Len,Bin2} = decode_tag_and_length(Bin),
+ case Len of
+ indefinite ->
+ {{Form,TagNo,Len,Bin2},[]};
+ _ ->
+ <<V:Len/binary,Bin3/binary>> = Bin2,
+ {{Form,TagNo,Len,V},Bin3}
+ end.
+
+%% decode_primitive_incomplete/2 decodes an encoded message incomplete
+%% by help of the pattern attribute (first argument).
+decode_primitive_incomplete([[default,TagNo]],Bin) -> %default
+ case decode_tlv(Bin) of
+ {{Form,TagNo,Len,V},Rest} ->
+ decode_incomplete2(Form,TagNo,Len,V,[],Rest);
+ _ ->
+ %{asn1_DEFAULT,Bin}
+ asn1_NOVALUE
+ end;
+decode_primitive_incomplete([[default,TagNo,Directives]],Bin) -> %default, constructed type, Directives points into this type
+ case decode_tlv(Bin) of
+ {{Form,TagNo,Len,V},Rest} ->
+ decode_incomplete2(Form,TagNo,Len,V,Directives,Rest);
+ _ ->
+ %{asn1_DEFAULT,Bin}
+ asn1_NOVALUE
+ end;
+decode_primitive_incomplete([[opt,TagNo]],Bin) -> %optional
+ case decode_tlv(Bin) of
+ {{Form,TagNo,Len,V},Rest} ->
+ decode_incomplete2(Form,TagNo,Len,V,[],Rest);
+ _ ->
+ %{{TagNo,asn1_NOVALUE},Bin}
+ asn1_NOVALUE
+ end;
+decode_primitive_incomplete([[opt,TagNo,Directives]],Bin) -> %optional
+ case decode_tlv(Bin) of
+ {{Form,TagNo,Len,V},Rest} ->
+ decode_incomplete2(Form,TagNo,Len,V,Directives,Rest);
+ _ ->
+ %{{TagNo,asn1_NOVALUE},Bin}
+ asn1_NOVALUE
+ end;
+%% A choice alternative that shall be undecoded
+decode_primitive_incomplete([[alt_undec,TagNo]|RestAlts],Bin) ->
+% decode_incomplete_bin(Bin);
+ case decode_tlv(Bin) of
+ {{_Form,TagNo,_Len,_V},_R} ->
+ decode_incomplete_bin(Bin);
+ _ ->
+ decode_primitive_incomplete(RestAlts,Bin)
+ end;
+decode_primitive_incomplete([[alt,TagNo]|RestAlts],Bin) ->
+ case decode_tlv(Bin) of
+ {{_Form,TagNo,_Len,V},Rest} ->
+ {{TagNo,V},Rest};
+ _ ->
+ decode_primitive_incomplete(RestAlts,Bin)
+ end;
+decode_primitive_incomplete([[alt,TagNo,Directives]|RestAlts],Bin) ->
+ case decode_tlv(Bin) of
+ {{Form,TagNo,Len,V},Rest} ->
+ decode_incomplete2(Form,TagNo,Len,V,Directives,Rest);
+ _ ->
+ decode_primitive_incomplete(RestAlts,Bin)
+ end;
+decode_primitive_incomplete([[alt_parts,TagNo]|RestAlts],Bin) ->
+ case decode_tlv(Bin) of
+ {{_Form,TagNo,_Len,V},Rest} ->
+ {{TagNo,decode_parts_incomplete(V)},Rest};
+ _ ->
+ decode_primitive_incomplete(RestAlts,Bin)
+ end;
+decode_primitive_incomplete([[undec,_TagNo]|_RestTag],Bin) -> %incomlete decode
+ decode_incomplete_bin(Bin); %% use this if changing handling of
+decode_primitive_incomplete([[parts,TagNo]|_RestTag],Bin) ->
+ case decode_tlv(Bin) of
+ {{_Form,TagNo,_Len,V},Rest} ->
+ {{TagNo,decode_parts_incomplete(V)},Rest};
+ Err ->
+ {error,{asn1,"tag failure",TagNo,Err}}
+ end;
+decode_primitive_incomplete([mandatory|RestTag],Bin) ->
+ case decode_tlv(Bin) of
+ {{Form,TagNo,Len,V},Rest} ->
+ decode_incomplete2(Form,TagNo,Len,V,RestTag,Rest);
+ _ ->
+ {error,{asn1,"partial incomplete decode failure"}}
+ end;
+%% A choice that is a toptype or a mandatory component of a
+%% SEQUENCE or SET.
+decode_primitive_incomplete([[mandatory,Directives]],Bin) ->
+ case decode_tlv(Bin) of
+ {{Form,TagNo,Len,V},Rest} ->
+ decode_incomplete2(Form,TagNo,Len,V,Directives,Rest);
+ _ ->
+ {error,{asn1,"partial incomplete decode failure"}}
+ end;
+decode_primitive_incomplete([],Bin) ->
+ decode_primitive(Bin).
+
+%% decode_parts_incomplete/1 receives a number of values encoded in
+%% sequence and returns the parts as unencoded binaries
+decode_parts_incomplete(<<>>) ->
+ [];
+decode_parts_incomplete(Bin) ->
+ {ok,Rest} = skip_tag(Bin),
+ {ok,Rest2} = skip_length_and_value(Rest),
+ LenPart = size(Bin) - size(Rest2),
+ <<Part:LenPart/binary,RestBin/binary>> = Bin,
+ [Part|decode_parts_incomplete(RestBin)].
+
+
+%% decode_incomplete2 checks if V is a value of a constructed or
+%% primitive type, and continues the decode propeerly.
+decode_incomplete2(1,TagNo,indefinite,V,TagMatch,_) ->
+ %% constructed indefinite length
+ {Vlist,Rest2} = decode_constr_indef_incomplete(TagMatch,V,[]),
+ {{TagNo,Vlist},Rest2};
+decode_incomplete2(1,TagNo,_Len,V,TagMatch,Rest) ->
+ {{TagNo,decode_constructed_incomplete(TagMatch,V)},Rest};
+decode_incomplete2(0,TagNo,_Len,V,_TagMatch,Rest) ->
+ {{TagNo,V},Rest}.
+
+decode_constructed_incomplete(_TagMatch,<<>>) ->
+ [];
+decode_constructed_incomplete([mandatory|RestTag],Bin) ->
+ {Tlv,Rest} = decode_primitive(Bin),
+ [Tlv|decode_constructed_incomplete(RestTag,Rest)];
+decode_constructed_incomplete(Directives=[[Alt,_]|_],Bin)
+ when Alt == alt_undec; Alt == alt ->
+ case decode_tlv(Bin) of
+ {{_Form,TagNo,_Len,V},Rest} ->
+ case incomplete_choice_alt(TagNo,Directives) of
+ alt_undec ->
+ LenA = size(Bin)-size(Rest),
+ <<A:LenA/binary,Rest/binary>> = Bin,
+ A;
+% {UndecBin,_}=decode_incomplete_bin(Bin),
+% UndecBin;
+% [{TagNo,V}];
+ alt ->
+ {Tlv,_} = decode_primitive(V),
+ [{TagNo,Tlv}];
+ alt_parts ->
+ %{{TagNo,decode_parts_incomplete(V)},Rest}; % maybe wrong
+ [{TagNo,decode_parts_incomplete(V)}];
+ Err ->
+ {error,{asn1,"partial incomplete decode failure",Err}}
+ end;
+ _ ->
+ {error,{asn1,"partial incomplete decode failure"}}
+ end;
+decode_constructed_incomplete([TagNo|RestTag],Bin) ->
+%% {Tlv,Rest} = decode_primitive_incomplete([TagNo],Bin),
+ case decode_primitive_incomplete([TagNo],Bin) of
+ {Tlv,Rest} ->
+ [Tlv|decode_constructed_incomplete(RestTag,Rest)];
+ asn1_NOVALUE ->
+ decode_constructed_incomplete(RestTag,Bin)
+ end;
+decode_constructed_incomplete([],Bin) ->
+ {Tlv,_Rest}=decode_primitive(Bin),
+ [Tlv].
+
+decode_constr_indef_incomplete(_TagMatch,<<0,0,Rest/binary>>,Acc) ->
+ {lists:reverse(Acc),Rest};
+decode_constr_indef_incomplete([Tag|RestTags],Bin,Acc) ->
+% {Tlv,Rest} = decode_primitive_incomplete([Tag],Bin),
+ case decode_primitive_incomplete([Tag],Bin) of
+ {Tlv,Rest} ->
+ decode_constr_indef_incomplete(RestTags,Rest,[Tlv|Acc]);
+ asn1_NOVALUE ->
+ decode_constr_indef_incomplete(RestTags,Bin,Acc)
+ end.
+
+
+decode_incomplete_bin(Bin) ->
+ {ok,Rest} = skip_tag(Bin),
+ {ok,Rest2} = skip_length_and_value(Rest),
+ IncLen = size(Bin) - size(Rest2),
+ <<IncBin:IncLen/binary,Ret/binary>> = Bin,
+ {IncBin,Ret}.
+
+incomplete_choice_alt(TagNo,[[Alt,TagNo]|_Directives]) ->
+ Alt;
+incomplete_choice_alt(TagNo,[_H|Directives]) ->
+ incomplete_choice_alt(TagNo,Directives);
+incomplete_choice_alt(_,[]) ->
+ error.
+
+
+%% skip_tag and skip_length_and_value are rutines used both by
+%% decode_partial_incomplete and decode_partial (decode/2).
+
+skip_tag(<<_:3,31:5,Rest/binary>>)->
+ skip_long_tag(Rest);
+skip_tag(<<_:3,_Tag:5,Rest/binary>>) ->
+ {ok,Rest}.
+
+skip_long_tag(<<1:1,_:7,Rest/binary>>) ->
+ skip_long_tag(Rest);
+skip_long_tag(<<0:1,_:7,Rest/binary>>) ->
+ {ok,Rest}.
+
+skip_length_and_value(Binary) ->
+ case decode_length(Binary) of
+ {indefinite,RestBinary} ->
+ skip_indefinite_value(RestBinary);
+ {Length,RestBinary} ->
+ <<_:Length/unit:8,Rest/binary>> = RestBinary,
+ {ok,Rest}
+ end.
+
+skip_indefinite_value(<<0,0,Rest/binary>>) ->
+ {ok,Rest};
+skip_indefinite_value(Binary) ->
+ {ok,RestBinary}=skip_tag(Binary),
+ {ok,RestBinary2} = skip_length_and_value(RestBinary),
+ skip_indefinite_value(RestBinary2).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% match_tags takes a Tlv (Tag, Length, Value) structure and matches
+%% it with the tags in TagList. If the tags does not match the function
+%% crashes otherwise it returns the remaining Tlv after that the tags have
+%% been removed.
+%%
+%% match_tags(Tlv, TagList)
+%%
+
+
+match_tags({T,V}, [T|Tt]) ->
+ match_tags(V,Tt);
+match_tags([{T,V}],[T|Tt]) ->
+ match_tags(V, Tt);
+match_tags(Vlist = [{T,_V}|_], [T]) ->
+ Vlist;
+match_tags(Tlv, []) ->
+ Tlv;
+match_tags({Tag,_V},[T|_Tt]) ->
+ {error,{asn1,{wrong_tag,{Tag,T}}}}.
+
+
+cindex(Ix,Val,Cname) ->
+ case element(Ix,Val) of
+ {Cname,Val2} -> Val2;
+ X -> X
+ end.
+
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+%% Optionals, preset not filled optionals with asn1_NOVALUE
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+
+% converts a list to a record if necessary
+list_to_record(Name,List) when list(List) ->
+ list_to_tuple([Name|List]);
+list_to_record(_Name,Tuple) when tuple(Tuple) ->
+ Tuple.
+
+
+fixoptionals(OptList,Val) when list(Val) ->
+ fixoptionals(OptList,Val,1,[],[]).
+
+fixoptionals([{Name,Pos}|Ot],[{Name,Val}|Vt],_Opt,Acc1,Acc2) ->
+ fixoptionals(Ot,Vt,Pos+1,[1|Acc1],[{Name,Val}|Acc2]);
+fixoptionals([{_Name,Pos}|Ot],V,Pos,Acc1,Acc2) ->
+ fixoptionals(Ot,V,Pos+1,[0|Acc1],[asn1_NOVALUE|Acc2]);
+fixoptionals(O,[Vh|Vt],Pos,Acc1,Acc2) ->
+ fixoptionals(O,Vt,Pos+1,Acc1,[Vh|Acc2]);
+fixoptionals([],[Vh|Vt],Pos,Acc1,Acc2) ->
+ fixoptionals([],Vt,Pos+1,Acc1,[Vh|Acc2]);
+fixoptionals([],[],_,_Acc1,Acc2) ->
+ % return Val as a record
+ list_to_tuple([asn1_RECORDNAME|lists:reverse(Acc2)]).
+
+
+%%encode_tag(TagClass(?UNI, APP etc), Form (?PRIM etx), TagInteger) ->
+%% 8bit Int | binary
+encode_tag_val({Class, Form, TagNo}) when (TagNo =< 30) ->
+ <<(Class bsr 6):2,(Form bsr 5):1,TagNo:5>>;
+
+encode_tag_val({Class, Form, TagNo}) ->
+ {Octets,_Len} = mk_object_val(TagNo),
+ BinOct = list_to_binary(Octets),
+ <<(Class bsr 6):2, (Form bsr 5):1, 31:5,BinOct/binary>>;
+
+%% asumes whole correct tag bitpattern, multiple of 8
+encode_tag_val(Tag) when (Tag =< 255) -> Tag; %% anv�nds denna funktion??!!
+%% asumes correct bitpattern of 0-5
+encode_tag_val(Tag) -> encode_tag_val2(Tag,[]).
+
+encode_tag_val2(Tag, OctAck) when (Tag =< 255) ->
+ [Tag | OctAck];
+encode_tag_val2(Tag, OctAck) ->
+ encode_tag_val2(Tag bsr 8, [255 band Tag | OctAck]).
+
+
+%%===============================================================================
+%% Decode a tag
+%%
+%% decode_tag(OctetListBuffer) -> {{Form, (Class bsl 16)+ TagNo}, RestOfBuffer, RemovedBytes}
+%%===============================================================================
+
+decode_tag_and_length(<<Class:2, Form:1, TagNo:5, 0:1, Length:7, RestBuffer/binary>>) when TagNo < 31 ->
+ {Form, (Class bsl 16) + TagNo, Length, RestBuffer};
+decode_tag_and_length(<<Class:2, Form:1, TagNo:5, 1:1, 0:7, T/binary>>) when TagNo < 31 ->
+ {Form, (Class bsl 16) + TagNo, indefinite, T};
+decode_tag_and_length(<<Class:2, Form:1, TagNo:5, 1:1, LL:7, T/binary>>) when TagNo < 31 ->
+ <<Length:LL/unit:8,RestBuffer/binary>> = T,
+ {Form, (Class bsl 16) + TagNo, Length, RestBuffer};
+decode_tag_and_length(<<Class:2, Form:1, 31:5, 0:1, TagNo:7, 0:1, Length:7, RestBuffer/binary>>) ->
+ {Form, (Class bsl 16) + TagNo, Length, RestBuffer};
+decode_tag_and_length(<<Class:2, Form:1, 31:5, 0:1, TagNo:7, 1:1, 0:7, T/binary>>) ->
+ {Form, (Class bsl 16) + TagNo, indefinite, T};
+decode_tag_and_length(<<Class:2, Form:1, 31:5, 0:1, TagNo:7, 1:1, LL:7, T/binary>>) ->
+ <<Length:LL/unit:8,RestBuffer/binary>> = T,
+ {Form, (Class bsl 16) + TagNo, Length, RestBuffer};
+decode_tag_and_length(<<Class:2, Form:1, 31:5, Buffer/binary>>) ->
+ {TagNo, Buffer1} = decode_tag(Buffer, 0),
+ {Length, RestBuffer} = decode_length(Buffer1),
+ {Form, (Class bsl 16) + TagNo, Length, RestBuffer}.
+
+
+
+%% last partial tag
+decode_tag(<<0:1,PartialTag:7, Buffer/binary>>, TagAck) ->
+ TagNo = (TagAck bsl 7) bor PartialTag,
+ %%<<TagNo>> = <<TagAck:1, PartialTag:7>>,
+ {TagNo, Buffer};
+% more tags
+decode_tag(<<_:1,PartialTag:7, Buffer/binary>>, TagAck) ->
+ TagAck1 = (TagAck bsl 7) bor PartialTag,
+ %%<<TagAck1:16>> = <<TagAck:1, PartialTag:7,0:8>>,
+ decode_tag(Buffer, TagAck1).
+
+
+%%=======================================================================
+%%
+%% Encode all tags in the list Tags and return a possibly deep list of
+%% bytes with tag and length encoded
+%% The taglist must be in reverse order (fixed by the asn1 compiler)
+%% e.g [T1,T2] will result in
+%% {[EncodedT2,EncodedT1|BytesSoFar],LenSoFar+LenT2+LenT1}
+%%
+
+encode_tags([Tag|Trest], BytesSoFar, LenSoFar) ->
+% remove {Bytes1,L1} = encode_one_tag(Tag),
+ {Bytes2,L2} = encode_length(LenSoFar),
+ encode_tags(Trest, [Tag,Bytes2|BytesSoFar],
+ LenSoFar + size(Tag) + L2);
+encode_tags([], BytesSoFar, LenSoFar) ->
+ {BytesSoFar,LenSoFar}.
+
+encode_tags(TagIn, {BytesSoFar,LenSoFar}) ->
+ encode_tags(TagIn, BytesSoFar, LenSoFar).
+
+% encode_one_tag(#tag{class=Class,number=No,type=Type, form = Form}) ->
+% NewForm = case Type of
+% 'EXPLICIT' ->
+% ?CONSTRUCTED;
+% _ ->
+% Form
+% end,
+% Bytes = encode_tag_val({Class,NewForm,No}),
+% {Bytes,size(Bytes)}.
+
+
+%%===============================================================================
+%%
+%% This comment is valid for all the encode/decode functions
+%%
+%% C = Constraint -> typically {'ValueRange',LowerBound,UpperBound}
+%% used for PER-coding but not for BER-coding.
+%%
+%% Val = Value. If Val is an atom then it is a symbolic integer value
+%% (i.e the atom must be one of the names in the NamedNumberList).
+%% The NamedNumberList is used to translate the atom to an integer value
+%% before encoding.
+%%
+%%===============================================================================
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_open_type(Value) -> io_list (i.e nested list with integers, binaries)
+%% Value = list of bytes of an already encoded value (the list must be flat)
+%% | binary
+
+%%
+encode_open_type(Val) when list(Val) ->
+% {Val,length(Val)};
+ encode_open_type(list_to_binary(Val));
+encode_open_type(Val) ->
+ {Val, size(Val)}.
+
+%%
+encode_open_type(Val, T) when list(Val) ->
+ encode_open_type(list_to_binary(Val),T);
+encode_open_type(Val,[]) ->
+ {Val, size(Val)};
+encode_open_type(Val,Tag) ->
+ encode_tags(Tag,Val, size(Val)).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% decode_open_type(Tlv, TagIn) -> Value
+%% Tlv = {Tag,V} | V where V -> binary()
+%% TagIn = [TagVal] where TagVal -> int()
+%% Value = binary with decoded data (which must be decoded again as some type)
+%%
+decode_open_type(Tlv, TagIn) ->
+ case match_tags(Tlv,TagIn) of
+ Bin when binary(Bin) ->
+ {InnerTlv,_} = decode(Bin),
+ InnerTlv;
+ TlvBytes -> TlvBytes
+ end.
+
+
+decode_open_type_as_binary(Tlv,TagIn)->
+ case match_tags(Tlv,TagIn) of
+ V when binary(V) ->
+ V;
+ [Tlv2] -> encode(Tlv2);
+ Tlv2 -> encode(Tlv2)
+ end.
+
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+%% Boolean, ITU_T X.690 Chapter 8.2
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+
+%%===============================================================================
+%% encode_boolean(Integer, ReversedTagList) -> {[Octet],Len}
+%%===============================================================================
+
+encode_boolean({Name, Val}, TagIn) when atom(Name) ->
+ encode_boolean(Val, TagIn);
+encode_boolean(true, TagIn) ->
+ encode_tags(TagIn, [16#FF],1);
+encode_boolean(false, TagIn) ->
+ encode_tags(TagIn, [0],1);
+encode_boolean(X,_) ->
+ exit({error,{asn1, {encode_boolean, X}}}).
+
+
+%%===============================================================================
+%% decode_boolean(BuffList, HasTag, TotalLen) -> {true, Remain, RemovedBytes} |
+%% {false, Remain, RemovedBytes}
+%%===============================================================================
+decode_boolean(Tlv,TagIn) ->
+ Val = match_tags(Tlv, TagIn),
+ case Val of
+ <<0:8>> ->
+ false;
+ <<_:8>> ->
+ true;
+ _ ->
+ exit({error,{asn1, {decode_boolean, Val}}})
+ end.
+
+
+%%===========================================================================
+%% Integer, ITU_T X.690 Chapter 8.3
+
+%% encode_integer(Constraint, Value, Tag) -> [octet list]
+%% encode_integer(Constraint, Name, NamedNumberList, Tag) -> [octet list]
+%% Value = INTEGER | {Name,INTEGER}
+%% Tag = tag | notag
+%%===========================================================================
+
+encode_integer(C, Val, Tag) when integer(Val) ->
+ encode_tags(Tag, encode_integer(C, Val));
+encode_integer(C,{Name,Val},Tag) when atom(Name) ->
+ encode_integer(C,Val,Tag);
+encode_integer(_C, Val, _Tag) ->
+ exit({error,{asn1, {encode_integer, Val}}}).
+
+
+
+encode_integer(C, Val, NamedNumberList, Tag) when atom(Val) ->
+ case lists:keysearch(Val, 1, NamedNumberList) of
+ {value,{_, NewVal}} ->
+ encode_tags(Tag, encode_integer(C, NewVal));
+ _ ->
+ exit({error,{asn1, {encode_integer_namednumber, Val}}})
+ end;
+encode_integer(C,{_Name,Val},NamedNumberList,Tag) ->
+ encode_integer(C,Val,NamedNumberList,Tag);
+encode_integer(C, Val, _NamedNumberList, Tag) ->
+ encode_tags(Tag, encode_integer(C, Val)).
+
+
+encode_integer(_, Val) ->
+ Bytes =
+ if
+ Val >= 0 ->
+ encode_integer_pos(Val, []);
+ true ->
+ encode_integer_neg(Val, [])
+ end,
+ {Bytes,length(Bytes)}.
+
+encode_integer_pos(0, L=[B|_Acc]) when B < 128 ->
+ L;
+encode_integer_pos(N, Acc) ->
+ encode_integer_pos((N bsr 8), [N band 16#ff| Acc]).
+
+encode_integer_neg(-1, L=[B1|_T]) when B1 > 127 ->
+ L;
+encode_integer_neg(N, Acc) ->
+ encode_integer_neg(N bsr 8, [N band 16#ff|Acc]).
+
+%%===============================================================================
+%% decode integer
+%% (Buffer, Range, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
+%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
+%%===============================================================================
+
+decode_integer(Tlv,Range,NamedNumberList,TagIn) ->
+ V = match_tags(Tlv,TagIn),
+ Int = decode_integer(V),
+ range_check_integer(Int,Range),
+ number2name(Int,NamedNumberList).
+
+decode_integer(Tlv,Range,TagIn) ->
+ V = match_tags(Tlv, TagIn),
+ Int = decode_integer(V),
+ range_check_integer(Int,Range),
+ Int.
+
+%% decoding postitive integer values.
+decode_integer(Bin = <<0:1,_:7,_/binary>>) ->
+ Len = size(Bin),
+% <<Int:Len/unit:8,Buffer2/binary>> = Bin,
+ <<Int:Len/unit:8>> = Bin,
+ Int;
+%% decoding negative integer values.
+decode_integer(Bin = <<1:1,B2:7,Bs/binary>>) ->
+ Len = size(Bin),
+% <<N:Len/unit:8,Buffer2/binary>> = <<B2,Bs/binary>>,
+ <<N:Len/unit:8>> = <<B2,Bs/binary>>,
+ Int = N - (1 bsl (8 * Len - 1)),
+ Int.
+
+range_check_integer(Int,Range) ->
+ case Range of
+ [] -> % No length constraint
+ Int;
+ {Lb,Ub} when Int >= Lb, Ub >= Int -> % variable length constraint
+ Int;
+ Int -> % fixed value constraint
+ Int;
+ {_,_} ->
+ exit({error,{asn1,{integer_range,Range,Int}}});
+ SingleValue when integer(SingleValue) ->
+ exit({error,{asn1,{integer_range,Range,Int}}});
+ _ -> % some strange constraint that we don't support yet
+ Int
+ end.
+
+number2name(Int,[]) ->
+ Int;
+number2name(Int,NamedNumberList) ->
+ case lists:keysearch(Int, 2, NamedNumberList) of
+ {value,{NamedVal, _}} ->
+ NamedVal;
+ _ ->
+ Int
+ end.
+
+
+%%============================================================================
+%% Enumerated value, ITU_T X.690 Chapter 8.4
+
+%% encode enumerated value
+%%============================================================================
+encode_enumerated(Val, TagIn) when integer(Val)->
+ encode_tags(TagIn, encode_integer(false,Val));
+encode_enumerated({Name,Val}, TagIn) when atom(Name) ->
+ encode_enumerated(Val, TagIn).
+
+%% The encode_enumerated functions below this line can be removed when the
+%% new code generation is stable. (the functions might have to be kept here
+%% a while longer for compatibility reasons)
+
+encode_enumerated(C, Val, {NamedNumberList,ExtList}, TagIn) when atom(Val) ->
+ case catch encode_enumerated(C, Val, NamedNumberList, TagIn) of
+ {'EXIT',_} -> encode_enumerated(C, Val, ExtList, TagIn);
+ Result -> Result
+ end;
+
+encode_enumerated(C, Val, NamedNumberList, TagIn) when atom(Val) ->
+ case lists:keysearch(Val, 1, NamedNumberList) of
+ {value, {_, NewVal}} ->
+ encode_tags(TagIn, encode_integer(C, NewVal));
+ _ ->
+ exit({error,{asn1, {enumerated_not_in_range, Val}}})
+ end;
+
+encode_enumerated(C, {asn1_enum, Val}, {_,_}, TagIn) when integer(Val) ->
+ encode_tags(TagIn, encode_integer(C,Val));
+
+encode_enumerated(C, {Name,Val}, NamedNumberList, TagIn) when atom(Name) ->
+ encode_enumerated(C, Val, NamedNumberList, TagIn);
+
+encode_enumerated(_C, Val, _NamedNumberList, _TagIn) ->
+ exit({error,{asn1, {enumerated_not_namednumber, Val}}}).
+
+
+
+%%============================================================================
+%% decode enumerated value
+%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> Value
+%%===========================================================================
+decode_enumerated(Tlv, Range, NamedNumberList, Tags) ->
+ Buffer = match_tags(Tlv,Tags),
+ decode_enumerated_notag(Buffer, Range, NamedNumberList, Tags).
+
+decode_enumerated_notag(Buffer, _Range, {NamedNumberList,ExtList}, _Tags) ->
+
+ IVal = decode_integer2(size(Buffer), Buffer),
+ case decode_enumerated1(IVal, NamedNumberList) of
+ {asn1_enum,IVal} ->
+ decode_enumerated1(IVal,ExtList);
+ EVal ->
+ EVal
+ end;
+decode_enumerated_notag(Buffer, _Range, NNList, _Tags) ->
+ IVal = decode_integer2(size(Buffer), Buffer),
+ case decode_enumerated1(IVal, NNList) of
+ {asn1_enum,_} ->
+ exit({error,{asn1, {illegal_enumerated, IVal}}});
+ EVal ->
+ EVal
+ end.
+
+decode_enumerated1(Val, NamedNumberList) ->
+ %% it must be a named integer
+ case lists:keysearch(Val, 2, NamedNumberList) of
+ {value,{NamedVal, _}} ->
+ NamedVal;
+ _ ->
+ {asn1_enum,Val}
+ end.
+
+
+%%============================================================================
+%%
+%% Real value, ITU_T X.690 Chapter 8.5
+%%============================================================================
+%%
+%% encode real value
+%%============================================================================
+
+%% only base 2 internally so far!!
+encode_real(0, TagIn) ->
+ encode_tags(TagIn, {[],0});
+encode_real('PLUS-INFINITY', TagIn) ->
+ encode_tags(TagIn, {[64],1});
+encode_real('MINUS-INFINITY', TagIn) ->
+ encode_tags(TagIn, {[65],1});
+encode_real(Val, TagIn) when tuple(Val)->
+ encode_tags(TagIn, encode_real(Val)).
+
+%%%%%%%%%%%%%%
+%% not optimal efficient..
+%% only base 2 of Mantissa encoding!
+%% only base 2 of ExpBase encoding!
+encode_real({Man, Base, Exp}) ->
+%% io:format("Mantissa: ~w Base: ~w, Exp: ~w~n",[Man, Base, Exp]),
+
+ OctExp = if Exp >= 0 -> list_to_binary(encode_integer_pos(Exp, []));
+ true -> list_to_binary(encode_integer_neg(Exp, []))
+ end,
+%% ok = io:format("OctExp: ~w~n",[OctExp]),
+ SignBit = if Man > 0 -> 0; % bit 7 is pos or neg, no Zeroval
+ true -> 1
+ end,
+%% ok = io:format("SignBitMask: ~w~n",[SignBitMask]),
+ InBase = if Base =:= 2 -> 0; % bit 6,5: only base 2 this far!
+ true ->
+ exit({error,{asn1, {encode_real_non_supported_encodeing, Base}}})
+ end,
+ SFactor = 0, % bit 4,3: no scaling since only base 2
+ OctExpLen = size(OctExp),
+ if OctExpLen > 255 ->
+ exit({error,{asn1, {to_big_exp_in_encode_real, OctExpLen}}});
+ true -> true %% make real assert later..
+ end,
+ {LenCode, EOctets} = case OctExpLen of % bit 2,1
+ 1 -> {0, OctExp};
+ 2 -> {1, OctExp};
+ 3 -> {2, OctExp};
+ _ -> {3, <<OctExpLen, OctExp/binary>>}
+ end,
+ FirstOctet = <<1:1,SignBit:1,InBase:2,SFactor:2,LenCode:2>>,
+ OctMantissa = if Man > 0 -> list_to_binary(minimum_octets(Man));
+ true -> list_to_binary(minimum_octets(-(Man))) % signbit keeps track of sign
+ end,
+ %% ok = io:format("LenMask: ~w EOctets: ~w~nFirstOctet: ~w OctMantissa: ~w OctExpLen: ~w~n", [LenMask, EOctets, FirstOctet, OctMantissa, OctExpLen]),
+ Bin = <<FirstOctet/binary, EOctets/binary, OctMantissa/binary>>,
+ {Bin, size(Bin)}.
+
+
+%%============================================================================
+%% decode real value
+%%
+%% decode_real([OctetBufferList], tuple|value, tag|notag) ->
+%% {{Mantissa, Base, Exp} | realval | PLUS-INFINITY | MINUS-INFINITY | 0,
+%% RestBuff}
+%%
+%% only for base 2 decoding sofar!!
+%%============================================================================
+
+decode_real(Tlv, Form, Tags) ->
+ Buffer = match_tags(Tlv,Tags),
+ decode_real_notag(Buffer, Form).
+
+decode_real_notag(_Buffer, _Form) ->
+ exit({error,{asn1, {unimplemented,real}}}).
+%% decode_real2(Buffer, Form, size(Buffer)).
+
+% decode_real2(Buffer, Form, Len) ->
+% <<First, Buffer2/binary>> = Buffer,
+% if
+% First =:= 2#01000000 -> {'PLUS-INFINITY', Buffer2};
+% First =:= 2#01000001 -> {'MINUS-INFINITY', Buffer2};
+% First =:= 2#00000000 -> {0, Buffer2};
+% true ->
+% %% have some check here to verify only supported bases (2)
+% <<B7:1,B6:1,B5_4:2,B3_2:2,B1_0:2>> = <<First>>,
+% Sign = B6,
+% Base =
+% case B5_4 of
+% 0 -> 2; % base 2, only one so far
+% _ -> exit({error,{asn1, {non_supported_base, First}}})
+% end,
+% ScalingFactor =
+% case B3_2 of
+% 0 -> 0; % no scaling so far
+% _ -> exit({error,{asn1, {non_supported_scaling, First}}})
+% end,
+
+% {FirstLen,Exp,Buffer3} =
+% case B1_0 of
+% 0 ->
+% <<_:1/unit:8,Buffer21/binary>> = Buffer2,
+% {2, decode_integer2(1, Buffer2),Buffer21};
+% 1 ->
+% <<_:2/unit:8,Buffer21/binary>> = Buffer2,
+% {3, decode_integer2(2, Buffer2)};
+% 2 ->
+% <<_:3/unit:8,Buffer21/binary>> = Buffer2,
+% {4, decode_integer2(3, Buffer2)};
+% 3 ->
+% <<ExpLen1,RestBuffer/binary>> = Buffer2,
+% <<_:ExpLen1/unit:8,RestBuffer2/binary>> = RestBuffer,
+% { ExpLen1 + 2,
+% decode_integer2(ExpLen1, RestBuffer, RemBytes1),
+% RestBuffer2}
+% end,
+% Length = Len - FirstLen,
+% <<LongInt:Length/unit:8,RestBuff/binary>> = Buffer3,
+% {Mantissa, Buffer4} =
+% if Sign =:= 0 ->
+
+% {LongInt, RestBuff};% sign plus,
+% true ->
+
+% {-LongInt, RestBuff}% sign minus
+% end,
+% case Form of
+% tuple ->
+% {Val,Buf,RemB} = Exp,
+% {{Mantissa, Base, {Val,Buf}}, Buffer4, RemBytes2+RemBytes3};
+% _value ->
+% comming
+% end
+% end.
+
+
+%%============================================================================
+%% Bitstring value, ITU_T X.690 Chapter 8.6
+%%
+%% encode bitstring value
+%%
+%% bitstring NamedBitList
+%% Val can be of:
+%% - [identifiers] where only named identifers are set to one,
+%% the Constraint must then have some information of the
+%% bitlength.
+%% - [list of ones and zeroes] all bits
+%% - integer value representing the bitlist
+%% C is constrint Len, only valid when identifiers
+%%============================================================================
+
+encode_bit_string(C,Bin={Unused,BinBits},NamedBitList,TagIn) when integer(Unused), binary(BinBits) ->
+ encode_bin_bit_string(C,Bin,NamedBitList,TagIn);
+encode_bit_string(C, [FirstVal | RestVal], NamedBitList, TagIn) when atom(FirstVal) ->
+ encode_bit_string_named(C, [FirstVal | RestVal], NamedBitList, TagIn);
+
+encode_bit_string(C, [{bit,X} | RestVal], NamedBitList, TagIn) ->
+ encode_bit_string_named(C, [{bit,X} | RestVal], NamedBitList, TagIn);
+
+encode_bit_string(C, [FirstVal| RestVal], NamedBitList, TagIn) when integer(FirstVal) ->
+ encode_bit_string_bits(C, [FirstVal | RestVal], NamedBitList, TagIn);
+
+encode_bit_string(_C, 0, _NamedBitList, TagIn) ->
+ encode_tags(TagIn, <<0>>,1);
+
+encode_bit_string(_C, [], _NamedBitList, TagIn) ->
+ encode_tags(TagIn, <<0>>,1);
+
+encode_bit_string(C, IntegerVal, NamedBitList, TagIn) when integer(IntegerVal) ->
+ BitListVal = int_to_bitlist(IntegerVal),
+ encode_bit_string_bits(C, BitListVal, NamedBitList, TagIn);
+
+encode_bit_string(C, {Name,BitList}, NamedBitList, TagIn) when atom(Name) ->
+ encode_bit_string(C, BitList, NamedBitList, TagIn).
+
+
+
+int_to_bitlist(0) ->
+ [];
+int_to_bitlist(Int) when integer(Int), Int >= 0 ->
+ [Int band 1 | int_to_bitlist(Int bsr 1)].
+
+
+%%=================================================================
+%% Encode BIT STRING of the form {Unused,BinBits}.
+%% Unused is the number of unused bits in the last byte in BinBits
+%% and BinBits is a binary representing the BIT STRING.
+%%=================================================================
+encode_bin_bit_string(C,{Unused,BinBits},_NamedBitList,TagIn)->
+ case get_constraint(C,'SizeConstraint') of
+ no ->
+ remove_unused_then_dotag(TagIn, Unused, BinBits);
+ {_Min,Max} ->
+ BBLen = (size(BinBits)*8)-Unused,
+ if
+ BBLen > Max ->
+ exit({error,{asn1,
+ {bitstring_length,
+ {{was,BBLen},{maximum,Max}}}}});
+ true ->
+ remove_unused_then_dotag(TagIn, Unused, BinBits)
+ end;
+ Size ->
+ case ((size(BinBits)*8)-Unused) of
+ BBSize when BBSize =< Size ->
+ remove_unused_then_dotag(TagIn, Unused, BinBits);
+ BBSize ->
+ exit({error,{asn1,
+ {bitstring_length,
+ {{was,BBSize},{should_be,Size}}}}})
+ end
+ end.
+
+remove_unused_then_dotag(TagIn,Unused,BinBits) ->
+ case Unused of
+ 0 when (size(BinBits) == 0) ->
+ encode_tags(TagIn,<<0>>,1);
+ 0 ->
+ Bin = <<Unused,BinBits/binary>>,
+ encode_tags(TagIn,Bin,size(Bin));
+ Num ->
+ N = (size(BinBits)-1),
+ <<BBits:N/binary,LastByte>> = BinBits,
+ encode_tags(TagIn,
+ [Unused,binary_to_list(BBits) ++[(LastByte bsr Num) bsl Num]],
+ 1+size(BinBits))
+ end.
+
+
+%%=================================================================
+%% Encode named bits
+%%=================================================================
+
+encode_bit_string_named(C, [FirstVal | RestVal], NamedBitList, TagIn) ->
+ ToSetPos = get_all_bitposes([FirstVal | RestVal], NamedBitList, []),
+ Size =
+ case get_constraint(C,'SizeConstraint') of
+ no ->
+ lists:max(ToSetPos)+1;
+ {_Min,Max} ->
+ Max;
+ TSize ->
+ TSize
+ end,
+ BitList = make_and_set_list(Size, ToSetPos, 0),
+ {Len, Unused, OctetList} = encode_bitstring(BitList),
+ encode_tags(TagIn, [Unused|OctetList],Len+1).
+
+
+%%----------------------------------------
+%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
+%% [sorted_list_of_bitpositions_to_set]
+%%----------------------------------------
+
+get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
+ get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
+get_all_bitposes([Val | Rest], NamedBitList, Ack) when atom(Val) ->
+ case lists:keysearch(Val, 1, NamedBitList) of
+ {value, {_ValName, ValPos}} ->
+ get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
+ _ ->
+ exit({error,{asn1, {bitstring_namedbit, Val}}})
+ end;
+get_all_bitposes([], _NamedBitList, Ack) ->
+ lists:sort(Ack).
+
+
+%%----------------------------------------
+%% make_and_set_list(Len of list to return, [list of positions to set to 1])->
+%% returns list of Len length, with all in SetPos set.
+%% in positioning in list the first element is 0, the second 1 etc.., but
+%% Len will make a list of length Len, not Len + 1.
+%% BitList = make_and_set_list(C, ToSetPos, 0),
+%%----------------------------------------
+
+make_and_set_list(0, [], _) -> [];
+make_and_set_list(0, _, _) ->
+ exit({error,{asn1,bitstring_sizeconstraint}});
+make_and_set_list(Len, [XPos|SetPos], XPos) ->
+ [1 | make_and_set_list(Len - 1, SetPos, XPos + 1)];
+make_and_set_list(Len, [Pos|SetPos], XPos) ->
+ [0 | make_and_set_list(Len - 1, [Pos | SetPos], XPos + 1)];
+make_and_set_list(Len, [], XPos) ->
+ [0 | make_and_set_list(Len - 1, [], XPos + 1)].
+
+
+
+
+
+
+%%=================================================================
+%% Encode bit string for lists of ones and zeroes
+%%=================================================================
+encode_bit_string_bits(C, BitListVal, _NamedBitList, TagIn) when list(BitListVal) ->
+ case get_constraint(C,'SizeConstraint') of
+ no ->
+ {Len, Unused, OctetList} = encode_bitstring(BitListVal),
+ %%add unused byte to the Len
+ encode_tags(TagIn, [Unused | OctetList], Len+1);
+ Constr={Min,Max} when integer(Min),integer(Max) ->
+ encode_constr_bit_str_bits(Constr,BitListVal,TagIn);
+ {Constr={_,_},[]} ->%Constr={Min,Max}
+ %% constraint with extension mark
+ encode_constr_bit_str_bits(Constr,BitListVal,TagIn);
+ Constr={{_,_},{_,_}} ->%{{Min1,Max1},{Min2,Max2}}
+ %% constraint with extension mark
+ encode_constr_bit_str_bits(Constr,BitListVal,TagIn);
+ Size ->
+ case length(BitListVal) of
+ BitSize when BitSize == Size ->
+ {Len, Unused, OctetList} = encode_bitstring(BitListVal),
+ %%add unused byte to the Len
+ encode_tags(TagIn, [Unused | OctetList], Len+1);
+ BitSize when BitSize < Size ->
+ PaddedList = pad_bit_list(Size-BitSize,BitListVal),
+ {Len, Unused, OctetList} = encode_bitstring(PaddedList),
+ %%add unused byte to the Len
+ encode_tags(TagIn, [Unused | OctetList], Len+1);
+ BitSize ->
+ exit({error,{asn1,
+ {bitstring_length, {{was,BitSize},{should_be,Size}}}}})
+ end
+
+ end.
+
+encode_constr_bit_str_bits({_Min,Max},BitListVal,TagIn) ->
+ BitLen = length(BitListVal),
+ if
+ BitLen > Max ->
+ exit({error,{asn1,{bitstring_length,{{was,BitLen},
+ {maximum,Max}}}}});
+ true ->
+ {Len, Unused, OctetList} = encode_bitstring(BitListVal),
+ %%add unused byte to the Len
+ encode_tags(TagIn, [Unused, OctetList], Len+1)
+ end;
+encode_constr_bit_str_bits({{_Min1,Max1},{Min2,Max2}},BitListVal,TagIn) ->
+ BitLen = length(BitListVal),
+ case BitLen of
+ Len when Len > Max2 ->
+ exit({error,{asn1,{bitstring_length,{{was,BitLen},
+ {maximum,Max2}}}}});
+ Len when Len > Max1, Len < Min2 ->
+ exit({error,{asn1,{bitstring_length,{{was,BitLen},
+ {not_allowed_interval,
+ Max1,Min2}}}}});
+ _ ->
+ {Len, Unused, OctetList} = encode_bitstring(BitListVal),
+ %%add unused byte to the Len
+ encode_tags(TagIn, [Unused, OctetList], Len+1)
+ end.
+
+%% returns a list of length Size + length(BitListVal), with BitListVal
+%% as the most significant elements followed by padded zero elements
+pad_bit_list(Size,BitListVal) ->
+ Tail = lists:duplicate(Size,0),
+ lists:append(BitListVal,Tail).
+
+%%=================================================================
+%% Do the actual encoding
+%% ([bitlist]) -> {ListLen, UnusedBits, OctetList}
+%%=================================================================
+
+encode_bitstring([B8, B7, B6, B5, B4, B3, B2, B1 | Rest]) ->
+ Val = (B8 bsl 7) bor (B7 bsl 6) bor (B6 bsl 5) bor (B5 bsl 4) bor
+ (B4 bsl 3) bor (B3 bsl 2) bor (B2 bsl 1) bor B1,
+ encode_bitstring(Rest, [Val], 1);
+encode_bitstring(Val) ->
+ {Unused, Octet} = unused_bitlist(Val, 7, 0),
+ {1, Unused, [Octet]}.
+
+encode_bitstring([B8, B7, B6, B5, B4, B3, B2, B1 | Rest], Ack, Len) ->
+ Val = (B8 bsl 7) bor (B7 bsl 6) bor (B6 bsl 5) bor (B5 bsl 4) bor
+ (B4 bsl 3) bor (B3 bsl 2) bor (B2 bsl 1) bor B1,
+ encode_bitstring(Rest, [Ack | [Val]], Len + 1);
+%%even multiple of 8 bits..
+encode_bitstring([], Ack, Len) ->
+ {Len, 0, Ack};
+%% unused bits in last octet
+encode_bitstring(Rest, Ack, Len) ->
+% io:format("uneven ~w ~w ~w~n",[Rest, Ack, Len]),
+ {Unused, Val} = unused_bitlist(Rest, 7, 0),
+ {Len + 1, Unused, [Ack | [Val]]}.
+
+%%%%%%%%%%%%%%%%%%
+%% unused_bitlist([list of ones and zeros <= 7], 7, []) ->
+%% {Unused bits, Last octet with bits moved to right}
+unused_bitlist([], Trail, Ack) ->
+ {Trail + 1, Ack};
+unused_bitlist([Bit | Rest], Trail, Ack) ->
+%% io:format("trail Bit: ~w Rest: ~w Trail: ~w Ack:~w~n",[Bit, Rest, Trail, Ack]),
+ unused_bitlist(Rest, Trail - 1, (Bit bsl Trail) bor Ack).
+
+
+%%============================================================================
+%% decode bitstring value
+%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
+%%============================================================================
+
+decode_compact_bit_string(Buffer, Range, NamedNumberList, Tags) ->
+% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_BIT_STRING}),
+ decode_restricted_string(Buffer, Range, ?N_BIT_STRING, Tags,
+ NamedNumberList,bin).
+
+decode_bit_string(Buffer, Range, NamedNumberList, Tags) ->
+% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_BIT_STRING}),
+ decode_restricted_string(Buffer, Range, ?N_BIT_STRING, Tags,
+ NamedNumberList,old).
+
+
+decode_bit_string2(<<0>>,_NamedNumberList,BinOrOld) ->
+ case BinOrOld of
+ bin ->
+ {0,<<>>};
+ _ ->
+ []
+ end;
+decode_bit_string2(<<Unused,Bits/binary>>,NamedNumberList,BinOrOld) ->
+ case NamedNumberList of
+ [] ->
+ case BinOrOld of
+ bin ->
+ {Unused,Bits};
+ _ ->
+ decode_bitstring2(size(Bits), Unused, Bits)
+ end;
+ _ ->
+ BitString = decode_bitstring2(size(Bits), Unused, Bits),
+ decode_bitstring_NNL(BitString,NamedNumberList)
+ end.
+
+%%----------------------------------------
+%% Decode the in buffer to bits
+%%----------------------------------------
+decode_bitstring2(1,Unused,<<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,_/binary>>) ->
+ lists:sublist([B7,B6,B5,B4,B3,B2,B1,B0],8-Unused);
+decode_bitstring2(Len, Unused,
+ <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Buffer/binary>>) ->
+ [B7, B6, B5, B4, B3, B2, B1, B0 |
+ decode_bitstring2(Len - 1, Unused, Buffer)].
+
+%%decode_bitstring2(1, Unused, Buffer) ->
+%% make_bits_of_int(hd(Buffer), 128, 8-Unused);
+%%decode_bitstring2(Len, Unused, [BitVal | Buffer]) ->
+%% [B7, B6, B5, B4, B3, B2, B1, B0] = make_bits_of_int(BitVal, 128, 8),
+%% [B7, B6, B5, B4, B3, B2, B1, B0 |
+%% decode_bitstring2(Len - 1, Unused, Buffer)].
+
+
+%%make_bits_of_int(_, _, 0) ->
+%% [];
+%%make_bits_of_int(BitVal, MaskVal, Unused) when Unused > 0 ->
+%% X = case MaskVal band BitVal of
+%% 0 -> 0 ;
+%% _ -> 1
+%% end,
+%% [X | make_bits_of_int(BitVal, MaskVal bsr 1, Unused - 1)].
+
+
+
+%%----------------------------------------
+%% Decode the bitlist to names
+%%----------------------------------------
+
+
+decode_bitstring_NNL(BitList,NamedNumberList) ->
+ decode_bitstring_NNL(BitList,NamedNumberList,0,[]).
+
+
+decode_bitstring_NNL([],_,_No,Result) ->
+ lists:reverse(Result);
+
+decode_bitstring_NNL([B|BitList],[{Name,No}|NamedNumberList],No,Result) ->
+ if
+ B == 0 ->
+ decode_bitstring_NNL(BitList,NamedNumberList,No+1,Result);
+ true ->
+ decode_bitstring_NNL(BitList,NamedNumberList,No+1,[Name|Result])
+ end;
+decode_bitstring_NNL([1|BitList],NamedNumberList,No,Result) ->
+ decode_bitstring_NNL(BitList,NamedNumberList,No+1,[{bit,No}|Result]);
+decode_bitstring_NNL([0|BitList],NamedNumberList,No,Result) ->
+ decode_bitstring_NNL(BitList,NamedNumberList,No+1,Result).
+
+
+%%============================================================================
+%% Octet string, ITU_T X.690 Chapter 8.7
+%%
+%% encode octet string
+%% The OctetList must be a flat list of integers in the range 0..255
+%% the function does not check this because it takes to much time
+%%============================================================================
+encode_octet_string(_C, OctetList, TagIn) when binary(OctetList) ->
+ encode_tags(TagIn, OctetList, size(OctetList));
+encode_octet_string(_C, OctetList, TagIn) when list(OctetList) ->
+ encode_tags(TagIn, OctetList, length(OctetList));
+encode_octet_string(C, {Name,OctetList}, TagIn) when atom(Name) ->
+ encode_octet_string(C, OctetList, TagIn).
+
+
+%%============================================================================
+%% decode octet string
+%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
+%%
+%% Octet string is decoded as a restricted string
+%%============================================================================
+decode_octet_string(Buffer, Range, Tags) ->
+% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_OCTET_STRING}),
+ decode_restricted_string(Buffer, Range, ?N_OCTET_STRING,
+ Tags, [], old).
+
+%%============================================================================
+%% Null value, ITU_T X.690 Chapter 8.8
+%%
+%% encode NULL value
+%%============================================================================
+
+encode_null({Name, _Val}, TagIn) when atom(Name) ->
+ encode_tags(TagIn, [], 0);
+encode_null(_Val, TagIn) ->
+ encode_tags(TagIn, [], 0).
+
+%%============================================================================
+%% decode NULL value
+%% (Buffer, HasTag, TotalLen) -> {NULL, Remain, RemovedBytes}
+%%============================================================================
+
+decode_null(Tlv, Tags) ->
+ Val = match_tags(Tlv, Tags),
+ case Val of
+ <<>> ->
+ 'NULL';
+ _ ->
+ exit({error,{asn1,{decode_null,Val}}})
+ end.
+
+%%============================================================================
+%% Object identifier, ITU_T X.690 Chapter 8.19
+%%
+%% encode Object Identifier value
+%%============================================================================
+
+encode_object_identifier({Name,Val}, TagIn) when atom(Name) ->
+ encode_object_identifier(Val, TagIn);
+encode_object_identifier(Val, TagIn) ->
+ encode_tags(TagIn, e_object_identifier(Val)).
+
+e_object_identifier({'OBJECT IDENTIFIER', V}) ->
+ e_object_identifier(V);
+e_object_identifier({Cname, V}) when atom(Cname), tuple(V) ->
+ e_object_identifier(tuple_to_list(V));
+e_object_identifier({Cname, V}) when atom(Cname), list(V) ->
+ e_object_identifier(V);
+e_object_identifier(V) when tuple(V) ->
+ e_object_identifier(tuple_to_list(V));
+
+%%%%%%%%%%%%%%%
+%% e_object_identifier([List of Obect Identifiers]) ->
+%% {[Encoded Octetlist of ObjIds], IntLength}
+%%
+e_object_identifier([E1, E2 | Tail]) ->
+ Head = 40*E1 + E2, % wow!
+ {H,Lh} = mk_object_val(Head),
+ {R,Lr} = enc_obj_id_tail(Tail, [], 0),
+ {[H|R], Lh+Lr}.
+
+enc_obj_id_tail([], Ack, Len) ->
+ {lists:reverse(Ack), Len};
+enc_obj_id_tail([H|T], Ack, Len) ->
+ {B, L} = mk_object_val(H),
+ enc_obj_id_tail(T, [B|Ack], Len+L).
+
+%% e_object_identifier([List of Obect Identifiers]) ->
+%% {[Encoded Octetlist of ObjIds], IntLength}
+%%
+%%e_object_identifier([E1, E2 | Tail]) ->
+%% Head = 40*E1 + E2, % wow!
+%% F = fun(Val, AckLen) ->
+%% {L, Ack} = mk_object_val(Val),
+%% {L, Ack + AckLen}
+%% end,
+%% {Octets, Len} = lists:mapfoldl(F, 0, [Head | Tail]).
+
+%%%%%%%%%%%
+%% mk_object_val(Value) -> {OctetList, Len}
+%% returns a Val as a list of octets, the 8 bit is allways set to one except
+%% for the last octet, where its 0
+%%
+
+
+mk_object_val(Val) when Val =< 127 ->
+ {[255 band Val], 1};
+mk_object_val(Val) ->
+ mk_object_val(Val bsr 7, [Val band 127], 1).
+mk_object_val(0, Ack, Len) ->
+ {Ack, Len};
+mk_object_val(Val, Ack, Len) ->
+ mk_object_val(Val bsr 7, [((Val band 127) bor 128) | Ack], Len + 1).
+
+
+
+%%============================================================================
+%% decode Object Identifier value
+%% (Buffer, HasTag, TotalLen) -> {{ObjId}, Remain, RemovedBytes}
+%%============================================================================
+
+decode_object_identifier(Tlv, Tags) ->
+ Val = match_tags(Tlv, Tags),
+ [AddedObjVal|ObjVals] = dec_subidentifiers(Val,0,[]),
+ {Val1, Val2} = if
+ AddedObjVal < 40 ->
+ {0, AddedObjVal};
+ AddedObjVal < 80 ->
+ {1, AddedObjVal - 40};
+ true ->
+ {2, AddedObjVal - 80}
+ end,
+ list_to_tuple([Val1, Val2 | ObjVals]).
+
+dec_subidentifiers(<<>>,_Av,Al) ->
+ lists:reverse(Al);
+dec_subidentifiers(<<1:1,H:7,T/binary>>,Av,Al) ->
+ dec_subidentifiers(T,(Av bsl 7) + H,Al);
+dec_subidentifiers(<<H,T/binary>>,Av,Al) ->
+ dec_subidentifiers(T,0,[((Av bsl 7) + H)|Al]).
+
+
+%%============================================================================
+%% Restricted character string types, ITU_T X.690 Chapter 8.20
+%%
+%% encode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings
+%%============================================================================
+%% The StringType arg is kept for future use but might be removed
+encode_restricted_string(_C, OctetList, _StringType, TagIn)
+ when binary(OctetList) ->
+ encode_tags(TagIn, OctetList, size(OctetList));
+encode_restricted_string(_C, OctetList, _StringType, TagIn)
+ when list(OctetList) ->
+ encode_tags(TagIn, OctetList, length(OctetList));
+encode_restricted_string(C,{Name,OctetL}, StringType, TagIn) when atom(Name)->
+ encode_restricted_string(C, OctetL, StringType, TagIn).
+
+%%============================================================================
+%% decode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings
+%% (Buffer, Range, StringType, HasTag, TotalLen) ->
+%% {String, Remain, RemovedBytes}
+%%============================================================================
+
+decode_restricted_string(Buffer, Range, StringType, Tags) ->
+ decode_restricted_string(Buffer, Range, StringType, Tags, [], old).
+
+
+decode_restricted_string(Tlv, Range, StringType, TagsIn,
+ NamedNumberList, BinOrOld) ->
+ Val = match_tags(Tlv, TagsIn),
+ Val2 =
+ case Val of
+ PartList = [_H|_T] -> % constructed val
+ Bin = collect_parts(PartList),
+ decode_restricted(Bin, StringType,
+ NamedNumberList, BinOrOld);
+ Bin ->
+ decode_restricted(Bin, StringType,
+ NamedNumberList, BinOrOld)
+ end,
+ check_and_convert_restricted_string(Val2,StringType,Range,NamedNumberList,BinOrOld).
+
+
+
+% case StringType of
+% ?N_BIT_STRING when BinOrOld == bin ->
+% {concat_bit_binaries(AccVal, Val), AccRb+Rb};
+% _ when binary(Val),binary(AccVal) ->
+% {<<AccVal/binary,Val/binary>>,AccRb+Rb};
+% _ when binary(Val), AccVal==[] ->
+% {Val,AccRb+Rb};
+% _ ->
+% {AccVal++Val, AccRb+Rb}
+% end,
+
+
+
+decode_restricted(Bin, StringType, NamedNumberList,BinOrOld) ->
+ case StringType of
+ ?N_BIT_STRING ->
+ decode_bit_string2(Bin, NamedNumberList, BinOrOld);
+ ?N_UniversalString ->
+ mk_universal_string(binary_to_list(Bin));
+ ?N_BMPString ->
+ mk_BMP_string(binary_to_list(Bin));
+ _ ->
+ Bin
+ end.
+
+
+check_and_convert_restricted_string(Val,StringType,Range,NamedNumberList,_BinOrOld) ->
+ {StrLen,NewVal} = case StringType of
+ ?N_BIT_STRING when NamedNumberList /= [] ->
+ {no_check,Val};
+ ?N_BIT_STRING when list(Val) ->
+ {length(Val),Val};
+ ?N_BIT_STRING when tuple(Val) ->
+ {(size(element(2,Val))*8) - element(1,Val),Val};
+ _ when binary(Val) ->
+ {size(Val),binary_to_list(Val)};
+ _ when list(Val) ->
+ {length(Val), Val}
+ end,
+ case Range of
+ _ when StrLen == no_check ->
+ NewVal;
+ [] -> % No length constraint
+ NewVal;
+ {Lb,Ub} when StrLen >= Lb, Ub >= StrLen -> % variable length constraint
+ NewVal;
+ {{Lb,_Ub},[]} when StrLen >= Lb ->
+ NewVal;
+ {{Lb1,Ub1},{Lb2,Ub2}} when StrLen >= Lb1, StrLen =< Ub1;
+ StrLen =< Ub2, StrLen >= Lb2 ->
+ NewVal;
+ StrLen -> % fixed length constraint
+ NewVal;
+ {_,_} ->
+ exit({error,{asn1,{length,Range,Val}}});
+ _Len when integer(_Len) ->
+ exit({error,{asn1,{length,Range,Val}}});
+ _ -> % some strange constraint that we don't support yet
+ NewVal
+ end.
+
+
+%%============================================================================
+%% encode Universal string
+%%============================================================================
+
+encode_universal_string(C, {Name, Universal}, TagIn) when atom(Name) ->
+ encode_universal_string(C, Universal, TagIn);
+encode_universal_string(_C, Universal, TagIn) ->
+ OctetList = mk_uni_list(Universal),
+ encode_tags(TagIn, OctetList, length(OctetList)).
+
+mk_uni_list(In) ->
+ mk_uni_list(In,[]).
+
+mk_uni_list([],List) ->
+ lists:reverse(List);
+mk_uni_list([{A,B,C,D}|T],List) ->
+ mk_uni_list(T,[D,C,B,A|List]);
+mk_uni_list([H|T],List) ->
+ mk_uni_list(T,[H,0,0,0|List]).
+
+%%===========================================================================
+%% decode Universal strings
+%% (Buffer, Range, StringType, HasTag, LenIn) ->
+%% {String, Remain, RemovedBytes}
+%%===========================================================================
+
+decode_universal_string(Buffer, Range, Tags) ->
+ decode_restricted_string(Buffer, Range, ?N_UniversalString,
+ Tags, [], old).
+
+
+mk_universal_string(In) ->
+ mk_universal_string(In,[]).
+
+mk_universal_string([],Acc) ->
+ lists:reverse(Acc);
+mk_universal_string([0,0,0,D|T],Acc) ->
+ mk_universal_string(T,[D|Acc]);
+mk_universal_string([A,B,C,D|T],Acc) ->
+ mk_universal_string(T,[{A,B,C,D}|Acc]).
+
+
+%%============================================================================
+%% encode BMP string
+%%============================================================================
+
+encode_BMP_string(C, {Name,BMPString}, TagIn) when atom(Name)->
+ encode_BMP_string(C, BMPString, TagIn);
+encode_BMP_string(_C, BMPString, TagIn) ->
+ OctetList = mk_BMP_list(BMPString),
+ encode_tags(TagIn, OctetList, length(OctetList)).
+
+mk_BMP_list(In) ->
+ mk_BMP_list(In,[]).
+
+mk_BMP_list([],List) ->
+ lists:reverse(List);
+mk_BMP_list([{0,0,C,D}|T],List) ->
+ mk_BMP_list(T,[D,C|List]);
+mk_BMP_list([H|T],List) ->
+ mk_BMP_list(T,[H,0|List]).
+
+%%============================================================================
+%% decode (OctetList, Range(ignored), tag|notag) -> {ValList, RestList}
+%% (Buffer, Range, StringType, HasTag, TotalLen) ->
+%% {String, Remain, RemovedBytes}
+%%============================================================================
+decode_BMP_string(Buffer, Range, Tags) ->
+ decode_restricted_string(Buffer, Range, ?N_BMPString,
+ Tags, [], old).
+
+mk_BMP_string(In) ->
+ mk_BMP_string(In,[]).
+
+mk_BMP_string([],US) ->
+ lists:reverse(US);
+mk_BMP_string([0,B|T],US) ->
+ mk_BMP_string(T,[B|US]);
+mk_BMP_string([C,D|T],US) ->
+ mk_BMP_string(T,[{0,0,C,D}|US]).
+
+
+%%============================================================================
+%% Generalized time, ITU_T X.680 Chapter 39
+%%
+%% encode Generalized time
+%%============================================================================
+
+encode_generalized_time(C, {Name,OctetList}, TagIn) when atom(Name) ->
+ encode_generalized_time(C, OctetList, TagIn);
+encode_generalized_time(_C, OctetList, TagIn) ->
+ encode_tags(TagIn, OctetList, length(OctetList)).
+
+%%============================================================================
+%% decode Generalized time
+%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
+%%============================================================================
+
+decode_generalized_time(Tlv, _Range, Tags) ->
+ Val = match_tags(Tlv, Tags),
+ NewVal = case Val of
+ PartList = [_H|_T] -> % constructed
+ collect_parts(PartList);
+ Bin ->
+ Bin
+ end,
+ binary_to_list(NewVal).
+
+%%============================================================================
+%% Universal time, ITU_T X.680 Chapter 40
+%%
+%% encode UTC time
+%%============================================================================
+
+encode_utc_time(C, {Name,OctetList}, TagIn) when atom(Name) ->
+ encode_utc_time(C, OctetList, TagIn);
+encode_utc_time(_C, OctetList, TagIn) ->
+ encode_tags(TagIn, OctetList, length(OctetList)).
+
+%%============================================================================
+%% decode UTC time
+%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
+%%============================================================================
+
+decode_utc_time(Tlv, _Range, Tags) ->
+ Val = match_tags(Tlv, Tags),
+ NewVal = case Val of
+ PartList = [_H|_T] -> % constructed
+ collect_parts(PartList);
+ Bin ->
+ Bin
+ end,
+ binary_to_list(NewVal).
+
+
+%%============================================================================
+%% Length handling
+%%
+%% Encode length
+%%
+%% encode_length(Int | indefinite) ->
+%% [<127]| [128 + Int (<127),OctetList] | [16#80]
+%%============================================================================
+
+encode_length(indefinite) ->
+ {[16#80],1}; % 128
+encode_length(L) when L =< 16#7F ->
+ {[L],1};
+encode_length(L) ->
+ Oct = minimum_octets(L),
+ Len = length(Oct),
+ if
+ Len =< 126 ->
+ {[ (16#80+Len) | Oct ],Len+1};
+ true ->
+ exit({error,{asn1, to_long_length_oct, Len}})
+ end.
+
+
+%% Val must be >= 0
+minimum_octets(Val) ->
+ minimum_octets(Val,[]).
+
+minimum_octets(0,Acc) ->
+ Acc;
+minimum_octets(Val, Acc) ->
+ minimum_octets((Val bsr 8),[Val band 16#FF | Acc]).
+
+
+%%===========================================================================
+%% Decode length
+%%
+%% decode_length(OctetList) -> {{indefinite, RestOctetsL}, NoRemovedBytes} |
+%% {{Length, RestOctetsL}, NoRemovedBytes}
+%%===========================================================================
+
+decode_length(<<1:1,0:7,T/binary>>) ->
+ {indefinite, T};
+decode_length(<<0:1,Length:7,T/binary>>) ->
+ {Length,T};
+decode_length(<<1:1,LL:7,T/binary>>) ->
+ <<Length:LL/unit:8,Rest/binary>> = T,
+ {Length,Rest}.
+
+
+
+%%-------------------------------------------------------------------------
+%% INTERNAL HELPER FUNCTIONS (not exported)
+%%-------------------------------------------------------------------------
+
+
+%% decoding postitive integer values.
+decode_integer2(Len,Bin = <<0:1,_:7,_Bs/binary>>) ->
+ <<Int:Len/unit:8>> = Bin,
+ Int;
+%% decoding negative integer values.
+decode_integer2(Len,<<1:1,B2:7,Bs/binary>>) ->
+ <<N:Len/unit:8>> = <<B2,Bs/binary>>,
+ Int = N - (1 bsl (8 * Len - 1)),
+ Int.
+
+get_constraint(C,Key) ->
+ case lists:keysearch(Key,1,C) of
+ false ->
+ no;
+ {value,{_,V}} ->
+ V
+ end.
+
+collect_parts(TlvList) ->
+ collect_parts(TlvList,[]).
+
+collect_parts([{_,L}|Rest],Acc) when list(L) ->
+ collect_parts(Rest,[collect_parts(L)|Acc]);
+collect_parts([{?N_BIT_STRING,<<Unused,Bits/binary>>}|Rest],_Acc) ->
+ collect_parts_bit(Rest,[Bits],Unused);
+collect_parts([{_T,V}|Rest],Acc) ->
+ collect_parts(Rest,[V|Acc]);
+collect_parts([],Acc) ->
+ list_to_binary(lists:reverse(Acc)).
+
+collect_parts_bit([{?N_BIT_STRING,<<Unused,Bits/binary>>}|Rest],Acc,Uacc) ->
+ collect_parts_bit(Rest,[Bits|Acc],Unused+Uacc);
+collect_parts_bit([],Acc,Uacc) ->
+ list_to_binary([Uacc|lists:reverse(Acc)]).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_check.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_check.erl
new file mode 100644
index 0000000000..cfda8a2a88
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_check.erl
@@ -0,0 +1,333 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1rt_check.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
+%%
+-module(asn1rt_check).
+
+-include("asn1_records.hrl").
+
+-export([check_bool/2,
+ check_int/3,
+ check_bitstring/3,
+ check_octetstring/2,
+ check_null/2,
+ check_objectidentifier/2,
+ check_objectdescriptor/2,
+ check_real/2,
+ check_enum/3,
+ check_restrictedstring/2]).
+
+-export([transform_to_EXTERNAL1990/1,
+ transform_to_EXTERNAL1994/1]).
+
+
+check_bool(_Bool,asn1_DEFAULT) ->
+ true;
+check_bool(Bool,Bool) when Bool == true; Bool == false ->
+ true;
+check_bool(_Bool1,Bool2) ->
+ throw({error,Bool2}).
+
+check_int(_,asn1_DEFAULT,_) ->
+ true;
+check_int(Value,Value,_) when integer(Value) ->
+ true;
+check_int(DefValue,Value,NNL) when atom(Value) ->
+ case lists:keysearch(Value,1,NNL) of
+ {value,{_,DefValue}} ->
+ true;
+ _ ->
+ throw({error,DefValue})
+ end;
+check_int(DefaultValue,_Value,_) ->
+ throw({error,DefaultValue}).
+
+% check_bitstring([H|T],[H|T],_) when integer(H) ->
+% true;
+% check_bitstring(V,V,_) when integer(V) ->
+% true;
+%% Two equal lists or integers
+check_bitstring(_,asn1_DEFAULT,_) ->
+ true;
+check_bitstring(V,V,_) ->
+ true;
+%% Default value as a list of 1 and 0 and user value as an integer
+check_bitstring(L=[H|T],Int,_) when integer(Int),integer(H) ->
+ case bit_list_to_int(L,length(T)) of
+ Int -> true;
+ _ -> throw({error,L,Int})
+ end;
+%% Default value as an integer, val as list
+check_bitstring(Int,Val,NBL) when integer(Int),list(Val) ->
+ BL = int_to_bit_list(Int,[],length(Val)),
+ check_bitstring(BL,Val,NBL);
+%% Default value and user value as lists of ones and zeros
+check_bitstring(L1=[H1|_T1],L2=[H2|_T2],NBL=[_H|_T]) when integer(H1),integer(H2) ->
+ L2new = remove_trailing_zeros(L2),
+ check_bitstring(L1,L2new,NBL);
+%% Default value as a list of 1 and 0 and user value as a list of atoms
+check_bitstring(L1=[H1|_T1],L2=[H2|_T2],NBL) when integer(H1),atom(H2) ->
+ case bit_list_to_nbl(L1,NBL,0,[]) of
+ L3 -> check_bitstring(L3,L2,NBL);
+ _ -> throw({error,L2})
+ end;
+%% Both default value and user value as a list of atoms
+check_bitstring(L1=[H1|T1],L2=[H2|_T2],_) when atom(H1),atom(H2) ->
+ length(L1) == length(L2),
+ case lists:member(H1,L2) of
+ true ->
+ check_bitstring1(T1,L2);
+ false -> throw({error,L2})
+ end;
+%% Default value as a list of atoms and user value as a list of 1 and 0
+check_bitstring(L1=[H1|_T1],L2=[H2|_T2],NBL) when atom(H1),integer(H2) ->
+ case bit_list_to_nbl(L2,NBL,0,[]) of
+ L3 ->
+ check_bitstring(L1,L3,NBL);
+ _ -> throw({error,L2})
+ end;
+%% User value in compact format
+check_bitstring(DefVal,CBS={_,_},NBL) ->
+ NewVal = cbs_to_bit_list(CBS),
+ check_bitstring(DefVal,NewVal,NBL);
+check_bitstring(DV,V,_) ->
+ throw({error,DV,V}).
+
+
+bit_list_to_int([0|Bs],ShL)->
+ bit_list_to_int(Bs,ShL-1) + 0;
+bit_list_to_int([1|Bs],ShL) ->
+ bit_list_to_int(Bs,ShL-1) + (1 bsl ShL);
+bit_list_to_int([],_) ->
+ 0.
+
+int_to_bit_list(0,Acc,0) ->
+ Acc;
+int_to_bit_list(Int,Acc,Len) ->
+ int_to_bit_list(Int bsr 1,[Int band 1|Acc],Len - 1).
+
+bit_list_to_nbl([0|T],NBL,Pos,Acc) ->
+ bit_list_to_nbl(T,NBL,Pos+1,Acc);
+bit_list_to_nbl([1|T],NBL,Pos,Acc) ->
+ case lists:keysearch(Pos,2,NBL) of
+ {value,{N,_}} ->
+ bit_list_to_nbl(T,NBL,Pos+1,[N|Acc]);
+ _ ->
+ throw({error,{no,named,element,at,pos,Pos}})
+ end;
+bit_list_to_nbl([],_,_,Acc) ->
+ Acc.
+
+remove_trailing_zeros(L2) ->
+ remove_trailing_zeros1(lists:reverse(L2)).
+remove_trailing_zeros1(L) ->
+ lists:reverse(lists:dropwhile(fun(0)->true;
+ (_) ->false
+ end,
+ L)).
+
+check_bitstring1([H|T],NBL) ->
+ case lists:member(H,NBL) of
+ true ->
+ check_bitstring1(T,NBL);
+ V -> throw({error,V})
+ end;
+check_bitstring1([],_) ->
+ true.
+
+cbs_to_bit_list({Unused,<<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Rest/binary>>}) when size(Rest) >= 1 ->
+ [B7,B6,B5,B4,B3,B2,B1,B0|cbs_to_bit_list({Unused,Rest})];
+cbs_to_bit_list({0,<<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1>>}) ->
+ [B7,B6,B5,B4,B3,B2,B1,B0];
+cbs_to_bit_list({Unused,Bin}) when size(Bin) == 1 ->
+ Used = 8-Unused,
+ <<Int:Used,_:Unused>> = Bin,
+ int_to_bit_list(Int,[],Used).
+
+
+check_octetstring(_,asn1_DEFAULT) ->
+ true;
+check_octetstring(L,L) ->
+ true;
+check_octetstring(L,Int) when list(L),integer(Int) ->
+ case integer_to_octetlist(Int) of
+ L -> true;
+ V -> throw({error,V})
+ end;
+check_octetstring(_,V) ->
+ throw({error,V}).
+
+integer_to_octetlist(Int) ->
+ integer_to_octetlist(Int,[]).
+integer_to_octetlist(0,Acc) ->
+ Acc;
+integer_to_octetlist(Int,Acc) ->
+ integer_to_octetlist(Int bsr 8,[(Int band 255)|Acc]).
+
+check_null(_,asn1_DEFAULT) ->
+ true;
+check_null('NULL','NULL') ->
+ true;
+check_null(_,V) ->
+ throw({error,V}).
+
+check_objectidentifier(_,asn1_DEFAULT) ->
+ true;
+check_objectidentifier(OI,OI) ->
+ true;
+check_objectidentifier(DOI,OI) when tuple(DOI),tuple(OI) ->
+ check_objectidentifier1(tuple_to_list(DOI),tuple_to_list(OI));
+check_objectidentifier(_,OI) ->
+ throw({error,OI}).
+
+check_objectidentifier1([V|Rest1],[V|Rest2]) ->
+ check_objectidentifier1(Rest1,Rest2,V);
+check_objectidentifier1([V1|Rest1],[V2|Rest2]) ->
+ case reserved_objectid(V2,[]) of
+ V1 ->
+ check_objectidentifier1(Rest1,Rest2,[V1]);
+ V ->
+ throw({error,V})
+ end.
+check_objectidentifier1([V|Rest1],[V|Rest2],Above) ->
+ check_objectidentifier1(Rest1,Rest2,[V|Above]);
+check_objectidentifier1([V1|Rest1],[V2|Rest2],Above) ->
+ case reserved_objectid(V2,Above) of
+ V1 ->
+ check_objectidentifier1(Rest1,Rest2,[V1|Above]);
+ V ->
+ throw({error,V})
+ end;
+check_objectidentifier1([],[],_) ->
+ true;
+check_objectidentifier1(_,V,_) ->
+ throw({error,object,identifier,V}).
+
+%% ITU-T Rec. X.680 Annex B - D
+reserved_objectid('itu-t',[]) -> 0;
+reserved_objectid('ccitt',[]) -> 0;
+%% arcs below "itu-t"
+reserved_objectid('recommendation',[0]) -> 0;
+reserved_objectid('question',[0]) -> 1;
+reserved_objectid('administration',[0]) -> 2;
+reserved_objectid('network-operator',[0]) -> 3;
+reserved_objectid('identified-organization',[0]) -> 4;
+
+reserved_objectid(iso,[]) -> 1;
+%% arcs below "iso", note that number 1 is not used
+reserved_objectid('standard',[1]) -> 0;
+reserved_objectid('member-body',[1]) -> 2;
+reserved_objectid('identified-organization',[1]) -> 3;
+
+reserved_objectid('joint-iso-itu-t',[]) -> 2;
+reserved_objectid('joint-iso-ccitt',[]) -> 2;
+
+reserved_objectid(_,_) -> false.
+
+
+check_objectdescriptor(_,asn1_DEFAULT) ->
+ true;
+check_objectdescriptor(OD,OD) ->
+ true;
+check_objectdescriptor(OD,OD) ->
+ throw({error,{not_implemented_yet,check_objectdescriptor}}).
+
+check_real(_,asn1_DEFAULT) ->
+ true;
+check_real(R,R) ->
+ true;
+check_real(_,_) ->
+ throw({error,{not_implemented_yet,check_real}}).
+
+check_enum(_,asn1_DEFAULT,_) ->
+ true;
+check_enum(Val,Val,_) ->
+ true;
+check_enum(Int,Atom,Enumerations) when integer(Int),atom(Atom) ->
+ case lists:keysearch(Atom,1,Enumerations) of
+ {value,{_,Int}} -> true;
+ _ -> throw({error,{enumerated,Int,Atom}})
+ end;
+check_enum(DefVal,Val,_) ->
+ throw({error,{enumerated,DefVal,Val}}).
+
+
+check_restrictedstring(_,asn1_DEFAULT) ->
+ true;
+check_restrictedstring(Val,Val) ->
+ true;
+check_restrictedstring([V|Rest1],[V|Rest2]) ->
+ check_restrictedstring(Rest1,Rest2);
+check_restrictedstring([V1|Rest1],[V2|Rest2]) ->
+ check_restrictedstring(V1,V2),
+ check_restrictedstring(Rest1,Rest2);
+%% tuple format of value
+check_restrictedstring({V1,V2},[V1,V2]) ->
+ true;
+check_restrictedstring([V1,V2],{V1,V2}) ->
+ true;
+%% quadruple format of value
+check_restrictedstring({V1,V2,V3,V4},[V1,V2,V3,V4]) ->
+ true;
+check_restrictedstring([V1,V2,V3,V4],{V1,V2,V3,V4}) ->
+ true;
+%% character string list
+check_restrictedstring(V1,V2) when list(V1),tuple(V2) ->
+ check_restrictedstring(V1,tuple_to_list(V2));
+check_restrictedstring(V1,V2) ->
+ throw({error,{restricted,string,V1,V2}}).
+
+transform_to_EXTERNAL1990(Val) when tuple(Val),size(Val) == 4 ->
+ transform_to_EXTERNAL1990(tuple_to_list(Val),[]);
+transform_to_EXTERNAL1990(Val) when tuple(Val) ->
+ %% Data already in ASN1 1990 format
+ Val.
+
+transform_to_EXTERNAL1990(['EXTERNAL'|Rest],Acc) ->
+ transform_to_EXTERNAL1990(Rest,['EXTERNAL'|Acc]);
+transform_to_EXTERNAL1990([{syntax,Syntax}|Rest],Acc) ->
+ transform_to_EXTERNAL1990(Rest,[asn1_NOVALUE,Syntax|Acc]);
+transform_to_EXTERNAL1990([{'presentation-context-id',PCid}|Rest],Acc) ->
+ transform_to_EXTERNAL1990(Rest,[PCid,asn1_NOVALUE|Acc]);
+transform_to_EXTERNAL1990([{'context-negotiation',Context_negot}|Rest],Acc) ->
+ {_,Presentation_Cid,Transfer_syntax} = Context_negot,
+ transform_to_EXTERNAL1990(Rest,[Transfer_syntax,Presentation_Cid|Acc]);
+transform_to_EXTERNAL1990([asn1_NOVALUE|Rest],Acc) ->
+ transform_to_EXTERNAL1990(Rest,[asn1_NOVALUE|Acc]);
+transform_to_EXTERNAL1990([Data_val_desc,Data_value],Acc) when list(Data_value)->
+ list_to_tuple(lists:reverse([{'octet-aligned',Data_value},
+ Data_val_desc|Acc]));
+transform_to_EXTERNAL1990([Data_value],Acc) when list(Data_value)->
+ list_to_tuple(lists:reverse([{'octet-aligned',Data_value}|Acc])).
+
+
+transform_to_EXTERNAL1994(V={'EXTERNAL',DRef,IndRef,Data_v_desc,Encoding}) ->
+ Identification =
+ case {DRef,IndRef} of
+ {DRef,asn1_NOVALUE} ->
+ {syntax,DRef};
+ {asn1_NOVALUE,IndRef} ->
+ {'presentation-context-id',IndRef};
+ _ ->
+ {'context-negotiation',
+ {'EXTERNAL_identification_context-negotiation',IndRef,DRef}}
+ end,
+ case Encoding of
+ {_,Val} when list(Val) ->
+ {'EXTERNAL',Identification,Data_v_desc,Val};
+ _ ->
+ V
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_driver_handler.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_driver_handler.erl
new file mode 100644
index 0000000000..5200f9d2d9
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_driver_handler.erl
@@ -0,0 +1,108 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1rt_driver_handler.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
+%%
+
+-module(asn1rt_driver_handler).
+
+-export([init/1,load_driver/0,unload_driver/0]).
+
+
+load_driver() ->
+ spawn(asn1rt_driver_handler, init, [self()]).
+
+init(From) ->
+ Port=
+ case load_driver("asn1_erl_drv") of
+ ok ->
+ open_named_port(From);
+ already_done ->
+ From ! driver_ready;
+ Error -> % if erl_ddll:load_driver fails
+ erl_ddll:unload_driver("asn1_erl_drv"),
+ From ! Error
+ end,
+ register_and_loop(Port).
+
+load_driver(DriverName) ->
+ case is_driver_loaded(DriverName) of
+ false ->
+ Dir = filename:join([code:priv_dir(asn1),"lib"]),
+ erl_ddll:load_driver(Dir,DriverName);
+ true ->
+ ok
+ end.
+
+
+is_driver_loaded(_Name) ->
+ case whereis(asn1_driver_owner) of
+ undefined ->
+ false;
+ _ ->
+ true
+ end.
+
+open_named_port(From) ->
+ case is_port_open(drv_complete) of
+ false ->
+ case catch open_port({spawn,"asn1_erl_drv"},[]) of
+ {'EXIT',Reason} ->
+ From ! {port_error,Reason};
+ Port ->
+ register(drv_complete,Port),
+ From ! driver_ready,
+ Port
+ end;
+ _ ->
+ From ! driver_ready,
+ ok
+ end.
+
+is_port_open(Name) ->
+ case whereis(Name) of
+ Port when port(Port) ->
+ true;
+ _ -> false
+ end.
+
+register_and_loop(Port) when port(Port) ->
+ register(asn1_driver_owner,self()),
+ loop();
+register_and_loop(_) ->
+ ok.
+
+loop() ->
+ receive
+ unload ->
+ case whereis(drv_complete) of
+ Port when port(Port) ->
+ port_close(Port);
+ _ -> ok
+ end,
+ erl_ddll:unload_driver("asn1_erl_drv"),
+ ok;
+ _ ->
+ loop()
+ end.
+
+unload_driver() ->
+ case whereis(asn1_driver_owner) of
+ Pid when pid(Pid) ->
+ Pid ! unload,
+ ok;
+ _ ->
+ ok
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per.erl
new file mode 100644
index 0000000000..4999dde2cc
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per.erl
@@ -0,0 +1,1593 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1rt_per.erl,v 1.1 2008/12/17 09:53:31 mikpe Exp $
+%%
+-module(asn1rt_per).
+
+%% encoding / decoding of PER aligned
+
+-include("asn1_records.hrl").
+
+-export([dec_fixup/3, cindex/3, list_to_record/2]).
+-export([setchoiceext/1, setext/1, fixoptionals/2, fixextensions/2, setoptionals/1,
+ getext/1, getextension/2, skipextensions/3, getbit/1, getchoice/3 ]).
+-export([getoptionals/3, set_choice/3, encode_integer/2, encode_integer/3 ]).
+-export([decode_integer/2, decode_integer/3, encode_boolean/1,
+ decode_boolean/1, encode_length/2, decode_length/1, decode_length/2,
+ encode_small_length/1, decode_small_length/1]).
+-export([encode_enumerated/3, decode_enumerated/3,
+ encode_bit_string/3, decode_bit_string/3 ]).
+-export([encode_octet_string/2, decode_octet_string/2,
+ encode_restricted_string/4, encode_restricted_string/5,
+ decode_restricted_string/4, decode_restricted_string/5,
+ encode_null/1, decode_null/1,
+ encode_object_identifier/1, decode_object_identifier/1,
+ complete/1]).
+
+-export([encode_open_type/2, decode_open_type/2]).
+
+-export([encode_UniversalString/2, decode_UniversalString/2,
+ encode_PrintableString/2, decode_PrintableString/2,
+ encode_GeneralString/2, decode_GeneralString/2,
+ encode_GraphicString/2, decode_GraphicString/2,
+ encode_TeletexString/2, decode_TeletexString/2,
+ encode_VideotexString/2, decode_VideotexString/2,
+ encode_VisibleString/2, decode_VisibleString/2,
+ encode_BMPString/2, decode_BMPString/2,
+ encode_IA5String/2, decode_IA5String/2,
+ encode_NumericString/2, decode_NumericString/2
+ ]).
+
+
+dec_fixup(Terms,Cnames,RemBytes) ->
+ dec_fixup(Terms,Cnames,RemBytes,[]).
+
+dec_fixup([novalue|T],[_Hc|Tc],RemBytes,Acc) ->
+ dec_fixup(T,Tc,RemBytes,Acc);
+dec_fixup([{_Name,novalue}|T],[_Hc|Tc],RemBytes,Acc) ->
+ dec_fixup(T,Tc,RemBytes,Acc);
+dec_fixup([H|T],[Hc|Tc],RemBytes,Acc) ->
+ dec_fixup(T,Tc,RemBytes,[{Hc,H}|Acc]);
+dec_fixup([],_Cnames,RemBytes,Acc) ->
+ {lists:reverse(Acc),RemBytes}.
+
+cindex(Ix,Val,Cname) ->
+ case element(Ix,Val) of
+ {Cname,Val2} -> Val2;
+ X -> X
+ end.
+
+% converts a list to a record if necessary
+list_to_record(Name,List) when list(List) ->
+ list_to_tuple([Name|List]);
+list_to_record(_Name,Tuple) when tuple(Tuple) ->
+ Tuple.
+
+%%--------------------------------------------------------
+%% setchoiceext(InRootSet) -> [{bit,X}]
+%% X is set to 1 when InRootSet==false
+%% X is set to 0 when InRootSet==true
+%%
+setchoiceext(true) ->
+ [{debug,choiceext},{bit,0}];
+setchoiceext(false) ->
+ [{debug,choiceext},{bit,1}].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% setext(true|false) -> CompleteList
+%%
+
+setext(true) ->
+ [{debug,ext},{bit,1}];
+setext(false) ->
+ [{debug,ext},{bit,0}].
+
+fixoptionals(OptList,Val) when tuple(Val) ->
+ fixoptionals(OptList,Val,[]);
+
+fixoptionals(OptList,Val) when list(Val) ->
+ fixoptionals(OptList,Val,1,[],[]).
+
+fixoptionals([],Val,Acc) ->
+ % return {Val,Opt}
+ {Val,lists:reverse(Acc)};
+fixoptionals([{_,Pos}|Ot],Val,Acc) ->
+ case element(Pos+1,Val) of
+ asn1_NOVALUE -> fixoptionals(Ot,Val,[0|Acc]);
+ asn1_DEFAULT -> fixoptionals(Ot,Val,[0|Acc]);
+ _ -> fixoptionals(Ot,Val,[1|Acc])
+ end.
+
+
+%setoptionals(OptList,Val) ->
+% Vlist = tuple_to_list(Val),
+% setoptionals(OptList,Vlist,1,[]).
+
+fixoptionals([{Name,Pos}|Ot],[{Name,Val}|Vt],_Opt,Acc1,Acc2) ->
+ fixoptionals(Ot,Vt,Pos+1,[1|Acc1],[{Name,Val}|Acc2]);
+fixoptionals([{_Name,Pos}|Ot],V,Pos,Acc1,Acc2) ->
+ fixoptionals(Ot,V,Pos+1,[0|Acc1],[asn1_NOVALUE|Acc2]);
+fixoptionals(O,[Vh|Vt],Pos,Acc1,Acc2) ->
+ fixoptionals(O,Vt,Pos+1,Acc1,[Vh|Acc2]);
+fixoptionals([],[Vh|Vt],Pos,Acc1,Acc2) ->
+ fixoptionals([],Vt,Pos+1,Acc1,[Vh|Acc2]);
+fixoptionals([],[],_,Acc1,Acc2) ->
+ % return {Val,Opt}
+ {list_to_tuple([asn1_RECORDNAME|lists:reverse(Acc2)]),lists:reverse(Acc1)}.
+
+setoptionals([H|T]) ->
+ [{bit,H}|setoptionals(T)];
+setoptionals([]) ->
+ [{debug,optionals}].
+
+getext(Bytes) when tuple(Bytes) ->
+ getbit(Bytes);
+getext(Bytes) when list(Bytes) ->
+ getbit({0,Bytes}).
+
+getextension(0, Bytes) ->
+ {{},Bytes};
+getextension(1, Bytes) ->
+ {Len,Bytes2} = decode_small_length(Bytes),
+ {Blist, Bytes3} = getbits_as_list(Len,Bytes2),
+ {list_to_tuple(Blist),Bytes3}.
+
+fixextensions({ext,ExtPos,ExtNum},Val) ->
+ case fixextensions(ExtPos,ExtNum+ExtPos,Val,0) of
+ 0 -> [];
+ ExtBits ->
+ [encode_small_length(ExtNum),{bits,ExtNum,ExtBits}]
+ end.
+
+fixextensions(Pos,MaxPos,_,Acc) when Pos >= MaxPos ->
+ Acc;
+fixextensions(Pos,ExtPos,Val,Acc) ->
+ Bit = case catch(element(Pos+1,Val)) of
+ asn1_NOVALUE ->
+ 0;
+ asn1_NOEXTVALUE ->
+ 0;
+ {'EXIT',_} ->
+ 0;
+ _ ->
+ 1
+ end,
+ fixextensions(Pos+1,ExtPos,Val,(Acc bsl 1)+Bit).
+
+skipextensions(Bytes,Nr,ExtensionBitPattern) ->
+ case (catch element(Nr,ExtensionBitPattern)) of
+ 1 ->
+ {_,Bytes2} = decode_open_type(Bytes,[]),
+ skipextensions(Bytes2, Nr+1, ExtensionBitPattern);
+ 0 ->
+ skipextensions(Bytes, Nr+1, ExtensionBitPattern);
+ {'EXIT',_} -> % badarg, no more extensions
+ Bytes
+ end.
+
+
+getchoice(Bytes,1,0) -> % only 1 alternative is not encoded
+ {0,Bytes};
+getchoice(Bytes,_NumChoices,1) ->
+ decode_small_number(Bytes);
+getchoice(Bytes,NumChoices,0) ->
+ decode_integer(Bytes,[{'ValueRange',{0,NumChoices-1}}]).
+
+getoptionals(Bytes,L,NumComp) when list(L) ->
+ {Blist,Bytes1} = getbits_as_list(length(L),Bytes),
+ {list_to_tuple(comptuple(Blist,L,NumComp,1)),Bytes1}.
+
+comptuple([Bh|Bt],[{_Name,Nr}|T],NumComp,Nr) ->
+ [Bh|comptuple(Bt,T,NumComp-1,Nr+1)];
+comptuple(Bl,[{Name,Tnr}|Tl],NumComp,Nr) ->
+ [0|comptuple(Bl,[{Name,Tnr}|Tl],NumComp-1,Nr+1)];
+comptuple(_B,_L,0,_Nr) ->
+ [];
+comptuple(B,O,N,Nr) ->
+ [0|comptuple(B,O,N-1,Nr+1)].
+
+getbits_as_list(Num,Bytes) ->
+ getbits_as_list(Num,Bytes,[]).
+
+getbits_as_list(0,Bytes,Acc) ->
+ {lists:reverse(Acc),Bytes};
+getbits_as_list(Num,Bytes,Acc) ->
+ {Bit,NewBytes} = getbit(Bytes),
+ getbits_as_list(Num-1,NewBytes,[Bit|Acc]).
+
+getbit(Bytes) ->
+% io:format("getbit:~p~n",[Bytes]),
+ getbit1(Bytes).
+
+getbit1({7,[H|T]}) ->
+ {H band 1,{0,T}};
+getbit1({Pos,[H|T]}) ->
+ {(H bsr (7-Pos)) band 1,{(Pos+1) rem 8,[H|T]}};
+getbit1(Bytes) when list(Bytes) ->
+ getbit1({0,Bytes}).
+
+%% This could be optimized
+getbits(Buffer,Num) ->
+% io:format("getbits:Buffer = ~p~nNum=~p~n",[Buffer,Num]),
+ getbits(Buffer,Num,0).
+
+getbits(Buffer,0,Acc) ->
+ {Acc,Buffer};
+getbits(Buffer,Num,Acc) ->
+ {B,NewBuffer} = getbit(Buffer),
+ getbits(NewBuffer,Num-1,B + (Acc bsl 1)).
+
+
+getoctet(Bytes) when list(Bytes) ->
+ getoctet({0,Bytes});
+getoctet(Bytes) ->
+% io:format("getoctet:Buffer = ~p~n",[Bytes]),
+ getoctet1(Bytes).
+
+getoctet1({0,[H|T]}) ->
+ {H,{0,T}};
+getoctet1({_Pos,[_,H|T]}) ->
+ {H,{0,T}}.
+
+align({0,L}) ->
+ {0,L};
+align({_Pos,[_H|T]}) ->
+ {0,T};
+align(Bytes) ->
+ {0,Bytes}.
+
+getoctets(Buffer,Num) ->
+% io:format("getoctets:Buffer = ~p~nNum = ~p~n",[Buffer,Num]),
+ getoctets(Buffer,Num,0).
+
+getoctets(Buffer,0,Acc) ->
+ {Acc,Buffer};
+getoctets(Buffer,Num,Acc) ->
+ {Oct,NewBuffer} = getoctet(Buffer),
+ getoctets(NewBuffer,Num-1,(Acc bsl 8)+Oct).
+
+getoctets_as_list(Buffer,Num) ->
+ getoctets_as_list(Buffer,Num,[]).
+
+getoctets_as_list(Buffer,0,Acc) ->
+ {lists:reverse(Acc),Buffer};
+getoctets_as_list(Buffer,Num,Acc) ->
+ {Oct,NewBuffer} = getoctet(Buffer),
+ getoctets_as_list(NewBuffer,Num-1,[Oct|Acc]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% set_choice(Alt,Choices,Altnum) -> ListofBitSettings
+%% Alt = atom()
+%% Altnum = integer() | {integer(),integer()}% number of alternatives
+%% Choices = [atom()] | {[atom()],[atom()]}
+%% When Choices is a tuple the first list is the Rootset and the
+%% second is the Extensions and then Altnum must also be a tuple with the
+%% lengths of the 2 lists
+%%
+set_choice(Alt,{L1,L2},{Len1,_Len2}) ->
+ case set_choice_tag(Alt,L1) of
+ N when integer(N), Len1 > 1 ->
+ [{bit,0}, % the value is in the root set
+ encode_integer([{'ValueRange',{0,Len1-1}}],N)];
+ N when integer(N) ->
+ [{bit,0}]; % no encoding if only 0 or 1 alternative
+ false ->
+ [{bit,1}, % extension value
+ case set_choice_tag(Alt,L2) of
+ N2 when integer(N2) ->
+ encode_small_number(N2);
+ false ->
+ unknown_choice_alt
+ end]
+ end;
+set_choice(Alt,L,Len) ->
+ case set_choice_tag(Alt,L) of
+ N when integer(N), Len > 1 ->
+ encode_integer([{'ValueRange',{0,Len-1}}],N);
+ N when integer(N) ->
+ []; % no encoding if only 0 or 1 alternative
+ false ->
+ [unknown_choice_alt]
+ end.
+
+set_choice_tag(Alt,Choices) ->
+ set_choice_tag(Alt,Choices,0).
+
+set_choice_tag(Alt,[Alt|_Rest],Tag) ->
+ Tag;
+set_choice_tag(Alt,[_H|Rest],Tag) ->
+ set_choice_tag(Alt,Rest,Tag+1);
+set_choice_tag(_,[],_) ->
+ false.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_open_type(Constraint, Value) -> CompleteList
+%% Value = list of bytes of an already encoded value (the list must be flat)
+%% | binary
+%% Contraint = not used in this version
+%%
+encode_open_type(_Constraint, Val) when list(Val) ->
+ [encode_length(undefined,length(Val)),align,
+ {octets,Val}];
+encode_open_type(_Constraint, Val) when binary(Val) ->
+ [encode_length(undefined,size(Val)),align,
+ {octets,binary_to_list(Val)}].
+%% the binary_to_list is not optimal but compatible with the current solution
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% decode_open_type(Buffer,Constraint) -> Value
+%% Constraint is not used in this version
+%% Buffer = [byte] with PER encoded data
+%% Value = [byte] with decoded data (which must be decoded again as some type)
+%%
+decode_open_type(Bytes, _Constraint) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ Bytes3 = align(Bytes2),
+ getoctets_as_list(Bytes3,Len).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_integer(Constraint,Value,NamedNumberList) -> CompleteList
+%% encode_integer(Constraint,Value) -> CompleteList
+%% encode_integer(Constraint,{Name,Value}) -> CompleteList
+%%
+%%
+encode_integer(C,V,NamedNumberList) when atom(V) ->
+ case lists:keysearch(V,1,NamedNumberList) of
+ {value,{_,NewV}} ->
+ encode_integer(C,NewV);
+ _ ->
+ exit({error,{asn1,{namednumber,V}}})
+ end;
+encode_integer(C,V,_NamedNumberList) when integer(V) ->
+ encode_integer(C,V).
+
+encode_integer(C,{Name,Val}) when atom(Name) ->
+ encode_integer(C,Val);
+
+encode_integer({Rc,_Ec},Val) ->
+ case (catch encode_integer(Rc,Val)) of
+ {'EXIT',{error,{asn1,_}}} ->
+ [{bit,1},encode_unconstrained_number(Val)];
+ Encoded ->
+ [{bit,0},Encoded]
+ end;
+encode_integer(C,Val ) when list(C) ->
+ case get_constraint(C,'SingleValue') of
+ no ->
+ encode_integer1(C,Val);
+ V when integer(V),V == Val ->
+ []; % a type restricted to a single value encodes to nothing
+ V when list(V) ->
+ case lists:member(Val,V) of
+ true ->
+ encode_integer1(C,Val);
+ _ ->
+ exit({error,{asn1,{illegal_value,Val}}})
+ end;
+ _ ->
+ exit({error,{asn1,{illegal_value,Val}}})
+ end.
+
+encode_integer1(C, Val) ->
+ case VR = get_constraint(C,'ValueRange') of
+ no ->
+ encode_unconstrained_number(Val);
+ {Lb,'MAX'} ->
+ encode_semi_constrained_number(Lb,Val);
+ %% positive with range
+ {Lb,Ub} when Val >= Lb,
+ Ub >= Val ->
+ encode_constrained_number(VR,Val)
+ end.
+
+decode_integer(Buffer,Range,NamedNumberList) ->
+ {Val,Buffer2} = decode_integer(Buffer,Range),
+ case lists:keysearch(Val,2,NamedNumberList) of
+ {value,{NewVal,_}} -> {NewVal,Buffer2};
+ _ -> {Val,Buffer2}
+ end.
+
+decode_integer(Buffer,{Rc,_Ec}) ->
+ {Ext,Buffer2} = getext(Buffer),
+ case Ext of
+ 0 -> decode_integer(Buffer2,Rc);
+ 1 -> decode_unconstrained_number(Buffer2)
+ end;
+decode_integer(Buffer,undefined) ->
+ decode_unconstrained_number(Buffer);
+decode_integer(Buffer,C) ->
+ case get_constraint(C,'SingleValue') of
+ V when integer(V) ->
+ {V,Buffer};
+ V when list(V) ->
+ {Val,Buffer2} = decode_integer1(Buffer,C),
+ case lists:member(Val,V) of
+ true ->
+ {Val,Buffer2};
+ _ ->
+ exit({error,{asn1,{illegal_value,Val}}})
+ end;
+ _ ->
+ decode_integer1(Buffer,C)
+ end.
+
+decode_integer1(Buffer,C) ->
+ case VR = get_constraint(C,'ValueRange') of
+ no ->
+ decode_unconstrained_number(Buffer);
+ {Lb, 'MAX'} ->
+ decode_semi_constrained_number(Buffer,Lb);
+ {_,_} ->
+ decode_constrained_number(Buffer,VR)
+ end.
+
+% X.691:10.6 Encoding of a normally small non-negative whole number
+% Use this for encoding of CHOICE index if there is an extension marker in
+% the CHOICE
+encode_small_number({Name,Val}) when atom(Name) ->
+ encode_small_number(Val);
+encode_small_number(Val) when Val =< 63 ->
+ [{bit,0},{bits,6,Val}];
+encode_small_number(Val) ->
+ [{bit,1},encode_semi_constrained_number(0,Val)].
+
+decode_small_number(Bytes) ->
+ {Bit,Bytes2} = getbit(Bytes),
+ case Bit of
+ 0 ->
+ getbits(Bytes2,6);
+ 1 ->
+ decode_semi_constrained_number(Bytes2,{0,'MAX'})
+ end.
+
+% X.691:10.7 Encoding of a semi-constrained whole number
+%% might be an optimization encode_semi_constrained_number(0,Val) ->
+encode_semi_constrained_number(C,{Name,Val}) when atom(Name) ->
+ encode_semi_constrained_number(C,Val);
+encode_semi_constrained_number({Lb,'MAX'},Val) ->
+ encode_semi_constrained_number(Lb,Val);
+encode_semi_constrained_number(Lb,Val) ->
+ Val2 = Val - Lb,
+ Octs = eint_positive(Val2),
+ [encode_length(undefined,length(Octs)),{octets,Octs}].
+
+decode_semi_constrained_number(Bytes,{Lb,_}) ->
+ decode_semi_constrained_number(Bytes,Lb);
+decode_semi_constrained_number(Bytes,Lb) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ {V,Bytes3} = getoctets(Bytes2,Len),
+ {V+Lb,Bytes3}.
+
+encode_constrained_number(Range,{Name,Val}) when atom(Name) ->
+ encode_constrained_number(Range,Val);
+encode_constrained_number({Lb,Ub},Val) when Val >= Lb, Ub >= Val ->
+ Range = Ub - Lb + 1,
+ Val2 = Val - Lb,
+ if
+ Range == 2 ->
+ {bits,1,Val2};
+ Range =< 4 ->
+ {bits,2,Val2};
+ Range =< 8 ->
+ {bits,3,Val2};
+ Range =< 16 ->
+ {bits,4,Val2};
+ Range =< 32 ->
+ {bits,5,Val2};
+ Range =< 64 ->
+ {bits,6,Val2};
+ Range =< 128 ->
+ {bits,7,Val2};
+ Range =< 255 ->
+ {bits,8,Val2};
+ Range =< 256 ->
+ {octets,1,Val2};
+ Range =< 65536 ->
+ {octets,2,Val2};
+ Range =< 16#1000000 ->
+ Octs = eint_positive(Val2),
+ [encode_length({1,3},length(Octs)),{octets,Octs}];
+ Range =< 16#100000000 ->
+ Octs = eint_positive(Val2),
+ [encode_length({1,4},length(Octs)),{octets,Octs}];
+ Range =< 16#10000000000 ->
+ Octs = eint_positive(Val2),
+ [encode_length({1,5},length(Octs)),{octets,Octs}];
+ true ->
+ exit({not_supported,{integer_range,Range}})
+ end.
+
+decode_constrained_number(Buffer,{Lb,Ub}) ->
+ Range = Ub - Lb + 1,
+% Val2 = Val - Lb,
+ {Val,Remain} =
+ if
+ Range == 2 ->
+ getbits(Buffer,1);
+ Range =< 4 ->
+ getbits(Buffer,2);
+ Range =< 8 ->
+ getbits(Buffer,3);
+ Range =< 16 ->
+ getbits(Buffer,4);
+ Range =< 32 ->
+ getbits(Buffer,5);
+ Range =< 64 ->
+ getbits(Buffer,6);
+ Range =< 128 ->
+ getbits(Buffer,7);
+ Range =< 255 ->
+ getbits(Buffer,8);
+ Range =< 256 ->
+ getoctets(Buffer,1);
+ Range =< 65536 ->
+ getoctets(Buffer,2);
+ Range =< 16#1000000 ->
+ {Len,Bytes2} = decode_length(Buffer,{1,3}),
+ {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
+ {dec_pos_integer(Octs),Bytes3};
+ Range =< 16#100000000 ->
+ {Len,Bytes2} = decode_length(Buffer,{1,4}),
+ {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
+ {dec_pos_integer(Octs),Bytes3};
+ Range =< 16#10000000000 ->
+ {Len,Bytes2} = decode_length(Buffer,{1,5}),
+ {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
+ {dec_pos_integer(Octs),Bytes3};
+ true ->
+ exit({not_supported,{integer_range,Range}})
+ end,
+ {Val+Lb,Remain}.
+
+% X.691:10.8 Encoding of an unconstrained whole number
+
+encode_unconstrained_number(Val) when Val >= 0 ->
+ Oct = eint(Val,[]),
+ [{debug,unconstrained_number},
+ encode_length({0,'MAX'},length(Oct)),
+ {octets,Oct}];
+encode_unconstrained_number(Val) -> % negative
+ Oct = enint(Val,[]),
+ [{debug,unconstrained_number},
+ encode_length({0,'MAX'},length(Oct)),
+ {octets,Oct}].
+
+%% used for positive Values which don't need a sign bit
+eint_positive(Val) ->
+ case eint(Val,[]) of
+ [0,B1|T] ->
+ [B1|T];
+ T ->
+ T
+ end.
+
+eint(0, [B|Acc]) when B < 128 ->
+ [B|Acc];
+eint(N, Acc) ->
+ eint(N bsr 8, [N band 16#ff| Acc]).
+
+enint(-1, [B1|T]) when B1 > 127 ->
+ [B1|T];
+enint(N, Acc) ->
+ enint(N bsr 8, [N band 16#ff|Acc]).
+
+%% used for signed positive values
+
+%eint(Val, Ack) ->
+% X = Val band 255,
+% Next = Val bsr 8,
+% if
+% Next == 0, X >= 127 ->
+% [0,X|Ack];
+% Next == 0 ->
+% [X|Ack];
+% true ->
+% eint(Next,[X|Ack])
+% end.
+
+%%% used for signed negative values
+%enint(Val, Acc) ->
+% NumOctets = if
+% -Val < 16#80 -> 1;
+% -Val < 16#8000 ->2;
+% -Val < 16#800000 ->3;
+% -Val < 16#80000000 ->4;
+% -Val < 16#8000000000 ->5;
+% -Val < 16#800000000000 ->6;
+% -Val < 16#80000000000000 ->7;
+% -Val < 16#8000000000000000 ->8;
+% -Val < 16#800000000000000000 ->9
+% end,
+% enint(Val,Acc,NumOctets).
+
+%enint(Val, Acc,0) ->
+% Acc;
+%enint(Val, Acc,NumOctets) ->
+% enint(Val bsr 8,[Val band 255|Acc],NumOctets-1).
+
+
+decode_unconstrained_number(Bytes) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ {Ints,Bytes3} = getoctets_as_list(Bytes2,Len),
+ {dec_integer(Ints),Bytes3}.
+
+dec_pos_integer(Ints) ->
+ decpint(Ints, 8 * (length(Ints) - 1)).
+dec_integer(Ints) when hd(Ints) band 255 =< 127 -> %% Positive number
+ decpint(Ints, 8 * (length(Ints) - 1));
+dec_integer(Ints) -> %% Negative
+ decnint(Ints, 8 * (length(Ints) - 1)).
+
+decpint([Byte|Tail], Shift) ->
+ (Byte bsl Shift) bor decpint(Tail, Shift-8);
+decpint([], _) -> 0.
+
+decnint([Byte|Tail], Shift) ->
+ (-128 + (Byte band 127) bsl Shift) bor decpint(Tail, Shift-8).
+
+minimum_octets(Val) ->
+ minimum_octets(Val,[]).
+
+minimum_octets(Val,Acc) when Val > 0 ->
+ minimum_octets((Val bsr 8),[Val band 16#FF|Acc]);
+minimum_octets(0,Acc) ->
+ Acc.
+
+
+%% X.691:10.9 Encoding of a length determinant
+%%encode_small_length(undefined,Len) -> % null means no UpperBound
+%% encode_small_number(Len).
+
+%% X.691:10.9.3.5
+%% X.691:10.9.3.7
+encode_length(undefined,Len) -> % un-constrained
+ if
+ Len < 128 ->
+ {octet,Len band 16#7F};
+ Len < 16384 ->
+ {octets,2,2#1000000000000000 bor Len};
+ true ->
+ exit({error,{asn1,{encode_length,{nyi,above_16k}}}})
+ end;
+
+encode_length({0,'MAX'},Len) ->
+ encode_length(undefined,Len);
+encode_length({Lb,Ub},Len) when Ub =< 65535 ,Lb >= 0 -> % constrained
+ encode_constrained_number({Lb,Ub},Len);
+encode_length(SingleValue,_Len) when integer(SingleValue) ->
+ [].
+
+encode_small_length(Len) when Len =< 64 ->
+ [{bit,0},{bits,6,Len-1}];
+encode_small_length(Len) ->
+ [{bit,1},encode_length(undefined,Len)].
+
+decode_small_length(Buffer) ->
+ case getbit(Buffer) of
+ {0,Remain} ->
+ {Bits,Remain2} = getbits(Remain,6),
+ {Bits+1,Remain2};
+ {1,Remain} ->
+ decode_length(Remain,undefined)
+ end.
+
+decode_length(Buffer) ->
+ decode_length(Buffer,undefined).
+
+decode_length(Buffer,undefined) -> % un-constrained
+ Buffer2 = align(Buffer),
+ {Bits,_} = getbits(Buffer2,2),
+ case Bits of
+ 2 ->
+ {Val,Bytes3} = getoctets(Buffer2,2),
+ {(Val band 16#3FFF),Bytes3};
+ 3 ->
+ exit({error,{asn1,{decode_length,{nyi,above_16k}}}});
+ _ ->
+ {Val,Bytes3} = getoctet(Buffer2),
+ {Val band 16#7F,Bytes3}
+ end;
+
+decode_length(Buffer,{Lb,Ub}) when Ub =< 65535 ,Lb >= 0 -> % constrained
+ decode_constrained_number(Buffer,{Lb,Ub});
+ % X.691:10.9.3.5
+decode_length(Buffer,{_,_Lb,_Ub}) -> %when Len =< 127 -> % Unconstrained or large Ub
+ case getbit(Buffer) of
+ {0,Remain} ->
+ getbits(Remain,7);
+ {1,_Remain} ->
+ {Val,Remain2} = getoctets(Buffer,2),
+ {Val band 2#0111111111111111, Remain2}
+ end;
+decode_length(Buffer,SingleValue) when integer(SingleValue) ->
+ {SingleValue,Buffer}.
+
+
+% X.691:11
+encode_boolean({Name,Val}) when atom(Name) ->
+ encode_boolean(Val);
+encode_boolean(true) ->
+ {bit,1};
+encode_boolean(false) ->
+ {bit,0};
+encode_boolean(Val) ->
+ exit({error,{asn1,{encode_boolean,Val}}}).
+
+
+decode_boolean(Buffer) -> %when record(Buffer,buffer)
+ case getbit(Buffer) of
+ {1,Remain} -> {true,Remain};
+ {0,Remain} -> {false,Remain}
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% X.691:12
+%% ENUMERATED
+%%
+%% encode_enumerated(C,Value,NamedNumberTup) -> CompleteList
+%%
+%%
+
+encode_enumerated(C,{Name,Value},NamedNumberList) when
+ atom(Name),list(NamedNumberList) ->
+ encode_enumerated(C,Value,NamedNumberList);
+
+%% ENUMERATED with extension mark
+encode_enumerated(_C,{asn1_enum,Value},{_Nlist1,Nlist2}) when Value >= length(Nlist2) ->
+ [{bit,1},encode_small_number(Value)];
+encode_enumerated(C,Value,{Nlist1,Nlist2}) ->
+ case enum_search(Value,Nlist1,0) of
+ NewV when integer(NewV) ->
+ [{bit,0},encode_integer(C,NewV)];
+ false ->
+ case enum_search(Value,Nlist2,0) of
+ ExtV when integer(ExtV) ->
+ [{bit,1},encode_small_number(ExtV)];
+ false ->
+ exit({error,{asn1,{encode_enumerated,Value}}})
+ end
+ end;
+
+encode_enumerated(C,Value,NamedNumberList) when list(NamedNumberList) ->
+ case enum_search(Value,NamedNumberList,0) of
+ NewV when integer(NewV) ->
+ encode_integer(C,NewV);
+ false ->
+ exit({error,{asn1,{encode_enumerated,Value}}})
+ end.
+
+%% returns the ordinal number from 0 ,1 ... in the list where Name is found
+%% or false if not found
+%%
+enum_search(Name,[Name|_NamedNumberList],Acc) ->
+ Acc;
+enum_search(Name,[_H|T],Acc) ->
+ enum_search(Name,T,Acc+1);
+enum_search(_,[],_) ->
+ false. % name not found !error
+
+%% ENUMERATED with extension marker
+decode_enumerated(Buffer,C,{Ntup1,Ntup2}) when tuple(Ntup1), tuple(Ntup2) ->
+ {Ext,Buffer2} = getext(Buffer),
+ case Ext of
+ 0 -> % not an extension value
+ {Val,Buffer3} = decode_integer(Buffer2,C),
+ case catch (element(Val+1,Ntup1)) of
+ NewVal when atom(NewVal) -> {NewVal,Buffer3};
+ _Error -> exit({error,{asn1,{decode_enumerated,{Val,[Ntup1,Ntup2]}}}})
+ end;
+ 1 -> % this an extension value
+ {Val,Buffer3} = decode_small_number(Buffer2),
+ case catch (element(Val+1,Ntup2)) of
+ NewVal when atom(NewVal) -> {NewVal,Buffer3};
+ _ -> {{asn1_enum,Val},Buffer3}
+ end
+ end;
+
+decode_enumerated(Buffer,C,NamedNumberTup) when tuple(NamedNumberTup) ->
+ {Val,Buffer2} = decode_integer(Buffer,C),
+ case catch (element(Val+1,NamedNumberTup)) of
+ NewVal when atom(NewVal) -> {NewVal,Buffer2};
+ _Error -> exit({error,{asn1,{decode_enumerated,{Val,NamedNumberTup}}}})
+ end.
+
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+%% Bitstring value, ITU_T X.690 Chapter 8.5
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+
+%%===============================================================================
+%% encode bitstring value
+%%===============================================================================
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% bitstring NamedBitList
+%% Val can be of:
+%% - [identifiers] where only named identifers are set to one,
+%% the Constraint must then have some information of the
+%% bitlength.
+%% - [list of ones and zeroes] all bits
+%% - integer value representing the bitlist
+%% C is constraint Len, only valid when identifiers
+
+%% when the value is a list of named bits
+encode_bit_string(C, [FirstVal | RestVal], NamedBitList) when atom(FirstVal) ->
+ ToSetPos = get_all_bitposes([FirstVal | RestVal], NamedBitList, []),
+ BitList = make_and_set_list(ToSetPos,0),
+ encode_bit_string(C,BitList,NamedBitList);
+
+encode_bit_string(C, [{bit,No} | RestVal], NamedBitList) ->
+ ToSetPos = get_all_bitposes([{bit,No} | RestVal], NamedBitList, []),
+ BitList = make_and_set_list(ToSetPos,0),
+ encode_bit_string(C,BitList,NamedBitList);
+
+%% when the value is a list of ones and zeroes
+
+encode_bit_string(C, BitListValue, _NamedBitList) when list(BitListValue) ->
+ %% first remove any trailing zeroes
+ Bl1 = lists:dropwhile(fun(0)->true;(1)->false end,lists:reverse(BitListValue)),
+ BitList = [{bit,X} || X <- lists:reverse(Bl1)],
+ case get_constraint(C,'SizeConstraint') of
+ 0 -> % fixed length
+ []; % nothing to encode
+ V when integer(V),V=<16 -> % fixed length 16 bits or less
+ pad_list(V,BitList);
+ V when integer(V) -> % fixed length more than 16 bits
+ [align,pad_list(V,BitList)];
+ {Lb,Ub} when integer(Lb),integer(Ub) ->
+ [encode_length({Lb,Ub},length(BitList)),align,BitList];
+ no ->
+ [encode_length(undefined,length(BitList)),align,BitList]
+ end;
+
+%% when the value is an integer
+encode_bit_string(C, IntegerVal, NamedBitList) ->
+ BitList = int_to_bitlist(IntegerVal),
+ encode_bit_string(C,BitList,NamedBitList).
+
+
+
+
+%%%%%%%%%%%%%%%
+%% The result is presented as a list of named bits (if possible)
+%% else as a list of 0 and 1.
+%%
+decode_bit_string(Buffer, C, NamedNumberList) ->
+ case get_constraint(C,'SizeConstraint') of
+ 0 -> % fixed length
+ {[],Buffer}; % nothing to encode
+ V when integer(V),V=<16 -> % fixed length 16 bits or less
+ bit_list_to_named(Buffer,V,NamedNumberList);
+ V when integer(V) -> % fixed length 16 bits or less
+ Bytes2 = align(Buffer),
+ bit_list_to_named(Bytes2,V,NamedNumberList);
+ {Lb,Ub} when integer(Lb),integer(Ub) ->
+ {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
+ Bytes3 = align(Bytes2),
+ bit_list_to_named(Bytes3,Len,NamedNumberList);
+ no ->
+ {Len,Bytes2} = decode_length(Buffer,undefined),
+ Bytes3 = align(Bytes2),
+ bit_list_to_named(Bytes3,Len,NamedNumberList)
+ end.
+
+%% if no named bits are declared we will return a
+%% BitList = [0 | 1]
+
+bit_list_to_named(Buffer,Len,[]) ->
+ getbits_as_list(Len,Buffer);
+
+%% if there are named bits declared we will return a named
+%% BitList where the names are atoms and unnamed bits represented
+%% as {bit,Pos}
+%% BitList = [atom() | {bit,Pos}]
+%% Pos = integer()
+
+bit_list_to_named(Buffer,Len,NamedNumberList) ->
+ {BitList,Rest} = getbits_as_list(Len,Buffer),
+ {bit_list_to_named1(0,BitList,NamedNumberList,[]), Rest}.
+
+bit_list_to_named1(Pos,[0|Bt],Names,Acc) ->
+ bit_list_to_named1(Pos+1,Bt,Names,Acc);
+bit_list_to_named1(Pos,[1|Bt],Names,Acc) ->
+ case lists:keysearch(Pos,2,Names) of
+ {value,{Name,_}} ->
+ bit_list_to_named1(Pos+1,Bt,Names,[Name|Acc]);
+ _ ->
+ bit_list_to_named1(Pos+1,Bt,Names,[{bit,Pos}|Acc])
+ end;
+bit_list_to_named1(_Pos,[],_Names,Acc) ->
+ lists:reverse(Acc).
+
+
+
+%%%%%%%%%%%%%%%
+%%
+
+int_to_bitlist(0) ->
+ [];
+int_to_bitlist(Int) when integer(Int), Int >= 0 ->
+ [Int band 1 | int_to_bitlist(Int bsr 1)].
+
+
+%%%%%%%%%%%%%%%%%%
+%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
+%% [sorted_list_of_bitpositions_to_set]
+
+get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
+ get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
+
+get_all_bitposes([Val | Rest], NamedBitList, Ack) ->
+ case lists:keysearch(Val, 1, NamedBitList) of
+ {value, {_ValName, ValPos}} ->
+ get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
+ _ ->
+ exit({error,{asn1, {bitstring_namedbit, Val}}})
+ end;
+get_all_bitposes([], _NamedBitList, Ack) ->
+ lists:sort(Ack).
+
+%%%%%%%%%%%%%%%%%%
+%% make_and_set_list([list of positions to set to 1])->
+%% returns list with all in SetPos set.
+%% in positioning in list the first element is 0, the second 1 etc.., but
+%%
+
+make_and_set_list([XPos|SetPos], XPos) ->
+ [1 | make_and_set_list(SetPos, XPos + 1)];
+make_and_set_list([Pos|SetPos], XPos) ->
+ [0 | make_and_set_list([Pos | SetPos], XPos + 1)];
+make_and_set_list([], _) ->
+ [].
+
+%%%%%%%%%%%%%%%%%
+%% pad_list(N,BitList) -> PaddedList
+%% returns a padded (with trailing {bit,0} elements) list of length N
+%% if Bitlist contains more than N significant bits set an exit asn1_error
+%% is generated
+
+pad_list(0,BitList) ->
+ case BitList of
+ [] -> [];
+ _ -> exit({error,{asn1,{range_error,{bit_string,BitList}}}})
+ end;
+pad_list(N,[Bh|Bt]) ->
+ [Bh|pad_list(N-1,Bt)];
+pad_list(N,[]) ->
+ [{bit,0},pad_list(N-1,[])].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% X.691:16
+%% encode_octet_string(Constraint,ExtensionMarker,Val)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+encode_octet_string(C,{Name,Val}) when atom(Name) ->
+ encode_octet_string(C,false,Val);
+encode_octet_string(C,Val) ->
+ encode_octet_string(C,false,Val).
+
+encode_octet_string(_C,true,_Val) ->
+ exit({error,{asn1,{'not_supported',extensionmarker}}});
+encode_octet_string(C,false,Val) ->
+ case get_constraint(C,'SizeConstraint') of
+ 0 ->
+ [];
+ 1 ->
+ [V] = Val,
+ {bits,8,V};
+ 2 ->
+ [V1,V2] = Val,
+ [{bits,8,V1},{bits,8,V2}];
+ Sv when Sv =<65535, Sv == length(Val) -> % fixed length
+ [align,{octets,Val}];
+ {Lb,Ub} ->
+ [encode_length({Lb,Ub},length(Val)),align,
+ {octets,Val}];
+ Sv when list(Sv) ->
+ [encode_length({hd(Sv),lists:max(Sv)},length(Val)),align,
+ {octets,Val}];
+ no ->
+ [encode_length(undefined,length(Val)),align,
+ {octets,Val}]
+ end.
+
+decode_octet_string(Bytes,Range) ->
+ decode_octet_string(Bytes,Range,false).
+
+decode_octet_string(Bytes,C,false) ->
+ case get_constraint(C,'SizeConstraint') of
+ 0 ->
+ {[],Bytes};
+ 1 ->
+ {B1,Bytes2} = getbits(Bytes,8),
+ {[B1],Bytes2};
+ 2 ->
+ {B1,Bytes2}= getbits(Bytes,8),
+ {B2,Bytes3}= getbits(Bytes2,8),
+ {[B1,B2],Bytes3};
+ {_,0} ->
+ {[],Bytes};
+ Sv when integer(Sv), Sv =<65535 -> % fixed length
+ Bytes2 = align(Bytes),
+ getoctets_as_list(Bytes2,Sv);
+ {Lb,Ub} ->
+ {Len,Bytes2} = decode_length(Bytes,{Lb,Ub}),
+ Bytes3 = align(Bytes2),
+ getoctets_as_list(Bytes3,Len);
+ Sv when list(Sv) ->
+ {Len,Bytes2} = decode_length(Bytes,{hd(Sv),lists:max(Sv)}),
+ Bytes3 = align(Bytes2),
+ getoctets_as_list(Bytes3,Len);
+ no ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ Bytes3 = align(Bytes2),
+ getoctets_as_list(Bytes3,Len)
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Restricted char string types
+%% (NumericString, PrintableString,VisibleString,IA5String,BMPString,UniversalString)
+%% X.691:26 and X.680:34-36
+%%encode_restricted_string(aligned,'BMPString',Constraints,Extension,Val)
+
+encode_restricted_string(aligned,StringType,C,Val) ->
+encode_restricted_string(aligned,StringType,C,false,Val).
+
+
+encode_restricted_string(aligned,StringType,C,_Ext,{Name,Val}) when atom(Name) ->
+ encode_restricted_string(aligned,StringType,C,false,Val);
+encode_restricted_string(aligned,StringType,C,_Ext,Val) ->
+ Result = chars_encode(C,StringType,Val),
+ NumBits = get_NumBits(C,StringType),
+ case get_constraint(C,'SizeConstraint') of
+ Ub when integer(Ub), Ub*NumBits =< 16 ->
+ case {StringType,Result} of
+ {'BMPString',{octets,Ol}} ->
+ [{bits,8,Oct}||Oct <- Ol];
+ _ ->
+ Result
+ end;
+ 0 ->
+ [];
+ Ub when integer(Ub),Ub =<65535 -> % fixed length
+ [align,Result];
+ {Ub,Lb} ->
+ [encode_length({Ub,Lb},length(Val)),align,Result];
+ Vl when list(Vl) ->
+ [encode_length({lists:min(Vl),lists:max(Vl)},length(Val)),align,Result];
+ no ->
+ [encode_length(undefined,length(Val)),align,Result]
+ end.
+
+decode_restricted_string(Bytes,aligned,StringType,C) ->
+ decode_restricted_string(Bytes,aligned,StringType,C,false).
+
+decode_restricted_string(Bytes,aligned,StringType,C,_Ext) ->
+ NumBits = get_NumBits(C,StringType),
+ case get_constraint(C,'SizeConstraint') of
+ Ub when integer(Ub), Ub*NumBits =< 16 ->
+ chars_decode(Bytes,NumBits,StringType,C,Ub);
+ Ub when integer(Ub),Ub =<65535 -> % fixed length
+ Bytes1 = align(Bytes),
+ chars_decode(Bytes1,NumBits,StringType,C,Ub);
+ 0 ->
+ {[],Bytes};
+ Vl when list(Vl) ->
+ {Len,Bytes1} = decode_length(Bytes,{hd(Vl),lists:max(Vl)}),
+ Bytes2 = align(Bytes1),
+ chars_decode(Bytes2,NumBits,StringType,C,Len);
+ no ->
+ {Len,Bytes1} = decode_length(Bytes,undefined),
+ Bytes2 = align(Bytes1),
+ chars_decode(Bytes2,NumBits,StringType,C,Len);
+ {Lb,Ub}->
+ {Len,Bytes1} = decode_length(Bytes,{Lb,Ub}),
+ Bytes2 = align(Bytes1),
+ chars_decode(Bytes2,NumBits,StringType,C,Len)
+ end.
+
+
+
+encode_BMPString(C,Val) ->
+ encode_restricted_string(aligned,'BMPString',C,false,Val).
+decode_BMPString(Bytes,C) ->
+ decode_restricted_string(Bytes,aligned,'BMPString',C,false).
+
+encode_GeneralString(C,Val) ->
+ encode_restricted_string(aligned,'GeneralString',C,false,Val).
+decode_GeneralString(Bytes,C) ->
+ decode_restricted_string(Bytes,aligned,'GeneralString',C,false).
+
+encode_GraphicString(C,Val) ->
+ encode_restricted_string(aligned,'GraphicString',C,false,Val).
+decode_GraphicString(Bytes,C) ->
+ decode_restricted_string(Bytes,aligned,'GraphicString',C,false).
+
+encode_IA5String(C,Val) ->
+ encode_restricted_string(aligned,'IA5String',C,false,Val).
+decode_IA5String(Bytes,C) ->
+ decode_restricted_string(Bytes,aligned,'IA5String',C,false).
+
+encode_NumericString(C,Val) ->
+ encode_restricted_string(aligned,'NumericString',C,false,Val).
+decode_NumericString(Bytes,C) ->
+ decode_restricted_string(Bytes,aligned,'NumericString',C,false).
+
+encode_PrintableString(C,Val) ->
+ encode_restricted_string(aligned,'PrintableString',C,false,Val).
+decode_PrintableString(Bytes,C) ->
+ decode_restricted_string(Bytes,aligned,'PrintableString',C,false).
+
+encode_TeletexString(C,Val) -> % equivalent with T61String
+ encode_restricted_string(aligned,'TeletexString',C,false,Val).
+decode_TeletexString(Bytes,C) ->
+ decode_restricted_string(Bytes,aligned,'TeletexString',C,false).
+
+encode_UniversalString(C,Val) ->
+ encode_restricted_string(aligned,'UniversalString',C,false,Val).
+decode_UniversalString(Bytes,C) ->
+ decode_restricted_string(Bytes,aligned,'UniversalString',C,false).
+
+encode_VideotexString(C,Val) ->
+ encode_restricted_string(aligned,'VideotexString',C,false,Val).
+decode_VideotexString(Bytes,C) ->
+ decode_restricted_string(Bytes,aligned,'VideotexString',C,false).
+
+encode_VisibleString(C,Val) -> % equivalent with ISO646String
+ encode_restricted_string(aligned,'VisibleString',C,false,Val).
+decode_VisibleString(Bytes,C) ->
+ decode_restricted_string(Bytes,aligned,'VisibleString',C,false).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% getBMPChars(Bytes,Len) ->{BMPcharList,RemainingBytes}
+%%
+getBMPChars(Bytes,1) ->
+ {O1,Bytes2} = getbits(Bytes,8),
+ {O2,Bytes3} = getbits(Bytes2,8),
+ if
+ O1 == 0 ->
+ {[O2],Bytes3};
+ true ->
+ {[{O1,O2}],Bytes3}
+ end;
+getBMPChars(Bytes,Len) ->
+ getBMPChars(Bytes,Len,[]).
+
+getBMPChars(Bytes,0,Acc) ->
+ {lists:reverse(Acc),Bytes};
+getBMPChars(Bytes,Len,Acc) ->
+ {Octs,Bytes1} = getoctets_as_list(Bytes,2),
+ case Octs of
+ [0,O2] ->
+ getBMPChars(Bytes1,Len-1,[O2|Acc]);
+ [O1,O2]->
+ getBMPChars(Bytes1,Len-1,[{O1,O2}|Acc])
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% chars_encode(C,StringType,Value) -> ValueList
+%%
+%% encodes chars according to the per rules taking the constraint PermittedAlphabet
+%% into account.
+%% This function does only encode the value part and NOT the length
+
+chars_encode(C,StringType,Value) ->
+ case {StringType,get_constraint(C,'PermittedAlphabet')} of
+ {'UniversalString',{_,_Sv}} ->
+ exit({error,{asn1,{'not implemented',"UniversalString with PermittedAlphabet constraint"}}});
+ {'BMPString',{_,_Sv}} ->
+ exit({error,{asn1,{'not implemented',"BMPString with PermittedAlphabet constraint"}}});
+ _ ->
+ {NumBits,CharOutTab} = {get_NumBits(C,StringType),get_CharOutTab(C,StringType)},
+ chars_encode2(Value,NumBits,CharOutTab)
+ end.
+
+chars_encode2([H|T],NumBits,{Min,Max,notab}) when H =< Max, H >= Min ->
+ [{bits,NumBits,H-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
+chars_encode2([H|T],NumBits,{Min,Max,Tab}) when H =< Max, H >= Min ->
+ [{bits,NumBits,element(H-Min+1,Tab)}|chars_encode2(T,NumBits,{Min,Max,Tab})];
+chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,notab}) ->
+ %% no value range check here (ought to be, but very expensive)
+ [{bits,NumBits,(A*B*C*D)-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
+chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,Tab}) ->
+ %% no value range check here (ought to be, but very expensive)
+ [{bits,NumBits,element((A*B*C*D)-Min,Tab)}|chars_encode2(T,NumBits,{Min,Max,notab})];
+chars_encode2([H|_T],_NumBits,{_Min,_Max,_Tab}) ->
+ exit({error,{asn1,{illegal_char_value,H}}});
+chars_encode2([],_,_) ->
+ [].
+
+
+get_NumBits(C,StringType) ->
+ case get_constraint(C,'PermittedAlphabet') of
+ {'SingleValue',Sv} ->
+ charbits(length(Sv),aligned);
+ no ->
+ case StringType of
+ 'GeneralString' ->
+ exit({error,{asn1,{not implemented,'GeneralString'}}});
+ 'GraphicString' ->
+ exit({error,{asn1,{not implemented,'GraphicString'}}});
+ 'TeletexString' ->
+ exit({error,{asn1,{not implemented,'TeletexString'}}});
+ 'VideotexString' ->
+ exit({error,{asn1,{not implemented,'VideotexString'}}});
+ 'IA5String' ->
+ charbits(128,aligned); % 16#00..16#7F
+ 'VisibleString' ->
+ charbits(95,aligned); % 16#20..16#7E
+ 'PrintableString' ->
+ charbits(74,aligned); % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
+ 'NumericString' ->
+ charbits(11,aligned); % $ ,"0123456789"
+ 'UniversalString' ->
+ 32;
+ 'BMPString' ->
+ 16
+ end
+ end.
+
+%%Maybe used later
+%%get_MaxChar(C,StringType) ->
+%% case get_constraint(C,'PermittedAlphabet') of
+%% {'SingleValue',Sv} ->
+%% lists:nth(length(Sv),Sv);
+%% no ->
+%% case StringType of
+%% 'IA5String' ->
+%% 16#7F; % 16#00..16#7F
+%% 'VisibleString' ->
+%% 16#7E; % 16#20..16#7E
+%% 'PrintableString' ->
+%% $z; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
+%% 'NumericString' ->
+%% $9; % $ ,"0123456789"
+%% 'UniversalString' ->
+%% 16#ffffffff;
+%% 'BMPString' ->
+%% 16#ffff
+%% end
+%% end.
+
+%%Maybe used later
+%%get_MinChar(C,StringType) ->
+%% case get_constraint(C,'PermittedAlphabet') of
+%% {'SingleValue',Sv} ->
+%% hd(Sv);
+%% no ->
+%% case StringType of
+%% 'IA5String' ->
+%% 16#00; % 16#00..16#7F
+%% 'VisibleString' ->
+%% 16#20; % 16#20..16#7E
+%% 'PrintableString' ->
+%% $\s; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
+%% 'NumericString' ->
+%% $\s; % $ ,"0123456789"
+%% 'UniversalString' ->
+%% 16#00;
+%% 'BMPString' ->
+%% 16#00
+%% end
+%% end.
+
+get_CharOutTab(C,StringType) ->
+ get_CharTab(C,StringType,out).
+
+get_CharInTab(C,StringType) ->
+ get_CharTab(C,StringType,in).
+
+get_CharTab(C,StringType,InOut) ->
+ case get_constraint(C,'PermittedAlphabet') of
+ {'SingleValue',Sv} ->
+ get_CharTab2(C,StringType,hd(Sv),lists:max(Sv),Sv,InOut);
+ no ->
+ case StringType of
+ 'IA5String' ->
+ {0,16#7F,notab};
+ 'VisibleString' ->
+ get_CharTab2(C,StringType,16#20,16#7F,notab,InOut);
+ 'PrintableString' ->
+ Chars = lists:sort(
+ " '()+,-./0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
+ get_CharTab2(C,StringType,hd(Chars),lists:max(Chars),Chars,InOut);
+ 'NumericString' ->
+ get_CharTab2(C,StringType,16#20,$9," 0123456789",InOut);
+ 'UniversalString' ->
+ {0,16#FFFFFFFF,notab};
+ 'BMPString' ->
+ {0,16#FFFF,notab}
+ end
+ end.
+
+get_CharTab2(C,StringType,Min,Max,Chars,InOut) ->
+ BitValMax = (1 bsl get_NumBits(C,StringType))-1,
+ if
+ Max =< BitValMax ->
+ {0,Max,notab};
+ true ->
+ case InOut of
+ out ->
+ {Min,Max,create_char_tab(Min,Chars)};
+ in ->
+ {Min,Max,list_to_tuple(Chars)}
+ end
+ end.
+
+create_char_tab(Min,L) ->
+ list_to_tuple(create_char_tab(Min,L,0)).
+create_char_tab(Min,[Min|T],V) ->
+ [V|create_char_tab(Min+1,T,V+1)];
+create_char_tab(_Min,[],_V) ->
+ [];
+create_char_tab(Min,L,V) ->
+ [false|create_char_tab(Min+1,L,V)].
+
+%% This very inefficient and should be moved to compiletime
+charbits(NumOfChars,aligned) ->
+ case charbits(NumOfChars) of
+ 1 -> 1;
+ 2 -> 2;
+ B when B > 2, B =< 4 -> 4;
+ B when B > 4, B =< 8 -> 8;
+ B when B > 8, B =< 16 -> 16;
+ B when B > 16, B =< 32 -> 32
+ end.
+
+charbits(NumOfChars) when NumOfChars =< 2 -> 1;
+charbits(NumOfChars) when NumOfChars =< 4 -> 2;
+charbits(NumOfChars) when NumOfChars =< 8 -> 3;
+charbits(NumOfChars) when NumOfChars =< 16 -> 4;
+charbits(NumOfChars) when NumOfChars =< 32 -> 5;
+charbits(NumOfChars) when NumOfChars =< 64 -> 6;
+charbits(NumOfChars) when NumOfChars =< 128 -> 7;
+charbits(NumOfChars) when NumOfChars =< 256 -> 8;
+charbits(NumOfChars) when NumOfChars =< 512 -> 9;
+charbits(NumOfChars) when NumOfChars =< 1024 -> 10;
+charbits(NumOfChars) when NumOfChars =< 2048 -> 11;
+charbits(NumOfChars) when NumOfChars =< 4096 -> 12;
+charbits(NumOfChars) when NumOfChars =< 8192 -> 13;
+charbits(NumOfChars) when NumOfChars =< 16384 -> 14;
+charbits(NumOfChars) when NumOfChars =< 32768 -> 15;
+charbits(NumOfChars) when NumOfChars =< 65536 -> 16;
+charbits(NumOfChars) when integer(NumOfChars) ->
+ 16 + charbits1(NumOfChars bsr 16).
+
+charbits1(0) ->
+ 0;
+charbits1(NumOfChars) ->
+ 1 + charbits1(NumOfChars bsr 1).
+
+
+chars_decode(Bytes,_,'BMPString',C,Len) ->
+ case get_constraint(C,'PermittedAlphabet') of
+ no ->
+ getBMPChars(Bytes,Len);
+ _ ->
+ exit({error,{asn1,
+ {'not implemented',
+ "BMPString with PermittedAlphabet constraint"}}})
+ end;
+chars_decode(Bytes,NumBits,StringType,C,Len) ->
+ CharInTab = get_CharInTab(C,StringType),
+ chars_decode2(Bytes,CharInTab,NumBits,Len).
+
+
+chars_decode2(Bytes,CharInTab,NumBits,Len) ->
+ chars_decode2(Bytes,CharInTab,NumBits,Len,[]).
+
+chars_decode2(Bytes,_CharInTab,_NumBits,0,Acc) ->
+ {lists:reverse(Acc),Bytes};
+chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) when NumBits > 8 ->
+ {Char,Bytes2} = getbits(Bytes,NumBits),
+ Result = case minimum_octets(Char+Min) of
+ [NewChar] -> NewChar;
+ [C1,C2] -> {0,0,C1,C2};
+ [C1,C2,C3] -> {0,C1,C2,C3};
+ [C1,C2,C3,C4] -> {C1,C2,C3,C4}
+ end,
+ chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Result|Acc]);
+chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) ->
+ {Char,Bytes2} = getbits(Bytes,NumBits),
+ chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Char+Min|Acc]);
+
+%% BMPString and UniversalString with PermittedAlphabet is currently not supported
+chars_decode2(Bytes,{Min,Max,CharInTab},NumBits,Len,Acc) ->
+ {Char,Bytes2} = getbits(Bytes,NumBits),
+ chars_decode2(Bytes2,{Min,Max,CharInTab},NumBits,Len -1,[element(Char+1,CharInTab)|Acc]).
+
+
+ % X.691:17
+encode_null({Name,Val}) when atom(Name) ->
+ encode_null(Val);
+encode_null(_) -> []. % encodes to nothing
+
+decode_null(Bytes) ->
+ {'NULL',Bytes}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_object_identifier(Val) -> CompleteList
+%% encode_object_identifier({Name,Val}) -> CompleteList
+%% Val -> {Int1,Int2,...,IntN} % N >= 2
+%% Name -> atom()
+%% Int1 -> integer(0..2)
+%% Int2 -> integer(0..39) when Int1 (0..1) else integer()
+%% Int3-N -> integer()
+%% CompleteList -> [{bits,8,Val}|{octets,Ol}|align|...]
+%%
+encode_object_identifier(Val) ->
+ Octets = e_object_identifier(Val,notag),
+ [{debug,object_identifier},encode_length(undefined,length(Octets)),{octets,Octets}].
+
+%% This code is copied from asn1_encode.erl (BER) and corrected and modified
+
+e_object_identifier({'OBJECT IDENTIFIER',V},DoTag) ->
+ e_object_identifier(V,DoTag);
+e_object_identifier({Cname,V},DoTag) when atom(Cname),tuple(V) ->
+ e_object_identifier(tuple_to_list(V),DoTag);
+e_object_identifier({Cname,V},DoTag) when atom(Cname),list(V) ->
+ e_object_identifier(V,DoTag);
+e_object_identifier(V,DoTag) when tuple(V) ->
+ e_object_identifier(tuple_to_list(V),DoTag);
+
+% E1 = 0|1|2 and (E2 < 40 when E1 = 0|1)
+e_object_identifier([E1,E2|Tail],_DoTag) when E1 =< 2 ->
+ Head = 40*E1 + E2, % weird
+ Res = e_object_elements([Head|Tail]),
+% dotag(DoTag,[6],elength(length(Res)+1),[Head|Res]),
+ Res.
+
+e_object_elements([]) ->
+ [];
+e_object_elements([H|T]) ->
+ lists:append(e_object_element(H),e_object_elements(T)).
+
+e_object_element(Num) when Num < 128 ->
+ [Num];
+% must be changed to handle more than 2 octets
+e_object_element(Num) -> %% when Num < ???
+ Left = ((Num band 2#11111110000000) bsr 7) bor 2#10000000,
+ Right = Num band 2#1111111 ,
+ [Left,Right].
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% decode_object_identifier(Bytes) -> {ObjId,RemainingBytes}
+%% ObjId -> {integer(),integer(),...} % at least 2 integers
+%% RemainingBytes -> [integer()] when integer() (0..255)
+decode_object_identifier(Bytes) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
+ [First|Rest] = dec_subidentifiers(Octs,0,[]),
+ Idlist = if
+ First < 40 ->
+ [0,First|Rest];
+ First < 80 ->
+ [1,First - 40|Rest];
+ true ->
+ [2,First - 80|Rest]
+ end,
+ {list_to_tuple(Idlist),Bytes3}.
+
+dec_subidentifiers([H|T],Av,Al) when H >=16#80 ->
+ dec_subidentifiers(T,(Av bsl 7) + (H band 16#7F),Al);
+dec_subidentifiers([H|T],Av,Al) ->
+ dec_subidentifiers(T,0,[(Av bsl 7) + H |Al]);
+dec_subidentifiers([],_Av,Al) ->
+ lists:reverse(Al).
+
+get_constraint(C,Key) ->
+ case lists:keysearch(Key,1,C) of
+ false ->
+ no;
+ {value,{_,V}} ->
+ V
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% complete(InList) -> ByteList
+%% Takes a coded list with bits and bytes and converts it to a list of bytes
+%% Should be applied as the last step at encode of a complete ASN.1 type
+%%
+complete(InList) when list(InList) ->
+ complete(InList,[],0);
+complete(InList) ->
+ complete([InList],[],0).
+
+complete([{debug,_}|T], Acc, Acclen) ->
+ complete(T,Acc,Acclen);
+complete([H|T],Acc,Acclen) when list(H) ->
+ complete(lists:concat([H,T]),Acc,Acclen);
+
+
+complete([{octets,N,Val}|T],Acc,Acclen) when N =< 4 ,integer(Val) ->
+ Newval = case N of
+ 1 ->
+ Val4 = Val band 16#FF,
+ [Val4];
+ 2 ->
+ Val3 = (Val bsr 8) band 16#FF,
+ Val4 = Val band 16#FF,
+ [Val3,Val4];
+ 3 ->
+ Val2 = (Val bsr 16) band 16#FF,
+ Val3 = (Val bsr 8) band 16#FF,
+ Val4 = Val band 16#FF,
+ [Val2,Val3,Val4];
+ 4 ->
+ Val1 = (Val bsr 24) band 16#FF,
+ Val2 = (Val bsr 16) band 16#FF,
+ Val3 = (Val bsr 8) band 16#FF,
+ Val4 = Val band 16#FF,
+ [Val1,Val2,Val3,Val4]
+ end,
+ complete([{octets,Newval}|T],Acc,Acclen);
+
+complete([{octets,Oct}|T],[],_Acclen) when list(Oct) ->
+ complete(T,lists:reverse(Oct),0);
+complete([{octets,Oct}|T],[Hacc|Tacc],Acclen) when list(Oct) ->
+ Rest = 8 - Acclen,
+ if
+ Rest == 8 ->
+ complete(T,lists:concat([lists:reverse(Oct),[Hacc|Tacc]]),0);
+ true ->
+ complete(T,lists:concat([lists:reverse(Oct),[Hacc bsl Rest|Tacc]]),0)
+ end;
+
+complete([{bit,Val}|T], Acc, Acclen) ->
+ complete([{bits,1,Val}|T],Acc,Acclen);
+complete([{octet,Val}|T], Acc, Acclen) ->
+ complete([{octets,1,Val}|T],Acc,Acclen);
+
+complete([{bits,N,Val}|T], Acc, 0) when N =< 8 ->
+ complete(T,[Val|Acc],N);
+complete([{bits,N,Val}|T], [Hacc|Tacc], Acclen) when N =< 8 ->
+ Rest = 8 - Acclen,
+ if
+ Rest >= N ->
+ complete(T,[(Hacc bsl N) + Val|Tacc],(Acclen+N) rem 8);
+ true ->
+ Diff = N - Rest,
+ NewHacc = (Hacc bsl Rest) + (Val bsr Diff),
+ Mask = element(Diff,{1,3,7,15,31,63,127,255}),
+ complete(T,[(Val band Mask),NewHacc|Tacc],(Acclen+N) rem 8)
+ end;
+complete([{bits,N,Val}|T], Acc, Acclen) -> % N > 8
+ complete([{bits,N-8,Val bsr 8},{bits,8,Val band 255}|T],Acc,Acclen);
+
+complete([align|T],Acc,0) ->
+ complete(T,Acc,0);
+complete([align|T],[Hacc|Tacc],Acclen) ->
+ Rest = 8 - Acclen,
+ complete(T,[Hacc bsl Rest|Tacc],0);
+complete([{octets,_N,Val}|T],Acc,Acclen) when list(Val) -> % no security check here
+ complete([{octets,Val}|T],Acc,Acclen);
+complete([],Acc,0) ->
+ lists:reverse(Acc);
+complete([],[Hacc|Tacc],Acclen) when Acclen > 0->
+ Rest = 8 - Acclen,
+ NewHacc = Hacc bsl Rest,
+ lists:reverse([NewHacc|Tacc]).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per_bin.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per_bin.erl
new file mode 100644
index 0000000000..8b4512b58e
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per_bin.erl
@@ -0,0 +1,2176 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1rt_per_bin.erl,v 1.1 2008/12/17 09:53:31 mikpe Exp $
+%%
+-module(asn1rt_per_bin).
+
+%% encoding / decoding of PER aligned
+
+-include("asn1_records.hrl").
+
+-export([dec_fixup/3, cindex/3, list_to_record/2]).
+-export([setchoiceext/1, setext/1, fixoptionals/2, fixoptionals/3,
+ fixextensions/2,
+ getext/1, getextension/2, skipextensions/3, getbit/1, getchoice/3 ]).
+-export([getoptionals/2, getoptionals2/2, set_choice/3, encode_integer/2, encode_integer/3 ]).
+-export([decode_integer/2, decode_integer/3, encode_small_number/1, encode_boolean/1,
+ decode_boolean/1, encode_length/2, decode_length/1, decode_length/2,
+ encode_small_length/1, decode_small_length/1,
+ decode_compact_bit_string/3]).
+-export([decode_enumerated/3,
+ encode_bit_string/3, decode_bit_string/3 ]).
+-export([encode_octet_string/2, decode_octet_string/2,
+ encode_null/1, decode_null/1,
+ encode_object_identifier/1, decode_object_identifier/1,
+ complete/1]).
+
+
+-export([encode_open_type/2, decode_open_type/2]).
+
+-export([encode_UniversalString/2, decode_UniversalString/2,
+ encode_PrintableString/2, decode_PrintableString/2,
+ encode_GeneralString/2, decode_GeneralString/2,
+ encode_GraphicString/2, decode_GraphicString/2,
+ encode_TeletexString/2, decode_TeletexString/2,
+ encode_VideotexString/2, decode_VideotexString/2,
+ encode_VisibleString/2, decode_VisibleString/2,
+ encode_BMPString/2, decode_BMPString/2,
+ encode_IA5String/2, decode_IA5String/2,
+ encode_NumericString/2, decode_NumericString/2,
+ encode_ObjectDescriptor/2, decode_ObjectDescriptor/1
+ ]).
+-export([complete_bytes/1]).
+
+-define('16K',16384).
+-define('32K',32768).
+-define('64K',65536).
+
+dec_fixup(Terms,Cnames,RemBytes) ->
+ dec_fixup(Terms,Cnames,RemBytes,[]).
+
+dec_fixup([novalue|T],[_Hc|Tc],RemBytes,Acc) ->
+ dec_fixup(T,Tc,RemBytes,Acc);
+dec_fixup([{_Name,novalue}|T],[_Hc|Tc],RemBytes,Acc) ->
+ dec_fixup(T,Tc,RemBytes,Acc);
+dec_fixup([H|T],[Hc|Tc],RemBytes,Acc) ->
+ dec_fixup(T,Tc,RemBytes,[{Hc,H}|Acc]);
+dec_fixup([],_Cnames,RemBytes,Acc) ->
+ {lists:reverse(Acc),RemBytes}.
+
+cindex(Ix,Val,Cname) ->
+ case element(Ix,Val) of
+ {Cname,Val2} -> Val2;
+ X -> X
+ end.
+
+%% converts a list to a record if necessary
+list_to_record(_Name,Tuple) when tuple(Tuple) ->
+ Tuple;
+list_to_record(Name,List) when list(List) ->
+ list_to_tuple([Name|List]).
+
+%%--------------------------------------------------------
+%% setchoiceext(InRootSet) -> [{bit,X}]
+%% X is set to 1 when InRootSet==false
+%% X is set to 0 when InRootSet==true
+%%
+setchoiceext(true) ->
+ [{debug,choiceext},{bits,1,0}];
+setchoiceext(false) ->
+ [{debug,choiceext},{bits,1,1}].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% setext(true|false) -> CompleteList
+%%
+
+setext(false) ->
+ [{debug,ext},{bits,1,0}];
+setext(true) ->
+ [{debug,ext},{bits,1,1}].
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% This version of fixoptionals/2 are left only because of
+%% backward compatibility with older generates
+
+fixoptionals(OptList,Val) when tuple(Val) ->
+ fixoptionals1(OptList,Val,[]);
+
+fixoptionals(OptList,Val) when list(Val) ->
+ fixoptionals1(OptList,Val,1,[],[]).
+
+fixoptionals1([],Val,Acc) ->
+ %% return {Val,Opt}
+ {Val,lists:reverse(Acc)};
+fixoptionals1([{_,Pos}|Ot],Val,Acc) ->
+ case element(Pos+1,Val) of
+ asn1_NOVALUE -> fixoptionals1(Ot,Val,[0|Acc]);
+ asn1_DEFAULT -> fixoptionals1(Ot,Val,[0|Acc]);
+ _ -> fixoptionals1(Ot,Val,[1|Acc])
+ end.
+
+
+fixoptionals1([{Name,Pos}|Ot],[{Name,Val}|Vt],_Opt,Acc1,Acc2) ->
+ fixoptionals1(Ot,Vt,Pos+1,[1|Acc1],[{Name,Val}|Acc2]);
+fixoptionals1([{_Name,Pos}|Ot],V,Pos,Acc1,Acc2) ->
+ fixoptionals1(Ot,V,Pos+1,[0|Acc1],[asn1_NOVALUE|Acc2]);
+fixoptionals1(O,[Vh|Vt],Pos,Acc1,Acc2) ->
+ fixoptionals1(O,Vt,Pos+1,Acc1,[Vh|Acc2]);
+fixoptionals1([],[Vh|Vt],Pos,Acc1,Acc2) ->
+ fixoptionals1([],Vt,Pos+1,Acc1,[Vh|Acc2]);
+fixoptionals1([],[],_,Acc1,Acc2) ->
+ % return {Val,Opt}
+ {list_to_tuple([asn1_RECORDNAME|lists:reverse(Acc2)]),lists:reverse(Acc1)}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% This is the new fixoptionals/3 which is used by the new generates
+%%
+fixoptionals(OptList,OptLength,Val) when tuple(Val) ->
+ Bits = fixoptionals(OptList,Val,0),
+ {Val,{bits,OptLength,Bits}};
+
+fixoptionals([],_Val,Acc) ->
+ %% Optbits
+ Acc;
+fixoptionals([Pos|Ot],Val,Acc) ->
+ case element(Pos,Val) of
+ asn1_NOVALUE -> fixoptionals(Ot,Val,Acc bsl 1);
+ asn1_DEFAULT -> fixoptionals(Ot,Val,Acc bsl 1);
+ _ -> fixoptionals(Ot,Val,(Acc bsl 1) + 1)
+ end.
+
+
+getext(Bytes) when tuple(Bytes) ->
+ getbit(Bytes);
+getext(Bytes) when binary(Bytes) ->
+ getbit({0,Bytes});
+getext(Bytes) when list(Bytes) ->
+ getbit({0,Bytes}).
+
+getextension(0, Bytes) ->
+ {{},Bytes};
+getextension(1, Bytes) ->
+ {Len,Bytes2} = decode_small_length(Bytes),
+ {Blist, Bytes3} = getbits_as_list(Len,Bytes2),
+ {list_to_tuple(Blist),Bytes3}.
+
+fixextensions({ext,ExtPos,ExtNum},Val) ->
+ case fixextensions(ExtPos,ExtNum+ExtPos,Val,0) of
+ 0 -> [];
+ ExtBits ->
+ [encode_small_length(ExtNum),{bits,ExtNum,ExtBits}]
+ end.
+
+fixextensions(Pos,MaxPos,_,Acc) when Pos >= MaxPos ->
+ Acc;
+fixextensions(Pos,ExtPos,Val,Acc) ->
+ Bit = case catch(element(Pos+1,Val)) of
+ asn1_NOVALUE ->
+ 0;
+ asn1_NOEXTVALUE ->
+ 0;
+ {'EXIT',_} ->
+ 0;
+ _ ->
+ 1
+ end,
+ fixextensions(Pos+1,ExtPos,Val,(Acc bsl 1)+Bit).
+
+skipextensions(Bytes,Nr,ExtensionBitPattern) ->
+ case (catch element(Nr,ExtensionBitPattern)) of
+ 1 ->
+ {_,Bytes2} = decode_open_type(Bytes,[]),
+ skipextensions(Bytes2, Nr+1, ExtensionBitPattern);
+ 0 ->
+ skipextensions(Bytes, Nr+1, ExtensionBitPattern);
+ {'EXIT',_} -> % badarg, no more extensions
+ Bytes
+ end.
+
+
+getchoice(Bytes,1,0) -> % only 1 alternative is not encoded
+ {0,Bytes};
+getchoice(Bytes,_,1) ->
+ decode_small_number(Bytes);
+getchoice(Bytes,NumChoices,0) ->
+ decode_constrained_number(Bytes,{0,NumChoices-1}).
+
+%% old version kept for backward compatibility with generates from R7B
+getoptionals(Bytes,NumOpt) ->
+ {Blist,Bytes1} = getbits_as_list(NumOpt,Bytes),
+ {list_to_tuple(Blist),Bytes1}.
+
+%% new version used in generates from r8b_patch/3 and later
+getoptionals2(Bytes,NumOpt) ->
+ getbits(Bytes,NumOpt).
+
+
+%% getbits_as_binary(Num,Bytes) -> {{Unused,BinBits},RestBytes},
+%% Num = integer(),
+%% Bytes = list() | tuple(),
+%% Unused = integer(),
+%% BinBits = binary(),
+%% RestBytes = tuple()
+getbits_as_binary(Num,Bytes) when binary(Bytes) ->
+ getbits_as_binary(Num,{0,Bytes});
+getbits_as_binary(0,Buffer) ->
+ {{0,<<>>},Buffer};
+getbits_as_binary(Num,{0,Bin}) when Num > 16 ->
+ Used = Num rem 8,
+ Pad = (8 - Used) rem 8,
+% Nbytes = Num div 8,
+ <<Bits:Num,_:Pad,RestBin/binary>> = Bin,
+ {{Pad,<<Bits:Num,0:Pad>>},RestBin};
+getbits_as_binary(Num,Buffer={_Used,_Bin}) -> % Unaligned buffer
+ %% Num =< 16,
+ {Bits2,Buffer2} = getbits(Buffer,Num),
+ Pad = (8 - (Num rem 8)) rem 8,
+ {{Pad,<<Bits2:Num,0:Pad>>},Buffer2}.
+
+
+% integer_from_list(Int,[],BigInt) ->
+% BigInt;
+% integer_from_list(Int,[H|T],BigInt) when Int < 8 ->
+% (BigInt bsl Int) bor (H bsr (8-Int));
+% integer_from_list(Int,[H|T],BigInt) ->
+% integer_from_list(Int-8,T,(BigInt bsl 8) bor H).
+
+getbits_as_list(Num,Bytes) when binary(Bytes) ->
+ getbits_as_list(Num,{0,Bytes},[]);
+getbits_as_list(Num,Bytes) ->
+ getbits_as_list(Num,Bytes,[]).
+
+%% If buffer is empty and nothing more will be picked.
+getbits_as_list(0, B, Acc) ->
+ {lists:reverse(Acc),B};
+%% If first byte in buffer is full and at least one byte will be picked,
+%% then pick one byte.
+getbits_as_list(N,{0,Bin},Acc) when N >= 8 ->
+ <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Rest/binary>> = Bin,
+ getbits_as_list(N-8,{0,Rest},[B0,B1,B2,B3,B4,B5,B6,B7|Acc]);
+getbits_as_list(N,{Used,Bin},Acc) when N >= 4, Used =< 4 ->
+ NewUsed = Used + 4,
+ Rem = 8 - NewUsed,
+ <<_:Used,B3:1,B2:1,B1:1,B0:1,_:Rem, Rest/binary>> = Bin,
+ NewRest = case Rem of 0 -> Rest; _ -> Bin end,
+ getbits_as_list(N-4,{NewUsed rem 8,NewRest},[B0,B1,B2,B3|Acc]);
+getbits_as_list(N,{Used,Bin},Acc) when N >= 2, Used =< 6 ->
+ NewUsed = Used + 2,
+ Rem = 8 - NewUsed,
+ <<_:Used,B1:1,B0:1,_:Rem, Rest/binary>> = Bin,
+ NewRest = case Rem of 0 -> Rest; _ -> Bin end,
+ getbits_as_list(N-2,{NewUsed rem 8,NewRest},[B0,B1|Acc]);
+getbits_as_list(N,{Used,Bin},Acc) when Used =< 7 ->
+ NewUsed = Used + 1,
+ Rem = 8 - NewUsed,
+ <<_:Used,B0:1,_:Rem, Rest/binary>> = Bin,
+ NewRest = case Rem of 0 -> Rest; _ -> Bin end,
+ getbits_as_list(N-1,{NewUsed rem 8,NewRest},[B0|Acc]).
+
+
+getbit({7,<<_:7,B:1,Rest/binary>>}) ->
+ {B,{0,Rest}};
+getbit({0,Buffer = <<B:1,_:7,_/binary>>}) ->
+ {B,{1,Buffer}};
+getbit({Used,Buffer}) ->
+ Unused = (8 - Used) - 1,
+ <<_:Used,B:1,_:Unused,_/binary>> = Buffer,
+ {B,{Used+1,Buffer}};
+getbit(Buffer) when binary(Buffer) ->
+ getbit({0,Buffer}).
+
+
+getbits({0,Buffer},Num) when (Num rem 8) == 0 ->
+ <<Bits:Num,Rest/binary>> = Buffer,
+ {Bits,{0,Rest}};
+getbits({Used,Bin},Num) ->
+ NumPlusUsed = Num + Used,
+ NewUsed = NumPlusUsed rem 8,
+ Unused = (8-NewUsed) rem 8,
+ case Unused of
+ 0 ->
+ <<_:Used,Bits:Num,Rest/binary>> = Bin,
+ {Bits,{0,Rest}};
+ _ ->
+ Bytes = NumPlusUsed div 8,
+ <<_:Used,Bits:Num,_UBits:Unused,_/binary>> = Bin,
+ <<_:Bytes/binary,Rest/binary>> = Bin,
+ {Bits,{NewUsed,Rest}}
+ end;
+getbits(Bin,Num) when binary(Bin) ->
+ getbits({0,Bin},Num).
+
+
+
+% getoctet(Bytes) when list(Bytes) ->
+% getoctet({0,Bytes});
+% getoctet(Bytes) ->
+% %% io:format("getoctet:Buffer = ~p~n",[Bytes]),
+% getoctet1(Bytes).
+
+% getoctet1({0,[H|T]}) ->
+% {H,{0,T}};
+% getoctet1({Pos,[_,H|T]}) ->
+% {H,{0,T}}.
+
+align({0,L}) ->
+ {0,L};
+align({_Pos,<<_H,T/binary>>}) ->
+ {0,T};
+align(Bytes) ->
+ {0,Bytes}.
+
+%% First align buffer, then pick the first Num octets.
+%% Returns octets as an integer with bit significance as in buffer.
+getoctets({0,Buffer},Num) ->
+ <<Val:Num/integer-unit:8,RestBin/binary>> = Buffer,
+ {Val,{0,RestBin}};
+getoctets({U,<<_Padding,Rest/binary>>},Num) when U /= 0 ->
+ getoctets({0,Rest},Num);
+getoctets(Buffer,Num) when binary(Buffer) ->
+ getoctets({0,Buffer},Num).
+% getoctets(Buffer,Num) ->
+% %% io:format("getoctets:Buffer = ~p~nNum = ~p~n",[Buffer,Num]),
+% getoctets(Buffer,Num,0).
+
+% getoctets(Buffer,0,Acc) ->
+% {Acc,Buffer};
+% getoctets(Buffer,Num,Acc) ->
+% {Oct,NewBuffer} = getoctet(Buffer),
+% getoctets(NewBuffer,Num-1,(Acc bsl 8)+Oct).
+
+% getoctets_as_list(Buffer,Num) ->
+% getoctets_as_list(Buffer,Num,[]).
+
+% getoctets_as_list(Buffer,0,Acc) ->
+% {lists:reverse(Acc),Buffer};
+% getoctets_as_list(Buffer,Num,Acc) ->
+% {Oct,NewBuffer} = getoctet(Buffer),
+% getoctets_as_list(NewBuffer,Num-1,[Oct|Acc]).
+
+%% First align buffer, then pick the first Num octets.
+%% Returns octets as a binary
+getoctets_as_bin({0,Bin},Num)->
+ <<Octets:Num/binary,RestBin/binary>> = Bin,
+ {Octets,{0,RestBin}};
+getoctets_as_bin({_U,Bin},Num) ->
+ <<_Padding,Octets:Num/binary,RestBin/binary>> = Bin,
+ {Octets,{0,RestBin}};
+getoctets_as_bin(Bin,Num) when binary(Bin) ->
+ getoctets_as_bin({0,Bin},Num).
+
+%% same as above but returns octets as a List
+getoctets_as_list(Buffer,Num) ->
+ {Bin,Buffer2} = getoctets_as_bin(Buffer,Num),
+ {binary_to_list(Bin),Buffer2}.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% set_choice(Alt,Choices,Altnum) -> ListofBitSettings
+%% Alt = atom()
+%% Altnum = integer() | {integer(),integer()}% number of alternatives
+%% Choices = [atom()] | {[atom()],[atom()]}
+%% When Choices is a tuple the first list is the Rootset and the
+%% second is the Extensions and then Altnum must also be a tuple with the
+%% lengths of the 2 lists
+%%
+set_choice(Alt,{L1,L2},{Len1,_Len2}) ->
+ case set_choice_tag(Alt,L1) of
+ N when integer(N), Len1 > 1 ->
+ [{bits,1,0}, % the value is in the root set
+ encode_integer([{'ValueRange',{0,Len1-1}}],N)];
+ N when integer(N) ->
+ [{bits,1,0}]; % no encoding if only 0 or 1 alternative
+ false ->
+ [{bits,1,1}, % extension value
+ case set_choice_tag(Alt,L2) of
+ N2 when integer(N2) ->
+ encode_small_number(N2);
+ false ->
+ unknown_choice_alt
+ end]
+ end;
+set_choice(Alt,L,Len) ->
+ case set_choice_tag(Alt,L) of
+ N when integer(N), Len > 1 ->
+ encode_integer([{'ValueRange',{0,Len-1}}],N);
+ N when integer(N) ->
+ []; % no encoding if only 0 or 1 alternative
+ false ->
+ [unknown_choice_alt]
+ end.
+
+set_choice_tag(Alt,Choices) ->
+ set_choice_tag(Alt,Choices,0).
+
+set_choice_tag(Alt,[Alt|_Rest],Tag) ->
+ Tag;
+set_choice_tag(Alt,[_H|Rest],Tag) ->
+ set_choice_tag(Alt,Rest,Tag+1);
+set_choice_tag(_Alt,[],_Tag) ->
+ false.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% decode_fragmented_XXX; decode of values encoded fragmented according
+%% to ITU-T X.691 clause 10.9.3.8. The unit (XXX) is either bits, octets,
+%% characters or number of components (in a choice,sequence or similar).
+%% Buffer is a buffer {Used, Bin}.
+%% C is the constrained length.
+%% If the buffer is not aligned, this function does that.
+decode_fragmented_bits({0,Buffer},C) ->
+ decode_fragmented_bits(Buffer,C,[]);
+decode_fragmented_bits({_N,<<_,Bs/binary>>},C) ->
+ decode_fragmented_bits(Bs,C,[]).
+
+decode_fragmented_bits(<<3:2,Len:6,Bin/binary>>,C,Acc) ->
+ {Value,Bin2} = split_binary(Bin, Len * ?'16K'),
+ decode_fragmented_bits(Bin2,C,[Value,Acc]);
+decode_fragmented_bits(<<0:1,0:7,Bin/binary>>,C,Acc) ->
+ BinBits = list_to_binary(lists:reverse(Acc)),
+ case C of
+ Int when integer(Int),C == size(BinBits) ->
+ {BinBits,{0,Bin}};
+ Int when integer(Int) ->
+ exit({error,{asn1,{illegal_value,C,BinBits}}});
+ _ ->
+ {BinBits,{0,Bin}}
+ end;
+decode_fragmented_bits(<<0:1,Len:7,Bin/binary>>,C,Acc) ->
+ Result = {BinBits,{Used,_Rest}} =
+ case (Len rem 8) of
+ 0 ->
+ <<Value:Len/binary-unit:1,Bin2/binary>> = Bin,
+ {list_to_binary(lists:reverse([Value|Acc])),{0,Bin2}};
+ Rem ->
+ Bytes = Len div 8,
+ U = 8 - Rem,
+ <<Value:Bytes/binary-unit:8,Bits1:Rem,Bits2:U,Bin2/binary>> = Bin,
+ {list_to_binary(lists:reverse([Bits1 bsl U,Value|Acc])),
+ {Rem,<<Bits2,Bin2/binary>>}}
+ end,
+ case C of
+ Int when integer(Int),C == (size(BinBits) - ((8 - Used) rem 8)) ->
+ Result;
+ Int when integer(Int) ->
+ exit({error,{asn1,{illegal_value,C,BinBits}}});
+ _ ->
+ Result
+ end.
+
+
+decode_fragmented_octets({0,Bin},C) ->
+ decode_fragmented_octets(Bin,C,[]);
+decode_fragmented_octets({_N,<<_,Bs/binary>>},C) ->
+ decode_fragmented_octets(Bs,C,[]).
+
+decode_fragmented_octets(<<3:2,Len:6,Bin/binary>>,C,Acc) ->
+ {Value,Bin2} = split_binary(Bin,Len * ?'16K'),
+ decode_fragmented_octets(Bin2,C,[Value,Acc]);
+decode_fragmented_octets(<<0:1,0:7,Bin/binary>>,C,Acc) ->
+ Octets = list_to_binary(lists:reverse(Acc)),
+ case C of
+ Int when integer(Int), C == size(Octets) ->
+ {Octets,{0,Bin}};
+ Int when integer(Int) ->
+ exit({error,{asn1,{illegal_value,C,Octets}}});
+ _ ->
+ {Octets,{0,Bin}}
+ end;
+decode_fragmented_octets(<<0:1,Len:7,Bin/binary>>,C,Acc) ->
+ <<Value:Len/binary-unit:8,Bin2/binary>> = Bin,
+ BinOctets = list_to_binary(lists:reverse([Value|Acc])),
+ case C of
+ Int when integer(Int),size(BinOctets) == Int ->
+ {BinOctets,Bin2};
+ Int when integer(Int) ->
+ exit({error,{asn1,{illegal_value,C,BinOctets}}});
+ _ ->
+ {BinOctets,Bin2}
+ end.
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_open_type(Constraint, Value) -> CompleteList
+%% Value = list of bytes of an already encoded value (the list must be flat)
+%% | binary
+%% Contraint = not used in this version
+%%
+encode_open_type(_C, Val) when list(Val) ->
+ Bin = list_to_binary(Val),
+ [encode_length(undefined,size(Bin)),{octets,Bin}]; % octets implies align
+encode_open_type(_C, Val) when binary(Val) ->
+ [encode_length(undefined,size(Val)),{octets,Val}]. % octets implies align
+%% the binary_to_list is not optimal but compatible with the current solution
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% decode_open_type(Buffer,Constraint) -> Value
+%% Constraint is not used in this version
+%% Buffer = [byte] with PER encoded data
+%% Value = [byte] with decoded data (which must be decoded again as some type)
+%%
+decode_open_type(Bytes, _C) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ getoctets_as_bin(Bytes2,Len).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_integer(Constraint,Value,NamedNumberList) -> CompleteList
+%% encode_integer(Constraint,Value) -> CompleteList
+%% encode_integer(Constraint,{Name,Value}) -> CompleteList
+%%
+%%
+encode_integer(C,V,NamedNumberList) when atom(V) ->
+ case lists:keysearch(V,1,NamedNumberList) of
+ {value,{_,NewV}} ->
+ encode_integer(C,NewV);
+ _ ->
+ exit({error,{asn1,{namednumber,V}}})
+ end;
+encode_integer(C,V,_NamedNumberList) when integer(V) ->
+ encode_integer(C,V);
+encode_integer(C,{Name,V},NamedNumberList) when atom(Name) ->
+ encode_integer(C,V,NamedNumberList).
+
+encode_integer(C,{Name,Val}) when atom(Name) ->
+ encode_integer(C,Val);
+
+encode_integer([{Rc,_Ec}],Val) when tuple(Rc) -> % XXX when is this invoked? First argument most often a list,...Ok this is the extension case...but it doesn't work.
+ case (catch encode_integer([Rc],Val)) of
+ {'EXIT',{error,{asn1,_}}} ->
+ [{bits,1,1},encode_unconstrained_number(Val)];
+ Encoded ->
+ [{bits,1,0},Encoded]
+ end;
+encode_integer(C,Val ) when list(C) ->
+ case get_constraint(C,'SingleValue') of
+ no ->
+ encode_integer1(C,Val);
+ V when integer(V),V == Val ->
+ []; % a type restricted to a single value encodes to nothing
+ V when list(V) ->
+ case lists:member(Val,V) of
+ true ->
+ encode_integer1(C,Val);
+ _ ->
+ exit({error,{asn1,{illegal_value,Val}}})
+ end;
+ _ ->
+ exit({error,{asn1,{illegal_value,Val}}})
+ end.
+
+encode_integer1(C, Val) ->
+ case VR = get_constraint(C,'ValueRange') of
+ no ->
+ encode_unconstrained_number(Val);
+ {Lb,'MAX'} ->
+ encode_semi_constrained_number(Lb,Val);
+ %% positive with range
+ {Lb,Ub} when Val >= Lb,
+ Ub >= Val ->
+ encode_constrained_number(VR,Val);
+ _ ->
+ exit({error,{asn1,{illegal_value,VR,Val}}})
+ end.
+
+decode_integer(Buffer,Range,NamedNumberList) ->
+ {Val,Buffer2} = decode_integer(Buffer,Range),
+ case lists:keysearch(Val,2,NamedNumberList) of
+ {value,{NewVal,_}} -> {NewVal,Buffer2};
+ _ -> {Val,Buffer2}
+ end.
+
+decode_integer(Buffer,[{Rc,_Ec}]) when tuple(Rc) ->
+ {Ext,Buffer2} = getext(Buffer),
+ case Ext of
+ 0 -> decode_integer(Buffer2,[Rc]);
+ 1 -> decode_unconstrained_number(Buffer2)
+ end;
+decode_integer(Buffer,undefined) ->
+ decode_unconstrained_number(Buffer);
+decode_integer(Buffer,C) ->
+ case get_constraint(C,'SingleValue') of
+ V when integer(V) ->
+ {V,Buffer};
+ V when list(V) ->
+ {Val,Buffer2} = decode_integer1(Buffer,C),
+ case lists:member(Val,V) of
+ true ->
+ {Val,Buffer2};
+ _ ->
+ exit({error,{asn1,{illegal_value,Val}}})
+ end;
+ _ ->
+ decode_integer1(Buffer,C)
+ end.
+
+decode_integer1(Buffer,C) ->
+ case VR = get_constraint(C,'ValueRange') of
+ no ->
+ decode_unconstrained_number(Buffer);
+ {Lb, 'MAX'} ->
+ decode_semi_constrained_number(Buffer,Lb);
+ {_,_} ->
+ decode_constrained_number(Buffer,VR)
+ end.
+
+ % X.691:10.6 Encoding of a normally small non-negative whole number
+ % Use this for encoding of CHOICE index if there is an extension marker in
+ % the CHOICE
+encode_small_number({Name,Val}) when atom(Name) ->
+ encode_small_number(Val);
+encode_small_number(Val) when Val =< 63 ->
+% [{bits,1,0},{bits,6,Val}];
+ [{bits,7,Val}]; % same as above but more efficient
+encode_small_number(Val) ->
+ [{bits,1,1},encode_semi_constrained_number(0,Val)].
+
+decode_small_number(Bytes) ->
+ {Bit,Bytes2} = getbit(Bytes),
+ case Bit of
+ 0 ->
+ getbits(Bytes2,6);
+ 1 ->
+ decode_semi_constrained_number(Bytes2,0)
+ end.
+
+%% X.691:10.7 Encoding of a semi-constrained whole number
+%% might be an optimization encode_semi_constrained_number(0,Val) ->
+encode_semi_constrained_number(C,{Name,Val}) when atom(Name) ->
+ encode_semi_constrained_number(C,Val);
+encode_semi_constrained_number({Lb,'MAX'},Val) ->
+ encode_semi_constrained_number(Lb,Val);
+encode_semi_constrained_number(Lb,Val) ->
+ Val2 = Val - Lb,
+ Oct = eint_positive(Val2),
+ Len = length(Oct),
+ if
+ Len < 128 ->
+ {octets,[Len|Oct]}; % equiv with encode_length(undefined,Len) but faster
+ true ->
+ [encode_length(undefined,Len),{octets,Oct}]
+ end.
+
+decode_semi_constrained_number(Bytes,{Lb,_}) ->
+ decode_semi_constrained_number(Bytes,Lb);
+decode_semi_constrained_number(Bytes,Lb) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ {V,Bytes3} = getoctets(Bytes2,Len),
+ {V+Lb,Bytes3}.
+
+encode_constrained_number(Range,{Name,Val}) when atom(Name) ->
+ encode_constrained_number(Range,Val);
+encode_constrained_number({Lb,Ub},Val) when Val >= Lb, Ub >= Val ->
+ Range = Ub - Lb + 1,
+ Val2 = Val - Lb,
+ if
+ Range == 2 ->
+ {bits,1,Val2};
+ Range =< 4 ->
+ {bits,2,Val2};
+ Range =< 8 ->
+ {bits,3,Val2};
+ Range =< 16 ->
+ {bits,4,Val2};
+ Range =< 32 ->
+ {bits,5,Val2};
+ Range =< 64 ->
+ {bits,6,Val2};
+ Range =< 128 ->
+ {bits,7,Val2};
+ Range =< 255 ->
+ {bits,8,Val2};
+ Range =< 256 ->
+ {octets,[Val2]};
+ Range =< 65536 ->
+ {octets,<<Val2:16>>};
+ Range =< 16#1000000 ->
+ Octs = eint_positive(Val2),
+ [{bits,2,length(Octs)-1},{octets,Octs}];
+ Range =< 16#100000000 ->
+ Octs = eint_positive(Val2),
+ [{bits,2,length(Octs)-1},{octets,Octs}];
+ Range =< 16#10000000000 ->
+ Octs = eint_positive(Val2),
+ [{bits,3,length(Octs)-1},{octets,Octs}];
+ true ->
+ exit({not_supported,{integer_range,Range}})
+ end;
+encode_constrained_number(Range,Val) ->
+ exit({error,{asn1,{integer_range,Range,value,Val}}}).
+
+
+decode_constrained_number(Buffer,{Lb,Ub}) ->
+ Range = Ub - Lb + 1,
+ % Val2 = Val - Lb,
+ {Val,Remain} =
+ if
+ Range == 2 ->
+ getbits(Buffer,1);
+ Range =< 4 ->
+ getbits(Buffer,2);
+ Range =< 8 ->
+ getbits(Buffer,3);
+ Range =< 16 ->
+ getbits(Buffer,4);
+ Range =< 32 ->
+ getbits(Buffer,5);
+ Range =< 64 ->
+ getbits(Buffer,6);
+ Range =< 128 ->
+ getbits(Buffer,7);
+ Range =< 255 ->
+ getbits(Buffer,8);
+ Range =< 256 ->
+ getoctets(Buffer,1);
+ Range =< 65536 ->
+ getoctets(Buffer,2);
+ Range =< 16#1000000 ->
+ {Len,Bytes2} = decode_length(Buffer,{1,3}),
+ {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
+ {dec_pos_integer(Octs),Bytes3};
+ Range =< 16#100000000 ->
+ {Len,Bytes2} = decode_length(Buffer,{1,4}),
+ {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
+ {dec_pos_integer(Octs),Bytes3};
+ Range =< 16#10000000000 ->
+ {Len,Bytes2} = decode_length(Buffer,{1,5}),
+ {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
+ {dec_pos_integer(Octs),Bytes3};
+ true ->
+ exit({not_supported,{integer_range,Range}})
+ end,
+ {Val+Lb,Remain}.
+
+%% X.691:10.8 Encoding of an unconstrained whole number
+
+encode_unconstrained_number(Val) when Val >= 0 ->
+ Oct = eint(Val,[]),
+ Len = length(Oct),
+ if
+ Len < 128 ->
+ {octets,[Len|Oct]}; % equiv with encode_length(undefined,Len) but faster
+ true ->
+ [encode_length(undefined,Len),{octets,Oct}]
+ end;
+encode_unconstrained_number(Val) -> % negative
+ Oct = enint(Val,[]),
+ Len = length(Oct),
+ if
+ Len < 128 ->
+ {octets,[Len|Oct]}; % equiv with encode_length(undefined,Len) but faster
+ true ->
+ [encode_length(undefined,Len),{octets,Oct}]
+ end.
+
+
+%% used for positive Values which don't need a sign bit
+%% returns a binary
+eint_positive(Val) ->
+ case eint(Val,[]) of
+ [0,B1|T] ->
+ [B1|T];
+ T ->
+ T
+ end.
+
+
+eint(0, [B|Acc]) when B < 128 ->
+ [B|Acc];
+eint(N, Acc) ->
+ eint(N bsr 8, [N band 16#ff| Acc]).
+
+enint(-1, [B1|T]) when B1 > 127 ->
+ [B1|T];
+enint(N, Acc) ->
+ enint(N bsr 8, [N band 16#ff|Acc]).
+
+decode_unconstrained_number(Bytes) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ {Ints,Bytes3} = getoctets_as_list(Bytes2,Len),
+ {dec_integer(Ints),Bytes3}.
+
+dec_pos_integer(Ints) ->
+ decpint(Ints, 8 * (length(Ints) - 1)).
+dec_integer(Ints) when hd(Ints) band 255 =< 127 -> %% Positive number
+ decpint(Ints, 8 * (length(Ints) - 1));
+dec_integer(Ints) -> %% Negative
+ decnint(Ints, 8 * (length(Ints) - 1)).
+
+decpint([Byte|Tail], Shift) ->
+ (Byte bsl Shift) bor decpint(Tail, Shift-8);
+decpint([], _) -> 0.
+
+decnint([Byte|Tail], Shift) ->
+ (-128 + (Byte band 127) bsl Shift) bor decpint(Tail, Shift-8).
+
+% minimum_octets(Val) ->
+% minimum_octets(Val,[]).
+
+% minimum_octets(Val,Acc) when Val > 0 ->
+% minimum_octets((Val bsr 8),[Val band 16#FF|Acc]);
+% minimum_octets(0,Acc) ->
+% Acc.
+
+
+%% X.691:10.9 Encoding of a length determinant
+%%encode_small_length(undefined,Len) -> % null means no UpperBound
+%% encode_small_number(Len).
+
+%% X.691:10.9.3.5
+%% X.691:10.9.3.7
+encode_length(undefined,Len) -> % un-constrained
+ if
+ Len < 128 ->
+ {octets,[Len]};
+ Len < 16384 ->
+ {octets,<<2:2,Len:14>>};
+ true -> % should be able to endode length >= 16384
+ exit({error,{asn1,{encode_length,{nyi,above_16k}}}})
+ end;
+
+encode_length({0,'MAX'},Len) ->
+ encode_length(undefined,Len);
+encode_length(Vr={Lb,Ub},Len) when Ub =< 65535 ,Lb >= 0 -> % constrained
+ encode_constrained_number(Vr,Len);
+encode_length({Lb,_Ub},Len) when integer(Lb), Lb >= 0 -> % Ub > 65535
+ encode_length(undefined,Len);
+encode_length({Vr={Lb,Ub},[]},Len) when Ub =< 65535 ,Lb >= 0 ->
+ %% constrained extensible
+ [{bits,1,0},encode_constrained_number(Vr,Len)];
+encode_length(SingleValue,_Len) when integer(SingleValue) ->
+ [].
+
+%% X.691 10.9.3.4 (only used for length of bitmap that prefixes extension
+%% additions in a sequence or set
+encode_small_length(Len) when Len =< 64 ->
+%% [{bits,1,0},{bits,6,Len-1}];
+ {bits,7,Len-1}; % the same as above but more efficient
+encode_small_length(Len) ->
+ [{bits,1,1},encode_length(undefined,Len)].
+
+% decode_small_length({Used,<<_:Used,0:1,Num:6,_:((8-Used+1) rem 8),Rest/binary>>}) ->
+% case Buffer of
+% <<_:Used,0:1,Num:6,_:((8-Used+1) rem 8),Rest/binary>> ->
+% {Num,
+% case getbit(Buffer) of
+% {0,Remain} ->
+% {Bits,Remain2} = getbits(Remain,6),
+% {Bits+1,Remain2};
+% {1,Remain} ->
+% decode_length(Remain,undefined)
+% end.
+
+decode_small_length(Buffer) ->
+ case getbit(Buffer) of
+ {0,Remain} ->
+ {Bits,Remain2} = getbits(Remain,6),
+ {Bits+1,Remain2};
+ {1,Remain} ->
+ decode_length(Remain,undefined)
+ end.
+
+decode_length(Buffer) ->
+ decode_length(Buffer,undefined).
+
+decode_length(Buffer,undefined) -> % un-constrained
+ {0,Buffer2} = align(Buffer),
+ case Buffer2 of
+ <<0:1,Oct:7,Rest/binary>> ->
+ {Oct,{0,Rest}};
+ <<2:2,Val:14,Rest/binary>> ->
+ {Val,{0,Rest}};
+ <<3:2,_:14,_Rest/binary>> ->
+ %% this case should be fixed
+ exit({error,{asn1,{decode_length,{nyi,above_16k}}}})
+ end;
+%% {Bits,_} = getbits(Buffer2,2),
+% case Bits of
+% 2 ->
+% {Val,Bytes3} = getoctets(Buffer2,2),
+% {(Val band 16#3FFF),Bytes3};
+% 3 ->
+% exit({error,{asn1,{decode_length,{nyi,above_16k}}}});
+% _ ->
+% {Val,Bytes3} = getoctet(Buffer2),
+% {Val band 16#7F,Bytes3}
+% end;
+
+decode_length(Buffer,{Lb,Ub}) when Ub =< 65535 ,Lb >= 0 -> % constrained
+ decode_constrained_number(Buffer,{Lb,Ub});
+decode_length(_,{Lb,_}) when integer(Lb), Lb >= 0 -> % Ub > 65535
+ exit({error,{asn1,{decode_length,{nyi,above_64K}}}});
+decode_length(Buffer,{{Lb,Ub},[]}) ->
+ case getbit(Buffer) of
+ {0,Buffer2} ->
+ decode_length(Buffer2, {Lb,Ub})
+ end;
+
+
+%When does this case occur with {_,_Lb,Ub} ??
+% X.691:10.9.3.5
+decode_length({Used,Bin},{_,_Lb,_Ub}) -> %when Len =< 127 -> % Unconstrained or large Ub NOTE! this case does not cover case when Ub > 65535
+ Unused = (8-Used) rem 8,
+ case Bin of
+ <<_:Used,0:1,Val:7,R:Unused,Rest/binary>> ->
+ {Val,{Used,<<R,Rest/binary>>}};
+ <<_:Used,_:Unused,2:2,Val:14,Rest/binary>> ->
+ {Val, {0,Rest}};
+ <<_:Used,_:Unused,3:2,_:14,_Rest/binary>> ->
+ exit({error,{asn1,{decode_length,{nyi,length_above_64K}}}})
+ end;
+% decode_length(Buffer,{_,_Lb,Ub}) -> %when Len =< 127 -> % Unconstrained or large Ub
+% case getbit(Buffer) of
+% {0,Remain} ->
+% getbits(Remain,7);
+% {1,Remain} ->
+% {Val,Remain2} = getoctets(Buffer,2),
+% {Val band 2#0111111111111111, Remain2}
+% end;
+decode_length(Buffer,SingleValue) when integer(SingleValue) ->
+ {SingleValue,Buffer}.
+
+
+ % X.691:11
+encode_boolean(true) ->
+ {bits,1,1};
+encode_boolean(false) ->
+ {bits,1,0};
+encode_boolean({Name,Val}) when atom(Name) ->
+ encode_boolean(Val);
+encode_boolean(Val) ->
+ exit({error,{asn1,{encode_boolean,Val}}}).
+
+decode_boolean(Buffer) -> %when record(Buffer,buffer)
+ case getbit(Buffer) of
+ {1,Remain} -> {true,Remain};
+ {0,Remain} -> {false,Remain}
+ end.
+
+
+%% ENUMERATED with extension marker
+decode_enumerated(Buffer,C,{Ntup1,Ntup2}) when tuple(Ntup1), tuple(Ntup2) ->
+ {Ext,Buffer2} = getext(Buffer),
+ case Ext of
+ 0 -> % not an extension value
+ {Val,Buffer3} = decode_integer(Buffer2,C),
+ case catch (element(Val+1,Ntup1)) of
+ NewVal when atom(NewVal) -> {NewVal,Buffer3};
+ _Error -> exit({error,{asn1,{decode_enumerated,{Val,[Ntup1,Ntup2]}}}})
+ end;
+ 1 -> % this an extension value
+ {Val,Buffer3} = decode_small_number(Buffer2),
+ case catch (element(Val+1,Ntup2)) of
+ NewVal when atom(NewVal) -> {NewVal,Buffer3};
+ _ -> {{asn1_enum,Val},Buffer3}
+ end
+ end;
+
+decode_enumerated(Buffer,C,NamedNumberTup) when tuple(NamedNumberTup) ->
+ {Val,Buffer2} = decode_integer(Buffer,C),
+ case catch (element(Val+1,NamedNumberTup)) of
+ NewVal when atom(NewVal) -> {NewVal,Buffer2};
+ _Error -> exit({error,{asn1,{decode_enumerated,{Val,NamedNumberTup}}}})
+ end.
+
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+%% Bitstring value, ITU_T X.690 Chapter 8.5
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+
+%%===============================================================================
+%% encode bitstring value
+%%===============================================================================
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% bitstring NamedBitList
+%% Val can be of:
+%% - [identifiers] where only named identifers are set to one,
+%% the Constraint must then have some information of the
+%% bitlength.
+%% - [list of ones and zeroes] all bits
+%% - integer value representing the bitlist
+%% C is constraint Len, only valid when identifiers
+
+
+%% when the value is a list of {Unused,BinBits}, where
+%% Unused = integer(),
+%% BinBits = binary().
+
+encode_bit_string(C,Bin={Unused,BinBits},NamedBitList) when integer(Unused),
+ binary(BinBits) ->
+ encode_bin_bit_string(C,Bin,NamedBitList);
+
+%% when the value is a list of named bits
+encode_bit_string(C, LoNB=[FirstVal | _RestVal], NamedBitList) when atom(FirstVal) ->
+ ToSetPos = get_all_bitposes(LoNB, NamedBitList, []),
+ BitList = make_and_set_list(ToSetPos,0),
+ encode_bit_string(C,BitList,NamedBitList);
+
+encode_bit_string(C, BL=[{bit,_No} | _RestVal], NamedBitList) ->
+ ToSetPos = get_all_bitposes(BL, NamedBitList, []),
+ BitList = make_and_set_list(ToSetPos,0),
+ encode_bit_string(C,BitList,NamedBitList);
+
+%% when the value is a list of ones and zeroes
+
+% encode_bit_string(C, BitListValue, NamedBitList) when list(BitListValue) ->
+% Bl1 =
+% case NamedBitList of
+% [] -> % dont remove trailing zeroes
+% BitListValue;
+% _ -> % first remove any trailing zeroes
+% lists:reverse(lists:dropwhile(fun(0)->true;(1)->false end,
+% lists:reverse(BitListValue)))
+% end,
+% BitList = [{bit,X} || X <- Bl1],
+% %% BListLen = length(BitList),
+% case get_constraint(C,'SizeConstraint') of
+% 0 -> % fixed length
+% []; % nothing to encode
+% V when integer(V),V=<16 -> % fixed length 16 bits or less
+% pad_list(V,BitList);
+% V when integer(V) -> % fixed length 16 bits or more
+% [align,pad_list(V,BitList)]; % should be another case for V >= 65537
+% {Lb,Ub} when integer(Lb),integer(Ub) ->
+% [encode_length({Lb,Ub},length(BitList)),align,BitList];
+% no ->
+% [encode_length(undefined,length(BitList)),align,BitList];
+% Sc -> % extension marker
+% [encode_length(Sc,length(BitList)),align,BitList]
+% end;
+encode_bit_string(C, BitListValue, NamedBitList) when list(BitListValue) ->
+ BitListToBinary =
+ %% fun that transforms a list of 1 and 0 to a tuple:
+ %% {UnusedBitsInLastByte, Binary}
+ fun([H|T],Acc,N,Fun) ->
+ Fun(T,(Acc bsl 1)+H,N+1,Fun);
+ ([],Acc,N,_) ->
+ Unused = (8 - (N rem 8)) rem 8,
+ {Unused,<<Acc:N,0:Unused>>}
+ end,
+ UnusedAndBin =
+ case NamedBitList of
+ [] -> % dont remove trailing zeroes
+ BitListToBinary(BitListValue,0,0,BitListToBinary);
+ _ ->
+ BitListToBinary(lists:reverse(
+ lists:dropwhile(fun(0)->true;(1)->false end,
+ lists:reverse(BitListValue))),
+ 0,0,BitListToBinary)
+ end,
+ encode_bin_bit_string(C,UnusedAndBin,NamedBitList);
+
+%% when the value is an integer
+encode_bit_string(C, IntegerVal, NamedBitList) when integer(IntegerVal)->
+ BitList = int_to_bitlist(IntegerVal),
+ encode_bit_string(C,BitList,NamedBitList);
+
+%% when the value is a tuple
+encode_bit_string(C,{Name,Val}, NamedBitList) when atom(Name) ->
+ encode_bit_string(C,Val,NamedBitList).
+
+
+%% encode_bin_bit_string/3, when value is a tuple of Unused and BinBits.
+%% Unused = integer(),i.e. number unused bits in least sign. byte of
+%% BinBits = binary().
+
+
+encode_bin_bit_string(C,UnusedAndBin={_Unused,_BinBits},NamedBitList) ->
+ Constr = get_constraint(C,'SizeConstraint'),
+ UnusedAndBin1 = {Unused1,Bin1} =
+ remove_trailing_bin(NamedBitList,UnusedAndBin,lower_bound(Constr)),
+ case Constr of
+ 0 ->
+ [];
+ V when integer(V),V=<16 ->
+ {Unused2,Bin2} = pad_list(V,UnusedAndBin1),
+ <<BitVal:V,_:Unused2>> = Bin2,
+ {bits,V,BitVal};
+ V when integer(V) ->
+ [align, pad_list(V, UnusedAndBin1)];
+ {Lb,Ub} when integer(Lb),integer(Ub) ->
+ [encode_length({Lb,Ub},size(Bin1)*8 - Unused1),
+ align,UnusedAndBin1];
+ no ->
+ [encode_length(undefined,size(Bin1)*8 - Unused1),
+ align,UnusedAndBin1];
+ Sc ->
+ [encode_length(Sc,size(Bin1)*8 - Unused1),
+ align,UnusedAndBin1]
+ end.
+
+remove_trailing_bin([], {Unused,Bin},_) ->
+ {Unused,Bin};
+remove_trailing_bin(NamedNumberList, {_Unused,Bin},C) ->
+ Size = size(Bin)-1,
+ <<Bfront:Size/binary, LastByte:8>> = Bin,
+ %% clear the Unused bits to be sure
+% LastByte1 = LastByte band (((1 bsl Unused) -1) bxor 255),
+ Unused1 = trailingZeroesInNibble(LastByte band 15),
+ Unused2 =
+ case Unused1 of
+ 4 ->
+ 4 + trailingZeroesInNibble(LastByte bsr 4);
+ _ -> Unused1
+ end,
+ case Unused2 of
+ 8 ->
+ remove_trailing_bin(NamedNumberList,{0,Bfront},C);
+ _ ->
+ case C of
+ Int when integer(Int),Int > ((size(Bin)*8)-Unused2) ->
+ %% this padding see OTP-4353
+ pad_list(Int,{Unused2,Bin});
+ _ -> {Unused2,Bin}
+ end
+ end.
+
+
+trailingZeroesInNibble(0) ->
+ 4;
+trailingZeroesInNibble(1) ->
+ 0;
+trailingZeroesInNibble(2) ->
+ 1;
+trailingZeroesInNibble(3) ->
+ 0;
+trailingZeroesInNibble(4) ->
+ 2;
+trailingZeroesInNibble(5) ->
+ 0;
+trailingZeroesInNibble(6) ->
+ 1;
+trailingZeroesInNibble(7) ->
+ 0;
+trailingZeroesInNibble(8) ->
+ 3;
+trailingZeroesInNibble(9) ->
+ 0;
+trailingZeroesInNibble(10) ->
+ 1;
+trailingZeroesInNibble(11) ->
+ 0;
+trailingZeroesInNibble(12) -> %#1100
+ 2;
+trailingZeroesInNibble(13) ->
+ 0;
+trailingZeroesInNibble(14) ->
+ 1;
+trailingZeroesInNibble(15) ->
+ 0.
+
+lower_bound({{Lb,_},_}) when integer(Lb) ->
+ Lb;
+lower_bound({Lb,_}) when integer(Lb) ->
+ Lb;
+lower_bound(C) ->
+ C.
+
+%%%%%%%%%%%%%%%
+%% The result is presented as a list of named bits (if possible)
+%% else as a tuple {Unused,Bits}. Unused is the number of unused
+%% bits, least significant bits in the last byte of Bits. Bits is
+%% the BIT STRING represented as a binary.
+%%
+decode_compact_bit_string(Buffer, C, NamedNumberList) ->
+ case get_constraint(C,'SizeConstraint') of
+ 0 -> % fixed length
+ {{8,0},Buffer};
+ V when integer(V),V=<16 -> %fixed length 16 bits or less
+ compact_bit_string(Buffer,V,NamedNumberList);
+ V when integer(V),V=<65536 -> %fixed length > 16 bits
+ Bytes2 = align(Buffer),
+ compact_bit_string(Bytes2,V,NamedNumberList);
+ V when integer(V) -> % V > 65536 => fragmented value
+ {Bin,Buffer2} = decode_fragmented_bits(Buffer,V),
+ case Buffer2 of
+ {0,_} -> {{0,Bin},Buffer2};
+ {U,_} -> {{8-U,Bin},Buffer2}
+ end;
+ {Lb,Ub} when integer(Lb),integer(Ub) ->
+ %% This case may demand decoding of fragmented length/value
+ {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
+ Bytes3 = align(Bytes2),
+ compact_bit_string(Bytes3,Len,NamedNumberList);
+ no ->
+ %% This case may demand decoding of fragmented length/value
+ {Len,Bytes2} = decode_length(Buffer,undefined),
+ Bytes3 = align(Bytes2),
+ compact_bit_string(Bytes3,Len,NamedNumberList);
+ Sc ->
+ {Len,Bytes2} = decode_length(Buffer,Sc),
+ Bytes3 = align(Bytes2),
+ compact_bit_string(Bytes3,Len,NamedNumberList)
+ end.
+
+
+%%%%%%%%%%%%%%%
+%% The result is presented as a list of named bits (if possible)
+%% else as a list of 0 and 1.
+%%
+decode_bit_string(Buffer, C, NamedNumberList) ->
+ case get_constraint(C,'SizeConstraint') of
+ {Lb,Ub} when integer(Lb),integer(Ub) ->
+ {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
+ Bytes3 = align(Bytes2),
+ bit_list_or_named(Bytes3,Len,NamedNumberList);
+ no ->
+ {Len,Bytes2} = decode_length(Buffer,undefined),
+ Bytes3 = align(Bytes2),
+ bit_list_or_named(Bytes3,Len,NamedNumberList);
+ 0 -> % fixed length
+ {[],Buffer}; % nothing to encode
+ V when integer(V),V=<16 -> % fixed length 16 bits or less
+ bit_list_or_named(Buffer,V,NamedNumberList);
+ V when integer(V),V=<65536 ->
+ Bytes2 = align(Buffer),
+ bit_list_or_named(Bytes2,V,NamedNumberList);
+ V when integer(V) ->
+ Bytes2 = align(Buffer),
+ {BinBits,_} = decode_fragmented_bits(Bytes2,V),
+ bit_list_or_named(BinBits,V,NamedNumberList);
+ Sc -> % extension marker
+ {Len,Bytes2} = decode_length(Buffer,Sc),
+ Bytes3 = align(Bytes2),
+ bit_list_or_named(Bytes3,Len,NamedNumberList)
+ end.
+
+
+%% if no named bits are declared we will return a
+%% {Unused,Bits}. Unused = integer(),
+%% Bits = binary().
+compact_bit_string(Buffer,Len,[]) ->
+ getbits_as_binary(Len,Buffer); % {{Unused,BinBits},NewBuffer}
+compact_bit_string(Buffer,Len,NamedNumberList) ->
+ bit_list_or_named(Buffer,Len,NamedNumberList).
+
+
+%% if no named bits are declared we will return a
+%% BitList = [0 | 1]
+
+bit_list_or_named(Buffer,Len,[]) ->
+ getbits_as_list(Len,Buffer);
+
+%% if there are named bits declared we will return a named
+%% BitList where the names are atoms and unnamed bits represented
+%% as {bit,Pos}
+%% BitList = [atom() | {bit,Pos}]
+%% Pos = integer()
+
+bit_list_or_named(Buffer,Len,NamedNumberList) ->
+ {BitList,Rest} = getbits_as_list(Len,Buffer),
+ {bit_list_or_named1(0,BitList,NamedNumberList,[]), Rest}.
+
+bit_list_or_named1(Pos,[0|Bt],Names,Acc) ->
+ bit_list_or_named1(Pos+1,Bt,Names,Acc);
+bit_list_or_named1(Pos,[1|Bt],Names,Acc) ->
+ case lists:keysearch(Pos,2,Names) of
+ {value,{Name,_}} ->
+ bit_list_or_named1(Pos+1,Bt,Names,[Name|Acc]);
+ _ ->
+ bit_list_or_named1(Pos+1,Bt,Names,[{bit,Pos}|Acc])
+ end;
+bit_list_or_named1(_,[],_,Acc) ->
+ lists:reverse(Acc).
+
+
+
+%%%%%%%%%%%%%%%
+%%
+
+int_to_bitlist(Int) when integer(Int), Int > 0 ->
+ [Int band 1 | int_to_bitlist(Int bsr 1)];
+int_to_bitlist(0) ->
+ [].
+
+
+%%%%%%%%%%%%%%%%%%
+%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
+%% [sorted_list_of_bitpositions_to_set]
+
+get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
+ get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
+
+get_all_bitposes([Val | Rest], NamedBitList, Ack) ->
+ case lists:keysearch(Val, 1, NamedBitList) of
+ {value, {_ValName, ValPos}} ->
+ get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
+ _ ->
+ exit({error,{asn1, {bitstring_namedbit, Val}}})
+ end;
+get_all_bitposes([], _NamedBitList, Ack) ->
+ lists:sort(Ack).
+
+%%%%%%%%%%%%%%%%%%
+%% make_and_set_list([list of positions to set to 1])->
+%% returns list with all in SetPos set.
+%% in positioning in list the first element is 0, the second 1 etc.., but
+%%
+
+make_and_set_list([XPos|SetPos], XPos) ->
+ [1 | make_and_set_list(SetPos, XPos + 1)];
+make_and_set_list([Pos|SetPos], XPos) ->
+ [0 | make_and_set_list([Pos | SetPos], XPos + 1)];
+make_and_set_list([], _) ->
+ [].
+
+%%%%%%%%%%%%%%%%%
+%% pad_list(N,BitList) -> PaddedList
+%% returns a padded (with trailing {bit,0} elements) list of length N
+%% if Bitlist contains more than N significant bits set an exit asn1_error
+%% is generated
+
+pad_list(N,In={Unused,Bin}) ->
+ pad_list(N, size(Bin)*8 - Unused, In).
+
+pad_list(N,Size,In={_,_}) when N < Size ->
+ exit({error,{asn1,{range_error,{bit_string,In}}}});
+pad_list(N,Size,{Unused,Bin}) when N > Size, Unused > 0 ->
+ pad_list(N,Size+1,{Unused-1,Bin});
+pad_list(N,Size,{_Unused,Bin}) when N > Size ->
+ pad_list(N,Size+1,{7,<<Bin/binary,0>>});
+pad_list(N,N,In={_,_}) ->
+ In.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% X.691:16
+%% encode_octet_string(Constraint,ExtensionMarker,Val)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+encode_octet_string(C,Val) ->
+ encode_octet_string(C,false,Val).
+
+encode_octet_string(C,Bool,{_Name,Val}) ->
+ encode_octet_string(C,Bool,Val);
+encode_octet_string(_,true,_) ->
+ exit({error,{asn1,{'not_supported',extensionmarker}}});
+encode_octet_string(C,false,Val) ->
+ case get_constraint(C,'SizeConstraint') of
+ 0 ->
+ [];
+ 1 ->
+ [V] = Val,
+ {bits,8,V};
+ 2 ->
+ [V1,V2] = Val,
+ [{bits,8,V1},{bits,8,V2}];
+ Sv when Sv =<65535, Sv == length(Val) -> % fixed length
+ {octets,Val};
+ {Lb,Ub} ->
+ [encode_length({Lb,Ub},length(Val)),{octets,Val}];
+ Sv when list(Sv) ->
+ [encode_length({hd(Sv),lists:max(Sv)},length(Val)),{octets,Val}];
+ no ->
+ [encode_length(undefined,length(Val)),{octets,Val}]
+ end.
+
+decode_octet_string(Bytes,Range) ->
+ decode_octet_string(Bytes,Range,false).
+
+decode_octet_string(Bytes,C,false) ->
+ case get_constraint(C,'SizeConstraint') of
+ 0 ->
+ {[],Bytes};
+ 1 ->
+ {B1,Bytes2} = getbits(Bytes,8),
+ {[B1],Bytes2};
+ 2 ->
+ {Bs,Bytes2}= getbits(Bytes,16),
+ {binary_to_list(<<Bs:16>>),Bytes2};
+ {_,0} ->
+ {[],Bytes};
+ Sv when integer(Sv), Sv =<65535 -> % fixed length
+ getoctets_as_list(Bytes,Sv);
+ Sv when integer(Sv) -> % fragmented encoding
+ Bytes2 = align(Bytes),
+ decode_fragmented_octets(Bytes2,Sv);
+ {Lb,Ub} ->
+ {Len,Bytes2} = decode_length(Bytes,{Lb,Ub}),
+ getoctets_as_list(Bytes2,Len);
+ Sv when list(Sv) ->
+ {Len,Bytes2} = decode_length(Bytes,{hd(Sv),lists:max(Sv)}),
+ getoctets_as_list(Bytes2,Len);
+ no ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ getoctets_as_list(Bytes2,Len)
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Restricted char string types
+%% (NumericString, PrintableString,VisibleString,IA5String,BMPString,UniversalString)
+%% X.691:26 and X.680:34-36
+%%encode_restricted_string(aligned,'BMPString',Constraints,Extension,Val)
+
+
+encode_restricted_string(aligned,{Name,Val}) when atom(Name) ->
+ encode_restricted_string(aligned,Val);
+
+encode_restricted_string(aligned,Val) when list(Val)->
+ [encode_length(undefined,length(Val)),{octets,Val}].
+
+encode_known_multiplier_string(aligned,StringType,C,_Ext,{Name,Val}) when atom(Name) ->
+ encode_known_multiplier_string(aligned,StringType,C,false,Val);
+
+encode_known_multiplier_string(aligned,StringType,C,_Ext,Val) ->
+ Result = chars_encode(C,StringType,Val),
+ NumBits = get_NumBits(C,StringType),
+ case get_constraint(C,'SizeConstraint') of
+ Ub when integer(Ub), Ub*NumBits =< 16 ->
+ case {StringType,Result} of
+ {'BMPString',{octets,Ol}} ->
+ [{bits,8,Oct}||Oct <- Ol];
+ _ ->
+ Result
+ end;
+ 0 ->
+ [];
+ Ub when integer(Ub),Ub =<65535 -> % fixed length
+ [align,Result];
+ {Ub,Lb} ->
+ [encode_length({Ub,Lb},length(Val)),align,Result];
+ Vl when list(Vl) ->
+ [encode_length({lists:min(Vl),lists:max(Vl)},length(Val)),align,Result];
+ no ->
+ [encode_length(undefined,length(Val)),align,Result]
+ end.
+
+decode_restricted_string(Bytes,aligned) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ getoctets_as_list(Bytes2,Len).
+
+decode_known_multiplier_string(Bytes,aligned,StringType,C,_Ext) ->
+ NumBits = get_NumBits(C,StringType),
+ case get_constraint(C,'SizeConstraint') of
+ Ub when integer(Ub), Ub*NumBits =< 16 ->
+ chars_decode(Bytes,NumBits,StringType,C,Ub);
+ Ub when integer(Ub),Ub =<65535 -> % fixed length
+ Bytes1 = align(Bytes),
+ chars_decode(Bytes1,NumBits,StringType,C,Ub);
+ 0 ->
+ {[],Bytes};
+ Vl when list(Vl) ->
+ {Len,Bytes1} = decode_length(Bytes,{hd(Vl),lists:max(Vl)}),
+ Bytes2 = align(Bytes1),
+ chars_decode(Bytes2,NumBits,StringType,C,Len);
+ no ->
+ {Len,Bytes1} = decode_length(Bytes,undefined),
+ Bytes2 = align(Bytes1),
+ chars_decode(Bytes2,NumBits,StringType,C,Len);
+ {Lb,Ub}->
+ {Len,Bytes1} = decode_length(Bytes,{Lb,Ub}),
+ Bytes2 = align(Bytes1),
+ chars_decode(Bytes2,NumBits,StringType,C,Len)
+ end.
+
+
+encode_NumericString(C,Val) ->
+ encode_known_multiplier_string(aligned,'NumericString',C,false,Val).
+decode_NumericString(Bytes,C) ->
+ decode_known_multiplier_string(Bytes,aligned,'NumericString',C,false).
+
+encode_PrintableString(C,Val) ->
+ encode_known_multiplier_string(aligned,'PrintableString',C,false,Val).
+decode_PrintableString(Bytes,C) ->
+ decode_known_multiplier_string(Bytes,aligned,'PrintableString',C,false).
+
+encode_VisibleString(C,Val) -> % equivalent with ISO646String
+ encode_known_multiplier_string(aligned,'VisibleString',C,false,Val).
+decode_VisibleString(Bytes,C) ->
+ decode_known_multiplier_string(Bytes,aligned,'VisibleString',C,false).
+
+encode_IA5String(C,Val) ->
+ encode_known_multiplier_string(aligned,'IA5String',C,false,Val).
+decode_IA5String(Bytes,C) ->
+ decode_known_multiplier_string(Bytes,aligned,'IA5String',C,false).
+
+encode_BMPString(C,Val) ->
+ encode_known_multiplier_string(aligned,'BMPString',C,false,Val).
+decode_BMPString(Bytes,C) ->
+ decode_known_multiplier_string(Bytes,aligned,'BMPString',C,false).
+
+encode_UniversalString(C,Val) ->
+ encode_known_multiplier_string(aligned,'UniversalString',C,false,Val).
+decode_UniversalString(Bytes,C) ->
+ decode_known_multiplier_string(Bytes,aligned,'UniversalString',C,false).
+
+%% end of known-multiplier strings for which PER visible constraints are
+%% applied
+
+encode_GeneralString(_C,Val) ->
+ encode_restricted_string(aligned,Val).
+decode_GeneralString(Bytes,_C) ->
+ decode_restricted_string(Bytes,aligned).
+
+encode_GraphicString(_C,Val) ->
+ encode_restricted_string(aligned,Val).
+decode_GraphicString(Bytes,_C) ->
+ decode_restricted_string(Bytes,aligned).
+
+encode_ObjectDescriptor(_C,Val) ->
+ encode_restricted_string(aligned,Val).
+decode_ObjectDescriptor(Bytes) ->
+ decode_restricted_string(Bytes,aligned).
+
+encode_TeletexString(_C,Val) -> % equivalent with T61String
+ encode_restricted_string(aligned,Val).
+decode_TeletexString(Bytes,_C) ->
+ decode_restricted_string(Bytes,aligned).
+
+encode_VideotexString(_C,Val) ->
+ encode_restricted_string(aligned,Val).
+decode_VideotexString(Bytes,_C) ->
+ decode_restricted_string(Bytes,aligned).
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% getBMPChars(Bytes,Len) ->{BMPcharList,RemainingBytes}
+%%
+getBMPChars(Bytes,1) ->
+ {O1,Bytes2} = getbits(Bytes,8),
+ {O2,Bytes3} = getbits(Bytes2,8),
+ if
+ O1 == 0 ->
+ {[O2],Bytes3};
+ true ->
+ {[{0,0,O1,O2}],Bytes3}
+ end;
+getBMPChars(Bytes,Len) ->
+ getBMPChars(Bytes,Len,[]).
+
+getBMPChars(Bytes,0,Acc) ->
+ {lists:reverse(Acc),Bytes};
+getBMPChars(Bytes,Len,Acc) ->
+ {Octs,Bytes1} = getoctets_as_list(Bytes,2),
+ case Octs of
+ [0,O2] ->
+ getBMPChars(Bytes1,Len-1,[O2|Acc]);
+ [O1,O2]->
+ getBMPChars(Bytes1,Len-1,[{0,0,O1,O2}|Acc])
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% chars_encode(C,StringType,Value) -> ValueList
+%%
+%% encodes chars according to the per rules taking the constraint PermittedAlphabet
+%% into account.
+%% This function does only encode the value part and NOT the length
+
+chars_encode(C,StringType,Value) ->
+ case {StringType,get_constraint(C,'PermittedAlphabet')} of
+ {'UniversalString',{_,_Sv}} ->
+ exit({error,{asn1,{'not implemented',"UniversalString with PermittedAlphabet constraint"}}});
+ {'BMPString',{_,_Sv}} ->
+ exit({error,{asn1,{'not implemented',"BMPString with PermittedAlphabet constraint"}}});
+ _ ->
+ {NumBits,CharOutTab} = {get_NumBits(C,StringType),get_CharOutTab(C,StringType)},
+ chars_encode2(Value,NumBits,CharOutTab)
+ end.
+
+chars_encode2([H|T],NumBits,{Min,Max,notab}) when H =< Max, H >= Min ->
+ [{bits,NumBits,H-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
+chars_encode2([H|T],NumBits,{Min,Max,Tab}) when H =< Max, H >= Min ->
+ [{bits,NumBits,exit_if_false(H,element(H-Min+1,Tab))}|chars_encode2(T,NumBits,{Min,Max,Tab})];
+chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,notab}) ->
+ %% no value range check here (ought to be, but very expensive)
+% [{bits,NumBits,(A*B*C*D)-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
+ [{bits,NumBits,((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
+chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,Tab}) ->
+ %% no value range check here (ought to be, but very expensive)
+% [{bits,NumBits,element((A*B*C*D)-Min,Tab)}|chars_encode2(T,NumBits,{Min,Max,notab})];
+ [{bits,NumBits,exit_if_false({A,B,C,D},element(((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min,Tab))}|chars_encode2(T,NumBits,{Min,Max,notab})];
+chars_encode2([H|_T],_,{_,_,_}) ->
+ exit({error,{asn1,{illegal_char_value,H}}});
+chars_encode2([],_,_) ->
+ [].
+
+exit_if_false(V,false)->
+ exit({error,{asn1,{"illegal value according to Permitted alphabet constraint",V}}});
+exit_if_false(_,V) ->V.
+
+
+get_NumBits(C,StringType) ->
+ case get_constraint(C,'PermittedAlphabet') of
+ {'SingleValue',Sv} ->
+ charbits(length(Sv),aligned);
+ no ->
+ case StringType of
+ 'IA5String' ->
+ charbits(128,aligned); % 16#00..16#7F
+ 'VisibleString' ->
+ charbits(95,aligned); % 16#20..16#7E
+ 'PrintableString' ->
+ charbits(74,aligned); % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
+ 'NumericString' ->
+ charbits(11,aligned); % $ ,"0123456789"
+ 'UniversalString' ->
+ 32;
+ 'BMPString' ->
+ 16
+ end
+ end.
+
+%%Maybe used later
+%%get_MaxChar(C,StringType) ->
+%% case get_constraint(C,'PermittedAlphabet') of
+%% {'SingleValue',Sv} ->
+%% lists:nth(length(Sv),Sv);
+%% no ->
+%% case StringType of
+%% 'IA5String' ->
+%% 16#7F; % 16#00..16#7F
+%% 'VisibleString' ->
+%% 16#7E; % 16#20..16#7E
+%% 'PrintableString' ->
+%% $z; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
+%% 'NumericString' ->
+%% $9; % $ ,"0123456789"
+%% 'UniversalString' ->
+%% 16#ffffffff;
+%% 'BMPString' ->
+%% 16#ffff
+%% end
+%% end.
+
+%%Maybe used later
+%%get_MinChar(C,StringType) ->
+%% case get_constraint(C,'PermittedAlphabet') of
+%% {'SingleValue',Sv} ->
+%% hd(Sv);
+%% no ->
+%% case StringType of
+%% 'IA5String' ->
+%% 16#00; % 16#00..16#7F
+%% 'VisibleString' ->
+%% 16#20; % 16#20..16#7E
+%% 'PrintableString' ->
+%% $\s; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
+%% 'NumericString' ->
+%% $\s; % $ ,"0123456789"
+%% 'UniversalString' ->
+%% 16#00;
+%% 'BMPString' ->
+%% 16#00
+%% end
+%% end.
+
+get_CharOutTab(C,StringType) ->
+ get_CharTab(C,StringType,out).
+
+get_CharInTab(C,StringType) ->
+ get_CharTab(C,StringType,in).
+
+get_CharTab(C,StringType,InOut) ->
+ case get_constraint(C,'PermittedAlphabet') of
+ {'SingleValue',Sv} ->
+ get_CharTab2(C,StringType,hd(Sv),lists:max(Sv),Sv,InOut);
+ no ->
+ case StringType of
+ 'IA5String' ->
+ {0,16#7F,notab};
+ 'VisibleString' ->
+ get_CharTab2(C,StringType,16#20,16#7F,notab,InOut);
+ 'PrintableString' ->
+ Chars = lists:sort(
+ " '()+,-./0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
+ get_CharTab2(C,StringType,hd(Chars),lists:max(Chars),Chars,InOut);
+ 'NumericString' ->
+ get_CharTab2(C,StringType,16#20,$9," 0123456789",InOut);
+ 'UniversalString' ->
+ {0,16#FFFFFFFF,notab};
+ 'BMPString' ->
+ {0,16#FFFF,notab}
+ end
+ end.
+
+get_CharTab2(C,StringType,Min,Max,Chars,InOut) ->
+ BitValMax = (1 bsl get_NumBits(C,StringType))-1,
+ if
+ Max =< BitValMax ->
+ {0,Max,notab};
+ true ->
+ case InOut of
+ out ->
+ {Min,Max,create_char_tab(Min,Chars)};
+ in ->
+ {Min,Max,list_to_tuple(Chars)}
+ end
+ end.
+
+create_char_tab(Min,L) ->
+ list_to_tuple(create_char_tab(Min,L,0)).
+create_char_tab(Min,[Min|T],V) ->
+ [V|create_char_tab(Min+1,T,V+1)];
+create_char_tab(_Min,[],_V) ->
+ [];
+create_char_tab(Min,L,V) ->
+ [false|create_char_tab(Min+1,L,V)].
+
+%% This very inefficient and should be moved to compiletime
+charbits(NumOfChars,aligned) ->
+ case charbits(NumOfChars) of
+ 1 -> 1;
+ 2 -> 2;
+ B when B =< 4 -> 4;
+ B when B =< 8 -> 8;
+ B when B =< 16 -> 16;
+ B when B =< 32 -> 32
+ end.
+
+charbits(NumOfChars) when NumOfChars =< 2 -> 1;
+charbits(NumOfChars) when NumOfChars =< 4 -> 2;
+charbits(NumOfChars) when NumOfChars =< 8 -> 3;
+charbits(NumOfChars) when NumOfChars =< 16 -> 4;
+charbits(NumOfChars) when NumOfChars =< 32 -> 5;
+charbits(NumOfChars) when NumOfChars =< 64 -> 6;
+charbits(NumOfChars) when NumOfChars =< 128 -> 7;
+charbits(NumOfChars) when NumOfChars =< 256 -> 8;
+charbits(NumOfChars) when NumOfChars =< 512 -> 9;
+charbits(NumOfChars) when NumOfChars =< 1024 -> 10;
+charbits(NumOfChars) when NumOfChars =< 2048 -> 11;
+charbits(NumOfChars) when NumOfChars =< 4096 -> 12;
+charbits(NumOfChars) when NumOfChars =< 8192 -> 13;
+charbits(NumOfChars) when NumOfChars =< 16384 -> 14;
+charbits(NumOfChars) when NumOfChars =< 32768 -> 15;
+charbits(NumOfChars) when NumOfChars =< 65536 -> 16;
+charbits(NumOfChars) when integer(NumOfChars) ->
+ 16 + charbits1(NumOfChars bsr 16).
+
+charbits1(0) ->
+ 0;
+charbits1(NumOfChars) ->
+ 1 + charbits1(NumOfChars bsr 1).
+
+
+chars_decode(Bytes,_,'BMPString',C,Len) ->
+ case get_constraint(C,'PermittedAlphabet') of
+ no ->
+ getBMPChars(Bytes,Len);
+ _ ->
+ exit({error,{asn1,
+ {'not implemented',
+ "BMPString with PermittedAlphabet constraint"}}})
+ end;
+chars_decode(Bytes,NumBits,StringType,C,Len) ->
+ CharInTab = get_CharInTab(C,StringType),
+ chars_decode2(Bytes,CharInTab,NumBits,Len).
+
+
+chars_decode2(Bytes,CharInTab,NumBits,Len) ->
+ chars_decode2(Bytes,CharInTab,NumBits,Len,[]).
+
+chars_decode2(Bytes,_CharInTab,_NumBits,0,Acc) ->
+ {lists:reverse(Acc),Bytes};
+chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) when NumBits > 8 ->
+ {Char,Bytes2} = getbits(Bytes,NumBits),
+ Result =
+ if
+ Char < 256 -> Char;
+ true ->
+ list_to_tuple(binary_to_list(<<Char:32>>))
+ end,
+ chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Result|Acc]);
+% chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) when NumBits > 8 ->
+% {Char,Bytes2} = getbits(Bytes,NumBits),
+% Result = case minimum_octets(Char+Min) of
+% [NewChar] -> NewChar;
+% [C1,C2] -> {0,0,C1,C2};
+% [C1,C2,C3] -> {0,C1,C2,C3};
+% [C1,C2,C3,C4] -> {C1,C2,C3,C4}
+% end,
+% chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Result|Acc]);
+chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) ->
+ {Char,Bytes2} = getbits(Bytes,NumBits),
+ chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Char+Min|Acc]);
+
+%% BMPString and UniversalString with PermittedAlphabet is currently not supported
+chars_decode2(Bytes,{Min,Max,CharInTab},NumBits,Len,Acc) ->
+ {Char,Bytes2} = getbits(Bytes,NumBits),
+ chars_decode2(Bytes2,{Min,Max,CharInTab},NumBits,Len -1,[element(Char+1,CharInTab)|Acc]).
+
+
+ % X.691:17
+encode_null(_) -> []; % encodes to nothing
+encode_null({Name,Val}) when atom(Name) ->
+ encode_null(Val).
+
+decode_null(Bytes) ->
+ {'NULL',Bytes}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_object_identifier(Val) -> CompleteList
+%% encode_object_identifier({Name,Val}) -> CompleteList
+%% Val -> {Int1,Int2,...,IntN} % N >= 2
+%% Name -> atom()
+%% Int1 -> integer(0..2)
+%% Int2 -> integer(0..39) when Int1 (0..1) else integer()
+%% Int3-N -> integer()
+%% CompleteList -> [{bits,8,Val}|{octets,Ol}|align|...]
+%%
+encode_object_identifier({Name,Val}) when atom(Name) ->
+ encode_object_identifier(Val);
+encode_object_identifier(Val) ->
+ OctetList = e_object_identifier(Val),
+ Octets = list_to_binary(OctetList), % performs a flatten at the same time
+ [{debug,object_identifier},encode_length(undefined,size(Octets)),{octets,Octets}].
+
+%% This code is copied from asn1_encode.erl (BER) and corrected and modified
+
+e_object_identifier({'OBJECT IDENTIFIER',V}) ->
+ e_object_identifier(V);
+e_object_identifier({Cname,V}) when atom(Cname),tuple(V) ->
+ e_object_identifier(tuple_to_list(V));
+e_object_identifier({Cname,V}) when atom(Cname),list(V) ->
+ e_object_identifier(V);
+e_object_identifier(V) when tuple(V) ->
+ e_object_identifier(tuple_to_list(V));
+
+%% E1 = 0|1|2 and (E2 < 40 when E1 = 0|1)
+e_object_identifier([E1,E2|Tail]) when E1 >= 0, E1 < 2, E2 < 40 ; E1==2 ->
+ Head = 40*E1 + E2, % weird
+ e_object_elements([Head|Tail],[]);
+e_object_identifier(Oid=[_,_|_Tail]) ->
+ exit({error,{asn1,{'illegal_value',Oid}}}).
+
+e_object_elements([],Acc) ->
+ lists:reverse(Acc);
+e_object_elements([H|T],Acc) ->
+ e_object_elements(T,[e_object_element(H)|Acc]).
+
+e_object_element(Num) when Num < 128 ->
+ Num;
+%% must be changed to handle more than 2 octets
+e_object_element(Num) -> %% when Num < ???
+ Left = ((Num band 2#11111110000000) bsr 7) bor 2#10000000,
+ Right = Num band 2#1111111 ,
+ [Left,Right].
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% decode_object_identifier(Bytes) -> {ObjId,RemainingBytes}
+%% ObjId -> {integer(),integer(),...} % at least 2 integers
+%% RemainingBytes -> [integer()] when integer() (0..255)
+decode_object_identifier(Bytes) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
+ [First|Rest] = dec_subidentifiers(Octs,0,[]),
+ Idlist = if
+ First < 40 ->
+ [0,First|Rest];
+ First < 80 ->
+ [1,First - 40|Rest];
+ true ->
+ [2,First - 80|Rest]
+ end,
+ {list_to_tuple(Idlist),Bytes3}.
+
+dec_subidentifiers([H|T],Av,Al) when H >=16#80 ->
+ dec_subidentifiers(T,(Av bsl 7) + (H band 16#7F),Al);
+dec_subidentifiers([H|T],Av,Al) ->
+ dec_subidentifiers(T,0,[(Av bsl 7) + H |Al]);
+dec_subidentifiers([],_Av,Al) ->
+ lists:reverse(Al).
+
+get_constraint([{Key,V}],Key) ->
+ V;
+get_constraint([],_Key) ->
+ no;
+get_constraint(C,Key) ->
+ case lists:keysearch(Key,1,C) of
+ false ->
+ no;
+ {value,{_,V}} ->
+ V
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% complete(InList) -> ByteList
+%% Takes a coded list with bits and bytes and converts it to a list of bytes
+%% Should be applied as the last step at encode of a complete ASN.1 type
+%%
+
+% complete(L) ->
+% case complete1(L) of
+% {[],0} ->
+% <<0>>;
+% {Acc,0} ->
+% lists:reverse(Acc);
+% {[Hacc|Tacc],Acclen} -> % Acclen >0
+% Rest = 8 - Acclen,
+% NewHacc = Hacc bsl Rest,
+% lists:reverse([NewHacc|Tacc])
+% end.
+
+
+% complete1(InList) when list(InList) ->
+% complete1(InList,[]);
+% complete1(InList) ->
+% complete1([InList],[]).
+
+% complete1([{debug,_}|T], Acc) ->
+% complete1(T,Acc);
+% complete1([H|T],Acc) when list(H) ->
+% {NewH,NewAcclen} = complete1(H,Acc),
+% complete1(T,NewH,NewAcclen);
+
+% complete1([{0,Bin}|T],Acc,0) when binary(Bin) ->
+% complete1(T,[Bin|Acc],0);
+% complete1([{Unused,Bin}|T],Acc,0) when integer(Unused),binary(Bin) ->
+% Size = size(Bin)-1,
+% <<Bs:Size/binary,B>> = Bin,
+% complete1(T,[(B bsr Unused),Bs|Acc],8-Unused);
+% complete1([{Unused,Bin}|T],[Hacc|Tacc],Acclen) when integer(Unused),binary(Bin) ->
+% Rest = 8 - Acclen,
+% Used = 8 - Unused,
+% case size(Bin) of
+% 1 ->
+% if
+% Rest >= Used ->
+% <<B:Used,_:Unused>> = Bin,
+% complete1(T,[(Hacc bsl Used) + B|Tacc],
+% (Acclen+Used) rem 8);
+% true ->
+% LeftOver = 8 - Rest - Unused,
+% <<Val2:Rest,Val1:LeftOver,_:Unused>> = Bin,
+% complete1(T,[Val1,(Hacc bsl Rest) + Val2|Tacc],
+% (Acclen+Used) rem 8)
+% end;
+% N ->
+% if
+% Rest == Used ->
+% N1 = N - 1,
+% <<B:Rest,Bs:N1/binary,_:Unused>> = Bin,
+% complete1(T,[Bs,(Hacc bsl Rest) + B|Tacc],0);
+% Rest > Used ->
+% N1 = N - 2,
+% N2 = (8 - Rest) + Used,
+% <<B1:Rest,Bytes:N1/binary,B2:N2,_:Unused>> = Bin,
+% complete1(T,[B2,Bytes,(Hacc bsl Rest) + B1|Tacc],
+% (Acclen + Used) rem 8);
+% true -> % Rest < Used
+% N1 = N - 1,
+% N2 = Used - Rest,
+% <<B1:Rest,Bytes:N1/binary,B2:N2,_:Unused>> = Bin,
+% complete1(T,[B2,Bytes,(Hacc bsl Rest) + B1|Tacc],
+% (Acclen + Used) rem 8)
+% end
+% end;
+
+% %complete1([{octets,N,Val}|T],Acc,Acclen) when N =< 4 ,integer(Val) ->
+% % complete1([{octets,<<Val:N/unit:8>>}|T],Acc,Acclen);
+% complete1([{octets,N,Val}|T],Acc,Acclen) when N =< 4 ,integer(Val) ->
+% Newval = case N of
+% 1 ->
+% Val4 = Val band 16#FF,
+% [Val4];
+% 2 ->
+% Val3 = (Val bsr 8) band 16#FF,
+% Val4 = Val band 16#FF,
+% [Val3,Val4];
+% 3 ->
+% Val2 = (Val bsr 16) band 16#FF,
+% Val3 = (Val bsr 8) band 16#FF,
+% Val4 = Val band 16#FF,
+% [Val2,Val3,Val4];
+% 4 ->
+% Val1 = (Val bsr 24) band 16#FF,
+% Val2 = (Val bsr 16) band 16#FF,
+% Val3 = (Val bsr 8) band 16#FF,
+% Val4 = Val band 16#FF,
+% [Val1,Val2,Val3,Val4]
+% end,
+% complete1([{octets,Newval}|T],Acc,Acclen);
+
+% complete1([{octets,Bin}|T],Acc,Acclen) when binary(Bin) ->
+% Rest = 8 - Acclen,
+% if
+% Rest == 8 ->
+% complete1(T,[Bin|Acc],0);
+% true ->
+% [Hacc|Tacc]=Acc,
+% complete1(T,[Bin, Hacc bsl Rest|Tacc],0)
+% end;
+
+% complete1([{octets,Oct}|T],Acc,Acclen) when list(Oct) ->
+% Rest = 8 - Acclen,
+% if
+% Rest == 8 ->
+% complete1(T,[list_to_binary(Oct)|Acc],0);
+% true ->
+% [Hacc|Tacc]=Acc,
+% complete1(T,[list_to_binary(Oct), Hacc bsl Rest|Tacc],0)
+% end;
+
+% complete1([{bit,Val}|T], Acc, Acclen) ->
+% complete1([{bits,1,Val}|T],Acc,Acclen);
+% complete1([{octet,Val}|T], Acc, Acclen) ->
+% complete1([{octets,1,Val}|T],Acc,Acclen);
+
+% complete1([{bits,N,Val}|T], Acc, 0) when N =< 8 ->
+% complete1(T,[Val|Acc],N);
+% complete1([{bits,N,Val}|T], [Hacc|Tacc], Acclen) when N =< 8 ->
+% Rest = 8 - Acclen,
+% if
+% Rest >= N ->
+% complete1(T,[(Hacc bsl N) + Val|Tacc],(Acclen+N) rem 8);
+% true ->
+% Diff = N - Rest,
+% NewHacc = (Hacc bsl Rest) + (Val bsr Diff),
+% Mask = element(Diff,{1,3,7,15,31,63,127,255}),
+% complete1(T,[(Val band Mask),NewHacc|Tacc],(Acclen+N) rem 8)
+% end;
+% complete1([{bits,N,Val}|T], Acc, Acclen) -> % N > 8
+% complete1([{bits,N-8,Val bsr 8},{bits,8,Val band 255}|T],Acc,Acclen);
+
+% complete1([align|T],Acc,0) ->
+% complete1(T,Acc,0);
+% complete1([align|T],[Hacc|Tacc],Acclen) ->
+% Rest = 8 - Acclen,
+% complete1(T,[Hacc bsl Rest|Tacc],0);
+% complete1([{octets,N,Val}|T],Acc,Acclen) when list(Val) -> % no security check here
+% complete1([{octets,Val}|T],Acc,Acclen);
+
+% complete1([],Acc,Acclen) ->
+% {Acc,Acclen}.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% complete(InList) -> ByteList
+%% Takes a coded list with bits and bytes and converts it to a list of bytes
+%% Should be applied as the last step at encode of a complete ASN.1 type
+%%
+
+complete(L) ->
+ case complete1(L) of
+ {[],[]} ->
+ <<0>>;
+ {Acc,[]} ->
+ Acc;
+ {Acc,Bacc} ->
+ [Acc|complete_bytes(Bacc)]
+ end.
+
+%% this function builds the ugly form of lists [E1|E2] to avoid having to reverse it at the end.
+%% this is done because it is efficient and that the result always will be sent on a port or
+%% converted by means of list_to_binary/1
+complete1(InList) when list(InList) ->
+ complete1(InList,[],[]);
+complete1(InList) ->
+ complete1([InList],[],[]).
+
+complete1([],Acc,Bacc) ->
+ {Acc,Bacc};
+complete1([H|T],Acc,Bacc) when list(H) ->
+ {NewH,NewBacc} = complete1(H,Acc,Bacc),
+ complete1(T,NewH,NewBacc);
+
+complete1([{octets,Bin}|T],Acc,[]) ->
+ complete1(T,[Acc|Bin],[]);
+
+complete1([{octets,Bin}|T],Acc,Bacc) ->
+ complete1(T,[Acc|[complete_bytes(Bacc),Bin]],[]);
+
+complete1([{debug,_}|T], Acc,Bacc) ->
+ complete1(T,Acc,Bacc);
+
+complete1([{bits,N,Val}|T],Acc,Bacc) ->
+ complete1(T,Acc,complete_update_byte(Bacc,Val,N));
+
+complete1([{bit,Val}|T],Acc,Bacc) ->
+ complete1(T,Acc,complete_update_byte(Bacc,Val,1));
+
+complete1([align|T],Acc,[]) ->
+ complete1(T,Acc,[]);
+complete1([align|T],Acc,Bacc) ->
+ complete1(T,[Acc|complete_bytes(Bacc)],[]);
+complete1([{0,Bin}|T],Acc,[]) when binary(Bin) ->
+ complete1(T,[Acc|Bin],[]);
+complete1([{Unused,Bin}|T],Acc,[]) when integer(Unused),binary(Bin) ->
+ Size = size(Bin)-1,
+ <<Bs:Size/binary,B>> = Bin,
+ NumBits = 8-Unused,
+ complete1(T,[Acc|Bs],[[B bsr Unused]|NumBits]);
+complete1([{Unused,Bin}|T],Acc,Bacc) when integer(Unused),binary(Bin) ->
+ Size = size(Bin)-1,
+ <<Bs:Size/binary,B>> = Bin,
+ NumBits = 8 - Unused,
+ Bf = complete_bytes(Bacc),
+ complete1(T,[Acc|[Bf,Bs]],[[B bsr Unused]|NumBits]).
+
+
+complete_update_byte([],Val,Len) ->
+ complete_update_byte([[0]|0],Val,Len);
+complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) when NumBits + Len == 8 ->
+ [[0,((Byte bsl Len) + Val) band 255|Bacc]|0];
+complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) when NumBits + Len > 8 ->
+ Rem = 8 - NumBits,
+ Rest = Len - Rem,
+ complete_update_byte([[0,((Byte bsl Rem) + (Val bsr Rest)) band 255 |Bacc]|0],Val,Rest);
+complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) ->
+ [[((Byte bsl Len) + Val) band 255|Bacc]|NumBits+Len].
+
+
+complete_bytes([[_Byte|Bacc]|0]) ->
+ lists:reverse(Bacc);
+complete_bytes([[Byte|Bacc]|NumBytes]) ->
+ lists:reverse([(Byte bsl (8-NumBytes)) band 255|Bacc]);
+complete_bytes([]) ->
+ [].
+
+% complete_bytes(L) ->
+% complete_bytes1(lists:reverse(L),[],[],0,0).
+
+% complete_bytes1([H={V,B}|T],Acc,ReplyAcc,NumBits,NumFields) when ((NumBits+B) rem 8) == 0 ->
+% NewReplyAcc = [complete_bytes2([H|Acc],0)|ReplyAcc],
+% complete_bytes1(T,[],NewReplyAcc,0,0);
+% complete_bytes1([H={V,B}|T],Acc,ReplyAcc,NumBits,NumFields) when NumFields == 7; (NumBits+B) div 8 > 0 ->
+% Rem = (NumBits+B) rem 8,
+% NewReplyAcc = [complete_bytes2([{V bsr Rem,B - Rem}|Acc],0)|ReplyAcc],
+% complete_bytes1([{V,Rem}|T],[],NewReplyAcc,0,0);
+% complete_bytes1([H={V,B}|T],Acc,ReplyAcc,NumBits,NumFields) ->
+% complete_bytes1(T,[H|Acc],ReplyAcc,NumBits+B,NumFields+1);
+% complete_bytes1([],[],ReplyAcc,_,_) ->
+% lists:reverse(ReplyAcc);
+% complete_bytes1([],Acc,ReplyAcc,NumBits,_) ->
+% PadBits = case NumBits rem 8 of
+% 0 -> 0;
+% Rem -> 8 - Rem
+% end,
+% lists:reverse([complete_bytes2(Acc,PadBits)|ReplyAcc]).
+
+
+% complete_bytes2([{V1,B1}],PadBits) ->
+% <<V1:B1,0:PadBits>>;
+% complete_bytes2([{V2,B2},{V1,B1}],PadBits) ->
+% <<V1:B1,V2:B2,0:PadBits>>;
+% complete_bytes2([{V3,B3},{V2,B2},{V1,B1}],PadBits) ->
+% <<V1:B1,V2:B2,V3:B3,0:PadBits>>;
+% complete_bytes2([{V4,B4},{V3,B3},{V2,B2},{V1,B1}],PadBits) ->
+% <<V1:B1,V2:B2,V3:B3,V4:B4,0:PadBits>>;
+% complete_bytes2([{V5,B5},{V4,B4},{V3,B3},{V2,B2},{V1,B1}],PadBits) ->
+% <<V1:B1,V2:B2,V3:B3,V4:B4,V5:B5,0:PadBits>>;
+% complete_bytes2([{V6,B6},{V5,B5},{V4,B4},{V3,B3},{V2,B2},{V1,B1}],PadBits) ->
+% <<V1:B1,V2:B2,V3:B3,V4:B4,V5:B5,V6:B6,0:PadBits>>;
+% complete_bytes2([{V7,B7},{V6,B6},{V5,B5},{V4,B4},{V3,B3},{V2,B2},{V1,B1}],PadBits) ->
+% <<V1:B1,V2:B2,V3:B3,V4:B4,V5:B5,V6:B6,V7:B7,0:PadBits>>;
+% complete_bytes2([{V8,B8},{V7,B7},{V6,B6},{V5,B5},{V4,B4},{V3,B3},{V2,B2},{V1,B1}],PadBits) ->
+% <<V1:B1,V2:B2,V3:B3,V4:B4,V5:B5,V6:B6,V7:B7,V8:B8,0:PadBits>>.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per_bin_rt2ct.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per_bin_rt2ct.erl
new file mode 100644
index 0000000000..9f02ad4466
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per_bin_rt2ct.erl
@@ -0,0 +1,2102 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1rt_per_bin_rt2ct.erl,v 1.1 2008/12/17 09:53:31 mikpe Exp $
+%%
+-module(asn1rt_per_bin_rt2ct).
+
+%% encoding / decoding of PER aligned
+
+-include("asn1_records.hrl").
+
+-export([dec_fixup/3, cindex/3, list_to_record/2]).
+-export([setchoiceext/1, setext/1, fixoptionals/3, fixextensions/2,
+ getext/1, getextension/2, skipextensions/3, getbit/1, getchoice/3 ]).
+-export([getoptionals/2, getoptionals2/2,
+ set_choice/3, encode_integer/2, encode_integer/3 ]).
+-export([decode_integer/2, decode_integer/3, encode_small_number/1,
+ decode_boolean/1, encode_length/2, decode_length/1, decode_length/2,
+ encode_small_length/1, decode_small_length/1,
+ decode_compact_bit_string/3]).
+-export([decode_enumerated/3,
+ encode_bit_string/3, decode_bit_string/3 ]).
+-export([encode_octet_string/2, decode_octet_string/2,
+ encode_null/1, decode_null/1,
+ encode_object_identifier/1, decode_object_identifier/1,
+ complete/1]).
+
+
+-export([encode_open_type/2, decode_open_type/2]).
+
+-export([%encode_UniversalString/2, decode_UniversalString/2,
+ %encode_PrintableString/2, decode_PrintableString/2,
+ encode_GeneralString/2, decode_GeneralString/2,
+ encode_GraphicString/2, decode_GraphicString/2,
+ encode_TeletexString/2, decode_TeletexString/2,
+ encode_VideotexString/2, decode_VideotexString/2,
+ %encode_VisibleString/2, decode_VisibleString/2,
+ %encode_BMPString/2, decode_BMPString/2,
+ %encode_IA5String/2, decode_IA5String/2,
+ %encode_NumericString/2, decode_NumericString/2,
+ encode_ObjectDescriptor/2, decode_ObjectDescriptor/1
+ ]).
+
+-export([decode_constrained_number/2,
+ decode_constrained_number/3,
+ decode_unconstrained_number/1,
+ decode_semi_constrained_number/2,
+ encode_unconstrained_number/1,
+ decode_constrained_number/4,
+ encode_octet_string/3,
+ decode_octet_string/3,
+ encode_known_multiplier_string/5,
+ decode_known_multiplier_string/5,
+ getoctets/2, getbits/2
+% start_drv/1,start_drv2/1,init_drv/1
+ ]).
+
+
+-export([eint_positive/1]).
+-export([pre_complete_bits/2]).
+
+-define('16K',16384).
+-define('32K',32768).
+-define('64K',65536).
+
+%%-define(nodriver,true).
+
+dec_fixup(Terms,Cnames,RemBytes) ->
+ dec_fixup(Terms,Cnames,RemBytes,[]).
+
+dec_fixup([novalue|T],[_Hc|Tc],RemBytes,Acc) ->
+ dec_fixup(T,Tc,RemBytes,Acc);
+dec_fixup([{_Name,novalue}|T],[_Hc|Tc],RemBytes,Acc) ->
+ dec_fixup(T,Tc,RemBytes,Acc);
+dec_fixup([H|T],[Hc|Tc],RemBytes,Acc) ->
+ dec_fixup(T,Tc,RemBytes,[{Hc,H}|Acc]);
+dec_fixup([],_Cnames,RemBytes,Acc) ->
+ {lists:reverse(Acc),RemBytes}.
+
+cindex(Ix,Val,Cname) ->
+ case element(Ix,Val) of
+ {Cname,Val2} -> Val2;
+ X -> X
+ end.
+
+%% converts a list to a record if necessary
+list_to_record(_,Tuple) when tuple(Tuple) ->
+ Tuple;
+list_to_record(Name,List) when list(List) ->
+ list_to_tuple([Name|List]).
+
+%%--------------------------------------------------------
+%% setchoiceext(InRootSet) -> [{bit,X}]
+%% X is set to 1 when InRootSet==false
+%% X is set to 0 when InRootSet==true
+%%
+setchoiceext(true) ->
+% [{debug,choiceext},{bits,1,0}];
+ [0];
+setchoiceext(false) ->
+% [{debug,choiceext},{bits,1,1}].
+ [1].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% setext(true|false) -> CompleteList
+%%
+
+setext(false) ->
+% [{debug,ext},{bits,1,0}];
+ [0];
+setext(true) ->
+% [{debug,ext},{bits,1,1}];
+ [1].
+
+fixoptionals(OptList,_OptLength,Val) when tuple(Val) ->
+% Bits = fixoptionals(OptList,Val,0),
+% {Val,{bits,OptLength,Bits}};
+% {Val,[10,OptLength,Bits]};
+ {Val,fixoptionals(OptList,Val,[])};
+
+fixoptionals([],_,Acc) ->
+ %% Optbits
+ lists:reverse(Acc);
+fixoptionals([Pos|Ot],Val,Acc) ->
+ case element(Pos,Val) of
+% asn1_NOVALUE -> fixoptionals(Ot,Val,Acc bsl 1);
+% asn1_DEFAULT -> fixoptionals(Ot,Val,Acc bsl 1);
+% _ -> fixoptionals(Ot,Val,(Acc bsl 1) + 1)
+ asn1_NOVALUE -> fixoptionals(Ot,Val,[0|Acc]);
+ asn1_DEFAULT -> fixoptionals(Ot,Val,[0|Acc]);
+ _ -> fixoptionals(Ot,Val,[1|Acc])
+ end.
+
+
+getext(Bytes) when tuple(Bytes) ->
+ getbit(Bytes);
+getext(Bytes) when binary(Bytes) ->
+ getbit({0,Bytes});
+getext(Bytes) when list(Bytes) ->
+ getbit({0,Bytes}).
+
+getextension(0, Bytes) ->
+ {{},Bytes};
+getextension(1, Bytes) ->
+ {Len,Bytes2} = decode_small_length(Bytes),
+ {Blist, Bytes3} = getbits_as_list(Len,Bytes2),
+ {list_to_tuple(Blist),Bytes3}.
+
+fixextensions({ext,ExtPos,ExtNum},Val) ->
+ case fixextensions(ExtPos,ExtNum+ExtPos,Val,0) of
+ 0 -> [];
+ ExtBits ->
+% [encode_small_length(ExtNum),{bits,ExtNum,ExtBits}]
+% [encode_small_length(ExtNum),[10,ExtNum,ExtBits]]
+ [encode_small_length(ExtNum),pre_complete_bits(ExtNum,ExtBits)]
+ end.
+
+fixextensions(Pos,MaxPos,_,Acc) when Pos >= MaxPos ->
+ Acc;
+fixextensions(Pos,ExtPos,Val,Acc) ->
+ Bit = case catch(element(Pos+1,Val)) of
+ asn1_NOVALUE ->
+ 0;
+ asn1_NOEXTVALUE ->
+ 0;
+ {'EXIT',_} ->
+ 0;
+ _ ->
+ 1
+ end,
+ fixextensions(Pos+1,ExtPos,Val,(Acc bsl 1)+Bit).
+
+skipextensions(Bytes,Nr,ExtensionBitPattern) ->
+ case (catch element(Nr,ExtensionBitPattern)) of
+ 1 ->
+ {_,Bytes2} = decode_open_type(Bytes,[]),
+ skipextensions(Bytes2, Nr+1, ExtensionBitPattern);
+ 0 ->
+ skipextensions(Bytes, Nr+1, ExtensionBitPattern);
+ {'EXIT',_} -> % badarg, no more extensions
+ Bytes
+ end.
+
+
+getchoice(Bytes,1,0) -> % only 1 alternative is not encoded
+ {0,Bytes};
+getchoice(Bytes,_,1) ->
+ decode_small_number(Bytes);
+getchoice(Bytes,NumChoices,0) ->
+ decode_constrained_number(Bytes,{0,NumChoices-1}).
+
+%% old version kept for backward compatibility with generates from R7B01
+getoptionals(Bytes,NumOpt) ->
+ {Blist,Bytes1} = getbits_as_list(NumOpt,Bytes),
+ {list_to_tuple(Blist),Bytes1}.
+
+%% new version used in generates from r8b_patch/3 and later
+getoptionals2(Bytes,NumOpt) ->
+ {_,_} = getbits(Bytes,NumOpt).
+
+
+%% getbits_as_binary(Num,Bytes) -> {{Unused,BinBits},RestBytes},
+%% Num = integer(),
+%% Bytes = list() | tuple(),
+%% Unused = integer(),
+%% BinBits = binary(),
+%% RestBytes = tuple()
+getbits_as_binary(Num,Bytes) when binary(Bytes) ->
+ getbits_as_binary(Num,{0,Bytes});
+getbits_as_binary(0,Buffer) ->
+ {{0,<<>>},Buffer};
+getbits_as_binary(Num,{0,Bin}) when Num > 16 ->
+ Used = Num rem 8,
+ Pad = (8 - Used) rem 8,
+%% Nbytes = Num div 8,
+ <<Bits:Num,_:Pad,RestBin/binary>> = Bin,
+ {{Pad,<<Bits:Num,0:Pad>>},RestBin};
+getbits_as_binary(Num,Buffer={_Used,_Bin}) -> % Unaligned buffer
+ %% Num =< 16,
+ {Bits2,Buffer2} = getbits(Buffer,Num),
+ Pad = (8 - (Num rem 8)) rem 8,
+ {{Pad,<<Bits2:Num,0:Pad>>},Buffer2}.
+
+
+% integer_from_list(Int,[],BigInt) ->
+% BigInt;
+% integer_from_list(Int,[H|T],BigInt) when Int < 8 ->
+% (BigInt bsl Int) bor (H bsr (8-Int));
+% integer_from_list(Int,[H|T],BigInt) ->
+% integer_from_list(Int-8,T,(BigInt bsl 8) bor H).
+
+getbits_as_list(Num,Bytes) when binary(Bytes) ->
+ getbits_as_list(Num,{0,Bytes},[]);
+getbits_as_list(Num,Bytes) ->
+ getbits_as_list(Num,Bytes,[]).
+
+%% If buffer is empty and nothing more will be picked.
+getbits_as_list(0, B, Acc) ->
+ {lists:reverse(Acc),B};
+%% If first byte in buffer is full and at least one byte will be picked,
+%% then pick one byte.
+getbits_as_list(N,{0,Bin},Acc) when N >= 8 ->
+ <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Rest/binary>> = Bin,
+ getbits_as_list(N-8,{0,Rest},[B0,B1,B2,B3,B4,B5,B6,B7|Acc]);
+getbits_as_list(N,{Used,Bin},Acc) when N >= 4, Used =< 4 ->
+ NewUsed = Used + 4,
+ Rem = 8 - NewUsed,
+ <<_:Used,B3:1,B2:1,B1:1,B0:1,_:Rem, Rest/binary>> = Bin,
+ NewRest = case Rem of 0 -> Rest; _ -> Bin end,
+ getbits_as_list(N-4,{NewUsed rem 8,NewRest},[B0,B1,B2,B3|Acc]);
+getbits_as_list(N,{Used,Bin},Acc) when N >= 2, Used =< 6 ->
+ NewUsed = Used + 2,
+ Rem = 8 - NewUsed,
+ <<_:Used,B1:1,B0:1,_:Rem, Rest/binary>> = Bin,
+ NewRest = case Rem of 0 -> Rest; _ -> Bin end,
+ getbits_as_list(N-2,{NewUsed rem 8,NewRest},[B0,B1|Acc]);
+getbits_as_list(N,{Used,Bin},Acc) when Used =< 7 ->
+ NewUsed = Used + 1,
+ Rem = 8 - NewUsed,
+ <<_:Used,B0:1,_:Rem, Rest/binary>> = Bin,
+ NewRest = case Rem of 0 -> Rest; _ -> Bin end,
+ getbits_as_list(N-1,{NewUsed rem 8,NewRest},[B0|Acc]).
+
+
+getbit({7,<<_:7,B:1,Rest/binary>>}) ->
+ {B,{0,Rest}};
+getbit({0,Buffer = <<B:1,_:7,_/binary>>}) ->
+ {B,{1,Buffer}};
+getbit({Used,Buffer}) ->
+ Unused = (8 - Used) - 1,
+ <<_:Used,B:1,_:Unused,_/binary>> = Buffer,
+ {B,{Used+1,Buffer}};
+getbit(Buffer) when binary(Buffer) ->
+ getbit({0,Buffer}).
+
+
+getbits({0,Buffer},Num) when (Num rem 8) == 0 ->
+ <<Bits:Num,Rest/binary>> = Buffer,
+ {Bits,{0,Rest}};
+getbits({Used,Bin},Num) ->
+ NumPlusUsed = Num + Used,
+ NewUsed = NumPlusUsed rem 8,
+ Unused = (8-NewUsed) rem 8,
+ case Unused of
+ 0 ->
+ <<_:Used,Bits:Num,Rest/binary>> = Bin,
+ {Bits,{0,Rest}};
+ _ ->
+ Bytes = NumPlusUsed div 8,
+ <<_:Used,Bits:Num,_:Unused,_/binary>> = Bin,
+ <<_:Bytes/binary,Rest/binary>> = Bin,
+ {Bits,{NewUsed,Rest}}
+ end;
+getbits(Bin,Num) when binary(Bin) ->
+ getbits({0,Bin},Num).
+
+
+
+% getoctet(Bytes) when list(Bytes) ->
+% getoctet({0,Bytes});
+% getoctet(Bytes) ->
+% %% io:format("getoctet:Buffer = ~p~n",[Bytes]),
+% getoctet1(Bytes).
+
+% getoctet1({0,[H|T]}) ->
+% {H,{0,T}};
+% getoctet1({Pos,[_,H|T]}) ->
+% {H,{0,T}}.
+
+align({0,L}) ->
+ {0,L};
+align({_Pos,<<_H,T/binary>>}) ->
+ {0,T};
+align(Bytes) ->
+ {0,Bytes}.
+
+%% First align buffer, then pick the first Num octets.
+%% Returns octets as an integer with bit significance as in buffer.
+getoctets({0,Buffer},Num) ->
+ <<Val:Num/integer-unit:8,RestBin/binary>> = Buffer,
+ {Val,{0,RestBin}};
+getoctets({U,<<_Padding,Rest/binary>>},Num) when U /= 0 ->
+ getoctets({0,Rest},Num);
+getoctets(Buffer,Num) when binary(Buffer) ->
+ getoctets({0,Buffer},Num).
+% getoctets(Buffer,Num) ->
+% %% io:format("getoctets:Buffer = ~p~nNum = ~p~n",[Buffer,Num]),
+% getoctets(Buffer,Num,0).
+
+% getoctets(Buffer,0,Acc) ->
+% {Acc,Buffer};
+% getoctets(Buffer,Num,Acc) ->
+% {Oct,NewBuffer} = getoctet(Buffer),
+% getoctets(NewBuffer,Num-1,(Acc bsl 8)+Oct).
+
+% getoctets_as_list(Buffer,Num) ->
+% getoctets_as_list(Buffer,Num,[]).
+
+% getoctets_as_list(Buffer,0,Acc) ->
+% {lists:reverse(Acc),Buffer};
+% getoctets_as_list(Buffer,Num,Acc) ->
+% {Oct,NewBuffer} = getoctet(Buffer),
+% getoctets_as_list(NewBuffer,Num-1,[Oct|Acc]).
+
+%% First align buffer, then pick the first Num octets.
+%% Returns octets as a binary
+getoctets_as_bin({0,Bin},Num)->
+ <<Octets:Num/binary,RestBin/binary>> = Bin,
+ {Octets,{0,RestBin}};
+getoctets_as_bin({_U,Bin},Num) ->
+ <<_Padding,Octets:Num/binary,RestBin/binary>> = Bin,
+ {Octets,{0,RestBin}};
+getoctets_as_bin(Bin,Num) when binary(Bin) ->
+ getoctets_as_bin({0,Bin},Num).
+
+%% same as above but returns octets as a List
+getoctets_as_list(Buffer,Num) ->
+ {Bin,Buffer2} = getoctets_as_bin(Buffer,Num),
+ {binary_to_list(Bin),Buffer2}.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% set_choice(Alt,Choices,Altnum) -> ListofBitSettings
+%% Alt = atom()
+%% Altnum = integer() | {integer(),integer()}% number of alternatives
+%% Choices = [atom()] | {[atom()],[atom()]}
+%% When Choices is a tuple the first list is the Rootset and the
+%% second is the Extensions and then Altnum must also be a tuple with the
+%% lengths of the 2 lists
+%%
+set_choice(Alt,{L1,L2},{Len1,_Len2}) ->
+ case set_choice_tag(Alt,L1) of
+ N when integer(N), Len1 > 1 ->
+% [{bits,1,0}, % the value is in the root set
+% encode_constrained_number({0,Len1-1},N)];
+ [0, % the value is in the root set
+ encode_constrained_number({0,Len1-1},N)];
+ N when integer(N) ->
+% [{bits,1,0}]; % no encoding if only 0 or 1 alternative
+ [0]; % no encoding if only 0 or 1 alternative
+ false ->
+% [{bits,1,1}, % extension value
+ [1, % extension value
+ case set_choice_tag(Alt,L2) of
+ N2 when integer(N2) ->
+ encode_small_number(N2);
+ false ->
+ unknown_choice_alt
+ end]
+ end;
+set_choice(Alt,L,Len) ->
+ case set_choice_tag(Alt,L) of
+ N when integer(N), Len > 1 ->
+ encode_constrained_number({0,Len-1},N);
+ N when integer(N) ->
+ []; % no encoding if only 0 or 1 alternative
+ false ->
+ [unknown_choice_alt]
+ end.
+
+set_choice_tag(Alt,Choices) ->
+ set_choice_tag(Alt,Choices,0).
+
+set_choice_tag(Alt,[Alt|_Rest],Tag) ->
+ Tag;
+set_choice_tag(Alt,[_H|Rest],Tag) ->
+ set_choice_tag(Alt,Rest,Tag+1);
+set_choice_tag(_Alt,[],_Tag) ->
+ false.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% decode_fragmented_XXX; decode of values encoded fragmented according
+%% to ITU-T X.691 clause 10.9.3.8. The unit (XXX) is either bits, octets,
+%% characters or number of components (in a choice,sequence or similar).
+%% Buffer is a buffer {Used, Bin}.
+%% C is the constrained length.
+%% If the buffer is not aligned, this function does that.
+decode_fragmented_bits({0,Buffer},C) ->
+ decode_fragmented_bits(Buffer,C,[]);
+decode_fragmented_bits({_N,<<_B,Bs/binary>>},C) ->
+ decode_fragmented_bits(Bs,C,[]).
+
+decode_fragmented_bits(<<3:2,Len:6,Bin/binary>>,C,Acc) ->
+ {Value,Bin2} = split_binary(Bin, Len * ?'16K'),
+ decode_fragmented_bits(Bin2,C,[Value,Acc]);
+decode_fragmented_bits(<<0:1,0:7,Bin/binary>>,C,Acc) ->
+ BinBits = list_to_binary(lists:reverse(Acc)),
+ case C of
+ Int when integer(Int),C == size(BinBits) ->
+ {BinBits,{0,Bin}};
+ Int when integer(Int) ->
+ exit({error,{asn1,{illegal_value,C,BinBits}}});
+ _ ->
+ {BinBits,{0,Bin}}
+ end;
+decode_fragmented_bits(<<0:1,Len:7,Bin/binary>>,C,Acc) ->
+ Result = {BinBits,{Used,_Rest}} =
+ case (Len rem 8) of
+ 0 ->
+ <<Value:Len/binary-unit:1,Bin2/binary>> = Bin,
+ {list_to_binary(lists:reverse([Value|Acc])),{0,Bin2}};
+ Rem ->
+ Bytes = Len div 8,
+ U = 8 - Rem,
+ <<Value:Bytes/binary-unit:8,Bits1:Rem,Bits2:U,Bin2/binary>> = Bin,
+ {list_to_binary(lists:reverse([Bits1 bsl U,Value|Acc])),
+ {Rem,<<Bits2,Bin2/binary>>}}
+ end,
+ case C of
+ Int when integer(Int),C == (size(BinBits) - ((8 - Used) rem 8)) ->
+ Result;
+ Int when integer(Int) ->
+ exit({error,{asn1,{illegal_value,C,BinBits}}});
+ _ ->
+ Result
+ end.
+
+
+decode_fragmented_octets({0,Bin},C) ->
+ decode_fragmented_octets(Bin,C,[]);
+decode_fragmented_octets({_N,<<_B,Bs/binary>>},C) ->
+ decode_fragmented_octets(Bs,C,[]).
+
+decode_fragmented_octets(<<3:2,Len:6,Bin/binary>>,C,Acc) ->
+ {Value,Bin2} = split_binary(Bin,Len * ?'16K'),
+ decode_fragmented_octets(Bin2,C,[Value,Acc]);
+decode_fragmented_octets(<<0:1,0:7,Bin/binary>>,C,Acc) ->
+ Octets = list_to_binary(lists:reverse(Acc)),
+ case C of
+ Int when integer(Int), C == size(Octets) ->
+ {Octets,{0,Bin}};
+ Int when integer(Int) ->
+ exit({error,{asn1,{illegal_value,C,Octets}}});
+ _ ->
+ {Octets,{0,Bin}}
+ end;
+decode_fragmented_octets(<<0:1,Len:7,Bin/binary>>,C,Acc) ->
+ <<Value:Len/binary-unit:8,Bin2/binary>> = Bin,
+ BinOctets = list_to_binary(lists:reverse([Value|Acc])),
+ case C of
+ Int when integer(Int),size(BinOctets) == Int ->
+ {BinOctets,Bin2};
+ Int when integer(Int) ->
+ exit({error,{asn1,{illegal_value,C,BinOctets}}});
+ _ ->
+ {BinOctets,Bin2}
+ end.
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_open_type(Constraint, Value) -> CompleteList
+%% Value = list of bytes of an already encoded value (the list must be flat)
+%% | binary
+%% Contraint = not used in this version
+%%
+encode_open_type(_Constraint, Val) when list(Val) ->
+ Bin = list_to_binary(Val),
+ case size(Bin) of
+ Size when Size>255 ->
+ [encode_length(undefined,Size),[21,<<Size:16>>,Bin]];
+ Size ->
+ [encode_length(undefined,Size),[20,Size,Bin]]
+ end;
+% [encode_length(undefined,size(Bin)),{octets,Bin}]; % octets implies align
+encode_open_type(_Constraint, Val) when binary(Val) ->
+% [encode_length(undefined,size(Val)),{octets,Val}]. % octets implies align
+ case size(Val) of
+ Size when Size>255 ->
+ [encode_length(undefined,size(Val)),[21,<<Size:16>>,Val]]; % octets implies align
+ Size ->
+ [encode_length(undefined,Size),[20,Size,Val]]
+ end.
+%% the binary_to_list is not optimal but compatible with the current solution
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% decode_open_type(Buffer,Constraint) -> Value
+%% Constraint is not used in this version
+%% Buffer = [byte] with PER encoded data
+%% Value = [byte] with decoded data (which must be decoded again as some type)
+%%
+decode_open_type(Bytes, _Constraint) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ getoctets_as_bin(Bytes2,Len).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_integer(Constraint,Value,NamedNumberList) -> CompleteList
+%% encode_integer(Constraint,Value) -> CompleteList
+%% encode_integer(Constraint,{Name,Value}) -> CompleteList
+%%
+%%
+encode_integer(C,V,NamedNumberList) when atom(V) ->
+ case lists:keysearch(V,1,NamedNumberList) of
+ {value,{_,NewV}} ->
+ encode_integer(C,NewV);
+ _ ->
+ exit({error,{asn1,{namednumber,V}}})
+ end;
+encode_integer(C,V,_NamedNumberList) when integer(V) ->
+ encode_integer(C,V);
+encode_integer(C,{Name,V},NamedNumberList) when atom(Name) ->
+ encode_integer(C,V,NamedNumberList).
+
+encode_integer(C,{Name,Val}) when atom(Name) ->
+ encode_integer(C,Val);
+
+encode_integer([{Rc,_Ec}],Val) when tuple(Rc) -> % XXX when is this invoked? First argument most often a list,...Ok this is the extension case...but it doesn't work.
+ case (catch encode_integer([Rc],Val)) of
+ {'EXIT',{error,{asn1,_}}} ->
+% [{bits,1,1},encode_unconstrained_number(Val)];
+ [1,encode_unconstrained_number(Val)];
+ Encoded ->
+% [{bits,1,0},Encoded]
+ [0,Encoded]
+ end;
+
+encode_integer([],Val) ->
+ encode_unconstrained_number(Val);
+%% The constraint is the effective constraint, and in this case is a number
+encode_integer([{'SingleValue',V}],V) ->
+ [];
+encode_integer([{'ValueRange',VR={Lb,Ub},Range,PreEnc}],Val) when Val >= Lb,
+ Ub >= Val ->
+ %% this case when NamedNumberList
+ encode_constrained_number(VR,Range,PreEnc,Val);
+encode_integer([{'ValueRange',{Lb,'MAX'}}],Val) ->
+ encode_semi_constrained_number(Lb,Val);
+encode_integer([{'ValueRange',{'MIN',_}}],Val) ->
+ encode_unconstrained_number(Val);
+encode_integer([{'ValueRange',VR={_Lb,_Ub}}],Val) ->
+ encode_constrained_number(VR,Val);
+encode_integer(_,Val) ->
+ exit({error,{asn1,{illegal_value,Val}}}).
+
+
+
+decode_integer(Buffer,Range,NamedNumberList) ->
+ {Val,Buffer2} = decode_integer(Buffer,Range),
+ case lists:keysearch(Val,2,NamedNumberList) of
+ {value,{NewVal,_}} -> {NewVal,Buffer2};
+ _ -> {Val,Buffer2}
+ end.
+
+decode_integer(Buffer,[{Rc,_Ec}]) when tuple(Rc) ->
+ {Ext,Buffer2} = getext(Buffer),
+ case Ext of
+ 0 -> decode_integer(Buffer2,[Rc]);
+ 1 -> decode_unconstrained_number(Buffer2)
+ end;
+decode_integer(Buffer,undefined) ->
+ decode_unconstrained_number(Buffer);
+decode_integer(Buffer,C) ->
+ case get_constraint(C,'SingleValue') of
+ V when integer(V) ->
+ {V,Buffer};
+ _ ->
+ decode_integer1(Buffer,C)
+ end.
+
+decode_integer1(Buffer,C) ->
+ case VR = get_constraint(C,'ValueRange') of
+ no ->
+ decode_unconstrained_number(Buffer);
+ {Lb, 'MAX'} ->
+ decode_semi_constrained_number(Buffer,Lb);
+ {_Lb,_Ub} ->
+ decode_constrained_number(Buffer,VR)
+ end.
+
+%% X.691:10.6 Encoding of a normally small non-negative whole number
+%% Use this for encoding of CHOICE index if there is an extension marker in
+%% the CHOICE
+encode_small_number({Name,Val}) when atom(Name) ->
+ encode_small_number(Val);
+encode_small_number(Val) when Val =< 63 ->
+% [{bits,1,0},{bits,6,Val}];
+% [{bits,7,Val}]; % same as above but more efficient
+ [10,7,Val]; % same as above but more efficient
+encode_small_number(Val) ->
+% [{bits,1,1},encode_semi_constrained_number(0,Val)].
+ [1,encode_semi_constrained_number(0,Val)].
+
+decode_small_number(Bytes) ->
+ {Bit,Bytes2} = getbit(Bytes),
+ case Bit of
+ 0 ->
+ getbits(Bytes2,6);
+ 1 ->
+ decode_semi_constrained_number(Bytes2,0)
+ end.
+
+%% X.691:10.7 Encoding of a semi-constrained whole number
+%% might be an optimization encode_semi_constrained_number(0,Val) ->
+encode_semi_constrained_number(C,{Name,Val}) when atom(Name) ->
+ encode_semi_constrained_number(C,Val);
+encode_semi_constrained_number({Lb,'MAX'},Val) ->
+ encode_semi_constrained_number(Lb,Val);
+encode_semi_constrained_number(Lb,Val) ->
+ Val2 = Val - Lb,
+ Oct = eint_positive(Val2),
+ Len = length(Oct),
+ if
+ Len < 128 ->
+ %{octets,[Len|Oct]}; % equiv with encode_length(undefined,Len) but faster
+ [20,Len+1,[Len|Oct]];
+ Len < 256 ->
+ [encode_length(undefined,Len),[20,Len,Oct]];
+ true ->
+ [encode_length(undefined,Len),[21,<<Len:16>>,Oct]]
+ end.
+
+decode_semi_constrained_number(Bytes,{Lb,_}) ->
+ decode_semi_constrained_number(Bytes,Lb);
+decode_semi_constrained_number(Bytes,Lb) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ {V,Bytes3} = getoctets(Bytes2,Len),
+ {V+Lb,Bytes3}.
+
+encode_constrained_number({Lb,_Ub},_Range,{bits,N},Val) ->
+ Val2 = Val-Lb,
+% {bits,N,Val2};
+ [10,N,Val2];
+encode_constrained_number({Lb,_Ub},_Range,{octets,N},Val) when N < 256->
+ %% N is 8 or 16 (1 or 2 octets)
+ Val2 = Val-Lb,
+% {octets,<<Val2:N/unit:8>>};
+ [20,N,Val2];
+encode_constrained_number({Lb,_Ub},_Range,{octets,N},Val) -> % N>255
+ %% N is 8 or 16 (1 or 2 octets)
+ Val2 = Val-Lb,
+% {octets,<<Val2:N/unit:8>>};
+ [21,<<N:16>>,Val2];
+encode_constrained_number({Lb,_Ub},Range,_,Val) ->
+ Val2 = Val-Lb,
+ if
+ Range =< 16#1000000 -> % max 3 octets
+ Octs = eint_positive(Val2),
+% [encode_length({1,3},size(Octs)),{octets,Octs}];
+ L = length(Octs),
+ [encode_length({1,3},L),[20,L,Octs]];
+ Range =< 16#100000000 -> % max 4 octets
+ Octs = eint_positive(Val2),
+% [encode_length({1,4},size(Octs)),{octets,Octs}];
+ L = length(Octs),
+ [encode_length({1,4},L),[20,L,Octs]];
+ Range =< 16#10000000000 -> % max 5 octets
+ Octs = eint_positive(Val2),
+% [encode_length({1,5},size(Octs)),{octets,Octs}];
+ L = length(Octs),
+ [encode_length({1,5},L),[20,L,Octs]];
+ true ->
+ exit({not_supported,{integer_range,Range}})
+ end.
+
+encode_constrained_number(Range,{Name,Val}) when atom(Name) ->
+ encode_constrained_number(Range,Val);
+encode_constrained_number({Lb,Ub},Val) when Val >= Lb, Ub >= Val ->
+ Range = Ub - Lb + 1,
+ Val2 = Val - Lb,
+ if
+ Range == 2 ->
+% Size = {bits,1,Val2};
+ [Val2];
+ Range =< 4 ->
+% Size = {bits,2,Val2};
+ [10,2,Val2];
+ Range =< 8 ->
+ [10,3,Val2];
+ Range =< 16 ->
+ [10,4,Val2];
+ Range =< 32 ->
+ [10,5,Val2];
+ Range =< 64 ->
+ [10,6,Val2];
+ Range =< 128 ->
+ [10,7,Val2];
+ Range =< 255 ->
+ [10,8,Val2];
+ Range =< 256 ->
+% Size = {octets,[Val2]};
+ [20,1,Val2];
+ Range =< 65536 ->
+% Size = {octets,<<Val2:16>>};
+ [20,2,<<Val2:16>>];
+ Range =< 16#1000000 ->
+ Octs = eint_positive(Val2),
+% [{bits,2,length(Octs)-1},{octets,Octs}];
+ Len = length(Octs),
+ [10,2,Len-1,20,Len,Octs];
+ Range =< 16#100000000 ->
+ Octs = eint_positive(Val2),
+ Len = length(Octs),
+ [10,2,Len-1,20,Len,Octs];
+ Range =< 16#10000000000 ->
+ Octs = eint_positive(Val2),
+ Len = length(Octs),
+ [10,3,Len-1,20,Len,Octs];
+ true ->
+ exit({not_supported,{integer_range,Range}})
+ end;
+encode_constrained_number({_,_},Val) ->
+ exit({error,{asn1,{illegal_value,Val}}}).
+
+decode_constrained_number(Buffer,VR={Lb,Ub}) ->
+ Range = Ub - Lb + 1,
+ decode_constrained_number(Buffer,VR,Range).
+
+decode_constrained_number(Buffer,{Lb,_Ub},_Range,{bits,N}) ->
+ {Val,Remain} = getbits(Buffer,N),
+ {Val+Lb,Remain};
+decode_constrained_number(Buffer,{Lb,_Ub},_Range,{octets,N}) ->
+ {Val,Remain} = getoctets(Buffer,N),
+ {Val+Lb,Remain}.
+
+decode_constrained_number(Buffer,{Lb,_Ub},Range) ->
+ % Val2 = Val - Lb,
+ {Val,Remain} =
+ if
+ Range == 2 ->
+ getbits(Buffer,1);
+ Range =< 4 ->
+ getbits(Buffer,2);
+ Range =< 8 ->
+ getbits(Buffer,3);
+ Range =< 16 ->
+ getbits(Buffer,4);
+ Range =< 32 ->
+ getbits(Buffer,5);
+ Range =< 64 ->
+ getbits(Buffer,6);
+ Range =< 128 ->
+ getbits(Buffer,7);
+ Range =< 255 ->
+ getbits(Buffer,8);
+ Range =< 256 ->
+ getoctets(Buffer,1);
+ Range =< 65536 ->
+ getoctets(Buffer,2);
+ Range =< 16#1000000 ->
+ {Len,Bytes2} = decode_length(Buffer,{1,3}),
+ {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
+ {dec_pos_integer(Octs),Bytes3};
+ Range =< 16#100000000 ->
+ {Len,Bytes2} = decode_length(Buffer,{1,4}),
+ {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
+ {dec_pos_integer(Octs),Bytes3};
+ Range =< 16#10000000000 ->
+ {Len,Bytes2} = decode_length(Buffer,{1,5}),
+ {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
+ {dec_pos_integer(Octs),Bytes3};
+ true ->
+ exit({not_supported,{integer_range,Range}})
+ end,
+ {Val+Lb,Remain}.
+
+%% X.691:10.8 Encoding of an unconstrained whole number
+
+encode_unconstrained_number(Val) when Val >= 0 ->
+ Oct = eint(Val,[]),
+ Len = length(Oct),
+ if
+ Len < 128 ->
+ %{octets,[Len|Oct]}; % equiv with encode_length(undefined,Len) but faster
+ [20,Len+1,[Len|Oct]];
+ Len < 256 ->
+% [encode_length(undefined,Len),20,Len,Oct];
+ [20,Len+2,<<2:2,Len:14>>,Oct];% equiv with encode_length(undefined,Len) but faster
+ true ->
+% [encode_length(undefined,Len),{octets,Oct}]
+ [encode_length(undefined,Len),[21,<<Len:16>>,Oct]]
+ end;
+encode_unconstrained_number(Val) -> % negative
+ Oct = enint(Val,[]),
+ Len = length(Oct),
+ if
+ Len < 128 ->
+% {octets,[Len|Oct]}; % equiv with encode_length(undefined,Len) but faster
+ [20,Len+1,[Len|Oct]];% equiv with encode_length(undefined,Len) but faster
+ Len < 256 ->
+% [encode_length(undefined,Len),20,Len,Oct];
+ [20,Len+2,<<2:2,Len:14>>,Oct];% equiv with encode_length(undefined,Len) but faster
+ true ->
+ %[encode_length(undefined,Len),{octets,Oct}]
+ [encode_length(undefined,Len),[21,<<Len:16>>,Oct]]
+ end.
+
+
+%% used for positive Values which don't need a sign bit
+%% returns a list
+eint_positive(Val) ->
+ case eint(Val,[]) of
+ [0,B1|T] ->
+ [B1|T];
+ T ->
+ T
+ end.
+
+
+eint(0, [B|Acc]) when B < 128 ->
+ [B|Acc];
+eint(N, Acc) ->
+ eint(N bsr 8, [N band 16#ff| Acc]).
+
+enint(-1, [B1|T]) when B1 > 127 ->
+ [B1|T];
+enint(N, Acc) ->
+ enint(N bsr 8, [N band 16#ff|Acc]).
+
+decode_unconstrained_number(Bytes) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ {Ints,Bytes3} = getoctets_as_list(Bytes2,Len),
+ {dec_integer(Ints),Bytes3}.
+
+dec_pos_integer(Ints) ->
+ decpint(Ints, 8 * (length(Ints) - 1)).
+dec_integer(Ints) when hd(Ints) band 255 =< 127 -> %% Positive number
+ decpint(Ints, 8 * (length(Ints) - 1));
+dec_integer(Ints) -> %% Negative
+ decnint(Ints, 8 * (length(Ints) - 1)).
+
+decpint([Byte|Tail], Shift) ->
+ (Byte bsl Shift) bor decpint(Tail, Shift-8);
+decpint([], _) -> 0.
+
+decnint([Byte|Tail], Shift) ->
+ (-128 + (Byte band 127) bsl Shift) bor decpint(Tail, Shift-8).
+
+% minimum_octets(Val) ->
+% minimum_octets(Val,[]).
+
+% minimum_octets(Val,Acc) when Val > 0 ->
+% minimum_octets((Val bsr 8),[Val band 16#FF|Acc]);
+% minimum_octets(0,Acc) ->
+% Acc.
+
+
+%% X.691:10.9 Encoding of a length determinant
+%%encode_small_length(undefined,Len) -> % null means no UpperBound
+%% encode_small_number(Len).
+
+%% X.691:10.9.3.5
+%% X.691:10.9.3.7
+encode_length(undefined,Len) -> % un-constrained
+ if
+ Len < 128 ->
+% {octets,[Len]};
+ [20,1,Len];
+ Len < 16384 ->
+ %{octets,<<2:2,Len:14>>};
+ [20,2,<<2:2,Len:14>>];
+ true -> % should be able to endode length >= 16384 i.e. fragmented length
+ exit({error,{asn1,{encode_length,{nyi,above_16k}}}})
+ end;
+
+encode_length({0,'MAX'},Len) ->
+ encode_length(undefined,Len);
+encode_length(Vr={Lb,Ub},Len) when Ub =< 65535 ,Lb >= 0 -> % constrained
+ encode_constrained_number(Vr,Len);
+encode_length({Lb,_Ub},Len) when integer(Lb), Lb >= 0 -> % Ub > 65535
+ encode_length(undefined,Len);
+encode_length({Vr={Lb,Ub},[]},Len) when Ub =< 65535 ,Lb >= 0,Len=<Ub ->
+ %% constrained extensible
+% [{bits,1,0},encode_constrained_number(Vr,Len)];
+ [0,encode_constrained_number(Vr,Len)];
+encode_length({{Lb,_},[]},Len) ->
+ [1,encode_semi_constrained_number(Lb,Len)];
+encode_length(SingleValue,_Len) when integer(SingleValue) ->
+ [].
+
+%% X.691 10.9.3.4 (only used for length of bitmap that prefixes extension
+%% additions in a sequence or set
+encode_small_length(Len) when Len =< 64 ->
+%% [{bits,1,0},{bits,6,Len-1}];
+% {bits,7,Len-1}; % the same as above but more efficient
+ [10,7,Len-1];
+encode_small_length(Len) ->
+% [{bits,1,1},encode_length(undefined,Len)].
+ [1,encode_length(undefined,Len)].
+
+% decode_small_length({Used,<<_:Used,0:1,Num:6,_:((8-Used+1) rem 8),Rest/binary>>}) ->
+% case Buffer of
+% <<_:Used,0:1,Num:6,_:((8-Used+1) rem 8),Rest/binary>> ->
+% {Num,
+% case getbit(Buffer) of
+% {0,Remain} ->
+% {Bits,Remain2} = getbits(Remain,6),
+% {Bits+1,Remain2};
+% {1,Remain} ->
+% decode_length(Remain,undefined)
+% end.
+
+decode_small_length(Buffer) ->
+ case getbit(Buffer) of
+ {0,Remain} ->
+ {Bits,Remain2} = getbits(Remain,6),
+ {Bits+1,Remain2};
+ {1,Remain} ->
+ decode_length(Remain,undefined)
+ end.
+
+decode_length(Buffer) ->
+ decode_length(Buffer,undefined).
+
+decode_length(Buffer,undefined) -> % un-constrained
+ {0,Buffer2} = align(Buffer),
+ case Buffer2 of
+ <<0:1,Oct:7,Rest/binary>> ->
+ {Oct,{0,Rest}};
+ <<2:2,Val:14,Rest/binary>> ->
+ {Val,{0,Rest}};
+ <<3:2,_Val:14,_Rest/binary>> ->
+ %% this case should be fixed
+ exit({error,{asn1,{decode_length,{nyi,above_16k}}}})
+ end;
+%% {Bits,_} = getbits(Buffer2,2),
+% case Bits of
+% 2 ->
+% {Val,Bytes3} = getoctets(Buffer2,2),
+% {(Val band 16#3FFF),Bytes3};
+% 3 ->
+% exit({error,{asn1,{decode_length,{nyi,above_16k}}}});
+% _ ->
+% {Val,Bytes3} = getoctet(Buffer2),
+% {Val band 16#7F,Bytes3}
+% end;
+
+decode_length(Buffer,{Lb,Ub}) when Ub =< 65535 ,Lb >= 0 -> % constrained
+ decode_constrained_number(Buffer,{Lb,Ub});
+decode_length(_Buffer,{Lb,_Ub}) when integer(Lb), Lb >= 0 -> % Ub > 65535
+ exit({error,{asn1,{decode_length,{nyi,above_64K}}}});
+decode_length(Buffer,{{Lb,Ub},[]}) ->
+ case getbit(Buffer) of
+ {0,Buffer2} ->
+ decode_length(Buffer2, {Lb,Ub})
+ end;
+
+
+%When does this case occur with {_,_Lb,Ub} ??
+% X.691:10.9.3.5
+decode_length({Used,Bin},{_,_Lb,_Ub}) -> %when Len =< 127 -> % Unconstrained or large Ub NOTE! this case does not cover case when Ub > 65535
+ Unused = (8-Used) rem 8,
+ case Bin of
+ <<_:Used,0:1,Val:7,R:Unused,Rest/binary>> ->
+ {Val,{Used,<<R,Rest/binary>>}};
+ <<_:Used,_:Unused,2:2,Val:14,Rest/binary>> ->
+ {Val, {0,Rest}};
+ <<_:Used,_:Unused,3:2,_:14,_Rest/binary>> ->
+ exit({error,{asn1,{decode_length,{nyi,length_above_64K}}}})
+ end;
+% decode_length(Buffer,{_,_Lb,Ub}) -> %when Len =< 127 -> % Unconstrained or large Ub
+% case getbit(Buffer) of
+% {0,Remain} ->
+% getbits(Remain,7);
+% {1,Remain} ->
+% {Val,Remain2} = getoctets(Buffer,2),
+% {Val band 2#0111111111111111, Remain2}
+% end;
+decode_length(Buffer,SingleValue) when integer(SingleValue) ->
+ {SingleValue,Buffer}.
+
+
+ % X.691:11
+decode_boolean(Buffer) -> %when record(Buffer,buffer)
+ case getbit(Buffer) of
+ {1,Remain} -> {true,Remain};
+ {0,Remain} -> {false,Remain}
+ end.
+
+
+%% ENUMERATED with extension marker
+decode_enumerated(Buffer,C,{Ntup1,Ntup2}) when tuple(Ntup1), tuple(Ntup2) ->
+ {Ext,Buffer2} = getext(Buffer),
+ case Ext of
+ 0 -> % not an extension value
+ {Val,Buffer3} = decode_integer(Buffer2,C),
+ case catch (element(Val+1,Ntup1)) of
+ NewVal when atom(NewVal) -> {NewVal,Buffer3};
+ _Error -> exit({error,{asn1,{decode_enumerated,{Val,[Ntup1,Ntup2]}}}})
+ end;
+ 1 -> % this an extension value
+ {Val,Buffer3} = decode_small_number(Buffer2),
+ case catch (element(Val+1,Ntup2)) of
+ NewVal when atom(NewVal) -> {NewVal,Buffer3};
+ _ -> {{asn1_enum,Val},Buffer3}
+ end
+ end;
+
+decode_enumerated(Buffer,C,NamedNumberTup) when tuple(NamedNumberTup) ->
+ {Val,Buffer2} = decode_integer(Buffer,C),
+ case catch (element(Val+1,NamedNumberTup)) of
+ NewVal when atom(NewVal) -> {NewVal,Buffer2};
+ _Error -> exit({error,{asn1,{decode_enumerated,{Val,NamedNumberTup}}}})
+ end.
+
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+%% Bitstring value, ITU_T X.690 Chapter 8.5
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+
+%%===============================================================================
+%% encode bitstring value
+%%===============================================================================
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% bitstring NamedBitList
+%% Val can be of:
+%% - [identifiers] where only named identifers are set to one,
+%% the Constraint must then have some information of the
+%% bitlength.
+%% - [list of ones and zeroes] all bits
+%% - integer value representing the bitlist
+%% C is constraint Len, only valid when identifiers
+
+
+%% when the value is a list of {Unused,BinBits}, where
+%% Unused = integer(),
+%% BinBits = binary().
+
+encode_bit_string(C,Bin={Unused,BinBits},NamedBitList) when integer(Unused),
+ binary(BinBits) ->
+ encode_bin_bit_string(C,Bin,NamedBitList);
+
+%% when the value is a list of named bits
+
+encode_bit_string(C, LoNB=[FirstVal | _RestVal], NamedBitList) when atom(FirstVal) ->
+ ToSetPos = get_all_bitposes(LoNB, NamedBitList, []),
+ BitList = make_and_set_list(ToSetPos,0),
+ encode_bit_string(C,BitList,NamedBitList);% consider the constraint
+
+encode_bit_string(C, BL=[{bit,_} | _RestVal], NamedBitList) ->
+ ToSetPos = get_all_bitposes(BL, NamedBitList, []),
+ BitList = make_and_set_list(ToSetPos,0),
+ encode_bit_string(C,BitList,NamedBitList);
+
+%% when the value is a list of ones and zeroes
+encode_bit_string(Int, BitListValue, _)
+ when list(BitListValue),integer(Int) ->
+ %% The type is constrained by a single value size constraint
+ [40,Int,length(BitListValue),BitListValue];
+% encode_bit_string(C, BitListValue,NamedBitList)
+% when list(BitListValue) ->
+% [encode_bit_str_length(C,BitListValue),
+% 2,45,BitListValue];
+encode_bit_string(no, BitListValue,[])
+ when list(BitListValue) ->
+ [encode_length(undefined,length(BitListValue)),
+ 2,BitListValue];
+encode_bit_string(C, BitListValue,[])
+ when list(BitListValue) ->
+ [encode_length(C,length(BitListValue)),
+ 2,BitListValue];
+encode_bit_string(no, BitListValue,_NamedBitList)
+ when list(BitListValue) ->
+ %% this case with an unconstrained BIT STRING can be made more efficient
+ %% if the complete driver can take a special code so the length field
+ %% is encoded there.
+ NewBitLVal = lists:reverse(lists:dropwhile(fun(0)->true;(1)->false end,
+ lists:reverse(BitListValue))),
+ [encode_length(undefined,length(NewBitLVal)),
+ 2,NewBitLVal];
+encode_bit_string(C,BitListValue,_NamedBitList)
+ when list(BitListValue) ->% C = {_,'MAX'}
+% NewBitLVal = lists:reverse(lists:dropwhile(fun(0)->true;(1)->false end,
+% lists:reverse(BitListValue))),
+ NewBitLVal = bit_string_trailing_zeros(BitListValue,C),
+ [encode_length(C,length(NewBitLVal)),
+ 2,NewBitLVal];
+
+% encode_bit_string(C, BitListValue, NamedBitList) when list(BitListValue) ->
+% BitListToBinary =
+% %% fun that transforms a list of 1 and 0 to a tuple:
+% %% {UnusedBitsInLastByte, Binary}
+% fun([H|T],Acc,N,Fun) ->
+% Fun(T,(Acc bsl 1)+H,N+1,Fun);
+% ([],Acc,N,_) -> % length fits in one byte
+% Unused = (8 - (N rem 8)) rem 8,
+% % case N/8 of
+% % _Len =< 255 ->
+% % [30,Unused,(Unused+N)/8,<<Acc:N,0:Unused>>];
+% % _Len ->
+% % Len = (Unused+N)/8,
+% % [31,Unused,<<Len:16>>,<<Acc:N,0:Unused>>]
+% % end
+% {Unused,<<Acc:N,0:Unused>>}
+% end,
+% UnusedAndBin =
+% case NamedBitList of
+% [] -> % dont remove trailing zeroes
+% BitListToBinary(BitListValue,0,0,BitListToBinary);
+% _ ->
+% BitListToBinary(lists:reverse(
+% lists:dropwhile(fun(0)->true;(1)->false end,
+% lists:reverse(BitListValue))),
+% 0,0,BitListToBinary)
+% end,
+% encode_bin_bit_string(C,UnusedAndBin,NamedBitList);
+
+%% when the value is an integer
+encode_bit_string(C, IntegerVal, NamedBitList) when integer(IntegerVal)->
+ BitList = int_to_bitlist(IntegerVal),
+ encode_bit_string(C,BitList,NamedBitList);
+
+%% when the value is a tuple
+encode_bit_string(C,{Name,Val}, NamedBitList) when atom(Name) ->
+ encode_bit_string(C,Val,NamedBitList).
+
+bit_string_trailing_zeros(BitList,C) when integer(C) ->
+ bit_string_trailing_zeros1(BitList,C,C);
+bit_string_trailing_zeros(BitList,{Lb,Ub}) when integer(Lb) ->
+ bit_string_trailing_zeros1(BitList,Lb,Ub);
+bit_string_trailing_zeros(BitList,{{Lb,Ub},_}) when integer(Lb) ->
+ bit_string_trailing_zeros1(BitList,Lb,Ub);
+bit_string_trailing_zeros(BitList,_) ->
+ BitList.
+
+bit_string_trailing_zeros1(BitList,Lb,Ub) ->
+ case length(BitList) of
+ Lb -> BitList;
+ B when B<Lb -> BitList++lists:duplicate(Lb-B,0);
+ D -> F = fun(L,LB,LB,_,_)->lists:reverse(L);
+ ([0|R],L1,LB,UB,Fun)->Fun(R,L1-1,LB,UB,Fun);
+ (L,L1,_,UB,_)when L1 =< UB -> lists:reverse(L);
+ (_,_L1,_,_,_) ->exit({error,{list_length_BIT_STRING,
+ BitList}}) end,
+ F(lists:reverse(BitList),D,Lb,Ub,F)
+ end.
+
+%% encode_bin_bit_string/3, when value is a tuple of Unused and BinBits.
+%% Unused = integer(),i.e. number unused bits in least sign. byte of
+%% BinBits = binary().
+encode_bin_bit_string(C,{_,BinBits},_NamedBitList)
+ when integer(C),C=<16 ->
+ [45,C,size(BinBits),BinBits];
+encode_bin_bit_string(C,{_Unused,BinBits},_NamedBitList)
+ when integer(C) ->
+ [2,45,C,size(BinBits),BinBits];
+encode_bin_bit_string(C,UnusedAndBin={_,_},NamedBitList) ->
+% UnusedAndBin1 = {Unused1,Bin1} =
+ {Unused1,Bin1} =
+ %% removes all trailing bits if NamedBitList is not empty
+ remove_trailing_bin(NamedBitList,UnusedAndBin),
+ case C of
+% case get_constraint(C,'SizeConstraint') of
+
+% 0 ->
+% []; % borde avg�ras i compile-time
+% V when integer(V),V=<16 ->
+% {Unused2,Bin2} = pad_list(V,UnusedAndBin1),
+% <<BitVal:V,_:Unused2>> = Bin2,
+% % {bits,V,BitVal};
+% [10,V,BitVal];
+% V when integer(V) ->
+% %[align, pad_list(V, UnusedAndBin1)];
+% {Unused2,Bin2} = pad_list(V, UnusedAndBin1),
+% <<BitVal:V,_:Unused2>> = Bin2,
+% [2,octets_unused_to_complete(Unused2,size(Bin2),Bin2)];
+
+ {Lb,Ub} when integer(Lb),integer(Ub) ->
+% [encode_length({Lb,Ub},size(Bin1)*8 - Unused1),
+% align,UnusedAndBin1];
+ Size=size(Bin1),
+ [encode_length({Lb,Ub},Size*8 - Unused1),
+ 2,octets_unused_to_complete(Unused1,Size,Bin1)];
+ no ->
+ Size=size(Bin1),
+ [encode_length(undefined,Size*8 - Unused1),
+ 2,octets_unused_to_complete(Unused1,Size,Bin1)];
+ Sc ->
+ Size=size(Bin1),
+ [encode_length(Sc,Size*8 - Unused1),
+ 2,octets_unused_to_complete(Unused1,Size,Bin1)]
+ end.
+
+remove_trailing_bin([], {Unused,Bin}) ->
+ {Unused,Bin};
+remove_trailing_bin(NamedNumberList, {_Unused,Bin}) ->
+ Size = size(Bin)-1,
+ <<Bfront:Size/binary, LastByte:8>> = Bin,
+ %% clear the Unused bits to be sure
+% LastByte1 = LastByte band (((1 bsl Unused) -1) bxor 255),% why this???
+ Unused1 = trailingZeroesInNibble(LastByte band 15),
+ Unused2 =
+ case Unused1 of
+ 4 ->
+ 4 + trailingZeroesInNibble(LastByte bsr 4);
+ _ -> Unused1
+ end,
+ case Unused2 of
+ 8 ->
+ remove_trailing_bin(NamedNumberList,{0,Bfront});
+ _ ->
+ {Unused2,Bin}
+ end.
+
+
+trailingZeroesInNibble(0) ->
+ 4;
+trailingZeroesInNibble(1) ->
+ 0;
+trailingZeroesInNibble(2) ->
+ 1;
+trailingZeroesInNibble(3) ->
+ 0;
+trailingZeroesInNibble(4) ->
+ 2;
+trailingZeroesInNibble(5) ->
+ 0;
+trailingZeroesInNibble(6) ->
+ 1;
+trailingZeroesInNibble(7) ->
+ 0;
+trailingZeroesInNibble(8) ->
+ 3;
+trailingZeroesInNibble(9) ->
+ 0;
+trailingZeroesInNibble(10) ->
+ 1;
+trailingZeroesInNibble(11) ->
+ 0;
+trailingZeroesInNibble(12) -> %#1100
+ 2;
+trailingZeroesInNibble(13) ->
+ 0;
+trailingZeroesInNibble(14) ->
+ 1;
+trailingZeroesInNibble(15) ->
+ 0.
+
+%%%%%%%%%%%%%%%
+%% The result is presented as a list of named bits (if possible)
+%% else as a tuple {Unused,Bits}. Unused is the number of unused
+%% bits, least significant bits in the last byte of Bits. Bits is
+%% the BIT STRING represented as a binary.
+%%
+decode_compact_bit_string(Buffer, C, NamedNumberList) ->
+ case get_constraint(C,'SizeConstraint') of
+ 0 -> % fixed length
+ {{8,0},Buffer};
+ V when integer(V),V=<16 -> %fixed length 16 bits or less
+ compact_bit_string(Buffer,V,NamedNumberList);
+ V when integer(V),V=<65536 -> %fixed length > 16 bits
+ Bytes2 = align(Buffer),
+ compact_bit_string(Bytes2,V,NamedNumberList);
+ V when integer(V) -> % V > 65536 => fragmented value
+ {Bin,Buffer2} = decode_fragmented_bits(Buffer,V),
+ case Buffer2 of
+ {0,_} -> {{0,Bin},Buffer2};
+ {U,_} -> {{8-U,Bin},Buffer2}
+ end;
+ {Lb,Ub} when integer(Lb),integer(Ub) ->
+ %% This case may demand decoding of fragmented length/value
+ {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
+ Bytes3 = align(Bytes2),
+ compact_bit_string(Bytes3,Len,NamedNumberList);
+ no ->
+ %% This case may demand decoding of fragmented length/value
+ {Len,Bytes2} = decode_length(Buffer,undefined),
+ Bytes3 = align(Bytes2),
+ compact_bit_string(Bytes3,Len,NamedNumberList);
+ Sc ->
+ {Len,Bytes2} = decode_length(Buffer,Sc),
+ Bytes3 = align(Bytes2),
+ compact_bit_string(Bytes3,Len,NamedNumberList)
+ end.
+
+
+%%%%%%%%%%%%%%%
+%% The result is presented as a list of named bits (if possible)
+%% else as a list of 0 and 1.
+%%
+decode_bit_string(Buffer, C, NamedNumberList) ->
+ case get_constraint(C,'SizeConstraint') of
+ {Lb,Ub} when integer(Lb),integer(Ub) ->
+ {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
+ Bytes3 = align(Bytes2),
+ bit_list_or_named(Bytes3,Len,NamedNumberList);
+ no ->
+ {Len,Bytes2} = decode_length(Buffer,undefined),
+ Bytes3 = align(Bytes2),
+ bit_list_or_named(Bytes3,Len,NamedNumberList);
+ 0 -> % fixed length
+ {[],Buffer}; % nothing to encode
+ V when integer(V),V=<16 -> % fixed length 16 bits or less
+ bit_list_or_named(Buffer,V,NamedNumberList);
+ V when integer(V),V=<65536 ->
+ Bytes2 = align(Buffer),
+ bit_list_or_named(Bytes2,V,NamedNumberList);
+ V when integer(V) ->
+ Bytes2 = align(Buffer),
+ {BinBits,_Bytes3} = decode_fragmented_bits(Bytes2,V),
+ bit_list_or_named(BinBits,V,NamedNumberList);
+ Sc -> % extension marker
+ {Len,Bytes2} = decode_length(Buffer,Sc),
+ Bytes3 = align(Bytes2),
+ bit_list_or_named(Bytes3,Len,NamedNumberList)
+ end.
+
+
+%% if no named bits are declared we will return a
+%% {Unused,Bits}. Unused = integer(),
+%% Bits = binary().
+compact_bit_string(Buffer,Len,[]) ->
+ getbits_as_binary(Len,Buffer); % {{Unused,BinBits},NewBuffer}
+compact_bit_string(Buffer,Len,NamedNumberList) ->
+ bit_list_or_named(Buffer,Len,NamedNumberList).
+
+
+%% if no named bits are declared we will return a
+%% BitList = [0 | 1]
+
+bit_list_or_named(Buffer,Len,[]) ->
+ getbits_as_list(Len,Buffer);
+
+%% if there are named bits declared we will return a named
+%% BitList where the names are atoms and unnamed bits represented
+%% as {bit,Pos}
+%% BitList = [atom() | {bit,Pos}]
+%% Pos = integer()
+
+bit_list_or_named(Buffer,Len,NamedNumberList) ->
+ {BitList,Rest} = getbits_as_list(Len,Buffer),
+ {bit_list_or_named1(0,BitList,NamedNumberList,[]), Rest}.
+
+bit_list_or_named1(Pos,[0|Bt],Names,Acc) ->
+ bit_list_or_named1(Pos+1,Bt,Names,Acc);
+bit_list_or_named1(Pos,[1|Bt],Names,Acc) ->
+ case lists:keysearch(Pos,2,Names) of
+ {value,{Name,_}} ->
+ bit_list_or_named1(Pos+1,Bt,Names,[Name|Acc]);
+ _ ->
+ bit_list_or_named1(Pos+1,Bt,Names,[{bit,Pos}|Acc])
+ end;
+bit_list_or_named1(_Pos,[],_Names,Acc) ->
+ lists:reverse(Acc).
+
+
+
+%%%%%%%%%%%%%%%
+%%
+
+int_to_bitlist(Int) when integer(Int), Int > 0 ->
+ [Int band 1 | int_to_bitlist(Int bsr 1)];
+int_to_bitlist(0) ->
+ [].
+
+
+%%%%%%%%%%%%%%%%%%
+%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
+%% [sorted_list_of_bitpositions_to_set]
+
+get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
+ get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
+
+get_all_bitposes([Val | Rest], NamedBitList, Ack) ->
+ case lists:keysearch(Val, 1, NamedBitList) of
+ {value, {_ValName, ValPos}} ->
+ get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
+ _ ->
+ exit({error,{asn1, {bitstring_namedbit, Val}}})
+ end;
+get_all_bitposes([], _NamedBitList, Ack) ->
+ lists:sort(Ack).
+
+%%%%%%%%%%%%%%%%%%
+%% make_and_set_list([list of positions to set to 1])->
+%% returns list with all in SetPos set.
+%% in positioning in list the first element is 0, the second 1 etc.., but
+%%
+
+make_and_set_list([XPos|SetPos], XPos) ->
+ [1 | make_and_set_list(SetPos, XPos + 1)];
+make_and_set_list([Pos|SetPos], XPos) ->
+ [0 | make_and_set_list([Pos | SetPos], XPos + 1)];
+make_and_set_list([], _) ->
+ [].
+
+%%%%%%%%%%%%%%%%%
+%% pad_list(N,BitList) -> PaddedList
+%% returns a padded (with trailing {bit,0} elements) list of length N
+%% if Bitlist contains more than N significant bits set an exit asn1_error
+%% is generated
+
+% pad_list(N,In={Unused,Bin}) ->
+% pad_list(N, size(Bin)*8 - Unused, In).
+
+% pad_list(N,Size,In={Unused,Bin}) when N < Size ->
+% exit({error,{asn1,{range_error,{bit_string,In}}}});
+% pad_list(N,Size,{Unused,Bin}) when N > Size, Unused > 0 ->
+% pad_list(N,Size+1,{Unused-1,Bin});
+% pad_list(N,Size,{Unused,Bin}) when N > Size ->
+% pad_list(N,Size+1,{7,<<Bin/binary,0>>});
+% pad_list(N,N,In={Unused,Bin}) ->
+% In.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% X.691:16
+%% encode_octet_string(Constraint,ExtensionMarker,Val)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+encode_octet_string(C,Val) ->
+ encode_octet_string(C,false,Val).
+
+encode_octet_string(C,Bool,{_Name,Val}) ->
+ encode_octet_string(C,Bool,Val);
+encode_octet_string(_C,true,_Val) ->
+ exit({error,{asn1,{'not_supported',extensionmarker}}});
+encode_octet_string(SZ={_,_},false,Val) ->
+% [encode_length(SZ,length(Val)),align,
+% {octets,Val}];
+ Len = length(Val),
+ [encode_length(SZ,Len),2,
+ octets_to_complete(Len,Val)];
+encode_octet_string(SZ,false,Val) when list(SZ) ->
+ Len = length(Val),
+ [encode_length({hd(SZ),lists:max(SZ)},Len),2,
+ octets_to_complete(Len,Val)];
+encode_octet_string(no,false,Val) ->
+ Len = length(Val),
+ [encode_length(undefined,Len),2,
+ octets_to_complete(Len,Val)];
+encode_octet_string(C,_,_) ->
+ exit({error,{not_implemented,C}}).
+
+
+decode_octet_string(Bytes,Range) ->
+ decode_octet_string(Bytes,Range,false).
+
+decode_octet_string(Bytes,1,false) ->
+ {B1,Bytes2} = getbits(Bytes,8),
+ {[B1],Bytes2};
+decode_octet_string(Bytes,2,false) ->
+ {Bs,Bytes2}= getbits(Bytes,16),
+ {binary_to_list(<<Bs:16>>),Bytes2};
+decode_octet_string(Bytes,Sv,false) when integer(Sv),Sv=<65535 ->
+ Bytes2 = align(Bytes),
+ getoctets_as_list(Bytes2,Sv);
+decode_octet_string(Bytes,Sv,false) when integer(Sv) ->
+ Bytes2 = align(Bytes),
+ decode_fragmented_octets(Bytes2,Sv);
+decode_octet_string(Bytes,{Lb,Ub},false) ->
+ {Len,Bytes2} = decode_length(Bytes,{Lb,Ub}),
+ Bytes3 = align(Bytes2),
+ getoctets_as_list(Bytes3,Len);
+decode_octet_string(Bytes,Sv,false) when list(Sv) ->
+ {Len,Bytes2} = decode_length(Bytes,{hd(Sv),lists:max(Sv)}),
+ Bytes3 = align(Bytes2),
+ getoctets_as_list(Bytes3,Len);
+decode_octet_string(Bytes,no,false) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ Bytes3 = align(Bytes2),
+ getoctets_as_list(Bytes3,Len).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Restricted char string types
+%% (NumericString, PrintableString,VisibleString,IA5String,BMPString,UniversalString)
+%% X.691:26 and X.680:34-36
+%%encode_restricted_string(aligned,'BMPString',Constraints,Extension,Val)
+
+
+encode_restricted_string(aligned,{Name,Val}) when atom(Name) ->
+ encode_restricted_string(aligned,Val);
+
+encode_restricted_string(aligned,Val) when list(Val)->
+ Len = length(Val),
+% [encode_length(undefined,length(Val)),{octets,Val}].
+ [encode_length(undefined,Len),octets_to_complete(Len,Val)].
+
+
+encode_known_multiplier_string(StringType,SizeC,NumBits,CharOutTab,{Name,Val}) when atom(Name) ->
+ encode_known_multiplier_string(StringType,SizeC,NumBits,CharOutTab,Val);
+encode_known_multiplier_string(StringType,SizeC,NumBits,CharOutTab,Val) ->
+ Result = chars_encode2(Val,NumBits,CharOutTab),
+ case SizeC of
+ Ub when integer(Ub), Ub*NumBits =< 16 ->
+ case {StringType,Result} of
+ {'BMPString',{octets,Ol}} -> %% this case cannot happen !!??
+ [{bits,8,Oct}||Oct <- Ol];
+ _ ->
+ Result
+ end;
+ Ub when integer(Ub),Ub =<65535 -> % fixed length
+%% [align,Result];
+ [2,Result];
+ {Ub,Lb} ->
+% [encode_length({Ub,Lb},length(Val)),align,Result];
+ [encode_length({Ub,Lb},length(Val)),2,Result];
+ no ->
+% [encode_length(undefined,length(Val)),align,Result]
+ [encode_length(undefined,length(Val)),2,Result]
+ end.
+
+decode_restricted_string(Bytes,aligned) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ getoctets_as_list(Bytes2,Len).
+
+decode_known_multiplier_string(StringType,SizeC,NumBits,CharInTab,Bytes) ->
+ case SizeC of
+ Ub when integer(Ub), Ub*NumBits =< 16 ->
+ chars_decode(Bytes,NumBits,StringType,CharInTab,Ub);
+ Ub when integer(Ub),Ub =<65535 -> % fixed length
+ Bytes1 = align(Bytes),
+ chars_decode(Bytes1,NumBits,StringType,CharInTab,Ub);
+ Vl when list(Vl) ->
+ {Len,Bytes1} = decode_length(Bytes,{hd(Vl),lists:max(Vl)}),
+ Bytes2 = align(Bytes1),
+ chars_decode(Bytes2,NumBits,StringType,CharInTab,Len);
+ no ->
+ {Len,Bytes1} = decode_length(Bytes,undefined),
+ Bytes2 = align(Bytes1),
+ chars_decode(Bytes2,NumBits,StringType,CharInTab,Len);
+ {Lb,Ub}->
+ {Len,Bytes1} = decode_length(Bytes,{Lb,Ub}),
+ Bytes2 = align(Bytes1),
+ chars_decode(Bytes2,NumBits,StringType,CharInTab,Len)
+ end.
+
+encode_GeneralString(_C,Val) ->
+ encode_restricted_string(aligned,Val).
+decode_GeneralString(Bytes,_C) ->
+ decode_restricted_string(Bytes,aligned).
+
+encode_GraphicString(_C,Val) ->
+ encode_restricted_string(aligned,Val).
+decode_GraphicString(Bytes,_C) ->
+ decode_restricted_string(Bytes,aligned).
+
+encode_ObjectDescriptor(_C,Val) ->
+ encode_restricted_string(aligned,Val).
+decode_ObjectDescriptor(Bytes) ->
+ decode_restricted_string(Bytes,aligned).
+
+encode_TeletexString(_C,Val) -> % equivalent with T61String
+ encode_restricted_string(aligned,Val).
+decode_TeletexString(Bytes,_C) ->
+ decode_restricted_string(Bytes,aligned).
+
+encode_VideotexString(_C,Val) ->
+ encode_restricted_string(aligned,Val).
+decode_VideotexString(Bytes,_C) ->
+ decode_restricted_string(Bytes,aligned).
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% getBMPChars(Bytes,Len) ->{BMPcharList,RemainingBytes}
+%%
+getBMPChars(Bytes,1) ->
+ {O1,Bytes2} = getbits(Bytes,8),
+ {O2,Bytes3} = getbits(Bytes2,8),
+ if
+ O1 == 0 ->
+ {[O2],Bytes3};
+ true ->
+ {[{0,0,O1,O2}],Bytes3}
+ end;
+getBMPChars(Bytes,Len) ->
+ getBMPChars(Bytes,Len,[]).
+
+getBMPChars(Bytes,0,Acc) ->
+ {lists:reverse(Acc),Bytes};
+getBMPChars(Bytes,Len,Acc) ->
+ {Octs,Bytes1} = getoctets_as_list(Bytes,2),
+ case Octs of
+ [0,O2] ->
+ getBMPChars(Bytes1,Len-1,[O2|Acc]);
+ [O1,O2]->
+ getBMPChars(Bytes1,Len-1,[{0,0,O1,O2}|Acc])
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% chars_encode(C,StringType,Value) -> ValueList
+%%
+%% encodes chars according to the per rules taking the constraint PermittedAlphabet
+%% into account.
+%% This function does only encode the value part and NOT the length
+
+% chars_encode(C,StringType,Value) ->
+% case {StringType,get_constraint(C,'PermittedAlphabet')} of
+% {'UniversalString',{_,Sv}} ->
+% exit({error,{asn1,{'not implemented',"UniversalString with PermittedAlphabet constraint"}}});
+% {'BMPString',{_,Sv}} ->
+% exit({error,{asn1,{'not implemented',"BMPString with PermittedAlphabet constraint"}}});
+% _ ->
+% {NumBits,CharOutTab} = {get_NumBits(C,StringType),get_CharOutTab(C,StringType)},
+% chars_encode2(Value,NumBits,CharOutTab)
+% end.
+
+
+chars_encode2([H|T],NumBits,T1={Min,Max,notab}) when H =< Max, H >= Min ->
+% [[10,NumBits,H-Min]|chars_encode2(T,NumBits,T1)];
+ [pre_complete_bits(NumBits,H-Min)|chars_encode2(T,NumBits,T1)];
+chars_encode2([H|T],NumBits,T1={Min,Max,Tab}) when H =< Max, H >= Min ->
+% [[10,NumBits,element(H-Min+1,Tab)]|chars_encode2(T,NumBits,T1)];
+ [pre_complete_bits(NumBits,exit_if_false(H,element(H-Min+1,Tab)))|
+ chars_encode2(T,NumBits,T1)];
+chars_encode2([{A,B,C,D}|T],NumBits,T1={Min,_Max,notab}) ->
+ %% no value range check here (ought to be, but very expensive)
+% [{bits,NumBits,(A*B*C*D)-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
+% [[10,NumBits,((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min]|chars_encode2(T,NumBits,T1)];
+ [pre_complete_bits(NumBits,
+ ((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min)|
+ chars_encode2(T,NumBits,T1)];
+chars_encode2([H={A,B,C,D}|T],NumBits,{Min,Max,Tab}) ->
+ %% no value range check here (ought to be, but very expensive)
+ [pre_complete_bits(NumBits,exit_if_false(H,element(((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min,Tab)))|chars_encode2(T,NumBits,{Min,Max,notab})];
+chars_encode2([H|_T],_NumBits,{_Min,_Max,_Tab}) ->
+ exit({error,{asn1,{illegal_char_value,H}}});
+chars_encode2([],_,_) ->
+ [].
+
+exit_if_false(V,false)->
+ exit({error,{asn1,{"illegal value according to Permitted alphabet constraint",V}}});
+exit_if_false(_,V) ->V.
+
+pre_complete_bits(NumBits,Val) when NumBits =< 8 ->
+ [10,NumBits,Val];
+pre_complete_bits(NumBits,Val) when NumBits =< 16 ->
+ [10,NumBits-8,Val bsr 8,10,8,(Val band 255)];
+pre_complete_bits(NumBits,Val) when NumBits =< 2040 -> % 255 * 8
+% LBUsed = NumBits rem 8,
+% {Unused,Len} = case (8 - LBUsed) of
+% 8 -> {0,NumBits div 8};
+% U -> {U,(NumBits div 8) + 1}
+% end,
+% NewVal = Val bsr LBUsed,
+% [30,Unused,Len,<<NewVal:Len/unit:8,Val:LBUsed,0:Unused>>].
+ Unused = (8 - (NumBits rem 8)) rem 8,
+ Len = NumBits + Unused,
+ [30,Unused,Len div 8,<<(Val bsl Unused):Len>>].
+
+% get_NumBits(C,StringType) ->
+% case get_constraint(C,'PermittedAlphabet') of
+% {'SingleValue',Sv} ->
+% charbits(length(Sv),aligned);
+% no ->
+% case StringType of
+% 'IA5String' ->
+% charbits(128,aligned); % 16#00..16#7F
+% 'VisibleString' ->
+% charbits(95,aligned); % 16#20..16#7E
+% 'PrintableString' ->
+% charbits(74,aligned); % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
+% 'NumericString' ->
+% charbits(11,aligned); % $ ,"0123456789"
+% 'UniversalString' ->
+% 32;
+% 'BMPString' ->
+% 16
+% end
+% end.
+
+%%Maybe used later
+%%get_MaxChar(C,StringType) ->
+%% case get_constraint(C,'PermittedAlphabet') of
+%% {'SingleValue',Sv} ->
+%% lists:nth(length(Sv),Sv);
+%% no ->
+%% case StringType of
+%% 'IA5String' ->
+%% 16#7F; % 16#00..16#7F
+%% 'VisibleString' ->
+%% 16#7E; % 16#20..16#7E
+%% 'PrintableString' ->
+%% $z; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
+%% 'NumericString' ->
+%% $9; % $ ,"0123456789"
+%% 'UniversalString' ->
+%% 16#ffffffff;
+%% 'BMPString' ->
+%% 16#ffff
+%% end
+%% end.
+
+%%Maybe used later
+%%get_MinChar(C,StringType) ->
+%% case get_constraint(C,'PermittedAlphabet') of
+%% {'SingleValue',Sv} ->
+%% hd(Sv);
+%% no ->
+%% case StringType of
+%% 'IA5String' ->
+%% 16#00; % 16#00..16#7F
+%% 'VisibleString' ->
+%% 16#20; % 16#20..16#7E
+%% 'PrintableString' ->
+%% $\s; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
+%% 'NumericString' ->
+%% $\s; % $ ,"0123456789"
+%% 'UniversalString' ->
+%% 16#00;
+%% 'BMPString' ->
+%% 16#00
+%% end
+%% end.
+
+% get_CharOutTab(C,StringType) ->
+% get_CharTab(C,StringType,out).
+
+% get_CharInTab(C,StringType) ->
+% get_CharTab(C,StringType,in).
+
+% get_CharTab(C,StringType,InOut) ->
+% case get_constraint(C,'PermittedAlphabet') of
+% {'SingleValue',Sv} ->
+% get_CharTab2(C,StringType,hd(Sv),lists:max(Sv),Sv,InOut);
+% no ->
+% case StringType of
+% 'IA5String' ->
+% {0,16#7F,notab};
+% 'VisibleString' ->
+% get_CharTab2(C,StringType,16#20,16#7F,notab,InOut);
+% 'PrintableString' ->
+% Chars = lists:sort(
+% " '()+,-./0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
+% get_CharTab2(C,StringType,hd(Chars),lists:max(Chars),Chars,InOut);
+% 'NumericString' ->
+% get_CharTab2(C,StringType,16#20,$9," 0123456789",InOut);
+% 'UniversalString' ->
+% {0,16#FFFFFFFF,notab};
+% 'BMPString' ->
+% {0,16#FFFF,notab}
+% end
+% end.
+
+% get_CharTab2(C,StringType,Min,Max,Chars,InOut) ->
+% BitValMax = (1 bsl get_NumBits(C,StringType))-1,
+% if
+% Max =< BitValMax ->
+% {0,Max,notab};
+% true ->
+% case InOut of
+% out ->
+% {Min,Max,create_char_tab(Min,Chars)};
+% in ->
+% {Min,Max,list_to_tuple(Chars)}
+% end
+% end.
+
+% create_char_tab(Min,L) ->
+% list_to_tuple(create_char_tab(Min,L,0)).
+% create_char_tab(Min,[Min|T],V) ->
+% [V|create_char_tab(Min+1,T,V+1)];
+% create_char_tab(_Min,[],_V) ->
+% [];
+% create_char_tab(Min,L,V) ->
+% [false|create_char_tab(Min+1,L,V)].
+
+%% This very inefficient and should be moved to compiletime
+% charbits(NumOfChars,aligned) ->
+% case charbits(NumOfChars) of
+% 1 -> 1;
+% 2 -> 2;
+% B when B =< 4 -> 4;
+% B when B =< 8 -> 8;
+% B when B =< 16 -> 16;
+% B when B =< 32 -> 32
+% end.
+
+% charbits(NumOfChars) when NumOfChars =< 2 -> 1;
+% charbits(NumOfChars) when NumOfChars =< 4 -> 2;
+% charbits(NumOfChars) when NumOfChars =< 8 -> 3;
+% charbits(NumOfChars) when NumOfChars =< 16 -> 4;
+% charbits(NumOfChars) when NumOfChars =< 32 -> 5;
+% charbits(NumOfChars) when NumOfChars =< 64 -> 6;
+% charbits(NumOfChars) when NumOfChars =< 128 -> 7;
+% charbits(NumOfChars) when NumOfChars =< 256 -> 8;
+% charbits(NumOfChars) when NumOfChars =< 512 -> 9;
+% charbits(NumOfChars) when NumOfChars =< 1024 -> 10;
+% charbits(NumOfChars) when NumOfChars =< 2048 -> 11;
+% charbits(NumOfChars) when NumOfChars =< 4096 -> 12;
+% charbits(NumOfChars) when NumOfChars =< 8192 -> 13;
+% charbits(NumOfChars) when NumOfChars =< 16384 -> 14;
+% charbits(NumOfChars) when NumOfChars =< 32768 -> 15;
+% charbits(NumOfChars) when NumOfChars =< 65536 -> 16;
+% charbits(NumOfChars) when integer(NumOfChars) ->
+% 16 + charbits1(NumOfChars bsr 16).
+
+% charbits1(0) ->
+% 0;
+% charbits1(NumOfChars) ->
+% 1 + charbits1(NumOfChars bsr 1).
+
+
+chars_decode(Bytes,_,'BMPString',_,Len) ->
+ getBMPChars(Bytes,Len);
+chars_decode(Bytes,NumBits,_StringType,CharInTab,Len) ->
+ chars_decode2(Bytes,CharInTab,NumBits,Len).
+
+
+chars_decode2(Bytes,CharInTab,NumBits,Len) ->
+ chars_decode2(Bytes,CharInTab,NumBits,Len,[]).
+
+chars_decode2(Bytes,_CharInTab,_NumBits,0,Acc) ->
+ {lists:reverse(Acc),Bytes};
+chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) when NumBits > 8 ->
+ {Char,Bytes2} = getbits(Bytes,NumBits),
+ Result =
+ if
+ Char < 256 -> Char;
+ true ->
+ list_to_tuple(binary_to_list(<<Char:32>>))
+ end,
+ chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Result|Acc]);
+chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) ->
+ {Char,Bytes2} = getbits(Bytes,NumBits),
+ chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Char+Min|Acc]);
+
+%% BMPString and UniversalString with PermittedAlphabet is currently not supported
+chars_decode2(Bytes,{Min,Max,CharInTab},NumBits,Len,Acc) ->
+ {Char,Bytes2} = getbits(Bytes,NumBits),
+ chars_decode2(Bytes2,{Min,Max,CharInTab},NumBits,Len -1,[element(Char+1,CharInTab)|Acc]).
+
+
+ % X.691:17
+encode_null(_Val) -> []; % encodes to nothing
+encode_null({Name,Val}) when atom(Name) ->
+ encode_null(Val).
+
+decode_null(Bytes) ->
+ {'NULL',Bytes}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_object_identifier(Val) -> CompleteList
+%% encode_object_identifier({Name,Val}) -> CompleteList
+%% Val -> {Int1,Int2,...,IntN} % N >= 2
+%% Name -> atom()
+%% Int1 -> integer(0..2)
+%% Int2 -> integer(0..39) when Int1 (0..1) else integer()
+%% Int3-N -> integer()
+%% CompleteList -> [{bits,8,Val}|{octets,Ol}|align|...]
+%%
+encode_object_identifier({Name,Val}) when atom(Name) ->
+ encode_object_identifier(Val);
+encode_object_identifier(Val) ->
+ OctetList = e_object_identifier(Val),
+ Octets = list_to_binary(OctetList), % performs a flatten at the same time
+% [{debug,object_identifier},encode_length(undefined,size(Octets)),{octets,Octets}].
+ [encode_length(undefined,size(Octets)),
+ octets_to_complete(size(Octets),Octets)].
+
+%% This code is copied from asn1_encode.erl (BER) and corrected and modified
+
+e_object_identifier({'OBJECT IDENTIFIER',V}) ->
+ e_object_identifier(V);
+e_object_identifier({Cname,V}) when atom(Cname),tuple(V) ->
+ e_object_identifier(tuple_to_list(V));
+e_object_identifier({Cname,V}) when atom(Cname),list(V) ->
+ e_object_identifier(V);
+e_object_identifier(V) when tuple(V) ->
+ e_object_identifier(tuple_to_list(V));
+
+%% E1 = 0|1|2 and (E2 < 40 when E1 = 0|1)
+e_object_identifier([E1,E2|Tail]) when E1 >= 0, E1 < 2, E2 < 40 ; E1==2 ->
+ Head = 40*E1 + E2, % weird
+ e_object_elements([Head|Tail],[]);
+e_object_identifier(Oid=[_,_|_Tail]) ->
+ exit({error,{asn1,{'illegal_value',Oid}}}).
+
+e_object_elements([],Acc) ->
+ lists:reverse(Acc);
+e_object_elements([H|T],Acc) ->
+ e_object_elements(T,[e_object_element(H)|Acc]).
+
+e_object_element(Num) when Num < 128 ->
+ Num;
+%% must be changed to handle more than 2 octets
+e_object_element(Num) -> %% when Num < ???
+ Left = ((Num band 2#11111110000000) bsr 7) bor 2#10000000,
+ Right = Num band 2#1111111 ,
+ [Left,Right].
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% decode_object_identifier(Bytes) -> {ObjId,RemainingBytes}
+%% ObjId -> {integer(),integer(),...} % at least 2 integers
+%% RemainingBytes -> [integer()] when integer() (0..255)
+decode_object_identifier(Bytes) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
+ [First|Rest] = dec_subidentifiers(Octs,0,[]),
+ Idlist = if
+ First < 40 ->
+ [0,First|Rest];
+ First < 80 ->
+ [1,First - 40|Rest];
+ true ->
+ [2,First - 80|Rest]
+ end,
+ {list_to_tuple(Idlist),Bytes3}.
+
+dec_subidentifiers([H|T],Av,Al) when H >=16#80 ->
+ dec_subidentifiers(T,(Av bsl 7) + (H band 16#7F),Al);
+dec_subidentifiers([H|T],Av,Al) ->
+ dec_subidentifiers(T,0,[(Av bsl 7) + H |Al]);
+dec_subidentifiers([],_Av,Al) ->
+ lists:reverse(Al).
+
+get_constraint([{Key,V}],Key) ->
+ V;
+get_constraint([],_) ->
+ no;
+get_constraint(C,Key) ->
+ case lists:keysearch(Key,1,C) of
+ false ->
+ no;
+ {value,{_,V}} ->
+ V
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% complete(InList) -> ByteList
+%% Takes a coded list with bits and bytes and converts it to a list of bytes
+%% Should be applied as the last step at encode of a complete ASN.1 type
+%%
+
+-ifdef(nodriver).
+
+complete(L) ->
+ case complete1(L) of
+ {[],[]} ->
+ <<0>>;
+ {Acc,[]} ->
+ Acc;
+ {Acc,Bacc} ->
+ [Acc|complete_bytes(Bacc)]
+ end.
+
+
+% this function builds the ugly form of lists [E1|E2] to avoid having to reverse it at the end.
+% this is done because it is efficient and that the result always will be sent on a port or
+% converted by means of list_to_binary/1
+ complete1(InList) when list(InList) ->
+ complete1(InList,[],[]);
+ complete1(InList) ->
+ complete1([InList],[],[]).
+
+ complete1([],Acc,Bacc) ->
+ {Acc,Bacc};
+ complete1([H|T],Acc,Bacc) when list(H) ->
+ {NewH,NewBacc} = complete1(H,Acc,Bacc),
+ complete1(T,NewH,NewBacc);
+
+ complete1([{octets,Bin}|T],Acc,[]) ->
+ complete1(T,[Acc|Bin],[]);
+
+ complete1([{octets,Bin}|T],Acc,Bacc) ->
+ complete1(T,[Acc|[complete_bytes(Bacc),Bin]],[]);
+
+ complete1([{debug,_}|T], Acc,Bacc) ->
+ complete1(T,Acc,Bacc);
+
+ complete1([{bits,N,Val}|T],Acc,Bacc) ->
+ complete1(T,Acc,complete_update_byte(Bacc,Val,N));
+
+ complete1([{bit,Val}|T],Acc,Bacc) ->
+ complete1(T,Acc,complete_update_byte(Bacc,Val,1));
+
+ complete1([align|T],Acc,[]) ->
+ complete1(T,Acc,[]);
+ complete1([align|T],Acc,Bacc) ->
+ complete1(T,[Acc|complete_bytes(Bacc)],[]);
+ complete1([{0,Bin}|T],Acc,[]) when binary(Bin) ->
+ complete1(T,[Acc|Bin],[]);
+ complete1([{Unused,Bin}|T],Acc,[]) when integer(Unused),binary(Bin) ->
+ Size = size(Bin)-1,
+ <<Bs:Size/binary,B>> = Bin,
+ NumBits = 8-Unused,
+ complete1(T,[Acc|Bs],[[B bsr Unused]|NumBits]);
+ complete1([{Unused,Bin}|T],Acc,Bacc) when integer(Unused),binary(Bin) ->
+ Size = size(Bin)-1,
+ <<Bs:Size/binary,B>> = Bin,
+ NumBits = 8 - Unused,
+ Bf = complete_bytes(Bacc),
+ complete1(T,[Acc|[Bf,Bs]],[[B bsr Unused]|NumBits]).
+
+
+ complete_update_byte([],Val,Len) ->
+ complete_update_byte([[0]|0],Val,Len);
+ complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) when NumBits + Len == 8 ->
+ [[0,((Byte bsl Len) + Val) band 255|Bacc]|0];
+ complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) when NumBits + Len > 8 ->
+ Rem = 8 - NumBits,
+ Rest = Len - Rem,
+ complete_update_byte([[0,((Byte bsl Rem) + (Val bsr Rest)) band 255 |Bacc]|0],Val,Rest);
+ complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) ->
+ [[((Byte bsl Len) + Val) band 255|Bacc]|NumBits+Len].
+
+
+ complete_bytes([[Byte|Bacc]|0]) ->
+ lists:reverse(Bacc);
+ complete_bytes([[Byte|Bacc]|NumBytes]) ->
+ lists:reverse([(Byte bsl (8-NumBytes)) band 255|Bacc]);
+ complete_bytes([]) ->
+ [].
+
+-else.
+
+
+ complete(L) ->
+ case catch port_control(drv_complete,1,L) of
+ Bin when binary(Bin) ->
+ Bin;
+ List when list(List) -> handle_error(List,L);
+ {'EXIT',{badarg,Reason}} ->
+ asn1rt_driver_handler:load_driver(),
+ receive
+ driver_ready ->
+ case catch port_control(drv_complete,1,L) of
+ Bin2 when binary(Bin2) -> Bin2;
+ List when list(List) -> handle_error(List,L);
+ Error -> exit(Error)
+ end;
+ {error,Error} -> % error when loading driver
+ %% the driver could not be loaded
+ exit(Error);
+ Error={port_error,Reason} ->
+ exit(Error)
+ end;
+ {'EXIT',Reason} ->
+ exit(Reason)
+ end.
+
+handle_error([],_)->
+ exit({error,{"memory allocation problem"}});
+handle_error("1",L) -> % error in complete in driver
+ exit({error,{asn1_error,L}});
+handle_error(ErrL,L) ->
+ exit({error,{unknown_error,ErrL,L}}).
+
+-endif.
+
+
+octets_to_complete(Len,Val) when Len < 256 ->
+ [20,Len,Val];
+octets_to_complete(Len,Val) ->
+ [21,<<Len:16>>,Val].
+
+octets_unused_to_complete(Unused,Len,Val) when Len < 256 ->
+ [30,Unused,Len,Val];
+octets_unused_to_complete(Unused,Len,Val) ->
+ [31,Unused,<<Len:16>>,Val].
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per_v1.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per_v1.erl
new file mode 100644
index 0000000000..90ffb0cb1c
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per_v1.erl
@@ -0,0 +1,1827 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: asn1rt_per_v1.erl,v 1.1 2008/12/17 09:53:31 mikpe Exp $
+%%
+-module(asn1rt_per_v1).
+
+%% encoding / decoding of PER aligned
+
+-include("asn1_records.hrl").
+
+-export([dec_fixup/3, cindex/3, list_to_record/2]).
+-export([setchoiceext/1, setext/1, fixoptionals/2, fixextensions/2,
+ setoptionals/1, fixoptionals2/3, getext/1, getextension/2,
+ skipextensions/3, getbit/1, getchoice/3 ]).
+-export([getoptionals/2, getoptionals/3, set_choice/3,
+ getoptionals2/2,
+ encode_integer/2, encode_integer/3 ]).
+-export([decode_integer/2, decode_integer/3, encode_small_number/1,
+ encode_boolean/1, decode_boolean/1, encode_length/2,
+ decode_length/1, decode_length/2,
+ encode_small_length/1, decode_small_length/1,
+ decode_compact_bit_string/3]).
+-export([encode_enumerated/3, decode_enumerated/3,
+ encode_bit_string/3, decode_bit_string/3 ]).
+-export([encode_octet_string/2, decode_octet_string/2,
+ encode_null/1, decode_null/1,
+ encode_object_identifier/1, decode_object_identifier/1,
+ complete/1]).
+
+-export([encode_open_type/2, decode_open_type/2]).
+
+-export([encode_UniversalString/2, decode_UniversalString/2,
+ encode_PrintableString/2, decode_PrintableString/2,
+ encode_GeneralString/2, decode_GeneralString/2,
+ encode_GraphicString/2, decode_GraphicString/2,
+ encode_TeletexString/2, decode_TeletexString/2,
+ encode_VideotexString/2, decode_VideotexString/2,
+ encode_VisibleString/2, decode_VisibleString/2,
+ encode_BMPString/2, decode_BMPString/2,
+ encode_IA5String/2, decode_IA5String/2,
+ encode_NumericString/2, decode_NumericString/2,
+ encode_ObjectDescriptor/2, decode_ObjectDescriptor/1
+ ]).
+
+
+dec_fixup(Terms,Cnames,RemBytes) ->
+ dec_fixup(Terms,Cnames,RemBytes,[]).
+
+dec_fixup([novalue|T],[_Hc|Tc],RemBytes,Acc) ->
+ dec_fixup(T,Tc,RemBytes,Acc);
+dec_fixup([{_Name,novalue}|T],[_Hc|Tc],RemBytes,Acc) ->
+ dec_fixup(T,Tc,RemBytes,Acc);
+dec_fixup([H|T],[Hc|Tc],RemBytes,Acc) ->
+ dec_fixup(T,Tc,RemBytes,[{Hc,H}|Acc]);
+dec_fixup([],_Cnames,RemBytes,Acc) ->
+ {lists:reverse(Acc),RemBytes}.
+
+cindex(Ix,Val,Cname) ->
+ case element(Ix,Val) of
+ {Cname,Val2} -> Val2;
+ X -> X
+ end.
+
+% converts a list to a record if necessary
+list_to_record(Name,List) when list(List) ->
+ list_to_tuple([Name|List]);
+list_to_record(_Name,Tuple) when tuple(Tuple) ->
+ Tuple.
+
+%%--------------------------------------------------------
+%% setchoiceext(InRootSet) -> [{bit,X}]
+%% X is set to 1 when InRootSet==false
+%% X is set to 0 when InRootSet==true
+%%
+setchoiceext(true) ->
+ [{debug,choiceext},{bit,0}];
+setchoiceext(false) ->
+ [{debug,choiceext},{bit,1}].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% setext(true|false) -> CompleteList
+%%
+
+setext(true) ->
+ [{debug,ext},{bit,1}];
+setext(false) ->
+ [{debug,ext},{bit,0}].
+
+%%
+
+fixoptionals2(OptList,OptLength,Val) when tuple(Val) ->
+ Bits = fixoptionals2(OptList,Val,0),
+ {Val,{bits,OptLength,Bits}};
+
+fixoptionals2([],_Val,Acc) ->
+ %% Optbits
+ Acc;
+fixoptionals2([Pos|Ot],Val,Acc) ->
+ case element(Pos,Val) of
+ asn1_NOVALUE -> fixoptionals2(Ot,Val,Acc bsl 1);
+ asn1_DEFAULT -> fixoptionals2(Ot,Val,Acc bsl 1);
+ _ -> fixoptionals2(Ot,Val,(Acc bsl 1) + 1)
+ end.
+
+
+%%
+%% fixoptionals remains only for backward compatibility purpose
+fixoptionals(OptList,Val) when tuple(Val) ->
+ fixoptionals(OptList,Val,[]);
+
+fixoptionals(OptList,Val) when list(Val) ->
+ fixoptionals(OptList,Val,1,[],[]).
+
+fixoptionals([],Val,Acc) ->
+ % return {Val,Opt}
+ {Val,lists:reverse(Acc)};
+fixoptionals([{_,Pos}|Ot],Val,Acc) ->
+ case element(Pos+1,Val) of
+ asn1_NOVALUE -> fixoptionals(Ot,Val,[0|Acc]);
+ asn1_DEFAULT -> fixoptionals(Ot,Val,[0|Acc]);
+ _ -> fixoptionals(Ot,Val,[1|Acc])
+ end.
+
+
+%setoptionals(OptList,Val) ->
+% Vlist = tuple_to_list(Val),
+% setoptionals(OptList,Vlist,1,[]).
+
+fixoptionals([{Name,Pos}|Ot],[{Name,Val}|Vt],_Opt,Acc1,Acc2) ->
+ fixoptionals(Ot,Vt,Pos+1,[1|Acc1],[{Name,Val}|Acc2]);
+fixoptionals([{_Name,Pos}|Ot],V,Pos,Acc1,Acc2) ->
+ fixoptionals(Ot,V,Pos+1,[0|Acc1],[asn1_NOVALUE|Acc2]);
+fixoptionals(O,[Vh|Vt],Pos,Acc1,Acc2) ->
+ fixoptionals(O,Vt,Pos+1,Acc1,[Vh|Acc2]);
+fixoptionals([],[Vh|Vt],Pos,Acc1,Acc2) ->
+ fixoptionals([],Vt,Pos+1,Acc1,[Vh|Acc2]);
+fixoptionals([],[],_,Acc1,Acc2) ->
+ % return {Val,Opt}
+ {list_to_tuple([asn1_RECORDNAME|lists:reverse(Acc2)]),lists:reverse(Acc1)}.
+
+setoptionals([H|T]) ->
+ [{bit,H}|setoptionals(T)];
+setoptionals([]) ->
+ [{debug,optionals}].
+
+getext(Bytes) when tuple(Bytes) ->
+ getbit(Bytes);
+getext(Bytes) when list(Bytes) ->
+ getbit({0,Bytes}).
+
+getextension(0, Bytes) ->
+ {{},Bytes};
+getextension(1, Bytes) ->
+ {Len,Bytes2} = decode_small_length(Bytes),
+ {Blist, Bytes3} = getbits_as_list(Len,Bytes2),
+ {list_to_tuple(Blist),Bytes3}.
+
+fixextensions({ext,ExtPos,ExtNum},Val) ->
+ case fixextensions(ExtPos,ExtNum+ExtPos,Val,0) of
+ 0 -> [];
+ ExtBits ->
+ [encode_small_length(ExtNum),{bits,ExtNum,ExtBits}]
+ end.
+
+fixextensions(Pos,MaxPos,_,Acc) when Pos >= MaxPos ->
+ Acc;
+fixextensions(Pos,ExtPos,Val,Acc) ->
+ Bit = case catch(element(Pos+1,Val)) of
+ asn1_NOVALUE ->
+ 0;
+ asn1_NOEXTVALUE ->
+ 0;
+ {'EXIT',_} ->
+ 0;
+ _ ->
+ 1
+ end,
+ fixextensions(Pos+1,ExtPos,Val,(Acc bsl 1)+Bit).
+
+skipextensions(Bytes,Nr,ExtensionBitPattern) ->
+ case (catch element(Nr,ExtensionBitPattern)) of
+ 1 ->
+ {_,Bytes2} = decode_open_type(Bytes,[]),
+ skipextensions(Bytes2, Nr+1, ExtensionBitPattern);
+ 0 ->
+ skipextensions(Bytes, Nr+1, ExtensionBitPattern);
+ {'EXIT',_} -> % badarg, no more extensions
+ Bytes
+ end.
+
+
+getchoice(Bytes,1,0) -> % only 1 alternative is not encoded
+ {0,Bytes};
+getchoice(Bytes,_NumChoices,1) ->
+ decode_small_number(Bytes);
+getchoice(Bytes,NumChoices,0) ->
+ decode_integer(Bytes,[{'ValueRange',{0,NumChoices-1}}]).
+
+getoptionals2(Bytes,NumOpt) ->
+ getbits(Bytes,NumOpt).
+
+%% getoptionals is kept only for bakwards compatibility
+getoptionals(Bytes,NumOpt) ->
+ {Blist,Bytes1} = getbits_as_list(NumOpt,Bytes),
+ {list_to_tuple(Blist),Bytes1}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% getoptionals/3 is only here for compatibility from 1.3.2
+%% the codegenerator uses getoptionals/2
+
+getoptionals(Bytes,L,NumComp) when list(L) ->
+ {Blist,Bytes1} = getbits_as_list(length(L),Bytes),
+ {list_to_tuple(comptuple(Blist,L,NumComp,1)),Bytes1}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% comptuple is only here for compatibility not used from 1.3.2
+comptuple([Bh|Bt],[{_Name,Nr}|T],NumComp,Nr) ->
+ [Bh|comptuple(Bt,T,NumComp-1,Nr+1)];
+comptuple(Bl,[{Name,Tnr}|Tl],NumComp,Nr) ->
+ [0|comptuple(Bl,[{Name,Tnr}|Tl],NumComp-1,Nr+1)];
+comptuple(_B,_L,0,_Nr) ->
+ [];
+comptuple(B,O,N,Nr) ->
+ [0|comptuple(B,O,N-1,Nr+1)].
+
+%% getbits_as_binary(Num,Bytes) -> {{Unused,BinBits},RestBytes},
+%% Num = integer(),
+%% Bytes = list() | tuple(),
+%% Unused = integer(),
+%% BinBits = binary(),
+%% RestBytes = tuple()
+getbits_as_binary(Num,Bytes) when list(Bytes) ->
+ getbits_as_binary(Num,{0,Bytes});
+getbits_as_binary(_Num,{Used,[]}) ->
+ {{0,<<>>},{Used,[]}};
+getbits_as_binary(Num,{Used,Bits=[H|T]}) ->
+ B1 = case (Num+Used) =< 8 of
+ true -> Num;
+ _ -> 8-Used
+ end,
+ B2 = Num - B1,
+ Pad = (8 - ((B1+B2) rem 8)) rem 8,% Pad /= 8
+ RestBits = lists:nthtail((B1+B2) div 8,Bits),
+ Int = integer_from_list(B2,T,0),
+ NewUsed = (Used + Num) rem 8,
+ {{Pad,<<(H bsr (8-(Used+B1))):B1,Int:B2,0:Pad>>},{NewUsed,RestBits}}.
+
+integer_from_list(_Int,[],BigInt) ->
+ BigInt;
+integer_from_list(Int,[H|_T],BigInt) when Int < 8 ->
+ (BigInt bsl Int) bor (H bsr (8-Int));
+integer_from_list(Int,[H|T],BigInt) ->
+ integer_from_list(Int-8,T,(BigInt bsl 8) bor H).
+
+getbits_as_list(Num,Bytes) ->
+ getbits_as_list(Num,Bytes,[]).
+
+getbits_as_list(0,Bytes,Acc) ->
+ {lists:reverse(Acc),Bytes};
+getbits_as_list(Num,Bytes,Acc) ->
+ {Bit,NewBytes} = getbit(Bytes),
+ getbits_as_list(Num-1,NewBytes,[Bit|Acc]).
+
+getbit(Bytes) ->
+% io:format("getbit:~p~n",[Bytes]),
+ getbit1(Bytes).
+
+getbit1({7,[H|T]}) ->
+ {H band 1,{0,T}};
+getbit1({Pos,[H|T]}) ->
+ {(H bsr (7-Pos)) band 1,{(Pos+1) rem 8,[H|T]}};
+getbit1(Bytes) when list(Bytes) ->
+ getbit1({0,Bytes}).
+
+%% This could be optimized
+getbits(Buffer,Num) ->
+% io:format("getbits:Buffer = ~p~nNum=~p~n",[Buffer,Num]),
+ getbits(Buffer,Num,0).
+
+getbits(Buffer,0,Acc) ->
+ {Acc,Buffer};
+getbits(Buffer,Num,Acc) ->
+ {B,NewBuffer} = getbit(Buffer),
+ getbits(NewBuffer,Num-1,B + (Acc bsl 1)).
+
+
+getoctet(Bytes) when list(Bytes) ->
+ getoctet({0,Bytes});
+getoctet(Bytes) ->
+% io:format("getoctet:Buffer = ~p~n",[Bytes]),
+ getoctet1(Bytes).
+
+getoctet1({0,[H|T]}) ->
+ {H,{0,T}};
+getoctet1({_Pos,[_,H|T]}) ->
+ {H,{0,T}}.
+
+align({0,L}) ->
+ {0,L};
+align({_Pos,[_H|T]}) ->
+ {0,T};
+align(Bytes) ->
+ {0,Bytes}.
+
+getoctets(Buffer,Num) ->
+% io:format("getoctets:Buffer = ~p~nNum = ~p~n",[Buffer,Num]),
+ getoctets(Buffer,Num,0).
+
+getoctets(Buffer,0,Acc) ->
+ {Acc,Buffer};
+getoctets(Buffer,Num,Acc) ->
+ {Oct,NewBuffer} = getoctet(Buffer),
+ getoctets(NewBuffer,Num-1,(Acc bsl 8)+Oct).
+
+getoctets_as_list(Buffer,Num) ->
+ getoctets_as_list(Buffer,Num,[]).
+
+getoctets_as_list(Buffer,0,Acc) ->
+ {lists:reverse(Acc),Buffer};
+getoctets_as_list(Buffer,Num,Acc) ->
+ {Oct,NewBuffer} = getoctet(Buffer),
+ getoctets_as_list(NewBuffer,Num-1,[Oct|Acc]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% set_choice(Alt,Choices,Altnum) -> ListofBitSettings
+%% Alt = atom()
+%% Altnum = integer() | {integer(),integer()}% number of alternatives
+%% Choices = [atom()] | {[atom()],[atom()]}
+%% When Choices is a tuple the first list is the Rootset and the
+%% second is the Extensions and then Altnum must also be a tuple with the
+%% lengths of the 2 lists
+%%
+set_choice(Alt,{L1,L2},{Len1,_Len2}) ->
+ case set_choice_tag(Alt,L1) of
+ N when integer(N), Len1 > 1 ->
+ [{bit,0}, % the value is in the root set
+ encode_integer([{'ValueRange',{0,Len1-1}}],N)];
+ N when integer(N) ->
+ [{bit,0}]; % no encoding if only 0 or 1 alternative
+ false ->
+ [{bit,1}, % extension value
+ case set_choice_tag(Alt,L2) of
+ N2 when integer(N2) ->
+ encode_small_number(N2);
+ false ->
+ unknown_choice_alt
+ end]
+ end;
+set_choice(Alt,L,Len) ->
+ case set_choice_tag(Alt,L) of
+ N when integer(N), Len > 1 ->
+ encode_integer([{'ValueRange',{0,Len-1}}],N);
+ N when integer(N) ->
+ []; % no encoding if only 0 or 1 alternative
+ false ->
+ [unknown_choice_alt]
+ end.
+
+set_choice_tag(Alt,Choices) ->
+ set_choice_tag(Alt,Choices,0).
+
+set_choice_tag(Alt,[Alt|_Rest],Tag) ->
+ Tag;
+set_choice_tag(Alt,[_H|Rest],Tag) ->
+ set_choice_tag(Alt,Rest,Tag+1);
+set_choice_tag(_Alt,[],_Tag) ->
+ false.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_open_type(Constraint, Value) -> CompleteList
+%% Value = list of bytes of an already encoded value (the list must be flat)
+%% | binary
+%% Contraint = not used in this version
+%%
+encode_open_type(_Constraint, Val) when list(Val) ->
+ [encode_length(undefined,length(Val)),align,
+ {octets,Val}];
+encode_open_type(_Constraint, Val) when binary(Val) ->
+ [encode_length(undefined,size(Val)),align,
+ {octets,binary_to_list(Val)}].
+%% the binary_to_list is not optimal but compatible with the current solution
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% decode_open_type(Buffer,Constraint) -> Value
+%% Constraint is not used in this version
+%% Buffer = [byte] with PER encoded data
+%% Value = [byte] with decoded data (which must be decoded again as some type)
+%%
+decode_open_type(Bytes, _Constraint) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ Bytes3 = align(Bytes2),
+ getoctets_as_list(Bytes3,Len).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_integer(Constraint,Value,NamedNumberList) -> CompleteList
+%% encode_integer(Constraint,Value) -> CompleteList
+%% encode_integer(Constraint,{Name,Value}) -> CompleteList
+%%
+%%
+encode_integer(C,V,NamedNumberList) when atom(V) ->
+ case lists:keysearch(V,1,NamedNumberList) of
+ {value,{_,NewV}} ->
+ encode_integer(C,NewV);
+ _ ->
+ exit({error,{asn1,{namednumber,V}}})
+ end;
+encode_integer(C,V,_) when integer(V) ->
+ encode_integer(C,V);
+encode_integer(C,{Name,V},NamedNumberList) when atom(Name) ->
+ encode_integer(C,V,NamedNumberList).
+
+encode_integer(C,{Name,Val}) when atom(Name) ->
+ encode_integer(C,Val);
+
+encode_integer({Rc,_Ec},Val) ->
+ case (catch encode_integer(Rc,Val)) of
+ {'EXIT',{error,{asn1,_}}} ->
+ [{bit,1},encode_unconstrained_number(Val)];
+ Encoded ->
+ [{bit,0},Encoded]
+ end;
+encode_integer(C,Val ) when list(C) ->
+ case get_constraint(C,'SingleValue') of
+ no ->
+ encode_integer1(C,Val);
+ V when integer(V),V == Val ->
+ []; % a type restricted to a single value encodes to nothing
+ V when list(V) ->
+ case lists:member(Val,V) of
+ true ->
+ encode_integer1(C,Val);
+ _ ->
+ exit({error,{asn1,{illegal_value,Val}}})
+ end;
+ _ ->
+ exit({error,{asn1,{illegal_value,Val}}})
+ end.
+
+encode_integer1(C, Val) ->
+ case VR = get_constraint(C,'ValueRange') of
+ no ->
+ encode_unconstrained_number(Val);
+ {Lb,'MAX'} ->
+ encode_semi_constrained_number(Lb,Val);
+ %% positive with range
+ {Lb,Ub} when Val >= Lb,
+ Ub >= Val ->
+ encode_constrained_number(VR,Val);
+ _ ->
+ exit({error,{asn1,{illegal_value,VR,Val}}})
+ end.
+
+decode_integer(Buffer,Range,NamedNumberList) ->
+ {Val,Buffer2} = decode_integer(Buffer,Range),
+ case lists:keysearch(Val,2,NamedNumberList) of
+ {value,{NewVal,_}} -> {NewVal,Buffer2};
+ _ -> {Val,Buffer2}
+ end.
+
+decode_integer(Buffer,{Rc,_Ec}) ->
+ {Ext,Buffer2} = getext(Buffer),
+ case Ext of
+ 0 -> decode_integer(Buffer2,Rc);
+ 1 -> decode_unconstrained_number(Buffer2)
+ end;
+decode_integer(Buffer,undefined) ->
+ decode_unconstrained_number(Buffer);
+decode_integer(Buffer,C) ->
+ case get_constraint(C,'SingleValue') of
+ V when integer(V) ->
+ {V,Buffer};
+ V when list(V) ->
+ {Val,Buffer2} = decode_integer1(Buffer,C),
+ case lists:member(Val,V) of
+ true ->
+ {Val,Buffer2};
+ _ ->
+ exit({error,{asn1,{illegal_value,Val}}})
+ end;
+ _ ->
+ decode_integer1(Buffer,C)
+ end.
+
+decode_integer1(Buffer,C) ->
+ case VR = get_constraint(C,'ValueRange') of
+ no ->
+ decode_unconstrained_number(Buffer);
+ {Lb, 'MAX'} ->
+ decode_semi_constrained_number(Buffer,Lb);
+ {_,_} ->
+ decode_constrained_number(Buffer,VR)
+ end.
+
+% X.691:10.6 Encoding of a normally small non-negative whole number
+% Use this for encoding of CHOICE index if there is an extension marker in
+% the CHOICE
+encode_small_number({Name,Val}) when atom(Name) ->
+ encode_small_number(Val);
+encode_small_number(Val) when Val =< 63 ->
+ [{bit,0},{bits,6,Val}];
+encode_small_number(Val) ->
+ [{bit,1},encode_semi_constrained_number(0,Val)].
+
+decode_small_number(Bytes) ->
+ {Bit,Bytes2} = getbit(Bytes),
+ case Bit of
+ 0 ->
+ getbits(Bytes2,6);
+ 1 ->
+ decode_semi_constrained_number(Bytes2,{0,'MAX'})
+ end.
+
+% X.691:10.7 Encoding of a semi-constrained whole number
+%% might be an optimization encode_semi_constrained_number(0,Val) ->
+encode_semi_constrained_number(C,{Name,Val}) when atom(Name) ->
+ encode_semi_constrained_number(C,Val);
+encode_semi_constrained_number({Lb,'MAX'},Val) ->
+ encode_semi_constrained_number(Lb,Val);
+encode_semi_constrained_number(Lb,Val) ->
+ Val2 = Val - Lb,
+ Octs = eint_positive(Val2),
+ [encode_length(undefined,length(Octs)),{octets,Octs}].
+
+decode_semi_constrained_number(Bytes,{Lb,_}) ->
+ decode_semi_constrained_number(Bytes,Lb);
+decode_semi_constrained_number(Bytes,Lb) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ {V,Bytes3} = getoctets(Bytes2,Len),
+ {V+Lb,Bytes3}.
+
+encode_constrained_number(Range,{Name,Val}) when atom(Name) ->
+ encode_constrained_number(Range,Val);
+encode_constrained_number({Lb,Ub},Val) when Val >= Lb, Ub >= Val ->
+ Range = Ub - Lb + 1,
+ Val2 = Val - Lb,
+ if
+ Range == 2 ->
+ {bits,1,Val2};
+ Range =< 4 ->
+ {bits,2,Val2};
+ Range =< 8 ->
+ {bits,3,Val2};
+ Range =< 16 ->
+ {bits,4,Val2};
+ Range =< 32 ->
+ {bits,5,Val2};
+ Range =< 64 ->
+ {bits,6,Val2};
+ Range =< 128 ->
+ {bits,7,Val2};
+ Range =< 255 ->
+ {bits,8,Val2};
+ Range =< 256 ->
+ {octets,1,Val2};
+ Range =< 65536 ->
+ {octets,2,Val2};
+ Range =< 16#1000000 ->
+ Octs = eint_positive(Val2),
+ [encode_length({1,3},length(Octs)),{octets,Octs}];
+ Range =< 16#100000000 ->
+ Octs = eint_positive(Val2),
+ [encode_length({1,4},length(Octs)),{octets,Octs}];
+ Range =< 16#10000000000 ->
+ Octs = eint_positive(Val2),
+ [encode_length({1,5},length(Octs)),{octets,Octs}];
+ true ->
+ exit({not_supported,{integer_range,Range}})
+ end.
+
+decode_constrained_number(Buffer,{Lb,Ub}) ->
+ Range = Ub - Lb + 1,
+% Val2 = Val - Lb,
+ {Val,Remain} =
+ if
+ Range == 2 ->
+ getbits(Buffer,1);
+ Range =< 4 ->
+ getbits(Buffer,2);
+ Range =< 8 ->
+ getbits(Buffer,3);
+ Range =< 16 ->
+ getbits(Buffer,4);
+ Range =< 32 ->
+ getbits(Buffer,5);
+ Range =< 64 ->
+ getbits(Buffer,6);
+ Range =< 128 ->
+ getbits(Buffer,7);
+ Range =< 255 ->
+ getbits(Buffer,8);
+ Range =< 256 ->
+ getoctets(Buffer,1);
+ Range =< 65536 ->
+ getoctets(Buffer,2);
+ Range =< 16#1000000 ->
+ {Len,Bytes2} = decode_length(Buffer,{1,3}),
+ {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
+ {dec_pos_integer(Octs),Bytes3};
+ Range =< 16#100000000 ->
+ {Len,Bytes2} = decode_length(Buffer,{1,4}),
+ {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
+ {dec_pos_integer(Octs),Bytes3};
+ Range =< 16#10000000000 ->
+ {Len,Bytes2} = decode_length(Buffer,{1,5}),
+ {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
+ {dec_pos_integer(Octs),Bytes3};
+ true ->
+ exit({not_supported,{integer_range,Range}})
+ end,
+ {Val+Lb,Remain}.
+
+% X.691:10.8 Encoding of an unconstrained whole number
+
+encode_unconstrained_number(Val) when Val >= 0 ->
+ Oct = eint(Val,[]),
+ [{debug,unconstrained_number},
+ encode_length({0,'MAX'},length(Oct)),
+ {octets,Oct}];
+encode_unconstrained_number(Val) -> % negative
+ Oct = enint(Val,[]),
+ [{debug,unconstrained_number},
+ encode_length({0,'MAX'},length(Oct)),
+ {octets,Oct}].
+
+%% used for positive Values which don't need a sign bit
+eint_positive(Val) ->
+ case eint(Val,[]) of
+ [0,B1|T] ->
+ [B1|T];
+ T ->
+ T
+ end.
+
+eint(0, [B|Acc]) when B < 128 ->
+ [B|Acc];
+eint(N, Acc) ->
+ eint(N bsr 8, [N band 16#ff| Acc]).
+
+enint(-1, [B1|T]) when B1 > 127 ->
+ [B1|T];
+enint(N, Acc) ->
+ enint(N bsr 8, [N band 16#ff|Acc]).
+
+%% used for signed positive values
+
+%eint(Val, Ack) ->
+% X = Val band 255,
+% Next = Val bsr 8,
+% if
+% Next == 0, X >= 127 ->
+% [0,X|Ack];
+% Next == 0 ->
+% [X|Ack];
+% true ->
+% eint(Next,[X|Ack])
+% end.
+
+%%% used for signed negative values
+%enint(Val, Acc) ->
+% NumOctets = if
+% -Val < 16#80 -> 1;
+% -Val < 16#8000 ->2;
+% -Val < 16#800000 ->3;
+% -Val < 16#80000000 ->4;
+% -Val < 16#8000000000 ->5;
+% -Val < 16#800000000000 ->6;
+% -Val < 16#80000000000000 ->7;
+% -Val < 16#8000000000000000 ->8;
+% -Val < 16#800000000000000000 ->9
+% end,
+% enint(Val,Acc,NumOctets).
+
+%enint(Val, Acc,0) ->
+% Acc;
+%enint(Val, Acc,NumOctets) ->
+% enint(Val bsr 8,[Val band 255|Acc],NumOctets-1).
+
+
+decode_unconstrained_number(Bytes) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ {Ints,Bytes3} = getoctets_as_list(Bytes2,Len),
+ {dec_integer(Ints),Bytes3}.
+
+dec_pos_integer(Ints) ->
+ decpint(Ints, 8 * (length(Ints) - 1)).
+dec_integer(Ints) when hd(Ints) band 255 =< 127 -> %% Positive number
+ decpint(Ints, 8 * (length(Ints) - 1));
+dec_integer(Ints) -> %% Negative
+ decnint(Ints, 8 * (length(Ints) - 1)).
+
+decpint([Byte|Tail], Shift) ->
+ (Byte bsl Shift) bor decpint(Tail, Shift-8);
+decpint([], _) -> 0.
+
+decnint([Byte|Tail], Shift) ->
+ (-128 + (Byte band 127) bsl Shift) bor decpint(Tail, Shift-8).
+
+minimum_octets(Val) ->
+ minimum_octets(Val,[]).
+
+minimum_octets(Val,Acc) when Val > 0 ->
+ minimum_octets((Val bsr 8),[Val band 16#FF|Acc]);
+minimum_octets(0,Acc) ->
+ Acc.
+
+
+%% X.691:10.9 Encoding of a length determinant
+%%encode_small_length(undefined,Len) -> % null means no UpperBound
+%% encode_small_number(Len).
+
+%% X.691:10.9.3.5
+%% X.691:10.9.3.7
+encode_length(undefined,Len) -> % un-constrained
+ if
+ Len < 128 ->
+ {octet,Len band 16#7F};
+ Len < 16384 ->
+ {octets,2,2#1000000000000000 bor Len};
+ true ->
+ exit({error,{asn1,{encode_length,{nyi,above_16k}}}})
+ end;
+
+encode_length({0,'MAX'},Len) ->
+ encode_length(undefined,Len);
+encode_length({Lb,Ub},Len) when Ub =< 65535 ,Lb >= 0 -> % constrained
+ encode_constrained_number({Lb,Ub},Len);
+encode_length({{Lb,Ub},[]},Len) when Ub =< 65535 ,Lb >= 0 ->
+ %% constrained extensible
+ [{bit,0},encode_constrained_number({Lb,Ub},Len)];
+encode_length(SingleValue,_) when integer(SingleValue) ->
+ [].
+
+encode_small_length(Len) when Len =< 64 ->
+ [{bit,0},{bits,6,Len-1}];
+encode_small_length(Len) ->
+ [{bit,1},encode_length(undefined,Len)].
+
+decode_small_length(Buffer) ->
+ case getbit(Buffer) of
+ {0,Remain} ->
+ {Bits,Remain2} = getbits(Remain,6),
+ {Bits+1,Remain2};
+ {1,Remain} ->
+ decode_length(Remain,undefined)
+ end.
+
+decode_length(Buffer) ->
+ decode_length(Buffer,undefined).
+
+decode_length(Buffer,undefined) -> % un-constrained
+ Buffer2 = align(Buffer),
+ {Bits,_} = getbits(Buffer2,2),
+ case Bits of
+ 2 ->
+ {Val,Bytes3} = getoctets(Buffer2,2),
+ {(Val band 16#3FFF),Bytes3};
+ 3 ->
+ exit({error,{asn1,{decode_length,{nyi,above_16k}}}});
+ _ ->
+ {Val,Bytes3} = getoctet(Buffer2),
+ {Val band 16#7F,Bytes3}
+ end;
+
+decode_length(Buffer,{Lb,Ub}) when Ub =< 65535 ,Lb >= 0 -> % constrained
+ decode_constrained_number(Buffer,{Lb,Ub});
+
+decode_length(Buffer,{{Lb,Ub},[]}) ->
+ case getbit(Buffer) of
+ {0,Buffer2} ->
+ decode_length(Buffer2, {Lb,Ub})
+ end;
+ % X.691:10.9.3.5
+decode_length(Buffer,{_,_Lb,_Ub}) -> %when Len =< 127 -> % Unconstrained or large Ub
+ case getbit(Buffer) of
+ {0,Remain} ->
+ getbits(Remain,7);
+ {1,_Remain} ->
+ {Val,Remain2} = getoctets(Buffer,2),
+ {Val band 2#0111111111111111, Remain2}
+ end;
+decode_length(Buffer,SingleValue) when integer(SingleValue) ->
+ {SingleValue,Buffer}.
+
+
+% X.691:11
+encode_boolean({Name,Val}) when atom(Name) ->
+ encode_boolean(Val);
+encode_boolean(true) ->
+ {bit,1};
+encode_boolean(false) ->
+ {bit,0};
+encode_boolean(Val) ->
+ exit({error,{asn1,{encode_boolean,Val}}}).
+
+
+decode_boolean(Buffer) -> %when record(Buffer,buffer)
+ case getbit(Buffer) of
+ {1,Remain} -> {true,Remain};
+ {0,Remain} -> {false,Remain}
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% X.691:12
+%% ENUMERATED
+%%
+%% encode_enumerated(C,Value,NamedNumberTup) -> CompleteList
+%%
+%%
+
+encode_enumerated(C,{Name,Value},NamedNumberList) when
+ atom(Name),list(NamedNumberList) ->
+ encode_enumerated(C,Value,NamedNumberList);
+
+%% ENUMERATED with extension mark
+encode_enumerated(_C,{asn1_enum,Value},{_Nlist1,Nlist2}) when Value >= length(Nlist2) ->
+ [{bit,1},encode_small_number(Value)];
+encode_enumerated(C,Value,{Nlist1,Nlist2}) ->
+ case enum_search(Value,Nlist1,0) of
+ NewV when integer(NewV) ->
+ [{bit,0},encode_integer(C,NewV)];
+ false ->
+ case enum_search(Value,Nlist2,0) of
+ ExtV when integer(ExtV) ->
+ [{bit,1},encode_small_number(ExtV)];
+ false ->
+ exit({error,{asn1,{encode_enumerated,Value}}})
+ end
+ end;
+
+encode_enumerated(C,Value,NamedNumberList) when list(NamedNumberList) ->
+ case enum_search(Value,NamedNumberList,0) of
+ NewV when integer(NewV) ->
+ encode_integer(C,NewV);
+ false ->
+ exit({error,{asn1,{encode_enumerated,Value}}})
+ end.
+
+%% returns the ordinal number from 0 ,1 ... in the list where Name is found
+%% or false if not found
+%%
+enum_search(Name,[Name|_NamedNumberList],Acc) ->
+ Acc;
+enum_search(Name,[_H|T],Acc) ->
+ enum_search(Name,T,Acc+1);
+enum_search(_,[],_) ->
+ false. % name not found !error
+
+%% ENUMERATED with extension marker
+decode_enumerated(Buffer,C,{Ntup1,Ntup2}) when tuple(Ntup1), tuple(Ntup2) ->
+ {Ext,Buffer2} = getext(Buffer),
+ case Ext of
+ 0 -> % not an extension value
+ {Val,Buffer3} = decode_integer(Buffer2,C),
+ case catch (element(Val+1,Ntup1)) of
+ NewVal when atom(NewVal) -> {NewVal,Buffer3};
+ _Error -> exit({error,{asn1,{decode_enumerated,{Val,[Ntup1,Ntup2]}}}})
+ end;
+ 1 -> % this an extension value
+ {Val,Buffer3} = decode_small_number(Buffer2),
+ case catch (element(Val+1,Ntup2)) of
+ NewVal when atom(NewVal) -> {NewVal,Buffer3};
+ _ -> {{asn1_enum,Val},Buffer3}
+ end
+ end;
+
+decode_enumerated(Buffer,C,NamedNumberTup) when tuple(NamedNumberTup) ->
+ {Val,Buffer2} = decode_integer(Buffer,C),
+ case catch (element(Val+1,NamedNumberTup)) of
+ NewVal when atom(NewVal) -> {NewVal,Buffer2};
+ _Error -> exit({error,{asn1,{decode_enumerated,{Val,NamedNumberTup}}}})
+ end.
+
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+%% Bitstring value, ITU_T X.690 Chapter 8.5
+%%===============================================================================
+%%===============================================================================
+%%===============================================================================
+
+%%===============================================================================
+%% encode bitstring value
+%%===============================================================================
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% bitstring NamedBitList
+%% Val can be of:
+%% - [identifiers] where only named identifers are set to one,
+%% the Constraint must then have some information of the
+%% bitlength.
+%% - [list of ones and zeroes] all bits
+%% - integer value representing the bitlist
+%% C is constraint Len, only valid when identifiers
+
+
+%% when the value is a list of {Unused,BinBits}, where
+%% Unused = integer(),
+%% BinBits = binary().
+encode_bit_string(C,Bin={Unused,BinBits},NamedBitList) when integer(Unused),
+ binary(BinBits) ->
+ encode_bin_bit_string(C,Bin,NamedBitList);
+
+%% when the value is a list of named bits
+encode_bit_string(C, [FirstVal | RestVal], NamedBitList) when atom(FirstVal) ->
+ ToSetPos = get_all_bitposes([FirstVal | RestVal], NamedBitList, []),
+ BitList = make_and_set_list(ToSetPos,0),
+ encode_bit_string(C,BitList,NamedBitList);
+
+encode_bit_string(C, [{bit,No} | RestVal], NamedBitList) ->
+ ToSetPos = get_all_bitposes([{bit,No} | RestVal], NamedBitList, []),
+ BitList = make_and_set_list(ToSetPos,0),
+ encode_bit_string(C,BitList,NamedBitList);
+
+%% when the value is a list of ones and zeroes
+
+encode_bit_string(C, BitListValue, NamedBitList) when list(BitListValue) ->
+ Bl1 =
+ case NamedBitList of
+ [] -> % dont remove trailing zeroes
+ BitListValue;
+ _ -> % first remove any trailing zeroes
+ lists:reverse(lists:dropwhile(fun(0)->true;(1)->false end,
+ lists:reverse(BitListValue)))
+ end,
+ BitList = [{bit,X} || X <- Bl1],
+ BListLen = length(BitList),
+ case get_constraint(C,'SizeConstraint') of
+ 0 -> % fixed length
+ []; % nothing to encode
+ V when integer(V),V=<16 -> % fixed length 16 bits or less
+ pad_list(V,BitList);
+ V when integer(V) -> % fixed length 16 bits or less
+ [align,pad_list(V,BitList)];
+ {Lb,Ub} when integer(Lb),integer(Ub),BListLen<Lb ->
+ %% padding due to OTP-4353
+ [encode_length({Lb,Ub},Lb),align,pad_list(Lb,BitList)];
+ {Lb,Ub} when integer(Lb),integer(Ub) ->
+ [encode_length({Lb,Ub},length(BitList)),align,BitList];
+ no ->
+ [encode_length(undefined,length(BitList)),align,BitList];
+ Sc={{Lb,Ub},_} when integer(Lb),integer(Ub),BListLen<Lb ->
+ %% padding due to OTP-4353
+ [encode_length(Sc,Lb),align,pad_list(Lb,BitList)];
+ Sc -> % extension marker
+ [encode_length(Sc,length(BitList)),align,BitList]
+ end;
+
+%% when the value is an integer
+encode_bit_string(C, IntegerVal, NamedBitList) when integer(IntegerVal)->
+ BitList = int_to_bitlist(IntegerVal),
+ encode_bit_string(C,BitList,NamedBitList);
+
+%% when the value is a tuple
+encode_bit_string(C,{Name,Val}, NamedBitList) when atom(Name) ->
+ encode_bit_string(C,Val,NamedBitList).
+
+
+%% encode_bin_bit_string/3, when value is a tuple of Unused and BinBits.
+%% Unused = integer(),
+%% BinBits = binary().
+
+encode_bin_bit_string(C,{Unused,BinBits},NamedBitList) ->
+ RemoveZerosIfNNL =
+ fun({NNL,BitList}) ->
+ case NNL of
+ [] -> BitList;
+ _ ->
+ lists:reverse(
+ lists:dropwhile(fun(0)->true;(1)->false end,
+ lists:reverse(BitList)))
+ end
+ end,
+ {OctetList,OLSize,LastBits} =
+ case size(BinBits) of
+ N when N>1 ->
+ IntList = binary_to_list(BinBits),
+ [H|T] = lists:reverse(IntList),
+ Bl1 = RemoveZerosIfNNL({NamedBitList,lists:reverse(int_to_bitlist(H,8-Unused))}),% lists:sublist obsolete if trailing bits are zero !
+ {[{octet,X} || X <- lists:reverse(T)],size(BinBits)-1,
+ [{bit,X} || X <- Bl1]};
+ 1 ->
+ <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1>> = BinBits,
+ {[],0,[{bit,X} || X <- lists:sublist([B7,B6,B5,B4,B3,B2,B1,B0],8-Unused)]};
+ _ ->
+ {[],0,[]}
+ end,
+ case get_constraint(C,'SizeConstraint') of
+ 0 ->
+ [];
+ V when integer(V),V=<16 ->
+ [OctetList, pad_list(V,LastBits)];
+ V when integer(V) ->
+% [OctetList, align, pad_list(V rem 8,LastBits)];
+ [align,OctetList, pad_list(V rem 8,LastBits)];
+ {Lb,Ub} when integer(Lb),integer(Ub) ->
+ NewLastBits = maybe_pad(Lb,length(LastBits)+(OLSize*8),LastBits,NamedBitList),
+ [encode_length({Lb,Ub},length(NewLastBits)+(OLSize*8)),
+% OctetList,align,LastBits];
+ align,OctetList,NewLastBits];
+ no ->
+ [encode_length(undefined,length(LastBits)+(OLSize*8)),
+% OctetList,align,LastBits];
+ align,OctetList,LastBits];
+ Sc={{Lb,_},_} when integer(Lb) ->
+ NewLastBits = maybe_pad(Lb,length(LastBits)+(OLSize*8),LastBits,NamedBitList),
+ [encode_length(Sc,length(NewLastBits)+(OLSize*8)),
+ align,OctetList,NewLastBits];
+ Sc ->
+ [encode_length(Sc,length(LastBits)+(OLSize*8)),
+% OctetList,align,LastBits]
+ align,OctetList,LastBits]
+ end.
+
+maybe_pad(_,_,Bits,[]) ->
+ Bits;
+maybe_pad(Lb,LenBits,Bits,_) when Lb>LenBits ->
+ pad_list(Lb,Bits);
+maybe_pad(_,_,Bits,_) ->
+ Bits.
+
+%%%%%%%%%%%%%%%
+%% The result is presented as a list of named bits (if possible)
+%% else as a tuple {Unused,Bits}. Unused is the number of unused
+%% bits, least significant bits in the last byte of Bits. Bits is
+%% the BIT STRING represented as a binary.
+%%
+decode_compact_bit_string(Buffer, C, NamedNumberList) ->
+ case get_constraint(C,'SizeConstraint') of
+ 0 -> % fixed length
+ {{0,<<>>},Buffer};
+ V when integer(V),V=<16 -> %fixed length 16 bits or less
+ compact_bit_string(Buffer,V,NamedNumberList);
+ V when integer(V) -> %fixed length > 16 bits
+ Bytes2 = align(Buffer),
+ compact_bit_string(Bytes2,V,NamedNumberList);
+ {Lb,Ub} when integer(Lb),integer(Ub) ->
+ {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
+ Bytes3 = align(Bytes2),
+ compact_bit_string(Bytes3,Len,NamedNumberList);
+ no ->
+ {Len,Bytes2} = decode_length(Buffer,undefined),
+ Bytes3 = align(Bytes2),
+ compact_bit_string(Bytes3,Len,NamedNumberList);
+ Sc ->
+ {Len,Bytes2} = decode_length(Buffer,Sc),
+ Bytes3 = align(Bytes2),
+ compact_bit_string(Bytes3,Len,NamedNumberList)
+ end.
+
+
+%%%%%%%%%%%%%%%
+%% The result is presented as a list of named bits (if possible)
+%% else as a list of 0 and 1.
+%%
+decode_bit_string(Buffer, C, NamedNumberList) ->
+ case get_constraint(C,'SizeConstraint') of
+ 0 -> % fixed length
+ {[],Buffer}; % nothing to encode
+ V when integer(V),V=<16 -> % fixed length 16 bits or less
+ bit_list_to_named(Buffer,V,NamedNumberList);
+ V when integer(V) -> % fixed length 16 bits or less
+ Bytes2 = align(Buffer),
+ bit_list_to_named(Bytes2,V,NamedNumberList);
+ {Lb,Ub} when integer(Lb),integer(Ub) ->
+ {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
+ Bytes3 = align(Bytes2),
+ bit_list_to_named(Bytes3,Len,NamedNumberList);
+ no ->
+ {Len,Bytes2} = decode_length(Buffer,undefined),
+ Bytes3 = align(Bytes2),
+ bit_list_to_named(Bytes3,Len,NamedNumberList);
+ Sc -> % extension marker
+ {Len,Bytes2} = decode_length(Buffer,Sc),
+ Bytes3 = align(Bytes2),
+ bit_list_to_named(Bytes3,Len,NamedNumberList)
+ end.
+
+
+%% if no named bits are declared we will return a
+%% {Unused,Bits}. Unused = integer(),
+%% Bits = binary().
+compact_bit_string(Buffer,Len,[]) ->
+ getbits_as_binary(Len,Buffer); % {{Unused,BinBits},NewBuffer}
+compact_bit_string(Buffer,Len,NamedNumberList) ->
+ bit_list_to_named(Buffer,Len,NamedNumberList).
+
+
+%% if no named bits are declared we will return a
+%% BitList = [0 | 1]
+
+bit_list_to_named(Buffer,Len,[]) ->
+ getbits_as_list(Len,Buffer);
+
+%% if there are named bits declared we will return a named
+%% BitList where the names are atoms and unnamed bits represented
+%% as {bit,Pos}
+%% BitList = [atom() | {bit,Pos}]
+%% Pos = integer()
+
+bit_list_to_named(Buffer,Len,NamedNumberList) ->
+ {BitList,Rest} = getbits_as_list(Len,Buffer),
+ {bit_list_to_named1(0,BitList,NamedNumberList,[]), Rest}.
+
+bit_list_to_named1(Pos,[0|Bt],Names,Acc) ->
+ bit_list_to_named1(Pos+1,Bt,Names,Acc);
+bit_list_to_named1(Pos,[1|Bt],Names,Acc) ->
+ case lists:keysearch(Pos,2,Names) of
+ {value,{Name,_}} ->
+ bit_list_to_named1(Pos+1,Bt,Names,[Name|Acc]);
+ _ ->
+ bit_list_to_named1(Pos+1,Bt,Names,[{bit,Pos}|Acc])
+ end;
+bit_list_to_named1(_Pos,[],_Names,Acc) ->
+ lists:reverse(Acc).
+
+
+
+%%%%%%%%%%%%%%%
+%%
+
+int_to_bitlist(0) ->
+ [];
+int_to_bitlist(Int) when integer(Int), Int >= 0 ->
+ [Int band 1 | int_to_bitlist(Int bsr 1)].
+
+int_to_bitlist(_Int,0) ->
+ [];
+int_to_bitlist(0,N) ->
+ [0|int_to_bitlist(0,N-1)];
+int_to_bitlist(Int,N) ->
+ [Int band 1 | int_to_bitlist(Int bsr 1, N-1)].
+
+
+%%%%%%%%%%%%%%%%%%
+%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
+%% [sorted_list_of_bitpositions_to_set]
+
+get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
+ get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
+
+get_all_bitposes([Val | Rest], NamedBitList, Ack) ->
+ case lists:keysearch(Val, 1, NamedBitList) of
+ {value, {_ValName, ValPos}} ->
+ get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
+ _ ->
+ exit({error,{asn1, {bitstring_namedbit, Val}}})
+ end;
+get_all_bitposes([], _NamedBitList, Ack) ->
+ lists:sort(Ack).
+
+%%%%%%%%%%%%%%%%%%
+%% make_and_set_list([list of positions to set to 1])->
+%% returns list with all in SetPos set.
+%% in positioning in list the first element is 0, the second 1 etc.., but
+%%
+
+make_and_set_list([XPos|SetPos], XPos) ->
+ [1 | make_and_set_list(SetPos, XPos + 1)];
+make_and_set_list([Pos|SetPos], XPos) ->
+ [0 | make_and_set_list([Pos | SetPos], XPos + 1)];
+make_and_set_list([], _XPos) ->
+ [].
+
+%%%%%%%%%%%%%%%%%
+%% pad_list(N,BitList) -> PaddedList
+%% returns a padded (with trailing {bit,0} elements) list of length N
+%% if Bitlist contains more than N significant bits set an exit asn1_error
+%% is generated
+
+pad_list(0,BitList) ->
+ case BitList of
+ [] -> [];
+ _ -> exit({error,{asn1,{range_error,{bit_string,BitList}}}})
+ end;
+pad_list(N,[Bh|Bt]) ->
+ [Bh|pad_list(N-1,Bt)];
+pad_list(N,[]) ->
+ [{bit,0},pad_list(N-1,[])].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% X.691:16
+%% encode_octet_string(Constraint,ExtensionMarker,Val)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+encode_octet_string(C,{Name,Val}) when atom(Name) ->
+ encode_octet_string(C,false,Val);
+encode_octet_string(C,Val) ->
+ encode_octet_string(C,false,Val).
+
+encode_octet_string(C,Bool,{_Name,Val}) ->
+ encode_octet_string(C,Bool,Val);
+encode_octet_string(_,true,_) ->
+ exit({error,{asn1,{'not_supported',extensionmarker}}});
+encode_octet_string(C,false,Val) ->
+ case get_constraint(C,'SizeConstraint') of
+ 0 ->
+ [];
+ 1 ->
+ [V] = Val,
+ {bits,8,V};
+ 2 ->
+ [V1,V2] = Val,
+ [{bits,8,V1},{bits,8,V2}];
+ Sv when Sv =<65535, Sv == length(Val) -> % fixed length
+ [align,{octets,Val}];
+ {Lb,Ub} ->
+ [encode_length({Lb,Ub},length(Val)),align,
+ {octets,Val}];
+ Sv when list(Sv) ->
+ [encode_length({hd(Sv),lists:max(Sv)},length(Val)),align,
+ {octets,Val}];
+ no ->
+ [encode_length(undefined,length(Val)),align,
+ {octets,Val}]
+ end.
+
+decode_octet_string(Bytes,Range) ->
+ decode_octet_string(Bytes,Range,false).
+
+decode_octet_string(Bytes,C,false) ->
+ case get_constraint(C,'SizeConstraint') of
+ 0 ->
+ {[],Bytes};
+ 1 ->
+ {B1,Bytes2} = getbits(Bytes,8),
+ {[B1],Bytes2};
+ 2 ->
+ {B1,Bytes2}= getbits(Bytes,8),
+ {B2,Bytes3}= getbits(Bytes2,8),
+ {[B1,B2],Bytes3};
+ {_,0} ->
+ {[],Bytes};
+ Sv when integer(Sv), Sv =<65535 -> % fixed length
+ Bytes2 = align(Bytes),
+ getoctets_as_list(Bytes2,Sv);
+ {Lb,Ub} ->
+ {Len,Bytes2} = decode_length(Bytes,{Lb,Ub}),
+ Bytes3 = align(Bytes2),
+ getoctets_as_list(Bytes3,Len);
+ Sv when list(Sv) ->
+ {Len,Bytes2} = decode_length(Bytes,{hd(Sv),lists:max(Sv)}),
+ Bytes3 = align(Bytes2),
+ getoctets_as_list(Bytes3,Len);
+ no ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ Bytes3 = align(Bytes2),
+ getoctets_as_list(Bytes3,Len)
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Restricted char string types
+%% (NumericString, PrintableString,VisibleString,IA5String,BMPString,UniversalString)
+%% X.691:26 and X.680:34-36
+%%encode_restricted_string(aligned,'BMPString',Constraints,Extension,Val)
+
+
+encode_restricted_string(aligned,{Name,Val}) when atom(Name) ->
+ encode_restricted_string(aligned,Val);
+
+encode_restricted_string(aligned,Val) when list(Val)->
+ [encode_length(undefined,length(Val)),align,
+ {octets,Val}].
+
+encode_known_multiplier_string(aligned,StringType,C,_Ext,{Name,Val}) when atom(Name) ->
+ encode_known_multiplier_string(aligned,StringType,C,false,Val);
+
+encode_known_multiplier_string(aligned,StringType,C,_Ext,Val) ->
+ Result = chars_encode(C,StringType,Val),
+ NumBits = get_NumBits(C,StringType),
+ case get_constraint(C,'SizeConstraint') of
+ Ub when integer(Ub), Ub*NumBits =< 16 ->
+ case {StringType,Result} of
+ {'BMPString',{octets,Ol}} ->
+ [{bits,8,Oct}||Oct <- Ol];
+ _ ->
+ Result
+ end;
+ 0 ->
+ [];
+ Ub when integer(Ub),Ub =<65535 -> % fixed length
+ [align,Result];
+ {Ub,Lb} ->
+ [encode_length({Ub,Lb},length(Val)),align,Result];
+ Vl when list(Vl) ->
+ [encode_length({lists:min(Vl),lists:max(Vl)},length(Val)),align,Result];
+ no ->
+ [encode_length(undefined,length(Val)),align,Result]
+ end.
+
+decode_restricted_string(Bytes,aligned) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ Bytes3 = align(Bytes2),
+ getoctets_as_list(Bytes3,Len).
+
+decode_known_multiplier_string(Bytes,aligned,StringType,C,_Ext) ->
+ NumBits = get_NumBits(C,StringType),
+ case get_constraint(C,'SizeConstraint') of
+ Ub when integer(Ub), Ub*NumBits =< 16 ->
+ chars_decode(Bytes,NumBits,StringType,C,Ub);
+ Ub when integer(Ub),Ub =<65535 -> % fixed length
+ Bytes1 = align(Bytes),
+ chars_decode(Bytes1,NumBits,StringType,C,Ub);
+ 0 ->
+ {[],Bytes};
+ Vl when list(Vl) ->
+ {Len,Bytes1} = decode_length(Bytes,{hd(Vl),lists:max(Vl)}),
+ Bytes2 = align(Bytes1),
+ chars_decode(Bytes2,NumBits,StringType,C,Len);
+ no ->
+ {Len,Bytes1} = decode_length(Bytes,undefined),
+ Bytes2 = align(Bytes1),
+ chars_decode(Bytes2,NumBits,StringType,C,Len);
+ {Lb,Ub}->
+ {Len,Bytes1} = decode_length(Bytes,{Lb,Ub}),
+ Bytes2 = align(Bytes1),
+ chars_decode(Bytes2,NumBits,StringType,C,Len)
+ end.
+
+
+encode_NumericString(C,Val) ->
+ encode_known_multiplier_string(aligned,'NumericString',C,false,Val).
+decode_NumericString(Bytes,C) ->
+ decode_known_multiplier_string(Bytes,aligned,'NumericString',C,false).
+
+encode_PrintableString(C,Val) ->
+ encode_known_multiplier_string(aligned,'PrintableString',C,false,Val).
+decode_PrintableString(Bytes,C) ->
+ decode_known_multiplier_string(Bytes,aligned,'PrintableString',C,false).
+
+encode_VisibleString(C,Val) -> % equivalent with ISO646String
+ encode_known_multiplier_string(aligned,'VisibleString',C,false,Val).
+decode_VisibleString(Bytes,C) ->
+ decode_known_multiplier_string(Bytes,aligned,'VisibleString',C,false).
+
+encode_IA5String(C,Val) ->
+ encode_known_multiplier_string(aligned,'IA5String',C,false,Val).
+decode_IA5String(Bytes,C) ->
+ decode_known_multiplier_string(Bytes,aligned,'IA5String',C,false).
+
+encode_BMPString(C,Val) ->
+ encode_known_multiplier_string(aligned,'BMPString',C,false,Val).
+decode_BMPString(Bytes,C) ->
+ decode_known_multiplier_string(Bytes,aligned,'BMPString',C,false).
+
+encode_UniversalString(C,Val) ->
+ encode_known_multiplier_string(aligned,'UniversalString',C,false,Val).
+decode_UniversalString(Bytes,C) ->
+ decode_known_multiplier_string(Bytes,aligned,'UniversalString',C,false).
+
+%% end of known-multiplier strings for which PER visible constraints are
+%% applied
+
+encode_GeneralString(_C,Val) ->
+ encode_restricted_string(aligned,Val).
+decode_GeneralString(Bytes,_C) ->
+ decode_restricted_string(Bytes,aligned).
+
+encode_GraphicString(_C,Val) ->
+ encode_restricted_string(aligned,Val).
+decode_GraphicString(Bytes,_C) ->
+ decode_restricted_string(Bytes,aligned).
+
+encode_ObjectDescriptor(_C,Val) ->
+ encode_restricted_string(aligned,Val).
+decode_ObjectDescriptor(Bytes) ->
+ decode_restricted_string(Bytes,aligned).
+
+encode_TeletexString(_C,Val) -> % equivalent with T61String
+ encode_restricted_string(aligned,Val).
+decode_TeletexString(Bytes,_C) ->
+ decode_restricted_string(Bytes,aligned).
+
+encode_VideotexString(_C,Val) ->
+ encode_restricted_string(aligned,Val).
+decode_VideotexString(Bytes,_C) ->
+ decode_restricted_string(Bytes,aligned).
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% getBMPChars(Bytes,Len) ->{BMPcharList,RemainingBytes}
+%%
+getBMPChars(Bytes,1) ->
+ {O1,Bytes2} = getbits(Bytes,8),
+ {O2,Bytes3} = getbits(Bytes2,8),
+ if
+ O1 == 0 ->
+ {[O2],Bytes3};
+ true ->
+ {[{0,0,O1,O2}],Bytes3}
+ end;
+getBMPChars(Bytes,Len) ->
+ getBMPChars(Bytes,Len,[]).
+
+getBMPChars(Bytes,0,Acc) ->
+ {lists:reverse(Acc),Bytes};
+getBMPChars(Bytes,Len,Acc) ->
+ {Octs,Bytes1} = getoctets_as_list(Bytes,2),
+ case Octs of
+ [0,O2] ->
+ getBMPChars(Bytes1,Len-1,[O2|Acc]);
+ [O1,O2]->
+ getBMPChars(Bytes1,Len-1,[{0,0,O1,O2}|Acc])
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% chars_encode(C,StringType,Value) -> ValueList
+%%
+%% encodes chars according to the per rules taking the constraint PermittedAlphabet
+%% into account.
+%% This function does only encode the value part and NOT the length
+
+chars_encode(C,StringType,Value) ->
+ case {StringType,get_constraint(C,'PermittedAlphabet')} of
+ {'UniversalString',{_,_Sv}} ->
+ exit({error,{asn1,{'not implemented',"UniversalString with PermittedAlphabet constraint"}}});
+ {'BMPString',{_,_Sv}} ->
+ exit({error,{asn1,{'not implemented',"BMPString with PermittedAlphabet constraint"}}});
+ _ ->
+ {NumBits,CharOutTab} = {get_NumBits(C,StringType),get_CharOutTab(C,StringType)},
+ chars_encode2(Value,NumBits,CharOutTab)
+ end.
+
+chars_encode2([H|T],NumBits,{Min,Max,notab}) when H =< Max, H >= Min ->
+ [{bits,NumBits,H-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
+chars_encode2([H|T],NumBits,{Min,Max,Tab}) when H =< Max, H >= Min ->
+ [{bits,NumBits,element(H-Min+1,Tab)}|chars_encode2(T,NumBits,{Min,Max,Tab})];
+chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,notab}) ->
+ %% no value range check here (ought to be, but very expensive)
+% [{bits,NumBits,(A*B*C*D)-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
+ [{bits,NumBits,((((((A bsl 8) + B) bsl 8) + C) bsl 8) + D)-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
+chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,Tab}) ->
+ %% no value range check here (ought to be, but very expensive)
+% [{bits,NumBits,element((A*B*C*D)-Min,Tab)}|chars_encode2(T,NumBits,{Min,Max,notab})];
+ [{bits,NumBits,element(((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min,Tab)}|chars_encode2(T,NumBits,{Min,Max,notab})];
+chars_encode2([H|_T],_,{_,_,_}) ->
+ exit({error,{asn1,{illegal_char_value,H}}});
+chars_encode2([],_,_) ->
+ [].
+
+
+get_NumBits(C,StringType) ->
+ case get_constraint(C,'PermittedAlphabet') of
+ {'SingleValue',Sv} ->
+ charbits(length(Sv),aligned);
+ no ->
+ case StringType of
+ 'IA5String' ->
+ charbits(128,aligned); % 16#00..16#7F
+ 'VisibleString' ->
+ charbits(95,aligned); % 16#20..16#7E
+ 'PrintableString' ->
+ charbits(74,aligned); % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
+ 'NumericString' ->
+ charbits(11,aligned); % $ ,"0123456789"
+ 'UniversalString' ->
+ 32;
+ 'BMPString' ->
+ 16
+ end
+ end.
+
+%%Maybe used later
+%%get_MaxChar(C,StringType) ->
+%% case get_constraint(C,'PermittedAlphabet') of
+%% {'SingleValue',Sv} ->
+%% lists:nth(length(Sv),Sv);
+%% no ->
+%% case StringType of
+%% 'IA5String' ->
+%% 16#7F; % 16#00..16#7F
+%% 'VisibleString' ->
+%% 16#7E; % 16#20..16#7E
+%% 'PrintableString' ->
+%% $z; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
+%% 'NumericString' ->
+%% $9; % $ ,"0123456789"
+%% 'UniversalString' ->
+%% 16#ffffffff;
+%% 'BMPString' ->
+%% 16#ffff
+%% end
+%% end.
+
+%%Maybe used later
+%%get_MinChar(C,StringType) ->
+%% case get_constraint(C,'PermittedAlphabet') of
+%% {'SingleValue',Sv} ->
+%% hd(Sv);
+%% no ->
+%% case StringType of
+%% 'IA5String' ->
+%% 16#00; % 16#00..16#7F
+%% 'VisibleString' ->
+%% 16#20; % 16#20..16#7E
+%% 'PrintableString' ->
+%% $\s; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
+%% 'NumericString' ->
+%% $\s; % $ ,"0123456789"
+%% 'UniversalString' ->
+%% 16#00;
+%% 'BMPString' ->
+%% 16#00
+%% end
+%% end.
+
+get_CharOutTab(C,StringType) ->
+ get_CharTab(C,StringType,out).
+
+get_CharInTab(C,StringType) ->
+ get_CharTab(C,StringType,in).
+
+get_CharTab(C,StringType,InOut) ->
+ case get_constraint(C,'PermittedAlphabet') of
+ {'SingleValue',Sv} ->
+ get_CharTab2(C,StringType,hd(Sv),lists:max(Sv),Sv,InOut);
+ no ->
+ case StringType of
+ 'IA5String' ->
+ {0,16#7F,notab};
+ 'VisibleString' ->
+ get_CharTab2(C,StringType,16#20,16#7F,notab,InOut);
+ 'PrintableString' ->
+ Chars = lists:sort(
+ " '()+,-./0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
+ get_CharTab2(C,StringType,hd(Chars),lists:max(Chars),Chars,InOut);
+ 'NumericString' ->
+ get_CharTab2(C,StringType,16#20,$9," 0123456789",InOut);
+ 'UniversalString' ->
+ {0,16#FFFFFFFF,notab};
+ 'BMPString' ->
+ {0,16#FFFF,notab}
+ end
+ end.
+
+get_CharTab2(C,StringType,Min,Max,Chars,InOut) ->
+ BitValMax = (1 bsl get_NumBits(C,StringType))-1,
+ if
+ Max =< BitValMax ->
+ {0,Max,notab};
+ true ->
+ case InOut of
+ out ->
+ {Min,Max,create_char_tab(Min,Chars)};
+ in ->
+ {Min,Max,list_to_tuple(Chars)}
+ end
+ end.
+
+create_char_tab(Min,L) ->
+ list_to_tuple(create_char_tab(Min,L,0)).
+create_char_tab(Min,[Min|T],V) ->
+ [V|create_char_tab(Min+1,T,V+1)];
+create_char_tab(_Min,[],_V) ->
+ [];
+create_char_tab(Min,L,V) ->
+ [false|create_char_tab(Min+1,L,V)].
+
+%% This very inefficient and should be moved to compiletime
+charbits(NumOfChars,aligned) ->
+ case charbits(NumOfChars) of
+ 1 -> 1;
+ 2 -> 2;
+ B when B > 2, B =< 4 -> 4;
+ B when B > 4, B =< 8 -> 8;
+ B when B > 8, B =< 16 -> 16;
+ B when B > 16, B =< 32 -> 32
+ end.
+
+charbits(NumOfChars) when NumOfChars =< 2 -> 1;
+charbits(NumOfChars) when NumOfChars =< 4 -> 2;
+charbits(NumOfChars) when NumOfChars =< 8 -> 3;
+charbits(NumOfChars) when NumOfChars =< 16 -> 4;
+charbits(NumOfChars) when NumOfChars =< 32 -> 5;
+charbits(NumOfChars) when NumOfChars =< 64 -> 6;
+charbits(NumOfChars) when NumOfChars =< 128 -> 7;
+charbits(NumOfChars) when NumOfChars =< 256 -> 8;
+charbits(NumOfChars) when NumOfChars =< 512 -> 9;
+charbits(NumOfChars) when NumOfChars =< 1024 -> 10;
+charbits(NumOfChars) when NumOfChars =< 2048 -> 11;
+charbits(NumOfChars) when NumOfChars =< 4096 -> 12;
+charbits(NumOfChars) when NumOfChars =< 8192 -> 13;
+charbits(NumOfChars) when NumOfChars =< 16384 -> 14;
+charbits(NumOfChars) when NumOfChars =< 32768 -> 15;
+charbits(NumOfChars) when NumOfChars =< 65536 -> 16;
+charbits(NumOfChars) when integer(NumOfChars) ->
+ 16 + charbits1(NumOfChars bsr 16).
+
+charbits1(0) ->
+ 0;
+charbits1(NumOfChars) ->
+ 1 + charbits1(NumOfChars bsr 1).
+
+
+chars_decode(Bytes,_,'BMPString',C,Len) ->
+ case get_constraint(C,'PermittedAlphabet') of
+ no ->
+ getBMPChars(Bytes,Len);
+ _ ->
+ exit({error,{asn1,
+ {'not implemented',
+ "BMPString with PermittedAlphabet constraint"}}})
+ end;
+chars_decode(Bytes,NumBits,StringType,C,Len) ->
+ CharInTab = get_CharInTab(C,StringType),
+ chars_decode2(Bytes,CharInTab,NumBits,Len).
+
+
+chars_decode2(Bytes,CharInTab,NumBits,Len) ->
+ chars_decode2(Bytes,CharInTab,NumBits,Len,[]).
+
+chars_decode2(Bytes,_CharInTab,_NumBits,0,Acc) ->
+ {lists:reverse(Acc),Bytes};
+chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) when NumBits > 8 ->
+ {Char,Bytes2} = getbits(Bytes,NumBits),
+ Result = case minimum_octets(Char+Min) of
+ [NewChar] -> NewChar;
+ [C1,C2] -> {0,0,C1,C2};
+ [C1,C2,C3] -> {0,C1,C2,C3};
+ [C1,C2,C3,C4] -> {C1,C2,C3,C4}
+ end,
+ chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Result|Acc]);
+chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) ->
+ {Char,Bytes2} = getbits(Bytes,NumBits),
+ chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Char+Min|Acc]);
+
+%% BMPString and UniversalString with PermittedAlphabet is currently not supported
+chars_decode2(Bytes,{Min,Max,CharInTab},NumBits,Len,Acc) ->
+ {Char,Bytes2} = getbits(Bytes,NumBits),
+ chars_decode2(Bytes2,{Min,Max,CharInTab},NumBits,Len -1,[element(Char+1,CharInTab)|Acc]).
+
+
+ % X.691:17
+encode_null({Name,Val}) when atom(Name) ->
+ encode_null(Val);
+encode_null(_) -> []. % encodes to nothing
+
+decode_null(Bytes) ->
+ {'NULL',Bytes}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% encode_object_identifier(Val) -> CompleteList
+%% encode_object_identifier({Name,Val}) -> CompleteList
+%% Val -> {Int1,Int2,...,IntN} % N >= 2
+%% Name -> atom()
+%% Int1 -> integer(0..2)
+%% Int2 -> integer(0..39) when Int1 (0..1) else integer()
+%% Int3-N -> integer()
+%% CompleteList -> [{bits,8,Val}|{octets,Ol}|align|...]
+%%
+encode_object_identifier({Name,Val}) when atom(Name) ->
+ encode_object_identifier(Val);
+encode_object_identifier(Val) ->
+ Octets = e_object_identifier(Val,notag),
+ [{debug,object_identifier},encode_length(undefined,length(Octets)),{octets,Octets}].
+
+%% This code is copied from asn1_encode.erl (BER) and corrected and modified
+
+e_object_identifier({'OBJECT IDENTIFIER',V},DoTag) ->
+ e_object_identifier(V,DoTag);
+e_object_identifier({Cname,V},DoTag) when atom(Cname),tuple(V) ->
+ e_object_identifier(tuple_to_list(V),DoTag);
+e_object_identifier({Cname,V},DoTag) when atom(Cname),list(V) ->
+ e_object_identifier(V,DoTag);
+e_object_identifier(V,DoTag) when tuple(V) ->
+ e_object_identifier(tuple_to_list(V),DoTag);
+
+% E1 = 0|1|2 and (E2 < 40 when E1 = 0|1)
+e_object_identifier([E1,E2|Tail],_DoTag) when E1 =< 2 ->
+ Head = 40*E1 + E2, % weird
+ Res = e_object_elements([Head|Tail]),
+% dotag(DoTag,[6],elength(length(Res)+1),[Head|Res]),
+ Res.
+
+e_object_elements([]) ->
+ [];
+e_object_elements([H|T]) ->
+ lists:append(e_object_element(H),e_object_elements(T)).
+
+e_object_element(Num) when Num < 128 ->
+ [Num];
+% must be changed to handle more than 2 octets
+e_object_element(Num) -> %% when Num < ???
+ Left = ((Num band 2#11111110000000) bsr 7) bor 2#10000000,
+ Right = Num band 2#1111111 ,
+ [Left,Right].
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% decode_object_identifier(Bytes) -> {ObjId,RemainingBytes}
+%% ObjId -> {integer(),integer(),...} % at least 2 integers
+%% RemainingBytes -> [integer()] when integer() (0..255)
+decode_object_identifier(Bytes) ->
+ {Len,Bytes2} = decode_length(Bytes,undefined),
+ {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
+ [First|Rest] = dec_subidentifiers(Octs,0,[]),
+ Idlist = if
+ First < 40 ->
+ [0,First|Rest];
+ First < 80 ->
+ [1,First - 40|Rest];
+ true ->
+ [2,First - 80|Rest]
+ end,
+ {list_to_tuple(Idlist),Bytes3}.
+
+dec_subidentifiers([H|T],Av,Al) when H >=16#80 ->
+ dec_subidentifiers(T,(Av bsl 7) + (H band 16#7F),Al);
+dec_subidentifiers([H|T],Av,Al) ->
+ dec_subidentifiers(T,0,[(Av bsl 7) + H |Al]);
+dec_subidentifiers([],_Av,Al) ->
+ lists:reverse(Al).
+
+get_constraint(C,Key) ->
+ case lists:keysearch(Key,1,C) of
+ false ->
+ no;
+ {value,{_,V}} ->
+ V
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% complete(InList) -> ByteList
+%% Takes a coded list with bits and bytes and converts it to a list of bytes
+%% Should be applied as the last step at encode of a complete ASN.1 type
+%%
+complete(InList) when list(InList) ->
+ complete(InList,[],0);
+complete(InList) ->
+ complete([InList],[],0).
+
+complete([{debug,_}|T], Acc, Acclen) ->
+ complete(T,Acc,Acclen);
+complete([H|T],Acc,Acclen) when list(H) ->
+ complete(lists:concat([H,T]),Acc,Acclen);
+
+
+complete([{octets,N,Val}|T],Acc,Acclen) when N =< 4 ,integer(Val) ->
+ Newval = case N of
+ 1 ->
+ Val4 = Val band 16#FF,
+ [Val4];
+ 2 ->
+ Val3 = (Val bsr 8) band 16#FF,
+ Val4 = Val band 16#FF,
+ [Val3,Val4];
+ 3 ->
+ Val2 = (Val bsr 16) band 16#FF,
+ Val3 = (Val bsr 8) band 16#FF,
+ Val4 = Val band 16#FF,
+ [Val2,Val3,Val4];
+ 4 ->
+ Val1 = (Val bsr 24) band 16#FF,
+ Val2 = (Val bsr 16) band 16#FF,
+ Val3 = (Val bsr 8) band 16#FF,
+ Val4 = Val band 16#FF,
+ [Val1,Val2,Val3,Val4]
+ end,
+ complete([{octets,Newval}|T],Acc,Acclen);
+
+complete([{octets,Oct}|T],[],_Acclen) when list(Oct) ->
+ complete(T,lists:reverse(Oct),0);
+complete([{octets,Oct}|T],[Hacc|Tacc],Acclen) when list(Oct) ->
+ Rest = 8 - Acclen,
+ if
+ Rest == 8 ->
+ complete(T,lists:concat([lists:reverse(Oct),[Hacc|Tacc]]),0);
+ true ->
+ complete(T,lists:concat([lists:reverse(Oct),[Hacc bsl Rest|Tacc]]),0)
+ end;
+
+complete([{bit,Val}|T], Acc, Acclen) ->
+ complete([{bits,1,Val}|T],Acc,Acclen);
+complete([{octet,Val}|T], Acc, Acclen) ->
+ complete([{octets,1,Val}|T],Acc,Acclen);
+
+complete([{bits,N,Val}|T], Acc, 0) when N =< 8 ->
+ complete(T,[Val|Acc],N);
+complete([{bits,N,Val}|T], [Hacc|Tacc], Acclen) when N =< 8 ->
+ Rest = 8 - Acclen,
+ if
+ Rest >= N ->
+ complete(T,[(Hacc bsl N) + Val|Tacc],(Acclen+N) rem 8);
+ true ->
+ Diff = N - Rest,
+ NewHacc = (Hacc bsl Rest) + (Val bsr Diff),
+ Mask = element(Diff,{1,3,7,15,31,63,127,255}),
+ complete(T,[(Val band Mask),NewHacc|Tacc],(Acclen+N) rem 8)
+ end;
+complete([{bits,N,Val}|T], Acc, Acclen) -> % N > 8
+ complete([{bits,N-8,Val bsr 8},{bits,8,Val band 255}|T],Acc,Acclen);
+
+complete([align|T],Acc,0) ->
+ complete(T,Acc,0);
+complete([align|T],[Hacc|Tacc],Acclen) ->
+ Rest = 8 - Acclen,
+ complete(T,[Hacc bsl Rest|Tacc],0);
+complete([{octets,_N,Val}|T],Acc,Acclen) when list(Val) -> % no security check here
+ complete([{octets,Val}|T],Acc,Acclen);
+
+complete([],[],0) ->
+ [0]; % a complete encoding must always be at least 1 byte
+complete([],Acc,0) ->
+ lists:reverse(Acc);
+complete([],[Hacc|Tacc],Acclen) when Acclen > 0->
+ Rest = 8 - Acclen,
+ NewHacc = Hacc bsl Rest,
+ lists:reverse([NewHacc|Tacc]).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/notes_history.sgml b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/notes_history.sgml
new file mode 100644
index 0000000000..3b50c1b73f
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/notes_history.sgml
@@ -0,0 +1,97 @@
+<!doctype chapter PUBLIC "-//Stork//DTD chapter//EN">
+<!--
+ ``The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance 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: notes_history.sgml,v 1.1 2008/12/17 09:53:31 mikpe Exp $
+-->
+<chapter>
+ <header>
+ <title>ASN1 Release Notes (Old)</title>
+ <prepared>Kenneth Lundin</prepared>
+ <responsible>Kenneth Lundin</responsible>
+ <docno></docno>
+ <approved>Kenneth Lundin</approved>
+ <checked>Kenneth Lundin</checked>
+ <date>98-02-02</date>
+ <rev>A</rev>
+ <file>notes_history.sgml</file>
+ </header>
+
+ <p>This document describes the changes made to old versions of the <c>asn1</c> application.
+
+ <section>
+ <title>ASN1 0.8.1</title>
+ <p>This is the first release of the ASN1 application. This version is released
+ for beta-testing. Some functionality will be added until the 1.0 version is
+ released. A list of missing features and restrictions can be found in the
+ chapter below.
+
+ <section>
+ <title>Missing features and other restrictions</title>
+ <list>
+ <item>
+ <p>The encoding rules BER and PER (aligned) is supported. <em>PER (unaligned)
+ IS NOT SUPPORTED</em>.
+ <item>
+ <p>NOT SUPPORTED types <c>ANY</c> and <c>ANY DEFINED BY</c>
+ (is not in the standard any more).
+ <item>
+ <p>NOT SUPPORTED types <c>EXTERNAL</c> and <c>EMBEDDED-PDV</c>.
+ <item>
+ <p>NOT SUPPORTED type <c>REAL</c> (planned to be implemented).
+ <item>
+ <p>The code generation support for value definitions in the ASN.1 notation is very limited
+ (planned to be enhanced).
+ <item>
+ <p>The support for constraints is limited to:
+ <list>
+ <item><p>
+ SizeConstraint SIZE(X)
+ <item><p>
+ SingleValue (1)
+ <item><p>
+ ValueRange (X..Y)
+ <item><p>
+ PermittedAlpabet FROM (but not for BMPString and UniversalString when generating PER).
+ </list>
+ <p>Complex expressions in constraints is not supported (planned to be extended).
+ <item>
+ <p>The current version of the compiler has very limited error checking:
+ <list>
+ <item><p>Stops at first syntax error.
+ <item><p>Does not stop when a reference to an undefined type is found ,
+ but prints an error message. Compilation of the generated
+ Erlang module will then fail.
+ <item><p>A whole number of other semantical controls is currently missing. This
+ means that the compiler will give little or bad help to detect what's wrong
+ with an ASN.1 specification, but will mostly work very well when the
+ ASN.1 specification is correct.
+ </list>
+ <item>
+ <p>The maximum INTEGER supported in this version is a signed 64 bit integer. This
+ limitation is probably quite reasonable. (Planned to be extended).
+ <item>
+ <p>Only AUTOMATIC TAGS supported for PER.
+ <item>
+ <p>Only EXPLICIT and IMPLICIT TAGS supported for BER.
+ <item>
+ <p>The compiler supports decoding of BER-data with indefinite length but it is
+ not possible to produce data with indefinite length with the encoder.
+ </list>
+ </section>
+
+ </section>
+</chapter>
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/notes_latest.sgml b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/notes_latest.sgml
new file mode 100644
index 0000000000..ff1f5adfa2
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/notes_latest.sgml
@@ -0,0 +1,97 @@
+<!doctype chapter PUBLIC "-//Stork//DTD chapter//EN">
+<!--
+ ``The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance 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: notes_latest.sgml,v 1.1 2008/12/17 09:53:31 mikpe Exp $
+-->
+<chapter>
+ <header>
+ <title>ASN1 Release Notes</title>
+ <prepared>Kenneth Lundin</prepared>
+ <responsible>Kenneth Lundin</responsible>
+ <docno></docno>
+ <approved>Kenneth Lundin</approved>
+ <checked>Kenneth Lundin</checked>
+ <date>97-10-07</date>
+ <rev>A</rev>
+ <file>notes_latest.sgml</file>
+ </header>
+
+ <p>This document describes the changes made to the asn1 application.
+
+ <section>
+ <title>ASN1 0.8.1</title>
+ <p>This is the first release of the ASN1 application. This version is released
+ for beta-testing. Some functionality will be added until the 1.0 version is
+ released. A list of missing features and restrictions can be found in the
+ chapter below.
+
+ <section>
+ <title>Missing features and other restrictions</title>
+ <list>
+ <item>
+ <p>The encoding rules BER and PER (aligned) is supported. <em>PER (unaligned)
+ IS NOT SUPPORTED</em>.
+ <item>
+ <p>NOT SUPPORTED types <c>ANY</c> and <c>ANY DEFINED BY</c>
+ (is not in the standard any more).
+ <item>
+ <p>NOT SUPPORTED types <c>EXTERNAL</c> and <c>EMBEDDED-PDV</c>.
+ <item>
+ <p>NOT SUPPORTED type <c>REAL</c> (planned to be implemented).
+ <item>
+ <p>The code generation support for value definitions in the ASN.1 notation is very limited
+ (planned to be enhanced).
+ <item>
+ <p>The support for constraints is limited to:
+ <list>
+ <item><p>
+ SizeConstraint SIZE(X)
+ <item><p>
+ SingleValue (1)
+ <item><p>
+ ValueRange (X..Y)
+ <item><p>
+ PermittedAlpabet FROM (but not for BMPString and UniversalString when generating PER).
+ </list>
+ <p>Complex expressions in constraints is not supported (planned to be extended).
+ <item>
+ <p>The current version of the compiler has very limited error checking:
+ <list>
+ <item><p>Stops at first syntax error.
+ <item><p>Does not stop when a reference to an undefined type is found ,
+ but prints an error message. Compilation of the generated
+ Erlang module will then fail.
+ <item><p>A whole number of other semantical controls is currently missing. This
+ means that the compiler will give little or bad help to detect what's wrong
+ with an ASN.1 specification, but will mostly work very well when the
+ ASN.1 specification is correct.
+ </list>
+ <item>
+ <p>The maximum INTEGER supported in this version is a signed 64 bit integer. This
+ limitation is probably quite reasonable. (Planned to be extended).
+ <item>
+ <p>Only AUTOMATIC TAGS supported for PER.
+ <item>
+ <p>Only EXPLICIT and IMPLICIT TAGS supported for BER.
+ <item>
+ <p>The compiler supports decoding of BER-data with indefinite length but it is
+ not possible to produce data with indefinite length with the encoder.
+ </list>
+ </section>
+
+ </section>
+</chapter>
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/Makefile b/lib/dialyzer/test/r9c_SUITE_data/src/inets/Makefile
new file mode 100644
index 0000000000..be63eb73b2
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/Makefile
@@ -0,0 +1,178 @@
+# ``The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance 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: Makefile,v 1.1 2008/12/17 09:53:33 mikpe Exp $
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+
+VSN = $(INETS_VSN)
+APP_VSN = "inets-$(VSN)"
+
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/inets-$(VSN)
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+MODULES = \
+ ftp \
+ http \
+ http_lib \
+ httpc_handler \
+ httpc_manager \
+ uri \
+ httpd \
+ httpd_acceptor \
+ httpd_acceptor_sup \
+ httpd_conf \
+ httpd_example \
+ httpd_manager \
+ httpd_misc_sup \
+ httpd_parse \
+ httpd_request_handler \
+ httpd_response \
+ httpd_socket \
+ httpd_sup \
+ httpd_util \
+ httpd_verbosity \
+ inets_sup \
+ mod_actions \
+ mod_alias \
+ mod_auth \
+ mod_auth_plain \
+ mod_auth_dets \
+ mod_auth_mnesia \
+ mod_auth_server \
+ mod_browser \
+ mod_cgi \
+ mod_dir \
+ mod_disk_log \
+ mod_esi \
+ mod_get \
+ mod_head \
+ mod_htaccess \
+ mod_include \
+ mod_log \
+ mod_range \
+ mod_responsecontrol \
+ mod_trace \
+ mod_security \
+ mod_security_server
+
+HRL_FILES = httpd.hrl httpd_verbosity.hrl mod_auth.hrl \
+ http.hrl jnets_httpd.hrl
+
+ERL_FILES = $(MODULES:%=%.erl)
+
+TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
+
+APP_FILE= inets.app
+APPUP_FILE= inets.appup
+
+APP_SRC= $(APP_FILE).src
+APP_TARGET= $(EBIN)/$(APP_FILE)
+
+APPUP_SRC= $(APPUP_FILE).src
+APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
+
+# ----------------------------------------------------
+# INETS FLAGS
+# ----------------------------------------------------
+# DONT_USE_VERBOSITY = -Ddont_use_verbosity=true
+INETS_FLAGS = -D'SERVER_SOFTWARE="inets/$(VSN)"' \
+ -Ddefault_verbosity=silence \
+ $(DONT_USE_VERBOSITY)
+
+# INETS_DEBUG_DEFAULT = d
+ifeq ($(INETS_DEBUG),)
+ INETS_DEBUG = $(INETS_DEBUG_DEFAULT)
+endif
+
+ifeq ($(INETS_DEBUG),c)
+ INETS_FLAGS += -Dinets_cdebug -Dinets_debug -Dinets_log -Dinets_error
+endif
+ifeq ($(INETS_DEBUG),d)
+ INETS_FLAGS += -Dinets_debug -Dinets_log -Dinets_error
+endif
+ifeq ($(INETS_DEBUG),l)
+ INETS_FLAGS += -Dinets_log -Dinets_error
+endif
+ifeq ($(INETS_DEBUG),e)
+ INETS_FLAGS += -Dinets_error
+endif
+
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ERL_FLAGS +=
+
+ifeq ($(WARN_UNUSED_WARS),true)
+ERL_COMPILE_FLAGS += +warn_unused_vars
+endif
+
+ERL_COMPILE_FLAGS += $(INETS_FLAGS) \
+ +'{parse_transform,sys_pre_attributes}' \
+ +'{attribute,insert,app_vsn,$(APP_VSN)}'
+
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+debug opt: $(TARGET_FILES)
+
+clean:
+ rm -f $(TARGET_FILES)
+ rm -f core
+
+docs:
+
+# ----------------------------------------------------
+# Special Build Targets
+# ----------------------------------------------------
+
+$(APP_TARGET): $(APP_SRC) ../vsn.mk
+ sed -e 's;%VSN%;$(VSN);' $< > $@
+
+$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
+ sed -e 's;%VSN%;$(VSN);' $< > $@
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/src
+ $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src
+ $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+
+release_docs_spec:
+
+info:
+ @echo "INETS_DEBUG = $(INETS_DEBUG)"
+ @echo "INETS_FLAGS = $(INETS_FLAGS)"
+ @echo "ERL_COMPILE_FLAGS = $(ERL_COMPILE_FLAGS)"
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/ftp.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/ftp.erl
new file mode 100644
index 0000000000..312bb3a5c8
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/ftp.erl
@@ -0,0 +1,1582 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: ftp.erl,v 1.2 2009/03/03 01:55:01 kostis Exp $
+%%
+-module(ftp).
+
+-behaviour(gen_server).
+
+%% This module implements an ftp client based on socket(3)/gen_tcp(3),
+%% file(3) and filename(3).
+%%
+
+
+-define(OPEN_TIMEOUT, 60*1000).
+-define(BYTE_TIMEOUT, 1000). % Timeout for _ONE_ byte to arrive. (ms)
+-define(OPER_TIMEOUT, 300). % Operation timeout (seconds)
+-define(FTP_PORT, 21).
+
+%% Client interface
+-export([cd/2, close/1, delete/2, formaterror/1, help/0,
+ lcd/2, lpwd/1, ls/1, ls/2,
+ mkdir/2, nlist/1, nlist/2,
+ open/1, open/2, open/3,
+ pwd/1,
+ recv/2, recv/3, recv_bin/2,
+ recv_chunk_start/2, recv_chunk/1,
+ rename/3, rmdir/2,
+ send/2, send/3, send_bin/3,
+ send_chunk_start/2, send_chunk/2, send_chunk_end/1,
+ type/2, user/3,user/4,account/2,
+ append/3, append/2, append_bin/3,
+ append_chunk/2, append_chunk_end/1, append_chunk_start/2]).
+
+%% Internal
+-export([init/1, handle_call/3, handle_cast/2,
+ handle_info/2, terminate/2,code_change/3]).
+
+
+%%
+%% CLIENT FUNCTIONS
+%%
+
+%% open(Host)
+%% open(Host, Flags)
+%%
+%% Purpose: Start an ftp client and connect to a host.
+%% Args: Host = string(),
+%% Port = integer(),
+%% Flags = [Flag],
+%% Flag = verbose | debug
+%% Returns: {ok, Pid} | {error, ehost}
+
+%%Tho only option was the host in textual form
+open({option_list,Option_list})->
+ %% Dbg = {debug,[trace,log,statistics]},
+ %% Options = [Dbg],
+ Options = [],
+ {ok,Pid1}=case lists:keysearch(flags,1,Option_list) of
+ {value,{flags,Flags}}->
+ {ok, Pid} = gen_server:start_link(?MODULE, [Flags], Options);
+ false ->
+ {ok, Pid} = gen_server:start_link(?MODULE, [], Options)
+ end,
+ gen_server:call(Pid1, {open, ip_comm,Option_list}, infinity);
+
+
+%%The only option was the tuple form of the ip-number
+open(Host)when tuple(Host) ->
+ open(Host, ?FTP_PORT, []);
+
+%%Host is the string form of the hostname
+open(Host)->
+ open(Host,?FTP_PORT,[]).
+
+
+
+open(Host, Port) when integer(Port) ->
+ open(Host,Port,[]);
+
+open(Host, Flags) when list(Flags) ->
+ open(Host,?FTP_PORT, Flags).
+
+open(Host,Port,Flags) when integer(Port), list(Flags) ->
+ %% Dbg = {debug,[trace,log,statistics]},
+ %% Options = [Dbg],
+ Options = [],
+ {ok, Pid} = gen_server:start_link(?MODULE, [Flags], Options),
+ gen_server:call(Pid, {open, ip_comm, Host, Port}, infinity).
+
+%% user(Pid, User, Pass)
+%% Purpose: Login.
+%% Args: Pid = pid(), User = Pass = string()
+%% Returns: ok | {error, euser} | {error, econn}
+user(Pid, User, Pass) ->
+ gen_server:call(Pid, {user, User, Pass}, infinity).
+
+%% user(Pid, User, Pass,Acc)
+%% Purpose: Login whith a supplied account name
+%% Args: Pid = pid(), User = Pass = Acc = string()
+%% Returns: ok | {error, euser} | {error, econn} | {error, eacct}
+user(Pid, User, Pass,Acc) ->
+ gen_server:call(Pid, {user, User, Pass,Acc}, infinity).
+
+%% account(Pid,Acc)
+%% Purpose: Set a user Account.
+%% Args: Pid = pid(), Acc= string()
+%% Returns: ok | {error, eacct}
+account(Pid,Acc) ->
+ gen_server:call(Pid, {account,Acc}, infinity).
+
+%% pwd(Pid)
+%%
+%% Purpose: Get the current working directory at remote server.
+%% Args: Pid = pid()
+%% Returns: {ok, Dir} | {error, elogin} | {error, econn}
+pwd(Pid) ->
+ gen_server:call(Pid, pwd, infinity).
+
+%% lpwd(Pid)
+%%
+%% Purpose: Get the current working directory at local server.
+%% Args: Pid = pid()
+%% Returns: {ok, Dir} | {error, elogin}
+lpwd(Pid) ->
+ gen_server:call(Pid, lpwd, infinity).
+
+%% cd(Pid, Dir)
+%%
+%% Purpose: Change current working directory at remote server.
+%% Args: Pid = pid(), Dir = string()
+%% Returns: ok | {error, epath} | {error, elogin} | {error, econn}
+cd(Pid, Dir) ->
+ gen_server:call(Pid, {cd, Dir}, infinity).
+
+%% lcd(Pid, Dir)
+%%
+%% Purpose: Change current working directory for the local client.
+%% Args: Pid = pid(), Dir = string()
+%% Returns: ok | {error, epath}
+lcd(Pid, Dir) ->
+ gen_server:call(Pid, {lcd, Dir}, infinity).
+
+%% ls(Pid)
+%% ls(Pid, Dir)
+%%
+%% Purpose: List the contents of current directory (ls/1) or directory
+%% Dir (ls/2) at remote server.
+%% Args: Pid = pid(), Dir = string()
+%% Returns: {ok, Listing} | {error, epath} | {error, elogin} | {error, econn}
+ls(Pid) ->
+ ls(Pid, "").
+ls(Pid, Dir) ->
+ gen_server:call(Pid, {dir, long, Dir}, infinity).
+
+%% nlist(Pid)
+%% nlist(Pid, Dir)
+%%
+%% Purpose: List the contents of current directory (ls/1) or directory
+%% Dir (ls/2) at remote server. The returned list is a stream
+%% of file names.
+%% Args: Pid = pid(), Dir = string()
+%% Returns: {ok, Listing} | {error, epath} | {error, elogin} | {error, econn}
+nlist(Pid) ->
+ nlist(Pid, "").
+nlist(Pid, Dir) ->
+ gen_server:call(Pid, {dir, short, Dir}, infinity).
+
+%% rename(Pid, CurrFile, NewFile)
+%%
+%% Purpose: Rename a file at remote server.
+%% Args: Pid = pid(), CurrFile = NewFile = string()
+%% Returns: ok | {error, epath} | {error, elogin} | {error, econn}
+rename(Pid, CurrFile, NewFile) ->
+ gen_server:call(Pid, {rename, CurrFile, NewFile}, infinity).
+
+%% delete(Pid, File)
+%%
+%% Purpose: Remove file at remote server.
+%% Args: Pid = pid(), File = string()
+%% Returns: ok | {error, epath} | {error, elogin} | {error, econn}
+delete(Pid, File) ->
+ gen_server:call(Pid, {delete, File}, infinity).
+
+%% mkdir(Pid, Dir)
+%%
+%% Purpose: Make directory at remote server.
+%% Args: Pid = pid(), Dir = string()
+%% Returns: ok | {error, epath} | {error, elogin} | {error, econn}
+mkdir(Pid, Dir) ->
+ gen_server:call(Pid, {mkdir, Dir}, infinity).
+
+%% rmdir(Pid, Dir)
+%%
+%% Purpose: Remove directory at remote server.
+%% Args: Pid = pid(), Dir = string()
+%% Returns: ok | {error, epath} | {error, elogin} | {error, econn}
+rmdir(Pid, Dir) ->
+ gen_server:call(Pid, {rmdir, Dir}, infinity).
+
+%% type(Pid, Type)
+%%
+%% Purpose: Set transfer type.
+%% Args: Pid = pid(), Type = ascii | binary
+%% Returns: ok | {error, etype} | {error, elogin} | {error, econn}
+type(Pid, Type) ->
+ gen_server:call(Pid, {type, Type}, infinity).
+
+%% recv(Pid, RFile [, LFile])
+%%
+%% Purpose: Transfer file from remote server.
+%% Args: Pid = pid(), RFile = LFile = string()
+%% Returns: ok | {error, epath} | {error, elogin} | {error, econn}
+recv(Pid, RFile) ->
+ recv(Pid, RFile, "").
+
+recv(Pid, RFile, LFile) ->
+ gen_server:call(Pid, {recv, RFile, LFile}, infinity).
+
+%% recv_bin(Pid, RFile)
+%%
+%% Purpose: Transfer file from remote server into binary.
+%% Args: Pid = pid(), RFile = string()
+%% Returns: {ok, Bin} | {error, epath} | {error, elogin} | {error, econn}
+recv_bin(Pid, RFile) ->
+ gen_server:call(Pid, {recv_bin, RFile}, infinity).
+
+%% recv_chunk_start(Pid, RFile)
+%%
+%% Purpose: Start receive of chunks of remote file.
+%% Args: Pid = pid(), RFile = string().
+%% Returns: ok | {error, elogin} | {error, epath} | {error, econn}
+recv_chunk_start(Pid, RFile) ->
+ gen_server:call(Pid, {recv_chunk_start, RFile}, infinity).
+
+
+%% recv_chunk(Pid, RFile)
+%%
+%% Purpose: Transfer file from remote server into binary in chunks
+%% Args: Pid = pid(), RFile = string()
+%% Returns: Reference
+recv_chunk(Pid) ->
+ gen_server:call(Pid, recv_chunk, infinity).
+
+%% send(Pid, LFile [, RFile])
+%%
+%% Purpose: Transfer file to remote server.
+%% Args: Pid = pid(), LFile = RFile = string()
+%% Returns: ok | {error, epath} | {error, elogin} | {error, econn}
+send(Pid, LFile) ->
+ send(Pid, LFile, "").
+
+send(Pid, LFile, RFile) ->
+ gen_server:call(Pid, {send, LFile, RFile}, infinity).
+
+%% send_bin(Pid, Bin, RFile)
+%%
+%% Purpose: Transfer a binary to a remote file.
+%% Args: Pid = pid(), Bin = binary(), RFile = string()
+%% Returns: ok | {error, epath} | {error, elogin} | {error, enotbinary}
+%% | {error, econn}
+send_bin(Pid, Bin, RFile) when binary(Bin) ->
+ gen_server:call(Pid, {send_bin, Bin, RFile}, infinity);
+send_bin(Pid, Bin, RFile) ->
+ {error, enotbinary}.
+
+%% send_chunk_start(Pid, RFile)
+%%
+%% Purpose: Start transfer of chunks to remote file.
+%% Args: Pid = pid(), RFile = string().
+%% Returns: ok | {error, elogin} | {error, epath} | {error, econn}
+send_chunk_start(Pid, RFile) ->
+ gen_server:call(Pid, {send_chunk_start, RFile}, infinity).
+
+
+%% append_chunk_start(Pid, RFile)
+%%
+%% Purpose: Start append chunks of data to remote file.
+%% Args: Pid = pid(), RFile = string().
+%% Returns: ok | {error, elogin} | {error, epath} | {error, econn}
+append_chunk_start(Pid, RFile) ->
+ gen_server:call(Pid, {append_chunk_start, RFile}, infinity).
+
+
+%% send_chunk(Pid, Bin)
+%%
+%% Purpose: Send chunk to remote file.
+%% Args: Pid = pid(), Bin = binary().
+%% Returns: ok | {error, elogin} | {error, enotbinary} | {error, echunk}
+%% | {error, econn}
+send_chunk(Pid, Bin) when binary(Bin) ->
+ gen_server:call(Pid, {send_chunk, Bin}, infinity);
+send_chunk(Pid, Bin) ->
+ {error, enotbinary}.
+
+%%append_chunk(Pid, Bin)
+%%
+%% Purpose: Append chunk to remote file.
+%% Args: Pid = pid(), Bin = binary().
+%% Returns: ok | {error, elogin} | {error, enotbinary} | {error, echunk}
+%% | {error, econn}
+append_chunk(Pid, Bin) when binary(Bin) ->
+ gen_server:call(Pid, {append_chunk, Bin}, infinity);
+append_chunk(Pid, Bin) ->
+ {error, enotbinary}.
+
+%% send_chunk_end(Pid)
+%%
+%% Purpose: End sending of chunks to remote file.
+%% Args: Pid = pid().
+%% Returns: ok | {error, elogin} | {error, echunk} | {error, econn}
+send_chunk_end(Pid) ->
+ gen_server:call(Pid, send_chunk_end, infinity).
+
+%% append_chunk_end(Pid)
+%%
+%% Purpose: End appending of chunks to remote file.
+%% Args: Pid = pid().
+%% Returns: ok | {error, elogin} | {error, echunk} | {error, econn}
+append_chunk_end(Pid) ->
+ gen_server:call(Pid, append_chunk_end, infinity).
+
+%% append(Pid, LFile,RFile)
+%%
+%% Purpose: Append the local file to the remote file
+%% Args: Pid = pid(), LFile = RFile = string()
+%% Returns: ok | {error, epath} | {error, elogin} | {error, econn}
+append(Pid, LFile) ->
+ append(Pid, LFile, "").
+
+append(Pid, LFile, RFile) ->
+ gen_server:call(Pid, {append, LFile, RFile}, infinity).
+
+%% append_bin(Pid, Bin, RFile)
+%%
+%% Purpose: Append a binary to a remote file.
+%% Args: Pid = pid(), Bin = binary(), RFile = string()
+%% Returns: ok | {error, epath} | {error, elogin} | {error, enotbinary}
+%% | {error, econn}
+append_bin(Pid, Bin, RFile) when binary(Bin) ->
+ gen_server:call(Pid, {append_bin, Bin, RFile}, infinity);
+append_bin(Pid, Bin, RFile) ->
+ {error, enotbinary}.
+
+
+%% close(Pid)
+%%
+%% Purpose: End the ftp session.
+%% Args: Pid = pid()
+%% Returns: ok
+close(Pid) ->
+ case (catch gen_server:call(Pid, close, 30000)) of
+ ok ->
+ ok;
+ {'EXIT',{noproc,_}} ->
+ %% Already gone...
+ ok;
+ Res ->
+ Res
+ end.
+
+%% formaterror(Tag)
+%%
+%% Purpose: Return diagnostics.
+%% Args: Tag = atom() | {error, atom()}
+%% Returns: string().
+formaterror(Tag) ->
+ errstr(Tag).
+
+%% help()
+%%
+%% Purpose: Print list of valid commands.
+%%
+%% Undocumented.
+%%
+help() ->
+ io:format("\n Commands:\n"
+ " ---------\n"
+ " cd(Pid, Dir)\n"
+ " close(Pid)\n"
+ " delete(Pid, File)\n"
+ " formaterror(Tag)\n"
+ " help()\n"
+ " lcd(Pid, Dir)\n"
+ " lpwd(Pid)\n"
+ " ls(Pid [, Dir])\n"
+ " mkdir(Pid, Dir)\n"
+ " nlist(Pid [, Dir])\n"
+ " open(Host [Port, Flags])\n"
+ " pwd(Pid)\n"
+ " recv(Pid, RFile [, LFile])\n"
+ " recv_bin(Pid, RFile)\n"
+ " recv_chunk_start(Pid, RFile)\n"
+ " recv_chunk(Pid)\n"
+ " rename(Pid, CurrFile, NewFile)\n"
+ " rmdir(Pid, Dir)\n"
+ " send(Pid, LFile [, RFile])\n"
+ " send_chunk(Pid, Bin)\n"
+ " send_chunk_start(Pid, RFile)\n"
+ " send_chunk_end(Pid)\n"
+ " send_bin(Pid, Bin, RFile)\n"
+ " append(Pid, LFile [, RFile])\n"
+ " append_chunk(Pid, Bin)\n"
+ " append_chunk_start(Pid, RFile)\n"
+ " append_chunk_end(Pid)\n"
+ " append_bin(Pid, Bin, RFile)\n"
+ " type(Pid, Type)\n"
+ " account(Pid,Account)\n"
+ " user(Pid, User, Pass)\n"
+ " user(Pid, User, Pass,Account)\n").
+
+%%
+%% INIT
+%%
+
+-record(state, {csock = undefined, dsock = undefined, flags = undefined,
+ ldir = undefined, type = undefined, chunk = false,
+ pending = undefined}).
+
+init([Flags]) ->
+ sock_start(),
+ put(debug,get_debug(Flags)),
+ put(verbose,get_verbose(Flags)),
+ process_flag(priority, low),
+ {ok, LDir} = file:get_cwd(),
+ {ok, #state{flags = Flags, ldir = LDir}}.
+
+%%
+%% HANDLERS
+%%
+
+%% First group of reply code digits
+-define(POS_PREL, 1).
+-define(POS_COMPL, 2).
+-define(POS_INTERM, 3).
+-define(TRANS_NEG_COMPL, 4).
+-define(PERM_NEG_COMPL, 5).
+
+%% Second group of reply code digits
+-define(SYNTAX,0).
+-define(INFORMATION,1).
+-define(CONNECTION,2).
+-define(AUTH_ACC,3).
+-define(UNSPEC,4).
+-define(FILE_SYSTEM,5).
+
+
+-define(STOP_RET(E),{stop, normal, {error, E},
+ State#state{csock = undefined}}).
+
+
+rescode(?POS_PREL,_,_) -> pos_prel; %%Positive Preleminary Reply
+rescode(?POS_COMPL,_,_) -> pos_compl; %%Positive Completion Reply
+rescode(?POS_INTERM,?AUTH_ACC,2) -> pos_interm_acct; %%Positive Intermediate Reply nedd account
+rescode(?POS_INTERM,_,_) -> pos_interm; %%Positive Intermediate Reply
+rescode(?TRANS_NEG_COMPL,?FILE_SYSTEM,2) -> trans_no_space; %%No storage area no action taken
+rescode(?TRANS_NEG_COMPL,_,_) -> trans_neg_compl;%%Temporary Error, no action taken
+rescode(?PERM_NEG_COMPL,?FILE_SYSTEM,2) -> perm_no_space; %%Permanent disk space error, the user shall not try again
+rescode(?PERM_NEG_COMPL,?FILE_SYSTEM,3) -> perm_fname_not_allowed;
+rescode(?PERM_NEG_COMPL,_,_) -> perm_neg_compl.
+
+retcode(trans_no_space,_) -> etnospc;
+retcode(perm_no_space,_) -> epnospc;
+retcode(perm_fname_not_allowed,_) -> efnamena;
+retcode(_,Otherwise) -> Otherwise.
+
+handle_call({open,ip_comm,Conn_data},From,State) ->
+ case lists:keysearch(host,1,Conn_data) of
+ {value,{host,Host}}->
+ Port=get_key1(port,Conn_data,?FTP_PORT),
+ Timeout=get_key1(timeout,Conn_data,?OPEN_TIMEOUT),
+ open(Host,Port,Timeout,State);
+ false ->
+ ehost
+ end;
+
+handle_call({open,ip_comm,Host,Port},From,State) ->
+ open(Host,Port,?OPEN_TIMEOUT,State);
+
+handle_call({user, User, Pass}, _From, State) ->
+ #state{csock = CSock} = State,
+ case ctrl_cmd(CSock, "USER ~s", [User]) of
+ pos_interm ->
+ case ctrl_cmd(CSock, "PASS ~s", [Pass]) of
+ pos_compl ->
+ set_type(binary, CSock),
+ {reply, ok, State#state{type = binary}};
+ {error,enotconn} ->
+ ?STOP_RET(econn);
+ _ ->
+ {reply, {error, euser}, State}
+ end;
+ pos_compl ->
+ set_type(binary, CSock),
+ {reply, ok, State#state{type = binary}};
+ {error, enotconn} ->
+ ?STOP_RET(econn);
+ _ ->
+ {reply, {error, euser}, State}
+ end;
+
+handle_call({user, User, Pass,Acc}, _From, State) ->
+ #state{csock = CSock} = State,
+ case ctrl_cmd(CSock, "USER ~s", [User]) of
+ pos_interm ->
+ case ctrl_cmd(CSock, "PASS ~s", [Pass]) of
+ pos_compl ->
+ set_type(binary, CSock),
+ {reply, ok, State#state{type = binary}};
+ pos_interm_acct->
+ case ctrl_cmd(CSock,"ACCT ~s",[Acc]) of
+ pos_compl->
+ set_type(binary, CSock),
+ {reply, ok, State#state{type = binary}};
+ {error,enotconn}->
+ ?STOP_RET(econn);
+ _ ->
+ {reply, {error, eacct}, State}
+ end;
+ {error,enotconn} ->
+ ?STOP_RET(econn);
+ _ ->
+ {reply, {error, euser}, State}
+ end;
+ pos_compl ->
+ set_type(binary, CSock),
+ {reply, ok, State#state{type = binary}};
+ {error, enotconn} ->
+ ?STOP_RET(econn);
+ _ ->
+ {reply, {error, euser}, State}
+ end;
+
+%%set_account(Acc,State)->Reply
+%%Reply={reply, {error, euser}, State} | {error,enotconn}->
+handle_call({account,Acc},_From,State)->
+ #state{csock = CSock} = State,
+ case ctrl_cmd(CSock,"ACCT ~s",[Acc]) of
+ pos_compl->
+ {reply, ok,State};
+ {error,enotconn}->
+ ?STOP_RET(econn);
+ Error ->
+ debug(" error: ~p",[Error]),
+ {reply, {error, eacct}, State}
+ end;
+
+handle_call(pwd, _From, State) when State#state.chunk == false ->
+ #state{csock = CSock} = State,
+ %%
+ %% NOTE: The directory string comes over the control connection.
+ case sock_write(CSock, mk_cmd("PWD", [])) of
+ ok ->
+ {_, Line} = result_line(CSock),
+ {_, Cs} = split($", Line), % XXX Ugly
+ {Dir0, _} = split($", Cs),
+ Dir = lists:delete($", Dir0),
+ {reply, {ok, Dir}, State};
+ {error, enotconn} ->
+ ?STOP_RET(econn)
+ end;
+
+handle_call(lpwd, _From, State) ->
+ #state{csock = CSock, ldir = LDir} = State,
+ {reply, {ok, LDir}, State};
+
+handle_call({cd, Dir}, _From, State) when State#state.chunk == false ->
+ #state{csock = CSock} = State,
+ case ctrl_cmd(CSock, "CWD ~s", [Dir]) of
+ pos_compl ->
+ {reply, ok, State};
+ {error, enotconn} ->
+ ?STOP_RET(econn);
+ _ ->
+ {reply, {error, epath}, State}
+ end;
+
+handle_call({lcd, Dir}, _From, State) ->
+ #state{csock = CSock, ldir = LDir0} = State,
+ LDir = absname(LDir0, Dir),
+ case file:read_file_info(LDir) of
+ {ok, _ } ->
+ {reply, ok, State#state{ldir = LDir}};
+ _ ->
+ {reply, {error, epath}, State}
+ end;
+
+handle_call({dir, Len, Dir}, _From, State) when State#state.chunk == false ->
+ debug(" dir : ~p: ~s~n",[Len,Dir]),
+ #state{csock = CSock, type = Type} = State,
+ set_type(ascii, Type, CSock),
+ LSock = listen_data(CSock, raw),
+ Cmd = case Len of
+ short -> "NLST";
+ long -> "LIST"
+ end,
+ Result = case Dir of
+ "" ->
+ ctrl_cmd(CSock, Cmd, "");
+ _ ->
+ ctrl_cmd(CSock, Cmd ++ " ~s", [Dir])
+ end,
+ debug(" ctrl : command result: ~p~n",[Result]),
+ case Result of
+ pos_prel ->
+ debug(" dbg : await the data connection", []),
+ DSock = accept_data(LSock),
+ debug(" dbg : await the data", []),
+ Reply0 =
+ case recv_data(DSock) of
+ {ok, DirData} ->
+ debug(" data : DirData: ~p~n",[DirData]),
+ case result(CSock) of
+ pos_compl ->
+ {ok, DirData};
+ _ ->
+ {error, epath}
+ end;
+ {error, Reason} ->
+ sock_close(DSock),
+ verbose(" data : error: ~p, ~p~n",[Reason, result(CSock)]),
+ {error, epath}
+ end,
+
+ debug(" ctrl : reply: ~p~n",[Reply0]),
+ reset_type(ascii, Type, CSock),
+ {reply, Reply0, State};
+ {closed, _Why} ->
+ ?STOP_RET(econn);
+ _ ->
+ sock_close(LSock),
+ {reply, {error, epath}, State}
+ end;
+
+
+handle_call({rename, CurrFile, NewFile}, _From, State) when State#state.chunk == false ->
+ #state{csock = CSock} = State,
+ case ctrl_cmd(CSock, "RNFR ~s", [CurrFile]) of
+ pos_interm ->
+ case ctrl_cmd(CSock, "RNTO ~s", [NewFile]) of
+ pos_compl ->
+ {reply, ok, State};
+ _ ->
+ {reply, {error, epath}, State}
+ end;
+ {error, enotconn} ->
+ ?STOP_RET(econn);
+ _ ->
+ {reply, {error, epath}, State}
+ end;
+
+handle_call({delete, File}, _From, State) when State#state.chunk == false ->
+ #state{csock = CSock} = State,
+ case ctrl_cmd(CSock, "DELE ~s", [File]) of
+ pos_compl ->
+ {reply, ok, State};
+ {error, enotconn} ->
+ ?STOP_RET(econn);
+ _ ->
+ {reply, {error, epath}, State}
+ end;
+
+handle_call({mkdir, Dir}, _From, State) when State#state.chunk == false ->
+ #state{csock = CSock} = State,
+ case ctrl_cmd(CSock, "MKD ~s", [Dir]) of
+ pos_compl ->
+ {reply, ok, State};
+ {error, enotconn} ->
+ ?STOP_RET(econn);
+ _ ->
+ {reply, {error, epath}, State}
+ end;
+
+handle_call({rmdir, Dir}, _From, State) when State#state.chunk == false ->
+ #state{csock = CSock} = State,
+ case ctrl_cmd(CSock, "RMD ~s", [Dir]) of
+ pos_compl ->
+ {reply, ok, State};
+ {error, enotconn} ->
+ ?STOP_RET(econn);
+ _ ->
+ {reply, {error, epath}, State}
+ end;
+
+handle_call({type, Type}, _From, State) when State#state.chunk == false ->
+ #state{csock = CSock} = State,
+ case Type of
+ ascii ->
+ set_type(ascii, CSock),
+ {reply, ok, State#state{type = ascii}};
+ binary ->
+ set_type(binary, CSock),
+ {reply, ok, State#state{type = binary}};
+ _ ->
+ {reply, {error, etype}, State}
+ end;
+
+handle_call({recv, RFile, LFile}, _From, State) when State#state.chunk == false ->
+ #state{csock = CSock, ldir = LDir} = State,
+ ALFile = case LFile of
+ "" ->
+ absname(LDir, RFile);
+ _ ->
+ absname(LDir, LFile)
+ end,
+ case file_open(ALFile, write) of
+ {ok, Fd} ->
+ LSock = listen_data(CSock, binary),
+ Ret = case ctrl_cmd(CSock, "RETR ~s", [RFile]) of
+ pos_prel ->
+ DSock = accept_data(LSock),
+ recv_file(DSock, Fd),
+ Reply0 = case result(CSock) of
+ pos_compl ->
+ ok;
+ _ ->
+ {error, epath}
+ end,
+ sock_close(DSock),
+ {reply, Reply0, State};
+ {error, enotconn} ->
+ ?STOP_RET(econn);
+ _ ->
+ {reply, {error, epath}, State}
+ end,
+ file_close(Fd),
+ Ret;
+ {error, _What} ->
+ {reply, {error, epath}, State}
+ end;
+
+handle_call({recv_bin, RFile}, _From, State) when State#state.chunk == false ->
+ #state{csock = CSock, ldir = LDir} = State,
+ LSock = listen_data(CSock, binary),
+ case ctrl_cmd(CSock, "RETR ~s", [RFile]) of
+ pos_prel ->
+ DSock = accept_data(LSock),
+ Reply = recv_binary(DSock,CSock),
+ sock_close(DSock),
+ {reply, Reply, State};
+ {error, enotconn} ->
+ ?STOP_RET(econn);
+ _ ->
+ {reply, {error, epath}, State}
+ end;
+
+
+handle_call({recv_chunk_start, RFile}, _From, State)
+ when State#state.chunk == false ->
+ start_chunk_transfer("RETR",RFile,State);
+
+handle_call(recv_chunk, _From, State)
+ when State#state.chunk == true ->
+ do_recv_chunk(State);
+
+
+handle_call({send, LFile, RFile}, _From, State)
+ when State#state.chunk == false ->
+ transfer_file("STOR",LFile,RFile,State);
+
+handle_call({append, LFile, RFile}, _From, State)
+ when State#state.chunk == false ->
+ transfer_file("APPE",LFile,RFile,State);
+
+
+handle_call({send_bin, Bin, RFile}, _From, State)
+ when State#state.chunk == false ->
+ transfer_data("STOR",Bin,RFile,State);
+
+handle_call({append_bin, Bin, RFile}, _From, State)
+ when State#state.chunk == false ->
+ transfer_data("APPE",Bin,RFile,State);
+
+
+
+handle_call({send_chunk_start, RFile}, _From, State)
+ when State#state.chunk == false ->
+ start_chunk_transfer("STOR",RFile,State);
+
+handle_call({append_chunk_start,RFile},_From,State)
+ when State#state.chunk==false->
+ start_chunk_transfer("APPE",RFile,State);
+
+handle_call({send_chunk, Bin}, _From, State)
+ when State#state.chunk == true ->
+ chunk_transfer(Bin,State);
+
+handle_call({append_chunk, Bin}, _From, State)
+ when State#state.chunk == true ->
+ chunk_transfer(Bin,State);
+
+handle_call(append_chunk_end, _From, State)
+ when State#state.chunk == true ->
+ end_chunk_transfer(State);
+
+handle_call(send_chunk_end, _From, State)
+ when State#state.chunk == true ->
+ end_chunk_transfer(State);
+
+
+
+handle_call(close, _From, State) when State#state.chunk == false ->
+ #state{csock = CSock} = State,
+ ctrl_cmd(CSock, "QUIT", []),
+ sock_close(CSock),
+ {stop, normal, ok, State};
+
+handle_call(_, _From, State) when State#state.chunk == true ->
+ {reply, {error, echunk}, State}.
+
+
+handle_cast(Msg, State) ->
+ {noreply, State}.
+
+
+handle_info({Sock, {fromsocket, Bytes}}, State) when Sock == State#state.csock ->
+ put(leftovers, Bytes ++ leftovers()),
+ {noreply, State};
+
+%% Data connection closed (during chunk sending)
+handle_info({Sock, {socket_closed, _Reason}}, State) when Sock == State#state.dsock ->
+ {noreply, State#state{dsock = undefined}};
+
+%% Control connection closed.
+handle_info({Sock, {socket_closed, _Reason}}, State) when Sock == State#state.csock ->
+ debug(" sc : ~s~n",[leftovers()]),
+ {stop, ftp_server_close, State#state{csock = undefined}};
+
+handle_info(Info, State) ->
+ error_logger:info_msg("ftp : ~w : Unexpected message: ~w\n", [self(),Info]),
+ {noreply, State}.
+
+code_change(OldVsn,State,Extra)->
+ {ok,State}.
+
+terminate(Reason, State) ->
+ ok.
+%%
+%% OPEN CONNECTION
+%%
+open(Host,Port,Timeout,State)->
+ case sock_connect(Host,Port,Timeout) of
+ {error, What} ->
+ {stop, normal, {error, What}, State};
+ CSock ->
+ case result(CSock, State#state.flags) of
+ {error,Reason} ->
+ sock_close(CSock),
+ {stop,normal,{error,Reason},State};
+ _ -> % We should really check this...
+ {reply, {ok, self()}, State#state{csock = CSock}}
+ end
+ end.
+
+
+
+%%
+%% CONTROL CONNECTION
+%%
+
+ctrl_cmd(CSock, Fmt, Args) ->
+ Cmd = mk_cmd(Fmt, Args),
+ case sock_write(CSock, Cmd) of
+ ok ->
+ debug(" cmd : ~s",[Cmd]),
+ result(CSock);
+ {error, enotconn} ->
+ {error, enotconn};
+ Other ->
+ Other
+ end.
+
+mk_cmd(Fmt, Args) ->
+ [io_lib:format(Fmt, Args)| "\r\n"]. % Deep list ok.
+
+%%
+%% TRANSFER TYPE
+%%
+
+%%
+%% set_type(NewType, CurrType, CSock)
+%% reset_type(NewType, CurrType, CSock)
+%%
+set_type(Type, Type, CSock) ->
+ ok;
+set_type(NewType, _OldType, CSock) ->
+ set_type(NewType, CSock).
+
+reset_type(Type, Type, CSock) ->
+ ok;
+reset_type(_NewType, OldType, CSock) ->
+ set_type(OldType, CSock).
+
+set_type(ascii, CSock) ->
+ ctrl_cmd(CSock, "TYPE A", []);
+set_type(binary, CSock) ->
+ ctrl_cmd(CSock, "TYPE I", []).
+
+%%
+%% DATA CONNECTION
+%%
+
+%% Create a listen socket for a data connection and send a PORT command
+%% containing the IP address and port number. Mode is binary or raw.
+%%
+listen_data(CSock, Mode) ->
+ {IP, _} = sock_name(CSock), % IP address of control conn.
+ LSock = sock_listen(Mode, IP),
+ Port = sock_listen_port(LSock),
+ {A1, A2, A3, A4} = IP,
+ {P1, P2} = {Port div 256, Port rem 256},
+ ctrl_cmd(CSock, "PORT ~w,~w,~w,~w,~w,~w", [A1, A2, A3, A4, P1, P2]),
+ LSock.
+
+%%
+%% Accept the data connection and close the listen socket.
+%%
+accept_data(LSock) ->
+ Sock = sock_accept(LSock),
+ sock_close(LSock),
+ Sock.
+
+%%
+%% DATA COLLECTION (ls, dir)
+%%
+%% Socket is a byte stream in ASCII mode.
+%%
+
+%% Receive data (from data connection).
+recv_data(Sock) ->
+ recv_data(Sock, [], 0).
+recv_data(Sock, Sofar, ?OPER_TIMEOUT) ->
+ sock_close(Sock),
+ {ok, lists:flatten(lists:reverse(Sofar))};
+recv_data(Sock, Sofar, Retry) ->
+ case sock_read(Sock) of
+ {ok, Data} ->
+ debug(" dbg : received some data: ~n~s", [Data]),
+ recv_data(Sock, [Data| Sofar], 0);
+ {error, timeout} ->
+ %% Retry..
+ recv_data(Sock, Sofar, Retry+1);
+ {error, Reason} ->
+ SoFar1 = lists:flatten(lists:reverse(Sofar)),
+ {error, {socket_error, Reason, SoFar1, Retry}};
+ {closed, _} ->
+ {ok, lists:flatten(lists:reverse(Sofar))}
+ end.
+
+%%
+%% BINARY TRANSFER
+%%
+
+%% --------------------------------------------------
+
+%% recv_binary(DSock,CSock) = {ok,Bin} | {error,Reason}
+%%
+recv_binary(DSock,CSock) ->
+ recv_binary1(recv_binary2(DSock,[],0),CSock).
+
+recv_binary1(Reply,Sock) ->
+ case result(Sock) of
+ pos_compl -> Reply;
+ _ -> {error, epath}
+ end.
+
+recv_binary2(Sock, _Bs, ?OPER_TIMEOUT) ->
+ sock_close(Sock),
+ {error,eclosed};
+recv_binary2(Sock, Bs, Retry) ->
+ case sock_read(Sock) of
+ {ok, Bin} ->
+ recv_binary2(Sock, [Bs, Bin], 0);
+ {error, timeout} ->
+ recv_binary2(Sock, Bs, Retry+1);
+ {closed, _Why} ->
+ {ok,list_to_binary(Bs)}
+ end.
+
+%% --------------------------------------------------
+
+%%
+%% recv_chunk
+%%
+
+do_recv_chunk(#state{dsock = undefined} = State) ->
+ {reply, {error,econn}, State};
+do_recv_chunk(State) ->
+ recv_chunk1(recv_chunk2(State, 0), State).
+
+recv_chunk1({ok, _Bin} = Reply, State) ->
+ {reply, Reply, State};
+%% Reply = ok | {error, Reason}
+recv_chunk1(Reply, #state{csock = CSock} = State) ->
+ State1 = State#state{dsock = undefined, chunk = false},
+ case result(CSock) of
+ pos_compl ->
+ {reply, Reply, State1};
+ _ ->
+ {reply, {error, epath}, State1}
+ end.
+
+recv_chunk2(#state{dsock = DSock} = State, ?OPER_TIMEOUT) ->
+ sock_close(DSock),
+ {error, eclosed};
+recv_chunk2(#state{dsock = DSock} = State, Retry) ->
+ case sock_read(DSock) of
+ {ok, Bin} ->
+ {ok, Bin};
+ {error, timeout} ->
+ recv_chunk2(State, Retry+1);
+ {closed, Reason} ->
+ debug(" dbg : socket closed: ~p", [Reason]),
+ ok
+ end.
+
+
+%% --------------------------------------------------
+
+%%
+%% FILE TRANSFER
+%%
+
+recv_file(Sock, Fd) ->
+ recv_file(Sock, Fd, 0).
+
+recv_file(Sock, Fd, ?OPER_TIMEOUT) ->
+ sock_close(Sock),
+ {closed, timeout};
+recv_file(Sock, Fd, Retry) ->
+ case sock_read(Sock) of
+ {ok, Bin} ->
+ file_write(Fd, Bin),
+ recv_file(Sock, Fd);
+ {error, timeout} ->
+ recv_file(Sock, Fd, Retry+1);
+% {error, Reason} ->
+% SoFar1 = lists:flatten(lists:reverse(Sofar)),
+% exit({socket_error, Reason, Sock, SoFar1, Retry});
+ {closed, How} ->
+ {closed, How}
+ end.
+
+%%
+%% send_file(Fd, Sock) = ok | {error, Why}
+%%
+
+send_file(Fd, Sock) ->
+ {N, Bin} = file_read(Fd),
+ if
+ N > 0 ->
+ case sock_write(Sock, Bin) of
+ ok ->
+ send_file(Fd, Sock);
+ {error, Reason} ->
+ {error, Reason}
+ end;
+ true ->
+ ok
+ end.
+
+
+
+%%
+%% PARSING OF RESULT LINES
+%%
+
+%% Excerpt from RFC 959:
+%%
+%% "A reply is defined to contain the 3-digit code, followed by Space
+%% <SP>, followed by one line of text (where some maximum line length
+%% has been specified), and terminated by the Telnet end-of-line
+%% code. There will be cases however, where the text is longer than
+%% a single line. In these cases the complete text must be bracketed
+%% so the User-process knows when it may stop reading the reply (i.e.
+%% stop processing input on the control connection) and go do other
+%% things. This requires a special format on the first line to
+%% indicate that more than one line is coming, and another on the
+%% last line to designate it as the last. At least one of these must
+%% contain the appropriate reply code to indicate the state of the
+%% transaction. To satisfy all factions, it was decided that both
+%% the first and last line codes should be the same.
+%%
+%% Thus the format for multi-line replies is that the first line
+%% will begin with the exact required reply code, followed
+%% immediately by a Hyphen, "-" (also known as Minus), followed by
+%% text. The last line will begin with the same code, followed
+%% immediately by Space <SP>, optionally some text, and the Telnet
+%% end-of-line code.
+%%
+%% For example:
+%% 123-First line
+%% Second line
+%% 234 A line beginning with numbers
+%% 123 The last line
+%%
+%% The user-process then simply needs to search for the second
+%% occurrence of the same reply code, followed by <SP> (Space), at
+%% the beginning of a line, and ignore all intermediary lines. If
+%% an intermediary line begins with a 3-digit number, the Server
+%% must pad the front to avoid confusion.
+%%
+%% This scheme allows standard system routines to be used for
+%% reply information (such as for the STAT reply), with
+%% "artificial" first and last lines tacked on. In rare cases
+%% where these routines are able to generate three digits and a
+%% Space at the beginning of any line, the beginning of each
+%% text line should be offset by some neutral text, like Space.
+%%
+%% This scheme assumes that multi-line replies may not be nested."
+
+%% We have to collect the stream of result characters into lines (ending
+%% in "\r\n"; we check for "\n"). When a line is assembled, left-over
+%% characters are saved in the process dictionary.
+%%
+
+%% result(Sock) = rescode()
+%%
+result(Sock) ->
+ result(Sock, false).
+
+result_line(Sock) ->
+ result(Sock, true).
+
+%% result(Sock, Bool) = {error,Reason} | rescode() | {rescode(), Lines}
+%% Printout if Bool = true.
+%%
+result(Sock, RetForm) ->
+ case getline(Sock) of
+ Line when length(Line) > 3 ->
+ [D1, D2, D3| Tail] = Line,
+ case Tail of
+ [$-| _] ->
+ parse_to_end(Sock, [D1, D2, D3, $ ]); % 3 digits + space
+ _ ->
+ ok
+ end,
+ result(D1,D2,D3,Line,RetForm);
+ _ ->
+ retform(rescode(?PERM_NEG_COMPL,-1,-1),[],RetForm)
+ end.
+
+result(D1,_D2,_D3,Line,_RetForm) when D1 - $0 > 10 ->
+ {error,{invalid_server_response,Line}};
+result(D1,_D2,_D3,Line,_RetForm) when D1 - $0 < 0 ->
+ {error,{invalid_server_response,Line}};
+result(D1,D2,D3,Line,RetForm) ->
+ Res1 = D1 - $0,
+ Res2 = D2 - $0,
+ Res3 = D3 - $0,
+ verbose(" ~w : ~s", [Res1, Line]),
+ retform(rescode(Res1,Res2,Res3),Line,RetForm).
+
+retform(ResCode,Line,true) ->
+ {ResCode,Line};
+retform(ResCode,_,_) ->
+ ResCode.
+
+leftovers() ->
+ case get(leftovers) of
+ undefined -> [];
+ X -> X
+ end.
+
+%% getline(Sock) = Line
+%%
+getline(Sock) ->
+ getline(Sock, leftovers()).
+
+getline(Sock, Rest) ->
+ getline1(Sock, split($\n, Rest), 0).
+
+getline1(Sock, {[], Rest}, ?OPER_TIMEOUT) ->
+ sock_close(Sock),
+ put(leftovers, Rest),
+ [];
+getline1(Sock, {[], Rest}, Retry) ->
+ case sock_read(Sock) of
+ {ok, More} ->
+ debug(" read : ~s~n",[More]),
+ getline(Sock, Rest ++ More);
+ {error, timeout} ->
+ %% Retry..
+ getline1(Sock, {[], Rest}, Retry+1);
+ Error ->
+ put(leftovers, Rest),
+ []
+ end;
+getline1(Sock, {Line, Rest}, Retry) ->
+ put(leftovers, Rest),
+ Line.
+
+parse_to_end(Sock, Prefix) ->
+ Line = getline(Sock),
+ case lists:prefix(Prefix, Line) of
+ false ->
+ parse_to_end(Sock, Prefix);
+ true ->
+ ok
+ end.
+
+
+%% Split list after first occurence of S.
+%% Returns {Prefix, Suffix} ({[], Cs} if S not found).
+split(S, Cs) ->
+ split(S, Cs, []).
+
+split(S, [S| Cs], As) ->
+ {lists:reverse([S|As]), Cs};
+split(S, [C| Cs], As) ->
+ split(S, Cs, [C| As]);
+split(_, [], As) ->
+ {[], lists:reverse(As)}.
+
+%%
+%% FILE INTERFACE
+%%
+%% All files are opened raw in binary mode.
+%%
+-define(BUFSIZE, 4096).
+
+file_open(File, Option) ->
+ file:open(File, [raw, binary, Option]).
+
+file_close(Fd) ->
+ file:close(Fd).
+
+
+file_read(Fd) -> % Compatible with pre R2A.
+ case file:read(Fd, ?BUFSIZE) of
+ {ok, {N, Bytes}} ->
+ {N, Bytes};
+ {ok, Bytes} ->
+ {size(Bytes), Bytes};
+ eof ->
+ {0, []}
+ end.
+
+file_write(Fd, Bytes) ->
+ file:write(Fd, Bytes).
+
+absname(Dir, File) -> % Args swapped.
+ filename:absname(File, Dir).
+
+
+
+%% sock_start()
+%%
+
+%%
+%% USE GEN_TCP
+%%
+
+sock_start() ->
+ inet_db:start().
+
+%%
+%% Connect to FTP server at Host (default is TCP port 21) in raw mode,
+%% in order to establish a control connection.
+%%
+
+sock_connect(Host,Port,TimeOut) ->
+ debug(" info : connect to server on ~p:~p~n",[Host,Port]),
+ Opts = [{packet, 0}, {active, false}],
+ case (catch gen_tcp:connect(Host, Port, Opts,TimeOut)) of
+ {'EXIT', R1} -> % XXX Probably no longer needed.
+ debug(" error: socket connectionn failed with exit reason:"
+ "~n ~p",[R1]),
+ {error, ehost};
+ {error, R2} ->
+ debug(" error: socket connectionn failed with exit reason:"
+ "~n ~p",[R2]),
+ {error, ehost};
+ {ok, Sock} ->
+ Sock
+ end.
+
+%%
+%% Create a listen socket (any port) in binary or raw non-packet mode for
+%% data connection.
+%%
+sock_listen(Mode, IP) ->
+ Opts = case Mode of
+ binary ->
+ [binary, {packet, 0}];
+ raw ->
+ [{packet, 0}]
+ end,
+ {ok, Sock} = gen_tcp:listen(0, [{ip, IP}, {active, false} | Opts]),
+ Sock.
+
+sock_accept(LSock) ->
+ {ok, Sock} = gen_tcp:accept(LSock),
+ Sock.
+
+sock_close(undefined) ->
+ ok;
+sock_close(Sock) ->
+ gen_tcp:close(Sock).
+
+sock_read(Sock) ->
+ case gen_tcp:recv(Sock, 0, ?BYTE_TIMEOUT) of
+ {ok, Bytes} ->
+ {ok, Bytes};
+
+ {error, closed} ->
+ {closed, closed}; % Yes
+
+ %% --- OTP-4770 begin ---
+ %%
+ %% This seems to happen on windows
+ %% "Someone" tried to close an already closed socket...
+ %%
+
+ {error, enotsock} ->
+ {closed, enotsock};
+
+ %%
+ %% --- OTP-4770 end ---
+
+ {error, etimedout} ->
+ {error, timeout};
+
+ Other ->
+ Other
+ end.
+
+%% receive
+%% {tcp, Sock, Bytes} ->
+%% {ok, Bytes};
+%% {tcp_closed, Sock} ->
+%% {closed, closed}
+%% end.
+
+sock_write(Sock, Bytes) ->
+ gen_tcp:send(Sock, Bytes).
+
+sock_name(Sock) ->
+ {ok, {IP, Port}} = inet:sockname(Sock),
+ {IP, Port}.
+
+sock_listen_port(LSock) ->
+ {ok, Port} = inet:port(LSock),
+ Port.
+
+
+%%
+%% ERROR STRINGS
+%%
+errstr({error, Reason}) ->
+ errstr(Reason);
+
+errstr(echunk) -> "Synchronisation error during chung sending.";
+errstr(eclosed) -> "Session has been closed.";
+errstr(econn) -> "Connection to remote server prematurely closed.";
+errstr(eexists) ->"File or directory already exists.";
+errstr(ehost) -> "Host not found, FTP server not found, "
+"or connection rejected.";
+errstr(elogin) -> "User not logged in.";
+errstr(enotbinary) -> "Term is not a binary.";
+errstr(epath) -> "No such file or directory, already exists, "
+"or permission denied.";
+errstr(etype) -> "No such type.";
+errstr(euser) -> "User name or password not valid.";
+errstr(etnospc) -> "Insufficient storage space in system.";
+errstr(epnospc) -> "Exceeded storage allocation "
+"(for current directory or dataset).";
+errstr(efnamena) -> "File name not allowed.";
+errstr(Reason) ->
+ lists:flatten(io_lib:format("Unknown error: ~w", [Reason])).
+
+
+
+%% ----------------------------------------------------------
+
+get_verbose(Params) -> check_param(verbose,Params).
+
+get_debug(Flags) -> check_param(debug,Flags).
+
+check_param(P,Ps) -> lists:member(P,Ps).
+
+
+%% verbose -> ok
+%%
+%% Prints the string if the Flags list is non-epmty
+%%
+%% Params: F Format string
+%% A Arguments to the format string
+%%
+verbose(F,A) -> verbose(get(verbose),F,A).
+
+verbose(true,F,A) -> print(F,A);
+verbose(_,_F,_A) -> ok.
+
+
+
+
+%% debug -> ok
+%%
+%% Prints the string if debug enabled
+%%
+%% Params: F Format string
+%% A Arguments to the format string
+%%
+debug(F,A) -> debug(get(debug),F,A).
+
+debug(true,F,A) -> print(F,A);
+debug(_,_F,_A) -> ok.
+
+
+print(F,A) -> io:format(F,A).
+
+
+
+transfer_file(Cmd,LFile,RFile,State)->
+ #state{csock = CSock, ldir = LDir} = State,
+ ARFile = case RFile of
+ "" ->
+ LFile;
+ _ ->
+ RFile
+ end,
+ ALFile = absname(LDir, LFile),
+ case file_open(ALFile, read) of
+ {ok, Fd} ->
+ LSock = listen_data(CSock, binary),
+ case ctrl_cmd(CSock, "~s ~s", [Cmd,ARFile]) of
+ pos_prel ->
+ DSock = accept_data(LSock),
+ SFreply = send_file(Fd, DSock),
+ file_close(Fd),
+ sock_close(DSock),
+ case {SFreply,result(CSock)} of
+ {ok,pos_compl} ->
+ {reply, ok, State};
+ {ok,Other} ->
+ debug(" error: unknown reply: ~p~n",[Other]),
+ {reply, {error, epath}, State};
+ {{error,Why},Result} ->
+ ?STOP_RET(retcode(Result,econn))
+ end;
+ {error, enotconn} ->
+ ?STOP_RET(econn);
+ Other ->
+ debug(" error: ctrl failed: ~p~n",[Other]),
+ {reply, {error, epath}, State}
+ end;
+ {error, Reason} ->
+ debug(" error: file open: ~p~n",[Reason]),
+ {reply, {error, epath}, State}
+ end.
+
+transfer_data(Cmd,Bin,RFile,State)->
+ #state{csock = CSock, ldir = LDir} = State,
+ LSock = listen_data(CSock, binary),
+ case ctrl_cmd(CSock, "~s ~s", [Cmd,RFile]) of
+ pos_prel ->
+ DSock = accept_data(LSock),
+ SReply = sock_write(DSock, Bin),
+ sock_close(DSock),
+ case {SReply,result(CSock)} of
+ {ok,pos_compl} ->
+ {reply, ok, State};
+ {ok,trans_no_space} ->
+ ?STOP_RET(etnospc);
+ {ok,perm_no_space} ->
+ ?STOP_RET(epnospc);
+ {ok,perm_fname_not_allowed} ->
+ ?STOP_RET(efnamena);
+ {ok,Other} ->
+ debug(" error: unknown reply: ~p~n",[Other]),
+ {reply, {error, epath}, State};
+ {{error,Why},Result} ->
+ ?STOP_RET(retcode(Result,econn))
+ %% {{error,_Why},_Result} ->
+ %% ?STOP_RET(econn)
+ end;
+
+ {error, enotconn} ->
+ ?STOP_RET(econn);
+
+ Other ->
+ debug(" error: ctrl failed: ~p~n",[Other]),
+ {reply, {error, epath}, State}
+ end.
+
+
+start_chunk_transfer(Cmd, RFile, #state{csock = CSock} = State) ->
+ LSock = listen_data(CSock, binary),
+ case ctrl_cmd(CSock, "~s ~s", [Cmd,RFile]) of
+ pos_prel ->
+ DSock = accept_data(LSock),
+ {reply, ok, State#state{dsock = DSock, chunk = true}};
+ {error, enotconn} ->
+ ?STOP_RET(econn);
+ Otherwise ->
+ debug(" error: ctrl failed: ~p~n",[Otherwise]),
+ {reply, {error, epath}, State}
+ end.
+
+
+chunk_transfer(Bin,State)->
+ #state{dsock = DSock, csock = CSock} = State,
+ case DSock of
+ undefined ->
+ {reply,{error,econn},State};
+ _ ->
+ case sock_write(DSock, Bin) of
+ ok ->
+ {reply, ok, State};
+ Other ->
+ debug(" error: chunk write error: ~p~n",[Other]),
+ {reply, {error, econn}, State#state{dsock = undefined}}
+ end
+ end.
+
+
+
+end_chunk_transfer(State)->
+ #state{csock = CSock, dsock = DSock} = State,
+ case DSock of
+ undefined ->
+ Result = result(CSock),
+ case Result of
+ pos_compl ->
+ {reply,ok,State#state{dsock = undefined,
+ chunk = false}};
+ trans_no_space ->
+ ?STOP_RET(etnospc);
+ perm_no_space ->
+ ?STOP_RET(epnospc);
+ perm_fname_not_allowed ->
+ ?STOP_RET(efnamena);
+ Result ->
+ debug(" error: send chunk end (1): ~p~n",
+ [Result]),
+ {reply,{error,epath},State#state{dsock = undefined,
+ chunk = false}}
+ end;
+ _ ->
+ sock_close(DSock),
+ Result = result(CSock),
+ case Result of
+ pos_compl ->
+ {reply,ok,State#state{dsock = undefined,
+ chunk = false}};
+ trans_no_space ->
+ sock_close(CSock),
+ ?STOP_RET(etnospc);
+ perm_no_space ->
+ sock_close(CSock),
+ ?STOP_RET(epnospc);
+ perm_fname_not_allowed ->
+ sock_close(CSock),
+ ?STOP_RET(efnamena);
+ Result ->
+ debug(" error: send chunk end (2): ~p~n",
+ [Result]),
+ {reply,{error,epath},State#state{dsock = undefined,
+ chunk = false}}
+ end
+ end.
+
+get_key1(Key,List,Default)->
+ case lists:keysearch(Key,1,List)of
+ {value,{_,Val}}->
+ Val;
+ false->
+ Default
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/http.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/http.erl
new file mode 100644
index 0000000000..a732f23aec
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/http.erl
@@ -0,0 +1,260 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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 Mobile Arts AB
+%% Portions created by Mobile Arts are Copyright 2002, Mobile Arts AB
+%% All Rights Reserved.''
+%%
+%%
+
+%%% This version of the HTTP/1.1 client implements:
+%%% - RFC 2616 HTTP 1.1 client part
+%%% - RFC 2817 Upgrading to TLS Within HTTP/1.1 (not yet!)
+%%% - RFC 2818 HTTP Over TLS
+%%% - RFC 3229 Delta encoding in HTTP (not yet!)
+%%% - RFC 3230 Instance Digests in HTTP (not yet!)
+%%% - RFC 3310 Authentication and Key Agreement (AKA) (not yet!)
+%%% - HTTP/1.1 Specification Errata found at
+%%% http://world.std.com/~lawrence/http_errata.html
+%%% Additionaly follows the following recommendations:
+%%% - RFC 3143 Known HTTP Proxy/Caching Problems (not yet!)
+%%% - draft-nottingham-hdrreg-http-00.txt (not yet!)
+%%%
+%%% Depends on
+%%% - uri.erl for all URL parsing (except what is handled by the C driver)
+%%% - http_lib.erl for all parsing of body and headers
+%%%
+%%% Supported Settings are:
+%%% http_timeout % (int) Milliseconds before a request times out
+%%% http_useproxy % (bool) True if a proxy should be used
+%%% http_proxy % (string) Proxy
+%%% http_noproxylist % (list) List with hosts not requiring proxy
+%%% http_autoredirect % (bool) True if automatic redirection on 30X responses
+%%% http_ssl % (list) SSL settings. A non-empty list enables SSL/TLS
+%%% support in the HTTP client
+%%% http_pipelinesize % (int) Length of pipeline. 1 means no pipeline.
+%%% Only has effect when initiating a new session.
+%%% http_sessions % (int) Max number of open sessions for {Addr,Port}
+%%%
+%%% TODO: (Known bugs!)
+%% - Cache handling
+%% - Doesn't handle a bunch of entity headers properly
+%% - Better handling of status codes different from 200,30X and 50X
+%% - Many of the settings above are not implemented!
+%% - close_session/2 and cancel_request/1 doesn't work
+%% - Variable pipe size.
+%% - Due to the fact that inet_drv only has a single timer, the timeouts given
+%% for pipelined requests are not ok (too long)
+%%
+%% Note:
+%% - Some servers (e.g. Microsoft-IIS/5.0) may sometimes not return a proper
+%% 'Location' header on a redirect.
+%% The client will fail with {error,no_scheme} in these cases.
+
+-module(http).
+-author("[email protected]").
+
+-export([start/0,
+ request/3,request/4,cancel_request/1,
+ request_sync/2,request_sync/3]).
+
+-include("http.hrl").
+-include("jnets_httpd.hrl").
+
+-define(START_OPTIONS,[]).
+
+%%% HTTP Client manager. Used to store open connections.
+%%% Will be started automatically unless started explicitly.
+start() ->
+ application:start(ssl),
+ httpc_manager:start().
+
+%%% Asynchronous HTTP request that spawns a handler.
+%%% Method HTTPReq
+%%% options,get,head,delete,trace = {Url,Headers}
+%%% post,put = {Url,Headers,ContentType,Body}
+%%% where Url is a {Scheme,Host,Port,PathQuery} tuple, as returned by uri.erl
+%%%
+%%% Returns: {ok,ReqId} |
+%%% {error,Reason}
+%%% If {ok,Pid} was returned, the handler will return with
+%%% gen_server:cast(From,{Ref,ReqId,{error,Reason}}) |
+%%% gen_server:cast(From,{Ref,ReqId,{Status,Headers,Body}})
+%%% where Reason is an atom and Headers a #res_headers{} record
+%%% http:format_error(Reason) gives a more informative description.
+%%%
+%%% Note:
+%%% - Always try to find an open connection to a given host and port, and use
+%%% the associated socket.
+%%% - Unless a 'Connection: close' header is provided don't close the socket
+%%% after a response is given
+%%% - A given Pid, found in the database, might be terminated before the
+%%% message is sent to the Pid. This will happen e.g., if the connection is
+%%% closed by the other party and there are no pending requests.
+%%% - The HTTP connection process is spawned, if necessary, in
+%%% httpc_manager:add_connection/4
+request(Ref,Method,HTTPReqCont) ->
+ request(Ref,Method,HTTPReqCont,[],self()).
+
+request(Ref,Method,HTTPReqCont,Settings) ->
+ request(Ref,Method,HTTPReqCont,Settings,self()).
+
+request(Ref,Method,{{Scheme,Host,Port,PathQuery},
+ Headers,ContentType,Body},Settings,From) ->
+ case create_settings(Settings,#client_settings{}) of
+ {error,Reason} ->
+ {error,Reason};
+ CS ->
+ case create_headers(Headers,#req_headers{}) of
+ {error,Reason} ->
+ {error,Reason};
+ H ->
+ Req=#request{ref=Ref,from=From,
+ scheme=Scheme,address={Host,Port},
+ pathquery=PathQuery,method=Method,
+ headers=H,content={ContentType,Body},
+ settings=CS},
+ httpc_manager:request(Req)
+ end
+ end;
+request(Ref,Method,{Url,Headers},Settings,From) ->
+ request(Ref,Method,{Url,Headers,[],[]},Settings,From).
+
+%%% Cancels requests identified with ReqId.
+%%% FIXME! Doesn't work...
+cancel_request(ReqId) ->
+ httpc_manager:cancel_request(ReqId).
+
+%%% Close all sessions currently open to Host:Port
+%%% FIXME! Doesn't work...
+close_session(Host,Port) ->
+ httpc_manager:close_session(Host,Port).
+
+
+%%% Synchronous HTTP request that waits until a response is created
+%%% (e.g. successfull reply or timeout)
+%%% Method HTTPReq
+%%% options,get,head,delete,trace = {Url,Headers}
+%%% post,put = {Url,Headers,ContentType,Body}
+%%% where Url is a string() or a {Scheme,Host,Port,PathQuery} tuple
+%%%
+%%% Returns: {Status,Headers,Body} |
+%%% {error,Reason}
+%%% where Reason is an atom.
+%%% http:format_error(Reason) gives a more informative description.
+request_sync(Method,HTTPReqCont) ->
+ request_sync(Method,HTTPReqCont,[]).
+
+request_sync(Method,{Url,Headers},Settings)
+ when Method==options;Method==get;Method==head;Method==delete;Method==trace ->
+ case uri:parse(Url) of
+ {error,Reason} ->
+ {error,Reason};
+ ParsedUrl ->
+ request_sync(Method,{ParsedUrl,Headers,[],[]},Settings,0)
+ end;
+request_sync(Method,{Url,Headers,ContentType,Body},Settings)
+ when Method==post;Method==put ->
+ case uri:parse(Url) of
+ {error,Reason} ->
+ {error,Reason};
+ ParsedUrl ->
+ request_sync(Method,{ParsedUrl,Headers,ContentType,Body},Settings,0)
+ end;
+request_sync(Method,Request,Settings) ->
+ {error,bad_request}.
+
+request_sync(Method,HTTPCont,Settings,_Redirects) ->
+ case request(request_sync,Method,HTTPCont,Settings,self()) of
+ {ok,_ReqId} ->
+ receive
+ {'$gen_cast',{request_sync,_ReqId2,{Status,Headers,Body}}} ->
+ {Status,pp_headers(Headers),binary_to_list(Body)};
+ {'$gen_cast',{request_sync,_ReqId2,{error,Reason}}} ->
+ {error,Reason};
+ Error ->
+ Error
+ end;
+ Error ->
+ Error
+ end.
+
+
+create_settings([],Out) ->
+ Out;
+create_settings([{http_timeout,Val}|Settings],Out) ->
+ create_settings(Settings,Out#client_settings{timeout=Val});
+create_settings([{http_useproxy,Val}|Settings],Out) ->
+ create_settings(Settings,Out#client_settings{useproxy=Val});
+create_settings([{http_proxy,Val}|Settings],Out) ->
+ create_settings(Settings,Out#client_settings{proxy=Val});
+create_settings([{http_noproxylist,Val}|Settings],Out) ->
+ create_settings(Settings,Out#client_settings{noproxylist=Val});
+create_settings([{http_autoredirect,Val}|Settings],Out) ->
+ create_settings(Settings,Out#client_settings{autoredirect=Val});
+create_settings([{http_ssl,Val}|Settings],Out) ->
+ create_settings(Settings,Out#client_settings{ssl=Val});
+create_settings([{http_pipelinesize,Val}|Settings],Out)
+ when integer(Val),Val>0 ->
+ create_settings(Settings,Out#client_settings{max_quelength=Val});
+create_settings([{http_sessions,Val}|Settings],Out)
+ when integer(Val),Val>0 ->
+ create_settings(Settings,Out#client_settings{max_sessions=Val});
+create_settings([{Key,_Val}|_Settings],_Out) ->
+ io:format("ERROR bad settings, got ~p~n",[Key]),
+ {error,bad_settings}.
+
+
+create_headers([],Req) ->
+ Req;
+create_headers([{Key,Val}|Rest],Req) ->
+ case httpd_util:to_lower(Key) of
+ "expect" ->
+ create_headers(Rest,Req#req_headers{expect=Val});
+ OtherKey ->
+ create_headers(Rest,
+ Req#req_headers{other=[{OtherKey,Val}|
+ Req#req_headers.other]})
+ end.
+
+
+pp_headers(#res_headers{connection=Connection,
+ transfer_encoding=Transfer_encoding,
+ retry_after=Retry_after,
+ content_length=Content_length,
+ content_type=Content_type,
+ location=Location,
+ other=Other}) ->
+ H1=case Connection of
+ undefined -> [];
+ _ -> [{'Connection',Connection}]
+ end,
+ H2=case Transfer_encoding of
+ undefined -> [];
+ _ -> [{'Transfer-Encoding',Transfer_encoding}]
+ end,
+ H3=case Retry_after of
+ undefined -> [];
+ _ -> [{'Retry-After',Retry_after}]
+ end,
+ H4=case Location of
+ undefined -> [];
+ _ -> [{'Location',Location}]
+ end,
+ HCL=case Content_length of
+ "0" -> [];
+ _ -> [{'Content-Length',Content_length}]
+ end,
+ HCT=case Content_type of
+ undefined -> [];
+ _ -> [{'Content-Type',Content_type}]
+ end,
+ H1++H2++H3++H4++HCL++HCT++Other.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/http.hrl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/http.hrl
new file mode 100644
index 0000000000..6904a2379f
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/http.hrl
@@ -0,0 +1,127 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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 Mobile Arts AB
+%% Portions created by Mobile Arts are Copyright 2002, Mobile Arts AB
+%% All Rights Reserved.''
+%%
+%%
+
+-define(HTTP_REQUEST_TIMEOUT, 5000).
+-define(PIPELINE_LENGTH,3).
+-define(OPEN_SESSIONS,400).
+
+
+%%% FIXME! These definitions should probably be possible to defined via
+%%% user settings
+-define(MAX_REDIRECTS, 4).
+
+
+%%% Note that if not persitent the connection can be closed immediately on a
+%%% response, because new requests are not sent to this connection process.
+%%% address, % ({Host,Port}) Destination Host and Port
+-record(session,{
+ id, % (int) Session Id identifies session in http_manager
+ clientclose, % (bool) true if client requested "close" connection
+ scheme, % (atom) http (HTTP/TCP) or https (TCP/SSL/TCP)
+ socket, % (socket) Open socket, used by connection
+ pipeline=[], % (list) Sent requests, not yet taken care of by the
+ % associated http_responder.
+ quelength=1, % (int) Current length of pipeline (1 when created)
+ max_quelength% (int) Max pipeline length
+ }).
+
+%%% [{Pid,RequestQue,QueLength},...] list where
+%%% - RequestQue (implemented with a list) contains sent requests that
+%%% has not yet received a response (pipelined) AND is not currently
+%%% handled (awaiting data) by the session process.
+%%% - QueLength is the length of this que, but
+
+%%% Response headers
+-record(res_headers,{
+%%% --- Standard "General" headers
+% cache_control,
+ connection,
+% date,
+% pragma,
+% trailer,
+ transfer_encoding,
+% upgrade,
+% via,
+% warning,
+%%% --- Standard "Request" headers
+% accept_ranges,
+% age,
+% etag,
+ location,
+% proxy_authenticate,
+ retry_after,
+% server,
+% vary,
+% www_authenticate,
+%%% --- Standard "Entity" headers
+% allow,
+% content_encoding,
+% content_language,
+ content_length="0",
+% content_location,
+% content_md5,
+% content_range,
+ content_type,
+% expires,
+% last_modified,
+ other=[] % (list) Key/Value list with other headers
+ }).
+
+%%% All data associated to a specific HTTP request
+-record(request,{
+ id, % (int) Request Id
+ ref, % Caller specific
+ from, % (pid) Caller
+ redircount=0,% (int) Number of redirects made for this request
+ scheme, % (http|https) (HTTP/TCP) or (TCP/SSL/TCP) connection
+ address, % ({Host,Port}) Destination Host and Port
+ pathquery, % (string) Rest of parsed URL
+ method, % (atom) HTTP request Method
+ headers, % (list) Key/Value list with Headers
+ content, % ({ContentType,Body}) Current HTTP request
+ settings % (#client_settings{}) User defined settings
+ }).
+
+-record(response,{
+ scheme, % (atom) http (HTTP/TCP) or https (TCP/SSL/TCP)
+ socket, % (socket) Open socket, used by connection
+ status,
+ http_version,
+ headers=#res_headers{},
+ body = <<>>
+ }).
+
+
+
+
+%%% HTTP Client settings
+-record(client_settings,{
+ timeout=?HTTP_REQUEST_TIMEOUT,
+ % (int) Milliseconds before a request times out
+ useproxy=false, % (bool) True if the proxy should be used
+ proxy=undefined, % (tuple) Parsed Proxy URL
+ noproxylist=[], % (list) List with hosts not requiring proxy
+ autoredirect=true, % (bool) True if automatic redirection on 30X
+ % responses.
+ max_sessions=?OPEN_SESSIONS,% (int) Max open sessions for any Adr,Port
+ max_quelength=?PIPELINE_LENGTH, % (int) Max pipeline length
+% ssl=[{certfile,"/jb/server_root/ssl/ssl_client.pem"},
+% {keyfile,"/jb/server_root/ssl/ssl_client.pem"},
+% {verify,0}]
+ ssl=false % (list) SSL settings. A non-empty list enables SSL/TLS
+ % support in the HTTP client
+ }).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/http_lib.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/http_lib.erl
new file mode 100644
index 0000000000..4f6c43710b
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/http_lib.erl
@@ -0,0 +1,745 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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 Mobile Arts AB
+%% Portions created by Mobile Arts are Copyright 2002, Mobile Arts AB
+%% All Rights Reserved.''
+%%
+%%
+%%% File : http_lib.erl
+%%% Author : Johan Blom <[email protected]>
+%%% Description : Generic, HTTP specific helper functions
+%%% Created : 4 Mar 2002 by Johan Blom
+
+%%% TODO
+%%% - Check if I need to anything special when parsing
+%%% "Content-Type:multipart/form-data"
+
+-module(http_lib).
+-author("[email protected]").
+
+-include("http.hrl").
+-include("jnets_httpd.hrl").
+
+-export([connection_close/1,
+ accept/3,deliver/3,recv/4,recv0/3,
+ connect/1,send/3,close/2,controlling_process/3,setopts/3,
+ getParameterValue/2,
+% get_var/2,
+ create_request_line/3]).
+
+-export([read_client_headers/2,read_server_headers/2,
+ get_auth_data/1,create_header_list/1,
+ read_client_body/2,read_client_multipartrange_body/3,
+ read_server_body/2]).
+
+
+%%% Server response:
+%%% Check "Connection" header if server requests session to be closed.
+%%% No 'close' means returns false
+%%% Client Request:
+%%% Check if 'close' in request headers
+%%% Only care about HTTP 1.1 clients!
+connection_close(Headers) when record(Headers,req_headers) ->
+ case Headers#req_headers.connection of
+ "close" ->
+ true;
+ "keep-alive" ->
+ false;
+ Value when list(Value) ->
+ true;
+ _ ->
+ false
+ end;
+connection_close(Headers) when record(Headers,res_headers) ->
+ case Headers#res_headers.connection of
+ "close" ->
+ true;
+ "keep-alive" ->
+ false;
+ Value when list(Value) ->
+ true;
+ _ ->
+ false
+ end.
+
+
+%% =============================================================================
+%%% Debugging:
+
+% format_time(TS) ->
+% {_,_,MicroSecs}=TS,
+% {{Y,Mon,D},{H,M,S}}=calendar:now_to_universal_time(TS),
+% lists:flatten(io_lib:format("~4.4.0w-~2.2.0w-~2.2.0w,~2.2.0w:~2.2.0w:~6.3.0f",
+% [Y,Mon,D,H,M,S+(MicroSecs/1000000)])).
+
+%% Time in milli seconds
+% t() ->
+% {A,B,C} = erlang:now(),
+% A*1000000000+B*1000+(C div 1000).
+
+% sz(L) when list(L) ->
+% length(L);
+% sz(B) when binary(B) ->
+% size(B);
+% sz(O) ->
+% {unknown_size,O}.
+
+
+%% =============================================================================
+
+getHeaderValue(_Attr,[]) ->
+ [];
+getHeaderValue(Attr,[{Attr,Value}|_Rest]) ->
+ Value;
+getHeaderValue(Attr,[_|Rest]) ->
+ getHeaderValue(Attr,Rest).
+
+getParameterValue(_Attr,undefined) ->
+ undefined;
+getParameterValue(Attr,List) ->
+ case lists:keysearch(Attr,1,List) of
+ {value,{Attr,Val}} ->
+ Val;
+ _ ->
+ undefined
+ end.
+
+create_request_line(Method,Path,{Major,Minor}) ->
+ [atom_to_list(Method)," ",Path,
+ " HTTP/",integer_to_list(Major),".",integer_to_list(Minor)];
+create_request_line(Method,Path,Minor) ->
+ [atom_to_list(Method)," ",Path," HTTP/1.",integer_to_list(Minor)].
+
+
+%%% ============================================================================
+read_client_headers(Info,Timeout) ->
+ Headers=read_response_h(Info#response.scheme,Info#response.socket,Timeout,
+ Info#response.headers),
+ Info#response{headers=Headers}.
+
+read_server_headers(Info,Timeout) ->
+ Headers=read_request_h(Info#mod.socket_type,Info#mod.socket,Timeout,
+ Info#mod.headers),
+ Info#mod{headers=Headers}.
+
+
+%% Parses the header of a HTTP request and returns a key,value tuple
+%% list containing Name and Value of each header directive as of:
+%%
+%% Content-Type: multipart/mixed -> {"Content-Type", "multipart/mixed"}
+%%
+%% But in http/1.1 the field-names are case insencitive so now it must be
+%% Content-Type: multipart/mixed -> {"content-type", "multipart/mixed"}
+%% The standard furthermore says that leading and traling white space
+%% is not a part of the fieldvalue and shall therefore be removed.
+read_request_h(SType,S,Timeout,H) ->
+ case recv0(SType,S,Timeout) of
+ {ok,{http_header,_,'Connection',_,Value}} ->
+ read_request_h(SType,S,Timeout,H#req_headers{connection=Value});
+ {ok,{http_header,_,'Content-Type',_,Val}} ->
+ read_request_h(SType,S,Timeout,H#req_headers{content_type=Val});
+ {ok,{http_header,_,'Host',_,Value}} ->
+ read_request_h(SType,S,Timeout,H#req_headers{host=Value});
+ {ok,{http_header,_,'Content-Length',_,Value}} ->
+ read_request_h(SType,S,Timeout,H#req_headers{content_length=Value});
+% {ok,{http_header,_,'Expect',_,Value}} -> % FIXME! Update inet_drv.c!!
+% read_request_h(SType,S,Timeout,H#req_headers{expect=Value});
+ {ok,{http_header,_,'Transfer-Encoding',_,V}} ->
+ read_request_h(SType,S,Timeout,H#req_headers{transfer_encoding=V});
+ {ok,{http_header,_,'Authorization',_,Value}} ->
+ read_request_h(SType,S,Timeout,H#req_headers{authorization=Value});
+ {ok,{http_header,_,'User-Agent',_,Value}} ->
+ read_request_h(SType,S,Timeout,H#req_headers{user_agent=Value});
+ {ok,{http_header,_,'Range',_,Value}} ->
+ read_request_h(SType,S,Timeout,H#req_headers{range=Value});
+ {ok,{http_header,_,'If-Range',_,Value}} ->
+ read_request_h(SType,S,Timeout,H#req_headers{if_range=Value});
+ {ok,{http_header,_,'If-Match',_,Value}} ->
+ read_request_h(SType,S,Timeout,H#req_headers{if_match=Value});
+ {ok,{http_header,_,'If-None-Match',_,Value}} ->
+ read_request_h(SType,S,Timeout,H#req_headers{if_none_match=Value});
+ {ok,{http_header,_,'If-Modified-Since',_,V}} ->
+ read_request_h(SType,S,Timeout,H#req_headers{if_modified_since=V});
+ {ok,{http_header,_,'If-Unmodified-Since',_,V}} ->
+ read_request_h(SType,S,Timeout,H#req_headers{if_unmodified_since=V});
+ {ok,{http_header,_,K,_,V}} ->
+ read_request_h(SType,S,Timeout,
+ H#req_headers{other=H#req_headers.other++[{K,V}]});
+ {ok,http_eoh} ->
+ H;
+ {error, timeout} when SType==http ->
+ throw({error, session_local_timeout});
+ {error, etimedout} when SType==https ->
+ throw({error, session_local_timeout});
+ {error, Reason} when Reason==closed;Reason==enotconn ->
+ throw({error, session_remotely_closed});
+ {error, Reason} ->
+ throw({error,Reason})
+ end.
+
+
+read_response_h(SType,S,Timeout,H) ->
+ case recv0(SType,S,Timeout) of
+ {ok,{http_header,_,'Connection',_,Val}} ->
+ read_response_h(SType,S,Timeout,H#res_headers{connection=Val});
+ {ok,{http_header,_,'Content-Length',_,Val}} ->
+ read_response_h(SType,S,Timeout,H#res_headers{content_length=Val});
+ {ok,{http_header,_,'Content-Type',_,Val}} ->
+ read_response_h(SType,S,Timeout,H#res_headers{content_type=Val});
+ {ok,{http_header,_,'Transfer-Encoding',_,V}} ->
+ read_response_h(SType,S,Timeout,H#res_headers{transfer_encoding=V});
+ {ok,{http_header,_,'Location',_,V}} ->
+ read_response_h(SType,S,Timeout,H#res_headers{location=V});
+ {ok,{http_header,_,'Retry-After',_,V}} ->
+ read_response_h(SType,S,Timeout,H#res_headers{retry_after=V});
+ {ok,{http_header,_,K,_,V}} ->
+ read_response_h(SType,S,Timeout,
+ H#res_headers{other=H#res_headers.other++[{K,V}]});
+ {ok,http_eoh} ->
+ H;
+ {error, timeout} when SType==http ->
+ throw({error, session_local_timeout});
+ {error, etimedout} when SType==https ->
+ throw({error, session_local_timeout});
+ {error, Reason} when Reason==closed;Reason==enotconn ->
+ throw({error, session_remotely_closed});
+ {error, Reason} ->
+ throw({error,Reason})
+ end.
+
+
+%%% Got the headers, and maybe a part of the body, now read in the rest
+%%% Note:
+%%% - No need to check for Expect header if client
+%%% - Currently no support for setting MaxHeaderSize in client, set to
+%%% unlimited.
+%%% - Move to raw packet mode as we are finished with HTTP parsing
+read_client_body(Info,Timeout) ->
+ Headers=Info#response.headers,
+ case Headers#res_headers.transfer_encoding of
+ "chunked" ->
+ ?DEBUG("read_entity_body2()->"
+ "Transfer-encoding:Chunked Data:",[]),
+ read_client_chunked_body(Info,Timeout,?MAXBODYSIZE);
+ Encoding when list(Encoding) ->
+ ?DEBUG("read_entity_body2()->"
+ "Transfer-encoding:Unknown",[]),
+ throw({error,unknown_coding});
+ _ ->
+ ContLen=list_to_integer(Headers#res_headers.content_length),
+ if
+ ContLen>?MAXBODYSIZE ->
+ throw({error,body_too_big});
+ true ->
+ ?DEBUG("read_entity_body2()->"
+ "Transfer-encoding:none ",[]),
+ Info#response{body=read_plain_body(Info#response.scheme,
+ Info#response.socket,
+ ContLen,
+ Info#response.body,
+ Timeout)}
+ end
+ end.
+
+
+%%% ----------------------------------------------------------------------
+read_server_body(Info,Timeout) ->
+ MaxBodySz=httpd_util:lookup(Info#mod.config_db,max_body_size,?MAXBODYSIZE),
+ ContLen=list_to_integer((Info#mod.headers)#req_headers.content_length),
+ %% ?vtrace("ContentLength: ~p", [ContLen]),
+ if
+ integer(ContLen),integer(MaxBodySz),ContLen>MaxBodySz ->
+ throw({error,body_too_big});
+ true ->
+ read_server_body2(Info,Timeout,ContLen,MaxBodySz)
+ end.
+
+
+%%----------------------------------------------------------------------
+%% Control if the body is transfer encoded, if so decode it.
+%% Note:
+%% - MaxBodySz has an integer value or 'nolimit'
+%% - ContLen has an integer value or 'undefined'
+%% All applications MUST be able to receive and decode the "chunked"
+%% transfer-coding, see RFC 2616 Section 3.6.1
+read_server_body2(Info,Timeout,ContLen,MaxBodySz) ->
+ ?DEBUG("read_entity_body2()->Max: ~p ~nLength:~p ~nSocket: ~p ~n",
+ [MaxBodySz,ContLen,Info#mod.socket]),
+ case (Info#mod.headers)#req_headers.transfer_encoding of
+ "chunked" ->
+ ?DEBUG("read_entity_body2()->"
+ "Transfer-encoding:Chunked Data:",[]),
+ read_server_chunked_body(Info,Timeout,MaxBodySz);
+ Encoding when list(Encoding) ->
+ ?DEBUG("read_entity_body2()->"
+ "Transfer-encoding:Unknown",[]),
+ httpd_response:send_status(Info,501,"Unknown Transfer-Encoding"),
+ http_lib:close(Info#mod.socket_type,Info#mod.socket),
+ throw({error,{status_sent,"Unknown Transfer-Encoding "++Encoding}});
+ _ when integer(ContLen),integer(MaxBodySz),ContLen>MaxBodySz ->
+ throw({error,body_too_big});
+ _ when integer(ContLen) ->
+ ?DEBUG("read_entity_body2()->"
+ "Transfer-encoding:none ",[]),
+ Info#mod{entity_body=read_plain_body(Info#mod.socket_type,
+ Info#mod.socket,
+ ContLen,Info#mod.entity_body,
+ Timeout)}
+ end.
+
+
+%%% ----------------------------------------------------------------------------
+%%% The body was plain, just read it from the socket.
+read_plain_body(_SocketType,Socket,0,Cont,_Timeout) ->
+ Cont;
+read_plain_body(SocketType,Socket,ContLen,Cont,Timeout) ->
+ Body=read_more_data(SocketType,Socket,ContLen,Timeout),
+ <<Cont/binary,Body/binary>>.
+
+%%% ----------------------------------------------------------------------------
+%%% The body was chunked, decode it.
+%%% From RFC2616, Section 3.6.1
+%% Chunked-Body = *chunk
+%% last-chunk
+%% trailer
+%% CRLF
+%%
+%% chunk = chunk-size [ chunk-extension ] CRLF
+%% chunk-data CRLF
+%% chunk-size = 1*HEX
+%% last-chunk = 1*("0") [ chunk-extension ] CRLF
+%%
+%% chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
+%% chunk-ext-name = token
+%% chunk-ext-val = token | quoted-string
+%% chunk-data = chunk-size(OCTET)
+%% trailer = *(entity-header CRLF)
+%%
+%%% "All applications MUST ignore chunk-extension extensions they do not
+%%% understand.", see RFC 2616 Section 3.6.1
+%%% We don't understand any extension...
+read_client_chunked_body(Info,Timeout,MaxChunkSz) ->
+ case read_chunk(Info#response.scheme,Info#response.socket,
+ Timeout,0,MaxChunkSz) of
+ {last_chunk,_ExtensionList} -> % Ignore extension
+ TrailH=read_headers_old(Info#response.scheme,Info#response.socket,
+ Timeout),
+ H=Info#response.headers,
+ OtherHeaders=H#res_headers.other++TrailH,
+ Info#response{headers=H#res_headers{other=OtherHeaders}};
+ {Chunk,ChunkSize,_ExtensionList} -> % Ignore extension
+ Info1=Info#response{body= <<(Info#response.body)/binary,
+ Chunk/binary>>},
+ read_client_chunked_body(Info1,Timeout,MaxChunkSz-ChunkSize);
+ {error,Reason} ->
+ throw({error,Reason})
+ end.
+
+
+read_server_chunked_body(Info,Timeout,MaxChunkSz) ->
+ case read_chunk(Info#mod.socket_type,Info#mod.socket,
+ Timeout,0,MaxChunkSz) of
+ {last_chunk,_ExtensionList} -> % Ignore extension
+ TrailH=read_headers_old(Info#mod.socket_type,Info#mod.socket,
+ Timeout),
+ H=Info#mod.headers,
+ OtherHeaders=H#req_headers.other++TrailH,
+ Info#mod{headers=H#req_headers{other=OtherHeaders}};
+ {Chunk,ChunkSize,_ExtensionList} -> % Ignore extension
+ Info1=Info#mod{entity_body= <<(Info#mod.entity_body)/binary,
+ Chunk/binary>>},
+ read_server_chunked_body(Info1,Timeout,MaxChunkSz-ChunkSize);
+ {error,Reason} ->
+ throw({error,Reason})
+ end.
+
+
+read_chunk(Scheme,Socket,Timeout,Int,MaxChunkSz) when MaxChunkSz>Int ->
+ case read_more_data(Scheme,Socket,1,Timeout) of
+ <<C>> when $0=<C,C=<$9 ->
+ read_chunk(Scheme,Socket,Timeout,16*Int+(C-$0),MaxChunkSz);
+ <<C>> when $a=<C,C=<$f ->
+ read_chunk(Scheme,Socket,Timeout,16*Int+10+(C-$a),MaxChunkSz);
+ <<C>> when $A=<C,C=<$F ->
+ read_chunk(Scheme,Socket,Timeout,16*Int+10+(C-$A),MaxChunkSz);
+ <<$;>> when Int>0 ->
+ ExtensionList=read_chunk_ext_name(Scheme,Socket,Timeout,[],[]),
+ read_chunk_data(Scheme,Socket,Int+1,ExtensionList,Timeout);
+ <<$;>> when Int==0 ->
+ ExtensionList=read_chunk_ext_name(Scheme,Socket,Timeout,[],[]),
+ read_data_lf(Scheme,Socket,Timeout),
+ {last_chunk,ExtensionList};
+ <<?CR>> when Int>0 ->
+ read_chunk_data(Scheme,Socket,Int+1,[],Timeout);
+ <<?CR>> when Int==0 ->
+ read_data_lf(Scheme,Socket,Timeout),
+ {last_chunk,[]};
+ <<C>> when C==$ -> % Some servers (e.g., Apache 1.3.6) throw in
+ % additional whitespace...
+ read_chunk(Scheme,Socket,Timeout,Int,MaxChunkSz);
+ _Other ->
+ {error,unexpected_chunkdata}
+ end;
+read_chunk(_Scheme,_Socket,_Timeout,_Int,_MaxChunkSz) ->
+ {error,body_too_big}.
+
+
+%%% Note:
+%%% - Got the initial ?CR already!
+%%% - Bitsyntax does not allow matching of ?CR,?LF in the end of the first read
+read_chunk_data(Scheme,Socket,Int,ExtensionList,Timeout) ->
+ case read_more_data(Scheme,Socket,Int,Timeout) of
+ <<?LF,Chunk/binary>> ->
+ case read_more_data(Scheme,Socket,2,Timeout) of
+ <<?CR,?LF>> ->
+ {Chunk,size(Chunk),ExtensionList};
+ _ ->
+ {error,bad_chunkdata}
+ end;
+ _ ->
+ {error,bad_chunkdata}
+ end.
+
+read_chunk_ext_name(Scheme,Socket,Timeout,Name,Acc) ->
+ Len=length(Name),
+ case read_more_data(Scheme,Socket,1,Timeout) of
+ $= when Len>0 ->
+ read_chunk_ext_val(Scheme,Socket,Timeout,Name,[],Acc);
+ $; when Len>0 ->
+ read_chunk_ext_name(Scheme,Socket,Timeout,[],
+ [{lists:reverse(Name),""}|Acc]);
+ ?CR when Len>0 ->
+ lists:reverse([{lists:reverse(Name,"")}|Acc]);
+ Token -> % FIXME Check that it is "token"
+ read_chunk_ext_name(Scheme,Socket,Timeout,[Token|Name],Acc);
+ _ ->
+ {error,bad_chunk_extension_name}
+ end.
+
+read_chunk_ext_val(Scheme,Socket,Timeout,Name,Val,Acc) ->
+ Len=length(Val),
+ case read_more_data(Scheme,Socket,1,Timeout) of
+ $; when Len>0 ->
+ read_chunk_ext_name(Scheme,Socket,Timeout,[],
+ [{Name,lists:reverse(Val)}|Acc]);
+ ?CR when Len>0 ->
+ lists:reverse([{Name,lists:reverse(Val)}|Acc]);
+ Token -> % FIXME Check that it is "token" or "quoted-string"
+ read_chunk_ext_val(Scheme,Socket,Timeout,Name,[Token|Val],Acc);
+ _ ->
+ {error,bad_chunk_extension_value}
+ end.
+
+read_data_lf(Scheme,Socket,Timeout) ->
+ case read_more_data(Scheme,Socket,1,Timeout) of
+ ?LF ->
+ ok;
+ _ ->
+ {error,bad_chunkdata}
+ end.
+
+%%% ----------------------------------------------------------------------------
+%%% The body was "multipart/byteranges", decode it.
+%%% Example from RFC 2616, Appendix 19.2
+%%% HTTP/1.1 206 Partial Content
+%%% Date: Wed, 15 Nov 1995 06:25:24 GMT
+%%% Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
+%%% Content-type: multipart/byteranges; boundary=THIS_STRING_SEPARATES
+%%%
+%%% --THIS_STRING_SEPARATES
+%%% Content-type: application/pdf
+%%% Content-range: bytes 500-999/8000
+%%%
+%%% ...the first range...
+%%% --THIS_STRING_SEPARATES
+%%% Content-type: application/pdf
+%%% Content-range: bytes 7000-7999/8000
+%%%
+%%% ...the second range
+%%% --THIS_STRING_SEPARATES--
+%%%
+%%% Notes:
+%%%
+%%% 1) Additional CRLFs may precede the first boundary string in the
+%%% entity.
+%%% FIXME!!
+read_client_multipartrange_body(Info,Parstr,Timeout) ->
+ Boundary=get_boundary(Parstr),
+ scan_boundary(Info,Boundary),
+ Info#response{body=read_multipart_body(Info,Boundary,Timeout)}.
+
+read_multipart_body(Info,Boundary,Timeout) ->
+ Info.
+
+% Headers=read_headers_old(Info#response.scheme,Info#response.socket,Timeout),
+% H=Info#response.headers,
+% OtherHeaders=H#res_headers.other++TrailH,
+% Info#response{headers=H#res_headers{other=OtherHeaders}}.
+
+
+scan_boundary(Info,Boundary) ->
+ Info.
+
+
+get_boundary(Parstr) ->
+ case skip_lwsp(Parstr) of
+ [] ->
+ throw({error,missing_range_boundary_parameter});
+ Val ->
+ get_boundary2(string:tokens(Val, ";"))
+ end.
+
+get_boundary2([]) ->
+ undefined;
+get_boundary2([Param|Rest]) ->
+ case string:tokens(skip_lwsp(Param), "=") of
+ ["boundary"++Attribute,Value] ->
+ Value;
+ _ ->
+ get_boundary2(Rest)
+ end.
+
+
+%% skip space & tab
+skip_lwsp([$ | Cs]) -> skip_lwsp(Cs);
+skip_lwsp([$\t | Cs]) -> skip_lwsp(Cs);
+skip_lwsp(Cs) -> Cs.
+
+%%% ----------------------------------------------------------------------------
+
+%%% Read the incoming data from the open socket.
+read_more_data(http,Socket,Len,Timeout) ->
+ case gen_tcp:recv(Socket,Len,Timeout) of
+ {ok,Val} ->
+ Val;
+ {error, timeout} ->
+ throw({error, session_local_timeout});
+ {error, Reason} when Reason==closed;Reason==enotconn ->
+ throw({error, session_remotely_closed});
+ {error, Reason} ->
+% httpd_response:send_status(Info,400,none),
+ throw({error, Reason})
+ end;
+read_more_data(https,Socket,Len,Timeout) ->
+ case ssl:recv(Socket,Len,Timeout) of
+ {ok,Val} ->
+ Val;
+ {error, etimedout} ->
+ throw({error, session_local_timeout});
+ {error, Reason} when Reason==closed;Reason==enotconn ->
+ throw({error, session_remotely_closed});
+ {error, Reason} ->
+% httpd_response:send_status(Info,400,none),
+ throw({error, Reason})
+ end.
+
+
+%% =============================================================================
+%%% Socket handling
+
+accept(http,ListenSocket, Timeout) ->
+ gen_tcp:accept(ListenSocket, Timeout);
+accept(https,ListenSocket, Timeout) ->
+ ssl:accept(ListenSocket, Timeout).
+
+
+close(http,Socket) ->
+ gen_tcp:close(Socket);
+close(https,Socket) ->
+ ssl:close(Socket).
+
+
+connect(#request{scheme=http,settings=Settings,address=Addr}) ->
+ case proxyusage(Addr,Settings) of
+ {error,Reason} ->
+ {error,Reason};
+ {Host,Port} ->
+ Opts=[binary,{active,false},{reuseaddr,true}],
+ gen_tcp:connect(Host,Port,Opts)
+ end;
+connect(#request{scheme=https,settings=Settings,address=Addr}) ->
+ case proxyusage(Addr,Settings) of
+ {error,Reason} ->
+ {error,Reason};
+ {Host,Port} ->
+ Opts=case Settings#client_settings.ssl of
+ false ->
+ [binary,{active,false}];
+ SSLSettings ->
+ [binary,{active,false}]++SSLSettings
+ end,
+ ssl:connect(Host,Port,Opts)
+ end.
+
+
+%%% Check to see if the given {Host,Port} tuple is in the NoProxyList
+%%% Returns an eventually updated {Host,Port} tuple, with the proxy address
+proxyusage(HostPort,Settings) ->
+ case Settings#client_settings.useproxy of
+ true ->
+ case noProxy(HostPort,Settings#client_settings.noproxylist) of
+ true ->
+ HostPort;
+ _ ->
+ case Settings#client_settings.proxy of
+ undefined ->
+ {error,no_proxy_defined};
+ ProxyHostPort ->
+ ProxyHostPort
+ end
+ end;
+ _ ->
+ HostPort
+ end.
+
+noProxy(_HostPort,[]) ->
+ false;
+noProxy({Host,Port},[{Host,Port}|Rest]) ->
+ true;
+noProxy(HostPort,[_|Rest]) ->
+ noProxy(HostPort,Rest).
+
+
+controlling_process(http,Socket,Pid) ->
+ gen_tcp:controlling_process(Socket,Pid);
+controlling_process(https,Socket,Pid) ->
+ ssl:controlling_process(Socket,Pid).
+
+
+deliver(SocketType, Socket, Message) ->
+ case send(SocketType, Socket, Message) of
+ {error, einval} ->
+ close(SocketType, Socket),
+ socket_closed;
+ {error, _Reason} ->
+% ?vlog("deliver(~p) failed for reason:"
+% "~n Reason: ~p",[SocketType,_Reason]),
+ close(SocketType, Socket),
+ socket_closed;
+ _Other ->
+ ok
+ end.
+
+
+recv0(http,Socket,Timeout) ->
+ gen_tcp:recv(Socket,0,Timeout);
+recv0(https,Socket,Timeout) ->
+ ssl:recv(Socket,0,Timeout).
+
+recv(http,Socket,Len,Timeout) ->
+ gen_tcp:recv(Socket,Len,Timeout);
+recv(https,Socket,Len,Timeout) ->
+ ssl:recv(Socket,Len,Timeout).
+
+
+setopts(http,Socket,Options) ->
+ inet:setopts(Socket,Options);
+setopts(https,Socket,Options) ->
+ ssl:setopts(Socket,Options).
+
+
+send(http,Socket,Message) ->
+ gen_tcp:send(Socket,Message);
+send(https,Socket,Message) ->
+ ssl:send(Socket,Message).
+
+
+%%% ============================================================================
+%%% HTTP Server only
+
+%%% Returns the Authenticating data in the HTTP request
+get_auth_data("Basic "++EncodedString) ->
+ UnCodedString=httpd_util:decode_base64(EncodedString),
+ case catch string:tokens(UnCodedString,":") of
+ [User,PassWord] ->
+ {User,PassWord};
+ {error,Error}->
+ {error,Error}
+ end;
+get_auth_data(BadCredentials) when list(BadCredentials) ->
+ {error,BadCredentials};
+get_auth_data(_) ->
+ {error,nouser}.
+
+
+create_header_list(H) ->
+ lookup(connection,H#req_headers.connection)++
+ lookup(host,H#req_headers.host)++
+ lookup(content_length,H#req_headers.content_length)++
+ lookup(transfer_encoding,H#req_headers.transfer_encoding)++
+ lookup(authorization,H#req_headers.authorization)++
+ lookup(user_agent,H#req_headers.user_agent)++
+ lookup(user_agent,H#req_headers.range)++
+ lookup(user_agent,H#req_headers.if_range)++
+ lookup(user_agent,H#req_headers.if_match)++
+ lookup(user_agent,H#req_headers.if_none_match)++
+ lookup(user_agent,H#req_headers.if_modified_since)++
+ lookup(user_agent,H#req_headers.if_unmodified_since)++
+ H#req_headers.other.
+
+lookup(_Key,undefined) ->
+ [];
+lookup(Key,Val) ->
+ [{Key,Val}].
+
+
+
+%%% ============================================================================
+%%% This code is for parsing trailer headers in chunked messages.
+%%% Will be deprecated whenever I have found an alternative working solution!
+%%% Note:
+%%% - The header names are returned slighly different from what the what
+%%% inet_drv returns
+read_headers_old(Scheme,Socket,Timeout) ->
+ read_headers_old(<<>>,Scheme,Socket,Timeout,[],[]).
+
+read_headers_old(<<>>,Scheme,Socket,Timeout,Acc,AccHdrs) ->
+ read_headers_old(read_more_data(Scheme,Socket,1,Timeout),
+ Scheme,Socket,Timeout,Acc,AccHdrs);
+read_headers_old(<<$\r>>,Scheme,Socket,Timeout,Acc,AccHdrs) ->
+ read_headers_old(<<$\r,(read_more_data(Scheme,Socket,1,Timeout))/binary>>,
+ Scheme,Socket,Timeout,Acc,AccHdrs);
+read_headers_old(<<$\r,$\n>>,Scheme,Socket,Timeout,Acc,AccHdrs) ->
+ if
+ Acc==[] -> % Done!
+ tagup_header(lists:reverse(AccHdrs));
+ true ->
+ read_headers_old(read_more_data(Scheme,Socket,1,Timeout),
+ Scheme,Socket,
+ Timeout,[],[lists:reverse(Acc)|AccHdrs])
+ end;
+read_headers_old(<<C>>,Scheme,Socket,Timeout,Acc,AccHdrs) ->
+ read_headers_old(read_more_data(Scheme,Socket,1,Timeout),
+ Scheme,Socket,Timeout,[C|Acc],AccHdrs);
+read_headers_old(Bin,_Scheme,_Socket,_Timeout,_Acc,_AccHdrs) ->
+ io:format("ERROR: Unexpected data from inet driver: ~p",[Bin]),
+ throw({error,this_is_a_bug}).
+
+
+%% Parses the header of a HTTP request and returns a key,value tuple
+%% list containing Name and Value of each header directive as of:
+%%
+%% Content-Type: multipart/mixed -> {"Content-Type", "multipart/mixed"}
+%%
+%% But in http/1.1 the field-names are case insencitive so now it must be
+%% Content-Type: multipart/mixed -> {"content-type", "multipart/mixed"}
+%% The standard furthermore says that leading and traling white space
+%% is not a part of the fieldvalue and shall therefore be removed.
+tagup_header([]) -> [];
+tagup_header([Line|Rest]) -> [tag(Line, [])|tagup_header(Rest)].
+
+tag([], Tag) ->
+ {httpd_util:to_lower(lists:reverse(Tag)), ""};
+tag([$:|Rest], Tag) ->
+ {httpd_util:to_lower(lists:reverse(Tag)), httpd_util:strip(Rest)};
+tag([Chr|Rest], Tag) ->
+ tag(Rest, [Chr|Tag]).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpc_handler.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpc_handler.erl
new file mode 100644
index 0000000000..8e5e1c709a
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpc_handler.erl
@@ -0,0 +1,724 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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 Mobile Arts AB
+%% Portions created by Mobile Arts are Copyright 2002, Mobile Arts AB
+%% All Rights Reserved.''
+%%
+%%
+
+%%% TODO:
+%%% - If an error is returned when sending a request, don't use this
+%%% session anymore.
+%%% - Closing of sessions not properly implemented for some cases
+
+%%% File : httpc_handler.erl
+%%% Author : Johan Blom <[email protected]>
+%%% Description : Handles HTTP client responses, for a single TCP session
+%%% Created : 4 Mar 2002 by Johan Blom
+
+-module(httpc_handler).
+
+-include("http.hrl").
+-include("jnets_httpd.hrl").
+
+-export([init_connection/2,http_request/2]).
+
+%%% ==========================================================================
+%%% "Main" function in the spawned process for the session.
+init_connection(Req,Session) when record(Req,request) ->
+ case catch http_lib:connect(Req) of
+ {ok,Socket} ->
+ case catch http_request(Req,Socket) of
+ ok ->
+ case Session#session.clientclose of
+ true ->
+ ok;
+ false ->
+ httpc_manager:register_socket(Req#request.address,
+ Session#session.id,
+ Socket)
+ end,
+ next_response_with_request(Req,
+ Session#session{socket=Socket});
+ {error,Reason} -> % Not possible to use new session
+ gen_server:cast(Req#request.from,
+ {Req#request.ref,Req#request.id,{error,Reason}}),
+ exit_session_ok(Req#request.address,
+ Session#session{socket=Socket})
+ end;
+ {error,Reason} -> % Not possible to set up new session
+ gen_server:cast(Req#request.from,
+ {Req#request.ref,Req#request.id,{error,Reason}}),
+ exit_session_ok2(Req#request.address,
+ Session#session.clientclose,Session#session.id)
+ end.
+
+next_response_with_request(Req,Session) ->
+ Timeout=(Req#request.settings)#client_settings.timeout,
+ case catch read(Timeout,Session#session.scheme,Session#session.socket) of
+ {Status,Headers,Body} ->
+ NewReq=handle_response({Status,Headers,Body},Timeout,Req,Session),
+ next_response_with_request(NewReq,Session);
+ {error,Reason} ->
+ gen_server:cast(Req#request.from,
+ {Req#request.ref,Req#request.id,{error,Reason}}),
+ exit_session(Req#request.address,Session,aborted_request);
+ {'EXIT',Reason} ->
+ gen_server:cast(Req#request.from,
+ {Req#request.ref,Req#request.id,{error,Reason}}),
+ exit_session(Req#request.address,Session,aborted_request)
+ end.
+
+handle_response(Response,Timeout,Req,Session) ->
+ case http_response(Response,Req,Session) of
+ ok ->
+ next_response(Timeout,Req#request.address,Session);
+ stop ->
+ exit(normal);
+ {error,Reason} ->
+ gen_server:cast(Req#request.from,
+ {Req#request.ref,Req#request.id,{error,Reason}}),
+ exit_session(Req#request.address,Session,aborted_request)
+ end.
+
+
+
+%%% Wait for the next respond until
+%%% - session is closed by the other side
+%%% => set up a new a session, if there are pending requests in the que
+%%% - "Connection:close" header is received
+%%% => close the connection (release socket) then
+%%% set up a new a session, if there are pending requests in the que
+%%%
+%%% Note:
+%%% - When invoked there are no pending responses on received requests.
+%%% - Never close the session explicitly, let it timeout instead!
+next_response(Timeout,Address,Session) ->
+ case httpc_manager:next_request(Address,Session#session.id) of
+ no_more_requests ->
+ %% There are no more pending responses, now just wait for
+ %% timeout or a new response.
+ case catch read(Timeout,
+ Session#session.scheme,Session#session.socket) of
+ {error,Reason} when Reason==session_remotely_closed;
+ Reason==session_local_timeout ->
+ exit_session_ok(Address,Session);
+ {error,Reason} ->
+ exit_session(Address,Session,aborted_request);
+ {'EXIT',Reason} ->
+ exit_session(Address,Session,aborted_request);
+ {Status2,Headers2,Body2} ->
+ case httpc_manager:next_request(Address,
+ Session#session.id) of
+ no_more_requests -> % Should not happen!
+ exit_session(Address,Session,aborted_request);
+ {error,Reason} -> % Should not happen!
+ exit_session(Address,Session,aborted_request);
+ NewReq ->
+ handle_response({Status2,Headers2,Body2},
+ Timeout,NewReq,Session)
+ end
+ end;
+ {error,Reason} -> % The connection has been closed by httpc_manager
+ exit_session(Address,Session,aborted_request);
+ NewReq ->
+ NewReq
+ end.
+
+%% ===========================================================================
+%% Internals
+
+%%% Read in and parse response data from the socket
+read(Timeout,SockType,Socket) ->
+ Info=#response{scheme=SockType,socket=Socket},
+ http_lib:setopts(SockType,Socket,[{packet, http}]),
+ Info1=read_response(SockType,Socket,Info,Timeout),
+ http_lib:setopts(SockType,Socket,[binary,{packet, raw}]),
+ case (Info1#response.headers)#res_headers.content_type of
+ "multipart/byteranges"++Param ->
+ range_response_body(Info1,Timeout,Param);
+ _ ->
+ #response{status=Status2,headers=Headers2,body=Body2}=
+ http_lib:read_client_body(Info1,Timeout),
+ {Status2,Headers2,Body2}
+ end.
+
+
+%%% From RFC 2616:
+%%% Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
+%%% HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
+%%% Status-Code = 3DIGIT
+%%% Reason-Phrase = *<TEXT, excluding CR, LF>
+read_response(SockType,Socket,Info,Timeout) ->
+ case http_lib:recv0(SockType,Socket,Timeout) of
+ {ok,{http_response,{1,VerMin}, Status, _Phrase}} when VerMin==0;
+ VerMin==1 ->
+ Info1=Info#response{status=Status,http_version=VerMin},
+ http_lib:read_client_headers(Info1,Timeout);
+ {ok,{http_response,_Version, _Status, _Phrase}} ->
+ throw({error,bad_status_line});
+ {error, timeout} ->
+ throw({error,session_local_timeout});
+ {error, Reason} when Reason==closed;Reason==enotconn ->
+ throw({error,session_remotely_closed});
+ {error, Reason} ->
+ throw({error,Reason})
+ end.
+
+%%% From RFC 2616, Section 4.4, Page 34
+%% 4.If the message uses the media type "multipart/byteranges", and the
+%% transfer-length is not otherwise specified, then this self-
+%% delimiting media type defines the transfer-length. This media type
+%% MUST NOT be used unless the sender knows that the recipient can parse
+%% it; the presence in a request of a Range header with multiple byte-
+%% range specifiers from a 1.1 client implies that the client can parse
+%% multipart/byteranges responses.
+%%% FIXME !!
+range_response_body(Info,Timeout,Param) ->
+ Headers=Info#response.headers,
+ case {Headers#res_headers.content_length,
+ Headers#res_headers.transfer_encoding} of
+ {undefined,undefined} ->
+ #response{status=Status2,headers=Headers2,body=Body2}=
+ http_lib:read_client_multipartrange_body(Info,Param,Timeout),
+ {Status2,Headers2,Body2};
+ _ ->
+ #response{status=Status2,headers=Headers2,body=Body2}=
+ http_lib:read_client_body(Info,Timeout),
+ {Status2,Headers2,Body2}
+ end.
+
+
+%%% ----------------------------------------------------------------------------
+%%% Host: field is required when addressing multi-homed sites ...
+%%% It must not be present when the request is being made to a proxy.
+http_request(#request{method=Method,id=Id,
+ scheme=Scheme,address={Host,Port},pathquery=PathQuery,
+ headers=Headers, content={ContentType,Body},
+ settings=Settings},
+ Socket) ->
+ PostData=
+ if
+ Method==post;Method==put ->
+ case Headers#req_headers.expect of
+ "100-continue" ->
+ content_type_header(ContentType) ++
+ content_length_header(length(Body)) ++
+ "\r\n";
+ _ ->
+ content_type_header(ContentType) ++
+ content_length_header(length(Body)) ++
+ "\r\n" ++ Body
+ end;
+ true ->
+ "\r\n"
+ end,
+ Message=
+ case useProxy(Settings#client_settings.useproxy,
+ {Scheme,Host,Port,PathQuery}) of
+ false ->
+ method(Method)++" "++PathQuery++" HTTP/1.1\r\n"++
+ host_header(Host)++te_header()++
+ headers(Headers) ++ PostData;
+ AbsURI ->
+ method(Method)++" "++AbsURI++" HTTP/1.1\r\n"++
+ te_header()++
+ headers(Headers)++PostData
+ end,
+ http_lib:send(Scheme,Socket,Message).
+
+useProxy(false,_) ->
+ false;
+useProxy(true,{Scheme,Host,Port,PathQuery}) ->
+ [atom_to_list(Scheme),"://",Host,":",integer_to_list(Port),PathQuery].
+
+
+
+headers(#req_headers{expect=Expect,
+ other=Other}) ->
+ H1=case Expect of
+ undefined ->[];
+ _ -> "Expect: "++Expect++"\r\n"
+ end,
+ H1++headers_other(Other).
+
+
+headers_other([]) ->
+ [];
+headers_other([{Key,Value}|Rest]) when atom(Key) ->
+ Head = atom_to_list(Key)++": "++Value++"\r\n",
+ Head ++ headers_other(Rest);
+headers_other([{Key,Value}|Rest]) ->
+ Head = Key++": "++Value++"\r\n",
+ Head ++ headers_other(Rest).
+
+host_header(Host) ->
+ "Host: "++lists:concat([Host])++"\r\n".
+content_type_header(ContentType) ->
+ "Content-Type: " ++ ContentType ++ "\r\n".
+content_length_header(ContentLength) ->
+ "Content-Length: "++integer_to_list(ContentLength) ++ "\r\n".
+te_header() ->
+ "TE: \r\n".
+
+method(Method) ->
+ httpd_util:to_upper(atom_to_list(Method)).
+
+
+%%% ----------------------------------------------------------------------------
+http_response({Status,Headers,Body},Req,Session) ->
+ case Status of
+ 100 ->
+ status_continue(Req,Session);
+ 200 ->
+ gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
+ {Status,Headers,Body}}),
+ ServerClose=http_lib:connection_close(Headers),
+ handle_connection(Session#session.clientclose,ServerClose,
+ Req,Session);
+ 300 -> status_multiple_choices(Headers,Body,Req,Session);
+ 301 -> status_moved_permanently(Req#request.method,
+ Headers,Body,Req,Session);
+ 302 -> status_found(Headers,Body,Req,Session);
+ 303 -> status_see_other(Headers,Body,Req,Session);
+ 304 -> status_not_modified(Headers,Body,Req,Session);
+ 305 -> status_use_proxy(Headers,Body,Req,Session);
+ %% 306 This Status code is not used in HTTP 1.1
+ 307 -> status_temporary_redirect(Headers,Body,Req,Session);
+ 503 -> status_service_unavailable({Status,Headers,Body},Req,Session);
+ Status50x when Status50x==500;Status50x==501;Status50x==502;
+ Status50x==504;Status50x==505 ->
+ status_server_error_50x({Status,Headers,Body},Req,Session);
+ _ -> % FIXME May want to take some action on other Status codes as well
+ gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
+ {Status,Headers,Body}}),
+ ServerClose=http_lib:connection_close(Headers),
+ handle_connection(Session#session.clientclose,ServerClose,
+ Req,Session)
+ end.
+
+
+%%% Status code dependent functions.
+
+%%% Received a 100 Status code ("Continue")
+%%% From RFC2616
+%%% The client SHOULD continue with its request. This interim response is
+%%% used to inform the client that the initial part of the request has
+%%% been received and has not yet been rejected by the server. The client
+%%% SHOULD continue by sending the remainder of the request or, if the
+%%% request has already been completed, ignore this response. The server
+%%% MUST send a final response after the request has been completed. See
+%%% section 8.2.3 for detailed discussion of the use and handling of this
+%%% status code.
+status_continue(Req,Session) ->
+ {_,Body}=Req#request.content,
+ http_lib:send(Session#session.scheme,Session#session.socket,Body),
+ next_response_with_request(Req,Session).
+
+
+%%% Received a 300 Status code ("Multiple Choices")
+%%% The resource is located in any one of a set of locations
+%%% - If a 'Location' header is present (preserved server choice), use that
+%%% to automatically redirect to the given URL
+%%% - else if the Content-Type/Body both are non-empty let the user agent make
+%%% the choice and thus return a response with status 300
+%%% Note:
+%%% - If response to a HEAD request, the Content-Type/Body both should be empty.
+%%% - The behaviour on an empty Content-Type or Body is unspecified.
+%%% However, e.g. "Apache/1.3" servers returns both empty if the header
+%%% 'if-modified-since: Date' was sent in the request and the content is
+%%% "not modified" (instead of 304). Thus implicitly giving the cache as the
+%%% only choice.
+status_multiple_choices(Headers,Body,Req,Session)
+ when ((Req#request.settings)#client_settings.autoredirect)==true ->
+ ServerClose=http_lib:connection_close(Headers),
+ case Headers#res_headers.location of
+ undefined ->
+ gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
+ {300,Headers,Body}}),
+ handle_connection(Session#session.clientclose,ServerClose,
+ Req,Session);
+ RedirUrl ->
+ Scheme=Session#session.scheme,
+ case uri:parse(RedirUrl) of
+ {error,Reason} ->
+ {error,Reason};
+ {Scheme,Host,Port,PathQuery} -> % Automatic redirection
+ NewReq=Req#request{redircount=Req#request.redircount+1,
+ address={Host,Port},pathquery=PathQuery},
+ handle_redirect(Session#session.clientclose,ServerClose,
+ NewReq,Session)
+ end
+ end;
+status_multiple_choices(Headers,Body,Req,Session) ->
+ ServerClose=http_lib:connection_close(Headers),
+ gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
+ {300,Headers,Body}}),
+ handle_connection(Session#session.clientclose,ServerClose,Req,Session).
+
+
+%%% Received a 301 Status code ("Moved Permanently")
+%%% The resource has been assigned a new permanent URI
+%%% - If a 'Location' header is present, use that to automatically redirect to
+%%% the given URL if GET or HEAD request
+%%% - else return
+%%% Note:
+%%% - The Body should contain a short hypertext note with a hyperlink to the
+%%% new URI. Return this if Content-Type acceptable (some HTTP servers doesn't
+%%% deal properly with Accept headers)
+status_moved_permanently(Method,Headers,Body,Req,Session)
+ when (((Req#request.settings)#client_settings.autoredirect)==true) and
+ (Method==get) or (Method==head) ->
+ ServerClose=http_lib:connection_close(Headers),
+ case Headers#res_headers.location of
+ undefined ->
+ gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
+ {301,Headers,Body}}),
+ handle_connection(Session#session.clientclose,ServerClose,
+ Req,Session);
+ RedirUrl ->
+ Scheme=Session#session.scheme,
+ case uri:parse(RedirUrl) of
+ {error,Reason} ->
+ {error,Reason};
+ {Scheme,Host,Port,PathQuery} -> % Automatic redirection
+ NewReq=Req#request{redircount=Req#request.redircount+1,
+ address={Host,Port},pathquery=PathQuery},
+ handle_redirect(Session#session.clientclose,ServerClose,
+ NewReq,Session)
+ end
+ end;
+status_moved_permanently(_Method,Headers,Body,Req,Session) ->
+ ServerClose=http_lib:connection_close(Headers),
+ gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
+ {301,Headers,Body}}),
+ handle_connection(Session#session.clientclose,ServerClose,Req,Session).
+
+
+%%% Received a 302 Status code ("Found")
+%%% The requested resource resides temporarily under a different URI.
+%%% Note:
+%%% - Only cacheable if indicated by a Cache-Control or Expires header
+status_found(Headers,Body,Req,Session)
+ when ((Req#request.settings)#client_settings.autoredirect)==true ->
+ ServerClose=http_lib:connection_close(Headers),
+ case Headers#res_headers.location of
+ undefined ->
+ gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
+ {302,Headers,Body}}),
+ handle_connection(Session#session.clientclose,ServerClose,
+ Req,Session);
+ RedirUrl ->
+ Scheme=Session#session.scheme,
+ case uri:parse(RedirUrl) of
+ {error,Reason} ->
+ {error,Reason};
+ {Scheme,Host,Port,PathQuery} -> % Automatic redirection
+ NewReq=Req#request{redircount=Req#request.redircount+1,
+ address={Host,Port},pathquery=PathQuery},
+ handle_redirect(Session#session.clientclose,ServerClose,
+ NewReq,Session)
+ end
+ end;
+status_found(Headers,Body,Req,Session) ->
+ ServerClose=http_lib:connection_close(Headers),
+ gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
+ {302,Headers,Body}}),
+ handle_connection(Session#session.clientclose,ServerClose,Req,Session).
+
+%%% Received a 303 Status code ("See Other")
+%%% The request found under a different URI and should be retrieved using GET
+%%% Note:
+%%% - Must not be cached
+status_see_other(Headers,Body,Req,Session)
+ when ((Req#request.settings)#client_settings.autoredirect)==true ->
+ ServerClose=http_lib:connection_close(Headers),
+ case Headers#res_headers.location of
+ undefined ->
+ gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
+ {303,Headers,Body}}),
+ handle_connection(Session#session.clientclose,ServerClose,
+ Req,Session);
+ RedirUrl ->
+ Scheme=Session#session.scheme,
+ case uri:parse(RedirUrl) of
+ {error,Reason} ->
+ {error,Reason};
+ {Scheme,Host,Port,PathQuery} -> % Automatic redirection
+ NewReq=Req#request{redircount=Req#request.redircount+1,
+ method=get,
+ address={Host,Port},pathquery=PathQuery},
+ handle_redirect(Session#session.clientclose,ServerClose,
+ NewReq,Session)
+ end
+ end;
+status_see_other(Headers,Body,Req,Session) ->
+ ServerClose=http_lib:connection_close(Headers),
+ gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
+ {303,Headers,Body}}),
+ handle_connection(Session#session.clientclose,ServerClose,Req,Session).
+
+
+%%% Received a 304 Status code ("Not Modified")
+%%% Note:
+%%% - The response MUST NOT contain a body.
+%%% - The response MUST include the following header fields:
+%%% - Date, unless its omission is required
+%%% - ETag and/or Content-Location, if the header would have been sent
+%%% in a 200 response to the same request
+%%% - Expires, Cache-Control, and/or Vary, if the field-value might
+%%% differ from that sent in any previous response for the same
+%%% variant
+status_not_modified(Headers,Body,Req,Session)
+ when ((Req#request.settings)#client_settings.autoredirect)==true ->
+ ServerClose=http_lib:connection_close(Headers),
+ case Headers#res_headers.location of
+ undefined ->
+ gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
+ {304,Headers,Body}}),
+ handle_connection(Session#session.clientclose,ServerClose,
+ Req,Session);
+ RedirUrl ->
+ Scheme=Session#session.scheme,
+ case uri:parse(RedirUrl) of
+ {error,Reason} ->
+ {error,Reason};
+ {Scheme,Host,Port,PathQuery} -> % Automatic redirection
+ NewReq=Req#request{redircount=Req#request.redircount+1,
+ address={Host,Port},pathquery=PathQuery},
+ handle_redirect(Session#session.clientclose,ServerClose,
+ NewReq,Session)
+ end
+ end;
+status_not_modified(Headers,Body,Req,Session) ->
+ ServerClose=http_lib:connection_close(Headers),
+ gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
+ {304,Headers,Body}}),
+ handle_connection(Session#session.clientclose,ServerClose,Req,Session).
+
+
+
+%%% Received a 305 Status code ("Use Proxy")
+%%% The requested resource MUST be accessed through the proxy given by the
+%%% Location field
+status_use_proxy(Headers,Body,Req,Session)
+ when ((Req#request.settings)#client_settings.autoredirect)==true ->
+ ServerClose=http_lib:connection_close(Headers),
+ case Headers#res_headers.location of
+ undefined ->
+ gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
+ {305,Headers,Body}}),
+ handle_connection(Session#session.clientclose,ServerClose,
+ Req,Session);
+ RedirUrl ->
+ Scheme=Session#session.scheme,
+ case uri:parse(RedirUrl) of
+ {error,Reason} ->
+ {error,Reason};
+ {Scheme,Host,Port,PathQuery} -> % Automatic redirection
+ NewReq=Req#request{redircount=Req#request.redircount+1,
+ address={Host,Port},pathquery=PathQuery},
+ handle_redirect(Session#session.clientclose,ServerClose,
+ NewReq,Session)
+ end
+ end;
+status_use_proxy(Headers,Body,Req,Session) ->
+ ServerClose=http_lib:connection_close(Headers),
+ gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
+ {305,Headers,Body}}),
+ handle_connection(Session#session.clientclose,ServerClose,Req,Session).
+
+
+%%% Received a 307 Status code ("Temporary Redirect")
+status_temporary_redirect(Headers,Body,Req,Session)
+ when ((Req#request.settings)#client_settings.autoredirect)==true ->
+ ServerClose=http_lib:connection_close(Headers),
+ case Headers#res_headers.location of
+ undefined ->
+ gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
+ {307,Headers,Body}}),
+ handle_connection(Session#session.clientclose,ServerClose,
+ Req,Session);
+ RedirUrl ->
+ Scheme=Session#session.scheme,
+ case uri:parse(RedirUrl) of
+ {error,Reason} ->
+ {error,Reason};
+ {Scheme,Host,Port,PathQuery} -> % Automatic redirection
+ NewReq=Req#request{redircount=Req#request.redircount+1,
+ address={Host,Port},pathquery=PathQuery},
+ handle_redirect(Session#session.clientclose,ServerClose,
+ NewReq,Session)
+ end
+ end;
+status_temporary_redirect(Headers,Body,Req,Session) ->
+ ServerClose=http_lib:connection_close(Headers),
+ gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
+ {307,Headers,Body}}),
+ handle_connection(Session#session.clientclose,ServerClose,Req,Session).
+
+
+
+%%% Received a 503 Status code ("Service Unavailable")
+%%% The server is currently unable to handle the request due to a
+%%% temporary overloading or maintenance of the server. The implication
+%%% is that this is a temporary condition which will be alleviated after
+%%% some delay. If known, the length of the delay MAY be indicated in a
+%%% Retry-After header. If no Retry-After is given, the client SHOULD
+%%% handle the response as it would for a 500 response.
+%% Note:
+%% - This session is now considered busy, thus cancel any requests in the
+%% pipeline and close the session.
+%% FIXME! Implement a user option to automatically retry if the 'Retry-After'
+%% header is given.
+status_service_unavailable(Resp,Req,Session) ->
+% RetryAfter=Headers#res_headers.retry_after,
+ gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,Resp}),
+ close_session(server_connection_close,Req,Session).
+
+
+%%% Received a 50x Status code (~ "Service Error")
+%%% Response status codes beginning with the digit "5" indicate cases in
+%%% which the server is aware that it has erred or is incapable of
+%%% performing the request.
+status_server_error_50x(Resp,Req,Session) ->
+ gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,Resp}),
+ close_session(server_connection_close,Req,Session).
+
+
+%%% Handles requests for redirects
+%%% The redirected request might be:
+%%% - FIXME! on another TCP session, another scheme
+%%% - on the same TCP session, same scheme
+%%% - on another TCP session , same scheme
+%%% However, in all cases treat it as a new request, with redircount updated.
+%%%
+%%% The redirect may fail, but this not a reason to close this session.
+%%% Instead return a error for this request, and continue as ok.
+handle_redirect(ClientClose,ServerClose,Req,Session) ->
+ case httpc_manager:request(Req) of
+ {ok,_ReqId} -> % FIXME Should I perhaps reuse the Reqid?
+ handle_connection(ClientClose,ServerClose,Req,Session);
+ {error,Reason} ->
+ gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
+ {error,Reason}}),
+ handle_connection(ClientClose,ServerClose,Req,Session)
+ end.
+
+%%% Check if the persistent connection flag is false (ie client request
+%%% non-persistive connection), or if the server requires a closed connection
+%%% (by sending a "Connection: close" header). If the connection required
+%%% non-persistent, we may close the connection immediately.
+handle_connection(ClientClose,ServerClose,Req,Session) ->
+ case {ClientClose,ServerClose} of
+ {false,false} ->
+ ok;
+ {false,true} -> % The server requests this session to be closed.
+ close_session(server_connection_close,Req,Session);
+ {true,_} -> % The client requested a non-persistent connection
+ close_session(client_connection_close,Req,Session)
+ end.
+
+
+%%% Close the session.
+%%% We now have three cases:
+%%% - Client request a non-persistent connection when initiating the request.
+%%% Session info not stored in httpc_manager
+%%% - Server requests a non-persistent connection when answering a request.
+%%% No need to resend request, but there might be a pipeline.
+%%% - Some kind of error
+%%% Close the session, we may then try resending all requests in the pipeline
+%%% including the current depending on the error.
+%%% FIXME! Should not always abort the session (see close_session in
+%%% httpc_manager for more details)
+close_session(client_connection_close,_Req,Session) ->
+ http_lib:close(Session#session.scheme,Session#session.socket),
+ stop;
+close_session(server_connection_close,Req,Session) ->
+ http_lib:close(Session#session.scheme,Session#session.socket),
+ httpc_manager:abort_session(Req#request.address,Session#session.id,
+ aborted_request),
+ stop.
+
+exit_session(Address,Session,Reason) ->
+ http_lib:close(Session#session.scheme,Session#session.socket),
+ httpc_manager:abort_session(Address,Session#session.id,Reason),
+ exit(normal).
+
+%%% This is the "normal" case to close a persistent connection. I.e., there are
+%%% no more requests waiting and the session was closed by the client, or
+%%% server because of a timeout or user request.
+exit_session_ok(Address,Session) ->
+ http_lib:close(Session#session.scheme,Session#session.socket),
+ exit_session_ok2(Address,Session#session.clientclose,Session#session.id).
+
+exit_session_ok2(Address,ClientClose,Sid) ->
+ case ClientClose of
+ false ->
+ httpc_manager:close_session(Address,Sid);
+ true ->
+ ok
+ end,
+ exit(normal).
+
+%%% ============================================================================
+%%% This is deprecated code, to be removed
+
+format_time() ->
+ {_,_,MicroSecs}=TS=now(),
+ {{Y,Mon,D},{H,M,S}}=calendar:now_to_universal_time(TS),
+ lists:flatten(io_lib:format("~4.4.0w-~2.2.0w-~2.2.0w,~2.2.0w:~2.2.0w:~6.3.0f",
+ [Y,Mon,D,H,M,S+(MicroSecs/1000000)])).
+
+%%% Read more data from the open socket.
+%%% Two different read functions is used because for the {active, once} socket
+%%% option is (currently) not available for SSL...
+%%% FIXME
+% read_more_data(http,Socket,Timeout) ->
+% io:format("read_more_data(ip_comm) -> "
+% "~n set active = 'once' and "
+% "await a chunk data", []),
+% http_lib:setopts(Socket, [{active,once}]),
+% read_more_data_ipcomm(Socket,Timeout);
+% read_more_data(https,Socket,Timeout) ->
+% case ssl:recv(Socket,0,Timeout) of
+% {ok,MoreData} ->
+% MoreData;
+% {error,closed} ->
+% throw({error, session_remotely_closed});
+% {error,etimedout} ->
+% throw({error, session_local_timeout});
+% {error,Reason} ->
+% throw({error, Reason});
+% Other ->
+% throw({error, Other})
+% end.
+
+% %%% Send any incoming requests on the open session immediately
+% read_more_data_ipcomm(Socket,Timeout) ->
+% receive
+% {tcp,Socket,MoreData} ->
+% % ?vtrace("read_more_data(ip_comm) -> got some data:~p",
+% % [MoreData]),
+% MoreData;
+% {tcp_closed,Socket} ->
+% % ?vtrace("read_more_data(ip_comm) -> socket closed",[]),
+% throw({error,session_remotely_closed});
+% {tcp_error,Socket,Reason} ->
+% % ?vtrace("read_more_data(ip_comm) -> ~p socket error: ~p",
+% % [self(),Reason]),
+% throw({error, Reason});
+% stop ->
+% throw({error, user_req})
+% after Timeout ->
+% throw({error, session_local_timeout})
+% end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpc_manager.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpc_manager.erl
new file mode 100644
index 0000000000..29659ce1ce
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpc_manager.erl
@@ -0,0 +1,542 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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 Mobile Arts AB
+%% Portions created by Mobile Arts are Copyright 2002, Mobile Arts AB
+%% All Rights Reserved.''
+%%
+%%
+%% Created : 18 Dec 2001 by Johan Blom <[email protected]>
+%%
+
+-module(httpc_manager).
+
+-behaviour(gen_server).
+
+-include("http.hrl").
+
+-define(HMACALL, ?MODULE).
+-define(HMANAME, ?MODULE).
+
+%%--------------------------------------------------------------------
+%% External exports
+-export([start_link/0,start/0,
+ request/1,cancel_request/1,
+ next_request/2,
+ register_socket/3,
+ abort_session/3,close_session/2,close_session/3
+ ]).
+
+%% Debugging only
+-export([status/0]).
+
+%% gen_server callbacks
+-export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,
+ code_change/3]).
+
+%%% address_db - ets() Contains mappings from a tuple {Host,Port} to a tuple
+%%% {LastSID,OpenSessions,ets()} where
+%%% LastSid is the last allocated session id,
+%%% OpenSessions is the number of currently open sessions and
+%%% ets() contains mappings from Session Id to #session{}.
+%%%
+%%% Note:
+%%% - Only persistent connections are stored in address_db
+%%% - When automatically redirecting, multiple requests are performed.
+-record(state,{
+ address_db, % ets()
+ reqid % int() Next Request id to use (identifies request).
+ }).
+
+%%====================================================================
+%% External functions
+%%====================================================================
+%%--------------------------------------------------------------------
+%% Function: start_link/0
+%% Description: Starts the server
+%%--------------------------------------------------------------------
+start() ->
+ ensure_started().
+
+start_link() ->
+ gen_server:start_link({local,?HMACALL}, ?HMANAME, [], []).
+
+
+%% Find available session process and store in address_db. If no
+%% available, start new handler process.
+request(Req) ->
+ ensure_started(),
+ ClientClose=http_lib:connection_close(Req#request.headers),
+ gen_server:call(?HMACALL,{request,ClientClose,Req},infinity).
+
+cancel_request(ReqId) ->
+ gen_server:call(?HMACALL,{cancel_request,ReqId},infinity).
+
+
+%%% Close Session
+close_session(Addr,Sid) ->
+ gen_server:call(?HMACALL,{close_session,Addr,Sid},infinity).
+close_session(Req,Addr,Sid) ->
+ gen_server:call(?HMACALL,{close_session,Req,Addr,Sid},infinity).
+
+abort_session(Addr,Sid,Msg) ->
+ gen_server:call(?HMACALL,{abort_session,Addr,Sid,Msg},infinity).
+
+
+%%% Pick next in request que
+next_request(Addr,Sid) ->
+ gen_server:call(?HMACALL,{next_request,Addr,Sid},infinity).
+
+%%% Session handler has succeded to set up a new session, now register
+%%% the socket
+register_socket(Addr,Sid,Socket) ->
+ gen_server:cast(?HMACALL,{register_socket,Addr,Sid,Socket}).
+
+
+%%% Debugging
+status() ->
+ gen_server:cast(?HMACALL,status).
+
+
+%%--------------------------------------------------------------------
+%% Function: init/1
+%% Description: Initiates the server
+%% Returns: {ok, State} |
+%% {ok, State, Timeout} |
+%% ignore |
+%% {stop, Reason}
+%%--------------------------------------------------------------------
+init([]) ->
+ process_flag(trap_exit, true),
+ {ok,#state{address_db=ets:new(address_db,[private]),
+ reqid=0}}.
+
+
+%%--------------------------------------------------------------------
+%% Function: handle_call/3
+%% Description: Handling call messages
+%% Returns: {reply, Reply, State} |
+%% {reply, Reply, State, Timeout} |
+%% {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, Reply, State} | (terminate/2 is called)
+%% {stop, Reason, State} (terminate/2 is called)
+%%--------------------------------------------------------------------
+%%% Note:
+%%% - We may have multiple non-persistent connections, each will be handled in
+%%% separate processes, thus don't add such connections to address_db
+handle_call({request,false,Req},_From,State) ->
+ case ets:lookup(State#state.address_db,Req#request.address) of
+ [] ->
+ STab=ets:new(session_db,[private,{keypos,2},set]),
+ case persistent_new_session_request(0,Req,STab,State) of
+ {Reply,LastSid,State2} ->
+ ets:insert(State2#state.address_db,
+ {Req#request.address,{LastSid,1,STab}}),
+ {reply,Reply,State2};
+ {ErrorReply,State2} ->
+ {reply,ErrorReply,State2}
+ end;
+ [{_,{LastSid,OpenS,STab}}] ->
+ case lookup_session_entry(STab) of
+ {ok,Session} ->
+ old_session_request(Session,Req,STab,State);
+ need_new_session when OpenS<(Req#request.settings)#client_settings.max_sessions ->
+ case persistent_new_session_request(LastSid,Req,
+ STab,State) of
+ {Reply,LastSid2,State2} ->
+ ets:insert(State2#state.address_db,
+ {Req#request.address,
+ {LastSid2,OpenS+1,STab}}),
+ {reply,Reply,State2};
+ {ErrorReply,State2} ->
+ {reply,ErrorReply,State2}
+ end;
+ need_new_session ->
+ {reply,{error,too_many_sessions},State}
+ end
+ end;
+handle_call({request,true,Req},_From,State) ->
+ {Reply,State2}=not_persistent_new_session_request(Req,State),
+ {reply,Reply,State2};
+handle_call({cancel_request,true,_ReqId},_From,State) ->
+%% FIXME Should be possible to scan through all requests made, but perhaps
+%% better to give some more hints (such as Addr etc)
+ Reply=ok,
+ {reply,Reply,State};
+handle_call({next_request,Addr,Sid},_From,State) ->
+ case ets:lookup(State#state.address_db,Addr) of
+ [] ->
+ {reply,{error,no_connection},State};
+ [{_,{_,_,STab}}] ->
+ case ets:lookup(STab,Sid) of
+ [] ->
+ {reply,{error,session_not_registered},State};
+ [S=#session{pipeline=[],quelength=QueLen}] ->
+ if
+ QueLen==1 ->
+ ets:insert(STab,S#session{quelength=0});
+ true ->
+ ok
+ end,
+ {reply,no_more_requests,State};
+ [S=#session{pipeline=Que}] ->
+ [Req|RevQue]=lists:reverse(Que),
+ ets:insert(STab,S#session{pipeline=lists:reverse(RevQue),
+ quelength=S#session.quelength-1}),
+ {reply,Req,State}
+ end
+ end;
+handle_call({close_session,Addr,Sid},_From,State) ->
+ case ets:lookup(State#state.address_db,Addr) of
+ [] ->
+ {reply,{error,no_connection},State};
+ [{_,{LastSid,OpenS,STab}}] ->
+ case ets:lookup(STab,Sid) of
+ [#session{pipeline=Que}] ->
+ R=handle_close_session(lists:reverse(Que),STab,Sid,State),
+ ets:insert(State#state.address_db,
+ {Addr,{LastSid,OpenS-1,STab}}),
+ {reply,R,State};
+ [] ->
+ {reply,{error,session_not_registered},State}
+ end
+ end;
+handle_call({close_session,Req,Addr,Sid},_From,State) ->
+ case ets:lookup(State#state.address_db,Addr) of
+ [] ->
+ {reply,{error,no_connection},State};
+ [{_,{LastSid,OpenS,STab}}] ->
+ case ets:lookup(STab,Sid) of
+ [#session{pipeline=Que}] ->
+ R=handle_close_session([Req|lists:reverse(Que)],
+ STab,Sid,State),
+ ets:insert(State#state.address_db,
+ {Addr,{LastSid,OpenS-1,STab}}),
+ {reply,R,State};
+ [] ->
+ {reply,{error,session_not_registered},State}
+ end
+ end;
+handle_call({abort_session,Addr,Sid,Msg},_From,State) ->
+ case ets:lookup(State#state.address_db,Addr) of
+ [] ->
+ {reply,{error,no_connection},State};
+ [{_,{LastSid,OpenS,STab}}] ->
+ case ets:lookup(STab,Sid) of
+ [#session{pipeline=Que}] ->
+ R=abort_request_que(Que,{error,Msg}),
+ ets:delete(STab,Sid),
+ ets:insert(State#state.address_db,
+ {Addr,{LastSid,OpenS-1,STab}}),
+ {reply,R,State};
+ [] ->
+ {reply,{error,session_not_registered},State}
+ end
+ end.
+
+
+%%--------------------------------------------------------------------
+%% Function: handle_cast/2
+%% Description: Handling cast messages
+%% Returns: {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State} (terminate/2 is called)
+%%--------------------------------------------------------------------
+handle_cast(status, State) ->
+ io:format("Status:~n"),
+ print_all(lists:sort(ets:tab2list(State#state.address_db))),
+ {noreply, State};
+handle_cast({register_socket,Addr,Sid,Socket},State) ->
+ case ets:lookup(State#state.address_db,Addr) of
+ [] ->
+ {noreply,State};
+ [{_,{_,_,STab}}] ->
+ case ets:lookup(STab,Sid) of
+ [Session] ->
+ ets:insert(STab,Session#session{socket=Socket}),
+ {noreply,State};
+ [] ->
+ {noreply,State}
+ end
+ end.
+
+print_all([]) ->
+ ok;
+print_all([{Addr,{LastSid,OpenSessions,STab}}|Rest]) ->
+ io:format(" Address:~p LastSid=~p OpenSessions=~p~n",[Addr,LastSid,OpenSessions]),
+ SortedList=lists:sort(fun(A,B) ->
+ if
+ A#session.id<B#session.id ->
+ true;
+ true ->
+ false
+ end
+ end,ets:tab2list(STab)),
+ print_all2(SortedList),
+ print_all(Rest).
+
+print_all2([]) ->
+ ok;
+print_all2([Session|Rest]) ->
+ io:format(" Session:~p~n",[Session#session.id]),
+ io:format(" Client close:~p~n",[Session#session.clientclose]),
+ io:format(" Socket:~p~n",[Session#session.socket]),
+ io:format(" Pipe: length=~p Que=~p~n",[Session#session.quelength,Session#session.pipeline]),
+ print_all2(Rest).
+
+%%--------------------------------------------------------------------
+%% Function: handle_info/2
+%% Description: Handling all non call/cast messages
+%% Returns: {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State} (terminate/2 is called)
+%%--------------------------------------------------------------------
+handle_info({'EXIT',_Pid,normal}, State) ->
+ {noreply, State};
+handle_info(Info, State) ->
+ io:format("ERROR httpc_manager:handle_info ~p~n",[Info]),
+ {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% Function: terminate/2
+%% Description: Shutdown the server
+%% Returns: any (ignored by gen_server)
+%%--------------------------------------------------------------------
+terminate(_Reason, State) ->
+ ets:delete(State#state.address_db).
+
+%%--------------------------------------------------------------------
+%% Func: code_change/3
+%% Purpose: Convert process state when code is changed
+%% Returns: {ok, NewState}
+%%--------------------------------------------------------------------
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+
+%%% From RFC 2616, Section 8.1.4
+%%% A client, server, or proxy MAY close the transport connection at any
+%%% time. For example, a client might have started to send a new request
+%%% at the same time that the server has decided to close the "idle"
+%%% connection. From the server's point of view, the connection is being
+%%% closed while it was idle, but from the client's point of view, a
+%%% request is in progress.
+%%%
+%%% This means that clients, servers, and proxies MUST be able to recover
+%%% from asynchronous close events. Client software SHOULD reopen the
+%%% transport connection and retransmit the aborted sequence of requests
+%%% without user interaction so long as the request sequence is
+%%% idempotent (see section 9.1.2). Non-idempotent methods or sequences
+%%%
+%%% FIXME
+%%% Note:
+%%% - If this happen (server close because of idle) there can't be any requests
+%%% in the que.
+%%% - This is the main function for closing of sessions
+handle_close_session([],STab,Sid,_State) ->
+ ets:delete(STab,Sid);
+handle_close_session(Que,STab,Sid,_State) ->
+ ets:delete(STab,Sid),
+ abort_request_que(Que,{error,aborted_request}).
+
+
+%%% From RFC 2616, Section 8.1.2.2
+%%% Clients which assume persistent connections and pipeline immediately
+%%% after connection establishment SHOULD be prepared to retry their
+%%% connection if the first pipelined attempt fails. If a client does
+%%% such a retry, it MUST NOT pipeline before it knows the connection is
+%%% persistent. Clients MUST also be prepared to resend their requests if
+%%% the server closes the connection before sending all of the
+%%% corresponding responses.
+%%% FIXME! I'm currently not checking if tis is the first attempt on the session
+%%% FIXME! Pipeline size must be dynamically variable (e.g. 0 if resend, 2 else)
+%%% The que contains requests that have been sent ok previously, but the session
+%%% was closed prematurely when reading the response.
+%%% Try setup a new session and resend these requests.
+%%% Note:
+%%% - This MUST be a persistent session
+% handle_closed_pipelined_session_que([],_State) ->
+% ok;
+% handle_closed_pipelined_session_que(_Que,_State) ->
+% ok.
+
+
+%%% From RFC 2616, Section 8.2.4
+%%% If an HTTP/1.1 client sends a request which includes a request body,
+%%% but which does not include an Expect request-header field with the
+%%% "100-continue" expectation, and if the client is not directly
+%%% connected to an HTTP/1.1 origin server, and if the client sees the
+%%% connection close before receiving any status from the server, the
+%%% client SHOULD retry the request. If the client does retry this
+%%% request, it MAY use the following "binary exponential backoff"
+%%% algorithm to be assured of obtaining a reliable response:
+%%% ...
+%%% FIXME! I'm currently not checking if a "Expect: 100-continue" has been sent.
+% handle_remotely_closed_session_que([],_State) ->
+% ok;
+% handle_remotely_closed_session_que(_Que,_State) ->
+% % resend_que(Que,Socket),
+% ok.
+
+%%% Resend all requests in the request que
+% resend_que([],_) ->
+% ok;
+% resend_que([Req|Que],Socket) ->
+% case catch httpc_handler:http_request(Req,Socket) of
+% ok ->
+% resend_que(Que,Socket);
+% {error,Reason} ->
+% {error,Reason}
+% end.
+
+
+%%% From RFC 2616,
+%%% Section 8.1.2.2:
+%%% Clients SHOULD NOT pipeline requests using non-idempotent methods or
+%%% non-idempotent sequences of methods (see section 9.1.2). Otherwise, a
+%%% premature termination of the transport connection could lead to
+%%% indeterminate results. A client wishing to send a non-idempotent
+%%% request SHOULD wait to send that request until it has received the
+%%% response status for the previous request.
+%%% Section 9.1.2:
+%%% Methods can also have the property of "idempotence" in that (aside
+%%% from error or expiration issues) the side-effects of N > 0 identical
+%%% requests is the same as for a single request. The methods GET, HEAD,
+%%% PUT and DELETE share this property. Also, the methods OPTIONS and
+%%% TRACE SHOULD NOT have side effects, and so are inherently idempotent.
+%%%
+%%% Note that POST and CONNECT are idempotent methods.
+%%%
+%%% Tries to find an open, free session i STab. Such a session has quelength
+%%% less than ?MAX_PIPELINE_LENGTH
+%%% Don't care about non-standard, user defined methods.
+%%%
+%%% Returns {ok,Session} or need_new_session where
+%%% Session is the session that may be used
+lookup_session_entry(STab) ->
+ MS=[{#session{quelength='$1',max_quelength='$2',
+ id='_',clientclose='_',socket='$3',scheme='_',pipeline='_'},
+ [{'<','$1','$2'},{is_port,'$3'}],
+ ['$_']}],
+ case ets:select(STab,MS) of
+ [] ->
+ need_new_session;
+ SessionList -> % Now check if any of these has an empty pipeline.
+ case lists:keysearch(0,2,SessionList) of
+ {value,Session} ->
+ {ok,Session};
+ false ->
+ {ok,hd(SessionList)}
+ end
+ end.
+
+
+%%% Returns a tuple {Reply,State} where
+%%% Reply is the response sent back to the application
+%%%
+%%% Note:
+%%% - An {error,einval} from a send should sometimes rather be {error,closed}
+%%% - Don't close the session from here, let httpc_handler take care of that.
+%old_session_request(Session,Req,STab,State)
+% when (Req#request.settings)#client_settings.max_quelength==0 ->
+% Session1=Session#session{pipeline=[Req]},
+% ets:insert(STab,Session1),
+% {reply,{ok,ReqId},State#state{reqid=ReqId+1}};
+old_session_request(Session,Req,STab,State) ->
+ ReqId=State#state.reqid,
+ Req1=Req#request{id=ReqId},
+ case catch httpc_handler:http_request(Req1,Session#session.socket) of
+ ok ->
+ Session1=Session#session{pipeline=[Req1|Session#session.pipeline],
+ quelength=Session#session.quelength+1},
+ ets:insert(STab,Session1),
+ {reply,{ok,ReqId},State#state{reqid=ReqId+1}};
+ {error,Reason} ->
+ ets:insert(STab,Session#session{socket=undefined}),
+% http_lib:close(Session#session.sockettype,Session#session.socket),
+ {reply,{error,Reason},State#state{reqid=ReqId+1}}
+ end.
+
+%%% Returns atuple {Reply,Sid,State} where
+%%% Reply is the response sent back to the application, and
+%%% Sid is the last used Session Id
+persistent_new_session_request(Sid,Req,STab,State) ->
+ ReqId=State#state.reqid,
+ case setup_new_session(Req#request{id=ReqId},false,Sid) of
+ {error,Reason} ->
+ {{error,Reason},State#state{reqid=ReqId+1}};
+ {NewSid,Session} ->
+ ets:insert(STab,Session),
+ {{ok,ReqId},NewSid,State#state{reqid=ReqId+1}}
+ end.
+
+%%% Returns a tuple {Reply,State} where
+%%% Reply is the response sent back to the application
+not_persistent_new_session_request(Req,State) ->
+ ReqId=State#state.reqid,
+ case setup_new_session(Req#request{id=ReqId},true,undefined) of
+ {error,Reason} ->
+ {{error,Reason},State#state{reqid=ReqId+1}};
+ ok ->
+ {{ok,ReqId},State#state{reqid=ReqId+1}}
+ end.
+
+%%% As there are no sessions available, setup a new session and send the request
+%%% on it.
+setup_new_session(Req,ClientClose,Sid) ->
+ S=#session{id=Sid,clientclose=ClientClose,
+ scheme=Req#request.scheme,
+ max_quelength=(Req#request.settings)#client_settings.max_quelength},
+ spawn_link(httpc_handler,init_connection,[Req,S]),
+ case ClientClose of
+ false ->
+ {Sid+1,S};
+ true ->
+ ok
+ end.
+
+
+%%% ----------------------------------------------------------------------------
+%%% Abort all requests in the request que.
+abort_request_que([],_Msg) ->
+ ok;
+abort_request_que([#request{from=From,ref=Ref,id=Id}|Que],Msg) ->
+ gen_server:cast(From,{Ref,Id,Msg}),
+ abort_request_que(Que,Msg);
+abort_request_que(#request{from=From,ref=Ref,id=Id},Msg) ->
+ gen_server:cast(From,{Ref,Id,Msg}).
+
+
+%%% --------------------------------
+% C={httpc_manager,{?MODULE,start_link,[]},permanent,1000,
+% worker,[?MODULE]},
+% supervisor:start_child(inets_sup, C),
+ensure_started() ->
+ case whereis(?HMANAME) of
+ undefined ->
+ start_link();
+ _ ->
+ ok
+ end.
+
+
+%%% ============================================================================
+%%% This is deprecated code, to be removed
+
+% format_time() ->
+% {_,_,MicroSecs}=TS=now(),
+% {{Y,Mon,D},{H,M,S}}=calendar:now_to_universal_time(TS),
+% lists:flatten(io_lib:format("~4.4.0w-~2.2.0w-~2.2.0w,~2.2.0w:~2.2.0w:~6.3.0f",
+% [Y,Mon,D,H,M,S+(MicroSecs/1000000)])).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd.erl
new file mode 100644
index 0000000000..3199e4430d
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd.erl
@@ -0,0 +1,594 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: httpd.erl,v 1.1 2008/12/17 09:53:33 mikpe Exp $
+%%
+-module(httpd).
+-export([multi_start/1, multi_start_link/1,
+ start/0, start/1, start/2,
+ start_link/0, start_link/1, start_link/2,
+ start_child/0,start_child/1,
+ multi_stop/1,
+ stop/0,stop/1,stop/2,
+ stop_child/0,stop_child/1,stop_child/2,
+ multi_restart/1,
+ restart/0,restart/1,restart/2,
+ parse_query/1]).
+
+%% Optional start related stuff...
+-export([load/1, load_mime_types/1,
+ start2/1, start2/2,
+ start_link2/1, start_link2/2,
+ stop2/1]).
+
+%% Management stuff
+-export([block/0,block/1,block/2,block/3,block/4,
+ unblock/0,unblock/1,unblock/2]).
+
+%% Debugging and status info stuff...
+-export([verbosity/3,verbosity/4]).
+-export([get_status/1,get_status/2,get_status/3,
+ get_admin_state/0,get_admin_state/1,get_admin_state/2,
+ get_usage_state/0,get_usage_state/1,get_usage_state/2]).
+
+-include("httpd.hrl").
+
+-define(D(F, A), io:format("~p:" ++ F ++ "~n", [?MODULE|A])).
+
+
+%% start
+
+start() ->
+ start("/var/tmp/server_root/conf/8888.conf").
+
+start(ConfigFile) ->
+ %% ?D("start(~s) -> entry", [ConfigFile]),
+ start(ConfigFile, []).
+
+start(ConfigFile, Verbosity) when list(ConfigFile), list(Verbosity) ->
+ httpd_sup:start(ConfigFile, Verbosity).
+
+
+%% start_link
+
+start_link() ->
+ start("/var/tmp/server_root/conf/8888.conf").
+
+start_link(ConfigFile) ->
+ start_link(ConfigFile, []).
+
+start_link(ConfigFile, Verbosity) when list(ConfigFile), list(Verbosity) ->
+ httpd_sup:start_link(ConfigFile, Verbosity).
+
+
+%% start2 & start_link2
+
+start2(Config) ->
+ start2(Config, []).
+
+start2(Config, Verbosity) when list(Config), list(Verbosity) ->
+ httpd_sup:start2(Config, Verbosity).
+
+start_link2(Config) ->
+ start_link2(Config, []).
+
+start_link2(Config, Verbosity) when list(Config), list(Verbosity) ->
+ httpd_sup:start_link2(Config, Verbosity).
+
+
+%% stop
+
+stop() ->
+ stop(8888).
+
+stop(Port) when integer(Port) ->
+ stop(undefined, Port);
+stop(Pid) when pid(Pid) ->
+ httpd_sup:stop(Pid);
+stop(ConfigFile) when list(ConfigFile) ->
+ %% ?D("stop(~s) -> entry", [ConfigFile]),
+ httpd_sup:stop(ConfigFile).
+
+stop(Addr, Port) when integer(Port) ->
+ httpd_sup:stop(Addr, Port).
+
+stop2(Config) when list(Config) ->
+ httpd_sup:stop2(Config).
+
+%% start_child
+
+start_child() ->
+ start_child("/var/tmp/server_root/conf/8888.conf").
+
+start_child(ConfigFile) ->
+ start_child(ConfigFile, []).
+
+start_child(ConfigFile, Verbosity) ->
+ inets_sup:start_child(ConfigFile, Verbosity).
+
+
+%% stop_child
+
+stop_child() ->
+ stop_child(8888).
+
+stop_child(Port) ->
+ stop_child(undefined,Port).
+
+stop_child(Addr, Port) when integer(Port) ->
+ inets_sup:stop_child(Addr, Port).
+
+
+%% multi_start
+
+multi_start(MultiConfigFile) ->
+ case read_multi_file(MultiConfigFile) of
+ {ok,ConfigFiles} ->
+ mstart(ConfigFiles);
+ Error ->
+ Error
+ end.
+
+mstart(ConfigFiles) ->
+ mstart(ConfigFiles,[]).
+mstart([],Results) ->
+ {ok,lists:reverse(Results)};
+mstart([H|T],Results) ->
+ Res = start(H),
+ mstart(T,[Res|Results]).
+
+
+%% multi_start_link
+
+multi_start_link(MultiConfigFile) ->
+ case read_multi_file(MultiConfigFile) of
+ {ok,ConfigFiles} ->
+ mstart_link(ConfigFiles);
+ Error ->
+ Error
+ end.
+
+mstart_link(ConfigFiles) ->
+ mstart_link(ConfigFiles,[]).
+mstart_link([],Results) ->
+ {ok,lists:reverse(Results)};
+mstart_link([H|T],Results) ->
+ Res = start_link(H),
+ mstart_link(T,[Res|Results]).
+
+
+%% multi_stop
+
+multi_stop(MultiConfigFile) ->
+ case read_multi_file(MultiConfigFile) of
+ {ok,ConfigFiles} ->
+ mstop(ConfigFiles);
+ Error ->
+ Error
+ end.
+
+mstop(ConfigFiles) ->
+ mstop(ConfigFiles,[]).
+mstop([],Results) ->
+ {ok,lists:reverse(Results)};
+mstop([H|T],Results) ->
+ Res = stop(H),
+ mstop(T,[Res|Results]).
+
+
+%% multi_restart
+
+multi_restart(MultiConfigFile) ->
+ case read_multi_file(MultiConfigFile) of
+ {ok,ConfigFiles} ->
+ mrestart(ConfigFiles);
+ Error ->
+ Error
+ end.
+
+mrestart(ConfigFiles) ->
+ mrestart(ConfigFiles,[]).
+mrestart([],Results) ->
+ {ok,lists:reverse(Results)};
+mrestart([H|T],Results) ->
+ Res = restart(H),
+ mrestart(T,[Res|Results]).
+
+
+%% restart
+
+restart() -> restart(undefined,8888).
+
+restart(Port) when integer(Port) ->
+ restart(undefined,Port);
+restart(ConfigFile) when list(ConfigFile) ->
+ case get_addr_and_port(ConfigFile) of
+ {ok,Addr,Port} ->
+ restart(Addr,Port);
+ Error ->
+ Error
+ end.
+
+
+restart(Addr,Port) when integer(Port) ->
+ do_restart(Addr,Port).
+
+do_restart(Addr,Port) when integer(Port) ->
+ Name = make_name(Addr,Port),
+ case whereis(Name) of
+ Pid when pid(Pid) ->
+ httpd_manager:restart(Pid);
+ _ ->
+ {error,not_started}
+ end.
+
+
+%%% =========================================================
+%%% Function: block/0, block/1, block/2, block/3, block/4
+%%% block()
+%%% block(Port)
+%%% block(ConfigFile)
+%%% block(Addr,Port)
+%%% block(Port,Mode)
+%%% block(ConfigFile,Mode)
+%%% block(Addr,Port,Mode)
+%%% block(ConfigFile,Mode,Timeout)
+%%% block(Addr,Port,Mode,Timeout)
+%%%
+%%% Returns: ok | {error,Reason}
+%%%
+%%% Description: This function is used to block an HTTP server.
+%%% The blocking can be done in two ways,
+%%% disturbing or non-disturbing. Default is disturbing.
+%%% When a HTTP server is blocked, all requests are rejected
+%%% (status code 503).
+%%%
+%%% disturbing:
+%%% By performing a disturbing block, the server
+%%% is blocked forcefully and all ongoing requests
+%%% are terminated. No new connections are accepted.
+%%% If a timeout time is given then, on-going requests
+%%% are given this much time to complete before the
+%%% server is forcefully blocked. In this case no new
+%%% connections is accepted.
+%%%
+%%% non-disturbing:
+%%% A non-disturbing block is more gracefull. No
+%%% new connections are accepted, but the ongoing
+%%% requests are allowed to complete.
+%%% If a timeout time is given, it waits this long before
+%%% giving up (the block operation is aborted and the
+%%% server state is once more not-blocked).
+%%%
+%%% Types: Port -> integer()
+%%% Addr -> {A,B,C,D} | string() | undefined
+%%% ConfigFile -> string()
+%%% Mode -> disturbing | non_disturbing
+%%% Timeout -> integer()
+%%%
+block() -> block(undefined,8888,disturbing).
+
+block(Port) when integer(Port) ->
+ block(undefined,Port,disturbing);
+
+block(ConfigFile) when list(ConfigFile) ->
+ case get_addr_and_port(ConfigFile) of
+ {ok,Addr,Port} ->
+ block(Addr,Port,disturbing);
+ Error ->
+ Error
+ end.
+
+block(Addr,Port) when integer(Port) ->
+ block(Addr,Port,disturbing);
+
+block(Port,Mode) when integer(Port), atom(Mode) ->
+ block(undefined,Port,Mode);
+
+block(ConfigFile,Mode) when list(ConfigFile), atom(Mode) ->
+ case get_addr_and_port(ConfigFile) of
+ {ok,Addr,Port} ->
+ block(Addr,Port,Mode);
+ Error ->
+ Error
+ end.
+
+
+block(Addr,Port,disturbing) when integer(Port) ->
+ do_block(Addr,Port,disturbing);
+block(Addr,Port,non_disturbing) when integer(Port) ->
+ do_block(Addr,Port,non_disturbing);
+
+block(ConfigFile,Mode,Timeout) when list(ConfigFile), atom(Mode), integer(Timeout) ->
+ case get_addr_and_port(ConfigFile) of
+ {ok,Addr,Port} ->
+ block(Addr,Port,Mode,Timeout);
+ Error ->
+ Error
+ end.
+
+
+block(Addr,Port,non_disturbing,Timeout) when integer(Port), integer(Timeout) ->
+ do_block(Addr,Port,non_disturbing,Timeout);
+block(Addr,Port,disturbing,Timeout) when integer(Port), integer(Timeout) ->
+ do_block(Addr,Port,disturbing,Timeout).
+
+do_block(Addr,Port,Mode) when integer(Port), atom(Mode) ->
+ Name = make_name(Addr,Port),
+ case whereis(Name) of
+ Pid when pid(Pid) ->
+ httpd_manager:block(Pid,Mode);
+ _ ->
+ {error,not_started}
+ end.
+
+
+do_block(Addr,Port,Mode,Timeout) when integer(Port), atom(Mode) ->
+ Name = make_name(Addr,Port),
+ case whereis(Name) of
+ Pid when pid(Pid) ->
+ httpd_manager:block(Pid,Mode,Timeout);
+ _ ->
+ {error,not_started}
+ end.
+
+
+%%% =========================================================
+%%% Function: unblock/0, unblock/1, unblock/2
+%%% unblock()
+%%% unblock(Port)
+%%% unblock(ConfigFile)
+%%% unblock(Addr,Port)
+%%%
+%%% Description: This function is used to reverse a previous block
+%%% operation on the HTTP server.
+%%%
+%%% Types: Port -> integer()
+%%% Addr -> {A,B,C,D} | string() | undefined
+%%% ConfigFile -> string()
+%%%
+unblock() -> unblock(undefined,8888).
+unblock(Port) when integer(Port) -> unblock(undefined,Port);
+
+unblock(ConfigFile) when list(ConfigFile) ->
+ case get_addr_and_port(ConfigFile) of
+ {ok,Addr,Port} ->
+ unblock(Addr,Port);
+ Error ->
+ Error
+ end.
+
+unblock(Addr,Port) when integer(Port) ->
+ Name = make_name(Addr,Port),
+ case whereis(Name) of
+ Pid when pid(Pid) ->
+ httpd_manager:unblock(Pid);
+ _ ->
+ {error,not_started}
+ end.
+
+
+verbosity(Port,Who,Verbosity) ->
+ verbosity(undefined,Port,Who,Verbosity).
+
+verbosity(Addr,Port,Who,Verbosity) ->
+ Name = make_name(Addr,Port),
+ case whereis(Name) of
+ Pid when pid(Pid) ->
+ httpd_manager:verbosity(Pid,Who,Verbosity);
+ _ ->
+ not_started
+ end.
+
+
+%%% =========================================================
+%%% Function: get_admin_state/0, get_admin_state/1, get_admin_state/2
+%%% get_admin_state()
+%%% get_admin_state(Port)
+%%% get_admin_state(Addr,Port)
+%%%
+%%% Returns: {ok,State} | {error,Reason}
+%%%
+%%% Description: This function is used to retrieve the administrative
+%%% state of the HTTP server.
+%%%
+%%% Types: Port -> integer()
+%%% Addr -> {A,B,C,D} | string() | undefined
+%%% State -> unblocked | shutting_down | blocked
+%%% Reason -> term()
+%%%
+get_admin_state() -> get_admin_state(undefined,8888).
+get_admin_state(Port) when integer(Port) -> get_admin_state(undefined,Port);
+
+get_admin_state(ConfigFile) when list(ConfigFile) ->
+ case get_addr_and_port(ConfigFile) of
+ {ok,Addr,Port} ->
+ unblock(Addr,Port);
+ Error ->
+ Error
+ end.
+
+get_admin_state(Addr,Port) when integer(Port) ->
+ Name = make_name(Addr,Port),
+ case whereis(Name) of
+ Pid when pid(Pid) ->
+ httpd_manager:get_admin_state(Pid);
+ _ ->
+ {error,not_started}
+ end.
+
+
+
+%%% =========================================================
+%%% Function: get_usage_state/0, get_usage_state/1, get_usage_state/2
+%%% get_usage_state()
+%%% get_usage_state(Port)
+%%% get_usage_state(Addr,Port)
+%%%
+%%% Returns: {ok,State} | {error,Reason}
+%%%
+%%% Description: This function is used to retrieve the usage
+%%% state of the HTTP server.
+%%%
+%%% Types: Port -> integer()
+%%% Addr -> {A,B,C,D} | string() | undefined
+%%% State -> idle | active | busy
+%%% Reason -> term()
+%%%
+get_usage_state() -> get_usage_state(undefined,8888).
+get_usage_state(Port) when integer(Port) -> get_usage_state(undefined,Port);
+
+get_usage_state(ConfigFile) when list(ConfigFile) ->
+ case get_addr_and_port(ConfigFile) of
+ {ok,Addr,Port} ->
+ unblock(Addr,Port);
+ Error ->
+ Error
+ end.
+
+get_usage_state(Addr,Port) when integer(Port) ->
+ Name = make_name(Addr,Port),
+ case whereis(Name) of
+ Pid when pid(Pid) ->
+ httpd_manager:get_usage_state(Pid);
+ _ ->
+ {error,not_started}
+ end.
+
+
+
+%%% =========================================================
+%% Function: get_status(ConfigFile) -> Status
+%% get_status(Port) -> Status
+%% get_status(Addr,Port) -> Status
+%% get_status(Port,Timeout) -> Status
+%% get_status(Addr,Port,Timeout) -> Status
+%%
+%% Arguments: ConfigFile -> string()
+%% Configuration file from which Port and
+%% BindAddress will be extracted.
+%% Addr -> {A,B,C,D} | string()
+%% Bind Address of the http server
+%% Port -> integer()
+%% Port number of the http server
+%% Timeout -> integer()
+%% Timeout time for the call
+%%
+%% Returns: Status -> list()
+%%
+%% Description: This function is used when the caller runs in the
+%% same node as the http server or if calling with a
+%% program such as erl_call (see erl_interface).
+%%
+
+get_status(ConfigFile) when list(ConfigFile) ->
+ case get_addr_and_port(ConfigFile) of
+ {ok,Addr,Port} ->
+ get_status(Addr,Port);
+ Error ->
+ Error
+ end;
+
+get_status(Port) when integer(Port) ->
+ get_status(undefined,Port,5000).
+
+get_status(Port,Timeout) when integer(Port), integer(Timeout) ->
+ get_status(undefined,Port,Timeout);
+
+get_status(Addr,Port) when list(Addr), integer(Port) ->
+ get_status(Addr,Port,5000).
+
+get_status(Addr,Port,Timeout) when integer(Port) ->
+ Name = make_name(Addr,Port),
+ case whereis(Name) of
+ Pid when pid(Pid) ->
+ httpd_manager:get_status(Pid,Timeout);
+ _ ->
+ not_started
+ end.
+
+
+%% load config
+
+load(ConfigFile) ->
+ httpd_conf:load(ConfigFile).
+
+load_mime_types(MimeTypesFile) ->
+ httpd_conf:load_mime_types(MimeTypesFile).
+
+
+%% parse_query
+
+parse_query(String) ->
+ {ok, SplitString} = regexp:split(String,"[&;]"),
+ foreach(SplitString).
+
+foreach([]) ->
+ [];
+foreach([KeyValue|Rest]) ->
+ {ok, Plus2Space, _} = regexp:gsub(KeyValue,"[\+]"," "),
+ case regexp:split(Plus2Space,"=") of
+ {ok,[Key|Value]} ->
+ [{httpd_util:decode_hex(Key),
+ httpd_util:decode_hex(lists:flatten(Value))}|foreach(Rest)];
+ {ok,_} ->
+ foreach(Rest)
+ end.
+
+
+%% get_addr_and_port
+
+get_addr_and_port(ConfigFile) ->
+ case httpd_conf:load(ConfigFile) of
+ {ok,ConfigList} ->
+ Port = httpd_util:key1search(ConfigList,port,80),
+ Addr = httpd_util:key1search(ConfigList,bind_address),
+ {ok,Addr,Port};
+ Error ->
+ Error
+ end.
+
+
+%% make_name
+
+make_name(Addr,Port) ->
+ httpd_util:make_name("httpd",Addr,Port).
+
+
+%% Multi stuff
+%%
+
+read_multi_file(File) ->
+ read_mfile(file:open(File,[read])).
+
+read_mfile({ok,Fd}) ->
+ read_mfile(read_line(Fd),Fd,[]);
+read_mfile(Error) ->
+ Error.
+
+read_mfile(eof,_Fd,SoFar) ->
+ {ok,lists:reverse(SoFar)};
+read_mfile({error,Reason},_Fd,SoFar) ->
+ {error,Reason};
+read_mfile([$#|Comment],Fd,SoFar) ->
+ read_mfile(read_line(Fd),Fd,SoFar);
+read_mfile([],Fd,SoFar) ->
+ read_mfile(read_line(Fd),Fd,SoFar);
+read_mfile(Line,Fd,SoFar) ->
+ read_mfile(read_line(Fd),Fd,[Line|SoFar]).
+
+read_line(Fd) -> read_line1(io:get_line(Fd,[])).
+read_line1(eof) -> eof;
+read_line1(String) -> httpd_conf:clean(String).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd.hrl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd.hrl
new file mode 100644
index 0000000000..015c1b1e2d
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd.hrl
@@ -0,0 +1,77 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: httpd.hrl,v 1.1 2008/12/17 09:53:33 mikpe Exp $
+%%
+
+-include_lib("kernel/include/file.hrl").
+
+-ifndef(SERVER_SOFTWARE).
+-define(SERVER_SOFTWARE,"inets/develop"). % Define in Makefile!
+-endif.
+-define(SERVER_PROTOCOL,"HTTP/1.1").
+-define(SOCKET_CHUNK_SIZE,8192).
+-define(SOCKET_MAX_POLL,25).
+-define(FILE_CHUNK_SIZE,64*1024).
+-define(NICE(Reason),lists:flatten(atom_to_list(?MODULE)++": "++Reason)).
+-define(DEFAULT_CONTEXT,
+ [{errmsg,"[an error occurred while processing this directive]"},
+ {timefmt,"%A, %d-%b-%y %T %Z"},
+ {sizefmt,"abbrev"}]).
+
+
+-ifdef(inets_error).
+-define(ERROR(Format, Args), io:format("E(~p:~p:~p) : "++Format++"~n",
+ [self(),?MODULE,?LINE]++Args)).
+-else.
+-define(ERROR(F,A),[]).
+-endif.
+
+-ifdef(inets_log).
+-define(LOG(Format, Args), io:format("L(~p:~p:~p) : "++Format++"~n",
+ [self(),?MODULE,?LINE]++Args)).
+-else.
+-define(LOG(F,A),[]).
+-endif.
+
+-ifdef(inets_debug).
+-define(DEBUG(Format, Args), io:format("D(~p:~p:~p) : "++Format++"~n",
+ [self(),?MODULE,?LINE]++Args)).
+-else.
+-define(DEBUG(F,A),[]).
+-endif.
+
+-ifdef(inets_cdebug).
+-define(CDEBUG(Format, Args), io:format("C(~p:~p:~p) : "++Format++"~n",
+ [self(),?MODULE,?LINE]++Args)).
+-else.
+-define(CDEBUG(F,A),[]).
+-endif.
+
+
+-record(init_data,{peername,resolve}).
+-record(mod,{init_data,
+ data=[],
+ socket_type=ip_comm,
+ socket,
+ config_db,
+ method,
+ absolute_uri=[],
+ request_uri,
+ http_version,
+ request_line,
+ parsed_header=[],
+ entity_body,
+ connection}).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_acceptor.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_acceptor.erl
new file mode 100644
index 0000000000..7bf2d5d868
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_acceptor.erl
@@ -0,0 +1,174 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: httpd_acceptor.erl,v 1.1 2008/12/17 09:53:33 mikpe Exp $
+%%
+-module(httpd_acceptor).
+
+-include("httpd.hrl").
+-include("httpd_verbosity.hrl").
+
+
+%% External API
+-export([start_link/6]).
+
+%% Other exports (for spawn's etc.)
+-export([acceptor/4, acceptor/7]).
+
+
+%%
+%% External API
+%%
+
+%% start_link
+
+start_link(Manager, SocketType, Addr, Port, ConfigDb, Verbosity) ->
+ Args = [self(), Manager, SocketType, Addr, Port, ConfigDb, Verbosity],
+ proc_lib:start_link(?MODULE, acceptor, Args).
+
+
+acceptor(Parent, Manager, SocketType, Addr, Port, ConfigDb, Verbosity) ->
+ put(sname,acc),
+ put(verbosity,Verbosity),
+ ?vlog("starting",[]),
+ case (catch do_init(SocketType, Addr, Port)) of
+ {ok, ListenSocket} ->
+ proc_lib:init_ack(Parent, {ok, self()}),
+ acceptor(Manager, SocketType, ListenSocket, ConfigDb);
+ Error ->
+ proc_lib:init_ack(Parent, Error),
+ error
+ end.
+
+do_init(SocketType, Addr, Port) ->
+ do_socket_start(SocketType),
+ ListenSocket = do_socket_listen(SocketType, Addr, Port),
+ {ok, ListenSocket}.
+
+
+do_socket_start(SocketType) ->
+ case httpd_socket:start(SocketType) of
+ ok ->
+ ok;
+ {error, Reason} ->
+ ?vinfo("failed socket start: ~p",[Reason]),
+ throw({error, {socket_start_failed, Reason}})
+ end.
+
+
+do_socket_listen(SocketType, Addr, Port) ->
+ case httpd_socket:listen(SocketType, Addr, Port) of
+ {error, Reason} ->
+ ?vinfo("failed socket listen operation: ~p", [Reason]),
+ throw({error, {listen, Reason}});
+ ListenSocket ->
+ ListenSocket
+ end.
+
+
+%% acceptor
+
+acceptor(Manager, SocketType, ListenSocket, ConfigDb) ->
+ ?vdebug("await connection",[]),
+ case (catch httpd_socket:accept(SocketType, ListenSocket, 30000)) of
+ {error, Reason} ->
+ handle_error(Reason, ConfigDb, SocketType),
+ ?MODULE:acceptor(Manager, SocketType, ListenSocket, ConfigDb);
+
+ {'EXIT', Reason} ->
+ handle_error({'EXIT', Reason}, ConfigDb, SocketType),
+ ?MODULE:acceptor(Manager, SocketType, ListenSocket, ConfigDb);
+
+ Socket ->
+ handle_connection(Manager, ConfigDb, SocketType, Socket),
+ ?MODULE:acceptor(Manager, SocketType, ListenSocket, ConfigDb)
+ end.
+
+
+handle_connection(Manager, ConfigDb, SocketType, Socket) ->
+ case httpd_request_handler:start_link(Manager, ConfigDb) of
+ {ok, Pid} ->
+ httpd_socket:controlling_process(SocketType, Socket, Pid),
+ httpd_request_handler:synchronize(Pid, SocketType, Socket);
+ {error, Reason} ->
+ handle_connection_err(SocketType, Socket, ConfigDb, Reason)
+ end.
+
+
+handle_connection_err(SocketType, Socket, ConfigDb, Reason) ->
+ String =
+ lists:flatten(
+ io_lib:format("failed starting request handler:~n ~p", [Reason])),
+ report_error(ConfigDb, String),
+ httpd_socket:close(SocketType, Socket).
+
+
+handle_error(timeout, _, _) ->
+ ?vtrace("Accept timeout",[]),
+ ok;
+
+handle_error({enfile, _}, _, _) ->
+ ?vinfo("Accept error: enfile",[]),
+ %% Out of sockets...
+ sleep(200);
+
+handle_error(emfile, _, _) ->
+ ?vinfo("Accept error: emfile",[]),
+ %% Too many open files -> Out of sockets...
+ sleep(200);
+
+handle_error(closed, _, _) ->
+ ?vlog("Accept error: closed",[]),
+ %% This propably only means that the application is stopping,
+ %% but just in case
+ exit(closed);
+
+handle_error(econnaborted, _, _) ->
+ ?vlog("Accept aborted",[]),
+ ok;
+
+handle_error(esslaccept, _, _) ->
+ %% The user has selected to cancel the installation of
+ %% the certifikate, This is not a real error, so we do
+ %% not write an error message.
+ ok;
+
+handle_error({'EXIT', Reason}, ConfigDb, SocketType) ->
+ ?vinfo("Accept exit:~n ~p",[Reason]),
+ String = lists:flatten(io_lib:format("Accept exit: ~p", [Reason])),
+ accept_failed(SocketType, ConfigDb, String);
+
+handle_error(Reason, ConfigDb, SocketType) ->
+ ?vinfo("Accept error:~n ~p",[Reason]),
+ String = lists:flatten(io_lib:format("Accept error: ~p", [Reason])),
+ accept_failed(SocketType, ConfigDb, String).
+
+
+accept_failed(SocketType, ConfigDb, String) ->
+ error_logger:error_report(String),
+ mod_log:error_log(SocketType, undefined, ConfigDb,
+ {0, "unknown"}, String),
+ mod_disk_log:error_log(SocketType, undefined, ConfigDb,
+ {0, "unknown"}, String),
+ exit({accept_failed, String}).
+
+
+report_error(Db, String) ->
+ error_logger:error_report(String),
+ mod_log:report_error(Db, String),
+ mod_disk_log:report_error(Db, String).
+
+
+sleep(T) -> receive after T -> ok end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_acceptor_sup.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_acceptor_sup.erl
new file mode 100644
index 0000000000..86c31ad5df
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_acceptor_sup.erl
@@ -0,0 +1,116 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: httpd_acceptor_sup.erl,v 1.1 2008/12/17 09:53:33 mikpe Exp $
+%%
+%%----------------------------------------------------------------------
+%% Purpose: The top supervisor for the Megaco/H.248 application
+%%----------------------------------------------------------------------
+
+-module(httpd_acceptor_sup).
+
+-behaviour(supervisor).
+
+-include("httpd_verbosity.hrl").
+
+%% public
+-export([start/3, stop/1, init/1]).
+
+-export([start_acceptor/4, stop_acceptor/2]).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% supervisor callback functions
+
+
+start(Addr, Port, AccSupVerbosity) ->
+ SupName = make_name(Addr, Port),
+ supervisor:start_link({local, SupName}, ?MODULE, [AccSupVerbosity]).
+
+stop(StartArgs) ->
+ ok.
+
+init([Verbosity]) -> % Supervisor
+ do_init(Verbosity);
+init(BadArg) ->
+ {error, {badarg, BadArg}}.
+
+do_init(Verbosity) ->
+ put(verbosity,?vvalidate(Verbosity)),
+ put(sname,acc_sup),
+ ?vlog("starting", []),
+ Flags = {one_for_one, 500, 100},
+ KillAfter = timer:seconds(1),
+ Workers = [],
+ {ok, {Flags, Workers}}.
+
+
+%%----------------------------------------------------------------------
+%% Function: [start|stop]_acceptor/5
+%% Description: Starts a [auth | security] worker (child) process
+%%----------------------------------------------------------------------
+
+start_acceptor(SocketType, Addr, Port, ConfigDb) ->
+ Verbosity = get_acc_verbosity(),
+ start_worker(httpd_acceptor, SocketType, Addr, Port,
+ ConfigDb, Verbosity, self(), []).
+
+stop_acceptor(Addr, Port) ->
+ stop_worker(httpd_acceptor, Addr, Port).
+
+
+%%----------------------------------------------------------------------
+%% Function: start_worker/5
+%% Description: Starts a (permanent) worker (child) process
+%%----------------------------------------------------------------------
+
+start_worker(M, SocketType, Addr, Port, ConfigDB, Verbosity, Manager,
+ Modules) ->
+ SupName = make_name(Addr, Port),
+ Args = [Manager, SocketType, Addr, Port, ConfigDB, Verbosity],
+ Spec = {{M, Addr, Port},
+ {M, start_link, Args},
+ permanent, timer:seconds(1), worker, [M] ++ Modules},
+ supervisor:start_child(SupName, Spec).
+
+
+%%----------------------------------------------------------------------
+%% Function: stop_permanent_worker/3
+%% Description: Stops a permanent worker (child) process
+%%----------------------------------------------------------------------
+
+stop_worker(M, Addr, Port) ->
+ SupName = make_name(Addr, Port),
+ Name = {M, Addr, Port},
+ case supervisor:terminate_child(SupName, Name) of
+ ok ->
+ supervisor:delete_child(SupName, Name);
+ Error ->
+ Error
+ end.
+
+
+make_name(Addr,Port) ->
+ httpd_util:make_name("httpd_acc_sup",Addr,Port).
+
+
+
+get_acc_verbosity() ->
+ get_verbosity(get(acceptor_verbosity)).
+
+get_verbosity(undefined) ->
+ ?default_verbosity;
+get_verbosity(V) ->
+ ?vvalidate(V).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_conf.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_conf.erl
new file mode 100644
index 0000000000..69419b1eb3
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_conf.erl
@@ -0,0 +1,688 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: httpd_conf.erl,v 1.1 2008/12/17 09:53:33 mikpe Exp $
+%%
+-module(httpd_conf).
+-export([load/1, load_mime_types/1,
+ load/2, store/1, store/2,
+ remove_all/1, remove/1,
+ is_directory/1, is_file/1,
+ make_integer/1, clean/1, custom_clean/3, check_enum/2]).
+
+
+-define(VMODULE,"CONF").
+-include("httpd_verbosity.hrl").
+
+%% The configuration data is handled in three (3) phases:
+%% 1. Parse the config file and put all directives into a key-vale
+%% tuple list (load/1).
+%% 2. Traverse the key-value tuple list store it into an ETS table.
+%% Directives depending on other directives are taken care of here
+%% (store/1).
+%% 3. Traverse the ETS table and do a complete clean-up (remove/1).
+
+-include("httpd.hrl").
+
+%%
+%% Phase 1: Load
+%%
+
+%% load
+
+load(ConfigFile) ->
+ ?CDEBUG("load -> ConfigFile: ~p",[ConfigFile]),
+ case read_config_file(ConfigFile) of
+ {ok, Config} ->
+ case bootstrap(Config) of
+ {error, Reason} ->
+ {error, Reason};
+ {ok, Modules} ->
+ load_config(Config, lists:append(Modules, [?MODULE]))
+ end;
+ {error, Reason} ->
+ {error, ?NICE("Error while reading config file: "++Reason)}
+ end.
+
+
+bootstrap([]) ->
+ {error, ?NICE("Modules must be specified in the config file")};
+bootstrap([Line|Config]) ->
+ case Line of
+ [$M,$o,$d,$u,$l,$e,$s,$ |Modules] ->
+ {ok, ModuleList} = regexp:split(Modules," "),
+ TheMods = [list_to_atom(X) || X <- ModuleList],
+ case verify_modules(TheMods) of
+ ok ->
+ {ok, TheMods};
+ {error, Reason} ->
+ ?ERROR("bootstrap -> : validation failed: ~p",[Reason]),
+ {error, Reason}
+ end;
+ _ ->
+ bootstrap(Config)
+ end.
+
+
+%%
+%% verify_modules/1 -> ok | {error, Reason}
+%%
+%% Verifies that all specified modules are available.
+%%
+verify_modules([]) ->
+ ok;
+verify_modules([Mod|Rest]) ->
+ case code:which(Mod) of
+ non_existing ->
+ {error, ?NICE(atom_to_list(Mod)++" does not exist")};
+ Path ->
+ verify_modules(Rest)
+ end.
+
+%%
+%% read_config_file/1 -> {ok, [line(), line()..]} | {error, Reason}
+%%
+%% Reads the entire configuration file and returns list of strings or
+%% and error.
+%%
+
+
+read_config_file(FileName) ->
+ case file:open(FileName, [read]) of
+ {ok, Stream} ->
+ read_config_file(Stream, []);
+ {error, Reason} ->
+ {error, ?NICE("Cannot open "++FileName)}
+ end.
+
+read_config_file(Stream, SoFar) ->
+ case io:get_line(Stream, []) of
+ eof ->
+ {ok, lists:reverse(SoFar)};
+ {error, Reason} ->
+ {error, Reason};
+ [$#|Rest] ->
+ %% Ignore commented lines for efficiency later ..
+ read_config_file(Stream, SoFar);
+ Line ->
+ {ok, NewLine, _}=regexp:sub(clean(Line),"[\t\r\f ]"," "),
+ case NewLine of
+ [] ->
+ %% Also ignore empty lines ..
+ read_config_file(Stream, SoFar);
+ Other ->
+ read_config_file(Stream, [NewLine|SoFar])
+ end
+ end.
+
+is_exported(Module, ToFind) ->
+ Exports = Module:module_info(exports),
+ lists:member(ToFind, Exports).
+
+%%
+%% load/4 -> {ok, ConfigList} | {error, Reason}
+%%
+%% This loads the config file into each module specified by Modules
+%% Each module has its own context that is passed to and (optionally)
+%% returned by the modules load function. The module can also return
+%% a ConfigEntry, which will be added to the global configuration
+%% list.
+%% All configuration directives are guaranteed to be passed to all
+%% modules. Each module only implements the function clauses of
+%% the load function for the configuration directives it supports,
+%% it's ok if an apply returns {'EXIT', {function_clause, ..}}.
+%%
+load_config(Config, Modules) ->
+ %% Create default contexts for all modules
+ Contexts = lists:duplicate(length(Modules), []),
+ load_config(Config, Modules, Contexts, []).
+
+
+load_config([], _Modules, _Contexts, ConfigList) ->
+ case a_must(ConfigList, [server_name,port,server_root,document_root]) of
+ ok ->
+ {ok, ConfigList};
+ {missing, Directive} ->
+ {error, ?NICE(atom_to_list(Directive)++
+ " must be specified in the config file")}
+ end;
+
+load_config([Line|Config], Modules, Contexts, ConfigList) ->
+ ?CDEBUG("load_config -> Line: ~p",[Line]),
+ case load_traverse(Line, Contexts, Modules, [], ConfigList, no) of
+ {ok, NewContexts, NewConfigList} ->
+ load_config(Config, Modules, NewContexts, NewConfigList);
+ {error, Reason} ->
+ ?ERROR("load_config -> traverse failed: ~p",[Reason]),
+ {error, Reason}
+ end.
+
+
+load_traverse(Line, [], [], NewContexts, ConfigList, no) ->
+ ?CDEBUG("load_traverse/no -> ~n"
+ " Line: ~p~n"
+ " NewContexts: ~p~n"
+ " ConfigList: ~p",
+ [Line,NewContexts,ConfigList]),
+ {error, ?NICE("Configuration directive not recognized: "++Line)};
+load_traverse(Line, [], [], NewContexts, ConfigList, yes) ->
+ ?CDEBUG("load_traverse/yes -> ~n"
+ " Line: ~p~n"
+ " NewContexts: ~p~n"
+ " ConfigList: ~p",
+ [Line,NewContexts,ConfigList]),
+ {ok, lists:reverse(NewContexts), ConfigList};
+load_traverse(Line, [Context|Contexts], [Module|Modules], NewContexts, ConfigList, State) ->
+ ?CDEBUG("load_traverse/~p -> ~n"
+ " Line: ~p~n"
+ " Module: ~p~n"
+ " Context: ~p~n"
+ " Contexts: ~p~n"
+ " NewContexts: ~p",
+ [State,Line,Module,Context,Contexts,NewContexts]),
+ case is_exported(Module, {load, 2}) of
+ true ->
+ ?CDEBUG("load_traverse -> ~p:load/2 exported",[Module]),
+ case catch apply(Module, load, [Line, Context]) of
+ {'EXIT', {function_clause, _}} ->
+ ?CDEBUG("load_traverse -> exit: function_clause"
+ "~n Module: ~p"
+ "~n Line: ~s",[Module,Line]),
+ load_traverse(Line, Contexts, Modules, [Context|NewContexts], ConfigList, State);
+ {'EXIT', Reason} ->
+ ?CDEBUG("load_traverse -> exit: ~p",[Reason]),
+ error_logger:error_report({'EXIT', Reason}),
+ load_traverse(Line, Contexts, Modules, [Context|NewContexts], ConfigList, State);
+ {ok, NewContext} ->
+ ?CDEBUG("load_traverse -> ~n"
+ " NewContext: ~p",[NewContext]),
+ load_traverse(Line, Contexts, Modules, [NewContext|NewContexts], ConfigList,yes);
+ {ok, NewContext, ConfigEntry} when tuple(ConfigEntry) ->
+ ?CDEBUG("load_traverse (tuple) -> ~n"
+ " NewContext: ~p~n"
+ " ConfigEntry: ~p",[NewContext,ConfigEntry]),
+ load_traverse(Line, Contexts, Modules, [NewContext|NewContexts],
+ [ConfigEntry|ConfigList], yes);
+ {ok, NewContext, ConfigEntry} when list(ConfigEntry) ->
+ ?CDEBUG("load_traverse (list) -> ~n"
+ " NewContext: ~p~n"
+ " ConfigEntry: ~p",[NewContext,ConfigEntry]),
+ load_traverse(Line, Contexts, Modules, [NewContext|NewContexts],
+ lists:append(ConfigEntry, ConfigList), yes);
+ {error, Reason} ->
+ ?CDEBUG("load_traverse -> error: ~p",[Reason]),
+ {error, Reason}
+ end;
+ false ->
+ ?CDEBUG("load_traverse -> ~p:load/2 not exported",[Module]),
+ load_traverse(Line, Contexts, Modules, [Context|NewContexts],
+ ConfigList,yes)
+ end.
+
+
+load(eof, []) ->
+ eof;
+
+load([$M,$a,$x,$H,$e,$a,$d,$e,$r,$S,$i,$z,$e,$ |MaxHeaderSize], []) ->
+ ?DEBUG("load -> MaxHeaderSize: ~p",[MaxHeaderSize]),
+ case make_integer(MaxHeaderSize) of
+ {ok, Integer} ->
+ {ok, [], {max_header_size,Integer}};
+ {error, _} ->
+ {error, ?NICE(clean(MaxHeaderSize)++
+ " is an invalid number of MaxHeaderSize")}
+ end;
+load([$M,$a,$x,$H,$e,$a,$d,$e,$r,$A,$c,$t,$i,$o,$n,$ |Action], []) ->
+ ?DEBUG("load -> MaxHeaderAction: ~p",[Action]),
+ {ok, [], {max_header_action,list_to_atom(clean(Action))}};
+load([$M,$a,$x,$B,$o,$d,$y,$S,$i,$z,$e,$ |MaxBodySize], []) ->
+ ?DEBUG("load -> MaxBodySize: ~p",[MaxBodySize]),
+ case make_integer(MaxBodySize) of
+ {ok, Integer} ->
+ {ok, [], {max_body_size,Integer}};
+ {error, _} ->
+ {error, ?NICE(clean(MaxBodySize)++
+ " is an invalid number of MaxBodySize")}
+ end;
+load([$M,$a,$x,$B,$o,$d,$y,$A,$c,$t,$i,$o,$n,$ |Action], []) ->
+ ?DEBUG("load -> MaxBodyAction: ~p",[Action]),
+ {ok, [], {max_body_action,list_to_atom(clean(Action))}};
+load([$S,$e,$r,$v,$e,$r,$N,$a,$m,$e,$ |ServerName], []) ->
+ ?DEBUG("load -> ServerName: ~p",[ServerName]),
+ {ok,[],{server_name,clean(ServerName)}};
+load([$S,$o,$c,$k,$e,$t,$T,$y,$p,$e,$ |SocketType], []) ->
+ ?DEBUG("load -> SocketType: ~p",[SocketType]),
+ case check_enum(clean(SocketType),["ssl","ip_comm"]) of
+ {ok, ValidSocketType} ->
+ {ok, [], {com_type,ValidSocketType}};
+ {error,_} ->
+ {error, ?NICE(clean(SocketType) ++ " is an invalid SocketType")}
+ end;
+load([$P,$o,$r,$t,$ |Port], []) ->
+ ?DEBUG("load -> Port: ~p",[Port]),
+ case make_integer(Port) of
+ {ok, Integer} ->
+ {ok, [], {port,Integer}};
+ {error, _} ->
+ {error, ?NICE(clean(Port)++" is an invalid Port")}
+ end;
+load([$B,$i,$n,$d,$A,$d,$d,$r,$e,$s,$s,$ |Address], []) ->
+ ?DEBUG("load -> Address: ~p",[Address]),
+ case clean(Address) of
+ "*" ->
+ {ok, [], {bind_address,any}};
+ CAddress ->
+ ?CDEBUG("load -> CAddress: ~p",[CAddress]),
+ case inet:getaddr(CAddress,inet) of
+ {ok, IPAddr} ->
+ ?CDEBUG("load -> IPAddr: ~p",[IPAddr]),
+ {ok, [], {bind_address,IPAddr}};
+ {error, _} ->
+ {error, ?NICE(CAddress++" is an invalid address")}
+ end
+ end;
+load([$K,$e,$e,$p,$A,$l,$i,$v,$e,$ |OnorOff], []) ->
+ case list_to_atom(clean(OnorOff)) of
+ off ->
+ {ok, [], {persistent_conn, false}};
+ _ ->
+ {ok, [], {persistent_conn, true}}
+ end;
+load([$M,$a,$x,$K,$e,$e,$p,$A,$l,$i,$v,$e,$R,$e,$q,$u,$e,$s,$t,$ |MaxRequests], []) ->
+ case make_integer(MaxRequests) of
+ {ok, Integer} ->
+ {ok, [], {max_keep_alive_request, Integer}};
+ {error, _} ->
+ {error, ?NICE(clean(MaxRequests)++" is an invalid MaxKeepAliveRequest")}
+ end;
+load([$K,$e,$e,$p,$A,$l,$i,$v,$e,$T,$i,$m,$e,$o,$u,$t,$ |Timeout], []) ->
+ case make_integer(Timeout) of
+ {ok, Integer} ->
+ {ok, [], {keep_alive_timeout, Integer*1000}};
+ {error, _} ->
+ {error, ?NICE(clean(Timeout)++" is an invalid KeepAliveTimeout")}
+ end;
+load([$M,$o,$d,$u,$l,$e,$s,$ |Modules], []) ->
+ {ok, ModuleList} = regexp:split(Modules," "),
+ {ok, [], {modules,[list_to_atom(X) || X <- ModuleList]}};
+load([$S,$e,$r,$v,$e,$r,$A,$d,$m,$i,$n,$ |ServerAdmin], []) ->
+ {ok, [], {server_admin,clean(ServerAdmin)}};
+load([$S,$e,$r,$v,$e,$r,$R,$o,$o,$t,$ |ServerRoot], []) ->
+ case is_directory(clean(ServerRoot)) of
+ {ok, Directory} ->
+ MimeTypesFile =
+ filename:join([clean(ServerRoot),"conf", "mime.types"]),
+ case load_mime_types(MimeTypesFile) of
+ {ok, MimeTypesList} ->
+ {ok, [], [{server_root,string:strip(Directory,right,$/)},
+ {mime_types,MimeTypesList}]};
+ {error, Reason} ->
+ {error, Reason}
+ end;
+ {error, _} ->
+ {error, ?NICE(clean(ServerRoot)++" is an invalid ServerRoot")}
+ end;
+load([$M,$a,$x,$C,$l,$i,$e,$n,$t,$s,$ |MaxClients], []) ->
+ ?DEBUG("load -> MaxClients: ~p",[MaxClients]),
+ case make_integer(MaxClients) of
+ {ok, Integer} ->
+ {ok, [], {max_clients,Integer}};
+ {error, _} ->
+ {error, ?NICE(clean(MaxClients)++" is an invalid number of MaxClients")}
+ end;
+load([$D,$o,$c,$u,$m,$e,$n,$t,$R,$o,$o,$t,$ |DocumentRoot],[]) ->
+ case is_directory(clean(DocumentRoot)) of
+ {ok, Directory} ->
+ {ok, [], {document_root,string:strip(Directory,right,$/)}};
+ {error, _} ->
+ {error, ?NICE(clean(DocumentRoot)++"is an invalid DocumentRoot")}
+ end;
+load([$D,$e,$f,$a,$u,$l,$t,$T,$y,$p,$e,$ |DefaultType], []) ->
+ {ok, [], {default_type,clean(DefaultType)}};
+load([$S,$S,$L,$C,$e,$r,$t,$i,$f,$i,$c,$a,$t,$e,$F,$i,$l,$e,$ | SSLCertificateFile], []) ->
+ ?DEBUG("load -> SSLCertificateFile: ~p",[SSLCertificateFile]),
+ case is_file(clean(SSLCertificateFile)) of
+ {ok, File} ->
+ {ok, [], {ssl_certificate_file,File}};
+ {error, _} ->
+ {error, ?NICE(clean(SSLCertificateFile)++
+ " is an invalid SSLCertificateFile")}
+ end;
+load([$S,$S,$L,$C,$e,$r,$t,$i,$f,$i,$c,$a,$t,$e,$K,$e,$y,$F,$i,$l,$e,$ |
+ SSLCertificateKeyFile], []) ->
+ ?DEBUG("load -> SSLCertificateKeyFile: ~p",[SSLCertificateKeyFile]),
+ case is_file(clean(SSLCertificateKeyFile)) of
+ {ok, File} ->
+ {ok, [], {ssl_certificate_key_file,File}};
+ {error, _} ->
+ {error, ?NICE(clean(SSLCertificateKeyFile)++
+ " is an invalid SSLCertificateKeyFile")}
+ end;
+load([$S,$S,$L,$V,$e,$r,$i,$f,$y,$C,$l,$i,$e,$n,$t,$ |SSLVerifyClient], []) ->
+ ?DEBUG("load -> SSLVerifyClient: ~p",[SSLVerifyClient]),
+ case make_integer(clean(SSLVerifyClient)) of
+ {ok, Integer} when Integer >=0,Integer =< 2 ->
+ {ok, [], {ssl_verify_client,Integer}};
+ {ok, Integer} ->
+ {error,?NICE(clean(SSLVerifyClient)++" is an invalid SSLVerifyClient")};
+ {error, nomatch} ->
+ {error,?NICE(clean(SSLVerifyClient)++" is an invalid SSLVerifyClient")}
+ end;
+load([$S,$S,$L,$V,$e,$r,$i,$f,$y,$D,$e,$p,$t,$h,$ |
+ SSLVerifyDepth], []) ->
+ ?DEBUG("load -> SSLVerifyDepth: ~p",[SSLVerifyDepth]),
+ case make_integer(clean(SSLVerifyDepth)) of
+ {ok, Integer} when Integer > 0 ->
+ {ok, [], {ssl_verify_client_depth,Integer}};
+ {ok, Integer} ->
+ {error,?NICE(clean(SSLVerifyDepth) ++
+ " is an invalid SSLVerifyDepth")};
+ {error, nomatch} ->
+ {error,?NICE(clean(SSLVerifyDepth) ++
+ " is an invalid SSLVerifyDepth")}
+ end;
+load([$S,$S,$L,$C,$i,$p,$h,$e,$r,$s,$ | SSLCiphers], []) ->
+ ?DEBUG("load -> SSLCiphers: ~p",[SSLCiphers]),
+ {ok, [], {ssl_ciphers, clean(SSLCiphers)}};
+load([$S,$S,$L,$C,$A,$C,$e,$r,$t,$i,$f,$i,$c,$a,$t,$e,$F,$i,$l,$e,$ |
+ SSLCACertificateFile], []) ->
+ case is_file(clean(SSLCACertificateFile)) of
+ {ok, File} ->
+ {ok, [], {ssl_ca_certificate_file,File}};
+ {error, _} ->
+ {error, ?NICE(clean(SSLCACertificateFile)++
+ " is an invalid SSLCACertificateFile")}
+ end;
+load([$S,$S,$L,$P,$a,$s,$s,$w,$o,$r,$d,$C,$a,$l,$l,$b,$a,$c,$k,$M,$o,$d,$u,$l,$e,$ | SSLPasswordCallbackModule], []) ->
+ ?DEBUG("load -> SSLPasswordCallbackModule: ~p",
+ [SSLPasswordCallbackModule]),
+ {ok, [], {ssl_password_callback_module,
+ list_to_atom(clean(SSLPasswordCallbackModule))}};
+load([$S,$S,$L,$P,$a,$s,$s,$w,$o,$r,$d,$C,$a,$l,$l,$b,$a,$c,$k,$F,$u,$n,$c,$t,$i,$o,$n,$ | SSLPasswordCallbackFunction], []) ->
+ ?DEBUG("load -> SSLPasswordCallbackFunction: ~p",
+ [SSLPasswordCallbackFunction]),
+ {ok, [], {ssl_password_callback_function,
+ list_to_atom(clean(SSLPasswordCallbackFunction))}}.
+
+
+%%
+%% load_mime_types/1 -> {ok, MimeTypes} | {error, Reason}
+%%
+load_mime_types(MimeTypesFile) ->
+ case file:open(MimeTypesFile, [read]) of
+ {ok, Stream} ->
+ parse_mime_types(Stream, []);
+ {error, _} ->
+ {error, ?NICE("Can't open " ++ MimeTypesFile)}
+ end.
+
+parse_mime_types(Stream,MimeTypesList) ->
+ Line=
+ case io:get_line(Stream,'') of
+ eof ->
+ eof;
+ String ->
+ clean(String)
+ end,
+ parse_mime_types(Stream, MimeTypesList, Line).
+
+parse_mime_types(Stream, MimeTypesList, eof) ->
+ file:close(Stream),
+ {ok, MimeTypesList};
+parse_mime_types(Stream, MimeTypesList, "") ->
+ parse_mime_types(Stream, MimeTypesList);
+parse_mime_types(Stream, MimeTypesList, [$#|_]) ->
+ parse_mime_types(Stream, MimeTypesList);
+parse_mime_types(Stream, MimeTypesList, Line) ->
+ case regexp:split(Line, " ") of
+ {ok, [NewMimeType|Suffixes]} ->
+ parse_mime_types(Stream,lists:append(suffixes(NewMimeType,Suffixes),
+ MimeTypesList));
+ {ok, _} ->
+ {error, ?NICE(Line)}
+ end.
+
+suffixes(MimeType,[]) ->
+ [];
+suffixes(MimeType,[Suffix|Rest]) ->
+ [{Suffix,MimeType}|suffixes(MimeType,Rest)].
+
+%%
+%% Phase 2: Store
+%%
+
+%% store
+
+store(ConfigList) ->
+ Modules = httpd_util:key1search(ConfigList, modules, []),
+ Port = httpd_util:key1search(ConfigList, port),
+ Addr = httpd_util:key1search(ConfigList,bind_address),
+ Name = httpd_util:make_name("httpd_conf",Addr,Port),
+ ?CDEBUG("store -> Name = ~p",[Name]),
+ ConfigDB = ets:new(Name, [named_table, bag, protected]),
+ ?CDEBUG("store -> ConfigDB = ~p",[ConfigDB]),
+ store(ConfigDB, ConfigList, lists:append(Modules,[?MODULE]),ConfigList).
+
+store(ConfigDB, ConfigList, Modules,[]) ->
+ ?vtrace("store -> done",[]),
+ ?CDEBUG("store -> done",[]),
+ {ok, ConfigDB};
+store(ConfigDB, ConfigList, Modules, [ConfigListEntry|Rest]) ->
+ ?vtrace("store -> entry with"
+ "~n ConfigListEntry: ~p",[ConfigListEntry]),
+ ?CDEBUG("store -> "
+ "~n ConfigListEntry: ~p",[ConfigListEntry]),
+ case store_traverse(ConfigListEntry,ConfigList,Modules) of
+ {ok, ConfigDBEntry} when tuple(ConfigDBEntry) ->
+ ?vtrace("store -> ConfigDBEntry(tuple): "
+ "~n ~p",[ConfigDBEntry]),
+ ?CDEBUG("store -> ConfigDBEntry(tuple): "
+ "~n ~p",[ConfigDBEntry]),
+ ets:insert(ConfigDB,ConfigDBEntry),
+ store(ConfigDB,ConfigList,Modules,Rest);
+ {ok, ConfigDBEntry} when list(ConfigDBEntry) ->
+ ?vtrace("store -> ConfigDBEntry(list): "
+ "~n ~p",[ConfigDBEntry]),
+ ?CDEBUG("store -> ConfigDBEntry(list): "
+ "~n ~p",[ConfigDBEntry]),
+ lists:foreach(fun(Entry) ->
+ ets:insert(ConfigDB,Entry)
+ end,ConfigDBEntry),
+ store(ConfigDB,ConfigList,Modules,Rest);
+ {error, Reason} ->
+ ?vlog("store -> error: ~p",[Reason]),
+ ?ERROR("store -> error: ~p",[Reason]),
+ {error,Reason}
+ end.
+
+store_traverse(ConfigListEntry,ConfigList,[]) ->
+ {error,?NICE("Unable to store configuration...")};
+store_traverse(ConfigListEntry, ConfigList, [Module|Rest]) ->
+ case is_exported(Module, {store, 2}) of
+ true ->
+ ?CDEBUG("store_traverse -> call ~p:store/2",[Module]),
+ case catch apply(Module,store,[ConfigListEntry, ConfigList]) of
+ {'EXIT',{function_clause,_}} ->
+ ?CDEBUG("store_traverse -> exit: function_clause",[]),
+ store_traverse(ConfigListEntry,ConfigList,Rest);
+ {'EXIT',Reason} ->
+ ?ERROR("store_traverse -> exit: ~p",[Reason]),
+ error_logger:error_report({'EXIT',Reason}),
+ store_traverse(ConfigListEntry,ConfigList,Rest);
+ Result ->
+ ?CDEBUG("store_traverse -> ~n"
+ " Result: ~p",[Result]),
+ Result
+ end;
+ false ->
+ store_traverse(ConfigListEntry,ConfigList,Rest)
+ end.
+
+store({mime_types,MimeTypesList},ConfigList) ->
+ Port = httpd_util:key1search(ConfigList, port),
+ Addr = httpd_util:key1search(ConfigList, bind_address),
+ Name = httpd_util:make_name("httpd_mime",Addr,Port),
+ ?CDEBUG("store(mime_types) -> Name: ~p",[Name]),
+ {ok, MimeTypesDB} = store_mime_types(Name,MimeTypesList),
+ ?CDEBUG("store(mime_types) -> ~n"
+ " MimeTypesDB: ~p~n"
+ " MimeTypesDB info: ~p",
+ [MimeTypesDB,ets:info(MimeTypesDB)]),
+ {ok, {mime_types,MimeTypesDB}};
+store(ConfigListEntry,ConfigList) ->
+ ?CDEBUG("store/2 -> ~n"
+ " ConfigListEntry: ~p~n"
+ " ConfigList: ~p",
+ [ConfigListEntry,ConfigList]),
+ {ok, ConfigListEntry}.
+
+
+%% store_mime_types
+store_mime_types(Name,MimeTypesList) ->
+ ?CDEBUG("store_mime_types -> Name: ~p",[Name]),
+ MimeTypesDB = ets:new(Name, [set, protected]),
+ ?CDEBUG("store_mime_types -> MimeTypesDB: ~p",[MimeTypesDB]),
+ store_mime_types1(MimeTypesDB, MimeTypesList).
+
+store_mime_types1(MimeTypesDB,[]) ->
+ {ok, MimeTypesDB};
+store_mime_types1(MimeTypesDB,[Type|Rest]) ->
+ ?CDEBUG("store_mime_types1 -> Type: ~p",[Type]),
+ ets:insert(MimeTypesDB, Type),
+ store_mime_types1(MimeTypesDB, Rest).
+
+
+%%
+%% Phase 3: Remove
+%%
+
+remove_all(ConfigDB) ->
+ Modules = httpd_util:lookup(ConfigDB,modules,[]),
+ remove_traverse(ConfigDB, lists:append(Modules,[?MODULE])).
+
+remove_traverse(ConfigDB,[]) ->
+ ?vtrace("remove_traverse -> done", []),
+ ok;
+remove_traverse(ConfigDB,[Module|Rest]) ->
+ ?vtrace("remove_traverse -> call ~p:remove", [Module]),
+ case (catch apply(Module,remove,[ConfigDB])) of
+ {'EXIT',{undef,_}} ->
+ ?vtrace("remove_traverse -> undef", []),
+ remove_traverse(ConfigDB,Rest);
+ {'EXIT',{function_clause,_}} ->
+ ?vtrace("remove_traverse -> function_clause", []),
+ remove_traverse(ConfigDB,Rest);
+ {'EXIT',Reason} ->
+ ?vtrace("remove_traverse -> exit: ~p", [Reason]),
+ error_logger:error_report({'EXIT',Reason}),
+ remove_traverse(ConfigDB,Rest);
+ {error,Reason} ->
+ ?vtrace("remove_traverse -> error: ~p", [Reason]),
+ error_logger:error_report(Reason),
+ remove_traverse(ConfigDB,Rest);
+ _ ->
+ remove_traverse(ConfigDB,Rest)
+ end.
+
+remove(ConfigDB) ->
+ ets:delete(ConfigDB),
+ ok.
+
+
+%%
+%% Utility functions
+%%
+
+%% is_directory
+
+is_directory(Directory) ->
+ case file:read_file_info(Directory) of
+ {ok,FileInfo} ->
+ #file_info{type = Type, access = Access} = FileInfo,
+ is_directory(Type,Access,FileInfo,Directory);
+ {error,Reason} ->
+ {error,Reason}
+ end.
+
+is_directory(directory,read,_FileInfo,Directory) ->
+ {ok,Directory};
+is_directory(directory,read_write,_FileInfo,Directory) ->
+ {ok,Directory};
+is_directory(_Type,_Access,FileInfo,_Directory) ->
+ {error,FileInfo}.
+
+
+%% is_file
+
+is_file(File) ->
+ case file:read_file_info(File) of
+ {ok,FileInfo} ->
+ #file_info{type = Type, access = Access} = FileInfo,
+ is_file(Type,Access,FileInfo,File);
+ {error,Reason} ->
+ {error,Reason}
+ end.
+
+is_file(regular,read,_FileInfo,File) ->
+ {ok,File};
+is_file(regular,read_write,_FileInfo,File) ->
+ {ok,File};
+is_file(_Type,_Access,FileInfo,_File) ->
+ {error,FileInfo}.
+
+%% make_integer
+
+make_integer(String) ->
+ case regexp:match(clean(String),"[0-9]+") of
+ {match, _, _} ->
+ {ok, list_to_integer(clean(String))};
+ nomatch ->
+ {error, nomatch}
+ end.
+
+
+%% clean
+
+clean(String) ->
+ {ok,CleanedString,_} = regexp:gsub(String, "^[ \t\n\r\f]*|[ \t\n\r\f]*\$",""),
+ CleanedString.
+
+%% custom_clean
+
+custom_clean(String,MoreBefore,MoreAfter) ->
+ {ok,CleanedString,_}=regexp:gsub(String,"^[ \t\n\r\f"++MoreBefore++
+ "]*|[ \t\n\r\f"++MoreAfter++"]*\$",""),
+ CleanedString.
+
+%% check_enum
+
+check_enum(Enum,[]) ->
+ {error, not_valid};
+check_enum(Enum,[Enum|Rest]) ->
+ {ok, list_to_atom(Enum)};
+check_enum(Enum, [NotValid|Rest]) ->
+ check_enum(Enum, Rest).
+
+%% a_must
+
+a_must(ConfigList,[]) ->
+ ok;
+a_must(ConfigList,[Directive|Rest]) ->
+ case httpd_util:key1search(ConfigList,Directive) of
+ undefined ->
+ {missing,Directive};
+ _ ->
+ a_must(ConfigList,Rest)
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_example.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_example.erl
new file mode 100644
index 0000000000..4aec440db3
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_example.erl
@@ -0,0 +1,134 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: httpd_example.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
+%%
+-module(httpd_example).
+-export([print/1]).
+-export([get/2, post/2, yahoo/2, test1/2]).
+
+-export([newformat/3]).
+%% These are used by the inets test-suite
+-export([delay/1]).
+
+
+print(String) ->
+ [header(),
+ top("Print"),
+ String++"\n",
+ footer()].
+
+
+test1(Env, []) ->
+ io:format("Env:~p~n",[Env]),
+ ["<html>",
+ "<head>",
+ "<title>Test1</title>",
+ "</head>",
+ "<body>",
+ "<h1>Erlang Body</h1>",
+ "<h2>Stuff</h2>",
+ "</body>",
+ "</html>"].
+
+
+get(Env,[]) ->
+ [header(),
+ top("GET Example"),
+ "<FORM ACTION=\"/cgi-bin/erl/httpd_example:get\" METHOD=GET>
+<B>Input:</B> <INPUT TYPE=\"text\" NAME=\"input1\">
+<INPUT TYPE=\"text\" NAME=\"input2\">
+<INPUT TYPE=\"submit\"><BR>
+</FORM>" ++ "\n",
+ footer()];
+
+get(Env,Input) ->
+ default(Env,Input).
+
+post(Env,[]) ->
+ [header(),
+ top("POST Example"),
+ "<FORM ACTION=\"/cgi-bin/erl/httpd_example:post\" METHOD=POST>
+<B>Input:</B> <INPUT TYPE=\"text\" NAME=\"input1\">
+<INPUT TYPE=\"text\" NAME=\"input2\">
+<INPUT TYPE=\"submit\"><BR>
+</FORM>" ++ "\n",
+ footer()];
+
+post(Env,Input) ->
+ default(Env,Input).
+
+yahoo(Env,Input) ->
+ "Location: http://www.yahoo.com\r\n\r\n".
+
+default(Env,Input) ->
+ [header(),
+ top("Default Example"),
+ "<B>Environment:</B> ",io_lib:format("~p",[Env]),"<BR>\n",
+ "<B>Input:</B> ",Input,"<BR>\n",
+ "<B>Parsed Input:</B> ",
+ io_lib:format("~p",[httpd:parse_query(Input)]),"\n",
+ footer()].
+
+header() ->
+ header("text/html").
+header(MimeType) ->
+ "Content-type: " ++ MimeType ++ "\r\n\r\n".
+
+top(Title) ->
+ "<HTML>
+<HEAD>
+<TITLE>" ++ Title ++ "</TITLE>
+</HEAD>
+<BODY>\n".
+
+footer() ->
+ "</BODY>
+</HTML>\n".
+
+
+newformat(SessionID,Env,Input)->
+ mod_esi:deliver(SessionID,"Content-Type:text/html\r\n\r\n"),
+ mod_esi:deliver(SessionID,top("new esi format test")),
+ mod_esi:deliver(SessionID,"This new format is nice<BR>"),
+ mod_esi:deliver(SessionID,"This new format is nice<BR>"),
+ mod_esi:deliver(SessionID,"This new format is nice<BR>"),
+ mod_esi:deliver(SessionID,footer()).
+
+%% ------------------------------------------------------
+
+delay(Time) when integer(Time) ->
+ i("httpd_example:delay(~p) -> do the delay",[Time]),
+ sleep(Time),
+ i("httpd_example:delay(~p) -> done, now reply",[Time]),
+ delay_reply("delay ok");
+delay(Time) when list(Time) ->
+ delay(httpd_conf:make_integer(Time));
+delay({ok,Time}) when integer(Time) ->
+ delay(Time);
+delay({error,_Reason}) ->
+ i("delay -> called with invalid time"),
+ delay_reply("delay failed: invalid delay time").
+
+delay_reply(Reply) ->
+ [header(),
+ top("delay"),
+ Reply,
+ footer()].
+
+i(F) -> i(F,[]).
+i(F,A) -> io:format(F ++ "~n",A).
+
+sleep(T) -> receive after T -> ok end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_manager.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_manager.erl
new file mode 100644
index 0000000000..704cb1f319
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_manager.erl
@@ -0,0 +1,1029 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: httpd_manager.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
+%%
+
+-module(httpd_manager).
+
+-include("httpd.hrl").
+-include("httpd_verbosity.hrl").
+
+-behaviour(gen_server).
+
+%% External API
+-export([start/2, start/3, start_link/2, start_link/3, stop/1, restart/1]).
+
+%% Internal API
+-export([new_connection/1, done_connection/1]).
+
+%% Module API
+-export([config_lookup/2, config_lookup/3,
+ config_multi_lookup/2, config_multi_lookup/3,
+ config_match/2, config_match/3]).
+
+%% gen_server exports
+-export([init/1,
+ handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2,
+ code_change/3]).
+
+
+%% Management exports
+-export([block/2, block/3, unblock/1]).
+-export([get_admin_state/1, get_usage_state/1]).
+-export([is_busy/1,is_busy/2,is_busy_or_blocked/1,is_blocked/1]). %% ???????
+-export([get_status/1, get_status/2]).
+-export([verbosity/2, verbosity/3]).
+
+
+-export([c/1]).
+
+-record(state,{socket_type = ip_comm,
+ config_file,
+ config_db = null,
+ connections, %% Current request handlers
+ admin_state = unblocked,
+ blocker_ref = undefined,
+ blocking_tmr = undefined,
+ status = []}).
+
+
+c(Port) ->
+ Ref = httpd_util:make_name("httpd",undefined,Port),
+ gen_server:call(Ref, fake_close).
+
+
+%%
+%% External API
+%%
+
+start(ConfigFile, ConfigList) ->
+ start(ConfigFile, ConfigList, []).
+
+start(ConfigFile, ConfigList, Verbosity) ->
+ Port = httpd_util:key1search(ConfigList,port,80),
+ Addr = httpd_util:key1search(ConfigList,bind_address),
+ Name = make_name(Addr,Port),
+ ?LOG("start -> Name = ~p",[Name]),
+ gen_server:start({local,Name},?MODULE,
+ [ConfigFile, ConfigList, Addr, Port, Verbosity],[]).
+
+start_link(ConfigFile, ConfigList) ->
+ start_link(ConfigFile, ConfigList, []).
+
+start_link(ConfigFile, ConfigList, Verbosity) ->
+ Port = httpd_util:key1search(ConfigList,port,80),
+ Addr = httpd_util:key1search(ConfigList,bind_address),
+ Name = make_name(Addr,Port),
+ ?LOG("start_link -> Name = ~p",[Name]),
+ gen_server:start_link({local, Name},?MODULE,
+ [ConfigFile, ConfigList, Addr, Port, Verbosity],[]).
+
+%% stop
+
+stop(ServerRef) ->
+ gen_server:call(ServerRef, stop).
+
+%% restart
+
+restart(ServerRef) ->
+ gen_server:call(ServerRef, restart).
+
+
+%%%----------------------------------------------------------------
+
+block(ServerRef, disturbing) ->
+ call(ServerRef,block);
+
+block(ServerRef, non_disturbing) ->
+ do_block(ServerRef, non_disturbing, infinity).
+
+block(ServerRef, Method, Timeout) ->
+ do_block(ServerRef, Method, Timeout).
+
+
+%% The reason for not using call here, is that the manager cannot
+%% _wait_ for completion of the requests. It must be able to do
+%% do other things at the same time as the blocking goes on.
+do_block(ServerRef, Method, infinity) ->
+ Ref = make_ref(),
+ cast(ServerRef, {block, Method, infinity, self(), Ref}),
+ receive
+ {block_reply, Reply, Ref} ->
+ Reply
+ end;
+do_block(ServerRef,Method,Timeout) when Timeout > 0 ->
+ Ref = make_ref(),
+ cast(ServerRef,{block,Method,Timeout,self(),Ref}),
+ receive
+ {block_reply,Reply,Ref} ->
+ Reply
+ end.
+
+
+%%%----------------------------------------------------------------
+
+%% unblock
+
+unblock(ServerRef) ->
+ call(ServerRef,unblock).
+
+%% get admin/usage state
+
+get_admin_state(ServerRef) ->
+ call(ServerRef,get_admin_state).
+
+get_usage_state(ServerRef) ->
+ call(ServerRef,get_usage_state).
+
+
+%% get_status
+
+get_status(ServerRef) ->
+ gen_server:call(ServerRef,get_status).
+
+get_status(ServerRef,Timeout) ->
+ gen_server:call(ServerRef,get_status,Timeout).
+
+
+verbosity(ServerRef,Verbosity) ->
+ verbosity(ServerRef,all,Verbosity).
+
+verbosity(ServerRef,all,Verbosity) ->
+ gen_server:call(ServerRef,{verbosity,all,Verbosity});
+verbosity(ServerRef,manager,Verbosity) ->
+ gen_server:call(ServerRef,{verbosity,manager,Verbosity});
+verbosity(ServerRef,request,Verbosity) ->
+ gen_server:call(ServerRef,{verbosity,request,Verbosity});
+verbosity(ServerRef,acceptor,Verbosity) ->
+ gen_server:call(ServerRef,{verbosity,acceptor,Verbosity});
+verbosity(ServerRef,security,Verbosity) ->
+ gen_server:call(ServerRef,{verbosity,security,Verbosity});
+verbosity(ServerRef,auth,Verbosity) ->
+ gen_server:call(ServerRef,{verbosity,auth,Verbosity}).
+
+%%
+%% Internal API
+%%
+
+
+%% new_connection
+
+new_connection(Manager) ->
+ gen_server:call(Manager, {new_connection, self()}).
+
+%% done
+
+done_connection(Manager) ->
+ gen_server:cast(Manager, {done_connection, self()}).
+
+
+%% is_busy(ServerRef) -> true | false
+%%
+%% Tests if the server is (in usage state) busy,
+%% i.e. has rached the heavy load limit.
+%%
+
+is_busy(ServerRef) ->
+ gen_server:call(ServerRef,is_busy).
+
+is_busy(ServerRef,Timeout) ->
+ gen_server:call(ServerRef,is_busy,Timeout).
+
+
+%% is_busy_or_blocked(ServerRef) -> busy | blocked | false
+%%
+%% Tests if the server is busy (usage state), i.e. has rached,
+%% the heavy load limit, or blocked (admin state) .
+%%
+
+is_busy_or_blocked(ServerRef) ->
+ gen_server:call(ServerRef,is_busy_or_blocked).
+
+
+%% is_blocked(ServerRef) -> true | false
+%%
+%% Tests if the server is blocked (admin state) .
+%%
+
+is_blocked(ServerRef) ->
+ gen_server:call(ServerRef,is_blocked).
+
+
+%%
+%% Module API. Theese functions are intended for use from modules only.
+%%
+
+config_lookup(Port, Query) ->
+ config_lookup(undefined, Port, Query).
+config_lookup(Addr, Port, Query) ->
+ Name = httpd_util:make_name("httpd",Addr,Port),
+ gen_server:call(whereis(Name), {config_lookup, Query}).
+
+config_multi_lookup(Port, Query) ->
+ config_multi_lookup(undefined,Port,Query).
+config_multi_lookup(Addr,Port, Query) ->
+ Name = httpd_util:make_name("httpd",Addr,Port),
+ gen_server:call(whereis(Name), {config_multi_lookup, Query}).
+
+config_match(Port, Pattern) ->
+ config_match(undefined,Port,Pattern).
+config_match(Addr, Port, Pattern) ->
+ Name = httpd_util:make_name("httpd",Addr,Port),
+ gen_server:call(whereis(Name), {config_match, Pattern}).
+
+
+%%
+%% Server call-back functions
+%%
+
+%% init
+
+init([ConfigFile, ConfigList, Addr, Port, Verbosity]) ->
+ process_flag(trap_exit, true),
+ case (catch do_init(ConfigFile, ConfigList, Addr, Port, Verbosity)) of
+ {error, Reason} ->
+ ?vlog("failed starting server: ~p", [Reason]),
+ {stop, Reason};
+ {ok, State} ->
+ {ok, State}
+ end.
+
+
+do_init(ConfigFile, ConfigList, Addr, Port, Verbosity) ->
+ put(sname,man),
+ set_verbosity(Verbosity),
+ ?vlog("starting",[]),
+ ConfigDB = do_initial_store(ConfigList),
+ ?vtrace("config db: ~p", [ConfigDB]),
+ SocketType = httpd_socket:config(ConfigDB),
+ ?vtrace("socket type: ~p, now start acceptor", [SocketType]),
+ case httpd_acceptor_sup:start_acceptor(SocketType, Addr, Port, ConfigDB) of
+ {ok, Pid} ->
+ ?vtrace("acceptor started: ~p", [Pid]),
+ Status = [{max_conn,0}, {last_heavy_load,never},
+ {last_connection,never}],
+ State = #state{socket_type = SocketType,
+ config_file = ConfigFile,
+ config_db = ConfigDB,
+ connections = [],
+ status = Status},
+ ?vdebug("started",[]),
+ {ok, State};
+ Else ->
+ Else
+ end.
+
+
+do_initial_store(ConfigList) ->
+ case httpd_conf:store(ConfigList) of
+ {ok, ConfigDB} ->
+ ConfigDB;
+ {error, Reason} ->
+ ?vinfo("failed storing configuration: ~p",[Reason]),
+ throw({error, Reason})
+ end.
+
+
+
+%% handle_call
+
+handle_call(stop, _From, State) ->
+ ?vlog("stop",[]),
+ {stop, normal, ok, State};
+
+handle_call({config_lookup, Query}, _From, State) ->
+ ?vlog("config lookup: Query = ~p",[Query]),
+ Res = httpd_util:lookup(State#state.config_db, Query),
+ ?vdebug("config lookup result: ~p",[Res]),
+ {reply, Res, State};
+
+handle_call({config_multi_lookup, Query}, _From, State) ->
+ ?vlog("multi config lookup: Query = ~p",[Query]),
+ Res = httpd_util:multi_lookup(State#state.config_db, Query),
+ ?vdebug("multi config lookup result: ~p",[Res]),
+ {reply, Res, State};
+
+handle_call({config_match, Query}, _From, State) ->
+ ?vlog("config match: Query = ~p",[Query]),
+ Res = ets:match_object(State#state.config_db, Query),
+ ?vdebug("config match result: ~p",[Res]),
+ {reply, Res, State};
+
+handle_call(get_status, _From, State) ->
+ ?vdebug("get status",[]),
+ ManagerStatus = manager_status(self()),
+ %% AuthStatus = auth_status(get(auth_server)),
+ %% SecStatus = sec_status(get(sec_server)),
+ %% AccStatus = sec_status(get(acceptor_server)),
+ S1 = [{current_conn,length(State#state.connections)}|State#state.status]++
+ [ManagerStatus],
+ ?vtrace("status = ~p",[S1]),
+ {reply,S1,State};
+
+handle_call(is_busy, From, State) ->
+ Reply = case get_ustate(State) of
+ busy ->
+ true;
+ _ ->
+ false
+ end,
+ ?vlog("is busy: ~p",[Reply]),
+ {reply,Reply,State};
+
+handle_call(is_busy_or_blocked, From, State) ->
+ Reply =
+ case get_astate(State) of
+ unblocked ->
+ case get_ustate(State) of
+ busy ->
+ busy;
+ _ ->
+ false
+ end;
+ _ ->
+ blocked
+ end,
+ ?vlog("is busy or blocked: ~p",[Reply]),
+ {reply,Reply,State};
+
+handle_call(is_blocked, From, State) ->
+ Reply =
+ case get_astate(State) of
+ unblocked ->
+ false;
+ _ ->
+ true
+ end,
+ ?vlog("is blocked: ~p",[Reply]),
+ {reply,Reply,State};
+
+handle_call(get_admin_state, From, State) ->
+ Reply = get_astate(State),
+ ?vlog("admin state: ~p",[Reply]),
+ {reply,Reply,State};
+
+handle_call(get_usage_state, From, State) ->
+ Reply = get_ustate(State),
+ ?vlog("usage state: ~p",[Reply]),
+ {reply,Reply,State};
+
+handle_call({verbosity,Who,Verbosity}, From, State) ->
+ V = ?vvalidate(Verbosity),
+ ?vlog("~n Set new verbosity to ~p for ~p",[V,Who]),
+ Reply = set_verbosity(Who,V,State),
+ {reply,Reply,State};
+
+handle_call(restart, From, State) when State#state.admin_state == blocked ->
+ ?vlog("restart",[]),
+ case handle_restart(State) of
+ {stop, Reply,S1} ->
+ {stop, Reply, S1};
+ {_, Reply, S1} ->
+ {reply,Reply,S1}
+ end;
+
+handle_call(restart, From, State) ->
+ ?vlog("restart(~p)",[State#state.admin_state]),
+ {reply,{error,{invalid_admin_state,State#state.admin_state}},State};
+
+handle_call(block, From, State) ->
+ ?vlog("block(disturbing)",[]),
+ {Reply,S1} = handle_block(State),
+ {reply,Reply,S1};
+
+handle_call(unblock, {From,_Tag}, State) ->
+ ?vlog("unblock",[]),
+ {Reply,S1} = handle_unblock(State,From),
+ {reply, Reply, S1};
+
+handle_call({new_connection, Pid}, From, State) ->
+ ?vlog("~n New connection (~p) when connection count = ~p",
+ [Pid,length(State#state.connections)]),
+ {S, S1} = handle_new_connection(State, Pid),
+ Reply = {S, get(request_handler_verbosity)},
+ {reply, Reply, S1};
+
+handle_call(Request, From, State) ->
+ ?vinfo("~n unknown request '~p' from ~p", [Request,From]),
+ String =
+ lists:flatten(
+ io_lib:format("Unknown request "
+ "~n ~p"
+ "~nto manager (~p)"
+ "~nfrom ~p",
+ [Request, self(), From])),
+ report_error(State,String),
+ {reply, ok, State}.
+
+
+%% handle_cast
+
+handle_cast({done_connection, Pid}, State) ->
+ ?vlog("~n Done connection (~p)", [Pid]),
+ S1 = handle_done_connection(State, Pid),
+ {noreply, S1};
+
+handle_cast({block, disturbing, Timeout, From, Ref}, State) ->
+ ?vlog("block(disturbing,~p)",[Timeout]),
+ S1 = handle_block(State, Timeout, From, Ref),
+ {noreply,S1};
+
+handle_cast({block, non_disturbing, Timeout, From, Ref}, State) ->
+ ?vlog("block(non-disturbing,~p)",[Timeout]),
+ S1 = handle_nd_block(State, Timeout, From, Ref),
+ {noreply,S1};
+
+handle_cast(Message, State) ->
+ ?vinfo("~n received unknown message '~p'",[Message]),
+ String =
+ lists:flatten(
+ io_lib:format("Unknown message "
+ "~n ~p"
+ "~nto manager (~p)",
+ [Message, self()])),
+ report_error(State, String),
+ {noreply, State}.
+
+%% handle_info
+
+handle_info({block_timeout, Method}, State) ->
+ ?vlog("received block_timeout event",[]),
+ S1 = handle_block_timeout(State,Method),
+ {noreply, S1};
+
+handle_info({'DOWN', Ref, process, _Object, Info}, State) ->
+ ?vlog("~n down message for ~p",[Ref]),
+ S1 =
+ case State#state.blocker_ref of
+ Ref ->
+ handle_blocker_exit(State);
+ _ ->
+ %% Not our blocker, so ignore
+ State
+ end,
+ {noreply, S1};
+
+handle_info({'EXIT', Pid, normal}, State) ->
+ ?vdebug("~n Normal exit message from ~p", [Pid]),
+ {noreply, State};
+
+handle_info({'EXIT', Pid, blocked}, S) ->
+ ?vdebug("blocked exit signal from request handler (~p)", [Pid]),
+ {noreply, S};
+
+handle_info({'EXIT', Pid, Reason}, State) ->
+ ?vlog("~n Exit message from ~p for reason ~p",[Pid, Reason]),
+ S1 = check_connections(State, Pid, Reason),
+ {noreply, S1};
+
+handle_info(Info, State) ->
+ ?vinfo("~n received unknown info '~p'",[Info]),
+ String =
+ lists:flatten(
+ io_lib:format("Unknown info "
+ "~n ~p"
+ "~nto manager (~p)",
+ [Info, self()])),
+ report_error(State, String),
+ {noreply, State}.
+
+
+%% terminate
+
+terminate(R, #state{config_db = Db}) ->
+ ?vlog("Terminating for reason: ~n ~p", [R]),
+ httpd_conf:remove_all(Db),
+ ok.
+
+
+%% code_change({down,ToVsn}, State, Extra)
+%%
+%% NOTE:
+%% Actually upgrade from 2.5.1 to 2.5.3 and downgrade from
+%% 2.5.3 to 2.5.1 is done with an application restart, so
+%% these function is actually never used. The reason for keeping
+%% this stuff is only for future use.
+%%
+code_change({down,ToVsn},State,Extra) ->
+ {ok,State};
+
+%% code_change(FromVsn, State, Extra)
+%%
+code_change(FromVsn,State,Extra) ->
+ {ok,State}.
+
+
+
+%% -------------------------------------------------------------------------
+%% check_connection
+%%
+%%
+%%
+%%
+
+check_connections(#state{connections = []} = State, _Pid, _Reason) ->
+ State;
+check_connections(#state{admin_state = shutting_down,
+ connections = Connections} = State, Pid, Reason) ->
+ %% Could be a crashing request handler
+ case lists:delete(Pid, Connections) of
+ [] -> % Crashing request handler => block complete
+ String =
+ lists:flatten(
+ io_lib:format("request handler (~p) crashed:"
+ "~n ~p", [Pid, Reason])),
+ report_error(State, String),
+ ?vlog("block complete",[]),
+ demonitor_blocker(State#state.blocker_ref),
+ {Tmr,From,Ref} = State#state.blocking_tmr,
+ ?vlog("(possibly) stop block timer",[]),
+ stop_block_tmr(Tmr),
+ ?vlog("and send the reply",[]),
+ From ! {block_reply,ok,Ref},
+ State#state{admin_state = blocked, connections = [],
+ blocker_ref = undefined};
+ Connections1 ->
+ State#state{connections = Connections1}
+ end;
+check_connections(#state{connections = Connections} = State, Pid, Reason) ->
+ case lists:delete(Pid, Connections) of
+ Connections -> % Not a request handler, so ignore
+ State;
+ Connections1 ->
+ String =
+ lists:flatten(
+ io_lib:format("request handler (~p) crashed:"
+ "~n ~p", [Pid, Reason])),
+ report_error(State, String),
+ State#state{connections = lists:delete(Pid, Connections)}
+ end.
+
+
+%% -------------------------------------------------------------------------
+%% handle_[new | done]_connection
+%%
+%%
+%%
+%%
+
+handle_new_connection(State, Handler) ->
+ UsageState = get_ustate(State),
+ AdminState = get_astate(State),
+ handle_new_connection(UsageState, AdminState, State, Handler).
+
+handle_new_connection(busy, unblocked, State, Handler) ->
+ Status = update_heavy_load_status(State#state.status),
+ {{reject, busy},
+ State#state{status = Status}};
+
+handle_new_connection(_UsageState, unblocked, State, Handler) ->
+ Connections = State#state.connections,
+ Status = update_connection_status(State#state.status,
+ length(Connections)+1),
+ link(Handler),
+ {accept,
+ State#state{connections = [Handler|Connections], status = Status}};
+
+handle_new_connection(_UsageState, _AdminState, State, _Handler) ->
+ {{reject, blocked},
+ State}.
+
+
+handle_done_connection(#state{admin_state = shutting_down,
+ connections = Connections} = State, Handler) ->
+ unlink(Handler),
+ case lists:delete(Handler, Connections) of
+ [] -> % Ok, block complete
+ ?vlog("block complete",[]),
+ demonitor_blocker(State#state.blocker_ref),
+ {Tmr,From,Ref} = State#state.blocking_tmr,
+ ?vlog("(possibly) stop block timer",[]),
+ stop_block_tmr(Tmr),
+ ?vlog("and send the reply",[]),
+ From ! {block_reply,ok,Ref},
+ State#state{admin_state = blocked, connections = [],
+ blocker_ref = undefined};
+ Connections1 ->
+ State#state{connections = Connections1}
+ end;
+
+handle_done_connection(#state{connections = Connections} = State, Handler) ->
+ State#state{connections = lists:delete(Handler, Connections)}.
+
+
+%% -------------------------------------------------------------------------
+%% handle_block
+%%
+%%
+%%
+%%
+handle_block(#state{admin_state = AdminState} = S) ->
+ handle_block(S, AdminState).
+
+handle_block(S,unblocked) ->
+ %% Kill all connections
+ ?vtrace("handle_block(unblocked) -> kill all request handlers",[]),
+%% [exit(Pid,blocked) || Pid <- S#state.connections],
+ [kill_handler(Pid) || Pid <- S#state.connections],
+ {ok,S#state{connections = [], admin_state = blocked}};
+handle_block(S,blocked) ->
+ ?vtrace("handle_block(blocked) -> already blocked",[]),
+ {ok,S};
+handle_block(S,shutting_down) ->
+ ?vtrace("handle_block(shutting_down) -> ongoing...",[]),
+ {{error,shutting_down},S}.
+
+
+kill_handler(Pid) ->
+ ?vtrace("kill request handler: ~p",[Pid]),
+ exit(Pid, blocked).
+%% exit(Pid, kill).
+
+handle_block(S,Timeout,From,Ref) when Timeout >= 0 ->
+ do_block(S,Timeout,From,Ref);
+
+handle_block(S,Timeout,From,Ref) ->
+ Reply = {error,{invalid_block_request,Timeout}},
+ From ! {block_reply,Reply,Ref},
+ S.
+
+do_block(S,Timeout,From,Ref) ->
+ case S#state.connections of
+ [] ->
+ %% Already in idle usage state => go directly to blocked
+ ?vdebug("do_block -> already in idle usage state",[]),
+ From ! {block_reply,ok,Ref},
+ S#state{admin_state = blocked};
+ _ ->
+ %% Active or Busy usage state => go to shutting_down
+ ?vdebug("do_block -> active or busy usage state",[]),
+ %% Make sure we get to know if blocker dies...
+ ?vtrace("do_block -> create blocker monitor",[]),
+ MonitorRef = monitor_blocker(From),
+ ?vtrace("do_block -> (possibly) start block timer",[]),
+ Tmr = {start_block_tmr(Timeout,disturbing),From,Ref},
+ S#state{admin_state = shutting_down,
+ blocker_ref = MonitorRef, blocking_tmr = Tmr}
+ end.
+
+handle_nd_block(S,infinity,From,Ref) ->
+ do_nd_block(S,infinity,From,Ref);
+
+handle_nd_block(S,Timeout,From,Ref) when Timeout >= 0 ->
+ do_nd_block(S,Timeout,From,Ref);
+
+handle_nd_block(S,Timeout,From,Ref) ->
+ Reply = {error,{invalid_block_request,Timeout}},
+ From ! {block_reply,Reply,Ref},
+ S.
+
+do_nd_block(S,Timeout,From,Ref) ->
+ case S#state.connections of
+ [] ->
+ %% Already in idle usage state => go directly to blocked
+ ?vdebug("do_nd_block -> already in idle usage state",[]),
+ From ! {block_reply,ok,Ref},
+ S#state{admin_state = blocked};
+ _ ->
+ %% Active or Busy usage state => go to shutting_down
+ ?vdebug("do_nd_block -> active or busy usage state",[]),
+ %% Make sure we get to know if blocker dies...
+ ?vtrace("do_nd_block -> create blocker monitor",[]),
+ MonitorRef = monitor_blocker(From),
+ ?vtrace("do_nd_block -> (possibly) start block timer",[]),
+ Tmr = {start_block_tmr(Timeout,non_disturbing),From,Ref},
+ S#state{admin_state = shutting_down,
+ blocker_ref = MonitorRef, blocking_tmr = Tmr}
+ end.
+
+handle_block_timeout(S,Method) ->
+ %% Time to take this to the road...
+ demonitor_blocker(S#state.blocker_ref),
+ handle_block_timeout1(S,Method,S#state.blocking_tmr).
+
+handle_block_timeout1(S,non_disturbing,{_,From,Ref}) ->
+ ?vdebug("handle_block_timeout1(non-disturbing) -> send reply: timeout",[]),
+ From ! {block_reply,{error,timeout},Ref},
+ S#state{admin_state = unblocked,
+ blocker_ref = undefined, blocking_tmr = undefined};
+
+handle_block_timeout1(S,disturbing,{_,From,Ref}) ->
+ ?vdebug("handle_block_timeout1(disturbing) -> kill all connections",[]),
+ [exit(Pid,blocked) || Pid <- S#state.connections],
+
+ ?vdebug("handle_block_timeout1 -> send reply: ok",[]),
+ From ! {block_reply,ok,Ref},
+ S#state{admin_state = blocked, connections = [],
+ blocker_ref = undefined, blocking_tmr = undefined};
+
+handle_block_timeout1(S,Method,{_,From,Ref}) ->
+ ?vinfo("received block timeout with unknown block method:"
+ "~n Method: ~p",[Method]),
+ From ! {block_reply,{error,{unknown_block_method,Method}},Ref},
+ S#state{admin_state = blocked, connections = [],
+ blocker_ref = undefined, blocking_tmr = undefined};
+
+handle_block_timeout1(S,Method,TmrInfo) ->
+ ?vinfo("received block timeout with erroneous timer info:"
+ "~n Method: ~p"
+ "~n TmrInfo: ~p",[Method,TmrInfo]),
+ S#state{admin_state = unblocked,
+ blocker_ref = undefined, blocking_tmr = undefined}.
+
+handle_unblock(S,FromA) ->
+ handle_unblock(S,FromA,S#state.admin_state).
+
+handle_unblock(S,_FromA,unblocked) ->
+ {ok,S};
+handle_unblock(S,FromA,_AdminState) ->
+ ?vtrace("handle_unblock -> (possibly) stop block timer",[]),
+ stop_block_tmr(S#state.blocking_tmr),
+ case S#state.blocking_tmr of
+ {Tmr,FromB,Ref} ->
+ %% Another process is trying to unblock
+ %% Inform the blocker
+ FromB ! {block_reply, {error,{unblocked,FromA}},Ref};
+ _ ->
+ ok
+ end,
+ {ok,S#state{admin_state = unblocked, blocking_tmr = undefined}}.
+
+%% The blocker died so we give up on the block.
+handle_blocker_exit(S) ->
+ {Tmr,_From,_Ref} = S#state.blocking_tmr,
+ ?vtrace("handle_blocker_exit -> (possibly) stop block timer",[]),
+ stop_block_tmr(Tmr),
+ S#state{admin_state = unblocked,
+ blocker_ref = undefined, blocking_tmr = undefined}.
+
+
+
+%% -------------------------------------------------------------------------
+%% handle_restart
+%%
+%%
+%%
+%%
+handle_restart(#state{config_file = undefined} = State) ->
+ {continue, {error, undefined_config_file}, State};
+handle_restart(#state{config_db = Db, config_file = ConfigFile} = State) ->
+ ?vtrace("load new configuration",[]),
+ {ok, Config} = httpd_conf:load(ConfigFile),
+ ?vtrace("check for illegal changes (addr, port and socket-type)",[]),
+ case (catch check_constant_values(Db, Config)) of
+ ok ->
+ %% If something goes wrong between the remove
+ %% and the store where fu-ed
+ ?vtrace("remove old configuration, now hold you breath...",[]),
+ httpd_conf:remove_all(Db),
+ ?vtrace("store new configuration",[]),
+ case httpd_conf:store(Config) of
+ {ok, NewConfigDB} ->
+ ?vlog("restart done, puh!",[]),
+ {continue, ok, State#state{config_db = NewConfigDB}};
+ Error ->
+ ?vlog("failed store new config: ~n ~p",[Error]),
+ {stop, Error, State}
+ end;
+ Error ->
+ ?vlog("restart NOT performed due to:"
+ "~n ~p",[Error]),
+ {continue, Error, State}
+ end.
+
+
+check_constant_values(Db, Config) ->
+ %% Check port number
+ ?vtrace("check_constant_values -> check port number",[]),
+ Port = httpd_util:lookup(Db,port),
+ case httpd_util:key1search(Config,port) of %% MUST be equal
+ Port ->
+ ok;
+ OtherPort ->
+ throw({error,{port_number_changed,Port,OtherPort}})
+ end,
+
+ %% Check bind address
+ ?vtrace("check_constant_values -> check bind address",[]),
+ Addr = httpd_util:lookup(Db,bind_address),
+ case httpd_util:key1search(Config,bind_address) of %% MUST be equal
+ Addr ->
+ ok;
+ OtherAddr ->
+ throw({error,{addr_changed,Addr,OtherAddr}})
+ end,
+
+ %% Check socket type
+ ?vtrace("check_constant_values -> check socket type",[]),
+ SockType = httpd_util:lookup(Db, com_type),
+ case httpd_util:key1search(Config, com_type) of %% MUST be equal
+ SockType ->
+ ok;
+ OtherSockType ->
+ throw({error,{sock_type_changed,SockType,OtherSockType}})
+ end,
+ ?vtrace("check_constant_values -> done",[]),
+ ok.
+
+
+%% get_ustate(State) -> idle | active | busy
+%%
+%% Retrieve the usage state of the HTTP server:
+%% 0 active connection -> idle
+%% max_clients active connections -> busy
+%% Otherwise -> active
+%%
+get_ustate(State) ->
+ get_ustate(length(State#state.connections),State).
+
+get_ustate(0,_State) ->
+ idle;
+get_ustate(ConnectionCnt,State) ->
+ ConfigDB = State#state.config_db,
+ case httpd_util:lookup(ConfigDB, max_clients, 150) of
+ ConnectionCnt ->
+ busy;
+ _ ->
+ active
+ end.
+
+
+get_astate(S) -> S#state.admin_state.
+
+
+%% Timer handling functions
+start_block_tmr(infinity,_) ->
+ undefined;
+start_block_tmr(T,M) ->
+ erlang:send_after(T,self(),{block_timeout,M}).
+
+stop_block_tmr(undefined) ->
+ ok;
+stop_block_tmr(Ref) ->
+ erlang:cancel_timer(Ref).
+
+
+%% Monitor blocker functions
+monitor_blocker(Pid) when pid(Pid) ->
+ case (catch erlang:monitor(process,Pid)) of
+ MonitorRef ->
+ MonitorRef;
+ {'EXIT',Reason} ->
+ undefined
+ end;
+monitor_blocker(_) ->
+ undefined.
+
+demonitor_blocker(undefined) ->
+ ok;
+demonitor_blocker(Ref) ->
+ (catch erlang:demonitor(Ref)).
+
+
+%% Some status utility functions
+
+update_heavy_load_status(Status) ->
+ update_status_with_time(Status,last_heavy_load).
+
+update_connection_status(Status,ConnCount) ->
+ S1 = case lists:keysearch(max_conn,1,Status) of
+ {value,{max_conn,C1}} when ConnCount > C1 ->
+ lists:keyreplace(max_conn,1,Status,{max_conn,ConnCount});
+ {value,{max_conn,C2}} ->
+ Status;
+ false ->
+ [{max_conn,ConnCount}|Status]
+ end,
+ update_status_with_time(S1,last_connection).
+
+update_status_with_time(Status,Key) ->
+ lists:keyreplace(Key,1,Status,{Key,universal_time()}).
+
+universal_time() -> calendar:universal_time().
+
+
+auth_status(P) when pid(P) ->
+ Items = [status, message_queue_len, reductions,
+ heap_size, stack_size, current_function],
+ {auth_status, process_status(P,Items,[])};
+auth_status(_) ->
+ {auth_status, undefined}.
+
+sec_status(P) when pid(P) ->
+ Items = [status, message_queue_len, reductions,
+ heap_size, stack_size, current_function],
+ {security_status, process_status(P,Items,[])};
+sec_status(_) ->
+ {security_status, undefined}.
+
+acceptor_status(P) when pid(P) ->
+ Items = [status, message_queue_len, reductions,
+ heap_size, stack_size, current_function],
+ {acceptor_status, process_status(P,Items,[])};
+acceptor_status(_) ->
+ {acceptor_status, undefined}.
+
+
+manager_status(P) ->
+ Items = [status, message_queue_len, reductions,
+ heap_size, stack_size],
+ {manager_status, process_status(P,Items,[])}.
+
+
+process_status(P,[],L) ->
+ [{pid,P}|lists:reverse(L)];
+process_status(P,[H|T],L) ->
+ case (catch process_info(P,H)) of
+ {H, Value} ->
+ process_status(P,T,[{H,Value}|L]);
+ _ ->
+ process_status(P,T,[{H,undefined}|L])
+ end.
+
+make_name(Addr,Port) ->
+ httpd_util:make_name("httpd",Addr,Port).
+
+
+report_error(State,String) ->
+ Cdb = State#state.config_db,
+ error_logger:error_report(String),
+ mod_log:report_error(Cdb,String),
+ mod_disk_log:report_error(Cdb,String).
+
+
+set_verbosity(V) ->
+ Units = [manager_verbosity,
+ acceptor_verbosity, request_handler_verbosity,
+ security_verbosity, auth_verbosity],
+ case httpd_util:key1search(V, all) of
+ undefined ->
+ set_verbosity(V, Units);
+ Verbosity when atom(Verbosity) ->
+ V1 = [{Unit, Verbosity} || Unit <- Units],
+ set_verbosity(V1, Units)
+ end.
+
+set_verbosity(_V, []) ->
+ ok;
+set_verbosity(V, [manager_verbosity = Unit|Units]) ->
+ Verbosity = httpd_util:key1search(V, Unit, ?default_verbosity),
+ put(verbosity, ?vvalidate(Verbosity)),
+ set_verbosity(V, Units);
+set_verbosity(V, [Unit|Units]) ->
+ Verbosity = httpd_util:key1search(V, Unit, ?default_verbosity),
+ put(Unit, ?vvalidate(Verbosity)),
+ set_verbosity(V, Units).
+
+
+set_verbosity(manager,V,_S) ->
+ put(verbosity,V);
+set_verbosity(acceptor,V,_S) ->
+ put(acceptor_verbosity,V);
+set_verbosity(request,V,_S) ->
+ put(request_handler_verbosity,V);
+set_verbosity(security,V,S) ->
+ OldVerbosity = put(security_verbosity,V),
+ Addr = httpd_util:lookup(S#state.config_db, bind_address),
+ Port = httpd_util:lookup(S#state.config_db, port),
+ mod_security_server:verbosity(Addr,Port,V),
+ OldVerbosity;
+set_verbosity(auth,V,S) ->
+ OldVerbosity = put(auth_verbosity,V),
+ Addr = httpd_util:lookup(S#state.config_db, bind_address),
+ Port = httpd_util:lookup(S#state.config_db, port),
+ mod_auth_server:verbosity(Addr,Port,V),
+ OldVerbosity;
+
+set_verbosity(all,V,S) ->
+ OldMv = put(verbosity,V),
+ OldAv = put(acceptor_verbosity,V),
+ OldRv = put(request_handler_verbosity,V),
+ OldSv = put(security_verbosity,V),
+ OldAv = put(auth_verbosity,V),
+ Addr = httpd_util:lookup(S#state.config_db, bind_address),
+ Port = httpd_util:lookup(S#state.config_db, port),
+ mod_security_server:verbosity(Addr,Port,V),
+ mod_auth_server:verbosity(Addr,Port,V),
+ [{manager,OldMv}, {request,OldRv}, {security,OldSv}, {auth, OldAv}].
+
+
+%%
+call(ServerRef,Request) ->
+ gen_server:call(ServerRef,Request).
+
+cast(ServerRef,Message) ->
+ gen_server:cast(ServerRef,Message).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_misc_sup.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_misc_sup.erl
new file mode 100644
index 0000000000..e671f05206
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_misc_sup.erl
@@ -0,0 +1,113 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: httpd_misc_sup.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
+%%
+%%----------------------------------------------------------------------
+%% Purpose: The top supervisor for the Megaco/H.248 application
+%%----------------------------------------------------------------------
+
+-module(httpd_misc_sup).
+
+-behaviour(supervisor).
+
+-include("httpd_verbosity.hrl").
+
+%% public
+-export([start/3, stop/1, init/1]).
+
+-export([start_auth_server/3, stop_auth_server/2,
+ start_sec_server/3, stop_sec_server/2]).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% supervisor callback functions
+
+
+start(Addr, Port, MiscSupVerbosity) ->
+ SupName = make_name(Addr, Port),
+ supervisor:start_link({local, SupName}, ?MODULE, [MiscSupVerbosity]).
+
+stop(StartArgs) ->
+ ok.
+
+init([Verbosity]) -> % Supervisor
+ do_init(Verbosity);
+init(BadArg) ->
+ {error, {badarg, BadArg}}.
+
+do_init(Verbosity) ->
+ put(verbosity,?vvalidate(Verbosity)),
+ put(sname,misc_sup),
+ ?vlog("starting", []),
+ Flags = {one_for_one, 0, 1},
+ KillAfter = timer:seconds(1),
+ Workers = [],
+ {ok, {Flags, Workers}}.
+
+
+%%----------------------------------------------------------------------
+%% Function: [start|stop]_[auth|sec]_server/3
+%% Description: Starts a [auth | security] worker (child) process
+%%----------------------------------------------------------------------
+
+start_auth_server(Addr, Port, Verbosity) ->
+ start_permanent_worker(mod_auth_server, Addr, Port,
+ Verbosity, [gen_server]).
+
+stop_auth_server(Addr, Port) ->
+ stop_permanent_worker(mod_auth_server, Addr, Port).
+
+
+start_sec_server(Addr, Port, Verbosity) ->
+ start_permanent_worker(mod_security_server, Addr, Port,
+ Verbosity, [gen_server]).
+
+stop_sec_server(Addr, Port) ->
+ stop_permanent_worker(mod_security_server, Addr, Port).
+
+
+
+%%----------------------------------------------------------------------
+%% Function: start_permanent_worker/5
+%% Description: Starts a permanent worker (child) process
+%%----------------------------------------------------------------------
+
+start_permanent_worker(Mod, Addr, Port, Verbosity, Modules) ->
+ SupName = make_name(Addr, Port),
+ Spec = {{Mod, Addr, Port},
+ {Mod, start_link, [Addr, Port, Verbosity]},
+ permanent, timer:seconds(1), worker, [Mod] ++ Modules},
+ supervisor:start_child(SupName, Spec).
+
+
+%%----------------------------------------------------------------------
+%% Function: stop_permanent_worker/3
+%% Description: Stops a permanent worker (child) process
+%%----------------------------------------------------------------------
+
+stop_permanent_worker(Mod, Addr, Port) ->
+ SupName = make_name(Addr, Port),
+ Name = {Mod, Addr, Port},
+ case supervisor:terminate_child(SupName, Name) of
+ ok ->
+ supervisor:delete_child(SupName, Name);
+ Error ->
+ Error
+ end.
+
+
+make_name(Addr,Port) ->
+ httpd_util:make_name("httpd_misc_sup",Addr,Port).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_parse.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_parse.erl
new file mode 100644
index 0000000000..2f4163de00
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_parse.erl
@@ -0,0 +1,344 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: httpd_parse.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
+%%
+-module(httpd_parse).
+-export([
+ request_header/1,
+ hsplit/2,
+ get_request_record/10,
+ split_lines/1,
+ tagup_header/1]).
+-include("httpd.hrl").
+
+
+%%----------------------------------------------------------------------
+%% request_header
+%%
+%% Input: The request as sent from the client (list of characters)
+%% (may include part of the entity body)
+%%
+%% Returns:
+%% {ok, Info#mod}
+%% {not_implemented,Info#mod}
+%% {bad_request, Reason}
+%%----------------------------------------------------------------------
+
+request_header(Header)->
+ [RequestLine|HeaderFields] = split_lines(Header),
+ ?DEBUG("request ->"
+ "~n RequestLine: ~p"
+ "~n Header: ~p",[RequestLine,Header]),
+ ParsedHeader = tagup_header(HeaderFields),
+ ?DEBUG("request ->"
+ "~n ParseHeader: ~p",[ParsedHeader]),
+ case verify_request(string:tokens(RequestLine," ")) of
+ ["HEAD", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N]] ->
+ {ok, ["HEAD", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N], RequestLine,
+ ParsedHeader]};
+ ["GET", RequestURI, "HTTP/0.9"] ->
+ {ok, ["GET", RequestURI, "HTTP/0.9", RequestLine, ParsedHeader]};
+ ["GET", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N]] ->
+ {ok, ["GET", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N], RequestLine,
+ ParsedHeader]};
+ ["POST", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N]] ->
+ {ok, ["POST", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N], RequestLine,
+ ParsedHeader]};
+ %%HTTP must be 1.1 or higher
+ ["TRACE", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N]] when N>48->
+ {ok, ["TRACE", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N], RequestLine,
+ ParsedHeader]};
+ [Method, RequestURI] ->
+ {not_implemented, RequestLine, Method, RequestURI,ParsedHeader,"HTTP/0.9"};
+ [Method, RequestURI, HTTPVersion] ->
+ {not_implemented, RequestLine, Method, RequestURI,ParsedHeader, HTTPVersion};
+ {bad_request, Reason} ->
+ {bad_request, Reason};
+ Reason ->
+ {bad_request, "Unknown request method"}
+ end.
+
+
+
+
+
+
+%%----------------------------------------------------------------------
+%% The request is passed through the server as a record of type mod get it
+%% ----------------------------------------------------------------------
+
+get_request_record(Socket,SocketType,ConfigDB,Method,RequestURI,
+ HTTPVersion,RequestLine,ParsedHeader,EntityBody,InitData)->
+ PersistentConn=get_persistens(HTTPVersion,ParsedHeader,ConfigDB),
+ Info=#mod{init_data=InitData,
+ data=[],
+ socket_type=SocketType,
+ socket=Socket,
+ config_db=ConfigDB,
+ method=Method,
+ absolute_uri=formatAbsoluteURI(RequestURI,ParsedHeader),
+ request_uri=formatRequestUri(RequestURI),
+ http_version=HTTPVersion,
+ request_line=RequestLine,
+ parsed_header=ParsedHeader,
+ entity_body=maybe_remove_nl(ParsedHeader,EntityBody),
+ connection=PersistentConn},
+ {ok,Info}.
+
+%%----------------------------------------------------------------------
+%% Conmtrol wheater we shall maintain a persistent connection or not
+%%----------------------------------------------------------------------
+get_persistens(HTTPVersion,ParsedHeader,ConfigDB)->
+ case httpd_util:lookup(ConfigDB,persistent_conn,true) of
+ true->
+ case HTTPVersion of
+ %%If it is version prio to 1.1 kill the conneciton
+ [$H, $T, $T, $P, $\/, $1, $.,N] ->
+ case httpd_util:key1search(ParsedHeader,"connection","keep-alive")of
+ %%if the connection isnt ordered to go down let it live
+ %%The keep-alive value is the older http/1.1 might be older
+ %%Clients that use it.
+ "keep-alive" when N >= 49 ->
+ ?DEBUG("CONNECTION MODE: ~p",[true]),
+ true;
+ "close" ->
+ ?DEBUG("CONNECTION MODE: ~p",[false]),
+ false;
+ Connect ->
+ ?DEBUG("CONNECTION MODE: ~p VALUE: ~p",[false,Connect]),
+ false
+ end;
+ _ ->
+ ?DEBUG("CONNECTION MODE: ~p VERSION: ~p",[false,HTTPVersion]),
+ false
+
+ end;
+ _ ->
+ false
+ end.
+
+
+
+
+%%----------------------------------------------------------------------
+%% Control whether the last newline of the body is a part of the message or
+%%it is a part of the multipart message.
+%%----------------------------------------------------------------------
+maybe_remove_nl(Header,Rest) ->
+ case find_content_type(Header) of
+ false ->
+ {ok,EntityBody,_}=regexp:sub(Rest,"\r\n\$",""),
+ EntityBody;
+ {ok, Value} ->
+ case string:str(Value, "multipart/form-data") of
+ 0 ->
+ {ok,EntityBody,_}=regexp:sub(Rest,"\r\n\$",""),
+ EntityBody;
+ _ ->
+ Rest
+ end
+ end.
+
+%%----------------------------------------------------------------------
+%% Cet the content type of the incomming request
+%%----------------------------------------------------------------------
+
+
+find_content_type([]) ->
+ false;
+find_content_type([{Name,Value}|Tail]) ->
+ case httpd_util:to_lower(Name) of
+ "content-type" ->
+ {ok, Value};
+ _ ->
+ find_content_type(Tail)
+ end.
+
+%%----------------------------------------------------------------------
+%% Split the header to a list of strings where each string represents a
+%% HTTP header-field
+%%----------------------------------------------------------------------
+split_lines(Request) ->
+ split_lines(Request, [], []).
+split_lines([], CAcc, Acc) ->
+ lists:reverse([lists:reverse(CAcc)|Acc]);
+
+%%White space in the header fields are allowed but the new line must begin with LWS se
+%%rfc2616 chap 4.2. The rfc do not say what to
+split_lines([$\r, $\n, $\t |Rest], CAcc, Acc) ->
+ split_lines(Rest, [$\r, $\n |CAcc], Acc);
+
+split_lines([$\r, $\n, $\s |Rest], CAcc, Acc) ->
+ split_lines(Rest, [$\r, $\n |CAcc], Acc);
+
+split_lines([$\r, $\n|Rest], CAcc, Acc) ->
+ split_lines(Rest, [], [lists:reverse(CAcc)|Acc]);
+split_lines([Chr|Rest], CAcc, Acc) ->
+ split_lines(Rest, [Chr|CAcc], Acc).
+
+
+%%----------------------------------------------------------------------
+%% This is a 'hack' to stop people from trying to access directories/files
+%% relative to the ServerRoot.
+%%----------------------------------------------------------------------
+
+
+verify_request([Request, RequestURI]) ->
+ verify_request([Request, RequestURI, "HTTP/0.9"]);
+
+verify_request([Request, RequestURI, Protocol]) ->
+ NewRequestURI =
+ case string:str(RequestURI, "?") of
+ 0 ->
+ RequestURI;
+ Ndx ->
+ string:left(RequestURI, Ndx)
+ end,
+ case string:str(NewRequestURI, "..") of
+ 0 ->
+ [Request, RequestURI, Protocol];
+ _ ->
+ {bad_request, {forbidden, RequestURI}}
+ end;
+verify_request(Request) ->
+ Request.
+
+%%----------------------------------------------------------------------
+%% tagup_header
+%%
+%% Parses the header of a HTTP request and returns a key,value tuple
+%% list containing Name and Value of each header directive as of:
+%%
+%% Content-Type: multipart/mixed -> {"Content-Type", "multipart/mixed"}
+%%
+%% But in http/1.1 the field-names are case insencitive so now it must be
+%% Content-Type: multipart/mixed -> {"content-type", "multipart/mixed"}
+%% The standard furthermore says that leading and traling white space
+%% is not a part of the fieldvalue and shall therefore be removed.
+%%----------------------------------------------------------------------
+
+tagup_header([]) -> [];
+tagup_header([Line|Rest]) -> [tag(Line, [])|tagup_header(Rest)].
+
+tag([], Tag) ->
+ {httpd_util:to_lower(lists:reverse(Tag)), ""};
+tag([$:|Rest], Tag) ->
+ {httpd_util:to_lower(lists:reverse(Tag)), httpd_util:strip(Rest)};
+tag([Chr|Rest], Tag) ->
+ tag(Rest, [Chr|Tag]).
+
+
+%%----------------------------------------------------------------------
+%% There are 3 possible forms of the reuqest URI
+%%
+%% 1. * When the request is not for a special assset. is is instead
+%% to the server itself
+%%
+%% 2. absoluteURI the whole servername port and asset is in the request
+%%
+%% 3. The most common form that http/1.0 used abs path that is a path
+%% to the requested asset.
+%5----------------------------------------------------------------------
+formatRequestUri("*")->
+ "*";
+formatRequestUri([$h,$t,$t,$p,$:,$\/,$\/|ServerAndPath]) ->
+ removeServer(ServerAndPath);
+
+formatRequestUri([$H,$T,$T,$P,$:,$\/,$\/|ServerAndPath]) ->
+ removeServer(ServerAndPath);
+
+formatRequestUri(ABSPath) ->
+ ABSPath.
+
+removeServer([$\/|Url])->
+ case Url of
+ []->
+ "/";
+ _->
+ [$\/|Url]
+ end;
+removeServer([N|Url]) ->
+ removeServer(Url).
+
+
+formatAbsoluteURI([$h,$t,$t,$p,$:,$\/,$\/|Uri],ParsedHeader)->
+ [$H,$T,$T,$P,$:,$\/,$\/|Uri];
+
+formatAbsoluteURI([$H,$T,$T,$P,$:,$\/,$\/|Uri],ParsedHeader)->
+ [$H,$T,$T,$P,$:,$\/,$\/|Uri];
+
+formatAbsoluteURI(Uri,ParsedHeader)->
+ case httpd_util:key1search(ParsedHeader,"host") of
+ undefined ->
+ nohost;
+ Host ->
+ Host++Uri
+ end.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%Code below is crap from an older version shall be removed when
+%%transformation to http/1.1 is finished
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+%request(Request) ->
+% ?DEBUG("request -> entry with:"
+% "~n Request: ~s",[Request]),
+ % {BeforeEntityBody, Rest} = hsplit([], Request),
+ % ?DEBUG("request ->"
+% "~n BeforeEntityBody: ~p"
+% "~n Rest: ~p",[BeforeEntityBody, Rest]),
+% [RequestLine|Header] = split_lines(BeforeEntityBody),
+% ?DEBUG("request ->"
+% "~n RequestLine: ~p"
+% "~n Header: ~p",[RequestLine,Header]),
+% ParsedHeader = tagup_header(Header),
+% ?DEBUG("request ->"
+% "~n ParseHeader: ~p",[ParsedHeader]),
+% EntityBody = maybe_remove_nl(ParsedHeader,Rest),
+% ?DEBUG("request ->"
+% "~n EntityBody: ~p",[EntityBody]),
+% case verify_request(string:tokens(RequestLine," ")) of
+% ["HEAD", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N]] ->
+% {ok, ["HEAD", formatRequestUri(RequestURI), [$H,$T,$T,$P,$/,$1,$.,N], RequestLine,
+% ParsedHeader, EntityBody]};
+% ["GET", RequestURI, "HTTP/0.9"] ->
+% {ok, ["GET", RequestURI, "HTTP/0.9", RequestLine, ParsedHeader,
+% EntityBody]};
+% ["GET", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N]] ->
+% {ok, ["GET", formatRequestUri(RequestURI), [$H,$T,$T,$P,$/,$1,$.,N], RequestLine,
+% ParsedHeader,EntityBody]};
+%% ["POST", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N]] ->
+% {ok, ["POST", formatRequestUri(RequestURI), [$H,$T,$T,$P,$/,$1,$.,N], RequestLine,
+% ParsedHeader, EntityBody]};
+% [Method, RequestURI] ->
+% {not_implemented, RequestLine, Method, RequestURI,ParsedHeader,"HTTP/0.9"};
+% [Method, RequestURI, HTTPVersion] ->
+% {not_implemented, RequestLine, Method, RequestURI,ParsedHeader, HTTPVersion};
+% {bad_request, Reason} ->
+% {bad_request, Reason};
+% Reason ->
+% {bad_request, "Unknown request method"}
+% end.
+
+hsplit(Accu,[]) ->
+ {lists:reverse(Accu), []};
+hsplit(Accu, [ $\r, $\n, $\r, $\n | Tail]) ->
+ {lists:reverse(Accu), Tail};
+hsplit(Accu, [H|T]) ->
+ hsplit([H|Accu],T).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_request_handler.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_request_handler.erl
new file mode 100644
index 0000000000..b2d375ceff
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_request_handler.erl
@@ -0,0 +1,994 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: httpd_request_handler.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
+%%
+-module(httpd_request_handler).
+
+%% app internal api
+-export([start_link/2, synchronize/3]).
+
+%% module internal api
+-export([connection/2, do_next_connection/6, read_header/7]).
+-export([parse_trailers/1, newline/1]).
+
+-include("httpd.hrl").
+-include("httpd_verbosity.hrl").
+
+
+%% start_link
+
+start_link(Manager, ConfigDB) ->
+ Pid = proc_lib:spawn(?MODULE, connection, [Manager, ConfigDB]),
+ {ok, Pid}.
+
+
+%% synchronize
+
+synchronize(Pid, SocketType, Socket) ->
+ Pid ! {synchronize, SocketType, Socket}.
+
+% connection
+
+connection(Manager, ConfigDB) ->
+ {SocketType, Socket, {Status, Verbosity}} = await_synchronize(Manager),
+ put(sname,self()),
+ put(verbosity,?vvalidate(Verbosity)),
+ connection1(Status, Manager, ConfigDB, SocketType, Socket).
+
+
+connection1({reject, busy}, Manager, ConfigDB, SocketType, Socket) ->
+ handle_busy(Manager, ConfigDB, SocketType, Socket);
+
+connection1({reject, blocked}, Manager, ConfigDB, SocketType, Socket) ->
+ handle_blocked(Manager, ConfigDB, SocketType, Socket);
+
+connection1(accept, Manager, ConfigDB, SocketType, Socket) ->
+ handle_connection(Manager, ConfigDB, SocketType, Socket).
+
+
+%% await_synchronize
+
+await_synchronize(Manager) ->
+ receive
+ {synchronize, SocketType, Socket} ->
+ ?vlog("received syncronize: "
+ "~n SocketType: ~p"
+ "~n Socket: ~p", [SocketType, Socket]),
+ {SocketType, Socket, httpd_manager:new_connection(Manager)}
+ after 5000 ->
+ exit(synchronize_timeout)
+ end.
+
+
+% handle_busy
+
+handle_busy(Manager, ConfigDB, SocketType, Socket) ->
+ ?vlog("handle busy: ~p", [Socket]),
+ MaxClients = httpd_util:lookup(ConfigDB, max_clients, 150),
+ String = io_lib:format("heavy load (>~w processes)", [MaxClients]),
+ reject_connection(Manager, ConfigDB, SocketType, Socket, String).
+
+
+% handle_blocked
+
+handle_blocked(Manager, ConfigDB, SocketType, Socket) ->
+ ?vlog("handle blocked: ~p", [Socket]),
+ String = "Server maintenance performed, try again later",
+ reject_connection(Manager, ConfigDB, SocketType, Socket, String).
+
+
+% reject_connection
+
+reject_connection(Manager, ConfigDB, SocketType, Socket, Info) ->
+ String = lists:flatten(Info),
+ ?vtrace("send status (503) message", []),
+ httpd_response:send_status(SocketType, Socket, 503, String, ConfigDB),
+ %% This ugly thing is to make ssl deliver the message, before the close...
+ close_sleep(SocketType, 1000),
+ ?vtrace("close the socket", []),
+ close(SocketType, Socket, ConfigDB).
+
+
+% handle_connection
+
+handle_connection(Manager, ConfigDB, SocketType, Socket) ->
+ ?vlog("handle connection: ~p", [Socket]),
+ Resolve = httpd_socket:resolve(SocketType),
+ Peername = httpd_socket:peername(SocketType, Socket),
+ InitData = #init_data{peername=Peername, resolve=Resolve},
+ TimeOut = httpd_util:lookup(ConfigDB, keep_alive_timeout, 150000),
+ NrOfRequest = httpd_util:lookup(ConfigDB, max_keep_alive_request, forever),
+ ?MODULE:do_next_connection(ConfigDB, InitData,
+ SocketType, Socket,NrOfRequest,TimeOut),
+ ?vlog("handle connection: done", []),
+ httpd_manager:done_connection(Manager),
+ ?vlog("handle connection: close socket", []),
+ close(SocketType, Socket, ConfigDB).
+
+
+% do_next_connection
+do_next_connection(_ConfigDB, _InitData, _SocketType, _Socket, NrOfRequests,
+ _Timeout) when NrOfRequests < 1 ->
+ ?vtrace("do_next_connection: done", []),
+ ok;
+do_next_connection(ConfigDB, InitData, SocketType, Socket, NrOfRequests,
+ Timeout) ->
+ Peername = InitData#init_data.peername,
+ case (catch read(ConfigDB, SocketType, Socket, InitData, Timeout)) of
+ {'EXIT', Reason} ->
+ ?vlog("exit reading from socket: ~p",[Reason]),
+ error_logger:error_report({'EXIT',Reason}),
+ String =
+ lists:flatten(
+ io_lib:format("exit reading from socket: ~p => ~n~p~n",
+ [Socket, Reason])),
+ error_log(mod_log,
+ SocketType, Socket, ConfigDB, Peername, String),
+ error_log(mod_disk_log,
+ SocketType, Socket, ConfigDB, Peername, String);
+ {error, Reason} ->
+ handle_read_error(Reason,SocketType,Socket,ConfigDB,Peername);
+ Info when record(Info, mod) ->
+ case Info#mod.connection of
+ true ->
+ ReqTimeout = httpd_util:lookup(ConfigDB,
+ keep_alive_timeout, 150000),
+ ?MODULE:do_next_connection(ConfigDB, InitData,
+ SocketType, Socket,
+ dec(NrOfRequests), ReqTimeout);
+ _ ->
+ ok
+ end;
+ _ ->
+ ok
+ end.
+
+
+
+%% read
+read(ConfigDB, SocketType, Socket, InitData, Timeout) ->
+ ?vdebug("read from socket ~p with Timeout ~p",[Socket, Timeout]),
+ MaxHdrSz = httpd_util:lookup(ConfigDB, max_header_size, 10240),
+ case ?MODULE:read_header(SocketType, Socket, Timeout, MaxHdrSz,
+ ConfigDB, InitData, []) of
+ {socket_closed, Reason} ->
+ ?vlog("Socket closed while reading request header: "
+ "~n ~p", [Reason]),
+ socket_close;
+ {error, Error} ->
+ {error, Error};
+ {ok, Info, EntityBodyPart} ->
+ read1(SocketType, Socket, ConfigDB, InitData, Timeout, Info,
+ EntityBodyPart)
+ end.
+
+%% Got the head and maybe a part of the body: read in the rest
+read1(SocketType, Socket, ConfigDB, InitData, Timeout, Info, BodyPart)->
+ MaxBodySz = httpd_util:lookup(ConfigDB, max_body_size, nolimit),
+ ContentLength = content_length(Info),
+ ?vtrace("ContentLength: ~p", [ContentLength]),
+ case read_entity_body(SocketType, Socket, Timeout, MaxBodySz,
+ ContentLength, BodyPart, Info, ConfigDB) of
+ {socket_closed, Reason} ->
+ ?vlog("Socket closed while reading request body: "
+ "~n ~p", [Reason]),
+ socket_close;
+ {ok, EntityBody} ->
+ finish_request(EntityBody, [], Info);
+ {ok, ExtraHeader, EntityBody} ->
+ finish_request(EntityBody, ExtraHeader, Info);
+ Response ->
+ httpd_socket:close(SocketType, Socket),
+ socket_closed
+ %% Catch up all bad return values
+ end.
+
+
+%% The request is read in send it forward to the module that
+%% generates the response
+
+finish_request(EntityBody, ExtraHeader,
+ #mod{parsed_header = ParsedHeader} = Info)->
+ ?DEBUG("finish_request -> ~n"
+ " EntityBody: ~p~n"
+ " ExtraHeader: ~p~n"
+ " ParsedHeader: ~p~n",
+ [EntityBody, ExtraHeader, ParsedHeader]),
+ httpd_response:send(Info#mod{parsed_header = ParsedHeader ++ ExtraHeader,
+ entity_body = EntityBody}).
+
+
+%% read_header
+
+%% This algorithm rely on the buffer size of the inet driver together
+%% with the {active, once} socket option. Atmost one message of this
+%% size will be received at a given time. When a full header has been
+%% read, the body is read with the recv function (the body size is known).
+%%
+read_header(SocketType, Socket, Timeout, MaxHdrSz, ConfigDB,
+ InitData, SoFar0) ->
+ T = t(),
+ %% remove any newlines at the begining, they might be crap from ?
+ SoFar = remove_newline(SoFar0),
+
+ case terminated_header(MaxHdrSz, SoFar) of
+ {true, Header, EntityBodyPart} ->
+ ?vdebug("read_header -> done reading header: "
+ "~n length(Header): ~p"
+ "~n length(EntityBodyPart): ~p",
+ [length(Header), length(EntityBodyPart)]),
+ transform_header(SocketType, Socket, Header, ConfigDB, InitData,
+ EntityBodyPart);
+ false ->
+ ?vtrace("read_header -> "
+ "~n set active = 'once' and "
+ "await a chunk of the header", []),
+
+ case httpd_socket:active_once(SocketType, Socket) of
+ ok ->
+ receive
+ %%
+ %% TCP
+ %%
+ {tcp, Socket, Data} ->
+ ?vtrace("read_header(ip) -> got some data: ~p",
+ [sz(Data)]),
+ ?MODULE:read_header(SocketType, Socket,
+ Timeout - (t()-T),
+ MaxHdrSz, ConfigDB,
+ InitData, SoFar ++ Data);
+ {tcp_closed, Socket} ->
+ ?vtrace("read_header(ip) -> socket closed",[]),
+ {socket_closed,normal};
+ {tcp_error, Socket, Reason} ->
+ ?vtrace("read_header(ip) -> socket error: ~p",
+ [Reason]),
+ {socket_closed, Reason};
+
+ %%
+ %% SSL
+ %%
+ {ssl, Socket, Data} ->
+ ?vtrace("read_header(ssl) -> got some data: ~p",
+ [sz(Data)]),
+ ?MODULE:read_header(SocketType, Socket,
+ Timeout - (t()-T),
+ MaxHdrSz, ConfigDB,
+ InitData, SoFar ++ Data);
+ {ssl_closed, Socket} ->
+ ?vtrace("read_header(ssl) -> socket closed", []),
+ {socket_closed, normal};
+ {ssl_error, Socket, Reason} ->
+ ?vtrace("read_header(ssl) -> socket error: ~p",
+ [Reason]),
+ {socket_closed, Reason}
+
+ after Timeout ->
+ ?vlog("read_header -> timeout", []),
+ {socket_closed, timeout}
+ end;
+
+ Error ->
+ httpd_response:send_status(SocketType, Socket,
+ 500, none, ConfigDB),
+ Error
+ end
+ end.
+
+
+terminated_header(MaxHdrSz, Data) ->
+ D1 = lists:flatten(Data),
+ ?vtrace("terminated_header -> Data size: ~p",[sz(D1)]),
+ case hsplit(MaxHdrSz,[],D1) of
+ not_terminated ->
+ false;
+ [Header, EntityBodyPart] ->
+ {true, Header++"\r\n\r\n",EntityBodyPart}
+ end.
+
+
+transform_header(SocketType, Socket, Request, ConfigDB, InitData, BodyPart) ->
+ case httpd_parse:request_header(Request) of
+ {not_implemented, RequestLine, Method, RequestURI, ParsedHeader,
+ HTTPVersion} ->
+ httpd_response:send_status(SocketType, Socket, 501,
+ {Method, RequestURI, HTTPVersion},
+ ConfigDB),
+ {error,"Not Implemented"};
+ {bad_request, {forbidden, URI}} ->
+ httpd_response:send_status(SocketType, Socket, 403, URI, ConfigDB),
+ {error,"Forbidden Request"};
+ {bad_request, Reason} ->
+ httpd_response:send_status(SocketType, Socket, 400, none,
+ ConfigDB),
+ {error,"Malformed request"};
+ {ok,[Method, RequestURI, HTTPVersion, RequestLine, ParsedHeader]} ->
+ ?DEBUG("send -> ~n"
+ " Method: ~p~n"
+ " RequestURI: ~p~n"
+ " HTTPVersion: ~p~n"
+ " RequestLine: ~p~n",
+ [Method, RequestURI, HTTPVersion, RequestLine]),
+ {ok, Info} =
+ httpd_parse:get_request_record(Socket, SocketType, ConfigDB,
+ Method, RequestURI, HTTPVersion,
+ RequestLine, ParsedHeader,
+ [], InitData),
+ %% Control that the Host header field is provided
+ case Info#mod.absolute_uri of
+ nohost ->
+ case Info#mod.http_version of
+ "HTTP/1.1" ->
+ httpd_response:send_status(Info, 400, none),
+ {error,"No host specified"};
+ _ ->
+ {ok, Info, BodyPart}
+ end;
+ _ ->
+ {ok, Info, BodyPart}
+ end
+ end.
+
+
+hsplit(_MaxHdrSz, Accu,[]) ->
+ not_terminated;
+hsplit(_MaxHdrSz, Accu, [ $\r, $\n, $\r, $\n | Tail]) ->
+ [lists:reverse(Accu), Tail];
+hsplit(nolimit, Accu, [H|T]) ->
+ hsplit(nolimit,[H|Accu],T);
+hsplit(MaxHdrSz, Accu, [H|T]) when length(Accu) < MaxHdrSz ->
+ hsplit(MaxHdrSz,[H|Accu],T);
+hsplit(MaxHdrSz, Accu, D) ->
+ throw({error,{header_too_long,length(Accu),length(D)}}).
+
+
+
+%%----------------------------------------------------------------------
+%% The http/1.1 standard chapter 8.2.3 says that a request containing
+%% An Except header-field must be responded to by 100 (Continue) by
+%% the server before the client sends the body.
+%%----------------------------------------------------------------------
+
+read_entity_body(SocketType, Socket, Timeout, Max, Length, BodyPart, Info,
+ ConfigDB) when integer(Max) ->
+ case expect(Info#mod.http_version, Info#mod.parsed_header, ConfigDB) of
+ continue when Max > Length ->
+ ?DEBUG("read_entity_body()->100 Continue ~n", []),
+ httpd_response:send_status(Info, 100, ""),
+ read_entity_body2(SocketType, Socket, Timeout, Max, Length,
+ BodyPart, Info, ConfigDB);
+ continue when Max < Length ->
+ httpd_response:send_status(Info, 417, "Body to big"),
+ httpd_socket:close(SocketType, Socket),
+ {socket_closed,"Expect denied according to size"};
+ break ->
+ httpd_response:send_status(Info, 417, "Method not allowed"),
+ httpd_socket:close(SocketType, Socket),
+ {socket_closed,"Expect conditions was not fullfilled"};
+ no_expect_header ->
+ read_entity_body2(SocketType, Socket, Timeout, Max, Length,
+ BodyPart, Info, ConfigDB);
+ http_1_0_expect_header ->
+ httpd_response:send_status(Info, 400,
+ "Only HTTP/1.1 Clients "
+ "may use the Expect Header"),
+ httpd_socket:close(SocketType, Socket),
+ {socket_closed,"Due to a HTTP/1.0 expect header"}
+ end;
+
+read_entity_body(SocketType, Socket, Timeout, Max, Length, BodyPart,
+ Info, ConfigDB) ->
+ case expect(Info#mod.http_version, Info#mod.parsed_header, ConfigDB) of
+ continue ->
+ ?DEBUG("read_entity_body() -> 100 Continue ~n", []),
+ httpd_response:send_status(Info, 100, ""),
+ read_entity_body2(SocketType, Socket, Timeout, Max, Length,
+ BodyPart, Info, ConfigDB);
+ break->
+ httpd_response:send_status(Info, 417, "Method not allowed"),
+ httpd_socket:close(SocketType, Socket),
+ {socket_closed,"Expect conditions was not fullfilled"};
+ no_expect_header ->
+ read_entity_body2(SocketType, Socket, Timeout, Max, Length,
+ BodyPart, Info, ConfigDB);
+ http_1_0_expect_header ->
+ httpd_response:send_status(Info, 400,
+ "HTTP/1.0 Clients are not allowed "
+ "to use the Expect Header"),
+ httpd_socket:close(SocketType, Socket),
+ {socket_closed,"Expect header field in an HTTP/1.0 request"}
+ end.
+
+%%----------------------------------------------------------------------
+%% control if the body is transfer encoded
+%%----------------------------------------------------------------------
+read_entity_body2(SocketType, Socket, Timeout, Max, Length, BodyPart,
+ Info, ConfigDB) ->
+ ?DEBUG("read_entity_body2() -> "
+ "~n Max: ~p"
+ "~n Length: ~p"
+ "~n Socket: ~p", [Max, Length, Socket]),
+
+ case transfer_coding(Info) of
+ {chunked, ChunkedData} ->
+ ?DEBUG("read_entity_body2() -> "
+ "Transfer-encoding: Chunked Data: BodyPart ~s", [BodyPart]),
+ read_chunked_entity(Info, Timeout, Max, Length, ChunkedData, [],
+ BodyPart);
+ unknown_coding ->
+ ?DEBUG("read_entity_body2() -> Transfer-encoding: Unknown",[]),
+ httpd_response:send_status(Info, 501, "Unknown Transfer-Encoding"),
+ httpd_socket:close(SocketType, Socket),
+ {socket_closed,"Expect conditions was not fullfilled"};
+ none ->
+ ?DEBUG("read_entity_body2() -> Transfer-encoding: none",[]),
+ read_entity_body(SocketType, Socket, Timeout, Max, Length,
+ BodyPart)
+ end.
+
+
+%%----------------------------------------------------------------------
+%% The body was plain read it from the socket
+%% ----------------------------------------------------------------------
+read_entity_body(_SocketType, _Socket, _Timeout, _Max, 0, _BodyPart) ->
+ {ok, []};
+
+read_entity_body(_SocketType, _Socket, _Timeout, Max, Len, _BodyPart)
+ when Max < Len ->
+ ?vlog("body to long: "
+ "~n Max: ~p"
+ "~n Len: ~p", [Max,Len]),
+ throw({error,{body_too_long,Max,Len}});
+
+%% OTP-4409: Fixing POST problem
+read_entity_body(_,_,_,_, Len, BodyPart) when Len == length(BodyPart) ->
+ ?vtrace("read_entity_body -> done when"
+ "~n Len = length(BodyPart): ~p", [Len]),
+ {ok, BodyPart};
+
+%% OTP-4550: Fix problem with trailing garbage produced by some clients.
+read_entity_body(_, _, _, _, Len, BodyPart) when Len < length(BodyPart) ->
+ ?vtrace("read_entity_body -> done when"
+ "~n Len: ~p"
+ "~n length(BodyPart): ~p", [Len, length(BodyPart)]),
+ {ok, lists:sublist(BodyPart,Len)};
+
+read_entity_body(SocketType, Socket, Timeout, Max, Len, BodyPart) ->
+ ?vtrace("read_entity_body -> entry when"
+ "~n Len: ~p"
+ "~n length(BodyPart): ~p", [Len, length(BodyPart)]),
+ %% OTP-4548:
+ %% The length calculation was previously (inets-2.*) done in the
+ %% read function. As of 3.0 it was removed from read but not
+ %% included here.
+ L = Len - length(BodyPart),
+ case httpd_socket:recv(SocketType, Socket, L, Timeout) of
+ {ok, Body} ->
+ ?vtrace("read_entity_body -> received some data:"
+ "~n length(Body): ~p", [length(Body)]),
+ {ok, BodyPart ++ Body};
+ {error,closed} ->
+ {socket_closed,normal};
+ {error,etimedout} ->
+ {socket_closed, timeout};
+ {error,Reason} ->
+ {socket_closed, Reason};
+ Other ->
+ {socket_closed, Other}
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% If the body of the message is encoded used the chunked transfer encoding
+%% it looks somethin like this:
+%% METHOD URI HTTP/VSN
+%% Transfer-Encoding: chunked
+%% CRLF
+%% ChunkSize
+%% Chunk
+%% ChunkSize
+%% Chunk
+%% 0
+%% Trailer
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+read_chunked_entity(Info, Timeout, Max, Length, ChunkedData, Body, []) ->
+ ?DEBUG("read_chunked_entity()->:no_chunks ~n", []),
+ read_chunked_entity(Info#mod.socket_type, Info#mod.socket,
+ Timeout, Max, Length, ChunkedData, Body,
+ Info#mod.config_db, Info);
+
+read_chunked_entity(Info, Timeout, Max, Length, ChunkedData, Body, BodyPart) ->
+ %% Get the size
+ ?DEBUG("read_chunked_entity() -> PrefetchedBodyPart: ~p ~n",[BodyPart]),
+ case parse_chunk_size(Info, Timeout, BodyPart) of
+ {ok, Size, NewBodyPart} when Size > 0 ->
+ ?DEBUG("read_chunked_entity() -> Size: ~p ~n", [Size]),
+ case parse_chunked_entity_body(Info, Timeout, Max, length(Body),
+ Size, NewBodyPart) of
+ {ok, Chunk, NewBodyPart1} ->
+ ?DEBUG("read_chunked_entity()->Size: ~p ~n", [Size]),
+ read_chunked_entity(Info, Timeout, Max, Length,
+ ChunkedData, Body ++ Chunk,
+ NewBodyPart1);
+ OK ->
+ httpd_socket:close(Info#mod.socket_type, Info#mod.socket),
+ {socket_closed, error}
+ end;
+ {ok, 0, Trailers} ->
+ ?DEBUG("read_chunked_entity()->Size: 0, Trailers: ~s Body: ~s ~n",
+ [Trailers, Body]),
+ case parse_chunk_trailer(Info, Timeout, Info#mod.config_db,
+ Trailers) of
+ {ok, TrailerFields} ->
+ {ok, TrailerFields, Body};
+ _->
+ {ok, []}
+ end;
+ Error ->
+ Error
+ end.
+
+
+parse_chunk_size(Info, Timeout, BodyPart) ->
+ case httpd_util:split(remove_newline(BodyPart), "\r\n", 2) of
+ {ok, [Size, Body]} ->
+ ?DEBUG("parse_chunk_size()->Size: ~p ~n", [Size]),
+ {ok, httpd_util:hexlist_to_integer(Size), Body};
+ {ok, [Size]} ->
+ ?DEBUG("parse_chunk_size()->Size: ~p ~n", [Size]),
+ Sz = get_chunk_size(Info#mod.socket_type,
+ Info#mod.socket, Timeout,
+ lists:reverse(Size)),
+ {ok, Sz, []}
+ end.
+
+%%----------------------------------------------------------------------
+%% We got the chunk size get the chunk
+%%
+%% Max: Max numbers of bytes to read may also be undefined
+%% Length: Numbers of bytes already read
+%% Size Numbers of byte to read for the chunk
+%%----------------------------------------------------------------------
+
+%% body to big
+parse_chunked_entity_body(Info, Timeout, Max, Length, Size, BodyPart)
+ when Max =< (Length + Size) ->
+ {error, body_to_big};
+
+%% Prefetched body part is bigger than the current chunk
+%% (i.e. BodyPart includes more than one chunk)
+parse_chunked_entity_body(Info, Timeout, Max, Length, Size, BodyPart)
+ when (Size+2) =< length(BodyPart) ->
+ Chunk = string:substr(BodyPart, 1, Size),
+ Rest = string:substr(BodyPart, Size+3),
+ ?DEBUG("parse_chunked_entity_body() -> ~nChunk: ~s ~nRest: ~s ~n",
+ [Chunk, Rest]),
+ {ok, Chunk, Rest};
+
+
+%% We just got a part of the current chunk
+parse_chunked_entity_body(Info, Timeout, Max, Length, Size, BodyPart) ->
+ %% OTP-4551:
+ %% Subtracting BodyPart from Size does not produce an integer
+ %% when BodyPart is a list...
+ Remaining = Size - length(BodyPart),
+ LastPartOfChunk = read_chunked_entity_body(Info#mod.socket_type,
+ Info#mod.socket,
+ Timeout, Max,
+ Length, Remaining),
+ %% Remove newline
+ httpd_socket:recv(Info#mod.socket_type, Info#mod.socket, 2, Timeout),
+ ?DEBUG("parse_chunked_entity_body() -> "
+ "~nBodyPart: ~s"
+ "~nLastPartOfChunk: ~s ~n",
+ [BodyPart, LastPartOfChunk]),
+ {ok, BodyPart ++ LastPartOfChunk, []}.
+
+
+%%----------------------------------------------------------------------
+%% If the data we got along with the header contained the whole chunked body
+%% It may aswell contain the trailer :-(
+%%----------------------------------------------------------------------
+%% Either trailer begins with \r\n and then all data is there or
+%% The trailer has data then read upto \r\n\r\n
+parse_chunk_trailer(Info,Timeout,ConfigDB,"\r\n")->
+ {ok,[]};
+parse_chunk_trailer(Info,Timeout,ConfigDB,Trailers) ->
+ ?DEBUG("parse_chunk_trailer()->Trailers: ~s ~n", [Trailers]),
+ case string:rstr(Trailers,"\r\n\r\n") of
+ 0 ->
+ MaxHdrSz=httpd_util:lookup(ConfigDB, max_header_size, 10240),
+ read_trailer_end(Info,Timeout,MaxHdrSz,Trailers);
+ _->
+ %%We got the whole header parse it up
+ parse_trailers(Trailers)
+ end.
+
+parse_trailers(Trailer)->
+ ?DEBUG("parse_trailer()->Trailer: ~s",[Trailer]),
+ {ok,[Fields0|Crap]}=httpd_util:split(Trailer,"\r\n\r\n",2),
+ Fields=string:tokens(Fields0,"\r\n"),
+ [getTrailerField(X)||X<-Fields,lists:member($:,X)].
+
+
+read_trailer_end(Info,Timeout,MaxHdrSz,[])->
+ ?DEBUG("read_trailer_end()->[]",[]),
+ case read_trailer(Info#mod.socket_type,Info#mod.socket,
+ Timeout,MaxHdrSz,[],[],
+ httpd_util:key1search(Info#mod.parsed_header,"trailer",[])) of
+ {ok,Trailers}->
+ Trailers;
+ _->
+ []
+ end;
+read_trailer_end(Info,Timeout,MaxHdrSz,Trailers)->
+ ?DEBUG("read_trailer_end()->Trailers: ~s ~n ",[Trailers]),
+ %% Get the last paart of the the last headerfield
+ End=lists:reverse(lists:takewhile(fun(X)->case X of 10 ->false;13->false;_ ->true end end,lists:reverse(Trailers))),
+ Fields0=regexp:split(Trailers,"\r\n"),
+ %%Get rid of the last header field
+ [_Last|Fields]=lists:reverse(Fields0),
+ Headers=[getTrailerField(X)||X<-Fields,lists:member($:,X)],
+ case read_trailer(Info#mod.socket_type,Info#mod.socket,
+ Timeout,MaxHdrSz,Headers,End,
+ httpd_util:key1search(Info#mod.parsed_header,"trailer",[])) of
+ {ok,Trailers}->
+ Trailers;
+ _->
+ []
+ end.
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% The code below is a a good way to read in chunked encoding but
+%% that require that the encoding comes from a stream and not from a list
+%%&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+
+%%----------------------------------------------------------------------
+%% The body is encoded by chubnked encoding read it in
+%% ChunkedData= Chunked extensions
+%% Body= the inread chunked body
+%% Max: Max numbers of bytes to read
+%% Length: Numbers of bytes already readed
+%% Size Numbers of byte to read for the chunk
+%%----------------------------------------------------------------------
+
+
+
+read_chunked_entity(SocketType, Socket, Timeout, Max, Length, ChunkedData,
+ Body, ConfigDB, Info) ->
+ T = t(),
+ case get_chunk_size(SocketType,Socket,Timeout,[]) of
+ Size when integer(Size), Size>0 ->
+ case read_chunked_entity_body(SocketType, Socket,
+ Timeout-(t()-T),
+ Max, length(Body), Size) of
+ {ok,Chunk} ->
+ ?DEBUG("read_chunked_entity/9 Got a chunk: ~p " ,[Chunk]),
+ %% Two bytes are left of the chunk, that is the CRLF
+ %% at the end that is not a part of the message
+ %% So we read it and do nothing with it.
+ httpd_socket:recv(SocketType,Socket,2,Timeout-(t()-T)),
+ read_chunked_entity(SocketType, Socket, Timeout-(t()-T),
+ Max, Length, ChunkedData, Body++Chunk,
+ ConfigDB, Info);
+ Error ->
+ ?DEBUG("read_chunked_entity/9 Error: ~p " ,[Error]),
+ httpd_socket:close(SocketType,Socket),
+ {socket_closed,error}
+ end;
+ Size when integer(Size), Size == 0 ->
+ %% Must read in any trailer fields here
+ read_chunk_trailer(SocketType, Socket, Timeout,
+ Max, Info, ChunkedData, Body, ConfigDB);
+ Error ->
+ Error
+ end.
+
+
+%% If a user wants to send header data after the chunked data we
+%% must pick it out
+read_chunk_trailer(SocketType, Socket, Timeout, Max, Info, ChunkedData,
+ Body, ConfigDB) ->
+ ?DEBUG("read_chunk_trailer/8: ~p " ,[Body]),
+ MaxHdrSz = httpd_util:lookup(ConfigDB,max_header_size,10240),
+ case httpd_util:key1search(Info#mod.parsed_header,"trailer")of
+ undefined ->
+ {ok,Body};
+ Fields ->
+ case read_trailer(SocketType, Socket, Timeout,
+ MaxHdrSz, [], [],
+ string:tokens(
+ httpd_util:to_lower(Fields),",")) of
+ {ok,[]} ->
+ {ok,Body};
+ {ok,HeaderFields} ->
+ % ParsedExtraHeaders =
+ % httpd_parse:tagup_header(httpd_parse:split_lines(HeaderFields)),
+ {ok,HeaderFields,Body};
+ Error ->
+ Error
+ end
+ end.
+
+read_chunked_entity_body(SocketType, Socket, Timeout, Max, Length, Size)
+ when integer(Max) ->
+ read_entity_body(SocketType, Socket, Timeout, Max-Length, Size, []);
+
+read_chunked_entity_body(SocketType, Socket, Timeout, Max, _Length, Size) ->
+ read_entity_body(SocketType, Socket, Timeout, Max, Size, []).
+
+%% If we read in the \r\n the httpd_util:hexlist_to_integer
+%% Will remove it and we get rid of it emmediatly :-)
+get_chunk_size(SocketType, Socket, Timeout, Size) ->
+ T = t(),
+ ?DEBUG("get_chunk_size: ~p " ,[Size]),
+ case httpd_socket:recv(SocketType,Socket,1,Timeout) of
+ {ok,[Digit]} when Digit==$\n ->
+ httpd_util:hexlist_to_integer(lists:reverse(Size));
+ {ok,[Digit]} ->
+ get_chunk_size(SocketType,Socket,Timeout-(t()-T),[Digit|Size]);
+ {error,closed} ->
+ {socket_closed,normal};
+ {error,etimedout} ->
+ {socket_closed, timeout};
+ {error,Reason} ->
+ {socket_closed, Reason};
+ Other ->
+ {socket_closed,Other}
+ end.
+
+
+
+
+%%----------------------------------------------------------------------
+%% Reads the HTTP-trailer
+%% Would be easy to tweak the read_head to do this but in this way
+%% the chunked encoding can be updated better.
+%%----------------------------------------------------------------------
+
+
+%% When end is reached
+%% read_trailer(SocketType,Socket,Timeout,MaxHdrSz,Headers,Last,[]) ->
+%% {ok,Headers};
+
+%% When header to big
+read_trailer(_,_,_,MaxHdrSz,Headers,Bs,_Fields)
+ when MaxHdrSz < length(Headers) ->
+ ?vlog("header to long: "
+ "~n MaxHdrSz: ~p"
+ "~n length(Bs): ~p", [MaxHdrSz,length(Bs)]),
+ throw({error,{header_too_long,MaxHdrSz,length(Bs)}});
+
+%% The last Crlf is there
+read_trailer(_, _, _, _, Headers, [$\n, $\r], _) ->
+ {ok,Headers};
+
+read_trailer(SocketType, Socket, Timeout, MaxHdrSz, Headers,
+ [$\n, $\r|Rest], Fields) ->
+ case getTrailerField(lists:reverse(Rest))of
+ {error,Reason}->
+ {error,"Bad trailer"};
+ {HeaderField,Value}->
+ case lists:member(HeaderField,Fields) of
+ true ->
+ read_trailer(SocketType,Socket,Timeout,MaxHdrSz,
+ [{HeaderField,Value} |Headers],[],
+ lists:delete(HeaderField,Fields));
+ false ->
+ read_trailer(SocketType,Socket,Timeout,MaxHdrSz,
+ Headers,[],Fields)
+ end
+ end;
+
+% read_trailer(SocketType,Socket,Timeout,MaxHdrSz,Headers,[$\n, $\r|Rest],Fields) ->
+% case Rest of
+% [] ->
+% read_trailer(SocketType,Socket,Timeout,MaxHdrSz,Headers,Rest,Fields);
+% Field ->
+% case getTrailerField(lists:reverse(Rest))of
+% {error,Reason}->
+% {error,"Bad trailer"};
+% {HeaderField,Value}->
+% case lists:member(HeaderField,Fields) of
+% true ->
+% read_trailer(SocketType,Socket,Timeout,MaxHdrSz,
+% [{HeaderField,Value} |Headers],[],
+% lists:delete(HeaderField,Fields));
+% false ->
+% read_trailer(SocketType,Socket,Timeout,MaxHdrSz,
+% Headers,[],Fields)
+% end
+% end
+% end;
+
+read_trailer(SocketType,Socket,Timeout,MaxHdrSz,Headers,Bs,Fields) ->
+ %% ?vlog("read_header -> entry with Timeout: ~p",[Timeout]),
+ T = t(),
+ case (catch httpd_socket:recv(SocketType,Socket,1,Timeout)) of
+ {ok,[B]} ->
+ read_trailer(SocketType, Socket, Timeout-(t()-T),
+ MaxHdrSz, Headers, [B|Bs], Fields);
+ {error,closed} ->
+ {socket_closed,normal};
+ {error,etimedout} ->
+ {socket_closed, timeout};
+ {error,Reason} ->
+ {socket_closed, Reason};
+ Other ->
+ {socket_closed,Other}
+ end.
+
+getTrailerField(HeaderField)->
+ case string:str(HeaderField,":") of
+ 0->
+ {error,"badheaderfield"};
+ Number ->
+ {httpd_util:to_lower(string:substr(HeaderField,1,Number-1)),
+ httpd_util:to_lower(string:substr(HeaderField,Number+1))}
+ end.
+
+
+
+
+%% Time in milli seconds
+t() ->
+ {A,B,C} = erlang:now(),
+ A*1000000000+B*1000+(C div 1000).
+
+%%----------------------------------------------------------------------
+%% If the user sends an expect header-field with the value 100-continue
+%% We must send a 100 status message if he is a HTTP/1.1 client.
+
+%% If it is an HTTP/1.0 client it's little more difficult.
+%% If expect is not defined it is easy but in the other case shall we
+%% Break or the transmission or let it continue the standard is not clear
+%% if to break connection or wait for data.
+%%----------------------------------------------------------------------
+expect(HTTPVersion,ParsedHeader,ConfigDB)->
+ case HTTPVersion of
+ [$H,$T,$T,$P,$\/,$1,$.,N|_Whatever]when N>=1->
+ case httpd_util:key1search(ParsedHeader,"expect") of
+ "100-continue" ->
+ continue;
+ undefined ->
+ no_expect_header;
+ NewValue ->
+ break
+ end;
+ _OldVersion ->
+ case httpd_util:key1search(ParsedHeader,"expect") of
+ undefined ->
+ no_expect_header;
+ NewValue ->
+ case httpd_util:lookup(ConfigDB,expect,continue) of
+ continue->
+ no_expect_header;
+ _ ->
+ http_1_0_expect_header
+ end
+ end
+ end.
+
+
+%%----------------------------------------------------------------------
+%% According to the http/1.1 standard all applications must understand
+%% Chunked encoded data. (Last line chapter 3.6.1).
+transfer_coding(#mod{parsed_header = Ph}) ->
+ case httpd_util:key1search(Ph, "transfer-encoding", none) of
+ none ->
+ none;
+ [$c,$h,$u,$n,$k,$e,$d|Data]->
+ {chunked,Data};
+ _ ->
+ unknown_coding
+ end.
+
+
+
+handle_read_error({header_too_long,Max,Rem},
+ SocketType,Socket,ConfigDB,Peername) ->
+ String = io_lib:format("header too long: ~p : ~p",[Max,Rem]),
+ handle_read_error(ConfigDB,String,SocketType,Socket,Peername,
+ max_header_action,close);
+handle_read_error({body_too_long,Max,Actual},
+ SocketType,Socket,ConfigDB,Peername) ->
+ String = io_lib:format("body too long: ~p : ~p",[Max,Actual]),
+ handle_read_error(ConfigDB,String,SocketType,Socket,Peername,
+ max_body_action,close);
+handle_read_error(Error,SocketType,Socket,ConfigDB,Peername) ->
+ ok.
+
+
+handle_read_error(ConfigDB, ReasonString, SocketType, Socket, Peername,
+ Item, Default) ->
+ ?vlog("error reading request: ~s",[ReasonString]),
+ E = lists:flatten(
+ io_lib:format("Error reading request: ~s",[ReasonString])),
+ error_log(mod_log, SocketType, Socket, ConfigDB, Peername, E),
+ error_log(mod_disk_log, SocketType, Socket, ConfigDB, Peername, E),
+ case httpd_util:lookup(ConfigDB,Item,Default) of
+ reply414 ->
+ send_read_status(SocketType, Socket, 414, ReasonString, ConfigDB);
+ _ ->
+ ok
+ end.
+
+send_read_status(SocketType, Socket, Code, ReasonString, ConfigDB) ->
+ httpd_response:send_status(SocketType, Socket, Code, ReasonString,
+ ConfigDB).
+
+
+error_log(Mod, SocketType, Socket, ConfigDB, Peername, String) ->
+ Modules = httpd_util:lookup(ConfigDB, modules,
+ [mod_get, mod_head, mod_log]),
+ case lists:member(Mod, Modules) of
+ true ->
+ Mod:error_log(SocketType, Socket, ConfigDB, Peername, String);
+ _ ->
+ ok
+ end.
+
+
+sz(L) when list(L) ->
+ length(L);
+sz(B) when binary(B) ->
+ size(B);
+sz(O) ->
+ {unknown_size,O}.
+
+
+%% Socket utility functions:
+
+close(SocketType, Socket, ConfigDB) ->
+ case httpd_socket:close(SocketType, Socket) of
+ ok ->
+ ok;
+ {error, Reason} ->
+ ?vlog("error while closing socket: ~p",[Reason]),
+ ok
+ end.
+
+close_sleep({ssl, _}, Time) ->
+ sleep(Time);
+close_sleep(_, _) ->
+ ok.
+
+
+sleep(T) -> receive after T -> ok end.
+
+
+dec(N) when integer(N) ->
+ N-1;
+dec(N) ->
+ N.
+
+
+content_length(#mod{parsed_header = Ph}) ->
+ list_to_integer(httpd_util:key1search(Ph, "content-length","0")).
+
+
+remove_newline(List)->
+ lists:dropwhile(fun newline/1,List).
+
+newline($\r) ->
+ true;
+newline($\n) ->
+ true;
+newline(_Sign) ->
+ false.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_response.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_response.erl
new file mode 100644
index 0000000000..1685cbc129
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_response.erl
@@ -0,0 +1,437 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: httpd_response.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
+%%
+-module(httpd_response).
+-export([send/1, send_status/3, send_status/5]).
+
+%%code is the key for the statuscode ex: 200 404 ...
+-define(HTTP11HEADERFIELDS,[content_length, accept_ranges, cache_control, date,
+ pragma, trailer, transfer_encoding, etag, location,
+ retry_after, server, allow,
+ content_encoding, content_language,
+ content_location, content_MD5, content_range,
+ content_type, expires, last_modified]).
+
+-define(HTTP10HEADERFIELDS,[content_length, date, pragma, transfer_encoding,
+ location, server, allow, content_encoding,
+ content_type, last_modified]).
+
+-define(PROCEED_RESPONSE(StatusCode, Info),
+ {proceed,
+ [{response,{already_sent, StatusCode,
+ httpd_util:key1search(Info#mod.data,content_lenght)}}]}).
+
+
+-include("httpd.hrl").
+
+-define(VMODULE,"RESPONSE").
+-include("httpd_verbosity.hrl").
+
+%% send
+
+send(#mod{config_db = ConfigDB} = Info) ->
+ ?vtrace("send -> Request line: ~p", [Info#mod.request_line]),
+ Modules = httpd_util:lookup(ConfigDB,modules,[mod_get, mod_head, mod_log]),
+ case traverse_modules(Info, Modules) of
+ done ->
+ Info;
+ {proceed, Data} ->
+ case httpd_util:key1search(Data, status) of
+ {StatusCode, PhraseArgs, Reason} ->
+ ?vdebug("send -> proceed/status: ~n"
+ "~n StatusCode: ~p"
+ "~n PhraseArgs: ~p"
+ "~n Reason: ~p",
+ [StatusCode, PhraseArgs, Reason]),
+ send_status(Info, StatusCode, PhraseArgs),
+ Info;
+
+ undefined ->
+ case httpd_util:key1search(Data, response) of
+ {already_sent, StatusCode, Size} ->
+ ?vtrace("send -> already sent: "
+ "~n StatusCode: ~p"
+ "~n Size: ~p",
+ [StatusCode, Size]),
+ Info;
+ {response, Header, Body} -> %% New way
+ send_response(Info, Header, Body),
+ Info;
+ {StatusCode, Response} -> %% Old way
+ send_response_old(Info, StatusCode, Response),
+ Info;
+ undefined ->
+ ?vtrace("send -> undefined response", []),
+ send_status(Info, 500, none),
+ Info
+ end
+ end
+ end.
+
+
+%% traverse_modules
+
+traverse_modules(Info,[]) ->
+ {proceed,Info#mod.data};
+traverse_modules(Info,[Module|Rest]) ->
+ case (catch apply(Module,do,[Info])) of
+ {'EXIT', Reason} ->
+ ?vlog("traverse_modules -> exit reason: ~p",[Reason]),
+ String =
+ lists:flatten(
+ io_lib:format("traverse exit from apply: ~p:do => ~n~p",
+ [Module, Reason])),
+ report_error(mod_log, Info#mod.config_db, String),
+ report_error(mod_disk_log, Info#mod.config_db, String),
+ done;
+ done ->
+ done;
+ {break,NewData} ->
+ {proceed,NewData};
+ {proceed,NewData} ->
+ traverse_modules(Info#mod{data=NewData},Rest)
+ end.
+
+%% send_status %%
+
+
+send_status(#mod{socket_type = SocketType,
+ socket = Socket,
+ connection = Conn} = Info, 100, _PhraseArgs) ->
+ ?DEBUG("send_status -> StatusCode: ~p~n",[100]),
+ Header = httpd_util:header(100, Conn),
+ httpd_socket:deliver(SocketType, Socket,
+ [Header, "Content-Length:0\r\n\r\n"]);
+
+send_status(#mod{socket_type = SocketType,
+ socket = Socket,
+ config_db = ConfigDB} = Info, StatusCode, PhraseArgs) ->
+ send_status(SocketType, Socket, StatusCode, PhraseArgs, ConfigDB).
+
+send_status(SocketType, Socket, StatusCode, PhraseArgs, ConfigDB) ->
+ ?DEBUG("send_status -> ~n"
+ " StatusCode: ~p~n"
+ " PhraseArgs: ~p",
+ [StatusCode, PhraseArgs]),
+ Header = httpd_util:header(StatusCode, "text/html", false),
+ ReasonPhrase = httpd_util:reason_phrase(StatusCode),
+ Message = httpd_util:message(StatusCode, PhraseArgs, ConfigDB),
+ Body = get_body(ReasonPhrase, Message),
+ Header1 =
+ Header ++
+ "Content-Length:" ++
+ integer_to_list(length(Body)) ++
+ "\r\n\r\n",
+ httpd_socket:deliver(SocketType, Socket, [Header1, Body]).
+
+
+get_body(ReasonPhrase, Message)->
+ "<HTML>
+ <HEAD>
+ <TITLE>"++ReasonPhrase++"</TITLE>
+ </HEAD>
+ <BODY>
+ <H1>"++ReasonPhrase++"</H1>\n"++Message++"\n</BODY>
+ </HTML>\n".
+
+
+%%% Create a response from the Key/Val tuples In the Head List
+%%% Body is a tuple {body,Fun(),Args}
+
+%% send_response
+%% Allowed Fields
+
+% HTTP-Version StatusCode Reason-Phrase
+% *((general-headers
+% response-headers
+% entity-headers)CRLF)
+% CRLF
+% ?(BODY)
+
+% General Header fields
+% ======================
+% Cache-Control cache_control
+% Connection %%Is set dependiong on the request
+% Date
+% Pramga
+% Trailer
+% Transfer-Encoding
+
+% Response Header field
+% =====================
+% Accept-Ranges
+% (Age) Mostly for proxys
+% Etag
+% Location
+% (Proxy-Authenticate) Only for proxies
+% Retry-After
+% Server
+% Vary
+% WWW-Authenticate
+%
+% Entity Header Fields
+% ====================
+% Allow
+% Content-Encoding
+% Content-Language
+% Content-Length
+% Content-Location
+% Content-MD5
+% Content-Range
+% Content-Type
+% Expires
+% Last-Modified
+
+
+send_response(Info, Header, Body) ->
+ ?vtrace("send_response -> (new) entry with"
+ "~n Header: ~p", [Header]),
+ case httpd_util:key1search(Header, code) of
+ undefined ->
+ %% No status code
+ %% Ooops this must be very bad:
+ %% generate a 404 content not availible
+ send_status(Info, 404, "The file is not availible");
+ StatusCode ->
+ case send_header(Info, StatusCode, Header) of
+ ok ->
+ send_body(Info, StatusCode, Body);
+ Error ->
+ ?vlog("head delivery failure: ~p", [Error]),
+ done
+ end
+ end.
+
+
+send_header(#mod{socket_type = Type, socket = Sock,
+ http_version = Ver, connection = Conn} = Info,
+ StatusCode, Head0) ->
+ ?vtrace("send_haeder -> entry with"
+ "~n Ver: ~p"
+ "~n Conn: ~p", [Ver, Conn]),
+ Head1 = create_header(Ver, Head0),
+ StatusLine = [Ver, " ",
+ io_lib:write(StatusCode), " ",
+ httpd_util:reason_phrase(StatusCode), "\r\n"],
+ Connection = get_connection(Conn, Ver),
+ Head = list_to_binary([StatusLine, Head1, Connection,"\r\n"]),
+ ?vtrace("deliver head", []),
+ httpd_socket:deliver(Type, Sock, Head).
+
+
+send_body(_, _, nobody) ->
+ ?vtrace("send_body -> no body", []),
+ ok;
+
+send_body(#mod{socket_type = Type, socket = Sock},
+ StatusCode, Body) when list(Body) ->
+ ?vtrace("deliver body of size ~p", [length(Body)]),
+ httpd_socket:deliver(Type, Sock, Body);
+
+send_body(#mod{socket_type = Type, socket = Sock} = Info,
+ StatusCode, {Fun, Args}) ->
+ case (catch apply(Fun, Args)) of
+ close ->
+ httpd_socket:close(Type, Sock),
+ done;
+
+ sent ->
+ ?PROCEED_RESPONSE(StatusCode, Info);
+
+ {ok, Body} ->
+ ?vtrace("deliver body", []),
+ case httpd_socket:deliver(Type, Sock, Body) of
+ ok ->
+ ?PROCEED_RESPONSE(StatusCode, Info);
+ Error ->
+ ?vlog("body delivery failure: ~p", [Error]),
+ done
+ end;
+
+ Error ->
+ ?vlog("failure of apply(~p,~p): ~p", [Fun, Args, Error]),
+ done
+ end;
+send_body(I, S, B) ->
+ ?vinfo("BAD ARGS: "
+ "~n I: ~p"
+ "~n S: ~p"
+ "~n B: ~p", [I, S, B]),
+ exit({bad_args, {I, S, B}}).
+
+
+%% Return a HTTP-header field that indicates that the
+%% connection will be inpersistent
+get_connection(true,"HTTP/1.0")->
+ "Connection:close\r\n";
+get_connection(false,"HTTP/1.1") ->
+ "Connection:close\r\n";
+get_connection(_,_) ->
+ "".
+
+
+create_header("HTTP/1.1", Data) ->
+ create_header1(?HTTP11HEADERFIELDS, Data);
+create_header(_, Data) ->
+ create_header1(?HTTP10HEADERFIELDS, Data).
+
+create_header1(Fields, Data) ->
+ ?DEBUG("create_header() -> "
+ "~n Fields :~p~n Data: ~p ~n", [Fields, Data]),
+ mapfilter(fun(Field)->
+ transform({Field, httpd_util:key1search(Data, Field)})
+ end, Fields, undefined).
+
+
+%% Do a map and removes the values that evaluates to RemoveVal
+mapfilter(Fun,List,RemoveVal)->
+ mapfilter(Fun,List,[],RemoveVal).
+
+mapfilter(Fun,[],[RemoveVal|Acc],RemoveVal)->
+ Acc;
+mapfilter(Fun,[],Acc,_RemoveVal)->
+ Acc;
+
+mapfilter(Fun,[Elem|Rest],[RemoveVal|Acc],RemoveVal)->
+ mapfilter(Fun,Rest,[Fun(Elem)|Acc],RemoveVal);
+mapfilter(Fun,[Elem|Rest],Acc,RemoveVal)->
+ mapfilter(Fun,Rest,[Fun(Elem)|Acc],RemoveVal).
+
+
+transform({content_type,undefined})->
+ ["Content-Type:text/plain\r\n"];
+
+transform({date,undefined})->
+ ["Date:",httpd_util:rfc1123_date(),"\r\n"];
+
+transform({date,RFCDate})->
+ ["Date:",RFCDate,"\r\n"];
+
+
+transform({_Key,undefined})->
+ undefined;
+transform({accept_ranges,Value})->
+ ["Accept-Ranges:",Value,"\r\n"];
+transform({cache_control,Value})->
+ ["Cache-Control:",Value,"\r\n"];
+transform({pragma,Value})->
+ ["Pragma:",Value,"\r\n"];
+transform({trailer,Value})->
+ ["Trailer:",Value,"\r\n"];
+transform({transfer_encoding,Value})->
+ ["Pragma:",Value,"\r\n"];
+transform({etag,Value})->
+ ["ETag:",Value,"\r\n"];
+transform({location,Value})->
+ ["Retry-After:",Value,"\r\n"];
+transform({server,Value})->
+ ["Server:",Value,"\r\n"];
+transform({allow,Value})->
+ ["Allow:",Value,"\r\n"];
+transform({content_encoding,Value})->
+ ["Content-Encoding:",Value,"\r\n"];
+transform({content_language,Value})->
+ ["Content-Language:",Value,"\r\n"];
+transform({retry_after,Value})->
+ ["Retry-After:",Value,"\r\n"];
+transform({server,Value})->
+ ["Server:",Value,"\r\n"];
+transform({allow,Value})->
+ ["Allow:",Value,"\r\n"];
+transform({content_encoding,Value})->
+ ["Content-Encoding:",Value,"\r\n"];
+transform({content_language,Value})->
+ ["Content-Language:",Value,"\r\n"];
+transform({content_location,Value})->
+ ["Content-Location:",Value,"\r\n"];
+transform({content_length,Value})->
+ ["Content-Length:",Value,"\r\n"];
+transform({content_MD5,Value})->
+ ["Content-MD5:",Value,"\r\n"];
+transform({content_range,Value})->
+ ["Content-Range:",Value,"\r\n"];
+transform({content_type,Value})->
+ ["Content-Type:",Value,"\r\n"];
+transform({expires,Value})->
+ ["Expires:",Value,"\r\n"];
+transform({last_modified,Value})->
+ ["Last-Modified:",Value,"\r\n"].
+
+
+
+%%----------------------------------------------------------------------
+%% This is the old way of sending data it is strongly encouraged to
+%% Leave this method and go on to the newer form of response
+%% OTP-4408
+%%----------------------------------------------------------------------
+
+send_response_old(#mod{socket_type = Type,
+ socket = Sock,
+ method = "HEAD"} = Info,
+ StatusCode, Response) ->
+ ?vtrace("send_response_old(HEAD) -> entry with"
+ "~n StatusCode: ~p"
+ "~n Response: ~p",
+ [StatusCode,Response]),
+ case httpd_util:split(lists:flatten(Response),"\r\n\r\n|\n\n",2) of
+ {ok, [Head, Body]} ->
+ Header =
+ httpd_util:header(StatusCode,Info#mod.connection) ++
+ "Content-Length:" ++ content_length(Body),
+ httpd_socket:deliver(Type, Sock, [Header,Head,"\r\n"]);
+
+ Error ->
+ send_status(Info, 500, "Internal Server Error")
+ end;
+
+send_response_old(#mod{socket_type = Type,
+ socket = Sock} = Info,
+ StatusCode, Response) ->
+ ?vtrace("send_response_old -> entry with"
+ "~n StatusCode: ~p"
+ "~n Response: ~p",
+ [StatusCode,Response]),
+ case httpd_util:split(lists:flatten(Response),"\r\n\r\n|\n\n",2) of
+ {ok, [_Head, Body]} ->
+ Header =
+ httpd_util:header(StatusCode,Info#mod.connection) ++
+ "Content-Length:" ++ content_length(Body),
+ httpd_socket:deliver(Type, Sock, [Header, Response]);
+
+ {ok, Body} ->
+ Header =
+ httpd_util:header(StatusCode,Info#mod.connection) ++
+ "Content-Length:" ++ content_length(Body) ++ "\r\n",
+ httpd_socket:deliver(Type, Sock, [Header, Response]);
+
+ {error, Reason} ->
+ send_status(Info, 500, "Internal Server Error")
+ end.
+
+content_length(Body)->
+ integer_to_list(httpd_util:flatlength(Body))++"\r\n".
+
+
+report_error(Mod, ConfigDB, Error) ->
+ Modules = httpd_util:lookup(ConfigDB, modules,
+ [mod_get, mod_head, mod_log]),
+ case lists:member(Mod, Modules) of
+ true ->
+ Mod:report_error(ConfigDB, Error);
+ _ ->
+ ok
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_socket.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_socket.erl
new file mode 100644
index 0000000000..375b43784b
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_socket.erl
@@ -0,0 +1,381 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: httpd_socket.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
+%%
+-module(httpd_socket).
+-export([start/1,
+ listen/2, listen/3, accept/2, accept/3,
+ deliver/3, send/3, recv/4,
+ close/2,
+ peername/2, resolve/1, config/1,
+ controlling_process/3,
+ active_once/2]).
+
+-include("httpd.hrl").
+
+-define(VMODULE,"SOCKET").
+-include("httpd_verbosity.hrl").
+
+-include_lib("kernel/include/inet.hrl").
+
+%% start -> ok | {error,Reason}
+
+start(ip_comm) ->
+ case inet_db:start() of
+ {ok,_Pid} ->
+ ok;
+ {error,{already_started,_Pid}} ->
+ ok;
+ Error ->
+ Error
+ end;
+start({ssl,_SSLConfig}) ->
+ case ssl:start() of
+ ok ->
+ ok;
+ {ok, _} ->
+ ok;
+ {error,{already_started,_}} ->
+ ok;
+ Error ->
+ Error
+ end.
+
+%% listen
+
+listen(SocketType,Port) ->
+ listen(SocketType,undefined,Port).
+
+listen(ip_comm,Addr,Port) ->
+ ?DEBUG("listening(ip_comm) to port ~p", [Port]),
+ Opt = sock_opt(Addr,[{backlog,128},{reuseaddr,true}]),
+ case gen_tcp:listen(Port,Opt) of
+ {ok,ListenSocket} ->
+ ListenSocket;
+ Error ->
+ Error
+ end;
+listen({ssl,SSLConfig},Addr,Port) ->
+ ?DEBUG("listening(ssl) to port ~p"
+ "~n SSLConfig: ~p", [Port,SSLConfig]),
+ Opt = sock_opt(Addr,SSLConfig),
+ case ssl:listen(Port, Opt) of
+ {ok,ListenSocket} ->
+ ListenSocket;
+ Error ->
+ Error
+ end.
+
+
+sock_opt(undefined,Opt) -> [{packet,0},{active,false}|Opt];
+sock_opt(Addr,Opt) -> [{ip, Addr},{packet,0},{active,false}|Opt].
+
+%% -define(packet_type_http,true).
+%% -define(packet_type_httph,true).
+
+%% -ifdef(packet_type_http).
+%% sock_opt(undefined,Opt) -> [{packet,http},{active,false}|Opt];
+%% sock_opt(Addr,Opt) -> [{ip, Addr},{packet,http},{active,false}|Opt].
+%% -elif(packet_type_httph).
+%% sock_opt(undefined,Opt) -> [{packet,httph},{active,false}|Opt];
+%% sock_opt(Addr,Opt) -> [{ip, Addr},{packet,httph},{active,false}|Opt].
+%% -else.
+%% sock_opt(undefined,Opt) -> [{packet,0},{active,false}|Opt];
+%% sock_opt(Addr,Opt) -> [{ip, Addr},{packet,0},{active,false}|Opt].
+%% -endif.
+
+
+%% active_once
+
+active_once(Type, Sock) ->
+ active(Type, Sock, once).
+
+active(ip_comm, Sock, Active) ->
+ inet:setopts(Sock, [{active, Active}]);
+active({ssl, _SSLConfig}, Sock, Active) ->
+ ssl:setopts(Sock, [{active, Active}]).
+
+%% accept
+
+accept(A, B) ->
+ accept(A, B, infinity).
+
+
+accept(ip_comm,ListenSocket, T) ->
+ ?DEBUG("accept(ip_comm) on socket ~p", [ListenSocket]),
+ case gen_tcp:accept(ListenSocket, T) of
+ {ok,Socket} ->
+ Socket;
+ Error ->
+ ?vtrace("accept(ip_comm) failed for reason:"
+ "~n Error: ~p",[Error]),
+ Error
+ end;
+accept({ssl,_SSLConfig},ListenSocket, T) ->
+ ?DEBUG("accept(ssl) on socket ~p", [ListenSocket]),
+ case ssl:accept(ListenSocket, T) of
+ {ok,Socket} ->
+ Socket;
+ Error ->
+ ?vtrace("accept(ssl) failed for reason:"
+ "~n Error: ~p",[Error]),
+ Error
+ end.
+
+
+%% controlling_process
+
+controlling_process(ip_comm, Socket, Pid) ->
+ gen_tcp:controlling_process(Socket, Pid);
+controlling_process({ssl, _}, Socket, Pid) ->
+ ssl:controlling_process(Socket, Pid).
+
+
+%% deliver
+
+deliver(SocketType, Socket, IOListOrBinary) ->
+ case send(SocketType, Socket, IOListOrBinary) of
+% {error, einval} ->
+% ?vlog("deliver failed for reason: einval"
+% "~n SocketType: ~p"
+% "~n Socket: ~p"
+% "~n Data: ~p",
+% [SocketType, Socket, type(IOListOrBinary)]),
+% (catch close(SocketType, Socket)),
+% socket_closed;
+ {error, _Reason} ->
+ ?vlog("deliver(~p) failed for reason:"
+ "~n Reason: ~p",[SocketType,_Reason]),
+ (catch close(SocketType, Socket)),
+ socket_closed;
+ _ ->
+ ok
+ end.
+
+% type(L) when list(L) ->
+% {list, L};
+% type(B) when binary(B) ->
+% Decoded =
+% case (catch binary_to_term(B)) of
+% {'EXIT', _} ->
+% %% Oups, not a term, try list
+% case (catch binary_to_list(B)) of
+% %% Oups, not a list either, give up
+% {'EXIT', _} ->
+% {size, size(B)};
+% L ->
+% {list, L}
+% end;
+
+% T ->
+% {term, T}
+% end,
+% {binary, Decoded};
+% type(T) when tuple(T) ->
+% {tuple, T};
+% type(I) when integer(I) ->
+% {integer, I};
+% type(F) when float(F) ->
+% {float, F};
+% type(P) when pid(P) ->
+% {pid, P};
+% type(P) when port(P) ->
+% {port, P};
+% type(R) when reference(R) ->
+% {reference, R};
+% type(T) ->
+% {term, T}.
+
+
+
+send(ip_comm,Socket,Data) ->
+ ?DEBUG("send(ip_comm) -> ~p bytes on socket ~p",[data_size(Data),Socket]),
+ gen_tcp:send(Socket,Data);
+send({ssl,SSLConfig},Socket,Data) ->
+ ?DEBUG("send(ssl) -> ~p bytes on socket ~p",[data_size(Data),Socket]),
+ ssl:send(Socket, Data).
+
+recv(ip_comm,Socket,Length,Timeout) ->
+ ?DEBUG("recv(ip_comm) -> read from socket ~p",[Socket]),
+ gen_tcp:recv(Socket,Length,Timeout);
+recv({ssl,SSLConfig},Socket,Length,Timeout) ->
+ ?DEBUG("recv(ssl) -> read from socket ~p",[Socket]),
+ ssl:recv(Socket,Length,Timeout).
+
+-ifdef(inets_debug).
+data_size(L) when list(L) ->
+ httpd_util:flatlength(L);
+data_size(B) when binary(B) ->
+ size(B);
+data_size(O) ->
+ {unknown_size,O}.
+-endif.
+
+
+%% peername
+
+peername(ip_comm, Socket) ->
+ case inet:peername(Socket) of
+ {ok,{{A,B,C,D},Port}} ->
+ PeerName = integer_to_list(A)++"."++integer_to_list(B)++"."++
+ integer_to_list(C)++"."++integer_to_list(D),
+ ?DEBUG("peername(ip_comm) on socket ~p: ~p",
+ [Socket,{Port,PeerName}]),
+ {Port,PeerName};
+ {error,Reason} ->
+ ?vlog("failed getting peername:"
+ "~n Reason: ~p"
+ "~n Socket: ~p",
+ [Reason,Socket]),
+ {-1,"unknown"}
+ end;
+peername({ssl,_SSLConfig},Socket) ->
+ case ssl:peername(Socket) of
+ {ok,{{A,B,C,D},Port}} ->
+ PeerName = integer_to_list(A)++"."++integer_to_list(B)++"."++
+ integer_to_list(C)++"."++integer_to_list(D),
+ ?DEBUG("peername(ssl) on socket ~p: ~p",
+ [Socket, {Port,PeerName}]),
+ {Port,PeerName};
+ {error,_Reason} ->
+ {-1,"unknown"}
+ end.
+
+%% resolve
+
+resolve(_) ->
+ {ok,Name} = inet:gethostname(),
+ Name.
+
+%% close
+
+close(ip_comm,Socket) ->
+ Res =
+ case (catch gen_tcp:close(Socket)) of
+ ok -> ok;
+ {error,Reason} -> {error,Reason};
+ {'EXIT',{noproc,_}} -> {error,closed};
+ {'EXIT',Reason} -> {error,Reason};
+ Otherwise -> {error,Otherwise}
+ end,
+ ?vtrace("close(ip_comm) result: ~p",[Res]),
+ Res;
+close({ssl,_SSLConfig},Socket) ->
+ Res =
+ case (catch ssl:close(Socket)) of
+ ok -> ok;
+ {error,Reason} -> {error,Reason};
+ {'EXIT',{noproc,_}} -> {error,closed};
+ {'EXIT',Reason} -> {error,Reason};
+ Otherwise -> {error,Otherwise}
+ end,
+ ?vtrace("close(ssl) result: ~p",[Res]),
+ Res.
+
+%% config (debug: {certfile, "/var/tmp/server_root/conf/ssl_server.pem"})
+
+config(ConfigDB) ->
+ case httpd_util:lookup(ConfigDB,com_type,ip_comm) of
+ ssl ->
+ case ssl_certificate_file(ConfigDB) of
+ undefined ->
+ {error,
+ ?NICE("Directive SSLCertificateFile "
+ "not found in the config file")};
+ SSLCertificateFile ->
+ {ssl,
+ SSLCertificateFile++
+ ssl_certificate_key_file(ConfigDB)++
+ ssl_verify_client(ConfigDB)++
+ ssl_ciphers(ConfigDB)++
+ ssl_password(ConfigDB)++
+ ssl_verify_depth(ConfigDB)++
+ ssl_ca_certificate_file(ConfigDB)}
+ end;
+ ip_comm ->
+ ip_comm
+ end.
+
+ssl_certificate_file(ConfigDB) ->
+ case httpd_util:lookup(ConfigDB,ssl_certificate_file) of
+ undefined ->
+ undefined;
+ SSLCertificateFile ->
+ [{certfile,SSLCertificateFile}]
+ end.
+
+ssl_certificate_key_file(ConfigDB) ->
+ case httpd_util:lookup(ConfigDB,ssl_certificate_key_file) of
+ undefined ->
+ [];
+ SSLCertificateKeyFile ->
+ [{keyfile,SSLCertificateKeyFile}]
+ end.
+
+ssl_verify_client(ConfigDB) ->
+ case httpd_util:lookup(ConfigDB,ssl_verify_client) of
+ undefined ->
+ [];
+ SSLVerifyClient ->
+ [{verify,SSLVerifyClient}]
+ end.
+
+ssl_ciphers(ConfigDB) ->
+ case httpd_util:lookup(ConfigDB,ssl_ciphers) of
+ undefined ->
+ [];
+ Ciphers ->
+ [{ciphers, Ciphers}]
+ end.
+
+ssl_password(ConfigDB) ->
+ case httpd_util:lookup(ConfigDB,ssl_password_callback_module) of
+ undefined ->
+ [];
+ Module ->
+ case httpd_util:lookup(ConfigDB, ssl_password_callback_function) of
+ undefined ->
+ [];
+ Function ->
+ case catch apply(Module, Function, []) of
+ Password when list(Password) ->
+ [{password, Password}];
+ Error ->
+ error_report(ssl_password,Module,Function,Error),
+ []
+ end
+ end
+ end.
+
+ssl_verify_depth(ConfigDB) ->
+ case httpd_util:lookup(ConfigDB, ssl_verify_client_depth) of
+ undefined ->
+ [];
+ Depth ->
+ [{depth, Depth}]
+ end.
+
+ssl_ca_certificate_file(ConfigDB) ->
+ case httpd_util:lookup(ConfigDB, ssl_ca_certificate_file) of
+ undefined ->
+ [];
+ File ->
+ [{cacertfile, File}]
+ end.
+
+
+error_report(Where,M,F,Error) ->
+ error_logger:error_report([{?MODULE, Where}, {apply, {M, F, []}}, Error]).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_sup.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_sup.erl
new file mode 100644
index 0000000000..e7a3557c9d
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_sup.erl
@@ -0,0 +1,202 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: httpd_sup.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
+%%
+%%----------------------------------------------------------------------
+%% Purpose: The top supervisor for the inets application
+%%----------------------------------------------------------------------
+
+-module(httpd_sup).
+
+-behaviour(supervisor).
+
+-include("httpd_verbosity.hrl").
+
+%% public
+-export([start/2, start_link/2, start2/2, start_link2/2, stop/1, stop/2, stop2/1]).
+-export([init/1]).
+
+
+-define(D(F, A), io:format("~p:" ++ F ++ "~n", [?MODULE|A])).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% supervisor callback functions
+
+start(ConfigFile, Verbosity) ->
+ case start_link(ConfigFile, Verbosity) of
+ {ok, Pid} ->
+ unlink(Pid),
+ {ok, Pid};
+
+ Else ->
+ Else
+ end.
+
+
+start_link(ConfigFile, Verbosity) ->
+ case get_addr_and_port(ConfigFile) of
+ {ok, ConfigList, Addr, Port} ->
+ Name = make_name(Addr, Port),
+ SupName = {local, Name},
+ supervisor:start_link(SupName, ?MODULE,
+ [ConfigFile, ConfigList,
+ Verbosity, Addr, Port]);
+
+ {error, Reason} ->
+ error_logger:error_report(Reason),
+ {stop, Reason};
+
+ Else ->
+ error_logger:error_report(Else),
+ {stop, Else}
+ end.
+
+
+start2(ConfigList, Verbosity) ->
+ case start_link2(ConfigList, Verbosity) of
+ {ok, Pid} ->
+ unlink(Pid),
+ {ok, Pid};
+
+ Else ->
+ Else
+ end.
+
+
+start_link2(ConfigList, Verbosity) ->
+ case get_addr_and_port2(ConfigList) of
+ {ok, Addr, Port} ->
+ Name = make_name(Addr, Port),
+ SupName = {local, Name},
+ supervisor:start_link(SupName, ?MODULE,
+ [undefined, ConfigList, Verbosity, Addr, Port]);
+
+ {error, Reason} ->
+ error_logger:error_report(Reason),
+ {stop, Reason};
+
+ Else ->
+ error_logger:error_report(Else),
+ {stop, Else}
+ end.
+
+
+
+stop(Pid) when pid(Pid) ->
+ do_stop(Pid);
+stop(ConfigFile) when list(ConfigFile) ->
+ case get_addr_and_port(ConfigFile) of
+ {ok, _, Addr, Port} ->
+ stop(Addr, Port);
+
+ Error ->
+ Error
+ end;
+stop(StartArgs) ->
+ ok.
+
+
+stop(Addr, Port) when integer(Port) ->
+ Name = make_name(Addr, Port),
+ case whereis(Name) of
+ Pid when pid(Pid) ->
+ do_stop(Pid),
+ ok;
+ _ ->
+ not_started
+ end.
+
+stop2(ConfigList) when list(ConfigList) ->
+ {ok, Addr, Port} = get_addr_and_port2(ConfigList),
+ stop(Addr, Port).
+
+
+do_stop(Pid) ->
+ exit(Pid, shutdown).
+
+
+init([ConfigFile, ConfigList, Verbosity, Addr, Port]) ->
+ init(ConfigFile, ConfigList, Verbosity, Addr, Port);
+init(BadArg) ->
+ {error, {badarg, BadArg}}.
+
+init(ConfigFile, ConfigList, Verbosity, Addr, Port) ->
+ Flags = {one_for_one, 0, 1},
+ AccSupVerbosity = get_acc_sup_verbosity(Verbosity),
+ MiscSupVerbosity = get_misc_sup_verbosity(Verbosity),
+ Sups = [sup_spec(httpd_acceptor_sup, Addr, Port, AccSupVerbosity),
+ sup_spec(httpd_misc_sup, Addr, Port, MiscSupVerbosity),
+ worker_spec(httpd_manager, Addr, Port, ConfigFile, ConfigList,
+ Verbosity, [gen_server])],
+ {ok, {Flags, Sups}}.
+
+
+sup_spec(Name, Addr, Port, Verbosity) ->
+ {{Name, Addr, Port},
+ {Name, start, [Addr, Port, Verbosity]},
+ permanent, 2000, supervisor, [Name, supervisor]}.
+
+worker_spec(Name, Addr, Port, ConfigFile, ConfigList, Verbosity, Modules) ->
+ {{Name, Addr, Port},
+ {Name, start_link, [ConfigFile, ConfigList, Verbosity]},
+ permanent, 2000, worker, [Name] ++ Modules}.
+
+
+make_name(Addr,Port) ->
+ httpd_util:make_name("httpd_sup",Addr,Port).
+
+
+%% get_addr_and_port
+
+get_addr_and_port(ConfigFile) ->
+ case httpd_conf:load(ConfigFile) of
+ {ok, ConfigList} ->
+ {ok, Addr, Port} = get_addr_and_port2(ConfigList),
+ {ok, ConfigList, Addr, Port};
+ Error ->
+ Error
+ end.
+
+
+get_addr_and_port2(ConfigList) ->
+ Port = httpd_util:key1search(ConfigList, port, 80),
+ Addr = httpd_util:key1search(ConfigList, bind_address),
+ {ok, Addr, Port}.
+
+get_acc_sup_verbosity(V) ->
+ case key1search(V, all) of
+ undefined ->
+ key1search(V, acceptor_sup_verbosity, ?default_verbosity);
+ Verbosity ->
+ Verbosity
+ end.
+
+
+get_misc_sup_verbosity(V) ->
+ case key1search(V, all) of
+ undefined ->
+ key1search(V, misc_sup_verbosity, ?default_verbosity);
+ Verbosity ->
+ Verbosity
+ end.
+
+
+key1search(L, K) ->
+ httpd_util:key1search(L, K).
+
+key1search(L, K, D) ->
+ httpd_util:key1search(L, K, D).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_util.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_util.erl
new file mode 100644
index 0000000000..045e6f6516
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_util.erl
@@ -0,0 +1,773 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: httpd_util.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
+%%
+-module(httpd_util).
+-export([key1search/2, key1search/3, lookup/2, lookup/3, multi_lookup/2,
+ lookup_mime/2, lookup_mime/3, lookup_mime_default/2,
+ lookup_mime_default/3, reason_phrase/1, message/3, rfc1123_date/0,
+ rfc1123_date/1, day/1, month/1, decode_hex/1, decode_base64/1, encode_base64/1,
+ flatlength/1, split_path/1, split_script_path/1, suffix/1, to_upper/1,
+ to_lower/1, split/3, header/2, header/3, header/4, uniq/1,
+ make_name/2,make_name/3,make_name/4,strip/1,
+ hexlist_to_integer/1,integer_to_hexlist/1,
+ convert_request_date/1,create_etag/1,create_etag/2,getSize/1,
+ response_generated/1]).
+
+%%Since hexlist_to_integer is a lousy name make a name convert
+-export([encode_hex/1]).
+-include("httpd.hrl").
+
+%% key1search
+
+key1search(TupleList,Key) ->
+ key1search(TupleList,Key,undefined).
+
+key1search(TupleList,Key,Undefined) ->
+ case lists:keysearch(Key,1,TupleList) of
+ {value,{Key,Value}} ->
+ Value;
+ false ->
+ Undefined
+ end.
+
+%% lookup
+
+lookup(Table,Key) ->
+ lookup(Table,Key,undefined).
+
+lookup(Table,Key,Undefined) ->
+ case catch ets:lookup(Table,Key) of
+ [{Key,Value}|_] ->
+ Value;
+ _->
+ Undefined
+ end.
+
+%% multi_lookup
+
+multi_lookup(Table,Key) ->
+ remove_key(ets:lookup(Table,Key)).
+
+remove_key([]) ->
+ [];
+remove_key([{_Key,Value}|Rest]) ->
+ [Value|remove_key(Rest)].
+
+%% lookup_mime
+
+lookup_mime(ConfigDB,Suffix) ->
+ lookup_mime(ConfigDB,Suffix,undefined).
+
+lookup_mime(ConfigDB,Suffix,Undefined) ->
+ [{mime_types,MimeTypesDB}|_]=ets:lookup(ConfigDB,mime_types),
+ case ets:lookup(MimeTypesDB,Suffix) of
+ [] ->
+ Undefined;
+ [{Suffix,MimeType}|_] ->
+ MimeType
+ end.
+
+%% lookup_mime_default
+
+lookup_mime_default(ConfigDB,Suffix) ->
+ lookup_mime_default(ConfigDB,Suffix,undefined).
+
+lookup_mime_default(ConfigDB,Suffix,Undefined) ->
+ [{mime_types,MimeTypesDB}|_]=ets:lookup(ConfigDB,mime_types),
+ case ets:lookup(MimeTypesDB,Suffix) of
+ [] ->
+ case ets:lookup(ConfigDB,default_type) of
+ [] ->
+ Undefined;
+ [{default_type,DefaultType}|_] ->
+ DefaultType
+ end;
+ [{Suffix,MimeType}|_] ->
+ MimeType
+ end.
+
+%% reason_phrase
+reason_phrase(100) -> "Continue";
+reason_phrase(101) -> "Swithing protocol";
+reason_phrase(200) -> "OK";
+reason_phrase(201) -> "Created";
+reason_phrase(202) -> "Accepted";
+reason_phrase(204) -> "No Content";
+reason_phrase(205) -> "Reset Content";
+reason_phrase(206) -> "Partial Content";
+reason_phrase(301) -> "Moved Permanently";
+reason_phrase(302) -> "Moved Temporarily";
+reason_phrase(304) -> "Not Modified";
+reason_phrase(400) -> "Bad Request";
+reason_phrase(401) -> "Unauthorized";
+reason_phrase(402) -> "Payment Required";
+reason_phrase(403) -> "Forbidden";
+reason_phrase(404) -> "Not Found";
+reason_phrase(405) -> "Method Not Allowed";
+reason_phrase(408) -> "Request Timeout";
+reason_phrase(411) -> "Length Required";
+reason_phrase(414) -> "Request-URI Too Long";
+reason_phrase(412) -> "Precondition Failed";
+reason_phrase(416) -> "request Range Not Satisfiable";
+reason_phrase(417) -> "Expectation failed";
+reason_phrase(500) -> "Internal Server Error";
+reason_phrase(501) -> "Not Implemented";
+reason_phrase(502) -> "Bad Gateway";
+reason_phrase(503) -> "Service Unavailable";
+reason_phrase(_) -> "Internal Server Error".
+
+%% message
+
+message(301,URL,_) ->
+ "The document has moved <A HREF=\""++URL++"\">here</A>.";
+message(304,_URL,_) ->
+ "The document has not been changed.";
+message(400,none,_) ->
+ "Your browser sent a query that this server could not understand.";
+message(401,none,_) ->
+ "This server could not verify that you
+are authorized to access the document you
+requested. Either you supplied the wrong
+credentials (e.g., bad password), or your
+browser does not understand how to supply
+the credentials required.";
+message(403,RequestURI,_) ->
+ "You do not have permission to access "++RequestURI++" on this server.";
+message(404,RequestURI,_) ->
+ "The requested URL "++RequestURI++" was not found on this server.";
+message(412,none,_) ->
+ "The requested preconditions where false";
+message(414,ReasonPhrase,_) ->
+ "Message "++ReasonPhrase++".";
+message(416,ReasonPhrase,_) ->
+ ReasonPhrase;
+
+message(500,none,ConfigDB) ->
+ ServerAdmin=lookup(ConfigDB,server_admin,"unknown@unknown"),
+ "The server encountered an internal error or
+misconfiguration and was unable to complete
+your request.
+<P>Please contact the server administrator "++ServerAdmin++",
+and inform them of the time the error occurred
+and anything you might have done that may have
+caused the error.";
+message(501,{Method,RequestURI,HTTPVersion},_ConfigDB) ->
+ Method++" to "++RequestURI++" ("++HTTPVersion++") not supported.";
+message(503,String,_ConfigDB) ->
+ "This service in unavailable due to: "++String.
+
+%%convert_rfc_date(Date)->{{YYYY,MM,DD},{HH,MIN,SEC}}
+
+convert_request_date([D,A,Y,DateType|Rest]) ->
+ Func=case DateType of
+ $\, ->
+ fun convert_rfc1123_date/1;
+ $\ ->
+ fun convert_ascii_date/1;
+ _ ->
+ fun convert_rfc850_date/1
+ end,
+ case catch Func([D,A,Y,DateType|Rest])of
+ {ok,Date} ->
+ Date;
+ _Error ->
+ bad_date
+ end.
+
+convert_rfc850_date(DateStr) ->
+ case string:tokens(DateStr," ") of
+ [_WeekDay,Date,Time,_TimeZone|_Rest] ->
+ convert_rfc850_date(Date,Time);
+ _Error ->
+ bad_date
+ end.
+
+convert_rfc850_date([D1,D2,_,M,O,N,_,Y1,Y2|_Rest],[H1,H2,_Col,M1,M2,_Col,S1,S2|_Rest2])->
+ Year=list_to_integer([50,48,Y1,Y2]),
+ Day=list_to_integer([D1,D2]),
+ Month=convert_month([M,O,N]),
+ Hour=list_to_integer([H1,H2]),
+ Min=list_to_integer([M1,M2]),
+ Sec=list_to_integer([S1,S2]),
+ {ok,{{Year,Month,Day},{Hour,Min,Sec}}};
+convert_rfc850_date(_BadDate,_BadTime)->
+ bad_date.
+
+convert_ascii_date([_D,_A,_Y,_SP,M,O,N,_SP,D1,D2,_SP,H1,H2,_Col,M1,M2,_Col,S1,S2,_SP,Y1,Y2,Y3,Y4|_Rest])->
+ Year=list_to_integer([Y1,Y2,Y3,Y4]),
+ Day=case D1 of
+ $\ ->
+ list_to_integer([D2]);
+ _->
+ list_to_integer([D1,D2])
+ end,
+ Month=convert_month([M,O,N]),
+ Hour=list_to_integer([H1,H2]),
+ Min=list_to_integer([M1,M2]),
+ Sec=list_to_integer([S1,S2]),
+ {ok,{{Year,Month,Day},{Hour,Min,Sec}}};
+convert_ascii_date(BadDate)->
+ bad_date.
+convert_rfc1123_date([_D,_A,_Y,_C,_SP,D1,D2,_SP,M,O,N,_SP,Y1,Y2,Y3,Y4,_SP,H1,H2,_Col,M1,M2,_Col,S1,S2|Rest])->
+ Year=list_to_integer([Y1,Y2,Y3,Y4]),
+ Day=list_to_integer([D1,D2]),
+ Month=convert_month([M,O,N]),
+ Hour=list_to_integer([H1,H2]),
+ Min=list_to_integer([M1,M2]),
+ Sec=list_to_integer([S1,S2]),
+ {ok,{{Year,Month,Day},{Hour,Min,Sec}}};
+convert_rfc1123_date(BadDate)->
+ bad_date.
+
+convert_month("Jan")->1;
+convert_month("Feb") ->2;
+convert_month("Mar") ->3;
+convert_month("Apr") ->4;
+convert_month("May") ->5;
+convert_month("Jun") ->6;
+convert_month("Jul") ->7;
+convert_month("Aug") ->8;
+convert_month("Sep") ->9;
+convert_month("Oct") ->10;
+convert_month("Nov") ->11;
+convert_month("Dec") ->12.
+
+
+%% rfc1123_date
+
+rfc1123_date() ->
+ {{YYYY,MM,DD},{Hour,Min,Sec}}=calendar:universal_time(),
+ DayNumber=calendar:day_of_the_week({YYYY,MM,DD}),
+ lists:flatten(io_lib:format("~s, ~2.2.0w ~3.s ~4.4.0w ~2.2.0w:~2.2.0w:~2.2.0w GMT",
+ [day(DayNumber),DD,month(MM),YYYY,Hour,Min,Sec])).
+
+rfc1123_date({{YYYY,MM,DD},{Hour,Min,Sec}}) ->
+ DayNumber=calendar:day_of_the_week({YYYY,MM,DD}),
+ lists:flatten(io_lib:format("~s, ~2.2.0w ~3.s ~4.4.0w ~2.2.0w:~2.2.0w:~2.2.0w GMT",
+ [day(DayNumber),DD,month(MM),YYYY,Hour,Min,Sec])).
+
+%% uniq
+
+uniq([]) ->
+ [];
+uniq([First,First|Rest]) ->
+ uniq([First|Rest]);
+uniq([First|Rest]) ->
+ [First|uniq(Rest)].
+
+
+%% day
+
+day(1) -> "Mon";
+day(2) -> "Tue";
+day(3) -> "Wed";
+day(4) -> "Thu";
+day(5) -> "Fri";
+day(6) -> "Sat";
+day(7) -> "Sun".
+
+%% month
+
+month(1) -> "Jan";
+month(2) -> "Feb";
+month(3) -> "Mar";
+month(4) -> "Apr";
+month(5) -> "May";
+month(6) -> "Jun";
+month(7) -> "Jul";
+month(8) -> "Aug";
+month(9) -> "Sep";
+month(10) -> "Oct";
+month(11) -> "Nov";
+month(12) -> "Dec".
+
+%% decode_hex
+
+decode_hex([$%,Hex1,Hex2|Rest]) ->
+ [hex2dec(Hex1)*16+hex2dec(Hex2)|decode_hex(Rest)];
+decode_hex([First|Rest]) ->
+ [First|decode_hex(Rest)];
+decode_hex([]) ->
+ [].
+
+hex2dec(X) when X>=$0,X=<$9 -> X-$0;
+hex2dec(X) when X>=$A,X=<$F -> X-$A+10;
+hex2dec(X) when X>=$a,X=<$f -> X-$a+10.
+
+%% decode_base64 (DEBUG STRING: QWxhZGRpbjpvcGVuIHNlc2FtZQ==)
+
+decode_base64([]) ->
+ [];
+decode_base64([Sextet1,Sextet2,$=,$=|Rest]) ->
+ Bits2x6=
+ (d(Sextet1) bsl 18) bor
+ (d(Sextet2) bsl 12),
+ Octet1=Bits2x6 bsr 16,
+ [Octet1|decode_base64(Rest)];
+decode_base64([Sextet1,Sextet2,Sextet3,$=|Rest]) ->
+ Bits3x6=
+ (d(Sextet1) bsl 18) bor
+ (d(Sextet2) bsl 12) bor
+ (d(Sextet3) bsl 6),
+ Octet1=Bits3x6 bsr 16,
+ Octet2=(Bits3x6 bsr 8) band 16#ff,
+ [Octet1,Octet2|decode_base64(Rest)];
+decode_base64([Sextet1,Sextet2,Sextet3,Sextet4|Rest]) ->
+ Bits4x6=
+ (d(Sextet1) bsl 18) bor
+ (d(Sextet2) bsl 12) bor
+ (d(Sextet3) bsl 6) bor
+ d(Sextet4),
+ Octet1=Bits4x6 bsr 16,
+ Octet2=(Bits4x6 bsr 8) band 16#ff,
+ Octet3=Bits4x6 band 16#ff,
+ [Octet1,Octet2,Octet3|decode_base64(Rest)];
+decode_base64(CatchAll) ->
+ "BAD!".
+
+d(X) when X >= $A, X =<$Z ->
+ X-65;
+d(X) when X >= $a, X =<$z ->
+ X-71;
+d(X) when X >= $0, X =<$9 ->
+ X+4;
+d($+) -> 62;
+d($/) -> 63;
+d(_) -> 63.
+
+
+encode_base64([]) ->
+ [];
+encode_base64([A]) ->
+ [e(A bsr 2), e((A band 3) bsl 4), $=, $=];
+encode_base64([A,B]) ->
+ [e(A bsr 2), e(((A band 3) bsl 4) bor (B bsr 4)), e((B band 15) bsl 2), $=];
+encode_base64([A,B,C|Ls]) ->
+ encode_base64_do(A,B,C, Ls).
+encode_base64_do(A,B,C, Rest) ->
+ BB = (A bsl 16) bor (B bsl 8) bor C,
+ [e(BB bsr 18), e((BB bsr 12) band 63),
+ e((BB bsr 6) band 63), e(BB band 63)|encode_base64(Rest)].
+
+e(X) when X >= 0, X < 26 -> X+65;
+e(X) when X>25, X<52 -> X+71;
+e(X) when X>51, X<62 -> X-4;
+e(62) -> $+;
+e(63) -> $/;
+e(X) -> exit({bad_encode_base64_token, X}).
+
+
+%% flatlength
+
+flatlength(List) ->
+ flatlength(List, 0).
+
+flatlength([H|T],L) when list(H) ->
+ flatlength(H,flatlength(T,L));
+flatlength([H|T],L) when binary(H) ->
+ flatlength(T,L+size(H));
+flatlength([H|T],L) ->
+ flatlength(T,L+1);
+flatlength([],L) ->
+ L.
+
+%% split_path
+
+split_path(Path) ->
+ case regexp:match(Path,"[\?].*\$") of
+ %% A QUERY_STRING exists!
+ {match,Start,Length} ->
+ {httpd_util:decode_hex(string:substr(Path,1,Start-1)),
+ string:substr(Path,Start,Length)};
+ %% A possible PATH_INFO exists!
+ nomatch ->
+ split_path(Path,[])
+ end.
+
+split_path([],SoFar) ->
+ {httpd_util:decode_hex(lists:reverse(SoFar)),[]};
+split_path([$/|Rest],SoFar) ->
+ Path=httpd_util:decode_hex(lists:reverse(SoFar)),
+ case file:read_file_info(Path) of
+ {ok,FileInfo} when FileInfo#file_info.type == regular ->
+ {Path,[$/|Rest]};
+ {ok,FileInfo} ->
+ split_path(Rest,[$/|SoFar]);
+ {error,Reason} ->
+ split_path(Rest,[$/|SoFar])
+ end;
+split_path([C|Rest],SoFar) ->
+ split_path(Rest,[C|SoFar]).
+
+%% split_script_path
+
+split_script_path(Path) ->
+ case split_script_path(Path, []) of
+ {Script, AfterPath} ->
+ {PathInfo, QueryString} = pathinfo_querystring(AfterPath),
+ {Script, {PathInfo, QueryString}};
+ not_a_script ->
+ not_a_script
+ end.
+
+pathinfo_querystring(Str) ->
+ pathinfo_querystring(Str, []).
+pathinfo_querystring([], SoFar) ->
+ {lists:reverse(SoFar), []};
+pathinfo_querystring([$?|Rest], SoFar) ->
+ {lists:reverse(SoFar), Rest};
+pathinfo_querystring([C|Rest], SoFar) ->
+ pathinfo_querystring(Rest, [C|SoFar]).
+
+split_script_path([$?|QueryString], SoFar) ->
+ Path = httpd_util:decode_hex(lists:reverse(SoFar)),
+ case file:read_file_info(Path) of
+ {ok,FileInfo} when FileInfo#file_info.type == regular ->
+ {Path, [$?|QueryString]};
+ {ok,FileInfo} ->
+ not_a_script;
+ {error,Reason} ->
+ not_a_script
+ end;
+split_script_path([], SoFar) ->
+ Path = httpd_util:decode_hex(lists:reverse(SoFar)),
+ case file:read_file_info(Path) of
+ {ok,FileInfo} when FileInfo#file_info.type == regular ->
+ {Path, []};
+ {ok,FileInfo} ->
+ not_a_script;
+ {error,Reason} ->
+ not_a_script
+ end;
+split_script_path([$/|Rest], SoFar) ->
+ Path = httpd_util:decode_hex(lists:reverse(SoFar)),
+ case file:read_file_info(Path) of
+ {ok, FileInfo} when FileInfo#file_info.type == regular ->
+ {Path, [$/|Rest]};
+ {ok, _FileInfo} ->
+ split_script_path(Rest, [$/|SoFar]);
+ {error, _Reason} ->
+ split_script_path(Rest, [$/|SoFar])
+ end;
+split_script_path([C|Rest], SoFar) ->
+ split_script_path(Rest,[C|SoFar]).
+
+%% suffix
+
+suffix(Path) ->
+ case filename:extension(Path) of
+ [] ->
+ [];
+ Extension ->
+ tl(Extension)
+ end.
+
+%% to_upper
+
+to_upper([C|Cs]) when C >= $a, C =< $z ->
+ [C-($a-$A)|to_upper(Cs)];
+to_upper([C|Cs]) ->
+ [C|to_upper(Cs)];
+to_upper([]) ->
+ [].
+
+%% to_lower
+
+to_lower([C|Cs]) when C >= $A, C =< $Z ->
+ [C+($a-$A)|to_lower(Cs)];
+to_lower([C|Cs]) ->
+ [C|to_lower(Cs)];
+to_lower([]) ->
+ [].
+
+
+%% strip
+strip(Value)->
+ lists:reverse(remove_ws(lists:reverse(remove_ws(Value)))).
+
+remove_ws([$\s|Rest])->
+ remove_ws(Rest);
+remove_ws([$\t|Rest]) ->
+ remove_ws(Rest);
+remove_ws(Rest) ->
+ Rest.
+
+%% split
+
+split(String,RegExp,Limit) ->
+ case regexp:parse(RegExp) of
+ {error,Reason} ->
+ {error,Reason};
+ {ok,_} ->
+ {ok,do_split(String,RegExp,Limit)}
+ end.
+
+do_split(String,RegExp,1) ->
+ [String];
+
+do_split(String,RegExp,Limit) ->
+ case regexp:first_match(String,RegExp) of
+ {match,Start,Length} ->
+ [string:substr(String,1,Start-1)|
+ do_split(lists:nthtail(Start+Length-1,String),RegExp,Limit-1)];
+ nomatch ->
+ [String]
+ end.
+
+%% header
+header(StatusCode,Date)when list(Date)->
+ header(StatusCode,"text/plain",false);
+
+header(StatusCode, PersistentConnection) when integer(StatusCode)->
+ Date = rfc1123_date(),
+ Connection =
+ case PersistentConnection of
+ true ->
+ "";
+ _ ->
+ "Connection: close \r\n"
+ end,
+ io_lib:format("HTTP/1.1 ~w ~s \r\nDate: ~s\r\nServer: ~s\r\n~s",
+ [StatusCode, httpd_util:reason_phrase(StatusCode),
+ Date, ?SERVER_SOFTWARE, Connection]).
+
+%%----------------------------------------------------------------------
+
+header(StatusCode, MimeType, Date) when list(Date) ->
+ header(StatusCode, MimeType, false,rfc1123_date());
+
+
+header(StatusCode, MimeType, PersistentConnection) when integer(StatusCode) ->
+ header(StatusCode, MimeType, PersistentConnection,rfc1123_date()).
+
+
+%%----------------------------------------------------------------------
+
+header(416, MimeType,PersistentConnection,Date)->
+ Connection =
+ case PersistentConnection of
+ true ->
+ "";
+ _ ->
+ "Connection: close \r\n"
+ end,
+ io_lib:format("HTTP/1.1 ~w ~s \r\nDate: ~s\r\nServer: ~s\r\n"
+ "Content-Range:bytes *"
+ "Content-Type: ~s\r\n~s",
+ [416, httpd_util:reason_phrase(416),
+ Date, ?SERVER_SOFTWARE, MimeType, Connection]);
+
+
+header(StatusCode, MimeType,PersistentConnection,Date) when integer(StatusCode)->
+ Connection =
+ case PersistentConnection of
+ true ->
+ "";
+ _ ->
+ "Connection: close \r\n"
+ end,
+ io_lib:format("HTTP/1.1 ~w ~s \r\nDate: ~s\r\nServer: ~s\r\n"
+ "Content-Type: ~s\r\n~s",
+ [StatusCode, httpd_util:reason_phrase(StatusCode),
+ Date, ?SERVER_SOFTWARE, MimeType, Connection]).
+
+
+
+%% make_name/2, make_name/3
+%% Prefix -> string()
+%% First part of the name, e.g. "httpd"
+%% Addr -> {A,B,C,D} | string() | undefined
+%% The address part of the name.
+%% e.g. "123.234.55.66" or {123,234,55,66} or "otp.ericsson.se"
+%% for a host address or undefined if local host.
+%% Port -> integer()
+%% Last part of the name, such as the HTTPD server port
+%% number (80).
+%% Postfix -> Any string that will be added last to the name
+%%
+%% Example:
+%% make_name("httpd","otp.ericsson.se",80) => httpd__otp_ericsson_se__80
+%% make_name("httpd",undefined,8088) => httpd_8088
+
+make_name(Prefix,Port) ->
+ make_name(Prefix,undefined,Port,"").
+
+make_name(Prefix,Addr,Port) ->
+ make_name(Prefix,Addr,Port,"").
+
+make_name(Prefix,"*",Port,Postfix) ->
+ make_name(Prefix,undefined,Port,Postfix);
+
+make_name(Prefix,any,Port,Postfix) ->
+ make_name1(io_lib:format("~s_~w~s",[Prefix,Port,Postfix]));
+
+make_name(Prefix,undefined,Port,Postfix) ->
+ make_name1(io_lib:format("~s_~w~s",[Prefix,Port,Postfix]));
+
+make_name(Prefix,Addr,Port,Postfix) ->
+ NameString =
+ Prefix ++ "__" ++ make_name2(Addr) ++ "__" ++
+ integer_to_list(Port) ++ Postfix,
+ make_name1(NameString).
+
+make_name1(String) ->
+ list_to_atom(lists:flatten(String)).
+
+make_name2({A,B,C,D}) ->
+ io_lib:format("~w_~w_~w_~w",[A,B,C,D]);
+make_name2(Addr) ->
+ search_and_replace(Addr,$.,$_).
+
+search_and_replace(S,A,B) ->
+ Fun = fun(What) ->
+ case What of
+ A -> B;
+ O -> O
+ end
+ end,
+ lists:map(Fun,S).
+
+
+
+%%----------------------------------------------------------------------
+%% Converts a string that constists of 0-9,A-F,a-f to a
+%% integer
+%%----------------------------------------------------------------------
+
+hexlist_to_integer([])->
+ empty;
+
+
+%%When the string only contains one value its eaasy done.
+%% 0-9
+hexlist_to_integer([Size]) when Size>=48 , Size=<57 ->
+ Size-48;
+%% A-F
+hexlist_to_integer([Size]) when Size>=65 , Size=<70 ->
+ Size-55;
+%% a-f
+hexlist_to_integer([Size]) when Size>=97 , Size=<102 ->
+ Size-87;
+hexlist_to_integer([Size]) ->
+ not_a_num;
+
+hexlist_to_integer(Size) ->
+ Len=string:span(Size,"1234567890abcdefABCDEF"),
+ hexlist_to_integer2(Size,16 bsl (4 *(Len-2)),0).
+
+hexlist_to_integer2([],_Pos,Sum)->
+ Sum;
+hexlist_to_integer2([HexVal|HexString],Pos,Sum)when HexVal>=48,HexVal=<57->
+ hexlist_to_integer2(HexString,Pos bsr 4,Sum+((HexVal-48)*Pos));
+
+hexlist_to_integer2([HexVal|HexString],Pos,Sum)when HexVal>=65,HexVal=<70->
+ hexlist_to_integer2(HexString,Pos bsr 4,Sum+((HexVal-55)*Pos));
+
+hexlist_to_integer2([HexVal|HexString],Pos,Sum)when HexVal>=97,HexVal=<102->
+ hexlist_to_integer2(HexString,Pos bsr 4,Sum+((HexVal-87)*Pos));
+
+hexlist_to_integer2(_AfterHexString,_Pos,Sum)->
+ Sum.
+
+%%----------------------------------------------------------------------
+%%Converts an integer to an hexlist
+%%----------------------------------------------------------------------
+encode_hex(Num)->
+ integer_to_hexlist(Num).
+
+
+integer_to_hexlist(Num)->
+ integer_to_hexlist(Num,getSize(Num),[]).
+
+integer_to_hexlist(Num,Pot,Res) when Pot<0 ->
+ convert_to_ascii([Num|Res]);
+
+integer_to_hexlist(Num,Pot,Res) ->
+ Position=(16 bsl (Pot*4)),
+ PosVal=Num div Position,
+ integer_to_hexlist(Num-(PosVal*Position),Pot-1,[PosVal|Res]).
+convert_to_ascii(RevesedNum)->
+ convert_to_ascii(RevesedNum,[]).
+
+convert_to_ascii([],Num)->
+ Num;
+convert_to_ascii([Num|Reversed],Number)when Num>-1, Num<10 ->
+ convert_to_ascii(Reversed,[Num+48|Number]);
+convert_to_ascii([Num|Reversed],Number)when Num>9, Num<16 ->
+ convert_to_ascii(Reversed,[Num+55|Number]);
+convert_to_ascii(NumReversed,Number) ->
+ error.
+
+
+
+getSize(Num)->
+ getSize(Num,0).
+
+getSize(Num,Pot)when Num<(16 bsl(Pot *4)) ->
+ Pot-1;
+
+getSize(Num,Pot) ->
+ getSize(Num,Pot+1).
+
+
+
+
+
+create_etag(FileInfo)->
+ create_etag(FileInfo#file_info.mtime,FileInfo#file_info.size).
+
+create_etag({{Year,Month,Day},{Hour,Min,Sec}},Size)->
+ create_part([Year,Month,Day,Hour,Min,Sec])++io_lib:write(Size);
+
+create_etag(FileInfo,Size)->
+ create_etag(FileInfo#file_info.mtime,Size).
+
+create_part(Values)->
+ lists:map(fun(Val0)->
+ Val=Val0 rem 60,
+ if
+ Val=<25 ->
+ 65+Val; % A-Z
+ Val=<50 ->
+ 72+Val; % a-z
+ %%Since no date s
+ true ->
+ Val-3
+ end
+ end,Values).
+
+
+
+%%----------------------------------------------------------------------
+%%Function that controls whether a response is generated or not
+%%----------------------------------------------------------------------
+response_generated(Info)->
+ case httpd_util:key1search(Info#mod.data,status) of
+ %% A status code has been generated!
+ {StatusCode,PhraseArgs,Reason}->
+ true;
+ %%No status code control repsonsxe
+ undefined ->
+ case httpd_util:key1search(Info#mod.data, response) of
+ %% No response has been generated!
+ undefined ->
+ false;
+ %% A response has been generated or sent!
+ Response ->
+ true
+ end
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_verbosity.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_verbosity.erl
new file mode 100644
index 0000000000..f676eb4c99
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_verbosity.erl
@@ -0,0 +1,93 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: httpd_verbosity.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
+%%
+-module(httpd_verbosity).
+
+-include_lib("stdlib/include/erl_compile.hrl").
+
+-export([print/4,print/5,printc/4,validate/1]).
+
+print(silence,_Severity,_Format,_Arguments) ->
+ ok;
+print(Verbosity,Severity,Format,Arguments) ->
+ print1(printable(Verbosity,Severity),Format,Arguments).
+
+
+print(silence,_Severity,_Module,_Format,_Arguments) ->
+ ok;
+print(Verbosity,Severity,Module,Format,Arguments) ->
+ print1(printable(Verbosity,Severity),Module,Format,Arguments).
+
+
+printc(silence,Severity,Format,Arguments) ->
+ ok;
+printc(Verbosity,Severity,Format,Arguments) ->
+ print2(printable(Verbosity,Severity),Format,Arguments).
+
+
+print1(false,_Format,_Arguments) -> ok;
+print1(Verbosity,Format,Arguments) ->
+ V = image_of_verbosity(Verbosity),
+ S = image_of_sname(get(sname)),
+ io:format("** HTTPD ~s ~s: " ++ Format ++ "~n",[S,V]++Arguments).
+
+print1(false,_Module,_Format,_Arguments) -> ok;
+print1(Verbosity,Module,Format,Arguments) ->
+ V = image_of_verbosity(Verbosity),
+ S = image_of_sname(get(sname)),
+ io:format("** HTTPD ~s ~s ~s: " ++ Format ++ "~n",[S,Module,V]++Arguments).
+
+
+print2(false,_Format,_Arguments) -> ok;
+print2(_Verbosity,Format,Arguments) ->
+ io:format(Format ++ "~n",Arguments).
+
+
+%% printable(Verbosity,Severity)
+printable(info,info) -> info;
+printable(log,info) -> info;
+printable(log,log) -> log;
+printable(debug,info) -> info;
+printable(debug,log) -> log;
+printable(debug,debug) -> debug;
+printable(trace,V) -> V;
+printable(_Verb,_Sev) -> false.
+
+
+image_of_verbosity(info) -> "INFO";
+image_of_verbosity(log) -> "LOG";
+image_of_verbosity(debug) -> "DEBUG";
+image_of_verbosity(trace) -> "TRACE";
+image_of_verbosity(_) -> "".
+
+%% ShortName
+image_of_sname(acc) -> "ACCEPTOR";
+image_of_sname(acc_sup) -> "ACCEPTOR_SUP";
+image_of_sname(auth) -> "AUTH";
+image_of_sname(man) -> "MANAGER";
+image_of_sname(misc_sup) -> "MISC_SUP";
+image_of_sname(sec) -> "SECURITY";
+image_of_sname(P) when pid(P) -> io_lib:format("REQUEST_HANDLER(~p)",[P]);
+image_of_sname(undefined) -> "";
+image_of_sname(V) -> io_lib:format("~p",[V]).
+
+
+validate(info) -> info;
+validate(log) -> log;
+validate(debug) -> debug;
+validate(trace) -> trace;
+validate(_) -> silence.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_verbosity.hrl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_verbosity.hrl
new file mode 100644
index 0000000000..cecaf693d3
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_verbosity.hrl
@@ -0,0 +1,62 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: httpd_verbosity.hrl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
+%%
+
+-ifndef(dont_use_verbosity).
+
+-ifndef(default_verbosity).
+-define(default_verbosity,silence).
+-endif.
+
+-define(vvalidate(V), httpd_verbosity:validate(V)).
+
+-ifdef(VMODULE).
+
+-define(vinfo(F,A), httpd_verbosity:print(get(verbosity),info, ?VMODULE,F,A)).
+-define(vlog(F,A), httpd_verbosity:print(get(verbosity),log, ?VMODULE,F,A)).
+-define(vdebug(F,A),httpd_verbosity:print(get(verbosity),debug,?VMODULE,F,A)).
+-define(vtrace(F,A),httpd_verbosity:print(get(verbosity),trace,?VMODULE,F,A)).
+
+-else.
+
+-define(vinfo(F,A), httpd_verbosity:print(get(verbosity),info, F,A)).
+-define(vlog(F,A), httpd_verbosity:print(get(verbosity),log, F,A)).
+-define(vdebug(F,A),httpd_verbosity:print(get(verbosity),debug,F,A)).
+-define(vtrace(F,A),httpd_verbosity:print(get(verbosity),trace,F,A)).
+
+-endif.
+
+-define(vinfoc(F,A), httpd_verbosity:printc(get(verbosity),info, F,A)).
+-define(vlogc(F,A), httpd_verbosity:printc(get(verbosity),log, F,A)).
+-define(vdebugc(F,A),httpd_verbosity:printc(get(verbosity),debug,F,A)).
+-define(vtracec(F,A),httpd_verbosity:printc(get(verbosity),trace,F,A)).
+
+-else.
+
+-define(vvalidate(V),ok).
+
+-define(vinfo(F,A),ok).
+-define(vlog(F,A),ok).
+-define(vdebug(F,A),ok).
+-define(vtrace(F,A),ok).
+
+-define(vinfoc(F,A),ok).
+-define(vlogc(F,A),ok).
+-define(vdebugc(F,A),ok).
+-define(vtracec(F,A),ok).
+
+-endif.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/inets.app.src b/lib/dialyzer/test/r9c_SUITE_data/src/inets/inets.app.src
new file mode 100644
index 0000000000..750dbc6dba
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/inets.app.src
@@ -0,0 +1,56 @@
+{application,inets,
+ [{description,"INETS CXC 138 49"},
+ {vsn,"%VSN%"},
+ {modules,[
+ %% FTP
+ ftp,
+
+ %% HTTP client:
+ http,
+ http_lib,
+ httpc_handler,
+ httpc_manager,
+ uri,
+
+ %% HTTP server:
+ httpd,
+ httpd_acceptor,
+ httpd_acceptor_sup,
+ httpd_conf,
+ httpd_example,
+ httpd_manager,
+ httpd_misc_sup,
+ httpd_parse,
+ httpd_request_handler,
+ httpd_response,
+ httpd_socket,
+ httpd_sup,
+ httpd_util,
+ httpd_verbosity,
+ inets_sup,
+ mod_actions,
+ mod_alias,
+ mod_auth,
+ mod_auth_dets,
+ mod_auth_mnesia,
+ mod_auth_plain,
+ mod_auth_server,
+ mod_browser,
+ mod_cgi,
+ mod_dir,
+ mod_disk_log,
+ mod_esi,
+ mod_get,
+ mod_head,
+ mod_htaccess,
+ mod_include,
+ mod_log,
+ mod_range,
+ mod_responsecontrol,
+ mod_security,
+ mod_security_server,
+ mod_trace
+ ]},
+ {registered,[inets_sup]},
+ {applications,[kernel,stdlib]},
+ {mod,{inets_sup,[]}}]}.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/inets.appup.src b/lib/dialyzer/test/r9c_SUITE_data/src/inets/inets.appup.src
new file mode 100644
index 0000000000..e9ad0d0fe2
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/inets.appup.src
@@ -0,0 +1,133 @@
+{"%VSN%",
+ [{"3.0.5",
+ [
+ {load_module, ftp, soft_purge, soft_purge, []}
+ ]
+ },
+ {"3.0.4",
+ [
+ {update, httpd_acceptor, soft, soft_purge, soft_purge, []}
+ ]
+ },
+ {"3.0.3",
+ [{load_module, httpd, soft_purge, soft_purge, [httpd_conf, httpd_sup]},
+ {load_module, httpd_conf, soft_purge, soft_purge, []},
+ {load_module, httpd_socket, soft_purge, soft_purge, []},
+ {load_module, httpd_response, soft_purge, soft_purge, [mod_disk_log]},
+ {load_module, mod_disk_log, soft_purge, soft_purge, []},
+ {update, httpd_acceptor, soft, soft_purge, soft_purge, []},
+ {update, httpd_sup, soft, soft_purge, soft_purge, [httpd_manager]},
+ {update, httpd_manager, soft, soft_purge, soft_purge,
+ [mod_disk_log, httpd_conf, httpd_socket]}]
+ },
+ {"3.0.2",
+ [{load_module, httpd, soft_purge, soft_purge, [httpd_conf, httpd_sup]},
+ {load_module, httpd_conf, soft_purge, soft_purge, []},
+ {load_module, httpd_socket, soft_purge, soft_purge, []},
+ {load_module, mod_disk_log, soft_purge, soft_purge, []},
+ {load_module, httpd_response, soft_purge, soft_purge, [mod_disk_log]},
+ {update, httpd_sup, soft, soft_purge, soft_purge, [httpd_manager]},
+ {update, httpd_acceptor, soft, soft_purge, soft_purge, []},
+ {update, httpd_manager, soft, soft_purge, soft_purge,
+ [httpd_request_handler, httpd_conf, httpd_socket]},
+ {update, httpd_request_handler, soft, soft_purge, soft_purge,
+ [httpd_response]}]
+ },
+ {"3.0.1",
+ [{load_module, httpd, soft_purge, soft_purge, [httpd_conf, httpd_sup]},
+ {load_module, httpd_conf, soft_purge, soft_purge, []},
+ {load_module, httpd_socket, soft_purge, soft_purge, []},
+ {load_module, httpd_response, soft_purge, soft_purge,
+ [mod_auth, mod_disk_log]},
+ {load_module, mod_disk_log, soft_purge, soft_purge, []},
+ {load_module, mod_auth, soft_purge, soft_purge, []},
+ {update, httpd_sup, soft, soft_purge, soft_purge, [httpd_manager]},
+ {update, httpd_acceptor, soft, soft_purge, soft_purge, []},
+ {update, httpd_manager, soft, soft_purge, soft_purge,
+ [httpd_request_handler, httpd_conf, httpd_socket]},
+ {update, httpd_request_handler, soft, soft_purge, soft_purge,
+ [httpd_response]}]
+ },
+ {"3.0",
+ [{load_module, httpd, soft_purge, soft_purge, [httpd_conf, httpd_sup]},
+ {load_module, httpd_conf, soft_purge, soft_purge, []},
+ {load_module, httpd_socket, soft_purge, soft_purge, []},
+ {load_module, httpd_response, soft_purge, soft_purge,
+ [mod_auth, mod_disk_log]},
+ {load_module, mod_disk_log, soft_purge, soft_purge, []},
+ {load_module, mod_auth, soft_purge, soft_purge, []},
+ {update, httpd_sup, soft, soft_purge, soft_purge,
+ [httpd_manager, httpd_misc_sup]},
+ {update, httpd_misc_sup, soft, soft_purge, soft_purge, []},
+ {update, httpd_acceptor, soft, soft_purge, soft_purge, []},
+ {update, httpd_manager, soft, soft_purge, soft_purge,
+ [httpd_request_handler, httpd_conf, httpd_socket]},
+ {update, httpd_request_handler, soft, soft_purge, soft_purge,
+ [httpd_response]}]
+ }
+ ],
+ [{"3.0.5",
+ [
+ {load_module, ftp, soft_purge, soft_purge, []}
+ ]
+ },
+ {"3.0.4",
+ [{update, httpd_acceptor, soft, soft_purge, soft_purge, []}]
+ },
+ {"3.0.3",
+ [{load_module, httpd, soft_purge, soft_purge, [httpd_conf, httpd_sup]},
+ {load_module, httpd_conf, soft_purge, soft_purge, []},
+ {load_module, httpd_socket, soft_purge, soft_purge, []},
+ {load_module, httpd_response, soft_purge, soft_purge, [mod_disk_log]},
+ {load_module, mod_disk_log, soft_purge, soft_purge, []},
+ {update, httpd_sup, soft, soft_purge, soft_purge, [httpd_manager]},
+ {update, httpd_manager, soft, soft_purge, soft_purge,
+ [mod_disk_log, httpd_conf, httpd_socket]}]
+ },
+ {"3.0.2",
+ [{load_module, httpd, soft_purge, soft_purge, [httpd_conf, httpd_sup]},
+ {load_module, httpd_conf, soft_purge, soft_purge, []},
+ {load_module, httpd_socket, soft_purge, soft_purge, []},
+ {load_module, httpd_response, soft_purge, soft_purge, [mod_disk_log]},
+ {load_module, mod_disk_log, soft_purge, soft_purge, []},
+ {update, httpd_sup, soft, soft_purge, soft_purge, [httpd_manager]},
+ {update, httpd_acceptor, soft, soft_purge, soft_purge, []},
+ {update, httpd_manager, soft, soft_purge, soft_purge,
+ [httpd_request_handler, httpd_conf, httpd_socket]},
+ {update, httpd_request_handler, soft, soft_purge, soft_purge,
+ [httpd_response]}]
+ },
+ {"3.0.1",
+ [{load_module, httpd, soft_purge, soft_purge, [httpd_conf, httpd_sup]},
+ {load_module, httpd_conf, soft_purge, soft_purge, []},
+ {load_module, httpd_socket, soft_purge, soft_purge, []},
+ {load_module, httpd_response, soft_purge, soft_purge,
+ [mod_auth, mod_disk_log]},
+ {load_module, mod_disk_log, soft_purge, soft_purge, []},
+ {load_module, mod_auth, soft_purge, soft_purge, []},
+ {update, httpd_sup, soft, soft_purge, soft_purge, [httpd_manager]},
+ {update, httpd_acceptor, soft, soft_purge, soft_purge, []},
+ {update, httpd_manager, soft, soft_purge, soft_purge,
+ [httpd_request_handler, httpd_conf, httpd_socket]},
+ {update, httpd_request_handler, soft, soft_purge, soft_purge,
+ [httpd_response]}]
+ },
+ {"3.0",
+ [{load_module, httpd, soft_purge, soft_purge, [httpd_conf, httpd_sup]},
+ {load_module, httpd_conf, soft_purge, soft_purge, []},
+ {load_module, httpd_socket, soft_purge, soft_purge, []},
+ {load_module, httpd_response, soft_purge, soft_purge,
+ [mod_auth, mod_disk_log]},
+ {load_module, mod_disk_log, soft_purge, soft_purge, []},
+ {load_module, mod_auth, soft_purge, soft_purge, []},
+ {update, httpd_sup, soft, soft_purge, soft_purge,
+ [httpd_manager, httpd_misc_sup]},
+ {update, httpd_misc_sup, soft, soft_purge, soft_purge, []},
+ {update, httpd_acceptor, soft, soft_purge, soft_purge, []},
+ {update, httpd_manager, soft, soft_purge, soft_purge,
+ [httpd_request_handler, httpd_conf, httpd_socket]},
+ {update, httpd_request_handler, soft, soft_purge, soft_purge,
+ [httpd_response]}]
+ }
+ ]
+}.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/inets.config b/lib/dialyzer/test/r9c_SUITE_data/src/inets/inets.config
new file mode 100644
index 0000000000..814ddd9fc0
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/inets.config
@@ -0,0 +1,2 @@
+[{inets,[{services,[{httpd,"/var/tmp/server_root/conf/8888.conf"},
+ {httpd,"/var/tmp/server_root/conf/8080.conf"}]}]}].
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/inets_sup.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/inets_sup.erl
new file mode 100644
index 0000000000..878fa2c54b
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/inets_sup.erl
@@ -0,0 +1,158 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: inets_sup.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
+%%
+-module(inets_sup).
+
+-export([crock/0]).
+-export([start/2, stop/1, init/1]).
+-export([start_child/2, stop_child/2, which_children/0]).
+
+
+%% crock (Used for debugging!)
+
+crock() ->
+ application:start(sasl),
+ application:start(inets).
+
+
+%% start
+
+start(Type, State) ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+
+%% stop
+
+stop(State) ->
+ ok.
+
+
+%% start_child
+
+start_child(ConfigFile, Verbosity) ->
+ {ok, Spec} = httpd_child_spec(ConfigFile, Verbosity),
+ supervisor:start_child(?MODULE, Spec).
+
+
+%% stop_child
+
+stop_child(Addr, Port) ->
+ Name = {httpd_sup, Addr, Port},
+ case supervisor:terminate_child(?MODULE, Name) of
+ ok ->
+ supervisor:delete_child(?MODULE, Name);
+ Error ->
+ Error
+ end.
+
+
+%% which_children
+
+which_children() ->
+ supervisor:which_children(?MODULE).
+
+
+%% init
+
+init([]) ->
+ case get_services() of
+ {error, Reason} ->
+ {error,Reason};
+ Services ->
+ SupFlags = {one_for_one, 10, 3600},
+ {ok, {SupFlags, child_spec(Services, [])}}
+ end.
+
+get_services() ->
+ case (catch application:get_env(inets, services)) of
+ {ok, Services} ->
+ Services;
+ _ ->
+ []
+ end.
+
+
+child_spec([], Acc) ->
+ Acc;
+child_spec([{httpd, ConfigFile, Verbosity}|Rest], Acc) ->
+ case httpd_child_spec(ConfigFile, Verbosity) of
+ {ok, Spec} ->
+ child_spec(Rest, [Spec | Acc]);
+ {error, Reason} ->
+ error_msg("Failed creating child spec "
+ "using ~p for reason: ~p", [ConfigFile, Reason]),
+ child_spec(Rest, Acc)
+ end;
+child_spec([{httpd, ConfigFile}|Rest], Acc) ->
+ case httpd_child_spec(ConfigFile, []) of
+ {ok, Spec} ->
+ child_spec(Rest, [Spec | Acc]);
+ {error, Reason} ->
+ error_msg("Failed creating child spec "
+ "using ~p for reason: ~p", [ConfigFile, Reason]),
+ child_spec(Rest, Acc)
+ end.
+
+
+httpd_child_spec(ConfigFile, Verbosity) ->
+ case httpd_conf:load(ConfigFile) of
+ {ok, ConfigList} ->
+ Port = httpd_util:key1search(ConfigList, port, 80),
+ Addr = httpd_util:key1search(ConfigList, bind_address),
+ {ok, httpd_child_spec(ConfigFile, Addr, Port, Verbosity)};
+ Error ->
+ Error
+ end.
+
+
+httpd_child_spec(ConfigFile, Addr, Port, Verbosity) ->
+ {{httpd_sup, Addr, Port},{httpd_sup, start_link,[ConfigFile, Verbosity]},
+ permanent, 20000, supervisor,
+ [ftp,
+ httpd,
+ httpd_conf,
+ httpd_example,
+ httpd_manager,
+ httpd_misc_sup,
+ httpd_listener,
+ httpd_parse,
+ httpd_request,
+ httpd_response,
+ httpd_socket,
+ httpd_sup,
+ httpd_util,
+ httpd_verbosity,
+ inets_sup,
+ mod_actions,
+ mod_alias,
+ mod_auth,
+ mod_cgi,
+ mod_dir,
+ mod_disk_log,
+ mod_esi,
+ mod_get,
+ mod_head,
+ mod_include,
+ mod_log,
+ mod_auth_mnesia,
+ mod_auth_plain,
+ mod_auth_dets,
+ mod_security]}.
+
+
+error_msg(F, A) ->
+ error_logger:error_msg(F ++ "~n", A).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/jnets_httpd.hrl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/jnets_httpd.hrl
new file mode 100644
index 0000000000..0a96560c92
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/jnets_httpd.hrl
@@ -0,0 +1,138 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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 Mobile Arts AB
+%% Portions created by Mobile Arts are Copyright 2002, Mobile Arts AB
+%% All Rights Reserved.''
+%%
+%%
+
+-include_lib("kernel/include/file.hrl").
+
+-define(SOCKET_CHUNK_SIZE,8192).
+-define(SOCKET_MAX_POLL,25).
+-define(FILE_CHUNK_SIZE,64*1024).
+-define(NICE(Reason),lists:flatten(atom_to_list(?MODULE)++": "++Reason)).
+-define(DEFAULT_CONTEXT,
+ [{errmsg,"[an error occurred while processing this directive]"},
+ {timefmt,"%A, %d-%b-%y %T %Z"},
+ {sizefmt,"abbrev"}]).
+
+
+-ifdef(inets_debug).
+-define(DEBUG(Format, Args), io:format("D(~p:~p:~p) : "++Format++"~n",
+ [self(),?MODULE,?LINE]++Args)).
+-else.
+-define(DEBUG(F,A),[]).
+-endif.
+
+-define(MAXBODYSIZE,16#ffffffff).
+
+-define(HTTP_VERSION_10,0).
+-define(HTTP_VERSION_11,1).
+
+-define(CR,13).
+-define(LF,10).
+
+
+-record(init_data,{peername,resolve}).
+
+
+-record(mod,{
+ init_data, %
+ data= [], % list() Used to propagate data between modules
+ socket_type=ip_comm, % socket_type() IP or SSL socket
+ socket, % socket() Actual socket
+ config_db, % ets() {key,val} db with config entries
+ method, % atom() HTTP method, e.g. 'GET'
+% request_uri, % string() Request URI
+ path, % string() Absolute path. May include query etc
+ http_version, % int() HTTP minor version number, e.g. 0 or 1
+% request_line, % string() Request Line
+ headers, % #req_headers{} Parsed request headers
+ entity_body= <<>>, % binary() Body of request
+ connection, % boolean() true if persistant connection
+ status_code, % int() Status code
+ logging % int() 0=No logging
+ % 1=Only mod_log present
+ % 2=Only mod_disk_log present
+ % 3=Both mod_log and mod_disk_log present
+ }).
+
+% -record(ssl,{
+% certfile, %
+% keyfile, %
+% verify= 0, %
+% ciphers, %
+% password, %
+% depth = 1, %
+% cacertfile, %
+
+% cachetimeout % Found in yaws....
+% }).
+
+
+-record(http_request,{
+ method, % atom() if known else string() HTTP methd
+ path, % {abs_path,string()} URL path
+ version % {int(),int()} {Major,Minor} HTTP version
+ }).
+
+-record(http_response,{
+ version, % {int(),int()} {Major,Minor} HTTP version
+ status, % int() Status code
+ phrase % string() HTTP Reason phrase
+ }).
+
+
+%%% Request headers
+-record(req_headers,{
+%%% --- Standard "General" headers
+% cache_control,
+ connection="keep-alive",
+% date,
+% pragma,
+% trailer,
+ transfer_encoding,
+% upgrade,
+% via,
+% warning,
+%%% --- Standard "Request" headers
+% accept,
+% accept_charset,
+% accept_encoding,
+% accept_language,
+ authorization,
+ expect, %% FIXME! Update inet_drv.c!!
+% from,
+ host,
+ if_match,
+ if_modified_since,
+ if_none_match,
+ if_range,
+ if_unmodified_since,
+% max_forwards,
+% proxy_authorization,
+ range,
+% referer,
+% te, %% FIXME! Update inet_drv.c!!
+ user_agent,
+%%% --- Standard "Entity" headers
+% content_encoding,
+% content_language,
+ content_length="0",
+% content_location,
+% content_md5,
+% content_range,
+ content_type,
+% last_modified,
+ other=[] % (list) Key/Value list with other headers
+ }).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_actions.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_actions.erl
new file mode 100644
index 0000000000..47395d4c12
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_actions.erl
@@ -0,0 +1,92 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_actions.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
+%%
+-module(mod_actions).
+-export([do/1,load/2]).
+
+-include("httpd.hrl").
+
+%% do
+
+do(Info) ->
+ case httpd_util:key1search(Info#mod.data,status) of
+ %% A status code has been generated!
+ {StatusCode,PhraseArgs,Reason} ->
+ {proceed,Info#mod.data};
+ %% No status code has been generated!
+ undefined ->
+ case httpd_util:key1search(Info#mod.data,response) of
+ %% No response has been generated!
+ undefined ->
+ Path=mod_alias:path(Info#mod.data,Info#mod.config_db,
+ Info#mod.request_uri),
+ Suffix=httpd_util:suffix(Path),
+ MimeType=httpd_util:lookup_mime(Info#mod.config_db,Suffix,
+ "text/plain"),
+ Actions=httpd_util:multi_lookup(Info#mod.config_db,action),
+ case action(Info#mod.request_uri,MimeType,Actions) of
+ {yes,RequestURI} ->
+ {proceed,[{new_request_uri,RequestURI}|Info#mod.data]};
+ no ->
+ Scripts=httpd_util:multi_lookup(Info#mod.config_db,script),
+ case script(Info#mod.request_uri,Info#mod.method,Scripts) of
+ {yes,RequestURI} ->
+ {proceed,[{new_request_uri,RequestURI}|Info#mod.data]};
+ no ->
+ {proceed,Info#mod.data}
+ end
+ end;
+ %% A response has been generated or sent!
+ Response ->
+ {proceed,Info#mod.data}
+ end
+ end.
+
+action(RequestURI,MimeType,[]) ->
+ no;
+action(RequestURI,MimeType,[{MimeType,CGIScript}|Rest]) ->
+ {yes,CGIScript++RequestURI};
+action(RequestURI,MimeType,[_|Rest]) ->
+ action(RequestURI,MimeType,Rest).
+
+script(RequestURI,Method,[]) ->
+ no;
+script(RequestURI,Method,[{Method,CGIScript}|Rest]) ->
+ {yes,CGIScript++RequestURI};
+script(RequestURI,Method,[_|Rest]) ->
+ script(RequestURI,Method,Rest).
+
+%%
+%% Configuration
+%%
+
+%% load
+
+load([$A,$c,$t,$i,$o,$n,$ |Action],[]) ->
+ case regexp:split(Action," ") of
+ {ok,[MimeType,CGIScript]} ->
+ {ok,[],{action,{MimeType,CGIScript}}};
+ {ok,_} ->
+ {error,?NICE(httpd_conf:clean(Action)++" is an invalid Action")}
+ end;
+load([$S,$c,$r,$i,$p,$t,$ |Script],[]) ->
+ case regexp:split(Script," ") of
+ {ok,[Method,CGIScript]} ->
+ {ok,[],{script,{Method,CGIScript}}};
+ {ok,_} ->
+ {error,?NICE(httpd_conf:clean(Script)++" is an invalid Script")}
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_alias.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_alias.erl
new file mode 100644
index 0000000000..6b8f7210c4
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_alias.erl
@@ -0,0 +1,175 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_alias.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
+%%
+-module(mod_alias).
+-export([do/1,real_name/3,real_script_name/3,default_index/2,load/2,path/3]).
+
+-include("httpd.hrl").
+
+%% do
+
+do(Info) ->
+ ?DEBUG("do -> entry",[]),
+ case httpd_util:key1search(Info#mod.data,status) of
+ %% A status code has been generated!
+ {StatusCode,PhraseArgs,Reason} ->
+ {proceed,Info#mod.data};
+ %% No status code has been generated!
+ undefined ->
+ case httpd_util:key1search(Info#mod.data,response) of
+ %% No response has been generated!
+ undefined ->
+ do_alias(Info);
+ %% A response has been generated or sent!
+ Response ->
+ {proceed,Info#mod.data}
+ end
+ end.
+
+do_alias(Info) ->
+ ?DEBUG("do_alias -> Request URI: ~p",[Info#mod.request_uri]),
+ {ShortPath,Path,AfterPath} =
+ real_name(Info#mod.config_db,Info#mod.request_uri,
+ httpd_util:multi_lookup(Info#mod.config_db,alias)),
+ %% Relocate if a trailing slash is missing else proceed!
+ LastChar = lists:last(ShortPath),
+ case file:read_file_info(ShortPath) of
+ {ok,FileInfo} when FileInfo#file_info.type == directory,LastChar /= $/ ->
+ ?LOG("do_alias -> ~n"
+ " ShortPath: ~p~n"
+ " LastChar: ~p~n"
+ " FileInfo: ~p",
+ [ShortPath,LastChar,FileInfo]),
+ ServerName = httpd_util:lookup(Info#mod.config_db,server_name),
+ Port = port_string(httpd_util:lookup(Info#mod.config_db,port,80)),
+ URL = "http://"++ServerName++Port++Info#mod.request_uri++"/",
+ ReasonPhrase = httpd_util:reason_phrase(301),
+ Message = httpd_util:message(301,URL,Info#mod.config_db),
+ {proceed,
+ [{response,
+ {301, ["Location: ", URL, "\r\n"
+ "Content-Type: text/html\r\n",
+ "\r\n",
+ "<HTML>\n<HEAD>\n<TITLE>",ReasonPhrase,
+ "</TITLE>\n</HEAD>\n"
+ "<BODY>\n<H1>",ReasonPhrase,
+ "</H1>\n", Message,
+ "\n</BODY>\n</HTML>\n"]}}|
+ [{real_name,{Path,AfterPath}}|Info#mod.data]]};
+ NoFile ->
+ {proceed,[{real_name,{Path,AfterPath}}|Info#mod.data]}
+ end.
+
+port_string(80) ->
+ "";
+port_string(Port) ->
+ ":"++integer_to_list(Port).
+
+%% real_name
+
+real_name(ConfigDB, RequestURI,[]) ->
+ DocumentRoot = httpd_util:lookup(ConfigDB, document_root, ""),
+ RealName = DocumentRoot++RequestURI,
+ {ShortPath, _AfterPath} = httpd_util:split_path(RealName),
+ {Path, AfterPath}=httpd_util:split_path(default_index(ConfigDB,RealName)),
+ {ShortPath, Path, AfterPath};
+real_name(ConfigDB, RequestURI, [{FakeName,RealName}|Rest]) ->
+ case regexp:match(RequestURI, "^"++FakeName) of
+ {match, _, _} ->
+ {ok, ActualName, _} = regexp:sub(RequestURI,
+ "^"++FakeName, RealName),
+ {ShortPath, _AfterPath} = httpd_util:split_path(ActualName),
+ {Path, AfterPath} =
+ httpd_util:split_path(default_index(ConfigDB, ActualName)),
+ {ShortPath, Path, AfterPath};
+ nomatch ->
+ real_name(ConfigDB,RequestURI,Rest)
+ end.
+
+%% real_script_name
+
+real_script_name(ConfigDB,RequestURI,[]) ->
+ not_a_script;
+real_script_name(ConfigDB,RequestURI,[{FakeName,RealName}|Rest]) ->
+ case regexp:match(RequestURI,"^"++FakeName) of
+ {match,_,_} ->
+ {ok,ActualName,_}=regexp:sub(RequestURI,"^"++FakeName,RealName),
+ httpd_util:split_script_path(default_index(ConfigDB,ActualName));
+ nomatch ->
+ real_script_name(ConfigDB,RequestURI,Rest)
+ end.
+
+%% default_index
+
+default_index(ConfigDB, Path) ->
+ case file:read_file_info(Path) of
+ {ok, FileInfo} when FileInfo#file_info.type == directory ->
+ DirectoryIndex = httpd_util:lookup(ConfigDB, directory_index, []),
+ append_index(Path, DirectoryIndex);
+ _ ->
+ Path
+ end.
+
+append_index(RealName, []) ->
+ RealName;
+append_index(RealName, [Index|Rest]) ->
+ case file:read_file_info(filename:join(RealName, Index)) of
+ {error,Reason} ->
+ append_index(RealName, Rest);
+ _ ->
+ filename:join(RealName,Index)
+ end.
+
+%% path
+
+path(Data, ConfigDB, RequestURI) ->
+ case httpd_util:key1search(Data,real_name) of
+ undefined ->
+ DocumentRoot = httpd_util:lookup(ConfigDB, document_root, ""),
+ {Path,AfterPath} =
+ httpd_util:split_path(DocumentRoot++RequestURI),
+ Path;
+ {Path,AfterPath} ->
+ Path
+ end.
+
+%%
+%% Configuration
+%%
+
+%% load
+
+load([$D,$i,$r,$e,$c,$t,$o,$r,$y,$I,$n,$d,$e,$x,$ |DirectoryIndex],[]) ->
+ {ok, DirectoryIndexes} = regexp:split(DirectoryIndex," "),
+ {ok,[], {directory_index, DirectoryIndexes}};
+load([$A,$l,$i,$a,$s,$ |Alias],[]) ->
+ case regexp:split(Alias," ") of
+ {ok, [FakeName, RealName]} ->
+ {ok,[],{alias,{FakeName,RealName}}};
+ {ok, _} ->
+ {error,?NICE(httpd_conf:clean(Alias)++" is an invalid Alias")}
+ end;
+load([$S,$c,$r,$i,$p,$t,$A,$l,$i,$a,$s,$ |ScriptAlias],[]) ->
+ case regexp:split(ScriptAlias," ") of
+ {ok, [FakeName, RealName]} ->
+ %% Make sure the path always has a trailing slash..
+ RealName1 = filename:join(filename:split(RealName)),
+ {ok, [], {script_alias,{FakeName, RealName1++"/"}}};
+ {ok, _} ->
+ {error, ?NICE(httpd_conf:clean(ScriptAlias)++
+ " is an invalid ScriptAlias")}
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth.erl
new file mode 100644
index 0000000000..9f3289c826
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth.erl
@@ -0,0 +1,748 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_auth.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
+%%
+-module(mod_auth).
+
+
+%% The functions that the webbserver call on startup stop
+%% and when the server traverse the modules.
+-export([do/1, load/2, store/2, remove/1]).
+
+%% User entries to the gen-server.
+-export([add_user/2, add_user/5, add_user/6,
+ add_group_member/3, add_group_member/4, add_group_member/5,
+ list_users/1, list_users/2, list_users/3,
+ delete_user/2, delete_user/3, delete_user/4,
+ delete_group_member/3, delete_group_member/4, delete_group_member/5,
+ list_groups/1, list_groups/2, list_groups/3,
+ delete_group/2, delete_group/3, delete_group/4,
+ get_user/2, get_user/3, get_user/4,
+ list_group_members/2, list_group_members/3, list_group_members/4,
+ update_password/6, update_password/5]).
+
+-include("httpd.hrl").
+-include("mod_auth.hrl").
+
+-define(VMODULE,"AUTH").
+-include("httpd_verbosity.hrl").
+
+-define(NOPASSWORD,"NoPassword").
+
+
+%% do
+do(Info) ->
+ ?vtrace("do", []),
+ case httpd_util:key1search(Info#mod.data,status) of
+ %% A status code has been generated!
+ {StatusCode,PhraseArgs,Reason} ->
+ {proceed, Info#mod.data};
+ %% No status code has been generated!
+ undefined ->
+ case httpd_util:key1search(Info#mod.data,response) of
+ %% No response has been generated!
+ undefined ->
+ Path = mod_alias:path(Info#mod.data,Info#mod.config_db,
+ Info#mod.request_uri),
+ %% Is it a secret area?
+ case secretp(Path,Info#mod.config_db) of
+ {yes, Directory, DirectoryData} ->
+ %% Authenticate (allow)
+ case allow((Info#mod.init_data)#init_data.peername,
+ Info#mod.socket_type,Info#mod.socket,
+ DirectoryData) of
+ allowed ->
+ case deny((Info#mod.init_data)#init_data.peername,
+ Info#mod.socket_type, Info#mod.socket,
+ DirectoryData) of
+ not_denied ->
+ case httpd_util:key1search(DirectoryData,
+ auth_type) of
+ undefined ->
+ {proceed, Info#mod.data};
+ none ->
+ {proceed, Info#mod.data};
+ AuthType ->
+ do_auth(Info,
+ Directory,
+ DirectoryData,
+ AuthType)
+ end;
+ {denied, Reason} ->
+ {proceed,
+ [{status,{403,Info#mod.request_uri,Reason}}|
+ Info#mod.data]}
+ end;
+ {not_allowed, Reason} ->
+ {proceed,[{status,{403,Info#mod.request_uri,Reason}}|
+ Info#mod.data]}
+ end;
+ no ->
+ {proceed, Info#mod.data}
+ end;
+ %% A response has been generated or sent!
+ Response ->
+ {proceed, Info#mod.data}
+ end
+ end.
+
+
+do_auth(Info, Directory, DirectoryData, AuthType) ->
+ %% Authenticate (require)
+ case require(Info, Directory, DirectoryData) of
+ authorized ->
+ {proceed,Info#mod.data};
+ {authorized, User} ->
+ {proceed, [{remote_user,User}|Info#mod.data]};
+ {authorization_failed, Reason} ->
+ ?vtrace("do_auth -> authorization_failed: ~p",[Reason]),
+ {proceed, [{status,{401,none,Reason}}|Info#mod.data]};
+ {authorization_required, Realm} ->
+ ?vtrace("do_auth -> authorization_required: ~p",[Realm]),
+ ReasonPhrase = httpd_util:reason_phrase(401),
+ Message = httpd_util:message(401,none,Info#mod.config_db),
+ {proceed,
+ [{response,
+ {401,
+ ["WWW-Authenticate: Basic realm=\"",Realm,
+ "\"\r\n\r\n","<HTML>\n<HEAD>\n<TITLE>",
+ ReasonPhrase,"</TITLE>\n",
+ "</HEAD>\n<BODY>\n<H1>",ReasonPhrase,
+ "</H1>\n",Message,"\n</BODY>\n</HTML>\n"]}}|
+ Info#mod.data]};
+ {status, {StatusCode,PhraseArgs,Reason}} ->
+ {proceed, [{status,{StatusCode,PhraseArgs,Reason}}|
+ Info#mod.data]}
+ end.
+
+
+%% require
+
+require(Info, Directory, DirectoryData) ->
+ ParsedHeader = Info#mod.parsed_header,
+ ValidUsers = httpd_util:key1search(DirectoryData, require_user),
+ ValidGroups = httpd_util:key1search(DirectoryData, require_group),
+
+ %% Any user or group restrictions?
+ case ValidGroups of
+ undefined when ValidUsers == undefined ->
+ authorized;
+ _ ->
+ case httpd_util:key1search(ParsedHeader, "authorization") of
+ %% Authorization required!
+ undefined ->
+ case httpd_util:key1search(DirectoryData, auth_name) of
+ undefined ->
+ {status,{500,none,?NICE("AuthName directive not specified")}};
+ Realm ->
+ {authorization_required, Realm}
+ end;
+ %% Check credentials!
+ [$B,$a,$s,$i,$c,$ | EncodedString] ->
+ DecodedString = httpd_util:decode_base64(EncodedString),
+ case a_valid_user(Info, DecodedString,
+ ValidUsers, ValidGroups,
+ Directory, DirectoryData) of
+ {yes, User} ->
+ {authorized, User};
+ {no, Reason} ->
+ {authorization_failed, Reason};
+ {status, {StatusCode,PhraseArgs,Reason}} ->
+ {status,{StatusCode,PhraseArgs,Reason}}
+ end;
+ %% Bad credentials!
+ BadCredentials ->
+ {status,{401,none,?NICE("Bad credentials "++BadCredentials)}}
+ end
+ end.
+
+a_valid_user(Info,DecodedString,ValidUsers,ValidGroups,Dir,DirData) ->
+ case httpd_util:split(DecodedString,":",2) of
+ {ok,[SupposedUser, Password]} ->
+ case user_accepted(SupposedUser, ValidUsers) of
+ true ->
+ check_password(SupposedUser, Password, Dir, DirData);
+ false ->
+ case group_accepted(Info,SupposedUser,ValidGroups,Dir,DirData) of
+ true ->
+ check_password(SupposedUser,Password,Dir,DirData);
+ false ->
+ {no,?NICE("No such user exists")}
+ end
+ end;
+ {ok,BadCredentials} ->
+ {status,{401,none,?NICE("Bad credentials "++BadCredentials)}}
+ end.
+
+user_accepted(SupposedUser, undefined) ->
+ false;
+user_accepted(SupposedUser, ValidUsers) ->
+ lists:member(SupposedUser, ValidUsers).
+
+
+group_accepted(Info, User, undefined, Dir, DirData) ->
+ false;
+group_accepted(Info, User, [], Dir, DirData) ->
+ false;
+group_accepted(Info, User, [Group|Rest], Dir, DirData) ->
+ Ret = int_list_group_members(Group, Dir, DirData),
+ case Ret of
+ {ok, UserList} ->
+ case lists:member(User, UserList) of
+ true ->
+ true;
+ false ->
+ group_accepted(Info, User, Rest, Dir, DirData)
+ end;
+ Other ->
+ false
+ end.
+
+check_password(User, Password, Dir, DirData) ->
+ case int_get_user(DirData, User) of
+ {ok, UStruct} ->
+ case UStruct#httpd_user.password of
+ Password ->
+ %% FIXME
+ {yes, UStruct#httpd_user.username};
+ Other ->
+ {no, "No such user"} % Don't say 'Bad Password' !!!
+ end;
+ _ ->
+ {no, "No such user"}
+ end.
+
+
+%% Middle API. Theese functions call the appropriate authentication module.
+int_get_user(DirData, User) ->
+ AuthMod = auth_mod_name(DirData),
+ apply(AuthMod, get_user, [DirData, User]).
+
+int_list_group_members(Group, Dir, DirData) ->
+ AuthMod = auth_mod_name(DirData),
+ apply(AuthMod, list_group_members, [DirData, Group]).
+
+auth_mod_name(DirData) ->
+ case httpd_util:key1search(DirData, auth_type, plain) of
+ plain -> mod_auth_plain;
+ mnesia -> mod_auth_mnesia;
+ dets -> mod_auth_dets
+ end.
+
+
+%%
+%% Is it a secret area?
+%%
+
+%% secretp
+
+secretp(Path,ConfigDB) ->
+ Directories = ets:match(ConfigDB,{directory,'$1','_'}),
+ case secret_path(Path, Directories) of
+ {yes,Directory} ->
+ {yes,Directory,
+ lists:flatten(ets:match(ConfigDB,{directory,Directory,'$1'}))};
+ no ->
+ no
+ end.
+
+secret_path(Path,Directories) ->
+ secret_path(Path, httpd_util:uniq(lists:sort(Directories)),to_be_found).
+
+secret_path(Path,[],to_be_found) ->
+ no;
+secret_path(Path,[],Directory) ->
+ {yes,Directory};
+secret_path(Path,[[NewDirectory]|Rest],Directory) ->
+ case regexp:match(Path,NewDirectory) of
+ {match,_,_} when Directory == to_be_found ->
+ secret_path(Path,Rest,NewDirectory);
+ {match,_,Length} when Length > length(Directory)->
+ secret_path(Path,Rest,NewDirectory);
+ {match,_,Length} ->
+ secret_path(Path,Rest,Directory);
+ nomatch ->
+ secret_path(Path,Rest,Directory)
+ end.
+
+%%
+%% Authenticate
+%%
+
+%% allow
+
+allow({_,RemoteAddr},SocketType,Socket,DirectoryData) ->
+ Hosts = httpd_util:key1search(DirectoryData, allow_from, all),
+ case validate_addr(RemoteAddr,Hosts) of
+ true ->
+ allowed;
+ false ->
+ {not_allowed, ?NICE("Connection from your host is not allowed")}
+ end.
+
+validate_addr(RemoteAddr,all) -> % When called from 'allow'
+ true;
+validate_addr(RemoteAddr,none) -> % When called from 'deny'
+ false;
+validate_addr(RemoteAddr,[]) ->
+ false;
+validate_addr(RemoteAddr,[HostRegExp|Rest]) ->
+ ?DEBUG("validate_addr -> RemoteAddr: ~p HostRegExp: ~p",
+ [RemoteAddr, HostRegExp]),
+ case regexp:match(RemoteAddr, HostRegExp) of
+ {match,_,_} ->
+ true;
+ nomatch ->
+ validate_addr(RemoteAddr,Rest)
+ end.
+
+%% deny
+
+deny({_,RemoteAddr},SocketType,Socket,DirectoryData) ->
+ ?DEBUG("deny -> RemoteAddr: ~p",[RemoteAddr]),
+ Hosts = httpd_util:key1search(DirectoryData, deny_from, none),
+ ?DEBUG("deny -> Hosts: ~p",[Hosts]),
+ case validate_addr(RemoteAddr,Hosts) of
+ true ->
+ {denied, ?NICE("Connection from your host is not allowed")};
+ false ->
+ not_denied
+ end.
+
+%%
+%% Configuration
+%%
+
+%% load/2
+%%
+
+%% mod_auth recognizes the following Configuration Directives:
+%% <Directory /path/to/directory>
+%% AuthDBType
+%% AuthName
+%% AuthUserFile
+%% AuthGroupFile
+%% AuthAccessPassword
+%% require
+%% allow
+%% </Directory>
+
+%% When a <Directory> directive is found, a new context is set to
+%% [{directory, Directory, DirData}|OtherContext]
+%% DirData in this case is a key-value list of data belonging to the
+%% directory in question.
+%%
+%% When the </Directory> statement is found, the Context created earlier
+%% will be returned as a ConfigList and the context will return to the
+%% state it was previously.
+
+load([$<,$D,$i,$r,$e,$c,$t,$o,$r,$y,$ |Directory],[]) ->
+ Dir = httpd_conf:custom_clean(Directory,"",">"),
+ {ok,[{directory, Dir, [{path, Dir}]}]};
+load(eof,[{directory,Directory, DirData}|_]) ->
+ {error, ?NICE("Premature end-of-file in "++Directory)};
+
+load([$A,$u,$t,$h,$N,$a,$m,$e,$ |AuthName], [{directory,Directory, DirData}|Rest]) ->
+ {ok, [{directory,Directory,
+ [ {auth_name, httpd_conf:clean(AuthName)}|DirData]} | Rest ]};
+
+load([$A,$u,$t,$h,$U,$s,$e,$r,$F,$i,$l,$e,$ |AuthUserFile0],
+ [{directory, Directory, DirData}|Rest]) ->
+ AuthUserFile = httpd_conf:clean(AuthUserFile0),
+ {ok,[{directory,Directory,
+ [ {auth_user_file, AuthUserFile}|DirData]} | Rest ]};
+
+load([$A,$u,$t,$h,$G,$r,$o,$u,$p,$F,$i,$l,$e,$ |AuthGroupFile0],
+ [{directory,Directory, DirData}|Rest]) ->
+ AuthGroupFile = httpd_conf:clean(AuthGroupFile0),
+ {ok,[{directory,Directory,
+ [ {auth_group_file, AuthGroupFile}|DirData]} | Rest]};
+
+%AuthAccessPassword
+load([$A,$u,$t,$h,$A,$c,$c,$e,$s,$s,$P,$a,$s,$s,$w,$o,$r,$d,$ |AuthAccessPassword0],
+ [{directory,Directory, DirData}|Rest]) ->
+ AuthAccessPassword = httpd_conf:clean(AuthAccessPassword0),
+ {ok,[{directory,Directory,
+ [{auth_access_password, AuthAccessPassword}|DirData]} | Rest]};
+
+
+
+
+load([$A,$u,$t,$h,$D,$B,$T,$y,$p,$e,$ |Type],
+ [{directory, Dir, DirData}|Rest]) ->
+ case httpd_conf:clean(Type) of
+ "plain" ->
+ {ok, [{directory, Dir, [{auth_type, plain}|DirData]} | Rest ]};
+ "mnesia" ->
+ {ok, [{directory, Dir, [{auth_type, mnesia}|DirData]} | Rest ]};
+ "dets" ->
+ {ok, [{directory, Dir, [{auth_type, dets}|DirData]} | Rest ]};
+ _ ->
+ {error, ?NICE(httpd_conf:clean(Type)++" is an invalid AuthDBType")}
+ end;
+
+load([$r,$e,$q,$u,$i,$r,$e,$ |Require],[{directory,Directory, DirData}|Rest]) ->
+ case regexp:split(Require," ") of
+ {ok,["user"|Users]} ->
+ {ok,[{directory,Directory,
+ [{require_user,Users}|DirData]} | Rest]};
+ {ok,["group"|Groups]} ->
+ {ok,[{directory,Directory,
+ [{require_group,Groups}|DirData]} | Rest]};
+ {ok,_} ->
+ {error,?NICE(httpd_conf:clean(Require)++" is an invalid require")}
+ end;
+
+load([$a,$l,$l,$o,$w,$ |Allow],[{directory,Directory, DirData}|Rest]) ->
+ case regexp:split(Allow," ") of
+ {ok,["from","all"]} ->
+ {ok,[{directory,Directory,
+ [{allow_from,all}|DirData]} | Rest]};
+ {ok,["from"|Hosts]} ->
+ {ok,[{directory,Directory,
+ [{allow_from,Hosts}|DirData]} | Rest]};
+ {ok,_} ->
+ {error,?NICE(httpd_conf:clean(Allow)++" is an invalid allow")}
+ end;
+
+load([$d,$e,$n,$y,$ |Deny],[{directory,Directory, DirData}|Rest]) ->
+ case regexp:split(Deny," ") of
+ {ok, ["from", "all"]} ->
+ {ok,[{directory, Directory,
+ [{deny_from, all}|DirData]} | Rest]};
+ {ok, ["from"|Hosts]} ->
+ {ok,[{directory, Directory,
+ [{deny_from, Hosts}|DirData]} | Rest]};
+ {ok, _} ->
+ {error,?NICE(httpd_conf:clean(Deny)++" is an invalid deny")}
+ end;
+
+load("</Directory>",[{directory,Directory, DirData}|Rest]) ->
+ {ok, Rest, {directory, Directory, DirData}};
+
+load([$A,$u,$t,$h,$M,$n,$e,$s,$i,$a,$D,$B,$ |AuthMnesiaDB],
+ [{directory, Dir, DirData}|Rest]) ->
+ case httpd_conf:clean(AuthMnesiaDB) of
+ "On" ->
+ {ok,[{directory,Dir,[{auth_type,mnesia}|DirData]}|Rest]};
+ "Off" ->
+ {ok,[{directory,Dir,[{auth_type,plain}|DirData]}|Rest]};
+ _ ->
+ {error, ?NICE(httpd_conf:clean(AuthMnesiaDB)++" is an invalid AuthMnesiaDB")}
+ end.
+
+%% store
+
+store({directory,Directory0, DirData0}, ConfigList) ->
+ Port = httpd_util:key1search(ConfigList, port),
+ DirData = case httpd_util:key1search(ConfigList, bind_address) of
+ undefined ->
+ [{port, Port}|DirData0];
+ Addr ->
+ [{port, Port},{bind_address,Addr}|DirData0]
+ end,
+ Directory =
+ case filename:pathtype(Directory0) of
+ relative ->
+ SR = httpd_util:key1search(ConfigList, server_root),
+ filename:join(SR, Directory0);
+ _ ->
+ Directory0
+ end,
+ AuthMod =
+ case httpd_util:key1search(DirData0, auth_type) of
+ mnesia -> mod_auth_mnesia;
+ dets -> mod_auth_dets;
+ plain -> mod_auth_plain;
+ _ -> no_module_at_all
+ end,
+ case AuthMod of
+ no_module_at_all ->
+ {ok, {directory, Directory, DirData}};
+ _ ->
+ %% Control that there are a password or add a standard password:
+ %% "NoPassword"
+ %% In this way a user must select to use a noPassword
+ Pwd = case httpd_util:key1search(DirData,auth_access_password)of
+ undefined->
+ ?NOPASSWORD;
+ PassW->
+ PassW
+ end,
+ DirDataLast = lists:keydelete(auth_access_password,1,DirData),
+ case catch AuthMod:store_directory_data(Directory, DirDataLast) of
+ ok ->
+ add_auth_password(Directory,Pwd,ConfigList),
+ {ok, {directory, Directory, DirDataLast}};
+ {ok, NewDirData} ->
+ add_auth_password(Directory,Pwd,ConfigList),
+ {ok, {directory, Directory, NewDirData}};
+ {error, Reason} ->
+ {error, Reason};
+ Other ->
+ ?ERROR("unexpected result: ~p",[Other]),
+ {error, Other}
+ end
+ end.
+
+
+add_auth_password(Dir, Pwd0, ConfigList) ->
+ Addr = httpd_util:key1search(ConfigList, bind_address),
+ Port = httpd_util:key1search(ConfigList, port),
+ mod_auth_server:start(Addr, Port),
+ mod_auth_server:add_password(Addr, Port, Dir, Pwd0).
+
+%% remove
+
+
+remove(ConfigDB) ->
+ lists:foreach(fun({directory, Dir, DirData}) ->
+ AuthMod = auth_mod_name(DirData),
+ (catch apply(AuthMod, remove, [DirData]))
+ end,
+ ets:match_object(ConfigDB,{directory,'_','_'})),
+ Addr = case lookup(ConfigDB, bind_address) of
+ [] ->
+ undefined;
+ [{bind_address, Address}] ->
+ Address
+ end,
+ [{port, Port}] = lookup(ConfigDB, port),
+ mod_auth_server:stop(Addr, Port),
+ ok.
+
+
+
+
+%% --------------------------------------------------------------------
+
+%% update_password
+
+update_password(Port, Dir, Old, New, New)->
+ update_password(undefined, Port, Dir, Old, New, New).
+
+update_password(Addr, Port, Dir, Old, New, New) when list(New) ->
+ mod_auth_server:update_password(Addr, Port, Dir, Old, New);
+
+update_password(_Addr, _Port, _Dir, _Old, New, New) ->
+ {error, badtype};
+update_password(_Addr, _Port, _Dir, _Old, New, New1) ->
+ {error, notqeual}.
+
+
+%% add_user
+
+add_user(UserName, Opt) ->
+ case get_options(Opt, mandatory) of
+ {Addr, Port, Dir, AuthPwd}->
+ case get_options(Opt, userData) of
+ {error, Reason}->
+ {error, Reason};
+ {UserData, Password}->
+ User = [#httpd_user{username = UserName,
+ password = Password,
+ user_data = UserData}],
+ mod_auth_server:add_user(Addr, Port, Dir, User, AuthPwd);
+ {error, Reason} ->
+ {error, Reason}
+ end
+ end.
+
+
+add_user(UserName, Password, UserData, Port, Dir) ->
+ add_user(UserName, Password, UserData, undefined, Port, Dir).
+add_user(UserName, Password, UserData, Addr, Port, Dir) ->
+ User = [#httpd_user{username = UserName,
+ password = Password,
+ user_data = UserData}],
+ mod_auth_server:add_user(Addr, Port, Dir, User, ?NOPASSWORD).
+
+
+%% get_user
+
+get_user(UserName, Opt) ->
+ case get_options(Opt, mandatory) of
+ {Addr, Port, Dir, AuthPwd} ->
+ mod_auth_server:get_user(Addr, Port, Dir, UserName, AuthPwd);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+get_user(UserName, Port, Dir) ->
+ get_user(UserName, undefined, Port, Dir).
+get_user(UserName, Addr, Port, Dir) ->
+ mod_auth_server:get_user(Addr, Port, Dir, UserName, ?NOPASSWORD).
+
+
+%% add_group_member
+
+add_group_member(GroupName, UserName, Opt)->
+ case get_options(Opt, mandatory) of
+ {Addr, Port, Dir, AuthPwd}->
+ mod_auth_server:add_group_member(Addr, Port, Dir,
+ GroupName, UserName, AuthPwd);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+add_group_member(GroupName, UserName, Port, Dir) ->
+ add_group_member(GroupName, UserName, undefined, Port, Dir).
+
+add_group_member(GroupName, UserName, Addr, Port, Dir) ->
+ mod_auth_server:add_group_member(Addr, Port, Dir,
+ GroupName, UserName, ?NOPASSWORD).
+
+
+%% delete_group_member
+
+delete_group_member(GroupName, UserName, Opt) ->
+ case get_options(Opt, mandatory) of
+ {Addr, Port, Dir, AuthPwd} ->
+ mod_auth_server:delete_group_member(Addr, Port, Dir,
+ GroupName, UserName, AuthPwd);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+delete_group_member(GroupName, UserName, Port, Dir) ->
+ delete_group_member(GroupName, UserName, undefined, Port, Dir).
+delete_group_member(GroupName, UserName, Addr, Port, Dir) ->
+ mod_auth_server:delete_group_member(Addr, Port, Dir,
+ GroupName, UserName, ?NOPASSWORD).
+
+
+%% list_users
+
+list_users(Opt) ->
+ case get_options(Opt, mandatory) of
+ {Addr, Port, Dir, AuthPwd} ->
+ mod_auth_server:list_users(Addr, Port, Dir, AuthPwd);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+list_users(Port, Dir) ->
+ list_users(undefined, Port, Dir).
+list_users(Addr, Port, Dir) ->
+ mod_auth_server:list_users(Addr, Port, Dir, ?NOPASSWORD).
+
+
+%% delete_user
+
+delete_user(UserName, Opt) ->
+ case get_options(Opt, mandatory) of
+ {Addr, Port, Dir, AuthPwd} ->
+ mod_auth_server:delete_user(Addr, Port, Dir, UserName, AuthPwd);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+delete_user(UserName, Port, Dir) ->
+ delete_user(UserName, undefined, Port, Dir).
+delete_user(UserName, Addr, Port, Dir) ->
+ mod_auth_server:delete_user(Addr, Port, Dir, UserName, ?NOPASSWORD).
+
+
+%% delete_group
+
+delete_group(GroupName, Opt) ->
+ case get_options(Opt, mandatory) of
+ {Addr, Port, Dir, AuthPwd}->
+ mod_auth_server:delete_group(Addr, Port, Dir, GroupName, AuthPwd);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+delete_group(GroupName, Port, Dir) ->
+ delete_group(GroupName, undefined, Port, Dir).
+delete_group(GroupName, Addr, Port, Dir) ->
+ mod_auth_server:delete_group(Addr, Port, Dir, GroupName, ?NOPASSWORD).
+
+
+%% list_groups
+
+list_groups(Opt) ->
+ case get_options(Opt, mandatory) of
+ {Addr, Port, Dir, AuthPwd}->
+ mod_auth_server:list_groups(Addr, Port, Dir, AuthPwd);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+list_groups(Port, Dir) ->
+ list_groups(undefined, Port, Dir).
+list_groups(Addr, Port, Dir) ->
+ mod_auth_server:list_groups(Addr, Port, Dir, ?NOPASSWORD).
+
+
+%% list_group_members
+
+list_group_members(GroupName,Opt) ->
+ case get_options(Opt, mandatory) of
+ {Addr, Port, Dir, AuthPwd} ->
+ mod_auth_server:list_group_members(Addr, Port, Dir, GroupName,
+ AuthPwd);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+list_group_members(GroupName, Port, Dir) ->
+ list_group_members(GroupName, undefined, Port, Dir).
+list_group_members(GroupName, Addr, Port, Dir) ->
+ mod_auth_server:list_group_members(Addr, Port, Dir, GroupName, ?NOPASSWORD).
+
+
+
+%% Opt = [{port, Port},
+%% {addr, Addr},
+%% {dir, Dir},
+%% {authPassword, AuthPassword} | FunctionSpecificData]
+get_options(Opt, mandatory)->
+ case httpd_util:key1search(Opt, port, undefined) of
+ Port when integer(Port) ->
+ case httpd_util:key1search(Opt, dir, undefined) of
+ Dir when list(Dir) ->
+ Addr = httpd_util:key1search(Opt,
+ addr,
+ undefined),
+ AuthPwd = httpd_util:key1search(Opt,
+ authPassword,
+ ?NOPASSWORD),
+ {Addr, Port, Dir, AuthPwd};
+ _->
+ {error, bad_dir}
+ end;
+ _ ->
+ {error, bad_dir}
+ end;
+
+%% FunctionSpecificData = {userData, UserData} | {password, Password}
+get_options(Opt, userData)->
+ case httpd_util:key1search(Opt, userData, undefined) of
+ undefined ->
+ {error, no_userdata};
+ UserData ->
+ case httpd_util:key1search(Opt, password, undefined) of
+ undefined->
+ {error, no_password};
+ Pwd ->
+ {UserData, Pwd}
+ end
+ end.
+
+
+lookup(Db, Key) ->
+ ets:lookup(Db, Key).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth.hrl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth.hrl
new file mode 100644
index 0000000000..2b8ea6657f
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth.hrl
@@ -0,0 +1,26 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_auth.hrl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
+%%
+
+-record(httpd_user,
+ {username,
+ password,
+ user_data}).
+
+-record(httpd_group,
+ {name,
+ userlist}).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth_dets.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth_dets.erl
new file mode 100644
index 0000000000..d947d6cf49
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth_dets.erl
@@ -0,0 +1,222 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_auth_dets.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
+%%
+-module(mod_auth_dets).
+
+%% dets authentication storage
+
+-export([get_user/2,
+ list_group_members/2,
+ add_user/2,
+ add_group_member/3,
+ list_users/1,
+ delete_user/2,
+ list_groups/1,
+ delete_group_member/3,
+ delete_group/2,
+ remove/1]).
+
+-export([store_directory_data/2]).
+
+-include("httpd.hrl").
+-include("mod_auth.hrl").
+
+store_directory_data(Directory, DirData) ->
+ ?CDEBUG("store_directory_data -> ~n"
+ " Directory: ~p~n"
+ " DirData: ~p",
+ [Directory, DirData]),
+
+ PWFile = httpd_util:key1search(DirData, auth_user_file),
+ GroupFile = httpd_util:key1search(DirData, auth_group_file),
+ Addr = httpd_util:key1search(DirData, bind_address),
+ Port = httpd_util:key1search(DirData, port),
+
+ PWName = httpd_util:make_name("httpd_dets_pwdb",Addr,Port),
+ case dets:open_file(PWName,[{type,set},{file,PWFile},{repair,true}]) of
+ {ok, PWDB} ->
+ GDBName = httpd_util:make_name("httpd_dets_groupdb",Addr,Port),
+ case dets:open_file(GDBName,[{type,set},{file,GroupFile},{repair,true}]) of
+ {ok, GDB} ->
+ NDD1 = lists:keyreplace(auth_user_file, 1, DirData,
+ {auth_user_file, PWDB}),
+ NDD2 = lists:keyreplace(auth_group_file, 1, NDD1,
+ {auth_group_file, GDB}),
+ {ok, NDD2};
+ {error, Err}->
+ {error, {{file, GroupFile},Err}}
+ end;
+ {error, Err2} ->
+ {error, {{file, PWFile},Err2}}
+ end.
+
+%%
+%% Storage format of users in the dets table:
+%% {{UserName, Addr, Port, Dir}, Password, UserData}
+%%
+
+add_user(DirData, UStruct) ->
+ {Addr, Port, Dir} = lookup_common(DirData),
+ PWDB = httpd_util:key1search(DirData, auth_user_file),
+ Record = {{UStruct#httpd_user.username, Addr, Port, Dir},
+ UStruct#httpd_user.password, UStruct#httpd_user.user_data},
+ case dets:lookup(PWDB, UStruct#httpd_user.username) of
+ [Record] ->
+ {error, user_already_in_db};
+ _ ->
+ dets:insert(PWDB, Record),
+ true
+ end.
+
+get_user(DirData, UserName) ->
+ {Addr, Port, Dir} = lookup_common(DirData),
+ PWDB = httpd_util:key1search(DirData, auth_user_file),
+ User = {UserName, Addr, Port, Dir},
+ case dets:lookup(PWDB, User) of
+ [{User, Password, UserData}] ->
+ {ok, #httpd_user{username=UserName, password=Password, user_data=UserData}};
+ Other ->
+ {error, no_such_user}
+ end.
+
+list_users(DirData) ->
+ ?DEBUG("list_users -> ~n"
+ " DirData: ~p", [DirData]),
+ {Addr, Port, Dir} = lookup_common(DirData),
+ PWDB = httpd_util:key1search(DirData, auth_user_file),
+ case dets:traverse(PWDB, fun(X) -> {continue, X} end) of %% SOOOO Ugly !
+ Records when list(Records) ->
+ ?DEBUG("list_users -> ~n"
+ " Records: ~p", [Records]),
+ {ok, [UserName || {{UserName, AnyAddr, AnyPort, AnyDir}, Password, _Data} <- Records,
+ AnyAddr == Addr, AnyPort == Port, AnyDir == Dir]};
+ O ->
+ ?DEBUG("list_users -> ~n"
+ " O: ~p", [O]),
+ {ok, []}
+ end.
+
+delete_user(DirData, UserName) ->
+ {Addr, Port, Dir} = lookup_common(DirData),
+ PWDB = httpd_util:key1search(DirData, auth_user_file),
+ User = {UserName, Addr, Port, Dir},
+ case dets:lookup(PWDB, User) of
+ [{User, SomePassword, UserData}] ->
+ dets:delete(PWDB, User),
+ lists:foreach(fun(Group) -> delete_group_member(DirData, Group, UserName) end,
+ list_groups(DirData)),
+ true;
+ _ ->
+ {error, no_such_user}
+ end.
+
+%%
+%% Storage of groups in the dets table:
+%% {Group, UserList} where UserList is a list of strings.
+%%
+add_group_member(DirData, GroupName, UserName) ->
+ {Addr, Port, Dir} = lookup_common(DirData),
+ GDB = httpd_util:key1search(DirData, auth_group_file),
+ Group = {GroupName, Addr, Port, Dir},
+ case dets:lookup(GDB, Group) of
+ [{Group, Users}] ->
+ case lists:member(UserName, Users) of
+ true ->
+ true;
+ false ->
+ dets:insert(GDB, {Group, [UserName|Users]}),
+ true
+ end;
+ [] ->
+ dets:insert(GDB, {Group, [UserName]}),
+ true;
+ Other ->
+ {error, Other}
+ end.
+
+list_group_members(DirData, GroupName) ->
+ {Addr, Port, Dir} = lookup_common(DirData),
+ GDB = httpd_util:key1search(DirData, auth_group_file),
+ Group = {GroupName, Addr, Port, Dir},
+ case dets:lookup(GDB, Group) of
+ [{Group, Users}] ->
+ {ok, Users};
+ Other ->
+ {error, no_such_group}
+ end.
+
+list_groups(DirData) ->
+ {Addr, Port, Dir} = lookup_common(DirData),
+ GDB = httpd_util:key1search(DirData, auth_group_file),
+ case dets:match(GDB, {'$1', '_'}) of
+ [] ->
+ {ok, []};
+ List when list(List) ->
+ Groups = lists:flatten(List),
+ {ok, [GroupName || {GroupName, AnyAddr, AnyPort, AnyDir} <- Groups,
+ AnyAddr == Addr, AnyPort == Port, AnyDir == Dir]};
+ _ ->
+ {ok, []}
+ end.
+
+delete_group_member(DirData, GroupName, UserName) ->
+ {Addr, Port, Dir} = lookup_common(DirData),
+ GDB = httpd_util:key1search(DirData, auth_group_file),
+ Group = {GroupName, Addr, Port, Dir},
+ case dets:lookup(GDB, GroupName) of
+ [{Group, Users}] ->
+ case lists:member(UserName, Users) of
+ true ->
+ dets:delete(GDB, Group),
+ dets:insert(GDB, {Group,
+ lists:delete(UserName, Users)}),
+ true;
+ false ->
+ {error, no_such_group_member}
+ end;
+ _ ->
+ {error, no_such_group}
+ end.
+
+delete_group(DirData, GroupName) ->
+ {Addr, Port, Dir} = lookup_common(DirData),
+ GDB = httpd_util:key1search(DirData, auth_group_file),
+ Group = {GroupName, Addr, Port, Dir},
+ case dets:lookup(GDB, Group) of
+ [{Group, Users}] ->
+ dets:delete(GDB, Group),
+ true;
+ _ ->
+ {error, no_such_group}
+ end.
+
+lookup_common(DirData) ->
+ Dir = httpd_util:key1search(DirData, path),
+ Port = httpd_util:key1search(DirData, port),
+ Addr = httpd_util:key1search(DirData, bind_address),
+ {Addr, Port, Dir}.
+
+%% remove/1
+%%
+%% Closes dets tables used by this auth mod.
+%%
+remove(DirData) ->
+ PWDB = httpd_util:key1search(DirData, auth_user_file),
+ GDB = httpd_util:key1search(DirData, auth_group_file),
+ dets:close(GDB),
+ dets:close(PWDB),
+ ok.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth_mnesia.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth_mnesia.erl
new file mode 100644
index 0000000000..ea2f0cb905
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth_mnesia.erl
@@ -0,0 +1,269 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_auth_mnesia.erl,v 1.2 2010/03/04 13:54:19 maria Exp $
+%%
+-module(mod_auth_mnesia).
+-export([get_user/2,
+ list_group_members/2,
+ add_user/2,
+ add_group_member/3,
+ list_users/1,
+ delete_user/2,
+ list_groups/1,
+ delete_group_member/3,
+ delete_group/2]).
+
+-export([store_user/5, store_user/6,
+ store_group_member/5, store_group_member/6,
+ list_group_members/3, list_group_members/4,
+ list_groups/2, list_groups/3,
+ list_users/2, list_users/3,
+ remove_user/4, remove_user/5,
+ remove_group_member/5, remove_group_member/6,
+ remove_group/4, remove_group/5]).
+
+-export([store_directory_data/2]).
+
+-include("httpd.hrl").
+-include("mod_auth.hrl").
+
+
+
+store_directory_data(Directory, DirData) ->
+ %% We don't need to do anything here, we could ofcourse check that the appropriate
+ %% mnesia tables has been created prior to starting the http server.
+ ok.
+
+
+%%
+%% API
+%%
+
+%% Compability API
+
+
+store_user(UserName, Password, Port, Dir, AccessPassword) ->
+ %% AccessPassword is ignored - was not used in previous version
+ DirData = [{path,Dir},{port,Port}],
+ UStruct = #httpd_user{username = UserName,
+ password = Password},
+ add_user(DirData, UStruct).
+
+store_user(UserName, Password, Addr, Port, Dir, AccessPassword) ->
+ %% AccessPassword is ignored - was not used in previous version
+ DirData = [{path,Dir},{bind_address,Addr},{port,Port}],
+ UStruct = #httpd_user{username = UserName,
+ password = Password},
+ add_user(DirData, UStruct).
+
+store_group_member(GroupName, UserName, Port, Dir, AccessPassword) ->
+ DirData = [{path,Dir},{port,Port}],
+ add_group_member(DirData, GroupName, UserName).
+
+store_group_member(GroupName, UserName, Addr, Port, Dir, AccessPassword) ->
+ DirData = [{path,Dir},{bind_address,Addr},{port,Port}],
+ add_group_member(DirData, GroupName, UserName).
+
+list_group_members(GroupName, Port, Dir) ->
+ DirData = [{path,Dir},{port,Port}],
+ list_group_members(DirData, GroupName).
+
+list_group_members(GroupName, Addr, Port, Dir) ->
+ DirData = [{path,Dir},{bind_address,Addr},{port,Port}],
+ list_group_members(DirData, GroupName).
+
+list_groups(Port, Dir) ->
+ DirData = [{path,Dir},{port,Port}],
+ list_groups(DirData).
+
+list_groups(Addr, Port, Dir) ->
+ DirData = [{path,Dir},{bind_address,Addr},{port,Port}],
+ list_groups(DirData).
+
+list_users(Port, Dir) ->
+ DirData = [{path,Dir},{port,Port}],
+ list_users(DirData).
+
+list_users(Addr, Port, Dir) ->
+ DirData = [{path,Dir},{bind_address,Addr},{port,Port}],
+ list_users(DirData).
+
+remove_user(UserName, Port, Dir, _AccessPassword) ->
+ DirData = [{path,Dir},{port,Port}],
+ delete_user(DirData, UserName).
+
+remove_user(UserName, Addr, Port, Dir, _AccessPassword) ->
+ DirData = [{path,Dir},{bind_address,Addr},{port,Port}],
+ delete_user(DirData, UserName).
+
+remove_group_member(GroupName,UserName,Port,Dir,_AccessPassword) ->
+ DirData = [{path,Dir},{port,Port}],
+ delete_group_member(DirData, GroupName, UserName).
+
+remove_group_member(GroupName,UserName,Addr,Port,Dir,_AccessPassword) ->
+ DirData = [{path,Dir},{bind_address,Addr},{port,Port}],
+ delete_group_member(DirData, GroupName, UserName).
+
+remove_group(GroupName,Port,Dir,_AccessPassword) ->
+ DirData = [{path,Dir},{port,Port}],
+ delete_group(DirData, GroupName).
+
+remove_group(GroupName,Addr,Port,Dir,_AccessPassword) ->
+ DirData = [{path,Dir},{bind_address,Addr},{port,Port}],
+ delete_group(DirData, GroupName).
+
+%%
+%% Storage format of users in the mnesia table:
+%% httpd_user records
+%%
+
+add_user(DirData, UStruct) ->
+ {Addr, Port, Dir} = lookup_common(DirData),
+ UserName = UStruct#httpd_user.username,
+ Password = UStruct#httpd_user.password,
+ Data = UStruct#httpd_user.user_data,
+ User=#httpd_user{username={UserName,Addr,Port,Dir},
+ password=Password,
+ user_data=Data},
+ case mnesia:transaction(fun() -> mnesia:write(User) end) of
+ {aborted,Reason} ->
+ {error,Reason};
+ _ ->
+ true
+ end.
+
+get_user(DirData, UserName) ->
+ {Addr, Port, Dir} = lookup_common(DirData),
+ case mnesia:transaction(fun() ->
+ mnesia:read({httpd_user,
+ {UserName,Addr,Port,Dir}})
+ end) of
+ {aborted,Reason} ->
+ {error, Reason};
+ {'atomic',[]} ->
+ {error, no_such_user};
+ {'atomic', [Record]} when record(Record, httpd_user) ->
+ {ok, Record#httpd_user{username=UserName}};
+ Other ->
+ {error, no_such_user}
+ end.
+
+list_users(DirData) ->
+ {Addr, Port, Dir} = lookup_common(DirData),
+ case mnesia:transaction(fun() ->
+ mnesia:match_object({httpd_user,
+ {'_',Addr,Port,Dir},'_','_'})
+ end) of
+ {aborted,Reason} ->
+ {error,Reason};
+ {'atomic',Users} ->
+ {ok,
+ lists:foldr(fun({httpd_user, {UserName, AnyAddr, AnyPort, AnyDir},
+ Password, Data}, Acc) ->
+ [UserName|Acc]
+ end,
+ [], Users)}
+ end.
+
+delete_user(DirData, UserName) ->
+ {Addr, Port, Dir} = lookup_common(DirData),
+ case mnesia:transaction(fun() ->
+ mnesia:delete({httpd_user,
+ {UserName,Addr,Port,Dir}})
+ end) of
+ {aborted,Reason} ->
+ {error,Reason};
+ _ ->
+ true
+ end.
+
+%%
+%% Storage of groups in the mnesia table:
+%% Multiple instances of {#httpd_group, User}
+%%
+
+add_group_member(DirData, GroupName, User) ->
+ {Addr, Port, Dir} = lookup_common(DirData),
+ Group=#httpd_group{name={GroupName, Addr, Port, Dir}, userlist=User},
+ case mnesia:transaction(fun() -> mnesia:write(Group) end) of
+ {aborted,Reason} ->
+ {error,Reason};
+ _ ->
+ true
+ end.
+
+list_group_members(DirData, GroupName) ->
+ {Addr, Port, Dir} = lookup_common(DirData),
+ case mnesia:transaction(fun() ->
+ mnesia:read({httpd_group,
+ {GroupName,Addr,Port,Dir}})
+ end) of
+ {aborted, Reason} ->
+ {error,Reason};
+ {'atomic', Members} ->
+ {ok,[UserName || {httpd_group,{AnyGroupName,AnyAddr,AnyPort,AnyDir},UserName} <- Members,
+ AnyGroupName == GroupName, AnyAddr == Addr,
+ AnyPort == Port, AnyDir == Dir]}
+ end.
+
+list_groups(DirData) ->
+ {Addr, Port, Dir} = lookup_common(DirData),
+ case mnesia:transaction(fun() ->
+ mnesia:match_object({httpd_group,
+ {'_',Addr,Port,Dir},'_'})
+ end) of
+ {aborted, Reason} ->
+ {error, Reason};
+ {'atomic', Groups} ->
+ GroupNames=
+ [GroupName || {httpd_group,{GroupName,AnyAddr,AnyPort,AnyDir}, UserName} <- Groups,
+ AnyAddr == Addr, AnyPort == AnyPort, AnyDir == Dir],
+ {ok, httpd_util:uniq(lists:sort(GroupNames))}
+ end.
+
+delete_group_member(DirData, GroupName, UserName) ->
+ {Addr, Port, Dir} = lookup_common(DirData),
+ Group = #httpd_group{name={GroupName, Addr, Port, Dir}, userlist=UserName},
+ case mnesia:transaction(fun() -> mnesia:delete_object(Group) end) of
+ {aborted,Reason} ->
+ {error,Reason};
+ _ ->
+ true
+ end.
+
+%% THIS IS WRONG (?) !
+%% Should first match out all httpd_group records for this group and then
+%% do mnesia:delete on those. Or ?
+
+delete_group(DirData, GroupName) ->
+ {Addr, Port, Dir} = lookup_common(DirData),
+ case mnesia:transaction(fun() ->
+ mnesia:delete({httpd_group,
+ {GroupName,Addr,Port,Dir}})
+ end) of
+ {aborted,Reason} ->
+ {error,Reason};
+ _ ->
+ true
+ end.
+
+%% Utility functions.
+
+lookup_common(DirData) ->
+ Dir = httpd_util:key1search(DirData, path),
+ Port = httpd_util:key1search(DirData, port),
+ Addr = httpd_util:key1search(DirData, bind_address),
+ {Addr, Port, Dir}.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth_plain.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth_plain.erl
new file mode 100644
index 0000000000..75cc60f288
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth_plain.erl
@@ -0,0 +1,338 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_auth_plain.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
+%%
+-module(mod_auth_plain).
+
+-include("httpd.hrl").
+-include("mod_auth.hrl").
+
+-define(VMODULE,"AUTH_PLAIN").
+-include("httpd_verbosity.hrl").
+
+
+%% Internal API
+-export([store_directory_data/2]).
+
+
+-export([get_user/2,
+ list_group_members/2,
+ add_user/2,
+ add_group_member/3,
+ list_users/1,
+ delete_user/2,
+ list_groups/1,
+ delete_group_member/3,
+ delete_group/2,
+ remove/1]).
+
+%%
+%% API
+%%
+
+%%
+%% Storage format of users in the ets table:
+%% {UserName, Password, UserData}
+%%
+
+add_user(DirData, #httpd_user{username = User} = UStruct) ->
+ ?vtrace("add_user -> entry with:"
+ "~n User: ~p",[User]),
+ PWDB = httpd_util:key1search(DirData, auth_user_file),
+ Record = {User,
+ UStruct#httpd_user.password,
+ UStruct#httpd_user.user_data},
+ case ets:lookup(PWDB, User) of
+ [{User, _SomePassword, _SomeData}] ->
+ {error, user_already_in_db};
+ _ ->
+ ets:insert(PWDB, Record),
+ true
+ end.
+
+get_user(DirData, User) ->
+ ?vtrace("get_user -> entry with:"
+ "~n User: ~p",[User]),
+ PWDB = httpd_util:key1search(DirData, auth_user_file),
+ case ets:lookup(PWDB, User) of
+ [{User, PassWd, Data}] ->
+ {ok, #httpd_user{username=User, password=PassWd, user_data=Data}};
+ _ ->
+ {error, no_such_user}
+ end.
+
+list_users(DirData) ->
+ PWDB = httpd_util:key1search(DirData, auth_user_file),
+ case ets:match(PWDB, '$1') of
+ Records when list(Records) ->
+ {ok, lists:foldr(fun({User,PassWd,Data}, A) -> [User|A] end,
+ [], lists:flatten(Records))};
+ O ->
+ {ok, []}
+ end.
+
+delete_user(DirData, UserName) ->
+ ?vtrace("delete_user -> entry with:"
+ "~n UserName: ~p",[UserName]),
+ PWDB = httpd_util:key1search(DirData, auth_user_file),
+ case ets:lookup(PWDB, UserName) of
+ [{UserName, SomePassword, SomeData}] ->
+ ets:delete(PWDB, UserName),
+ case list_groups(DirData) of
+ {ok,Groups}->
+ lists:foreach(fun(Group) ->
+ delete_group_member(DirData, Group, UserName)
+ end,Groups),
+ true;
+ _->
+ true
+ end;
+ _ ->
+ {error, no_such_user}
+ end.
+
+%%
+%% Storage of groups in the ets table:
+%% {Group, UserList} where UserList is a list of strings.
+%%
+
+add_group_member(DirData, Group, UserName) ->
+ ?DEBUG("add_group_members -> ~n"
+ " Group: ~p~n"
+ " UserName: ~p",[Group,UserName]),
+ GDB = httpd_util:key1search(DirData, auth_group_file),
+ case ets:lookup(GDB, Group) of
+ [{Group, Users}] ->
+ case lists:member(UserName, Users) of
+ true ->
+ ?DEBUG("add_group_members -> already member in group",[]),
+ true;
+ false ->
+ ?DEBUG("add_group_members -> add",[]),
+ ets:insert(GDB, {Group, [UserName|Users]}),
+ true
+ end;
+ [] ->
+ ?DEBUG("add_group_members -> create grouo",[]),
+ ets:insert(GDB, {Group, [UserName]}),
+ true;
+ Other ->
+ ?ERROR("add_group_members -> Other: ~p",[Other]),
+ {error, Other}
+ end.
+
+list_group_members(DirData, Group) ->
+ ?DEBUG("list_group_members -> Group: ~p",[Group]),
+ GDB = httpd_util:key1search(DirData, auth_group_file),
+ case ets:lookup(GDB, Group) of
+ [{Group, Users}] ->
+ ?DEBUG("list_group_members -> Users: ~p",[Users]),
+ {ok, Users};
+ _ ->
+ {error, no_such_group}
+ end.
+
+list_groups(DirData) ->
+ ?DEBUG("list_groups -> entry",[]),
+ GDB = httpd_util:key1search(DirData, auth_group_file),
+ case ets:match(GDB, '$1') of
+ [] ->
+ ?DEBUG("list_groups -> []",[]),
+ {ok, []};
+ Groups0 when list(Groups0) ->
+ ?DEBUG("list_groups -> Groups0: ~p",[Groups0]),
+ {ok, httpd_util:uniq(lists:foldr(fun({G, U}, A) -> [G|A] end,
+ [], lists:flatten(Groups0)))};
+ _ ->
+ {ok, []}
+ end.
+
+delete_group_member(DirData, Group, User) ->
+ ?DEBUG("list_group_members -> ~n"
+ " Group: ~p~n"
+ " User: ~p",[Group,User]),
+ GDB = httpd_util:key1search(DirData, auth_group_file),
+ UDB = httpd_util:key1search(DirData, auth_user_file),
+ case ets:lookup(GDB, Group) of
+ [{Group, Users}] when list(Users) ->
+ case lists:member(User, Users) of
+ true ->
+ ?DEBUG("list_group_members -> deleted from group",[]),
+ ets:delete(GDB, Group),
+ ets:insert(GDB, {Group, lists:delete(User, Users)}),
+ true;
+ false ->
+ ?DEBUG("list_group_members -> not member",[]),
+ {error, no_such_group_member}
+ end;
+ _ ->
+ ?ERROR("list_group_members -> no such group",[]),
+ {error, no_such_group}
+ end.
+
+delete_group(DirData, Group) ->
+ ?DEBUG("list_group_members -> Group: ~p",[Group]),
+ GDB = httpd_util:key1search(DirData, auth_group_file),
+ case ets:lookup(GDB, Group) of
+ [{Group, Users}] ->
+ ?DEBUG("list_group_members -> delete",[]),
+ ets:delete(GDB, Group),
+ true;
+ _ ->
+ ?ERROR("delete_group -> no such group",[]),
+ {error, no_such_group}
+ end.
+
+
+store_directory_data(Directory, DirData) ->
+ PWFile = httpd_util:key1search(DirData, auth_user_file),
+ GroupFile = httpd_util:key1search(DirData, auth_group_file),
+ case load_passwd(PWFile) of
+ {ok, PWDB} ->
+ case load_group(GroupFile) of
+ {ok, GRDB} ->
+ %% Address and port is included in the file names...
+ Addr = httpd_util:key1search(DirData, bind_address),
+ Port = httpd_util:key1search(DirData, port),
+ {ok, PasswdDB} = store_passwd(Addr,Port,PWDB),
+ {ok, GroupDB} = store_group(Addr,Port,GRDB),
+ NDD1 = lists:keyreplace(auth_user_file, 1, DirData,
+ {auth_user_file, PasswdDB}),
+ NDD2 = lists:keyreplace(auth_group_file, 1, NDD1,
+ {auth_group_file, GroupDB}),
+ {ok, NDD2};
+ Err ->
+ ?ERROR("failed storing directory data: "
+ "load group error: ~p",[Err]),
+ {error, Err}
+ end;
+ Err2 ->
+ ?ERROR("failed storing directory data: "
+ "load passwd error: ~p",[Err2]),
+ {error, Err2}
+ end.
+
+
+
+%% load_passwd
+
+load_passwd(AuthUserFile) ->
+ case file:open(AuthUserFile, [read]) of
+ {ok,Stream} ->
+ parse_passwd(Stream, []);
+ {error, _} ->
+ {error, ?NICE("Can't open "++AuthUserFile)}
+ end.
+
+parse_passwd(Stream,PasswdList) ->
+ Line =
+ case io:get_line(Stream, '') of
+ eof ->
+ eof;
+ String ->
+ httpd_conf:clean(String)
+ end,
+ parse_passwd(Stream, PasswdList, Line).
+
+parse_passwd(Stream, PasswdList, eof) ->
+ file:close(Stream),
+ {ok, PasswdList};
+parse_passwd(Stream, PasswdList, "") ->
+ parse_passwd(Stream, PasswdList);
+parse_passwd(Stream, PasswdList, [$#|_]) ->
+ parse_passwd(Stream, PasswdList);
+parse_passwd(Stream, PasswdList, Line) ->
+ case regexp:split(Line,":") of
+ {ok, [User,Password]} ->
+ parse_passwd(Stream, [{User,Password, []}|PasswdList]);
+ {ok,_} ->
+ {error, ?NICE(Line)}
+ end.
+
+%% load_group
+
+load_group(AuthGroupFile) ->
+ case file:open(AuthGroupFile, [read]) of
+ {ok, Stream} ->
+ parse_group(Stream,[]);
+ {error, _} ->
+ {error, ?NICE("Can't open "++AuthGroupFile)}
+ end.
+
+parse_group(Stream, GroupList) ->
+ Line=
+ case io:get_line(Stream,'') of
+ eof ->
+ eof;
+ String ->
+ httpd_conf:clean(String)
+ end,
+ parse_group(Stream, GroupList, Line).
+
+parse_group(Stream, GroupList, eof) ->
+ file:close(Stream),
+ {ok, GroupList};
+parse_group(Stream, GroupList, "") ->
+ parse_group(Stream, GroupList);
+parse_group(Stream, GroupList, [$#|_]) ->
+ parse_group(Stream, GroupList);
+parse_group(Stream, GroupList, Line) ->
+ case regexp:split(Line, ":") of
+ {ok, [Group,Users]} ->
+ {ok, UserList} = regexp:split(Users," "),
+ parse_group(Stream, [{Group,UserList}|GroupList]);
+ {ok, _} ->
+ {error, ?NICE(Line)}
+ end.
+
+
+%% store_passwd
+
+store_passwd(Addr,Port,PasswdList) ->
+ Name = httpd_util:make_name("httpd_passwd",Addr,Port),
+ PasswdDB = ets:new(Name, [set, public]),
+ store_passwd(PasswdDB, PasswdList).
+
+store_passwd(PasswdDB, []) ->
+ {ok, PasswdDB};
+store_passwd(PasswdDB, [User|Rest]) ->
+ ets:insert(PasswdDB, User),
+ store_passwd(PasswdDB, Rest).
+
+%% store_group
+
+store_group(Addr,Port,GroupList) ->
+ Name = httpd_util:make_name("httpd_group",Addr,Port),
+ GroupDB = ets:new(Name, [set, public]),
+ store_group(GroupDB, GroupList).
+
+
+store_group(GroupDB,[]) ->
+ {ok, GroupDB};
+store_group(GroupDB,[User|Rest]) ->
+ ets:insert(GroupDB, User),
+ store_group(GroupDB, Rest).
+
+
+%% remove/1
+%%
+%% Deletes ets tables used by this auth mod.
+%%
+remove(DirData) ->
+ PWDB = httpd_util:key1search(DirData, auth_user_file),
+ GDB = httpd_util:key1search(DirData, auth_group_file),
+ ets:delete(PWDB),
+ ets:delete(GDB).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth_server.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth_server.erl
new file mode 100644
index 0000000000..59402ac169
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_auth_server.erl
@@ -0,0 +1,422 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_auth_server.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
+%%
+
+-module(mod_auth_server).
+
+-include("httpd.hrl").
+%% -include("mod_auth.hrl").
+-include("httpd_verbosity.hrl").
+
+-behaviour(gen_server).
+
+
+%% mod_auth exports
+-export([start/2, stop/2,
+ add_password/4, update_password/5,
+ add_user/5, delete_user/5, get_user/5, list_users/4,
+ add_group_member/6, delete_group_member/6, list_group_members/5,
+ delete_group/5, list_groups/4]).
+
+%% Management exports
+-export([verbosity/3]).
+
+%% gen_server exports
+-export([start_link/3,
+ init/1,
+ handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+
+-record(state,{tab}).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% External API %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% start_link/3
+%%
+%% NOTE: This is called by httpd_misc_sup when the process is started
+%%
+start_link(Addr, Port, Verbosity)->
+ ?vlog("start_link -> entry with"
+ "~n Addr: ~p"
+ "~n Port: ~p", [Addr, Port]),
+ Name = make_name(Addr, Port),
+ gen_server:start_link({local, Name}, ?MODULE, [Verbosity],
+ [{timeout, infinity}]).
+
+
+%% start/2
+
+start(Addr, Port)->
+ ?vtrace("start -> entry with"
+ "~n Addr: ~p"
+ "~n Port: ~p", [Addr, Port]),
+ Name = make_name(Addr, Port),
+ case whereis(Name) of
+ undefined ->
+ Verbosity = get(auth_verbosity),
+ case (catch httpd_misc_sup:start_auth_server(Addr, Port,
+ Verbosity)) of
+ {ok, Pid} ->
+ put(auth_server, Pid),
+ ok;
+ {error, Reason} ->
+ exit({failed_start_auth_server, Reason});
+ Error ->
+ exit({failed_start_auth_server, Error})
+ end;
+ _ -> %% Already started...
+ ok
+ end.
+
+
+%% stop/2
+
+stop(Addr, Port)->
+ ?vtrace("stop -> entry with"
+ "~n Addr: ~p"
+ "~n Port: ~p", [Addr, Port]),
+ Name = make_name(Addr, Port),
+ case whereis(Name) of
+ undefined -> %% Already stopped
+ ok;
+ _ ->
+ (catch httpd_misc_sup:stop_auth_server(Addr, Port))
+ end.
+
+
+%% verbosity/3
+
+verbosity(Addr, Port, Verbosity) ->
+ Name = make_name(Addr, Port),
+ Req = {verbosity, Verbosity},
+ call(Name, Req).
+
+
+%% add_password/4
+
+add_password(Addr, Port, Dir, Password)->
+ Name = make_name(Addr, Port),
+ Req = {add_password, Dir, Password},
+ call(Name, Req).
+
+
+%% update_password/6
+
+update_password(Addr, Port, Dir, Old, New) when list(New) ->
+ Name = make_name(Addr, Port),
+ Req = {update_password, Dir, Old, New},
+ call(Name, Req).
+
+
+%% add_user/5
+
+add_user(Addr, Port, Dir, User, Password) ->
+ Name = make_name(Addr, Port),
+ Req = {add_user, Addr, Port, Dir, User, Password},
+ call(Name, Req).
+
+
+%% delete_user/5
+
+delete_user(Addr, Port, Dir, UserName, Password) ->
+ Name = make_name(Addr, Port),
+ Req = {delete_user, Addr, Port, Dir, UserName, Password},
+ call(Name, Req).
+
+
+%% get_user/5
+
+get_user(Addr, Port, Dir, UserName, Password) ->
+ Name = make_name(Addr, Port),
+ Req = {get_user, Addr, Port, Dir, UserName, Password},
+ call(Name, Req).
+
+
+%% list_users/4
+
+list_users(Addr, Port, Dir, Password) ->
+ Name = make_name(Addr,Port),
+ Req = {list_users, Addr, Port, Dir, Password},
+ call(Name, Req).
+
+
+%% add_group_member/6
+
+add_group_member(Addr, Port, Dir, GroupName, UserName, Password) ->
+ Name = make_name(Addr,Port),
+ Req = {add_group_member, Addr, Port, Dir, GroupName, UserName, Password},
+ call(Name, Req).
+
+
+%% delete_group_member/6
+
+delete_group_member(Addr, Port, Dir, GroupName, UserName, Password) ->
+ Name = make_name(Addr,Port),
+ Req = {delete_group_member, Addr, Port, Dir, GroupName, UserName, Password},
+ call(Name, Req).
+
+
+%% list_group_members/4
+
+list_group_members(Addr, Port, Dir, Group, Password) ->
+ Name = make_name(Addr, Port),
+ Req = {list_group_members, Addr, Port, Dir, Group, Password},
+ call(Name, Req).
+
+
+%% delete_group/5
+
+delete_group(Addr, Port, Dir, GroupName, Password) ->
+ Name = make_name(Addr, Port),
+ Req = {delete_group, Addr, Port, Dir, GroupName, Password},
+ call(Name, Req).
+
+
+%% list_groups/4
+
+list_groups(Addr, Port, Dir, Password) ->
+ Name = make_name(Addr, Port),
+ Req = {list_groups, Addr, Port, Dir, Password},
+ call(Name, Req).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% Server call-back functions %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% init
+
+init([undefined]) ->
+ init([?default_verbosity]);
+
+init([Verbosity]) ->
+ put(sname,auth),
+ put(verbosity,Verbosity),
+ ?vlog("starting",[]),
+ {ok,#state{tab = ets:new(auth_pwd,[set,protected])}}.
+
+
+%% handle_call
+
+%% Add a user
+handle_call({add_user, Addr, Port, Dir, User, AuthPwd}, _From, State) ->
+ Reply = api_call(Addr, Port, Dir, add_user, User, AuthPwd, State),
+ {reply, Reply, State};
+
+%% Get data about a user
+handle_call({get_user, Addr, Port, Dir, User, AuthPwd}, _From, State) ->
+ Reply = api_call(Addr, Port, Dir, get_user, [User], AuthPwd, State),
+ {reply, Reply, State};
+
+%% Add a group member
+handle_call({add_group_member, Addr, Port, Dir, Group, User, AuthPwd},
+ _From, State) ->
+ Reply = api_call(Addr, Port, Dir, add_group_member, [Group, User],
+ AuthPwd, State),
+ {reply, Reply, State};
+
+%% delete a group
+handle_call({delete_group_member, Addr, Port, Dir, Group, User, AuthPwd},
+ _From, State)->
+ Reply = api_call(Addr, Port, Dir, delete_group_member, [Group, User],
+ AuthPwd, State),
+ {reply, Reply, State};
+
+%% List all users thats standalone users
+handle_call({list_users, Addr, Port, Dir, AuthPwd}, _From, State)->
+ Reply = api_call(Addr, Port, Dir, list_users, [], AuthPwd, State),
+ {reply, Reply, State};
+
+%% Delete a user
+handle_call({delete_user, Addr, Port, Dir, User, AuthPwd}, _From, State)->
+ Reply = api_call(Addr, Port, Dir, delete_user, [User], AuthPwd, State),
+ {reply, Reply, State};
+
+%% Delete a group
+handle_call({delete_group, Addr, Port, Dir, Group, AuthPwd}, _From, State)->
+ Reply = api_call(Addr, Port, Dir, delete_group, [Group], AuthPwd, State),
+ {reply, Reply, State};
+
+%% List the current groups
+handle_call({list_groups, Addr, Port, Dir, AuthPwd}, _From, State)->
+ Reply = api_call(Addr, Port, Dir, list_groups, [], AuthPwd, State),
+ {reply, Reply, State};
+
+%% List the members of the given group
+handle_call({list_group_members, Addr, Port, Dir, Group, AuthPwd},
+ _From, State)->
+ Reply = api_call(Addr, Port, Dir, list_group_members, [Group],
+ AuthPwd, State),
+ {reply, Reply, State};
+
+
+%% Add password for a directory
+handle_call({add_password, Dir, Password}, _From, State)->
+ Reply = do_add_password(Dir, Password, State),
+ {reply, Reply, State};
+
+
+%% Update the password for a directory
+
+handle_call({update_password, Dir, Old, New},_From,State)->
+ Reply =
+ case getPassword(State, Dir) of
+ OldPwd when binary(OldPwd)->
+ case erlang:md5(Old) of
+ OldPwd ->
+ %% The old password is right =>
+ %% update the password to the new
+ do_update_password(Dir,New,State),
+ ok;
+ _->
+ {error, error_new}
+ end;
+ _->
+ {error, error_old}
+ end,
+ {reply, Reply, State};
+
+handle_call(stop, _From, State)->
+ {stop, normal, State};
+
+handle_call({verbosity,Verbosity},_From,State)->
+ OldVerbosity = put(verbosity,Verbosity),
+ ?vlog("set verbosity: ~p -> ~p",[Verbosity,OldVerbosity]),
+ {reply,OldVerbosity,State}.
+
+handle_info(Info,State)->
+ {noreply,State}.
+
+handle_cast(Request,State)->
+ {noreply,State}.
+
+
+terminate(Reason,State) ->
+ ets:delete(State#state.tab),
+ ok.
+
+
+%% code_change({down, ToVsn}, State, Extra)
+%%
+code_change({down, _}, #state{tab = Tab}, downgrade_to_2_6_0) ->
+ ?vlog("downgrade to 2.6.0", []),
+ {ok, {state, Tab, undefined}};
+
+
+%% code_change(FromVsn, State, Extra)
+%%
+code_change(_, {state, Tab, _}, upgrade_from_2_6_0) ->
+ ?vlog("upgrade from 2.6.0", []),
+ {ok, #state{tab = Tab}}.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% The functions that really changes the data in the database %%
+%% of users to different directories %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% API gateway
+
+api_call(Addr, Port, Dir, Func, Args,Password,State) ->
+ case controlPassword(Password,State,Dir) of
+ ok->
+ ConfigName = httpd_util:make_name("httpd_conf",Addr,Port),
+ case ets:match_object(ConfigName, {directory, Dir, '$1'}) of
+ [{directory, Dir, DirData}] ->
+ AuthMod = auth_mod_name(DirData),
+ ?DEBUG("api_call -> call ~p:~p",[AuthMod,Func]),
+ Ret = (catch apply(AuthMod, Func, [DirData|Args])),
+ ?DEBUG("api_call -> Ret: ~p",[ret]),
+ Ret;
+ O ->
+ ?DEBUG("api_call -> O: ~p",[O]),
+ {error, no_such_directory}
+ end;
+ bad_password ->
+ {error,bad_password}
+ end.
+
+controlPassword(Password,State,Dir)when Password=:="DummyPassword"->
+ bad_password;
+
+controlPassword(Password,State,Dir)->
+ case getPassword(State,Dir) of
+ Pwd when binary(Pwd)->
+ case erlang:md5(Password) of
+ Pwd ->
+ ok;
+ _->
+ bad_password
+ end;
+ _ ->
+ bad_password
+ end.
+
+
+getPassword(State,Dir)->
+ case lookup(State#state.tab, Dir) of
+ [{_,Pwd}]->
+ Pwd;
+ _ ->
+ {error,bad_password}
+ end.
+
+do_update_password(Dir, New, State) ->
+ ets:insert(State#state.tab, {Dir, erlang:md5(New)}).
+
+do_add_password(Dir, Password, State) ->
+ case getPassword(State,Dir) of
+ PwdExists when binary(PwdExists) ->
+ {error, dir_protected};
+ {error, _} ->
+ do_update_password(Dir, Password, State)
+ end.
+
+
+auth_mod_name(DirData) ->
+ case httpd_util:key1search(DirData, auth_type, plain) of
+ plain -> mod_auth_plain;
+ mnesia -> mod_auth_mnesia;
+ dets -> mod_auth_dets
+ end.
+
+
+lookup(Db, Key) ->
+ ets:lookup(Db, Key).
+
+
+make_name(Addr,Port) ->
+ httpd_util:make_name("httpd_auth",Addr,Port).
+
+
+call(Name, Req) ->
+ case (catch gen_server:call(Name, Req)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Reply ->
+ Reply
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_browser.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_browser.erl
new file mode 100644
index 0000000000..1153a5fc47
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_browser.erl
@@ -0,0 +1,213 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_browser.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
+%%
+%% ----------------------------------------------------------------------
+%%
+%% Browsers sends a string to the webbserver
+%% to identify themsevles. They are a bit nasty
+%% since the only thing that the specification really
+%% is strict about is that they shall be short
+%% tree axamples:
+%%
+%% Netscape Mozilla/4.75 [en] (X11; U; SunOS 5.8 sun4u)
+%% IE5 Mozilla/4.0 (compatible; MSIE 5.0; SP1B; SunOS 5.8 sun4u; X11)
+%% Lynx Lynx/2.8.3rel.1 libwww-FM/2.142
+%%
+%% ----------------------------------------------------------------------
+
+-module(mod_browser).
+
+%% Remember that the order of the mozilla browsers are
+%% important since some browsers include others to behave
+%% as they were something else
+-define(MOZILLA_BROWSERS,[{opera,"opera"},{msie,"msie"}]).
+
+
+%% If your operatingsystem is not recognized add it to this list.
+-define(OPERATIVE_SYSTEMS,[{win3x,["win16","windows 3","windows 16-bit"]},
+ {win95,["win95","windows 95"]},
+ {win98,["win98", "windows 98"]},
+ {winnt,["winnt", "windows nt"]},
+ {win2k,["nt 5"]},
+ {sunos4,["sunos 4"]},
+ {sunos5,["sunos 5"]},
+ {sun,["sunos"]},
+ {aix,["aix"]},
+ {linux,["linux"]},
+ {sco,["sco","unix_sv"]},
+ {freebsd,["freebsd"]},
+ {bsd,["bsd"]}]).
+
+-define(LYNX,lynx).
+-define(MOZILLA,mozilla).
+-define(EMACS,emacs).
+-define(STAROFFICE,soffice).
+-define(MOSAIC,mosaic).
+-define(NETSCAPE,netscape).
+-define(UNKOWN,unknown).
+
+-include("httpd.hrl").
+
+-export([do/1, test/0, getBrowser/1]).
+
+
+do(Info) ->
+ case httpd_util:key1search(Info#mod.data,status) of
+ {Status_code,PhraseArgs,Reason} ->
+ {proceed,Info#mod.data};
+ undefined ->
+ {proceed,[{'user-agent',getBrowser1(Info)}|Info#mod.data]}
+ end.
+
+getBrowser1(Info) ->
+ PHead=Info#mod.parsed_header,
+ case httpd_util:key1search(PHead,"User-Agent") of
+ undefined->
+ undefined;
+ AgentString ->
+ getBrowser(AgentString)
+ end.
+
+getBrowser(AgentString) ->
+ LAgentString = httpd_util:to_lower(AgentString),
+ case regexp:first_match(LAgentString,"^[^ ]*") of
+ {match,Start,Length} ->
+ Browser=lists:sublist(LAgentString,Start,Length),
+ case browserType(Browser) of
+ {mozilla,Vsn} ->
+ {getMozilla(LAgentString,
+ ?MOZILLA_BROWSERS,{?NETSCAPE,Vsn}),
+ operativeSystem(LAgentString)};
+ AnyBrowser ->
+ {AnyBrowser,operativeSystem(LAgentString)}
+ end;
+ nomatch ->
+ browserType(LAgentString)
+ end.
+
+browserType([$l,$y,$n,$x|Version]) ->
+ {?LYNX,browserVersion(Version)};
+browserType([$m,$o,$z,$i,$l,$l,$a|Version]) ->
+ {?MOZILLA,browserVersion(Version)};
+browserType([$e,$m,$a,$c,$s|Version]) ->
+ {?EMACS,browserVersion(Version)};
+browserType([$e,$t,$a,$r,$o,$f,$f,$i,$c,$e|Version]) ->
+ {?STAROFFICE,browserVersion(Version)};
+browserType([$m,$o,$s,$a,$i,$c|Version]) ->
+ {?MOSAIC,browserVersion(Version)};
+browserType(Unknown)->
+ unknown.
+
+
+browserVersion([$/|VsnString]) ->
+ case catch list_to_float(VsnString) of
+ Number when float(Number) ->
+ Number;
+ Whatever ->
+ case string:span(VsnString,"1234567890.") of
+ 0 ->
+ unknown;
+ VLength ->
+ Vsn = string:substr(VsnString,1,VLength),
+ case string:tokens(Vsn,".") of
+ [Number] ->
+ list_to_float(Number++".0");
+ [Major,Minor|_MinorMinor] ->
+ list_to_float(Major++"."++Minor)
+ end
+ end
+ end;
+browserVersion(VsnString) ->
+ browserVersion([$/|VsnString]).
+
+operativeSystem(OpString) ->
+ operativeSystem(OpString, ?OPERATIVE_SYSTEMS).
+
+operativeSystem(OpString,[]) ->
+ unknown;
+operativeSystem(OpString,[{RetVal,RegExps}|Rest]) ->
+ case controlOperativeSystem(OpString,RegExps) of
+ true->
+ RetVal;
+ _ ->
+ operativeSystem(OpString,Rest)
+ end.
+
+controlOperativeSystem(OpString,[]) ->
+ false;
+controlOperativeSystem(OpString,[Regexp|Regexps]) ->
+ case regexp:match(OpString,Regexp) of
+ {match,_,_}->
+ true;
+ nomatch->
+ controlOperativeSystem(OpString,Regexps)
+ end.
+
+
+%% OK this is ugly but thats the only way since
+%% all browsers dont conform to the name/vsn standard
+%% First we check if it is one of the browsers that
+%% not are the default mozillaborwser against the regexp
+%% for the different browsers. if no match it a mozilla
+%% browser i.e opera netscape or internet explorer
+
+getMozilla(AgentString,[],Default) ->
+ Default;
+getMozilla(AgentString,[{Agent,AgentRegExp}|Rest],Default) ->
+ case regexp:match(AgentString,AgentRegExp) of
+ {match,_,_} ->
+ {Agent,getVersion(AgentString,AgentRegExp)};
+ nomatch ->
+ getMozilla(AgentString,Rest,Default)
+ end.
+
+getVersion(AgentString,AgentRegExp) ->
+ case regexp:match(AgentString,AgentRegExp++"[0-9\.\ ]*") of
+ {match,Start,Length} when length(AgentRegExp) < Length ->
+ %% Ok we got the number split it out
+ RealStart=Start+length(AgentRegExp),
+ RealLength=Length-length(AgentRegExp),
+ VsnString=string:substr(AgentString,RealStart,RealLength),
+ case string:strip(VsnString,both,$\ ) of
+ [] ->
+ unknown;
+ Vsn ->
+ case string:tokens(Vsn,".") of
+ [Number]->
+ list_to_float(Number++".0");
+ [Major,Minor|_MinorMinor]->
+ list_to_float(Major++"."++Minor)
+ end
+ end;
+ nomatch ->
+ unknown
+ end.
+
+
+test()->
+ io:format("~n--------------------------------------------------------~n"),
+ Res1=getBrowser("Mozilla/4.75 [en] (X11; U; SunOS 5.8 sun4u)"),
+ io:format("~p",[Res1]),
+ io:format("~n--------------------------------------------------------~n"),
+ io:format("~n--------------------------------------------------------~n"),
+ Res2=getBrowser("Mozilla/4.0 (compatible; MSIE 5.0; SP1B; SunOS 5.8 sun4u; X11)"),
+ io:format("~p",[Res2]),
+ io:format("~n--------------------------------------------------------~n"),
+ io:format("~n--------------------------------------------------------~n"),
+ Res3=getBrowser("Lynx/2.8.3rel.1 libwww-FM/2.142"),
+ io:format("~p",[Res3]),
+ io:format("~n--------------------------------------------------------~n").
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_cgi.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_cgi.erl
new file mode 100644
index 0000000000..d3f67eb77a
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_cgi.erl
@@ -0,0 +1,692 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_cgi.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
+%%
+-module(mod_cgi).
+-export([do/1,env/3,status_code/1,load/2]).
+
+%%Exports to the interface for sending chunked data
+%% to http/1.1 users and full responses to http/1.0
+-export([send/5,final_send/4, update_status_code/2,get_new_size/2]).
+-include("httpd.hrl").
+
+-define(VMODULE,"CGI").
+-include("httpd_verbosity.hrl").
+
+-define(GATEWAY_INTERFACE,"CGI/1.1").
+-define(DEFAULT_CGI_TIMEOUT,15000).
+
+%% do
+
+do(Info) ->
+ ?vtrace("do",[]),
+ case httpd_util:key1search(Info#mod.data,status) of
+ %% A status code has been generated!
+ {StatusCode, PhraseArgs, Reason} ->
+ {proceed, Info#mod.data};
+ %% No status code has been generated!
+ undefined ->
+ ?vtrace("do -> no status code has been generated", []),
+ case httpd_util:key1search(Info#mod.data,response) of
+ %% No response has been generated!
+ undefined ->
+ ?vtrace("do -> no response has been generated", []),
+ RequestURI =
+ case httpd_util:key1search(Info#mod.data,
+ new_request_uri) of
+ undefined ->
+ Info#mod.request_uri;
+ Value ->
+ Value
+ end,
+ ?vtrace("do -> RequestURI: ~p", [RequestURI]),
+ ScriptAliases =
+ httpd_util:multi_lookup(Info#mod.config_db,
+ script_alias),
+ ?vtrace("do -> ScriptAliases: ~p", [ScriptAliases]),
+ case mod_alias:real_script_name(Info#mod.config_db,
+ RequestURI,
+ ScriptAliases) of
+ {Script, AfterScript} ->
+ exec_script(Info, Script, AfterScript, RequestURI);
+ not_a_script ->
+ {proceed,Info#mod.data}
+ end;
+ %% A response has been generated or sent!
+ Response ->
+ {proceed,Info#mod.data}
+ end
+ end.
+
+
+%% is_executable(File) ->
+%% ?DEBUG("is_executable -> entry with~n"
+%% " File: ~s",[File]),
+%% Dir = filename:dirname(File),
+%% FileName = filename:basename(File),
+%% is_executable(FileName,Dir).
+%%
+%% is_executable(FileName,Dir) ->
+%% ?DEBUG("is_executable -> entry with~n"
+%% " Dir: ~s~n"
+%% " FileName: ~s",[Dir,FileName]),
+%% case os:find_executable(FileName, Dir) of
+%% false ->
+%% false;
+%% _ ->
+%% true
+%% end.
+
+
+%% -------------------------
+%% Start temporary (hopefully) fix for win32
+%% OTP-3627
+%%
+
+is_executable(File) ->
+ Dir = filename:dirname(File),
+ FileName = filename:basename(File),
+ case os:type() of
+ {win32,_} ->
+ is_win32_executable(Dir,FileName);
+ _ ->
+ is_other_executable(Dir,FileName)
+ end.
+
+
+is_win32_executable(D,F) ->
+ case ends_with(F,[".bat",".exe",".com"]) of
+ false ->
+ %% This is why we cant use 'os:find_executable' directly.
+ %% It assumes that executable files is given without extension
+ case os:find_executable(F,D) of
+ false ->
+ false;
+ _ ->
+ true
+ end;
+ true ->
+ case file:read_file_info(D ++ "/" ++ F) of
+ {ok,_} ->
+ true;
+ _ ->
+ false
+ end
+ end.
+
+
+is_other_executable(D,F) ->
+ case os:find_executable(F,D) of
+ false ->
+ false;
+ _ ->
+ true
+ end.
+
+
+ends_with(File,[]) ->
+ false;
+ends_with(File,[Ext|Rest]) ->
+ case ends_with1(File,Ext) of
+ true ->
+ true;
+ false ->
+ ends_with(File,Rest)
+ end.
+
+ends_with1(S,E) when length(S) >= length(E) ->
+ case to_lower(string:right(S,length(E))) of
+ E ->
+ true;
+ _ ->
+ false
+ end;
+ends_with1(_S,_E) ->
+ false.
+
+
+to_lower(S) -> to_lower(S,[]).
+
+to_lower([],L) -> lists:reverse(L);
+to_lower([H|T],L) -> to_lower(T,[to_lower1(H)|L]).
+
+to_lower1(C) when C >= $A, C =< $Z ->
+ C + ($a - $A);
+to_lower1(C) ->
+ C.
+
+%%
+%% End fix
+%% ---------------------------------
+
+
+env(VarName, Value) ->
+ {VarName, Value}.
+
+env(Info, Script, AfterScript) ->
+ ?vtrace("env -> entry with"
+ "~n Script: ~p"
+ "~n AfterScript: ~p",
+ [Script, AfterScript]),
+ {_, RemoteAddr} = (Info#mod.init_data)#init_data.peername,
+ ServerName = (Info#mod.init_data)#init_data.resolve,
+ PH = parsed_header(Info#mod.parsed_header),
+ Env =
+ [env("SERVER_SOFTWARE",?SERVER_SOFTWARE),
+ env("SERVER_NAME",ServerName),
+ env("GATEWAY_INTERFACE",?GATEWAY_INTERFACE),
+ env("SERVER_PROTOCOL",?SERVER_PROTOCOL),
+ env("SERVER_PORT",
+ integer_to_list(httpd_util:lookup(Info#mod.config_db,port,80))),
+ env("REQUEST_METHOD",Info#mod.method),
+ env("REMOTE_ADDR",RemoteAddr),
+ env("SCRIPT_NAME",Script)],
+ Env1 =
+ case Info#mod.method of
+ "GET" ->
+ case AfterScript of
+ {[], QueryString} ->
+ [env("QUERY_STRING", QueryString)|Env];
+ {PathInfo, []} ->
+ Aliases = httpd_util:multi_lookup(
+ Info#mod.config_db,alias),
+ {_, PathTranslated, _} =
+ mod_alias:real_name(
+ Info#mod.config_db, PathInfo, Aliases),
+ [Env|
+ [env("PATH_INFO","/"++httpd_util:decode_hex(PathInfo)),
+ env("PATH_TRANSLATED",PathTranslated)]];
+ {PathInfo, QueryString} ->
+ Aliases = httpd_util:multi_lookup(
+ Info#mod.config_db,alias),
+ {_, PathTranslated, _} =
+ mod_alias:real_name(
+ Info#mod.config_db, PathInfo, Aliases),
+ [Env|
+ [env("PATH_INFO",
+ httpd_util:decode_hex(PathInfo)),
+ env("PATH_TRANSLATED",PathTranslated),
+ env("QUERY_STRING", QueryString)]];
+ [] ->
+ Env
+ end;
+ "POST" ->
+ [env("CONTENT_LENGTH",
+ integer_to_list(httpd_util:flatlength(
+ Info#mod.entity_body)))|Env];
+ _ ->
+ Env
+ end,
+ Env2 =
+ case httpd_util:key1search(Info#mod.data,remote_user) of
+ undefined ->
+ Env1;
+ RemoteUser ->
+ [env("REMOTE_USER",RemoteUser)|Env1] %% OTP-4416
+ end,
+ lists:flatten([Env2|PH]).
+
+
+parsed_header(List) ->
+ parsed_header(List, []).
+
+parsed_header([], SoFar) ->
+ SoFar;
+parsed_header([{Name,[Value|R1]}|R2], SoFar) when list(Value)->
+ NewName=lists:map(fun(X) -> if X == $- -> $_; true -> X end end,Name),
+ Env = env("HTTP_"++httpd_util:to_upper(NewName),
+ multi_value([Value|R1])),
+ parsed_header(R2, [Env|SoFar]);
+
+parsed_header([{Name,Value}|Rest], SoFar) ->
+ {ok,NewName,_} = regexp:gsub(Name, "-", "_"),
+ Env=env("HTTP_"++httpd_util:to_upper(NewName),Value),
+ parsed_header(Rest, [Env|SoFar]).
+
+
+multi_value([]) ->
+ [];
+multi_value([Value]) ->
+ Value;
+multi_value([Value|Rest]) ->
+ Value++", "++multi_value(Rest).
+
+
+exec_script(Info, Script, AfterScript, RequestURI) ->
+ ?vdebug("exec_script -> entry with"
+ "~n Script: ~p"
+ "~n AfterScript: ~p",
+ [Script,AfterScript]),
+ exec_script(is_executable(Script),Info,Script,AfterScript,RequestURI).
+
+exec_script(true, Info, Script, AfterScript, RequestURI) ->
+ ?vtrace("exec_script -> entry when script is executable",[]),
+ process_flag(trap_exit,true),
+ Dir = filename:dirname(Script),
+ [Script_Name|_] = string:tokens(RequestURI, "?"),
+ Env = env(Info, Script_Name, AfterScript),
+ Port = (catch open_port({spawn,Script},[stream,{cd, Dir},{env, Env}])),
+ ?vtrace("exec_script -> Port: ~w",[Port]),
+ case Port of
+ P when port(P) ->
+ %% Send entity_body to port.
+ Res = case Info#mod.entity_body of
+ [] ->
+ true;
+ EntityBody ->
+ (catch port_command(Port, EntityBody))
+ end,
+ case Res of
+ {'EXIT',Reason} ->
+ ?vlog("port send failed:"
+ "~n Port: ~p"
+ "~n URI: ~p"
+ "~n Reason: ~p",
+ [Port,Info#mod.request_uri,Reason]),
+ exit({open_cmd_failed,Reason,
+ [{mod,?MODULE},{port,Port},
+ {uri,Info#mod.request_uri},
+ {script,Script},{env,Env},{dir,Dir},
+ {ebody_size,sz(Info#mod.entity_body)}]});
+ true ->
+ proxy(Info, Port)
+ end;
+ {'EXIT',Reason} ->
+ ?vlog("open port failed: exit"
+ "~n URI: ~p"
+ "~n Reason: ~p",
+ [Info#mod.request_uri,Reason]),
+ exit({open_port_failed,Reason,
+ [{mod,?MODULE},{uri,Info#mod.request_uri},{script,Script},
+ {env,Env},{dir,Dir}]});
+ O ->
+ ?vlog("open port failed: unknown result"
+ "~n URI: ~p"
+ "~n O: ~p",
+ [Info#mod.request_uri,O]),
+ exit({open_port_failed,O,
+ [{mod,?MODULE},{uri,Info#mod.request_uri},{script,Script},
+ {env,Env},{dir,Dir}]})
+ end;
+
+exec_script(false,Info,Script,_AfterScript,_RequestURI) ->
+ ?vlog("script ~s not executable",[Script]),
+ {proceed,
+ [{status,
+ {404,Info#mod.request_uri,
+ ?NICE("You don't have permission to execute " ++
+ Info#mod.request_uri ++ " on this server")}}|
+ Info#mod.data]}.
+
+
+
+%%
+%% Socket <-> Port communication
+%%
+
+proxy(#mod{config_db = ConfigDb} = Info, Port) ->
+ Timeout = httpd_util:lookup(ConfigDb, cgi_timeout, ?DEFAULT_CGI_TIMEOUT),
+ proxy(Info, Port, 0, undefined,[], Timeout).
+
+proxy(Info, Port, Size, StatusCode, AccResponse, Timeout) ->
+ ?vdebug("proxy -> entry with"
+ "~n Size: ~p"
+ "~n StatusCode ~p"
+ "~n Timeout: ~p",
+ [Size, StatusCode, Timeout]),
+ receive
+ {Port, {data, Response}} when port(Port) ->
+ ?vtrace("proxy -> got some data from the port",[]),
+
+ NewStatusCode = update_status_code(StatusCode, Response),
+
+ ?vtrace("proxy -> NewStatusCode: ~p",[NewStatusCode]),
+ case send(Info, NewStatusCode, Response, Size, AccResponse) of
+ socket_closed ->
+ ?vtrace("proxy -> socket closed: kill port",[]),
+ (catch port_close(Port)), % KILL the port !!!!
+ process_flag(trap_exit,false),
+ {proceed,
+ [{response,{already_sent,200,Size}}|Info#mod.data]};
+
+ head_sent ->
+ ?vtrace("proxy -> head sent: kill port",[]),
+ (catch port_close(Port)), % KILL the port !!!!
+ process_flag(trap_exit,false),
+ {proceed,
+ [{response,{already_sent,200,Size}}|Info#mod.data]};
+
+ {http_response, NewAccResponse} ->
+ ?vtrace("proxy -> head response: continue",[]),
+ NewSize = get_new_size(Size, Response),
+ proxy(Info, Port, NewSize, NewStatusCode,
+ NewAccResponse, Timeout);
+
+ _ ->
+ ?vtrace("proxy -> continue",[]),
+ %% The data is sent and the socket is not closed, continue
+ NewSize = get_new_size(Size, Response),
+ proxy(Info, Port, NewSize, NewStatusCode,
+ "nonempty", Timeout)
+ end;
+
+ {'EXIT', Port, normal} when port(Port) ->
+ ?vtrace("proxy -> exit signal from port: normal",[]),
+ NewStatusCode = update_status_code(StatusCode,AccResponse),
+ final_send(Info,NewStatusCode,Size,AccResponse),
+ process_flag(trap_exit,false),
+ {proceed, [{response,{already_sent,200,Size}}|Info#mod.data]};
+
+ {'EXIT', Port, Reason} when port(Port) ->
+ ?vtrace("proxy -> exit signal from port: ~p",[Reason]),
+ process_flag(trap_exit, false),
+ {proceed, [{status,{400,none,reason(Reason)}}|Info#mod.data]};
+
+ {'EXIT', Pid, Reason} when pid(Pid) ->
+ %% This is the case that a linked process has died,
+ %% It would be nice to response with a server error
+ %% but since the heade alredy is sent
+ ?vtrace("proxy -> exit signal from ~p: ~p",[Pid, Reason]),
+ proxy(Info, Port, Size, StatusCode, AccResponse, Timeout);
+
+ %% This should not happen
+ WhatEver ->
+ ?vinfo("proxy -> received garbage: ~n~p", [WhatEver]),
+ NewStatusCode = update_status_code(StatusCode, AccResponse),
+ final_send(Info, StatusCode, Size, AccResponse),
+ process_flag(trap_exit, false),
+ {proceed, [{response,{already_sent,200,Size}}|Info#mod.data]}
+
+ after Timeout ->
+ ?vlog("proxy -> timeout",[]),
+ (catch port_close(Port)), % KILL the port !!!!
+ httpd_socket:close(Info#mod.socket_type, Info#mod.socket),
+ process_flag(trap_exit,false),
+ {proceed,[{response,{already_sent,200,Size}}|Info#mod.data]}
+ end.
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% The functions that handles the sending of the data to the client %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%----------------------------------------------------------------------
+%% Send the header the first time the size of the body is Zero
+%%----------------------------------------------------------------------
+
+send(#mod{method = "HEAD"} = Info, StatusCode, Response, 0, []) ->
+ first_handle_head_request(Info, StatusCode, Response);
+send(Info, StatusCode, Response, 0, []) ->
+ first_handle_other_request(Info, StatusCode, Response);
+
+%%----------------------------------------------------------------------
+%% The size of the body is bigger than zero =>
+%% we have a part of the body to send
+%%----------------------------------------------------------------------
+send(Info, StatusCode, Response, Size, AccResponse) ->
+ handle_other_request(Info, StatusCode, Response).
+
+
+%%----------------------------------------------------------------------
+%% The function is called the last time when the port has closed
+%%----------------------------------------------------------------------
+
+final_send(Info, StatusCode, Size, AccResponse)->
+ final_handle_other_request(Info, StatusCode).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% The code that handles the head requests %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%----------------------------------------------------------------------
+%% The request is a head request if its a HTPT/1.1 request answer to it
+%% otherwise we must collect the size of hte body before we can answer.
+%% Return Values:
+%% head_sent
+%%----------------------------------------------------------------------
+first_handle_head_request(Info, StatusCode, Response)->
+ case Info#mod.http_version of
+ "HTTP/1.1" ->
+ %% Since we have all we need to create the header create it
+ %% send it and return head_sent.
+ case httpd_util:split(Response,"\r\n\r\n|\n\n",2) of
+ {ok, [HeadEnd, Rest]} ->
+ HeadEnd1 = removeStatus(HeadEnd),
+ httpd_socket:deliver(Info#mod.socket_type,Info#mod.socket,
+ [create_header(Info,StatusCode),
+ HeadEnd1,"\r\n\r\n"]);
+ _ ->
+ httpd_socket:deliver(Info#mod.socket_type,Info#mod.socket,
+ [create_header(Info, StatusCode),
+ "Content-Type:text/html\r\n\r\n"])
+ end;
+ _ ->
+ Response1= case regexp:split(Response,"\r\n\r\n|\n\n") of
+ {ok,[HeadEnd|Rest]} ->
+ removeStatus(HeadEnd);
+ _ ->
+ ["Content-Type:text/html"]
+ end,
+ H1 = httpd_util:header(StatusCode,Info#mod.connection),
+ httpd_socket:deliver(Info#mod.socket_type,Info#mod.socket,
+ [H1,Response1,"\r\n\r\n"])
+ end,
+ head_sent.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% Handle the requests that is to the other methods %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%----------------------------------------------------------------------
+%% Create the http-response header and send it to the user if it is
+%% a http/1.1 request otherwise we must accumulate it
+%%----------------------------------------------------------------------
+first_handle_other_request(Info,StatusCode,Response)->
+ Header = create_header(Info,StatusCode),
+ Response1 =
+ case httpd_util:split(Response,"\r\n\r\n|\n\n",2) of
+ {ok,[HeadPart,[]]} ->
+ [Header, removeStatus(HeadPart),"\r\n\r\n"];
+
+ {ok,[HeadPart,BodyPart]} ->
+ [Header, removeStatus(HeadPart), "\r\n\r\n",
+ httpd_util:integer_to_hexlist(length(BodyPart)),
+ "\r\n", BodyPart];
+ _WhatEver ->
+ %% No response header field from the cgi-script,
+ %% Just a body
+ [Header, "Content-Type:text/html","\r\n\r\n",
+ httpd_util:integer_to_hexlist(length(Response)),
+ "\r\n", Response]
+ end,
+ httpd_socket:deliver(Info#mod.socket_type,Info#mod.socket, Response1).
+
+
+handle_other_request(#mod{http_version = "HTTP/1.1",
+ socket_type = Type, socket = Sock} = Info,
+ StatusCode, Response0) ->
+ Response = create_chunk(Info, Response0),
+ httpd_socket:deliver(Type, Sock, Response);
+handle_other_request(#mod{socket_type = Type, socket = Sock} = Info,
+ StatusCode, Response) ->
+ httpd_socket:deliver(Type, Sock, Response).
+
+
+final_handle_other_request(#mod{http_version = "HTTP/1.1",
+ socket_type = Type, socket = Sock},
+ StatusCode) ->
+ httpd_socket:deliver(Type, Sock, "0\r\n");
+final_handle_other_request(#mod{socket_type = Type, socket = Sock},
+ StatusCode) ->
+ httpd_socket:close(Type, Sock),
+ socket_closed.
+
+
+create_chunk(_Info, Response) ->
+ HEXSize = httpd_util:integer_to_hexlist(length(lists:flatten(Response))),
+ HEXSize++"\r\n"++Response++"\r\n".
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% The various helper functions %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+update_status_code(undefined, Response) ->
+ case status_code(Response) of
+ {ok, StatusCode1} ->
+ StatusCode1;
+ _ ->
+ ?vlog("invalid response from script:~n~p", [Response]),
+ 500
+ end;
+update_status_code(StatusCode,_Response)->
+ StatusCode.
+
+
+get_new_size(0,Response)->
+ case httpd_util:split(Response,"\r\n\r\n|\n\n",2) of
+ {ok,[Head,Body]}->
+ length(lists:flatten(Body));
+ _ ->
+ %%No header in the respone
+ length(lists:flatten(Response))
+ end;
+
+get_new_size(Size,Response)->
+ Size+length(lists:flatten(Response)).
+
+%%----------------------------------------------------------------------
+%% Creates the http-header for a response
+%%----------------------------------------------------------------------
+create_header(Info,StatusCode)->
+ Cache=case httpd_util:lookup(Info#mod.config_db,script_nocache,false) of
+ true->
+ Date=httpd_util:rfc1123_date(),
+ "Cache-Control:no-cache\r\nPragma:no-cache\r\nExpires:"++ Date ++ "\r\n";
+ false ->
+ []
+ end,
+ case Info#mod.http_version of
+ "HTTP/1.1" ->
+ Header=httpd_util:header(StatusCode, Info#mod.connection),
+ Header++"Transfer-encoding:chunked\r\n"++Cache;
+ _ ->
+ httpd_util:header(StatusCode,Info#mod.connection)++Cache
+ end.
+
+
+
+%% status_code
+
+status_code(Response) ->
+ case httpd_util:split(Response,"\n\n|\r\n\r\n",2) of
+ {ok,[Header,Body]} ->
+ case regexp:split(Header,"\n|\r\n") of
+ {ok,HeaderFields} ->
+ {ok,extract_status_code(HeaderFields)};
+ {error,_} ->
+ {error, bad_script_output(Response)}
+ end;
+ _ ->
+ %% No header field in the returned data return 200 the standard code
+ {ok, 200}
+ end.
+
+bad_script_output(Bad) ->
+ lists:flatten(io_lib:format("Bad script output ~s",[Bad])).
+
+
+extract_status_code([]) ->
+ 200;
+extract_status_code([[$L,$o,$c,$a,$t,$i,$o,$n,$:,$ |_]|_]) ->
+ 302;
+extract_status_code([[$S,$t,$a,$t,$u,$s,$:,$ |CodeAndReason]|_]) ->
+ case httpd_util:split(CodeAndReason," ",2) of
+ {ok,[Code,_]} ->
+ list_to_integer(Code);
+ {ok,_} ->
+ 200
+ end;
+extract_status_code([_|Rest]) ->
+ extract_status_code(Rest).
+
+
+sz(B) when binary(B) -> {binary,size(B)};
+sz(L) when list(L) -> {list,length(L)};
+sz(_) -> undefined.
+
+
+%% Convert error to printable string
+%%
+reason({error,emfile}) -> ": To many open files";
+reason({error,{enfile,_}}) -> ": File/port table overflow";
+reason({error,enomem}) -> ": Not enough memory";
+reason({error,eagain}) -> ": No more available OS processes";
+reason(_) -> "".
+
+removeStatus(Head)->
+ case httpd_util:split(Head,"Status:.\r\n",2) of
+ {ok,[HeadPart,HeadEnd]}->
+ HeadPart++HeadEnd;
+ _ ->
+ Head
+ end.
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% There are 2 config directives for mod_cgi: %%
+%% ScriptNoCache true|false, defines whether the server shall add %%
+%% header fields to stop proxies and %%
+%% clients from saving the page in history %%
+%% or cache %%
+%% %%
+%% ScriptTimeout Seconds, The number of seconds that the server %%
+%% maximum will wait for the script to %%
+%% generate a part of the document %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+load([$S,$c,$r,$i,$p,$t,$N,$o,$C,$a,$c,$h,$e |CacheArg],[])->
+ case catch list_to_atom(httpd_conf:clean(CacheArg)) of
+ true ->
+ {ok, [], {script_nocache,true}};
+ false ->
+ {ok, [], {script_nocache,false}};
+ _ ->
+ {error, ?NICE(httpd_conf:clean(CacheArg)++
+ " is an invalid ScriptNoCache directive")}
+ end;
+
+load([$S,$c,$r,$i,$p,$t,$T,$i,$m,$e,$o,$u,$t,$ |Timeout],[])->
+ case catch list_to_integer(httpd_conf:clean(Timeout)) of
+ TimeoutSec when integer(TimeoutSec) ->
+ {ok, [], {script_timeout,TimeoutSec*1000}};
+ _ ->
+ {error, ?NICE(httpd_conf:clean(Timeout)++
+ " is an invalid ScriptTimeout")}
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_dir.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_dir.erl
new file mode 100644
index 0000000000..9dda6d9119
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_dir.erl
@@ -0,0 +1,266 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_dir.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
+%%
+-module(mod_dir).
+-export([do/1]).
+
+-include("httpd.hrl").
+
+%% do
+
+do(Info) ->
+ ?DEBUG("do -> entry",[]),
+ case Info#mod.method of
+ "GET" ->
+ case httpd_util:key1search(Info#mod.data,status) of
+ %% A status code has been generated!
+ {StatusCode,PhraseArgs,Reason} ->
+ {proceed,Info#mod.data};
+ %% No status code has been generated!
+ undefined ->
+ case httpd_util:key1search(Info#mod.data,response) of
+ %% No response has been generated!
+ undefined ->
+ do_dir(Info);
+ %% A response has been generated or sent!
+ Response ->
+ {proceed,Info#mod.data}
+ end
+ end;
+ %% Not a GET method!
+ _ ->
+ {proceed,Info#mod.data}
+ end.
+
+do_dir(Info) ->
+ ?DEBUG("do_dir -> Request URI: ~p",[Info#mod.request_uri]),
+ Path = mod_alias:path(Info#mod.data,Info#mod.config_db,
+ Info#mod.request_uri),
+ DefaultPath = mod_alias:default_index(Info#mod.config_db,Path),
+ %% Is it a directory?
+ case file:read_file_info(DefaultPath) of
+ {ok,FileInfo} when FileInfo#file_info.type == directory ->
+ DecodedRequestURI =
+ httpd_util:decode_hex(Info#mod.request_uri),
+ ?DEBUG("do_dir -> ~n"
+ " Path: ~p~n"
+ " DefaultPath: ~p~n"
+ " DecodedRequestURI: ~p",
+ [Path,DefaultPath,DecodedRequestURI]),
+ case dir(DefaultPath,string:strip(DecodedRequestURI,right,$/),Info#mod.config_db) of
+ {ok, Dir} ->
+ Head=[{content_type,"text/html"},
+ {content_length,integer_to_list(httpd_util:flatlength(Dir))},
+ {date,httpd_util:rfc1123_date(FileInfo#file_info.mtime)},
+ {code,200}],
+ {proceed,[{response,{response,Head,Dir}},
+ {mime_type,"text/html"}|Info#mod.data]};
+ {error, Reason} ->
+ ?ERROR("do_dir -> dir operation failed: ~p",[Reason]),
+ {proceed,
+ [{status,{404,Info#mod.request_uri,Reason}}|
+ Info#mod.data]}
+ end;
+ {ok,FileInfo} ->
+ ?DEBUG("do_dir -> ~n"
+ " Path: ~p~n"
+ " DefaultPath: ~p~n"
+ " FileInfo: ~p",
+ [Path,DefaultPath,FileInfo]),
+ {proceed,Info#mod.data};
+ {error,Reason} ->
+ ?LOG("do_dir -> failed reading file info (~p) for: ~p",
+ [Reason,DefaultPath]),
+ {proceed,
+ [{status,read_file_info_error(Reason,Info,DefaultPath)}|
+ Info#mod.data]}
+ end.
+
+dir(Path,RequestURI,ConfigDB) ->
+ case file:list_dir(Path) of
+ {ok,FileList} ->
+ SortedFileList=lists:sort(FileList),
+ {ok,[header(Path,RequestURI),
+ body(Path,RequestURI,ConfigDB,SortedFileList),
+ footer(Path,SortedFileList)]};
+ {error,Reason} ->
+ {error,?NICE("Can't open directory "++Path++": "++Reason)}
+ end.
+
+%% header
+
+header(Path,RequestURI) ->
+ Header=
+ "<HTML>\n<HEAD>\n<TITLE>Index of "++RequestURI++"</TITLE>\n</HEAD>\n<BODY>\n<H1>Index of "++
+ RequestURI++"</H1>\n<PRE><IMG SRC=\""++icon(blank)++
+ "\" ALT=" "> Name Last modified Size Description
+<HR>\n",
+ case regexp:sub(RequestURI,"[^/]*\$","") of
+ {ok,"/",_} ->
+ Header;
+ {ok,ParentRequestURI,_} ->
+ {ok,ParentPath,_}=regexp:sub(string:strip(Path,right,$/),"[^/]*\$",""),
+ Header++format(ParentPath,ParentRequestURI)
+ end.
+
+format(Path,RequestURI) ->
+ {ok,FileInfo}=file:read_file_info(Path),
+ {{Year,Month,Day},{Hour,Minute,Second}}=FileInfo#file_info.mtime,
+ io_lib:format("<IMG SRC=\"~s\" ALT=\"[~s]\"> <A HREF=\"~s\">Parent directory</A> ~2.2.0w-~s-~w ~2.2.0w:~2.2.0w -\n",
+ [icon(back),"DIR",RequestURI,Day,
+ httpd_util:month(Month),Year,Hour,Minute]).
+
+%% body
+
+body(Path,RequestURI,ConfigDB,[]) ->
+ [];
+body(Path,RequestURI,ConfigDB,[Entry|Rest]) ->
+ [format(Path,RequestURI,ConfigDB,Entry)|body(Path,RequestURI,ConfigDB,Rest)].
+
+format(Path,RequestURI,ConfigDB,Entry) ->
+ case file:read_file_info(Path++"/"++Entry) of
+ {ok,FileInfo} when FileInfo#file_info.type == directory ->
+ {{Year,Month,Day},{Hour,Minute,Second}}=FileInfo#file_info.mtime,
+ EntryLength=length(Entry),
+ if
+ EntryLength > 21 ->
+ io_lib:format("<IMG SRC=\"~s\" ALT=\"[~s]\"> <A HREF=\"~s\">~-21.s..</A>~2.2.0w-~s-~w ~2.2.0w:~2.2.0w -\n",
+ [icon(folder),"DIR",RequestURI++"/"++Entry++"/",Entry,
+ Day,httpd_util:month(Month),Year,Hour,Minute]);
+ true ->
+ io_lib:format("<IMG SRC=\"~s\" ALT=\"[~s]\"> <A HREF=\"~s\">~s</A>~*.*c~2.2.0w-~s-~w ~2.2.0w:~2.2.0w -\n",
+ [icon(folder),"DIR",RequestURI++"/"++Entry++"/",Entry,
+ 23-EntryLength,23-EntryLength,$ ,Day,
+ httpd_util:month(Month),Year,Hour,Minute])
+ end;
+ {ok,FileInfo} ->
+ {{Year,Month,Day},{Hour,Minute,Second}}=FileInfo#file_info.mtime,
+ Suffix=httpd_util:suffix(Entry),
+ MimeType=httpd_util:lookup_mime(ConfigDB,Suffix,""),
+ EntryLength=length(Entry),
+ if
+ EntryLength > 21 ->
+ io_lib:format("<IMG SRC=\"~s\" ALT=\"[~s]\"> <A HREF=\"~s\">~-21.s..</A>~2.2.0w-~s-~w ~2.2.0w:~2.2.0w~8wk ~s\n",
+ [icon(Suffix,MimeType),Suffix,RequestURI++"/"++Entry,
+ Entry,Day,httpd_util:month(Month),Year,Hour,Minute,
+ trunc(FileInfo#file_info.size/1024+1),MimeType]);
+ true ->
+ io_lib:format("<IMG SRC=\"~s\" ALT=\"[~s]\"> <A HREF=\"~s\">~s</A>~*.*c~2.2.0w-~s-~w ~2.2.0w:~2.2.0w~8wk ~s\n",
+ [icon(Suffix,MimeType),Suffix,RequestURI++"/"++Entry,
+ Entry,23-EntryLength,23-EntryLength,$ ,Day,
+ httpd_util:month(Month),Year,Hour,Minute,
+ trunc(FileInfo#file_info.size/1024+1),MimeType])
+ end;
+ {error,Reason} ->
+ ""
+ end.
+
+%% footer
+
+footer(Path,FileList) ->
+ case lists:member("README",FileList) of
+ true ->
+ {ok,Body}=file:read_file(Path++"/README"),
+ "</PRE>\n<HR>\n<PRE>\n"++binary_to_list(Body)++
+ "\n</PRE>\n</BODY>\n</HTML>\n";
+ false ->
+ "</PRE>\n</BODY>\n</HTML>\n"
+ end.
+
+%%
+%% Icon mappings are hard-wired ala default Apache (Ugly!)
+%%
+
+icon(Suffix,MimeType) ->
+ case icon(Suffix) of
+ undefined ->
+ case MimeType of
+ [$t,$e,$x,$t,$/|_] ->
+ "/icons/text.gif";
+ [$i,$m,$a,$g,$e,$/|_] ->
+ "/icons/image2.gif";
+ [$a,$u,$d,$i,$o,$/|_] ->
+ "/icons/sound2.gif";
+ [$v,$i,$d,$e,$o,$/|_] ->
+ "/icons/movie.gif";
+ _ ->
+ "/icons/unknown.gif"
+ end;
+ Icon ->
+ Icon
+ end.
+
+icon(blank) -> "/icons/blank.gif";
+icon(back) -> "/icons/back.gif";
+icon(folder) -> "/icons/folder.gif";
+icon("bin") -> "/icons/binary.gif";
+icon("exe") -> "/icons/binary.gif";
+icon("hqx") -> "/icons/binhex.gif";
+icon("tar") -> "/icons/tar.gif";
+icon("wrl") -> "/icons/world2.gif";
+icon("wrl.gz") -> "/icons/world2.gif";
+icon("vrml") -> "/icons/world2.gif";
+icon("vrm") -> "/icons/world2.gif";
+icon("iv") -> "/icons/world2.gif";
+icon("Z") -> "/icons/compressed.gif";
+icon("z") -> "/icons/compressed.gif";
+icon("tgz") -> "/icons/compressed.gif";
+icon("gz") -> "/icons/compressed.gif";
+icon("zip") -> "/icons/compressed.gif";
+icon("ps") -> "/icons/a.gif";
+icon("ai") -> "/icons/a.gif";
+icon("eps") -> "/icons/a.gif";
+icon("html") -> "/icons/layout.gif";
+icon("shtml") -> "/icons/layout.gif";
+icon("htm") -> "/icons/layout.gif";
+icon("pdf") -> "/icons/layout.gif";
+icon("txt") -> "/icons/text.gif";
+icon("erl") -> "/icons/burst.gif";
+icon("c") -> "/icons/c.gif";
+icon("pl") -> "/icons/p.gif";
+icon("py") -> "/icons/p.gif";
+icon("for") -> "/icons/f.gif";
+icon("dvi") -> "/icons/dvi.gif";
+icon("uu") -> "/icons/uuencoded.gif";
+icon("conf") -> "/icons/script.gif";
+icon("sh") -> "/icons/script.gif";
+icon("shar") -> "/icons/script.gif";
+icon("csh") -> "/icons/script.gif";
+icon("ksh") -> "/icons/script.gif";
+icon("tcl") -> "/icons/script.gif";
+icon("tex") -> "/icons/tex.gif";
+icon("core") -> "/icons/tex.gif";
+icon(_) -> undefined.
+
+
+read_file_info_error(eacces,Info,Path) ->
+ read_file_info_error(403,Info,Path,
+ ": Missing search permissions for one "
+ "of the parent directories");
+read_file_info_error(enoent,Info,Path) ->
+ read_file_info_error(404,Info,Path,"");
+read_file_info_error(enotdir,Info,Path) ->
+ read_file_info_error(404,Info,Path,
+ ": A component of the file name is not a directory");
+read_file_info_error(_,Info,Path) ->
+ read_file_info_error(500,none,Path,"").
+
+read_file_info_error(StatusCode,none,Path,Reason) ->
+ {StatusCode,none,?NICE("Can't access "++Path++Reason)};
+read_file_info_error(StatusCode,Info,Path,Reason) ->
+ {StatusCode,Info#mod.request_uri,
+ ?NICE("Can't access "++Path++Reason)}.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_disk_log.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_disk_log.erl
new file mode 100644
index 0000000000..bb175f24b0
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_disk_log.erl
@@ -0,0 +1,404 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_disk_log.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
+%%
+-module(mod_disk_log).
+-export([do/1,error_log/5,security_log/2,load/2,store/2,remove/1]).
+
+-export([report_error/2]).
+
+-define(VMODULE,"DISK_LOG").
+-include("httpd_verbosity.hrl").
+
+-include("httpd.hrl").
+
+%% do
+
+do(Info) ->
+ AuthUser = auth_user(Info#mod.data),
+ Date = custom_date(),
+ log_internal_info(Info,Date,Info#mod.data),
+ LogFormat = get_log_format(Info#mod.config_db),
+ case httpd_util:key1search(Info#mod.data,status) of
+ %% A status code has been generated!
+ {StatusCode,PhraseArgs,Reason} ->
+ transfer_log(Info, "-", AuthUser, Date, StatusCode, 0, LogFormat),
+ if
+ StatusCode >= 400 ->
+ error_log(Info, Date, Reason, LogFormat);
+ true ->
+ not_an_error
+ end,
+ {proceed,Info#mod.data};
+ %% No status code has been generated!
+ undefined ->
+ case httpd_util:key1search(Info#mod.data,response) of
+ {already_sent,StatusCode,Size} ->
+ transfer_log(Info, "-", AuthUser, Date, StatusCode,
+ Size, LogFormat),
+ {proceed,Info#mod.data};
+
+ {response, Head, Body} ->
+ Size = httpd_util:key1search(Head, content_length, 0),
+ Code = httpd_util:key1search(Head, code, 200),
+ transfer_log(Info, "-", AuthUser, Date, Code,
+ Size, LogFormat),
+ {proceed,Info#mod.data};
+
+ {StatusCode,Response} ->
+ transfer_log(Info, "-", AuthUser, Date, 200,
+ httpd_util:flatlength(Response), LogFormat),
+ {proceed,Info#mod.data};
+ undefined ->
+ transfer_log(Info, "-", AuthUser, Date, 200,
+ 0, LogFormat),
+ {proceed,Info#mod.data}
+ end
+ end.
+
+custom_date() ->
+ LocalTime = calendar:local_time(),
+ UniversalTime = calendar:universal_time(),
+ Minutes = round(diff_in_minutes(LocalTime,UniversalTime)),
+ {{YYYY,MM,DD},{Hour,Min,Sec}} = LocalTime,
+ Date =
+ io_lib:format("~.2.0w/~.3s/~.4w:~.2.0w:~.2.0w:~.2.0w ~c~.2.0w~.2.0w",
+ [DD,httpd_util:month(MM),YYYY,Hour,Min,Sec,sign(Minutes),
+ abs(Minutes) div 60,abs(Minutes) rem 60]),
+ lists:flatten(Date).
+
+diff_in_minutes(L,U) ->
+ (calendar:datetime_to_gregorian_seconds(L) -
+ calendar:datetime_to_gregorian_seconds(U))/60.
+
+sign(Minutes) when Minutes > 0 ->
+ $+;
+sign(Minutes) ->
+ $-.
+
+auth_user(Data) ->
+ case httpd_util:key1search(Data,remote_user) of
+ undefined ->
+ "-";
+ RemoteUser ->
+ RemoteUser
+ end.
+
+%% log_internal_info
+
+log_internal_info(Info,Date,[]) ->
+ ok;
+log_internal_info(Info,Date,[{internal_info,Reason}|Rest]) ->
+ Format = get_log_format(Info#mod.config_db),
+ error_log(Info,Date,Reason,Format),
+ log_internal_info(Info,Date,Rest);
+log_internal_info(Info,Date,[_|Rest]) ->
+ log_internal_info(Info,Date,Rest).
+
+
+%% transfer_log
+
+transfer_log(Info,RFC931,AuthUser,Date,StatusCode,Bytes,Format) ->
+ case httpd_util:lookup(Info#mod.config_db,transfer_disk_log) of
+ undefined ->
+ no_transfer_log;
+ TransferDiskLog ->
+ {PortNumber,RemoteHost}=(Info#mod.init_data)#init_data.peername,
+ Entry = io_lib:format("~s ~s ~s [~s] \"~s\" ~w ~w~n",
+ [RemoteHost,RFC931,AuthUser,Date,
+ Info#mod.request_line,StatusCode,Bytes]),
+ write(TransferDiskLog, Entry, Format)
+ end.
+
+
+%% error_log
+
+error_log(Info, Date, Reason, Format) ->
+ Format=get_log_format(Info#mod.config_db),
+ case httpd_util:lookup(Info#mod.config_db,error_disk_log) of
+ undefined ->
+ no_error_log;
+ ErrorDiskLog ->
+ {PortNumber,RemoteHost}=(Info#mod.init_data)#init_data.peername,
+ Entry =
+ io_lib:format("[~s] access to ~s failed for ~s, reason: ~p~n",
+ [Date, Info#mod.request_uri,
+ RemoteHost, Reason]),
+ write(ErrorDiskLog, Entry, Format)
+ end.
+
+error_log(SocketType, Socket, ConfigDB, {PortNumber, RemoteHost}, Reason) ->
+ Format = get_log_format(ConfigDB),
+ case httpd_util:lookup(ConfigDB,error_disk_log) of
+ undefined ->
+ no_error_log;
+ ErrorDiskLog ->
+ Date = custom_date(),
+ Entry =
+ io_lib:format("[~s] server crash for ~s, reason: ~p~n",
+ [Date,RemoteHost,Reason]),
+ write(ErrorDiskLog, Entry, Format),
+ ok
+ end.
+
+
+%% security_log
+
+security_log(ConfigDB, Event) ->
+ Format = get_log_format(ConfigDB),
+ case httpd_util:lookup(ConfigDB,security_disk_log) of
+ undefined ->
+ no_error_log;
+ DiskLog ->
+ Date = custom_date(),
+ Entry = io_lib:format("[~s] ~s ~n", [Date, Event]),
+ write(DiskLog, Entry, Format),
+ ok
+ end.
+
+report_error(ConfigDB, Error) ->
+ Format = get_log_format(ConfigDB),
+ case httpd_util:lookup(ConfigDB, error_disk_log) of
+ undefined ->
+ no_error_log;
+ ErrorDiskLog ->
+ Date = custom_date(),
+ Entry = io_lib:format("[~s] reporting error: ~s",[Date,Error]),
+ write(ErrorDiskLog, Entry, Format),
+ ok
+ end.
+
+%%----------------------------------------------------------------------
+%% Get the current format of the disklog
+%%----------------------------------------------------------------------
+get_log_format(ConfigDB)->
+ httpd_util:lookup(ConfigDB,disk_log_format,external).
+
+
+%%
+%% Configuration
+%%
+
+%% load
+
+load([$T,$r,$a,$n,$s,$f,$e,$r,$D,$i,$s,$k,$L,$o,$g,$S,$i,$z,$e,$ |
+ TransferDiskLogSize],[]) ->
+ case regexp:split(TransferDiskLogSize," ") of
+ {ok,[MaxBytes,MaxFiles]} ->
+ case httpd_conf:make_integer(MaxBytes) of
+ {ok,MaxBytesInteger} ->
+ case httpd_conf:make_integer(MaxFiles) of
+ {ok,MaxFilesInteger} ->
+ {ok,[],{transfer_disk_log_size,
+ {MaxBytesInteger,MaxFilesInteger}}};
+ {error,_} ->
+ {error,
+ ?NICE(httpd_conf:clean(TransferDiskLogSize)++
+ " is an invalid TransferDiskLogSize")}
+ end;
+ {error,_} ->
+ {error,?NICE(httpd_conf:clean(TransferDiskLogSize)++
+ " is an invalid TransferDiskLogSize")}
+ end
+ end;
+load([$T,$r,$a,$n,$s,$f,$e,$r,$D,$i,$s,$k,$L,$o,$g,$ |TransferDiskLog],[]) ->
+ {ok,[],{transfer_disk_log,httpd_conf:clean(TransferDiskLog)}};
+
+load([$E,$r,$r,$o,$r,$D,$i,$s,$k,$L,$o,$g,$S,$i,$z,$e,$ | ErrorDiskLogSize],[]) ->
+ case regexp:split(ErrorDiskLogSize," ") of
+ {ok,[MaxBytes,MaxFiles]} ->
+ case httpd_conf:make_integer(MaxBytes) of
+ {ok,MaxBytesInteger} ->
+ case httpd_conf:make_integer(MaxFiles) of
+ {ok,MaxFilesInteger} ->
+ {ok,[],{error_disk_log_size,
+ {MaxBytesInteger,MaxFilesInteger}}};
+ {error,_} ->
+ {error,?NICE(httpd_conf:clean(ErrorDiskLogSize)++
+ " is an invalid ErrorDiskLogSize")}
+ end;
+ {error,_} ->
+ {error,?NICE(httpd_conf:clean(ErrorDiskLogSize)++
+ " is an invalid ErrorDiskLogSize")}
+ end
+ end;
+load([$E,$r,$r,$o,$r,$D,$i,$s,$k,$L,$o,$g,$ |ErrorDiskLog],[]) ->
+ {ok, [], {error_disk_log, httpd_conf:clean(ErrorDiskLog)}};
+
+load([$S,$e,$c,$u,$r,$i,$t,$y,$D,$i,$s,$k,$L,$o,$g,$S,$i,$z,$e,$ |SecurityDiskLogSize],[]) ->
+ case regexp:split(SecurityDiskLogSize, " ") of
+ {ok, [MaxBytes, MaxFiles]} ->
+ case httpd_conf:make_integer(MaxBytes) of
+ {ok, MaxBytesInteger} ->
+ case httpd_conf:make_integer(MaxFiles) of
+ {ok, MaxFilesInteger} ->
+ {ok, [], {security_disk_log_size,
+ {MaxBytesInteger, MaxFilesInteger}}};
+ {error,_} ->
+ {error, ?NICE(httpd_conf:clean(SecurityDiskLogSize)++
+ " is an invalid SecurityDiskLogSize")}
+ end;
+ {error, _} ->
+ {error, ?NICE(httpd_conf:clean(SecurityDiskLogSize)++
+ " is an invalid SecurityDiskLogSize")}
+ end
+ end;
+load([$S,$e,$c,$u,$r,$i,$t,$y,$D,$i,$s,$k,$L,$o,$g,$ |SecurityDiskLog],[]) ->
+ {ok, [], {security_disk_log, httpd_conf:clean(SecurityDiskLog)}};
+
+load([$D,$i,$s,$k,$L,$o,$g,$F,$o,$r,$m,$a,$t,$ |Format],[]) ->
+ case httpd_conf:clean(Format) of
+ "internal" ->
+ {ok, [], {disk_log_format,internal}};
+ "external" ->
+ {ok, [], {disk_log_format,external}};
+ _Default ->
+ {ok, [], {disk_log_format,external}}
+ end.
+
+%% store
+
+store({transfer_disk_log,TransferDiskLog},ConfigList) ->
+ case create_disk_log(TransferDiskLog, transfer_disk_log_size, ConfigList) of
+ {ok,TransferDB} ->
+ {ok,{transfer_disk_log,TransferDB}};
+ {error,Reason} ->
+ {error,Reason}
+ end;
+store({security_disk_log,SecurityDiskLog},ConfigList) ->
+ case create_disk_log(SecurityDiskLog, security_disk_log_size, ConfigList) of
+ {ok,SecurityDB} ->
+ {ok,{security_disk_log,SecurityDB}};
+ {error,Reason} ->
+ {error,Reason}
+ end;
+store({error_disk_log,ErrorDiskLog},ConfigList) ->
+ case create_disk_log(ErrorDiskLog, error_disk_log_size, ConfigList) of
+ {ok,ErrorDB} ->
+ {ok,{error_disk_log,ErrorDB}};
+ {error,Reason} ->
+ {error,Reason}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% Open or creates the disklogs
+%%----------------------------------------------------------------------
+log_size(ConfigList, Tag) ->
+ httpd_util:key1search(ConfigList, Tag, {500*1024,8}).
+
+create_disk_log(LogFile, SizeTag, ConfigList) ->
+ Filename = httpd_conf:clean(LogFile),
+ {MaxBytes, MaxFiles} = log_size(ConfigList, SizeTag),
+ case filename:pathtype(Filename) of
+ absolute ->
+ create_disk_log(Filename, MaxBytes, MaxFiles, ConfigList);
+ volumerelative ->
+ create_disk_log(Filename, MaxBytes, MaxFiles, ConfigList);
+ relative ->
+ case httpd_util:key1search(ConfigList,server_root) of
+ undefined ->
+ {error,
+ ?NICE(Filename++
+ " is an invalid ErrorLog beacuse ServerRoot is not defined")};
+ ServerRoot ->
+ AbsoluteFilename = filename:join(ServerRoot,Filename),
+ create_disk_log(AbsoluteFilename, MaxBytes, MaxFiles,
+ ConfigList)
+ end
+ end.
+
+create_disk_log(Filename, MaxBytes, MaxFiles, ConfigList) ->
+ Format = httpd_util:key1search(ConfigList, disk_log_format, external),
+ open(Filename, MaxBytes, MaxFiles, Format).
+
+
+
+%% remove
+remove(ConfigDB) ->
+ lists:foreach(fun([DiskLog]) -> close(DiskLog) end,
+ ets:match(ConfigDB,{transfer_disk_log,'$1'})),
+ lists:foreach(fun([DiskLog]) -> close(DiskLog) end,
+ ets:match(ConfigDB,{error_disk_log,'$1'})),
+ ok.
+
+
+%%
+%% Some disk_log wrapper functions:
+%%
+
+%%----------------------------------------------------------------------
+%% Function: open/4
+%% Description: Open a disk log file.
+%% Control which format the disk log will be in. The external file
+%% format is used as default since that format was used by older
+%% implementations of inets.
+%%
+%% When the internal disk log format is used, we will do some extra
+%% controls. If the files are valid, try to repair them and if
+%% thats not possible, truncate.
+%%----------------------------------------------------------------------
+
+open(Filename, MaxBytes, MaxFiles, internal) ->
+ Opts = [{format, internal}, {repair, truncate}],
+ open1(Filename, MaxBytes, MaxFiles, Opts);
+open(Filename, MaxBytes, MaxFiles, _) ->
+ Opts = [{format, external}],
+ open1(Filename, MaxBytes, MaxFiles, Opts).
+
+open1(Filename, MaxBytes, MaxFiles, Opts0) ->
+ Opts1 = [{name, Filename}, {file, Filename}, {type, wrap}] ++ Opts0,
+ case open2(Opts1, {MaxBytes, MaxFiles}) of
+ {ok, LogDB} ->
+ {ok, LogDB};
+ {error, Reason} ->
+ ?vlog("failed opening disk log with args:"
+ "~n Filename: ~p"
+ "~n MaxBytes: ~p"
+ "~n MaxFiles: ~p"
+ "~n Opts0: ~p"
+ "~nfor reason:"
+ "~n ~p", [Filename, MaxBytes, MaxFiles, Opts0, Reason]),
+ {error,
+ ?NICE("Can't create " ++ Filename ++
+ lists:flatten(io_lib:format(", ~p",[Reason])))};
+ _ ->
+ {error, ?NICE("Can't create "++Filename)}
+ end.
+
+open2(Opts, Size) ->
+ case disk_log:open(Opts) of
+ {error, {badarg, size}} ->
+ %% File did not exist, add the size option and try again
+ disk_log:open([{size, Size} | Opts]);
+ Else ->
+ Else
+ end.
+
+
+%%----------------------------------------------------------------------
+%% Actually writes the entry to the disk_log. If the log is an
+%% internal disk_log write it with log otherwise with blog.
+%%----------------------------------------------------------------------
+write(Log, Entry, internal) ->
+ disk_log:log(Log, Entry);
+
+write(Log, Entry, _) ->
+ disk_log:blog(Log, Entry).
+
+%% Close the log file
+close(Log) ->
+ disk_log:close(Log).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_esi.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_esi.erl
new file mode 100644
index 0000000000..cb211749da
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_esi.erl
@@ -0,0 +1,481 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_esi.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
+%%
+-module(mod_esi).
+-export([do/1,load/2]).
+
+%%Functions provided to help erl scheme alias programmer to
+%%Create dynamic webpages that are sent back to the user during
+%%Generation
+-export([deliver/2]).
+
+
+-include("httpd.hrl").
+
+-define(VMODULE,"ESI").
+-include("httpd_verbosity.hrl").
+
+-define(GATEWAY_INTERFACE,"CGI/1.1").
+-define(DEFAULT_ERL_TIMEOUT,15000).
+%% do
+
+do(Info) ->
+ ?vtrace("do",[]),
+ case httpd_util:key1search(Info#mod.data,status) of
+ %% A status code has been generated!
+ {StatusCode,PhraseArgs,Reason} ->
+ {proceed,Info#mod.data};
+ %% No status code has been generated!
+ undefined ->
+ case httpd_util:key1search(Info#mod.data,response) of
+ %% No response has been generated!
+ undefined ->
+ case erl_or_eval(Info#mod.request_uri,
+ Info#mod.config_db) of
+ {eval,CGIBody,Modules} ->
+ eval(Info,Info#mod.method,CGIBody,Modules);
+ {erl,CGIBody,Modules} ->
+ erl(Info,Info#mod.method,CGIBody,Modules);
+ proceed ->
+ {proceed,Info#mod.data}
+ end;
+ %% A response has been generated or sent!
+ Response ->
+ {proceed,Info#mod.data}
+ end
+ end.
+
+
+
+%% erl_or_eval
+
+erl_or_eval(RequestURI, ConfigDB) ->
+ case erlp(RequestURI, ConfigDB) of
+ false ->
+ case evalp(RequestURI, ConfigDB) of
+ false ->
+ ?vtrace("neither erl nor eval",[]),
+ proceed;
+ Other ->
+ Other
+ end;
+ Other ->
+ Other
+ end.
+
+erlp(RequestURI, ConfigDB) ->
+ case httpd_util:multi_lookup(ConfigDB, erl_script_alias) of
+ [] ->
+ false;
+ AliasMods ->
+ erlp_find_alias(RequestURI,AliasMods)
+ end.
+
+erlp_find_alias(_RequestURI,[]) ->
+ ?vtrace("erlp_find_alias -> no match",[]),
+ false;
+erlp_find_alias(RequestURI,[{Alias,Modules}|Rest]) ->
+ case regexp:first_match(RequestURI,"^"++Alias++"/") of
+ {match,1,Length} ->
+ ?vtrace("erlp -> match with Length: ~p",[Length]),
+ {erl,string:substr(RequestURI,Length+1),Modules};
+ nomatch ->
+ erlp_find_alias(RequestURI,Rest)
+ end.
+
+evalp(RequestURI, ConfigDB) ->
+ case httpd_util:multi_lookup(ConfigDB, eval_script_alias) of
+ [] ->
+ false;
+ AliasMods ->
+ evalp_find_alias(RequestURI,AliasMods)
+ end.
+
+evalp_find_alias(_RequestURI,[]) ->
+ ?vtrace("evalp_find_alias -> no match",[]),
+ false;
+evalp_find_alias(RequestURI,[{Alias,Modules}|Rest]) ->
+ case regexp:first_match(RequestURI,"^"++Alias++"\\?") of
+ {match, 1, Length} ->
+ ?vtrace("evalp_find_alias -> match with Length: ~p",[Length]),
+ {eval, string:substr(RequestURI,Length+1),Modules};
+ nomatch ->
+ evalp_find_alias(RequestURI,Rest)
+ end.
+
+
+%%
+%% Erl mechanism
+%%
+
+%%This is exactly the same as the GET method the difference is that
+%%The response must not contain any data expect the response header
+
+
+erl(Info,"HEAD",CGIBody,Modules) ->
+ erl(Info,"GET",CGIBody,Modules);
+
+erl(Info,"GET",CGIBody,Modules) ->
+ ?vtrace("erl GET request",[]),
+ case httpd_util:split(CGIBody,":|%3A|/",2) of
+ {ok, [Mod,FuncAndInput]} ->
+ ?vtrace("~n Mod: ~p"
+ "~n FuncAndInput: ~p",[Mod,FuncAndInput]),
+ case httpd_util:split(FuncAndInput,"[\?/]",2) of
+ {ok, [Func,Input]} ->
+ ?vtrace("~n Func: ~p"
+ "~n Input: ~p",[Func,Input]),
+ exec(Info,"GET",CGIBody,Modules,Mod,Func,
+ {input_type(FuncAndInput),Input});
+ {ok, [Func]} ->
+ exec(Info,"GET",CGIBody,Modules,Mod,Func,{no_input,""});
+ {ok, BadRequest} ->
+ {proceed,[{status,{400,none,BadRequest}}|Info#mod.data]}
+ end;
+ {ok, BadRequest} ->
+ ?vlog("erl BAD (GET-) request",[]),
+ {proceed, [{status,{400,none,BadRequest}}|Info#mod.data]}
+ end;
+
+erl(Info, "POST", CGIBody, Modules) ->
+ ?vtrace("erl POST request",[]),
+ case httpd_util:split(CGIBody,":|%3A|/",2) of
+ {ok,[Mod,Func]} ->
+ ?vtrace("~n Mod: ~p"
+ "~n Func: ~p",[Mod,Func]),
+ exec(Info,"POST",CGIBody,Modules,Mod,Func,
+ {entity_body,Info#mod.entity_body});
+ {ok,BadRequest} ->
+ ?vlog("erl BAD (POST-) request",[]),
+ {proceed,[{status,{400,none,BadRequest}}|Info#mod.data]}
+ end.
+
+input_type([]) ->
+ no_input;
+input_type([$/|Rest]) ->
+ path_info;
+input_type([$?|Rest]) ->
+ query_string;
+input_type([First|Rest]) ->
+ input_type(Rest).
+
+
+%% exec
+
+exec(Info,Method,CGIBody,["all"],Mod,Func,{Type,Input}) ->
+ ?vtrace("exec ~s 'all'",[Method]),
+ exec(Info,Method,CGIBody,[Mod],Mod,Func,{Type,Input});
+exec(Info,Method,CGIBody,Modules,Mod,Func,{Type,Input}) ->
+ ?vtrace("exec ~s request with:"
+ "~n Modules: ~p"
+ "~n Mod: ~p"
+ "~n Func: ~p"
+ "~n Type: ~p"
+ "~n Input: ~p",
+ [Method,Modules,Mod,Func,Type,Input]),
+ case lists:member(Mod,Modules) of
+ true ->
+ {_,RemoteAddr}=(Info#mod.init_data)#init_data.peername,
+ ServerName=(Info#mod.init_data)#init_data.resolve,
+ Env=get_environment(Info,ServerName,Method,RemoteAddr,Type,Input),
+ ?vtrace("and now call the module",[]),
+ case try_new_erl_scheme_method(Info,Env,Input,list_to_atom(Mod),list_to_atom(Func)) of
+ {error,not_new_method}->
+ case catch apply(list_to_atom(Mod),list_to_atom(Func),[Env,Input]) of
+ {'EXIT',Reason} ->
+ ?vlog("exit with Reason: ~p",[Reason]),
+ {proceed,[{status,{500,none,Reason}}|Info#mod.data]};
+ Response ->
+ control_response_header(Info,Mod,Func,Response)
+ end;
+ ResponseResult->
+ ResponseResult
+ end;
+ false ->
+ ?vlog("unknown module",[]),
+ {proceed,[{status,{403,Info#mod.request_uri,
+ ?NICE("Client not authorized to evaluate: "++CGIBody)}}|Info#mod.data]}
+ end.
+
+control_response_header(Info,Mod,Func,Response)->
+ case control_response(Response,Info,Mod,Func) of
+ {proceed,[{response,{StatusCode,Response}}|Rest]} ->
+ case httpd_util:lookup(Info#mod.config_db,erl_script_nocache,false) of
+ true ->
+ case httpd_util:split(Response,"\r\n\r\n|\n\n",2) of
+ {ok,[Head,Body]}->
+ Date=httpd_util:rfc1123_date(),
+ Cache="Cache-Control:no-cache\r\nPragma:no-cache\r\nExpires:"++ Date ++ "\r\n",
+ {proceed,[{response,{StatusCode,[Head,"\r\n",Cache,"\r\n",Body]}}|Rest]};
+ _->
+ {proceed,[{response,{StatusCode,Response}}|Rest]}
+ end;
+ WhatEver->
+ {proceed,[{response,{StatusCode,Response}}|Rest]}
+ end;
+ WhatEver->
+ WhatEver
+ end.
+
+control_response(Response,Info,Mod,Func)->
+ ?vdebug("Response: ~n~p",[Response]),
+ case mod_cgi:status_code(lists:flatten(Response)) of
+ {ok,StatusCode} ->
+ {proceed,[{response,{StatusCode,Response}}|Info#mod.data]};
+ {error,Reason} ->
+ {proceed,
+ [{status,{400,none,
+ ?NICE("Error in "++Mod++":"++Func++"/2: "++
+ lists:flatten(io_lib:format("~p",[Reason])))}}|
+ Info#mod.data]}
+ end.
+
+parsed_header([]) ->
+ [];
+parsed_header([{Name,[Value|R1]}|R2]) when list(Value) ->
+ NewName=lists:map(fun(X) -> if X == $- -> $_; true -> X end end,Name),
+ [{list_to_atom("http_"++httpd_util:to_lower(NewName)),
+ multi_value([Value|R1])}|parsed_header(R2)];
+parsed_header([{Name,Value}|Rest]) when list(Value)->
+ {ok,NewName,_}=regexp:gsub(Name,"-","_"),
+ [{list_to_atom("http_"++httpd_util:to_lower(NewName)),Value}|
+ parsed_header(Rest)].
+
+multi_value([]) ->
+ [];
+multi_value([Value]) ->
+ Value;
+multi_value([Value|Rest]) ->
+ Value++", "++multi_value(Rest).
+
+%%
+%% Eval mechanism
+%%
+
+
+eval(Info,"POST",CGIBody,Modules) ->
+ ?vtrace("eval(POST) -> method not supported",[]),
+ {proceed,[{status,{501,{"POST",Info#mod.request_uri,Info#mod.http_version},
+ ?NICE("Eval mechanism doesn't support method POST")}}|
+ Info#mod.data]};
+
+eval(Info,"HEAD",CGIBody,Modules) ->
+ %%The function that sends the data in httpd_response handles HEAD reqest by not
+ %% Sending the body
+ eval(Info,"GET",CGIBody,Modules);
+
+
+eval(Info,"GET",CGIBody,Modules) ->
+ ?vtrace("eval(GET) -> entry when"
+ "~n Modules: ~p",[Modules]),
+ case auth(CGIBody,Modules) of
+ true ->
+ case lib:eval_str(string:concat(CGIBody,". ")) of
+ {error,Reason} ->
+ ?vlog("eval -> error:"
+ "~n Reason: ~p",[Reason]),
+ {proceed,[{status,{500,none,Reason}}|Info#mod.data]};
+ {ok,Response} ->
+ ?vtrace("eval -> ok:"
+ "~n Response: ~p",[Response]),
+ case mod_cgi:status_code(lists:flatten(Response)) of
+ {ok,StatusCode} ->
+ {proceed,[{response,{StatusCode,Response}}|Info#mod.data]};
+ {error,Reason} ->
+ {proceed,[{status,{400,none,Reason}}|Info#mod.data]}
+ end
+ end;
+ false ->
+ ?vlog("eval -> auth failed",[]),
+ {proceed,[{status,
+ {403,Info#mod.request_uri,
+ ?NICE("Client not authorized to evaluate: "++CGIBody)}}|
+ Info#mod.data]}
+ end.
+
+auth(CGIBody,["all"]) ->
+ true;
+auth(CGIBody,Modules) ->
+ case regexp:match(CGIBody,"^[^\:(%3A)]*") of
+ {match,Start,Length} ->
+ lists:member(string:substr(CGIBody,Start,Length),Modules);
+ nomatch ->
+ false
+ end.
+
+%%----------------------------------------------------------------------
+%%Creates the environment list that will be the first arg to the
+%%Functions that is called through the ErlScript Schema
+%%----------------------------------------------------------------------
+
+get_environment(Info,ServerName,Method,RemoteAddr,Type,Input)->
+ Env=[{server_software,?SERVER_SOFTWARE},
+ {server_name,ServerName},
+ {gateway_interface,?GATEWAY_INTERFACE},
+ {server_protocol,?SERVER_PROTOCOL},
+ {server_port,httpd_util:lookup(Info#mod.config_db,port,80)},
+ {request_method,Method},
+ {remote_addr,RemoteAddr},
+ {script_name,Info#mod.request_uri}|
+ parsed_header(Info#mod.parsed_header)],
+ get_environment(Type,Input,Env,Info).
+
+
+get_environment(Type,Input,Env,Info)->
+ Env1=case Type of
+ query_string ->
+ [{query_string,Input}|Env];
+ path_info ->
+ Aliases=httpd_util:multi_lookup(Info#mod.config_db,alias),
+ {_,PathTranslated,_}=mod_alias:real_name(Info#mod.config_db,[$/|Input],Aliases),
+ [{path_info,"/"++httpd_util:decode_hex(Input)},
+ {path_translated,PathTranslated}|Env];
+ entity_body ->
+ [{content_length,httpd_util:flatlength(Input)}|Env];
+ no_input ->
+ Env
+ end,
+ get_environment(Info,Env1).
+
+get_environment(Info,Env)->
+ case httpd_util:key1search(Info#mod.data,remote_user) of
+ undefined ->
+ Env;
+ RemoteUser ->
+ [{remote_user,RemoteUser}|Env]
+ end.
+%%
+%% Configuration
+%%
+
+%% load
+
+load([$E,$r,$l,$S,$c,$r,$i,$p,$t,$A,$l,$i,$a,$s,$ |ErlScriptAlias],[]) ->
+ case regexp:split(ErlScriptAlias," ") of
+ {ok, [ErlName|Modules]} ->
+ {ok, [], {erl_script_alias, {ErlName,Modules}}};
+ {ok, _} ->
+ {error,?NICE(httpd_conf:clean(ErlScriptAlias)++
+ " is an invalid ErlScriptAlias")}
+ end;
+load([$E,$v,$a,$l,$S,$c,$r,$i,$p,$t,$A,$l,$i,$a,$s,$ |EvalScriptAlias],[]) ->
+ case regexp:split(EvalScriptAlias, " ") of
+ {ok, [EvalName|Modules]} ->
+ {ok, [], {eval_script_alias, {EvalName,Modules}}};
+ {ok, _} ->
+ {error, ?NICE(httpd_conf:clean(EvalScriptAlias)++
+ " is an invalid EvalScriptAlias")}
+ end;
+load([$E,$r,$l,$S,$c,$r,$i,$p,$t,$T,$i,$m,$e,$o,$u,$t,$ |Timeout],[])->
+ case catch list_to_integer(httpd_conf:clean(Timeout)) of
+ TimeoutSec when integer(TimeoutSec) ->
+ {ok, [], {erl_script_timeout,TimeoutSec*1000}};
+ _ ->
+ {error, ?NICE(httpd_conf:clean(Timeout)++
+ " is an invalid ErlScriptTimeout")}
+ end;
+load([$E,$r,$l,$S,$c,$r,$i,$p,$t,$N,$o,$C,$a,$c,$h,$e |CacheArg],[])->
+ case catch list_to_atom(httpd_conf:clean(CacheArg)) of
+ true ->
+ {ok, [], {erl_script_nocache,true}};
+ false ->
+ {ok, [], {erl_script_nocache,false}};
+ _ ->
+ {error, ?NICE(httpd_conf:clean(CacheArg)++
+ " is an invalid ErlScriptNoCache directive")}
+ end.
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% Functions below handles the data from the dynamic webpages %%
+%% That sends data back to the user part by part %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%----------------------------------------------------------------------
+%%Deliver is the callback function users can call to deliver back data to the
+%%client
+%%----------------------------------------------------------------------
+
+deliver(SessionID,Data)when pid(SessionID) ->
+ SessionID ! {ok,Data},
+ ok;
+deliver(SessionID,Data) ->
+ {error,bad_sessionID}.
+
+
+%%----------------------------------------------------------------------
+%% The method that tries to execute the new format
+%%----------------------------------------------------------------------
+
+%%It would be nicer to use erlang:function_exported/3 but if the
+%%Module isn't loaded the function says that it is not loaded
+
+
+try_new_erl_scheme_method(Info,Env,Input,Mod,Func)->
+ process_flag(trap_exit,true),
+ Pid=spawn_link(Mod,Func,[self(),Env,Input]),
+ Timeout=httpd_util:lookup(Info#mod.config_db,erl_script_timeout,?DEFAULT_ERL_TIMEOUT),
+ RetVal=receive_response_data(Info,Pid,0,undefined,[],Timeout),
+ process_flag(trap_exit,false),
+ RetVal.
+
+
+%%----------------------------------------------------------------------
+%%The function recieves the data from the process that generates the page
+%%and send the data to the client through the mod_cgi:send function
+%%----------------------------------------------------------------------
+
+receive_response_data(Info,Pid,Size,StatusCode,AccResponse,Timeout) ->
+ ?DEBUG("receive_response_data()-> Script Size: ~p,StatusCode ~p ,Timeout: ~p ~n",[Size,StatusCode,Timeout]),
+ receive
+ {ok, Response} ->
+ NewStatusCode=mod_cgi:update_status_code(StatusCode,Response),
+
+ ?DEBUG("receive_response_data/2 NewStatusCode: ~p~n",[NewStatusCode]),
+ case mod_cgi:send(Info, NewStatusCode,Response, Size,AccResponse) of
+ socket_closed ->
+ (catch exit(Pid,final)),
+ {proceed,[{response,{already_sent,200,Size}}|Info#mod.data]};
+ head_sent->
+ (catch exit(Pid,final)),
+ {proceed,[{response,{already_sent,200,Size}}|Info#mod.data]};
+ _ ->
+ %%The data is sent and the socket is not closed contine
+ NewSize = mod_cgi:get_new_size(Size,Response),
+ receive_response_data(Info,Pid,NewSize,NewStatusCode,"notempty",Timeout)
+ end;
+ {'EXIT', Pid, Reason} when AccResponse==[] ->
+ {error,not_new_method};
+ {'EXIT', Pid, Reason} when pid(Pid) ->
+ NewStatusCode=mod_cgi:update_status_code(StatusCode,AccResponse),
+ mod_cgi:final_send(Info,NewStatusCode,Size,AccResponse),
+ {proceed, [{response,{already_sent,200,Size}}|Info#mod.data]};
+ %% This should not happen!
+ WhatEver ->
+ NewStatusCode=mod_cgi:update_status_code(StatusCode,AccResponse),
+ mod_cgi:final_send(Info,StatusCode,Size,AccResponse),
+ {proceed, [{response,{already_sent,200,Size}}|Info#mod.data]}
+ after
+ Timeout ->
+ (catch exit(Pid,timeout)), % KILL the port !!!!
+ httpd_socket:close(Info#mod.socket_type,Info#mod.socket),
+ {proceed,[{response,{already_sent,200,Size}}|Info#mod.data]}
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_get.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_get.erl
new file mode 100644
index 0000000000..4136d31669
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_get.erl
@@ -0,0 +1,151 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_get.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
+%%
+-module(mod_get).
+-export([do/1]).
+-include("httpd.hrl").
+
+%% do
+
+do(Info) ->
+ ?DEBUG("do -> entry",[]),
+ case Info#mod.method of
+ "GET" ->
+ case httpd_util:key1search(Info#mod.data,status) of
+ %% A status code has been generated!
+ {StatusCode,PhraseArgs,Reason} ->
+ {proceed,Info#mod.data};
+ %% No status code has been generated!
+ undefined ->
+ case httpd_util:key1search(Info#mod.data,response) of
+ %% No response has been generated!
+ undefined ->
+ do_get(Info);
+ %% A response has been generated or sent!
+ Response ->
+ {proceed,Info#mod.data}
+ end
+ end;
+ %% Not a GET method!
+ _ ->
+ {proceed,Info#mod.data}
+ end.
+
+
+do_get(Info) ->
+ ?DEBUG("do_get -> Request URI: ~p",[Info#mod.request_uri]),
+ Path = mod_alias:path(Info#mod.data, Info#mod.config_db,
+ Info#mod.request_uri),
+ {FileInfo, LastModified} =get_modification_date(Path),
+
+ send_response(Info#mod.socket,Info#mod.socket_type,Path,Info,FileInfo,LastModified).
+
+
+%%The common case when no range is specified
+send_response(Socket,SocketType,Path,Info,FileInfo,LastModified)->
+ %% Send the file!
+ %% Find the modification date of the file
+ case file:open(Path,[raw,binary]) of
+ {ok, FileDescriptor} ->
+ ?DEBUG("do_get -> FileDescriptor: ~p",[FileDescriptor]),
+ Suffix = httpd_util:suffix(Path),
+ MimeType = httpd_util:lookup_mime_default(Info#mod.config_db,
+ Suffix,"text/plain"),
+ %FileInfo=file:read_file_info(Path),
+ Date = httpd_util:rfc1123_date(),
+ Size = integer_to_list(FileInfo#file_info.size),
+ Header=case Info#mod.http_version of
+ "HTTP/1.1" ->
+ [httpd_util:header(200, MimeType, Info#mod.connection),
+ "Last-Modified: ", LastModified, "\r\n",
+ "Etag: ",httpd_util:create_etag(FileInfo),"\r\n",
+ "Content-Length: ",Size,"\r\n\r\n"];
+ "HTTP/1.0" ->
+ [httpd_util:header(200, MimeType, Info#mod.connection),
+ "Last-Modified: ", LastModified, "\r\n",
+ "Content-Length: ",Size,"\r\n\r\n"]
+ end,
+
+ send(Info#mod.socket_type, Info#mod.socket,
+ Header, FileDescriptor),
+ file:close(FileDescriptor),
+ {proceed,[{response,{already_sent,200,
+ FileInfo#file_info.size}},
+ {mime_type,MimeType}|Info#mod.data]};
+ {error, Reason} ->
+
+ {proceed,
+ [{status,open_error(Reason,Info,Path)}|Info#mod.data]}
+ end.
+
+%% send
+
+send(SocketType,Socket,Header,FileDescriptor) ->
+ ?DEBUG("send -> send header",[]),
+ case httpd_socket:deliver(SocketType,Socket,Header) of
+ socket_closed ->
+ ?LOG("send -> socket closed while sending header",[]),
+ socket_close;
+ _ ->
+ send_body(SocketType,Socket,FileDescriptor)
+ end.
+
+send_body(SocketType,Socket,FileDescriptor) ->
+ case file:read(FileDescriptor,?FILE_CHUNK_SIZE) of
+ {ok,Binary} ->
+ ?DEBUG("send_body -> send another chunk: ~p",[size(Binary)]),
+ case httpd_socket:deliver(SocketType,Socket,Binary) of
+ socket_closed ->
+ ?LOG("send_body -> socket closed while sending",[]),
+ socket_close;
+ _ ->
+ send_body(SocketType,Socket,FileDescriptor)
+ end;
+ eof ->
+ ?DEBUG("send_body -> done with this file",[]),
+ eof
+ end.
+
+
+%% open_error - Handle file open failure
+%%
+open_error(eacces,Info,Path) ->
+ open_error(403,Info,Path,"");
+open_error(enoent,Info,Path) ->
+ open_error(404,Info,Path,"");
+open_error(enotdir,Info,Path) ->
+ open_error(404,Info,Path,
+ ": A component of the file name is not a directory");
+open_error(emfile,_Info,Path) ->
+ open_error(500,none,Path,": To many open files");
+open_error({enfile,_},_Info,Path) ->
+ open_error(500,none,Path,": File table overflow");
+open_error(_Reason,_Info,Path) ->
+ open_error(500,none,Path,"").
+
+open_error(StatusCode,none,Path,Reason) ->
+ {StatusCode,none,?NICE("Can't open "++Path++Reason)};
+open_error(StatusCode,Info,Path,Reason) ->
+ {StatusCode,Info#mod.request_uri,?NICE("Can't open "++Path++Reason)}.
+
+get_modification_date(Path)->
+ case file:read_file_info(Path) of
+ {ok, FileInfo0} ->
+ {FileInfo0, httpd_util:rfc1123_date(FileInfo0#file_info.mtime)};
+ _ ->
+ {#file_info{},""}
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_head.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_head.erl
new file mode 100644
index 0000000000..ce71e6532e
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_head.erl
@@ -0,0 +1,89 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_head.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
+%%
+-module(mod_head).
+-export([do/1]).
+
+-include("httpd.hrl").
+
+%% do
+
+do(Info) ->
+ ?DEBUG("do -> entry",[]),
+ case Info#mod.method of
+ "HEAD" ->
+ case httpd_util:key1search(Info#mod.data,status) of
+ %% A status code has been generated!
+ {StatusCode,PhraseArgs,Reason} ->
+ {proceed,Info#mod.data};
+ %% No status code has been generated!
+ _undefined ->
+ case httpd_util:key1search(Info#mod.data,response) of
+ %% No response has been generated!
+ undefined ->
+ do_head(Info);
+ %% A response has been sent! Nothing to do about it!
+ {already_sent,StatusCode,Size} ->
+ {proceed,Info#mod.data};
+ %% A response has been generated!
+ {StatusCode,Response} ->
+ {proceed,Info#mod.data}
+ end
+ end;
+ %% Not a HEAD method!
+ _ ->
+ {proceed,Info#mod.data}
+ end.
+
+do_head(Info) ->
+ ?DEBUG("do_head -> Request URI: ~p",[Info#mod.request_uri]),
+ Path = mod_alias:path(Info#mod.data,Info#mod.config_db,
+ Info#mod.request_uri),
+ Suffix = httpd_util:suffix(Path),
+ %% Does the file exists?
+ case file:read_file_info(Path) of
+ {ok,FileInfo} ->
+ MimeType=httpd_util:lookup_mime_default(Info#mod.config_db,Suffix,"text/plain"),
+ Length=io_lib:write(FileInfo#file_info.size),
+ Head=[{content_type,MimeType},{content_length,Length},{code,200}],
+ {proceed,[{response,{response,Head,nobody}}|Info#mod.data]};
+ {error,Reason} ->
+ {proceed,
+ [{status,read_file_info_error(Reason,Info,Path)}|Info#mod.data]}
+ end.
+
+%% read_file_info_error - Handle file info read failure
+%%
+read_file_info_error(eacces,Info,Path) ->
+ read_file_info_error(403,Info,Path,"");
+read_file_info_error(enoent,Info,Path) ->
+ read_file_info_error(404,Info,Path,"");
+read_file_info_error(enotdir,Info,Path) ->
+ read_file_info_error(404,Info,Path,
+ ": A component of the file name is not a directory");
+read_file_info_error(emfile,_Info,Path) ->
+ read_file_info_error(500,none,Path,": To many open files");
+read_file_info_error({enfile,_},_Info,Path) ->
+ read_file_info_error(500,none,Path,": File table overflow");
+read_file_info_error(_Reason,_Info,Path) ->
+ read_file_info_error(500,none,Path,"").
+
+read_file_info_error(StatusCode,none,Path,Reason) ->
+ {StatusCode,none,?NICE("Can't access "++Path++Reason)};
+read_file_info_error(StatusCode,Info,Path,Reason) ->
+ {StatusCode,Info#mod.request_uri,
+ ?NICE("Can't access "++Path++Reason)}.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_htaccess.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_htaccess.erl
new file mode 100644
index 0000000000..3806ce2e06
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_htaccess.erl
@@ -0,0 +1,1136 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_htaccess.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
+%%
+
+-module(mod_htaccess).
+
+-export([do/1, load/2]).
+-export([debug/0]).
+
+-include("httpd.hrl").
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Public methods that interface the eswapi %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%----------------------------------------------------------------------
+% Public method called by the webbserver to insert the data about
+% Names on accessfiles
+%----------------------------------------------------------------------
+load([$A,$c,$c,$e,$s,$s,$F,$i,$l,$e,$N,$a,$m,$e|FileNames],Context)->
+ CleanFileNames=httpd_conf:clean(FileNames),
+ %%io:format("\n The filenames is:" ++ FileNames ++ "\n"),
+ {ok,[],{access_files,string:tokens(CleanFileNames," ")}}.
+
+
+%----------------------------------------------------------------------
+% Public method that the webbserver calls to control the page
+%----------------------------------------------------------------------
+do(Info)->
+ case httpd_util:key1search(Info#mod.data,status) of
+ {Status_code,PhraseArgs,Reason}->
+ {proceed,Info#mod.data};
+ undefined ->
+ control_path(Info)
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% The functions that start the control if there is a accessfile %%
+%% and if so controls if the dir is allowed or not %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%----------------------------------------------------------------------
+%Info = record mod as specified in httpd.hrl
+%returns either {proceed,Info#mod.data}
+%{proceed,[{status,403....}|Info#mod.data]}
+%{proceed,[{status,401....}|Info#mod.data]}
+%{proceed,[{status,500....}|Info#mod.data]}
+%----------------------------------------------------------------------
+control_path(Info) ->
+ Path = mod_alias:path(Info#mod.data,
+ Info#mod.config_db,
+ Info#mod.request_uri),
+ case isErlScriptOrNotAccessibleFile(Path,Info) of
+ true->
+ {proceed,Info#mod.data};
+ false->
+ case getHtAccessData(Path,Info)of
+ {ok,public}->
+ %%There was no restrictions on the page continue
+ {proceed,Info#mod.data};
+ {error,Reason} ->
+ %Something got wrong continue or quit??????????????????/
+ {proceed,Info#mod.data};
+ {accessData,AccessData}->
+ controlAllowedMethod(Info,AccessData)
+ end
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% These methods controls that the method the client used in the %%
+%% request is one of the limited %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%----------------------------------------------------------------------
+%Control that if the accessmethod used is in the list of modes to challenge
+%
+%Info is the mod record as specified in httpd.hrl
+%AccessData is an ets table whit the data in the .htaccessfiles
+%----------------------------------------------------------------------
+controlAllowedMethod(Info,AccessData)->
+ case allowedRequestMethod(Info,AccessData) of
+ allow->
+ %%The request didnt use one of the limited methods
+ ets:delete(AccessData),
+ {proceed,Info#mod.data};
+ challenge->
+ authenticateUser(Info,AccessData)
+ end.
+
+%----------------------------------------------------------------------
+%Check the specified access method in the .htaccessfile
+%----------------------------------------------------------------------
+allowedRequestMethod(Info,AccessData)->
+ case ets:lookup(AccessData,limit) of
+ [{limit,all}]->
+ challenge;
+ [{limit,Methods}]->
+ isLimitedRequestMethod(Info,Methods)
+ end.
+
+
+%----------------------------------------------------------------------
+%Check the specified accessmethods in the .htaccesfile against the users
+%accessmethod
+%
+%Info is the record from the do call
+%Methods is a list of the methods specified in the .htaccessfile
+%----------------------------------------------------------------------
+isLimitedRequestMethod(Info,Methods)->
+ case lists:member(Info#mod.method,Methods) of
+ true->
+ challenge;
+ false ->
+ allow
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% These methods controls that the user comes from an allowwed net %%
+%% and if so wheather its a valid user or a challenge shall be %%
+%% generated %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%----------------------------------------------------------------------
+%The first thing to control is that the user is from a network
+%that has access to the page
+%----------------------------------------------------------------------
+authenticateUser(Info,AccessData)->
+ case controlNet(Info,AccessData) of
+ allow->
+ %the network is ok control that it is an allowed user
+ authenticateUser2(Info,AccessData);
+ deny->
+ %The user isnt allowed to access the pages from that network
+ ets:delete(AccessData),
+ {proceed,[{status,{403,Info#mod.request_uri,
+ "Restricted area not allowed from your network"}}|Info#mod.data]}
+ end.
+
+
+%----------------------------------------------------------------------
+%The network the user comes from is allowed to view the resources
+%control whether the user needsto supply a password or not
+%----------------------------------------------------------------------
+authenticateUser2(Info,AccessData)->
+ case ets:lookup(AccessData,require) of
+ [{require,AllowedUsers}]->
+ case ets:lookup(AccessData,auth_name) of
+ [{auth_name,Realm}]->
+ authenticateUser2(Info,AccessData,Realm,AllowedUsers);
+ _NoAuthName->
+ ets:delete(AccessData),
+ {break,[{status,{500,none,
+ ?NICE("mod_htaccess:AuthName directive not specified")}}]}
+ end;
+ [] ->
+ %%No special user is required the network is ok so let
+ %%the user in
+ ets:delete(AccessData),
+ {proceed,Info#mod.data}
+ end.
+
+
+%----------------------------------------------------------------------
+%The user must send a userId and a password to get the resource
+%Control if its already in the http-request
+%if the file with users is bad send an 500 response
+%----------------------------------------------------------------------
+authenticateUser2(Info,AccessData,Realm,AllowedUsers)->
+ case authenticateUser(Info,AccessData,AllowedUsers) of
+ allow ->
+ ets:delete(AccessData),
+ {user,Name,Pwd}=getAuthenticatingDataFromHeader(Info),
+ {proceed, [{remote_user_name,Name}|Info#mod.data]};
+ challenge->
+ ets:delete(AccessData),
+ ReasonPhrase = httpd_util:reason_phrase(401),
+ Message = httpd_util:message(401,none,Info#mod.config_db),
+ {proceed,
+ [{response,
+ {401,
+ ["WWW-Authenticate: Basic realm=\"",Realm,
+ "\"\r\n\r\n","<HTML>\n<HEAD>\n<TITLE>",
+ ReasonPhrase,"</TITLE>\n",
+ "</HEAD>\n<BODY>\n<H1>",ReasonPhrase,
+ "</H1>\n",Message,"\n</BODY>\n</HTML>\n"]}}|
+ Info#mod.data]};
+ deny->
+ ets:delete(AccessData),
+ {break,[{status,{500,none,
+ ?NICE("mod_htaccess:Bad path to user or group file")}}]}
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% Methods that validate the netwqork the user comes from %%
+%% according to the allowed networks %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%---------------------------------------------------------------------
+%Controls the users networkaddress agains the specifed networks to
+%allow or deny
+%
+%returns either allow or deny
+%----------------------------------------------------------------------
+controlNet(Info,AccessData)->
+ UserNetwork=getUserNetworkAddress(Info),
+ case getAllowDenyOrder(AccessData) of
+ {_deny,[],_allow,[]}->
+ allow;
+ {deny,[],allow,AllowedNetworks}->
+ controlIfAllowed(AllowedNetworks,UserNetwork,allow,deny);
+ {allow,AllowedNetworks,deny,[]}->
+ controlIfAllowed(AllowedNetworks,UserNetwork,allow,deny);
+
+ {deny,DeniedNetworks,allow,[]}->
+ controlIfAllowed(DeniedNetworks,UserNetwork,allow,deny);
+ {allow,[],deny,DeniedNetworks}->
+ controlIfAllowed(DeniedNetworks,UserNetwork,allow,deny);
+
+ {deny,DeniedNetworks,allow,AllowedNetworks}->
+ controlDenyAllow(DeniedNetworks,AllowedNetworks,UserNetwork);
+ {allow,AllowedNetworks,deny,DeniedNetworks}->
+ controlAllowDeny(AllowedNetworks,DeniedNetworks,UserNetwork)
+ end.
+
+
+%----------------------------------------------------------------------
+%Returns the users IP-Number
+%----------------------------------------------------------------------
+getUserNetworkAddress(Info)->
+ {_Socket,Address}=(Info#mod.init_data)#init_data.peername,
+ Address.
+
+
+%----------------------------------------------------------------------
+%Control the users Ip-number against the ip-numbers in the .htaccessfile
+%----------------------------------------------------------------------
+controlIfAllowed(AllowedNetworks,UserNetwork,IfAllowed,IfDenied)->
+ case AllowedNetworks of
+ [{allow,all}]->
+ IfAllowed;
+ [{deny,all}]->
+ IfDenied;
+ [{deny,Networks}]->
+ memberNetwork(Networks,UserNetwork,IfDenied,IfAllowed);
+ [{allow,Networks}]->
+ memberNetwork(Networks,UserNetwork,IfAllowed,IfDenied);
+ _Error->
+ IfDenied
+ end.
+
+
+%---------------------------------------------------------------------%
+%The Denycontrol isn't neccessary to preform since the allow control %
+%override the deny control %
+%---------------------------------------------------------------------%
+controlDenyAllow(DeniedNetworks,AllowedNetworks,UserNetwork)->
+ case AllowedNetworks of
+ [{allow,all}]->
+ allow;
+ [{allow,Networks}]->
+ case memberNetwork(Networks,UserNetwork) of
+ true->
+ allow;
+ false->
+ deny
+ end
+ end.
+
+
+%----------------------------------------------------------------------%
+%Control that the user is in the allowed list if so control that the %
+%network is in the denied list
+%----------------------------------------------------------------------%
+controlAllowDeny(AllowedNetworks,DeniedNetworks,UserNetwork)->
+ case controlIfAllowed(AllowedNetworks,UserNetwork,allow,deny) of
+ allow->
+ controlIfAllowed(DeniedNetworks,UserNetwork,deny,allow);
+ deny ->
+ deny
+ end.
+
+%----------------------------------------------------------------------
+%Controls if the users Ipnumber is in the list of either denied or
+%allowed networks
+%----------------------------------------------------------------------
+memberNetwork(Networks,UserNetwork,IfTrue,IfFalse)->
+ case memberNetwork(Networks,UserNetwork) of
+ true->
+ IfTrue;
+ false->
+ IfFalse
+ end.
+
+
+%----------------------------------------------------------------------
+%regexp match the users ip-address against the networks in the list of
+%ipadresses or subnet addresses.
+memberNetwork(Networks,UserNetwork)->
+ case lists:filter(fun(Net)->
+ case regexp:match(UserNetwork,
+ formatRegexp(Net)) of
+ {match,1,_}->
+ true;
+ _NotSubNet ->
+ false
+ end
+ end,Networks) of
+ []->
+ false;
+ MemberNetWork ->
+ true
+ end.
+
+
+%----------------------------------------------------------------------
+%Creates a regexp from an ip-number i.e "127.0.0-> "^127[.]0[.]0.*"
+%"127.0.0.-> "^127[.]0[.]0[.].*"
+%----------------------------------------------------------------------
+formatRegexp(Net)->
+ [SubNet1|SubNets]=string:tokens(Net,"."),
+ NetRegexp=lists:foldl(fun(SubNet,Newnet)->
+ Newnet ++ "[.]" ++SubNet
+ end,"^"++SubNet1,SubNets),
+ case string:len(Net)-string:rchr(Net,$.) of
+ 0->
+ NetRegexp++"[.].*";
+ _->
+ NetRegexp++".*"
+ end.
+
+
+%----------------------------------------------------------------------
+%If the user has specified if the allow or deny check shall be preformed
+%first get that order if no order is specified take
+%allow - deny since its harder that deny - allow
+%----------------------------------------------------------------------
+getAllowDenyOrder(AccessData)->
+ case ets:lookup(AccessData,order) of
+ [{order,{deny,allow}}]->
+ {deny,ets:lookup(AccessData,deny),
+ allow,ets:lookup(AccessData,allow)};
+ _DefaultOrder->
+ {allow,ets:lookup(AccessData,allow),
+ deny,ets:lookup(AccessData,deny)}
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% The methods that validates the user %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%----------------------------------------------------------------------
+%Control if there is anyu autheticating data in threquest header
+%if so it controls it against the users in the list Allowed Users
+%----------------------------------------------------------------------
+authenticateUser(Info,AccessData,AllowedUsers)->
+ case getAuthenticatingDataFromHeader(Info) of
+ {user,User,PassWord}->
+ authenticateUser(Info,AccessData,AllowedUsers,
+ {user,User,PassWord});
+ {error,nouser}->
+ challenge;
+ {error,BadData}->
+ challenge
+ end.
+
+
+%----------------------------------------------------------------------
+%Returns the Autheticating data in the http-request
+%----------------------------------------------------------------------
+getAuthenticatingDataFromHeader(Info)->
+ PrsedHeader=Info#mod.parsed_header,
+ case httpd_util:key1search(PrsedHeader,"authorization" ) of
+ undefined->
+ {error,nouser};
+ [$B,$a,$s,$i,$c,$\ |EncodedString]->
+ UnCodedString=httpd_util:decode_base64(EncodedString),
+ case httpd_util:split(UnCodedString,":",2) of
+ {ok,[User,PassWord]}->
+ {user,User,PassWord};
+ {error,Error}->
+ {error,Error}
+ end;
+ BadCredentials ->
+ {error,BadCredentials}
+ end.
+
+
+%----------------------------------------------------------------------
+%Returns a list of all members of the allowed groups
+%----------------------------------------------------------------------
+getGroupMembers(Groups,AllowedGroups)->
+ Allowed=lists:foldl(fun({group,Name,Members},AllowedMembers)->
+ case lists:member(Name,AllowedGroups) of
+ true->
+ AllowedMembers++Members;
+ false ->
+ AllowedMembers
+ end
+ end,[],Groups),
+ {ok,Allowed}.
+
+authenticateUser(Info,AccessData,{{users,[]},{groups,Groups}},User)->
+ authenticateUser(Info,AccessData,{groups,Groups},User);
+authenticateUser(Info,AccessData,{{users,Users},{groups,[]}},User)->
+ authenticateUser(Info,AccessData,{users,Users},User);
+
+authenticateUser(Info,AccessData,{{users,Users},{groups,Groups}},User)->
+ AllowUser=authenticateUser(Info,AccessData,{users,Users},User),
+ AllowGroup=authenticateUser(Info,AccessData,{groups,Groups},User),
+ case {AllowGroup,AllowUser} of
+ {_,allow}->
+ allow;
+ {allow,_}->
+ allow;
+ {challenge,_}->
+ challenge;
+ {_,challenge}->
+ challenge;
+ {_deny,_deny}->
+ deny
+ end;
+
+
+%----------------------------------------------------------------------
+%Controls that the user is a member in one of the allowed group
+%----------------------------------------------------------------------
+authenticateUser(Info,AccessData,{groups,AllowedGroups},{user,User,PassWord})->
+ case getUsers(AccessData,group_file) of
+ {group_data,Groups}->
+ case getGroupMembers(Groups,AllowedGroups) of
+ {ok,Members}->
+ authenticateUser(Info,AccessData,{users,Members},
+ {user,User,PassWord});
+ {error,BadData}->
+ deny
+ end;
+ {error,BadData}->
+ deny
+ end;
+
+
+%----------------------------------------------------------------------
+%Control that the user is one of the allowed users and that the passwd is ok
+%----------------------------------------------------------------------
+authenticateUser(Info,AccessData,{users,AllowedUsers},{user,User,PassWord})->
+ case lists:member(User,AllowedUsers) of
+ true->
+ %Get the usernames and passwords from the file
+ case getUsers(AccessData,user_file) of
+ {error,BadData}->
+ deny;
+ {user_data,Users}->
+ %Users is a list of the users in
+ %the userfile [{user,User,Passwd}]
+ checkPassWord(Users,{user,User,PassWord})
+ end;
+ false ->
+ challenge
+ end.
+
+
+%----------------------------------------------------------------------
+%Control that the user User={user,"UserName","PassWd"} is
+%member of the list of Users
+%----------------------------------------------------------------------
+checkPassWord(Users,User)->
+ case lists:member(User,Users) of
+ true->
+ allow;
+ false->
+ challenge
+ end.
+
+
+%----------------------------------------------------------------------
+%Get the users in the specified file
+%UserOrGroup is an atom that specify if its a group file or a user file
+%i.e. group_file or user_file
+%----------------------------------------------------------------------
+getUsers({file,FileName},UserOrGroup)->
+ case file:open(FileName,[read]) of
+ {ok,AccessFileHandle} ->
+ getUsers({stream,AccessFileHandle},[],UserOrGroup);
+ {error,Reason} ->
+ {error,{Reason,FileName}}
+ end;
+
+
+%----------------------------------------------------------------------
+%The method that starts the lokkong for user files
+%----------------------------------------------------------------------
+
+getUsers(AccessData,UserOrGroup)->
+ case ets:lookup(AccessData,UserOrGroup) of
+ [{UserOrGroup,File}]->
+ getUsers({file,File},UserOrGroup);
+ _ ->
+ {error,noUsers}
+ end.
+
+
+%----------------------------------------------------------------------
+%Reads data from the filehandle File to the list FileData and when its
+%reach the end it returns the list in a tuple {user_file|group_file,FileData}
+%----------------------------------------------------------------------
+getUsers({stream,File},FileData,UserOrGroup)->
+ case io:get_line(File,[]) of
+ eof when UserOrGroup==user_file->
+ {user_data,FileData};
+ eof when UserOrGroup ==group_file->
+ {group_data,FileData};
+ Line ->
+ getUsers({stream,File},
+ formatUser(Line,FileData,UserOrGroup),UserOrGroup)
+ end.
+
+
+%----------------------------------------------------------------------
+%If the line is a comment remove it
+%----------------------------------------------------------------------
+formatUser([$#|UserDataComment],FileData,_UserOrgroup)->
+ FileData;
+
+
+%----------------------------------------------------------------------
+%The user name in the file is Username:Passwd\n
+%Remove the newline sign and split the user name in
+%UserName and Password
+%----------------------------------------------------------------------
+formatUser(UserData,FileData,UserOrGroup)->
+ case string:tokens(UserData," \r\n")of
+ [User|Whitespace] when UserOrGroup==user_file->
+ case string:tokens(User,":") of
+ [Name,PassWord]->
+ [{user,Name,PassWord}|FileData];
+ _Error->
+ FileData
+ end;
+ GroupData when UserOrGroup==group_file ->
+ parseGroupData(GroupData,FileData);
+ _Error ->
+ FileData
+ end.
+
+
+%----------------------------------------------------------------------
+%if everything is right GroupData is on the form
+% ["groupName:", "Member1", "Member2", "Member2"
+%----------------------------------------------------------------------
+parseGroupData([GroupName|GroupData],FileData)->
+ [{group,formatGroupName(GroupName),GroupData}|FileData].
+
+
+%----------------------------------------------------------------------
+%the line in the file is GroupName: Member1 Member2 .....MemberN
+%Remove the : from the group name
+%----------------------------------------------------------------------
+formatGroupName(GroupName)->
+ string:strip(GroupName,right,$:).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% Functions that parses the accessfiles %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%----------------------------------------------------------------------
+%Control that the asset is a real file and not a request for an virtual
+%asset
+%----------------------------------------------------------------------
+isErlScriptOrNotAccessibleFile(Path,Info)->
+ case file:read_file_info(Path) of
+ {ok,_fileInfo}->
+ false;
+ {error,_Reason} ->
+ true
+ end.
+
+
+%----------------------------------------------------------------------
+%Path=PathToTheRequestedFile=String
+%Innfo=record#mod
+%----------------------------------------------------------------------
+getHtAccessData(Path,Info)->
+ HtAccessFileNames=getHtAccessFileNames(Info),
+ case getData(Path,Info,HtAccessFileNames) of
+ {ok,public}->
+ {ok,public};
+ {accessData,AccessData}->
+ {accessData,AccessData};
+ {error,Reason} ->
+ {error,Reason}
+ end.
+
+
+%----------------------------------------------------------------------
+%returns the names of the accessfiles
+%----------------------------------------------------------------------
+getHtAccessFileNames(Info)->
+ case httpd_util:lookup(Info#mod.config_db,access_files) of
+ undefined->
+ [".htaccess"];
+ Files->
+ Files
+ end.
+%----------------------------------------------------------------------
+%HtAccessFileNames=["accessfileName1",..."AccessFileName2"]
+%----------------------------------------------------------------------
+getData(Path,Info,HtAccessFileNames)->
+ case regexp:split(Path,"/") of
+ {error,Error}->
+ {error,Error};
+ {ok,SplittedPath}->
+ getData2(HtAccessFileNames,SplittedPath,Info)
+ end.
+
+
+%----------------------------------------------------------------------
+%Add to together the data in the Splittedpath up to the path
+%that is the alias or the document root
+%Since we do not need to control after any accessfiles before here
+%----------------------------------------------------------------------
+getData2(HtAccessFileNames,SplittedPath,Info)->
+ case getRootPath(SplittedPath,Info) of
+ {error,Path}->
+ {error,Path};
+ {ok,StartPath,RestOfSplittedPath} ->
+ getData2(HtAccessFileNames,StartPath,RestOfSplittedPath,Info)
+ end.
+
+
+%----------------------------------------------------------------------
+%HtAccessFilenames is a list the names the accesssfiles can have
+%Path is the shortest match agains all alias and documentroot
+%rest of splitted path is a list of the parts of the path
+%Info is the mod recod from the server
+%----------------------------------------------------------------------
+getData2(HtAccessFileNames,StartPath,RestOfSplittedPath,Info)->
+ case getHtAccessFiles(HtAccessFileNames,StartPath,RestOfSplittedPath) of
+ []->
+ %No accessfile qiut its a public directory
+ {ok,public};
+ Files ->
+ loadAccessFilesData(Files)
+ end.
+
+
+%----------------------------------------------------------------------
+%Loads the data in the accessFiles specifiied by
+% AccessFiles=["/hoem/public/html/accefile",
+% "/home/public/html/priv/accessfile"]
+%----------------------------------------------------------------------
+loadAccessFilesData(AccessFiles)->
+ loadAccessFilesData(AccessFiles,ets:new(accessData,[])).
+
+
+%----------------------------------------------------------------------
+%Returns the found data
+%----------------------------------------------------------------------
+contextToValues(AccessData)->
+ case ets:lookup(AccessData,context) of
+ [{context,Values}]->
+ ets:delete(AccessData,context),
+ insertContext(AccessData,Values),
+ {accessData,AccessData};
+ _Error->
+ {error,errorInAccessFile}
+ end.
+
+
+insertContext(AccessData,[])->
+ ok;
+
+insertContext(AccessData,[{allow,From}|Values])->
+ insertDenyAllowContext(AccessData,{allow,From}),
+ insertContext(AccessData,Values);
+
+insertContext(AccessData,[{deny,From}|Values])->
+ insertDenyAllowContext(AccessData,{deny,From}),
+ insertContext(AccessData,Values);
+
+insertContext(AccessData,[{require,{GrpOrUsr,Members}}|Values])->
+ case ets:lookup(AccessData,require) of
+ []when GrpOrUsr==users->
+ ets:insert(AccessData,{require,{{users,Members},{groups,[]}}});
+
+ [{require,{{users,Users},{groups,Groups}}}]when GrpOrUsr==users ->
+ ets:insert(AccessData,{require,{{users,Users++Members},
+ {groups,Groups}}});
+ []when GrpOrUsr==groups->
+ ets:insert(AccessData,{require,{{users,[]},{groups,Members}}});
+
+ [{require,{{users,Users},{groups,Groups}}}]when GrpOrUsr==groups ->
+ ets:insert(AccessData,{require,{{users,Users},
+ {groups,Groups++Members}}})
+ end,
+ insertContext(AccessData,Values);
+
+
+
+%%limit and order directive need no transforming they areis just to insert
+insertContext(AccessData,[Elem|Values])->
+ ets:insert(AccessData,Elem),
+ insertContext(AccessData,Values).
+
+
+insertDenyAllowContext(AccessData,{AllowDeny,From})->
+ case From of
+ all->
+ ets:insert(AccessData,{AllowDeny,all});
+ AllowedSubnets->
+ case ets:lookup(AccessData,AllowDeny) of
+ []->
+ ets:insert(AccessData,{AllowDeny,From});
+ [{AllowDeny,all}]->
+ ok;
+ [{AllowDeny,Networks}]->
+ ets:insert(AccessData,{allow,Networks++From})
+ end
+ end.
+
+loadAccessFilesData([],AccessData)->
+ %preform context to limits
+ contextToValues(AccessData),
+ {accessData,AccessData};
+
+%----------------------------------------------------------------------
+%Takes each file in the list and load the data to the ets table
+%AccessData
+%----------------------------------------------------------------------
+loadAccessFilesData([FileName|FileNames],AccessData)->
+ case loadAccessFileData({file,FileName},AccessData) of
+ overRide->
+ loadAccessFilesData(FileNames,AccessData);
+ noOverRide ->
+ {accessData,AccessData};
+ error->
+ ets:delete(AccessData),
+ {error,errorInAccessFile}
+ end.
+
+%----------------------------------------------------------------------
+%opens the filehandle to the specified file
+%----------------------------------------------------------------------
+loadAccessFileData({file,FileName},AccessData)->
+ case file:open(FileName,[read]) of
+ {ok,AccessFileHandle}->
+ loadAccessFileData({stream,AccessFileHandle},AccessData,[]);
+ {error,Reason} ->
+ overRide
+ end.
+
+%----------------------------------------------------------------------
+%%look att each line in the file and add them to the database
+%%When end of file is reached control i overrride is allowed
+%% if so return
+%----------------------------------------------------------------------
+loadAccessFileData({stream,File},AccessData,FileData)->
+ case io:get_line(File,[]) of
+ eof->
+ insertData(AccessData,FileData),
+ case ets:match_object(AccessData,{'_',error}) of
+ []->
+ %Case we got no error control that we can override a
+ %at least some of the values
+ case ets:match_object(AccessData,
+ {allow_over_ride,none}) of
+ []->
+ overRide;
+ _NoOverride->
+ noOverRide
+ end;
+ Errors->
+ error
+ end;
+ Line ->
+ loadAccessFileData({stream,File},AccessData,
+ insertLine(string:strip(Line,left),FileData))
+ end.
+
+%----------------------------------------------------------------------
+%AccessData is a ets table where the previous found data is inserted
+%FileData is a list of the directives in the last parsed file
+%before insertion a control is done that the directive is allowed to
+%override
+%----------------------------------------------------------------------
+insertData(AccessData,{{context,Values},FileData})->
+ insertData(AccessData,[{context,Values}|FileData]);
+
+insertData(AccessData,FileData)->
+ case ets:lookup(AccessData,allow_over_ride) of
+ [{allow_over_ride,all}]->
+ lists:foreach(fun(Elem)->
+ ets:insert(AccessData,Elem)
+ end,FileData);
+ []->
+ lists:foreach(fun(Elem)->
+ ets:insert(AccessData,Elem)
+ end,FileData);
+ [{allow_over_ride,Directives}]when list(Directives)->
+ lists:foreach(fun({Key,Value})->
+ case lists:member(Key,Directives) of
+ true->
+ ok;
+ false ->
+ ets:insert(AccessData,{Key,Value})
+ end
+ end,FileData);
+ [{allow_over_ride,_}]->
+ %Will never appear if the user
+ %aint doing very strang econfig files
+ ok
+ end.
+%----------------------------------------------------------------------
+%Take a line in the accessfile and transform it into a tuple that
+%later can be inserted in to the ets:table
+%----------------------------------------------------------------------
+%%%Here is the alternatives that resides inside the limit context
+
+insertLine([$o,$r,$d,$e,$r|Order],{{context,Values},FileData})->
+ {{context,[{order,getOrder(Order)}|Values]},FileData};
+%%Let the user place a tab in the beginning
+insertLine([$\t,$o,$r,$d,$e,$r|Order],{{context,Values},FileData})->
+ {{context,[{order,getOrder(Order)}|Values]},FileData};
+
+insertLine([$a,$l,$l,$o,$w|Allow],{{context,Values},FileData})->
+ {{context,[{allow,getAllowDenyData(Allow)}|Values]},FileData};
+insertLine([$\t,$a,$l,$l,$o,$w|Allow],{{context,Values},FileData})->
+ {{context,[{allow,getAllowDenyData(Allow)}|Values]},FileData};
+
+insertLine([$d,$e,$n,$y|Deny],{{context,Values},FileData})->
+ {{context,[{deny,getAllowDenyData(Deny)}|Values]},FileData};
+insertLine([$\t,$d,$e,$n,$y|Deny],{{context,Values},FileData})->
+ {{context,[{deny,getAllowDenyData(Deny)}|Values]},FileData};
+
+
+insertLine([$r,$e,$q,$u,$i,$r,$e|Require],{{context,Values},FileData})->
+ {{context,[{require,getRequireData(Require)}|Values]},FileData};
+insertLine([$\t,$r,$e,$q,$u,$i,$r,$e|Require],{{context,Values},FileData})->
+ {{context,[{require,getRequireData(Require)}|Values]},FileData};
+
+
+insertLine([$<,$/,$L,$i,$m,$i,$t|EndLimit],{Context,FileData})->
+ [Context|FileData];
+
+insertLine([$<,$L,$i,$m,$i,$t|Limit],FileData)->
+ {{context,[{limit,getLimits(Limit)}]}, FileData};
+
+
+
+insertLine([$A,$u,$t,$h,$U,$s,$e,$r,$F,$i,$l,$e,$\ |AuthUserFile],FileData)->
+ [{user_file,string:strip(AuthUserFile,right,$\n)}|FileData];
+
+insertLine([$A,$u,$t,$h,$G,$r,$o,$u,$p,$F,$i,$l,$e,$\ |AuthGroupFile],
+ FileData)->
+ [{group_file,string:strip(AuthGroupFile,right,$\n)}|FileData];
+
+insertLine([$A,$l,$l,$o,$w,$O,$v,$e,$r,$R,$i,$d,$e|AllowOverRide],FileData)->
+ [{allow_over_ride,getAllowOverRideData(AllowOverRide)}
+ |FileData];
+
+insertLine([$A,$u,$t,$h,$N,$a,$m,$e,$\ |AuthName],FileData)->
+ [{auth_name,string:strip(AuthName,right,$\n)}|FileData];
+
+insertLine([$A,$u,$t,$h,$T,$y,$p,$e|AuthType],FileData)->
+ [{auth_type,getAuthorizationType(AuthType)}|FileData];
+
+insertLine(_BadDirectiveOrComment,FileData)->
+ FileData.
+
+%----------------------------------------------------------------------
+%transform the Data specified about override to a form that is ieasier
+%handled later
+%Override data="all"|"md5"|"Directive1 .... DirectioveN"
+%----------------------------------------------------------------------
+
+getAllowOverRideData(OverRideData)->
+ case string:tokens(OverRideData," \r\n") of
+ [[$a,$l,$l]|_]->
+ all;
+ [[$n,$o,$n,$e]|_]->
+ none;
+ Directives ->
+ getOverRideDirectives(Directives)
+ end.
+
+getOverRideDirectives(Directives)->
+ lists:map(fun(Directive)->
+ transformDirective(Directive)
+ end,Directives).
+transformDirective([$A,$u,$t,$h,$U,$s,$e,$r,$F,$i,$l,$e|_])->
+ user_file;
+transformDirective([$A,$u,$t,$h,$G,$r,$o,$u,$p,$F,$i,$l,$e|_]) ->
+ group_file;
+transformDirective([$A,$u,$t,$h,$N,$a,$m,$e|_])->
+ auth_name;
+transformDirective([$A,$u,$t,$h,$T,$y,$p,$e|_])->
+ auth_type;
+transformDirective(_UnAllowedOverRideDirective) ->
+ unallowed.
+%----------------------------------------------------------------------
+%Replace the string that specify which method to use for authentication
+%and replace it with the atom for easier mathing
+%----------------------------------------------------------------------
+getAuthorizationType(AuthType)->
+ [Arg|Crap]=string:tokens(AuthType,"\n\r\ "),
+ case Arg of
+ [$B,$a,$s,$i,$c]->
+ basic;
+ [$M,$D,$5] ->
+ md5;
+ _What ->
+ error
+ end.
+%----------------------------------------------------------------------
+%Returns a list of the specified methods to limit or the atom all
+%----------------------------------------------------------------------
+getLimits(Limits)->
+ case regexp:split(Limits,">")of
+ {ok,[_NoEndOnLimit]}->
+ error;
+ {ok,[Methods|Crap]}->
+ case regexp:split(Methods," ")of
+ {ok,[]}->
+ all;
+ {ok,SplittedMethods}->
+ SplittedMethods;
+ {error,Error}->
+ error
+ end;
+ {error,_Error}->
+ error
+ end.
+
+
+%----------------------------------------------------------------------
+% Transform the order to prefrom deny allow control to a tuple of atoms
+%----------------------------------------------------------------------
+getOrder(Order)->
+ [First|Rest]=lists:map(fun(Part)->
+ list_to_atom(Part)
+ end,string:tokens(Order," \n\r")),
+ case First of
+ deny->
+ {deny,allow};
+ allow->
+ {allow,deny};
+ _Error->
+ error
+ end.
+
+%----------------------------------------------------------------------
+% The string AllowDeny is "from all" or "from Subnet1 Subnet2...SubnetN"
+%----------------------------------------------------------------------
+getAllowDenyData(AllowDeny)->
+ case string:tokens(AllowDeny," \n\r") of
+ [_From|AllowDenyData] when length(AllowDenyData)>=1->
+ case lists:nth(1,AllowDenyData) of
+ [$a,$l,$l]->
+ all;
+ Hosts->
+ AllowDenyData
+ end;
+ Error->
+ errror
+ end.
+%----------------------------------------------------------------------
+% Fix the string that describes who is allowed to se the page
+%----------------------------------------------------------------------
+getRequireData(Require)->
+ [UserOrGroup|UserData]=string:tokens(Require," \n\r"),
+ case UserOrGroup of
+ [$u,$s,$e,$r]->
+ {users,UserData};
+ [$g,$r,$o,$u,$p] ->
+ {groups,UserData};
+ _Whatever ->
+ error
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% Methods that collects the searchways to the accessfiles %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%----------------------------------------------------------------------
+% Get the whole path to the different accessfiles
+%----------------------------------------------------------------------
+getHtAccessFiles(HtAccessFileNames,Path,RestOfSplittedPath)->
+ getHtAccessFiles(HtAccessFileNames,Path,RestOfSplittedPath,[]).
+
+getHtAccessFiles(HtAccessFileNames,Path,[[]],HtAccessFiles)->
+ HtAccessFiles ++ accessFilesOfPath(HtAccessFileNames,Path++"/");
+
+getHtAccessFiles(HtAccessFileNames,Path,[],HtAccessFiles)->
+ HtAccessFiles;
+getHtAccessFiles(HtAccessFileNames,Path,[NextDir|RestOfSplittedPath],
+ AccessFiles)->
+ getHtAccessFiles(HtAccessFileNames,Path++"/"++NextDir,RestOfSplittedPath,
+ AccessFiles ++
+ accessFilesOfPath(HtAccessFileNames,Path++"/")).
+
+
+%----------------------------------------------------------------------
+%Control if therer are any accessfies in the path
+%----------------------------------------------------------------------
+accessFilesOfPath(HtAccessFileNames,Path)->
+ lists:foldl(fun(HtAccessFileName,Files)->
+ case file:read_file_info(Path++HtAccessFileName) of
+ {ok,FileInfo}->
+ [Path++HtAccessFileName|Files];
+ {error,_Error} ->
+ Files
+ end
+ end,[],HtAccessFileNames).
+
+
+%----------------------------------------------------------------------
+%Sake the splitted path and joins it up to the documentroot or the alias
+%that match first
+%----------------------------------------------------------------------
+
+getRootPath(SplittedPath,Info)->
+ DocRoot=httpd_util:lookup(Info#mod.config_db,document_root,"/"),
+ PresumtiveRootPath=
+ [DocRoot|lists:map(fun({Alias,RealPath})->
+ RealPath
+ end,
+ httpd_util:multi_lookup(Info#mod.config_db,alias))],
+ getRootPath(PresumtiveRootPath,SplittedPath,Info).
+
+
+getRootPath(PresumtiveRootPath,[[],Splittedpath],Info)->
+ getRootPath(PresumtiveRootPath,["/",Splittedpath],Info);
+
+
+getRootPath(PresumtiveRootPath,[Part,NextPart|SplittedPath],Info)->
+ case lists:member(Part,PresumtiveRootPath)of
+ true->
+ {ok,Part,[NextPart|SplittedPath]};
+ false ->
+ getRootPath(PresumtiveRootPath,
+ [Part++"/"++NextPart|SplittedPath],Info)
+ end;
+
+getRootPath(PresumtiveRootPath,[Part],Info)->
+ case lists:member(Part,PresumtiveRootPath)of
+ true->
+ {ok,Part,[]};
+ false ->
+ {error,Part}
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%Debug methods %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%----------------------------------------------------------------------
+% Simulate the webserver by calling do/1 with apropiate parameters
+%----------------------------------------------------------------------
+debug()->
+ Conf=getConfigData(),
+ Uri=getUri(),
+ {_Proceed,Data}=getDataFromAlias(Conf,Uri),
+ Init_data=#init_data{peername={socket,"127.0.0.1"}},
+ ParsedHeader=headerparts(),
+ do(#mod{init_data=Init_data,
+ data=Data,
+ config_db=Conf,
+ request_uri=Uri,
+ parsed_header=ParsedHeader,
+ method="GET"}).
+
+%----------------------------------------------------------------------
+%Add authenticate data to the fake http-request header
+%----------------------------------------------------------------------
+headerparts()->
+ [{"authorization","Basic " ++ httpd_util:encode_base64("lotta:potta")}].
+
+getDataFromAlias(Conf,Uri)->
+ mod_alias:do(#mod{config_db=Conf,request_uri=Uri}).
+
+getUri()->
+ "/appmon/test/test.html".
+
+getConfigData()->
+ Tab=ets:new(test_inets,[bag,public]),
+ ets:insert(Tab,{server_name,"localhost"}),
+ ets:insert(Tab,{bind_addresss,{127,0,0,1}}),
+ ets:insert(Tab,{erl_script_alias,{"/webcover/erl",["webcover"]}}),
+ ets:insert(Tab,{erl_script_alias,{"/erl",["webappmon"]}}),
+ ets:insert(Tab,{com_type,ip_comm}),
+ ets:insert(Tab,{modules,[mod_alias,mod_auth,mod_header]}),
+ ets:insert(Tab,{default_type,"text/plain"}),
+ ets:insert(Tab,{server_root,
+ "/home/gandalf/marting/exjobb/webtool-1.0/priv/root"}),
+ ets:insert(Tab,{port,8888}),
+ ets:insert(Tab,{document_root,
+ "/home/gandalf/marting/exjobb/webtool-1.0/priv/root"}),
+ ets:insert(Tab,
+ {alias,
+ {"/appmon"
+ ,"/home/gandalf/marting/exjobb/webappmon-1.0/priv"}}),
+ ets:insert(Tab,{alias,
+ {"/webcover"
+ ,"/home/gandalf/marting/exjobb/webcover-1.0/priv"}}),
+ ets:insert(Tab,{access_file,[".htaccess","kalle","pelle"]}),
+ Tab.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_include.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_include.erl
new file mode 100644
index 0000000000..eedbf4a669
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_include.erl
@@ -0,0 +1,722 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_include.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
+%%
+-module(mod_include).
+-export([do/1,parse/2,config/6,include/6,echo/6,fsize/6,flastmod/6,exec/6]).
+
+-include("httpd.hrl").
+
+-define(VMODULE,"INCLUDE").
+-include("httpd_verbosity.hrl").
+
+%% do
+
+do(Info) ->
+ ?vtrace("do",[]),
+ case Info#mod.method of
+ "GET" ->
+ case httpd_util:key1search(Info#mod.data,status) of
+ %% A status code has been generated!
+ {StatusCode,PhraseArgs,Reason} ->
+ {proceed,Info#mod.data};
+ %% No status code has been generated!
+ undefined ->
+ case httpd_util:key1search(Info#mod.data, response) of
+ %% No response has been generated!
+ undefined ->
+ do_include(Info);
+ %% A response has been generated or sent!
+ Response ->
+ {proceed,Info#mod.data}
+ end
+ end;
+ %% Not a GET method!
+ _ ->
+ {proceed,Info#mod.data}
+ end.
+
+do_include(Info) ->
+ ?vtrace("do_include -> entry with"
+ "~n URI: ~p",[Info#mod.request_uri]),
+ Path = mod_alias:path(Info#mod.data,Info#mod.config_db,
+ Info#mod.request_uri),
+ Suffix = httpd_util:suffix(Path),
+ case httpd_util:lookup_mime_default(Info#mod.config_db,Suffix) of
+ "text/x-server-parsed-html" ->
+ HeaderStart =
+ httpd_util:header(200, "text/html", Info#mod.connection),
+ ?vtrace("do_include -> send ~p", [Path]),
+ case send_in(Info,Path,HeaderStart,file:read_file_info(Path)) of
+ {ok, ErrorLog, Size} ->
+ ?vtrace("do_include -> sent ~w bytes", [Size]),
+ {proceed,[{response,{already_sent,200,Size}},
+ {mime_type,"text/html"}|
+ lists:append(ErrorLog,Info#mod.data)]};
+ {error, Reason} ->
+ ?vlog("send in failed:"
+ "~n Reason: ~p"
+ "~n Path: ~p"
+ "~n Info: ~p",
+ [Reason,Info,Path]),
+ {proceed,
+ [{status,send_error(Reason,Info,Path)}|Info#mod.data]}
+ end;
+ _ -> %% Unknown mime type, ignore
+ {proceed,Info#mod.data}
+ end.
+
+
+%%
+%% config directive
+%%
+
+config(Info, Context, ErrorLog, TagList, ValueList, R) ->
+ case verify_tags("config",[errmsg,timefmt,sizefmt],
+ TagList,ValueList) of
+ ok ->
+ {ok,update_context(TagList,ValueList,Context),ErrorLog,"",R};
+ {error,Reason} ->
+ {ok,Context,[{internal_info,Reason}|ErrorLog],
+ httpd_util:key1search(Context,errmsg,""),R}
+ end.
+
+update_context([],[],Context) ->
+ Context;
+update_context([Tag|R1],[Value|R2],Context) ->
+ update_context(R1,R2,[{Tag,Value}|Context]).
+
+verify_tags(Command,ValidTags,TagList,ValueList) when length(TagList)==length(ValueList) ->
+ verify_tags(Command,ValidTags,TagList);
+verify_tags(Command,ValidTags,TagList,ValueList) ->
+ {error,?NICE(Command++" directive has spurious tags")}.
+
+verify_tags(Command, ValidTags, []) ->
+ ok;
+verify_tags(Command, ValidTags, [Tag|Rest]) ->
+ case lists:member(Tag, ValidTags) of
+ true ->
+ verify_tags(Command, ValidTags, Rest);
+ false ->
+ {error,?NICE(Command++" directive has a spurious tag ("++
+ atom_to_list(Tag)++")")}
+ end.
+
+%%
+%% include directive
+%%
+
+include(Info,Context,ErrorLog,[virtual],[VirtualPath],R) ->
+ Aliases = httpd_util:multi_lookup(Info#mod.config_db,alias),
+ {_, Path, _AfterPath} =
+ mod_alias:real_name(Info#mod.config_db, VirtualPath, Aliases),
+ include(Info,Context,ErrorLog,R,Path);
+include(Info, Context, ErrorLog, [file], [FileName], R) ->
+ Path = file(Info#mod.config_db, Info#mod.request_uri, FileName),
+ include(Info, Context, ErrorLog, R, Path);
+include(Info, Context, ErrorLog, TagList, ValueList, R) ->
+ {ok, Context,
+ [{internal_info,?NICE("include directive has a spurious tag")}|
+ ErrorLog], httpd_util:key1search(Context, errmsg, ""), R}.
+
+include(Info, Context, ErrorLog, R, Path) ->
+ ?DEBUG("include -> read file: ~p",[Path]),
+ case file:read_file(Path) of
+ {ok, Body} ->
+ ?DEBUG("include -> size(Body): ~p",[size(Body)]),
+ {ok, NewContext, NewErrorLog, Result} =
+ parse(Info, binary_to_list(Body), Context, ErrorLog, []),
+ {ok, Context, NewErrorLog, Result, R};
+ {error, Reason} ->
+ {ok, Context,
+ [{internal_info, ?NICE("Can't open "++Path)}|ErrorLog],
+ httpd_util:key1search(Context, errmsg, ""), R}
+ end.
+
+file(ConfigDB, RequestURI, FileName) ->
+ Aliases = httpd_util:multi_lookup(ConfigDB, alias),
+ {_, Path, _AfterPath}
+ = mod_alias:real_name(ConfigDB, RequestURI, Aliases),
+ Pwd = filename:dirname(Path),
+ filename:join(Pwd, FileName).
+
+%%
+%% echo directive
+%%
+
+echo(Info,Context,ErrorLog,[var],["DOCUMENT_NAME"],R) ->
+ {ok,Context,ErrorLog,document_name(Info#mod.data,Info#mod.config_db,
+ Info#mod.request_uri),R};
+echo(Info,Context,ErrorLog,[var],["DOCUMENT_URI"],R) ->
+ {ok,Context,ErrorLog,document_uri(Info#mod.config_db,
+ Info#mod.request_uri),R};
+echo(Info,Context,ErrorLog,[var],["QUERY_STRING_UNESCAPED"],R) ->
+ {ok,Context,ErrorLog,query_string_unescaped(Info#mod.request_uri),R};
+echo(Info,Context,ErrorLog,[var],["DATE_LOCAL"],R) ->
+ {ok,Context,ErrorLog,date_local(),R};
+echo(Info,Context,ErrorLog,[var],["DATE_GMT"],R) ->
+ {ok,Context,ErrorLog,date_gmt(),R};
+echo(Info,Context,ErrorLog,[var],["LAST_MODIFIED"],R) ->
+ {ok,Context,ErrorLog,last_modified(Info#mod.data,Info#mod.config_db,
+ Info#mod.request_uri),R};
+echo(Info,Context,ErrorLog,TagList,ValueList,R) ->
+ {ok,Context,
+ [{internal_info,?NICE("echo directive has a spurious tag")}|
+ ErrorLog],"(none)",R}.
+
+document_name(Data,ConfigDB,RequestURI) ->
+ Path = mod_alias:path(Data,ConfigDB,RequestURI),
+ case regexp:match(Path,"[^/]*\$") of
+ {match,Start,Length} ->
+ string:substr(Path,Start,Length);
+ nomatch ->
+ "(none)"
+ end.
+
+document_uri(ConfigDB, RequestURI) ->
+ Aliases = httpd_util:multi_lookup(ConfigDB, alias),
+ {Path, AfterPath} =
+ case mod_alias:real_name(ConfigDB, RequestURI, Aliases) of
+ {_, Name, {[], []}} ->
+ {Name, ""};
+ {_, Name, {PathInfo, []}} ->
+ {Name, "/"++PathInfo};
+ {_, Name, {PathInfo, QueryString}} ->
+ {Name, "/"++PathInfo++"?"++QueryString};
+ {_, Name, _} ->
+ {Name, ""};
+ Gurka ->
+ io:format("Gurka: ~p~n", [Gurka])
+ end,
+ VirtualPath = string:substr(RequestURI, 1,
+ length(RequestURI)-length(AfterPath)),
+ {match, Start, Length} = regexp:match(Path,"[^/]*\$"),
+ FileName = string:substr(Path,Start,Length),
+ case regexp:match(VirtualPath, FileName++"\$") of
+ {match, _, _} ->
+ httpd_util:decode_hex(VirtualPath)++AfterPath;
+ nomatch ->
+ string:strip(httpd_util:decode_hex(VirtualPath),right,$/)++
+ "/"++FileName++AfterPath
+ end.
+
+query_string_unescaped(RequestURI) ->
+ case regexp:match(RequestURI,"[\?].*\$") of
+ {match,Start,Length} ->
+ %% Escape all shell-special variables with \
+ escape(string:substr(RequestURI,Start+1,Length-1));
+ nomatch ->
+ "(none)"
+ end.
+
+escape([]) -> [];
+escape([$;|R]) -> [$\\,$;|escape(R)];
+escape([$&|R]) -> [$\\,$&|escape(R)];
+escape([$(|R]) -> [$\\,$(|escape(R)];
+escape([$)|R]) -> [$\\,$)|escape(R)];
+escape([$||R]) -> [$\\,$||escape(R)];
+escape([$^|R]) -> [$\\,$^|escape(R)];
+escape([$<|R]) -> [$\\,$<|escape(R)];
+escape([$>|R]) -> [$\\,$>|escape(R)];
+escape([$\n|R]) -> [$\\,$\n|escape(R)];
+escape([$ |R]) -> [$\\,$ |escape(R)];
+escape([$\t|R]) -> [$\\,$\t|escape(R)];
+escape([C|R]) -> [C|escape(R)].
+
+date_local() ->
+ {{Year,Month,Day},{Hour,Minute,Second}}=calendar:local_time(),
+ %% Time format hard-wired to: "%a %b %e %T %Y" according to strftime(3)
+ io_lib:format("~s ~s ~2w ~2.2.0w:~2.2.0w:~2.2.0w ~w",
+ [httpd_util:day(calendar:day_of_the_week(Year,Month,Day)),
+ httpd_util:month(Month),Day,Hour,Minute,Second,Year]).
+
+date_gmt() ->
+ {{Year,Month,Day},{Hour,Minute,Second}}=calendar:universal_time(),
+ %% Time format hard-wired to: "%a %b %e %T %Z %Y" according to strftime(3)
+ io_lib:format("~s ~s ~2w ~2.2.0w:~2.2.0w:~2.2.0w GMT ~w",
+ [httpd_util:day(calendar:day_of_the_week(Year,Month,Day)),
+ httpd_util:month(Month),Day,Hour,Minute,Second,Year]).
+
+last_modified(Data,ConfigDB,RequestURI) ->
+ {ok,FileInfo}=file:read_file_info(mod_alias:path(Data,ConfigDB,RequestURI)),
+ {{Year,Month,Day},{Hour,Minute,Second}}=FileInfo#file_info.mtime,
+ io_lib:format("~s ~s ~2w ~2.2.0w:~2.2.0w:~2.2.0w ~w",
+ [httpd_util:day(calendar:day_of_the_week(Year,Month,Day)),
+ httpd_util:month(Month),Day,Hour,Minute,Second,Year]).
+
+%%
+%% fsize directive
+%%
+
+fsize(Info,Context,ErrorLog,[virtual],[VirtualPath],R) ->
+ Aliases=httpd_util:multi_lookup(Info#mod.config_db,alias),
+ {_,Path,AfterPath}=
+ mod_alias:real_name(Info#mod.config_db,VirtualPath,Aliases),
+ fsize(Info, Context, ErrorLog, R, Path);
+fsize(Info,Context,ErrorLog,[file],[FileName],R) ->
+ Path=file(Info#mod.config_db,Info#mod.request_uri,FileName),
+ fsize(Info,Context,ErrorLog,R,Path);
+fsize(Info,Context,ErrorLog,TagList,ValueList,R) ->
+ {ok,Context,[{internal_info,?NICE("fsize directive has a spurious tag")}|
+ ErrorLog],httpd_util:key1search(Context,errmsg,""),R}.
+
+fsize(Info,Context,ErrorLog,R,Path) ->
+ case file:read_file_info(Path) of
+ {ok,FileInfo} ->
+ case httpd_util:key1search(Context,sizefmt) of
+ "bytes" ->
+ {ok,Context,ErrorLog,
+ integer_to_list(FileInfo#file_info.size),R};
+ "abbrev" ->
+ Size = integer_to_list(trunc(FileInfo#file_info.size/1024+1))++"k",
+ {ok,Context,ErrorLog,Size,R};
+ Value->
+ {ok,Context,
+ [{internal_info,
+ ?NICE("fsize directive has a spurious tag value ("++
+ Value++")")}|
+ ErrorLog],
+ httpd_util:key1search(Context, errmsg, ""), R}
+ end;
+ {error,Reason} ->
+ {ok,Context,[{internal_info,?NICE("Can't open "++Path)}|ErrorLog],
+ httpd_util:key1search(Context,errmsg,""),R}
+ end.
+
+%%
+%% flastmod directive
+%%
+
+flastmod(Info, Context, ErrorLog, [virtual], [VirtualPath],R) ->
+ Aliases=httpd_util:multi_lookup(Info#mod.config_db,alias),
+ {_,Path,AfterPath}=
+ mod_alias:real_name(Info#mod.config_db,VirtualPath,Aliases),
+ flastmod(Info,Context,ErrorLog,R,Path);
+flastmod(Info, Context, ErrorLog, [file], [FileName], R) ->
+ Path = file(Info#mod.config_db, Info#mod.request_uri, FileName),
+ flastmod(Info, Context, ErrorLog, R, Path);
+flastmod(Info,Context,ErrorLog,TagList,ValueList,R) ->
+ {ok,Context,[{internal_info,?NICE("flastmod directive has a spurious tag")}|
+ ErrorLog],httpd_util:key1search(Context,errmsg,""),R}.
+
+flastmod(Info,Context,ErrorLog,R,File) ->
+ case file:read_file_info(File) of
+ {ok,FileInfo} ->
+ {{Yr,Mon,Day},{Hour,Minute,Second}}=FileInfo#file_info.mtime,
+ Result=
+ io_lib:format("~s ~s ~2w ~w:~w:~w ~w",
+ [httpd_util:day(
+ calendar:day_of_the_week(Yr,Mon, Day)),
+ httpd_util:month(Mon),Day,Hour,Minute,Second, Yr]),
+ {ok,Context,ErrorLog,Result,R};
+ {error,Reason} ->
+ {ok,Context,[{internal_info,?NICE("Can't open "++File)}|ErrorLog],
+ httpd_util:key1search(Context,errmsg,""),R}
+ end.
+
+%%
+%% exec directive
+%%
+
+exec(Info,Context,ErrorLog,[cmd],[Command],R) ->
+ ?vtrace("exec cmd:~n Command: ~p",[Command]),
+ cmd(Info,Context,ErrorLog,R,Command);
+exec(Info,Context,ErrorLog,[cgi],[RequestURI],R) ->
+ ?vtrace("exec cgi:~n RequestURI: ~p",[RequestURI]),
+ cgi(Info,Context,ErrorLog,R,RequestURI);
+exec(Info,Context,ErrorLog,TagList,ValueList,R) ->
+ ?vtrace("exec with spurious tag:"
+ "~n TagList: ~p"
+ "~n ValueList: ~p",
+ [TagList,ValueList]),
+ {ok, Context,
+ [{internal_info,?NICE("exec directive has a spurious tag")}|
+ ErrorLog], httpd_util:key1search(Context,errmsg,""),R}.
+
+%% cmd
+
+cmd(Info, Context, ErrorLog, R, Command) ->
+ process_flag(trap_exit,true),
+ Env = env(Info),
+ Dir = filename:dirname(Command),
+ Port = (catch open_port({spawn,Command},[stream,{cd,Dir},{env,Env}])),
+ case Port of
+ P when port(P) ->
+ {NewErrorLog, Result} = proxy(Port, ErrorLog),
+ {ok, Context, NewErrorLog, Result, R};
+ {'EXIT', Reason} ->
+ ?vlog("open port failed: exit"
+ "~n URI: ~p"
+ "~n Reason: ~p",
+ [Info#mod.request_uri,Reason]),
+ exit({open_port_failed,Reason,
+ [{uri,Info#mod.request_uri},{script,Command},
+ {env,Env},{dir,Dir}]});
+ O ->
+ ?vlog("open port failed: unknown result"
+ "~n URI: ~p"
+ "~n O: ~p",
+ [Info#mod.request_uri,O]),
+ exit({open_port_failed,O,
+ [{uri,Info#mod.request_uri},{script,Command},
+ {env,Env},{dir,Dir}]})
+ end.
+
+env(Info) ->
+ [{"DOCUMENT_NAME",document_name(Info#mod.data,Info#mod.config_db,
+ Info#mod.request_uri)},
+ {"DOCUMENT_URI", document_uri(Info#mod.config_db, Info#mod.request_uri)},
+ {"QUERY_STRING_UNESCAPED", query_string_unescaped(Info#mod.request_uri)},
+ {"DATE_LOCAL", date_local()},
+ {"DATE_GMT", date_gmt()},
+ {"LAST_MODIFIED", last_modified(Info#mod.data, Info#mod.config_db,
+ Info#mod.request_uri)}
+ ].
+
+%% cgi
+
+cgi(Info, Context, ErrorLog, R, RequestURI) ->
+ ScriptAliases = httpd_util:multi_lookup(Info#mod.config_db, script_alias),
+ case mod_alias:real_script_name(Info#mod.config_db, RequestURI,
+ ScriptAliases) of
+ {Script, AfterScript} ->
+ exec_script(Info,Script,AfterScript,ErrorLog,Context,R);
+ not_a_script ->
+ {ok, Context,
+ [{internal_info, ?NICE(RequestURI++" is not a script")}|
+ ErrorLog], httpd_util:key1search(Context, errmsg, ""),R}
+ end.
+
+remove_header([]) ->
+ [];
+remove_header([$\n,$\n|Rest]) ->
+ Rest;
+remove_header([C|Rest]) ->
+ remove_header(Rest).
+
+
+exec_script(Info,Script,AfterScript,ErrorLog,Context,R) ->
+ process_flag(trap_exit,true),
+ Aliases = httpd_util:multi_lookup(Info#mod.config_db, alias),
+ {_, Path, AfterPath} = mod_alias:real_name(Info#mod.config_db,
+ Info#mod.request_uri,
+ Aliases),
+ Env = env(Info)++mod_cgi:env(Info, Path, AfterPath),
+ Dir = filename:dirname(Path),
+ Port = (catch open_port({spawn,Script},[stream,{env, Env},{cd, Dir}])),
+ case Port of
+ P when port(P) ->
+ %% Send entity body to port.
+ Res = case Info#mod.entity_body of
+ [] ->
+ true;
+ EntityBody ->
+ (catch port_command(Port,EntityBody))
+ end,
+ case Res of
+ {'EXIT', Reason} ->
+ ?vlog("port send failed:"
+ "~n Port: ~p"
+ "~n URI: ~p"
+ "~n Reason: ~p",
+ [Port,Info#mod.request_uri,Reason]),
+ exit({open_cmd_failed,Reason,
+ [{mod,?MODULE},{port,Port},
+ {uri,Info#mod.request_uri},
+ {script,Script},{env,Env},{dir,Dir},
+ {ebody_size,sz(Info#mod.entity_body)}]});
+ true ->
+ {NewErrorLog, Result} = proxy(Port, ErrorLog),
+ {ok, Context, NewErrorLog, remove_header(Result), R}
+ end;
+ {'EXIT', Reason} ->
+ ?vlog("open port failed: exit"
+ "~n URI: ~p"
+ "~n Reason: ~p",
+ [Info#mod.request_uri,Reason]),
+ exit({open_port_failed,Reason,
+ [{mod,?MODULE},{uri,Info#mod.request_uri},{script,Script},
+ {env,Env},{dir,Dir}]});
+ O ->
+ ?vlog("open port failed: unknown result"
+ "~n URI: ~p"
+ "~n O: ~p",
+ [Info#mod.request_uri,O]),
+ exit({open_port_failed,O,
+ [{mod,?MODULE},{uri,Info#mod.request_uri},{script,Script},
+ {env,Env},{dir,Dir}]})
+ end.
+
+
+%%
+%% Port communication
+%%
+
+proxy(Port,ErrorLog) ->
+ process_flag(trap_exit, true),
+ proxy(Port, ErrorLog, []).
+
+proxy(Port, ErrorLog, Result) ->
+ receive
+ {Port, {data, Response}} ->
+ proxy(Port, ErrorLog, lists:append(Result,Response));
+ {'EXIT', Port, normal} when port(Port) ->
+ process_flag(trap_exit, false),
+ {ErrorLog, Result};
+ {'EXIT', Port, Reason} when port(Port) ->
+ process_flag(trap_exit, false),
+ {[{internal_info,
+ ?NICE("Scrambled output from CGI-script")}|ErrorLog],
+ Result};
+ {'EXIT', Pid, Reason} when pid(Pid) ->
+ process_flag(trap_exit, false),
+ {'EXIT', Pid, Reason};
+ %% This should not happen!
+ WhatEver ->
+ process_flag(trap_exit, false),
+ {ErrorLog, Result}
+ end.
+
+
+%% ------
+%% Temporary until I figure out a way to fix send_in_chunks
+%% (comments and directives that start in one chunk but end
+%% in another is not handled).
+%%
+
+send_in(Info, Path,Head, {ok,FileInfo}) ->
+ case file:read_file(Path) of
+ {ok, Bin} ->
+ send_in1(Info, binary_to_list(Bin), Head, FileInfo);
+ {error, Reason} ->
+ ?vlog("failed reading file: ~p",[Reason]),
+ {error, {open,Reason}}
+ end;
+send_in(Info,Path,Head,{error,Reason}) ->
+ ?vlog("failed open file: ~p",[Reason]),
+ {error, {open,Reason}}.
+
+send_in1(Info, Data,Head,FileInfo) ->
+ {ok, _Context, Err, ParsedBody} = parse(Info,Data,?DEFAULT_CONTEXT,[],[]),
+ Size = length(ParsedBody),
+ ?vdebug("send_in1 -> Size: ~p",[Size]),
+ Head1 = case Info#mod.http_version of
+ "HTTP/1.1"->
+ Head ++
+ "Content-Length: " ++
+ integer_to_list(Size) ++
+ "\r\nEtag:" ++
+ httpd_util:create_etag(FileInfo,Size) ++"\r\n" ++
+ "Last-Modified: " ++
+ httpd_util:rfc1123_date(FileInfo#file_info.mtime) ++
+ "\r\n\r\n";
+ _->
+ %% i.e http/1.0 and http/0.9
+ Head ++
+ "Content-Length: " ++
+ integer_to_list(Size) ++
+ "\r\nLast-Modified: " ++
+ httpd_util:rfc1123_date(FileInfo#file_info.mtime) ++
+ "\r\n\r\n"
+ end,
+ httpd_socket:deliver(Info#mod.socket_type,Info#mod.socket,
+ [Head1,ParsedBody]),
+ {ok, Err, Size}.
+
+
+
+%%
+%% Addition to "Fuzzy" HTML parser. This is actually a ugly hack to
+%% avoid putting to much data on the heap. To be rewritten...
+%%
+
+% -define(CHUNK_SIZE, 4096).
+
+% send_in_chunks(Info, Path) ->
+% ?DEBUG("send_in_chunks -> Path: ~p",[Path]),
+% case file:open(Path, [read, raw]) of
+% {ok, Stream} ->
+% send_in_chunks(Info, Stream, ?DEFAULT_CONTEXT,[]);
+% {error, Reason} ->
+% ?ERROR("Failed open file: ~p",[Reason]),
+% {error, {open,Reason}}
+% end.
+
+% send_in_chunks(Info, Stream, Context, ErrorLog) ->
+% case file:read(Stream, ?CHUNK_SIZE) of
+% {ok, Data} ->
+% ?DEBUG("send_in_chunks -> read ~p bytes",[length(Data)]),
+% {ok, NewContext, NewErrorLog, ParsedBody}=
+% parse(Info, Data, Context, ErrorLog, []),
+% httpd_socket:deliver(Info#mod.socket_type,
+% Info#mod.socket, ParsedBody),
+% send_in_chunks(Info,Stream,NewContext,NewErrorLog);
+% eof ->
+% {ok, ErrorLog};
+% {error, Reason} ->
+% ?ERROR("Failed read from file: ~p",[Reason]),
+% {error, {read,Reason}}
+% end.
+
+
+%%
+%% "Fuzzy" HTML parser
+%%
+
+parse(Info,Body) ->
+ parse(Info, Body, ?DEFAULT_CONTEXT, [], []).
+
+parse(Info, [], Context, ErrorLog, Result) ->
+ {ok, Context, lists:reverse(ErrorLog), lists:reverse(Result)};
+parse(Info,[$<,$!,$-,$-,$#|R1],Context,ErrorLog,Result) ->
+ ?DEBUG("parse -> start command directive when length(R1): ~p",[length(R1)]),
+ case catch parse0(R1,Context) of
+ {parse_error,Reason} ->
+ parse(Info,R1,Context,[{internal_info,?NICE(Reason)}|ErrorLog],
+ [$#,$-,$-,$!,$<|Result]);
+ {ok,Context,Command,TagList,ValueList,R2} ->
+ ?DEBUG("parse -> Command: ~p",[Command]),
+ {ok,NewContext,NewErrorLog,MoreResult,R3}=
+ handle(Info,Context,ErrorLog,Command,TagList,ValueList,R2),
+ parse(Info,R3,NewContext,NewErrorLog,lists:reverse(MoreResult)++Result)
+ end;
+parse(Info,[$<,$!,$-,$-|R1],Context,ErrorLog,Result) ->
+ ?DEBUG("parse -> start comment when length(R1) = ~p",[length(R1)]),
+ case catch parse5(R1,[],0) of
+ {parse_error,Reason} ->
+ ?ERROR("parse -> parse error: ~p",[Reason]),
+ parse(Info,R1,Context,[{internal_info,?NICE(Reason)}|ErrorLog],Result);
+ {Comment,R2} ->
+ ?DEBUG("parse -> length(Comment) = ~p, length(R2) = ~p",
+ [length(Comment),length(R2)]),
+ parse(Info,R2,Context,ErrorLog,Comment++Result)
+ end;
+parse(Info,[C|R],Context,ErrorLog,Result) ->
+ parse(Info,R,Context,ErrorLog,[C|Result]).
+
+handle(Info,Context,ErrorLog,Command,TagList,ValueList,R) ->
+ case catch apply(?MODULE,Command,[Info,Context,ErrorLog,TagList,ValueList,
+ R]) of
+ {'EXIT',{undef,_}} ->
+ throw({parse_error,"Unknown command "++atom_to_list(Command)++
+ " in parsed doc"});
+ Result ->
+ Result
+ end.
+
+parse0([],Context) ->
+ throw({parse_error,"Premature EOF in parsed file"});
+parse0([$-,$-,$>|R],Context) ->
+ throw({parse_error,"Premature EOF in parsed file"});
+parse0([$ |R],Context) ->
+ parse0(R,Context);
+parse0(String,Context) ->
+ parse1(String,Context,"").
+
+parse1([],Context,Command) ->
+ throw({parse_error,"Premature EOF in parsed file"});
+parse1([$-,$-,$>|R],Context,Command) ->
+ throw({parse_error,"Premature EOF in parsed file"});
+parse1([$ |R],Context,Command) ->
+ parse2(R,Context,list_to_atom(lists:reverse(Command)),[],[],"");
+parse1([C|R],Context,Command) ->
+ parse1(R,Context,[C|Command]).
+
+parse2([],Context,Command,TagList,ValueList,Tag) ->
+ throw({parse_error,"Premature EOF in parsed file"});
+parse2([$-,$-,$>|R],Context,Command,TagList,ValueList,Tag) ->
+ {ok,Context,Command,TagList,ValueList,R};
+parse2([$ |R],Context,Command,TagList,ValueList,Tag) ->
+ parse2(R,Context,Command,TagList,ValueList,Tag);
+parse2([$=|R],Context,Command,TagList,ValueList,Tag) ->
+ parse3(R,Context,Command,[list_to_atom(lists:reverse(Tag))|TagList],
+ ValueList);
+parse2([C|R],Context,Command,TagList,ValueList,Tag) ->
+ parse2(R,Context,Command,TagList,ValueList,[C|Tag]).
+
+parse3([],Context,Command,TagList,ValueList) ->
+ throw({parse_error,"Premature EOF in parsed file"});
+parse3([$-,$-,$>|R],Context,Command,TagList,ValueList) ->
+ throw({parse_error,"Premature EOF in parsed file"});
+parse3([$ |R],Context,Command,TagList,ValueList) ->
+ parse3(R,Context,Command,TagList,ValueList);
+parse3([$"|R],Context,Command,TagList,ValueList) ->
+ parse4(R,Context,Command,TagList,ValueList,"");
+parse3(String,Context,Command,TagList,ValueList) ->
+ throw({parse_error,"Premature EOF in parsed file"}).
+
+parse4([],Context,Command,TagList,ValueList,Value) ->
+ throw({parse_error,"Premature EOF in parsed file"});
+parse4([$-,$-,$>|R],Context,Command,TagList,ValueList,Value) ->
+ throw({parse_error,"Premature EOF in parsed file"});
+parse4([$"|R],Context,Command,TagList,ValueList,Value) ->
+ parse2(R,Context,Command,TagList,[lists:reverse(Value)|ValueList],"");
+parse4([C|R],Context,Command,TagList,ValueList,Value) ->
+ parse4(R,Context,Command,TagList,ValueList,[C|Value]).
+
+parse5([],Comment,Depth) ->
+ ?ERROR("parse5 -> unterminated comment of ~p bytes when Depth = ~p",
+ [length(Comment),Depth]),
+ throw({parse_error,"Premature EOF in parsed file"});
+parse5([$<,$!,$-,$-|R],Comment,Depth) ->
+ parse5(R,[$-,$-,$!,$<|Comment],Depth+1);
+parse5([$-,$-,$>|R],Comment,0) ->
+ {">--"++Comment++"--!<",R};
+parse5([$-,$-,$>|R],Comment,Depth) ->
+ parse5(R,[$>,$-,$-|Comment],Depth-1);
+parse5([C|R],Comment,Depth) ->
+ parse5(R,[C|Comment],Depth).
+
+
+sz(B) when binary(B) -> {binary,size(B)};
+sz(L) when list(L) -> {list,length(L)};
+sz(_) -> undefined.
+
+
+%% send_error - Handle failure to send the file
+%%
+send_error({open,Reason},Info,Path) -> open_error(Reason,Info,Path);
+send_error({read,Reason},Info,Path) -> read_error(Reason,Info,Path).
+
+
+%% open_error - Handle file open failure
+%%
+open_error(eacces,Info,Path) ->
+ open_error(403,Info,Path,"");
+open_error(enoent,Info,Path) ->
+ open_error(404,Info,Path,"");
+open_error(enotdir,Info,Path) ->
+ open_error(404,Info,Path,
+ ": A component of the file name is not a directory");
+open_error(emfile,_Info,Path) ->
+ open_error(500,none,Path,": To many open files");
+open_error({enfile,_},_Info,Path) ->
+ open_error(500,none,Path,": File table overflow");
+open_error(_Reason,_Info,Path) ->
+ open_error(500,none,Path,"").
+
+open_error(StatusCode,none,Path,Reason) ->
+ {StatusCode,none,?NICE("Can't open "++Path++Reason)};
+open_error(StatusCode,Info,Path,Reason) ->
+ {StatusCode,Info#mod.request_uri,?NICE("Can't open "++Path++Reason)}.
+
+read_error(_Reason,_Info,Path) ->
+ read_error(500,none,Path,"").
+
+read_error(StatusCode,none,Path,Reason) ->
+ {StatusCode,none,?NICE("Can't read "++Path++Reason)};
+read_error(StatusCode,Info,Path,Reason) ->
+ {StatusCode,Info#mod.request_uri,?NICE("Can't read "++Path++Reason)}.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_log.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_log.erl
new file mode 100644
index 0000000000..a24ac425e6
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_log.erl
@@ -0,0 +1,250 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_log.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
+%%
+-module(mod_log).
+-export([do/1,error_log/5,security_log/2,load/2,store/2,remove/1]).
+
+-export([report_error/2]).
+
+-include("httpd.hrl").
+
+-define(VMODULE,"LOG").
+-include("httpd_verbosity.hrl").
+
+%% do
+
+do(Info) ->
+ AuthUser = auth_user(Info#mod.data),
+ Date = custom_date(),
+ log_internal_info(Info,Date,Info#mod.data),
+ case httpd_util:key1search(Info#mod.data,status) of
+ %% A status code has been generated!
+ {StatusCode,PhraseArgs,Reason} ->
+ transfer_log(Info,"-",AuthUser,Date,StatusCode,0),
+ if
+ StatusCode >= 400 ->
+ error_log(Info,Date,Reason);
+ true ->
+ not_an_error
+ end,
+ {proceed,Info#mod.data};
+ %% No status code has been generated!
+ undefined ->
+ case httpd_util:key1search(Info#mod.data,response) of
+ {already_sent,StatusCode,Size} ->
+ transfer_log(Info,"-",AuthUser,Date,StatusCode,Size),
+ {proceed,Info#mod.data};
+ {response,Head,Body} ->
+ Size=httpd_util:key1search(Head,content_length,unknown),
+ Code=httpd_util:key1search(Head,code,unknown),
+ transfer_log(Info,"-",AuthUser,Date,Code,Size),
+ {proceed,Info#mod.data};
+ {StatusCode,Response} ->
+ transfer_log(Info,"-",AuthUser,Date,200,
+ httpd_util:flatlength(Response)),
+ {proceed,Info#mod.data};
+ undefined ->
+ transfer_log(Info,"-",AuthUser,Date,200,0),
+ {proceed,Info#mod.data}
+ end
+ end.
+
+custom_date() ->
+ LocalTime=calendar:local_time(),
+ UniversalTime=calendar:universal_time(),
+ Minutes=round(diff_in_minutes(LocalTime,UniversalTime)),
+ {{YYYY,MM,DD},{Hour,Min,Sec}}=LocalTime,
+ Date =
+ io_lib:format("~.2.0w/~.3s/~.4w:~.2.0w:~.2.0w:~.2.0w ~c~.2.0w~.2.0w",
+ [DD, httpd_util:month(MM), YYYY, Hour, Min, Sec,
+ sign(Minutes),
+ abs(Minutes) div 60, abs(Minutes) rem 60]),
+ lists:flatten(Date).
+
+diff_in_minutes(L,U) ->
+ (calendar:datetime_to_gregorian_seconds(L) -
+ calendar:datetime_to_gregorian_seconds(U))/60.
+
+sign(Minutes) when Minutes > 0 ->
+ $+;
+sign(Minutes) ->
+ $-.
+
+auth_user(Data) ->
+ case httpd_util:key1search(Data,remote_user) of
+ undefined ->
+ "-";
+ RemoteUser ->
+ RemoteUser
+ end.
+
+%% log_internal_info
+
+log_internal_info(Info,Date,[]) ->
+ ok;
+log_internal_info(Info,Date,[{internal_info,Reason}|Rest]) ->
+ error_log(Info,Date,Reason),
+ log_internal_info(Info,Date,Rest);
+log_internal_info(Info,Date,[_|Rest]) ->
+ log_internal_info(Info,Date,Rest).
+
+%% transfer_log
+
+transfer_log(Info,RFC931,AuthUser,Date,StatusCode,Bytes) ->
+ case httpd_util:lookup(Info#mod.config_db,transfer_log) of
+ undefined ->
+ no_transfer_log;
+ TransferLog ->
+ {PortNumber,RemoteHost}=(Info#mod.init_data)#init_data.peername,
+ case (catch io:format(TransferLog, "~s ~s ~s [~s] \"~s\" ~w ~w~n",
+ [RemoteHost, RFC931, AuthUser,
+ Date, Info#mod.request_line,
+ StatusCode, Bytes])) of
+ ok ->
+ ok;
+ Error ->
+ error_logger:error_report(Error)
+ end
+ end.
+
+%% security log
+
+security_log(Info, Reason) ->
+ case httpd_util:lookup(Info#mod.config_db, security_log) of
+ undefined ->
+ no_security_log;
+ SecurityLog ->
+ io:format(SecurityLog,"[~s] ~s~n", [custom_date(), Reason])
+ end.
+
+%% error_log
+
+error_log(Info,Date,Reason) ->
+ case httpd_util:lookup(Info#mod.config_db, error_log) of
+ undefined ->
+ no_error_log;
+ ErrorLog ->
+ {PortNumber,RemoteHost}=(Info#mod.init_data)#init_data.peername,
+ io:format(ErrorLog,"[~s] access to ~s failed for ~s, reason: ~p~n",
+ [Date,Info#mod.request_uri,RemoteHost,Reason])
+ end.
+
+error_log(SocketType,Socket,ConfigDB,{PortNumber,RemoteHost},Reason) ->
+ case httpd_util:lookup(ConfigDB,error_log) of
+ undefined ->
+ no_error_log;
+ ErrorLog ->
+ Date=custom_date(),
+ io:format(ErrorLog,"[~s] server crash for ~s, reason: ~p~n",
+ [Date,RemoteHost,Reason]),
+ ok
+ end.
+
+report_error(ConfigDB,Error) ->
+ case httpd_util:lookup(ConfigDB,error_log) of
+ undefined ->
+ no_error_log;
+ ErrorLog ->
+ Date=custom_date(),
+ io:format(ErrorLog,"[~s] reporting error: ~s~n",[Date,Error]),
+ ok
+ end.
+
+%%
+%% Configuration
+%%
+
+%% load
+
+load([$T,$r,$a,$n,$s,$f,$e,$r,$L,$o,$g,$ |TransferLog],[]) ->
+ {ok,[],{transfer_log,httpd_conf:clean(TransferLog)}};
+load([$E,$r,$r,$o,$r,$L,$o,$g,$ |ErrorLog],[]) ->
+ {ok,[],{error_log,httpd_conf:clean(ErrorLog)}};
+load([$S,$e,$c,$u,$r,$i,$t,$y,$L,$o,$g,$ |SecurityLog], []) ->
+ {ok, [], {security_log, httpd_conf:clean(SecurityLog)}}.
+
+%% store
+
+store({transfer_log,TransferLog},ConfigList) ->
+ case create_log(TransferLog,ConfigList) of
+ {ok,TransferLogStream} ->
+ {ok,{transfer_log,TransferLogStream}};
+ {error,Reason} ->
+ {error,Reason}
+ end;
+store({error_log,ErrorLog},ConfigList) ->
+ case create_log(ErrorLog,ConfigList) of
+ {ok,ErrorLogStream} ->
+ {ok,{error_log,ErrorLogStream}};
+ {error,Reason} ->
+ {error,Reason}
+ end;
+store({security_log, SecurityLog},ConfigList) ->
+ case create_log(SecurityLog, ConfigList) of
+ {ok, SecurityLogStream} ->
+ {ok, {security_log, SecurityLogStream}};
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+create_log(LogFile,ConfigList) ->
+ Filename = httpd_conf:clean(LogFile),
+ case filename:pathtype(Filename) of
+ absolute ->
+ case file:open(Filename, [read,write]) of
+ {ok,LogStream} ->
+ file:position(LogStream,{eof,0}),
+ {ok,LogStream};
+ {error,_} ->
+ {error,?NICE("Can't create "++Filename)}
+ end;
+ volumerelative ->
+ case file:open(Filename, [read,write]) of
+ {ok,LogStream} ->
+ file:position(LogStream,{eof,0}),
+ {ok,LogStream};
+ {error,_} ->
+ {error,?NICE("Can't create "++Filename)}
+ end;
+ relative ->
+ case httpd_util:key1search(ConfigList,server_root) of
+ undefined ->
+ {error,
+ ?NICE(Filename++
+ " is an invalid logfile name beacuse ServerRoot is not defined")};
+ ServerRoot ->
+ AbsoluteFilename=filename:join(ServerRoot,Filename),
+ case file:open(AbsoluteFilename, [read,write]) of
+ {ok,LogStream} ->
+ file:position(LogStream,{eof,0}),
+ {ok,LogStream};
+ {error,Reason} ->
+ {error,?NICE("Can't create "++AbsoluteFilename)}
+ end
+ end
+ end.
+
+%% remove
+
+remove(ConfigDB) ->
+ lists:foreach(fun([Stream]) -> file:close(Stream) end,
+ ets:match(ConfigDB,{transfer_log,'$1'})),
+ lists:foreach(fun([Stream]) -> file:close(Stream) end,
+ ets:match(ConfigDB,{error_log,'$1'})),
+ lists:foreach(fun([Stream]) -> file:close(Stream) end,
+ ets:match(ConfigDB,{security_log,'$1'})),
+ ok.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_range.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_range.erl
new file mode 100644
index 0000000000..f623dc3ec8
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_range.erl
@@ -0,0 +1,380 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_range.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
+%%
+-module(mod_range).
+-export([do/1]).
+-include("httpd.hrl").
+
+%% do
+
+
+
+do(Info) ->
+ ?DEBUG("do -> entry",[]),
+ case Info#mod.method of
+ "GET" ->
+ case httpd_util:key1search(Info#mod.data,status) of
+ %% A status code has been generated!
+ {StatusCode,PhraseArgs,Reason} ->
+ {proceed,Info#mod.data};
+ %% No status code has been generated!
+ undefined ->
+ case httpd_util:key1search(Info#mod.data,response) of
+ %% No response has been generated!
+ undefined ->
+ case httpd_util:key1search(Info#mod.parsed_header,"range") of
+ undefined ->
+ %Not a range response
+ {proceed,Info#mod.data};
+ Range ->
+ %%Control that there weren't a if-range field that stopped
+ %%The range request in favor for the whole file
+ case httpd_util:key1search(Info#mod.data,if_range) of
+ send_file ->
+ {proceed,Info#mod.data};
+ _undefined ->
+ do_get_range(Info,Range)
+ end
+ end;
+ %% A response has been generated or sent!
+ Response ->
+ {proceed,Info#mod.data}
+ end
+ end;
+ %% Not a GET method!
+ _ ->
+ {proceed,Info#mod.data}
+ end.
+
+do_get_range(Info,Ranges) ->
+ ?DEBUG("do_get_range -> Request URI: ~p",[Info#mod.request_uri]),
+ Path = mod_alias:path(Info#mod.data, Info#mod.config_db,
+ Info#mod.request_uri),
+ {FileInfo, LastModified} =get_modification_date(Path),
+ send_range_response(Path,Info,Ranges,FileInfo,LastModified).
+
+
+send_range_response(Path,Info,Ranges,FileInfo,LastModified)->
+ case parse_ranges(Ranges) of
+ error->
+ ?ERROR("send_range_response-> Unparsable range request",[]),
+ {proceed,Info#mod.data};
+ {multipart,RangeList}->
+ send_multi_range_response(Path,Info,RangeList);
+ {Start,Stop}->
+ send_range_response(Path,Info,Start,Stop,FileInfo,LastModified)
+ end.
+%%More than one range specified
+%%Send a multipart reponse to the user
+%
+%%An example of an multipart range response
+
+% HTTP/1.1 206 Partial Content
+% Date:Wed 15 Nov 1995 04:08:23 GMT
+% Last-modified:Wed 14 Nov 1995 04:08:23 GMT
+% Content-type: multipart/byteranges; boundary="SeparatorString"
+%
+% --"SeparatorString"
+% Content-Type: application/pdf
+% Content-Range: bytes 500-600/1010
+% .... The data..... 101 bytes
+%
+% --"SeparatorString"
+% Content-Type: application/pdf
+% Content-Range: bytes 700-1009/1010
+% .... The data.....
+
+
+
+send_multi_range_response(Path,Info,RangeList)->
+ case file:open(Path, [raw,binary]) of
+ {ok, FileDescriptor} ->
+ file:close(FileDescriptor),
+ ?DEBUG("send_multi_range_response -> FileDescriptor: ~p",[FileDescriptor]),
+ Suffix = httpd_util:suffix(Path),
+ PartMimeType = httpd_util:lookup_mime_default(Info#mod.config_db,Suffix,"text/plain"),
+ Date = httpd_util:rfc1123_date(),
+ {FileInfo,LastModified}=get_modification_date(Path),
+ case valid_ranges(RangeList,Path,FileInfo) of
+ {ValidRanges,true}->
+ ?DEBUG("send_multi_range_response -> Ranges are valid:",[]),
+ %Apache breaks the standard by sending the size field in the Header.
+ Header = [{code,206},
+ {content_type,"multipart/byteranges;boundary=RangeBoundarySeparator"},
+ {etag,httpd_util:create_etag(FileInfo)},
+ {last_modified,LastModified}
+ ],
+ ?DEBUG("send_multi_range_response -> Valid Ranges: ~p",[RagneList]),
+ Body={fun send_multiranges/4,[ValidRanges,Info,PartMimeType,Path]},
+ {proceed,[{response,{response,Header,Body}}|Info#mod.data]};
+ _ ->
+ {proceed, [{status, {416,"Range not valid",bad_range_boundaries }}]}
+ end;
+ {error, Reason} ->
+ ?ERROR("do_get -> failed open file: ~p",[Reason]),
+ {proceed,Info#mod.data}
+ end.
+
+send_multiranges(ValidRanges,Info,PartMimeType,Path)->
+ ?DEBUG("send_multiranges -> Start sending the ranges",[]),
+ case file:open(Path, [raw,binary]) of
+ {ok,FileDescriptor} ->
+ lists:foreach(fun(Range)->
+ send_multipart_start(Range,Info,PartMimeType,FileDescriptor)
+ end,ValidRanges),
+ file:close(FileDescriptor),
+ %%Sends an end of the multipart
+ httpd_socket:deliver(Info#mod.socket_type,Info#mod.socket,"\r\n--RangeBoundarySeparator--"),
+ sent;
+ _ ->
+ close
+ end.
+
+send_multipart_start({{Start,End},{StartByte,EndByte,Size}},Info,PartMimeType,FileDescriptor)when StartByte<Size->
+ PartHeader=["\r\n--RangeBoundarySeparator\r\n","Content-type: ",PartMimeType,"\r\n",
+ "Content-Range:bytes=",integer_to_list(StartByte),"-",integer_to_list(EndByte),"/",
+ integer_to_list(Size),"\r\n\r\n"],
+ send_part_start(Info#mod.socket_type,Info#mod.socket,PartHeader,FileDescriptor,Start,End);
+
+
+send_multipart_start({{Start,End},{StartByte,EndByte,Size}},Info,PartMimeType,FileDescriptor)->
+ PartHeader=["\r\n--RangeBoundarySeparator\r\n","Content-type: ",PartMimeType,"\r\n",
+ "Content-Range:bytes=",integer_to_list(Size-(StartByte-Size)),"-",integer_to_list(EndByte),"/",
+ integer_to_list(Size),"\r\n\r\n"],
+ send_part_start(Info#mod.socket_type,Info#mod.socket,PartHeader,FileDescriptor,Start,End).
+
+send_part_start(SocketType,Socket,PartHeader,FileDescriptor,Start,End)->
+ case httpd_socket:deliver(SocketType,Socket,PartHeader) of
+ ok ->
+ send_part_start(SocketType,Socket,FileDescriptor,Start,End);
+ _ ->
+ close
+ end.
+
+send_range_response(Path,Info,Start,Stop,FileInfo,LastModified)->
+ case file:open(Path, [raw,binary]) of
+ {ok, FileDescriptor} ->
+ file:close(FileDescriptor),
+ ?DEBUG("send_range_response -> FileDescriptor: ~p",[FileDescriptor]),
+ Suffix = httpd_util:suffix(Path),
+ MimeType = httpd_util:lookup_mime_default(Info#mod.config_db,Suffix,"text/plain"),
+ Date = httpd_util:rfc1123_date(),
+ Size = get_range_size(Start,Stop,FileInfo),
+ case valid_range(Start,Stop,FileInfo) of
+ {true,StartByte,EndByte,TotByte}->
+ Head=[{code,206},{content_type, MimeType},
+ {last_modified, LastModified},
+ {etag,httpd_util:create_etag(FileInfo)},
+ {content_range,["bytes=",integer_to_list(StartByte),"-",
+ integer_to_list(EndByte),"/",integer_to_list(TotByte)]},
+ {content_length,Size}],
+ BodyFunc=fun send_range_body/5,
+ Arg=[Info#mod.socket_type, Info#mod.socket,Path,Start,Stop],
+ {proceed,[{response,{response,Head,{BodyFunc,Arg}}}|Info#mod.data]};
+ {false,Reason} ->
+ {proceed, [{status, {416,Reason,bad_range_boundaries }}]}
+ end;
+ {error, Reason} ->
+ ?ERROR("send_range_response -> failed open file: ~p",[Reason]),
+ {proceed,Info#mod.data}
+ end.
+
+
+send_range_body(SocketType,Socket,Path,Start,End) ->
+ ?DEBUG("mod_range -> send_range_body",[]),
+ case file:open(Path, [raw,binary]) of
+ {ok,FileDescriptor} ->
+ send_part_start(SocketType,Socket,FileDescriptor,Start,End),
+ file:close(FileDescriptor);
+ _ ->
+ close
+ end.
+
+send_part_start(SocketType,Socket,FileDescriptor,Start,End) ->
+ case Start of
+ from_end ->
+ file:position(FileDescriptor,{eof,End}),
+ send_body(SocketType,Socket,FileDescriptor);
+ from_start ->
+ file:position(FileDescriptor,{bof,End}),
+ send_body(SocketType,Socket,FileDescriptor);
+ Byte when integer(Byte) ->
+ file:position(FileDescriptor,{bof,Start}),
+ send_part(SocketType,Socket,FileDescriptor,End)
+ end,
+ sent.
+
+
+%%This function could replace send_body by calling it with Start=0 end =FileSize
+%% But i gues it would be stupid when we look at performance
+send_part(SocketType,Socket,FileDescriptor,End)->
+ case file:position(FileDescriptor,{cur,0}) of
+ {ok,NewPos} ->
+ if
+ NewPos > End ->
+ ok;
+ true ->
+ Size=get_file_chunk_size(NewPos,End,?FILE_CHUNK_SIZE),
+ case file:read(FileDescriptor,Size) of
+ eof ->
+ ok;
+ {error,Reason} ->
+ ok;
+ {ok,Binary} ->
+ case httpd_socket:deliver(SocketType,Socket,Binary) of
+ socket_closed ->
+ ?LOG("send_range of body -> socket closed while sending",[]),
+ socket_close;
+ _ ->
+ send_part(SocketType,Socket,FileDescriptor,End)
+ end
+ end
+ end;
+ _->
+ ok
+ end.
+
+%% validate that the range is in the limits of the file
+valid_ranges(RangeList,Path,FileInfo)->
+ lists:mapfoldl(fun({Start,End},Acc)->
+ case Acc of
+ true ->
+ case valid_range(Start,End,FileInfo) of
+ {true,StartB,EndB,Size}->
+ {{{Start,End},{StartB,EndB,Size}},true};
+ _ ->
+ false
+ end;
+ _ ->
+ {false,false}
+ end
+ end,true,RangeList).
+
+
+
+valid_range(from_end,End,FileInfo)->
+ Size=FileInfo#file_info.size,
+ if
+ End < Size ->
+ {true,(Size+End),Size-1,Size};
+ true ->
+ false
+ end;
+valid_range(from_start,End,FileInfo)->
+ Size=FileInfo#file_info.size,
+ if
+ End < Size ->
+ {true,End,Size-1,Size};
+ true ->
+ false
+ end;
+
+valid_range(Start,End,FileInfo)when Start=<End->
+ case FileInfo#file_info.size of
+ FileSize when Start< FileSize ->
+ case FileInfo#file_info.size of
+ Size when End<Size ->
+ {true,Start,End,FileInfo#file_info.size};
+ Size ->
+ {true,Start,Size-1,Size}
+ end;
+ _->
+ {false,"The size of the range is negative"}
+ end;
+
+valid_range(Start,End,FileInfo)->
+ {false,"Range starts out of file boundaries"}.
+%% Find the modification date of the file
+get_modification_date(Path)->
+ case file:read_file_info(Path) of
+ {ok, FileInfo0} ->
+ {FileInfo0, httpd_util:rfc1123_date(FileInfo0#file_info.mtime)};
+ _ ->
+ {#file_info{},""}
+ end.
+
+%Calculate the size of the chunk to read
+
+get_file_chunk_size(Position,End,DefaultChunkSize)when (Position+DefaultChunkSize) =< End->
+ DefaultChunkSize;
+get_file_chunk_size(Position,End,DefaultChunkSize)->
+ (End-Position) +1.
+
+
+
+%Get the size of the range to send. Remember that
+%A range is from startbyte up to endbyte which means that
+%the nuber of byte in a range is (StartByte-EndByte)+1
+
+get_range_size(from_end,Stop,FileInfo)->
+ integer_to_list(-1*Stop);
+
+get_range_size(from_start,StartByte,FileInfo) ->
+ integer_to_list((((FileInfo#file_info.size)-StartByte)));
+
+get_range_size(StartByte,EndByte,FileInfo) ->
+ integer_to_list((EndByte-StartByte)+1).
+
+parse_ranges([$\ ,$b,$y,$t,$e,$s,$\=|Ranges])->
+ parse_ranges([$b,$y,$t,$e,$s,$\=|Ranges]);
+parse_ranges([$b,$y,$t,$e,$s,$\=|Ranges])->
+ case string:tokens(Ranges,", ") of
+ [Range] ->
+ parse_range(Range);
+ [Range1|SplittedRanges]->
+ {multipart,lists:map(fun parse_range/1,[Range1|SplittedRanges])}
+ end;
+%Bad unit
+parse_ranges(Ranges)->
+ io:format("Bad Ranges : ~p",[Ranges]),
+ error.
+%Parse the range specification from the request to {Start,End}
+%Start=End : Numreric string | []
+
+parse_range(Range)->
+ format_range(split_range(Range,[],[])).
+format_range({[],BytesFromEnd})->
+ {from_end,-1*(list_to_integer(BytesFromEnd))};
+format_range({StartByte,[]})->
+ {from_start,list_to_integer(StartByte)};
+format_range({StartByte,EndByte})->
+ {list_to_integer(StartByte),list_to_integer(EndByte)}.
+%Last case return the splitted range
+split_range([],Current,Other)->
+ {lists:reverse(Other),lists:reverse(Current)};
+
+split_range([$-|Rest],Current,Other)->
+ split_range(Rest,Other,Current);
+
+split_range([N|Rest],Current,End) ->
+ split_range(Rest,[N|Current],End).
+
+send_body(SocketType,Socket,FileDescriptor) ->
+ case file:read(FileDescriptor,?FILE_CHUNK_SIZE) of
+ {ok,Binary} ->
+ ?DEBUG("send_body -> send another chunk: ~p",[size(Binary)]),
+ case httpd_socket:deliver(SocketType,Socket,Binary) of
+ socket_closed ->
+ ?LOG("send_body -> socket closed while sending",[]),
+ socket_close;
+ _ ->
+ send_body(SocketType,Socket,FileDescriptor)
+ end;
+ eof ->
+ ?DEBUG("send_body -> done with this file",[]),
+ eof
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_responsecontrol.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_responsecontrol.erl
new file mode 100644
index 0000000000..b818a15f32
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_responsecontrol.erl
@@ -0,0 +1,320 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_responsecontrol.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
+%%
+
+-module(mod_responsecontrol).
+-export([do/1]).
+
+-include("httpd.hrl").
+
+
+do(Info) ->
+ ?DEBUG("do -> response_control",[]),
+ case httpd_util:key1search(Info#mod.data,status) of
+ %% A status code has been generated!
+ {StatusCode,PhraseArgs,Reason} ->
+ {proceed,Info#mod.data};
+ %% No status code has been generated!
+ undefined ->
+ case httpd_util:key1search(Info#mod.data,response) of
+ %% No response has been generated!
+ undefined ->
+ case do_responsecontrol(Info) of
+ continue ->
+ {proceed,Info#mod.data};
+ Response ->
+ {proceed,[Response|Info#mod.data]}
+ end;
+ %% A response has been generated or sent!
+ Response ->
+ {proceed,Info#mod.data}
+ end
+ end.
+
+
+%%----------------------------------------------------------------------
+%%Control that the request header did not contians any limitations
+%%wheather a response shall be createed or not
+%%----------------------------------------------------------------------
+
+do_responsecontrol(Info) ->
+ ?DEBUG("do_response_control -> Request URI: ~p",[Info#mod.request_uri]),
+ Path = mod_alias:path(Info#mod.data, Info#mod.config_db,
+ Info#mod.request_uri),
+ case file:read_file_info(Path) of
+ {ok, FileInfo} ->
+ control(Path,Info,FileInfo);
+ _ ->
+ %% The requested asset is not a plain file and then it must
+ %% be generated everytime its requested
+ continue
+ end.
+
+%%----------------------------------------------------------------------
+%%Control the If-Match, If-None-Match, and If-Modified-Since
+%%----------------------------------------------------------------------
+
+
+%% If a client sends more then one of the if-XXXX fields in a request
+%% The standard says it does not specify the behaviuor so I specified it :-)
+%% The priority between the fields is
+%% 1.If-modified
+%% 2.If-Unmodified
+%% 3.If-Match
+%% 4.If-Nomatch
+
+%% This means if more than one of the fields are in the request the
+%% field with highest priority will be used
+
+%%If the request is a range request the If-Range field will be the winner.
+
+control(Path,Info,FileInfo)->
+ case control_range(Path,Info,FileInfo) of
+ undefined ->
+ case control_Etag(Path,Info,FileInfo) of
+ undefined ->
+ case control_modification(Path,Info,FileInfo) of
+ continue ->
+ continue;
+ ReturnValue ->
+ send_return_value(ReturnValue,FileInfo)
+ end;
+ continue ->
+ continue;
+ ReturnValue ->
+ send_return_value(ReturnValue,FileInfo)
+ end;
+ Response->
+ Response
+ end.
+
+%%----------------------------------------------------------------------
+%%If there are both a range and an if-range field control if
+%%----------------------------------------------------------------------
+control_range(Path,Info,FileInfo) ->
+ case httpd_util:key1search(Info#mod.parsed_header,"range") of
+ undefined->
+ undefined;
+ _Range ->
+ case httpd_util:key1search(Info#mod.parsed_header,"if-range") of
+ undefined ->
+ undefined;
+ EtagOrDate ->
+ control_if_range(Path,Info,FileInfo,EtagOrDate)
+ end
+ end.
+
+control_if_range(Path,Info,FileInfo,EtagOrDate) ->
+ case httpd_util:convert_request_date(strip_date(EtagOrDate)) of
+ bad_date ->
+ FileEtag=httpd_util:create_etag(FileInfo),
+ case FileEtag of
+ EtagOrDate ->
+ continue;
+ _ ->
+ {if_range,send_file}
+ end;
+ ErlDate ->
+ %%We got the date in the request if it is
+ case control_modification_data(Info,FileInfo#file_info.mtime,"if-range") of
+ modified ->
+ {if_range,send_file};
+ _UnmodifiedOrUndefined->
+ continue
+ end
+ end.
+
+%%----------------------------------------------------------------------
+%%Controls the values of the If-Match and I-None-Mtch
+%%----------------------------------------------------------------------
+control_Etag(Path,Info,FileInfo)->
+ FileEtag=httpd_util:create_etag(FileInfo),
+ %%Control if the E-Tag for the resource matches one of the Etags in
+ %%the -if-match header field
+ case control_match(Info,FileInfo,"if-match",FileEtag) of
+ nomatch ->
+ %%None of the Etags in the if-match field matched the current
+ %%Etag for the resource return a 304
+ {412,Info,Path};
+ match ->
+ continue;
+ undefined ->
+ case control_match(Info,FileInfo,"if-none-match",FileEtag) of
+ nomatch ->
+ continue;
+ match ->
+ case Info#mod.method of
+ "GET" ->
+ {304,Info,Path};
+ "HEAD" ->
+ {304,Info,Path};
+ _OtherrequestMethod ->
+ {412,Info,Path}
+ end;
+ undefined ->
+ undefined
+ end
+ end.
+
+%%----------------------------------------------------------------------
+%%Control if there are any Etags for HeaderField in the request if so
+%%Control if they match the Etag for the requested file
+%%----------------------------------------------------------------------
+control_match(Info,FileInfo,HeaderField,FileEtag)->
+ case split_etags(httpd_util:key1search(Info#mod.parsed_header,HeaderField)) of
+ undefined->
+ undefined;
+ Etags->
+ %%Control that the match any star not is availible
+ case lists:member("*",Etags) of
+ true->
+ match;
+ false->
+ compare_etags(FileEtag,Etags)
+ end
+ end.
+
+%%----------------------------------------------------------------------
+%%Split the etags from the request
+%%----------------------------------------------------------------------
+split_etags(undefined)->
+ undefined;
+split_etags(Tags) ->
+ string:tokens(Tags,", ").
+
+%%----------------------------------------------------------------------
+%%Control if the etag for the file is in the list
+%%----------------------------------------------------------------------
+compare_etags(Tag,Etags) ->
+ case lists:member(Tag,Etags) of
+ true ->
+ match;
+ _ ->
+ nomatch
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%%Control if the file is modificated %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%----------------------------------------------------------------------
+%%Control the If-Modified-Since and If-Not-Modified-Since header fields
+%%----------------------------------------------------------------------
+control_modification(Path,Info,FileInfo)->
+ ?DEBUG("control_modification() -> entry",[]),
+ case control_modification_data(Info,FileInfo#file_info.mtime,"if-modified-since") of
+ modified->
+ continue;
+ unmodified->
+ {304,Info,Path};
+ undefined ->
+ case control_modification_data(Info,FileInfo#file_info.mtime,"if-unmodified-since") of
+ modified ->
+ {412,Info,Path};
+ _ContinueUndefined ->
+ continue
+ end
+ end.
+
+%%----------------------------------------------------------------------
+%%Controls the date from the http-request if-modified-since and
+%%if-not-modified-since against the modification data of the
+%%File
+%%----------------------------------------------------------------------
+%%Info is the record about the request
+%%ModificationTime is the time the file was edited last
+%%Header Field is the name of the field to control
+
+control_modification_data(Info,ModificationTime,HeaderField)->
+ case strip_date(httpd_util:key1search(Info#mod.parsed_header,HeaderField)) of
+ undefined->
+ undefined;
+ LastModified0 ->
+ LastModified=httpd_util:convert_request_date(LastModified0),
+ ?DEBUG("control_modification_data() -> "
+ "~n Request-Field: ~s"
+ "~n FileLastModified: ~p"
+ "~n FieldValue: ~p",
+ [HeaderField,ModificationTime,LastModified]),
+ case LastModified of
+ bad_date ->
+ undefined;
+ _ ->
+ FileTime=calendar:datetime_to_gregorian_seconds(ModificationTime),
+ FieldTime=calendar:datetime_to_gregorian_seconds(LastModified),
+ if
+ FileTime=<FieldTime ->
+ ?DEBUG("File unmodified~n", []),
+ unmodified;
+ FileTime>=FieldTime ->
+ ?DEBUG("File modified~n", []),
+ modified
+ end
+ end
+ end.
+
+%%----------------------------------------------------------------------
+%%Compare to dates on the form {{YYYY,MM,DD},{HH,MIN,SS}}
+%%If the first date is the biggest returns biggest1 (read biggestFirst)
+%%If the first date is smaller
+% compare_date(Date,bad_date)->
+% bad_date;
+
+% compare_date({D1,T1},{D2,T2})->
+% case compare_date1(D1,D2) of
+% equal ->
+% compare_date1(T1,T2);
+% GTorLT->
+% GTorLT
+% end.
+
+% compare_date1({T1,T2,T3},{T12,T22,T32}) when T1>T12 ->
+% bigger1;
+% compare_date1({T1,T2,T3},{T1,T22,T32}) when T2>T22 ->
+% bigger1;
+% compare_date1({T1,T2,T3},{T1,T2,T32}) when T3>T32 ->
+% bigger1;
+% compare_date1({T1,T2,T3},{T1,T2,T3})->
+% equal;
+% compare_date1(_D1,_D2)->
+% smaller1.
+
+
+%% IE4 & NS4 sends an extra '; length=xxxx' string at the end of the If-Modified-Since
+%% header, we detect this and ignore it (the RFCs does not mention this).
+strip_date(undefined) ->
+ undefined;
+strip_date([]) ->
+ [];
+strip_date([$;,$ |Rest]) ->
+ [];
+strip_date([C|Rest]) ->
+ [C|strip_date(Rest)].
+
+send_return_value({412,_,_},FileInfo)->
+ {status,{412,none,"Precondition Failed"}};
+
+send_return_value({304,Info,Path},FileInfo)->
+ Suffix=httpd_util:suffix(Path),
+ MimeType = httpd_util:lookup_mime_default(Info#mod.config_db,Suffix,"text/plain"),
+ Header = [{code,304},
+ {etag,httpd_util:create_etag(FileInfo)},
+ {content_length,0},
+ {last_modified,httpd_util:rfc1123_date(FileInfo#file_info.mtime)}],
+ {response,{response,Header,nobody}}.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_security.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_security.erl
new file mode 100644
index 0000000000..b4d52d1599
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_security.erl
@@ -0,0 +1,307 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_security.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
+%%
+-module(mod_security).
+
+%% Security Audit Functionality
+
+%% User API exports
+-export([list_blocked_users/1, list_blocked_users/2, list_blocked_users/3,
+ block_user/4, block_user/5,
+ unblock_user/2, unblock_user/3, unblock_user/4,
+ list_auth_users/1, list_auth_users/2, list_auth_users/3]).
+
+%% module API exports
+-export([do/1, load/2, store/2, remove/1]).
+
+-include("httpd.hrl").
+
+-define(VMODULE,"SEC").
+-include("httpd_verbosity.hrl").
+
+
+%% do/1
+do(Info) ->
+ ?vdebug("~n do with ~n Info: ~p",[Info]),
+ %% Check and see if any user has been authorized.
+ case httpd_util:key1search(Info#mod.data,remote_user,not_defined_user) of
+ not_defined_user ->
+ %% No user has been authorized.
+ case httpd_util:key1search(Info#mod.data, status) of
+ %% A status code has been generated!
+ {401, PhraseArgs, Reason} ->
+ case httpd_util:key1search(Info#mod.parsed_header,
+ "authorization") of
+ undefined ->
+ %% Not an authorization attempt (server just replied to
+ %% challenge for authentication)
+ {proceed, Info#mod.data};
+ [$B,$a,$s,$i,$c,$ |EncodedString] ->
+ %% Someone tried to authenticate, and obviously failed!
+ ?vlog("~n Authentication failed: ~s",
+ [EncodedString]),
+ report_failed(Info, EncodedString,"Failed authentication"),
+ take_failed_action(Info, EncodedString),
+ {proceed, Info#mod.data}
+ end;
+ _ ->
+ {proceed, Info#mod.data}
+ end;
+ User ->
+ %% A user has been authenticated, now is he blocked ?
+ ?vtrace("user '~p' authentication",[User]),
+ Path = mod_alias:path(Info#mod.data,
+ Info#mod.config_db,
+ Info#mod.request_uri),
+ {Dir, SDirData} = secretp(Path, Info#mod.config_db),
+ Addr = httpd_util:lookup(Info#mod.config_db, bind_address),
+ Port = httpd_util:lookup(Info#mod.config_db, port),
+ DF = httpd_util:key1search(SDirData, data_file),
+ case mod_security_server:check_blocked_user(Info, User,
+ SDirData,
+ Addr, Port) of
+ true ->
+ ?vtrace("user blocked",[]),
+ report_failed(Info,httpd_util:decode_base64(User) ,"User Blocked"),
+ {proceed, [{status, {403, Info#mod.request_uri, ""}}|Info#mod.data]};
+ false ->
+ ?vtrace("user not blocked",[]),
+ EncodedUser=httpd_util:decode_base64(User),
+ report_failed(Info, EncodedUser,"Authentication Succedded"),
+ mod_security_server:store_successful_auth(Addr, Port,
+ User, SDirData),
+ {proceed, Info#mod.data}
+ end
+ end.
+
+
+
+report_failed(Info, EncodedString,Event) ->
+ Request = Info#mod.request_line,
+ Decoded = httpd_util:decode_base64(EncodedString),
+ {PortNumber,RemoteHost}=(Info#mod.init_data)#init_data.peername,
+ String = RemoteHost++" : " ++ Event ++ " : "++Request++" : "++Decoded,
+ mod_disk_log:security_log(Info,String),
+ mod_log:security_log(Info, String).
+
+take_failed_action(Info, EncodedString) ->
+ Path = mod_alias:path(Info#mod.data,Info#mod.config_db, Info#mod.request_uri),
+ {Dir, SDirData} = secretp(Path, Info#mod.config_db),
+ Addr = httpd_util:lookup(Info#mod.config_db, bind_address),
+ Port = httpd_util:lookup(Info#mod.config_db, port),
+ DecodedString = httpd_util:decode_base64(EncodedString),
+ mod_security_server:store_failed_auth(Info, Addr, Port,
+ DecodedString, SDirData).
+
+secretp(Path, ConfigDB) ->
+ Directories = ets:match(ConfigDB,{directory,'$1','_'}),
+ case secret_path(Path, Directories) of
+ {yes, Directory} ->
+ SDirs0 = httpd_util:multi_lookup(ConfigDB, security_directory),
+ SDir = lists:filter(fun(X) ->
+ lists:member({path, Directory}, X)
+ end, SDirs0),
+ {Directory, lists:flatten(SDir)};
+ no ->
+ error_report({internal_error_secretp, ?MODULE}),
+ {[], []}
+ end.
+
+secret_path(Path,Directories) ->
+ secret_path(Path, httpd_util:uniq(lists:sort(Directories)), to_be_found).
+
+secret_path(Path, [], to_be_found) ->
+ no;
+secret_path(Path, [], Directory) ->
+ {yes, Directory};
+secret_path(Path, [[NewDirectory]|Rest], Directory) ->
+ case regexp:match(Path, NewDirectory) of
+ {match, _, _} when Directory == to_be_found ->
+ secret_path(Path, Rest, NewDirectory);
+ {match, _, Length} when Length > length(Directory)->
+ secret_path(Path, Rest, NewDirectory);
+ {match, _, Length} ->
+ secret_path(Path, Rest, Directory);
+ nomatch ->
+ secret_path(Path, Rest, Directory)
+ end.
+
+
+load([$<,$D,$i,$r,$e,$c,$t,$o,$r,$y,$ |Directory],[]) ->
+ Dir = httpd_conf:custom_clean(Directory,"",">"),
+ {ok, [{security_directory, Dir, [{path, Dir}]}]};
+load(eof,[{security_directory,Directory, DirData}|_]) ->
+ {error, ?NICE("Premature end-of-file in "++Directory)};
+load([$S,$e,$c,$u,$r,$i,$t,$y,$D,$a,$t,$a,$F,$i,$l,$e,$ |FileName],
+ [{security_directory, Dir, DirData}]) ->
+ File = httpd_conf:clean(FileName),
+ {ok, [{security_directory, Dir, [{data_file, File}|DirData]}]};
+load([$S,$e,$c,$u,$r,$i,$t,$y,$C,$a,$l,$l,$b,$a,$c,$k,$M,$o,$d,$u,$l,$e,$ |ModuleName],
+ [{security_directory, Dir, DirData}]) ->
+ Mod = list_to_atom(httpd_conf:clean(ModuleName)),
+ {ok, [{security_directory, Dir, [{callback_module, Mod}|DirData]}]};
+load([$S,$e,$c,$u,$r,$i,$t,$y,$M,$a,$x,$R,$e,$t,$r,$i,$e,$s,$ |Retries],
+ [{security_directory, Dir, DirData}]) ->
+ MaxRetries = httpd_conf:clean(Retries),
+ load_return_int_tag("SecurityMaxRetries", max_retries,
+ httpd_conf:clean(Retries), Dir, DirData);
+load([$S,$e,$c,$u,$r,$i,$t,$y,$B,$l,$o,$c,$k,$T,$i,$m,$e,$ |Time],
+ [{security_directory, Dir, DirData}]) ->
+ load_return_int_tag("SecurityBlockTime", block_time,
+ httpd_conf:clean(Time), Dir, DirData);
+load([$S,$e,$c,$u,$r,$i,$t,$y,$F,$a,$i,$l,$E,$x,$p,$i,$r,$e,$T,$i,$m,$e,$ |Time],
+ [{security_directory, Dir, DirData}]) ->
+ load_return_int_tag("SecurityFailExpireTime", fail_expire_time,
+ httpd_conf:clean(Time), Dir, DirData);
+load([$S,$e,$c,$u,$r,$i,$t,$y,$A,$u,$t,$h,$T,$i,$m,$e,$o,$u,$t,$ |Time0],
+ [{security_directory, Dir, DirData}]) ->
+ Time = httpd_conf:clean(Time0),
+ load_return_int_tag("SecurityAuthTimeout", auth_timeout,
+ httpd_conf:clean(Time), Dir, DirData);
+load([$A,$u,$t,$h,$N,$a,$m,$e,$ |Name0],
+ [{security_directory, Dir, DirData}]) ->
+ Name = httpd_conf:clean(Name0),
+ {ok, [{security_directory, Dir, [{auth_name, Name}|DirData]}]};
+load("</Directory>",[{security_directory,Directory, DirData}]) ->
+ {ok, [], {security_directory, Directory, DirData}}.
+
+load_return_int_tag(Name, Atom, Time, Dir, DirData) ->
+ case Time of
+ "infinity" ->
+ {ok, [{security_directory, Dir, [{Atom, 99999999999999999999999999999}|DirData]}]};
+ Int ->
+ case catch list_to_integer(Time) of
+ {'EXIT', _} ->
+ {error, Time++" is an invalid "++Name};
+ Val ->
+ {ok, [{security_directory, Dir, [{Atom, Val}|DirData]}]}
+ end
+ end.
+
+store({security_directory, Dir0, DirData}, ConfigList) ->
+ ?CDEBUG("store(security_directory) -> ~n"
+ " Dir0: ~p~n"
+ " DirData: ~p",
+ [Dir0, DirData]),
+ Addr = httpd_util:key1search(ConfigList, bind_address),
+ Port = httpd_util:key1search(ConfigList, port),
+ mod_security_server:start(Addr, Port),
+ SR = httpd_util:key1search(ConfigList, server_root),
+ Dir =
+ case filename:pathtype(Dir0) of
+ relative ->
+ filename:join(SR, Dir0);
+ _ ->
+ Dir0
+ end,
+ case httpd_util:key1search(DirData, data_file, no_data_file) of
+ no_data_file ->
+ {error, no_security_data_file};
+ DataFile0 ->
+ DataFile =
+ case filename:pathtype(DataFile0) of
+ relative ->
+ filename:join(SR, DataFile0);
+ _ ->
+ DataFile0
+ end,
+ case mod_security_server:new_table(Addr, Port, DataFile) of
+ {ok, TwoTables} ->
+ NewDirData0 = lists:keyreplace(data_file, 1, DirData,
+ {data_file, TwoTables}),
+ NewDirData1 = case Addr of
+ undefined ->
+ [{port,Port}|NewDirData0];
+ _ ->
+ [{port,Port},{bind_address,Addr}|
+ NewDirData0]
+ end,
+ {ok, {security_directory,NewDirData1}};
+ {error, Err} ->
+ {error, {{open_data_file, DataFile}, Err}}
+ end
+ end.
+
+
+remove(ConfigDB) ->
+ Addr = case ets:lookup(ConfigDB, bind_address) of
+ [] ->
+ undefined;
+ [{bind_address, Address}] ->
+ Address
+ end,
+ [{port, Port}] = ets:lookup(ConfigDB, port),
+ mod_security_server:delete_tables(Addr, Port),
+ mod_security_server:stop(Addr, Port).
+
+
+%%
+%% User API
+%%
+
+%% list_blocked_users
+
+list_blocked_users(Port) ->
+ list_blocked_users(undefined, Port).
+
+list_blocked_users(Port, Dir) when integer(Port) ->
+ list_blocked_users(undefined,Port,Dir);
+list_blocked_users(Addr, Port) when integer(Port) ->
+ mod_security_server:list_blocked_users(Addr, Port).
+
+list_blocked_users(Addr, Port, Dir) ->
+ mod_security_server:list_blocked_users(Addr, Port, Dir).
+
+
+%% block_user
+
+block_user(User, Port, Dir, Time) ->
+ block_user(User, undefined, Port, Dir, Time).
+block_user(User, Addr, Port, Dir, Time) ->
+ mod_security_server:block_user(User, Addr, Port, Dir, Time).
+
+
+%% unblock_user
+
+unblock_user(User, Port) ->
+ unblock_user(User, undefined, Port).
+
+unblock_user(User, Port, Dir) when integer(Port) ->
+ unblock_user(User, undefined, Port, Dir);
+unblock_user(User, Addr, Port) when integer(Port) ->
+ mod_security_server:unblock_user(User, Addr, Port).
+
+unblock_user(User, Addr, Port, Dir) ->
+ mod_security_server:unblock_user(User, Addr, Port, Dir).
+
+
+%% list_auth_users
+
+list_auth_users(Port) ->
+ list_auth_users(undefined,Port).
+
+list_auth_users(Port, Dir) when integer(Port) ->
+ list_auth_users(undefined, Port, Dir);
+list_auth_users(Addr, Port) when integer(Port) ->
+ mod_security_server:list_auth_users(Addr, Port).
+
+list_auth_users(Addr, Port, Dir) ->
+ mod_security_server:list_auth_users(Addr, Port, Dir).
+
+
+error_report(M) ->
+ error_logger:error_report(M).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_security_server.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_security_server.erl
new file mode 100644
index 0000000000..81156c24e8
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_security_server.erl
@@ -0,0 +1,727 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_security_server.erl,v 1.1 2008/12/17 09:53:36 mikpe Exp $
+%%
+%% Security Audit Functionality
+
+%%
+%% The gen_server code.
+%%
+%% A gen_server is needed in this module to take care of shared access to the
+%% data file used to store failed and successful authentications aswell as
+%% user blocks.
+%%
+%% The storage model is a write-through model with both an ets and a dets
+%% table. Writes are done to both the ets and then the dets table, but reads
+%% are only done from the ets table.
+%%
+%% This approach also enables parallelism when using dets by returning the
+%% same dets table identifier when opening several files with the same
+%% physical location.
+%%
+%% NOTE: This could be implemented using a single dets table, as it is
+%% possible to open a dets file with the ram_file flag, but this
+%% would require periodical sync's to disk, and it would be hard
+%% to decide when such an operation should occur.
+%%
+
+
+-module(mod_security_server).
+
+-include("httpd.hrl").
+-include("httpd_verbosity.hrl").
+
+
+-behaviour(gen_server).
+
+
+%% User API exports (called via mod_security)
+-export([list_blocked_users/2, list_blocked_users/3,
+ block_user/5,
+ unblock_user/3, unblock_user/4,
+ list_auth_users/2, list_auth_users/3]).
+
+%% Internal exports (for mod_security only)
+-export([start/2, stop/1, stop/2,
+ new_table/3, delete_tables/2,
+ store_failed_auth/5, store_successful_auth/4,
+ check_blocked_user/5]).
+
+%% gen_server exports
+-export([start_link/3,
+ init/1,
+ handle_info/2, handle_call/3, handle_cast/2,
+ terminate/2,
+ code_change/3]).
+
+-export([verbosity/3]).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% External API %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% start_link/3
+%%
+%% NOTE: This is called by httpd_misc_sup when the process is started
+%%
+
+start_link(Addr, Port, Verbosity) ->
+ ?vtrace("start_link -> entry with"
+ "~n Addr: ~p"
+ "~n Port: ~p", [Addr, Port]),
+ Name = make_name(Addr, Port),
+ gen_server:start_link({local, Name}, ?MODULE, [Verbosity],
+ [{timeout, infinity}]).
+
+
+%% start/2
+%% Called by the mod_security module.
+
+start(Addr, Port) ->
+ Name = make_name(Addr, Port),
+ case whereis(Name) of
+ undefined ->
+ Verbosity = get(security_verbosity),
+ case httpd_misc_sup:start_sec_server(Addr, Port, Verbosity) of
+ {ok, Pid} ->
+ put(security_server, Pid),
+ ok;
+ Error ->
+ exit({failed_start_security_server, Error})
+ end;
+ _ -> %% Already started...
+ ok
+ end.
+
+
+%% stop
+
+stop(Port) ->
+ stop(undefined, Port).
+stop(Addr, Port) ->
+ Name = make_name(Addr, Port),
+ case whereis(Name) of
+ undefined ->
+ ok;
+ _ ->
+ httpd_misc_sup:stop_sec_server(Addr, Port)
+ end.
+
+
+%% verbosity
+
+verbosity(Addr, Port, Verbosity) ->
+ Name = make_name(Addr, Port),
+ Req = {verbosity, Verbosity},
+ call(Name, Req).
+
+
+%% list_blocked_users
+
+list_blocked_users(Addr, Port) ->
+ Name = make_name(Addr,Port),
+ Req = {list_blocked_users, Addr, Port, '_'},
+ call(Name, Req).
+
+list_blocked_users(Addr, Port, Dir) ->
+ Name = make_name(Addr, Port),
+ Req = {list_blocked_users, Addr, Port, Dir},
+ call(Name, Req).
+
+
+%% block_user
+
+block_user(User, Addr, Port, Dir, Time) ->
+ Name = make_name(Addr, Port),
+ Req = {block_user, User, Addr, Port, Dir, Time},
+ call(Name, Req).
+
+
+%% unblock_user
+
+unblock_user(User, Addr, Port) ->
+ Name = make_name(Addr, Port),
+ Req = {unblock_user, User, Addr, Port, '_'},
+ call(Name, Req).
+
+unblock_user(User, Addr, Port, Dir) ->
+ Name = make_name(Addr, Port),
+ Req = {unblock_user, User, Addr, Port, Dir},
+ call(Name, Req).
+
+
+%% list_auth_users
+
+list_auth_users(Addr, Port) ->
+ Name = make_name(Addr, Port),
+ Req = {list_auth_users, Addr, Port, '_'},
+ call(Name, Req).
+
+list_auth_users(Addr, Port, Dir) ->
+ Name = make_name(Addr,Port),
+ Req = {list_auth_users, Addr, Port, Dir},
+ call(Name, Req).
+
+
+%% new_table
+
+new_table(Addr, Port, TabName) ->
+ Name = make_name(Addr,Port),
+ Req = {new_table, Addr, Port, TabName},
+ call(Name, Req).
+
+
+%% delete_tables
+
+delete_tables(Addr, Port) ->
+ Name = make_name(Addr, Port),
+ case whereis(Name) of
+ undefined ->
+ ok;
+ _ ->
+ call(Name, delete_tables)
+ end.
+
+
+%% store_failed_auth
+
+store_failed_auth(Info, Addr, Port, DecodedString, SDirData) ->
+ Name = make_name(Addr,Port),
+ Msg = {store_failed_auth,[Info,DecodedString,SDirData]},
+ cast(Name, Msg).
+
+
+%% store_successful_auth
+
+store_successful_auth(Addr, Port, User, SDirData) ->
+ Name = make_name(Addr,Port),
+ Msg = {store_successful_auth, [User,Addr,Port,SDirData]},
+ cast(Name, Msg).
+
+
+%% check_blocked_user
+
+check_blocked_user(Info, User, SDirData, Addr, Port) ->
+ Name = make_name(Addr, Port),
+ Req = {check_blocked_user, [Info, User, SDirData]},
+ call(Name, Req).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% %%
+%% Server call-back functions %%
+%% %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% init
+
+init([undefined]) ->
+ init([?default_verbosity]);
+init([Verbosity]) ->
+ ?DEBUG("init -> entry with Verbosity: ~p",[Verbosity]),
+ process_flag(trap_exit, true),
+ put(sname, sec),
+ put(verbosity, Verbosity),
+ ?vlog("starting",[]),
+ {ok, []}.
+
+
+%% handle_call
+
+handle_call(stop, _From, Tables) ->
+ ?vlog("stop",[]),
+ {stop, normal, ok, []};
+
+
+handle_call({verbosity,Verbosity}, _From, Tables) ->
+ ?vlog("set verbosity to ~p",[Verbosity]),
+ OldVerbosity = get(verbosity),
+ put(verbosity,Verbosity),
+ ?vdebug("old verbosity: ~p",[OldVerbosity]),
+ {reply,OldVerbosity,Tables};
+
+
+handle_call({block_user, User, Addr, Port, Dir, Time}, _From, Tables) ->
+ ?vlog("block user '~p' for ~p",[User,Dir]),
+ Ret = block_user_int({User, Addr, Port, Dir, Time}),
+ ?vdebug("block user result: ~p",[Ret]),
+ {reply, Ret, Tables};
+
+
+handle_call({list_blocked_users, Addr, Port, Dir}, _From, Tables) ->
+ ?vlog("list blocked users for ~p",[Dir]),
+ Blocked = list_blocked(Tables, Addr, Port, Dir, []),
+ ?vdebug("list blocked users: ~p",[Blocked]),
+ {reply, Blocked, Tables};
+
+
+handle_call({unblock_user, User, Addr, Port, Dir}, _From, Tables) ->
+ ?vlog("unblock user '~p' for ~p",[User,Dir]),
+ Ret = unblock_user_int({User, Addr, Port, Dir}),
+ ?vdebug("unblock user result: ~p",[Ret]),
+ {reply, Ret, Tables};
+
+
+handle_call({list_auth_users, Addr, Port, Dir}, _From, Tables) ->
+ ?vlog("list auth users for ~p",[Dir]),
+ Auth = list_auth(Tables, Addr, Port, Dir, []),
+ ?vdebug("list auth users result: ~p",[Auth]),
+ {reply, Auth, Tables};
+
+
+handle_call({new_table, Addr, Port, Name}, _From, Tables) ->
+ case lists:keysearch(Name, 1, Tables) of
+ {value, {Name, {Ets, Dets}}} ->
+ ?DEBUG("handle_call(new_table) -> we already have this table: ~p",
+ [Name]),
+ ?vdebug("new table; we already have this one: ~p",[Name]),
+ {reply, {ok, {Ets, Dets}}, Tables};
+ false ->
+ ?LOG("handle_call(new_table) -> new_table: Name = ~p",[Name]),
+ ?vlog("new table: ~p",[Name]),
+ TName = make_name(Addr,Port,length(Tables)),
+ ?DEBUG("handle_call(new_table) -> TName: ~p",[TName]),
+ ?vdebug("new table: ~p",[TName]),
+ case dets:open_file(TName, [{type, bag}, {file, Name},
+ {repair, true},
+ {access, read_write}]) of
+ {ok, DFile} ->
+ ETS = ets:new(TName, [bag, private]),
+ sync_dets_to_ets(DFile, ETS),
+ NewTables = [{Name, {ETS, DFile}}|Tables],
+ ?DEBUG("handle_call(new_table) -> ~n"
+ " NewTables: ~p",[NewTables]),
+ ?vtrace("new tables: ~p",[NewTables]),
+ {reply, {ok, {ETS, DFile}}, NewTables};
+ {error, Err} ->
+ ?LOG("handle_call -> Err: ~p",[Err]),
+ ?vinfo("failed open dets file: ~p",[Err]),
+ {reply, {error, {create_dets, Err}}, Tables}
+ end
+ end;
+
+handle_call(delete_tables, _From, Tables) ->
+ ?vlog("delete tables",[]),
+ lists:foreach(fun({Name, {ETS, DETS}}) ->
+ dets:close(DETS),
+ ets:delete(ETS)
+ end, Tables),
+ {reply, ok, []};
+
+handle_call({check_blocked_user, [Info, User, SDirData]}, _From, Tables) ->
+ ?vlog("check blocked user '~p'",[User]),
+ {ETS, DETS} = httpd_util:key1search(SDirData, data_file),
+ Dir = httpd_util:key1search(SDirData, path),
+ Addr = httpd_util:key1search(SDirData, bind_address),
+ Port = httpd_util:key1search(SDirData, port),
+ CBModule = httpd_util:key1search(SDirData, callback_module, no_module_at_all),
+ ?vdebug("call back module: ~p",[CBModule]),
+ Ret = check_blocked_user(Info, User, Dir, Addr, Port, ETS, DETS, CBModule),
+ ?vdebug("check result: ~p",[Ret]),
+ {reply, Ret, Tables};
+handle_call(Request,From,Tables) ->
+ ?vinfo("~n unknown call '~p' from ~p",[Request,From]),
+ {reply,ok,Tables}.
+
+
+%% handle_cast
+
+handle_cast({store_failed_auth, [Info, DecodedString, SDirData]}, Tables) ->
+ ?vlog("store failed auth",[]),
+ {ETS, DETS} = httpd_util:key1search(SDirData, data_file),
+ Dir = httpd_util:key1search(SDirData, path),
+ Addr = httpd_util:key1search(SDirData, bind_address),
+ Port = httpd_util:key1search(SDirData, port),
+ {ok, [User,Password]} = httpd_util:split(DecodedString,":",2),
+ ?vdebug("user '~p' and password '~p'",[User,Password]),
+ Seconds = universal_time(),
+ Key = {User, Dir, Addr, Port},
+
+ %% Event
+ CBModule = httpd_util:key1search(SDirData, callback_module, no_module_at_all),
+ ?vtrace("call back module: ~p",[CBModule]),
+ auth_fail_event(CBModule,Addr,Port,Dir,User,Password),
+
+ %% Find out if any of this user's other failed logins are too old to keep..
+ ?vtrace("remove old login failures",[]),
+ case ets:match_object(ETS, {failed, {Key, '_', '_'}}) of
+ [] ->
+ ?vtrace("no old login failures",[]),
+ no;
+ List when list(List) ->
+ ?vtrace("~p old login failures",[length(List)]),
+ ExpireTime = httpd_util:key1search(SDirData, fail_expire_time, 30)*60,
+ ?vtrace("expire time ~p",[ExpireTime]),
+ lists:map(fun({failed, {TheKey, LS, Gen}}) ->
+ Diff = Seconds-LS,
+ if
+ Diff > ExpireTime ->
+ ?vtrace("~n '~p' is to old to keep: ~p",
+ [TheKey,Gen]),
+ ets:match_delete(ETS, {failed, {TheKey, LS, Gen}}),
+ dets:match_delete(DETS, {failed, {TheKey, LS, Gen}});
+ true ->
+ ?vtrace("~n '~p' is not old enough: ~p",
+ [TheKey,Gen]),
+ ok
+ end
+ end,
+ List);
+ O ->
+ ?vlog("~n unknown login failure search resuylt: ~p",[O]),
+ no
+ end,
+
+ %% Insert the new failure..
+ Generation = length(ets:match_object(ETS, {failed, {Key, '_', '_'}})),
+ ?vtrace("insert ('~p') new login failure: ~p",[Key,Generation]),
+ ets:insert(ETS, {failed, {Key, Seconds, Generation}}),
+ dets:insert(DETS, {failed, {Key, Seconds, Generation}}),
+
+ %% See if we should block this user..
+ MaxRetries = httpd_util:key1search(SDirData, max_retries, 3),
+ BlockTime = httpd_util:key1search(SDirData, block_time, 60),
+ ?vtrace("~n Max retries ~p, block time ~p",[MaxRetries,BlockTime]),
+ case ets:match_object(ETS, {failed, {Key, '_', '_'}}) of
+ List1 ->
+ ?vtrace("~n ~p tries so far",[length(List1)]),
+ if
+ length(List1) >= MaxRetries ->
+ %% Block this user until Future
+ ?vtrace("block user '~p'",[User]),
+ Future = Seconds+BlockTime*60,
+ ?vtrace("future: ~p",[Future]),
+ Reason = io_lib:format("Blocking user ~s from dir ~s "
+ "for ~p minutes",
+ [User, Dir, BlockTime]),
+ mod_log:security_log(Info, lists:flatten(Reason)),
+
+ %% Event
+ user_block_event(CBModule,Addr,Port,Dir,User),
+
+ ets:match_delete(ETS,{blocked_user,
+ {User, Addr, Port, Dir, '$1'}}),
+ dets:match_delete(DETS, {blocked_user,
+ {User, Addr, Port, Dir, '$1'}}),
+ BlockRecord = {blocked_user,
+ {User, Addr, Port, Dir, Future}},
+ ets:insert(ETS, BlockRecord),
+ dets:insert(DETS, BlockRecord),
+ %% Remove previous failed requests.
+ ets:match_delete(ETS, {failed, {Key, '_', '_'}}),
+ dets:match_delete(DETS, {failed, {Key, '_', '_'}});
+ true ->
+ ?vtrace("still some tries to go",[]),
+ no
+ end;
+ Other ->
+ no
+ end,
+ {noreply, Tables};
+
+handle_cast({store_successful_auth, [User, Addr, Port, SDirData]}, Tables) ->
+ ?vlog("store successfull auth",[]),
+ {ETS, DETS} = httpd_util:key1search(SDirData, data_file),
+ AuthTimeOut = httpd_util:key1search(SDirData, auth_timeout, 30),
+ Dir = httpd_util:key1search(SDirData, path),
+ Key = {User, Dir, Addr, Port},
+
+ %% Remove failed entries for this Key
+ dets:match_delete(DETS, {failed, {Key, '_', '_'}}),
+ ets:match_delete(ETS, {failed, {Key, '_', '_'}}),
+
+ %% Keep track of when the last successful login took place.
+ Seconds = universal_time()+AuthTimeOut,
+ ets:match_delete(ETS, {success, {Key, '_'}}),
+ dets:match_delete(DETS, {success, {Key, '_'}}),
+ ets:insert(ETS, {success, {Key, Seconds}}),
+ dets:insert(DETS, {success, {Key, Seconds}}),
+ {noreply, Tables};
+
+handle_cast(Req, Tables) ->
+ ?vinfo("~n unknown cast '~p'",[Req]),
+ error_msg("security server got unknown cast: ~p",[Req]),
+ {noreply, Tables}.
+
+
+%% handle_info
+
+handle_info(Info, State) ->
+ ?vinfo("~n unknown info '~p'",[Info]),
+ {noreply, State}.
+
+
+%% terminate
+
+terminate(Reason, _Tables) ->
+ ?vlog("~n Terminating for reason: ~p",[Reason]),
+ ok.
+
+
+%% code_change({down, ToVsn}, State, Extra)
+%%
+code_change({down, _}, State, _Extra) ->
+ ?vlog("downgrade", []),
+ {ok, State};
+
+
+%% code_change(FromVsn, State, Extra)
+%%
+code_change(_, State, Extra) ->
+ ?vlog("upgrade", []),
+ {ok, State}.
+
+
+
+
+%% block_user_int/2
+block_user_int({User, Addr, Port, Dir, Time}) ->
+ Dirs = httpd_manager:config_match(Addr, Port, {security_directory, '_'}),
+ ?vtrace("block '~p' for ~p during ~p",[User,Dir,Time]),
+ case find_dirdata(Dirs, Dir) of
+ {ok, DirData, {ETS, DETS}} ->
+ Time1 =
+ case Time of
+ infinity ->
+ 99999999999999999999999999999;
+ _ ->
+ Time
+ end,
+ Future = universal_time()+Time1,
+ ets:match_delete(ETS, {blocked_user, {User,Addr,Port,Dir,'_'}}),
+ dets:match_delete(DETS, {blocked_user, {User,Addr,Port,Dir,'_'}}),
+ ets:insert(ETS, {blocked_user, {User,Addr,Port,Dir,Future}}),
+ dets:insert(DETS, {blocked_user, {User,Addr,Port,Dir,Future}}),
+ CBModule = httpd_util:key1search(DirData, callback_module,
+ no_module_at_all),
+ ?vtrace("call back module ~p",[CBModule]),
+ user_block_event(CBModule,Addr,Port,Dir,User),
+ true;
+ _ ->
+ {error, no_such_directory}
+ end.
+
+
+find_dirdata([], _Dir) ->
+ false;
+find_dirdata([{security_directory, DirData}|SDirs], Dir) ->
+ case lists:keysearch(path, 1, DirData) of
+ {value, {path, Dir}} ->
+ {value, {data_file, {ETS, DETS}}} =
+ lists:keysearch(data_file, 1, DirData),
+ {ok, DirData, {ETS, DETS}};
+ _ ->
+ find_dirdata(SDirs, Dir)
+ end.
+
+%% unblock_user_int/2
+
+unblock_user_int({User, Addr, Port, Dir}) ->
+ ?vtrace("unblock user '~p' for ~p",[User,Dir]),
+ Dirs = httpd_manager:config_match(Addr, Port, {security_directory, '_'}),
+ ?vtrace("~n dirs: ~p",[Dirs]),
+ case find_dirdata(Dirs, Dir) of
+ {ok, DirData, {ETS, DETS}} ->
+ case ets:match_object(ETS,{blocked_user,{User,Addr,Port,Dir,'_'}}) of
+ [] ->
+ ?vtrace("not blocked",[]),
+ {error, not_blocked};
+ Objects ->
+ ets:match_delete(ETS, {blocked_user,
+ {User, Addr, Port, Dir, '_'}}),
+ dets:match_delete(DETS, {blocked_user,
+ {User, Addr, Port, Dir, '_'}}),
+ CBModule = httpd_util:key1search(DirData, callback_module,
+ no_module_at_all),
+ user_unblock_event(CBModule,Addr,Port,Dir,User),
+ true
+ end;
+ _ ->
+ ?vlog("~n cannot unblock: no such directory '~p'",[Dir]),
+ {error, no_such_directory}
+ end.
+
+
+
+%% list_auth/2
+
+list_auth([], _Addr, _Port, Dir, Acc) ->
+ Acc;
+list_auth([{Name, {ETS, DETS}}|Tables], Addr, Port, Dir, Acc) ->
+ case ets:match_object(ETS, {success, {{'_', Dir, Addr, Port}, '_'}}) of
+ [] ->
+ list_auth(Tables, Addr, Port, Dir, Acc);
+ List when list(List) ->
+ TN = universal_time(),
+ NewAcc = lists:foldr(fun({success,{{U,Ad,P,D},T}},Ac) ->
+ if
+ T-TN > 0 ->
+ [U|Ac];
+ true ->
+ Rec = {success,{{U,Ad,P,D},T}},
+ ets:match_delete(ETS,Rec),
+ dets:match_delete(DETS,Rec),
+ Ac
+ end
+ end,
+ Acc, List),
+ list_auth(Tables, Addr, Port, Dir, NewAcc);
+ _ ->
+ list_auth(Tables, Addr, Port, Dir, Acc)
+ end.
+
+
+%% list_blocked/2
+
+list_blocked([], Addr, Port, Dir, Acc) ->
+ TN = universal_time(),
+ lists:foldl(fun({U,Ad,P,D,T}, Ac) ->
+ if
+ T-TN > 0 ->
+ [{U,Ad,P,D,local_time(T)}|Ac];
+ true ->
+ Ac
+ end
+ end,
+ [], Acc);
+list_blocked([{Name, {ETS, DETS}}|Tables], Addr, Port, Dir, Acc) ->
+ NewBlocked =
+ case ets:match_object(ETS, {blocked_user, {'_',Addr,Port,Dir,'_'}}) of
+ List when list(List) ->
+ lists:foldl(fun({blocked_user, X}, A) -> [X|A] end, Acc, List);
+ _ ->
+ Acc
+ end,
+ list_blocked(Tables, Addr, Port, Dir, NewBlocked).
+
+
+%%
+%% sync_dets_to_ets/2
+%%
+%% Reads dets-table DETS and syncronizes it with the ets-table ETS.
+%%
+sync_dets_to_ets(DETS, ETS) ->
+ dets:traverse(DETS, fun(X) ->
+ ets:insert(ETS, X),
+ continue
+ end).
+
+%%
+%% check_blocked_user/7 -> true | false
+%%
+%% Check if a specific user is blocked from access.
+%%
+%% The sideeffect of this routine is that it unblocks also other users
+%% whos blocking time has expired. This to keep the tables as small
+%% as possible.
+%%
+check_blocked_user(Info, User, Dir, Addr, Port, ETS, DETS, CBModule) ->
+ TN = universal_time(),
+ case ets:match_object(ETS, {blocked_user, {User, '_', '_', '_', '_'}}) of
+ List when list(List) ->
+ Blocked = lists:foldl(fun({blocked_user, X}, A) ->
+ [X|A] end, [], List),
+ check_blocked_user(Info,User,Dir,Addr,Port,ETS,DETS,TN,Blocked,CBModule);
+ _ ->
+ false
+ end.
+check_blocked_user(Info, User, Dir, Addr, Port, ETS, DETS, TN, [], CBModule) ->
+ false;
+check_blocked_user(Info, User, Dir, Addr, Port, ETS, DETS, TN,
+ [{User,Addr,Port,Dir,T}|Ls], CBModule) ->
+ TD = T-TN,
+ if
+ TD =< 0 ->
+ %% Blocking has expired, remove and grant access.
+ unblock_user(Info, User, Dir, Addr, Port, ETS, DETS, CBModule),
+ false;
+ true ->
+ true
+ end;
+check_blocked_user(Info, User, Dir, Addr, Port, ETS, DETS, TN,
+ [{OUser,ODir,OAddr,OPort,T}|Ls], CBModule) ->
+ TD = T-TN,
+ if
+ TD =< 0 ->
+ %% Blocking has expired, remove.
+ unblock_user(Info, OUser, ODir, OAddr, OPort, ETS, DETS, CBModule);
+ true ->
+ true
+ end,
+ check_blocked_user(Info, User, Dir, Addr, Port, ETS, DETS, TN, Ls, CBModule).
+
+unblock_user(Info, User, Dir, Addr, Port, ETS, DETS, CBModule) ->
+ Reason=io_lib:format("User ~s was removed from the block list for dir ~s",
+ [User, Dir]),
+ mod_log:security_log(Info, lists:flatten(Reason)),
+ user_unblock_event(CBModule,Addr,Port,Dir,User),
+ dets:match_delete(DETS, {blocked_user, {User, Addr, Port, Dir, '_'}}),
+ ets:match_delete(ETS, {blocked_user, {User, Addr, Port, Dir, '_'}}).
+
+
+make_name(Addr,Port) ->
+ httpd_util:make_name("httpd_security",Addr,Port).
+
+make_name(Addr,Port,Num) ->
+ httpd_util:make_name("httpd_security",Addr,Port,
+ "__" ++ integer_to_list(Num)).
+
+
+auth_fail_event(Mod,Addr,Port,Dir,User,Passwd) ->
+ event(auth_fail,Mod,Addr,Port,Dir,[{user,User},{password,Passwd}]).
+
+user_block_event(Mod,Addr,Port,Dir,User) ->
+ event(user_block,Mod,Addr,Port,Dir,[{user,User}]).
+
+user_unblock_event(Mod,Addr,Port,Dir,User) ->
+ event(user_unblock,Mod,Addr,Port,Dir,[{user,User}]).
+
+event(Event,Mod,undefined,Port,Dir,Info) ->
+ (catch Mod:event(Event,Port,Dir,Info));
+event(Event,Mod,Addr,Port,Dir,Info) ->
+ (catch Mod:event(Event,Addr,Port,Dir,Info)).
+
+universal_time() ->
+ calendar:datetime_to_gregorian_seconds(calendar:universal_time()).
+
+local_time(T) ->
+ calendar:universal_time_to_local_time(
+ calendar:gregorian_seconds_to_datetime(T)).
+
+
+error_msg(F, A) ->
+ error_logger:error_msg(F, A).
+
+
+call(Name, Req) ->
+ case (catch gen_server:call(Name, Req)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Reply ->
+ Reply
+ end.
+
+
+cast(Name, Msg) ->
+ case (catch gen_server:cast(Name, Msg)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Result ->
+ Result
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_trace.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_trace.erl
new file mode 100644
index 0000000000..9f4d331d82
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_trace.erl
@@ -0,0 +1,64 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mod_trace.erl,v 1.1 2008/12/17 09:53:36 mikpe Exp $
+%%
+-module(mod_trace).
+
+-export([do/1]).
+
+-include("httpd.hrl").
+
+
+do(Info) ->
+ %%?vtrace("do",[]),
+ case Info#mod.method of
+ "TRACE" ->
+ case httpd_util:response_generated(Info) of
+ false->
+ generate_trace_response(Info);
+ true->
+ {proceed,Info#mod.data}
+ end;
+ _ ->
+ {proceed,Info#mod.data}
+ end.
+
+
+%%---------------------------------------------------------------------
+%%Generate the trace response the trace response consists of a
+%%http-header and the body will be the request.
+%5----------------------------------------------------------------------
+
+generate_trace_response(Info)->
+ RequestHead=Info#mod.parsed_header,
+ Body=generate_trace_response_body(RequestHead),
+ Len=length(Body),
+ Response=["HTTP/1.1 200 OK\r\n",
+ "Content-Type:message/http\r\n",
+ "Content-Length:",integer_to_list(Len),"\r\n\r\n",
+ Info#mod.request_line,Body],
+ httpd_socket:deliver(Info#mod.socket_type,Info#mod.socket,Response),
+ {proceed,[{response,{already_sent,200,Len}}|Info#mod.data]}.
+
+generate_trace_response_body(Parsed_header)->
+ generate_trace_response_body(Parsed_header,[]).
+
+generate_trace_response_body([],Head)->
+ lists:flatten(Head);
+generate_trace_response_body([{[],[]}|Rest],Head) ->
+ generate_trace_response_body(Rest,Head);
+generate_trace_response_body([{Field,Value}|Rest],Head) ->
+ generate_trace_response_body(Rest,[Field ++ ":" ++ Value ++ "\r\n"|Head]).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/uri.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/uri.erl
new file mode 100644
index 0000000000..9a4f77f87b
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/uri.erl
@@ -0,0 +1,349 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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 Mobile Arts AB
+%% Portions created by Mobile Arts are Copyright 2002, Mobile Arts AB
+%% All Rights Reserved.''
+%%
+%%
+%% Author : Johan Blom <[email protected]>
+%% Description :
+%% Implements various scheme dependent subsets (e.g. HTTP, FTP etc) based on
+%% RFC 2396, Uniform Resource Identifiers (URI): Generic Syntax
+%% Created : 27 Jul 2001 by Johan Blom <[email protected]>
+%%
+
+-module(uri).
+
+-author('[email protected]').
+
+-export([parse/1,resolve/2]).
+
+
+%%% Parse URI and return {Scheme,Path}
+%%% Note that Scheme specific parsing/validation is not handled here!
+resolve(Root,Rel) ->
+ ok.
+
+%%% See "http://www.isi.edu/in-notes/iana/assignments/url-schemes" for a list of
+%%% defined URL schemes and references to its sources.
+
+parse(URI) ->
+ case parse_scheme(URI) of
+ {http,Cont} -> parse_http(Cont,http);
+ {https,Cont} -> parse_http(Cont,https);
+ {ftp,Cont} -> parse_ftp(Cont,ftp);
+ {sip,Cont} -> parse_sip(Cont,sip);
+ {sms,Cont} -> parse_sms(Cont,sip);
+ {error,Error} -> {error,Error};
+ {Scheme,Cont} -> {Scheme,Cont}
+ end.
+
+
+%%% Parse the scheme.
+parse_scheme(URI) ->
+ parse_scheme(URI,[]).
+
+parse_scheme([H|URI],Acc) when $a=<H,H=<$z; $A=<H,H=<$Z ->
+ parse_scheme2(URI,[H|Acc]);
+parse_scheme(_,_) ->
+ {error,no_scheme}.
+
+parse_scheme2([H|URI],Acc)
+ when $a=<H,H=<$z; $A=<H,H=<$Z; $0=<H,H=<$9; H==$-;H==$+;H==$. ->
+ parse_scheme2(URI,[H|Acc]);
+parse_scheme2([$:|URI],Acc) ->
+ {list_to_atom(lists:reverse(Acc)),URI};
+parse_scheme2(_,_) ->
+ {error,no_scheme}.
+
+
+%%% ............................................................................
+-define(HTTP_DEFAULT_PORT, 80).
+-define(HTTPS_DEFAULT_PORT, 443).
+
+%%% HTTP (Source RFC 2396, RFC 2616)
+%%% http_URL = "*" | absoluteURI | abs_path [ "?" query ] | authority
+
+%%% http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]
+%%% Returns a tuple {http,Host,Port,PathQuery} where
+%%% Host = string() Host value
+%%% Port = string() Port value
+%%% PathQuery= string() Combined absolute path and query value
+parse_http("//"++C0,Scheme) ->
+ case scan_hostport(C0,Scheme) of
+ {C1,Host,Port} ->
+ case scan_pathquery(C1) of
+ {error,Error} ->
+ {error,Error};
+ PathQuery ->
+ {Scheme,Host,Port,PathQuery}
+ end;
+ {error,Error} ->
+ {error,Error}
+ end;
+parse_http(_,_) ->
+ {error,invalid_url}.
+
+scan_pathquery(C0) ->
+ case scan_abspath(C0) of
+ {error,Error} ->
+ {error,Error};
+ {[],[]} -> % Add implicit path
+ "/";
+ {"?"++C1,Path} ->
+ case scan_query(C1,[]) of
+ {error,Error} ->
+ {error,Error};
+ Query ->
+ Path++"?"++Query
+ end;
+ {[],Path} ->
+ Path
+ end.
+
+
+%%% ............................................................................
+%%% FIXME!!! This is just a quick hack that doesn't work!
+-define(FTP_DEFAULT_PORT, 80).
+
+%%% FTP (Source RFC 2396, RFC 1738, RFC 959)
+%%% Note: This BNF has been modified to better fit with RFC 2396
+%%% ftp_URL = "ftp:" "//" [ ftp_userinfo ] host [ ":" port ] ftp_abs_path
+%%% ftp_userinfo = ftp_user [ ":" ftp_password ]
+%%% ftp_abs_path = "/" ftp_path_segments [ ";type=" ftp_type ]
+%%% ftp_path_segments = ftp_segment *( "/" ftp_segment)
+%%% ftp_segment = *[ ftp_uchar | "?" | ":" | "@" | "&" | "=" ]
+%%% ftp_type = "A" | "I" | "D" | "a" | "i" | "d"
+%%% ftp_user = *[ ftp_uchar | ";" | "?" | "&" | "=" ]
+%%% ftp_password = *[ ftp_uchar | ";" | "?" | "&" | "=" ]
+%%% ftp_uchar = ftp_unreserved | escaped
+%%% ftp_unreserved = alphanum | mark | "$" | "+" | ","
+parse_ftp("//"++C0,Scheme) ->
+ case ftp_userinfo(C0) of
+ {C1,Creds} ->
+ case scan_hostport(C1,Scheme) of
+ {C2,Host,Port} ->
+ case scan_abspath(C2) of
+ {error,Error} ->
+ {error,Error};
+ {[],[]} -> % Add implicit path
+ {Scheme,Creds,Host,Port,"/"};
+ {[],Path} ->
+ {Scheme,Creds,Host,Port,Path}
+ end;
+ {error,Error} ->
+ {error,Error}
+ end;
+ {error,Error} ->
+ {error,Error}
+ end.
+
+ftp_userinfo(C0) ->
+ User="",
+ Password="",
+ {C0,{User,Password}}.
+
+
+%%% ............................................................................
+%%% SIP (Source RFC 2396, RFC 2543)
+%%% sip_URL = "sip:" [ sip_userinfo "@" ] host [ ":" port ]
+%%% sip_url-parameters [ sip_headers ]
+%%% sip_userinfo = sip_user [ ":" sip_password ]
+%%% sip_user = *( unreserved | escaped | "&" | "=" | "+" | "$" | "," )
+%%% sip_password = *( unreserved | escaped | "&" | "=" | "+" | "$" | "," )
+%%% sip_url-parameters = *( ";" sip_url-parameter )
+%%% sip_url-parameter = sip_transport-param | sip_user-param |
+%%% sip_method-param | sip_ttl-param |
+%%% sip_maddr-param | sip_other-param
+%%% sip_transport-param = "transport=" ( "udp" | "tcp" )
+%%% sip_ttl-param = "ttl=" sip_ttl
+%%% sip_ttl = 1*3DIGIT ; 0 to 255
+%%% sip_maddr-param = "maddr=" host
+%%% sip_user-param = "user=" ( "phone" | "ip" )
+%%% sip_method-param = "method=" sip_Method
+%%% sip_tag-param = "tag=" sip_UUID
+%%% sip_UUID = 1*( hex | "-" )
+%%% sip_other-param = ( token | ( token "=" ( token | quoted-string )))
+%%% sip_Method = "INVITE" | "ACK" | "OPTIONS" | "BYE" |
+%%% "CANCEL" | "REGISTER"
+%%% sip_token = 1*< any CHAR except CTL's or separators>
+%%% sip_quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
+%%% sip_qdtext = <any TEXT-UTF8 except <">>
+%%% sip_quoted-pair = " \ " CHAR
+parse_sip(Cont,Scheme) ->
+ {Scheme,Cont}.
+
+
+
+
+%%% ............................................................................
+%%% SMS (Source draft-wilde-sms-uri-01, January 24 2002 and
+%%% draft-allocchio-gstn-01, November 2001)
+%%% The syntax definition for "gstn-phone" is taken from
+%%% [draft-allocchio-gstn-01], allowing global as well as local telephone
+%%% numbers.
+%%% Note: This BNF has been modified to better fit with RFC 2396
+%%% sms_URI = sms ":" 1*( sms-recipient ) [ sms-body ]
+%%% sms-recipient = gstn-phone sms-qualifier
+%%% [ "," sms-recipient ]
+%%% sms-qualifier = *( smsc-qualifier / pid-qualifier )
+%%% smsc-qualifier = ";smsc=" SMSC-sub-addr
+%%% pid-qualifier = ";pid=" PID-sub-addr
+%%% sms-body = ";body=" *urlc
+%%% gstn-phone = ( global-phone / local-phone )
+%%% global-phone = "+" 1*( DIGIT / written-sep )
+%%% local-phone = [ exit-code ] dial-number / exit-code [ dial-number ]
+%%% exit-code = phone-string
+%%% dial-number = phone-string
+%%% subaddr-string = phone-string
+%%% post-dial = phone-string
+%%% phone-string = 1*( DTMF / pause / tonewait / written-sep )
+%%% DTMF = ( DIGIT / "#" / "*" / "A" / "B" / "C" / "D" )
+%%% written-sep = ( "-" / "." )
+%%% pause = "p"
+%%% tonewait = "w"
+parse_sms(Cont,Scheme) ->
+ {Scheme,Cont}.
+
+
+%%% ============================================================================
+%%% Generic URI parsing. BNF rules from RFC 2396
+
+%%% hostport = host [ ":" port ]
+scan_hostport(C0,Scheme) ->
+ case scan_host(C0) of
+ {error,Error} ->
+ {error,Error};
+ {":"++C1,Host} ->
+ {C2,Port}=scan_port(C1,[]),
+ {C2,Host,list_to_integer(Port)};
+ {C1,Host} when Scheme==http ->
+ {C1,Host,?HTTP_DEFAULT_PORT};
+ {C1,Host} when Scheme==https ->
+ {C1,Host,?HTTPS_DEFAULT_PORT};
+ {C1,Host} when Scheme==ftp ->
+ {C1,Host,?FTP_DEFAULT_PORT}
+ end.
+
+
+%%% host = hostname | IPv4address
+%%% hostname = *( domainlabel "." ) toplabel [ "." ]
+%%% domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
+%%% toplabel = alpha | alpha *( alphanum | "-" ) alphanum
+%%% IPv4address = 1*digit "." 1*digit "." 1*digit "." 1*digit
+
+-define(ALPHA, 1).
+-define(DIGIT, 2).
+
+scan_host(C0) ->
+ case scan_host2(C0,[],0,[],[]) of
+ {C1,IPv4address,[?DIGIT,?DIGIT,?DIGIT,?DIGIT]} ->
+ {C1,lists:reverse(lists:append(IPv4address))};
+ {C1,Hostname,[?ALPHA|HostF]} ->
+ {C1,lists:reverse(lists:append(Hostname))};
+ _ ->
+ {error,no_host}
+ end.
+
+scan_host2([H|C0],Acc,CurF,Host,HostF) when $0=<H,H=<$9 ->
+ scan_host2(C0,[H|Acc],CurF bor ?DIGIT,Host,HostF);
+scan_host2([H|C0],Acc,CurF,Host,HostF) when $a=<H,H=<$z; $A=<H,H=<$Z ->
+ scan_host2(C0,[H|Acc],CurF bor ?ALPHA,Host,HostF);
+scan_host2([$-|C0],Acc,CurF,Host,HostF) when CurF=/=0 ->
+ scan_host2(C0,[$-|Acc],CurF,Host,HostF);
+scan_host2([$.|C0],Acc,CurF,Host,HostF) when CurF=/=0 ->
+ scan_host2(C0,[],0,[".",Acc|Host],[CurF|HostF]);
+scan_host2(C0,Acc,CurF,Host,HostF) ->
+ {C0,[Acc|Host],[CurF|HostF]}.
+
+
+%%% port = *digit
+scan_port([H|C0],Acc) when $0=<H,H=<$9 ->
+ scan_port(C0,[H|Acc]);
+scan_port(C0,Acc) ->
+ {C0,lists:reverse(Acc)}.
+
+%%% abs_path = "/" path_segments
+scan_abspath([]) ->
+ {[],[]};
+scan_abspath("/"++C0) ->
+ scan_pathsegments(C0,["/"]);
+scan_abspath(_) ->
+ {error,no_abspath}.
+
+%%% path_segments = segment *( "/" segment )
+scan_pathsegments(C0,Acc) ->
+ case scan_segment(C0,[]) of
+ {"/"++C1,Segment} ->
+ scan_pathsegments(C1,["/",Segment|Acc]);
+ {C1,Segment} ->
+ {C1,lists:reverse(lists:append([Segment|Acc]))}
+ end.
+
+
+%%% segment = *pchar *( ";" param )
+%%% param = *pchar
+scan_segment(";"++C0,Acc) ->
+ {C1,ParamAcc}=scan_pchars(C0,";"++Acc),
+ scan_segment(C1,ParamAcc);
+scan_segment(C0,Acc) ->
+ case scan_pchars(C0,Acc) of
+ {";"++C1,Segment} ->
+ {C2,ParamAcc}=scan_pchars(C1,";"++Segment),
+ scan_segment(C2,ParamAcc);
+ {C1,Segment} ->
+ {C1,Segment}
+ end.
+
+%%% query = *uric
+%%% uric = reserved | unreserved | escaped
+%%% reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
+%%% "$" | ","
+%%% unreserved = alphanum | mark
+%%% mark = "-" | "_" | "." | "!" | "~" | "*" | "'" |
+%%% "(" | ")"
+%%% escaped = "%" hex hex
+scan_query([],Acc) ->
+ lists:reverse(Acc);
+scan_query([$%,H1,H2|C0],Acc) -> % escaped
+ scan_query(C0,[hex2dec(H1)*16+hex2dec(H2)|Acc]);
+scan_query([H|C0],Acc) when $a=<H,H=<$z;$A=<H,H=<$Z;$0=<H,H=<$9 -> % alphanum
+ scan_query(C0,[H|Acc]);
+scan_query([H|C0],Acc) when H==$;; H==$/; H==$?; H==$:; H==$@;
+ H==$&; H==$=; H==$+; H==$$; H==$, -> % reserved
+ scan_query(C0,[H|Acc]);
+scan_query([H|C0],Acc) when H==$-; H==$_; H==$.; H==$!; H==$~;
+ H==$*; H==$'; H==$(; H==$) -> % mark
+ scan_query(C0,[H|Acc]);
+scan_query([H|C0],Acc) ->
+ {error,no_query}.
+
+
+%%% pchar = unreserved | escaped |
+%%% ":" | "@" | "&" | "=" | "+" | "$" | ","
+scan_pchars([],Acc) ->
+ {[],Acc};
+scan_pchars([$%,H1,H2|C0],Acc) -> % escaped
+ scan_pchars(C0,[hex2dec(H1)*16+hex2dec(H2)|Acc]);
+scan_pchars([H|C0],Acc) when $a=<H,H=<$z;$A=<H,H=<$Z;$0=<H,H=<$9 -> % alphanum
+ scan_pchars(C0,[H|Acc]);
+scan_pchars([H|C0],Acc) when H==$-; H==$_; H==$.; H==$!; H==$~;
+ H==$*; H==$'; H==$(; H==$) -> % mark
+ scan_pchars(C0,[H|Acc]);
+scan_pchars([H|C0],Acc) when H==$:; H==$@; H==$&; H==$=; H==$+; H==$$; H==$, ->
+ scan_pchars(C0,[H|Acc]);
+scan_pchars(C0,Acc) ->
+ {C0,Acc}.
+
+hex2dec(X) when X>=$0,X=<$9 -> X-$0;
+hex2dec(X) when X>=$A,X=<$F -> X-$A+10;
+hex2dec(X) when X>=$a,X=<$f -> X-$a+10.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/Makefile b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/Makefile
new file mode 100644
index 0000000000..8b57868117
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/Makefile
@@ -0,0 +1,136 @@
+# ``The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance 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: Makefile,v 1.1 2008/12/17 09:53:37 mikpe Exp $
+#
+include $(ERL_TOP)/make/target.mk
+
+ifeq ($(TYPE),debug)
+ERL_COMPILE_FLAGS += -Ddebug -W
+endif
+
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+VSN=$(MNESIA_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/mnesia-$(VSN)
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+MODULES= \
+ mnesia \
+ mnesia_backup \
+ mnesia_bup \
+ mnesia_checkpoint \
+ mnesia_checkpoint_sup \
+ mnesia_controller \
+ mnesia_dumper\
+ mnesia_event \
+ mnesia_frag \
+ mnesia_frag_hash \
+ mnesia_frag_old_hash \
+ mnesia_index \
+ mnesia_kernel_sup \
+ mnesia_late_loader \
+ mnesia_lib\
+ mnesia_loader \
+ mnesia_locker \
+ mnesia_log \
+ mnesia_monitor \
+ mnesia_recover \
+ mnesia_registry \
+ mnesia_schema\
+ mnesia_snmp_hook \
+ mnesia_snmp_sup \
+ mnesia_subscr \
+ mnesia_sup \
+ mnesia_sp \
+ mnesia_text \
+ mnesia_tm
+
+HRL_FILES= mnesia.hrl
+
+ERL_FILES= $(MODULES:%=%.erl)
+
+TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
+
+APP_FILE= mnesia.app
+
+APP_SRC= $(APP_FILE).src
+APP_TARGET= $(EBIN)/$(APP_FILE)
+
+APPUP_FILE= mnesia.appup
+
+APPUP_SRC= $(APPUP_FILE).src
+APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
+
+
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ERL_FLAGS +=
+ERL_COMPILE_FLAGS += \
+ +warn_unused_vars \
+ +'{parse_transform,sys_pre_attributes}' \
+ +'{attribute,insert,vsn,"mnesia_$(MNESIA_VSN)"}' \
+ -W
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+opt: $(TARGET_FILES)
+
+debug:
+ @${MAKE} TYPE=debug
+
+clean:
+ rm -f $(TARGET_FILES)
+ rm -f core
+
+docs:
+
+# ----------------------------------------------------
+# Special Build Targets
+# ----------------------------------------------------
+
+$(APP_TARGET): $(APP_SRC) ../vsn.mk
+ sed -e 's;%VSN%;$(VSN);' $< > $@
+
+$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
+ sed -e 's;%VSN%;$(VSN);' $< > $@
+
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/src
+ $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src
+ $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+
+release_docs_spec:
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.app.src b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.app.src
new file mode 100644
index 0000000000..fb9d7aa0ca
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.app.src
@@ -0,0 +1,50 @@
+{application, mnesia,
+ [{description, "MNESIA CXC 138 12"},
+ {vsn, "%VSN%"},
+ {modules, [
+ mnesia,
+ mnesia_backup,
+ mnesia_bup,
+ mnesia_checkpoint,
+ mnesia_checkpoint_sup,
+ mnesia_controller,
+ mnesia_dumper,
+ mnesia_event,
+ mnesia_frag,
+ mnesia_frag_hash,
+ mnesia_frag_old_hash,
+ mnesia_index,
+ mnesia_kernel_sup,
+ mnesia_late_loader,
+ mnesia_lib,
+ mnesia_loader,
+ mnesia_locker,
+ mnesia_log,
+ mnesia_monitor,
+ mnesia_recover,
+ mnesia_registry,
+ mnesia_schema,
+ mnesia_snmp_hook,
+ mnesia_snmp_sup,
+ mnesia_subscr,
+ mnesia_sup,
+ mnesia_sp,
+ mnesia_text,
+ mnesia_tm
+ ]},
+ {registered, [
+ mnesia_dumper_load_regulator,
+ mnesia_event,
+ mnesia_fallback,
+ mnesia_controller,
+ mnesia_kernel_sup,
+ mnesia_late_loader,
+ mnesia_locker,
+ mnesia_monitor,
+ mnesia_recover,
+ mnesia_substr,
+ mnesia_sup,
+ mnesia_tm
+ ]},
+ {applications, [kernel, stdlib]},
+ {mod, {mnesia_sup, []}}]}.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.appup.src b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.appup.src
new file mode 100644
index 0000000000..64f50dd5c6
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.appup.src
@@ -0,0 +1,6 @@
+{"%VSN%",
+ [
+ ],
+ [
+ ]
+}.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.erl
new file mode 100644
index 0000000000..b4f03fab03
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.erl
@@ -0,0 +1,2191 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia.erl,v 1.2 2010/03/04 13:54:19 maria Exp $
+%%
+%% This module exports the public interface of the Mnesia DBMS engine
+
+-module(mnesia).
+%-behaviour(mnesia_access).
+
+-export([
+ %% Start, stop and debugging
+ start/0, start/1, stop/0, % Not for public use
+ set_debug_level/1, lkill/0, kill/0, % Not for public use
+ ms/0, nc/0, nc/1, ni/0, ni/1, % Not for public use
+ change_config/2,
+
+ %% Activity mgt
+ abort/1, transaction/1, transaction/2, transaction/3,
+ sync_transaction/1, sync_transaction/2, sync_transaction/3,
+ async_dirty/1, async_dirty/2, sync_dirty/1, sync_dirty/2, ets/1, ets/2,
+ activity/2, activity/3, activity/4, % Not for public use
+
+ %% Access within an activity - Lock acquisition
+ lock/2, lock/4,
+ read_lock_table/1,
+ write_lock_table/1,
+
+ %% Access within an activity - Updates
+ write/1, s_write/1, write/3, write/5,
+ delete/1, s_delete/1, delete/3, delete/5,
+ delete_object/1, s_delete_object/1, delete_object/3, delete_object/5,
+
+ %% Access within an activity - Reads
+ read/1, wread/1, read/3, read/5,
+ match_object/1, match_object/3, match_object/5,
+ select/2, select/3, select/5,
+ all_keys/1, all_keys/4,
+ index_match_object/2, index_match_object/4, index_match_object/6,
+ index_read/3, index_read/6,
+
+ %% Iterators within an activity
+ foldl/3, foldl/4, foldr/3, foldr/4,
+
+ %% Dirty access regardless of activities - Updates
+ dirty_write/1, dirty_write/2,
+ dirty_delete/1, dirty_delete/2,
+ dirty_delete_object/1, dirty_delete_object/2,
+ dirty_update_counter/2, dirty_update_counter/3,
+
+ %% Dirty access regardless of activities - Read
+ dirty_read/1, dirty_read/2,
+ dirty_select/2,
+ dirty_match_object/1, dirty_match_object/2, dirty_all_keys/1,
+ dirty_index_match_object/2, dirty_index_match_object/3,
+ dirty_index_read/3, dirty_slot/2,
+ dirty_first/1, dirty_next/2, dirty_last/1, dirty_prev/2,
+
+ %% Info
+ table_info/2, table_info/4, schema/0, schema/1,
+ error_description/1, info/0, system_info/1,
+ system_info/0, % Not for public use
+
+ %% Database mgt
+ create_schema/1, delete_schema/1,
+ backup/1, backup/2, traverse_backup/4, traverse_backup/6,
+ install_fallback/1, install_fallback/2,
+ uninstall_fallback/0, uninstall_fallback/1,
+ activate_checkpoint/1, deactivate_checkpoint/1,
+ backup_checkpoint/2, backup_checkpoint/3, restore/2,
+
+ %% Table mgt
+ create_table/1, create_table/2, delete_table/1,
+ add_table_copy/3, del_table_copy/2, move_table_copy/3,
+ add_table_index/2, del_table_index/2,
+ transform_table/3, transform_table/4,
+ change_table_copy_type/3,
+ read_table_property/2, write_table_property/2, delete_table_property/2,
+ change_table_frag/2,
+ clear_table/1,
+
+ %% Table load
+ dump_tables/1, wait_for_tables/2, force_load_table/1,
+ change_table_access_mode/2, change_table_load_order/2,
+ set_master_nodes/1, set_master_nodes/2,
+
+ %% Misc admin
+ dump_log/0, subscribe/1, unsubscribe/1, report_event/1,
+
+ %% Snmp
+ snmp_open_table/2, snmp_close_table/1,
+ snmp_get_row/2, snmp_get_next_index/2, snmp_get_mnesia_key/2,
+
+ %% Textfile access
+ load_textfile/1, dump_to_textfile/1,
+
+ %% Mnemosyne exclusive
+ get_activity_id/0, put_activity_id/1, % Not for public use
+
+ %% Mnesia internal functions
+ dirty_rpc/4, % Not for public use
+ has_var/1, fun_select/7,
+ foldl/6, foldr/6,
+
+ %% Module internal callback functions
+ remote_dirty_match_object/2, % Not for public use
+ remote_dirty_select/2 % Not for public use
+ ]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-include("mnesia.hrl").
+-import(mnesia_lib, [verbose/2]).
+
+-define(DEFAULT_ACCESS, ?MODULE).
+
+%% Select
+-define(PATTERN_TO_OBJECT_MATCH_SPEC(Pat), [{Pat,[],['$_']}]).
+-define(PATTERN_TO_BINDINGS_MATCH_SPEC(Pat), [{Pat,[],['$$']}]).
+
+%% Local function in order to avoid external function call
+val(Var) ->
+ case ?catch_val(Var) of
+ {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
+ Value -> Value
+ end.
+
+is_dollar_digits(Var) ->
+ case atom_to_list(Var) of
+ [$$ | Digs] ->
+ is_digits(Digs);
+ _ ->
+ false
+ end.
+
+is_digits([Dig | Tail]) ->
+ if
+ $0 =< Dig, Dig =< $9 ->
+ is_digits(Tail);
+ true ->
+ false
+ end;
+is_digits([]) ->
+ true.
+
+has_var(X) when atom(X) ->
+ if
+ X == '_' ->
+ true;
+ atom(X) ->
+ is_dollar_digits(X);
+ true ->
+ false
+ end;
+has_var(X) when tuple(X) ->
+ e_has_var(X, size(X));
+has_var([H|T]) ->
+ case has_var(H) of
+ false -> has_var(T);
+ Other -> Other
+ end;
+has_var(_) -> false.
+
+e_has_var(_, 0) -> false;
+e_has_var(X, Pos) ->
+ case has_var(element(Pos, X))of
+ false -> e_has_var(X, Pos-1);
+ Other -> Other
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Start and stop
+
+start() ->
+ {Time , Res} = timer:tc(application, start, [?APPLICATION, temporary]),
+
+ Secs = Time div 1000000,
+ case Res of
+ ok ->
+ verbose("Mnesia started, ~p seconds~n",[ Secs]),
+ ok;
+ {error, {already_started, mnesia}} ->
+ verbose("Mnesia already started, ~p seconds~n",[ Secs]),
+ ok;
+ {error, R} ->
+ verbose("Mnesia failed to start, ~p seconds: ~p~n",[ Secs, R]),
+ {error, R}
+ end.
+
+start(ExtraEnv) when list(ExtraEnv) ->
+ case mnesia_lib:ensure_loaded(?APPLICATION) of
+ ok ->
+ patched_start(ExtraEnv);
+ Error ->
+ Error
+ end;
+start(ExtraEnv) ->
+ {error, {badarg, ExtraEnv}}.
+
+patched_start([{Env, Val} | Tail]) when atom(Env) ->
+ case mnesia_monitor:patch_env(Env, Val) of
+ {error, Reason} ->
+ {error, Reason};
+ _NewVal ->
+ patched_start(Tail)
+ end;
+patched_start([Head | _]) ->
+ {error, {bad_type, Head}};
+patched_start([]) ->
+ start().
+
+stop() ->
+ case application:stop(?APPLICATION) of
+ ok -> stopped;
+ {error, {not_started, ?APPLICATION}} -> stopped;
+ Other -> Other
+ end.
+
+change_config(extra_db_nodes, Ns) when list(Ns) ->
+ mnesia_controller:connect_nodes(Ns);
+change_config(BadKey, _BadVal) ->
+ {error, {badarg, BadKey}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Debugging
+
+set_debug_level(Level) ->
+ mnesia_subscr:set_debug_level(Level).
+
+lkill() ->
+ mnesia_sup:kill().
+
+kill() ->
+ rpc:multicall(mnesia_sup, kill, []).
+
+ms() ->
+ [
+ mnesia,
+ mnesia_backup,
+ mnesia_bup,
+ mnesia_checkpoint,
+ mnesia_checkpoint_sup,
+ mnesia_controller,
+ mnesia_dumper,
+ mnesia_loader,
+ mnesia_frag,
+ mnesia_frag_hash,
+ mnesia_frag_old_hash,
+ mnesia_index,
+ mnesia_kernel_sup,
+ mnesia_late_loader,
+ mnesia_lib,
+ mnesia_log,
+ mnesia_registry,
+ mnesia_schema,
+ mnesia_snmp_hook,
+ mnesia_snmp_sup,
+ mnesia_subscr,
+ mnesia_sup,
+ mnesia_text,
+ mnesia_tm,
+ mnesia_recover,
+ mnesia_locker,
+
+ %% Keep these last in the list, so
+ %% mnesia_sup kills these last
+ mnesia_monitor,
+ mnesia_event
+ ].
+
+nc() ->
+ Mods = ms(),
+ nc(Mods).
+
+nc(Mods) when list(Mods)->
+ [Mod || Mod <- Mods, ok /= load(Mod, compile)].
+
+ni() ->
+ Mods = ms(),
+ ni(Mods).
+
+ni(Mods) when list(Mods) ->
+ [Mod || Mod <- Mods, ok /= load(Mod, interpret)].
+
+load(Mod, How) when atom(Mod) ->
+ case try_load(Mod, How) of
+ ok ->
+ ok;
+ _ ->
+ mnesia_lib:show( "~n RETRY ~p FROM: ", [Mod]),
+ Abs = mod2abs(Mod),
+ load(Abs, How)
+ end;
+load(Abs, How) ->
+ case try_load(Abs, How) of
+ ok ->
+ ok;
+ {error, Reason} ->
+ mnesia_lib:show( " *** ERROR *** ~p~n", [Reason]),
+ {error, Reason}
+ end.
+
+try_load(Mod, How) ->
+ mnesia_lib:show( " ~p ", [Mod]),
+ Flags = [{d, debug}],
+ case How of
+ compile ->
+ case catch c:nc(Mod, Flags) of
+ {ok, _} -> ok;
+ Other -> {error, Other}
+ end;
+ interpret ->
+ case catch int:ni(Mod, Flags) of
+ {module, _} -> ok;
+ Other -> {error, Other}
+ end
+ end.
+
+mod2abs(Mod) ->
+ ModString = atom_to_list(Mod),
+ SubDir =
+ case lists:suffix("test", ModString) of
+ true -> test;
+ false -> src
+ end,
+ filename:join([code:lib_dir(?APPLICATION), SubDir, ModString]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Activity mgt
+
+abort(Reason) ->
+ exit({aborted, Reason}).
+
+transaction(Fun) ->
+ transaction(get(mnesia_activity_state), Fun, [], infinity, ?DEFAULT_ACCESS, async).
+transaction(Fun, Retries) when integer(Retries), Retries >= 0 ->
+ transaction(get(mnesia_activity_state), Fun, [], Retries, ?DEFAULT_ACCESS, async);
+transaction(Fun, Retries) when Retries == infinity ->
+ transaction(get(mnesia_activity_state), Fun, [], Retries, ?DEFAULT_ACCESS, async);
+transaction(Fun, Args) ->
+ transaction(get(mnesia_activity_state), Fun, Args, infinity, ?DEFAULT_ACCESS, async).
+transaction(Fun, Args, Retries) ->
+ transaction(get(mnesia_activity_state), Fun, Args, Retries, ?DEFAULT_ACCESS, async).
+
+sync_transaction(Fun) ->
+ transaction(get(mnesia_activity_state), Fun, [], infinity, ?DEFAULT_ACCESS, sync).
+sync_transaction(Fun, Retries) when integer(Retries), Retries >= 0 ->
+ transaction(get(mnesia_activity_state), Fun, [], Retries, ?DEFAULT_ACCESS, sync);
+sync_transaction(Fun, Retries) when Retries == infinity ->
+ transaction(get(mnesia_activity_state), Fun, [], Retries, ?DEFAULT_ACCESS, sync);
+sync_transaction(Fun, Args) ->
+ transaction(get(mnesia_activity_state), Fun, Args, infinity, ?DEFAULT_ACCESS, sync).
+sync_transaction(Fun, Args, Retries) ->
+ transaction(get(mnesia_activity_state), Fun, Args, Retries, ?DEFAULT_ACCESS, sync).
+
+
+transaction(State, Fun, Args, Retries, Mod, Kind)
+ when function(Fun), list(Args), Retries == infinity, atom(Mod) ->
+ mnesia_tm:transaction(State, Fun, Args, Retries, Mod, Kind);
+transaction(State, Fun, Args, Retries, Mod, Kind)
+ when function(Fun), list(Args), integer(Retries), Retries >= 0, atom(Mod) ->
+ mnesia_tm:transaction(State, Fun, Args, Retries, Mod, Kind);
+transaction(_State, Fun, Args, Retries, Mod, _Kind) ->
+ {aborted, {badarg, Fun, Args, Retries, Mod}}.
+
+non_transaction(State, Fun, Args, ActivityKind, Mod)
+ when function(Fun), list(Args), atom(Mod) ->
+ mnesia_tm:non_transaction(State, Fun, Args, ActivityKind, Mod);
+non_transaction(_State, Fun, Args, _ActivityKind, _Mod) ->
+ {aborted, {badarg, Fun, Args}}.
+
+async_dirty(Fun) ->
+ async_dirty(Fun, []).
+async_dirty(Fun, Args) ->
+ non_transaction(get(mnesia_activity_state), Fun, Args, async_dirty, ?DEFAULT_ACCESS).
+
+sync_dirty(Fun) ->
+ sync_dirty(Fun, []).
+sync_dirty(Fun, Args) ->
+ non_transaction(get(mnesia_activity_state), Fun, Args, sync_dirty, ?DEFAULT_ACCESS).
+
+ets(Fun) ->
+ ets(Fun, []).
+ets(Fun, Args) ->
+ non_transaction(get(mnesia_activity_state), Fun, Args, ets, ?DEFAULT_ACCESS).
+
+activity(Kind, Fun) ->
+ activity(Kind, Fun, []).
+activity(Kind, Fun, Args) when list(Args) ->
+ activity(Kind, Fun, Args, mnesia_monitor:get_env(access_module));
+activity(Kind, Fun, Mod) ->
+ activity(Kind, Fun, [], Mod).
+
+activity(Kind, Fun, Args, Mod) ->
+ State = get(mnesia_activity_state),
+ case Kind of
+ ets -> non_transaction(State, Fun, Args, Kind, Mod);
+ async_dirty -> non_transaction(State, Fun, Args, Kind, Mod);
+ sync_dirty -> non_transaction(State, Fun, Args, Kind, Mod);
+ transaction -> wrap_trans(State, Fun, Args, infinity, Mod, async);
+ {transaction, Retries} -> wrap_trans(State, Fun, Args, Retries, Mod, async);
+ sync_transaction -> wrap_trans(State, Fun, Args, infinity, Mod, sync);
+ {sync_transaction, Retries} -> wrap_trans(State, Fun, Args, Retries, Mod, sync);
+ _ -> {aborted, {bad_type, Kind}}
+ end.
+
+wrap_trans(State, Fun, Args, Retries, Mod, Kind) ->
+ case transaction(State, Fun, Args, Retries, Mod, Kind) of
+ {'atomic', GoodRes} -> GoodRes;
+ BadRes -> exit(BadRes)
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Access within an activity - lock acquisition
+
+%% Grab a lock on an item in the global lock table
+%% Item may be any term. Lock may be write or read.
+%% write lock is set on all the given nodes
+%% read lock is only set on the first node
+%% Nodes may either be a list of nodes or one node as an atom
+%% Mnesia on all Nodes must be connected to each other, but
+%% it is not neccessary that they are up and running.
+
+lock(LockItem, LockKind) ->
+ case get(mnesia_activity_state) of
+ {?DEFAULT_ACCESS, Tid, Ts} ->
+ lock(Tid, Ts, LockItem, LockKind);
+ {Mod, Tid, Ts} ->
+ Mod:lock(Tid, Ts, LockItem, LockKind);
+ _ ->
+ abort(no_transaction)
+ end.
+
+lock(Tid, Ts, LockItem, LockKind) ->
+ case element(1, Tid) of
+ tid ->
+ case LockItem of
+ {record, Tab, Key} ->
+ lock_record(Tid, Ts, Tab, Key, LockKind);
+ {table, Tab} ->
+ lock_table(Tid, Ts, Tab, LockKind);
+ {global, GlobalKey, Nodes} ->
+ global_lock(Tid, Ts, GlobalKey, LockKind, Nodes);
+ _ ->
+ abort({bad_type, LockItem})
+ end;
+ _Protocol ->
+ []
+ end.
+
+%% Grab a read lock on a whole table
+read_lock_table(Tab) ->
+ lock({table, Tab}, read),
+ ok.
+
+%% Grab a write lock on a whole table
+write_lock_table(Tab) ->
+ lock({table, Tab}, write),
+ ok.
+
+lock_record(Tid, Ts, Tab, Key, LockKind) when atom(Tab) ->
+ Store = Ts#tidstore.store,
+ Oid = {Tab, Key},
+ case LockKind of
+ read ->
+ mnesia_locker:rlock(Tid, Store, Oid);
+ write ->
+ mnesia_locker:wlock(Tid, Store, Oid);
+ sticky_write ->
+ mnesia_locker:sticky_wlock(Tid, Store, Oid);
+ none ->
+ [];
+ _ ->
+ abort({bad_type, Tab, LockKind})
+ end;
+lock_record(_Tid, _Ts, Tab, _Key, _LockKind) ->
+ abort({bad_type, Tab}).
+
+lock_table(Tid, Ts, Tab, LockKind) when atom(Tab) ->
+ Store = Ts#tidstore.store,
+ case LockKind of
+ read ->
+ mnesia_locker:rlock_table(Tid, Store, Tab);
+ write ->
+ mnesia_locker:wlock_table(Tid, Store, Tab);
+ sticky_write ->
+ mnesia_locker:sticky_wlock_table(Tid, Store, Tab);
+ none ->
+ [];
+ _ ->
+ abort({bad_type, Tab, LockKind})
+ end;
+lock_table(_Tid, _Ts, Tab, _LockKind) ->
+ abort({bad_type, Tab}).
+
+global_lock(Tid, Ts, Item, Kind, Nodes) when list(Nodes) ->
+ case element(1, Tid) of
+ tid ->
+ Store = Ts#tidstore.store,
+ GoodNs = good_global_nodes(Nodes),
+ if
+ Kind /= read, Kind /= write ->
+ abort({bad_type, Kind});
+ true ->
+ mnesia_locker:global_lock(Tid, Store, Item, Kind, GoodNs)
+ end;
+ _Protocol ->
+ []
+ end;
+global_lock(_Tid, _Ts, _Item, _Kind, Nodes) ->
+ abort({bad_type, Nodes}).
+
+good_global_nodes(Nodes) ->
+ Recover = [node() | val(recover_nodes)],
+ mnesia_lib:intersect(Nodes, Recover).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Access within an activity - updates
+
+write(Val) when tuple(Val), size(Val) > 2 ->
+ Tab = element(1, Val),
+ write(Tab, Val, write);
+write(Val) ->
+ abort({bad_type, Val}).
+
+s_write(Val) when tuple(Val), size(Val) > 2 ->
+ Tab = element(1, Val),
+ write(Tab, Val, sticky_write).
+
+write(Tab, Val, LockKind) ->
+ case get(mnesia_activity_state) of
+ {?DEFAULT_ACCESS, Tid, Ts} ->
+ write(Tid, Ts, Tab, Val, LockKind);
+ {Mod, Tid, Ts} ->
+ Mod:write(Tid, Ts, Tab, Val, LockKind);
+ _ ->
+ abort(no_transaction)
+ end.
+
+write(Tid, Ts, Tab, Val, LockKind)
+ when atom(Tab), Tab /= schema, tuple(Val), size(Val) > 2 ->
+ case element(1, Tid) of
+ ets ->
+ ?ets_insert(Tab, Val),
+ ok;
+ tid ->
+ Store = Ts#tidstore.store,
+ Oid = {Tab, element(2, Val)},
+ case LockKind of
+ write ->
+ mnesia_locker:wlock(Tid, Store, Oid);
+ sticky_write ->
+ mnesia_locker:sticky_wlock(Tid, Store, Oid);
+ _ ->
+ abort({bad_type, Tab, LockKind})
+ end,
+ write_to_store(Tab, Store, Oid, Val);
+ Protocol ->
+ do_dirty_write(Protocol, Tab, Val)
+ end;
+write(_Tid, _Ts, Tab, Val, LockKind) ->
+ abort({bad_type, Tab, Val, LockKind}).
+
+write_to_store(Tab, Store, Oid, Val) ->
+ case ?catch_val({Tab, record_validation}) of
+ {RecName, Arity, Type}
+ when size(Val) == Arity, RecName == element(1, Val) ->
+ case Type of
+ bag ->
+ ?ets_insert(Store, {Oid, Val, write});
+ _ ->
+ ?ets_delete(Store, Oid),
+ ?ets_insert(Store, {Oid, Val, write})
+ end,
+ ok;
+ {'EXIT', _} ->
+ abort({no_exists, Tab});
+ _ ->
+ abort({bad_type, Val})
+ end.
+
+delete({Tab, Key}) ->
+ delete(Tab, Key, write);
+delete(Oid) ->
+ abort({bad_type, Oid}).
+
+s_delete({Tab, Key}) ->
+ delete(Tab, Key, sticky_write);
+s_delete(Oid) ->
+ abort({bad_type, Oid}).
+
+delete(Tab, Key, LockKind) ->
+ case get(mnesia_activity_state) of
+ {?DEFAULT_ACCESS, Tid, Ts} ->
+ delete(Tid, Ts, Tab, Key, LockKind);
+ {Mod, Tid, Ts} ->
+ Mod:delete(Tid, Ts, Tab, Key, LockKind);
+ _ ->
+ abort(no_transaction)
+ end.
+
+delete(Tid, Ts, Tab, Key, LockKind)
+ when atom(Tab), Tab /= schema ->
+ case element(1, Tid) of
+ ets ->
+ ?ets_delete(Tab, Key),
+ ok;
+ tid ->
+ Store = Ts#tidstore.store,
+ Oid = {Tab, Key},
+ case LockKind of
+ write ->
+ mnesia_locker:wlock(Tid, Store, Oid);
+ sticky_write ->
+ mnesia_locker:sticky_wlock(Tid, Store, Oid);
+ _ ->
+ abort({bad_type, Tab, LockKind})
+ end,
+ ?ets_delete(Store, Oid),
+ ?ets_insert(Store, {Oid, Oid, delete}),
+ ok;
+ Protocol ->
+ do_dirty_delete(Protocol, Tab, Key)
+ end;
+delete(_Tid, _Ts, Tab, _Key, _LockKind) ->
+ abort({bad_type, Tab}).
+
+delete_object(Val) when tuple(Val), size(Val) > 2 ->
+ Tab = element(1, Val),
+ delete_object(Tab, Val, write);
+delete_object(Val) ->
+ abort({bad_type, Val}).
+
+s_delete_object(Val) when tuple(Val), size(Val) > 2 ->
+ Tab = element(1, Val),
+ delete_object(Tab, Val, sticky_write);
+s_delete_object(Val) ->
+ abort({bad_type, Val}).
+
+delete_object(Tab, Val, LockKind) ->
+ case get(mnesia_activity_state) of
+ {?DEFAULT_ACCESS, Tid, Ts} ->
+ delete_object(Tid, Ts, Tab, Val, LockKind);
+ {Mod, Tid, Ts} ->
+ Mod:delete_object(Tid, Ts, Tab, Val, LockKind);
+ _ ->
+ abort(no_transaction)
+ end.
+
+delete_object(Tid, Ts, Tab, Val, LockKind)
+ when atom(Tab), Tab /= schema, tuple(Val), size(Val) > 2 ->
+ case element(1, Tid) of
+ ets ->
+ ?ets_match_delete(Tab, Val),
+ ok;
+ tid ->
+ Store = Ts#tidstore.store,
+ Oid = {Tab, element(2, Val)},
+ case LockKind of
+ write ->
+ mnesia_locker:wlock(Tid, Store, Oid);
+ sticky_write ->
+ mnesia_locker:sticky_wlock(Tid, Store, Oid);
+ _ ->
+ abort({bad_type, Tab, LockKind})
+ end,
+ case val({Tab, setorbag}) of
+ bag ->
+ ?ets_match_delete(Store, {Oid, Val, '_'}),
+ ?ets_insert(Store, {Oid, Val, delete_object});
+ _ ->
+ case ?ets_match_object(Store, {Oid, '_', write}) of
+ [] ->
+ ?ets_match_delete(Store, {Oid, Val, '_'}),
+ ?ets_insert(Store, {Oid, Val, delete_object});
+ _ ->
+ ?ets_delete(Store, Oid),
+ ?ets_insert(Store, {Oid, Oid, delete})
+ end
+ end,
+ ok;
+ Protocol ->
+ do_dirty_delete_object(Protocol, Tab, Val)
+ end;
+delete_object(_Tid, _Ts, Tab, _Key, _LockKind) ->
+ abort({bad_type, Tab}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Access within an activity - read
+
+read({Tab, Key}) ->
+ read(Tab, Key, read);
+read(Oid) ->
+ abort({bad_type, Oid}).
+
+wread({Tab, Key}) ->
+ read(Tab, Key, write);
+wread(Oid) ->
+ abort({bad_type, Oid}).
+
+read(Tab, Key, LockKind) ->
+ case get(mnesia_activity_state) of
+ {?DEFAULT_ACCESS, Tid, Ts} ->
+ read(Tid, Ts, Tab, Key, LockKind);
+ {Mod, Tid, Ts} ->
+ Mod:read(Tid, Ts, Tab, Key, LockKind);
+ _ ->
+ abort(no_transaction)
+ end.
+
+read(Tid, Ts, Tab, Key, LockKind)
+ when atom(Tab), Tab /= schema ->
+ case element(1, Tid) of
+ ets ->
+ ?ets_lookup(Tab, Key);
+ tid ->
+ Store = Ts#tidstore.store,
+ Oid = {Tab, Key},
+ Objs =
+ case LockKind of
+ read ->
+ mnesia_locker:rlock(Tid, Store, Oid);
+ write ->
+ mnesia_locker:rwlock(Tid, Store, Oid);
+ sticky_write ->
+ mnesia_locker:sticky_rwlock(Tid, Store, Oid);
+ _ ->
+ abort({bad_type, Tab, LockKind})
+ end,
+ add_written(?ets_lookup(Store, Oid), Tab, Objs);
+ _Protocol ->
+ dirty_read(Tab, Key)
+ end;
+read(_Tid, _Ts, Tab, _Key, _LockKind) ->
+ abort({bad_type, Tab}).
+
+%%%%%%%%%%%%%%%%%%%%%
+%% Iterators
+
+foldl(Fun, Acc, Tab) ->
+ foldl(Fun, Acc, Tab, read).
+
+foldl(Fun, Acc, Tab, LockKind) when function(Fun) ->
+ case get(mnesia_activity_state) of
+ {?DEFAULT_ACCESS, Tid, Ts} ->
+ foldl(Tid, Ts, Fun, Acc, Tab, LockKind);
+ {Mod, Tid, Ts} ->
+ Mod:foldl(Tid, Ts, Fun, Acc, Tab, LockKind);
+ _ ->
+ abort(no_transaction)
+ end.
+
+foldl(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
+ {Type, Prev} = init_iteration(ActivityId, Opaque, Tab, LockKind),
+ Res = (catch do_foldl(ActivityId, Opaque, Tab, dirty_first(Tab), Fun, Acc, Type, Prev)),
+ close_iteration(Res, Tab).
+
+do_foldl(A, O, Tab, '$end_of_table', Fun, RAcc, _Type, Stored) ->
+ lists:foldl(fun(Key, Acc) ->
+ lists:foldl(Fun, Acc, read(A, O, Tab, Key, read))
+ end, RAcc, Stored);
+do_foldl(A, O, Tab, Key, Fun, Acc, ordered_set, [H | Stored]) when H == Key ->
+ NewAcc = lists:foldl(Fun, Acc, read(A, O, Tab, Key, read)),
+ do_foldl(A, O, Tab, dirty_next(Tab, Key), Fun, NewAcc, ordered_set, Stored);
+do_foldl(A, O, Tab, Key, Fun, Acc, ordered_set, [H | Stored]) when H < Key ->
+ NewAcc = lists:foldl(Fun, Acc, read(A, O, Tab, H, read)),
+ do_foldl(A, O, Tab, Key, Fun, NewAcc, ordered_set, Stored);
+do_foldl(A, O, Tab, Key, Fun, Acc, ordered_set, [H | Stored]) when H > Key ->
+ NewAcc = lists:foldl(Fun, Acc, read(A, O, Tab, Key, read)),
+ do_foldl(A, O, Tab, dirty_next(Tab, Key), Fun, NewAcc, ordered_set, [H |Stored]);
+do_foldl(A, O, Tab, Key, Fun, Acc, Type, Stored) -> %% Type is set or bag
+ NewAcc = lists:foldl(Fun, Acc, read(A, O, Tab, Key, read)),
+ NewStored = ordsets:del_element(Key, Stored),
+ do_foldl(A, O, Tab, dirty_next(Tab, Key), Fun, NewAcc, Type, NewStored).
+
+foldr(Fun, Acc, Tab) ->
+ foldr(Fun, Acc, Tab, read).
+foldr(Fun, Acc, Tab, LockKind) when function(Fun) ->
+ case get(mnesia_activity_state) of
+ {?DEFAULT_ACCESS, Tid, Ts} ->
+ foldr(Tid, Ts, Fun, Acc, Tab, LockKind);
+ {Mod, Tid, Ts} ->
+ Mod:foldr(Tid, Ts, Fun, Acc, Tab, LockKind);
+ _ ->
+ abort(no_transaction)
+ end.
+
+foldr(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
+ {Type, TempPrev} = init_iteration(ActivityId, Opaque, Tab, LockKind),
+ Prev =
+ if
+ Type == ordered_set ->
+ lists:reverse(TempPrev);
+ true -> %% Order doesn't matter for set and bag
+ TempPrev %% Keep the order so we can use ordsets:del_element
+ end,
+ Res = (catch do_foldr(ActivityId, Opaque, Tab, dirty_last(Tab), Fun, Acc, Type, Prev)),
+ close_iteration(Res, Tab).
+
+do_foldr(A, O, Tab, '$end_of_table', Fun, RAcc, _Type, Stored) ->
+ lists:foldl(fun(Key, Acc) ->
+ lists:foldl(Fun, Acc, read(A, O, Tab, Key, read))
+ end, RAcc, Stored);
+do_foldr(A, O, Tab, Key, Fun, Acc, ordered_set, [H | Stored]) when H == Key ->
+ NewAcc = lists:foldl(Fun, Acc, read(A, O, Tab, Key, read)),
+ do_foldr(A, O, Tab, dirty_prev(Tab, Key), Fun, NewAcc, ordered_set, Stored);
+do_foldr(A, O, Tab, Key, Fun, Acc, ordered_set, [H | Stored]) when H > Key ->
+ NewAcc = lists:foldl(Fun, Acc, read(A, O, Tab, H, read)),
+ do_foldr(A, O, Tab, Key, Fun, NewAcc, ordered_set, Stored);
+do_foldr(A, O, Tab, Key, Fun, Acc, ordered_set, [H | Stored]) when H < Key ->
+ NewAcc = lists:foldl(Fun, Acc, read(A, O, Tab, Key, read)),
+ do_foldr(A, O, Tab, dirty_prev(Tab, Key), Fun, NewAcc, ordered_set, [H |Stored]);
+do_foldr(A, O, Tab, Key, Fun, Acc, Type, Stored) -> %% Type is set or bag
+ NewAcc = lists:foldl(Fun, Acc, read(A, O, Tab, Key, read)),
+ NewStored = ordsets:del_element(Key, Stored),
+ do_foldr(A, O, Tab, dirty_prev(Tab, Key), Fun, NewAcc, Type, NewStored).
+
+init_iteration(ActivityId, Opaque, Tab, LockKind) ->
+ lock(ActivityId, Opaque, {table, Tab}, LockKind),
+ Type = val({Tab, setorbag}),
+ Previous = add_previous(ActivityId, Opaque, Type, Tab),
+ St = val({Tab, storage_type}),
+ if
+ St == unknown ->
+ ignore;
+ true ->
+ mnesia_lib:db_fixtable(St, Tab, true)
+ end,
+ {Type, Previous}.
+
+close_iteration(Res, Tab) ->
+ case val({Tab, storage_type}) of
+ unknown ->
+ ignore;
+ St ->
+ mnesia_lib:db_fixtable(St, Tab, false)
+ end,
+ case Res of
+ {'EXIT', {aborted, What}} ->
+ abort(What);
+ {'EXIT', What} ->
+ abort(What);
+ _ ->
+ Res
+ end.
+
+add_previous(_ActivityId, non_transaction, _Type, _Tab) ->
+ [];
+add_previous(_Tid, Ts, _Type, Tab) ->
+ Previous = ?ets_match(Ts#tidstore.store, {{Tab, '$1'}, '_', write}),
+ lists:sort(lists:concat(Previous)).
+
+%% This routine fixes up the return value from read/1 so that
+%% it is correct with respect to what this particular transaction
+%% has already written, deleted .... etc
+
+add_written([], _Tab, Objs) ->
+ Objs; % standard normal fast case
+add_written(Written, Tab, Objs) ->
+ case val({Tab, setorbag}) of
+ bag ->
+ add_written_to_bag(Written, Objs, []);
+ _ ->
+ add_written_to_set(Written)
+ end.
+
+add_written_to_set(Ws) ->
+ case lists:last(Ws) of
+ {_, _, delete} -> [];
+ {_, Val, write} -> [Val];
+ {_, _, delete_object} -> []
+ end.
+
+add_written_to_bag([{_, Val, write} | Tail], Objs, Ack) ->
+ add_written_to_bag(Tail, lists:delete(Val, Objs), [Val | Ack]);
+add_written_to_bag([], Objs, Ack) ->
+ Objs ++ lists:reverse(Ack); %% Oldest write first as in ets
+add_written_to_bag([{_, _ , delete} | Tail], _Objs, _Ack) ->
+ %% This transaction just deleted all objects
+ %% with this key
+ add_written_to_bag(Tail, [], []);
+add_written_to_bag([{_, Val, delete_object} | Tail], Objs, Ack) ->
+ add_written_to_bag(Tail, lists:delete(Val, Objs), lists:delete(Val, Ack)).
+
+match_object(Pat) when tuple(Pat), size(Pat) > 2 ->
+ Tab = element(1, Pat),
+ match_object(Tab, Pat, read);
+match_object(Pat) ->
+ abort({bad_type, Pat}).
+
+match_object(Tab, Pat, LockKind) ->
+ case get(mnesia_activity_state) of
+ {?DEFAULT_ACCESS, Tid, Ts} ->
+ match_object(Tid, Ts, Tab, Pat, LockKind);
+ {Mod, Tid, Ts} ->
+ Mod:match_object(Tid, Ts, Tab, Pat, LockKind);
+ _ ->
+ abort(no_transaction)
+ end.
+
+match_object(Tid, Ts, Tab, Pat, LockKind)
+ when atom(Tab), Tab /= schema, tuple(Pat), size(Pat) > 2 ->
+ case element(1, Tid) of
+ ets ->
+ mnesia_lib:db_match_object(ram_copies, Tab, Pat);
+ tid ->
+ Key = element(2, Pat),
+ case has_var(Key) of
+ false -> lock_record(Tid, Ts, Tab, Key, LockKind);
+ true -> lock_table(Tid, Ts, Tab, LockKind)
+ end,
+ Objs = dirty_match_object(Tab, Pat),
+ add_written_match(Ts#tidstore.store, Pat, Tab, Objs);
+ _Protocol ->
+ dirty_match_object(Tab, Pat)
+ end;
+match_object(_Tid, _Ts, Tab, Pat, _LockKind) ->
+ abort({bad_type, Tab, Pat}).
+
+add_written_match(S, Pat, Tab, Objs) ->
+ Ops = find_ops(S, Tab, Pat),
+ add_match(Ops, Objs, val({Tab, setorbag})).
+
+find_ops(S, Tab, Pat) ->
+ GetWritten = [{{{Tab, '_'}, Pat, write}, [], ['$_']},
+ {{{Tab, '_'}, '_', delete}, [], ['$_']},
+ {{{Tab, '_'}, Pat, delete_object}, [], ['$_']}],
+ ets:select(S, GetWritten).
+
+add_match([], Objs, _Type) ->
+ Objs;
+add_match(Written, Objs, ordered_set) ->
+ %% Must use keysort which is stable
+ add_ordered_match(lists:keysort(1,Written), Objs, []);
+add_match([{Oid, _, delete}|R], Objs, Type) ->
+ add_match(R, deloid(Oid, Objs), Type);
+add_match([{_Oid, Val, delete_object}|R], Objs, Type) ->
+ add_match(R, lists:delete(Val, Objs), Type);
+add_match([{_Oid, Val, write}|R], Objs, bag) ->
+ add_match(R, [Val | lists:delete(Val, Objs)], bag);
+add_match([{Oid, Val, write}|R], Objs, set) ->
+ add_match(R, [Val | deloid(Oid,Objs)],set).
+
+%% For ordered_set only !!
+add_ordered_match(Written = [{{_, Key}, _, _}|_], [Obj|Objs], Acc)
+ when Key > element(2, Obj) ->
+ add_ordered_match(Written, Objs, [Obj|Acc]);
+add_ordered_match([{{_, Key}, Val, write}|Rest], Objs =[Obj|_], Acc)
+ when Key < element(2, Obj) ->
+ add_ordered_match(Rest, [Val|Objs],Acc);
+add_ordered_match([{{_, Key}, _, _DelOP}|Rest], Objs =[Obj|_], Acc)
+ when Key < element(2, Obj) ->
+ add_ordered_match(Rest,Objs,Acc);
+%% Greater than last object
+add_ordered_match([{_, Val, write}|Rest], [], Acc) ->
+ add_ordered_match(Rest, [Val], Acc);
+add_ordered_match([_|Rest], [], Acc) ->
+ add_ordered_match(Rest, [], Acc);
+%% Keys are equal from here
+add_ordered_match([{_, Val, write}|Rest], [_Obj|Objs], Acc) ->
+ add_ordered_match(Rest, [Val|Objs], Acc);
+add_ordered_match([{_, _Val, delete}|Rest], [_Obj|Objs], Acc) ->
+ add_ordered_match(Rest, Objs, Acc);
+add_ordered_match([{_, Val, delete_object}|Rest], [Val|Objs], Acc) ->
+ add_ordered_match(Rest, Objs, Acc);
+add_ordered_match([{_, _, delete_object}|Rest], Objs, Acc) ->
+ add_ordered_match(Rest, Objs, Acc);
+add_ordered_match([], Objs, Acc) ->
+ lists:reverse(Acc, Objs).
+
+
+%%%%%%%%%%%%%%%%%%
+% select
+
+select(Tab, Pat) ->
+ select(Tab, Pat, read).
+select(Tab, Pat, LockKind)
+ when atom(Tab), Tab /= schema, list(Pat) ->
+ case get(mnesia_activity_state) of
+ {?DEFAULT_ACCESS, Tid, Ts} ->
+ select(Tid, Ts, Tab, Pat, LockKind);
+ {Mod, Tid, Ts} ->
+ Mod:select(Tid, Ts, Tab, Pat, LockKind);
+ _ ->
+ abort(no_transaction)
+ end;
+select(Tab, Pat, _Lock) ->
+ abort({badarg, Tab, Pat}).
+
+select(Tid, Ts, Tab, Spec, LockKind) ->
+ SelectFun = fun(FixedSpec) -> dirty_select(Tab, FixedSpec) end,
+ fun_select(Tid, Ts, Tab, Spec, LockKind, Tab, SelectFun).
+
+fun_select(Tid, Ts, Tab, Spec, LockKind, TabPat, SelectFun) ->
+ case element(1, Tid) of
+ ets ->
+ mnesia_lib:db_select(ram_copies, Tab, Spec);
+ tid ->
+ Store = Ts#tidstore.store,
+ Written = ?ets_match_object(Store, {{TabPat, '_'}, '_', '_'}),
+ %% Avoid table lock if possible
+ case Spec of
+ [{HeadPat,_, _}] when tuple(HeadPat), size(HeadPat) > 2 ->
+ Key = element(2, HeadPat),
+ case has_var(Key) of
+ false -> lock_record(Tid, Ts, Tab, Key, LockKind);
+ true -> lock_table(Tid, Ts, Tab, LockKind)
+ end;
+ _ ->
+ lock_table(Tid, Ts, Tab, LockKind)
+ end,
+ case Written of
+ [] ->
+ %% Nothing changed in the table during this transaction,
+ %% Simple case get results from [d]ets
+ SelectFun(Spec);
+ _ ->
+ %% Hard (slow case) records added or deleted earlier
+ %% in the transaction, have to cope with that.
+ Type = val({Tab, setorbag}),
+ FixedSpec = get_record_pattern(Spec),
+ TabRecs = SelectFun(FixedSpec),
+ FixedRes = add_match(Written, TabRecs, Type),
+ CMS = ets:match_spec_compile(Spec),
+% case Type of
+% ordered_set ->
+% ets:match_spec_run(lists:sort(FixedRes), CMS);
+% _ ->
+% ets:match_spec_run(FixedRes, CMS)
+% end
+ ets:match_spec_run(FixedRes, CMS)
+ end;
+ _Protocol ->
+ SelectFun(Spec)
+ end.
+
+get_record_pattern([]) ->
+ [];
+get_record_pattern([{M,C,_B}|R]) ->
+ [{M,C,['$_']} | get_record_pattern(R)].
+
+deloid(_Oid, []) ->
+ [];
+deloid({Tab, Key}, [H | T]) when element(2, H) == Key ->
+ deloid({Tab, Key}, T);
+deloid(Oid, [H | T]) ->
+ [H | deloid(Oid, T)].
+
+all_keys(Tab) ->
+ case get(mnesia_activity_state) of
+ {?DEFAULT_ACCESS, Tid, Ts} ->
+ all_keys(Tid, Ts, Tab, read);
+ {Mod, Tid, Ts} ->
+ Mod:all_keys(Tid, Ts, Tab, read);
+ _ ->
+ abort(no_transaction)
+ end.
+
+all_keys(Tid, Ts, Tab, LockKind)
+ when atom(Tab), Tab /= schema ->
+ Pat0 = val({Tab, wild_pattern}),
+ Pat = setelement(2, Pat0, '$1'),
+ Keys = select(Tid, Ts, Tab, [{Pat, [], ['$1']}], LockKind),
+ case val({Tab, setorbag}) of
+ bag ->
+ mnesia_lib:uniq(Keys);
+ _ ->
+ Keys
+ end;
+all_keys(_Tid, _Ts, Tab, _LockKind) ->
+ abort({bad_type, Tab}).
+
+index_match_object(Pat, Attr) when tuple(Pat), size(Pat) > 2 ->
+ Tab = element(1, Pat),
+ index_match_object(Tab, Pat, Attr, read);
+index_match_object(Pat, _Attr) ->
+ abort({bad_type, Pat}).
+
+index_match_object(Tab, Pat, Attr, LockKind) ->
+ case get(mnesia_activity_state) of
+ {?DEFAULT_ACCESS, Tid, Ts} ->
+ index_match_object(Tid, Ts, Tab, Pat, Attr, LockKind);
+ {Mod, Tid, Ts} ->
+ Mod:index_match_object(Tid, Ts, Tab, Pat, Attr, LockKind);
+ _ ->
+ abort(no_transaction)
+ end.
+
+index_match_object(Tid, Ts, Tab, Pat, Attr, LockKind)
+ when atom(Tab), Tab /= schema, tuple(Pat), size(Pat) > 2 ->
+ case element(1, Tid) of
+ ets ->
+ dirty_index_match_object(Tab, Pat, Attr); % Should be optimized?
+ tid ->
+ case mnesia_schema:attr_tab_to_pos(Tab, Attr) of
+ Pos when Pos =< size(Pat) ->
+ case LockKind of
+ read ->
+ Store = Ts#tidstore.store,
+ mnesia_locker:rlock_table(Tid, Store, Tab),
+ Objs = dirty_index_match_object(Tab, Pat, Attr),
+ add_written_match(Store, Pat, Tab, Objs);
+ _ ->
+ abort({bad_type, Tab, LockKind})
+ end;
+ BadPos ->
+ abort({bad_type, Tab, BadPos})
+ end;
+ _Protocol ->
+ dirty_index_match_object(Tab, Pat, Attr)
+ end;
+index_match_object(_Tid, _Ts, Tab, Pat, _Attr, _LockKind) ->
+ abort({bad_type, Tab, Pat}).
+
+index_read(Tab, Key, Attr) ->
+ case get(mnesia_activity_state) of
+ {?DEFAULT_ACCESS, Tid, Ts} ->
+ index_read(Tid, Ts, Tab, Key, Attr, read);
+ {Mod, Tid, Ts} ->
+ Mod:index_read(Tid, Ts, Tab, Key, Attr, read);
+ _ ->
+ abort(no_transaction)
+ end.
+
+index_read(Tid, Ts, Tab, Key, Attr, LockKind)
+ when atom(Tab), Tab /= schema ->
+ case element(1, Tid) of
+ ets ->
+ dirty_index_read(Tab, Key, Attr); % Should be optimized?
+ tid ->
+ Pos = mnesia_schema:attr_tab_to_pos(Tab, Attr),
+ case LockKind of
+ read ->
+ case has_var(Key) of
+ false ->
+ Store = Ts#tidstore.store,
+ Objs = mnesia_index:read(Tid, Store, Tab, Key, Pos),
+ Pat = setelement(Pos, val({Tab, wild_pattern}), Key),
+ add_written_match(Store, Pat, Tab, Objs);
+ true ->
+ abort({bad_type, Tab, Attr, Key})
+ end;
+ _ ->
+ abort({bad_type, Tab, LockKind})
+ end;
+ _Protocol ->
+ dirty_index_read(Tab, Key, Attr)
+ end;
+index_read(_Tid, _Ts, Tab, _Key, _Attr, _LockKind) ->
+ abort({bad_type, Tab}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Dirty access regardless of activities - updates
+
+dirty_write(Val) when tuple(Val), size(Val) > 2 ->
+ Tab = element(1, Val),
+ dirty_write(Tab, Val);
+dirty_write(Val) ->
+ abort({bad_type, Val}).
+
+dirty_write(Tab, Val) ->
+ do_dirty_write(async_dirty, Tab, Val).
+
+do_dirty_write(SyncMode, Tab, Val)
+ when atom(Tab), Tab /= schema, tuple(Val), size(Val) > 2 ->
+ case ?catch_val({Tab, record_validation}) of
+ {RecName, Arity, _Type}
+ when size(Val) == Arity, RecName == element(1, Val) ->
+ Oid = {Tab, element(2, Val)},
+ mnesia_tm:dirty(SyncMode, {Oid, Val, write});
+ {'EXIT', _} ->
+ abort({no_exists, Tab});
+ _ ->
+ abort({bad_type, Val})
+ end;
+do_dirty_write(_SyncMode, Tab, Val) ->
+ abort({bad_type, Tab, Val}).
+
+dirty_delete({Tab, Key}) ->
+ dirty_delete(Tab, Key);
+dirty_delete(Oid) ->
+ abort({bad_type, Oid}).
+
+dirty_delete(Tab, Key) ->
+ do_dirty_delete(async_dirty, Tab, Key).
+
+do_dirty_delete(SyncMode, Tab, Key) when atom(Tab), Tab /= schema ->
+ Oid = {Tab, Key},
+ mnesia_tm:dirty(SyncMode, {Oid, Oid, delete});
+do_dirty_delete(_SyncMode, Tab, _Key) ->
+ abort({bad_type, Tab}).
+
+dirty_delete_object(Val) when tuple(Val), size(Val) > 2 ->
+ Tab = element(1, Val),
+ dirty_delete_object(Tab, Val);
+dirty_delete_object(Val) ->
+ abort({bad_type, Val}).
+
+dirty_delete_object(Tab, Val) ->
+ do_dirty_delete_object(async_dirty, Tab, Val).
+
+do_dirty_delete_object(SyncMode, Tab, Val)
+ when atom(Tab), Tab /= schema, tuple(Val), size(Val) > 2 ->
+ Oid = {Tab, element(2, Val)},
+ mnesia_tm:dirty(SyncMode, {Oid, Val, delete_object});
+do_dirty_delete_object(_SyncMode, Tab, Val) ->
+ abort({bad_type, Tab, Val}).
+
+%% A Counter is an Oid being {CounterTab, CounterName}
+
+dirty_update_counter({Tab, Key}, Incr) ->
+ dirty_update_counter(Tab, Key, Incr);
+dirty_update_counter(Counter, _Incr) ->
+ abort({bad_type, Counter}).
+
+dirty_update_counter(Tab, Key, Incr) ->
+ do_dirty_update_counter(async_dirty, Tab, Key, Incr).
+
+do_dirty_update_counter(SyncMode, Tab, Key, Incr)
+ when atom(Tab), Tab /= schema, integer(Incr) ->
+ case ?catch_val({Tab, record_validation}) of
+ {RecName, 3, set} ->
+ Oid = {Tab, Key},
+ mnesia_tm:dirty(SyncMode, {Oid, {RecName, Incr}, update_counter});
+ _ ->
+ abort({combine_error, Tab, update_counter})
+ end;
+do_dirty_update_counter(_SyncMode, Tab, _Key, Incr) ->
+ abort({bad_type, Tab, Incr}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Dirty access regardless of activities - read
+
+dirty_read({Tab, Key}) ->
+ dirty_read(Tab, Key);
+dirty_read(Oid) ->
+ abort({bad_type, Oid}).
+
+dirty_read(Tab, Key)
+ when atom(Tab), Tab /= schema ->
+%% case catch ?ets_lookup(Tab, Key) of
+%% {'EXIT', _} ->
+ %% Bad luck, we have to perform a real lookup
+ dirty_rpc(Tab, mnesia_lib, db_get, [Tab, Key]);
+%% Val ->
+%% Val
+%% end;
+dirty_read(Tab, _Key) ->
+ abort({bad_type, Tab}).
+
+dirty_match_object(Pat) when tuple(Pat), size(Pat) > 2 ->
+ Tab = element(1, Pat),
+ dirty_match_object(Tab, Pat);
+dirty_match_object(Pat) ->
+ abort({bad_type, Pat}).
+
+dirty_match_object(Tab, Pat)
+ when atom(Tab), Tab /= schema, tuple(Pat), size(Pat) > 2 ->
+ dirty_rpc(Tab, ?MODULE, remote_dirty_match_object, [Tab, Pat]);
+dirty_match_object(Tab, Pat) ->
+ abort({bad_type, Tab, Pat}).
+
+remote_dirty_match_object(Tab, Pat) ->
+ Key = element(2, Pat),
+ case has_var(Key) of
+ false ->
+ mnesia_lib:db_match_object(Tab, Pat);
+ true ->
+ PosList = val({Tab, index}),
+ remote_dirty_match_object(Tab, Pat, PosList)
+ end.
+
+remote_dirty_match_object(Tab, Pat, [Pos | Tail]) when Pos =< size(Pat) ->
+ IxKey = element(Pos, Pat),
+ case has_var(IxKey) of
+ false ->
+ mnesia_index:dirty_match_object(Tab, Pat, Pos);
+ true ->
+ remote_dirty_match_object(Tab, Pat, Tail)
+ end;
+remote_dirty_match_object(Tab, Pat, []) ->
+ mnesia_lib:db_match_object(Tab, Pat);
+remote_dirty_match_object(Tab, Pat, _PosList) ->
+ abort({bad_type, Tab, Pat}).
+
+dirty_select(Tab, Spec) when atom(Tab), Tab /= schema, list(Spec) ->
+ dirty_rpc(Tab, ?MODULE, remote_dirty_select, [Tab, Spec]);
+dirty_select(Tab, Spec) ->
+ abort({bad_type, Tab, Spec}).
+
+remote_dirty_select(Tab, Spec) ->
+ case Spec of
+ [{HeadPat, _, _}] when tuple(HeadPat), size(HeadPat) > 2 ->
+ Key = element(2, HeadPat),
+ case has_var(Key) of
+ false ->
+ mnesia_lib:db_select(Tab, Spec);
+ true ->
+ PosList = val({Tab, index}),
+ remote_dirty_select(Tab, Spec, PosList)
+ end;
+ _ ->
+ mnesia_lib:db_select(Tab, Spec)
+ end.
+
+remote_dirty_select(Tab, [{HeadPat,_, _}] = Spec, [Pos | Tail])
+ when tuple(HeadPat), size(HeadPat) > 2, Pos =< size(Spec) ->
+ Key = element(Pos, HeadPat),
+ case has_var(Key) of
+ false ->
+ Recs = mnesia_index:dirty_select(Tab, Spec, Pos),
+ %% Returns the records without applying the match spec
+ %% The actual filtering is handled by the caller
+ CMS = ets:match_spec_compile(Spec),
+ case val({Tab, setorbag}) of
+ ordered_set ->
+ ets:match_spec_run(lists:sort(Recs), CMS);
+ _ ->
+ ets:match_spec_run(Recs, CMS)
+ end;
+ true ->
+ remote_dirty_select(Tab, Spec, Tail)
+ end;
+remote_dirty_select(Tab, Spec, _) ->
+ mnesia_lib:db_select(Tab, Spec).
+
+dirty_all_keys(Tab) when atom(Tab), Tab /= schema ->
+ case ?catch_val({Tab, wild_pattern}) of
+ {'EXIT', _} ->
+ abort({no_exists, Tab});
+ Pat0 ->
+ Pat = setelement(2, Pat0, '$1'),
+ Keys = dirty_select(Tab, [{Pat, [], ['$1']}]),
+ case val({Tab, setorbag}) of
+ bag -> mnesia_lib:uniq(Keys);
+ _ -> Keys
+ end
+ end;
+dirty_all_keys(Tab) ->
+ abort({bad_type, Tab}).
+
+dirty_index_match_object(Pat, Attr) when tuple(Pat), size(Pat) > 2 ->
+ Tab = element(1, Pat),
+ dirty_index_match_object(Tab, Pat, Attr);
+dirty_index_match_object(Pat, _Attr) ->
+ abort({bad_type, Pat}).
+
+dirty_index_match_object(Tab, Pat, Attr)
+ when atom(Tab), Tab /= schema, tuple(Pat), size(Pat) > 2 ->
+ case mnesia_schema:attr_tab_to_pos(Tab, Attr) of
+ Pos when Pos =< size(Pat) ->
+ case has_var(element(2, Pat)) of
+ false ->
+ dirty_match_object(Tab, Pat);
+ true ->
+ Elem = element(Pos, Pat),
+ case has_var(Elem) of
+ false ->
+ dirty_rpc(Tab, mnesia_index, dirty_match_object,
+ [Tab, Pat, Pos]);
+ true ->
+ abort({bad_type, Tab, Attr, Elem})
+ end
+ end;
+ BadPos ->
+ abort({bad_type, Tab, BadPos})
+ end;
+dirty_index_match_object(Tab, Pat, _Attr) ->
+ abort({bad_type, Tab, Pat}).
+
+dirty_index_read(Tab, Key, Attr) when atom(Tab), Tab /= schema ->
+ Pos = mnesia_schema:attr_tab_to_pos(Tab, Attr),
+ case has_var(Key) of
+ false ->
+ mnesia_index:dirty_read(Tab, Key, Pos);
+ true ->
+ abort({bad_type, Tab, Attr, Key})
+ end;
+dirty_index_read(Tab, _Key, _Attr) ->
+ abort({bad_type, Tab}).
+
+dirty_slot(Tab, Slot) when atom(Tab), Tab /= schema, integer(Slot) ->
+ dirty_rpc(Tab, mnesia_lib, db_slot, [Tab, Slot]);
+dirty_slot(Tab, Slot) ->
+ abort({bad_type, Tab, Slot}).
+
+dirty_first(Tab) when atom(Tab), Tab /= schema ->
+ dirty_rpc(Tab, mnesia_lib, db_first, [Tab]);
+dirty_first(Tab) ->
+ abort({bad_type, Tab}).
+
+dirty_last(Tab) when atom(Tab), Tab /= schema ->
+ dirty_rpc(Tab, mnesia_lib, db_last, [Tab]);
+dirty_last(Tab) ->
+ abort({bad_type, Tab}).
+
+dirty_next(Tab, Key) when atom(Tab), Tab /= schema ->
+ dirty_rpc(Tab, mnesia_lib, db_next_key, [Tab, Key]);
+dirty_next(Tab, _Key) ->
+ abort({bad_type, Tab}).
+
+dirty_prev(Tab, Key) when atom(Tab), Tab /= schema ->
+ dirty_rpc(Tab, mnesia_lib, db_prev_key, [Tab, Key]);
+dirty_prev(Tab, _Key) ->
+ abort({bad_type, Tab}).
+
+
+dirty_rpc(Tab, M, F, Args) ->
+ Node = val({Tab, where_to_read}),
+ do_dirty_rpc(Tab, Node, M, F, Args).
+
+do_dirty_rpc(_Tab, nowhere, _, _, Args) ->
+ mnesia:abort({no_exists, Args});
+do_dirty_rpc(Tab, Node, M, F, Args) ->
+ case rpc:call(Node, M, F, Args) of
+ {badrpc,{'EXIT', {undef, [{ M, F, _} | _]}}}
+ when M == ?MODULE, F == remote_dirty_select ->
+ %% Oops, the other node has not been upgraded
+ %% to 4.0.3 yet. Lets do it the old way.
+ %% Remove this in next release.
+ do_dirty_rpc(Tab, Node, mnesia_lib, db_select, Args);
+ {badrpc, Reason} ->
+ erlang:yield(), %% Do not be too eager
+ case mnesia_controller:call({check_w2r, Node, Tab}) of % Sync
+ NewNode when NewNode == Node ->
+ ErrorTag = mnesia_lib:dirty_rpc_error_tag(Reason),
+ mnesia:abort({ErrorTag, Args});
+ NewNode ->
+ case get(mnesia_activity_state) of
+ {_Mod, Tid, _Ts} when record(Tid, tid) ->
+ %% In order to perform a consistent
+ %% retry of a transaction we need
+ %% to acquire the lock on the NewNode.
+ %% In this context we do neither know
+ %% the kind or granularity of the lock.
+ %% --> Abort the transaction
+ mnesia:abort({node_not_running, Node});
+ _ ->
+ %% Splendid! A dirty retry is safe
+ %% 'Node' probably went down now
+ %% Let mnesia_controller get broken link message first
+ do_dirty_rpc(Tab, NewNode, M, F, Args)
+ end
+ end;
+ Other ->
+ Other
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Info
+
+%% Info about one table
+table_info(Tab, Item) ->
+ case get(mnesia_activity_state) of
+ undefined ->
+ any_table_info(Tab, Item);
+ {?DEFAULT_ACCESS, _Tid, _Ts} ->
+ any_table_info(Tab, Item);
+ {Mod, Tid, Ts} ->
+ Mod:table_info(Tid, Ts, Tab, Item);
+ _ ->
+ abort(no_transaction)
+ end.
+
+table_info(_Tid, _Ts, Tab, Item) ->
+ any_table_info(Tab, Item).
+
+
+any_table_info(Tab, Item) when atom(Tab) ->
+ case Item of
+ master_nodes ->
+ mnesia_recover:get_master_nodes(Tab);
+% checkpoints ->
+% case ?catch_val({Tab, commit_work}) of
+% [{checkpoints, List} | _] -> List;
+% No_chk when list(No_chk) -> [];
+% Else -> info_reply(Else, Tab, Item)
+% end;
+ size ->
+ raw_table_info(Tab, Item);
+ memory ->
+ raw_table_info(Tab, Item);
+ type ->
+ case ?catch_val({Tab, setorbag}) of
+ {'EXIT', _} ->
+ bad_info_reply(Tab, Item);
+ Val ->
+ Val
+ end;
+ all ->
+ case mnesia_schema:get_table_properties(Tab) of
+ [] ->
+ abort({no_exists, Tab, Item});
+ Props ->
+ lists:map(fun({setorbag, Type}) -> {type, Type};
+ (Prop) -> Prop end,
+ Props)
+ end;
+ _ ->
+ case ?catch_val({Tab, Item}) of
+ {'EXIT', _} ->
+ bad_info_reply(Tab, Item);
+ Val ->
+ Val
+ end
+ end;
+any_table_info(Tab, _Item) ->
+ abort({bad_type, Tab}).
+
+raw_table_info(Tab, Item) ->
+ case ?catch_val({Tab, storage_type}) of
+ ram_copies ->
+ info_reply(catch ?ets_info(Tab, Item), Tab, Item);
+ disc_copies ->
+ info_reply(catch ?ets_info(Tab, Item), Tab, Item);
+ disc_only_copies ->
+ info_reply(catch dets:info(Tab, Item), Tab, Item);
+ unknown ->
+ bad_info_reply(Tab, Item);
+ {'EXIT', _} ->
+ bad_info_reply(Tab, Item)
+ end.
+
+info_reply({'EXIT', _Reason}, Tab, Item) ->
+ bad_info_reply(Tab, Item);
+info_reply({error, _Reason}, Tab, Item) ->
+ bad_info_reply(Tab, Item);
+info_reply(Val, _Tab, _Item) ->
+ Val.
+
+bad_info_reply(_Tab, size) -> 0;
+bad_info_reply(_Tab, memory) -> 0;
+bad_info_reply(Tab, Item) -> abort({no_exists, Tab, Item}).
+
+%% Raw info about all tables
+schema() ->
+ mnesia_schema:info().
+
+%% Raw info about one tables
+schema(Tab) ->
+ mnesia_schema:info(Tab).
+
+error_description(Err) ->
+ mnesia_lib:error_desc(Err).
+
+info() ->
+ case mnesia_lib:is_running() of
+ yes ->
+ TmInfo = mnesia_tm:get_info(10000),
+ Held = system_info(held_locks),
+ Queued = system_info(lock_queue),
+
+ io:format("---> Processes holding locks <--- ~n", []),
+ lists:foreach(fun(L) -> io:format("Lock: ~p~n", [L]) end,
+ Held),
+
+ io:format( "---> Processes waiting for locks <--- ~n", []),
+ lists:foreach(fun({Oid, Op, _Pid, Tid, OwnerTid}) ->
+ io:format("Tid ~p waits for ~p lock "
+ "on oid ~p owned by ~p ~n",
+ [Tid, Op, Oid, OwnerTid])
+ end, Queued),
+ mnesia_tm:display_info(group_leader(), TmInfo),
+
+ Pat = {'_', unclear, '_'},
+ Uncertain = ets:match_object(mnesia_decision, Pat),
+
+ io:format( "---> Uncertain transactions <--- ~n", []),
+ lists:foreach(fun({Tid, _, Nodes}) ->
+ io:format("Tid ~w waits for decision "
+ "from ~w~n",
+ [Tid, Nodes])
+ end, Uncertain),
+
+ mnesia_controller:info(),
+ display_system_info(Held, Queued, TmInfo, Uncertain);
+ _ ->
+ mini_info()
+ end,
+ ok.
+
+mini_info() ->
+ io:format("===> System info in version ~p, debug level = ~p <===~n",
+ [system_info(version), system_info(debug)]),
+ Not =
+ case system_info(use_dir) of
+ true -> "";
+ false -> "NOT "
+ end,
+
+ io:format("~w. Directory ~p is ~sused.~n",
+ [system_info(schema_location), system_info(directory), Not]),
+ io:format("use fallback at restart = ~w~n",
+ [system_info(fallback_activated)]),
+ Running = system_info(running_db_nodes),
+ io:format("running db nodes = ~w~n", [Running]),
+ All = mnesia_lib:all_nodes(),
+ io:format("stopped db nodes = ~w ~n", [All -- Running]).
+
+display_system_info(Held, Queued, TmInfo, Uncertain) ->
+ mini_info(),
+ display_tab_info(),
+ S = fun(Items) -> [system_info(I) || I <- Items] end,
+
+ io:format("~w transactions committed, ~w aborted, "
+ "~w restarted, ~w logged to disc~n",
+ S([transaction_commits, transaction_failures,
+ transaction_restarts, transaction_log_writes])),
+
+ {Active, Pending} =
+ case TmInfo of
+ {timeout, _} -> {infinity, infinity};
+ {info, P, A} -> {length(A), length(P)}
+ end,
+ io:format("~w held locks, ~w in queue; "
+ "~w local transactions, ~w remote~n",
+ [length(Held), length(Queued), Active, Pending]),
+
+ Ufold = fun({_, _, Ns}, {C, Old}) ->
+ New = [N || N <- Ns, not lists:member(N, Old)],
+ {C + 1, New ++ Old}
+ end,
+ {Ucount, Unodes} = lists:foldl(Ufold, {0, []}, Uncertain),
+ io:format("~w transactions waits for other nodes: ~p~n",
+ [Ucount, Unodes]).
+
+display_tab_info() ->
+ MasterTabs = mnesia_recover:get_master_node_tables(),
+ io:format("master node tables = ~p~n", [lists:sort(MasterTabs)]),
+
+ Tabs = system_info(tables),
+
+ {Unknown, Ram, Disc, DiscOnly} =
+ lists:foldl(fun storage_count/2, {[], [], [], []}, Tabs),
+
+ io:format("remote = ~p~n", [lists:sort(Unknown)]),
+ io:format("ram_copies = ~p~n", [lists:sort(Ram)]),
+ io:format("disc_copies = ~p~n", [lists:sort(Disc)]),
+ io:format("disc_only_copies = ~p~n", [lists:sort(DiscOnly)]),
+
+ Rfoldl = fun(T, Acc) ->
+ Rpat =
+ case val({T, access_mode}) of
+ read_only ->
+ lists:sort([{A, read_only} || A <- val({T, active_replicas})]);
+ read_write ->
+ table_info(T, where_to_commit)
+ end,
+ case lists:keysearch(Rpat, 1, Acc) of
+ {value, {_Rpat, Rtabs}} ->
+ lists:keyreplace(Rpat, 1, Acc, {Rpat, [T | Rtabs]});
+ false ->
+ [{Rpat, [T]} | Acc]
+ end
+ end,
+ Repl = lists:foldl(Rfoldl, [], Tabs),
+ Rdisp = fun({Rpat, Rtabs}) -> io:format("~p = ~p~n", [Rpat, Rtabs]) end,
+ lists:foreach(Rdisp, lists:sort(Repl)).
+
+storage_count(T, {U, R, D, DO}) ->
+ case table_info(T, storage_type) of
+ unknown -> {[T | U], R, D, DO};
+ ram_copies -> {U, [T | R], D, DO};
+ disc_copies -> {U, R, [T | D], DO};
+ disc_only_copies -> {U, R, D, [T | DO]}
+ end.
+
+system_info(Item) ->
+ case catch system_info2(Item) of
+ {'EXIT',Error} -> abort(Error);
+ Other -> Other
+ end.
+
+system_info2(all) ->
+ Items = system_info_items(mnesia_lib:is_running()),
+ [{I, system_info(I)} || I <- Items];
+
+system_info2(db_nodes) ->
+ DiscNs = ?catch_val({schema, disc_copies}),
+ RamNs = ?catch_val({schema, ram_copies}),
+ if
+ list(DiscNs), list(RamNs) ->
+ DiscNs ++ RamNs;
+ true ->
+ case mnesia_schema:read_nodes() of
+ {ok, Nodes} -> Nodes;
+ {error,Reason} -> exit(Reason)
+ end
+ end;
+system_info2(running_db_nodes) ->
+ case ?catch_val({current, db_nodes}) of
+ {'EXIT',_} ->
+ %% Ensure that we access the intended Mnesia
+ %% directory. This function may not be called
+ %% during startup since it will cause the
+ %% application_controller to get into deadlock
+ load_mnesia_or_abort(),
+ mnesia_lib:running_nodes();
+ Other ->
+ Other
+ end;
+
+system_info2(extra_db_nodes) ->
+ case ?catch_val(extra_db_nodes) of
+ {'EXIT',_} ->
+ %% Ensure that we access the intended Mnesia
+ %% directory. This function may not be called
+ %% during startup since it will cause the
+ %% application_controller to get into deadlock
+ load_mnesia_or_abort(),
+ mnesia_monitor:get_env(extra_db_nodes);
+ Other ->
+ Other
+ end;
+
+system_info2(directory) ->
+ case ?catch_val(directory) of
+ {'EXIT',_} ->
+ %% Ensure that we access the intended Mnesia
+ %% directory. This function may not be called
+ %% during startup since it will cause the
+ %% application_controller to get into deadlock
+ load_mnesia_or_abort(),
+ mnesia_monitor:get_env(dir);
+ Other ->
+ Other
+ end;
+
+system_info2(use_dir) ->
+ case ?catch_val(use_dir) of
+ {'EXIT',_} ->
+ %% Ensure that we access the intended Mnesia
+ %% directory. This function may not be called
+ %% during startup since it will cause the
+ %% application_controller to get into deadlock
+ load_mnesia_or_abort(),
+ mnesia_monitor:use_dir();
+ Other ->
+ Other
+ end;
+
+system_info2(schema_location) ->
+ case ?catch_val(schema_location) of
+ {'EXIT',_} ->
+ %% Ensure that we access the intended Mnesia
+ %% directory. This function may not be called
+ %% during startup since it will cause the
+ %% application_controller to get into deadlock
+ load_mnesia_or_abort(),
+ mnesia_monitor:get_env(schema_location);
+ Other ->
+ Other
+ end;
+
+system_info2(fallback_activated) ->
+ case ?catch_val(fallback_activated) of
+ {'EXIT',_} ->
+ %% Ensure that we access the intended Mnesia
+ %% directory. This function may not be called
+ %% during startup since it will cause the
+ %% application_controller to get into deadlock
+ load_mnesia_or_abort(),
+ mnesia_bup:fallback_exists();
+ Other ->
+ Other
+ end;
+
+system_info2(version) ->
+ case ?catch_val(version) of
+ {'EXIT', _} ->
+ Apps = application:loaded_applications(),
+ case lists:keysearch(?APPLICATION, 1, Apps) of
+ {value, {_Name, _Desc, Version}} ->
+ Version;
+ false ->
+ %% Ensure that it does not match
+ {mnesia_not_loaded, node(), now()}
+ end;
+ Version ->
+ Version
+ end;
+
+system_info2(access_module) -> mnesia_monitor:get_env(access_module);
+system_info2(auto_repair) -> mnesia_monitor:get_env(auto_repair);
+system_info2(is_running) -> mnesia_lib:is_running();
+system_info2(backup_module) -> mnesia_monitor:get_env(backup_module);
+system_info2(event_module) -> mnesia_monitor:get_env(event_module);
+system_info2(debug) -> mnesia_monitor:get_env(debug);
+system_info2(dump_log_load_regulation) -> mnesia_monitor:get_env(dump_log_load_regulation);
+system_info2(dump_log_write_threshold) -> mnesia_monitor:get_env(dump_log_write_threshold);
+system_info2(dump_log_time_threshold) -> mnesia_monitor:get_env(dump_log_time_threshold);
+system_info2(dump_log_update_in_place) ->
+ mnesia_monitor:get_env(dump_log_update_in_place);
+system_info2(dump_log_update_in_place) ->
+ mnesia_monitor:get_env(dump_log_update_in_place);
+system_info2(max_wait_for_decision) -> mnesia_monitor:get_env(max_wait_for_decision);
+system_info2(embedded_mnemosyne) -> mnesia_monitor:get_env(embedded_mnemosyne);
+system_info2(ignore_fallback_at_startup) -> mnesia_monitor:get_env(ignore_fallback_at_startup);
+system_info2(fallback_error_function) -> mnesia_monitor:get_env(fallback_error_function);
+system_info2(log_version) -> mnesia_log:version();
+system_info2(protocol_version) -> mnesia_monitor:protocol_version();
+system_info2(schema_version) -> mnesia_schema:version(); %backward compatibility
+system_info2(tables) -> val({schema, tables});
+system_info2(local_tables) -> val({schema, local_tables});
+system_info2(master_node_tables) -> mnesia_recover:get_master_node_tables();
+system_info2(subscribers) -> mnesia_subscr:subscribers();
+system_info2(checkpoints) -> mnesia_checkpoint:checkpoints();
+system_info2(held_locks) -> mnesia_locker:get_held_locks();
+system_info2(lock_queue) -> mnesia_locker:get_lock_queue();
+system_info2(transactions) -> mnesia_tm:get_transactions();
+system_info2(transaction_failures) -> mnesia_lib:read_counter(trans_failures);
+system_info2(transaction_commits) -> mnesia_lib:read_counter(trans_commits);
+system_info2(transaction_restarts) -> mnesia_lib:read_counter(trans_restarts);
+system_info2(transaction_log_writes) -> mnesia_dumper:get_log_writes();
+
+system_info2(Item) -> exit({badarg, Item}).
+
+system_info_items(yes) ->
+ [
+ access_module,
+ auto_repair,
+ backup_module,
+ checkpoints,
+ db_nodes,
+ debug,
+ directory,
+ dump_log_load_regulation,
+ dump_log_time_threshold,
+ dump_log_update_in_place,
+ dump_log_write_threshold,
+ embedded_mnemosyne,
+ event_module,
+ extra_db_nodes,
+ fallback_activated,
+ held_locks,
+ ignore_fallback_at_startup,
+ fallback_error_function,
+ is_running,
+ local_tables,
+ lock_queue,
+ log_version,
+ master_node_tables,
+ max_wait_for_decision,
+ protocol_version,
+ running_db_nodes,
+ schema_location,
+ schema_version,
+ subscribers,
+ tables,
+ transaction_commits,
+ transaction_failures,
+ transaction_log_writes,
+ transaction_restarts,
+ transactions,
+ use_dir,
+ version
+ ];
+system_info_items(no) ->
+ [
+ auto_repair,
+ backup_module,
+ db_nodes,
+ debug,
+ directory,
+ dump_log_load_regulation,
+ dump_log_time_threshold,
+ dump_log_update_in_place,
+ dump_log_write_threshold,
+ event_module,
+ extra_db_nodes,
+ ignore_fallback_at_startup,
+ fallback_error_function,
+ is_running,
+ log_version,
+ max_wait_for_decision,
+ protocol_version,
+ running_db_nodes,
+ schema_location,
+ schema_version,
+ use_dir,
+ version
+ ].
+
+system_info() ->
+ IsRunning = mnesia_lib:is_running(),
+ case IsRunning of
+ yes ->
+ TmInfo = mnesia_tm:get_info(10000),
+ Held = system_info(held_locks),
+ Queued = system_info(lock_queue),
+ Pat = {'_', unclear, '_'},
+ Uncertain = ets:match_object(mnesia_decision, Pat),
+ display_system_info(Held, Queued, TmInfo, Uncertain);
+ _ ->
+ mini_info()
+ end,
+ IsRunning.
+
+load_mnesia_or_abort() ->
+ case mnesia_lib:ensure_loaded(?APPLICATION) of
+ ok ->
+ ok;
+ {error, Reason} ->
+ abort(Reason)
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Database mgt
+
+create_schema(Ns) ->
+ mnesia_bup:create_schema(Ns).
+
+delete_schema(Ns) ->
+ mnesia_schema:delete_schema(Ns).
+
+backup(Opaque) ->
+ mnesia_log:backup(Opaque).
+
+backup(Opaque, Mod) ->
+ mnesia_log:backup(Opaque, Mod).
+
+traverse_backup(S, T, Fun, Acc) ->
+ mnesia_bup:traverse_backup(S, T, Fun, Acc).
+
+traverse_backup(S, SM, T, TM, F, A) ->
+ mnesia_bup:traverse_backup(S, SM, T, TM, F, A).
+
+install_fallback(Opaque) ->
+ mnesia_bup:install_fallback(Opaque).
+
+install_fallback(Opaque, Mod) ->
+ mnesia_bup:install_fallback(Opaque, Mod).
+
+uninstall_fallback() ->
+ mnesia_bup:uninstall_fallback().
+
+uninstall_fallback(Args) ->
+ mnesia_bup:uninstall_fallback(Args).
+
+activate_checkpoint(Args) ->
+ mnesia_checkpoint:activate(Args).
+
+deactivate_checkpoint(Name) ->
+ mnesia_checkpoint:deactivate(Name).
+
+backup_checkpoint(Name, Opaque) ->
+ mnesia_log:backup_checkpoint(Name, Opaque).
+
+backup_checkpoint(Name, Opaque, Mod) ->
+ mnesia_log:backup_checkpoint(Name, Opaque, Mod).
+
+restore(Opaque, Args) ->
+ mnesia_schema:restore(Opaque, Args).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Table mgt
+
+create_table(Arg) ->
+ mnesia_schema:create_table(Arg).
+create_table(Name, Arg) when list(Arg) ->
+ mnesia_schema:create_table([{name, Name}| Arg]);
+create_table(Name, Arg) ->
+ {aborted, badarg, Name, Arg}.
+
+delete_table(Tab) ->
+ mnesia_schema:delete_table(Tab).
+
+add_table_copy(Tab, N, S) ->
+ mnesia_schema:add_table_copy(Tab, N, S).
+del_table_copy(Tab, N) ->
+ mnesia_schema:del_table_copy(Tab, N).
+
+move_table_copy(Tab, From, To) ->
+ mnesia_schema:move_table(Tab, From, To).
+
+add_table_index(Tab, Ix) ->
+ mnesia_schema:add_table_index(Tab, Ix).
+del_table_index(Tab, Ix) ->
+ mnesia_schema:del_table_index(Tab, Ix).
+
+transform_table(Tab, Fun, NewA) ->
+ case catch val({Tab, record_name}) of
+ {'EXIT', Reason} ->
+ mnesia:abort(Reason);
+ OldRN ->
+ mnesia_schema:transform_table(Tab, Fun, NewA, OldRN)
+ end.
+
+transform_table(Tab, Fun, NewA, NewRN) ->
+ mnesia_schema:transform_table(Tab, Fun, NewA, NewRN).
+
+change_table_copy_type(T, N, S) ->
+ mnesia_schema:change_table_copy_type(T, N, S).
+
+clear_table(Tab) ->
+ mnesia_schema:clear_table(Tab).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Table mgt - user properties
+
+read_table_property(Tab, PropKey) ->
+ val({Tab, user_property, PropKey}).
+
+write_table_property(Tab, Prop) ->
+ mnesia_schema:write_table_property(Tab, Prop).
+
+delete_table_property(Tab, PropKey) ->
+ mnesia_schema:delete_table_property(Tab, PropKey).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Table mgt - user properties
+
+change_table_frag(Tab, FragProp) ->
+ mnesia_schema:change_table_frag(Tab, FragProp).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Table mgt - table load
+
+%% Dump a ram table to disc
+dump_tables(Tabs) ->
+ mnesia_schema:dump_tables(Tabs).
+
+%% allow the user to wait for some tables to be loaded
+wait_for_tables(Tabs, Timeout) ->
+ mnesia_controller:wait_for_tables(Tabs, Timeout).
+
+force_load_table(Tab) ->
+ case mnesia_controller:force_load_table(Tab) of
+ ok -> yes; % Backwards compatibility
+ Other -> Other
+ end.
+
+change_table_access_mode(T, Access) ->
+ mnesia_schema:change_table_access_mode(T, Access).
+
+change_table_load_order(T, O) ->
+ mnesia_schema:change_table_load_order(T, O).
+
+set_master_nodes(Nodes) when list(Nodes) ->
+ UseDir = system_info(use_dir),
+ IsRunning = system_info(is_running),
+ case IsRunning of
+ yes ->
+ CsPat = {{'_', cstruct}, '_'},
+ Cstructs0 = ?ets_match_object(mnesia_gvar, CsPat),
+ Cstructs = [Cs || {_, Cs} <- Cstructs0],
+ log_valid_master_nodes(Cstructs, Nodes, UseDir, IsRunning);
+ _NotRunning ->
+ case UseDir of
+ true ->
+ mnesia_lib:lock_table(schema),
+ Res =
+ case mnesia_schema:read_cstructs_from_disc() of
+ {ok, Cstructs} ->
+ log_valid_master_nodes(Cstructs, Nodes, UseDir, IsRunning);
+ {error, Reason} ->
+ {error, Reason}
+ end,
+ mnesia_lib:unlock_table(schema),
+ Res;
+ false ->
+ ok
+ end
+ end;
+set_master_nodes(Nodes) ->
+ {error, {bad_type, Nodes}}.
+
+log_valid_master_nodes(Cstructs, Nodes, UseDir, IsRunning) ->
+ Fun = fun(Cs) ->
+ Copies = mnesia_lib:copy_holders(Cs),
+ Valid = mnesia_lib:intersect(Nodes, Copies),
+ {Cs#cstruct.name, Valid}
+ end,
+ Args = lists:map(Fun, Cstructs),
+ mnesia_recover:log_master_nodes(Args, UseDir, IsRunning).
+
+set_master_nodes(Tab, Nodes) when list(Nodes) ->
+ UseDir = system_info(use_dir),
+ IsRunning = system_info(is_running),
+ case IsRunning of
+ yes ->
+ case ?catch_val({Tab, cstruct}) of
+ {'EXIT', _} ->
+ {error, {no_exists, Tab}};
+ Cs ->
+ case Nodes -- mnesia_lib:copy_holders(Cs) of
+ [] ->
+ Args = [{Tab , Nodes}],
+ mnesia_recover:log_master_nodes(Args, UseDir, IsRunning);
+ BadNodes ->
+ {error, {no_exists, Tab, BadNodes}}
+ end
+ end;
+ _NotRunning ->
+ case UseDir of
+ true ->
+ mnesia_lib:lock_table(schema),
+ Res =
+ case mnesia_schema:read_cstructs_from_disc() of
+ {ok, Cstructs} ->
+ case lists:keysearch(Tab, 2, Cstructs) of
+ {value, Cs} ->
+ case Nodes -- mnesia_lib:copy_holders(Cs) of
+ [] ->
+ Args = [{Tab , Nodes}],
+ mnesia_recover:log_master_nodes(Args, UseDir, IsRunning);
+ BadNodes ->
+ {error, {no_exists, Tab, BadNodes}}
+ end;
+ false ->
+ {error, {no_exists, Tab}}
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end,
+ mnesia_lib:unlock_table(schema),
+ Res;
+ false ->
+ ok
+ end
+ end;
+set_master_nodes(Tab, Nodes) ->
+ {error, {bad_type, Tab, Nodes}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Misc admin
+
+dump_log() ->
+ mnesia_controller:sync_dump_log(user).
+
+subscribe(What) ->
+ mnesia_subscr:subscribe(self(), What).
+
+unsubscribe(What) ->
+ mnesia_subscr:unsubscribe(self(), What).
+
+report_event(Event) ->
+ mnesia_lib:report_system_event({mnesia_user, Event}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Snmp
+
+snmp_open_table(Tab, Us) ->
+ mnesia_schema:add_snmp(Tab, Us).
+
+snmp_close_table(Tab) ->
+ mnesia_schema:del_snmp(Tab).
+
+snmp_get_row(Tab, RowIndex) when atom(Tab), Tab /= schema ->
+ dirty_rpc(Tab, mnesia_snmp_hook, get_row, [Tab, RowIndex]);
+snmp_get_row(Tab, _RowIndex) ->
+ abort({bad_type, Tab}).
+
+snmp_get_next_index(Tab, RowIndex) when atom(Tab), Tab /= schema ->
+ dirty_rpc(Tab, mnesia_snmp_hook, get_next_index, [Tab, RowIndex]);
+snmp_get_next_index(Tab, _RowIndex) ->
+ abort({bad_type, Tab}).
+
+snmp_get_mnesia_key(Tab, RowIndex) when atom(Tab), Tab /= schema ->
+ dirty_rpc(Tab, mnesia_snmp_hook, get_mnesia_key, [Tab, RowIndex]);
+snmp_get_mnesia_key(Tab, _RowIndex) ->
+ abort({bad_type, Tab}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Textfile access
+
+load_textfile(F) ->
+ mnesia_text:load_textfile(F).
+dump_to_textfile(F) ->
+ mnesia_text:dump_to_textfile(F).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Mnemosyne exclusive
+
+get_activity_id() ->
+ get(mnesia_activity_state).
+
+put_activity_id(Activity) ->
+ mnesia_tm:put_activity_id(Activity).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.hrl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.hrl
new file mode 100644
index 0000000000..cd3cee974b
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia.hrl
@@ -0,0 +1,117 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia.hrl,v 1.1 2008/12/17 09:53:37 mikpe Exp $
+%%
+
+-define(APPLICATION, mnesia).
+
+-define(ets_lookup(Tab, Key), ets:lookup(Tab, Key)).
+-define(ets_lookup_element(Tab, Key, Pos), ets:lookup_element(Tab, Key, Pos)).
+-define(ets_insert(Tab, Rec), ets:insert(Tab, Rec)).
+-define(ets_delete(Tab, Key), ets:delete(Tab, Key)).
+-define(ets_match_delete(Tab, Pat), ets:match_delete(Tab, Pat)).
+-define(ets_match_object(Tab, Pat), ets:match_object(Tab, Pat)).
+-define(ets_match(Tab, Pat), ets:match(Tab, Pat)).
+-define(ets_info(Tab, Item), ets:info(Tab, Item)).
+-define(ets_update_counter(Tab, Key, Incr), ets:update_counter(Tab, Key, Incr)).
+-define(ets_first(Tab), ets:first(Tab)).
+-define(ets_next(Tab, Key), ets:next(Tab, Key)).
+-define(ets_last(Tab), ets:last(Tab)).
+-define(ets_prev(Tab, Key), ets:prev(Tab, Key)).
+-define(ets_slot(Tab, Pos), ets:slot(Tab, Pos)).
+-define(ets_new_table(Tab, Props), ets:new(Tab, Props)).
+-define(ets_delete_table(Tab), ets:delete(Tab)).
+-define(ets_fixtable(Tab, Bool), ets:fixtable(Tab, Bool)).
+
+-define(catch_val(Var), (catch ?ets_lookup_element(mnesia_gvar, Var, 2))).
+
+%% It's important that counter is first, since we compare tid's
+
+-record(tid,
+ {counter, %% serial no for tid
+ pid}). %% owner of tid
+
+
+-record(tidstore,
+ {store, %% current ets table for tid
+ up_stores = [], %% list of upper layer stores for nested trans
+ level = 1}). %% transaction level
+
+-define(unique_cookie, {erlang:now(), node()}).
+
+-record(cstruct, {name, % Atom
+ type = set, % set | bag
+ ram_copies = [], % [Node]
+ disc_copies = [], % [Node]
+ disc_only_copies = [], % [Node]
+ load_order = 0, % Integer
+ access_mode = read_write, % read_write | read_only
+ index = [], % [Integer]
+ snmp = [], % Snmp Ustruct
+ local_content = false, % true | false
+ record_name = {bad_record_name}, % Atom (Default = Name)
+ attributes = [key, val], % [Atom]
+ user_properties = [], % [Record]
+ frag_properties = [], % [{Key, Val]
+ cookie = ?unique_cookie, % Term
+ version = {{2, 0}, []}}). % {{Integer, Integer}, [Node]}
+
+%% Record for the head structure in Mnesia's log files
+%%
+%% The definition of this record may *NEVER* be changed
+%% since it may be written to very old backup files.
+%% By holding this record definition stable we can be
+%% able to comprahend backups from timepoint 0. It also
+%% allows us to use the backup format as an interchange
+%% format between Mnesia releases.
+
+-record(log_header,{log_kind,
+ log_version,
+ mnesia_version,
+ node,
+ now}).
+
+%% Commit records stored in the transaction log
+-record(commit, {node,
+ decision, % presume_commit | Decision
+ ram_copies = [],
+ disc_copies = [],
+ disc_only_copies = [],
+ snmp = [],
+ schema_ops = []
+ }).
+
+-record(decision, {tid,
+ outcome, % presume_abort | committed
+ disc_nodes,
+ ram_nodes}).
+
+%% Maybe cyclic wait
+-record(cyclic, {node = node(),
+ oid, % {Tab, Key}
+ op, % read | write
+ lock, % read | write
+ lucky
+ }).
+
+%% Managing conditional debug functions
+
+-ifdef(debug).
+ -define(eval_debug_fun(I, C),
+ mnesia_lib:eval_debug_fun(I, C, ?FILE, ?LINE)).
+-else.
+ -define(eval_debug_fun(I, C), ok).
+-endif.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_backup.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_backup.erl
new file mode 100644
index 0000000000..f01310530e
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_backup.erl
@@ -0,0 +1,194 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_backup.erl,v 1.1 2008/12/17 09:53:37 mikpe Exp $
+%%
+%0
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% This module contains one implementation of callback functions
+%% used by Mnesia at backup and restore. The user may however
+%% write an own module the same interface as mnesia_backup and
+%% configure Mnesia so the alternate module performs the actual
+%% accesses to the backup media. This means that the user may put
+%% the backup on medias that Mnesia does not know about, possibly
+%% on hosts where Erlang is not running.
+%%
+%% The OpaqueData argument is never interpreted by other parts of
+%% Mnesia. It is the property of this module. Alternate implementations
+%% of this module may have different interpretations of OpaqueData.
+%% The OpaqueData argument given to open_write/1 and open_read/1
+%% are forwarded directly from the user.
+%%
+%% All functions must return {ok, NewOpaqueData} or {error, Reason}.
+%%
+%% The NewOpaqueData arguments returned by backup callback functions will
+%% be given as input when the next backup callback function is invoked.
+%% If any return value does not match {ok, _} the backup will be aborted.
+%%
+%% The NewOpaqueData arguments returned by restore callback functions will
+%% be given as input when the next restore callback function is invoked
+%% If any return value does not match {ok, _} the restore will be aborted.
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-module(mnesia_backup).
+-behaviour(mnesia_backup).
+
+-include_lib("kernel/include/file.hrl").
+
+-export([
+ %% Write access
+ open_write/1,
+ write/2,
+ commit_write/1,
+ abort_write/1,
+
+ %% Read access
+ open_read/1,
+ read/1,
+ close_read/1
+ ]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Backup callback interface
+-record(backup, {tmp_file, file, file_desc}).
+
+%% Opens backup media for write
+%%
+%% Returns {ok, OpaqueData} or {error, Reason}
+open_write(OpaqueData) ->
+ File = OpaqueData,
+ Tmp = lists:concat([File,".BUPTMP"]),
+ file:delete(Tmp),
+ file:delete(File),
+ case disk_log:open([{name, make_ref()},
+ {file, Tmp},
+ {repair, false},
+ {linkto, self()}]) of
+ {ok, Fd} ->
+ {ok, #backup{tmp_file = Tmp, file = File, file_desc = Fd}};
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+%% Writes BackupItems to the backup media
+%%
+%% Returns {ok, OpaqueData} or {error, Reason}
+write(OpaqueData, BackupItems) ->
+ B = OpaqueData,
+ case disk_log:log_terms(B#backup.file_desc, BackupItems) of
+ ok ->
+ {ok, B};
+ {error, Reason} ->
+ abort_write(B),
+ {error, Reason}
+ end.
+
+%% Closes the backup media after a successful backup
+%%
+%% Returns {ok, ReturnValueToUser} or {error, Reason}
+commit_write(OpaqueData) ->
+ B = OpaqueData,
+ case disk_log:sync(B#backup.file_desc) of
+ ok ->
+ case disk_log:close(B#backup.file_desc) of
+ ok ->
+ case file:rename(B#backup.tmp_file, B#backup.file) of
+ ok ->
+ {ok, B#backup.file};
+ {error, Reason} ->
+ {error, Reason}
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+%% Closes the backup media after an interrupted backup
+%%
+%% Returns {ok, ReturnValueToUser} or {error, Reason}
+abort_write(BackupRef) ->
+ Res = disk_log:close(BackupRef#backup.file_desc),
+ file:delete(BackupRef#backup.tmp_file),
+ case Res of
+ ok ->
+ {ok, BackupRef#backup.file};
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Restore callback interface
+
+-record(restore, {file, file_desc, cont}).
+
+%% Opens backup media for read
+%%
+%% Returns {ok, OpaqueData} or {error, Reason}
+open_read(OpaqueData) ->
+ File = OpaqueData,
+ case file:read_file_info(File) of
+ {error, Reason} ->
+ {error, Reason};
+ _FileInfo -> %% file exists
+ case disk_log:open([{file, File},
+ {name, make_ref()},
+ {repair, false},
+ {mode, read_only},
+ {linkto, self()}]) of
+ {ok, Fd} ->
+ {ok, #restore{file = File, file_desc = Fd, cont = start}};
+ {repaired, Fd, _, {badbytes, 0}} ->
+ {ok, #restore{file = File, file_desc = Fd, cont = start}};
+ {repaired, Fd, _, _} ->
+ {ok, #restore{file = File, file_desc = Fd, cont = start}};
+ {error, Reason} ->
+ {error, Reason}
+ end
+ end.
+
+%% Reads BackupItems from the backup media
+%%
+%% Returns {ok, OpaqueData, BackupItems} or {error, Reason}
+%%
+%% BackupItems == [] is interpreted as eof
+read(OpaqueData) ->
+ R = OpaqueData,
+ Fd = R#restore.file_desc,
+ case disk_log:chunk(Fd, R#restore.cont) of
+ {error, Reason} ->
+ {error, {"Possibly truncated", Reason}};
+ eof ->
+ {ok, R, []};
+ {Cont, []} ->
+ read(R#restore{cont = Cont});
+ {Cont, BackupItems} ->
+ {ok, R#restore{cont = Cont}, BackupItems}
+ end.
+
+%% Closes the backup media after restore
+%%
+%% Returns {ok, ReturnValueToUser} or {error, Reason}
+close_read(OpaqueData) ->
+ R = OpaqueData,
+ case disk_log:close(R#restore.file_desc) of
+ ok -> {ok, R#restore.file};
+ {error, Reason} -> {error, Reason}
+ end.
+%0
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_bup.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_bup.erl
new file mode 100644
index 0000000000..eb636a8447
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_bup.erl
@@ -0,0 +1,1168 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_bup.erl,v 1.1 2008/12/17 09:53:37 mikpe Exp $
+%%
+-module(mnesia_bup).
+-export([
+ %% Public interface
+ iterate/4,
+ read_schema/2,
+ fallback_bup/0,
+ fallback_exists/0,
+ tm_fallback_start/1,
+ create_schema/1,
+ install_fallback/1,
+ install_fallback/2,
+ uninstall_fallback/0,
+ uninstall_fallback/1,
+ traverse_backup/4,
+ traverse_backup/6,
+ make_initial_backup/3,
+ fallback_to_schema/0,
+ lookup_schema/2,
+ schema2bup/1,
+ refresh_cookie/2,
+
+ %% Internal
+ fallback_receiver/2,
+ install_fallback_master/2,
+ uninstall_fallback_master/2,
+ local_uninstall_fallback/2,
+ do_traverse_backup/7,
+ trav_apply/4
+ ]).
+
+-include("mnesia.hrl").
+-import(mnesia_lib, [verbose/2, dbg_out/2]).
+
+-record(restore, {mode, bup_module, bup_data}).
+
+-record(fallback_args, {opaque,
+ scope = global,
+ module = mnesia_monitor:get_env(backup_module),
+ use_default_dir = true,
+ mnesia_dir,
+ fallback_bup,
+ fallback_tmp,
+ skip_tables = [],
+ keep_tables = [],
+ default_op = keep_tables
+ }).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Backup iterator
+
+%% Reads schema section and iterates over all records in a backup.
+%%
+%% Fun(BunchOfRecords, Header, Schema, Acc) is applied when a suitable amount
+%% of records has been collected.
+%%
+%% BunchOfRecords will be [] when the iteration is done.
+iterate(Mod, Fun, Opaque, Acc) ->
+ R = #restore{bup_module = Mod, bup_data = Opaque},
+ case catch read_schema_section(R) of
+ {error, Reason} ->
+ {error, Reason};
+ {R2, {Header, Schema, Rest}} ->
+ case catch iter(R2, Header, Schema, Fun, Acc, Rest) of
+ {ok, R3, Res} ->
+ catch safe_apply(R3, close_read, [R3#restore.bup_data]),
+ {ok, Res};
+ {error, Reason} ->
+ catch safe_apply(R2, close_read, [R2#restore.bup_data]),
+ {error, Reason};
+ {'EXIT', Pid, Reason} ->
+ catch safe_apply(R2, close_read, [R2#restore.bup_data]),
+ {error, {'EXIT', Pid, Reason}};
+ {'EXIT', Reason} ->
+ catch safe_apply(R2, close_read, [R2#restore.bup_data]),
+ {error, {'EXIT', Reason}}
+ end
+ end.
+
+iter(R, Header, Schema, Fun, Acc, []) ->
+ case safe_apply(R, read, [R#restore.bup_data]) of
+ {R2, []} ->
+ Res = Fun([], Header, Schema, Acc),
+ {ok, R2, Res};
+ {R2, BupItems} ->
+ iter(R2, Header, Schema, Fun, Acc, BupItems)
+ end;
+iter(R, Header, Schema, Fun, Acc, BupItems) ->
+ Acc2 = Fun(BupItems, Header, Schema, Acc),
+ iter(R, Header, Schema, Fun, Acc2, []).
+
+safe_apply(R, write, [_, Items]) when Items == [] ->
+ R;
+safe_apply(R, What, Args) ->
+ Abort = fun(Re) -> abort_restore(R, What, Args, Re) end,
+ receive
+ {'EXIT', Pid, Re} -> Abort({'EXIT', Pid, Re})
+ after 0 ->
+ Mod = R#restore.bup_module,
+ case catch apply(Mod, What, Args) of
+ {ok, Opaque, Items} when What == read ->
+ {R#restore{bup_data = Opaque}, Items};
+ {ok, Opaque} when What /= read->
+ R#restore{bup_data = Opaque};
+ {error, Re} ->
+ Abort(Re);
+ Re ->
+ Abort(Re)
+ end
+ end.
+
+abort_restore(R, What, Args, Reason) ->
+ Mod = R#restore.bup_module,
+ Opaque = R#restore.bup_data,
+ dbg_out("Restore aborted. ~p:~p~p -> ~p~n",
+ [Mod, What, Args, Reason]),
+ catch apply(Mod, close_read, [Opaque]),
+ throw({error, Reason}).
+
+fallback_to_schema() ->
+ Fname = fallback_bup(),
+ fallback_to_schema(Fname).
+
+fallback_to_schema(Fname) ->
+ Mod = mnesia_backup,
+ case read_schema(Mod, Fname) of
+ {error, Reason} ->
+ {error, Reason};
+ Schema ->
+ case catch lookup_schema(schema, Schema) of
+ {error, _} ->
+ {error, "No schema in fallback"};
+ List ->
+ {ok, fallback, List}
+ end
+ end.
+
+%% Opens Opaque reads schema and then close
+read_schema(Mod, Opaque) ->
+ R = #restore{bup_module = Mod, bup_data = Opaque},
+ case catch read_schema_section(R) of
+ {error, Reason} ->
+ {error, Reason};
+ {R2, {_Header, Schema, _}} ->
+ catch safe_apply(R2, close_read, [R2#restore.bup_data]),
+ Schema
+ end.
+
+%% Open backup media and extract schema
+%% rewind backup media and leave it open
+%% Returns {R, {Header, Schema}}
+read_schema_section(R) ->
+ case catch do_read_schema_section(R) of
+ {'EXIT', Reason} ->
+ catch safe_apply(R, close_read, [R#restore.bup_data]),
+ {error, {'EXIT', Reason}};
+ {error, Reason} ->
+ catch safe_apply(R, close_read, [R#restore.bup_data]),
+ {error, Reason};
+ {R2, {H, Schema, Rest}} ->
+ Schema2 = convert_schema(H#log_header.log_version, Schema),
+ {R2, {H, Schema2, Rest}}
+ end.
+
+do_read_schema_section(R) ->
+ R2 = safe_apply(R, open_read, [R#restore.bup_data]),
+ {R3, RawSchema} = safe_apply(R2, read, [R2#restore.bup_data]),
+ do_read_schema_section(R3, verify_header(RawSchema), []).
+
+do_read_schema_section(R, {ok, B, C, []}, Acc) ->
+ case safe_apply(R, read, [R#restore.bup_data]) of
+ {R2, []} ->
+ {R2, {B, Acc, []}};
+ {R2, RawSchema} ->
+ do_read_schema_section(R2, {ok, B, C, RawSchema}, Acc)
+ end;
+
+do_read_schema_section(R, {ok, B, C, [Head | Tail]}, Acc)
+ when element(1, Head) == schema ->
+ do_read_schema_section(R, {ok, B, C, Tail}, Acc ++ [Head]);
+
+do_read_schema_section(R, {ok, B, _C, Rest}, Acc) ->
+ {R, {B, Acc, Rest}};
+
+do_read_schema_section(_R, {error, Reason}, _Acc) ->
+ {error, Reason}.
+
+verify_header([H | RawSchema]) when record(H, log_header) ->
+ Current = mnesia_log:backup_log_header(),
+ if
+ H#log_header.log_kind == Current#log_header.log_kind ->
+ Versions = ["0.1", "1.1", Current#log_header.log_version],
+ case lists:member(H#log_header.log_version, Versions) of
+ true ->
+ {ok, H, Current, RawSchema};
+ false ->
+ {error, {"Bad header version. Cannot be used as backup.", H}}
+ end;
+ true ->
+ {error, {"Bad kind of header. Cannot be used as backup.", H}}
+ end;
+verify_header(RawSchema) ->
+ {error, {"Missing header. Cannot be used as backup.", catch hd(RawSchema)}}.
+
+refresh_cookie(Schema, NewCookie) ->
+ case lists:keysearch(schema, 2, Schema) of
+ {value, {schema, schema, List}} ->
+ Cs = mnesia_schema:list2cs(List),
+ Cs2 = Cs#cstruct{cookie = NewCookie},
+ Item = {schema, schema, mnesia_schema:cs2list(Cs2)},
+ lists:keyreplace(schema, 2, Schema, Item);
+
+ false ->
+ Reason = "No schema found. Cannot be used as backup.",
+ throw({error, {Reason, Schema}})
+ end.
+
+%% Convert schema items from an external backup
+%% If backup format is the latest, no conversion is needed
+%% All supported backup formats should have their converters
+%% here as separate function clauses.
+convert_schema("0.1", Schema) ->
+ convert_0_1(Schema);
+convert_schema("1.1", Schema) ->
+ %% The new backup format is a pure extension of the old one
+ Current = mnesia_log:backup_log_header(),
+ convert_schema(Current#log_header.log_version, Schema);
+convert_schema(Latest, Schema) ->
+ H = mnesia_log:backup_log_header(),
+ if
+ H#log_header.log_version == Latest ->
+ Schema;
+ true ->
+ Reason = "Bad backup header version. Cannot convert schema.",
+ throw({error, {Reason, H}})
+ end.
+
+%% Backward compatibility for 0.1
+convert_0_1(Schema) ->
+ case lists:keysearch(schema, 2, Schema) of
+ {value, {schema, schema, List}} ->
+ Schema2 = lists:keydelete(schema, 2, Schema),
+ Cs = mnesia_schema:list2cs(List),
+ convert_0_1(Schema2, [], Cs);
+ false ->
+ List = mnesia_schema:get_initial_schema(disc_copies, [node()]),
+ Cs = mnesia_schema:list2cs(List),
+ convert_0_1(Schema, [], Cs)
+ end.
+
+convert_0_1([{schema, cookie, Cookie} | Schema], Acc, Cs) ->
+ convert_0_1(Schema, Acc, Cs#cstruct{cookie = Cookie});
+convert_0_1([{schema, db_nodes, DbNodes} | Schema], Acc, Cs) ->
+ convert_0_1(Schema, Acc, Cs#cstruct{disc_copies = DbNodes});
+convert_0_1([{schema, version, Version} | Schema], Acc, Cs) ->
+ convert_0_1(Schema, Acc, Cs#cstruct{version = Version});
+convert_0_1([{schema, Tab, Def} | Schema], Acc, Cs) ->
+ Head =
+ case lists:keysearch(index, 1, Def) of
+ {value, {index, PosList}} ->
+ %% Remove the snmp "index"
+ P = PosList -- [snmp],
+ Def2 = lists:keyreplace(index, 1, Def, {index, P}),
+ {schema, Tab, Def2};
+ false ->
+ {schema, Tab, Def}
+ end,
+ convert_0_1(Schema, [Head | Acc], Cs);
+convert_0_1([Head | Schema], Acc, Cs) ->
+ convert_0_1(Schema, [Head | Acc], Cs);
+convert_0_1([], Acc, Cs) ->
+ [schema2bup({schema, schema, Cs}) | Acc].
+
+%% Returns Val or throw error
+lookup_schema(Key, Schema) ->
+ case lists:keysearch(Key, 2, Schema) of
+ {value, {schema, Key, Val}} -> Val;
+ false -> throw({error, {"Cannot lookup", Key}})
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Backup compatibility
+
+%% Convert internal schema items to backup dito
+schema2bup({schema, Tab}) ->
+ {schema, Tab};
+schema2bup({schema, Tab, TableDef}) ->
+ {schema, Tab, mnesia_schema:cs2list(TableDef)}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Create schema on the given nodes
+%% Requires that old schemas has been deleted
+%% Returns ok | {error, Reason}
+create_schema([]) ->
+ create_schema([node()]);
+create_schema(Ns) when list(Ns) ->
+ case is_set(Ns) of
+ true ->
+ create_schema(Ns, mnesia_schema:ensure_no_schema(Ns));
+ false ->
+ {error, {combine_error, Ns}}
+ end;
+create_schema(Ns) ->
+ {error, {badarg, Ns}}.
+
+is_set(List) when list(List) ->
+ ordsets:is_set(lists:sort(List));
+is_set(_) ->
+ false.
+
+create_schema(Ns, ok) ->
+ %% Ensure that we access the intended Mnesia
+ %% directory. This function may not be called
+ %% during startup since it will cause the
+ %% application_controller to get into deadlock
+ case mnesia_lib:ensure_loaded(?APPLICATION) of
+ ok ->
+ case mnesia_monitor:get_env(schema_location) of
+ ram ->
+ {error, {has_no_disc, node()}};
+ _ ->
+ case mnesia_schema:opt_create_dir(true, mnesia_lib:dir()) of
+ {error, What} ->
+ {error, What};
+ ok ->
+ Mod = mnesia_backup,
+ Str = mk_str(),
+ File = mnesia_lib:dir(Str),
+ file:delete(File),
+ case catch make_initial_backup(Ns, File, Mod) of
+ {ok, _Res} ->
+ case do_install_fallback(File, Mod) of
+ ok ->
+ file:delete(File),
+ ok;
+ {error, Reason} ->
+ {error, Reason}
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end
+ end
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end;
+create_schema(_Ns, {error, Reason}) ->
+ {error, Reason};
+create_schema(_Ns, Reason) ->
+ {error, Reason}.
+
+mk_str() ->
+ Now = [integer_to_list(I) || I <- tuple_to_list(now())],
+ lists:concat([node()] ++ Now ++ ".TMP").
+
+make_initial_backup(Ns, Opaque, Mod) ->
+ Schema = [{schema, schema, mnesia_schema:get_initial_schema(disc_copies, Ns)}],
+ O2 = do_apply(Mod, open_write, [Opaque], Opaque),
+ O3 = do_apply(Mod, write, [O2, [mnesia_log:backup_log_header()]], O2),
+ O4 = do_apply(Mod, write, [O3, Schema], O3),
+ O5 = do_apply(Mod, commit_write, [O4], O4),
+ {ok, O5}.
+
+do_apply(_, write, [_, Items], Opaque) when Items == [] ->
+ Opaque;
+do_apply(Mod, What, Args, _Opaque) ->
+ case catch apply(Mod, What, Args) of
+ {ok, Opaque2} -> Opaque2;
+ {error, Reason} -> throw({error, Reason});
+ {'EXIT', Reason} -> throw({error, {'EXIT', Reason}})
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Restore
+
+%% Restore schema and possibly other tables from a backup
+%% and replicate them to the necessary nodes
+%% Requires that old schemas has been deleted
+%% Returns ok | {error, Reason}
+install_fallback(Opaque) ->
+ install_fallback(Opaque, []).
+
+install_fallback(Opaque, Args) ->
+ %% Ensure that we access the intended Mnesia
+ %% directory. This function may not be called
+ %% during startup since it will cause the
+ %% application_controller to get into deadlock
+ case mnesia_lib:ensure_loaded(?APPLICATION) of
+ ok ->
+ do_install_fallback(Opaque, Args);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+do_install_fallback(Opaque, Mod) when atom(Mod) ->
+ do_install_fallback(Opaque, [{module, Mod}]);
+do_install_fallback(Opaque, Args) when list(Args) ->
+ case check_fallback_args(Args, #fallback_args{opaque = Opaque}) of
+ {ok, FA} ->
+ do_install_fallback(FA);
+ {error, Reason} ->
+ {error, Reason}
+ end;
+do_install_fallback(_Opaque, Args) ->
+ {error, {badarg, Args}}.
+
+check_fallback_args([Arg | Tail], FA) ->
+ case catch check_fallback_arg_type(Arg, FA) of
+ {'EXIT', _Reason} ->
+ {error, {badarg, Arg}};
+ FA2 ->
+ check_fallback_args(Tail, FA2)
+ end;
+check_fallback_args([], FA) ->
+ {ok, FA}.
+
+check_fallback_arg_type(Arg, FA) ->
+ case Arg of
+ {scope, global} ->
+ FA#fallback_args{scope = global};
+ {scope, local} ->
+ FA#fallback_args{scope = local};
+ {module, Mod} ->
+ Mod2 = mnesia_monitor:do_check_type(backup_module, Mod),
+ FA#fallback_args{module = Mod2};
+ {mnesia_dir, Dir} ->
+ FA#fallback_args{mnesia_dir = Dir,
+ use_default_dir = false};
+ {keep_tables, Tabs} ->
+ atom_list(Tabs),
+ FA#fallback_args{keep_tables = Tabs};
+ {skip_tables, Tabs} ->
+ atom_list(Tabs),
+ FA#fallback_args{skip_tables = Tabs};
+ {default_op, keep_tables} ->
+ FA#fallback_args{default_op = keep_tables};
+ {default_op, skip_tables} ->
+ FA#fallback_args{default_op = skip_tables}
+ end.
+
+atom_list([H | T]) when atom(H) ->
+ atom_list(T);
+atom_list([]) ->
+ ok.
+
+do_install_fallback(FA) ->
+ Pid = spawn_link(?MODULE, install_fallback_master, [self(), FA]),
+ Res =
+ receive
+ {'EXIT', Pid, Reason} -> % if appl has trapped exit
+ {error, {'EXIT', Reason}};
+ {Pid, Res2} ->
+ case Res2 of
+ {ok, _} ->
+ ok;
+ {error, Reason} ->
+ {error, {"Cannot install fallback", Reason}}
+ end
+ end,
+ Res.
+
+install_fallback_master(ClientPid, FA) ->
+ process_flag(trap_exit, true),
+ State = {start, FA},
+ Opaque = FA#fallback_args.opaque,
+ Mod = FA#fallback_args.module,
+ Res = (catch iterate(Mod, fun restore_recs/4, Opaque, State)),
+ unlink(ClientPid),
+ ClientPid ! {self(), Res},
+ exit(shutdown).
+
+restore_recs(_, _, _, stop) ->
+ throw({error, "restore_recs already stopped"});
+
+restore_recs(Recs, Header, Schema, {start, FA}) ->
+ %% No records in backup
+ Schema2 = convert_schema(Header#log_header.log_version, Schema),
+ CreateList = lookup_schema(schema, Schema2),
+ case catch mnesia_schema:list2cs(CreateList) of
+ {'EXIT', Reason} ->
+ throw({error, {"Bad schema in restore_recs", Reason}});
+ Cs ->
+ Ns = get_fallback_nodes(FA, Cs#cstruct.disc_copies),
+ global:set_lock({{mnesia_table_lock, schema}, self()}, Ns, infinity),
+ Args = [self(), FA],
+ Pids = [spawn_link(N, ?MODULE, fallback_receiver, Args) || N <- Ns],
+ send_fallback(Pids, {start, Header, Schema2}),
+ Res = restore_recs(Recs, Header, Schema2, Pids),
+ global:del_lock({{mnesia_table_lock, schema}, self()}, Ns),
+ Res
+ end;
+
+restore_recs([], _Header, _Schema, Pids) ->
+ send_fallback(Pids, swap),
+ send_fallback(Pids, stop),
+ stop;
+
+restore_recs(Recs, _, _, Pids) ->
+ send_fallback(Pids, {records, Recs}),
+ Pids.
+
+get_fallback_nodes(FA, Ns) ->
+ This = node(),
+ case lists:member(This, Ns) of
+ true ->
+ case FA#fallback_args.scope of
+ global -> Ns;
+ local -> [This]
+ end;
+ false ->
+ throw({error, {"No disc resident schema on local node", Ns}})
+ end.
+
+send_fallback(Pids, Msg) when list(Pids), Pids /= [] ->
+ lists:foreach(fun(Pid) -> Pid ! {self(), Msg} end, Pids),
+ rec_answers(Pids, []).
+
+rec_answers([], Acc) ->
+ case {lists:keysearch(error, 1, Acc), mnesia_lib:uniq(Acc)} of
+ {{value, {error, Val}}, _} -> throw({error, Val});
+ {_, [SameAnswer]} -> SameAnswer;
+ {_, Other} -> throw({error, {"Different answers", Other}})
+ end;
+rec_answers(Pids, Acc) ->
+ receive
+ {'EXIT', Pid, stopped} ->
+ Pids2 = lists:delete(Pid, Pids),
+ rec_answers(Pids2, [stopped|Acc]);
+ {'EXIT', Pid, Reason} ->
+ Pids2 = lists:delete(Pid, Pids),
+ rec_answers(Pids2, [{error, {'EXIT', Pid, Reason}}|Acc]);
+ {Pid, Reply} ->
+ Pids2 = lists:delete(Pid, Pids),
+ rec_answers(Pids2, [Reply|Acc])
+ end.
+
+fallback_exists() ->
+ Fname = fallback_bup(),
+ fallback_exists(Fname).
+
+fallback_exists(Fname) ->
+ case mnesia_monitor:use_dir() of
+ true ->
+ mnesia_lib:exists(Fname);
+ false ->
+ case ?catch_val(active_fallback) of
+ {'EXIT', _} -> false;
+ Bool -> Bool
+ end
+ end.
+
+fallback_name() -> "FALLBACK.BUP".
+fallback_bup() -> mnesia_lib:dir(fallback_name()).
+
+fallback_tmp_name() -> "FALLBACK.TMP".
+%% fallback_full_tmp_name() -> mnesia_lib:dir(fallback_tmp_name()).
+
+fallback_receiver(Master, FA) ->
+ process_flag(trap_exit, true),
+
+ case catch register(mnesia_fallback, self()) of
+ {'EXIT', _} ->
+ Reason = {already_exists, node()},
+ local_fallback_error(Master, Reason);
+ true ->
+ FA2 = check_fallback_dir(Master, FA),
+ Bup = FA2#fallback_args.fallback_bup,
+ case mnesia_lib:exists(Bup) of
+ true ->
+ Reason2 = {already_exists, node()},
+ local_fallback_error(Master, Reason2);
+ false ->
+ Mod = mnesia_backup,
+ Tmp = FA2#fallback_args.fallback_tmp,
+ R = #restore{mode = replace,
+ bup_module = Mod,
+ bup_data = Tmp},
+ file:delete(Tmp),
+ case catch fallback_receiver_loop(Master, R, FA2, schema) of
+ {error, Reason} ->
+ local_fallback_error(Master, Reason);
+ Other ->
+ exit(Other)
+ end
+ end
+ end.
+
+local_fallback_error(Master, Reason) ->
+ Master ! {self(), {error, Reason}},
+ unlink(Master),
+ exit(Reason).
+
+check_fallback_dir(Master, FA) ->
+ case mnesia:system_info(schema_location) of
+ ram ->
+ Reason = {has_no_disc, node()},
+ local_fallback_error(Master, Reason);
+ _ ->
+ Dir = check_fallback_dir_arg(Master, FA),
+ Bup = filename:join([Dir, fallback_name()]),
+ Tmp = filename:join([Dir, fallback_tmp_name()]),
+ FA#fallback_args{fallback_bup = Bup,
+ fallback_tmp = Tmp,
+ mnesia_dir = Dir}
+ end.
+
+check_fallback_dir_arg(Master, FA) ->
+ case FA#fallback_args.use_default_dir of
+ true ->
+ mnesia_lib:dir();
+ false when FA#fallback_args.scope == local ->
+ Dir = FA#fallback_args.mnesia_dir,
+ case catch mnesia_monitor:do_check_type(dir, Dir) of
+ {'EXIT', _R} ->
+ Reason = {badarg, {dir, Dir}, node()},
+ local_fallback_error(Master, Reason);
+ AbsDir->
+ AbsDir
+ end;
+ false when FA#fallback_args.scope == global ->
+ Reason = {combine_error, global, dir, node()},
+ local_fallback_error(Master, Reason)
+ end.
+
+fallback_receiver_loop(Master, R, FA, State) ->
+ receive
+ {Master, {start, Header, Schema}} when State == schema ->
+ Dir = FA#fallback_args.mnesia_dir,
+ throw_bad_res(ok, mnesia_schema:opt_create_dir(true, Dir)),
+ R2 = safe_apply(R, open_write, [R#restore.bup_data]),
+ R3 = safe_apply(R2, write, [R2#restore.bup_data, [Header]]),
+ BupSchema = [schema2bup(S) || S <- Schema],
+ R4 = safe_apply(R3, write, [R3#restore.bup_data, BupSchema]),
+ Master ! {self(), ok},
+ fallback_receiver_loop(Master, R4, FA, records);
+
+ {Master, {records, Recs}} when State == records ->
+ R2 = safe_apply(R, write, [R#restore.bup_data, Recs]),
+ Master ! {self(), ok},
+ fallback_receiver_loop(Master, R2, FA, records);
+
+ {Master, swap} when State /= schema ->
+ ?eval_debug_fun({?MODULE, fallback_receiver_loop, pre_swap}, []),
+ safe_apply(R, commit_write, [R#restore.bup_data]),
+ Bup = FA#fallback_args.fallback_bup,
+ Tmp = FA#fallback_args.fallback_tmp,
+ throw_bad_res(ok, file:rename(Tmp, Bup)),
+ catch mnesia_lib:set(active_fallback, true),
+ ?eval_debug_fun({?MODULE, fallback_receiver_loop, post_swap}, []),
+ Master ! {self(), ok},
+ fallback_receiver_loop(Master, R, FA, stop);
+
+ {Master, stop} when State == stop ->
+ stopped;
+
+ Msg ->
+ safe_apply(R, abort_write, [R#restore.bup_data]),
+ Tmp = FA#fallback_args.fallback_tmp,
+ file:delete(Tmp),
+ throw({error, "Unexpected msg fallback_receiver_loop", Msg})
+ end.
+
+throw_bad_res(Expected, Expected) -> Expected;
+throw_bad_res(_Expected, {error, Actual}) -> throw({error, Actual});
+throw_bad_res(_Expected, Actual) -> throw({error, Actual}).
+
+-record(local_tab, {name, storage_type, dets_args, open, close, add, record_name}).
+
+tm_fallback_start(IgnoreFallback) ->
+ mnesia_schema:lock_schema(),
+ Res = do_fallback_start(fallback_exists(), IgnoreFallback),
+ mnesia_schema: unlock_schema(),
+ case Res of
+ ok -> ok;
+ {error, Reason} -> exit(Reason)
+ end.
+
+do_fallback_start(false, _IgnoreFallback) ->
+ ok;
+do_fallback_start(true, true) ->
+ verbose("Ignoring fallback at startup, but leaving it active...~n", []),
+ mnesia_lib:set(active_fallback, true),
+ ok;
+do_fallback_start(true, false) ->
+ verbose("Starting from fallback...~n", []),
+
+ Fname = fallback_bup(),
+ Mod = mnesia_backup,
+ Ets = ?ets_new_table(mnesia_local_tables, [set, public, {keypos, 2}]),
+ case catch iterate(Mod, fun restore_tables/4, Fname, {start, Ets}) of
+ {ok, Res} ->
+ case Res of
+ {local, _, LT} -> %% Close the last file
+ (LT#local_tab.close)(LT);
+ _ ->
+ ignore
+ end,
+ List = ?ets_match_object(Ets, '_'),
+ Tabs = [L#local_tab.name || L <- List, L#local_tab.name /= schema],
+ ?ets_delete_table(Ets),
+ mnesia_lib:swap_tmp_files(Tabs),
+ catch dets:close(schema),
+ Tmp = mnesia_lib:tab2tmp(schema),
+ Dat = mnesia_lib:tab2dat(schema),
+ case file:rename(Tmp, Dat) of
+ ok ->
+ file:delete(Fname),
+ ok;
+ {error, Reason} ->
+ file:delete(Tmp),
+ {error, {"Cannot start from fallback. Rename error.", Reason}}
+ end;
+ {error, Reason} ->
+ {error, {"Cannot start from fallback", Reason}};
+ {'EXIT', Reason} ->
+ {error, {"Cannot start from fallback", Reason}}
+ end.
+
+restore_tables(Recs, Header, Schema, {start, LocalTabs}) ->
+ Dir = mnesia_lib:dir(),
+ OldDir = filename:join([Dir, "OLD_DIR"]),
+ mnesia_schema:purge_dir(OldDir, []),
+ mnesia_schema:purge_dir(Dir, [fallback_name()]),
+ init_dat_files(Schema, LocalTabs),
+ State = {new, LocalTabs},
+ restore_tables(Recs, Header, Schema, State);
+restore_tables([Rec | Recs], Header, Schema, {new, LocalTabs}) ->
+ Tab = element(1, Rec),
+ case ?ets_lookup(LocalTabs, Tab) of
+ [] ->
+ State = {not_local, LocalTabs, Tab},
+ restore_tables(Recs, Header, Schema, State);
+ [L] when record(L, local_tab) ->
+ (L#local_tab.open)(Tab, L),
+ State = {local, LocalTabs, L},
+ restore_tables([Rec | Recs], Header, Schema, State)
+ end;
+restore_tables([Rec | Recs], Header, Schema, S = {not_local, LocalTabs, PrevTab}) ->
+ Tab = element(1, Rec),
+ if
+ Tab == PrevTab ->
+ restore_tables(Recs, Header, Schema, S);
+ true ->
+ State = {new, LocalTabs},
+ restore_tables([Rec | Recs], Header, Schema, State)
+ end;
+restore_tables([Rec | Recs], Header, Schema, State = {local, LocalTabs, L}) ->
+ Tab = element(1, Rec),
+ if
+ Tab == L#local_tab.name ->
+ Key = element(2, Rec),
+ (L#local_tab.add)(Tab, Key, Rec, L),
+ restore_tables(Recs, Header, Schema, State);
+ true ->
+ (L#local_tab.close)(L),
+ NState = {new, LocalTabs},
+ restore_tables([Rec | Recs], Header, Schema, NState)
+ end;
+restore_tables([], _Header, _Schema, State) ->
+ State.
+
+%% Creates all neccessary dat files and inserts
+%% the table definitions in the schema table
+%%
+%% Returns a list of local_tab tuples for all local tables
+init_dat_files(Schema, LocalTabs) ->
+ Fname = mnesia_lib:tab2tmp(schema),
+ Args = [{file, Fname}, {keypos, 2}, {type, set}],
+ case dets:open_file(schema, Args) of % Assume schema lock
+ {ok, _} ->
+ create_dat_files(Schema, LocalTabs),
+ dets:close(schema),
+ LocalTab = #local_tab{name = schema,
+ storage_type = disc_copies,
+ dets_args = Args,
+ open = fun open_media/2,
+ close = fun close_media/1,
+ add = fun add_to_media/4,
+ record_name = schema},
+ ?ets_insert(LocalTabs, LocalTab);
+ {error, Reason} ->
+ throw({error, {"Cannot open file", schema, Args, Reason}})
+ end.
+
+create_dat_files([{schema, schema, TabDef} | Tail], LocalTabs) ->
+ ok = dets:insert(schema, {schema, schema, TabDef}),
+ create_dat_files(Tail, LocalTabs);
+create_dat_files([{schema, Tab, TabDef} | Tail], LocalTabs) ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ ok = dets:insert(schema, {schema, Tab, TabDef}),
+ RecName = Cs#cstruct.record_name,
+ case mnesia_lib:cs_to_storage_type(node(), Cs) of
+ unknown ->
+ cleanup_dat_file(Tab),
+ create_dat_files(Tail, LocalTabs);
+ disc_only_copies ->
+ Fname = mnesia_lib:tab2tmp(Tab),
+ Args = [{file, Fname}, {keypos, 2},
+ {type, mnesia_lib:disk_type(Tab, Cs#cstruct.type)}],
+ case mnesia_lib:dets_sync_open(Tab, Args) of
+ {ok, _} ->
+ mnesia_lib:dets_sync_close(Tab),
+ LocalTab = #local_tab{name = Tab,
+ storage_type = disc_only_copies,
+ dets_args = Args,
+ open = fun open_media/2,
+ close = fun close_media/1,
+ add = fun add_to_media/4,
+ record_name = RecName},
+ ?ets_insert(LocalTabs, LocalTab),
+ create_dat_files(Tail, LocalTabs);
+ {error, Reason} ->
+ throw({error, {"Cannot open file", Tab, Args, Reason}})
+ end;
+ ram_copies ->
+ %% Create .DCD if needed in open_media in case any ram_copies
+ %% are backed up.
+ LocalTab = #local_tab{name = Tab,
+ storage_type = ram_copies,
+ dets_args = ignore,
+ open = fun open_media/2,
+ close = fun close_media/1,
+ add = fun add_to_media/4,
+ record_name = RecName},
+ ?ets_insert(LocalTabs, LocalTab),
+ create_dat_files(Tail, LocalTabs);
+ Storage ->
+ %% Create DCD
+ Fname = mnesia_lib:tab2dcd(Tab),
+ file:delete(Fname),
+ Log = mnesia_log:open_log(fallback_tab, mnesia_log:dcd_log_header(),
+ Fname, false),
+ LocalTab = #local_tab{name = Tab,
+ storage_type = Storage,
+ dets_args = ignore,
+ open = fun open_media/2,
+ close = fun close_media/1,
+ add = fun add_to_media/4,
+ record_name = RecName},
+ mnesia_log:close_log(Log),
+ ?ets_insert(LocalTabs, LocalTab),
+ create_dat_files(Tail, LocalTabs)
+ end;
+create_dat_files([{schema, Tab} | Tail], LocalTabs) ->
+ cleanup_dat_file(Tab),
+ create_dat_files(Tail, LocalTabs);
+create_dat_files([], _LocalTabs) ->
+ ok.
+
+cleanup_dat_file(Tab) ->
+ ok = dets:delete(schema, {schema, Tab}),
+ mnesia_lib:cleanup_tmp_files([Tab]).
+
+open_media(Tab, LT) ->
+ case LT#local_tab.storage_type of
+ disc_only_copies ->
+ Args = LT#local_tab.dets_args,
+ case mnesia_lib:dets_sync_open(Tab, Args) of
+ {ok, _} -> ok;
+ {error, Reason} ->
+ throw({error, {"Cannot open file", Tab, Args, Reason}})
+ end;
+ ram_copies ->
+ %% Create .DCD as ram_copies backed up.
+ FnameDCD = mnesia_lib:tab2dcd(Tab),
+ file:delete(FnameDCD),
+ Log = mnesia_log:open_log(fallback_tab,
+ mnesia_log:dcd_log_header(),
+ FnameDCD, false),
+ mnesia_log:close_log(Log),
+
+ %% Create .DCL
+ Fname = mnesia_lib:tab2dcl(Tab),
+ file:delete(Fname),
+ mnesia_log:open_log({?MODULE,Tab},
+ mnesia_log:dcl_log_header(),
+ Fname, false, false,
+ read_write);
+ _ ->
+ Fname = mnesia_lib:tab2dcl(Tab),
+ file:delete(Fname),
+ mnesia_log:open_log({?MODULE,Tab},
+ mnesia_log:dcl_log_header(),
+ Fname, false, false,
+ read_write)
+ end.
+close_media(L) ->
+ Tab = L#local_tab.name,
+ case L#local_tab.storage_type of
+ disc_only_copies ->
+ mnesia_lib:dets_sync_close(Tab);
+ _ ->
+ mnesia_log:close_log({?MODULE,Tab})
+ end.
+
+add_to_media(Tab, Key, Rec, L) ->
+ RecName = L#local_tab.record_name,
+ case L#local_tab.storage_type of
+ disc_only_copies ->
+ case Rec of
+ {Tab, Key} ->
+ ok = dets:delete(Tab, Key);
+ (Rec) when Tab == RecName ->
+ ok = dets:insert(Tab, Rec);
+ (Rec) ->
+ Rec2 = setelement(1, Rec, RecName),
+ ok = dets:insert(Tab, Rec2)
+ end;
+ _ ->
+ Log = {?MODULE, Tab},
+ case Rec of
+ {Tab, Key} ->
+ mnesia_log:append(Log, {{Tab, Key}, {Tab, Key}, delete});
+ (Rec) when Tab == RecName ->
+ mnesia_log:append(Log, {{Tab, Key}, Rec, write});
+ (Rec) ->
+ Rec2 = setelement(1, Rec, RecName),
+ mnesia_log:append(Log, {{Tab, Key}, Rec2, write})
+ end
+ end.
+
+uninstall_fallback() ->
+ uninstall_fallback([{scope, global}]).
+
+uninstall_fallback(Args) ->
+ case check_fallback_args(Args, #fallback_args{}) of
+ {ok, FA} ->
+ do_uninstall_fallback(FA);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+do_uninstall_fallback(FA) ->
+ %% Ensure that we access the intended Mnesia
+ %% directory. This function may not be called
+ %% during startup since it will cause the
+ %% application_controller to get into deadlock
+ case mnesia_lib:ensure_loaded(?APPLICATION) of
+ ok ->
+ Pid = spawn_link(?MODULE, uninstall_fallback_master, [self(), FA]),
+ receive
+ {'EXIT', Pid, Reason} -> % if appl has trapped exit
+ {error, {'EXIT', Reason}};
+ {Pid, Res} ->
+ Res
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+uninstall_fallback_master(ClientPid, FA) ->
+ process_flag(trap_exit, true),
+
+ FA2 = check_fallback_dir(ClientPid, FA), % May exit
+ Bup = FA2#fallback_args.fallback_bup,
+ case fallback_to_schema(Bup) of
+ {ok, fallback, List} ->
+ Cs = mnesia_schema:list2cs(List),
+ case catch get_fallback_nodes(FA, Cs#cstruct.disc_copies) of
+ Ns when list(Ns) ->
+ do_uninstall(ClientPid, Ns, FA);
+ {error, Reason} ->
+ local_fallback_error(ClientPid, Reason)
+ end;
+ {error, Reason} ->
+ local_fallback_error(ClientPid, Reason)
+ end.
+
+do_uninstall(ClientPid, Ns, FA) ->
+ Args = [self(), FA],
+ global:set_lock({{mnesia_table_lock, schema}, self()}, Ns, infinity),
+ Pids = [spawn_link(N, ?MODULE, local_uninstall_fallback, Args) || N <- Ns],
+ Res = do_uninstall(ClientPid, Pids, [], [], ok),
+ global:del_lock({{mnesia_table_lock, schema}, self()}, Ns),
+ ClientPid ! {self(), Res},
+ unlink(ClientPid),
+ exit(shutdown).
+
+do_uninstall(ClientPid, [Pid | Pids], GoodPids, BadNodes, Res) ->
+ receive
+ %% {'EXIT', ClientPid, _} ->
+ %% client_exit;
+ {'EXIT', Pid, Reason} ->
+ BadNode = node(Pid),
+ BadRes = {error, {"Uninstall fallback", BadNode, Reason}},
+ do_uninstall(ClientPid, Pids, GoodPids, [BadNode | BadNodes], BadRes);
+ {Pid, {error, Reason}} ->
+ BadNode = node(Pid),
+ BadRes = {error, {"Uninstall fallback", BadNode, Reason}},
+ do_uninstall(ClientPid, Pids, GoodPids, [BadNode | BadNodes], BadRes);
+ {Pid, started} ->
+ do_uninstall(ClientPid, Pids, [Pid | GoodPids], BadNodes, Res)
+ end;
+do_uninstall(ClientPid, [], GoodPids, [], ok) ->
+ lists:foreach(fun(Pid) -> Pid ! {self(), do_uninstall} end, GoodPids),
+ rec_uninstall(ClientPid, GoodPids, ok);
+do_uninstall(_ClientPid, [], GoodPids, BadNodes, BadRes) ->
+ lists:foreach(fun(Pid) -> exit(Pid, shutdown) end, GoodPids),
+ {error, {node_not_running, BadNodes, BadRes}}.
+
+local_uninstall_fallback(Master, FA) ->
+ %% Don't trap exit
+
+ register(mnesia_fallback, self()), % May exit
+ FA2 = check_fallback_dir(Master, FA), % May exit
+ Master ! {self(), started},
+
+ receive
+ {Master, do_uninstall} ->
+ ?eval_debug_fun({?MODULE, uninstall_fallback2, pre_delete}, []),
+ catch mnesia_lib:set(active_fallback, false),
+ Tmp = FA2#fallback_args.fallback_tmp,
+ Bup = FA2#fallback_args.fallback_bup,
+ file:delete(Tmp),
+ Res =
+ case fallback_exists(Bup) of
+ true -> file:delete(Bup);
+ false -> ok
+ end,
+ ?eval_debug_fun({?MODULE, uninstall_fallback2, post_delete}, []),
+ Master ! {self(), Res},
+ unlink(Master),
+ exit(normal)
+ end.
+
+rec_uninstall(ClientPid, [Pid | Pids], AccRes) ->
+ receive
+ %% {'EXIT', ClientPid, _} ->
+ %% exit(shutdown);
+ {'EXIT', Pid, R} ->
+ Reason = {node_not_running, {node(Pid), R}},
+ rec_uninstall(ClientPid, Pids, {error, Reason});
+ {Pid, ok} ->
+ rec_uninstall(ClientPid, Pids, AccRes);
+ {Pid, BadRes} ->
+ rec_uninstall(ClientPid, Pids, BadRes)
+ end;
+rec_uninstall(ClientPid, [], Res) ->
+ ClientPid ! {self(), Res},
+ unlink(ClientPid),
+ exit(normal).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Backup traversal
+
+%% Iterate over a backup and produce a new backup.
+%% Fun(BackupItem, Acc) is applied for each BackupItem.
+%%
+%% Valid BackupItems are:
+%%
+%% {schema, Tab} Table to be deleted
+%% {schema, Tab, CreateList} Table to be created, CreateList may be empty
+%% {schema, db_nodes, DbNodes}List of nodes, defaults to [node()] OLD
+%% {schema, version, Version} Schema version OLD
+%% {schema, cookie, Cookie} Unique schema cookie OLD
+%% {Tab, Key} Oid for record to be deleted
+%% Record Record to be inserted.
+%%
+%% The Fun must return a tuple {BackupItems, NewAcc}
+%% where BackupItems is a list of valid BackupItems and
+%% NewAcc is a new accumulator value. Once BackupItems
+%% that not are schema related has been returned, no more schema
+%% items may be returned. The schema related items must always be
+%% first in the backup.
+%%
+%% If TargetMod == read_only, no new backup will be created.
+%%
+%% Opening of the source media will be performed by
+%% to SourceMod:open_read(Source)
+%%
+%% Opening of the target media will be performed by
+%% to TargetMod:open_write(Target)
+traverse_backup(Source, Target, Fun, Acc) ->
+ Mod = mnesia_monitor:get_env(backup_module),
+ traverse_backup(Source, Mod, Target, Mod, Fun, Acc).
+
+traverse_backup(Source, SourceMod, Target, TargetMod, Fun, Acc) ->
+ Args = [self(), Source, SourceMod, Target, TargetMod, Fun, Acc],
+ Pid = spawn_link(?MODULE, do_traverse_backup, Args),
+ receive
+ {'EXIT', Pid, Reason} ->
+ {error, {"Backup traversal crashed", Reason}};
+ {iter_done, Pid, Res} ->
+ Res
+ end.
+
+do_traverse_backup(ClientPid, Source, SourceMod, Target, TargetMod, Fun, Acc) ->
+ process_flag(trap_exit, true),
+ Iter =
+ if
+ TargetMod /= read_only ->
+ case catch do_apply(TargetMod, open_write, [Target], Target) of
+ {error, Error} ->
+ unlink(ClientPid),
+ ClientPid ! {iter_done, self(), {error, Error}},
+ exit(Error);
+ Else -> Else
+ end;
+ true ->
+ ignore
+ end,
+ A = {start, Fun, Acc, TargetMod, Iter},
+ Res =
+ case iterate(SourceMod, fun trav_apply/4, Source, A) of
+ {ok, {iter, _, Acc2, _, Iter2}} when TargetMod /= read_only ->
+ case catch do_apply(TargetMod, commit_write, [Iter2], Iter2) of
+ {error, Reason} ->
+ {error, Reason};
+ _ ->
+ {ok, Acc2}
+ end;
+ {ok, {iter, _, Acc2, _, _}} ->
+ {ok, Acc2};
+ {error, Reason} when TargetMod /= read_only->
+ catch do_apply(TargetMod, abort_write, [Iter], Iter),
+ {error, {"Backup traversal failed", Reason}};
+ {error, Reason} ->
+ {error, {"Backup traversal failed", Reason}}
+ end,
+ unlink(ClientPid),
+ ClientPid ! {iter_done, self(), Res}.
+
+trav_apply(Recs, _Header, _Schema, {iter, Fun, Acc, Mod, Iter}) ->
+ {NewRecs, Acc2} = filter_foldl(Fun, Acc, Recs),
+ if
+ Mod /= read_only, NewRecs /= [] ->
+ Iter2 = do_apply(Mod, write, [Iter, NewRecs], Iter),
+ {iter, Fun, Acc2, Mod, Iter2};
+ true ->
+ {iter, Fun, Acc2, Mod, Iter}
+ end;
+trav_apply(Recs, Header, Schema, {start, Fun, Acc, Mod, Iter}) ->
+ Iter2 =
+ if
+ Mod /= read_only ->
+ do_apply(Mod, write, [Iter, [Header]], Iter);
+ true ->
+ Iter
+ end,
+ TravAcc = trav_apply(Schema, Header, Schema, {iter, Fun, Acc, Mod, Iter2}),
+ trav_apply(Recs, Header, Schema, TravAcc).
+
+filter_foldl(Fun, Acc, [Head|Tail]) ->
+ case Fun(Head, Acc) of
+ {HeadItems, HeadAcc} when list(HeadItems) ->
+ {TailItems, TailAcc} = filter_foldl(Fun, HeadAcc, Tail),
+ {HeadItems ++ TailItems, TailAcc};
+ Other ->
+ throw({error, {"Fun must return a list", Other}})
+ end;
+filter_foldl(_Fun, Acc, []) ->
+ {[], Acc}.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_checkpoint.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_checkpoint.erl
new file mode 100644
index 0000000000..60a7a29861
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_checkpoint.erl
@@ -0,0 +1,1283 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_checkpoint.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
+%%
+-module(mnesia_checkpoint).
+
+%% TM callback interface
+-export([
+ tm_add_copy/2,
+ tm_change_table_copy_type/3,
+ tm_del_copy/2,
+ tm_mnesia_down/1,
+ tm_prepare/1,
+ tm_retain/4,
+ tm_retain/5,
+ tm_enter_pending/1,
+ tm_enter_pending/3,
+ tm_exit_pending/1,
+ convert_cp_record/1
+ ]).
+
+%% Public interface
+-export([
+ activate/1,
+ checkpoints/0,
+ deactivate/1,
+ deactivate/2,
+ iterate/6,
+ most_local_node/2,
+ really_retain/2,
+ stop/0,
+ stop_iteration/1,
+ tables_and_cookie/1
+ ]).
+
+%% Internal
+-export([
+ call/2,
+ cast/2,
+ init/1,
+ remote_deactivate/1,
+ start/1
+ ]).
+
+%% sys callback interface
+-export([
+ system_code_change/4,
+ system_continue/3,
+ system_terminate/4
+ ]).
+
+-include("mnesia.hrl").
+-import(mnesia_lib, [add/2, del/2, set/2, unset/1]).
+-import(mnesia_lib, [dbg_out/2]).
+
+-record(tm, {log, pending, transactions, checkpoints}).
+
+-record(checkpoint_args, {name = {now(), node()},
+ allow_remote = true,
+ ram_overrides_dump = false,
+ nodes = [],
+ node = node(),
+ now = now(),
+ cookie = ?unique_cookie,
+ min = [],
+ max = [],
+ pending_tab,
+ wait_for_old, % Initially undefined then List
+ is_activated = false,
+ ignore_new = [],
+ retainers = [],
+ iterators = [],
+ supervisor,
+ pid
+ }).
+
+%% Old record definition
+-record(checkpoint, {name,
+ allow_remote,
+ ram_overrides_dump,
+ nodes,
+ node,
+ now,
+ min,
+ max,
+ pending_tab,
+ wait_for_old,
+ is_activated,
+ ignore_new,
+ retainers,
+ iterators,
+ supervisor,
+ pid
+ }).
+
+-record(retainer, {cp_name, tab_name, store, writers = [], really_retain = true}).
+
+-record(iter, {tab_name, oid_tab, main_tab, retainer_tab, source, val, pid}).
+
+-record(pending, {tid, disc_nodes = [], ram_nodes = []}).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% TM callback functions
+
+stop() ->
+ lists:foreach(fun(Name) -> call(Name, stop) end,
+ checkpoints()),
+ ok.
+
+tm_prepare(Cp) when record(Cp, checkpoint_args) ->
+ Name = Cp#checkpoint_args.name,
+ case lists:member(Name, checkpoints()) of
+ false ->
+ start_retainer(Cp);
+ true ->
+ {error, {already_exists, Name, node()}}
+ end;
+tm_prepare(Cp) when record(Cp, checkpoint) ->
+ %% Node with old protocol sent an old checkpoint record
+ %% and we have to convert it
+ case convert_cp_record(Cp) of
+ {ok, NewCp} ->
+ tm_prepare(NewCp);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+tm_mnesia_down(Node) ->
+ lists:foreach(fun(Name) -> cast(Name, {mnesia_down, Node}) end,
+ checkpoints()).
+
+%% Returns pending
+tm_enter_pending(Tid, DiscNs, RamNs) ->
+ Pending = #pending{tid = Tid, disc_nodes = DiscNs, ram_nodes = RamNs},
+ tm_enter_pending(Pending).
+
+tm_enter_pending(Pending) ->
+ PendingTabs = val(pending_checkpoints),
+ tm_enter_pending(PendingTabs, Pending).
+
+tm_enter_pending([], Pending) ->
+ Pending;
+tm_enter_pending([Tab | Tabs], Pending) ->
+ catch ?ets_insert(Tab, Pending),
+ tm_enter_pending(Tabs, Pending).
+
+tm_exit_pending(Tid) ->
+ Pids = val(pending_checkpoint_pids),
+ tm_exit_pending(Pids, Tid).
+
+tm_exit_pending([], Tid) ->
+ Tid;
+tm_exit_pending([Pid | Pids], Tid) ->
+ Pid ! {self(), {exit_pending, Tid}},
+ tm_exit_pending(Pids, Tid).
+
+enter_still_pending([Tid | Tids], Tab) ->
+ ?ets_insert(Tab, #pending{tid = Tid}),
+ enter_still_pending(Tids, Tab);
+enter_still_pending([], _Tab) ->
+ ok.
+
+
+%% Looks up checkpoints for functions in mnesia_tm.
+tm_retain(Tid, Tab, Key, Op) ->
+ case val({Tab, commit_work}) of
+ [{checkpoints, Checkpoints} | _ ] ->
+ tm_retain(Tid, Tab, Key, Op, Checkpoints);
+ _ ->
+ undefined
+ end.
+
+tm_retain(Tid, Tab, Key, Op, Checkpoints) ->
+ case Op of
+ clear_table ->
+ OldRecs = mnesia_lib:db_match_object(Tab, '_'),
+ send_group_retain(OldRecs, Checkpoints, Tid, Tab, []),
+ OldRecs;
+ _ ->
+ OldRecs = mnesia_lib:db_get(Tab, Key),
+ send_retain(Checkpoints, {retain, Tid, Tab, Key, OldRecs}),
+ OldRecs
+ end.
+
+send_group_retain([Rec | Recs], Checkpoints, Tid, Tab, [PrevRec | PrevRecs])
+ when element(2, Rec) /= element(2, PrevRec) ->
+ Key = element(2, PrevRec),
+ OldRecs = lists:reverse([PrevRec | PrevRecs]),
+ send_retain(Checkpoints, {retain, Tid, Tab, Key, OldRecs}),
+ send_group_retain(Recs, Checkpoints, Tid, Tab, [Rec]);
+send_group_retain([Rec | Recs], Checkpoints, Tid, Tab, Acc) ->
+ send_group_retain(Recs, Checkpoints, Tid, Tab, [Rec | Acc]);
+send_group_retain([], Checkpoints, Tid, Tab, [PrevRec | PrevRecs]) ->
+ Key = element(2, PrevRec),
+ OldRecs = lists:reverse([PrevRec | PrevRecs]),
+ send_retain(Checkpoints, {retain, Tid, Tab, Key, OldRecs}),
+ ok;
+send_group_retain([], _Checkpoints, _Tid, _Tab, []) ->
+ ok.
+
+send_retain([Name | Names], Msg) ->
+ cast(Name, Msg),
+ send_retain(Names, Msg);
+send_retain([], _Msg) ->
+ ok.
+
+tm_add_copy(Tab, Node) when Node /= node() ->
+ case val({Tab, commit_work}) of
+ [{checkpoints, Checkpoints} | _ ] ->
+ Fun = fun(Name) -> call(Name, {add_copy, Tab, Node}) end,
+ map_call(Fun, Checkpoints, ok);
+ _ ->
+ ok
+ end.
+
+tm_del_copy(Tab, Node) when Node == node() ->
+ mnesia_subscr:unsubscribe_table(Tab),
+ case val({Tab, commit_work}) of
+ [{checkpoints, Checkpoints} | _ ] ->
+ Fun = fun(Name) -> call(Name, {del_copy, Tab, Node}) end,
+ map_call(Fun, Checkpoints, ok);
+ _ ->
+ ok
+ end.
+
+tm_change_table_copy_type(Tab, From, To) ->
+ case val({Tab, commit_work}) of
+ [{checkpoints, Checkpoints} | _ ] ->
+ Fun = fun(Name) -> call(Name, {change_copy, Tab, From, To}) end,
+ map_call(Fun, Checkpoints, ok);
+ _ ->
+ ok
+ end.
+
+map_call(Fun, [Name | Names], Res) ->
+ case Fun(Name) of
+ ok ->
+ map_call(Fun, Names, Res);
+ {error, {no_exists, Name}} ->
+ map_call(Fun, Names, Res);
+ {error, Reason} ->
+ %% BUGBUG: We may end up with some checkpoint retainers
+ %% too much in the add_copy case. How do we remove them?
+ map_call(Fun, Names, {error, Reason})
+ end;
+map_call(_Fun, [], Res) ->
+ Res.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Public functions
+
+deactivate(Name) ->
+ case call(Name, get_checkpoint) of
+ {error, Reason} ->
+ {error, Reason};
+ Cp ->
+ deactivate(Cp#checkpoint_args.nodes, Name)
+ end.
+
+deactivate(Nodes, Name) ->
+ rpc:multicall(Nodes, ?MODULE, remote_deactivate, [Name]),
+ ok.
+
+remote_deactivate(Name) ->
+ call(Name, deactivate).
+
+checkpoints() -> val(checkpoints).
+
+tables_and_cookie(Name) ->
+ case call(Name, get_checkpoint) of
+ {error, Reason} ->
+ {error, Reason};
+ Cp ->
+ Tabs = Cp#checkpoint_args.min ++ Cp#checkpoint_args.max,
+ Cookie = Cp#checkpoint_args.cookie,
+ {ok, Tabs, Cookie}
+ end.
+
+most_local_node(Name, Tab) ->
+ case ?catch_val({Tab, {retainer, Name}}) of
+ {'EXIT', _} ->
+ {error, {"No retainer attached to table", [Tab, Name]}};
+ R ->
+ Writers = R#retainer.writers,
+ LocalWriter = lists:member(node(), Writers),
+ if
+ LocalWriter == true ->
+ {ok, node()};
+ Writers /= [] ->
+ {ok, hd(Writers)};
+ true ->
+ {error, {"No retainer attached to table", [Tab, Name]}}
+ end
+ end.
+
+really_retain(Name, Tab) ->
+ R = val({Tab, {retainer, Name}}),
+ R#retainer.really_retain.
+
+%% Activate a checkpoint.
+%%
+%% A checkpoint is a transaction consistent state that may be used to
+%% perform a distributed backup or to rollback the involved tables to
+%% their old state. Backups may also be used to restore tables to
+%% their old state. Args is a list of the following tuples:
+%%
+%% {name, Name}
+%% Name of checkpoint. Each checkpoint must have a name which
+%% is unique on the reachable nodes. The name may be reused when
+%% the checkpoint has been deactivated.
+%% By default a probably unique name is generated.
+%% Multiple checkpoints may be set on the same table.
+%%
+%% {allow_remote, Bool}
+%% false means that all retainers must be local. If the
+%% table does not reside locally, the checkpoint fails.
+%% true allows retainers on other nodes.
+%%
+%% {min, MinTabs}
+%% Minimize redundancy and only keep checkpoint info together with
+%% one replica, preferrably at the local node. If any node involved
+%% the checkpoint goes down, the checkpoint is deactivated.
+%%
+%% {max, MaxTabs}
+%% Maximize redundancy and keep checkpoint info together with all
+%% replicas. The checkpoint becomes more fault tolerant if the
+%% tables has several replicas. When new replicas are added, they
+%% will also get a retainer attached to them.
+%%
+%% {ram_overrides_dump, Bool}
+%% {ram_overrides_dump, Tabs}
+%% Only applicable for ram_copies. Bool controls which versions of
+%% the records that should be included in the checkpoint state.
+%% true means that the latest comitted records in ram (i.e. the
+%% records that the application accesses) should be included
+%% in the checkpoint. false means that the records dumped to
+%% dat-files (the records that will be loaded at startup) should
+%% be included in the checkpoint. Tabs is a list of tables.
+%% Default is false.
+%%
+%% {ignore_new, TidList}
+%% Normally we wait for all pending transactions to complete
+%% before we allow iteration over the checkpoint. But in order
+%% to cope with checkpoint activation inside a transaction that
+%% currently prepares commit (mnesia_init:get_net_work_copy) we
+%% need to have the ability to ignore the enclosing transaction.
+%% We do not wait for the transactions in TidList to end. The
+%% transactions in TidList are regarded as newer than the checkpoint.
+
+activate(Args) ->
+ case args2cp(Args) of
+ {ok, Cp} ->
+ do_activate(Cp);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+args2cp(Args) when list(Args)->
+ case catch lists:foldl(fun check_arg/2, #checkpoint_args{}, Args) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Cp ->
+ case check_tables(Cp) of
+ {error, Reason} ->
+ {error, Reason};
+ {ok, Overriders, AllTabs} ->
+ arrange_retainers(Cp, Overriders, AllTabs)
+ end
+ end;
+args2cp(Args) ->
+ {error, {badarg, Args}}.
+
+check_arg({name, Name}, Cp) ->
+ case lists:member(Name, checkpoints()) of
+ true ->
+ exit({already_exists, Name});
+ false ->
+ case catch tab2retainer({foo, Name}) of
+ List when list(List) ->
+ Cp#checkpoint_args{name = Name};
+ _ ->
+ exit({badarg, Name})
+ end
+ end;
+check_arg({allow_remote, true}, Cp) ->
+ Cp#checkpoint_args{allow_remote = true};
+check_arg({allow_remote, false}, Cp) ->
+ Cp#checkpoint_args{allow_remote = false};
+check_arg({ram_overrides_dump, true}, Cp) ->
+ Cp#checkpoint_args{ram_overrides_dump = true};
+check_arg({ram_overrides_dump, false}, Cp) ->
+ Cp#checkpoint_args{ram_overrides_dump = false};
+check_arg({ram_overrides_dump, Tabs}, Cp) when list(Tabs) ->
+ Cp#checkpoint_args{ram_overrides_dump = Tabs};
+check_arg({min, Tabs}, Cp) when list(Tabs) ->
+ Cp#checkpoint_args{min = Tabs};
+check_arg({max, Tabs}, Cp) when list(Tabs) ->
+ Cp#checkpoint_args{max = Tabs};
+check_arg({ignore_new, Tids}, Cp) when list(Tids) ->
+ Cp#checkpoint_args{ignore_new = Tids};
+check_arg(Arg, _) ->
+ exit({badarg, Arg}).
+
+check_tables(Cp) ->
+ Min = Cp#checkpoint_args.min,
+ Max = Cp#checkpoint_args.max,
+ AllTabs = Min ++ Max,
+ DoubleTabs = [T || T <- Min, lists:member(T, Max)],
+ Overriders = Cp#checkpoint_args.ram_overrides_dump,
+ if
+ DoubleTabs /= [] ->
+ {error, {combine_error, Cp#checkpoint_args.name,
+ [{min, DoubleTabs}, {max, DoubleTabs}]}};
+ Min == [], Max == [] ->
+ {error, {combine_error, Cp#checkpoint_args.name,
+ [{min, Min}, {max, Max}]}};
+ Overriders == false ->
+ {ok, [], AllTabs};
+ Overriders == true ->
+ {ok, AllTabs, AllTabs};
+ list(Overriders) ->
+ case [T || T <- Overriders, not lists:member(T, Min)] of
+ [] ->
+ case [T || T <- Overriders, not lists:member(T, Max)] of
+ [] ->
+ {ok, Overriders, AllTabs};
+ Outsiders ->
+ {error, {combine_error, Cp#checkpoint_args.name,
+ [{ram_overrides_dump, Outsiders},
+ {max, Outsiders}]}}
+ end;
+ Outsiders ->
+ {error, {combine_error, Cp#checkpoint_args.name,
+ [{ram_overrides_dump, Outsiders},
+ {min, Outsiders}]}}
+ end
+ end.
+
+arrange_retainers(Cp, Overriders, AllTabs) ->
+ R = #retainer{cp_name = Cp#checkpoint_args.name},
+ case catch [R#retainer{tab_name = Tab,
+ writers = select_writers(Cp, Tab)}
+ || Tab <- AllTabs] of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ Retainers ->
+ {ok, Cp#checkpoint_args{ram_overrides_dump = Overriders,
+ retainers = Retainers,
+ nodes = writers(Retainers)}}
+ end.
+
+select_writers(Cp, Tab) ->
+ case filter_remote(Cp, val({Tab, active_replicas})) of
+ [] ->
+ exit({"Cannot prepare checkpoint (replica not available)",
+ [Tab, Cp#checkpoint_args.name]});
+ Writers ->
+ This = node(),
+ case {lists:member(Tab, Cp#checkpoint_args.max),
+ lists:member(This, Writers)} of
+ {true, _} -> Writers; % Max
+ {false, true} -> [This];
+ {false, false} -> [hd(Writers)]
+ end
+ end.
+
+filter_remote(Cp, Writers) when Cp#checkpoint_args.allow_remote == true ->
+ Writers;
+filter_remote(_Cp, Writers) ->
+ This = node(),
+ case lists:member(This, Writers) of
+ true -> [This];
+ false -> []
+ end.
+
+writers(Retainers) ->
+ Fun = fun(R, Acc) -> R#retainer.writers ++ Acc end,
+ Writers = lists:foldl(Fun, [], Retainers),
+ mnesia_lib:uniq(Writers).
+
+do_activate(Cp) ->
+ Name = Cp#checkpoint_args.name,
+ Nodes = Cp#checkpoint_args.nodes,
+ case mnesia_tm:prepare_checkpoint(Nodes, Cp) of
+ {Replies, []} ->
+ check_prep(Replies, Name, Nodes, Cp#checkpoint_args.ignore_new);
+ {_, BadNodes} ->
+ {error, {"Cannot prepare checkpoint (bad nodes)",
+ [Name, BadNodes]}}
+ end.
+
+check_prep([{ok, Name, IgnoreNew, _Node} | Replies], Name, Nodes, IgnoreNew) ->
+ check_prep(Replies, Name, Nodes, IgnoreNew);
+check_prep([{error, Reason} | _Replies], Name, _Nodes, _IgnoreNew) ->
+ {error, {"Cannot prepare checkpoint (bad reply)",
+ [Name, Reason]}};
+check_prep([{badrpc, Reason} | _Replies], Name, _Nodes, _IgnoreNew) ->
+ {error, {"Cannot prepare checkpoint (badrpc)",
+ [Name, Reason]}};
+check_prep([], Name, Nodes, IgnoreNew) ->
+ collect_pending(Name, Nodes, IgnoreNew).
+
+collect_pending(Name, Nodes, IgnoreNew) ->
+ case rpc:multicall(Nodes, ?MODULE, call, [Name, collect_pending]) of
+ {Replies, []} ->
+ case catch ?ets_new_table(mnesia_union, [bag]) of
+ {'EXIT', Reason} -> %% system limit
+ Msg = "Cannot create an ets table pending union",
+ {error, {system_limit, Msg, Reason}};
+ UnionTab ->
+ compute_union(Replies, Nodes, Name, UnionTab, IgnoreNew)
+ end;
+ {_, BadNodes} ->
+ deactivate(Nodes, Name),
+ {error, {"Cannot collect from pending checkpoint", Name, BadNodes}}
+ end.
+
+compute_union([{ok, Pending} | Replies], Nodes, Name, UnionTab, IgnoreNew) ->
+ add_pending(Pending, UnionTab),
+ compute_union(Replies, Nodes, Name, UnionTab, IgnoreNew);
+compute_union([{error, Reason} | _Replies], Nodes, Name, UnionTab, _IgnoreNew) ->
+ deactivate(Nodes, Name),
+ ?ets_delete_table(UnionTab),
+ {error, Reason};
+compute_union([{badrpc, Reason} | _Replies], Nodes, Name, UnionTab, _IgnoreNew) ->
+ deactivate(Nodes, Name),
+ ?ets_delete_table(UnionTab),
+ {error, {badrpc, Reason}};
+compute_union([], Nodes, Name, UnionTab, IgnoreNew) ->
+ send_activate(Nodes, Nodes, Name, UnionTab, IgnoreNew).
+
+add_pending([P | Pending], UnionTab) ->
+ add_pending_node(P#pending.disc_nodes, P#pending.tid, UnionTab),
+ add_pending_node(P#pending.ram_nodes, P#pending.tid, UnionTab),
+ add_pending(Pending, UnionTab);
+add_pending([], _UnionTab) ->
+ ok.
+
+add_pending_node([Node | Nodes], Tid, UnionTab) ->
+ ?ets_insert(UnionTab, {Node, Tid}),
+ add_pending_node(Nodes, Tid, UnionTab);
+add_pending_node([], _Tid, _UnionTab) ->
+ ok.
+
+send_activate([Node | Nodes], AllNodes, Name, UnionTab, IgnoreNew) ->
+ Pending = [Tid || {_, Tid} <- ?ets_lookup(UnionTab, Node),
+ not lists:member(Tid, IgnoreNew)],
+ case rpc:call(Node, ?MODULE, call, [Name, {activate, Pending}]) of
+ activated ->
+ send_activate(Nodes, AllNodes, Name, UnionTab, IgnoreNew);
+ {badrpc, Reason} ->
+ deactivate(Nodes, Name),
+ ?ets_delete_table(UnionTab),
+ {error, {"Activation failed (bad node)", Name, Node, Reason}};
+ {error, Reason} ->
+ deactivate(Nodes, Name),
+ ?ets_delete_table(UnionTab),
+ {error, {"Activation failed", Name, Node, Reason}}
+ end;
+send_activate([], AllNodes, Name, UnionTab, _IgnoreNew) ->
+ ?ets_delete_table(UnionTab),
+ {ok, Name, AllNodes}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Checkpoint server
+
+cast(Name, Msg) ->
+ case ?catch_val({checkpoint, Name}) of
+ {'EXIT', _} ->
+ {error, {no_exists, Name}};
+
+ Pid when pid(Pid) ->
+ Pid ! {self(), Msg},
+ {ok, Pid}
+ end.
+
+call(Name, Msg) ->
+ case cast(Name, Msg) of
+ {ok, Pid} ->
+ catch link(Pid), % Always local
+ Self = self(),
+ receive
+ {'EXIT', Pid, Reason} ->
+ {error, {"Got exit", [Name, Reason]}};
+ {Name, Self, Reply} ->
+ unlink(Pid),
+ Reply
+ end;
+ Error ->
+ Error
+ end.
+
+abcast(Nodes, Name, Msg) ->
+ rpc:eval_everywhere(Nodes, ?MODULE, cast, [Name, Msg]).
+
+reply(nopid, _Name, _Reply) ->
+ ignore;
+reply(ReplyTo, Name, Reply) ->
+ ReplyTo ! {Name, ReplyTo, Reply}.
+
+%% Returns {ok, NewCp} or {error, Reason}
+start_retainer(Cp) ->
+ % Will never be restarted
+ Name = Cp#checkpoint_args.name,
+ case supervisor:start_child(mnesia_checkpoint_sup, [Cp]) of
+ {ok, _Pid} ->
+ {ok, Name, Cp#checkpoint_args.ignore_new, node()};
+ {error, Reason} ->
+ {error, {"Cannot create checkpoint retainer",
+ Name, node(), Reason}}
+ end.
+
+start(Cp) ->
+ Name = Cp#checkpoint_args.name,
+ Args = [Cp#checkpoint_args{supervisor = self()}],
+ mnesia_monitor:start_proc({?MODULE, Name}, ?MODULE, init, Args).
+
+init(Cp) ->
+ process_flag(trap_exit, true),
+ Name = Cp#checkpoint_args.name,
+ Props = [set, public, {keypos, 2}],
+ case catch ?ets_new_table(mnesia_pending_checkpoint, Props) of
+ {'EXIT', Reason} -> %% system limit
+ Msg = "Cannot create an ets table for pending transactions",
+ Error = {error, {system_limit, Name, Msg, Reason}},
+ proc_lib:init_ack(Cp#checkpoint_args.supervisor, Error);
+ PendingTab ->
+ Rs = [prepare_tab(Cp, R) || R <- Cp#checkpoint_args.retainers],
+ Cp2 = Cp#checkpoint_args{retainers = Rs,
+ pid = self(),
+ pending_tab = PendingTab},
+ add(pending_checkpoint_pids, self()),
+ add(pending_checkpoints, PendingTab),
+ set({checkpoint, Name}, self()),
+ add(checkpoints, Name),
+ dbg_out("Checkpoint ~p (~p) started~n", [Name, self()]),
+ proc_lib:init_ack(Cp2#checkpoint_args.supervisor, {ok, self()}),
+ retainer_loop(Cp2)
+ end.
+
+prepare_tab(Cp, R) ->
+ Tab = R#retainer.tab_name,
+ prepare_tab(Cp, R, val({Tab, storage_type})).
+
+prepare_tab(Cp, R, Storage) ->
+ Tab = R#retainer.tab_name,
+ Name = R#retainer.cp_name,
+ case lists:member(node(), R#retainer.writers) of
+ true ->
+ R2 = retainer_create(Cp, R, Tab, Name, Storage),
+ set({Tab, {retainer, Name}}, R2),
+ add({Tab, checkpoints}, Name), %% Keep checkpoint info for table_info & mnesia_session
+ add_chkp_info(Tab, Name),
+ R2;
+ false ->
+ set({Tab, {retainer, Name}}, R#retainer{store = undefined}),
+ R
+ end.
+
+add_chkp_info(Tab, Name) ->
+ case val({Tab, commit_work}) of
+ [{checkpoints, OldList} | CommitList] ->
+ case lists:member(Name, OldList) of
+ true ->
+ ok;
+ false ->
+ NewC = [{checkpoints, [Name | OldList]} | CommitList],
+ mnesia_lib:set({Tab, commit_work}, NewC)
+ end;
+ CommitList ->
+ Chkp = {checkpoints, [Name]},
+ %% OBS checkpoints needs to be first in the list!
+ mnesia_lib:set({Tab, commit_work}, [Chkp | CommitList])
+ end.
+
+tab2retainer({Tab, Name}) ->
+ FlatName = lists:flatten(io_lib:write(Name)),
+ mnesia_lib:dir(lists:concat([?MODULE, "_", Tab, "_", FlatName, ".RET"])).
+
+retainer_create(_Cp, R, Tab, Name, disc_only_copies) ->
+ Fname = tab2retainer({Tab, Name}),
+ file:delete(Fname),
+ Args = [{file, Fname}, {type, set}, {keypos, 2}, {repair, false}],
+ {ok, _} = mnesia_lib:dets_sync_open({Tab, Name}, Args),
+ dbg_out("Checkpoint retainer created ~p ~p~n", [Name, Tab]),
+ R#retainer{store = {dets, {Tab, Name}}, really_retain = true};
+retainer_create(Cp, R, Tab, Name, Storage) ->
+ T = ?ets_new_table(mnesia_retainer, [set, public, {keypos, 2}]),
+ Overriders = Cp#checkpoint_args.ram_overrides_dump,
+ ReallyR = R#retainer.really_retain,
+ ReallyCp = lists:member(Tab, Overriders),
+ ReallyR2 = prepare_ram_tab(Tab, T, Storage, ReallyR, ReallyCp),
+ dbg_out("Checkpoint retainer created ~p ~p~n", [Name, Tab]),
+ R#retainer{store = {ets, T}, really_retain = ReallyR2}.
+
+%% Copy the dumped table into retainer if needed
+%% If the really_retain flag already has been set to false,
+%% it should remain false even if we change storage type
+%% while the checkpoint is activated.
+prepare_ram_tab(Tab, T, ram_copies, true, false) ->
+ Fname = mnesia_lib:tab2dcd(Tab),
+ case mnesia_lib:exists(Fname) of
+ true ->
+ Log = mnesia_log:open_log(prepare_ram_tab,
+ mnesia_log:dcd_log_header(),
+ Fname, true,
+ mnesia_monitor:get_env(auto_repair),
+ read_only),
+ Add = fun(Rec) ->
+ Key = element(2, Rec),
+ Recs =
+ case ?ets_lookup(T, Key) of
+ [] -> [];
+ [{_, _, Old}] -> Old
+ end,
+ ?ets_insert(T, {Tab, Key, [Rec | Recs]}),
+ continue
+ end,
+ traverse_dcd(mnesia_log:chunk_log(Log, start), Log, Add),
+ mnesia_log:close_log(Log);
+ false ->
+ ok
+ end,
+ false;
+prepare_ram_tab(_, _, _, ReallyRetain, _) ->
+ ReallyRetain.
+
+traverse_dcd({Cont, [LogH | Rest]}, Log, Fun)
+ when record(LogH, log_header),
+ LogH#log_header.log_kind == dcd_log,
+ LogH#log_header.log_version >= "1.0" ->
+ traverse_dcd({Cont, Rest}, Log, Fun); %% BUGBUG Error handling repaired files
+traverse_dcd({Cont, Recs}, Log, Fun) -> %% trashed data??
+ lists:foreach(Fun, Recs),
+ traverse_dcd(mnesia_log:chunk_log(Log, Cont), Log, Fun);
+traverse_dcd(eof, _Log, _Fun) ->
+ ok.
+
+retainer_get({ets, Store}, Key) -> ?ets_lookup(Store, Key);
+retainer_get({dets, Store}, Key) -> dets:lookup(Store, Key).
+
+retainer_put({ets, Store}, Val) -> ?ets_insert(Store, Val);
+retainer_put({dets, Store}, Val) -> dets:insert(Store, Val).
+
+retainer_first({ets, Store}) -> ?ets_first(Store);
+retainer_first({dets, Store}) -> dets:first(Store).
+
+retainer_next({ets, Store}, Key) -> ?ets_next(Store, Key);
+retainer_next({dets, Store}, Key) -> dets:next(Store, Key).
+
+%% retainer_next_slot(Tab, Pos) ->
+%% case retainer_slot(Tab, Pos) of
+%% '$end_of_table' ->
+%% '$end_of_table';
+%% [] ->
+%% retainer_next_slot(Tab, Pos + 1);
+%% Recs when list(Recs) ->
+%% {Pos, Recs}
+%% end.
+%%
+%% retainer_slot({ets, Store}, Pos) -> ?ets_next(Store, Pos);
+%% retainer_slot({dets, Store}, Pos) -> dets:slot(Store, Pos).
+
+retainer_fixtable(Tab, Bool) when atom(Tab) ->
+ mnesia_lib:db_fixtable(val({Tab, storage_type}), Tab, Bool);
+retainer_fixtable({ets, Tab}, Bool) ->
+ mnesia_lib:db_fixtable(ram_copies, Tab, Bool);
+retainer_fixtable({dets, Tab}, Bool) ->
+ mnesia_lib:db_fixtable(disc_only_copies, Tab, Bool).
+
+retainer_delete({ets, Store}) ->
+ ?ets_delete_table(Store);
+retainer_delete({dets, Store}) ->
+ mnesia_lib:dets_sync_close(Store),
+ Fname = tab2retainer(Store),
+ file:delete(Fname).
+
+retainer_loop(Cp) ->
+ Name = Cp#checkpoint_args.name,
+ receive
+ {_From, {retain, Tid, Tab, Key, OldRecs}}
+ when Cp#checkpoint_args.wait_for_old == [] ->
+ R = val({Tab, {retainer, Name}}),
+ case R#retainer.really_retain of
+ true ->
+ PendingTab = Cp#checkpoint_args.pending_tab,
+ case catch ?ets_lookup_element(PendingTab, Tid, 1) of
+ {'EXIT', _} ->
+ Store = R#retainer.store,
+ case retainer_get(Store, Key) of
+ [] ->
+ retainer_put(Store, {Tab, Key, OldRecs});
+ _ ->
+ already_retained
+ end;
+ pending ->
+ ignore
+ end;
+ false ->
+ ignore
+ end,
+ retainer_loop(Cp);
+
+ %% Adm
+ {From, deactivate} ->
+ do_stop(Cp),
+ reply(From, Name, deactivated),
+ unlink(From),
+ exit(shutdown);
+
+ {'EXIT', Parent, _} when Parent == Cp#checkpoint_args.supervisor ->
+ %% do_stop(Cp),
+ %% assume that entire Mnesia is terminating
+ exit(shutdown);
+
+ {_From, {mnesia_down, Node}} ->
+ Cp2 = do_del_retainers(Cp, Node),
+ retainer_loop(Cp2);
+ {From, get_checkpoint} ->
+ reply(From, Name, Cp),
+ retainer_loop(Cp);
+ {From, {add_copy, Tab, Node}} when Cp#checkpoint_args.wait_for_old == [] ->
+ {Res, Cp2} = do_add_copy(Cp, Tab, Node),
+ reply(From, Name, Res),
+ retainer_loop(Cp2);
+ {From, {del_copy, Tab, Node}} when Cp#checkpoint_args.wait_for_old == [] ->
+ Cp2 = do_del_copy(Cp, Tab, Node),
+ reply(From, Name, ok),
+ retainer_loop(Cp2);
+ {From, {change_copy, Tab, From, To}} when Cp#checkpoint_args.wait_for_old == [] ->
+ Cp2 = do_change_copy(Cp, Tab, From, To),
+ reply(From, Name, ok),
+ retainer_loop(Cp2);
+ {_From, {add_retainer, R, Node}} ->
+ Cp2 = do_add_retainer(Cp, R, Node),
+ retainer_loop(Cp2);
+ {_From, {del_retainer, R, Node}} when Cp#checkpoint_args.wait_for_old == [] ->
+ Cp2 = do_del_retainer(Cp, R, Node),
+ retainer_loop(Cp2);
+
+ %% Iteration
+ {From, {iter_begin, Iter}} when Cp#checkpoint_args.wait_for_old == [] ->
+ Cp2 = iter_begin(Cp, From, Iter),
+ retainer_loop(Cp2);
+
+ {From, {iter_end, Iter}} when Cp#checkpoint_args.wait_for_old == [] ->
+ retainer_fixtable(Iter#iter.oid_tab, false),
+ Iters = Cp#checkpoint_args.iterators -- [Iter],
+ reply(From, Name, ok),
+ retainer_loop(Cp#checkpoint_args{iterators = Iters});
+
+ {_From, {exit_pending, Tid}}
+ when list(Cp#checkpoint_args.wait_for_old) ->
+ StillPending = lists:delete(Tid, Cp#checkpoint_args.wait_for_old),
+ Cp2 = Cp#checkpoint_args{wait_for_old = StillPending},
+ Cp3 = maybe_activate(Cp2),
+ retainer_loop(Cp3);
+
+ {From, collect_pending} ->
+ PendingTab = Cp#checkpoint_args.pending_tab,
+ del(pending_checkpoints, PendingTab),
+ Pending = ?ets_match_object(PendingTab, '_'),
+ reply(From, Name, {ok, Pending}),
+ retainer_loop(Cp);
+
+ {From, {activate, Pending}} ->
+ StillPending = mnesia_recover:still_pending(Pending),
+ enter_still_pending(StillPending, Cp#checkpoint_args.pending_tab),
+ Cp2 = maybe_activate(Cp#checkpoint_args{wait_for_old = StillPending}),
+ reply(From, Name, activated),
+ retainer_loop(Cp2);
+
+ {'EXIT', From, _Reason} ->
+ Iters = [Iter || Iter <- Cp#checkpoint_args.iterators,
+ check_iter(From, Iter)],
+ retainer_loop(Cp#checkpoint_args{iterators = Iters});
+
+ {system, From, Msg} ->
+ dbg_out("~p got {system, ~p, ~p}~n", [?MODULE, From, Msg]),
+ sys:handle_system_msg(Msg, From, no_parent, ?MODULE, [], Cp)
+ end.
+
+maybe_activate(Cp)
+ when Cp#checkpoint_args.wait_for_old == [],
+ Cp#checkpoint_args.is_activated == false ->
+ Cp#checkpoint_args{pending_tab = undefined, is_activated = true};
+maybe_activate(Cp) ->
+ Cp.
+
+iter_begin(Cp, From, Iter) ->
+ Name = Cp#checkpoint_args.name,
+ R = val({Iter#iter.tab_name, {retainer, Name}}),
+ Iter2 = init_tabs(R, Iter),
+ Iter3 = Iter2#iter{pid = From},
+ retainer_fixtable(Iter3#iter.oid_tab, true),
+ Iters = [Iter3 | Cp#checkpoint_args.iterators],
+ reply(From, Name, {ok, Iter3, self()}),
+ Cp#checkpoint_args{iterators = Iters}.
+
+do_stop(Cp) ->
+ Name = Cp#checkpoint_args.name,
+ del(pending_checkpoints, Cp#checkpoint_args.pending_tab),
+ del(pending_checkpoint_pids, self()),
+ del(checkpoints, Name),
+ unset({checkpoint, Name}),
+ lists:foreach(fun deactivate_tab/1, Cp#checkpoint_args.retainers),
+ Iters = Cp#checkpoint_args.iterators,
+ lists:foreach(fun(I) -> retainer_fixtable(I#iter.oid_tab, false) end, Iters).
+
+deactivate_tab(R) ->
+ Name = R#retainer.cp_name,
+ Tab = R#retainer.tab_name,
+ del({Tab, checkpoints}, Name), %% Keep checkpoint info for table_info & mnesia_session
+ del_chkp_info(Tab, Name),
+ unset({Tab, {retainer, Name}}),
+ Active = lists:member(node(), R#retainer.writers),
+ case R#retainer.store of
+ undefined ->
+ ignore;
+ Store when Active == true ->
+ retainer_delete(Store);
+ _ ->
+ ignore
+ end.
+
+del_chkp_info(Tab, Name) ->
+ case val({Tab, commit_work}) of
+ [{checkpoints, ChkList} | Rest] ->
+ case lists:delete(Name, ChkList) of
+ [] ->
+ %% The only checkpoint was deleted
+ mnesia_lib:set({Tab, commit_work}, Rest);
+ NewList ->
+ mnesia_lib:set({Tab, commit_work},
+ [{checkpoints, NewList} | Rest])
+ end;
+ _ -> ignore
+ end.
+
+do_del_retainers(Cp, Node) ->
+ Rs = [do_del_retainer2(Cp, R, Node) || R <- Cp#checkpoint_args.retainers],
+ Cp#checkpoint_args{retainers = Rs, nodes = writers(Rs)}.
+
+do_del_retainer2(Cp, R, Node) ->
+ Writers = R#retainer.writers -- [Node],
+ R2 = R#retainer{writers = Writers},
+ set({R2#retainer.tab_name, {retainer, R2#retainer.cp_name}}, R2),
+ if
+ Writers == [] ->
+ Event = {mnesia_checkpoint_deactivated, Cp#checkpoint_args.name},
+ mnesia_lib:report_system_event(Event),
+ do_stop(Cp),
+ exit(shutdown);
+ Node == node() ->
+ deactivate_tab(R), % Avoids unnecessary tm_retain accesses
+ set({R2#retainer.tab_name, {retainer, R2#retainer.cp_name}}, R2),
+ R2;
+ true ->
+ R2
+ end.
+
+do_del_retainer(Cp, R0, Node) ->
+ {R, Rest} = find_retainer(R0, Cp#checkpoint_args.retainers, []),
+ R2 = do_del_retainer2(Cp, R, Node),
+ Rs = [R2|Rest],
+ Cp#checkpoint_args{retainers = Rs, nodes = writers(Rs)}.
+
+do_del_copy(Cp, Tab, ThisNode) when ThisNode == node() ->
+ Name = Cp#checkpoint_args.name,
+ Others = Cp#checkpoint_args.nodes -- [ThisNode],
+ R = val({Tab, {retainer, Name}}),
+ abcast(Others, Name, {del_retainer, R, ThisNode}),
+ do_del_retainer(Cp, R, ThisNode).
+
+do_add_copy(Cp, Tab, Node) when Node /= node()->
+ case lists:member(Tab, Cp#checkpoint_args.max) of
+ false ->
+ {ok, Cp};
+ true ->
+ Name = Cp#checkpoint_args.name,
+ R0 = val({Tab, {retainer, Name}}),
+ W = R0#retainer.writers,
+ R = R0#retainer{writers = W ++ [Node]},
+
+ case lists:member(Node, Cp#checkpoint_args.nodes) of
+ true ->
+ send_retainer(Cp, R, Node);
+ false ->
+ case tm_remote_prepare(Node, Cp) of
+ {ok, Name, _IgnoreNew, Node} ->
+ case lists:member(schema, Cp#checkpoint_args.max) of
+ true ->
+ %% We need to send schema retainer somewhere
+ RS0 = val({schema, {retainer, Name}}),
+ W = RS0#retainer.writers,
+ RS1 = RS0#retainer{writers = W ++ [Node]},
+ case send_retainer(Cp, RS1, Node) of
+ {ok, Cp1} ->
+ send_retainer(Cp1, R, Node);
+ Error ->
+ Error
+ end;
+ false ->
+ send_retainer(Cp, R, Node)
+ end;
+ {badrpc, Reason} ->
+ {{error, {badrpc, Reason}}, Cp};
+ {error, Reason} ->
+ {{error, Reason}, Cp}
+ end
+ end
+ end.
+
+tm_remote_prepare(Node, Cp) ->
+ rpc:call(Node, ?MODULE, tm_prepare, [Cp]).
+
+do_add_retainer(Cp, R0, Node) ->
+ Writers = R0#retainer.writers,
+ {R, Rest} = find_retainer(R0, Cp#checkpoint_args.retainers, []),
+ NewRet =
+ if
+ Node == node() ->
+ prepare_tab(Cp, R#retainer{writers = Writers});
+ true ->
+ R#retainer{writers = Writers}
+ end,
+ Rs = [NewRet | Rest],
+ set({NewRet#retainer.tab_name, {retainer, NewRet#retainer.cp_name}}, NewRet),
+ Cp#checkpoint_args{retainers = Rs, nodes = writers(Rs)}.
+
+find_retainer(#retainer{cp_name = CP, tab_name = Tab},
+ [Ret = #retainer{cp_name = CP, tab_name = Tab} | R], Acc) ->
+ {Ret, R ++ Acc};
+find_retainer(Ret, [H|R], Acc) ->
+ find_retainer(Ret, R, [H|Acc]).
+
+send_retainer(Cp, R, Node) ->
+ Name = Cp#checkpoint_args.name,
+ Nodes0 = Cp#checkpoint_args.nodes -- [Node],
+ Nodes1 = Nodes0 ++ [Node],
+ Nodes = Nodes1 -- [node()],
+ abcast(Nodes, Name, {add_retainer, R, Node}),
+ Store = R#retainer.store,
+%% send_retainer2(Node, Name, Store, retainer_next_slot(Store, 0)),
+ send_retainer2(Node, Name, Store, retainer_first(Store)),
+ Cp2 = do_add_retainer(Cp, R, Node),
+ {ok, Cp2}.
+
+send_retainer2(_, _, _, '$end_of_table') ->
+ ok;
+%%send_retainer2(Node, Name, Store, {Slot, Records}) ->
+send_retainer2(Node, Name, Store, Key) ->
+ [{Tab, _, Records}] = retainer_get(Store, Key),
+ abcast([Node], Name, {retain, {dirty, send_retainer}, Tab, Key, Records}),
+ send_retainer2(Node, Name, Store, retainer_next(Store, Key)).
+
+do_change_copy(Cp, Tab, FromType, ToType) ->
+ Name = Cp#checkpoint_args.name,
+ R = val({Tab, {retainer, Name}}),
+ R2 = prepare_tab(Cp, R, ToType),
+ {_, Old} = R#retainer.store,
+ {_, New} = R2#retainer.store,
+
+ Fname = tab2retainer({Tab, Name}),
+ if
+ FromType == disc_only_copies ->
+ mnesia_lib:dets_sync_close(Old),
+ loaded = mnesia_lib:dets_to_ets(Old, New, Fname, set, no, yes),
+ ok = file:delete(Fname);
+ ToType == disc_only_copies ->
+ TabSize = ?ets_info(Old, size),
+ Props = [{file, Fname},
+ {type, set},
+ {keypos, 2},
+%% {ram_file, true},
+ {estimated_no_objects, TabSize + 256},
+ {repair, false}],
+ {ok, _} = mnesia_lib:dets_sync_open(New, Props),
+ ok = mnesia_dumper:raw_dump_table(New, Old),
+ ?ets_delete_table(Old);
+ true ->
+ ignore
+ end,
+ Pos = #retainer.tab_name,
+ Rs = lists:keyreplace(Tab, Pos, Cp#checkpoint_args.retainers, R2),
+ Cp#checkpoint_args{retainers = Rs, nodes = writers(Rs)}.
+
+check_iter(From, Iter) when Iter#iter.pid == From ->
+ retainer_fixtable(Iter#iter.oid_tab, false),
+ false;
+check_iter(_From, _Iter) ->
+ true.
+
+init_tabs(R, Iter) ->
+ {Kind, _} = Store = R#retainer.store,
+ Main = {Kind, Iter#iter.tab_name},
+ Ret = Store,
+ Iter2 = Iter#iter{main_tab = Main, retainer_tab = Ret},
+ case Iter#iter.source of
+ table -> Iter2#iter{oid_tab = Main};
+ retainer -> Iter2#iter{oid_tab = Ret}
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Iteration
+%%
+%% Iterates over a table and applies Fun(ListOfRecords)
+%% with a suitable amount of records, e.g. 1000 or so.
+%% ListOfRecords is [] when the iteration is over.
+%%
+%% OidKind affects which internal table to be iterated over and
+%% ValKind affects which table to pick the actual records from. Legal
+%% values for OidKind and ValKind is the atom table or the atom
+%% retainer.
+%%
+%% The iteration may either be performed over the main table (which
+%% contains the latest values of the records, i.e. the values that
+%% are visible to the applications) or over the checkpoint retainer
+%% (which contains the values as the looked like the timepoint when
+%% the checkpoint was activated).
+%%
+%% It is possible to iterate over the main table and pick values
+%% from the retainer and vice versa.
+
+iterate(Name, Tab, Fun, Acc, Source, Val) ->
+ Iter0 = #iter{tab_name = Tab, source = Source, val = Val},
+ case call(Name, {iter_begin, Iter0}) of
+ {error, Reason} ->
+ {error, Reason};
+ {ok, Iter, Pid} ->
+ link(Pid), % We don't want any pending fixtable's
+ Res = (catch iter(Fun, Acc, Iter)),
+ unlink(Pid),
+ call(Name, {iter_end, Iter}),
+ case Res of
+ {'EXIT', Reason} -> {error, Reason};
+ {error, Reason} -> {error, Reason};
+ Acc2 -> {ok, Acc2}
+ end
+ end.
+
+iter(Fun, Acc, Iter)->
+ iter(Fun, Acc, Iter, retainer_first(Iter#iter.oid_tab)).
+
+iter(Fun, Acc, Iter, Key) ->
+ case get_records(Iter, Key) of
+ {'$end_of_table', []} ->
+ Fun([], Acc);
+ {'$end_of_table', Records} ->
+ Acc2 = Fun(Records, Acc),
+ Fun([], Acc2);
+ {Next, Records} ->
+ Acc2 = Fun(Records, Acc),
+ iter(Fun, Acc2, Iter, Next)
+ end.
+
+stop_iteration(Reason) ->
+ throw({error, {stopped, Reason}}).
+
+get_records(Iter, Key) ->
+ get_records(Iter, Key, 500, []). % 500 keys
+
+get_records(_Iter, Key, 0, Acc) ->
+ {Key, lists:append(lists:reverse(Acc))};
+get_records(_Iter, '$end_of_table', _I, Acc) ->
+ {'$end_of_table', lists:append(lists:reverse(Acc))};
+get_records(Iter, Key, I, Acc) ->
+ Recs = get_val(Iter, Key),
+ Next = retainer_next(Iter#iter.oid_tab, Key),
+ get_records(Iter, Next, I-1, [Recs | Acc]).
+
+get_val(Iter, Key) when Iter#iter.val == latest ->
+ get_latest_val(Iter, Key);
+get_val(Iter, Key) when Iter#iter.val == checkpoint ->
+ get_checkpoint_val(Iter, Key).
+
+get_latest_val(Iter, Key) when Iter#iter.source == table ->
+ retainer_get(Iter#iter.main_tab, Key);
+get_latest_val(Iter, Key) when Iter#iter.source == retainer ->
+ DeleteOid = {Iter#iter.tab_name, Key},
+ [DeleteOid | retainer_get(Iter#iter.main_tab, Key)].
+
+get_checkpoint_val(Iter, Key) when Iter#iter.source == table ->
+ retainer_get(Iter#iter.main_tab, Key);
+get_checkpoint_val(Iter, Key) when Iter#iter.source == retainer ->
+ DeleteOid = {Iter#iter.tab_name, Key},
+ case retainer_get(Iter#iter.retainer_tab, Key) of
+ [{_, _, []}] -> [DeleteOid];
+ [{_, _, Records}] -> [DeleteOid | Records]
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% System upgrade
+
+system_continue(_Parent, _Debug, Cp) ->
+ retainer_loop(Cp).
+
+system_terminate(_Reason, _Parent,_Debug, Cp) ->
+ do_stop(Cp).
+
+system_code_change(Cp, _Module, _OldVsn, _Extra) ->
+ {ok, Cp}.
+
+convert_cp_record(Cp) when record(Cp, checkpoint) ->
+ ROD =
+ case Cp#checkpoint.ram_overrides_dump of
+ true -> Cp#checkpoint.min ++ Cp#checkpoint.max;
+ false -> []
+ end,
+
+ {ok, #checkpoint_args{name = Cp#checkpoint.name,
+ allow_remote = Cp#checkpoint.name,
+ ram_overrides_dump = ROD,
+ nodes = Cp#checkpoint.nodes,
+ node = Cp#checkpoint.node,
+ now = Cp#checkpoint.now,
+ cookie = ?unique_cookie,
+ min = Cp#checkpoint.min,
+ max = Cp#checkpoint.max,
+ pending_tab = Cp#checkpoint.pending_tab,
+ wait_for_old = Cp#checkpoint.wait_for_old,
+ is_activated = Cp#checkpoint.is_activated,
+ ignore_new = Cp#checkpoint.ignore_new,
+ retainers = Cp#checkpoint.retainers,
+ iterators = Cp#checkpoint.iterators,
+ supervisor = Cp#checkpoint.supervisor,
+ pid = Cp#checkpoint.pid
+ }};
+convert_cp_record(Cp) when record(Cp, checkpoint_args) ->
+ AllTabs = Cp#checkpoint_args.min ++ Cp#checkpoint_args.max,
+ ROD = case Cp#checkpoint_args.ram_overrides_dump of
+ [] ->
+ false;
+ AllTabs ->
+ true;
+ _ ->
+ error
+ end,
+ if
+ ROD == error ->
+ {error, {"Old node cannot handle new checkpoint protocol",
+ ram_overrides_dump}};
+ true ->
+ {ok, #checkpoint{name = Cp#checkpoint_args.name,
+ allow_remote = Cp#checkpoint_args.name,
+ ram_overrides_dump = ROD,
+ nodes = Cp#checkpoint_args.nodes,
+ node = Cp#checkpoint_args.node,
+ now = Cp#checkpoint_args.now,
+ min = Cp#checkpoint_args.min,
+ max = Cp#checkpoint_args.max,
+ pending_tab = Cp#checkpoint_args.pending_tab,
+ wait_for_old = Cp#checkpoint_args.wait_for_old,
+ is_activated = Cp#checkpoint_args.is_activated,
+ ignore_new = Cp#checkpoint_args.ignore_new,
+ retainers = Cp#checkpoint_args.retainers,
+ iterators = Cp#checkpoint_args.iterators,
+ supervisor = Cp#checkpoint_args.supervisor,
+ pid = Cp#checkpoint_args.pid
+ }}
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+val(Var) ->
+ case ?catch_val(Var) of
+ {'EXIT', _ReASoN_} -> mnesia_lib:other_val(Var, _ReASoN_);
+ _VaLuE_ -> _VaLuE_
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_checkpoint_sup.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_checkpoint_sup.erl
new file mode 100644
index 0000000000..36425537eb
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_checkpoint_sup.erl
@@ -0,0 +1,39 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_checkpoint_sup.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
+%%
+-module(mnesia_checkpoint_sup).
+
+-behaviour(supervisor).
+
+-export([start/0, init/1]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% top supervisor callback functions
+
+start() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% sub supervisor callback functions
+
+init([]) ->
+ Flags = {simple_one_for_one, 0, timer:hours(24)}, % Trust the top supervisor
+ MFA = {mnesia_checkpoint, start, []},
+ Modules = [?MODULE, mnesia_checkpoint, supervisor],
+ KillAfter = mnesia_kernel_sup:supervisor_timeout(timer:seconds(3)),
+ Workers = [{?MODULE, MFA, transient, KillAfter, worker, Modules}],
+ {ok, {Flags, Workers}}.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_controller.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_controller.erl
new file mode 100644
index 0000000000..1d7f29bfbd
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_controller.erl
@@ -0,0 +1,2010 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_controller.erl,v 1.3 2010/03/04 13:54:19 maria Exp $
+%%
+%% The mnesia_init process loads tables from local disc or from
+%% another nodes. It also coordinates updates of the info about
+%% where we can read and write tables.
+%%
+%% Tables may need to be loaded initially at startup of the local
+%% node or when other nodes announces that they already have loaded
+%% tables that we also want.
+%%
+%% Initially we set the load request queue to those tables that we
+%% safely can load locally, i.e. tables where we have the last
+%% consistent replica and we have received mnesia_down from all
+%% other nodes holding the table. Then we let the mnesia_init
+%% process enter its normal working state.
+%%
+%% When we need to load a table we append a request to the load
+%% request queue. All other requests are regarded as high priority
+%% and are processed immediately (e.g. update table whereabouts).
+%% We processes the load request queue as a "background" job..
+
+-module(mnesia_controller).
+
+-behaviour(gen_server).
+
+%% Mnesia internal stuff
+-export([
+ start/0,
+ i_have_tab/1,
+ info/0,
+ get_info/1,
+ get_workers/1,
+ force_load_table/1,
+ async_dump_log/1,
+ sync_dump_log/1,
+ connect_nodes/1,
+ wait_for_schema_commit_lock/0,
+ release_schema_commit_lock/0,
+ create_table/1,
+ get_disc_copy/1,
+ get_cstructs/0,
+ sync_and_block_table_whereabouts/4,
+ sync_del_table_copy_whereabouts/2,
+ block_table/1,
+ unblock_table/1,
+ block_controller/0,
+ unblock_controller/0,
+ unannounce_add_table_copy/2,
+ master_nodes_updated/2,
+ mnesia_down/1,
+ add_active_replica/2,
+ add_active_replica/3,
+ add_active_replica/4,
+ change_table_access_mode/1,
+ del_active_replica/2,
+ wait_for_tables/2,
+ get_network_copy/2,
+ merge_schema/0,
+ start_remote_sender/4,
+ schedule_late_disc_load/2
+ ]).
+
+%% gen_server callbacks
+-export([init/1,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ terminate/2,
+ code_change/3]).
+
+%% Module internal stuff
+-export([call/1,
+ cast/1,
+ dump_and_reply/2,
+ load_and_reply/2,
+ send_and_reply/2,
+ wait_for_tables_init/2
+ ]).
+
+-import(mnesia_lib, [set/2, add/2]).
+-import(mnesia_lib, [fatal/2, error/2, verbose/2, dbg_out/2]).
+
+-include("mnesia.hrl").
+
+-define(SERVER_NAME, ?MODULE).
+
+-record(state, {supervisor,
+ schema_is_merged = false,
+ early_msgs = [],
+ loader_pid,
+ loader_queue = [],
+ sender_pid,
+ sender_queue = [],
+ late_loader_queue = [],
+ dumper_pid, % Dumper or schema commit pid
+ dumper_queue = [], % Dumper or schema commit queue
+ dump_log_timer_ref,
+ is_stopping = false
+ }).
+
+-record(worker_reply, {what,
+ pid,
+ result
+ }).
+
+-record(schema_commit_lock, {owner}).
+-record(block_controller, {owner}).
+
+-record(dump_log, {initiated_by,
+ opt_reply_to
+ }).
+
+-record(net_load, {table,
+ reason,
+ opt_reply_to,
+ cstruct = unknown
+ }).
+
+-record(send_table, {table,
+ receiver_pid,
+ remote_storage
+ }).
+
+-record(disc_load, {table,
+ reason,
+ opt_reply_to
+ }).
+
+-record(late_load, {table,
+ reason,
+ opt_reply_to,
+ loaders
+ }).
+
+-record(loader_done, {worker_pid,
+ is_loaded,
+ table_name,
+ needs_announce,
+ needs_sync,
+ needs_reply,
+ reply_to,
+ reply}).
+
+-record(sender_done, {worker_pid,
+ worker_res,
+ table_name
+ }).
+
+-record(dumper_done, {worker_pid,
+ worker_res
+ }).
+
+val(Var) ->
+ case ?catch_val(Var) of
+ {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
+ Value -> Value
+ end.
+
+start() ->
+ gen_server:start_link({local, ?SERVER_NAME}, ?MODULE, [self()],
+ [{timeout, infinity}
+ %% ,{debug, [trace]}
+ ]).
+
+sync_dump_log(InitBy) ->
+ call({sync_dump_log, InitBy}).
+
+async_dump_log(InitBy) ->
+ ?SERVER_NAME ! {async_dump_log, InitBy}.
+
+%% Wait for tables to be active
+%% If needed, we will wait for Mnesia to start
+%% If Mnesia stops, we will wait for Mnesia to restart
+%% We will wait even if the list of tables is empty
+%%
+wait_for_tables(Tabs, Timeout) when list(Tabs), Timeout == infinity ->
+ do_wait_for_tables(Tabs, Timeout);
+wait_for_tables(Tabs, Timeout) when list(Tabs),
+ integer(Timeout), Timeout >= 0 ->
+ do_wait_for_tables(Tabs, Timeout);
+wait_for_tables(Tabs, Timeout) ->
+ {error, {badarg, Tabs, Timeout}}.
+
+do_wait_for_tables(Tabs, 0) ->
+ reply_wait(Tabs);
+do_wait_for_tables(Tabs, Timeout) ->
+ Pid = spawn_link(?MODULE, wait_for_tables_init, [self(), Tabs]),
+ receive
+ {?SERVER_NAME, Pid, Res} ->
+ Res;
+
+ {'EXIT', Pid, _} ->
+ reply_wait(Tabs)
+
+ after Timeout ->
+ unlink(Pid),
+ exit(Pid, timeout),
+ reply_wait(Tabs)
+ end.
+
+reply_wait(Tabs) ->
+ case catch mnesia_lib:active_tables() of
+ {'EXIT', _} ->
+ {error, {node_not_running, node()}};
+ Active when list(Active) ->
+ case Tabs -- Active of
+ [] ->
+ ok;
+ BadTabs ->
+ {timeout, BadTabs}
+ end
+ end.
+
+wait_for_tables_init(From, Tabs) ->
+ process_flag(trap_exit, true),
+ Res = wait_for_init(From, Tabs, whereis(?SERVER_NAME)),
+ From ! {?SERVER_NAME, self(), Res},
+ unlink(From),
+ exit(normal).
+
+wait_for_init(From, Tabs, Init) ->
+ case catch link(Init) of
+ {'EXIT', _} ->
+ %% Mnesia is not started
+ {error, {node_not_running, node()}};
+ true when pid(Init) ->
+ cast({sync_tabs, Tabs, self()}),
+ rec_tabs(Tabs, Tabs, From, Init)
+ end.
+
+sync_reply(Waiter, Tab) ->
+ Waiter ! {?SERVER_NAME, {tab_synced, Tab}}.
+
+rec_tabs([Tab | Tabs], AllTabs, From, Init) ->
+ receive
+ {?SERVER_NAME, {tab_synced, Tab}} ->
+ rec_tabs(Tabs, AllTabs, From, Init);
+
+ {'EXIT', From, _} ->
+ %% This will trigger an exit signal
+ %% to mnesia_init
+ exit(wait_for_tables_timeout);
+
+ {'EXIT', Init, _} ->
+ %% Oops, mnesia_init stopped,
+ exit(mnesia_stopped)
+ end;
+rec_tabs([], _, _, Init) ->
+ unlink(Init),
+ ok.
+
+get_cstructs() ->
+ call(get_cstructs).
+
+mnesia_down(Node) ->
+ case cast({mnesia_down, Node}) of
+ {error, _} -> mnesia_monitor:mnesia_down(?SERVER_NAME, Node);
+ _Pid -> ok
+ end.
+wait_for_schema_commit_lock() ->
+ link(whereis(?SERVER_NAME)),
+ unsafe_call(wait_for_schema_commit_lock).
+
+block_controller() ->
+ call(block_controller).
+
+unblock_controller() ->
+ cast(unblock_controller).
+
+release_schema_commit_lock() ->
+ cast({release_schema_commit_lock, self()}),
+ unlink(whereis(?SERVER_NAME)).
+
+%% Special for preparation of add table copy
+get_network_copy(Tab, Cs) ->
+ Work = #net_load{table = Tab,
+ reason = {dumper, add_table_copy},
+ cstruct = Cs
+ },
+ Res = (catch load_table(Work)),
+ if Res#loader_done.is_loaded == true ->
+ Tab = Res#loader_done.table_name,
+ case Res#loader_done.needs_announce of
+ true ->
+ i_have_tab(Tab);
+ false ->
+ ignore
+ end;
+ true -> ignore
+ end,
+
+ receive %% Flush copier done message
+ {copier_done, _Node} ->
+ ok
+ after 500 -> %% avoid hanging if something is wrong and we shall fail.
+ ignore
+ end,
+ Res#loader_done.reply.
+
+%% This functions is invoked from the dumper
+%%
+%% There are two cases here:
+%% startup ->
+%% no need for sync, since mnesia_controller not started yet
+%% schema_trans ->
+%% already synced with mnesia_controller since the dumper
+%% is syncronously started from mnesia_controller
+
+create_table(Tab) ->
+ {loaded, ok} = mnesia_loader:disc_load_table(Tab, {dumper,create_table}).
+
+get_disc_copy(Tab) ->
+ disc_load_table(Tab, {dumper,change_table_copy_type}, undefined).
+
+%% Returns ok instead of yes
+force_load_table(Tab) when atom(Tab), Tab /= schema ->
+ case ?catch_val({Tab, storage_type}) of
+ ram_copies ->
+ do_force_load_table(Tab);
+ disc_copies ->
+ do_force_load_table(Tab);
+ disc_only_copies ->
+ do_force_load_table(Tab);
+ unknown ->
+ set({Tab, load_by_force}, true),
+ cast({force_load_updated, Tab}),
+ wait_for_tables([Tab], infinity);
+ {'EXIT', _} ->
+ {error, {no_exists, Tab}}
+ end;
+force_load_table(Tab) ->
+ {error, {bad_type, Tab}}.
+
+do_force_load_table(Tab) ->
+ Loaded = ?catch_val({Tab, load_reason}),
+ case Loaded of
+ unknown ->
+ set({Tab, load_by_force}, true),
+ mnesia_late_loader:async_late_disc_load(node(), [Tab], forced_by_user),
+ wait_for_tables([Tab], infinity);
+ {'EXIT', _} ->
+ set({Tab, load_by_force}, true),
+ mnesia_late_loader:async_late_disc_load(node(), [Tab], forced_by_user),
+ wait_for_tables([Tab], infinity);
+ _ ->
+ ok
+ end.
+master_nodes_updated(schema, _Masters) ->
+ ignore;
+master_nodes_updated(Tab, Masters) ->
+ cast({master_nodes_updated, Tab, Masters}).
+
+schedule_late_disc_load(Tabs, Reason) ->
+ MsgTag = late_disc_load,
+ try_schedule_late_disc_load(Tabs, Reason, MsgTag).
+
+try_schedule_late_disc_load(Tabs, _Reason, MsgTag)
+ when Tabs == [], MsgTag /= schema_is_merged ->
+ ignore;
+try_schedule_late_disc_load(Tabs, Reason, MsgTag) ->
+ GetIntents =
+ fun() ->
+ Item = mnesia_late_disc_load,
+ Nodes = val({current, db_nodes}),
+ mnesia:lock({global, Item, Nodes}, write),
+ case multicall(Nodes -- [node()], disc_load_intents) of
+ {Replies, []} ->
+ call({MsgTag, Tabs, Reason, Replies}),
+ done;
+ {_, BadNodes} ->
+ %% Some nodes did not respond, lets try again
+ {retry, BadNodes}
+ end
+ end,
+ case mnesia:transaction(GetIntents) of
+ {'atomic', done} ->
+ done;
+ {'atomic', {retry, BadNodes}} ->
+ verbose("Retry late_load_tables because bad nodes: ~p~n",
+ [BadNodes]),
+ try_schedule_late_disc_load(Tabs, Reason, MsgTag);
+ {aborted, AbortReason} ->
+ fatal("Cannot late_load_tables~p: ~p~n",
+ [[Tabs, Reason, MsgTag], AbortReason])
+ end.
+
+connect_nodes(Ns) ->
+ case mnesia:system_info(is_running) of
+ no ->
+ {error, {node_not_running, node()}};
+ yes ->
+ {NewC, OldC} = mnesia_recover:connect_nodes(Ns),
+ Connected = NewC ++OldC,
+ New1 = mnesia_lib:intersect(Ns, Connected),
+ New = New1 -- val({current, db_nodes}),
+
+ case try_merge_schema(New) of
+ ok ->
+ mnesia_lib:add_list(extra_db_nodes, New),
+ {ok, New};
+ {aborted, {throw, Str}} when list(Str) ->
+ %%mnesia_recover:disconnect_nodes(New),
+ {error, {merge_schema_failed, lists:flatten(Str)}};
+ Else ->
+ %% Unconnect nodes where merge failed!!
+ %% mnesia_recover:disconnect_nodes(New),
+ {error, Else}
+ end
+ end.
+
+%% Merge the local schema with the schema on other nodes.
+%% But first we must let all processes that want to force
+%% load tables wait until the schema merge is done.
+
+merge_schema() ->
+ AllNodes = mnesia_lib:all_nodes(),
+ case try_merge_schema(AllNodes) of
+ ok ->
+ schema_is_merged();
+ {aborted, {throw, Str}} when list(Str) ->
+ fatal("Failed to merge schema: ~s~n", [Str]);
+ Else ->
+ fatal("Failed to merge schema: ~p~n", [Else])
+ end.
+
+try_merge_schema(Nodes) ->
+ case mnesia_schema:merge_schema() of
+ {'atomic', not_merged} ->
+ %% No more nodes that we need to merge the schema with
+ ok;
+ {'atomic', {merged, OldFriends, NewFriends}} ->
+ %% Check if new nodes has been added to the schema
+ Diff = mnesia_lib:all_nodes() -- [node() | Nodes],
+ mnesia_recover:connect_nodes(Diff),
+
+ %% Tell everybody to adopt orphan tables
+ im_running(OldFriends, NewFriends),
+ im_running(NewFriends, OldFriends),
+
+ try_merge_schema(Nodes);
+ {'atomic', {"Cannot get cstructs", Node, Reason}} ->
+ dbg_out("Cannot get cstructs, Node ~p ~p~n", [Node, Reason]),
+ timer:sleep(1000), % Avoid a endless loop look alike
+ try_merge_schema(Nodes);
+ Other ->
+ Other
+ end.
+
+im_running(OldFriends, NewFriends) ->
+ abcast(OldFriends, {im_running, node(), NewFriends}).
+
+schema_is_merged() ->
+ MsgTag = schema_is_merged,
+ SafeLoads = initial_safe_loads(),
+
+ %% At this point we do not know anything about
+ %% which tables that the other nodes already
+ %% has loaded and therefore we let the normal
+ %% processing of the loader_queue take care
+ %% of it, since we at that time point will
+ %% know the whereabouts. We rely on the fact
+ %% that all nodes tells each other directly
+ %% when they have loaded a table and are
+ %% willing to share it.
+
+ try_schedule_late_disc_load(SafeLoads, initial, MsgTag).
+
+
+cast(Msg) ->
+ case whereis(?SERVER_NAME) of
+ undefined ->{error, {node_not_running, node()}};
+ Pid -> gen_server:cast(Pid, Msg)
+ end.
+
+abcast(Nodes, Msg) ->
+ gen_server:abcast(Nodes, ?SERVER_NAME, Msg).
+
+unsafe_call(Msg) ->
+ case whereis(?SERVER_NAME) of
+ undefined -> {error, {node_not_running, node()}};
+ Pid -> gen_server:call(Pid, Msg, infinity)
+ end.
+
+call(Msg) ->
+ case whereis(?SERVER_NAME) of
+ undefined ->
+ {error, {node_not_running, node()}};
+ Pid ->
+ link(Pid),
+ Res = gen_server:call(Pid, Msg, infinity),
+ unlink(Pid),
+
+ %% We get an exit signal if server dies
+ receive
+ {'EXIT', Pid, _Reason} ->
+ {error, {node_not_running, node()}}
+ after 0 ->
+ ignore
+ end,
+ Res
+ end.
+
+remote_call(Node, Func, Args) ->
+ case catch gen_server:call({?MODULE, Node}, {Func, Args, self()}, infinity) of
+ {'EXIT', Error} ->
+ {error, Error};
+ Else ->
+ Else
+ end.
+
+multicall(Nodes, Msg) ->
+ {Good, Bad} = gen_server:multi_call(Nodes, ?MODULE, Msg, infinity),
+ PatchedGood = [Reply || {_Node, Reply} <- Good],
+ {PatchedGood, Bad}. %% Make the replies look like rpc:multicalls..
+%% rpc:multicall(Nodes, ?MODULE, call, [Msg]).
+
+%%%----------------------------------------------------------------------
+%%% Callback functions from gen_server
+%%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% Func: init/1
+%% Returns: {ok, State} |
+%% {ok, State, Timeout} |
+%% {stop, Reason}
+%%----------------------------------------------------------------------
+init([Parent]) ->
+ process_flag(trap_exit, true),
+ mnesia_lib:verbose("~p starting: ~p~n", [?SERVER_NAME, self()]),
+
+ %% Handshake and initialize transaction recovery
+ %% for new nodes detected in the schema
+ All = mnesia_lib:all_nodes(),
+ Diff = All -- [node() | val(original_nodes)],
+ mnesia_lib:unset(original_nodes),
+ mnesia_recover:connect_nodes(Diff),
+
+ Interval = mnesia_monitor:get_env(dump_log_time_threshold),
+ Msg = {async_dump_log, time_threshold},
+ {ok, Ref} = timer:send_interval(Interval, Msg),
+ mnesia_dumper:start_regulator(),
+
+ {ok, #state{supervisor = Parent, dump_log_timer_ref = Ref}}.
+
+%%----------------------------------------------------------------------
+%% Func: handle_call/3
+%% Returns: {reply, Reply, State} |
+%% {reply, Reply, State, Timeout} |
+%% {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, Reply, State} | (terminate/2 is called)
+%% {stop, Reason, Reply, State} (terminate/2 is called)
+%%----------------------------------------------------------------------
+
+handle_call({sync_dump_log, InitBy}, From, State) ->
+ Worker = #dump_log{initiated_by = InitBy,
+ opt_reply_to = From
+ },
+ State2 = add_worker(Worker, State),
+ noreply(State2);
+
+handle_call(wait_for_schema_commit_lock, From, State) ->
+ Worker = #schema_commit_lock{owner = From},
+ State2 = add_worker(Worker, State),
+ noreply(State2);
+
+handle_call(block_controller, From, State) ->
+ Worker = #block_controller{owner = From},
+ State2 = add_worker(Worker, State),
+ noreply(State2);
+
+
+handle_call(get_cstructs, From, State) ->
+ Tabs = val({schema, tables}),
+ Cstructs = [val({T, cstruct}) || T <- Tabs],
+ Running = val({current, db_nodes}),
+ reply(From, {cstructs, Cstructs, Running}),
+ noreply(State);
+
+handle_call({schema_is_merged, TabsR, Reason, RemoteLoaders}, From, State) ->
+ State2 = late_disc_load(TabsR, Reason, RemoteLoaders, From, State),
+
+ %% Handle early messages
+ Msgs = State2#state.early_msgs,
+ State3 = State2#state{early_msgs = [], schema_is_merged = true},
+ Ns = val({current, db_nodes}),
+ dbg_out("Schema is merged ~w, State ~w~n", [Ns, State3]),
+%% dbg_out("handle_early_msgs ~p ~n", [Msgs]), % qqqq
+ handle_early_msgs(lists:reverse(Msgs), State3);
+
+handle_call(disc_load_intents, From, State) ->
+ Tabs = disc_load_intents(State#state.loader_queue) ++
+ disc_load_intents(State#state.late_loader_queue),
+ ActiveTabs = mnesia_lib:local_active_tables(),
+ reply(From, {ok, node(), mnesia_lib:union(Tabs, ActiveTabs)}),
+ noreply(State);
+
+handle_call({update_where_to_write, [add, Tab, AddNode], _From}, _Dummy, State) ->
+%%% dbg_out("update_w2w ~p", [[add, Tab, AddNode]]), %%% qqqq
+ Current = val({current, db_nodes}),
+ Res =
+ case lists:member(AddNode, Current) and
+ State#state.schema_is_merged == true of
+ true ->
+ mnesia_lib:add({Tab, where_to_write}, AddNode);
+ false ->
+ ignore
+ end,
+ {reply, Res, State};
+
+handle_call({add_active_replica, [Tab, ToNode, RemoteS, AccessMode], From},
+ ReplyTo, State) ->
+ KnownNode = lists:member(ToNode, val({current, db_nodes})),
+ Merged = State#state.schema_is_merged,
+ if
+ KnownNode == false ->
+ reply(ReplyTo, ignore),
+ noreply(State);
+ Merged == true ->
+ Res = add_active_replica(Tab, ToNode, RemoteS, AccessMode),
+ reply(ReplyTo, Res),
+ noreply(State);
+ true -> %% Schema is not merged
+ Msg = {add_active_replica, [Tab, ToNode, RemoteS, AccessMode], From},
+ Msgs = State#state.early_msgs,
+ reply(ReplyTo, ignore), %% Reply ignore and add data after schema merge
+ noreply(State#state{early_msgs = [{call, Msg, undefined} | Msgs]})
+ end;
+
+handle_call({unannounce_add_table_copy, [Tab, Node], From}, ReplyTo, State) ->
+ KnownNode = lists:member(node(From), val({current, db_nodes})),
+ Merged = State#state.schema_is_merged,
+ if
+ KnownNode == false ->
+ reply(ReplyTo, ignore),
+ noreply(State);
+ Merged == true ->
+ Res = unannounce_add_table_copy(Tab, Node),
+ reply(ReplyTo, Res),
+ noreply(State);
+ true -> %% Schema is not merged
+ Msg = {unannounce_add_table_copy, [Tab, Node], From},
+ Msgs = State#state.early_msgs,
+ reply(ReplyTo, ignore), %% Reply ignore and add data after schema merge
+ %% Set ReplyTO to undefined so we don't reply twice
+ noreply(State#state{early_msgs = [{call, Msg, undefined} | Msgs]})
+ end;
+
+handle_call(Msg, From, State) when State#state.schema_is_merged == false ->
+ %% Buffer early messages
+%% dbg_out("Buffered early msg ~p ~n", [Msg]), %% qqqq
+ Msgs = State#state.early_msgs,
+ noreply(State#state{early_msgs = [{call, Msg, From} | Msgs]});
+
+handle_call({net_load, Tab, Cs}, From, State) ->
+ Worker = #net_load{table = Tab,
+ opt_reply_to = From,
+ reason = add_table_copy,
+ cstruct = Cs
+ },
+ State2 = add_worker(Worker, State),
+ noreply(State2);
+
+handle_call({late_disc_load, Tabs, Reason, RemoteLoaders}, From, State) ->
+ State2 = late_disc_load(Tabs, Reason, RemoteLoaders, From, State),
+ noreply(State2);
+
+handle_call({block_table, [Tab], From}, _Dummy, State) ->
+ case lists:member(node(From), val({current, db_nodes})) of
+ true ->
+ block_table(Tab);
+ false ->
+ ignore
+ end,
+ {reply, ok, State};
+
+handle_call({check_w2r, _Node, Tab}, _From, State) ->
+ {reply, val({Tab, where_to_read}), State};
+
+handle_call(Msg, _From, State) ->
+ error("~p got unexpected call: ~p~n", [?SERVER_NAME, Msg]),
+ noreply(State).
+
+disc_load_intents([H | T]) when record(H, disc_load) ->
+ [H#disc_load.table | disc_load_intents(T)];
+disc_load_intents([H | T]) when record(H, late_load) ->
+ [H#late_load.table | disc_load_intents(T)];
+disc_load_intents( [H | T]) when record(H, net_load) ->
+ disc_load_intents(T);
+disc_load_intents([]) ->
+ [].
+
+late_disc_load(TabsR, Reason, RemoteLoaders, From, State) ->
+ verbose("Intend to load tables: ~p~n", [TabsR]),
+ ?eval_debug_fun({?MODULE, late_disc_load},
+ [{tabs, TabsR},
+ {reason, Reason},
+ {loaders, RemoteLoaders}]),
+
+ reply(From, queued),
+ %% RemoteLoaders is a list of {ok, Node, Tabs} tuples
+
+ %% Remove deleted tabs
+ LocalTabs = mnesia_lib:val({schema, local_tables}),
+ Filter = fun({Tab, Reas}, Acc) ->
+ case lists:member(Tab, LocalTabs) of
+ true -> [{Tab, Reas} | Acc];
+ false -> Acc
+ end;
+ (Tab, Acc) ->
+ case lists:member(Tab, LocalTabs) of
+ true -> [Tab | Acc];
+ false -> Acc
+ end
+ end,
+
+ Tabs = lists:foldl(Filter, [], TabsR),
+
+ Nodes = val({current, db_nodes}),
+ LateLoaders = late_loaders(Tabs, Reason, RemoteLoaders, Nodes),
+ LateQueue = State#state.late_loader_queue ++ LateLoaders,
+ State#state{late_loader_queue = LateQueue}.
+
+late_loaders([{Tab, Reason} | Tabs], DefaultReason, RemoteLoaders, Nodes) ->
+ LoadNodes = late_load_filter(RemoteLoaders, Tab, Nodes, []),
+ case LoadNodes of
+ [] ->
+ cast({disc_load, Tab, Reason}); % Ugly cast
+ _ ->
+ ignore
+ end,
+ LateLoad = #late_load{table = Tab, loaders = LoadNodes, reason = Reason},
+ [LateLoad | late_loaders(Tabs, DefaultReason, RemoteLoaders, Nodes)];
+
+late_loaders([Tab | Tabs], Reason, RemoteLoaders, Nodes) ->
+ Loaders = late_load_filter(RemoteLoaders, Tab, Nodes, []),
+ case Loaders of
+ [] ->
+ cast({disc_load, Tab, Reason}); % Ugly cast
+ _ ->
+ ignore
+ end,
+ LateLoad = #late_load{table = Tab, loaders = Loaders, reason = Reason},
+ [LateLoad | late_loaders(Tabs, Reason, RemoteLoaders, Nodes)];
+late_loaders([], _Reason, _RemoteLoaders, _Nodes) ->
+ [].
+
+late_load_filter([{error, _} | RemoteLoaders], Tab, Nodes, Acc) ->
+ late_load_filter(RemoteLoaders, Tab, Nodes, Acc);
+late_load_filter([{badrpc, _} | RemoteLoaders], Tab, Nodes, Acc) ->
+ late_load_filter(RemoteLoaders, Tab, Nodes, Acc);
+late_load_filter([RL | RemoteLoaders], Tab, Nodes, Acc) ->
+ {ok, Node, Intents} = RL,
+ Access = val({Tab, access_mode}),
+ LocalC = val({Tab, local_content}),
+ StillActive = lists:member(Node, Nodes),
+ RemoteIntent = lists:member(Tab, Intents),
+ if
+ Access == read_write,
+ LocalC == false,
+ StillActive == true,
+ RemoteIntent == true ->
+ Masters = mnesia_recover:get_master_nodes(Tab),
+ case lists:member(Node, Masters) of
+ true ->
+ %% The other node is master node for
+ %% the table, accept his load intent
+ late_load_filter(RemoteLoaders, Tab, Nodes, [Node | Acc]);
+ false when Masters == [] ->
+ %% The table has no master nodes
+ %% accept his load intent
+ late_load_filter(RemoteLoaders, Tab, Nodes, [Node | Acc]);
+ false ->
+ %% Some one else is master node for
+ %% the table, ignore his load intent
+ late_load_filter(RemoteLoaders, Tab, Nodes, Acc)
+ end;
+ true ->
+ late_load_filter(RemoteLoaders, Tab, Nodes, Acc)
+ end;
+late_load_filter([], _Tab, _Nodes, Acc) ->
+ Acc.
+
+%%----------------------------------------------------------------------
+%% Func: handle_cast/2
+%% Returns: {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State} (terminate/2 is called)
+%%----------------------------------------------------------------------
+
+handle_cast({release_schema_commit_lock, _Owner}, State) ->
+ if
+ State#state.is_stopping == true ->
+ {stop, shutdown, State};
+ true ->
+ case State#state.dumper_queue of
+ [#schema_commit_lock{}|Rest] ->
+ [_Worker | Rest] = State#state.dumper_queue,
+ State2 = State#state{dumper_pid = undefined,
+ dumper_queue = Rest},
+ State3 = opt_start_worker(State2),
+ noreply(State3);
+ _ ->
+ noreply(State)
+ end
+ end;
+
+handle_cast(unblock_controller, State) ->
+ if
+ State#state.is_stopping == true ->
+ {stop, shutdown, State};
+ record(hd(State#state.dumper_queue), block_controller) ->
+ [_Worker | Rest] = State#state.dumper_queue,
+ State2 = State#state{dumper_pid = undefined,
+ dumper_queue = Rest},
+ State3 = opt_start_worker(State2),
+ noreply(State3)
+ end;
+
+handle_cast({mnesia_down, Node}, State) ->
+ maybe_log_mnesia_down(Node),
+ mnesia_lib:del({current, db_nodes}, Node),
+ mnesia_checkpoint:tm_mnesia_down(Node),
+ Alltabs = val({schema, tables}),
+ State2 = reconfigure_tables(Node, State, Alltabs),
+ case State#state.sender_pid of
+ undefined -> ignore;
+ Pid when pid(Pid) -> Pid ! {copier_done, Node}
+ end,
+ case State#state.loader_pid of
+ undefined -> ignore;
+ Pid2 when pid(Pid2) -> Pid2 ! {copier_done, Node}
+ end,
+ NewSenders =
+ case State#state.sender_queue of
+ [OldSender | RestSenders] ->
+ Remove = fun(ST) ->
+ node(ST#send_table.receiver_pid) /= Node
+ end,
+ NewS = lists:filter(Remove, RestSenders),
+ %% Keep old sender it will be removed by sender_done
+ [OldSender | NewS];
+ [] ->
+ []
+ end,
+ Early = remove_early_messages(State2#state.early_msgs, Node),
+ mnesia_monitor:mnesia_down(?SERVER_NAME, Node),
+ noreply(State2#state{sender_queue = NewSenders, early_msgs = Early});
+
+handle_cast({im_running, _Node, NewFriends}, State) ->
+ Tabs = mnesia_lib:local_active_tables() -- [schema],
+ Ns = mnesia_lib:intersect(NewFriends, val({current, db_nodes})),
+ abcast(Ns, {adopt_orphans, node(), Tabs}),
+ noreply(State);
+
+handle_cast(Msg, State) when State#state.schema_is_merged == false ->
+ %% Buffer early messages
+ Msgs = State#state.early_msgs,
+ noreply(State#state{early_msgs = [{cast, Msg} | Msgs]});
+
+handle_cast({disc_load, Tab, Reason}, State) ->
+ Worker = #disc_load{table = Tab, reason = Reason},
+ State2 = add_worker(Worker, State),
+ noreply(State2);
+
+handle_cast(Worker, State) when record(Worker, send_table) ->
+ State2 = add_worker(Worker, State),
+ noreply(State2);
+
+handle_cast({sync_tabs, Tabs, From}, State) ->
+ %% user initiated wait_for_tables
+ handle_sync_tabs(Tabs, From),
+ noreply(State);
+
+handle_cast({i_have_tab, Tab, Node}, State) ->
+ case lists:member(Node, val({current, db_nodes})) of
+ true ->
+ State2 = node_has_tabs([Tab], Node, State),
+ noreply(State2);
+ false ->
+ noreply(State)
+ end;
+
+handle_cast({force_load_updated, Tab}, State) ->
+ case val({Tab, active_replicas}) of
+ [] ->
+ %% No valid replicas
+ noreply(State);
+ [SomeNode | _] ->
+ State2 = node_has_tabs([Tab], SomeNode, State),
+ noreply(State2)
+ end;
+
+handle_cast({master_nodes_updated, Tab, Masters}, State) ->
+ Active = val({Tab, active_replicas}),
+ Valid =
+ case val({Tab, load_by_force}) of
+ true ->
+ Active;
+ false ->
+ if
+ Masters == [] ->
+ Active;
+ true ->
+ mnesia_lib:intersect(Masters, Active)
+ end
+ end,
+ case Valid of
+ [] ->
+ %% No valid replicas
+ noreply(State);
+ [SomeNode | _] ->
+ State2 = node_has_tabs([Tab], SomeNode, State),
+ noreply(State2)
+ end;
+
+handle_cast({adopt_orphans, Node, Tabs}, State) ->
+
+ State2 = node_has_tabs(Tabs, Node, State),
+
+ %% Register the other node as up and running
+ mnesia_recover:log_mnesia_up(Node),
+ verbose("Logging mnesia_up ~w~n", [Node]),
+ mnesia_lib:report_system_event({mnesia_up, Node}),
+
+ %% Load orphan tables
+ LocalTabs = val({schema, local_tables}) -- [schema],
+ Nodes = val({current, db_nodes}),
+ {LocalOrphans, RemoteMasters} =
+ orphan_tables(LocalTabs, Node, Nodes, [], []),
+ Reason = {adopt_orphan, node()},
+ mnesia_late_loader:async_late_disc_load(node(), LocalOrphans, Reason),
+
+ Fun =
+ fun(N) ->
+ RemoteOrphans =
+ [Tab || {Tab, Ns} <- RemoteMasters,
+ lists:member(N, Ns)],
+ mnesia_late_loader:maybe_async_late_disc_load(N, RemoteOrphans, Reason)
+ end,
+ lists:foreach(Fun, Nodes),
+
+ Queue = State2#state.loader_queue,
+ State3 = State2#state{loader_queue = Queue},
+ noreply(State3);
+
+handle_cast(Msg, State) ->
+ error("~p got unexpected cast: ~p~n", [?SERVER_NAME, Msg]),
+ noreply(State).
+
+handle_sync_tabs([Tab | Tabs], From) ->
+ case val({Tab, where_to_read}) of
+ nowhere ->
+ case get({sync_tab, Tab}) of
+ undefined ->
+ put({sync_tab, Tab}, [From]);
+ Pids ->
+ put({sync_tab, Tab}, [From | Pids])
+ end;
+ _ ->
+ sync_reply(From, Tab)
+ end,
+ handle_sync_tabs(Tabs, From);
+handle_sync_tabs([], _From) ->
+ ok.
+
+%%----------------------------------------------------------------------
+%% Func: handle_info/2
+%% Returns: {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State} (terminate/2 is called)
+%%----------------------------------------------------------------------
+
+handle_info({async_dump_log, InitBy}, State) ->
+ Worker = #dump_log{initiated_by = InitBy},
+ State2 = add_worker(Worker, State),
+ noreply(State2);
+
+handle_info(Done, State) when record(Done, dumper_done) ->
+ Pid = Done#dumper_done.worker_pid,
+ Res = Done#dumper_done.worker_res,
+ if
+ State#state.is_stopping == true ->
+ {stop, shutdown, State};
+ Res == dumped, Pid == State#state.dumper_pid ->
+ [Worker | Rest] = State#state.dumper_queue,
+ reply(Worker#dump_log.opt_reply_to, Res),
+ State2 = State#state{dumper_pid = undefined,
+ dumper_queue = Rest},
+ State3 = opt_start_worker(State2),
+ noreply(State3);
+ true ->
+ fatal("Dumper failed: ~p~n state: ~p~n", [Res, State]),
+ {stop, fatal, State}
+ end;
+
+handle_info(Done, State) when record(Done, loader_done) ->
+ if
+ %% Assertion
+ Done#loader_done.worker_pid == State#state.loader_pid -> ok
+ end,
+
+ [_Worker | Rest] = LoadQ0 = State#state.loader_queue,
+ LateQueue0 = State#state.late_loader_queue,
+ {LoadQ, LateQueue} =
+ case Done#loader_done.is_loaded of
+ true ->
+ Tab = Done#loader_done.table_name,
+
+ %% Optional user sync
+ case Done#loader_done.needs_sync of
+ true -> user_sync_tab(Tab);
+ false -> ignore
+ end,
+
+ %% Optional table announcement
+ case Done#loader_done.needs_announce of
+ true ->
+ i_have_tab(Tab),
+ case Tab of
+ schema ->
+ ignore;
+ _ ->
+ %% Local node needs to perform user_sync_tab/1
+ Ns = val({current, db_nodes}),
+ abcast(Ns, {i_have_tab, Tab, node()})
+ end;
+ false ->
+ case Tab of
+ schema ->
+ ignore;
+ _ ->
+ %% Local node needs to perform user_sync_tab/1
+ Ns = val({current, db_nodes}),
+ AlreadyKnows = val({Tab, active_replicas}),
+ abcast(Ns -- AlreadyKnows, {i_have_tab, Tab, node()})
+ end
+ end,
+
+ %% Optional client reply
+ case Done#loader_done.needs_reply of
+ true ->
+ reply(Done#loader_done.reply_to,
+ Done#loader_done.reply);
+ false ->
+ ignore
+ end,
+ {Rest, reply_late_load(Tab, LateQueue0)};
+ false ->
+ case Done#loader_done.reply of
+ restart ->
+ {LoadQ0, LateQueue0};
+ _ ->
+ {Rest, LateQueue0}
+ end
+ end,
+
+ State2 = State#state{loader_pid = undefined,
+ loader_queue = LoadQ,
+ late_loader_queue = LateQueue},
+
+ State3 = opt_start_worker(State2),
+ noreply(State3);
+
+handle_info(Done, State) when record(Done, sender_done) ->
+ Pid = Done#sender_done.worker_pid,
+ Res = Done#sender_done.worker_res,
+ if
+ Res == ok, Pid == State#state.sender_pid ->
+ [Worker | Rest] = State#state.sender_queue,
+ Worker#send_table.receiver_pid ! {copier_done, node()},
+ State2 = State#state{sender_pid = undefined,
+ sender_queue = Rest},
+ State3 = opt_start_worker(State2),
+ noreply(State3);
+ true ->
+ %% No need to send any message to the table receiver
+ %% since it will soon get a mnesia_down anyway
+ fatal("Sender failed: ~p~n state: ~p~n", [Res, State]),
+ {stop, fatal, State}
+ end;
+
+handle_info({'EXIT', Pid, R}, State) when Pid == State#state.supervisor ->
+ catch set(mnesia_status, stopping),
+ case State#state.dumper_pid of
+ undefined ->
+ dbg_out("~p was ~p~n", [?SERVER_NAME, R]),
+ {stop, shutdown, State};
+ _ ->
+ noreply(State#state{is_stopping = true})
+ end;
+
+handle_info({'EXIT', Pid, R}, State) when Pid == State#state.dumper_pid ->
+ case State#state.dumper_queue of
+ [#schema_commit_lock{}|Workers] -> %% Schema trans crashed or was killed
+ State2 = State#state{dumper_queue = Workers, dumper_pid = undefined},
+ State3 = opt_start_worker(State2),
+ noreply(State3);
+ _Other ->
+ fatal("Dumper or schema commit crashed: ~p~n state: ~p~n", [R, State]),
+ {stop, fatal, State}
+ end;
+
+handle_info({'EXIT', Pid, R}, State) when Pid == State#state.loader_pid ->
+ fatal("Loader crashed: ~p~n state: ~p~n", [R, State]),
+ {stop, fatal, State};
+
+handle_info({'EXIT', Pid, R}, State) when Pid == State#state.sender_pid ->
+ %% No need to send any message to the table receiver
+ %% since it will soon get a mnesia_down anyway
+ fatal("Sender crashed: ~p~n state: ~p~n", [R, State]),
+ {stop, fatal, State};
+
+handle_info({From, get_state}, State) ->
+ From ! {?SERVER_NAME, State},
+ noreply(State);
+
+%% No real need for buffering
+handle_info(Msg, State) when State#state.schema_is_merged == false ->
+ %% Buffer early messages
+ Msgs = State#state.early_msgs,
+ noreply(State#state{early_msgs = [{info, Msg} | Msgs]});
+
+handle_info({'EXIT', Pid, wait_for_tables_timeout}, State) ->
+ sync_tab_timeout(Pid, get()),
+ noreply(State);
+
+handle_info(Msg, State) ->
+ error("~p got unexpected info: ~p~n", [?SERVER_NAME, Msg]),
+ noreply(State).
+
+reply_late_load(Tab, [H | T]) when H#late_load.table == Tab ->
+ reply(H#late_load.opt_reply_to, ok),
+ reply_late_load(Tab, T);
+reply_late_load(Tab, [H | T]) ->
+ [H | reply_late_load(Tab, T)];
+reply_late_load(_Tab, []) ->
+ [].
+
+sync_tab_timeout(Pid, [{{sync_tab, Tab}, Pids} | Tail]) ->
+ case lists:delete(Pid, Pids) of
+ [] ->
+ erase({sync_tab, Tab});
+ Pids2 ->
+ put({sync_tab, Tab}, Pids2)
+ end,
+ sync_tab_timeout(Pid, Tail);
+sync_tab_timeout(Pid, [_ | Tail]) ->
+ sync_tab_timeout(Pid, Tail);
+sync_tab_timeout(_Pid, []) ->
+ ok.
+
+%% Pick the load record that has the highest load order
+%% Returns {BestLoad, RemainingQueue} or {none, []} if queue is empty
+pick_next(Queue) ->
+ pick_next(Queue, none, none, []).
+
+pick_next([Head | Tail], Load, Order, Rest) when record(Head, net_load) ->
+ Tab = Head#net_load.table,
+ select_best(Head, Tail, val({Tab, load_order}), Load, Order, Rest);
+pick_next([Head | Tail], Load, Order, Rest) when record(Head, disc_load) ->
+ Tab = Head#disc_load.table,
+ select_best(Head, Tail, val({Tab, load_order}), Load, Order, Rest);
+pick_next([], Load, _Order, Rest) ->
+ {Load, Rest}.
+
+select_best(Load, Tail, Order, none, none, Rest) ->
+ pick_next(Tail, Load, Order, Rest);
+select_best(Load, Tail, Order, OldLoad, OldOrder, Rest) when Order > OldOrder ->
+ pick_next(Tail, Load, Order, [OldLoad | Rest]);
+select_best(Load, Tail, _Order, OldLoad, OldOrder, Rest) ->
+ pick_next(Tail, OldLoad, OldOrder, [Load | Rest]).
+
+%%----------------------------------------------------------------------
+%% Func: terminate/2
+%% Purpose: Shutdown the server
+%% Returns: any (ignored by gen_server)
+%%----------------------------------------------------------------------
+terminate(Reason, State) ->
+ mnesia_monitor:terminate_proc(?SERVER_NAME, Reason, State).
+
+%%----------------------------------------------------------------------
+%% Func: code_change/3
+%% Purpose: Upgrade process when its code is to be changed
+%% Returns: {ok, NewState}
+%%----------------------------------------------------------------------
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%%----------------------------------------------------------------------
+%%% Internal functions
+%%%----------------------------------------------------------------------
+
+maybe_log_mnesia_down(N) ->
+ %% We use mnesia_down when deciding which tables to load locally,
+ %% so if we are not running (i.e haven't decided which tables
+ %% to load locally), don't log mnesia_down yet.
+ case mnesia_lib:is_running() of
+ yes ->
+ verbose("Logging mnesia_down ~w~n", [N]),
+ mnesia_recover:log_mnesia_down(N),
+ ok;
+ _ ->
+ Filter = fun(Tab) ->
+ inactive_copy_holders(Tab, N)
+ end,
+ HalfLoadedTabs = lists:any(Filter, val({schema, local_tables}) -- [schema]),
+ if
+ HalfLoadedTabs == true ->
+ verbose("Logging mnesia_down ~w~n", [N]),
+ mnesia_recover:log_mnesia_down(N),
+ ok;
+ true ->
+ %% Unfortunately we have not loaded some common
+ %% tables yet, so we cannot rely on the nodedown
+ log_later %% BUGBUG handle this case!!!
+ end
+ end.
+
+inactive_copy_holders(Tab, Node) ->
+ Cs = val({Tab, cstruct}),
+ case mnesia_lib:cs_to_storage_type(Node, Cs) of
+ unknown ->
+ false;
+ _Storage ->
+ mnesia_lib:not_active_here(Tab)
+ end.
+
+orphan_tables([Tab | Tabs], Node, Ns, Local, Remote) ->
+ Cs = val({Tab, cstruct}),
+ CopyHolders = mnesia_lib:copy_holders(Cs),
+ RamCopyHolders = Cs#cstruct.ram_copies,
+ DiscCopyHolders = CopyHolders -- RamCopyHolders,
+ DiscNodes = val({schema, disc_copies}),
+ LocalContent = Cs#cstruct.local_content,
+ RamCopyHoldersOnDiscNodes = mnesia_lib:intersect(RamCopyHolders, DiscNodes),
+ Active = val({Tab, active_replicas}),
+ case lists:member(Node, DiscCopyHolders) of
+ true when Active == [] ->
+ case DiscCopyHolders -- Ns of
+ [] ->
+ %% We're last up and the other nodes have not
+ %% loaded the table. Lets load it if we are
+ %% the smallest node.
+ case lists:min(DiscCopyHolders) of
+ Min when Min == node() ->
+ case mnesia_recover:get_master_nodes(Tab) of
+ [] ->
+ L = [Tab | Local],
+ orphan_tables(Tabs, Node, Ns, L, Remote);
+ Masters ->
+ R = [{Tab, Masters} | Remote],
+ orphan_tables(Tabs, Node, Ns, Local, R)
+ end;
+ _ ->
+ orphan_tables(Tabs, Node, Ns, Local, Remote)
+ end;
+ _ ->
+ orphan_tables(Tabs, Node, Ns, Local, Remote)
+ end;
+ false when Active == [], DiscCopyHolders == [], RamCopyHoldersOnDiscNodes == [] ->
+ %% Special case when all replicas resides on disc less nodes
+ orphan_tables(Tabs, Node, Ns, [Tab | Local], Remote);
+ _ when LocalContent == true ->
+ orphan_tables(Tabs, Node, Ns, [Tab | Local], Remote);
+ _ ->
+ orphan_tables(Tabs, Node, Ns, Local, Remote)
+ end;
+orphan_tables([], _, _, LocalOrphans, RemoteMasters) ->
+ {LocalOrphans, RemoteMasters}.
+
+node_has_tabs([Tab | Tabs], Node, State) when Node /= node() ->
+ State2 = update_whereabouts(Tab, Node, State),
+ node_has_tabs(Tabs, Node, State2);
+node_has_tabs([Tab | Tabs], Node, State) ->
+ user_sync_tab(Tab),
+ node_has_tabs(Tabs, Node, State);
+node_has_tabs([], _Node, State) ->
+ State.
+
+update_whereabouts(Tab, Node, State) ->
+ Storage = val({Tab, storage_type}),
+ Read = val({Tab, where_to_read}),
+ LocalC = val({Tab, local_content}),
+ BeingCreated = (?catch_val({Tab, create_table}) == true),
+ Masters = mnesia_recover:get_master_nodes(Tab),
+ ByForce = val({Tab, load_by_force}),
+ GoGetIt =
+ if
+ ByForce == true ->
+ true;
+ Masters == [] ->
+ true;
+ true ->
+ lists:member(Node, Masters)
+ end,
+
+ dbg_out("Table ~w is loaded on ~w. s=~w, r=~w, lc=~w, f=~w, m=~w~n",
+ [Tab, Node, Storage, Read, LocalC, ByForce, GoGetIt]),
+ if
+ LocalC == true ->
+ %% Local contents, don't care about other node
+ State;
+ Storage == unknown, Read == nowhere ->
+ %% No own copy, time to read remotely
+ %% if the other node is a good node
+ add_active_replica(Tab, Node),
+ case GoGetIt of
+ true ->
+ set({Tab, where_to_read}, Node),
+ user_sync_tab(Tab),
+ State;
+ false ->
+ State
+ end;
+ Storage == unknown ->
+ %% No own copy, continue to read remotely
+ add_active_replica(Tab, Node),
+ NodeST = mnesia_lib:storage_type_at_node(Node, Tab),
+ ReadST = mnesia_lib:storage_type_at_node(Read, Tab),
+ if %% Avoid reading from disc_only_copies
+ NodeST == disc_only_copies ->
+ ignore;
+ ReadST == disc_only_copies ->
+ mnesia_lib:set_remote_where_to_read(Tab);
+ true ->
+ ignore
+ end,
+ user_sync_tab(Tab),
+ State;
+ BeingCreated == true ->
+ %% The table is currently being created
+ %% and we shall have an own copy of it.
+ %% We will load the (empty) table locally.
+ add_active_replica(Tab, Node),
+ State;
+ Read == nowhere ->
+ %% Own copy, go and get a copy of the table
+ %% if the other node is master or if there
+ %% are no master at all
+ add_active_replica(Tab, Node),
+ case GoGetIt of
+ true ->
+ Worker = #net_load{table = Tab,
+ reason = {active_remote, Node}},
+ add_worker(Worker, State);
+ false ->
+ State
+ end;
+ true ->
+ %% We already have an own copy
+ add_active_replica(Tab, Node),
+ user_sync_tab(Tab),
+ State
+ end.
+
+initial_safe_loads() ->
+ case val({schema, storage_type}) of
+ ram_copies ->
+ Downs = [],
+ Tabs = val({schema, local_tables}) -- [schema],
+ LastC = fun(T) -> last_consistent_replica(T, Downs) end,
+ lists:zf(LastC, Tabs);
+
+ disc_copies ->
+ Downs = mnesia_recover:get_mnesia_downs(),
+ dbg_out("mnesia_downs = ~p~n", [Downs]),
+
+ Tabs = val({schema, local_tables}) -- [schema],
+ LastC = fun(T) -> last_consistent_replica(T, Downs) end,
+ lists:zf(LastC, Tabs)
+ end.
+
+last_consistent_replica(Tab, Downs) ->
+ Cs = val({Tab, cstruct}),
+ Storage = mnesia_lib:cs_to_storage_type(node(), Cs),
+ Ram = Cs#cstruct.ram_copies,
+ Disc = Cs#cstruct.disc_copies,
+ DiscOnly = Cs#cstruct.disc_only_copies,
+ BetterCopies0 = mnesia_lib:remote_copy_holders(Cs) -- Downs,
+ BetterCopies = BetterCopies0 -- Ram,
+ AccessMode = Cs#cstruct.access_mode,
+ Copies = mnesia_lib:copy_holders(Cs),
+ Masters = mnesia_recover:get_master_nodes(Tab),
+ LocalMaster0 = lists:member(node(), Masters),
+ LocalContent = Cs#cstruct.local_content,
+ RemoteMaster =
+ if
+ Masters == [] -> false;
+ true -> not LocalMaster0
+ end,
+ LocalMaster =
+ if
+ Masters == [] -> false;
+ true -> LocalMaster0
+ end,
+ if
+ Copies == [node()] ->
+ %% Only one copy holder and it is local.
+ %% It may also be a local contents table
+ {true, {Tab, local_only}};
+ LocalContent == true ->
+ {true, {Tab, local_content}};
+ LocalMaster == true ->
+ %% We have a local master
+ {true, {Tab, local_master}};
+ RemoteMaster == true ->
+ %% Wait for remote master copy
+ false;
+ Storage == ram_copies ->
+ if
+ Disc == [], DiscOnly == [] ->
+ %% Nobody has copy on disc
+ {true, {Tab, ram_only}};
+ true ->
+ %% Some other node has copy on disc
+ false
+ end;
+ AccessMode == read_only ->
+ %% No one has been able to update the table,
+ %% i.e. all disc resident copies are equal
+ {true, {Tab, read_only}};
+ BetterCopies /= [], Masters /= [node()] ->
+ %% There are better copies on other nodes
+ %% and we do not have the only master copy
+ false;
+ true ->
+ {true, {Tab, initial}}
+ end.
+
+reconfigure_tables(N, State, [Tab |Tail]) ->
+ del_active_replica(Tab, N),
+ case val({Tab, where_to_read}) of
+ N -> mnesia_lib:set_remote_where_to_read(Tab);
+ _ -> ignore
+ end,
+ LateQ = drop_loaders(Tab, N, State#state.late_loader_queue),
+ reconfigure_tables(N, State#state{late_loader_queue = LateQ}, Tail);
+
+reconfigure_tables(_, State, []) ->
+ State.
+
+remove_early_messages([], _Node) ->
+ [];
+remove_early_messages([{call, {add_active_replica, [_, Node, _, _], _}, _}|R], Node) ->
+ remove_early_messages(R, Node); %% Does a reply before queuing
+remove_early_messages([{call, {block_table, _, From}, ReplyTo}|R], Node)
+ when node(From) == Node ->
+ reply(ReplyTo, ok), %% Remove gen:server waits..
+ remove_early_messages(R, Node);
+remove_early_messages([{cast, {i_have_tab, _Tab, Node}}|R], Node) ->
+ remove_early_messages(R, Node);
+remove_early_messages([{cast, {adopt_orphans, Node, _Tabs}}|R], Node) ->
+ remove_early_messages(R, Node);
+remove_early_messages([M|R],Node) ->
+ [M|remove_early_messages(R,Node)].
+
+%% Drop loader from late load queue and possibly trigger a disc_load
+drop_loaders(Tab, Node, [H | T]) when H#late_load.table == Tab ->
+ %% Check if it is time to issue a disc_load request
+ case H#late_load.loaders of
+ [Node] ->
+ Reason = {H#late_load.reason, last_loader_down, Node},
+ cast({disc_load, Tab, Reason}); % Ugly cast
+ _ ->
+ ignore
+ end,
+ %% Drop the node from the list of loaders
+ H2 = H#late_load{loaders = H#late_load.loaders -- [Node]},
+ [H2 | drop_loaders(Tab, Node, T)];
+drop_loaders(Tab, Node, [H | T]) ->
+ [H | drop_loaders(Tab, Node, T)];
+drop_loaders(_, _, []) ->
+ [].
+
+add_active_replica(Tab, Node) ->
+ add_active_replica(Tab, Node, val({Tab, cstruct})).
+
+add_active_replica(Tab, Node, Cs) when record(Cs, cstruct) ->
+ Storage = mnesia_lib:schema_cs_to_storage_type(Node, Cs),
+ AccessMode = Cs#cstruct.access_mode,
+ add_active_replica(Tab, Node, Storage, AccessMode).
+
+%% Block table primitives
+
+block_table(Tab) ->
+ Var = {Tab, where_to_commit},
+ Old = val(Var),
+ New = {blocked, Old},
+ set(Var, New). % where_to_commit
+
+unblock_table(Tab) ->
+ Var = {Tab, where_to_commit},
+ New =
+ case val(Var) of
+ {blocked, List} ->
+ List;
+ List ->
+ List
+ end,
+ set(Var, New). % where_to_commit
+
+is_tab_blocked(W2C) when list(W2C) ->
+ {false, W2C};
+is_tab_blocked({blocked, W2C}) when list(W2C) ->
+ {true, W2C}.
+
+mark_blocked_tab(true, Value) ->
+ {blocked, Value};
+mark_blocked_tab(false, Value) ->
+ Value.
+
+%%
+
+add_active_replica(Tab, Node, Storage, AccessMode) ->
+ Var = {Tab, where_to_commit},
+ {Blocked, Old} = is_tab_blocked(val(Var)),
+ Del = lists:keydelete(Node, 1, Old),
+ case AccessMode of
+ read_write ->
+ New = lists:sort([{Node, Storage} | Del]),
+ set(Var, mark_blocked_tab(Blocked, New)), % where_to_commit
+ add({Tab, where_to_write}, Node);
+ read_only ->
+ set(Var, mark_blocked_tab(Blocked, Del)),
+ mnesia_lib:del({Tab, where_to_write}, Node)
+ end,
+ add({Tab, active_replicas}, Node).
+
+del_active_replica(Tab, Node) ->
+ Var = {Tab, where_to_commit},
+ {Blocked, Old} = is_tab_blocked(val(Var)),
+ Del = lists:keydelete(Node, 1, Old),
+ New = lists:sort(Del),
+ set(Var, mark_blocked_tab(Blocked, New)), % where_to_commit
+ mnesia_lib:del({Tab, active_replicas}, Node),
+ mnesia_lib:del({Tab, where_to_write}, Node).
+
+change_table_access_mode(Cs) ->
+ Tab = Cs#cstruct.name,
+ lists:foreach(fun(N) -> add_active_replica(Tab, N, Cs) end,
+ val({Tab, active_replicas})).
+
+%% node To now has tab loaded, but this must be undone
+%% This code is rpc:call'ed from the tab_copier process
+%% when it has *not* released it's table lock
+unannounce_add_table_copy(Tab, To) ->
+ del_active_replica(Tab, To),
+ case val({Tab , where_to_read}) of
+ To ->
+ mnesia_lib:set_remote_where_to_read(Tab);
+ _ ->
+ ignore
+ end.
+
+user_sync_tab(Tab) ->
+ case val(debug) of
+ trace ->
+ mnesia_subscr:subscribe(whereis(mnesia_event), {table, Tab});
+ _ ->
+ ignore
+ end,
+
+ case erase({sync_tab, Tab}) of
+ undefined ->
+ ok;
+ Pids ->
+ lists:foreach(fun(Pid) -> sync_reply(Pid, Tab) end, Pids)
+ end.
+
+i_have_tab(Tab) ->
+ case val({Tab, local_content}) of
+ true ->
+ mnesia_lib:set_local_content_whereabouts(Tab);
+ false ->
+ set({Tab, where_to_read}, node())
+ end,
+ add_active_replica(Tab, node()).
+
+sync_and_block_table_whereabouts(Tab, ToNode, RemoteS, AccessMode) when Tab /= schema ->
+ Current = val({current, db_nodes}),
+ Ns =
+ case lists:member(ToNode, Current) of
+ true -> Current -- [ToNode];
+ false -> Current
+ end,
+ remote_call(ToNode, block_table, [Tab]),
+ [remote_call(Node, add_active_replica, [Tab, ToNode, RemoteS, AccessMode]) ||
+ Node <- [ToNode | Ns]],
+ ok.
+
+sync_del_table_copy_whereabouts(Tab, ToNode) when Tab /= schema ->
+ Current = val({current, db_nodes}),
+ Ns =
+ case lists:member(ToNode, Current) of
+ true -> Current;
+ false -> [ToNode | Current]
+ end,
+ Args = [Tab, ToNode],
+ [remote_call(Node, unannounce_add_table_copy, Args) || Node <- Ns],
+ ok.
+
+get_info(Timeout) ->
+ case whereis(?SERVER_NAME) of
+ undefined ->
+ {timeout, Timeout};
+ Pid ->
+ Pid ! {self(), get_state},
+ receive
+ {?SERVER_NAME, State} when record(State, state) ->
+ {info,State}
+ after Timeout ->
+ {timeout, Timeout}
+ end
+ end.
+
+get_workers(Timeout) ->
+ case whereis(?SERVER_NAME) of
+ undefined ->
+ {timeout, Timeout};
+ Pid ->
+ Pid ! {self(), get_state},
+ receive
+ {?SERVER_NAME, State} when record(State, state) ->
+ {workers, State#state.loader_pid, State#state.sender_pid, State#state.dumper_pid}
+ after Timeout ->
+ {timeout, Timeout}
+ end
+ end.
+
+info() ->
+ Tabs = mnesia_lib:local_active_tables(),
+ io:format( "---> Active tables <--- ~n", []),
+ info(Tabs).
+
+info([Tab | Tail]) ->
+ case val({Tab, storage_type}) of
+ disc_only_copies ->
+ info_format(Tab,
+ dets:info(Tab, size),
+ dets:info(Tab, file_size),
+ "bytes on disc");
+ _ ->
+ info_format(Tab,
+ ?ets_info(Tab, size),
+ ?ets_info(Tab, memory),
+ "words of mem")
+ end,
+ info(Tail);
+info([]) -> ok;
+info(Tab) -> info([Tab]).
+
+info_format(Tab, Size, Mem, Media) ->
+ StrT = mnesia_lib:pad_name(atom_to_list(Tab), 15, []),
+ StrS = mnesia_lib:pad_name(integer_to_list(Size), 8, []),
+ StrM = mnesia_lib:pad_name(integer_to_list(Mem), 8, []),
+ io:format("~s: with ~s records occupying ~s ~s~n",
+ [StrT, StrS, StrM, Media]).
+
+%% Handle early arrived messages
+handle_early_msgs([Msg | Msgs], State) ->
+ %% The messages are in reverse order
+ case handle_early_msg(Msg, State) of
+ {stop, Reason, Reply, State2} ->
+ {stop, Reason, Reply, State2};
+ {stop, Reason, State2} ->
+ {stop, Reason, State2};
+ {noreply, State2} ->
+ handle_early_msgs(Msgs, State2);
+ {noreply, State2, _Timeout} ->
+ handle_early_msgs(Msgs, State2);
+ Else ->
+ dbg_out("handle_early_msgs case clause ~p ~n", [Else]),
+ erlang:error(Else, [[Msg | Msgs], State])
+ end;
+handle_early_msgs([], State) ->
+ noreply(State).
+
+handle_early_msg({call, Msg, From}, State) ->
+ handle_call(Msg, From, State);
+handle_early_msg({cast, Msg}, State) ->
+ handle_cast(Msg, State);
+handle_early_msg({info, Msg}, State) ->
+ handle_info(Msg, State).
+
+noreply(State) ->
+ {noreply, State}.
+
+reply(undefined, Reply) ->
+ Reply;
+reply(ReplyTo, Reply) ->
+ gen_server:reply(ReplyTo, Reply),
+ Reply.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Worker management
+
+%% Returns new State
+add_worker(Worker, State) when record(Worker, dump_log) ->
+ InitBy = Worker#dump_log.initiated_by,
+ Queue = State#state.dumper_queue,
+ case lists:keymember(InitBy, #dump_log.initiated_by, Queue) of
+ false ->
+ ignore;
+ true when Worker#dump_log.opt_reply_to == undefined ->
+ %% The same threshold has been exceeded again,
+ %% before we have had the possibility to
+ %% process the older one.
+ DetectedBy = {dump_log, InitBy},
+ Event = {mnesia_overload, DetectedBy},
+ mnesia_lib:report_system_event(Event)
+ end,
+ Queue2 = Queue ++ [Worker],
+ State2 = State#state{dumper_queue = Queue2},
+ opt_start_worker(State2);
+add_worker(Worker, State) when record(Worker, schema_commit_lock) ->
+ Queue = State#state.dumper_queue,
+ Queue2 = Queue ++ [Worker],
+ State2 = State#state{dumper_queue = Queue2},
+ opt_start_worker(State2);
+add_worker(Worker, State) when record(Worker, net_load) ->
+ Queue = State#state.loader_queue,
+ State2 = State#state{loader_queue = Queue ++ [Worker]},
+ opt_start_worker(State2);
+add_worker(Worker, State) when record(Worker, send_table) ->
+ Queue = State#state.sender_queue,
+ State2 = State#state{sender_queue = Queue ++ [Worker]},
+ opt_start_worker(State2);
+add_worker(Worker, State) when record(Worker, disc_load) ->
+ Queue = State#state.loader_queue,
+ State2 = State#state{loader_queue = Queue ++ [Worker]},
+ opt_start_worker(State2);
+% Block controller should be used for upgrading mnesia.
+add_worker(Worker, State) when record(Worker, block_controller) ->
+ Queue = State#state.dumper_queue,
+ Queue2 = [Worker | Queue],
+ State2 = State#state{dumper_queue = Queue2},
+ opt_start_worker(State2).
+
+%% Optionally start a worker
+%%
+%% Dumpers and loaders may run simultaneously
+%% but neither of them may run during schema commit.
+%% Loaders may not start if a schema commit is enqueued.
+opt_start_worker(State) when State#state.is_stopping == true ->
+ State;
+opt_start_worker(State) ->
+ %% Prioritize dumper and schema commit
+ %% by checking them first
+ case State#state.dumper_queue of
+ [Worker | _Rest] when State#state.dumper_pid == undefined ->
+ %% Great, a worker in queue and neither
+ %% a schema transaction is being
+ %% committed and nor a dumper is running
+
+ %% Start worker but keep him in the queue
+ if
+ record(Worker, schema_commit_lock) ->
+ ReplyTo = Worker#schema_commit_lock.owner,
+ reply(ReplyTo, granted),
+ {Owner, _Tag} = ReplyTo,
+ State#state{dumper_pid = Owner};
+
+ record(Worker, dump_log) ->
+ Pid = spawn_link(?MODULE, dump_and_reply, [self(), Worker]),
+ State2 = State#state{dumper_pid = Pid},
+
+ %% If the worker was a dumper we may
+ %% possibly be able to start a loader
+ %% or sender
+ State3 = opt_start_sender(State2),
+ opt_start_loader(State3);
+
+ record(Worker, block_controller) ->
+ case {State#state.sender_pid, State#state.loader_pid} of
+ {undefined, undefined} ->
+ ReplyTo = Worker#block_controller.owner,
+ reply(ReplyTo, granted),
+ {Owner, _Tag} = ReplyTo,
+ State#state{dumper_pid = Owner};
+ _ ->
+ State
+ end
+ end;
+ _ ->
+ %% Bad luck, try with a loader or sender instead
+ State2 = opt_start_sender(State),
+ opt_start_loader(State2)
+ end.
+
+opt_start_sender(State) ->
+ case State#state.sender_queue of
+ []->
+ %% No need
+ State;
+
+ _ when State#state.sender_pid /= undefined ->
+ %% Bad luck, a sender is already running
+ State;
+
+ [Sender | _SenderRest] ->
+ case State#state.loader_queue of
+ [Loader | _LoaderRest]
+ when State#state.loader_pid /= undefined,
+ Loader#net_load.table == Sender#send_table.table ->
+ %% A conflicting loader is running
+ State;
+ _ ->
+ SchemaQueue = State#state.dumper_queue,
+ case lists:keymember(schema_commit, 1, SchemaQueue) of
+ false ->
+
+ %% Start worker but keep him in the queue
+ Pid = spawn_link(?MODULE, send_and_reply,
+ [self(), Sender]),
+ State#state{sender_pid = Pid};
+ true ->
+ %% Bad luck, we must wait for the schema commit
+ State
+ end
+ end
+ end.
+
+opt_start_loader(State) ->
+ LoaderQueue = State#state.loader_queue,
+ if
+ LoaderQueue == [] ->
+ %% No need
+ State;
+
+ State#state.loader_pid /= undefined ->
+ %% Bad luck, an loader is already running
+ State;
+
+ true ->
+ SchemaQueue = State#state.dumper_queue,
+ case lists:keymember(schema_commit, 1, SchemaQueue) of
+ false ->
+ {Worker, Rest} = pick_next(LoaderQueue),
+
+ %% Start worker but keep him in the queue
+ Pid = spawn_link(?MODULE, load_and_reply, [self(), Worker]),
+ State#state{loader_pid = Pid,
+ loader_queue = [Worker | Rest]};
+ true ->
+ %% Bad luck, we must wait for the schema commit
+ State
+ end
+ end.
+
+start_remote_sender(Node, Tab, Receiver, Storage) ->
+ Msg = #send_table{table = Tab,
+ receiver_pid = Receiver,
+ remote_storage = Storage},
+ gen_server:cast({?SERVER_NAME, Node}, Msg).
+
+dump_and_reply(ReplyTo, Worker) ->
+ %% No trap_exit, die intentionally instead
+ Res = mnesia_dumper:opt_dump_log(Worker#dump_log.initiated_by),
+ ReplyTo ! #dumper_done{worker_pid = self(),
+ worker_res = Res},
+ unlink(ReplyTo),
+ exit(normal).
+
+send_and_reply(ReplyTo, Worker) ->
+ %% No trap_exit, die intentionally instead
+ Res = mnesia_loader:send_table(Worker#send_table.receiver_pid,
+ Worker#send_table.table,
+ Worker#send_table.remote_storage),
+ ReplyTo ! #sender_done{worker_pid = self(),
+ worker_res = Res},
+ unlink(ReplyTo),
+ exit(normal).
+
+
+load_and_reply(ReplyTo, Worker) ->
+ process_flag(trap_exit, true),
+ Done = load_table(Worker),
+ ReplyTo ! Done#loader_done{worker_pid = self()},
+ unlink(ReplyTo),
+ exit(normal).
+
+%% Now it is time to load the table
+%% but first we must check if it still is neccessary
+load_table(Load) when record(Load, net_load) ->
+ Tab = Load#net_load.table,
+ ReplyTo = Load#net_load.opt_reply_to,
+ Reason = Load#net_load.reason,
+ LocalC = val({Tab, local_content}),
+ AccessMode = val({Tab, access_mode}),
+ ReadNode = val({Tab, where_to_read}),
+ Active = filter_active(Tab),
+ Done = #loader_done{is_loaded = true,
+ table_name = Tab,
+ needs_announce = false,
+ needs_sync = false,
+ needs_reply = true,
+ reply_to = ReplyTo,
+ reply = {loaded, ok}
+ },
+ if
+ ReadNode == node() ->
+ %% Already loaded locally
+ Done;
+ LocalC == true ->
+ Res = mnesia_loader:disc_load_table(Tab, load_local_content),
+ Done#loader_done{reply = Res, needs_announce = true, needs_sync = true};
+ AccessMode == read_only ->
+ disc_load_table(Tab, Reason, ReplyTo);
+ true ->
+ %% Either we cannot read the table yet
+ %% or someone is moving a replica between
+ %% two nodes
+ Cs = Load#net_load.cstruct,
+ Res = mnesia_loader:net_load_table(Tab, Reason, Active, Cs),
+ case Res of
+ {loaded, ok} ->
+ Done#loader_done{needs_sync = true,
+ reply = Res};
+ {not_loaded, storage_unknown} ->
+ Done#loader_done{reply = Res};
+ {not_loaded, _} ->
+ Done#loader_done{is_loaded = false,
+ needs_reply = false,
+ reply = Res}
+ end
+ end;
+
+load_table(Load) when record(Load, disc_load) ->
+ Tab = Load#disc_load.table,
+ Reason = Load#disc_load.reason,
+ ReplyTo = Load#disc_load.opt_reply_to,
+ ReadNode = val({Tab, where_to_read}),
+ Active = filter_active(Tab),
+ Done = #loader_done{is_loaded = true,
+ table_name = Tab,
+ needs_announce = false,
+ needs_sync = false,
+ needs_reply = false
+ },
+ if
+ Active == [], ReadNode == nowhere ->
+ %% Not loaded anywhere, lets load it from disc
+ disc_load_table(Tab, Reason, ReplyTo);
+ ReadNode == nowhere ->
+ %% Already loaded on other node, lets get it
+ Cs = val({Tab, cstruct}),
+ case mnesia_loader:net_load_table(Tab, Reason, Active, Cs) of
+ {loaded, ok} ->
+ Done#loader_done{needs_sync = true};
+ {not_loaded, storage_unknown} ->
+ Done#loader_done{is_loaded = false};
+ {not_loaded, ErrReason} ->
+ Done#loader_done{is_loaded = false,
+ reply = {not_loaded,ErrReason}}
+ end;
+ true ->
+ %% Already readable, do not worry be happy
+ Done
+ end.
+
+disc_load_table(Tab, Reason, ReplyTo) ->
+ Done = #loader_done{is_loaded = true,
+ table_name = Tab,
+ needs_announce = false,
+ needs_sync = false,
+ needs_reply = true,
+ reply_to = ReplyTo,
+ reply = {loaded, ok}
+ },
+ Res = mnesia_loader:disc_load_table(Tab, Reason),
+ if
+ Res == {loaded, ok} ->
+ Done#loader_done{needs_announce = true,
+ needs_sync = true,
+ reply = Res};
+ ReplyTo /= undefined ->
+ Done#loader_done{is_loaded = false,
+ reply = Res};
+ true ->
+ fatal("Cannot load table ~p from disc: ~p~n", [Tab, Res])
+ end.
+
+filter_active(Tab) ->
+ ByForce = val({Tab, load_by_force}),
+ Active = val({Tab, active_replicas}),
+ Masters = mnesia_recover:get_master_nodes(Tab),
+ do_filter_active(ByForce, Active, Masters).
+
+do_filter_active(true, Active, _Masters) ->
+ Active;
+do_filter_active(false, Active, []) ->
+ Active;
+do_filter_active(false, Active, Masters) ->
+ mnesia_lib:intersect(Active, Masters).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_dumper.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_dumper.erl
new file mode 100644
index 0000000000..116823a779
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_dumper.erl
@@ -0,0 +1,1092 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_dumper.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
+%%
+-module(mnesia_dumper).
+
+%% The InitBy arg may be one of the following:
+%% scan_decisions Initial scan for decisions
+%% startup Initial dump during startup
+%% schema_prepare Dump initiated during schema transaction preparation
+%% schema_update Dump initiated during schema transaction commit
+%% fast_schema_update A schema_update, but ignores the log file
+%% user Dump initiated by user
+%% write_threshold Automatic dump caused by too many log writes
+%% time_threshold Automatic dump caused by timeout
+
+%% Public interface
+-export([
+ get_log_writes/0,
+ incr_log_writes/0,
+ raw_dump_table/2,
+ raw_named_dump_table/2,
+ start_regulator/0,
+ opt_dump_log/1,
+ update/3
+ ]).
+
+ %% Internal stuff
+-export([regulator_init/1]).
+
+-include("mnesia.hrl").
+-include_lib("kernel/include/file.hrl").
+
+-import(mnesia_lib, [fatal/2, dbg_out/2]).
+
+-define(REGULATOR_NAME, mnesia_dumper_load_regulator).
+-define(DumpToEtsMultiplier, 4).
+
+-record(state, {initiated_by = nobody,
+ dumper = nopid,
+ regulator_pid,
+ supervisor_pid,
+ queue = [],
+ timeout}).
+
+get_log_writes() ->
+ Max = mnesia_monitor:get_env(dump_log_write_threshold),
+ Prev = mnesia_lib:read_counter(trans_log_writes),
+ Left = mnesia_lib:read_counter(trans_log_writes_left),
+ Diff = Max - Left,
+ Prev + Diff.
+
+incr_log_writes() ->
+ Left = mnesia_lib:incr_counter(trans_log_writes_left, -1),
+ if
+ Left > 0 ->
+ ignore;
+ true ->
+ adjust_log_writes(true)
+ end.
+
+adjust_log_writes(DoCast) ->
+ Token = {mnesia_adjust_log_writes, self()},
+ case global:set_lock(Token, [node()], 1) of
+ false ->
+ ignore; %% Somebody else is sending a dump request
+ true ->
+ case DoCast of
+ false ->
+ ignore;
+ true ->
+ mnesia_controller:async_dump_log(write_threshold)
+ end,
+ Max = mnesia_monitor:get_env(dump_log_write_threshold),
+ Left = mnesia_lib:read_counter(trans_log_writes_left),
+ %% Don't care if we lost a few writes
+ mnesia_lib:set_counter(trans_log_writes_left, Max),
+ Diff = Max - Left,
+ mnesia_lib:incr_counter(trans_log_writes, Diff),
+ global:del_lock(Token, [node()])
+ end.
+
+%% Returns 'ok' or exits
+opt_dump_log(InitBy) ->
+ Reg = case whereis(?REGULATOR_NAME) of
+ undefined ->
+ nopid;
+ Pid when pid(Pid) ->
+ Pid
+ end,
+ perform_dump(InitBy, Reg).
+
+%% Scan for decisions
+perform_dump(InitBy, Regulator) when InitBy == scan_decisions ->
+ ?eval_debug_fun({?MODULE, perform_dump}, [InitBy]),
+
+ dbg_out("Transaction log dump initiated by ~w~n", [InitBy]),
+ scan_decisions(mnesia_log:previous_log_file(), InitBy, Regulator),
+ scan_decisions(mnesia_log:latest_log_file(), InitBy, Regulator);
+
+%% Propagate the log into the DAT-files
+perform_dump(InitBy, Regulator) ->
+ ?eval_debug_fun({?MODULE, perform_dump}, [InitBy]),
+ LogState = mnesia_log:prepare_log_dump(InitBy),
+ dbg_out("Transaction log dump initiated by ~w: ~w~n",
+ [InitBy, LogState]),
+ adjust_log_writes(false),
+ mnesia_recover:allow_garb(),
+ case LogState of
+ already_dumped ->
+ dumped;
+ {needs_dump, Diff} ->
+ U = mnesia_monitor:get_env(dump_log_update_in_place),
+ Cont = mnesia_log:init_log_dump(),
+ case catch do_perform_dump(Cont, U, InitBy, Regulator, undefined) of
+ ok ->
+ ?eval_debug_fun({?MODULE, post_dump}, [InitBy]),
+ case mnesia_monitor:use_dir() of
+ true ->
+ mnesia_recover:dump_decision_tab();
+ false ->
+ mnesia_log:purge_some_logs()
+ end,
+ %% And now to the crucial point...
+ mnesia_log:confirm_log_dump(Diff);
+ {error, Reason} ->
+ {error, Reason};
+ {'EXIT', {Desc, Reason}} ->
+ case mnesia_monitor:get_env(auto_repair) of
+ true ->
+ mnesia_lib:important(Desc, Reason),
+ %% Ignore rest of the log
+ mnesia_log:confirm_log_dump(Diff);
+ false ->
+ fatal(Desc, Reason)
+ end
+ end;
+ {error, Reason} ->
+ {error, {"Cannot prepare log dump", Reason}}
+ end.
+
+scan_decisions(Fname, InitBy, Regulator) ->
+ Exists = mnesia_lib:exists(Fname),
+ case Exists of
+ false ->
+ ok;
+ true ->
+ Header = mnesia_log:trans_log_header(),
+ Name = previous_log,
+ mnesia_log:open_log(Name, Header, Fname, Exists,
+ mnesia_monitor:get_env(auto_repair), read_only),
+ Cont = start,
+ Res = (catch do_perform_dump(Cont, false, InitBy, Regulator, undefined)),
+ mnesia_log:close_log(Name),
+ case Res of
+ ok -> ok;
+ {'EXIT', Reason} -> {error, Reason}
+ end
+ end.
+
+do_perform_dump(Cont, InPlace, InitBy, Regulator, OldVersion) ->
+ case mnesia_log:chunk_log(Cont) of
+ {C2, Recs} ->
+ case catch insert_recs(Recs, InPlace, InitBy, Regulator, OldVersion) of
+ {'EXIT', R} ->
+ Reason = {"Transaction log dump error: ~p~n", [R]},
+ close_files(InPlace, {error, Reason}, InitBy),
+ exit(Reason);
+ Version ->
+ do_perform_dump(C2, InPlace, InitBy, Regulator, Version)
+ end;
+ eof ->
+ close_files(InPlace, ok, InitBy),
+ ok
+ end.
+
+insert_recs([Rec | Recs], InPlace, InitBy, Regulator, LogV) ->
+ regulate(Regulator),
+ case insert_rec(Rec, InPlace, InitBy, LogV) of
+ LogH when record(LogH, log_header) ->
+ insert_recs(Recs, InPlace, InitBy, Regulator, LogH#log_header.log_version);
+ _ ->
+ insert_recs(Recs, InPlace, InitBy, Regulator, LogV)
+ end;
+
+insert_recs([], _InPlace, _InitBy, _Regulator, Version) ->
+ Version.
+
+insert_rec(Rec, _InPlace, scan_decisions, _LogV) ->
+ if
+ record(Rec, commit) ->
+ ignore;
+ record(Rec, log_header) ->
+ ignore;
+ true ->
+ mnesia_recover:note_log_decision(Rec, scan_decisions)
+ end;
+insert_rec(Rec, InPlace, InitBy, LogV) when record(Rec, commit) ->
+ %% Determine the Outcome of the transaction and recover it
+ D = Rec#commit.decision,
+ case mnesia_recover:wait_for_decision(D, InitBy) of
+ {Tid, committed} ->
+ do_insert_rec(Tid, Rec, InPlace, InitBy, LogV);
+ {Tid, aborted} ->
+ mnesia_schema:undo_prepare_commit(Tid, Rec)
+ end;
+insert_rec(H, _InPlace, _InitBy, _LogV) when record(H, log_header) ->
+ CurrentVersion = mnesia_log:version(),
+ if
+ H#log_header.log_kind /= trans_log ->
+ exit({"Bad kind of transaction log", H});
+ H#log_header.log_version == CurrentVersion ->
+ ok;
+ H#log_header.log_version == "4.2" ->
+ ok;
+ H#log_header.log_version == "4.1" ->
+ ok;
+ H#log_header.log_version == "4.0" ->
+ ok;
+ true ->
+ fatal("Bad version of transaction log: ~p~n", [H])
+ end,
+ H;
+
+insert_rec(_Rec, _InPlace, _InitBy, _LogV) ->
+ ok.
+
+do_insert_rec(Tid, Rec, InPlace, InitBy, LogV) ->
+ case Rec#commit.schema_ops of
+ [] ->
+ ignore;
+ SchemaOps ->
+ case val({schema, storage_type}) of
+ ram_copies ->
+ insert_ops(Tid, schema_ops, SchemaOps, InPlace, InitBy, LogV);
+ Storage ->
+ true = open_files(schema, Storage, InPlace, InitBy),
+ insert_ops(Tid, schema_ops, SchemaOps, InPlace, InitBy, LogV)
+ end
+ end,
+ D = Rec#commit.disc_copies,
+ insert_ops(Tid, disc_copies, D, InPlace, InitBy, LogV),
+ case InitBy of
+ startup ->
+ DO = Rec#commit.disc_only_copies,
+ insert_ops(Tid, disc_only_copies, DO, InPlace, InitBy, LogV);
+ _ ->
+ ignore
+ end.
+
+
+update(_Tid, [], _DumperMode) ->
+ dumped;
+update(Tid, SchemaOps, DumperMode) ->
+ UseDir = mnesia_monitor:use_dir(),
+ Res = perform_update(Tid, SchemaOps, DumperMode, UseDir),
+ mnesia_controller:release_schema_commit_lock(),
+ Res.
+
+perform_update(_Tid, _SchemaOps, mandatory, true) ->
+ %% Force a dump of the transaction log in order to let the
+ %% dumper perform needed updates
+
+ InitBy = schema_update,
+ ?eval_debug_fun({?MODULE, dump_schema_op}, [InitBy]),
+ opt_dump_log(InitBy);
+perform_update(Tid, SchemaOps, _DumperMode, _UseDir) ->
+ %% No need for a full transaction log dump.
+ %% Ignore the log file and perform only perform
+ %% the corresponding updates.
+
+ InitBy = fast_schema_update,
+ InPlace = mnesia_monitor:get_env(dump_log_update_in_place),
+ ?eval_debug_fun({?MODULE, dump_schema_op}, [InitBy]),
+ case catch insert_ops(Tid, schema_ops, SchemaOps, InPlace, InitBy,
+ mnesia_log:version()) of
+ {'EXIT', Reason} ->
+ Error = {error, {"Schema update error", Reason}},
+ close_files(InPlace, Error, InitBy),
+ fatal("Schema update error ~p ~p", [Reason, SchemaOps]);
+ _ ->
+ ?eval_debug_fun({?MODULE, post_dump}, [InitBy]),
+ close_files(InPlace, ok, InitBy),
+ ok
+ end.
+
+insert_ops(_Tid, _Storage, [], _InPlace, _InitBy, _) -> ok;
+insert_ops(Tid, Storage, [Op], InPlace, InitBy, Ver) when Ver >= "4.3"->
+ insert_op(Tid, Storage, Op, InPlace, InitBy),
+ ok;
+insert_ops(Tid, Storage, [Op | Ops], InPlace, InitBy, Ver) when Ver >= "4.3"->
+ insert_op(Tid, Storage, Op, InPlace, InitBy),
+ insert_ops(Tid, Storage, Ops, InPlace, InitBy, Ver);
+insert_ops(Tid, Storage, [Op | Ops], InPlace, InitBy, Ver) when Ver < "4.3" ->
+ insert_ops(Tid, Storage, Ops, InPlace, InitBy, Ver),
+ insert_op(Tid, Storage, Op, InPlace, InitBy).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Normal ops
+
+disc_insert(_Tid, Storage, Tab, Key, Val, Op, InPlace, InitBy) ->
+ case open_files(Tab, Storage, InPlace, InitBy) of
+ true ->
+ case Storage of
+ disc_copies when Tab /= schema ->
+ mnesia_log:append({?MODULE,Tab}, {{Tab, Key}, Val, Op}),
+ ok;
+ _ ->
+ case Op of
+ write ->
+ ok = dets:insert(Tab, Val);
+ delete ->
+ ok = dets:delete(Tab, Key);
+ update_counter ->
+ {RecName, Incr} = Val,
+ case catch dets:update_counter(Tab, Key, Incr) of
+ CounterVal when integer(CounterVal) ->
+ ok;
+ _ ->
+ Zero = {RecName, Key, 0},
+ ok = dets:insert(Tab, Zero)
+ end;
+ delete_object ->
+ ok = dets:delete_object(Tab, Val);
+ clear_table ->
+ ok = dets:match_delete(Tab, '_')
+ end
+ end;
+ false ->
+ ignore
+ end.
+
+insert(Tid, Storage, Tab, Key, [Val | Tail], Op, InPlace, InitBy) ->
+ insert(Tid, Storage, Tab, Key, Val, Op, InPlace, InitBy),
+ insert(Tid, Storage, Tab, Key, Tail, Op, InPlace, InitBy);
+
+insert(_Tid, _Storage, _Tab, _Key, [], _Op, _InPlace, _InitBy) ->
+ ok;
+
+insert(Tid, Storage, Tab, Key, Val, Op, InPlace, InitBy) ->
+ Item = {{Tab, Key}, Val, Op},
+ case InitBy of
+ startup ->
+ disc_insert(Tid, Storage, Tab, Key, Val, Op, InPlace, InitBy);
+
+ _ when Storage == ram_copies ->
+ mnesia_tm:do_update_op(Tid, Storage, Item),
+ Snmp = mnesia_tm:prepare_snmp(Tab, Key, [Item]),
+ mnesia_tm:do_snmp(Tid, Snmp);
+
+ _ when Storage == disc_copies ->
+ disc_insert(Tid, Storage, Tab, Key, Val, Op, InPlace, InitBy),
+ mnesia_tm:do_update_op(Tid, Storage, Item),
+ Snmp = mnesia_tm:prepare_snmp(Tab, Key, [Item]),
+ mnesia_tm:do_snmp(Tid, Snmp);
+
+ _ when Storage == disc_only_copies ->
+ mnesia_tm:do_update_op(Tid, Storage, Item),
+ Snmp = mnesia_tm:prepare_snmp(Tab, Key, [Item]),
+ mnesia_tm:do_snmp(Tid, Snmp);
+
+ _ when Storage == unknown ->
+ ignore
+ end.
+
+disc_delete_table(Tab, Storage) ->
+ case mnesia_monitor:use_dir() of
+ true ->
+ if
+ Storage == disc_only_copies; Tab == schema ->
+ mnesia_monitor:unsafe_close_dets(Tab),
+ Dat = mnesia_lib:tab2dat(Tab),
+ file:delete(Dat);
+ true ->
+ DclFile = mnesia_lib:tab2dcl(Tab),
+ case get({?MODULE,Tab}) of
+ {opened_dumper, dcl} ->
+ del_opened_tab(Tab),
+ mnesia_log:unsafe_close_log(Tab);
+ _ ->
+ ok
+ end,
+ file:delete(DclFile),
+ DcdFile = mnesia_lib:tab2dcd(Tab),
+ file:delete(DcdFile),
+ ok
+ end,
+ erase({?MODULE, Tab});
+ false ->
+ ignore
+ end.
+
+disc_delete_indecies(_Tab, _Cs, Storage) when Storage /= disc_only_copies ->
+ ignore;
+disc_delete_indecies(Tab, Cs, disc_only_copies) ->
+ Indecies = Cs#cstruct.index,
+ mnesia_index:del_transient(Tab, Indecies, disc_only_copies).
+
+insert_op(Tid, Storage, {{Tab, Key}, Val, Op}, InPlace, InitBy) ->
+ %% Propagate to disc only
+ disc_insert(Tid, Storage, Tab, Key, Val, Op, InPlace, InitBy);
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% NOTE that all operations below will only
+%% be performed if the dump is initiated by
+%% startup or fast_schema_update
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+insert_op(_Tid, schema_ops, _OP, _InPlace, Initby)
+ when Initby /= startup,
+ Initby /= fast_schema_update,
+ Initby /= schema_update ->
+ ignore;
+
+insert_op(Tid, _, {op, rec, Storage, Item}, InPlace, InitBy) ->
+ {{Tab, Key}, ValList, Op} = Item,
+ insert(Tid, Storage, Tab, Key, ValList, Op, InPlace, InitBy);
+
+insert_op(Tid, _, {op, change_table_copy_type, N, FromS, ToS, TabDef}, InPlace, InitBy) ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ Val = mnesia_schema:insert_cstruct(Tid, Cs, true), % Update ram only
+ {schema, Tab, _} = Val,
+ if
+ InitBy /= startup ->
+ mnesia_controller:add_active_replica(Tab, N, Cs);
+ true ->
+ ignore
+ end,
+ if
+ N == node() ->
+ Dmp = mnesia_lib:tab2dmp(Tab),
+ Dat = mnesia_lib:tab2dat(Tab),
+ Dcd = mnesia_lib:tab2dcd(Tab),
+ Dcl = mnesia_lib:tab2dcl(Tab),
+ case {FromS, ToS} of
+ {ram_copies, disc_copies} when Tab == schema ->
+ ok = ensure_rename(Dmp, Dat);
+ {ram_copies, disc_copies} ->
+ file:delete(Dcl),
+ ok = ensure_rename(Dmp, Dcd);
+ {disc_copies, ram_copies} when Tab == schema ->
+ mnesia_lib:set(use_dir, false),
+ mnesia_monitor:unsafe_close_dets(Tab),
+ file:delete(Dat);
+ {disc_copies, ram_copies} ->
+ file:delete(Dcl),
+ file:delete(Dcd);
+ {ram_copies, disc_only_copies} ->
+ ok = ensure_rename(Dmp, Dat),
+ true = open_files(Tab, disc_only_copies, InPlace, InitBy),
+ %% ram_delete_table must be done before init_indecies,
+ %% it uses info which is reset in init_indecies,
+ %% it doesn't matter, because init_indecies don't use
+ %% the ram replica of the table when creating the disc
+ %% index; Could be improved :)
+ mnesia_schema:ram_delete_table(Tab, FromS),
+ PosList = Cs#cstruct.index,
+ mnesia_index:init_indecies(Tab, disc_only_copies, PosList);
+ {disc_only_copies, ram_copies} ->
+ mnesia_monitor:unsafe_close_dets(Tab),
+ disc_delete_indecies(Tab, Cs, disc_only_copies),
+ case InitBy of
+ startup ->
+ ignore;
+ _ ->
+ mnesia_controller:get_disc_copy(Tab)
+ end,
+ disc_delete_table(Tab, disc_only_copies);
+ {disc_copies, disc_only_copies} ->
+ ok = ensure_rename(Dmp, Dat),
+ true = open_files(Tab, disc_only_copies, InPlace, InitBy),
+ mnesia_schema:ram_delete_table(Tab, FromS),
+ PosList = Cs#cstruct.index,
+ mnesia_index:init_indecies(Tab, disc_only_copies, PosList),
+ file:delete(Dcl),
+ file:delete(Dcd);
+ {disc_only_copies, disc_copies} ->
+ mnesia_monitor:unsafe_close_dets(Tab),
+ disc_delete_indecies(Tab, Cs, disc_only_copies),
+ case InitBy of
+ startup ->
+ ignore;
+ _ ->
+ mnesia_log:ets2dcd(Tab),
+ mnesia_controller:get_disc_copy(Tab),
+ disc_delete_table(Tab, disc_only_copies)
+ end
+ end;
+ true ->
+ ignore
+ end,
+ S = val({schema, storage_type}),
+ disc_insert(Tid, S, schema, Tab, Val, write, InPlace, InitBy);
+
+insert_op(Tid, _, {op, transform, _Fun, TabDef}, InPlace, InitBy) ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ case mnesia_lib:cs_to_storage_type(node(), Cs) of
+ disc_copies ->
+ open_dcl(Cs#cstruct.name);
+ _ ->
+ ignore
+ end,
+ insert_cstruct(Tid, Cs, true, InPlace, InitBy);
+
+%%% Operations below this are handled without using the logg.
+
+insert_op(Tid, _, {op, restore_recreate, TabDef}, InPlace, InitBy) ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ Tab = Cs#cstruct.name,
+ Type = Cs#cstruct.type,
+ Storage = mnesia_lib:cs_to_storage_type(node(), Cs),
+ %% Delete all possbibly existing files and tables
+ disc_delete_table(Tab, Storage),
+ disc_delete_indecies(Tab, Cs, Storage),
+ case InitBy of
+ startup ->
+ ignore;
+ _ ->
+ mnesia_schema:ram_delete_table(Tab, Storage),
+ mnesia_checkpoint:tm_del_copy(Tab, node())
+ end,
+ %% delete_cstruct(Tid, Cs, InPlace, InitBy),
+ %% And create new ones..
+ if
+ (InitBy == startup) or (Storage == unknown) ->
+ ignore;
+ Storage == ram_copies ->
+ Args = [{keypos, 2}, public, named_table, Type],
+ mnesia_monitor:mktab(Tab, Args);
+ Storage == disc_copies ->
+ Args = [{keypos, 2}, public, named_table, Type],
+ mnesia_monitor:mktab(Tab, Args),
+ File = mnesia_lib:tab2dcd(Tab),
+ FArg = [{file, File}, {name, {mnesia,create}},
+ {repair, false}, {mode, read_write}],
+ {ok, Log} = mnesia_monitor:open_log(FArg),
+ mnesia_monitor:unsafe_close_log(Log);
+ Storage == disc_only_copies ->
+ File = mnesia_lib:tab2dat(Tab),
+ file:delete(File),
+ Args = [{file, mnesia_lib:tab2dat(Tab)},
+ {type, mnesia_lib:disk_type(Tab, Type)},
+ {keypos, 2},
+ {repair, mnesia_monitor:get_env(auto_repair)}],
+ mnesia_monitor:open_dets(Tab, Args)
+ end,
+ insert_op(Tid, ignore, {op, create_table, TabDef}, InPlace, InitBy);
+
+insert_op(Tid, _, {op, create_table, TabDef}, InPlace, InitBy) ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ insert_cstruct(Tid, Cs, false, InPlace, InitBy),
+ Tab = Cs#cstruct.name,
+ Storage = mnesia_lib:cs_to_storage_type(node(), Cs),
+ case InitBy of
+ startup ->
+ case Storage of
+ unknown ->
+ ignore;
+ ram_copies ->
+ ignore;
+ disc_copies ->
+ Dcd = mnesia_lib:tab2dcd(Tab),
+ case mnesia_lib:exists(Dcd) of
+ true -> ignore;
+ false ->
+ mnesia_log:open_log(temp,
+ mnesia_log:dcl_log_header(),
+ Dcd,
+ false,
+ false,
+ read_write),
+ mnesia_log:unsafe_close_log(temp)
+ end;
+ _ ->
+ Args = [{file, mnesia_lib:tab2dat(Tab)},
+ {type, mnesia_lib:disk_type(Tab, Cs#cstruct.type)},
+ {keypos, 2},
+ {repair, mnesia_monitor:get_env(auto_repair)}],
+ case mnesia_monitor:open_dets(Tab, Args) of
+ {ok, _} ->
+ mnesia_monitor:unsafe_close_dets(Tab);
+ {error, Error} ->
+ exit({"Failed to create dets table", Error})
+ end
+ end;
+ _ ->
+ Copies = mnesia_lib:copy_holders(Cs),
+ Active = mnesia_lib:intersect(Copies, val({current, db_nodes})),
+ [mnesia_controller:add_active_replica(Tab, N, Cs) || N <- Active],
+
+ case Storage of
+ unknown ->
+ case Cs#cstruct.local_content of
+ true ->
+ ignore;
+ false ->
+ mnesia_lib:set_remote_where_to_read(Tab)
+ end;
+ _ ->
+ case Cs#cstruct.local_content of
+ true ->
+ mnesia_lib:set_local_content_whereabouts(Tab);
+ false ->
+ mnesia_lib:set({Tab, where_to_read}, node())
+ end,
+ case Storage of
+ ram_copies ->
+ ignore;
+ _ ->
+ %% Indecies are still created by loader
+ disc_delete_indecies(Tab, Cs, Storage)
+ %% disc_delete_table(Tab, Storage)
+ end,
+
+ %% Update whereabouts and create table
+ mnesia_controller:create_table(Tab)
+ end
+ end;
+
+insert_op(_Tid, _, {op, dump_table, Size, TabDef}, _InPlace, _InitBy) ->
+ case Size of
+ unknown ->
+ ignore;
+ _ ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ Tab = Cs#cstruct.name,
+ Dmp = mnesia_lib:tab2dmp(Tab),
+ Dat = mnesia_lib:tab2dcd(Tab),
+ case Size of
+ 0 ->
+ %% Assume that table files already are closed
+ file:delete(Dmp),
+ file:delete(Dat);
+ _ ->
+ ok = ensure_rename(Dmp, Dat)
+ end
+ end;
+
+insert_op(Tid, _, {op, delete_table, TabDef}, InPlace, InitBy) ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ Tab = Cs#cstruct.name,
+ case mnesia_lib:cs_to_storage_type(node(), Cs) of
+ unknown ->
+ ignore;
+ Storage ->
+ disc_delete_table(Tab, Storage),
+ disc_delete_indecies(Tab, Cs, Storage),
+ case InitBy of
+ startup ->
+ ignore;
+ _ ->
+ mnesia_schema:ram_delete_table(Tab, Storage),
+ mnesia_checkpoint:tm_del_copy(Tab, node())
+ end
+ end,
+ delete_cstruct(Tid, Cs, InPlace, InitBy);
+
+insert_op(Tid, _, {op, clear_table, TabDef}, InPlace, InitBy) ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ Tab = Cs#cstruct.name,
+ case mnesia_lib:cs_to_storage_type(node(), Cs) of
+ unknown ->
+ ignore;
+ Storage ->
+ Oid = '_', %%val({Tab, wild_pattern}),
+ if Storage == disc_copies ->
+ open_dcl(Cs#cstruct.name);
+ true ->
+ ignore
+ end,
+ insert(Tid, Storage, Tab, '_', Oid, clear_table, InPlace, InitBy)
+ end;
+
+insert_op(Tid, _, {op, merge_schema, TabDef}, InPlace, InitBy) ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ insert_cstruct(Tid, Cs, false, InPlace, InitBy);
+
+insert_op(Tid, _, {op, del_table_copy, Storage, Node, TabDef}, InPlace, InitBy) ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ Tab = Cs#cstruct.name,
+ if
+ Tab == schema, Storage == ram_copies ->
+ insert_cstruct(Tid, Cs, true, InPlace, InitBy);
+ Tab /= schema ->
+ mnesia_controller:del_active_replica(Tab, Node),
+ mnesia_lib:del({Tab, Storage}, Node),
+ if
+ Node == node() ->
+ case Cs#cstruct.local_content of
+ true -> mnesia_lib:set({Tab, where_to_read}, nowhere);
+ false -> mnesia_lib:set_remote_where_to_read(Tab)
+ end,
+ mnesia_lib:del({schema, local_tables}, Tab),
+ mnesia_lib:set({Tab, storage_type}, unknown),
+ insert_cstruct(Tid, Cs, true, InPlace, InitBy),
+ disc_delete_table(Tab, Storage),
+ disc_delete_indecies(Tab, Cs, Storage),
+ mnesia_schema:ram_delete_table(Tab, Storage),
+ mnesia_checkpoint:tm_del_copy(Tab, Node);
+ true ->
+ case val({Tab, where_to_read}) of
+ Node ->
+ mnesia_lib:set_remote_where_to_read(Tab);
+ _ ->
+ ignore
+ end,
+ insert_cstruct(Tid, Cs, true, InPlace, InitBy)
+ end
+ end;
+
+insert_op(Tid, _, {op, add_table_copy, _Storage, _Node, TabDef}, InPlace, InitBy) ->
+ %% During prepare commit, the files was created
+ %% and the replica was announced
+ Cs = mnesia_schema:list2cs(TabDef),
+ insert_cstruct(Tid, Cs, true, InPlace, InitBy);
+
+insert_op(Tid, _, {op, add_snmp, _Us, TabDef}, InPlace, InitBy) ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ insert_cstruct(Tid, Cs, true, InPlace, InitBy);
+
+insert_op(Tid, _, {op, del_snmp, TabDef}, InPlace, InitBy) ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ Tab = Cs#cstruct.name,
+ Storage = mnesia_lib:cs_to_storage_type(node(), Cs),
+ if
+ InitBy /= startup,
+ Storage /= unknown ->
+ case ?catch_val({Tab, {index, snmp}}) of
+ {'EXIT', _} ->
+ ignore;
+ Stab ->
+ mnesia_snmp_hook:delete_table(Tab, Stab),
+ mnesia_lib:unset({Tab, {index, snmp}})
+ end;
+ true ->
+ ignore
+ end,
+ insert_cstruct(Tid, Cs, true, InPlace, InitBy);
+
+insert_op(Tid, _, {op, add_index, Pos, TabDef}, InPlace, InitBy) ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ Tab = insert_cstruct(Tid, Cs, true, InPlace, InitBy),
+ Storage = mnesia_lib:cs_to_storage_type(node(), Cs),
+ case InitBy of
+ startup when Storage == disc_only_copies ->
+ mnesia_index:init_indecies(Tab, Storage, [Pos]);
+ startup ->
+ ignore;
+ _ ->
+ mnesia_index:init_indecies(Tab, Storage, [Pos])
+ end;
+
+insert_op(Tid, _, {op, del_index, Pos, TabDef}, InPlace, InitBy) ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ Tab = Cs#cstruct.name,
+ Storage = mnesia_lib:cs_to_storage_type(node(), Cs),
+ case InitBy of
+ startup when Storage == disc_only_copies ->
+ mnesia_index:del_index_table(Tab, Storage, Pos);
+ startup ->
+ ignore;
+ _ ->
+ mnesia_index:del_index_table(Tab, Storage, Pos)
+ end,
+ insert_cstruct(Tid, Cs, true, InPlace, InitBy);
+
+insert_op(Tid, _, {op, change_table_access_mode,TabDef, _OldAccess, _Access}, InPlace, InitBy) ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ case InitBy of
+ startup -> ignore;
+ _ -> mnesia_controller:change_table_access_mode(Cs)
+ end,
+ insert_cstruct(Tid, Cs, true, InPlace, InitBy);
+
+insert_op(Tid, _, {op, change_table_load_order, TabDef, _OldLevel, _Level}, InPlace, InitBy) ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ insert_cstruct(Tid, Cs, true, InPlace, InitBy);
+
+insert_op(Tid, _, {op, delete_property, TabDef, PropKey}, InPlace, InitBy) ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ Tab = Cs#cstruct.name,
+ mnesia_lib:unset({Tab, user_property, PropKey}),
+ insert_cstruct(Tid, Cs, true, InPlace, InitBy);
+
+insert_op(Tid, _, {op, write_property, TabDef, _Prop}, InPlace, InitBy) ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ insert_cstruct(Tid, Cs, true, InPlace, InitBy);
+
+insert_op(Tid, _, {op, change_table_frag, _Change, TabDef}, InPlace, InitBy) ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ insert_cstruct(Tid, Cs, true, InPlace, InitBy).
+
+open_files(Tab, Storage, UpdateInPlace, InitBy)
+ when Storage /= unknown, Storage /= ram_copies ->
+ case get({?MODULE, Tab}) of
+ undefined ->
+ case ?catch_val({Tab, setorbag}) of
+ {'EXIT', _} ->
+ false;
+ Type ->
+ case Storage of
+ disc_copies when Tab /= schema ->
+ Bool = open_disc_copies(Tab, InitBy),
+ Bool;
+ _ ->
+ Fname = prepare_open(Tab, UpdateInPlace),
+ Args = [{file, Fname},
+ {keypos, 2},
+ {repair, mnesia_monitor:get_env(auto_repair)},
+ {type, mnesia_lib:disk_type(Tab, Type)}],
+ {ok, _} = mnesia_monitor:open_dets(Tab, Args),
+ put({?MODULE, Tab}, {opened_dumper, dat}),
+ true
+ end
+ end;
+ already_dumped ->
+ false;
+ {opened_dumper, _} ->
+ true
+ end;
+open_files(_Tab, _Storage, _UpdateInPlace, _InitBy) ->
+ false.
+
+open_disc_copies(Tab, InitBy) ->
+ DclF = mnesia_lib:tab2dcl(Tab),
+ DumpEts =
+ case file:read_file_info(DclF) of
+ {error, enoent} ->
+ false;
+ {ok, DclInfo} ->
+ DcdF = mnesia_lib:tab2dcd(Tab),
+ case file:read_file_info(DcdF) of
+ {error, Reason} ->
+ mnesia_lib:dbg_out("File ~p info_error ~p ~n",
+ [DcdF, Reason]),
+ true;
+ {ok, DcdInfo} ->
+ DcdInfo#file_info.size =<
+ (DclInfo#file_info.size *
+ ?DumpToEtsMultiplier)
+ end
+ end,
+ if
+ DumpEts == false; InitBy == startup ->
+ mnesia_log:open_log({?MODULE,Tab},
+ mnesia_log:dcl_log_header(),
+ DclF,
+ mnesia_lib:exists(DclF),
+ mnesia_monitor:get_env(auto_repair),
+ read_write),
+ put({?MODULE, Tab}, {opened_dumper, dcl}),
+ true;
+ true ->
+ mnesia_log:ets2dcd(Tab),
+ put({?MODULE, Tab}, already_dumped),
+ false
+ end.
+
+%% Always opens the dcl file for writing overriding already_dumped
+%% mechanismen, used for schema transactions.
+open_dcl(Tab) ->
+ case get({?MODULE, Tab}) of
+ {opened_dumper, _} ->
+ true;
+ _ -> %% undefined or already_dumped
+ DclF = mnesia_lib:tab2dcl(Tab),
+ mnesia_log:open_log({?MODULE,Tab},
+ mnesia_log:dcl_log_header(),
+ DclF,
+ mnesia_lib:exists(DclF),
+ mnesia_monitor:get_env(auto_repair),
+ read_write),
+ put({?MODULE, Tab}, {opened_dumper, dcl}),
+ true
+ end.
+
+prepare_open(Tab, UpdateInPlace) ->
+ Dat = mnesia_lib:tab2dat(Tab),
+ case UpdateInPlace of
+ true ->
+ Dat;
+ false ->
+ Tmp = mnesia_lib:tab2tmp(Tab),
+ case catch mnesia_lib:copy_file(Dat, Tmp) of
+ ok ->
+ Tmp;
+ Error ->
+ fatal("Cannot copy dets file ~p to ~p: ~p~n",
+ [Dat, Tmp, Error])
+ end
+ end.
+
+del_opened_tab(Tab) ->
+ erase({?MODULE, Tab}).
+
+close_files(UpdateInPlace, Outcome, InitBy) -> % Update in place
+ close_files(UpdateInPlace, Outcome, InitBy, get()).
+
+close_files(InPlace, Outcome, InitBy, [{{?MODULE, Tab}, already_dumped} | Tail]) ->
+ erase({?MODULE, Tab}),
+ close_files(InPlace, Outcome, InitBy, Tail);
+close_files(InPlace, Outcome, InitBy, [{{?MODULE, Tab}, {opened_dumper, Type}} | Tail]) ->
+ erase({?MODULE, Tab}),
+ case val({Tab, storage_type}) of
+ disc_only_copies when InitBy /= startup ->
+ ignore;
+ disc_copies when Tab /= schema ->
+ mnesia_log:close_log({?MODULE,Tab});
+ Storage ->
+ do_close(InPlace, Outcome, Tab, Type, Storage)
+ end,
+ close_files(InPlace, Outcome, InitBy, Tail);
+
+close_files(InPlace, Outcome, InitBy, [_ | Tail]) ->
+ close_files(InPlace, Outcome, InitBy, Tail);
+close_files(_, _, _InitBy, []) ->
+ ok.
+
+%% If storage is unknown during close clean up files, this can happen if timing
+%% is right and dirty_write conflicts with schema operations.
+do_close(_, _, Tab, dcl, unknown) ->
+ mnesia_log:close_log({?MODULE,Tab}),
+ file:delete(mnesia_lib:tab2dcl(Tab));
+do_close(_, _, Tab, dcl, _) -> %% To be safe, can it happen?
+ mnesia_log:close_log({?MODULE,Tab});
+
+do_close(InPlace, Outcome, Tab, dat, Storage) ->
+ mnesia_monitor:close_dets(Tab),
+ if
+ Storage == unknown, InPlace == true ->
+ file:delete(mnesia_lib:tab2dat(Tab));
+ InPlace == true ->
+ %% Update in place
+ ok;
+ Outcome == ok, Storage /= unknown ->
+ %% Success: swap tmp files with dat files
+ TabDat = mnesia_lib:tab2dat(Tab),
+ ok = file:rename(mnesia_lib:tab2tmp(Tab), TabDat);
+ true ->
+ file:delete(mnesia_lib:tab2tmp(Tab))
+ end.
+
+
+ensure_rename(From, To) ->
+ case mnesia_lib:exists(From) of
+ true ->
+ file:rename(From, To);
+ false ->
+ case mnesia_lib:exists(To) of
+ true ->
+ ok;
+ false ->
+ {error, {rename_failed, From, To}}
+ end
+ end.
+
+insert_cstruct(Tid, Cs, KeepWhereabouts, InPlace, InitBy) ->
+ Val = mnesia_schema:insert_cstruct(Tid, Cs, KeepWhereabouts),
+ {schema, Tab, _} = Val,
+ S = val({schema, storage_type}),
+ disc_insert(Tid, S, schema, Tab, Val, write, InPlace, InitBy),
+ Tab.
+
+delete_cstruct(Tid, Cs, InPlace, InitBy) ->
+ Val = mnesia_schema:delete_cstruct(Tid, Cs),
+ {schema, Tab, _} = Val,
+ S = val({schema, storage_type}),
+ disc_insert(Tid, S, schema, Tab, Val, delete, InPlace, InitBy),
+ Tab.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Raw dump of table. Dumper must have unique access to the ets table.
+
+raw_named_dump_table(Tab, Ftype) ->
+ case mnesia_monitor:use_dir() of
+ true ->
+ mnesia_lib:lock_table(Tab),
+ TmpFname = mnesia_lib:tab2tmp(Tab),
+ Fname =
+ case Ftype of
+ dat -> mnesia_lib:tab2dat(Tab);
+ dmp -> mnesia_lib:tab2dmp(Tab)
+ end,
+ file:delete(TmpFname),
+ file:delete(Fname),
+ TabSize = ?ets_info(Tab, size),
+ TabRef = Tab,
+ DiskType = mnesia_lib:disk_type(Tab),
+ Args = [{file, TmpFname},
+ {keypos, 2},
+ %% {ram_file, true},
+ {estimated_no_objects, TabSize + 256},
+ {repair, mnesia_monitor:get_env(auto_repair)},
+ {type, DiskType}],
+ case mnesia_lib:dets_sync_open(TabRef, Args) of
+ {ok, TabRef} ->
+ Storage = ram_copies,
+ mnesia_lib:db_fixtable(Storage, Tab, true),
+
+ case catch raw_dump_table(TabRef, Tab) of
+ {'EXIT', Reason} ->
+ mnesia_lib:db_fixtable(Storage, Tab, false),
+ mnesia_lib:dets_sync_close(Tab),
+ file:delete(TmpFname),
+ mnesia_lib:unlock_table(Tab),
+ exit({"Dump of table to disc failed", Reason});
+ ok ->
+ mnesia_lib:db_fixtable(Storage, Tab, false),
+ mnesia_lib:dets_sync_close(Tab),
+ mnesia_lib:unlock_table(Tab),
+ ok = file:rename(TmpFname, Fname)
+ end;
+ {error, Reason} ->
+ mnesia_lib:unlock_table(Tab),
+ exit({"Open of file before dump to disc failed", Reason})
+ end;
+ false ->
+ exit({has_no_disc, node()})
+ end.
+
+raw_dump_table(DetsRef, EtsRef) ->
+ dets:from_ets(DetsRef, EtsRef).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Load regulator
+%%
+%% This is a poor mans substitute for a fair scheduler algorithm
+%% in the Erlang emulator. The mnesia_dumper process performs many
+%% costly BIF invokations and must pay for this. But since the
+%% Emulator does not handle this properly we must compensate for
+%% this with some form of load regulation of ourselves in order to
+%% not steal all computation power in the Erlang Emulator ans make
+%% other processes starve. Hopefully this is a temporary solution.
+
+start_regulator() ->
+ case mnesia_monitor:get_env(dump_log_load_regulation) of
+ false ->
+ nopid;
+ true ->
+ N = ?REGULATOR_NAME,
+ case mnesia_monitor:start_proc(N, ?MODULE, regulator_init, [self()]) of
+ {ok, Pid} ->
+ Pid;
+ {error, Reason} ->
+ fatal("Failed to start ~n: ~p~n", [N, Reason])
+ end
+ end.
+
+regulator_init(Parent) ->
+ %% No need for trapping exits.
+ %% Using low priority causes the regulation
+ process_flag(priority, low),
+ register(?REGULATOR_NAME, self()),
+ proc_lib:init_ack(Parent, {ok, self()}),
+ regulator_loop().
+
+regulator_loop() ->
+ receive
+ {regulate, From} ->
+ From ! {regulated, self()},
+ regulator_loop();
+ {stop, From} ->
+ From ! {stopped, self()},
+ exit(normal)
+ end.
+
+regulate(nopid) ->
+ ok;
+regulate(RegulatorPid) ->
+ RegulatorPid ! {regulate, self()},
+ receive
+ {regulated, RegulatorPid} -> ok
+ end.
+
+val(Var) ->
+ case ?catch_val(Var) of
+ {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
+ Value -> Value
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_event.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_event.erl
new file mode 100644
index 0000000000..6053179194
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_event.erl
@@ -0,0 +1,260 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_event.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
+%%
+-module(mnesia_event).
+
+-behaviour(gen_event).
+%-behaviour(mnesia_event).
+
+%% gen_event callback interface
+-export([init/1,
+ handle_event/2,
+ handle_call/2,
+ handle_info/2,
+ terminate/2,
+ code_change/3]).
+
+-record(state, {nodes = [],
+ dumped_core = false, %% only dump fatal core once
+ args}).
+
+%%%----------------------------------------------------------------
+%%% Callback functions from gen_server
+%%%----------------------------------------------------------------
+
+%%-----------------------------------------------------------------
+%% init(Args) ->
+%% {ok, State} | Error
+%%-----------------------------------------------------------------
+
+init(Args) ->
+ {ok, #state{args = Args}}.
+
+%%-----------------------------------------------------------------
+%% handle_event(Event, State) ->
+%% {ok, NewState} | remove_handler |
+%% {swap_handler, Args1, State1, Mod2, Args2}
+%%-----------------------------------------------------------------
+
+handle_event(Event, State) ->
+ handle_any_event(Event, State).
+
+%%-----------------------------------------------------------------
+%% handle_info(Msg, State) ->
+%% {ok, NewState} | remove_handler |
+%% {swap_handler, Args1, State1, Mod2, Args2}
+%%-----------------------------------------------------------------
+
+handle_info(Msg, State) ->
+ handle_any_event(Msg, State),
+ {ok, State}.
+
+%%-----------------------------------------------------------------
+%% handle_call(Event, State) ->
+%% {ok, Reply, NewState} | {remove_handler, Reply} |
+%% {swap_handler, Reply, Args1, State1, Mod2, Args2}
+%%-----------------------------------------------------------------
+
+handle_call(Msg, State) ->
+ Reply = ok,
+ case handle_any_event(Msg, State) of
+ {ok, NewState} ->
+ {ok, Reply, NewState};
+ remove_handler ->
+ {remove_handler, Reply};
+ {swap_handler,Args1, State1, Mod2, Args2} ->
+ {swap_handler, Reply, Args1, State1, Mod2, Args2}
+ end.
+
+%%-----------------------------------------------------------------
+%% terminate(Reason, State) ->
+%% AnyVal
+%%-----------------------------------------------------------------
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%----------------------------------------------------------------------
+%% Func: code_change/3
+%% Purpose: Upgrade process when its code is to be changed
+%% Returns: {ok, NewState}
+%%----------------------------------------------------------------------
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%-----------------------------------------------------------------
+%% Internal functions
+%%-----------------------------------------------------------------
+
+handle_any_event({mnesia_system_event, Event}, State) ->
+ handle_system_event(Event, State);
+handle_any_event({mnesia_table_event, Event}, State) ->
+ handle_table_event(Event, State);
+handle_any_event(Msg, State) ->
+ report_error("~p got unexpected event: ~p~n", [?MODULE, Msg]),
+ {ok, State}.
+
+handle_table_event({Oper, Record, TransId}, State) ->
+ report_info("~p performed by ~p on record:~n\t~p~n",
+ [Oper, TransId, Record]),
+ {ok, State}.
+
+handle_system_event({mnesia_checkpoint_activated, _Checkpoint}, State) ->
+ {ok, State};
+
+handle_system_event({mnesia_checkpoint_deactivated, _Checkpoint}, State) ->
+ {ok, State};
+
+handle_system_event({mnesia_up, Node}, State) ->
+ Nodes = [Node | State#state.nodes],
+ {ok, State#state{nodes = Nodes}};
+
+handle_system_event({mnesia_down, Node}, State) ->
+ case mnesia:system_info(fallback_activated) of
+ true ->
+ case mnesia_monitor:get_env(fallback_error_function) of
+ {mnesia, lkill} ->
+ Msg = "A fallback is installed and Mnesia "
+ "must be restarted. Forcing shutdown "
+ "after mnesia_down from ~p...~n",
+ report_fatal(Msg, [Node], nocore, State#state.dumped_core),
+ mnesia:lkill(),
+ exit(fatal);
+ {UserMod, UserFunc} ->
+ Msg = "Warning: A fallback is installed and Mnesia got mnesia_down "
+ "from ~p. ~n",
+ report_info(Msg, [Node]),
+ case catch apply(UserMod, UserFunc, [Node]) of
+ {'EXIT', {undef, _Reason}} ->
+ %% Backward compatibility
+ apply(UserMod, UserFunc, []);
+ {'EXIT', Reason} ->
+ exit(Reason);
+ _ ->
+ ok
+ end,
+ Nodes = lists:delete(Node, State#state.nodes),
+ {ok, State#state{nodes = Nodes}}
+ end;
+ false ->
+ Nodes = lists:delete(Node, State#state.nodes),
+ {ok, State#state{nodes = Nodes}}
+ end;
+
+handle_system_event({mnesia_overload, Details}, State) ->
+ report_warning("Mnesia is overloaded: ~p~n", [Details]),
+ {ok, State};
+
+handle_system_event({mnesia_info, Format, Args}, State) ->
+ report_info(Format, Args),
+ {ok, State};
+
+handle_system_event({mnesia_warning, Format, Args}, State) ->
+ report_warning(Format, Args),
+ {ok, State};
+
+handle_system_event({mnesia_error, Format, Args}, State) ->
+ report_error(Format, Args),
+ {ok, State};
+
+handle_system_event({mnesia_fatal, Format, Args, BinaryCore}, State) ->
+ report_fatal(Format, Args, BinaryCore, State#state.dumped_core),
+ {ok, State#state{dumped_core = true}};
+
+handle_system_event({inconsistent_database, Reason, Node}, State) ->
+ report_error("mnesia_event got {inconsistent_database, ~w, ~w}~n",
+ [Reason, Node]),
+ {ok, State};
+
+handle_system_event({mnesia_user, Event}, State) ->
+ report_info("User event: ~p~n", [Event]),
+ {ok, State};
+
+handle_system_event(Msg, State) ->
+ report_error("mnesia_event got unexpected system event: ~p~n", [Msg]),
+ {ok, State}.
+
+report_info(Format0, Args0) ->
+ Format = "Mnesia(~p): " ++ Format0,
+ Args = [node() | Args0],
+ case global:whereis_name(mnesia_global_logger) of
+ undefined ->
+ io:format(Format, Args);
+ Pid ->
+ io:format(Pid, Format, Args)
+ end.
+
+report_warning(Format0, Args0) ->
+ Format = "Mnesia(~p): ** WARNING ** " ++ Format0,
+ Args = [node() | Args0],
+ case erlang:function_exported(error_logger, warning_msg, 2) of
+ true ->
+ error_logger:warning_msg(Format, Args);
+ false ->
+ error_logger:format(Format, Args)
+ end,
+ case global:whereis_name(mnesia_global_logger) of
+ undefined ->
+ ok;
+ Pid ->
+ io:format(Pid, Format, Args)
+ end.
+
+report_error(Format0, Args0) ->
+ Format = "Mnesia(~p): ** ERROR ** " ++ Format0,
+ Args = [node() | Args0],
+ error_logger:format(Format, Args),
+ case global:whereis_name(mnesia_global_logger) of
+ undefined ->
+ ok;
+ Pid ->
+ io:format(Pid, Format, Args)
+ end.
+
+report_fatal(Format, Args, BinaryCore, CoreDumped) ->
+ UseDir = mnesia_monitor:use_dir(),
+ CoreDir = mnesia_monitor:get_env(core_dir),
+ if
+ list(CoreDir),CoreDumped == false,binary(BinaryCore) ->
+ core_file(CoreDir,BinaryCore,Format,Args);
+ (UseDir == true),CoreDumped == false,binary(BinaryCore) ->
+ core_file(CoreDir,BinaryCore,Format,Args);
+ true ->
+ report_error("(ignoring core) ** FATAL ** " ++ Format, Args)
+ end.
+
+core_file(CoreDir,BinaryCore,Format,Args) ->
+ %% Integers = tuple_to_list(date()) ++ tuple_to_list(time()),
+ Integers = tuple_to_list(now()),
+ Fun = fun(I) when I < 10 -> ["_0",I];
+ (I) -> ["_",I]
+ end,
+ List = lists:append([Fun(I) || I <- Integers]),
+ CoreFile = if list(CoreDir) ->
+ filename:absname(lists:concat(["MnesiaCore.", node()] ++ List),
+ CoreDir);
+ true ->
+ filename:absname(lists:concat(["MnesiaCore.", node()] ++ List))
+ end,
+ case file:write_file(CoreFile, BinaryCore) of
+ ok ->
+ report_error("(core dumped to file: ~p)~n ** FATAL ** " ++ Format,
+ [CoreFile] ++ Args);
+ {error, Reason} ->
+ report_error("(could not write core file: ~p)~n ** FATAL ** " ++ Format,
+ [Reason] ++ Args)
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_frag.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_frag.erl
new file mode 100644
index 0000000000..92ac51a0dc
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_frag.erl
@@ -0,0 +1,1201 @@
+%%% ``The contents of this file are subject to the Erlang Public License,
+%%% Version 1.1, (the "License"); you may not use this file except in
+%%% compliance 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: mnesia_frag.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
+%%%
+%%%----------------------------------------------------------------------
+%%% Purpose : Support tables so large that they need
+%%% to be divided into several fragments.
+%%%----------------------------------------------------------------------
+
+%header_doc_include
+
+-module(mnesia_frag).
+-behaviour(mnesia_access).
+
+%% Callback functions when accessed within an activity
+-export([
+ lock/4,
+ write/5, delete/5, delete_object/5,
+ read/5, match_object/5, all_keys/4,
+ select/5,
+ index_match_object/6, index_read/6,
+ foldl/6, foldr/6,
+ table_info/4
+ ]).
+
+%header_doc_include
+
+-export([
+ change_table_frag/2,
+ remove_node/2,
+ expand_cstruct/1,
+ lookup_frag_hash/1,
+ lookup_foreigners/1,
+ frag_names/1,
+ set_frag_hash/2,
+ local_select/4,
+ remote_select/4
+ ]).
+
+-include("mnesia.hrl").
+
+-define(OLD_HASH_MOD, mnesia_frag_old_hash).
+-define(DEFAULT_HASH_MOD, mnesia_frag_hash).
+%%-define(DEFAULT_HASH_MOD, ?OLD_HASH_MOD). %% BUGBUG: New should be default
+
+-record(frag_state,
+ {foreign_key,
+ n_fragments,
+ hash_module,
+ hash_state}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Access functions
+
+%impl_doc_include
+
+%% Callback functions which provides transparent
+%% access of fragmented tables from any activity
+%% access context.
+
+lock(ActivityId, Opaque, {table , Tab}, LockKind) ->
+ case frag_names(Tab) of
+ [Tab] ->
+ mnesia:lock(ActivityId, Opaque, {table, Tab}, LockKind);
+ Frags ->
+ DeepNs = [mnesia:lock(ActivityId, Opaque, {table, F}, LockKind) ||
+ F <- Frags],
+ mnesia_lib:uniq(lists:append(DeepNs))
+ end;
+
+lock(ActivityId, Opaque, LockItem, LockKind) ->
+ mnesia:lock(ActivityId, Opaque, LockItem, LockKind).
+
+write(ActivityId, Opaque, Tab, Rec, LockKind) ->
+ Frag = record_to_frag_name(Tab, Rec),
+ mnesia:write(ActivityId, Opaque, Frag, Rec, LockKind).
+
+delete(ActivityId, Opaque, Tab, Key, LockKind) ->
+ Frag = key_to_frag_name(Tab, Key),
+ mnesia:delete(ActivityId, Opaque, Frag, Key, LockKind).
+
+delete_object(ActivityId, Opaque, Tab, Rec, LockKind) ->
+ Frag = record_to_frag_name(Tab, Rec),
+ mnesia:delete_object(ActivityId, Opaque, Frag, Rec, LockKind).
+
+read(ActivityId, Opaque, Tab, Key, LockKind) ->
+ Frag = key_to_frag_name(Tab, Key),
+ mnesia:read(ActivityId, Opaque, Frag, Key, LockKind).
+
+match_object(ActivityId, Opaque, Tab, HeadPat, LockKind) ->
+ MatchSpec = [{HeadPat, [], ['$_']}],
+ select(ActivityId, Opaque, Tab, MatchSpec, LockKind).
+
+select(ActivityId, Opaque, Tab, MatchSpec, LockKind) ->
+ do_select(ActivityId, Opaque, Tab, MatchSpec, LockKind).
+
+all_keys(ActivityId, Opaque, Tab, LockKind) ->
+ Match = [mnesia:all_keys(ActivityId, Opaque, Frag, LockKind)
+ || Frag <- frag_names(Tab)],
+ lists:append(Match).
+
+index_match_object(ActivityId, Opaque, Tab, Pat, Attr, LockKind) ->
+ Match =
+ [mnesia:index_match_object(ActivityId, Opaque, Frag, Pat, Attr, LockKind)
+ || Frag <- frag_names(Tab)],
+ lists:append(Match).
+
+index_read(ActivityId, Opaque, Tab, Key, Attr, LockKind) ->
+ Match =
+ [mnesia:index_read(ActivityId, Opaque, Frag, Key, Attr, LockKind)
+ || Frag <- frag_names(Tab)],
+ lists:append(Match).
+
+foldl(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
+ Fun2 = fun(Frag, A) ->
+ mnesia:foldl(ActivityId, Opaque, Fun, A, Frag, LockKind)
+ end,
+ lists:foldl(Fun2, Acc, frag_names(Tab)).
+
+foldr(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
+ Fun2 = fun(Frag, A) ->
+ mnesia:foldr(ActivityId, Opaque, Fun, A, Frag, LockKind)
+ end,
+ lists:foldr(Fun2, Acc, frag_names(Tab)).
+
+table_info(ActivityId, Opaque, {Tab, Key}, Item) ->
+ Frag = key_to_frag_name(Tab, Key),
+ table_info2(ActivityId, Opaque, Tab, Frag, Item);
+table_info(ActivityId, Opaque, Tab, Item) ->
+ table_info2(ActivityId, Opaque, Tab, Tab, Item).
+
+table_info2(ActivityId, Opaque, Tab, Frag, Item) ->
+ case Item of
+ size ->
+ SumFun = fun({_, Size}, Acc) -> Acc + Size end,
+ lists:foldl(SumFun, 0, frag_size(ActivityId, Opaque, Tab));
+ memory ->
+ SumFun = fun({_, Size}, Acc) -> Acc + Size end,
+ lists:foldl(SumFun, 0, frag_memory(ActivityId, Opaque, Tab));
+ base_table ->
+ lookup_prop(Tab, base_table);
+ node_pool ->
+ lookup_prop(Tab, node_pool);
+ n_fragments ->
+ FH = lookup_frag_hash(Tab),
+ FH#frag_state.n_fragments;
+ foreign_key ->
+ FH = lookup_frag_hash(Tab),
+ FH#frag_state.foreign_key;
+ foreigners ->
+ lookup_foreigners(Tab);
+ n_ram_copies ->
+ length(val({Tab, ram_copies}));
+ n_disc_copies ->
+ length(val({Tab, disc_copies}));
+ n_disc_only_copies ->
+ length(val({Tab, disc_only_copies}));
+
+ frag_names ->
+ frag_names(Tab);
+ frag_dist ->
+ frag_dist(Tab);
+ frag_size ->
+ frag_size(ActivityId, Opaque, Tab);
+ frag_memory ->
+ frag_memory(ActivityId, Opaque, Tab);
+ _ ->
+ mnesia:table_info(ActivityId, Opaque, Frag, Item)
+ end.
+%impl_doc_include
+
+frag_size(ActivityId, Opaque, Tab) ->
+ [{F, remote_table_info(ActivityId, Opaque, F, size)} || F <- frag_names(Tab)].
+
+frag_memory(ActivityId, Opaque, Tab) ->
+ [{F, remote_table_info(ActivityId, Opaque, F, memory)} || F <- frag_names(Tab)].
+
+
+
+remote_table_info(ActivityId, Opaque, Tab, Item) ->
+ N = val({Tab, where_to_read}),
+ case rpc:call(N, mnesia, table_info, [ActivityId, Opaque, Tab, Item]) of
+ {badrpc, _} ->
+ mnesia:abort({no_exists, Tab, Item});
+ Info ->
+ Info
+ end.
+
+do_select(ActivityId, Opaque, Tab, MatchSpec, LockKind) ->
+ case ?catch_val({Tab, frag_hash}) of
+ {'EXIT', _} ->
+ mnesia:select(ActivityId, Opaque, Tab, MatchSpec, LockKind);
+ FH ->
+ HashState = FH#frag_state.hash_state,
+ FragNumbers =
+ case FH#frag_state.hash_module of
+ HashMod when HashMod == ?DEFAULT_HASH_MOD ->
+ ?DEFAULT_HASH_MOD:match_spec_to_frag_numbers(HashState, MatchSpec);
+ HashMod ->
+ HashMod:match_spec_to_frag_numbers(HashState, MatchSpec)
+ end,
+ N = FH#frag_state.n_fragments,
+ VerifyFun = fun(F) when integer(F), F >= 1, F =< N -> false;
+ (_F) -> true
+ end,
+ case catch lists:filter(VerifyFun, FragNumbers) of
+ [] ->
+ Fun = fun(Num) ->
+ Name = n_to_frag_name(Tab, Num),
+ Node = val({Name, where_to_read}),
+ mnesia:lock(ActivityId, Opaque, {table, Name}, LockKind),
+ {Name, Node}
+ end,
+ NameNodes = lists:map(Fun, FragNumbers),
+ SelectAllFun =
+ fun(PatchedMatchSpec) ->
+ Match = [mnesia:dirty_select(Name, PatchedMatchSpec)
+ || {Name, _Node} <- NameNodes],
+ lists:append(Match)
+ end,
+ case [{Name, Node} || {Name, Node} <- NameNodes, Node /= node()] of
+ [] ->
+ %% All fragments are local
+ mnesia:fun_select(ActivityId, Opaque, Tab, MatchSpec, none, '_', SelectAllFun);
+ RemoteNameNodes ->
+ SelectFun =
+ fun(PatchedMatchSpec) ->
+ Ref = make_ref(),
+ Args = [self(), Ref, RemoteNameNodes, PatchedMatchSpec],
+ Pid = spawn_link(?MODULE, local_select, Args),
+ LocalMatch = [mnesia:dirty_select(Name, PatchedMatchSpec)
+ || {Name, Node} <- NameNodes, Node == node()],
+ OldSelectFun = fun() -> SelectAllFun(PatchedMatchSpec) end,
+ local_collect(Ref, Pid, lists:append(LocalMatch), OldSelectFun)
+ end,
+ mnesia:fun_select(ActivityId, Opaque, Tab, MatchSpec, none, '_', SelectFun)
+ end;
+ BadFrags ->
+ mnesia:abort({"match_spec_to_frag_numbers: Fragment numbers out of range",
+ BadFrags, {range, 1, N}})
+ end
+ end.
+
+local_select(ReplyTo, Ref, RemoteNameNodes, MatchSpec) ->
+ RemoteNodes = mnesia_lib:uniq([Node || {_Name, Node} <- RemoteNameNodes]),
+ Args = [ReplyTo, Ref, RemoteNameNodes, MatchSpec],
+ {Replies, BadNodes} = rpc:multicall(RemoteNodes, ?MODULE, remote_select, Args),
+ case mnesia_lib:uniq(Replies) -- [ok] of
+ [] when BadNodes == [] ->
+ ReplyTo ! {local_select, Ref, ok};
+ _ when BadNodes /= [] ->
+ ReplyTo ! {local_select, Ref, {error, {node_not_running, hd(BadNodes)}}};
+ [{badrpc, {'EXIT', Reason}} | _] ->
+ ReplyTo ! {local_select, Ref, {error, Reason}};
+ [Reason | _] ->
+ ReplyTo ! {local_select, Ref, {error, Reason}}
+ end,
+ unlink(ReplyTo),
+ exit(normal).
+
+remote_select(ReplyTo, Ref, NameNodes, MatchSpec) ->
+ do_remote_select(ReplyTo, Ref, NameNodes, MatchSpec).
+
+do_remote_select(ReplyTo, Ref, [{Name, Node} | NameNodes], MatchSpec) ->
+ if
+ Node == node() ->
+ Res = (catch {ok, mnesia:dirty_select(Name, MatchSpec)}),
+ ReplyTo ! {remote_select, Ref, Node, Res},
+ do_remote_select(ReplyTo, Ref, NameNodes, MatchSpec);
+ true ->
+ do_remote_select(ReplyTo, Ref, NameNodes, MatchSpec)
+ end;
+do_remote_select(_ReplyTo, _Ref, [], _MatchSpec) ->
+ ok.
+
+local_collect(Ref, Pid, LocalMatch, OldSelectFun) ->
+ receive
+ {local_select, Ref, LocalRes} ->
+ remote_collect(Ref, LocalRes, LocalMatch, OldSelectFun);
+ {'EXIT', Pid, Reason} ->
+ remote_collect(Ref, {error, Reason}, [], OldSelectFun)
+ end.
+
+remote_collect(Ref, LocalRes = ok, Acc, OldSelectFun) ->
+ receive
+ {remote_select, Ref, Node, RemoteRes} ->
+ case RemoteRes of
+ {ok, RemoteMatch} ->
+ remote_collect(Ref, LocalRes, RemoteMatch ++ Acc, OldSelectFun);
+ _ ->
+ remote_collect(Ref, {error, {node_not_running, Node}}, [], OldSelectFun)
+ end
+ after 0 ->
+ Acc
+ end;
+remote_collect(Ref, LocalRes = {error, Reason}, _Acc, OldSelectFun) ->
+ receive
+ {remote_select, Ref, _Node, _RemoteRes} ->
+ remote_collect(Ref, LocalRes, [], OldSelectFun)
+ after 0 ->
+ mnesia:abort(Reason)
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Returns a list of cstructs
+
+expand_cstruct(Cs) ->
+ expand_cstruct(Cs, create).
+
+expand_cstruct(Cs, Mode) ->
+ Tab = Cs#cstruct.name,
+ Props = Cs#cstruct.frag_properties,
+ mnesia_schema:verify({alt, [nil, list]}, mnesia_lib:etype(Props),
+ {badarg, Tab, Props}),
+ %% Verify keys
+ ValidKeys = [foreign_key, n_fragments, node_pool,
+ n_ram_copies, n_disc_copies, n_disc_only_copies,
+ hash_module, hash_state],
+ Keys = mnesia_schema:check_keys(Tab, Props, ValidKeys),
+ mnesia_schema:check_duplicates(Tab, Keys),
+
+ %% Pick fragmentation props
+ ForeignKey = mnesia_schema:pick(Tab, foreign_key, Props, undefined),
+ {ForeignKey2, N, Pool, DefaultNR, DefaultND, DefaultNDO} =
+ pick_props(Tab, Cs, ForeignKey),
+
+ %% Verify node_pool
+ BadPool = {bad_type, Tab, {node_pool, Pool}},
+ mnesia_schema:verify(list, mnesia_lib:etype(Pool), BadPool),
+ NotAtom = fun(A) when atom(A) -> false;
+ (_A) -> true
+ end,
+ mnesia_schema:verify([], [P || P <- Pool, NotAtom(P)], BadPool),
+
+ NR = mnesia_schema:pick(Tab, n_ram_copies, Props, 0),
+ ND = mnesia_schema:pick(Tab, n_disc_copies, Props, 0),
+ NDO = mnesia_schema:pick(Tab, n_disc_only_copies, Props, 0),
+
+ PosInt = fun(I) when integer(I), I >= 0 -> true;
+ (_I) -> false
+ end,
+ mnesia_schema:verify(true, PosInt(NR),
+ {bad_type, Tab, {n_ram_copies, NR}}),
+ mnesia_schema:verify(true, PosInt(ND),
+ {bad_type, Tab, {n_disc_copies, ND}}),
+ mnesia_schema:verify(true, PosInt(NDO),
+ {bad_type, Tab, {n_disc_only_copies, NDO}}),
+
+ %% Verify n_fragments
+ Cs2 = verify_n_fragments(N, Cs, Mode),
+
+ %% Verify hash callback
+ HashMod = mnesia_schema:pick(Tab, hash_module, Props, ?DEFAULT_HASH_MOD),
+ HashState = mnesia_schema:pick(Tab, hash_state, Props, undefined),
+ HashState2 = HashMod:init_state(Tab, HashState), %% BUGBUG: Catch?
+
+ FH = #frag_state{foreign_key = ForeignKey2,
+ n_fragments = 1,
+ hash_module = HashMod,
+ hash_state = HashState2},
+ if
+ NR == 0, ND == 0, NDO == 0 ->
+ do_expand_cstruct(Cs2, FH, N, Pool, DefaultNR, DefaultND, DefaultNDO, Mode);
+ true ->
+ do_expand_cstruct(Cs2, FH, N, Pool, NR, ND, NDO, Mode)
+ end.
+
+do_expand_cstruct(Cs, FH, N, Pool, NR, ND, NDO, Mode) ->
+ Tab = Cs#cstruct.name,
+
+ LC = Cs#cstruct.local_content,
+ mnesia_schema:verify(false, LC,
+ {combine_error, Tab, {local_content, LC}}),
+
+ Snmp = Cs#cstruct.snmp,
+ mnesia_schema:verify([], Snmp,
+ {combine_error, Tab, {snmp, Snmp}}),
+
+ %% Add empty fragments
+ CommonProps = [{base_table, Tab}],
+ Cs2 = Cs#cstruct{frag_properties = lists:sort(CommonProps)},
+ expand_frag_cstructs(N, NR, ND, NDO, Cs2, Pool, Pool, FH, Mode).
+
+verify_n_fragments(N, Cs, Mode) when integer(N), N >= 1 ->
+ case Mode of
+ create ->
+ Cs#cstruct{ram_copies = [],
+ disc_copies = [],
+ disc_only_copies = []};
+ activate ->
+ Reason = {combine_error, Cs#cstruct.name, {n_fragments, N}},
+ mnesia_schema:verify(1, N, Reason),
+ Cs
+ end;
+verify_n_fragments(N, Cs, _Mode) ->
+ mnesia:abort({bad_type, Cs#cstruct.name, {n_fragments, N}}).
+
+pick_props(Tab, Cs, {ForeignTab, Attr}) ->
+ mnesia_schema:verify(true, ForeignTab /= Tab,
+ {combine_error, Tab, {ForeignTab, Attr}}),
+ Props = Cs#cstruct.frag_properties,
+ Attrs = Cs#cstruct.attributes,
+
+ ForeignKey = lookup_prop(ForeignTab, foreign_key),
+ ForeignN = lookup_prop(ForeignTab, n_fragments),
+ ForeignPool = lookup_prop(ForeignTab, node_pool),
+ N = mnesia_schema:pick(Tab, n_fragments, Props, ForeignN),
+ Pool = mnesia_schema:pick(Tab, node_pool, Props, ForeignPool),
+
+ mnesia_schema:verify(ForeignN, N,
+ {combine_error, Tab, {n_fragments, N},
+ ForeignTab, {n_fragments, ForeignN}}),
+
+ mnesia_schema:verify(ForeignPool, Pool,
+ {combine_error, Tab, {node_pool, Pool},
+ ForeignTab, {node_pool, ForeignPool}}),
+
+ mnesia_schema:verify(undefined, ForeignKey,
+ {combine_error, Tab,
+ "Multiple levels of foreign_key dependencies",
+ {ForeignTab, Attr}, ForeignKey}),
+
+ Key = {ForeignTab, mnesia_schema:attr_to_pos(Attr, Attrs)},
+ DefaultNR = length(val({ForeignTab, ram_copies})),
+ DefaultND = length(val({ForeignTab, disc_copies})),
+ DefaultNDO = length(val({ForeignTab, disc_only_copies})),
+ {Key, N, Pool, DefaultNR, DefaultND, DefaultNDO};
+pick_props(Tab, Cs, undefined) ->
+ Props = Cs#cstruct.frag_properties,
+ DefaultN = 1,
+ DefaultPool = mnesia:system_info(db_nodes),
+ N = mnesia_schema:pick(Tab, n_fragments, Props, DefaultN),
+ Pool = mnesia_schema:pick(Tab, node_pool, Props, DefaultPool),
+ DefaultNR = 1,
+ DefaultND = 0,
+ DefaultNDO = 0,
+ {undefined, N, Pool, DefaultNR, DefaultND, DefaultNDO};
+pick_props(Tab, _Cs, BadKey) ->
+ mnesia:abort({bad_type, Tab, {foreign_key, BadKey}}).
+
+expand_frag_cstructs(N, NR, ND, NDO, CommonCs, Dist, Pool, FH, Mode)
+ when N > 1, Mode == create ->
+ Frag = n_to_frag_name(CommonCs#cstruct.name, N),
+ Cs = CommonCs#cstruct{name = Frag},
+ {Cs2, RevModDist, RestDist} = set_frag_nodes(NR, ND, NDO, Cs, Dist, []),
+ ModDist = lists:reverse(RevModDist),
+ Dist2 = rearrange_dist(Cs, ModDist, RestDist, Pool),
+ %% Adjusts backwards, but it doesn't matter.
+ {FH2, _FromFrags, _AdditionalWriteFrags} = adjust_before_split(FH),
+ CsList = expand_frag_cstructs(N - 1, NR, ND, NDO, CommonCs, Dist2, Pool, FH2, Mode),
+ [Cs2 | CsList];
+expand_frag_cstructs(1, NR, ND, NDO, CommonCs, Dist, Pool, FH, Mode) ->
+ BaseProps = CommonCs#cstruct.frag_properties ++
+ [{foreign_key, FH#frag_state.foreign_key},
+ {hash_module, FH#frag_state.hash_module},
+ {hash_state, FH#frag_state.hash_state},
+ {n_fragments, FH#frag_state.n_fragments},
+ {node_pool, Pool}
+ ],
+ BaseCs = CommonCs#cstruct{frag_properties = lists:sort(BaseProps)},
+ case Mode of
+ activate ->
+ [BaseCs];
+ create ->
+ {BaseCs2, _, _} = set_frag_nodes(NR, ND, NDO, BaseCs, Dist, []),
+ [BaseCs2]
+ end.
+
+set_frag_nodes(NR, ND, NDO, Cs, [Head | Tail], Acc) when NR > 0 ->
+ Pos = #cstruct.ram_copies,
+ {Cs2, Head2} = set_frag_node(Cs, Pos, Head),
+ set_frag_nodes(NR - 1, ND, NDO, Cs2, Tail, [Head2 | Acc]);
+set_frag_nodes(NR, ND, NDO, Cs, [Head | Tail], Acc) when ND > 0 ->
+ Pos = #cstruct.disc_copies,
+ {Cs2, Head2} = set_frag_node(Cs, Pos, Head),
+ set_frag_nodes(NR, ND - 1, NDO, Cs2, Tail, [Head2 | Acc]);
+set_frag_nodes(NR, ND, NDO, Cs, [Head | Tail], Acc) when NDO > 0 ->
+ Pos = #cstruct.disc_only_copies,
+ {Cs2, Head2} = set_frag_node(Cs, Pos, Head),
+ set_frag_nodes(NR, ND, NDO - 1, Cs2, Tail, [Head2 | Acc]);
+set_frag_nodes(0, 0, 0, Cs, RestDist, ModDist) ->
+ {Cs, ModDist, RestDist};
+set_frag_nodes(_, _, _, Cs, [], _) ->
+ mnesia:abort({combine_error, Cs#cstruct.name, "Too few nodes in node_pool"}).
+
+set_frag_node(Cs, Pos, Head) ->
+ Ns = element(Pos, Cs),
+ {Node, Count2} =
+ case Head of
+ {N, Count} when atom(N), integer(Count), Count >= 0 ->
+ {N, Count + 1};
+ N when atom(N) ->
+ {N, 1};
+ BadNode ->
+ mnesia:abort({bad_type, Cs#cstruct.name, BadNode})
+ end,
+ Cs2 = setelement(Pos, Cs, [Node | Ns]),
+ {Cs2, {Node, Count2}}.
+
+rearrange_dist(Cs, [{Node, Count} | ModDist], Dist, Pool) ->
+ Dist2 = insert_dist(Cs, Node, Count, Dist, Pool),
+ rearrange_dist(Cs, ModDist, Dist2, Pool);
+rearrange_dist(_Cs, [], Dist, _) ->
+ Dist.
+
+insert_dist(Cs, Node, Count, [Head | Tail], Pool) ->
+ case Head of
+ {Node2, Count2} when atom(Node2), integer(Count2), Count2 >= 0 ->
+ case node_diff(Node, Count, Node2, Count2, Pool) of
+ less ->
+ [{Node, Count}, Head | Tail];
+ greater ->
+ [Head | insert_dist(Cs, Node, Count, Tail, Pool)]
+ end;
+ Node2 when atom(Node2) ->
+ insert_dist(Cs, Node, Count, [{Node2, 0} | Tail], Pool);
+ BadNode ->
+ mnesia:abort({bad_type, Cs#cstruct.name, BadNode})
+ end;
+insert_dist(_Cs, Node, Count, [], _Pool) ->
+ [{Node, Count}];
+insert_dist(_Cs, _Node, _Count, Dist, _Pool) ->
+ mnesia:abort({bad_type, Dist}).
+
+node_diff(_Node, Count, _Node2, Count2, _Pool) when Count < Count2 ->
+ less;
+node_diff(Node, Count, Node2, Count2, Pool) when Count == Count2 ->
+ Pos = list_pos(Node, Pool, 1),
+ Pos2 = list_pos(Node2, Pool, 1),
+ if
+ Pos < Pos2 ->
+ less;
+ Pos > Pos2 ->
+ greater
+ end;
+node_diff(_Node, Count, _Node2, Count2, _Pool) when Count > Count2 ->
+ greater.
+
+%% Returns position of element in list
+list_pos(H, [H | _T], Pos) ->
+ Pos;
+list_pos(E, [_H | T], Pos) ->
+ list_pos(E, T, Pos + 1).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Switch function for changing of table fragmentation
+%%
+%% Returns a list of lists of schema ops
+
+change_table_frag(Tab, {activate, FragProps}) ->
+ make_activate(Tab, FragProps);
+change_table_frag(Tab, deactivate) ->
+ make_deactivate(Tab);
+change_table_frag(Tab, {add_frag, SortedNodes}) ->
+ make_multi_add_frag(Tab, SortedNodes);
+change_table_frag(Tab, del_frag) ->
+ make_multi_del_frag(Tab);
+change_table_frag(Tab, {add_node, Node}) ->
+ make_multi_add_node(Tab, Node);
+change_table_frag(Tab, {del_node, Node}) ->
+ make_multi_del_node(Tab, Node);
+change_table_frag(Tab, Change) ->
+ mnesia:abort({bad_type, Tab, Change}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Turn a normal table into a fragmented table
+%%
+%% The storage type must be the same on all nodes
+
+make_activate(Tab, Props) ->
+ Cs = mnesia_schema:incr_version(val({Tab, cstruct})),
+ mnesia_schema:ensure_active(Cs),
+ case Cs#cstruct.frag_properties of
+ [] ->
+ Cs2 = Cs#cstruct{frag_properties = Props},
+ [Cs3] = expand_cstruct(Cs2, activate),
+ TabDef = mnesia_schema:cs2list(Cs3),
+ Op = {op, change_table_frag, activate, TabDef},
+ [[Op]];
+ BadProps ->
+ mnesia:abort({already_exists, Tab, {frag_properties, BadProps}})
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Turn a table into a normal defragmented table
+
+make_deactivate(Tab) ->
+ Cs = mnesia_schema:incr_version(val({Tab, cstruct})),
+ mnesia_schema:ensure_active(Cs),
+ Foreigners = lookup_foreigners(Tab),
+ BaseTab = lookup_prop(Tab, base_table),
+ FH = lookup_frag_hash(Tab),
+ if
+ BaseTab /= Tab ->
+ mnesia:abort({combine_error, Tab, "Not a base table"});
+ Foreigners /= [] ->
+ mnesia:abort({combine_error, Tab, "Too many foreigners", Foreigners});
+ FH#frag_state.n_fragments > 1 ->
+ mnesia:abort({combine_error, Tab, "Too many fragments"});
+ true ->
+ Cs2 = Cs#cstruct{frag_properties = []},
+ TabDef = mnesia_schema:cs2list(Cs2),
+ Op = {op, change_table_frag, deactivate, TabDef},
+ [[Op]]
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Add a fragment to a fragmented table and fill it with half of
+%% the records from one of the old fragments
+
+make_multi_add_frag(Tab, SortedNs) when list(SortedNs) ->
+ verify_multi(Tab),
+ Ops = make_add_frag(Tab, SortedNs),
+
+ %% Propagate to foreigners
+ MoreOps = [make_add_frag(T, SortedNs) || T <- lookup_foreigners(Tab)],
+ [Ops | MoreOps];
+make_multi_add_frag(Tab, SortedNs) ->
+ mnesia:abort({bad_type, Tab, SortedNs}).
+
+verify_multi(Tab) ->
+ FH = lookup_frag_hash(Tab),
+ ForeignKey = FH#frag_state.foreign_key,
+ mnesia_schema:verify(undefined, ForeignKey,
+ {combine_error, Tab,
+ "Op only allowed via foreign table",
+ {foreign_key, ForeignKey}}).
+
+make_frag_names_and_acquire_locks(Tab, N, FragIndecies, DoNotLockN) ->
+ mnesia_schema:get_tid_ts_and_lock(Tab, write),
+ Fun = fun(Index, FN) ->
+ if
+ DoNotLockN == true, Index == N ->
+ Name = n_to_frag_name(Tab, Index),
+ setelement(Index, FN, Name);
+ true ->
+ Name = n_to_frag_name(Tab, Index),
+ mnesia_schema:get_tid_ts_and_lock(Name, write),
+ setelement(Index , FN, Name)
+ end
+ end,
+ FragNames = erlang:make_tuple(N, undefined),
+ lists:foldl(Fun, FragNames, FragIndecies).
+
+make_add_frag(Tab, SortedNs) ->
+ Cs = mnesia_schema:incr_version(val({Tab, cstruct})),
+ mnesia_schema:ensure_active(Cs),
+ FH = lookup_frag_hash(Tab),
+ {FH2, FromIndecies, WriteIndecies} = adjust_before_split(FH),
+ N = FH2#frag_state.n_fragments,
+ FragNames = make_frag_names_and_acquire_locks(Tab, N, WriteIndecies, true),
+ NewFrag = element(N, FragNames),
+
+ NR = length(Cs#cstruct.ram_copies),
+ ND = length(Cs#cstruct.disc_copies),
+ NDO = length(Cs#cstruct.disc_only_copies),
+ NewCs = Cs#cstruct{name = NewFrag,
+ frag_properties = [{base_table, Tab}],
+ ram_copies = [],
+ disc_copies = [],
+ disc_only_copies = []},
+ {NewCs2, _, _} = set_frag_nodes(NR, ND, NDO, NewCs, SortedNs, []),
+ [NewOp] = mnesia_schema:make_create_table(NewCs2),
+
+ SplitOps = split(Tab, FH2, FromIndecies, FragNames, []),
+
+ Cs2 = replace_frag_hash(Cs, FH2),
+ TabDef = mnesia_schema:cs2list(Cs2),
+ BaseOp = {op, change_table_frag, {add_frag, SortedNs}, TabDef},
+
+ [BaseOp, NewOp | SplitOps].
+
+replace_frag_hash(Cs, FH) when record(FH, frag_state) ->
+ Fun = fun(Prop) ->
+ case Prop of
+ {n_fragments, _} ->
+ {true, {n_fragments, FH#frag_state.n_fragments}};
+ {hash_module, _} ->
+ {true, {hash_module, FH#frag_state.hash_module}};
+ {hash_state, _} ->
+ {true, {hash_state, FH#frag_state.hash_state}};
+ {next_n_to_split, _} ->
+ false;
+ {n_doubles, _} ->
+ false;
+ _ ->
+ true
+ end
+ end,
+ Props = lists:zf(Fun, Cs#cstruct.frag_properties),
+ Cs#cstruct{frag_properties = Props}.
+
+%% Adjust table info before split
+adjust_before_split(FH) ->
+ HashState = FH#frag_state.hash_state,
+ {HashState2, FromFrags, AdditionalWriteFrags} =
+ case FH#frag_state.hash_module of
+ HashMod when HashMod == ?DEFAULT_HASH_MOD ->
+ ?DEFAULT_HASH_MOD:add_frag(HashState);
+ HashMod ->
+ HashMod:add_frag(HashState)
+ end,
+ N = FH#frag_state.n_fragments + 1,
+ FromFrags2 = (catch lists:sort(FromFrags)),
+ UnionFrags = (catch lists:merge(FromFrags2, lists:sort(AdditionalWriteFrags))),
+ VerifyFun = fun(F) when integer(F), F >= 1, F =< N -> false;
+ (_F) -> true
+ end,
+ case catch lists:filter(VerifyFun, UnionFrags) of
+ [] ->
+ FH2 = FH#frag_state{n_fragments = N,
+ hash_state = HashState2},
+ {FH2, FromFrags2, UnionFrags};
+ BadFrags ->
+ mnesia:abort({"add_frag: Fragment numbers out of range",
+ BadFrags, {range, 1, N}})
+ end.
+
+split(Tab, FH, [SplitN | SplitNs], FragNames, Ops) ->
+ SplitFrag = element(SplitN, FragNames),
+ Pat = mnesia:table_info(SplitFrag, wild_pattern),
+ {_Mod, Tid, Ts} = mnesia_schema:get_tid_ts_and_lock(Tab, none),
+ Recs = mnesia:match_object(Tid, Ts, SplitFrag, Pat, read),
+ Ops2 = do_split(FH, SplitN, FragNames, Recs, Ops),
+ split(Tab, FH, SplitNs, FragNames, Ops2);
+split(_Tab, _FH, [], _FragNames, Ops) ->
+ Ops.
+
+%% Perform the split of the table
+do_split(FH, OldN, FragNames, [Rec | Recs], Ops) ->
+ Pos = key_pos(FH),
+ HashKey = element(Pos, Rec),
+ case key_to_n(FH, HashKey) of
+ NewN when NewN == OldN ->
+ %% Keep record in the same fragment. No need to move it.
+ do_split(FH, OldN, FragNames, Recs, Ops);
+ NewN ->
+ case element(NewN, FragNames) of
+ NewFrag when NewFrag /= undefined ->
+ OldFrag = element(OldN, FragNames),
+ Key = element(2, Rec),
+ NewOid = {NewFrag, Key},
+ OldOid = {OldFrag, Key},
+ Ops2 = [{op, rec, unknown, {NewOid, [Rec], write}},
+ {op, rec, unknown, {OldOid, [OldOid], delete}} | Ops],
+ do_split(FH, OldN, FragNames, Recs, Ops2);
+ _NewFrag ->
+ %% Tried to move record to fragment that not is locked
+ mnesia:abort({"add_frag: Fragment not locked", NewN})
+ end
+ end;
+do_split(_FH, _OldN, _FragNames, [], Ops) ->
+ Ops.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Delete a fragment from a fragmented table
+%% and merge its records with an other fragment
+
+make_multi_del_frag(Tab) ->
+ verify_multi(Tab),
+ Ops = make_del_frag(Tab),
+
+ %% Propagate to foreigners
+ MoreOps = [make_del_frag(T) || T <- lookup_foreigners(Tab)],
+ [Ops | MoreOps].
+
+make_del_frag(Tab) ->
+ FH = lookup_frag_hash(Tab),
+ case FH#frag_state.n_fragments of
+ N when N > 1 ->
+ Cs = mnesia_schema:incr_version(val({Tab, cstruct})),
+ mnesia_schema:ensure_active(Cs),
+ {FH2, FromIndecies, WriteIndecies} = adjust_before_merge(FH),
+ FragNames = make_frag_names_and_acquire_locks(Tab, N, WriteIndecies, false),
+
+ MergeOps = merge(Tab, FH2, FromIndecies, FragNames, []),
+ LastFrag = element(N, FragNames),
+ [LastOp] = mnesia_schema:make_delete_table(LastFrag, single_frag),
+ Cs2 = replace_frag_hash(Cs, FH2),
+ TabDef = mnesia_schema:cs2list(Cs2),
+ BaseOp = {op, change_table_frag, del_frag, TabDef},
+ [BaseOp, LastOp | MergeOps];
+ _ ->
+ %% Cannot remove the last fragment
+ mnesia:abort({no_exists, Tab})
+ end.
+
+%% Adjust tab info before merge
+adjust_before_merge(FH) ->
+ HashState = FH#frag_state.hash_state,
+ {HashState2, FromFrags, AdditionalWriteFrags} =
+ case FH#frag_state.hash_module of
+ HashMod when HashMod == ?DEFAULT_HASH_MOD ->
+ ?DEFAULT_HASH_MOD:del_frag(HashState);
+ HashMod ->
+ HashMod:del_frag(HashState)
+ end,
+ N = FH#frag_state.n_fragments,
+ FromFrags2 = (catch lists:sort(FromFrags)),
+ UnionFrags = (catch lists:merge(FromFrags2, lists:sort(AdditionalWriteFrags))),
+ VerifyFun = fun(F) when integer(F), F >= 1, F =< N -> false;
+ (_F) -> true
+ end,
+ case catch lists:filter(VerifyFun, UnionFrags) of
+ [] ->
+ case lists:member(N, FromFrags2) of
+ true ->
+ FH2 = FH#frag_state{n_fragments = N - 1,
+ hash_state = HashState2},
+ {FH2, FromFrags2, UnionFrags};
+ false ->
+ mnesia:abort({"del_frag: Last fragment number not included", N})
+ end;
+ BadFrags ->
+ mnesia:abort({"del_frag: Fragment numbers out of range",
+ BadFrags, {range, 1, N}})
+ end.
+
+merge(Tab, FH, [FromN | FromNs], FragNames, Ops) ->
+ FromFrag = element(FromN, FragNames),
+ Pat = mnesia:table_info(FromFrag, wild_pattern),
+ {_Mod, Tid, Ts} = mnesia_schema:get_tid_ts_and_lock(Tab, none),
+ Recs = mnesia:match_object(Tid, Ts, FromFrag, Pat, read),
+ Ops2 = do_merge(FH, FromN, FragNames, Recs, Ops),
+ merge(Tab, FH, FromNs, FragNames, Ops2);
+merge(_Tab, _FH, [], _FragNames, Ops) ->
+ Ops.
+
+%% Perform the merge of the table
+do_merge(FH, OldN, FragNames, [Rec | Recs], Ops) ->
+ Pos = key_pos(FH),
+ LastN = FH#frag_state.n_fragments + 1,
+ HashKey = element(Pos, Rec),
+ case key_to_n(FH, HashKey) of
+ NewN when NewN == LastN ->
+ %% Tried to leave a record in the fragment that is to be deleted
+ mnesia:abort({"del_frag: Fragment number out of range",
+ NewN, {range, 1, LastN}});
+ NewN when NewN == OldN ->
+ %% Keep record in the same fragment. No need to move it.
+ do_merge(FH, OldN, FragNames, Recs, Ops);
+ NewN when OldN == LastN ->
+ %% Move record from the fragment that is to be deleted
+ %% No need to create a delete op for each record.
+ case element(NewN, FragNames) of
+ NewFrag when NewFrag /= undefined ->
+ Key = element(2, Rec),
+ NewOid = {NewFrag, Key},
+ Ops2 = [{op, rec, unknown, {NewOid, [Rec], write}} | Ops],
+ do_merge(FH, OldN, FragNames, Recs, Ops2);
+ _NewFrag ->
+ %% Tried to move record to fragment that not is locked
+ mnesia:abort({"del_frag: Fragment not locked", NewN})
+ end;
+ NewN ->
+ case element(NewN, FragNames) of
+ NewFrag when NewFrag /= undefined ->
+ OldFrag = element(OldN, FragNames),
+ Key = element(2, Rec),
+ NewOid = {NewFrag, Key},
+ OldOid = {OldFrag, Key},
+ Ops2 = [{op, rec, unknown, {NewOid, [Rec], write}},
+ {op, rec, unknown, {OldOid, [OldOid], delete}} | Ops],
+ do_merge(FH, OldN, FragNames, Recs, Ops2);
+ _NewFrag ->
+ %% Tried to move record to fragment that not is locked
+ mnesia:abort({"del_frag: Fragment not locked", NewN})
+ end
+ end;
+ do_merge(_FH, _OldN, _FragNames, [], Ops) ->
+ Ops.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Add a node to the node pool of a fragmented table
+
+make_multi_add_node(Tab, Node) ->
+ verify_multi(Tab),
+ Ops = make_add_node(Tab, Node),
+
+ %% Propagate to foreigners
+ MoreOps = [make_add_node(T, Node) || T <- lookup_foreigners(Tab)],
+ [Ops | MoreOps].
+
+make_add_node(Tab, Node) when atom(Node) ->
+ Pool = lookup_prop(Tab, node_pool),
+ case lists:member(Node, Pool) of
+ false ->
+ Cs = mnesia_schema:incr_version(val({Tab, cstruct})),
+ Pool2 = Pool ++ [Node],
+ Props = Cs#cstruct.frag_properties,
+ Props2 = lists:keyreplace(node_pool, 1, Props, {node_pool, Pool2}),
+ Cs2 = Cs#cstruct{frag_properties = Props2},
+ TabDef = mnesia_schema:cs2list(Cs2),
+ Op = {op, change_table_frag, {add_node, Node}, TabDef},
+ [Op];
+ true ->
+ mnesia:abort({already_exists, Tab, Node})
+ end;
+make_add_node(Tab, Node) ->
+ mnesia:abort({bad_type, Tab, Node}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Delet a node from the node pool of a fragmented table
+
+make_multi_del_node(Tab, Node) ->
+ verify_multi(Tab),
+ Ops = make_del_node(Tab, Node),
+
+ %% Propagate to foreigners
+ MoreOps = [make_del_node(T, Node) || T <- lookup_foreigners(Tab)],
+ [Ops | MoreOps].
+
+make_del_node(Tab, Node) when atom(Node) ->
+ Cs = mnesia_schema:incr_version(val({Tab, cstruct})),
+ mnesia_schema:ensure_active(Cs),
+ Pool = lookup_prop(Tab, node_pool),
+ case lists:member(Node, Pool) of
+ true ->
+ Pool2 = Pool -- [Node],
+ Props = lists:keyreplace(node_pool, 1, Cs#cstruct.frag_properties, {node_pool, Pool2}),
+ Cs2 = Cs#cstruct{frag_properties = Props},
+ TabDef = mnesia_schema:cs2list(Cs2),
+ Op = {op, change_table_frag, {del_node, Node}, TabDef},
+ [Op];
+ false ->
+ mnesia:abort({no_exists, Tab, Node})
+ end;
+make_del_node(Tab, Node) ->
+ mnesia:abort({bad_type, Tab, Node}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Special case used to remove all references to a node during
+%% mnesia:del_table_copy(schema, Node)
+
+remove_node(Node, Cs) ->
+ Tab = Cs#cstruct.name,
+ case is_top_frag(Tab) of
+ false ->
+ {Cs, false};
+ true ->
+ Pool = lookup_prop(Tab, node_pool),
+ case lists:member(Node, Pool) of
+ true ->
+ Pool2 = Pool -- [Node],
+ Props = lists:keyreplace(node_pool, 1,
+ Cs#cstruct.frag_properties,
+ {node_pool, Pool2}),
+ {Cs#cstruct{frag_properties = Props}, true};
+ false ->
+ {Cs, false}
+ end
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Helpers
+
+val(Var) ->
+ case ?catch_val(Var) of
+ {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
+ Value -> Value
+ end.
+
+set_frag_hash(Tab, Props) ->
+ case props_to_frag_hash(Tab, Props) of
+ FH when record(FH, frag_state) ->
+ mnesia_lib:set({Tab, frag_hash}, FH);
+ no_hash ->
+ mnesia_lib:unset({Tab, frag_hash})
+ end.
+
+props_to_frag_hash(_Tab, []) ->
+ no_hash;
+props_to_frag_hash(Tab, Props) ->
+ case mnesia_schema:pick(Tab, base_table, Props, undefined) of
+ T when T == Tab ->
+ Foreign = mnesia_schema:pick(Tab, foreign_key, Props, must),
+ N = mnesia_schema:pick(Tab, n_fragments, Props, must),
+
+ case mnesia_schema:pick(Tab, hash_module, Props, undefined) of
+ undefined ->
+ Split = mnesia_schema:pick(Tab, next_n_to_split, Props, must),
+ Doubles = mnesia_schema:pick(Tab, n_doubles, Props, must),
+ FH = {frag_hash, Foreign, N, Split, Doubles},
+ HashState = ?OLD_HASH_MOD:init_state(Tab, FH),
+ #frag_state{foreign_key = Foreign,
+ n_fragments = N,
+ hash_module = ?OLD_HASH_MOD,
+ hash_state = HashState};
+ HashMod ->
+ HashState = mnesia_schema:pick(Tab, hash_state, Props, must),
+ #frag_state{foreign_key = Foreign,
+ n_fragments = N,
+ hash_module = HashMod,
+ hash_state = HashState}
+ %% Old style. Kept for backwards compatibility.
+ end;
+ _ ->
+ no_hash
+ end.
+
+lookup_prop(Tab, Prop) ->
+ Props = val({Tab, frag_properties}),
+ case lists:keysearch(Prop, 1, Props) of
+ {value, {Prop, Val}} ->
+ Val;
+ false ->
+ mnesia:abort({no_exists, Tab, Prop, {frag_properties, Props}})
+ end.
+
+lookup_frag_hash(Tab) ->
+ case ?catch_val({Tab, frag_hash}) of
+ FH when record(FH, frag_state) ->
+ FH;
+ {frag_hash, K, N, _S, _D} = FH ->
+ %% Old style. Kept for backwards compatibility.
+ HashState = ?OLD_HASH_MOD:init_state(Tab, FH),
+ #frag_state{foreign_key = K,
+ n_fragments = N,
+ hash_module = ?OLD_HASH_MOD,
+ hash_state = HashState};
+ {'EXIT', _} ->
+ mnesia:abort({no_exists, Tab, frag_properties, frag_hash})
+ end.
+
+is_top_frag(Tab) ->
+ case ?catch_val({Tab, frag_hash}) of
+ {'EXIT', _} ->
+ false;
+ _ ->
+ [] == lookup_foreigners(Tab)
+ end.
+
+%% Returns a list of tables
+lookup_foreigners(Tab) ->
+ %% First field in HashPat is either frag_hash or frag_state
+ HashPat = {'_', {Tab, '_'}, '_', '_', '_'},
+ [T || [T] <- ?ets_match(mnesia_gvar, {{'$1', frag_hash}, HashPat})].
+
+%% Returns name of fragment table
+record_to_frag_name(Tab, Rec) ->
+ case ?catch_val({Tab, frag_hash}) of
+ {'EXIT', _} ->
+ Tab;
+ FH ->
+ Pos = key_pos(FH),
+ Key = element(Pos, Rec),
+ N = key_to_n(FH, Key),
+ n_to_frag_name(Tab, N)
+ end.
+
+key_pos(FH) ->
+ case FH#frag_state.foreign_key of
+ undefined ->
+ 2;
+ {_ForeignTab, Pos} ->
+ Pos
+ end.
+
+%% Returns name of fragment table
+key_to_frag_name({BaseTab, _} = Tab, Key) ->
+ N = key_to_frag_number(Tab, Key),
+ n_to_frag_name(BaseTab, N);
+key_to_frag_name(Tab, Key) ->
+ N = key_to_frag_number(Tab, Key),
+ n_to_frag_name(Tab, N).
+
+%% Returns name of fragment table
+n_to_frag_name(Tab, 1) ->
+ Tab;
+n_to_frag_name(Tab, N) when atom(Tab), integer(N) ->
+ list_to_atom(atom_to_list(Tab) ++ "_frag" ++ integer_to_list(N));
+n_to_frag_name(Tab, N) ->
+ mnesia:abort({bad_type, Tab, N}).
+
+%% Returns name of fragment table
+key_to_frag_number({Tab, ForeignKey}, _Key) ->
+ FH = val({Tab, frag_hash}),
+ case FH#frag_state.foreign_key of
+ {_ForeignTab, _Pos} ->
+ key_to_n(FH, ForeignKey);
+ undefined ->
+ mnesia:abort({combine_error, Tab, frag_properties,
+ {foreign_key, undefined}})
+ end;
+key_to_frag_number(Tab, Key) ->
+ case ?catch_val({Tab, frag_hash}) of
+ {'EXIT', _} ->
+ 1;
+ FH ->
+ key_to_n(FH, Key)
+ end.
+
+%% Returns fragment number
+key_to_n(FH, Key) ->
+ HashState = FH#frag_state.hash_state,
+ N =
+ case FH#frag_state.hash_module of
+ HashMod when HashMod == ?DEFAULT_HASH_MOD ->
+ ?DEFAULT_HASH_MOD:key_to_frag_number(HashState, Key);
+ HashMod ->
+ HashMod:key_to_frag_number(HashState, Key)
+ end,
+ if
+ integer(N), N >= 1, N =< FH#frag_state.n_fragments ->
+ N;
+ true ->
+ mnesia:abort({"key_to_frag_number: Fragment number out of range",
+ N, {range, 1, FH#frag_state.n_fragments}})
+ end.
+
+%% Returns a list of frament table names
+frag_names(Tab) ->
+ case ?catch_val({Tab, frag_hash}) of
+ {'EXIT', _} ->
+ [Tab];
+ FH ->
+ N = FH#frag_state.n_fragments,
+ frag_names(Tab, N, [])
+ end.
+
+frag_names(Tab, 1, Acc) ->
+ [Tab | Acc];
+frag_names(Tab, N, Acc) ->
+ Frag = n_to_frag_name(Tab, N),
+ frag_names(Tab, N - 1, [Frag | Acc]).
+
+%% Returns a list of {Node, FragCount} tuples
+%% sorted on FragCounts
+frag_dist(Tab) ->
+ Pool = lookup_prop(Tab, node_pool),
+ Dist = [{good, Node, 0} || Node <- Pool],
+ Dist2 = count_frag(frag_names(Tab), Dist),
+ sort_dist(Dist2).
+
+count_frag([Frag | Frags], Dist) ->
+ Dist2 = incr_nodes(val({Frag, ram_copies}), Dist),
+ Dist3 = incr_nodes(val({Frag, disc_copies}), Dist2),
+ Dist4 = incr_nodes(val({Frag, disc_only_copies}), Dist3),
+ count_frag(Frags, Dist4);
+count_frag([], Dist) ->
+ Dist.
+
+incr_nodes([Node | Nodes], Dist) ->
+ Dist2 = incr_node(Node, Dist),
+ incr_nodes(Nodes, Dist2);
+incr_nodes([], Dist) ->
+ Dist.
+
+incr_node(Node, [{Kind, Node, Count} | Tail]) ->
+ [{Kind, Node, Count + 1} | Tail];
+incr_node(Node, [Head | Tail]) ->
+ [Head | incr_node(Node, Tail)];
+incr_node(Node, []) ->
+ [{bad, Node, 1}].
+
+%% Sorts dist according in decreasing count order
+sort_dist(Dist) ->
+ Dist2 = deep_dist(Dist, []),
+ Dist3 = lists:keysort(1, Dist2),
+ shallow_dist(Dist3).
+
+deep_dist([Head | Tail], Deep) ->
+ {Kind, _Node, Count} = Head,
+ {Tag, Same, Other} = pick_count(Kind, Count, [Head | Tail]),
+ deep_dist(Other, [{Tag, Same} | Deep]);
+deep_dist([], Deep) ->
+ Deep.
+
+pick_count(Kind, Count, [{Kind2, Node2, Count2} | Tail]) ->
+ Head = {Node2, Count2},
+ {_, Same, Other} = pick_count(Kind, Count, Tail),
+ if
+ Kind == bad ->
+ {bad, [Head | Same], Other};
+ Kind2 == bad ->
+ {Count, Same, [{Kind2, Node2, Count2} | Other]};
+ Count == Count2 ->
+ {Count, [Head | Same], Other};
+ true ->
+ {Count, Same, [{Kind2, Node2, Count2} | Other]}
+ end;
+pick_count(_Kind, Count, []) ->
+ {Count, [], []}.
+
+shallow_dist([{_Tag, Shallow} | Deep]) ->
+ Shallow ++ shallow_dist(Deep);
+shallow_dist([]) ->
+ [].
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_frag_hash.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_frag_hash.erl
new file mode 100644
index 0000000000..591f2ce9c8
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_frag_hash.erl
@@ -0,0 +1,118 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_frag_hash.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
+%%
+%%%----------------------------------------------------------------------
+%%% Purpose : Implements hashing functionality for fragmented tables
+%%%----------------------------------------------------------------------
+
+%header_doc_include
+-module(mnesia_frag_hash).
+-behaviour(mnesia_frag_hash).
+
+%% Fragmented Table Hashing callback functions
+-export([
+ init_state/2,
+ add_frag/1,
+ del_frag/1,
+ key_to_frag_number/2,
+ match_spec_to_frag_numbers/2
+ ]).
+
+%header_doc_include
+
+%impl_doc_include
+-record(hash_state, {n_fragments, next_n_to_split, n_doubles}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+init_state(_Tab, State) when State == undefined ->
+ #hash_state{n_fragments = 1,
+ next_n_to_split = 1,
+ n_doubles = 0}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+add_frag(State) when record(State, hash_state) ->
+ SplitN = State#hash_state.next_n_to_split,
+ P = SplitN + 1,
+ L = State#hash_state.n_doubles,
+ NewN = State#hash_state.n_fragments + 1,
+ State2 = case trunc(math:pow(2, L)) + 1 of
+ P2 when P2 == P ->
+ State#hash_state{n_fragments = NewN,
+ n_doubles = L + 1,
+ next_n_to_split = 1};
+ _ ->
+ State#hash_state{n_fragments = NewN,
+ next_n_to_split = P}
+ end,
+ {State2, [SplitN], [NewN]}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+del_frag(State) when record(State, hash_state) ->
+ P = State#hash_state.next_n_to_split - 1,
+ L = State#hash_state.n_doubles,
+ N = State#hash_state.n_fragments,
+ if
+ P < 1 ->
+ L2 = L - 1,
+ MergeN = trunc(math:pow(2, L2)),
+ State2 = State#hash_state{n_fragments = N - 1,
+ next_n_to_split = MergeN,
+ n_doubles = L2},
+ {State2, [N], [MergeN]};
+ true ->
+ MergeN = P,
+ State2 = State#hash_state{n_fragments = N - 1,
+ next_n_to_split = MergeN},
+ {State2, [N], [MergeN]}
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+key_to_frag_number(State, Key) when record(State, hash_state) ->
+ L = State#hash_state.n_doubles,
+ A = erlang:phash(Key, trunc(math:pow(2, L))),
+ P = State#hash_state.next_n_to_split,
+ if
+ A < P ->
+ erlang:phash(Key, trunc(math:pow(2, L + 1)));
+ true ->
+ A
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+match_spec_to_frag_numbers(State, MatchSpec) when record(State, hash_state) ->
+ case MatchSpec of
+ [{HeadPat, _, _}] when tuple(HeadPat), size(HeadPat) > 2 ->
+ KeyPat = element(2, HeadPat),
+ case has_var(KeyPat) of
+ false ->
+ [key_to_frag_number(State, KeyPat)];
+ true ->
+ lists:seq(1, State#hash_state.n_fragments)
+ end;
+ _ ->
+ lists:seq(1, State#hash_state.n_fragments)
+ end.
+
+%impl_doc_include
+
+has_var(Pat) ->
+ mnesia:has_var(Pat).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_frag_old_hash.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_frag_old_hash.erl
new file mode 100644
index 0000000000..8dc128a42e
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_frag_old_hash.erl
@@ -0,0 +1,127 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_frag_old_hash.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
+%%
+%%%----------------------------------------------------------------------
+%%% Purpose : Implements hashing functionality for fragmented tables
+%%%----------------------------------------------------------------------
+
+-module(mnesia_frag_old_hash).
+-behaviour(mnesia_frag_hash).
+
+%% Hashing callback functions
+-export([
+ init_state/2,
+ add_frag/1,
+ del_frag/1,
+ key_to_frag_number/2,
+ match_spec_to_frag_numbers/2
+ ]).
+
+-record(old_hash_state,
+ {n_fragments,
+ next_n_to_split,
+ n_doubles}).
+
+%% Old style. Kept for backwards compatibility.
+-record(frag_hash,
+ {foreign_key,
+ n_fragments,
+ next_n_to_split,
+ n_doubles}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+init_state(_Tab, InitialState) when InitialState == undefined ->
+ #old_hash_state{n_fragments = 1,
+ next_n_to_split = 1,
+ n_doubles = 0};
+init_state(_Tab, FH) when record(FH, frag_hash) ->
+ %% Old style. Kept for backwards compatibility.
+ #old_hash_state{n_fragments = FH#frag_hash.n_fragments,
+ next_n_to_split = FH#frag_hash.next_n_to_split,
+ n_doubles = FH#frag_hash.n_doubles}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+add_frag(State) when record(State, old_hash_state) ->
+ SplitN = State#old_hash_state.next_n_to_split,
+ P = SplitN + 1,
+ L = State#old_hash_state.n_doubles,
+ NewN = State#old_hash_state.n_fragments + 1,
+ State2 = case trunc(math:pow(2, L)) + 1 of
+ P2 when P2 == P ->
+ State#old_hash_state{n_fragments = NewN,
+ next_n_to_split = 1,
+ n_doubles = L + 1};
+ _ ->
+ State#old_hash_state{n_fragments = NewN,
+ next_n_to_split = P}
+ end,
+ {State2, [SplitN], [NewN]}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+del_frag(State) when record(State, old_hash_state) ->
+ P = State#old_hash_state.next_n_to_split - 1,
+ L = State#old_hash_state.n_doubles,
+ N = State#old_hash_state.n_fragments,
+ if
+ P < 1 ->
+ L2 = L - 1,
+ MergeN = trunc(math:pow(2, L2)),
+ State2 = State#old_hash_state{n_fragments = N - 1,
+ next_n_to_split = MergeN,
+ n_doubles = L2},
+ {State2, [N], [MergeN]};
+ true ->
+ MergeN = P,
+ State2 = State#old_hash_state{n_fragments = N - 1,
+ next_n_to_split = MergeN},
+ {State2, [N], [MergeN]}
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+key_to_frag_number(State, Key) when record(State, old_hash_state) ->
+ L = State#old_hash_state.n_doubles,
+ A = erlang:hash(Key, trunc(math:pow(2, L))),
+ P = State#old_hash_state.next_n_to_split,
+ if
+ A < P ->
+ erlang:hash(Key, trunc(math:pow(2, L + 1)));
+ true ->
+ A
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+match_spec_to_frag_numbers(State, MatchSpec) when record(State, old_hash_state) ->
+ case MatchSpec of
+ [{HeadPat, _, _}] when tuple(HeadPat), size(HeadPat) > 2 ->
+ KeyPat = element(2, HeadPat),
+ case has_var(KeyPat) of
+ false ->
+ [key_to_frag_number(State, KeyPat)];
+ true ->
+ lists:seq(1, State#old_hash_state.n_fragments)
+ end;
+ _ ->
+ lists:seq(1, State#old_hash_state.n_fragments)
+ end.
+
+has_var(Pat) ->
+ mnesia:has_var(Pat).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_index.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_index.erl
new file mode 100644
index 0000000000..650a2d1d3c
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_index.erl
@@ -0,0 +1,379 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_index.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
+%%
+%% Purpose: Handles index functionality in mnesia
+
+-module(mnesia_index).
+-export([read/5,
+ add_index/5,
+ delete_index/3,
+ del_object_index/5,
+ clear_index/4,
+ dirty_match_object/3,
+ dirty_select/3,
+ dirty_read/3,
+ dirty_read2/3,
+
+ db_put/2,
+ db_get/2,
+ db_match_erase/2,
+ get_index_table/2,
+ get_index_table/3,
+
+ tab2filename/2,
+ tab2tmp_filename/2,
+ init_index/2,
+ init_indecies/3,
+ del_transient/2,
+ del_transient/3,
+ del_index_table/3]).
+
+-import(mnesia_lib, [verbose/2]).
+-include("mnesia.hrl").
+
+-record(index, {setorbag, pos_list}).
+
+val(Var) ->
+ case ?catch_val(Var) of
+ {'EXIT', _ReASoN_} -> mnesia_lib:other_val(Var, _ReASoN_);
+ _VaLuE_ -> _VaLuE_
+ end.
+
+%% read an object list throuh its index table
+%% we assume that table Tab has index on attribute number Pos
+
+read(Tid, Store, Tab, IxKey, Pos) ->
+ ResList = mnesia_locker:ixrlock(Tid, Store, Tab, IxKey, Pos),
+ %% Remove all tuples which don't include Ixkey, happens when Tab is a bag
+ case val({Tab, setorbag}) of
+ bag ->
+ mnesia_lib:key_search_all(IxKey, Pos, ResList);
+ _ ->
+ ResList
+ end.
+
+add_index(Index, Tab, Key, Obj, Old) ->
+ add_index2(Index#index.pos_list, Index#index.setorbag, Tab, Key, Obj, Old).
+
+add_index2([{Pos, Ixt} |Tail], bag, Tab, K, Obj, OldRecs) ->
+ db_put(Ixt, {element(Pos, Obj), K}),
+ add_index2(Tail, bag, Tab, K, Obj, OldRecs);
+add_index2([{Pos, Ixt} |Tail], Type, Tab, K, Obj, OldRecs) ->
+ %% Remove old tuples in index if Tab is updated
+ case OldRecs of
+ undefined ->
+ Old = mnesia_lib:db_get(Tab, K),
+ del_ixes(Ixt, Old, Pos, K);
+ Old ->
+ del_ixes(Ixt, Old, Pos, K)
+ end,
+ db_put(Ixt, {element(Pos, Obj), K}),
+ add_index2(Tail, Type, Tab, K, Obj, OldRecs);
+add_index2([], _, _Tab, _K, _Obj, _) -> ok.
+
+delete_index(Index, Tab, K) ->
+ delete_index2(Index#index.pos_list, Tab, K).
+
+delete_index2([{Pos, Ixt} | Tail], Tab, K) ->
+ DelObjs = mnesia_lib:db_get(Tab, K),
+ del_ixes(Ixt, DelObjs, Pos, K),
+ delete_index2(Tail, Tab, K);
+delete_index2([], _Tab, _K) -> ok.
+
+
+del_ixes(_Ixt, [], _Pos, _L) -> ok;
+del_ixes(Ixt, [Obj | Tail], Pos, Key) ->
+ db_match_erase(Ixt, {element(Pos, Obj), Key}),
+ del_ixes(Ixt, Tail, Pos, Key).
+
+del_object_index(Index, Tab, K, Obj, Old) ->
+ del_object_index2(Index#index.pos_list, Index#index.setorbag, Tab, K, Obj, Old).
+
+del_object_index2([], _, _Tab, _K, _Obj, _Old) -> ok;
+del_object_index2([{Pos, Ixt} | Tail], SoB, Tab, K, Obj, Old) ->
+ case SoB of
+ bag ->
+ del_object_bag(Tab, K, Obj, Pos, Ixt, Old);
+ _ -> %% If set remove the tuple in index table
+ del_ixes(Ixt, [Obj], Pos, K)
+ end,
+ del_object_index2(Tail, SoB, Tab, K, Obj, Old).
+
+del_object_bag(Tab, Key, Obj, Pos, Ixt, undefined) ->
+ Old = mnesia_lib:db_get(Tab, Key),
+ del_object_bag(Tab, Key, Obj, Pos, Ixt, Old);
+%% If Tab type is bag we need remove index identifier if Tab
+%% contains less than 2 elements.
+del_object_bag(_Tab, Key, Obj, Pos, Ixt, Old) when length(Old) < 2 ->
+ del_ixes(Ixt, [Obj], Pos, Key);
+del_object_bag(_Tab, _Key, _Obj, _Pos, _Ixt, _Old) -> ok.
+
+clear_index(Index, Tab, K, Obj) ->
+ clear_index2(Index#index.pos_list, Tab, K, Obj).
+
+clear_index2([], _Tab, _K, _Obj) -> ok;
+clear_index2([{_Pos, Ixt} | Tail], Tab, K, Obj) ->
+ db_match_erase(Ixt, Obj),
+ clear_index2(Tail, Tab, K, Obj).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+dirty_match_object(Tab, Pat, Pos) ->
+ %% Assume that we are on the node where the replica is
+ case element(2, Pat) of
+ '_' ->
+ IxKey = element(Pos, Pat),
+ RealKeys = realkeys(Tab, Pos, IxKey),
+ merge(RealKeys, Tab, Pat, []);
+ _Else ->
+ mnesia_lib:db_match_object(Tab, Pat)
+ end.
+
+merge([{_IxKey, RealKey} | Tail], Tab, Pat, Ack) ->
+ %% Assume that we are on the node where the replica is
+ Pat2 = setelement(2, Pat, RealKey),
+ Recs = mnesia_lib:db_match_object(Tab, Pat2),
+ merge(Tail, Tab, Pat, Recs ++ Ack);
+merge([], _, _, Ack) ->
+ Ack.
+
+realkeys(Tab, Pos, IxKey) ->
+ Index = get_index_table(Tab, Pos),
+ db_get(Index, IxKey). % a list on the form [{IxKey, RealKey1} , ....
+
+dirty_select(Tab, Spec, Pos) ->
+ %% Assume that we are on the node where the replica is
+ %% Returns the records without applying the match spec
+ %% The actual filtering is handled by the caller
+ IxKey = element(Pos, Spec),
+ RealKeys = realkeys(Tab, Pos, IxKey),
+ StorageType = val({Tab, storage_type}),
+ lists:append([mnesia_lib:db_get(StorageType, Tab, Key) || Key <- RealKeys]).
+
+dirty_read(Tab, IxKey, Pos) ->
+ ResList = mnesia:dirty_rpc(Tab, ?MODULE, dirty_read2,
+ [Tab, IxKey, Pos]),
+ case val({Tab, setorbag}) of
+ bag ->
+ %% Remove all tuples which don't include Ixkey
+ mnesia_lib:key_search_all(IxKey, Pos, ResList);
+ _ ->
+ ResList
+ end.
+
+dirty_read2(Tab, IxKey, Pos) ->
+ Ix = get_index_table(Tab, Pos),
+ Keys = db_match(Ix, {IxKey, '$1'}),
+ r_keys(Keys, Tab, []).
+
+r_keys([[H]|T],Tab,Ack) ->
+ V = mnesia_lib:db_get(Tab, H),
+ r_keys(T, Tab, V ++ Ack);
+r_keys([], _, Ack) ->
+ Ack.
+
+
+%%%%%%% Creation, Init and deletion routines for index tables
+%% We can have several indexes on the same table
+%% this can be a fairly costly operation if table is *very* large
+
+tab2filename(Tab, Pos) ->
+ mnesia_lib:dir(Tab) ++ "_" ++ integer_to_list(Pos) ++ ".DAT".
+
+tab2tmp_filename(Tab, Pos) ->
+ mnesia_lib:dir(Tab) ++ "_" ++ integer_to_list(Pos) ++ ".TMP".
+
+init_index(Tab, Storage) ->
+ PosList = val({Tab, index}),
+ init_indecies(Tab, Storage, PosList).
+
+init_indecies(Tab, Storage, PosList) ->
+ case Storage of
+ unknown ->
+ ignore;
+ disc_only_copies ->
+ init_disc_index(Tab, PosList);
+ ram_copies ->
+ make_ram_index(Tab, PosList);
+ disc_copies ->
+ make_ram_index(Tab, PosList)
+ end.
+
+%% works for both ram and disc indexes
+
+del_index_table(_, unknown, _) ->
+ ignore;
+del_index_table(Tab, Storage, Pos) ->
+ delete_transient_index(Tab, Pos, Storage),
+ mnesia_lib:del({Tab, index}, Pos).
+
+del_transient(Tab, Storage) ->
+ PosList = val({Tab, index}),
+ del_transient(Tab, PosList, Storage).
+
+del_transient(_, [], _) -> done;
+del_transient(Tab, [Pos | Tail], Storage) ->
+ delete_transient_index(Tab, Pos, Storage),
+ del_transient(Tab, Tail, Storage).
+
+delete_transient_index(Tab, Pos, disc_only_copies) ->
+ Tag = {Tab, index, Pos},
+ mnesia_monitor:unsafe_close_dets(Tag),
+ file:delete(tab2filename(Tab, Pos)),
+ del_index_info(Tab, Pos), %% Uses val(..)
+ mnesia_lib:unset({Tab, {index, Pos}});
+
+delete_transient_index(Tab, Pos, _Storage) ->
+ Ixt = val({Tab, {index, Pos}}),
+ ?ets_delete_table(Ixt),
+ del_index_info(Tab, Pos),
+ mnesia_lib:unset({Tab, {index, Pos}}).
+
+%%%%% misc functions for the index create/init/delete functions above
+
+%% assuming that the file exists.
+init_disc_index(_Tab, []) ->
+ done;
+init_disc_index(Tab, [Pos | Tail]) when integer(Pos) ->
+ Fn = tab2filename(Tab, Pos),
+ IxTag = {Tab, index, Pos},
+ file:delete(Fn),
+ Args = [{file, Fn}, {keypos, 1}, {type, bag}],
+ mnesia_monitor:open_dets(IxTag, Args),
+ Storage = disc_only_copies,
+ Key = mnesia_lib:db_first(Storage, Tab),
+ Recs = mnesia_lib:db_get(Storage, Tab, Key),
+ BinSize = size(term_to_binary(Recs)),
+ KeysPerChunk = (4000 div BinSize) + 1,
+ Init = {start, KeysPerChunk},
+ mnesia_lib:db_fixtable(Storage, Tab, true),
+ ok = dets:init_table(IxTag, create_fun(Init, Tab, Pos)),
+ mnesia_lib:db_fixtable(Storage, Tab, false),
+ mnesia_lib:set({Tab, {index, Pos}}, IxTag),
+ add_index_info(Tab, val({Tab, setorbag}), {Pos, {dets, IxTag}}),
+ init_disc_index(Tab, Tail).
+
+create_fun(Cont, Tab, Pos) ->
+ fun(read) ->
+ Data =
+ case Cont of
+ {start, KeysPerChunk} ->
+ mnesia_lib:db_init_chunk(disc_only_copies, Tab, KeysPerChunk);
+ '$end_of_table' ->
+ '$end_of_table';
+ _Else ->
+ mnesia_lib:db_chunk(disc_only_copies, Cont)
+ end,
+ case Data of
+ '$end_of_table' ->
+ end_of_input;
+ {Recs, Next} ->
+ IdxElems = [{element(Pos, Obj), element(2, Obj)} || Obj <- Recs],
+ {IdxElems, create_fun(Next, Tab, Pos)}
+ end;
+ (close) ->
+ ok
+ end.
+
+make_ram_index(_, []) ->
+ done;
+make_ram_index(Tab, [Pos | Tail]) ->
+ add_ram_index(Tab, Pos),
+ make_ram_index(Tab, Tail).
+
+add_ram_index(Tab, Pos) when integer(Pos) ->
+ verbose("Creating index for ~w ~n", [Tab]),
+ Index = mnesia_monitor:mktab(mnesia_index, [bag, public]),
+ Insert = fun(Rec, _Acc) ->
+ true = ?ets_insert(Index, {element(Pos, Rec), element(2, Rec)})
+ end,
+ mnesia_lib:db_fixtable(ram_copies, Tab, true),
+ true = ets:foldl(Insert, true, Tab),
+ mnesia_lib:db_fixtable(ram_copies, Tab, false),
+ mnesia_lib:set({Tab, {index, Pos}}, Index),
+ add_index_info(Tab, val({Tab, setorbag}), {Pos, {ram, Index}});
+add_ram_index(_Tab, snmp) ->
+ ok.
+
+add_index_info(Tab, Type, IxElem) ->
+ Commit = val({Tab, commit_work}),
+ case lists:keysearch(index, 1, Commit) of
+ false ->
+ Index = #index{setorbag = Type,
+ pos_list = [IxElem]},
+ %% Check later if mnesia_tm is sensative about the order
+ mnesia_lib:set({Tab, commit_work},
+ mnesia_lib:sort_commit([Index | Commit]));
+ {value, Old} ->
+ %% We could check for consistency here
+ Index = Old#index{pos_list = [IxElem | Old#index.pos_list]},
+ NewC = lists:keyreplace(index, 1, Commit, Index),
+ mnesia_lib:set({Tab, commit_work},
+ mnesia_lib:sort_commit(NewC))
+ end.
+
+del_index_info(Tab, Pos) ->
+ Commit = val({Tab, commit_work}),
+ case lists:keysearch(index, 1, Commit) of
+ false ->
+ %% Something is wrong ignore
+ skip;
+ {value, Old} ->
+ case lists:keydelete(Pos, 1, Old#index.pos_list) of
+ [] ->
+ NewC = lists:keydelete(index, 1, Commit),
+ mnesia_lib:set({Tab, commit_work},
+ mnesia_lib:sort_commit(NewC));
+ New ->
+ Index = Old#index{pos_list = New},
+ NewC = lists:keyreplace(index, 1, Commit, Index),
+ mnesia_lib:set({Tab, commit_work},
+ mnesia_lib:sort_commit(NewC))
+ end
+ end.
+
+db_put({ram, Ixt}, V) ->
+ true = ?ets_insert(Ixt, V);
+db_put({dets, Ixt}, V) ->
+ ok = dets:insert(Ixt, V).
+
+db_get({ram, Ixt}, K) ->
+ ?ets_lookup(Ixt, K);
+db_get({dets, Ixt}, K) ->
+ dets:lookup(Ixt, K).
+
+db_match_erase({ram, Ixt}, Pat) ->
+ true = ?ets_match_delete(Ixt, Pat);
+db_match_erase({dets, Ixt}, Pat) ->
+ ok = dets:match_delete(Ixt, Pat).
+
+db_match({ram, Ixt}, Pat) ->
+ ?ets_match(Ixt, Pat);
+db_match({dets, Ixt}, Pat) ->
+ dets:match(Ixt, Pat).
+
+get_index_table(Tab, Pos) ->
+ get_index_table(Tab, val({Tab, storage_type}), Pos).
+
+get_index_table(Tab, ram_copies, Pos) ->
+ {ram, val({Tab, {index, Pos}})};
+get_index_table(Tab, disc_copies, Pos) ->
+ {ram, val({Tab, {index, Pos}})};
+get_index_table(Tab, disc_only_copies, Pos) ->
+ {dets, val({Tab, {index, Pos}})};
+get_index_table(_Tab, unknown, _Pos) ->
+ unknown.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_kernel_sup.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_kernel_sup.erl
new file mode 100644
index 0000000000..015a42c749
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_kernel_sup.erl
@@ -0,0 +1,60 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_kernel_sup.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
+%%
+-module(mnesia_kernel_sup).
+
+-behaviour(supervisor).
+
+-export([start/0, init/1, supervisor_timeout/1]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% top supervisor callback functions
+
+start() ->
+ supervisor:start_link({local, mnesia_kernel_sup}, ?MODULE, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% sub supervisor callback functions
+
+init([]) ->
+ ProcLib = [mnesia_monitor, proc_lib],
+ Flags = {one_for_all, 0, timer:hours(24)}, % Trust the top supervisor
+ Workers = [worker_spec(mnesia_monitor, timer:seconds(3), [gen_server]),
+ worker_spec(mnesia_subscr, timer:seconds(3), [gen_server]),
+ worker_spec(mnesia_locker, timer:seconds(3), ProcLib),
+ worker_spec(mnesia_recover, timer:minutes(3), [gen_server]),
+ worker_spec(mnesia_tm, timer:seconds(30), ProcLib),
+ supervisor_spec(mnesia_checkpoint_sup),
+ supervisor_spec(mnesia_snmp_sup),
+ worker_spec(mnesia_controller, timer:seconds(3), [gen_server]),
+ worker_spec(mnesia_late_loader, timer:seconds(3), ProcLib)
+ ],
+ {ok, {Flags, Workers}}.
+
+worker_spec(Name, KillAfter, Modules) ->
+ KA = supervisor_timeout(KillAfter),
+ {Name, {Name, start, []}, permanent, KA, worker, [Name] ++ Modules}.
+
+supervisor_spec(Name) ->
+ {Name, {Name, start, []}, permanent, infinity, supervisor,
+ [Name, supervisor]}.
+
+-ifdef(debug_shutdown).
+supervisor_timeout(_KillAfter) -> timer:hours(24).
+-else.
+supervisor_timeout(KillAfter) -> KillAfter.
+-endif.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_late_loader.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_late_loader.erl
new file mode 100644
index 0000000000..b49cf22fd9
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_late_loader.erl
@@ -0,0 +1,95 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_late_loader.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
+%%
+-module(mnesia_late_loader).
+
+-export([
+ async_late_disc_load/3,
+ maybe_async_late_disc_load/3,
+ init/1,
+ start/0
+ ]).
+
+%% sys callback functions
+-export([
+ system_continue/3,
+ system_terminate/4,
+ system_code_change/4
+ ]).
+
+-define(SERVER_NAME, ?MODULE).
+
+-record(state, {supervisor}).
+
+async_late_disc_load(Node, Tabs, Reason) ->
+ Msg = {async_late_disc_load, Tabs, Reason},
+ catch ({?SERVER_NAME, Node} ! {self(), Msg}).
+
+maybe_async_late_disc_load(Node, Tabs, Reason) ->
+ Msg = {maybe_async_late_disc_load, Tabs, Reason},
+ catch ({?SERVER_NAME, Node} ! {self(), Msg}).
+
+start() ->
+ mnesia_monitor:start_proc(?SERVER_NAME, ?MODULE, init, [self()]).
+
+init(Parent) ->
+ %% Trap exit omitted intentionally
+ register(?SERVER_NAME, self()),
+ link(whereis(mnesia_controller)), %% We may not hang
+ mnesia_controller:merge_schema(),
+ unlink(whereis(mnesia_controller)),
+ mnesia_lib:set(mnesia_status, running),
+ proc_lib:init_ack(Parent, {ok, self()}),
+ loop(#state{supervisor = Parent}).
+
+loop(State) ->
+ receive
+ {_From, {async_late_disc_load, Tabs, Reason}} ->
+ mnesia_controller:schedule_late_disc_load(Tabs, Reason),
+ loop(State);
+
+ {_From, {maybe_async_late_disc_load, Tabs, Reason}} ->
+ GoodTabs =
+ [T || T <- Tabs,
+ lists:member(node(),
+ mnesia_recover:get_master_nodes(T))],
+ mnesia_controller:schedule_late_disc_load(GoodTabs, Reason),
+ loop(State);
+
+ {system, From, Msg} ->
+ mnesia_lib:dbg_out("~p got {system, ~p, ~p}~n",
+ [?SERVER_NAME, From, Msg]),
+ Parent = State#state.supervisor,
+ sys:handle_system_msg(Msg, From, Parent, ?MODULE, [], State);
+
+ Msg ->
+ mnesia_lib:error("~p got unexpected message: ~p~n",
+ [?SERVER_NAME, Msg]),
+ loop(State)
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% System upgrade
+
+system_continue(_Parent, _Debug, State) ->
+ loop(State).
+
+system_terminate(Reason, _Parent, _Debug, _State) ->
+ exit(Reason).
+
+system_code_change(State, _Module, _OldVsn, _Extra) ->
+ {ok, State}.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_lib.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_lib.erl
new file mode 100644
index 0000000000..29a54936d4
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_lib.erl
@@ -0,0 +1,1276 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_lib.erl,v 1.3 2009/07/01 15:45:40 kostis Exp $
+%%
+%% This module contains all sorts of various which doesn't fit
+%% anywhere else. Basically everything is exported.
+
+-module(mnesia_lib).
+
+-include("mnesia.hrl").
+-include_lib("kernel/include/file.hrl").
+
+-export([core_file/0]).
+
+-export([
+ active_tables/0,
+ add/2,
+ add_list/2,
+ all_nodes/0,
+%% catch_val/1,
+ cleanup_tmp_files/1,
+ copy_file/2,
+ copy_holders/1,
+ coredump/0,
+ coredump/1,
+ create_counter/1,
+ cs_to_nodes/1,
+ cs_to_storage_type/2,
+ dets_to_ets/6,
+ db_chunk/2,
+ db_init_chunk/1,
+ db_init_chunk/2,
+ db_init_chunk/3,
+ db_erase/2,
+ db_erase/3,
+ db_erase_tab/1,
+ db_erase_tab/2,
+ db_first/1,
+ db_first/2,
+ db_last/1,
+ db_last/2,
+ db_fixtable/3,
+ db_get/2,
+ db_get/3,
+ db_match_erase/2,
+ db_match_erase/3,
+ db_match_object/2,
+ db_match_object/3,
+ db_next_key/2,
+ db_next_key/3,
+ db_prev_key/2,
+ db_prev_key/3,
+ db_put/2,
+ db_put/3,
+ db_select/2,
+ db_select/3,
+ db_slot/2,
+ db_slot/3,
+ db_update_counter/3,
+ db_update_counter/4,
+ dbg_out/2,
+ del/2,
+ dets_sync_close/1,
+ dets_sync_open/2,
+ dets_sync_open/3,
+ dir/0,
+ dir/1,
+ dir_info/0,
+ dirty_rpc_error_tag/1,
+ dist_coredump/0,
+ disk_type/1,
+ disk_type/2,
+ elems/2,
+ ensure_loaded/1,
+ error/2,
+ error_desc/1,
+ etype/1,
+ exists/1,
+ fatal/2,
+ get_node_number/0,
+ fix_error/1,
+ important/2,
+ incr_counter/1,
+ incr_counter/2,
+ intersect/2,
+ is_running/0,
+ is_running/1,
+ is_running_remote/0,
+ is_string/1,
+ key_search_delete/3,
+ key_search_all/3,
+ last_error/0,
+ local_active_tables/0,
+ lock_table/1,
+ mkcore/1,
+ not_active_here/1,
+ other_val/2,
+ pad_name/3,
+ random_time/2,
+ read_counter/1,
+ readable_indecies/1,
+ remote_copy_holders/1,
+ report_fatal/2,
+ report_system_event/1,
+ running_nodes/0,
+ running_nodes/1,
+ schema_cs_to_storage_type/2,
+ search_delete/2,
+ set/2,
+ set_counter/2,
+ set_local_content_whereabouts/1,
+ set_remote_where_to_read/1,
+ set_remote_where_to_read/2,
+ show/1,
+ show/2,
+ sort_commit/1,
+ storage_type_at_node/2,
+ swap_tmp_files/1,
+ tab2dat/1,
+ tab2dmp/1,
+ tab2tmp/1,
+ tab2dcd/1,
+ tab2dcl/1,
+ to_list/1,
+ union/2,
+ uniq/1,
+ unlock_table/1,
+ unset/1,
+ update_counter/2,
+ val/1,
+ vcore/0,
+ vcore/1,
+ verbose/2,
+ view/0,
+ view/1,
+ view/2,
+ warning/2,
+
+ is_debug_compiled/0,
+ activate_debug_fun/5,
+ deactivate_debug_fun/3,
+ eval_debug_fun/4,
+ scratch_debug_fun/0
+ ]).
+
+
+search_delete(Obj, List) ->
+ search_delete(Obj, List, [], none).
+search_delete(Obj, [Obj|Tail], Ack, _Res) ->
+ search_delete(Obj, Tail, Ack, Obj);
+search_delete(Obj, [H|T], Ack, Res) ->
+ search_delete(Obj, T, [H|Ack], Res);
+search_delete(_, [], Ack, Res) ->
+ {Res, Ack}.
+
+key_search_delete(Key, Pos, TupleList) ->
+ key_search_delete(Key, Pos, TupleList, none, []).
+key_search_delete(Key, Pos, [H|T], _Obj, Ack) when element(Pos, H) == Key ->
+ key_search_delete(Key, Pos, T, H, Ack);
+key_search_delete(Key, Pos, [H|T], Obj, Ack) ->
+ key_search_delete(Key, Pos, T, Obj, [H|Ack]);
+key_search_delete(_, _, [], Obj, Ack) ->
+ {Obj, Ack}.
+
+key_search_all(Key, Pos, TupleList) ->
+ key_search_all(Key, Pos, TupleList, []).
+key_search_all(Key, N, [H|T], Ack) when element(N, H) == Key ->
+ key_search_all(Key, N, T, [H|Ack]);
+key_search_all(Key, N, [_|T], Ack) ->
+ key_search_all(Key, N, T, Ack);
+key_search_all(_, _, [], Ack) -> Ack.
+
+intersect(L1, L2) ->
+ L2 -- (L2 -- L1).
+
+elems(I, [H|T]) ->
+ [element(I, H) | elems(I, T)];
+elems(_, []) ->
+ [].
+
+%% sort_commit see to that checkpoint info is always first in
+%% commit_work structure the other info don't need to be sorted.
+sort_commit(List) ->
+ sort_commit2(List, []).
+
+sort_commit2([{checkpoints, ChkpL}| Rest], Acc) ->
+ [{checkpoints, ChkpL}| Rest] ++ Acc;
+sort_commit2([H | R], Acc) ->
+ sort_commit2(R, [H | Acc]);
+sort_commit2([], Acc) -> Acc.
+
+is_string([H|T]) ->
+ if
+ 0 =< H, H < 256, integer(H) -> is_string(T);
+ true -> false
+ end;
+is_string([]) -> true.
+
+%%%
+
+union([H|L1], L2) ->
+ case lists:member(H, L2) of
+ true -> union(L1, L2);
+ false -> [H | union(L1, L2)]
+ end;
+union([], L2) -> L2.
+
+uniq([]) ->
+ [];
+uniq(List) ->
+ [H|T] = lists:sort(List),
+ uniq1(H, T, []).
+
+uniq1(H, [H|R], Ack) ->
+ uniq1(H, R, Ack);
+uniq1(Old, [H|R], Ack) ->
+ uniq1(H, R, [Old|Ack]);
+uniq1(Old, [], Ack) ->
+ [Old| Ack].
+
+to_list(X) when list(X) -> X;
+to_list(X) -> atom_to_list(X).
+
+all_nodes() ->
+ Ns = mnesia:system_info(db_nodes) ++
+ mnesia:system_info(extra_db_nodes),
+ mnesia_lib:uniq(Ns).
+
+running_nodes() ->
+ running_nodes(all_nodes()).
+
+running_nodes(Ns) ->
+ {Replies, _BadNs} = rpc:multicall(Ns, ?MODULE, is_running_remote, []),
+ [N || {GoodState, N} <- Replies, GoodState == true].
+
+is_running_remote() ->
+ IsRunning = is_running(),
+ {IsRunning == yes, node()}.
+
+is_running(Node) when atom(Node) ->
+ case rpc:call(Node, ?MODULE, is_running, []) of
+ {badrpc, _} -> no;
+ X -> X
+ end.
+
+is_running() ->
+ case ?catch_val(mnesia_status) of
+ {'EXIT', _} -> no;
+ running -> yes;
+ starting -> starting;
+ stopping -> stopping
+ end.
+
+show(X) ->
+ show(X, []).
+show(F, A) ->
+ io:format(user, F, A).
+
+
+pad_name([Char | Chars], Len, Tail) ->
+ [Char | pad_name(Chars, Len - 1, Tail)];
+pad_name([], Len, Tail) when Len =< 0 ->
+ Tail;
+pad_name([], Len, Tail) ->
+ [$ | pad_name([], Len - 1, Tail)].
+
+%% Some utility functions .....
+active_here(Tab) ->
+ case val({Tab, where_to_read}) of
+ Node when Node == node() -> true;
+ _ -> false
+ end.
+
+not_active_here(Tab) ->
+ not active_here(Tab).
+
+exists(Fname) ->
+ case file:open(Fname, [raw,read]) of
+ {ok, F} ->file:close(F), true;
+ _ -> false
+ end.
+
+dir() -> mnesia_monitor:get_env(dir).
+
+dir(Fname) ->
+ filename:join([dir(), to_list(Fname)]).
+
+tab2dat(Tab) -> %% DETS files
+ dir(lists:concat([Tab, ".DAT"])).
+
+tab2tmp(Tab) ->
+ dir(lists:concat([Tab, ".TMP"])).
+
+tab2dmp(Tab) -> %% Dumped ets tables
+ dir(lists:concat([Tab, ".DMP"])).
+
+tab2dcd(Tab) -> %% Disc copies data
+ dir(lists:concat([Tab, ".DCD"])).
+
+tab2dcl(Tab) -> %% Disc copies log
+ dir(lists:concat([Tab, ".DCL"])).
+
+storage_type_at_node(Node, Tab) ->
+ search_key(Node, [{disc_copies, val({Tab, disc_copies})},
+ {ram_copies, val({Tab, ram_copies})},
+ {disc_only_copies, val({Tab, disc_only_copies})}]).
+
+cs_to_storage_type(Node, Cs) ->
+ search_key(Node, [{disc_copies, Cs#cstruct.disc_copies},
+ {ram_copies, Cs#cstruct.ram_copies},
+ {disc_only_copies, Cs#cstruct.disc_only_copies}]).
+
+schema_cs_to_storage_type(Node, Cs) ->
+ case cs_to_storage_type(Node, Cs) of
+ unknown when Cs#cstruct.name == schema -> ram_copies;
+ Other -> Other
+ end.
+
+
+search_key(Key, [{Val, List} | Tail]) ->
+ case lists:member(Key, List) of
+ true -> Val;
+ false -> search_key(Key, Tail)
+ end;
+search_key(_Key, []) ->
+ unknown.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% ops, we've got some global variables here :-)
+
+%% They are
+%%
+%% {Tab, setorbag}, -> set | bag
+%% {Tab, storage_type} -> disc_copies |ram_copies | unknown (**)
+%% {Tab, disc_copies} -> node list (from schema)
+%% {Tab, ram_copies}, -> node list (from schema)
+%% {Tab, arity}, -> number
+%% {Tab, attributes}, -> atom list
+%% {Tab, wild_pattern}, -> record tuple with '_'s
+%% {Tab, {index, Pos}} -> ets table
+%% {Tab, index} -> integer list
+%% {Tab, cstruct} -> cstruct structure
+%%
+
+%% The following fields are dynamic according to the
+%% the current node/table situation
+
+%% {Tab, where_to_write} -> node list
+%% {Tab, where_to_read} -> node | nowhere
+%%
+%% {schema, tables} -> tab list
+%% {schema, local_tables} -> tab list (**)
+%%
+%% {current, db_nodes} -> node list
+%%
+%% dir -> directory path (**)
+%% mnesia_status -> status | running | stopping (**)
+%% (**) == (Different on all nodes)
+%%
+
+val(Var) ->
+ case ?catch_val(Var) of
+ {'EXIT', _ReASoN_} -> mnesia_lib:other_val(Var, _ReASoN_);
+ _VaLuE_ -> _VaLuE_
+ end.
+
+set(Var, Val) ->
+ ?ets_insert(mnesia_gvar, {Var, Val}).
+
+unset(Var) ->
+ ?ets_delete(mnesia_gvar, Var).
+
+other_val(Var, Other) ->
+ case Var of
+ {_, where_to_read} -> nowhere;
+ {_, where_to_write} -> [];
+ {_, active_replicas} -> [];
+ _ ->
+ pr_other(Var, Other)
+ end.
+
+pr_other(Var, Other) ->
+ Why =
+ case is_running() of
+ no -> {node_not_running, node()};
+ _ -> {no_exists, Var}
+ end,
+ verbose("~p (~p) val(mnesia_gvar, ~w) -> ~p ~p ~n",
+ [self(), process_info(self(), registered_name),
+ Var, Other, Why]),
+ case Other of
+ {badarg, [{ets, lookup_element, _}|_]} ->
+ exit(Why);
+ _ ->
+ erlang:error(Why)
+ end.
+
+%% Some functions for list valued variables
+add(Var, Val) ->
+ L = val(Var),
+ set(Var, [Val | lists:delete(Val, L)]).
+
+add_list(Var, List) ->
+ L = val(Var),
+ set(Var, union(L, List)).
+
+del(Var, Val) ->
+ L = val(Var),
+ set(Var, lists:delete(Val, L)).
+
+%% This function is needed due to the fact
+%% that the application_controller enters
+%% a deadlock now and then. ac is implemented
+%% as a rather naive server.
+ensure_loaded(Appl) ->
+ case application_controller:get_loaded(Appl) of
+ {true, _} ->
+ ok;
+ false ->
+ case application:load(Appl) of
+ ok ->
+ ok;
+ {error, {already_loaded, Appl}} ->
+ ok;
+ {error, Reason} ->
+ {error, {application_load_error, Reason}}
+ end
+ end.
+
+local_active_tables() ->
+ Tabs = val({schema, local_tables}),
+ lists:zf(fun(Tab) -> active_here(Tab) end, Tabs).
+
+active_tables() ->
+ Tabs = val({schema, tables}),
+ F = fun(Tab) ->
+ case val({Tab, where_to_read}) of
+ nowhere -> false;
+ _ -> {true, Tab}
+ end
+ end,
+ lists:zf(F, Tabs).
+
+etype(X) when integer(X) -> integer;
+etype([]) -> nil;
+etype(X) when list(X) -> list;
+etype(X) when tuple(X) -> tuple;
+etype(X) when atom(X) -> atom;
+etype(_) -> othertype.
+
+remote_copy_holders(Cs) ->
+ copy_holders(Cs) -- [node()].
+
+copy_holders(Cs) when Cs#cstruct.local_content == false ->
+ cs_to_nodes(Cs);
+copy_holders(Cs) when Cs#cstruct.local_content == true ->
+ case lists:member(node(), cs_to_nodes(Cs)) of
+ true -> [node()];
+ false -> []
+ end.
+
+
+set_remote_where_to_read(Tab) ->
+ set_remote_where_to_read(Tab, []).
+
+set_remote_where_to_read(Tab, Ignore) ->
+ Active = val({Tab, active_replicas}),
+ Valid =
+ case mnesia_recover:get_master_nodes(Tab) of
+ [] -> Active;
+ Masters -> mnesia_lib:intersect(Masters, Active)
+ end,
+ Available = mnesia_lib:intersect(val({current, db_nodes}), Valid -- Ignore),
+ DiscOnlyC = val({Tab, disc_only_copies}),
+ Prefered = Available -- DiscOnlyC,
+ if
+ Prefered /= [] ->
+ set({Tab, where_to_read}, hd(Prefered));
+ Available /= [] ->
+ set({Tab, where_to_read}, hd(Available));
+ true ->
+ set({Tab, where_to_read}, nowhere)
+ end.
+
+%%% Local only
+set_local_content_whereabouts(Tab) ->
+ add({schema, local_tables}, Tab),
+ add({Tab, active_replicas}, node()),
+ set({Tab, where_to_write}, [node()]),
+ set({Tab, where_to_read}, node()).
+
+%%% counter routines
+
+create_counter(Name) ->
+ set_counter(Name, 0).
+
+set_counter(Name, Val) ->
+ ?ets_insert(mnesia_gvar, {Name, Val}).
+
+incr_counter(Name) ->
+ ?ets_update_counter(mnesia_gvar, Name, 1).
+
+incr_counter(Name, I) ->
+ ?ets_update_counter(mnesia_gvar, Name, I).
+
+update_counter(Name, Val) ->
+ ?ets_update_counter(mnesia_gvar, Name, Val).
+
+read_counter(Name) ->
+ ?ets_lookup_element(mnesia_gvar, Name, 2).
+
+cs_to_nodes(Cs) ->
+ Cs#cstruct.disc_only_copies ++
+ Cs#cstruct.disc_copies ++
+ Cs#cstruct.ram_copies.
+
+dist_coredump() ->
+ dist_coredump(all_nodes()).
+dist_coredump(Ns) ->
+ {Replies, _} = rpc:multicall(Ns, ?MODULE, coredump, []),
+ Replies.
+
+coredump() ->
+ coredump({crashinfo, {"user initiated~n", []}}).
+coredump(CrashInfo) ->
+ Core = mkcore(CrashInfo),
+ Out = core_file(),
+ important("Writing Mnesia core to file: ~p...~p~n", [Out, CrashInfo]),
+ file:write_file(Out, Core),
+ Out.
+
+core_file() ->
+ Integers = tuple_to_list(date()) ++ tuple_to_list(time()),
+ Fun = fun(I) when I < 10 -> ["_0", I];
+ (I) -> ["_", I]
+ end,
+ List = lists:append([Fun(I) || I <- Integers]),
+ filename:absname(lists:concat(["MnesiaCore.", node()] ++ List)).
+
+mkcore(CrashInfo) ->
+% dbg_out("Making a Mnesia core dump...~p~n", [CrashInfo]),
+ Nodes = [node() |nodes()],
+ TidLocks = (catch ets:tab2list(mnesia_tid_locks)),
+ Core = [
+ CrashInfo,
+ {time, {date(), time()}},
+ {self, catch process_info(self())},
+ {nodes, catch rpc:multicall(Nodes, ?MODULE, get_node_number, [])},
+ {applications, catch lists:sort(application:loaded_applications())},
+ {flags, catch init:get_arguments()},
+ {code_path, catch code:get_path()},
+ {code_loaded, catch lists:sort(code:all_loaded())},
+ {etsinfo, catch ets_info(ets:all())},
+
+ {version, catch mnesia:system_info(version)},
+ {schema, catch ets:tab2list(schema)},
+ {gvar, catch ets:tab2list(mnesia_gvar)},
+ {master_nodes, catch mnesia_recover:get_master_node_info()},
+
+ {processes, catch procs()},
+ {relatives, catch relatives()},
+ {workers, catch workers(mnesia_controller:get_workers(2000))},
+ {locking_procs, catch locking_procs(TidLocks)},
+
+ {held_locks, catch mnesia:system_info(held_locks)},
+ {tid_locks, TidLocks},
+ {lock_queue, catch mnesia:system_info(lock_queue)},
+ {load_info, catch mnesia_controller:get_info(2000)},
+ {trans_info, catch mnesia_tm:get_info(2000)},
+
+ {schema_file, catch file:read_file(tab2dat(schema))},
+ {dir_info, catch dir_info()},
+ {logfile, catch {ok, read_log_files()}}
+ ],
+ term_to_binary(Core).
+
+procs() ->
+ Fun = fun(P) -> {P, (catch lists:zf(fun proc_info/1, process_info(P)))} end,
+ lists:map(Fun, processes()).
+
+proc_info({registered_name, Val}) -> {true, Val};
+proc_info({message_queue_len, Val}) -> {true, Val};
+proc_info({status, Val}) -> {true, Val};
+proc_info({current_function, Val}) -> {true, Val};
+proc_info(_) -> false.
+
+get_node_number() ->
+ {node(), self()}.
+
+read_log_files() ->
+ [{F, catch file:read_file(F)} || F <- mnesia_log:log_files()].
+
+dir_info() ->
+ {ok, Cwd} = file:get_cwd(),
+ Dir = dir(),
+ [{cwd, Cwd, file:read_file_info(Cwd)},
+ {mnesia_dir, Dir, file:read_file_info(Dir)}] ++
+ case file:list_dir(Dir) of
+ {ok, Files} ->
+ [{mnesia_file, F, catch file:read_file_info(dir(F))} || F <- Files];
+ Other ->
+ [Other]
+ end.
+
+ets_info([H|T]) ->
+ [{table, H, ets:info(H)} | ets_info(T)];
+ets_info([]) -> [].
+
+relatives() ->
+ Info = fun(Name) ->
+ case whereis(Name) of
+ undefined -> false;
+ Pid -> {true, {Name, Pid, catch process_info(Pid)}}
+ end
+ end,
+ lists:zf(Info, mnesia:ms()).
+
+workers({workers, Loader, Sender, Dumper}) ->
+ Info = fun({Name, Pid}) ->
+ case Pid of
+ undefined -> false;
+ Pid -> {true, {Name, Pid, catch process_info(Pid)}}
+ end
+ end,
+ lists:zf(Info, [{loader, Loader}, {sender, Sender}, {dumper, Dumper}]).
+
+locking_procs(LockList) when list(LockList) ->
+ Tids = [element(1, Lock) || Lock <- LockList],
+ UT = uniq(Tids),
+ Info = fun(Tid) ->
+ Pid = Tid#tid.pid,
+ case node(Pid) == node() of
+ true ->
+ {true, {Pid, catch process_info(Pid)}};
+ _ ->
+ false
+ end
+ end,
+ lists:zf(Info, UT).
+
+view() ->
+ Bin = mkcore({crashinfo, {"view only~n", []}}),
+ vcore(Bin).
+
+%% Displays a Mnesia file on the tty. The file may be repaired.
+view(File) ->
+ case suffix([".DAT", ".RET", ".DMP", ".TMP"], File) of
+ true ->
+ view(File, dat);
+ false ->
+ case suffix([".LOG", ".BUP", ".ETS"], File) of
+ true ->
+ view(File, log);
+ false ->
+ case lists:prefix("MnesiaCore.", File) of
+ true ->
+ view(File, core);
+ false ->
+ {error, "Unknown file name"}
+ end
+ end
+ end.
+
+view(File, dat) ->
+ dets:view(File);
+view(File, log) ->
+ mnesia_log:view(File);
+view(File, core) ->
+ vcore(File).
+
+suffix(Suffixes, File) ->
+ Fun = fun(S) -> lists:suffix(S, File) end,
+ lists:any(Fun, Suffixes).
+
+%% View a core file
+
+vcore() ->
+ Prefix = lists:concat(["MnesiaCore.", node()]),
+ Filter = fun(F) -> lists:prefix(Prefix, F) end,
+ {ok, Cwd} = file:get_cwd(),
+ case file:list_dir(Cwd) of
+ {ok, Files}->
+ CoreFiles = lists:sort(lists:zf(Filter, Files)),
+ show("Mnesia core files: ~p~n", [CoreFiles]),
+ vcore(lists:last(CoreFiles));
+ Error ->
+ Error
+ end.
+
+vcore(Bin) when binary(Bin) ->
+ Core = binary_to_term(Bin),
+ Fun = fun({Item, Info}) ->
+ show("***** ~p *****~n", [Item]),
+ case catch vcore_elem({Item, Info}) of
+ {'EXIT', Reason} ->
+ show("{'EXIT', ~p}~n", [Reason]);
+ _ -> ok
+ end
+ end,
+ lists:foreach(Fun, Core);
+
+vcore(File) ->
+ show("~n***** Mnesia core: ~p *****~n", [File]),
+ case file:read_file(File) of
+ {ok, Bin} ->
+ vcore(Bin);
+ _ ->
+ nocore
+ end.
+
+vcore_elem({schema_file, {ok, B}}) ->
+ Fname = "/tmp/schema.DAT",
+ file:write_file(Fname, B),
+ dets:view(Fname),
+ file:delete(Fname);
+
+vcore_elem({logfile, {ok, BinList}}) ->
+ Fun = fun({F, Info}) ->
+ show("----- logfile: ~p -----~n", [F]),
+ case Info of
+ {ok, B} ->
+ Fname = "/tmp/mnesia_vcore_elem.TMP",
+ file:write_file(Fname, B),
+ mnesia_log:view(Fname),
+ file:delete(Fname);
+ _ ->
+ show("~p~n", [Info])
+ end
+ end,
+ lists:foreach(Fun, BinList);
+
+vcore_elem({crashinfo, {Format, Args}}) ->
+ show(Format, Args);
+vcore_elem({gvar, L}) ->
+ show("~p~n", [lists:sort(L)]);
+vcore_elem({transactions, Info}) ->
+ mnesia_tm:display_info(user, Info);
+
+vcore_elem({_Item, Info}) ->
+ show("~p~n", [Info]).
+
+fix_error(X) ->
+ set(last_error, X), %% for debugabililty
+ case X of
+ {aborted, Reason} -> Reason;
+ {abort, Reason} -> Reason;
+ Y when atom(Y) -> Y;
+ {'EXIT', {_Reason, {Mod, _, _}}} when atom(Mod) ->
+ save(X),
+ case atom_to_list(Mod) of
+ [$m, $n, $e|_] -> badarg;
+ _ -> X
+ end;
+ _ -> X
+ end.
+
+last_error() ->
+ val(last_error).
+
+%% The following is a list of possible mnesia errors and what they
+%% actually mean
+
+error_desc(nested_transaction) -> "Nested transactions are not allowed";
+error_desc(badarg) -> "Bad or invalid argument, possibly bad type";
+error_desc(no_transaction) -> "Operation not allowed outside transactions";
+error_desc(combine_error) -> "Table options were ilegally combined";
+error_desc(bad_index) -> "Index already exists or was out of bounds";
+error_desc(already_exists) -> "Some schema option we try to set is already on";
+error_desc(index_exists)-> "Some ops can not be performed on tabs with index";
+error_desc(no_exists)-> "Tried to perform op on non-existing (non alive) item";
+error_desc(system_limit) -> "Some system_limit was exhausted";
+error_desc(mnesia_down) -> "A transaction involving objects at some remote "
+ "node which died while transaction was executing"
+ "*and* object(s) are no longer available elsewhere"
+ "in the network";
+error_desc(not_a_db_node) -> "A node which is non existant in "
+ "the schema was mentioned";
+error_desc(bad_type) -> "Bad type on some provided arguments";
+error_desc(node_not_running) -> "Node not running";
+error_desc(truncated_binary_file) -> "Truncated binary in file";
+error_desc(active) -> "Some delete ops require that "
+ "all active objects are removed";
+error_desc(illegal) -> "Operation not supported on object";
+error_desc({'EXIT', Reason}) ->
+ error_desc(Reason);
+error_desc({error, Reason}) ->
+ error_desc(Reason);
+error_desc({aborted, Reason}) ->
+ error_desc(Reason);
+error_desc(Reason) when tuple(Reason), size(Reason) > 0 ->
+ setelement(1, Reason, error_desc(element(1, Reason)));
+error_desc(Reason) ->
+ Reason.
+
+dirty_rpc_error_tag(Reason) ->
+ case Reason of
+ {'EXIT', _} -> badarg;
+ no_variable -> badarg;
+ _ -> no_exists
+ end.
+
+fatal(Format, Args) ->
+ catch set(mnesia_status, stopping),
+ Core = mkcore({crashinfo, {Format, Args}}),
+ report_fatal(Format, Args, Core),
+ timer:sleep(10000), % Enough to write the core dump to disc?
+ mnesia:lkill(),
+ exit(fatal).
+
+report_fatal(Format, Args) ->
+ report_fatal(Format, Args, nocore).
+
+report_fatal(Format, Args, Core) ->
+ report_system_event({mnesia_fatal, Format, Args, Core}),
+ catch exit(whereis(mnesia_monitor), fatal).
+
+%% We sleep longer and longer the more we try
+%% Made some testing and came up with the following constants
+random_time(Retries, _Counter0) ->
+% UpperLimit = 2000,
+% MaxIntv = trunc(UpperLimit * (1-(4/((Retries*Retries)+4)))),
+ UpperLimit = 500,
+ Dup = Retries * Retries,
+ MaxIntv = trunc(UpperLimit * (1-(50/((Dup)+50)))),
+
+ case get(random_seed) of
+ undefined ->
+ {X, Y, Z} = erlang:now(), %% time()
+ random:seed(X, Y, Z),
+ Time = Dup + random:uniform(MaxIntv),
+ %% dbg_out("---random_test rs ~w max ~w val ~w---~n", [Retries, MaxIntv, Time]),
+ Time;
+ _ ->
+ Time = Dup + random:uniform(MaxIntv),
+ %% dbg_out("---random_test rs ~w max ~w val ~w---~n", [Retries, MaxIntv, Time]),
+ Time
+ end.
+
+report_system_event(Event0) ->
+ Event = {mnesia_system_event, Event0},
+ report_system_event(catch_notify(Event), Event),
+ case ?catch_val(subscribers) of
+ {'EXIT', _} -> ignore;
+ Pids -> lists:foreach(fun(Pid) -> Pid ! Event end, Pids)
+ end,
+ ok.
+
+catch_notify(Event) ->
+ case whereis(mnesia_event) of
+ undefined ->
+ {'EXIT', {badarg, {mnesia_event, Event}}};
+ Pid ->
+ gen_event:notify(Pid, Event)
+ end.
+
+report_system_event({'EXIT', Reason}, Event) ->
+ Mod = mnesia_monitor:get_env(event_module),
+ case mnesia_sup:start_event() of
+ {ok, Pid} ->
+ link(Pid),
+ gen_event:call(mnesia_event, Mod, Event, infinity),
+ unlink(Pid),
+
+ %% We get an exit signal if server dies
+ receive
+ {'EXIT', Pid, _Reason} ->
+ {error, {node_not_running, node()}}
+ after 0 ->
+ gen_event:stop(mnesia_event),
+ ok
+ end;
+
+ Error ->
+ Msg = "Mnesia(~p): Cannot report event ~p: ~p (~p)~n",
+ error_logger:format(Msg, [node(), Event, Reason, Error])
+ end;
+report_system_event(_Res, _Event) ->
+ ignore.
+
+%% important messages are reported regardless of debug level
+important(Format, Args) ->
+ save({Format, Args}),
+ report_system_event({mnesia_info, Format, Args}).
+
+%% Warning messages are reported regardless of debug level
+warning(Format, Args) ->
+ save({Format, Args}),
+ report_system_event({mnesia_warning, Format, Args}).
+
+%% error messages are reported regardless of debug level
+error(Format, Args) ->
+ save({Format, Args}),
+ report_system_event({mnesia_error, Format, Args}).
+
+%% verbose messages are reported if debug level == debug or verbose
+verbose(Format, Args) ->
+ case mnesia_monitor:get_env(debug) of
+ none -> save({Format, Args});
+ verbose -> important(Format, Args);
+ debug -> important(Format, Args);
+ trace -> important(Format, Args)
+ end.
+
+%% debug message are display if debug level == 2
+dbg_out(Format, Args) ->
+ case mnesia_monitor:get_env(debug) of
+ none -> ignore;
+ verbose -> save({Format, Args});
+ _ -> report_system_event({mnesia_info, Format, Args})
+ end.
+
+%% Keep the last 10 debug print outs
+save(DbgInfo) ->
+ catch save2(DbgInfo).
+
+save2(DbgInfo) ->
+ Key = {'$$$_report', current_pos},
+ P =
+ case ?ets_lookup_element(mnesia_gvar, Key, 2) of
+ 30 -> -1;
+ I -> I
+ end,
+ set({'$$$_report', current_pos}, P+1),
+ set({'$$$_report', P+1}, {date(), time(), DbgInfo}).
+
+copy_file(From, To) ->
+ case file:open(From, [raw, binary, read]) of
+ {ok, F} ->
+ case file:open(To, [raw, binary, write]) of
+ {ok, T} ->
+ Res = copy_file_loop(F, T, 8000),
+ file:close(F),
+ file:close(T),
+ Res;
+ {error, Reason} ->
+ {error, Reason}
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+copy_file_loop(F, T, ChunkSize) ->
+ case file:read(F, ChunkSize) of
+ {ok, {0, _}} ->
+ ok;
+ {ok, {_, Bin}} ->
+ file:write(T, Bin),
+ copy_file_loop(F, T, ChunkSize);
+ {ok, Bin} ->
+ file:write(T, Bin),
+ copy_file_loop(F, T, ChunkSize);
+ eof ->
+ ok;
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+
+%%%%%%%%%%%%
+%% versions of all the lowlevel db funcs that determine whether we
+%% shall go to disc or ram to do the actual operation.
+
+db_get(Tab, Key) ->
+ db_get(val({Tab, storage_type}), Tab, Key).
+db_get(ram_copies, Tab, Key) -> ?ets_lookup(Tab, Key);
+db_get(disc_copies, Tab, Key) -> ?ets_lookup(Tab, Key);
+db_get(disc_only_copies, Tab, Key) -> dets:lookup(Tab, Key).
+
+db_init_chunk(Tab) ->
+ db_init_chunk(val({Tab, storage_type}), Tab, 1000).
+db_init_chunk(Tab, N) ->
+ db_init_chunk(val({Tab, storage_type}), Tab, N).
+
+db_init_chunk(disc_only_copies, Tab, N) ->
+ dets:select(Tab, [{'_', [], ['$_']}], N);
+db_init_chunk(_, Tab, N) ->
+ ets:select(Tab, [{'_', [], ['$_']}], N).
+
+db_chunk(disc_only_copies, State) ->
+ dets:select(State);
+db_chunk(_, State) ->
+ ets:select(State).
+
+db_put(Tab, Val) ->
+ db_put(val({Tab, storage_type}), Tab, Val).
+
+db_put(ram_copies, Tab, Val) -> ?ets_insert(Tab, Val), ok;
+db_put(disc_copies, Tab, Val) -> ?ets_insert(Tab, Val), ok;
+db_put(disc_only_copies, Tab, Val) -> dets:insert(Tab, Val).
+
+db_match_object(Tab, Pat) ->
+ db_match_object(val({Tab, storage_type}), Tab, Pat).
+db_match_object(Storage, Tab, Pat) ->
+ db_fixtable(Storage, Tab, true),
+ Res = catch_match_object(Storage, Tab, Pat),
+ db_fixtable(Storage, Tab, false),
+ case Res of
+ {'EXIT', Reason} -> exit(Reason);
+ _ -> Res
+ end.
+
+catch_match_object(disc_only_copies, Tab, Pat) ->
+ catch dets:match_object(Tab, Pat);
+catch_match_object(_, Tab, Pat) ->
+ catch ets:match_object(Tab, Pat).
+
+db_select(Tab, Pat) ->
+ db_select(val({Tab, storage_type}), Tab, Pat).
+
+db_select(Storage, Tab, Pat) ->
+ db_fixtable(Storage, Tab, true),
+ Res = catch_select(Storage, Tab, Pat),
+ db_fixtable(Storage, Tab, false),
+ case Res of
+ {'EXIT', Reason} -> exit(Reason);
+ _ -> Res
+ end.
+
+catch_select(disc_only_copies, Tab, Pat) ->
+ dets:select(Tab, Pat);
+catch_select(_, Tab, Pat) ->
+ ets:select(Tab, Pat).
+
+db_fixtable(ets, Tab, Bool) ->
+ ets:safe_fixtable(Tab, Bool);
+db_fixtable(ram_copies, Tab, Bool) ->
+ ets:safe_fixtable(Tab, Bool);
+db_fixtable(disc_copies, Tab, Bool) ->
+ ets:safe_fixtable(Tab, Bool);
+db_fixtable(dets, Tab, Bool) ->
+ dets:safe_fixtable(Tab, Bool);
+db_fixtable(disc_only_copies, Tab, Bool) ->
+ dets:safe_fixtable(Tab, Bool).
+
+db_erase(Tab, Key) ->
+ db_erase(val({Tab, storage_type}), Tab, Key).
+db_erase(ram_copies, Tab, Key) -> ?ets_delete(Tab, Key), ok;
+db_erase(disc_copies, Tab, Key) -> ?ets_delete(Tab, Key), ok;
+db_erase(disc_only_copies, Tab, Key) -> dets:delete(Tab, Key).
+
+db_match_erase(Tab, Pat) ->
+ db_match_erase(val({Tab, storage_type}), Tab, Pat).
+db_match_erase(ram_copies, Tab, Pat) -> ?ets_match_delete(Tab, Pat), ok;
+db_match_erase(disc_copies, Tab, Pat) -> ?ets_match_delete(Tab, Pat), ok;
+db_match_erase(disc_only_copies, Tab, Pat) -> dets:match_delete(Tab, Pat).
+
+db_first(Tab) ->
+ db_first(val({Tab, storage_type}), Tab).
+db_first(ram_copies, Tab) -> ?ets_first(Tab);
+db_first(disc_copies, Tab) -> ?ets_first(Tab);
+db_first(disc_only_copies, Tab) -> dets:first(Tab).
+
+db_next_key(Tab, Key) ->
+ db_next_key(val({Tab, storage_type}), Tab, Key).
+db_next_key(ram_copies, Tab, Key) -> ?ets_next(Tab, Key);
+db_next_key(disc_copies, Tab, Key) -> ?ets_next(Tab, Key);
+db_next_key(disc_only_copies, Tab, Key) -> dets:next(Tab, Key).
+
+db_last(Tab) ->
+ db_last(val({Tab, storage_type}), Tab).
+db_last(ram_copies, Tab) -> ?ets_last(Tab);
+db_last(disc_copies, Tab) -> ?ets_last(Tab);
+db_last(disc_only_copies, Tab) -> dets:first(Tab). %% Dets don't have order
+
+db_prev_key(Tab, Key) ->
+ db_prev_key(val({Tab, storage_type}), Tab, Key).
+db_prev_key(ram_copies, Tab, Key) -> ?ets_prev(Tab, Key);
+db_prev_key(disc_copies, Tab, Key) -> ?ets_prev(Tab, Key);
+db_prev_key(disc_only_copies, Tab, Key) -> dets:next(Tab, Key). %% Dets don't have order
+
+db_slot(Tab, Pos) ->
+ db_slot(val({Tab, storage_type}), Tab, Pos).
+db_slot(ram_copies, Tab, Pos) -> ?ets_slot(Tab, Pos);
+db_slot(disc_copies, Tab, Pos) -> ?ets_slot(Tab, Pos);
+db_slot(disc_only_copies, Tab, Pos) -> dets:slot(Tab, Pos).
+
+db_update_counter(Tab, C, Val) ->
+ db_update_counter(val({Tab, storage_type}), Tab, C, Val).
+db_update_counter(ram_copies, Tab, C, Val) ->
+ ?ets_update_counter(Tab, C, Val);
+db_update_counter(disc_copies, Tab, C, Val) ->
+ ?ets_update_counter(Tab, C, Val);
+db_update_counter(disc_only_copies, Tab, C, Val) ->
+ dets:update_counter(Tab, C, Val).
+
+db_erase_tab(Tab) ->
+ db_erase_tab(val({Tab, storage_type}), Tab).
+db_erase_tab(ram_copies, Tab) -> ?ets_delete_table(Tab);
+db_erase_tab(disc_copies, Tab) -> ?ets_delete_table(Tab);
+db_erase_tab(disc_only_copies, _Tab) -> ignore.
+
+%% assuming that Tab is a valid ets-table
+dets_to_ets(Tabname, Tab, File, Type, Rep, Lock) ->
+ {Open, Close} = mkfuns(Lock),
+ case Open(Tabname, [{file, File}, {type, disk_type(Tab, Type)},
+ {keypos, 2}, {repair, Rep}]) of
+ {ok, Tabname} ->
+ Res = dets:to_ets(Tabname, Tab),
+ Close(Tabname),
+ trav_ret(Res, Tab);
+ Other ->
+ Other
+ end.
+
+trav_ret(Tabname, Tabname) -> loaded;
+trav_ret(Other, _Tabname) -> Other.
+
+mkfuns(yes) ->
+ {fun(Tab, Args) -> dets_sync_open(Tab, Args) end,
+ fun(Tab) -> dets_sync_close(Tab) end};
+mkfuns(no) ->
+ {fun(Tab, Args) -> dets:open_file(Tab, Args) end,
+ fun(Tab) -> dets:close(Tab) end}.
+
+disk_type(Tab) ->
+ disk_type(Tab, val({Tab, setorbag})).
+
+disk_type(_Tab, ordered_set) ->
+ set;
+disk_type(_, Type) ->
+ Type.
+
+dets_sync_open(Tab, Ref, File) ->
+ Args = [{file, File},
+ {keypos, 2},
+ {repair, mnesia_monitor:get_env(auto_repair)},
+ {type, disk_type(Tab)}],
+ dets_sync_open(Ref, Args).
+
+lock_table(Tab) ->
+ global:set_lock({{mnesia_table_lock, Tab}, self()}, [node()], infinity).
+% dbg_out("dets_sync_open: ~p ~p~n", [T, self()]),
+
+unlock_table(Tab) ->
+ global:del_lock({{mnesia_table_lock, Tab}, self()}, [node()]).
+% dbg_out("unlock_table: ~p ~p~n", [T, self()]),
+
+dets_sync_open(Tab, Args) ->
+ lock_table(Tab),
+ case dets:open_file(Tab, Args) of
+ {ok, Tab} ->
+ {ok, Tab};
+ Other ->
+ dets_sync_close(Tab),
+ Other
+ end.
+
+dets_sync_close(Tab) ->
+ catch dets:close(Tab),
+ unlock_table(Tab),
+ ok.
+
+cleanup_tmp_files([Tab | Tabs]) ->
+ dets_sync_close(Tab),
+ file:delete(tab2tmp(Tab)),
+ cleanup_tmp_files(Tabs);
+cleanup_tmp_files([]) ->
+ ok.
+
+%% Returns a list of bad tables
+swap_tmp_files([Tab | Tabs]) ->
+ dets_sync_close(Tab),
+ Tmp = tab2tmp(Tab),
+ Dat = tab2dat(Tab),
+ case file:rename(Tmp, Dat) of
+ ok ->
+ swap_tmp_files(Tabs);
+ _ ->
+ file:delete(Tmp),
+ [Tab | swap_tmp_files(Tabs)]
+ end;
+swap_tmp_files([]) ->
+ [].
+
+readable_indecies(Tab) ->
+ val({Tab, index}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Managing conditional debug functions
+%%
+%% The main idea with the debug_fun's is to allow test programs
+%% to control the internal behaviour of Mnesia. This is needed
+%% to make the test programs independent of system load, swapping
+%% and other circumstances that may affect the behaviour of Mnesia.
+%%
+%% First should calls to ?eval_debug_fun be inserted at well
+%% defined places in Mnesia's code. E.g. in critical situations
+%% of startup, transaction commit, backups etc.
+%%
+%% Then compile Mnesia with the compiler option 'debug'.
+%%
+%% In test programs ?activate_debug_fun should be called
+%% in order to bind a fun to the debug identifier stated
+%% in the call to ?eval_debug_fun.
+%%
+%% If eval_debug_fun finds that the fun is activated it
+%% invokes the fun as NewContext = Fun(PreviousContext, EvalContext)
+%% and replaces the PreviousContext with the NewContext.
+%% The initial context of a debug_fun is given as argument to
+%% activate_debug_fun.
+
+-define(DEBUG_TAB, mnesia_debug).
+-record(debug_info, {id, function, context, file, line}).
+
+scratch_debug_fun() ->
+ dbg_out("scratch_debug_fun(): ~p~n", [?DEBUG_TAB]),
+ (catch ?ets_delete_table(?DEBUG_TAB)),
+ ?ets_new_table(?DEBUG_TAB, [set, public, named_table, {keypos, 2}]).
+
+activate_debug_fun(FunId, Fun, InitialContext, File, Line) ->
+ Info = #debug_info{id = FunId,
+ function = Fun,
+ context = InitialContext,
+ file = File,
+ line = Line
+ },
+ update_debug_info(Info).
+
+update_debug_info(Info) ->
+ case catch ?ets_insert(?DEBUG_TAB, Info) of
+ {'EXIT', _} ->
+ scratch_debug_fun(),
+ ?ets_insert(?DEBUG_TAB, Info);
+ _ ->
+ ok
+ end,
+ dbg_out("update_debug_info(~p)~n", [Info]),
+ ok.
+
+deactivate_debug_fun(FunId, _File, _Line) ->
+ catch ?ets_delete(?DEBUG_TAB, FunId),
+ ok.
+
+eval_debug_fun(FunId, EvalContext, EvalFile, EvalLine) ->
+ case catch ?ets_lookup(?DEBUG_TAB, FunId) of
+ [] ->
+ ok;
+ [Info] ->
+ OldContext = Info#debug_info.context,
+ dbg_out("~s(~p): ~w "
+ "activated in ~s(~p)~n "
+ "eval_debug_fun(~w, ~w)~n",
+ [filename:basename(EvalFile), EvalLine, Info#debug_info.id,
+ filename:basename(Info#debug_info.file), Info#debug_info.line,
+ OldContext, EvalContext]),
+ Fun = Info#debug_info.function,
+ NewContext = Fun(OldContext, EvalContext),
+
+ case catch ?ets_lookup(?DEBUG_TAB, FunId) of
+ [Info] when NewContext /= OldContext ->
+ NewInfo = Info#debug_info{context = NewContext},
+ update_debug_info(NewInfo);
+ _ ->
+ ok
+ end;
+ {'EXIT', _} -> ok
+ end.
+
+-ifdef(debug).
+ is_debug_compiled() -> true.
+-else.
+ is_debug_compiled() -> false.
+-endif.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_loader.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_loader.erl
new file mode 100644
index 0000000000..f21a8240aa
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_loader.erl
@@ -0,0 +1,805 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_loader.erl,v 1.2 2010/03/04 13:54:19 maria Exp $
+%%
+%%% Purpose : Loads tables from local disc or from remote node
+
+-module(mnesia_loader).
+
+%% Mnesia internal stuff
+-export([disc_load_table/2,
+ net_load_table/4,
+ send_table/3]).
+
+-export([old_node_init_table/6]). %% Spawned old node protocol conversion hack
+-export([spawned_receiver/8]). %% Spawned lock taking process
+
+-import(mnesia_lib, [set/2, fatal/2, verbose/2, dbg_out/2]).
+
+-include("mnesia.hrl").
+
+val(Var) ->
+ case ?catch_val(Var) of
+ {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
+ Value -> Value
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Load a table from local disc
+
+disc_load_table(Tab, Reason) ->
+ Storage = val({Tab, storage_type}),
+ Type = val({Tab, setorbag}),
+ dbg_out("Getting table ~p (~p) from disc: ~p~n",
+ [Tab, Storage, Reason]),
+ ?eval_debug_fun({?MODULE, do_get_disc_copy},
+ [{tab, Tab},
+ {reason, Reason},
+ {storage, Storage},
+ {type, Type}]),
+ do_get_disc_copy2(Tab, Reason, Storage, Type).
+
+do_get_disc_copy2(Tab, _Reason, Storage, _Type) when Storage == unknown ->
+ verbose("Local table copy of ~p has recently been deleted, ignored.~n",
+ [Tab]),
+ {loaded, ok}; %% ?
+do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_copies ->
+ %% NOW we create the actual table
+ Repair = mnesia_monitor:get_env(auto_repair),
+ Args = [{keypos, 2}, public, named_table, Type],
+ case Reason of
+ {dumper, _} -> %% Resources allready allocated
+ ignore;
+ _ ->
+ mnesia_monitor:mktab(Tab, Args),
+ Count = mnesia_log:dcd2ets(Tab, Repair),
+ case ets:info(Tab, size) of
+ X when X < Count * 4 ->
+ ok = mnesia_log:ets2dcd(Tab);
+ _ ->
+ ignore
+ end
+ end,
+ mnesia_index:init_index(Tab, Storage),
+ snmpify(Tab, Storage),
+ set({Tab, load_node}, node()),
+ set({Tab, load_reason}, Reason),
+ {loaded, ok};
+
+do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == ram_copies ->
+ Args = [{keypos, 2}, public, named_table, Type],
+ case Reason of
+ {dumper, _} -> %% Resources allready allocated
+ ignore;
+ _ ->
+ mnesia_monitor:mktab(Tab, Args),
+ Fname = mnesia_lib:tab2dcd(Tab),
+ Datname = mnesia_lib:tab2dat(Tab),
+ Repair = mnesia_monitor:get_env(auto_repair),
+ case mnesia_monitor:use_dir() of
+ true ->
+ case mnesia_lib:exists(Fname) of
+ true -> mnesia_log:dcd2ets(Tab, Repair);
+ false ->
+ case mnesia_lib:exists(Datname) of
+ true ->
+ mnesia_lib:dets_to_ets(Tab, Tab, Datname,
+ Type, Repair, no);
+ false ->
+ false
+ end
+ end;
+ false ->
+ false
+ end
+ end,
+ mnesia_index:init_index(Tab, Storage),
+ snmpify(Tab, Storage),
+ set({Tab, load_node}, node()),
+ set({Tab, load_reason}, Reason),
+ {loaded, ok};
+
+do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_only_copies ->
+ Args = [{file, mnesia_lib:tab2dat(Tab)},
+ {type, mnesia_lib:disk_type(Tab, Type)},
+ {keypos, 2},
+ {repair, mnesia_monitor:get_env(auto_repair)}],
+ case Reason of
+ {dumper, _} ->
+ mnesia_index:init_index(Tab, Storage),
+ snmpify(Tab, Storage),
+ set({Tab, load_node}, node()),
+ set({Tab, load_reason}, Reason),
+ {loaded, ok};
+ _ ->
+ case mnesia_monitor:open_dets(Tab, Args) of
+ {ok, _} ->
+ mnesia_index:init_index(Tab, Storage),
+ snmpify(Tab, Storage),
+ set({Tab, load_node}, node()),
+ set({Tab, load_reason}, Reason),
+ {loaded, ok};
+ {error, Error} ->
+ {not_loaded, {"Failed to create dets table", Error}}
+ end
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Load a table from a remote node
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Receiver Sender
+%% -------- ------
+%% Grab schema lock on table
+%% Determine table size
+%% Create empty pre-grown table
+%% Grab read lock on table
+%% Let receiver subscribe on updates done on sender node
+%% Disable rehashing of table
+%% Release read lock on table
+%% Send table to receiver in chunks
+%%
+%% Grab read lock on table
+%% Block dirty updates
+%% Update wherabouts
+%%
+%% Cancel the update subscription
+%% Process the subscription events
+%% Optionally dump to disc
+%% Unblock dirty updates
+%% Release read lock on table
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-define(MAX_TRANSFER_SIZE, 7500).
+-define(MAX_RAM_FILE_SIZE, 1000000).
+-define(MAX_RAM_TRANSFERS, (?MAX_RAM_FILE_SIZE div ?MAX_TRANSFER_SIZE) + 1).
+-define(MAX_NOPACKETS, 20).
+
+net_load_table(Tab, Reason, Ns, Cs)
+ when Reason == {dumper,add_table_copy} ->
+ try_net_load_table(Tab, Reason, Ns, Cs);
+net_load_table(Tab, Reason, Ns, _Cs) ->
+ try_net_load_table(Tab, Reason, Ns, val({Tab, cstruct})).
+
+try_net_load_table(Tab, _Reason, [], _Cs) ->
+ verbose("Copy failed. No active replicas of ~p are available.~n", [Tab]),
+ {not_loaded, none_active};
+try_net_load_table(Tab, Reason, Ns, Cs) ->
+ Storage = mnesia_lib:cs_to_storage_type(node(), Cs),
+ do_get_network_copy(Tab, Reason, Ns, Storage, Cs).
+
+do_get_network_copy(Tab, _Reason, _Ns, unknown, _Cs) ->
+ verbose("Local table copy of ~p has recently been deleted, ignored.~n", [Tab]),
+ {not_loaded, storage_unknown};
+do_get_network_copy(Tab, Reason, Ns, Storage, Cs) ->
+ [Node | Tail] = Ns,
+ dbg_out("Getting table ~p (~p) from node ~p: ~p~n",
+ [Tab, Storage, Node, Reason]),
+ ?eval_debug_fun({?MODULE, do_get_network_copy},
+ [{tab, Tab}, {reason, Reason},
+ {nodes, Ns}, {storage, Storage}]),
+ mnesia_controller:start_remote_sender(Node, Tab, self(), Storage),
+ put(mnesia_table_sender_node, {Tab, Node}),
+ case init_receiver(Node, Tab, Storage, Cs, Reason) of
+ ok ->
+ set({Tab, load_node}, Node),
+ set({Tab, load_reason}, Reason),
+ mnesia_controller:i_have_tab(Tab),
+ dbg_out("Table ~p copied from ~p to ~p~n", [Tab, Node, node()]),
+ {loaded, ok};
+ Err = {error, _} when element(1, Reason) == dumper ->
+ {not_loaded,Err};
+ restart ->
+ try_net_load_table(Tab, Reason, Tail, Cs);
+ down ->
+ try_net_load_table(Tab, Reason, Tail, Cs)
+ end.
+
+snmpify(Tab, Storage) ->
+ do_snmpify(Tab, val({Tab, snmp}), Storage).
+
+do_snmpify(_Tab, [], _Storage) ->
+ ignore;
+do_snmpify(Tab, Us, Storage) ->
+ Snmp = mnesia_snmp_hook:create_table(Us, Tab, Storage),
+ set({Tab, {index, snmp}}, Snmp).
+
+%% Start the recieiver
+%% Sender should be started first, so we don't have the schema-read
+%% lock to long (or get stuck in a deadlock)
+init_receiver(Node, Tab, Storage, Cs, Reason) ->
+ receive
+ {SenderPid, {first, TabSize}} ->
+ spawn_receiver(Tab,Storage,Cs,SenderPid,
+ TabSize,false,Reason);
+ {SenderPid, {first, TabSize, DetsData}} ->
+ spawn_receiver(Tab,Storage,Cs,SenderPid,
+ TabSize,DetsData,Reason);
+ %% Protocol conversion hack
+ {copier_done, Node} ->
+ dbg_out("Sender of table ~p crashed on node ~p ~n", [Tab, Node]),
+ down(Tab, Storage)
+ end.
+
+
+table_init_fun(SenderPid) ->
+ PConv = mnesia_monitor:needs_protocol_conversion(node(SenderPid)),
+ MeMyselfAndI = self(),
+ fun(read) ->
+ Receiver =
+ if
+ PConv == true ->
+ MeMyselfAndI ! {actual_tabrec, self()},
+ MeMyselfAndI; %% Old mnesia
+ PConv == false -> self()
+ end,
+ SenderPid ! {Receiver, more},
+ get_data(SenderPid, Receiver)
+ end.
+
+
+%% Add_table_copy get's it's own locks.
+spawn_receiver(Tab,Storage,Cs,SenderPid,TabSize,DetsData,{dumper,add_table_copy}) ->
+ Init = table_init_fun(SenderPid),
+ case do_init_table(Tab,Storage,Cs,SenderPid,TabSize,DetsData,self(), Init) of
+ Err = {error, _} ->
+ SenderPid ! {copier_done, node()},
+ Err;
+ Else ->
+ Else
+ end;
+
+spawn_receiver(Tab,Storage,Cs,SenderPid,
+ TabSize,DetsData,Reason) ->
+ %% Grab a schema lock to avoid deadlock between table_loader and schema_commit dumping.
+ %% Both may grab tables-locks in different order.
+ Load = fun() ->
+ {_,Tid,Ts} = get(mnesia_activity_state),
+ mnesia_locker:rlock(Tid, Ts#tidstore.store,
+ {schema, Tab}),
+ Init = table_init_fun(SenderPid),
+ Pid = spawn_link(?MODULE, spawned_receiver,
+ [self(),Tab,Storage,Cs,
+ SenderPid,TabSize,DetsData,
+ Init]),
+ put(mnesia_real_loader, Pid),
+ wait_on_load_complete(Pid)
+ end,
+ Res = case mnesia:transaction(Load, 20) of
+ {'atomic', {error,Result}} when element(1,Reason) == dumper ->
+ SenderPid ! {copier_done, node()},
+ {error,Result};
+ {'atomic', {error,Result}} ->
+ SenderPid ! {copier_done, node()},
+ fatal("Cannot create table ~p: ~p~n",
+ [[Tab, Storage], Result]);
+ {'atomic', Result} -> Result;
+ {aborted, nomore} ->
+ SenderPid ! {copier_done, node()},
+ restart;
+ {aborted, _ } ->
+ SenderPid ! {copier_done, node()},
+ down %% either this node or sender is dying
+ end,
+ unlink(whereis(mnesia_tm)), %% Avoid late unlink from tm
+ Res.
+
+spawned_receiver(ReplyTo,Tab,Storage,Cs,
+ SenderPid,TabSize,DetsData, Init) ->
+ process_flag(trap_exit, true),
+ Done = do_init_table(Tab,Storage,Cs,
+ SenderPid,TabSize,DetsData,
+ ReplyTo, Init),
+ ReplyTo ! {self(),Done},
+ unlink(ReplyTo),
+ unlink(whereis(mnesia_controller)),
+ exit(normal).
+
+wait_on_load_complete(Pid) ->
+ receive
+ {Pid, Res} ->
+ Res;
+ {'EXIT', Pid, Reason} ->
+ exit(Reason);
+ Else ->
+ Pid ! Else,
+ wait_on_load_complete(Pid)
+ end.
+
+tab_receiver(Node, Tab, Storage, Cs, PConv, OrigTabRec) ->
+ receive
+ {SenderPid, {no_more, DatBin}} when PConv == false ->
+ finish_copy(Storage,Tab,Cs,SenderPid,DatBin,OrigTabRec);
+
+ %% Protocol conversion hack
+ {SenderPid, {no_more, DatBin}} when pid(PConv) ->
+ PConv ! {SenderPid, no_more},
+ receive
+ {old_init_table_complete, ok} ->
+ finish_copy(Storage, Tab, Cs, SenderPid, DatBin,OrigTabRec);
+ {old_init_table_complete, Reason} ->
+ Msg = "OLD: [d]ets:init table failed",
+ dbg_out("~s: ~p: ~p~n", [Msg, Tab, Reason]),
+ down(Tab, Storage)
+ end;
+
+ {actual_tabrec, Pid} ->
+ tab_receiver(Node, Tab, Storage, Cs, Pid,OrigTabRec);
+
+ {SenderPid, {more, [Recs]}} when pid(PConv) ->
+ PConv ! {SenderPid, {more, Recs}}, %% Forward Msg to OldNodes
+ tab_receiver(Node, Tab, Storage, Cs, PConv,OrigTabRec);
+
+ {'EXIT', PConv, Reason} -> %% [d]ets:init process crashed
+ Msg = "Receiver crashed",
+ dbg_out("~s: ~p: ~p~n", [Msg, Tab, Reason]),
+ down(Tab, Storage);
+
+ %% Protocol conversion hack
+ {copier_done, Node} ->
+ dbg_out("Sender of table ~p crashed on node ~p ~n", [Tab, Node]),
+ down(Tab, Storage);
+
+ {'EXIT', Pid, Reason} ->
+ handle_exit(Pid, Reason),
+ tab_receiver(Node, Tab, Storage, Cs, PConv,OrigTabRec)
+ end.
+
+create_table(Tab, TabSize, Storage, Cs) ->
+ if
+ Storage == disc_only_copies ->
+ mnesia_lib:lock_table(Tab),
+ Tmp = mnesia_lib:tab2tmp(Tab),
+ Size = lists:max([TabSize, 256]),
+ Args = [{file, Tmp},
+ {keypos, 2},
+%% {ram_file, true},
+ {estimated_no_objects, Size},
+ {repair, mnesia_monitor:get_env(auto_repair)},
+ {type, mnesia_lib:disk_type(Tab, Cs#cstruct.type)}],
+ file:delete(Tmp),
+ case mnesia_lib:dets_sync_open(Tab, Args) of
+ {ok, _} ->
+ mnesia_lib:unlock_table(Tab),
+ {Storage, Tab};
+ Else ->
+ mnesia_lib:unlock_table(Tab),
+ Else
+ end;
+ (Storage == ram_copies) or (Storage == disc_copies) ->
+ Args = [{keypos, 2}, public, named_table, Cs#cstruct.type],
+ case mnesia_monitor:unsafe_mktab(Tab, Args) of
+ Tab ->
+ {Storage, Tab};
+ Else ->
+ Else
+ end
+ end.
+
+do_init_table(Tab,Storage,Cs,SenderPid,
+ TabSize,DetsInfo,OrigTabRec,Init) ->
+ case create_table(Tab, TabSize, Storage, Cs) of
+ {Storage,Tab} ->
+ %% Debug info
+ Node = node(SenderPid),
+ put(mnesia_table_receiver, {Tab, Node, SenderPid}),
+ mnesia_tm:block_tab(Tab),
+ PConv = mnesia_monitor:needs_protocol_conversion(Node),
+
+ case init_table(Tab,Storage,Init,PConv,DetsInfo,SenderPid) of
+ ok ->
+ tab_receiver(Node,Tab,Storage,Cs,PConv,OrigTabRec);
+ Reason ->
+ Msg = "[d]ets:init table failed",
+ dbg_out("~s: ~p: ~p~n", [Msg, Tab, Reason]),
+ down(Tab, Storage)
+ end;
+ Error ->
+ Error
+ end.
+
+make_table_fun(Pid, TabRec) ->
+ fun(close) ->
+ ok;
+ (read) ->
+ get_data(Pid, TabRec)
+ end.
+
+get_data(Pid, TabRec) ->
+ receive
+ {Pid, {more, Recs}} ->
+ Pid ! {TabRec, more},
+ {Recs, make_table_fun(Pid,TabRec)};
+ {Pid, no_more} ->
+ end_of_input;
+ {copier_done, Node} ->
+ case node(Pid) of
+ Node ->
+ {copier_done, Node};
+ _ ->
+ get_data(Pid, TabRec)
+ end;
+ {'EXIT', Pid, Reason} ->
+ handle_exit(Pid, Reason),
+ get_data(Pid, TabRec)
+ end.
+
+init_table(Tab, disc_only_copies, Fun, false, DetsInfo,Sender) ->
+ ErtsVer = erlang:system_info(version),
+ case DetsInfo of
+ {ErtsVer, DetsData} ->
+ Res = (catch dets:is_compatible_bchunk_format(Tab, DetsData)),
+ case Res of
+ {'EXIT',{undef,[{dets,_,_}|_]}} ->
+ Sender ! {self(), {old_protocol, Tab}},
+ dets:init_table(Tab, Fun); %% Old dets version
+ {'EXIT', What} ->
+ exit(What);
+ false ->
+ Sender ! {self(), {old_protocol, Tab}},
+ dets:init_table(Tab, Fun); %% Old dets version
+ true ->
+ dets:init_table(Tab, Fun, [{format, bchunk}])
+ end;
+ Old when Old /= false ->
+ Sender ! {self(), {old_protocol, Tab}},
+ dets:init_table(Tab, Fun); %% Old dets version
+ _ ->
+ dets:init_table(Tab, Fun)
+ end;
+init_table(Tab, _, Fun, false, _DetsInfo,_) ->
+ case catch ets:init_table(Tab, Fun) of
+ true ->
+ ok;
+ {'EXIT', Else} -> Else
+ end;
+init_table(Tab, Storage, Fun, true, _DetsInfo, Sender) -> %% Old Nodes
+ spawn_link(?MODULE, old_node_init_table,
+ [Tab, Storage, Fun, self(), false, Sender]),
+ ok.
+
+old_node_init_table(Tab, Storage, Fun, TabReceiver, DetsInfo,Sender) ->
+ Res = init_table(Tab, Storage, Fun, false, DetsInfo,Sender),
+ TabReceiver ! {old_init_table_complete, Res},
+ unlink(TabReceiver),
+ ok.
+
+finish_copy(Storage,Tab,Cs,SenderPid,DatBin,OrigTabRec) ->
+ TabRef = {Storage, Tab},
+ subscr_receiver(TabRef, Cs#cstruct.record_name),
+ case handle_last(TabRef, Cs#cstruct.type, DatBin) of
+ ok ->
+ mnesia_index:init_index(Tab, Storage),
+ snmpify(Tab, Storage),
+ %% OrigTabRec must not be the spawned tab-receiver
+ %% due to old protocol.
+ SenderPid ! {OrigTabRec, no_more},
+ mnesia_tm:unblock_tab(Tab),
+ ok;
+ {error, Reason} ->
+ Msg = "Failed to handle last",
+ dbg_out("~s: ~p: ~p~n", [Msg, Tab, Reason]),
+ down(Tab, Storage)
+ end.
+
+subscr_receiver(TabRef = {_, Tab}, RecName) ->
+ receive
+ {mnesia_table_event, {Op, Val, _Tid}} ->
+ if
+ Tab == RecName ->
+ handle_event(TabRef, Op, Val);
+ true ->
+ handle_event(TabRef, Op, setelement(1, Val, RecName))
+ end,
+ subscr_receiver(TabRef, RecName);
+
+ {'EXIT', Pid, Reason} ->
+ handle_exit(Pid, Reason),
+ subscr_receiver(TabRef, RecName)
+ after 0 ->
+ ok
+ end.
+
+handle_event(TabRef, write, Rec) ->
+ db_put(TabRef, Rec);
+handle_event(TabRef, delete, {_Tab, Key}) ->
+ db_erase(TabRef, Key);
+handle_event(TabRef, delete_object, OldRec) ->
+ db_match_erase(TabRef, OldRec);
+handle_event(TabRef, clear_table, {_Tab, _Key}) ->
+ db_match_erase(TabRef, '_').
+
+handle_last({disc_copies, Tab}, _Type, nobin) ->
+ Ret = mnesia_log:ets2dcd(Tab),
+ Fname = mnesia_lib:tab2dat(Tab),
+ case mnesia_lib:exists(Fname) of
+ true -> %% Remove old .DAT files.
+ file:delete(Fname);
+ false ->
+ ok
+ end,
+ Ret;
+
+handle_last({disc_only_copies, Tab}, Type, nobin) ->
+ case mnesia_lib:swap_tmp_files([Tab]) of
+ [] ->
+ Args = [{file, mnesia_lib:tab2dat(Tab)},
+ {type, mnesia_lib:disk_type(Tab, Type)},
+ {keypos, 2},
+ {repair, mnesia_monitor:get_env(auto_repair)}],
+ mnesia_monitor:open_dets(Tab, Args),
+ ok;
+ L when list(L) ->
+ {error, {"Cannot swap tmp files", Tab, L}}
+ end;
+
+handle_last({ram_copies, _Tab}, _Type, nobin) ->
+ ok;
+handle_last({ram_copies, Tab}, _Type, DatBin) ->
+ case mnesia_monitor:use_dir() of
+ true ->
+ mnesia_lib:lock_table(Tab),
+ Tmp = mnesia_lib:tab2tmp(Tab),
+ ok = file:write_file(Tmp, DatBin),
+ ok = file:rename(Tmp, mnesia_lib:tab2dcd(Tab)),
+ mnesia_lib:unlock_table(Tab),
+ ok;
+ false ->
+ ok
+ end.
+
+down(Tab, Storage) ->
+ case Storage of
+ ram_copies ->
+ catch ?ets_delete_table(Tab);
+ disc_copies ->
+ catch ?ets_delete_table(Tab);
+ disc_only_copies ->
+ mnesia_lib:cleanup_tmp_files([Tab])
+ end,
+ mnesia_checkpoint:tm_del_copy(Tab, node()),
+ mnesia_controller:sync_del_table_copy_whereabouts(Tab, node()),
+ mnesia_tm:unblock_tab(Tab),
+ flush_subcrs(),
+ down.
+
+flush_subcrs() ->
+ receive
+ {mnesia_table_event, _} ->
+ flush_subcrs();
+
+ {'EXIT', Pid, Reason} ->
+ handle_exit(Pid, Reason),
+ flush_subcrs()
+ after 0 ->
+ done
+ end.
+
+db_erase({ram_copies, Tab}, Key) ->
+ true = ?ets_delete(Tab, Key);
+db_erase({disc_copies, Tab}, Key) ->
+ true = ?ets_delete(Tab, Key);
+db_erase({disc_only_copies, Tab}, Key) ->
+ ok = dets:delete(Tab, Key).
+
+db_match_erase({ram_copies, Tab} , Pat) ->
+ true = ?ets_match_delete(Tab, Pat);
+db_match_erase({disc_copies, Tab} , Pat) ->
+ true = ?ets_match_delete(Tab, Pat);
+db_match_erase({disc_only_copies, Tab}, Pat) ->
+ ok = dets:match_delete(Tab, Pat).
+
+db_put({ram_copies, Tab}, Val) ->
+ true = ?ets_insert(Tab, Val);
+db_put({disc_copies, Tab}, Val) ->
+ true = ?ets_insert(Tab, Val);
+db_put({disc_only_copies, Tab}, Val) ->
+ ok = dets:insert(Tab, Val).
+
+%% This code executes at the remote site where the data is
+%% executes in a special copier process.
+
+calc_nokeys(Storage, Tab) ->
+ %% Calculate #keys per transfer
+ Key = mnesia_lib:db_first(Storage, Tab),
+ Recs = mnesia_lib:db_get(Storage, Tab, Key),
+ BinSize = size(term_to_binary(Recs)),
+ (?MAX_TRANSFER_SIZE div BinSize) + 1.
+
+send_table(Pid, Tab, RemoteS) ->
+ case ?catch_val({Tab, storage_type}) of
+ {'EXIT', _} ->
+ {error, {no_exists, Tab}};
+ unknown ->
+ {error, {no_exists, Tab}};
+ Storage ->
+ %% Send first
+ TabSize = mnesia:table_info(Tab, size),
+ Pconvert = mnesia_monitor:needs_protocol_conversion(node(Pid)),
+ KeysPerTransfer = calc_nokeys(Storage, Tab),
+ ChunkData = dets:info(Tab, bchunk_format),
+
+ UseDetsChunk =
+ Storage == RemoteS andalso
+ Storage == disc_only_copies andalso
+ ChunkData /= undefined andalso
+ Pconvert == false,
+ if
+ UseDetsChunk == true ->
+ DetsInfo = erlang:system_info(version),
+ Pid ! {self(), {first, TabSize, {DetsInfo, ChunkData}}};
+ true ->
+ Pid ! {self(), {first, TabSize}}
+ end,
+
+ %% Debug info
+ put(mnesia_table_sender, {Tab, node(Pid), Pid}),
+ {Init, Chunk} = reader_funcs(UseDetsChunk, Tab, Storage, KeysPerTransfer),
+
+ SendIt = fun() ->
+ prepare_copy(Pid, Tab, Storage),
+ send_more(Pid, 1, Chunk, Init(), Tab, Pconvert),
+ finish_copy(Pid, Tab, Storage, RemoteS)
+ end,
+
+ case catch SendIt() of
+ receiver_died ->
+ cleanup_tab_copier(Pid, Storage, Tab),
+ unlink(whereis(mnesia_tm)),
+ ok;
+ {_, receiver_died} ->
+ unlink(whereis(mnesia_tm)),
+ ok;
+ {'atomic', no_more} ->
+ unlink(whereis(mnesia_tm)),
+ ok;
+ Reason ->
+ cleanup_tab_copier(Pid, Storage, Tab),
+ unlink(whereis(mnesia_tm)),
+ {error, Reason}
+ end
+ end.
+
+prepare_copy(Pid, Tab, Storage) ->
+ Trans =
+ fun() ->
+ mnesia:write_lock_table(Tab),
+ mnesia_subscr:subscribe(Pid, {table, Tab}),
+ update_where_to_write(Tab, node(Pid)),
+ mnesia_lib:db_fixtable(Storage, Tab, true),
+ ok
+ end,
+ case mnesia:transaction(Trans) of
+ {'atomic', ok} ->
+ ok;
+ {aborted, Reason} ->
+ exit({tab_copier_prepare, Tab, Reason})
+ end.
+
+update_where_to_write(Tab, Node) ->
+ case val({Tab, access_mode}) of
+ read_only ->
+ ignore;
+ read_write ->
+ Current = val({current, db_nodes}),
+ Ns =
+ case lists:member(Node, Current) of
+ true -> Current;
+ false -> [Node | Current]
+ end,
+ update_where_to_write(Ns, Tab, Node)
+ end.
+
+update_where_to_write([], _, _) ->
+ ok;
+update_where_to_write([H|T], Tab, AddNode) ->
+ rpc:call(H, mnesia_controller, call,
+ [{update_where_to_write, [add, Tab, AddNode], self()}]),
+ update_where_to_write(T, Tab, AddNode).
+
+send_more(Pid, N, Chunk, DataState, Tab, OldNode) ->
+ receive
+ {NewPid, more} ->
+ case send_packet(N - 1, NewPid, Chunk, DataState, OldNode) of
+ New when integer(New) ->
+ New - 1;
+ NewData ->
+ send_more(NewPid, ?MAX_NOPACKETS, Chunk, NewData, Tab, OldNode)
+ end;
+ {_NewPid, {old_protocol, Tab}} ->
+ Storage = val({Tab, storage_type}),
+ {Init, NewChunk} =
+ reader_funcs(false, Tab, Storage, calc_nokeys(Storage, Tab)),
+ send_more(Pid, 1, NewChunk, Init(), Tab, OldNode);
+
+ {copier_done, Node} when Node == node(Pid)->
+ verbose("Receiver of table ~p crashed on ~p (more)~n", [Tab, Node]),
+ throw(receiver_died)
+ end.
+
+reader_funcs(UseDetsChunk, Tab, Storage, KeysPerTransfer) ->
+ case UseDetsChunk of
+ false ->
+ {fun() -> mnesia_lib:db_init_chunk(Storage, Tab, KeysPerTransfer) end,
+ fun(Cont) -> mnesia_lib:db_chunk(Storage, Cont) end};
+ true ->
+ {fun() -> dets_bchunk(Tab, start) end,
+ fun(Cont) -> dets_bchunk(Tab, Cont) end}
+ end.
+
+dets_bchunk(Tab, Chunk) -> %% Arrg
+ case dets:bchunk(Tab, Chunk) of
+ {Cont, Data} -> {Data, Cont};
+ Else -> Else
+ end.
+
+send_packet(N, Pid, _Chunk, '$end_of_table', OldNode) ->
+ case OldNode of
+ true -> ignore; %% Old nodes can't handle the new no_more
+ false -> Pid ! {self(), no_more}
+ end,
+ N;
+send_packet(N, Pid, Chunk, {[], Cont}, OldNode) ->
+ send_packet(N, Pid, Chunk, Chunk(Cont), OldNode);
+send_packet(N, Pid, Chunk, {Recs, Cont}, OldNode) when N < ?MAX_NOPACKETS ->
+ case OldNode of
+ true -> Pid ! {self(), {more, [Recs]}}; %% Old need's wrapping list
+ false -> Pid ! {self(), {more, Recs}}
+ end,
+ send_packet(N+1, Pid, Chunk, Chunk(Cont), OldNode);
+send_packet(_N, _Pid, _Chunk, DataState, _OldNode) ->
+ DataState.
+
+finish_copy(Pid, Tab, Storage, RemoteS) ->
+ RecNode = node(Pid),
+ DatBin = dat2bin(Tab, Storage, RemoteS),
+ Trans =
+ fun() ->
+ mnesia:read_lock_table(Tab),
+ A = val({Tab, access_mode}),
+ mnesia_controller:sync_and_block_table_whereabouts(Tab, RecNode, RemoteS, A),
+ cleanup_tab_copier(Pid, Storage, Tab),
+ mnesia_checkpoint:tm_add_copy(Tab, RecNode),
+ Pid ! {self(), {no_more, DatBin}},
+ receive
+ {Pid, no_more} -> % Dont bother about the spurious 'more' message
+ no_more;
+ {copier_done, Node} when Node == node(Pid)->
+ verbose("Tab receiver ~p crashed (more): ~p~n", [Tab, Node]),
+ receiver_died
+ end
+ end,
+ mnesia:transaction(Trans).
+
+cleanup_tab_copier(Pid, Storage, Tab) ->
+ mnesia_lib:db_fixtable(Storage, Tab, false),
+ mnesia_subscr:unsubscribe(Pid, {table, Tab}).
+
+dat2bin(Tab, ram_copies, ram_copies) ->
+ mnesia_lib:lock_table(Tab),
+ Res = file:read_file(mnesia_lib:tab2dcd(Tab)),
+ mnesia_lib:unlock_table(Tab),
+ case Res of
+ {ok, DatBin} -> DatBin;
+ _ -> nobin
+ end;
+dat2bin(_Tab, _LocalS, _RemoteS) ->
+ nobin.
+
+handle_exit(Pid, Reason) when node(Pid) == node() ->
+ exit(Reason);
+handle_exit(_Pid, _Reason) -> %% Not from our node, this will be handled by
+ ignore. %% mnesia_down soon.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_locker.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_locker.erl
new file mode 100644
index 0000000000..c24ccc5518
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_locker.erl
@@ -0,0 +1,1021 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_locker.erl,v 1.2 2009/07/01 15:45:40 kostis Exp $
+%%
+-module(mnesia_locker).
+
+-export([
+ get_held_locks/0,
+ get_lock_queue/0,
+ global_lock/5,
+ ixrlock/5,
+ init/1,
+ mnesia_down/2,
+ release_tid/1,
+ async_release_tid/2,
+ send_release_tid/2,
+ receive_release_tid_acc/2,
+ rlock/3,
+ rlock_table/3,
+ rwlock/3,
+ sticky_rwlock/3,
+ start/0,
+ sticky_wlock/3,
+ sticky_wlock_table/3,
+ wlock/3,
+ wlock_no_exist/4,
+ wlock_table/3
+ ]).
+
+%% sys callback functions
+-export([system_continue/3,
+ system_terminate/4,
+ system_code_change/4
+ ]).
+
+-include("mnesia.hrl").
+-import(mnesia_lib, [dbg_out/2, error/2, verbose/2]).
+
+-define(dbg(S,V), ok).
+%-define(dbg(S,V), dbg_out("~p:~p: " ++ S, [?MODULE, ?LINE] ++ V)).
+
+-define(ALL, '______WHOLETABLE_____').
+-define(STICK, '______STICK_____').
+-define(GLOBAL, '______GLOBAL_____').
+
+-record(state, {supervisor}).
+
+-record(queue, {oid, tid, op, pid, lucky}).
+
+%% mnesia_held_locks: contain {Oid, Op, Tid} entries (bag)
+-define(match_oid_held_locks(Oid), {Oid, '_', '_'}).
+%% mnesia_tid_locks: contain {Tid, Oid, Op} entries (bag)
+-define(match_oid_tid_locks(Tid), {Tid, '_', '_'}).
+%% mnesia_sticky_locks: contain {Oid, Node} entries and {Tab, Node} entries (set)
+-define(match_oid_sticky_locks(Oid),{Oid, '_'}).
+%% mnesia_lock_queue: contain {queue, Oid, Tid, Op, ReplyTo, WaitForTid} entries (ordered_set)
+-define(match_oid_lock_queue(Oid), #queue{oid=Oid, tid='_', op = '_', pid = '_', lucky = '_'}).
+%% mnesia_lock_counter: {{write, Tab}, Number} &&
+%% {{read, Tab}, Number} entries (set)
+
+start() ->
+ mnesia_monitor:start_proc(?MODULE, ?MODULE, init, [self()]).
+
+init(Parent) ->
+ register(?MODULE, self()),
+ process_flag(trap_exit, true),
+ proc_lib:init_ack(Parent, {ok, self()}),
+ loop(#state{supervisor = Parent}).
+
+val(Var) ->
+ case ?catch_val(Var) of
+ {'EXIT', _ReASoN_} -> mnesia_lib:other_val(Var, _ReASoN_);
+ _VaLuE_ -> _VaLuE_
+ end.
+
+reply(From, R) ->
+ From ! {?MODULE, node(), R}.
+
+l_request(Node, X, Store) ->
+ {?MODULE, Node} ! {self(), X},
+ l_req_rec(Node, Store).
+
+l_req_rec(Node, Store) ->
+ ?ets_insert(Store, {nodes, Node}),
+ receive
+ {?MODULE, Node, {switch, Node2, Req}} ->
+ ?ets_insert(Store, {nodes, Node2}),
+ {?MODULE, Node2} ! Req,
+ {switch, Node2, Req};
+ {?MODULE, Node, Reply} ->
+ Reply;
+ {mnesia_down, Node} ->
+ {not_granted, {node_not_running, Node}}
+ end.
+
+release_tid(Tid) ->
+ ?MODULE ! {release_tid, Tid}.
+
+async_release_tid(Nodes, Tid) ->
+ rpc:abcast(Nodes, ?MODULE, {release_tid, Tid}).
+
+send_release_tid(Nodes, Tid) ->
+ rpc:abcast(Nodes, ?MODULE, {self(), {sync_release_tid, Tid}}).
+
+receive_release_tid_acc([Node | Nodes], Tid) ->
+ receive
+ {?MODULE, Node, {tid_released, Tid}} ->
+ receive_release_tid_acc(Nodes, Tid);
+ {mnesia_down, Node} ->
+ receive_release_tid_acc(Nodes, Tid)
+ end;
+receive_release_tid_acc([], _Tid) ->
+ ok.
+
+loop(State) ->
+ receive
+ {From, {write, Tid, Oid}} ->
+ try_sticky_lock(Tid, write, From, Oid),
+ loop(State);
+
+ %% If Key == ?ALL it's a request to lock the entire table
+ %%
+
+ {From, {read, Tid, Oid}} ->
+ try_sticky_lock(Tid, read, From, Oid),
+ loop(State);
+
+ %% Really do a read, but get hold of a write lock
+ %% used by mnesia:wread(Oid).
+
+ {From, {read_write, Tid, Oid}} ->
+ try_sticky_lock(Tid, read_write, From, Oid),
+ loop(State);
+
+ %% Tid has somehow terminated, clear up everything
+ %% and pass locks on to queued processes.
+ %% This is the purpose of the mnesia_tid_locks table
+
+ {release_tid, Tid} ->
+ do_release_tid(Tid),
+ loop(State);
+
+ %% stick lock, first tries this to the where_to_read Node
+ {From, {test_set_sticky, Tid, {Tab, _} = Oid, Lock}} ->
+ case ?ets_lookup(mnesia_sticky_locks, Tab) of
+ [] ->
+ reply(From, not_stuck),
+ loop(State);
+ [{_,Node}] when Node == node() ->
+ %% Lock is stuck here, see now if we can just set
+ %% a regular write lock
+ try_lock(Tid, Lock, From, Oid),
+ loop(State);
+ [{_,Node}] ->
+ reply(From, {stuck_elsewhere, Node}),
+ loop(State)
+ end;
+
+ %% If test_set_sticky fails, we send this to all nodes
+ %% after aquiring a real write lock on Oid
+
+ {stick, {Tab, _}, N} ->
+ ?ets_insert(mnesia_sticky_locks, {Tab, N}),
+ loop(State);
+
+ %% The caller which sends this message, must have first
+ %% aquired a write lock on the entire table
+ {unstick, Tab} ->
+ ?ets_delete(mnesia_sticky_locks, Tab),
+ loop(State);
+
+ {From, {ix_read, Tid, Tab, IxKey, Pos}} ->
+ case catch mnesia_index:get_index_table(Tab, Pos) of
+ {'EXIT', _} ->
+ reply(From, {not_granted, {no_exists, Tab, {index, [Pos]}}}),
+ loop(State);
+ Index ->
+ Rk = mnesia_lib:elems(2,mnesia_index:db_get(Index, IxKey)),
+ %% list of real keys
+ case ?ets_lookup(mnesia_sticky_locks, Tab) of
+ [] ->
+ set_read_lock_on_all_keys(Tid, From,Tab,Rk,Rk,
+ []),
+ loop(State);
+ [{_,N}] when N == node() ->
+ set_read_lock_on_all_keys(Tid, From,Tab,Rk,Rk,
+ []),
+ loop(State);
+ [{_,N}] ->
+ Req = {From, {ix_read, Tid, Tab, IxKey, Pos}},
+ From ! {?MODULE, node(), {switch, N, Req}},
+ loop(State)
+ end
+ end;
+
+ {From, {sync_release_tid, Tid}} ->
+ do_release_tid(Tid),
+ reply(From, {tid_released, Tid}),
+ loop(State);
+
+ {release_remote_non_pending, Node, Pending} ->
+ release_remote_non_pending(Node, Pending),
+ mnesia_monitor:mnesia_down(?MODULE, Node),
+ loop(State);
+
+ {'EXIT', Pid, _} when Pid == State#state.supervisor ->
+ do_stop();
+
+ {system, From, Msg} ->
+ verbose("~p got {system, ~p, ~p}~n", [?MODULE, From, Msg]),
+ Parent = State#state.supervisor,
+ sys:handle_system_msg(Msg, From, Parent, ?MODULE, [], State);
+
+ Msg ->
+ error("~p got unexpected message: ~p~n", [?MODULE, Msg]),
+ loop(State)
+ end.
+
+set_lock(Tid, Oid, Op) ->
+ ?dbg("Granted ~p ~p ~p~n", [Tid,Oid,Op]),
+ ?ets_insert(mnesia_held_locks, {Oid, Op, Tid}),
+ ?ets_insert(mnesia_tid_locks, {Tid, Oid, Op}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Acquire locks
+
+try_sticky_lock(Tid, Op, Pid, {Tab, _} = Oid) ->
+ case ?ets_lookup(mnesia_sticky_locks, Tab) of
+ [] ->
+ try_lock(Tid, Op, Pid, Oid);
+ [{_,N}] when N == node() ->
+ try_lock(Tid, Op, Pid, Oid);
+ [{_,N}] ->
+ Req = {Pid, {Op, Tid, Oid}},
+ Pid ! {?MODULE, node(), {switch, N, Req}}
+ end.
+
+try_lock(Tid, read_write, Pid, Oid) ->
+ try_lock(Tid, read_write, read, write, Pid, Oid);
+try_lock(Tid, Op, Pid, Oid) ->
+ try_lock(Tid, Op, Op, Op, Pid, Oid).
+
+try_lock(Tid, Op, SimpleOp, Lock, Pid, Oid) ->
+ case can_lock(Tid, Lock, Oid, {no, bad_luck}) of
+ yes ->
+ Reply = grant_lock(Tid, SimpleOp, Lock, Oid),
+ reply(Pid, Reply);
+ {no, Lucky} ->
+ C = #cyclic{op = SimpleOp, lock = Lock, oid = Oid, lucky = Lucky},
+ ?dbg("Rejected ~p ~p ~p ~p ~n", [Tid, Oid, Lock, Lucky]),
+ reply(Pid, {not_granted, C});
+ {queue, Lucky} ->
+ ?dbg("Queued ~p ~p ~p ~p ~n", [Tid, Oid, Lock, Lucky]),
+ %% Append to queue: Nice place for trace output
+ ?ets_insert(mnesia_lock_queue,
+ #queue{oid = Oid, tid = Tid, op = Op,
+ pid = Pid, lucky = Lucky}),
+ ?ets_insert(mnesia_tid_locks, {Tid, Oid, {queued, Op}})
+ end.
+
+grant_lock(Tid, read, Lock, {Tab, Key})
+ when Key /= ?ALL, Tab /= ?GLOBAL ->
+ case node(Tid#tid.pid) == node() of
+ true ->
+ set_lock(Tid, {Tab, Key}, Lock),
+ {granted, lookup_in_client};
+ false ->
+ case catch mnesia_lib:db_get(Tab, Key) of %% lookup as well
+ {'EXIT', _Reason} ->
+ %% Table has been deleted from this node,
+ %% restart the transaction.
+ C = #cyclic{op = read, lock = Lock, oid = {Tab, Key},
+ lucky = nowhere},
+ {not_granted, C};
+ Val ->
+ set_lock(Tid, {Tab, Key}, Lock),
+ {granted, Val}
+ end
+ end;
+grant_lock(Tid, read, Lock, Oid) ->
+ set_lock(Tid, Oid, Lock),
+ {granted, ok};
+grant_lock(Tid, write, Lock, Oid) ->
+ set_lock(Tid, Oid, Lock),
+ granted.
+
+%% 1) Impose an ordering on all transactions favour old (low tid) transactions
+%% newer (higher tid) transactions may never wait on older ones,
+%% 2) When releasing the tids from the queue always begin with youngest (high tid)
+%% because of 1) it will avoid the deadlocks.
+%% 3) TabLocks is the problem :-) They should not starve and not deadlock
+%% handle tablocks in queue as they had locks on unlocked records.
+
+can_lock(Tid, read, {Tab, Key}, AlreadyQ) when Key /= ?ALL ->
+ %% The key is bound, no need for the other BIF
+ Oid = {Tab, Key},
+ ObjLocks = ?ets_match_object(mnesia_held_locks, {Oid, write, '_'}),
+ TabLocks = ?ets_match_object(mnesia_held_locks, {{Tab, ?ALL}, write, '_'}),
+ check_lock(Tid, Oid, ObjLocks, TabLocks, yes, AlreadyQ, read);
+
+can_lock(Tid, read, Oid, AlreadyQ) -> % Whole tab
+ Tab = element(1, Oid),
+ ObjLocks = ?ets_match_object(mnesia_held_locks, {{Tab, '_'}, write, '_'}),
+ check_lock(Tid, Oid, ObjLocks, [], yes, AlreadyQ, read);
+
+can_lock(Tid, write, {Tab, Key}, AlreadyQ) when Key /= ?ALL ->
+ Oid = {Tab, Key},
+ ObjLocks = ?ets_lookup(mnesia_held_locks, Oid),
+ TabLocks = ?ets_lookup(mnesia_held_locks, {Tab, ?ALL}),
+ check_lock(Tid, Oid, ObjLocks, TabLocks, yes, AlreadyQ, write);
+
+can_lock(Tid, write, Oid, AlreadyQ) -> % Whole tab
+ Tab = element(1, Oid),
+ ObjLocks = ?ets_match_object(mnesia_held_locks, ?match_oid_held_locks({Tab, '_'})),
+ check_lock(Tid, Oid, ObjLocks, [], yes, AlreadyQ, write).
+
+%% Check held locks for conflicting locks
+check_lock(Tid, Oid, [Lock | Locks], TabLocks, X, AlreadyQ, Type) ->
+ case element(3, Lock) of
+ Tid ->
+ check_lock(Tid, Oid, Locks, TabLocks, X, AlreadyQ, Type);
+ WaitForTid when WaitForTid > Tid -> % Important order
+ check_lock(Tid, Oid, Locks, TabLocks, {queue, WaitForTid}, AlreadyQ, Type);
+ WaitForTid when Tid#tid.pid == WaitForTid#tid.pid ->
+ dbg_out("Spurious lock conflict ~w ~w: ~w -> ~w~n",
+ [Oid, Lock, Tid, WaitForTid]),
+%% check_lock(Tid, Oid, Locks, TabLocks, {queue, WaitForTid}, AlreadyQ);
+ %% BUGBUG Fix this if possible
+ {no, WaitForTid};
+ WaitForTid ->
+ {no, WaitForTid}
+ end;
+
+check_lock(_, _, [], [], X, {queue, bad_luck}, _) ->
+ X; %% The queue should be correct already no need to check it again
+
+check_lock(_, _, [], [], X = {queue, _Tid}, _AlreadyQ, _) ->
+ X;
+
+check_lock(Tid, Oid, [], [], X, AlreadyQ, Type) ->
+ {Tab, Key} = Oid,
+ if
+ Type == write ->
+ check_queue(Tid, Tab, X, AlreadyQ);
+ Key == ?ALL ->
+ %% hmm should be solvable by a clever select expr but not today...
+ check_queue(Tid, Tab, X, AlreadyQ);
+ true ->
+ %% If there is a queue on that object, read_lock shouldn't be granted
+ ObjLocks = ets:lookup(mnesia_lock_queue, Oid),
+ Greatest = max(ObjLocks),
+ case Greatest of
+ empty ->
+ check_queue(Tid, Tab, X, AlreadyQ);
+ ObjL when Tid > ObjL ->
+ {no, ObjL}; %% Starvation Preemption (write waits for read)
+ ObjL ->
+ check_queue(Tid, Tab, {queue, ObjL}, AlreadyQ)
+ end
+ end;
+
+check_lock(Tid, Oid, [], TabLocks, X, AlreadyQ, Type) ->
+ check_lock(Tid, Oid, TabLocks, [], X, AlreadyQ, Type).
+
+%% Check queue for conflicting locks
+%% Assume that all queued locks belongs to other tid's
+
+check_queue(Tid, Tab, X, AlreadyQ) ->
+ TabLocks = ets:lookup(mnesia_lock_queue, {Tab,?ALL}),
+ Greatest = max(TabLocks),
+ case Greatest of
+ empty ->
+ X;
+ Tid ->
+ X;
+ WaitForTid when WaitForTid#queue.tid > Tid -> % Important order
+ {queue, WaitForTid};
+ WaitForTid ->
+ case AlreadyQ of
+ {no, bad_luck} -> {no, WaitForTid};
+ _ ->
+ erlang:error({mnesia_locker, assert, AlreadyQ})
+ end
+ end.
+
+max([]) ->
+ empty;
+max([H|R]) ->
+ max(R, H#queue.tid).
+
+max([H|R], Tid) when H#queue.tid > Tid ->
+ max(R, H#queue.tid);
+max([_|R], Tid) ->
+ max(R, Tid);
+max([], Tid) ->
+ Tid.
+
+%% We can't queue the ixlock requests since it
+%% becomes to complivated for little me :-)
+%% If we encounter an object with a wlock we reject the
+%% entire lock request
+%%
+%% BUGBUG: this is actually a bug since we may starve
+
+set_read_lock_on_all_keys(Tid, From, Tab, [RealKey | Tail], Orig, Ack) ->
+ Oid = {Tab, RealKey},
+ case can_lock(Tid, read, Oid, {no, bad_luck}) of
+ yes ->
+ {granted, Val} = grant_lock(Tid, read, read, Oid),
+ case opt_lookup_in_client(Val, Oid, read) of % Ought to be invoked
+ C when record(C, cyclic) -> % in the client
+ reply(From, {not_granted, C});
+ Val2 ->
+ Ack2 = lists:append(Val2, Ack),
+ set_read_lock_on_all_keys(Tid, From, Tab, Tail, Orig, Ack2)
+ end;
+ {no, Lucky} ->
+ C = #cyclic{op = read, lock = read, oid = Oid, lucky = Lucky},
+ reply(From, {not_granted, C});
+ {queue, Lucky} ->
+ C = #cyclic{op = read, lock = read, oid = Oid, lucky = Lucky},
+ reply(From, {not_granted, C})
+ end;
+set_read_lock_on_all_keys(_Tid, From, _Tab, [], Orig, Ack) ->
+ reply(From, {granted, Ack, Orig}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Release of locks
+
+%% Release remote non-pending nodes
+release_remote_non_pending(Node, Pending) ->
+ %% Clear the mnesia_sticky_locks table first, to avoid
+ %% unnecessary requests to the failing node
+ ?ets_match_delete(mnesia_sticky_locks, {'_' , Node}),
+
+ %% Then we have to release all locks held by processes
+ %% running at the failed node and also simply remove all
+ %% queue'd requests back to the failed node
+
+ AllTids = ?ets_match(mnesia_tid_locks, {'$1', '_', '_'}),
+ Tids = [T || [T] <- AllTids, Node == node(T#tid.pid), not lists:member(T, Pending)],
+ do_release_tids(Tids).
+
+do_release_tids([Tid | Tids]) ->
+ do_release_tid(Tid),
+ do_release_tids(Tids);
+do_release_tids([]) ->
+ ok.
+
+do_release_tid(Tid) ->
+ Locks = ?ets_lookup(mnesia_tid_locks, Tid),
+ ?dbg("Release ~p ~p ~n", [Tid, Locks]),
+ ?ets_delete(mnesia_tid_locks, Tid),
+ release_locks(Locks),
+ %% Removed queued locks which has had locks
+ UniqueLocks = keyunique(lists:sort(Locks),[]),
+ rearrange_queue(UniqueLocks).
+
+keyunique([{_Tid, Oid, _Op}|R], Acc = [{_, Oid, _}|_]) ->
+ keyunique(R, Acc);
+keyunique([H|R], Acc) ->
+ keyunique(R, [H|Acc]);
+keyunique([], Acc) ->
+ Acc.
+
+release_locks([Lock | Locks]) ->
+ release_lock(Lock),
+ release_locks(Locks);
+release_locks([]) ->
+ ok.
+
+release_lock({Tid, Oid, {queued, _}}) ->
+ ?ets_match_delete(mnesia_lock_queue,
+ #queue{oid=Oid, tid = Tid, op = '_',
+ pid = '_', lucky = '_'});
+release_lock({Tid, Oid, Op}) ->
+ if
+ Op == write ->
+ ?ets_delete(mnesia_held_locks, Oid);
+ Op == read ->
+ ?ets_match_delete(mnesia_held_locks, {Oid, Op, Tid})
+ end.
+
+rearrange_queue([{_Tid, {Tab, Key}, _} | Locks]) ->
+ if
+ Key /= ?ALL->
+ Queue =
+ ets:lookup(mnesia_lock_queue, {Tab, ?ALL}) ++
+ ets:lookup(mnesia_lock_queue, {Tab, Key}),
+ case Queue of
+ [] ->
+ ok;
+ _ ->
+ Sorted = lists:reverse(lists:keysort(#queue.tid, Queue)),
+ try_waiters_obj(Sorted)
+ end;
+ true ->
+ Pat = ?match_oid_lock_queue({Tab, '_'}),
+ Queue = ?ets_match_object(mnesia_lock_queue, Pat),
+ Sorted = lists:reverse(lists:keysort(#queue.tid, Queue)),
+ try_waiters_tab(Sorted)
+ end,
+ ?dbg("RearrQ ~p~n", [Queue]),
+ rearrange_queue(Locks);
+rearrange_queue([]) ->
+ ok.
+
+try_waiters_obj([W | Waiters]) ->
+ case try_waiter(W) of
+ queued ->
+ no;
+ _ ->
+ try_waiters_obj(Waiters)
+ end;
+try_waiters_obj([]) ->
+ ok.
+
+try_waiters_tab([W | Waiters]) ->
+ case W#queue.oid of
+ {_Tab, ?ALL} ->
+ case try_waiter(W) of
+ queued ->
+ no;
+ _ ->
+ try_waiters_tab(Waiters)
+ end;
+ Oid ->
+ case try_waiter(W) of
+ queued ->
+ Rest = key_delete_all(Oid, #queue.oid, Waiters),
+ try_waiters_tab(Rest);
+ _ ->
+ try_waiters_tab(Waiters)
+ end
+ end;
+try_waiters_tab([]) ->
+ ok.
+
+try_waiter({queue, Oid, Tid, read_write, ReplyTo, _}) ->
+ try_waiter(Oid, read_write, read, write, ReplyTo, Tid);
+try_waiter({queue, Oid, Tid, Op, ReplyTo, _}) ->
+ try_waiter(Oid, Op, Op, Op, ReplyTo, Tid).
+
+try_waiter(Oid, Op, SimpleOp, Lock, ReplyTo, Tid) ->
+ case can_lock(Tid, Lock, Oid, {queue, bad_luck}) of
+ yes ->
+ %% Delete from queue: Nice place for trace output
+ ?ets_match_delete(mnesia_lock_queue,
+ #queue{oid=Oid, tid = Tid, op = Op,
+ pid = ReplyTo, lucky = '_'}),
+ Reply = grant_lock(Tid, SimpleOp, Lock, Oid),
+ ReplyTo ! {?MODULE, node(), Reply},
+ locked;
+ {queue, _Why} ->
+ ?dbg("Keep ~p ~p ~p ~p~n", [Tid, Oid, Lock, _Why]),
+ queued; % Keep waiter in queue
+ {no, Lucky} ->
+ C = #cyclic{op = SimpleOp, lock = Lock, oid = Oid, lucky = Lucky},
+ verbose("** WARNING ** Restarted transaction, possible deadlock in lock queue ~w: cyclic = ~w~n",
+ [Tid, C]),
+ ?ets_match_delete(mnesia_lock_queue,
+ #queue{oid=Oid, tid = Tid, op = Op,
+ pid = ReplyTo, lucky = '_'}),
+ Reply = {not_granted, C},
+ ReplyTo ! {?MODULE, node(), Reply},
+ removed
+ end.
+
+key_delete_all(Key, Pos, TupleList) ->
+ key_delete_all(Key, Pos, TupleList, []).
+key_delete_all(Key, Pos, [H|T], Ack) when element(Pos, H) == Key ->
+ key_delete_all(Key, Pos, T, Ack);
+key_delete_all(Key, Pos, [H|T], Ack) ->
+ key_delete_all(Key, Pos, T, [H|Ack]);
+key_delete_all(_, _, [], Ack) ->
+ lists:reverse(Ack).
+
+
+%% ********************* end server code ********************
+%% The following code executes at the client side of a transactions
+
+mnesia_down(N, Pending) ->
+ case whereis(?MODULE) of
+ undefined ->
+ %% Takes care of mnesia_down's in early startup
+ mnesia_monitor:mnesia_down(?MODULE, N);
+ Pid ->
+ %% Syncronously call needed in order to avoid
+ %% race with mnesia_tm's coordinator processes
+ %% that may restart and acquire new locks.
+ %% mnesia_monitor ensures the sync.
+ Pid ! {release_remote_non_pending, N, Pending}
+ end.
+
+%% Aquire a write lock, but do a read, used by
+%% mnesia:wread/1
+
+rwlock(Tid, Store, Oid) ->
+ {Tab, Key} = Oid,
+ case val({Tab, where_to_read}) of
+ nowhere ->
+ mnesia:abort({no_exists, Tab});
+ Node ->
+ Lock = write,
+ case need_lock(Store, Tab, Key, Lock) of
+ yes ->
+ Ns = w_nodes(Tab),
+ Res = get_rwlocks_on_nodes(Ns, Ns, Node, Store, Tid, Oid),
+ ?ets_insert(Store, {{locks, Tab, Key}, Lock}),
+ Res;
+ no ->
+ if
+ Key == ?ALL ->
+ w_nodes(Tab);
+ Tab == ?GLOBAL ->
+ w_nodes(Tab);
+ true ->
+ dirty_rpc(Node, Tab, Key, Lock)
+ end
+ end
+ end.
+
+get_rwlocks_on_nodes([Node | Tail], Orig, Node, Store, Tid, Oid) ->
+ Op = {self(), {read_write, Tid, Oid}},
+ {?MODULE, Node} ! Op,
+ ?ets_insert(Store, {nodes, Node}),
+ add_debug(Node),
+ get_rwlocks_on_nodes(Tail, Orig, Node, Store, Tid, Oid);
+get_rwlocks_on_nodes([Node | Tail], Orig, OtherNode, Store, Tid, Oid) ->
+ Op = {self(), {write, Tid, Oid}},
+ {?MODULE, Node} ! Op,
+ add_debug(Node),
+ ?ets_insert(Store, {nodes, Node}),
+ get_rwlocks_on_nodes(Tail, Orig, OtherNode, Store, Tid, Oid);
+get_rwlocks_on_nodes([], Orig, _Node, Store, _Tid, Oid) ->
+ receive_wlocks(Orig, read_write_lock, Store, Oid).
+
+%% Return a list of nodes or abort transaction
+%% WE also insert any additional where_to_write nodes
+%% in the local store under the key == nodes
+
+w_nodes(Tab) ->
+ Nodes = ?catch_val({Tab, where_to_write}),
+ case Nodes of
+ [_ | _] -> Nodes;
+ _ -> mnesia:abort({no_exists, Tab})
+ end.
+
+%% aquire a sticky wlock, a sticky lock is a lock
+%% which remains at this node after the termination of the
+%% transaction.
+
+sticky_wlock(Tid, Store, Oid) ->
+ sticky_lock(Tid, Store, Oid, write).
+
+sticky_rwlock(Tid, Store, Oid) ->
+ sticky_lock(Tid, Store, Oid, read_write).
+
+sticky_lock(Tid, Store, {Tab, Key} = Oid, Lock) ->
+ N = val({Tab, where_to_read}),
+ if
+ node() == N ->
+ case need_lock(Store, Tab, Key, write) of
+ yes ->
+ do_sticky_lock(Tid, Store, Oid, Lock);
+ no ->
+ dirty_sticky_lock(Tab, Key, [N], Lock)
+ end;
+ true ->
+ mnesia:abort({not_local, Tab})
+ end.
+
+do_sticky_lock(Tid, Store, {Tab, Key} = Oid, Lock) ->
+ ?MODULE ! {self(), {test_set_sticky, Tid, Oid, Lock}},
+ receive
+ {?MODULE, _N, granted} ->
+ ?ets_insert(Store, {{locks, Tab, Key}, write}),
+ granted;
+ {?MODULE, _N, {granted, Val}} -> %% for rwlocks
+ case opt_lookup_in_client(Val, Oid, write) of
+ C when record(C, cyclic) ->
+ exit({aborted, C});
+ Val2 ->
+ ?ets_insert(Store, {{locks, Tab, Key}, write}),
+ Val2
+ end;
+ {?MODULE, _N, {not_granted, Reason}} ->
+ exit({aborted, Reason});
+ {?MODULE, N, not_stuck} ->
+ not_stuck(Tid, Store, Tab, Key, Oid, Lock, N),
+ dirty_sticky_lock(Tab, Key, [N], Lock);
+ {mnesia_down, N} ->
+ exit({aborted, {node_not_running, N}});
+ {?MODULE, N, {stuck_elsewhere, _N2}} ->
+ stuck_elsewhere(Tid, Store, Tab, Key, Oid, Lock),
+ dirty_sticky_lock(Tab, Key, [N], Lock)
+ end.
+
+not_stuck(Tid, Store, Tab, _Key, Oid, _Lock, N) ->
+ rlock(Tid, Store, {Tab, ?ALL}), %% needed?
+ wlock(Tid, Store, Oid), %% perfect sync
+ wlock(Tid, Store, {Tab, ?STICK}), %% max one sticker/table
+ Ns = val({Tab, where_to_write}),
+ rpc:abcast(Ns, ?MODULE, {stick, Oid, N}).
+
+stuck_elsewhere(Tid, Store, Tab, _Key, Oid, _Lock) ->
+ rlock(Tid, Store, {Tab, ?ALL}), %% needed?
+ wlock(Tid, Store, Oid), %% perfect sync
+ wlock(Tid, Store, {Tab, ?STICK}), %% max one sticker/table
+ Ns = val({Tab, where_to_write}),
+ rpc:abcast(Ns, ?MODULE, {unstick, Tab}).
+
+dirty_sticky_lock(Tab, Key, Nodes, Lock) ->
+ if
+ Lock == read_write ->
+ mnesia_lib:db_get(Tab, Key);
+ Key == ?ALL ->
+ Nodes;
+ Tab == ?GLOBAL ->
+ Nodes;
+ true ->
+ ok
+ end.
+
+sticky_wlock_table(Tid, Store, Tab) ->
+ sticky_lock(Tid, Store, {Tab, ?ALL}, write).
+
+%% aquire a wlock on Oid
+%% We store a {Tabname, write, Tid} in all locktables
+%% on all nodes containing a copy of Tabname
+%% We also store an item {{locks, Tab, Key}, write} in the
+%% local store when we have aquired the lock.
+%%
+wlock(Tid, Store, Oid) ->
+ {Tab, Key} = Oid,
+ case need_lock(Store, Tab, Key, write) of
+ yes ->
+ Ns = w_nodes(Tab),
+ Op = {self(), {write, Tid, Oid}},
+ ?ets_insert(Store, {{locks, Tab, Key}, write}),
+ get_wlocks_on_nodes(Ns, Ns, Store, Op, Oid);
+ no when Key /= ?ALL, Tab /= ?GLOBAL ->
+ [];
+ no ->
+ w_nodes(Tab)
+ end.
+
+wlock_table(Tid, Store, Tab) ->
+ wlock(Tid, Store, {Tab, ?ALL}).
+
+%% Write lock even if the table does not exist
+
+wlock_no_exist(Tid, Store, Tab, Ns) ->
+ Oid = {Tab, ?ALL},
+ Op = {self(), {write, Tid, Oid}},
+ get_wlocks_on_nodes(Ns, Ns, Store, Op, Oid).
+
+need_lock(Store, Tab, Key, LockPattern) ->
+ TabL = ?ets_match_object(Store, {{locks, Tab, ?ALL}, LockPattern}),
+ if
+ TabL == [] ->
+ KeyL = ?ets_match_object(Store, {{locks, Tab, Key}, LockPattern}),
+ if
+ KeyL == [] ->
+ yes;
+ true ->
+ no
+ end;
+ true ->
+ no
+ end.
+
+add_debug(Node) -> % Use process dictionary for debug info
+ case get(mnesia_wlock_nodes) of
+ undefined ->
+ put(mnesia_wlock_nodes, [Node]);
+ NodeList ->
+ put(mnesia_wlock_nodes, [Node|NodeList])
+ end.
+
+del_debug(Node) ->
+ case get(mnesia_wlock_nodes) of
+ undefined -> % Shouldn't happen
+ ignore;
+ [Node] ->
+ erase(mnesia_wlock_nodes);
+ List ->
+ put(mnesia_wlock_nodes, lists:delete(Node, List))
+ end.
+
+%% We first send lock requests to the lockmanagers on all
+%% nodes holding a copy of the table
+
+get_wlocks_on_nodes([Node | Tail], Orig, Store, Request, Oid) ->
+ {?MODULE, Node} ! Request,
+ ?ets_insert(Store, {nodes, Node}),
+ add_debug(Node),
+ get_wlocks_on_nodes(Tail, Orig, Store, Request, Oid);
+get_wlocks_on_nodes([], Orig, Store, _Request, Oid) ->
+ receive_wlocks(Orig, Orig, Store, Oid).
+
+receive_wlocks([Node | Tail], Res, Store, Oid) ->
+ receive
+ {?MODULE, Node, granted} ->
+ del_debug(Node),
+ receive_wlocks(Tail, Res, Store, Oid);
+ {?MODULE, Node, {granted, Val}} -> %% for rwlocks
+ del_debug(Node),
+ case opt_lookup_in_client(Val, Oid, write) of
+ C when record(C, cyclic) ->
+ flush_remaining(Tail, Node, {aborted, C});
+ Val2 ->
+ receive_wlocks(Tail, Val2, Store, Oid)
+ end;
+ {?MODULE, Node, {not_granted, Reason}} ->
+ del_debug(Node),
+ Reason1 = {aborted, Reason},
+ flush_remaining(Tail, Node, Reason1);
+ {mnesia_down, Node} ->
+ del_debug(Node),
+ Reason1 = {aborted, {node_not_running, Node}},
+ flush_remaining(Tail, Node, Reason1);
+ {?MODULE, Node, {switch, Node2, Req}} -> %% for rwlocks
+ del_debug(Node),
+ add_debug(Node2),
+ ?ets_insert(Store, {nodes, Node2}),
+ {?MODULE, Node2} ! Req,
+ receive_wlocks([Node2 | Tail], Res, Store, Oid)
+ end;
+
+receive_wlocks([], Res, _Store, _Oid) ->
+ Res.
+
+flush_remaining([], _SkipNode, Res) ->
+ exit(Res);
+flush_remaining([SkipNode | Tail ], SkipNode, Res) ->
+ del_debug(SkipNode),
+ flush_remaining(Tail, SkipNode, Res);
+flush_remaining([Node | Tail], SkipNode, Res) ->
+ receive
+ {?MODULE, Node, _} ->
+ del_debug(Node),
+ flush_remaining(Tail, SkipNode, Res);
+ {mnesia_down, Node} ->
+ del_debug(Node),
+ flush_remaining(Tail, SkipNode, {aborted, {node_not_running, Node}})
+ end.
+
+opt_lookup_in_client(lookup_in_client, Oid, Lock) ->
+ {Tab, Key} = Oid,
+ case catch mnesia_lib:db_get(Tab, Key) of
+ {'EXIT', _} ->
+ %% Table has been deleted from this node,
+ %% restart the transaction.
+ #cyclic{op = read, lock = Lock, oid = Oid, lucky = nowhere};
+ Val ->
+ Val
+ end;
+opt_lookup_in_client(Val, _Oid, _Lock) ->
+ Val.
+
+return_granted_or_nodes({_, ?ALL} , Nodes) -> Nodes;
+return_granted_or_nodes({?GLOBAL, _}, Nodes) -> Nodes;
+return_granted_or_nodes(_ , _Nodes) -> granted.
+
+%% We store a {Tab, read, From} item in the
+%% locks table on the node where we actually do pick up the object
+%% and we also store an item {lock, Oid, read} in our local store
+%% so that we can release any locks we hold when we commit.
+%% This function not only aquires a read lock, but also reads the object
+
+%% Oid's are always {Tab, Key} tuples
+rlock(Tid, Store, Oid) ->
+ {Tab, Key} = Oid,
+ case val({Tab, where_to_read}) of
+ nowhere ->
+ mnesia:abort({no_exists, Tab});
+ Node ->
+ case need_lock(Store, Tab, Key, '_') of
+ yes ->
+ R = l_request(Node, {read, Tid, Oid}, Store),
+ rlock_get_reply(Node, Store, Oid, R);
+ no ->
+ if
+ Key == ?ALL ->
+ [Node];
+ Tab == ?GLOBAL ->
+ [Node];
+ true ->
+ dirty_rpc(Node, Tab, Key, read)
+ end
+ end
+ end.
+
+dirty_rpc(nowhere, Tab, Key, _Lock) ->
+ mnesia:abort({no_exists, {Tab, Key}});
+dirty_rpc(Node, _Tab, ?ALL, _Lock) ->
+ [Node];
+dirty_rpc(Node, ?GLOBAL, _Key, _Lock) ->
+ [Node];
+dirty_rpc(Node, Tab, Key, Lock) ->
+ Args = [Tab, Key],
+ case rpc:call(Node, mnesia_lib, db_get, Args) of
+ {badrpc, Reason} ->
+ case val({Tab, where_to_read}) of
+ Node ->
+ ErrorTag = mnesia_lib:dirty_rpc_error_tag(Reason),
+ mnesia:abort({ErrorTag, Args});
+ _NewNode ->
+ %% Table has been deleted from the node,
+ %% restart the transaction.
+ C = #cyclic{op = read, lock = Lock, oid = {Tab, Key}, lucky = nowhere},
+ exit({aborted, C})
+ end;
+ Other ->
+ Other
+ end.
+
+rlock_get_reply(Node, Store, Oid, {granted, V}) ->
+ {Tab, Key} = Oid,
+ ?ets_insert(Store, {{locks, Tab, Key}, read}),
+ ?ets_insert(Store, {nodes, Node}),
+ case opt_lookup_in_client(V, Oid, read) of
+ C when record(C, cyclic) ->
+ mnesia:abort(C);
+ Val ->
+ Val
+ end;
+rlock_get_reply(Node, Store, Oid, granted) ->
+ {Tab, Key} = Oid,
+ ?ets_insert(Store, {{locks, Tab, Key}, read}),
+ ?ets_insert(Store, {nodes, Node}),
+ return_granted_or_nodes(Oid, [Node]);
+rlock_get_reply(Node, Store, Tab, {granted, V, RealKeys}) ->
+ L = fun(K) -> ?ets_insert(Store, {{locks, Tab, K}, read}) end,
+ lists:foreach(L, RealKeys),
+ ?ets_insert(Store, {nodes, Node}),
+ V;
+rlock_get_reply(_Node, _Store, _Oid, {not_granted , Reason}) ->
+ exit({aborted, Reason});
+
+rlock_get_reply(_Node, Store, Oid, {switch, N2, Req}) ->
+ ?ets_insert(Store, {nodes, N2}),
+ {?MODULE, N2} ! Req,
+ rlock_get_reply(N2, Store, Oid, l_req_rec(N2, Store)).
+
+
+rlock_table(Tid, Store, Tab) ->
+ rlock(Tid, Store, {Tab, ?ALL}).
+
+ixrlock(Tid, Store, Tab, IxKey, Pos) ->
+ case val({Tab, where_to_read}) of
+ nowhere ->
+ mnesia:abort({no_exists, Tab});
+ Node ->
+ R = l_request(Node, {ix_read, Tid, Tab, IxKey, Pos}, Store),
+ rlock_get_reply(Node, Store, Tab, R)
+ end.
+
+%% Grabs the locks or exits
+global_lock(Tid, Store, Item, write, Ns) ->
+ Oid = {?GLOBAL, Item},
+ Op = {self(), {write, Tid, Oid}},
+ get_wlocks_on_nodes(Ns, Ns, Store, Op, Oid);
+global_lock(Tid, Store, Item, read, Ns) ->
+ Oid = {?GLOBAL, Item},
+ send_requests(Ns, {read, Tid, Oid}),
+ rec_requests(Ns, Oid, Store),
+ Ns.
+
+send_requests([Node | Nodes], X) ->
+ {?MODULE, Node} ! {self(), X},
+ send_requests(Nodes, X);
+send_requests([], _X) ->
+ ok.
+
+rec_requests([Node | Nodes], Oid, Store) ->
+ Res = l_req_rec(Node, Store),
+ case catch rlock_get_reply(Node, Store, Oid, Res) of
+ {'EXIT', Reason} ->
+ flush_remaining(Nodes, Node, Reason);
+ _ ->
+ rec_requests(Nodes, Oid, Store)
+ end;
+rec_requests([], _Oid, _Store) ->
+ ok.
+
+get_held_locks() ->
+ ?ets_match_object(mnesia_held_locks, '_').
+
+get_lock_queue() ->
+ Q = ?ets_match_object(mnesia_lock_queue, '_'),
+ [{Oid, Op, Pid, Tid, WFT} || {queue, Oid, Tid, Op, Pid, WFT} <- Q].
+
+do_stop() ->
+ exit(shutdown).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% System upgrade
+
+system_continue(_Parent, _Debug, State) ->
+ loop(State).
+
+system_terminate(_Reason, _Parent, _Debug, _State) ->
+ do_stop().
+
+system_code_change(State, _Module, _OldVsn, _Extra) ->
+ {ok, State}.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_log.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_log.erl
new file mode 100644
index 0000000000..47e8be32c0
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_log.erl
@@ -0,0 +1,1019 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_log.erl,v 1.2 2009/07/01 15:45:40 kostis Exp $
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% This module administers three kinds of log files:
+%%
+%% 1 The transaction log
+%% mnesia_tm appends to the log (via mnesia_log) at the
+%% end of each transaction (or dirty write) and
+%% mnesia_dumper reads the log and performs the ops in
+%% the dat files. The dump_log is done at startup and
+%% at intervals controlled by the user.
+%%
+%% 2 The mnesia_down log
+%% mnesia_tm appends to the log (via mnesia_log) when it
+%% realizes that mnesia goes up or down on another node.
+%% mnesia_init reads the log (via mnesia_log) at startup.
+%%
+%% 3 The backup log
+%% mnesia_schema produces one tiny log when the schema is
+%% initially created. mnesia_schema also reads the log
+%% when the user wants tables (possibly incl the schema)
+%% to be restored. mnesia_log appends to the log when the
+%% user wants to produce a real backup.
+%%
+%% The actual access to the backup media is performed via the
+%% mnesia_backup module for both read and write. mnesia_backup
+%% uses the disk_log (*), BUT the user may write an own module
+%% with the same interface as mnesia_backup and configure
+%% Mnesia so the alternate module performs the actual accesses
+%% to the backup media. This means that the user may put the
+%% backup on medias that Mnesia does not know about possibly on
+%% hosts where Erlang is not running.
+%%
+%% All these logs have to some extent a common structure.
+%% They are all using the disk_log module (*) for the basic
+%% file structure. The disk_log has a repair feature that
+%% can be used to skip erroneous log records if one comes to
+%% the conclusion that it is more important to reuse some
+%% of the log records than the risque of obtaining inconsistent
+%% data. If the data becomes inconsistent it is solely up to the
+%% application to make it consistent again. The automatic
+%% reparation of the disk_log is very powerful, but use it
+%% with extreme care.
+%%
+%% First in all Mnesia's log file is a mnesia log header.
+%% It contains a list with a log_header record as single
+%% element. The structure of the log_header may never be
+%% changed since it may be written to very old backup files.
+%% By holding this record definition stable we can be
+%% able to comprahend backups from timepoint 0. It also
+%% allows us to use the backup format as an interchange
+%% format between Mnesia releases.
+%%
+%% An op-list is a list of tuples with arity 3. Each tuple
+%% has this structure: {Oid, Recs, Op} where Oid is the tuple
+%% {Tab, Key}, Recs is a (possibly empty) list of records and
+%% Op is an atom.
+%%
+%% The log file structure for the transaction log is as follows.
+%%
+%% After the mnesia log section follows an extended record section
+%% containing op-lists. There are several values that Op may
+%% have, such as write, delete, update_counter, delete_object,
+%% and replace. There is no special end of section marker.
+%%
+%% +-----------------+
+%% | mnesia log head |
+%% +-----------------+
+%% | extended record |
+%% | section |
+%% +-----------------+
+%%
+%% The log file structure for the mnesia_down log is as follows.
+%%
+%% After the mnesia log section follows a mnesia_down section
+%% containg lists with yoyo records as single element.
+%%
+%% +-----------------+
+%% | mnesia log head |
+%% +-----------------+
+%% | mnesia_down |
+%% | section |
+%% +-----------------+
+%%
+%% The log file structure for the backup log is as follows.
+%%
+%% After the mnesia log section follows a schema section
+%% containing record lists. A record list is a list of tuples
+%% where {schema, Tab} is interpreted as a delete_table(Tab) and
+%% {schema, Tab, CreateList} are interpreted as create_table.
+%%
+%% The record section also contains record lists. In this section
+%% {Tab, Key} is interpreted as delete({Tab, Key}) and other tuples
+%% as write(Tuple). There is no special end of section marker.
+%%
+%% +-----------------+
+%% | mnesia log head |
+%% +-----------------+
+%% | schema section |
+%% +-----------------+
+%% | record section |
+%% +-----------------+
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-module(mnesia_log).
+
+-export([
+ append/2,
+ backup/1,
+ backup/2,
+ backup_checkpoint/2,
+ backup_checkpoint/3,
+ backup_log_header/0,
+ backup_master/2,
+ chunk_decision_log/1,
+ chunk_decision_tab/1,
+ chunk_log/1,
+ chunk_log/2,
+ close_decision_log/0,
+ close_decision_tab/0,
+ close_log/1,
+ unsafe_close_log/1,
+ confirm_log_dump/1,
+ confirm_decision_log_dump/0,
+ previous_log_file/0,
+ previous_decision_log_file/0,
+ latest_log_file/0,
+ decision_log_version/0,
+ decision_log_file/0,
+ decision_tab_file/0,
+ decision_tab_version/0,
+ dcl_version/0,
+ dcd_version/0,
+ ets2dcd/1,
+ ets2dcd/2,
+ dcd2ets/1,
+ dcd2ets/2,
+ init/0,
+ init_log_dump/0,
+ log/1,
+ slog/1,
+ log_decision/1,
+ log_files/0,
+ open_decision_log/0,
+ trans_log_header/0,
+ open_decision_tab/0,
+ dcl_log_header/0,
+ dcd_log_header/0,
+ open_log/4,
+ open_log/6,
+ prepare_decision_log_dump/0,
+ prepare_log_dump/1,
+ save_decision_tab/1,
+ purge_all_logs/0,
+ purge_some_logs/0,
+ stop/0,
+ tab_copier/3,
+ version/0,
+ view/0,
+ view/1,
+ write_trans_log_header/0
+ ]).
+
+
+-include("mnesia.hrl").
+-import(mnesia_lib, [val/1, dir/1]).
+-import(mnesia_lib, [exists/1, fatal/2, error/2, dbg_out/2]).
+
+trans_log_header() -> log_header(trans_log, version()).
+backup_log_header() -> log_header(backup_log, "1.2").
+decision_log_header() -> log_header(decision_log, decision_log_version()).
+decision_tab_header() -> log_header(decision_tab, decision_tab_version()).
+dcl_log_header() -> log_header(dcl_log, dcl_version()).
+dcd_log_header() -> log_header(dcd_log, dcd_version()).
+
+log_header(Kind, Version) ->
+ #log_header{log_version=Version,
+ log_kind=Kind,
+ mnesia_version=mnesia:system_info(version),
+ node=node(),
+ now=now()}.
+
+version() -> "4.3".
+
+decision_log_version() -> "3.0".
+
+decision_tab_version() -> "1.0".
+
+dcl_version() -> "1.0".
+dcd_version() -> "1.0".
+
+append(Log, Bin) when binary(Bin) ->
+ disk_log:balog(Log, Bin);
+append(Log, Term) ->
+ disk_log:alog(Log, Term).
+
+%% Synced append
+sappend(Log, Bin) when binary(Bin) ->
+ ok = disk_log:blog(Log, Bin);
+sappend(Log, Term) ->
+ ok = disk_log:log(Log, Term).
+
+%% Write commit records to the latest_log
+log(C) when C#commit.disc_copies == [],
+ C#commit.disc_only_copies == [],
+ C#commit.schema_ops == [] ->
+ ignore;
+log(C) ->
+ case mnesia_monitor:use_dir() of
+ true ->
+ if
+ record(C, commit) ->
+ C2 = C#commit{ram_copies = [], snmp = []},
+ append(latest_log, C2);
+ true ->
+ %% Either a commit record as binary
+ %% or some decision related info
+ append(latest_log, C)
+ end,
+ mnesia_dumper:incr_log_writes();
+ false ->
+ ignore
+ end.
+
+%% Synced
+
+slog(C) when C#commit.disc_copies == [],
+ C#commit.disc_only_copies == [],
+ C#commit.schema_ops == [] ->
+ ignore;
+slog(C) ->
+ case mnesia_monitor:use_dir() of
+ true ->
+ if
+ record(C, commit) ->
+ C2 = C#commit{ram_copies = [], snmp = []},
+ sappend(latest_log, C2);
+ true ->
+ %% Either a commit record as binary
+ %% or some decision related info
+ sappend(latest_log, C)
+ end,
+ mnesia_dumper:incr_log_writes();
+ false ->
+ ignore
+ end.
+
+
+%% Stuff related to the file LOG
+
+%% Returns a list of logfiles. The oldest is first.
+log_files() -> [previous_log_file(),
+ latest_log_file(),
+ decision_tab_file()
+ ].
+
+latest_log_file() -> dir(latest_log_name()).
+
+previous_log_file() -> dir("PREVIOUS.LOG").
+
+decision_log_file() -> dir(decision_log_name()).
+
+decision_tab_file() -> dir(decision_tab_name()).
+
+previous_decision_log_file() -> dir("PDECISION.LOG").
+
+latest_log_name() -> "LATEST.LOG".
+
+decision_log_name() -> "DECISION.LOG".
+
+decision_tab_name() -> "DECISION_TAB.LOG".
+
+init() ->
+ case mnesia_monitor:use_dir() of
+ true ->
+ Prev = previous_log_file(),
+ verify_no_exists(Prev),
+
+ Latest = latest_log_file(),
+ verify_no_exists(Latest),
+
+ Header = trans_log_header(),
+ open_log(latest_log, Header, Latest);
+ false ->
+ ok
+ end.
+
+verify_no_exists(Fname) ->
+ case exists(Fname) of
+ false ->
+ ok;
+ true ->
+ fatal("Log file exists: ~p~n", [Fname])
+ end.
+
+open_log(Name, Header, Fname) ->
+ Exists = exists(Fname),
+ open_log(Name, Header, Fname, Exists).
+
+open_log(Name, Header, Fname, Exists) ->
+ Repair = mnesia_monitor:get_env(auto_repair),
+ open_log(Name, Header, Fname, Exists, Repair).
+
+open_log(Name, Header, Fname, Exists, Repair) ->
+ case Name == previous_log of
+ true ->
+ open_log(Name, Header, Fname, Exists, Repair, read_only);
+ false ->
+ open_log(Name, Header, Fname, Exists, Repair, read_write)
+ end.
+
+open_log(Name, Header, Fname, Exists, Repair, Mode) ->
+ Args = [{file, Fname}, {name, Name}, {repair, Repair}, {mode, Mode}],
+%% io:format("~p:open_log: ~p ~p~n", [?MODULE, Name, Fname]),
+ case mnesia_monitor:open_log(Args) of
+ {ok, Log} when Exists == true ->
+ Log;
+ {ok, Log} ->
+ write_header(Log, Header),
+ Log;
+ {repaired, Log, _, {badbytes, 0}} when Exists == true ->
+ Log;
+ {repaired, Log, _, {badbytes, 0}} ->
+ write_header(Log, Header),
+ Log;
+ {repaired, Log, _Recover, BadBytes} ->
+ mnesia_lib:important("Data may be missing, log ~p repaired: Lost ~p bytes~n",
+ [Fname, BadBytes]),
+ Log;
+ {error, Reason} when Repair == true ->
+ file:delete(Fname),
+ mnesia_lib:important("Data may be missing, Corrupt logfile deleted: ~p, ~p ~n",
+ [Fname, Reason]),
+ %% Create a new
+ open_log(Name, Header, Fname, false, false, read_write);
+ {error, Reason} ->
+ fatal("Cannot open log file ~p: ~p~n", [Fname, Reason])
+ end.
+
+write_header(Log, Header) ->
+ append(Log, Header).
+
+write_trans_log_header() ->
+ write_header(latest_log, trans_log_header()).
+
+stop() ->
+ case mnesia_monitor:use_dir() of
+ true ->
+ close_log(latest_log);
+ false ->
+ ok
+ end.
+
+close_log(Log) ->
+%% io:format("mnesia_log:close_log ~p~n", [Log]),
+%% io:format("mnesia_log:close_log ~p~n", [Log]),
+ case disk_log:sync(Log) of
+ ok -> ok;
+ {error, {read_only_mode, Log}} ->
+ ok;
+ {error, Reason} ->
+ mnesia_lib:important("Failed syncing ~p to_disk reason ~p ~n",
+ [Log, Reason])
+ end,
+ mnesia_monitor:close_log(Log).
+
+unsafe_close_log(Log) ->
+%% io:format("mnesia_log:close_log ~p~n", [Log]),
+ mnesia_monitor:unsafe_close_log(Log).
+
+
+purge_some_logs() ->
+ mnesia_monitor:unsafe_close_log(latest_log),
+ file:delete(latest_log_file()),
+ file:delete(decision_tab_file()).
+
+purge_all_logs() ->
+ file:delete(previous_log_file()),
+ file:delete(latest_log_file()),
+ file:delete(decision_tab_file()).
+
+%% Prepare dump by renaming the open logfile if possible
+%% Returns a tuple on the following format: {Res, OpenLog}
+%% where OpenLog is the file descriptor to log file, ready for append
+%% and Res is one of the following: already_dumped, needs_dump or {error, Reason}
+prepare_log_dump(InitBy) ->
+ Diff = mnesia_dumper:get_log_writes() -
+ mnesia_lib:read_counter(trans_log_writes_prev),
+ if
+ Diff == 0, InitBy /= startup ->
+ already_dumped;
+ true ->
+ case mnesia_monitor:use_dir() of
+ true ->
+ Prev = previous_log_file(),
+ prepare_prev(Diff, InitBy, Prev, exists(Prev));
+ false ->
+ already_dumped
+ end
+ end.
+
+prepare_prev(Diff, _, _, true) ->
+ {needs_dump, Diff};
+prepare_prev(Diff, startup, Prev, false) ->
+ Latest = latest_log_file(),
+ case exists(Latest) of
+ true ->
+ case file:rename(Latest, Prev) of
+ ok ->
+ {needs_dump, Diff};
+ {error, Reason} ->
+ {error, Reason}
+ end;
+ false ->
+ already_dumped
+ end;
+prepare_prev(Diff, _InitBy, Prev, false) ->
+ Head = trans_log_header(),
+ case mnesia_monitor:reopen_log(latest_log, Prev, Head) of
+ ok ->
+ {needs_dump, Diff};
+ {error, Reason} ->
+ Latest = latest_log_file(),
+ {error, {"Cannot rename log file",
+ [Latest, Prev, Reason]}}
+ end.
+
+%% Init dump and return PrevLogFileDesc or exit.
+init_log_dump() ->
+ Fname = previous_log_file(),
+ open_log(previous_log, trans_log_header(), Fname),
+ start.
+
+
+chunk_log(Cont) ->
+ chunk_log(previous_log, Cont).
+
+chunk_log(_Log, eof) ->
+ eof;
+chunk_log(Log, Cont) ->
+ case catch disk_log:chunk(Log, Cont) of
+ {error, Reason} ->
+ fatal("Possibly truncated ~p file: ~p~n",
+ [Log, Reason]);
+ {C2, Chunk, _BadBytes} ->
+ %% Read_only case, should we warn about the bad log file?
+ %% BUGBUG Should we crash if Repair == false ??
+ %% We got to check this !!
+ mnesia_lib:important("~p repaired, lost ~p bad bytes~n", [Log, _BadBytes]),
+ {C2, Chunk};
+ Other ->
+ Other
+ end.
+
+%% Confirms the dump by closing prev log and delete the file
+confirm_log_dump(Updates) ->
+ case mnesia_monitor:close_log(previous_log) of
+ ok ->
+ file:delete(previous_log_file()),
+ mnesia_lib:incr_counter(trans_log_writes_prev, Updates),
+ dumped;
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Decision log
+
+open_decision_log() ->
+ Latest = decision_log_file(),
+ open_log(decision_log, decision_log_header(), Latest),
+ start.
+
+prepare_decision_log_dump() ->
+ Prev = previous_decision_log_file(),
+ prepare_decision_log_dump(exists(Prev), Prev).
+
+prepare_decision_log_dump(false, Prev) ->
+ Head = decision_log_header(),
+ case mnesia_monitor:reopen_log(decision_log, Prev, Head) of
+ ok ->
+ prepare_decision_log_dump(true, Prev);
+ {error, Reason} ->
+ fatal("Cannot rename decision log file ~p -> ~p: ~p~n",
+ [decision_log_file(), Prev, Reason])
+ end;
+prepare_decision_log_dump(true, Prev) ->
+ open_log(previous_decision_log, decision_log_header(), Prev),
+ start.
+
+chunk_decision_log(Cont) ->
+ %% dbg_out("chunk log ~p~n", [Cont]),
+ chunk_log(previous_decision_log, Cont).
+
+%% Confirms dump of the decision log
+confirm_decision_log_dump() ->
+ case mnesia_monitor:close_log(previous_decision_log) of
+ ok ->
+ file:delete(previous_decision_log_file());
+ {error, Reason} ->
+ fatal("Cannot confirm decision log dump: ~p~n",
+ [Reason])
+ end.
+
+save_decision_tab(Decisions) ->
+ Log = decision_tab,
+ Tmp = mnesia_lib:dir("DECISION_TAB.TMP"),
+ file:delete(Tmp),
+ open_log(Log, decision_tab_header(), Tmp),
+ append(Log, Decisions),
+ close_log(Log),
+ TabFile = decision_tab_file(),
+ ok = file:rename(Tmp, TabFile).
+
+open_decision_tab() ->
+ TabFile = decision_tab_file(),
+ open_log(decision_tab, decision_tab_header(), TabFile),
+ start.
+
+close_decision_tab() ->
+ close_log(decision_tab).
+
+chunk_decision_tab(Cont) ->
+ %% dbg_out("chunk tab ~p~n", [Cont]),
+ chunk_log(decision_tab, Cont).
+
+close_decision_log() ->
+ close_log(decision_log).
+
+log_decision(Decision) ->
+ append(decision_log, Decision).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Debug functions
+
+view() ->
+ lists:foreach(fun(F) -> view(F) end, log_files()).
+
+view(File) ->
+ mnesia_lib:show("***** ~p ***** ~n", [File]),
+ case exists(File) of
+ false ->
+ nolog;
+ true ->
+ N = view_only,
+ Args = [{file, File}, {name, N}, {mode, read_only}],
+ case disk_log:open(Args) of
+ {ok, N} ->
+ view_file(start, N);
+ {repaired, _, _, _} ->
+ view_file(start, N);
+ {error, Reason} ->
+ error("Cannot open log ~p: ~p~n", [File, Reason])
+ end
+ end.
+
+view_file(C, Log) ->
+ case disk_log:chunk(Log, C) of
+ {error, Reason} ->
+ error("** Possibly truncated FILE ~p~n", [Reason]),
+ error;
+ eof ->
+ disk_log:close(Log),
+ eof;
+ {C2, Terms, _BadBytes} ->
+ dbg_out("Lost ~p bytes in ~p ~n", [_BadBytes, Log]),
+ lists:foreach(fun(X) -> mnesia_lib:show("~p~n", [X]) end,
+ Terms),
+ view_file(C2, Log);
+ {C2, Terms} ->
+ lists:foreach(fun(X) -> mnesia_lib:show("~p~n", [X]) end,
+ Terms),
+ view_file(C2, Log)
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Backup
+
+-record(backup_args, {name, module, opaque, scope, prev_name, tables, cookie}).
+
+backup(Opaque) ->
+ backup(Opaque, []).
+
+backup(Opaque, Mod) when atom(Mod) ->
+ backup(Opaque, [{module, Mod}]);
+backup(Opaque, Args) when list(Args) ->
+ %% Backup all tables with max redundancy
+ CpArgs = [{ram_overrides_dump, false}, {max, val({schema, tables})}],
+ case mnesia_checkpoint:activate(CpArgs) of
+ {ok, Name, _Nodes} ->
+ Res = backup_checkpoint(Name, Opaque, Args),
+ mnesia_checkpoint:deactivate(Name),
+ Res;
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+backup_checkpoint(Name, Opaque) ->
+ backup_checkpoint(Name, Opaque, []).
+
+backup_checkpoint(Name, Opaque, Mod) when atom(Mod) ->
+ backup_checkpoint(Name, Opaque, [{module, Mod}]);
+backup_checkpoint(Name, Opaque, Args) when list(Args) ->
+ DefaultMod = mnesia_monitor:get_env(backup_module),
+ B = #backup_args{name = Name,
+ module = DefaultMod,
+ opaque = Opaque,
+ scope = global,
+ tables = all,
+ prev_name = Name},
+ case check_backup_args(Args, B) of
+ {ok, B2} ->
+ %% Decentralized backup
+ %% Incremental
+
+ Self = self(),
+ Pid = spawn_link(?MODULE, backup_master, [Self, B2]),
+ receive
+ {Pid, Self, Res} -> Res
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+check_backup_args([Arg | Tail], B) ->
+ case catch check_backup_arg_type(Arg, B) of
+ {'EXIT', _Reason} ->
+ {error, {badarg, Arg}};
+ B2 ->
+ check_backup_args(Tail, B2)
+ end;
+
+check_backup_args([], B) ->
+ {ok, B}.
+
+check_backup_arg_type(Arg, B) ->
+ case Arg of
+ {scope, global} ->
+ B#backup_args{scope = global};
+ {scope, local} ->
+ B#backup_args{scope = local};
+ {module, Mod} ->
+ Mod2 = mnesia_monitor:do_check_type(backup_module, Mod),
+ B#backup_args{module = Mod2};
+ {incremental, Name} ->
+ B#backup_args{prev_name = Name};
+ {tables, Tabs} when list(Tabs) ->
+ B#backup_args{tables = Tabs}
+ end.
+
+backup_master(ClientPid, B) ->
+ process_flag(trap_exit, true),
+ case catch do_backup_master(B) of
+ {'EXIT', Reason} ->
+ ClientPid ! {self(), ClientPid, {error, {'EXIT', Reason}}};
+ Res ->
+ ClientPid ! {self(), ClientPid, Res}
+ end,
+ unlink(ClientPid),
+ exit(normal).
+
+do_backup_master(B) ->
+ Name = B#backup_args.name,
+ B2 = safe_apply(B, open_write, [B#backup_args.opaque]),
+ B3 = safe_write(B2, [backup_log_header()]),
+ case mnesia_checkpoint:tables_and_cookie(Name) of
+ {ok, AllTabs, Cookie} ->
+ Tabs = select_tables(AllTabs, B3),
+ B4 = B3#backup_args{cookie = Cookie},
+ %% Always put schema first in backup file
+ B5 = backup_schema(B4, Tabs),
+ B6 = lists:foldl(fun backup_tab/2, B5, Tabs -- [schema]),
+ safe_apply(B6, commit_write, [B6#backup_args.opaque]),
+ ok;
+ {error, Reason} ->
+ abort_write(B3, {?MODULE, backup_master}, [B], {error, Reason})
+ end.
+
+select_tables(AllTabs, B) ->
+ Tabs =
+ case B#backup_args.tables of
+ all -> AllTabs;
+ SomeTabs when list(SomeTabs) -> SomeTabs
+ end,
+ case B#backup_args.scope of
+ global ->
+ Tabs;
+ local ->
+ Name = B#backup_args.name,
+ [T || T <- Tabs, mnesia_checkpoint:most_local_node(Name, T) == node()]
+ end.
+
+safe_write(B, []) ->
+ B;
+safe_write(B, Recs) ->
+ safe_apply(B, write, [B#backup_args.opaque, Recs]).
+
+backup_schema(B, Tabs) ->
+ case lists:member(schema, Tabs) of
+ true ->
+ backup_tab(schema, B);
+ false ->
+ Defs = [{schema, T, mnesia_schema:get_create_list(T)} || T <- Tabs],
+ safe_write(B, Defs)
+ end.
+
+safe_apply(B, write, [_, Items]) when Items == [] ->
+ B;
+safe_apply(B, What, Args) ->
+ Abort = fun(R) -> abort_write(B, What, Args, R) end,
+ receive
+ {'EXIT', Pid, R} -> Abort({'EXIT', Pid, R})
+ after 0 ->
+ Mod = B#backup_args.module,
+ case catch apply(Mod, What, Args) of
+ {ok, Opaque} -> B#backup_args{opaque=Opaque};
+ {error, R} -> Abort(R);
+ R -> Abort(R)
+ end
+ end.
+
+abort_write(B, What, Args, Reason) ->
+ Mod = B#backup_args.module,
+ Opaque = B#backup_args.opaque,
+ dbg_out("Failed to perform backup. M=~p:F=~p:A=~p -> ~p~n",
+ [Mod, What, Args, Reason]),
+ case catch apply(Mod, abort_write, [Opaque]) of
+ {ok, _Res} ->
+ throw({error, Reason});
+ Other ->
+ error("Failed to abort backup. ~p:~p~p -> ~p~n",
+ [Mod, abort_write, [Opaque], Other]),
+ throw({error, Reason})
+ end.
+
+backup_tab(Tab, B) ->
+ Name = B#backup_args.name,
+ case mnesia_checkpoint:most_local_node(Name, Tab) of
+ {ok, Node} when Node == node() ->
+ tab_copier(self(), B, Tab);
+ {ok, Node} ->
+ RemoteB = B,
+ Pid = spawn_link(Node, ?MODULE, tab_copier, [self(), RemoteB, Tab]),
+ RecName = val({Tab, record_name}),
+ tab_receiver(Pid, B, Tab, RecName, 0);
+ {error, Reason} ->
+ abort_write(B, {?MODULE, backup_tab}, [Tab, B], {error, Reason})
+ end.
+
+tab_copier(Pid, B, Tab) when record(B, backup_args) ->
+ %% Intentional crash at exit
+ Name = B#backup_args.name,
+ PrevName = B#backup_args.prev_name,
+ {FirstName, FirstSource} = select_source(Tab, Name, PrevName),
+
+ ?eval_debug_fun({?MODULE, tab_copier, pre}, [{name, Name}, {tab, Tab}]),
+ Res = handle_more(Pid, B, Tab, FirstName, FirstSource, Name),
+ ?eval_debug_fun({?MODULE, tab_copier, post}, [{name, Name}, {tab, Tab}]),
+
+ handle_last(Pid, Res).
+
+select_source(Tab, Name, PrevName) ->
+ if
+ Tab == schema ->
+ %% Always full backup of schema
+ {Name, table};
+ Name == PrevName ->
+ %% Full backup
+ {Name, table};
+ true ->
+ %% Wants incremental backup
+ case mnesia_checkpoint:most_local_node(PrevName, Tab) of
+ {ok, Node} when Node == node() ->
+ %% Accept incremental backup
+ {PrevName, retainer};
+ _ ->
+ %% Do a full backup anyway
+ dbg_out("Incremental backup escalated to full backup: ~p~n", [Tab]),
+ {Name, table}
+ end
+ end.
+
+handle_more(Pid, B, Tab, FirstName, FirstSource, Name) ->
+ Acc = {0, B},
+ case {mnesia_checkpoint:really_retain(Name, Tab),
+ mnesia_checkpoint:really_retain(FirstName, Tab)} of
+ {true, true} ->
+ Acc2 = iterate(B, FirstName, Tab, Pid, FirstSource, latest, first, Acc),
+ iterate(B, Name, Tab, Pid, retainer, checkpoint, last, Acc2);
+ {false, false}->
+ %% Put the dumped file in the backup
+ %% instead of the ram table. Does
+ %% only apply to ram_copies.
+ iterate(B, Name, Tab, Pid, retainer, checkpoint, last, Acc);
+ Bad ->
+ Reason = {"Checkpoints for incremental backup must have same "
+ "setting of ram_overrides_dump",
+ Tab, Name, FirstName, Bad},
+ abort_write(B, {?MODULE, backup_tab}, [Tab, B], {error, Reason})
+ end.
+
+handle_last(Pid, {_Count, B}) when Pid == self() ->
+ B;
+handle_last(Pid, _Acc) ->
+ unlink(Pid),
+ Pid ! {self(), {last, {ok, dummy}}},
+ exit(normal).
+
+iterate(B, Name, Tab, Pid, Source, Age, Pass, Acc) ->
+ Fun =
+ if
+ Pid == self() ->
+ RecName = val({Tab, record_name}),
+ fun(Recs, A) -> copy_records(RecName, Tab, Recs, A) end;
+ true ->
+ fun(Recs, A) -> send_records(Pid, Tab, Recs, Pass, A) end
+ end,
+ case mnesia_checkpoint:iterate(Name, Tab, Fun, Acc, Source, Age) of
+ {ok, Acc2} ->
+ Acc2;
+ {error, Reason} ->
+ R = {error, {"Tab copier iteration failed", Reason}},
+ abort_write(B, {?MODULE, iterate}, [self(), B, Tab], R)
+ end.
+
+copy_records(_RecName, _Tab, [], Acc) ->
+ Acc;
+copy_records(RecName, Tab, Recs, {Count, B}) ->
+ Recs2 = rec_filter(B, Tab, RecName, Recs),
+ B2 = safe_write(B, Recs2),
+ {Count + 1, B2}.
+
+send_records(Pid, Tab, Recs, Pass, {Count, B}) ->
+ receive
+ {Pid, more, Count} ->
+ if
+ Pass == last, Recs == [] ->
+ {Count, B};
+ true ->
+ Next = Count + 1,
+ Pid ! {self(), {more, Next, Recs}},
+ {Next, B}
+ end;
+ Msg ->
+ exit({send_records_unexpected_msg, Tab, Msg})
+ end.
+
+tab_receiver(Pid, B, Tab, RecName, Slot) ->
+ Pid ! {self(), more, Slot},
+ receive
+ {Pid, {more, Next, Recs}} ->
+ Recs2 = rec_filter(B, Tab, RecName, Recs),
+ B2 = safe_write(B, Recs2),
+ tab_receiver(Pid, B2, Tab, RecName, Next);
+
+ {Pid, {last, {ok,_}}} ->
+ B;
+
+ {'EXIT', Pid, {error, R}} ->
+ Reason = {error, {"Tab copier crashed", R}},
+ abort_write(B, {?MODULE, remote_tab_sender}, [self(), B, Tab], Reason);
+ {'EXIT', Pid, R} ->
+ Reason = {error, {"Tab copier crashed", {'EXIT', R}}},
+ abort_write(B, {?MODULE, remote_tab_sender}, [self(), B, Tab], Reason);
+ Msg ->
+ R = {error, {"Tab receiver got unexpected msg", Msg}},
+ abort_write(B, {?MODULE, remote_tab_sender}, [self(), B, Tab], R)
+ end.
+
+rec_filter(B, schema, _RecName, Recs) ->
+ case catch mnesia_bup:refresh_cookie(Recs, B#backup_args.cookie) of
+ Recs2 when list(Recs2) ->
+ Recs2;
+ {error, _Reason} ->
+ %% No schema table cookie
+ Recs
+ end;
+rec_filter(_B, Tab, Tab, Recs) ->
+ Recs;
+rec_filter(_B, Tab, _RecName, Recs) ->
+ [setelement(1, Rec, Tab) || Rec <- Recs].
+
+ets2dcd(Tab) ->
+ ets2dcd(Tab, dcd).
+
+ets2dcd(Tab, Ftype) ->
+ Fname =
+ case Ftype of
+ dcd -> mnesia_lib:tab2dcd(Tab);
+ dmp -> mnesia_lib:tab2dmp(Tab)
+ end,
+ TmpF = mnesia_lib:tab2tmp(Tab),
+ file:delete(TmpF),
+ Log = open_log({Tab, ets2dcd}, dcd_log_header(), TmpF, false),
+ mnesia_lib:db_fixtable(ram_copies, Tab, true),
+ ok = ets2dcd(mnesia_lib:db_init_chunk(ram_copies, Tab, 1000), Tab, Log),
+ mnesia_lib:db_fixtable(ram_copies, Tab, false),
+ close_log(Log),
+ ok = file:rename(TmpF, Fname),
+ %% Remove old log data which is now in the new dcd.
+ %% No one else should be accessing this file!
+ file:delete(mnesia_lib:tab2dcl(Tab)),
+ ok.
+
+ets2dcd('$end_of_table', _Tab, _Log) ->
+ ok;
+ets2dcd({Recs, Cont}, Tab, Log) ->
+ ok = disk_log:alog_terms(Log, Recs),
+ ets2dcd(mnesia_lib:db_chunk(ram_copies, Cont), Tab, Log).
+
+dcd2ets(Tab) ->
+ dcd2ets(Tab, mnesia_monitor:get_env(auto_repair)).
+
+dcd2ets(Tab, Rep) ->
+ Dcd = mnesia_lib:tab2dcd(Tab),
+ case mnesia_lib:exists(Dcd) of
+ true ->
+ Log = open_log({Tab, dcd2ets}, dcd_log_header(), Dcd,
+ true, Rep, read_only),
+ Data = chunk_log(Log, start),
+ ok = insert_dcdchunk(Data, Log, Tab),
+ close_log(Log),
+ load_dcl(Tab, Rep);
+ false -> %% Handle old dets files, and conversion from disc_only to disc.
+ Fname = mnesia_lib:tab2dat(Tab),
+ Type = val({Tab, setorbag}),
+ case mnesia_lib:dets_to_ets(Tab, Tab, Fname, Type, Rep, yes) of
+ loaded ->
+ ets2dcd(Tab),
+ file:delete(Fname),
+ 0;
+ {error, Error} ->
+ erlang:error({"Failed to load table from disc", [Tab, Error]})
+ end
+ end.
+
+insert_dcdchunk({Cont, [LogH | Rest]}, Log, Tab)
+ when record(LogH, log_header),
+ LogH#log_header.log_kind == dcd_log,
+ LogH#log_header.log_version >= "1.0" ->
+ insert_dcdchunk({Cont, Rest}, Log, Tab);
+
+insert_dcdchunk({Cont, Recs}, Log, Tab) ->
+ true = ets:insert(Tab, Recs),
+ insert_dcdchunk(chunk_log(Log, Cont), Log, Tab);
+insert_dcdchunk(eof, _Log, _Tab) ->
+ ok.
+
+load_dcl(Tab, Rep) ->
+ FName = mnesia_lib:tab2dcl(Tab),
+ case mnesia_lib:exists(FName) of
+ true ->
+ Name = {load_dcl,Tab},
+ open_log(Name,
+ dcl_log_header(),
+ FName,
+ true,
+ Rep,
+ read_only),
+ FirstChunk = chunk_log(Name, start),
+ N = insert_logchunk(FirstChunk, Name, 0),
+ close_log(Name),
+ N;
+ false ->
+ 0
+ end.
+
+insert_logchunk({C2, Recs}, Tab, C) ->
+ N = add_recs(Recs, C),
+ insert_logchunk(chunk_log(Tab, C2), Tab, C+N);
+insert_logchunk(eof, _Tab, C) ->
+ C.
+
+add_recs([{{Tab, _Key}, Val, write} | Rest], N) ->
+ true = ets:insert(Tab, Val),
+ add_recs(Rest, N+1);
+add_recs([{{Tab, Key}, _Val, delete} | Rest], N) ->
+ true = ets:delete(Tab, Key),
+ add_recs(Rest, N+1);
+add_recs([{{Tab, _Key}, Val, delete_object} | Rest], N) ->
+ true = ets:match_delete(Tab, Val),
+ add_recs(Rest, N+1);
+add_recs([{{Tab, Key}, Val, update_counter} | Rest], N) ->
+ {RecName, Incr} = Val,
+ case catch ets:update_counter(Tab, Key, Incr) of
+ CounterVal when integer(CounterVal) ->
+ ok;
+ _ ->
+ Zero = {RecName, Key, 0},
+ true = ets:insert(Tab, Zero)
+ end,
+ add_recs(Rest, N+1);
+add_recs([LogH|Rest], N)
+ when record(LogH, log_header),
+ LogH#log_header.log_kind == dcl_log,
+ LogH#log_header.log_version >= "1.0" ->
+ add_recs(Rest, N);
+add_recs([{{Tab, _Key}, _Val, clear_table} | Rest], N) ->
+ true = ets:match_delete(Tab, '_'),
+ add_recs(Rest, N+ets:info(Tab, size));
+add_recs([], N) ->
+ N.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_monitor.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_monitor.erl
new file mode 100644
index 0000000000..b64419d5a8
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_monitor.erl
@@ -0,0 +1,776 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_monitor.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
+%%
+-module(mnesia_monitor).
+
+-behaviour(gen_server).
+
+%% Public exports
+-export([
+ close_dets/1,
+ close_log/1,
+ detect_inconcistency/2,
+ get_env/1,
+ init/0,
+ mktab/2,
+ unsafe_mktab/2,
+ mnesia_down/2,
+ needs_protocol_conversion/1,
+ negotiate_protocol/1,
+ disconnect/1,
+ open_dets/2,
+ unsafe_open_dets/2,
+ open_log/1,
+ patch_env/2,
+ protocol_version/0,
+ reopen_log/3,
+ set_env/2,
+ start/0,
+ start_proc/4,
+ terminate_proc/3,
+ unsafe_close_dets/1,
+ unsafe_close_log/1,
+ use_dir/0,
+ do_check_type/2
+ ]).
+
+%% gen_server callbacks
+-export([
+ init/1,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ terminate/2,
+ code_change/3
+ ]).
+
+%% Internal exports
+-export([
+ call/1,
+ cast/1,
+ detect_partitioned_network/2,
+ has_remote_mnesia_down/1
+ ]).
+
+-import(mnesia_lib, [dbg_out/2, verbose/2, error/2, fatal/2, set/2]).
+
+-include("mnesia.hrl").
+
+-record(state, {supervisor, pending_negotiators = [],
+ going_down = [], tm_started = false, early_connects = []}).
+
+-define(current_protocol_version, {7,6}).
+
+-define(previous_protocol_version, {7,5}).
+
+start() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE,
+ [self()], [{timeout, infinity}
+ %% ,{debug, [trace]}
+ ]).
+
+init() ->
+ call(init).
+
+mnesia_down(From, Node) ->
+ cast({mnesia_down, From, Node}).
+
+mktab(Tab, Args) ->
+ unsafe_call({mktab, Tab, Args}).
+unsafe_mktab(Tab, Args) ->
+ unsafe_call({unsafe_mktab, Tab, Args}).
+
+open_dets(Tab, Args) ->
+ unsafe_call({open_dets, Tab, Args}).
+unsafe_open_dets(Tab, Args) ->
+ unsafe_call({unsafe_open_dets, Tab, Args}).
+
+close_dets(Tab) ->
+ unsafe_call({close_dets, Tab}).
+
+unsafe_close_dets(Name) ->
+ unsafe_call({unsafe_close_dets, Name}).
+
+open_log(Args) ->
+ unsafe_call({open_log, Args}).
+
+reopen_log(Name, Fname, Head) ->
+ unsafe_call({reopen_log, Name, Fname, Head}).
+
+close_log(Name) ->
+ unsafe_call({close_log, Name}).
+
+unsafe_close_log(Name) ->
+ unsafe_call({unsafe_close_log, Name}).
+
+
+disconnect(Node) ->
+ cast({disconnect, Node}).
+
+%% Returns GoodNoodes
+%% Creates a link to each compatible monitor and
+%% protocol_version to agreed version upon success
+
+negotiate_protocol(Nodes) ->
+ Version = mnesia:system_info(version),
+ Protocols = acceptable_protocol_versions(),
+ MonitorPid = whereis(?MODULE),
+ Msg = {negotiate_protocol, MonitorPid, Version, Protocols},
+ {Replies, _BadNodes} = multicall(Nodes, Msg),
+ check_protocol(Replies, Protocols).
+
+check_protocol([{Node, {accept, Mon, _Version, Protocol}} | Tail], Protocols) ->
+ case lists:member(Protocol, Protocols) of
+ true ->
+ case Protocol == protocol_version() of
+ true ->
+ set({protocol, Node}, {Protocol, false});
+ false ->
+ set({protocol, Node}, {Protocol, true})
+ end,
+ [node(Mon) | check_protocol(Tail, Protocols)];
+ false ->
+ unlink(Mon), % Get rid of unneccessary link
+ check_protocol(Tail, Protocols)
+ end;
+check_protocol([{Node, {reject, _Mon, Version, Protocol}} | Tail], Protocols) ->
+ verbose("Failed to connect with ~p. ~p protocols rejected. "
+ "expected version = ~p, expected protocol = ~p~n",
+ [Node, Protocols, Version, Protocol]),
+ check_protocol(Tail, Protocols);
+check_protocol([{error, _Reason} | Tail], Protocols) ->
+ check_protocol(Tail, Protocols);
+check_protocol([{badrpc, _Reason} | Tail], Protocols) ->
+ check_protocol(Tail, Protocols);
+check_protocol([], [Protocol | _Protocols]) ->
+ set(protocol_version, Protocol),
+ [];
+check_protocol([], []) ->
+ set(protocol_version, protocol_version()),
+ [].
+
+protocol_version() ->
+ case ?catch_val(protocol_version) of
+ {'EXIT', _} -> ?current_protocol_version;
+ Version -> Version
+ end.
+
+%% A sorted list of acceptable protocols the
+%% preferred protocols are first in the list
+acceptable_protocol_versions() ->
+ [protocol_version(), ?previous_protocol_version].
+
+needs_protocol_conversion(Node) ->
+ case {?catch_val({protocol, Node}), protocol_version()} of
+ {{'EXIT', _}, _} ->
+ false;
+ {{_, Bool}, ?current_protocol_version} ->
+ Bool;
+ {{_, Bool}, _} ->
+ not Bool
+ end.
+
+cast(Msg) ->
+ case whereis(?MODULE) of
+ undefined -> ignore;
+ Pid -> gen_server:cast(Pid, Msg)
+ end.
+
+unsafe_call(Msg) ->
+ case whereis(?MODULE) of
+ undefined -> {error, {node_not_running, node()}};
+ Pid -> gen_server:call(Pid, Msg, infinity)
+ end.
+
+call(Msg) ->
+ case whereis(?MODULE) of
+ undefined ->
+ {error, {node_not_running, node()}};
+ Pid ->
+ link(Pid),
+ Res = gen_server:call(Pid, Msg, infinity),
+ unlink(Pid),
+
+ %% We get an exit signal if server dies
+ receive
+ {'EXIT', Pid, _Reason} ->
+ {error, {node_not_running, node()}}
+ after 0 ->
+ ignore
+ end,
+ Res
+ end.
+
+multicall(Nodes, Msg) ->
+ rpc:multicall(Nodes, ?MODULE, call, [Msg]).
+
+start_proc(Who, Mod, Fun, Args) ->
+ Args2 = [Who, Mod, Fun, Args],
+ proc_lib:start_link(mnesia_sp, init_proc, Args2, infinity).
+
+terminate_proc(Who, R, State) when R /= shutdown, R /= killed ->
+ fatal("~p crashed: ~p state: ~p~n", [Who, R, State]);
+
+terminate_proc(Who, Reason, _State) ->
+ mnesia_lib:verbose("~p terminated: ~p~n", [Who, Reason]),
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% Callback functions from gen_server
+
+%%----------------------------------------------------------------------
+%% Func: init/1
+%% Returns: {ok, State} |
+%% {ok, State, Timeout} |
+%% {stop, Reason}
+%%----------------------------------------------------------------------
+init([Parent]) ->
+ process_flag(trap_exit, true),
+ ?ets_new_table(mnesia_gvar, [set, public, named_table]),
+ set(subscribers, []),
+ mnesia_lib:verbose("~p starting: ~p~n", [?MODULE, self()]),
+ Version = mnesia:system_info(version),
+ set(version, Version),
+ dbg_out("Version: ~p~n", [Version]),
+
+ case catch process_config_args(env()) of
+ ok ->
+ mnesia_lib:set({'$$$_report', current_pos}, 0),
+ Level = mnesia_lib:val(debug),
+ mnesia_lib:verbose("Mnesia debug level set to ~p\n", [Level]),
+ set(mnesia_status, starting), %% set start status
+ set({current, db_nodes}, [node()]),
+ set(use_dir, use_dir()),
+ mnesia_lib:create_counter(trans_aborts),
+ mnesia_lib:create_counter(trans_commits),
+ mnesia_lib:create_counter(trans_log_writes),
+ Left = get_env(dump_log_write_threshold),
+ mnesia_lib:set_counter(trans_log_writes_left, Left),
+ mnesia_lib:create_counter(trans_log_writes_prev),
+ mnesia_lib:create_counter(trans_restarts),
+ mnesia_lib:create_counter(trans_failures),
+ ?ets_new_table(mnesia_held_locks, [bag, public, named_table]),
+ ?ets_new_table(mnesia_tid_locks, [bag, public, named_table]),
+ ?ets_new_table(mnesia_sticky_locks, [set, public, named_table]),
+ ?ets_new_table(mnesia_lock_queue,
+ [bag, public, named_table, {keypos, 2}]),
+ ?ets_new_table(mnesia_lock_counter, [set, public, named_table]),
+ set(checkpoints, []),
+ set(pending_checkpoints, []),
+ set(pending_checkpoint_pids, []),
+
+ {ok, #state{supervisor = Parent}};
+ {'EXIT', Reason} ->
+ mnesia_lib:report_fatal("Bad configuration: ~p~n", [Reason]),
+ {stop, {bad_config, Reason}}
+ end.
+
+use_dir() ->
+ case ?catch_val(use_dir) of
+ {'EXIT', _} ->
+ case get_env(schema_location) of
+ disc -> true;
+ opt_disc -> non_empty_dir();
+ ram -> false
+ end;
+ Bool ->
+ Bool
+ end.
+
+%% Returns true if the Mnesia directory contains
+%% important files
+non_empty_dir() ->
+ mnesia_lib:exists(mnesia_bup:fallback_bup()) or
+ mnesia_lib:exists(mnesia_lib:tab2dmp(schema)) or
+ mnesia_lib:exists(mnesia_lib:tab2dat(schema)).
+
+%%----------------------------------------------------------------------
+%% Func: handle_call/3
+%% Returns: {reply, Reply, State} |
+%% {reply, Reply, State, Timeout} |
+%% {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, Reply, State} | (terminate/2 is called)
+%%----------------------------------------------------------------------
+
+handle_call({mktab, Tab, Args}, _From, State) ->
+ case catch ?ets_new_table(Tab, Args) of
+ {'EXIT', ExitReason} ->
+ Msg = "Cannot create ets table",
+ Reason = {system_limit, Msg, Tab, Args, ExitReason},
+ fatal("~p~n", [Reason]),
+ {noreply, State};
+ Reply ->
+ {reply, Reply, State}
+ end;
+
+handle_call({unsafe_mktab, Tab, Args}, _From, State) ->
+ case catch ?ets_new_table(Tab, Args) of
+ {'EXIT', ExitReason} ->
+ {reply, {error, ExitReason}, State};
+ Reply ->
+ {reply, Reply, State}
+ end;
+
+
+handle_call({open_dets, Tab, Args}, _From, State) ->
+ case mnesia_lib:dets_sync_open(Tab, Args) of
+ {ok, Tab} ->
+ {reply, {ok, Tab}, State};
+
+ {error, Reason} ->
+ Msg = "Cannot open dets table",
+ Error = {error, {Msg, Tab, Args, Reason}},
+ fatal("~p~n", [Error]),
+ {noreply, State}
+ end;
+
+handle_call({unsafe_open_dets, Tab, Args}, _From, State) ->
+ case mnesia_lib:dets_sync_open(Tab, Args) of
+ {ok, Tab} ->
+ {reply, {ok, Tab}, State};
+ {error, Reason} ->
+ {reply, {error,Reason}, State}
+ end;
+
+handle_call({close_dets, Tab}, _From, State) ->
+ case mnesia_lib:dets_sync_close(Tab) of
+ ok ->
+ {reply, ok, State};
+ {error, Reason} ->
+ Msg = "Cannot close dets table",
+ Error = {error, {Msg, Tab, Reason}},
+ fatal("~p~n", [Error]),
+ {noreply, State}
+ end;
+
+handle_call({unsafe_close_dets, Tab}, _From, State) ->
+ mnesia_lib:dets_sync_close(Tab),
+ {reply, ok, State};
+
+handle_call({open_log, Args}, _From, State) ->
+ Res = disk_log:open([{notify, true}|Args]),
+ {reply, Res, State};
+
+handle_call({reopen_log, Name, Fname, Head}, _From, State) ->
+ case disk_log:reopen(Name, Fname, Head) of
+ ok ->
+ {reply, ok, State};
+
+ {error, Reason} ->
+ Msg = "Cannot rename disk_log file",
+ Error = {error, {Msg, Name, Fname, Head, Reason}},
+ fatal("~p~n", [Error]),
+ {noreply, State}
+ end;
+
+handle_call({close_log, Name}, _From, State) ->
+ case disk_log:close(Name) of
+ ok ->
+ {reply, ok, State};
+
+ {error, Reason} ->
+ Msg = "Cannot close disk_log file",
+ Error = {error, {Msg, Name, Reason}},
+ fatal("~p~n", [Error]),
+ {noreply, State}
+ end;
+
+handle_call({unsafe_close_log, Name}, _From, State) ->
+ disk_log:close(Name),
+ {reply, ok, State};
+
+handle_call({negotiate_protocol, Mon, _Version, _Protocols}, _From, State)
+ when State#state.tm_started == false ->
+ State2 = State#state{early_connects = [node(Mon) | State#state.early_connects]},
+ {reply, {node(), {reject, self(), uninitialized, uninitialized}}, State2};
+
+handle_call({negotiate_protocol, Mon, Version, Protocols}, From, State)
+ when node(Mon) /= node() ->
+ Protocol = protocol_version(),
+ MyVersion = mnesia:system_info(version),
+ case lists:member(Protocol, Protocols) of
+ true ->
+ accept_protocol(Mon, MyVersion, Protocol, From, State);
+ false ->
+ %% in this release we should be able to handle the previous
+ %% protocol
+ case hd(Protocols) of
+ ?previous_protocol_version ->
+ accept_protocol(Mon, MyVersion, ?previous_protocol_version, From, State);
+ _ ->
+ verbose("Connection with ~p rejected. "
+ "version = ~p, protocols = ~p, "
+ "expected version = ~p, expected protocol = ~p~n",
+ [node(Mon), Version, Protocols, MyVersion, Protocol]),
+ {reply, {node(), {reject, self(), MyVersion, Protocol}}, State}
+ end
+ end;
+
+handle_call(init, _From, State) ->
+ net_kernel:monitor_nodes(true),
+ EarlyNodes = State#state.early_connects,
+ State2 = State#state{tm_started = true},
+ {reply, EarlyNodes, State2};
+
+handle_call(Msg, _From, State) ->
+ error("~p got unexpected call: ~p~n", [?MODULE, Msg]),
+ {noreply, State}.
+
+accept_protocol(Mon, Version, Protocol, From, State) ->
+ Reply = {node(), {accept, self(), Version, Protocol}},
+ Node = node(Mon),
+ Pending0 = State#state.pending_negotiators,
+ Pending = lists:keydelete(Node, 1, Pending0),
+ case lists:member(Node, State#state.going_down) of
+ true ->
+ %% Wait for the mnesia_down to be processed,
+ %% before we reply
+ P = Pending ++ [{Node, Mon, From, Reply}],
+ {noreply, State#state{pending_negotiators = P}};
+ false ->
+ %% No need for wait
+ link(Mon), %% link to remote Monitor
+ case Protocol == protocol_version() of
+ true ->
+ set({protocol, Node}, {Protocol, false});
+ false ->
+ set({protocol, Node}, {Protocol, true})
+ end,
+ {reply, Reply, State#state{pending_negotiators = Pending}}
+ end.
+
+%%----------------------------------------------------------------------
+%% Func: handle_cast/2
+%% Returns: {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State} (terminate/2 is called)
+%%----------------------------------------------------------------------
+
+handle_cast({mnesia_down, mnesia_controller, Node}, State) ->
+ mnesia_tm:mnesia_down(Node),
+ {noreply, State};
+
+handle_cast({mnesia_down, mnesia_tm, {Node, Pending}}, State) ->
+ mnesia_locker:mnesia_down(Node, Pending),
+ {noreply, State};
+
+handle_cast({mnesia_down, mnesia_locker, Node}, State) ->
+ Down = {mnesia_down, Node},
+ mnesia_lib:report_system_event(Down),
+ GoingDown = lists:delete(Node, State#state.going_down),
+ State2 = State#state{going_down = GoingDown},
+ Pending = State#state.pending_negotiators,
+ case lists:keysearch(Node, 1, Pending) of
+ {value, {Node, Mon, ReplyTo, Reply}} ->
+ %% Late reply to remote monitor
+ link(Mon), %% link to remote Monitor
+ gen_server:reply(ReplyTo, Reply),
+ P2 = lists:keydelete(Node, 1,Pending),
+ State3 = State2#state{pending_negotiators = P2},
+ {noreply, State3};
+ false ->
+ %% No pending remote monitors
+ {noreply, State2}
+ end;
+
+handle_cast({disconnect, Node}, State) ->
+ case rpc:call(Node, erlang, whereis, [?MODULE]) of
+ {badrpc, _} ->
+ ignore;
+ RemoteMon when pid(RemoteMon) ->
+ unlink(RemoteMon)
+ end,
+ {noreply, State};
+
+handle_cast({inconsistent_database, Context, Node}, State) ->
+ Msg = {inconsistent_database, Context, Node},
+ mnesia_lib:report_system_event(Msg),
+ {noreply, State};
+
+handle_cast(Msg, State) ->
+ error("~p got unexpected cast: ~p~n", [?MODULE, Msg]),
+ {noreply, State}.
+
+%%----------------------------------------------------------------------
+%% Func: handle_info/2
+%% Returns: {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State} (terminate/2 is called)
+%%----------------------------------------------------------------------
+
+handle_info({'EXIT', Pid, R}, State) when Pid == State#state.supervisor ->
+ dbg_out("~p was ~p by supervisor~n",[?MODULE, R]),
+ {stop, R, State};
+
+handle_info({'EXIT', Pid, fatal}, State) when node(Pid) == node() ->
+ dbg_out("~p got FATAL ERROR from: ~p~n",[?MODULE, Pid]),
+ exit(State#state.supervisor, shutdown),
+ {noreply, State};
+
+handle_info({'EXIT', Pid, Reason}, State) ->
+ Node = node(Pid),
+ if
+ Node /= node() ->
+ %% Remotly linked process died, assume that it was a mnesia_monitor
+ mnesia_recover:mnesia_down(Node),
+ mnesia_controller:mnesia_down(Node),
+ {noreply, State#state{going_down = [Node | State#state.going_down]}};
+ true ->
+ %% We have probably got an exit signal from from
+ %% disk_log or dets
+ Hint = "Hint: check that the disk still is writable",
+ Msg = {'EXIT', Pid, Reason},
+ fatal("~p got unexpected info: ~p; ~p~n",
+ [?MODULE, Msg, Hint])
+ end;
+
+handle_info({nodeup, Node}, State) ->
+ %% Ok, we are connected to yet another Erlang node
+ %% Let's check if Mnesia is running there in order
+ %% to detect if the network has been partitioned
+ %% due to communication failure.
+
+ HasDown = mnesia_recover:has_mnesia_down(Node),
+ ImRunning = mnesia_lib:is_running(),
+
+ if
+ %% If I'm not running the test will be made later.
+ HasDown == true, ImRunning == yes ->
+ spawn_link(?MODULE, detect_partitioned_network, [self(), Node]);
+ true ->
+ ignore
+ end,
+ {noreply, State};
+
+handle_info({nodedown, _Node}, State) ->
+ %% Ignore, we are only caring about nodeup's
+ {noreply, State};
+
+handle_info({disk_log, _Node, Log, Info}, State) ->
+ case Info of
+ {truncated, _No} ->
+ ok;
+ _ ->
+ mnesia_lib:important("Warning Log file ~p error reason ~s~n",
+ [Log, disk_log:format_error(Info)])
+ end,
+ {noreply, State};
+
+handle_info(Msg, State) ->
+ error("~p got unexpected info (~p): ~p~n", [?MODULE, State, Msg]).
+
+%%----------------------------------------------------------------------
+%% Func: terminate/2
+%% Purpose: Shutdown the server
+%% Returns: any (ignored by gen_server)
+%%----------------------------------------------------------------------
+terminate(Reason, State) ->
+ terminate_proc(?MODULE, Reason, State).
+
+%%----------------------------------------------------------------------
+%% Func: code_change/3
+%% Purpose: Upgrade process when its code is to be changed
+%% Returns: {ok, NewState}
+%%----------------------------------------------------------------------
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%%----------------------------------------------------------------------
+%%% Internal functions
+%%%----------------------------------------------------------------------
+
+process_config_args([]) ->
+ ok;
+process_config_args([C|T]) ->
+ V = get_env(C),
+ dbg_out("Env ~p: ~p~n", [C, V]),
+ mnesia_lib:set(C, V),
+ process_config_args(T).
+
+set_env(E,Val) ->
+ mnesia_lib:set(E, check_type(E,Val)),
+ ok.
+
+get_env(E) ->
+ case ?catch_val(E) of
+ {'EXIT', _} ->
+ case application:get_env(mnesia, E) of
+ {ok, Val} ->
+ check_type(E, Val);
+ undefined ->
+ check_type(E, default_env(E))
+ end;
+ Val ->
+ Val
+ end.
+
+env() ->
+ [
+ access_module,
+ auto_repair,
+ backup_module,
+ debug,
+ dir,
+ dump_log_load_regulation,
+ dump_log_time_threshold,
+ dump_log_update_in_place,
+ dump_log_write_threshold,
+ embedded_mnemosyne,
+ event_module,
+ extra_db_nodes,
+ ignore_fallback_at_startup,
+ fallback_error_function,
+ max_wait_for_decision,
+ schema_location,
+ core_dir
+ ].
+
+default_env(access_module) ->
+ mnesia;
+default_env(auto_repair) ->
+ true;
+default_env(backup_module) ->
+ mnesia_backup;
+default_env(debug) ->
+ none;
+default_env(dir) ->
+ Name = lists:concat(["Mnesia.", node()]),
+ filename:absname(Name);
+default_env(dump_log_load_regulation) ->
+ false;
+default_env(dump_log_time_threshold) ->
+ timer:minutes(3);
+default_env(dump_log_update_in_place) ->
+ true;
+default_env(dump_log_write_threshold) ->
+ 1000;
+default_env(embedded_mnemosyne) ->
+ false;
+default_env(event_module) ->
+ mnesia_event;
+default_env(extra_db_nodes) ->
+ [];
+default_env(ignore_fallback_at_startup) ->
+ false;
+default_env(fallback_error_function) ->
+ {mnesia, lkill};
+default_env(max_wait_for_decision) ->
+ infinity;
+default_env(schema_location) ->
+ opt_disc;
+default_env(core_dir) ->
+ false.
+
+check_type(Env, Val) ->
+ case catch do_check_type(Env, Val) of
+ {'EXIT', _Reason} ->
+ exit({bad_config, Env, Val});
+ NewVal ->
+ NewVal
+ end.
+
+do_check_type(access_module, A) when atom(A) -> A;
+do_check_type(auto_repair, B) -> bool(B);
+do_check_type(backup_module, B) when atom(B) -> B;
+do_check_type(debug, debug) -> debug;
+do_check_type(debug, false) -> none;
+do_check_type(debug, none) -> none;
+do_check_type(debug, trace) -> trace;
+do_check_type(debug, true) -> debug;
+do_check_type(debug, verbose) -> verbose;
+do_check_type(dir, V) -> filename:absname(V);
+do_check_type(dump_log_load_regulation, B) -> bool(B);
+do_check_type(dump_log_time_threshold, I) when integer(I), I > 0 -> I;
+do_check_type(dump_log_update_in_place, B) -> bool(B);
+do_check_type(dump_log_write_threshold, I) when integer(I), I > 0 -> I;
+do_check_type(event_module, A) when atom(A) -> A;
+do_check_type(ignore_fallback_at_startup, B) -> bool(B);
+do_check_type(fallback_error_function, {Mod, Func})
+ when atom(Mod), atom(Func) -> {Mod, Func};
+do_check_type(embedded_mnemosyne, B) -> bool(B);
+do_check_type(extra_db_nodes, L) when list(L) ->
+ Fun = fun(N) when N == node() -> false;
+ (A) when atom(A) -> true
+ end,
+ lists:filter(Fun, L);
+do_check_type(max_wait_for_decision, infinity) -> infinity;
+do_check_type(max_wait_for_decision, I) when integer(I), I > 0 -> I;
+do_check_type(schema_location, M) -> media(M);
+do_check_type(core_dir, "false") -> false;
+do_check_type(core_dir, false) -> false;
+do_check_type(core_dir, Dir) when list(Dir) -> Dir.
+
+
+bool(true) -> true;
+bool(false) -> false.
+
+media(disc) -> disc;
+media(opt_disc) -> opt_disc;
+media(ram) -> ram.
+
+patch_env(Env, Val) ->
+ case catch do_check_type(Env, Val) of
+ {'EXIT', _Reason} ->
+ {error, {bad_type, Env, Val}};
+ NewVal ->
+ application_controller:set_env(mnesia, Env, NewVal),
+ NewVal
+ end.
+
+detect_partitioned_network(Mon, Node) ->
+ GoodNodes = negotiate_protocol([Node]),
+ detect_inconcistency(GoodNodes, running_partitioned_network),
+ unlink(Mon),
+ exit(normal).
+
+detect_inconcistency([], _Context) ->
+ ok;
+detect_inconcistency(Nodes, Context) ->
+ Downs = [N || N <- Nodes, mnesia_recover:has_mnesia_down(N)],
+ {Replies, _BadNodes} =
+ rpc:multicall(Downs, ?MODULE, has_remote_mnesia_down, [node()]),
+ report_inconsistency(Replies, Context, ok).
+
+has_remote_mnesia_down(Node) ->
+ HasDown = mnesia_recover:has_mnesia_down(Node),
+ Master = mnesia_recover:get_master_nodes(schema),
+ if
+ HasDown == true, Master == [] ->
+ {true, node()};
+ true ->
+ {false, node()}
+ end.
+
+report_inconsistency([{true, Node} | Replies], Context, _Status) ->
+ %% Oops, Mnesia is already running on the
+ %% other node AND we both regard each
+ %% other as down. The database is
+ %% potentially inconsistent and we has to
+ %% do tell the applications about it, so
+ %% they may perform some clever recovery
+ %% action.
+ Msg = {inconsistent_database, Context, Node},
+ mnesia_lib:report_system_event(Msg),
+ report_inconsistency(Replies, Context, inconsistent_database);
+report_inconsistency([{false, _Node} | Replies], Context, Status) ->
+ report_inconsistency(Replies, Context, Status);
+report_inconsistency([{badrpc, _Reason} | Replies], Context, Status) ->
+ report_inconsistency(Replies, Context, Status);
+report_inconsistency([], _Context, Status) ->
+ Status.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_recover.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_recover.erl
new file mode 100644
index 0000000000..cbb110fa6c
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_recover.erl
@@ -0,0 +1,1174 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_recover.erl,v 1.1 2008/12/17 09:53:39 mikpe Exp $
+%%
+-module(mnesia_recover).
+
+-behaviour(gen_server).
+
+-export([
+ allow_garb/0,
+ call/1,
+ connect_nodes/1,
+ disconnect/1,
+ dump_decision_tab/0,
+ get_master_node_info/0,
+ get_master_node_tables/0,
+ get_master_nodes/1,
+ get_mnesia_downs/0,
+ has_mnesia_down/1,
+ incr_trans_tid_serial/0,
+ init/0,
+ log_decision/1,
+ log_master_nodes/3,
+ log_mnesia_down/1,
+ log_mnesia_up/1,
+ mnesia_down/1,
+ note_decision/2,
+ note_log_decision/2,
+ outcome/2,
+ start/0,
+ start_garb/0,
+ still_pending/1,
+ sync_trans_tid_serial/1,
+ wait_for_decision/2,
+ what_happened/3
+ ]).
+
+%% gen_server callbacks
+-export([init/1,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ terminate/2,
+ code_change/3
+ ]).
+
+
+-include("mnesia.hrl").
+-import(mnesia_lib, [set/2, verbose/2, error/2, fatal/2]).
+
+-record(state, {supervisor,
+ unclear_pid,
+ unclear_decision,
+ unclear_waitfor,
+ tm_queue_len = 0,
+ initiated = false,
+ early_msgs = []
+ }).
+
+%%-define(DBG(F, A), mnesia:report_event(list_to_atom(lists:flatten(io_lib:format(F, A))))).
+%%-define(DBG(F, A), io:format("DBG: " ++ F, A)).
+
+-record(transient_decision, {tid, outcome}).
+
+start() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [self()],
+ [{timeout, infinity}
+ %%, {debug, [trace]}
+ ]).
+
+init() ->
+ call(init).
+
+start_garb() ->
+ Pid = whereis(mnesia_recover),
+ {ok, _} = timer:send_interval(timer:minutes(2), Pid, garb_decisions),
+ {ok, _} = timer:send_interval(timer:seconds(10), Pid, check_overload).
+
+allow_garb() ->
+ cast(allow_garb).
+
+
+%% The transaction log has either been swiched (latest -> previous) or
+%% there is nothing to be dumped. This means that the previous
+%% transaction log only may contain commit records which refers to
+%% transactions noted in the last two of the 'Prev' tables. All other
+%% tables may now be garbed by 'garb_decisions' (after 2 minutes).
+%% Max 10 tables are kept.
+do_allow_garb() ->
+ %% The order of the following stuff is important!
+ Curr = val(latest_transient_decision),
+ Old = val(previous_transient_decisions),
+ Next = create_transient_decision(),
+ {Prev, ReallyOld} = sublist([Curr | Old], 10, []),
+ [?ets_delete_table(Tab) || Tab <- ReallyOld],
+ set(previous_transient_decisions, Prev),
+ set(latest_transient_decision, Next).
+
+sublist([H|R], N, Acc) when N > 0 ->
+ sublist(R, N-1, [H| Acc]);
+sublist(List, _N, Acc) ->
+ {lists:reverse(Acc), List}.
+
+do_garb_decisions() ->
+ case val(previous_transient_decisions) of
+ [First, Second | Rest] ->
+ set(previous_transient_decisions, [First, Second]),
+ [?ets_delete_table(Tab) || Tab <- Rest];
+ _ ->
+ ignore
+ end.
+
+connect_nodes([]) ->
+ [];
+connect_nodes(Ns) ->
+ %% Determine which nodes we should try to connect
+ AlreadyConnected = val(recover_nodes),
+ {_, Nodes} = mnesia_lib:search_delete(node(), Ns),
+ Check = Nodes -- AlreadyConnected,
+ GoodNodes = mnesia_monitor:negotiate_protocol(Check),
+ if
+ GoodNodes == [] ->
+ %% No good noodes to connect to
+ ignore;
+ true ->
+ %% Now we have agreed upon a protocol with some new nodes
+ %% and we may use them when we recover transactions
+ mnesia_lib:add_list(recover_nodes, GoodNodes),
+ cast({announce_all, GoodNodes}),
+ case get_master_nodes(schema) of
+ [] ->
+ Context = starting_partitioned_network,
+ mnesia_monitor:detect_inconcistency(GoodNodes, Context);
+ _ -> %% If master_nodes is set ignore old inconsistencies
+ ignore
+ end
+ end,
+ {GoodNodes, AlreadyConnected}.
+
+disconnect(Node) ->
+ mnesia_monitor:disconnect(Node),
+ mnesia_lib:del(recover_nodes, Node).
+
+val(Var) ->
+ case ?catch_val(Var) of
+ {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
+ Value -> Value
+ end.
+
+call(Msg) ->
+ Pid = whereis(?MODULE),
+ case Pid of
+ undefined ->
+ {error, {node_not_running, node()}};
+ Pid ->
+ link(Pid),
+ Res = gen_server:call(Pid, Msg, infinity),
+ unlink(Pid),
+
+ %% We get an exit signal if server dies
+ receive
+ {'EXIT', Pid, _Reason} ->
+ {error, {node_not_running, node()}}
+ after 0 ->
+ ignore
+ end,
+ Res
+ end.
+
+multicall(Nodes, Msg) ->
+ rpc:multicall(Nodes, ?MODULE, call, [Msg]).
+
+cast(Msg) ->
+ case whereis(?MODULE) of
+ undefined -> ignore;
+ Pid -> gen_server:cast(Pid, Msg)
+ end.
+
+abcast(Nodes, Msg) ->
+ gen_server:abcast(Nodes, ?MODULE, Msg).
+
+note_decision(Tid, Outcome) ->
+ Tab = val(latest_transient_decision),
+ ?ets_insert(Tab, #transient_decision{tid = Tid, outcome = Outcome}).
+
+note_up(Node, _Date, _Time) ->
+ ?ets_delete(mnesia_decision, Node).
+
+note_down(Node, Date, Time) ->
+ ?ets_insert(mnesia_decision, {mnesia_down, Node, Date, Time}).
+
+note_master_nodes(Tab, []) ->
+ ?ets_delete(mnesia_decision, Tab);
+note_master_nodes(Tab, Nodes) when list(Nodes) ->
+ Master = {master_nodes, Tab, Nodes},
+ ?ets_insert(mnesia_decision, Master).
+
+note_outcome(D) when D#decision.disc_nodes == [] ->
+%% ?DBG("~w: note_tmp_decision: ~w~n", [node(), D]),
+ note_decision(D#decision.tid, filter_outcome(D#decision.outcome)),
+ ?ets_delete(mnesia_decision, D#decision.tid);
+note_outcome(D) when D#decision.disc_nodes /= [] ->
+%% ?DBG("~w: note_decision: ~w~n", [node(), D]),
+ ?ets_insert(mnesia_decision, D).
+
+log_decision(D) when D#decision.outcome /= unclear ->
+ OldD = decision(D#decision.tid),
+ MergedD = merge_decisions(node(), OldD, D),
+ do_log_decision(MergedD, true);
+log_decision(D) ->
+ do_log_decision(D, false).
+
+do_log_decision(D, DoTell) ->
+ RamNs = D#decision.ram_nodes,
+ DiscNs = D#decision.disc_nodes -- [node()],
+ Outcome = D#decision.outcome,
+ D2 =
+ case Outcome of
+ aborted -> D#decision{disc_nodes = DiscNs};
+ committed -> D#decision{disc_nodes = DiscNs};
+ _ -> D
+ end,
+ note_outcome(D2),
+ case mnesia_monitor:use_dir() of
+ true ->
+ mnesia_log:append(latest_log, D2),
+ if
+ DoTell == true, Outcome /= unclear ->
+ tell_im_certain(DiscNs, D2),
+ tell_im_certain(RamNs, D2);
+ true ->
+ ignore
+ end;
+ false ->
+ ignore
+ end.
+
+tell_im_certain([], _D) ->
+ ignore;
+tell_im_certain(Nodes, D) ->
+ Msg = {im_certain, node(), D},
+%% ?DBG("~w: ~w: tell: ~w~n", [node(), Msg, Nodes]),
+ abcast(Nodes, Msg).
+
+log_mnesia_up(Node) ->
+ call({log_mnesia_up, Node}).
+
+log_mnesia_down(Node) ->
+ call({log_mnesia_down, Node}).
+
+get_mnesia_downs() ->
+ Tab = mnesia_decision,
+ Pat = {mnesia_down, '_', '_', '_'},
+ Downs = ?ets_match_object(Tab, Pat),
+ [Node || {mnesia_down, Node, _Date, _Time} <- Downs].
+
+%% Check if we have got a mnesia_down from Node
+has_mnesia_down(Node) ->
+ case ?ets_lookup(mnesia_decision, Node) of
+ [{mnesia_down, Node, _Date, _Time}] ->
+ true;
+ [] ->
+ false
+ end.
+
+mnesia_down(Node) ->
+ case ?catch_val(recover_nodes) of
+ {'EXIT', _} ->
+ %% Not started yet
+ ignore;
+ _ ->
+ mnesia_lib:del(recover_nodes, Node),
+ cast({mnesia_down, Node})
+ end.
+
+log_master_nodes(Args, UseDir, IsRunning) ->
+ if
+ IsRunning == yes ->
+ log_master_nodes2(Args, UseDir, IsRunning, ok);
+ UseDir == false ->
+ ok;
+ true ->
+ Name = latest_log,
+ Fname = mnesia_log:latest_log_file(),
+ Exists = mnesia_lib:exists(Fname),
+ Repair = mnesia:system_info(auto_repair),
+ OpenArgs = [{file, Fname}, {name, Name}, {repair, Repair}],
+ case disk_log:open(OpenArgs) of
+ {ok, Name} ->
+ log_master_nodes2(Args, UseDir, IsRunning, ok);
+ {repaired, Name, {recovered, _R}, {badbytes, _B}}
+ when Exists == true ->
+ log_master_nodes2(Args, UseDir, IsRunning, ok);
+ {repaired, Name, {recovered, _R}, {badbytes, _B}}
+ when Exists == false ->
+ mnesia_log:write_trans_log_header(),
+ log_master_nodes2(Args, UseDir, IsRunning, ok);
+ {error, Reason} ->
+ {error, Reason}
+ end
+ end.
+
+log_master_nodes2([{Tab, Nodes} | Tail], UseDir, IsRunning, WorstRes) ->
+ Res =
+ case IsRunning of
+ yes ->
+ R = call({log_master_nodes, Tab, Nodes, UseDir, IsRunning}),
+ mnesia_controller:master_nodes_updated(Tab, Nodes),
+ R;
+ _ ->
+ do_log_master_nodes(Tab, Nodes, UseDir, IsRunning)
+ end,
+ case Res of
+ ok ->
+ log_master_nodes2(Tail, UseDir, IsRunning, WorstRes);
+ {error, Reason} ->
+ log_master_nodes2(Tail, UseDir, IsRunning, {error, Reason})
+ end;
+log_master_nodes2([], _UseDir, IsRunning, WorstRes) ->
+ case IsRunning of
+ yes ->
+ WorstRes;
+ _ ->
+ disk_log:close(latest_log),
+ WorstRes
+ end.
+
+get_master_node_info() ->
+ Tab = mnesia_decision,
+ Pat = {master_nodes, '_', '_'},
+ case catch mnesia_lib:db_match_object(ram_copies,Tab, Pat) of
+ {'EXIT', _} ->
+ [];
+ Masters ->
+ Masters
+ end.
+
+get_master_node_tables() ->
+ Masters = get_master_node_info(),
+ [Tab || {master_nodes, Tab, _Nodes} <- Masters].
+
+get_master_nodes(Tab) ->
+ case catch ?ets_lookup_element(mnesia_decision, Tab, 3) of
+ {'EXIT', _} -> [];
+ Nodes -> Nodes
+ end.
+
+%% Determine what has happened to the transaction
+what_happened(Tid, Protocol, Nodes) ->
+ Default =
+ case Protocol of
+ asym_trans -> aborted;
+ _ -> unclear %% sym_trans and sync_sym_trans
+ end,
+ This = node(),
+ case lists:member(This, Nodes) of
+ true ->
+ {ok, Outcome} = call({what_happened, Default, Tid}),
+ Others = Nodes -- [This],
+ case filter_outcome(Outcome) of
+ unclear -> what_happened_remotely(Tid, Default, Others);
+ aborted -> aborted;
+ committed -> committed
+ end;
+ false ->
+ what_happened_remotely(Tid, Default, Nodes)
+ end.
+
+what_happened_remotely(Tid, Default, Nodes) ->
+ {Replies, _} = multicall(Nodes, {what_happened, Default, Tid}),
+ check_what_happened(Replies, 0, 0).
+
+check_what_happened([H | T], Aborts, Commits) ->
+ case H of
+ {ok, R} ->
+ case filter_outcome(R) of
+ committed ->
+ check_what_happened(T, Aborts, Commits + 1);
+ aborted ->
+ check_what_happened(T, Aborts + 1, Commits);
+ unclear ->
+ check_what_happened(T, Aborts, Commits)
+ end;
+ {error, _} ->
+ check_what_happened(T, Aborts, Commits);
+ {badrpc, _} ->
+ check_what_happened(T, Aborts, Commits)
+ end;
+check_what_happened([], Aborts, Commits) ->
+ if
+ Aborts == 0, Commits == 0 -> aborted; % None of the active nodes knows
+ Aborts > 0 -> aborted; % Someody has aborted
+ Aborts == 0, Commits > 0 -> committed % All has committed
+ end.
+
+%% Determine what has happened to the transaction
+%% and possibly wait forever for the decision.
+wait_for_decision(presume_commit, _InitBy) ->
+ %% sym_trans
+ {{presume_commit, self()}, committed};
+
+wait_for_decision(D, InitBy) when D#decision.outcome == presume_abort ->
+ %% asym_trans
+ Tid = D#decision.tid,
+ Outcome = filter_outcome(outcome(Tid, D#decision.outcome)),
+ if
+ Outcome /= unclear ->
+ {Tid, Outcome};
+
+ InitBy /= startup ->
+ %% Wait a while for active transactions
+ %% to end and try again
+ timer:sleep(200),
+ wait_for_decision(D, InitBy);
+
+ InitBy == startup ->
+ {ok, Res} = call({wait_for_decision, D}),
+ {Tid, Res}
+ end.
+
+still_pending([Tid | Pending]) ->
+ case filter_outcome(outcome(Tid, unclear)) of
+ unclear -> [Tid | still_pending(Pending)];
+ _ -> still_pending(Pending)
+ end;
+still_pending([]) ->
+ [].
+
+load_decision_tab() ->
+ Cont = mnesia_log:open_decision_tab(),
+ load_decision_tab(Cont, load_decision_tab),
+ mnesia_log:close_decision_tab().
+
+load_decision_tab(eof, _InitBy) ->
+ ok;
+load_decision_tab(Cont, InitBy) ->
+ case mnesia_log:chunk_decision_tab(Cont) of
+ {Cont2, Decisions} ->
+ note_log_decisions(Decisions, InitBy),
+ load_decision_tab(Cont2, InitBy);
+ eof ->
+ ok
+ end.
+
+%% Dumps DECISION.LOG and PDECISION.LOG and removes them.
+%% From now on all decisions are logged in the transaction log file
+convert_old() ->
+ HasOldStuff =
+ mnesia_lib:exists(mnesia_log:previous_decision_log_file()) or
+ mnesia_lib:exists(mnesia_log:decision_log_file()),
+ case HasOldStuff of
+ true ->
+ mnesia_log:open_decision_log(),
+ dump_decision_log(startup),
+ dump_decision_log(startup),
+ mnesia_log:close_decision_log(),
+ Latest = mnesia_log:decision_log_file(),
+ ok = file:delete(Latest);
+ false ->
+ ignore
+ end.
+
+dump_decision_log(InitBy) ->
+ %% Assumed to be run in transaction log dumper process
+ Cont = mnesia_log:prepare_decision_log_dump(),
+ perform_dump_decision_log(Cont, InitBy).
+
+perform_dump_decision_log(eof, _InitBy) ->
+ confirm_decision_log_dump();
+perform_dump_decision_log(Cont, InitBy) when InitBy == startup ->
+ case mnesia_log:chunk_decision_log(Cont) of
+ {Cont2, Decisions} ->
+ note_log_decisions(Decisions, InitBy),
+ perform_dump_decision_log(Cont2, InitBy);
+ eof ->
+ confirm_decision_log_dump()
+ end;
+perform_dump_decision_log(_Cont, _InitBy) ->
+ confirm_decision_log_dump().
+
+confirm_decision_log_dump() ->
+ dump_decision_tab(),
+ mnesia_log:confirm_decision_log_dump().
+
+dump_decision_tab() ->
+ Tab = mnesia_decision,
+ All = mnesia_lib:db_match_object(ram_copies,Tab, '_'),
+ mnesia_log:save_decision_tab({decision_list, All}).
+
+note_log_decisions([What | Tail], InitBy) ->
+ note_log_decision(What, InitBy),
+ note_log_decisions(Tail, InitBy);
+note_log_decisions([], _InitBy) ->
+ ok.
+
+note_log_decision(NewD, InitBy) when NewD#decision.outcome == pre_commit ->
+ note_log_decision(NewD#decision{outcome = unclear}, InitBy);
+
+note_log_decision(NewD, _InitBy) when record(NewD, decision) ->
+ Tid = NewD#decision.tid,
+ sync_trans_tid_serial(Tid),
+ OldD = decision(Tid),
+ MergedD = merge_decisions(node(), OldD, NewD),
+ note_outcome(MergedD);
+
+note_log_decision({trans_tid, serial, _Serial}, startup) ->
+ ignore;
+
+note_log_decision({trans_tid, serial, Serial}, _InitBy) ->
+ sync_trans_tid_serial(Serial);
+
+note_log_decision({mnesia_up, Node, Date, Time}, _InitBy) ->
+ note_up(Node, Date, Time);
+
+note_log_decision({mnesia_down, Node, Date, Time}, _InitBy) ->
+ note_down(Node, Date, Time);
+
+note_log_decision({master_nodes, Tab, Nodes}, _InitBy) ->
+ note_master_nodes(Tab, Nodes);
+
+note_log_decision(H, _InitBy) when H#log_header.log_kind == decision_log ->
+ V = mnesia_log:decision_log_version(),
+ if
+ H#log_header.log_version == V->
+ ok;
+ H#log_header.log_version == "2.0" ->
+ verbose("Accepting an old version format of decision log: ~p~n",
+ [V]),
+ ok;
+ true ->
+ fatal("Bad version of decision log: ~p~n", [H])
+ end;
+
+note_log_decision(H, _InitBy) when H#log_header.log_kind == decision_tab ->
+ V = mnesia_log:decision_tab_version(),
+ if
+ V == H#log_header.log_version ->
+ ok;
+ true ->
+ fatal("Bad version of decision tab: ~p~n", [H])
+ end;
+note_log_decision({decision_list, ItemList}, InitBy) ->
+ note_log_decisions(ItemList, InitBy);
+note_log_decision(BadItem, InitBy) ->
+ exit({"Bad decision log item", BadItem, InitBy}).
+
+trans_tid_serial() ->
+ ?ets_lookup_element(mnesia_decision, serial, 3).
+
+set_trans_tid_serial(Val) ->
+ ?ets_insert(mnesia_decision, {trans_tid, serial, Val}).
+
+incr_trans_tid_serial() ->
+ ?ets_update_counter(mnesia_decision, serial, 1).
+
+sync_trans_tid_serial(ThatCounter) when integer(ThatCounter) ->
+ ThisCounter = trans_tid_serial(),
+ if
+ ThatCounter > ThisCounter ->
+ set_trans_tid_serial(ThatCounter + 1);
+ true ->
+ ignore
+ end;
+sync_trans_tid_serial(Tid) ->
+ sync_trans_tid_serial(Tid#tid.counter).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% Callback functions from gen_server
+
+%%----------------------------------------------------------------------
+%% Func: init/1
+%% Returns: {ok, State} |
+%% {ok, State, Timeout} |
+%% {stop, Reason}
+%%----------------------------------------------------------------------
+init([Parent]) ->
+ process_flag(trap_exit, true),
+ mnesia_lib:verbose("~p starting: ~p~n", [?MODULE, self()]),
+ set(latest_transient_decision, create_transient_decision()),
+ set(previous_transient_decisions, []),
+ set(recover_nodes, []),
+ State = #state{supervisor = Parent},
+ {ok, State}.
+
+create_transient_decision() ->
+ ?ets_new_table(mnesia_transient_decision, [{keypos, 2}, set, public]).
+
+%%----------------------------------------------------------------------
+%% Func: handle_call/3
+%% Returns: {reply, Reply, State} |
+%% {reply, Reply, State, Timeout} |
+%% {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, Reply, State} | (terminate/2 is called)
+%%----------------------------------------------------------------------
+
+handle_call(init, From, State) when State#state.initiated == false ->
+ Args = [{keypos, 2}, set, public, named_table],
+ case mnesia_monitor:use_dir() of
+ true ->
+ ?ets_new_table(mnesia_decision, Args),
+ set_trans_tid_serial(0),
+ TabFile = mnesia_log:decision_tab_file(),
+ case mnesia_lib:exists(TabFile) of
+ true ->
+ load_decision_tab();
+ false ->
+ ignore
+ end,
+ convert_old(),
+ mnesia_dumper:opt_dump_log(scan_decisions);
+ false ->
+ ?ets_new_table(mnesia_decision, Args),
+ set_trans_tid_serial(0)
+ end,
+ handle_early_msgs(State, From);
+
+handle_call(Msg, From, State) when State#state.initiated == false ->
+ %% Buffer early messages
+ Msgs = State#state.early_msgs,
+ {noreply, State#state{early_msgs = [{call, Msg, From} | Msgs]}};
+
+handle_call({what_happened, Default, Tid}, _From, State) ->
+ sync_trans_tid_serial(Tid),
+ Outcome = outcome(Tid, Default),
+ {reply, {ok, Outcome}, State};
+
+handle_call({wait_for_decision, D}, From, State) ->
+ Recov = val(recover_nodes),
+ AliveRam = (mnesia_lib:intersect(D#decision.ram_nodes, Recov) -- [node()]),
+ RemoteDisc = D#decision.disc_nodes -- [node()],
+ if
+ AliveRam == [], RemoteDisc == [] ->
+ %% No more else to wait for and we may safely abort
+ {reply, {ok, aborted}, State};
+ true ->
+ verbose("Transaction ~p is unclear. "
+ "Wait for disc nodes: ~w ram: ~w~n",
+ [D#decision.tid, RemoteDisc, AliveRam]),
+ AliveDisc = mnesia_lib:intersect(RemoteDisc, Recov),
+ Msg = {what_decision, node(), D},
+ abcast(AliveRam, Msg),
+ abcast(AliveDisc, Msg),
+ case val(max_wait_for_decision) of
+ infinity ->
+ ignore;
+ MaxWait ->
+ ForceMsg = {force_decision, D#decision.tid},
+ {ok, _} = timer:send_after(MaxWait, ForceMsg)
+ end,
+ State2 = State#state{unclear_pid = From,
+ unclear_decision = D,
+ unclear_waitfor = (RemoteDisc ++ AliveRam)},
+ {noreply, State2}
+ end;
+
+handle_call({log_mnesia_up, Node}, _From, State) ->
+ do_log_mnesia_up(Node),
+ {reply, ok, State};
+
+handle_call({log_mnesia_down, Node}, _From, State) ->
+ do_log_mnesia_down(Node),
+ {reply, ok, State};
+
+handle_call({log_master_nodes, Tab, Nodes, UseDir, IsRunning}, _From, State) ->
+ do_log_master_nodes(Tab, Nodes, UseDir, IsRunning),
+ {reply, ok, State};
+
+handle_call(Msg, _From, State) ->
+ error("~p got unexpected call: ~p~n", [?MODULE, Msg]),
+ {noreply, State}.
+
+do_log_mnesia_up(Node) ->
+ Yoyo = {mnesia_up, Node, Date = date(), Time = time()},
+ case mnesia_monitor:use_dir() of
+ true ->
+ mnesia_log:append(latest_log, Yoyo),
+ disk_log:sync(latest_log);
+ false ->
+ ignore
+ end,
+ note_up(Node, Date, Time).
+
+do_log_mnesia_down(Node) ->
+ Yoyo = {mnesia_down, Node, Date = date(), Time = time()},
+ case mnesia_monitor:use_dir() of
+ true ->
+ mnesia_log:append(latest_log, Yoyo),
+ disk_log:sync(latest_log);
+ false ->
+ ignore
+ end,
+ note_down(Node, Date, Time).
+
+do_log_master_nodes(Tab, Nodes, UseDir, IsRunning) ->
+ Master = {master_nodes, Tab, Nodes},
+ Res =
+ case UseDir of
+ true ->
+ LogRes = mnesia_log:append(latest_log, Master),
+ disk_log:sync(latest_log),
+ LogRes;
+ false ->
+ ok
+ end,
+ case IsRunning of
+ yes ->
+ note_master_nodes(Tab, Nodes);
+ _NotRunning ->
+ ignore
+ end,
+ Res.
+
+%%----------------------------------------------------------------------
+%% Func: handle_cast/2
+%% Returns: {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State} (terminate/2 is called)
+%%----------------------------------------------------------------------
+
+handle_cast(Msg, State) when State#state.initiated == false ->
+ %% Buffer early messages
+ Msgs = State#state.early_msgs,
+ {noreply, State#state{early_msgs = [{cast, Msg} | Msgs]}};
+
+handle_cast({im_certain, Node, NewD}, State) ->
+ OldD = decision(NewD#decision.tid),
+ MergedD = merge_decisions(Node, OldD, NewD),
+ do_log_decision(MergedD, false),
+ {noreply, State};
+
+handle_cast(allow_garb, State) ->
+ do_allow_garb(),
+ {noreply, State};
+
+handle_cast({decisions, Node, Decisions}, State) ->
+ mnesia_lib:add(recover_nodes, Node),
+ State2 = add_remote_decisions(Node, Decisions, State),
+ {noreply, State2};
+
+handle_cast({what_decision, Node, OtherD}, State) ->
+ Tid = OtherD#decision.tid,
+ sync_trans_tid_serial(Tid),
+ Decision =
+ case decision(Tid) of
+ no_decision -> OtherD;
+ MyD when record(MyD, decision) -> MyD
+ end,
+ announce([Node], [Decision], [], true),
+ {noreply, State};
+
+handle_cast({mnesia_down, Node}, State) ->
+ case State#state.unclear_decision of
+ undefined ->
+ {noreply, State};
+ D ->
+ case lists:member(Node, D#decision.ram_nodes) of
+ false ->
+ {noreply, State};
+ true ->
+ State2 = add_remote_decision(Node, D, State),
+ {noreply, State2}
+ end
+ end;
+
+handle_cast({announce_all, Nodes}, State) ->
+ announce_all(Nodes, tabs()),
+ {noreply, State};
+
+handle_cast(Msg, State) ->
+ error("~p got unexpected cast: ~p~n", [?MODULE, Msg]),
+ {noreply, State}.
+
+%%----------------------------------------------------------------------
+%% Func: handle_info/2
+%% Returns: {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State} (terminate/2 is called)
+%%----------------------------------------------------------------------
+
+%% No need for buffering
+%% handle_info(Msg, State) when State#state.initiated == false ->
+%% %% Buffer early messages
+%% Msgs = State#state.early_msgs,
+%% {noreply, State#state{early_msgs = [{info, Msg} | Msgs]}};
+
+handle_info(check_overload, S) ->
+ %% Time to check if mnesia_tm is overloaded
+ case whereis(mnesia_tm) of
+ Pid when pid(Pid) ->
+
+ Threshold = 100,
+ Prev = S#state.tm_queue_len,
+ {message_queue_len, Len} =
+ process_info(Pid, message_queue_len),
+ if
+ Len > Threshold, Prev > Threshold ->
+ What = {mnesia_tm, message_queue_len, [Prev, Len]},
+ mnesia_lib:report_system_event({mnesia_overload, What}),
+ {noreply, S#state{tm_queue_len = 0}};
+
+ Len > Threshold ->
+ {noreply, S#state{tm_queue_len = Len}};
+
+ true ->
+ {noreply, S#state{tm_queue_len = 0}}
+ end;
+ undefined ->
+ {noreply, S}
+ end;
+
+handle_info(garb_decisions, State) ->
+ do_garb_decisions(),
+ {noreply, State};
+
+handle_info({force_decision, Tid}, State) ->
+ %% Enforce a transaction recovery decision,
+ %% if we still are waiting for the outcome
+
+ case State#state.unclear_decision of
+ U when U#decision.tid == Tid ->
+ verbose("Decided to abort transaction ~p since "
+ "max_wait_for_decision has been exceeded~n",
+ [Tid]),
+ D = U#decision{outcome = aborted},
+ State2 = add_remote_decision(node(), D, State),
+ {noreply, State2};
+ _ ->
+ {noreply, State}
+ end;
+
+handle_info({'EXIT', Pid, R}, State) when Pid == State#state.supervisor ->
+ mnesia_lib:dbg_out("~p was ~p~n",[?MODULE, R]),
+ {stop, shutdown, State};
+
+handle_info(Msg, State) ->
+ error("~p got unexpected info: ~p~n", [?MODULE, Msg]),
+ {noreply, State}.
+
+%%----------------------------------------------------------------------
+%% Func: terminate/2
+%% Purpose: Shutdown the server
+%% Returns: any (ignored by gen_server)
+%%----------------------------------------------------------------------
+
+terminate(Reason, State) ->
+ mnesia_monitor:terminate_proc(?MODULE, Reason, State).
+
+%%----------------------------------------------------------------------
+%% Func: code_change/3
+%% Purpose: Upgrade process when its code is to be changed
+%% Returns: {ok, NewState}
+%%----------------------------------------------------------------------
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%%----------------------------------------------------------------------
+%%% Internal functions
+%%%----------------------------------------------------------------------
+
+handle_early_msgs(State, From) ->
+ Res = do_handle_early_msgs(State#state.early_msgs,
+ State#state{early_msgs = [],
+ initiated = true}),
+ gen_server:reply(From, ok),
+ Res.
+
+do_handle_early_msgs([Msg | Msgs], State) ->
+ %% The messages are in reverted order
+ case do_handle_early_msgs(Msgs, State) of
+ {stop, Reason, Reply, State2} ->
+ {stop, Reason, Reply, State2};
+ {stop, Reason, State2} ->
+ {stop, Reason, State2};
+ {noreply, State2} ->
+ handle_early_msg(Msg, State2)
+ end;
+
+do_handle_early_msgs([], State) ->
+ {noreply, State}.
+
+handle_early_msg({call, Msg, From}, State) ->
+ case handle_call(Msg, From, State) of
+ {reply, R, S} ->
+ gen_server:reply(From, R),
+ {noreply, S};
+ Other ->
+ Other
+ end;
+handle_early_msg({cast, Msg}, State) ->
+ handle_cast(Msg, State);
+handle_early_msg({info, Msg}, State) ->
+ handle_info(Msg, State).
+
+tabs() ->
+ Curr = val(latest_transient_decision), % Do not miss any trans even
+ Prev = val(previous_transient_decisions), % if the tabs are switched
+ [Curr, mnesia_decision | Prev]. % Ordered by hit probability
+
+decision(Tid) ->
+ decision(Tid, tabs()).
+
+decision(Tid, [Tab | Tabs]) ->
+ case catch ?ets_lookup(Tab, Tid) of
+ [D] when record(D, decision) ->
+ D;
+ [C] when record(C, transient_decision) ->
+ #decision{tid = C#transient_decision.tid,
+ outcome = C#transient_decision.outcome,
+ disc_nodes = [],
+ ram_nodes = []
+ };
+ [] ->
+ decision(Tid, Tabs);
+ {'EXIT', _} ->
+ %% Recently switched transient decision table
+ decision(Tid, Tabs)
+ end;
+decision(_Tid, []) ->
+ no_decision.
+
+outcome(Tid, Default) ->
+ outcome(Tid, Default, tabs()).
+
+outcome(Tid, Default, [Tab | Tabs]) ->
+ case catch ?ets_lookup_element(Tab, Tid, 3) of
+ {'EXIT', _} ->
+ outcome(Tid, Default, Tabs);
+ Val ->
+ Val
+ end;
+outcome(_Tid, Default, []) ->
+ Default.
+
+filter_outcome(Val) ->
+ case Val of
+ unclear -> unclear;
+ aborted -> aborted;
+ presume_abort -> aborted;
+ committed -> committed;
+ pre_commit -> unclear
+ end.
+
+filter_aborted(D) when D#decision.outcome == presume_abort ->
+ D#decision{outcome = aborted};
+filter_aborted(D) ->
+ D.
+
+%% Merge old decision D with new (probably remote) decision
+merge_decisions(Node, D, NewD0) ->
+ NewD = filter_aborted(NewD0),
+ if
+ D == no_decision, node() /= Node ->
+ %% We did not know anything about this txn
+ NewD#decision{disc_nodes = []};
+ D == no_decision ->
+ NewD;
+ record(D, decision) ->
+ DiscNs = D#decision.disc_nodes -- ([node(), Node]),
+ OldD = filter_aborted(D#decision{disc_nodes = DiscNs}),
+%% mnesia_lib:dbg_out("merge ~w: NewD = ~w~n D = ~w~n OldD = ~w~n",
+%% [Node, NewD, D, OldD]),
+ if
+ OldD#decision.outcome == unclear,
+ NewD#decision.outcome == unclear ->
+ D;
+
+ OldD#decision.outcome == NewD#decision.outcome ->
+ %% We have come to the same decision
+ OldD;
+
+ OldD#decision.outcome == committed,
+ NewD#decision.outcome == aborted ->
+ %% Interesting! We have already committed,
+ %% but someone else has aborted. Now we
+ %% have a nice little inconcistency. The
+ %% other guy (or some one else) has
+ %% enforced a recovery decision when
+ %% max_wait_for_decision was exceeded.
+ %% We will pretend that we have obeyed
+ %% the forced recovery decision, but we
+ %% will also generate an event in case the
+ %% application wants to do something clever.
+ Msg = {inconsistent_database, bad_decision, Node},
+ mnesia_lib:report_system_event(Msg),
+ OldD#decision{outcome = aborted};
+
+ OldD#decision.outcome == aborted ->
+ %% aborted overrrides anything
+ OldD#decision{outcome = aborted};
+
+ NewD#decision.outcome == aborted ->
+ %% aborted overrrides anything
+ OldD#decision{outcome = aborted};
+
+ OldD#decision.outcome == committed,
+ NewD#decision.outcome == unclear ->
+ %% committed overrides unclear
+ OldD#decision{outcome = committed};
+
+ OldD#decision.outcome == unclear,
+ NewD#decision.outcome == committed ->
+ %% committed overrides unclear
+ OldD#decision{outcome = committed}
+ end
+ end.
+
+add_remote_decisions(Node, [D | Tail], State) when record(D, decision) ->
+ State2 = add_remote_decision(Node, D, State),
+ add_remote_decisions(Node, Tail, State2);
+
+add_remote_decisions(Node, [C | Tail], State)
+ when record(C, transient_decision) ->
+ D = #decision{tid = C#transient_decision.tid,
+ outcome = C#transient_decision.outcome,
+ disc_nodes = [],
+ ram_nodes = []},
+ State2 = add_remote_decision(Node, D, State),
+ add_remote_decisions(Node, Tail, State2);
+
+add_remote_decisions(Node, [{mnesia_down, _, _, _} | Tail], State) ->
+ add_remote_decisions(Node, Tail, State);
+
+add_remote_decisions(Node, [{trans_tid, serial, Serial} | Tail], State) ->
+ sync_trans_tid_serial(Serial),
+ case State#state.unclear_decision of
+ undefined ->
+ ignored;
+ D ->
+ case lists:member(Node, D#decision.ram_nodes) of
+ true ->
+ ignore;
+ false ->
+ abcast([Node], {what_decision, node(), D})
+ end
+ end,
+ add_remote_decisions(Node, Tail, State);
+
+add_remote_decisions(_Node, [], State) ->
+ State.
+
+add_remote_decision(Node, NewD, State) ->
+ Tid = NewD#decision.tid,
+ OldD = decision(Tid),
+ D = merge_decisions(Node, OldD, NewD),
+ do_log_decision(D, false),
+ Outcome = D#decision.outcome,
+ if
+ OldD == no_decision ->
+ ignore;
+ Outcome == unclear ->
+ ignore;
+ true ->
+ case lists:member(node(), NewD#decision.disc_nodes) or
+ lists:member(node(), NewD#decision.ram_nodes) of
+ true ->
+ tell_im_certain([Node], D);
+ false ->
+ ignore
+ end
+ end,
+ case State#state.unclear_decision of
+ U when U#decision.tid == Tid ->
+ WaitFor = State#state.unclear_waitfor -- [Node],
+ if
+ Outcome == unclear, WaitFor == [] ->
+ %% Everybody are uncertain, lets abort
+ NewOutcome = aborted,
+ CertainD = D#decision{outcome = NewOutcome,
+ disc_nodes = [],
+ ram_nodes = []},
+ tell_im_certain(D#decision.disc_nodes, CertainD),
+ tell_im_certain(D#decision.ram_nodes, CertainD),
+ do_log_decision(CertainD, false),
+ verbose("Decided to abort transaction ~p "
+ "since everybody are uncertain ~p~n",
+ [Tid, CertainD]),
+ gen_server:reply(State#state.unclear_pid, {ok, NewOutcome}),
+ State#state{unclear_pid = undefined,
+ unclear_decision = undefined,
+ unclear_waitfor = undefined};
+ Outcome /= unclear ->
+ verbose("~p told us that transaction ~p was ~p~n",
+ [Node, Tid, Outcome]),
+ gen_server:reply(State#state.unclear_pid, {ok, Outcome}),
+ State#state{unclear_pid = undefined,
+ unclear_decision = undefined,
+ unclear_waitfor = undefined};
+ Outcome == unclear ->
+ State#state{unclear_waitfor = WaitFor}
+ end;
+ _ ->
+ State
+ end.
+
+announce_all([], _Tabs) ->
+ ok;
+announce_all(ToNodes, [Tab | Tabs]) ->
+ case catch mnesia_lib:db_match_object(ram_copies, Tab, '_') of
+ {'EXIT', _} ->
+ %% Oops, we are in the middle of a 'garb_decisions'
+ announce_all(ToNodes, Tabs);
+ List ->
+ announce(ToNodes, List, [], false),
+ announce_all(ToNodes, Tabs)
+ end;
+announce_all(_ToNodes, []) ->
+ ok.
+
+announce(ToNodes, [Head | Tail], Acc, ForceSend) ->
+ Acc2 = arrange(ToNodes, Head, Acc, ForceSend),
+ announce(ToNodes, Tail, Acc2, ForceSend);
+
+announce(_ToNodes, [], Acc, _ForceSend) ->
+ send_decisions(Acc).
+
+send_decisions([{Node, Decisions} | Tail]) ->
+ abcast([Node], {decisions, node(), Decisions}),
+ send_decisions(Tail);
+send_decisions([]) ->
+ ok.
+
+arrange([To | ToNodes], D, Acc, ForceSend) when record(D, decision) ->
+ NeedsAdd = (ForceSend or
+ lists:member(To, D#decision.disc_nodes) or
+ lists:member(To, D#decision.ram_nodes)),
+ case NeedsAdd of
+ true ->
+ Acc2 = add_decision(To, D, Acc),
+ arrange(ToNodes, D, Acc2, ForceSend);
+ false ->
+ arrange(ToNodes, D, Acc, ForceSend)
+ end;
+
+arrange([To | ToNodes], C, Acc, ForceSend) when record(C, transient_decision) ->
+ Acc2 = add_decision(To, C, Acc),
+ arrange(ToNodes, C, Acc2, ForceSend);
+
+arrange([_To | _ToNodes], {mnesia_down, _Node, _Date, _Time}, Acc, _ForceSend) ->
+ %% The others have their own info about this
+ Acc;
+
+arrange([_To | _ToNodes], {master_nodes, _Tab, _Nodes}, Acc, _ForceSend) ->
+ %% The others have their own info about this
+ Acc;
+
+arrange([To | ToNodes], {trans_tid, serial, Serial}, Acc, ForceSend) ->
+ %% Do the lamport thing plus release the others
+ %% from uncertainity.
+ Acc2 = add_decision(To, {trans_tid, serial, Serial}, Acc),
+ arrange(ToNodes, {trans_tid, serial, Serial}, Acc2, ForceSend);
+
+arrange([], _Decision, Acc, _ForceSend) ->
+ Acc.
+
+add_decision(Node, Decision, [{Node, Decisions} | Tail]) ->
+ [{Node, [Decision | Decisions]} | Tail];
+add_decision(Node, Decision, [Head | Tail]) ->
+ [Head | add_decision(Node, Decision, Tail)];
+add_decision(Node, Decision, []) ->
+ [{Node, [Decision]}].
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_registry.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_registry.erl
new file mode 100644
index 0000000000..a7e65506fa
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_registry.erl
@@ -0,0 +1,276 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_registry.erl,v 1.2 2010/03/04 13:54:19 maria Exp $
+%%
+-module(mnesia_registry).
+
+%%%----------------------------------------------------------------------
+%%% File : mnesia_registry.erl
+%%% Purpose : Support dump and restore of a registry on a C-node
+%%% This is an OTP internal module and is not public available.
+%%%
+%%% Example : Dump some hardcoded records into the Mnesia table Tab
+%%%
+%%% case rpc:call(Node, mnesia_registry, start_dump, [Tab, self()]) of
+%%% Pid when pid(Pid) ->
+%%% Pid ! {write, key1, key_size1, val_type1, val_size1, val1},
+%%% Pid ! {delete, key3},
+%%% Pid ! {write, key2, key_size2, val_type2, val_size2, val2},
+%%% Pid ! {write, key4, key_size4, val_type4, val_size4, val4},
+%%% Pid ! {commit, self()},
+%%% receive
+%%% {ok, Pid} ->
+%%% ok;
+%%% {'EXIT', Pid, Reason} ->
+%%% exit(Reason)
+%%% end;
+%%% {badrpc, Reason} ->
+%%% exit(Reason)
+%%% end.
+%%%
+%%% Example : Restore the corresponding Mnesia table Tab
+%%%
+%%% case rpc:call(Node, mnesia_registry, start_restore, [Tab, self()]) of
+%%% {size, Pid, N, LargestKey, LargestVal} ->
+%%% Pid ! {send_records, self()},
+%%% Fun = fun() ->
+%%% receive
+%%% {restore, KeySize, ValSize, ValType, Key, Val} ->
+%%% {Key, Val};
+%%% {'EXIT', Pid, Reason} ->
+%%% exit(Reason)
+%%% end
+%%% end,
+%%% lists:map(Fun, lists:seq(1, N));
+%%% {badrpc, Reason} ->
+%%% exit(Reason)
+%%% end.
+%%%
+%%%----------------------------------------------------------------------
+
+%% External exports
+-export([start_dump/2, start_restore/2]).
+-export([create_table/1, create_table/2]).
+
+%% Internal exports
+-export([init/4]).
+
+-record(state, {table, ops = [], link_to}).
+
+-record(registry_entry, {key, key_size, val_type, val_size, val}).
+
+-record(size, {pid = self(), n_values = 0, largest_key = 0, largest_val = 0}).
+
+%%%----------------------------------------------------------------------
+%%% Client
+%%%----------------------------------------------------------------------
+
+start(Type, Tab, LinkTo) ->
+ Starter = self(),
+ Args = [Type, Starter, LinkTo, Tab],
+ Pid = spawn_link(?MODULE, init, Args),
+ %% The receiver process may unlink the current process
+ receive
+ {ok, Res} ->
+ Res;
+ {'EXIT', Pid, Reason} when LinkTo == Starter ->
+ exit(Reason)
+ end.
+
+%% Starts a receiver process and optionally creates a Mnesia table
+%% with suitable default values. Returns the Pid of the receiver process
+%%
+%% The receiver process accumulates Mnesia operations and performs
+%% all operations or none at commit. The understood messages are:
+%%
+%% {write, Key, KeySize, ValType, ValSize, Val} ->
+%% accumulates mnesia:write({Tab, Key, KeySize, ValType, ValSize, Val})
+%% (no reply)
+%% {delete, Key} ->
+%% accumulates mnesia:delete({Tab, Key}) (no reply)
+%% {commit, ReplyTo} ->
+%% commits all accumulated operations
+%% and stops the process (replies {ok, Pid})
+%% abort ->
+%% stops the process (no reply)
+%%
+%% The receiver process is linked to the process with the process identifier
+%% LinkTo. If some error occurs the receiver process will invoke exit(Reason)
+%% and it is up to he LinkTo process to act properly when it receives an exit
+%% signal.
+
+start_dump(Tab, LinkTo) ->
+ start(dump, Tab, LinkTo).
+
+%% Starts a sender process which sends restore messages back to the
+%% LinkTo process. But first are some statistics about the table
+%% determined and returned as a 5-tuple:
+%%
+%% {size, SenderPid, N, LargestKeySize, LargestValSize}
+%%
+%% where N is the number of records in the table. Then the sender process
+%% waits for a 2-tuple message:
+%%
+%% {send_records, ReplyTo}
+%%
+%% At last N 6-tuple messages is sent to the ReplyTo process:
+%%
+%% ReplyTo ! {restore, KeySize, ValSize, ValType, Key, Val}
+%%
+%% If some error occurs the receiver process will invoke exit(Reason)
+%% and it is up to he LinkTo process to act properly when it receives an
+%% exit signal.
+
+start_restore(Tab, LinkTo) ->
+ start(restore, Tab, LinkTo).
+
+
+%% Optionally creates the Mnesia table Tab with suitable default values.
+%% Returns ok or EXIT's
+create_table(Tab) ->
+ Storage = mnesia:table_info(schema, storage_type),
+ create_table(Tab, [{Storage, [node()]}]).
+
+create_table(Tab, TabDef) ->
+ Attrs = record_info(fields, registry_entry),
+ case mnesia:create_table(Tab, [{attributes, Attrs} | TabDef]) of
+ {'atomic', ok} ->
+ ok;
+ {aborted, {already_exists, Tab}} ->
+ ok;
+ {aborted, Reason} ->
+ exit(Reason)
+ end.
+
+%%%----------------------------------------------------------------------
+%%% Server
+%%%----------------------------------------------------------------------
+
+init(Type, Starter, LinkTo, Tab) ->
+ if
+ LinkTo /= Starter ->
+ link(LinkTo),
+ unlink(Starter);
+ true ->
+ ignore
+ end,
+ case Type of
+ dump ->
+ Starter ! {ok, self()},
+ dump_loop(#state{table = Tab, link_to = LinkTo});
+ restore ->
+ restore_table(Tab, Starter, LinkTo)
+ end.
+
+%%%----------------------------------------------------------------------
+%%% Dump loop
+%%%----------------------------------------------------------------------
+
+dump_loop(S) ->
+ Tab = S#state.table,
+ Ops = S#state.ops,
+ receive
+ {write, Key, KeySize, ValType, ValSize, Val} ->
+ RE = #registry_entry{key = Key,
+ key_size = KeySize,
+ val_type = ValType,
+ val_size = ValSize,
+ val = Val},
+ dump_loop(S#state{ops = [{write, RE} | Ops]});
+ {delete, Key} ->
+ dump_loop(S#state{ops = [{delete, Key} | Ops]});
+ {commit, ReplyTo} ->
+ create_table(Tab),
+ RecName = mnesia:table_info(Tab, record_name),
+ %% The Ops are in reverse order, but there is no need
+ %% for reversing the list of accumulated operations
+ case mnesia:transaction(fun handle_ops/3, [Tab, RecName, Ops]) of
+ {'atomic', ok} ->
+ ReplyTo ! {ok, self()},
+ stop(S#state.link_to);
+ {aborted, Reason} ->
+ exit({aborted, Reason})
+ end;
+ abort ->
+ stop(S#state.link_to);
+ BadMsg ->
+ exit({bad_message, BadMsg})
+ end.
+
+stop(LinkTo) ->
+ unlink(LinkTo),
+ exit(normal).
+
+%% Grab a write lock for the entire table
+%% and iterate over all accumulated operations
+handle_ops(Tab, RecName, Ops) ->
+ mnesia:write_lock_table(Tab),
+ do_handle_ops(Tab, RecName, Ops).
+
+do_handle_ops(Tab, RecName, [{write, RegEntry} | Ops]) ->
+ Record = setelement(1, RegEntry, RecName),
+ mnesia:write(Tab, Record, write),
+ do_handle_ops(Tab, RecName, Ops);
+do_handle_ops(Tab, RecName, [{delete, Key} | Ops]) ->
+ mnesia:delete(Tab, Key, write),
+ do_handle_ops(Tab, RecName, Ops);
+do_handle_ops(_Tab, _RecName, []) ->
+ ok.
+
+%%%----------------------------------------------------------------------
+%%% Restore table
+%%%----------------------------------------------------------------------
+
+restore_table(Tab, Starter, LinkTo) ->
+ Pat = mnesia:table_info(Tab, wild_pattern),
+ Fun = fun() -> mnesia:match_object(Tab, Pat, read) end,
+ case mnesia:transaction(Fun) of
+ {'atomic', AllRecords} ->
+ Size = calc_size(AllRecords, #size{}),
+ Starter ! {ok, Size},
+ receive
+ {send_records, ReplyTo} ->
+ send_records(AllRecords, ReplyTo),
+ unlink(LinkTo),
+ exit(normal);
+ BadMsg ->
+ exit({bad_message, BadMsg})
+ end;
+ {aborted, Reason} ->
+ exit(Reason)
+ end.
+
+calc_size([H | T], S) ->
+ KeySize = max(element(#registry_entry.key_size, H), S#size.largest_key),
+ ValSize = max(element(#registry_entry.val_size, H), S#size.largest_val),
+ N = S#size.n_values + 1,
+ calc_size(T, S#size{n_values = N, largest_key = KeySize, largest_val = ValSize});
+calc_size([], Size) ->
+ Size.
+
+max(New, Old) when New > Old -> New;
+max(_New, Old) -> Old.
+
+send_records([H | T], ReplyTo) ->
+ KeySize = element(#registry_entry.key_size, H),
+ ValSize = element(#registry_entry.val_size, H),
+ ValType = element(#registry_entry.val_type, H),
+ Key = element(#registry_entry.key, H),
+ Val = element(#registry_entry.val, H),
+ ReplyTo ! {restore, KeySize, ValSize, ValType, Key, Val},
+ send_records(T, ReplyTo);
+send_records([], _ReplyTo) ->
+ ok.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_schema.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_schema.erl
new file mode 100644
index 0000000000..395532e91b
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_schema.erl
@@ -0,0 +1,2898 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_schema.erl,v 1.2 2010/03/04 13:54:20 maria Exp $
+%%
+%% In this module we provide a number of explicit functions
+%% to maninpulate the schema. All these functions are called
+%% within a special schema transaction.
+%%
+%% We also have an init/1 function defined here, this func is
+%% used by mnesia:start() to initialize the entire schema.
+
+-module(mnesia_schema).
+
+-export([
+ add_snmp/2,
+ add_table_copy/3,
+ add_table_index/2,
+ arrange_restore/3,
+ attr_tab_to_pos/2,
+ attr_to_pos/2,
+ change_table_copy_type/3,
+ change_table_access_mode/2,
+ change_table_load_order/2,
+ change_table_frag/2,
+ clear_table/1,
+ create_table/1,
+ cs2list/1,
+ del_snmp/1,
+ del_table_copy/2,
+ del_table_index/2,
+ delete_cstruct/2,
+ delete_schema/1,
+ delete_schema2/0,
+ delete_table/1,
+ delete_table_property/2,
+ dump_tables/1,
+ ensure_no_schema/1,
+ get_create_list/1,
+ get_initial_schema/2,
+ get_table_properties/1,
+ info/0,
+ info/1,
+ init/1,
+ insert_cstruct/3,
+ is_remote_member/1,
+ list2cs/1,
+ lock_schema/0,
+ lock_del_table/4, % Spawned
+ merge_schema/0,
+ move_table/3,
+ opt_create_dir/2,
+ prepare_commit/3,
+ purge_dir/2,
+ purge_tmp_files/0,
+ ram_delete_table/2,
+% ram_delete_table/3,
+ read_cstructs_from_disc/0,
+ read_nodes/0,
+ remote_read_schema/0,
+ restore/1,
+ restore/2,
+ restore/3,
+ schema_coordinator/3,
+ set_where_to_read/3,
+ transform_table/4,
+ undo_prepare_commit/2,
+ unlock_schema/0,
+ version/0,
+ write_table_property/2
+ ]).
+
+%% Exports for mnesia_frag
+-export([
+ get_tid_ts_and_lock/2,
+ make_create_table/1,
+ ensure_active/1,
+ pick/4,
+ verify/3,
+ incr_version/1,
+ check_keys/3,
+ check_duplicates/2,
+ make_delete_table/2
+ ]).
+
+%% Needed outside to be able to use/set table_properties
+%% from user (not supported)
+-export([schema_transaction/1,
+ insert_schema_ops/2,
+ do_create_table/1,
+ do_delete_table/1,
+ do_delete_table_property/2,
+ do_write_table_property/2]).
+
+-include("mnesia.hrl").
+-include_lib("kernel/include/file.hrl").
+
+-import(mnesia_lib, [set/2, del/2, verbose/2, dbg_out/2]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Here comes the init function which also resides in
+%% this module, it is called upon by the trans server
+%% at startup of the system
+%%
+%% We have a meta table which looks like
+%% {table, schema,
+%% {type, set},
+%% {disc_copies, all},
+%% {arity, 2}
+%% {attributes, [key, val]}
+%%
+%% This means that we have a series of {schema, Name, Cs} tuples
+%% in a table called schema !!
+
+init(IgnoreFallback) ->
+ Res = read_schema(true, false, IgnoreFallback),
+ {ok, Source, _CreateList} = exit_on_error(Res),
+ verbose("Schema initiated from: ~p~n", [Source]),
+ set({schema, tables}, []),
+ set({schema, local_tables}, []),
+ Tabs = set_schema(?ets_first(schema)),
+ lists:foreach(fun(Tab) -> clear_whereabouts(Tab) end, Tabs),
+ set({schema, where_to_read}, node()),
+ set({schema, load_node}, node()),
+ set({schema, load_reason}, initial),
+ mnesia_controller:add_active_replica(schema, node()).
+
+exit_on_error({error, Reason}) ->
+ exit(Reason);
+exit_on_error(GoodRes) ->
+ GoodRes.
+
+val(Var) ->
+ case ?catch_val(Var) of
+ {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
+ Value -> Value
+ end.
+
+%% This function traverses all cstructs in the schema and
+%% sets all values in mnesia_gvar accordingly for each table/cstruct
+
+set_schema('$end_of_table') ->
+ [];
+set_schema(Tab) ->
+ do_set_schema(Tab),
+ [Tab | set_schema(?ets_next(schema, Tab))].
+
+get_create_list(Tab) ->
+ ?ets_lookup_element(schema, Tab, 3).
+
+do_set_schema(Tab) ->
+ List = get_create_list(Tab),
+ Cs = list2cs(List),
+ do_set_schema(Tab, Cs).
+
+do_set_schema(Tab, Cs) ->
+ Type = Cs#cstruct.type,
+ set({Tab, setorbag}, Type),
+ set({Tab, local_content}, Cs#cstruct.local_content),
+ set({Tab, ram_copies}, Cs#cstruct.ram_copies),
+ set({Tab, disc_copies}, Cs#cstruct.disc_copies),
+ set({Tab, disc_only_copies}, Cs#cstruct.disc_only_copies),
+ set({Tab, load_order}, Cs#cstruct.load_order),
+ set({Tab, access_mode}, Cs#cstruct.access_mode),
+ set({Tab, snmp}, Cs#cstruct.snmp),
+ set({Tab, user_properties}, Cs#cstruct.user_properties),
+ [set({Tab, user_property, element(1, P)}, P) || P <- Cs#cstruct.user_properties],
+ set({Tab, frag_properties}, Cs#cstruct.frag_properties),
+ mnesia_frag:set_frag_hash(Tab, Cs#cstruct.frag_properties),
+ set({Tab, attributes}, Cs#cstruct.attributes),
+ Arity = length(Cs#cstruct.attributes) + 1,
+ set({Tab, arity}, Arity),
+ RecName = Cs#cstruct.record_name,
+ set({Tab, record_name}, RecName),
+ set({Tab, record_validation}, {RecName, Arity, Type}),
+ set({Tab, wild_pattern}, wild(RecName, Arity)),
+ set({Tab, index}, Cs#cstruct.index),
+ %% create actual index tabs later
+ set({Tab, cookie}, Cs#cstruct.cookie),
+ set({Tab, version}, Cs#cstruct.version),
+ set({Tab, cstruct}, Cs),
+ Storage = mnesia_lib:schema_cs_to_storage_type(node(), Cs),
+ set({Tab, storage_type}, Storage),
+ mnesia_lib:add({schema, tables}, Tab),
+ Ns = mnesia_lib:cs_to_nodes(Cs),
+ case lists:member(node(), Ns) of
+ true ->
+ mnesia_lib:add({schema, local_tables}, Tab);
+ false when Tab == schema ->
+ mnesia_lib:add({schema, local_tables}, Tab);
+ false ->
+ ignore
+ end.
+
+wild(RecName, Arity) ->
+ Wp0 = list_to_tuple(lists:duplicate(Arity, '_')),
+ setelement(1, Wp0, RecName).
+
+%% Temporarily read the local schema and return a list
+%% of all nodes mentioned in the schema.DAT file
+read_nodes() ->
+ %% Ensure that we access the intended Mnesia
+ %% directory. This function may not be called
+ %% during startup since it will cause the
+ %% application_controller to get into deadlock
+ case mnesia_lib:ensure_loaded(?APPLICATION) of
+ ok ->
+ case read_schema(false, false) of
+ {ok, _Source, CreateList} ->
+ Cs = list2cs(CreateList),
+ {ok, Cs#cstruct.disc_copies ++ Cs#cstruct.ram_copies};
+ {error, Reason} ->
+ {error, Reason}
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+%% Returns Version from the tuple {Version,MasterNodes}
+version() ->
+ case read_schema(false, false) of
+ {ok, Source, CreateList} when Source /= default ->
+ Cs = list2cs(CreateList),
+ {Version, _Details} = Cs#cstruct.version,
+ Version;
+ _ ->
+ case dir_exists(mnesia_lib:dir()) of
+ true -> {1,0};
+ false -> {0,0}
+ end
+ end.
+
+%% Calculate next table version from old cstruct
+incr_version(Cs) ->
+ {{Major, Minor}, _} = Cs#cstruct.version,
+ Nodes = mnesia_lib:intersect(val({schema, disc_copies}),
+ mnesia_lib:cs_to_nodes(Cs)),
+ V =
+ case Nodes -- val({Cs#cstruct.name, active_replicas}) of
+ [] -> {Major + 1, 0}; % All replicas are active
+ _ -> {Major, Minor + 1} % Some replicas are inactive
+ end,
+ Cs#cstruct{version = {V, {node(), now()}}}.
+
+%% Returns table name
+insert_cstruct(Tid, Cs, KeepWhereabouts) ->
+ Tab = Cs#cstruct.name,
+ TabDef = cs2list(Cs),
+ Val = {schema, Tab, TabDef},
+ mnesia_checkpoint:tm_retain(Tid, schema, Tab, write),
+ mnesia_subscr:report_table_event(schema, Tid, Val, write),
+ Active = val({Tab, active_replicas}),
+
+ case KeepWhereabouts of
+ true ->
+ ignore;
+ false when Active == [] ->
+ clear_whereabouts(Tab);
+ false ->
+ %% Someone else has initiated table
+ ignore
+ end,
+ set({Tab, cstruct}, Cs),
+ ?ets_insert(schema, Val),
+ do_set_schema(Tab, Cs),
+ Val.
+
+clear_whereabouts(Tab) ->
+ set({Tab, checkpoints}, []),
+ set({Tab, subscribers}, []),
+ set({Tab, where_to_read}, nowhere),
+ set({Tab, active_replicas}, []),
+ set({Tab, commit_work}, []),
+ set({Tab, where_to_write}, []),
+ set({Tab, where_to_commit}, []),
+ set({Tab, load_by_force}, false),
+ set({Tab, load_node}, unknown),
+ set({Tab, load_reason}, unknown).
+
+%% Returns table name
+delete_cstruct(Tid, Cs) ->
+ Tab = Cs#cstruct.name,
+ TabDef = cs2list(Cs),
+ Val = {schema, Tab, TabDef},
+ mnesia_checkpoint:tm_retain(Tid, schema, Tab, delete),
+ mnesia_subscr:report_table_event(schema, Tid, Val, delete),
+ ?ets_match_delete(mnesia_gvar, {{Tab, '_'}, '_'}),
+ ?ets_match_delete(mnesia_gvar, {{Tab, '_', '_'}, '_'}),
+ del({schema, local_tables}, Tab),
+ del({schema, tables}, Tab),
+ ?ets_delete(schema, Tab),
+ Val.
+
+%% Delete the Mnesia directory on all given nodes
+%% Requires that Mnesia is not running anywhere
+%% Returns ok | {error,Reason}
+delete_schema(Ns) when list(Ns), Ns /= [] ->
+ RunningNs = mnesia_lib:running_nodes(Ns),
+ Reason = "Cannot delete schema on all nodes",
+ if
+ RunningNs == [] ->
+ case rpc:multicall(Ns, ?MODULE, delete_schema2, []) of
+ {Replies, []} ->
+ case [R || R <- Replies, R /= ok] of
+ [] ->
+ ok;
+ BadReplies ->
+ verbose("~s: ~p~n", [Reason, BadReplies]),
+ {error, {"All nodes not running", BadReplies}}
+ end;
+ {_Replies, BadNs} ->
+ verbose("~s: ~p~n", [Reason, BadNs]),
+ {error, {"All nodes not running", BadNs}}
+ end;
+ true ->
+ verbose("~s: ~p~n", [Reason, RunningNs]),
+ {error, {"Mnesia is not stopped everywhere", RunningNs}}
+ end;
+delete_schema(Ns) ->
+ {error, {badarg, Ns}}.
+
+delete_schema2() ->
+ %% Ensure that we access the intended Mnesia
+ %% directory. This function may not be called
+ %% during startup since it will cause the
+ %% application_controller to get into deadlock
+ case mnesia_lib:ensure_loaded(?APPLICATION) of
+ ok ->
+ case mnesia_lib:is_running() of
+ no ->
+ Dir = mnesia_lib:dir(),
+ purge_dir(Dir, []),
+ ok;
+ _ ->
+ {error, {"Mnesia still running", node()}}
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+ensure_no_schema([H|T]) when atom(H) ->
+ case rpc:call(H, ?MODULE, remote_read_schema, []) of
+ {badrpc, Reason} ->
+ {H, {"All nodes not running", H, Reason}};
+ {ok,Source, _} when Source /= default ->
+ {H, {already_exists, H}};
+ _ ->
+ ensure_no_schema(T)
+ end;
+ensure_no_schema([H|_]) ->
+ {error,{badarg, H}};
+ensure_no_schema([]) ->
+ ok.
+
+remote_read_schema() ->
+ %% Ensure that we access the intended Mnesia
+ %% directory. This function may not be called
+ %% during startup since it will cause the
+ %% application_controller to get into deadlock
+ case mnesia_lib:ensure_loaded(?APPLICATION) of
+ ok ->
+ case mnesia_monitor:get_env(schema_location) of
+ opt_disc ->
+ read_schema(false, true);
+ _ ->
+ read_schema(false, false)
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+dir_exists(Dir) ->
+ dir_exists(Dir, mnesia_monitor:use_dir()).
+dir_exists(Dir, true) ->
+ case file:read_file_info(Dir) of
+ {ok, _} -> true;
+ _ -> false
+ end;
+dir_exists(_Dir, false) ->
+ false.
+
+opt_create_dir(UseDir, Dir) when UseDir == true->
+ case dir_exists(Dir, UseDir) of
+ true ->
+ check_can_write(Dir);
+ false ->
+ case file:make_dir(Dir) of
+ ok ->
+ verbose("Create Directory ~p~n", [Dir]),
+ ok;
+ {error, Reason} ->
+ verbose("Cannot create mnesia dir ~p~n", [Reason]),
+ {error, {"Cannot create Mnesia dir", Dir, Reason}}
+ end
+ end;
+opt_create_dir(false, _) ->
+ {error, {has_no_disc, node()}}.
+
+check_can_write(Dir) ->
+ case file:read_file_info(Dir) of
+ {ok, FI} when FI#file_info.type == directory,
+ FI#file_info.access == read_write ->
+ ok;
+ {ok, _} ->
+ {error, "Not allowed to write in Mnesia dir", Dir};
+ _ ->
+ {error, "Non existent Mnesia dir", Dir}
+ end.
+
+lock_schema() ->
+ mnesia_lib:lock_table(schema).
+
+unlock_schema() ->
+ mnesia_lib:unlock_table(schema).
+
+read_schema(Keep, _UseDirAnyway) ->
+ read_schema(Keep, false, false).
+
+%% The schema may be read for several reasons.
+%% If Mnesia is not already started the read intention
+%% we normally do not want the ets table named schema
+%% be left around.
+%% If Keep == true, the ets table schema is kept
+%% If Keep == false, the ets table schema is removed
+%%
+%% Returns {ok, Source, SchemaCstruct} or {error, Reason}
+%% Source may be: default | ram | disc | fallback
+
+read_schema(Keep, UseDirAnyway, IgnoreFallback) ->
+ lock_schema(),
+ Res =
+ case mnesia:system_info(is_running) of
+ yes ->
+ {ok, ram, get_create_list(schema)};
+ _IsRunning ->
+ case mnesia_monitor:use_dir() of
+ true ->
+ read_disc_schema(Keep, IgnoreFallback);
+ false when UseDirAnyway == true ->
+ read_disc_schema(Keep, IgnoreFallback);
+ false when Keep == true ->
+ Args = [{keypos, 2}, public, named_table, set],
+ mnesia_monitor:mktab(schema, Args),
+ CreateList = get_initial_schema(ram_copies, []),
+ ?ets_insert(schema,{schema, schema, CreateList}),
+ {ok, default, CreateList};
+ false when Keep == false ->
+ CreateList = get_initial_schema(ram_copies, []),
+ {ok, default, CreateList}
+ end
+ end,
+ unlock_schema(),
+ Res.
+
+read_disc_schema(Keep, IgnoreFallback) ->
+ Running = mnesia:system_info(is_running),
+ case mnesia_bup:fallback_exists() of
+ true when IgnoreFallback == false, Running /= yes ->
+ mnesia_bup:fallback_to_schema();
+ _ ->
+ %% If we're running, we read the schema file even
+ %% if fallback exists
+ Dat = mnesia_lib:tab2dat(schema),
+ case mnesia_lib:exists(Dat) of
+ true ->
+ do_read_disc_schema(Dat, Keep);
+ false ->
+ Dmp = mnesia_lib:tab2dmp(schema),
+ case mnesia_lib:exists(Dmp) of
+ true ->
+ %% May only happen when toggling of
+ %% schema storage type has been
+ %% interrupted
+ do_read_disc_schema(Dmp, Keep);
+ false ->
+ {error, "No schema file exists"}
+ end
+ end
+ end.
+
+do_read_disc_schema(Fname, Keep) ->
+ T =
+ case Keep of
+ false ->
+ Args = [{keypos, 2}, public, set],
+ ?ets_new_table(schema, Args);
+ true ->
+ Args = [{keypos, 2}, public, named_table, set],
+ mnesia_monitor:mktab(schema, Args)
+ end,
+ Repair = mnesia_monitor:get_env(auto_repair),
+ Res = % BUGBUG Fixa till dcl!
+ case mnesia_lib:dets_to_ets(schema, T, Fname, set, Repair, no) of
+ loaded -> {ok, disc, ?ets_lookup_element(T, schema, 3)};
+ Other -> {error, {"Cannot read schema", Fname, Other}}
+ end,
+ case Keep of
+ true -> ignore;
+ false -> ?ets_delete_table(T)
+ end,
+ Res.
+
+get_initial_schema(SchemaStorage, Nodes) ->
+ Cs = #cstruct{name = schema,
+ record_name = schema,
+ attributes = [table, cstruct]},
+ Cs2 =
+ case SchemaStorage of
+ ram_copies -> Cs#cstruct{ram_copies = Nodes};
+ disc_copies -> Cs#cstruct{disc_copies = Nodes}
+ end,
+ cs2list(Cs2).
+
+read_cstructs_from_disc() ->
+ %% Assumptions:
+ %% - local schema lock in global
+ %% - use_dir is true
+ %% - Mnesia is not running
+ %% - Ignore fallback
+
+ Fname = mnesia_lib:tab2dat(schema),
+ case mnesia_lib:exists(Fname) of
+ true ->
+ Args = [{file, Fname},
+ {keypos, 2},
+ {repair, mnesia_monitor:get_env(auto_repair)},
+ {type, set}],
+ case dets:open_file(make_ref(), Args) of
+ {ok, Tab} ->
+ Fun = fun({_, _, List}) ->
+ {continue, list2cs(List)}
+ end,
+ Cstructs = dets:traverse(Tab, Fun),
+ dets:close(Tab),
+ {ok, Cstructs};
+ {error, Reason} ->
+ {error, Reason}
+ end;
+ false ->
+ {error, "No schema file exists"}
+ end.
+
+%% We run a very special type of transactions when we
+%% we want to manipulate the schema.
+
+get_tid_ts_and_lock(Tab, Intent) ->
+ TidTs = get(mnesia_activity_state),
+ case TidTs of
+ {_Mod, Tid, Ts} when record(Ts, tidstore)->
+ Store = Ts#tidstore.store,
+ case Intent of
+ read -> mnesia_locker:rlock_table(Tid, Store, Tab);
+ write -> mnesia_locker:wlock_table(Tid, Store, Tab);
+ none -> ignore
+ end,
+ TidTs;
+ _ ->
+ mnesia:abort(no_transaction)
+ end.
+
+schema_transaction(Fun) ->
+ case get(mnesia_activity_state) of
+ undefined ->
+ Args = [self(), Fun, whereis(mnesia_controller)],
+ Pid = spawn_link(?MODULE, schema_coordinator, Args),
+ receive
+ {transaction_done, Res, Pid} -> Res;
+ {'EXIT', Pid, R} -> {aborted, {transaction_crashed, R}}
+ end;
+ _ ->
+ {aborted, nested_transaction}
+ end.
+
+%% This process may dump the transaction log, and should
+%% therefore not be run in an application process
+%%
+schema_coordinator(Client, _Fun, undefined) ->
+ Res = {aborted, {node_not_running, node()}},
+ Client ! {transaction_done, Res, self()},
+ unlink(Client);
+
+schema_coordinator(Client, Fun, Controller) when pid(Controller) ->
+ %% Do not trap exit in order to automatically die
+ %% when the controller dies
+
+ link(Controller),
+ unlink(Client),
+
+ %% Fulfull the transaction even if the client dies
+ Res = mnesia:transaction(Fun),
+ Client ! {transaction_done, Res, self()},
+ unlink(Controller), % Avoids spurious exit message
+ unlink(whereis(mnesia_tm)), % Avoids spurious exit message
+ exit(normal).
+
+%% The make* rotines return a list of ops, this function
+%% inserts em all in the Store and maintains the local order
+%% of ops.
+
+insert_schema_ops({_Mod, _Tid, Ts}, SchemaIOps) ->
+ do_insert_schema_ops(Ts#tidstore.store, SchemaIOps).
+
+do_insert_schema_ops(Store, [Head | Tail]) ->
+ ?ets_insert(Store, Head),
+ do_insert_schema_ops(Store, Tail);
+do_insert_schema_ops(_Store, []) ->
+ ok.
+
+cs2list(Cs) when record(Cs, cstruct) ->
+ Tags = record_info(fields, cstruct),
+ rec2list(Tags, 2, Cs);
+cs2list(CreateList) when list(CreateList) ->
+ CreateList.
+
+rec2list([Tag | Tags], Pos, Rec) ->
+ Val = element(Pos, Rec),
+ [{Tag, Val} | rec2list(Tags, Pos + 1, Rec)];
+rec2list([], _Pos, _Rec) ->
+ [].
+
+list2cs(List) when list(List) ->
+ Name = pick(unknown, name, List, must),
+ Type = pick(Name, type, List, set),
+ Rc0 = pick(Name, ram_copies, List, []),
+ Dc = pick(Name, disc_copies, List, []),
+ Doc = pick(Name, disc_only_copies, List, []),
+ Rc = case {Rc0, Dc, Doc} of
+ {[], [], []} -> [node()];
+ _ -> Rc0
+ end,
+ LC = pick(Name, local_content, List, false),
+ RecName = pick(Name, record_name, List, Name),
+ Attrs = pick(Name, attributes, List, [key, val]),
+ Snmp = pick(Name, snmp, List, []),
+ LoadOrder = pick(Name, load_order, List, 0),
+ AccessMode = pick(Name, access_mode, List, read_write),
+ UserProps = pick(Name, user_properties, List, []),
+ verify({alt, [nil, list]}, mnesia_lib:etype(UserProps),
+ {bad_type, Name, {user_properties, UserProps}}),
+ Cookie = pick(Name, cookie, List, ?unique_cookie),
+ Version = pick(Name, version, List, {{2, 0}, []}),
+ Ix = pick(Name, index, List, []),
+ verify({alt, [nil, list]}, mnesia_lib:etype(Ix),
+ {bad_type, Name, {index, [Ix]}}),
+ Ix2 = [attr_to_pos(I, Attrs) || I <- Ix],
+
+ Frag = pick(Name, frag_properties, List, []),
+ verify({alt, [nil, list]}, mnesia_lib:etype(Frag),
+ {badarg, Name, {frag_properties, Frag}}),
+
+ Keys = check_keys(Name, List, record_info(fields, cstruct)),
+ check_duplicates(Name, Keys),
+ #cstruct{name = Name,
+ ram_copies = Rc,
+ disc_copies = Dc,
+ disc_only_copies = Doc,
+ type = Type,
+ index = Ix2,
+ snmp = Snmp,
+ load_order = LoadOrder,
+ access_mode = AccessMode,
+ local_content = LC,
+ record_name = RecName,
+ attributes = Attrs,
+ user_properties = lists:sort(UserProps),
+ frag_properties = lists:sort(Frag),
+ cookie = Cookie,
+ version = Version};
+list2cs(Other) ->
+ mnesia:abort({badarg, Other}).
+
+pick(Tab, Key, List, Default) ->
+ case lists:keysearch(Key, 1, List) of
+ false when Default == must ->
+ mnesia:abort({badarg, Tab, "Missing key", Key, List});
+ false ->
+ Default;
+ {value, {Key, Value}} ->
+ Value;
+ {value, BadArg} ->
+ mnesia:abort({bad_type, Tab, BadArg})
+ end.
+
+%% Convert attribute name to integer if neccessary
+attr_tab_to_pos(_Tab, Pos) when integer(Pos) ->
+ Pos;
+attr_tab_to_pos(Tab, Attr) ->
+ attr_to_pos(Attr, val({Tab, attributes})).
+
+%% Convert attribute name to integer if neccessary
+attr_to_pos(Pos, _Attrs) when integer(Pos) ->
+ Pos;
+attr_to_pos(Attr, Attrs) when atom(Attr) ->
+ attr_to_pos(Attr, Attrs, 2);
+attr_to_pos(Attr, _) ->
+ mnesia:abort({bad_type, Attr}).
+
+attr_to_pos(Attr, [Attr | _Attrs], Pos) ->
+ Pos;
+attr_to_pos(Attr, [_ | Attrs], Pos) ->
+ attr_to_pos(Attr, Attrs, Pos + 1);
+attr_to_pos(Attr, _, _) ->
+ mnesia:abort({bad_type, Attr}).
+
+check_keys(Tab, [{Key, _Val} | Tail], Items) ->
+ case lists:member(Key, Items) of
+ true -> [Key | check_keys(Tab, Tail, Items)];
+ false -> mnesia:abort({badarg, Tab, Key})
+ end;
+check_keys(_, [], _) ->
+ [];
+check_keys(Tab, Arg, _) ->
+ mnesia:abort({badarg, Tab, Arg}).
+
+check_duplicates(Tab, Keys) ->
+ case has_duplicates(Keys) of
+ false -> ok;
+ true -> mnesia:abort({badarg, Tab, "Duplicate keys", Keys})
+ end.
+
+has_duplicates([H | T]) ->
+ case lists:member(H, T) of
+ true -> true;
+ false -> has_duplicates(T)
+ end;
+has_duplicates([]) ->
+ false.
+
+%% This is the only place where we check the validity of data
+verify_cstruct(Cs) when record(Cs, cstruct) ->
+ verify_nodes(Cs),
+
+ Tab = Cs#cstruct.name,
+ verify(atom, mnesia_lib:etype(Tab), {bad_type, Tab}),
+ Type = Cs#cstruct.type,
+ verify(true, lists:member(Type, [set, bag, ordered_set]),
+ {bad_type, Tab, {type, Type}}),
+
+ %% Currently ordered_set is not supported for disk_only_copies.
+ if
+ Type == ordered_set, Cs#cstruct.disc_only_copies /= [] ->
+ mnesia:abort({bad_type, Tab, {not_supported, Type, disc_only_copies}});
+ true ->
+ ok
+ end,
+
+ RecName = Cs#cstruct.record_name,
+ verify(atom, mnesia_lib:etype(RecName),
+ {bad_type, Tab, {record_name, RecName}}),
+
+ Attrs = Cs#cstruct.attributes,
+ verify(list, mnesia_lib:etype(Attrs),
+ {bad_type, Tab, {attributes, Attrs}}),
+
+ Arity = length(Attrs) + 1,
+ verify(true, Arity > 2, {bad_type, Tab, {attributes, Attrs}}),
+
+ lists:foldl(fun(Attr,_Other) when Attr == snmp ->
+ mnesia:abort({bad_type, Tab, {attributes, [Attr]}});
+ (Attr,Other) ->
+ verify(atom, mnesia_lib:etype(Attr),
+ {bad_type, Tab, {attributes, [Attr]}}),
+ verify(false, lists:member(Attr, Other),
+ {combine_error, Tab, {attributes, [Attr | Other]}}),
+ [Attr | Other]
+ end,
+ [],
+ Attrs),
+
+ Index = Cs#cstruct.index,
+ verify({alt, [nil, list]}, mnesia_lib:etype(Index),
+ {bad_type, Tab, {index, Index}}),
+
+ IxFun =
+ fun(Pos) ->
+ verify(true, fun() ->
+ if
+ integer(Pos),
+ Pos > 2,
+ Pos =< Arity ->
+ true;
+ true -> false
+ end
+ end,
+ {bad_type, Tab, {index, [Pos]}})
+ end,
+ lists:foreach(IxFun, Index),
+
+ LC = Cs#cstruct.local_content,
+ verify({alt, [true, false]}, LC,
+ {bad_type, Tab, {local_content, LC}}),
+ Access = Cs#cstruct.access_mode,
+ verify({alt, [read_write, read_only]}, Access,
+ {bad_type, Tab, {access_mode, Access}}),
+
+ Snmp = Cs#cstruct.snmp,
+ verify(true, mnesia_snmp_hook:check_ustruct(Snmp),
+ {badarg, Tab, {snmp, Snmp}}),
+
+ CheckProp = fun(Prop) when tuple(Prop), size(Prop) >= 1 -> ok;
+ (Prop) -> mnesia:abort({bad_type, Tab, {user_properties, [Prop]}})
+ end,
+ lists:foreach(CheckProp, Cs#cstruct.user_properties),
+
+ case Cs#cstruct.cookie of
+ {{MegaSecs, Secs, MicroSecs}, _Node}
+ when integer(MegaSecs), integer(Secs),
+ integer(MicroSecs), atom(node) ->
+ ok;
+ Cookie ->
+ mnesia:abort({bad_type, Tab, {cookie, Cookie}})
+ end,
+ case Cs#cstruct.version of
+ {{Major, Minor}, _Detail}
+ when integer(Major), integer(Minor) ->
+ ok;
+ Version ->
+ mnesia:abort({bad_type, Tab, {version, Version}})
+ end.
+
+verify_nodes(Cs) ->
+ Tab = Cs#cstruct.name,
+ Ram = Cs#cstruct.ram_copies,
+ Disc = Cs#cstruct.disc_copies,
+ DiscOnly = Cs#cstruct.disc_only_copies,
+ LoadOrder = Cs#cstruct.load_order,
+
+ verify({alt, [nil, list]}, mnesia_lib:etype(Ram),
+ {bad_type, Tab, {ram_copies, Ram}}),
+ verify({alt, [nil, list]}, mnesia_lib:etype(Disc),
+ {bad_type, Tab, {disc_copies, Disc}}),
+ case Tab of
+ schema ->
+ verify([], DiscOnly, {bad_type, Tab, {disc_only_copies, DiscOnly}});
+ _ ->
+ verify({alt, [nil, list]},
+ mnesia_lib:etype(DiscOnly),
+ {bad_type, Tab, {disc_only_copies, DiscOnly}})
+ end,
+ verify(integer, mnesia_lib:etype(LoadOrder),
+ {bad_type, Tab, {load_order, LoadOrder}}),
+
+ Nodes = Ram ++ Disc ++ DiscOnly,
+ verify(list, mnesia_lib:etype(Nodes),
+ {combine_error, Tab,
+ [{ram_copies, []}, {disc_copies, []}, {disc_only_copies, []}]}),
+ verify(false, has_duplicates(Nodes), {combine_error, Tab, Nodes}),
+ AtomCheck = fun(N) -> verify(atom, mnesia_lib:etype(N), {bad_type, Tab, N}) end,
+ lists:foreach(AtomCheck, Nodes).
+
+verify(Expected, Fun, Error) when function(Fun) ->
+ do_verify(Expected, catch Fun(), Error);
+verify(Expected, Actual, Error) ->
+ do_verify(Expected, Actual, Error).
+
+do_verify({alt, Values}, Value, Error) ->
+ case lists:member(Value, Values) of
+ true -> ok;
+ false -> mnesia:abort(Error)
+ end;
+do_verify(Value, Value, _) ->
+ ok;
+do_verify(_Value, _, Error) ->
+ mnesia:abort(Error).
+
+ensure_writable(Tab) ->
+ case val({Tab, where_to_write}) of
+ [] -> mnesia:abort({read_only, Tab});
+ _ -> ok
+ end.
+
+%% Ensure that all replicas on disk full nodes are active
+ensure_active(Cs) ->
+ ensure_active(Cs, active_replicas).
+
+ensure_active(Cs, What) ->
+ Tab = Cs#cstruct.name,
+ case val({Tab, What}) of
+ [] -> mnesia:abort({no_exists, Tab});
+ _ -> ok
+ end,
+ Nodes = mnesia_lib:intersect(val({schema, disc_copies}),
+ mnesia_lib:cs_to_nodes(Cs)),
+ W = {Tab, What},
+ case Nodes -- val(W) of
+ [] ->
+ ok;
+ Ns ->
+ Expl = "All replicas on diskfull nodes are not active yet",
+ case val({Tab, local_content}) of
+ true ->
+ case rpc:multicall(Ns, ?MODULE, is_remote_member, [W]) of
+ {Replies, []} ->
+ check_active(Replies, Expl, Tab);
+ {_Replies, BadNs} ->
+ mnesia:abort({not_active, Expl, Tab, BadNs})
+ end;
+ false ->
+ mnesia:abort({not_active, Expl, Tab, Ns})
+ end
+ end.
+
+ensure_not_active(schema, Node) ->
+ case lists:member(Node, val({schema, active_replicas})) of
+ false ->
+ ok;
+ true ->
+ Expl = "Mnesia is running",
+ mnesia:abort({active, Expl, Node})
+ end.
+
+is_remote_member(Key) ->
+ IsActive = lists:member(node(), val(Key)),
+ {IsActive, node()}.
+
+check_active([{true, _Node} | Replies], Expl, Tab) ->
+ check_active(Replies, Expl, Tab);
+check_active([{false, Node} | _Replies], Expl, Tab) ->
+ mnesia:abort({not_active, Expl, Tab, [Node]});
+check_active([{badrpc, Reason} | _Replies], Expl, Tab) ->
+ mnesia:abort({not_active, Expl, Tab, Reason});
+check_active([], _Expl, _Tab) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Here's the real interface function to create a table
+
+create_table(TabDef) ->
+ schema_transaction(fun() -> do_multi_create_table(TabDef) end).
+
+%% And the corresponding do routines ....
+
+do_multi_create_table(TabDef) ->
+ get_tid_ts_and_lock(schema, write),
+ ensure_writable(schema),
+ Cs = list2cs(TabDef),
+ case Cs#cstruct.frag_properties of
+ [] ->
+ do_create_table(Cs);
+ _Props ->
+ CsList = mnesia_frag:expand_cstruct(Cs),
+ lists:foreach(fun do_create_table/1, CsList)
+ end,
+ ok.
+
+do_create_table(Cs) ->
+ {_Mod, _Tid, Ts} = get_tid_ts_and_lock(schema, none),
+ Store = Ts#tidstore.store,
+ do_insert_schema_ops(Store, make_create_table(Cs)).
+
+make_create_table(Cs) ->
+ Tab = Cs#cstruct.name,
+ verify('EXIT', element(1, ?catch_val({Tab, cstruct})),
+ {already_exists, Tab}),
+ unsafe_make_create_table(Cs).
+
+% unsafe_do_create_table(Cs) ->
+% {_Mod, Tid, Ts} = get_tid_ts_and_lock(schema, none),
+% Store = Ts#tidstore.store,
+% do_insert_schema_ops(Store, unsafe_make_create_table(Cs)).
+
+unsafe_make_create_table(Cs) ->
+ {_Mod, Tid, Ts} = get_tid_ts_and_lock(schema, none),
+ verify_cstruct(Cs),
+ Tab = Cs#cstruct.name,
+
+ %% Check that we have all disc replica nodes running
+ DiscNodes = Cs#cstruct.disc_copies ++ Cs#cstruct.disc_only_copies,
+ RunningNodes = val({current, db_nodes}),
+ CheckDisc = fun(N) ->
+ verify(true, lists:member(N, RunningNodes),
+ {not_active, Tab, N})
+ end,
+ lists:foreach(CheckDisc, DiscNodes),
+
+ Nodes = mnesia_lib:intersect(mnesia_lib:cs_to_nodes(Cs), RunningNodes),
+ Store = Ts#tidstore.store,
+ mnesia_locker:wlock_no_exist(Tid, Store, Tab, Nodes),
+ [{op, create_table, cs2list(Cs)}].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Delete a table entirely on all nodes.
+
+delete_table(Tab) ->
+ schema_transaction(fun() -> do_delete_table(Tab) end).
+
+do_delete_table(schema) ->
+ mnesia:abort({bad_type, schema});
+do_delete_table(Tab) ->
+ TidTs = get_tid_ts_and_lock(schema, write),
+ ensure_writable(schema),
+ insert_schema_ops(TidTs, make_delete_table(Tab, whole_table)).
+
+make_delete_table(Tab, Mode) ->
+ case Mode of
+ whole_table ->
+ case val({Tab, frag_properties}) of
+ [] ->
+ [make_delete_table2(Tab)];
+ _Props ->
+ %% Check if it is a base table
+ mnesia_frag:lookup_frag_hash(Tab),
+
+ %% Check for foreigners
+ F = mnesia_frag:lookup_foreigners(Tab),
+ verify([], F, {combine_error, Tab, "Too many foreigners", F}),
+ [make_delete_table2(T) || T <- mnesia_frag:frag_names(Tab)]
+ end;
+ single_frag ->
+ [make_delete_table2(Tab)]
+ end.
+
+make_delete_table2(Tab) ->
+ get_tid_ts_and_lock(Tab, write),
+ Cs = val({Tab, cstruct}),
+ ensure_active(Cs),
+ ensure_writable(Tab),
+ {op, delete_table, cs2list(Cs)}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Change fragmentation of a table
+
+change_table_frag(Tab, Change) ->
+ schema_transaction(fun() -> do_change_table_frag(Tab, Change) end).
+
+do_change_table_frag(Tab, Change) when atom(Tab), Tab /= schema ->
+ TidTs = get_tid_ts_and_lock(schema, write),
+ Ops = mnesia_frag:change_table_frag(Tab, Change),
+ [insert_schema_ops(TidTs, Op) || Op <- Ops],
+ ok;
+do_change_table_frag(Tab, _Change) ->
+ mnesia:abort({bad_type, Tab}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Clear a table
+
+clear_table(Tab) ->
+ schema_transaction(fun() -> do_clear_table(Tab) end).
+
+do_clear_table(schema) ->
+ mnesia:abort({bad_type, schema});
+do_clear_table(Tab) ->
+ TidTs = get_tid_ts_and_lock(schema, write),
+ get_tid_ts_and_lock(Tab, write),
+ insert_schema_ops(TidTs, make_clear_table(Tab)).
+
+make_clear_table(Tab) ->
+ ensure_writable(schema),
+ Cs = val({Tab, cstruct}),
+ ensure_active(Cs),
+ ensure_writable(Tab),
+ [{op, clear_table, cs2list(Cs)}].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+add_table_copy(Tab, Node, Storage) ->
+ schema_transaction(fun() -> do_add_table_copy(Tab, Node, Storage) end).
+
+do_add_table_copy(Tab, Node, Storage) when atom(Tab), atom(Node) ->
+ TidTs = get_tid_ts_and_lock(schema, write),
+ insert_schema_ops(TidTs, make_add_table_copy(Tab, Node, Storage));
+do_add_table_copy(Tab,Node,_) ->
+ mnesia:abort({badarg, Tab, Node}).
+
+make_add_table_copy(Tab, Node, Storage) ->
+ ensure_writable(schema),
+ Cs = incr_version(val({Tab, cstruct})),
+ Ns = mnesia_lib:cs_to_nodes(Cs),
+ verify(false, lists:member(Node, Ns), {already_exists, Tab, Node}),
+ Cs2 = new_cs(Cs, Node, Storage, add),
+ verify_cstruct(Cs2),
+
+ %% Check storage and if node is running
+ IsRunning = lists:member(Node, val({current, db_nodes})),
+ if
+ Storage == unknown ->
+ mnesia:abort({badarg, Tab, Storage});
+ Tab == schema ->
+ if
+ Storage /= ram_copies ->
+ mnesia:abort({badarg, Tab, Storage});
+ IsRunning == true ->
+ mnesia:abort({already_exists, Tab, Node});
+ true ->
+ ignore
+ end;
+ Storage == ram_copies ->
+ ignore;
+ IsRunning == true ->
+ ignore;
+ IsRunning == false ->
+ mnesia:abort({not_active, schema, Node})
+ end,
+ [{op, add_table_copy, Storage, Node, cs2list(Cs2)}].
+
+del_table_copy(Tab, Node) ->
+ schema_transaction(fun() -> do_del_table_copy(Tab, Node) end).
+
+do_del_table_copy(Tab, Node) when atom(Node) ->
+ TidTs = get_tid_ts_and_lock(schema, write),
+%% get_tid_ts_and_lock(Tab, write),
+ insert_schema_ops(TidTs, make_del_table_copy(Tab, Node));
+do_del_table_copy(Tab, Node) ->
+ mnesia:abort({badarg, Tab, Node}).
+
+make_del_table_copy(Tab, Node) ->
+ ensure_writable(schema),
+ Cs = incr_version(val({Tab, cstruct})),
+ Storage = mnesia_lib:schema_cs_to_storage_type(Node, Cs),
+ Cs2 = new_cs(Cs, Node, Storage, del),
+ case mnesia_lib:cs_to_nodes(Cs2) of
+ [] when Tab == schema ->
+ mnesia:abort({combine_error, Tab, "Last replica"});
+ [] ->
+ ensure_active(Cs),
+ dbg_out("Last replica deleted in table ~p~n", [Tab]),
+ make_delete_table(Tab, whole_table);
+ _ when Tab == schema ->
+ ensure_active(Cs2),
+ ensure_not_active(Tab, Node),
+ verify_cstruct(Cs2),
+ Ops = remove_node_from_tabs(val({schema, tables}), Node),
+ [{op, del_table_copy, ram_copies, Node, cs2list(Cs2)} | Ops];
+ _ ->
+ ensure_active(Cs),
+ verify_cstruct(Cs2),
+ [{op, del_table_copy, Storage, Node, cs2list(Cs2)}]
+ end.
+
+remove_node_from_tabs([], _Node) ->
+ [];
+remove_node_from_tabs([schema|Rest], Node) ->
+ remove_node_from_tabs(Rest, Node);
+remove_node_from_tabs([Tab|Rest], Node) ->
+ {Cs, IsFragModified} =
+ mnesia_frag:remove_node(Node, incr_version(val({Tab, cstruct}))),
+ case mnesia_lib:schema_cs_to_storage_type(Node, Cs) of
+ unknown ->
+ case IsFragModified of
+ true ->
+ [{op, change_table_frag, {del_node, Node}, cs2list(Cs)} |
+ remove_node_from_tabs(Rest, Node)];
+ false ->
+ remove_node_from_tabs(Rest, Node)
+ end;
+ Storage ->
+ Cs2 = new_cs(Cs, Node, Storage, del),
+ case mnesia_lib:cs_to_nodes(Cs2) of
+ [] ->
+ [{op, delete_table, cs2list(Cs)} |
+ remove_node_from_tabs(Rest, Node)];
+ _Ns ->
+ verify_cstruct(Cs2),
+ [{op, del_table_copy, ram_copies, Node, cs2list(Cs2)}|
+ remove_node_from_tabs(Rest, Node)]
+ end
+ end.
+
+new_cs(Cs, Node, ram_copies, add) ->
+ Cs#cstruct{ram_copies = opt_add(Node, Cs#cstruct.ram_copies)};
+new_cs(Cs, Node, disc_copies, add) ->
+ Cs#cstruct{disc_copies = opt_add(Node, Cs#cstruct.disc_copies)};
+new_cs(Cs, Node, disc_only_copies, add) ->
+ Cs#cstruct{disc_only_copies = opt_add(Node, Cs#cstruct.disc_only_copies)};
+new_cs(Cs, Node, ram_copies, del) ->
+ Cs#cstruct{ram_copies = lists:delete(Node , Cs#cstruct.ram_copies)};
+new_cs(Cs, Node, disc_copies, del) ->
+ Cs#cstruct{disc_copies = lists:delete(Node , Cs#cstruct.disc_copies)};
+new_cs(Cs, Node, disc_only_copies, del) ->
+ Cs#cstruct{disc_only_copies =
+ lists:delete(Node , Cs#cstruct.disc_only_copies)};
+new_cs(Cs, _Node, Storage, _Op) ->
+ mnesia:abort({badarg, Cs#cstruct.name, Storage}).
+
+
+opt_add(N, L) -> [N | lists:delete(N, L)].
+
+move_table(Tab, FromNode, ToNode) ->
+ schema_transaction(fun() -> do_move_table(Tab, FromNode, ToNode) end).
+
+do_move_table(schema, _FromNode, _ToNode) ->
+ mnesia:abort({bad_type, schema});
+do_move_table(Tab, FromNode, ToNode) when atom(FromNode), atom(ToNode) ->
+ TidTs = get_tid_ts_and_lock(schema, write),
+ insert_schema_ops(TidTs, make_move_table(Tab, FromNode, ToNode));
+do_move_table(Tab, FromNode, ToNode) ->
+ mnesia:abort({badarg, Tab, FromNode, ToNode}).
+
+make_move_table(Tab, FromNode, ToNode) ->
+ ensure_writable(schema),
+ Cs = incr_version(val({Tab, cstruct})),
+ Ns = mnesia_lib:cs_to_nodes(Cs),
+ verify(false, lists:member(ToNode, Ns), {already_exists, Tab, ToNode}),
+ verify(true, lists:member(FromNode, val({Tab, where_to_write})),
+ {not_active, Tab, FromNode}),
+ verify(false, val({Tab,local_content}),
+ {"Cannot move table with local content", Tab}),
+ ensure_active(Cs),
+ Running = val({current, db_nodes}),
+ Storage = mnesia_lib:schema_cs_to_storage_type(FromNode, Cs),
+ verify(true, lists:member(ToNode, Running), {not_active, schema, ToNode}),
+
+ Cs2 = new_cs(Cs, ToNode, Storage, add),
+ Cs3 = new_cs(Cs2, FromNode, Storage, del),
+ verify_cstruct(Cs3),
+ [{op, add_table_copy, Storage, ToNode, cs2list(Cs2)},
+ {op, sync_trans},
+ {op, del_table_copy, Storage, FromNode, cs2list(Cs3)}].
+
+%% end of functions to add and delete nodes to tables
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+
+change_table_copy_type(Tab, Node, ToS) ->
+ schema_transaction(fun() -> do_change_table_copy_type(Tab, Node, ToS) end).
+
+do_change_table_copy_type(Tab, Node, ToS) when atom(Node) ->
+ TidTs = get_tid_ts_and_lock(schema, write),
+ get_tid_ts_and_lock(Tab, write), % ensure global sync
+ %% get_tid_ts_and_lock(Tab, read),
+ insert_schema_ops(TidTs, make_change_table_copy_type(Tab, Node, ToS));
+do_change_table_copy_type(Tab, Node, _ToS) ->
+ mnesia:abort({badarg, Tab, Node}).
+
+make_change_table_copy_type(Tab, Node, unknown) ->
+ make_del_table_copy(Tab, Node);
+make_change_table_copy_type(Tab, Node, ToS) ->
+ ensure_writable(schema),
+ Cs = incr_version(val({Tab, cstruct})),
+ FromS = mnesia_lib:storage_type_at_node(Node, Tab),
+
+ case compare_storage_type(false, FromS, ToS) of
+ {same, _} ->
+ mnesia:abort({already_exists, Tab, Node, ToS});
+ {diff, _} ->
+ ignore;
+ incompatible ->
+ ensure_active(Cs)
+ end,
+
+ Cs2 = new_cs(Cs, Node, FromS, del),
+ Cs3 = new_cs(Cs2, Node, ToS, add),
+ verify_cstruct(Cs3),
+
+ if
+ FromS == unknown ->
+ make_add_table_copy(Tab, Node, ToS);
+ true ->
+ ignore
+ end,
+
+ [{op, change_table_copy_type, Node, FromS, ToS, cs2list(Cs3)}].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% change index functions ....
+%% Pos is allready added by 1 in both of these functions
+
+add_table_index(Tab, Pos) ->
+ schema_transaction(fun() -> do_add_table_index(Tab, Pos) end).
+
+do_add_table_index(schema, _Attr) ->
+ mnesia:abort({bad_type, schema});
+do_add_table_index(Tab, Attr) ->
+ TidTs = get_tid_ts_and_lock(schema, write),
+ get_tid_ts_and_lock(Tab, read),
+ Pos = attr_tab_to_pos(Tab, Attr),
+ insert_schema_ops(TidTs, make_add_table_index(Tab, Pos)).
+
+make_add_table_index(Tab, Pos) ->
+ ensure_writable(schema),
+ Cs = incr_version(val({Tab, cstruct})),
+ ensure_active(Cs),
+ Ix = Cs#cstruct.index,
+ verify(false, lists:member(Pos, Ix), {already_exists, Tab, Pos}),
+ Ix2 = lists:sort([Pos | Ix]),
+ Cs2 = Cs#cstruct{index = Ix2},
+ verify_cstruct(Cs2),
+ [{op, add_index, Pos, cs2list(Cs2)}].
+
+del_table_index(Tab, Pos) ->
+ schema_transaction(fun() -> do_del_table_index(Tab, Pos) end).
+
+do_del_table_index(schema, _Attr) ->
+ mnesia:abort({bad_type, schema});
+do_del_table_index(Tab, Attr) ->
+ TidTs = get_tid_ts_and_lock(schema, write),
+ get_tid_ts_and_lock(Tab, read),
+ Pos = attr_tab_to_pos(Tab, Attr),
+ insert_schema_ops(TidTs, make_del_table_index(Tab, Pos)).
+
+make_del_table_index(Tab, Pos) ->
+ ensure_writable(schema),
+ Cs = incr_version(val({Tab, cstruct})),
+ ensure_active(Cs),
+ Ix = Cs#cstruct.index,
+ verify(true, lists:member(Pos, Ix), {no_exists, Tab, Pos}),
+ Cs2 = Cs#cstruct{index = lists:delete(Pos, Ix)},
+ verify_cstruct(Cs2),
+ [{op, del_index, Pos, cs2list(Cs2)}].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+add_snmp(Tab, Ustruct) ->
+ schema_transaction(fun() -> do_add_snmp(Tab, Ustruct) end).
+
+do_add_snmp(schema, _Ustruct) ->
+ mnesia:abort({bad_type, schema});
+do_add_snmp(Tab, Ustruct) ->
+ TidTs = get_tid_ts_and_lock(schema, write),
+ get_tid_ts_and_lock(Tab, read),
+ insert_schema_ops(TidTs, make_add_snmp(Tab, Ustruct)).
+
+make_add_snmp(Tab, Ustruct) ->
+ ensure_writable(schema),
+ Cs = incr_version(val({Tab, cstruct})),
+ ensure_active(Cs),
+ verify([], Cs#cstruct.snmp, {already_exists, Tab, snmp}),
+ Error = {badarg, Tab, snmp, Ustruct},
+ verify(true, mnesia_snmp_hook:check_ustruct(Ustruct), Error),
+ Cs2 = Cs#cstruct{snmp = Ustruct},
+ verify_cstruct(Cs2),
+ [{op, add_snmp, Ustruct, cs2list(Cs2)}].
+
+del_snmp(Tab) ->
+ schema_transaction(fun() -> do_del_snmp(Tab) end).
+
+do_del_snmp(schema) ->
+ mnesia:abort({bad_type, schema});
+do_del_snmp(Tab) ->
+ TidTs = get_tid_ts_and_lock(schema, write),
+ get_tid_ts_and_lock(Tab, read),
+ insert_schema_ops(TidTs, make_del_snmp(Tab)).
+
+make_del_snmp(Tab) ->
+ ensure_writable(schema),
+ Cs = incr_version(val({Tab, cstruct})),
+ ensure_active(Cs),
+ Cs2 = Cs#cstruct{snmp = []},
+ verify_cstruct(Cs2),
+ [{op, del_snmp, cs2list(Cs2)}].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+
+transform_table(Tab, Fun, NewAttrs, NewRecName)
+ when function(Fun), list(NewAttrs), atom(NewRecName) ->
+ schema_transaction(fun() -> do_transform_table(Tab, Fun, NewAttrs, NewRecName) end);
+
+transform_table(Tab, ignore, NewAttrs, NewRecName)
+ when list(NewAttrs), atom(NewRecName) ->
+ schema_transaction(fun() -> do_transform_table(Tab, ignore, NewAttrs, NewRecName) end);
+
+transform_table(Tab, Fun, NewAttrs, NewRecName) ->
+ {aborted,{bad_type, Tab, Fun, NewAttrs, NewRecName}}.
+
+do_transform_table(schema, _Fun, _NewAttrs, _NewRecName) ->
+ mnesia:abort({bad_type, schema});
+do_transform_table(Tab, Fun, NewAttrs, NewRecName) ->
+ TidTs = get_tid_ts_and_lock(schema, write),
+ get_tid_ts_and_lock(Tab, write),
+ insert_schema_ops(TidTs, make_transform(Tab, Fun, NewAttrs, NewRecName)).
+
+make_transform(Tab, Fun, NewAttrs, NewRecName) ->
+ ensure_writable(schema),
+ Cs = incr_version(val({Tab, cstruct})),
+ ensure_active(Cs),
+ ensure_writable(Tab),
+ case mnesia_lib:val({Tab, index}) of
+ [] ->
+ Cs2 = Cs#cstruct{attributes = NewAttrs, record_name = NewRecName},
+ verify_cstruct(Cs2),
+ [{op, transform, Fun, cs2list(Cs2)}];
+ PosList ->
+ DelIdx = fun(Pos, Ncs) ->
+ Ix = Ncs#cstruct.index,
+ Ncs1 = Ncs#cstruct{index = lists:delete(Pos, Ix)},
+ Op = {op, del_index, Pos, cs2list(Ncs1)},
+ {Op, Ncs1}
+ end,
+ AddIdx = fun(Pos, Ncs) ->
+ Ix = Ncs#cstruct.index,
+ Ix2 = lists:sort([Pos | Ix]),
+ Ncs1 = Ncs#cstruct{index = Ix2},
+ Op = {op, add_index, Pos, cs2list(Ncs1)},
+ {Op, Ncs1}
+ end,
+ {DelOps, Cs1} = lists:mapfoldl(DelIdx, Cs, PosList),
+ Cs2 = Cs1#cstruct{attributes = NewAttrs, record_name = NewRecName},
+ {AddOps, Cs3} = lists:mapfoldl(AddIdx, Cs2, PosList),
+ verify_cstruct(Cs3),
+ lists:flatten([DelOps, {op, transform, Fun, cs2list(Cs2)}, AddOps])
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+
+change_table_access_mode(Tab, Mode) ->
+ schema_transaction(fun() -> do_change_table_access_mode(Tab, Mode) end).
+
+do_change_table_access_mode(Tab, Mode) ->
+ {_Mod, Tid, Ts} = get_tid_ts_and_lock(schema, write),
+ Store = Ts#tidstore.store,
+ mnesia_locker:wlock_no_exist(Tid, Store, schema, val({schema, active_replicas})),
+ mnesia_locker:wlock_no_exist(Tid, Store, Tab, val({Tab, active_replicas})),
+ do_insert_schema_ops(Store, make_change_table_access_mode(Tab, Mode)).
+
+make_change_table_access_mode(Tab, Mode) ->
+ ensure_writable(schema),
+ Cs = incr_version(val({Tab, cstruct})),
+ ensure_active(Cs),
+ OldMode = Cs#cstruct.access_mode,
+ verify(false, OldMode == Mode, {already_exists, Tab, Mode}),
+ Cs2 = Cs#cstruct{access_mode = Mode},
+ verify_cstruct(Cs2),
+ [{op, change_table_access_mode, cs2list(Cs2), OldMode, Mode}].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+change_table_load_order(Tab, LoadOrder) ->
+ schema_transaction(fun() -> do_change_table_load_order(Tab, LoadOrder) end).
+
+do_change_table_load_order(schema, _LoadOrder) ->
+ mnesia:abort({bad_type, schema});
+do_change_table_load_order(Tab, LoadOrder) ->
+ TidTs = get_tid_ts_and_lock(schema, write),
+ get_tid_ts_and_lock(Tab, none),
+ insert_schema_ops(TidTs, make_change_table_load_order(Tab, LoadOrder)).
+
+make_change_table_load_order(Tab, LoadOrder) ->
+ ensure_writable(schema),
+ Cs = incr_version(val({Tab, cstruct})),
+ ensure_active(Cs),
+ OldLoadOrder = Cs#cstruct.load_order,
+ Cs2 = Cs#cstruct{load_order = LoadOrder},
+ verify_cstruct(Cs2),
+ [{op, change_table_load_order, cs2list(Cs2), OldLoadOrder, LoadOrder}].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+write_table_property(Tab, Prop) when tuple(Prop), size(Prop) >= 1 ->
+ schema_transaction(fun() -> do_write_table_property(Tab, Prop) end);
+write_table_property(Tab, Prop) ->
+ {aborted, {bad_type, Tab, Prop}}.
+do_write_table_property(Tab, Prop) ->
+ TidTs = get_tid_ts_and_lock(schema, write),
+ {_, _, Ts} = TidTs,
+ Store = Ts#tidstore.store,
+ case change_prop_in_existing_op(Tab, Prop, write_property, Store) of
+ true ->
+ dbg_out("change_prop_in_existing_op"
+ "(~p,~p,write_property,Store) -> true~n",
+ [Tab,Prop]),
+ %% we have merged the table prop into the create_table op
+ ok;
+ false ->
+ dbg_out("change_prop_in_existing_op"
+ "(~p,~p,write_property,Store) -> false~n",
+ [Tab,Prop]),
+ %% this must be an existing table
+ get_tid_ts_and_lock(Tab, none),
+ insert_schema_ops(TidTs, make_write_table_properties(Tab, [Prop]))
+ end.
+
+make_write_table_properties(Tab, Props) ->
+ ensure_writable(schema),
+ Cs = incr_version(val({Tab, cstruct})),
+ ensure_active(Cs),
+ make_write_table_properties(Tab, Props, Cs).
+
+make_write_table_properties(Tab, [Prop | Props], Cs) ->
+ OldProps = Cs#cstruct.user_properties,
+ PropKey = element(1, Prop),
+ DelProps = lists:keydelete(PropKey, 1, OldProps),
+ MergedProps = lists:merge(DelProps, [Prop]),
+ Cs2 = Cs#cstruct{user_properties = MergedProps},
+ verify_cstruct(Cs2),
+ [{op, write_property, cs2list(Cs2), Prop} |
+ make_write_table_properties(Tab, Props, Cs2)];
+make_write_table_properties(_Tab, [], _Cs) ->
+ [].
+
+change_prop_in_existing_op(Tab, Prop, How, Store) ->
+ Ops = ets:match_object(Store, '_'),
+ case update_existing_op(Ops, Tab, Prop, How, []) of
+ {true, Ops1} ->
+ ets:match_delete(Store, '_'),
+ [ets:insert(Store, Op) || Op <- Ops1],
+ true;
+ false ->
+ false
+ end.
+
+update_existing_op([{op, Op, L = [{name,Tab}|_], _OldProp}|Ops],
+ Tab, Prop, How, Acc) when Op == write_property;
+ Op == delete_property ->
+ %% Apparently, mnesia_dumper doesn't care about OldProp here -- just L,
+ %% so we will throw away OldProp (not that it matters...) and insert Prop.
+ %% as element 3.
+ L1 = insert_prop(Prop, L, How),
+ NewOp = {op, How, L1, Prop},
+ {true, lists:reverse(Acc) ++ [NewOp|Ops]};
+update_existing_op([Op = {op, create_table, L}|Ops], Tab, Prop, How, Acc) ->
+ case lists:keysearch(name, 1, L) of
+ {value, {_, Tab}} ->
+ %% Tab is being created here -- insert Prop into L
+ L1 = insert_prop(Prop, L, How),
+ {true, lists:reverse(Acc) ++ [{op, create_table, L1}|Ops]};
+ _ ->
+ update_existing_op(Ops, Tab, Prop, How, [Op|Acc])
+ end;
+update_existing_op([Op|Ops], Tab, Prop, How, Acc) ->
+ update_existing_op(Ops, Tab, Prop, How, [Op|Acc]);
+update_existing_op([], _, _, _, _) ->
+ false.
+
+%% perhaps a misnomer. How could also be delete_property... never mind.
+%% Returns the modified L.
+insert_prop(Prop, L, How) ->
+ Prev = find_props(L),
+ MergedProps = merge_with_previous(How, Prop, Prev),
+ replace_props(L, MergedProps).
+
+
+find_props([{user_properties, P}|_]) -> P;
+find_props([_H|T]) -> find_props(T).
+%% we shouldn't reach []
+
+replace_props([{user_properties, _}|T], P) -> [{user_properties, P}|T];
+replace_props([H|T], P) -> [H|replace_props(T, P)].
+%% again, we shouldn't reach []
+
+merge_with_previous(write_property, Prop, Prev) ->
+ Key = element(1, Prop),
+ Prev1 = lists:keydelete(Key, 1, Prev),
+ lists:sort([Prop|Prev1]);
+merge_with_previous(delete_property, PropKey, Prev) ->
+ lists:keydelete(PropKey, 1, Prev).
+
+delete_table_property(Tab, PropKey) ->
+ schema_transaction(fun() -> do_delete_table_property(Tab, PropKey) end).
+
+do_delete_table_property(Tab, PropKey) ->
+ TidTs = get_tid_ts_and_lock(schema, write),
+ {_, _, Ts} = TidTs,
+ Store = Ts#tidstore.store,
+ case change_prop_in_existing_op(Tab, PropKey, delete_property, Store) of
+ true ->
+ dbg_out("change_prop_in_existing_op"
+ "(~p,~p,delete_property,Store) -> true~n",
+ [Tab,PropKey]),
+ %% we have merged the table prop into the create_table op
+ ok;
+ false ->
+ dbg_out("change_prop_in_existing_op"
+ "(~p,~p,delete_property,Store) -> false~n",
+ [Tab,PropKey]),
+ %% this must be an existing table
+ get_tid_ts_and_lock(Tab, none),
+ insert_schema_ops(TidTs,
+ make_delete_table_properties(Tab, [PropKey]))
+ end.
+
+make_delete_table_properties(Tab, PropKeys) ->
+ ensure_writable(schema),
+ Cs = incr_version(val({Tab, cstruct})),
+ ensure_active(Cs),
+ make_delete_table_properties(Tab, PropKeys, Cs).
+
+make_delete_table_properties(Tab, [PropKey | PropKeys], Cs) ->
+ OldProps = Cs#cstruct.user_properties,
+ Props = lists:keydelete(PropKey, 1, OldProps),
+ Cs2 = Cs#cstruct{user_properties = Props},
+ verify_cstruct(Cs2),
+ [{op, delete_property, cs2list(Cs2), PropKey} |
+ make_delete_table_properties(Tab, PropKeys, Cs2)];
+make_delete_table_properties(_Tab, [], _Cs) ->
+ [].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Ensure that the transaction can be committed even
+%% if the node crashes and Mnesia is restarted
+prepare_commit(Tid, Commit, WaitFor) ->
+ case Commit#commit.schema_ops of
+ [] ->
+ {false, Commit, optional};
+ OrigOps ->
+ {Modified, Ops, DumperMode} =
+ prepare_ops(Tid, OrigOps, WaitFor, false, [], optional),
+ InitBy = schema_prepare,
+ GoodRes = {Modified,
+ Commit#commit{schema_ops = lists:reverse(Ops)},
+ DumperMode},
+ case DumperMode of
+ optional ->
+ dbg_out("Transaction log dump skipped (~p): ~w~n",
+ [DumperMode, InitBy]);
+ mandatory ->
+ case mnesia_controller:sync_dump_log(InitBy) of
+ dumped ->
+ GoodRes;
+ {error, Reason} ->
+ mnesia:abort(Reason)
+ end
+ end,
+ case Ops of
+ [] ->
+ ignore;
+ _ ->
+ %% We need to grab a dumper lock here, the log may not
+ %% be dumped by others, during the schema commit phase.
+ mnesia_controller:wait_for_schema_commit_lock()
+ end,
+ GoodRes
+ end.
+
+prepare_ops(Tid, [Op | Ops], WaitFor, Changed, Acc, DumperMode) ->
+ case prepare_op(Tid, Op, WaitFor) of
+ {true, mandatory} ->
+ prepare_ops(Tid, Ops, WaitFor, Changed, [Op | Acc], mandatory);
+ {true, optional} ->
+ prepare_ops(Tid, Ops, WaitFor, Changed, [Op | Acc], DumperMode);
+ {true, Ops2, mandatory} ->
+ prepare_ops(Tid, Ops, WaitFor, true, Ops2 ++ Acc, mandatory);
+ {true, Ops2, optional} ->
+ prepare_ops(Tid, Ops, WaitFor, true, Ops2 ++ Acc, DumperMode);
+ {false, mandatory} ->
+ prepare_ops(Tid, Ops, WaitFor, true, Acc, mandatory);
+ {false, optional} ->
+ prepare_ops(Tid, Ops, WaitFor, true, Acc, DumperMode)
+ end;
+prepare_ops(_Tid, [], _WaitFor, Changed, Acc, DumperMode) ->
+ {Changed, Acc, DumperMode}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Prepare for commit
+%% returns true if Op should be included, i.e. unmodified
+%% {true, Operation} if NewRecs should be included, i.e. modified
+%% false if Op should NOT be included, i.e. modified
+%%
+prepare_op(_Tid, {op, rec, unknown, Rec}, _WaitFor) ->
+ {{Tab, Key}, Items, _Op} = Rec,
+ case val({Tab, storage_type}) of
+ unknown ->
+ {false, optional};
+ Storage ->
+ mnesia_tm:prepare_snmp(Tab, Key, Items), % May exit
+ {true, [{op, rec, Storage, Rec}], optional}
+ end;
+
+prepare_op(_Tid, {op, announce_im_running, _Node, SchemaDef, Running, RemoteRunning}, _WaitFor) ->
+ SchemaCs = list2cs(SchemaDef),
+ case lists:member(node(), Running) of
+ true ->
+ announce_im_running(RemoteRunning -- Running, SchemaCs);
+ false ->
+ announce_im_running(Running -- RemoteRunning, SchemaCs)
+ end,
+ {false, optional};
+
+prepare_op(_Tid, {op, sync_trans}, {part, CoordPid}) ->
+ CoordPid ! {sync_trans, self()},
+ receive
+ {sync_trans, CoordPid} ->
+ {false, optional};
+ Else ->
+ mnesia_lib:verbose("sync_op terminated due to ~p~n", [Else]),
+ mnesia:abort(Else)
+ end;
+
+prepare_op(_Tid, {op, sync_trans}, {coord, Nodes}) ->
+ case receive_sync(Nodes, []) of
+ {abort, Reason} ->
+ mnesia_lib:verbose("sync_op terminated due to ~p~n", [Reason]),
+ mnesia:abort(Reason);
+ Pids ->
+ [Pid ! {sync_trans, self()} || Pid <- Pids],
+ {false, optional}
+ end;
+prepare_op(Tid, {op, create_table, TabDef}, _WaitFor) ->
+ Cs = list2cs(TabDef),
+ Storage = mnesia_lib:cs_to_storage_type(node(), Cs),
+ UseDir = mnesia_monitor:use_dir(),
+ Tab = Cs#cstruct.name,
+ case Storage of
+ disc_copies when UseDir == false ->
+ UseDirReason = {bad_type, Tab, Storage, node()},
+ mnesia:abort(UseDirReason);
+ disc_only_copies when UseDir == false ->
+ UseDirReason = {bad_type, Tab, Storage, node()},
+ mnesia:abort(UseDirReason);
+ ram_copies ->
+ create_ram_table(Tab, Cs#cstruct.type),
+ insert_cstruct(Tid, Cs, false),
+ {true, optional};
+ disc_copies ->
+ create_ram_table(Tab, Cs#cstruct.type),
+ create_disc_table(Tab),
+ insert_cstruct(Tid, Cs, false),
+ {true, optional};
+ disc_only_copies ->
+ create_disc_only_table(Tab,Cs#cstruct.type),
+ insert_cstruct(Tid, Cs, false),
+ {true, optional};
+ unknown -> %% No replica on this node
+ insert_cstruct(Tid, Cs, false),
+ {true, optional}
+ end;
+
+prepare_op(Tid, {op, add_table_copy, Storage, Node, TabDef}, _WaitFor) ->
+ Cs = list2cs(TabDef),
+ Tab = Cs#cstruct.name,
+
+ if
+ Tab == schema ->
+ {true, optional}; % Nothing to prepare
+ Node == node() ->
+ case mnesia_lib:val({schema, storage_type}) of
+ ram_copies when Storage /= ram_copies ->
+ Error = {combine_error, Tab, "has no disc", Node},
+ mnesia:abort(Error);
+ _ ->
+ ok
+ end,
+ %% Tables are created by mnesia_loader get_network code
+ insert_cstruct(Tid, Cs, true),
+ case mnesia_controller:get_network_copy(Tab, Cs) of
+ {loaded, ok} ->
+ {true, optional};
+ {not_loaded, ErrReason} ->
+ Reason = {system_limit, Tab, {Node, ErrReason}},
+ mnesia:abort(Reason)
+ end;
+ Node /= node() ->
+ %% Verify that ram table not has been dumped to disc
+ if
+ Storage /= ram_copies ->
+ case mnesia_lib:schema_cs_to_storage_type(node(), Cs) of
+ ram_copies ->
+ Dat = mnesia_lib:tab2dcd(Tab),
+ case mnesia_lib:exists(Dat) of
+ true ->
+ mnesia:abort({combine_error, Tab, Storage,
+ "Table dumped to disc", node()});
+ false ->
+ ok
+ end;
+ _ ->
+ ok
+ end;
+ true ->
+ ok
+ end,
+ insert_cstruct(Tid, Cs, true),
+ {true, optional}
+ end;
+
+prepare_op(Tid, {op, del_table_copy, _Storage, Node, TabDef}, _WaitFor) ->
+ Cs = list2cs(TabDef),
+ Tab = Cs#cstruct.name,
+
+ if
+ %% Schema table lock is always required to run a schema op.
+ %% No need to look it.
+ node(Tid#tid.pid) == node(), Tab /= schema ->
+ Pid = spawn_link(?MODULE, lock_del_table, [Tab, Node, Cs, self()]),
+ receive
+ {Pid, updated} ->
+ {true, optional};
+ {Pid, FailReason} ->
+ mnesia:abort(FailReason);
+ {'EXIT', Pid, Reason} ->
+ mnesia:abort(Reason)
+ end;
+ true ->
+ {true, optional}
+ end;
+
+prepare_op(_Tid, {op, change_table_copy_type, N, FromS, ToS, TabDef}, _WaitFor)
+ when N == node() ->
+ Cs = list2cs(TabDef),
+ Tab = Cs#cstruct.name,
+
+ NotActive = mnesia_lib:not_active_here(Tab),
+
+ if
+ NotActive == true ->
+ mnesia:abort({not_active, Tab, node()});
+
+ Tab == schema ->
+ case {FromS, ToS} of
+ {ram_copies, disc_copies} ->
+ case mnesia:system_info(schema_location) of
+ opt_disc ->
+ ignore;
+ _ ->
+ mnesia:abort({combine_error, Tab, node(),
+ "schema_location must be opt_disc"})
+ end,
+ Dir = mnesia_lib:dir(),
+ case opt_create_dir(true, Dir) of
+ ok ->
+ purge_dir(Dir, []),
+ mnesia_log:purge_all_logs(),
+ set(use_dir, true),
+ mnesia_log:init(),
+ Ns = val({current, db_nodes}), %mnesia_lib:running_nodes(),
+ F = fun(U) -> mnesia_recover:log_mnesia_up(U) end,
+ lists:foreach(F, Ns),
+
+ mnesia_dumper:raw_named_dump_table(Tab, dmp),
+ mnesia_checkpoint:tm_change_table_copy_type(Tab, FromS, ToS);
+ {error, Reason} ->
+ mnesia:abort(Reason)
+ end;
+ {disc_copies, ram_copies} ->
+ Ltabs = val({schema, local_tables}) -- [schema],
+ Dtabs = [L || L <- Ltabs,
+ val({L, storage_type}) /= ram_copies],
+ verify([], Dtabs, {"Disc resident tables", Dtabs, N});
+ _ ->
+ mnesia:abort({combine_error, Tab, ToS})
+ end;
+
+ FromS == ram_copies ->
+ case mnesia_monitor:use_dir() of
+ true ->
+ Dat = mnesia_lib:tab2dcd(Tab),
+ case mnesia_lib:exists(Dat) of
+ true ->
+ mnesia:abort({combine_error, Tab, node(),
+ "Table dump exists"});
+ false ->
+ case ToS of
+ disc_copies ->
+ mnesia_log:ets2dcd(Tab, dmp);
+ disc_only_copies ->
+ mnesia_dumper:raw_named_dump_table(Tab, dmp)
+ end,
+ mnesia_checkpoint:tm_change_table_copy_type(Tab, FromS, ToS)
+ end;
+ false ->
+ mnesia:abort({has_no_disc, node()})
+ end;
+
+ FromS == disc_copies, ToS == disc_only_copies ->
+ mnesia_dumper:raw_named_dump_table(Tab, dmp);
+ FromS == disc_only_copies ->
+ Type = Cs#cstruct.type,
+ create_ram_table(Tab, Type),
+ Datname = mnesia_lib:tab2dat(Tab),
+ Repair = mnesia_monitor:get_env(auto_repair),
+ case mnesia_lib:dets_to_ets(Tab, Tab, Datname, Type, Repair, no) of
+ loaded -> ok;
+ Reason ->
+ Err = "Failed to copy disc data to ram",
+ mnesia:abort({system_limit, Tab, {Err,Reason}})
+ end;
+ true ->
+ ignore
+ end,
+ {true, mandatory};
+
+prepare_op(_Tid, {op, change_table_copy_type, N, _FromS, _ToS, _TabDef}, _WaitFor)
+ when N /= node() ->
+ {true, mandatory};
+
+prepare_op(_Tid, {op, delete_table, _TabDef}, _WaitFor) ->
+ {true, mandatory};
+
+prepare_op(_Tid, {op, dump_table, unknown, TabDef}, _WaitFor) ->
+ Cs = list2cs(TabDef),
+ Tab = Cs#cstruct.name,
+ case lists:member(node(), Cs#cstruct.ram_copies) of
+ true ->
+ case mnesia_monitor:use_dir() of
+ true ->
+ mnesia_log:ets2dcd(Tab, dmp),
+ Size = mnesia:table_info(Tab, size),
+ {true, [{op, dump_table, Size, TabDef}], optional};
+ false ->
+ mnesia:abort({has_no_disc, node()})
+ end;
+ false ->
+ {false, optional}
+ end;
+
+prepare_op(_Tid, {op, add_snmp, Ustruct, TabDef}, _WaitFor) ->
+ Cs = list2cs(TabDef),
+ case mnesia_lib:cs_to_storage_type(node(), Cs) of
+ unknown ->
+ {true, optional};
+ Storage ->
+ Tab = Cs#cstruct.name,
+ Stab = mnesia_snmp_hook:create_table(Ustruct, Tab, Storage),
+ mnesia_lib:set({Tab, {index, snmp}}, Stab),
+ {true, optional}
+ end;
+
+prepare_op(_Tid, {op, transform, ignore, _TabDef}, _WaitFor) ->
+ {true, mandatory}; %% Apply schema changes only.
+prepare_op(_Tid, {op, transform, Fun, TabDef}, _WaitFor) ->
+ Cs = list2cs(TabDef),
+ case mnesia_lib:cs_to_storage_type(node(), Cs) of
+ unknown ->
+ {true, mandatory};
+ Storage ->
+ Tab = Cs#cstruct.name,
+ RecName = Cs#cstruct.record_name,
+ Type = Cs#cstruct.type,
+ NewArity = length(Cs#cstruct.attributes) + 1,
+ mnesia_lib:db_fixtable(Storage, Tab, true),
+ Key = mnesia_lib:db_first(Tab),
+ Op = {op, transform, Fun, TabDef},
+ case catch transform_objs(Fun, Tab, RecName,
+ Key, NewArity, Storage, Type, [Op]) of
+ {'EXIT', Reason} ->
+ mnesia_lib:db_fixtable(Storage, Tab, false),
+ exit({"Bad transform function", Tab, Fun, node(), Reason});
+ Objs ->
+ mnesia_lib:db_fixtable(Storage, Tab, false),
+ {true, Objs, mandatory}
+ end
+ end;
+
+prepare_op(_Tid, _Op, _WaitFor) ->
+ {true, optional}.
+
+
+create_ram_table(Tab, Type) ->
+ Args = [{keypos, 2}, public, named_table, Type],
+ case mnesia_monitor:unsafe_mktab(Tab, Args) of
+ Tab ->
+ ok;
+ {error,Reason} ->
+ Err = "Failed to create ets table",
+ mnesia:abort({system_limit, Tab, {Err,Reason}})
+ end.
+create_disc_table(Tab) ->
+ File = mnesia_lib:tab2dcd(Tab),
+ file:delete(File),
+ FArg = [{file, File}, {name, {mnesia,create}},
+ {repair, false}, {mode, read_write}],
+ case mnesia_monitor:open_log(FArg) of
+ {ok,Log} ->
+ mnesia_monitor:unsafe_close_log(Log),
+ ok;
+ {error,Reason} ->
+ Err = "Failed to create disc table",
+ mnesia:abort({system_limit, Tab, {Err,Reason}})
+ end.
+create_disc_only_table(Tab,Type) ->
+ File = mnesia_lib:tab2dat(Tab),
+ file:delete(File),
+ Args = [{file, mnesia_lib:tab2dat(Tab)},
+ {type, mnesia_lib:disk_type(Tab, Type)},
+ {keypos, 2},
+ {repair, mnesia_monitor:get_env(auto_repair)}],
+ case mnesia_monitor:unsafe_open_dets(Tab, Args) of
+ {ok, _} ->
+ ok;
+ {error,Reason} ->
+ Err = "Failed to create disc table",
+ mnesia:abort({system_limit, Tab, {Err,Reason}})
+ end.
+
+
+receive_sync([], Pids) ->
+ Pids;
+receive_sync(Nodes, Pids) ->
+ receive
+ {sync_trans, Pid} ->
+ Node = node(Pid),
+ receive_sync(lists:delete(Node, Nodes), [Pid | Pids]);
+ Else ->
+ {abort, Else}
+ end.
+
+lock_del_table(Tab, Node, Cs, Father) ->
+ Ns = val({schema, active_replicas}),
+ Lock = fun() ->
+ mnesia:write_lock_table(Tab),
+ {Res, []} = rpc:multicall(Ns, ?MODULE, set_where_to_read, [Tab, Node, Cs]),
+ Filter = fun(ok) ->
+ false;
+ ({badrpc, {'EXIT', {undef, _}}}) ->
+ %% This will be the case we talks with elder nodes
+ %% than 3.8.2, they will set where_to_read without
+ %% getting a lock.
+ false;
+ (_) ->
+ true
+ end,
+ [] = lists:filter(Filter, Res),
+ ok
+ end,
+ case mnesia:transaction(Lock) of
+ {'atomic', ok} ->
+ Father ! {self(), updated};
+ {aborted, R} ->
+ Father ! {self(), R}
+ end,
+ unlink(Father),
+ exit(normal).
+
+set_where_to_read(Tab, Node, Cs) ->
+ case mnesia_lib:val({Tab, where_to_read}) of
+ Node ->
+ case Cs#cstruct.local_content of
+ true ->
+ ok;
+ false ->
+ mnesia_lib:set_remote_where_to_read(Tab, [Node]),
+ ok
+ end;
+ _ ->
+ ok
+ end.
+
+%% Build up the list in reverse order.
+transform_objs(_Fun, _Tab, _RT, '$end_of_table', _NewArity, _Storage, _Type, Acc) ->
+ Acc;
+transform_objs(Fun, Tab, RecName, Key, A, Storage, Type, Acc) ->
+ Objs = mnesia_lib:db_get(Tab, Key),
+ NextKey = mnesia_lib:db_next_key(Tab, Key),
+ Oid = {Tab, Key},
+ NewObjs = {Ws, Ds} = transform_obj(Tab, RecName, Key, Fun, Objs, A, Type, [], []),
+ if
+ NewObjs == {[], []} ->
+ transform_objs(Fun, Tab, RecName, NextKey, A, Storage, Type, Acc);
+ Type == bag ->
+ transform_objs(Fun, Tab, RecName, NextKey, A, Storage, Type,
+ [{op, rec, Storage, {Oid, Ws, write}},
+ {op, rec, Storage, {Oid, [Oid], delete}} | Acc]);
+ Ds == [] ->
+ %% Type is set or ordered_set, no need to delete the record first
+ transform_objs(Fun, Tab, RecName, NextKey, A, Storage, Type,
+ [{op, rec, Storage, {Oid, Ws, write}} | Acc]);
+ Ws == [] ->
+ transform_objs(Fun, Tab, RecName, NextKey, A, Storage, Type,
+ [{op, rec, Storage, {Oid, Ds, write}} | Acc]);
+ true ->
+ transform_objs(Fun, Tab, RecName, NextKey, A, Storage, Type,
+ [{op, rec, Storage, {Oid, Ws, write}},
+ {op, rec, Storage, {Oid, Ds, delete}} | Acc])
+ end.
+
+transform_obj(Tab, RecName, Key, Fun, [Obj|Rest], NewArity, Type, Ws, Ds) ->
+ NewObj = Fun(Obj),
+ if
+ size(NewObj) /= NewArity ->
+ exit({"Bad arity", Obj, NewObj});
+ NewObj == Obj ->
+ transform_obj(Tab, RecName, Key, Fun, Rest, NewArity, Type, Ws, Ds);
+ RecName == element(1, NewObj), Key == element(2, NewObj) ->
+ transform_obj(Tab, RecName, Key, Fun, Rest, NewArity,
+ Type, [NewObj | Ws], Ds);
+ NewObj == delete ->
+ case Type of
+ bag -> %% Just don't write that object
+ transform_obj(Tab, RecName, Key, Fun, Rest,
+ NewArity, Type, Ws, Ds);
+ _ ->
+ transform_obj(Tab, RecName, Key, Fun, Rest, NewArity,
+ Type, Ws, [NewObj | Ds])
+ end;
+ true ->
+ exit({"Bad key or Record Name", Obj, NewObj})
+ end;
+transform_obj(_Tab, _RecName, _Key, _Fun, [], _NewArity, _Type, Ws, Ds) ->
+ {lists:reverse(Ws), lists:reverse(Ds)}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Undo prepare of commit
+undo_prepare_commit(Tid, Commit) ->
+ case Commit#commit.schema_ops of
+ [] ->
+ ignore;
+ Ops ->
+ %% Catch to allow failure mnesia_controller may not be started
+ catch mnesia_controller:release_schema_commit_lock(),
+ undo_prepare_ops(Tid, Ops)
+ end,
+ Commit.
+
+%% Undo in reverse order
+undo_prepare_ops(Tid, [Op | Ops]) ->
+ case element(1, Op) of
+ TheOp when TheOp /= op, TheOp /= restore_op ->
+ undo_prepare_ops(Tid, Ops);
+ _ ->
+ undo_prepare_ops(Tid, Ops),
+ undo_prepare_op(Tid, Op)
+ end;
+undo_prepare_ops(_Tid, []) ->
+ [].
+
+undo_prepare_op(_Tid, {op, announce_im_running, _, _, Running, RemoteRunning}) ->
+ case lists:member(node(), Running) of
+ true ->
+ unannounce_im_running(RemoteRunning -- Running);
+ false ->
+ unannounce_im_running(Running -- RemoteRunning)
+ end;
+
+undo_prepare_op(_Tid, {op, sync_trans}) ->
+ ok;
+
+undo_prepare_op(Tid, {op, create_table, TabDef}) ->
+ Cs = list2cs(TabDef),
+ Tab = Cs#cstruct.name,
+ mnesia_lib:unset({Tab, create_table}),
+ delete_cstruct(Tid, Cs),
+ case mnesia_lib:cs_to_storage_type(node(), Cs) of
+ unknown ->
+ ok;
+ ram_copies ->
+ ram_delete_table(Tab, ram_copies);
+ disc_copies ->
+ ram_delete_table(Tab, disc_copies),
+ DcdFile = mnesia_lib:tab2dcd(Tab),
+ %% disc_delete_table(Tab, Storage),
+ file:delete(DcdFile);
+ disc_only_copies ->
+ mnesia_monitor:unsafe_close_dets(Tab),
+ Dat = mnesia_lib:tab2dat(Tab),
+ %% disc_delete_table(Tab, Storage),
+ file:delete(Dat)
+ end;
+
+undo_prepare_op(Tid, {op, add_table_copy, Storage, Node, TabDef}) ->
+ Cs = list2cs(TabDef),
+ Tab = Cs#cstruct.name,
+ if
+ Tab == schema ->
+ true; % Nothing to prepare
+ Node == node() ->
+ mnesia_checkpoint:tm_del_copy(Tab, Node),
+ mnesia_controller:unannounce_add_table_copy(Tab, Node),
+ if
+ Storage == disc_only_copies; Tab == schema ->
+ mnesia_monitor:close_dets(Tab),
+ file:delete(mnesia_lib:tab2dat(Tab));
+ true ->
+ file:delete(mnesia_lib:tab2dcd(Tab))
+ end,
+ ram_delete_table(Tab, Storage),
+ Cs2 = new_cs(Cs, Node, Storage, del),
+ insert_cstruct(Tid, Cs2, true); % Don't care about the version
+ Node /= node() ->
+ mnesia_controller:unannounce_add_table_copy(Tab, Node),
+ Cs2 = new_cs(Cs, Node, Storage, del),
+ insert_cstruct(Tid, Cs2, true) % Don't care about the version
+ end;
+
+undo_prepare_op(_Tid, {op, del_table_copy, _, Node, TabDef})
+ when Node == node() ->
+ Cs = list2cs(TabDef),
+ Tab = Cs#cstruct.name,
+ mnesia_lib:set({Tab, where_to_read}, Node);
+
+
+undo_prepare_op(_Tid, {op, change_table_copy_type, N, FromS, ToS, TabDef})
+ when N == node() ->
+ Cs = list2cs(TabDef),
+ Tab = Cs#cstruct.name,
+ mnesia_checkpoint:tm_change_table_copy_type(Tab, ToS, FromS),
+ Dmp = mnesia_lib:tab2dmp(Tab),
+
+ case {FromS, ToS} of
+ {ram_copies, disc_copies} when Tab == schema ->
+ file:delete(Dmp),
+ mnesia_log:purge_some_logs(),
+ set(use_dir, false);
+ {ram_copies, disc_copies} ->
+ file:delete(Dmp);
+ {ram_copies, disc_only_copies} ->
+ file:delete(Dmp);
+ {disc_only_copies, _} ->
+ ram_delete_table(Tab, ram_copies);
+ _ ->
+ ignore
+ end;
+
+undo_prepare_op(_Tid, {op, dump_table, _Size, TabDef}) ->
+ Cs = list2cs(TabDef),
+ case lists:member(node(), Cs#cstruct.ram_copies) of
+ true ->
+ Tab = Cs#cstruct.name,
+ Dmp = mnesia_lib:tab2dmp(Tab),
+ file:delete(Dmp);
+ false ->
+ ignore
+ end;
+
+undo_prepare_op(_Tid, {op, add_snmp, _Ustruct, TabDef}) ->
+ Cs = list2cs(TabDef),
+ case mnesia_lib:cs_to_storage_type(node(), Cs) of
+ unknown ->
+ true;
+ _Storage ->
+ Tab = Cs#cstruct.name,
+ case ?catch_val({Tab, {index, snmp}}) of
+ {'EXIT',_} ->
+ ignore;
+ Stab ->
+ mnesia_snmp_hook:delete_table(Tab, Stab),
+ mnesia_lib:unset({Tab, {index, snmp}})
+ end
+ end;
+
+undo_prepare_op(_Tid, _Op) ->
+ ignore.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ram_delete_table(Tab, Storage) ->
+ case Storage of
+ unknown ->
+ ignore;
+ disc_only_copies ->
+ ignore;
+ _Else ->
+ %% delete possible index files and data .....
+ %% Got to catch this since if no info has been set in the
+ %% mnesia_gvar it will crash
+ catch mnesia_index:del_transient(Tab, Storage),
+ case ?catch_val({Tab, {index, snmp}}) of
+ {'EXIT', _} ->
+ ignore;
+ Etab ->
+ catch mnesia_snmp_hook:delete_table(Tab, Etab)
+ end,
+ catch ?ets_delete_table(Tab)
+ end.
+
+purge_dir(Dir, KeepFiles) ->
+ Suffixes = known_suffixes(),
+ purge_dir(Dir, KeepFiles, Suffixes).
+
+purge_dir(Dir, KeepFiles, Suffixes) ->
+ case dir_exists(Dir) of
+ true ->
+ {ok, AllFiles} = file:list_dir(Dir),
+ purge_known_files(AllFiles, KeepFiles, Dir, Suffixes);
+ false ->
+ ok
+ end.
+
+purge_tmp_files() ->
+ case mnesia_monitor:use_dir() of
+ true ->
+ Dir = mnesia_lib:dir(),
+ KeepFiles = [],
+ Exists = mnesia_lib:exists(mnesia_lib:tab2dat(schema)),
+ case Exists of
+ true ->
+ Suffixes = tmp_suffixes(),
+ purge_dir(Dir, KeepFiles, Suffixes);
+ false ->
+ %% Interrupted change of storage type
+ %% for schema table
+ Suffixes = known_suffixes(),
+ purge_dir(Dir, KeepFiles, Suffixes),
+ mnesia_lib:set(use_dir, false)
+ end;
+
+ false ->
+ ok
+ end.
+
+purge_known_files([File | Tail], KeepFiles, Dir, Suffixes) ->
+ case lists:member(File, KeepFiles) of
+ true ->
+ ignore;
+ false ->
+ case has_known_suffix(File, Suffixes, false) of
+ false ->
+ ignore;
+ true ->
+ AbsFile = filename:join([Dir, File]),
+ file:delete(AbsFile)
+ end
+ end,
+ purge_known_files(Tail, KeepFiles, Dir, Suffixes);
+purge_known_files([], _KeepFiles, _Dir, _Suffixes) ->
+ ok.
+
+has_known_suffix(_File, _Suffixes, true) ->
+ true;
+has_known_suffix(File, [Suffix | Tail], false) ->
+ has_known_suffix(File, Tail, lists:suffix(Suffix, File));
+has_known_suffix(_File, [], Bool) ->
+ Bool.
+
+known_suffixes() -> real_suffixes() ++ tmp_suffixes().
+
+real_suffixes() -> [".DAT", ".LOG", ".BUP", ".DCL", ".DCD"].
+
+tmp_suffixes() -> [".TMP", ".BUPTMP", ".RET", ".DMP"].
+
+info() ->
+ Tabs = lists:sort(val({schema, tables})),
+ lists:foreach(fun(T) -> info(T) end, Tabs),
+ ok.
+
+info(Tab) ->
+ Props = get_table_properties(Tab),
+ io:format("-- Properties for ~w table --- ~n",[Tab]),
+ info2(Tab, Props).
+info2(Tab, [{cstruct, _V} | Tail]) -> % Ignore cstruct
+ info2(Tab, Tail);
+info2(Tab, [{frag_hash, _V} | Tail]) -> % Ignore frag_hash
+ info2(Tab, Tail);
+info2(Tab, [{P, V} | Tail]) ->
+ io:format("~-20w -> ~p~n",[P,V]),
+ info2(Tab, Tail);
+info2(_, []) ->
+ io:format("~n", []).
+
+get_table_properties(Tab) ->
+ case catch mnesia_lib:db_match_object(ram_copies,
+ mnesia_gvar, {{Tab, '_'}, '_'}) of
+ {'EXIT', _} ->
+ mnesia:abort({no_exists, Tab, all});
+ RawGvar ->
+ case [{Item, Val} || {{_Tab, Item}, Val} <- RawGvar] of
+ [] ->
+ [];
+ Gvar ->
+ Size = {size, mnesia:table_info(Tab, size)},
+ Memory = {memory, mnesia:table_info(Tab, memory)},
+ Master = {master_nodes, mnesia:table_info(Tab, master_nodes)},
+ lists:sort([Size, Memory, Master | Gvar])
+ end
+ end.
+
+%%%%%%%%%%% RESTORE %%%%%%%%%%%
+
+-record(r, {iter = schema,
+ module,
+ table_options = [],
+ default_op = clear_tables,
+ tables = [],
+ opaque,
+ insert_op = error_fun,
+ recs = error_recs
+ }).
+
+restore(Opaque) ->
+ restore(Opaque, [], mnesia_monitor:get_env(backup_module)).
+restore(Opaque, Args) when list(Args) ->
+ restore(Opaque, Args, mnesia_monitor:get_env(backup_module));
+restore(_Opaque, BadArg) ->
+ {aborted, {badarg, BadArg}}.
+restore(Opaque, Args, Module) when list(Args), atom(Module) ->
+ InitR = #r{opaque = Opaque, module = Module},
+ case catch lists:foldl(fun check_restore_arg/2, InitR, Args) of
+ R when record(R, r) ->
+ case mnesia_bup:read_schema(Module, Opaque) of
+ {error, Reason} ->
+ {aborted, Reason};
+ BupSchema ->
+ schema_transaction(fun() -> do_restore(R, BupSchema) end)
+ end;
+ {'EXIT', Reason} ->
+ {aborted, Reason}
+ end;
+restore(_Opaque, Args, Module) ->
+ {aborted, {badarg, Args, Module}}.
+
+check_restore_arg({module, Mod}, R) when atom(Mod) ->
+ R#r{module = Mod};
+
+check_restore_arg({clear_tables, List}, R) when list(List) ->
+ case lists:member(schema, List) of
+ false ->
+ TableList = [{Tab, clear_tables} || Tab <- List],
+ R#r{table_options = R#r.table_options ++ TableList};
+ true ->
+ exit({badarg, {clear_tables, schema}})
+ end;
+check_restore_arg({recreate_tables, List}, R) when list(List) ->
+ case lists:member(schema, List) of
+ false ->
+ TableList = [{Tab, recreate_tables} || Tab <- List],
+ R#r{table_options = R#r.table_options ++ TableList};
+ true ->
+ exit({badarg, {recreate_tables, schema}})
+ end;
+check_restore_arg({keep_tables, List}, R) when list(List) ->
+ TableList = [{Tab, keep_tables} || Tab <- List],
+ R#r{table_options = R#r.table_options ++ TableList};
+check_restore_arg({skip_tables, List}, R) when list(List) ->
+ TableList = [{Tab, skip_tables} || Tab <- List],
+ R#r{table_options = R#r.table_options ++ TableList};
+check_restore_arg({default_op, Op}, R) ->
+ case Op of
+ clear_tables -> ok;
+ recreate_tables -> ok;
+ keep_tables -> ok;
+ skip_tables -> ok;
+ Else ->
+ exit({badarg, {bad_default_op, Else}})
+ end,
+ R#r{default_op = Op};
+
+check_restore_arg(BadArg,_) ->
+ exit({badarg, BadArg}).
+
+do_restore(R, BupSchema) ->
+ TidTs = get_tid_ts_and_lock(schema, write),
+ R2 = restore_schema(BupSchema, R),
+ insert_schema_ops(TidTs, [{restore_op, R2}]),
+ [element(1, TabStruct) || TabStruct <- R2#r.tables].
+
+arrange_restore(R, Fun, Recs) ->
+ R2 = R#r{insert_op = Fun, recs = Recs},
+ case mnesia_bup:iterate(R#r.module, fun restore_items/4, R#r.opaque, R2) of
+ {ok, R3} -> R3#r.recs;
+ {error, Reason} -> mnesia:abort(Reason);
+ Reason -> mnesia:abort(Reason)
+ end.
+
+restore_items([Rec | Recs], Header, Schema, R) ->
+ Tab = element(1, Rec),
+ case lists:keysearch(Tab, 1, R#r.tables) of
+ {value, {Tab, Where, Snmp, RecName}} ->
+ {Rest, NRecs} =
+ restore_tab_items([Rec | Recs], Tab, RecName, Where, Snmp,
+ R#r.recs, R#r.insert_op),
+ restore_items(Rest, Header, Schema, R#r{recs = NRecs});
+ false ->
+ Rest = skip_tab_items(Recs, Tab),
+ restore_items(Rest, Header, Schema, R)
+ end;
+
+restore_items([], _Header, _Schema, R) ->
+ R.
+
+restore_func(Tab, R) ->
+ case lists:keysearch(Tab, 1, R#r.table_options) of
+ {value, {Tab, OP}} ->
+ OP;
+ false ->
+ R#r.default_op
+ end.
+
+where_to_commit(Tab, CsList) ->
+ Ram = [{N, ram_copies} || N <- pick(Tab, ram_copies, CsList, [])],
+ Disc = [{N, disc_copies} || N <- pick(Tab, disc_copies, CsList, [])],
+ DiscO = [{N, disc_only_copies} || N <- pick(Tab, disc_only_copies, CsList, [])],
+ Ram ++ Disc ++ DiscO.
+
+%% Changes of the Meta info of schema itself is not allowed
+restore_schema([{schema, schema, _List} | Schema], R) ->
+ restore_schema(Schema, R);
+restore_schema([{schema, Tab, List} | Schema], R) ->
+ case restore_func(Tab, R) of
+ clear_tables ->
+ do_clear_table(Tab),
+ Where = val({Tab, where_to_commit}),
+ Snmp = val({Tab, snmp}),
+ RecName = val({Tab, record_name}),
+ R2 = R#r{tables = [{Tab, Where, Snmp, RecName} | R#r.tables]},
+ restore_schema(Schema, R2);
+ recreate_tables ->
+ TidTs = get_tid_ts_and_lock(Tab, write),
+ NC = {cookie, ?unique_cookie},
+ List2 = lists:keyreplace(cookie, 1, List, NC),
+ Where = where_to_commit(Tab, List2),
+ Snmp = pick(Tab, snmp, List2, []),
+ RecName = pick(Tab, record_name, List2, Tab),
+% case ?catch_val({Tab, cstruct}) of
+% {'EXIT', _} ->
+% ignore;
+% OldCs when record(OldCs, cstruct) ->
+% do_delete_table(Tab)
+% end,
+% unsafe_do_create_table(list2cs(List2)),
+ insert_schema_ops(TidTs, [{op, restore_recreate, List2}]),
+ R2 = R#r{tables = [{Tab, Where, Snmp, RecName} | R#r.tables]},
+ restore_schema(Schema, R2);
+ keep_tables ->
+ get_tid_ts_and_lock(Tab, write),
+ Where = val({Tab, where_to_commit}),
+ Snmp = val({Tab, snmp}),
+ RecName = val({Tab, record_name}),
+ R2 = R#r{tables = [{Tab, Where, Snmp, RecName} | R#r.tables]},
+ restore_schema(Schema, R2);
+ skip_tables ->
+ restore_schema(Schema, R)
+ end;
+
+restore_schema([{schema, Tab} | Schema], R) ->
+ do_delete_table(Tab),
+ Tabs = lists:delete(Tab,R#r.tables),
+ restore_schema(Schema, R#r{tables = Tabs});
+restore_schema([], R) ->
+ R.
+
+restore_tab_items([Rec | Rest], Tab, RecName, Where, Snmp, Recs, Op)
+ when element(1, Rec) == Tab ->
+ NewRecs = Op(Rec, Recs, RecName, Where, Snmp),
+ restore_tab_items(Rest, Tab, RecName, Where, Snmp, NewRecs, Op);
+
+restore_tab_items(Rest, _Tab, _RecName, _Where, _Snmp, Recs, _Op) ->
+ {Rest, Recs}.
+
+skip_tab_items([Rec| Rest], Tab)
+ when element(1, Rec) == Tab ->
+ skip_tab_items(Rest, Tab);
+skip_tab_items(Recs, _) ->
+ Recs.
+
+%%%%%%%%% Dump tables %%%%%%%%%%%%%
+dump_tables(Tabs) when list(Tabs) ->
+ schema_transaction(fun() -> do_dump_tables(Tabs) end);
+dump_tables(Tabs) ->
+ {aborted, {bad_type, Tabs}}.
+
+do_dump_tables(Tabs) ->
+ TidTs = get_tid_ts_and_lock(schema, write),
+ insert_schema_ops(TidTs, make_dump_tables(Tabs)).
+
+make_dump_tables([schema | _Tabs]) ->
+ mnesia:abort({bad_type, schema});
+make_dump_tables([Tab | Tabs]) ->
+ get_tid_ts_and_lock(Tab, read),
+ TabDef = get_create_list(Tab),
+ DiscResident = val({Tab, disc_copies}) ++ val({Tab, disc_only_copies}),
+ verify([], DiscResident,
+ {"Only allowed on ram_copies", Tab, DiscResident}),
+ [{op, dump_table, unknown, TabDef} | make_dump_tables(Tabs)];
+make_dump_tables([]) ->
+ [].
+
+%% Merge the local schema with the schema on other nodes
+merge_schema() ->
+ schema_transaction(fun() -> do_merge_schema() end).
+
+do_merge_schema() ->
+ {_Mod, Tid, Ts} = get_tid_ts_and_lock(schema, write),
+ Connected = val(recover_nodes),
+ Running = val({current, db_nodes}),
+ Store = Ts#tidstore.store,
+ case Connected -- Running of
+ [Node | _] ->
+ %% Time for a schema merging party!
+ mnesia_locker:wlock_no_exist(Tid, Store, schema, [Node]),
+
+ case rpc:call(Node, mnesia_controller, get_cstructs, []) of
+ {cstructs, Cstructs, RemoteRunning1} ->
+ LockedAlready = Running ++ [Node],
+ {New, Old} = mnesia_recover:connect_nodes(RemoteRunning1),
+ RemoteRunning = mnesia_lib:intersect(New ++ Old, RemoteRunning1),
+ if
+ RemoteRunning /= RemoteRunning1 ->
+ mnesia_lib:error("Mnesia on ~p could not connect to node(s) ~p~n",
+ [node(), RemoteRunning1 -- RemoteRunning]);
+ true -> ok
+ end,
+ NeedsLock = RemoteRunning -- LockedAlready,
+ mnesia_locker:wlock_no_exist(Tid, Store, schema, NeedsLock),
+
+ {value, SchemaCs} =
+ lists:keysearch(schema, #cstruct.name, Cstructs),
+
+ %% Announce that Node is running
+ A = [{op, announce_im_running, node(),
+ cs2list(SchemaCs), Running, RemoteRunning}],
+ do_insert_schema_ops(Store, A),
+
+ %% Introduce remote tables to local node
+ do_insert_schema_ops(Store, make_merge_schema(Node, Cstructs)),
+
+ %% Introduce local tables to remote nodes
+ Tabs = val({schema, tables}),
+ Ops = [{op, merge_schema, get_create_list(T)}
+ || T <- Tabs,
+ not lists:keymember(T, #cstruct.name, Cstructs)],
+ do_insert_schema_ops(Store, Ops),
+
+ %% Ensure that the txn will be committed on all nodes
+ announce_im_running(RemoteRunning, SchemaCs),
+ {merged, Running, RemoteRunning};
+ {error, Reason} ->
+ {"Cannot get cstructs", Node, Reason};
+ {badrpc, Reason} ->
+ {"Cannot get cstructs", Node, {badrpc, Reason}}
+ end;
+ [] ->
+ %% No more nodes to merge schema with
+ not_merged
+ end.
+
+make_merge_schema(Node, [Cs | Cstructs]) ->
+ Ops = do_make_merge_schema(Node, Cs),
+ Ops ++ make_merge_schema(Node, Cstructs);
+make_merge_schema(_Node, []) ->
+ [].
+
+%% Merge definitions of schema table
+do_make_merge_schema(Node, RemoteCs)
+ when RemoteCs#cstruct.name == schema ->
+ Cs = val({schema, cstruct}),
+ Masters = mnesia_recover:get_master_nodes(schema),
+ HasRemoteMaster = lists:member(Node, Masters),
+ HasLocalMaster = lists:member(node(), Masters),
+ Force = HasLocalMaster or HasRemoteMaster,
+ %% What is the storage types opinions?
+ StCsLocal = mnesia_lib:cs_to_storage_type(node(), Cs),
+ StRcsLocal = mnesia_lib:cs_to_storage_type(node(), RemoteCs),
+ StCsRemote = mnesia_lib:cs_to_storage_type(Node, Cs),
+ StRcsRemote = mnesia_lib:cs_to_storage_type(Node, RemoteCs),
+
+ if
+ Cs#cstruct.cookie == RemoteCs#cstruct.cookie,
+ Cs#cstruct.version == RemoteCs#cstruct.version ->
+ %% Great, we have the same cookie and version
+ %% and do not need to merge cstructs
+ [];
+
+ Cs#cstruct.cookie /= RemoteCs#cstruct.cookie,
+ Cs#cstruct.disc_copies /= [],
+ RemoteCs#cstruct.disc_copies /= [] ->
+ %% Both cstructs involves disc nodes
+ %% and we cannot merge them
+ if
+ HasLocalMaster == true,
+ HasRemoteMaster == false ->
+ %% Choose local cstruct,
+ %% since it's the master
+ [{op, merge_schema, cs2list(Cs)}];
+
+ HasRemoteMaster == true,
+ HasLocalMaster == false ->
+ %% Choose remote cstruct,
+ %% since it's the master
+ [{op, merge_schema, cs2list(RemoteCs)}];
+
+ true ->
+ Str = io_lib:format("Incompatible schema cookies. "
+ "Please, restart from old backup."
+ "~w = ~w, ~w = ~w~n",
+ [Node, cs2list(RemoteCs), node(), cs2list(Cs)]),
+ throw(Str)
+ end;
+
+ StCsLocal /= StRcsLocal, StRcsLocal /= unknown ->
+ Str = io_lib:format("Incompatible schema storage types. "
+ "on ~w storage ~w, on ~w storage ~w~n",
+ [node(), StCsLocal, Node, StRcsLocal]),
+ throw(Str);
+ StCsRemote /= StRcsRemote, StCsRemote /= unknown ->
+ Str = io_lib:format("Incompatible schema storage types. "
+ "on ~w storage ~w, on ~w storage ~w~n",
+ [node(), StCsRemote, Node, StRcsRemote]),
+ throw(Str);
+
+ Cs#cstruct.disc_copies /= [] ->
+ %% Choose local cstruct,
+ %% since it involves disc nodes
+ MergedCs = merge_cstructs(Cs, RemoteCs, Force),
+ [{op, merge_schema, cs2list(MergedCs)}];
+
+ RemoteCs#cstruct.disc_copies /= [] ->
+ %% Choose remote cstruct,
+ %% since it involves disc nodes
+ MergedCs = merge_cstructs(RemoteCs, Cs, Force),
+ [{op, merge_schema, cs2list(MergedCs)}];
+
+ Cs > RemoteCs ->
+ %% Choose remote cstruct
+ MergedCs = merge_cstructs(RemoteCs, Cs, Force),
+ [{op, merge_schema, cs2list(MergedCs)}];
+
+ true ->
+ %% Choose local cstruct
+ MergedCs = merge_cstructs(Cs, RemoteCs, Force),
+ [{op, merge_schema, cs2list(MergedCs)}]
+ end;
+
+%% Merge definitions of normal table
+do_make_merge_schema(Node, RemoteCs) ->
+ Tab = RemoteCs#cstruct.name,
+ Masters = mnesia_recover:get_master_nodes(schema),
+ HasRemoteMaster = lists:member(Node, Masters),
+ HasLocalMaster = lists:member(node(), Masters),
+ Force = HasLocalMaster or HasRemoteMaster,
+ case ?catch_val({Tab, cstruct}) of
+ {'EXIT', _} ->
+ %% A completely new table, created while Node was down
+ [{op, merge_schema, cs2list(RemoteCs)}];
+ Cs when Cs#cstruct.cookie == RemoteCs#cstruct.cookie ->
+ if
+ Cs#cstruct.version == RemoteCs#cstruct.version ->
+ %% We have exactly the same version of the
+ %% table def
+ [];
+
+ Cs#cstruct.version > RemoteCs#cstruct.version ->
+ %% Oops, we have different versions
+ %% of the table def, lets merge them.
+ %% The only changes that may have occurred
+ %% is that new replicas may have been added.
+ MergedCs = merge_cstructs(Cs, RemoteCs, Force),
+ [{op, merge_schema, cs2list(MergedCs)}];
+
+ Cs#cstruct.version < RemoteCs#cstruct.version ->
+ %% Oops, we have different versions
+ %% of the table def, lets merge them
+ MergedCs = merge_cstructs(RemoteCs, Cs, Force),
+ [{op, merge_schema, cs2list(MergedCs)}]
+ end;
+ Cs ->
+ %% Different cookies, not possible to merge
+ if
+ HasLocalMaster == true,
+ HasRemoteMaster == false ->
+ %% Choose local cstruct,
+ %% since it's the master
+ [{op, merge_schema, cs2list(Cs)}];
+
+ HasRemoteMaster == true,
+ HasLocalMaster == false ->
+ %% Choose remote cstruct,
+ %% since it's the master
+ [{op, merge_schema, cs2list(RemoteCs)}];
+
+ true ->
+ Str = io_lib:format("Bad cookie in table definition"
+ " ~w: ~w = ~w, ~w = ~w~n",
+ [Tab, node(), Cs, Node, RemoteCs]),
+ throw(Str)
+ end
+ end.
+
+%% Change of table definitions (cstructs) requires all replicas
+%% of the table to be active. New replicas, db_nodes and tables
+%% may however be added even if some replica is inactive. These
+%% invariants must be enforced in order to allow merge of cstructs.
+%%
+%% Returns a new cstruct or issues a fatal error
+merge_cstructs(Cs, RemoteCs, Force) ->
+ verify_cstruct(Cs),
+ case catch do_merge_cstructs(Cs, RemoteCs, Force) of
+ {'EXIT', {aborted, _Reason}} when Force == true ->
+ Cs;
+ {'EXIT', Reason} ->
+ exit(Reason);
+ MergedCs when record(MergedCs, cstruct) ->
+ MergedCs;
+ Other ->
+ throw(Other)
+ end.
+
+do_merge_cstructs(Cs, RemoteCs, Force) ->
+ verify_cstruct(RemoteCs),
+ Ns = mnesia_lib:uniq(mnesia_lib:cs_to_nodes(Cs) ++
+ mnesia_lib:cs_to_nodes(RemoteCs)),
+ {AnythingNew, MergedCs} =
+ merge_storage_type(Ns, false, Cs, RemoteCs, Force),
+ MergedCs2 = merge_versions(AnythingNew, MergedCs, RemoteCs, Force),
+ verify_cstruct(MergedCs2),
+ MergedCs2.
+
+merge_storage_type([N | Ns], AnythingNew, Cs, RemoteCs, Force) ->
+ Local = mnesia_lib:cs_to_storage_type(N, Cs),
+ Remote = mnesia_lib:cs_to_storage_type(N, RemoteCs),
+ case compare_storage_type(true, Local, Remote) of
+ {same, _Storage} ->
+ merge_storage_type(Ns, AnythingNew, Cs, RemoteCs, Force);
+ {diff, Storage} ->
+ Cs2 = change_storage_type(N, Storage, Cs),
+ merge_storage_type(Ns, true, Cs2, RemoteCs, Force);
+ incompatible when Force == true ->
+ merge_storage_type(Ns, AnythingNew, Cs, RemoteCs, Force);
+ Other ->
+ Str = io_lib:format("Cannot merge storage type for node ~w "
+ "in cstruct ~w with remote cstruct ~w (~w)~n",
+ [N, Cs, RemoteCs, Other]),
+ throw(Str)
+ end;
+merge_storage_type([], AnythingNew, MergedCs, _RemoteCs, _Force) ->
+ {AnythingNew, MergedCs}.
+
+compare_storage_type(_Retry, Any, Any) ->
+ {same, Any};
+compare_storage_type(_Retry, unknown, Any) ->
+ {diff, Any};
+compare_storage_type(_Retry, ram_copies, disc_copies) ->
+ {diff, disc_copies};
+compare_storage_type(_Retry, disc_copies, disc_only_copies) ->
+ {diff, disc_only_copies};
+compare_storage_type(true, One, Another) ->
+ compare_storage_type(false, Another, One);
+compare_storage_type(false, _One, _Another) ->
+ incompatible.
+
+change_storage_type(N, ram_copies, Cs) ->
+ Nodes = [N | Cs#cstruct.ram_copies],
+ Cs#cstruct{ram_copies = mnesia_lib:uniq(Nodes)};
+change_storage_type(N, disc_copies, Cs) ->
+ Nodes = [N | Cs#cstruct.disc_copies],
+ Cs#cstruct{disc_copies = mnesia_lib:uniq(Nodes)};
+change_storage_type(N, disc_only_copies, Cs) ->
+ Nodes = [N | Cs#cstruct.disc_only_copies],
+ Cs#cstruct{disc_only_copies = mnesia_lib:uniq(Nodes)}.
+
+%% BUGBUG: Verify match of frag info; equalit demanded for all but add_node
+
+merge_versions(AnythingNew, Cs, RemoteCs, Force) ->
+ if
+ Cs#cstruct.name == schema ->
+ ok;
+ Cs#cstruct.name /= schema,
+ Cs#cstruct.cookie == RemoteCs#cstruct.cookie ->
+ ok;
+ Force == true ->
+ ok;
+ true ->
+ Str = io_lib:format("Bad cookies. Cannot merge definitions of "
+ "table ~w. Local = ~w, Remote = ~w~n",
+ [Cs#cstruct.name, Cs, RemoteCs]),
+ throw(Str)
+ end,
+ if
+ Cs#cstruct.name == RemoteCs#cstruct.name,
+ Cs#cstruct.type == RemoteCs#cstruct.type,
+ Cs#cstruct.local_content == RemoteCs#cstruct.local_content,
+ Cs#cstruct.attributes == RemoteCs#cstruct.attributes,
+ Cs#cstruct.index == RemoteCs#cstruct.index,
+ Cs#cstruct.snmp == RemoteCs#cstruct.snmp,
+ Cs#cstruct.access_mode == RemoteCs#cstruct.access_mode,
+ Cs#cstruct.load_order == RemoteCs#cstruct.load_order,
+ Cs#cstruct.user_properties == RemoteCs#cstruct.user_properties ->
+ do_merge_versions(AnythingNew, Cs, RemoteCs);
+ Force == true ->
+ do_merge_versions(AnythingNew, Cs, RemoteCs);
+ true ->
+ Str1 = io_lib:format("Cannot merge definitions of "
+ "table ~w. Local = ~w, Remote = ~w~n",
+ [Cs#cstruct.name, Cs, RemoteCs]),
+ throw(Str1)
+ end.
+
+do_merge_versions(AnythingNew, MergedCs, RemoteCs) ->
+ {{Major1, Minor1}, _Detail1} = MergedCs#cstruct.version,
+ {{Major2, Minor2}, _Detail2} = RemoteCs#cstruct.version,
+ if
+ MergedCs#cstruct.version == RemoteCs#cstruct.version ->
+ MergedCs;
+ AnythingNew == false ->
+ MergedCs;
+ Major1 == Major2 ->
+ Minor = lists:max([Minor1, Minor2]),
+ V = {{Major1, Minor}, dummy},
+ incr_version(MergedCs#cstruct{version = V});
+ Major1 /= Major2 ->
+ Major = lists:max([Major1, Major2]),
+ V = {{Major, 0}, dummy},
+ incr_version(MergedCs#cstruct{version = V})
+ end.
+
+announce_im_running([N | Ns], SchemaCs) ->
+ {L1, L2} = mnesia_recover:connect_nodes([N]),
+ case lists:member(N, L1) or lists:member(N, L2) of
+ true ->
+%% dbg_out("Adding ~p to {current db_nodes} ~n", [N]), %% qqqq
+ mnesia_lib:add({current, db_nodes}, N),
+ mnesia_controller:add_active_replica(schema, N, SchemaCs);
+ false ->
+ ignore
+ end,
+ announce_im_running(Ns, SchemaCs);
+announce_im_running([], _) ->
+ [].
+
+unannounce_im_running([N | Ns]) ->
+ mnesia_lib:del({current, db_nodes}, N),
+ mnesia_controller:del_active_replica(schema, N),
+ mnesia_recover:disconnect(N),
+ unannounce_im_running(Ns);
+unannounce_im_running([]) ->
+ [].
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_snmp_hook.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_snmp_hook.erl
new file mode 100644
index 0000000000..ad88bc6e6a
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_snmp_hook.erl
@@ -0,0 +1,271 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_snmp_hook.erl,v 1.1 2008/12/17 09:53:39 mikpe Exp $
+%%
+-module(mnesia_snmp_hook).
+
+%% Hooks (called from mnesia)
+-export([check_ustruct/1, create_table/3, delete_table/2,
+ key_to_oid/3, update/1, start/2,
+ get_row/2, get_next_index/2, get_mnesia_key/2]).
+
+%% sys callback functions
+-export([system_continue/3,
+ system_terminate/4,
+ system_code_change/4
+ ]).
+
+%% Internal exports
+-export([b_init/2]).
+
+check_ustruct([]) ->
+ true; %% default value, not SNMP'ified
+check_ustruct([{key, Types}]) ->
+ is_snmp_type(to_list(Types));
+check_ustruct(_) -> false.
+
+to_list(Tuple) when tuple(Tuple) -> tuple_to_list(Tuple);
+to_list(X) -> [X].
+
+is_snmp_type([integer | T]) -> is_snmp_type(T);
+is_snmp_type([string | T]) -> is_snmp_type(T);
+is_snmp_type([fix_string | T]) -> is_snmp_type(T);
+is_snmp_type([]) -> true;
+is_snmp_type(_) -> false.
+
+create_table([], MnesiaTab, _Storage) ->
+ mnesia:abort({badarg, MnesiaTab, {snmp, empty_snmpstruct}});
+
+create_table([{key, Us}], MnesiaTab, Storage) ->
+ Tree = b_new(MnesiaTab, Us),
+ mnesia_lib:db_fixtable(Storage, MnesiaTab, true),
+ First = mnesia_lib:db_first(Storage, MnesiaTab),
+ build_table(First, MnesiaTab, Tree, Us, Storage),
+ mnesia_lib:db_fixtable(Storage, MnesiaTab, false),
+ Tree.
+
+build_table(MnesiaKey, MnesiaTab, Tree, Us, Storage)
+ when MnesiaKey /= '$end_of_table' ->
+%% SnmpKey = key_to_oid(MnesiaTab, MnesiaKey, Us),
+%% update(write, Tree, MnesiaKey, SnmpKey),
+ update(write, Tree, MnesiaKey, MnesiaKey),
+ Next = mnesia_lib:db_next_key(Storage, MnesiaTab, MnesiaKey),
+ build_table(Next, MnesiaTab, Tree, Us, Storage);
+build_table('$end_of_table', _MnesiaTab, _Tree, _Us, _Storage) ->
+ ok.
+
+delete_table(_MnesiaTab, Tree) ->
+ exit(Tree, shutdown),
+ ok.
+
+%%-----------------------------------------------------------------
+%% update({Op, MnesiaTab, MnesiaKey, SnmpKey})
+%%-----------------------------------------------------------------
+
+update({clear_table, MnesiaTab}) ->
+ Tree = mnesia_lib:val({MnesiaTab, {index, snmp}}),
+ b_clear(Tree);
+
+update({Op, MnesiaTab, MnesiaKey, SnmpKey}) ->
+ Tree = mnesia_lib:val({MnesiaTab, {index, snmp}}),
+ update(Op, Tree, MnesiaKey, SnmpKey).
+
+update(Op, Tree, MnesiaKey, _) ->
+ case Op of
+ write ->
+ b_insert(Tree, MnesiaKey, MnesiaKey);
+ update_counter ->
+ ignore;
+ delete ->
+ b_delete(Tree, MnesiaKey);
+ delete_object ->
+ b_delete(Tree, MnesiaKey)
+ end,
+ ok.
+
+%%-----------------------------------------------------------------
+%% Func: key_to_oid(Tab, Key, Ustruct)
+%% Args: Key ::= key()
+%% key() ::= int() | string() | {int() | string()}
+%% Type ::= {fix_string | term()}
+%% Make an OBJECT IDENTIFIER out of it.
+%% Variable length objects are prepended by their length.
+%% Ex. Key = {"pelle", 42} AND Type = {string, integer} =>
+%% OID [5, $p, $e, $l, $l, $e, 42]
+%% Key = {"pelle", 42} AND Type = {fix_string, integer} =>
+%% OID [$p, $e, $l, $l, $e, 42]
+%%-----------------------------------------------------------------
+key_to_oid(Tab, Key, [{key, Types}]) ->
+ MnesiaOid = {Tab, Key},
+ if
+ tuple(Key), tuple(Types) ->
+ case {size(Key), size(Types)} of
+ {Size, Size} ->
+ keys_to_oid(MnesiaOid, Size, Key, [], Types);
+ _ ->
+ exit({bad_snmp_key, MnesiaOid})
+ end;
+ true ->
+ key_to_oid_i(MnesiaOid, Key, Types)
+ end.
+
+key_to_oid_i(_MnesiaOid, Key, integer) when integer(Key) -> [Key];
+key_to_oid_i(_MnesiaOid, Key, fix_string) when list(Key) -> Key;
+key_to_oid_i(_MnesiaOid, Key, string) when list(Key) -> [length(Key) | Key];
+key_to_oid_i(MnesiaOid, Key, Type) ->
+ exit({bad_snmp_key, [MnesiaOid, Key, Type]}).
+
+keys_to_oid(_MnesiaOid, 0, _Key, Oid, _Types) -> Oid;
+keys_to_oid(MnesiaOid, N, Key, Oid, Types) ->
+ Type = element(N, Types),
+ KeyPart = element(N, Key),
+ Oid2 = key_to_oid_i(MnesiaOid, KeyPart, Type) ++ Oid,
+ keys_to_oid(MnesiaOid, N-1, Key, Oid2, Types).
+
+%%-----------------------------------------------------------------
+%% Func: get_row/2
+%% Args: Name is the name of the table (atom)
+%% RowIndex is an Oid
+%% Returns: {ok, Row} | undefined
+%% Note that the Row returned might contain columns that
+%% are not visible via SNMP. e.g. the first column may be
+%% ifIndex, and the last MFA ({ifIndex, col1, col2, MFA}).
+%% where ifIndex is used only as index (not as a real col),
+%% and MFA as extra info, used by the application.
+%%-----------------------------------------------------------------
+get_row(Name, RowIndex) ->
+ Tree = mnesia_lib:val({Name, {index, snmp}}),
+ case b_lookup(Tree, RowIndex) of
+ {ok, {_RowIndex, Key}} ->
+ [Row] = mnesia:dirty_read({Name, Key}),
+ {ok, Row};
+ _ ->
+ undefined
+ end.
+
+%%-----------------------------------------------------------------
+%% Func: get_next_index/2
+%% Args: Name is the name of the table (atom)
+%% RowIndex is an Oid
+%% Returns: {ok, NextIndex} | endOfTable
+%%-----------------------------------------------------------------
+get_next_index(Name, RowIndex) ->
+ Tree = mnesia_lib:val({Name, {index, snmp}}),
+ case b_lookup_next(Tree, RowIndex) of
+ {ok, {NextIndex, _Key}} ->
+ {ok, NextIndex};
+ _ ->
+ endOfTable
+ end.
+
+%%-----------------------------------------------------------------
+%% Func: get_mnesia_key/2
+%% Purpose: Get the mnesia key corresponding to the RowIndex.
+%% Args: Name is the name of the table (atom)
+%% RowIndex is an Oid
+%% Returns: {ok, Key} | undefiend
+%%-----------------------------------------------------------------
+get_mnesia_key(Name, RowIndex) ->
+ Tree = mnesia_lib:val({Name, {index, snmp}}),
+ case b_lookup(Tree, RowIndex) of
+ {ok, {_RowIndex, Key}} ->
+ {ok, Key};
+ _ ->
+ undefined
+ end.
+
+%%-----------------------------------------------------------------
+%% Encapsulate a bplus_tree in a process.
+%%-----------------------------------------------------------------
+
+b_new(MnesiaTab, Us) ->
+ case supervisor:start_child(mnesia_snmp_sup, [MnesiaTab, Us]) of
+ {ok, Tree} ->
+ Tree;
+ {error, Reason} ->
+ exit({badsnmp, MnesiaTab, Reason})
+ end.
+
+start(MnesiaTab, Us) ->
+ Name = {mnesia_snmp, MnesiaTab},
+ mnesia_monitor:start_proc(Name, ?MODULE, b_init, [self(), Us]).
+
+b_insert(Tree, Key, Val) -> Tree ! {insert, Key, Val}.
+b_delete(Tree, Key) -> Tree ! {delete, Key}.
+b_lookup(Tree, Key) ->
+ Tree ! {lookup, self(), Key},
+ receive
+ {bplus_res, Res} ->
+ Res
+ end.
+b_lookup_next(Tree, Key) ->
+ Tree ! {lookup_next, self(), Key},
+ receive
+ {bplus_res, Res} ->
+ Res
+ end.
+
+b_clear(Tree) ->
+ Tree ! clear,
+ ok.
+
+b_init(Parent, Us) ->
+ %% Do not trap exit
+ Tree = snmp_index:new(Us),
+ proc_lib:init_ack(Parent, {ok, self()}),
+ b_loop(Parent, Tree, Us).
+
+b_loop(Parent, Tree, Us) ->
+ receive
+ {insert, Key, Val} ->
+ NTree = snmp_index:insert(Tree, Key, Val),
+ b_loop(Parent, NTree, Us);
+ {delete, Key} ->
+ NTree = snmp_index:delete(Tree, Key),
+ b_loop(Parent, NTree, Us);
+ {lookup, From, Key} ->
+ Res = snmp_index:get(Tree, Key),
+ From ! {bplus_res, Res},
+ b_loop(Parent, Tree, Us);
+ {lookup_next, From, Key} ->
+ Res = snmp_index:get_next(Tree, Key),
+ From ! {bplus_res, Res},
+ b_loop(Parent, Tree, Us);
+ clear ->
+ catch snmp_index:delete(Tree), %% Catch because delete/1 is not
+ NewTree = snmp_index:new(Us), %% available in old snmp (before R5)
+ b_loop(Parent, NewTree, Us);
+
+ {'EXIT', Parent, Reason} ->
+ exit(Reason);
+
+ {system, From, Msg} ->
+ mnesia_lib:dbg_out("~p got {system, ~p, ~p}~n", [?MODULE, From, Msg]),
+ sys:handle_system_msg(Msg, From, Parent, ?MODULE, [], {Tree, Us})
+
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% System upgrade
+
+system_continue(Parent, _Debug, {Tree, Us}) ->
+ b_loop(Parent, Tree, Us).
+
+system_terminate(Reason, _Parent, _Debug, _Tree) ->
+ exit(Reason).
+
+system_code_change(State, _Module, _OldVsn, _Extra) ->
+ {ok, State}.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_snmp_sup.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_snmp_sup.erl
new file mode 100644
index 0000000000..227eec060f
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_snmp_sup.erl
@@ -0,0 +1,39 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_snmp_sup.erl,v 1.1 2008/12/17 09:53:39 mikpe Exp $
+%%
+-module(mnesia_snmp_sup).
+
+-behaviour(supervisor).
+
+-export([start/0, init/1]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% top supervisor callback functions
+
+start() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% sub supervisor callback functions
+
+init([]) ->
+ Flags = {simple_one_for_one, 0, timer:hours(24)}, % Trust the top supervisor
+ MFA = {mnesia_snmp_hook, start, []},
+ Modules = [?MODULE, mnesia_snmp_hook, supervisor],
+ KillAfter = mnesia_kernel_sup:supervisor_timeout(timer:seconds(3)),
+ Workers = [{?MODULE, MFA, transient, KillAfter, worker, Modules}],
+ {ok, {Flags, Workers}}.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_sp.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_sp.erl
new file mode 100644
index 0000000000..bc52ad7f84
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_sp.erl
@@ -0,0 +1,35 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_sp.erl,v 1.1 2008/12/17 09:53:39 mikpe Exp $
+%%
+
+%% To able to generate nice crash reports we need a catch on the highest level.
+%% This code can't be purged so a code change is not possible.
+%% And hence this a simple module.
+
+-module(mnesia_sp).
+
+-export([init_proc/4]).
+
+init_proc(Who, Mod, Fun, Args) ->
+ mnesia_lib:verbose("~p starting: ~p~n", [Who, self()]),
+ case catch apply(Mod, Fun, Args) of
+ {'EXIT', Reason} ->
+ mnesia_monitor:terminate_proc(Who, Reason, Args),
+ exit(Reason);
+ Other ->
+ Other
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_subscr.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_subscr.erl
new file mode 100644
index 0000000000..dc66451206
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_subscr.erl
@@ -0,0 +1,491 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_subscr.erl,v 1.1 2008/12/17 09:53:39 mikpe Exp $
+%%
+-module(mnesia_subscr).
+
+-behaviour(gen_server).
+
+-export([start/0,
+ set_debug_level/1,
+ subscribe/2,
+ unsubscribe/2,
+ unsubscribe_table/1,
+ subscribers/0,
+ report_table_event/4,
+ report_table_event/5,
+ report_table_event/6
+ ]).
+
+%% gen_server callbacks
+-export([init/1,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ terminate/2,
+ code_change/3
+ ]).
+
+-include("mnesia.hrl").
+
+-import(mnesia_lib, [error/2]).
+-record(state, {supervisor, pid_tab}).
+
+start() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [self()],
+ [{timeout, infinity}]).
+
+set_debug_level(Level) ->
+ OldEnv = application:get_env(mnesia, debug),
+ case mnesia_monitor:patch_env(debug, Level) of
+ {error, Reason} ->
+ {error, Reason};
+ NewLevel ->
+ set_debug_level(NewLevel, OldEnv)
+ end.
+
+set_debug_level(Level, OldEnv) ->
+ case mnesia:system_info(is_running) of
+ no when OldEnv == undefined ->
+ none;
+ no ->
+ {ok, E} = OldEnv,
+ E;
+ _ ->
+ Old = mnesia_lib:val(debug),
+ Local = mnesia:system_info(local_tables),
+ E = whereis(mnesia_event),
+ Sub = fun(Tab) -> subscribe(E, {table, Tab}) end,
+ UnSub = fun(Tab) -> unsubscribe(E, {table, Tab}) end,
+
+ case Level of
+ none ->
+ lists:foreach(UnSub, Local);
+ verbose ->
+ lists:foreach(UnSub, Local);
+ debug ->
+ lists:foreach(UnSub, Local -- [schema]),
+ Sub(schema);
+ trace ->
+ lists:foreach(Sub, Local)
+ end,
+ mnesia_lib:set(debug, Level),
+ Old
+ end.
+
+subscribe(ClientPid, system) ->
+ change_subscr(activate, ClientPid, system);
+subscribe(ClientPid, {table, Tab}) ->
+ change_subscr(activate, ClientPid, {table, Tab, simple});
+subscribe(ClientPid, {table, Tab, simple}) ->
+ change_subscr(activate, ClientPid, {table, Tab, simple});
+subscribe(ClientPid, {table, Tab, detailed}) ->
+ change_subscr(activate, ClientPid, {table, Tab, detailed});
+subscribe(_ClientPid, What) ->
+ {error, {badarg, What}}.
+
+unsubscribe(ClientPid, system) ->
+ change_subscr(deactivate, ClientPid, system);
+unsubscribe(ClientPid, {table, Tab}) ->
+ change_subscr(deactivate, ClientPid, {table, Tab, simple});
+unsubscribe(ClientPid, {table, Tab, simple}) ->
+ change_subscr(deactivate, ClientPid, {table, Tab, simple});
+unsubscribe(ClientPid, {table, Tab, detailed}) ->
+ change_subscr(deactivate, ClientPid, {table, Tab, detailed});
+unsubscribe(_ClientPid, What) ->
+ {error, {badarg, What}}.
+
+unsubscribe_table(Tab) ->
+ call({change, {deactivate_table, Tab}}).
+
+change_subscr(Kind, ClientPid, What) ->
+ call({change, {Kind, ClientPid, What}}).
+
+subscribers() ->
+ [whereis(mnesia_event) | mnesia_lib:val(subscribers)].
+
+report_table_event(Tab, Tid, Obj, Op) ->
+ case ?catch_val({Tab, commit_work}) of
+ {'EXIT', _} -> ok;
+ Commit ->
+ case lists:keysearch(subscribers, 1, Commit) of
+ false -> ok;
+ {value, Subs} ->
+ report_table_event(Subs, Tab, Tid, Obj, Op, undefined)
+ end
+ end.
+
+%% Backwards compatible for the moment when mnesia_tm get's updated!
+report_table_event(Subscr, Tab, Tid, Obj, Op) ->
+ report_table_event(Subscr, Tab, Tid, Obj, Op, undefined).
+
+report_table_event({subscribers, S1, S2}, Tab, Tid, _Obj, clear_table, _Old) ->
+ What = {delete, {schema, Tab}, Tid},
+ deliver(S1, {mnesia_table_event, What}),
+ TabDef = mnesia_schema:cs2list(?catch_val({Tab, cstruct})),
+ What2 = {write, {schema, Tab, TabDef}, Tid},
+ deliver(S1, {mnesia_table_event, What2}),
+ What3 = {delete, schema, {schema, Tab}, [{schema, Tab, TabDef}], Tid},
+ deliver(S2, {mnesia_table_event, What3}),
+ What4 = {write, schema, {schema, Tab, TabDef}, [], Tid},
+ deliver(S2, {mnesia_table_event, What4});
+
+report_table_event({subscribers, Subscr, []}, Tab, Tid, Obj, Op, _Old) ->
+ What = {Op, patch_record(Tab, Obj), Tid},
+ deliver(Subscr, {mnesia_table_event, What});
+
+report_table_event({subscribers, S1, S2}, Tab, Tid, Obj, Op, Old) ->
+ Standard = {Op, patch_record(Tab, Obj), Tid},
+ deliver(S1, {mnesia_table_event, Standard}),
+ Extended = what(Tab, Tid, Obj, Op, Old),
+ deliver(S2, Extended);
+
+%% Backwards compatible for the moment when mnesia_tm get's updated!
+report_table_event({subscribers, Subscr}, Tab, Tid, Obj, Op, Old) ->
+ report_table_event({subscribers, Subscr, []}, Tab, Tid, Obj, Op, Old).
+
+
+patch_record(Tab, Obj) ->
+ case Tab == element(1, Obj) of
+ true ->
+ Obj;
+ false ->
+ setelement(1, Obj, Tab)
+ end.
+
+what(Tab, Tid, {RecName, Key}, delete, undefined) ->
+ case catch mnesia_lib:db_get(Tab, Key) of
+ Old when list(Old) -> %% Op only allowed for set table.
+ {mnesia_table_event, {delete, Tab, {RecName, Key}, Old, Tid}};
+ _ ->
+ %% Record just deleted by a dirty_op or
+ %% the whole table has been deleted
+ ignore
+ end;
+what(Tab, Tid, Obj, delete, Old) ->
+ {mnesia_table_event, {delete, Tab, Obj, Old, Tid}};
+what(Tab, Tid, Obj, delete_object, _Old) ->
+ {mnesia_table_event, {delete, Tab, Obj, [Obj], Tid}};
+what(Tab, Tid, Obj, write, undefined) ->
+ case catch mnesia_lib:db_get(Tab, element(2, Obj)) of
+ Old when list(Old) ->
+ {mnesia_table_event, {write, Tab, Obj, Old, Tid}};
+ {'EXIT', _} ->
+ ignore
+ end.
+
+deliver(_, ignore) ->
+ ok;
+deliver([Pid | Pids], Msg) ->
+ Pid ! Msg,
+ deliver(Pids, Msg);
+deliver([], _Msg) ->
+ ok.
+
+call(Msg) ->
+ Pid = whereis(?MODULE),
+ case Pid of
+ undefined ->
+ {error, {node_not_running, node()}};
+ Pid ->
+ Res = gen_server:call(Pid, Msg, infinity),
+ %% We get an exit signal if server dies
+ receive
+ {'EXIT', _Pid, _Reason} ->
+ {error, {node_not_running, node()}}
+ after 0 ->
+ ignore
+ end,
+ Res
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% Callback functions from gen_server
+
+%%----------------------------------------------------------------------
+%% Func: init/1
+%% Returns: {ok, State} |
+%% {ok, State, Timeout} |
+%% {stop, Reason}
+%%----------------------------------------------------------------------
+init([Parent]) ->
+ process_flag(trap_exit, true),
+ ClientPid = whereis(mnesia_event),
+ link(ClientPid),
+ mnesia_lib:verbose("~p starting: ~p~n", [?MODULE, self()]),
+ Tab = ?ets_new_table(mnesia_subscr, [duplicate_bag, private]),
+ ?ets_insert(Tab, {ClientPid, system}),
+ {ok, #state{supervisor = Parent, pid_tab = Tab}}.
+
+%%----------------------------------------------------------------------
+%% Func: handle_call/3
+%% Returns: {reply, Reply, State} |
+%% {reply, Reply, State, Timeout} |
+%% {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, Reply, State} | (terminate/2 is called)
+%%----------------------------------------------------------------------
+handle_call({change, How}, _From, State) ->
+ Reply = do_change(How, State#state.pid_tab),
+ {reply, Reply, State};
+
+handle_call(Msg, _From, State) ->
+ error("~p got unexpected call: ~p~n", [?MODULE, Msg]),
+ {noreply, State}.
+
+%%----------------------------------------------------------------------
+%% Func: handle_cast/2
+%% Returns: {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State} (terminate/2 is called)
+%%----------------------------------------------------------------------
+handle_cast(Msg, State) ->
+ error("~p got unexpected cast: ~p~n", [?MODULE, Msg]),
+ {noreply, State}.
+
+%%----------------------------------------------------------------------
+%% Func: handle_info/2
+%% Returns: {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State} (terminate/2 is called)
+%%----------------------------------------------------------------------
+
+handle_info({'EXIT', Pid, _R}, State) when Pid == State#state.supervisor ->
+ {stop, shutdown, State};
+
+handle_info({'EXIT', Pid, _Reason}, State) ->
+ handle_exit(Pid, State#state.pid_tab),
+ {noreply, State};
+
+handle_info(Msg, State) ->
+ error("~p got unexpected info: ~p~n", [?MODULE, Msg]),
+ {noreply, State}.
+
+%%----------------------------------------------------------------------
+%% Func: terminate/2
+%% Purpose: Shutdown the server
+%% Returns: any (ignored by gen_server)
+%%----------------------------------------------------------------------
+terminate(Reason, State) ->
+ prepare_stop(State#state.pid_tab),
+ mnesia_monitor:terminate_proc(?MODULE, Reason, State).
+
+%%----------------------------------------------------------------------
+%% Func: code_change/3
+%% Purpose: Upgrade process when its code is to be changed
+%% Returns: {ok, NewState}
+%%----------------------------------------------------------------------
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%%----------------------------------------------------------------------
+%%% Internal functions
+%%%----------------------------------------------------------------------
+
+do_change({activate, ClientPid, system}, SubscrTab) when pid(ClientPid) ->
+ Var = subscribers,
+ activate(ClientPid, system, Var, subscribers(), SubscrTab);
+do_change({activate, ClientPid, {table, Tab, How}}, SubscrTab) when pid(ClientPid) ->
+ case ?catch_val({Tab, where_to_read}) of
+ Node when Node == node() ->
+ Var = {Tab, commit_work},
+ activate(ClientPid, {table, Tab, How}, Var, mnesia_lib:val(Var), SubscrTab);
+ {'EXIT', _} ->
+ {error, {no_exists, Tab}};
+ _Node ->
+ {error, {not_active_local, Tab}}
+ end;
+do_change({deactivate, ClientPid, system}, SubscrTab) ->
+ Var = subscribers,
+ deactivate(ClientPid, system, Var, SubscrTab);
+do_change({deactivate, ClientPid, {table, Tab, How}}, SubscrTab) ->
+ Var = {Tab, commit_work},
+ deactivate(ClientPid, {table, Tab, How}, Var, SubscrTab);
+do_change({deactivate_table, Tab}, SubscrTab) ->
+ Var = {Tab, commit_work},
+ case ?catch_val(Var) of
+ {'EXIT', _} ->
+ {error, {no_exists, Tab}};
+ CommitWork ->
+ case lists:keysearch(subscribers, 1, CommitWork) of
+ false ->
+ ok;
+ {value, Subs} ->
+ Simple = {table, Tab, simple},
+ Detailed = {table, Tab, detailed},
+ Fs = fun(C) -> deactivate(C, Simple, Var, SubscrTab) end,
+ Fd = fun(C) -> deactivate(C, Detailed, Var, SubscrTab) end,
+ case Subs of
+ {subscribers, L1, L2} ->
+ lists:foreach(Fs, L1),
+ lists:foreach(Fd, L2);
+ {subscribers, L1} ->
+ lists:foreach(Fs, L1)
+ end
+ end,
+ {ok, node()}
+ end;
+do_change(_, _) ->
+ {error, badarg}.
+
+activate(ClientPid, What, Var, OldSubscribers, SubscrTab) ->
+ Old =
+ if Var == subscribers ->
+ OldSubscribers;
+ true ->
+ case lists:keysearch(subscribers, 1, OldSubscribers) of
+ false -> [];
+ {value, Subs} ->
+ case Subs of
+ {subscribers, L1, L2} ->
+ L1 ++ L2;
+ {subscribers, L1} ->
+ L1
+ end
+ end
+ end,
+ case lists:member(ClientPid, Old) of
+ false ->
+ %% Don't care about checking old links
+ case catch link(ClientPid) of
+ true ->
+ ?ets_insert(SubscrTab, {ClientPid, What}),
+ add_subscr(Var, What, ClientPid),
+ {ok, node()};
+ {'EXIT', _Reason} ->
+ {error, {no_exists, ClientPid}}
+ end;
+ true ->
+ {error, {already_exists, What}}
+ end.
+
+%%-record(subscribers, {pids = []}). Old subscriber record removed
+%% To solve backward compatibility, this code is a cludge..
+add_subscr(subscribers, _What, Pid) ->
+ mnesia_lib:add(subscribers, Pid),
+ {ok, node()};
+add_subscr({Tab, commit_work}, What, Pid) ->
+ Commit = mnesia_lib:val({Tab, commit_work}),
+ case lists:keysearch(subscribers, 1, Commit) of
+ false ->
+ Subscr =
+ case What of
+ {table, _, simple} ->
+ {subscribers, [Pid], []};
+ {table, _, detailed} ->
+ {subscribers, [], [Pid]}
+ end,
+ mnesia_lib:add({Tab, subscribers}, Pid),
+ mnesia_lib:set({Tab, commit_work},
+ mnesia_lib:sort_commit([Subscr | Commit]));
+ {value, Old} ->
+ {L1, L2} =
+ case Old of
+ {subscribers, L} -> %% Old Way
+ {L, []};
+ {subscribers, SL1, SL2} ->
+ {SL1, SL2}
+ end,
+ Subscr =
+ case What of
+ {table, _, simple} ->
+ {subscribers, [Pid | L1], L2};
+ {table, _, detailed} ->
+ {subscribers, L1, [Pid | L2]}
+ end,
+ NewC = lists:keyreplace(subscribers, 1, Commit, Subscr),
+ mnesia_lib:set({Tab, commit_work},
+ mnesia_lib:sort_commit(NewC)),
+ mnesia_lib:add({Tab, subscribers}, Pid)
+ end.
+
+deactivate(ClientPid, What, Var, SubscrTab) ->
+ ?ets_match_delete(SubscrTab, {ClientPid, What}),
+ case catch ?ets_lookup_element(SubscrTab, ClientPid, 1) of
+ List when list(List) ->
+ ignore;
+ {'EXIT', _} ->
+ unlink(ClientPid)
+ end,
+ del_subscr(Var, What, ClientPid),
+ {ok, node()}.
+
+del_subscr(subscribers, _What, Pid) ->
+ mnesia_lib:del(subscribers, Pid);
+del_subscr({Tab, commit_work}, What, Pid) ->
+ Commit = mnesia_lib:val({Tab, commit_work}),
+ case lists:keysearch(subscribers, 1, Commit) of
+ false ->
+ false;
+ {value, Old} ->
+ {L1, L2} =
+ case Old of
+ {subscribers, L} -> %% Old Way
+ {L, []};
+ {subscribers, SL1, SL2} ->
+ {SL1, SL2}
+ end,
+ Subscr =
+ case What of %% Ignore user error delete subscr from any list
+ {table, _, simple} ->
+ NewL1 = lists:delete(Pid, L1),
+ NewL2 = lists:delete(Pid, L2),
+ {subscribers, NewL1, NewL2};
+ {table, _, detailed} ->
+ NewL1 = lists:delete(Pid, L1),
+ NewL2 = lists:delete(Pid, L2),
+ {subscribers, NewL1, NewL2}
+ end,
+ case Subscr of
+ {subscribers, [], []} ->
+ NewC = lists:keydelete(subscribers, 1, Commit),
+ mnesia_lib:del({Tab, subscribers}, Pid),
+ mnesia_lib:set({Tab, commit_work},
+ mnesia_lib:sort_commit(NewC));
+ _ ->
+ NewC = lists:keyreplace(subscribers, 1, Commit, Subscr),
+ mnesia_lib:del({Tab, subscribers}, Pid),
+ mnesia_lib:set({Tab, commit_work},
+ mnesia_lib:sort_commit(NewC))
+ end
+ end.
+
+handle_exit(ClientPid, SubscrTab) ->
+ do_handle_exit(?ets_lookup(SubscrTab, ClientPid)),
+ ?ets_delete(SubscrTab, ClientPid).
+
+do_handle_exit([{ClientPid, What} | Tail]) ->
+ case What of
+ system ->
+ del_subscr(subscribers, What, ClientPid);
+ {_, Tab, _Level} ->
+ del_subscr({Tab, commit_work}, What, ClientPid)
+ end,
+ do_handle_exit(Tail);
+do_handle_exit([]) ->
+ ok.
+
+prepare_stop(SubscrTab) ->
+ mnesia_lib:report_system_event({mnesia_down, node()}),
+ do_prepare_stop(?ets_first(SubscrTab), SubscrTab).
+
+do_prepare_stop('$end_of_table', _SubscrTab) ->
+ ok;
+do_prepare_stop(ClientPid, SubscrTab) ->
+ Next = ?ets_next(SubscrTab, ClientPid),
+ handle_exit(ClientPid, SubscrTab),
+ unlink(ClientPid),
+ do_prepare_stop(Next, SubscrTab).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_sup.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_sup.erl
new file mode 100644
index 0000000000..78609ffdde
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_sup.erl
@@ -0,0 +1,136 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_sup.erl,v 1.1 2008/12/17 09:53:39 mikpe Exp $
+%%
+%% Supervisor for the entire Mnesia application
+
+-module(mnesia_sup).
+
+-behaviour(application).
+-behaviour(supervisor).
+
+-export([start/0, start/2, init/1, stop/1, start_event/0, kill/0]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% application and suprvisor callback functions
+
+start(normal, Args) ->
+ SupName = {local,?MODULE},
+ case supervisor:start_link(SupName, ?MODULE, [Args]) of
+ {ok, Pid} ->
+ {ok, Pid, {normal, Args}};
+ Error ->
+ Error
+ end;
+start(_, _) ->
+ {error, badarg}.
+
+start() ->
+ SupName = {local,?MODULE},
+ supervisor:start_link(SupName, ?MODULE, []).
+
+stop(_StartArgs) ->
+ ok.
+
+init([]) -> % Supervisor
+ init();
+init([[]]) -> % Application
+ init();
+init(BadArg) ->
+ {error, {badarg, BadArg}}.
+
+init() ->
+ Flags = {one_for_all, 0, 3600}, % Should be rest_for_one policy
+
+ Event = event_procs(),
+ Kernel = kernel_procs(),
+ Mnemosyne = mnemosyne_procs(),
+
+ {ok, {Flags, Event ++ Kernel ++ Mnemosyne}}.
+
+event_procs() ->
+ KillAfter = timer:seconds(30),
+ KA = mnesia_kernel_sup:supervisor_timeout(KillAfter),
+ E = mnesia_event,
+ [{E, {?MODULE, start_event, []}, permanent, KA, worker, [E, gen_event]}].
+
+kernel_procs() ->
+ K = mnesia_kernel_sup,
+ KA = infinity,
+ [{K, {K, start, []}, permanent, KA, supervisor, [K, supervisor]}].
+
+mnemosyne_procs() ->
+ case mnesia_monitor:get_env(embedded_mnemosyne) of
+ true ->
+ Q = mnemosyne_sup,
+ KA = infinity,
+ [{Q, {Q, start, []}, permanent, KA, supervisor, [Q, supervisor]}];
+ false ->
+ []
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% event handler
+
+start_event() ->
+ case gen_event:start_link({local, mnesia_event}) of
+ {ok, Pid} ->
+ case add_event_handler() of
+ ok ->
+ {ok, Pid};
+ Error ->
+ Error
+ end;
+ Error ->
+ Error
+ end.
+
+add_event_handler() ->
+ Handler = mnesia_monitor:get_env(event_module),
+ gen_event:add_handler(mnesia_event, Handler, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% debug functions
+
+kill() ->
+ Mnesia = [mnesia_fallback | mnesia:ms()],
+ Mnemosyne = mnemosyne_ms(),
+ Kill = fun(Name) -> catch exit(whereis(Name), kill) end,
+ lists:foreach(Kill, Mnemosyne),
+ lists:foreach(Kill, Mnesia),
+ lists:foreach(fun ensure_dead/1, Mnemosyne),
+ lists:foreach(fun ensure_dead/1, Mnesia),
+ timer:sleep(10),
+ case lists:keymember(mnesia, 1, application:which_applications()) of
+ true -> kill();
+ false -> ok
+ end.
+
+ensure_dead(Name) ->
+ case whereis(Name) of
+ undefined ->
+ ok;
+ Pid when pid(Pid) ->
+ exit(Pid, kill),
+ timer:sleep(10),
+ ensure_dead(Name)
+ end.
+
+mnemosyne_ms() ->
+ case mnesia_monitor:get_env(embedded_mnemosyne) of
+ true -> mnemosyne:ms();
+ false -> []
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_text.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_text.erl
new file mode 100644
index 0000000000..d74f3bf07b
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_text.erl
@@ -0,0 +1,189 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_text.erl,v 1.2 2010/03/04 13:54:20 maria Exp $
+%%
+-module(mnesia_text).
+
+-export([parse/1, file/1, load_textfile/1, dump_to_textfile/1]).
+
+load_textfile(File) ->
+ ensure_started(),
+ case parse(File) of
+ {ok, {Tabs, Data}} ->
+ Badtabs = make_tabs(lists:map(fun validate_tab/1, Tabs)),
+ load_data(del_data(Badtabs, Data, []));
+ Other ->
+ Other
+ end.
+
+dump_to_textfile(File) ->
+ dump_to_textfile(mnesia_lib:is_running(), file:open(File, [write])).
+dump_to_textfile(yes, {ok, F}) ->
+ Tabs = lists:delete(schema, mnesia_lib:local_active_tables()),
+ Defs = lists:map(fun(T) -> {T, [{record_name, mnesia_lib:val({T, record_name})},
+ {attributes, mnesia_lib:val({T, attributes})}]}
+ end,
+ Tabs),
+ io:format(F, "~p.~n", [{tables, Defs}]),
+ lists:foreach(fun(T) -> dump_tab(F, T) end, Tabs),
+ file:close(F);
+dump_to_textfile(_,_) -> error.
+
+
+dump_tab(F, T) ->
+ W = mnesia_lib:val({T, wild_pattern}),
+ {'atomic',All} = mnesia:transaction(fun() -> mnesia:match_object(T, W, read) end),
+ lists:foreach(fun(Term) -> io:format(F,"~p.~n", [setelement(1, Term, T)]) end, All).
+
+
+ensure_started() ->
+ case mnesia_lib:is_running() of
+ yes ->
+ yes;
+ no ->
+ case mnesia_lib:exists(mnesia_lib:dir("schema.DAT")) of
+ true ->
+ mnesia:start();
+ false ->
+ mnesia:create_schema([node()]),
+ mnesia:start()
+ end
+ end.
+
+del_data(Bad, [H|T], Ack) ->
+ case lists:member(element(1, H), Bad) of
+ true -> del_data(Bad, T, Ack);
+ false -> del_data(Bad, T, [H|Ack])
+ end;
+del_data(_Bad, [], Ack) ->
+ lists:reverse(Ack).
+
+%% Tis the place to call the validate func in mnesia_schema
+validate_tab({Tabname, List}) ->
+ {Tabname, List};
+validate_tab({Tabname, RecName, List}) ->
+ {Tabname, RecName, List};
+validate_tab(_) -> error(badtab).
+
+make_tabs([{Tab, Def} | Tail]) ->
+ case catch mnesia:table_info(Tab, where_to_read) of
+ {'EXIT', _} -> %% non-existing table
+ case mnesia:create_table(Tab, Def) of
+ {aborted, Reason} ->
+ io:format("** Failed to create table ~w ~n"
+ "** Reason = ~w, Args = ~p~n",
+ [Tab, Reason, Def]),
+ [Tab | make_tabs(Tail)];
+ _ ->
+ io:format("New table ~w~n", [Tab]),
+ make_tabs(Tail)
+ end;
+ Node ->
+ io:format("** Table ~w already exists on ~p, just entering data~n",
+ [Tab, Node]),
+ make_tabs(Tail)
+ end;
+
+make_tabs([]) ->
+ [].
+
+load_data(L) ->
+ mnesia:transaction(fun() ->
+ F = fun(X) ->
+ Tab = element(1, X),
+ RN = mnesia:table_info(Tab, record_name),
+ Rec = setelement(1, X, RN),
+ mnesia:write(Tab, Rec, write) end,
+ lists:foreach(F, L)
+ end).
+
+parse(File) ->
+ case file(File) of
+ {ok, Terms} ->
+ case catch collect(Terms) of
+ {error, X} ->
+ {error, X};
+ Other ->
+ {ok, Other}
+ end;
+ Other ->
+ Other
+ end.
+
+collect([{_, {tables, Tabs}}|L]) ->
+ {Tabs, collect_data(Tabs, L)};
+
+collect(_) ->
+ io:format("No tables found\n", []),
+ error(bad_header).
+
+collect_data(Tabs, [{Line, Term} | Tail]) when tuple(Term) ->
+ case lists:keysearch(element(1, Term), 1, Tabs) of
+ {value, _} ->
+ [Term | collect_data(Tabs, Tail)];
+ _Other ->
+ io:format("Object:~p at line ~w unknown\n", [Term,Line]),
+ error(undefined_object)
+ end;
+collect_data(_Tabs, []) -> [];
+collect_data(_Tabs, [H|_T]) ->
+ io:format("Object:~p unknown\n", [H]),
+ error(undefined_object).
+
+error(What) -> throw({error, What}).
+
+file(File) ->
+ case file:open(File, [read]) of
+ {ok, Stream} ->
+ Res = read_terms(Stream, File, 1, []),
+ file:close(Stream),
+ Res;
+ _Other ->
+ {error, open}
+ end.
+
+read_terms(Stream, File, Line, L) ->
+ case read_term_from_stream(Stream, File, Line) of
+ {ok, Term, NextLine} ->
+ read_terms(Stream, File, NextLine, [Term|L]);
+ error ->
+ {error, read};
+ eof ->
+ {ok, lists:reverse(L)}
+ end.
+
+read_term_from_stream(Stream, File, Line) ->
+ R = io:request(Stream, {get_until,'',erl_scan,tokens,[Line]}),
+ case R of
+ {ok,Toks,EndLine} ->
+ case erl_parse:parse_term(Toks) of
+ {ok, Term} ->
+ {ok, {Line, Term}, EndLine};
+ {error, {NewLine,Mod,What}} ->
+ Str = Mod:format_error(What),
+ io:format("Error in line:~p of:~p ~s\n",
+ [NewLine, File, Str]),
+ error;
+ T ->
+ io:format("Error2 **~p~n",[T]),
+ error
+ end;
+ {eof,_EndLine} ->
+ eof;
+ Other ->
+ io:format("Error1 **~p~n",[Other]),
+ error
+ end.
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_tm.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_tm.erl
new file mode 100644
index 0000000000..ac11087fa0
--- /dev/null
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_tm.erl
@@ -0,0 +1,2173 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: mnesia_tm.erl,v 1.2 2010/03/04 13:54:20 maria Exp $
+%%
+-module(mnesia_tm).
+
+-export([
+ start/0,
+ init/1,
+ non_transaction/5,
+ transaction/6,
+ commit_participant/5,
+ dirty/2,
+ display_info/2,
+ do_update_op/3,
+ get_info/1,
+ get_transactions/0,
+ info/1,
+ mnesia_down/1,
+ prepare_checkpoint/2,
+ prepare_checkpoint/1, % Internal
+ prepare_snmp/3,
+ do_snmp/2,
+ put_activity_id/1,
+ block_tab/1,
+ unblock_tab/1
+ ]).
+
+%% sys callback functions
+-export([system_continue/3,
+ system_terminate/4,
+ system_code_change/4
+ ]).
+
+-include("mnesia.hrl").
+-import(mnesia_lib, [set/2]).
+-import(mnesia_lib, [fatal/2, verbose/2, dbg_out/2]).
+
+-record(state, {coordinators = [], participants = [], supervisor,
+ blocked_tabs = [], dirty_queue = []}).
+%% Format on coordinators is [{Tid, EtsTabList} .....
+
+-record(prep, {protocol = sym_trans,
+ %% async_dirty | sync_dirty | sym_trans | sync_sym_trans | asym_trans
+ records = [],
+ prev_tab = [], % initiate to a non valid table name
+ prev_types,
+ prev_snmp,
+ types
+ }).
+
+-record(participant, {tid, pid, commit, disc_nodes = [],
+ ram_nodes = [], protocol = sym_trans}).
+
+start() ->
+ mnesia_monitor:start_proc(?MODULE, ?MODULE, init, [self()]).
+
+init(Parent) ->
+ register(?MODULE, self()),
+ process_flag(trap_exit, true),
+
+ %% Initialize the schema
+ IgnoreFallback = mnesia_monitor:get_env(ignore_fallback_at_startup),
+ mnesia_bup:tm_fallback_start(IgnoreFallback),
+ mnesia_schema:init(IgnoreFallback),
+
+ %% Handshake and initialize transaction recovery
+ mnesia_recover:init(),
+ Early = mnesia_monitor:init(),
+ AllOthers = mnesia_lib:uniq(Early ++ mnesia_lib:all_nodes()) -- [node()],
+ set(original_nodes, AllOthers),
+ mnesia_recover:connect_nodes(AllOthers),
+
+ %% Recover transactions, may wait for decision
+ case mnesia_monitor:use_dir() of
+ true ->
+ P = mnesia_dumper:opt_dump_log(startup), % previous log
+ L = mnesia_dumper:opt_dump_log(startup), % latest log
+ Msg = "Initial dump of log during startup: ~p~n",
+ mnesia_lib:verbose(Msg, [[P, L]]),
+ mnesia_log:init();
+ false ->
+ ignore
+ end,
+
+ mnesia_schema:purge_tmp_files(),
+ mnesia_recover:start_garb(),
+
+ ?eval_debug_fun({?MODULE, init}, [{nodes, AllOthers}]),
+
+ case val(debug) of
+ Debug when Debug /= debug, Debug /= trace ->
+ ignore;
+ _ ->
+ mnesia_subscr:subscribe(whereis(mnesia_event), {table, schema})
+ end,
+ proc_lib:init_ack(Parent, {ok, self()}),
+ doit_loop(#state{supervisor = Parent}).
+
+val(Var) ->
+ case ?catch_val(Var) of
+ {'EXIT', _ReASoN_} -> mnesia_lib:other_val(Var, _ReASoN_);
+ _VaLuE_ -> _VaLuE_
+ end.
+
+reply({From,Ref}, R) ->
+ From ! {?MODULE, Ref, R};
+reply(From, R) ->
+ From ! {?MODULE, node(), R}.
+
+reply(From, R, State) ->
+ reply(From, R),
+ doit_loop(State).
+
+req(R) ->
+ case whereis(?MODULE) of
+ undefined ->
+ {error, {node_not_running, node()}};
+ Pid ->
+ Ref = make_ref(),
+ Pid ! {{self(), Ref}, R},
+ rec(Pid, Ref)
+ end.
+
+rec() ->
+ rec(whereis(?MODULE)).
+
+rec(Pid) when pid(Pid) ->
+ receive
+ {?MODULE, _, Reply} ->
+ Reply;
+
+ {'EXIT', Pid, _} ->
+ {error, {node_not_running, node()}}
+ end;
+rec(undefined) ->
+ {error, {node_not_running, node()}}.
+
+rec(Pid, Ref) ->
+ receive
+ {?MODULE, Ref, Reply} ->
+ Reply;
+ {'EXIT', Pid, _} ->
+ {error, {node_not_running, node()}}
+ end.
+
+tmlink({From, Ref}) when reference(Ref) ->
+ link(From);
+tmlink(From) ->
+ link(From).
+tmpid({Pid, _Ref}) when pid(Pid) ->
+ Pid;
+tmpid(Pid) ->
+ Pid.
+
+%% Returns a list of participant transaction Tid's
+mnesia_down(Node) ->
+ %% Syncronously call needed in order to avoid
+ %% race with mnesia_tm's coordinator processes
+ %% that may restart and acquire new locks.
+ %% mnesia_monitor takes care of the sync
+ case whereis(?MODULE) of
+ undefined ->
+ mnesia_monitor:mnesia_down(?MODULE, {Node, []});
+ Pid ->
+ Pid ! {mnesia_down, Node}
+ end.
+
+prepare_checkpoint(Nodes, Cp) ->
+ rpc:multicall(Nodes, ?MODULE, prepare_checkpoint, [Cp]).
+
+prepare_checkpoint(Cp) ->
+ req({prepare_checkpoint,Cp}).
+
+block_tab(Tab) ->
+ req({block_tab, Tab}).
+
+unblock_tab(Tab) ->
+ req({unblock_tab, Tab}).
+
+doit_loop(#state{coordinators = Coordinators, participants = Participants, supervisor = Sup}
+ = State) ->
+ receive
+ {_From, {async_dirty, Tid, Commit, Tab}} ->
+ case lists:member(Tab, State#state.blocked_tabs) of
+ false ->
+ do_async_dirty(Tid, Commit, Tab),
+ doit_loop(State);
+ true ->
+ Item = {async_dirty, Tid, Commit, Tab},
+ State2 = State#state{dirty_queue = [Item | State#state.dirty_queue]},
+ doit_loop(State2)
+ end;
+
+ {From, {sync_dirty, Tid, Commit, Tab}} ->
+ case lists:member(Tab, State#state.blocked_tabs) of
+ false ->
+ do_sync_dirty(From, Tid, Commit, Tab),
+ doit_loop(State);
+ true ->
+ Item = {sync_dirty, From, Tid, Commit, Tab},
+ State2 = State#state{dirty_queue = [Item | State#state.dirty_queue]},
+ doit_loop(State2)
+ end;
+
+ {From, start_outer} -> %% Create and associate ets_tab with Tid
+ case catch ?ets_new_table(mnesia_trans_store, [bag, public]) of
+ {'EXIT', Reason} -> %% system limit
+ Msg = "Cannot create an ets table for the "
+ "local transaction store",
+ reply(From, {error, {system_limit, Msg, Reason}}, State);
+ Etab ->
+ tmlink(From),
+ C = mnesia_recover:incr_trans_tid_serial(),
+ ?ets_insert(Etab, {nodes, node()}),
+ Tid = #tid{pid = tmpid(From), counter = C},
+ A2 = [{Tid , [Etab]} | Coordinators],
+ S2 = State#state{coordinators = A2},
+ reply(From, {new_tid, Tid, Etab}, S2)
+ end;
+
+ {From, {ask_commit, Protocol, Tid, Commit, DiscNs, RamNs}} ->
+ ?eval_debug_fun({?MODULE, doit_ask_commit},
+ [{tid, Tid}, {prot, Protocol}]),
+ mnesia_checkpoint:tm_enter_pending(Tid, DiscNs, RamNs),
+ Pid =
+ case Protocol of
+ asym_trans when node(Tid#tid.pid) /= node() ->
+ Args = [tmpid(From), Tid, Commit, DiscNs, RamNs],
+ spawn_link(?MODULE, commit_participant, Args);
+ _ when node(Tid#tid.pid) /= node() -> %% *_sym_trans
+ reply(From, {vote_yes, Tid}),
+ nopid
+ end,
+ P = #participant{tid = Tid,
+ pid = Pid,
+ commit = Commit,
+ disc_nodes = DiscNs,
+ ram_nodes = RamNs,
+ protocol = Protocol},
+ State2 = State#state{participants = [P | Participants]},
+ doit_loop(State2);
+
+ {Tid, do_commit} ->
+ case mnesia_lib:key_search_delete(Tid, #participant.tid, Participants) of
+ {none, _} ->
+ verbose("Tried to commit a non participant transaction ~p~n",
+ [Tid]),
+ doit_loop(State);
+ {P, Participants2} ->
+ ?eval_debug_fun({?MODULE, do_commit, pre},
+ [{tid, Tid}, {participant, P}]),
+ case P#participant.pid of
+ nopid ->
+ Commit = P#participant.commit,
+ Member = lists:member(node(), P#participant.disc_nodes),
+ if Member == false ->
+ ignore;
+ P#participant.protocol == sym_trans ->
+ mnesia_log:log(Commit);
+ P#participant.protocol == sync_sym_trans ->
+ mnesia_log:slog(Commit)
+ end,
+ mnesia_recover:note_decision(Tid, committed),
+ do_commit(Tid, Commit),
+ if
+ P#participant.protocol == sync_sym_trans ->
+ Tid#tid.pid ! {?MODULE, node(), {committed, Tid}};
+ true ->
+ ignore
+ end,
+ mnesia_locker:release_tid(Tid),
+ transaction_terminated(Tid),
+ ?eval_debug_fun({?MODULE, do_commit, post}, [{tid, Tid}, {pid, nopid}]),
+ doit_loop(State#state{participants = Participants2});
+ Pid when pid(Pid) ->
+ Pid ! {Tid, committed},
+ ?eval_debug_fun({?MODULE, do_commit, post}, [{tid, Tid}, {pid, Pid}]),
+ doit_loop(State)
+ end
+ end;
+
+ {Tid, simple_commit} ->
+ mnesia_recover:note_decision(Tid, committed),
+ mnesia_locker:release_tid(Tid),
+ transaction_terminated(Tid),
+ doit_loop(State);
+
+ {Tid, {do_abort, Reason}} ->
+ ?eval_debug_fun({?MODULE, do_abort, pre}, [{tid, Tid}]),
+ mnesia_locker:release_tid(Tid),
+ case mnesia_lib:key_search_delete(Tid, #participant.tid, Participants) of
+ {none, _} ->
+ verbose("Tried to abort a non participant transaction ~p: ~p~n",
+ [Tid, Reason]),
+ doit_loop(State);
+ {P, Participants2} ->
+ case P#participant.pid of
+ nopid ->
+ Commit = P#participant.commit,
+ mnesia_recover:note_decision(Tid, aborted),
+ do_abort(Tid, Commit),
+ if
+ P#participant.protocol == sync_sym_trans ->
+ Tid#tid.pid ! {?MODULE, node(), {aborted, Tid}};
+ true ->
+ ignore
+ end,
+ transaction_terminated(Tid),
+ ?eval_debug_fun({?MODULE, do_abort, post}, [{tid, Tid}, {pid, nopid}]),
+ doit_loop(State#state{participants = Participants2});
+ Pid when pid(Pid) ->
+ Pid ! {Tid, {do_abort, Reason}},
+ ?eval_debug_fun({?MODULE, do_abort, post},
+ [{tid, Tid}, {pid, Pid}]),
+ doit_loop(State)
+ end
+ end;
+
+ {From, {add_store, Tid}} -> %% new store for nested transaction
+ case catch ?ets_new_table(mnesia_trans_store, [bag, public]) of
+ {'EXIT', Reason} -> %% system limit
+ Msg = "Cannot create an ets table for a nested "
+ "local transaction store",
+ reply(From, {error, {system_limit, Msg, Reason}}, State);
+ Etab ->
+ A2 = add_coord_store(Coordinators, Tid, Etab),
+ reply(From, {new_store, Etab},
+ State#state{coordinators = A2})
+ end;
+
+ {From, {del_store, Tid, Current, Obsolete, PropagateStore}} ->
+ opt_propagate_store(Current, Obsolete, PropagateStore),
+ A2 = del_coord_store(Coordinators, Tid, Current, Obsolete),
+ reply(From, store_erased, State#state{coordinators = A2});
+
+ {'EXIT', Pid, Reason} ->
+ handle_exit(Pid, Reason, State);
+
+ {From, {restart, Tid, Store}} ->
+ A2 = restore_stores(Coordinators, Tid, Store),
+ ?ets_match_delete(Store, '_'),
+ ?ets_insert(Store, {nodes, node()}),
+ reply(From, {restarted, Tid}, State#state{coordinators = A2});
+
+ {delete_transaction, Tid} ->
+ %% used to clear transactions which are committed
+ %% in coordinator or participant processes
+ case mnesia_lib:key_search_delete(Tid, #participant.tid, Participants) of
+ {none, _} ->
+ case mnesia_lib:key_search_delete(Tid, 1, Coordinators) of
+ {none, _} ->
+ verbose("** ERROR ** Tried to delete a non transaction ~p~n",
+ [Tid]),
+ doit_loop(State);
+ {{_Tid, Etabs}, A2} ->
+ erase_ets_tabs(Etabs),
+ transaction_terminated(Tid),
+ doit_loop(State#state{coordinators = A2})
+ end;
+ {_P, Participants2} ->
+ transaction_terminated(Tid),
+ State2 = State#state{participants = Participants2},
+ doit_loop(State2)
+ end;
+
+ {sync_trans_serial, Tid} ->
+ %% Do the Lamport thing here
+ mnesia_recover:sync_trans_tid_serial(Tid),
+ doit_loop(State);
+
+ {From, info} ->
+ reply(From, {info, Participants, Coordinators}, State);
+
+ {mnesia_down, N} ->
+ verbose("Got mnesia_down from ~p, reconfiguring...~n", [N]),
+ reconfigure_coordinators(N, Coordinators),
+
+ Tids = [P#participant.tid || P <- Participants],
+ reconfigure_participants(N, Participants),
+ mnesia_monitor:mnesia_down(?MODULE, {N, Tids}),
+ doit_loop(State);
+
+ {From, {unblock_me, Tab}} ->
+ case lists:member(Tab, State#state.blocked_tabs) of
+ false ->
+ verbose("Wrong dirty Op blocked on ~p ~p ~p",
+ [node(), Tab, From]),
+ reply(From, unblocked),
+ doit_loop(State);
+ true ->
+ Item = {Tab, unblock_me, From},
+ State2 = State#state{dirty_queue = [Item | State#state.dirty_queue]},
+ doit_loop(State2)
+ end;
+
+ {From, {block_tab, Tab}} ->
+ State2 = State#state{blocked_tabs = [Tab | State#state.blocked_tabs]},
+ reply(From, ok, State2);
+
+ {From, {unblock_tab, Tab}} ->
+ BlockedTabs2 = State#state.blocked_tabs -- [Tab],
+ case lists:member(Tab, BlockedTabs2) of
+ false ->
+ mnesia_controller:unblock_table(Tab),
+ Queue = process_dirty_queue(Tab, State#state.dirty_queue),
+ State2 = State#state{blocked_tabs = BlockedTabs2,
+ dirty_queue = Queue},
+ reply(From, ok, State2);
+ true ->
+ State2 = State#state{blocked_tabs = BlockedTabs2},
+ reply(From, ok, State2)
+ end;
+
+ {From, {prepare_checkpoint, Cp}} ->
+ Res = mnesia_checkpoint:tm_prepare(Cp),
+ case Res of
+ {ok, _Name, IgnoreNew, _Node} ->
+ prepare_pending_coordinators(Coordinators, IgnoreNew),
+ prepare_pending_participants(Participants, IgnoreNew);
+ {error, _Reason} ->
+ ignore
+ end,
+ reply(From, Res, State);
+
+ {system, From, Msg} ->
+ dbg_out("~p got {system, ~p, ~p}~n", [?MODULE, From, Msg]),
+ sys:handle_system_msg(Msg, From, Sup, ?MODULE, [], State);
+
+ Msg ->
+ verbose("** ERROR ** ~p got unexpected message: ~p~n", [?MODULE, Msg]),
+ doit_loop(State)
+ end.
+
+do_sync_dirty(From, Tid, Commit, _Tab) ->
+ ?eval_debug_fun({?MODULE, sync_dirty, pre}, [{tid, Tid}]),
+ Res = (catch do_dirty(Tid, Commit)),
+ ?eval_debug_fun({?MODULE, sync_dirty, post}, [{tid, Tid}]),
+ From ! {?MODULE, node(), {dirty_res, Res}}.
+
+do_async_dirty(Tid, Commit, _Tab) ->
+ ?eval_debug_fun({?MODULE, async_dirty, pre}, [{tid, Tid}]),
+ catch do_dirty(Tid, Commit),
+ ?eval_debug_fun({?MODULE, async_dirty, post}, [{tid, Tid}]).
+
+%% Process items in fifo order
+process_dirty_queue(Tab, [Item | Queue]) ->
+ Queue2 = process_dirty_queue(Tab, Queue),
+ case Item of
+ {async_dirty, Tid, Commit, Tab} ->
+ do_async_dirty(Tid, Commit, Tab),
+ Queue2;
+ {sync_dirty, From, Tid, Commit, Tab} ->
+ do_sync_dirty(From, Tid, Commit, Tab),
+ Queue2;
+ {Tab, unblock_me, From} ->
+ reply(From, unblocked),
+ Queue2;
+ _ ->
+ [Item | Queue2]
+ end;
+process_dirty_queue(_Tab, []) ->
+ [].
+
+prepare_pending_coordinators([{Tid, [Store | _Etabs]} | Coords], IgnoreNew) ->
+ case catch ?ets_lookup(Store, pending) of
+ [] ->
+ prepare_pending_coordinators(Coords, IgnoreNew);
+ [Pending] ->
+ case lists:member(Tid, IgnoreNew) of
+ false ->
+ mnesia_checkpoint:tm_enter_pending(Pending);
+ true ->
+ ignore
+ end,
+ prepare_pending_coordinators(Coords, IgnoreNew);
+ {'EXIT', _} ->
+ prepare_pending_coordinators(Coords, IgnoreNew)
+ end;
+prepare_pending_coordinators([], _IgnoreNew) ->
+ ok.
+
+prepare_pending_participants([Part | Parts], IgnoreNew) ->
+ Tid = Part#participant.tid,
+ D = Part#participant.disc_nodes,
+ R = Part#participant.ram_nodes,
+ case lists:member(Tid, IgnoreNew) of
+ false ->
+ mnesia_checkpoint:tm_enter_pending(Tid, D, R);
+ true ->
+ ignore
+ end,
+ prepare_pending_participants(Parts, IgnoreNew);
+prepare_pending_participants([], _IgnoreNew) ->
+ ok.
+
+handle_exit(Pid, Reason, State) when node(Pid) /= node() ->
+ %% We got exit from a remote fool
+ dbg_out("~p got remote EXIT from unknown ~p~n",
+ [?MODULE, {Pid, Reason}]),
+ doit_loop(State);
+
+handle_exit(Pid, _Reason, State) when Pid == State#state.supervisor ->
+ %% Our supervisor has died, time to stop
+ do_stop(State);
+
+handle_exit(Pid, Reason, State) ->
+ %% Check if it is a coordinator
+ case pid_search_delete(Pid, State#state.coordinators) of
+ {none, _} ->
+ %% Check if it is a participant
+ case mnesia_lib:key_search_delete(Pid, #participant.pid, State#state.participants) of
+ {none, _} ->
+ %% We got exit from a local fool
+ verbose("** ERROR ** ~p got local EXIT from unknown process: ~p~n",
+ [?MODULE, {Pid, Reason}]),
+ doit_loop(State);
+
+ {P, RestP} when record(P, participant) ->
+ fatal("Participant ~p in transaction ~p died ~p~n",
+ [P#participant.pid, P#participant.tid, Reason]),
+ doit_loop(State#state{participants = RestP})
+ end;
+
+ {{Tid, Etabs}, RestC} ->
+ %% A local coordinator has died and
+ %% we must determine the outcome of the
+ %% transaction and tell mnesia_tm on the
+ %% other nodes about it and then recover
+ %% locally.
+ recover_coordinator(Tid, Etabs),
+ doit_loop(State#state{coordinators = RestC})
+ end.
+
+recover_coordinator(Tid, Etabs) ->
+ verbose("Coordinator ~p in transaction ~p died.~n", [Tid#tid.pid, Tid]),
+
+ Store = hd(Etabs),
+ CheckNodes = get_nodes(Store),
+ TellNodes = CheckNodes -- [node()],
+ case catch arrange(Tid, Store, async) of
+ {'EXIT', Reason} ->
+ dbg_out("Recovery of coordinator ~p failed:~n", [Tid, Reason]),
+ Protocol = asym_trans,
+ tell_outcome(Tid, Protocol, node(), CheckNodes, TellNodes);
+ {_N, Prep} ->
+ %% Tell the participants about the outcome
+ Protocol = Prep#prep.protocol,
+ Outcome = tell_outcome(Tid, Protocol, node(), CheckNodes, TellNodes),
+
+ %% Recover locally
+ CR = Prep#prep.records,
+ {DiscNs, RamNs} = commit_nodes(CR, [], []),
+ {value, Local} = lists:keysearch(node(), #commit.node, CR),
+
+ ?eval_debug_fun({?MODULE, recover_coordinator, pre},
+ [{tid, Tid}, {outcome, Outcome}, {prot, Protocol}]),
+ recover_coordinator(Tid, Protocol, Outcome, Local, DiscNs, RamNs),
+ ?eval_debug_fun({?MODULE, recover_coordinator, post},
+ [{tid, Tid}, {outcome, Outcome}, {prot, Protocol}])
+
+ end,
+ erase_ets_tabs(Etabs),
+ transaction_terminated(Tid),
+ mnesia_locker:release_tid(Tid).
+
+recover_coordinator(Tid, sym_trans, committed, Local, _, _) ->
+ mnesia_recover:note_decision(Tid, committed),
+ do_dirty(Tid, Local);
+recover_coordinator(Tid, sym_trans, aborted, _Local, _, _) ->
+ mnesia_recover:note_decision(Tid, aborted);
+recover_coordinator(Tid, sync_sym_trans, committed, Local, _, _) ->
+ mnesia_recover:note_decision(Tid, committed),
+ do_dirty(Tid, Local);
+recover_coordinator(Tid, sync_sym_trans, aborted, _Local, _, _) ->
+ mnesia_recover:note_decision(Tid, aborted);
+
+recover_coordinator(Tid, asym_trans, committed, Local, DiscNs, RamNs) ->
+ D = #decision{tid = Tid, outcome = committed,
+ disc_nodes = DiscNs, ram_nodes = RamNs},
+ mnesia_recover:log_decision(D),
+ do_commit(Tid, Local);
+recover_coordinator(Tid, asym_trans, aborted, Local, DiscNs, RamNs) ->
+ D = #decision{tid = Tid, outcome = aborted,
+ disc_nodes = DiscNs, ram_nodes = RamNs},
+ mnesia_recover:log_decision(D),
+ do_abort(Tid, Local).
+
+restore_stores([{Tid, Etstabs} | Tail], Tid, Store) ->
+ Remaining = lists:delete(Store, Etstabs),
+ erase_ets_tabs(Remaining),
+ [{Tid, [Store]} | Tail];
+restore_stores([H | T], Tid, Store) ->
+ [H | restore_stores(T, Tid, Store)].
+%% No NIL case on purpose
+
+add_coord_store([{Tid, Stores} | Coordinators], Tid, Etab) ->
+ [{Tid, [Etab | Stores]} | Coordinators];
+add_coord_store([H | T], Tid, Etab) ->
+ [H | add_coord_store(T, Tid, Etab)].
+%% no NIL case on purpose
+
+del_coord_store([{Tid, Stores} | Coordinators], Tid, Current, Obsolete) ->
+ Rest =
+ case Stores of
+ [Obsolete, Current | Tail] -> Tail;
+ [Current, Obsolete | Tail] -> Tail
+ end,
+ ?ets_delete_table(Obsolete),
+ [{Tid, [Current | Rest]} | Coordinators];
+del_coord_store([H | T], Tid, Current, Obsolete) ->
+ [H | del_coord_store(T, Tid, Current, Obsolete)].
+%% no NIL case on purpose
+
+erase_ets_tabs([H | T]) ->
+ ?ets_delete_table(H),
+ erase_ets_tabs(T);
+erase_ets_tabs([]) ->
+ ok.
+
+%% Deletes a pid from a list of participants
+%% or from a list of coordinators and returns
+%% {none, All} or {Tr, Rest}
+pid_search_delete(Pid, Trs) ->
+ pid_search_delete(Pid, Trs, none, []).
+pid_search_delete(Pid, [Tr = {Tid, _Ts} | Trs], _Val, Ack) when Tid#tid.pid == Pid ->
+ pid_search_delete(Pid, Trs, Tr, Ack);
+pid_search_delete(Pid, [Tr | Trs], Val, Ack) ->
+ pid_search_delete(Pid, Trs, Val, [Tr | Ack]);
+
+pid_search_delete(_Pid, [], Val, Ack) ->
+ {Val, Ack}.
+
+%% When TM gets an EXIT sig, we must also check to see
+%% if the crashing transaction is in the Participant list
+%%
+%% search_participant_for_pid([Participant | Tail], Pid) ->
+%% Tid = Participant#participant.tid,
+%% if
+%% Tid#tid.pid == Pid ->
+%% {coordinator, Participant};
+%% Participant#participant.pid == Pid ->
+%% {participant, Participant};
+%% true ->
+%% search_participant_for_pid(Tail, Pid)
+%% end;
+%% search_participant_for_pid([], _) ->
+%% fool.
+
+transaction_terminated(Tid) ->
+ mnesia_checkpoint:tm_exit_pending(Tid),
+ Pid = Tid#tid.pid,
+ if
+ node(Pid) == node() ->
+ unlink(Pid);
+ true -> %% Do the Lamport thing here
+ mnesia_recover:sync_trans_tid_serial(Tid)
+ end.
+
+non_transaction(OldState, Fun, Args, ActivityKind, Mod) ->
+ Id = {ActivityKind, self()},
+ NewState = {Mod, Id, non_transaction},
+ put(mnesia_activity_state, NewState),
+ %% I Want something uniqe here, references are expensive
+ Ref = mNeSia_nOn_TrAnSacTioN,
+ RefRes = (catch {Ref, apply(Fun, Args)}),
+ case OldState of
+ undefined -> erase(mnesia_activity_state);
+ _ -> put(mnesia_activity_state, OldState)
+ end,
+ case RefRes of
+ {Ref, Res} ->
+ case Res of
+ {'EXIT', Reason} -> exit(Reason);
+ {aborted, Reason} -> mnesia:abort(Reason);
+ _ -> Res
+ end;
+ {'EXIT', Reason} ->
+ exit(Reason);
+ Throw ->
+ throw(Throw)
+ end.
+
+transaction(OldTidTs, Fun, Args, Retries, Mod, Type) ->
+ Factor = 1,
+ case OldTidTs of
+ undefined -> % Outer
+ execute_outer(Mod, Fun, Args, Factor, Retries, Type);
+ {_OldMod, Tid, Ts} -> % Nested
+ execute_inner(Mod, Tid, Ts, Fun, Args, Factor, Retries, Type);
+ _ -> % Bad nesting
+ {aborted, nested_transaction}
+ end.
+
+execute_outer(Mod, Fun, Args, Factor, Retries, Type) ->
+ case req(start_outer) of
+ {error, Reason} ->
+ {aborted, Reason};
+ {new_tid, Tid, Store} ->
+ Ts = #tidstore{store = Store},
+ NewTidTs = {Mod, Tid, Ts},
+ put(mnesia_activity_state, NewTidTs),
+ execute_transaction(Fun, Args, Factor, Retries, Type)
+ end.
+
+execute_inner(Mod, Tid, Ts, Fun, Args, Factor, Retries, Type) ->
+ case req({add_store, Tid}) of
+ {error, Reason} ->
+ {aborted, Reason};
+ {new_store, Ets} ->
+ copy_ets(Ts#tidstore.store, Ets),
+ Up = [Ts#tidstore.store | Ts#tidstore.up_stores],
+ NewTs = Ts#tidstore{level = 1 + Ts#tidstore.level,
+ store = Ets,
+ up_stores = Up},
+ NewTidTs = {Mod, Tid, NewTs},
+ put(mnesia_activity_state, NewTidTs),
+ execute_transaction(Fun, Args, Factor, Retries, Type)
+ end.
+
+copy_ets(From, To) ->
+ do_copy_ets(?ets_first(From), From, To).
+do_copy_ets('$end_of_table', _,_) ->
+ ok;
+do_copy_ets(K, From, To) ->
+ Objs = ?ets_lookup(From, K),
+ insert_objs(Objs, To),
+ do_copy_ets(?ets_next(From, K), From, To).
+
+insert_objs([H|T], Tab) ->
+ ?ets_insert(Tab, H),
+ insert_objs(T, Tab);
+insert_objs([], _Tab) ->
+ ok.
+
+execute_transaction(Fun, Args, Factor, Retries, Type) ->
+ case catch apply_fun(Fun, Args, Type) of
+ {'EXIT', Reason} ->
+ check_exit(Fun, Args, Factor, Retries, Reason, Type);
+ {'atomic', Value} ->
+ mnesia_lib:incr_counter(trans_commits),
+ erase(mnesia_activity_state),
+ %% no need to clear locks, already done by commit ...
+ %% Flush any un processed mnesia_down messages we might have
+ flush_downs(),
+ {'atomic', Value};
+ {nested_atomic, Value} ->
+ mnesia_lib:incr_counter(trans_commits),
+ {'atomic', Value};
+ Value -> %% User called throw
+ Reason = {aborted, {throw, Value}},
+ return_abort(Fun, Args, Reason)
+ end.
+
+apply_fun(Fun, Args, Type) ->
+ Result = apply(Fun, Args),
+ case t_commit(Type) of
+ do_commit ->
+ {'atomic', Result};
+ do_commit_nested ->
+ {nested_atomic, Result};
+ {do_abort, {aborted, Reason}} ->
+ {'EXIT', {aborted, Reason}};
+ {do_abort, Reason} ->
+ {'EXIT', {aborted, Reason}}
+ end.
+
+check_exit(Fun, Args, Factor, Retries, Reason, Type) ->
+ case Reason of
+ {aborted, C} when record(C, cyclic) ->
+ maybe_restart(Fun, Args, Factor, Retries, Type, C);
+ {aborted, {node_not_running, N}} ->
+ maybe_restart(Fun, Args, Factor, Retries, Type, {node_not_running, N});
+ {aborted, {bad_commit, N}} ->
+ maybe_restart(Fun, Args, Factor, Retries, Type, {bad_commit, N});
+ _ ->
+ return_abort(Fun, Args, Reason)
+ end.
+
+maybe_restart(Fun, Args, Factor, Retries, Type, Why) ->
+ {Mod, Tid, Ts} = get(mnesia_activity_state),
+ case try_again(Retries) of
+ yes when Ts#tidstore.level == 1 ->
+ restart(Mod, Tid, Ts, Fun, Args, Factor, Retries, Type, Why);
+ yes ->
+ return_abort(Fun, Args, Why);
+ no ->
+ return_abort(Fun, Args, {aborted, nomore})
+ end.
+
+try_again(infinity) -> yes;
+try_again(X) when number(X) , X > 1 -> yes;
+try_again(_) -> no.
+
+%% We can only restart toplevel transactions.
+%% If a deadlock situation occurs in a nested transaction
+%% The whole thing including all nested transactions need to be
+%% restarted. The stack is thus popped by a consequtive series of
+%% exit({aborted, #cyclic{}}) calls
+
+restart(Mod, Tid, Ts, Fun, Args, Factor0, Retries0, Type, Why) ->
+ mnesia_lib:incr_counter(trans_restarts),
+ Retries = decr(Retries0),
+ case Why of
+ {bad_commit, _N} ->
+ return_abort(Fun, Args, Why),
+ Factor = 1,
+ SleepTime = mnesia_lib:random_time(Factor, Tid#tid.counter),
+ dbg_out("Restarting transaction ~w: in ~wms ~w~n", [Tid, SleepTime, Why]),
+ timer:sleep(SleepTime),
+ execute_outer(Mod, Fun, Args, Factor, Retries, Type);
+ {node_not_running, _N} -> %% Avoids hanging in receive_release_tid_ack
+ return_abort(Fun, Args, Why),
+ Factor = 1,
+ SleepTime = mnesia_lib:random_time(Factor, Tid#tid.counter),
+ dbg_out("Restarting transaction ~w: in ~wms ~w~n", [Tid, SleepTime, Why]),
+ timer:sleep(SleepTime),
+ execute_outer(Mod, Fun, Args, Factor, Retries, Type);
+ _ ->
+ SleepTime = mnesia_lib:random_time(Factor0, Tid#tid.counter),
+ dbg_out("Restarting transaction ~w: in ~wms ~w~n", [Tid, SleepTime, Why]),
+
+ if
+ Factor0 /= 10 ->
+ ignore;
+ true ->
+ %% Our serial may be much larger than other nodes ditto
+ AllNodes = val({current, db_nodes}),
+ verbose("Sync serial ~p~n", [Tid]),
+ rpc:abcast(AllNodes, ?MODULE, {sync_trans_serial, Tid})
+ end,
+ intercept_friends(Tid, Ts),
+ Store = Ts#tidstore.store,
+ Nodes = get_nodes(Store),
+ ?MODULE ! {self(), {restart, Tid, Store}},
+ mnesia_locker:send_release_tid(Nodes, Tid),
+ timer:sleep(SleepTime),
+ mnesia_locker:receive_release_tid_acc(Nodes, Tid),
+ case rec() of
+ {restarted, Tid} ->
+ execute_transaction(Fun, Args, Factor0 + 1,
+ Retries, Type);
+ {error, Reason} ->
+ mnesia:abort(Reason)
+ end
+ end.
+
+decr(infinity) -> infinity;
+decr(X) when integer(X), X > 1 -> X - 1;
+decr(_X) -> 0.
+
+return_abort(Fun, Args, Reason) ->
+ {Mod, Tid, Ts} = get(mnesia_activity_state),
+ OldStore = Ts#tidstore.store,
+ Nodes = get_nodes(OldStore),
+ intercept_friends(Tid, Ts),
+ catch mnesia_lib:incr_counter(trans_failures),
+ Level = Ts#tidstore.level,
+ if
+ Level == 1 ->
+ mnesia_locker:async_release_tid(Nodes, Tid),
+ ?MODULE ! {delete_transaction, Tid},
+ erase(mnesia_activity_state),
+ dbg_out("Transaction ~p calling ~p with ~p, failed ~p~n",
+ [Tid, Fun, Args, Reason]),
+ flush_downs(),
+ {aborted, mnesia_lib:fix_error(Reason)};
+ true ->
+ %% Nested transaction
+ [NewStore | Tail] = Ts#tidstore.up_stores,
+ req({del_store, Tid, NewStore, OldStore, true}),
+ Ts2 = Ts#tidstore{store = NewStore,
+ up_stores = Tail,
+ level = Level - 1},
+ NewTidTs = {Mod, Tid, Ts2},
+ put(mnesia_activity_state, NewTidTs),
+ case Reason of
+ #cyclic{} ->
+ exit({aborted, Reason});
+ {node_not_running, _N} ->
+ exit({aborted, Reason});
+ {bad_commit, _N}->
+ exit({aborted, Reason});
+ _ ->
+ {aborted, mnesia_lib:fix_error(Reason)}
+ end
+ end.
+
+flush_downs() ->
+ receive
+ {?MODULE, _, _} -> flush_downs(); % Votes
+ {mnesia_down, _} -> flush_downs()
+ after 0 -> flushed
+ end.
+
+put_activity_id(undefined) ->
+ erase_activity_id();
+put_activity_id({Mod, Tid, Ts}) when record(Tid, tid), record(Ts, tidstore) ->
+ flush_downs(),
+ Store = Ts#tidstore.store,
+ ?ets_insert(Store, {friends, self()}),
+ NewTidTs = {Mod, Tid, Ts},
+ put(mnesia_activity_state, NewTidTs);
+put_activity_id(SimpleState) ->
+ put(mnesia_activity_state, SimpleState).
+
+erase_activity_id() ->
+ flush_downs(),
+ erase(mnesia_activity_state).
+
+get_nodes(Store) ->
+ case catch ?ets_lookup_element(Store, nodes, 2) of
+ {'EXIT', _} -> [node()];
+ Nodes -> Nodes
+ end.
+
+get_friends(Store) ->
+ case catch ?ets_lookup_element(Store, friends, 2) of
+ {'EXIT', _} -> [];
+ Friends -> Friends
+ end.
+
+opt_propagate_store(_Current, _Obsolete, false) ->
+ ok;
+opt_propagate_store(Current, Obsolete, true) ->
+ propagate_store(Current, nodes, get_nodes(Obsolete)),
+ propagate_store(Current, friends, get_friends(Obsolete)).
+
+propagate_store(Store, Var, [Val | Vals]) ->
+ ?ets_insert(Store, {Var, Val}),
+ propagate_store(Store, Var, Vals);
+propagate_store(_Store, _Var, []) ->
+ ok.
+
+%% Tell all processes that are cooperating with the current transaction
+intercept_friends(_Tid, Ts) ->
+ Friends = get_friends(Ts#tidstore.store),
+ Message = {activity_ended, undefined, self()},
+ intercept_best_friend(Friends, Message).
+
+intercept_best_friend([], _Message) ->
+ ok;
+intercept_best_friend([Pid | _], Message) ->
+ Pid ! Message,
+ wait_for_best_friend(Pid, 0).
+
+wait_for_best_friend(Pid, Timeout) ->
+ receive
+ {'EXIT', Pid, _} -> ok;
+ {activity_ended, _, Pid} -> ok
+ after Timeout ->
+ case my_process_is_alive(Pid) of
+ true -> wait_for_best_friend(Pid, 1000);
+ false -> ok
+ end
+ end.
+
+my_process_is_alive(Pid) ->
+ case catch erlang:is_process_alive(Pid) of % New BIF in R5
+ true ->
+ true;
+ false ->
+ false;
+ {'EXIT', _} -> % Pre R5 backward compatibility
+ case process_info(Pid, message_queue_len) of
+ undefined -> false;
+ _ -> true
+ end
+ end.
+
+dirty(Protocol, Item) ->
+ {{Tab, Key}, _Val, _Op} = Item,
+ Tid = {dirty, self()},
+ Prep = prepare_items(Tid, Tab, Key, [Item], #prep{protocol= Protocol}),
+ CR = Prep#prep.records,
+ case Protocol of
+ async_dirty ->
+ %% Send commit records to the other involved nodes,
+ %% but do only wait for one node to complete.
+ %% Preferrably, the local node if possible.
+
+ ReadNode = val({Tab, where_to_read}),
+ {WaitFor, FirstRes} = async_send_dirty(Tid, CR, Tab, ReadNode),
+ rec_dirty(WaitFor, FirstRes);
+
+ sync_dirty ->
+ %% Send commit records to the other involved nodes,
+ %% and wait for all nodes to complete
+ {WaitFor, FirstRes} = sync_send_dirty(Tid, CR, Tab, []),
+ rec_dirty(WaitFor, FirstRes);
+ _ ->
+ mnesia:abort({bad_activity, Protocol})
+ end.
+
+%% This is the commit function, The first thing it does,
+%% is to find out which nodes that have been participating
+%% in this particular transaction, all of the mnesia_locker:lock*
+%% functions insert the names of the nodes where it aquires locks
+%% into the local shadow Store
+%% This function exacutes in the context of the user process
+t_commit(Type) ->
+ {Mod, Tid, Ts} = get(mnesia_activity_state),
+ Store = Ts#tidstore.store,
+ if
+ Ts#tidstore.level == 1 ->
+ intercept_friends(Tid, Ts),
+ %% N is number of updates
+ case arrange(Tid, Store, Type) of
+ {N, Prep} when N > 0 ->
+ multi_commit(Prep#prep.protocol,
+ Tid, Prep#prep.records, Store);
+ {0, Prep} ->
+ multi_commit(read_only, Tid, Prep#prep.records, Store)
+ end;
+ true ->
+ %% nested commit
+ Level = Ts#tidstore.level,
+ [Obsolete | Tail] = Ts#tidstore.up_stores,
+ req({del_store, Tid, Store, Obsolete, false}),
+ NewTs = Ts#tidstore{store = Store,
+ up_stores = Tail,
+ level = Level - 1},
+ NewTidTs = {Mod, Tid, NewTs},
+ put(mnesia_activity_state, NewTidTs),
+ do_commit_nested
+ end.
+
+%% This function arranges for all objects we shall write in S to be
+%% in a list of {Node, CommitRecord}
+%% Important function for the performance of mnesia.
+
+arrange(Tid, Store, Type) ->
+ %% The local node is always included
+ Nodes = get_nodes(Store),
+ Recs = prep_recs(Nodes, []),
+ Key = ?ets_first(Store),
+ N = 0,
+ Prep =
+ case Type of
+ async -> #prep{protocol = sym_trans, records = Recs};
+ sync -> #prep{protocol = sync_sym_trans, records = Recs}
+ end,
+ case catch do_arrange(Tid, Store, Key, Prep, N) of
+ {'EXIT', Reason} ->
+ dbg_out("do_arrange failed ~p ~p~n", [Reason, Tid]),
+ case Reason of
+ {aborted, R} ->
+ mnesia:abort(R);
+ _ ->
+ mnesia:abort(Reason)
+ end;
+ {New, Prepared} ->
+ {New, Prepared#prep{records = reverse(Prepared#prep.records)}}
+ end.
+
+reverse([]) ->
+ [];
+reverse([H|R]) when record(H, commit) ->
+ [
+ H#commit{
+ ram_copies = lists:reverse(H#commit.ram_copies),
+ disc_copies = lists:reverse(H#commit.disc_copies),
+ disc_only_copies = lists:reverse(H#commit.disc_only_copies),
+ snmp = lists:reverse(H#commit.snmp)
+ }
+ | reverse(R)].
+
+prep_recs([N | Nodes], Recs) ->
+ prep_recs(Nodes, [#commit{decision = presume_commit, node = N} | Recs]);
+prep_recs([], Recs) ->
+ Recs.
+
+%% storage_types is a list of {Node, Storage} tuples
+%% where each tuple represents an active replica
+do_arrange(Tid, Store, {Tab, Key}, Prep, N) ->
+ Oid = {Tab, Key},
+ Items = ?ets_lookup(Store, Oid), %% Store is a bag
+ P2 = prepare_items(Tid, Tab, Key, Items, Prep),
+ do_arrange(Tid, Store, ?ets_next(Store, Oid), P2, N + 1);
+do_arrange(Tid, Store, SchemaKey, Prep, N) when SchemaKey == op ->
+ Items = ?ets_lookup(Store, SchemaKey), %% Store is a bag
+ P2 = prepare_schema_items(Tid, Items, Prep),
+ do_arrange(Tid, Store, ?ets_next(Store, SchemaKey), P2, N + 1);
+do_arrange(Tid, Store, RestoreKey, Prep, N) when RestoreKey == restore_op ->
+ [{restore_op, R}] = ?ets_lookup(Store, RestoreKey),
+ Fun = fun({Tab, Key}, CommitRecs, _RecName, Where, Snmp) ->
+ Item = [{{Tab, Key}, {Tab, Key}, delete}],
+ do_prepare_items(Tid, Tab, Key, Where, Snmp, Item, CommitRecs);
+ (BupRec, CommitRecs, RecName, Where, Snmp) ->
+ Tab = element(1, BupRec),
+ Key = element(2, BupRec),
+ Item =
+ if
+ Tab == RecName ->
+ [{{Tab, Key}, BupRec, write}];
+ true ->
+ BupRec2 = setelement(1, BupRec, RecName),
+ [{{Tab, Key}, BupRec2, write}]
+ end,
+ do_prepare_items(Tid, Tab, Key, Where, Snmp, Item, CommitRecs)
+ end,
+ Recs2 = mnesia_schema:arrange_restore(R, Fun, Prep#prep.records),
+ P2 = Prep#prep{protocol = asym_trans, records = Recs2},
+ do_arrange(Tid, Store, ?ets_next(Store, RestoreKey), P2, N + 1);
+do_arrange(_Tid, _Store, '$end_of_table', Prep, N) ->
+ {N, Prep};
+do_arrange(Tid, Store, IgnoredKey, Prep, N) -> %% locks, nodes ... local atoms...
+ do_arrange(Tid, Store, ?ets_next(Store, IgnoredKey), Prep, N).
+
+%% Returns a prep record with all items in reverse order
+prepare_schema_items(Tid, Items, Prep) ->
+ Types = [{N, schema_ops} || N <- val({current, db_nodes})],
+ Recs = prepare_nodes(Tid, Types, Items, Prep#prep.records, schema),
+ Prep#prep{protocol = asym_trans, records = Recs}.
+
+%% Returns a prep record with all items in reverse order
+prepare_items(Tid, Tab, Key, Items, Prep) when Prep#prep.prev_tab == Tab ->
+ Types = Prep#prep.prev_types,
+ Snmp = Prep#prep.prev_snmp,
+ Recs = Prep#prep.records,
+ Recs2 = do_prepare_items(Tid, Tab, Key, Types, Snmp, Items, Recs),
+ Prep#prep{records = Recs2};
+
+prepare_items(Tid, Tab, Key, Items, Prep) ->
+ Types = val({Tab, where_to_commit}),
+ case Types of
+ [] -> mnesia:abort({no_exists, Tab});
+ {blocked, _} ->
+ unblocked = req({unblock_me, Tab}),
+ prepare_items(Tid, Tab, Key, Items, Prep);
+ _ ->
+ Snmp = val({Tab, snmp}),
+ Recs2 = do_prepare_items(Tid, Tab, Key, Types,
+ Snmp, Items, Prep#prep.records),
+ Prep2 = Prep#prep{records = Recs2, prev_tab = Tab,
+ prev_types = Types, prev_snmp = Snmp},
+ check_prep(Prep2, Types)
+ end.
+
+do_prepare_items(Tid, Tab, Key, Types, Snmp, Items, Recs) ->
+ Recs2 = prepare_snmp(Tid, Tab, Key, Types, Snmp, Items, Recs), % May exit
+ prepare_nodes(Tid, Types, Items, Recs2, normal).
+
+prepare_snmp(Tab, Key, Items) ->
+ case val({Tab, snmp}) of
+ [] ->
+ [];
+ Ustruct when Key /= '_' ->
+ {_Oid, _Val, Op} = hd(Items),
+ %% Still making snmp oid (not used) because we want to catch errors here
+ %% And also it keeps backwards comp. with old nodes.
+ SnmpOid = mnesia_snmp_hook:key_to_oid(Tab, Key, Ustruct), % May exit
+ [{Op, Tab, Key, SnmpOid}];
+ _ ->
+ [{clear_table, Tab}]
+ end.
+
+prepare_snmp(_Tid, _Tab, _Key, _Types, [], _Items, Recs) ->
+ Recs;
+
+prepare_snmp(Tid, Tab, Key, Types, Us, Items, Recs) ->
+ if Key /= '_' ->
+ {_Oid, _Val, Op} = hd(Items),
+ SnmpOid = mnesia_snmp_hook:key_to_oid(Tab, Key, Us), % May exit
+ prepare_nodes(Tid, Types, [{Op, Tab, Key, SnmpOid}], Recs, snmp);
+ Key == '_' ->
+ prepare_nodes(Tid, Types, [{clear_table, Tab}], Recs, snmp)
+ end.
+
+check_prep(Prep, Types) when Prep#prep.types == Types ->
+ Prep;
+check_prep(Prep, Types) when Prep#prep.types == undefined ->
+ Prep#prep{types = Types};
+check_prep(Prep, _Types) ->
+ Prep#prep{protocol = asym_trans}.
+
+%% Returns a list of commit records
+prepare_nodes(Tid, [{Node, Storage} | Rest], Items, C, Kind) ->
+ {Rec, C2} = pick_node(Tid, Node, C, []),
+ Rec2 = prepare_node(Node, Storage, Items, Rec, Kind),
+ [Rec2 | prepare_nodes(Tid, Rest, Items, C2, Kind)];
+prepare_nodes(_Tid, [], _Items, CommitRecords, _Kind) ->
+ CommitRecords.
+
+pick_node(Tid, Node, [Rec | Rest], Done) ->
+ if
+ Rec#commit.node == Node ->
+ {Rec, Done ++ Rest};
+ true ->
+ pick_node(Tid, Node, Rest, [Rec | Done])
+ end;
+pick_node(_Tid, Node, [], Done) ->
+ {#commit{decision = presume_commit, node = Node}, Done}.
+
+prepare_node(Node, Storage, [Item | Items], Rec, Kind) when Kind == snmp ->
+ Rec2 = Rec#commit{snmp = [Item | Rec#commit.snmp]},
+ prepare_node(Node, Storage, Items, Rec2, Kind);
+prepare_node(Node, Storage, [Item | Items], Rec, Kind) when Kind /= schema ->
+ Rec2 =
+ case Storage of
+ ram_copies ->
+ Rec#commit{ram_copies = [Item | Rec#commit.ram_copies]};
+ disc_copies ->
+ Rec#commit{disc_copies = [Item | Rec#commit.disc_copies]};
+ disc_only_copies ->
+ Rec#commit{disc_only_copies =
+ [Item | Rec#commit.disc_only_copies]}
+ end,
+ prepare_node(Node, Storage, Items, Rec2, Kind);
+prepare_node(_Node, _Storage, Items, Rec, Kind)
+ when Kind == schema, Rec#commit.schema_ops == [] ->
+ Rec#commit{schema_ops = Items};
+prepare_node(_Node, _Storage, [], Rec, _Kind) ->
+ Rec.
+
+%% multi_commit((Protocol, Tid, CommitRecords, Store)
+%% Local work is always performed in users process
+multi_commit(read_only, Tid, CR, _Store) ->
+ %% This featherweight commit protocol is used when no
+ %% updates has been performed in the transaction.
+
+ {DiscNs, RamNs} = commit_nodes(CR, [], []),
+ Msg = {Tid, simple_commit},
+ rpc:abcast(DiscNs -- [node()], ?MODULE, Msg),
+ rpc:abcast(RamNs -- [node()], ?MODULE, Msg),
+ mnesia_recover:note_decision(Tid, committed),
+ mnesia_locker:release_tid(Tid),
+ ?MODULE ! {delete_transaction, Tid},
+ do_commit;
+
+multi_commit(sym_trans, Tid, CR, Store) ->
+ %% This lightweight commit protocol is used when all
+ %% the involved tables are replicated symetrically.
+ %% Their storage types must match on each node.
+ %%
+ %% 1 Ask the other involved nodes if they want to commit
+ %% All involved nodes votes yes if they are up
+ %% 2a Somebody has voted no
+ %% Tell all yes voters to do_abort
+ %% 2b Everybody has voted yes
+ %% Tell everybody to do_commit. I.e. that they should
+ %% prepare the commit, log the commit record and
+ %% perform the updates.
+ %%
+ %% The outcome is kept 3 minutes in the transient decision table.
+ %%
+ %% Recovery:
+ %% If somebody dies before the coordinator has
+ %% broadcasted do_commit, the transaction is aborted.
+ %%
+ %% If a participant dies, the table load algorithm
+ %% ensures that the contents of the involved tables
+ %% are picked from another node.
+ %%
+ %% If the coordinator dies, each participants checks
+ %% the outcome with all the others. If all are uncertain
+ %% about the outcome, the transaction is aborted. If
+ %% somebody knows the outcome the others will follow.
+
+ {DiscNs, RamNs} = commit_nodes(CR, [], []),
+ Pending = mnesia_checkpoint:tm_enter_pending(Tid, DiscNs, RamNs),
+ ?ets_insert(Store, Pending),
+
+ {WaitFor, Local} = ask_commit(sym_trans, Tid, CR, DiscNs, RamNs),
+ {Outcome, []} = rec_all(WaitFor, Tid, do_commit, []),
+ ?eval_debug_fun({?MODULE, multi_commit_sym},
+ [{tid, Tid}, {outcome, Outcome}]),
+ rpc:abcast(DiscNs -- [node()], ?MODULE, {Tid, Outcome}),
+ rpc:abcast(RamNs -- [node()], ?MODULE, {Tid, Outcome}),
+ case Outcome of
+ do_commit ->
+ mnesia_recover:note_decision(Tid, committed),
+ do_dirty(Tid, Local),
+ mnesia_locker:release_tid(Tid),
+ ?MODULE ! {delete_transaction, Tid};
+ {do_abort, _Reason} ->
+ mnesia_recover:note_decision(Tid, aborted)
+ end,
+ ?eval_debug_fun({?MODULE, multi_commit_sym, post},
+ [{tid, Tid}, {outcome, Outcome}]),
+ Outcome;
+
+multi_commit(sync_sym_trans, Tid, CR, Store) ->
+ %% This protocol is the same as sym_trans except that it
+ %% uses syncronized calls to disk_log and syncronized commits
+ %% when several nodes are involved.
+
+ {DiscNs, RamNs} = commit_nodes(CR, [], []),
+ Pending = mnesia_checkpoint:tm_enter_pending(Tid, DiscNs, RamNs),
+ ?ets_insert(Store, Pending),
+
+ {WaitFor, Local} = ask_commit(sync_sym_trans, Tid, CR, DiscNs, RamNs),
+ {Outcome, []} = rec_all(WaitFor, Tid, do_commit, []),
+ ?eval_debug_fun({?MODULE, multi_commit_sym_sync},
+ [{tid, Tid}, {outcome, Outcome}]),
+ rpc:abcast(DiscNs -- [node()], ?MODULE, {Tid, Outcome}),
+ rpc:abcast(RamNs -- [node()], ?MODULE, {Tid, Outcome}),
+ case Outcome of
+ do_commit ->
+ mnesia_recover:note_decision(Tid, committed),
+ mnesia_log:slog(Local),
+ do_commit(Tid, Local),
+ %% Just wait for completion result is ignore.
+ rec_all(WaitFor, Tid, ignore, []),
+ mnesia_locker:release_tid(Tid),
+ ?MODULE ! {delete_transaction, Tid};
+ {do_abort, _Reason} ->
+ mnesia_recover:note_decision(Tid, aborted)
+ end,
+ ?eval_debug_fun({?MODULE, multi_commit_sym, post},
+ [{tid, Tid}, {outcome, Outcome}]),
+ Outcome;
+
+multi_commit(asym_trans, Tid, CR, Store) ->
+ %% This more expensive commit protocol is used when
+ %% table definitions are changed (schema transactions).
+ %% It is also used when the involved tables are
+ %% replicated asymetrically. If the storage type differs
+ %% on at least one node this protocol is used.
+ %%
+ %% 1 Ask the other involved nodes if they want to commit.
+ %% All involved nodes prepares the commit, logs a presume_abort
+ %% commit record and votes yes or no depending of the
+ %% outcome of the prepare. The preparation is also performed
+ %% by the coordinator.
+ %%
+ %% 2a Somebody has died or voted no
+ %% Tell all yes voters to do_abort
+ %% 2b Everybody has voted yes
+ %% Put a unclear marker in the log.
+ %% Tell the others to pre_commit. I.e. that they should
+ %% put a unclear marker in the log and reply
+ %% acc_pre_commit when they are done.
+ %%
+ %% 3a Somebody died
+ %% Tell the remaining participants to do_abort
+ %% 3b Everybody has replied acc_pre_commit
+ %% Tell everybody to committed. I.e that they should
+ %% put a committed marker in the log, perform the updates
+ %% and reply done_commit when they are done. The coordinator
+ %% must wait with putting his committed marker inte the log
+ %% until the committed has been sent to all the others.
+ %% Then he performs local commit before collecting replies.
+ %%
+ %% 4 Everybody has either died or replied done_commit
+ %% Return to the caller.
+ %%
+ %% Recovery:
+ %% If the coordinator dies, the participants (and
+ %% the coordinator when he starts again) must do
+ %% the following:
+ %%
+ %% If we have no unclear marker in the log we may
+ %% safely abort, since we know that nobody may have
+ %% decided to commit yet.
+ %%
+ %% If we have a committed marker in the log we may
+ %% safely commit since we know that everybody else
+ %% also will come to this conclusion.
+ %%
+ %% If we have a unclear marker but no committed
+ %% in the log we are uncertain about the real outcome
+ %% of the transaction and must ask the others before
+ %% we can decide what to do. If someone knows the
+ %% outcome we will do the same. If nobody knows, we
+ %% will wait for the remaining involved nodes to come
+ %% up. When all involved nodes are up and uncertain,
+ %% we decide to commit (first put a committed marker
+ %% in the log, then do the updates).
+
+ D = #decision{tid = Tid, outcome = presume_abort},
+ {D2, CR2} = commit_decision(D, CR, [], []),
+ DiscNs = D2#decision.disc_nodes,
+ RamNs = D2#decision.ram_nodes,
+ Pending = mnesia_checkpoint:tm_enter_pending(Tid, DiscNs, RamNs),
+ ?ets_insert(Store, Pending),
+ {WaitFor, Local} = ask_commit(asym_trans, Tid, CR2, DiscNs, RamNs),
+ SchemaPrep = (catch mnesia_schema:prepare_commit(Tid, Local, {coord, WaitFor})),
+ {Votes, Pids} = rec_all(WaitFor, Tid, do_commit, []),
+
+ ?eval_debug_fun({?MODULE, multi_commit_asym_got_votes},
+ [{tid, Tid}, {votes, Votes}]),
+ case Votes of
+ do_commit ->
+ case SchemaPrep of
+ {_Modified, C, DumperMode} when record(C, commit) ->
+ mnesia_log:log(C), % C is not a binary
+ ?eval_debug_fun({?MODULE, multi_commit_asym_log_commit_rec},
+ [{tid, Tid}]),
+
+ D3 = C#commit.decision,
+ D4 = D3#decision{outcome = unclear},
+ mnesia_recover:log_decision(D4),
+ ?eval_debug_fun({?MODULE, multi_commit_asym_log_commit_dec},
+ [{tid, Tid}]),
+ tell_participants(Pids, {Tid, pre_commit}),
+ %% Now we are uncertain and we do not know
+ %% if all participants have logged that
+ %% they are uncertain or not
+ rec_acc_pre_commit(Pids, Tid, Store, C,
+ do_commit, DumperMode, [], []);
+ {'EXIT', Reason} ->
+ %% The others have logged the commit
+ %% record but they are not uncertain
+ mnesia_recover:note_decision(Tid, aborted),
+ ?eval_debug_fun({?MODULE, multi_commit_asym_prepare_exit},
+ [{tid, Tid}]),
+ tell_participants(Pids, {Tid, {do_abort, Reason}}),
+ do_abort(Tid, Local),
+ {do_abort, Reason}
+ end;
+
+ {do_abort, Reason} ->
+ %% The others have logged the commit
+ %% record but they are not uncertain
+ mnesia_recover:note_decision(Tid, aborted),
+ ?eval_debug_fun({?MODULE, multi_commit_asym_do_abort}, [{tid, Tid}]),
+ tell_participants(Pids, {Tid, {do_abort, Reason}}),
+ do_abort(Tid, Local),
+ {do_abort, Reason}
+ end.
+
+%% Returns do_commit or {do_abort, Reason}
+rec_acc_pre_commit([Pid | Tail], Tid, Store, Commit, Res, DumperMode,
+ GoodPids, SchemaAckPids) ->
+ receive
+ {?MODULE, _, {acc_pre_commit, Tid, Pid, true}} ->
+ rec_acc_pre_commit(Tail, Tid, Store, Commit, Res, DumperMode,
+ [Pid | GoodPids], [Pid | SchemaAckPids]);
+
+ {?MODULE, _, {acc_pre_commit, Tid, Pid, false}} ->
+ rec_acc_pre_commit(Tail, Tid, Store, Commit, Res, DumperMode,
+ [Pid | GoodPids], SchemaAckPids);
+
+ {?MODULE, _, {acc_pre_commit, Tid, Pid}} ->
+ %% Kept for backwards compatibility. Remove after Mnesia 4.x
+ rec_acc_pre_commit(Tail, Tid, Store, Commit, Res, DumperMode,
+ [Pid | GoodPids], [Pid | SchemaAckPids]);
+
+ {mnesia_down, Node} when Node == node(Pid) ->
+ AbortRes = {do_abort, {bad_commit, Node}},
+ rec_acc_pre_commit(Tail, Tid, Store, Commit, AbortRes, DumperMode,
+ GoodPids, SchemaAckPids)
+ end;
+rec_acc_pre_commit([], Tid, Store, Commit, Res, DumperMode, GoodPids, SchemaAckPids) ->
+ D = Commit#commit.decision,
+ case Res of
+ do_commit ->
+ %% Now everybody knows that the others
+ %% has voted yes. We also know that
+ %% everybody are uncertain.
+ prepare_sync_schema_commit(Store, SchemaAckPids),
+ tell_participants(GoodPids, {Tid, committed}),
+ D2 = D#decision{outcome = committed},
+ mnesia_recover:log_decision(D2),
+ ?eval_debug_fun({?MODULE, rec_acc_pre_commit_log_commit},
+ [{tid, Tid}]),
+
+ %% Now we have safely logged committed
+ %% and we can recover without asking others
+ do_commit(Tid, Commit, DumperMode),
+ ?eval_debug_fun({?MODULE, rec_acc_pre_commit_done_commit},
+ [{tid, Tid}]),
+ sync_schema_commit(Tid, Store, SchemaAckPids),
+ mnesia_locker:release_tid(Tid),
+ ?MODULE ! {delete_transaction, Tid};
+
+ {do_abort, Reason} ->
+ tell_participants(GoodPids, {Tid, {do_abort, Reason}}),
+ D2 = D#decision{outcome = aborted},
+ mnesia_recover:log_decision(D2),
+ ?eval_debug_fun({?MODULE, rec_acc_pre_commit_log_abort},
+ [{tid, Tid}]),
+ do_abort(Tid, Commit),
+ ?eval_debug_fun({?MODULE, rec_acc_pre_commit_done_abort},
+ [{tid, Tid}])
+ end,
+ Res.
+
+%% Note all nodes in case of mnesia_down mgt
+prepare_sync_schema_commit(_Store, []) ->
+ ok;
+prepare_sync_schema_commit(Store, [Pid | Pids]) ->
+ ?ets_insert(Store, {waiting_for_commit_ack, node(Pid)}),
+ prepare_sync_schema_commit(Store, Pids).
+
+sync_schema_commit(_Tid, _Store, []) ->
+ ok;
+sync_schema_commit(Tid, Store, [Pid | Tail]) ->
+ receive
+ {?MODULE, _, {schema_commit, Tid, Pid}} ->
+ ?ets_match_delete(Store, {waiting_for_commit_ack, node(Pid)}),
+ sync_schema_commit(Tid, Store, Tail);
+
+ {mnesia_down, Node} when Node == node(Pid) ->
+ ?ets_match_delete(Store, {waiting_for_commit_ack, Node}),
+ sync_schema_commit(Tid, Store, Tail)
+ end.
+
+tell_participants([Pid | Pids], Msg) ->
+ Pid ! Msg,
+ tell_participants(Pids, Msg);
+tell_participants([], _Msg) ->
+ ok.
+
+%% No need for trapping exits. We are only linked
+%% to mnesia_tm and if it dies we should also die.
+%% The same goes for disk_log and dets.
+commit_participant(Coord, Tid, Bin, DiscNs, RamNs) when binary(Bin) ->
+ Commit = binary_to_term(Bin),
+ commit_participant(Coord, Tid, Bin, Commit, DiscNs, RamNs);
+commit_participant(Coord, Tid, C, DiscNs, RamNs) when record(C, commit) ->
+ commit_participant(Coord, Tid, C, C, DiscNs, RamNs).
+
+commit_participant(Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
+ ?eval_debug_fun({?MODULE, commit_participant, pre}, [{tid, Tid}]),
+ case catch mnesia_schema:prepare_commit(Tid, C0, {part, Coord}) of
+ {Modified, C, DumperMode} when record(C, commit) ->
+ %% If we can not find any local unclear decision
+ %% we should presume abort at startup recovery
+ case lists:member(node(), DiscNs) of
+ false ->
+ ignore;
+ true ->
+ case Modified of
+ false -> mnesia_log:log(Bin);
+ true -> mnesia_log:log(C)
+ end
+ end,
+ ?eval_debug_fun({?MODULE, commit_participant, vote_yes},
+ [{tid, Tid}]),
+ reply(Coord, {vote_yes, Tid, self()}),
+
+ receive
+ {Tid, pre_commit} ->
+ D = C#commit.decision,
+ mnesia_recover:log_decision(D#decision{outcome = unclear}),
+ ?eval_debug_fun({?MODULE, commit_participant, pre_commit},
+ [{tid, Tid}]),
+ Expect_schema_ack = C#commit.schema_ops /= [],
+ reply(Coord, {acc_pre_commit, Tid, self(), Expect_schema_ack}),
+
+ %% Now we are vulnerable for failures, since
+ %% we cannot decide without asking others
+ receive
+ {Tid, committed} ->
+ mnesia_recover:log_decision(D#decision{outcome = committed}),
+ ?eval_debug_fun({?MODULE, commit_participant, log_commit},
+ [{tid, Tid}]),
+ do_commit(Tid, C, DumperMode),
+ case Expect_schema_ack of
+ false -> ignore;
+ true -> reply(Coord, {schema_commit, Tid, self()})
+ end,
+ ?eval_debug_fun({?MODULE, commit_participant, do_commit},
+ [{tid, Tid}]);
+
+ {Tid, {do_abort, _Reason}} ->
+ mnesia_recover:log_decision(D#decision{outcome = aborted}),
+ ?eval_debug_fun({?MODULE, commit_participant, log_abort},
+ [{tid, Tid}]),
+ mnesia_schema:undo_prepare_commit(Tid, C),
+ ?eval_debug_fun({?MODULE, commit_participant, undo_prepare},
+ [{tid, Tid}]);
+
+ {'EXIT', _, _} ->
+ mnesia_recover:log_decision(D#decision{outcome = aborted}),
+ ?eval_debug_fun({?MODULE, commit_participant, exit_log_abort},
+ [{tid, Tid}]),
+ mnesia_schema:undo_prepare_commit(Tid, C),
+ ?eval_debug_fun({?MODULE, commit_participant, exit_undo_prepare},
+ [{tid, Tid}]);
+
+ Msg ->
+ verbose("** ERROR ** commit_participant ~p, got unexpected msg: ~p~n",
+ [Tid, Msg])
+ end;
+ {Tid, {do_abort, _Reason}} ->
+ mnesia_schema:undo_prepare_commit(Tid, C),
+ ?eval_debug_fun({?MODULE, commit_participant, pre_commit_undo_prepare},
+ [{tid, Tid}]);
+
+ {'EXIT', _, _} ->
+ mnesia_schema:undo_prepare_commit(Tid, C),
+ ?eval_debug_fun({?MODULE, commit_participant, pre_commit_undo_prepare}, [{tid, Tid}]);
+
+ Msg ->
+ verbose("** ERROR ** commit_participant ~p, got unexpected msg: ~p~n",
+ [Tid, Msg])
+ end;
+
+ {'EXIT', Reason} ->
+ ?eval_debug_fun({?MODULE, commit_participant, vote_no},
+ [{tid, Tid}]),
+ reply(Coord, {vote_no, Tid, Reason}),
+ mnesia_schema:undo_prepare_commit(Tid, C0)
+ end,
+ mnesia_locker:release_tid(Tid),
+ ?MODULE ! {delete_transaction, Tid},
+ unlink(whereis(?MODULE)),
+ exit(normal).
+
+do_abort(Tid, Bin) when binary(Bin) ->
+ %% Possible optimization:
+ %% If we want we could pass arround a flag
+ %% that tells us whether the binary contains
+ %% schema ops or not. Only if the binary
+ %% contains schema ops there are meningful
+ %% unpack the binary and perform
+ %% mnesia_schema:undo_prepare_commit/1.
+ do_abort(Tid, binary_to_term(Bin));
+do_abort(Tid, Commit) ->
+ mnesia_schema:undo_prepare_commit(Tid, Commit),
+ Commit.
+
+do_dirty(Tid, Commit) when Commit#commit.schema_ops == [] ->
+ mnesia_log:log(Commit),
+ do_commit(Tid, Commit).
+
+%% do_commit(Tid, CommitRecord)
+do_commit(Tid, Bin) when binary(Bin) ->
+ do_commit(Tid, binary_to_term(Bin));
+do_commit(Tid, C) ->
+ do_commit(Tid, C, optional).
+do_commit(Tid, Bin, DumperMode) when binary(Bin) ->
+ do_commit(Tid, binary_to_term(Bin), DumperMode);
+do_commit(Tid, C, DumperMode) ->
+ mnesia_dumper:update(Tid, C#commit.schema_ops, DumperMode),
+ R = do_snmp(Tid, C#commit.snmp),
+ R2 = do_update(Tid, ram_copies, C#commit.ram_copies, R),
+ R3 = do_update(Tid, disc_copies, C#commit.disc_copies, R2),
+ do_update(Tid, disc_only_copies, C#commit.disc_only_copies, R3).
+
+%% Update the items
+do_update(Tid, Storage, [Op | Ops], OldRes) ->
+ case catch do_update_op(Tid, Storage, Op) of
+ ok ->
+ do_update(Tid, Storage, Ops, OldRes);
+ {'EXIT', Reason} ->
+ %% This may only happen when we recently have
+ %% deleted our local replica, changed storage_type
+ %% or transformed table
+ %% BUGBUG: Updates may be lost if storage_type is changed.
+ %% Determine actual storage type and try again.
+ %% BUGBUG: Updates may be lost if table is transformed.
+
+ verbose("do_update in ~w failed: ~p -> {'EXIT', ~p}~n",
+ [Tid, Op, Reason]),
+ do_update(Tid, Storage, Ops, OldRes);
+ NewRes ->
+ do_update(Tid, Storage, Ops, NewRes)
+ end;
+do_update(_Tid, _Storage, [], Res) ->
+ Res.
+
+do_update_op(Tid, Storage, {{Tab, K}, Obj, write}) ->
+ commit_write(?catch_val({Tab, commit_work}), Tid,
+ Tab, K, Obj, undefined),
+ mnesia_lib:db_put(Storage, Tab, Obj);
+
+do_update_op(Tid, Storage, {{Tab, K}, Val, delete}) ->
+ commit_delete(?catch_val({Tab, commit_work}), Tid, Tab, K, Val, undefined),
+ mnesia_lib:db_erase(Storage, Tab, K);
+
+do_update_op(Tid, Storage, {{Tab, K}, {RecName, Incr}, update_counter}) ->
+ {NewObj, OldObjs} =
+ case catch mnesia_lib:db_update_counter(Storage, Tab, K, Incr) of
+ NewVal when integer(NewVal), NewVal >= 0 ->
+ {{RecName, K, NewVal}, [{RecName, K, NewVal - Incr}]};
+ _ ->
+ Zero = {RecName, K, 0},
+ mnesia_lib:db_put(Storage, Tab, Zero),
+ {Zero, []}
+ end,
+ commit_update(?catch_val({Tab, commit_work}), Tid, Tab,
+ K, NewObj, OldObjs),
+ element(3, NewObj);
+
+do_update_op(Tid, Storage, {{Tab, Key}, Obj, delete_object}) ->
+ commit_del_object(?catch_val({Tab, commit_work}),
+ Tid, Tab, Key, Obj, undefined),
+ mnesia_lib:db_match_erase(Storage, Tab, Obj);
+
+do_update_op(Tid, Storage, {{Tab, Key}, Obj, clear_table}) ->
+ commit_clear(?catch_val({Tab, commit_work}), Tid, Tab, Key, Obj),
+ mnesia_lib:db_match_erase(Storage, Tab, Obj).
+
+commit_write([], _, _, _, _, _) -> ok;
+commit_write([{checkpoints, CpList}|R], Tid, Tab, K, Obj, Old) ->
+ mnesia_checkpoint:tm_retain(Tid, Tab, K, write, CpList),
+ commit_write(R, Tid, Tab, K, Obj, Old);
+commit_write([H|R], Tid, Tab, K, Obj, Old)
+ when element(1, H) == subscribers ->
+ mnesia_subscr:report_table_event(H, Tab, Tid, Obj, write, Old),
+ commit_write(R, Tid, Tab, K, Obj, Old);
+commit_write([H|R], Tid, Tab, K, Obj, Old)
+ when element(1, H) == index ->
+ mnesia_index:add_index(H, Tab, K, Obj, Old),
+ commit_write(R, Tid, Tab, K, Obj, Old).
+
+commit_update([], _, _, _, _, _) -> ok;
+commit_update([{checkpoints, CpList}|R], Tid, Tab, K, Obj, _) ->
+ Old = mnesia_checkpoint:tm_retain(Tid, Tab, K, write, CpList),
+ commit_update(R, Tid, Tab, K, Obj, Old);
+commit_update([H|R], Tid, Tab, K, Obj, Old)
+ when element(1, H) == subscribers ->
+ mnesia_subscr:report_table_event(H, Tab, Tid, Obj, write, Old),
+ commit_update(R, Tid, Tab, K, Obj, Old);
+commit_update([H|R], Tid, Tab, K, Obj, Old)
+ when element(1, H) == index ->
+ mnesia_index:add_index(H, Tab, K, Obj, Old),
+ commit_update(R, Tid, Tab, K, Obj, Old).
+
+commit_delete([], _, _, _, _, _) -> ok;
+commit_delete([{checkpoints, CpList}|R], Tid, Tab, K, Obj, _) ->
+ Old = mnesia_checkpoint:tm_retain(Tid, Tab, K, delete, CpList),
+ commit_delete(R, Tid, Tab, K, Obj, Old);
+commit_delete([H|R], Tid, Tab, K, Obj, Old)
+ when element(1, H) == subscribers ->
+ mnesia_subscr:report_table_event(H, Tab, Tid, Obj, delete, Old),
+ commit_delete(R, Tid, Tab, K, Obj, Old);
+commit_delete([H|R], Tid, Tab, K, Obj, Old)
+ when element(1, H) == index ->
+ mnesia_index:delete_index(H, Tab, K),
+ commit_delete(R, Tid, Tab, K, Obj, Old).
+
+commit_del_object([], _, _, _, _, _) -> ok;
+commit_del_object([{checkpoints, CpList}|R], Tid, Tab, K, Obj, _) ->
+ Old = mnesia_checkpoint:tm_retain(Tid, Tab, K, delete_object, CpList),
+ commit_del_object(R, Tid, Tab, K, Obj, Old);
+commit_del_object([H|R], Tid, Tab, K, Obj, Old)
+ when element(1, H) == subscribers ->
+ mnesia_subscr:report_table_event(H, Tab, Tid, Obj, delete_object, Old),
+ commit_del_object(R, Tid, Tab, K, Obj, Old);
+commit_del_object([H|R], Tid, Tab, K, Obj, Old)
+ when element(1, H) == index ->
+ mnesia_index:del_object_index(H, Tab, K, Obj, Old),
+ commit_del_object(R, Tid, Tab, K, Obj, Old).
+
+commit_clear([], _, _, _, _) -> ok;
+commit_clear([{checkpoints, CpList}|R], Tid, Tab, K, Obj) ->
+ mnesia_checkpoint:tm_retain(Tid, Tab, K, clear_table, CpList),
+ commit_clear(R, Tid, Tab, K, Obj);
+commit_clear([H|R], Tid, Tab, K, Obj)
+ when element(1, H) == subscribers ->
+ mnesia_subscr:report_table_event(H, Tab, Tid, Obj, clear_table, undefined),
+ commit_clear(R, Tid, Tab, K, Obj);
+commit_clear([H|R], Tid, Tab, K, Obj)
+ when element(1, H) == index ->
+ mnesia_index:clear_index(H, Tab, K, Obj),
+ commit_clear(R, Tid, Tab, K, Obj).
+
+do_snmp(_, []) -> ok;
+do_snmp(Tid, [Head | Tail]) ->
+ case catch mnesia_snmp_hook:update(Head) of
+ {'EXIT', Reason} ->
+ %% This should only happen when we recently have
+ %% deleted our local replica or recently deattached
+ %% the snmp table
+
+ verbose("do_snmp in ~w failed: ~p -> {'EXIT', ~p}~n",
+ [Tid, Head, Reason]);
+ ok ->
+ ignore
+ end,
+ do_snmp(Tid, Tail).
+
+commit_nodes([C | Tail], AccD, AccR)
+ when C#commit.disc_copies == [],
+ C#commit.disc_only_copies == [],
+ C#commit.schema_ops == [] ->
+ commit_nodes(Tail, AccD, [C#commit.node | AccR]);
+commit_nodes([C | Tail], AccD, AccR) ->
+ commit_nodes(Tail, [C#commit.node | AccD], AccR);
+commit_nodes([], AccD, AccR) ->
+ {AccD, AccR}.
+
+commit_decision(D, [C | Tail], AccD, AccR) ->
+ N = C#commit.node,
+ {D2, Tail2} =
+ case C#commit.schema_ops of
+ [] when C#commit.disc_copies == [],
+ C#commit.disc_only_copies == [] ->
+ commit_decision(D, Tail, AccD, [N | AccR]);
+ [] ->
+ commit_decision(D, Tail, [N | AccD], AccR);
+ Ops ->
+ case ram_only_ops(N, Ops) of
+ true ->
+ commit_decision(D, Tail, AccD, [N | AccR]);
+ false ->
+ commit_decision(D, Tail, [N | AccD], AccR)
+ end
+ end,
+ {D2, [C#commit{decision = D2} | Tail2]};
+commit_decision(D, [], AccD, AccR) ->
+ {D#decision{disc_nodes = AccD, ram_nodes = AccR}, []}.
+
+ram_only_ops(N, [{op, change_table_copy_type, N, _FromS, _ToS, Cs} | _Ops ]) ->
+ case lists:member({name, schema}, Cs) of
+ true ->
+ %% We always use disk if change type of the schema
+ false;
+ false ->
+ not lists:member(N, val({schema, disc_copies}))
+ end;
+
+ram_only_ops(N, _Ops) ->
+ not lists:member(N, val({schema, disc_copies})).
+
+%% Returns {WaitFor, Res}
+sync_send_dirty(Tid, [Head | Tail], Tab, WaitFor) ->
+ Node = Head#commit.node,
+ if
+ Node == node() ->
+ {WF, _} = sync_send_dirty(Tid, Tail, Tab, WaitFor),
+ Res = do_dirty(Tid, Head),
+ {WF, Res};
+ true ->
+ {?MODULE, Node} ! {self(), {sync_dirty, Tid, Head, Tab}},
+ sync_send_dirty(Tid, Tail, Tab, [Node | WaitFor])
+ end;
+sync_send_dirty(_Tid, [], _Tab, WaitFor) ->
+ {WaitFor, {'EXIT', {aborted, {node_not_running, WaitFor}}}}.
+
+%% Returns {WaitFor, Res}
+async_send_dirty(_Tid, _Nodes, Tab, nowhere) ->
+ {[], {'EXIT', {aborted, {no_exists, Tab}}}};
+async_send_dirty(Tid, Nodes, Tab, ReadNode) ->
+ async_send_dirty(Tid, Nodes, Tab, ReadNode, [], ok).
+
+async_send_dirty(Tid, [Head | Tail], Tab, ReadNode, WaitFor, Res) ->
+ Node = Head#commit.node,
+ if
+ ReadNode == Node, Node == node() ->
+ NewRes = do_dirty(Tid, Head),
+ async_send_dirty(Tid, Tail, Tab, ReadNode, WaitFor, NewRes);
+ ReadNode == Node ->
+ {?MODULE, Node} ! {self(), {sync_dirty, Tid, Head, Tab}},
+ NewRes = {'EXIT', {aborted, {node_not_running, Node}}},
+ async_send_dirty(Tid, Tail, Tab, ReadNode, [Node | WaitFor], NewRes);
+ true ->
+ {?MODULE, Node} ! {self(), {async_dirty, Tid, Head, Tab}},
+ async_send_dirty(Tid, Tail, Tab, ReadNode, WaitFor, Res)
+ end;
+async_send_dirty(_Tid, [], _Tab, _ReadNode, WaitFor, Res) ->
+ {WaitFor, Res}.
+
+rec_dirty([Node | Tail], Res) when Node /= node() ->
+ NewRes = get_dirty_reply(Node, Res),
+ rec_dirty(Tail, NewRes);
+rec_dirty([], Res) ->
+ Res.
+
+get_dirty_reply(Node, Res) ->
+ receive
+ {?MODULE, Node, {'EXIT', Reason}} ->
+ {'EXIT', {aborted, {badarg, Reason}}};
+ {?MODULE, Node, {dirty_res, ok}} ->
+ case Res of
+ {'EXIT', {aborted, {node_not_running, _Node}}} ->
+ ok;
+ _ ->
+ %% Prioritize bad results, but node_not_running
+ Res
+ end;
+ {?MODULE, Node, {dirty_res, Reply}} ->
+ Reply;
+ {mnesia_down, Node} ->
+ %% It's ok to ignore mnesia_down's
+ %% since we will make the replicas
+ %% consistent again when Node is started
+ Res
+ after 1000 ->
+ case lists:member(Node, val({current, db_nodes})) of
+ true ->
+ get_dirty_reply(Node, Res);
+ false ->
+ Res
+ end
+ end.
+
+%% Assume that CommitRecord is no binary
+%% Return {Res, Pids}
+ask_commit(Protocol, Tid, CR, DiscNs, RamNs) ->
+ ask_commit(Protocol, Tid, CR, DiscNs, RamNs, [], no_local).
+
+ask_commit(Protocol, Tid, [Head | Tail], DiscNs, RamNs, WaitFor, Local) ->
+ Node = Head#commit.node,
+ if
+ Node == node() ->
+ ask_commit(Protocol, Tid, Tail, DiscNs, RamNs, WaitFor, Head);
+ true ->
+ Bin = opt_term_to_binary(Protocol, Head, DiscNs++RamNs),
+ Msg = {ask_commit, Protocol, Tid, Bin, DiscNs, RamNs},
+ {?MODULE, Node} ! {self(), Msg},
+ ask_commit(Protocol, Tid, Tail, DiscNs, RamNs, [Node | WaitFor], Local)
+ end;
+ask_commit(_Protocol, _Tid, [], _DiscNs, _RamNs, WaitFor, Local) ->
+ {WaitFor, Local}.
+
+opt_term_to_binary(asym_trans, Head, Nodes) ->
+ opt_term_to_binary(Nodes, Head);
+opt_term_to_binary(_Protocol, Head, _Nodes) ->
+ Head.
+
+opt_term_to_binary([], Head) ->
+ term_to_binary(Head);
+opt_term_to_binary([H|R], Head) ->
+ case mnesia_monitor:needs_protocol_conversion(H) of
+ true -> Head;
+ false ->
+ opt_term_to_binary(R, Head)
+ end.
+
+rec_all([Node | Tail], Tid, Res, Pids) ->
+ receive
+ {?MODULE, Node, {vote_yes, Tid}} ->
+ rec_all(Tail, Tid, Res, Pids);
+ {?MODULE, Node, {vote_yes, Tid, Pid}} ->
+ rec_all(Tail, Tid, Res, [Pid | Pids]);
+ {?MODULE, Node, {vote_no, Tid, Reason}} ->
+ rec_all(Tail, Tid, {do_abort, Reason}, Pids);
+ {?MODULE, Node, {committed, Tid}} ->
+ rec_all(Tail, Tid, Res, Pids);
+ {?MODULE, Node, {aborted, Tid}} ->
+ rec_all(Tail, Tid, Res, Pids);
+
+ {mnesia_down, Node} ->
+ rec_all(Tail, Tid, {do_abort, {bad_commit, Node}}, Pids)
+ end;
+rec_all([], _Tid, Res, Pids) ->
+ {Res, Pids}.
+
+get_transactions() ->
+ {info, Participant, Coordinator} = req(info),
+ lists:map(fun({Tid, _Tabs}) ->
+ Status = tr_status(Tid,Participant),
+ {Tid#tid.counter, Tid#tid.pid, Status}
+ end,Coordinator).
+
+tr_status(Tid,Participant) ->
+ case lists:keymember(Tid, 1, Participant) of
+ true -> participant;
+ false -> coordinator
+ end.
+
+get_info(Timeout) ->
+ case whereis(?MODULE) of
+ undefined ->
+ {timeout, Timeout};
+ Pid ->
+ Pid ! {self(), info},
+ receive
+ {?MODULE, _, {info, Part, Coord}} ->
+ {info, Part, Coord}
+ after Timeout ->
+ {timeout, Timeout}
+ end
+ end.
+
+display_info(Stream, {timeout, T}) ->
+ io:format(Stream, "---> No info about coordinator and participant transactions, "
+ "timeout ~p <--- ~n", [T]);
+
+display_info(Stream, {info, Part, Coord}) ->
+ io:format(Stream, "---> Participant transactions <--- ~n", []),
+ lists:foreach(fun(P) -> pr_participant(Stream, P) end, Part),
+ io:format(Stream, "---> Coordinator transactions <---~n", []),
+ lists:foreach(fun({Tid, _Tabs}) -> pr_tid(Stream, Tid) end, Coord).
+
+pr_participant(Stream, P) ->
+ Commit0 = P#participant.commit,
+ Commit =
+ if
+ binary(Commit0) -> binary_to_term(Commit0);
+ true -> Commit0
+ end,
+ pr_tid(Stream, P#participant.tid),
+ io:format(Stream, "with participant objects ~p~n", [Commit]).
+
+
+pr_tid(Stream, Tid) ->
+ io:format(Stream, "Tid: ~p (owned by ~p) ~n",
+ [Tid#tid.counter, Tid#tid.pid]).
+
+info(Serial) ->
+ io:format( "Info about transaction with serial == ~p~n", [Serial]),
+ {info, Participant, Trs} = req(info),
+ search_pr_participant(Serial, Participant),
+ search_pr_coordinator(Serial, Trs).
+
+
+search_pr_coordinator(_S, []) -> no;
+search_pr_coordinator(S, [{Tid, _Ts}|Tail]) ->
+ case Tid#tid.counter of
+ S ->
+ io:format( "Tid is coordinator, owner == \n", []),
+ display_pid_info(Tid#tid.pid),
+ search_pr_coordinator(S, Tail);
+ _ ->
+ search_pr_coordinator(S, Tail)
+ end.
+
+search_pr_participant(_S, []) ->
+ false;
+search_pr_participant(S, [ P | Tail]) ->
+ Tid = P#participant.tid,
+ Commit0 = P#participant.commit,
+ if
+ Tid#tid.counter == S ->
+ io:format( "Tid is participant to commit, owner == \n", []),
+ Pid = Tid#tid.pid,
+ display_pid_info(Pid),
+ io:format( "Tid wants to write objects \n",[]),
+ Commit =
+ if
+ binary(Commit0) -> binary_to_term(Commit0);
+ true -> Commit0
+ end,
+
+ io:format("~p~n", [Commit]),
+ search_pr_participant(S,Tail); %% !!!!!
+ true ->
+ search_pr_participant(S, Tail)
+ end.
+
+display_pid_info(Pid) ->
+ case rpc:pinfo(Pid) of
+ undefined ->
+ io:format( "Dead process \n");
+ Info ->
+ Call = fetch(initial_call, Info),
+ Curr = case fetch(current_function, Info) of
+ {Mod,F,Args} when list(Args) ->
+ {Mod,F,length(Args)};
+ Other ->
+ Other
+ end,
+ Reds = fetch(reductions, Info),
+ LM = length(fetch(messages, Info)),
+ pformat(io_lib:format("~p", [Pid]),
+ io_lib:format("~p", [Call]),
+ io_lib:format("~p", [Curr]), Reds, LM)
+ end.
+
+pformat(A1, A2, A3, A4, A5) ->
+ io:format( "~-12s ~-21s ~-21s ~9w ~4w~n", [A1,A2,A3,A4,A5]).
+
+fetch(Key, Info) ->
+ case lists:keysearch(Key, 1, Info) of
+ {value, {_, Val}} ->
+ Val;
+ _ ->
+ 0
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%% reconfigure stuff comes here ......
+%%%%%%%%%%%%%%%%%%%%%
+
+reconfigure_coordinators(N, [{Tid, [Store | _]} | Coordinators]) ->
+ case mnesia_recover:outcome(Tid, unknown) of
+ committed ->
+ WaitingNodes = ?ets_lookup(Store, waiting_for_commit_ack),
+ case lists:keymember(N, 2, WaitingNodes) of
+ false ->
+ ignore; % avoid spurious mnesia_down messages
+ true ->
+ send_mnesia_down(Tid, Store, N)
+ end;
+ aborted ->
+ ignore; % avoid spurious mnesia_down messages
+ _ ->
+ %% Tell the coordinator about the mnesia_down
+ send_mnesia_down(Tid, Store, N)
+ end,
+ reconfigure_coordinators(N, Coordinators);
+reconfigure_coordinators(_N, []) ->
+ ok.
+
+send_mnesia_down(Tid, Store, Node) ->
+ Msg = {mnesia_down, Node},
+ send_to_pids([Tid#tid.pid | get_friends(Store)], Msg).
+
+send_to_pids([Pid | Pids], Msg) ->
+ Pid ! Msg,
+ send_to_pids(Pids, Msg);
+send_to_pids([], _Msg) ->
+ ok.
+
+reconfigure_participants(N, [P | Tail]) ->
+ case lists:member(N, P#participant.disc_nodes) or
+ lists:member(N, P#participant.ram_nodes) of
+ false ->
+ %% Ignore, since we are not a participant
+ %% in the transaction.
+ reconfigure_participants(N, Tail);
+
+ true ->
+ %% We are on a participant node, lets
+ %% check if the dead one was a
+ %% participant or a coordinator.
+ Tid = P#participant.tid,
+ if
+ node(Tid#tid.pid) /= N ->
+ %% Another participant node died. Ignore.
+ reconfigure_participants(N, Tail);
+
+ true ->
+ %% The coordinator node has died and
+ %% we must determine the outcome of the
+ %% transaction and tell mnesia_tm on all
+ %% nodes (including the local node) about it
+ verbose("Coordinator ~p in transaction ~p died~n",
+ [Tid#tid.pid, Tid]),
+
+ Nodes = P#participant.disc_nodes ++
+ P#participant.ram_nodes,
+ AliveNodes = Nodes -- [N],
+ Protocol = P#participant.protocol,
+ tell_outcome(Tid, Protocol, N, AliveNodes, AliveNodes),
+ reconfigure_participants(N, Tail)
+ end
+ end;
+reconfigure_participants(_, []) ->
+ [].
+
+%% We need to determine the outcome of the transaction and
+%% tell mnesia_tm on all involved nodes (including the local node)
+%% about the outcome.
+tell_outcome(Tid, Protocol, Node, CheckNodes, TellNodes) ->
+ Outcome = mnesia_recover:what_happened(Tid, Protocol, CheckNodes),
+ case Outcome of
+ aborted ->
+ rpc:abcast(TellNodes, ?MODULE, {Tid,{do_abort, {mnesia_down, Node}}});
+ committed ->
+ rpc:abcast(TellNodes, ?MODULE, {Tid, do_commit})
+ end,
+ Outcome.
+
+do_stop(#state{coordinators = Coordinators}) ->
+ Msg = {mnesia_down, node()},
+ lists:foreach(fun({Tid, _}) -> Tid#tid.pid ! Msg end, Coordinators),
+ mnesia_checkpoint:stop(),
+ mnesia_log:stop(),
+ exit(shutdown).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% System upgrade
+
+system_continue(_Parent, _Debug, State) ->
+ doit_loop(State).
+
+system_terminate(_Reason, _Parent, _Debug, State) ->
+ do_stop(State).
+
+system_code_change(State, _Module, _OldVsn, _Extra) ->
+ {ok, State}.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE.erl b/lib/dialyzer/test/r9c_tests_SUITE.erl
deleted file mode 100644
index cd5bd5ec61..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE.erl
+++ /dev/null
@@ -1,64 +0,0 @@
-%% ATTENTION!
-%% This is an automatically generated file. Do not edit.
-%% Use './remake' script to refresh it if needed.
-%% All Dialyzer options should be defined in dialyzer_options
-%% file.
-
--module(r9c_tests_SUITE).
-
--include("ct.hrl").
--include("dialyzer_test_constants.hrl").
-
--export([suite/0, init_per_suite/0, init_per_suite/1,
- end_per_suite/1, all/0]).
--export([r9c_tests_SUITE_consistency/1, asn1/1, inets/1, mnesia/1]).
-
-suite() ->
- [{timetrap, {minutes, 20}}].
-
-init_per_suite() ->
- [{timetrap, ?plt_timeout}].
-init_per_suite(Config) ->
- OutDir = ?config(priv_dir, Config),
- case dialyzer_common:check_plt(OutDir) of
- fail -> {skip, "Plt creation/check failed."};
- ok -> [{dialyzer_options, [{defines,[{vsn,42}]}]}|Config]
- end.
-
-end_per_suite(_Config) ->
- ok.
-
-all() ->
- [r9c_tests_SUITE_consistency,asn1,inets,mnesia].
-
-dialyze(Config, TestCase) ->
- Opts = ?config(dialyzer_options, Config),
- Dir = ?config(data_dir, Config),
- OutDir = ?config(priv_dir, Config),
- dialyzer_common:check(TestCase, Opts, Dir, OutDir).
-
-r9c_tests_SUITE_consistency(Config) ->
- Dir = ?config(data_dir, Config),
- case dialyzer_common:new_tests(Dir, all()) of
- [] -> ok;
- New -> ct:fail({missing_tests,New})
- end.
-
-asn1(Config) ->
- case dialyze(Config, asn1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-inets(Config) ->
- case dialyze(Config, inets) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-mnesia(Config) ->
- case dialyze(Config, mnesia) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/results/asn1 b/lib/dialyzer/test/r9c_tests_SUITE_data/results/asn1
deleted file mode 100644
index ac83366bc8..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/results/asn1
+++ /dev/null
@@ -1,106 +0,0 @@
-
-asn1ct.erl:1500: The variable Err can never match since previous clauses completely covered the type #type{}
-asn1ct.erl:1596: The variable _ can never match since previous clauses completely covered the type 'ber_bin_v2'
-asn1ct.erl:1673: The pattern 'all' can never match the type 'asn1_module' | 'exclusive_decode' | 'partial_decode'
-asn1ct.erl:672: The pattern <{'false', Result}, _, _> can never match the type <{'true','true'},atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()],[any()]>
-asn1ct.erl:909: Guard test is_atom(Ext::[49 | 97 | 98 | 100 | 110 | 115]) can never succeed
-asn1ct_check.erl:1698: The pattern {'error', _} can never match the type [any()]
-asn1ct_check.erl:2733: The pattern {'type', Tag, _, _, _, _} can never match the type 'ASN1_OPEN_TYPE' | {_,_} | {'fixedtypevaluefield',_,_}
-asn1ct_check.erl:2738: The pattern <_S, _> can never match since previous clauses completely covered the type <#state{},#ObjectClassFieldType{class::#objectclass{fields::maybe_improper_list() | {_,_,_,_}},fieldname::{_,maybe_improper_list()},type::'ASN1_OPEN_TYPE' | {_,_} | {'fixedtypevaluefield',_,_}}>
-asn1ct_check.erl:2887: The variable Other can never match since previous clauses completely covered the type any()
-asn1ct_check.erl:3188: The pattern <_S, [], B> can never match the type <#state{},{'SingleValue',_},{'ValueRange',_}>
-asn1ct_check.erl:3190: The pattern <_S, A, []> can never match the type <#state{},{'SingleValue',_},{'ValueRange',_}>
-asn1ct_check.erl:3212: The pattern {[], C3} can never match the type {[any(),...],{'ValueRange',{'MIN','MAX'}}}
-asn1ct_check.erl:3225: The pattern {L1, UbNew} can never match the type 'false'
-asn1ct_check.erl:3228: The pattern {L1, LbNew} can never match the type 'false'
-asn1ct_check.erl:3235: The call asn1ct_check:remove_val_from_list(number(),L::[any(),...]) will never return since it differs in the 1st argument from the success typing arguments: ([any()],any())
-asn1ct_check.erl:3240: The call asn1ct_check:remove_val_from_list(number(),L::[any(),...]) will never return since it differs in the 1st argument from the success typing arguments: ([any()],any())
-asn1ct_check.erl:3242: Function remove_val_from_list/2 has no local return
-asn1ct_check.erl:3243: The call lists:member(Val::[any(),...],List::number()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),[any()])
-asn1ct_check.erl:3283: The pattern [] can never match the type [any(),...]
-asn1ct_check.erl:3362: The pattern <_, [], _VR> can never match the type <#state{},[any(),...],[any(),...]>
-asn1ct_check.erl:3364: The pattern <_, _SV, []> can never match the type <#state{},[any(),...],[any(),...]>
-asn1ct_check.erl:4150: The pattern <_, [_]> can never match the type <_,[]>
-asn1ct_check.erl:4314: The pattern <S, Type, {Rlist, ExtList}> can never match the type <#state{},_,[any()]>
-asn1ct_check.erl:4360: The pattern <S, Type, {Rlist, ExtList}> can never match the type <#state{},_,[any()]>
-asn1ct_check.erl:4719: The call asn1ct_check:error({'type',{'asn1',[1..255,...],[any(),...]}}) will never return since it differs in the 1st argument from the success typing arguments: ({'ObjectSet' | 'class' | 'export' | 'ptype' | 'type' | 'value',_,#state{}})
-asn1ct_check.erl:5120: Guard test is_record(Type::{_,_} | {'fixedtypevaluefield',_,_},'type',6) can never succeed
-asn1ct_check.erl:5128: Guard test is_record(Type::{_,_} | {'fixedtypevaluefield',_,_},'type',6) can never succeed
-asn1ct_check.erl:540: The pattern <_S, {'poc', _ObjSet, _Params}> can never match since previous clauses completely covered the type <#state{},_>
-asn1ct_check.erl:5517: The pattern <_, []> can never match the type <_,[{'ABSTRACT-SYNTAX',{_,_,_}} | {'TYPE-IDENTIFIER',{_,_,_}},...]>
-asn1ct_constructed_ber.erl:1075: The pattern {{{'ObjectClassFieldType', _, _, _, {'objectfield', PrimFieldName1, PFNList}}, _}, {'componentrelation', _, _}} can never match the type {#type{},_}
-asn1ct_constructed_ber.erl:695: The pattern {'EXTENSIONMARK', _, _} can never match the type #ComponentType{}
-asn1ct_constructed_ber.erl:748: The pattern <Erules, TopType, {CompList, _ExtList}> can never match the type <_,maybe_improper_list(),[#ComponentType{typespec::{_,_,_,_,_,_}}]>
-asn1ct_constructed_ber_bin_v2.erl:914: The pattern {{{'ObjectClassFieldType', _, _, _, {'objectfield', PrimFieldName1, PFNList}}, _}, {'componentrelation', _, _}} can never match the type {#type{},_}
-asn1ct_gen.erl:740: The pattern [] can never match the type [any(),...]
-asn1ct_gen_ber.erl:974: The pattern <Erules, [{Name, Def} | Rest]> can never match the type <_,[#typedef{name::atom(),typespec::{_,_,_,_,_,_}}]>
-asn1ct_gen_ber_bin_v2.erl:975: The pattern <Erules, [{Name, Def} | Rest]> can never match the type <_,[#typedef{name::atom(),typespec::{_,_,_,_,_,_}}]>
-asn1ct_gen_per.erl:646: The pattern <Erules, [{Name, Def} | Rest]> can never match the type <_,[#typedef{name::atom()}]>
-asn1ct_gen_per_rt2ct.erl:1189: The pattern <Erules, [{Name, Def} | Rest]> can never match the type <_,[#typedef{name::atom()}]>
-asn1ct_gen_per_rt2ct.erl:563: The pattern <C, ['EXT_MARK' | T], _Count> can never match the type <[{'ValueRange',{_,_}},...],[char() | {'asn1_enum',integer()},...],non_neg_integer()>
-asn1ct_gen_per_rt2ct.erl:580: The pattern <_C, 'EXT_MARK', _Count> can never match the type <[{'ValueRange',{_,_}},...],char(),non_neg_integer()>
-asn1ct_gen_per_rt2ct.erl:583: The pattern <_C, {1, EnumName}, Count> can never match the type <[{'ValueRange',{_,_}},...],char(),non_neg_integer()>
-asn1ct_gen_per_rt2ct.erl:587: The pattern <C, {0, EnumName}, Count> can never match the type <[{'ValueRange',{_,_}},...],char(),non_neg_integer()>
-asn1ct_gen_per_rt2ct.erl:656: The pattern <Type, C> can never match since previous clauses completely covered the type <'bitstring' | 'integer',_>
-asn1ct_parser2.erl:2017: Call to missing or unexported function ordsets:list_to_set/1
-asn1ct_parser2.erl:2497: The variable _ can never match since previous clauses completely covered the type 'ok'
-asn1ct_parser2.erl:2628: The pattern {Rlist, ExtList} can never match the type [{_,_,_},...]
-asn1ct_parser2.erl:2660: Call to missing or unexported function ordsets:list_to_set/1
-asn1ct_parser2.erl:2685: Call to missing or unexported function ordsets:list_to_set/1
-asn1ct_parser2.erl:281: The variable Other can never match since previous clauses completely covered the type [any()]
-asn1ct_parser2.erl:529: The variable _ can never match since previous clauses completely covered the type #constraint{}
-asn1ct_parser2.erl:555: The variable _ can never match since previous clauses completely covered the type #constraint{}
-asn1ct_parser2.erl:796: The variable _ can never match since previous clauses completely covered the type {_,_}
-asn1ct_parser2.erl:814: The variable _ can never match since previous clauses completely covered the type {_,_}
-asn1ct_parser2.erl:831: The variable _ can never match since previous clauses completely covered the type {_,_}
-asn1ct_value.erl:247: The pattern <'undefined', Default> can never match the type <maybe_improper_list(),[1..255,...]>
-asn1rt_ber_bin.erl:1125: Cons will produce an improper list since its 2nd argument is binary() | tuple()
-asn1rt_ber_bin.erl:1276: The pattern <{{_Min1, Max1}, {Min2, Max2}}, BitListVal, _DoTag> can never match since previous clauses completely covered the type <{_,_},maybe_improper_list(),_>
-asn1rt_ber_bin.erl:2057: The call asn1rt_ber_bin:check_if_valid_tag2('false',[],[],OptOrMand::any()) will never return since it differs in the 2nd argument from the success typing arguments: ('false' | {'APPLICATION',_} | {'CONTEXT',_} | {'PRIVATE',_} | {'UNIVERSAL',_},nonempty_maybe_improper_list(),[] | {_,_,_},any())
-asn1rt_ber_bin.erl:969: The pattern {Val01, Buffer01, Rb01} can never match the type {'MINUS-INFINITY' | 'PLUS-INFINITY' | 0,binary()}
-asn1rt_ber_bin.erl:998: The pattern {FirstLen, {Exp, Buffer3}, RemBytes2} can never match the type {1..1114111,{integer(),binary(),number()},number()}
-asn1rt_ber_bin_v2.erl:1230: The pattern <{{_Min1, Max1}, {Min2, Max2}}, BitListVal, TagIn> can never match since previous clauses completely covered the type <{_,_},maybe_improper_list(),_>
-asn1rt_ber_bin_v2.erl:328: The variable _ can never match since previous clauses completely covered the type {{0 | 1,non_neg_integer(),'indefinite' | non_neg_integer(),binary()},binary() | []}
-asn1rt_ber_bin_v2.erl:337: The variable _ can never match since previous clauses completely covered the type {{0 | 1,non_neg_integer(),'indefinite' | non_neg_integer(),binary()},binary() | []}
-asn1rt_ber_bin_v2.erl:392: The variable _ can never match since previous clauses completely covered the type {{0 | 1,non_neg_integer(),'indefinite' | non_neg_integer(),binary()},binary() | []}
-asn1rt_ber_bin_v2.erl:963: Function decode_real/3 has no local return
-asn1rt_check.erl:100: The variable _ can never match since previous clauses completely covered the type [any()]
-asn1rt_check.erl:85: The variable _ can never match since previous clauses completely covered the type [any()]
-asn1rt_driver_handler.erl:32: The pattern 'already_done' can never match the type {'error',_}
-asn1rt_per.erl:1065: The pattern {'BMPString', {'octets', Ol}} can never match the type {_,[{'bits',1 | 2 | 4 | 8 | 16 | 32,_}]}
-asn1rt_per.erl:1066: Function will never be called
-asn1rt_per.erl:1231: The call erlang:'not'('implemented') will never return since it differs in the 1st argument from the success typing arguments: (boolean())
-asn1rt_per.erl:1233: The call erlang:'not'('implemented') will never return since it differs in the 1st argument from the success typing arguments: (boolean())
-asn1rt_per.erl:1235: The call erlang:'not'('implemented') will never return since it differs in the 1st argument from the success typing arguments: (boolean())
-asn1rt_per.erl:1237: The call erlang:'not'('implemented') will never return since it differs in the 1st argument from the success typing arguments: (boolean())
-asn1rt_per.erl:989: The pattern <_C, 'true', _Val> can never match the type <_,'false',_>
-asn1rt_per_bin.erl:1361: The pattern <_, 'true', _> can never match the type <_,'false',_>
-asn1rt_per_bin.erl:1436: The pattern {'BMPString', {'octets', Ol}} can never match the type {'BMPString' | 'IA5String' | 'NumericString' | 'PrintableString' | 'UniversalString' | 'VisibleString',[{'bits',1 | 2 | 4 | 8 | 16 | 32,_}]}
-asn1rt_per_bin.erl:1437: Function will never be called
-asn1rt_per_bin.erl:161: The call asn1rt_per_bin:getbit({0,maybe_improper_list()}) will never return since it differs in the 1st argument from the success typing arguments: (<<_:8,_:_*8>> | {non_neg_integer(),<<_:1,_:_*1>>})
-asn1rt_per_bin.erl:1812: The pattern {Name, Val} can never match since previous clauses completely covered the type any()
-asn1rt_per_bin.erl:2106: Cons will produce an improper list since its 2nd argument is binary()
-asn1rt_per_bin.erl:2111: Cons will produce an improper list since its 2nd argument is binary()
-asn1rt_per_bin.erl:2111: Cons will produce an improper list since its 2nd argument is integer()
-asn1rt_per_bin.erl:2117: Cons will produce an improper list since its 2nd argument is integer()
-asn1rt_per_bin.erl:2121: Cons will produce an improper list since its 2nd argument is 0
-asn1rt_per_bin.erl:2123: Cons will produce an improper list since its 2nd argument is 0
-asn1rt_per_bin.erl:2127: Cons will produce an improper list since its 2nd argument is 0
-asn1rt_per_bin.erl:2129: Cons will produce an improper list since its 2nd argument is integer()
-asn1rt_per_bin.erl:446: The variable _ can never match since previous clauses completely covered the type integer()
-asn1rt_per_bin.erl:467: The variable _ can never match since previous clauses completely covered the type integer()
-asn1rt_per_bin.erl:474: The pattern <{_N, <<_:8/integer-unit:1,Bs/binary-unit:8>>}, C> can never match since previous clauses completely covered the type <{0,_},integer()>
-asn1rt_per_bin.erl:487: The variable _ can never match since previous clauses completely covered the type integer()
-asn1rt_per_bin.erl:498: The variable _ can never match since previous clauses completely covered the type integer()
-asn1rt_per_bin_rt2ct.erl:152: The call asn1rt_per_bin_rt2ct:getbit({0,maybe_improper_list()}) will never return since it differs in the 1st argument from the success typing arguments: (<<_:8,_:_*8>> | {non_neg_integer(),<<_:1,_:_*1>>})
-asn1rt_per_bin_rt2ct.erl:1533: The pattern {'BMPString', {'octets', Ol}} can never match the type {_,[[any(),...]]}
-asn1rt_per_bin_rt2ct.erl:1534: Function will never be called
-asn1rt_per_bin_rt2ct.erl:1875: The pattern {Name, Val} can never match since previous clauses completely covered the type any()
-asn1rt_per_bin_rt2ct.erl:443: The variable _ can never match since previous clauses completely covered the type integer()
-asn1rt_per_bin_rt2ct.erl:464: The variable _ can never match since previous clauses completely covered the type integer()
-asn1rt_per_bin_rt2ct.erl:471: The pattern <{_N, <<_B:8/integer-unit:1,Bs/binary-unit:8>>}, C> can never match since previous clauses completely covered the type <{0,_},integer()>
-asn1rt_per_bin_rt2ct.erl:484: The variable _ can never match since previous clauses completely covered the type integer()
-asn1rt_per_bin_rt2ct.erl:495: The variable _ can never match since previous clauses completely covered the type integer()
-asn1rt_per_v1.erl:1209: The pattern <_, 'true', _> can never match the type <_,'false',_>
-asn1rt_per_v1.erl:1290: The pattern {'BMPString', {'octets', Ol}} can never match the type {'BMPString' | 'IA5String' | 'NumericString' | 'PrintableString' | 'UniversalString' | 'VisibleString',[{'bits',1 | 2 | 4 | 8 | 16 | 32,_}]}
-asn1rt_per_v1.erl:1291: Function will never be called
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/results/inets b/lib/dialyzer/test/r9c_tests_SUITE_data/results/inets
deleted file mode 100644
index fd5e36a3cd..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/results/inets
+++ /dev/null
@@ -1,59 +0,0 @@
-
-ftp.erl:1243: The pattern {'ok', {N, Bytes}} can never match the type 'eof' | {'error',atom()} | {'ok',binary() | string()}
-ftp.erl:640: The pattern {'closed', _Why} can never match the type 'perm_fname_not_allowed' | 'perm_neg_compl' | 'perm_no_space' | 'pos_compl' | 'pos_interm' | 'pos_interm_acct' | 'trans_neg_compl' | 'trans_no_space' | {'error' | 'perm_fname_not_allowed' | 'perm_neg_compl' | 'perm_no_space' | 'pos_compl' | 'pos_interm' | 'pos_interm_acct' | 'pos_prel' | 'trans_neg_compl' | 'trans_no_space',atom() | [any()] | {'invalid_server_response',[any(),...]}}
-http.erl:117: The pattern {'error', Reason} can never match the type #req_headers{connection::[45 | 97 | 101 | 105 | 107 | 108 | 112 | 118,...],content_length::[48,...],other::[{_,_}]}
-http.erl:138: Function close_session/2 will never be called
-http_lib.erl:286: The call http_lib:close('ip_comm' | {'ssl',_},any()) will never return since it differs in the 1st argument from the success typing arguments: ('http' | 'https',any())
-http_lib.erl:424: The variable _ can never match since previous clauses completely covered the type any()
-http_lib.erl:438: The variable _ can never match since previous clauses completely covered the type any()
-http_lib.erl:99: Function getHeaderValue/2 will never be called
-httpc_handler.erl:322: Function status_continue/2 has no local return
-httpc_handler.erl:37: Function init_connection/2 has no local return
-httpc_handler.erl:65: Function next_response_with_request/2 has no local return
-httpc_handler.erl:660: Function exit_session_ok/2 has no local return
-httpc_manager.erl:145: The pattern {ErrorReply, State2} can never match the type {{'ok',number()},number(),#state{reqid::number()}}
-httpc_manager.erl:160: The pattern {ErrorReply, State2} can never match the type {{'ok',number()},number(),#state{reqid::number()}}
-httpc_manager.erl:478: The pattern {'error', Reason} can never match the type 'ok' | {number(),#session{clientclose::boolean(),pipeline::[],quelength::1}}
-httpc_manager.erl:490: The pattern {'error', Reason} can never match the type 'ok' | {number(),#session{clientclose::boolean(),pipeline::[],quelength::1}}
-httpd.erl:583: The pattern <{'error', Reason}, _Fd, SoFar> can never match the type <[any()],pid(),[[any(),...]]>
-httpd_acceptor.erl:105: The pattern {'error', Reason} can never match the type {'ok',pid()}
-httpd_acceptor.erl:110: Function handle_connection_err/4 will never be called
-httpd_acceptor.erl:168: Function report_error/2 will never be called
-httpd_acceptor.erl:91: The call httpd_acceptor:handle_error({'EXIT',_},ConfigDb::any(),SocketType::any()) will never return since it differs in the 1st argument from the success typing arguments: ('econnaborted' | 'emfile' | 'esslaccept' | 'timeout' | {'enfile',_},any(),any())
-httpd_manager.erl:885: The pattern {'EXIT', Reason} can never match since previous clauses completely covered the type any()
-httpd_manager.erl:919: Function auth_status/1 will never be called
-httpd_manager.erl:926: Function sec_status/1 will never be called
-httpd_manager.erl:933: Function acceptor_status/1 will never be called
-httpd_request_handler.erl:374: The call httpd_response:send_status(Info::#mod{parsed_header::maybe_improper_list()},417,[32 | 66 | 98 | 100 | 103 | 105 | 111 | 116 | 121,...]) will never return since it differs in the 2nd argument from the success typing arguments: (#mod{socket_type::'ip_comm' | {'ssl',_}},100 | 301 | 304 | 400 | 401 | 403 | 404 | 412 | 414 | 416 | 500 | 501 | 503,any())
-httpd_request_handler.erl:378: The call httpd_response:send_status(Info::#mod{parsed_header::maybe_improper_list()},417,[32 | 77 | 97 | 100 | 101 | 104 | 108 | 110 | 111 | 116 | 119,...]) will never return since it differs in the 2nd argument from the success typing arguments: (#mod{socket_type::'ip_comm' | {'ssl',_}},100 | 301 | 304 | 400 | 401 | 403 | 404 | 412 | 414 | 416 | 500 | 501 | 503,any())
-httpd_request_handler.erl:401: The call httpd_response:send_status(Info::#mod{parsed_header::maybe_improper_list()},417,[32 | 77 | 97 | 100 | 101 | 104 | 108 | 110 | 111 | 116 | 119,...]) will never return since it differs in the 2nd argument from the success typing arguments: (#mod{socket_type::'ip_comm' | {'ssl',_}},100 | 301 | 304 | 400 | 401 | 403 | 404 | 412 | 414 | 416 | 500 | 501 | 503,any())
-httpd_request_handler.erl:644: The call lists:reverse(Fields0::{'error',_} | {'ok',[[any()]]}) will never return since it differs in the 1st argument from the success typing arguments: ([any()])
-httpd_request_handler.erl:645: Function will never be called
-httpd_sup.erl:63: The variable Else can never match since previous clauses completely covered the type {'error',_} | {'ok',[any()],_,_}
-httpd_sup.erl:88: The pattern {'error', Reason} can never match the type {'ok',_,_}
-httpd_sup.erl:92: The variable Else can never match since previous clauses completely covered the type {'ok',_,_}
-mod_auth.erl:559: The pattern {'error', Reason} can never match the type {_,integer(),maybe_improper_list(),_}
-mod_auth_dets.erl:120: The call lists:foreach(fun((_) -> 'true' | {'error','no_such_group' | 'no_such_group_member'}),{'ok',[any()]}) will never return since it differs in the 2nd argument from the success typing arguments: (fun((_) -> any()),[any()])
-mod_auth_plain.erl:100: The variable _ can never match since previous clauses completely covered the type {'ok',[any()]}
-mod_auth_plain.erl:159: The variable _ can never match since previous clauses completely covered the type [any()]
-mod_auth_plain.erl:83: The variable O can never match since previous clauses completely covered the type [any()]
-mod_cgi.erl:372: The pattern {'http_response', NewAccResponse} can never match the type 'ok'
-mod_dir.erl:101: The call lists:flatten(nonempty_improper_list(atom() | binary() | [any()] | char(),atom())) will never return since it differs in the 1st argument from the success typing arguments: ([any()])
-mod_dir.erl:72: The pattern {'error', Reason} can never match the type {'ok',[[[any()] | char()],...]}
-mod_get.erl:135: The pattern <{'enfile', _}, _Info, Path> can never match the type <atom(),#mod{},atom() | binary() | [atom() | binary() | [any()] | char()]>
-mod_head.erl:80: The pattern <{'enfile', _}, _Info, Path> can never match the type <atom(),#mod{},atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]>
-mod_htaccess.erl:460: The pattern {'error', BadData} can never match the type {'ok',_}
-mod_include.erl:193: The pattern {_, Name, {[], []}} can never match the type {[any()],[any()],maybe_improper_list()}
-mod_include.erl:195: The pattern {_, Name, {PathInfo, []}} can never match the type {[any()],[any()],maybe_improper_list()}
-mod_include.erl:197: The pattern {_, Name, {PathInfo, QueryString}} can never match the type {[any()],[any()],maybe_improper_list()}
-mod_include.erl:201: The variable Gurka can never match since previous clauses completely covered the type {[any()],[any()],maybe_improper_list()}
-mod_include.erl:692: The pattern <{'read', Reason}, Info, Path> can never match the type <{'open',atom()},#mod{},atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]>
-mod_include.erl:706: The pattern <{'enfile', _}, _Info, Path> can never match the type <atom(),#mod{},atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]>
-mod_include.erl:716: Function read_error/3 will never be called
-mod_include.erl:719: Function read_error/4 will never be called
-mod_security_server.erl:386: The variable O can never match since previous clauses completely covered the type [any()]
-mod_security_server.erl:433: The variable Other can never match since previous clauses completely covered the type [any()]
-mod_security_server.erl:585: The variable _ can never match since previous clauses completely covered the type [any()]
-mod_security_server.erl:608: The variable _ can never match since previous clauses completely covered the type [any()]
-mod_security_server.erl:641: The variable _ can never match since previous clauses completely covered the type [any()]
-uri.erl:146: The pattern {'error', Error} can never match since previous clauses completely covered the type {_,{[],[]}}
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/results/mnesia b/lib/dialyzer/test/r9c_tests_SUITE_data/results/mnesia
deleted file mode 100644
index e199581a0e..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/results/mnesia
+++ /dev/null
@@ -1,34 +0,0 @@
-
-mnesia.erl:1319: Guard test size(Spec::[{_,_,_},...]) can never succeed
-mnesia.erl:1498: The call mnesia:bad_info_reply(Tab::atom(),Item::'type') will never return since it differs in the 2nd argument from the success typing arguments: (atom(),'memory' | 'size')
-mnesia.erl:331: Function mod2abs/1 has no local return
-mnesia_bup.erl:111: The created fun has no local return
-mnesia_bup.erl:574: Function fallback_receiver/2 has no local return
-mnesia_bup.erl:967: Function uninstall_fallback_master/2 has no local return
-mnesia_checkpoint.erl:1014: The variable Error can never match since previous clauses completely covered the type {'ok',#checkpoint_args{nodes::[any()],retainers::[any(),...]}}
-mnesia_controller.erl:1666: The variable Tab can never match since previous clauses completely covered the type [any()]
-mnesia_controller.erl:1679: The pattern {'stop', Reason, Reply, State2} can never match the type {'noreply',_} | {'reply',_,_} | {'stop','shutdown',#state{}}
-mnesia_controller.erl:1685: The pattern {'noreply', State2, _Timeout} can never match the type {'reply',_,_}
-mnesia_event.erl:77: The pattern 'remove_handler' can never match the type {'ok',_}
-mnesia_event.erl:79: The pattern {'swap_handler', Args1, State1, Mod2, Args2} can never match the type {'ok',_}
-mnesia_frag.erl:294: The call mnesia_frag:remote_collect(Ref::reference(),{'error',_},[],OldSelectFun::fun(() -> [any()])) will never return since it differs in the 2nd argument from the success typing arguments: (reference(),'ok',[any()],fun(() -> [any()]))
-mnesia_frag.erl:304: The call mnesia_frag:remote_collect(Ref::reference(),{'error',{'node_not_running',_}},[],OldSelectFun::fun(() -> [any()])) will never return since it differs in the 2nd argument from the success typing arguments: (reference(),'ok',[any()],fun(() -> [any()]))
-mnesia_frag.erl:312: The call mnesia_frag:remote_collect(Ref::reference(),LocalRes::{'error',_},[],OldSelectFun::fun(() -> [any()])) will never return since it differs in the 2nd argument from the success typing arguments: (reference(),'ok',[any()],fun(() -> [any()]))
-mnesia_index.erl:52: The call mnesia_lib:other_val(Var::{_,'commit_work' | 'index' | 'setorbag' | 'storage_type' | {'index',_}},_ReASoN_::any()) will never return since it differs in the 1st argument from the success typing arguments: ({_,'active_replicas' | 'where_to_read' | 'where_to_write'},any())
-mnesia_lib.erl:957: The pattern {'ok', {0, _}} can never match the type 'eof' | {'error',atom()} | {'ok',binary() | string()}
-mnesia_lib.erl:959: The pattern {'ok', {_, Bin}} can never match the type 'eof' | {'error',atom()} | {'ok',binary() | string()}
-mnesia_loader.erl:36: The call mnesia_lib:other_val(Var::{_,'access_mode' | 'cstruct' | 'db_nodes' | 'setorbag' | 'snmp' | 'storage_type'},Reason::any()) will never return since it differs in the 1st argument from the success typing arguments: ({_,'active_replicas' | 'where_to_read' | 'where_to_write'},any())
-mnesia_locker.erl:1017: Function system_terminate/4 has no local return
-mnesia_log.erl:707: The test {'error',{[1..255,...],[any(),...]}} | {'ok',_} == atom() can never evaluate to 'true'
-mnesia_log.erl:727: The created fun has no local return
-mnesia_monitor.erl:162: The pattern <[], []> can never match the type <[any(),...],[any(),...]>
-mnesia_monitor.erl:354: The pattern {'error', Reason} can never match the type 'ok'
-mnesia_recover.erl:159: The call mnesia_lib:other_val(Var::'latest_transient_decision' | 'max_wait_for_decision' | 'previous_transient_decisions' | 'recover_nodes',Reason::any()) will never return since it differs in the 1st argument from the success typing arguments: ({_,'active_replicas' | 'where_to_read' | 'where_to_write'},any())
-mnesia_recover.erl:884: The pattern {'stop', Reason, Reply, State2} can never match the type {'noreply',_} | {'stop','shutdown',#state{}}
-mnesia_schema.erl:1088: Guard test Storage::'disc_copies' | 'disc_only_copies' | 'ram_copies' == 'unknown' can never succeed
-mnesia_schema.erl:1258: Guard test FromS::'disc_copies' | 'disc_only_copies' | 'ram_copies' == 'unknown' can never succeed
-mnesia_schema.erl:1639: The pattern {'false', 'mandatory'} can never match the type {'false','optional'}
-mnesia_schema.erl:2434: The variable Reason can never match since previous clauses completely covered the type {'error',_} | {'ok',_}
-mnesia_schema.erl:451: Guard test UseDirAnyway::'false' == 'true' can never succeed
-mnesia_tm.erl:1522: Function commit_participant/5 has no local return
-mnesia_tm.erl:2169: Function system_terminate/4 has no local return
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/Makefile b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/Makefile
deleted file mode 100644
index b539e88108..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/Makefile
+++ /dev/null
@@ -1,151 +0,0 @@
-#
-# Copyright (C) 1997, Ericsson Telecommunications
-# Author: Kenneth Lundin
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(ASN1_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/asn1-$(VSN)
-
-
-
-
-#
-# Common Macros
-#
-# PARSER_SRC = \
-# asn1ct_parser.yrl
-
-# PARSER_MODULE=$(PARSER_SRC:%.yrl=%)
-
-EBIN = ../ebin
-CT_MODULES= \
- asn1ct \
- asn1ct_check \
- asn1_db \
- asn1ct_pretty_format \
- asn1ct_gen \
- asn1ct_gen_per \
- asn1ct_gen_per_rt2ct \
- asn1ct_name \
- asn1ct_constructed_per \
- asn1ct_constructed_ber \
- asn1ct_gen_ber \
- asn1ct_constructed_ber_bin_v2 \
- asn1ct_gen_ber_bin_v2 \
- asn1ct_value \
- asn1ct_tok \
- asn1ct_parser2
-
-RT_MODULES= \
- asn1rt \
- asn1rt_per \
- asn1rt_per_bin \
- asn1rt_per_v1 \
- asn1rt_ber_bin \
- asn1rt_ber_bin_v2 \
- asn1rt_per_bin_rt2ct \
- asn1rt_driver_handler \
- asn1rt_check
-
-# asn1rt_ber_v1 \
-# asn1rt_ber \
-# the rt module to use is defined in asn1_records.hrl
-# and must be updated when an incompatible change is done in the rt modules
-
-
-MODULES= $(CT_MODULES) $(RT_MODULES)
-
-ERL_FILES = $(MODULES:%=%.erl)
-
-TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-GENERATED_PARSER = $(PARSER_MODULE:%=%.erl)
-
-# internal hrl file
-HRL_FILES = asn1_records.hrl
-
-APP_FILE = asn1.app
-APPUP_FILE = asn1.appup
-
-APP_SRC = $(APP_FILE).src
-APP_TARGET = $(EBIN)/$(APP_FILE)
-
-APPUP_SRC = $(APPUP_FILE).src
-APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
-
-EXAMPLES = \
- ../examples/P-Record.asn
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_FLAGS +=
-ERL_COMPILE_FLAGS += \
- -I$(ERL_TOP)/lib/stdlib \
- +warn_unused_vars
-YRL_FLAGS =
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
-
-
-clean:
- rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(GENERATED_PARSER)
- rm -f core *~
-
-docs:
-
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-$(EBIN)/asn1ct.$(EMULATOR):asn1ct.erl
- $(ERLC) -b$(EMULATOR) -o$(EBIN) $(ERL_COMPILE_FLAGS) -Dvsn=\"$(VSN)\" $<
-
-$(APP_TARGET): $(APP_SRC) ../vsn.mk
- sed -e 's;%VSN%;$(VSN);' $< > $@
-
-$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
- sed -e 's;%VSN%;$(VSN);' $< > $@
-
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(RELSYSDIR)/ebin
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(PARSER_SRC) $(ERL_FILES) $(HRL_FILES) $(APP_SRC) $(APPUP_SRC) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/examples
- $(INSTALL_DATA) $(EXAMPLES) $(RELSYSDIR)/examples
-
-# there are no include files to be used by the user
-#$(INSTALL_DIR) $(RELSYSDIR)/include
-#$(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include
-
-release_docs_spec:
-
-
-
-
-
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/Restrictions.txt b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/Restrictions.txt
deleted file mode 100644
index 73b725245d..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/Restrictions.txt
+++ /dev/null
@@ -1,55 +0,0 @@
-The following restrictions apply to this implementation of the ASN.1 compiler:
-
-Supported encoding rules are:
-BER
-PER (aligned)
-
-PER (unaligned) IS NOT SUPPORTED
-
-Supported types are:
-
-INTEGER
-BOOLEAN
-ENUMERATION
-SEQUENCE
-SEQUENCE OF
-SET
-SET OF
-CHOICE
-OBJECT IDENTIFIER
-RestrictedCharacterStringTypes
-UnrestrictedCharacterStringTypes
-
-
-NOT SUPPORTED types are:
-ANY IS (IS NOT IN THE STANDARD ANY MORE)
-ANY DEFINED BY (IS NOT IN THE STANDARD ANY MORE)
-EXTERNAL
-EMBEDDED-PDV
-REAL
-
-The support for value definitions in the ASN.1 notation is very limited.
-
-The support for constraints is limited to:
-SizeConstraint SIZE(X)
-SingleValue (1)
-ValueRange (X..Y)
-PermittedAlpabet FROM
-
-The only supported value-notation for SEQUENCE and SET in Erlang is
-the record variant.
-The list notation with named components used by the old ASN.1 compiler
-was supported in the first versions of this compiler both are no longer
-supported.
-
-The decode functions always return a symbolic value if they can.
-
-
-Files with ASN.1 source must have a suffix .asn1 the suffix .py used by the
-old ASN.1 compiler is supported in this version but will not be supported in the future.
-
-Generated files:
-X.asn1db % the intermediate format of a compiled ASN.1 module
-X.hrl % generated Erlang include file for module X
-X.erl % generated Erlang module with encode decode functions for
- % ASN.1 module X
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1.appup.src b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1.appup.src
deleted file mode 100644
index 255dec709e..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1.appup.src
+++ /dev/null
@@ -1,166 +0,0 @@
-{"%VSN%",
- [
- {"1.3",
- [
- {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {add_module, asn1rt_per_bin},
- {add_module, asn1rt_check}
- {add_module, asn1rt_per_bin_rt2ct},
- {add_module, asn1rt_ber_bin_v2},
- {add_module, asn1rt_driver_handler}
- {remove, {asn1rt_ber_v1, soft_purge, soft_purge}},
- ]
- },
- {"1.3.1",
- [
- {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {add_module, asn1rt_per_bin},
- {add_module, asn1rt_check}
- {add_module, asn1rt_per_bin_rt2ct},
- {add_module, asn1rt_ber_bin_v2},
- {add_module, asn1rt_driver_handler}
- {remove, {asn1rt_ber_v1, soft_purge, soft_purge}},
- ]
- },
- {"1.3.1.1",
- [
- {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {add_module, asn1rt_per_bin},
- {add_module, asn1rt_check}
- {add_module, asn1rt_per_bin_rt2ct},
- {add_module, asn1rt_ber_bin_v2},
- {add_module, asn1rt_driver_handler}
- {remove, {asn1rt_ber_v1, soft_purge, soft_purge}},
- ]
- },
- {"1.3.2",
- [
- {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_check, soft_purge, soft_purge, []},
- {add_module, asn1rt_per_bin_rt2ct},
- {add_module, asn1rt_ber_bin_v2},
- {add_module, asn1rt_driver_handler}
- {remove, {asn1rt_ber_v1, soft_purge, soft_purge}},
- ]
- },
- {"1.3.3",
- [
- {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_check, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []},
- {add_module, asn1rt_ber_bin_v2},
- {add_module, asn1rt_driver_handler}
- {remove, {asn1rt_ber_v1, soft_purge, soft_purge}},
- ]
- },
- {"1.3.3.1",
- [
- {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_check, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []},
- {add_module, asn1rt_ber_bin_v2},
- {add_module, asn1rt_driver_handler}
- {remove, {asn1rt_ber_v1, soft_purge, soft_purge}},
- ]
- }
- ],
- [
- {"1.3",
- [
- {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {add_module, asn1rt_ber_v1},
- {remove, {asn1rt_per_bin, soft_purge, soft_purge}},
- {remove, {asn1rt_check, soft_purge, soft_purge}}
- {remove, {asn1rt_per_bin_rt2ct, soft_purge, soft_purge}},
- {remove, {asn1rt_ber_bin_v2, soft_purge, soft_purge}},
- {remove, {asn1rt_driver_handler, soft_purge, soft_purge}}
- ]
- },
- {"1.3.1",
- [
- {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {add_module, asn1rt_ber_v1},
- {remove, {asn1rt_per_bin, soft_purge, soft_purge}},
- {remove, {asn1rt_check, soft_purge, soft_purge}}
- {remove, {asn1rt_per_bin_rt2ct, soft_purge, soft_purge}},
- {remove, {asn1rt_ber_bin_v2, soft_purge, soft_purge}},
- {remove, {asn1rt_driver_handler, soft_purge, soft_purge}}
- ]
- },
- {"1.3.1.1",
- [
- {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {add_module, asn1rt_ber_v1},
- {remove, {asn1rt_per_bin, soft_purge, soft_purge}},
- {remove, {asn1rt_check, soft_purge, soft_purge}}
- {remove, {asn1rt_per_bin_rt2ct, soft_purge, soft_purge}},
- {remove, {asn1rt_ber_bin_v2, soft_purge, soft_purge}},
- {remove, {asn1rt_driver_handler, soft_purge, soft_purge}}
- ]
- },
- {"1.3.2",
- [
- {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_check, soft_purge, soft_purge, []},
- {add_module, asn1rt_ber_v1},
- {remove, {asn1rt_per_bin_rt2ct, soft_purge, soft_purge}},
- {remove, {asn1rt_ber_bin_v2, soft_purge, soft_purge}},
- {remove, {asn1rt_driver_handler, soft_purge, soft_purge}}
- ]
- },
- {"1.3.3",
- [
- {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_check, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []},
- {add_module, asn1rt_ber_v1},
- {remove, {asn1rt_ber_bin_v2, soft_purge, soft_purge}},
- {remove, {asn1rt_driver_handler, soft_purge, soft_purge}}
- ]
- },
- {"1.3.3.1",
- [
- {load_module, asn1rt_per_v1, soft_purge, soft_purge, []},
- {load_module, asn1rt_ber_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin, soft_purge, soft_purge, []},
- {load_module, asn1rt_check, soft_purge, soft_purge, []},
- {load_module, asn1rt_per_bin_rt2ct, soft_purge, soft_purge, []},
- {add_module, asn1rt_ber_v1},
- {remove, {asn1rt_ber_bin_v2, soft_purge, soft_purge}},
- {remove, {asn1rt_driver_handler, soft_purge, soft_purge}}
- ]
- }
-
- ]}.
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1_db.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1_db.erl
deleted file mode 100644
index cf01e39fed..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1_db.erl
+++ /dev/null
@@ -1,162 +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: asn1_db.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
-%%
--module(asn1_db).
-%-compile(export_all).
--export([dbnew/1,dbsave/2,dbload/1,dbput/3,dbget/2,dbget_all/1]).
--export([dbget_all_mod/1,dbstop/0,dbclear/0,dberase_module/1,dbstart/1,stop_server/1]).
-%% internal exports
--export([dbloop0/1,dbloop/2]).
-
-%% Db stuff
-dbstart(Includes) ->
- start_server(asn1db, asn1_db, dbloop0, [Includes]).
-
-dbloop0(Includes) ->
- dbloop(Includes, ets:new(asn1, [set,named_table])).
-
-opentab(Tab,Mod,[]) ->
- opentab(Tab,Mod,["."]);
-opentab(Tab,Mod,Includes) ->
- Base = lists:concat([Mod,".asn1db"]),
- opentab2(Tab,Base,Mod,Includes,ok).
-
-opentab2(_Tab,_Base,_Mod,[],Error) ->
- Error;
-opentab2(Tab,Base,Mod,[Ih|It],_Error) ->
- File = filename:join(Ih,Base),
- case ets:file2tab(File) of
- {ok,Modtab} ->
- ets:insert(Tab,{Mod, Modtab}),
- {ok,Modtab};
- NewErr ->
- opentab2(Tab,Base,Mod,It,NewErr)
- end.
-
-
-dbloop(Includes, Tab) ->
- receive
- {From,{set, Mod, K2, V}} ->
- [{_,Modtab}] = ets:lookup(Tab,Mod),
- ets:insert(Modtab,{K2, V}),
- From ! {asn1db, ok},
- dbloop(Includes, Tab);
- {From, {get, Mod, K2}} ->
- Result = case ets:lookup(Tab,Mod) of
- [] ->
- opentab(Tab,Mod,Includes);
- [{_,Modtab}] -> {ok,Modtab}
- end,
- case Result of
- {ok,Newtab} ->
- From ! {asn1db, lookup(Newtab, K2)};
- _Error ->
- From ! {asn1db, undefined}
- end,
- dbloop(Includes, Tab);
- {From, {all_mod, Mod}} ->
- [{_,Modtab}] = ets:lookup(Tab,Mod),
- From ! {asn1db, ets:tab2list(Modtab)},
- dbloop(Includes, Tab);
- {From, {delete_mod, Mod}} ->
- [{_,Modtab}] = ets:lookup(Tab,Mod),
- ets:delete(Modtab),
- ets:delete(Tab,Mod),
- From ! {asn1db, ok},
- dbloop(Includes, Tab);
- {From, {save, OutFile,Mod}} ->
- [{_,Mtab}] = ets:lookup(Tab,Mod),
- {From ! {asn1db, ets:tab2file(Mtab,OutFile)}},
- dbloop(Includes,Tab);
- {From, {load, Mod}} ->
- Result = case ets:lookup(Tab,Mod) of
- [] ->
- opentab(Tab,Mod,Includes);
- [{_,Modtab}] -> {ok,Modtab}
- end,
- {From, {asn1db,Result}},
- dbloop(Includes,Tab);
- {From, {new, Mod}} ->
- case ets:lookup(Tab,Mod) of
- [{_,Modtab}] ->
- ets:delete(Modtab);
- _ ->
- true
- end,
- Tabname = list_to_atom(lists:concat(["asn1_",Mod])),
- ets:new(Tabname, [set,named_table]),
- ets:insert(Tab,{Mod,Tabname}),
- From ! {asn1db, ok},
- dbloop(Includes,Tab);
- {From, stop} ->
- From ! {asn1db, ok}; %% nothing to store
- {From, clear} ->
- ModTabList = [Mt||{_,Mt} <- ets:tab2list(Tab)],
- lists:foreach(fun(T) -> ets:delete(T) end,ModTabList),
- ets:delete(Tab),
- From ! {asn1db, cleared},
- dbloop(Includes, ets:new(asn1, [set]))
- end.
-
-
-%%all(Tab, K) ->
-%% pickup(K, ets:match(Tab, {{K, '$1'}, '$2'})).
-%%pickup(K, []) -> [];
-%%pickup(K, [[V1,V2] |T]) ->
-%% [{{K,V1},V2} | pickup(K, T)].
-
-lookup(Tab, K) ->
- case ets:lookup(Tab, K) of
- [] -> undefined;
- [{K,V}] -> V
- end.
-
-
-dbnew(Module) -> req({new,Module}).
-dbsave(OutFile,Module) -> req({save,OutFile,Module}).
-dbload(Module) -> req({load,Module}).
-
-dbput(Module,K,V) -> req({set, Module, K, V}).
-dbget(Module,K) -> req({get, Module, K}).
-dbget_all(K) -> req({get_all, K}).
-dbget_all_mod(Mod) -> req({all_mod,Mod}).
-dbstop() -> stop_server(asn1db).
-dbclear() -> req(clear).
-dberase_module({module,M})->
- req({delete_mod, M}).
-
-req(R) ->
- asn1db ! {self(), R},
- receive {asn1db, Reply} -> Reply end.
-
-stop_server(Name) ->
- stop_server(Name, whereis(Name)).
-stop_server(_, undefined) -> stopped;
-stop_server(Name, _Pid) ->
- Name ! {self(), stop},
- receive {Name, _} -> stopped end.
-
-
-start_server(Name,Mod,Fun,Args) ->
- case whereis(Name) of
- undefined ->
- register(Name, spawn(Mod,Fun, Args));
- _Pid ->
- already_started
- end.
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1_records.hrl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1_records.hrl
deleted file mode 100644
index 07ca8cccf3..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1_records.hrl
+++ /dev/null
@@ -1,96 +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: asn1_records.hrl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
-%%
--define('RT_BER',"asn1rt_ber_v1").
--define('RT_BER_BIN',"asn1rt_ber_bin").
--define('RT_PER',"asn1rt_per_v1").
-%% change to this when we have this module -define('RT_PER_BIN',"asn1rt_per_bin").
--define('RT_PER_BIN',"asn1rt_per_bin").
-
--record(module,{pos,name,defid,tagdefault='EXPLICIT',exports={exports,[]},imports={imports,[]}, extensiondefault=empty,typeorval}).
-
--record('SEQUENCE',{pname=false,tablecinf=false,components=[]}).
--record('SET',{pname=false,sorted=false,tablecinf=false,components=[]}).
--record('ComponentType',{pos,name,typespec,prop,tags}).
--record('ObjectClassFieldType',{classname,class,fieldname,type}).
-
--record(typedef,{checked=false,pos,name,typespec}).
--record(classdef,{checked=false,pos,name,typespec}).
--record(valuedef,{checked=false,pos,name,type,value}).
--record(ptypedef,{checked=false,pos,name,args,typespec}).
--record(pvaluedef,{checked=false,pos,name,args,type,value}).
--record(pvaluesetdef,{checked=false,pos,name,args,type,valueset}).
--record(pobjectdef,{checked=false,pos,name,args,class,def}).
--record(pobjectsetdef,{checked=false,pos,name,args,class,def}).
-
--record(typereference,{pos,val}).
--record(identifier,{pos,val}).
--record(constraint,{c,e}).
--record('Constraint',{'SingleValue'=no,'SizeConstraint'=no,'ValueRange'=no,'PermittedAlphabet'=no,
- 'ContainedSubtype'=no, 'TypeConstraint'=no,'InnerSubtyping'=no,e=no,'Other'=no}).
--record(simpletableattributes,{objectsetname,c_name,c_index,usedclassfield,
- uniqueclassfield,valueindex}).
--record(type,{tag=[],def,constraint=[],tablecinf=[],inlined=no}).
-
--record(objectclass,{fields=[],syntax}).
--record('Object',{classname,gen=true,def}).
--record('ObjectSet',{class,gen=true,uniquefname,set}).
-
--record(tag,{class,number,type,form=32}). % form = ?CONSTRUCTED
-% This record holds information about allowed constraint types per type
--record(cmap,{single_value=no,contained_subtype=no,value_range=no,
- size=no,permitted_alphabet=no,type_constraint=no,
- inner_subtyping=no}).
-
-
--record('EXTENSIONMARK',{pos,val}).
-
-% each IMPORT contains a list of 'SymbolsFromModule'
--record('SymbolsFromModule',{symbols,module,objid}).
-
-% Externaltypereference -> modulename '.' typename
--record('Externaltypereference',{pos,module,type}).
-% Externalvaluereference -> modulename '.' typename
--record('Externalvaluereference',{pos,module,value}).
-
--record(state,{module,mname,type,tname,value,vname,erule,parameters=[],
- inputmodules,abscomppath=[],recordtopname=[],options}).
-
-%% state record used by backend at partial decode
-%% active is set to 'yes' when a partial decode function is generated.
-%% prefix is set to 'dec-inc-' or 'dec-partial-' is for
-%% incomplete partial decode or partial decode respectively
-%% inc_tag_pattern holds the tags of the significant types/components
-%% for incomplete partial decode.
-%% tag_pattern holds the tags for partial decode.
-%% inc_type_pattern and type_pattern holds the names of the
-%% significant types/components.
-%% func_name holds the name of the function for the toptype.
-%% namelist holds the list of names of types/components that still
-%% haven't been generated.
-%% tobe_refed_funcs is a list of tuples {function names
-%% (Types),namelist of incomplete decode spec}, with function names
-%% that are referenced within other generated partial incomplete
-%% decode functions. They shall be generated as partial incomplete
-%% decode functions.
-
-%% gen_refed_funcs is as list of function names. Unlike
-%% tobe_refed_funcs these have been generated.
--record(gen_state,{active=false,prefix,inc_tag_pattern,
- tag_pattern,inc_type_pattern,
- type_pattern,func_name,namelist,
- tobe_refed_funcs=[],gen_refed_funcs=[]}).
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct.erl
deleted file mode 100644
index 37189e3780..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct.erl
+++ /dev/null
@@ -1,1904 +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: asn1ct.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
-%%
--module(asn1ct).
-
-%% Compile Time functions for ASN.1 (e.g ASN.1 compiler).
-
-%%-compile(export_all).
-%% Public exports
--export([compile/1, compile/2]).
--export([start/0, start/1, stop/0]).
--export([encode/2, encode/3, decode/3]).
--export([test/1, test/2, test/3, value/2]).
-%% Application internal exports
--export([compile_asn/3,compile_asn1/3,compile_py/3,compile/3,value/1,vsn/0,
- create_ets_table/2,get_name_of_def/1,get_pos_of_def/1]).
--export([read_config_data/1,get_gen_state_field/1,get_gen_state/0,
- partial_inc_dec_toptype/1,save_gen_state/1,update_gen_state/2,
- get_tobe_refed_func/1,reset_gen_state/0,is_function_generated/1,
- generated_refed_func/1,next_refed_func/0,pop_namelist/0,
- next_namelist_el/0,update_namelist/1,step_in_constructed/0,
- add_tobe_refed_func/1,add_generated_refed_func/1]).
-
--include("asn1_records.hrl").
--include_lib("stdlib/include/erl_compile.hrl").
-
--import(asn1ct_gen_ber_bin_v2,[encode_tag_val/3,decode_class/1]).
-
--define(unique_names,0).
--define(dupl_uniquedefs,1).
--define(dupl_equaldefs,2).
--define(dupl_eqdefs_uniquedefs,?dupl_equaldefs bor ?dupl_uniquedefs).
-
--define(CONSTRUCTED, 2#00100000).
-
-%% macros used for partial decode commands
--define(CHOOSEN,choosen).
--define(SKIP,skip).
--define(SKIP_OPTIONAL,skip_optional).
-
-%% macros used for partial incomplete decode commands
--define(MANDATORY,mandatory).
--define(DEFAULT,default).
--define(OPTIONAL,opt).
--define(PARTS,parts).
--define(UNDECODED,undec).
--define(ALTERNATIVE,alt).
--define(ALTERNATIVE_UNDECODED,alt_undec).
--define(ALTERNATIVE_PARTS,alt_parts).
-%-define(BINARY,bin).
-
-%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% This is the interface to the compiler
-%%
-%%
-
-
-compile(File) ->
- compile(File,[]).
-
-compile(File,Options) when list(Options) ->
- Options1 =
- case {lists:member(optimize,Options),lists:member(ber_bin,Options)} of
- {true,true} ->
- [ber_bin_v2|Options--[ber_bin]];
- _ -> Options
- end,
- case (catch input_file_type(File)) of
- {single_file,PrefixedFile} ->
- (catch compile1(PrefixedFile,Options1));
- {multiple_files_file,SetBase,FileName} ->
- FileList = get_file_list(FileName),
- (catch compile_set(SetBase,filename:dirname(FileName),
- FileList,Options1));
- Err = {input_file_error,_Reason} ->
- {error,Err}
- end.
-
-
-compile1(File,Options) when list(Options) ->
- io:format("Erlang ASN.1 version ~p compiling ~p ~n",[?vsn,File]),
- io:format("Compiler Options: ~p~n",[Options]),
- Ext = filename:extension(File),
- Base = filename:basename(File,Ext),
- OutFile = outfile(Base,"",Options),
- DbFile = outfile(Base,"asn1db",Options),
- Includes = [I || {i,I} <- Options],
- EncodingRule = get_rule(Options),
- create_ets_table(asn1_functab,[named_table]),
- Continue1 = scan({true,true},File,Options),
- Continue2 = parse(Continue1,File,Options),
- Continue3 = check(Continue2,File,OutFile,Includes,EncodingRule,
- DbFile,Options,[]),
- Continue4 = generate(Continue3,OutFile,EncodingRule,Options),
- delete_tables([asn1_functab]),
- compile_erl(Continue4,OutFile,Options).
-
-%%****************************************************************************%%
-%% functions dealing with compiling of several input files to one output file %%
-%%****************************************************************************%%
-compile_set(SetBase,DirName,Files,Options) when list(hd(Files)),list(Options) ->
- %% case when there are several input files in a list
- io:format("Erlang ASN.1 version ~p compiling ~p ~n",[?vsn,Files]),
- io:format("Compiler Options: ~p~n",[Options]),
- OutFile = outfile(SetBase,"",Options),
- DbFile = outfile(SetBase,"asn1db",Options),
- Includes = [I || {i,I} <- Options],
- EncodingRule = get_rule(Options),
- create_ets_table(asn1_functab,[named_table]),
- ScanRes = scan_set(DirName,Files,Options),
- ParseRes = parse_set(ScanRes,Options),
- Result =
- case [X||X <- ParseRes,element(1,X)==true] of
- [] -> %% all were false, time to quit
- lists:map(fun(X)->element(2,X) end,ParseRes);
- ParseRes -> %% all were true, continue with check
- InputModules =
- lists:map(
- fun(F)->
- E = filename:extension(F),
- B = filename:basename(F,E),
- if
- list(B) -> list_to_atom(B);
- true -> B
- end
- end,
- Files),
- check_set(ParseRes,SetBase,OutFile,Includes,
- EncodingRule,DbFile,Options,InputModules);
- Other ->
- {error,{'unexpected error in scan/parse phase',
- lists:map(fun(X)->element(3,X) end,Other)}}
- end,
- delete_tables([asn1_functab]),
- Result.
-
-check_set(ParseRes,SetBase,OutFile,Includes,EncRule,DbFile,
- Options,InputModules) ->
- lists:foreach(fun({_T,M,File})->
- cmp(M#module.name,File)
- end,
- ParseRes),
- MergedModule = merge_modules(ParseRes,SetBase),
- SetM = MergedModule#module{name=SetBase},
- Continue1 = check({true,SetM},SetBase,OutFile,Includes,EncRule,DbFile,
- Options,InputModules),
- Continue2 = generate(Continue1,OutFile,EncRule,Options),
-
- delete_tables([renamed_defs,original_imports,automatic_tags]),
-
- compile_erl(Continue2,OutFile,Options).
-
-%% merge_modules/2 -> returns a module record where the typeorval lists are merged,
-%% the exports lists are merged, the imports lists are merged when the
-%% elements come from other modules than the merge set, the tagdefault
-%% field gets the shared value if all modules have same tagging scheme,
-%% otherwise a tagging_error exception is thrown,
-%% the extensiondefault ...(not handled yet).
-merge_modules(ParseRes,CommonName) ->
- ModuleList = lists:map(fun(X)->element(2,X) end,ParseRes),
- NewModuleList = remove_name_collisions(ModuleList),
- case ets:info(renamed_defs,size) of
- 0 -> ets:delete(renamed_defs);
- _ -> ok
- end,
- save_imports(NewModuleList),
-% io:format("~p~n~p~n~p~n~n",[ets:lookup(original_imports,'M1'),ets:lookup(original_imports,'M2'),ets:tab2list(original_imports)]),
- TypeOrVal = lists:append(lists:map(fun(X)->X#module.typeorval end,
- NewModuleList)),
- InputMNameList = lists:map(fun(X)->X#module.name end,
- NewModuleList),
- CExports = common_exports(NewModuleList),
-
- ImportsModuleNameList = lists:map(fun(X)->
- {X#module.imports,
- X#module.name} end,
- NewModuleList),
- %% ImportsModuleNameList: [{Imports,ModuleName},...]
- %% Imports is a tuple {imports,[#'SymbolsFromModule'{},...]}
- CImports = common_imports(ImportsModuleNameList,InputMNameList),
- TagDefault = check_tagdefault(NewModuleList),
- #module{name=CommonName,tagdefault=TagDefault,exports=CExports,
- imports=CImports,typeorval=TypeOrVal}.
-
-%% causes an exit if duplicate definition names exist in a module
-remove_name_collisions(Modules) ->
- create_ets_table(renamed_defs,[named_table]),
- %% Name duplicates in the same module is not allowed.
- lists:foreach(fun exit_if_nameduplicate/1,Modules),
- %% Then remove duplicates in different modules and return the
- %% new list of modules.
- remove_name_collisions2(Modules,[]).
-
-%% For each definition in the first module in module list, find
-%% all definitons with same name and rename both definitions in
-%% the first module and in rest of modules
-remove_name_collisions2([M|Ms],Acc) ->
- TypeOrVal = M#module.typeorval,
- MName = M#module.name,
- %% Test each name in TypeOrVal on all modules in Ms
- {NewM,NewMs} = remove_name_collisions2(MName,TypeOrVal,Ms,[]),
- remove_name_collisions2(NewMs,[M#module{typeorval=NewM}|Acc]);
-remove_name_collisions2([],Acc) ->
- finished_warn_prints(),
- Acc.
-
-%% For each definition in list of defs find definitions in (rest of)
-%% modules that have same name. If duplicate was found rename def.
-%% Test each name in [T|Ts] on all modules in Ms
-remove_name_collisions2(ModName,[T|Ts],Ms,Acc) ->
- Name = get_name_of_def(T),
- case discover_dupl_in_mods(Name,T,Ms,[],?unique_names) of
- {_,?unique_names} -> % there was no name collision
- remove_name_collisions2(ModName,Ts,Ms,[T|Acc]);
- {NewMs,?dupl_uniquedefs} -> % renamed defs in NewMs
- %% rename T
- NewT = set_name_of_def(ModName,Name,T), %rename def
- warn_renamed_def(ModName,get_name_of_def(NewT),Name),
- ets:insert(renamed_defs,{get_name_of_def(NewT),Name,ModName}),
- remove_name_collisions2(ModName,Ts,NewMs,[NewT|Acc]);
- {NewMs,?dupl_equaldefs} -> % name duplicates, but identical defs
- %% keep name of T
- warn_kept_def(ModName,Name),
- remove_name_collisions2(ModName,Ts,NewMs,[T|Acc]);
- {NewMs,?dupl_eqdefs_uniquedefs} ->
- %% keep name of T, renamed defs in NewMs
- warn_kept_def(ModName,Name),
- remove_name_collisions2(ModName,Ts,NewMs,[T|Acc])
- end;
-remove_name_collisions2(_,[],Ms,Acc) ->
- {Acc,Ms}.
-
-%% Name is the name of a definition. If a definition with the same name
-%% is found in the modules Ms the definition will be renamed and returned.
-discover_dupl_in_mods(Name,Def,[M=#module{name=N,typeorval=TorV}|Ms],
- Acc,AnyRenamed) ->
- Fun = fun(T,RenamedOrDupl)->
- case {get_name_of_def(T),compare_defs(Def,T)} of
- {Name,not_equal} ->
- %% rename def
- NewT=set_name_of_def(N,Name,T),
- warn_renamed_def(N,get_name_of_def(NewT),Name),
- ets:insert(renamed_defs,{get_name_of_def(NewT),
- Name,N}),
- {NewT,?dupl_uniquedefs bor RenamedOrDupl};
- {Name,equal} ->
- %% delete def
- warn_deleted_def(N,Name),
- {[],?dupl_equaldefs bor RenamedOrDupl};
- _ ->
- {T,RenamedOrDupl}
- end
- end,
- {NewTorV,NewAnyRenamed} = lists:mapfoldl(Fun,AnyRenamed,TorV),
- %% have to flatten the NewTorV to remove any empty list elements
- discover_dupl_in_mods(Name,Def,Ms,
- [M#module{typeorval=lists:flatten(NewTorV)}|Acc],
- NewAnyRenamed);
-discover_dupl_in_mods(_,_,[],Acc,AnyRenamed) ->
- {Acc,AnyRenamed}.
-
-warn_renamed_def(ModName,NewName,OldName) ->
- maybe_first_warn_print(),
- io:format("NOTICE: The ASN.1 definition in module ~p with name ~p has been renamed in generated module. New name is ~p.~n",[ModName,OldName,NewName]).
-
-warn_deleted_def(ModName,DefName) ->
- maybe_first_warn_print(),
- io:format("NOTICE: The ASN.1 definition in module ~p with name ~p has been deleted in generated module.~n",[ModName,DefName]).
-
-warn_kept_def(ModName,DefName) ->
- maybe_first_warn_print(),
- io:format("NOTICE: The ASN.1 definition in module ~p with name ~p has kept its name due to equal definition as duplicate.~n",[ModName,DefName]).
-
-maybe_first_warn_print() ->
- case get(warn_duplicate_defs) of
- undefined ->
- put(warn_duplicate_defs,true),
- io:format("~nDue to multiple occurrences of a definition name in "
- "multi-file compiled files:~n");
- _ ->
- ok
- end.
-finished_warn_prints() ->
- put(warn_duplicate_defs,undefined).
-
-
-exit_if_nameduplicate(#module{typeorval=TorV}) ->
- exit_if_nameduplicate(TorV);
-exit_if_nameduplicate([]) ->
- ok;
-exit_if_nameduplicate([Def|Rest]) ->
- Name=get_name_of_def(Def),
- exit_if_nameduplicate2(Name,Rest),
- exit_if_nameduplicate(Rest).
-
-exit_if_nameduplicate2(Name,Rest) ->
- Pred=fun(Def)->
- case get_name_of_def(Def) of
- Name -> true;
- _ -> false
- end
- end,
- case lists:any(Pred,Rest) of
- true ->
- throw({error,{"more than one definition with same name",Name}});
- _ ->
- ok
- end.
-
-compare_defs(D1,D2) ->
- compare_defs2(unset_pos(D1),unset_pos(D2)).
-compare_defs2(D,D) ->
- equal;
-compare_defs2(_,_) ->
- not_equal.
-
-unset_pos(Def) when record(Def,typedef) ->
- Def#typedef{pos=undefined};
-unset_pos(Def) when record(Def,classdef) ->
- Def#classdef{pos=undefined};
-unset_pos(Def) when record(Def,valuedef) ->
- Def#valuedef{pos=undefined};
-unset_pos(Def) when record(Def,ptypedef) ->
- Def#ptypedef{pos=undefined};
-unset_pos(Def) when record(Def,pvaluedef) ->
- Def#pvaluedef{pos=undefined};
-unset_pos(Def) when record(Def,pvaluesetdef) ->
- Def#pvaluesetdef{pos=undefined};
-unset_pos(Def) when record(Def,pobjectdef) ->
- Def#pobjectdef{pos=undefined};
-unset_pos(Def) when record(Def,pobjectsetdef) ->
- Def#pobjectsetdef{pos=undefined}.
-
-get_pos_of_def(#typedef{pos=Pos}) ->
- Pos;
-get_pos_of_def(#classdef{pos=Pos}) ->
- Pos;
-get_pos_of_def(#valuedef{pos=Pos}) ->
- Pos;
-get_pos_of_def(#ptypedef{pos=Pos}) ->
- Pos;
-get_pos_of_def(#pvaluedef{pos=Pos}) ->
- Pos;
-get_pos_of_def(#pvaluesetdef{pos=Pos}) ->
- Pos;
-get_pos_of_def(#pobjectdef{pos=Pos}) ->
- Pos;
-get_pos_of_def(#pobjectsetdef{pos=Pos}) ->
- Pos.
-
-
-get_name_of_def(#typedef{name=Name}) ->
- Name;
-get_name_of_def(#classdef{name=Name}) ->
- Name;
-get_name_of_def(#valuedef{name=Name}) ->
- Name;
-get_name_of_def(#ptypedef{name=Name}) ->
- Name;
-get_name_of_def(#pvaluedef{name=Name}) ->
- Name;
-get_name_of_def(#pvaluesetdef{name=Name}) ->
- Name;
-get_name_of_def(#pobjectdef{name=Name}) ->
- Name;
-get_name_of_def(#pobjectsetdef{name=Name}) ->
- Name.
-
-set_name_of_def(ModName,Name,OldDef) ->
- NewName = list_to_atom(lists:concat([Name,ModName])),
- case OldDef of
- #typedef{} -> OldDef#typedef{name=NewName};
- #classdef{} -> OldDef#classdef{name=NewName};
- #valuedef{} -> OldDef#valuedef{name=NewName};
- #ptypedef{} -> OldDef#ptypedef{name=NewName};
- #pvaluedef{} -> OldDef#pvaluedef{name=NewName};
- #pvaluesetdef{} -> OldDef#pvaluesetdef{name=NewName};
- #pobjectdef{} -> OldDef#pobjectdef{name=NewName};
- #pobjectsetdef{} -> OldDef#pobjectsetdef{name=NewName}
- end.
-
-save_imports(ModuleList)->
- Fun = fun(M) ->
- case M#module.imports of
- {_,[]} -> [];
- {_,I} ->
- {M#module.name,I}
- end
- end,
- ImportsList = lists:map(Fun,ModuleList),
- case lists:flatten(ImportsList) of
- [] ->
- ok;
- ImportsList2 ->
- create_ets_table(original_imports,[named_table]),
- ets:insert(original_imports,ImportsList2)
- end.
-
-
-common_exports(ModuleList) ->
- %% if all modules exports 'all' then export 'all',
- %% otherwise export each typeorval name
- case lists:filter(fun(X)->
- element(2,X#module.exports) /= all
- end,
- ModuleList) of
- []->
- {exports,all};
- ModsWithExpList ->
- CExports1 =
- lists:append(lists:map(fun(X)->element(2,X#module.exports) end,
- ModsWithExpList)),
- CExports2 = export_all(lists:subtract(ModuleList,ModsWithExpList)),
- {exports,CExports1++CExports2}
- end.
-
-export_all([])->[];
-export_all(ModuleList) ->
- ExpList =
- lists:map(
- fun(M)->
- TorVL=M#module.typeorval,
- MName = M#module.name,
- lists:map(
- fun(Def)->
- case Def of
- T when record(T,typedef)->
- #'Externaltypereference'{pos=0,
- module=MName,
- type=T#typedef.name};
- V when record(V,valuedef) ->
- #'Externalvaluereference'{pos=0,
- module=MName,
- value=V#valuedef.name};
- C when record(C,classdef) ->
- #'Externaltypereference'{pos=0,
- module=MName,
- type=C#classdef.name};
- P when record(P,ptypedef) ->
- #'Externaltypereference'{pos=0,
- module=MName,
- type=P#ptypedef.name};
- PV when record(PV,pvaluesetdef) ->
- #'Externaltypereference'{pos=0,
- module=MName,
- type=PV#pvaluesetdef.name};
- PO when record(PO,pobjectdef) ->
- #'Externalvaluereference'{pos=0,
- module=MName,
- value=PO#pobjectdef.name}
- end
- end,
- TorVL)
- end,
- ModuleList),
- lists:append(ExpList).
-
-%% common_imports/2
-%% IList is a list of tuples, {Imports,MName}, where Imports is the imports of
-%% the module with name MName.
-%% InputMNameL holds the names of all merged modules.
-%% Returns an import tuple with a list of imports that are external the merged
-%% set of modules.
-common_imports(IList,InputMNameL) ->
- SetExternalImportsList = remove_in_set_imports(IList,InputMNameL,[]),
- {imports,remove_import_doubles(SetExternalImportsList)}.
-
-check_tagdefault(ModList) ->
- case have_same_tagdefault(ModList) of
- {true,TagDefault} -> TagDefault;
- {false,TagDefault} ->
- create_ets_table(automatic_tags,[named_table]),
- save_automatic_tagged_types(ModList),
- TagDefault
- end.
-
-have_same_tagdefault([#module{tagdefault=T}|Ms]) ->
- have_same_tagdefault(Ms,{true,T}).
-
-have_same_tagdefault([],TagDefault) ->
- TagDefault;
-have_same_tagdefault([#module{tagdefault=T}|Ms],TDefault={_,T}) ->
- have_same_tagdefault(Ms,TDefault);
-have_same_tagdefault([#module{tagdefault=T1}|Ms],{_,T2}) ->
- have_same_tagdefault(Ms,{false,rank_tagdef([T1,T2])}).
-
-rank_tagdef(L) ->
- case lists:member('EXPLICIT',L) of
- true -> 'EXPLICIT';
- _ -> 'IMPLICIT'
- end.
-
-save_automatic_tagged_types([])->
- done;
-save_automatic_tagged_types([#module{tagdefault='AUTOMATIC',
- typeorval=TorV}|Ms]) ->
- Fun =
- fun(T) ->
- ets:insert(automatic_tags,{get_name_of_def(T)})
- end,
- lists:foreach(Fun,TorV),
- save_automatic_tagged_types(Ms);
-save_automatic_tagged_types([_M|Ms]) ->
- save_automatic_tagged_types(Ms).
-
-%% remove_in_set_imports/3 :
-%% input: list with tuples of each module's imports and module name
-%% respectively.
-%% output: one list with same format but each occured import from a
-%% module in the input set (IMNameL) is removed.
-remove_in_set_imports([{{imports,ImpL},_ModName}|Rest],InputMNameL,Acc) ->
- NewImpL = remove_in_set_imports1(ImpL,InputMNameL,[]),
- remove_in_set_imports(Rest,InputMNameL,NewImpL++Acc);
-remove_in_set_imports([],_,Acc) ->
- lists:reverse(Acc).
-
-remove_in_set_imports1([I|Is],InputMNameL,Acc) ->
- case I#'SymbolsFromModule'.module of
- #'Externaltypereference'{type=MName} ->
- case lists:member(MName,InputMNameL) of
- true ->
- remove_in_set_imports1(Is,InputMNameL,Acc);
- false ->
- remove_in_set_imports1(Is,InputMNameL,[I|Acc])
- end;
- _ ->
- remove_in_set_imports1(Is,InputMNameL,[I|Acc])
- end;
-remove_in_set_imports1([],_,Acc) ->
- lists:reverse(Acc).
-
-remove_import_doubles([]) ->
- [];
-%% If several modules in the merge set imports symbols from
-%% the same external module it might be doubled.
-%% ImportList has #'SymbolsFromModule' elements
-remove_import_doubles(ImportList) ->
- MergedImportList =
- merge_symbols_from_module(ImportList,[]),
-%% io:format("MergedImportList: ~p~n",[MergedImportList]),
- delete_double_of_symbol(MergedImportList,[]).
-
-merge_symbols_from_module([Imp|Imps],Acc) ->
- #'Externaltypereference'{type=ModName} = Imp#'SymbolsFromModule'.module,
- IfromModName =
- lists:filter(
- fun(I)->
- case I#'SymbolsFromModule'.module of
- #'Externaltypereference'{type=ModName} ->
- true;
- #'Externalvaluereference'{value=ModName} ->
- true;
- _ -> false
- end
- end,
- Imps),
- NewImps = lists:subtract(Imps,IfromModName),
-%% io:format("Imp: ~p~nIfromModName: ~p~n",[Imp,IfromModName]),
- NewImp =
- Imp#'SymbolsFromModule'{
- symbols = lists:append(
- lists:map(fun(SL)->
- SL#'SymbolsFromModule'.symbols
- end,[Imp|IfromModName]))},
- merge_symbols_from_module(NewImps,[NewImp|Acc]);
-merge_symbols_from_module([],Acc) ->
- lists:reverse(Acc).
-
-delete_double_of_symbol([I|Is],Acc) ->
- SymL=I#'SymbolsFromModule'.symbols,
- NewSymL = delete_double_of_symbol1(SymL,[]),
- delete_double_of_symbol(Is,[I#'SymbolsFromModule'{symbols=NewSymL}|Acc]);
-delete_double_of_symbol([],Acc) ->
- Acc.
-
-delete_double_of_symbol1([TRef=#'Externaltypereference'{type=TrefName}|Rest],Acc)->
- NewRest =
- lists:filter(fun(S)->
- case S of
- #'Externaltypereference'{type=TrefName}->
- false;
- _ -> true
- end
- end,
- Rest),
- delete_double_of_symbol1(NewRest,[TRef|Acc]);
-delete_double_of_symbol1([VRef=#'Externalvaluereference'{value=VName}|Rest],Acc) ->
- NewRest =
- lists:filter(fun(S)->
- case S of
- #'Externalvaluereference'{value=VName}->
- false;
- _ -> true
- end
- end,
- Rest),
- delete_double_of_symbol1(NewRest,[VRef|Acc]);
-delete_double_of_symbol1([TRef={#'Externaltypereference'{type=MRef},
- #'Externaltypereference'{type=TRef}}|Rest],
- Acc)->
- NewRest =
- lists:filter(
- fun(S)->
- case S of
- {#'Externaltypereference'{type=MRef},
- #'Externaltypereference'{type=TRef}}->
- false;
- _ -> true
- end
- end,
- Rest),
- delete_double_of_symbol1(NewRest,[TRef|Acc]);
-delete_double_of_symbol1([],Acc) ->
- Acc.
-
-
-scan_set(DirName,Files,Options) ->
- lists:map(
- fun(F)->
- case scan({true,true},filename:join([DirName,F]),Options) of
- {false,{error,Reason}} ->
- throw({error,{'scan error in file:',F,Reason}});
- {TrueOrFalse,Res} ->
- {TrueOrFalse,Res,F}
- end
- end,
- Files).
-
-parse_set(ScanRes,Options) ->
- lists:map(
- fun({TorF,Toks,F})->
- case parse({TorF,Toks},F,Options) of
- {false,{error,Reason}} ->
- throw({error,{'parse error in file:',F,Reason}});
- {TrueOrFalse,Res} ->
- {TrueOrFalse,Res,F}
- end
- end,
- ScanRes).
-
-
-%%***********************************
-
-
-scan({true,_}, File,Options) ->
- case asn1ct_tok:file(File) of
- {error,Reason} ->
- io:format("~p~n",[Reason]),
- {false,{error,Reason}};
- Tokens ->
- case lists:member(ss,Options) of
- true -> % we terminate after scan
- {false,Tokens};
- false -> % continue with next pass
- {true,Tokens}
- end
- end;
-scan({false,Result},_,_) ->
- Result.
-
-
-parse({true,Tokens},File,Options) ->
- %Presult = asn1ct_parser2:parse(Tokens),
- %%case lists:member(p1,Options) of
- %% true ->
- %% asn1ct_parser:parse(Tokens);
- %% _ ->
- %% asn1ct_parser2:parse(Tokens)
- %% end,
- case catch asn1ct_parser2:parse(Tokens) of
- {error,{{Line,_Mod,Message},_TokTup}} ->
- if
- integer(Line) ->
- BaseName = filename:basename(File),
- io:format("syntax error at line ~p in module ~s:~n",
- [Line,BaseName]);
- true ->
- io:format("syntax error in module ~p:~n",[File])
- end,
- print_error_message(Message),
- {false,{error,Message}};
- {error,{Line,_Mod,[Message,Token]}} ->
- io:format("syntax error: ~p ~p at line ~p~n",
- [Message,Token,Line]),
- {false,{error,{Line,[Message,Token]}}};
- {ok,M} ->
- case lists:member(sp,Options) of
- true -> % terminate after parse
- {false,M};
- false -> % continue with next pass
- {true,M}
- end;
- OtherError ->
- io:format("~p~n",[OtherError])
- end;
-parse({false,Tokens},_,_) ->
- {false,Tokens}.
-
-check({true,M},File,OutFile,Includes,EncodingRule,DbFile,Options,InputMods) ->
- cmp(M#module.name,File),
- start(["."|Includes]),
- case asn1ct_check:storeindb(M) of
- ok ->
- Module = asn1_db:dbget(M#module.name,'MODULE'),
- State = #state{mname=Module#module.name,
- module=Module#module{typeorval=[]},
- erule=EncodingRule,
- inputmodules=InputMods,
- options=Options},
- Check = asn1ct_check:check(State,Module#module.typeorval),
- case {Check,lists:member(abs,Options)} of
- {{error,Reason},_} ->
- {false,{error,Reason}};
- {{ok,NewTypeOrVal,_},true} ->
- NewM = Module#module{typeorval=NewTypeOrVal},
- asn1_db:dbput(NewM#module.name,'MODULE',NewM),
- pretty2(M#module.name,lists:concat([OutFile,".abs"])),
- {false,ok};
- {{ok,NewTypeOrVal,GenTypeOrVal},_} ->
- NewM = Module#module{typeorval=NewTypeOrVal},
- asn1_db:dbput(NewM#module.name,'MODULE',NewM),
- asn1_db:dbsave(DbFile,M#module.name),
- io:format("--~p--~n",[{generated,DbFile}]),
- {true,{M,NewM,GenTypeOrVal}}
- end
- end;
-check({false,M},_,_,_,_,_,_,_) ->
- {false,M}.
-
-generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) ->
- debug_on(Options),
- case lists:member(compact_bit_string,Options) of
- true -> put(compact_bit_string,true);
- _ -> ok
- end,
- put(encoding_options,Options),
- create_ets_table(check_functions,[named_table]),
-
- %% create decoding function names and taglists for partial decode
- %% For the time being leave errors unnoticed !!!!!!!!!
-% io:format("Options: ~p~n",[Options]),
- case catch specialized_decode_prepare(EncodingRule,M,GenTOrV,Options) of
- {error, enoent} -> ok;
- {error, Reason} -> io:format("WARNING: Error in configuration"
- "file: ~n~p~n",[Reason]);
- {'EXIT',Reason} -> io:format("WARNING: Internal error when "
- "analyzing configuration"
- "file: ~n~p~n",[Reason]);
- _ -> ok
- end,
-
- asn1ct_gen:pgen(OutFile,EncodingRule,M#module.name,GenTOrV),
- debug_off(Options),
- put(compact_bit_string,false),
- erase(encoding_options),
- erase(tlv_format), % used in ber_bin, optimize
- erase(class_default_type),% used in ber_bin, optimize
- ets:delete(check_functions),
- case lists:member(sg,Options) of
- true -> % terminate here , with .erl file generated
- {false,true};
- false ->
- {true,true}
- end;
-generate({false,M},_,_,_) ->
- {false,M}.
-
-compile_erl({true,_},OutFile,Options) ->
- erl_compile(OutFile,Options);
-compile_erl({false,true},_,_) ->
- ok;
-compile_erl({false,Result},_,_) ->
- Result.
-
-input_file_type([]) ->
- {empty_name,[]};
-input_file_type(File) ->
- case filename:extension(File) of
- [] ->
- case file:read_file_info(lists:concat([File,".asn1"])) of
- {ok,_FileInfo} ->
- {single_file, lists:concat([File,".asn1"])};
- _Error ->
- case file:read_file_info(lists:concat([File,".asn"])) of
- {ok,_FileInfo} ->
- {single_file, lists:concat([File,".asn"])};
- _Error ->
- {single_file, lists:concat([File,".py"])}
- end
- end;
- ".asn1config" ->
- case read_config_file(File,asn1_module) of
- {ok,Asn1Module} ->
- put(asn1_config_file,File),
- input_file_type(Asn1Module);
- Error ->
- Error
- end;
- Asn1PFix ->
- Base = filename:basename(File,Asn1PFix),
- case filename:extension(Base) of
- [] ->
- {single_file,File};
- SetPFix when (SetPFix == ".set") ->
- {multiple_files_file,
- filename:basename(Base,SetPFix),
- File};
- _Error ->
- throw({input_file_error,{'Bad input file',File}})
- end
- end.
-
-get_file_list(File) ->
- case file:open(File, [read]) of
- {error,Reason} ->
- {error,{File,file:format_error(Reason)}};
- {ok,Stream} ->
- get_file_list1(Stream,[])
- end.
-
-get_file_list1(Stream,Acc) ->
- Ret = io:get_line(Stream,''),
- case Ret of
- eof ->
- file:close(Stream),
- lists:reverse(Acc);
- FileName ->
- PrefixedNameList =
- case (catch input_file_type(lists:delete($\n,FileName))) of
- {empty_name,[]} -> [];
- {single_file,Name} -> [Name];
- {multiple_files_file,Name} ->
- get_file_list(Name);
- Err = {input_file_error,_Reason} ->
- throw(Err)
- end,
- get_file_list1(Stream,PrefixedNameList++Acc)
- end.
-
-get_rule(Options) ->
- case [Rule ||Rule <-[per,ber,ber_bin,ber_bin_v2,per_bin],
- Opt <- Options,
- Rule==Opt] of
- [Rule] ->
- Rule;
- [Rule|_] ->
- Rule;
- [] ->
- ber
- end.
-
-erl_compile(OutFile,Options) ->
-% io:format("Options:~n~p~n",[Options]),
- case lists:member(noobj,Options) of
- true ->
- ok;
- _ ->
- ErlOptions = remove_asn_flags(Options),
- case c:c(OutFile,ErlOptions) of
- {ok,_Module} ->
- ok;
- _ ->
- {error,'no_compilation'}
- end
- end.
-
-remove_asn_flags(Options) ->
- [X || X <- Options,
- X /= get_rule(Options),
- X /= optimize,
- X /= compact_bit_string,
- X /= debug,
- X /= keyed_list].
-
-debug_on(Options) ->
- case lists:member(debug,Options) of
- true ->
- put(asndebug,true);
- _ ->
- true
- end,
- case lists:member(keyed_list,Options) of
- true ->
- put(asn_keyed_list,true);
- _ ->
- true
- end.
-
-
-debug_off(_Options) ->
- erase(asndebug),
- erase(asn_keyed_list).
-
-
-outfile(Base, Ext, Opts) when atom(Ext) ->
- outfile(Base, atom_to_list(Ext), Opts);
-outfile(Base, Ext, Opts) ->
- Obase = case lists:keysearch(outdir, 1, Opts) of
- {value, {outdir, Odir}} -> filename:join(Odir, Base);
- _NotFound -> Base % Not found or bad format
- end,
- case Ext of
- [] ->
- Obase;
- _ ->
- Obase++"."++Ext
- end.
-
-%% compile(AbsFileName, Options)
-%% Compile entry point for erl_compile.
-
-compile_asn(File,OutFile,Options) ->
- compile(lists:concat([File,".asn"]),OutFile,Options).
-
-compile_asn1(File,OutFile,Options) ->
- compile(lists:concat([File,".asn1"]),OutFile,Options).
-
-compile_py(File,OutFile,Options) ->
- compile(lists:concat([File,".py"]),OutFile,Options).
-
-compile(File, _OutFile, Options) ->
- case catch compile(File, make_erl_options(Options)) of
- Exit = {'EXIT',_Reason} ->
- io:format("~p~n~s~n",[Exit,"error"]),
- error;
- {error,_Reason} ->
- %% case occurs due to error in asn1ct_parser2,asn1ct_check
-%% io:format("~p~n",[_Reason]),
-%% io:format("~p~n~s~n",[_Reason,"error"]),
- error;
- ok ->
- io:format("ok~n"),
- ok;
- ParseRes when tuple(ParseRes) ->
- io:format("~p~n",[ParseRes]),
- ok;
- ScanRes when list(ScanRes) ->
- io:format("~p~n",[ScanRes]),
- ok;
- Unknown ->
- io:format("~p~n~s~n",[Unknown,"error"]),
- error
- end.
-
-%% Converts generic compiler options to specific options.
-
-make_erl_options(Opts) ->
-
- %% This way of extracting will work even if the record passed
- %% has more fields than known during compilation.
-
- Includes = Opts#options.includes,
- Defines = Opts#options.defines,
- Outdir = Opts#options.outdir,
-%% Warning = Opts#options.warning,
- Verbose = Opts#options.verbose,
- Specific = Opts#options.specific,
- Optimize = Opts#options.optimize,
- OutputType = Opts#options.output_type,
- Cwd = Opts#options.cwd,
-
- Options =
- case Verbose of
- true -> [verbose];
- false -> []
- end ++
-%%% case Warning of
-%%% 0 -> [];
-%%% _ -> [report_warnings]
-%%% end ++
- [] ++
- case Optimize of
- 1 -> [optimize];
- 999 -> [];
- _ -> [{optimize,Optimize}]
- end ++
- lists:map(
- fun ({Name, Value}) ->
- {d, Name, Value};
- (Name) ->
- {d, Name}
- end,
- Defines) ++
- case OutputType of
- undefined -> [ber]; % temporary default (ber when it's ready)
- ber -> [ber];
- ber_bin -> [ber_bin];
- ber_bin_v2 -> [ber_bin_v2];
- per -> [per];
- per_bin -> [per_bin]
- end,
-
- Options++[report_errors, {cwd, Cwd}, {outdir, Outdir}|
- lists:map(fun(Dir) -> {i, Dir} end, Includes)]++Specific.
-
-pretty2(Module,AbsFile) ->
- start(),
- {ok,F} = file:open(AbsFile, [write]),
- M = asn1_db:dbget(Module,'MODULE'),
- io:format(F,"%%%%%%%%%%%%%%%%%%% ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
- io:format(F,"~s\n",[asn1ct_pretty_format:term(M#module.defid)]),
- io:format(F,"~s\n",[asn1ct_pretty_format:term(M#module.tagdefault)]),
- io:format(F,"~s\n",[asn1ct_pretty_format:term(M#module.exports)]),
- io:format(F,"~s\n",[asn1ct_pretty_format:term(M#module.imports)]),
- io:format(F,"~s\n\n",[asn1ct_pretty_format:term(M#module.extensiondefault)]),
-
- {Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets} = M#module.typeorval,
- io:format(F,"%%%%%%%%%%%%%%%%%%% TYPES in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
- lists:foreach(fun(T)-> io:format(F,"~s\n",
- [asn1ct_pretty_format:term(asn1_db:dbget(Module,T))])
- end,Types),
- io:format(F,"%%%%%%%%%%%%%%%%%%% VALUES in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
- lists:foreach(fun(T)-> io:format(F,"~s\n",
- [asn1ct_pretty_format:term(asn1_db:dbget(Module,T))])
- end,Values),
- io:format(F,"%%%%%%%%%%%%%%%%%%% Parameterized Types in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
- lists:foreach(fun(T)-> io:format(F,"~s\n",
- [asn1ct_pretty_format:term(asn1_db:dbget(Module,T))])
- end,ParameterizedTypes),
- io:format(F,"%%%%%%%%%%%%%%%%%%% Classes in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
- lists:foreach(fun(T)-> io:format(F,"~s\n",
- [asn1ct_pretty_format:term(asn1_db:dbget(Module,T))])
- end,Classes),
- io:format(F,"%%%%%%%%%%%%%%%%%%% Objects in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
- lists:foreach(fun(T)-> io:format(F,"~s\n",
- [asn1ct_pretty_format:term(asn1_db:dbget(Module,T))])
- end,Objects),
- io:format(F,"%%%%%%%%%%%%%%%%%%% Object Sets in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]),
- lists:foreach(fun(T)-> io:format(F,"~s\n",
- [asn1ct_pretty_format:term(asn1_db:dbget(Module,T))])
- end,ObjectSets).
-start() ->
- Includes = ["."],
- start(Includes).
-
-
-start(Includes) when list(Includes) ->
- asn1_db:dbstart(Includes).
-
-stop() ->
- save(),
- asn1_db:stop_server(ns),
- asn1_db:stop_server(rand),
- stopped.
-
-save() ->
- asn1_db:dbstop().
-
-%%clear() ->
-%% asn1_db:dbclear().
-
-encode(Module,Term) ->
- asn1rt:encode(Module,Term).
-
-encode(Module,Type,Term) when list(Module) ->
- asn1rt:encode(list_to_atom(Module),Type,Term);
-encode(Module,Type,Term) ->
- asn1rt:encode(Module,Type,Term).
-
-decode(Module,Type,Bytes) when list(Module) ->
- asn1rt:decode(list_to_atom(Module),Type,Bytes);
-decode(Module,Type,Bytes) ->
- asn1rt:decode(Module,Type,Bytes).
-
-
-test(Module) ->
- start(),
- M = asn1_db:dbget(Module,'MODULE'),
- {Types,_Values,_Ptypes,_Classes,_Objects,_ObjectSets} = M#module.typeorval,
- test_each(Module,Types).
-
-test_each(Module,[Type | Rest]) ->
- case test(Module,Type) of
- {ok,_Result} ->
- test_each(Module,Rest);
- Error ->
- Error
- end;
-test_each(_,[]) ->
- ok.
-
-test(Module,Type) ->
- io:format("~p:~p~n",[Module,Type]),
- case (catch value(Module,Type)) of
- {ok,Val} ->
- %% io:format("asn1ct:test/2: ~w~n",[Val]),
- test(Module,Type,Val);
- {'EXIT',Reason} ->
- {error,{asn1,{value,Reason}}}
- end.
-
-
-test(Module,Type,Value) ->
- case catch encode(Module,Type,Value) of
- {ok,Bytes} ->
- %% io:format("test 1: ~p~n",[{Bytes}]),
- M = if
- list(Module) ->
- list_to_atom(Module);
- true ->
- Module
- end,
- NewBytes =
- case M:encoding_rule() of
- ber ->
- lists:flatten(Bytes);
- ber_bin when binary(Bytes) ->
- Bytes;
- ber_bin ->
- list_to_binary(Bytes);
- ber_bin_v2 when binary(Bytes) ->
- Bytes;
- ber_bin_v2 ->
- list_to_binary(Bytes);
- per ->
- lists:flatten(Bytes);
- per_bin when binary(Bytes) ->
- Bytes;
- per_bin ->
- list_to_binary(Bytes)
- end,
- case decode(Module,Type,NewBytes) of
- {ok,Value} ->
- {ok,{Module,Type,Value}};
- {ok,Res} ->
- {error,{asn1,{encode_decode_mismatch,
- {{Module,Type,Value},Res}}}};
- Error ->
- {error,{asn1,{{decode,
- {Module,Type,Value},Error}}}}
- end;
- Error ->
- {error,{asn1,{encode,{{Module,Type,Value},Error}}}}
- end.
-
-value(Module) ->
- start(),
- M = asn1_db:dbget(Module,'MODULE'),
- {Types,_Values,_Ptypes,_Classes,_Objects,_ObjectSets} = M#module.typeorval,
- lists:map(fun(A) ->value(Module,A) end,Types).
-
-value(Module,Type) ->
- start(),
- case catch asn1ct_value:get_type(Module,Type,no) of
- {error,Reason} ->
- {error,Reason};
- {'EXIT',Reason} ->
- {error,Reason};
- Result ->
- {ok,Result}
- end.
-
-cmp(Module,InFile) ->
- Base = filename:basename(InFile),
- Dir = filename:dirname(InFile),
- Ext = filename:extension(Base),
- Finfo = file:read_file_info(InFile),
- Minfo = file:read_file_info(filename:join(Dir,lists:concat([Module,Ext]))),
- case Finfo of
- Minfo ->
- ok;
- _ ->
- io:format("asn1error: Modulename and filename must be equal~n",[]),
- throw(error)
- end.
-
-vsn() ->
- ?vsn.
-
-print_error_message([got,H|T]) when list(H) ->
- io:format(" got:"),
- print_listing(H,"and"),
- print_error_message(T);
-print_error_message([expected,H|T]) when list(H) ->
- io:format(" expected one of:"),
- print_listing(H,"or"),
- print_error_message(T);
-print_error_message([H|T]) ->
- io:format(" ~p",[H]),
- print_error_message(T);
-print_error_message([]) ->
- io:format("~n").
-
-print_listing([H1,H2|[]],AndOr) ->
- io:format(" ~p ~s ~p",[H1,AndOr,H2]);
-print_listing([H1,H2|T],AndOr) ->
- io:format(" ~p,",[H1]),
- print_listing([H2|T],AndOr);
-print_listing([H],_AndOr) ->
- io:format(" ~p",[H]);
-print_listing([],_) ->
- ok.
-
-
-%% functions to administer ets tables
-
-%% Always creates a new table
-create_ets_table(Name,Options) when atom(Name) ->
- case ets:info(Name) of
- undefined ->
- ets:new(Name,Options);
- _ ->
- ets:delete(Name),
- ets:new(Name,Options)
- end.
-
-%% Creates a new ets table only if no table exists
-create_if_no_table(Name,Options) ->
- case ets:info(Name) of
- undefined ->
- %% create a new table
- create_ets_table(Name,Options);
- _ -> ok
- end.
-
-
-delete_tables([Table|Ts]) ->
- case ets:info(Table) of
- undefined -> ok;
- _ -> ets:delete(Table)
- end,
- delete_tables(Ts);
-delete_tables([]) ->
- ok.
-
-
-specialized_decode_prepare(Erule,M,TsAndVs,Options) ->
-% Asn1confMember =
-% fun([{asn1config,File}|_],_) ->
-% {true,File};
-% ([],_) -> false;
-% ([_H|T],Fun) ->
-% Fun(T,Fun)
-% end,
-% case Asn1confMember(Options,Asn1confMember) of
-% {true,File} ->
- case lists:member(asn1config,Options) of
- true ->
- partial_decode_prepare(Erule,M,TsAndVs,Options);
- _ ->
- ok
- end.
-%% Reads the configuration file if it exists and stores information
-%% about partial decode and incomplete decode
-partial_decode_prepare(ber_bin_v2,M,TsAndVs,Options) when tuple(TsAndVs) ->
- %% read configure file
-% Types = element(1,TsAndVs),
- CfgList = read_config_file(M#module.name),
- SelectedDecode = get_config_info(CfgList,partial_decode),
- ExclusiveDecode = get_config_info(CfgList,exclusive_decode),
- CommandList =
- create_partial_decode_gen_info(M#module.name,SelectedDecode),
-% io:format("partial_decode = ~p~n",[CommandList]),
-
- save_config(partial_decode,CommandList),
- CommandList2 =
- create_partial_inc_decode_gen_info(M#module.name,ExclusiveDecode),
-% io:format("partial_incomplete_decode = ~p~n",[CommandList2]),
- Part_inc_tlv_tags = tag_format(ber_bin_v2,Options,CommandList2),
-% io:format("partial_incomplete_decode: tlv_tags = ~p~n",[Part_inc_tlv_tags]),
- save_config(partial_incomplete_decode,Part_inc_tlv_tags),
- save_gen_state(ExclusiveDecode,Part_inc_tlv_tags);
-partial_decode_prepare(_,_,_,_) ->
- ok.
-
-
-
-%% create_partial_inc_decode_gen_info/2
-%%
-%% Creats a list of tags out of the information in TypeNameList that
-%% tells which value will be incomplete decoded, i.e. each end
-%% component/type in TypeNameList. The significant types/components in
-%% the path from the toptype must be specified in the
-%% TypeNameList. Significant elements are all constructed types that
-%% branches the path to the leaf and the leaf it selfs.
-%%
-%% Returns a list of elements, where an element may be one of
-%% mandatory|[opt,Tag]|[bin,Tag]. mandatory correspond to a mandatory
-%% element that shall be decoded as usual. [opt,Tag] matches an
-%% OPTIONAL or DEFAULT element that shall be decoded as
-%% usual. [bin,Tag] corresponds to an element, mandatory, OPTIONAL or
-%% DEFAULT, that shall be left encoded (incomplete decoded).
-create_partial_inc_decode_gen_info(ModName,{Mod,[{Name,L}|Ls]}) when list(L) ->
- TopTypeName = partial_inc_dec_toptype(L),
- [{Name,TopTypeName,
- create_partial_inc_decode_gen_info1(ModName,TopTypeName,{Mod,L})}|
- create_partial_inc_decode_gen_info(ModName,{Mod,Ls})];
-create_partial_inc_decode_gen_info(_,{_,[]}) ->
- [];
-create_partial_inc_decode_gen_info(_,[]) ->
- [].
-
-create_partial_inc_decode_gen_info1(ModName,TopTypeName,{ModName,
- [_TopType|Rest]}) ->
- case asn1_db:dbget(ModName,TopTypeName) of
- #typedef{typespec=TS} ->
- TagCommand = get_tag_command(TS,?MANDATORY,mandatory),
- create_pdec_inc_command(ModName,get_components(TS#type.def),
- Rest,[TagCommand]);
- _ ->
- throw({error,{"wrong type list in asn1 config file",
- TopTypeName}})
- end;
-create_partial_inc_decode_gen_info1(M1,_,{M2,_}) when M1 /= M2 ->
- throw({error,{"wrong module name in asn1 config file",
- M2}});
-create_partial_inc_decode_gen_info1(_,_,TNL) ->
- throw({error,{"wrong type list in asn1 config file",
- TNL}}).
-
-%%
-%% Only when there is a 'ComponentType' the config data C1 may be a
-%% list, where the incomplete decode is branched. So, C1 may be a
-%% list, a "binary tuple", a "parts tuple" or an atom. The second
-%% element of a binary tuple and a parts tuple is an atom.
-create_pdec_inc_command(_ModName,_,[],Acc) ->
- lists:reverse(Acc);
-create_pdec_inc_command(ModName,{Comps1,Comps2},TNL,Acc)
- when list(Comps1),list(Comps2) ->
- create_pdec_inc_command(ModName,Comps1 ++ Comps2,TNL,Acc);
-create_pdec_inc_command(ModN,Clist,[CL|_Rest],Acc) when list(CL) ->
- create_pdec_inc_command(ModN,Clist,CL,Acc);
-create_pdec_inc_command(ModName,
- CList=[#'ComponentType'{name=Name,typespec=TS,
- prop=Prop}|Comps],
- TNL=[C1|Cs],Acc) ->
- case C1 of
-% Name ->
-% %% In this case C1 is an atom
-% TagCommand = get_tag_command(TS,?MANDATORY,Prop),
-% create_pdec_inc_command(ModName,get_components(TS#type.def),Cs,[TagCommand|Acc]);
- {Name,undecoded} ->
- TagCommand = get_tag_command(TS,?UNDECODED,Prop),
- create_pdec_inc_command(ModName,Comps,Cs,[TagCommand|Acc]);
- {Name,parts} ->
- TagCommand = get_tag_command(TS,?PARTS,Prop),
- create_pdec_inc_command(ModName,Comps,Cs,[TagCommand|Acc]);
- L when list(L) ->
- %% This case is only possible as the first element after
- %% the top type element, when top type is SEGUENCE or SET.
- %% Follow each element in L. Must note every tag on the
- %% way until the last command is reached, but it ought to
- %% be enough to have a "complete" or "complete optional"
- %% command for each component that is not specified in the
- %% config file. Then in the TLV decode the components with
- %% a "complete" command will be decoded by an ordinary TLV
- %% decode.
- create_pdec_inc_command(ModName,CList,L,Acc);
- {Name,RestPartsList} when list(RestPartsList) ->
- %% Same as previous, but this may occur at any place in
- %% the structure. The previous is only possible as the
- %% second element.
- case get_tag_command(TS,?MANDATORY,Prop) of
- ?MANDATORY ->
- InnerDirectives=
- create_pdec_inc_command(ModName,TS#type.def,
- RestPartsList,[]),
- create_pdec_inc_command(ModName,Comps,Cs,
- [[?MANDATORY,InnerDirectives]|Acc]);
-% create_pdec_inc_command(ModName,Comps,Cs,
-% [InnerDirectives,?MANDATORY|Acc]);
- [Opt,EncTag] ->
- InnerDirectives =
- create_pdec_inc_command(ModName,TS#type.def,
- RestPartsList,[]),
- create_pdec_inc_command(ModName,Comps,Cs,
- [[Opt,EncTag,InnerDirectives]|Acc])
- end;
-% create_pdec_inc_command(ModName,CList,RestPartsList,Acc);
-%% create_pdec_inc_command(ModName,TS#type.def,RestPartsList,Acc);
- _ -> %% this component may not be in the config list
- TagCommand = get_tag_command(TS,?MANDATORY,Prop),
- create_pdec_inc_command(ModName,Comps,TNL,[TagCommand|Acc])
- end;
-create_pdec_inc_command(ModName,
- {'CHOICE',[#'ComponentType'{name=C1,
- typespec=TS,
- prop=Prop}|Comps]},
- [{C1,Directive}|Rest],Acc) ->
- case Directive of
- List when list(List) ->
- [Command,Tag] = get_tag_command(TS,?ALTERNATIVE,Prop),
- CompAcc = create_pdec_inc_command(ModName,TS#type.def,List,[]),
- create_pdec_inc_command(ModName,{'CHOICE',Comps},Rest,
- [[Command,Tag,CompAcc]|Acc]);
- undecoded ->
- TagCommand = get_tag_command(TS,?ALTERNATIVE_UNDECODED,Prop),
- create_pdec_inc_command(ModName,{'CHOICE',Comps},Rest,
- [TagCommand|Acc]);
- parts ->
- TagCommand = get_tag_command(TS,?ALTERNATIVE_PARTS,Prop),
- create_pdec_inc_command(ModName,{'CHOICE',Comps},Rest,
- [TagCommand|Acc])
- end;
-create_pdec_inc_command(ModName,
- {'CHOICE',[#'ComponentType'{typespec=TS,
- prop=Prop}|Comps]},
- TNL,Acc) ->
- TagCommand = get_tag_command(TS,?ALTERNATIVE,Prop),
- create_pdec_inc_command(ModName,{'CHOICE',Comps},TNL,[TagCommand|Acc]);
-create_pdec_inc_command(M,{'CHOICE',{Cs1,Cs2}},TNL,Acc)
- when list(Cs1),list(Cs2) ->
- create_pdec_inc_command(M,{'CHOICE',Cs1 ++ Cs2},TNL,Acc);
-create_pdec_inc_command(ModName,#'Externaltypereference'{module=M,type=Name},
- TNL,Acc) ->
- #type{def=Def} = get_referenced_type(M,Name),
- create_pdec_inc_command(ModName,get_components(Def),TNL,Acc);
-create_pdec_inc_command(_,_,TNL,_) ->
- throw({error,{"unexpected error when creating partial "
- "decode command",TNL}}).
-
-partial_inc_dec_toptype([T|_]) when atom(T) ->
- T;
-partial_inc_dec_toptype([{T,_}|_]) when atom(T) ->
- T;
-partial_inc_dec_toptype([L|_]) when list(L) ->
- partial_inc_dec_toptype(L);
-partial_inc_dec_toptype(_) ->
- throw({error,{"no top type found for partial incomplete decode"}}).
-
-
-%% Creats a list of tags out of the information in TypeList and Types
-%% that tells which value will be decoded. Each constructed type that
-%% is in the TypeList will get a "choosen" command. Only the last
-%% type/component in the TypeList may be a primitive type. Components
-%% "on the way" to the final element may get the "skip" or the
-%% "skip_optional" command.
-%% CommandList = [Elements]
-%% Elements = {choosen,Tag}|{skip_optional,Tag}|skip
-%% Tag is a binary with the tag BER encoded.
-create_partial_decode_gen_info(ModName,{{_,ModName},TypeList}) ->
- case TypeList of
- [TopType|Rest] ->
- case asn1_db:dbget(ModName,TopType) of
- #typedef{typespec=TS} ->
- TagCommand = get_tag_command(TS,?CHOOSEN),
- create_pdec_command(ModName,get_components(TS#type.def),
- Rest,[TagCommand]);
- _ ->
- throw({error,{"wrong type list in asn1 config file",
- TypeList}})
- end;
- _ ->
- []
- end;
-create_partial_decode_gen_info(_,[]) ->
- [];
-create_partial_decode_gen_info(_M1,{{_,M2},_}) ->
- throw({error,{"wrong module name in asn1 config file",
- M2}}).
-
-%% create_pdec_command/4 for each name (type or component) in the
-%% third argument, TypeNameList, a command is created. The command has
-%% information whether the component/type shall be skipped, looked
-%% into or returned. The list of commands is returned.
-create_pdec_command(_ModName,_,[],Acc) ->
- lists:reverse(Acc);
-create_pdec_command(ModName,[#'ComponentType'{name=C1,typespec=TS}|_Comps],
- [C1|Cs],Acc) ->
- %% this component is a constructed type or the last in the
- %% TypeNameList otherwise the config spec is wrong
- TagCommand = get_tag_command(TS,?CHOOSEN),
- create_pdec_command(ModName,get_components(TS#type.def),
- Cs,[TagCommand|Acc]);
-create_pdec_command(ModName,[#'ComponentType'{typespec=TS,
- prop=Prop}|Comps],
- [C2|Cs],Acc) ->
- TagCommand =
- case Prop of
- mandatory ->
- get_tag_command(TS,?SKIP);
- _ ->
- get_tag_command(TS,?SKIP_OPTIONAL)
- end,
- create_pdec_command(ModName,Comps,[C2|Cs],[TagCommand|Acc]);
-create_pdec_command(ModName,{'CHOICE',[Comp=#'ComponentType'{name=C1}|_]},TNL=[C1|_Cs],Acc) ->
- create_pdec_command(ModName,[Comp],TNL,Acc);
-create_pdec_command(ModName,{'CHOICE',[#'ComponentType'{}|Comps]},TNL,Acc) ->
- create_pdec_command(ModName,{'CHOICE',Comps},TNL,Acc);
-create_pdec_command(ModName,#'Externaltypereference'{module=M,type=C1},
- TypeNameList,Acc) ->
- case get_referenced_type(M,C1) of
- #type{def=Def} ->
- create_pdec_command(ModName,get_components(Def),TypeNameList,
- Acc);
- Err ->
- throw({error,{"unexpected result when fetching "
- "referenced element",Err}})
- end;
-create_pdec_command(ModName,TS=#type{def=Def},[C1|Cs],Acc) ->
- %% This case when we got the "components" of a SEQUENCE/SET OF
- case C1 of
- [1] ->
- %% A list with an integer is the only valid option in a 'S
- %% OF', the other valid option would be an empty
- %% TypeNameList saying that the entire 'S OF' will be
- %% decoded.
- TagCommand = get_tag_command(TS,?CHOOSEN),
- create_pdec_command(ModName,Def,Cs,[TagCommand|Acc]);
- [N] when integer(N) ->
- TagCommand = get_tag_command(TS,?SKIP),
- create_pdec_command(ModName,Def,[[N-1]|Cs],[TagCommand|Acc]);
- Err ->
- throw({error,{"unexpected error when creating partial "
- "decode command",Err}})
- end;
-create_pdec_command(_,_,TNL,_) ->
- throw({error,{"unexpected error when creating partial "
- "decode command",TNL}}).
-
-% get_components({'CHOICE',Components}) ->
-% Components;
-get_components(#'SEQUENCE'{components=Components}) ->
- Components;
-get_components(#'SET'{components=Components}) ->
- Components;
-get_components({'SEQUENCE OF',Components}) ->
- Components;
-get_components({'SET OF',Components}) ->
- Components;
-get_components(Def) ->
- Def.
-
-%% get_tag_command(Type,Command)
-
-%% Type is the type that has information about the tag Command tells
-%% what to do with the encoded value with the tag of Type when
-%% decoding.
-get_tag_command(#type{tag=[]},_) ->
- [];
-get_tag_command(#type{tag=[_Tag]},?SKIP) ->
- ?SKIP;
-get_tag_command(#type{tag=[Tag]},Command) ->
- %% encode the tag according to BER
- [Command,encode_tag_val(decode_class(Tag#tag.class),Tag#tag.form,
- Tag#tag.number)];
-get_tag_command(T=#type{tag=[Tag|Tags]},Command) ->
- [get_tag_command(T#type{tag=Tag},Command)|
- get_tag_command(T#type{tag=Tags},Command)].
-
-%% get_tag_command/3 used by create_pdec_inc_command
-get_tag_command(#type{tag=[]},_,_) ->
- [];
-get_tag_command(#type{tag=[Tag]},?MANDATORY,Prop) ->
- case Prop of
- mandatory ->
- ?MANDATORY;
- {'DEFAULT',_} ->
- [?DEFAULT,encode_tag_val(decode_class(Tag#tag.class),
- Tag#tag.form,Tag#tag.number)];
- _ -> [?OPTIONAL,encode_tag_val(decode_class(Tag#tag.class),
- Tag#tag.form,Tag#tag.number)]
- end;
-get_tag_command(#type{tag=[Tag]},Command,_) ->
- [Command,encode_tag_val(decode_class(Tag#tag.class),Tag#tag.form,
- Tag#tag.number)].
-
-
-get_referenced_type(M,Name) ->
- case asn1_db:dbget(M,Name) of
- #typedef{typespec=TS} ->
- case TS of
- #type{def=#'Externaltypereference'{module=M2,type=Name2}} ->
- %% The tags have already been taken care of in the
- %% first reference where they were gathered in a
- %% list of tags.
- get_referenced_type(M2,Name2);
- #type{} -> TS;
- _ ->
- throw({error,{"unexpected element when"
- " fetching referenced type",TS}})
- end;
- T ->
- throw({error,{"unexpected element when fetching "
- "referenced type",T}})
- end.
-
-tag_format(EncRule,_Options,CommandList) ->
- case EncRule of
- ber_bin_v2 ->
- tlv_tags(CommandList);
- _ ->
- CommandList
- end.
-
-tlv_tags([]) ->
- [];
-tlv_tags([mandatory|Rest]) ->
- [mandatory|tlv_tags(Rest)];
-tlv_tags([[Command,Tag]|Rest]) when atom(Command),binary(Tag) ->
- [[Command,tlv_tag(Tag)]|tlv_tags(Rest)];
-tlv_tags([[Command,Directives]|Rest]) when atom(Command),list(Directives) ->
- [[Command,tlv_tags(Directives)]|tlv_tags(Rest)];
-%% remove all empty lists
-tlv_tags([[]|Rest]) ->
- tlv_tags(Rest);
-tlv_tags([{Name,TopType,L1}|Rest]) when list(L1),atom(TopType) ->
- [{Name,TopType,tlv_tags(L1)}|tlv_tags(Rest)];
-tlv_tags([[Command,Tag,L1]|Rest]) when list(L1),binary(Tag) ->
- [[Command,tlv_tag(Tag),tlv_tags(L1)]|tlv_tags(Rest)];
-tlv_tags([L=[L1|_]|Rest]) when list(L1) ->
- [tlv_tags(L)|tlv_tags(Rest)].
-
-tlv_tag(<<Cl:2,_:1,TagNo:5>>) when TagNo < 31 ->
- (Cl bsl 16) + TagNo;
-tlv_tag(<<Cl:2,_:1,31:5,0:1,TagNo:7>>) ->
- (Cl bsl 16) + TagNo;
-tlv_tag(<<Cl:2,_:1,31:5,Buffer/binary>>) ->
- TagNo = tlv_tag1(Buffer,0),
- (Cl bsl 16) + TagNo.
-tlv_tag1(<<0:1,PartialTag:7>>,Acc) ->
- (Acc bsl 7) bor PartialTag;
-tlv_tag1(<<1:1,PartialTag:7,Buffer/binary>>,Acc) ->
- tlv_tag1(Buffer,(Acc bsl 7) bor PartialTag).
-
-%% reads the content from the configuration file and returns the
-%% selected part choosen by InfoType. Assumes that the config file
-%% content is an Erlang term.
-read_config_file(ModuleName,InfoType) when atom(InfoType) ->
- CfgList = read_config_file(ModuleName),
- get_config_info(CfgList,InfoType).
-
-
-read_config_file(ModuleName) ->
- case file:consult(lists:concat([ModuleName,'.asn1config'])) of
-% case file:consult(ModuleName) of
- {ok,CfgList} ->
- CfgList;
- {error,enoent} ->
- Options = get(encoding_options),
- Includes = [I || {i,I} <- Options],
- read_config_file1(ModuleName,Includes);
- {error,Reason} ->
- file:format_error(Reason),
- throw({error,{"error reading asn1 config file",Reason}})
- end.
-read_config_file1(ModuleName,[]) ->
- case filename:extension(ModuleName) of
- ".asn1config" ->
- throw({error,enoent});
- _ ->
- read_config_file(lists:concat([ModuleName,".asn1config"]))
- end;
-read_config_file1(ModuleName,[H|T]) ->
-% File = filename:join([H,lists:concat([ModuleName,'.asn1config'])]),
- File = filename:join([H,ModuleName]),
- case file:consult(File) of
- {ok,CfgList} ->
- CfgList;
- {error,enoent} ->
- read_config_file1(ModuleName,T);
- {error,Reason} ->
- file:format_error(Reason),
- throw({error,{"error reading asn1 config file",Reason}})
- end.
-
-get_config_info(CfgList,InfoType) ->
- case InfoType of
- all ->
- CfgList;
- _ ->
- case lists:keysearch(InfoType,1,CfgList) of
- {value,{InfoType,Value}} ->
- Value;
- false ->
- []
- end
- end.
-
-%% save_config/2 saves the Info with the key Key
-%% Before saving anything check if a table exists
-save_config(Key,Info) ->
- create_if_no_table(asn1_general,[named_table]),
- ets:insert(asn1_general,{{asn1_config,Key},Info}).
-
-read_config_data(Key) ->
- case ets:info(asn1_general) of
- undefined -> undefined;
- _ ->
- case ets:lookup(asn1_general,{asn1_config,Key}) of
- [{_,Data}] -> Data;
- Err ->
- io:format("strange data from config file ~w~n",[Err]),
- Err
- end
- end.
-
-
-%%
-%% Functions to manipulate the gen_state record saved in the
-%% asn1_general ets table.
-%%
-
-%% saves input data in a new gen_state record
-save_gen_state({_,ConfList},PartIncTlvTagList) ->
- %ConfList=[{FunctionName,PatternList}|Rest]
- StateRec = #gen_state{inc_tag_pattern=PartIncTlvTagList,
- inc_type_pattern=ConfList},
- save_config(gen_state,StateRec);
-save_gen_state(_,_) ->
-%% ok.
- save_config(gen_state,#gen_state{}).
-
-save_gen_state(GenState) when record(GenState,gen_state) ->
- save_config(gen_state,GenState).
-
-
-%% get_gen_state_field returns undefined if no gen_state exists or if
-%% Field is undefined or the data at the field.
-get_gen_state_field(Field) ->
- case read_config_data(gen_state) of
- undefined ->
- undefined;
- GenState ->
- get_gen_state_field(GenState,Field)
- end.
-get_gen_state_field(#gen_state{active=Active},active) ->
- Active;
-get_gen_state_field(_,active) ->
- false;
-get_gen_state_field(GS,prefix) ->
- GS#gen_state.prefix;
-get_gen_state_field(GS,inc_tag_pattern) ->
- GS#gen_state.inc_tag_pattern;
-get_gen_state_field(GS,tag_pattern) ->
- GS#gen_state.tag_pattern;
-get_gen_state_field(GS,inc_type_pattern) ->
- GS#gen_state.inc_type_pattern;
-get_gen_state_field(GS,type_pattern) ->
- GS#gen_state.type_pattern;
-get_gen_state_field(GS,func_name) ->
- GS#gen_state.func_name;
-get_gen_state_field(GS,namelist) ->
- GS#gen_state.namelist;
-get_gen_state_field(GS,tobe_refed_funcs) ->
- GS#gen_state.tobe_refed_funcs;
-get_gen_state_field(GS,gen_refed_funcs) ->
- GS#gen_state.gen_refed_funcs.
-
-
-get_gen_state() ->
- read_config_data(gen_state).
-
-
-update_gen_state(Field,Data) ->
- case get_gen_state() of
- State when record(State,gen_state) ->
- update_gen_state(Field,State,Data);
- _ ->
- exit({error,{asn1,{internal,
- "tried to update nonexistent gen_state",Field,Data}}})
- end.
-update_gen_state(active,State,Data) ->
- save_gen_state(State#gen_state{active=Data});
-update_gen_state(prefix,State,Data) ->
- save_gen_state(State#gen_state{prefix=Data});
-update_gen_state(inc_tag_pattern,State,Data) ->
- save_gen_state(State#gen_state{inc_tag_pattern=Data});
-update_gen_state(tag_pattern,State,Data) ->
- save_gen_state(State#gen_state{tag_pattern=Data});
-update_gen_state(inc_type_pattern,State,Data) ->
- save_gen_state(State#gen_state{inc_type_pattern=Data});
-update_gen_state(type_pattern,State,Data) ->
- save_gen_state(State#gen_state{type_pattern=Data});
-update_gen_state(func_name,State,Data) ->
- save_gen_state(State#gen_state{func_name=Data});
-update_gen_state(namelist,State,Data) ->
-% SData =
-% case Data of
-% [D] when list(D) -> D;
-% _ -> Data
-% end,
- save_gen_state(State#gen_state{namelist=Data});
-update_gen_state(tobe_refed_funcs,State,Data) ->
- save_gen_state(State#gen_state{tobe_refed_funcs=Data});
-update_gen_state(gen_refed_funcs,State,Data) ->
- save_gen_state(State#gen_state{gen_refed_funcs=Data}).
-
-update_namelist(Name) ->
- case get_gen_state_field(namelist) of
- [Name,Rest] -> update_gen_state(namelist,Rest);
- [Name|Rest] -> update_gen_state(namelist,Rest);
- [{Name,List}] when list(List) -> update_gen_state(namelist,List);
- [{Name,Atom}|Rest] when atom(Atom) -> update_gen_state(namelist,Rest);
- Other -> Other
- end.
-
-pop_namelist() ->
- DeepTail = %% removes next element in order
- fun([[{_,A}]|T],_Fun) when atom(A) -> T;
- ([{_N,L}|T],_Fun) when list(L) -> [L|T];
- ([[]|T],Fun) -> Fun(T,Fun);
- ([L1|L2],Fun) when list(L1) ->
- case lists:flatten(L1) of
- [] -> Fun([L2],Fun);
- _ -> [Fun(L1,Fun)|L2]
- end;
- ([_H|T],_Fun) -> T
- end,
- {Pop,NewNL} =
- case get_gen_state_field(namelist) of
- [] -> {[],[]};
- L ->
- {next_namelist_el(L),
- DeepTail(L,DeepTail)}
- end,
- update_gen_state(namelist,NewNL),
- Pop.
-
-%% next_namelist_el fetches the next type/component name in turn in
-%% the namelist, without changing the namelist.
-next_namelist_el() ->
- case get_gen_state_field(namelist) of
- undefined -> undefined;
- L when list(L) -> next_namelist_el(L)
- end.
-
-next_namelist_el([]) ->
- [];
-next_namelist_el([L]) when list(L) ->
- next_namelist_el(L);
-next_namelist_el([H|_]) when atom(H) ->
- H;
-next_namelist_el([L|T]) when list(L) ->
- case next_namelist_el(L) of
- [] ->
- next_namelist_el([T]);
- R ->
- R
- end;
-next_namelist_el([H={_,A}|_]) when atom(A) ->
- H.
-
-%% removes a bracket from the namelist
-step_in_constructed() ->
- case get_gen_state_field(namelist) of
- [L] when list(L) ->
- update_gen_state(namelist,L);
- _ -> ok
- end.
-
-is_function_generated(Name) ->
- case get_gen_state_field(gen_refed_funcs) of
- L when list(L) ->
- lists:member(Name,L);
- _ ->
- false
- end.
-
-get_tobe_refed_func(Name) ->
- case get_gen_state_field(tobe_refed_funcs) of
- L when list(L) ->
- case lists:keysearch(Name,1,L) of
- {_,Element} ->
- Element;
- _ ->
- undefined
- end;
- _ ->
- undefined
- end.
-
-add_tobe_refed_func(Data) ->
- L = get_gen_state_field(tobe_refed_funcs),
- update_gen_state(tobe_refed_funcs,[Data|L]).
-
-%% moves Name from the to be list to the generated list.
-generated_refed_func(Name) ->
- L = get_gen_state_field(tobe_refed_funcs),
- NewL = lists:keydelete(Name,1,L),
- update_gen_state(tobe_refed_funcs,NewL),
- L2 = get_gen_state_field(gen_refed_funcs),
- update_gen_state(gen_refed_funcs,[Name|L2]).
-
-add_generated_refed_func(Data) ->
- L = get_gen_state_field(gen_refed_funcs),
- update_gen_state(gen_refed_funcs,[Data|L]).
-
-
-next_refed_func() ->
- case get_gen_state_field(tobe_refed_funcs) of
- [] ->
- [];
- [H|T] ->
- update_gen_state(tobe_refed_funcs,T),
- H
- end.
-
-reset_gen_state() ->
- save_gen_state(#gen_state{}).
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_check.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_check.erl
deleted file mode 100644
index 9da6611dba..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_check.erl
+++ /dev/null
@@ -1,5567 +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: asn1ct_check.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
-%%
--module(asn1ct_check).
-
-%% Main Module for ASN.1 compile time functions
-
-%-compile(export_all).
--export([check/2,storeindb/1]).
--include("asn1_records.hrl").
-%%% The tag-number for universal types
--define(N_BOOLEAN, 1).
--define(N_INTEGER, 2).
--define(N_BIT_STRING, 3).
--define(N_OCTET_STRING, 4).
--define(N_NULL, 5).
--define(N_OBJECT_IDENTIFIER, 6).
--define(N_OBJECT_DESCRIPTOR, 7).
--define(N_EXTERNAL, 8). % constructed
--define(N_INSTANCE_OF,8).
--define(N_REAL, 9).
--define(N_ENUMERATED, 10).
--define(N_EMBEDDED_PDV, 11). % constructed
--define(N_SEQUENCE, 16).
--define(N_SET, 17).
--define(N_NumericString, 18).
--define(N_PrintableString, 19).
--define(N_TeletexString, 20).
--define(N_VideotexString, 21).
--define(N_IA5String, 22).
--define(N_UTCTime, 23).
--define(N_GeneralizedTime, 24).
--define(N_GraphicString, 25).
--define(N_VisibleString, 26).
--define(N_GeneralString, 27).
--define(N_UniversalString, 28).
--define(N_CHARACTER_STRING, 29). % constructed
--define(N_BMPString, 30).
-
--define(TAG_PRIMITIVE(Num),
- case S#state.erule of
- ber_bin_v2 ->
- #tag{class='UNIVERSAL',number=Num,type='IMPLICIT',form=0};
- _ -> []
- end).
--define(TAG_CONSTRUCTED(Num),
- case S#state.erule of
- ber_bin_v2 ->
- #tag{class='UNIVERSAL',number=Num,type='IMPLICIT',form=32};
- _ -> []
- end).
-
--record(newt,{type=unchanged,tag=unchanged,constraint=unchanged,inlined=no}). % used in check_type to update type and tag
--record(newv,{type=unchanged,value=unchanged}). % used in check_value to update type and value
-
-check(S,{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets}) ->
- %%Predicates used to filter errors
- TupleIs = fun({T,_},T) -> true;
- (_,_) -> false
- end,
- IsClass = fun(X) -> TupleIs(X,asn1_class) end,
- IsObjSet = fun(X) -> TupleIs(X,objectsetdef) end,
- IsPObjSet = fun(X) -> TupleIs(X,pobjectsetdef) end,
- IsObject = fun(X) -> TupleIs(X,objectdef) end,
- IsValueSet = fun(X) -> TupleIs(X,valueset) end,
- Element2 = fun(X) -> element(2,X) end,
-
- _Perror = checkp(S,ParameterizedTypes,[]), % must do this before the templates are used
- Terror = checkt(S,Types,[]),
-
- %% get parameterized object sets sent to checkt/3
- %% and update Terror
-
- {PObjSetNames1,Terror2} = filter_errors(IsPObjSet,Terror),
-
- Verror = checkv(S,Values ++ ObjectSets,[]), %value sets may be parsed as object sets
-
- %% get information object classes wrongly sent to checkt/3
- %% and update Terror2
-
- {AddClasses,Terror3} = filter_errors(IsClass,Terror2),
-
- NewClasses = Classes++AddClasses,
-
- Cerror = checkc(S,NewClasses,[]),
-
- %% get object sets incorrectly sent to checkv/3
- %% and update Verror
-
- {ObjSetNames,Verror2} = filter_errors(IsObjSet,Verror),
-
- %% get parameterized object sets incorrectly sent to checkv/3
- %% and update Verror2
-
- {PObjSetNames,Verror3} = filter_errors(IsPObjSet,Verror2),
-
- %% get objects incorrectly sent to checkv/3
- %% and update Verror3
-
- {ObjectNames,Verror4} = filter_errors(IsObject,Verror3),
-
- NewObjects = Objects++ObjectNames,
- NewObjectSets = ObjSetNames ++ PObjSetNames ++ PObjSetNames1,
-
- %% get value sets
- %% and update Verror4
-
- {ValueSetNames,Verror5} = filter_errors(IsValueSet,Verror4),
-
- asn1ct:create_ets_table(inlined_objects,[named_table]),
- {Oerror,ExclO,ExclOS} = checko(S,NewObjects ++
- NewObjectSets,
- [],[],[]),
- InlinedObjTuples = ets:tab2list(inlined_objects),
- InlinedObjects = lists:map(Element2,InlinedObjTuples),
- ets:delete(inlined_objects),
-
- Exporterror = check_exports(S,S#state.module),
- case {Terror3,Verror5,Cerror,Oerror,Exporterror} of
- {[],[],[],[],[]} ->
- ContextSwitchTs = context_switch_in_spec(),
- InstanceOf = instance_of_in_spec(),
- NewTypes = lists:subtract(Types,AddClasses) ++ ContextSwitchTs
- ++ InstanceOf,
- NewValues = lists:subtract(Values,PObjSetNames++ObjectNames++
- ValueSetNames),
- {ok,
- {NewTypes,NewValues,ParameterizedTypes,
- NewClasses,NewObjects,NewObjectSets},
- {NewTypes,NewValues,ParameterizedTypes,NewClasses,
- lists:subtract(NewObjects,ExclO)++InlinedObjects,
- lists:subtract(NewObjectSets,ExclOS)}};
- _ ->{error,{asn1,lists:flatten([Terror3,Verror5,Cerror,
- Oerror,Exporterror])}}
- end.
-
-context_switch_in_spec() ->
- L = [{external,'EXTERNAL'},
- {embedded_pdv,'EMBEDDED PDV'},
- {character_string,'CHARACTER STRING'}],
- F = fun({T,TName},Acc) ->
- case get(T) of
- generate -> erase(T),
- [TName|Acc];
- _ -> Acc
- end
- end,
- lists:foldl(F,[],L).
-
-instance_of_in_spec() ->
- case get(instance_of) of
- generate ->
- erase(instance_of),
- ['INSTANCE OF'];
- _ ->
- []
- end.
-
-filter_errors(Pred,ErrorList) ->
- Element2 = fun(X) -> element(2,X) end,
- RemovedTupleElements = lists:filter(Pred,ErrorList),
- RemovedNames = lists:map(Element2,RemovedTupleElements),
- %% remove value set name tuples from Verror
- RestErrors = lists:subtract(ErrorList,RemovedTupleElements),
- {RemovedNames,RestErrors}.
-
-
-check_exports(S,Module = #module{}) ->
- case Module#module.exports of
- {exports,[]} ->
- [];
- {exports,all} ->
- [];
- {exports,ExportList} when list(ExportList) ->
- IsNotDefined =
- fun(X) ->
- case catch get_referenced_type(S,X) of
- {error,{asn1,_}} ->
- true;
- _ -> false
- end
- end,
- case lists:filter(IsNotDefined,ExportList) of
- [] ->
- [];
- NoDefExp ->
- GetName =
- fun(T = #'Externaltypereference'{type=N})->
- %%{exported,undefined,entity,N}
- NewS=S#state{type=T,tname=N},
- error({export,"exported undefined entity",NewS})
- end,
- lists:map(GetName,NoDefExp)
- end
- end.
-
-checkt(S,[Name|T],Acc) ->
- %%io:format("check_typedef:~p~n",[Name]),
- Result =
- case asn1_db:dbget(S#state.mname,Name) of
- undefined ->
- error({type,{internal_error,'???'},S});
- Type when record(Type,typedef) ->
- NewS = S#state{type=Type,tname=Name},
- case catch(check_type(NewS,Type,Type#typedef.typespec)) of
- {error,Reason} ->
- error({type,Reason,NewS});
- {'EXIT',Reason} ->
- error({type,{internal_error,Reason},NewS});
- {asn1_class,_ClassDef} ->
- {asn1_class,Name};
- pobjectsetdef ->
- {pobjectsetdef,Name};
- pvalueset ->
- {pvalueset,Name};
- Ts ->
- case Type#typedef.checked of
- true -> % already checked and updated
- ok;
- _ ->
- NewTypeDef = Type#typedef{checked=true,typespec = Ts},
- %io:format("checkt:dbput:~p, ~p~n",[S#state.mname,NewTypeDef#typedef.name]),
- asn1_db:dbput(NewS#state.mname,Name,NewTypeDef), % update the type
- ok
- end
- end
- end,
- case Result of
- ok ->
- checkt(S,T,Acc);
- _ ->
- checkt(S,T,[Result|Acc])
- end;
-checkt(S,[],Acc) ->
- case check_contextswitchingtypes(S,[]) of
- [] ->
- lists:reverse(Acc);
- L ->
- checkt(S,L,Acc)
- end.
-
-check_contextswitchingtypes(S,Acc) ->
- CSTList=[{external,'EXTERNAL'},
- {embedded_pdv,'EMBEDDED PDV'},
- {character_string,'CHARACTER STRING'}],
- check_contextswitchingtypes(S,CSTList,Acc).
-
-check_contextswitchingtypes(S,[{T,TName}|Ts],Acc) ->
- case get(T) of
- unchecked ->
- put(T,generate),
- check_contextswitchingtypes(S,Ts,[TName|Acc]);
- _ ->
- check_contextswitchingtypes(S,Ts,Acc)
- end;
-check_contextswitchingtypes(_,[],Acc) ->
- Acc.
-
-checkv(S,[Name|T],Acc) ->
- %%io:format("check_valuedef:~p~n",[Name]),
- Result = case asn1_db:dbget(S#state.mname,Name) of
- undefined -> error({value,{internal_error,'???'},S});
- Value when record(Value,valuedef);
- record(Value,typedef); %Value set may be parsed as object set.
- record(Value,pvaluedef);
- record(Value,pvaluesetdef) ->
- NewS = S#state{value=Value},
- case catch(check_value(NewS,Value)) of
- {error,Reason} ->
- error({value,Reason,NewS});
- {'EXIT',Reason} ->
- error({value,{internal_error,Reason},NewS});
- {pobjectsetdef} ->
- {pobjectsetdef,Name};
- {objectsetdef} ->
- {objectsetdef,Name};
- {objectdef} ->
- %% this is an object, save as typedef
- #valuedef{checked=C,pos=Pos,name=N,type=Type,
- value=Def}=Value,
-% Currmod = S#state.mname,
-% #type{def=
-% #'Externaltypereference'{module=Mod,
-% type=CName}} = Type,
- ClassName =
- Type#type.def,
-% case Mod of
-% Currmod ->
-% {objectclassname,CName};
-% _ ->
-% {objectclassname,Mod,CName}
-% end,
- NewSpec = #'Object'{classname=ClassName,
- def=Def},
- NewDef = #typedef{checked=C,pos=Pos,name=N,
- typespec=NewSpec},
- asn1_db:dbput(NewS#state.mname,Name,NewDef),
- {objectdef,Name};
- {valueset,VSet} ->
- Pos = asn1ct:get_pos_of_def(Value),
- CheckedVSDef = #typedef{checked=true,pos=Pos,
- name=Name,typespec=VSet},
- asn1_db:dbput(NewS#state.mname,Name,CheckedVSDef),
- {valueset,Name};
- V ->
- %% update the valuedef
- asn1_db:dbput(NewS#state.mname,Name,V),
- ok
- end
- end,
- case Result of
- ok ->
- checkv(S,T,Acc);
- _ ->
- checkv(S,T,[Result|Acc])
- end;
-checkv(_S,[],Acc) ->
- lists:reverse(Acc).
-
-
-checkp(S,[Name|T],Acc) ->
- %io:format("check_ptypedef:~p~n",[Name]),
- Result = case asn1_db:dbget(S#state.mname,Name) of
- undefined ->
- error({type,{internal_error,'???'},S});
- Type when record(Type,ptypedef) ->
- NewS = S#state{type=Type,tname=Name},
- case catch(check_ptype(NewS,Type,Type#ptypedef.typespec)) of
- {error,Reason} ->
- error({type,Reason,NewS});
- {'EXIT',Reason} ->
- error({type,{internal_error,Reason},NewS});
- {asn1_class,_ClassDef} ->
- {asn1_class,Name};
- Ts ->
- NewType = Type#ptypedef{checked=true,typespec = Ts},
- asn1_db:dbput(NewS#state.mname,Name,NewType), % update the type
- ok
- end
- end,
- case Result of
- ok ->
- checkp(S,T,Acc);
- _ ->
- checkp(S,T,[Result|Acc])
- end;
-checkp(_S,[],Acc) ->
- lists:reverse(Acc).
-
-
-
-
-checkc(S,[Name|Cs],Acc) ->
- Result =
- case asn1_db:dbget(S#state.mname,Name) of
- undefined ->
- error({class,{internal_error,'???'},S});
- Class ->
- ClassSpec = if
- record(Class,classdef) ->
- Class#classdef.typespec;
- record(Class,typedef) ->
- Class#typedef.typespec
- end,
- NewS = S#state{type=Class,tname=Name},
- case catch(check_class(NewS,ClassSpec)) of
- {error,Reason} ->
- error({class,Reason,NewS});
- {'EXIT',Reason} ->
- error({class,{internal_error,Reason},NewS});
- C ->
- %% update the classdef
- NewClass =
- if
- record(Class,classdef) ->
- Class#classdef{checked=true,typespec=C};
- record(Class,typedef) ->
- #classdef{checked=true,name=Name,typespec=C}
- end,
- asn1_db:dbput(NewS#state.mname,Name,NewClass),
- ok
- end
- end,
- case Result of
- ok ->
- checkc(S,Cs,Acc);
- _ ->
- checkc(S,Cs,[Result|Acc])
- end;
-checkc(_S,[],Acc) ->
-%% include_default_class(S#state.mname),
- lists:reverse(Acc).
-
-checko(S,[Name|Os],Acc,ExclO,ExclOS) ->
- Result =
- case asn1_db:dbget(S#state.mname,Name) of
- undefined ->
- error({type,{internal_error,'???'},S});
- Object when record(Object,typedef) ->
- NewS = S#state{type=Object,tname=Name},
- case catch(check_object(NewS,Object,Object#typedef.typespec)) of
- {error,Reason} ->
- error({type,Reason,NewS});
- {'EXIT',Reason} ->
- error({type,{internal_error,Reason},NewS});
- {asn1,Reason} ->
- error({type,Reason,NewS});
- O ->
- NewObj = Object#typedef{checked=true,typespec=O},
- asn1_db:dbput(NewS#state.mname,Name,NewObj),
- if
- record(O,'Object') ->
- case O#'Object'.gen of
- true ->
- {ok,ExclO,ExclOS};
- false ->
- {ok,[Name|ExclO],ExclOS}
- end;
- record(O,'ObjectSet') ->
- case O#'ObjectSet'.gen of
- true ->
- {ok,ExclO,ExclOS};
- false ->
- {ok,ExclO,[Name|ExclOS]}
- end
- end
- end;
- PObject when record(PObject,pobjectdef) ->
- NewS = S#state{type=PObject,tname=Name},
- case (catch check_pobject(NewS,PObject)) of
- {error,Reason} ->
- error({type,Reason,NewS});
- {'EXIT',Reason} ->
- error({type,{internal_error,Reason},NewS});
- {asn1,Reason} ->
- error({type,Reason,NewS});
- PO ->
- NewPObj = PObject#pobjectdef{def=PO},
- asn1_db:dbput(NewS#state.mname,Name,NewPObj),
- {ok,[Name|ExclO],ExclOS}
- end;
- PObjSet when record(PObjSet,pvaluesetdef) ->
- %% this is a parameterized object set. Might be a parameterized
- %% value set, couldn't it?
- NewS = S#state{type=PObjSet,tname=Name},
- case (catch check_pobjectset(NewS,PObjSet)) of
- {error,Reason} ->
- error({type,Reason,NewS});
- {'EXIT',Reason} ->
- error({type,{internal_error,Reason},NewS});
- {asn1,Reason} ->
- error({type,Reason,NewS});
- POS ->
- %%NewPObjSet = PObjSet#pvaluesetdef{valueset=POS},
- asn1_db:dbput(NewS#state.mname,Name,POS),
- {ok,ExclO,[Name|ExclOS]}
- end
- end,
- case Result of
- {ok,NewExclO,NewExclOS} ->
- checko(S,Os,Acc,NewExclO,NewExclOS);
- _ ->
- checko(S,Os,[Result|Acc],ExclO,ExclOS)
- end;
-checko(_S,[],Acc,ExclO,ExclOS) ->
- {lists:reverse(Acc),lists:reverse(ExclO),lists:reverse(ExclOS)}.
-
-check_class(S,CDef=#classdef{checked=Ch,name=Name,typespec=TS}) ->
- case Ch of
- true -> TS;
- idle -> TS;
- _ ->
- NewCDef = CDef#classdef{checked=idle},
- asn1_db:dbput(S#state.mname,Name,NewCDef),
- CheckedTS = check_class(S,TS),
- asn1_db:dbput(S#state.mname,Name,
- NewCDef#classdef{checked=true,
- typespec=CheckedTS}),
- CheckedTS
- end;
-check_class(S = #state{mname=M,tname=T},ClassSpec)
- when record(ClassSpec,type) ->
- Def = ClassSpec#type.def,
- case Def of
- #'Externaltypereference'{module=M,type=T} ->
- #objectclass{fields=Def}; % in case of recursive definitions
- Tref when record(Tref,'Externaltypereference') ->
- {_,RefType} = get_referenced_type(S,Tref),
-% case RefType of
-% RefClass when record(RefClass,classdef) ->
-% check_class(S,RefClass#classdef.typespec)
-% end
- case is_class(S,RefType) of
- true ->
- check_class(S,get_class_def(S,RefType));
- _ ->
- error({class,{internal_error,RefType},S})
- end
- end;
-% check_class(S,{objectclassname,ModuleName,ClassName}) when atom(ModuleName),atom(ClassName) ->
-% 'fix this';
-check_class(S,C) when record(C,objectclass) ->
- NewFieldSpec = check_class_fields(S,C#objectclass.fields),
- C#objectclass{fields=NewFieldSpec};
-%check_class(S,{objectclassname,ClassName}) ->
-check_class(S,ClassName) ->
- {_,Def} = get_referenced_type(S,ClassName),
- case Def of
- ClassDef when record(ClassDef,classdef) ->
- case ClassDef#classdef.checked of
- true ->
- ClassDef#classdef.typespec;
- idle ->
- ClassDef#classdef.typespec;
- false ->
- check_class(S,ClassDef#classdef.typespec)
- end;
- TypeDef when record(TypeDef,typedef) ->
- %% this case may occur when a definition is a reference
- %% to a class definition.
- case TypeDef#typedef.typespec of
- #type{def=Ext} when record(Ext,'Externaltypereference') ->
- check_class(S,Ext)
- end
- end;
-check_class(_S,{poc,_ObjSet,_Params}) ->
- 'fix this later'.
-
-check_class_fields(S,Fields) ->
- check_class_fields(S,Fields,[]).
-
-check_class_fields(S,[F|Fields],Acc) ->
- NewField =
- case element(1,F) of
- fixedtypevaluefield ->
- {_,Name,Type,Unique,OSpec} = F,
- RefType = check_type(S,#typedef{typespec=Type},Type),
- {fixedtypevaluefield,Name,RefType,Unique,OSpec};
- object_or_fixedtypevalue_field ->
- {_,Name,Type,Unique,OSpec} = F,
- Cat =
- case asn1ct_gen:type(asn1ct_gen:get_inner(Type#type.def)) of
- Def when record(Def,typereference);
- record(Def,'Externaltypereference') ->
- {_,D} = get_referenced_type(S,Def),
- D;
- {undefined,user} ->
- %% neither of {primitive,bif} or {constructed,bif}
-%% {_,D} = get_referenced_type(S,#typereference{val=Type#type.def}),
- {_,D} = get_referenced_type(S,#'Externaltypereference'{module=S#state.mname,type=Type#type.def}),
- D;
- _ ->
- Type
- end,
- case Cat of
- Class when record(Class,classdef) ->
- {objectfield,Name,Type,Unique,OSpec};
- _ ->
- RefType = check_type(S,#typedef{typespec=Type},Type),
- {fixedtypevaluefield,Name,RefType,Unique,OSpec}
- end;
- objectset_or_fixedtypevalueset_field ->
- {_,Name,Type,OSpec} = F,
-%% RefType = check_type(S,#typedef{typespec=Type},Type),
- RefType =
- case (catch check_type(S,#typedef{typespec=Type},Type)) of
- {asn1_class,_ClassDef} ->
- case if_current_checked_type(S,Type) of
- true ->
- Type#type.def;
- _ ->
- check_class(S,Type)
- end;
- CheckedType when record(CheckedType,type) ->
- CheckedType;
- _ ->
- error({class,"internal error, check_class_fields",S})
- end,
- if
- record(RefType,'Externaltypereference') ->
- {objectsetfield,Name,Type,OSpec};
- record(RefType,classdef) ->
- {objectsetfield,Name,Type,OSpec};
- record(RefType,objectclass) ->
- {objectsetfield,Name,Type,OSpec};
- true ->
- {fixedtypevaluesetfield,Name,RefType,OSpec}
- end;
- typefield ->
- case F of
- {TF,Name,{'DEFAULT',Type}} ->
- {TF,Name,{'DEFAULT',check_type(S,#typedef{typespec=Type},Type)}};
- _ -> F
- end;
- _ -> F
- end,
- check_class_fields(S,Fields,[NewField|Acc]);
-check_class_fields(_S,[],Acc) ->
- lists:reverse(Acc).
-
-if_current_checked_type(S,#type{def=Def}) ->
- CurrentCheckedName = S#state.tname,
- MergedModules = S#state.inputmodules,
- % CurrentCheckedModule = S#state.mname,
- case Def of
- #'Externaltypereference'{module=CurrentCheckedName,
- type=CurrentCheckedName} ->
- true;
- #'Externaltypereference'{module=ModuleName,
- type=CurrentCheckedName} ->
- case MergedModules of
- undefined ->
- false;
- _ ->
- lists:member(ModuleName,MergedModules)
- end;
- _ ->
- false
- end.
-
-
-
-check_pobject(_S,PObject) when record(PObject,pobjectdef) ->
- Def = PObject#pobjectdef.def,
- Def.
-
-
-check_pobjectset(S,PObjSet) ->
- #pvaluesetdef{pos=Pos,name=Name,args=Args,type=Type,
- valueset=ValueSet}=PObjSet,
- {Mod,Def} = get_referenced_type(S,Type#type.def),
- case Def of
- #classdef{} ->
- ClassName = #'Externaltypereference'{module=Mod,
- type=Def#classdef.name},
- {valueset,Set} = ValueSet,
-% ObjectSet = #'ObjectSet'{class={objectclassname,ClassName},
- ObjectSet = #'ObjectSet'{class=ClassName,
- set=Set},
- #pobjectsetdef{pos=Pos,name=Name,args=Args,class=Type#type.def,
- def=ObjectSet};
- _ ->
- PObjSet
- end.
-
-check_object(_S,ObjDef,ObjSpec) when (ObjDef#typedef.checked == true) ->
- ObjSpec;
-check_object(S,_ObjDef,#'Object'{classname=ClassRef,def=ObjectDef}) ->
- {_,_ClassDef} = get_referenced_type(S,ClassRef),
- NewClassRef = check_externaltypereference(S,ClassRef),
- ClassDef =
- case _ClassDef#classdef.checked of
- false ->
- #classdef{checked=true,
- typespec=check_class(S,_ClassDef#classdef.typespec)};
- _ ->
- _ClassDef
- end,
- NewObj =
- case ObjectDef of
- Def when tuple(Def), (element(1,Def)==object) ->
- NewSettingList = check_objectdefn(S,Def,ClassDef),
- #'Object'{def=NewSettingList};
-% Def when tuple(Def), (element(1,Def)=='ObjectFromObject') ->
-% fixa;
- {po,{object,DefObj},ArgsList} ->
- {_,Object} = get_referenced_type(S,DefObj),%DefObj is a
- %%#'Externalvaluereference' or a #'Externaltypereference'
- %% Maybe this call should be catched and in case of an exception
- %% an nonallocated parameterized object should be returned.
- instantiate_po(S,ClassDef,Object,ArgsList);
- #'Externalvaluereference'{} ->
- {_,Object} = get_referenced_type(S,ObjectDef),
- check_object(S,Object,Object#typedef.typespec);
- _ ->
- exit({error,{no_object,ObjectDef},S})
- end,
- Gen = gen_incl(S,NewObj#'Object'.def,
- (ClassDef#classdef.typespec)#objectclass.fields),
- NewObj#'Object'{classname=NewClassRef,gen=Gen};
-
-%%check_object(S,ObjSetDef,ObjSet=#type{def={pt,ObjSetRef,Args}}) ->
- %% A parameterized
-
-check_object(S,
- _ObjSetDef,
- ObjSet=#'ObjectSet'{class=ClassRef}) ->
- {_,ClassDef} = get_referenced_type(S,ClassRef),
- NewClassRef = check_externaltypereference(S,ClassRef),
- UniqueFieldName =
- case (catch get_unique_fieldname(ClassDef)) of
- {error,'__undefined_'} -> {unique,undefined};
- {asn1,Msg,_} -> error({class,Msg,S});
- Other -> Other
- end,
- NewObjSet=
- case ObjSet#'ObjectSet'.set of
- {'SingleValue',Set} when list(Set) ->
- CheckedSet = check_object_list(S,NewClassRef,Set),
- NewSet = get_unique_valuelist(S,CheckedSet,UniqueFieldName),
- ObjSet#'ObjectSet'{uniquefname=UniqueFieldName,
- set=NewSet};
- {'SingleValue',{definedvalue,ObjName}} ->
- {_,ObjDef} = get_referenced_type(S,#identifier{val=ObjName}),
- #'Object'{def=CheckedObj} =
- check_object(S,ObjDef,ObjDef#typedef.typespec),
- NewSet = get_unique_valuelist(S,[{ObjDef#typedef.name,
- CheckedObj}],
- UniqueFieldName),
- ObjSet#'ObjectSet'{uniquefname=UniqueFieldName,
- set=NewSet};
- {'SingleValue',#'Externalvaluereference'{value=ObjName}} ->
- {_,ObjDef} = get_referenced_type(S,#identifier{val=ObjName}),
- #'Object'{def=CheckedObj} =
- check_object(S,ObjDef,ObjDef#typedef.typespec),
- NewSet = get_unique_valuelist(S,[{ObjDef#typedef.name,
- CheckedObj}],
- UniqueFieldName),
- ObjSet#'ObjectSet'{uniquefname=UniqueFieldName,
- set=NewSet};
- ['EXTENSIONMARK'] ->
- ObjSet#'ObjectSet'{uniquefname=UniqueFieldName,
- set=['EXTENSIONMARK']};
- Set when list(Set) ->
- CheckedSet = check_object_list(S,NewClassRef,Set),
- NewSet = get_unique_valuelist(S,CheckedSet,UniqueFieldName),
- ObjSet#'ObjectSet'{uniquefname=UniqueFieldName,
- set=NewSet};
- {Set,Ext} when list(Set) ->
- CheckedSet = check_object_list(S,NewClassRef,Set++Ext),
- NewSet = get_unique_valuelist(S,CheckedSet,UniqueFieldName),
- ObjSet#'ObjectSet'{uniquefname=UniqueFieldName,
- set=NewSet++['EXTENSIONMARK']};
- {{'SingleValue',Set},Ext} ->
- CheckedSet = check_object_list(S,NewClassRef,
- merge_sets(Set,Ext)),
- NewSet = get_unique_valuelist(S,CheckedSet,UniqueFieldName),
- ObjSet#'ObjectSet'{uniquefname=UniqueFieldName,
- set=NewSet++['EXTENSIONMARK']};
- {Type,{'EXCEPT',Exclusion}} when record(Type,type) ->
- {_,TDef} = get_referenced_type(S,Type#type.def),
- OS = TDef#typedef.typespec,
- NewSet = reduce_objectset(OS#'ObjectSet'.set,Exclusion),
- NewOS = OS#'ObjectSet'{set=NewSet},
- check_object(S,TDef#typedef{typespec=NewOS},
- NewOS);
- #type{def={pt,DefinedObjSet,ParamList}} ->
- {_,PObjSetDef} = get_referenced_type(S,DefinedObjSet),
- instantiate_pos(S,ClassDef,PObjSetDef,ParamList);
- {ObjDef={object,definedsyntax,_ObjFields},_Ext} ->
- CheckedSet = check_object_list(S,NewClassRef,[ObjDef]),
- NewSet = get_unique_valuelist(S,CheckedSet,UniqueFieldName),
- ObjSet#'ObjectSet'{uniquefname=UniqueFieldName,
- set=NewSet++['EXTENSIONMARK']}
- end,
- Gen = gen_incl_set(S,NewObjSet#'ObjectSet'.set,
- ClassDef),
- NewObjSet#'ObjectSet'{class=NewClassRef,gen=Gen}.
-
-
-merge_sets(Set,Ext) when list(Set),list(Ext) ->
- Set ++ Ext;
-merge_sets(Set,Ext) when list(Ext) ->
- [Set|Ext];
-merge_sets(Set,{'SingleValue',Ext}) when list(Set) ->
- Set ++ [Ext];
-merge_sets(Set,{'SingleValue',Ext}) ->
- [Set] ++ [Ext].
-
-reduce_objectset(ObjectSet,Exclusion) ->
- case Exclusion of
- {'SingleValue',#'Externalvaluereference'{value=Name}} ->
- case lists:keysearch(Name,1,ObjectSet) of
- {value,El} ->
- lists:subtract(ObjectSet,[El]);
- _ ->
- ObjectSet
- end
- end.
-
-%% Checks a list of objects or object sets and returns a list of selected
-%% information for the code generation.
-check_object_list(S,ClassRef,ObjectList) ->
- check_object_list(S,ClassRef,ObjectList,[]).
-
-check_object_list(S,ClassRef,[ObjOrSet|Objs],Acc) ->
- case ObjOrSet of
- ObjDef when tuple(ObjDef),(element(1,ObjDef)==object) ->
- Def =
- check_object(S,#typedef{typespec=ObjDef},
-% #'Object'{classname={objectclassname,ClassRef},
- #'Object'{classname=ClassRef,
- def=ObjDef}),
- check_object_list(S,ClassRef,Objs,[{no_name,Def#'Object'.def}|Acc]);
- {'SingleValue',{definedvalue,ObjName}} ->
- {_,ObjectDef} = get_referenced_type(S,#identifier{val=ObjName}),
- #'Object'{def=Def} = check_object(S,ObjectDef,ObjectDef#typedef.typespec),
- check_object_list(S,ClassRef,Objs,[{ObjectDef#typedef.name,Def}|Acc]);
- {'SingleValue',Ref = #'Externalvaluereference'{}} ->
- {_,ObjectDef} = get_referenced_type(S,Ref),
- #'Object'{def=Def} = check_object(S,ObjectDef,ObjectDef#typedef.typespec),
- check_object_list(S,ClassRef,Objs,[{ObjectDef#typedef.name,Def}|Acc]);
- ObjRef when record(ObjRef,'Externalvaluereference') ->
- {_,ObjectDef} = get_referenced_type(S,ObjRef),
- #'Object'{def=Def} = check_object(S,ObjectDef,ObjectDef#typedef.typespec),
- check_object_list(S,ClassRef,Objs,
-%% [{ObjRef#'Externalvaluereference'.value,Def}|Acc]);
- [{ObjectDef#typedef.name,Def}|Acc]);
- {'ValueFromObject',{_,Object},FieldName} ->
- {_,Def} = get_referenced_type(S,Object),
-%% TypeOrVal = get_fieldname_element(S,Def,FieldName);%% this must result in an object set
- TypeDef = get_fieldname_element(S,Def,FieldName),
- (TypeDef#typedef.typespec)#'ObjectSet'.set;
- ObjSet when record(ObjSet,type) ->
- ObjSetDef =
- case ObjSet#type.def of
- Ref when record(Ref,typereference);
- record(Ref,'Externaltypereference') ->
- {_,D} = get_referenced_type(S,ObjSet#type.def),
- D;
- Other ->
- throw({asn1_error,{'unknown objecset',Other,S}})
- end,
- #'ObjectSet'{set=ObjectsInSet} =
- check_object(S,ObjSetDef,ObjSetDef#typedef.typespec),
- AccList = transform_set_to_object_list(ObjectsInSet,[]),
- check_object_list(S,ClassRef,Objs,AccList++Acc);
- union ->
- check_object_list(S,ClassRef,Objs,Acc);
- Other ->
- exit({error,{'unknown object',Other},S})
- end;
-%% Finally reverse the accumulated list and if there are any extension
-%% marks in the object set put one indicator of that in the end of the
-%% list.
-check_object_list(_,_,[],Acc) ->
- lists:reverse(Acc).
-%% case lists:member('EXTENSIONMARK',RevAcc) of
-%% true ->
-%% ExclRevAcc = lists:filter(fun(X)->X /= 'EXTENSIONMARK' end,
-%% RevAcc),
-%% ExclRevAcc ++ ['EXTENSIONMARK'];
-%% false ->
-%% RevAcc
-%% end.
-
-
-%% get_fieldname_element/3
-%% gets the type/value/object/... of the referenced element in FieldName
-%% FieldName is a list and may have more than one element.
-%% Each element in FieldName can be either {typefieldreference,AnyFieldName}
-%% or {valuefieldreference,AnyFieldName}
-%% Def is the def of the first object referenced by FieldName
-get_fieldname_element(S,Def,[{_RefType,FieldName}]) when record(Def,typedef) ->
- {_,_,ObjComps} = (Def#typedef.typespec)#'Object'.def,
- case lists:keysearch(FieldName,1,ObjComps) of
- {value,{_,TDef}} when record(TDef,typedef) ->
- %% ORec = TDef#typedef.typespec, %% XXX This must be made general
-% case TDef#typedef.typespec of
-% ObjSetRec when record(ObjSetRec,'ObjectSet') ->
-% ObjSet = ObjSetRec#'ObjectSet'.set;
-% ObjRec when record(ObjRec,'Object') ->
-% %% now get the field in ObjRec that RestFName points out
-% %ObjRec
-% TDef
-% end;
- TDef;
- {value,{_,VDef}} when record(VDef,valuedef) ->
- check_value(S,VDef);
- _ ->
- throw({assigned_object_error,"not_assigned_object",S})
- end;
-get_fieldname_element(_S,Def,[{_RefType,_FieldName}|_RestFName])
- when record(Def,typedef) ->
- ok.
-
-transform_set_to_object_list([{Name,_UVal,Fields}|Objs],Acc) ->
- transform_set_to_object_list(Objs,[{Name,{object,generatesyntax,Fields}}|Acc]);
-transform_set_to_object_list(['EXTENSIONMARK'|Objs],Acc) ->
-%% transform_set_to_object_list(Objs,['EXTENSIONMARK'|Acc]);
- transform_set_to_object_list(Objs,Acc);
-transform_set_to_object_list([],Acc) ->
- Acc.
-
-get_unique_valuelist(_S,ObjSet,{unique,undefined}) -> % no unique field in object
- lists:map(fun({N,{_,_,F}})->{N,F};
- (V={_,_,_}) ->V end, ObjSet);
-get_unique_valuelist(S,ObjSet,UFN) ->
- get_unique_vlist(S,ObjSet,UFN,[]).
-
-get_unique_vlist(S,[],_,Acc) ->
- case catch check_uniqueness(Acc) of
- {asn1_error,_} ->
-% exit({error,Reason,S});
- error({'ObjectSet',"not unique objects in object set",S});
- true ->
- lists:reverse(Acc)
- end;
-get_unique_vlist(S,[{ObjName,Obj}|Rest],UniqueFieldName,Acc) ->
- {_,_,Fields} = Obj,
- VDef = get_unique_value(S,Fields,UniqueFieldName),
- get_unique_vlist(S,Rest,UniqueFieldName,
- [{ObjName,VDef#valuedef.value,Fields}|Acc]);
-get_unique_vlist(S,[V={_,_,_}|Rest],UniqueFieldName,Acc) ->
- get_unique_vlist(S,Rest,UniqueFieldName,[V|Acc]).
-
-get_unique_value(S,Fields,UniqueFieldName) ->
- Module = S#state.mname,
- case lists:keysearch(UniqueFieldName,1,Fields) of
- {value,Field} ->
- case element(2,Field) of
- VDef when record(VDef,valuedef) ->
- VDef;
- {definedvalue,ValName} ->
- ValueDef = asn1_db:dbget(Module,ValName),
- case ValueDef of
- VDef when record(VDef,valuedef) ->
- ValueDef;
- undefined ->
- #valuedef{value=ValName}
- end;
- {'ValueFromObject',Object,Name} ->
- case Object of
- {object,Ext} when record(Ext,'Externaltypereference') ->
- OtherModule = Ext#'Externaltypereference'.module,
- ExtObjName = Ext#'Externaltypereference'.type,
- ObjDef = asn1_db:dbget(OtherModule,ExtObjName),
- ObjSpec = ObjDef#typedef.typespec,
- get_unique_value(OtherModule,element(3,ObjSpec),Name);
- {object,{_,_,ObjName}} ->
- ObjDef = asn1_db:dbget(Module,ObjName),
- ObjSpec = ObjDef#typedef.typespec,
- get_unique_value(Module,element(3,ObjSpec),Name);
- {po,Object,_Params} ->
- exit({error,{'parameterized object not implemented yet',
- Object},S})
- end;
- Value when atom(Value);number(Value) ->
- #valuedef{value=Value};
- {'CHOICE',{_,Value}} when atom(Value);number(Value) ->
- #valuedef{value=Value}
- end;
- false ->
- exit({error,{'no unique value',Fields,UniqueFieldName},S})
-%% io:format("WARNING: no unique value in object"),
-%% exit(uniqueFieldName)
- end.
-
-check_uniqueness(NameValueList) ->
- check_uniqueness1(lists:keysort(2,NameValueList)).
-
-check_uniqueness1([]) ->
- true;
-check_uniqueness1([_]) ->
- true;
-check_uniqueness1([{_,N,_},{_,N,_}|_Rest]) ->
- throw({asn1_error,{'objects in set must have unique values in UNIQUE fields',N}});
-check_uniqueness1([_|Rest]) ->
- check_uniqueness1(Rest).
-
-%% instantiate_po/4
-%% ClassDef is the class of Object,
-%% Object is the Parameterized object, which is referenced,
-%% ArgsList is the list of actual parameters
-%% returns an #'Object' record.
-instantiate_po(S,_ClassDef,Object,ArgsList) when record(Object,pobjectdef) ->
- FormalParams = get_pt_args(Object),
- MatchedArgs = match_args(FormalParams,ArgsList,[]),
- NewS = S#state{type=Object,parameters=MatchedArgs},
- check_object(NewS,Object,#'Object'{classname=Object#pobjectdef.class,
- def=Object#pobjectdef.def}).
-
-%% instantiate_pos/4
-%% ClassDef is the class of ObjectSetDef,
-%% ObjectSetDef is the Parameterized object set, which is referenced
-%% on the right side of the assignment,
-%% ArgsList is the list of actual parameters, i.e. real objects
-instantiate_pos(S,ClassDef,ObjectSetDef,ArgsList) ->
- ClassName = ClassDef#classdef.name,
- FormalParams = get_pt_args(ObjectSetDef),
- Set = case get_pt_spec(ObjectSetDef) of
- {valueset,_Set} -> _Set;
- _Set -> _Set
- end,
- MatchedArgs = match_args(FormalParams,ArgsList,[]),
- NewS = S#state{type=ObjectSetDef,parameters=MatchedArgs},
- check_object(NewS,ObjectSetDef,
- #'ObjectSet'{class=name2Extref(S#state.mname,ClassName),
- set=Set}).
-
-
-%% gen_incl -> boolean()
-%% If object with Fields has any of the corresponding class' typefields
-%% then return value is true otherwise it is false.
-%% If an object lacks a typefield but the class has a type field that
-%% is OPTIONAL then we want gen to be true
-gen_incl(S,{_,_,Fields},CFields)->
- gen_incl1(S,Fields,CFields).
-
-gen_incl1(_,_,[]) ->
- false;
-gen_incl1(S,Fields,[C|CFields]) ->
- case element(1,C) of
- typefield ->
-% case lists:keymember(element(2,C),1,Fields) of
-% true ->
-% true;
-% false ->
-% gen_incl1(S,Fields,CFields)
-% end;
- true; %% should check that field is OPTIONAL or DEFUALT if
- %% the object lacks this field
- objectfield ->
- case lists:keysearch(element(2,C),1,Fields) of
- {value,Field} ->
- Type = element(3,C),
- {_,ClassDef} = get_referenced_type(S,Type#type.def),
-% {_,ClassFields,_} = ClassDef#classdef.typespec,
- #objectclass{fields=ClassFields} =
- ClassDef#classdef.typespec,
- ObjTDef = element(2,Field),
- case gen_incl(S,(ObjTDef#typedef.typespec)#'Object'.def,
- ClassFields) of
- true ->
- true;
- _ ->
- gen_incl1(S,Fields,CFields)
- end;
- _ ->
- gen_incl1(S,Fields,CFields)
- end;
- _ ->
- gen_incl1(S,Fields,CFields)
- end.
-
-%% first if no unique field in the class return false.(don't generate code)
-gen_incl_set(S,Fields,ClassDef) ->
- case catch get_unique_fieldname(ClassDef) of
- Tuple when tuple(Tuple) ->
- false;
- _ ->
- gen_incl_set1(S,Fields,
- (ClassDef#classdef.typespec)#objectclass.fields)
- end.
-
-%% if any of the existing or potentially existing objects has a typefield
-%% then return true.
-gen_incl_set1(_,[],_CFields)->
- false;
-gen_incl_set1(_,['EXTENSIONMARK'],_) ->
- true;
-%% Fields are the fields of an object in the object set.
-%% CFields are the fields of the class of the object set.
-gen_incl_set1(S,[Object|Rest],CFields)->
- Fields = element(size(Object),Object),
- case gen_incl1(S,Fields,CFields) of
- true ->
- true;
- false ->
- gen_incl_set1(S,Rest,CFields)
- end.
-
-check_objectdefn(S,Def,CDef) when record(CDef,classdef) ->
- WithSyntax = (CDef#classdef.typespec)#objectclass.syntax,
- ClassFields = (CDef#classdef.typespec)#objectclass.fields,
- case Def of
- {object,defaultsyntax,Fields} ->
- check_defaultfields(S,Fields,ClassFields);
- {object,definedsyntax,Fields} ->
- {_,WSSpec} = WithSyntax,
- NewFields =
- case catch( convert_definedsyntax(S,Fields,WSSpec,
- ClassFields,[])) of
- {asn1,{_ErrorType,ObjToken,ClassToken}} ->
- throw({asn1,{'match error in object',ObjToken,
- 'found in object',ClassToken,'found in class'}});
- Err={asn1,_} -> throw(Err);
- Err={'EXIT',_} -> throw(Err);
- DefaultFields when list(DefaultFields) ->
- DefaultFields
- end,
- {object,defaultsyntax,NewFields};
- {object,_ObjectId} -> % This is a DefinedObject
- fixa;
- Other ->
- exit({error,{objectdefn,Other}})
- end.
-
-check_defaultfields(S,Fields,ClassFields) ->
- check_defaultfields(S,Fields,ClassFields,[]).
-
-check_defaultfields(_S,[],_ClassFields,Acc) ->
- {object,defaultsyntax,lists:reverse(Acc)};
-check_defaultfields(S,[{FName,Spec}|Fields],ClassFields,Acc) ->
- case lists:keysearch(FName,2,ClassFields) of
- {value,CField} ->
- NewField = convert_to_defaultfield(S,FName,Spec,CField),
- check_defaultfields(S,Fields,ClassFields,[NewField|Acc]);
- _ ->
- throw({error,{asn1,{'unvalid field in object',FName}}})
- end.
-%% {object,defaultsyntax,Fields}.
-
-convert_definedsyntax(_S,[],[],_ClassFields,Acc) ->
- lists:reverse(Acc);
-convert_definedsyntax(S,Fields,WithSyntax,ClassFields,Acc) ->
- case match_field(S,Fields,WithSyntax,ClassFields) of
- {MatchedField,RestFields,RestWS} ->
- if
- list(MatchedField) ->
- convert_definedsyntax(S,RestFields,RestWS,ClassFields,
- lists:append(MatchedField,Acc));
- true ->
- convert_definedsyntax(S,RestFields,RestWS,ClassFields,
- [MatchedField|Acc])
- end
-%% throw({error,{asn1,{'unvalid syntax in object',WorS}}})
- end.
-
-match_field(S,Fields,WithSyntax,ClassFields) ->
- match_field(S,Fields,WithSyntax,ClassFields,[]).
-
-match_field(S,Fields,[W|Ws],ClassFields,Acc) when list(W) ->
- case catch(match_optional_field(S,Fields,W,ClassFields,[])) of
- {'EXIT',_} ->
- match_field(Fields,Ws,ClassFields,Acc); %% add S
-%% {[Result],RestFields} ->
-%% {Result,RestFields,Ws};
- {Result,RestFields} when list(Result) ->
- {Result,RestFields,Ws};
- _ ->
- match_field(S,Fields,Ws,ClassFields,Acc)
- end;
-match_field(S,Fields,WithSyntax,ClassFields,_Acc) ->
- match_mandatory_field(S,Fields,WithSyntax,ClassFields,[]).
-
-match_optional_field(_S,RestFields,[],_,Ret) ->
- {Ret,RestFields};
-%% An additional optional field within an optional field
-match_optional_field(S,Fields,[W|Ws],ClassFields,Ret) when list(W) ->
- case catch match_optional_field(S,Fields,W,ClassFields,[]) of
- {'EXIT',_} ->
- {Ret,Fields};
- {asn1,{optional_matcherror,_,_}} ->
- {Ret,Fields};
- {OptionalField,RestFields} ->
- match_optional_field(S,RestFields,Ws,ClassFields,
- lists:append(OptionalField,Ret))
- end;
-%% identify and skip word
-%match_optional_field(S,[#'Externaltypereference'{type=WorS}|Rest],
-match_optional_field(S,[{_,_,WorS}|Rest],
- [WorS|Ws],ClassFields,Ret) ->
- match_optional_field(S,Rest,Ws,ClassFields,Ret);
-match_optional_field(S,[],_,ClassFields,Ret) ->
- match_optional_field(S,[],[],ClassFields,Ret);
-%% identify and skip comma
-match_optional_field(S,[{WorS,_}|Rest],[{WorS,_}|Ws],ClassFields,Ret) ->
- match_optional_field(S,Rest,Ws,ClassFields,Ret);
-%% identify and save field data
-match_optional_field(S,[Setting|Rest],[{_,W}|Ws],ClassFields,Ret) ->
- WorS =
- case Setting of
- Type when record(Type,type) -> Type;
-%% #'Externalvaluereference'{value=WordOrSetting} -> WordOrSetting;
- {'ValueFromObject',_,_} -> Setting;
- {object,_,_} -> Setting;
- {_,_,WordOrSetting} -> WordOrSetting;
-%% Atom when atom(Atom) -> Atom
- Other -> Other
- end,
- case lists:keysearch(W,2,ClassFields) of
- false ->
- throw({asn1,{optional_matcherror,WorS,W}});
- {value,CField} ->
- NewField = convert_to_defaultfield(S,W,WorS,CField),
- match_optional_field(S,Rest,Ws,ClassFields,[NewField|Ret])
- end;
-match_optional_field(_S,[WorS|_Rest],[W|_Ws],_ClassFields,_Ret) ->
- throw({asn1,{optional_matcherror,WorS,W}}).
-
-match_mandatory_field(_S,[],[],_,[Acc]) ->
- {Acc,[],[]};
-match_mandatory_field(_S,[],[],_,Acc) ->
- {Acc,[],[]};
-match_mandatory_field(S,[],[H|T],CF,Acc) when list(H) ->
- match_mandatory_field(S,[],T,CF,Acc);
-match_mandatory_field(_S,[],WithSyntax,_,_Acc) ->
- throw({asn1,{mandatory_matcherror,[],WithSyntax}});
-%match_mandatory_field(_S,Fields,WithSyntax=[W|_Ws],_ClassFields,[Acc]) when list(W) ->
-match_mandatory_field(_S,Fields,WithSyntax=[W|_Ws],_ClassFields,Acc) when list(W), length(Acc) >= 1 ->
- {Acc,Fields,WithSyntax};
-%% identify and skip word
-match_mandatory_field(S,[{_,_,WorS}|Rest],
- [WorS|Ws],ClassFields,Acc) ->
- match_mandatory_field(S,Rest,Ws,ClassFields,Acc);
-%% identify and skip comma
-match_mandatory_field(S,[{WorS,_}|Rest],[{WorS,_}|Ws],ClassFields,Ret) ->
- match_mandatory_field(S,Rest,Ws,ClassFields,Ret);
-%% identify and save field data
-match_mandatory_field(S,[Setting|Rest],[{_,W}|Ws],ClassFields,Acc) ->
- WorS =
- case Setting of
-%% Atom when atom(Atom) -> Atom;
-%% #'Externalvaluereference'{value=WordOrSetting} -> WordOrSetting;
- {object,_,_} -> Setting;
- {_,_,WordOrSetting} -> WordOrSetting;
- Type when record(Type,type) -> Type;
- Other -> Other
- end,
- case lists:keysearch(W,2,ClassFields) of
- false ->
- throw({asn1,{mandatory_matcherror,WorS,W}});
- {value,CField} ->
- NewField = convert_to_defaultfield(S,W,WorS,CField),
- match_mandatory_field(S,Rest,Ws,ClassFields,[NewField|Acc])
- end;
-
-match_mandatory_field(_S,[WorS|_Rest],[W|_Ws],_ClassFields,_Acc) ->
- throw({asn1,{mandatory_matcherror,WorS,W}}).
-
-%% Converts a field of an object from defined syntax to default syntax
-convert_to_defaultfield(S,ObjFieldName,ObjFieldSetting,CField)->
- CurrMod = S#state.mname,
- case element(1,CField) of
- typefield ->
- TypeDef=
- case ObjFieldSetting of
- TypeRec when record(TypeRec,type) -> TypeRec#type.def;
- TDef when record(TDef,typedef) ->
- TDef#typedef{typespec=check_type(S,TDef,
- TDef#typedef.typespec)};
- _ -> ObjFieldSetting
- end,
- Type =
- if
- record(TypeDef,typedef) -> TypeDef;
- true ->
- case asn1ct_gen:type(asn1ct_gen:get_inner(TypeDef)) of
- ERef = #'Externaltypereference'{module=CurrMod} ->
- {_,T} = get_referenced_type(S,ERef),
- T#typedef{checked=true,
- typespec=check_type(S,T,
- T#typedef.typespec)};
- ERef = #'Externaltypereference'{module=ExtMod} ->
- {_,T} = get_referenced_type(S,ERef),
- #typedef{name=Name} = T,
- check_type(S,T,T#typedef.typespec),
- #typedef{checked=true,
- name={ExtMod,Name},
- typespec=ERef};
- Bif when Bif=={primitive,bif};Bif=={constructed,bif} ->
- T = check_type(S,#typedef{typespec=ObjFieldSetting},
- ObjFieldSetting),
- #typedef{checked=true,name=Bif,typespec=T};
- _ ->
- {Mod,T} =
- %% get_referenced_type(S,#typereference{val=ObjFieldSetting}),
- get_referenced_type(S,#'Externaltypereference'{module=S#state.mname,type=ObjFieldSetting}),
- case Mod of
- CurrMod ->
- T;
- ExtMod ->
- #typedef{name=Name} = T,
- T#typedef{name={ExtMod,Name}}
- end
- end
- end,
- {ObjFieldName,Type};
- fixedtypevaluefield ->
- case ObjFieldName of
- Val when atom(Val) ->
- %% ObjFieldSetting can be a value,an objectidentifiervalue,
- %% an element in an enumeration or namednumberlist etc.
- ValRef =
- case ObjFieldSetting of
- #'Externalvaluereference'{} -> ObjFieldSetting;
- {'ValueFromObject',{_,ObjRef},FieldName} ->
- {_,Object} = get_referenced_type(S,ObjRef),
- ChObject = check_object(S,Object,
- Object#typedef.typespec),
- get_fieldname_element(S,Object#typedef{typespec=ChObject},
- FieldName);
- #valuedef{} ->
- ObjFieldSetting;
- _ ->
- #identifier{val=ObjFieldSetting}
- end,
- case ValRef of
- #valuedef{} ->
- {ObjFieldName,check_value(S,ValRef)};
- _ ->
- ValDef =
- case catch get_referenced_type(S,ValRef) of
- {error,_} ->
- check_value(S,#valuedef{name=Val,
- type=element(3,CField),
- value=ObjFieldSetting});
- {_,VDef} when record(VDef,valuedef) ->
- check_value(S,VDef);%% XXX
- {_,VDef} ->
- check_value(S,#valuedef{name=Val,
- type=element(3,CField),
- value=VDef})
- end,
- {ObjFieldName,ValDef}
- end;
- Val ->
- {ObjFieldName,Val}
- end;
- fixedtypevaluesetfield ->
- {ObjFieldName,ObjFieldSetting};
- objectfield ->
- ObjectSpec =
- case ObjFieldSetting of
- Ref when record(Ref,typereference);record(Ref,identifier);
- record(Ref,'Externaltypereference');
- record(Ref,'Externalvaluereference') ->
- {_,R} = get_referenced_type(S,ObjFieldSetting),
- R;
- {'ValueFromObject',{_,ObjRef},FieldName} ->
- %% This is an ObjectFromObject
- {_,Object} = get_referenced_type(S,ObjRef),
- ChObject = check_object(S,Object,
- Object#typedef.typespec),
- _ObjFromObj=
- get_fieldname_element(S,Object#typedef{
- typespec=ChObject},
- FieldName);
- %%ClassName = ObjFromObj#'Object'.classname,
- %%#typedef{name=,
- %% typespec=
- %% ObjFromObj#'Object'{classname=
- %% {objectclassname,ClassName}}};
- {object,_,_} ->
- %% An object defined inlined in another object
- #type{def=Ref} = element(3,CField),
-% CRef = case Ref of
-% #'Externaltypereference'{module=CurrMod,
-% type=CName} ->
-% CName;
-% #'Externaltypereference'{module=ExtMod,
-% type=CName} ->
-% {ExtMod,CName}
-% end,
- InlinedObjName=
- list_to_atom(lists:concat([S#state.tname]++
- ['_',ObjFieldName])),
-% ObjSpec = #'Object'{classname={objectclassname,CRef},
- ObjSpec = #'Object'{classname=Ref,
- def=ObjFieldSetting},
- CheckedObj=
- check_object(S,#typedef{typespec=ObjSpec},ObjSpec),
- InlObj = #typedef{checked=true,name=InlinedObjName,
- typespec=CheckedObj},
- asn1ct_gen:insert_once(inlined_objects,{InlinedObjName,
- InlinedObjName}),
- asn1_db:dbput(S#state.mname,InlinedObjName,InlObj),
- InlObj;
- #type{def=Eref} when record(Eref,'Externaltypereference') ->
- {_,R} = get_referenced_type(S,Eref),
- R;
- _ ->
-%% {_,R} = get_referenced_type(S,#typereference{val=ObjFieldSetting}),
- {_,R} = get_referenced_type(S,#'Externaltypereference'{module=S#state.mname,type=ObjFieldSetting}),
- R
- end,
- {ObjFieldName,
- ObjectSpec#typedef{checked=true,
- typespec=check_object(S,ObjectSpec,
- ObjectSpec#typedef.typespec)}};
- variabletypevaluefield ->
- {ObjFieldName,ObjFieldSetting};
- variabletypevaluesetfield ->
- {ObjFieldName,ObjFieldSetting};
- objectsetfield ->
- {_,ObjSetSpec} =
- case ObjFieldSetting of
- Ref when record(Ref,'Externaltypereference');
- record(Ref,'Externalvaluereference') ->
- get_referenced_type(S,ObjFieldSetting);
- ObjectList when list(ObjectList) ->
- %% an objctset defined in the object,though maybe
- %% parsed as a SequenceOfValue
- %% The ObjectList may be a list of references to
- %% objects, a ValueFromObject
- {_,_,Type,_} = CField,
- ClassDef = Type#type.def,
- case ClassDef#'Externaltypereference'.module of
- CurrMod ->
- ClassDef#'Externaltypereference'.type;
- ExtMod ->
- {ExtMod,
- ClassDef#'Externaltypereference'.type}
- end,
- {no_name,
- #typedef{typespec=
- #'ObjectSet'{class=
-% {objectclassname,ClassRef},
- ClassDef,
- set=ObjectList}}};
- ObjectSet={'SingleValue',_} ->
- %% a Union of defined objects
- {_,_,Type,_} = CField,
- ClassDef = Type#type.def,
-% ClassRef =
-% case ClassDef#'Externaltypereference'.module of
-% CurrMod ->
-% ClassDef#'Externaltypereference'.type;
-% ExtMod ->
-% {ExtMod,
-% ClassDef#'Externaltypereference'.type}
-% end,
- {no_name,
-% #typedef{typespec=#'ObjectSet'{class={objectclassname,ClassRef},
- #typedef{typespec=#'ObjectSet'{class=ClassDef,
- set=ObjectSet}}};
- {object,_,[#type{def={'TypeFromObject',
- {object,RefedObj},
- FieldName}}]} ->
- %% This case occurs when an ObjectSetFromObjects
- %% production is used
- {M,Def} = get_referenced_type(S,RefedObj),
- {M,get_fieldname_element(S,Def,FieldName)};
- #type{def=Eref} when
- record(Eref,'Externaltypereference') ->
- get_referenced_type(S,Eref);
- _ ->
-%% get_referenced_type(S,#typereference{val=ObjFieldSetting})
- get_referenced_type(S,#'Externaltypereference'{module=S#state.mname,type=ObjFieldSetting})
- end,
- {ObjFieldName,
- ObjSetSpec#typedef{checked=true,
- typespec=check_object(S,ObjSetSpec,
- ObjSetSpec#typedef.typespec)}}
- end.
-
-check_value(OldS,V) when record(V,pvaluesetdef) ->
- #pvaluesetdef{checked=Checked,type=Type} = V,
- case Checked of
- true -> V;
- {error,_} -> V;
- false ->
- case get_referenced_type(OldS,Type#type.def) of
- {_,Class} when record(Class,classdef) ->
- throw({pobjectsetdef});
- _ -> continue
- end
- end;
-check_value(_OldS,V) when record(V,pvaluedef) ->
- %% Fix this case later
- V;
-check_value(OldS,V) when record(V,typedef) ->
- %% This case when a value set has been parsed as an object set.
- %% It may be a value set
- #typedef{typespec=TS} = V,
- case TS of
- #'ObjectSet'{class=ClassRef} ->
- {_,TSDef} = get_referenced_type(OldS,ClassRef),
- %%IsObjectSet(TSDef);
- case TSDef of
- #classdef{} -> throw({objectsetdef});
- #typedef{typespec=#type{def=Eref}} when
- record(Eref,'Externaltypereference') ->
- %% This case if the class reference is a defined
- %% reference to class
- check_value(OldS,V#typedef{typespec=TS#'ObjectSet'{class=Eref}});
- #typedef{} ->
- % an ordinary value set with a type in #typedef.typespec
- ValueSet = TS#'ObjectSet'.set,
- Type=check_type(OldS,TSDef,TSDef#typedef.typespec),
- Value = check_value(OldS,#valuedef{type=Type,
- value=ValueSet}),
- {valueset,Type#type{constraint=Value#valuedef.value}}
- end;
- _ ->
- throw({objectsetdef})
- end;
-check_value(S,#valuedef{pos=Pos,name=Name,type=Type,
- value={valueset,Constr}}) ->
- NewType = Type#type{constraint=[Constr]},
- {valueset,
- check_type(S,#typedef{pos=Pos,name=Name,typespec=NewType},NewType)};
-check_value(OldS=#state{recordtopname=TopName},V) when record(V,valuedef) ->
- #valuedef{name=Name,checked=Checked,type=Vtype,value=Value} = V,
- case Checked of
- true ->
- V;
- {error,_} ->
- V;
- false ->
- Def = Vtype#type.def,
- Constr = Vtype#type.constraint,
- S = OldS#state{type=Vtype,tname=Def,value=V,vname=Name},
- NewDef =
- case Def of
- Ext when record(Ext,'Externaltypereference') ->
- RecName = Ext#'Externaltypereference'.type,
- {_,Type} = get_referenced_type(S,Ext),
- %% If V isn't a value but an object Type is a #classdef{}
- case Type of
- #classdef{} ->
- throw({objectdef});
- #typedef{} ->
- case is_contextswitchtype(Type) of
- true ->
- #valuedef{value=CheckedVal}=
- check_value(S,V#valuedef{type=Type#typedef.typespec}),
- #newv{value=CheckedVal};
- _ ->
- #valuedef{value=CheckedVal}=
- check_value(S#state{recordtopname=[RecName|TopName]},
- V#valuedef{type=Type#typedef.typespec}),
- #newv{value=CheckedVal}
- end
- end;
- 'ANY' ->
- throw({error,{asn1,{'cant check value of type',Def}}});
- 'INTEGER' ->
- validate_integer(S,Value,[],Constr),
- #newv{value=normalize_value(S,Vtype,Value,[])};
- {'INTEGER',NamedNumberList} ->
- validate_integer(S,Value,NamedNumberList,Constr),
- #newv{value=normalize_value(S,Vtype,Value,[])};
- {'BIT STRING',NamedNumberList} ->
- validate_bitstring(S,Value,NamedNumberList,Constr),
- #newv{value=normalize_value(S,Vtype,Value,[])};
- 'NULL' ->
- validate_null(S,Value,Constr),
- #newv{};
- 'OBJECT IDENTIFIER' ->
- validate_objectidentifier(S,Value,Constr),
- #newv{value = normalize_value(S,Vtype,Value,[])};
- 'ObjectDescriptor' ->
- validate_objectdescriptor(S,Value,Constr),
- #newv{value=normalize_value(S,Vtype,Value,[])};
- {'ENUMERATED',NamedNumberList} ->
- validate_enumerated(S,Value,NamedNumberList,Constr),
- #newv{value=normalize_value(S,Vtype,Value,[])};
- 'BOOLEAN'->
- validate_boolean(S,Value,Constr),
- #newv{value=normalize_value(S,Vtype,Value,[])};
- 'OCTET STRING' ->
- validate_octetstring(S,Value,Constr),
- #newv{value=normalize_value(S,Vtype,Value,[])};
- 'NumericString' ->
- validate_restrictedstring(S,Value,Def,Constr),
- #newv{value=normalize_value(S,Vtype,Value,[])};
- 'TeletexString' ->
- validate_restrictedstring(S,Value,Def,Constr),
- #newv{value=normalize_value(S,Vtype,Value,[])};
- 'VideotexString' ->
- validate_restrictedstring(S,Value,Def,Constr),
- #newv{value=normalize_value(S,Vtype,Value,[])};
- 'UTCTime' ->
- #newv{value=normalize_value(S,Vtype,Value,[])};
-% exit({'cant check value of type' ,Def});
- 'GeneralizedTime' ->
- #newv{value=normalize_value(S,Vtype,Value,[])};
-% exit({'cant check value of type' ,Def});
- 'GraphicString' ->
- validate_restrictedstring(S,Value,Def,Constr),
- #newv{value=normalize_value(S,Vtype,Value,[])};
- 'VisibleString' ->
- validate_restrictedstring(S,Value,Def,Constr),
- #newv{value=normalize_value(S,Vtype,Value,[])};
- 'GeneralString' ->
- validate_restrictedstring(S,Value,Def,Constr),
- #newv{value=normalize_value(S,Vtype,Value,[])};
- 'PrintableString' ->
- validate_restrictedstring(S,Value,Def,Constr),
- #newv{value=normalize_value(S,Vtype,Value,[])};
- 'IA5String' ->
- validate_restrictedstring(S,Value,Def,Constr),
- #newv{value=normalize_value(S,Vtype,Value,[])};
- 'BMPString' ->
- validate_restrictedstring(S,Value,Def,Constr),
- #newv{value=normalize_value(S,Vtype,Value,[])};
-%% 'UniversalString' -> %added 6/12 -00
-%% #newv{value=validate_restrictedstring(S,Value,Def,Constr)};
- Seq when record(Seq,'SEQUENCE') ->
- SeqVal = validate_sequence(S,Value,
- Seq#'SEQUENCE'.components,
- Constr),
- #newv{value=normalize_value(S,Vtype,SeqVal,TopName)};
- {'SEQUENCE OF',Components} ->
- validate_sequenceof(S,Value,Components,Constr),
- #newv{value=normalize_value(S,Vtype,Value,TopName)};
- {'CHOICE',Components} ->
- validate_choice(S,Value,Components,Constr),
- #newv{value=normalize_value(S,Vtype,Value,TopName)};
- Set when record(Set,'SET') ->
- validate_set(S,Value,Set#'SET'.components,
- Constr),
- #newv{value=normalize_value(S,Vtype,Value,TopName)};
- {'SET OF',Components} ->
- validate_setof(S,Value,Components,Constr),
- #newv{value=normalize_value(S,Vtype,Value,TopName)};
- Other ->
- exit({'cant check value of type' ,Other})
- end,
- case NewDef#newv.value of
- unchanged ->
- V#valuedef{checked=true,value=Value};
- ok ->
- V#valuedef{checked=true,value=Value};
- {error,Reason} ->
- V#valuedef{checked={error,Reason},value=Value};
- _V ->
- V#valuedef{checked=true,value=_V}
- end
- end.
-
-is_contextswitchtype(#typedef{name='EXTERNAL'})->
- true;
-is_contextswitchtype(#typedef{name='EMBEDDED PDV'}) ->
- true;
-is_contextswitchtype(#typedef{name='CHARACTER STRING'}) ->
- true;
-is_contextswitchtype(_) ->
- false.
-
-% validate_integer(S,{identifier,Pos,Id},NamedNumberList,Constr) ->
-% case lists:keysearch(Id,1,NamedNumberList) of
-% {value,_} -> ok;
-% false -> error({value,"unknown NamedNumber",S})
-% end;
-%% This case occurs when there is a valuereference
-validate_integer(S=#state{mname=M},
- #'Externalvaluereference'{module=M,value=Id},
- NamedNumberList,_Constr) ->
- case lists:keysearch(Id,1,NamedNumberList) of
- {value,_} -> ok;
- false -> error({value,"unknown NamedNumber",S})
- end;
-validate_integer(S,Id,NamedNumberList,_Constr) when atom(Id) ->
- case lists:keysearch(Id,1,NamedNumberList) of
- {value,_} -> ok;
- false -> error({value,"unknown NamedNumber",S})
- end;
-validate_integer(_S,Value,_NamedNumberList,Constr) when integer(Value) ->
- check_integer_range(Value,Constr).
-
-check_integer_range(Int,Constr) when list(Constr) ->
- NewConstr = [X || #constraint{c=X} <- Constr],
- check_constr(Int,NewConstr);
-
-check_integer_range(_Int,_Constr) ->
- %%io:format("~p~n",[Constr]),
- ok.
-
-check_constr(Int,[{'ValueRange',Lb,Ub}|T]) when Int >= Lb, Int =< Ub ->
- check_constr(Int,T);
-check_constr(_Int,[]) ->
- ok.
-
-validate_bitstring(_S,_Value,_NamedNumberList,_Constr) ->
- ok.
-
-validate_null(_S,'NULL',_Constr) ->
- ok.
-
-%%------------
-%% This can be removed when the old parser is removed
-%% The function removes 'space' atoms from the list
-
-is_space_list([H],Acc) ->
- lists:reverse([H|Acc]);
-is_space_list([H,space|T],Acc) ->
- is_space_list(T,[H|Acc]);
-is_space_list([],Acc) ->
- lists:reverse(Acc);
-is_space_list([H|T],Acc) ->
- is_space_list(T,[H|Acc]).
-
-validate_objectidentifier(S,L,_) ->
- case is_space_list(L,[]) of
- NewL when list(NewL) ->
- case validate_objectidentifier1(S,NewL) of
- NewL2 when list(NewL2) ->
- list_to_tuple(NewL2);
- Other -> Other
- end;
- {error,_} ->
- error({value, "illegal OBJECT IDENTIFIER", S})
- end.
-
-validate_objectidentifier1(S, [Id|T]) when record(Id,'Externalvaluereference') ->
- case catch get_referenced_type(S,Id) of
- {_,V} when record(V,valuedef) ->
- case check_value(S,V) of
- #valuedef{type=#type{def='OBJECT IDENTIFIER'},
- checked=true,value=Value} when tuple(Value) ->
- validate_objectid(S, T, lists:reverse(tuple_to_list(Value)));
- _ ->
- error({value, "illegal OBJECT IDENTIFIER", S})
- end;
- _ ->
- validate_objectid(S, [Id|T], [])
- end;
-validate_objectidentifier1(S,V) ->
- validate_objectid(S,V,[]).
-
-validate_objectid(_, [], Acc) ->
- lists:reverse(Acc);
-validate_objectid(S, [Value|Vrest], Acc) when integer(Value) ->
- validate_objectid(S, Vrest, [Value|Acc]);
-validate_objectid(S, [{'NamedNumber',_Name,Value}|Vrest], Acc)
- when integer(Value) ->
- validate_objectid(S, Vrest, [Value|Acc]);
-validate_objectid(S, [Id|Vrest], Acc)
- when record(Id,'Externalvaluereference') ->
- case catch get_referenced_type(S, Id) of
- {_,V} when record(V,valuedef) ->
- case check_value(S, V) of
- #valuedef{checked=true,value=Value} when integer(Value) ->
- validate_objectid(S, Vrest, [Value|Acc]);
- _ ->
- error({value, "illegal OBJECT IDENTIFIER", S})
- end;
- _ ->
- case reserved_objectid(Id#'Externalvaluereference'.value, Acc) of
- Value when integer(Value) ->
- validate_objectid(S, Vrest, [Value|Acc]);
- false ->
- error({value, "illegal OBJECT IDENTIFIER", S})
- end
- end;
-validate_objectid(S, [{Atom,Value}],[]) when atom(Atom),integer(Value) ->
- %% this case when an OBJECT IDENTIFIER value has been parsed as a
- %% SEQUENCE value
- Rec = #'Externalvaluereference'{module=S#state.mname,
- value=Atom},
- validate_objectidentifier1(S,[Rec,Value]);
-validate_objectid(S, [{Atom,EVRef}],[])
- when atom(Atom),record(EVRef,'Externalvaluereference') ->
- %% this case when an OBJECT IDENTIFIER value has been parsed as a
- %% SEQUENCE value OTP-4354
- Rec = #'Externalvaluereference'{module=S#state.mname,
- value=Atom},
- validate_objectidentifier1(S,[Rec,EVRef]);
-validate_objectid(S, _V, _Acc) ->
- error({value, "illegal OBJECT IDENTIFIER",S}).
-
-
-%% ITU-T Rec. X.680 Annex B - D
-reserved_objectid('itu-t',[]) -> 0;
-reserved_objectid('ccitt',[]) -> 0;
-%% arcs below "itu-t"
-reserved_objectid('recommendation',[0]) -> 0;
-reserved_objectid('question',[0]) -> 1;
-reserved_objectid('administration',[0]) -> 2;
-reserved_objectid('network-operator',[0]) -> 3;
-reserved_objectid('identified-organization',[0]) -> 4;
-%% arcs below "recommendation"
-reserved_objectid('a',[0,0]) -> 1;
-reserved_objectid('b',[0,0]) -> 2;
-reserved_objectid('c',[0,0]) -> 3;
-reserved_objectid('d',[0,0]) -> 4;
-reserved_objectid('e',[0,0]) -> 5;
-reserved_objectid('f',[0,0]) -> 6;
-reserved_objectid('g',[0,0]) -> 7;
-reserved_objectid('h',[0,0]) -> 8;
-reserved_objectid('i',[0,0]) -> 9;
-reserved_objectid('j',[0,0]) -> 10;
-reserved_objectid('k',[0,0]) -> 11;
-reserved_objectid('l',[0,0]) -> 12;
-reserved_objectid('m',[0,0]) -> 13;
-reserved_objectid('n',[0,0]) -> 14;
-reserved_objectid('o',[0,0]) -> 15;
-reserved_objectid('p',[0,0]) -> 16;
-reserved_objectid('q',[0,0]) -> 17;
-reserved_objectid('r',[0,0]) -> 18;
-reserved_objectid('s',[0,0]) -> 19;
-reserved_objectid('t',[0,0]) -> 20;
-reserved_objectid('u',[0,0]) -> 21;
-reserved_objectid('v',[0,0]) -> 22;
-reserved_objectid('w',[0,0]) -> 23;
-reserved_objectid('x',[0,0]) -> 24;
-reserved_objectid('y',[0,0]) -> 25;
-reserved_objectid('z',[0,0]) -> 26;
-
-
-reserved_objectid(iso,[]) -> 1;
-%% arcs below "iso", note that number 1 is not used
-reserved_objectid('standard',[1]) -> 0;
-reserved_objectid('member-body',[1]) -> 2;
-reserved_objectid('identified-organization',[1]) -> 3;
-
-reserved_objectid('joint-iso-itu-t',[]) -> 2;
-reserved_objectid('joint-iso-ccitt',[]) -> 2;
-
-reserved_objectid(_,_) -> false.
-
-
-
-
-
-validate_objectdescriptor(_S,_Value,_Constr) ->
- ok.
-
-validate_enumerated(S,Id,NamedNumberList,_Constr) when atom(Id) ->
- case lists:keysearch(Id,1,NamedNumberList) of
- {value,_} -> ok;
- false -> error({value,"unknown ENUMERATED",S})
- end;
-validate_enumerated(S,{identifier,_Pos,Id},NamedNumberList,_Constr) ->
- case lists:keysearch(Id,1,NamedNumberList) of
- {value,_} -> ok;
- false -> error({value,"unknown ENUMERATED",S})
- end;
-validate_enumerated(S,#'Externalvaluereference'{value=Id},
- NamedNumberList,_Constr) ->
- case lists:keysearch(Id,1,NamedNumberList) of
- {value,_} -> ok;
- false -> error({value,"unknown ENUMERATED",S})
- end.
-
-validate_boolean(_S,_Value,_Constr) ->
- ok.
-
-validate_octetstring(_S,_Value,_Constr) ->
- ok.
-
-validate_restrictedstring(_S,_Value,_Def,_Constr) ->
- ok.
-
-validate_sequence(S=#state{type=Vtype},Value,_Components,_Constr) ->
- case Vtype of
- #type{tag=[{tag,'UNIVERSAL',8,'IMPLICIT',32}]} ->
- %% this is an 'EXTERNAL' (or INSTANCE OF)
- case Value of
- [{identification,_}|_RestVal] ->
- to_EXTERNAL1990(S,Value);
- _ ->
- Value
- end;
- _ ->
- Value
- end.
-
-validate_sequenceof(_S,_Value,_Components,_Constr) ->
- ok.
-
-validate_choice(_S,_Value,_Components,_Constr) ->
- ok.
-
-validate_set(_S,_Value,_Components,_Constr) ->
- ok.
-
-validate_setof(_S,_Value,_Components,_Constr) ->
- ok.
-
-to_EXTERNAL1990(S,[{identification,{'CHOICE',{syntax,Stx}}}|Rest]) ->
- to_EXTERNAL1990(S,Rest,[{'direct-reference',Stx}]);
-to_EXTERNAL1990(S,[{identification,{'CHOICE',{'presentation-context-id',I}}}|Rest]) ->
- to_EXTERNAL1990(S,Rest,[{'indirect-reference',I}]);
-to_EXTERNAL1990(S,[{identification,{'CHOICE',{'context-negotiation',[{_,PCid},{_,TrStx}]}}}|Rest]) ->
- to_EXTERNAL1990(S,Rest,[{'indirect-reference',PCid},{'direct-reference',TrStx}]);
-to_EXTERNAL1990(S,_) ->
- error({value,"illegal value in EXTERNAL type",S}).
-
-to_EXTERNAL1990(S,[V={'data-value-descriptor',_}|Rest],Acc) ->
- to_EXTERNAL1990(S,Rest,[V|Acc]);
-to_EXTERNAL1990(_S,[{'data-value',Val}],Acc) ->
- Encoding = {encoding,{'CHOICE',{'octet-aligned',Val}}},
- lists:reverse([Encoding|Acc]);
-to_EXTERNAL1990(S,_,_) ->
- error({value,"illegal value in EXTERNAL type",S}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Functions to normalize the default values of SEQUENCE
-%% and SET components into Erlang valid format
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-normalize_value(_,_,mandatory,_) ->
- mandatory;
-normalize_value(_,_,'OPTIONAL',_) ->
- 'OPTIONAL';
-normalize_value(S,Type,{'DEFAULT',Value},NameList) ->
- case catch get_canonic_type(S,Type,NameList) of
- {'BOOLEAN',CType,_} ->
- normalize_boolean(S,Value,CType);
- {'INTEGER',CType,_} ->
- normalize_integer(S,Value,CType);
- {'BIT STRING',CType,_} ->
- normalize_bitstring(S,Value,CType);
- {'OCTET STRING',CType,_} ->
- normalize_octetstring(S,Value,CType);
- {'NULL',_CType,_} ->
- %%normalize_null(Value);
- 'NULL';
- {'OBJECT IDENTIFIER',_,_} ->
- normalize_objectidentifier(S,Value);
- {'ObjectDescriptor',_,_} ->
- normalize_objectdescriptor(Value);
- {'REAL',_,_} ->
- normalize_real(Value);
- {'ENUMERATED',CType,_} ->
- normalize_enumerated(Value,CType);
- {'CHOICE',CType,NewNameList} ->
- normalize_choice(S,Value,CType,NewNameList);
- {'SEQUENCE',CType,NewNameList} ->
- normalize_sequence(S,Value,CType,NewNameList);
- {'SEQUENCE OF',CType,NewNameList} ->
- normalize_seqof(S,Value,CType,NewNameList);
- {'SET',CType,NewNameList} ->
- normalize_set(S,Value,CType,NewNameList);
- {'SET OF',CType,NewNameList} ->
- normalize_setof(S,Value,CType,NewNameList);
- {restrictedstring,CType,_} ->
- normalize_restrictedstring(S,Value,CType);
- _ ->
- io:format("WARNING: could not check default value ~p~n",[Value]),
- Value
- end;
-normalize_value(S,Type,Val,NameList) ->
- normalize_value(S,Type,{'DEFAULT',Val},NameList).
-
-normalize_boolean(S,{Name,Bool},CType) when atom(Name) ->
- normalize_boolean(S,Bool,CType);
-normalize_boolean(_,true,_) ->
- true;
-normalize_boolean(_,false,_) ->
- false;
-normalize_boolean(S,Bool=#'Externalvaluereference'{},CType) ->
- get_normalized_value(S,Bool,CType,fun normalize_boolean/3,[]);
-normalize_boolean(_,Other,_) ->
- throw({error,{asn1,{'invalid default value',Other}}}).
-
-normalize_integer(_S,Int,_) when integer(Int) ->
- Int;
-normalize_integer(_S,{Name,Int},_) when atom(Name),integer(Int) ->
- Int;
-normalize_integer(S,{Name,Int=#'Externalvaluereference'{}},
- Type) when atom(Name) ->
- normalize_integer(S,Int,Type);
-normalize_integer(S,Int=#'Externalvaluereference'{value=Name},Type) ->
- case Type of
- NNL when list(NNL) ->
- case lists:keysearch(Name,1,NNL) of
- {value,{Name,Val}} ->
- Val;
- false ->
- get_normalized_value(S,Int,Type,
- fun normalize_integer/3,[])
- end;
- _ ->
- get_normalized_value(S,Int,Type,fun normalize_integer/3,[])
- end;
-normalize_integer(_,Int,_) ->
- exit({'Unknown INTEGER value',Int}).
-
-normalize_bitstring(S,Value,Type)->
- %% There are four different Erlang formats of BIT STRING:
- %% 1 - a list of ones and zeros.
- %% 2 - a list of atoms.
- %% 3 - as an integer, for instance in hexadecimal form.
- %% 4 - as a tuple {Unused, Binary} where Unused is an integer
- %% and tells how many bits of Binary are unused.
- %%
- %% normalize_bitstring/3 transforms Value according to:
- %% A to 3,
- %% B to 1,
- %% C to 1 or 3
- %% D to 2,
- %% Value can be on format:
- %% A - {hstring, String}, where String is a hexadecimal string.
- %% B - {bstring, String}, where String is a string on bit format
- %% C - #'Externalvaluereference'{value=V}, where V is a defined value
- %% D - list of #'Externalvaluereference', where each value component
- %% is an identifier corresponing to NamedBits in Type.
- case Value of
- {hstring,String} when list(String) ->
- hstring_to_int(String);
- {bstring,String} when list(String) ->
- bstring_to_bitlist(String);
- Rec when record(Rec,'Externalvaluereference') ->
- get_normalized_value(S,Value,Type,
- fun normalize_bitstring/3,[]);
- RecList when list(RecList) ->
- case Type of
- NBL when list(NBL) ->
- F = fun(#'Externalvaluereference'{value=Name}) ->
- case lists:keysearch(Name,1,NBL) of
- {value,{Name,_}} ->
- Name;
- Other ->
- throw({error,Other})
- end;
- (Other) ->
- throw({error,Other})
- end,
- case catch lists:map(F,RecList) of
- {error,Reason} ->
- io:format("WARNING: default value not "
- "compatible with type definition ~p~n",
- [Reason]),
- Value;
- NewList ->
- NewList
- end;
- _ ->
- io:format("WARNING: default value not "
- "compatible with type definition ~p~n",
- [RecList]),
- Value
- end;
- {Name,String} when atom(Name) ->
- normalize_bitstring(S,String,Type);
- Other ->
- io:format("WARNING: illegal default value ~p~n",[Other]),
- Value
- end.
-
-hstring_to_int(L) when list(L) ->
- hstring_to_int(L,0).
-hstring_to_int([H|T],Acc) when H >= $A, H =< $F ->
- hstring_to_int(T,(Acc bsl 4) + (H - $A + 10) ) ;
-hstring_to_int([H|T],Acc) when H >= $0, H =< $9 ->
- hstring_to_int(T,(Acc bsl 4) + (H - $0));
-hstring_to_int([],Acc) ->
- Acc.
-
-bstring_to_bitlist([H|T]) when H == $0; H == $1 ->
- [H - $0 | bstring_to_bitlist(T)];
-bstring_to_bitlist([]) ->
- [].
-
-%% normalize_octetstring/1 changes representation of input Value to a
-%% list of octets.
-%% Format of Value is one of:
-%% {bstring,String} each element in String corresponds to one bit in an octet
-%% {hstring,String} each element in String corresponds to one byte in an octet
-%% #'Externalvaluereference'
-normalize_octetstring(S,Value,CType) ->
- case Value of
- {bstring,String} ->
- bstring_to_octetlist(String);
- {hstring,String} ->
- hstring_to_octetlist(String);
- Rec when record(Rec,'Externalvaluereference') ->
- get_normalized_value(S,Value,CType,
- fun normalize_octetstring/3,[]);
- {Name,String} when atom(Name) ->
- normalize_octetstring(S,String,CType);
- List when list(List) ->
- %% check if list elements are valid octet values
- lists:map(fun([])-> ok;
- (H)when H > 255->
- io:format("WARNING: not legal octet value ~p in OCTET STRING, ~p~n",[H,List]);
- (_)-> ok
- end, List),
- List;
- Other ->
- io:format("WARNING: unknown default value ~p~n",[Other]),
- Value
- end.
-
-
-bstring_to_octetlist([]) ->
- [];
-bstring_to_octetlist([H|T]) when H == $0 ; H == $1 ->
- bstring_to_octetlist(T,6,[(H - $0) bsl 7]).
-bstring_to_octetlist([H|T],0,[Hacc|Tacc]) when H == $0; H == $1 ->
- bstring_to_octetlist(T, 7, [0,Hacc + (H -$0)| Tacc]);
-bstring_to_octetlist([H|T],BSL,[Hacc|Tacc]) when H == $0; H == $1 ->
- bstring_to_octetlist(T, BSL-1, [Hacc + ((H - $0) bsl BSL)| Tacc]);
-bstring_to_octetlist([],7,[0|Acc]) ->
- lists:reverse(Acc);
-bstring_to_octetlist([],_,Acc) ->
- lists:reverse(Acc).
-
-hstring_to_octetlist([]) ->
- [];
-hstring_to_octetlist(L) ->
- hstring_to_octetlist(L,4,[]).
-hstring_to_octetlist([H|T],0,[Hacc|Tacc]) when H >= $A, H =< $F ->
- hstring_to_octetlist(T,4,[Hacc + (H - $A + 10)|Tacc]);
-hstring_to_octetlist([H|T],BSL,Acc) when H >= $A, H =< $F ->
- hstring_to_octetlist(T,0,[(H - $A + 10) bsl BSL|Acc]);
-hstring_to_octetlist([H|T],0,[Hacc|Tacc]) when H >= $0; H =< $9 ->
- hstring_to_octetlist(T,4,[Hacc + (H - $0)|Tacc]);
-hstring_to_octetlist([H|T],BSL,Acc) when H >= $0; H =< $9 ->
- hstring_to_octetlist(T,0,[(H - $0) bsl BSL|Acc]);
-hstring_to_octetlist([],_,Acc) ->
- lists:reverse(Acc).
-
-normalize_objectidentifier(S,Value) ->
- validate_objectidentifier(S,Value,[]).
-
-normalize_objectdescriptor(Value) ->
- Value.
-
-normalize_real(Value) ->
- Value.
-
-normalize_enumerated(#'Externalvaluereference'{value=V},CType)
- when list(CType) ->
- normalize_enumerated2(V,CType);
-normalize_enumerated(Value,CType) when atom(Value),list(CType) ->
- normalize_enumerated2(Value,CType);
-normalize_enumerated({Name,EnumV},CType) when atom(Name) ->
- normalize_enumerated(EnumV,CType);
-normalize_enumerated(Value,{CType1,CType2}) when list(CType1), list(CType2)->
- normalize_enumerated(Value,CType1++CType2);
-normalize_enumerated(V,CType) ->
- io:format("WARNING: Enumerated unknown type ~p~n",[CType]),
- V.
-normalize_enumerated2(V,Enum) ->
- case lists:keysearch(V,1,Enum) of
- {value,{Val,_}} -> Val;
- _ ->
- io:format("WARNING: Enumerated value is not correct ~p~n",[V]),
- V
- end.
-
-normalize_choice(S,{'CHOICE',{C,V}},CType,NameList) when atom(C) ->
- Value =
- case V of
- Rec when record(Rec,'Externalvaluereference') ->
- get_normalized_value(S,V,CType,
- fun normalize_choice/4,
- [NameList]);
- _ -> V
- end,
- case catch lists:keysearch(C,#'ComponentType'.name,CType) of
- {value,#'ComponentType'{typespec=CT,name=Name}} ->
- {C,normalize_value(S,CT,{'DEFAULT',Value},
- [Name|NameList])};
- Other ->
- io:format("WARNING: Wrong format of type/value ~p/~p~n",
- [Other,Value]),
- {C,Value}
- end;
-normalize_choice(S,{'DEFAULT',ValueList},CType,NameList) ->
- lists:map(fun(X)-> normalize_choice(S,X,CType,NameList) end, ValueList);
-normalize_choice(S,Val=#'Externalvaluereference'{},CType,NameList) ->
- {_,#valuedef{value=V}}=get_referenced_type(S,Val),
- normalize_choice(S,{'CHOICE',V},CType,NameList);
-% get_normalized_value(S,Val,CType,fun normalize_choice/4,[NameList]);
-normalize_choice(S,{Name,ChoiceVal},CType,NameList)
- when atom(Name) ->
- normalize_choice(S,ChoiceVal,CType,NameList).
-
-normalize_sequence(S,{Name,Value},Components,NameList)
- when atom(Name),list(Value) ->
- normalize_sequence(S,Value,Components,NameList);
-normalize_sequence(S,Value,Components,NameList) ->
- normalized_record('SEQUENCE',S,Value,Components,NameList).
-
-normalize_set(S,{Name,Value},Components,NameList)
- when atom(Name),list(Value) ->
- normalized_record('SET',S,Value,Components,NameList);
-normalize_set(S,Value,Components,NameList) ->
- normalized_record('SET',S,Value,Components,NameList).
-
-normalized_record(SorS,S,Value,Components,NameList) ->
- NewName = list_to_atom(asn1ct_gen:list2name(NameList)),
- NoComps = length(Components),
- case normalize_seq_or_set(SorS,S,Value,Components,NameList,[]) of
- ListOfVals when length(ListOfVals) == NoComps ->
- list_to_tuple([NewName|ListOfVals]);
- _ ->
- error({type,{illegal,default,value,Value},S})
- end.
-
-normalize_seq_or_set(SorS,S,[{Cname,V}|Vs],
- [#'ComponentType'{name=Cname,typespec=TS}|Cs],
- NameList,Acc) ->
- NewNameList =
- case TS#type.def of
- #'Externaltypereference'{type=TName} ->
- [TName];
- _ -> [Cname|NameList]
- end,
- NVal = normalize_value(S,TS,{'DEFAULT',V},NewNameList),
- normalize_seq_or_set(SorS,S,Vs,Cs,NameList,[NVal|Acc]);
-normalize_seq_or_set(SorS,S,Values=[{_Cname1,_V}|_Vs],
- [#'ComponentType'{prop='OPTIONAL'}|Cs],
- NameList,Acc) ->
- normalize_seq_or_set(SorS,S,Values,Cs,NameList,[asn1_NOVALUE|Acc]);
-normalize_seq_or_set(SorS,S,Values=[{_Cname1,_V}|_Vs],
- [#'ComponentType'{name=Cname2,typespec=TS,
- prop={'DEFAULT',Value}}|Cs],
- NameList,Acc) ->
- NewNameList =
- case TS#type.def of
- #'Externaltypereference'{type=TName} ->
- [TName];
- _ -> [Cname2|NameList]
- end,
- NVal = normalize_value(S,TS,{'DEFAULT',Value},NewNameList),
- normalize_seq_or_set(SorS,S,Values,Cs,NameList,[NVal|Acc]);
-normalize_seq_or_set(_SorS,_S,[],[],_,Acc) ->
- lists:reverse(Acc);
-%% If default value is {} ComponentTypes in SEQUENCE are marked DEFAULT
-%% or OPTIONAL (or the type is defined SEQUENCE{}, which is handled by
-%% the previous case).
-normalize_seq_or_set(SorS,S,[],
- [#'ComponentType'{name=Name,typespec=TS,
- prop={'DEFAULT',Value}}|Cs],
- NameList,Acc) ->
- NewNameList =
- case TS#type.def of
- #'Externaltypereference'{type=TName} ->
- [TName];
- _ -> [Name|NameList]
- end,
- NVal = normalize_value(S,TS,{'DEFAULT',Value},NewNameList),
- normalize_seq_or_set(SorS,S,[],Cs,NameList,[NVal|Acc]);
-normalize_seq_or_set(SorS,S,[],[#'ComponentType'{prop='OPTIONAL'}|Cs],
- NameList,Acc) ->
- normalize_seq_or_set(SorS,S,[],Cs,NameList,[asn1_NOVALUE|Acc]);
-normalize_seq_or_set(SorS,S,Value=#'Externalvaluereference'{},
- Cs,NameList,Acc) ->
- get_normalized_value(S,Value,Cs,fun normalize_seq_or_set/6,
- [SorS,NameList,Acc]);
-normalize_seq_or_set(_SorS,S,V,_,_,_) ->
- error({type,{illegal,default,value,V},S}).
-
-normalize_seqof(S,Value,Type,NameList) ->
- normalize_s_of('SEQUENCE OF',S,Value,Type,NameList).
-
-normalize_setof(S,Value,Type,NameList) ->
- normalize_s_of('SET OF',S,Value,Type,NameList).
-
-normalize_s_of(SorS,S,Value,Type,NameList) when list(Value) ->
- DefValueList = lists:map(fun(X) -> {'DEFAULT',X} end,Value),
- Suffix = asn1ct_gen:constructed_suffix(SorS,Type),
- Def = Type#type.def,
- InnerType = asn1ct_gen:get_inner(Def),
- WhatKind = asn1ct_gen:type(InnerType),
- NewNameList =
- case WhatKind of
- {constructed,bif} ->
- [Suffix|NameList];
- #'Externaltypereference'{type=Name} ->
- [Name];
- _ -> []
- end,
- NormFun = fun (X) -> normalize_value(S,Type,X,
- NewNameList) end,
- case catch lists:map(NormFun, DefValueList) of
- List when list(List) ->
- List;
- _ ->
- io:format("WARNING: ~p could not handle value ~p~n",
- [SorS,Value]),
- Value
- end;
-normalize_s_of(SorS,S,Value,Type,NameList)
- when record(Value,'Externalvaluereference') ->
- get_normalized_value(S,Value,Type,fun normalize_s_of/5,
- [SorS,NameList]).
-% case catch get_referenced_type(S,Value) of
-% {_,#valuedef{value=V}} ->
-% normalize_s_of(SorS,S,V,Type);
-% {error,Reason} ->
-% io:format("WARNING: ~p could not handle value ~p~n",
-% [SorS,Value]),
-% Value;
-% {_,NewVal} ->
-% normalize_s_of(SorS,S,NewVal,Type);
-% _ ->
-% io:format("WARNING: ~p could not handle value ~p~n",
-% [SorS,Value]),
-% Value
-% end.
-
-
-%% normalize_restrictedstring handles all format of restricted strings.
-%% tuple case
-normalize_restrictedstring(_S,[Int1,Int2],_) when integer(Int1),integer(Int2) ->
- {Int1,Int2};
-%% quadruple case
-normalize_restrictedstring(_S,[Int1,Int2,Int3,Int4],_) when integer(Int1),
- integer(Int2),
- integer(Int3),
- integer(Int4) ->
- {Int1,Int2,Int3,Int4};
-%% character string list case
-normalize_restrictedstring(S,[H|T],CType) when list(H);tuple(H) ->
- [normalize_restrictedstring(S,H,CType)|normalize_restrictedstring(S,T,CType)];
-%% character sting case
-normalize_restrictedstring(_S,CString,_) when list(CString) ->
- Fun =
- fun(X) ->
- if
- $X =< 255, $X >= 0 ->
- ok;
- true ->
- io:format("WARNING: illegal character in string"
- " ~p~n",[X])
- end
- end,
- lists:foreach(Fun,CString),
- CString;
-%% definedvalue case or argument in a parameterized type
-normalize_restrictedstring(S,ERef,CType) when record(ERef,'Externalvaluereference') ->
- get_normalized_value(S,ERef,CType,
- fun normalize_restrictedstring/3,[]);
-%%
-normalize_restrictedstring(S,{Name,Val},CType) when atom(Name) ->
- normalize_restrictedstring(S,Val,CType).
-
-
-get_normalized_value(S,Val,Type,Func,AddArg) ->
- case catch get_referenced_type(S,Val) of
- {_,#valuedef{type=_T,value=V}} ->
- %% should check that Type and T equals
- call_Func(S,V,Type,Func,AddArg);
- {error,_} ->
- io:format("WARNING: default value not "
- "comparable ~p~n",[Val]),
- Val;
- {_,NewVal} ->
- call_Func(S,NewVal,Type,Func,AddArg);
- _ ->
- io:format("WARNING: default value not "
- "comparable ~p~n",[Val]),
- Val
- end.
-
-call_Func(S,Val,Type,Func,ArgList) ->
- case ArgList of
- [] ->
- Func(S,Val,Type);
- [LastArg] ->
- Func(S,Val,Type,LastArg);
- [Arg1,LastArg1] ->
- Func(Arg1,S,Val,Type,LastArg1);
- [Arg1,LastArg1,LastArg2] ->
- Func(Arg1,S,Val,Type,LastArg1,LastArg2)
- end.
-
-
-get_canonic_type(S,Type,NameList) ->
- {InnerType,NewType,NewNameList} =
- case Type#type.def of
- Name when atom(Name) ->
- {Name,Type,NameList};
- Ref when record(Ref,'Externaltypereference') ->
- {_,#typedef{name=Name,typespec=RefedType}} =
- get_referenced_type(S,Ref),
- get_canonic_type(S,RefedType,[Name]);
- {Name,T} when atom(Name) ->
- {Name,T,NameList};
- Seq when record(Seq,'SEQUENCE') ->
- {'SEQUENCE',Seq#'SEQUENCE'.components,NameList};
- Set when record(Set,'SET') ->
- {'SET',Set#'SET'.components,NameList}
- end,
- {asn1ct_gen:unify_if_string(InnerType),NewType,NewNameList}.
-
-
-
-check_ptype(_S,Type,Ts) when record(Ts,type) ->
- %Tag = Ts#type.tag,
- %Constr = Ts#type.constraint,
- Def = Ts#type.def,
- NewDef=
- case Def of
- Seq when record(Seq,'SEQUENCE') ->
- #newt{type=Seq#'SEQUENCE'{pname=Type#ptypedef.name}};
- Set when record(Set,'SET') ->
- #newt{type=Set#'SET'{pname=Type#ptypedef.name}};
- _Other ->
- #newt{}
- end,
- Ts2 = case NewDef of
- #newt{type=unchanged} ->
- Ts;
- #newt{type=TDef}->
- Ts#type{def=TDef}
- end,
- Ts2.
-
-
-% check_type(S,Type,ObjSpec={{objectclassname,_},_}) ->
-% check_class(S,ObjSpec);
-check_type(_S,Type,Ts) when record(Type,typedef),
- (Type#typedef.checked==true) ->
- Ts;
-check_type(_S,Type,Ts) when record(Type,typedef),
- (Type#typedef.checked==idle) -> % the check is going on
- Ts;
-check_type(S=#state{recordtopname=TopName},Type,Ts) when record(Ts,type) ->
- {Def,Tag,Constr} =
- case match_parameters(Ts#type.def,S#state.parameters) of
- #type{constraint=_Ctmp,def=Dtmp} ->
- {Dtmp,Ts#type.tag,Ts#type.constraint};
- Dtmp ->
- {Dtmp,Ts#type.tag,Ts#type.constraint}
- end,
- TempNewDef = #newt{type=Def,tag=Tag,constraint=Constr},
- TestFun =
- fun(Tref) ->
- {_,MaybeChoice} = get_referenced_type(S,Tref),
- case catch((MaybeChoice#typedef.typespec)#type.def) of
- {'CHOICE',_} ->
- maybe_illicit_implicit_tag(choice,Tag);
- 'ANY' ->
- maybe_illicit_implicit_tag(open_type,Tag);
- 'ANY DEFINED BY' ->
- maybe_illicit_implicit_tag(open_type,Tag);
- 'ASN1_OPEN_TYPE' ->
- maybe_illicit_implicit_tag(open_type,Tag);
- _ ->
- Tag
- end
- end,
- NewDef=
- case Def of
- Ext when record(Ext,'Externaltypereference') ->
- {_,RefTypeDef} = get_referenced_type(S,Ext),
-% case RefTypeDef of
-% Class when record(Class,classdef) ->
-% throw({asn1_class,Class});
-% _ -> ok
-% end,
- case is_class(S,RefTypeDef) of
- true -> throw({asn1_class,RefTypeDef});
- _ -> ok
- end,
- Ct = TestFun(Ext),
- RefType =
-%case S#state.erule of
-% ber_bin_v2 ->
- case RefTypeDef#typedef.checked of
- true ->
- RefTypeDef#typedef.typespec;
- _ ->
- NewRefTypeDef1 = RefTypeDef#typedef{checked=idle},
- asn1_db:dbput(S#state.mname,
- NewRefTypeDef1#typedef.name,NewRefTypeDef1),
- RefType1 =
- check_type(S,RefTypeDef,RefTypeDef#typedef.typespec),
- NewRefTypeDef2 =
- RefTypeDef#typedef{checked=true,typespec = RefType1},
- asn1_db:dbput(S#state.mname,
- NewRefTypeDef2#typedef.name,NewRefTypeDef2),
- %% update the type and mark as checked
- RefType1
- end,
-% _ -> RefTypeDef#typedef.typespec
-% end,
-
- case asn1ct_gen:prim_bif(asn1ct_gen:get_inner(RefType#type.def)) of
- true ->
- %% Here we expand to a built in type and inline it
- TempNewDef#newt{
- type=
- RefType#type.def,
- tag=
- merge_tags(Ct,RefType#type.tag),
- constraint=
- merge_constraints(check_constraints(S,Constr),
- RefType#type.constraint)};
- _ ->
- %% Here we only expand the tags and keep the ext ref
-
- TempNewDef#newt{
- type=
- check_externaltypereference(S,Ext),
- tag =
- case S#state.erule of
- ber_bin_v2 ->
- merge_tags(Ct,RefType#type.tag);
- _ ->
- Ct
- end
- }
- end;
- 'ANY' ->
- Ct=maybe_illicit_implicit_tag(open_type,Tag),
- TempNewDef#newt{type='ASN1_OPEN_TYPE',tag=Ct};
- {'ANY_DEFINED_BY',_} ->
- Ct=maybe_illicit_implicit_tag(open_type,Tag),
- TempNewDef#newt{type='ASN1_OPEN_TYPE',tag=Ct};
- 'INTEGER' ->
- check_integer(S,[],Constr),
- TempNewDef#newt{tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_INTEGER))};
-
- {'INTEGER',NamedNumberList} ->
- TempNewDef#newt{type={'INTEGER',check_integer(S,NamedNumberList,Constr)},
- tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_INTEGER))};
- {'BIT STRING',NamedNumberList} ->
- NewL = check_bitstring(S,NamedNumberList,Constr),
-%% erlang:display({asn1ct_check,NamedNumberList,NewL}),
- TempNewDef#newt{type={'BIT STRING',NewL},
- tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_BIT_STRING))};
- 'NULL' ->
- TempNewDef#newt{tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_NULL))};
- 'OBJECT IDENTIFIER' ->
- check_objectidentifier(S,Constr),
- TempNewDef#newt{tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_OBJECT_IDENTIFIER))};
- 'ObjectDescriptor' ->
- TempNewDef#newt{tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_OBJECT_DESCRIPTOR))};
- 'EXTERNAL' ->
-%% AssociatedType = asn1_db:dbget(S#state.mname,'EXTERNAL'),
-%% #newt{type=check_type(S,Type,AssociatedType)};
- put(external,unchecked),
- TempNewDef#newt{type=
- #'Externaltypereference'{module=S#state.mname,
- type='EXTERNAL'},
- tag=
- merge_tags(Tag,?TAG_CONSTRUCTED(?N_EXTERNAL))};
- {'INSTANCE OF',DefinedObjectClass,Constraint} ->
- %% check that DefinedObjectClass is of TYPE-IDENTIFIER class
- %% If Constraint is empty make it the general INSTANCE OF type
- %% If Constraint is not empty make an inlined type
- %% convert INSTANCE OF to the associated type
- IOFDef=check_instance_of(S,DefinedObjectClass,Constraint),
- TempNewDef#newt{type=IOFDef,
- tag=merge_tags(Tag,?TAG_CONSTRUCTED(?N_INSTANCE_OF))};
- {'ENUMERATED',NamedNumberList} ->
- TempNewDef#newt{type=
- {'ENUMERATED',
- check_enumerated(S,NamedNumberList,Constr)},
- tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_ENUMERATED))};
- 'EMBEDDED PDV' ->
-% AssociatedType = asn1_db:dbget(S#state.mname,'EMBEDDED PDV'),
-% CheckedType = check_type(S,Type,
-% AssociatedType#typedef.typespec),
- put(embedded_pdv,unchecked),
- TempNewDef#newt{type=
- #'Externaltypereference'{module=S#state.mname,
- type='EMBEDDED PDV'},
- tag=
- merge_tags(Tag,?TAG_CONSTRUCTED(?N_EMBEDDED_PDV))};
- 'BOOLEAN'->
- check_boolean(S,Constr),
- TempNewDef#newt{tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_BOOLEAN))};
- 'OCTET STRING' ->
- check_octetstring(S,Constr),
- TempNewDef#newt{tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_OCTET_STRING))};
- 'NumericString' ->
- check_restrictedstring(S,Def,Constr),
- TempNewDef#newt{tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_NumericString))};
- 'TeletexString' ->
- check_restrictedstring(S,Def,Constr),
- TempNewDef#newt{tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_TeletexString))};
- 'VideotexString' ->
- check_restrictedstring(S,Def,Constr),
- TempNewDef#newt{tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_VideotexString))};
- 'UTCTime' ->
- TempNewDef#newt{tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_UTCTime))};
- 'GeneralizedTime' ->
- TempNewDef#newt{tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_GeneralizedTime))};
- 'GraphicString' ->
- check_restrictedstring(S,Def,Constr),
- TempNewDef#newt{tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_GraphicString))};
- 'VisibleString' ->
- check_restrictedstring(S,Def,Constr),
- TempNewDef#newt{tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_VisibleString))};
- 'GeneralString' ->
- check_restrictedstring(S,Def,Constr),
- TempNewDef#newt{tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_GeneralString))};
- 'PrintableString' ->
- check_restrictedstring(S,Def,Constr),
- TempNewDef#newt{tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_PrintableString))};
- 'IA5String' ->
- check_restrictedstring(S,Def,Constr),
- TempNewDef#newt{tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_IA5String))};
- 'BMPString' ->
- check_restrictedstring(S,Def,Constr),
- TempNewDef#newt{tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_BMPString))};
- 'UniversalString' ->
- check_restrictedstring(S,Def,Constr),
- TempNewDef#newt{tag=
- merge_tags(Tag,?TAG_PRIMITIVE(?N_UniversalString))};
- 'CHARACTER STRING' ->
-% AssociatedType = asn1_db:dbget(S#state.mname,
-% 'CHARACTER STRING'),
-% CheckedType = check_type(S,Type,
-% AssociatedType#typedef.typespec),
- put(character_string,unchecked),
- TempNewDef#newt{type=
- #'Externaltypereference'{module=S#state.mname,
- type='CHARACTER STRING'},
- tag=
- merge_tags(Tag,?TAG_CONSTRUCTED(?N_CHARACTER_STRING))};
- Seq when record(Seq,'SEQUENCE') ->
- RecordName =
- case TopName of
- [] ->
- [Type#typedef.name];
- _ ->
- TopName
- end,
- {TableCInf,Components} =
- check_sequence(S#state{recordtopname=
- RecordName},
- Type,Seq#'SEQUENCE'.components),
- TempNewDef#newt{type=Seq#'SEQUENCE'{tablecinf=TableCInf,
- components=Components},
- tag=
- merge_tags(Tag,?TAG_CONSTRUCTED(?N_SEQUENCE))};
- {'SEQUENCE OF',Components} ->
- TempNewDef#newt{type={'SEQUENCE OF',check_sequenceof(S,Type,Components)},
- tag=
- merge_tags(Tag,?TAG_CONSTRUCTED(?N_SEQUENCE))};
- {'CHOICE',Components} ->
- Ct = maybe_illicit_implicit_tag(choice,Tag),
- TempNewDef#newt{type={'CHOICE',check_choice(S,Type,Components)},tag=Ct};
- Set when record(Set,'SET') ->
- RecordName=
- case TopName of
- [] ->
- [Type#typedef.name];
- _ ->
- TopName
- end,
- {Sorted,TableCInf,Components} =
- check_set(S#state{recordtopname=RecordName},
- Type,Set#'SET'.components),
- TempNewDef#newt{type=Set#'SET'{sorted=Sorted,
- tablecinf=TableCInf,
- components=Components},
- tag=
- merge_tags(Tag,?TAG_CONSTRUCTED(?N_SET))};
- {'SET OF',Components} ->
- TempNewDef#newt{type={'SET OF',check_setof(S,Type,Components)},
- tag=
- merge_tags(Tag,?TAG_CONSTRUCTED(?N_SET))};
- %% This is a temporary hack until the full Information Obj Spec
- %% in X.681 is supported
- {{typereference,_,'TYPE-IDENTIFIER'},[{typefieldreference,_,'Type'}]} ->
- Ct=maybe_illicit_implicit_tag(open_type,Tag),
- TempNewDef#newt{type='ASN1_OPEN_TYPE',tag=Ct};
-
- {#'Externaltypereference'{type='TYPE-IDENTIFIER'},
- [{typefieldreference,_,'Type'}]} ->
- Ct=maybe_illicit_implicit_tag(open_type,Tag),
- TempNewDef#newt{type='ASN1_OPEN_TYPE',tag=Ct};
-
- {pt,Ptype,ParaList} ->
- %% Ptype might be a parameterized - type, object set or
- %% value set. If it isn't a parameterized type notify the
- %% calling function.
- {_,Ptypedef} = get_referenced_type(S,Ptype),
- notify_if_not_ptype(S,Ptypedef),
- NewParaList = [match_parameters(TmpParam,S#state.parameters)||
- TmpParam <- ParaList],
- Instance = instantiate_ptype(S,Ptypedef,NewParaList),
- TempNewDef#newt{type=Instance#type.def,
- tag=merge_tags(Tag,Instance#type.tag),
- constraint=Instance#type.constraint,
- inlined=yes};
-
-% {ClRef,FieldRefList} when record(ClRef,'Externaltypereference') ->
- OCFT=#'ObjectClassFieldType'{class=ClRef} ->
- %% this case occures in a SEQUENCE when
- %% the type of the component is a ObjectClassFieldType
- ClassSpec = check_class(S,ClRef),
- NewTypeDef = maybe_open_type(S,ClassSpec,OCFT,Constr),
- InnerTag = get_innertag(S,NewTypeDef),
- MergedTag = merge_tags(Tag,InnerTag),
- Ct =
- case is_open_type(NewTypeDef) of
- true ->
- maybe_illicit_implicit_tag(open_type,MergedTag);
- _ ->
- MergedTag
- end,
- TempNewDef#newt{type=NewTypeDef,tag=Ct};
- {valueset,Vtype} ->
- TempNewDef#newt{type={valueset,check_type(S,Type,Vtype)}};
- Other ->
- exit({'cant check' ,Other})
- end,
- Ts2 = case NewDef of
- #newt{type=unchanged} ->
- Ts#type{def=Def};
- #newt{type=TDef}->
- Ts#type{def=TDef}
- end,
- NewTag = case NewDef of
- #newt{tag=unchanged} ->
- Tag;
- #newt{tag=TT} ->
- TT
- end,
- T3 = Ts2#type{tag = lists:map(fun(TempTag = #tag{type={default,TTx}}) ->
- TempTag#tag{type=TTx};
- (Else) -> Else end, NewTag)},
- T4 = case NewDef of
- #newt{constraint=unchanged} ->
- T3#type{constraint=Constr};
- #newt{constraint=NewConstr} ->
- T3#type{constraint=NewConstr}
- end,
- T5 = T4#type{inlined=NewDef#newt.inlined},
- T5#type{constraint=check_constraints(S,T5#type.constraint)}.
-
-
-get_innertag(_S,#'ObjectClassFieldType'{type=Type}) ->
- case Type of
- #type{tag=Tag} -> Tag;
- {fixedtypevaluefield,_,#type{tag=Tag}} -> Tag;
- {TypeFieldName,_} when atom(TypeFieldName) -> [];
- _ -> []
- end;
-get_innertag(_S,_) ->
- [].
-
-is_class(_S,#classdef{}) ->
- true;
-is_class(S,#typedef{typespec=#type{def=Eref}})
- when record(Eref,'Externaltypereference')->
- {_,NextDef} = get_referenced_type(S,Eref),
- is_class(S,NextDef);
-is_class(_,_) ->
- false.
-
-get_class_def(_S,CD=#classdef{}) ->
- CD;
-get_class_def(S,#typedef{typespec=#type{def=Eref}})
- when record(Eref,'Externaltypereference') ->
- {_,NextDef} = get_referenced_type(S,Eref),
- get_class_def(S,NextDef).
-
-maybe_illicit_implicit_tag(Kind,Tag) ->
- case Tag of
- [#tag{type='IMPLICIT'}|_T] ->
- throw({error,{asn1,{implicit_tag_before,Kind}}});
- [ChTag = #tag{type={default,_}}|T] ->
- case Kind of
- open_type ->
- [ChTag#tag{type='EXPLICIT',form=32}|T]; %X.680 30.6c, X.690 8.14.2
- choice ->
- [ChTag#tag{type='EXPLICIT',form=32}|T] % X.680 28.6 c, 30.6c
- end;
- _ ->
- Tag % unchanged
- end.
-
-%% maybe_open_type/2 -> {ClassSpec,FieldRefList} | 'ASN1_OPEN_TYPE'
-%% if the FieldRefList points out a typefield and the class don't have
-%% any UNIQUE field, so that a component relation constraint cannot specify
-%% the type of a typefield, return 'ASN1_OPEN_TYPE', otherwise return
-%% {ClassSpec,FieldRefList}.
-maybe_open_type(S,ClassSpec=#objectclass{fields=Fs},
- OCFT=#'ObjectClassFieldType'{fieldname=FieldRefList},
- Constr) ->
- Type = get_ObjectClassFieldType(S,Fs,FieldRefList),
- FieldNames=get_referenced_fieldname(FieldRefList),
- case lists:last(FieldRefList) of
- {valuefieldreference,_} ->
- OCFT#'ObjectClassFieldType'{class=ClassSpec,
- fieldname=FieldNames,
- type=Type};
- {typefieldreference,_} ->
- case {catch get_unique_fieldname(#classdef{typespec=ClassSpec}),
- asn1ct_gen:get_constraint(Constr,componentrelation)}of
- {Tuple,_} when tuple(Tuple) ->
- OCFT#'ObjectClassFieldType'{class=ClassSpec,
- fieldname=FieldNames,
- type='ASN1_OPEN_TYPE'};
- {_,no} ->
- OCFT#'ObjectClassFieldType'{class=ClassSpec,
- fieldname=FieldNames,
- type='ASN1_OPEN_TYPE'};
- _ ->
- OCFT#'ObjectClassFieldType'{class=ClassSpec,
- fieldname=FieldNames,
- type=Type}
- end
- end.
-
-is_open_type(#'ObjectClassFieldType'{type='ASN1_OPEN_TYPE'}) ->
- true;
-is_open_type(#'ObjectClassFieldType'{}) ->
- false.
-
-
-notify_if_not_ptype(S,#pvaluesetdef{type=Type}) ->
- case Type#type.def of
- Ref when record(Ref,'Externaltypereference') ->
- case get_referenced_type(S,Ref) of
- {_,#classdef{}} ->
- throw(pobjectsetdef);
- {_,#typedef{}} ->
- throw(pvalueset)
- end;
- T when record(T,type) -> % this must be a value set
- throw(pvalueset)
- end;
-notify_if_not_ptype(_S,#ptypedef{}) ->
- ok.
-
-% fix me
-instantiate_ptype(S,Ptypedef,ParaList) ->
- #ptypedef{args=Args,typespec=Type} = Ptypedef,
-% Args = get_pt_args(Ptypedef),
-% Type = get_pt_spec(Ptypedef),
- MatchedArgs = match_args(Args, ParaList, []),
- NewS = S#state{type=Type,parameters=MatchedArgs,abscomppath=[]},
- %The abscomppath must be empty since a table constraint in a
- %parameterized type only can refer to components within the type
- check_type(NewS, Ptypedef, Type).
-
-get_pt_args(#ptypedef{args=Args}) ->
- Args;
-get_pt_args(#pvaluesetdef{args=Args}) ->
- Args;
-get_pt_args(#pvaluedef{args=Args}) ->
- Args;
-get_pt_args(#pobjectdef{args=Args}) ->
- Args;
-get_pt_args(#pobjectsetdef{args=Args}) ->
- Args.
-
-get_pt_spec(#ptypedef{typespec=Type}) ->
- Type;
-get_pt_spec(#pvaluedef{value=Value}) ->
- Value;
-get_pt_spec(#pvaluesetdef{valueset=VS}) ->
- VS;
-get_pt_spec(#pobjectdef{def=Def}) ->
- Def;
-get_pt_spec(#pobjectsetdef{def=Def}) ->
- Def.
-
-
-
-match_args([FormArg|Ft], [ActArg|At], Acc) ->
- match_args(Ft, At, [{FormArg,ActArg}|Acc]);
-match_args([], [], Acc) ->
- lists:reverse(Acc);
-match_args(_, _, _) ->
- throw({error,{asn1,{wrong_number_of_arguments}}}).
-
-check_constraints(S,C) when list(C) ->
- check_constraints(S, C, []);
-check_constraints(S,C) when record(C,constraint) ->
- check_constraints(S, C#constraint.c, []).
-
-
-resolv_tuple_or_list(S,List) when list(List) ->
- lists:map(fun(X)->resolv_value(S,X) end, List);
-resolv_tuple_or_list(S,{Lb,Ub}) ->
- {resolv_value(S,Lb),resolv_value(S,Ub)}.
-
-%%%-----------------------------------------
-%% If the constraint value is a defined value the valuename
-%% is replaced by the actual value
-%%
-resolv_value(S,Val) ->
- case match_parameters(Val, S#state.parameters) of
- Id -> % unchanged
- resolv_value1(S,Id);
- Other ->
- resolv_value(S,Other)
- end.
-
-resolv_value1(S = #state{mname=M,inputmodules=InpMods},
- V=#'Externalvaluereference'{pos=Pos,module=ExtM,value=Name}) ->
- case ExtM of
- M -> resolv_value2(S,M,Name,Pos);
- _ ->
- case lists:member(ExtM,InpMods) of
- true ->
- resolv_value2(S,M,Name,Pos);
- false ->
- V
- end
- end;
-resolv_value1(S,{gt,V}) ->
- case V of
- Int when integer(Int) ->
- V + 1;
- #valuedef{value=Int} ->
- 1 + resolv_value(S,Int);
- Other ->
- throw({error,{asn1,{undefined_type_or_value,Other}}})
- end;
-resolv_value1(S,{lt,V}) ->
- case V of
- Int when integer(Int) ->
- V - 1;
- #valuedef{value=Int} ->
- resolv_value(S,Int) - 1;
- Other ->
- throw({error,{asn1,{undefined_type_or_value,Other}}})
- end;
-resolv_value1(S,{'ValueFromObject',{object,Object},[{valuefieldreference,
- FieldName}]}) ->
- %% FieldName can hold either a fixed-type value or a variable-type value
- %% Object is a DefinedObject, i.e. a #'Externaltypereference'
- {_,ObjTDef} = get_referenced_type(S,Object),
- TS = check_object(S,ObjTDef,ObjTDef#typedef.typespec),
- {_,_,Components} = TS#'Object'.def,
- case lists:keysearch(FieldName,1,Components) of
- {value,{_,#valuedef{value=Val}}} ->
- Val;
- _ ->
- error({value,"illegal value in constraint",S})
- end;
-% resolv_value1(S,{'ValueFromObject',{po,Object,Params},FieldName}) ->
-% %% FieldName can hold either a fixed-type value or a variable-type value
-% %% Object is a ParameterizedObject
-resolv_value1(_,V) ->
- V.
-
-resolv_value2(S,ModuleName,Name,Pos) ->
- case asn1_db:dbget(ModuleName,Name) of
- undefined ->
- case imported(S,Name) of
- {ok,Imodule} ->
- {_,V2} = get_referenced(S,Imodule,Name,Pos),
- V2#valuedef.value;
- _ ->
- throw({error,{asn1,{undefined_type_or_value,Name}}})
- end;
- Val ->
- Val#valuedef.value
- end.
-
-check_constraints(S,[{'ContainedSubtype',Type} | Rest], Acc) ->
- {_,CTDef} = get_referenced_type(S,Type#type.def),
- CType = check_type(S,S#state.tname,CTDef#typedef.typespec),
- check_constraints(S,Rest,CType#type.constraint ++ Acc);
-check_constraints(S,[C | Rest], Acc) ->
- check_constraints(S,Rest,[check_constraint(S,C) | Acc]);
-check_constraints(S,[],Acc) ->
-% io:format("Acc: ~p~n",[Acc]),
- C = constraint_merge(S,lists:reverse(Acc)),
-% io:format("C: ~p~n",[C]),
- lists:flatten(C).
-
-
-range_check(F={FixV,FixV}) ->
-% FixV;
- F;
-range_check(VR={Lb,Ub}) when Lb < Ub ->
- VR;
-range_check(Err={_,_}) ->
- throw({error,{asn1,{illegal_size_constraint,Err}}});
-range_check(Value) ->
- Value.
-
-check_constraint(S,Ext) when record(Ext,'Externaltypereference') ->
- check_externaltypereference(S,Ext);
-
-
-check_constraint(S,{'SizeConstraint',{Lb,Ub}})
- when list(Lb);tuple(Lb),size(Lb)==2 ->
- case Lb of
- #'Externalvaluereference'{} ->
- check_constraint(S,{'SizeConstraint',{resolv_value(S,Lb),Ub}});
- _ ->
- NewLb = range_check(resolv_tuple_or_list(S,Lb)),
- NewUb = range_check(resolv_tuple_or_list(S,Ub)),
- {'SizeConstraint',{NewLb,NewUb}}
- end;
-check_constraint(S,{'SizeConstraint',{Lb,Ub}}) ->
- case {resolv_value(S,Lb),resolv_value(S,Ub)} of
- {FixV,FixV} ->
- {'SizeConstraint',FixV};
- {Low,High} when Low < High ->
- {'SizeConstraint',{Low,High}};
- Err ->
- throw({error,{asn1,{illegal_size_constraint,Err}}})
- end;
-check_constraint(S,{'SizeConstraint',Lb}) ->
- {'SizeConstraint',resolv_value(S,Lb)};
-
-check_constraint(S,{'SingleValue', L}) when list(L) ->
- F = fun(A) -> resolv_value(S,A) end,
- {'SingleValue',lists:map(F,L)};
-
-check_constraint(S,{'SingleValue', V}) when integer(V) ->
- Val = resolv_value(S,V),
-%% [{'SingleValue',Val},{'ValueRange',{Val,Val}}]; % Why adding value range?
- {'SingleValue',Val};
-check_constraint(S,{'SingleValue', V}) ->
- {'SingleValue',resolv_value(S,V)};
-
-check_constraint(S,{'ValueRange', {Lb, Ub}}) ->
- {'ValueRange',{resolv_value(S,Lb),resolv_value(S,Ub)}};
-
-%%check_constraint(S,{'ContainedSubtype',Type}) ->
-%% #typedef{typespec=TSpec} =
-%% check_type(S,S#state.tname,get_referenced_type(S,Type#type.def)),
-%% [C] = TSpec#type.constraint,
-%% C;
-
-check_constraint(S,{valueset,Type}) ->
- {valueset,check_type(S,S#state.tname,Type)};
-
-check_constraint(S,{simpletable,Type}) ->
- OSName = (Type#type.def)#'Externaltypereference'.type,
- C = match_parameters(Type#type.def,S#state.parameters),
- case C of
- #'Externaltypereference'{} ->
- Type#type{def=check_externaltypereference(S,C)},
- {simpletable,OSName};
- _ ->
- check_type(S,S#state.tname,Type),
- {simpletable,OSName}
- end;
-
-check_constraint(S,{componentrelation,{objectset,Opos,Objset},Id}) ->
- %% Objset is an 'Externaltypereference' record, since Objset is
- %% a DefinedObjectSet.
- RealObjset = match_parameters(Objset,S#state.parameters),
- Ext = check_externaltypereference(S,RealObjset),
- {componentrelation,{objectset,Opos,Ext},Id};
-
-check_constraint(S,Type) when record(Type,type) ->
- #type{def=Def} = check_type(S,S#state.tname,Type),
- Def;
-
-check_constraint(S,C) when list(C) ->
- lists:map(fun(X)->check_constraint(S,X) end,C);
-% else keep the constraint unchanged
-check_constraint(_S,Any) ->
-% io:format("Constraint = ~p~n",[Any]),
- Any.
-
-%% constraint_merge/2
-%% Compute the intersection of the outermost level of the constraint list.
-%% See Dubuisson second paragraph and fotnote on page 285.
-%% If constraints with extension are included in combined constraints. The
-%% resulting combination will have the extension of the last constraint. Thus,
-%% there will be no extension if the last constraint is without extension.
-%% The rootset of all constraints are considered in the "outermoust
-%% intersection". See section 13.1.2 in Dubuisson.
-constraint_merge(_S,C=[H])when tuple(H) ->
- C;
-constraint_merge(_S,[]) ->
- [];
-constraint_merge(S,C) ->
- %% skip all extension but the last
- C1 = filter_extensions(C),
- %% perform all internal level intersections, intersections first
- %% since they have precedence over unions
- C2 = lists:map(fun(X)when list(X)->constraint_intersection(S,X);
- (X) -> X end,
- C1),
- %% perform all internal level unions
- C3 = lists:map(fun(X)when list(X)->constraint_union(S,X);
- (X) -> X end,
- C2),
-
- %% now get intersection of the outermost level
- %% get the least common single value constraint
- SVs = get_constraints(C3,'SingleValue'),
- CombSV = intersection_of_sv(S,SVs),
- %% get the least common value range constraint
- VRs = get_constraints(C3,'ValueRange'),
- CombVR = intersection_of_vr(S,VRs),
- %% get the least common size constraint
- SZs = get_constraints(C3,'SizeConstraint'),
- CombSZ = intersection_of_size(S,SZs),
- CminusSVs=ordsets:subtract(ordsets:from_list(C3),ordsets:from_list(SVs)),
- % CminusSVsVRs = ordsets:subtract(ordsets:from_list(CminusSVs),
-% ordsets:from_list(VRs)),
- RestC = ordsets:subtract(ordsets:from_list(CminusSVs),
- ordsets:from_list(SZs)),
- %% get the least common combined constraint. That is the union of each
- %% deep costraint and merge of single value and value range constraints
- combine_constraints(S,CombSV,CombVR,CombSZ++RestC).
-
-%% constraint_union(S,C) takes a list of constraints as input and
-%% merge them to a union. Unions are performed when two
-%% constraints is found with an atom union between.
-%% The list may be nested. Fix that later !!!
-constraint_union(_S,[]) ->
- [];
-constraint_union(_S,C=[_E]) ->
- C;
-constraint_union(S,C) when list(C) ->
- case lists:member(union,C) of
- true ->
- constraint_union1(S,C,[]);
- _ ->
- C
- end;
-% SV = get_constraints(C,'SingleValue'),
-% SV1 = constraint_union_sv(S,SV),
-% VR = get_constraints(C,'ValueRange'),
-% VR1 = constraint_union_vr(VR),
-% RestC = ordsets:filter(fun({'SingleValue',_})->false;
-% ({'ValueRange',_})->false;
-% (_) -> true end,ordsets:from_list(C)),
-% SV1++VR1++RestC;
-constraint_union(_S,C) ->
- [C].
-
-constraint_union1(S,[A={'ValueRange',_},union,B={'ValueRange',_}|Rest],Acc) ->
- AunionB = constraint_union_vr([A,B]),
- constraint_union1(S,Rest,AunionB++Acc);
-constraint_union1(S,[A={'SingleValue',_},union,B={'SingleValue',_}|Rest],Acc) ->
- AunionB = constraint_union_sv(S,[A,B]),
- constraint_union1(S,Rest,AunionB++Acc);
-constraint_union1(S,[A={'SingleValue',_},union,B={'ValueRange',_}|Rest],Acc) ->
- AunionB = union_sv_vr(S,A,B),
- constraint_union1(S,Rest,AunionB++Acc);
-constraint_union1(S,[A={'ValueRange',_},union,B={'SingleValue',_}|Rest],Acc) ->
- AunionB = union_sv_vr(S,B,A),
- constraint_union1(S,Rest,AunionB++Acc);
-constraint_union1(S,[union|Rest],Acc) -> %skip when unsupported constraints
- constraint_union1(S,Rest,Acc);
-constraint_union1(S,[A|Rest],Acc) ->
- constraint_union1(S,Rest,[A|Acc]);
-constraint_union1(_S,[],Acc) ->
- lists:reverse(Acc).
-
-constraint_union_sv(_S,SV) ->
- Values=lists:map(fun({_,V})->V end,SV),
- case ordsets:from_list(Values) of
- [] -> [];
- [N] -> [{'SingleValue',N}];
- L -> [{'SingleValue',L}]
- end.
-
-%% REMOVE????
-%%constraint_union(S,VR,'ValueRange') ->
-%% constraint_union_vr(VR).
-
-%% constraint_union_vr(VR)
-%% VR = [{'ValueRange',{Lb,Ub}},...]
-%% Lb = 'MIN' | integer()
-%% Ub = 'MAX' | integer()
-%% Returns if possible only one ValueRange tuple with a range that
-%% is a union of all ranges in VR.
-constraint_union_vr(VR) ->
- %% Sort VR by Lb in first hand and by Ub in second hand
- Fun=fun({_,{'MIN',_B1}},{_,{A2,_B2}}) when integer(A2)->true;
- ({_,{A1,_B1}},{_,{'MAX',_B2}}) when integer(A1) -> true;
- ({_,{A1,_B1}},{_,{A2,_B2}}) when integer(A1),integer(A2),A1<A2 -> true;
- ({_,{A,B1}},{_,{A,B2}}) when B1=<B2->true;
- (_,_)->false end,
- constraint_union_vr(lists:usort(Fun,VR),[]).
-
-constraint_union_vr([],Acc) ->
- lists:reverse(Acc);
-constraint_union_vr([C|Rest],[]) ->
- constraint_union_vr(Rest,[C]);
-constraint_union_vr([{_,{Lb,Ub2}}|Rest],[{_,{Lb,_Ub1}}|Acc]) -> %Ub2 > Ub1
- constraint_union_vr(Rest,[{'ValueRange',{Lb,Ub2}}|Acc]);
-constraint_union_vr([{_,{_,Ub}}|Rest],A=[{_,{_,Ub}}|_Acc]) ->
- constraint_union_vr(Rest,A);
-constraint_union_vr([{_,{Lb2,Ub2}}|Rest],[{_,{Lb1,Ub1}}|Acc]) when Lb2=<Ub1,
- Ub2>Ub1->
- constraint_union_vr(Rest,[{'ValueRange',{Lb1,Ub2}}|Acc]);
-constraint_union_vr([{_,{_,Ub2}}|Rest],A=[{_,{_,Ub1}}|_Acc]) when Ub2=<Ub1->
- constraint_union_vr(Rest,A);
-constraint_union_vr([VR|Rest],Acc) ->
- constraint_union_vr(Rest,[VR|Acc]).
-
-union_sv_vr(_S,[],B) ->
- [B];
-union_sv_vr(_S,A,[]) ->
- [A];
-union_sv_vr(_S,C1={'SingleValue',SV},C2={'ValueRange',VR={Lb,Ub}})
- when integer(SV) ->
- case is_int_in_vr(SV,C2) of
- true -> [C2];
- _ ->
- case VR of
- {'MIN',Ub} when SV==Ub+1 -> [{'ValueRange',{'MIN',SV}}];
- {Lb,'MAX'} when SV==Lb-1 -> [{'ValueRange',{SV,'MAX'}}];
- {Lb,Ub} when SV==Ub+1 -> [{'ValueRange',{Lb,SV}}];
- {Lb,Ub} when SV==Lb-1 -> [{'ValueRange',{SV,Ub}}];
- _ ->
- [C1,C2]
- end
- end;
-union_sv_vr(_S,C1={'SingleValue',SV},C2={'ValueRange',{_Lb,_Ub}})
- when list(SV) ->
- case lists:filter(fun(X)->is_int_in_vr(X,C2) end,SV) of
- [] -> [C2];
- L ->
- case expand_vr(L,C2) of
- {[],C3} -> [C3];
- {L,C2} -> [C1,C2];
- {[Val],C3} -> [{'SingleValue',Val},C3];
- {L2,C3} -> [{'SingleValue',L2},C3]
- end
- end.
-
-expand_vr(L,VR={_,{Lb,Ub}}) ->
- case lower_Lb(L,Lb) of
- false ->
- case higher_Ub(L,Ub) of
- false ->
- {L,VR};
- {L1,UbNew} ->
- expand_vr(L1,{'ValueRange',{Lb,UbNew}})
- end;
- {L1,LbNew} ->
- expand_vr(L1,{'ValueRange',{LbNew,Ub}})
- end.
-
-lower_Lb(_,'MIN') ->
- false;
-lower_Lb(L,Lb) ->
- remove_val_from_list(Lb - 1,L).
-
-higher_Ub(_,'MAX') ->
- false;
-higher_Ub(L,Ub) ->
- remove_val_from_list(Ub + 1,L).
-
-remove_val_from_list(List,Val) ->
- case lists:member(Val,List) of
- true ->
- {lists:delete(Val,List),Val};
- false ->
- false
- end.
-
-%% get_constraints/2
-%% Arguments are a list of constraints, which has the format {key,value},
-%% and a constraint type
-%% Returns a list of constraints only of the requested type or the atom
-%% 'no' if no such constraints were found
-get_constraints(L=[{CType,_}],CType) ->
- L;
-get_constraints(C,CType) ->
- keysearch_allwithkey(CType,1,C).
-
-%% keysearch_allwithkey(Key,Ix,L)
-%% Types:
-%% Key = atom()
-%% Ix = integer()
-%% L = [TwoTuple]
-%% TwoTuple = [{atom(),term()}|...]
-%% Returns a List that contains all
-%% elements from L that has a key Key as element Ix
-keysearch_allwithkey(Key,Ix,L) ->
- lists:filter(fun(X) when tuple(X) ->
- case element(Ix,X) of
- Key -> true;
- _ -> false
- end;
- (_) -> false
- end, L).
-
-
-%% filter_extensions(C)
-%% takes a list of constraints as input and
-%% returns a list with the intersection of all extension roots
-%% and only the extension of the last constraint kept if any
-%% extension in the last constraint
-filter_extensions([]) ->
- [];
-filter_extensions(C=[_H]) ->
- C;
-filter_extensions(C) when list(C) ->
- filter_extensions(C,[]).
-
-filter_extensions([C],Acc) ->
- lists:reverse([C|Acc]);
-filter_extensions([{C,_E},H2|T],Acc) when tuple(C) ->
- filter_extensions([H2|T],[C|Acc]);
-filter_extensions([{'SizeConstraint',{A,_B}},H2|T],Acc)
- when list(A);tuple(A) ->
- filter_extensions([H2|T],[{'SizeConstraint',A}|Acc]);
-filter_extensions([H1,H2|T],Acc) ->
- filter_extensions([H2|T],[H1|Acc]).
-
-%% constraint_intersection(S,C) takes a list of constraints as input and
-%% performs intersections. Intersecions are performed when an
-%% atom intersection is found between two constraints.
-%% The list may be nested. Fix that later !!!
-constraint_intersection(_S,[]) ->
- [];
-constraint_intersection(_S,C=[_E]) ->
- C;
-constraint_intersection(S,C) when list(C) ->
-% io:format("constraint_intersection: ~p~n",[C]),
- case lists:member(intersection,C) of
- true ->
- constraint_intersection1(S,C,[]);
- _ ->
- C
- end;
-constraint_intersection(_S,C) ->
- [C].
-
-constraint_intersection1(S,[A,intersection,B|Rest],Acc) ->
- AisecB = c_intersect(S,A,B),
- constraint_intersection1(S,Rest,AisecB++Acc);
-constraint_intersection1(S,[A|Rest],Acc) ->
- constraint_intersection1(S,Rest,[A|Acc]);
-constraint_intersection1(_,[],Acc) ->
- lists:reverse(Acc).
-
-c_intersect(S,C1={'SingleValue',_},C2={'SingleValue',_}) ->
- intersection_of_sv(S,[C1,C2]);
-c_intersect(S,C1={'ValueRange',_},C2={'ValueRange',_}) ->
- intersection_of_vr(S,[C1,C2]);
-c_intersect(S,C1={'ValueRange',_},C2={'SingleValue',_}) ->
- intersection_sv_vr(S,[C2],[C1]);
-c_intersect(S,C1={'SingleValue',_},C2={'ValueRange',_}) ->
- intersection_sv_vr(S,[C1],[C2]);
-c_intersect(_S,C1,C2) ->
- [C1,C2].
-
-%% combine_constraints(S,SV,VR,CComb)
-%% Types:
-%% S = record(state,S)
-%% SV = [] | [SVC]
-%% VR = [] | [VRC]
-%% CComb = [] | [Lists]
-%% SVC = {'SingleValue',integer()} | {'SingleValue',[integer(),...]}
-%% VRC = {'ValueRange',{Lb,Ub}}
-%% Lists = List of lists containing any constraint combination
-%% Lb = 'MIN' | integer()
-%% Ub = 'MAX' | integer()
-%% Returns a combination of the least common constraint among SV,VR and all
-%% elements in CComb
-combine_constraints(_S,[],VR,CComb) ->
- VR ++ CComb;
-% combine_combined_cnstr(S,VR,CComb);
-combine_constraints(_S,SV,[],CComb) ->
- SV ++ CComb;
-% combine_combined_cnstr(S,SV,CComb);
-combine_constraints(S,SV,VR,CComb) ->
- C=intersection_sv_vr(S,SV,VR),
- C ++ CComb.
-% combine_combined_cnstr(S,C,CComb).
-
-intersection_sv_vr(_,[],_VR) ->
- [];
-intersection_sv_vr(_,_SV,[]) ->
- [];
-intersection_sv_vr(_S,[C1={'SingleValue',SV}],[C2={'ValueRange',{_Lb,_Ub}}])
- when integer(SV) ->
- case is_int_in_vr(SV,C2) of
- true -> [C1];
- _ -> %%error({type,{"asn1 illegal constraint",C1,C2},S})
- throw({error,{"asn1 illegal constraint",C1,C2}})
- end;
-intersection_sv_vr(_S,[C1={'SingleValue',SV}],[C2])
- when list(SV) ->
- case lists:filter(fun(X)->is_int_in_vr(X,C2) end,SV) of
- [] ->
- %%error({type,{"asn1 illegal constraint",C1,C2},S});
- throw({error,{"asn1 illegal constraint",C1,C2}});
- [V] -> [{'SingleValue',V}];
- L -> [{'SingleValue',L}]
- end.
-
-
-
-intersection_of_size(_,[]) ->
- [];
-intersection_of_size(_,C=[_SZ]) ->
- C;
-intersection_of_size(S,[SZ,SZ|Rest]) ->
- intersection_of_size(S,[SZ|Rest]);
-intersection_of_size(S,C=[C1={_,Int},{_,Range}|Rest])
- when integer(Int),tuple(Range) ->
- case Range of
- {Lb,Ub} when Int >= Lb,
- Int =< Ub ->
- intersection_of_size(S,[C1|Rest]);
- _ ->
- throw({error,{asn1,{illegal_size_constraint,C}}})
- end;
-intersection_of_size(S,[C1={_,Range},C2={_,Int}|Rest])
- when integer(Int),tuple(Range) ->
- intersection_of_size(S,[C2,C1|Rest]);
-intersection_of_size(S,[{_,{Lb1,Ub1}},{_,{Lb2,Ub2}}|Rest]) ->
- Lb=greatest_LB(ordsets:from_list([Lb1,Lb2])),
- Ub=smallest_UB(ordsets:from_list([Ub1,Ub2])),
- intersection_of_size(S,[{'SizeConstraint',{Lb,Ub}}|Rest]);
-intersection_of_size(_,SZ) ->
- throw({error,{asn1,{illegal_size_constraint,SZ}}}).
-
-intersection_of_vr(_,[]) ->
- [];
-intersection_of_vr(_,VR=[_C]) ->
- VR;
-intersection_of_vr(S,[{_,{Lb1,Ub1}},{_,{Lb2,Ub2}}|Rest]) ->
- Lb=greatest_LB(ordsets:from_list([Lb1,Lb2])),
- Ub=smallest_UB(ordsets:from_list([Ub1,Ub2])),
- intersection_of_vr(S,[{'ValueRange',{Lb,Ub}}|Rest]);
-intersection_of_vr(_S,VR) ->
- %%error({type,{asn1,{illegal_value_range_constraint,VR}},S});
- throw({error,{asn1,{illegal_value_range_constraint,VR}}}).
-
-intersection_of_sv(_,[]) ->
- [];
-intersection_of_sv(_,SV=[_C]) ->
- SV;
-intersection_of_sv(S,[SV,SV|Rest]) ->
- intersection_of_sv(S,[SV|Rest]);
-intersection_of_sv(S,[{_,Int},{_,SV}|Rest]) when integer(Int),
- list(SV) ->
- SV2=intersection_of_sv1(S,Int,SV),
- intersection_of_sv(S,[SV2|Rest]);
-intersection_of_sv(S,[{_,SV},{_,Int}|Rest]) when integer(Int),
- list(SV) ->
- SV2=intersection_of_sv1(S,Int,SV),
- intersection_of_sv(S,[SV2|Rest]);
-intersection_of_sv(S,[{_,SV1},{_,SV2}|Rest]) when list(SV1),
- list(SV2) ->
- SV3=common_set(SV1,SV2),
- intersection_of_sv(S,[SV3|Rest]);
-intersection_of_sv(_S,SV) ->
- %%error({type,{asn1,{illegal_single_value_constraint,SV}},S}).
- throw({error,{asn1,{illegal_single_value_constraint,SV}}}).
-
-intersection_of_sv1(_S,Int,SV) when integer(Int),list(SV) ->
- case lists:member(Int,SV) of
- true -> {'SingleValue',Int};
- _ ->
- %%error({type,{asn1,{illegal_single_value_constraint,Int,SV}},S})
- throw({error,{asn1,{illegal_single_value_constraint,Int,SV}}})
- end;
-intersection_of_sv1(_S,SV1,SV2) ->
- %%error({type,{asn1,{illegal_single_value_constraint,SV1,SV2}},S}).
- throw({error,{asn1,{illegal_single_value_constraint,SV1,SV2}}}).
-
-greatest_LB([H]) ->
- H;
-greatest_LB(L) ->
- greatest_LB1(lists:reverse(L)).
-greatest_LB1(['MIN',H2|_T])->
- H2;
-greatest_LB1([H|_T]) ->
- H.
-smallest_UB(L) ->
- hd(L).
-
-common_set(SV1,SV2) ->
- lists:filter(fun(X)->lists:member(X,SV1) end,SV2).
-
-is_int_in_vr(Int,{_,{'MIN','MAX'}}) when integer(Int) ->
- true;
-is_int_in_vr(Int,{_,{'MIN',Ub}}) when integer(Int),Int =< Ub ->
- true;
-is_int_in_vr(Int,{_,{Lb,'MAX'}}) when integer(Int),Int >= Lb ->
- true;
-is_int_in_vr(Int,{_,{Lb,Ub}}) when integer(Int),Int >= Lb,Int =< Ub ->
- true;
-is_int_in_vr(_,_) ->
- false.
-
-
-
-check_imported(_S,Imodule,Name) ->
- case asn1_db:dbget(Imodule,'MODULE') of
- undefined ->
- io:format("~s.asn1db not found~n",[Imodule]),
- io:format("Type ~s imported from non existing module ~s~n",[Name,Imodule]);
- Im when record(Im,module) ->
- case is_exported(Im,Name) of
- false ->
- io:format("Imported type ~s not exported from module ~s~n",[Name,Imodule]);
- _ ->
- ok
- end
- end,
- ok.
-
-is_exported(Module,Name) when record(Module,module) ->
- {exports,Exports} = Module#module.exports,
- case Exports of
- all ->
- true;
- [] ->
- false;
- L when list(L) ->
- case lists:keysearch(Name,#'Externaltypereference'.type,Exports) of
- false -> false;
- _ -> true
- end
- end.
-
-
-
-check_externaltypereference(S,Etref=#'Externaltypereference'{module=Emod})->
- Currmod = S#state.mname,
- MergedMods = S#state.inputmodules,
- case Emod of
- Currmod ->
- %% reference to current module or to imported reference
- check_reference(S,Etref);
- _ ->
- %% io:format("Type ~s IMPORTED FROM ~s~n",[Etype,Emod]),
- case lists:member(Emod,MergedMods) of
- true ->
- check_reference(S,Etref);
- false ->
- Etref
- end
- end.
-
-check_reference(S,#'Externaltypereference'{pos=Pos,module=Emod,type=Name}) ->
- ModName = S#state.mname,
- case asn1_db:dbget(ModName,Name) of
- undefined ->
- case imported(S,Name) of
- {ok,Imodule} ->
- check_imported(S,Imodule,Name),
- #'Externaltypereference'{module=Imodule,type=Name};
- _ ->
- %may be a renamed type in multi file compiling!
- {_,T}=renamed_reference(S,Name,Emod),
- NewName = asn1ct:get_name_of_def(T),
- NewPos = asn1ct:get_pos_of_def(T),
- #'Externaltypereference'{pos=NewPos,
- module=ModName,
- type=NewName}
- end;
- _ ->
- %% cannot do check_type here due to recursive definitions, like
- %% S ::= SEQUENCE {a INTEGER, b S}. This implies that references
- %% that appear before the definition will be an
- %% Externaltypereference in the abstract syntax tree
- #'Externaltypereference'{pos=Pos,module=ModName,type=Name}
- end.
-
-
-name2Extref(_Mod,Name) when record(Name,'Externaltypereference') ->
- Name;
-name2Extref(Mod,Name) ->
- #'Externaltypereference'{module=Mod,type=Name}.
-
-get_referenced_type(S,Ext) when record(Ext,'Externaltypereference') ->
- case match_parameters(Ext, S#state.parameters) of
- Ext ->
- #'Externaltypereference'{pos=Pos,module=Emod,type=Etype} = Ext,
- case S#state.mname of
- Emod -> % a local reference in this module
- get_referenced1(S,Emod,Etype,Pos);
- _ ->% always when multi file compiling
- case lists:member(Emod,S#state.inputmodules) of
- true ->
- get_referenced1(S,Emod,Etype,Pos);
- false ->
- get_referenced(S,Emod,Etype,Pos)
- end
- end;
- Other ->
- {undefined,Other}
- end;
-get_referenced_type(S=#state{mname=Emod},
- ERef=#'Externalvaluereference'{pos=P,module=Emod,
- value=Eval}) ->
- case match_parameters(ERef,S#state.parameters) of
- ERef ->
- get_referenced1(S,Emod,Eval,P);
- OtherERef when record(OtherERef,'Externalvaluereference') ->
- get_referenced_type(S,OtherERef);
- Value ->
- {Emod,Value}
- end;
-get_referenced_type(S,ERef=#'Externalvaluereference'{pos=Pos,module=Emod,
- value=Eval}) ->
- case match_parameters(ERef,S#state.parameters) of
- ERef ->
- case lists:member(Emod,S#state.inputmodules) of
- true ->
- get_referenced1(S,Emod,Eval,Pos);
- false ->
- get_referenced(S,Emod,Eval,Pos)
- end;
- OtherERef ->
- get_referenced_type(S,OtherERef)
- end;
-get_referenced_type(S,#identifier{val=Name,pos=Pos}) ->
- get_referenced1(S,undefined,Name,Pos);
-get_referenced_type(_S,Type) ->
- {undefined,Type}.
-
-%% get_referenced/3
-%% The referenced entity Ename may in case of an imported parameterized
-%% type reference imported entities in the other module, which implies that
-%% asn1_db:dbget will fail even though the referenced entity exists. Thus
-%% Emod may be the module that imports the entity Ename and not holds the
-%% data about Ename.
-get_referenced(S,Emod,Ename,Pos) ->
- case asn1_db:dbget(Emod,Ename) of
- undefined ->
- %% May be an imported entity in module Emod
-% throw({error,{asn1,{undefined_type_or_value,{Emod,Ename}}}});
- NewS = S#state{module=asn1_db:dbget(Emod,'MODULE')},
- get_imported(NewS,Ename,Emod,Pos);
- T when record(T,typedef) ->
- Spec = T#typedef.typespec,
- case Spec#type.def of
- Tref when record(Tref,typereference) ->
- Def = #'Externaltypereference'{module=Emod,
- type=Tref#typereference.val,
- pos=Tref#typereference.pos},
-
-
- {Emod,T#typedef{typespec=Spec#type{def=Def}}};
- _ ->
- {Emod,T} % should add check that T is exported here
- end;
- V -> {Emod,V}
- end.
-
-get_referenced1(S,ModuleName,Name,Pos) ->
- case asn1_db:dbget(S#state.mname,Name) of
- undefined ->
- %% ModuleName may be other than S#state.mname when
- %% multi file compiling is used.
- get_imported(S,Name,ModuleName,Pos);
- T ->
- {S#state.mname,T}
- end.
-
-get_imported(S,Name,Module,Pos) ->
- case imported(S,Name) of
- {ok,Imodule} ->
- case asn1_db:dbget(Imodule,'MODULE') of
- undefined ->
- throw({error,{asn1,{module_not_found,Imodule}}});
- Im when record(Im,module) ->
- case is_exported(Im,Name) of
- false ->
- throw({error,
- {asn1,{not_exported,{Im,Name}}}});
- _ ->
- get_referenced_type(S,
- #'Externaltypereference'
- {module=Imodule,
- type=Name,pos=Pos})
- end
- end;
- _ ->
- renamed_reference(S,Name,Module)
- end.
-
-renamed_reference(S,Name,Module) ->
- %% first check if there is a renamed type in this module
- %% second check if any type was imported with this name
- case ets:info(renamed_defs) of
- undefined -> throw({error,{asn1,{undefined_type,Name}}});
- _ ->
- case ets:match(renamed_defs,{'$1',Name,Module}) of
- [] ->
- case ets:info(original_imports) of
- undefined ->
- throw({error,{asn1,{undefined_type,Name}}});
- _ ->
- case ets:match(original_imports,{Module,'$1'}) of
- [] ->
- throw({error,{asn1,{undefined_type,Name}}});
- [[ImportsList]] ->
- case get_importmoduleoftype(ImportsList,Name) of
- undefined ->
- throw({error,{asn1,{undefined_type,Name}}});
- NextMod ->
- renamed_reference(S,Name,NextMod)
- end
- end
- end;
- [[NewTypeName]] ->
- get_referenced1(S,Module,NewTypeName,undefined)
- end
- end.
-
-get_importmoduleoftype([I|Is],Name) ->
- Index = #'Externaltypereference'.type,
- case lists:keysearch(Name,Index,I#'SymbolsFromModule'.symbols) of
- {value,_Ref} ->
- (I#'SymbolsFromModule'.module)#'Externaltypereference'.type;
- _ ->
- get_importmoduleoftype(Is,Name)
- end;
-get_importmoduleoftype([],_) ->
- undefined.
-
-
-match_parameters(Name,[]) ->
- Name;
-
-match_parameters(#'Externaltypereference'{type=Name},[{#'Externaltypereference'{type=Name},NewName}|_T]) ->
- NewName;
-match_parameters(#'Externaltypereference'{type=Name},[{{_,#'Externaltypereference'{type=Name}},NewName}|_T]) ->
- NewName;
-% match_parameters(#'Externaltypereference'{type=Name},[{#typereference{val=Name},NewName}|T]) ->
-% NewName;
-% match_parameters(#'Externaltypereference'{type=Name},[{{_,#typereference{val=Name}},NewName}|T]) ->
-% NewName;
-%match_parameters(#typereference{val=Name},[{#typereference{val=Name},NewName}|T]) ->
-% NewName;
-match_parameters(#'Externalvaluereference'{value=Name},[{#'Externalvaluereference'{value=Name},NewName}|_T]) ->
- NewName;
-match_parameters(#'Externalvaluereference'{value=Name},[{{_,#'Externalvaluereference'{value=Name}},NewName}|_T]) ->
- NewName;
-% match_parameters(#identifier{val=Name},[{#identifier{val=Name},NewName}|T]) ->
-% NewName;
-% match_parameters(#identifier{val=Name},[{{_,#identifier{val=Name}},NewName}|T]) ->
-% NewName;
-match_parameters({valueset,#type{def=#'Externaltypereference'{type=Name}}},
- [{{_,#'Externaltypereference'{type=Name}},{valueset,#type{def=NewName}}}|_T]) ->
- NewName;
-match_parameters({valueset,#type{def=#'Externaltypereference'{type=Name}}},
- [{{_,#'Externaltypereference'{type=Name}},NewName}|_T]) ->
- NewName;
-% match_parameters({valueset,#type{def=#'Externaltypereference'{type=Name}}},
-% [{{_,#typereference{val=Name}},{valueset,#type{def=NewName}}}|T]) ->
-% NewName;
-% match_parameters({valueset,#type{def=#'Externaltypereference'{type=Name}}},
-% [{{_,#typereference{val=Name}},NewName}|T]) ->
-% NewName;
-
-match_parameters(Name, [_H|T]) ->
- %%io:format("match_parameters(~p,~p)~n",[Name,[H|T]]),
- match_parameters(Name,T).
-
-imported(S,Name) ->
- {imports,Ilist} = (S#state.module)#module.imports,
- imported1(Name,Ilist).
-
-imported1(Name,
- [#'SymbolsFromModule'{symbols=Symlist,
- module=#'Externaltypereference'{type=ModuleName}}|T]) ->
- case lists:keysearch(Name,#'Externaltypereference'.type,Symlist) of
- {value,_V} ->
- {ok,ModuleName};
- _ ->
- imported1(Name,T)
- end;
-imported1(_Name,[]) ->
- false.
-
-
-check_integer(_S,[],_C) ->
- ok;
-check_integer(S,NamedNumberList,_C) ->
- case check_unique(NamedNumberList,2) of
- [] ->
- check_int(S,NamedNumberList,[]);
- L when list(L) ->
- error({type,{duplicates,L},S}),
- unchanged
-
- end.
-
-check_int(S,[{'NamedNumber',Id,Num}|T],Acc) when integer(Num) ->
- check_int(S,T,[{Id,Num}|Acc]);
-check_int(S,[{'NamedNumber',Id,{identifier,_,Name}}|T],Acc) ->
- Val = dbget_ex(S,S#state.mname,Name),
- check_int(S,[{'NamedNumber',Id,Val#valuedef.value}|T],Acc);
-check_int(_S,[],Acc) ->
- lists:keysort(2,Acc).
-
-
-
-check_bitstring(_S,[],_Constr) ->
- [];
-check_bitstring(S,NamedNumberList,_Constr) ->
- case check_unique(NamedNumberList,2) of
- [] ->
- check_bitstr(S,NamedNumberList,[]);
- L when list(L) ->
- error({type,{duplicates,L},S}),
- unchanged
- end.
-
-check_bitstr(S,[{'NamedNumber',Id,Num}|T],Acc)when integer(Num) ->
- check_bitstr(S,T,[{Id,Num}|Acc]);
-check_bitstr(S,[{'NamedNumber',Id,Name}|T],Acc) when atom(Name) ->
-%%check_bitstr(S,[{'NamedNumber',Id,{identifier,_,Name}}|T],Acc) ->
-%% io:format("asn1ct_check:check_bitstr/3 hej hop ~w~n",[Name]),
- Val = dbget_ex(S,S#state.mname,Name),
-%% io:format("asn1ct_check:check_bitstr/3: ~w~n",[Val]),
- check_bitstr(S,[{'NamedNumber',Id,Val#valuedef.value}|T],Acc);
-check_bitstr(S,[],Acc) ->
- case check_unique(Acc,2) of
- [] ->
- lists:keysort(2,Acc);
- L when list(L) ->
- error({type,{duplicate_values,L},S}),
- unchanged
- end.
-
-%%check_bitstring(S,NamedNumberList,Constr) ->
-%% NamedNumberList.
-
-%% Check INSTANCE OF
-%% check that DefinedObjectClass is of TYPE-IDENTIFIER class
-%% If Constraint is empty make it the general INSTANCE OF type
-%% If Constraint is not empty make an inlined type
-%% convert INSTANCE OF to the associated type
-check_instance_of(S,DefinedObjectClass,Constraint) ->
- check_type_identifier(S,DefinedObjectClass),
- iof_associated_type(S,Constraint).
-
-
-check_type_identifier(_S,'TYPE-IDENTIFIER') ->
- ok;
-check_type_identifier(S,Eref=#'Externaltypereference'{}) ->
- case get_referenced_type(S,Eref) of
- {_,#classdef{name='TYPE-IDENTIFIER'}} -> ok;
- {_,TD=#typedef{typespec=#type{def=#'Externaltypereference'{}}}} ->
- check_type_identifier(S,(TD#typedef.typespec)#type.def);
- _ ->
- error({type,{"object set in type INSTANCE OF "
- "not of class TYPE-IDENTIFIER",Eref},S})
- end.
-
-iof_associated_type(S,[]) ->
- %% in this case encode/decode functions for INSTANCE OF must be
- %% generated
- case get(instance_of) of
- undefined ->
- AssociateSeq = iof_associated_type1(S,[]),
- Tag =
- case S#state.erule of
- ber_bin_v2 ->
- [?TAG_CONSTRUCTED(?N_INSTANCE_OF)];
- _ -> []
- end,
- TypeDef=#typedef{checked=true,
- name='INSTANCE OF',
- typespec=#type{tag=Tag,
- def=AssociateSeq}},
- asn1_db:dbput(S#state.mname,'INSTANCE OF',TypeDef),
- put(instance_of,generate);
- _ ->
- ok
- end,
- #'Externaltypereference'{module=S#state.mname,type='INSTANCE OF'};
-iof_associated_type(S,C) ->
- iof_associated_type1(S,C).
-
-iof_associated_type1(S,C) ->
- {TableCInf,Comp1Cnstr,Comp2Cnstr,Comp2tablecinf}=
- instance_of_constraints(S,C),
-
- ModuleName = S#state.mname,
- Typefield_type=
- case C of
- [] -> 'ASN1_OPEN_TYPE';
- _ -> {typefield,'Type'}
- end,
- {ObjIdTag,C1TypeTag}=
- case S#state.erule of
- ber_bin_v2 ->
- {[{'UNIVERSAL',8}],
- [#tag{class='UNIVERSAL',
- number=6,
- type='IMPLICIT',
- form=0}]};
- _ -> {[{'UNIVERSAL','INTEGER'}],[]}
- end,
- TypeIdentifierRef=#'Externaltypereference'{module=ModuleName,
- type='TYPE-IDENTIFIER'},
- ObjectIdentifier =
- #'ObjectClassFieldType'{classname=TypeIdentifierRef,
- class=[],
- fieldname={id,[]},
- type={fixedtypevaluefield,id,
- #type{def='OBJECT IDENTIFIER'}}},
- Typefield =
- #'ObjectClassFieldType'{classname=TypeIdentifierRef,
- class=[],
- fieldname={'Type',[]},
- type=Typefield_type},
- IOFComponents =
- [#'ComponentType'{name='type-id',
- typespec=#type{tag=C1TypeTag,
- def=ObjectIdentifier,
- constraint=Comp1Cnstr},
- prop=mandatory,
- tags=ObjIdTag},
- #'ComponentType'{name=value,
- typespec=#type{tag=[#tag{class='CONTEXT',
- number=0,
- type='EXPLICIT',
- form=32}],
- def=Typefield,
- constraint=Comp2Cnstr,
- tablecinf=Comp2tablecinf},
- prop=mandatory,
- tags=[{'CONTEXT',0}]}],
- #'SEQUENCE'{tablecinf=TableCInf,
- components=IOFComponents}.
-
-
-%% returns the leading attribute, the constraint of the components and
-%% the tablecinf value for the second component.
-instance_of_constraints(_,[]) ->
- {false,[],[],[]};
-instance_of_constraints(S,#constraint{c={simpletable,Type}}) ->
- #type{def=#'Externaltypereference'{type=Name}} = Type,
- ModuleName = S#state.mname,
- ObjectSetRef=#'Externaltypereference'{module=ModuleName,
- type=Name},
- CRel=[{componentrelation,{objectset,
- undefined, %% pos
- ObjectSetRef},
- [{innermost,
- [#'Externalvaluereference'{module=ModuleName,
- value=type}]}]}],
- TableCInf=#simpletableattributes{objectsetname=Name,
- c_name='type-id',
- c_index=1,
- usedclassfield=id,
- uniqueclassfield=id,
- valueindex=[]},
- {TableCInf,[{simpletable,Name}],CRel,[{objfun,ObjectSetRef}]}.
-
-%% Check ENUMERATED
-%% ****************************************
-%% Check that all values are unique
-%% assign values to un-numbered identifiers
-%% check that the constraints are allowed and correct
-%% put the updated info back into database
-check_enumerated(_S,[{Name,Number}|Rest],_Constr) when atom(Name), integer(Number)->
- %% already checked , just return the same list
- [{Name,Number}|Rest];
-check_enumerated(S,NamedNumberList,_Constr) ->
- check_enum(S,NamedNumberList,[],[]).
-
-%% identifiers are put in Acc2
-%% returns either [{Name,Number}] or {[{Name,Number}],[{ExtName,ExtNumber}]}
-%% the latter is returned if the ENUMERATION contains EXTENSIONMARK
-check_enum(S,[{'NamedNumber',Id,Num}|T],Acc1,Acc2) when integer(Num) ->
- check_enum(S,T,[{Id,Num}|Acc1],Acc2);
-check_enum(S,[{'NamedNumber',Id,{identifier,_,Name}}|T],Acc1,Acc2) ->
- Val = dbget_ex(S,S#state.mname,Name),
- check_enum(S,[{'NamedNumber',Id,Val#valuedef.value}|T],Acc1,Acc2);
-check_enum(S,['EXTENSIONMARK'|T],Acc1,Acc2) ->
- NewAcc2 = lists:keysort(2,Acc1),
- NewList = enum_number(lists:reverse(Acc2),NewAcc2,0,[]),
- { NewList, check_enum(S,T,[],[])};
-check_enum(S,[Id|T],Acc1,Acc2) when atom(Id) ->
- check_enum(S,T,Acc1,[Id|Acc2]);
-check_enum(_S,[],Acc1,Acc2) ->
- NewAcc2 = lists:keysort(2,Acc1),
- enum_number(lists:reverse(Acc2),NewAcc2,0,[]).
-
-
-% assign numbers to identifiers , numbers from 0 ... but must not
-% be the same as already assigned to NamedNumbers
-enum_number([H|T],[{Id,Num}|T2],Cnt,Acc) when Num > Cnt ->
- enum_number(T,[{Id,Num}|T2],Cnt+1,[{H,Cnt}|Acc]);
-enum_number([H|T],[{Id,Num}|T2],Cnt,Acc) when Num < Cnt -> % negative Num
- enum_number(T,T2,Cnt+1,[{H,Cnt},{Id,Num}|Acc]);
-enum_number([],L2,_Cnt,Acc) ->
- lists:concat([lists:reverse(Acc),L2]);
-enum_number(L,[{Id,Num}|T2],Cnt,Acc) -> % Num == Cnt
- enum_number(L,T2,Cnt+1,[{Id,Num}|Acc]);
-enum_number([H|T],[],Cnt,Acc) ->
- enum_number(T,[],Cnt+1,[{H,Cnt}|Acc]).
-
-
-check_boolean(_S,_Constr) ->
- ok.
-
-check_octetstring(_S,_Constr) ->
- ok.
-
-% check all aspects of a SEQUENCE
-% - that all component names are unique
-% - that all TAGS are ok (when TAG default is applied)
-% - that each component is of a valid type
-% - that the extension marks are valid
-
-check_sequence(S,Type,Comps) ->
- Components = expand_components(S,Comps),
- case check_unique([C||C <- Components ,record(C,'ComponentType')]
- ,#'ComponentType'.name) of
- [] ->
- %% sort_canonical(Components),
- 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 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
- end,
- %% CRelInf is the "leading attribute" information
- %% necessary for code generating of the look up in the
- %% object set table,
- %% i.e. getenc_ObjectSet/getdec_ObjectSet.
- %% {objfun,ERef} tuple added in NewComps2 in tablecinf
- %% field in type record of component relation constrained
- %% type
-% io:format("NewComps: ~p~n",[NewComps]),
- {CRelInf,NewComps2} = componentrelation_leadingattr(S,NewComps),
-% io:format("CRelInf: ~p~n",[CRelInf]),
-% io:format("NewComps2: ~p~n",[NewComps2]),
- %% CompListWithTblInf has got a lot unecessary info about
- %% the involved class removed, as the class of the object
- %% set.
- CompListWithTblInf = get_tableconstraint_info(S,Type,NewComps2),
-% io:format("CompListWithTblInf: ~p~n",[CompListWithTblInf]),
- {CRelInf,CompListWithTblInf};
- Dupl ->
- throw({error,{asn1,{duplicate_components,Dupl}}})
- end.
-
-expand_components(S, [{'COMPONENTS OF',Type}|T]) ->
- CompList =
- case get_referenced_type(S,Type#type.def) of
- {_,#typedef{typespec=#type{def=Seq}}} when record(Seq,'SEQUENCE') ->
- case Seq#'SEQUENCE'.components of
- {Root,_Ext} -> Root;
- Root -> Root
- end;
- Err -> throw({error,{asn1,{illegal_COMPONENTS_OF,Err}}})
- end,
- expand_components(S,CompList) ++ expand_components(S,T);
-expand_components(S,[H|T]) ->
- [H|expand_components(S,T)];
-expand_components(_,[]) ->
- [].
-
-check_unique_sequence_tags(S,[#'ComponentType'{prop=mandatory}|Rest]) ->
- check_unique_sequence_tags(S,Rest);
-check_unique_sequence_tags(S,[C|Rest]) when record(C,'ComponentType') ->
- 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,[]) ->
- true.
-
-check_unique_sequence_tags1(S,[C|Rest],Acc) when record(C,'ComponentType') ->
- case C#'ComponentType'.prop of
- mandatory ->
- check_unique_tags(S,lists:reverse([C|Acc])),
- check_unique_sequence_tags(S,Rest);
- _ ->
- check_unique_sequence_tags1(S,Rest,[C|Acc]) % default or optional
- end;
-check_unique_sequence_tags1(S,[H|Rest],Acc) ->
- check_unique_sequence_tags1(S,Rest,[H|Acc]);
-check_unique_sequence_tags1(S,[],Acc) ->
- check_unique_tags(S,lists:reverse(Acc)).
-
-check_sequenceof(S,Type,Component) when record(Component,type) ->
- check_type(S,Type,Component).
-
-check_set(S,Type,Components) ->
- {TableCInf,NewComponents} = check_sequence(S,Type,Components),
- case lists:member(der,S#state.options) of
- true when S#state.erule == ber;
- S#state.erule == ber_bin ->
- {Sorted,SortedComponents} =
- sort_components(S#state.tname,
- (S#state.module)#module.tagdefault,
- NewComponents),
- {Sorted,TableCInf,SortedComponents};
- _ ->
- {false,TableCInf,NewComponents}
- end.
-
-sort_components(_TypeName,'AUTOMATIC',Components) ->
- {true,Components};
-sort_components(TypeName,_TagDefault,Components) ->
- case untagged_choice(Components) of
- false ->
- {true,sort_components1(TypeName,Components,[],[],[],[])};
- true ->
- {dynamic,Components} % sort in run-time
- end.
-
-sort_components1(TypeName,[C=#'ComponentType'{tags=[{'UNIVERSAL',_}|_R]}|Cs],
- UnivAcc,ApplAcc,ContAcc,PrivAcc) ->
- sort_components1(TypeName,Cs,[C|UnivAcc],ApplAcc,ContAcc,PrivAcc);
-sort_components1(TypeName,[C=#'ComponentType'{tags=[{'APPLICATION',_}|_R]}|Cs],
- UnivAcc,ApplAcc,ContAcc,PrivAcc) ->
- sort_components1(TypeName,Cs,UnivAcc,[C|ApplAcc],ContAcc,PrivAcc);
-sort_components1(TypeName,[C=#'ComponentType'{tags=[{'CONTEXT',_}|_R]}|Cs],
- UnivAcc,ApplAcc,ContAcc,PrivAcc) ->
- sort_components1(TypeName,Cs,UnivAcc,ApplAcc,[C|ContAcc],PrivAcc);
-sort_components1(TypeName,[C=#'ComponentType'{tags=[{'PRIVATE',_}|_R]}|Cs],
- UnivAcc,ApplAcc,ContAcc,PrivAcc) ->
- sort_components1(TypeName,Cs,UnivAcc,ApplAcc,ContAcc,[C|PrivAcc]);
-sort_components1(TypeName,[],UnivAcc,ApplAcc,ContAcc,PrivAcc) ->
- I = #'ComponentType'.tags,
- ascending_order_check(TypeName,sort_universal_type(UnivAcc)) ++
- ascending_order_check(TypeName,lists:keysort(I,ApplAcc)) ++
- ascending_order_check(TypeName,lists:keysort(I,ContAcc)) ++
- ascending_order_check(TypeName,lists:keysort(I,PrivAcc)).
-
-ascending_order_check(TypeName,Components) ->
- ascending_order_check1(TypeName,Components),
- Components.
-
-ascending_order_check1(TypeName,
- [C1 = #'ComponentType'{tags=[{_,T}|_]},
- C2 = #'ComponentType'{tags=[{_,T}|_]}|Rest]) ->
- io:format("WARNING: Indistinct tag ~p in SET ~p, components ~p and ~p~n",
- [T,TypeName,C1#'ComponentType'.name,C2#'ComponentType'.name]),
- ascending_order_check1(TypeName,[C2|Rest]);
-ascending_order_check1(TypeName,
- [C1 = #'ComponentType'{tags=[{'UNIVERSAL',T1}|_]},
- C2 = #'ComponentType'{tags=[{'UNIVERSAL',T2}|_]}|Rest]) ->
- case (asn1ct_gen_ber:decode_type(T1) == asn1ct_gen_ber:decode_type(T2)) of
- true ->
- io:format("WARNING: Indistinct tags ~p and ~p in"
- " SET ~p, components ~p and ~p~n",
- [T1,T2,TypeName,C1#'ComponentType'.name,
- C2#'ComponentType'.name]),
- ascending_order_check1(TypeName,[C2|Rest]);
- _ ->
- ascending_order_check1(TypeName,[C2|Rest])
- end;
-ascending_order_check1(N,[_|Rest]) ->
- ascending_order_check1(N,Rest);
-ascending_order_check1(_,[_]) ->
- ok;
-ascending_order_check1(_,[]) ->
- ok.
-
-sort_universal_type(Components) ->
- List = lists:map(fun(C) ->
- #'ComponentType'{tags=[{_,T}|_]} = C,
- {asn1ct_gen_ber:decode_type(T),C}
- end,
- Components),
- SortedList = lists:keysort(1,List),
- lists:map(fun(X)->element(2,X) end,SortedList).
-
-untagged_choice([#'ComponentType'{typespec=#type{tag=[],def={'CHOICE',_}}}|_Rest]) ->
- true;
-untagged_choice([_|Rest]) ->
- untagged_choice(Rest);
-untagged_choice([]) ->
- false.
-
-check_setof(S,Type,Component) when record(Component,type) ->
- check_type(S,Type,Component).
-
-check_restrictedstring(_S,_Def,_Constr) ->
- ok.
-
-check_objectidentifier(_S,_Constr) ->
- ok.
-
-% check all aspects of a CHOICE
-% - that all alternative names are unique
-% - that all TAGS are ok (when TAG default is applied)
-% - that each alternative is of a valid type
-% - that the extension marks are valid
-check_choice(S,Type,Components) when list(Components) ->
- case check_unique([C||C <- Components,
- record(C,'ComponentType')],#'ComponentType'.name) of
- [] ->
- %% 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;
-%% CompListWithTblInf = get_tableconstraint_info(S,Type,NewComps);
- Dupl ->
- throw({error,{asn1,{duplicate_choice_alternatives,Dupl}}})
- end;
-check_choice(_S,_,[]) ->
- [].
-
-%% probably dead code that should be removed
-%%maybe_automatic_tags(S,{Rc,Ec}) ->
-%% {maybe_automatic_tags1(S,Rc,0),maybe_automatic_tags1(S,Ec,length(Rc))};
-maybe_automatic_tags(#state{erule=per},C) ->
- C;
-maybe_automatic_tags(#state{erule=per_bin},C) ->
- C;
-maybe_automatic_tags(S,C) ->
- maybe_automatic_tags1(S,C,0).
-
-maybe_automatic_tags1(S,C,TagNo) ->
- case (S#state.module)#module.tagdefault of
- 'AUTOMATIC' ->
- generate_automatic_tags(S,C,TagNo);
- _ ->
- %% maybe is the module a multi file module were only some of
- %% the modules have defaulttag AUTOMATIC TAGS then the names
- %% of those types are saved in the table automatic_tags
- Name= S#state.tname,
- case is_automatic_tagged_in_multi_file(Name) of
- true ->
- generate_automatic_tags(S,C,TagNo);
- false ->
- C
- end
- end.
-
-is_automatic_tagged_in_multi_file(Name) ->
- case ets:info(automatic_tags) of
- undefined ->
- %% this case when not multifile compilation
- false;
- _ ->
- case ets:member(automatic_tags,Name) of
- true ->
- true;
- _ ->
- false
- end
- end.
-
-generate_automatic_tags(_S,C,TagNo) ->
- case any_manual_tag(C) of
- true ->
- C;
- false ->
- generate_automatic_tags1(C,TagNo)
- end.
-
-generate_automatic_tags1([H|T],TagNo) when record(H,'ComponentType') ->
- #'ComponentType'{typespec=Ts} = H,
- NewTs = Ts#type{tag=[#tag{class='CONTEXT',
- number=TagNo,
- type={default,'IMPLICIT'},
- form= 0 }]}, % PRIMITIVE
- [H#'ComponentType'{typespec=NewTs}|generate_automatic_tags1(T,TagNo+1)];
-generate_automatic_tags1([ExtMark|T],TagNo) -> % EXTENSIONMARK
- [ExtMark | generate_automatic_tags1(T,TagNo)];
-generate_automatic_tags1([],_) ->
- [].
-
-any_manual_tag([#'ComponentType'{typespec=#type{tag=[]}}|Rest]) ->
- any_manual_tag(Rest);
-any_manual_tag([{'EXTENSIONMARK',_,_}|Rest]) ->
- any_manual_tag(Rest);
-any_manual_tag([_|_Rest]) ->
- true;
-any_manual_tag([]) ->
- false.
-
-
-check_unique_tags(S,C) ->
- case (S#state.module)#module.tagdefault of
- 'AUTOMATIC' ->
- case any_manual_tag(C) of
- false -> true;
- _ -> collect_and_sort_tags(C,[])
- end;
- _ ->
- collect_and_sort_tags(C,[])
- end.
-
-collect_and_sort_tags([C|Rest],Acc) when record(C,'ComponentType') ->
- collect_and_sort_tags(Rest,C#'ComponentType'.tags ++ Acc);
-collect_and_sort_tags([_|Rest],Acc) ->
- collect_and_sort_tags(Rest,Acc);
-collect_and_sort_tags([],Acc) ->
- {Dupl,_}= lists:mapfoldl(fun(El,El)->{{dup,El},El};(El,_Prev)-> {El,El} end,notag,lists:sort(Acc)),
- Dupl2 = [Dup|| {dup,Dup} <- Dupl],
- if
- length(Dupl2) > 0 ->
- throw({error,{asn1,{duplicates_of_the_tags,Dupl2}}});
- true ->
- true
- end.
-
-check_unique(L,Pos) ->
- Slist = lists:keysort(Pos,L),
- check_unique2(Slist,Pos,[]).
-
-check_unique2([A,B|T],Pos,Acc) when element(Pos,A) == element(Pos,B) ->
- check_unique2([B|T],Pos,[element(Pos,B)|Acc]);
-check_unique2([_|T],Pos,Acc) ->
- check_unique2(T,Pos,Acc);
-check_unique2([],_,Acc) ->
- lists:reverse(Acc).
-
-check_each_component(S,Type,{Rlist,ExtList}) ->
- {check_each_component(S,Type,Rlist),
- check_each_component(S,Type,ExtList)};
-check_each_component(S,Type,Components) ->
- check_each_component(S,Type,Components,[],[],noext).
-
-check_each_component(S = #state{abscomppath=Path,recordtopname=TopName},Type,
- [C|Ct],Acc,Extacc,Ext) when record(C,'ComponentType') ->
- #'ComponentType'{name=Cname,typespec=Ts,prop=Prop} = C,
- NewAbsCPath =
- case Ts#type.def of
- #'Externaltypereference'{} -> [];
- _ -> [Cname|Path]
- end,
- CheckedTs = check_type(S#state{abscomppath=NewAbsCPath,
- recordtopname=[Cname|TopName]},Type,Ts),
- NewTags = get_taglist(S,CheckedTs),
-
- NewProp =
-% case lists:member(der,S#state.options) of
-% true ->
-% True ->
- case normalize_value(S,CheckedTs,Prop,[Cname|TopName]) of
- mandatory -> mandatory;
- 'OPTIONAL' -> 'OPTIONAL';
- DefaultValue -> {'DEFAULT',DefaultValue}
- end,
-% _ ->
-% Prop
-% end,
- NewC = C#'ComponentType'{typespec=CheckedTs,prop=NewProp,tags=NewTags},
- case Ext of
- noext ->
- check_each_component(S,Type,Ct,[NewC|Acc],Extacc,Ext);
- ext ->
- check_each_component(S,Type,Ct,Acc,[NewC|Extacc],Ext)
- end;
-check_each_component(S,Type,[_|Ct],Acc,Extacc,noext) -> % skip 'EXTENSIONMARK'
- check_each_component(S,Type,Ct,Acc,Extacc,ext);
-check_each_component(_S,_,[_C|_Ct],_,_,ext) -> % skip '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,_,[],Acc,_,noext) ->
- lists:reverse(Acc).
-
-check_each_alternative(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_alternative(S=#state{abscomppath=Path,recordtopname=TopName},Type,[C|Ct],
- Acc,Extacc,Ext) when record(C,'ComponentType') ->
- #'ComponentType'{name=Cname,typespec=Ts,prop=_Prop} = C,
- NewAbsCPath =
- case Ts#type.def of
- #'Externaltypereference'{} -> [];
- _ -> [Cname|Path]
- end,
- NewState =
- S#state{abscomppath=NewAbsCPath,recordtopname=[Cname|TopName]},
- CheckedTs = check_type(NewState,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_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) ->
- 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) ->
-% {Cs1,Cs2} =
- Cs =
- case CompList of
- {Components,EComponents} when list(Components) ->
-% {Components,Components};
- Components ++ EComponents;
- CompList when list(CompList) ->
-% {CompList,CompList}
- CompList
- end,
-% case any_simple_table(S,Cs1,[]) of
-
- %% get_simple_table_if_used/2 should find out whether there are any
- %% component relation constraints in the entire tree of Cs1 that
- %% relates to this level. It returns information about the simple
- %% table constraint necessary for the the call to
- %% 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
- [] -> {false,CompList};
- STList ->
-% componentrelation_leadingattr(S,Cs1,Cs2,STList,[],[])
- componentrelation_leadingattr(S,Cs,Cs,STList,[],[])
- end.
-
-%% 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
-%% field in the SEQUENCE/SET record. The "leading attribute"
-%% information is used to generate the lookup in the object set
-%% table. The other information gathered in the #type.tablecinf field
-%% 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) ->
- {false,lists:reverse(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) ->
- {LAAcc,NewC} =
- case catch componentrelation1(S,C#'ComponentType'.typespec,
- [C#'ComponentType'.name]) of
- {'EXIT',_} ->
- {[],C};
- {CRI=[{_A1,_B1,_C1,_D1}|_Rest],NewTSpec} ->
- %% {ObjectSet,AtPath,ClassDef,Path}
- %% _A1 is a reference to the object set of the
- %% component relation constraint.
- %% _B1 is the path of names in the at-list of the
- %% component relation constraint.
- %% _C1 is the class definition of the
- %% ObjectClassFieldType.
- %% _D1 is the path of components that was traversed to
- %% find this constraint.
- case leading_attr_index(S,CompList,CRI,
- lists:reverse(S#state.abscomppath),[]) of
- [] ->
- {[],C};
- [{ObjSet,Attr,N,ClassDef,_Path,ValueIndex}|_NewRest] ->
- OS = object_set_mod_name(S,ObjSet),
- UniqueFieldName =
- case (catch get_unique_fieldname(#classdef{typespec=ClassDef})) of
- {error,'__undefined_'} ->
- no_unique;
- {asn1,Msg,_} ->
- error({type,Msg,S});
- Other -> Other
- end,
-% UsedFieldName = get_used_fieldname(S,Attr,STList),
- %% Res should be done differently: even though
- %% a unique field name exists it is not
- %% certain that the ObjectClassFieldType of
- %% the simple table constraint picks that
- %% class field.
- Res = #simpletableattributes{objectsetname=OS,
-%% c_name=asn1ct_gen:un_hyphen_var(Attr),
- c_name=Attr,
- c_index=N,
- usedclassfield=UniqueFieldName,
- uniqueclassfield=UniqueFieldName,
- valueindex=ValueIndex},
- {[Res],C#'ComponentType'{typespec=NewTSpec}}
- end;
- _ ->
- %% no constraint was found
- {[],C}
- end,
- componentrelation_leadingattr(S,Cs,CompList,STList,LAAcc++Acc,
- [NewC|CompAcc]).
-
-object_set_mod_name(_S,ObjSet) when atom(ObjSet) ->
- ObjSet;
-object_set_mod_name(#state{mname=M},
- #'Externaltypereference'{module=M,type=T}) ->
- T;
-object_set_mod_name(S,#'Externaltypereference'{module=M,type=T}) ->
- case lists:member(M,S#state.inputmodules) of
- true ->
- T;
- false ->
- {M,T}
- end.
-
-%% get_used_fieldname gets the used field of the class referenced by
-%% the ObjectClassFieldType construct in the simple table constraint
-%% corresponding to the component relation constraint that depends on
-%% it.
-% get_used_fieldname(_S,CName,[{[CName|_Rest],_,ClFieldName}|_RestSimpleT]) ->
-% ClFieldName;
-% get_used_fieldname(S,CName,[_SimpleTC|Rest]) ->
-% get_used_fieldname(S,CName,Rest);
-% get_used_fieldname(S,_,[]) ->
-% error({type,"Error in Simple table constraint",S}).
-
-%% any_simple_table/3 checks if any of the components on this level is
-%% constrained by a simple table constraint. It returns a list of
-%% tuples with three elements. It is a name path to the place in the
-%% type structure where the constraint is, and the name of the object
-%% set and the referenced field in the class.
-% any_simple_table(S = #state{mname=M,abscomppath=Path},
-% [#'ComponentType'{name=Name,typespec=Type}|Cs],Acc) ->
-% Constraint = Type#type.constraint,
-% case lists:keysearch(simpletable,1,Constraint) of
-% {value,{_,#type{def=Ref}}} ->
-% %% This ObjectClassFieldType, which has a simple table
-% %% constraint, must pick a fixed type value, mustn't it ?
-% {ClassDef,[{_,ClassFieldName}]} = Type#type.def,
-% ST =
-% case Ref of
-% #'Externaltypereference'{module=M,type=ObjSetName} ->
-% {[Name|Path],ObjSetName,ClassFieldName};
-% _ ->
-% {[Name|Path],Ref,ClassFieldName}
-% end,
-% any_simple_table(S,Cs,[ST|Acc]);
-% false ->
-% any_simple_table(S,Cs,Acc)
-% end;
-% any_simple_table(_,[],Acc) ->
-% lists:reverse(Acc);
-% any_simple_table(S,[_|Cs],Acc) ->
-% any_simple_table(S,Cs,Acc).
-
-%% get_simple_table_if_used/2 searches the structure of Cs for any
-%% component relation constraints due to the present level of the
-%% structure. If there are any, the necessary information for code
-%% 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,[],[]),
- get_simple_table_info(S,Cs,remove_doubles(RefedSimpleTable)).
-
-remove_doubles(L) ->
- remove_doubles(L,[]).
-remove_doubles([H|T],Acc) ->
- NewT = remove_doubles1(H,T),
- remove_doubles(NewT,[H|Acc]);
-remove_doubles([],Acc) ->
- Acc.
-
-remove_doubles1(El,L) ->
- case lists:delete(El,L) of
- L -> L;
- NewL -> remove_doubles1(El,NewL)
- end.
-
-%% get_simple_table_info searches the commponents Cs by the path from
-%% an at-list (third argument), and follows into a component of it if
-%% necessary, to get information needed for code generating.
-%%
-%% Returns a list of tuples with three elements. It holds a list of
-%% atoms that is the path, the name of the field of the class that are
-%% referred to in the ObjectClassFieldType, and the name of the unique
-%% field of the class of the ObjectClassFieldType.
-%%
-% %% The level information outermost/innermost must be kept. There are
-% %% at least two possibilities to cover here for an outermost case: 1)
-% %% Both the simple table and the component relation have a common path
-% %% at least one step below the outermost level, i.e. the leading
-% %% information shall be on a sub level. 2) They don't have any common
-% %% path.
-get_simple_table_info(S,Cs,[AtList|Rest]) ->
-%% [get_simple_table_info1(S,Cs,AtList,S#state.abscomppath)|get_simple_table_info(S,Cs,Rest)];
- [get_simple_table_info1(S,Cs,AtList,[])|get_simple_table_info(S,Cs,Rest)];
-get_simple_table_info(_,_,[]) ->
- [].
-get_simple_table_info1(S,Cs,[Cname|Cnames],Path) when list(Cs) ->
- case lists:keysearch(Cname,#'ComponentType'.name,Cs) of
- {value,C} ->
- get_simple_table_info1(S,C,Cnames,[Cname|Path]);
- _ ->
- error({type,"Missing expected simple table constraint",S})
- end;
-get_simple_table_info1(S,#'ComponentType'{typespec=TS},[],Path) ->
- %% In this component there must be a simple table constraint
- %% o.w. the asn1 code is wrong.
- #type{def=OCFT,constraint=Cnstr} = TS,
- case Cnstr of
- [{simpletable,_OSRef}]�->
- #'ObjectClassFieldType'{classname=ClRef,
- class=ObjectClass,
- fieldname=FieldName} = OCFT,
-% #'ObjectClassFieldType'{ObjectClass,FieldType} = ObjectClassFieldType,
- ObjectClassFieldName =
- case FieldName of
- {LastFieldName,[]} -> LastFieldName;
- {_FirstFieldName,FieldNames} ->
- lists:last(FieldNames)
- end,
- %%ObjectClassFieldName is the last element in the dotted
- %%list of the ObjectClassFieldType. The last element may
- %%be of another class, that is referenced from the class
- %%of the ObjectClassFieldType
- ClassDef =
- case ObjectClass of
- [] ->
- {_,CDef}=get_referenced_type(S,ClRef),
- CDef;
- _ -> #classdef{typespec=ObjectClass}
- end,
- UniqueName =
- case (catch get_unique_fieldname(ClassDef)) of
- {error,'__undefined_'} -> no_unique;
- {asn1,Msg,_} ->
- error({type,Msg,S});
- Other -> Other
- end,
- {lists:reverse(Path),ObjectClassFieldName,UniqueName};
- _ ->
- error({type,{asn1,"missing expected simple table constraint",
- Cnstr},S})
- end;
-get_simple_table_info1(S,#'ComponentType'{typespec=TS},Cnames,Path) ->
- Components = get_atlist_components(TS#type.def),
- get_simple_table_info1(S,Components,Cnames,Path).
-
-%% any_component_relation searches for all component relation
-%% constraints that refers to the actual level and returns a list of
-%% the "name path" in the at-list to the component relation constraint
-%% that must refer to a simple table constraint. The list is empty if
-%% no component relation constraints were found.
-%%
-%% NamePath has the names of all components that are followed from the
-%% 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,
- CRelPath =
- case Type#type.constraint of
- [{componentrelation,_,AtNotation}] ->
- %% Found component relation constraint, now check
- %% whether this constraint is relevant for the level
- %% where the search started
- AtNot = extract_at_notation(AtNotation),
- %% evaluate_atpath returns the relative path to the
- %% simple table constraint from where the component
- %% relation is found.
- evaluate_atpath(S#state.abscomppath,NamePath,CNames,AtNot);
- _ ->
- []
- end,
- InnerAcc =
- 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,
- %% here we are interested in components of an
- %% SEQUENCE/SET OF as well as SEQUENCE, SET and CHOICE
- any_component_relation(S,InnerCs,CNames,[CName|NamePath],[]);
- _ ->
- []
- end,
- any_component_relation(S,Cs,CNames,NamePath,InnerAcc++CRelPath++Acc);
-any_component_relation(_,[],_,_,Acc) ->
- Acc.
-
-%% evaluate_atpath/4 finds out whether the at notation refers to the
-%% search level. The list of referenced names in the AtNot list shall
-%% begin with a name that exists on the level it refers to. If the
-%% found AtPath is refering to the same sub-branch as the simple table
-%% has, then there shall not be any leading attribute info on this
-%% level.
-evaluate_atpath(_,[],Cnames,{innermost,AtPath=[Ref|_Refs]}) ->
- %% any innermost constraint found deeper in the structure is
- %% ignored.
- case lists:member(Ref,Cnames) of
- true -> [AtPath];
- false -> []
- end;
-%% In this case must check that the AtPath doesn't step any step of
-%% the NamePath, in that case the constraint will be handled in an
-%% inner level.
-evaluate_atpath(TopPath,NamePath,Cnames,{outermost,AtPath=[_Ref|_Refs]}) ->
- AtPathBelowTop =
- case TopPath of
- [] -> AtPath;
- _ ->
- case lists:prefix(TopPath,AtPath) of
- true ->
- lists:subtract(AtPath,TopPath);
- _ -> []
- end
- end,
- case {NamePath,AtPathBelowTop} of
- {[H|_T1],[H|_T2]} -> []; % this must be handled in lower level
- {_,[]} -> [];% this must be handled in an above level
- {_,[H|_T]} ->
- case lists:member(H,Cnames) of
- true -> [AtPathBelowTop];
- _ -> error({type,{asn1,"failed to analyze at-path",AtPath}})
- end
- end;
-evaluate_atpath(_,_,_,_) ->
- [].
-
-%% Type may be any of SEQUENCE, SET, CHOICE, SEQUENCE OF, SET OF but
-%% only the three first have valid components.
-get_atlist_components(Def) ->
- get_components(atlist,Def).
-
-get_components(Def) ->
- get_components(any,Def).
-
-get_components(_,#'SEQUENCE'{components=Cs}) ->
- Cs;
-get_components(_,#'SET'{components=Cs}) ->
- Cs;
-get_components(_,{'CHOICE',Cs}) ->
- Cs;
-get_components(any,{'SEQUENCE OF',#type{def=Def}}) ->
- get_components(any,Def);
-get_components(any,{'SET OF',#type{def=Def}}) ->
- get_components(any,Def);
-get_components(_,_) ->
- [].
-
-
-extract_at_notation([{Level,[#'Externalvaluereference'{value=Name}|Rest]}]) ->
- {Level,[Name|extract_at_notation1(Rest)]};
-extract_at_notation(At) ->
- exit({error,{asn1,{at_notation,At}}}).
-extract_at_notation1([#'Externalvaluereference'{value=Name}|Rest]) ->
- [Name|extract_at_notation1(Rest)];
-extract_at_notation1([]) ->
- [].
-
-%% componentrelation1/1 identifies all componentrelation constraints
-%% that exist in C or in the substructure of C. Info about the found
-%% constraints are returned in a list. It is ObjectSet, the reference
-%% to the object set, AttrPath, the name atoms extracted from the
-%% at-list in the component relation constraint, ClassDef, the
-%% objectclass record of the class of the ObjectClassFieldType, Path,
-%% that is the component name "path" from the searched level to this
-%% constraint.
-%%
-%% The function is called with one component of the type in turn and
-%% with the component name in Path at the first call. When called from
-%% within, the name of the inner component is added to Path.
-componentrelation1(S,C = #type{def=Def,constraint=Constraint,tablecinf=TCI},
- Path) ->
- Ret =
- case Constraint of
- [{componentrelation,{_,_,ObjectSet},AtList}|_Rest] ->
- [{_,AL=[#'Externalvaluereference'{}|_R1]}|_R2] = AtList,
- %% Note: if Path is longer than one,i.e. it is within
- %% an inner type of the actual level, then the only
- %% relevant at-list is of "outermost" type.
-%% #'ObjectClassFieldType'{class=ClassDef} = Def,
- ClassDef = get_ObjectClassFieldType_classdef(S,Def),
- AtPath =
- lists:map(fun(#'Externalvaluereference'{value=V})->V end,
- AL),
- {[{ObjectSet,AtPath,ClassDef,Path}],Def};
- _Other ->
- %% check the inner type of component
- innertype_comprel(S,Def,Path)
- end,
- case Ret of
- nofunobj ->
- nofunobj; %% ignored by caller
- {CRelI=[{ObjSet,_,_,_}],NewDef} -> %%
- TCItmp = lists:subtract(TCI,[{objfun,ObjSet}]),
- {CRelI,C#type{tablecinf=[{objfun,ObjSet}|TCItmp],def=NewDef}};
- {CompRelInf,NewDef} -> %% more than one tuple in CompRelInf
- TCItmp = lists:subtract(TCI,[{objfun,anyset}]),
- {CompRelInf,C#type{tablecinf=[{objfun,anyset}|TCItmp],def=NewDef}}
- end.
-
-innertype_comprel(S,{'SEQUENCE OF',Type},Path) ->
- case innertype_comprel1(S,Type,Path) of
- nofunobj ->
- nofunobj;
- {CompRelInf,NewType} ->
- {CompRelInf,{'SEQUENCE OF',NewType}}
- end;
-innertype_comprel(S,{'SET OF',Type},Path) ->
- case innertype_comprel1(S,Type,Path) of
- nofunobj ->
- nofunobj;
- {CompRelInf,NewType} ->
- {CompRelInf,{'SET OF',NewType}}
- end;
-innertype_comprel(S,{'CHOICE',CTypeList},Path) ->
- case componentlist_comprel(S,CTypeList,[],Path,[]) of
- nofunobj ->
- nofunobj;
- {CompRelInf,NewCs} ->
- {CompRelInf,{'CHOICE',NewCs}}
- end;
-innertype_comprel(S,Seq = #'SEQUENCE'{components=Cs},Path) ->
- case componentlist_comprel(S,Cs,[],Path,[]) of
- nofunobj ->
- nofunobj;
- {CompRelInf,NewCs} ->
- {CompRelInf,Seq#'SEQUENCE'{components=NewCs}}
- end;
-innertype_comprel(S,Set = #'SET'{components=Cs},Path) ->
- case componentlist_comprel(S,Cs,[],Path,[]) of
- nofunobj ->
- nofunobj;
- {CompRelInf,NewCs} ->
- {CompRelInf,Set#'SET'{components=NewCs}}
- end;
-innertype_comprel(_,_,_) ->
- nofunobj.
-
-componentlist_comprel(S,[C = #'ComponentType'{name=Name,typespec=Type}|Cs],
- Acc,Path,NewCL) ->
- case catch componentrelation1(S,Type,Path++[Name]) of
- {'EXIT',_} ->
- componentlist_comprel(S,Cs,Acc,Path,[C|NewCL]);
- nofunobj ->
- componentlist_comprel(S,Cs,Acc,Path,[C|NewCL]);
- {CRelInf,NewType} ->
- componentlist_comprel(S,Cs,CRelInf++Acc,Path,
- [C#'ComponentType'{typespec=NewType}|NewCL])
- end;
-componentlist_comprel(_,[],Acc,_,NewCL) ->
- case Acc of
- [] ->
- nofunobj;
- _ ->
- {Acc,lists:reverse(NewCL)}
- end.
-
-innertype_comprel1(S,T = #type{def=Def,constraint=Cons,tablecinf=TCI},Path) ->
- Ret =
- case Cons of
- [{componentrelation,{_,_,ObjectSet},AtList}|_Rest] ->
- %% This AtList must have an "outermost" at sign to be
- %% relevent here.
- [{_,AL=[#'Externalvaluereference'{value=_Attr}|_R1]}|_R2]
- = AtList,
-%% #'ObjectClassFieldType'{class=ClassDef} = Def,
- ClassDef = get_ObjectClassFieldType_classdef(S,Def),
- AtPath =
- lists:map(fun(#'Externalvaluereference'{value=V})->V end,
- AL),
- [{ObjectSet,AtPath,ClassDef,Path}];
- _ ->
- innertype_comprel(S,Def,Path)
- end,
- case Ret of
- nofunobj -> nofunobj;
- L = [{ObjSet,_,_,_}] ->
- TCItmp = lists:subtract(TCI,[{objfun,ObjSet}]),
- {L,T#type{tablecinf=[{objfun,ObjSet}|TCItmp]}};
- {CRelInf,NewDef} ->
- TCItmp = lists:subtract(TCI,[{objfun,anyset}]),
- {CRelInf,T#type{def=NewDef,tablecinf=[{objfun,anyset}|TCItmp]}}
- end.
-
-
-%% leading_attr_index counts the index and picks the name of the
-%% component that is at the actual level in the at-list of the
-%% component relation constraint (AttrP). AbsP is the path of
-%% component names from the top type level to the actual level. AttrP
-%% is a list with the atoms from the at-list.
-leading_attr_index(S,Cs,[H={_,AttrP,_,_}|T],AbsP,Acc) ->
- AttrInfo =
- case lists:prefix(AbsP,AttrP) of
- %% why this ?? It is necessary when in same situation as
- %% TConstrChoice, there is an inner structure with an
- %% outermost at-list and the "leading attribute" code gen
- %% may be at a level some steps below the outermost level.
- true ->
- RelativAttrP = lists:subtract(AttrP,AbsP),
- %% The header is used to calculate the index of the
- %% component and to give the fun, received from the
- %% object set look up, an unique name. The tail is
- %% used to match the proper value input to the fun.
- {hd(RelativAttrP),tl(RelativAttrP)};
- false ->
- {hd(AttrP),tl(AttrP)}
- end,
- case leading_attr_index1(S,Cs,H,AttrInfo,1) of
- 0 ->
- leading_attr_index(S,Cs,T,AbsP,Acc);
- Res ->
- leading_attr_index(S,Cs,T,AbsP,[Res|Acc])
- end;
-leading_attr_index(_,_Cs,[],_,Acc) ->
- lists:reverse(Acc).
-
-leading_attr_index1(_,[],_,_,_) ->
- 0;
-leading_attr_index1(S,[C|Cs],Arg={ObjectSet,_,CDef,P},
- AttrInfo={Attr,SubAttr},N) ->
- case C#'ComponentType'.name of
- Attr ->
- ValueMatch = value_match(S,C,Attr,SubAttr),
- {ObjectSet,Attr,N,CDef,P,ValueMatch};
- _ ->
- leading_attr_index1(S,Cs,Arg,AttrInfo,N+1)
- end.
-
-%% value_math gathers information for a proper value match in the
-%% generated encode function. For a SEQUENCE or a SET the index of the
-%% component is counted. For a CHOICE the index is 2.
-value_match(S,C,Name,SubAttr) ->
- value_match(S,C,Name,SubAttr,[]). % C has name Name
-value_match(_S,#'ComponentType'{},_Name,[],Acc) ->
- Acc;% do not reverse, indexes in reverse order
-value_match(S,#'ComponentType'{typespec=Type},Name,[At|Ats],Acc) ->
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- Components =
- case get_atlist_components(Type#type.def) of
- [] -> error({type,{asn1,"element in at list must be a "
- "SEQUENCE, SET or CHOICE.",Name},S});
- Comps -> Comps
- end,
- {Index,ValueIndex} = component_value_index(S,InnerType,At,Components),
- value_match(S,lists:nth(Index,Components),At,Ats,[ValueIndex|Acc]).
-
-component_value_index(S,'CHOICE',At,Components) ->
- {component_index(S,At,Components),2};
-component_value_index(S,_,At,Components) ->
- %% SEQUENCE or SET
- Index = component_index(S,At,Components),
- {Index,{Index+1,At}}.
-
-component_index(S,Name,Components) ->
- component_index1(S,Name,Components,1).
-component_index1(_S,Name,[#'ComponentType'{name=Name}|_Cs],N) ->
- N;
-component_index1(S,Name,[_C|Cs],N) ->
- component_index1(S,Name,Cs,N+1);
-component_index1(S,Name,[],_) ->
- error({type,{asn1,"component of at-list was not"
- " found in substructure",Name},S}).
-
-get_unique_fieldname(ClassDef) ->
-%% {_,Fields,_} = ClassDef#classdef.typespec,
- Fields = (ClassDef#classdef.typespec)#objectclass.fields,
- get_unique_fieldname(Fields,[]).
-
-get_unique_fieldname([],[]) ->
- throw({error,'__undefined_'});
-get_unique_fieldname([],[Name]) ->
- Name;
-get_unique_fieldname([],Acc) ->
- throw({asn1,'only one UNIQUE field is allowed in CLASS',Acc});
-get_unique_fieldname([{fixedtypevaluefield,Name,_,'UNIQUE',_}|Rest],Acc) ->
- get_unique_fieldname(Rest,[Name|Acc]);
-get_unique_fieldname([_H|T],Acc) ->
- get_unique_fieldname(T,Acc).
-
-get_tableconstraint_info(S,Type,{CheckedTs,EComps}) ->
- {get_tableconstraint_info(S,Type,CheckedTs,[]),
- get_tableconstraint_info(S,Type,EComps,[])};
-get_tableconstraint_info(S,Type,CheckedTs) ->
- 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,
- AccComp =
- case CheckedTs#type.def of
- %% ObjectClassFieldType
- OCFT=#'ObjectClassFieldType'{class=#objectclass{},
- type=_AType} ->
-% AType = get_ObjectClassFieldType(S,Fields,FieldRef),
-% RefedFieldName =
-% get_referencedclassfield(CheckedTs#type.def),%is probably obsolete
- NewOCFT =
- OCFT#'ObjectClassFieldType'{class=[]},
- C#'ComponentType'{typespec=
- CheckedTs#type{
-% def=AType,
- def=NewOCFT
- }};
-% constraint=[{tableconstraint_info,
-% FieldRef}]}};
- {'SEQUENCE OF',SOType} when record(SOType,type),
- (element(1,SOType#type.def)=='CHOICE') ->
- CTypeList = element(2,SOType#type.def),
- NewInnerCList =
- get_tableconstraint_info(S,Type,CTypeList,[]),
- C#'ComponentType'{typespec=
- CheckedTs#type{
- def={'SEQUENCE OF',
- SOType#type{def={'CHOICE',
- NewInnerCList}}}}};
- {'SET OF',SOType} when record(SOType,type),
- (element(1,SOType#type.def)=='CHOICE') ->
- CTypeList = element(2,SOType#type.def),
- NewInnerCList =
- get_tableconstraint_info(S,Type,CTypeList,[]),
- C#'ComponentType'{typespec=
- CheckedTs#type{
- def={'SET OF',
- SOType#type{def={'CHOICE',
- NewInnerCList}}}}};
- _ ->
- C
- end,
- get_tableconstraint_info(S,Type,Cs,[AccComp|Acc]).
-
-get_referenced_fieldname([{_,FirstFieldname}]) ->
- {FirstFieldname,[]};
-get_referenced_fieldname([{_,FirstFieldname}|Rest]) ->
- {FirstFieldname,lists:map(fun(X)->element(2,X) end,Rest)};
-get_referenced_fieldname(Def) ->
- {no_type,Def}.
-
-%% get_ObjectClassFieldType extracts the type from the chain of
-%% objects that leads to a final type.
-get_ObjectClassFieldType(S,ERef,PrimFieldNameList) when
- record(ERef,'Externaltypereference') ->
- {_,Type} = get_referenced_type(S,ERef),
- ClassSpec = check_class(S,Type),
- Fields = ClassSpec#objectclass.fields,
- get_ObjectClassFieldType(S,Fields,PrimFieldNameList);
-get_ObjectClassFieldType(S,Fields,L=[_PrimFieldName1|_Rest]) ->
- check_PrimitiveFieldNames(S,Fields,L),
- get_OCFType(S,Fields,L).
-
-check_PrimitiveFieldNames(_S,_Fields,_) ->
- ok.
-
-%% get_ObjectClassFieldType_classdef gets the def of the class of the
-%% ObjectClassFieldType, i.e. the objectclass record. If the type has
-%% been checked (it may be a field type of an internal SEQUENCE) the
-%% class field = [], then the classdef has to be fetched by help of
-%% the class reference in the classname field.
-get_ObjectClassFieldType_classdef(S,#'ObjectClassFieldType'{classname=Name,
- class=[]}) ->
- {_,#classdef{typespec=TS}} = get_referenced_type(S,Name),
- TS;
-get_ObjectClassFieldType_classdef(_,#'ObjectClassFieldType'{class=Cl}) ->
- Cl.
-
-get_OCFType(S,Fields,[{_FieldType,PrimFieldName}|Rest]) ->
- case lists:keysearch(PrimFieldName,2,Fields) of
- {value,{fixedtypevaluefield,_,Type,_Unique,_OptSpec}} ->
- {fixedtypevaluefield,PrimFieldName,Type};
- {value,{objectfield,_,Type,_Unique,_OptSpec}} ->
- {_,ClassDef} = get_referenced_type(S,Type#type.def),
- CheckedCDef = check_class(S#state{type=ClassDef,
- tname=ClassDef#classdef.name},
- ClassDef#classdef.typespec),
- get_OCFType(S,CheckedCDef#objectclass.fields,Rest);
- {value,{objectsetfield,_,Type,_OptSpec}} ->
- {_,ClassDef} = get_referenced_type(S,Type#type.def),
- CheckedCDef = check_class(S#state{type=ClassDef,
- tname=ClassDef#classdef.name},
- ClassDef#classdef.typespec),
- get_OCFType(S,CheckedCDef#objectclass.fields,Rest);
-
- {value,Other} ->
- {element(1,Other),PrimFieldName};
- _ ->
- error({type,"undefined FieldName in ObjectClassFieldType",S})
- end.
-
-get_taglist(#state{erule=per},_) ->
- [];
-get_taglist(#state{erule=per_bin},_) ->
- [];
-get_taglist(S,Ext) when record(Ext,'Externaltypereference') ->
- {_,T} = get_referenced_type(S,Ext),
- get_taglist(S,T#typedef.typespec);
-get_taglist(S,Tref) when record(Tref,typereference) ->
- {_,T} = get_referenced_type(S,Tref),
- get_taglist(S,T#typedef.typespec);
-get_taglist(S,Type) when record(Type,type) ->
- case Type#type.tag of
- [] ->
- get_taglist(S,Type#type.def);
- [Tag|_] ->
-% case lists:member(S#state.erule,[ber,ber_bin]) of
-% true ->
-% lists:map(fun(Tx) -> asn1ct_gen:def_to_tag(Tx) end,Type#type.tag);
-% _ ->
- [asn1ct_gen:def_to_tag(Tag)]
-% end
- end;
-get_taglist(S,{'CHOICE',{Rc,Ec}}) ->
- get_taglist(S,{'CHOICE',Rc ++ Ec});
-get_taglist(S,{'CHOICE',Components}) ->
- get_taglist1(S,Components);
-%% ObjectClassFieldType OTP-4390
-get_taglist(_S,#'ObjectClassFieldType'{type={typefield,_}}) ->
- [];
-get_taglist(S,#'ObjectClassFieldType'{type={fixedtypevaluefield,_,Type}}) ->
- get_taglist(S,Type);
-get_taglist(S,{ERef=#'Externaltypereference'{},FieldNameList})
- when list(FieldNameList) ->
- case get_ObjectClassFieldType(S,ERef,FieldNameList) of
- Type when record(Type,type) ->
- get_taglist(S,Type);
- {fixedtypevaluefield,_,Type} -> get_taglist(S,Type);
- {TypeFieldName,_} when atom(TypeFieldName) -> []%should check if allowed
- end;
-get_taglist(S,{ObjCl,FieldNameList}) when record(ObjCl,objectclass),
- list(FieldNameList) ->
- case get_ObjectClassFieldType(S,ObjCl#objectclass.fields,FieldNameList) of
- Type when record(Type,type) ->
- get_taglist(S,Type);
- {fixedtypevaluefield,_,Type} -> get_taglist(S,Type);
- {TypeFieldName,_} when atom(TypeFieldName) -> []%should check if allowed
- end;
-get_taglist(S,Def) ->
- case lists:member(S#state.erule,[ber_bin_v2]) of
- false ->
- case Def of
- 'ASN1_OPEN_TYPE' -> % open_type has no UNIVERSAL tag as such
- [];
- _ ->
- [asn1ct_gen:def_to_tag(Def)]
- end;
- _ ->
- []
- end.
-
-get_taglist1(S,[#'ComponentType'{name=_Cname,tags=TagL}|Rest]) when list(TagL) ->
- %% tag_list has been here , just return TagL and continue with next alternative
- TagL ++ get_taglist1(S,Rest);
-get_taglist1(S,[#'ComponentType'{typespec=Ts,tags=undefined}|Rest]) ->
- get_taglist(S,Ts) ++ get_taglist1(S,Rest);
-get_taglist1(S,[_H|Rest]) -> % skip EXTENSIONMARK
- get_taglist1(S,Rest);
-get_taglist1(_S,[]) ->
- [].
-
-dbget_ex(_S,Module,Key) ->
- case asn1_db:dbget(Module,Key) of
- undefined ->
-
- throw({error,{asn1,{undefined,{Module,Key}}}}); % this is catched on toplevel type or value
- T -> T
- end.
-
-merge_tags(T1, T2) when list(T2) ->
- merge_tags2(T1 ++ T2, []);
-merge_tags(T1, T2) ->
- merge_tags2(T1 ++ [T2], []).
-
-merge_tags2([T1= #tag{type='IMPLICIT'}, T2 |Rest], Acc) ->
- merge_tags2([T1#tag{type=T2#tag.type, form=T2#tag.form}|Rest],Acc);
-merge_tags2([T1= #tag{type={default,'IMPLICIT'}}, T2 |Rest], Acc) ->
- merge_tags2([T1#tag{type=T2#tag.type, form=T2#tag.form}|Rest],Acc);
-merge_tags2([H|T],Acc) ->
- merge_tags2(T, [H|Acc]);
-merge_tags2([], Acc) ->
- lists:reverse(Acc).
-
-merge_constraints(C1, []) ->
- C1;
-merge_constraints([], C2) ->
- C2;
-merge_constraints(C1, C2) ->
- {SList,VList,PAList,Rest} = splitlist(C1++C2,[],[],[],[]),
- SizeC = merge_constraints(SList),
- ValueC = merge_constraints(VList),
- PermAlphaC = merge_constraints(PAList),
- case Rest of
- [] ->
- SizeC ++ ValueC ++ PermAlphaC;
- _ ->
- throw({error,{asn1,{not_implemented,{merge_constraints,Rest}}}})
- end.
-
-merge_constraints([]) -> [];
-merge_constraints([C1 = {_,{Low1,High1}},{_,{Low2,High2}}|Rest]) when Low1 >= Low2,
- High1 =< High2 ->
- merge_constraints([C1|Rest]);
-merge_constraints([C1={'PermittedAlphabet',_},C2|Rest]) ->
- [C1|merge_constraints([C2|Rest])];
-merge_constraints([C1 = {_,{_Low1,_High1}},C2 = {_,{_Low2,_High2}}|_Rest]) ->
- throw({error,asn1,{conflicting_constraints,{C1,C2}}});
-merge_constraints([C]) ->
- [C].
-
-splitlist([C={'SizeConstraint',_}|Rest],Sacc,Vacc,PAacc,Restacc) ->
- splitlist(Rest,[C|Sacc],Vacc,PAacc,Restacc);
-splitlist([C={'ValueRange',_}|Rest],Sacc,Vacc,PAacc,Restacc) ->
- splitlist(Rest,Sacc,[C|Vacc],PAacc,Restacc);
-splitlist([C={'PermittedAlphabet',_}|Rest],Sacc,Vacc,PAacc,Restacc) ->
- splitlist(Rest,Sacc,Vacc,[C|PAacc],Restacc);
-splitlist([C|Rest],Sacc,Vacc,PAacc,Restacc) ->
- splitlist(Rest,Sacc,Vacc,PAacc,[C|Restacc]);
-splitlist([],Sacc,Vacc,PAacc,Restacc) ->
- {lists:reverse(Sacc),
- lists:reverse(Vacc),
- lists:reverse(PAacc),
- lists:reverse(Restacc)}.
-
-
-
-storeindb(M) when record(M,module) ->
- TVlist = M#module.typeorval,
- NewM = M#module{typeorval=findtypes_and_values(TVlist)},
- asn1_db:dbnew(NewM#module.name),
- asn1_db:dbput(NewM#module.name,'MODULE', NewM),
- Res = storeindb(NewM#module.name,TVlist,[]),
- include_default_class(NewM#module.name),
- include_default_type(NewM#module.name),
- Res.
-
-storeindb(Module,[H|T],ErrAcc) when record(H,typedef) ->
- storeindb(Module,H#typedef.name,H,T,ErrAcc);
-storeindb(Module,[H|T],ErrAcc) when record(H,valuedef) ->
- storeindb(Module,H#valuedef.name,H,T,ErrAcc);
-storeindb(Module,[H|T],ErrAcc) when record(H,ptypedef) ->
- storeindb(Module,H#ptypedef.name,H,T,ErrAcc);
-storeindb(Module,[H|T],ErrAcc) when record(H,classdef) ->
- storeindb(Module,H#classdef.name,H,T,ErrAcc);
-storeindb(Module,[H|T],ErrAcc) when record(H,pvaluesetdef) ->
- storeindb(Module,H#pvaluesetdef.name,H,T,ErrAcc);
-storeindb(Module,[H|T],ErrAcc) when record(H,pobjectdef) ->
- storeindb(Module,H#pobjectdef.name,H,T,ErrAcc);
-storeindb(Module,[H|T],ErrAcc) when record(H,pvaluedef) ->
- storeindb(Module,H#pvaluedef.name,H,T,ErrAcc);
-storeindb(_,[],[]) -> ok;
-storeindb(_,[],ErrAcc) ->
- {error,ErrAcc}.
-
-storeindb(Module,Name,H,T,ErrAcc) ->
- case asn1_db:dbget(Module,Name) of
- undefined ->
- asn1_db:dbput(Module,Name,H),
- storeindb(Module,T,ErrAcc);
- _ ->
- case H of
- _Type when record(H,typedef) ->
- error({type,"already defined",
- #state{mname=Module,type=H,tname=Name}});
- _Type when record(H,valuedef) ->
- error({value,"already defined",
- #state{mname=Module,value=H,vname=Name}});
- _Type when record(H,ptypedef) ->
- error({ptype,"already defined",
- #state{mname=Module,type=H,tname=Name}});
- _Type when record(H,pobjectdef) ->
- error({ptype,"already defined",
- #state{mname=Module,type=H,tname=Name}});
- _Type when record(H,pvaluesetdef) ->
- error({ptype,"already defined",
- #state{mname=Module,type=H,tname=Name}});
- _Type when record(H,pvaluedef) ->
- error({ptype,"already defined",
- #state{mname=Module,type=H,tname=Name}});
- _Type when record(H,classdef) ->
- error({class,"already defined",
- #state{mname=Module,value=H,vname=Name}})
- end,
- storeindb(Module,T,[H|ErrAcc])
- end.
-
-findtypes_and_values(TVList) ->
- findtypes_and_values(TVList,[],[],[],[],[],[]).%% Types,Values,
-%% Parameterizedtypes,Classes,Objects and ObjectSets
-
-findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
- when record(H,typedef),record(H#typedef.typespec,'Object') ->
- findtypes_and_values(T,Tacc,Vacc,Pacc,Cacc,[H#typedef.name|Oacc],OSacc);
-findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
- when record(H,typedef),record(H#typedef.typespec,'ObjectSet') ->
- findtypes_and_values(T,Tacc,Vacc,Pacc,Cacc,Oacc,[H#typedef.name|OSacc]);
-findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
- when record(H,typedef) ->
- findtypes_and_values(T,[H#typedef.name|Tacc],Vacc,Pacc,Cacc,Oacc,OSacc);
-findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
- when record(H,valuedef) ->
- findtypes_and_values(T,Tacc,[H#valuedef.name|Vacc],Pacc,Cacc,Oacc,OSacc);
-findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
- when record(H,ptypedef) ->
- findtypes_and_values(T,Tacc,Vacc,[H#ptypedef.name|Pacc],Cacc,Oacc,OSacc);
-findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
- when record(H,classdef) ->
- findtypes_and_values(T,Tacc,Vacc,Pacc,[H#classdef.name|Cacc],Oacc,OSacc);
-findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
- when record(H,pvaluedef) ->
- findtypes_and_values(T,Tacc,[H#pvaluedef.name|Vacc],Pacc,Cacc,Oacc,OSacc);
-findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
- when record(H,pvaluesetdef) ->
- findtypes_and_values(T,Tacc,[H#pvaluesetdef.name|Vacc],Pacc,Cacc,Oacc,OSacc);
-findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
- when record(H,pobjectdef) ->
- findtypes_and_values(T,Tacc,Vacc,Pacc,Cacc,[H#pobjectdef.name|Oacc],OSacc);
-findtypes_and_values([H|T],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc)
- when record(H,pobjectsetdef) ->
- findtypes_and_values(T,Tacc,Vacc,Pacc,Cacc,Oacc,[H#pobjectsetdef.name|OSacc]);
-findtypes_and_values([],Tacc,Vacc,Pacc,Cacc,Oacc,OSacc) ->
- {lists:reverse(Tacc),lists:reverse(Vacc),lists:reverse(Pacc),
- lists:reverse(Cacc),lists:reverse(Oacc),lists:reverse(OSacc)}.
-
-
-
-error({export,Msg,#state{mname=Mname,type=Ref,tname=Typename}}) ->
- Pos = Ref#'Externaltypereference'.pos,
- io:format("asn1error:~p:~p:~p ~p~n",[Pos,Mname,Typename,Msg]),
- {error,{export,Pos,Mname,Typename,Msg}};
-error({type,Msg,#state{mname=Mname,type=Type,tname=Typename}})
- when record(Type,typedef) ->
- io:format("asn1error:~p:~p:~p ~p~n",
- [Type#typedef.pos,Mname,Typename,Msg]),
- {error,{type,Type#typedef.pos,Mname,Typename,Msg}};
-error({type,Msg,#state{mname=Mname,type=Type,tname=Typename}})
- when record(Type,ptypedef) ->
- io:format("asn1error:~p:~p:~p ~p~n",
- [Type#ptypedef.pos,Mname,Typename,Msg]),
- {error,{type,Type#ptypedef.pos,Mname,Typename,Msg}};
-error({type,Msg,#state{mname=Mname,value=Value,vname=Valuename}})
- when record(Value,valuedef) ->
- io:format("asn1error:~p:~p:~p ~p~n",[Value#valuedef.pos,Mname,Valuename,Msg]),
- {error,{type,Value#valuedef.pos,Mname,Valuename,Msg}};
-error({type,Msg,#state{mname=Mname,type=Type,tname=Typename}})
- when record(Type,pobjectdef) ->
- io:format("asn1error:~p:~p:~p ~p~n",
- [Type#pobjectdef.pos,Mname,Typename,Msg]),
- {error,{type,Type#pobjectdef.pos,Mname,Typename,Msg}};
-error({value,Msg,#state{mname=Mname,value=Value,vname=Valuename}}) ->
- io:format("asn1error:~p:~p:~p ~p~n",[Value#valuedef.pos,Mname,Valuename,Msg]),
- {error,{value,Value#valuedef.pos,Mname,Valuename,Msg}};
-error({Other,Msg,#state{mname=Mname,value=#valuedef{pos=Pos},vname=Valuename}}) ->
- io:format("asn1error:~p:~p:~p ~p~n",[Pos,Mname,Valuename,Msg]),
- {error,{Other,Pos,Mname,Valuename,Msg}};
-error({Other,Msg,#state{mname=Mname,type=#typedef{pos=Pos},tname=Typename}}) ->
- io:format("asn1error:~p:~p:~p ~p~n",[Pos,Mname,Typename,Msg]),
- {error,{Other,Pos,Mname,Typename,Msg}};
-error({Other,Msg,#state{mname=Mname,type=#classdef{pos=Pos},tname=Typename}}) ->
- io:format("asn1error:~p:~p:~p ~p~n",[Pos,Mname,Typename,Msg]),
- {error,{Other,Pos,Mname,Typename,Msg}}.
-
-include_default_type(Module) ->
- NameAbsList = default_type_list(),
- include_default_type1(Module,NameAbsList).
-
-include_default_type1(_,[]) ->
- ok;
-include_default_type1(Module,[{Name,TS}|Rest]) ->
- case asn1_db:dbget(Module,Name) of
- undefined ->
- T = #typedef{name=Name,
- typespec=TS},
- asn1_db:dbput(Module,Name,T);
- _ -> ok
- end,
- include_default_type1(Module,Rest).
-
-default_type_list() ->
- %% The EXTERNAL type is represented, according to ASN.1 1997,
- %% as a SEQUENCE with components: identification, data-value-descriptor
- %% and data-value.
- Syntax =
- #'ComponentType'{name=syntax,
- typespec=#type{def='OBJECT IDENTIFIER'},
- prop=mandatory},
- Presentation_Cid =
- #'ComponentType'{name='presentation-context-id',
- typespec=#type{def='INTEGER'},
- prop=mandatory},
- Transfer_syntax =
- #'ComponentType'{name='transfer-syntax',
- typespec=#type{def='OBJECT IDENTIFIER'},
- prop=mandatory},
- Negotiation_items =
- #type{def=
- #'SEQUENCE'{components=
- [Presentation_Cid,
- Transfer_syntax#'ComponentType'{prop=mandatory}]}},
- Context_negot =
- #'ComponentType'{name='context-negotiation',
- typespec=Negotiation_items,
- prop=mandatory},
-
- Data_value_descriptor =
- #'ComponentType'{name='data-value-descriptor',
- typespec=#type{def='ObjectDescriptor'},
- prop='OPTIONAL'},
- Data_value =
- #'ComponentType'{name='data-value',
- typespec=#type{def='OCTET STRING'},
- prop=mandatory},
-
- %% The EXTERNAL type is represented, according to ASN.1 1990,
- %% as a SEQUENCE with components: direct-reference, indirect-reference,
- %% data-value-descriptor and encoding.
-
- Direct_reference =
- #'ComponentType'{name='direct-reference',
- typespec=#type{def='OBJECT IDENTIFIER'},
- prop='OPTIONAL'},
-
- Indirect_reference =
- #'ComponentType'{name='indirect-reference',
- typespec=#type{def='INTEGER'},
- prop='OPTIONAL'},
-
- Single_ASN1_type =
- #'ComponentType'{name='single-ASN1-type',
- typespec=#type{tag=[{tag,'CONTEXT',0,
- 'EXPLICIT',32}],
- def='ANY'},
- prop=mandatory},
-
- Octet_aligned =
- #'ComponentType'{name='octet-aligned',
- typespec=#type{tag=[{tag,'CONTEXT',1,
- 'IMPLICIT',32}],
- def='OCTET STRING'},
- prop=mandatory},
-
- Arbitrary =
- #'ComponentType'{name=arbitrary,
- typespec=#type{tag=[{tag,'CONTEXT',2,
- 'IMPLICIT',32}],
- def={'BIT STRING',[]}},
- prop=mandatory},
-
- Encoding =
- #'ComponentType'{name=encoding,
- typespec=#type{def={'CHOICE',
- [Single_ASN1_type,Octet_aligned,
- Arbitrary]}},
- prop=mandatory},
-
- EXTERNAL_components1990 =
- [Direct_reference,Indirect_reference,Data_value_descriptor,Encoding],
-
- %% The EMBEDDED PDV type is represented by a SEQUENCE type
- %% with components: identification and data-value
- Abstract =
- #'ComponentType'{name=abstract,
- typespec=#type{def='OBJECT IDENTIFIER'},
- prop=mandatory},
- Transfer =
- #'ComponentType'{name=transfer,
- typespec=#type{def='OBJECT IDENTIFIER'},
- prop=mandatory},
- AbstractTrSeq =
- #'SEQUENCE'{components=[Abstract,Transfer]},
- Syntaxes =
- #'ComponentType'{name=syntaxes,
- typespec=#type{def=AbstractTrSeq},
- prop=mandatory},
- Fixed = #'ComponentType'{name=fixed,
- typespec=#type{def='NULL'},
- prop=mandatory},
- Negotiations =
- [Syntaxes,Syntax,Presentation_Cid,Context_negot,
- Transfer_syntax,Fixed],
- Identification2 =
- #'ComponentType'{name=identification,
- typespec=#type{def={'CHOICE',Negotiations}},
- prop=mandatory},
- EmbeddedPdv_components =
- [Identification2,Data_value],
-
- %% The CHARACTER STRING type is represented by a SEQUENCE type
- %% with components: identification and string-value
- String_value =
- #'ComponentType'{name='string-value',
- typespec=#type{def='OCTET STRING'},
- prop=mandatory},
- CharacterString_components =
- [Identification2,String_value],
-
- [{'EXTERNAL',
- #type{tag=[#tag{class='UNIVERSAL',
- number=8,
- type='IMPLICIT',
- form=32}],
- def=#'SEQUENCE'{components=
- EXTERNAL_components1990}}},
- {'EMBEDDED PDV',
- #type{tag=[#tag{class='UNIVERSAL',
- number=11,
- type='IMPLICIT',
- form=32}],
- def=#'SEQUENCE'{components=EmbeddedPdv_components}}},
- {'CHARACTER STRING',
- #type{tag=[#tag{class='UNIVERSAL',
- number=29,
- type='IMPLICIT',
- form=32}],
- def=#'SEQUENCE'{components=CharacterString_components}}}
- ].
-
-
-include_default_class(Module) ->
- NameAbsList = default_class_list(),
- include_default_class1(Module,NameAbsList).
-
-include_default_class1(_,[]) ->
- ok;
-include_default_class1(Module,[{Name,TS}|_Rest]) ->
- case asn1_db:dbget(Module,Name) of
- undefined ->
- C = #classdef{checked=true,name=Name,
- typespec=TS},
- asn1_db:dbput(Module,Name,C);
- _ -> ok
- end.
-
-default_class_list() ->
- [{'TYPE-IDENTIFIER',
- {objectclass,
- [{fixedtypevaluefield,
- id,
- {type,[],'OBJECT IDENTIFIER',[]},
- 'UNIQUE',
- 'MANDATORY'},
- {typefield,'Type','MANDATORY'}],
- {'WITH SYNTAX',
- [{typefieldreference,'Type'},
- 'IDENTIFIED',
- 'BY',
- {valuefieldreference,id}]}}},
- {'ABSTRACT-SYNTAX',
- {objectclass,
- [{fixedtypevaluefield,
- id,
- {type,[],'OBJECT IDENTIFIER',[]},
- 'UNIQUE',
- 'MANDATORY'},
- {typefield,'Type','MANDATORY'},
- {fixedtypevaluefield,
- property,
- {type,
- [],
- {'BIT STRING',[]},
- []},
- undefined,
- {'DEFAULT',
- [0,1,0]}}],
- {'WITH SYNTAX',
- [{typefieldreference,'Type'},
- 'IDENTIFIED',
- 'BY',
- {valuefieldreference,id},
- ['HAS',
- 'PROPERTY',
- {valuefieldreference,property}]]}}}].
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_constructed_ber.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_constructed_ber.erl
deleted file mode 100644
index 8a639de5bb..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_constructed_ber.erl
+++ /dev/null
@@ -1,1468 +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: asn1ct_constructed_ber.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
-%%
--module(asn1ct_constructed_ber).
-
--export([gen_encode_sequence/3]).
--export([gen_decode_sequence/3]).
--export([gen_encode_set/3]).
--export([gen_decode_set/3]).
--export([gen_encode_sof/4]).
--export([gen_decode_sof/4]).
--export([gen_encode_choice/3]).
--export([gen_decode_choice/3]).
-
-%%%% Application internal exports
--export([match_tag/2]).
-
--include("asn1_records.hrl").
-
--import(asn1ct_gen, [emit/1,demit/1]).
-
-% the encoding of class of tag bits 8 and 7
--define(UNIVERSAL, 0).
--define(APPLICATION, 16#40).
--define(CONTEXT, 16#80).
--define(PRIVATE, 16#C0).
-
-% primitive or constructed encoding % bit 6
--define(PRIMITIVE, 0).
--define(CONSTRUCTED, 2#00100000).
-
-
-
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Encode/decode SEQUENCE
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-gen_encode_sequence(Erules,Typename,D) when record(D,type) ->
- asn1ct_name:start(),
- asn1ct_name:new(term),
- asn1ct_name:new(bytes),
-
- %% if EXTERNAL type the input value must be transformed to
- %% ASN1 1990 format
- case Typename of
- ['EXTERNAL'] ->
- emit([" NewVal = asn1rt_check:transform_to_EXTERNAL1990(Val),",
- nl]);
- _ ->
- ok
- end,
-
- {SeqOrSet,TableConsInfo,CompList} =
- case D#type.def of
- #'SEQUENCE'{tablecinf=TCI,components=CL} ->
- {'SEQUENCE',TCI,CL};
- #'SET'{tablecinf=TCI,components=CL} ->
- {'SET',TCI,CL}
- end,
- Ext = extensible(CompList),
- CompList1 = case CompList of
- {Rl,El} -> Rl ++ El;
- _ -> CompList
- end,
- EncObj =
- case TableConsInfo of
- #simpletableattributes{usedclassfield=Used,
- uniqueclassfield=Unique} when Used /= Unique ->
- false;
- %% ObjectSet, name of the object set in constraints
- %%
- %%{ObjectSet,AttrN,N,UniqueFieldName}
- #simpletableattributes{objectsetname=ObjectSet,
- c_name=AttrN,
- c_index=N,
- usedclassfield=UniqueFieldName,
- uniqueclassfield=UniqueFieldName,
- valueindex=ValueIndex
- } ->
- OSDef =
- case ObjectSet of
- {Module,OSName} ->
- asn1_db:dbget(Module,OSName);
- OSName ->
- asn1_db:dbget(get(currmod),OSName)
- end,
-% io:format("currmod: ~p~nOSName: ~p~nAttrN: ~p~nN: ~p~nUniqueFieldName: ~p~n",
-% [get(currmod),OSName,AttrN,N,UniqueFieldName]),
- case (OSDef#typedef.typespec)#'ObjectSet'.gen of
- true ->
-% Val = lists:concat(["?RT_BER:cindex(",
-% N+1,",Val,"]),
- ObjectEncode =
- asn1ct_gen:un_hyphen_var(lists:concat(['Obj',
- AttrN])),
- emit({ObjectEncode," = ",nl}),
- emit({" 'getenc_",ObjectSet,"'(",{asis,UniqueFieldName},
- ", ",nl}),
-% emit({indent(35),"?RT_BER:cindex(",N+1,", Val,",
-% {asis,AttrN},")),",nl}),
- emit([indent(10+length(atom_to_list(ObjectSet))),
- "value_match(",{asis,ValueIndex},",",
- "?RT_BER:cindex(",N+1,",Val,",
- {asis,AttrN},"))),",nl]),
- notice_value_match(),
- {AttrN,ObjectEncode};
- _ ->
- false
- end;
- _ ->
- case D#type.tablecinf of
- [{objfun,_}|_] ->
- %% when the simpletableattributes was at an
- %% outer level and the objfun has been passed
- %% through the function call
- {"got objfun through args","ObjFun"};
- _ ->
- false
- end
- end,
-
- gen_enc_sequence_call(Erules,Typename,CompList1,1,Ext,EncObj),
-
- MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
- ++
- [#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
- number = asn1ct_gen_ber:decode_type(SeqOrSet),
- form = ?CONSTRUCTED,
- type = 'IMPLICIT'}],
- emit([nl," BytesSoFar = "]),
- case SeqOrSet of
- 'SET' when (D#type.def)#'SET'.sorted == dynamic ->
- emit("?RT_BER:dynamicsort_SET_components(["),
- mkvlist(asn1ct_name:all(encBytes)),
- emit(["]),",nl]);
- _ ->
- emit("["),
- mkvlist(asn1ct_name:all(encBytes)),
- emit(["],",nl])
- end,
- emit(" LenSoFar = "),
- case asn1ct_name:all(encLen) of
- [] -> emit("0");
- AllLengths ->
- mkvplus(AllLengths)
- end,
- emit([",",nl]),
-% emit(["{TagBytes,Len} = ?RT_BER:encode_tags(TagIn ++ ",
- emit([" ?RT_BER:encode_tags(TagIn ++ ",
- {asis,MyTag},", BytesSoFar, LenSoFar).",nl]).
-
-
-gen_decode_sequence(Erules,Typename,D) when record(D,type) ->
- asn1ct_name:start(),
-% asn1ct_name:new(term),
- asn1ct_name:new(tag),
- #'SEQUENCE'{tablecinf=TableConsInfo,components=CList} = D#type.def,
- Ext = extensible(CList),
- CompList = case CList of
- {Rl,El} -> Rl ++ El;
- _ -> CList
- end,
-
- emit({" %%-------------------------------------------------",nl}),
- emit({" %% decode tag and length ",nl}),
- emit({" %%-------------------------------------------------",nl}),
-
- asn1ct_name:new(rb),
- MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
- ++
- [#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
- number = asn1ct_gen_ber:decode_type('SEQUENCE'),
- form = ?CONSTRUCTED,
- type = 'IMPLICIT'}],
- emit([" {{_,",asn1ct_gen_ber:unused_var("Len",D#type.def),"},",{next,bytes},",",{curr,rb},
- "} = ?RT_BER:check_tags(TagIn ++ ",{asis,MyTag},", ",
- {curr,bytes},", OptOrMand), ",nl]),
- asn1ct_name:new(bytes),
- asn1ct_name:new(len),
-
- case CompList of
- [] -> true;
- _ ->
- emit({"{",{next,bytes},
- ",RemBytes} = ?RT_BER:split_list(",
- {curr,bytes},
- ",", {prev,len},"),",nl}),
- asn1ct_name:new(bytes)
- end,
-
- {DecObjInf,UniqueFName,ValueIndex} =
- case TableConsInfo of
- #simpletableattributes{objectsetname=ObjectSet,
- c_name=AttrN,
- usedclassfield=UniqueFieldName,
- uniqueclassfield=UniqueFieldName,
- valueindex=ValIndex
- } ->
- F = fun(#'ComponentType'{typespec=CT})->
- case {CT#type.constraint,CT#type.tablecinf} of
- {[],[{objfun,_}|_R]} -> true;
- _ -> false
- end
- end,
- case lists:any(F,CompList) of
- %%AttributeName = asn1ct_gen:un_hyphen_var(AttrN),
- true -> % when component relation constraint establish
- %% relation from a component to another components
- %% subtype component
- {{AttrN,{deep,ObjectSet,UniqueFieldName,
- ValIndex}},
- UniqueFieldName,ValIndex};
- false ->
- {{AttrN,ObjectSet},UniqueFieldName,ValIndex}
- end;
- _ ->
- {false,false,false}
- end,
- case gen_dec_sequence_call(Erules,Typename,CompList,Ext,DecObjInf) of
- no_terms -> % an empty sequence
- emit([nl,nl]),
- demit({"Result = "}), %dbg
- %% return value as record
- asn1ct_name:new(rb),
- emit([" {{'",asn1ct_gen:list2rname(Typename),"'}, ",{curr,bytes},",",nl," "]),
- asn1ct_gen_ber:add_removed_bytes(),
- emit(["}.",nl]);
- {LeadingAttrTerm,PostponedDecArgs} ->
- emit([com,nl,nl]),
- case {LeadingAttrTerm,PostponedDecArgs} of
- {[],[]} ->
- ok;
- {_,[]} ->
- ok;
- {[{ObjSet,LeadingAttr,Term}],PostponedDecArgs} ->
- DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])),
- ValueMatch = value_match(ValueIndex,Term),
- emit([DecObj," =",nl," 'getdec_",ObjSet,"'(",
-% {asis,UniqueFName},", ",Term,"),",nl}),
- {asis,UniqueFName},", ",ValueMatch,"),",nl]),
- gen_dec_postponed_decs(DecObj,PostponedDecArgs)
- end,
- demit({"Result = "}), %dbg
- %% return value as record
- asn1ct_name:new(rb),
- asn1ct_name:new(bytes),
- ExtStatus = case Ext of
- {ext,_,_} -> ext;
- noext -> noext
- end,
- emit([" {",{next,bytes},",",{curr,rb},"} = ?RT_BER:restbytes2(RemBytes, ",
- {curr,bytes},",",ExtStatus,"),",nl]),
- asn1ct_name:new(rb),
- case Typename of
- ['EXTERNAL'] ->
- emit([" OldFormat={'",asn1ct_gen:list2rname(Typename),
- "', "]),
- mkvlist(asn1ct_name:all(term)),
- emit(["},",nl]),
- emit([" ASN11994Format =",nl,
- " asn1rt_check:transform_to_EXTERNAL1994",
- "(OldFormat),",nl]),
- emit([" {ASN11994Format,",{next,bytes},", "]);
- _ ->
- emit([" {{'",asn1ct_gen:list2rname(Typename),"', "]),
- mkvlist(asn1ct_name:all(term)),
- emit(["}, ",{next,bytes},", "])
- end,
- asn1ct_gen_ber:add_removed_bytes(),
- emit(["}.",nl])
- end.
-
-gen_dec_postponed_decs(_,[]) ->
- emit(nl);
-gen_dec_postponed_decs(DecObj,[{_Cname,{FirstPFN,PFNList},Term,TmpTerm,_Tag,OptOrMand}|Rest]) ->
-% asn1ct_name:new(term),
- asn1ct_name:new(tmpterm),
- asn1ct_name:new(reason),
-
- emit({"{",Term,", _, _} = ",nl}),
- N = case OptOrMand of
- mandatory -> 0;
- 'OPTIONAL' ->
- emit_opt_or_mand_check(asn1_NOVALUE,TmpTerm),
- 6;
- {'DEFAULT',Val} ->
- emit_opt_or_mand_check(Val,TmpTerm),
- 6
- end,
- emit({indent(N+3),"case (catch ",DecObj,"(",{asis,FirstPFN},
-% ", ",TmpTerm,", ", {asis,Tag},", ",{asis,PFNList},")) of",nl}),
- ", ",TmpTerm,", [], ",{asis,PFNList},")) of",nl}),
- emit({indent(N+6),"{'EXIT', ",{curr,reason},"} ->",nl}),
- emit({indent(N+9),"exit({'Type not compatible with table constraint',",
- {curr,reason},"});",nl}),
- emit({indent(N+6),{curr,tmpterm}," ->",nl}),
- emit({indent(N+9),{curr,tmpterm},nl}),
-
- case OptOrMand of
- mandatory -> emit([indent(N+3),"end,",nl]);
- _ ->
- emit([indent(N+3),"end",nl,
- indent(3),"end,",nl])
- end,
-% emit({indent(3),"end,",nl}),
- gen_dec_postponed_decs(DecObj,Rest).
-
-
-emit_opt_or_mand_check(Value,TmpTerm) ->
- emit([indent(3),"case ",TmpTerm," of",nl,
- indent(6),{asis,Value}," -> {",{asis,Value},",[],[]};",nl,
- indent(6),"_ ->",nl]).
-
-%%============================================================================
-%% Encode/decode SET
-%%
-%%============================================================================
-
-gen_encode_set(Erules,Typename,D) when record(D,type) ->
- gen_encode_sequence(Erules,Typename,D).
-
-gen_decode_set(Erules,Typename,D) when record(D,type) ->
- asn1ct_name:start(),
- asn1ct_name:new(term),
- asn1ct_name:new(tag),
- #'SET'{components=TCompList} = D#type.def,
- Ext = extensible(TCompList),
- CompList = case TCompList of
- {Rl,El} -> Rl ++ El;
- _ -> TCompList
- end,
-
- emit([" %%-------------------------------------------------",nl]),
- emit([" %% decode tag and length ",nl]),
- emit([" %%-------------------------------------------------",nl]),
-
- asn1ct_name:new(rb),
- MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
- ++
- [#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
- number = asn1ct_gen_ber:decode_type('SET'),
- form = ?CONSTRUCTED,
- type = 'IMPLICIT'}],
- emit([" {{_,Len},",{next,bytes},",",{curr,rb},
- "} = ?RT_BER:check_tags(TagIn ++ ",{asis,MyTag},", ",
- {curr,bytes},", OptOrMand), ",nl]),
- asn1ct_name:new(bytes),
- asn1ct_name:new(len),
- asn1ct_name:new(rb),
-
- emit([" {SetTerm, SetBytes, ",{curr,rb},"} = ?RT_BER:decode_set(0, Len, ",
- {curr,bytes},", OptOrMand, ",
- "fun 'dec_",asn1ct_gen:list2name(Typename),"_fun'/2, []),",nl]),
-
- asn1ct_name:new(rb),
- emit([" 'dec_",asn1ct_gen:list2name(Typename),"_result'(lists:sort(SetTerm), SetBytes, "]),
- asn1ct_gen_ber:add_removed_bytes(),
- emit([").",nl,nl,nl]),
-
- emit({"%%-------------------------------------------------",nl}),
- emit({"%% Set loop fun for ",asn1ct_gen:list2name(Typename),nl}),
- emit({"%%-------------------------------------------------",nl}),
-
- asn1ct_name:clear(),
- asn1ct_name:new(term),
- emit(["'dec_",asn1ct_gen:list2name(Typename),"_fun'(",{curr,bytes},
- ", OptOrMand) ->",nl]),
-
- asn1ct_name:new(bytes),
- gen_dec_set(Erules,Typename,CompList,1,Ext),
-
- emit([" %% tag not found, if extensionmark we should skip bytes here",nl]),
- emit([indent(6),"_ -> {[], Bytes,0}",nl]),
- emit([indent(3),"end.",nl,nl,nl]),
-
-
- emit({"%%-------------------------------------------------",nl}),
- emit({"%% Result ",asn1ct_gen:list2name(Typename),nl}),
- emit({"%%-------------------------------------------------",nl}),
-
- asn1ct_name:clear(),
- emit({"'dec_",asn1ct_gen:list2name(Typename),"_result'(",
- asn1ct_gen_ber:unused_var("TermList",D#type.def),", Bytes, Rb) ->",nl}),
-
- case gen_dec_set_result(Erules,Typename,CompList) of
- no_terms ->
- %% return value as record
- asn1ct_name:new(rb),
- emit({" {{'",asn1ct_gen:list2rname(Typename),"'}, Bytes, Rb}.",nl});
- _ ->
- emit({nl," case ",{curr,termList}," of",nl}),
- emit({" [] -> {{'",asn1ct_gen:list2rname(Typename),"', "}),
- mkvlist(asn1ct_name:all(term)),
- emit({"}, Bytes, Rb};",nl}),
- emit({" ExtraAtt -> exit({error,{asn1,{too_many_attributes, ExtraAtt}}})",nl}),
- emit({" end.",nl}),
- emit({nl,nl,nl})
- end.
-
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Encode/decode SEQUENCE OF and SET OF
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-gen_encode_sof(Erules,Typename,_InnerTypename,D) when record(D,type) ->
- asn1ct_name:start(),
- {SeqOrSetOf, Cont} = D#type.def,
-
- Objfun = case D#type.tablecinf of
- [{objfun,_}|_R] ->
- ", ObjFun";
- _ ->
- ""
- end,
-
- emit({" {EncBytes,EncLen} = 'enc_",asn1ct_gen:list2name(Typename),
- "_components'(Val",Objfun,",[],0),",nl}),
-
- MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
- ++
- [#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
- number = asn1ct_gen_ber:decode_type(SeqOrSetOf),
- form = ?CONSTRUCTED,
- type = 'IMPLICIT'}],
-% gen_encode_tags(Erules,MyTag,"EncLen","EncBytes"),
- emit([" ?RT_BER:encode_tags(TagIn ++ ",
- {asis,MyTag},", EncBytes, EncLen).",nl,nl]),
-
- gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont).
-% gen_enc_line(Erules,Typename,TypeNameSuffix,Cont,"H",0,
-% mandatory,"{EncBytes,EncLen} = "),
-
-
-gen_decode_sof(Erules,Typename,_InnerTypename,D) when record(D,type) ->
- asn1ct_name:start(),
- {SeqOrSetOf, TypeTag, Cont} =
- case D#type.def of
- {'SET OF',_Cont} -> {'SET OF','SET',_Cont};
- {'SEQUENCE OF',_Cont} -> {'SEQUENCE OF','SEQUENCE',_Cont}
- end,
- TypeNameSuffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,Cont#type.def),
-
- emit({" %%-------------------------------------------------",nl}),
- emit({" %% decode tag and length ",nl}),
- emit({" %%-------------------------------------------------",nl}),
-
- asn1ct_name:new(rb),
- MyTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- D#type.tag]
- ++
- [#tag{class = asn1ct_gen_ber:decode_class('UNIVERSAL'),
- number = asn1ct_gen_ber:decode_type(TypeTag),
- form = ?CONSTRUCTED,
- type = 'IMPLICIT'}],
- emit([" {{_,Len},",{next,bytes},",",{curr,rb},
- "} = ?RT_BER:check_tags(TagIn ++ ",{asis,MyTag},", ",
- {curr,bytes},", OptOrMand), ",nl]),
-
- emit([" ?RT_BER:decode_components(",{curr,rb}]),
- InnerType = asn1ct_gen:get_inner(Cont#type.def),
- ContName = case asn1ct_gen:type(InnerType) of
- Atom when atom(Atom) -> Atom;
- _ -> TypeNameSuffix
- end,
- emit([", Len, ",{next,bytes},", "]),
-% NewCont =
-% case Cont#type.def of
-% {'ENUMERATED',_,Components}->
-% Cont#type{def={'ENUMERATED',Components}};
-% _ -> Cont
-% end,
- ObjFun =
- case D#type.tablecinf of
- [{objfun,_}|_R] ->
- ", ObjFun";
- _ ->
- []
- end,
- gen_dec_line_sof(Erules,Typename,ContName,Cont,ObjFun),
- emit([", []).",nl,nl,nl]).
-
-
-gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont)
- when record(Cont,type)->
-
- {Objfun,ObjFun_novar,EncObj} =
- case Cont#type.tablecinf of
- [{objfun,_}|_R] ->
- {", ObjFun",", _",{no_attr,"ObjFun"}};
- _ ->
- {"","",false}
- end,
- emit(["'enc_",asn1ct_gen:list2name(Typename),
- "_components'([]",ObjFun_novar,", AccBytes, AccLen) -> ",nl]),
-
- case catch lists:member(der,get(encoding_options)) of
- true ->
- emit([indent(3),
- "{?RT_BER:dynamicsort_SETOF(AccBytes),AccLen};",nl,nl]);
- _ ->
- emit([indent(3),"{lists:reverse(AccBytes),AccLen};",nl,nl])
- end,
- emit(["'enc_",asn1ct_gen:list2name(Typename),
- "_components'([H|T]",Objfun,",AccBytes, AccLen) ->",nl]),
- TypeNameSuffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,Cont#type.def),
- gen_enc_line(Erules,Typename,TypeNameSuffix,Cont,"H",3,
- mandatory,"{EncBytes,EncLen} = ",EncObj),
- emit([",",nl]),
- emit([indent(3),"'enc_",asn1ct_gen:list2name(Typename),
- "_components'(T",Objfun,","]),
- emit(["[EncBytes|AccBytes], AccLen + EncLen).",nl,nl]).
-
-%%============================================================================
-%% Encode/decode CHOICE
-%%
-%%============================================================================
-
-gen_encode_choice(Erules,Typename,D) when record(D,type) ->
- ChoiceTag = D#type.tag,
- {'CHOICE',CompList} = D#type.def,
- Ext = extensible(CompList),
- CompList1 = case CompList of
- {Rl,El} -> Rl ++ El;
- _ -> CompList
- end,
- gen_enc_choice(Erules,Typename,ChoiceTag,CompList1,Ext),
- emit({nl,nl}).
-
-gen_decode_choice(Erules,Typename,D) when record(D,type) ->
- asn1ct_name:start(),
- asn1ct_name:new(bytes),
- ChoiceTag = D#type.tag,
- {'CHOICE',CompList} = D#type.def,
- Ext = extensible(CompList),
- CompList1 = case CompList of
- {Rl,El} -> Rl ++ El;
- _ -> CompList
- end,
- gen_dec_choice(Erules,Typename,ChoiceTag,CompList1,Ext),
- emit({".",nl}).
-
-
-%%============================================================================
-%% Encode SEQUENCE
-%%
-%%============================================================================
-
-gen_enc_sequence_call(Erules,TopType,[#'ComponentType'{name=Cname,typespec=Type,prop=Prop}|Rest],Pos,Ext,EncObj) ->
- asn1ct_name:new(encBytes),
- asn1ct_name:new(encLen),
- Element =
- case TopType of
- ['EXTERNAL'] ->
- io_lib:format("?RT_BER:cindex(~w,NewVal,~w)",[Pos+1,Cname]);
- _ ->
- io_lib:format("?RT_BER:cindex(~w,Val,~w)",[Pos+1,Cname])
- end,
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- print_attribute_comment(InnerType,Pos,Prop),
- gen_enc_line(Erules,TopType,Cname,Type,Element,3,Prop,EncObj),
- case Rest of
- [] ->
- emit({com,nl});
- _ ->
- emit({com,nl}),
- gen_enc_sequence_call(Erules,TopType,Rest,Pos+1,Ext,EncObj)
- end;
-
-gen_enc_sequence_call(_Erules,_TopType,[],_Num,_,_) ->
- true.
-
-%%============================================================================
-%% Decode SEQUENCE
-%%
-%%============================================================================
-
-gen_dec_sequence_call(Erules,TopType,CompList,Ext,DecObjInf) ->
- gen_dec_sequence_call1(Erules,TopType, CompList, 1, Ext,DecObjInf,[],[]).
-
-
-gen_dec_sequence_call1(Erules,TopType,[#'ComponentType'{name=Cname,typespec=Type,prop=Prop,tags=Tags}|Rest],Num,Ext,DecObjInf,LeadingAttrAcc,ArgsAcc) ->
- {LA,PostponedDec} =
- gen_dec_component(Erules,TopType,Cname,Tags,Type,Num,Prop,
- Ext,DecObjInf),
- case Rest of
- [] ->
- {LA ++ LeadingAttrAcc,PostponedDec ++ ArgsAcc};
- _ ->
- emit({com,nl}),
-% asn1ct_name:new(term),
- asn1ct_name:new(bytes),
- gen_dec_sequence_call1(Erules,TopType,Rest,Num+1,Ext,DecObjInf,
- LA++LeadingAttrAcc,PostponedDec++ArgsAcc)
- end;
-
-gen_dec_sequence_call1(_Erules,_TopType,[],1,_,_,_,_) ->
- no_terms.
-%%gen_dec_sequence_call1(Erules,_TopType,[],Num,_) ->
-%% true.
-
-
-
-%%----------------------------
-%%SEQUENCE mandatory
-%%----------------------------
-
-gen_dec_component(Erules,TopType,Cname,CTags,Type,Pos,Prop,Ext,DecObjInf) ->
- InnerType =
- case Type#type.def of
- #'ObjectClassFieldType'{type=OCFTType} -> OCFTType;
- _ -> asn1ct_gen:get_inner(Type#type.def)
- end,
-% case asn1ct_gen:get_constraint(Type#type.constraint,
-% tableconstraint_info) of
-% no ->
-% asn1ct_gen:get_inner(Type#type.def);
-% _ ->
-% Type#type.def
-% end,
- Prop1 = case {Prop,Ext} of
- {mandatory,{ext,Epos,_}} when Pos >= Epos ->
- 'OPTIONAL';
- _ ->
- Prop
- end,
- print_attribute_comment(InnerType,Pos,Prop1),
- emit(" "),
-
- case {InnerType,DecObjInf} of
- {{typefield,_},NotFalse} when NotFalse /= false ->
- asn1ct_name:new(term),
- asn1ct_name:new(tmpterm),
- emit({"{",{curr,tmpterm},", ",{next,bytes},",",{next,rb},"} = "});
- {{objectfield,_,_},_} ->
- asn1ct_name:new(term),
- asn1ct_name:new(tmpterm),
- emit({"{",{curr,tmpterm},", ",{next,bytes},",",{next,rb},"} = "});
- _ ->
- asn1ct_name:new(term),
- emit({"{",{curr,term},",",{next,bytes},",",{next,rb},"} = "})
- end,
- asn1ct_name:new(rb),
- PostponedDec =
- gen_dec_line(Erules,TopType,Cname,CTags,Type,Prop1,DecObjInf),
- asn1ct_name:new(form),
- PostponedDec.
-
-
-%%-------------------------------------
-%% Decode SET
-%%-------------------------------------
-
-gen_dec_set(Erules,TopType,CompList,Pos,_Ext) ->
- TagList = get_all_choice_tags(CompList),
- emit({indent(3),
- {curr,tagList}," = ",{asis,TagList},",",nl}),
- emit({indent(3),
- "case ?RT_BER:check_if_valid_tag(Bytes, ",
- {curr,tagList},", OptOrMand) of",nl}),
- asn1ct_name:new(tagList),
- asn1ct_name:new(rbCho),
- asn1ct_name:new(choTags),
- gen_dec_set_cases(Erules,TopType,CompList,TagList,Pos),
- asn1ct_name:new(tag),
- asn1ct_name:new(bytes).
-
-
-
-gen_dec_set_cases(_,_,[],_,_) ->
- ok;
-gen_dec_set_cases(Erules,TopType,[H|T],List,Pos) ->
- case H of
- {'EXTENSIONMARK', _, _} ->
- gen_dec_set_cases(Erules,TopType,T,List,Pos);
- _ ->
- Name = H#'ComponentType'.name,
- Type = H#'ComponentType'.typespec,
-
- emit({indent(6),"'",Name,"' ->",nl}),
- case Type#type.def of
- {'CHOICE',_NewCompList} ->
- gen_dec_set_cases_choice(Erules,TopType,H,Pos);
- _ ->
- gen_dec_set_cases_type(Erules,TopType,H,Pos)
- end,
- gen_dec_set_cases(Erules,TopType,T,List,Pos+1)
- end.
-
-
-
-
-gen_dec_set_cases_choice(_Erules,TopType,H,Pos) ->
- Cname = H#'ComponentType'.name,
- Tag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}
- || X <- (H#'ComponentType'.typespec)#type.tag],
- asn1ct_name:new(rbCho),
- emit({indent(9),"{Dec, Rest, ",{curr,rbCho},"} = "}),
- emit({"'dec_",asn1ct_gen:list2name([Cname|TopType]),
- "'(Bytes,OptOrMand,",{asis,Tag},"),",nl}),
- emit([" {{",Pos,",Dec}, Rest, ",{curr,rbCho},"}"]),
- emit([";",nl,nl]).
-
-
-gen_dec_set_cases_type(Erules,TopType,H,Pos) ->
- Cname = H#'ComponentType'.name,
- Type = H#'ComponentType'.typespec,
- %% always use Prop = mandatory here Prop = H#'ComponentType'.prop,
-
- asn1ct_name:new(rbCho),
- emit({indent(9),"{Dec, Rest, ",{curr,rbCho},"} = "}),
- asn1ct_name:delete(bytes),
- %% we have already seen the tag so now we must find the value
- %% that why we always use 'mandatory' here
- gen_dec_line(Erules,TopType,Cname,[],Type,mandatory,decObjInf),
- asn1ct_name:new(bytes),
-
- emit([",",nl]),
- emit(["{{",Pos,",Dec}, Rest, ",{curr,rbCho},"}"]),
- emit([";",nl,nl]).
-
-
-%%---------------------------------
-%% Decode SET result
-%%---------------------------------
-
-gen_dec_set_result(Erules,TopType,{CompList,_ExtList}) ->
- gen_dec_set_result1(Erules,TopType, CompList, 1);
-gen_dec_set_result(Erules,TopType,CompList) ->
- gen_dec_set_result1(Erules,TopType, CompList, 1).
-
-gen_dec_set_result1(Erules,TopType,
- [#'ComponentType'{name=Cname,
- typespec=Type,
- prop=Prop}|Rest],Num) ->
- gen_dec_set_component(Erules,TopType,Cname,Type,Num,Prop),
- case Rest of
- [] ->
- true;
- _ ->
- gen_dec_set_result1(Erules,TopType,Rest,Num+1)
- end;
-
-gen_dec_set_result1(_Erules,_TopType,[],1) ->
- no_terms;
-gen_dec_set_result1(_Erules,_TopType,[],_Num) ->
- true.
-
-
-gen_dec_set_component(_Erules,_TopType,_Cname,Type,Pos,Prop) ->
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- print_attribute_comment(InnerType,Pos,Prop),
- emit({" {",{next,term},com,{next,termList},"} =",nl}),
- emit({" case ",{curr,termList}," of",nl}),
- emit({" [{",Pos,com,{curr,termTmp},"}|",
- {curr,rest},"] -> "}),
- emit({"{",{curr,termTmp},com,
- {curr,rest},"};",nl}),
- case Prop of
- 'OPTIONAL' ->
- emit([indent(10),"_ -> {asn1_NOVALUE, ",{curr,termList},"}",nl]);
- {'DEFAULT', DefVal} ->
- emit([indent(10),
- "_ -> {",{asis,DefVal},", ",{curr,termList},"}",nl]);
- mandatory ->
- emit([indent(10),
- "_ -> exit({error,{asn1,{mandatory_attribute_no, ",
- Pos,", missing}}})",nl])
- end,
- emit([indent(6),"end,",nl]),
- asn1ct_name:new(rest),
- asn1ct_name:new(term),
- asn1ct_name:new(termList),
- asn1ct_name:new(termTmp).
-
-
-%%---------------------------------------------
-%% Encode CHOICE
-%%---------------------------------------------
-%% for BER we currently do care (a little) if the choice has an EXTENSIONMARKER
-
-
-gen_enc_choice(Erules,TopType,Tag,CompList,_Ext) ->
- gen_enc_choice1(Erules,TopType,Tag,CompList,_Ext).
-
-gen_enc_choice1(Erules,TopType,Tag,CompList,_Ext) ->
- asn1ct_name:clear(),
- emit({" {EncBytes,EncLen} = case element(1,Val) of",nl}),
- gen_enc_choice2(Erules,TopType,CompList),
- emit([nl," end,",nl,nl]),
- NewTag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- Tag],
-% gen_encode_tags(Erules,NewTag,"EncLen","EncBytes").
- emit(["?RT_BER:encode_tags(TagIn ++",{asis,NewTag},", EncBytes, EncLen).",nl]).
-
-
-
-gen_enc_choice2(Erules,TopType,[H1|T]) when record(H1,'ComponentType') ->
- Cname = H1#'ComponentType'.name,
- Type = H1#'ComponentType'.typespec,
- emit({" ",{asis,Cname}," ->",nl}),
- {Encobj,Assign} =
-% case asn1ct_gen:get_constraint(Type#type.constraint,
-% tableconstraint_info) of
- case {Type#type.def,asn1ct_gen:get_constraint(Type#type.constraint,
- componentrelation)} of
- {#'ObjectClassFieldType'{},{componentrelation,_,_}} ->
- asn1ct_name:new(tmpBytes),
- asn1ct_name:new(encBytes),
- asn1ct_name:new(encLen),
- Emit = ["{",{curr,tmpBytes},", _} = "],
- {{no_attr,"ObjFun"},Emit};
- _ ->
- {false,[]}
- end,
- gen_enc_line(Erules,TopType,Cname,Type,"element(2,Val)",9,
- mandatory,Assign,Encobj),
- case Encobj of
- false -> ok;
- _ ->
- emit({",",nl,indent(9),"{",{curr,encBytes},", ",
- {curr,encLen},"}"})
- end,
- emit({";",nl}),
- case T of
- [] ->
- emit([indent(6), "Else -> ",nl,
- indent(9),"exit({error,{asn1,{invalid_choice_type,Else}}})"]);
- _ ->
- true
- end,
- gen_enc_choice2(Erules,TopType,T);
-
-gen_enc_choice2(_,_,[]) ->
- true.
-
-
-
-
-%%--------------------------------------------
-%% Decode CHOICE
-%%--------------------------------------------
-
-gen_dec_choice(Erules,TopType, ChTag, CompList, Ext) ->
- asn1ct_name:delete(bytes),
- Tags = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}|| X <- ChTag],
-
- emit([" {{_,Len},",{next,bytes},
- ", RbExp} = ?RT_BER:check_tags(TagIn++",
- {asis,Tags},", ",
- {curr,bytes},", OptOrMand),",nl]),
- asn1ct_name:new(bytes),
- asn1ct_name:new(len),
- gen_dec_choice_indef_funs(Erules),
- case Erules of
- ber_bin ->
- emit([indent(3),"case ",{curr,bytes}," of",nl]);
- ber ->
- emit([indent(3),
- "case (catch ?RT_BER:peek_tag(",{curr,bytes},")) of",nl])
- end,
- asn1ct_name:new(tagList),
- asn1ct_name:new(choTags),
- gen_dec_choice_cases(Erules,TopType,CompList),
- case Ext of
- noext ->
- emit([indent(6), {curr,else}," -> ",nl]),
- emit([indent(9),"case OptOrMand of",nl,
- indent(12),"mandatory ->","exit({error,{asn1,",
- "{invalid_choice_tag,",{curr,else},"}}});",nl,
- indent(12),"_ ->","exit({error,{asn1,{no_optional_tag,",
- {curr,else},"}}})",nl,
- indent(9),"end",nl]);
- _ ->
- emit([indent(6),"_ -> ",nl]),
- emit([indent(9),"{{asn1_ExtAlt,",{curr,bytes},"},",
- empty_lb(Erules),", RbExp}",nl])
- end,
- emit([indent(3),"end"]),
- asn1ct_name:new(tag),
- asn1ct_name:new(else).
-
-gen_dec_choice_indef_funs(Erules) ->
- emit({indent(3),"IndefEndBytes = fun(indefinite,",indefend_match(Erules,used_var),
- ")-> R; (_,B)-> B end,",nl}),
- emit({indent(3),"IndefEndRb = fun(indefinite,",indefend_match(Erules,unused_var),
- ")-> 2; (_,_)-> 0 end,",nl}).
-
-
-gen_dec_choice_cases(_,_, []) ->
- ok;
-gen_dec_choice_cases(Erules,TopType, [H|T]) ->
- asn1ct_name:push(rbCho),
- Name = H#'ComponentType'.name,
- emit([nl,"%% '",Name,"'",nl]),
- Fcases = fun([T1,T2|Tail],Fun) ->
- emit([indent(6),match_tag(Erules,T1)," ->",nl]),
- gen_dec_choice_cases_type(Erules,TopType, H),
- Fun([T2|Tail],Fun);
- ([T1],_) ->
- emit([indent(6),match_tag(Erules,T1)," ->",nl]),
- gen_dec_choice_cases_type(Erules,TopType, H)
- end,
- Fcases(H#'ComponentType'.tags,Fcases),
- asn1ct_name:pop(rbCho),
- gen_dec_choice_cases(Erules,TopType, T).
-
-
-
-gen_dec_choice_cases_type(Erules,TopType,H) ->
- Cname = H#'ComponentType'.name,
- Type = H#'ComponentType'.typespec,
- Prop = H#'ComponentType'.prop,
- emit({indent(9),"{Dec, Rest, ",{curr,rbCho},"} = "}),
- gen_dec_line(Erules,TopType,Cname,[],Type,Prop,false),
- emit([",",nl,indent(9),"{{",{asis,Cname},
- ", Dec}, IndefEndBytes(Len,Rest), RbExp + ",
- {curr,rbCho}," + IndefEndRb(Len,Rest)};",nl,nl]).
-
-encode_tag_val(Erules,{Class,TagNo}) when integer(TagNo) ->
- Rtmod = rtmod(Erules),
- Rtmod:encode_tag_val({asn1ct_gen_ber:decode_class(Class),
- 0,TagNo});
-encode_tag_val(Erules,{Class,TypeName}) ->
- Rtmod = rtmod(Erules),
- Rtmod:encode_tag_val({asn1ct_gen_ber:decode_class(Class),
- 0,asn1ct_gen_ber:decode_type(TypeName)}).
-
-
-match_tag(ber_bin,Arg) ->
- match_tag_with_bitsyntax(Arg);
-match_tag(Erules,Arg) ->
- io_lib:format("~p",[encode_tag_val(Erules,Arg)]).
-
-match_tag_with_bitsyntax({Class,TagNo}) when integer(TagNo) ->
- match_tag_with_bitsyntax1({asn1ct_gen_ber:decode_class(Class),
- 0,TagNo});
-match_tag_with_bitsyntax({Class,TypeName}) ->
- match_tag_with_bitsyntax1({asn1ct_gen_ber:decode_class(Class),
- 0,asn1ct_gen_ber:decode_type(TypeName)}).
-
-match_tag_with_bitsyntax1({Class, _Form, TagNo}) when (TagNo =< 30) ->
- io_lib:format("<<~p:2,_:1,~p:5,_/binary>>",[Class bsr 6,TagNo]);
-
-match_tag_with_bitsyntax1({Class, _Form, TagNo}) ->
- {Octets,Len} = mk_object_val(TagNo),
- OctForm = case Len of
- 1 -> "~p";
- 2 -> "~p,~p";
- 3 -> "~p,~p,~p";
- 4 -> "~p,~p,~p,~p"
- end,
- io_lib:format("<<~p:2,_:1,31:5," ++ OctForm ++ ",_/binary>>",
- [Class bsr 6] ++ Octets).
-
-%%%%%%%%%%%
-%% mk_object_val(Value) -> {OctetList, Len}
-%% returns a Val as a list of octets, the 8 bit is allways set to one except
-%% for the last octet, where its 0
-%%
-
-
-mk_object_val(Val) when Val =< 127 ->
- {[255 band Val], 1};
-mk_object_val(Val) ->
- mk_object_val(Val bsr 7, [Val band 127], 1).
-mk_object_val(0, Ack, Len) ->
- {Ack, Len};
-mk_object_val(Val, Ack, Len) ->
- mk_object_val(Val bsr 7, [((Val band 127) bor 128) | Ack], Len + 1).
-
-
-get_all_choice_tags(ComponentTypeList) ->
- get_all_choice_tags(ComponentTypeList,[]).
-
-get_all_choice_tags([],TagList) ->
- TagList;
-get_all_choice_tags([H|T],TagList) ->
- Tags = H#'ComponentType'.tags,
- get_all_choice_tags(T, TagList ++ [{H#'ComponentType'.name, Tags}]).
-
-
-
-%%---------------------------------------
-%% Generate the encode/decode code
-%%---------------------------------------
-
-gen_enc_line(Erules,TopType,Cname,
- Type=#type{constraint=[{componentrelation,_,_}],
- def=#'ObjectClassFieldType'{type={typefield,_}}},
- Element,Indent,OptOrMand=mandatory,EncObj)
- when list(Element) ->
- asn1ct_name:new(tmpBytes),
- gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,
- ["{",{curr,tmpBytes},",_} = "],EncObj);
-gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,EncObj)
- when list(Element) ->
- gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,
- ["{",{curr,encBytes},",",{curr,encLen},"} = "],EncObj).
-
-gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,Assign,EncObj)
- when list(Element) ->
- IndDeep = indent(Indent),
-
- Tag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}
- || X <- Type#type.tag],
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- WhatKind = asn1ct_gen:type(InnerType),
- emit(IndDeep),
- emit(Assign),
- gen_optormand_case(OptOrMand,Erules,TopType,Cname,Type,InnerType,WhatKind,
- Element),
- case {Type,asn1ct_gen:get_constraint(Type#type.constraint,
- componentrelation)} of
-% #type{constraint=[{tableconstraint_info,RefedFieldName}],
-% def={typefield,_}} ->
- {#type{def=#'ObjectClassFieldType'{type={typefield,_},
- fieldname=RefedFieldName}},
- {componentrelation,_,_}} ->
- {_LeadingAttrName,Fun} = EncObj,
- case RefedFieldName of
- {notype,T} ->
- throw({error,{notype,type_from_object,T}});
- {Name,RestFieldNames} when atom(Name) ->
- case OptOrMand of
- mandatory -> ok;
- _ ->
-% emit(["{",{curr,tmpBytes},",",{curr,tmpLen},
- emit(["{",{curr,tmpBytes},", _} = "])
-%% asn1ct_name:new(tmpBytes),
-%% asn1ct_name:new(tmpLen)
- end,
- emit({Fun,"(",{asis,Name},", ",Element,", [], ",
- {asis,RestFieldNames},"),",nl}),
- emit(IndDeep),
- case OptOrMand of
- mandatory ->
- emit({"{",{curr,encBytes},", ",{curr,encLen},"} = "}),
- emit({"?RT_BER:encode_open_type(",{curr,tmpBytes},
- ",",{asis,Tag},")"});
- _ ->
-% emit({"{",{next,tmpBytes},", _} = "}),
- emit({"{",{next,tmpBytes},", ",{curr,tmpLen},
- "} = "}),
- emit({"?RT_BER:encode_open_type(",{curr,tmpBytes},
- ",",{asis,Tag},"),",nl}),
- emit(IndDeep),
- emit({"{",{next,tmpBytes},", ",{curr,tmpLen},"}"})
- end;
- _ ->
- throw({asn1,{'internal error'}})
- end;
-% #type{constraint=[{tableconstraint_info,_}],
-% def={objectfield,PrimFieldName1,PFNList}} ->
- {{#'ObjectClassFieldType'{type={objectfield,PrimFieldName1,
- PFNList}},_},
- {componentrelation,_,_}} ->
- %% this is when the dotted list in the FieldName has more
- %% than one element
- {_LeadingAttrName,Fun} = EncObj,
- emit({"?RT_BER:encode_open_type(",Fun,"(",{asis,PrimFieldName1},
- ", ",Element,", ",{asis,PFNList},"),",{asis,Tag},")"});
- _ ->
- case WhatKind of
- {primitive,bif} ->
- EncType =
- case Type#type.def of
- #'ObjectClassFieldType'{
- type={fixedtypevaluefield,
- _,Btype}} ->
- Btype;
- _ ->
- Type
- end,
- asn1ct_gen_ber:gen_encode_prim(ber,EncType,{asis,Tag},
- Element);
- {notype,_} ->
- emit({"'enc_",InnerType,"'(",Element,", ",{asis,Tag},")"});
- 'ASN1_OPEN_TYPE' ->
- asn1ct_gen_ber:gen_encode_prim(ber,Type#type{def='ASN1_OPEN_TYPE'},{asis,Tag},Element);
- _ ->
- {EncFunName, _, _} =
- mkfuncname(TopType,Cname,WhatKind,enc),
- case {WhatKind,Type#type.tablecinf,EncObj} of
- {{constructed,bif},[{objfun,_}|_R],{_,Fun}} ->
- emit([EncFunName,"(",Element,", ",{asis,Tag},
- ", ",Fun,")"]);
- _ ->
- emit([EncFunName,"(",Element,", ",{asis,Tag},")"])
- end
- end
- end,
- case OptOrMand of
- mandatory -> true;
- _ ->
- emit({nl,indent(7),"end"})
- end.
-
-
-
-gen_optormand_case(mandatory,_,_,_,_,_,_, _) ->
- ok;
-gen_optormand_case('OPTIONAL',Erules,_,_,_,_,_,Element) ->
- emit({" case ",Element," of",nl}),
- emit({indent(9),"asn1_NOVALUE -> {",
- empty_lb(Erules),",0};",nl}),
- emit({indent(9),"_ ->",nl,indent(12)});
-gen_optormand_case({'DEFAULT',DefaultValue},Erules,TopType,Cname,Type,
- InnerType,WhatKind,Element) ->
- CurrMod = get(currmod),
- case catch lists:member(der,get(encoding_options)) of
- true ->
- emit(" case catch "),
- asn1ct_gen:gen_check_call(TopType,Cname,Type,InnerType,
- WhatKind,{asis,DefaultValue},
- Element),
- emit({" of",nl}),
- emit({indent(12),"true -> {[],0};",nl});
- _ ->
- emit({" case ",Element," of",nl}),
- emit({indent(9),"asn1_DEFAULT -> {",
- empty_lb(Erules),
- ",0};",nl}),
- case DefaultValue of
- #'Externalvaluereference'{module=CurrMod,
- value=V} ->
- emit({indent(9),"?",{asis,V}," -> {",
- empty_lb(Erules),",0};",nl});
- _ ->
- emit({indent(9),{asis,
- DefaultValue}," -> {",
- empty_lb(Erules),",0};",nl})
- end
- end,
- emit({indent(9),"_ ->",nl,indent(12)}).
-
-
-
-
-gen_dec_line_sof(_Erules,TopType,Cname,Type,ObjFun) ->
-
- Tag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}
- || X <- Type#type.tag],
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- WhatKind = asn1ct_gen:type(InnerType),
- case WhatKind of
- {primitive,bif} ->
- asn1ct_name:delete(len),
-
- asn1ct_name:new(len),
- emit(["fun(FBytes,_,_)->",nl]),
- EncType = case Type#type.def of
- #'ObjectClassFieldType'{
- type={fixedtypevaluefield,
- _,Btype}} ->
- Btype;
- _ ->
- Type
- end,
- asn1ct_gen_ber:gen_dec_prim(ber,EncType,"FBytes",Tag,
- [],no_length,?PRIMITIVE,
- mandatory),
- emit([nl,"end, []"]);
- _ ->
- case ObjFun of
- [] ->
- {DecFunName, _, _} =
- mkfunname(TopType,Cname,WhatKind,dec,3),
- emit([DecFunName,", ",{asis,Tag}]);
- _ ->
- {DecFunName, _, _} =
- mkfunname(TopType,Cname,WhatKind,dec,4),
- emit([DecFunName,", ",{asis,Tag},", ObjFun"])
- end
- end.
-
-
-gen_dec_line(Erules,TopType,Cname,CTags,Type,OptOrMand,DecObjInf) ->
- BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
- Tag = [X#tag{class=asn1ct_gen_ber:decode_class(X#tag.class)}
- || X <- Type#type.tag],
- InnerType =
- case Type#type.def of
- #'ObjectClassFieldType'{type=OCFTType} ->
- OCFTType;
- _ ->
- asn1ct_gen:get_inner(Type#type.def)
- end,
- PostpDec =
- case OptOrMand of
- mandatory ->
- gen_dec_call(InnerType,Erules,TopType,Cname,Type,
- BytesVar,Tag,mandatory,", mandatory, ",
- DecObjInf,OptOrMand);
- _ -> %optional or default
- case {CTags,Erules} of
- {[CTag],ber_bin} ->
- emit(["case ",{curr,bytes}," of",nl]),
- emit([match_tag(Erules,CTag)," ->",nl]),
- PostponedDec =
- gen_dec_call(InnerType,Erules,TopType,Cname,Type,
- BytesVar,Tag,mandatory,
- ", opt_or_default, ",DecObjInf,
- OptOrMand),
- emit([";",nl]),
- emit(["_ ->",nl]),
- case OptOrMand of
- {'DEFAULT', Def} ->
- emit(["{",{asis,Def},",",
- BytesVar,", 0 }",nl]);
- 'OPTIONAL' ->
- emit(["{ asn1_NOVALUE, ",
- BytesVar,", 0 }",nl])
- end,
- emit("end"),
- PostponedDec;
- _ ->
- emit("case (catch "),
- PostponedDec =
- gen_dec_call(InnerType,Erules,TopType,Cname,Type,
- BytesVar,Tag,OptOrMand,
- ", opt_or_default, ",DecObjInf,
- OptOrMand),
- emit([") of",nl]),
- case OptOrMand of
- {'DEFAULT', Def} ->
- emit(["{'EXIT',{error,{asn1,{no_optional_tag,_}}}}",
- " -> {",{asis,Def},",",
- BytesVar,", 0 };",nl]);
- 'OPTIONAL' ->
- emit(["{'EXIT',{error,{asn1,{no_optional_tag,_}}}}",
- " -> { asn1_NOVALUE, ",
- BytesVar,", 0 };",nl])
- end,
- asn1ct_name:new(casetmp),
- emit([{curr,casetmp},"-> ",{curr,casetmp},nl,"end"]),
- PostponedDec
- end
- end,
- case DecObjInf of
- {Cname,ObjSet} -> % this must be the component were an object is
- %% choosen from the object set according to the table
- %% constraint.
- {[{ObjSet,Cname,asn1ct_gen:mk_var(asn1ct_name:curr(term))}],
- PostpDec};
- _ -> {[],PostpDec}
- end.
-
-
-gen_dec_call({typefield,_},Erules,_,_,Type,_,Tag,_,_,false,_) ->
- %% this in case of a choice with typefield components
- asn1ct_name:new(reason),
- {FirstPFName,RestPFName} =
-% asn1ct_gen:get_constraint(Type#type.constraint,
-% tableconstraint_info),
- (Type#type.def)#'ObjectClassFieldType'.fieldname,
- emit([nl,indent(6),"begin",nl]),
- emit([indent(9),"{OpenDec,TmpRest,TmpRbCho} =",nl,indent(12),
- "?RT_BER:decode_open_type(",Erules,",",{curr,bytes},",",
- {asis,Tag},"),",nl]),
- emit([indent(9),"case (catch ObjFun(",{asis,FirstPFName},
- ", OpenDec, [], ",{asis,RestPFName},
- ")) of", nl]),%% ??? What about Tag
- emit([indent(12),"{'EXIT',",{curr,reason},"} ->",nl]),
-%% emit({indent(15),"throw({runtime_error,{'Type not ",
-%% "compatible with tableconstraint', OpenDec}});",nl}),
- emit([indent(15),"exit({'Type not ",
- "compatible with table constraint', ",{curr,reason},"});",nl]),
- emit([indent(12),"{TmpDec,_ ,_} ->",nl]),
- emit([indent(15),"{TmpDec, TmpRest, TmpRbCho}",nl]),
- emit([indent(9),"end",nl,indent(6),"end",nl]),
- [];
-gen_dec_call({typefield,_},_Erules,_,Cname,Type,_BytesVar,Tag,_,_,
- _DecObjInf,OptOrMandComp) ->
- emit(["?RT_BER:decode_open_type(",{curr,bytes},",",{asis,Tag},")"]),
- RefedFieldName =
- (Type#type.def)#'ObjectClassFieldType'.fieldname,
-% asn1ct_gen:get_constraint(Type#type.constraint,
-% tableconstraint_info),
- [{Cname,RefedFieldName,
- asn1ct_gen:mk_var(asn1ct_name:curr(term)),
-% asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),[],OptOrMandComp}];
- asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
-gen_dec_call({objectfield,PrimFieldName,PFNList},_Erules,_,Cname,_,_,Tag,_,_,_,
- OptOrMandComp) ->
- emit(["?RT_BER:decode_open_type(",{curr,bytes},",",{asis,Tag},")"]),
- [{Cname,{PrimFieldName,PFNList},
- asn1ct_gen:mk_var(asn1ct_name:curr(term)),
-% asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),[],OptOrMandComp}];
- asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
-gen_dec_call(InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,PrimOptOrMand,
- OptOrMand,DecObjInf,_) ->
- WhatKind = asn1ct_gen:type(InnerType),
- gen_dec_call1(WhatKind,InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,
- PrimOptOrMand,OptOrMand),
- case DecObjInf of
- {Cname,{_,OSet,UniqueFName,ValIndex}} ->
- Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
- ValueMatch = value_match(ValIndex,Term),
- emit({",",nl,"ObjFun = 'getdec_",OSet,"'(",
-% {asis,UniqueFName},", ",{curr,term},")"});
- {asis,UniqueFName},", ",ValueMatch,")"});
- _ ->
- ok
- end,
- [].
-gen_dec_call1({primitive,bif},InnerType,Erules,_,_,Type,BytesVar,
- Tag,OptOrMand,_) ->
- case InnerType of
- {fixedtypevaluefield,_,Btype} ->
- asn1ct_gen_ber:gen_dec_prim(Erules,Btype,BytesVar,Tag,[],no_length,
- ?PRIMITIVE,OptOrMand);
- _ ->
- asn1ct_gen_ber:gen_dec_prim(Erules,Type,BytesVar,Tag,[],no_length,
- ?PRIMITIVE,OptOrMand)
- end;
-gen_dec_call1('ASN1_OPEN_TYPE',_InnerType,Erules,_,_,Type,BytesVar,
- Tag,OptOrMand,_) ->
- asn1ct_gen_ber:gen_dec_prim(Erules,Type#type{def='ASN1_OPEN_TYPE'},
- BytesVar,Tag,[],no_length,
- ?PRIMITIVE,OptOrMand);
-gen_dec_call1(WhatKind,_,_Erules,TopType,Cname,Type,_,Tag,_,OptOrMand) ->
- {DecFunName,_,_} =
- mkfuncname(TopType,Cname,WhatKind,dec),
- case {WhatKind,Type#type.tablecinf} of
- {{constructed,bif},[{objfun,_}|_R]} ->
- emit({DecFunName,"(",{curr,bytes},OptOrMand,{asis,Tag},", ObjFun)"});
- _ ->
- emit({DecFunName,"(",{curr,bytes},OptOrMand,{asis,Tag},")"})
- end.
-
-
-%%------------------------------------------------------
-%% General and special help functions (not exported)
-%%------------------------------------------------------
-
-
-indent(N) ->
- lists:duplicate(N,32). % 32 = space
-
-
-mkvlist([H,T1|T], Sep) -> % Sep is a string e.g ", " or "+ "
- emit([{var,H},Sep]),
- mkvlist([T1|T], Sep);
-mkvlist([H|T], Sep) ->
- emit([{var,H}]),
- mkvlist(T, Sep);
-mkvlist([], _) ->
- true.
-
-mkvlist(L) ->
- mkvlist(L,", ").
-
-mkvplus(L) ->
- mkvlist(L," + ").
-
-extensible(CompList) when list(CompList) ->
- noext;
-extensible({RootList,ExtList}) ->
- {ext,length(RootList)+1,length(ExtList)}.
-
-
-print_attribute_comment(InnerType,Pos,Prop) ->
- CommentLine = "%%-------------------------------------------------",
- emit([nl,CommentLine]),
- case InnerType of
- {typereference,_,Name} ->
- emit([nl,"%% attribute number ",Pos," with type ",Name]);
- {'Externaltypereference',_,XModule,Name} ->
- emit([nl,"%% attribute number ",Pos," External ",XModule,":",Name]);
- _ ->
- emit([nl,"%% attribute number ",Pos," with type ",InnerType])
- end,
- case Prop of
- mandatory ->
- continue;
- {'DEFAULT', Def} ->
- emit([" DEFAULT = ",{asis,Def}]);
- 'OPTIONAL' ->
- emit([" OPTIONAL"])
- end,
- emit([nl,CommentLine,nl]).
-
-
-mkfuncname(TopType,Cname,WhatKind,DecOrEnc) ->
- CurrMod = get(currmod),
- case WhatKind of
- #'Externaltypereference'{module=CurrMod,type=EType} ->
- F = lists:concat(["'",DecOrEnc,"_",EType,"'"]),
- {F, "?MODULE", F};
- #'Externaltypereference'{module=Mod,type=EType} ->
- {lists:concat(["'",Mod,"':'",DecOrEnc,"_",EType,"'"]),Mod,
- lists:concat(["'",DecOrEnc,"_",EType,"'"])};
- {constructed,bif} ->
- F = lists:concat(["'",DecOrEnc,"_",asn1ct_gen:list2name([Cname|TopType]),"'"]),
- {F, "?MODULE", F}
- end.
-
-mkfunname(TopType,Cname,WhatKind,DecOrEnc,Arity) ->
- CurrMod = get(currmod),
- case WhatKind of
- #'Externaltypereference'{module=CurrMod,type=EType} ->
- F = lists:concat(["fun '",DecOrEnc,"_",EType,"'/",Arity]),
- {F, "?MODULE", F};
- #'Externaltypereference'{module=Mod,type=EType} ->
- {lists:concat(["{'",Mod,"','",DecOrEnc,"_",EType,"'}"]),Mod,
- lists:concat(["'",DecOrEnc,"_",EType,"'"])};
- {constructed,bif} ->
- F =
- lists:concat(["fun '",DecOrEnc,"_",
- asn1ct_gen:list2name([Cname|TopType]),"'/",
- Arity]),
- {F, "?MODULE", F}
- end.
-
-empty_lb(ber) ->
- "[]";
-empty_lb(ber_bin) ->
- "<<>>".
-
-rtmod(ber) ->
- list_to_atom(?RT_BER);
-rtmod(ber_bin) ->
- list_to_atom(?RT_BER_BIN).
-
-indefend_match(ber,used_var) ->
- "[0,0|R]";
-indefend_match(ber,unused_var) ->
- "[0,0|_R]";
-indefend_match(ber_bin,used_var) ->
- "<<0,0,R/binary>>";
-indefend_match(ber_bin,unused_var) ->
- "<<0,0,_R/binary>>".
-
-notice_value_match() ->
- Module = get(currmod),
- put(value_match,{true,Module}).
-
-value_match(Index,Value) when atom(Value) ->
- value_match(Index,atom_to_list(Value));
-value_match([],Value) ->
- Value;
-value_match([{VI,_Cname}|VIs],Value) ->
- value_match1(Value,VIs,lists:concat(["element(",VI,","]),1).
-value_match1(Value,[],Acc,Depth) ->
- Acc ++ Value ++ lists:concat(lists:duplicate(Depth,")"));
-value_match1(Value,[{VI,_Cname}|VIs],Acc,Depth) ->
- value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1).
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_constructed_ber_bin_v2.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_constructed_ber_bin_v2.erl
deleted file mode 100644
index 0684ffa084..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_constructed_ber_bin_v2.erl
+++ /dev/null
@@ -1,1357 +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: asn1ct_constructed_ber_bin_v2.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
-%%
--module(asn1ct_constructed_ber_bin_v2).
-
--export([gen_encode_sequence/3]).
--export([gen_decode_sequence/3]).
--export([gen_encode_set/3]).
--export([gen_decode_set/3]).
--export([gen_encode_sof/4]).
--export([gen_decode_sof/4]).
--export([gen_encode_choice/3]).
--export([gen_decode_choice/3]).
-
-
--include("asn1_records.hrl").
-
--import(asn1ct_gen, [emit/1,demit/1]).
--import(asn1ct_constructed_ber,[match_tag/2]).
-
--define(ASN1CT_GEN_BER,asn1ct_gen_ber_bin_v2).
-
-% the encoding of class of tag bits 8 and 7
--define(UNIVERSAL, 0).
--define(APPLICATION, 16#40).
--define(CONTEXT, 16#80).
--define(PRIVATE, 16#C0).
-
-% primitive or constructed encoding % bit 6
--define(PRIMITIVE, 0).
--define(CONSTRUCTED, 2#00100000).
-
-
-
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Encode/decode SEQUENCE (and SET)
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-gen_encode_sequence(Erules,Typename,D) when record(D,type) ->
- asn1ct_name:start(),
- asn1ct_name:new(term),
- asn1ct_name:new(bytes),
-
- %% if EXTERNAL type the input value must be transformed to
- %% ASN1 1990 format
- ValName =
- case Typename of
- ['EXTERNAL'] ->
- emit([indent(4),
- "NewVal = asn1rt_check:transform_to_EXTERNAL1990(Val),",
- nl]),
- "NewVal";
- _ ->
- "Val"
- end,
-
- {SeqOrSet,TableConsInfo,CompList} =
- case D#type.def of
- #'SEQUENCE'{tablecinf=TCI,components=CL} ->
- {'SEQUENCE',TCI,CL};
- #'SET'{tablecinf=TCI,components=CL} ->
- {'SET',TCI,CL}
- end,
- Ext = extensible(CompList),
- CompList1 = case CompList of
- {Rl,El} -> Rl ++ El;
- _ -> CompList
- end,
-
-%% don't match recordname for now, because of compatibility reasons
-%% emit(["{'",asn1ct_gen:list2rname(Typename),"'"]),
- emit(["{_"]),
- case length(CompList1) of
- 0 ->
- true;
- CompListLen ->
- emit([","]),
- mkcindexlist([Tc || Tc <- lists:seq(1,CompListLen)])
- end,
- emit(["} = ",ValName,",",nl]),
- EncObj =
- case TableConsInfo of
- #simpletableattributes{usedclassfield=Used,
- uniqueclassfield=Unique} when Used /= Unique ->
- false;
- %% ObjectSet, name of the object set in constraints
- %%
- #simpletableattributes{objectsetname=ObjectSet,
- c_name=AttrN,
- c_index=N,
- usedclassfield=UniqueFieldName,
- uniqueclassfield=UniqueFieldName,
- valueindex=ValueIndex} -> %% N is index of attribute that determines constraint
- OSDef =
- case ObjectSet of
- {Module,OSName} ->
- asn1_db:dbget(Module,OSName);
- OSName ->
- asn1_db:dbget(get(currmod),OSName)
- end,
-% io:format("currmod: ~p~nOSName: ~p~nAttrN: ~p~nN: ~p~nUniqueFieldName: ~p~n",
-% [get(currmod),OSName,AttrN,N,UniqueFieldName]),
- case (OSDef#typedef.typespec)#'ObjectSet'.gen of
- true ->
- ObjectEncode =
- asn1ct_gen:un_hyphen_var(lists:concat(['Obj',
- AttrN])),
- emit([ObjectEncode," = ",nl]),
- emit([" 'getenc_",ObjectSet,"'(",{asis,UniqueFieldName},
- ", ",nl]),
- ValueMatch = value_match(ValueIndex,
- lists:concat(["Cindex",N])),
- emit([indent(35),ValueMatch,"),",nl]),
- {AttrN,ObjectEncode};
- _ ->
- false
- end;
- _ ->
- case D#type.tablecinf of
- [{objfun,_}|_] ->
- %% when the simpletableattributes was at an outer
- %% level and the objfun has been passed through the
- %% function call
- {"got objfun through args","ObjFun"};
- _ ->
- false
- end
- end,
-
- gen_enc_sequence_call(Erules,Typename,CompList1,1,Ext,EncObj),
-
- emit([nl," BytesSoFar = "]),
- case SeqOrSet of
- 'SET' when (D#type.def)#'SET'.sorted == dynamic ->
- emit("?RT_BER:dynamicsort_SET_components(["),
- mkvlist(asn1ct_name:all(encBytes)),
- emit(["]),",nl]);
- _ ->
- emit("["),
- mkvlist(asn1ct_name:all(encBytes)),
- emit(["],",nl])
- end,
- emit("LenSoFar = "),
- case asn1ct_name:all(encLen) of
- [] -> emit("0");
- AllLengths ->
- mkvplus(AllLengths)
- end,
- emit([",",nl]),
- emit(["?RT_BER:encode_tags(TagIn, BytesSoFar, LenSoFar)."
- ,nl]).
-
-gen_decode_sequence(Erules,Typename,D) when record(D,type) ->
- asn1ct_name:start(),
- asn1ct_name:new(tag),
- #'SEQUENCE'{tablecinf=TableConsInfo,components=CList} = D#type.def,
- Ext = extensible(CList),
- CompList = case CList of
- {Rl,El} -> Rl ++ El;
- _ -> CList
- end,
-
- emit([" %%-------------------------------------------------",nl]),
- emit([" %% decode tag and length ",nl]),
- emit([" %%-------------------------------------------------",nl]),
-
- asn1ct_name:new(tlv),
- case CompList of
- EmptyCL when EmptyCL == [];EmptyCL == {[],[]}-> % empty sequence
- true;
- _ ->
- emit([{curr,tlv}," = "])
- end,
- emit(["?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
- asn1ct_name:new(tlv),
- asn1ct_name:new(v),
-
- {DecObjInf,UniqueFName,ValueIndex} =
- case TableConsInfo of
- #simpletableattributes{objectsetname=ObjectSet,
- c_name=AttrN,
- usedclassfield=UniqueFieldName,
- uniqueclassfield=UniqueFieldName,
- valueindex=ValIndex} ->
-% {ObjectSet,AttrN,_N,UniqueFieldName} ->%% N is index of attribute that determines constraint
- F = fun(#'ComponentType'{typespec=CT})->
- case {CT#type.constraint,CT#type.tablecinf} of
- {[],[{objfun,_}|_]} -> true;
- _ -> false
- end
- end,
- case lists:any(F,CompList) of
- true -> % when component relation constraint establish
- %% relation from a component to another components
- %% subtype component
- {{AttrN,{deep,ObjectSet,UniqueFieldName,ValIndex}},
- UniqueFieldName,ValIndex};
- false ->
- {{AttrN,ObjectSet},UniqueFieldName,ValIndex}
- end;
- _ ->
-% case D#type.tablecinf of
-% [{objfun,_}|_] ->
-% {{"got objfun through args","ObjFun"},false,false};
-% _ ->
- {false,false,false}
-% end
- end,
- case gen_dec_sequence_call(Erules,Typename,CompList,Ext,DecObjInf) of
- no_terms -> % an empty sequence
- emit([nl,nl]),
- demit(["Result = "]), %dbg
- %% return value as record
- asn1ct_name:new(rb),
- emit([" {'",asn1ct_gen:list2rname(Typename),"'}.",nl,nl]);
- {LeadingAttrTerm,PostponedDecArgs} ->
- emit([com,nl,nl]),
- case {LeadingAttrTerm,PostponedDecArgs} of
- {[],[]} ->
- ok;
- {_,[]} ->
- ok;
- {[{ObjSet,LeadingAttr,Term}],PostponedDecArgs} ->
- DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])),
- ValueMatch = value_match(ValueIndex,Term),
- emit([DecObj," =",nl," 'getdec_",ObjSet,"'(",
- {asis,UniqueFName},", ",ValueMatch,"),",nl]),
- gen_dec_postponed_decs(DecObj,PostponedDecArgs)
- end,
- demit(["Result = "]), %dbg
- %% return value as record
- case Ext of
- {ext,_,_} ->
- emit(["case ",{prev,tlv}," of [] -> true; _ -> true end, % ... extra fields skipped",nl]);
- noext ->
- emit(["case ",{prev,tlv}," of",nl,
- "[] -> true;",
- "_ -> exit({error,{asn1, {unexpected,",{prev,tlv},
- "}}}) % extra fields not allowed",nl,
- "end,",nl])
- end,
- asn1ct_name:new(rb),
- case Typename of
- ['EXTERNAL'] ->
- emit([" OldFormat={'",asn1ct_gen:list2rname(Typename),
- "', "]),
- mkvlist(asn1ct_name:all(term)),
- emit(["},",nl]),
- emit([" asn1rt_check:transform_to_EXTERNAL1994",
- "(OldFormat).",nl]);
- _ ->
- emit([" {'",asn1ct_gen:list2rname(Typename),"', "]),
- mkvlist(asn1ct_name:all(term)),
- emit(["}.",nl,nl])
- end
- end.
-
-gen_dec_postponed_decs(_,[]) ->
- emit(nl);
-gen_dec_postponed_decs(DecObj,[{_Cname,{FirstPFN,PFNList},Term,
- TmpTerm,_Tag,OptOrMand}|Rest]) ->
-
- asn1ct_name:new(tmpterm),
- asn1ct_name:new(reason),
- asn1ct_name:new(tmptlv),
-
- emit([Term," = ",nl]),
- N = case OptOrMand of
- mandatory -> 0;
- 'OPTIONAL' ->
- emit_opt_or_mand_check(asn1_NOVALUE,TmpTerm),
- 6;
- {'DEFAULT',Val} ->
- emit_opt_or_mand_check(Val,TmpTerm),
- 6
- end,
- emit([indent(N+3),"case (catch ",DecObj,"(",{asis,FirstPFN},
- ", ",TmpTerm,", ",{asis,PFNList},")) of",nl]),
- emit([indent(N+6),"{'EXIT', ",{curr,reason},"} ->",nl]),
- emit([indent(N+9),"exit({'Type not compatible with table constraint',",
- {curr,reason},"});",nl]),
- emit([indent(N+6),{curr,tmpterm}," ->",nl]),
- emit([indent(N+9),{curr,tmpterm},nl]),
-
- case OptOrMand of
- mandatory -> emit([indent(N+3),"end,",nl]);
- _ ->
- emit([indent(N+3),"end",nl,
- indent(3),"end,",nl])
- end,
- gen_dec_postponed_decs(DecObj,Rest).
-
-emit_opt_or_mand_check(Value,TmpTerm) ->
- emit([indent(3),"case ",TmpTerm," of",nl,
- indent(6),{asis,Value}," ->",{asis,Value},";",nl,
- indent(6),"_ ->",nl]).
-
-%%============================================================================
-%% Encode/decode SET
-%%
-%%============================================================================
-
-gen_encode_set(Erules,Typename,D) when record(D,type) ->
- gen_encode_sequence(Erules,Typename,D).
-
-gen_decode_set(Erules,Typename,D) when record(D,type) ->
- asn1ct_name:start(),
- asn1ct_name:new(term),
- asn1ct_name:new(tag),
- #'SET'{tablecinf=TableConsInfo,components=TCompList} = D#type.def,
- Ext = extensible(TCompList),
- CompList = case TCompList of
- {Rl,El} -> Rl ++ El;
- _ -> TCompList
- end,
-
- asn1ct_name:clear(),
- asn1ct_name:new(tlv),
- case CompList of
- EmptyCL when EmptyCL == [];EmptyCL == {[],[]}-> % empty sequence
- true;
- _ ->
- emit([{curr,tlv}," = "])
- end,
- emit(["?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
- asn1ct_name:new(v),
-
-
- {DecObjInf,UniqueFName} =
- case TableConsInfo of
- {ObjectSet,AttrN,_N,UniqueFieldName} ->%% N is index of attribute that determines constraint
- F = fun(#'ComponentType'{typespec=CT})->
- case {CT#type.constraint,CT#type.tablecinf} of
- {[],[{objfun,_}|_]} -> true;
- _ -> false
- end
- end,
- case lists:any(F,CompList) of
- true -> % when component relation constraint establish
- %% relation from a component to another components
- %% subtype component
- {{AttrN,{deep,ObjectSet,UniqueFieldName}},
- UniqueFieldName};
- false ->
- {{AttrN,ObjectSet},UniqueFieldName}
- end;
- _ ->
- {false,false}
- end,
-
- case CompList of
- [] -> % empty set
- true;
- _ ->
- emit(["SetFun = fun(FunTlv) ->", nl]),
- emit(["case FunTlv of ",nl]),
- NextNum = gen_dec_set_cases(Erules,Typename,CompList,1),
- emit([indent(6), {curr,else}," -> ",nl,
- indent(9),"{",NextNum,", ",{curr,else},"}",nl]),
- emit([indent(3),"end",nl]),
- emit([indent(3),"end,",nl]),
-
- emit(["PositionList = [SetFun(TempTlv)|| TempTlv <- ",{curr,tlv},"],",nl]),
- asn1ct_name:new(tlv),
- emit([{curr,tlv}," = [Stlv || {_,Stlv} <- lists:sort(PositionList)],",nl]),
- asn1ct_name:new(tlv)
-
- end,
- case gen_dec_sequence_call(Erules,Typename,CompList,Ext,DecObjInf) of
- no_terms -> % an empty sequence
- emit([nl,nl]),
- demit(["Result = "]), %dbg
- %% return value as record
- emit([" {'",asn1ct_gen:list2rname(Typename),"'}.",nl]);
- {LeadingAttrTerm,PostponedDecArgs} ->
- emit([com,nl,nl]),
- case {LeadingAttrTerm,PostponedDecArgs} of
- {[],[]} ->
- ok;
- {_,[]} ->
- ok;
- {[{ObjSet,LeadingAttr,Term}],PostponedDecArgs} ->
- DecObj = lists:concat(['DecObj',LeadingAttr,Term]),
- emit([DecObj," =",nl," 'getdec_",ObjSet,"'(",
- {asis,UniqueFName},", ",Term,"),",nl]),
- gen_dec_postponed_decs(DecObj,PostponedDecArgs)
- end,
- demit(["Result = "]), %dbg
- %% return value as record
- case Ext of
- {ext,_,_} ->
- emit(["case ",{prev,tlv}," of [] -> true; _ -> true end, % ... extra fields skipped",nl]);
- noext ->
- emit(["case ",{prev,tlv}," of",nl,
- "[] -> true;",
- "_ -> exit({error,{asn1, {unexpected,",{prev,tlv},
- "}}}) % extra fields not allowed",nl,
- "end,",nl])
- end,
- emit([" {'",asn1ct_gen:list2rname(Typename),"', "]),
- mkvlist(asn1ct_name:all(term)),
- emit(["}.",nl])
- end.
-
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Encode/decode SEQUENCE OF and SET OF
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-gen_encode_sof(Erules,Typename,_InnerTypename,D) when record(D,type) ->
- asn1ct_name:start(),
- {SeqOrSetOf, Cont} = D#type.def,
-
- Objfun = case D#type.tablecinf of
- [{objfun,_}|_R] ->
- ", ObjFun";
- _ ->
- ""
- end,
-
- emit([" {EncBytes,EncLen} = 'enc_",asn1ct_gen:list2name(Typename),
- "_components'(Val",Objfun,",[],0),",nl]),
-
- emit([" ?RT_BER:encode_tags(TagIn, EncBytes, EncLen).",nl,nl]),
-
- gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont).
-
-
-gen_decode_sof(Erules,TypeName,_InnerTypeName,D) when record(D,type) ->
- asn1ct_name:start(),
- {SeqOrSetOf, _TypeTag, Cont} =
- case D#type.def of
- {'SET OF',_Cont} -> {'SET OF','SET',_Cont};
- {'SEQUENCE OF',_Cont} -> {'SEQUENCE OF','SEQUENCE',_Cont}
- end,
- TypeNameSuffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,Cont#type.def),
-
- emit([" %%-------------------------------------------------",nl]),
- emit([" %% decode tag and length ",nl]),
- emit([" %%-------------------------------------------------",nl]),
-
- asn1ct_name:new(tlv),
- emit([{curr,tlv},
- " = ?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
- asn1ct_name:new(v),
-
- emit(["["]),
-
- InnerType = asn1ct_gen:get_inner(Cont#type.def),
- ContName = case asn1ct_gen:type(InnerType) of
- Atom when atom(Atom) -> Atom;
- _ -> TypeNameSuffix
- end,
-%% fix me
- ObjFun =
- case D#type.tablecinf of
- [{objfun,_}|_R] ->
- ", ObjFun";
- _ ->
- []
- end,
- gen_dec_line(Erules,TypeName,ContName,[],Cont,mandatory,ObjFun),
- %% gen_dec_line_sof(Erules,Typename,ContName,Cont,ObjFun),
- emit([" || ",{curr,v}," <- ",{curr,tlv},"].",nl,nl,nl]).
-
-
-gen_encode_sof_components(Erules,Typename,SeqOrSetOf,Cont)
- when record(Cont,type)->
-
- {Objfun,Objfun_novar,EncObj} =
- case Cont#type.tablecinf of
- [{objfun,_}|_R] ->
- {", ObjFun",", _",{no_attr,"ObjFun"}};
- _ ->
- {"","",false}
- end,
- emit(["'enc_",asn1ct_gen:list2name(Typename),
- "_components'([]",Objfun_novar,", AccBytes, AccLen) -> ",nl]),
-
- case catch lists:member(der,get(encoding_options)) of
- true ->
- emit([indent(3),
- "{?RT_BER:dynamicsort_SETOF(AccBytes),AccLen};",nl,nl]);
- _ ->
- emit([indent(3),"{lists:reverse(AccBytes),AccLen};",nl,nl])
- end,
- emit(["'enc_",asn1ct_gen:list2name(Typename),
- "_components'([H|T]",Objfun,",AccBytes, AccLen) ->",nl]),
- TypeNameSuffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,Cont#type.def),
- gen_enc_line(Erules,Typename,TypeNameSuffix,Cont,"H",3,
- mandatory,"{EncBytes,EncLen} = ",EncObj),
- emit([",",nl]),
- emit([indent(3),"'enc_",asn1ct_gen:list2name(Typename),
- "_components'(T",Objfun,","]),
- emit(["[EncBytes|AccBytes], AccLen + EncLen).",nl,nl]).
-
-%%============================================================================
-%% Encode/decode CHOICE
-%%
-%%============================================================================
-
-gen_encode_choice(Erules,Typename,D) when record(D,type) ->
- ChoiceTag = D#type.tag,
- {'CHOICE',CompList} = D#type.def,
- Ext = extensible(CompList),
- CompList1 = case CompList of
- {Rl,El} -> Rl ++ El;
- _ -> CompList
- end,
- gen_enc_choice(Erules,Typename,ChoiceTag,CompList1,Ext),
- emit([nl,nl]).
-
-gen_decode_choice(Erules,Typename,D) when record(D,type) ->
- asn1ct_name:start(),
- asn1ct_name:new(bytes),
- ChoiceTag = D#type.tag,
- {'CHOICE',CompList} = D#type.def,
- Ext = extensible(CompList),
- CompList1 = case CompList of
- {Rl,El} -> Rl ++ El;
- _ -> CompList
- end,
- gen_dec_choice(Erules,Typename,ChoiceTag,CompList1,Ext),
- emit([".",nl]).
-
-
-%%============================================================================
-%% Encode SEQUENCE
-%%
-%%============================================================================
-
-gen_enc_sequence_call(Erules,TopType,[#'ComponentType'{name=Cname,typespec=Type,prop=Prop}|Rest],Pos,Ext,EncObj) ->
- asn1ct_name:new(encBytes),
- asn1ct_name:new(encLen),
- Element =
- case TopType of
- ['EXTERNAL'] ->
- io_lib:format("Cindex~w",[Pos]);
- _ ->
- io_lib:format("Cindex~w",[Pos])
- end,
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- print_attribute_comment(InnerType,Pos,Cname,Prop),
- gen_enc_line(Erules,TopType,Cname,Type,Element,3,Prop,EncObj),
- emit([com,nl]),
- gen_enc_sequence_call(Erules,TopType,Rest,Pos+1,Ext,EncObj);
-
-gen_enc_sequence_call(_Erules,_TopType,[],_Num,_,_) ->
- true.
-
-%%============================================================================
-%% Decode SEQUENCE
-%%
-%%============================================================================
-
-gen_dec_sequence_call(Erules,TopType,CompList,Ext,DecObjInf) ->
- gen_dec_sequence_call1(Erules,TopType, CompList, 1, Ext,DecObjInf,[],[]).
-
-
-gen_dec_sequence_call1(Erules,TopType,[#'ComponentType'{name=Cname,typespec=Type,prop=Prop,tags=Tags}|Rest],Num,Ext,DecObjInf,LeadingAttrAcc,ArgsAcc) ->
- {LA,PostponedDec} =
- gen_dec_component(Erules,TopType,Cname,Tags,Type,Num,Prop,
- Ext,DecObjInf),
- case Rest of
- [] ->
- {LA ++ LeadingAttrAcc,PostponedDec ++ ArgsAcc};
- _ ->
- emit([com,nl]),
- asn1ct_name:new(bytes),
- gen_dec_sequence_call1(Erules,TopType,Rest,Num+1,Ext,DecObjInf,
- LA++LeadingAttrAcc,PostponedDec++ArgsAcc)
- end;
-
-gen_dec_sequence_call1(_Erules,_TopType,[],1,_,_,_,_) ->
- no_terms.
-
-
-%%----------------------------
-%%SEQUENCE mandatory
-%%----------------------------
-
-gen_dec_component(Erules,TopType,Cname,CTags,Type,Pos,Prop,Ext,DecObjInf) ->
- InnerType =
- case Type#type.def of
- #'ObjectClassFieldType'{type=OCFTType} -> OCFTType;
- _ -> asn1ct_gen:get_inner(Type#type.def)
- end,
-% case asn1ct_gen:get_constraint(Type#type.constraint,
-% tableconstraint_info) of
-% no ->
-% asn1ct_gen:get_inner(Type#type.def);
-% _ ->
-% Type#type.def
-% end,
- Prop1 = case {Prop,Ext} of
- {mandatory,{ext,Epos,_}} when Pos >= Epos ->
- 'OPTIONAL';
- _ ->
- Prop
- end,
- print_attribute_comment(InnerType,Pos,Cname,Prop1),
- asn1ct_name:new(term),
- emit_term_tlv(Prop1,InnerType,DecObjInf),
- asn1ct_name:new(rb),
- PostponedDec =
- gen_dec_line(Erules,TopType,Cname,CTags,Type,Prop1,DecObjInf),
- asn1ct_name:new(v),
- asn1ct_name:new(tlv),
- asn1ct_name:new(form),
- PostponedDec.
-
-
-emit_term_tlv({'DEFAULT',_},InnerType,DecObjInf) ->
- emit_term_tlv(opt_or_def,InnerType,DecObjInf);
-emit_term_tlv('OPTIONAL',InnerType,DecObjInf) ->
- emit_term_tlv(opt_or_def,InnerType,DecObjInf);
-emit_term_tlv(Prop,{typefield,_},DecObjInf) ->
- emit_term_tlv(Prop,type_or_object_field,DecObjInf);
-emit_term_tlv(Prop,{objectfield,_,_},DecObjInf) ->
- emit_term_tlv(Prop,type_or_object_field,DecObjInf);
-emit_term_tlv(opt_or_def,type_or_object_field,_) ->
- asn1ct_name:new(tmpterm),
- emit(["{",{curr,tmpterm},",",{curr,tlv},"} = "]);
-emit_term_tlv(opt_or_def,_,_) ->
- emit(["{",{curr,term},",",{curr,tlv},"} = "]);
-emit_term_tlv(_,type_or_object_field,false) ->
- emit(["[",{curr,v},"|",{curr,tlv},"] = ",{prev,tlv},", ",nl,
- {curr,term}," = "]);
-emit_term_tlv(_,type_or_object_field,_) ->
- asn1ct_name:new(tmpterm),
- emit(["[",{curr,v},"|",{curr,tlv},"] = ",{prev,tlv},", ",nl]),
- emit([nl," ",{curr,tmpterm}," = "]);
-emit_term_tlv(mandatory,_,_) ->
- emit(["[",{curr,v},"|",{curr,tlv},"] = ",{prev,tlv},", ",nl,
- {curr,term}," = "]).
-
-
-gen_dec_set_cases(_Erules,_TopType,[],Pos) ->
- Pos;
-gen_dec_set_cases(Erules,TopType,[Comp|RestComps],Pos) ->
- Name = Comp#'ComponentType'.name,
- Type = Comp#'ComponentType'.typespec,
- CTags = Comp#'ComponentType'.tags,
-
- emit([indent(6),"%",Name,nl]),
- Tags = case Type#type.tag of
- [] -> % this is a choice without explicit tag
- [(?ASN1CT_GEN_BER:decode_class(T1class) bsl 10) + T1number||
- {T1class,T1number} <- CTags];
- [FirstTag|_] ->
- [(?ASN1CT_GEN_BER:decode_class(FirstTag#tag.class) bsl 10) + FirstTag#tag.number]
- end,
-% emit([indent(6),"%Tags: ",Tags,nl]),
-% emit([indent(6),"%Type#type.tag: ",Type#type.tag,nl]),
- CaseFun = fun(TagList=[H|T],Fun,N) ->
- Semicolon = case TagList of
- [_Tag1,_|_] -> [";",nl];
- _ -> ""
- end,
- emit(["TTlv = {",H,",_} ->",nl]),
- emit([indent(4),"{",Pos,", TTlv}",Semicolon]),
- Fun(T,Fun,N+1);
- ([],_,0) ->
- true;
- ([],_,_) ->
- emit([";",nl])
- end,
- CaseFun(Tags,CaseFun,0),
-%% emit([";",nl]),
- gen_dec_set_cases(Erules,TopType,RestComps,Pos+1).
-
-
-
-%%---------------------------------------------
-%% Encode CHOICE
-%%---------------------------------------------
-%% for BER we currently do care (a little) if the choice has an EXTENSIONMARKER
-
-
-gen_enc_choice(Erules,TopType,Tag,CompList,_Ext) ->
- gen_enc_choice1(Erules,TopType,Tag,CompList,_Ext).
-
-gen_enc_choice1(Erules,TopType,_Tag,CompList,_Ext) ->
- asn1ct_name:clear(),
- emit([" {EncBytes,EncLen} = case element(1,Val) of",nl]),
- gen_enc_choice2(Erules,TopType,CompList),
- emit([nl," end,",nl,nl]),
-
- emit(["?RT_BER:encode_tags(TagIn, EncBytes, EncLen).",nl]).
-
-
-gen_enc_choice2(Erules,TopType,[H1|T]) when record(H1,'ComponentType') ->
- Cname = H1#'ComponentType'.name,
- Type = H1#'ComponentType'.typespec,
- emit([" ",{asis,Cname}," ->",nl]),
- {Encobj,Assign} =
- case {Type#type.def,asn1ct_gen:get_constraint(Type#type.constraint,
- componentrelation)} of
- {#'ObjectClassFieldType'{},{componentrelation,_,_}} ->
- asn1ct_name:new(tmpBytes),
- asn1ct_name:new(encBytes),
- asn1ct_name:new(encLen),
- Emit = ["{",{curr,tmpBytes},", _} = "],
- {{no_attr,"ObjFun"},Emit};
- _ ->
- {false,[]}
- end,
-% case asn1ct_gen:get_constraint(Type#type.constraint,
-% tableconstraint_info) of
-% no ->
-% {false,[]};
-% _ ->
-% asn1ct_name:new(tmpBytes),
-% asn1ct_name:new(encBytes),
-% asn1ct_name:new(encLen),
-% Emit = ["{",{curr,tmpBytes},", _} = "],
-% {{no_attr,"ObjFun"},Emit}
-% end,
- gen_enc_line(Erules,TopType,Cname,Type,"element(2,Val)",9,
- mandatory,Assign,Encobj),
- case Encobj of
- false -> ok;
- _ ->
- emit([",",nl,indent(9),"{",{curr,encBytes},", ",
- {curr,encLen},"}"])
- end,
- emit([";",nl]),
- case T of
- [] ->
- emit([indent(6), "Else -> ",nl,
- indent(9),"exit({error,{asn1,{invalid_choice_type,Else}}})"]);
- _ ->
- true
- end,
- gen_enc_choice2(Erules,TopType,T);
-
-gen_enc_choice2(_Erules,_TopType,[]) ->
- true.
-
-
-
-
-%%--------------------------------------------
-%% Decode CHOICE
-%%--------------------------------------------
-
-gen_dec_choice(Erules,TopType, _ChTag, CompList, Ext) ->
- asn1ct_name:clear(),
- asn1ct_name:new(tlv),
- emit([{curr,tlv},
- " = ?RT_BER:match_tags(",{prev,tlv},",TagIn), ",nl]),
- asn1ct_name:new(tlv),
- asn1ct_name:new(v),
- emit(["case (case ",{prev,tlv},
- " of [Ctemp",{prev,tlv},"] -> Ctemp",{prev,tlv},
- "; _ -> ",{prev,tlv}," end)"," of",nl]),
- asn1ct_name:new(tagList),
- asn1ct_name:new(choTags),
- asn1ct_name:new(res),
- gen_dec_choice_cases(Erules,TopType,CompList),
- emit([indent(6), {curr,else}," -> ",nl]),
- case Ext of
- noext ->
- emit([indent(9),"exit({error,{asn1,{invalid_choice_tag,",
- {curr,else},"}}})",nl]);
- _ ->
- emit([indent(9),"{asn1_ExtAlt, ?RT_BER:encode(",{curr,else},")}",nl])
- end,
- emit([indent(3),"end",nl]),
- asn1ct_name:new(tag),
- asn1ct_name:new(else).
-
-
-gen_dec_choice_cases(_Erules,_TopType, []) ->
- ok;
-gen_dec_choice_cases(Erules,TopType, [H|T]) ->
- Cname = H#'ComponentType'.name,
- Type = H#'ComponentType'.typespec,
- Prop = H#'ComponentType'.prop,
- Tags = Type#type.tag,
- Fcases = fun([{T1class,T1number}|Tail],Fun) ->
- emit([indent(4),{curr,v}," = {",
- (?ASN1CT_GEN_BER:decode_class(T1class) bsl 10) +
- T1number,",_} -> ",nl]),
- emit([indent(8),"{",{asis,Cname},", "]),
- gen_dec_line(Erules,TopType,Cname,[],Type,Prop,false),
- emit(["};",nl,nl]),
- Fun(Tail,Fun);
- ([],_) ->
- ok
- end,
- emit([nl,"%% '",Cname,"'",nl]),
- case {Tags,asn1ct:get_gen_state_field(namelist)} of
- {[],_} -> % choice without explicit tags
- Fcases(H#'ComponentType'.tags,Fcases);
- {[FirstT|_RestT],[{Cname,undecoded}|Names]} ->
- DecTag=(?ASN1CT_GEN_BER:decode_class(FirstT#tag.class) bsl 10) +
- FirstT#tag.number,
- asn1ct:add_generated_refed_func({[Cname|TopType],undecoded,
- [DecTag],Type}),
- asn1ct:update_gen_state(namelist,Names),
- emit([indent(4),{curr,res}," = ",
- match_tag(ber_bin,{FirstT#tag.class,FirstT#tag.number}),
- " -> ",nl]),
- emit([indent(8),"{",{asis,Cname},", {'",
- asn1ct_gen:list2name([Cname|TopType]),"',",
- {curr,res},"}};",nl,nl]);
- {[FirstT|RestT],_} ->
- emit([indent(4),"{",
- (?ASN1CT_GEN_BER:decode_class(FirstT#tag.class) bsl 10) +
- FirstT#tag.number,", ",{curr,v},"} -> ",nl]),
- emit([indent(8),"{",{asis,Cname},", "]),
- gen_dec_line(Erules,TopType,Cname,[],Type#type{tag=RestT},Prop,false),
- emit(["};",nl,nl])
- end,
- gen_dec_choice_cases(Erules,TopType, T).
-
-
-
-%%---------------------------------------
-%% Generate the encode/decode code
-%%---------------------------------------
-
-gen_enc_line(Erules,TopType,Cname,
- Type=#type{constraint=[{componentrelation,_,_}],
- def=#'ObjectClassFieldType'{type={typefield,_}}},
- Element,Indent,OptOrMand=mandatory,EncObj)
- when list(Element) ->
- asn1ct_name:new(tmpBytes),
- gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,
- ["{",{curr,tmpBytes},",_} = "],EncObj);
-gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,EncObj)
- when list(Element) ->
- gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,
- ["{",{curr,encBytes},",",{curr,encLen},"} = "],EncObj).
-
-gen_enc_line(Erules,TopType,Cname,Type,Element,Indent,OptOrMand,Assign,EncObj)
- when list(Element) ->
- IndDeep = indent(Indent),
- Tag = lists:reverse([?ASN1CT_GEN_BER:encode_tag_val(
- ?ASN1CT_GEN_BER:decode_class(X#tag.class),
- X#tag.form,
- X#tag.number)
- || X <- Type#type.tag]),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- WhatKind = asn1ct_gen:type(InnerType),
- emit(IndDeep),
- emit(Assign),
- gen_optormand_case(OptOrMand,Erules,TopType,Cname,Type,InnerType,WhatKind,
- Element),
- case {Type,asn1ct_gen:get_constraint(Type#type.constraint,
- componentrelation)} of
-% #type{constraint=[{tableconstraint_info,RefedFieldName}],
-% def={typefield,_}} ->
- {#type{def=#'ObjectClassFieldType'{type={typefield,_},
- fieldname=RefedFieldName}},
- {componentrelation,_,_}} ->
- {_LeadingAttrName,Fun} = EncObj,
- case RefedFieldName of
- {notype,T} ->
- throw({error,{notype,type_from_object,T}});
- {Name,RestFieldNames} when atom(Name) ->
- case OptOrMand of
- mandatory -> ok;
- _ ->
-% emit(["{",{curr,tmpBytes},",",{curr,tmpLen},
- emit(["{",{curr,tmpBytes},",_ } = "])
-% "} = "])
- end,
- emit([Fun,"(",{asis,Name},", ",Element,", ",
- {asis,RestFieldNames},"),",nl]),
- emit(IndDeep),
- case OptOrMand of
- mandatory ->
- emit(["{",{curr,encBytes},",",{curr,encLen},
- "} = "]),
- emit(["?RT_BER:encode_open_type(",{curr,tmpBytes},
- ",",{asis,Tag},")"]);
- _ ->
-% emit(["{",{next,tmpBytes},", _} = "]),
- emit(["{",{next,tmpBytes},",",{curr,tmpLen},
- "} = "]),
- emit(["?RT_BER:encode_open_type(",{curr,tmpBytes},
- ",",{asis,Tag},"),",nl]),
- emit(IndDeep),
- emit(["{",{next,tmpBytes},", ",{curr,tmpLen},"}"])
- end;
- _ ->
- throw({asn1,{'internal error'}})
- end;
- {{#'ObjectClassFieldType'{type={objectfield,PrimFieldName1,
- PFNList}},_},
- {componentrelation,_,_}} ->
- %% this is when the dotted list in the FieldName has more
- %% than one element
- {_LeadingAttrName,Fun} = EncObj,
- emit(["?RT_BER:encode_open_type(",Fun,"(",{asis,PrimFieldName1},
- ", ",Element,", ",{asis,PFNList},"))"]);
- _ ->
- case WhatKind of
- {primitive,bif} ->
- EncType =
- case Type#type.def of
- #'ObjectClassFieldType'{type={fixedtypevaluefield,_,Btype}} ->
- Btype;
- _ ->
- Type
- end,
- ?ASN1CT_GEN_BER:gen_encode_prim(ber,EncType,{asis,Tag},
- Element);
- {notype,_} ->
- emit(["'enc_",InnerType,"'(",Element,", ",{asis,Tag},")"]);
- 'ASN1_OPEN_TYPE' ->
- case Type#type.def of
- #'ObjectClassFieldType'{} -> %Open Type
- ?ASN1CT_GEN_BER:gen_encode_prim(ber,#type{def='ASN1_OPEN_TYPE'},{asis,Tag},Element);
- _ ->
- ?ASN1CT_GEN_BER:gen_encode_prim(ber,Type,
- {asis,Tag},
- Element)
- end;
- _ ->
- {EncFunName, _EncMod, _EncFun} =
- mkfuncname(TopType,Cname,WhatKind,"enc_"),
- case {WhatKind,Type#type.tablecinf,EncObj} of
- {{constructed,bif},[{objfun,_}|_R],{_,Fun}} ->
- emit([EncFunName,"(",Element,", ",{asis,Tag},
- ", ",Fun,")"]);
- _ ->
- emit([EncFunName,"(",Element,", ",{asis,Tag},")"])
- end
- end
- end,
- case OptOrMand of
- mandatory -> true;
- _ ->
- emit([nl,indent(7),"end"])
- end.
-
-gen_optormand_case(mandatory,_Erules,_TopType,_Cname,_Type,_InnerType,_WhatKind,
- _Element) ->
- ok;
-gen_optormand_case('OPTIONAL',Erules,_TopType,_Cname,_Type,_InnerType,_WhatKind,
- Element) ->
- emit([" case ",Element," of",nl]),
- emit([indent(9),"asn1_NOVALUE -> {",
- empty_lb(Erules),",0};",nl]),
- emit([indent(9),"_ ->",nl,indent(12)]);
-gen_optormand_case({'DEFAULT',DefaultValue},Erules,TopType,Cname,Type,
- InnerType,WhatKind,Element) ->
- CurrMod = get(currmod),
- case catch lists:member(der,get(encoding_options)) of
- true ->
- emit(" case catch "),
- asn1ct_gen:gen_check_call(TopType,Cname,Type,InnerType,
- WhatKind,{asis,DefaultValue},
- Element),
- emit([" of",nl]),
- emit([indent(12),"true -> {[],0};",nl]);
- _ ->
- emit([" case ",Element," of",nl]),
- emit([indent(9),"asn1_DEFAULT -> {",
- empty_lb(Erules),
- ",0};",nl]),
- case DefaultValue of
- #'Externalvaluereference'{module=CurrMod,
- value=V} ->
- emit([indent(9),"?",{asis,V}," -> {",
- empty_lb(Erules),",0};",nl]);
- _ ->
- emit([indent(9),{asis,
- DefaultValue}," -> {",
- empty_lb(Erules),",0};",nl])
- end
- end,
- emit([indent(9),"_ ->",nl,indent(12)]).
-
-
-
-gen_dec_line(Erules,TopType,Cname,CTags,Type,OptOrMand,DecObjInf) ->
- BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(v)),
- Tag =
- [(?ASN1CT_GEN_BER:decode_class(X#tag.class) bsl 10) + X#tag.number ||
- X <- Type#type.tag],
- ChoiceTags =
- [(?ASN1CT_GEN_BER:decode_class(Class) bsl 10) + Number||
- {Class,Number} <- CTags],
- InnerType =
- case Type#type.def of
- #'ObjectClassFieldType'{type=OCFTType} ->
- OCFTType;
- _ ->
- asn1ct_gen:get_inner(Type#type.def)
- end,
- PostpDec =
- case OptOrMand of
- mandatory ->
- gen_dec_call(InnerType,Erules,TopType,Cname,Type,
- BytesVar,Tag,
- mandatory,", mandatory, ",DecObjInf,OptOrMand);
- _ -> %optional or default or a mandatory component after an extensionmark
- {FirstTag,RestTag} =
- case Tag of
- [] ->
- {ChoiceTags,[]};
- [Ft|Rt] ->
- {Ft,Rt}
- end,
- emit(["case ",{prev,tlv}," of",nl]),
- PostponedDec =
- case Tag of
- [] when length(ChoiceTags) > 0 -> % a choice without explicit tag
- Fcases =
- fun(FirstTag1) ->
- emit(["[",{curr,v}," = {",{asis,FirstTag1},
- ",_}|Temp",
- {curr,tlv},
- "] ->",nl]),
- emit([indent(4),"{"]),
- Pdec=
- gen_dec_call(InnerType,Erules,
- TopType,Cname,Type,
- BytesVar,RestTag,
- mandatory,
- ", mandatory, ",
- DecObjInf,OptOrMand),
-
- emit([", Temp",{curr,tlv},"}"]),
- emit([";",nl]),
- Pdec
- end,
- hd([Fcases(TmpTag)|| TmpTag <- FirstTag]);
-
- [] -> % an open type without explicit tag
- emit(["[",{curr,v},"|Temp",{curr,tlv},"] ->",nl]),
- emit([indent(4),"{"]),
- Pdec=
- gen_dec_call(InnerType,Erules,TopType,Cname,
- Type,BytesVar,RestTag,mandatory,
- ", mandatory, ",DecObjInf,
- OptOrMand),
-
- emit([", Temp",{curr,tlv},"}"]),
- emit([";",nl]),
- Pdec;
-
- _ ->
- emit(["[{",{asis,FirstTag},
- ",",{curr,v},"}|Temp",
- {curr,tlv},
- "] ->",nl]),
- emit([indent(4),"{"]),
- Pdec=
- gen_dec_call(InnerType,Erules,TopType,Cname,
- Type,BytesVar,RestTag,mandatory,
- ", mandatory, ",DecObjInf,
- OptOrMand),
-
- emit([", Temp",{curr,tlv},"}"]),
- emit([";",nl]),
- Pdec
- end,
-
- emit([indent(4),"_ ->",nl]),
- case OptOrMand of
- {'DEFAULT', Def} ->
- emit([indent(8),"{",{asis,Def},",",{prev,tlv},"}",nl]);
- 'OPTIONAL' ->
- emit([indent(8),"{ asn1_NOVALUE, ",{prev,tlv},"}",nl])
- end,
- emit(["end"]),
- PostponedDec
- end,
- case DecObjInf of
- {Cname,ObjSet} -> % this must be the component were an object is
- %% choosen from the object set according to the table
- %% constraint.
- {[{ObjSet,Cname,asn1ct_gen:mk_var(asn1ct_name:curr(term))}],
- PostpDec};
- _ -> {[],PostpDec}
- end.
-
-gen_dec_call({typefield,_},_,_,_Cname,Type,BytesVar,Tag,_,_,false,_) ->
- %% this in case of a choice with typefield components
- asn1ct_name:new(reason),
- asn1ct_name:new(opendec),
- asn1ct_name:new(tmpterm),
- asn1ct_name:new(tmptlv),
-
- {FirstPFName,RestPFName} =
-% asn1ct_gen:get_constraint(Type#type.constraint,
-% tableconstraint_info),
- (Type#type.def)#'ObjectClassFieldType'.fieldname,
- emit([nl,indent(6),"begin",nl]),
-% emit([indent(9),{curr,opendec}," = ?RT_BER:decode_open_type(",
- emit([indent(9),{curr,tmptlv}," = ?RT_BER:decode_open_type(",
- BytesVar,",",{asis,Tag},"),",nl]),
-% emit([indent(9),"{",{curr,tmptlv},",_} = ?RT_BER:decode(",
-% {curr,opendec},"),",nl]),
-
- emit([indent(9),"case (catch ObjFun(",{asis,FirstPFName},
- ", ",{curr,tmptlv},", ",{asis,RestPFName},
- ")) of", nl]),%% ??? What about Tag
- emit([indent(12),"{'EXIT',",{curr,reason},"} ->",nl]),
- emit([indent(15),"exit({'Type not ",
- "compatible with table constraint', ",{curr,reason},"});",nl]),
- emit([indent(12),{curr,tmpterm}," ->",nl]),
- emit([indent(15),{curr,tmpterm},nl]),
- emit([indent(9),"end",nl,indent(6),"end",nl]),
- [];
-gen_dec_call({typefield,_},_,_,Cname,Type,BytesVar,Tag,_,_,_DecObjInf,OptOrMandComp) ->
- emit(["?RT_BER:decode_open_type(",BytesVar,",",{asis,Tag},")"]),
- RefedFieldName =
-% asn1ct_gen:get_constraint(Type#type.constraint,
-% tableconstraint_info),
- (Type#type.def)#'ObjectClassFieldType'.fieldname,
- [{Cname,RefedFieldName,asn1ct_gen:mk_var(asn1ct_name:curr(term)),
- asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
-gen_dec_call({objectfield,PrimFieldName,PFNList},_,_,Cname,_,BytesVar,Tag,_,_,_,OptOrMandComp) ->
- emit(["?RT_BER:decode_open_type(",BytesVar,",",{asis,Tag},")"]),
- [{Cname,{PrimFieldName,PFNList},asn1ct_gen:mk_var(asn1ct_name:curr(term)),
- asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),Tag,OptOrMandComp}];
-gen_dec_call(InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,PrimOptOrMand,
- OptOrMand,DecObjInf,_) ->
- WhatKind = asn1ct_gen:type(InnerType),
- gen_dec_call1(WhatKind,InnerType,Erules,TopType,Cname,Type,BytesVar,Tag,
- PrimOptOrMand,OptOrMand),
- case DecObjInf of
- {Cname,{_,OSet,UniqueFName,ValIndex}} ->
- Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
- ValueMatch = value_match(ValIndex,Term),
- emit([",",nl,"ObjFun = 'getdec_",OSet,"'(",
-% {asis,UniqueFName},", ",{curr,term},")"]);
- {asis,UniqueFName},", ",ValueMatch,")"]);
- _ ->
- ok
- end,
- [].
-gen_dec_call1({primitive,bif},InnerType,Erules,TopType,Cname,Type,BytesVar,
- Tag,OptOrMand,_) ->
- case {asn1ct:get_gen_state_field(namelist),InnerType} of
- {[{Cname,undecoded}|Rest],_} ->
- asn1ct:add_generated_refed_func({[Cname|TopType],undecoded,
- Tag,Type}),
- asn1ct:update_gen_state(namelist,Rest),
-% emit(["?RT_BER:match_tags(",BytesVar,",",{asis,Tag},")"]);
- emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',",
- BytesVar,"}"]);
- {_,{fixedtypevaluefield,_,Btype}} ->
- ?ASN1CT_GEN_BER:gen_dec_prim(Erules,Btype,BytesVar,Tag,[],
- ?PRIMITIVE,OptOrMand);
- _ ->
- ?ASN1CT_GEN_BER:gen_dec_prim(Erules,Type,BytesVar,Tag,[],
- ?PRIMITIVE,OptOrMand)
- end;
-gen_dec_call1('ASN1_OPEN_TYPE',_InnerType,Erules,TopType,Cname,Type,BytesVar,
- Tag,OptOrMand,_) ->
- case {asn1ct:get_gen_state_field(namelist),Type#type.def} of
- {[{Cname,undecoded}|Rest],_} ->
- asn1ct:add_generated_refed_func({[Cname|TopType],undecoded,
- Tag,Type}),
- asn1ct:update_gen_state(namelist,Rest),
- emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',",
- BytesVar,"}"]);
-% emit(["?RT_BER:match_tags(",BytesVar,",",{asis,Tag},")"]);
- {_,#'ObjectClassFieldType'{type=OpenType}} ->
- ?ASN1CT_GEN_BER:gen_dec_prim(Erules,#type{def=OpenType},
- BytesVar,Tag,[],
- ?PRIMITIVE,OptOrMand);
- _ ->
- ?ASN1CT_GEN_BER:gen_dec_prim(Erules,Type,BytesVar,Tag,[],
- ?PRIMITIVE,OptOrMand)
- end;
-gen_dec_call1(WhatKind,_,_Erules,TopType,Cname,Type,BytesVar,
- Tag,_,_OptOrMand) ->
- case asn1ct:get_gen_state_field(namelist) of
- [{Cname,undecoded}|Rest] ->
- asn1ct:add_generated_refed_func({[Cname|TopType],undecoded,
- Tag,Type}),
- asn1ct:update_gen_state(namelist,Rest),
- emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',",
- BytesVar,"}"]);
- _ ->
-% {DecFunName, _DecMod, _DecFun} =
-% case {asn1ct:get_gen_state_field(namelist),WhatKind} of
- EmitDecFunCall =
- fun(FuncName) ->
- case {WhatKind,Type#type.tablecinf} of
- {{constructed,bif},[{objfun,_}|_Rest]} ->
- emit([FuncName,"(",BytesVar,", ",{asis,Tag},
- ", ObjFun)"]);
- _ ->
- emit([FuncName,"(",BytesVar,", ",{asis,Tag},")"])
- end
- end,
- case asn1ct:get_gen_state_field(namelist) of
- [{Cname,List}|Rest] when list(List) ->
- case WhatKind of
- #'Externaltypereference'{} ->
- %%io:format("gen_dec_call1 1:~n~p~n~n",[WhatKind]),
- asn1ct:add_tobe_refed_func({WhatKind,List});
- _ ->
- %%io:format("gen_dec_call1 2:~n~p~n~n",[[Cname|TopType]]),
- asn1ct:add_tobe_refed_func({[Cname|TopType],
- List})
- end,
- asn1ct:update_gen_state(namelist,Rest),
- Prefix=asn1ct:get_gen_state_field(prefix),
- {DecFunName,_,_}=
- mkfuncname(TopType,Cname,WhatKind,Prefix),
- EmitDecFunCall(DecFunName);
- [{Cname,parts}|Rest] ->
- asn1ct:update_gen_state(namelist,Rest),
- asn1ct:get_gen_state_field(prefix),
- %% This is to prepare SEQUENCE OF value in
- %% partial incomplete decode for a later
- %% part-decode, i.e. skip %% the tag.
- asn1ct:add_generated_refed_func({[Cname|TopType],
- parts,
- [],Type}),
- emit(["{'",asn1ct_gen:list2name([Cname|TopType]),"',"]),
- EmitDecFunCall("?RT_BER:match_tags"),
- emit("}");
- _ ->
- {DecFunName,_,_}=
- mkfuncname(TopType,Cname,WhatKind,"dec_"),
- EmitDecFunCall(DecFunName)
- end
-% case {WhatKind,Type#type.tablecinf} of
-% {{constructed,bif},[{objfun,_}|_Rest]} ->
-% emit([DecFunName,"(",BytesVar,", ",{asis,Tag},
-% ", ObjFun)"]);
-% _ ->
-% emit([DecFunName,"(",BytesVar,", ",{asis,Tag},")"])
-% end
- end.
-
-
-%%------------------------------------------------------
-%% General and special help functions (not exported)
-%%------------------------------------------------------
-
-
-indent(N) ->
- lists:duplicate(N,32). % 32 = space
-
-mkcindexlist([H,T1|T], Sep) -> % Sep is a string e.g ", " or "+ "
- emit(["Cindex",H,Sep]),
- mkcindexlist([T1|T], Sep);
-mkcindexlist([H|T], Sep) ->
- emit(["Cindex",H]),
- mkcindexlist(T, Sep);
-mkcindexlist([], _) ->
- true.
-
-mkcindexlist(L) ->
- mkcindexlist(L,", ").
-
-
-mkvlist([H,T1|T], Sep) -> % Sep is a string e.g ", " or "+ "
- emit([{var,H},Sep]),
- mkvlist([T1|T], Sep);
-mkvlist([H|T], Sep) ->
- emit([{var,H}]),
- mkvlist(T, Sep);
-mkvlist([], _) ->
- true.
-
-mkvlist(L) ->
- mkvlist(L,", ").
-
-mkvplus(L) ->
- mkvlist(L," + ").
-
-extensible(CompList) when list(CompList) ->
- noext;
-extensible({RootList,ExtList}) ->
- {ext,length(RootList)+1,length(ExtList)}.
-
-
-print_attribute_comment(InnerType,Pos,Cname,Prop) ->
- CommentLine = "%%-------------------------------------------------",
- emit([nl,CommentLine]),
- case InnerType of
- {typereference,_,Name} ->
- emit([nl,"%% attribute ",Cname,"(",Pos,") with type ",Name]);
- {'Externaltypereference',_,XModule,Name} ->
- emit([nl,"%% attribute ",Cname,"(",Pos,") External ",XModule,":",Name]);
- _ ->
- emit([nl,"%% attribute ",Cname,"(",Pos,") with type ",InnerType])
- end,
- case Prop of
- mandatory ->
- continue;
- {'DEFAULT', Def} ->
- emit([" DEFAULT = ",{asis,Def}]);
- 'OPTIONAL' ->
- emit([" OPTIONAL"])
- end,
- emit([nl,CommentLine,nl]).
-
-
-
-mkfuncname(TopType,Cname,WhatKind,Prefix) ->
- CurrMod = get(currmod),
- case WhatKind of
- #'Externaltypereference'{module=CurrMod,type=EType} ->
- F = lists:concat(["'",Prefix,EType,"'"]),
- {F, "?MODULE", F};
- #'Externaltypereference'{module=Mod,type=EType} ->
- {lists:concat(["'",Mod,"':'",Prefix,EType,"'"]),Mod,
- lists:concat(["'",Prefix,EType,"'"])};
- {constructed,bif} ->
- F = lists:concat(["'",Prefix,asn1ct_gen:list2name([Cname|TopType]),"'"]),
- {F, "?MODULE", F}
- end.
-
-empty_lb(ber) ->
- "[]";
-empty_lb(ber_bin) ->
- "<<>>";
-empty_lb(ber_bin_v2) ->
- "<<>>".
-
-value_match(Index,Value) when atom(Value) ->
- value_match(Index,atom_to_list(Value));
-value_match([],Value) ->
- Value;
-value_match([{VI,_}|VIs],Value) ->
- value_match1(Value,VIs,lists:concat(["element(",VI,","]),1).
-value_match1(Value,[],Acc,Depth) ->
- Acc ++ Value ++ lists:concat(lists:duplicate(Depth,")"));
-value_match1(Value,[{VI,_}|VIs],Acc,Depth) ->
- value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1).
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_constructed_per.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_constructed_per.erl
deleted file mode 100644
index 9b4e0063bb..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_constructed_per.erl
+++ /dev/null
@@ -1,1235 +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: asn1ct_constructed_per.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
-%%
--module(asn1ct_constructed_per).
-
--export([gen_encode_sequence/3]).
--export([gen_decode_sequence/3]).
--export([gen_encode_set/3]).
--export([gen_decode_set/3]).
--export([gen_encode_sof/4]).
--export([gen_decode_sof/4]).
--export([gen_encode_choice/3]).
--export([gen_decode_choice/3]).
-
--include("asn1_records.hrl").
-%-compile(export_all).
-
--import(asn1ct_gen, [emit/1,demit/1]).
-
-
-%% ENCODE GENERATOR FOR SEQUENCE TYPE ** **********
-
-
-gen_encode_set(Erules,TypeName,D) ->
- gen_encode_constructed(Erules,TypeName,D).
-
-gen_encode_sequence(Erules,TypeName,D) ->
- gen_encode_constructed(Erules,TypeName,D).
-
-gen_encode_constructed(Erules,Typename,D) when record(D,type) ->
- asn1ct_name:start(),
- asn1ct_name:new(term),
- asn1ct_name:new(bytes),
- {CompList,TableConsInfo} =
- case D#type.def of
- #'SEQUENCE'{tablecinf=TCI,components=CL} ->
- {CL,TCI};
- #'SET'{tablecinf=TCI,components=CL} ->
- {CL,TCI}
- end,
- case Typename of
- ['EXTERNAL'] ->
- emit({{var,asn1ct_name:next(val)},
- " = asn1rt_check:transform_to_EXTERNAL1990(",
- {var,asn1ct_name:curr(val)},"),",nl}),
- asn1ct_name:new(val);
- _ ->
- ok
- end,
- case {Optionals = optionals(CompList),CompList} of
- {[],EmptyCL} when EmptyCL == {[],[]};EmptyCL == [] ->
- emit(["%%Variable setting just to eliminate ",
- "compiler warning for unused vars!",nl,
- "_Val = ",{var,asn1ct_name:curr(val)},",",nl]);
- {[],_} ->
- emit([{var,asn1ct_name:next(val)}," = ?RT_PER:list_to_record("]),
- emit(["'",asn1ct_gen:list2rname(Typename),"'"]),
- emit([", ",{var,asn1ct_name:curr(val)},"),",nl]);
- _ ->
- Fixoptcall =
- case Erules of
- per -> ",Opt} = ?RT_PER:fixoptionals2(";
- _ -> ",Opt} = ?RT_PER:fixoptionals("
- end,
- emit({"{",{var,asn1ct_name:next(val)},Fixoptcall,
- {asis,Optionals},",",length(Optionals),
- ",",{var,asn1ct_name:curr(val)},"),",nl})
- end,
- asn1ct_name:new(val),
- Ext = extensible(CompList),
- case Ext of
- {ext,_,NumExt} when NumExt > 0 ->
- emit(["Extensions = ?RT_PER:fixextensions(",{asis,Ext},
- ", ",{curr,val},"),",nl]);
- _ -> true
- end,
- EncObj =
- case TableConsInfo of
- #simpletableattributes{usedclassfield=Used,
- uniqueclassfield=Unique} when Used /= Unique ->
- false;
- %% ObjectSet, name of the object set in constraints
- %%
- %%{ObjectSet,AttrN,N,UniqueFieldName} -> %% N is index of attribute that determines constraint
- #simpletableattributes{objectsetname=ObjectSet,
- c_name=AttrN,
- c_index=N,
- usedclassfield=UniqueFieldName,
- uniqueclassfield=UniqueFieldName,
- valueindex=ValueIndex
- } -> %% N is index of attribute that determines constraint
- OSDef =
- case ObjectSet of
- {Module,OSName} ->
- asn1_db:dbget(Module,OSName);
- OSName ->
- asn1_db:dbget(get(currmod),OSName)
- end,
- case (OSDef#typedef.typespec)#'ObjectSet'.gen of
- true ->
- ObjectEncode =
- asn1ct_gen:un_hyphen_var(lists:concat(['Obj',AttrN])),
- emit([ObjectEncode," = ",nl]),
- emit([" 'getenc_",ObjectSet,"'(",
- {asis,UniqueFieldName},", ",nl]),
- El = make_element(N+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),AttrN),
- Indent = 12 + length(atom_to_list(ObjectSet)),
- case ValueIndex of
- [] ->
- emit([indent(Indent),El,"),",nl]);
- _ ->
- emit([indent(Indent),"value_match(",
- {asis,ValueIndex},",",El,")),",nl]),
- notice_value_match()
- end,
- {AttrN,ObjectEncode};
- _ ->
- false
- end;
- _ ->
- case D#type.tablecinf of
- [{objfun,_}|_] ->
- %% when the simpletableattributes was at an outer
- %% level and the objfun has been passed through the
- %% function call
- {"got objfun through args","ObjFun"};
- _ ->
- false
- end
- end,
- emit({"[",nl}),
- MaybeComma1 =
- case Ext of
- {ext,_Pos,NumExt2} when NumExt2 > 0 ->
- emit({"?RT_PER:setext(Extensions =/= [])"}),
- ", ";
- {ext,_Pos,_} ->
- emit({"?RT_PER:setext(false)"}),
- ", ";
- _ ->
- ""
- end,
- MaybeComma2 =
- case optionals(CompList) of
- [] -> MaybeComma1;
- _ ->
- emit(MaybeComma1),
- emit("Opt"),
- {",",nl}
- end,
- gen_enc_components_call(Typename,CompList,MaybeComma2,EncObj,Ext),
- emit({"].",nl}).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% generate decode function for SEQUENCE and SET
-%%
-gen_decode_set(Erules,Typename,D) ->
- gen_decode_constructed(Erules,Typename,D).
-
-gen_decode_sequence(Erules,Typename,D) ->
- gen_decode_constructed(Erules,Typename,D).
-
-gen_decode_constructed(_Erules,Typename,D) when record(D,type) ->
- asn1ct_name:start(),
- {CompList,TableConsInfo} =
- case D#type.def of
- #'SEQUENCE'{tablecinf=TCI,components=CL} ->
- {CL,TCI};
- #'SET'{tablecinf=TCI,components=CL} ->
- {CL,TCI}
- end,
- Ext = extensible(CompList),
- MaybeComma1 = case Ext of
- {ext,_Pos,_NumExt} ->
- gen_dec_extension_value("Bytes"),
- {",",nl};
- _ ->
- ""
- end,
- Optionals = optionals(CompList),
- MaybeComma2 = case Optionals of
- [] -> MaybeComma1;
- _ ->
- Bcurr = asn1ct_name:curr(bytes),
- Bnext = asn1ct_name:next(bytes),
- emit(MaybeComma1),
- GetoptCall = "} = ?RT_PER:getoptionals2(",
- emit({"{Opt,",{var,Bnext},GetoptCall,
- {var,Bcurr},",",{asis,length(Optionals)},")"}),
- asn1ct_name:new(bytes),
- ", "
- end,
- {DecObjInf,UniqueFName,ValueIndex} =
- case TableConsInfo of
-%% {ObjectSet,AttrN,N,UniqueFieldName} ->%% N is index of attribute that determines constraint
- #simpletableattributes{objectsetname=ObjectSet,
- c_name=AttrN,
- usedclassfield=UniqueFieldName,
- uniqueclassfield=UniqueFieldName,
- valueindex=ValIndex} ->
-%% {AttrN,ObjectSet};
- F = fun(#'ComponentType'{typespec=CT})->
- case {CT#type.constraint,CT#type.tablecinf} of
- {[],[{objfun,_}|_R]} -> true;
- _ -> false
- end
- end,
- case lists:any(F,CompList) of
- true -> % when component relation constraint establish
- %% relation from a component to another components
- %% subtype component
- {{AttrN,{deep,ObjectSet,UniqueFieldName,ValIndex}},
- UniqueFieldName,ValIndex};
- false ->
- {{AttrN,ObjectSet},UniqueFieldName,ValIndex}
- end;
- _ ->
- case D#type.tablecinf of
- [{objfun,_}|_] ->
- {{"got objfun through args","ObjFun"},false,false};
- _ ->
- {false,false,false}
- end
- end,
- {AccTerm,AccBytes} =
- gen_dec_components_call(Typename,CompList,MaybeComma2,DecObjInf,Ext,length(Optionals)),
- case asn1ct_name:all(term) of
- [] -> emit(MaybeComma2); % no components at all
- _ -> emit({com,nl})
- end,
- case {AccTerm,AccBytes} of
- {[],[]} ->
- ok;
- {_,[]} ->
- ok;
- {[{ObjSet,LeadingAttr,Term}],ListOfOpenTypes} ->
- DecObj = asn1ct_gen:un_hyphen_var(lists:concat(['DecObj',LeadingAttr,Term])),
- ValueMatch = value_match(ValueIndex,Term),
- emit({DecObj," =",nl," 'getdec_",ObjSet,"'(",
-% {asis,UniqueFName},", ",Term,"),",nl}),
- {asis,UniqueFName},", ",ValueMatch,"),",nl}),
- gen_dec_listofopentypes(DecObj,ListOfOpenTypes,false)
- end,
- %% we don't return named lists any more Cnames = mkcnamelist(CompList),
- demit({"Result = "}), %dbg
- %% return value as record
- case Typename of
- ['EXTERNAL'] ->
- emit({" OldFormat={'",asn1ct_gen:list2rname(Typename),
- "'"}),
- mkvlist(asn1ct_name:all(term)),
- emit({"},",nl}),
- emit({" ASN11994Format =",nl,
- " asn1rt_check:transform_to_EXTERNAL1994",
- "(OldFormat),",nl}),
- emit(" {ASN11994Format,");
- _ ->
- emit(["{{'",asn1ct_gen:list2rname(Typename),"'"]),
- mkvlist(asn1ct_name:all(term)),
- emit("},")
- end,
- emit({{var,asn1ct_name:curr(bytes)},"}"}),
- emit({".",nl,nl}).
-
-gen_dec_listofopentypes(_,[],_) ->
- emit(nl);
-gen_dec_listofopentypes(DecObj,[{_Cname,{FirstPFN,PFNList},Term,TmpTerm,Prop}|Rest],_Update) ->
-
-% asn1ct_name:new(term),
- asn1ct_name:new(tmpterm),
- asn1ct_name:new(reason),
-
- emit([Term," = ",nl]),
-
- N = case Prop of
- mandatory -> 0;
- 'OPTIONAL' ->
- emit_opt_or_mand_check(asn1_NOVALUE,TmpTerm),
- 6;
- {'DEFAULT',Val} ->
- emit_opt_or_mand_check(Val,TmpTerm),
- 6
- end,
-
- emit([indent(N+3),"case (catch ",DecObj,"(",
- {asis,FirstPFN},", ",TmpTerm,", telltype,",{asis,PFNList},")) of",nl]),
- emit([indent(N+6),"{'EXIT', ",{curr,reason},"} ->",nl]),
-%% emit({indent(9),"throw({runtime_error,{","'Type not compatible with table constraint'",",",Term,"}});",nl}),
- emit([indent(N+9),"exit({'Type not compatible with table constraint',",
- {curr,reason},"});",nl]),
- emit([indent(N+6),"{",{curr,tmpterm},",_} ->",nl]),
- emit([indent(N+9),{curr,tmpterm},nl]),
-
- case Prop of
- mandatory ->
- emit([indent(N+3),"end,",nl]);
- _ ->
- emit([indent(N+3),"end",nl,
- indent(3),"end,",nl])
- end,
- gen_dec_listofopentypes(DecObj,Rest,true).
-
-
-emit_opt_or_mand_check(Val,Term) ->
- emit([indent(3),"case ",Term," of",nl,
- indent(6),{asis,Val}," ->",{asis,Val},";",nl,
- indent(6),"_ ->",nl]).
-
-%% ENCODE GENERATOR FOR THE CHOICE TYPE *******
-%% assume Val = {Alternative,AltType}
-%% generate
-%%[
-%% ?RT_PER:set_choice(element(1,Val),Altnum,Altlist,ext),
-%%case element(1,Val) of
-%% alt1 ->
-%% encode_alt1(element(2,Val));
-%% alt2 ->
-%% encode_alt2(element(2,Val))
-%%end
-%%].
-
-gen_encode_choice(_Erules,Typename,D) when record(D,type) ->
- {'CHOICE',CompList} = D#type.def,
- emit({"[",nl}),
- Ext = extensible(CompList),
- gen_enc_choice(Typename,CompList,Ext),
- emit({nl,"].",nl}).
-
-gen_decode_choice(_Erules,Typename,D) when record(D,type) ->
- asn1ct_name:start(),
- asn1ct_name:new(bytes),
- {'CHOICE',CompList} = D#type.def,
- Ext = extensible(CompList),
- gen_dec_choice(Typename,CompList,Ext),
- emit({".",nl}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% Encode generator for SEQUENCE OF type
-
-
-gen_encode_sof(_Erules,Typename,SeqOrSetOf,D) when record(D,type) ->
- asn1ct_name:start(),
-% Val = [Component]
-% ?RT_PER:encode_length(length(Val)),
-% lists:
- {_SeqOrSetOf,ComponentType} = D#type.def,
- emit({"[",nl}),
- SizeConstraint =
- case asn1ct_gen:get_constraint(D#type.constraint,
- 'SizeConstraint') of
- no -> undefined;
- Range -> Range
- end,
- ObjFun =
- case D#type.tablecinf of
- [{objfun,_}|_R] ->
- ", ObjFun";
- _->
- ""
- end,
- emit({nl,indent(3),"?RT_PER:encode_length(",
- {asis,SizeConstraint},
- ",length(Val)),",nl}),
- emit({indent(3),"'enc_",asn1ct_gen:list2name(Typename),
- "_components'(Val",ObjFun,", [])"}),
- emit({nl,"].",nl}),
- NewComponentType =
- case ComponentType#type.def of
- {'ENUMERATED',_,Component}->
- ComponentType#type{def={'ENUMERATED',Component}};
- _ -> ComponentType
- end,
- gen_encode_sof_components(Typename,SeqOrSetOf,NewComponentType).
-
-gen_decode_sof(_Erules,Typename,SeqOrSetOf,D) when record(D,type) ->
- asn1ct_name:start(),
-% Val = [Component]
-% ?RT_PER:encode_length(length(Val)),
-% lists:
- {_SeqOrSetOf,ComponentType} = D#type.def,
- SizeConstraint =
- case asn1ct_gen:get_constraint(D#type.constraint,
- 'SizeConstraint') of
- no -> undefined;
- Range -> Range
- end,
- ObjFun =
- case D#type.tablecinf of
- [{objfun,_}|_R] ->
- ", ObjFun";
- _ ->
- ""
- end,
- emit({nl,"{Num,Bytes1} = ?RT_PER:decode_length(Bytes,",{asis,SizeConstraint},"),",nl}),
- emit({"'dec_",asn1ct_gen:list2name(Typename),
- "_components'(Num, Bytes1, telltype",ObjFun,", []).",nl}),
- NewComponentType =
- case ComponentType#type.def of
- {'ENUMERATED',_,Component}->
- ComponentType#type{def={'ENUMERATED',Component}};
- _ -> ComponentType
- end,
- gen_decode_sof_components(Typename,SeqOrSetOf,NewComponentType).
-
-gen_encode_sof_components(Typename,SeqOrSetOf,Cont) ->
- {ObjFun,ObjFun_Var} =
- case Cont#type.tablecinf of
- [{objfun,_}|_R] ->
- {", ObjFun",", _"};
- _ ->
- {"",""}
- end,
- emit({"'enc_",asn1ct_gen:list2name(Typename),"_components'([]",
- ObjFun_Var,", Acc) -> lists:reverse(Acc);",nl,nl}),
- emit({"'enc_",asn1ct_gen:list2name(Typename),"_components'([H|T]",
- ObjFun,", Acc) ->",nl}),
- emit({"'enc_",asn1ct_gen:list2name(Typename),"_components'(T"}),
- emit({ObjFun,", ["}),
- %% the component encoder
- Constructed_Suffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,
- Cont#type.def),
-
- Conttype = asn1ct_gen:get_inner(Cont#type.def),
- Currmod = get(currmod),
- Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
- asn1ct_gen:rt2ct_suffix()])),
- case asn1ct_gen:type(Conttype) of
- {primitive,bif} ->
- gen_encode_prim_wrapper(Ctgenmod,per,Cont,false,"H");
-% Ctgenmod:gen_encode_prim(per,Cont,false,"H");
- {constructed,bif} ->
- NewTypename = [Constructed_Suffix|Typename],
- emit({"'enc_",asn1ct_gen:list2name(NewTypename),"'(H",
- ObjFun,")",nl,nl});
- #'Externaltypereference'{module=Currmod,type=Ename} ->
- emit({"'enc_",Ename,"'(H)",nl,nl});
- #'Externaltypereference'{module=EMod,type=EType} ->
- emit({"'",EMod,"':'enc_",EType,"'(H)",nl,nl});
- _ ->
- emit({"'enc_",Conttype,"'(H)",nl,nl})
- end,
- emit({" | Acc]).",nl}).
-
-gen_decode_sof_components(Typename,SeqOrSetOf,Cont) ->
- {ObjFun,ObjFun_Var} =
- case Cont#type.tablecinf of
- [{objfun,_}|_R] ->
- {", ObjFun",", _"};
- _ ->
- {"",""}
- end,
- emit({"'dec_",asn1ct_gen:list2name(Typename),
- "_components'(0, Bytes, _",ObjFun_Var,", Acc) ->",nl,
- indent(3),"{lists:reverse(Acc), Bytes};",nl}),
- emit({"'dec_",asn1ct_gen:list2name(Typename),
- "_components'(Num, Bytes, _",ObjFun,", Acc) ->",nl}),
- emit({indent(3),"{Term,Remain} = "}),
- Constructed_Suffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,
- Cont#type.def),
- Conttype = asn1ct_gen:get_inner(Cont#type.def),
- Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
- asn1ct_gen:rt2ct_suffix()])),
- case asn1ct_gen:type(Conttype) of
- {primitive,bif} ->
- Ctgenmod:gen_dec_prim(per,Cont,"Bytes"),
- emit({com,nl});
- {constructed,bif} ->
- NewTypename = [Constructed_Suffix|Typename],
- emit({"'dec_",asn1ct_gen:list2name(NewTypename),
- "'(Bytes, telltype",ObjFun,"),",nl});
- #typereference{val=Dname} ->
- emit({"'dec_",Dname,"'(Bytes,telltype),",nl});
- #'Externaltypereference'{module=EMod,type=EType} ->
- emit({"'",EMod,"':'dec_",EType,"'(Bytes,telltype),",nl});
- _ ->
- emit({"'dec_",Conttype,"'(Bytes,telltype),",nl})
- end,
- emit({indent(3),"'dec_",asn1ct_gen:list2name(Typename),
- "_components'(Num-1, Remain, telltype",ObjFun,", [Term|Acc]).",nl}).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% General and special help functions (not exported)
-
-mkvlist([H|T]) ->
- emit(","),
- mkvlist2([H|T]);
-mkvlist([]) ->
- true.
-mkvlist2([H,T1|T]) ->
- emit({{var,H},","}),
- mkvlist2([T1|T]);
-mkvlist2([H|T]) ->
- emit({{var,H}}),
- mkvlist2(T);
-mkvlist2([]) ->
- true.
-
-extensible(CompList) when list(CompList) ->
- noext;
-extensible({RootList,ExtList}) ->
- {ext,length(RootList)+1,length(ExtList)}.
-
-gen_dec_extension_value(_) ->
- emit({"{Ext,",{next,bytes},"} = ?RT_PER:getext(",{curr,bytes},")"}),
- asn1ct_name:new(bytes).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Produce a list with positions (in the Value record) where
-%% there are optional components, start with 2 because first element
-%% is the record name
-
-optionals({L,_Ext}) -> optionals(L,[],2);
-optionals(L) -> optionals(L,[],2).
-
-optionals([{'EXTENSIONMARK',_,_}|Rest],Acc,Pos) ->
- optionals(Rest,Acc,Pos); % optionals in extension are currently not handled
-optionals([#'ComponentType'{prop='OPTIONAL'}|Rest],Acc,Pos) ->
- optionals(Rest,[Pos|Acc],Pos+1);
-optionals([#'ComponentType'{prop={'DEFAULT',_}}|Rest],Acc,Pos) ->
- optionals(Rest,[Pos|Acc],Pos+1);
-optionals([#'ComponentType'{}|Rest],Acc,Pos) ->
- optionals(Rest,Acc,Pos+1);
-optionals([],Acc,_) ->
- lists:reverse(Acc).
-
-
-gen_enc_components_call(TopType,{CompList,ExtList},MaybeComma,DynamicEnc,Ext) ->
- %% The type has extensionmarker
- Rpos = gen_enc_components_call1(TopType,CompList,1,MaybeComma,DynamicEnc,noext),
- case Ext of
- {ext,_,ExtNum} when ExtNum > 0 ->
- emit([nl,
- ",Extensions",nl]);
- _ -> true
- end,
- %handle extensions
- gen_enc_components_call1(TopType,ExtList,Rpos,MaybeComma,DynamicEnc,Ext);
-gen_enc_components_call(TopType, CompList, MaybeComma, DynamicEnc, Ext) ->
- %% The type has no extensionmarker
- gen_enc_components_call1(TopType,CompList,1,MaybeComma,DynamicEnc,Ext).
-
-gen_enc_components_call1(TopType,
- [C=#'ComponentType'{name=Cname,typespec=Type,prop=Prop}|Rest],
- Tpos,
- MaybeComma, DynamicEnc, Ext) ->
-
- put(component_type,{true,C}),
- %% information necessary in asn1ct_gen_per_rt2ct:gen_encode_prim
-
- Pos = case Ext of
- noext -> Tpos;
- {ext,Epos,_Enum} -> Tpos - Epos + 1
- end,
- emit(MaybeComma),
- case Prop of
- 'OPTIONAL' ->
- gen_enc_component_optional(TopType,Cname,Type,Tpos,DynamicEnc,Ext);
- {'DEFAULT',_DefVal} ->
- gen_enc_component_default(TopType,Cname,Type,Tpos,DynamicEnc,Ext);
- _ ->
- case Ext of
- {ext,ExtPos,_} when Tpos >= ExtPos ->
- gen_enc_component_optional(TopType,Cname,Type,Tpos,DynamicEnc,Ext);
- _ ->
- gen_enc_component_mandatory(TopType,Cname,Type,Tpos,DynamicEnc,Ext)
- end
- end,
-
- erase(component_type),
-
- case Rest of
- [] ->
- Pos+1;
- _ ->
- emit({com,nl}),
- gen_enc_components_call1(TopType,Rest,Tpos+1,"",DynamicEnc,Ext)
- end;
-gen_enc_components_call1(_TopType,[],Pos,_,_,_) ->
- Pos.
-
-gen_enc_component_default(TopType,Cname,Type,Pos,DynamicEnc,Ext) ->
-% Element = io_lib:format("?RT_PER:cindex(~w,Val1,~w)",[Pos+1,Cname]),
- Element = make_element(Pos+1,"Val1",Cname),
- emit({"case ",Element," of",nl}),
-% case Ext of
-% {ext,ExtPos,_} when Pos >= ExtPos ->
-% emit({"asn1_NOEXTVALUE -> [];",nl});
-% _ ->
- emit({"asn1_DEFAULT -> [];",nl}),
-% end,
- 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(TopType,Cname,Type,NextElement, Pos,DynamicEnc,Ext),
- emit({nl,"end"}).
-
-gen_enc_component_optional(TopType,Cname,Type,Pos,DynamicEnc,Ext) ->
-% Element = io_lib:format("?RT_PER:cindex(~w,Val1,~w)",[Pos+1,Cname]),
- Element = make_element(Pos+1,"Val1",Cname),
- emit({"case ",Element," of",nl}),
-% case Ext of
-% {ext,ExtPos,_} when Pos >= ExtPos ->
-% emit({"asn1_NOEXTVALUE -> [];",nl});
-% _ ->
- emit({"asn1_NOVALUE -> [];",nl}),
-% end,
- 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(TopType,Cname,Type,NextElement, Pos,DynamicEnc,Ext),
- emit({nl,"end"}).
-
-gen_enc_component_mandatory(TopType,Cname,Type,Pos,DynamicEnc,Ext) ->
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- emit({nl,"%% attribute number ",Pos," with type ",
- InnerType,nl}),
- gen_enc_line(TopType,Cname,Type,[],Pos,DynamicEnc,Ext).
-
-gen_enc_line(TopType, Cname, Type, [], Pos,DynamicEnc,Ext) ->
-% Element = io_lib:format("?RT_PER:cindex(~w,~s,~w)",[Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),Cname]),
- Element = make_element(Pos+1,asn1ct_gen:mk_var(asn1ct_name:curr(val)),Cname),
- gen_enc_line(TopType,Cname,Type,Element, Pos,DynamicEnc,Ext);
-gen_enc_line(TopType,Cname,Type,Element, Pos,DynamicEnc,Ext) ->
- Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
- asn1ct_gen:rt2ct_suffix()])),
- Atype =
- case Type of
- #type{def=#'ObjectClassFieldType'{type=InnerType}} ->
- InnerType;
- _ ->
- asn1ct_gen:get_inner(Type#type.def)
- end,
-% case asn1ct_gen:get_constraint(Type#type.constraint,
-% tableconstraint_info) of
-% no ->
-% asn1ct_gen:get_inner(Type#type.def);
-% _ ->
-% Type#type.def
-% end,
- case Ext of
- {ext,Ep1,_} when Pos >= Ep1 ->
- emit(["?RT_PER:encode_open_type(dummy,?RT_PER:complete("]);
- _ -> true
- end,
- case Atype of
- {typefield,_} ->
- case DynamicEnc of
- {_LeadingAttrName,Fun} ->
-% case asn1ct_gen:get_constraint(Type#type.constraint,
-% componentrelation) of
- case (Type#type.def)#'ObjectClassFieldType'.fieldname of
- {notype,T} ->
- throw({error,{notype,type_from_object,T}});
- {Name,RestFieldNames} when atom(Name) ->
- emit({"?RT_PER:encode_open_type([],?RT_PER:complete(",nl}),
- emit({" ",Fun,"(",{asis,Name},", ",
- Element,", ",{asis,RestFieldNames},")))"});
- Other ->
- throw({asn1,{'internal error',Other}})
- end
- end;
- {objectfield,PrimFieldName1,PFNList} ->
- case DynamicEnc of
- {_LeadingAttrName,Fun} ->
- emit({"?RT_PER:encode_open_type([],"
- "?RT_PER:complete(",nl}),
- emit({" ",Fun,"(",{asis,PrimFieldName1},
- ", ",Element,", ",{asis,PFNList},")))"})
- end;
- _ ->
- CurrMod = get(currmod),
- case asn1ct_gen:type(Atype) of
- #'Externaltypereference'{module=Mod,type=EType} when
- (CurrMod==Mod) ->
- emit({"'enc_",EType,"'(",Element,")"});
- #'Externaltypereference'{module=Mod,type=EType} ->
- emit({"'",Mod,"':'enc_",
- EType,"'(",Element,")"});
- #typereference{val=Ename} ->
- emit({"'enc_",Ename,"'(",Element,")"});
- {notype,_} ->
- emit({"'enc_",Atype,"'(",Element,")"});
- {primitive,bif} ->
- EncType =
- case Atype of
- {fixedtypevaluefield,_,Btype} ->
- Btype;
- _ ->
- Type
- end,
- gen_encode_prim_wrapper(Ctgenmod,per,EncType,
- false,Element);
-% Ctgenmod:gen_encode_prim(per,EncType,
-% false,Element);
- 'ASN1_OPEN_TYPE' ->
- case Type#type.def of
- #'ObjectClassFieldType'{type=OpenType} ->
- gen_encode_prim_wrapper(Ctgenmod,per,
- #type{def=OpenType},
- false,Element);
- _ ->
- gen_encode_prim_wrapper(Ctgenmod,per,Type,
- false,Element)
- end;
-% Ctgenmod:gen_encode_prim(per,Type,
-% false,Element);
- {constructed,bif} ->
- NewTypename = [Cname|TopType],
- case {Type#type.tablecinf,DynamicEnc} of
- {[{objfun,_}|_R],{_,EncFun}} ->
-%% emit({"?RT_PER:encode_open_type([],",
-%% "?RT_PER:complete(",nl}),
- emit({"'enc_",
- asn1ct_gen:list2name(NewTypename),
- "'(",Element,", ",EncFun,")"});
- _ ->
- emit({"'enc_",
- asn1ct_gen:list2name(NewTypename),
- "'(",Element,")"})
- end
- end
- end,
- case Ext of
- {ext,Ep2,_} when Pos >= Ep2 ->
- emit(["))"]);
- _ -> true
- end.
-
-gen_dec_components_call(TopType,{CompList,ExtList},MaybeComma,DecInfObj,Ext,NumberOfOptionals) ->
- %% The type has extensionmarker
- {Rpos,AccTerm,AccBytes} =
- gen_dec_components_call1(TopType, CompList, 1, 1, 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(TopType,ExtList,Rpos, 1, "",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),
- {AccTerm++AccTermE,AccBytes++AccBytesE};
-
-gen_dec_components_call(TopType,CompList,MaybeComma,DecInfObj,Ext,NumberOfOptionals) ->
- %% The type has no extensionmarker
- {_,AccTerm,AccBytes} =
- gen_dec_components_call1(TopType, CompList, 1, 1,MaybeComma,DecInfObj,Ext,[],[],NumberOfOptionals),
- {AccTerm,AccBytes}.
-
-
-gen_dec_components_call1(TopType,
- [C=#'ComponentType'{name=Cname,typespec=Type,prop=Prop}|Rest],
- Tpos,OptPos,MaybeComma,DecInfObj,Ext,AccTerm,AccBytes,NumberOfOptionals) ->
- Pos = case Ext of
- noext -> Tpos;
- {ext,Epos,_Enum} -> Tpos - Epos + 1
- end,
- emit(MaybeComma),
-%% asn1ct_name:new(term),
- InnerType =
- case Type#type.def of
- #'ObjectClassFieldType'{type=InType} ->
- InType;
- Def ->
- asn1ct_gen:get_inner(Def)
- end,
-% case asn1ct_gen:get_constraint(Type#type.constraint,
-% tableconstraint_info) of
-% no ->
-% asn1ct_gen:get_inner(Type#type.def);
-% _ ->
-% Type#type.def
-% end,
- case InnerType of
- #'Externaltypereference'{type=T} ->
- emit({nl,"%% attribute number ",Tpos," with type ",
- T,nl});
- IT when tuple(IT) ->
- emit({nl,"%% attribute number ",Tpos," with type ",
- element(2,IT),nl});
- _ ->
- emit({nl,"%% attribute number ",Tpos," with type ",
- InnerType,nl})
- end,
-
- case InnerType of
- {typefield,_} ->
- asn1ct_name:new(term),
- asn1ct_name:new(tmpterm),
- emit({"{",{curr,tmpterm},", ",{next,bytes},"} = "});
- {objectfield,_,_} ->
- asn1ct_name:new(term),
- asn1ct_name:new(tmpterm),
- emit({"{",{curr,tmpterm},", ",{next,bytes},"} = "});
- _ ->
- asn1ct_name:new(term),
- emit({"{",{curr,term},",",{next,bytes},"} = "})
- end,
-
- NewOptPos =
- case {Ext,Prop} of
- {noext,mandatory} -> OptPos; % generate nothing
- {noext,_} ->
- Element = io_lib:format("Opt band (1 bsl ~w)",[NumberOfOptionals - OptPos]),
- emit({"case ",Element," of",nl}),
- emit({"_Opt",OptPos," when _Opt",OptPos," > 0 ->"}),
- OptPos+1;
- _ ->
- emit(["case Extensions of",nl]),
- emit(["_ when size(Extensions) >= ",Pos,",element(",Pos,",Extensions) == 1 ->",nl])
- end,
- put(component_type,{true,C}),
- {TermVar,BytesVar} = gen_dec_line(TopType,Cname,Type,Tpos,DecInfObj,Ext),
- erase(component_type),
- case {Ext,Prop} of
- {noext,mandatory} -> true; % generate nothing
- {noext,_} ->
- emit([";",nl,"0 ->"]),
- gen_dec_component_no_val(TopType,Cname,Type,Prop,Tpos,Ext);
- _ ->
- emit([";",nl,"_ ->",nl]),
- gen_dec_component_no_val(TopType,Cname,Type,Prop,Tpos,Ext)
- end,
- case {Ext,Prop} of
- {noext,mandatory} -> true; % generate nothing
- {noext,_} ->
- emit([nl,"end"]);
- _ ->
- emit([nl,"end"])
-
- end,
- asn1ct_name:new(bytes),
- case Rest of
- [] ->
- {Pos+1,AccTerm++TermVar,AccBytes++BytesVar};
- _ ->
- emit({com,nl}),
- gen_dec_components_call1(TopType,Rest,Tpos+1,NewOptPos,"",DecInfObj,Ext,
- AccTerm++TermVar,AccBytes++BytesVar,NumberOfOptionals)
- end;
-
-gen_dec_components_call1(_TopType,[],Pos,_OptPos,_,_,_,AccTerm,AccBytes,_NumberOfOptionals) ->
- {Pos,AccTerm,AccBytes}.
-
-
-%%gen_dec_component_no_val(TopType,Cname,Type,_,Pos,{ext,Ep,Enum}) when Pos >= Ep ->
-%% emit({"{asn1_NOEXTVALUE,",{curr,bytes},"}",nl});
-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_line(TopType,Cname,Type,Pos,DecInfObj,Ext) ->
- Ctgenmod = list_to_atom(lists:concat(["asn1ct_gen_",per,
- asn1ct_gen:rt2ct_suffix()])),
- Atype =
- case Type of
- #type{def=#'ObjectClassFieldType'{type=InnerType}} ->
- InnerType;
- _ ->
- asn1ct_gen:get_inner(Type#type.def)
- end,
-% case asn1ct_gen:get_constraint(Type#type.constraint,
-% tableconstraint_info) of
-% no ->
-% asn1ct_gen:get_inner(Type#type.def);
-% _ ->
-% Type#type.def
-% end,
- BytesVar0 = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
- BytesVar = case Ext of
- {ext,Ep,_} when Pos >= Ep ->
- emit(["begin",nl,"{TmpVal",Pos,",Trem",Pos,
- "}=?RT_PER:decode_open_type(",
- {curr,bytes},",[]),",nl,
- "{TmpValx",Pos,",_}="]),
- io_lib:format("TmpVal~p",[Pos]);
- _ -> BytesVar0
- end,
- SaveBytes =
- case Atype of
- {typefield,_} ->
- case DecInfObj of
- false -> % This is in a choice with typefield components
- {Name,RestFieldNames} =
- (Type#type.def)#'ObjectClassFieldType'.fieldname,
-% asn1ct_gen:get_constraint(Type#type.constraint,
-% tableconstraint_info),
- asn1ct_name:new(tmpterm),
- asn1ct_name:new(reason),
- emit([indent(2),"{",{curr,tmpterm},", ",{next,bytes},
- "} = ?RT_PER:decode_open_type(",{curr,bytes},
- ", []),",nl]),
- emit([indent(2),"case (catch ObjFun(",
- {asis,Name},
- ",",{curr,tmpterm},",telltype,",
- {asis,RestFieldNames},")) of", nl]),
- emit([indent(4),"{'EXIT',",{curr,reason},"} ->",nl]),
- emit([indent(6),"exit({'Type not ",
- "compatible with table constraint', ",
- {curr,reason},"});",nl]),
- asn1ct_name:new(tmpterm),
- emit([indent(4),"{",{curr,tmpterm},", _} ->",nl]),
- emit([indent(6),"{",Cname,", {",{curr,tmpterm},", ",
- {next,bytes},"}}",nl]),
- emit([indent(2),"end"]),
- [];
- {"got objfun through args","ObjFun"} ->
- %% this is when the generated code gots the
- %% objfun though arguments on function
- %% invocation.
- {Name,RestFieldNames} =
- (Type#type.def)#'ObjectClassFieldType'.fieldname,
- emit(["?RT_PER:decode_open_type(",{curr,bytes},
- ", []),",nl]),
- emit([{curr,term}," =",nl,
- " case (catch ObjFun(",{asis,Name},",",
- {curr,tmpterm},",telltype,",
- {asis,RestFieldNames},")) of", nl]),
- emit([" {'EXIT',",{curr,reason},"} ->",nl]),
- emit([indent(6),"exit({'Type not ",
- "compatible with table constraint', ",
- {curr,reason},"});",nl]),
- asn1ct_name:new(tmpterm),
- emit([indent(4),"{",{curr,tmpterm},", _} ->",nl]),
- emit([indent(6),{curr,tmpterm},nl]),
- emit([indent(2),"end"]),
- [];
- _ ->
- emit({"?RT_PER:decode_open_type(",{curr,bytes},
- ", [])"}),
- RefedFieldName =
- (Type#type.def)#'ObjectClassFieldType'.fieldname,
-% asn1ct_gen:get_constraint(Type#type.constraint,
-% tableconstraint_info),
- [{Cname,RefedFieldName,
- asn1ct_gen:mk_var(asn1ct_name:curr(term)),
- asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
- get_components_prop()}]
- end;
- {objectfield,PrimFieldName1,PFNList} ->
- emit({"?RT_PER:decode_open_type(",{curr,bytes},", [])"}),
- [{Cname,{PrimFieldName1,PFNList},
- asn1ct_gen:mk_var(asn1ct_name:curr(term)),
- asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
- get_components_prop()}];
- _ ->
- CurrMod = get(currmod),
- case asn1ct_gen:type(Atype) of
- #'Externaltypereference'{module=CurrMod,type=EType} ->
- emit({"'dec_",EType,"'(",BytesVar,",telltype)"});
- #'Externaltypereference'{module=Mod,type=EType} ->
- emit({"'",Mod,"':'dec_",EType,"'(",BytesVar,
- ",telltype)"});
- {primitive,bif} ->
- case Atype of
- {fixedtypevaluefield,_,Btype} ->
- Ctgenmod:gen_dec_prim(per,Btype,
- BytesVar);
- _ ->
- Ctgenmod:gen_dec_prim(per,Type,
- BytesVar)
- end;
- 'ASN1_OPEN_TYPE' ->
- case Type#type.def of
- #'ObjectClassFieldType'{type=OpenType} ->
- Ctgenmod:gen_dec_prim(per,#type{def=OpenType},
- BytesVar);
- _ ->
- Ctgenmod:gen_dec_prim(per,Type,
- BytesVar)
- end;
- #typereference{val=Dname} ->
- emit({"'dec_",Dname,"'(",BytesVar,",telltype)"});
- {notype,_} ->
- emit({"'dec_",Atype,"'(",BytesVar,",telltype)"});
- {constructed,bif} ->
- NewTypename = [Cname|TopType],
- case Type#type.tablecinf of
- [{objfun,_}|_R] ->
- emit({"'dec_",asn1ct_gen:list2name(NewTypename),
- "'(",BytesVar,", telltype, ObjFun)"});
- _ ->
- emit({"'dec_",asn1ct_gen:list2name(NewTypename),
- "'(",BytesVar,", telltype)"})
- end
- end,
- case DecInfObj of
- {Cname,{_,OSet,UniqueFName,ValIndex}} ->
- Term = asn1ct_gen:mk_var(asn1ct_name:curr(term)),
- ValueMatch = value_match(ValIndex,Term),
- emit({",",nl,"ObjFun = 'getdec_",OSet,"'(",
- {asis,UniqueFName},", ",ValueMatch,")"});
- _ ->
- ok
- end,
- []
- end,
- case Ext of
- {ext,Ep2,_} when Pos >= Ep2 ->
- emit([", {TmpValx",Pos,",Trem",Pos,"}",nl,"end"]);
- _ -> true
- end,
- %% Prepare return value
- case DecInfObj of
- {Cname,ObjSet} ->
- {[{ObjSet,Cname,asn1ct_gen:mk_var(asn1ct_name:curr(term))}],
- SaveBytes};
- _ ->
- {[],SaveBytes}
- end.
-
-gen_enc_choice(TopType,CompList,Ext) ->
- gen_enc_choice_tag(CompList, [], Ext),
- emit({com,nl}),
- emit({"case element(1,Val) of",nl}),
- gen_enc_choice2(TopType, CompList, Ext),
- emit({nl,"end"}).
-
-gen_enc_choice_tag({C1,C2},_,_) ->
- N1 = get_name_list(C1),
- 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(C,_,_) ->
- N = get_name_list(C),
- emit(["?RT_PER:set_choice(element(1,Val),",
- {asis,N},", ",{asis,length(N)},")"]).
-
-get_name_list(L) ->
- get_name_list(L,[]).
-
-get_name_list([#'ComponentType'{name=Name}|T], Acc) ->
- get_name_list(T,[Name|Acc]);
-get_name_list([], Acc) ->
- lists:reverse(Acc).
-
-%gen_enc_choice_tag([H|T],Acc,Ext) when record(H,'ComponentType') ->
-% gen_enc_choice_tag(T,[H#'ComponentType'.name|Acc],Ext);
-%gen_enc_choice_tag([H|T],Acc,Ext) -> % skip EXTENSIONMARK
-% gen_enc_choice_tag(T,Acc,Ext);
-%gen_enc_choice_tag([],Acc,Ext) ->
-% Length = length(Acc),
-% emit({"?RT_PER:set_choice(element(1,Val),",{asis,Length},",",
-% {asis,lists:reverse(Acc)},",",{asis,Ext},")"}),
-% Length.
-
-gen_enc_choice2(TopType, {L1,L2}, Ext) ->
- gen_enc_choice2(TopType, L1 ++ L2, 0, Ext);
-gen_enc_choice2(TopType, L, Ext) ->
- gen_enc_choice2(TopType, L, 0, Ext).
-
-gen_enc_choice2(TopType,[H1,H2|T], Pos, Ext)
-when record(H1,'ComponentType'), record(H2,'ComponentType') ->
- Cname = H1#'ComponentType'.name,
- Type = H1#'ComponentType'.typespec,
- EncObj =
-% case asn1ct_gen:get_constraint(Type#type.constraint,
-% tableconstraint_info) of
-% no ->
-% false;
-% _ ->
-% {no_attr,"ObjFun"}
-% end,
- case asn1ct_gen:get_constraint(Type#type.constraint,
- componentrelation) of
- no -> false;
- _ -> {no_attr,"ObjFun"}
- end,
- emit({{asis,Cname}," ->",nl}),
- gen_enc_line(TopType,Cname,Type,"element(2,Val)", Pos+1,EncObj,Ext),
- emit({";",nl}),
- gen_enc_choice2(TopType,[H2|T], Pos+1, Ext);
-gen_enc_choice2(TopType,[H1|T], Pos, Ext) when record(H1,'ComponentType') ->
- Cname = H1#'ComponentType'.name,
- Type = H1#'ComponentType'.typespec,
- EncObj =
-% case asn1ct_gen:get_constraint(Type#type.constraint,
-% tableconstraint_info) of
-% no ->
-% false;
-% _ ->
-% {no_attr,"ObjFun"}
-% end,
- case asn1ct_gen:get_constraint(Type#type.constraint,
- componentrelation) of
- no -> false;
- _ -> {no_attr,"ObjFun"}
- end,
- emit({{asis,H1#'ComponentType'.name}," ->",nl}),
- gen_enc_line(TopType,Cname,Type,"element(2,Val)", Pos+1,EncObj,Ext),
- gen_enc_choice2(TopType,T, Pos+1, Ext);
-gen_enc_choice2(_,[], _, _) ->
- true.
-
-gen_dec_choice(TopType,CompList,{ext,Pos,NumExt}) ->
- emit({"{Ext,",{curr,bytes},"} = ?RT_PER:getbit(Bytes),",nl}),
- asn1ct_name:new(bytes),
- gen_dec_choice1(TopType,CompList,{ext,Pos,NumExt});
-gen_dec_choice(TopType,CompList,noext) ->
- gen_dec_choice1(TopType,CompList,noext).
-
-gen_dec_choice1(TopType,CompList,noext) ->
- emit({"{Choice,",{curr,bytes},
- "} = ?RT_PER:getchoice(",{prev,bytes},",",
- length(CompList),", 0),",nl}),
- emit({"{Cname,{Val,NewBytes}} = case Choice of",nl}),
- gen_dec_choice2(TopType,CompList,noext),
- emit({nl,"end,",nl}),
- emit({nl,"{{Cname,Val},NewBytes}"});
-gen_dec_choice1(TopType,{RootList,ExtList},Ext) ->
- NewList = RootList ++ ExtList,
- gen_dec_choice1(TopType, NewList, Ext);
-gen_dec_choice1(TopType,CompList,{ext,ExtPos,ExtNum}) ->
- emit({"{Choice,",{curr,bytes},
- "} = ?RT_PER:getchoice(",{prev,bytes},",",
- length(CompList)-ExtNum,",Ext ),",nl}),
- emit({"{Cname,{Val,NewBytes}} = case Choice + Ext*",ExtPos-1," of",nl}),
- gen_dec_choice2(TopType,CompList,{ext,ExtPos,ExtNum}),
- emit([";",nl,"_ -> {asn1_ExtAlt, ?RT_PER:decode_open_type(",{curr,bytes},",[])}"]),
- emit({nl,"end,",nl}),
- emit({nl,"{{Cname,Val},NewBytes}"}).
-
-
-gen_dec_choice2(TopType,L,Ext) ->
- gen_dec_choice2(TopType,L,0,Ext).
-
-gen_dec_choice2(TopType,[H1,H2|T],Pos,Ext)
-when record(H1,'ComponentType'), record(H2,'ComponentType') ->
- Cname = H1#'ComponentType'.name,
- Type = H1#'ComponentType'.typespec,
- case Type#type.def of
- #'ObjectClassFieldType'{type={typefield,_}} ->
- emit({Pos," -> ",nl}),
- wrap_gen_dec_line(H1,TopType,Cname,Type,Pos+1,false,Ext),
- emit({";",nl});
- _ ->
- emit({Pos," -> {",{asis,Cname},",",nl}),
- wrap_gen_dec_line(H1,TopType,Cname,Type,Pos+1,false,Ext),
- emit({"};",nl})
- end,
- gen_dec_choice2(TopType,[H2|T],Pos+1,Ext);
-gen_dec_choice2(TopType,[H1,_H2|T],Pos,Ext) when record(H1,'ComponentType') ->
- gen_dec_choice2(TopType,[H1|T],Pos,Ext); % skip extensionmark
-gen_dec_choice2(TopType,[H1|T],Pos,Ext) when record(H1,'ComponentType') ->
- Cname = H1#'ComponentType'.name,
- Type = H1#'ComponentType'.typespec,
- case Type#type.def of
- #'ObjectClassFieldType'{type={typefield,_}} ->
- emit({Pos," -> ",nl}),
- wrap_gen_dec_line(H1,TopType,Cname,Type,Pos+1,false,Ext);
- _ ->
- emit({Pos," -> {",{asis,Cname},",",nl}),
- wrap_gen_dec_line(H1,TopType,Cname,Type,Pos+1,false,Ext),
- emit("}")
- end,
- gen_dec_choice2(TopType,[T],Pos+1);
-gen_dec_choice2(TopType,[_|T],Pos,Ext) ->
- gen_dec_choice2(TopType,T,Pos,Ext);% skip extensionmark
-gen_dec_choice2(_,[],Pos,_) ->
- Pos.
-
-indent(N) ->
- lists:duplicate(N,32). % 32 = space
-
-gen_encode_prim_wrapper(CtgenMod,Erule,Cont,DoTag,Value) ->
-% put(component_type,true), % add more info in component_type
- CtgenMod:gen_encode_prim(Erule,Cont,DoTag,Value).
-% erase(component_type).
-
-make_element(I,Val,Cname) ->
- case lists:member(optimize,get(encoding_options)) of
- false ->
- io_lib:format("?RT_PER:cindex(~w,~s,~w)",[I,Val,Cname]);
- _ ->
- io_lib:format("element(~w,~s)",[I,Val])
- end.
-
-wrap_gen_dec_line(C,TopType,Cname,Type,Pos,DIO,Ext) ->
- put(component_type,{true,C}),
- gen_dec_line(TopType,Cname,Type,Pos,DIO,Ext),
- erase(component_type).
-
-get_components_prop() ->
- case get(component_type) of
- undefined ->
- mandatory;
- {true,#'ComponentType'{prop=Prop}} -> Prop
- end.
-
-
-value_match(Index,Value) when atom(Value) ->
- value_match(Index,atom_to_list(Value));
-value_match([],Value) ->
- Value;
-value_match([{VI,_}|VIs],Value) ->
- value_match1(Value,VIs,lists:concat(["element(",VI,","]),1).
-value_match1(Value,[],Acc,Depth) ->
- Acc ++ Value ++ lists:concat(lists:duplicate(Depth,")"));
-value_match1(Value,[{VI,_}|VIs],Acc,Depth) ->
- value_match1(Value,VIs,Acc++lists:concat(["element(",VI,","]),Depth+1).
-
-notice_value_match() ->
- Module = get(currmod),
- put(value_match,{true,Module}).
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen.erl
deleted file mode 100644
index e4a0b1fd9a..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen.erl
+++ /dev/null
@@ -1,1664 +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: asn1ct_gen.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
-%%
--module(asn1ct_gen).
-
--include("asn1_records.hrl").
-%%-compile(export_all).
--export([pgen_exports/3,
- pgen_hrl/4,
- gen_head/3,
- demit/1,
- emit/1,
- fopen/2,
- get_inner/1,type/1,def_to_tag/1,prim_bif/1,
- type_from_object/1,
- get_typefromobject/1,get_fieldcategory/2,
- get_classfieldcategory/2,
- list2name/1,
- list2rname/1,
- constructed_suffix/2,
- unify_if_string/1,
- gen_check_call/7,
- get_constraint/2,
- insert_once/2,
- rt2ct_suffix/1,rt2ct_suffix/0]).
--export([pgen/4,pgen_module/5,mk_var/1, un_hyphen_var/1]).
--export([gen_encode_constructed/4,gen_decode_constructed/4]).
-
-%% pgen(Erules, Module, TypeOrVal)
-%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module
-%% .hrl file is only generated if necessary
-%% Erules = per | ber | ber_bin | per_bin
-%% Module = atom()
-%% TypeOrVal = {TypeList,ValueList}
-%% TypeList = ValueList = [atom()]
-
-pgen(OutFile,Erules,Module,TypeOrVal) ->
- pgen_module(OutFile,Erules,Module,TypeOrVal,true).
-
-
-pgen_module(OutFile,Erules,Module,TypeOrVal,Indent) ->
- put(outfile,OutFile),
- HrlGenerated = asn1ct_gen:pgen_hrl(Erules,Module,TypeOrVal,Indent),
- asn1ct_name:start(),
- ErlFile = lists:concat([OutFile,".erl"]),
- Fid = asn1ct_gen:fopen(ErlFile,write),
- put(gen_file_out,Fid),
- asn1ct_gen:gen_head(Erules,Module,HrlGenerated),
- pgen_exports(Erules,Module,TypeOrVal),
- pgen_dispatcher(Erules,Module,TypeOrVal),
- pgen_info(Erules,Module),
- pgen_typeorval(wrap_ber(Erules),Module,TypeOrVal),
- pgen_partial_incomplete_decode(Erules),
-% gen_vars(asn1_db:mod_to_vars(Module)),
-% gen_tag_table(AllTypes),
- file:close(Fid),
- io:format("--~p--~n",[{generated,ErlFile}]).
-
-
-pgen_typeorval(Erules,Module,{Types,Values,_Ptypes,_Classes,Objects,ObjectSets}) ->
- pgen_types(Erules,Module,Types),
- pgen_values(Erules,Module,Values),
- pgen_objects(Erules,Module,Objects),
- pgen_objectsets(Erules,Module,ObjectSets),
- case catch lists:member(der,get(encoding_options)) of
- true ->
- pgen_check_defaultval(Erules,Module);
- _ -> ok
- end,
- pgen_partial_decode(Erules,Module).
-
-pgen_values(_,_,[]) ->
- true;
-pgen_values(Erules,Module,[H|T]) ->
- Valuedef = asn1_db:dbget(Module,H),
- gen_value(Valuedef),
- pgen_values(Erules,Module,T).
-
-pgen_types(_,Module,[]) ->
- gen_value_match(Module),
- true;
-pgen_types(Erules,Module,[H|T]) ->
- Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
- rt2ct_suffix(Erules)])),
- asn1ct_name:clear(),
- Typedef = asn1_db:dbget(Module,H),
- Rtmod:gen_encode(Erules,Typedef),
- asn1ct_name:clear(),
- Rtmod:gen_decode(Erules,Typedef),
- pgen_types(Erules,Module,T).
-
-pgen_objects(_,_,[]) ->
- true;
-pgen_objects(Erules,Module,[H|T]) ->
- Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
- rt2ct_suffix(Erules)])),
- asn1ct_name:clear(),
- Typedef = asn1_db:dbget(Module,H),
- Rtmod:gen_obj_code(Erules,Module,Typedef),
- pgen_objects(Erules,Module,T).
-
-pgen_objectsets(_,_,[]) ->
- true;
-pgen_objectsets(Erules,Module,[H|T]) ->
- Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
- rt2ct_suffix(Erules)])),
- asn1ct_name:clear(),
- TypeDef = asn1_db:dbget(Module,H),
- Rtmod:gen_objectset_code(Erules,TypeDef),
- pgen_objectsets(Erules,Module,T).
-
-pgen_check_defaultval(Erules,Module) ->
- CheckObjects = ets:tab2list(check_functions),
- case get(asndebug) of
- true ->
- FileName = lists:concat([Module,'.table']),
- {ok,IoDevice} = file:open(FileName,[write]),
- Fun =
- fun(X)->
- io:format(IoDevice,"~n~n************~n~n~p~n~n*****"
- "********~n~n",[X])
- end,
- lists:foreach(Fun,CheckObjects),
- file:close(IoDevice);
- _ -> ok
- end,
- gen_check_defaultval(Erules,Module,CheckObjects).
-
-pgen_partial_decode(Erules,Module) ->
- pgen_partial_inc_dec(Erules,Module),
- pgen_partial_dec(Erules,Module).
-
-pgen_partial_inc_dec(Erules,Module) ->
-% io:format("Start partial incomplete decode gen?~n"),
- case asn1ct:get_gen_state_field(inc_type_pattern) of
- undefined ->
-% io:format("Partial incomplete decode gen not started:�~w~n",[asn1ct:get_gen_state_field(active)]),
- ok;
-% [] ->
-% ok;
- ConfList ->
- PatternLists=lists:map(fun({_,P}) -> P end,ConfList),
- pgen_partial_inc_dec1(Erules,Module,PatternLists),
- gen_partial_inc_dec_refed_funcs(Erules)
- end.
-
-%% pgen_partial_inc_dec1 generates a function of the toptype in each
-%% of the partial incomplete decoded types.
-pgen_partial_inc_dec1(Erules,Module,[P|Ps]) ->
- Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
- rt2ct_suffix(Erules)])),
- TopTypeName = asn1ct:partial_inc_dec_toptype(P),
- TypeDef=asn1_db:dbget(Module,TopTypeName),
- asn1ct_name:clear(),
- asn1ct:update_gen_state(namelist,P),
- asn1ct:update_gen_state(active,true),
- asn1ct:update_gen_state(prefix,"dec-inc-"),
- Rtmod:gen_decode(Erules,TypeDef),
-%% asn1ct:update_gen_state(namelist,tl(P)), %%
- gen_dec_part_inner_constr(Erules,TypeDef,[TopTypeName]),
- pgen_partial_inc_dec1(Erules,Module,Ps);
-pgen_partial_inc_dec1(_,_,[]) ->
- ok.
-
-gen_partial_inc_dec_refed_funcs(Erule) when Erule == ber_bin_v2 ->
- Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erule),
- rt2ct_suffix(Erule)])),
- case asn1ct:next_refed_func() of
- [] ->
- ok;
- {#'Externaltypereference'{module=M,type=Name},Pattern} ->
- TypeDef = asn1_db:dbget(M,Name),
- asn1ct:update_gen_state(namelist,Pattern),
- Rtmod:gen_inc_decode(Erule,TypeDef),
- gen_dec_part_inner_constr(Erule,TypeDef,[Name]),
- gen_partial_inc_dec_refed_funcs(Erule);
- _ ->
- gen_partial_inc_dec_refed_funcs(Erule)
- end;
-gen_partial_inc_dec_refed_funcs(_) ->
- ok.
-
-pgen_partial_dec(_Erules,_Module) ->
- ok. %%%% implement later
-
-%% generate code for all inner types that are called from the top type
-%% of the partial incomplete decode
-gen_dec_part_inner_constr(Erules,TypeDef,TypeName) ->
- Def = TypeDef#typedef.typespec,
- InnerType = asn1ct_gen:get_inner(Def#type.def),
- case InnerType of
- 'SET' ->
- #'SET'{components=Components} = Def#type.def,
- gen_dec_part_inner_types(Erules,Components,TypeName);
- %% Continue generate the inner of each component
- 'SEQUENCE' ->
- #'SEQUENCE'{components=Components} = Def#type.def,
- gen_dec_part_inner_types(Erules,Components,TypeName);
- 'CHOICE' ->
- {_,Components} = Def#type.def,
- gen_dec_part_inner_types(Erules,Components,TypeName);
- 'SEQUENCE OF' ->
- %% this and next case must be the last component in the
- %% partial decode chain here. Not likely that this occur.
- {_,Type} = Def#type.def,
- NameSuffix = constructed_suffix(InnerType,Type#type.def),
- Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
- rt2ct_suffix(Erules)])),
- asn1ct_name:clear(),
- Rtmod:gen_decode(Erules,[NameSuffix|TypeName],Type);
-%% gen_types(Erules,[NameSuffix|Typename],Type);
- 'SET OF' ->
- {_,Type} = Def#type.def,
- NameSuffix = constructed_suffix(InnerType,Type#type.def),
- Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
- rt2ct_suffix(Erules)])),
- asn1ct_name:clear(),
- Rtmod:gen_decode(Erules,[NameSuffix|TypeName],Type);
- _ ->
- ok
- end.
-
-gen_dec_part_inner_types(Erules,[ComponentType|Rest],TypeName) ->
- Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
- rt2ct_suffix(Erules)])),
- asn1ct_name:clear(),
- Rtmod:gen_decode(Erules,TypeName,ComponentType),
- gen_dec_part_inner_types(Erules,Rest,TypeName);
-gen_dec_part_inner_types(Erules,{Comps1,Comps2},TypeName)
- when list(Comps1),list(Comps2) ->
- gen_dec_part_inner_types(Erules,Comps1 ++ Comps2,TypeName);
-gen_dec_part_inner_types(_,[],_) ->
- ok.
-
-
-pgen_partial_incomplete_decode(Erule) ->
- case asn1ct:get_gen_state_field(active) of
- true ->
- pgen_partial_incomplete_decode1(Erule),
- asn1ct:reset_gen_state();
- _ ->
- ok
- end.
-pgen_partial_incomplete_decode1(ber_bin_v2) ->
- case asn1ct:read_config_data(partial_incomplete_decode) of
- undefined ->
- ok;
- Data ->
- lists:foreach(fun emit_partial_incomplete_decode/1,Data)
- end,
- GeneratedFs= asn1ct:get_gen_state_field(gen_refed_funcs),
-% io:format("GeneratedFs :~n~p~n",[GeneratedFs]),
- gen_part_decode_funcs(GeneratedFs,0);
-pgen_partial_incomplete_decode1(_) -> ok.
-
-emit_partial_incomplete_decode({FuncName,TopTypeName,Pattern}) ->
- emit([{asis,FuncName},"(Bytes) ->",nl,
- " decode_partial_incomplete(",{asis,TopTypeName},",Bytes,",{asis,Pattern},").",nl]);
-emit_partial_incomplete_decode(D) ->
- throw({error,{asn1,{"bad data in asn1config file",D}}}).
-
-gen_part_decode_funcs([Data={Name,_,_,Type}|GeneratedFs],N) ->
- InnerType =
- case Type#type.def of
- #'ObjectClassFieldType'{type=OCFTType} ->
- OCFTType;
- _ ->
- get_inner(Type#type.def)
- end,
- WhatKind = type(InnerType),
- TypeName=list2name(Name),
- if
- N > 0 -> emit([";",nl]);
- true -> ok
- end,
- emit(["decode_inc_disp('",TypeName,"',Data) ->",nl]),
- gen_part_decode_funcs(WhatKind,TypeName,Data),
- gen_part_decode_funcs(GeneratedFs,N+1);
-gen_part_decode_funcs([_H|T],N) ->
- gen_part_decode_funcs(T,N);
-gen_part_decode_funcs([],N) ->
- if
- N > 0 ->
- .emit([".",nl]);
- true ->
- ok
- end.
-
-gen_part_decode_funcs(#'Externaltypereference'{module=M,type=T},
- _TypeName,Data) ->
- #typedef{typespec=TS} = asn1_db:dbget(M,T),
- InnerType =
- case TS#type.def of
- #'ObjectClassFieldType'{type=OCFTType} ->
- OCFTType;
- _ ->
- get_inner(TS#type.def)
- end,
- WhatKind = type(InnerType),
- gen_part_decode_funcs(WhatKind,[T],Data);
-gen_part_decode_funcs({constructed,bif},TypeName,
- {_Name,parts,Tag,_Type}) ->
- emit([" case Data of",nl,
- " L when list(L) ->",nl,
- " 'dec_",TypeName,"'(lists:map(fun(X)->element(1,?RT_BER:decode(X)) end,L),",{asis,Tag},");",nl,
- " _ ->",nl,
- " [Res] = 'dec_",TypeName,"'([Data],",{asis,Tag},"),",nl,
- " Res",nl,
- " end"]);
-gen_part_decode_funcs(WhatKind,_TypeName,{_Name,parts,_Tag,_Type}) ->
- throw({error,{asn1,{"only SEQUENCE OF/SET OF may have the partial incomplete directive 'parts'.",WhatKind}}});
-gen_part_decode_funcs({constructed,bif},TypeName,
- {_Name,undecoded,Tag,_Type}) ->
- emit([" 'dec_",TypeName,"'(Data,",{asis,Tag},")"]);
-gen_part_decode_funcs({primitive,bif},_TypeName,
- {_Name,undecoded,Tag,Type}) ->
- % Argument no 6 is 0, i.e. bit 6 for primitive encoding.
- asn1ct_gen_ber_bin_v2:gen_dec_prim(ber_bin_v2,Type,"Data",Tag,[],0,", mandatory, ");
-gen_part_decode_funcs(WhatKind,_TypeName,{_,Directive,_,_}) ->
- throw({error,{asn1,{"Not implemented yet",WhatKind," partial incomplete directive:",Directive}}}).
-
-gen_types(Erules,Tname,{RootList,ExtList}) when list(RootList) ->
- gen_types(Erules,Tname,RootList),
- gen_types(Erules,Tname,ExtList);
-gen_types(Erules,Tname,[{'EXTENSIONMARK',_,_}|Rest]) ->
- gen_types(Erules,Tname,Rest);
-gen_types(Erules,Tname,[ComponentType|Rest]) ->
- Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
- rt2ct_suffix(Erules)])),
- asn1ct_name:clear(),
- Rtmod:gen_encode(Erules,Tname,ComponentType),
- asn1ct_name:clear(),
- Rtmod:gen_decode(Erules,Tname,ComponentType),
- gen_types(Erules,Tname,Rest);
-gen_types(_,_,[]) ->
- true;
-gen_types(Erules,Tname,Type) when record(Type,type) ->
- Rtmod = list_to_atom(lists:concat(["asn1ct_gen_",erule(Erules),
- rt2ct_suffix(Erules)])),
- asn1ct_name:clear(),
- Rtmod:gen_encode(Erules,Tname,Type),
- asn1ct_name:clear(),
- Rtmod:gen_decode(Erules,Tname,Type).
-
-gen_value_match(Module) ->
- case get(value_match) of
- {true,Module} ->
- emit(["value_match([{Index,Cname}|Rest],Value) ->",nl,
- " Value2 =",nl,
- " case element(Index,Value) of",nl,
- " {Cname,Val2} -> Val2;",nl,
- " X -> X",nl,
- " end,",nl,
- " value_match(Rest,Value2);",nl,
- "value_match([],Value) ->",nl,
- " Value.",nl]);
- _ -> ok
- end,
- put(value_match,undefined).
-
-gen_check_defaultval(Erules,Module,[{Name,Type}|Rest]) ->
- gen_check_func(Name,Type),
- gen_check_defaultval(Erules,Module,Rest);
-gen_check_defaultval(_,_,[]) ->
- ok.
-
-gen_check_func(Name,FType = #type{def=Def}) ->
- emit({Name,"(V,asn1_DEFAULT) ->",nl," true;",nl}),
- emit({Name,"(V,V) ->",nl," true;",nl}),
- emit({Name,"(V,{_,V}) ->",nl," true;",nl}),
- case Def of
- {'SEQUENCE OF',Type} ->
- gen_check_sof(Name,'SEQOF',Type);
- {'SET OF',Type} ->
- gen_check_sof(Name,'SETOF',Type);
- #'SEQUENCE'{components=Components} ->
- gen_check_sequence(Name,Components);
- #'SET'{components=Components} ->
- gen_check_sequence(Name,Components);
- {'CHOICE',Components} ->
- gen_check_choice(Name,Components);
- #'Externaltypereference'{type=T} ->
- emit({Name,"(DefaultValue,Value) ->",nl}),
- emit({" ",list2name([T,check]),"(DefaultValue,Value).",nl});
- MaybePrim ->
- InnerType = get_inner(MaybePrim),
- case type(InnerType) of
- {primitive,bif} ->
- emit({Name,"(DefaultValue,Value) ->",nl," "}),
- gen_prim_check_call(InnerType,"DefaultValue","Value",
- FType),
- emit({".",nl,nl});
- _ ->
- throw({asn1_error,{unknown,type,MaybePrim}})
- end
- end.
-
-gen_check_sof(Name,SOF,Type) ->
- NewName = list2name([sorted,Name]),
- emit({Name,"(V1,V2) ->",nl}),
- emit({" ",NewName,"(lists:sort(V1),lists:sort(V2)).",nl,nl}),
- emit({NewName,"([],[]) ->",nl," true;",nl}),
- emit({NewName,"([DV|DVs],[V|Vs]) ->",nl," "}),
- InnerType = get_inner(Type#type.def),
- case type(InnerType) of
- {primitive,bif} ->
- gen_prim_check_call(InnerType,"DV","V",Type),
- emit({",",nl});
- {constructed,bif} ->
- emit({list2name([SOF,Name]),"(DV, V),",nl});
- #'Externaltypereference'{type=T} ->
- emit({list2name([T,check]),"(DV,V),",nl})
- end,
- emit({" ",NewName,"(DVs,Vs).",nl,nl}).
-
-gen_check_sequence(Name,Components) ->
- emit({Name,"(DefaultValue,Value) ->",nl}),
- gen_check_sequence(Name,Components,1).
-gen_check_sequence(Name,[#'ComponentType'{name=N,typespec=Type}|Cs],Num) ->
- InnerType = get_inner(Type#type.def),
-% NthDefV = lists:concat(["lists:nth(",Num,",DefaultValue)"]),
- NthDefV = ["element(",Num+1,",DefaultValue)"],
-% NthV = lists:concat(["lists:nth(",Num,",Value)"]),
- NthV = ["element(",Num+1,",Value)"],
- gen_check_func_call(Name,Type,InnerType,NthDefV,NthV,N),
- case Cs of
- [] ->
- emit({".",nl,nl});
- _ ->
- emit({",",nl}),
- gen_check_sequence(Name,Cs,Num+1)
- end;
-gen_check_sequence(_,[],_) ->
- ok.
-
-gen_check_choice(Name,CList=[#'ComponentType'{}|_Cs]) ->
- emit({Name,"({Id,DefaultValue},{Id,Value}) ->",nl}),
- emit({" case Id of",nl}),
- gen_check_choice_components(Name,CList,1).
-
-gen_check_choice_components(_,[],_)->
- ok;
-gen_check_choice_components(Name,[#'ComponentType'{name=N,typespec=Type}|
- Cs],Num) ->
- Ind6 = " ",
- InnerType = get_inner(Type#type.def),
-% DefVal = ["element(2,lists:nth(",Num,",DefaultValue))"],
- emit({Ind6,N," ->",nl,Ind6}),
- gen_check_func_call(Name,Type,InnerType,{var,"defaultValue"},
- {var,"value"},N),
- case Cs of
- [] ->
- emit({nl," end.",nl,nl});
- _ ->
- emit({";",nl}),
- gen_check_choice_components(Name,Cs,Num+1)
- end.
-
-gen_check_func_call(Name,Type,InnerType,DefVal,Val,N) ->
- case type(InnerType) of
- {primitive,bif} ->
- emit(" "),
- gen_prim_check_call(InnerType,DefVal,Val,Type);
- #'Externaltypereference'{type=T} ->
- emit({" ",list2name([T,check]),"(",DefVal,",",Val,")"});
- _ ->
- emit({" ",list2name([N,Name]),"(",DefVal,",",Val,")"})
- end.
-
-
-%% VARIOUS GENERATOR STUFF
-%% *************************************************
-%%**************************************************
-
-mk_var(X) when atom(X) ->
- list_to_atom(mk_var(atom_to_list(X)));
-
-mk_var([H|T]) ->
- [H-32|T].
-
-%% Since hyphens are allowed in ASN.1 names, it may occur in a
-%% variable to. Turn a hyphen into a under-score sign.
-un_hyphen_var(X) when atom(X) ->
- list_to_atom(un_hyphen_var(atom_to_list(X)));
-un_hyphen_var([45|T]) ->
- [95|un_hyphen_var(T)];
-un_hyphen_var([H|T]) ->
- [H|un_hyphen_var(T)];
-un_hyphen_var([]) ->
- [].
-
-%% Generate value functions ***************
-%% ****************************************
-%% Generates a function 'V'/0 for each Value V defined in the ASN.1 module
-%% the function returns the value in an Erlang representation which can be
-%% used as input to the runtime encode functions
-
-gen_value(Value) when record(Value,valuedef) ->
-%% io:format(" ~w ",[Value#valuedef.name]),
- emit({"'",Value#valuedef.name,"'() ->",nl}),
- V = Value#valuedef.value,
- emit([{asis,V},".",nl,nl]).
-
-gen_encode_constructed(Erules,Typename,InnerType,D) when record(D,type) ->
-
- Rtmod = list_to_atom(lists:concat(["asn1ct_constructed_",erule(Erules)])),
- case InnerType of
- 'SET' ->
- Rtmod:gen_encode_set(Erules,Typename,D),
- #'SET'{components=Components} = D#type.def,
- gen_types(Erules,Typename,Components);
- 'SEQUENCE' ->
- Rtmod:gen_encode_sequence(Erules,Typename,D),
- #'SEQUENCE'{components=Components} = D#type.def,
- gen_types(Erules,Typename,Components);
- 'CHOICE' ->
- Rtmod:gen_encode_choice(Erules,Typename,D),
- {_,Components} = D#type.def,
- gen_types(Erules,Typename,Components);
- 'SEQUENCE OF' ->
- Rtmod:gen_encode_sof(Erules,Typename,InnerType,D),
- {_,Type} = D#type.def,
- NameSuffix = asn1ct_gen:constructed_suffix(InnerType,Type#type.def),
- gen_types(Erules,[NameSuffix|Typename],Type);
- 'SET OF' ->
- Rtmod:gen_encode_sof(Erules,Typename,InnerType,D),
- {_,Type} = D#type.def,
- NameSuffix = asn1ct_gen:constructed_suffix(InnerType,Type#type.def),
- gen_types(Erules,[NameSuffix|Typename],Type);
- _ ->
- exit({nyi,InnerType})
- end;
-gen_encode_constructed(Erules,Typename,InnerType,D)
- when record(D,typedef) ->
- gen_encode_constructed(Erules,Typename,InnerType,D#typedef.typespec).
-
-gen_decode_constructed(Erules,Typename,InnerType,D) when record(D,type) ->
- Rtmod = list_to_atom(lists:concat(["asn1ct_constructed_",erule(Erules)])),
- asn1ct:step_in_constructed(), %% updates namelist for incomplete
- %% partial decode
- case InnerType of
- 'SET' ->
- Rtmod:gen_decode_set(Erules,Typename,D);
- 'SEQUENCE' ->
- Rtmod:gen_decode_sequence(Erules,Typename,D);
- 'CHOICE' ->
- Rtmod:gen_decode_choice(Erules,Typename,D);
- 'SEQUENCE OF' ->
- Rtmod:gen_decode_sof(Erules,Typename,InnerType,D);
- 'SET OF' ->
- Rtmod:gen_decode_sof(Erules,Typename,InnerType,D);
- _ ->
- exit({nyi,InnerType})
- end;
-
-
-gen_decode_constructed(Erules,Typename,InnerType,D) when record(D,typedef) ->
- gen_decode_constructed(Erules,Typename,InnerType,D#typedef.typespec).
-
-
-pgen_exports(Erules,_Module,{Types,Values,_,_,Objects,ObjectSets}) ->
- emit({"-export([encoding_rule/0]).",nl}),
- case Types of
- [] -> ok;
- _ ->
- emit({"-export([",nl}),
- case Erules of
- ber ->
- gen_exports1(Types,"enc_",2);
- ber_bin ->
- gen_exports1(Types,"enc_",2);
- ber_bin_v2 ->
- gen_exports1(Types,"enc_",2);
- _ ->
- gen_exports1(Types,"enc_",1)
- end,
- emit({"-export([",nl}),
- gen_exports1(Types,"dec_",2),
- case Erules of
- ber ->
- emit({"-export([",nl}),
- gen_exports1(Types,"dec_",3);
- ber_bin ->
- emit({"-export([",nl}),
- gen_exports1(Types,"dec_",3);
- ber_bin_v2 ->
- emit({"-export([",nl}),
- gen_exports1(Types,"dec_",2);
- _ -> ok
- end
- end,
- case Values of
- [] -> ok;
- _ ->
- emit({"-export([",nl}),
- gen_exports1(Values,"",0)
- end,
- case Objects of
- [] -> ok;
- _ ->
- case erule(Erules) of
- per ->
- emit({"-export([",nl}),
- gen_exports1(Objects,"enc_",3),
- emit({"-export([",nl}),
- gen_exports1(Objects,"dec_",4);
- ber_bin_v2 ->
- emit({"-export([",nl}),
- gen_exports1(Objects,"enc_",3),
- emit({"-export([",nl}),
- gen_exports1(Objects,"dec_",3);
- _ ->
- emit({"-export([",nl}),
- gen_exports1(Objects,"enc_",4),
- emit({"-export([",nl}),
- gen_exports1(Objects,"dec_",4)
- end
- end,
- case ObjectSets of
- [] -> ok;
- _ ->
- emit({"-export([",nl}),
- gen_exports1(ObjectSets,"getenc_",2),
- emit({"-export([",nl}),
- gen_exports1(ObjectSets,"getdec_",2)
- end,
- emit({"-export([info/0]).",nl}),
- gen_partial_inc_decode_exports(),
- emit({nl,nl}).
-
-gen_exports1([F1,F2|T],Prefix,Arity) ->
- emit({"'",Prefix,F1,"'/",Arity,com,nl}),
- gen_exports1([F2|T],Prefix,Arity);
-gen_exports1([Flast|_T],Prefix,Arity) ->
- emit({"'",Prefix,Flast,"'/",Arity,nl,"]).",nl,nl}).
-
-gen_partial_inc_decode_exports() ->
- case {asn1ct:read_config_data(partial_incomplete_decode),
- asn1ct:get_gen_state_field(inc_type_pattern)} of
- {undefined,_} ->
- ok;
- {_,undefined} ->
- ok;
- {Data,_} ->
- gen_partial_inc_decode_exports(Data),
- emit("-export([decode_part/2]).")
- end.
-gen_partial_inc_decode_exports([]) ->
- ok;
-gen_partial_inc_decode_exports([{Name,_,_}|Rest]) ->
- emit(["-export([",Name,"/1"]),
- gen_partial_inc_decode_exports1(Rest);
-gen_partial_inc_decode_exports([_|Rest]) ->
- gen_partial_inc_decode_exports(Rest).
-
-gen_partial_inc_decode_exports1([]) ->
- emit(["]).",nl]);
-gen_partial_inc_decode_exports1([{Name,_,_}|Rest]) ->
- emit([", ",Name,"/1"]),
- gen_partial_inc_decode_exports1(Rest);
-gen_partial_inc_decode_exports1([_|Rest]) ->
- gen_partial_inc_decode_exports1(Rest).
-
-pgen_dispatcher(Erules,_Module,{[],_Values,_,_,_Objects,_ObjectSets}) ->
- emit(["encoding_rule() ->",nl]),
- emit([{asis,Erules},".",nl,nl]);
-pgen_dispatcher(Erules,_Module,{Types,_Values,_,_,_Objects,_ObjectSets}) ->
- emit(["-export([encode/2,decode/2,encode_disp/2,decode_disp/2]).",nl,nl]),
- emit(["encoding_rule() ->",nl]),
- emit([" ",{asis,Erules},".",nl,nl]),
- Call = case Erules of
- per -> "?RT_PER:complete(encode_disp(Type,Data))";
- per_bin -> "?RT_PER:complete(encode_disp(Type,Data))";
- ber -> "encode_disp(Type,Data)";
- ber_bin -> "encode_disp(Type,Data)";
- ber_bin_v2 -> "encode_disp(Type,Data)"
- end,
- EncWrap = case Erules of
- ber -> "wrap_encode(Bytes)";
- _ -> "Bytes"
- end,
- emit(["encode(Type,Data) ->",nl,
- "case catch ",Call," of",nl,
- " {'EXIT',{error,Reason}} ->",nl,
- " {error,Reason};",nl,
- " {'EXIT',Reason} ->",nl,
- " {error,{asn1,Reason}};",nl,
- " {Bytes,_Len} ->",nl,
- " {ok,",EncWrap,"};",nl,
- " Bytes ->",nl,
- " {ok,",EncWrap,"}",nl,
- "end.",nl,nl]),
-
- case Erules of
- ber_bin_v2 ->
- emit(["decode(Type,Data0) ->",nl]),
- emit(["{Data,_RestBin} = ?RT_BER:decode(Data0",driver_parameter(),"),",nl]);
- _ ->
- emit(["decode(Type,Data) ->",nl])
- end,
- DecWrap = case Erules of
- ber -> "wrap_decode(Data)";
- _ -> "Data"
- end,
-
- emit(["case catch decode_disp(Type,",DecWrap,") of",nl,
- " {'EXIT',{error,Reason}} ->",nl,
- " {error,Reason};",nl,
- " {'EXIT',Reason} ->",nl,
- " {error,{asn1,Reason}};",nl]),
- case Erules of
- ber_bin_v2 ->
- emit([" Result ->",nl,
- " {ok,Result}",nl]);
- _ ->
- emit([" {X,_Rest} ->",nl,
- " {ok,X};",nl,
- " {X,_Rest,_Len} ->",nl,
- " {ok,X}",nl])
- end,
- emit(["end.",nl,nl]),
-
- gen_decode_partial_incomplete(Erules),
-
- case Types of
- [] -> ok;
- _ ->
- case Erules of
- ber ->
- gen_dispatcher(Types,"encode_disp","enc_",",[]"),
- gen_dispatcher(Types,"decode_disp","dec_",",mandatory");
- ber_bin ->
- gen_dispatcher(Types,"encode_disp","enc_",",[]"),
- gen_dispatcher(Types,"decode_disp","dec_",",mandatory");
- ber_bin_v2 ->
- gen_dispatcher(Types,"encode_disp","enc_",""),
- gen_dispatcher(Types,"decode_disp","dec_",""),
- gen_partial_inc_dispatcher();
- _PerOrPer_bin ->
- gen_dispatcher(Types,"encode_disp","enc_",""),
- gen_dispatcher(Types,"decode_disp","dec_",",mandatory")
- end,
- emit([nl])
- end,
- case Erules of
- ber ->
- gen_wrapper();
- _ -> ok
- end,
- emit({nl,nl}).
-
-
-gen_decode_partial_incomplete(Erule) when Erule == ber;Erule==ber_bin;
- Erule==ber_bin_v2 ->
- case {asn1ct:read_config_data(partial_incomplete_decode),
- asn1ct:get_gen_state_field(inc_type_pattern)} of
- {undefined,_} ->
- ok;
- {_,undefined} ->
- ok;
- _ ->
- case Erule of
- ber_bin_v2 ->
- EmitCaseClauses =
- fun() ->
- emit([" {'EXIT',{error,Reason}} ->",nl,
- " {error,Reason};",nl,
- " {'EXIT',Reason} ->",nl,
- " {error,{asn1,Reason}};",nl,
- " Result ->",nl,
- " {ok,Result}",nl,
- " end.",nl,nl])
- end,
- emit(["decode_partial_incomplete(Type,Data0,",
- "Pattern) ->",nl]),
- emit([" {Data,_RestBin} =",nl,
- " ?RT_BER:decode_primitive_",
- "incomplete(Pattern,Data0),",nl,
- " case catch decode_partial_inc_disp(Type,",
- "Data) of",nl]),
- EmitCaseClauses(),
- emit(["decode_part(Type,Data0) ->",nl,
- " {Data,_RestBin} = ?RT_BER:decode(Data0),",nl,
- " case catch decode_inc_disp(Type,Data) of",nl]),
- EmitCaseClauses();
- _ -> ok % add later
- end
- end;
-gen_decode_partial_incomplete(_Erule) ->
- ok.
-
-gen_partial_inc_dispatcher() ->
- case {asn1ct:read_config_data(partial_incomplete_decode),
- asn1ct:get_gen_state_field(inc_type_pattern)} of
- {undefined,_} ->
- ok;
- {_,undefined} ->
- ok;
- {Data,_} ->
- gen_partial_inc_dispatcher(Data)
- end.
-gen_partial_inc_dispatcher([{_FuncName,TopType,_Pattern}|Rest]) ->
- emit(["decode_partial_inc_disp(",{asis,TopType},",Data) ->",nl,
- " ",{asis,list_to_atom(lists:concat([dec,"-inc-",TopType]))},
- "(Data);",nl]),
- gen_partial_inc_dispatcher(Rest);
-gen_partial_inc_dispatcher([]) ->
- emit(["decode_partial_inc_disp(Type,_Data) ->",nl,
- " exit({error,{asn1,{undefined_type,Type}}}).",nl]).
-
-driver_parameter() ->
- Options = get(encoding_options),
- case lists:member(driver,Options) of
- true ->
- ",driver";
- _ -> ""
- end.
-
-gen_wrapper() ->
- emit(["wrap_encode(Bytes) when list(Bytes) ->",nl,
- " binary_to_list(list_to_binary(Bytes));",nl,
- "wrap_encode(Bytes) when binary(Bytes) ->",nl,
- " binary_to_list(Bytes);",nl,
- "wrap_encode(Bytes) -> Bytes.",nl,nl]),
- emit(["wrap_decode(Bytes) when list(Bytes) ->",nl,
- " list_to_binary(Bytes);",nl,
- "wrap_decode(Bytes) -> Bytes.",nl]).
-
-gen_dispatcher([F1,F2|T],FuncName,Prefix,ExtraArg) ->
- emit([FuncName,"('",F1,"',Data) -> '",Prefix,F1,"'(Data",ExtraArg,")",";",nl]),
- gen_dispatcher([F2|T],FuncName,Prefix,ExtraArg);
-gen_dispatcher([Flast|_T],FuncName,Prefix,ExtraArg) ->
- emit([FuncName,"('",Flast,"',Data) -> '",Prefix,Flast,"'(Data",ExtraArg,")",";",nl]),
- emit([FuncName,"(","Type",",_Data) -> exit({error,{asn1,{undefined_type,Type}}}).",nl,nl,nl]).
-
-pgen_info(_Erules,Module) ->
- Options = get(encoding_options),
- emit({"info() ->",nl,
- " [{vsn,'",asn1ct:vsn(),"'},",
- " {module,'",Module,"'},",
- " {options,",io_lib:format("~p",[Options]),"}].",nl}).
-
-open_hrl(OutFile,Module) ->
- File = lists:concat([OutFile,".hrl"]),
- Fid = fopen(File,write),
- put(gen_file_out,Fid),
- gen_hrlhead(Module).
-
-%% EMIT functions ************************
-%% ***************************************
-
- % debug generation
-demit(Term) ->
- case get(asndebug) of
- true -> emit(Term);
- _ ->true
- end.
-
- % always generation
-
-emit({external,_M,T}) ->
- emit(T);
-
-emit({prev,Variable}) when atom(Variable) ->
- emit({var,asn1ct_name:prev(Variable)});
-
-emit({next,Variable}) when atom(Variable) ->
- emit({var,asn1ct_name:next(Variable)});
-
-emit({curr,Variable}) when atom(Variable) ->
- emit({var,asn1ct_name:curr(Variable)});
-
-emit({var,Variable}) when atom(Variable) ->
- [Head|V] = atom_to_list(Variable),
- emit([Head-32|V]);
-
-emit({var,Variable}) ->
- [Head|V] = Variable,
- emit([Head-32|V]);
-
-emit({asis,What}) ->
- format(get(gen_file_out),"~w",[What]);
-
-emit(nl) ->
- nl(get(gen_file_out));
-
-emit(com) ->
- emit(",");
-
-emit(tab) ->
- put_chars(get(gen_file_out)," ");
-
-emit(What) when integer(What) ->
- put_chars(get(gen_file_out),integer_to_list(What));
-
-emit(What) when list(What), integer(hd(What)) ->
- put_chars(get(gen_file_out),What);
-
-emit(What) when atom(What) ->
- put_chars(get(gen_file_out),atom_to_list(What));
-
-emit(What) when tuple(What) ->
- emit_parts(tuple_to_list(What));
-
-emit(What) when list(What) ->
- emit_parts(What);
-
-emit(X) ->
- exit({'cant emit ',X}).
-
-emit_parts([]) -> true;
-emit_parts([H|T]) ->
- emit(H),
- emit_parts(T).
-
-format(undefined,X,Y) ->
- io:format(X,Y);
-format(X,Y,Z) ->
- io:format(X,Y,Z).
-
-nl(undefined) -> io:nl();
-nl(X) -> io:nl(X).
-
-put_chars(undefined,X) ->
- io:put_chars(X);
-put_chars(Y,X) ->
- io:put_chars(Y,X).
-
-fopen(F, Mode) ->
- case file:open(F, [Mode]) of
- {ok, Fd} ->
- Fd;
- {error, Reason} ->
- io:format("** Can't open file ~p ~n", [F]),
- exit({error,Reason})
- end.
-
-pgen_hrl(Erules,Module,TypeOrVal,_Indent) ->
- put(currmod,Module),
- {Types,Values,Ptypes,_,_,_} = TypeOrVal,
- Ret =
- case pgen_hrltypes(Erules,Module,Ptypes++Types,0) of
- 0 ->
- case Values of
- [] ->
- 0;
- _ ->
- open_hrl(get(outfile),get(currmod)),
- pgen_macros(Erules,Module,Values),
- 1
- end;
- X ->
- pgen_macros(Erules,Module,Values),
- X
- end,
- case Ret of
- 0 ->
- 0;
- Y ->
- Fid = get(gen_file_out),
- file:close(Fid),
- io:format("--~p--~n",
- [{generated,lists:concat([get(outfile),".hrl"])}]),
- Y
- end.
-
-pgen_macros(_,_,[]) ->
- true;
-pgen_macros(Erules,Module,[H|T]) ->
- Valuedef = asn1_db:dbget(Module,H),
- gen_macro(Valuedef),
- pgen_macros(Erules,Module,T).
-
-pgen_hrltypes(_,_,[],NumRecords) ->
- NumRecords;
-pgen_hrltypes(Erules,Module,[H|T],NumRecords) ->
-% io:format("records = ~p~n",NumRecords),
- Typedef = asn1_db:dbget(Module,H),
- AddNumRecords = gen_record(Typedef,NumRecords),
- pgen_hrltypes(Erules,Module,T,NumRecords+AddNumRecords).
-
-
-%% Generates a macro for value Value defined in the ASN.1 module
-gen_macro(Value) when record(Value,valuedef) ->
- emit({"-define('",Value#valuedef.name,"', ",
- {asis,Value#valuedef.value},").",nl}).
-
-%% Generate record functions **************
-%% Generates an Erlang record for each named and unnamed SEQUENCE and SET in the ASN.1
-%% module. If no SEQUENCE or SET is found there is no .hrl file generated
-
-
-gen_record(Tdef,NumRecords) when record(Tdef,typedef) ->
- Name = [Tdef#typedef.name],
- Type = Tdef#typedef.typespec,
- gen_record(type,Name,Type,NumRecords);
-
-gen_record(Tdef,NumRecords) when record(Tdef,ptypedef) ->
- Name = [Tdef#ptypedef.name],
- Type = Tdef#ptypedef.typespec,
- gen_record(ptype,Name,Type,NumRecords).
-
-gen_record(TorPtype,Name,[#'ComponentType'{name=Cname,typespec=Type}|T],Num) ->
- Num2 = gen_record(TorPtype,[Cname|Name],Type,Num),
- gen_record(TorPtype,Name,T,Num2);
-gen_record(TorPtype,Name,{Clist1,Clist2},Num) when list(Clist1), list(Clist2) ->
- gen_record(TorPtype,Name,Clist1++Clist2,Num);
-gen_record(TorPtype,Name,[_|T],Num) -> % skip EXTENSIONMARK
- gen_record(TorPtype,Name,T,Num);
-gen_record(_TorPtype,_Name,[],Num) ->
- Num;
-
-gen_record(TorPtype,Name,Type,Num) when record(Type,type) ->
- Def = Type#type.def,
- Rec = case Def of
- Seq when record(Seq,'SEQUENCE') ->
- case Seq#'SEQUENCE'.pname of
- false ->
- {record,Seq#'SEQUENCE'.components};
- _Pname when TorPtype == type ->
- false;
- _ ->
- {record,Seq#'SEQUENCE'.components}
- end;
- Set when record(Set,'SET') ->
- case Set#'SET'.pname of
- false ->
- {record,Set#'SET'.components};
- _Pname when TorPtype == type ->
- false;
- _ ->
- {record,Set#'SET'.components}
- end;
-% {'SET',{_,_CompList}} ->
-% {record,_CompList};
- {'CHOICE',_CompList} -> {inner,Def};
- {'SEQUENCE OF',_CompList} -> {['SEQOF'|Name],Def};
- {'SET OF',_CompList} -> {['SETOF'|Name],Def};
- _ -> false
- end,
- case Rec of
- false -> Num;
- {record,CompList} ->
- case Num of
- 0 -> open_hrl(get(outfile),get(currmod));
- _ -> true
- end,
- emit({"-record('",list2name(Name),"',{",nl}),
- RootList = case CompList of
- _ when list(CompList) ->
- CompList;
- {_Rl,_} -> _Rl
- end,
- gen_record2(Name,'SEQUENCE',RootList),
- NewCompList =
- case CompList of
- {CompList1,[]} ->
- emit({"}). % with extension mark",nl,nl}),
- CompList1;
- {Tr,ExtensionList2} ->
- case Tr of
- [] -> true;
- _ -> emit({",",nl})
- end,
- emit({"%% with extensions",nl}),
- gen_record2(Name, 'SEQUENCE', ExtensionList2,
- "", ext),
- emit({"}).",nl,nl}),
- Tr ++ ExtensionList2;
- _ ->
- emit({"}).",nl,nl}),
- CompList
- end,
- gen_record(TorPtype,Name,NewCompList,Num+1);
- {inner,{'CHOICE', CompList}} ->
- gen_record(TorPtype,Name,CompList,Num);
- {NewName,{_, CompList}} ->
- gen_record(TorPtype,NewName,CompList,Num)
- end;
-gen_record(_,_,_,NumRecords) -> % skip CLASS etc for now.
- NumRecords.
-
-gen_head(Erules,Mod,Hrl) ->
- {Rtmac,Rtmod} = case Erules of
- per ->
- emit({"%% Generated by the Erlang ASN.1 PER-"
- "compiler version:",asn1ct:vsn(),nl}),
- {"RT_PER",?RT_PER};
- ber ->
- emit({"%% Generated by the Erlang ASN.1 BER-"
- "compiler version:",asn1ct:vsn(),nl}),
- {"RT_BER",?RT_BER_BIN};
- per_bin ->
- emit({"%% Generated by the Erlang ASN.1 BER-"
- "compiler version, utilizing bit-syntax:",
- asn1ct:vsn(),nl}),
- %% temporary code to enable rt2ct optimization
- Options = get(encoding_options),
- case lists:member(optimize,Options) of
- true -> {"RT_PER","asn1rt_per_bin_rt2ct"};
- _ ->
- {"RT_PER",?RT_PER_BIN}
- end;
- ber_bin ->
- emit({"%% Generated by the Erlang ASN.1 BER-"
- "compiler version, utilizing bit-syntax:",
- asn1ct:vsn(),nl}),
- {"RT_BER",?RT_BER_BIN};
- ber_bin_v2 ->
- emit({"%% Generated by the Erlang ASN.1 BER_V2-"
- "compiler version, utilizing bit-syntax:",
- asn1ct:vsn(),nl}),
- {"RT_BER","asn1rt_ber_bin_v2"}
- end,
- emit({"%% Purpose: encoder and decoder to the types in mod ",Mod,nl,nl}),
- emit({"-module('",Mod,"').",nl}),
- put(currmod,Mod),
- %emit({"-compile(export_all).",nl}),
- case Hrl of
- 0 -> true;
- _ ->
- emit({"-include(\"",Mod,".hrl\").",nl})
- end,
- emit(["-define('",Rtmac,"',",Rtmod,").",nl]).
-
-
-gen_hrlhead(Mod) ->
- emit({"%% Generated by the Erlang ASN.1 compiler version:",asn1ct:vsn(),nl}),
- emit({"%% Purpose: Erlang record definitions for each named and unnamed",nl}),
- emit({"%% SEQUENCE and SET, and macro definitions for each value",nl}),
- emit({"%% definition,in module ",Mod,nl,nl}),
- emit({nl,nl}).
-
-gen_record2(Name,SeqOrSet,Comps) ->
- gen_record2(Name,SeqOrSet,Comps,"",noext).
-
-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,
- emit(Com),
- emit({asis,Cname}),
- gen_record_default(H, Extension);
-gen_record2(Name,SeqOrSet,[H|T],Com, Extension) ->
- #'ComponentType'{name=Cname} = H,
- emit(Com),
- emit({asis,Cname}),
- gen_record_default(H, Extension),
-% emit(", "),
- gen_record2(Name,SeqOrSet,T,", ", Extension).
-
-%gen_record_default(C, ext) ->
-% emit(" = asn1_NOEXTVALUE");
-gen_record_default(#'ComponentType'{prop='OPTIONAL'}, _)->
- emit(" = asn1_NOVALUE");
-gen_record_default(#'ComponentType'{prop={'DEFAULT',_}}, _)->
- emit(" = asn1_DEFAULT");
-gen_record_default(_, _) ->
- true.
-
-gen_check_call(TopType,Cname,Type,InnerType,WhatKind,DefaultValue,Element) ->
- case WhatKind of
- {primitive,bif} ->
- gen_prim_check_call(InnerType,DefaultValue,Element,Type);
- #'Externaltypereference'{module=M,type=T} ->
- %% generate function call
- Name = list2name([T,check]),
- emit({"'",Name,"'(",DefaultValue,", ",Element,")"}),
- %% insert in ets table and do look ahead check
- Typedef = asn1_db:dbget(M,T),
- RefType = Typedef#typedef.typespec,
- InType = asn1ct_gen:get_inner(RefType#type.def),
- case insert_once(check_functions,{Name,RefType}) of
- true ->
- lookahead_innertype([T],InType,RefType);
-% case asn1ct_gen:type(InType) of
-% {constructed,bif} ->
-% lookahead_innertype([T],InType,RefType);
-% #'Externaltypereference'{type=TNew} ->
-% lookahead_innertype([TNew],InType,RefType);
-% _ ->
-% ok
-% end;
- _ ->
- ok
- end;
- {constructed,bif} ->
- NameList = [Cname|TopType],
- Name = list2name(NameList ++ [check]),
- emit({"'",Name,"'(",DefaultValue,", ",Element,")"}),
- ets:insert(check_functions,{Name,Type}),
- %% Must look for check functions in InnerType,
- %% that may be referenced or internal defined
- %% constructed types not used elsewhere.
- lookahead_innertype(NameList,InnerType,Type)
- end.
-
-gen_prim_check_call(PrimType,DefaultValue,Element,Type) ->
- case unify_if_string(PrimType) of
- 'BOOLEAN' ->
- emit({"asn1rt_check:check_bool(",DefaultValue,", ",
- Element,")"});
- 'INTEGER' ->
- NNL =
- case Type#type.def of
- {_,NamedNumberList} -> NamedNumberList;
- _ -> []
- end,
- emit({"asn1rt_check:check_int(",DefaultValue,", ",
- Element,", ",{asis,NNL},")"});
- 'BIT STRING' ->
- {_,NBL} = Type#type.def,
- emit({"asn1rt_check:check_bitstring(",DefaultValue,", ",
- Element,", ",{asis,NBL},")"});
- 'OCTET STRING' ->
- emit({"asn1rt_check:check_octetstring(",DefaultValue,", ",
- Element,")"});
- 'NULL' ->
- emit({"asn1rt_check:check_null(",DefaultValue,", ",
- Element,")"});
- 'OBJECT IDENTIFIER' ->
- emit({"asn1rt_check:check_objectidentifier(",DefaultValue,
- ", ",Element,")"});
- 'ObjectDescriptor' ->
- emit({"asn1rt_check:check_objectdescriptor(",DefaultValue,
- ", ",Element,")"});
- 'REAL' ->
- emit({"asn1rt_check:check_real(",DefaultValue,
- ", ",Element,")"});
- 'ENUMERATED' ->
- {_,Enumerations} = Type#type.def,
- emit({"asn1rt_check:check_enum(",DefaultValue,
- ", ",Element,", ",{asis,Enumerations},")"});
- restrictedstring ->
- emit({"asn1rt_check:check_restrictedstring(",DefaultValue,
- ", ",Element,")"})
- end.
-
-%% lokahead_innertype/3 traverses Type and checks if check functions
-%% have to be generated, i.e. for all constructed or referenced types.
-lookahead_innertype(Name,'SEQUENCE',Type) ->
- Components = (Type#type.def)#'SEQUENCE'.components,
- lookahead_components(Name,Components);
-lookahead_innertype(Name,'SET',Type) ->
- Components = (Type#type.def)#'SET'.components,
- lookahead_components(Name,Components);
-lookahead_innertype(Name,'CHOICE',Type) ->
- {_,Components} = Type#type.def,
- lookahead_components(Name,Components);
-lookahead_innertype(Name,'SEQUENCE OF',SeqOf) ->
- lookahead_sof(Name,'SEQOF',SeqOf);
-lookahead_innertype(Name,'SET OF',SeqOf) ->
- lookahead_sof(Name,'SETOF',SeqOf);
-lookahead_innertype(_Name,#'Externaltypereference'{module=M,type=T},_) ->
- Typedef = asn1_db:dbget(M,T),
- RefType = Typedef#typedef.typespec,
- InType = asn1ct_gen:get_inner(RefType#type.def),
- case type(InType) of
- {constructed,bif} ->
- NewName = list2name([T,check]),
- case insert_once(check_functions,{NewName,RefType}) of
- true ->
- lookahead_innertype([T],InType,RefType);
- _ ->
- ok
- end;
- #'Externaltypereference'{} ->
- NewName = list2name([T,check]),
- case insert_once(check_functions,{NewName,RefType}) of
- true ->
- lookahead_innertype([T],InType,RefType);
- _ ->
- ok
- end;
- _ ->
- ok
- end;
-% case insert_once(check_functions,{list2name(Name++[check]),Type}) of
-% true ->
-% InnerType = asn1ct_gen:get_inner(Type#type.def),
-% case asn1ct_gen:type(InnerType) of
-% {constructed,bif} ->
-% lookahead_innertype([T],InnerType,Type);
-% #'Externaltypereference'{type=TNew} ->
-% lookahead_innertype([TNew],InnerType,Type);
-% _ ->
-% ok
-% end;
-% _ ->
-% ok
-% end;
-lookahead_innertype(_,_,_) ->
- ok.
-
-lookahead_components(_,[]) -> ok;
-lookahead_components(Name,[C|Cs]) ->
- #'ComponentType'{name=Cname,typespec=Type} = C,
- InType = asn1ct_gen:get_inner(Type#type.def),
- case asn1ct_gen:type(InType) of
- {constructed,bif} ->
- case insert_once(check_functions,
- {list2name([Cname|Name] ++ [check]),Type}) of
- true ->
- lookahead_innertype([Cname|Name],InType,Type);
- _ ->
- ok
- end;
- #'Externaltypereference'{module=RefMod,type=RefName} ->
- Typedef = asn1_db:dbget(RefMod,RefName),
- RefType = Typedef#typedef.typespec,
- case insert_once(check_functions,{list2name([RefName,check]),
- RefType}) of
- true ->
- lookahead_innertype([RefName],InType,RefType);
- _ ->
- ok
- end;
- _ ->
- ok
- end,
- lookahead_components(Name,Cs).
-
-lookahead_sof(Name,SOF,SOFType) ->
- Type = case SOFType#type.def of
- {_,_Type} -> _Type;
- _Type -> _Type
- end,
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- %% this is if a constructed type is defined in
- %% the SEQUENCE OF type
- NameList = [SOF|Name],
- insert_once(check_functions,
- {list2name(NameList ++ [check]),Type}),
- lookahead_innertype(NameList,InnerType,Type);
- #'Externaltypereference'{module=M,type=T} ->
- Typedef = asn1_db:dbget(M,T),
- RefType = Typedef#typedef.typespec,
- InType = get_inner(RefType#type.def),
- case insert_once(check_functions,
- {list2name([T,check]),RefType}) of
- true ->
- lookahead_innertype([T],InType,RefType);
- _ ->
- ok
- end;
- _ ->
- ok
- end.
-
-
-insert_once(Table,Object) ->
- case ets:lookup(Table,element(1,Object)) of
- [] ->
- ets:insert(Table,Object); %returns true
- _ -> false
- end.
-
-unify_if_string(PrimType) ->
- case PrimType of
- 'NumericString' ->
- restrictedstring;
- 'PrintableString' ->
- restrictedstring;
- 'TeletexString' ->
- restrictedstring;
- 'VideotexString' ->
- restrictedstring;
- 'IA5String' ->
- restrictedstring;
- 'UTCTime' ->
- restrictedstring;
- 'GeneralizedTime' ->
- restrictedstring;
- 'GraphicString' ->
- restrictedstring;
- 'VisibleString' ->
- restrictedstring;
- 'GeneralString' ->
- restrictedstring;
- 'UniversalString' ->
- restrictedstring;
- 'BMPString' ->
- restrictedstring;
- Other -> Other
- end.
-
-
-
-
-
-get_inner(A) when atom(A) -> A;
-get_inner(Ext) when record(Ext,'Externaltypereference') -> Ext;
-get_inner(Tref) when record(Tref,typereference) -> Tref;
-get_inner({fixedtypevaluefield,_,Type}) ->
- if
- record(Type,type) ->
- get_inner(Type#type.def);
- true ->
- get_inner(Type)
- end;
-get_inner({typefield,TypeName}) ->
- TypeName;
-get_inner(#'ObjectClassFieldType'{type=Type}) ->
-% get_inner(Type);
- Type;
-get_inner(T) when tuple(T) ->
- case element(1,T) of
- Tuple when tuple(Tuple),element(1,Tuple) == objectclass ->
- case catch(lists:last(element(2,T))) of
- {valuefieldreference,FieldName} ->
- get_fieldtype(element(2,Tuple),FieldName);
- {typefieldreference,FieldName} ->
- get_fieldtype(element(2,Tuple),FieldName);
- {'EXIT',Reason} ->
- throw({asn1,{'internal error in get_inner/1',Reason}})
- end;
- _ -> element(1,T)
- end.
-
-
-
-
-
-type(X) when record(X,'Externaltypereference') ->
- X;
-type(X) when record(X,typereference) ->
- X;
-type('ASN1_OPEN_TYPE') ->
- 'ASN1_OPEN_TYPE';
-type({fixedtypevaluefield,_Name,Type}) when record(Type,type) ->
- type(get_inner(Type#type.def));
-type({typefield,_}) ->
- 'ASN1_OPEN_TYPE';
-type(X) ->
- %% io:format("asn1_types:type(~p)~n",[X]),
- case catch type2(X) of
- {'EXIT',_} ->
- {notype,X};
- Normal ->
- Normal
- end.
-
-type2(X) ->
- case prim_bif(X) of
- true ->
- {primitive,bif};
- false ->
- case construct_bif(X) of
- true ->
- {constructed,bif};
- false ->
- {undefined,user}
- end
- end.
-
-prim_bif(X) ->
- lists:member(X,['INTEGER' ,
- 'ENUMERATED',
- 'OBJECT IDENTIFIER',
- 'ANY',
- 'NULL',
- 'BIT STRING' ,
- 'OCTET STRING' ,
- 'ObjectDescriptor',
- 'NumericString',
- 'TeletexString',
- 'VideotexString',
- 'UTCTime',
- 'GeneralizedTime',
- 'GraphicString',
- 'VisibleString',
- 'GeneralString',
- 'PrintableString',
- 'IA5String',
- 'UniversalString',
- 'BMPString',
- 'ENUMERATED',
- 'BOOLEAN']).
-
-construct_bif(T) ->
- lists:member(T,['SEQUENCE' ,
- 'SEQUENCE OF' ,
- 'CHOICE' ,
- 'SET' ,
- 'SET OF']).
-
-def_to_tag(#tag{class=Class,number=Number}) ->
- {Class,Number};
-def_to_tag(#'ObjectClassFieldType'{type=Type}) ->
- case Type of
- T when tuple(T),element(1,T)==fixedtypevaluefield ->
- {'UNIVERSAL',get_inner(Type)};
- _ ->
- []
- end;
-def_to_tag(Def) ->
- {'UNIVERSAL',get_inner(Def)}.
-
-
-%% Information Object Class
-
-type_from_object(X) ->
- case (catch lists:last(element(2,X))) of
- {'EXIT',_} ->
- {notype,X};
- Normal ->
- Normal
- end.
-
-
-get_fieldtype([],_FieldName)->
- {no_type,no_name};
-get_fieldtype([Field|Rest],FieldName) ->
- case element(2,Field) of
- FieldName ->
- case element(1,Field) of
- fixedtypevaluefield ->
- {element(1,Field),FieldName,element(3,Field)};
- _ ->
- {element(1,Field),FieldName}
- end;
- _ ->
- get_fieldtype(Rest,FieldName)
- end.
-
-get_fieldcategory([],_FieldName) ->
- no_cat;
-get_fieldcategory([Field|Rest],FieldName) ->
- case element(2,Field) of
- FieldName ->
- element(1,Field);
- _ ->
- get_fieldcategory(Rest,FieldName)
- end.
-
-get_typefromobject(Type) when record(Type,type) ->
- case Type#type.def of
- {{objectclass,_,_},TypeFrObj} when list(TypeFrObj) ->
- {_,FieldName} = lists:last(TypeFrObj),
- FieldName;
- _ ->
- {no_field}
- end.
-
-get_classfieldcategory(Type,FieldName) ->
- case (catch Type#type.def) of
- {{obejctclass,Fields,_},_} ->
- get_fieldcategory(Fields,FieldName);
- {'EXIT',_} ->
- no_cat;
- _ ->
- no_cat
- end.
-%% Information Object Class
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Convert a list of name parts to something that can be output by emit
-%%
-%% used to output function names in generated code.
-
-list2name(L) ->
- NewL = list2name1(L),
- lists:concat(lists:reverse(NewL)).
-
-list2name1([{ptype,H1},H2|T]) ->
- [H1,"_",list2name([H2|T])];
-list2name1([H1,H2|T]) ->
- [H1,"_",list2name([H2|T])];
-list2name1([{ptype,H}|_T]) ->
- [H];
-list2name1([H|_T]) ->
- [H];
-list2name1([]) ->
- [].
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Convert a list of name parts to something that can be output by emit
-%% stops at {ptype,Pname} i.e Pname whill be the first part of the name
-%% used to output record names in generated code.
-
-list2rname(L) ->
- NewL = list2rname1(L),
- lists:concat(lists:reverse(NewL)).
-
-list2rname1([{ptype,H1},_H2|_T]) ->
- [H1];
-list2rname1([H1,H2|T]) ->
- [H1,"_",list2name([H2|T])];
-list2rname1([{ptype,H}|_T]) ->
- [H];
-list2rname1([H|_T]) ->
- [H];
-list2rname1([]) ->
- [].
-
-
-
-constructed_suffix(_,#'SEQUENCE'{pname=Ptypename}) when Ptypename =/= false ->
- {ptype, Ptypename};
-constructed_suffix(_,#'SET'{pname=Ptypename}) when Ptypename =/= false ->
- {ptype,Ptypename};
-constructed_suffix('SEQUENCE OF',_) ->
- 'SEQOF';
-constructed_suffix('SET OF',_) ->
- 'SETOF'.
-
-erule(ber) ->
- ber;
-erule(ber_bin) ->
- ber;
-erule(ber_bin_v2) ->
- ber_bin_v2;
-erule(per) ->
- per;
-erule(per_bin) ->
- per.
-
-wrap_ber(ber) ->
- ber_bin;
-wrap_ber(Erule) ->
- Erule.
-
-rt2ct_suffix() ->
- Options = get(encoding_options),
- case {lists:member(optimize,Options),lists:member(per_bin,Options)} of
- {true,true} -> "_rt2ct";
- _ -> ""
- end.
-rt2ct_suffix(per_bin) ->
- Options = get(encoding_options),
- case lists:member(optimize,Options) of
- true -> "_rt2ct";
- _ -> ""
- end;
-rt2ct_suffix(_) -> "".
-
-get_constraint(C,Key) ->
- case lists:keysearch(Key,1,C) of
- false ->
- no;
- {value,{_,V}} ->
- V;
- {value,Cnstr} ->
- Cnstr
- end.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen_ber.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen_ber.erl
deleted file mode 100644
index f063dff765..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen_ber.erl
+++ /dev/null
@@ -1,1525 +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: asn1ct_gen_ber.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
-%%
--module(asn1ct_gen_ber).
-
-%% Generate erlang module which handles (PER) encode and decode for
-%% all types in an ASN.1 module
-
--include("asn1_records.hrl").
-
--export([pgen/4]).
--export([decode_class/1, decode_type/1]).
--export([add_removed_bytes/0]).
--export([gen_encode/2,gen_encode/3,gen_decode/2,gen_decode/3]).
--export([gen_encode_prim/4]).
--export([gen_dec_prim/8]).
--export([gen_objectset_code/2, gen_obj_code/3]).
--export([re_wrap_erule/1]).
--export([unused_var/2]).
-
--import(asn1ct_gen, [emit/1,demit/1]).
-
- % the encoding of class of tag bits 8 and 7
--define(UNIVERSAL, 0).
--define(APPLICATION, 16#40).
--define(CONTEXT, 16#80).
--define(PRIVATE, 16#C0).
-
- % primitive or constructed encoding % bit 6
--define(PRIMITIVE, 0).
--define(CONSTRUCTED, 2#00100000).
-
-
--define(T_ObjectDescriptor, ?UNIVERSAL bor ?PRIMITIVE bor 7).
- % restricted character string types
--define(T_NumericString, ?UNIVERSAL bor ?PRIMITIVE bor 18). %can be constructed
--define(T_PrintableString, ?UNIVERSAL bor ?PRIMITIVE bor 19). %can be constructed
--define(T_TeletexString, ?UNIVERSAL bor ?PRIMITIVE bor 20). %can be constructed
--define(T_VideotexString, ?UNIVERSAL bor ?PRIMITIVE bor 21). %can be constructed
--define(T_IA5String, ?UNIVERSAL bor ?PRIMITIVE bor 22). %can be constructed
--define(T_GraphicString, ?UNIVERSAL bor ?PRIMITIVE bor 25). %can be constructed
--define(T_VisibleString, ?UNIVERSAL bor ?PRIMITIVE bor 26). %can be constructed
--define(T_GeneralString, ?UNIVERSAL bor ?PRIMITIVE bor 27). %can be constructed
-
-%% pgen(Erules, Module, TypeOrVal)
-%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module
-%% .hrl file is only generated if necessary
-%% Erules = per | ber
-%% Module = atom()
-%% TypeOrVal = {TypeList,ValueList,PTypeList}
-%% TypeList = ValueList = [atom()]
-
-pgen(OutFile,Erules,Module,TypeOrVal) ->
- asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,true).
-
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Generate ENCODING
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-%%===============================================================================
-%% encode #{typedef, {pos, name, typespec}}
-%%===============================================================================
-
-gen_encode(Erules,Type) when record(Type,typedef) ->
- gen_encode_user(Erules,Type).
-
-%%===============================================================================
-%% encode #{type, {tag, def, constraint}}
-%%===============================================================================
-
-gen_encode(Erules,Typename,Type) when record(Type,type) ->
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- ObjFun =
- case lists:keysearch(objfun,1,Type#type.tablecinf) of
- {value,{_,_Name}} ->
- ", ObjFun";
- false ->
- ""
- end,
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- emit([nl,nl,nl,"%%================================"]),
- emit([nl,"%% ",asn1ct_gen:list2name(Typename)]),
- emit([nl,"%%================================",nl]),
- case lists:member(InnerType,['SET','SEQUENCE']) of
- true ->
- case get(asn_keyed_list) of
- true ->
- CompList =
- case Type#type.def of
- #'SEQUENCE'{components=Cl} -> Cl;
- #'SET'{components=Cl} -> Cl
- end,
- emit([nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'(Val, TagIn",ObjFun,
- ") when list(Val) ->",nl]),
- emit([" 'enc_",asn1ct_gen:list2name(Typename),
- "'(?RT_BER:fixoptionals(",
- {asis,optionals(CompList)},
- ",Val), TagIn",ObjFun,");",nl,nl]);
- _ -> true
- end;
- _ ->
- emit([nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'({'",asn1ct_gen:list2name(Typename),
- "',Val}, TagIn",ObjFun,") ->",nl]),
- emit([" 'enc_",asn1ct_gen:list2name(Typename),
- "'(Val, TagIn",ObjFun,");",nl,nl])
- end,
- emit(["'enc_",asn1ct_gen:list2name(Typename),
- "'(Val, TagIn",ObjFun,") ->",nl," "]),
- asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
- _ ->
- true
- end;
-
-%%===============================================================================
-%% encode ComponentType
-%%===============================================================================
-
-gen_encode(Erules,Tname,{'ComponentType',_Pos,Cname,Type,_,_}) ->
- NewTname = [Cname|Tname],
- %% The tag is set to [] to avoid that it is
- %% taken into account twice, both as a component/alternative (passed as
- %% argument to the encode decode function and within the encode decode
- %% function it self.
- NewType = Type#type{tag=[]},
- gen_encode(Erules,NewTname,NewType).
-
-gen_encode_user(Erules,D) when record(D,typedef) ->
- Typename = [D#typedef.name],
- Type = D#typedef.typespec,
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- emit([nl,nl,"%%================================"]),
- emit([nl,"%% ",Typename]),
- emit([nl,"%%================================",nl]),
- case lists:member(InnerType,['SET','SEQUENCE']) of
- true ->
- case get(asn_keyed_list) of
- true ->
- CompList =
- case Type#type.def of
- #'SEQUENCE'{components=Cl} -> Cl;
- #'SET'{components=Cl} -> Cl
- end,
-
- emit([nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'(Val, TagIn) when list(Val) ->",nl]),
- emit([" 'enc_",asn1ct_gen:list2name(Typename),
- "'(?RT_BER:fixoptionals(",
- {asis,optionals(CompList)},
- ",Val), TagIn);",nl,nl]);
- _ -> true
- end;
- _ ->
- emit({nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'({'",asn1ct_gen:list2name(Typename),"',Val}, TagIn) ->",nl}),
- emit({" 'enc_",asn1ct_gen:list2name(Typename),"'(Val, TagIn);",nl,nl})
- end,
- emit({"'enc_",asn1ct_gen:list2name(Typename),"'(",
- unused_var("Val",Type#type.def),", TagIn) ->",nl}),
- CurrentMod = get(currmod),
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,D);
- {primitive,bif} ->
- asn1ct_gen_ber:gen_encode_prim(ber,Type,["TagIn ++ ",
- {asis,Tag}],"Val"),
- emit([".",nl]);
- #typereference{val=Ename} ->
- emit([" 'enc_",Ename,"'(Val, TagIn ++ ",{asis,Tag},").",nl]);
- #'Externaltypereference'{module=CurrentMod,type=Etype} ->
- emit([" 'enc_",Etype,"'(Val, TagIn ++ ",
- {asis,Tag},").",nl]);
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit([" '",Emod,"':'enc_",Etype,"'(Val, TagIn ++ ",
- {asis,Tag},").",nl]);
- 'ASN1_OPEN_TYPE' ->
- emit(["%% OPEN TYPE",nl]),
- asn1ct_gen_ber:gen_encode_prim(ber,
- Type#type{def='ASN1_OPEN_TYPE'},
- ["TagIn ++ ",
- {asis,Tag}],"Val"),
- emit([".",nl])
- end.
-
-unused_var(Var,#'SEQUENCE'{components=Cl}) ->
- unused_var1(Var,Cl);
-unused_var(Var,#'SET'{components=Cl}) ->
- unused_var1(Var,Cl);
-unused_var(Var,_) ->
- Var.
-unused_var1(Var,Cs) when Cs == []; Cs == {[],[]} ->
- lists:concat(["_",Var]);
-unused_var1(Var,_) ->
- Var.
-
-unused_optormand_var(Var,Def) ->
- case asn1ct_gen:type(asn1ct_gen:get_inner(Def)) of
- 'ASN1_OPEN_TYPE' ->
- lists:concat(["_",Var]);
- _ ->
- Var
- end.
-
-
-gen_encode_prim(_Erules,D,DoTag,Value) when record(D,type) ->
-
-%%% Currently not used for BER (except for BitString) and therefore replaced
-%%% with [] as a placeholder
- BitStringConstraint = D#type.constraint,
- Constraint = [],
- asn1ct_name:new(enumval),
- case D#type.def of
- 'BOOLEAN' ->
- emit_encode_func('boolean',Value,DoTag);
- 'INTEGER' ->
- emit_encode_func('integer',Constraint,Value,DoTag);
- {'INTEGER',NamedNumberList} ->
- emit_encode_func('integer',Constraint,Value,
- NamedNumberList,DoTag);
- {'ENUMERATED',NamedNumberList={_,_}} ->
-
- emit(["case (case ",Value," of {asn1_enum,_}->",Value,";{_,_}->element(2,",Value,");_->",
- Value," end) of",nl]),
- emit_enc_enumerated_cases(NamedNumberList,DoTag);
- {'ENUMERATED',NamedNumberList} ->
-
- emit(["case (case ",Value," of {_,_}->element(2,",Value,");_->",
- Value," end) of",nl]),
- emit_enc_enumerated_cases(NamedNumberList,DoTag);
-
- {'BIT STRING',NamedNumberList} ->
- emit_encode_func('bit_string',BitStringConstraint,Value,
- NamedNumberList,DoTag);
- 'ANY' ->
- emit_encode_func('open_type', Value,DoTag);
- 'NULL' ->
- emit_encode_func('null',Value,DoTag);
- 'OBJECT IDENTIFIER' ->
- emit_encode_func("object_identifier",Value,DoTag);
- 'ObjectDescriptor' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_ObjectDescriptor,DoTag);
- 'OCTET STRING' ->
- emit_encode_func('octet_string',Constraint,Value,DoTag);
- 'NumericString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_NumericString,DoTag);
- 'TeletexString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_TeletexString,DoTag);
- 'VideotexString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_VideotexString,DoTag);
- 'GraphicString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_GraphicString,DoTag);
- 'VisibleString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_VisibleString,DoTag);
- 'GeneralString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_GeneralString,DoTag);
- 'PrintableString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_PrintableString,DoTag);
- 'IA5String' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_IA5String,DoTag);
- 'UniversalString' ->
- emit_encode_func('universal_string',Constraint,Value,DoTag);
- 'BMPString' ->
- emit_encode_func('BMP_string',Constraint,Value,DoTag);
- 'UTCTime' ->
- emit_encode_func('utc_time',Constraint,Value,DoTag);
- 'GeneralizedTime' ->
- emit_encode_func('generalized_time',Constraint,Value,DoTag);
- 'ASN1_OPEN_TYPE' ->
- emit_encode_func('open_type', Value,DoTag);
- XX ->
- exit({'can not encode' ,XX})
- end.
-
-
-emit_encode_func(Name,Value,Tags) when atom(Name) ->
- emit_encode_func(atom_to_list(Name),Value,Tags);
-emit_encode_func(Name,Value,Tags) ->
- Fname = "?RT_BER:encode_" ++ Name,
- emit([Fname,"(",Value,", ",Tags,")"]).
-
-emit_encode_func(Name,Constraint,Value,Tags) when atom(Name) ->
- emit_encode_func(atom_to_list(Name),Constraint,Value,Tags);
-emit_encode_func(Name,Constraint,Value,Tags) ->
- Fname = "?RT_BER:encode_" ++ Name,
- emit([Fname,"(",{asis,Constraint},", ",Value,", ",Tags,")"]).
-
-emit_encode_func(Name,Constraint,Value,Asis,Tags) when atom(Name) ->
- emit_encode_func(atom_to_list(Name),Constraint,Value,Asis,Tags);
-emit_encode_func(Name,Constraint,Value,Asis,Tags) ->
- Fname = "?RT_BER:encode_" ++ Name,
- emit([Fname,"(",{asis,Constraint},", ",Value,
- ", ",{asis,Asis},
- ", ",Tags,")"]).
-
-emit_enc_enumerated_cases({L1,L2}, Tags) ->
- emit_enc_enumerated_cases(L1++L2, Tags, ext);
-emit_enc_enumerated_cases(L, Tags) ->
- emit_enc_enumerated_cases(L, Tags, noext).
-
-emit_enc_enumerated_cases([{EnumName,EnumVal},H2|T], Tags, Ext) ->
- emit([{asis,EnumName}," -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,");",nl]),
-%% emit(["'",{asis,EnumName},"' -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,");",nl]),
- emit_enc_enumerated_cases([H2|T], Tags, Ext);
-emit_enc_enumerated_cases([{EnumName,EnumVal}], Tags, Ext) ->
- emit([{asis,EnumName}," -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,")"]),
-%% emit(["'",{asis,EnumName},"' -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,")"]),
- case Ext of
- noext -> emit([";",nl]);
- ext ->
- emit([";",nl,"{asn1_enum,",{curr,enumval},"} -> ",
- "?RT_BER:encode_enumerated(",{curr,enumval},",",Tags,");",nl]),
- asn1ct_name:new(enumval)
- end,
- emit([{curr,enumval}," -> exit({error,{asn1, {enumerated_not_in_range,",{curr, enumval},"}}})"]),
- emit([nl,"end"]).
-
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Generate DECODING
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-%%===============================================================================
-%% decode #{typedef, {pos, name, typespec}}
-%%===============================================================================
-
-gen_decode(Erules,Type) when record(Type,typedef) ->
- D = Type,
- emit({nl,nl}),
- emit({"'dec_",Type#typedef.name,"'(Bytes, OptOrMand) ->",nl}),
- emit({" 'dec_",Type#typedef.name,"'(Bytes, OptOrMand, []).",nl,nl}),
- emit({"'dec_",Type#typedef.name,"'(Bytes, ",
- unused_optormand_var("OptOrMand",(Type#typedef.typespec)#type.def),", TagIn) ->",nl}),
- dbdec(Type#typedef.name),
- gen_decode_user(Erules,D).
-
-
-%%===============================================================================
-%% decode #{type, {tag, def, constraint}}
-%%===============================================================================
-
-gen_decode(Erules,Tname,Type) when record(Type,type) ->
- Typename = Tname,
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- ObjFun =
- case Type#type.tablecinf of
- [{objfun,_}|_R] ->
- ", ObjFun";
- _ ->
- ""
- end,
- emit({"'dec_",asn1ct_gen:list2name(Typename),"'(Bytes, OptOrMand, TagIn",ObjFun,") ->",nl}),
- dbdec(Typename),
- asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,Type);
- _ ->
- true
- end;
-
-
-%%===============================================================================
-%% decode ComponentType
-%%===============================================================================
-
-gen_decode(Erules,Tname,{'ComponentType',_Pos,Cname,Type,_,_}) ->
- NewTname = [Cname|Tname],
- %% The tag is set to [] to avoid that it is
- %% taken into account twice, both as a component/alternative (passed as
- %% argument to the encode decode function and within the encode decode
- %% function it self.
- NewType = Type#type{tag=[]},
- gen_decode(Erules,NewTname,NewType).
-
-
-gen_decode_user(Erules,D) when record(D,typedef) ->
- Typename = [D#typedef.name],
- Def = D#typedef.typespec,
- InnerType = asn1ct_gen:get_inner(Def#type.def),
- InnerTag = Def#type.tag ,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- InnerTag],
- case asn1ct_gen:type(InnerType) of
- 'ASN1_OPEN_TYPE' ->
- BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
- asn1ct_name:new(len),
- gen_dec_prim(Erules, Def#type{def='ASN1_OPEN_TYPE'},
- BytesVar, Tag, "TagIn",no_length,
- ?PRIMITIVE,"OptOrMand"),
- emit({".",nl,nl});
- {primitive,bif} ->
- BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)),
- asn1ct_name:new(len),
- gen_dec_prim(Erules, Def, BytesVar, Tag, "TagIn",no_length,
- ?PRIMITIVE,"OptOrMand"),
- emit({".",nl,nl});
- {constructed,bif} ->
- asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,D);
- TheType ->
- DecFunName = mkfuncname(TheType,dec),
- emit({DecFunName,"(",{curr,bytes},
- ", OptOrMand, TagIn++",{asis,Tag},")"}),
- emit({".",nl,nl})
- end.
-
-
-gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Length,_Form,OptOrMand) ->
- Typename = Att#type.def,
-%% Currently not used for BER replaced with [] as place holder
-%% Constraint = Att#type.constraint,
-%% Constraint = [],
- Constraint =
- case get_constraint(Att#type.constraint,'SizeConstraint') of
- no -> [];
- Tc -> Tc
- end,
- ValueRange =
- case get_constraint(Att#type.constraint,'ValueRange') of
- no -> [];
- Tv -> Tv
- end,
- SingleValue =
- case get_constraint(Att#type.constraint,'SingleValue') of
- no -> [];
- Sv -> Sv
- end,
- AsBin = case get(binary_strings) of
- true -> "_as_bin";
- _ -> ""
- end,
- NewTypeName = case Typename of
- 'ANY' -> 'ASN1_OPEN_TYPE';
- _ -> Typename
- end,
- DoLength =
- case NewTypeName of
- 'BOOLEAN'->
- emit({"?RT_BER:decode_boolean(",BytesVar,","}),
- false;
- 'INTEGER' ->
- emit({"?RT_BER:decode_integer(",BytesVar,",",
- {asis,int_constr(SingleValue,ValueRange)},","}),
- false;
- {'INTEGER',NamedNumberList} ->
- emit({"?RT_BER:decode_integer(",BytesVar,",",
- {asis,int_constr(SingleValue,ValueRange)},",",
- {asis,NamedNumberList},","}),
- false;
- {'ENUMERATED',NamedNumberList} ->
- emit({"?RT_BER:decode_enumerated(",BytesVar,",",
- {asis,Constraint},",",
- {asis,NamedNumberList},","}),
- false;
- {'BIT STRING',NamedNumberList} ->
- case get(compact_bit_string) of
- true ->
- emit({"?RT_BER:decode_compact_bit_string(",
- BytesVar,",",{asis,Constraint},",",
- {asis,NamedNumberList},","});
- _ ->
- emit({"?RT_BER:decode_bit_string(",BytesVar,",",
- {asis,Constraint},",",
- {asis,NamedNumberList},","})
- end,
- true;
- 'NULL' ->
- emit({"?RT_BER:decode_null(",BytesVar,","}),
- false;
- 'OBJECT IDENTIFIER' ->
- emit({"?RT_BER:decode_object_identifier(",BytesVar,","}),
- false;
- 'ObjectDescriptor' ->
- emit({"?RT_BER:decode_restricted_string(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_ObjectDescriptor},","}),
- true;
- 'OCTET STRING' ->
- emit({"?RT_BER:decode_octet_string",AsBin,"(",BytesVar,",",{asis,Constraint},","}),
- true;
- 'NumericString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_NumericString},","}),true;
- 'TeletexString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_TeletexString},","}),
- true;
- 'VideotexString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_VideotexString},","}),
- true;
- 'GraphicString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_GraphicString},","})
- ,true;
- 'VisibleString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_VisibleString},","}),
- true;
- 'GeneralString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_GeneralString},","}),
- true;
- 'PrintableString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_PrintableString},","}),
- true;
- 'IA5String' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_IA5String},","}),
- true;
- 'UniversalString' ->
- emit({"?RT_BER:decode_universal_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},","}),
- true;
- 'BMPString' ->
- emit({"?RT_BER:decode_BMP_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},","}),
- true;
- 'UTCTime' ->
- emit({"?RT_BER:decode_utc_time",AsBin,"(",
- BytesVar,",",{asis,Constraint},","}),
- true;
- 'GeneralizedTime' ->
- emit({"?RT_BER:decode_generalized_time",AsBin,"(",
- BytesVar,",",{asis,Constraint},","}),
- true;
- 'ASN1_OPEN_TYPE' ->
- emit(["?RT_BER:decode_open_type(",re_wrap_erule(Erules),",",
- BytesVar,","]),
- false;
- Other ->
- exit({'can not decode' ,Other})
- end,
-
- NewLength = case DoLength of
- true -> [", ", Length];
- false -> ""
- end,
- NewOptOrMand = case OptOrMand of
- _ when list(OptOrMand) -> OptOrMand;
- mandatory -> {asis,mandatory};
- _ -> {asis,opt_or_default}
- end,
- case {TagIn,NewTypeName} of
- {[],'ASN1_OPEN_TYPE'} ->
- emit([{asis,DoTag},")"]);
- {_,'ASN1_OPEN_TYPE'} ->
- emit([TagIn,"++",{asis,DoTag},")"]);
- {[],_} ->
- emit([{asis,DoTag},NewLength,", ",NewOptOrMand,")"]);
- _ when list(TagIn) ->
- emit([TagIn,"++",{asis,DoTag},NewLength,", ",NewOptOrMand,")"])
- end.
-
-
-int_constr([],[]) ->
- [];
-int_constr([],ValueRange) ->
- ValueRange;
-int_constr(SingleValue,[]) ->
- SingleValue;
-int_constr(SV,VR) ->
- [SV,VR].
-
-%% Object code generating for encoding and decoding
-%% ------------------------------------------------
-
-gen_obj_code(Erules,_Module,Obj) when record(Obj,typedef) ->
- ObjName = Obj#typedef.name,
- Def = Obj#typedef.typespec,
- #'Externaltypereference'{module=M,type=ClName} = Def#'Object'.classname,
- Class = asn1_db:dbget(M,ClName),
-
- {object,_,Fields} = Def#'Object'.def,
- emit({nl,nl,nl,"%%================================"}),
- emit({nl,"%% ",ObjName}),
- emit({nl,"%%================================",nl}),
- EncConstructed =
- gen_encode_objectfields(ClName,get_class_fields(Class),
- ObjName,Fields,[]),
- emit(nl),
- gen_encode_constr_type(Erules,EncConstructed),
- emit(nl),
- DecConstructed =
- gen_decode_objectfields(ClName,get_class_fields(Class),
- ObjName,Fields,[]),
- emit(nl),
- gen_decode_constr_type(Erules,DecConstructed);
-gen_obj_code(_Erules,_Module,Obj) when record(Obj,pobjectdef) ->
- ok.
-
-
-gen_encode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(Args) ->
- emit(["'enc_",ObjName,"'(",{asis,Name},
- ", ",Args,", _RestPrimFieldName) ->",nl])
- end,
-% emit(["'enc_",ObjName,"'(",{asis,Name},
-% ", Val, TagIn, _RestPrimFieldName) ->",nl]),
- MaybeConstr=
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} -> %% this case is illegal
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("_, _"),
- emit([" {[],0}"]),
- [];
- {false,{'DEFAULT',DefaultType}} ->
- EmitFuncClause("Val, TagIn"),
- gen_encode_default_call(ClassName,Name,DefaultType);
- {{Name,TypeSpec},_} ->
- %% A specified field owerwrites any 'DEFAULT' or
- %% 'OPTIONAL' field in the class
- EmitFuncClause("Val, TagIn"),
- gen_encode_field_call(ObjName,Name,TypeSpec)
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_encode_objectfields(ClassName,Rest,ObjName,ObjectFields,
- MaybeConstr++ConstrAcc);
-gen_encode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(Args) ->
- emit(["'enc_",ObjName,"'(",{asis,Name},
- ", ",Args,") ->",nl])
- end,
-% emit(["'enc_",ObjName,"'(",{asis,Name},
-% ", Val, TagIn, [H|T]) ->",nl]),
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} ->
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("_,_,_"),
- emit([" exit({error,{'use of missing field in object', ",Name,
- "}})"]);
- {false,{'DEFAULT',_DefaultObject}} ->
- exit({error,{asn1,{"not implemented yet",Name}}});
- {{Name,TypeSpec},_} ->
- EmitFuncClause(" Val, TagIn, [H|T]"),
- case TypeSpec#typedef.name of
- {ExtMod,TypeName} ->
- emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
- "'(H, Val, TagIn, T)"});
- TypeName ->
- emit({indent(3),"'enc_",TypeName,"'(H, Val, TagIn, T)"})
- end
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_encode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
-gen_encode_objectfields(ClassName,[_|Cs],O,OF,Acc) ->
- gen_encode_objectfields(ClassName,Cs,O,OF,Acc);
-gen_encode_objectfields(_,[],_,_,Acc) ->
- Acc.
-
-
-% gen_encode_objectfields(Class,ObjName,[{FieldName,Type}|Rest],ConstrAcc) ->
-% Fields = Class#objectclass.fields,
-% MaybeConstr=
-% case is_typefield(Fields,FieldName) of
-% true ->
-% Def = Type#typedef.typespec,
-% OTag = Def#type.tag,
-% Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
-% emit({"'enc_",ObjName,"'(",{asis,FieldName},
-% ", Val, TagIn, RestPrimFieldName) ->",nl}),
-% CAcc=
-% case Type#typedef.name of
-% {primitive,bif} ->
-% gen_encode_prim(ber,Def,["TagIn ++ ",{asis,Tag}],
-% "Val"),
-% [];
-% {constructed,bif} ->
-% %%InnerType = asn1ct_gen:get_inner(Def#type.def),
-% %%asn1ct_gen:gen_encode_constructed(ber,[ObjName],
-% %% InnerType,Def);
-% emit({" 'enc_",ObjName,'_',FieldName,
-% "'(Val, TagIn ++ ",{asis,Tag},")"}),
-% [{['enc_',ObjName,'_',FieldName],Def}];
-% {ExtMod,TypeName} ->
-% emit({" '",ExtMod,"':'enc_",TypeName,
-% "'(Val, TagIn ++ ",{asis,Tag},")"}),
-% [];
-% TypeName ->
-% emit({" 'enc_",TypeName,"'(Val, TagIn ++ ",
-% {asis,Tag},")"}),
-% []
-% end,
-% case more_genfields(Fields,Rest) of
-% true ->
-% emit({";",nl});
-% false ->
-% emit({".",nl})
-% end,
-% CAcc;
-% {false,objectfield} ->
-% emit({"'enc_",ObjName,"'(",{asis,FieldName},
-% ", Val, TagIn, [H|T]) ->",nl}),
-% case Type#typedef.name of
-% {ExtMod,TypeName} ->
-% emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
-% "'(H, Val, TagIn, T)"});
-% TypeName ->
-% emit({indent(3),"'enc_",TypeName,"'(H, Val, TagIn, T)"})
-% end,
-% case more_genfields(Fields,Rest) of
-% true ->
-% emit({";",nl});
-% false ->
-% emit({".",nl})
-% end,
-% [];
-% {false,_} -> []
-% end,
-% gen_encode_objectfields(Class,ObjName,Rest,MaybeConstr ++ ConstrAcc);
-% gen_encode_objectfields(C,O,[H|T],Acc) ->
-% gen_encode_objectfields(C,O,T,Acc);
-% gen_encode_objectfields(_,_,[],Acc) ->
-% Acc.
-
-% gen_encode_constr_type([{Name,Def}|Rest]) ->
-% emit({Name,"(Val,TagIn) ->",nl}),
-% InnerType = asn1ct_gen:get_inner(Def#type.def),
-% asn1ct_gen:gen_encode_constructed(ber,Name,InnerType,Def),
-% gen_encode_constr_type(Rest);
-gen_encode_constr_type(Erules,[TypeDef|Rest]) when record(TypeDef,typedef) ->
- case is_already_generated(enc,TypeDef#typedef.name) of
- true -> ok;
- _ -> gen_encode_user(Erules,TypeDef)
- end,
- gen_encode_constr_type(Erules,Rest);
-gen_encode_constr_type(_,[]) ->
- ok.
-
-gen_encode_field_call(ObjName,FieldName,Type) ->
- Def = Type#typedef.typespec,
- OTag = Def#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- case Type#typedef.name of
- {primitive,bif} -> %%tag should be the primitive tag
- gen_encode_prim(ber,Def,["TagIn ++ ",{asis,Tag}],
- "Val"),
- [];
- {constructed,bif} ->
- emit({" 'enc_",ObjName,'_',FieldName,
- "'(Val, TagIn ++",{asis,Tag},")"}),
- [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
- {ExtMod,TypeName} ->
- emit({" '",ExtMod,"':'enc_",TypeName,
- "'(Val, TagIn ++ ",{asis,Tag},")"}),
- [];
- TypeName ->
- emit({" 'enc_",TypeName,"'(Val, TagIn ++ ",{asis,Tag},")"}),
- []
- end.
-
-gen_encode_default_call(ClassName,FieldName,Type) ->
- CurrentMod = get(currmod),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
-%% asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
- emit([" 'enc_",ClassName,'_',FieldName,"'(Bytes, TagIn ++ ",
- {asis,Tag},")"]),
- [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
- typespec=Type}];
- {primitive,bif} ->
- gen_encode_prim(ber,Type,["TagIn ++ ",{asis,Tag}],"Val"),
- [];
- #'Externaltypereference'{module=CurrentMod,type=Etype} ->
- emit([" 'enc_",Etype,"'(Val, TagIn ++ ",{asis,Tag},")",nl]),
- [];
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit([" '",Emod,"':'enc_",Etype,"'(Val, TagIn ++ ",{asis,Tag},")",nl]),
- []
- end.
-
-
-
-gen_decode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(Args) ->
- emit(["'dec_",ObjName,"'(",{asis,Name},
- ", ",Args,"_) ->",nl])
- end,
-% emit(["'dec_",ObjName,"'(",{asis,Name},
-% ", Bytes, TagIn, RestPrimFieldName) ->",nl]),
- MaybeConstr=
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} -> %% this case is illegal
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("_, _,"),
- emit([" asn1_NOVALUE"]),
- [];
- {false,{'DEFAULT',DefaultType}} ->
- EmitFuncClause("Bytes, TagIn,"),
- gen_decode_default_call(ClassName,Name,"Bytes",DefaultType);
- {{Name,TypeSpec},_} ->
- %% A specified field owerwrites any 'DEFAULT' or
- %% 'OPTIONAL' field in the class
- EmitFuncClause("Bytes, TagIn,"),
- gen_decode_field_call(ObjName,Name,"Bytes",TypeSpec)
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,MaybeConstr++ConstrAcc);
-gen_decode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(Args) ->
- emit(["'dec_",ObjName,"'(",{asis,Name},
- ", ",Args,") ->",nl])
- end,
-% emit(["'dec_",ObjName,"'(",{asis,Name},
-% ", Bytes,TagIn,[H|T]) ->",nl]),
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} ->
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("_,_,_"),
- emit([" exit({error,{'illegal use of missing field in object', ",Name,
- "}})"]);
- {false,{'DEFAULT',_DefaultObject}} ->
- exit({error,{asn1,{"not implemented yet",Name}}});
- {{Name,TypeSpec},_} ->
- EmitFuncClause("Bytes,TagIn,[H|T]"),
- case TypeSpec#typedef.name of
- {ExtMod,TypeName} ->
- emit({indent(3),"'",ExtMod,"':'dec_",TypeName,
- "'(H, Bytes, TagIn, T)"});
- TypeName ->
- emit({indent(3),"'dec_",TypeName,"'(H, Bytes, TagIn, T)"})
- end
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
-gen_decode_objectfields(CN,[_|Cs],O,OF,CAcc) ->
- gen_decode_objectfields(CN,Cs,O,OF,CAcc);
-gen_decode_objectfields(_,[],_,_,CAcc) ->
- CAcc.
-
-
-
-% gen_decode_objectfields(Erules,Class,ObjName,[{FieldName,Type}|Rest],ConstrAcc) ->
-% Fields = Class#objectclass.fields,
-% MaybeConstr =
-% case is_typefield(Fields,FieldName) of
-% true ->
-% Def = Type#typedef.typespec,
-% emit({"'dec_",ObjName,"'(",{asis,FieldName},
-% ", Bytes, TagIn, RestPrimFieldName) ->",nl}),
-% OTag = Def#type.tag,
-% Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
-% Prop =
-% case get_optionalityspec(Fields,FieldName) of
-% 'OPTIONAL' -> opt_or_default;
-% {'DEFAULT',_} -> opt_or_default;
-% _ -> mandatory
-% end,
-% CAcc =
-% case Type#typedef.name of
-% {primitive,bif} ->
-% gen_dec_prim(Erules,Def,"Bytes",Tag,"TagIn",no_length,
-% ?PRIMITIVE,Prop),
-% [];
-% {constructed,bif} ->
-% emit({" 'dec_",ObjName,'_',FieldName,"'(Bytes,",
-% {asis,Prop},", TagIn ++ ",{asis,Tag},")"}),
-% [{['dec_',ObjName,'_',FieldName],Def}];
-% {ExtMod,TypeName} ->
-% emit({" '",ExtMod,"':'dec_",TypeName,"'(Bytes, ",
-% {asis,Prop},", TagIn ++ ",{asis,Tag},")"}),
-% [];
-% TypeName ->
-% emit({" 'dec_",TypeName,"'(Bytes, ",{asis,Prop},
-% ", TagIn ++ ",{asis,Tag},")"}),
-% []
-% end,
-% case more_genfields(Fields,Rest) of
-% true ->
-% emit({";",nl});
-% false ->
-% emit({".",nl})
-% end,
-% CAcc;
-% {false,objectfield} ->
-% emit({"'dec_",ObjName,"'(",{asis,FieldName},
-% ", Bytes, TagIn, [H|T]) ->",nl}),
-% case Type#typedef.name of
-% {ExtMod,TypeName} ->
-% emit({indent(3),"'",ExtMod,"':'dec_",TypeName,
-% "'(H, Bytes, TagIn, T)"});
-% TypeName ->
-% emit({indent(3),"'dec_",TypeName,
-% "'(H, Bytes, TagIn, T)"})
-% end,
-% case more_genfields(Fields,Rest) of
-% true ->
-% emit({";",nl});
-% false ->
-% emit({".",nl})
-% end,
-% [];
-% {false,_} ->
-% []
-% end,
-% gen_decode_objectfields(Erules,Class,ObjName,Rest,MaybeConstr ++ ConstrAcc);
-% gen_decode_objectfields(Erules,C,O,[H|T],CAcc) ->
-% gen_decode_objectfields(Erules,C,O,T,CAcc);
-% gen_decode_objectfields(_,_,_,[],CAcc) ->
-% CAcc.
-
-gen_decode_constr_type(Erules,[{Name,Def}|Rest]) ->
-%% emit({Name,"(Bytes, OptOrMand) ->",nl}),
-%% emit({" ",Name,"(Bytes, OptOrMand, []).",nl,nl}),
- emit({Name,"(Bytes, OptOrMand, TagIn) ->",nl}),
- InnerType = asn1ct_gen:get_inner(Def#type.def),
- asn1ct_gen:gen_decode_constructed(ber,Name,InnerType,Def),
- gen_decode_constr_type(Erules,Rest);
-gen_decode_constr_type(Erules,[TypeDef|Rest]) when record(TypeDef,typedef) ->
- case is_already_generated(dec,TypeDef#typedef.name) of
- true -> ok;
- _ ->
- gen_decode(Erules,TypeDef)
- end,
- gen_decode_constr_type(Erules,Rest);
-gen_decode_constr_type(_,[]) ->
- ok.
-
-gen_decode_field_call(ObjName,FieldName,Bytes,Type) ->
- Def = Type#typedef.typespec,
- OTag = Def#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- case Type#typedef.name of
- {primitive,bif} -> %%tag should be the primitive tag
- gen_dec_prim(ber,Def,Bytes,Tag,"TagIn",no_length,
- ?PRIMITIVE,opt_or_default),
- [];
- {constructed,bif} ->
- emit({" 'dec_",ObjName,'_',FieldName,
- "'(",Bytes,",opt_or_default, TagIn ++ ",{asis,Tag},")"}),
- [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
- {ExtMod,TypeName} ->
- emit({" '",ExtMod,"':'dec_",TypeName,
- "'(",Bytes,", opt_or_default,TagIn ++ ",{asis,Tag},")"}),
- [];
- TypeName ->
- emit({" 'dec_",TypeName,"'(",Bytes,
- ", opt_or_default,TagIn ++ ",{asis,Tag},")"}),
- []
- end.
-
-gen_decode_default_call(ClassName,FieldName,Bytes,Type) ->
- CurrentMod = get(currmod),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- emit([" 'dec_",ClassName,'_',FieldName,"'(",Bytes,
- ",opt_or_default, TagIn ++ ",{asis,Tag},")"]),
- [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
- typespec=Type}];
- {primitive,bif} ->
- gen_dec_prim(ber,Type,Bytes,Tag,"TagIn",no_length,
- ?PRIMITIVE,opt_or_default),
- [];
- #'Externaltypereference'{module=CurrentMod,type=Etype} ->
- emit([" 'dec_",Etype,"'(",Bytes,
- " ,opt_or_default, TagIn ++ ",{asis,Tag},")",nl]),
- [];
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit([" '",Emod,"':'dec_",Etype,"'(",Bytes,
- ", opt_or_defualt, TagIn ++ ",{asis,Tag},")",nl]),
- []
- end.
-
-
-more_genfields([]) ->
- false;
-more_genfields([Field|Fields]) ->
- case element(1,Field) of
- typefield ->
- true;
- objectfield ->
- true;
- _ ->
- more_genfields(Fields)
- end.
-
-
-
-%% Object Set code generating for encoding and decoding
-%% ----------------------------------------------------
-gen_objectset_code(Erules,ObjSet) ->
- ObjSetName = ObjSet#typedef.name,
- Def = ObjSet#typedef.typespec,
-% {ClassName,ClassDef} = Def#'ObjectSet'.class,
- #'Externaltypereference'{module=ClassModule,
- type=ClassName} = Def#'ObjectSet'.class,
- ClassDef = asn1_db:dbget(ClassModule,ClassName),
- UniqueFName = Def#'ObjectSet'.uniquefname,
- Set = Def#'ObjectSet'.set,
- emit({nl,nl,nl,"%%================================"}),
- emit({nl,"%% ",ObjSetName}),
- emit({nl,"%%================================",nl}),
- case ClassName of
- {_Module,ExtClassName} ->
- gen_objset_code(Erules,ObjSetName,UniqueFName,Set,
- ExtClassName,ClassDef);
- _ ->
- gen_objset_code(Erules,ObjSetName,UniqueFName,Set,
- ClassName,ClassDef)
- end,
- emit(nl).
-
-gen_objset_code(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassDef)->
- ClassFields = (ClassDef#classdef.typespec)#objectclass.fields,
- InternalFuncs=gen_objset_enc(ObjSetName,UniqueFName,Set,ClassName,ClassFields,1,[]),
- gen_objset_dec(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassFields,1),
- gen_internal_funcs(Erules,InternalFuncs).
-
-%% gen_objset_enc iterates over the objects of the object set
-gen_objset_enc(_,{unique,undefined},_,_,_,_,_) ->
- %% There is no unique field in the class of this object set
- %% don't bother about the constraint
- [];
-gen_objset_enc(ObjSName,UniqueName,
- [{ObjName,Val,Fields},T|Rest],ClName,ClFields,NthObj,Acc)->
- emit({"'getenc_",ObjSName,"'(",{asis,UniqueName},",",{asis,Val},") ->",nl}),
- {InternalFunc,NewNthObj}=
- case ObjName of
- no_name ->
- gen_inlined_enc_funs(Fields,ClFields,ObjSName,NthObj);
- _Other ->
- emit({" fun 'enc_",ObjName,"'/4"}),
- {[],NthObj}
- end,
- emit({";",nl}),
- gen_objset_enc(ObjSName,UniqueName,[T|Rest],ClName,ClFields,
- NewNthObj,InternalFunc ++ Acc);
-gen_objset_enc(ObjSetName,UniqueName,
- [{ObjName,Val,Fields}],_ClName,ClFields,NthObj,Acc) ->
- emit({"'getenc_",ObjSetName,"'(",{asis,UniqueName},",",{asis,Val},") ->",nl}),
- {InternalFunc,_}=
- case ObjName of
- no_name ->
- gen_inlined_enc_funs(Fields,ClFields,ObjSetName,NthObj);
- _Other ->
- emit({" fun 'enc_",ObjName,"'/4"}),
- {[],NthObj}
- end,
- emit({".",nl,nl}),
- InternalFunc ++ Acc;
-%% See X.681 Annex E for the following case
-gen_objset_enc(ObjSetName,_UniqueName,['EXTENSIONMARK'],
- _ClName,_ClFields,_NthObj,Acc) ->
- emit({"'getenc_",ObjSetName,"'(_, _) ->",nl}),
- emit({indent(3),"fun(_Attr, Val, _TagIn, _RestPrimFieldName) ->",nl}),
- emit({indent(6),"Len = case Val of",nl,indent(9),
- "Bin when binary(Bin) -> size(Bin);",nl,indent(9),
- "_ -> length(Val)",nl,indent(6),"end,"}),
- emit({indent(6),"{Val,Len}",nl}),
- emit({indent(3),"end.",nl,nl}),
- Acc;
-gen_objset_enc(_,_,[],_,_,_,Acc) ->
- Acc.
-
-%% gen_inlined_enc_funs for each object iterates over all fields of a
-%% class, and for each typefield it checks if the object has that
-%% field and emits the proper code.
-gen_inlined_enc_funs(Fields,[{typefield,Name,_}|Rest],ObjSetName,
- NthObj) ->
- InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when record(Type,type) ->
- emit({indent(3),"fun(Type, Val, TagIn, _RestPrimFieldName) ->",nl,
- indent(6),"case Type of",nl}),
- {Ret,N} = emit_inner_of_fun(Type,InternalDefFunName),
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
- {value,{_,Type}} when record(Type,typedef) ->
- emit({indent(3),"fun(Type, Val, TagIn, _RestPrimFieldName) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- {Ret,N} = emit_inner_of_fun(Type,InternalDefFunName),
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
- false ->
- gen_inlined_enc_funs(Fields,Rest,ObjSetName,NthObj)
- end;
-gen_inlined_enc_funs(Fields,[_H|Rest],ObjSetName,NthObj) ->
- gen_inlined_enc_funs(Fields,Rest,ObjSetName,NthObj);
-gen_inlined_enc_funs(_,[],_,NthObj) ->
- {[],NthObj}.
-
-gen_inlined_enc_funs1(Fields,[{typefield,Name,_}|Rest],ObjSetName,
- NthObj,Acc) ->
- InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- {Acc2,NAdd}=
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when record(Type,type) ->
- emit({";",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- {Ret++Acc,N};
- {value,{_,Type}} when record(Type,typedef) ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- {Ret++Acc,N};
- false ->
- {Acc,0}
- end,
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+NAdd,Acc2);
-gen_inlined_enc_funs1(Fields,[_H|Rest],ObjSetName,NthObj,Acc)->
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj,Acc);
-gen_inlined_enc_funs1(_,[],_,NthObj,Acc) ->
- emit({nl,indent(6),"end",nl}),
- emit({indent(3),"end"}),
- {Acc,NthObj}.
-
-
-emit_inner_of_fun(TDef = #typedef{name={ExtMod,Name},typespec=Type},
- InternalDefFunName) ->
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- case {ExtMod,Name} of
- {primitive,bif} ->
- emit(indent(12)),
- gen_encode_prim(ber,Type,["TagIn ++ ",{asis,Tag}],"Val"),
- {[],0};
- {constructed,bif} ->
- emit([indent(12),"'enc_",
- InternalDefFunName,"'(Val,TagIn ++ ",
- {asis,Tag},")"]),
- {[TDef#typedef{name=InternalDefFunName}],1};
- _ ->
- emit({indent(12),"'",ExtMod,"':'enc_",Name,"'(Val, TagIn ++ ",
- {asis,Tag},")"}),
- {[],0}
- end;
-emit_inner_of_fun(#typedef{name=Name,typespec=Type},_) ->
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- emit({indent(12),"'enc_",Name,"'(Val, TagIn ++ ",{asis,Tag},")"}),
- {[],0};
-emit_inner_of_fun(Type,_) when record(Type,type) ->
- CurrMod = get(currmod),
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- case Type#type.def of
- Def when atom(Def) ->
- emit({indent(9),Def," ->",nl,indent(12)}),
- gen_encode_prim(ber,Type,["TagIn ++ ",{asis,Tag}],"Val");
- TRef when record(TRef,typereference) ->
- T = TRef#typereference.val,
- emit({indent(9),T," ->",nl,indent(12),"'enc_",T,
- "'(Val, TagIn ++ ",{asis,Tag},")"});
- #'Externaltypereference'{module=CurrMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),"'enc_",T,
- "'(Val, TagIn ++ ",{asis,Tag},")"});
- #'Externaltypereference'{module=ExtMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),ExtMod,":'enc_",
- T,"'(Val, TagIn ++ ",{asis,Tag},")"})
- end,
- {[],0}.
-
-indent(N) ->
- lists:duplicate(N,32). % 32 = space
-
-
-gen_objset_dec(_,_,{unique,undefined},_,_,_,_) ->
- %% There is no unique field in the class of this object set
- %% don't bother about the constraint
- ok;
-gen_objset_dec(Erules,ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],
- ClName,ClFields,NthObj)->
- emit({"'getdec_",ObjSName,"'(",{asis,UniqueName},",",{asis,Val},
- ") ->",nl}),
- NewNthObj=
- case ObjName of
- no_name ->
- gen_inlined_dec_funs(Erules,Fields,ClFields,ObjSName,
- NthObj);
- _Other ->
- emit({" fun 'dec_",ObjName,"'/4"}),
- NthObj
- end,
- emit({";",nl}),
- gen_objset_dec(Erules,ObjSName,UniqueName,[T|Rest],ClName,ClFields,
- NewNthObj);
-gen_objset_dec(Erules,ObjSetName,UniqueName,[{ObjName,Val,Fields}],_ClName,
- ClFields,NthObj) ->
- emit({"'getdec_",ObjSetName,"'(",{asis,UniqueName},",",{asis,Val},") ->",nl}),
- case ObjName of
- no_name ->
- gen_inlined_dec_funs(Erules,Fields,ClFields,ObjSetName,
- NthObj);
- _Other ->
- emit({" fun 'dec_",ObjName,"'/4"})
- end,
- emit({".",nl,nl});
-gen_objset_dec(_,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,_ClFields,
- _NthObj) ->
- emit({"'getdec_",ObjSetName,"'(_, _) ->",nl}),
- emit({indent(3),"fun(_, Bytes, _, _) ->",nl}),
- emit({indent(6),"Len = case Bytes of",nl,indent(9),
- "Bin when binary(Bin) -> size(Bin);",nl,indent(9),
- "_ -> length(Bytes)",nl,indent(6),"end,"}),
- emit({indent(6),"{Bytes,[],Len}",nl}),
- emit({indent(3),"end.",nl,nl}),
- ok;
-gen_objset_dec(_,_,_,[],_,_,_) ->
- ok.
-
-gen_inlined_dec_funs(Erules,Fields,[{typefield,Name,Prop}|Rest],
- ObjSetName,NthObj) ->
- DecProp = case Prop of
- 'OPTIONAL' -> opt_or_default;
- {'DEFAULT',_} -> opt_or_default;
- _ -> mandatory
- end,
- InternalDefFunName = [NthObj,Name,ObjSetName],
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when record(Type,type) ->
- emit({indent(3),"fun(Type, Bytes, TagIn, _RestPrimFieldName) ->",
- nl,indent(6),"case Type of",nl}),
- N=emit_inner_of_decfun(Erules,Type,DecProp,InternalDefFunName),
- gen_inlined_dec_funs1(Erules,Fields,Rest,ObjSetName,NthObj+N);
- {value,{_,Type}} when record(Type,typedef) ->
- emit({indent(3),"fun(Type, Bytes, TagIn, _RestPrimFieldName) ->",
- nl,indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- N=emit_inner_of_decfun(Erules,Type,DecProp,InternalDefFunName),
- gen_inlined_dec_funs1(Erules,Fields,Rest,ObjSetName,NthObj+N);
- false ->
- gen_inlined_dec_funs(Erules,Fields,Rest,ObjSetName,NthObj)
- end;
-gen_inlined_dec_funs(Erules,Fields,[_H|Rest],ObjSetName,NthObj) ->
- gen_inlined_dec_funs(Erules,Fields,Rest,ObjSetName,NthObj);
-gen_inlined_dec_funs(_,_,[],_,NthObj) ->
- NthObj.
-
-gen_inlined_dec_funs1(Erules,Fields,[{typefield,Name,Prop}|Rest],
- ObjSetName,NthObj) ->
- DecProp = case Prop of
- 'OPTIONAL' -> opt_or_default;
- {'DEFAULT',_} -> opt_or_default;
- _ -> mandatory
- end,
- InternalDefFunName = [NthObj,Name,ObjSetName],
- N=
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when record(Type,type) ->
- emit({";",nl}),
- emit_inner_of_decfun(Erules,Type,DecProp,InternalDefFunName);
- {value,{_,Type}} when record(Type,typedef) ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- emit_inner_of_decfun(Erules,Type,DecProp,InternalDefFunName);
- false ->
- 0
- end,
- gen_inlined_dec_funs1(Erules,Fields,Rest,ObjSetName,NthObj+N);
-gen_inlined_dec_funs1(Erules,Fields,[_H|Rest],ObjSetName,NthObj)->
- gen_inlined_dec_funs1(Erules,Fields,Rest,ObjSetName,NthObj);
-gen_inlined_dec_funs1(_,_,[],_,NthObj) ->
- emit({nl,indent(6),"end",nl}),
- emit({indent(3),"end"}),
- NthObj.
-
-emit_inner_of_decfun(Erules,#typedef{name={ExtName,Name},typespec=Type},
- Prop,InternalDefFunName) ->
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- case {ExtName,Name} of
- {primitive,bif} ->
- emit(indent(12)),
- gen_dec_prim(Erules,Type,"Bytes",Tag,"TagIn",no_length,
- ?PRIMITIVE,Prop),
- 0;
- {constructed,bif} ->
- emit({indent(12),"'dec_",
- asn1ct_gen:list2name(InternalDefFunName),"'(Bytes, ",Prop,
- ", TagIn ++ ",{asis,Tag},")"}),
- 1;
- _ ->
- emit({indent(12),"'",ExtName,"':'dec_",Name,"'(Bytes, ",Prop,
- ", TagIn ++ ",{asis,Tag},")"}),
- 0
- end;
-emit_inner_of_decfun(_,#typedef{name=Name,typespec=Type},Prop,_) ->
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- emit({indent(12),"'dec_",Name,"'(Bytes, ",Prop,", TagIn ++ ",
- {asis,Tag},")"}),
- 0;
-emit_inner_of_decfun(Erules,Type,Prop,_) when record(Type,type) ->
- OTag = Type#type.tag,
- Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- CurrMod = get(currmod),
- Def = Type#type.def,
- InnerType = asn1ct_gen:get_inner(Def),
- WhatKind = asn1ct_gen:type(InnerType),
- case WhatKind of
- {primitive,bif} ->
- emit({indent(9),Def," ->",nl,indent(12)}),
- gen_dec_prim(Erules,Type,"Bytes",Tag,"TagIn",no_length,
- ?PRIMITIVE,Prop);
-% TRef when record(TRef,typereference) ->
-% T = TRef#typereference.val,
-% emit({indent(9),T," ->",nl,indent(12),"'dec_",T,"'(Val)"});
- #'Externaltypereference'{module=CurrMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),"'dec_",T,
- "'(Bytes, ",Prop,", TagIn ++ ",{asis,Tag},")"});
- #'Externaltypereference'{module=ExtMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),ExtMod,":'dec_",
- T,"'(Bytes, ",Prop,", TagIn ++ ",{asis,Tag},")"})
- end,
- 0.
-
-
-gen_internal_funcs(_,[]) ->
- ok;
-gen_internal_funcs(Erules,[TypeDef|Rest]) ->
- gen_encode_user(Erules,TypeDef),
- emit({"'dec_",TypeDef#typedef.name,"'(Bytes, ",
- unused_optormand_var("OptOrMand",(TypeDef#typedef.typespec)#type.def),", TagIn) ->",nl}),
- gen_decode_user(Erules,TypeDef),
- gen_internal_funcs(Erules,Rest).
-
-
-dbdec(Type) ->
- demit({"io:format(\"decoding: ",{asis,Type},"~w~n\",[Bytes]),",nl}).
-
-
-decode_class('UNIVERSAL') ->
- ?UNIVERSAL;
-decode_class('APPLICATION') ->
- ?APPLICATION;
-decode_class('CONTEXT') ->
- ?CONTEXT;
-decode_class('PRIVATE') ->
- ?PRIVATE.
-
-decode_type('BOOLEAN') -> 1;
-decode_type('INTEGER') -> 2;
-decode_type('BIT STRING') -> 3;
-decode_type('OCTET STRING') -> 4;
-decode_type('NULL') -> 5;
-decode_type('OBJECT IDENTIFIER') -> 6;
-decode_type('OBJECT DESCRIPTOR') -> 7;
-decode_type('EXTERNAL') -> 8;
-decode_type('REAL') -> 9;
-decode_type('ENUMERATED') -> 10;
-decode_type('EMBEDDED_PDV') -> 11;
-decode_type('SEQUENCE') -> 16;
-decode_type('SEQUENCE OF') -> 16;
-decode_type('SET') -> 17;
-decode_type('SET OF') -> 17;
-decode_type('NumericString') -> 18;
-decode_type('PrintableString') -> 19;
-decode_type('TeletexString') -> 20;
-decode_type('VideotexString') -> 21;
-decode_type('IA5String') -> 22;
-decode_type('UTCTime') -> 23;
-decode_type('GeneralizedTime') -> 24;
-decode_type('GraphicString') -> 25;
-decode_type('VisibleString') -> 26;
-decode_type('GeneralString') -> 27;
-decode_type('UniversalString') -> 28;
-decode_type('BMPString') -> 30;
-decode_type('CHOICE') -> 'CHOICE'; % choice gets the tag from the actual alternative
-decode_type(Else) -> exit({error,{asn1,{unrecognized_type,Else}}}).
-
-add_removed_bytes() ->
- asn1ct_name:delete(rb),
- add_removed_bytes(asn1ct_name:all(rb)).
-
-add_removed_bytes([H,T1|T]) ->
- emit({{var,H},"+"}),
- add_removed_bytes([T1|T]);
-add_removed_bytes([H|T]) ->
- emit({{var,H}}),
- add_removed_bytes(T);
-add_removed_bytes([]) ->
- true.
-
-mkfuncname(WhatKind,DecOrEnc) ->
- case WhatKind of
- #'Externaltypereference'{module=Mod,type=EType} ->
- CurrMod = get(currmod),
- case CurrMod of
- Mod ->
- lists:concat(["'",DecOrEnc,"_",EType,"'"]);
- _ ->
-% io:format("CurrMod: ~p, Mod: ~p~n",[CurrMod,Mod]),
- lists:concat(["'",Mod,"':'",DecOrEnc,"_",EType,"'"])
- end;
- #'typereference'{val=EType} ->
- lists:concat(["'",DecOrEnc,"_",EType,"'"]);
- 'ASN1_OPEN_TYPE' ->
- lists:concat(["'",DecOrEnc,"_",WhatKind,"'"])
-
- end.
-
-optionals(L) -> optionals(L,[],1).
-
-optionals([{'EXTENSIONMARK',_,_}|Rest],Acc,Pos) ->
- optionals(Rest,Acc,Pos); % optionals in extension are currently not handled
-optionals([#'ComponentType'{name=Name,prop='OPTIONAL'}|Rest],Acc,Pos) ->
- optionals(Rest,[{Name,Pos}|Acc],Pos+1);
-optionals([#'ComponentType'{name=Name,prop={'DEFAULT',_}}|Rest],Acc,Pos) ->
- optionals(Rest,[{Name,Pos}|Acc],Pos+1);
-optionals([#'ComponentType'{}|Rest],Acc,Pos) ->
- optionals(Rest,Acc,Pos+1);
-optionals([],Acc,_) ->
- lists:reverse(Acc).
-
-get_constraint(C,Key) ->
- case lists:keysearch(Key,1,C) of
- false ->
- no;
- {value,{_,V}} ->
- V
- end.
-
-%% if the original option was ber and it has been wrapped to ber_bin
-%% turn it back to ber
-re_wrap_erule(ber_bin) ->
- case get(encoding_options) of
- Options when list(Options) ->
- case lists:member(ber,Options) of
- true -> ber;
- _ -> ber_bin
- end;
- _ -> ber_bin
- end;
-re_wrap_erule(Erule) ->
- Erule.
-
-is_already_generated(Operation,Name) ->
- case get(class_default_type) of
- undefined ->
- put(class_default_type,[{Operation,Name}]),
- false;
- GeneratedList ->
- case lists:member({Operation,Name},GeneratedList) of
- true ->
- true;
- false ->
- put(class_default_type,[{Operation,Name}|GeneratedList]),
- false
- end
- end.
-
-get_class_fields(#classdef{typespec=ObjClass}) ->
- ObjClass#objectclass.fields;
-get_class_fields(#objectclass{fields=Fields}) ->
- Fields;
-get_class_fields(_) ->
- [].
-
-get_object_field(Name,ObjectFields) ->
- case lists:keysearch(Name,1,ObjectFields) of
- {value,Field} -> Field;
- false -> false
- end.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen_ber_bin_v2.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen_ber_bin_v2.erl
deleted file mode 100644
index be8ae6f8a5..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen_ber_bin_v2.erl
+++ /dev/null
@@ -1,1568 +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: asn1ct_gen_ber_bin_v2.erl,v 1.1 2008/12/17 09:53:29 mikpe Exp $
-%%
--module(asn1ct_gen_ber_bin_v2).
-
-%% Generate erlang module which handles (PER) encode and decode for
-%% all types in an ASN.1 module
-
--include("asn1_records.hrl").
-
--export([pgen/4]).
--export([decode_class/1, decode_type/1]).
--export([add_removed_bytes/0]).
--export([gen_encode/2,gen_encode/3,gen_decode/2,gen_decode/3]).
--export([gen_encode_prim/4]).
--export([gen_dec_prim/7]).
--export([gen_objectset_code/2, gen_obj_code/3]).
--export([encode_tag_val/3]).
--export([gen_inc_decode/2]).
-
--import(asn1ct_gen, [emit/1,demit/1]).
-
- % the encoding of class of tag bits 8 and 7
--define(UNIVERSAL, 0).
--define(APPLICATION, 16#40).
--define(CONTEXT, 16#80).
--define(PRIVATE, 16#C0).
-
- % primitive or constructed encoding % bit 6
--define(PRIMITIVE, 0).
--define(CONSTRUCTED, 2#00100000).
-
-
--define(T_ObjectDescriptor, ?UNIVERSAL bor ?PRIMITIVE bor 7).
- % restricted character string types
--define(T_NumericString, ?UNIVERSAL bor ?PRIMITIVE bor 18). %can be constructed
--define(T_PrintableString, ?UNIVERSAL bor ?PRIMITIVE bor 19). %can be constructed
--define(T_TeletexString, ?UNIVERSAL bor ?PRIMITIVE bor 20). %can be constructed
--define(T_VideotexString, ?UNIVERSAL bor ?PRIMITIVE bor 21). %can be constructed
--define(T_IA5String, ?UNIVERSAL bor ?PRIMITIVE bor 22). %can be constructed
--define(T_GraphicString, ?UNIVERSAL bor ?PRIMITIVE bor 25). %can be constructed
--define(T_VisibleString, ?UNIVERSAL bor ?PRIMITIVE bor 26). %can be constructed
--define(T_GeneralString, ?UNIVERSAL bor ?PRIMITIVE bor 27). %can be constructed
-
-%% pgen(Erules, Module, TypeOrVal)
-%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module
-%% .hrl file is only generated if necessary
-%% Erules = per | ber
-%% Module = atom()
-%% TypeOrVal = {TypeList,ValueList,PTypeList}
-%% TypeList = ValueList = [atom()]
-
-pgen(OutFile,Erules,Module,TypeOrVal) ->
- asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,true).
-
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Generate ENCODING
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-%%===============================================================================
-%% encode #{typedef, {pos, name, typespec}}
-%%===============================================================================
-
-gen_encode(Erules,Type) when record(Type,typedef) ->
- gen_encode_user(Erules,Type).
-
-%%===============================================================================
-%% encode #{type, {tag, def, constraint}}
-%%===============================================================================
-
-gen_encode(Erules,Typename,Type) when record(Type,type) ->
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- ObjFun =
- case lists:keysearch(objfun,1,Type#type.tablecinf) of
- {value,{_,_Name}} ->
- ", ObjFun";
- false ->
- ""
- end,
-
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- emit([nl,nl,nl,"%%================================"]),
- emit([nl,"%% ",asn1ct_gen:list2name(Typename)]),
- emit([nl,"%%================================",nl]),
- case length(Typename) of
- 1 -> % top level type
- emit(["'enc_",asn1ct_gen:list2name(Typename),
- "'(Val",ObjFun,") ->",nl]),
- emit([" 'enc_",asn1ct_gen:list2name(Typename),
- "'(Val, ", {asis,lists:reverse(Type#type.tag)},ObjFun,").",nl,nl]);
- _ -> % embedded type with constructed name
- true
- end,
- case lists:member(InnerType,['SET','SEQUENCE']) of
- true ->
- case get(asn_keyed_list) of
- true ->
- CompList =
- case Type#type.def of
- #'SEQUENCE'{components=Cl} -> Cl;
- #'SET'{components=Cl} -> Cl
- end,
- emit([nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'(Val, TagIn",ObjFun,
- ") when list(Val) ->",nl]),
- emit([" 'enc_",asn1ct_gen:list2name(Typename),
- "'(?RT_BER:fixoptionals(",
- {asis,optionals(CompList)},
- ",Val), TagIn",ObjFun,");",nl,nl]);
- _ -> true
- end;
- _ ->
- emit([nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'({'",asn1ct_gen:list2name(Typename),
- "',Val}, TagIn",ObjFun,") ->",nl]),
- emit([" 'enc_",asn1ct_gen:list2name(Typename),
- "'(Val, TagIn",ObjFun,");",nl,nl])
- end,
- emit(["'enc_",asn1ct_gen:list2name(Typename),
- "'(Val, TagIn",ObjFun,") ->",nl," "]),
- asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
- _ ->
- true
- end;
-
-%%===============================================================================
-%% encode ComponentType
-%%===============================================================================
-
-gen_encode(Erules,Tname,{'ComponentType',_Pos,Cname,Type,_Prop,_Tags}) ->
- NewTname = [Cname|Tname],
- %% The tag is set to [] to avoid that it is
- %% taken into account twice, both as a component/alternative (passed as
- %% argument to the encode decode function and within the encode decode
- %% function it self.
- NewType = Type#type{tag=[]},
- gen_encode(Erules,NewTname,NewType).
-
-gen_encode_user(Erules,D) when record(D,typedef) ->
- Typename = [D#typedef.name],
- Type = D#typedef.typespec,
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- OTag = Type#type.tag,
- Tag = [encode_tag_val(decode_class(X#tag.class),X#tag.form,X#tag.number)|| X <- OTag],
- emit([nl,nl,"%%================================"]),
- emit([nl,"%% ",Typename]),
- emit([nl,"%%================================",nl]),
- emit(["'enc_",asn1ct_gen:list2name(Typename),
- "'(Val",") ->",nl]),
- emit([" 'enc_",asn1ct_gen:list2name(Typename),
- "'(Val, ", {asis,lists:reverse(Tag)},").",nl,nl]),
-
- case lists:member(InnerType,['SET','SEQUENCE']) of
- true ->
- case get(asn_keyed_list) of
- true ->
- CompList =
- case Type#type.def of
- #'SEQUENCE'{components=Cl} -> Cl;
- #'SET'{components=Cl} -> Cl
- end,
-
- emit([nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'(Val, TagIn) when list(Val) ->",nl]),
- emit([" 'enc_",asn1ct_gen:list2name(Typename),
- "'(?RT_BER:fixoptionals(",
- {asis,optionals(CompList)},
- ",Val), TagIn);",nl,nl]);
- _ -> true
- end;
- _ ->
- emit({nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'({'",asn1ct_gen:list2name(Typename),"',Val}, TagIn) ->",nl}),
- emit({" 'enc_",asn1ct_gen:list2name(Typename),"'(Val, TagIn);",nl,nl})
- end,
- emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val, TagIn) ->",nl}),
- CurrentMod = get(currmod),
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,D);
- {primitive,bif} ->
- gen_encode_prim(ber,Type,"TagIn","Val"),
- emit([".",nl]);
- #typereference{val=Ename} ->
- emit([" 'enc_",Ename,"'(Val, TagIn).",nl]);
- #'Externaltypereference'{module=CurrentMod,type=Etype} ->
- emit([" 'enc_",Etype,"'(Val, TagIn).",nl]);
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit([" '",Emod,"':'enc_",Etype,"'(Val, TagIn).",nl]);
- 'ASN1_OPEN_TYPE' ->
- emit(["%% OPEN TYPE",nl]),
- gen_encode_prim(ber,
- Type#type{def='ASN1_OPEN_TYPE'},
- "TagIn","Val"),
- emit([".",nl])
- end.
-
-gen_encode_prim(_Erules,D,DoTag,Value) when record(D,type) ->
-
-%%% Constraint is currently not used for BER (except for BitString) and therefore replaced
-%%% with [] as a placeholder
- BitStringConstraint = D#type.constraint,
- Constraint = [],
- asn1ct_name:new(enumval),
- case D#type.def of
- 'BOOLEAN' ->
- emit_encode_func('boolean',Value,DoTag);
- 'INTEGER' ->
- emit_encode_func('integer',Constraint,Value,DoTag);
- {'INTEGER',NamedNumberList} ->
- emit_encode_func('integer',Constraint,Value,
- NamedNumberList,DoTag);
- {'ENUMERATED',NamedNumberList={_,_}} ->
-
- emit(["case (case ",Value," of {asn1_enum,_}->",Value,";{_,_}->element(2,",Value,");_->",
- Value," end) of",nl]),
- emit_enc_enumerated_cases(NamedNumberList,DoTag);
- {'ENUMERATED',NamedNumberList} ->
-
- emit(["case (case ",Value," of {_,_}->element(2,",Value,");_->",
- Value," end) of",nl]),
- emit_enc_enumerated_cases(NamedNumberList,DoTag);
-
- {'BIT STRING',NamedNumberList} ->
- emit_encode_func('bit_string',BitStringConstraint,Value,
- NamedNumberList,DoTag);
- 'ANY' ->
- emit_encode_func('open_type', Value,DoTag);
- 'NULL' ->
- emit_encode_func('null',Value,DoTag);
- 'OBJECT IDENTIFIER' ->
- emit_encode_func("object_identifier",Value,DoTag);
- 'ObjectDescriptor' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_ObjectDescriptor,DoTag);
- 'OCTET STRING' ->
- emit_encode_func('octet_string',Constraint,Value,DoTag);
- 'NumericString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_NumericString,DoTag);
- 'TeletexString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_TeletexString,DoTag);
- 'VideotexString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_VideotexString,DoTag);
- 'GraphicString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_GraphicString,DoTag);
- 'VisibleString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_VisibleString,DoTag);
- 'GeneralString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_GeneralString,DoTag);
- 'PrintableString' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_PrintableString,DoTag);
- 'IA5String' ->
- emit_encode_func('restricted_string',Constraint,Value,
- ?T_IA5String,DoTag);
- 'UniversalString' ->
- emit_encode_func('universal_string',Constraint,Value,DoTag);
- 'BMPString' ->
- emit_encode_func('BMP_string',Constraint,Value,DoTag);
- 'UTCTime' ->
- emit_encode_func('utc_time',Constraint,Value,DoTag);
- 'GeneralizedTime' ->
- emit_encode_func('generalized_time',Constraint,Value,DoTag);
- 'ASN1_OPEN_TYPE' ->
- emit_encode_func('open_type', Value,DoTag);
- XX ->
- exit({'can not encode' ,XX})
- end.
-
-
-emit_encode_func(Name,Value,Tags) when atom(Name) ->
- emit_encode_func(atom_to_list(Name),Value,Tags);
-emit_encode_func(Name,Value,Tags) ->
- Fname = "?RT_BER:encode_" ++ Name,
- emit([Fname,"(",Value,", ",Tags,")"]).
-
-emit_encode_func(Name,Constraint,Value,Tags) when atom(Name) ->
- emit_encode_func(atom_to_list(Name),Constraint,Value,Tags);
-emit_encode_func(Name,Constraint,Value,Tags) ->
- Fname = "?RT_BER:encode_" ++ Name,
- emit([Fname,"(",{asis,Constraint},", ",Value,", ",Tags,")"]).
-
-emit_encode_func(Name,Constraint,Value,Asis,Tags) when atom(Name) ->
- emit_encode_func(atom_to_list(Name),Constraint,Value,Asis,Tags);
-emit_encode_func(Name,Constraint,Value,Asis,Tags) ->
- Fname = "?RT_BER:encode_" ++ Name,
- emit([Fname,"(",{asis,Constraint},", ",Value,
- ", ",{asis,Asis},
- ", ",Tags,")"]).
-
-emit_enc_enumerated_cases({L1,L2}, Tags) ->
- emit_enc_enumerated_cases(L1++L2, Tags, ext);
-emit_enc_enumerated_cases(L, Tags) ->
- emit_enc_enumerated_cases(L, Tags, noext).
-
-emit_enc_enumerated_cases([{EnumName,EnumVal},H2|T], Tags, Ext) ->
- emit([{asis,EnumName}," -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,");",nl]),
-%% emit(["'",{asis,EnumName},"' -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,");",nl]),
- emit_enc_enumerated_cases([H2|T], Tags, Ext);
-emit_enc_enumerated_cases([{EnumName,EnumVal}], Tags, Ext) ->
- emit([{asis,EnumName}," -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,")"]),
-%% emit(["'",{asis,EnumName},"' -> ?RT_BER:encode_enumerated(",EnumVal,",",Tags,")"]),
- case Ext of
- noext -> emit([";",nl]);
- ext ->
- emit([";",nl,"{asn1_enum,",{curr,enumval},"} -> ",
- "?RT_BER:encode_enumerated(",{curr,enumval},",",Tags,");",nl]),
- asn1ct_name:new(enumval)
- end,
- emit([{curr,enumval}," -> exit({error,{asn1, {enumerated_not_in_range,",{curr, enumval},"}}})"]),
- emit([nl,"end"]).
-
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Generate DECODING
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-%%===============================================================================
-%% decode #{typedef, {pos, name, typespec}}
-%%===============================================================================
-
-gen_decode(Erules,Type) when record(Type,typedef) ->
- Def = Type#typedef.typespec,
- InnerTag = Def#type.tag ,
-
- Tag = [(decode_class(X#tag.class) bsl 10) + X#tag.number || X <- InnerTag],
-
- Prefix =
- case {asn1ct:get_gen_state_field(active),
- asn1ct:get_gen_state_field(prefix)} of
- {true,Pref} -> Pref;
- _ -> "dec_"
- end,
- emit({nl,nl}),
- emit(["'",Prefix,Type#typedef.name,"'(Tlv) ->",nl]),
- emit([" '",Prefix,Type#typedef.name,"'(Tlv, ",{asis,Tag},").",nl,nl]),
- emit(["'",Prefix,Type#typedef.name,"'(Tlv, TagIn) ->",nl]),
- dbdec(Type#typedef.name),
- gen_decode_user(Erules,Type).
-
-gen_inc_decode(Erules,Type) when record(Type,typedef) ->
- Prefix = asn1ct:get_gen_state_field(prefix),
- emit({nl,nl}),
- emit(["'",Prefix,Type#typedef.name,"'(Tlv, TagIn) ->",nl]),
- gen_decode_user(Erules,Type).
-
-%%===============================================================================
-%% decode #{type, {tag, def, constraint}}
-%%===============================================================================
-
-%% This gen_decode is called by the gen_decode/3 that decodes
-%% ComponentType and the type of a SEQUENCE OF/SET OF.
-gen_decode(Erules,Tname,Type) when record(Type,type) ->
- Typename = Tname,
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- Prefix =
- case asn1ct:get_gen_state_field(active) of
- true -> "'dec-inc-";
- _ -> "'dec_"
- end,
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- ObjFun =
- case Type#type.tablecinf of
- [{objfun,_}|_R] ->
- ", ObjFun";
- _ ->
- ""
- end,
- emit([Prefix,asn1ct_gen:list2name(Typename),"'(Tlv, TagIn",ObjFun,") ->",nl]),
- dbdec(Typename),
- asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,Type);
- Rec when record(Rec,'Externaltypereference') ->
- case {Typename,asn1ct:get_gen_state_field(namelist)} of
- {[Cname|_],[{Cname,_}|_]} -> %%
- %% This referenced type must only be generated
- %% once as incomplete partial decode. Therefore we
- %% have to check whether this function already is
- %% generated.
- case asn1ct:is_function_generated(Typename) of
- true ->
- ok;
- _ ->
- asn1ct:generated_refed_func(Typename),
- #'Externaltypereference'{module=M,type=Name}=Rec,
- TypeDef = asn1_db:dbget(M,Name),
- gen_decode(Erules,TypeDef)
- end;
- _ ->
- true
- end;
- _ ->
- true
- end;
-
-
-%%===============================================================================
-%% decode ComponentType
-%%===============================================================================
-
-gen_decode(Erules,Tname,{'ComponentType',_Pos,Cname,Type,_Prop,_Tags}) ->
- NewTname = [Cname|Tname],
- %% The tag is set to [] to avoid that it is
- %% taken into account twice, both as a component/alternative (passed as
- %% argument to the encode decode function and within the encode decode
- %% function it self.
- NewType = Type#type{tag=[]},
- case {asn1ct:get_gen_state_field(active),
- asn1ct:get_tobe_refed_func(NewTname)} of
- {true,{_,NameList}} ->
- asn1ct:update_gen_state(namelist,NameList),
- %% remove to gen_refed_funcs list from tobe_refed_funcs later
- gen_decode(Erules,NewTname,NewType);
- {No,_} when No == false; No == undefined ->
- gen_decode(Erules,NewTname,NewType);
- _ ->
- ok
- end.
-
-
-gen_decode_user(Erules,D) when record(D,typedef) ->
- Typename = [D#typedef.name],
- Def = D#typedef.typespec,
- InnerType = asn1ct_gen:get_inner(Def#type.def),
- BytesVar = "Tlv",
- case asn1ct_gen:type(InnerType) of
- 'ASN1_OPEN_TYPE' ->
- asn1ct_name:new(len),
- gen_dec_prim(ber, Def#type{def='ASN1_OPEN_TYPE'},
- BytesVar,{string,"TagIn"}, [] ,
- ?PRIMITIVE,"OptOrMand"),
- emit({".",nl,nl});
- {primitive,bif} ->
- asn1ct_name:new(len),
- gen_dec_prim(ber, Def, BytesVar,{string,"TagIn"},[] ,
- ?PRIMITIVE,"OptOrMand"),
- emit([".",nl,nl]);
- {constructed,bif} ->
- asn1ct:update_namelist(D#typedef.name),
- asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,D);
- TheType ->
- DecFunName = mkfuncname(TheType,dec),
- emit([DecFunName,"(",BytesVar,
- ", TagIn)"]),
- emit([".",nl,nl])
- end.
-
-
-gen_dec_prim(_Erules,Att,BytesVar,DoTag,_TagIn,_Form,_OptOrMand) ->
- Typename = Att#type.def,
-%% Currently not used for BER replaced with [] as place holder
-%% Constraint = Att#type.constraint,
-%% Constraint = [],
- Constraint =
- case get_constraint(Att#type.constraint,'SizeConstraint') of
- no -> [];
- Tc -> Tc
- end,
- ValueRange =
- case get_constraint(Att#type.constraint,'ValueRange') of
- no -> [];
- Tv -> Tv
- end,
- SingleValue =
- case get_constraint(Att#type.constraint,'SingleValue') of
- no -> [];
- Sv -> Sv
- end,
- AsBin = case get(binary_strings) of
- true -> "_as_bin";
- _ -> ""
- end,
- NewTypeName = case Typename of
- 'ANY' -> 'ASN1_OPEN_TYPE';
- _ -> Typename
- end,
-% DoLength =
- case NewTypeName of
- 'BOOLEAN'->
- emit({"?RT_BER:decode_boolean(",BytesVar,","}),
- add_func({decode_boolean,2});
- 'INTEGER' ->
- emit({"?RT_BER:decode_integer(",BytesVar,",",
- {asis,int_constr(SingleValue,ValueRange)},","}),
- add_func({decode_integer,3});
- {'INTEGER',NamedNumberList} ->
- emit({"?RT_BER:decode_integer(",BytesVar,",",
- {asis,int_constr(SingleValue,ValueRange)},",",
- {asis,NamedNumberList},","}),
- add_func({decode_integer,4});
- {'ENUMERATED',NamedNumberList} ->
- emit({"?RT_BER:decode_enumerated(",BytesVar,",",
- {asis,Constraint},",",
- {asis,NamedNumberList},","}),
- add_func({decode_enumerated,4});
- {'BIT STRING',NamedNumberList} ->
- case get(compact_bit_string) of
- true ->
- emit({"?RT_BER:decode_compact_bit_string(",
- BytesVar,",",{asis,Constraint},",",
- {asis,NamedNumberList},","}),
- add_func({decode_compact_bit_string,4});
- _ ->
- emit({"?RT_BER:decode_bit_string(",BytesVar,",",
- {asis,Constraint},",",
- {asis,NamedNumberList},","}),
- add_func({decode_bit_string,4})
- end;
- 'NULL' ->
- emit({"?RT_BER:decode_null(",BytesVar,","}),
- add_func({decode_null,2});
- 'OBJECT IDENTIFIER' ->
- emit({"?RT_BER:decode_object_identifier(",BytesVar,","}),
- add_func({decode_object_identifier,2});
- 'ObjectDescriptor' ->
- emit({"?RT_BER:decode_restricted_string(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_ObjectDescriptor},","}),
- add_func({decode_restricted_string,4});
- 'OCTET STRING' ->
- emit({"?RT_BER:decode_octet_string",AsBin,"(",BytesVar,",",{asis,Constraint},","}),
- add_func({decode_octet_string,3});
- 'NumericString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_NumericString},","}),
- add_func({decode_restricted_string,4});
- 'TeletexString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_TeletexString},","}),
- add_func({decode_restricted_string,4});
- 'VideotexString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_VideotexString},","}),
- add_func({decode_restricted_string,4});
- 'GraphicString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_GraphicString},","}),
- add_func({decode_restricted_string,4});
- 'VisibleString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_VisibleString},","}),
- add_func({decode_restricted_string,4});
- 'GeneralString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_GeneralString},","}),
- add_func({decode_restricted_string,4});
- 'PrintableString' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_PrintableString},","}),
- add_func({decode_restricted_string,4});
- 'IA5String' ->
- emit({"?RT_BER:decode_restricted_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},",",{asis,?T_IA5String},","}),
- add_func({decode_restricted_string,4}) ;
- 'UniversalString' ->
- emit({"?RT_BER:decode_universal_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},","}),
- add_func({decode_universal_string,3});
- 'BMPString' ->
- emit({"?RT_BER:decode_BMP_string",AsBin,"(",
- BytesVar,",",{asis,Constraint},","}),
- add_func({decode_BMP_string,3});
- 'UTCTime' ->
- emit({"?RT_BER:decode_utc_time",AsBin,"(",
- BytesVar,",",{asis,Constraint},","}),
- add_func({decode_utc_time,3});
- 'GeneralizedTime' ->
- emit({"?RT_BER:decode_generalized_time",AsBin,"(",
- BytesVar,",",{asis,Constraint},","}),
- add_func({decode_generalized_time,3});
- 'ASN1_OPEN_TYPE' ->
- emit(["?RT_BER:decode_open_type_as_binary(",
- BytesVar,","]),
- add_func({decode_open_type_as_binary,2});
- Other ->
- exit({'can not decode' ,Other})
- end,
-
- case {DoTag,NewTypeName} of
- {{string,TagStr},'ASN1_OPEN_TYPE'} ->
- emit([TagStr,")"]);
- {_,'ASN1_OPEN_TYPE'} ->
- emit([{asis,DoTag},")"]);
- {{string,TagStr},_} ->
- emit([TagStr,")"]);
- _ when list(DoTag) ->
- emit([{asis,DoTag},")"])
- end.
-
-
-int_constr([],[]) ->
- [];
-int_constr([],ValueRange) ->
- ValueRange;
-int_constr(SingleValue,[]) ->
- SingleValue;
-int_constr(SV,VR) ->
- [SV,VR].
-
-%% Object code generating for encoding and decoding
-%% ------------------------------------------------
-
-gen_obj_code(Erules,_Module,Obj) when record(Obj,typedef) ->
- ObjName = Obj#typedef.name,
- Def = Obj#typedef.typespec,
- #'Externaltypereference'{module=M,type=ClName} = Def#'Object'.classname,
- Class = asn1_db:dbget(M,ClName),
- {object,_,Fields} = Def#'Object'.def,
- emit({nl,nl,nl,"%%================================"}),
- emit({nl,"%% ",ObjName}),
- emit({nl,"%%================================",nl}),
- EncConstructed =
- gen_encode_objectfields(ClName,get_class_fields(Class),
- ObjName,Fields,[]),
- emit(nl),
- gen_encode_constr_type(Erules,EncConstructed),
- emit(nl),
- DecConstructed =
- gen_decode_objectfields(ClName,get_class_fields(Class),
- ObjName,Fields,[]),
- emit(nl),
- gen_decode_constr_type(Erules,DecConstructed),
- emit_tlv_format_function();
-gen_obj_code(_Erules,_Module,Obj) when record(Obj,pobjectdef) ->
- ok.
-
-gen_encode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(Arg) ->
- emit(["'enc_",ObjName,"'(",{asis,Name},
- ", ",Arg,", _RestPrimFieldName) ->",nl])
- end,
-% emit(["'enc_",ObjName,"'(",{asis,Name},
-% ", Val, RestPrimFieldName) ->",nl]),
- MaybeConstr=
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} -> %% this case is illegal
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("_"),
- emit([" {<<>>,0}"]),
- [];
- {false,{'DEFAULT',DefaultType}} ->
- EmitFuncClause("Val"),
- gen_encode_default_call(ClassName,Name,DefaultType);
- {{Name,TypeSpec},_} ->
- %% A specified field owerwrites any 'DEFAULT' or
- %% 'OPTIONAL' field in the class
- EmitFuncClause("Val"),
- gen_encode_field_call(ObjName,Name,TypeSpec)
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_encode_objectfields(ClassName,Rest,ObjName,ObjectFields,
- MaybeConstr++ConstrAcc);
-gen_encode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(Args) ->
- emit(["'enc_",ObjName,"'(",{asis,Name},
- ", ",Args,") ->",nl])
- end,
-% emit(["'enc_",ObjName,"'(",{asis,Name},
-% ", Val,[H|T]) ->",nl]),
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} ->
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("_,_"),
- emit([" exit({error,{'use of missing field in object', ",Name,
- "}})"]);
- {false,{'DEFAULT',_DefaultObject}} ->
- exit({error,{asn1,{"not implemented yet",Name}}});
- {{Name,TypeSpec},_} ->
- EmitFuncClause(" Val, [H|T]"),
- case TypeSpec#typedef.name of
- {ExtMod,TypeName} ->
- emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
- "'(H, Val, T)"});
- TypeName ->
- emit({indent(3),"'enc_",TypeName,"'(H, Val, T)"})
- end
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_encode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
-
-% gen_encode_objectfields(Class,ObjName,[{FieldName,Type}|Rest],ConstrAcc) ->
-% Fields = Class#objectclass.fields,
-% MaybeConstr=
-% case is_typefield(Fields,FieldName) of
-% true ->
-% Def = Type#typedef.typespec,
-% emit({"'enc_",ObjName,"'(",{asis,FieldName},
-% ", Val, RestPrimFieldName) ->",nl}),
-% CAcc=
-% case Type#typedef.name of
-% {primitive,bif} -> %%tag should be the primitive tag
-% OTag = Def#type.tag,
-% Tag = [encode_tag_val(decode_class(X#tag.class),
-% X#tag.form,X#tag.number)||
-% X <- OTag],
-% gen_encode_prim(ber,Def,{asis,lists:reverse(Tag)},
-% "Val"),
-% [];
-% {constructed,bif} ->
-% emit({" 'enc_",ObjName,'_',FieldName,
-% "'(Val)"}),
-% [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
-% {ExtMod,TypeName} ->
-% emit({" '",ExtMod,"':'enc_",TypeName,
-% "'(Val)"}),
-% [];
-% TypeName ->
-% emit({" 'enc_",TypeName,"'(Val)"}),
-% []
-% end,
-% case more_genfields(Fields,Rest) of
-% true ->
-% emit({";",nl});
-% false ->
-% emit({".",nl})
-% end,
-% CAcc;
-% {false,objectfield} ->
-% emit({"'enc_",ObjName,"'(",{asis,FieldName},
-% ", Val,[H|T]) ->",nl}),
-% case Type#typedef.name of
-% {ExtMod,TypeName} ->
-% emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
-% "'(H, Val, T)"});
-% TypeName ->
-% emit({indent(3),"'enc_",TypeName,"'(H, Val, T)"})
-% end,
-% case more_genfields(Fields,Rest) of
-% true ->
-% emit({";",nl});
-% false ->
-% emit({".",nl})
-% end,
-% [];
-% {false,_} -> []
-% end,
-% gen_encode_objectfields(Class,ObjName,Rest,MaybeConstr ++ ConstrAcc);
-gen_encode_objectfields(ClassName,[_C|Cs],O,OF,Acc) ->
- gen_encode_objectfields(ClassName,Cs,O,OF,Acc);
-gen_encode_objectfields(_,[],_,_,Acc) ->
- Acc.
-
-% gen_encode_constr_type(Erules,[{Name,Def}|Rest]) ->
-% emit({Name,"(Val,TagIn) ->",nl}),
-% InnerType = asn1ct_gen:get_inner(Def#type.def),
-% asn1ct_gen:gen_encode_constructed(Erules,Name,InnerType,Def),
-% gen_encode_constr_type(Erules,Rest);
-gen_encode_constr_type(Erules,[TypeDef|Rest]) when record(TypeDef,typedef) ->
- case is_already_generated(enc,TypeDef#typedef.name) of
- true -> ok;
- _ -> gen_encode_user(Erules,TypeDef)
- end,
- gen_encode_constr_type(Erules,Rest);
-gen_encode_constr_type(_,[]) ->
- ok.
-
-gen_encode_field_call(ObjName,FieldName,Type) ->
- Def = Type#typedef.typespec,
- OTag = Def#type.tag,
- Tag = [encode_tag_val(decode_class(X#tag.class),
- X#tag.form,X#tag.number)||
- X <- OTag],
- case Type#typedef.name of
- {primitive,bif} -> %%tag should be the primitive tag
-% OTag = Def#type.tag,
-% Tag = [encode_tag_val(decode_class(X#tag.class),
-% X#tag.form,X#tag.number)||
-% X <- OTag],
- gen_encode_prim(ber,Def,{asis,lists:reverse(Tag)},
- "Val"),
- [];
- {constructed,bif} ->
- emit({" 'enc_",ObjName,'_',FieldName,
- "'(Val,",{asis,Tag},")"}),
- [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
- {ExtMod,TypeName} ->
- emit({" '",ExtMod,"':'enc_",TypeName,
- "'(Val,",{asis,Tag},")"}),
- [];
- TypeName ->
- emit({" 'enc_",TypeName,"'(Val,",{asis,Tag},")"}),
- []
- end.
-
-gen_encode_default_call(ClassName,FieldName,Type) ->
- CurrentMod = get(currmod),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- OTag = Type#type.tag,
- Tag = [encode_tag_val(decode_class(X#tag.class),X#tag.form,X#tag.number)|| X <- OTag],
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
-%% asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
- emit([" 'enc_",ClassName,'_',FieldName,"'(Bytes)"]),
- [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
- typespec=Type}];
- {primitive,bif} ->
- gen_encode_prim(ber,Type,{asis,lists:reverse(Tag)},"Val"),
- [];
- #'Externaltypereference'{module=CurrentMod,type=Etype} ->
- emit([" 'enc_",Etype,"'(Val, ",{asis,Tag},")",nl]),
- [];
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit([" '",Emod,"':'enc_",Etype,"'(Val, ",{asis,Tag},")",nl]),
- []
-% 'ASN1_OPEN_TYPE' ->
-% emit(["%% OPEN TYPE",nl]),
-% gen_encode_prim(ber,
-% Type#type{def='ASN1_OPEN_TYPE'},
-% "TagIn","Val"),
-% emit([".",nl])
- end.
-
-%%%%%%%%%%%%%%%%
-
-gen_decode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(Arg) ->
- emit(["'dec_",ObjName,"'(",{asis,Name},
- ", ",Arg,",_) ->",nl])
- end,
-% emit(["'dec_",ObjName,"'(",{asis,Name},
-% ", Bytes, RestPrimFieldName) ->",nl]),
- MaybeConstr=
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} -> %% this case is illegal
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause(" _"),
- emit([" asn1_NOVALUE"]),
- [];
- {false,{'DEFAULT',DefaultType}} ->
- EmitFuncClause("Bytes"),
- emit_tlv_format("Bytes"),
- gen_decode_default_call(ClassName,Name,"Tlv",DefaultType);
- {{Name,TypeSpec},_} ->
- %% A specified field owerwrites any 'DEFAULT' or
- %% 'OPTIONAL' field in the class
- EmitFuncClause("Bytes"),
- emit_tlv_format("Bytes"),
- gen_decode_field_call(ObjName,Name,"Tlv",TypeSpec)
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,MaybeConstr++ConstrAcc);
-gen_decode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(Args) ->
- emit(["'dec_",ObjName,"'(",{asis,Name},
- ", ",Args,") ->",nl])
- end,
-% emit(["'dec_",ObjName,"'(",{asis,Name},
-% ", Bytes,[H|T]) ->",nl]),
-% emit_tlv_format("Bytes"),
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} ->
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("_,_"),
- emit([" exit({error,{'illegal use of missing field in object', ",Name,
- "}})"]);
- {false,{'DEFAULT',_DefaultObject}} ->
- exit({error,{asn1,{"not implemented yet",Name}}});
- {{Name,TypeSpec},_} ->
- EmitFuncClause("Bytes,[H|T]"),
-% emit_tlv_format("Bytes"),
- case TypeSpec#typedef.name of
- {ExtMod,TypeName} ->
- emit({indent(3),"'",ExtMod,"':'dec_",TypeName,
- "'(H, Bytes, T)"});
- TypeName ->
- emit({indent(3),"'dec_",TypeName,"'(H, Bytes, T)"})
- end
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
-gen_decode_objectfields(CN,[_C|Cs],O,OF,CAcc) ->
- gen_decode_objectfields(CN,Cs,O,OF,CAcc);
-gen_decode_objectfields(_,[],_,_,CAcc) ->
- CAcc.
-
-emit_tlv_format(Bytes) ->
- notice_tlv_format_gen(), % notice for generating of tlv_format/1
- emit([" Tlv = tlv_format(",Bytes,"),",nl]).
-
-notice_tlv_format_gen() ->
- Module = get(currmod),
-% io:format("Noticed: ~p~n",[Module]),
- case get(tlv_format) of
- {done,Module} ->
- ok;
- _ -> % true or undefined
- put(tlv_format,true)
- end.
-
-emit_tlv_format_function() ->
- Module = get(currmod),
-% io:format("Tlv formated: ~p",[Module]),
- case get(tlv_format) of
- true ->
-% io:format(" YES!~n"),
- emit_tlv_format_function1(),
- put(tlv_format,{done,Module});
- _ ->
-% io:format(" NO!~n"),
- ok
- end.
-emit_tlv_format_function1() ->
- emit(["tlv_format(Bytes) when binary(Bytes) ->",nl,
- " {Tlv,_}=?RT_BER:decode(Bytes),",nl,
- " Tlv;",nl,
- "tlv_format(Bytes) ->",nl,
- " Bytes.",nl]).
-
-
-gen_decode_constr_type(Erules,[{Name,Def}|Rest]) ->
- emit([Name,"(Tlv, TagIn) ->",nl]),
- InnerType = asn1ct_gen:get_inner(Def#type.def),
- asn1ct_gen:gen_decode_constructed(Erules,Name,InnerType,Def),
- gen_decode_constr_type(Erules,Rest);
-gen_decode_constr_type(Erules,[TypeDef|Rest]) when record(TypeDef,typedef) ->
- case is_already_generated(dec,TypeDef#typedef.name) of
- true -> ok;
- _ ->
- gen_decode(Erules,TypeDef)
- end,
- gen_decode_constr_type(Erules,Rest);
-gen_decode_constr_type(_,[]) ->
- ok.
-
-%%%%%%%%%%%
-gen_decode_field_call(ObjName,FieldName,Bytes,Type) ->
- Def = Type#typedef.typespec,
- OTag = Def#type.tag,
- Tag = [(decode_class(X#tag.class) bsl 10) + X#tag.number ||
- X <- OTag],
- case Type#typedef.name of
- {primitive,bif} -> %%tag should be the primitive tag
- gen_dec_prim(ber,Def,Bytes,Tag,"TagIn",?PRIMITIVE,
- opt_or_default),
- [];
- {constructed,bif} ->
- emit({" 'dec_",ObjName,'_',FieldName,
- "'(",Bytes,",",{asis,Tag},")"}),
- [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
- {ExtMod,TypeName} ->
- emit({" '",ExtMod,"':'dec_",TypeName,
- "'(",Bytes,",",{asis,Tag},")"}),
- [];
- TypeName ->
- emit({" 'dec_",TypeName,"'(",Bytes,",",{asis,Tag},")"}),
- []
- end.
-
-gen_decode_default_call(ClassName,FieldName,Bytes,Type) ->
- CurrentMod = get(currmod),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- OTag = Type#type.tag,
- Tag = [(decode_class(X#tag.class) bsl 10) + X#tag.number || X <- OTag],
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- emit([" 'dec_",ClassName,'_',FieldName,"'(",Bytes,",",
- {asis,Tag},")"]),
- [#typedef{name=list_to_atom(lists:concat([ClassName,'_',
- FieldName])),
- typespec=Type}];
- {primitive,bif} ->
- gen_dec_prim(ber,Type,Bytes,Tag,"TagIn",
- ?PRIMITIVE,opt_or_default),
- [];
- #'Externaltypereference'{module=CurrentMod,type=Etype} ->
- emit([" 'dec_",Etype,"'(",Bytes, " ,",{asis,Tag},")",nl]),
- [];
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit([" '",Emod,"':'dec_",Etype,"'(",Bytes,", ",
- {asis,Tag},")",nl]),
- []
-% 'ASN1_OPEN_TYPE' ->
-% emit(["%% OPEN TYPE",nl]),
-% gen_encode_prim(ber,
-% Type#type{def='ASN1_OPEN_TYPE'},
-% "TagIn","Val"),
-% emit([".",nl])
- end.
-%%%%%%%%%%%
-
-is_already_generated(Operation,Name) ->
- case get(class_default_type) of
- undefined ->
- put(class_default_type,[{Operation,Name}]),
- false;
- GeneratedList ->
- case lists:member({Operation,Name},GeneratedList) of
- true ->
- true;
- false ->
- put(class_default_type,[{Operation,Name}|GeneratedList]),
- false
- end
- end.
-
-more_genfields([]) ->
- false;
-more_genfields([Field|Fields]) ->
- case element(1,Field) of
- typefield ->
- true;
- objectfield ->
- true;
- _ ->
- more_genfields(Fields)
- end.
-
-
-
-
-%% Object Set code generating for encoding and decoding
-%% ----------------------------------------------------
-gen_objectset_code(Erules,ObjSet) ->
- ObjSetName = ObjSet#typedef.name,
- Def = ObjSet#typedef.typespec,
-% {ClassName,ClassDef} = Def#'ObjectSet'.class,
- #'Externaltypereference'{module=ClassModule,
- type=ClassName} = Def#'ObjectSet'.class,
- ClassDef = asn1_db:dbget(ClassModule,ClassName),
- UniqueFName = Def#'ObjectSet'.uniquefname,
- Set = Def#'ObjectSet'.set,
- emit({nl,nl,nl,"%%================================"}),
- emit({nl,"%% ",ObjSetName}),
- emit({nl,"%%================================",nl}),
- case ClassName of
- {_Module,ExtClassName} ->
- gen_objset_code(Erules,ObjSetName,UniqueFName,Set,ExtClassName,ClassDef);
- _ ->
- gen_objset_code(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassDef)
- end,
- emit(nl).
-
-gen_objset_code(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassDef)->
- ClassFields = get_class_fields(ClassDef),
- InternalFuncs=gen_objset_enc(Erules,ObjSetName,UniqueFName,Set,
- ClassName,ClassFields,1,[]),
- gen_objset_dec(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassFields,1),
- gen_internal_funcs(Erules,InternalFuncs).
-
-%% gen_objset_enc iterates over the objects of the object set
-gen_objset_enc(_,_,{unique,undefined},_,_,_,_,_) ->
- %% There is no unique field in the class of this object set
- %% don't bother about the constraint
- [];
-gen_objset_enc(Erules,ObjSName,UniqueName,
- [{ObjName,Val,Fields},T|Rest],ClName,ClFields,
- NthObj,Acc)->
- emit({"'getenc_",ObjSName,"'(",{asis,UniqueName},",",{asis,Val},
- ") ->",nl}),
- {InternalFunc,NewNthObj}=
- case ObjName of
- no_name ->
- gen_inlined_enc_funs(Fields,ClFields,ObjSName,NthObj);
- _ ->
- emit({" fun 'enc_",ObjName,"'/3"}),
- {[],NthObj}
- end,
- emit({";",nl}),
- gen_objset_enc(Erules,ObjSName,UniqueName,[T|Rest],ClName,ClFields,
- NewNthObj,InternalFunc ++ Acc);
-gen_objset_enc(_,ObjSetName,UniqueName,
- [{ObjName,Val,Fields}],_ClName,ClFields,NthObj,Acc) ->
- emit({"'getenc_",ObjSetName,"'(",{asis,UniqueName},",",
- {asis,Val},") ->",nl}),
- {InternalFunc,_} =
- case ObjName of
- no_name ->
- gen_inlined_enc_funs(Fields,ClFields,ObjSetName,NthObj);
- _ ->
- emit({" fun 'enc_",ObjName,"'/3"}),
- {[],NthObj}
- end,
- emit({".",nl,nl}),
- InternalFunc ++ Acc;
-%% See X.681 Annex E for the following case
-gen_objset_enc(_,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
- _ClFields,_NthObj,Acc) ->
- emit({"'getenc_",ObjSetName,"'(_, _) ->",nl}),
- emit({indent(3),"fun(_, Val, _RestPrimFieldName) ->",nl}),
- emit({indent(6),"Len = case Val of",nl,indent(9),
- "Bin when binary(Bin) -> size(Bin);",nl,indent(9),
- "_ -> length(Val)",nl,indent(6),"end,"}),
- emit({indent(6),"{Val,Len}",nl}),
- emit({indent(3),"end.",nl,nl}),
- Acc;
-gen_objset_enc(_,_,_,[],_,_,_,Acc) ->
- Acc.
-
-%% gen_inlined_enc_funs for each object iterates over all fields of a
-%% class, and for each typefield it checks if the object has that
-%% field and emits the proper code.
-gen_inlined_enc_funs(Fields,[{typefield,Name,_}|Rest],
- ObjSetName,NthObj) ->
- InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when record(Type,type) ->
- emit({indent(3),"fun(Type, Val, _RestPrimFieldName) ->",nl,
- indent(6),"case Type of",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
- {value,{_,Type}} when record(Type,typedef) ->
- emit({indent(3),"fun(Type, Val, _RestPrimFieldName) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
- false ->
- gen_inlined_enc_funs(Fields,Rest,ObjSetName,NthObj)
- end;
-gen_inlined_enc_funs(Fields,[_|Rest],ObjSetName,NthObj) ->
- gen_inlined_enc_funs(Fields,Rest,ObjSetName,NthObj);
-gen_inlined_enc_funs(_,[],_,NthObj) ->
- {[],NthObj}.
-
-gen_inlined_enc_funs1(Fields,[{typefield,Name,_}|Rest],ObjSetName,
- NthObj,Acc) ->
- InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- {Acc2,NAdd}=
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when record(Type,type) ->
- emit({";",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- {Ret++Acc,N};
- {value,{_,Type}} when record(Type,typedef) ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- {Ret++Acc,N};
- false ->
- {Acc,0}
- end,
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+NAdd,Acc2);
-gen_inlined_enc_funs1(Fields,[_|Rest],ObjSetName,NthObj,Acc)->
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj,Acc);
-gen_inlined_enc_funs1(_,[],_,NthObj,Acc) ->
- emit({nl,indent(6),"end",nl}),
- emit({indent(3),"end"}),
- {Acc,NthObj}.
-
-emit_inner_of_fun(TDef=#typedef{name={ExtMod,Name},typespec=Type},
- InternalDefFunName) ->
- OTag = Type#type.tag,
- Tag = [encode_tag_val(decode_class(X#tag.class),X#tag.form,X#tag.number)|| X <- OTag],
-% remove Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- case {ExtMod,Name} of
- {primitive,bif} ->
- emit(indent(12)),
- gen_encode_prim(ber,Type,[{asis,lists:reverse(Tag)}],"Val"),
- {[],0};
- {constructed,bif} ->
- emit([indent(12),"'enc_",
- InternalDefFunName,"'(Val)"]),
- {[TDef#typedef{name=InternalDefFunName}],1};
- _ ->
- emit({indent(12),"'",ExtMod,"':'enc_",Name,"'(Val)"}),
- {[],0}
- end;
-emit_inner_of_fun(#typedef{name=Name},_) ->
-% OTag = Type#type.tag,
-% remove Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
-% Tag = [encode_tag_val(decode_class(X#tag.class),X#tag.form,X#tag.number)|| X <- OTag],
- emit({indent(12),"'enc_",Name,"'(Val)"}),
- {[],0};
-emit_inner_of_fun(Type,_) when record(Type,type) ->
- CurrMod = get(currmod),
-% OTag = Type#type.tag,
-% remove Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
-% Tag = [encode_tag_val(decode_class(X#tag.class),X#tag.form,X#tag.number)|| X <- OTag],
- case Type#type.def of
- Def when atom(Def) ->
- OTag = Type#type.tag,
- Tag = [encode_tag_val(decode_class(X#tag.class),
- X#tag.form,X#tag.number)||X <- OTag],
- emit([indent(9),Def," ->",nl,indent(12)]),
- gen_encode_prim(ber,Type,{asis,lists:reverse(Tag)},"Val");
- TRef when record(TRef,typereference) ->
- T = TRef#typereference.val,
- emit([indent(9),T," ->",nl,indent(12),"'enc_",T,
- "'(Val)"]);
- #'Externaltypereference'{module=CurrMod,type=T} ->
- emit([indent(9),T," ->",nl,indent(12),"'enc_",T,
- "'(Val)"]);
- #'Externaltypereference'{module=ExtMod,type=T} ->
- emit([indent(9),T," ->",nl,indent(12),ExtMod,":'enc_",
- T,"'(Val)"])
- end,
- {[],0}.
-
-indent(N) ->
- lists:duplicate(N,32). % 32 = space
-
-
-gen_objset_dec(_,_,{unique,undefined},_,_,_,_) ->
- %% There is no unique field in the class of this object set
- %% don't bother about the constraint
- ok;
-gen_objset_dec(Erules,ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],
- ClName,ClFields,NthObj)->
- emit(["'getdec_",ObjSName,"'(",{asis,UniqueName},",",
- {asis,Val},") ->",nl]),
- NewNthObj=
- case ObjName of
- no_name ->
- gen_inlined_dec_funs(Fields,ClFields,ObjSName,NthObj);
- _ ->
- emit([" fun 'dec_",ObjName,"'/3"]),
- NthObj
- end,
- emit([";",nl]),
- gen_objset_dec(Erules,ObjSName,UniqueName,[T|Rest],ClName,
- ClFields,NewNthObj);
-gen_objset_dec(_,ObjSetName,UniqueName,[{ObjName,Val,Fields}],
- _ClName,ClFields,NthObj) ->
- emit(["'getdec_",ObjSetName,"'(",{asis,UniqueName},",",
- {asis,Val},") ->",nl]),
- case ObjName of
- no_name ->
- gen_inlined_dec_funs(Fields,ClFields,ObjSetName,NthObj);
- _ ->
- emit([" fun 'dec_",ObjName,"'/3"])
- end,
- emit([".",nl,nl]),
- ok;
-gen_objset_dec(Erules,ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
- _ClFields,_NthObj) ->
- emit(["'getdec_",ObjSetName,"'(_, _) ->",nl]),
- emit([indent(2),"fun(_,Bytes, _RestPrimFieldName) ->",nl]),
- case Erules of
- ber_bin_v2 ->
- emit([indent(4),"case Bytes of",nl,
- indent(6),"Bin when binary(Bin) -> ",nl,
- indent(8),"Bin;",nl,
- indent(6),"_ ->",nl,
- indent(8),"?RT_BER:encode(Bytes)",nl,
- indent(4),"end",nl]);
- _ ->
- emit([indent(6),"Len = case Bytes of",nl,indent(9),
- "Bin when binary(Bin) -> size(Bin);",nl,indent(9),
- "_ -> length(Bytes)",nl,indent(6),"end,"]),
- emit([indent(4),"{Bytes,[],Len}",nl])
- end,
- emit([indent(2),"end.",nl,nl]),
- ok;
-gen_objset_dec(_,_,_,[],_,_,_) ->
- ok.
-
-gen_inlined_dec_funs(Fields,[{typefield,Name,Prop}|Rest],
- ObjSetName,NthObj) ->
- DecProp = case Prop of
- 'OPTIONAL' -> opt_or_default;
- {'DEFAULT',_} -> opt_or_default;
- _ -> mandatory
- end,
- InternalDefFunName = [NthObj,Name,ObjSetName],
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when record(Type,type) ->
- emit([indent(3),"fun(Type, Bytes, _RestPrimFieldName) ->",
- nl,indent(6),"case Type of",nl]),
- N=emit_inner_of_decfun(Type,DecProp,InternalDefFunName),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
- {value,{_,Type}} when record(Type,typedef) ->
- emit([indent(3),"fun(Type, Bytes, _RestPrimFieldName) ->",
- nl,indent(6),"case Type of",nl]),
- emit([indent(9),{asis,Name}," ->",nl]),
- N=emit_inner_of_decfun(Type,DecProp,InternalDefFunName),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
- false ->
- gen_inlined_dec_funs(Fields,Rest,ObjSetName,NthObj)
- end;
-gen_inlined_dec_funs(Fields,[_H|Rest],ObjSetName,NthObj) ->
- gen_inlined_dec_funs(Fields,Rest,ObjSetName,NthObj);
-gen_inlined_dec_funs(_,[],_,NthObj) ->
- NthObj.
-
-gen_inlined_dec_funs1(Fields,[{typefield,Name,Prop}|Rest],
- ObjSetName,NthObj) ->
- DecProp = case Prop of
- 'OPTIONAL' -> opt_or_default;
- {'DEFAULT',_} -> opt_or_default;
- _ -> mandatory
- end,
- InternalDefFunName = [NthObj,Name,ObjSetName],
- N=
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when record(Type,type) ->
- emit([";",nl]),
- emit_inner_of_decfun(Type,DecProp,InternalDefFunName);
- {value,{_,Type}} when record(Type,typedef) ->
- emit([";",nl,indent(9),{asis,Name}," ->",nl]),
- emit_inner_of_decfun(Type,DecProp,InternalDefFunName);
- false ->
- 0
- end,
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
-gen_inlined_dec_funs1(Fields,[_|Rest],ObjSetName,NthObj)->
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj);
-gen_inlined_dec_funs1(_,[],_,NthObj) ->
- emit([nl,indent(6),"end",nl]),
- emit([indent(3),"end"]),
- NthObj.
-
-emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type},Prop,
- InternalDefFunName) ->
- OTag = Type#type.tag,
-%% Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- Tag = [(decode_class(X#tag.class) bsl 10) + X#tag.number || X <- OTag],
- case {ExtName,Name} of
- {primitive,bif} ->
- emit(indent(12)),
- gen_dec_prim(ber,Type,"Bytes",Tag,"TagIn",
- ?PRIMITIVE,Prop),
- 0;
- {constructed,bif} ->
- emit([indent(12),"'dec_",
-% asn1ct_gen:list2name(InternalDefFunName),"'(Bytes, ",Prop,
-% ", ",{asis,Tag},")"]),
- asn1ct_gen:list2name(InternalDefFunName),"'(Bytes, ",
- {asis,Tag},")"]),
- 1;
- _ ->
- emit([indent(12),"'",ExtName,"':'dec_",Name,"'(Bytes)"]),
- 0
- end;
-emit_inner_of_decfun(#typedef{name=Name},_Prop,_) ->
- emit([indent(12),"'dec_",Name,"'(Bytes)"]),
- 0;
-emit_inner_of_decfun(Type,Prop,_) when record(Type,type) ->
- OTag = Type#type.tag,
-%% Tag = [X#tag{class=decode_class(X#tag.class)}|| X <- OTag],
- Tag = [(decode_class(X#tag.class) bsl 10) + X#tag.number || X <- OTag],
- CurrMod = get(currmod),
- Def = Type#type.def,
- InnerType = asn1ct_gen:get_inner(Def),
- WhatKind = asn1ct_gen:type(InnerType),
- case WhatKind of
- {primitive,bif} ->
- emit([indent(9),Def," ->",nl,indent(12)]),
- gen_dec_prim(ber,Type,"Bytes",Tag,"TagIn",
- ?PRIMITIVE,Prop);
- #'Externaltypereference'{module=CurrMod,type=T} ->
- emit([indent(9),T," ->",nl,indent(12),"'dec_",T,
-% "'(Bytes, ",Prop,")"]);
- "'(Bytes)"]);
- #'Externaltypereference'{module=ExtMod,type=T} ->
- emit([indent(9),T," ->",nl,indent(12),ExtMod,":'dec_",
-% T,"'(Bytes, ",Prop,")"])
- T,"'(Bytes)"])
- end,
- 0.
-
-gen_internal_funcs(_,[]) ->
- ok;
-gen_internal_funcs(Erules,[TypeDef|Rest]) ->
- gen_encode_user(Erules,TypeDef),
- emit([nl,nl,"'dec_",TypeDef#typedef.name,
-% "'(Tlv, OptOrMand, TagIn) ->",nl]),
- "'(Tlv, TagIn) ->",nl]),
- gen_decode_user(Erules,TypeDef),
- gen_internal_funcs(Erules,Rest).
-
-
-dbdec(Type) ->
- demit({"io:format(\"decoding: ",{asis,Type},"~w~n\",[Bytes]),",nl}).
-
-
-decode_class('UNIVERSAL') ->
- ?UNIVERSAL;
-decode_class('APPLICATION') ->
- ?APPLICATION;
-decode_class('CONTEXT') ->
- ?CONTEXT;
-decode_class('PRIVATE') ->
- ?PRIVATE.
-
-decode_type('BOOLEAN') -> 1;
-decode_type('INTEGER') -> 2;
-decode_type('BIT STRING') -> 3;
-decode_type('OCTET STRING') -> 4;
-decode_type('NULL') -> 5;
-decode_type('OBJECT IDENTIFIER') -> 6;
-decode_type('OBJECT DESCRIPTOR') -> 7;
-decode_type('EXTERNAL') -> 8;
-decode_type('REAL') -> 9;
-decode_type('ENUMERATED') -> 10;
-decode_type('EMBEDDED_PDV') -> 11;
-decode_type('SEQUENCE') -> 16;
-decode_type('SEQUENCE OF') -> 16;
-decode_type('SET') -> 17;
-decode_type('SET OF') -> 17;
-decode_type('NumericString') -> 18;
-decode_type('PrintableString') -> 19;
-decode_type('TeletexString') -> 20;
-decode_type('VideotexString') -> 21;
-decode_type('IA5String') -> 22;
-decode_type('UTCTime') -> 23;
-decode_type('GeneralizedTime') -> 24;
-decode_type('GraphicString') -> 25;
-decode_type('VisibleString') -> 26;
-decode_type('GeneralString') -> 27;
-decode_type('UniversalString') -> 28;
-decode_type('BMPString') -> 30;
-decode_type('CHOICE') -> 'CHOICE'; % choice gets the tag from the actual alternative
-decode_type(Else) -> exit({error,{asn1,{unrecognized_type,Else}}}).
-
-add_removed_bytes() ->
- asn1ct_name:delete(rb),
- add_removed_bytes(asn1ct_name:all(rb)).
-
-add_removed_bytes([H,T1|T]) ->
- emit({{var,H},"+"}),
- add_removed_bytes([T1|T]);
-add_removed_bytes([H|T]) ->
- emit({{var,H}}),
- add_removed_bytes(T);
-add_removed_bytes([]) ->
- true.
-
-mkfuncname(WhatKind,DecOrEnc) ->
- case WhatKind of
- #'Externaltypereference'{module=Mod,type=EType} ->
- CurrMod = get(currmod),
- case CurrMod of
- Mod ->
- lists:concat(["'",DecOrEnc,"_",EType,"'"]);
- _ ->
-% io:format("CurrMod: ~p, Mod: ~p~n",[CurrMod,Mod]),
- lists:concat(["'",Mod,"':'",DecOrEnc,"_",EType,"'"])
- end;
- #'typereference'{val=EType} ->
- lists:concat(["'",DecOrEnc,"_",EType,"'"]);
- 'ASN1_OPEN_TYPE' ->
- lists:concat(["'",DecOrEnc,"_",WhatKind,"'"])
-
- end.
-
-optionals(L) -> optionals(L,[],1).
-
-optionals([{'EXTENSIONMARK',_,_}|Rest],Acc,Pos) ->
- optionals(Rest,Acc,Pos); % optionals in extension are currently not handled
-optionals([#'ComponentType'{name=Name,prop='OPTIONAL'}|Rest],Acc,Pos) ->
- optionals(Rest,[{Name,Pos}|Acc],Pos+1);
-optionals([#'ComponentType'{name=Name,prop={'DEFAULT',_}}|Rest],Acc,Pos) ->
- optionals(Rest,[{Name,Pos}|Acc],Pos+1);
-optionals([#'ComponentType'{}|Rest],Acc,Pos) ->
- optionals(Rest,Acc,Pos+1);
-optionals([],Acc,_) ->
- lists:reverse(Acc).
-
-get_constraint(C,Key) ->
- case lists:keysearch(Key,1,C) of
- false ->
- no;
- {value,{_,V}} ->
- V
- end.
-
-
-get_class_fields(#classdef{typespec=ObjClass}) ->
- ObjClass#objectclass.fields;
-get_class_fields(#objectclass{fields=Fields}) ->
- Fields;
-get_class_fields(_) ->
- [].
-
-get_object_field(Name,ObjectFields) ->
- case lists:keysearch(Name,1,ObjectFields) of
- {value,Field} -> Field;
- false -> false
- end.
-
-%%encode_tag(TagClass(?UNI, APP etc), Form (?PRIM etx), TagInteger) ->
-%% 8bit Int | binary
-encode_tag_val(Class, Form, TagNo) when (TagNo =< 30) ->
- <<(Class bsr 6):2,(Form bsr 5):1,TagNo:5>>;
-
-encode_tag_val(Class, Form, TagNo) ->
- {Octets,_Len} = mk_object_val(TagNo),
- BinOct = list_to_binary(Octets),
- <<(Class bsr 6):2, (Form bsr 5):1, 31:5,BinOct/binary>>.
-
-%%%%%%%%%%%
-%% mk_object_val(Value) -> {OctetList, Len}
-%% returns a Val as a list of octets, the 8 bit is allways set to one except
-%% for the last octet, where its 0
-%%
-
-
-mk_object_val(Val) when Val =< 127 ->
- {[255 band Val], 1};
-mk_object_val(Val) ->
- mk_object_val(Val bsr 7, [Val band 127], 1).
-mk_object_val(0, Ack, Len) ->
- {Ack, Len};
-mk_object_val(Val, Ack, Len) ->
- mk_object_val(Val bsr 7, [((Val band 127) bor 128) | Ack], Len + 1).
-
-add_func(F={_Func,_Arity}) ->
- ets:insert(asn1_functab,{F}).
-
-
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen_per.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen_per.erl
deleted file mode 100644
index 8cd8d34918..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen_per.erl
+++ /dev/null
@@ -1,1190 +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: asn1ct_gen_per.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
-%%
--module(asn1ct_gen_per).
-
-%% Generate erlang module which handles (PER) encode and decode for
-%% all types in an ASN.1 module
-
--include("asn1_records.hrl").
-%-compile(export_all).
-
--export([pgen/4,gen_dec_prim/3,gen_encode_prim/4]).
--export([gen_obj_code/3,gen_objectset_code/2]).
--export([gen_decode/2, gen_decode/3]).
--export([gen_encode/2, gen_encode/3]).
--export([is_already_generated/2,more_genfields/1,get_class_fields/1,
- get_object_field/2]).
-
--import(asn1ct_gen, [emit/1,demit/1]).
-
-%% pgen(Erules, Module, TypeOrVal)
-%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module
-%% .hrl file is only generated if necessary
-%% Erules = per | ber
-%% Module = atom()
-%% TypeOrVal = {TypeList,ValueList}
-%% TypeList = ValueList = [atom()]
-
-pgen(OutFile,Erules,Module,TypeOrVal) ->
- asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,true).
-
-
-%% Generate ENCODING ******************************
-%%****************************************x
-
-
-gen_encode(Erules,Type) when record(Type,typedef) ->
- gen_encode_user(Erules,Type).
-%% case Type#typedef.typespec of
-%% Def when record(Def,type) ->
-%% gen_encode_user(Erules,Type);
-%% Def when tuple(Def),(element(1,Def) == 'Object') ->
-%% gen_encode_object(Erules,Type);
-%% Other ->
-%% exit({error,{asn1,{unknown,Other}}})
-%% end.
-
-gen_encode(Erules,Typename,#'ComponentType'{name=Cname,typespec=Type}) ->
- NewTypename = [Cname|Typename],
- gen_encode(Erules,NewTypename,Type);
-
-gen_encode(Erules,Typename,Type) when record(Type,type) ->
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- ObjFun =
- case lists:keysearch(objfun,1,Type#type.tablecinf) of
- {value,{_,_Name}} ->
-%% lists:concat([", ObjFun",Name]);
- ", ObjFun";
- false ->
- ""
- end,
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- case InnerType of
- 'SET' ->
- true;
- 'SEQUENCE' ->
- true;
- _ ->
- emit({nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'({'",asn1ct_gen:list2name(Typename),
- "',Val}",ObjFun,") ->",nl}),
- emit({"'enc_",asn1ct_gen:list2name(Typename),
- "'(Val",ObjFun,");",nl,nl})
- end,
- emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val",ObjFun,
- ") ->",nl}),
- asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
- _ ->
- true
- end.
-
-
-gen_encode_user(Erules,D) when record(D,typedef) ->
- CurrMod = get(currmod),
- Typename = [D#typedef.name],
- Def = D#typedef.typespec,
- InnerType = asn1ct_gen:get_inner(Def#type.def),
- case InnerType of
- 'SET' -> true;
- 'SEQUENCE' -> true;
- _ ->
- emit({nl,"'enc_",asn1ct_gen:list2name(Typename),"'({'",asn1ct_gen:list2name(Typename),"',Val}) ->",nl}),
- emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val);",nl,nl})
- end,
- emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val) ->",nl}),
- case asn1ct_gen:type(InnerType) of
- {primitive,bif} ->
- gen_encode_prim(Erules,Def,"false"),
- emit({".",nl});
- 'ASN1_OPEN_TYPE' ->
- gen_encode_prim(Erules,Def#type{def='ASN1_OPEN_TYPE'},"false"),
- emit({".",nl});
- {constructed,bif} ->
- asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,D);
- #'Externaltypereference'{module=CurrMod,type=Etype} ->
- emit({"'enc_",Etype,"'(Val).",nl,nl});
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit({"'",Emod,"':'enc_",Etype,"'(Val).",nl,nl});
- #typereference{val=Ename} ->
- emit({"'enc_",Ename,"'(Val).",nl,nl});
- {notype,_} ->
- emit({"'enc_",InnerType,"'(Val).",nl,nl})
- end.
-
-
-gen_encode_prim(Erules,D,DoTag) ->
- Value = case asn1ct_name:active(val) of
- true ->
- asn1ct_gen:mk_var(asn1ct_name:curr(val));
- false ->
- "Val"
- end,
- gen_encode_prim(Erules,D,DoTag,Value).
-
-gen_encode_prim(_Erules,D,_DoTag,Value) when record(D,type) ->
- Constraint = D#type.constraint,
- case D#type.def of
- 'INTEGER' ->
- emit({"?RT_PER:encode_integer(", %fel
- {asis,Constraint},",",Value,")"});
- {'INTEGER',NamedNumberList} ->
- emit({"?RT_PER:encode_integer(",
- {asis,Constraint},",",Value,",",
- {asis,NamedNumberList},")"});
- {'ENUMERATED',{Nlist1,Nlist2}} ->
- NewList = lists:concat([[{0,X}||{X,_} <- Nlist1],['EXT_MARK'],[{1,X}||{X,_} <- Nlist2]]),
- NewC = [{'ValueRange',{0,length(Nlist1)-1}}],
- emit(["case (case ",Value," of {_,_}->element(2,",Value,");_->",
- Value," end) of",nl]),
- emit_enc_enumerated_cases(NewC, NewList++[{asn1_enum,length(Nlist1)-1}], 0);
- {'ENUMERATED',NamedNumberList} ->
- NewList = [X||{X,_} <- NamedNumberList],
- NewC = [{'ValueRange',{0,length(NewList)-1}}],
- emit(["case (case ",Value," of {_,_}->element(2,",Value,");_->",
- Value," end) of",nl]),
- emit_enc_enumerated_cases(NewC, NewList, 0);
- {'BIT STRING',NamedNumberList} ->
- emit({"?RT_PER:encode_bit_string(",
- {asis,Constraint},",",Value,",",
- {asis,NamedNumberList},")"});
- 'NULL' ->
- emit({"?RT_PER:encode_null(",Value,")"});
- 'OBJECT IDENTIFIER' ->
- emit({"?RT_PER:encode_object_identifier(",Value,")"});
- 'ObjectDescriptor' ->
- emit({"?RT_PER:encode_ObjectDescriptor(",{asis,Constraint},
- ",",Value,")"});
- 'BOOLEAN' ->
- emit({"?RT_PER:encode_boolean(",Value,")"});
- 'OCTET STRING' ->
- emit({"?RT_PER:encode_octet_string(",{asis,Constraint},",",Value,")"});
- 'NumericString' ->
- emit({"?RT_PER:encode_NumericString(",{asis,Constraint},",",Value,")"});
- 'TeletexString' ->
- emit({"?RT_PER:encode_TeletexString(",{asis,Constraint},",",Value,")"});
- 'VideotexString' ->
- emit({"?RT_PER:encode_VideotexString(",{asis,Constraint},",",Value,")"});
- 'UTCTime' ->
- emit({"?RT_PER:encode_VisibleString(",{asis,Constraint},",",Value,")"});
- 'GeneralizedTime' ->
- emit({"?RT_PER:encode_VisibleString(",{asis,Constraint},",",Value,")"});
- 'GraphicString' ->
- emit({"?RT_PER:encode_GraphicString(",{asis,Constraint},",",Value,")"});
- 'VisibleString' ->
- emit({"?RT_PER:encode_VisibleString(",{asis,Constraint},",",Value,")"});
- 'GeneralString' ->
- emit({"?RT_PER:encode_GeneralString(",{asis,Constraint},",",Value,")"});
- 'PrintableString' ->
- emit({"?RT_PER:encode_PrintableString(",{asis,Constraint},",",Value,")"});
- 'IA5String' ->
- emit({"?RT_PER:encode_IA5String(",{asis,Constraint},",",Value,")"});
- 'BMPString' ->
- emit({"?RT_PER:encode_BMPString(",{asis,Constraint},",",Value,")"});
- 'UniversalString' ->
- emit({"?RT_PER:encode_UniversalString(",{asis,Constraint},",",Value,")"});
- 'ANY' ->
- emit(["?RT_PER:encode_open_type(", {asis,Constraint}, ",",
- Value, ")"]);
- 'ASN1_OPEN_TYPE' ->
- NewValue = case Constraint of
- [#'Externaltypereference'{type=Tname}] ->
- io_lib:format(
- "?RT_PER:complete(enc_~s(~s))",[Tname,Value]);
- [#type{def=#'Externaltypereference'{type=Tname}}] ->
- io_lib:format(
- "?RT_PER:complete(enc_~s(~s))",[Tname,Value]);
- _ -> Value
- end,
- emit(["?RT_PER:encode_open_type(", {asis,Constraint}, ",",
- NewValue, ")"]);
- XX ->
- exit({asn1_error,nyi,XX})
- end.
-
-emit_enc_enumerated_cases(C, [H], Count) ->
- emit_enc_enumerated_case(C, H, Count),
- emit([";",nl,"EnumVal -> exit({error,{asn1, {enumerated_not_in_range, EnumVal}}})"]),
- emit([nl,"end"]);
-emit_enc_enumerated_cases(C, ['EXT_MARK'|T], _Count) ->
- emit_enc_enumerated_cases(C, T, 0);
-emit_enc_enumerated_cases(C, [H1,H2|T], Count) ->
- emit_enc_enumerated_case(C, H1, Count),
- emit([";",nl]),
- emit_enc_enumerated_cases(C, [H2|T], Count+1).
-
-
-
-emit_enc_enumerated_case(_C, {asn1_enum,High}, _) ->
- emit([
- "{asn1_enum,EnumV} when integer(EnumV), EnumV > ",High," -> ",
- "[{bit,1},?RT_PER:encode_small_number(EnumV)]"]);
-emit_enc_enumerated_case(_C, 'EXT_MARK', _Count) ->
- true;
-emit_enc_enumerated_case(_C, {1,EnumName}, Count) ->
- emit(["'",EnumName,"' -> [{bit,1},?RT_PER:encode_small_number(",Count,")]"]);
-emit_enc_enumerated_case(C, {0,EnumName}, Count) ->
- emit(["'",EnumName,"' -> [{bit,0},?RT_PER:encode_integer(",{asis,C},", ",Count,")]"]);
-emit_enc_enumerated_case(C, EnumName, Count) ->
- emit(["'",EnumName,"' -> ?RT_PER:encode_integer(",{asis,C},", ",Count,")"]).
-
-
-%% Object code generating for encoding and decoding
-%% ------------------------------------------------
-
-gen_obj_code(Erules,_Module,Obj) when record(Obj,typedef) ->
- ObjName = Obj#typedef.name,
- Def = Obj#typedef.typespec,
- #'Externaltypereference'{module=Mod,type=ClassName} =
- Def#'Object'.classname,
- Class = asn1_db:dbget(Mod,ClassName),
- {object,_,Fields} = Def#'Object'.def,
- emit({nl,nl,nl,"%%================================"}),
- emit({nl,"%% ",ObjName}),
- emit({nl,"%%================================",nl}),
- EncConstructed =
- gen_encode_objectfields(ClassName,get_class_fields(Class),
- ObjName,Fields,[]),
- emit(nl),
- gen_encode_constr_type(Erules,EncConstructed),
- emit(nl),
- DecConstructed =
- gen_decode_objectfields(ClassName,get_class_fields(Class),
- ObjName,Fields,[]),
- emit(nl),
- gen_decode_constr_type(Erules,DecConstructed),
- emit(nl);
-gen_obj_code(_,_,Obj) when record(Obj,pobjectdef) ->
- ok.
-
-
-gen_encode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(V) ->
- emit(["'enc_",ObjName,"'(",{asis,Name},
- ",",V,",_RestPrimFieldName) ->",nl])
- end,
-% emit(["'enc_",ObjName,"'(",{asis,Name},
-% ", Val, _RestPrimFieldName) ->",nl]),
- MaybeConstr =
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} -> %% this case is illegal
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("_"),
- emit(" []"),
- [];
- {false,{'DEFAULT',DefaultType}} ->
- EmitFuncClause("Val"),
- gen_encode_default_call(ClassName,Name,DefaultType);
- {{Name,TypeSpec},_} ->
- %% A specified field owerwrites any 'DEFAULT' or
- %% 'OPTIONAL' field in the class
- EmitFuncClause("Val"),
- gen_encode_field_call(ObjName,Name,TypeSpec)
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_encode_objectfields(ClassName,Rest,ObjName,ObjectFields,
- MaybeConstr++ConstrAcc);
-gen_encode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(Attrs) ->
- emit(["'enc_",ObjName,"'(",{asis,Name},
- ",",Attrs,") ->",nl])
- end,
-% emit(["'enc_",ObjName,"'(",{asis,Name},
-% ", Val,[H|T]) ->",nl]),
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} ->
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("_,_"),
- emit([" exit({error,{'use of missing field in object', ",Name,
- "}})"]);
- {false,{'DEFAULT',_DefaultObject}} ->
- exit({error,{asn1,{"not implemented yet",Name}}});
- {{Name,TypeSpec},_} ->
- EmitFuncClause("Val,[H|T]"),
- case TypeSpec#typedef.name of
- {ExtMod,TypeName} ->
- emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
- "'(H, Val, T)"});
- TypeName ->
- emit({indent(3),"'enc_",TypeName,"'(H, Val, T)"})
- end
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_encode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
-gen_encode_objectfields(ClassName,[_C|Cs],O,OF,Acc) ->
- gen_encode_objectfields(ClassName,Cs,O,OF,Acc);
-gen_encode_objectfields(_,[],_,_,Acc) ->
- Acc.
-
-
-% gen_encode_objectfields(Class,ObjName,[{FieldName,Type}|Rest],ConstrAcc) ->
-% Fields = Class#objectclass.fields,
-
-% MaybeConstr =
-% case is_typefield(Fields,FieldName) of
-% true ->
-% Def = Type#typedef.typespec,
-% emit({"'enc_",ObjName,"'(",{asis,FieldName},
-% ", Val, Dummy) ->",nl}),
-
-% CAcc =
-% case Type#typedef.name of
-% {primitive,bif} ->
-% gen_encode_prim(per,Def,"false","Val"),
-% [];
-% {constructed,bif} ->
-% emit({" 'enc_",ObjName,'_',FieldName,
-% "'(Val)"}),
-% [{['enc_',ObjName,'_',FieldName],Def}];
-% {ExtMod,TypeName} ->
-% emit({" '",ExtMod,"':'enc_",TypeName,"'(Val)"}),
-% [];
-% TypeName ->
-% emit({" 'enc_",TypeName,"'(Val)"}),
-% []
-% end,
-% case more_genfields(Fields,Rest) of
-% true ->
-% emit({";",nl});
-% false ->
-% emit({".",nl})
-% end,
-% CAcc;
-% {false,objectfield} ->
-% emit({"'enc_",ObjName,"'(",{asis,FieldName},
-% ", Val, [H|T]) ->",nl}),
-% case Type#typedef.name of
-% {ExtMod,TypeName} ->
-% emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
-% "'(H, Val, T)"});
-% TypeName ->
-% emit({indent(3),"'enc_",TypeName,"'(H, Val, T)"})
-% end,
-% case more_genfields(Fields,Rest) of
-% true ->
-% emit({";",nl});
-% false ->
-% emit({".",nl})
-% end,
-% [];
-% {false,_} -> []
-% end,
-% gen_encode_objectfields(Class,ObjName,Rest,MaybeConstr ++ ConstrAcc);
-% gen_encode_objectfields(C,O,[H|T],Acc) ->
-% gen_encode_objectfields(C,O,T,Acc);
-% gen_encode_objectfields(_,_,[],Acc) ->
-% Acc.
-
-% gen_encode_constr_type(Erules,[{Name,Def}|Rest]) ->
-% emit({Name,"(Val) ->",nl}),
-% InnerType = asn1ct_gen:get_inner(Def#type.def),
-% asn1ct_gen:gen_encode_constructed(Erules,Name,InnerType,Def),
-% gen_encode_constr_type(Erules,Rest);
-gen_encode_constr_type(Erules,[TypeDef|Rest]) when record(TypeDef,typedef) ->
- case is_already_generated(enc,TypeDef#typedef.name) of
- true -> ok;
- _ ->
- Name = lists:concat(["enc_",TypeDef#typedef.name]),
- emit({Name,"(Val) ->",nl}),
- Def = TypeDef#typedef.typespec,
- InnerType = asn1ct_gen:get_inner(Def#type.def),
- asn1ct_gen:gen_encode_constructed(Erules,Name,InnerType,Def),
- gen_encode_constr_type(Erules,Rest)
- end;
-gen_encode_constr_type(_,[]) ->
- ok.
-
-gen_encode_field_call(ObjName,FieldName,Type) ->
- Def = Type#typedef.typespec,
- case Type#typedef.name of
- {primitive,bif} ->
- gen_encode_prim(per,Def,"false",
- "Val"),
- [];
- {constructed,bif} ->
- emit({" 'enc_",ObjName,'_',FieldName,
- "'(Val)"}),
- [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
- {ExtMod,TypeName} ->
- emit({" '",ExtMod,"':'enc_",TypeName,
- "'(Val)"}),
- [];
- TypeName ->
- emit({" 'enc_",TypeName,"'(Val)"}),
- []
- end.
-
-gen_encode_default_call(ClassName,FieldName,Type) ->
- CurrentMod = get(currmod),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
-%% asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
- emit([" 'enc_",ClassName,'_',FieldName,"'(Val)"]),
- [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
- typespec=Type}];
- {primitive,bif} ->
- gen_encode_prim(per,Type,"false","Val"),
- [];
- #'Externaltypereference'{module=CurrentMod,type=Etype} ->
- emit([" 'enc_",Etype,"'(Val)",nl]),
- [];
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit([" '",Emod,"':'enc_",Etype,"'(Val)",nl]),
- []
- end.
-
-
-gen_decode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(Bytes) ->
- emit(["'dec_",ObjName,"'(",{asis,Name},",",Bytes,
- ",_,_RestPrimFieldName) ->",nl])
- end,
- MaybeConstr=
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} -> %% this case is illegal
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("_"),
- emit([" asn1_NOVALUE"]),
- [];
- {false,{'DEFAULT',DefaultType}} ->
- EmitFuncClause("Bytes"),
- gen_decode_default_call(ClassName,Name,"Bytes",DefaultType);
- {{Name,TypeSpec},_} ->
- %% A specified field owerwrites any 'DEFAULT' or
- %% 'OPTIONAL' field in the class
- EmitFuncClause("Bytes"),
- gen_decode_field_call(ObjName,Name,"Bytes",TypeSpec)
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,MaybeConstr++ConstrAcc);
-gen_decode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(Attrs) ->
- emit(["'dec_",ObjName,"'(",{asis,Name},
- ",",Attrs,") ->",nl])
- end,
-% emit(["'dec_",ObjName,"'(",{asis,Name},
-% ", Bytes,_,[H|T]) ->",nl]),
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} ->
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("_,_,_"),
- emit([" exit({error,{'illegal use of missing field in object', ",Name,
- "}})"]);
- {false,{'DEFAULT',_DefaultObject}} ->
- exit({error,{asn1,{"not implemented yet",Name}}});
- {{Name,TypeSpec},_} ->
- EmitFuncClause("Bytes,_,[H|T]"),
- case TypeSpec#typedef.name of
- {ExtMod,TypeName} ->
- emit({indent(3),"'",ExtMod,"':'dec_",TypeName,
- "'(H, Bytes, telltype, T)"});
- TypeName ->
- emit({indent(3),"'dec_",TypeName,"'(H, Bytes, telltype, T)"})
- end
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
-gen_decode_objectfields(CN,[_C|Cs],O,OF,CAcc) ->
- gen_decode_objectfields(CN,Cs,O,OF,CAcc);
-gen_decode_objectfields(_,[],_,_,CAcc) ->
- CAcc.
-
-
-% gen_decode_objectfields(Class,ObjName,[{FieldName,Type}|Rest],ConstrAcc) ->
-% Fields = Class#objectclass.fields,
-
-% MaybeConstr =
-% case is_typefield(Fields,FieldName) of
-% true ->
-% Def = Type#typedef.typespec,
-% emit({"'dec_",ObjName,"'(",{asis,FieldName},
-% ", Val, Telltype, RestPrimFieldName) ->",nl}),
-
-% CAcc =
-% case Type#typedef.name of
-% {primitive,bif} ->
-% gen_dec_prim(per,Def,"Val"),
-% [];
-% {constructed,bif} ->
-% emit({" 'dec_",ObjName,'_',FieldName,
-% "'(Val, Telltype)"}),
-% [{['dec_',ObjName,'_',FieldName],Def}];
-% {ExtMod,TypeName} ->
-% emit({" '",ExtMod,"':'dec_",TypeName,
-% "'(Val, Telltype)"}),
-% [];
-% TypeName ->
-% emit({" 'dec_",TypeName,"'(Val, Telltype)"}),
-% []
-% end,
-% case more_genfields(Fields,Rest) of
-% true ->
-% emit({";",nl});
-% false ->
-% emit({".",nl})
-% end,
-% CAcc;
-% {false,objectfield} ->
-% emit({"'dec_",ObjName,"'(",{asis,FieldName},
-% ", Val, Telltype, [H|T]) ->",nl}),
-% case Type#typedef.name of
-% {ExtMod,TypeName} ->
-% emit({indent(3),"'",ExtMod,"':'dec_",TypeName,
-% "'(H, Val, Telltype, T)"});
-% TypeName ->
-% emit({indent(3),"'dec_",TypeName,
-% "'(H, Val, Telltype, T)"})
-% end,
-% case more_genfields(Fields,Rest) of
-% true ->
-% emit({";",nl});
-% false ->
-% emit({".",nl})
-% end,
-% [];
-% {false,_} ->
-% []
-% end,
-% gen_decode_objectfields(Class,ObjName,Rest,MaybeConstr ++ ConstrAcc);
-% gen_decode_objectfields(C,O,[H|T],CAcc) ->
-% gen_decode_objectfields(C,O,T,CAcc);
-% gen_decode_objectfields(_,_,[],CAcc) ->
-% CAcc.
-
-
-gen_decode_field_call(ObjName,FieldName,Bytes,Type) ->
- Def = Type#typedef.typespec,
- case Type#typedef.name of
- {primitive,bif} ->
- gen_dec_prim(per,Def,Bytes),
- [];
- {constructed,bif} ->
- emit({" 'dec_",ObjName,'_',FieldName,
- "'(",Bytes,",telltype)"}),
- [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
- {ExtMod,TypeName} ->
- emit({" '",ExtMod,"':'dec_",TypeName,
- "'(",Bytes,", telltype)"}),
- [];
- TypeName ->
- emit({" 'dec_",TypeName,"'(",Bytes,", telltype)"}),
- []
- end.
-
-gen_decode_default_call(ClassName,FieldName,Bytes,Type) ->
- CurrentMod = get(currmod),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- emit([" 'dec_",ClassName,'_',FieldName,"'(",Bytes,", telltype)"]),
- [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
- typespec=Type}];
- {primitive,bif} ->
- gen_dec_prim(per,Type,Bytes),
- [];
- #'Externaltypereference'{module=CurrentMod,type=Etype} ->
- emit([" 'dec_",Etype,"'(",Bytes,", telltype)",nl]),
- [];
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit([" '",Emod,"':'dec_",Etype,"'(",Bytes,", telltype)",nl]),
- []
- end.
-
-
-gen_decode_constr_type(Erules,[{Name,Def}|Rest]) ->
- emit({Name,"(Bytes,_) ->",nl}),
- InnerType = asn1ct_gen:get_inner(Def#type.def),
- asn1ct_gen:gen_decode_constructed(Erules,Name,InnerType,Def),
- gen_decode_constr_type(Erules,Rest);
-gen_decode_constr_type(Erules,[TypeDef|Rest]) when record(TypeDef,typedef) ->
- case is_already_generated(dec,TypeDef#typedef.name) of
- true -> ok;
- _ ->
- gen_decode(Erules,TypeDef)
- end,
- gen_decode_constr_type(Erules,Rest);
-gen_decode_constr_type(_,[]) ->
- ok.
-
-% more_genfields(Fields,[]) ->
-% false;
-% more_genfields(Fields,[{FieldName,_}|T]) ->
-% case is_typefield(Fields,FieldName) of
-% true -> true;
-% {false,objectfield} -> true;
-% {false,_} -> more_genfields(Fields,T)
-% end.
-
-more_genfields([]) ->
- false;
-more_genfields([Field|Fields]) ->
- case element(1,Field) of
- typefield ->
- true;
- objectfield ->
- true;
- _ ->
- more_genfields(Fields)
- end.
-
-% is_typefield(Fields,FieldName) ->
-% case lists:keysearch(FieldName,2,Fields) of
-% {value,Field} ->
-% case element(1,Field) of
-% typefield ->
-% true;
-% Other ->
-% {false,Other}
-% end;
-% _ ->
-% false
-% end.
-%% Object Set code generating for encoding and decoding
-%% ----------------------------------------------------
-gen_objectset_code(Erules,ObjSet) ->
- ObjSetName = ObjSet#typedef.name,
- Def = ObjSet#typedef.typespec,
-%% {ClassName,ClassDef} = Def#'ObjectSet'.class,
- #'Externaltypereference'{module=ClassModule,
- type=ClassName} = Def#'ObjectSet'.class,
- ClassDef = asn1_db:dbget(ClassModule,ClassName),
- UniqueFName = Def#'ObjectSet'.uniquefname,
- Set = Def#'ObjectSet'.set,
- emit({nl,nl,nl,"%%================================"}),
- emit({nl,"%% ",ObjSetName}),
- emit({nl,"%%================================",nl}),
- case ClassName of
- {_Module,ExtClassName} ->
- gen_objset_code(Erules,ObjSetName,UniqueFName,Set,
- ExtClassName,ClassDef);
- _ ->
- gen_objset_code(Erules,ObjSetName,UniqueFName,Set,
- ClassName,ClassDef)
- end,
- emit(nl).
-
-gen_objset_code(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassDef)->
- ClassFields = (ClassDef#classdef.typespec)#objectclass.fields,
- InternalFuncs=
- gen_objset_enc(ObjSetName,UniqueFName,Set,ClassName,ClassFields,1,[]),
- gen_objset_dec(ObjSetName,UniqueFName,Set,ClassName,ClassFields,1),
- gen_internal_funcs(Erules,InternalFuncs).
-
-%% gen_objset_enc iterates over the objects of the object set
-gen_objset_enc(_,{unique,undefined},_,_,_,_,_) ->
- %% There is no unique field in the class of this object set
- %% don't bother about the constraint
- [];
-gen_objset_enc(ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],
- ClName,ClFields,NthObj,Acc)->
- emit({"'getenc_",ObjSName,"'(",{asis,UniqueName},",",{asis,Val},
- ") ->",nl}),
- {InternalFunc,NewNthObj}=
- case ObjName of
- no_name ->
- gen_inlined_enc_funs(Fields,ClFields,ObjSName,NthObj);
- _Other ->
- emit({" fun 'enc_",ObjName,"'/3"}),
- {[],0}
- end,
- emit({";",nl}),
- gen_objset_enc(ObjSName,UniqueName,[T|Rest],ClName,ClFields,
- NewNthObj,InternalFunc ++ Acc);
-gen_objset_enc(ObjSetName,UniqueName,
- [{ObjName,Val,Fields}],_ClName,ClFields,NthObj,Acc) ->
-
- emit({"'getenc_",ObjSetName,"'(",{asis,UniqueName},",",
- {asis,Val},") ->",nl}),
- {InternalFunc,_}=
- case ObjName of
- no_name ->
- gen_inlined_enc_funs(Fields,ClFields,ObjSetName,NthObj);
- _Other ->
- emit({" fun 'enc_",ObjName,"'/3"}),
- {[],NthObj}
- end,
- emit({".",nl,nl}),
- InternalFunc++Acc;
-gen_objset_enc(ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
- _ClFields,_NthObj,Acc) ->
- emit({"'getenc_",ObjSetName,"'(_, _) ->",nl}),
- emit({indent(3),"fun(_, Val, _) ->",nl}),
- emit({indent(6),"[{octets,Val}]",nl}),
- emit({indent(3),"end.",nl,nl}),
- Acc;
-gen_objset_enc(_,_,[],_,_,_,Acc) ->
- Acc.
-
-%% gen_inlined_enc_funs for each object iterates over all fields of a
-%% class, and for each typefield it checks if the object has that
-%% field and emits the proper code.
-gen_inlined_enc_funs(Fields,[{typefield,Name,_}|Rest],ObjSetName,NthObj) ->
- InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when record(Type,type) ->
- emit({indent(3),"fun(Type, Val, _) ->",nl,
- indent(6),"case Type of",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
- {value,{_,Type}} when record(Type,typedef) ->
- emit({indent(3),"fun(Type, Val, _) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- {Ret,N} = emit_inner_of_fun(Type,InternalDefFunName),
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
- false ->
- gen_inlined_enc_funs(Fields,Rest,ObjSetName,NthObj)
- end;
-gen_inlined_enc_funs(Fields,[_H|Rest],ObjSetName,NthObj) ->
- gen_inlined_enc_funs(Fields,Rest,ObjSetName,NthObj);
-gen_inlined_enc_funs(_,[],_,NthObj) ->
- {[],NthObj}.
-
-gen_inlined_enc_funs1(Fields,[{typefield,Name,_}|Rest],ObjSetName,
- NthObj,Acc) ->
- InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- {Acc2,NAdd}=
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when record(Type,type) ->
- emit({";",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- {Ret++Acc,N};
- {value,{_,Type}} when record(Type,typedef) ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- {Ret++Acc,N};
- false ->
- {Acc,0}
- end,
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+NAdd,Acc2);
-gen_inlined_enc_funs1(Fields,[_H|Rest],ObjSetName,NthObj,Acc)->
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj,Acc);
-gen_inlined_enc_funs1(_,[],_,NthObj,Acc) ->
- emit({nl,indent(6),"end",nl}),
- emit({indent(3),"end"}),
- {Acc,NthObj}.
-
-emit_inner_of_fun(TDef=#typedef{name={ExtMod,Name},typespec=Type},
- InternalDefFunName) ->
- case {ExtMod,Name} of
- {primitive,bif} ->
- emit(indent(12)),
- gen_encode_prim(per,Type,dotag,"Val"),
- {[],0};
- {constructed,bif} ->
- emit([indent(12),"'enc_",
- InternalDefFunName,"'(Val)"]),
- {[TDef#typedef{name=InternalDefFunName}],1};
- _ ->
- emit({indent(12),"'",ExtMod,"':'enc_",Name,"'(Val)"}),
- {[],0}
- end;
-emit_inner_of_fun(#typedef{name=Name},_) ->
- emit({indent(12),"'enc_",Name,"'(Val)"}),
- {[],0};
-emit_inner_of_fun(Type,_) when record(Type,type) ->
- CurrMod = get(currmod),
- case Type#type.def of
- Def when atom(Def) ->
- emit({indent(9),Def," ->",nl,indent(12)}),
- gen_encode_prim(erules,Type,dotag,"Val");
- TRef when record(TRef,typereference) ->
- T = TRef#typereference.val,
- emit({indent(9),T," ->",nl,indent(12),"'enc_",T,"'(Val)"});
- #'Externaltypereference'{module=CurrMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),"'enc_",T,"'(Val)"});
- #'Externaltypereference'{module=ExtMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),ExtMod,":'enc_",
- T,"'(Val)"})
- end,
- {[],0}.
-
-indent(N) ->
- lists:duplicate(N,32). % 32 = space
-
-
-gen_objset_dec(_,{unique,undefined},_,_,_,_) ->
- %% There is no unique field in the class of this object set
- %% don't bother about the constraint
- ok;
-gen_objset_dec(ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],ClName,
- ClFields,NthObj)->
-
- emit({"'getdec_",ObjSName,"'(",{asis,UniqueName},",",{asis,Val},
- ") ->",nl}),
- NewNthObj=
- case ObjName of
- no_name ->
- gen_inlined_dec_funs(Fields,ClFields,ObjSName,NthObj);
- _Other ->
- emit({" fun 'dec_",ObjName,"'/4"}),
- NthObj
- end,
- emit({";",nl}),
- gen_objset_dec(ObjSName,UniqueName,[T|Rest],ClName,ClFields,NewNthObj);
-gen_objset_dec(ObjSetName,UniqueName,[{ObjName,Val,Fields}],_ClName,
- ClFields,NthObj) ->
-
- emit({"'getdec_",ObjSetName,"'(",{asis,UniqueName},",",{asis,Val},
- ") ->",nl}),
- case ObjName of
- no_name ->
- gen_inlined_dec_funs(Fields,ClFields,ObjSetName,NthObj);
- _Other ->
- emit({" fun 'dec_",ObjName,"'/4"})
- end,
- emit({".",nl,nl}),
- ok;
-gen_objset_dec(ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,_ClFields,
- _NthObj) ->
- emit({"'getdec_",ObjSetName,"'(_, _) ->",nl}),
- emit({indent(3),"fun(Attr1, Bytes, _,_) ->",nl}),
-%% emit({indent(6),"?RT_PER:decode_open_type(Bytes,[])",nl}),
- emit({indent(6),"{Bytes,Attr1}",nl}),
- emit({indent(3),"end.",nl,nl}),
- ok;
-gen_objset_dec(_,_,[],_,_,_) ->
- ok.
-
-gen_inlined_dec_funs(Fields,[{typefield,Name,_}|Rest],
- ObjSetName,NthObj) ->
- InternalDefFunName = [NthObj,Name,ObjSetName],
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when record(Type,type) ->
- emit({indent(3),"fun(Type, Val, _, _) ->",nl,
- indent(6),"case Type of",nl}),
- N=emit_inner_of_decfun(Type,InternalDefFunName),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
- {value,{_,Type}} when record(Type,typedef) ->
- emit({indent(3),"fun(Type, Val, _, _) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- N=emit_inner_of_decfun(Type,InternalDefFunName),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
- false ->
- gen_inlined_dec_funs(Fields,Rest,ObjSetName,NthObj)
- end;
-gen_inlined_dec_funs(Fields,[_|Rest],ObjSetName,NthObj) ->
- gen_inlined_dec_funs(Fields,Rest,ObjSetName,NthObj);
-gen_inlined_dec_funs(_,[],_,NthObj) ->
- NthObj.
-
-gen_inlined_dec_funs1(Fields,[{typefield,Name,_}|Rest],
- ObjSetName,NthObj) ->
- InternalDefFunName = [NthObj,Name,ObjSetName],
- N=case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when record(Type,type) ->
- emit({";",nl}),
- emit_inner_of_decfun(Type,InternalDefFunName);
- {value,{_,Type}} when record(Type,typedef) ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- emit_inner_of_decfun(Type,InternalDefFunName);
- false ->
- 0
- end,
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
-gen_inlined_dec_funs1(Fields,[_|Rest],ObjSetName,NthObj)->
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj);
-gen_inlined_dec_funs1(_,[],_,NthObj) ->
- emit({nl,indent(6),"end",nl}),
- emit({indent(3),"end"}),
- NthObj.
-
-emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type},
- InternalDefFunName) ->
- case {ExtName,Name} of
- {primitive,bif} ->
- emit(indent(12)),
- gen_dec_prim(per,Type,"Val"),
- 0;
- {constructed,bif} ->
- emit({indent(12),"'dec_",
- asn1ct_gen:list2name(InternalDefFunName),"'(Val)"}),
- 1;
- _ ->
- emit({indent(12),"'",ExtName,"':'dec_",Name,"'(Val, telltype)"}),
- 0
- end;
-emit_inner_of_decfun(#typedef{name=Name},_) ->
- emit({indent(12),"'dec_",Name,"'(Val, telltype)"}),
- 0;
-emit_inner_of_decfun(Type,_) when record(Type,type) ->
- CurrMod = get(currmod),
- case Type#type.def of
- Def when atom(Def) ->
- emit({indent(9),Def," ->",nl,indent(12)}),
- gen_dec_prim(erules,Type,"Val");
- TRef when record(TRef,typereference) ->
- T = TRef#typereference.val,
- emit({indent(9),T," ->",nl,indent(12),"'dec_",T,"'(Val)"});
- #'Externaltypereference'{module=CurrMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),"'dec_",T,"'(Val)"});
- #'Externaltypereference'{module=ExtMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),ExtMod,":'dec_",
- T,"'(Val)"})
- end,
- 0.
-
-
-gen_internal_funcs(_,[]) ->
- ok;
-gen_internal_funcs(Erules,[TypeDef|Rest]) ->
- gen_encode_user(Erules,TypeDef),
- emit([nl,nl,"'dec_",TypeDef#typedef.name,"'(Bytes) ->",nl]),
- gen_decode_user(Erules,TypeDef),
- gen_internal_funcs(Erules,Rest).
-
-
-
-%% DECODING *****************************
-%%***************************************
-
-
-gen_decode(Erules,Type) when record(Type,typedef) ->
- D = Type,
- emit({nl,nl}),
- emit({"'dec_",Type#typedef.name,"'(Bytes,_) ->",nl}),
- dbdec(Type#typedef.name),
- gen_decode_user(Erules,D).
-
-gen_decode(Erules,Tname,#'ComponentType'{name=Cname,typespec=Type}) ->
- NewTname = [Cname|Tname],
- gen_decode(Erules,NewTname,Type);
-
-gen_decode(Erules,Typename,Type) when record(Type,type) ->
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- ObjFun =
- case Type#type.tablecinf of
- [{objfun,_}|_R] ->
- ", ObjFun";
- _ ->
- ""
- end,
- emit({nl,"'dec_",asn1ct_gen:list2name(Typename),
- "'(Bytes,_",ObjFun,") ->",nl}),
- dbdec(Typename),
- asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,Type);
- _ ->
- true
- end.
-
-dbdec(Type) when list(Type)->
- demit({"io:format(\"decoding: ",asn1ct_gen:list2name(Type),"~w~n\",[Bytes]),",nl});
-dbdec(Type) ->
- demit({"io:format(\"decoding: ",{asis,Type},"~w~n\",[Bytes]),",nl}).
-
-gen_decode_user(Erules,D) when record(D,typedef) ->
- CurrMod = get(currmod),
- Typename = [D#typedef.name],
- Def = D#typedef.typespec,
- InnerType = asn1ct_gen:get_inner(Def#type.def),
- case asn1ct_gen:type(InnerType) of
- {primitive,bif} ->
- gen_dec_prim(Erules,Def,"Bytes"),
- emit({".",nl,nl});
- 'ASN1_OPEN_TYPE' ->
- gen_dec_prim(Erules,Def#type{def='ASN1_OPEN_TYPE'},"Bytes"),
- emit({".",nl,nl});
- {constructed,bif} ->
- asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,D);
- #typereference{val=Dname} ->
- emit({"'dec_",Dname,"'(Bytes,telltype)"}),
- emit({".",nl,nl});
- #'Externaltypereference'{module=CurrMod,type=Etype} ->
- emit({"'dec_",Etype,"'(Bytes,telltype).",nl,nl});
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit({"'",Emod,"':'dec_",Etype,"'(Bytes,telltype).",nl,nl});
- Other ->
- exit({error,{asn1,{unknown,Other}}})
- end.
-
-
-gen_dec_prim(_Erules,Att,BytesVar) ->
- Typename = Att#type.def,
- Constraint = Att#type.constraint,
- case Typename of
- 'INTEGER' ->
- emit({"?RT_PER:decode_integer(",BytesVar,",",
- {asis,Constraint},")"});
- {'INTEGER',NamedNumberList} ->
- emit({"?RT_PER:decode_integer(",BytesVar,",",
- {asis,Constraint},",",
- {asis,NamedNumberList},")"});
- {'BIT STRING',NamedNumberList} ->
- case get(compact_bit_string) of
- true ->
- emit({"?RT_PER:decode_compact_bit_string(",
- BytesVar,",",{asis,Constraint},",",
- {asis,NamedNumberList},")"});
- _ ->
- emit({"?RT_PER:decode_bit_string(",BytesVar,",",
- {asis,Constraint},",",
- {asis,NamedNumberList},")"})
- end;
- 'NULL' ->
- emit({"?RT_PER:decode_null(",
- BytesVar,")"});
- 'OBJECT IDENTIFIER' ->
- emit({"?RT_PER:decode_object_identifier(",
- BytesVar,")"});
- 'ObjectDescriptor' ->
- emit({"?RT_PER:decode_ObjectDescriptor(",
- BytesVar,")"});
- {'ENUMERATED',{NamedNumberList1,NamedNumberList2}} ->
- NewTup = {list_to_tuple([X||{X,_} <- NamedNumberList1]),
- list_to_tuple([X||{X,_} <- NamedNumberList2])},
- NewC = [{'ValueRange',{0,size(element(1,NewTup))-1}}],
- emit({"?RT_PER:decode_enumerated(",BytesVar,",",
- {asis,NewC},",",
- {asis,NewTup},")"});
- {'ENUMERATED',NamedNumberList} ->
- NewTup = list_to_tuple([X||{X,_} <- NamedNumberList]),
- NewC = [{'ValueRange',{0,size(NewTup)-1}}],
- emit({"?RT_PER:decode_enumerated(",BytesVar,",",
- {asis,NewC},",",
- {asis,NewTup},")"});
- 'BOOLEAN'->
- emit({"?RT_PER:decode_boolean(",BytesVar,")"});
- 'OCTET STRING' ->
- emit({"?RT_PER:decode_octet_string(",BytesVar,",",
- {asis,Constraint},")"});
- 'NumericString' ->
- emit({"?RT_PER:decode_NumericString(",BytesVar,",",
- {asis,Constraint},")"});
- 'TeletexString' ->
- emit({"?RT_PER:decode_TeletexString(",BytesVar,",",
- {asis,Constraint},")"});
- 'VideotexString' ->
- emit({"?RT_PER:decode_VideotexString(",BytesVar,",",
- {asis,Constraint},")"});
- 'UTCTime' ->
- emit({"?RT_PER:decode_VisibleString(",BytesVar,",",
- {asis,Constraint},")"});
- 'GeneralizedTime' ->
- emit({"?RT_PER:decode_VisibleString(",BytesVar,",",
- {asis,Constraint},")"});
- 'GraphicString' ->
- emit({"?RT_PER:decode_GraphicString(",BytesVar,",",
- {asis,Constraint},")"});
- 'VisibleString' ->
- emit({"?RT_PER:decode_VisibleString(",BytesVar,",",
- {asis,Constraint},")"});
- 'GeneralString' ->
- emit({"?RT_PER:decode_GeneralString(",BytesVar,",",
- {asis,Constraint},")"});
- 'PrintableString' ->
- emit({"?RT_PER:decode_PrintableString(",BytesVar,",",{asis,Constraint},")"});
- 'IA5String' ->
- emit({"?RT_PER:decode_IA5String(",BytesVar,",",{asis,Constraint},")"});
- 'BMPString' ->
- emit({"?RT_PER:decode_BMPString(",BytesVar,",",{asis,Constraint},")"});
- 'UniversalString' ->
- emit({"?RT_PER:decode_UniversalString(",BytesVar,",",{asis,Constraint},")"});
- 'ANY' ->
- emit(["?RT_PER:decode_open_type(",BytesVar,",",
- {asis,Constraint}, ")"]);
- 'ASN1_OPEN_TYPE' ->
- case Constraint of
- [#'Externaltypereference'{type=Tname}] ->
- emit(["fun(FBytes) ->",nl,
- " {XTerm,XBytes} = "]),
- emit(["?RT_PER:decode_open_type(FBytes,[]),",nl]),
- emit([" {YTerm,_} = dec_",Tname,"(XTerm,mandatory),",nl]),
- emit([" {YTerm,XBytes} end(",BytesVar,")"]);
- [#type{def=#'Externaltypereference'{type=Tname}}] ->
- emit(["fun(FBytes) ->",nl,
- " {XTerm,XBytes} = "]),
- emit(["?RT_PER:decode_open_type(FBytes,[]),",nl]),
- emit([" {YTerm,_} = dec_",Tname,"(XTerm,mandatory),",nl]),
- emit([" {YTerm,XBytes} end(",BytesVar,")"]);
- _ ->
- emit(["?RT_PER:decode_open_type(",BytesVar,",[])"])
- end;
- Other ->
- exit({'cant decode' ,Other})
- end.
-
-
-is_already_generated(Operation,Name) ->
- case get(class_default_type) of
- undefined ->
- put(class_default_type,[{Operation,Name}]),
- false;
- GeneratedList ->
- case lists:member({Operation,Name},GeneratedList) of
- true ->
- true;
- false ->
- put(class_default_type,[{Operation,Name}|GeneratedList]),
- false
- end
- end.
-
-get_class_fields(#classdef{typespec=ObjClass}) ->
- ObjClass#objectclass.fields;
-get_class_fields(#objectclass{fields=Fields}) ->
- Fields;
-get_class_fields(_) ->
- [].
-
-
-get_object_field(Name,ObjectFields) ->
- case lists:keysearch(Name,1,ObjectFields) of
- {value,Field} -> Field;
- false -> false
- end.
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen_per_rt2ct.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen_per_rt2ct.erl
deleted file mode 100644
index 70a017ac6a..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_gen_per_rt2ct.erl
+++ /dev/null
@@ -1,1811 +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: asn1ct_gen_per_rt2ct.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
-%%
--module(asn1ct_gen_per_rt2ct).
-
-%% Generate erlang module which handles (PER) encode and decode for
-%% all types in an ASN.1 module
-
--include("asn1_records.hrl").
-%-compile(export_all).
-
--export([pgen/4,gen_dec_prim/3,gen_encode_prim/4]).
--export([gen_obj_code/3,gen_objectset_code/2]).
--export([gen_decode/2, gen_decode/3]).
--export([gen_encode/2, gen_encode/3]).
-
--import(asn1ct_gen, [emit/1,demit/1]).
--import(asn1ct_gen_per, [is_already_generated/2,more_genfields/1,
- get_class_fields/1,get_object_field/2]).
-
-%% pgen(Erules, Module, TypeOrVal)
-%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module
-%% .hrl file is only generated if necessary
-%% Erules = per | ber
-%% Module = atom()
-%% TypeOrVal = {TypeList,ValueList}
-%% TypeList = ValueList = [atom()]
-
-pgen(OutFile,Erules,Module,TypeOrVal) ->
- asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,true).
-
-
-%% Generate ENCODING ******************************
-%%****************************************x
-
-
-gen_encode(Erules,Type) when record(Type,typedef) ->
- gen_encode_user(Erules,Type).
-
-gen_encode(Erules,Typename,#'ComponentType'{name=Cname,typespec=Type}) ->
- NewTypename = [Cname|Typename],
- gen_encode(Erules,NewTypename,Type);
-
-gen_encode(Erules,Typename,Type) when record(Type,type) ->
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- ObjFun =
- case lists:keysearch(objfun,1,Type#type.tablecinf) of
- {value,{_,_Name}} ->
- ", ObjFun";
- false ->
- ""
- end,
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- case InnerType of
- 'SET' ->
- true;
- 'SEQUENCE' ->
- true;
- _ ->
- emit({nl,"'enc_",asn1ct_gen:list2name(Typename),
- "'({'",asn1ct_gen:list2name(Typename),
- "',Val}",ObjFun,") ->",nl}),
- emit({"'enc_",asn1ct_gen:list2name(Typename),
- "'(Val",ObjFun,");",nl,nl})
- end,
- emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val",ObjFun,
- ") ->",nl}),
- asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
- _ ->
- true
- end.
-
-
-gen_encode_user(Erules,D) when record(D,typedef) ->
- CurrMod = get(currmod),
- Typename = [D#typedef.name],
- Def = D#typedef.typespec,
- InnerType = asn1ct_gen:get_inner(Def#type.def),
- case InnerType of
- 'SET' -> true;
- 'SEQUENCE' -> true;
- _ ->
- emit({nl,"'enc_",asn1ct_gen:list2name(Typename),"'({'",asn1ct_gen:list2name(Typename),"',Val}) ->",nl}),
- emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val);",nl,nl})
- end,
- emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val) ->",nl}),
- case asn1ct_gen:type(InnerType) of
- {primitive,bif} ->
- gen_encode_prim(Erules,Def,"false"),
- emit({".",nl});
- 'ASN1_OPEN_TYPE' ->
- gen_encode_prim(Erules,Def#type{def='ASN1_OPEN_TYPE'},"false"),
- emit({".",nl});
- {constructed,bif} ->
- asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,D);
- #'Externaltypereference'{module=CurrMod,type=Etype} ->
- emit({"'enc_",Etype,"'(Val).",nl,nl});
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit({"'",Emod,"':'enc_",Etype,"'(Val).",nl,nl});
- #typereference{val=Ename} ->
- emit({"'enc_",Ename,"'(Val).",nl,nl});
- {notype,_} ->
- emit({"'enc_",InnerType,"'(Val).",nl,nl})
- end.
-
-
-gen_encode_prim(Erules,D,DoTag) ->
- Value = case asn1ct_name:active(val) of
- true ->
- asn1ct_gen:mk_var(asn1ct_name:curr(val));
- false ->
- "Val"
- end,
- gen_encode_prim(Erules,D,DoTag,Value).
-
-
-
-
-
-gen_encode_prim(_Erules,D,_DoTag,Value) when record(D,type) ->
- Constraint = D#type.constraint,
- case D#type.def of
- 'INTEGER' ->
- EffectiveConstr = effective_constraint(integer,Constraint),
- emit([" %%INTEGER with effective constraint: ",
- {asis,EffectiveConstr},nl]),
- emit_enc_integer(EffectiveConstr,Value);
- {'INTEGER',NamedNumberList} ->
- EffectiveConstr = effective_constraint(integer,Constraint),
- %% maybe an emit_enc_NNL_integer
- emit([" %%INTEGER with effective constraint: ",
- {asis,EffectiveConstr},nl]),
- emit_enc_integer_NNL(EffectiveConstr,Value,NamedNumberList);
- {'ENUMERATED',{Nlist1,Nlist2}} ->
- NewList = lists:concat([[{0,X}||{X,_} <- Nlist1],['EXT_MARK'],[{1,X}||{X,_} <- Nlist2]]),
- NewC = [{'ValueRange',{0,length(Nlist1)-1}}],
- emit(["case (case ",Value," of {_,_}->element(2,",Value,");_->",
- Value," end) of",nl]),
- emit_enc_enumerated_cases(NewC, NewList++[{asn1_enum,length(Nlist1)-1}], 0);
- {'ENUMERATED',NamedNumberList} ->
- NewList = [X||{X,_} <- NamedNumberList],
- NewC = effective_constraint(integer,
- [{'ValueRange',
- {0,length(NewList)-1}}]),
- NewVal = enc_enum_cases(Value,NewList),
- emit_enc_integer(NewC,NewVal);
- {'BIT STRING',NamedNumberList} ->
- EffectiveC = effective_constraint(bitstring,Constraint),
- case EffectiveC of
- 0 -> emit({"[]"});
- _ ->
- emit({"?RT_PER:encode_bit_string(",
- {asis,EffectiveC},",",Value,",",
- {asis,NamedNumberList},")"})
- end;
- 'NULL' ->
- emit({"?RT_PER:encode_null(",Value,")"});
- 'OBJECT IDENTIFIER' ->
- emit({"?RT_PER:encode_object_identifier(",Value,")"});
- 'ObjectDescriptor' ->
- emit({"?RT_PER:encode_ObjectDescriptor(",{asis,Constraint},
- ",",Value,")"});
- 'BOOLEAN' ->
-% emit({"?RT_PER:encode_boolean(",Value,")"});
- emit({"case ",Value," of",nl,
-% " true -> {bits,1,1};",nl,
- " true -> [1];",nl,
-% " false -> {bits,1,0};",nl,
- " false -> [0];",nl,
- " _ -> exit({error,{asn1,{encode_boolean,",Value,"}}})",nl,
- "end"});
- 'OCTET STRING' ->
- emit_enc_octet_string(Constraint,Value);
-
- 'NumericString' ->
- emit_enc_known_multiplier_string('NumericString',Constraint,Value);
- 'TeletexString' ->
- emit({"?RT_PER:encode_TeletexString(",{asis,Constraint},",",Value,")"});
- 'VideotexString' ->
- emit({"?RT_PER:encode_VideotexString(",{asis,Constraint},",",Value,")"});
- 'UTCTime' ->
- emit_enc_known_multiplier_string('VisibleString',Constraint,Value);
- 'GeneralizedTime' ->
- emit_enc_known_multiplier_string('VisibleString',Constraint,Value);
- 'GraphicString' ->
- emit({"?RT_PER:encode_GraphicString(",{asis,Constraint},",",Value,")"});
- 'VisibleString' ->
- emit_enc_known_multiplier_string('VisibleString',Constraint,Value);
- 'GeneralString' ->
- emit({"?RT_PER:encode_GeneralString(",{asis,Constraint},",",Value,")"});
- 'PrintableString' ->
- emit_enc_known_multiplier_string('PrintableString',Constraint,Value);
- 'IA5String' ->
- emit_enc_known_multiplier_string('IA5String',Constraint,Value);
- 'BMPString' ->
- emit_enc_known_multiplier_string('BMPString',Constraint,Value);
- 'UniversalString' ->
- emit_enc_known_multiplier_string('UniversalString',Constraint,Value);
- 'ANY' ->
- emit(["?RT_PER:encode_open_type(", {asis,Constraint}, ",",
- Value, ")"]);
- 'ASN1_OPEN_TYPE' ->
- NewValue = case Constraint of
- [#'Externaltypereference'{type=Tname}] ->
- io_lib:format(
- "?RT_PER:complete(enc_~s(~s))",[Tname,Value]);
- [#type{def=#'Externaltypereference'{type=Tname}}] ->
- io_lib:format(
- "?RT_PER:complete(enc_~s(~s))",[Tname,Value]);
- _ -> Value
- end,
- emit(["?RT_PER:encode_open_type(", {asis,Constraint}, ",",
- NewValue, ")"]);
- XX ->
- exit({asn1_error,nyi,XX})
- end.
-
-emit_enc_known_multiplier_string(StringType,C,Value) ->
- SizeC =
- case get_constraint(C,'SizeConstraint') of
- L when list(L) -> {lists:min(L),lists:max(L)};
- L -> L
- end,
- PAlphabC = get_constraint(C,'PermittedAlphabet'),
- case {StringType,PAlphabC} of
- {'UniversalString',{_,_}} ->
- exit({error,{asn1,{'not implemented',"UniversalString with "
- "PermittedAlphabet constraint"}}});
- {'BMPString',{_,_}} ->
- exit({error,{asn1,{'not implemented',"BMPString with "
- "PermittedAlphabet constraint"}}});
- _ -> ok
- end,
- NumBits = get_NumBits(C,StringType),
- CharOutTab = get_CharOutTab(C,StringType),
- %% NunBits and CharOutTab for chars_encode
- emit_enc_k_m_string(StringType,SizeC,NumBits,CharOutTab,Value).
-
-emit_enc_k_m_string(_StringType,0,_NumBits,_CharOutTab,_Value) ->
- emit({"[]"});
-emit_enc_k_m_string(StringType,SizeC,NumBits,CharOutTab,Value) ->
- emit({"?RT_PER:encode_known_multiplier_string(",{asis,StringType},",",
- {asis,SizeC},",",NumBits,",",{asis,CharOutTab},",",Value,")"}).
-
-emit_dec_known_multiplier_string(StringType,C,BytesVar) ->
- SizeC = get_constraint(C,'SizeConstraint'),
- PAlphabC = get_constraint(C,'PermittedAlphabet'),
- case {StringType,PAlphabC} of
- {'BMPString',{_,_}} ->
- exit({error,{asn1,
- {'not implemented',
- "BMPString with PermittedAlphabet "
- "constraint"}}});
- _ ->
- ok
- end,
- NumBits = get_NumBits(C,StringType),
- CharInTab = get_CharInTab(C,StringType),
- case SizeC of
- 0 ->
- emit({"{[],",BytesVar,"}"});
- _ ->
- emit({"?RT_PER:decode_known_multiplier_string(",
- {asis,StringType},",",{asis,SizeC},",",NumBits,
- ",",{asis,CharInTab},",",BytesVar,")"})
- end.
-
-
-%% copied from run time module
-
-get_CharOutTab(C,StringType) ->
- get_CharTab(C,StringType,out).
-
-get_CharInTab(C,StringType) ->
- get_CharTab(C,StringType,in).
-
-get_CharTab(C,StringType,InOut) ->
- case get_constraint(C,'PermittedAlphabet') of
- {'SingleValue',Sv} ->
- get_CharTab2(C,StringType,hd(Sv),lists:max(Sv),Sv,InOut);
- no ->
- case StringType of
- 'IA5String' ->
- {0,16#7F,notab};
- 'VisibleString' ->
- get_CharTab2(C,StringType,16#20,16#7F,notab,InOut);
- 'PrintableString' ->
- Chars = lists:sort(
- " '()+,-./0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
- get_CharTab2(C,StringType,hd(Chars),lists:max(Chars),Chars,InOut);
- 'NumericString' ->
- get_CharTab2(C,StringType,16#20,$9," 0123456789",InOut);
- 'UniversalString' ->
- {0,16#FFFFFFFF,notab};
- 'BMPString' ->
- {0,16#FFFF,notab}
- end
- end.
-
-get_CharTab2(C,StringType,Min,Max,Chars,InOut) ->
- BitValMax = (1 bsl get_NumBits(C,StringType))-1,
- if
- Max =< BitValMax ->
- {0,Max,notab};
- true ->
- case InOut of
- out ->
- {Min,Max,create_char_tab(Min,Chars)};
- in ->
- {Min,Max,list_to_tuple(Chars)}
- end
- end.
-
-create_char_tab(Min,L) ->
- list_to_tuple(create_char_tab(Min,L,0)).
-create_char_tab(Min,[Min|T],V) ->
- [V|create_char_tab(Min+1,T,V+1)];
-create_char_tab(_Min,[],_V) ->
- [];
-create_char_tab(Min,L,V) ->
- [false|create_char_tab(Min+1,L,V)].
-
-get_NumBits(C,StringType) ->
- case get_constraint(C,'PermittedAlphabet') of
- {'SingleValue',Sv} ->
- charbits(length(Sv),aligned);
- no ->
- case StringType of
- 'IA5String' ->
- charbits(128,aligned); % 16#00..16#7F
- 'VisibleString' ->
- charbits(95,aligned); % 16#20..16#7E
- 'PrintableString' ->
- charbits(74,aligned); % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
- 'NumericString' ->
- charbits(11,aligned); % $ ,"0123456789"
- 'UniversalString' ->
- 32;
- 'BMPString' ->
- 16
- end
- end.
-
-charbits(NumOfChars,aligned) ->
- case charbits(NumOfChars) of
- 1 -> 1;
- 2 -> 2;
- B when B =< 4 -> 4;
- B when B =< 8 -> 8;
- B when B =< 16 -> 16;
- B when B =< 32 -> 32
- end.
-
-charbits(NumOfChars) when NumOfChars =< 2 -> 1;
-charbits(NumOfChars) when NumOfChars =< 4 -> 2;
-charbits(NumOfChars) when NumOfChars =< 8 -> 3;
-charbits(NumOfChars) when NumOfChars =< 16 -> 4;
-charbits(NumOfChars) when NumOfChars =< 32 -> 5;
-charbits(NumOfChars) when NumOfChars =< 64 -> 6;
-charbits(NumOfChars) when NumOfChars =< 128 -> 7;
-charbits(NumOfChars) when NumOfChars =< 256 -> 8;
-charbits(NumOfChars) when NumOfChars =< 512 -> 9;
-charbits(NumOfChars) when NumOfChars =< 1024 -> 10;
-charbits(NumOfChars) when NumOfChars =< 2048 -> 11;
-charbits(NumOfChars) when NumOfChars =< 4096 -> 12;
-charbits(NumOfChars) when NumOfChars =< 8192 -> 13;
-charbits(NumOfChars) when NumOfChars =< 16384 -> 14;
-charbits(NumOfChars) when NumOfChars =< 32768 -> 15;
-charbits(NumOfChars) when NumOfChars =< 65536 -> 16;
-charbits(NumOfChars) when integer(NumOfChars) ->
- 16 + charbits1(NumOfChars bsr 16).
-
-charbits1(0) ->
- 0;
-charbits1(NumOfChars) ->
- 1 + charbits1(NumOfChars bsr 1).
-
-%% copied from run time module
-
-emit_enc_octet_string(Constraint,Value) ->
- case get_constraint(Constraint,'SizeConstraint') of
- 0 ->
- emit({" []"});
- 1 ->
- asn1ct_name:new(tmpval),
- emit({" begin",nl}),
- emit({" [",{curr,tmpval},"] = ",Value,",",nl}),
-% emit({" {bits,8,",{curr,tmpval},"}",nl}),
- emit({" [10,8,",{curr,tmpval},"]",nl}),
- emit(" end");
- 2 ->
- asn1ct_name:new(tmpval),
- emit({" begin",nl}),
- emit({" [",{curr,tmpval},",",{next,tmpval},"] = ",
- Value,",",nl}),
-% emit({" [{bits,8,",{curr,tmpval},"},{bits,8,",
-% {next,tmpval},"}]",nl}),
- emit({" [[10,8,",{curr,tmpval},"],[10,8,",
- {next,tmpval},"]]",nl}),
- emit(" end"),
- asn1ct_name:new(tmpval);
- Sv when integer(Sv),Sv =< 256 ->
- asn1ct_name:new(tmpval),
- emit({" begin",nl}),
-% emit({" case length(",Value,") == ",Sv," of",nl}),
- emit({" case length(",Value,") of",nl}),
- emit({" ",{curr,tmpval}," when ",{curr,tmpval}," == ",Sv," -> [2,20,",{curr,tmpval},",",Value,"];",nl}),
- emit({" _ -> exit({error,{value_out_of_bounds,",Value,"}})",
- nl," end",nl}),
- emit(" end");
- Sv when integer(Sv),Sv =< 65535 ->
- asn1ct_name:new(tmpval),
- emit({" begin",nl}),
-% emit({" case length(",Value,") == ",Sv," of",nl}),
- emit({" case length(",Value,") of",nl}),
-% emit({" true -> [align,{octets,",Value,"}];",nl}),
- emit({" ",{curr,tmpval}," when ",{curr,tmpval}," == ",Sv," -> [2,21,",{curr,tmpval},",",Value,"];",nl}),
- emit({" _ -> exit({error,{value_out_of_bounds,",Value,"}})",
- nl," end",nl}),
- emit(" end");
- C ->
- emit({" ?RT_PER:encode_octet_string(",{asis,C},",false,",Value,")",nl})
- end.
-
-emit_dec_octet_string(Constraint,BytesVar) ->
- case get_constraint(Constraint,'SizeConstraint') of
- 0 ->
- emit({" {[],",BytesVar,"}",nl});
- {_,0} ->
- emit({" {[],",BytesVar,"}",nl});
- C ->
- emit({" ?RT_PER:decode_octet_string(",BytesVar,",",
- {asis,C},",false)",nl})
- end.
-
-emit_enc_integer_case(Value) ->
- case get(component_type) of
- {true,#'ComponentType'{prop=Prop}} ->
- emit({" begin",nl}),
- case Prop of
- Opt when Opt=='OPTIONAL';
- tuple(Opt),element(1,Opt)=='DEFAULT' ->
- emit({" case ",Value," of",nl}),
- ok;
- _ ->
- emit({" ",{curr,tmpval},"=",Value,",",nl}),
- emit({" case ",{curr,tmpval}," of",nl}),
- asn1ct_name:new(tmpval)
- end;
-% asn1ct_name:new(tmpval);
- _ ->
- emit({" case ",Value," of ",nl})
- end.
-emit_enc_integer_end_case() ->
- case get(component_type) of
- {true,_} ->
- emit({nl," end"}); % end of begin ... end
- _ -> ok
- end.
-
-
-emit_enc_integer_NNL(C,Value,NNL) ->
- EncVal = enc_integer_NNL_cases(Value,NNL),
- emit_enc_integer(C,EncVal).
-
-enc_integer_NNL_cases(Value,NNL) ->
- asn1ct_name:new(tmpval),
- TmpVal = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)),
- Cases=enc_integer_NNL_cases1(NNL),
- lists:flatten(io_lib:format("(case ~s of "++Cases++
- "~s when atom(~s)->exit({error,{asn1,{namednumber,~s}}});_->~s end)",[Value,TmpVal,TmpVal,TmpVal,Value])).
-
-enc_integer_NNL_cases1([{NNo,No}|Rest]) ->
- io_lib:format("~w->~w;",[NNo,No])++enc_integer_NNL_cases1(Rest);
-enc_integer_NNL_cases1([]) ->
- "".
-
-emit_enc_integer([{'SingleValue',Int}],Value) ->
- asn1ct_name:new(tmpval),
- emit_enc_integer_case(Value),% emit([" case ",Value," of",nl]),
- emit([" ",Int," -> [];",nl]),
- emit([" ",{curr,tmpval}," ->",nl]),
- emit([" exit({error,{value_out_of_bounds,",{curr,tmpval},"}})",
- nl," end",nl]),
- emit_enc_integer_end_case();
-
-emit_enc_integer([{_,{Lb,Ub},_Range,{bits,NoBs}}],Value) -> % Range =< 255
- asn1ct_name:new(tmpval),
- emit_enc_integer_case(Value),
- emit([" ",{curr,tmpval}," when ",{curr,tmpval},"=<",Ub,",",
- {curr,tmpval},">=",Lb," ->",nl]),
- emit([" [10,",NoBs,",",{curr,tmpval},"-",Lb,"];",nl]),
- emit([" ",{curr,tmpval}," ->",nl]),
- emit([" exit({error,{value_out_of_bounds,",{curr,tmpval},"}})",
- nl," end",nl]),
- emit_enc_integer_end_case();
-
-emit_enc_integer([{_,{Lb,Ub},Range,_}],Value) when Range =< 256 ->
- asn1ct_name:new(tmpval),
- emit_enc_integer_case(Value),
- emit([" ",{curr,tmpval}," when ",{curr,tmpval},"=<",Ub,",",
- {curr,tmpval},">=",Lb," ->",nl]),
- emit([" [20,1,",{curr,tmpval},"-",Lb,"];",nl]),
- emit([" ",{curr,tmpval}," ->",nl]),
- emit([" exit({error,{value_out_of_bounds,",{curr,tmpval},"}})",
- nl," end",nl]),
- emit_enc_integer_end_case();
-
-emit_enc_integer([{_,{Lb,Ub},Range,_}],Value) when Range =< 65536 ->
- asn1ct_name:new(tmpval),
- emit_enc_integer_case(Value),
- emit([" ",{curr,tmpval}," when ",{curr,tmpval},"=<",Ub,",",
- {curr,tmpval},">=",Lb," ->",nl]),
- emit([" [20,2,<<(",{curr,tmpval},"-",Lb,"):16>>];",nl]),
- emit([" ",{curr,tmpval}," ->",nl]),
- emit([" exit({error,{value_out_of_bounds,",{curr,tmpval},"}})",
- nl," end",nl]),
- emit_enc_integer_end_case();
-
-
-emit_enc_integer(C,Value) ->
- emit({" ?RT_PER:encode_integer(",{asis,C},",",Value,")"}).
-
-
-
-
-enc_enum_cases(Value,NewList) ->
- asn1ct_name:new(tmpval),
- TmpVal = asn1ct_gen:mk_var(asn1ct_name:curr(tmpval)),
- Cases=enc_enum_cases1(NewList),
- lists:flatten(io_lib:format("(case ~s of "++Cases++
- "~s ->exit({error,"
- "{asn1,{enumerated,~s}}})"
- " end)",
- [Value,TmpVal,TmpVal])).
-enc_enum_cases1(NNL) ->
- enc_enum_cases1(NNL,0).
-enc_enum_cases1([H|T],Index) ->
- io_lib:format("~w->~w;",[H,Index])++enc_enum_cases1(T,Index+1);
-enc_enum_cases1([],_) ->
- "".
-
-
-emit_enc_enumerated_cases(C, [H], Count) ->
- emit_enc_enumerated_case(C, H, Count),
- emit([";",nl,"EnumVal -> exit({error,{asn1, {enumerated_not_in_range, EnumVal}}})"]),
- emit([nl,"end"]);
-emit_enc_enumerated_cases(C, ['EXT_MARK'|T], _Count) ->
- emit_enc_enumerated_cases(C, T, 0);
-emit_enc_enumerated_cases(C, [H1,H2|T], Count) ->
- emit_enc_enumerated_case(C, H1, Count),
- emit([";",nl]),
- emit_enc_enumerated_cases(C, [H2|T], Count+1).
-
-
-%% The function clauses matching on tuples with first element
-%% asn1_enum, 1 or 0 and the atom 'EXT_MARK' are for ENUMERATED
-%% with extension mark.
-emit_enc_enumerated_case(_C, {asn1_enum,High}, _) ->
- %% ENUMERATED with extensionmark
- %% value higher than the extension base and not
- %% present in the extension range.
- emit(["{asn1_enum,EnumV} when integer(EnumV), EnumV > ",High," -> ",
- "[1,?RT_PER:encode_small_number(EnumV)]"]);
-emit_enc_enumerated_case(_C, 'EXT_MARK', _Count) ->
- %% ENUMERATED with extensionmark
- true;
-emit_enc_enumerated_case(_C, {1,EnumName}, Count) ->
- %% ENUMERATED with extensionmark
- %% values higher than extension root
- emit(["'",EnumName,"' -> [1,?RT_PER:encode_small_number(",Count,")]"]);
-emit_enc_enumerated_case(C, {0,EnumName}, Count) ->
- %% ENUMERATED with extensionmark
- %% values within extension root
- emit(["'",EnumName,"' -> [0,?RT_PER:encode_integer(",{asis,C},", ",Count,")]"]);
-
-%% This clause is invoked in case of an ENUMERATED without extension mark
-emit_enc_enumerated_case(_C, EnumName, Count) ->
- emit(["'",EnumName,"' -> ",Count]).
-
-
-get_constraint([{Key,V}],Key) ->
- V;
-get_constraint([],_) ->
- no;
-get_constraint(C,Key) ->
- case lists:keysearch(Key,1,C) of
- false ->
- no;
- {value,{_,V}} ->
- V
- end.
-
-get_constraints(L=[{Key,_}],Key) ->
- L;
-get_constraints([],_) ->
- [];
-get_constraints(C,Key) ->
- {value,L} = keysearch_allwithkey(Key,1,C,[]),
- L.
-
-keysearch_allwithkey(Key,Ix,C,Acc) ->
- case lists:keysearch(Key,Ix,C) of
- false ->
- {value,Acc};
- {value,T} ->
- RestC = lists:delete(T,C),
- keysearch_allwithkey(Key,Ix,RestC,[T|Acc])
- end.
-
-%% effective_constraint(Type,C)
-%% Type = atom()
-%% C = [C1,...]
-%% C1 = {'SingleValue',SV} | {'ValueRange',VR} | {atom(),term()}
-%% SV = integer() | [integer(),...]
-%% VR = {Lb,Ub}
-%% Lb = 'MIN' | integer()
-%% Ub = 'MAX' | integer()
-%% Returns a single value if C only has a single value constraint, and no
-%% value range constraints, that constrains to a single value, otherwise
-%% returns a value range that has the lower bound set to the lowest value
-%% of all single values and lower bound values in C and the upper bound to
-%% the greatest value.
-effective_constraint(integer,[C={{_,_},_}|_Rest]) -> % extension
- [C]; %% [C|effective_constraint(integer,Rest)]; XXX what is possible ???
-effective_constraint(integer,C) ->
- SVs = get_constraints(C,'SingleValue'),
- SV = effective_constr('SingleValue',SVs),
- VRs = get_constraints(C,'ValueRange'),
- VR = effective_constr('ValueRange',VRs),
- CRange = greatest_common_range(SV,VR),
- pre_encode(integer,CRange);
-effective_constraint(bitstring,C) ->
-% Constr=get_constraints(C,'SizeConstraint'),
-% case Constr of
-% [] -> no;
-% [{'SizeConstraint',Val}] -> Val;
-% Other -> Other
-% end;
- get_constraint(C,'SizeConstraint');
-effective_constraint(Type,C) ->
- io:format("Effective constraint for ~p, not implemented yet.~n",[Type]),
- C.
-
-effective_constr(_,[]) ->
- [];
-effective_constr('SingleValue',List) ->
- SVList = lists:flatten(lists:map(fun(X)->element(2,X)end,List)),
- case lists:usort(SVList) of
- [N] ->
- [{'SingleValue',N}];
- L when list(L) ->
- [{'ValueRange',{hd(L),lists:last(L)}}]
- end;
-effective_constr('ValueRange',List) ->
- LBs = lists:map(fun({_,{Lb,_}})-> Lb end,List),
- UBs = lists:map(fun({_,{_,Ub}})-> Ub end,List),
- Lb = least_Lb(LBs),
- [{'ValueRange',{Lb,lists:max(UBs)}}].
-
-greatest_common_range([],VR) ->
- VR;
-greatest_common_range(SV,[]) ->
- SV;
-greatest_common_range([{_,Int}],[{_,{'MIN',Ub}}]) when integer(Int),
- Int > Ub ->
- [{'ValueRange',{'MIN',Int}}];
-greatest_common_range([{_,Int}],[{_,{Lb,Ub}}]) when integer(Int),
- Int < Lb ->
- [{'ValueRange',{Int,Ub}}];
-greatest_common_range([{_,Int}],VR=[{_,{_Lb,_Ub}}]) when integer(Int) ->
- VR;
-greatest_common_range([{_,L}],[{_,{Lb,Ub}}]) when list(L) ->
- Min = least_Lb([Lb|L]),
- Max = greatest_Ub([Ub|L]),
- [{'ValueRange',{Min,Max}}].
-
-
-least_Lb(L) ->
- case lists:member('MIN',L) of
- true -> 'MIN';
- _ -> lists:min(L)
- end.
-
-greatest_Ub(L) ->
- case lists:member('MAX',L) of
- true -> 'MAX';
- _ -> lists:max(L)
- end.
-
-% effective_constraint1('SingleValue',List) ->
-% SVList = lists:map(fun(X)->element(2,X)end,List),
-% sv_effective_constraint(hd(SVList),tl(SVList));
-% effective_constraint1('ValueRange',List) ->
-% VRList = lists:map(fun(X)->element(2,X)end,List),
-% vr_effective_constraint(lists:map(fun(X)->element(1,X)end,VRList),
-% lists:map(fun(X)->element(2,X)end,VRList)).
-
-%% vr_effective_constraint/2
-%% Gets all LowerEndPoints and UpperEndPoints as arguments
-%% Returns {'ValueRange',{Lb,Ub}} where Lb is the highest value of
-%% the LowerEndPoints and Ub is the lowest value of the UpperEndPoints,
-%% i.e. the intersection of all value ranges.
-% vr_effective_constraint(Mins,Maxs) ->
-% Lb=lists:foldl(fun(X,'MIN') when integer(X) -> X;
-% (X,'MIN') -> 'MIN';
-% (X,AccIn) when integer(X),X >= AccIn -> X;
-% (X,AccIn) -> AccIn
-% end,hd(Mins),tl(Mins)),
-% Ub = lists:min(Maxs),
-% {'ValueRange',{Lb,Ub}}.
-
-
-% sv_effective_constraint(SV,[]) ->
-% {'SingleValue',SV};
-% sv_effective_constraint([],_) ->
-% exit({error,{asn1,{illegal_single_value_constraint}}});
-% sv_effective_constraint(SV,[SV|Rest]) ->
-% sv_effective_constraint(SV,Rest);
-% sv_effective_constraint(Int,[SV|Rest]) when integer(Int),list(SV) ->
-% case lists:member(Int,SV) of
-% true ->
-% sv_effective_constraint(Int,Rest);
-% _ ->
-% exit({error,{asn1,{illegal_single_value_constraint}}})
-% end;
-% sv_effective_constraint(SV,[Int|Rest]) when integer(Int),list(SV) ->
-% case lists:member(Int,SV) of
-% true ->
-% sv_effective_constraint(Int,Rest);
-% _ ->
-% exit({error,{asn1,{illegal_single_value_constraint}}})
-% end;
-% sv_effective_constraint(SV1,[SV2|Rest]) when list(SV1),list(SV2) ->
-% sv_effective_constraint(common_set(SV1,SV2),Rest);
-% sv_effective_constraint(_,_) ->
-% exit({error,{asn1,{illegal_single_value_constraint}}}).
-
-%% common_set/2
-%% Two lists as input
-%% Returns the list with all elements that are common for both
-%% input lists
-% common_set(SV1,SV2) ->
-% lists:filter(fun(X)->lists:member(X,SV1) end,SV2).
-
-
-
-pre_encode(integer,[]) ->
- [];
-pre_encode(integer,C=[{'SingleValue',_}]) ->
- C;
-pre_encode(integer,C=[{'ValueRange',VR={Lb,Ub}}]) when integer(Lb),integer(Ub)->
- Range = Ub-Lb+1,
- if
- Range =< 255 ->
- NoBits = no_bits(Range),
- [{'ValueRange',VR,Range,{bits,NoBits}}];
- Range =< 256 ->
- [{'ValueRange',VR,Range,{octets,1}}];
- Range =< 65536 ->
- [{'ValueRange',VR,Range,{octets,2}}];
- true ->
- C
- end;
-pre_encode(integer,C) ->
- C.
-
-no_bits(2) -> 1;
-no_bits(N) when N=<4 -> 2;
-no_bits(N) when N=<8 -> 3;
-no_bits(N) when N=<16 -> 4;
-no_bits(N) when N=<32 -> 5;
-no_bits(N) when N=<64 -> 6;
-no_bits(N) when N=<128 -> 7;
-no_bits(N) when N=<255 -> 8.
-
-%% Object code generating for encoding and decoding
-%% ------------------------------------------------
-
-gen_obj_code(Erules,_Module,Obj) when record(Obj,typedef) ->
- ObjName = Obj#typedef.name,
- Def = Obj#typedef.typespec,
- #'Externaltypereference'{module=Mod,type=ClassName} =
- Def#'Object'.classname,
- Class = asn1_db:dbget(Mod,ClassName),
- {object,_,Fields} = Def#'Object'.def,
- emit({nl,nl,nl,"%%================================"}),
- emit({nl,"%% ",ObjName}),
- emit({nl,"%%================================",nl}),
- EncConstructed =
-% gen_encode_objectfields(Class#classdef.typespec,ObjName,Fields,[]),
- gen_encode_objectfields(ClassName,get_class_fields(Class),
- ObjName,Fields,[]),
- emit(nl),
- gen_encode_constr_type(Erules,EncConstructed),
- emit(nl),
- DecConstructed =
-% gen_decode_objectfields(Class#classdef.typespec,ObjName,Fields,[]),
- gen_decode_objectfields(ClassName,get_class_fields(Class),
- ObjName,Fields,[]),
- emit(nl),
- gen_decode_constr_type(Erules,DecConstructed),
- emit(nl);
-gen_obj_code(_Erules,_Module,Obj) when record(Obj,pobjectdef) ->
- ok.
-
-gen_encode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(V) ->
- emit(["'enc_",ObjName,"'(",{asis,Name},
- ",",V,",_RestPrimFieldName) ->",nl])
- end,
-% emit(["'enc_",ObjName,"'(",{asis,Name},
-% ", Val, RestPrimFieldName) ->",nl]),
- MaybeConstr =
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} -> %% this case is illegal
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("_"),
- emit(" <<>>"),
- [];
- {false,{'DEFAULT',DefaultType}} ->
- EmitFuncClause("Val"),
- gen_encode_default_call(ClassName,Name,DefaultType);
- {{Name,TypeSpec},_} ->
- %% A specified field owerwrites any 'DEFAULT' or
- %% 'OPTIONAL' field in the class
- EmitFuncClause("Val"),
- gen_encode_field_call(ObjName,Name,TypeSpec)
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_encode_objectfields(ClassName,Rest,ObjName,ObjectFields,
- MaybeConstr++ConstrAcc);
-gen_encode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(Attrs) ->
- emit(["'enc_",ObjName,"'(",{asis,Name},
- ",",Attrs,") ->",nl])
- end,
-% emit(["'enc_",ObjName,"'(",{asis,Name},
-% ", Val,[H|T]) ->",nl]),
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} ->
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("_,_"),
- emit([" exit({error,{'use of missing field in object', ",Name,
- "}})"]);
- {false,{'DEFAULT',_DefaultObject}} ->
- exit({error,{asn1,{"not implemented yet",Name}}});
- {{Name,TypeSpec},_} ->
- EmitFuncClause("Val,[H|T]"),
- case TypeSpec#typedef.name of
- {ExtMod,TypeName} ->
- emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
- "'(H, Val, T)"});
- TypeName ->
- emit({indent(3),"'enc_",TypeName,"'(H, Val, T)"})
- end
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_encode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
-gen_encode_objectfields(ClassName,[_C|Cs],O,OF,Acc) ->
- gen_encode_objectfields(ClassName,Cs,O,OF,Acc);
-gen_encode_objectfields(_,[],_,_,Acc) ->
- Acc.
-
-% gen_encode_objectfields(Class,ObjName,[{FieldName,Type}|Rest],ConstrAcc) ->
-% Fields = Class#objectclass.fields,
-
-% MaybeConstr =
-% case is_typefield(Fields,FieldName) of
-% true ->
-% Def = Type#typedef.typespec,
-% emit({"'enc_",ObjName,"'(",{asis,FieldName},
-% ", Val, Dummy) ->",nl}),
-
-% CAcc =
-% case Type#typedef.name of
-% {primitive,bif} ->
-% gen_encode_prim(per,Def,"false","Val"),
-% [];
-% {constructed,bif} ->
-% emit({" 'enc_",ObjName,'_',FieldName,
-% "'(Val)"}),
-% [{['enc_',ObjName,'_',FieldName],Def}];
-% {ExtMod,TypeName} ->
-% emit({" '",ExtMod,"':'enc_",TypeName,"'(Val)"}),
-% [];
-% TypeName ->
-% emit({" 'enc_",TypeName,"'(Val)"}),
-% []
-% end,
-% case more_genfields(Fields,Rest) of
-% true ->
-% emit({";",nl});
-% false ->
-% emit({".",nl})
-% end,
-% CAcc;
-% {false,objectfield} ->
-% emit({"'enc_",ObjName,"'(",{asis,FieldName},
-% ", Val, [H|T]) ->",nl}),
-% case Type#typedef.name of
-% {ExtMod,TypeName} ->
-% emit({indent(3),"'",ExtMod,"':'enc_",TypeName,
-% "'(H, Val, T)"});
-% TypeName ->
-% emit({indent(3),"'enc_",TypeName,"'(H, Val, T)"})
-% end,
-% case more_genfields(Fields,Rest) of
-% true ->
-% emit({";",nl});
-% false ->
-% emit({".",nl})
-% end,
-% [];
-% {false,_} -> []
-% end,
-% gen_encode_objectfields(Class,ObjName,Rest,MaybeConstr ++ ConstrAcc);
-% gen_encode_objectfields(C,O,[_|T],Acc) ->
-% gen_encode_objectfields(C,O,T,Acc);
-% gen_encode_objectfields(_,_,[],Acc) ->
-% Acc.
-
-gen_encode_constr_type(Erules,[TypeDef|Rest]) when record(TypeDef,typedef) ->
- case is_already_generated(enc,TypeDef#typedef.name) of
- true -> ok;
- _ ->
- Name = lists:concat(["enc_",TypeDef#typedef.name]),
- emit({Name,"(Val) ->",nl}),
- Def = TypeDef#typedef.typespec,
- InnerType = asn1ct_gen:get_inner(Def#type.def),
- asn1ct_gen:gen_encode_constructed(Erules,Name,InnerType,Def),
- gen_encode_constr_type(Erules,Rest)
- end;
-gen_encode_constr_type(_,[]) ->
- ok.
-
-gen_encode_field_call(ObjName,FieldName,Type) ->
- Def = Type#typedef.typespec,
- case Type#typedef.name of
- {primitive,bif} ->
- gen_encode_prim(per,Def,"false",
- "Val"),
- [];
- {constructed,bif} ->
- emit({" 'enc_",ObjName,'_',FieldName,
- "'(Val)"}),
- [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
- {ExtMod,TypeName} ->
- emit({" '",ExtMod,"':'enc_",TypeName,
- "'(Val)"}),
- [];
- TypeName ->
- emit({" 'enc_",TypeName,"'(Val)"}),
- []
- end.
-
-gen_encode_default_call(ClassName,FieldName,Type) ->
- CurrentMod = get(currmod),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
-%% asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type);
- emit([" 'enc_",ClassName,'_',FieldName,"'(Val)"]),
- [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
- typespec=Type}];
- {primitive,bif} ->
- gen_encode_prim(per,Type,"false","Val"),
- [];
- #'Externaltypereference'{module=CurrentMod,type=Etype} ->
- emit([" 'enc_",Etype,"'(Val)",nl]),
- [];
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit([" '",Emod,"':'enc_",Etype,"'(Val)",nl]),
- []
- end.
-
-
-
-gen_decode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(Bytes) ->
- emit(["'dec_",ObjName,"'(",{asis,Name},",",Bytes,
- ",_,_RestPrimFieldName) ->",nl])
- end,
-% emit(["'dec_",ObjName,"'(",{asis,Name},
-% ", Bytes, _, RestPrimFieldName) ->",nl]),
- MaybeConstr=
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} -> %% this case is illegal
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("_"),
- emit([" asn1_NOVALUE"]),
- [];
- {false,{'DEFAULT',DefaultType}} ->
- EmitFuncClause("Bytes"),
- gen_decode_default_call(ClassName,Name,"Bytes",DefaultType);
- {{Name,TypeSpec},_} ->
- %% A specified field owerwrites any 'DEFAULT' or
- %% 'OPTIONAL' field in the class
- EmitFuncClause("Bytes"),
- gen_decode_field_call(ObjName,Name,"Bytes",TypeSpec)
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,MaybeConstr++ConstrAcc);
-gen_decode_objectfields(ClassName,[{objectfield,Name,_,_,OptOrMand}|Rest],
- ObjName,ObjectFields,ConstrAcc) ->
- EmitFuncClause =
- fun(Attrs) ->
- emit(["'dec_",ObjName,"'(",{asis,Name},
- ",",Attrs,") ->",nl])
- end,
-% emit(["'dec_",ObjName,"'(",{asis,Name},
-% ", Bytes,_,[H|T]) ->",nl]),
- case {get_object_field(Name,ObjectFields),OptOrMand} of
- {false,'MANDATORY'} ->
- exit({error,{asn1,{"missing mandatory field in object",
- ObjName}}});
- {false,'OPTIONAL'} ->
- EmitFuncClause("_,_,_"),
- emit([" exit({error,{'illegal use of missing field in object', ",Name,
- "}})"]);
- {false,{'DEFAULT',_DefaultObject}} ->
- exit({error,{asn1,{"not implemented yet",Name}}});
- {{Name,TypeSpec},_} ->
- EmitFuncClause("Bytes,_,[H|T]"),
- case TypeSpec#typedef.name of
- {ExtMod,TypeName} ->
- emit({indent(3),"'",ExtMod,"':'dec_",TypeName,
- "'(H, Bytes, telltype, T)"});
- TypeName ->
- emit({indent(3),"'dec_",TypeName,"'(H, Bytes, telltype, T)"})
- end
- end,
- case more_genfields(Rest) of
- true ->
- emit([";",nl]);
- false ->
- emit([".",nl])
- end,
- gen_decode_objectfields(ClassName,Rest,ObjName,ObjectFields,ConstrAcc);
-gen_decode_objectfields(CN,[_C|Cs],O,OF,CAcc) ->
- gen_decode_objectfields(CN,Cs,O,OF,CAcc);
-gen_decode_objectfields(_,[],_,_,CAcc) ->
- CAcc.
-
-
-gen_decode_field_call(ObjName,FieldName,Bytes,Type) ->
- Def = Type#typedef.typespec,
- case Type#typedef.name of
- {primitive,bif} ->
- gen_dec_prim(per,Def,Bytes),
- [];
- {constructed,bif} ->
- emit({" 'dec_",ObjName,'_',FieldName,
- "'(",Bytes,",telltype)"}),
- [Type#typedef{name=list_to_atom(lists:concat([ObjName,'_',FieldName]))}];
- {ExtMod,TypeName} ->
- emit({" '",ExtMod,"':'dec_",TypeName,
- "'(",Bytes,", telltype)"}),
- [];
- TypeName ->
- emit({" 'dec_",TypeName,"'(",Bytes,", telltype)"}),
- []
- end.
-
-gen_decode_default_call(ClassName,FieldName,Bytes,Type) ->
- CurrentMod = get(currmod),
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- emit([" 'dec_",ClassName,'_',FieldName,"'(",Bytes,", telltype)"]),
- [#typedef{name=list_to_atom(lists:concat([ClassName,'_',FieldName])),
- typespec=Type}];
- {primitive,bif} ->
- gen_dec_prim(per,Type,Bytes),
- [];
- #'Externaltypereference'{module=CurrentMod,type=Etype} ->
- emit([" 'dec_",Etype,"'(",Bytes,", telltype)",nl]),
- [];
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit([" '",Emod,"':'dec_",Etype,"'(",Bytes,", telltype)",nl]),
- []
- end.
-
-%%%%%%%%%%%%%%%
-
-% gen_decode_objectfields(Class,ObjName,[{FieldName,Type}|Rest],ConstrAcc) ->
-% Fields = Class#objectclass.fields,
-
-% MaybeConstr =
-% case is_typefield(Fields,FieldName) of
-% true ->
-% Def = Type#typedef.typespec,
-% emit({"'dec_",ObjName,"'(",{asis,FieldName},
-% ", Val, Telltype, RestPrimFieldName) ->",nl}),
-
-% CAcc =
-% case Type#typedef.name of
-% {primitive,bif} ->
-% gen_dec_prim(per,Def,"Val"),
-% [];
-% {constructed,bif} ->
-% emit({" 'dec_",ObjName,'_',FieldName,
-% "'(Val, Telltype)"}),
-% [{['dec_',ObjName,'_',FieldName],Def}];
-% {ExtMod,TypeName} ->
-% emit({" '",ExtMod,"':'dec_",TypeName,
-% "'(Val, Telltype)"}),
-% [];
-% TypeName ->
-% emit({" 'dec_",TypeName,"'(Val, Telltype)"}),
-% []
-% end,
-% case more_genfields(Fields,Rest) of
-% true ->
-% emit({";",nl});
-% false ->
-% emit({".",nl})
-% end,
-% CAcc;
-% {false,objectfield} ->
-% emit({"'dec_",ObjName,"'(",{asis,FieldName},
-% ", Val, Telltype, [H|T]) ->",nl}),
-% case Type#typedef.name of
-% {ExtMod,TypeName} ->
-% emit({indent(3),"'",ExtMod,"':'dec_",TypeName,
-% "'(H, Val, Telltype, T)"});
-% TypeName ->
-% emit({indent(3),"'dec_",TypeName,
-% "'(H, Val, Telltype, T)"})
-% end,
-% case more_genfields(Fields,Rest) of
-% true ->
-% emit({";",nl});
-% false ->
-% emit({".",nl})
-% end,
-% [];
-% {false,_} ->
-% []
-% end,
-% gen_decode_objectfields(Class,ObjName,Rest,MaybeConstr ++ ConstrAcc);
-% gen_decode_objectfields(C,O,[_|T],CAcc) ->
-% gen_decode_objectfields(C,O,T,CAcc);
-% gen_decode_objectfields(_,_,[],CAcc) ->
-% CAcc.
-
-gen_decode_constr_type(Erules,[{Name,Def}|Rest]) ->
- emit({Name,"(Bytes,_) ->",nl}),
- InnerType = asn1ct_gen:get_inner(Def#type.def),
- asn1ct_gen:gen_decode_constructed(Erules,Name,InnerType,Def),
- gen_decode_constr_type(Erules,Rest);
-gen_decode_constr_type(Erules,[TypeDef|Rest]) when record(TypeDef,typedef) ->
- case is_already_generated(dec,TypeDef#typedef.name) of
- true -> ok;
- _ ->
- gen_decode(Erules,TypeDef)
- end,
- gen_decode_constr_type(Erules,Rest);
-gen_decode_constr_type(_,[]) ->
- ok.
-
-% is_typefield(Fields,FieldName) ->
-% case lists:keysearch(FieldName,2,Fields) of
-% {value,Field} ->
-% case element(1,Field) of
-% typefield ->
-% true;
-% Other ->
-% {false,Other}
-% end;
-% _ ->
-% false
-% end.
-%% Object Set code generating for encoding and decoding
-%% ----------------------------------------------------
-gen_objectset_code(Erules,ObjSet) ->
- ObjSetName = ObjSet#typedef.name,
- Def = ObjSet#typedef.typespec,
-%% {ClassName,ClassDef} = Def#'ObjectSet'.class,
- #'Externaltypereference'{module=ClassModule,
- type=ClassName} = Def#'ObjectSet'.class,
- ClassDef = asn1_db:dbget(ClassModule,ClassName),
- UniqueFName = Def#'ObjectSet'.uniquefname,
- Set = Def#'ObjectSet'.set,
- emit({nl,nl,nl,"%%================================"}),
- emit({nl,"%% ",ObjSetName}),
- emit({nl,"%%================================",nl}),
- case ClassName of
- {_Module,ExtClassName} ->
- gen_objset_code(Erules,ObjSetName,UniqueFName,Set,
- ExtClassName,ClassDef);
- _ ->
- gen_objset_code(Erules,ObjSetName,UniqueFName,Set,
- ClassName,ClassDef)
- end,
- emit(nl).
-
-gen_objset_code(Erules,ObjSetName,UniqueFName,Set,ClassName,ClassDef)->
- ClassFields = (ClassDef#classdef.typespec)#objectclass.fields,
- InternalFuncs=
- gen_objset_enc(ObjSetName,UniqueFName,Set,ClassName,
- ClassFields,1,[]),
- gen_objset_dec(ObjSetName,UniqueFName,Set,ClassName,ClassFields,1),
- gen_internal_funcs(Erules,InternalFuncs).
-
-gen_objset_enc(_,{unique,undefined},_,_,_,_,_) ->
- %% There is no unique field in the class of this object set
- %% don't bother about the constraint
- [];
-gen_objset_enc(ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],
- ClName,ClFields,NthObj,Acc)->
- emit({"'getenc_",ObjSName,"'(",{asis,UniqueName},",",
- {asis,Val},") ->",nl}),
- {InternalFunc,NewNthObj}=
- case ObjName of
- no_name ->
- gen_inlined_enc_funs(Fields,ClFields,ObjSName,NthObj);
- _ ->
- emit({" fun 'enc_",ObjName,"'/3"}),
- {[],NthObj}
- end,
- emit({";",nl}),
- gen_objset_enc(ObjSName,UniqueName,[T|Rest],ClName,ClFields,
- NewNthObj,InternalFunc++Acc);
-gen_objset_enc(ObjSetName,UniqueName,
- [{ObjName,Val,Fields}],_ClName,ClFields,NthObj,Acc) ->
-
- emit({"'getenc_",ObjSetName,"'(",{asis,UniqueName},",",
- {asis,Val},") ->",nl}),
- {InternalFunc,_}=
- case ObjName of
- no_name ->
- gen_inlined_enc_funs(Fields,ClFields,ObjSetName,NthObj);
- _ ->
- emit({" fun 'enc_",ObjName,"'/3"}),
- {[],NthObj}
- end,
- emit({".",nl,nl}),
- InternalFunc++Acc;
-gen_objset_enc(ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,
- _ClFields,_NthObj,Acc) ->
- emit({"'getenc_",ObjSetName,"'(_, _) ->",nl}),
- emit({indent(3),"fun(_, Val, _) ->",nl}),
- emit({indent(6),"Size = if",nl}),
- emit({indent(9),"list(Val) -> length(Val);",nl}),
- emit({indent(9),"true -> size(Val)",nl}),
- emit({indent(6),"end,",nl}),
- emit({indent(6),"if",nl}),
- emit({indent(9),"Size < 256 ->",nl}),
- emit({indent(12),"[20,Size,Val];",nl}),
- emit({indent(9),"true ->",nl}),
- emit({indent(12),"[21,<<Size:16>>,Val]",nl}),
- emit({indent(6),"end",nl}),
- emit({indent(3),"end.",nl,nl}),
- Acc;
-gen_objset_enc(_,_,[],_,_,_,Acc) ->
- Acc.
-
-%% gen_inlined_enc_funs for each object iterates over all fields of a
-%% class, and for each typefield it checks if the object has that
-%% field and emits the proper code.
-gen_inlined_enc_funs(Fields,[{typefield,Name,_}|Rest],ObjSetName,NthObj) ->
- InternalDefFunName=asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when record(Type,type) ->
- emit({indent(3),"fun(Type, Val, _) ->",nl,
- indent(6),"case Type of",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
- {value,{_,Type}} when record(Type,typedef) ->
- emit({indent(3),"fun(Type, Val, _) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+N,Ret);
- false ->
- gen_inlined_enc_funs(Fields,Rest,ObjSetName,NthObj)
- end;
-gen_inlined_enc_funs(Fields,[_|Rest],ObjSetName,NthObj) ->
- gen_inlined_enc_funs(Fields,Rest,ObjSetName,NthObj);
-gen_inlined_enc_funs(_,[],_,NthObj) ->
- {[],NthObj}.
-
-gen_inlined_enc_funs1(Fields,[{typefield,Name,_}|Rest],ObjSetName,
- NthObj,Acc) ->
- InternalDefFunName = asn1ct_gen:list2name([NthObj,Name,ObjSetName]),
- {Acc2,NAdd}=
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when record(Type,type) ->
- emit({";",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- {Ret++Acc,N};
- {value,{_,Type}} when record(Type,typedef) ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- {Ret,N}=emit_inner_of_fun(Type,InternalDefFunName),
- {Ret++Acc,N};
- false ->
- {Acc,0}
- end,
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj+NAdd,Acc2);
-gen_inlined_enc_funs1(Fields,[_|Rest],ObjSetName,NthObj,Acc)->
- gen_inlined_enc_funs1(Fields,Rest,ObjSetName,NthObj,Acc);
-gen_inlined_enc_funs1(_,[],_,NthObj,Acc) ->
- emit({nl,indent(6),"end",nl}),
- emit({indent(3),"end"}),
- {Acc,NthObj}.
-
-emit_inner_of_fun(TDef=#typedef{name={ExtMod,Name},typespec=Type},
- InternalDefFunName) ->
- case {ExtMod,Name} of
- {primitive,bif} ->
- emit(indent(12)),
- gen_encode_prim(per,Type,dotag,"Val"),
- {[],0};
- {constructed,bif} ->
- emit([indent(12),"'enc_",
- InternalDefFunName,"'(Val)"]),
- {[TDef#typedef{name=InternalDefFunName}],1};
- _ ->
- emit({indent(12),"'",ExtMod,"':'enc_",Name,"'(Val)"}),
- {[],0}
- end;
-emit_inner_of_fun(#typedef{name=Name},_) ->
- emit({indent(12),"'enc_",Name,"'(Val)"}),
- {[],0};
-emit_inner_of_fun(Type,_) when record(Type,type) ->
- CurrMod = get(currmod),
- case Type#type.def of
- Def when atom(Def) ->
- emit({indent(9),Def," ->",nl,indent(12)}),
- gen_encode_prim(erules,Type,dotag,"Val");
- TRef when record(TRef,typereference) ->
- T = TRef#typereference.val,
- emit({indent(9),T," ->",nl,indent(12),"'enc_",T,"'(Val)"});
- #'Externaltypereference'{module=CurrMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),"'enc_",T,"'(Val)"});
- #'Externaltypereference'{module=ExtMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),ExtMod,":'enc_",
- T,"'(Val)"})
- end,
- {[],0}.
-
-indent(N) ->
- lists:duplicate(N,32). % 32 = space
-
-
-gen_objset_dec(_,{unique,undefined},_,_,_,_) ->
- %% There is no unique field in the class of this object set
- %% don't bother about the constraint
- ok;
-gen_objset_dec(ObjSName,UniqueName,[{ObjName,Val,Fields},T|Rest],ClName,
- ClFields,NthObj)->
-
- emit({"'getdec_",ObjSName,"'(",{asis,UniqueName},",",
- {asis,Val},") ->",nl}),
- NewNthObj=
- case ObjName of
- no_name ->
- gen_inlined_dec_funs(Fields,ClFields,ObjSName,NthObj);
- _ ->
- emit({" fun 'dec_",ObjName,"'/4"}),
- NthObj
- end,
- emit({";",nl}),
- gen_objset_dec(ObjSName,UniqueName,[T|Rest],ClName,ClFields,NewNthObj);
-gen_objset_dec(ObjSetName,UniqueName,[{ObjName,Val,Fields}],_ClName,
- ClFields,NthObj) ->
-
- emit({"'getdec_",ObjSetName,"'(",{asis,UniqueName},",",
- {asis,Val},") ->",nl}),
- case ObjName of
- no_name ->
- gen_inlined_dec_funs(Fields,ClFields,ObjSetName,NthObj);
- _ ->
- emit({" fun 'dec_",ObjName,"'/4"})
- end,
- emit({".",nl,nl}),
- ok;
-gen_objset_dec(ObjSetName,_,['EXTENSIONMARK'],_ClName,_ClFields,
- _NthObj) ->
- emit({"'getdec_",ObjSetName,"'(_, _) ->",nl}),
- emit({indent(3),"fun(Attr1, Bytes, _, _) ->",nl}),
- %% emit({indent(6),"?RT_PER:decode_open_type(Bytes,[])",nl}),
- emit({indent(6),"{Bytes,Attr1}",nl}),
- emit({indent(3),"end.",nl,nl}),
- ok;
-gen_objset_dec(_,_,[],_,_,_) ->
- ok.
-
-gen_inlined_dec_funs(Fields,[{typefield,Name,_}|Rest],
- ObjSetName,NthObj) ->
- InternalDefFunName = [NthObj,Name,ObjSetName],
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when record(Type,type) ->
- emit({indent(3),"fun(Type, Val, _, _) ->",nl,
- indent(6),"case Type of",nl}),
- N=emit_inner_of_decfun(Type,InternalDefFunName),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
- {value,{_,Type}} when record(Type,typedef) ->
- emit({indent(3),"fun(Type, Val, _, _) ->",nl,
- indent(6),"case Type of",nl}),
- emit({indent(9),{asis,Name}," ->",nl}),
- N=emit_inner_of_decfun(Type,InternalDefFunName),
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
- false ->
- gen_inlined_dec_funs(Fields,Rest,ObjSetName,NthObj)
- end;
-gen_inlined_dec_funs(Fields,[_|Rest],ObjSetName,NthObj) ->
- gen_inlined_dec_funs(Fields,Rest,ObjSetName,NthObj);
-gen_inlined_dec_funs(_,[],_,NthObj) ->
- NthObj.
-
-gen_inlined_dec_funs1(Fields,[{typefield,Name,_}|Rest],
- ObjSetName,NthObj) ->
- InternalDefFunName = [NthObj,Name,ObjSetName],
- N=
- case lists:keysearch(Name,1,Fields) of
- {value,{_,Type}} when record(Type,type) ->
- emit({";",nl}),
- emit_inner_of_decfun(Type,InternalDefFunName);
- {value,{_,Type}} when record(Type,typedef) ->
- emit({";",nl,indent(9),{asis,Name}," ->",nl}),
- emit_inner_of_decfun(Type,InternalDefFunName);
- false ->
- 0
- end,
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N);
-gen_inlined_dec_funs1(Fields,[_|Rest],ObjSetName,NthObj)->
- gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj);
-gen_inlined_dec_funs1(_,[],_,NthObj) ->
- emit({nl,indent(6),"end",nl}),
- emit({indent(3),"end"}),
- NthObj.
-
-emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type},
- InternalDefFunName) ->
- case {ExtName,Name} of
- {primitive,bif} ->
- emit(indent(12)),
- gen_dec_prim(per,Type,"Val"),
- 0;
- {constructed,bif} ->
- emit({indent(12),"'dec_",
- asn1ct_gen:list2name(InternalDefFunName),"'(Val)"}),
- 1;
- _ ->
- emit({indent(12),"'",ExtName,"':'dec_",Name,
- "'(Val, telltype)"}),
- 0
- end;
-emit_inner_of_decfun(#typedef{name=Name},_) ->
- emit({indent(12),"'dec_",Name,"'(Val, telltype)"}),
- 0;
-emit_inner_of_decfun(Type,_) when record(Type,type) ->
- CurrMod = get(currmod),
- case Type#type.def of
- Def when atom(Def) ->
- emit({indent(9),Def," ->",nl,indent(12)}),
- gen_dec_prim(erules,Type,"Val");
- TRef when record(TRef,typereference) ->
- T = TRef#typereference.val,
- emit({indent(9),T," ->",nl,indent(12),"'dec_",T,"'(Val)"});
- #'Externaltypereference'{module=CurrMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),"'dec_",T,"'(Val)"});
- #'Externaltypereference'{module=ExtMod,type=T} ->
- emit({indent(9),T," ->",nl,indent(12),ExtMod,":'dec_",
- T,"'(Val)"})
- end,
- 0.
-
-
-gen_internal_funcs(_Erules,[]) ->
- ok;
-gen_internal_funcs(Erules,[TypeDef|Rest]) ->
- gen_encode_user(Erules,TypeDef),
- emit([nl,nl,"'dec_",TypeDef#typedef.name,"'(Bytes) ->",nl]),
- gen_decode_user(Erules,TypeDef),
- gen_internal_funcs(Erules,Rest).
-
-
-
-%% DECODING *****************************
-%%***************************************
-
-
-gen_decode(Erules,Type) when record(Type,typedef) ->
- D = Type,
- emit({nl,nl}),
- emit({"'dec_",Type#typedef.name,"'(Bytes,_) ->",nl}),
- dbdec(Type#typedef.name),
- gen_decode_user(Erules,D).
-
-gen_decode(Erules,Tname,#'ComponentType'{name=Cname,typespec=Type}) ->
- NewTname = [Cname|Tname],
- gen_decode(Erules,NewTname,Type);
-
-gen_decode(Erules,Typename,Type) when record(Type,type) ->
- InnerType = asn1ct_gen:get_inner(Type#type.def),
- case asn1ct_gen:type(InnerType) of
- {constructed,bif} ->
- ObjFun =
- case Type#type.tablecinf of
- [{objfun,_}|_R] ->
- ", ObjFun";
- _ ->
- ""
- end,
- emit({nl,"'dec_",asn1ct_gen:list2name(Typename),
- "'(Bytes,_",ObjFun,") ->",nl}),
- dbdec(Typename),
- asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,Type);
- _ ->
- true
- end.
-
-dbdec(Type) when list(Type)->
- demit({"io:format(\"decoding: ",asn1ct_gen:list2name(Type),"~w~n\",[Bytes]),",nl});
-dbdec(Type) ->
- demit({"io:format(\"decoding: ",{asis,Type},"~w~n\",[Bytes]),",nl}).
-
-gen_decode_user(Erules,D) when record(D,typedef) ->
- CurrMod = get(currmod),
- Typename = [D#typedef.name],
- Def = D#typedef.typespec,
- InnerType = asn1ct_gen:get_inner(Def#type.def),
- case asn1ct_gen:type(InnerType) of
- {primitive,bif} ->
- gen_dec_prim(Erules,Def,"Bytes"),
- emit({".",nl,nl});
- 'ASN1_OPEN_TYPE' ->
- gen_dec_prim(Erules,Def#type{def='ASN1_OPEN_TYPE'},"Bytes"),
- emit({".",nl,nl});
- {constructed,bif} ->
- asn1ct_gen:gen_decode_constructed(Erules,Typename,InnerType,D);
- #typereference{val=Dname} ->
- emit({"'dec_",Dname,"'(Bytes,telltype)"}),
- emit({".",nl,nl});
- #'Externaltypereference'{module=CurrMod,type=Etype} ->
- emit({"'dec_",Etype,"'(Bytes,telltype).",nl,nl});
- #'Externaltypereference'{module=Emod,type=Etype} ->
- emit({"'",Emod,"':'dec_",Etype,"'(Bytes,telltype).",nl,nl});
- Other ->
- exit({error,{asn1,{unknown,Other}}})
- end.
-
-
-
-gen_dec_prim(_Erules,Att,BytesVar) ->
- Typename = Att#type.def,
- Constraint = Att#type.constraint,
- case Typename of
- 'INTEGER' ->
- EffectiveConstr = effective_constraint(integer,Constraint),
- emit_dec_integer(EffectiveConstr,BytesVar);
-% emit({"?RT_PER:decode_integer(",BytesVar,",",
-% {asis,EffectiveConstr},")"});
- {'INTEGER',NamedNumberList} ->
- EffectiveConstr = effective_constraint(integer,Constraint),
- emit_dec_integer(EffectiveConstr,BytesVar,NamedNumberList);
-% emit({"?RT_PER:decode_integer(",BytesVar,",",
-% {asis,EffectiveConstr},",",
-% {asis,NamedNumberList},")"});
- {'BIT STRING',NamedNumberList} ->
- case get(compact_bit_string) of
- true ->
- emit({"?RT_PER:decode_compact_bit_string(",
- BytesVar,",",{asis,Constraint},",",
- {asis,NamedNumberList},")"});
- _ ->
- emit({"?RT_PER:decode_bit_string(",BytesVar,",",
- {asis,Constraint},",",
- {asis,NamedNumberList},")"})
- end;
- 'NULL' ->
- emit({"?RT_PER:decode_null(",
- BytesVar,")"});
- 'OBJECT IDENTIFIER' ->
- emit({"?RT_PER:decode_object_identifier(",
- BytesVar,")"});
- 'ObjectDescriptor' ->
- emit({"?RT_PER:decode_ObjectDescriptor(",
- BytesVar,")"});
- {'ENUMERATED',{NamedNumberList1,NamedNumberList2}} ->
- NewTup = {list_to_tuple([X||{X,_} <- NamedNumberList1]),
- list_to_tuple([X||{X,_} <- NamedNumberList2])},
- NewC = [{'ValueRange',{0,size(element(1,NewTup))-1}}],
- emit({"?RT_PER:decode_enumerated(",BytesVar,",",
- {asis,NewC},",",
- {asis,NewTup},")"});
- {'ENUMERATED',NamedNumberList} ->
- %NewTup = list_to_tuple([X||{X,Y} <- NamedNumberList]),
- NewNNL = [X||{X,_} <- NamedNumberList],
- NewC = effective_constraint(integer,
- [{'ValueRange',{0,length(NewNNL)-1}}]),
- emit_dec_enumerated(BytesVar,NewC,NewNNL);
-% emit({"?RT_PER:decode_enumerated(",BytesVar,",",
-% {asis,NewC},",",
-% {asis,NewTup},")"});
- 'BOOLEAN'->
- emit({"?RT_PER:decode_boolean(",BytesVar,")"});
- 'OCTET STRING' ->
- emit_dec_octet_string(Constraint,BytesVar);
-% emit({"?RT_PER:decode_octet_string(",BytesVar,",",
-% {asis,Constraint},")"});
- 'NumericString' ->
- emit_dec_known_multiplier_string('NumericString',
- Constraint,BytesVar);
-% emit({"?RT_PER:decode_NumericString(",BytesVar,",",
-% {asis,Constraint},")"});
- 'TeletexString' ->
- emit({"?RT_PER:decode_TeletexString(",BytesVar,",",
- {asis,Constraint},")"});
- 'VideotexString' ->
- emit({"?RT_PER:decode_VideotexString(",BytesVar,",",
- {asis,Constraint},")"});
- 'UTCTime' ->
- emit_dec_known_multiplier_string('VisibleString',
- Constraint,BytesVar);
-% emit({"?RT_PER:decode_VisibleString(",BytesVar,",",
-% {asis,Constraint},")"});
- 'GeneralizedTime' ->
- emit_dec_known_multiplier_string('VisibleString',
- Constraint,BytesVar);
-% emit({"?RT_PER:decode_VisibleString(",BytesVar,",",
-% {asis,Constraint},")"});
- 'GraphicString' ->
- emit({"?RT_PER:decode_GraphicString(",BytesVar,",",
- {asis,Constraint},")"});
- 'VisibleString' ->
- emit_dec_known_multiplier_string('VisibleString',
- Constraint,BytesVar);
-% emit({"?RT_PER:decode_VisibleString(",BytesVar,",",
-% {asis,Constraint},")"});
- 'GeneralString' ->
- emit({"?RT_PER:decode_GeneralString(",BytesVar,",",
- {asis,Constraint},")"});
- 'PrintableString' ->
- emit_dec_known_multiplier_string('PrintableString',
- Constraint,BytesVar);
-% emit({"?RT_PER:decode_PrintableString(",BytesVar,",",{asis,Constraint},")"});
- 'IA5String' ->
- emit_dec_known_multiplier_string('IA5String',Constraint,BytesVar);
-% emit({"?RT_PER:decode_IA5String(",BytesVar,",",{asis,Constraint},")"});
- 'BMPString' ->
- emit_dec_known_multiplier_string('BMPString',Constraint,BytesVar);
-% emit({"?RT_PER:decode_BMPString(",BytesVar,",",{asis,Constraint},")"});
- 'UniversalString' ->
- emit_dec_known_multiplier_string('UniversalString',
- Constraint,BytesVar);
-% emit({"?RT_PER:decode_UniversalString(",BytesVar,",",{asis,Constraint},")"});
- 'ANY' ->
- emit(["?RT_PER:decode_open_type(",BytesVar,",",
- {asis,Constraint}, ")"]);
- 'ASN1_OPEN_TYPE' ->
- case Constraint of
- [#'Externaltypereference'{type=Tname}] ->
- emit(["fun(FBytes) ->",nl,
- " {XTerm,XBytes} = "]),
- emit(["?RT_PER:decode_open_type(FBytes,[]),",nl]),
- emit([" {YTerm,_} = dec_",Tname,"(XTerm,mandatory),",nl]),
- emit([" {YTerm,XBytes} end(",BytesVar,")"]);
- [#type{def=#'Externaltypereference'{type=Tname}}] ->
- emit(["fun(FBytes) ->",nl,
- " {XTerm,XBytes} = "]),
- emit(["?RT_PER:decode_open_type(FBytes,[]),",nl]),
- emit([" {YTerm,_} = dec_",Tname,"(XTerm,mandatory),",nl]),
- emit([" {YTerm,XBytes} end(",BytesVar,")"]);
- _ ->
- emit(["?RT_PER:decode_open_type(",BytesVar,",[])"])
- end;
- Other ->
- exit({'cant decode' ,Other})
- end.
-
-
-emit_dec_integer(C,BytesVar,NNL) ->
- asn1ct_name:new(tmpterm),
- asn1ct_name:new(buffer),
- Tmpterm = asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
- Buffer = asn1ct_gen:mk_var(asn1ct_name:curr(buffer)),
- emit({" begin {",{curr,tmpterm},",",{curr,buffer},"} = ",nl}),
- emit_dec_integer(C,BytesVar),
- emit({",",nl," case ",Tmpterm," of",nl}),
- lists:map(fun({Name,Int})->emit({" ",Int," -> {",{asis,Name},",",
- Buffer,"};",nl});
- (_)-> exit({error,{asn1,{"error in named number list",NNL}}})
- end,
- NNL),
- emit({" _ -> {",Tmpterm,",",Buffer,"}",nl}),
- emit({" end",nl}), % end of case
- emit(" end"). % end of begin
-
-emit_dec_integer([{'SingleValue',Int}],BytesVar) when integer(Int) ->
- emit(["{",Int,",",BytesVar,"}"]);
-emit_dec_integer([{_,{Lb,_Ub},_Range,{BitsOrOctets,N}}],BytesVar) ->
- GetBorO =
- case BitsOrOctets of
- bits -> "getbits";
- _ -> "getoctets"
- end,
- asn1ct_name:new(tmpterm),
- asn1ct_name:new(tmpremain),
- emit({" begin",nl," {",{curr,tmpterm},",",{curr,tmpremain},"}=",
- "?RT_PER:",GetBorO,"(",BytesVar,",",N,"),",nl}),
- emit({" {",{curr,tmpterm},"+",Lb,",",{curr,tmpremain},"}",nl,
- " end"});
-emit_dec_integer([{_,{'MIN',_}}],BytesVar) ->
- emit({"?RT_PER:decode_unconstrained_number(",BytesVar,")"});
-emit_dec_integer([{_,{Lb,'MAX'}}],BytesVar) ->
- emit({"?RT_PER:decode_semi_constrained_number(",BytesVar,",",Lb,")"});
-emit_dec_integer([{'ValueRange',VR={Lb,Ub}}],BytesVar) ->
- Range = Ub-Lb+1,
- emit({"?RT_PER:decode_constrained_number(",BytesVar,",",
- {asis,VR},",",Range,")"});
-emit_dec_integer(C=[{Rc,_}],BytesVar) when tuple(Rc) ->
- emit({"?RT_PER:decode_integer(",BytesVar,",",{asis,C},")"});
-emit_dec_integer(_,BytesVar) ->
- emit({"?RT_PER:decode_unconstrained_number(",BytesVar,")"}).
-
-
-emit_dec_enumerated(BytesVar,C,NamedNumberList) ->
- emit_dec_enumerated_begin(),% emits a begin if component
- asn1ct_name:new(tmpterm),
- Tmpterm = asn1ct_gen:mk_var(asn1ct_name:curr(tmpterm)),
- asn1ct_name:new(tmpremain),
- Tmpremain = asn1ct_gen:mk_var(asn1ct_name:curr(tmpremain)),
- emit({" {",{curr,tmpterm},",",{curr,tmpremain},"} =",nl}),
- emit_dec_integer(C,BytesVar),
- emit({",",nl," case ",Tmpterm," of "}),
-% Cases=lists:flatten(dec_enumerated_cases(NamedNumberList,asn1ct_gen:mk_var(asn1ct_name:curr(tmpremain)),0)),
- Cases=lists:flatten(dec_enumerated_cases(NamedNumberList,Tmpremain,0)),
- emit({Cases++"_->exit({error,{asn1,{decode_enumerated,{",Tmpterm,
- ",",{asis,NamedNumberList},"}}}}) end",nl}),
- emit_dec_enumerated_end().
-
-emit_dec_enumerated_begin() ->
- case get(component_type) of
- {true,_} ->
- emit({" begin",nl});
- _ -> ok
- end.
-
-emit_dec_enumerated_end() ->
- case get(component_type) of
- {true,_} ->
- emit(" end");
- _ -> ok
- end.
-
-% dec_enumerated_cases(NNL,Tmpremain,No) ->
-% Cases=dec_enumerated_cases1(NNL,Tmpremain,0),
-% lists:flatten(io_lib:format("(case ~s "++Cases++
-% "~s when atom(~s)->exit({error,{asn1,{namednumber,~s}}});_->~s end)",[Value,"TmpVal","TmpVal","TmpVal",Value])).
-
-dec_enumerated_cases([Name|Rest],Tmpremain,No) ->
- io_lib:format("~w->{~w,~s};",[No,Name,Tmpremain])++
- dec_enumerated_cases(Rest,Tmpremain,No+1);
-dec_enumerated_cases([],_,_) ->
- "".
-
-
-% more_genfields(_Fields,[]) ->
-% false;
-% more_genfields(Fields,[{FieldName,_}|T]) ->
-% case is_typefield(Fields,FieldName) of
-% true -> true;
-% {false,objectfield} -> true;
-% {false,_} -> more_genfields(Fields,T)
-% end.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_name.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_name.erl
deleted file mode 100644
index 03252bd7d9..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_name.erl
+++ /dev/null
@@ -1,225 +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: asn1ct_name.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
-%%
--module(asn1ct_name).
-
-%%-compile(export_all).
--export([name_server_loop/1,
- start/0,
- stop/0,
- push/1,
- pop/1,
- curr/1,
- clear/0,
- delete/1,
- active/1,
- prev/1,
- next/1,
- all/1,
- new/1]).
-
-start() ->
- start_server(asn1_ns, asn1ct_name,name_server_loop,[[]]).
-
-stop() -> stop_server(asn1_ns).
-
-name_server_loop(Vars) ->
-%% io:format("name -- ~w~n",[Vars]),
- receive
- {From,{current,Variable}} ->
- From ! {asn1_ns,get_curr(Vars,Variable)},
- name_server_loop(Vars);
- {From,{pop,Variable}} ->
- From ! {asn1_ns,done},
- name_server_loop(pop_var(Vars,Variable));
- {From,{push,Variable}} ->
- From ! {asn1_ns,done},
- name_server_loop(push_var(Vars,Variable));
- {From,{delete,Variable}} ->
- From ! {asn1_ns,done},
- name_server_loop(delete_var(Vars,Variable));
- {From,{new,Variable}} ->
- From ! {asn1_ns,done},
- name_server_loop(new_var(Vars,Variable));
- {From,{prev,Variable}} ->
- From ! {asn1_ns,get_prev(Vars,Variable)},
- name_server_loop(Vars);
- {From,{next,Variable}} ->
- From ! {asn1_ns,get_next(Vars,Variable)},
- name_server_loop(Vars);
- {From,stop} ->
- From ! {asn1_ns,stopped},
- exit(normal)
- end.
-
-active(V) ->
- case curr(V) of
- nil -> false;
- _ -> true
- end.
-
-req(Req) ->
- asn1_ns ! {self(), Req},
- receive {asn1_ns, Reply} -> Reply end.
-
-pop(V) -> req({pop,V}).
-push(V) -> req({push,V}).
-clear() -> req(stop), start().
-curr(V) -> req({current,V}).
-new(V) -> req({new,V}).
-delete(V) -> req({delete,V}).
-prev(V) ->
- case req({prev,V}) of
- none ->
- exit('cant get prev of none');
- Rep -> Rep
- end.
-
-next(V) ->
- case req({next,V}) of
- none ->
- exit('cant get next of none');
- Rep -> Rep
- end.
-
-all(V) ->
- Curr = curr(V),
- if Curr == V -> [];
- true ->
- lists:reverse(generate(V,last(Curr),[],0))
- end.
-
-generate(V,Number,Res,Pos) ->
- Ell = Pos+1,
- if
- Ell > Number ->
- Res;
- true ->
- generate(V,Number,[list_to_atom(lists:concat([V,Ell]))|Res],Ell)
- end.
-
-last(V) ->
- last2(lists:reverse(atom_to_list(V))).
-
-last2(RevL) ->
- list_to_integer(lists:reverse(get_digs(RevL))).
-
-
-get_digs([H|T]) ->
- if
- H < $9+1,
- H > $0-1 ->
- [H|get_digs(T)];
- true ->
- []
- end.
-
-push_var(Vars,Variable) ->
- case lists:keysearch(Variable,1,Vars) of
- false ->
- [{Variable,[0]}|Vars];
- {value,{Variable,[Digit|Drest]}} ->
- NewVars = lists:keydelete(Variable,1,Vars),
- [{Variable,[Digit,Digit|Drest]}|NewVars]
- end.
-
-pop_var(Vars,Variable) ->
- case lists:keysearch(Variable,1,Vars) of
- false ->
- ok;
- {value,{Variable,[_Dig]}} ->
- lists:keydelete(Variable,1,Vars);
- {value,{Variable,[_Dig|Digits]}} ->
- NewVars = lists:keydelete(Variable,1,Vars),
- [{Variable,Digits}|NewVars]
- end.
-
-get_curr([],Variable) ->
- Variable;
-get_curr([{Variable,[0|_Drest]}|_Tail],Variable) ->
- Variable;
-get_curr([{Variable,[Digit|_Drest]}|_Tail],Variable) ->
- list_to_atom(lists:concat([Variable,integer_to_list(Digit)]));
-
-get_curr([_|Tail],Variable) ->
- get_curr(Tail,Variable).
-
-new_var(Vars,Variable) ->
- case lists:keysearch(Variable,1,Vars) of
- false ->
- [{Variable,[1]}|Vars];
- {value,{Variable,[Digit|Drest]}} ->
- NewVars = lists:keydelete(Variable,1,Vars),
- [{Variable,[Digit+1|Drest]}|NewVars]
- end.
-
-delete_var(Vars,Variable) ->
- case lists:keysearch(Variable,1,Vars) of
- false ->
- Vars;
- {value,{Variable,[N]}} when N =< 1 ->
- lists:keydelete(Variable,1,Vars);
- {value,{Variable,[Digit|Drest]}} ->
- case Digit of
- 0 ->
- Vars;
- _ ->
- NewVars = lists:keydelete(Variable,1,Vars),
- [{Variable,[Digit-1|Drest]}|NewVars]
- end
- end.
-
-get_prev(Vars,Variable) ->
- case lists:keysearch(Variable,1,Vars) of
- false ->
- none;
- {value,{Variable,[Digit|_]}} when Digit =< 1 ->
- Variable;
- {value,{Variable,[Digit|_]}} when Digit > 1 ->
- list_to_atom(lists:concat([Variable,
- integer_to_list(Digit-1)]));
- _ ->
- none
- end.
-
-get_next(Vars,Variable) ->
- case lists:keysearch(Variable,1,Vars) of
- false ->
- list_to_atom(lists:concat([Variable,"1"]));
- {value,{Variable,[Digit|_]}} when Digit >= 0 ->
- list_to_atom(lists:concat([Variable,
- integer_to_list(Digit+1)]));
- _ ->
- none
- end.
-
-
-stop_server(Name) ->
- stop_server(Name, whereis(Name)).
-stop_server(_Name, undefined) -> stopped;
-stop_server(Name, _Pid) ->
- Name ! {self(), stop},
- receive {Name, _} -> stopped end.
-
-
-start_server(Name,Mod,Fun,Args) ->
- case whereis(Name) of
- undefined ->
- register(Name, spawn(Mod,Fun, Args));
- _Pid ->
- already_started
- end.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_parser.yrl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_parser.yrl
deleted file mode 100644
index df74685cb7..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_parser.yrl
+++ /dev/null
@@ -1,1175 +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: asn1ct_parser.yrl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
-%%
-Nonterminals
-ModuleDefinition ModuleIdentifier DefinitiveIdentifier DefinitiveObjIdComponentList
-DefinitiveObjIdComponent TagDefault ExtensionDefault
-ModuleBody Exports SymbolsExported Imports SymbolsImported
-SymbolsFromModuleList SymbolsFromModule GlobalModuleReference AssignedIdentifier SymbolList
-Symbol Reference AssignmentList Assignment
-ExtensionAndException
-ComponentTypeLists
-Externaltypereference Externalvaluereference DefinedType DefinedValue
-AbsoluteReference ItemSpec ItemId ComponentId TypeAssignment
-ValueAssignment
-% ValueSetTypeAssignment
-ValueSet
-Type BuiltinType NamedType ReferencedType
-Value ValueNotNull BuiltinValue ReferencedValue NamedValue
-% BooleanType
-BooleanValue IntegerType NamedNumberList NamedNumber SignedNumber
-% inlined IntegerValue
-EnumeratedType
-% inlined Enumerations
-Enumeration EnumerationItem
-% inlined EnumeratedValue
-% RealType
-RealValue NumericRealValue SpecialRealValue BitStringType
-% inlined BitStringValue
-IdentifierList
-% OctetStringType
-% inlined OctetStringValue
-% NullType NullValue
-SequenceType ComponentTypeList ComponentType
-% SequenceValue SequenceOfValue
-ComponentValueList SequenceOfType
-SAndSOfValue ValueList SetType
-% SetValue SetOfValue
-SetOfType
-ChoiceType
-% AlternativeTypeList made common with ComponentTypeList
-ChoiceValue
-AnyValue
-AnyDefBy
-SelectionType
-TaggedType Tag ClassNumber Class
-% redundant TaggedValue
-% EmbeddedPDVType EmbeddedPDVValue ExternalType ExternalValue ObjectIdentifierType
-ObjectIdentifierValue ObjIdComponentList ObjIdComponent
-% NameForm NumberForm NameAndNumberForm
-CharacterStringType
-RestrictedCharacterStringValue CharacterStringList
-% CharSyms CharsDefn
-Quadruple
-% Group Plane Row Cell
-Tuple
-% TableColumn TableRow
-% UnrestrictedCharacterString
-CharacterStringValue
-% UnrestrictedCharacterStringValue
-ConstrainedType Constraint ConstraintSpec TypeWithConstraint
-ElementSetSpecs ElementSetSpec
-%GeneralConstraint
-UserDefinedConstraint UserDefinedConstraintParameter
-UserDefinedConstraintParameters
-ExceptionSpec
-ExceptionIdentification
-Unions
-UnionMark
-UElems
-Intersections
-IntersectionElements
-IntersectionMark
-IElems
-Elements
-Elems
-SubTypeElements
-Exclusions
-LowerEndpoint
-UpperEndpoint
-LowerEndValue
-UpperEndValue
-TypeConstraints NamedConstraint PresenceConstraint
-
-ParameterizedTypeAssignment
-ParameterList
-Parameters
-Parameter
-ParameterizedType
-
-% X.681
-ObjectClassAssignment ObjectClass ObjectClassDefn
-FieldSpecs FieldSpec OptionalitySpec WithSyntaxSpec
-TokenOrGroupSpecs TokenOrGroupSpec
-SyntaxList OptionalGroup RequiredToken Word
-TypeOptionalitySpec
-ValueOrObjectOptSpec
-VSetOrOSetOptSpec
-ValueOptionalitySpec
-ObjectOptionalitySpec
-ValueSetOptionalitySpec
-ObjectSetOptionalitySpec
-% X.681 chapter 15
-InformationFromObjects
-ValueFromObject
-%ValueSetFromObjects
-TypeFromObject
-%ObjectFromObject
-%ObjectSetFromObjects
-ReferencedObjects
-FieldName
-PrimitiveFieldName
-
-ObjectAssignment
-ObjectSetAssignment
-ObjectSet
-ObjectSetElements
-Object
-ObjectDefn
-DefaultSyntax
-DefinedSyntax
-FieldSettings
-FieldSetting
-DefinedSyntaxTokens
-DefinedSyntaxToken
-Setting
-DefinedObject
-ObjectFromObject
-ObjectSetFromObjects
-ParameterizedObject
-ExternalObjectReference
-DefinedObjectSet
-DefinedObjectClass
-ExternalObjectClassReference
-
-% X.682
-TableConstraint
-ComponentRelationConstraint
-ComponentIdList
-
-% X.683
-ActualParameter
-.
-
-%UsefulType.
-
-Terminals
-'ABSENT' 'ABSTRACT-SYNTAX' 'ALL' 'ANY'
-'APPLICATION' 'AUTOMATIC' 'BEGIN' 'BIT'
-'BOOLEAN' 'BY' 'CHARACTER' 'CHOICE' 'CLASS' 'COMPONENT'
-'COMPONENTS' 'CONSTRAINED' 'DEFAULT' 'DEFINED' 'DEFINITIONS'
-'EMBEDDED' 'END' 'ENUMERATED' 'EXCEPT' 'EXPLICIT'
-'EXPORTS' 'EXTENSIBILITY' 'EXTERNAL' 'FALSE' 'FROM' 'GeneralizedTime'
-'TYPE-IDENTIFIER'
-'IDENTIFIER' 'IMPLICIT' 'IMPLIED' 'IMPORTS'
-'INCLUDES' 'INSTANCE' 'INTEGER' 'INTERSECTION'
-'MAX' 'MIN' 'MINUS-INFINITY' 'NULL'
-'OBJECT' 'ObjectDescriptor' 'OCTET' 'OF' 'OPTIONAL' 'PDV' 'PLUS-INFINITY'
-'PRESENT' 'PRIVATE' 'REAL' 'SEQUENCE' 'SET' 'SIZE'
-'STRING' 'SYNTAX' 'TAGS' 'TRUE' 'UNION'
-'UNIQUE' 'UNIVERSAL' 'UTCTime' 'WITH'
-'{' '}' '(' ')' '.' '::=' ';' ',' '@' '*' '-' '[' ']'
-'!' '..' '...' '|' '<' ':' '^'
-number identifier typereference restrictedcharacterstringtype
-bstring hstring cstring typefieldreference valuefieldreference
-objectclassreference word.
-
-Rootsymbol ModuleDefinition.
-Endsymbol '$end'.
-
-Left 300 'EXCEPT'.
-Left 200 '^'.
-Left 200 'INTERSECTION'.
-Left 100 '|'.
-Left 100 'UNION'.
-
-
-ModuleDefinition -> ModuleIdentifier
- 'DEFINITIONS'
- TagDefault
- ExtensionDefault
- '::='
- 'BEGIN'
- ModuleBody
- 'END' :
- {'ModuleBody',Ex,Im,Types} = '$7',
- {{typereference,Pos,Name},Defid} = '$1',
- #module{
- pos= Pos,
- name= Name,
- defid= Defid,
- tagdefault='$3',
- extensiondefault='$4',
- exports=Ex,
- imports=Im,
- typeorval=Types}.
-% {module, '$1','$3','$6'}.
-% Results always in a record of type module defined in asn_records.hlr
-
-ModuleIdentifier -> typereference DefinitiveIdentifier :
- put(asn1_module,'$1'#typereference.val),
- {'$1','$2'}.
-
-DefinitiveIdentifier -> '{' DefinitiveObjIdComponentList '}' : '$2' .
-DefinitiveIdentifier -> '$empty': [].
-
-DefinitiveObjIdComponentList -> DefinitiveObjIdComponent : ['$1'].
-DefinitiveObjIdComponentList -> DefinitiveObjIdComponent DefinitiveObjIdComponentList : ['$1'|'$2'].
-
-DefinitiveObjIdComponent -> identifier : '$1' . %expanded->
-% DefinitiveObjIdComponent -> NameForm : '$1' .
-DefinitiveObjIdComponent -> number : '$1' . %expanded->
-% DefinitiveObjIdComponent -> DefinitiveNumberForm : 'fix' .
-DefinitiveObjIdComponent -> identifier '(' number ')' : {'$1','$3'} . %expanded->
-% DefinitiveObjIdComponent -> DefinitiveNameAndNumberForm : {'$1','$3'} .
-
-% DefinitiveNumberForm -> number : 'fix' .
-
-% DefinitiveNameAndNumberForm -> identifier '(' DefinitiveNumberForm ')' : 'fix' .
-
-TagDefault -> 'EXPLICIT' 'TAGS' : put(tagdefault,'EXPLICIT'),'EXPLICIT' .
-TagDefault -> 'IMPLICIT' 'TAGS' : put(tagdefault,'IMPLICIT'),'IMPLICIT' .
-TagDefault -> 'AUTOMATIC' 'TAGS' : put(tagdefault,'AUTOMATIC'),'AUTOMATIC' .
-TagDefault -> '$empty': put(tagdefault,'EXPLICIT'),'EXPLICIT'. % because this is the default
-
-ExtensionDefault -> 'EXTENSIBILITY' 'IMPLIED' : 'IMPLIED'.
-ExtensionDefault -> '$empty' : 'false'. % because this is the default
-
-ModuleBody -> Exports Imports AssignmentList : {'ModuleBody','$1','$2','$3'}.
-ModuleBody -> '$empty' : {'ModuleBody',nil,nil,[]}.
-
-Exports -> 'EXPORTS' SymbolList ';' : {exports,'$2'}.
-Exports -> 'EXPORTS' ';' : {exports,[]}.
-Exports -> '$empty' : {exports,all} .
-
-% inlined above SymbolsExported -> SymbolList : '$1'.
-% inlined above SymbolsExported -> '$empty' : [].
-
-Imports -> 'IMPORTS' SymbolsFromModuleList ';' : {imports,'$2'}.
-Imports -> 'IMPORTS' ';' : {imports,[]}.
-Imports -> '$empty' : {imports,[]} .
-
-% inlined above SymbolsImported -> SymbolsFromModuleList : '$1'.
-% inlined above SymbolsImported -> '$empty' : [].
-
-SymbolsFromModuleList -> SymbolsFromModule :['$1'].
-% SymbolsFromModuleList -> SymbolsFromModuleList SymbolsFromModule :$1.%changed
-SymbolsFromModuleList -> SymbolsFromModule SymbolsFromModuleList :['$1'|'$2'].
-
-% expanded SymbolsFromModule -> SymbolList 'FROM' GlobalModuleReference : #'SymbolsFromModule'{symbols = '$1',module='$3'}.
-SymbolsFromModule -> SymbolList 'FROM' typereference : #'SymbolsFromModule'{symbols = '$1',module='$3'}.
-SymbolsFromModule -> SymbolList 'FROM' typereference '{' ValueList '}': #'SymbolsFromModule'{symbols = '$1',module='$3'}.
-%SymbolsFromModule -> SymbolList 'FROM' typereference identifier: #'SymbolsFromModule'{symbols = '$1',module='$3'}.
-%SymbolsFromModule -> SymbolList 'FROM' typereference Externalvaluereference: #'SymbolsFromModule'{symbols = '$1',module='$3'}.
-%SymbolsFromModule -> SymbolList 'FROM' typereference DefinedValue: #'SymbolsFromModule'{symbols = '$1',module='$3'}.
-
-% inlined GlobalModuleReference -> typereference AssignedIdentifier : {'$1','$2'} .
-
-% inlined above AssignedIdentifier -> '{' ValueList '}' : '$2'.
-% replaced AssignedIdentifier -> '{' DefinedValue ObjIdComponentList '}' :{'$2','$3'}.
-% not necessary , replaced by SAndSOfValue AssignedIdentifier -> ObjectIdentifierValue :'$1'.
-% AssignedIdentifier -> DefinedValue : '$1'.
-% inlined AssignedIdentifier -> '$empty' : undefined.
-
-SymbolList -> Symbol : ['$1'].
-SymbolList -> Symbol ',' SymbolList :['$1'|'$3'].
-
-Symbol -> Reference :'$1'.
-% later Symbol -> ParameterizedReference :'$1'.
-
-Reference -> typereference :'$1'.
-Reference -> identifier:'$1'.
-Reference -> typereference '{' '}':'$1'.
-Reference -> Externaltypereference '{' '}':'$1'.
-
-% later Reference -> objectclassreference :'$1'.
-% later Reference -> objectreference :'$1'.
-% later Reference -> objectsetreference :'$1'.
-
-AssignmentList -> Assignment : ['$1'].
-% modified AssignmentList -> AssignmentList Assignment : '$1'.
-AssignmentList -> Assignment AssignmentList : ['$1'|'$2'].
-
-Assignment -> TypeAssignment : '$1'.
-Assignment -> ValueAssignment : '$1'.
-% later Assignment -> ValueSetTypeAssignment : '$1'.
-Assignment -> ObjectClassAssignment : '$1'.
-% later Assignment -> ObjectAssignment : '$1'.
-% combined with ValueAssignment Assignment -> ObjectAssignment : '$1'.
-Assignment -> ObjectSetAssignment : '$1'.
-Assignment -> ParameterizedTypeAssignment : '$1'.
-%Assignment -> ParameterizedValueAssignment : '$1'.
-%Assignment -> ParameterizedValueSetTypeAssignment : '$1'.
-%Assignment -> ParameterizedObjectClassAssignment : '$1'.
-
-ObjectClassAssignment -> typereference '::=' 'CLASS' '{' FieldSpecs '}' :
-%ObjectClassAssignment -> objectclassreference '::=' 'CLASS' '{' FieldSpecs '}' :
- #typedef{pos=element(2,'$1'),name=element(3,'$1'),typespec={'CLASS','$5',[]}}.
-ObjectClassAssignment -> typereference '::=' 'CLASS' '{' FieldSpecs '}' WithSyntaxSpec :
-%ObjectClassAssignment -> objectclassreference '::=' 'CLASS' '{' FieldSpecs '}' WithSyntaxSpec :
- #typedef{pos=element(2,'$1'),name=element(3,'$1'),typespec={'CLASS','$5','$7'}}.
-
-FieldSpecs -> FieldSpec : ['$1'].
-FieldSpecs -> FieldSpec ',' FieldSpecs : ['$1'|'$3'].
-
-FieldSpec -> typefieldreference TypeOptionalitySpec : {typefield,'$1','$2'}.
-
-FieldSpec -> valuefieldreference Type 'UNIQUE' ValueOrObjectOptSpec :
- {fixedtypevaluefield,'$1','$2','UNIQUE','$4'}.
-FieldSpec -> valuefieldreference Type ValueOrObjectOptSpec :
- {fixedtypevaluefield,'$1','$2',undefined,'$3'}.
-
-FieldSpec -> valuefieldreference typefieldreference ValueOrObjectOptSpec :
- {variabletypevaluefield, '$1','$2','$3'}.
-
-FieldSpec -> typefieldreference typefieldreference VSetOrOSetOptSpec :
- {variabletypevaluesetfield, '$1','$2','$3'}.
-
-FieldSpec -> typefieldreference Type VSetOrOSetOptSpec :
- {fixedtypevaluesetfield, '$1','$2','$3'}.
-
-TypeOptionalitySpec -> 'DEFAULT' Type : {'DEFAULT','$2'}.
-TypeOptionalitySpec -> 'OPTIONAL' : 'OPTIONAL'.
-TypeOptionalitySpec -> '$empty' : 'MANDATORY'.
-
-ValueOrObjectOptSpec -> ValueOptionalitySpec : '$1'.
-ValueOrObjectOptSpec -> ObjectOptionalitySpec : '$1'.
-ValueOrObjectOptSpec -> 'OPTIONAL' : 'OPTIONAL'.
-ValueOrObjectOptSpec -> '$empty' : 'MANDATORY'.
-
-ValueOptionalitySpec -> 'DEFAULT' Value :
- case '$2' of
- {identifier,_,Id} -> {'DEFAULT',Id};
- _ -> {'DEFAULT','$2'}
- end.
-
-%ObjectOptionalitySpec -> 'DEFAULT' Object :{'DEFAULT','$1'}.
-ObjectOptionalitySpec -> 'DEFAULT' '{' FieldSetting ',' FieldSettings '}' :
- {'DEFAULT',{object,['$2'|'$4']}}.
-ObjectOptionalitySpec -> 'DEFAULT' '{' FieldSetting '}' :
- {'DEFAULT',{object, ['$2']}}.
-%ObjectOptionalitySpec -> 'DEFAULT' '{' DefinedSyntaxTokens '}' :
-% {'DEFAULT',{object, '$2'}}.
-ObjectOptionalitySpec -> 'DEFAULT' ObjectFromObject :
- {'DEFAULT',{object, '$2'}}.
-
-
-VSetOrOSetOptSpec -> ValueSetOptionalitySpec : '$1'.
-%VSetOrOSetOptSpec -> ObjectSetOptionalitySpec : '$1'.
-VSetOrOSetOptSpec -> 'OPTIONAL' : 'OPTIONAL'.
-VSetOrOSetOptSpec -> '$empty' : 'MANDATORY'.
-
-ValueSetOptionalitySpec -> 'DEFAULT' ValueSet : {'DEFAULT','$1'}.
-
-%ObjectSetOptionalitySpec -> 'DEFAULT' ObjectSet : {'DEFAULT','$1'}.
-
-OptionalitySpec -> 'DEFAULT' Type : {'DEFAULT','$2'}.
-OptionalitySpec -> 'DEFAULT' ValueNotNull :
- case '$2' of
- {identifier,_,Id} -> {'DEFAULT',Id};
- _ -> {'DEFAULT','$2'}
- end.
-OptionalitySpec -> 'OPTIONAL' : 'OPTIONAL'.
-OptionalitySpec -> '$empty' : 'MANDATORY'.
-
-WithSyntaxSpec -> 'WITH' 'SYNTAX' SyntaxList : {'WITH SYNTAX','$3'}.
-
-SyntaxList -> '{' TokenOrGroupSpecs '}' : '$2'.
-SyntaxList -> '{' '}' : [].
-
-TokenOrGroupSpecs -> TokenOrGroupSpec : ['$1'].
-TokenOrGroupSpecs -> TokenOrGroupSpec TokenOrGroupSpecs : ['$1'|'$2'].
-
-TokenOrGroupSpec -> RequiredToken : '$1'.
-TokenOrGroupSpec -> OptionalGroup : '$1'.
-
-OptionalGroup -> '[' TokenOrGroupSpecs ']' : '$2'.
-
-RequiredToken -> typereference : '$1'.
-RequiredToken -> Word : '$1'.
-RequiredToken -> ',' : '$1'.
-RequiredToken -> PrimitiveFieldName : '$1'.
-
-Word -> 'BY' : 'BY'.
-
-ParameterizedTypeAssignment -> typereference ParameterList '::=' Type :
- #ptypedef{pos=element(2,'$1'),name=element(3,'$1'),
- args='$2', typespec='$4'}.
-
-ParameterList -> '{' Parameters '}':'$2'.
-
-Parameters -> Parameter: ['$1'].
-Parameters -> Parameter ',' Parameters: ['$1'|'$3'].
-
-Parameter -> typereference: '$1'.
-Parameter -> Value: '$1'.
-Parameter -> Type ':' typereference: {'$1','$3'}.
-Parameter -> Type ':' Value: {'$1','$3'}.
-Parameter -> '{' typereference '}': {objectset,'$2'}.
-
-
-% Externaltypereference -> modulereference '.' typereference : {'$1','$3'} .
-Externaltypereference -> typereference '.' typereference : #'Externaltypereference'{pos=element(2,'$1'),module=element(3,'$1'),type=element(3,'$3')}.
-
-% Externalvaluereference -> modulereference '.' valuereference : {'$1','$3'} .
-% inlined Externalvaluereference -> typereference '.' identifier : #'Externalvaluereference'{pos=element(2,'$1'),module=element(3,'$1'),value=element(3,'$3')}.
-
-
-DefinedType -> Externaltypereference : '$1' .
-DefinedType -> typereference :
- #'Externaltypereference'{pos='$1'#typereference.pos,
- module= get(asn1_module),
- type= '$1'#typereference.val} .
-DefinedType -> typereference ParameterList : {pt,'$1','$2'}.
-DefinedType -> Externaltypereference ParameterList : {pt,'$1','$2'}.
-
-% ActualParameterList -> '{' ActualParameters '}' : '$1'.
-
-% ActualParameters -> ActualParameter : ['$1'].
-% ActualParameters -> ActualParameter ',' ActualParameters : ['$1'|'$3'].
-
-ActualParameter -> Type : '$1'.
-ActualParameter -> ValueNotNull : '$1'.
-ActualParameter -> ValueSet : '$1'.
-% later DefinedType -> ParameterizedType : '$1' .
-% later DefinedType -> ParameterizedValueSetType : '$1' .
-
-% inlined DefinedValue -> Externalvaluereference :'$1'.
-% inlined DefinedValue -> identifier :'$1'.
-% later DefinedValue -> ParameterizedValue :'$1'.
-
-% not referenced yet AbsoluteReference -> '@' GlobalModuleReference '.' ItemSpec :{'$2','$4'}.
-
-% not referenced yet ItemSpec -> typereference :'$1'.
-% not referenced yet ItemSpec -> ItemId '.' ComponentId : {'$1','$3'}.
-
-% not referenced yet ItemId -> ItemSpec : '$1'.
-
-% not referenced yet ComponentId -> identifier :'$1'.
-% not referenced yet ComponentId -> number :'$1'.
-% not referenced yet ComponentId -> '*' :'$1'.
-
-TypeAssignment -> typereference '::=' Type :
- #typedef{pos=element(2,'$1'),name=element(3,'$1'),typespec='$3'}.
-
-ValueAssignment -> identifier Type '::=' Value :
- #valuedef{pos=element(2,'$1'),name=element(3,'$1'),type='$2',value='$4'}.
-
-% later ValueSetTypeAssignment -> typereference Type '::=' ValueSet :{'ValueSetTypeAssignment','$1','$2','$4'}.
-
-
-ValueSet -> '{' ElementSetSpec '}' : {valueset,'$2'}.
-
-% record(type,{tag,def,constraint}).
-Type -> BuiltinType :#type{def='$1'}.
-Type -> 'NULL' :#type{def='NULL'}.
-Type -> TaggedType:'$1'.
-Type -> ReferencedType:#type{def='$1'}. % change notag later
-Type -> ConstrainedType:'$1'.
-
-%ANY is here for compatibility with the old ASN.1 standard from 1988
-BuiltinType -> 'ANY' AnyDefBy:
- case '$2' of
- [] -> 'ANY';
- _ -> {'ANY DEFINED BY','$2'}
- end.
-BuiltinType -> BitStringType :'$1'.
-BuiltinType -> 'BOOLEAN' :element(1,'$1').
-BuiltinType -> CharacterStringType :'$1'.
-BuiltinType -> ChoiceType :'$1'.
-BuiltinType -> 'EMBEDDED' 'PDV' :'EMBEDDED PDV'.
-BuiltinType -> EnumeratedType :'$1'.
-BuiltinType -> 'EXTERNAL' :element(1,'$1').
-% later BuiltinType -> InstanceOfType :'$1'.
-BuiltinType -> IntegerType :'$1'.
-% BuiltinType -> 'NULL' :element(1,'$1').
-% later BuiltinType -> ObjectClassFieldType :'$1'.
-BuiltinType -> 'OBJECT' 'IDENTIFIER' :'OBJECT IDENTIFIER'.
-BuiltinType -> 'OCTET' 'STRING' :'OCTET STRING'.
-BuiltinType -> 'REAL' :element(1,'$1').
-BuiltinType -> SequenceType :'$1'.
-BuiltinType -> SequenceOfType :'$1'.
-BuiltinType -> SetType :'$1'.
-BuiltinType -> SetOfType :'$1'.
-% The so called Useful types
-BuiltinType -> 'GeneralizedTime': 'GeneralizedTime'.
-BuiltinType -> 'UTCTime' :'UTCTime'.
-BuiltinType -> 'ObjectDescriptor' : 'ObjectDescriptor'.
-
-% moved BuiltinType -> TaggedType :'$1'.
-
-
-AnyDefBy -> 'DEFINED' 'BY' identifier: '$3'.
-AnyDefBy -> '$empty': [].
-
-NamedType -> identifier Type :
-%{_,Pos,Val} = '$1',
-%{'NamedType',Pos,{Val,'$2'}}.
-V1 = '$1',
-{'NamedType',V1#identifier.pos,{V1#identifier.val,'$2'}}.
-NamedType -> SelectionType :'$1'.
-
-ReferencedType -> DefinedType : '$1'.
-% redundant ReferencedType -> UsefulType : 'fix'.
-ReferencedType -> SelectionType : '$1'.
-ReferencedType -> TypeFromObject : '$1'.
-% later ReferencedType -> ValueSetFromObjects : 'fix'.
-
-% to much conflicts Value -> AnyValue :'$1'.
-Value -> ValueNotNull : '$1'.
-Value -> 'NULL' :element(1,'$1').
-
-ValueNotNull -> BuiltinValue :'$1'.
-% inlined Value -> DefinedValue :'$1'. % DefinedValue , identifier
-% inlined Externalvaluereference -> Externalvaluereference :'$1'.
-ValueNotNull -> typereference '.' identifier :
- #'Externalvaluereference'{pos=element(2,'$1'),module=element(3,'$1'),
- value=element(3,'$3')}.
-ValueNotNull -> identifier :'$1'.
-
-
-%tmp Value -> NamedNumber: '$1'. % not a value but part of ObjIdC
-% redundant BuiltinValue -> BitStringValue :'$1'.
-BuiltinValue -> BooleanValue :'$1'.
-BuiltinValue -> CharacterStringValue :'$1'.
-BuiltinValue -> ChoiceValue :'$1'.
-% BuiltinValue -> EmbeddedPDVValue :'$1'. ==SequenceValue
-% BuiltinValue -> EnumeratedValue :'$1'. identifier
-% BuiltinValue -> ExternalValue :'$1'. ==SequenceValue
-% later BuiltinValue -> InstanceOfValue :'$1'.
-BuiltinValue -> SignedNumber :'$1'.
-% BuiltinValue -> 'NULL' :'$1'.
-% later BuiltinValue -> ObjectClassFieldValue :'$1'.
-% replaced by SAndSOfValue BuiltinValue -> ObjectIdentifierValue :'$1'.
-BuiltinValue -> bstring :element(3,'$1').
-BuiltinValue -> hstring :element(3,'$1').
-% conflict BuiltinValue -> RealValue :'$1'.
-BuiltinValue -> SAndSOfValue :'$1'.
-% replaced BuiltinValue -> SequenceOfValue :'$1'.
-% replaced BuiltinValue -> SequenceValue :'$1'.
-% replaced BuiltinValue -> SetValue :'$1'.
-% replaced BuiltinValue -> SetOfValue :'$1'.
-% conflict redundant BuiltinValue -> TaggedValue :'$1'.
-
-% inlined ReferencedValue -> DefinedValue:'$1'.
-% ReferencedValue -> Externalvaluereference:'$1'.
-% ReferencedValue -> identifier :'$1'.
-% later ReferencedValue -> ValueFromObject:'$1'.
-
-% inlined BooleanType -> BOOLEAN :'BOOLEAN'.
-
-% to much conflicts AnyValue -> Type ':' Value : {'ANYVALUE',{'$1','$3'}}.
-
-BooleanValue -> TRUE :true.
-BooleanValue -> FALSE :false.
-
-IntegerType -> 'INTEGER' : 'INTEGER'.
-IntegerType -> 'INTEGER' '{' NamedNumberList '}' : {'INTEGER','$3'}.
-
-NamedNumberList -> NamedNumber :['$1'].
-% modified NamedNumberList -> NamedNumberList ',' NamedNumber :'fix'.
-NamedNumberList -> NamedNumber ',' NamedNumberList :['$1'|'$3'].
-
-NamedNumber -> identifier '(' SignedNumber ')' : {'NamedNumber',element(3,'$1'),'$3'}.
-NamedNumber -> identifier '(' typereference '.' identifier ')' : {'NamedNumber',element(3,'$1'),{'ExternalValue',element(3,'$3'),element(3,'$5')}}.
-NamedNumber -> identifier '(' identifier ')' : {'NamedNumber',element(3,'$1'),element(3,'$3')}.
-
-%NamedValue -> identifier Value :
-% {'NamedValue',element(2,'$1'),element(3,'$1'),'$2'}.
-
-
-SignedNumber -> number : element(3,'$1').
-SignedNumber -> '-' number : - element(3,'$1').
-
-% inlined IntegerValue -> SignedNumber :'$1'.
-% conflict moved to Value IntegerValue -> identifier:'$1'.
-
-EnumeratedType -> ENUMERATED '{' Enumeration '}' :{'ENUMERATED','$3'}.
-
-% inlined Enumerations -> Enumeration :{'$1','false',[]}.
-% inlined Enumerations -> Enumeration ',' '...' : {'$1','true',[]}.
-% inlined Enumerations -> Enumeration ',' '...' ',' Enumeration : {'$1','true','$5'}.
-
-Enumeration -> EnumerationItem :['$1'].
-% modified Enumeration -> EnumerationItem ',' Enumeration :'fix'.
-Enumeration -> EnumerationItem ',' Enumeration :['$1'|'$3'].
-
-EnumerationItem -> identifier:element(3,'$1').
-EnumerationItem -> NamedNumber :'$1'.
-EnumerationItem -> '...' :'EXTENSIONMARK'.
-
-% conflict moved to Value EnumeratedValue -> identifier:'$1'.
-
-% inlined RealType -> REAL:'REAL'.
-
-RealValue -> NumericRealValue :'$1'.
-RealValue -> SpecialRealValue:'$1'.
-
-% ?? NumericRealValue -> number:'$1'. % number MUST BE '0'
-NumericRealValue -> SAndSOfValue : '$1'. % Value of the associated sequence type
-
-SpecialRealValue -> 'PLUS-INFINITY' :'$1'.
-SpecialRealValue -> 'MINUS-INFINITY' :'$1'.
-
-BitStringType -> 'BIT' 'STRING' :{'BIT STRING',[]}.
-BitStringType -> 'BIT' 'STRING' '{' NamedNumberList '}' :{'BIT STRING','$4'}.
-% NamedBitList replaced by NamedNumberList to reduce the grammar
-% Must check later that all "numbers" are positive
-
-% inlined BitStringValue -> bstring:'$1'.
-% inlined BitStringValue -> hstring:'$1'.
-% redundant use SequenceValue BitStringValue -> '{' IdentifierList '}' :$2.
-% redundant use SequenceValue BitStringValue -> '{' '}' :'fix'.
-
-IdentifierList -> identifier :[element(3,'$1')].
-% modified IdentifierList -> IdentifierList ',' identifier :'$1'.
-IdentifierList -> identifier ',' IdentifierList :[element(3,'$1')|'$3'].
-
-% inlined OctetStringType -> 'OCTET' 'STRING' :'OCTET STRING'.
-
-% inlined OctetStringValue -> bstring:'$1'.
-% inlined OctetStringValue -> hstring:'$1'.
-
-% inlined NullType -> 'NULL':'NULL'.
-
-% inlined NullValue -> NULL:'NULL'.
-
-% result is {'SEQUENCE',Optionals,Extensionmark,Componenttypelist}.
-SequenceType -> SEQUENCE '{' ComponentTypeList '}' :{'SEQUENCE','$3'}.
-% SequenceType -> SEQUENCE '{' ComponentTypeLists '}' :{'SEQUENCE','$3'}.
-% SequenceType -> SEQUENCE '{' ExtensionAndException '}' :{'SEQUENCE','$3'}.
-SequenceType -> SEQUENCE '{' '}' :{'SEQUENCE',[]}.
-
-% result is {RootComponentList,ExtensionAndException,AdditionalComponentTypeList}.
-%ComponentTypeLists -> ComponentTypeList ',' ExtensionAndException :{'$1','$3',[]}.
-%ComponentTypeLists -> ComponentTypeList :{'$1','false',[]}.
-%ComponentTypeLists -> ComponentTypeList ',' ExtensionAndException
-% ',' ComponentTypeList :{'$1','$3', '$5'}.
-%ComponentTypeLists -> ExtensionAndException ',' ComponentTypeList :{[],'$1','$3'}.
-
-ComponentTypeList -> ComponentType :['$1'].
-% modified below ComponentTypeList -> ComponentTypeList ',' ComponentType :'$1'.
-ComponentTypeList -> ComponentType ',' ComponentTypeList :['$1'|'$3'].
-
-% -record('ComponentType',{pos,name,type,attrib}).
-ComponentType -> '...' ExceptionSpec :{'EXTENSIONMARK',element(2,'$1'),'$2'}.
-ComponentType -> NamedType :
- {'NamedType',Pos,{Name,Type}} = '$1',
- #'ComponentType'{pos=Pos,name=Name,typespec=Type,prop=mandatory}.
-ComponentType -> NamedType 'OPTIONAL' :
- {'NamedType',Pos,{Name,Type}} = '$1',
- #'ComponentType'{pos=Pos,name=Name,typespec=Type,prop='OPTIONAL'}.
-ComponentType -> NamedType 'DEFAULT' Value:
- {'NamedType',Pos,{Name,Type}} = '$1',
- #'ComponentType'{pos=Pos,name=Name,typespec=Type,prop={'DEFAULT','$3'}}.
-ComponentType -> 'COMPONENTS' 'OF' Type :{'COMPONENTS OF','$3'}.
-
-% redundant ExtensionAndException -> '...' : extensionmark.
-% ExtensionAndException -> '...' ExceptionSpec : {extensionmark,'$2'}.
-
-% replaced SequenceValue -> '{' ComponentValueList '}':'$2'.
-% replaced SequenceValue -> '{' '}':[].
-
-ValueList -> Value :['$1'].
-ValueList -> NamedNumber :['$1'].
-% modified ValueList -> ValueList ',' Value :'$1'.
-ValueList -> Value ',' ValueList :['$1'|'$3'].
-ValueList -> Value ',' '...' :['$1' |[]].
-ValueList -> Value ValueList : ['$1',space|'$2'].
-ValueList -> NamedNumber ValueList: ['$1',space|'$2'].
-
-%ComponentValueList -> identifier ObjIdComponent:[{'NamedValue','$1','$2'}].
-%ComponentValueList -> NamedValue :['$1'].
-%ComponentValueList -> NamedValue ',' ComponentValueList:['$1'|'$3'].
-%ComponentValueList -> identifier ObjIdComponent ',' ComponentValueList :[{'NamedValue', '$1','$2'}|'$4'].
-
-SequenceOfType -> SEQUENCE OF Type : {'SEQUENCE OF','$3'}.
-
-% replaced SequenceOfValue with SAndSOfValue
-
-SAndSOfValue -> '{' ValueList '}' :'$2'.
-%SAndSOfValue -> '{' ComponentValueList '}' :'$2'.
-SAndSOfValue -> '{' '}' :[].
-
-% save for later SetType ->
-% result is {'SET',Optionals,Extensionmark,Componenttypelist}.
-SetType -> SET '{' ComponentTypeList '}' :{'SET','$3'}.
-% SetType -> SET '{' ExtensionAndException '}' :{'SET','$3'}.
-SetType -> SET '{' '}' :{'SET',[]}.
-
-% replaced SetValue with SAndSOfValue
-
-SetOfType -> SET OF Type : {'SET OF','$3'}.
-
-% replaced SetOfValue with SAndSOfValue
-
-ChoiceType -> 'CHOICE' '{' ComponentTypeList '}' :{'CHOICE','$3'}.
-% AlternativeTypeList is replaced by ComponentTypeList
-ChoiceValue -> identifier ':' Value : {'ChoiceValue',element(3,'$1'),'$3'}.
-% save for later SelectionType ->
-
-TaggedType -> Tag Type : '$2'#type{tag=['$1'#tag{type={default,get(tagdefault)}}]}.
-TaggedType -> Tag IMPLICIT Type :'$3'#type{tag=['$1'#tag{type='IMPLICIT'}]}.
-TaggedType -> Tag EXPLICIT Type :'$3'#type{tag=['$1'#tag{type='EXPLICIT'}]}.
-
-Tag -> '[' Class ClassNumber ']': #tag{class='$2',number='$3'}.
-Tag -> '[' Class typereference '.' identifier ']':
- #tag{class='$2',number=#'Externalvaluereference'{pos=element(2,'$3'),module=element(3,'$3'),
- value=element(3,'$5')}}.
-Tag -> '[' Class number ']': #tag{class='$2',number=element(3,'$3')}.
-Tag -> '[' Class identifier ']': #tag{class='$2',number=element(3,'$3')}.
-
-ClassNumber -> number :element(3,'$1').
-% inlined above ClassNumber -> typereference '.' identifier :{'Externalvaluereference',element(3,'$1'),element(3,'$3')}.
-ClassNumber -> identifier :element(3,'$1').
-
-Class -> 'UNIVERSAL' :element(1,'$1').
-Class -> 'APPLICATION' :element(1,'$1').
-Class -> 'PRIVATE' :element(1,'$1').
-Class -> '$empty' :'CONTEXT'.
-
-% conflict redundant TaggedValue -> Value:'$1'.
-
-% inlined EmbeddedPDVType -> 'EMBEDDED' 'PDV' :'EMBEDDED PDV'.
-
-% inlined EmbeddedPDVValue -> SequenceValue:'$1'.
-
-% inlined ExternalType -> 'EXTERNAL' :'EXTERNAL'.
-
-% inlined ExternalValue -> SequenceValue :'$1'.
-
-% inlined ObjectIdentifierType -> 'OBJECT' 'IDENTIFIER' :'OBJECT IDENTIFIER'.
-
-ObjectIdentifierValue -> '{' ObjIdComponentList '}' :'$2'.
-% inlined ObjectIdentifierValue -> SequenceAndSequenceOfValue :'$1'.
-% ObjectIdentifierValue -> '{' identifier ObjIdComponentList '}' :{'ObjectIdentifierValue','$2','$3'}.
-% ObjectIdentifierValue -> '{' typereference '.' identifier ObjIdComponentList '}' :{'ObjectIdentifierValue',{'$2','$4'},'$5'}.
-
-ObjIdComponentList -> Value:'$1'.
-ObjIdComponentList -> Value ObjIdComponentList :['$1'|'$2'].
-%ObjIdComponentList -> DefinedValue:'$1'.
-%ObjIdComponentList -> number:'$1'.
-%ObjIdComponentList -> DefinedValue ObjIdComponentList :['$1'|'$2'].
-%ObjIdComponentList -> number ObjIdComponentList :['$1'|'$2'].
-%ObjIdComponentList -> ObjIdComponent ObjIdComponentList :['$1'|'$2'].
-%ObjIdComponentList -> ObjIdComponent ObjIdComponentList :['$1'|'$2'].
-
-% redundant ObjIdComponent -> NameForm :'$1'. % expanded
-% replaced by 2 ObjIdComponent -> NumberForm :'$1'.
-% ObjIdComponent -> number :'$1'.
-% ObjIdComponent -> DefinedValue :'$1'. % means DefinedValue
-% ObjIdComponent -> NameAndNumberForm :'$1'.
-% ObjIdComponent -> NamedNumber :'$1'.
-% NamedBit replaced by NamedNumber to reduce grammar
-% must check later that "number" is positive
-
-% NameForm -> identifier:'$1'.
-
-% inlined NumberForm -> number :'$1'.
-% inlined NumberForm -> DefinedValue :'$1'.
-
-% replaced by NamedBit NameAndNumberForm -> identifier '(' NumberForm ')'.
-% NameAndNumberForm -> NamedBit:'$1'.
-
-
-CharacterStringType -> restrictedcharacterstringtype :element(3,'$1').
-CharacterStringType -> 'CHARACTER' 'STRING' :'CHARACTER STRING'.
-
-RestrictedCharacterStringValue -> cstring :element(3, '$1').
-% modified below RestrictedCharacterStringValue -> CharacterStringList :'$1'.
-% conflict vs BuiltinValue RestrictedCharacterStringValue -> SequenceAndSequenceOfValue :'$1'.
-RestrictedCharacterStringValue -> Quadruple :'$1'.
-RestrictedCharacterStringValue -> Tuple :'$1'.
-
-% redundant CharacterStringList -> '{' ValueList '}' :'$2'. % modified
-
-% redundant CharSyms -> CharsDefn :'$1'.
-% redundant CharSyms -> CharSyms ',' CharsDefn :['$1'|'$3'].
-
-% redundant CharsDefn -> cstring :'$1'.
-% temporary replaced see below CharsDefn -> DefinedValue :'$1'.
-% redundant CharsDefn -> Value :'$1'.
-
-Quadruple -> '{' number ',' number ',' number ',' number '}' :{'Quadruple','$2','$4','$6','$8'}.
-% {Group,Plane,Row,Cell}
-
-Tuple -> '{' number ',' number '}' :{'Tuple', '$2','$4'}.
-% {TableColumn,TableRow}
-
-% inlined UnrestrictedCharacterString -> 'CHARACTER' 'STRING' :'CHARACTER STRING'.
-
-CharacterStringValue -> RestrictedCharacterStringValue :'$1'.
-% conflict vs BuiltinValue CharacterStringValue -> SequenceValue :'$1'. % UnrestrictedCharacterStringValue
-
-% inlined UsefulType -> typereference :'$1'.
-
-SelectionType -> identifier '<' Type : {'SelectionType',element(3,'$1'),'$3'}.
-
-ConstrainedType -> Type Constraint :
- '$1'#type{constraint=merge_constraints(['$2'])}.
-ConstrainedType -> Type Constraint Constraint :
- '$1'#type{constraint=merge_constraints(['$2','$3'])}.
-ConstrainedType -> Type Constraint Constraint Constraint:
- '$1'#type{constraint=merge_constraints(['$2','$3','$4'])}.
-ConstrainedType -> Type Constraint Constraint Constraint Constraint:
- '$1'#type{constraint=merge_constraints(['$2','$3','$4','$5'])}.
-%ConstrainedType -> Type Constraint :'$1'#type{constraint='$2'}.
-%ConstrainedType -> Type Constraint :'$1'#type{constraint='$2'}.
-ConstrainedType -> TypeWithConstraint :'$1'.
-
-TypeWithConstraint -> 'SET' Constraint 'OF' Type :
- #type{def = {'SET OF','$4'},constraint=merge_constraints(['$2'])}.
-TypeWithConstraint -> 'SET' 'SIZE' Constraint 'OF' Type :
- #type{def = {'SET OF','$5'},constraint = merge_constraints([#constraint{c={'SizeConstraint','$3'#constraint.c}}])}.
-TypeWithConstraint -> 'SEQUENCE' Constraint 'OF' Type :
- #type{def = {'SEQUENCE OF','$4'},constraint =
- merge_constraints(['$2'])}.
-TypeWithConstraint -> 'SEQUENCE' 'SIZE' Constraint 'OF' Type :
- #type{def = {'SEQUENCE OF','$5'},constraint = merge_constraints([#constraint{c={'SizeConstraint','$3'#constraint.c}}])}.
-
-
-Constraint -> '(' ConstraintSpec ExceptionSpec ')' :
- #constraint{c='$2',e='$3'}.
-
-% inlined Constraint -> SubTypeConstraint :'$1'.
-ConstraintSpec -> ElementSetSpecs :'$1'.
-ConstraintSpec -> UserDefinedConstraint :'$1'.
-ConstraintSpec -> TableConstraint :'$1'.
-
-TableConstraint -> ComponentRelationConstraint : '$1'.
-TableConstraint -> ObjectSet : '$1'.
-%TableConstraint -> '{' typereference '}' :tableconstraint.
-
-ComponentRelationConstraint -> '{' typereference '}' '{' '@' ComponentIdList '}' : componentrelation.
-ComponentRelationConstraint -> '{' typereference '}' '{' '@' '.' ComponentIdList '}' : componentrelation.
-
-ComponentIdList -> identifier: ['$1'].
-ComponentIdList -> identifier '.' ComponentIdList: ['$1'| '$3'].
-
-
-% later ConstraintSpec -> GeneralConstraint :'$1'.
-
-% from X.682
-UserDefinedConstraint -> 'CONSTRAINED' 'BY' '{' '}' : {constrained_by,[]}.
-UserDefinedConstraint -> 'CONSTRAINED' 'BY'
- '{' UserDefinedConstraintParameters '}' : {constrained_by,'$4'}.
-
-UserDefinedConstraintParameters -> UserDefinedConstraintParameter : ['$1'].
-UserDefinedConstraintParameters ->
- UserDefinedConstraintParameter ','
- UserDefinedConstraintParameters: ['$1'|'$3'].
-
-UserDefinedConstraintParameter -> Type '.' ActualParameter : {'$1','$3'}.
-UserDefinedConstraintParameter -> ActualParameter : '$1'.
-
-
-
-ExceptionSpec -> '!' ExceptionIdentification : '$1'.
-ExceptionSpec -> '$empty' : undefined.
-
-ExceptionIdentification -> SignedNumber : '$1'.
-% inlined ExceptionIdentification -> DefinedValue : '$1'.
-ExceptionIdentification -> typereference '.' identifier :
- #'Externalvaluereference'{pos=element(2,'$1'),module=element(3,'$1'),
- value=element(3,'$1')}.
-ExceptionIdentification -> identifier :'$1'.
-ExceptionIdentification -> Type ':' Value : {'$1','$3'}.
-
-% inlined SubTypeConstraint -> ElementSetSpec
-
-ElementSetSpecs -> ElementSetSpec : '$1'.
-ElementSetSpecs -> ElementSetSpec ',' '...': {'$1',[]}.
-ElementSetSpecs -> '...' ',' ElementSetSpec : {[],'$3'}.
-ElementSetSpecs -> ElementSetSpec ',' '...' ',' ElementSetSpec : {'$1','$5'}.
-
-ElementSetSpec -> Unions : '$1'.
-ElementSetSpec -> 'ALL' Exclusions : {'ALL','$2'}.
-
-Unions -> Intersections : '$1'.
-Unions -> UElems UnionMark IntersectionElements :
- case {'$1','$3'} of
- {{'SingleValue',V1},{'SingleValue',V2}} ->
- {'SingleValue',ordsets:union(to_set(V1),to_set(V2))}
- end.
-
-UElems -> Unions :'$1'.
-
-Intersections -> IntersectionElements :'$1'.
-Intersections -> IElems IntersectionMark IntersectionElements :
- case {'$1','$3'} of
- {{'SingleValue',V1},{'SingleValue',V2}} ->
- {'SingleValue',ordsets:intersection(to_set(V1),to_set(V2))};
- {V1,V2} when list(V1) ->
- V1 ++ [V2];
- {V1,V2} ->
- [V1,V2]
- end.
-%Intersections -> IElems '^' IntersectionElements :{'INTERSECTION','$1','$3'}.
-%Intersections -> IElems 'INTERSECTION' IntersectionElements :{'INTERSECTION','$1','$3'}.
-
-IElems -> Intersections :'$1'.
-
-IntersectionElements -> Elements :'$1'.
-IntersectionElements -> Elems Exclusions :{'$1','$2'}.
-
-Elems -> Elements :'$1'.
-
-Exclusions -> 'EXCEPT' Elements :{'EXCEPT','$2'}.
-
-IntersectionMark -> 'INTERSECTION':'$1'.
-IntersectionMark -> '^':'$1'.
-UnionMark -> 'UNION':'$1'.
-UnionMark -> '|':'$1'.
-
-
-Elements -> SubTypeElements : '$1'.
-%Elements -> ObjectSetElements : '$1'.
-Elements -> '(' ElementSetSpec ')' : '$2'.
-Elements -> ReferencedType : '$1'.
-
-SubTypeElements -> ValueList : {'SingleValue','$1'}. % NOTE it must be a Value
-% The rule above modifyed only because of conflicts
-SubTypeElements -> 'INCLUDES' Type : {'ContainedSubType','$2'}.
-%not lalr1 if this is activated SubTypeElements -> Type : {'TypeConstraint','$1'}.
-SubTypeElements -> LowerEndpoint '..' UpperEndpoint : {'ValueRange',{'$1','$3'}}.
-SubTypeElements -> 'FROM' Constraint : {'PermittedAlphabet','$2'#constraint.c}.
-SubTypeElements -> 'SIZE' Constraint: {'SizeConstraint','$2'#constraint.c}.
-% later will introduce conflicts related to NULL SubTypeElements -> Type : {'TypeConstraint','$1'}.
-SubTypeElements -> 'WITH' 'COMPONENT' Constraint:{'WITH COMPONENT','$3'}.
-SubTypeElements -> 'WITH' 'COMPONENTS' '{' TypeConstraints '}':{'WITH COMPONENTS',{'FullSpecification','$4'}}.
-SubTypeElements -> 'WITH' 'COMPONENTS' '{' '...' ',' TypeConstraints '}' :{'WITH COMPONENTS',{'PartialSpecification','$3'}}.
-
-% inlined above InnerTypeConstraints ::=
-% inlined above SingleTypeConstraint::= Constraint
-% inlined above MultipleTypeConstraints ::= FullSpecification | PartialSpecification
-% inlined above FullSpecification ::= "{" TypeConstraints "}"
-% inlined above PartialSpecification ::= "{" "..." "," TypeConstraints "}"
-% TypeConstraints -> identifier : [{'NamedConstraint',element(3,'$1'),undefined,undefined}]. % is this really meaningful or allowed
-TypeConstraints -> NamedConstraint : ['$1'].
-TypeConstraints -> NamedConstraint ',' TypeConstraints : ['$1'|'$3'].
-TypeConstraints -> identifier : ['$1'].
-TypeConstraints -> identifier ',' TypeConstraints : ['$1'|'$3'].
-
-NamedConstraint -> identifier Constraint PresenceConstraint :{'NamedConstraint',element(3,'$1'),'$2','$3'}.
-NamedConstraint -> identifier Constraint :{'NamedConstraint',element(3,'$1'),'$2',undefined}.
-NamedConstraint -> identifier PresenceConstraint :{'NamedConstraint',element(3,'$1'),undefined,'$2'}.
-
-PresenceConstraint -> 'PRESENT' : 'PRESENT'.
-PresenceConstraint -> 'ABSENT' : 'ABSENT'.
-PresenceConstraint -> 'OPTIONAL' : 'OPTIONAL'.
-
-
-
-LowerEndpoint -> LowerEndValue :'$1'.
-%LowerEndpoint -> LowerEndValue '<':{gt,'$1'}.
-LowerEndpoint -> LowerEndValue '<':('$1'+1).
-
-UpperEndpoint -> UpperEndValue :'$1'.
-%UpperEndpoint -> '<' UpperEndValue :{lt,'$2'}.
-UpperEndpoint -> '<' UpperEndValue :('$2'-1).
-
-LowerEndValue -> Value :'$1'.
-LowerEndValue -> 'MIN' :'MIN'.
-
-UpperEndValue -> Value :'$1'.
-UpperEndValue -> 'MAX' :'MAX'.
-
-
-% X.681
-
-
-% X.681 chap 15
-
-%TypeFromObject -> ReferencedObjects '.' FieldName : {'$1','$3'}.
-TypeFromObject -> typereference '.' FieldName : {'$1','$3'}.
-
-ReferencedObjects -> typereference : '$1'.
-%ReferencedObjects -> ParameterizedObject
-%ReferencedObjects -> DefinedObjectSet
-%ReferencedObjects -> ParameterizedObjectSet
-
-FieldName -> typefieldreference : ['$1'].
-FieldName -> valuefieldreference : ['$1'].
-FieldName -> FieldName '.' FieldName : ['$1' | '$3'].
-
-PrimitiveFieldName -> typefieldreference : '$1'.
-PrimitiveFieldName -> valuefieldreference : '$1'.
-
-%ObjectSetAssignment -> typereference DefinedObjectClass '::=' ObjectSet: null.
-ObjectSetAssignment -> typereference typereference '::=' ObjectSet :
- #typedef{pos=element(2,'$1'),name=element(3,'$1'),typespec={'ObjectSet',element(3,'$2'), '$4'}}.
-ObjectSetAssignment -> typereference typereference '.' typereference '::=' ObjectSet.
-
-ObjectSet -> '{' ElementSetSpecs '}' : '$2'.
-ObjectSet -> '{' '...' '}' : ['EXTENSIONMARK'].
-
-%ObjectSetElements -> Object.
-% ObjectSetElements -> identifier : '$1'.
-%ObjectSetElements -> DefinedObjectSet.
-%ObjectSetElements -> ObjectSetFromObjects.
-%ObjectSetElements -> ParameterizedObjectSet.
-
-%ObjectAssignment -> identifier DefinedObjectClass '::=' Object.
-ObjectAssignment -> ValueAssignment.
-%ObjectAssignment -> identifier typereference '::=' Object.
-%ObjectAssignment -> identifier typereference '.' typereference '::=' Object.
-
-%Object -> DefinedObject: '$1'.
-%Object -> ExternalObjectReference: '$1'.%Object -> DefinedObject: '$1'.
-Object -> typereference '.' identifier: '$1'.%Object -> DefinedObject: '$1'.
-Object -> identifier: '$1'.%Object -> DefinedObject: '$1'.
-
-%Object -> ObjectDefn -> DefaultSyntax: '$1'.
-Object -> '{' FieldSetting ',' FieldSettings '}' : ['$2'|'$4'].
-Object -> '{' FieldSetting '}' :['$2'].
-
-%% For User-friendly notation
-%% Object -> ObjectDefn -> DefinedSyntax
-Object -> '{' '}'.
-Object -> '{' DefinedSyntaxTokens '}'.
-
-% later Object -> ParameterizedObject: '$1'. look in x.683
-
-%DefinedObject -> ExternalObjectReference: '$1'.
-%DefinedObject -> identifier: '$1'.
-
-DefinedObjectClass -> typereference.
-%DefinedObjectClass -> objectclassreference.
-DefinedObjectClass -> ExternalObjectClassReference.
-%DefinedObjectClass -> typereference '.' objectclassreference.
-%%DefinedObjectClass -> UsefulObjectClassReference.
-
-ExternalObjectReference -> typereference '.' identifier.
-ExternalObjectClassReference -> typereference '.' typereference.
-%%ExternalObjectClassReference -> typereference '.' objectclassreference.
-
-ObjectDefn -> DefaultSyntax: '$1'.
-%ObjectDefn -> DefinedSyntax: '$1'.
-
-ObjectFromObject -> ReferencedObjects '.' FieldName : {'ObjectFromObject','$1','$3'}.
-
-% later look in x.683 ParameterizedObject ->
-
-%DefaultSyntax -> '{' '}'.
-%DefaultSyntax -> '{' FieldSettings '}': '$2'.
-DefaultSyntax -> '{' FieldSetting ',' FieldSettings '}': '$2'.
-DefaultSyntax -> '{' FieldSetting '}': '$2'.
-
-FieldSetting -> PrimitiveFieldName Setting: {'$1','$2'}.
-
-FieldSettings -> FieldSetting ',' FieldSettings: ['$1'|'$3'].
-FieldSettings -> FieldSetting ',' FieldSettings: ['$1'|'$3'].
-FieldSettings -> FieldSetting: '$1'.
-
-%DefinedSyntax -> '{' '}'.
-DefinedSyntax -> '{' DefinedSyntaxTokens '}': '$2'.
-
-DefinedSyntaxTokens -> DefinedSyntaxToken: '$1'.
-DefinedSyntaxTokens -> DefinedSyntaxToken DefinedSyntaxTokens: ['$1'|'$2'].
-
-% expanded DefinedSyntaxToken -> Literal: '$1'.
-%DefinedSyntaxToken -> typereference: '$1'.
-DefinedSyntaxToken -> word: '$1'.
-DefinedSyntaxToken -> ',': '$1'.
-DefinedSyntaxToken -> Setting: '$1'.
-%DefinedSyntaxToken -> '$empty': nil .
-
-% Setting ::= Type|Value|ValueSet|Object|ObjectSet
-Setting -> Type: '$1'.
-%Setting -> Value: '$1'.
-%Setting -> ValueNotNull: '$1'.
-Setting -> BuiltinValue: '$1'.
-Setting -> ValueSet: '$1'.
-%Setting -> Object: '$1'.
-%Setting -> ExternalObjectReference.
-Setting -> typereference '.' identifier.
-Setting -> identifier.
-Setting -> ObjectDefn.
-
-Setting -> ObjectSet: '$1'.
-
-
-Erlang code.
-%%-author('[email protected]').
--copyright('Copyright (c) 1991-99 Ericsson Telecom AB').
--vsn('$Revision: 1.1 $').
--include("asn1_records.hrl").
-
-to_set(V) when list(V) ->
- ordsets:list_to_set(V);
-to_set(V) ->
- ordsets:list_to_set([V]).
-
-merge_constraints({Rlist,ExtList}) -> % extensionmarker in constraint
- {merge_constraints(Rlist,[],[]),
- merge_constraints(ExtList,[],[])};
-
-merge_constraints(Clist) ->
- merge_constraints(Clist, [], []).
-
-merge_constraints([Ch|Ct],Cacc, Eacc) ->
- NewEacc = case Ch#constraint.e of
- undefined -> Eacc;
- E -> [E|Eacc]
- end,
- merge_constraints(Ct,[fixup_constraint(Ch#constraint.c)|Cacc],NewEacc);
-
-merge_constraints([],Cacc,[]) ->
- lists:flatten(Cacc);
-merge_constraints([],Cacc,Eacc) ->
- lists:flatten(Cacc) ++ [{'Errors',Eacc}].
-
-fixup_constraint(C) ->
- case C of
- {'SingleValue',V} when list(V) ->
- [C,
- {'ValueRange',{lists:min(V),lists:max(V)}}];
- {'PermittedAlphabet',{'SingleValue',V}} when list(V) ->
- V2 = {'SingleValue',
- ordsets:list_to_set(lists:flatten(V))},
- {'PermittedAlphabet',V2};
- {'PermittedAlphabet',{'SingleValue',V}} ->
- V2 = {'SingleValue',[V]},
- {'PermittedAlphabet',V2};
- {'SizeConstraint',Sc} ->
- {'SizeConstraint',fixup_size_constraint(Sc)};
-
- List when list(List) ->
- [fixup_constraint(Xc)||Xc <- List];
- Other ->
- Other
- end.
-
-fixup_size_constraint({'ValueRange',{Lb,Ub}}) ->
- {Lb,Ub};
-fixup_size_constraint({{'ValueRange',R},[]}) ->
- {R,[]};
-fixup_size_constraint({[],{'ValueRange',R}}) ->
- {[],R};
-fixup_size_constraint({{'ValueRange',R1},{'ValueRange',R2}}) ->
- {R1,R2};
-fixup_size_constraint({'SingleValue',[Sv]}) ->
- fixup_size_constraint({'SingleValue',Sv});
-fixup_size_constraint({'SingleValue',L}) when list(L) ->
- ordsets:list_to_set(L);
-fixup_size_constraint({'SingleValue',L}) ->
- {L,L};
-fixup_size_constraint({C1,C2}) ->
- {fixup_size_constraint(C1), fixup_size_constraint(C2)}.
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_parser2.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_parser2.erl
deleted file mode 100644
index 639dcc6622..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_parser2.erl
+++ /dev/null
@@ -1,2764 +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 2000, Ericsson Utvecklings
-%% AB. All Rights Reserved.''
-%%
-%% $Id: asn1ct_parser2.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
-%%
--module(asn1ct_parser2).
-
--export([parse/1]).
--include("asn1_records.hrl").
-
-%% parse all types in module
-parse(Tokens) ->
- case catch parse_ModuleDefinition(Tokens) of
- {'EXIT',Reason} ->
- {error,{{undefined,get(asn1_module),
- [internal,error,'when',parsing,module,definition,Reason]},
- hd(Tokens)}};
- {asn1_error,Reason} ->
- {error,{Reason,hd(Tokens)}};
- {ModuleDefinition,Rest1} ->
- {Types,Rest2} = parse_AssignmentList(Rest1),
- case Rest2 of
- [{'END',_}|_Rest3] ->
- {ok,ModuleDefinition#module{typeorval = Types}};
- _ ->
- {error,{{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,'END']},
- hd(Rest2)}}
- end
- end.
-
-parse_ModuleDefinition([{typereference,L1,ModuleIdentifier}|Rest0]) ->
- put(asn1_module,ModuleIdentifier),
- {_DefinitiveIdentifier,Rest02} =
- case Rest0 of
- [{'{',_}|_Rest01] ->
- parse_ObjectIdentifierValue(Rest0);
- _ ->
- {[],Rest0}
- end,
- Rest = case Rest02 of
- [{'DEFINITIONS',_}|Rest03] ->
- Rest03;
- _ ->
- throw({asn1_error,{get_line(hd(Rest02)),get(asn1_module),
- [got,get_token(hd(Rest02)),
- expected,'DEFINITIONS']}})
- end,
- {TagDefault,Rest2} =
- case Rest of
- [{'EXPLICIT',_L3},{'TAGS',_L4}|Rest1] ->
- put(tagdefault,'EXPLICIT'), {'EXPLICIT',Rest1};
- [{'IMPLICIT',_L3},{'TAGS',_L4}|Rest1] ->
- put(tagdefault,'IMPLICIT'), {'IMPLICIT',Rest1};
- [{'AUTOMATIC',_L3},{'TAGS',_L4}|Rest1] ->
- put(tagdefault,'AUTOMATIC'), {'AUTOMATIC',Rest1};
- Rest1 ->
- put(tagdefault,'EXPLICIT'), {'EXPLICIT',Rest1} % The default
- end,
- {ExtensionDefault,Rest3} =
- case Rest2 of
- [{'EXTENSIBILITY',_L5}, {'IMPLIED',_L6}|Rest21] ->
- {'IMPLIED',Rest21};
- _ -> {false,Rest2}
- end,
- case Rest3 of
- [{'::=',_L7}, {'BEGIN',_L8}|Rest4] ->
- {Exports, Rest5} = parse_Exports(Rest4),
- {Imports, Rest6} = parse_Imports(Rest5),
- {#module{ pos = L1,
- name = ModuleIdentifier,
- defid = [], % fix this
- tagdefault = TagDefault,
- extensiondefault = ExtensionDefault,
- exports = Exports,
- imports = Imports},Rest6};
- _ -> throw({asn1_error,{get_line(hd(Rest3)),get(asn1_module),
- [got,get_token(hd(Rest3)),expected,"::= BEGIN"]}})
- end;
-parse_ModuleDefinition(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,typereference]}}).
-
-parse_Exports([{'EXPORTS',_L1},{';',_L2}|Rest]) ->
- {{exports,[]},Rest};
-parse_Exports([{'EXPORTS',_L1}|Rest]) ->
- {SymbolList,Rest2} = parse_SymbolList(Rest),
- case Rest2 of
- [{';',_}|Rest3] ->
- {{exports,SymbolList},Rest3};
- _ ->
- throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,';']}})
- end;
-parse_Exports(Rest) ->
- {{exports,all},Rest}.
-
-parse_SymbolList(Tokens) ->
- parse_SymbolList(Tokens,[]).
-
-parse_SymbolList(Tokens,Acc) ->
- {Symbol,Rest} = parse_Symbol(Tokens),
- case Rest of
- [{',',_L1}|Rest2] ->
- parse_SymbolList(Rest2,[Symbol|Acc]);
- Rest2 ->
- {lists:reverse([Symbol|Acc]),Rest2}
- end.
-
-parse_Symbol(Tokens) ->
- parse_Reference(Tokens).
-
-parse_Reference([{typereference,L1,TrefName},{'{',_L2},{'}',_L3}|Rest]) ->
-% {Tref,Rest};
- {tref2Exttref(L1,TrefName),Rest};
-parse_Reference([Tref1 = {typereference,_,_},{'.',_},Tref2 = {typereference,_,_},
- {'{',_L2},{'}',_L3}|Rest]) ->
-% {{Tref1,Tref2},Rest};
- {{tref2Exttref(Tref1),tref2Exttref(Tref2)},Rest};
-parse_Reference([Tref = {typereference,_L1,_TrefName}|Rest]) ->
- {tref2Exttref(Tref),Rest};
-parse_Reference([Vref = {identifier,_L1,_VName}|Rest]) ->
- {identifier2Extvalueref(Vref),Rest};
-parse_Reference(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- [typereference,identifier]]}}).
-
-parse_Imports([{'IMPORTS',_L1},{';',_L2}|Rest]) ->
- {{imports,[]},Rest};
-parse_Imports([{'IMPORTS',_L1}|Rest]) ->
- {SymbolsFromModuleList,Rest2} = parse_SymbolsFromModuleList(Rest),
- case Rest2 of
- [{';',_L2}|Rest3] ->
- {{imports,SymbolsFromModuleList},Rest3};
- Rest3 ->
- throw({asn1_error,{get_line(hd(Rest3)),get(asn1_module),
- [got,get_token(hd(Rest3)),expected,';']}})
- end;
-parse_Imports(Tokens) ->
- {{imports,[]},Tokens}.
-
-parse_SymbolsFromModuleList(Tokens) ->
- parse_SymbolsFromModuleList(Tokens,[]).
-
-parse_SymbolsFromModuleList(Tokens,Acc) ->
- {SymbolsFromModule,Rest} = parse_SymbolsFromModule(Tokens),
- case (catch parse_SymbolsFromModule(Rest)) of
- {Sl,_Rest2} when record(Sl,'SymbolsFromModule') ->
- parse_SymbolsFromModuleList(Rest,[SymbolsFromModule|Acc]);
- _ ->
- {lists:reverse([SymbolsFromModule|Acc]),Rest}
- end.
-
-parse_SymbolsFromModule(Tokens) ->
- SetRefModuleName =
- fun(N) ->
- fun(X) when record(X,'Externaltypereference')->
- X#'Externaltypereference'{module=N};
- (X) when record(X,'Externalvaluereference')->
- X#'Externalvaluereference'{module=N}
- end
- end,
- {SymbolList,Rest} = parse_SymbolList(Tokens),
- case Rest of
- %%How does this case correspond to x.680 ?
- [{'FROM',_L1},Tref = {typereference,_,_},Ref={identifier,_L2,_Id},C={',',_}|Rest2] ->
- {#'SymbolsFromModule'{symbols=SymbolList,
- module=tref2Exttref(Tref)},[Ref,C|Rest2]};
- %%How does this case correspond to x.680 ?
- [{'FROM',_L1},Tref = {typereference,_,_},{identifier,_L2,_Id}|Rest2] ->
- {#'SymbolsFromModule'{symbols=SymbolList,
- module=tref2Exttref(Tref)},Rest2};
- [{'FROM',_L1},Tref = {typereference,_,Name},Brace = {'{',_}|Rest2] ->
- {_ObjIdVal,Rest3} = parse_ObjectIdentifierValue([Brace|Rest2]), % value not used yet, fix me
- NewSymbolList = lists:map(SetRefModuleName(Name),SymbolList),
- {#'SymbolsFromModule'{symbols=NewSymbolList,
- module=tref2Exttref(Tref)},Rest3};
- [{'FROM',_L1},Tref = {typereference,_,Name}|Rest2] ->
- NewSymbolList = lists:map(SetRefModuleName(Name),SymbolList),
- {#'SymbolsFromModule'{symbols=NewSymbolList,
- module=tref2Exttref(Tref)},Rest2};
- _ ->
- throw({asn1_error,{get_line(hd(Rest)),get(asn1_module),
- [got,get_token(hd(Rest)),expected,
- ['FROM typerefernece identifier ,',
- 'FROM typereference identifier',
- 'FROM typereference {',
- 'FROM typereference']]}})
- end.
-
-parse_ObjectIdentifierValue([{'{',_}|Rest]) ->
- parse_ObjectIdentifierValue(Rest,[]).
-
-parse_ObjectIdentifierValue([{number,_,Num}|Rest],Acc) ->
- parse_ObjectIdentifierValue(Rest,[Num|Acc]);
-parse_ObjectIdentifierValue([{identifier,_,Id},{'(',_}, {number,_,Num}, {')',_}|Rest],Acc) ->
- parse_ObjectIdentifierValue(Rest,[{'NamedNumber',Id,Num}|Acc]);
-parse_ObjectIdentifierValue([{identifier,_,Id},{'(',_}, {identifier,_,Id2}, {')',_}|Rest],Acc) ->
- parse_ObjectIdentifierValue(Rest,[{'NamedNumber',Id,Id2}|Acc]);
-parse_ObjectIdentifierValue([{identifier,_,Id},{'(',_}, {typereference,_,Tref},{'.',_},{identifier,_,Id2}, {')',_}|Rest],Acc) ->
- parse_ObjectIdentifierValue(Rest,[{'NamedNumber',Id,{'ExternalValue',Tref,Id2}}|Acc]);
-parse_ObjectIdentifierValue([Id = {identifier,_,_}|Rest],Acc) ->
- parse_ObjectIdentifierValue(Rest,[identifier2Extvalueref(Id)|Acc]);
-parse_ObjectIdentifierValue([{'}',_}|Rest],Acc) ->
- {lists:reverse(Acc),Rest};
-parse_ObjectIdentifierValue([H|_T],_Acc) ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,
- ['{ some of the following }',number,'identifier ( number )',
- 'identifier ( identifier )',
- 'identifier ( typereference.identifier)',identifier]]}}).
-
-parse_AssignmentList(Tokens = [{'END',_}|_Rest]) ->
- {[],Tokens};
-parse_AssignmentList(Tokens = [{'$end',_}|_Rest]) ->
- {[],Tokens};
-parse_AssignmentList(Tokens) ->
- parse_AssignmentList(Tokens,[]).
-
-parse_AssignmentList(Tokens= [{'END',_}|_Rest],Acc) ->
- {lists:reverse(Acc),Tokens};
-parse_AssignmentList(Tokens= [{'$end',_}|_Rest],Acc) ->
- {lists:reverse(Acc),Tokens};
-parse_AssignmentList(Tokens,Acc) ->
- case (catch parse_Assignment(Tokens)) of
- {'EXIT',Reason} ->
- exit(Reason);
- {asn1_error,R} ->
-% [H|T] = Tokens,
- throw({error,{R,hd(Tokens)}});
- {Assignment,Rest} ->
- parse_AssignmentList(Rest,[Assignment|Acc])
- end.
-
-parse_Assignment(Tokens) ->
- Flist = [fun parse_TypeAssignment/1,
- fun parse_ValueAssignment/1,
- fun parse_ObjectClassAssignment/1,
- fun parse_ObjectAssignment/1,
- fun parse_ObjectSetAssignment/1,
- fun parse_ParameterizedAssignment/1,
- fun parse_ValueSetTypeAssignment/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- {asn1_assignment_error,Reason} ->
- throw({asn1_error,Reason});
- Result ->
- Result
- end.
-
-
-parse_or(Tokens,Flist) ->
- parse_or(Tokens,Flist,[]).
-
-parse_or(_Tokens,[],ErrList) ->
- case ErrList of
- [] ->
- throw({asn1_error,{parse_or,ErrList}});
- L when list(L) ->
-%%% throw({asn1_error,{parse_or,hd(lists:reverse(ErrList))}});
- %% chose to throw 1) the error with the highest line no,
- %% 2) the last error which is not a asn1_assignment_error or
- %% 3) the last error.
- throw(prioritize_error(ErrList));
- Other ->
- throw({asn1_error,{parse_or,Other}})
- end;
-parse_or(Tokens,[Fun|Frest],ErrList) ->
- case (catch Fun(Tokens)) of
- Exit = {'EXIT',_Reason} ->
- parse_or(Tokens,Frest,[Exit|ErrList]);
- AsnErr = {asn1_error,_} ->
- parse_or(Tokens,Frest,[AsnErr|ErrList]);
- AsnAssErr = {asn1_assignment_error,_} ->
- parse_or(Tokens,Frest,[AsnAssErr|ErrList]);
- Result = {_,L} when list(L) ->
- Result;
-% Result ->
-% Result
- Error ->
- parse_or(Tokens,Frest,[Error|ErrList])
- end.
-
-parse_TypeAssignment([{typereference,L1,Tref},{'::=',_}|Rest]) ->
- {Type,Rest2} = parse_Type(Rest),
- {#typedef{pos=L1,name=Tref,typespec=Type},Rest2};
-parse_TypeAssignment([H1,H2|_Rest]) ->
- throw({asn1_assignment_error,{get_line(H1),get(asn1_module),
- [got,[get_token(H1),get_token(H2)], expected,
- typereference,'::=']}});
-parse_TypeAssignment([H|_T]) ->
- throw({asn1_assignment_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,
- typereference]}}).
-
-parse_Type(Tokens) ->
- {Tag,Rest3} = case Tokens of
- [Lbr= {'[',_}|Rest] ->
- parse_Tag([Lbr|Rest]);
- Rest-> {[],Rest}
- end,
- {Tag2,Rest4} = case Rest3 of
- [{'IMPLICIT',_}|Rest31] when record(Tag,tag)->
- {[Tag#tag{type='IMPLICIT'}],Rest31};
- [{'EXPLICIT',_}|Rest31] when record(Tag,tag)->
- {[Tag#tag{type='EXPLICIT'}],Rest31};
- Rest31 when record(Tag,tag) ->
- {[Tag#tag{type={default,get(tagdefault)}}],Rest31};
- Rest31 ->
- {Tag,Rest31}
- end,
- Flist = [fun parse_BuiltinType/1,fun parse_ReferencedType/1,fun parse_TypeWithConstraint/1],
- {Type,Rest5} = case (catch parse_or(Rest4,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_Reason} ->
- throw(AsnErr);
- Result ->
- Result
- end,
- case hd(Rest5) of
- {'(',_} ->
- {Constraints,Rest6} = parse_Constraints(Rest5),
- if record(Type,type) ->
- {Type#type{constraint=merge_constraints(Constraints),
- tag=Tag2},Rest6};
- true ->
- {#type{def=Type,constraint=merge_constraints(Constraints),
- tag=Tag2},Rest6}
- end;
- _ ->
- if record(Type,type) ->
- {Type#type{tag=Tag2},Rest5};
- true ->
- {#type{def=Type,tag=Tag2},Rest5}
- end
- end.
-
-parse_BuiltinType([{'BIT',_},{'STRING',_}|Rest]) ->
- case Rest of
- [{'{',_}|Rest2] ->
- {NamedNumberList,Rest3} = parse_NamedNumberList(Rest2),
- case Rest3 of
- [{'}',_}|Rest4] ->
- {#type{def={'BIT STRING',NamedNumberList}},Rest4};
- _ ->
- throw({asn1_error,{get_line(hd(Rest3)),get(asn1_module),
- [got,get_token(hd(Rest3)),expected,'}']}})
- end;
- _ ->
- {{'BIT STRING',[]},Rest}
- end;
-parse_BuiltinType([{'BOOLEAN',_}|Rest]) ->
- {#type{def='BOOLEAN'},Rest};
-%% CharacterStringType ::= RestrictedCharacterStringType |
-%% UnrestrictedCharacterStringType
-parse_BuiltinType([{restrictedcharacterstringtype,_,StringName}|Rest]) ->
- {#type{def=StringName},Rest};
-parse_BuiltinType([{'CHARACTER',_},{'STRING',_}|Rest]) ->
- {#type{def='CHARACTER STRING'},Rest};
-
-parse_BuiltinType([{'CHOICE',_},{'{',_}|Rest]) ->
- {AlternativeTypeLists,Rest2} = parse_AlternativeTypeLists(Rest),
- case Rest2 of
- [{'}',_}|Rest3] ->
- {#type{def={'CHOICE',AlternativeTypeLists}},Rest3};
- _ ->
- throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,'}']}})
- end;
-parse_BuiltinType([{'EMBEDDED',_},{'PDV',_}|Rest]) ->
- {#type{def='EMBEDDED PDV'},Rest};
-parse_BuiltinType([{'ENUMERATED',_},{'{',_}|Rest]) ->
- {Enumerations,Rest2} = parse_Enumerations(Rest),
- case Rest2 of
- [{'}',_}|Rest3] ->
- {#type{def={'ENUMERATED',Enumerations}},Rest3};
- _ ->
- throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,'}']}})
- end;
-parse_BuiltinType([{'EXTERNAL',_}|Rest]) ->
- {#type{def='EXTERNAL'},Rest};
-
-% InstanceOfType
-parse_BuiltinType([{'INSTANCE',_},{'OF',_}|Rest]) ->
- {DefinedObjectClass,Rest2} = parse_DefinedObjectClass(Rest),
- case Rest2 of
- [{'(',_}|_] ->
- {Constraint,Rest3} = parse_Constraint(Rest2),
- {#type{def={'INSTANCE OF',DefinedObjectClass,Constraint}},Rest3};
- _ ->
- {#type{def={'INSTANCE OF',DefinedObjectClass,[]}},Rest2}
- end;
-
-% parse_BuiltinType(Tokens) ->
-
-parse_BuiltinType([{'INTEGER',_}|Rest]) ->
- case Rest of
- [{'{',_}|Rest2] ->
- {NamedNumberList,Rest3} = parse_NamedNumberList(Rest2),
- case Rest3 of
- [{'}',_}|Rest4] ->
- {#type{def={'INTEGER',NamedNumberList}},Rest4};
- _ ->
- throw({asn1_error,{get_line(hd(Rest3)),get(asn1_module),
- [got,get_token(hd(Rest3)),expected,'}']}})
- end;
- _ ->
- {#type{def='INTEGER'},Rest}
- end;
-parse_BuiltinType([{'NULL',_}|Rest]) ->
- {#type{def='NULL'},Rest};
-
-% ObjectClassFieldType fix me later
-
-parse_BuiltinType([{'OBJECT',_},{'IDENTIFIER',_}|Rest]) ->
- {#type{def='OBJECT IDENTIFIER'},Rest};
-parse_BuiltinType([{'OCTET',_},{'STRING',_}|Rest]) ->
- {#type{def='OCTET STRING'},Rest};
-parse_BuiltinType([{'REAL',_}|Rest]) ->
- {#type{def='REAL'},Rest};
-parse_BuiltinType([{'SEQUENCE',_},{'{',_},{'...',Line},{'}',_}|Rest]) ->
- {#type{def=#'SEQUENCE'{components=[{'EXTENSIONMARK',Line,undefined}]}},
- Rest};
-parse_BuiltinType([{'SEQUENCE',_},{'{',_},{'...',Line},{'!',_}|Rest]) ->
- {ExceptionIdentification,Rest2} = parse_ExceptionIdentification(Rest),
- case Rest2 of
- [{'}',_}|Rest3] ->
- {#type{def=#'SEQUENCE'{components=[{'EXTENSIONMARK',
- Line,
- ExceptionIdentification}]}},
- Rest3};
- _ ->
- throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,'}']}})
- end;
-parse_BuiltinType([{'SEQUENCE',_},{'{',_}|Rest]) ->
- {ComponentTypeLists,Rest2} = parse_ComponentTypeLists(Rest),
- case Rest2 of
- [{'}',_}|Rest3] ->
- {#type{def=#'SEQUENCE'{components=ComponentTypeLists}},Rest3};
- _ ->
- throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,'}']}})
- end;
-parse_BuiltinType([{'SEQUENCE',_},{'OF',_}|Rest]) ->
- {Type,Rest2} = parse_Type(Rest),
- {#type{def={'SEQUENCE OF',Type}},Rest2};
-
-
-parse_BuiltinType([{'SET',_},{'{',_},{'...',Line},{'}',_}|Rest]) ->
- {#type{def=#'SET'{components=[{'EXTENSIONMARK',Line,undefined}]}},Rest};
-parse_BuiltinType([{'SET',_},{'{',_},{'...',Line},{'!',_}|Rest]) ->
- {ExceptionIdentification,Rest2} = parse_ExceptionIdentification(Rest),
- case Rest2 of
- [{'}',_}|Rest3] ->
- {#type{def=#'SET'{components=
- [{'EXTENSIONMARK',Line,ExceptionIdentification}]}},
- Rest3};
- _ ->
- throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,'}']}})
- end;
-parse_BuiltinType([{'SET',_},{'{',_}|Rest]) ->
- {ComponentTypeLists,Rest2} = parse_ComponentTypeLists(Rest),
- case Rest2 of
- [{'}',_}|Rest3] ->
- {#type{def=#'SET'{components=ComponentTypeLists}},Rest3};
- _ ->
- throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,'}']}})
- end;
-parse_BuiltinType([{'SET',_},{'OF',_}|Rest]) ->
- {Type,Rest2} = parse_Type(Rest),
- {#type{def={'SET OF',Type}},Rest2};
-
-%% The so called Useful types
-parse_BuiltinType([{'GeneralizedTime',_}|Rest]) ->
- {#type{def='GeneralizedTime'},Rest};
-parse_BuiltinType([{'UTCTime',_}|Rest]) ->
- {#type{def='UTCTime'},Rest};
-parse_BuiltinType([{'ObjectDescriptor',_}|Rest]) ->
- {#type{def='ObjectDescriptor'},Rest};
-
-%% For compatibility with old standard
-parse_BuiltinType([{'ANY',_},{'DEFINED',_},{'BY',_},{identifier,_,Id}|Rest]) ->
- {#type{def={'ANY_DEFINED_BY',Id}},Rest};
-parse_BuiltinType([{'ANY',_}|Rest]) ->
- {#type{def='ANY'},Rest};
-
-parse_BuiltinType(Tokens) ->
- parse_ObjectClassFieldType(Tokens).
-% throw({asn1_error,unhandled_type}).
-
-
-parse_TypeWithConstraint([{'SEQUENCE',_},Lpar = {'(',_}|Rest]) ->
- {Constraint,Rest2} = parse_Constraint([Lpar|Rest]),
- case Rest2 of
- [{'OF',_}|Rest3] ->
- {Type,Rest4} = parse_Type(Rest3),
- {#type{def = {'SEQUENCE OF',Type}, constraint = merge_constraints([Constraint])},Rest4};
- _ ->
- throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,'OF']}})
- end;
-parse_TypeWithConstraint([{'SEQUENCE',_},{'SIZE',_},Lpar = {'(',_}|Rest]) ->
- {Constraint,Rest2} = parse_Constraint([Lpar|Rest]),
- Constraint2 =
- case Constraint of
- #constraint{c=C} ->
- Constraint#constraint{c={'SizeConstraint',C}};
- _ -> Constraint
- end,
- case Rest2 of
- [{'OF',_}|Rest3] ->
- {Type,Rest4} = parse_Type(Rest3),
- {#type{def = {'SEQUENCE OF',Type}, constraint = merge_constraints([Constraint2])},Rest4};
- _ ->
- throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,'OF']}})
- end;
-parse_TypeWithConstraint([{'SET',_},Lpar = {'(',_}|Rest]) ->
- {Constraint,Rest2} = parse_Constraint([Lpar|Rest]),
- case Rest2 of
- [{'OF',_}|Rest3] ->
- {Type,Rest4} = parse_Type(Rest3),
- {#type{def = {'SET OF',Type}, constraint = merge_constraints([Constraint])},Rest4};
- _ ->
- throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,'OF']}})
- end;
-parse_TypeWithConstraint([{'SET',_},{'SIZE',_},Lpar = {'(',_}|Rest]) ->
- {Constraint,Rest2} = parse_Constraint([Lpar|Rest]),
- Constraint2 =
- case Constraint of
- #constraint{c=C} ->
- Constraint#constraint{c={'SizeConstraint',C}};
- _ -> Constraint
- end,
- case Rest2 of
- [{'OF',_}|Rest3] ->
- {Type,Rest4} = parse_Type(Rest3),
- {#type{def = {'SET OF',Type}, constraint = merge_constraints([Constraint2])},Rest4};
- _ ->
- throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,'OF']}})
- end;
-parse_TypeWithConstraint(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- ['SEQUENCE','SEQUENCE SIZE','SET','SET SIZE'],
- followed,by,a,constraint]}}).
-
-
-%% --------------------------
-
-parse_ReferencedType(Tokens) ->
- Flist = [fun parse_DefinedType/1,
- fun parse_SelectionType/1,
- fun parse_TypeFromObject/1,
- fun parse_ValueSetFromObjects/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- Result ->
- Result
- end.
-
-parse_DefinedType(Tokens=[{typereference,_,_},{'{',_}|_Rest]) ->
- parse_ParameterizedType(Tokens);
-parse_DefinedType(Tokens=[{typereference,L1,TypeName},
- T2={typereference,_,_},T3={'{',_}|Rest]) ->
- case (catch parse_ParameterizedType(Tokens)) of
- {'EXIT',_Reason} ->
- Rest2 = [T2,T3|Rest],
- {#type{def = #'Externaltypereference'{pos=L1,
- module=get(asn1_module),
- type=TypeName}},Rest2};
- {asn1_error,_} ->
- Rest2 = [T2,T3|Rest],
- {#type{def = #'Externaltypereference'{pos=L1,
- module=get(asn1_module),
- type=TypeName}},Rest2};
- Result ->
- Result
- end;
-parse_DefinedType([{typereference,L1,Module},{'.',_},{typereference,_,TypeName}|Rest]) ->
- {#type{def = #'Externaltypereference'{pos=L1,module=Module,type=TypeName}},Rest};
-parse_DefinedType([{typereference,L1,TypeName}|Rest]) ->
- {#type{def = #'Externaltypereference'{pos=L1,module=get(asn1_module),
- type=TypeName}},Rest};
-parse_DefinedType(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- [typereference,'typereference.typereference',
- 'typereference typereference']]}}).
-
-parse_SelectionType([{identifier,_,Name},{'<',_}|Rest]) ->
- {Type,Rest2} = parse_Type(Rest),
- {{'SelectionType',Name,Type},Rest2};
-parse_SelectionType(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,'identifier <']}}).
-
-
-%% --------------------------
-
-
-%% This should probably be removed very soon
-% parse_ConstrainedType(Tokens) ->
-% case (catch parse_TypeWithConstraint(Tokens)) of
-% {'EXIT',Reason} ->
-% {Type,Rest} = parse_Type(Tokens),
-% {Constraint,Rest2} = parse_Constraint(Rest),
-% {Type#type{constraint=Constraint},Rest2};
-% {asn1_error,Reason2} ->
-% {Type,Rest} = parse_Type(Tokens),
-% {Constraint,Rest2} = parse_Constraint(Rest),
-% {Type#type{constraint=Constraint},Rest2};
-% Result ->
-% Result
-% end.
-
-parse_Constraints(Tokens) ->
- parse_Constraints(Tokens,[]).
-
-parse_Constraints(Tokens,Acc) ->
- {Constraint,Rest} = parse_Constraint(Tokens),
- case Rest of
- [{'(',_}|_Rest2] ->
- parse_Constraints(Rest,[Constraint|Acc]);
- _ ->
- {lists:reverse([Constraint|Acc]),Rest}
- end.
-
-parse_Constraint([{'(',_}|Rest]) ->
- {Constraint,Rest2} = parse_ConstraintSpec(Rest),
- {Exception,Rest3} = parse_ExceptionSpec(Rest2),
- case Rest3 of
- [{')',_}|Rest4] ->
- {#constraint{c=Constraint,e=Exception},Rest4};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,')']}})
- end;
-parse_Constraint(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,'(']}}).
-
-parse_ConstraintSpec(Tokens) ->
- Flist = [fun parse_GeneralConstraint/1,
- fun parse_SubtypeConstraint/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- {asn1_error,Reason2} ->
- throw({asn1_error,Reason2});
- Result ->
- Result
- end.
-
-parse_ExceptionSpec([LPar={')',_}|Rest]) ->
- {undefined,[LPar|Rest]};
-parse_ExceptionSpec([{'!',_}|Rest]) ->
- parse_ExceptionIdentification(Rest);
-parse_ExceptionSpec(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,[')','!']]}}).
-
-parse_ExceptionIdentification(Tokens) ->
- Flist = [fun parse_SignedNumber/1,
- fun parse_DefinedValue/1,
- fun parse_TypeColonValue/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- {asn1_error,Reason2} ->
- throw({asn1_error,Reason2});
- Result ->
- Result
- end.
-
-parse_TypeColonValue(Tokens) ->
- {Type,Rest} = parse_Type(Tokens),
- case Rest of
- [{':',_}|Rest2] ->
- {Value,Rest3} = parse_Value(Rest2),
- {{Type,Value},Rest3};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,':']}})
- end.
-
-parse_SubtypeConstraint(Tokens) ->
- parse_ElementSetSpecs(Tokens).
-
-parse_ElementSetSpecs([{'...',_}|Rest]) ->
- {Elements,Rest2} = parse_ElementSetSpec(Rest),
- {{[],Elements},Rest2};
-parse_ElementSetSpecs(Tokens) ->
- {RootElems,Rest} = parse_ElementSetSpec(Tokens),
- case Rest of
- [{',',_},{'...',_},{',',_}|Rest2] ->
- {AdditionalElems,Rest3} = parse_ElementSetSpec(Rest2),
- {{RootElems,AdditionalElems},Rest3};
- [{',',_},{'...',_}|Rest2] ->
- {{RootElems,[]},Rest2};
- _ ->
- {RootElems,Rest}
- end.
-
-parse_ElementSetSpec([{'ALL',_},{'EXCEPT',_}|Rest]) ->
- {Exclusions,Rest2} = parse_Elements(Rest),
- {{'ALL',{'EXCEPT',Exclusions}},Rest2};
-parse_ElementSetSpec(Tokens) ->
- parse_Unions(Tokens).
-
-
-parse_Unions(Tokens) ->
- {InterSec,Rest} = parse_Intersections(Tokens),
- {Unions,Rest2} = parse_UnionsRec(Rest),
- case {InterSec,Unions} of
- {InterSec,[]} ->
- {InterSec,Rest2};
- {{'SingleValue',V1},{'SingleValue',V2}} ->
- {{'SingleValue',ordsets:union(to_set(V1),to_set(V2))},Rest2};
- {V1,V2} when list(V2) ->
- {[V1] ++ [union|V2],Rest2};
- {V1,V2} ->
- {[V1,union,V2],Rest2}
-% Other ->
-% throw(Other)
- end.
-
-parse_UnionsRec([{'|',_}|Rest]) ->
- {InterSec,Rest2} = parse_Intersections(Rest),
- {URec,Rest3} = parse_UnionsRec(Rest2),
- case {InterSec,URec} of
- {V1,[]} ->
- {V1,Rest3};
- {{'SingleValue',V1},{'SingleValue',V2}} ->
- {{'SingleValue',ordsets:union(to_set(V1),to_set(V2))},Rest3};
- {V1,V2} when list(V2) ->
- {[V1] ++ V2,Rest3};
- {V1,V2} ->
- {[V1,V2],Rest3}
- end;
-parse_UnionsRec([{'UNION',_}|Rest]) ->
- {InterSec,Rest2} = parse_Intersections(Rest),
- {URec,Rest3} = parse_UnionsRec(Rest2),
- case {InterSec,URec} of
- {V1,[]} ->
- {V1,Rest3};
- {{'SingleValue',V1},{'SingleValue',V2}} ->
- {{'SingleValue',ordsets:union(to_set(V1),to_set(V2))},Rest3};
- {V1,V2} when list(V2) ->
- {[V1] ++ V2,Rest3};
- {V1,V2} ->
- {[V1,V2],Rest3}
- end;
-parse_UnionsRec(Tokens) ->
- {[],Tokens}.
-
-parse_Intersections(Tokens) ->
- {InterSec,Rest} = parse_IntersectionElements(Tokens),
- {IRec,Rest2} = parse_IElemsRec(Rest),
- case {InterSec,IRec} of
- {V1,[]} ->
- {V1,Rest2};
- {{'SingleValue',V1},{'SingleValue',V2}} ->
- {{'SingleValue',
- ordsets:intersection(to_set(V1),to_set(V2))},Rest2};
- {V1,V2} when list(V2) ->
- {[V1] ++ [intersection|V2],Rest2};
- {V1,V2} ->
- {[V1,intersection,V2],Rest2};
- _ ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,'a Union']}})
- end.
-
-parse_IElemsRec([{'^',_}|Rest]) ->
- {InterSec,Rest2} = parse_IntersectionElements(Rest),
- {IRec,Rest3} = parse_IElemsRec(Rest2),
- case {InterSec,IRec} of
- {{'SingleValue',V1},{'SingleValue',V2}} ->
- {{'SingleValue',
- ordsets:intersection(to_set(V1),to_set(V2))},Rest3};
- {V1,[]} ->
- {V1,Rest3};
- {V1,V2} when list(V2) ->
- {[V1] ++ V2,Rest3};
- {V1,V2} ->
- {[V1,V2],Rest3};
- _ ->
- throw({asn1_error,{get_line(hd(Rest)),get(asn1_module),
- [got,get_token(hd(Rest)),expected,'an Intersection']}})
- end;
-parse_IElemsRec([{'INTERSECTION',_}|Rest]) ->
- {InterSec,Rest2} = parse_IntersectionElements(Rest),
- {IRec,Rest3} = parse_IElemsRec(Rest2),
- case {InterSec,IRec} of
- {{'SingleValue',V1},{'SingleValue',V2}} ->
- {{'SingleValue',
- ordsets:intersection(to_set(V1),to_set(V2))},Rest3};
- {V1,[]} ->
- {V1,Rest3};
- {V1,V2} when list(V2) ->
- {[V1] ++ V2,Rest3};
- {V1,V2} ->
- {[V1,V2],Rest3};
- _ ->
- throw({asn1_error,{get_line(hd(Rest)),get(asn1_module),
- [got,get_token(hd(Rest)),expected,'an Intersection']}})
- end;
-parse_IElemsRec(Tokens) ->
- {[],Tokens}.
-
-parse_IntersectionElements(Tokens) ->
- {InterSec,Rest} = parse_Elements(Tokens),
- case Rest of
- [{'EXCEPT',_}|Rest2] ->
- {Exclusion,Rest3} = parse_Elements(Rest2),
- {{InterSec,{'EXCEPT',Exclusion}},Rest3};
- Rest ->
- {InterSec,Rest}
- end.
-
-parse_Elements([{'(',_}|Rest]) ->
- {Elems,Rest2} = parse_ElementSetSpec(Rest),
- case Rest2 of
- [{')',_}|Rest3] ->
- {Elems,Rest3};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,')']}})
- end;
-parse_Elements(Tokens) ->
- Flist = [fun parse_SubtypeElements/1,
- fun parse_ObjectSetElements/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- Err = {asn1_error,_} ->
- throw(Err);
- Result ->
- Result
- end.
-
-
-
-
-%% --------------------------
-
-parse_DefinedObjectClass([{typereference,_,_ModName},{'.',_},Tr={typereference,_,_ObjClName}|Rest]) ->
-%% {{objectclassname,ModName,ObjClName},Rest};
-% {{objectclassname,tref2Exttref(Tr)},Rest};
- {tref2Exttref(Tr),Rest};
-parse_DefinedObjectClass([Tr={typereference,_,_ObjClName}|Rest]) ->
-% {{objectclassname,tref2Exttref(Tr)},Rest};
- {tref2Exttref(Tr),Rest};
-parse_DefinedObjectClass([{'TYPE-IDENTIFIER',_}|Rest]) ->
- {'TYPE-IDENTIFIER',Rest};
-parse_DefinedObjectClass([{'ABSTRACT-SYNTAX',_}|Rest]) ->
- {'ABSTRACT-SYNTAX',Rest};
-parse_DefinedObjectClass(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- ['typereference . typereference',
- typereference,
- 'TYPE-IDENTIFIER',
- 'ABSTRACT-SYNTAX']]}}).
-
-parse_ObjectClassAssignment([{typereference,L1,ObjClName},{'::=',_}|Rest]) ->
- {Type,Rest2} = parse_ObjectClass(Rest),
- {#classdef{pos=L1,name=ObjClName,typespec=Type},Rest2};
-parse_ObjectClassAssignment(Tokens) ->
- throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- 'typereference ::=']}}).
-
-parse_ObjectClass(Tokens) ->
- Flist = [fun parse_DefinedObjectClass/1,
- fun parse_ObjectClassDefn/1,
- fun parse_ParameterizedObjectClass/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- {asn1_error,Reason2} ->
- throw({asn1_error,Reason2});
- Result ->
- Result
- end.
-
-parse_ObjectClassDefn([{'CLASS',_},{'{',_}|Rest]) ->
- {Type,Rest2} = parse_FieldSpec(Rest),
- {WithSyntaxSpec,Rest3} = parse_WithSyntaxSpec(Rest2),
- {#objectclass{fields=Type,syntax=WithSyntaxSpec},Rest3};
-parse_ObjectClassDefn(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,'CLASS {']}}).
-
-parse_FieldSpec(Tokens) ->
- parse_FieldSpec(Tokens,[]).
-
-parse_FieldSpec(Tokens,Acc) ->
- Flist = [fun parse_FixedTypeValueFieldSpec/1,
- fun parse_VariableTypeValueFieldSpec/1,
- fun parse_ObjectFieldSpec/1,
- fun parse_FixedTypeValueSetFieldSpec/1,
- fun parse_VariableTypeValueSetFieldSpec/1,
- fun parse_TypeFieldSpec/1,
- fun parse_ObjectSetFieldSpec/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- {Type,[{'}',_}|Rest]} ->
- {lists:reverse([Type|Acc]),Rest};
- {Type,[{',',_}|Rest2]} ->
- parse_FieldSpec(Rest2,[Type|Acc]);
- {_,[H|_T]} ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,'}']}})
- end.
-
-parse_PrimitiveFieldName([{typefieldreference,_,FieldName}|Rest]) ->
- {{typefieldreference,FieldName},Rest};
-parse_PrimitiveFieldName([{valuefieldreference,_,FieldName}|Rest]) ->
- {{valuefieldreference,FieldName},Rest};
-parse_PrimitiveFieldName(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- [typefieldreference,valuefieldreference]]}}).
-
-parse_FieldName(Tokens) ->
- {Field,Rest} = parse_PrimitiveFieldName(Tokens),
- parse_FieldName(Rest,[Field]).
-
-parse_FieldName([{'.',_}|Rest],Acc) ->
- case (catch parse_PrimitiveFieldName(Rest)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- {FieldName,Rest2} ->
- parse_FieldName(Rest2,[FieldName|Acc])
- end;
-parse_FieldName(Tokens,Acc) ->
- {lists:reverse(Acc),Tokens}.
-
-parse_FixedTypeValueFieldSpec([{valuefieldreference,L1,VFieldName}|Rest]) ->
- {Type,Rest2} = parse_Type(Rest),
- {Unique,Rest3} =
- case Rest2 of
- [{'UNIQUE',_}|Rest4] ->
- {'UNIQUE',Rest4};
- _ ->
- {undefined,Rest2}
- end,
- {OptionalitySpec,Rest5} = parse_ValueOptionalitySpec(Rest3),
- case Unique of
- 'UNIQUE' ->
- case OptionalitySpec of
- {'DEFAULT',_} ->
- throw({asn1_error,
- {L1,get(asn1_module),
- ['UNIQUE and DEFAULT in same field',VFieldName]}});
- _ ->
- {{fixedtypevaluefield,VFieldName,Type,Unique,OptionalitySpec},Rest5}
- end;
- _ ->
- {{object_or_fixedtypevalue_field,VFieldName,Type,Unique,OptionalitySpec},Rest5}
- end;
-parse_FixedTypeValueFieldSpec(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,valuefieldreference]}}).
-
-parse_VariableTypeValueFieldSpec([{valuefieldreference,_,VFieldName}|Rest]) ->
- {FieldRef,Rest2} = parse_FieldName(Rest),
- {OptionalitySpec,Rest3} = parse_ValueOptionalitySpec(Rest2),
- {{variabletypevaluefield,VFieldName,FieldRef,OptionalitySpec},Rest3};
-parse_VariableTypeValueFieldSpec(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,valuefieldreference]}}).
-
-parse_ObjectFieldSpec([{valuefieldreference,_,VFieldName}|Rest]) ->
- {Class,Rest2} = parse_DefinedObjectClass(Rest),
- {OptionalitySpec,Rest3} = parse_ObjectOptionalitySpec(Rest2),
- {{objectfield,VFieldName,Class,OptionalitySpec},Rest3};
-parse_ObjectFieldSpec(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,valuefieldreference]}}).
-
-parse_TypeFieldSpec([{typefieldreference,_,TFieldName}|Rest]) ->
- {OptionalitySpec,Rest2} = parse_TypeOptionalitySpec(Rest),
- {{typefield,TFieldName,OptionalitySpec},Rest2};
-parse_TypeFieldSpec(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,typefieldreference]}}).
-
-parse_FixedTypeValueSetFieldSpec([{typefieldreference,_,TFieldName}|Rest]) ->
- {Type,Rest2} = parse_Type(Rest),
- {OptionalitySpec,Rest3} = parse_ValueSetOptionalitySpec(Rest2),
- {{objectset_or_fixedtypevalueset_field,TFieldName,Type,
- OptionalitySpec},Rest3};
-parse_FixedTypeValueSetFieldSpec(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,typefieldreference]}}).
-
-parse_VariableTypeValueSetFieldSpec([{typefieldreference,_,TFieldName}|Rest]) ->
- {FieldRef,Rest2} = parse_FieldName(Rest),
- {OptionalitySpec,Rest3} = parse_ValueSetOptionalitySpec(Rest2),
- {{variabletypevaluesetfield,TFieldName,FieldRef,OptionalitySpec},Rest3};
-parse_VariableTypeValueSetFieldSpec(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,typefieldreference]}}).
-
-parse_ObjectSetFieldSpec([{typefieldreference,_,TFieldName}|Rest]) ->
- {Class,Rest2} = parse_DefinedObjectClass(Rest),
- {OptionalitySpec,Rest3} = parse_ObjectSetOptionalitySpec(Rest2),
- {{objectsetfield,TFieldName,Class,OptionalitySpec},Rest3};
-parse_ObjectSetFieldSpec(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,typefieldreference]}}).
-
-parse_ValueOptionalitySpec(Tokens)->
- case Tokens of
- [{'OPTIONAL',_}|Rest] -> {'OPTIONAL',Rest};
- [{'DEFAULT',_}|Rest] ->
- {Value,Rest2} = parse_Value(Rest),
- {{'DEFAULT',Value},Rest2};
- _ -> {'MANDATORY',Tokens}
- end.
-
-parse_ObjectOptionalitySpec(Tokens) ->
- case Tokens of
- [{'OPTIONAL',_}|Rest] -> {'OPTIONAL',Rest};
- [{'DEFAULT',_}|Rest] ->
- {Object,Rest2} = parse_Object(Rest),
- {{'DEFAULT',Object},Rest2};
- _ -> {'MANDATORY',Tokens}
- end.
-
-parse_TypeOptionalitySpec(Tokens) ->
- case Tokens of
- [{'OPTIONAL',_}|Rest] -> {'OPTIONAL',Rest};
- [{'DEFAULT',_}|Rest] ->
- {Type,Rest2} = parse_Type(Rest),
- {{'DEFAULT',Type},Rest2};
- _ -> {'MANDATORY',Tokens}
- end.
-
-parse_ValueSetOptionalitySpec(Tokens) ->
- case Tokens of
- [{'OPTIONAL',_}|Rest] -> {'OPTIONAL',Rest};
- [{'DEFAULT',_}|Rest] ->
- {ValueSet,Rest2} = parse_ValueSet(Rest),
- {{'DEFAULT',ValueSet},Rest2};
- _ -> {'MANDATORY',Tokens}
- end.
-
-parse_ObjectSetOptionalitySpec(Tokens) ->
- case Tokens of
- [{'OPTIONAL',_}|Rest] -> {'OPTIONAL',Rest};
- [{'DEFAULT',_}|Rest] ->
- {ObjectSet,Rest2} = parse_ObjectSet(Rest),
- {{'DEFAULT',ObjectSet},Rest2};
- _ -> {'MANDATORY',Tokens}
- end.
-
-parse_WithSyntaxSpec([{'WITH',_},{'SYNTAX',_}|Rest]) ->
- {SyntaxList,Rest2} = parse_SyntaxList(Rest),
- {{'WITH SYNTAX',SyntaxList},Rest2};
-parse_WithSyntaxSpec(Tokens) ->
- {[],Tokens}.
-
-parse_SyntaxList([{'{',_},{'}',_}|Rest]) ->
- {[],Rest};
-parse_SyntaxList([{'{',_}|Rest]) ->
- parse_SyntaxList(Rest,[]);
-parse_SyntaxList(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,['{}','{']]}}).
-
-parse_SyntaxList(Tokens,Acc) ->
- {SyntaxList,Rest} = parse_TokenOrGroupSpec(Tokens),
- case Rest of
- [{'}',_}|Rest2] ->
- {lists:reverse([SyntaxList|Acc]),Rest2};
- _ ->
- parse_SyntaxList(Rest,[SyntaxList|Acc])
- end.
-
-parse_TokenOrGroupSpec(Tokens) ->
- Flist = [fun parse_RequiredToken/1,
- fun parse_OptionalGroup/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- Result ->
- Result
- end.
-
-parse_RequiredToken([{typereference,L1,WordName}|Rest]) ->
- case is_word(WordName) of
- false ->
- throw({asn1_error,{L1,get(asn1_module),
- [got,WordName,expected,a,'Word']}});
- true ->
- {WordName,Rest}
- end;
-parse_RequiredToken([{',',L1}|Rest]) ->
- {{',',L1},Rest};
-parse_RequiredToken([{WordName,L1}|Rest]) ->
- case is_word(WordName) of
- false ->
- throw({asn1_error,{L1,get(asn1_module),
- [got,WordName,expected,a,'Word']}});
- true ->
- {WordName,Rest}
- end;
-parse_RequiredToken(Tokens) ->
- parse_PrimitiveFieldName(Tokens).
-
-parse_OptionalGroup([{'[',_}|Rest]) ->
- {Spec,Rest2} = parse_TokenOrGroupSpec(Rest),
- {SpecList,Rest3} = parse_OptionalGroup(Rest2,[Spec]),
- {SpecList,Rest3}.
-
-parse_OptionalGroup([{']',_}|Rest],Acc) ->
- {lists:reverse(Acc),Rest};
-parse_OptionalGroup(Tokens,Acc) ->
- {Spec,Rest} = parse_TokenOrGroupSpec(Tokens),
- parse_OptionalGroup(Rest,[Spec|Acc]).
-
-parse_DefinedObject([Id={identifier,_,_ObjName}|Rest]) ->
- {{object,identifier2Extvalueref(Id)},Rest};
-parse_DefinedObject([{typereference,L1,ModName},{'.',_},{identifier,_,ObjName}|Rest]) ->
- {{object, #'Externaltypereference'{pos=L1,module=ModName,type=ObjName}},Rest};
-parse_DefinedObject(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- [identifier,'typereference.identifier']]}}).
-
-parse_ObjectAssignment([{identifier,L1,ObjName}|Rest]) ->
- {Class,Rest2} = parse_DefinedObjectClass(Rest),
- case Rest2 of
- [{'::=',_}|Rest3] ->
- {Object,Rest4} = parse_Object(Rest3),
- {#typedef{pos=L1,name=ObjName,
- typespec=#'Object'{classname=Class,def=Object}},Rest4};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,'::=']}});
- Other ->
- throw({asn1_error,{L1,get(asn1_module),
- [got,Other,expected,'::=']}})
- end;
-parse_ObjectAssignment(Tokens) ->
- throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,identifier]}}).
-
-parse_Object(Tokens) ->
- Flist=[fun parse_ObjectDefn/1,
- fun parse_ObjectFromObject/1,
- fun parse_ParameterizedObject/1,
- fun parse_DefinedObject/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- Result ->
- Result
- end.
-
-parse_ObjectDefn(Tokens) ->
- Flist=[fun parse_DefaultSyntax/1,
- fun parse_DefinedSyntax/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- Result ->
- Result
- end.
-
-parse_DefaultSyntax([{'{',_},{'}',_}|Rest]) ->
- {{object,defaultsyntax,[]},Rest};
-parse_DefaultSyntax([{'{',_}|Rest]) ->
- parse_DefaultSyntax(Rest,[]);
-parse_DefaultSyntax(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,['{}','{']]}}).
-
-parse_DefaultSyntax(Tokens,Acc) ->
- {Setting,Rest} = parse_FieldSetting(Tokens),
- case Rest of
- [{',',_}|Rest2] ->
- parse_DefaultSyntax(Rest2,[Setting|Acc]);
- [{'}',_}|Rest3] ->
- {{object,defaultsyntax,lists:reverse([Setting|Acc])},Rest3};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,[',','}']]}})
- end.
-
-parse_FieldSetting(Tokens) ->
- {{_,PrimFieldName},Rest} = parse_PrimitiveFieldName(Tokens),
- {Setting,Rest2} = parse_Setting(Rest),
- {{PrimFieldName,Setting},Rest2}.
-
-parse_DefinedSyntax([{'{',_}|Rest]) ->
- parse_DefinedSyntax(Rest,[]).
-
-parse_DefinedSyntax(Tokens,Acc) ->
- case Tokens of
- [{'}',_}|Rest2] ->
- {{object,definedsyntax,lists:reverse(Acc)},Rest2};
- _ ->
- {DefSynTok,Rest3} = parse_DefinedSyntaxToken(Tokens),
- parse_DefinedSyntax(Rest3,[DefSynTok|Acc])
- end.
-
-parse_DefinedSyntaxToken([{',',L1}|Rest]) ->
- {{',',L1},Rest};
-parse_DefinedSyntaxToken([{typereference,L1,Name}|Rest]) ->
- case is_word(Name) of
- false ->
- {{setting,L1,Name},Rest};
- true ->
- {{word_or_setting,L1,Name},Rest}
- end;
-parse_DefinedSyntaxToken(Tokens) ->
- case catch parse_Setting(Tokens) of
- {asn1_error,_} ->
- parse_Word(Tokens);
- {'EXIT',Reason} ->
- exit(Reason);
- Result ->
- Result
- end.
-
-parse_Word([{Name,Pos}|Rest]) ->
- case is_word(Name) of
- false ->
- throw({asn1_error,{Pos,get(asn1_module),
- [got,Name, expected,a,'Word']}});
- true ->
- {{word_or_setting,Pos,Name},Rest}
- end.
-
-parse_Setting(Tokens) ->
- Flist = [fun parse_Type/1,
- fun parse_Value/1,
- fun parse_Object/1,
- fun parse_ObjectSet/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- Result ->
- Result
- end.
-
-parse_DefinedObjectSet([{typereference,L1,ModuleName},{'.',_},
- {typereference,L2,ObjSetName}|Rest]) ->
- {{objectset,L1,#'Externaltypereference'{pos=L2,module=ModuleName,
- type=ObjSetName}},Rest};
-parse_DefinedObjectSet([{typereference,L1,ObjSetName}|Rest]) ->
- {{objectset,L1,#'Externaltypereference'{pos=L1,module=get(asn1_module),
- type=ObjSetName}},Rest};
-parse_DefinedObjectSet(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- [typereference,'typereference.typereference']]}}).
-
-parse_ObjectSetAssignment([{typereference,L1,ObjSetName}|Rest]) ->
- {Class,Rest2} = parse_DefinedObjectClass(Rest),
- case Rest2 of
- [{'::=',_}|Rest3] ->
- {ObjectSet,Rest4} = parse_ObjectSet(Rest3),
- {#typedef{pos=L1,name=ObjSetName,
- typespec=#'ObjectSet'{class=Class,
- set=ObjectSet}},Rest4};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,'::=']}})
-%%% Other ->
-%%% throw(Other)
- end;
-parse_ObjectSetAssignment(Tokens) ->
- throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- typereference]}}).
-
-parse_ObjectSet([{'{',_}|Rest]) ->
- {ObjSetSpec,Rest2} = parse_ObjectSetSpec(Rest),
- case Rest2 of
- [{'}',_}|Rest3] ->
- {ObjSetSpec,Rest3};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,'}']}})
- end;
-parse_ObjectSet(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,'{']}}).
-
-parse_ObjectSetSpec([{'...',_}|Rest]) ->
- {['EXTENSIONMARK'],Rest};
-parse_ObjectSetSpec(Tokens) ->
- parse_ElementSetSpecs(Tokens).
-
-parse_ObjectSetElements(Tokens) ->
- Flist = [fun parse_Object/1,
- fun parse_DefinedObjectSet/1,
- fun parse_ObjectSetFromObjects/1,
- fun parse_ParameterizedObjectSet/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- Result ->
- Result
- end.
-
-parse_ObjectClassFieldType(Tokens) ->
- {Class,Rest} = parse_DefinedObjectClass(Tokens),
- case Rest of
- [{'.',_}|Rest2] ->
- {FieldName,Rest3} = parse_FieldName(Rest2),
- OCFT = #'ObjectClassFieldType'{
- classname=Class,
- class=Class,fieldname=FieldName},
- {#type{def=OCFT},Rest3};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,'.']}})
-%%% Other ->
-%%% throw(Other)
- end.
-
-%parse_ObjectClassFieldValue(Tokens) ->
-% Flist = [fun parse_OpenTypeFieldVal/1,
-% fun parse_FixedTypeFieldVal/1],
-% case (catch parse_or(Tokens,Flist)) of
-% {'EXIT',Reason} ->
-% throw(Reason);
-% AsnErr = {asn1_error,_} ->
-% throw(AsnErr);
-% Result ->
-% Result
-% end.
-
-parse_ObjectClassFieldValue(Tokens) ->
- parse_OpenTypeFieldVal(Tokens).
-
-parse_OpenTypeFieldVal(Tokens) ->
- {Type,Rest} = parse_Type(Tokens),
- case Rest of
- [{':',_}|Rest2] ->
- {Value,Rest3} = parse_Value(Rest2),
- {{opentypefieldvalue,Type,Value},Rest3};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,':']}})
- end.
-
-% parse_FixedTypeFieldVal(Tokens) ->
-% parse_Value(Tokens).
-
-% parse_InformationFromObjects(Tokens) ->
-% Flist = [fun parse_ValueFromObject/1,
-% fun parse_ValueSetFromObjects/1,
-% fun parse_TypeFromObject/1,
-% fun parse_ObjectFromObject/1],
-% case (catch parse_or(Tokens,Flist)) of
-% {'EXIT',Reason} ->
-% throw(Reason);
-% AsnErr = {asn1_error,_} ->
-% throw(AsnErr);
-% Result ->
-% Result
-% end.
-
-parse_ReferencedObjects(Tokens) ->
- Flist = [fun parse_DefinedObject/1,
- fun parse_DefinedObjectSet/1,
- fun parse_ParameterizedObject/1,
- fun parse_ParameterizedObjectSet/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- Result ->
- Result
- end.
-
-parse_ValueFromObject(Tokens) ->
- {Objects,Rest} = parse_ReferencedObjects(Tokens),
- case Rest of
- [{'.',_}|Rest2] ->
- {Name,Rest3} = parse_FieldName(Rest2),
- case lists:last(Name) of
- {valuefieldreference,_} ->
- {{'ValueFromObject',Objects,Name},Rest3};
- _ ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,typefieldreference,expected,
- valuefieldreference]}})
- end;
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,'.']}})
-%%% Other ->
-%%% throw({asn1_error,{got,Other,expected,'.'}})
- end.
-
-parse_ValueSetFromObjects(Tokens) ->
- {Objects,Rest} = parse_ReferencedObjects(Tokens),
- case Rest of
- [{'.',_}|Rest2] ->
- {Name,Rest3} = parse_FieldName(Rest2),
- case lists:last(Name) of
- {typefieldreference,_FieldName} ->
- {{'ValueSetFromObjects',Objects,Name},Rest3};
- _ ->
- throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,
- typefieldreference]}})
- end;
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,'.']}})
-%%% Other ->
-%%% throw({asn1_error,{got,Other,expected,'.'}})
- end.
-
-parse_TypeFromObject(Tokens) ->
- {Objects,Rest} = parse_ReferencedObjects(Tokens),
- case Rest of
- [{'.',_}|Rest2] ->
- {Name,Rest3} = parse_FieldName(Rest2),
- case lists:last(Name) of
- {typefieldreference,_FieldName} ->
- {{'TypeFromObject',Objects,Name},Rest3};
- _ ->
- throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,
- typefieldreference]}})
- end;
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,'.']}})
-%%% Other ->
-%%% throw({asn1_error,{got,Other,expected,'.'}})
- end.
-
-parse_ObjectFromObject(Tokens) ->
- {Objects,Rest} = parse_ReferencedObjects(Tokens),
- case Rest of
- [{'.',_}|Rest2] ->
- {Name,Rest3} = parse_FieldName(Rest2),
- {{'ObjectFromObject',Objects,Name},Rest3};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,'.']}})
-%%% Other ->
-%%% throw({asn1_error,{got,Other,expected,'.'}})
- end.
-
-parse_ObjectSetFromObjects(Tokens) ->
- {Objects,Rest} = parse_ReferencedObjects(Tokens),
- case Rest of
- [{'.',_}|Rest2] ->
- {Name,Rest3} = parse_FieldName(Rest2),
- {{'ObjectSetFromObjects',Objects,Name},Rest3};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,'.']}})
-%%% Other ->
-%%% throw({asn1_error,{got,Other,expected,'.'}})
- end.
-
-% parse_InstanceOfType([{'INSTANCE',_},{'OF',_}|Rest]) ->
-% {Class,Rest2} = parse_DefinedObjectClass(Rest),
-% {{'InstanceOfType',Class},Rest2}.
-
-% parse_InstanceOfValue(Tokens) ->
-% parse_Value(Tokens).
-
-
-
-%% X.682 constraint specification
-
-parse_GeneralConstraint(Tokens) ->
- Flist = [fun parse_UserDefinedConstraint/1,
- fun parse_TableConstraint/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- Result ->
- Result
- end.
-
-parse_UserDefinedConstraint([{'CONSTRAINED',_},{'BY',_},{'{',_},{'}',_}|Rest])->
- {{constrained_by,[]},Rest};
-parse_UserDefinedConstraint([{'CONSTRAINED',_},
- {'BY',_},
- {'{',_}|Rest]) ->
- {Param,Rest2} = parse_UserDefinedConstraintParameter(Rest),
- case Rest2 of
- [{'}',_}|Rest3] ->
- {{constrained_by,Param},Rest3};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,'}']}})
- end;
-parse_UserDefinedConstraint(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- ['CONSTRAINED BY {}','CONSTRAINED BY {']]}}).
-
-parse_UserDefinedConstraintParameter(Tokens) ->
- parse_UserDefinedConstraintParameter(Tokens,[]).
-parse_UserDefinedConstraintParameter(Tokens,Acc) ->
- Flist = [fun parse_GovernorAndActualParameter/1,
- fun parse_ActualParameter/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- {Result,Rest} ->
- case Rest of
- [{',',_}|_Rest2] ->
- parse_UserDefinedConstraintParameter(Tokens,[Result|Acc]);
- _ ->
- {lists:reverse([Result|Acc]),Rest}
- end
- end.
-
-parse_GovernorAndActualParameter(Tokens) ->
- {Governor,Rest} = parse_Governor(Tokens),
- case Rest of
- [{':',_}|Rest2] ->
- {Params,Rest3} = parse_ActualParameter(Rest2),
- {{'Governor_Params',Governor,Params},Rest3};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,':']}})
- end.
-
-parse_TableConstraint(Tokens) ->
- Flist = [fun parse_ComponentRelationConstraint/1,
- fun parse_SimpleTableConstraint/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- Result ->
- Result
- end.
-
-parse_SimpleTableConstraint(Tokens) ->
- {ObjectSet,Rest} = parse_ObjectSet(Tokens),
- {{simpletable,ObjectSet},Rest}.
-
-parse_ComponentRelationConstraint([{'{',_}|Rest]) ->
- {ObjectSet,Rest2} = parse_DefinedObjectSet(Rest),
- case Rest2 of
- [{'}',_},{'{',_}|Rest3] ->
- {AtNot,Rest4} = parse_AtNotationList(Rest3,[]),
- case Rest4 of
- [{'}',_}|Rest5] ->
- {{componentrelation,ObjectSet,AtNot},Rest5};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,'}']}})
- end;
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,
- 'ComponentRelationConstraint',ended,with,'}']}})
-%%% Other ->
-%%% throw(Other)
- end;
-parse_ComponentRelationConstraint(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,'{']}}).
-
-parse_AtNotationList(Tokens,Acc) ->
- {AtNot,Rest} = parse_AtNotation(Tokens),
- case Rest of
- [{',',_}|Rest2] ->
- parse_AtNotationList(Rest2,[AtNot|Acc]);
- _ ->
- {lists:reverse([AtNot|Acc]),Rest}
- end.
-
-parse_AtNotation([{'@',_},{'.',_}|Rest]) ->
- {CIdList,Rest2} = parse_ComponentIdList(Rest),
- {{innermost,CIdList},Rest2};
-parse_AtNotation([{'@',_}|Rest]) ->
- {CIdList,Rest2} = parse_ComponentIdList(Rest),
- {{outermost,CIdList},Rest2};
-parse_AtNotation(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,['@','@.']]}}).
-
-parse_ComponentIdList(Tokens) ->
- parse_ComponentIdList(Tokens,[]).
-
-parse_ComponentIdList([Id = {identifier,_,_},{'.',_}|Rest],Acc) ->
- parse_ComponentIdList(Rest,[identifier2Extvalueref(Id)|Acc]);
-parse_ComponentIdList([Id = {identifier,_,_}|Rest],Acc) ->
- {lists:reverse([identifier2Extvalueref(Id)|Acc]),Rest};
-parse_ComponentIdList(Tokens,_) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- [identifier,'identifier.']]}}).
-
-
-
-
-
-% X.683 Parameterization of ASN.1 specifications
-
-parse_Governor(Tokens) ->
- Flist = [fun parse_Type/1,
- fun parse_DefinedObjectClass/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- Result ->
- Result
- end.
-
-parse_ActualParameter(Tokens) ->
- Flist = [fun parse_Type/1,
- fun parse_Value/1,
- fun parse_ValueSet/1,
- fun parse_DefinedObjectClass/1,
- fun parse_Object/1,
- fun parse_ObjectSet/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- Result ->
- Result
- end.
-
-parse_ParameterizedAssignment(Tokens) ->
- Flist = [fun parse_ParameterizedTypeAssignment/1,
- fun parse_ParameterizedValueAssignment/1,
- fun parse_ParameterizedValueSetTypeAssignment/1,
- fun parse_ParameterizedObjectClassAssignment/1,
- fun parse_ParameterizedObjectAssignment/1,
- fun parse_ParameterizedObjectSetAssignment/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- AsnAssErr = {asn1_assignment_error,_} ->
- throw(AsnAssErr);
- Result ->
- Result
- end.
-
-parse_ParameterizedTypeAssignment([{typereference,L1,Name}|Rest]) ->
- {ParameterList,Rest2} = parse_ParameterList(Rest),
- case Rest2 of
- [{'::=',_}|Rest3] ->
- {Type,Rest4} = parse_Type(Rest3),
- {#ptypedef{pos=L1,name=Name,args=ParameterList,typespec=Type},
- Rest4};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,'::=']}})
- end;
-parse_ParameterizedTypeAssignment(Tokens) ->
- throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- typereference]}}).
-
-parse_ParameterizedValueAssignment([{identifier,L1,Name}|Rest]) ->
- {ParameterList,Rest2} = parse_ParameterList(Rest),
- {Type,Rest3} = parse_Type(Rest2),
- case Rest3 of
- [{'::=',_}|Rest4] ->
- {Value,Rest5} = parse_Value(Rest4),
- {#pvaluedef{pos=L1,name=Name,args=ParameterList,type=Type,
- value=Value},Rest5};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,'::=']}})
- end;
-parse_ParameterizedValueAssignment(Tokens) ->
- throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,identifier]}}).
-
-parse_ParameterizedValueSetTypeAssignment([{typereference,L1,Name}|Rest]) ->
- {ParameterList,Rest2} = parse_ParameterList(Rest),
- {Type,Rest3} = parse_Type(Rest2),
- case Rest3 of
- [{'::=',_}|Rest4] ->
- {ValueSet,Rest5} = parse_ValueSet(Rest4),
- {#pvaluesetdef{pos=L1,name=Name,args=ParameterList,
- type=Type,valueset=ValueSet},Rest5};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,'::=']}})
- end;
-parse_ParameterizedValueSetTypeAssignment(Tokens) ->
- throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- typereference]}}).
-
-parse_ParameterizedObjectClassAssignment([{typereference,L1,Name}|Rest]) ->
- {ParameterList,Rest2} = parse_ParameterList(Rest),
- case Rest2 of
- [{'::=',_}|Rest3] ->
- {Class,Rest4} = parse_ObjectClass(Rest3),
- {#ptypedef{pos=L1,name=Name,args=ParameterList,typespec=Class},
- Rest4};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,'::=']}})
- end;
-parse_ParameterizedObjectClassAssignment(Tokens) ->
- throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- typereference]}}).
-
-parse_ParameterizedObjectAssignment([{identifier,L1,Name}|Rest]) ->
- {ParameterList,Rest2} = parse_ParameterList(Rest),
- {Class,Rest3} = parse_DefinedObjectClass(Rest2),
- case Rest3 of
- [{'::=',_}|Rest4] ->
- {Object,Rest5} = parse_Object(Rest4),
- {#pobjectdef{pos=L1,name=Name,args=ParameterList,
- class=Class,def=Object},Rest5};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,'::=']}})
-%%% Other ->
-%%% throw(Other)
- end;
-parse_ParameterizedObjectAssignment(Tokens) ->
- throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,identifier]}}).
-
-parse_ParameterizedObjectSetAssignment([{typereference,L1,Name}|Rest]) ->
- {ParameterList,Rest2} = parse_ParameterList(Rest),
- {Class,Rest3} = parse_DefinedObjectClass(Rest2),
- case Rest3 of
- [{'::=',_}|Rest4] ->
- {ObjectSet,Rest5} = parse_ObjectSet(Rest4),
- {#pobjectsetdef{pos=L1,name=Name,args=ParameterList,
- class=Class,def=ObjectSet},Rest5};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,'::=']}})
-%%% Other ->
-%%% throw(Other)
- end;
-parse_ParameterizedObjectSetAssignment(Tokens) ->
- throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- typereference]}}).
-
-parse_ParameterList([{'{',_}|Rest]) ->
- parse_ParameterList(Rest,[]);
-parse_ParameterList(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,'{']}}).
-
-parse_ParameterList(Tokens,Acc) ->
- {Parameter,Rest} = parse_Parameter(Tokens),
- case Rest of
- [{',',_}|Rest2] ->
- parse_ParameterList(Rest2,[Parameter|Acc]);
- [{'}',_}|Rest3] ->
- {lists:reverse([Parameter|Acc]),Rest3};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,[',','}']]}})
- end.
-
-parse_Parameter(Tokens) ->
- Flist = [fun parse_ParamGovAndRef/1,
- fun parse_Reference/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- Result ->
- Result
- end.
-
-parse_ParamGovAndRef(Tokens) ->
- {ParamGov,Rest} = parse_ParamGovernor(Tokens),
- case Rest of
- [{':',_}|Rest2] ->
- {Ref,Rest3} = parse_Reference(Rest2),
- {{ParamGov,Ref},Rest3};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,':']}})
- end.
-
-parse_ParamGovernor(Tokens) ->
- Flist = [fun parse_Governor/1,
- fun parse_Reference/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- Result ->
- Result
- end.
-
-% parse_ParameterizedReference(Tokens) ->
-% {Ref,Rest} = parse_Reference(Tokens),
-% case Rest of
-% [{'{',_},{'}',_}|Rest2] ->
-% {{ptref,Ref},Rest2};
-% _ ->
-% {{ptref,Ref},Rest}
-% end.
-
-parse_SimpleDefinedType([{typereference,L1,ModuleName},{'.',_},
- {typereference,_,TypeName}|Rest]) ->
- {#'Externaltypereference'{pos=L1,module=ModuleName,
- type=TypeName},Rest};
-parse_SimpleDefinedType([Tref={typereference,_,_}|Rest]) ->
-% {#'Externaltypereference'{pos=L2,module=get(asn1_module),
-% type=TypeName},Rest};
- {tref2Exttref(Tref),Rest};
-parse_SimpleDefinedType(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- [typereference,'typereference.typereference']]}}).
-
-parse_SimpleDefinedValue([{typereference,L1,ModuleName},{'.',_},
- {identifier,_,Value}|Rest]) ->
- {{simpledefinedvalue,#'Externalvaluereference'{pos=L1,module=ModuleName,
- value=Value}},Rest};
-parse_SimpleDefinedValue([{identifier,L2,Value}|Rest]) ->
- {{simpledefinedvalue,L2,Value},Rest};
-parse_SimpleDefinedValue(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- ['typereference.identifier',identifier]]}}).
-
-parse_ParameterizedType(Tokens) ->
- {Type,Rest} = parse_SimpleDefinedType(Tokens),
- {Params,Rest2} = parse_ActualParameterList(Rest),
- {{pt,Type,Params},Rest2}.
-
-parse_ParameterizedValue(Tokens) ->
- {Value,Rest} = parse_SimpleDefinedValue(Tokens),
- {Params,Rest2} = parse_ActualParameterList(Rest),
- {{pv,Value,Params},Rest2}.
-
-parse_ParameterizedObjectClass(Tokens) ->
- {Type,Rest} = parse_DefinedObjectClass(Tokens),
- {Params,Rest2} = parse_ActualParameterList(Rest),
- {{poc,Type,Params},Rest2}.
-
-parse_ParameterizedObjectSet(Tokens) ->
- {ObjectSet,Rest} = parse_DefinedObjectSet(Tokens),
- {Params,Rest2} = parse_ActualParameterList(Rest),
- {{pos,ObjectSet,Params},Rest2}.
-
-parse_ParameterizedObject(Tokens) ->
- {Object,Rest} = parse_DefinedObject(Tokens),
- {Params,Rest2} = parse_ActualParameterList(Rest),
- {{po,Object,Params},Rest2}.
-
-parse_ActualParameterList([{'{',_}|Rest]) ->
- parse_ActualParameterList(Rest,[]);
-parse_ActualParameterList(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,'{']}}).
-
-parse_ActualParameterList(Tokens,Acc) ->
- {Parameter,Rest} = parse_ActualParameter(Tokens),
- case Rest of
- [{',',_}|Rest2] ->
- parse_ActualParameterList(Rest2,[Parameter|Acc]);
- [{'}',_}|Rest3] ->
- {lists:reverse([Parameter|Acc]),Rest3};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,[',','}']]}})
-%%% Other ->
-%%% throw(Other)
- end.
-
-
-
-
-
-
-
-%-------------------------
-
-is_word(Token) ->
- case not_allowed_word(Token) of
- true -> false;
- _ ->
- if
- atom(Token) ->
- Item = atom_to_list(Token),
- is_word(Item);
- list(Token), length(Token) == 1 ->
- check_one_char_word(Token);
- list(Token) ->
- [A|Rest] = Token,
- case check_first(A) of
- true ->
- check_rest(Rest);
- _ ->
- false
- end
- end
- end.
-
-not_allowed_word(Name) ->
- lists:member(Name,["BIT",
- "BOOLEAN",
- "CHARACTER",
- "CHOICE",
- "EMBEDDED",
- "END",
- "ENUMERATED",
- "EXTERNAL",
- "FALSE",
- "INSTANCE",
- "INTEGER",
- "INTERSECTION",
- "MINUS-INFINITY",
- "NULL",
- "OBJECT",
- "OCTET",
- "PLUS-INFINITY",
- "REAL",
- "SEQUENCE",
- "SET",
- "TRUE",
- "UNION"]).
-
-check_one_char_word([A]) when $A =< A, $Z >= A ->
- true;
-check_one_char_word([_]) ->
- false. %% unknown item in SyntaxList
-
-check_first(A) when $A =< A, $Z >= A ->
- true;
-check_first(_) ->
- false. %% unknown item in SyntaxList
-
-check_rest([R,R|_Rs]) when $- == R ->
- false; %% two consecutive hyphens are not allowed in a word
-check_rest([R]) when $- == R ->
- false; %% word cannot end with hyphen
-check_rest([R|Rs]) when $A=<R, $Z>=R; $-==R ->
- check_rest(Rs);
-check_rest([]) ->
- true;
-check_rest(_) ->
- false.
-
-
-to_set(V) when list(V) ->
- ordsets:list_to_set(V);
-to_set(V) ->
- ordsets:list_to_set([V]).
-
-
-parse_AlternativeTypeLists(Tokens) ->
- {AlternativeTypeList,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,
- case ExtensionAndException of
- [] ->
- {AlternativeTypeList,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,
- {AlternativeTypeList ++ ExtensionAndException ++ ExtensionAddition ++ OptionalExtensionMarker, Rest4}
- end.
-
-
-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) ->
- parse_ExtensionAdditionAlternativeList(Tokens,[]).
-
-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_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),
- {#'ComponentType'{pos=L1,name=Idname,typespec=Type,prop=mandatory},Rest2};
-parse_NamedType(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,identifier]}}).
-
-
-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);
- _ ->
- {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,[])
- 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) ->
- 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_ComponentTypeList(Tokens) ->
- parse_ComponentTypeList(Tokens,[]).
-
-parse_ComponentTypeList(Tokens,Acc) ->
- {ComponentType,Rest} = parse_ComponentType(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};
- _ ->
- 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);
- _ ->
- 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]);
- _ ->
- {lists:reverse([Element|Acc]),Rest0}
- 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([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),
- case Rest of
- [{'OPTIONAL',_}|Rest2] ->
- {NamedType#'ComponentType'{prop='OPTIONAL'},Rest2};
- [{'DEFAULT',_}|Rest2] ->
- {Value,Rest21} = parse_Value(Rest2),
- {NamedType#'ComponentType'{prop={'DEFAULT',Value}},Rest21};
- _ ->
- {NamedType,Rest}
- end.
-
-
-
-parse_SignedNumber([{number,_,Value}|Rest]) ->
- {Value,Rest};
-parse_SignedNumber([{'-',_},{number,_,Value}|Rest]) ->
- {-Value,Rest};
-parse_SignedNumber(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- [number,'-number']]}}).
-
-parse_Enumerations(Tokens=[{identifier,_,_}|_Rest]) ->
- parse_Enumerations(Tokens,[]);
-parse_Enumerations([H|_T]) ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,identifier]}}).
-
-parse_Enumerations(Tokens = [{identifier,_,_},{'(',_}|_Rest], Acc) ->
- {NamedNumber,Rest2} = parse_NamedNumber(Tokens),
- case Rest2 of
- [{',',_}|Rest3] ->
- parse_Enumerations(Rest3,[NamedNumber|Acc]);
- _ ->
- {lists:reverse([NamedNumber|Acc]),Rest2}
- end;
-parse_Enumerations([{identifier,_,Id}|Rest], Acc) ->
- case Rest of
- [{',',_}|Rest2] ->
- parse_Enumerations(Rest2,[Id|Acc]);
- _ ->
- {lists:reverse([Id|Acc]),Rest}
- end;
-parse_Enumerations([{'...',_}|Rest], Acc) ->
- case Rest of
- [{',',_}|Rest2] ->
- parse_Enumerations(Rest2,['EXTENSIONMARK'|Acc]);
- _ ->
- {lists:reverse(['EXTENSIONMARK'|Acc]),Rest}
- end;
-parse_Enumerations([H|_T],_) ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,identifier]}}).
-
-parse_NamedNumberList(Tokens) ->
- parse_NamedNumberList(Tokens,[]).
-
-parse_NamedNumberList(Tokens,Acc) ->
- {NamedNum,Rest} = parse_NamedNumber(Tokens),
- case Rest of
- [{',',_}|Rest2] ->
- parse_NamedNumberList(Rest2,[NamedNum|Acc]);
- _ ->
- {lists:reverse([NamedNum|Acc]),Rest}
- end.
-
-parse_NamedNumber([{identifier,_,Name},{'(',_}|Rest]) ->
- Flist = [fun parse_SignedNumber/1,
- fun parse_DefinedValue/1],
- case (catch parse_or(Rest,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- {NamedNum,[{')',_}|Rest2]} ->
- {{'NamedNumber',Name,NamedNum},Rest2};
- _ ->
- throw({asn1_error,{get_line(hd(Rest)),get(asn1_module),
- [got,get_token(hd(Rest)),expected,'NamedNumberList']}})
- end;
-parse_NamedNumber(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,identifier]}}).
-
-
-parse_Tag([{'[',_}|Rest]) ->
- {Class,Rest2} = parse_Class(Rest),
- {ClassNumber,Rest3} =
- case Rest2 of
- [{number,_,Num}|Rest21] ->
- {Num,Rest21};
- _ ->
- parse_DefinedValue(Rest2)
- end,
- case Rest3 of
- [{']',_}|Rest4] ->
- {#tag{class=Class,number=ClassNumber},Rest4};
- _ ->
- throw({asn1_error,{get_line(hd(Rest3)),get(asn1_module),
- [got,get_token(hd(Rest3)),expected,']']}})
- end;
-parse_Tag(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,'[']}}).
-
-parse_Class([{'UNIVERSAL',_}|Rest]) ->
- {'UNIVERSAL',Rest};
-parse_Class([{'APPLICATION',_}|Rest]) ->
- {'APPLICATION',Rest};
-parse_Class([{'PRIVATE',_}|Rest]) ->
- {'PRIVATE',Rest};
-parse_Class(Tokens) ->
- {'CONTEXT',Tokens}.
-
-parse_Value(Tokens) ->
- Flist = [fun parse_BuiltinValue/1,
- fun parse_ValueFromObject/1,
- fun parse_DefinedValue/1],
-
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- Result ->
- Result
- end.
-
-parse_BuiltinValue([{bstring,_,Bstr}|Rest]) ->
- {{bstring,Bstr},Rest};
-parse_BuiltinValue([{hstring,_,Hstr}|Rest]) ->
- {{hstring,Hstr},Rest};
-parse_BuiltinValue([{'{',_},{'}',_}|Rest]) ->
- {[],Rest};
-parse_BuiltinValue(Tokens = [{'{',_}|_Rest]) ->
- Flist = [
- fun parse_SequenceOfValue/1,
- fun parse_SequenceValue/1,
- fun parse_ObjectIdentifierValue/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- Result ->
- Result
- end;
-parse_BuiltinValue([{identifier,_,IdName},{':',_}|Rest]) ->
- {Value,Rest2} = parse_Value(Rest),
- {{'CHOICE',{IdName,Value}},Rest2};
-parse_BuiltinValue([{'NULL',_}|Rest]) ->
- {'NULL',Rest};
-parse_BuiltinValue([{'TRUE',_}|Rest]) ->
- {true,Rest};
-parse_BuiltinValue([{'FALSE',_}|Rest]) ->
- {false,Rest};
-parse_BuiltinValue([{'PLUS-INFINITY',_}|Rest]) ->
- {'PLUS-INFINITY',Rest};
-parse_BuiltinValue([{'MINUS-INFINITY',_}|Rest]) ->
- {'MINUS-INFINITY',Rest};
-parse_BuiltinValue([{cstring,_,Cstr}|Rest]) ->
- {Cstr,Rest};
-parse_BuiltinValue([{number,_,Num}|Rest]) ->
- {Num,Rest};
-parse_BuiltinValue([{'-',_},{number,_,Num}|Rest]) ->
- {- Num,Rest};
-parse_BuiltinValue(Tokens) ->
- parse_ObjectClassFieldValue(Tokens).
-
-%% Externalvaluereference
-parse_DefinedValue([{typereference,L1,Tname},{'.',_},{identifier,_,Idname}|Rest]) ->
- {#'Externalvaluereference'{pos=L1,module=Tname,value=Idname},Rest};
-%% valuereference
-parse_DefinedValue([Id = {identifier,_,_}|Rest]) ->
- {identifier2Extvalueref(Id),Rest};
-%% ParameterizedValue
-parse_DefinedValue(Tokens) ->
- parse_ParameterizedValue(Tokens).
-
-
-parse_SequenceValue([{'{',_}|Tokens]) ->
- parse_SequenceValue(Tokens,[]);
-parse_SequenceValue(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,'{']}}).
-
-parse_SequenceValue([{identifier,_,IdName}|Rest],Acc) ->
- {Value,Rest2} = parse_Value(Rest),
- case Rest2 of
- [{',',_}|Rest3] ->
- parse_SequenceValue(Rest3,[{IdName,Value}|Acc]);
- [{'}',_}|Rest3] ->
- {lists:reverse([{IdName,Value}|Acc]),Rest3};
- _ ->
- throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,'}']}})
- end;
-parse_SequenceValue(Tokens,_Acc) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,identifier]}}).
-
-parse_SequenceOfValue([{'{',_}|Tokens]) ->
- parse_SequenceOfValue(Tokens,[]);
-parse_SequenceOfValue(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,'{']}}).
-
-parse_SequenceOfValue(Tokens,Acc) ->
- {Value,Rest2} = parse_Value(Tokens),
- case Rest2 of
- [{',',_}|Rest3] ->
- parse_SequenceOfValue(Rest3,[Value|Acc]);
- [{'}',_}|Rest3] ->
- {lists:reverse([Value|Acc]),Rest3};
- _ ->
- throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,'}']}})
- end.
-
-parse_ValueSetTypeAssignment([{typereference,L1,Name}|Rest]) ->
- {Type,Rest2} = parse_Type(Rest),
- case Rest2 of
- [{'::=',_}|Rest3] ->
- {ValueSet,Rest4} = parse_ValueSet(Rest3),
- {#valuedef{pos=L1,name=Name,type=Type,value=ValueSet},Rest4};
- [H|_T] ->
- throw({asn1_error,{get_line(L1),get(asn1_module),
- [got,get_token(H),expected,'::=']}})
- end;
-parse_ValueSetTypeAssignment(Tokens) ->
- throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,
- typereference]}}).
-
-parse_ValueSet([{'{',_}|Rest]) ->
- {Elems,Rest2} = parse_ElementSetSpecs(Rest),
- case Rest2 of
- [{'}',_}|Rest3] ->
- {{valueset,Elems},Rest3};
- [H|_T] ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,'}']}})
- end;
-parse_ValueSet(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,'{']}}).
-
-parse_ValueAssignment([{identifier,L1,IdName}|Rest]) ->
- {Type,Rest2} = parse_Type(Rest),
- case Rest2 of
- [{'::=',_}|Rest3] ->
- {Value,Rest4} = parse_Value(Rest3),
- case lookahead_assignment(Rest4) of
- ok ->
- {#valuedef{pos=L1,name=IdName,type=Type,value=Value},Rest4};
- _ ->
- throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,'::=']}})
- end;
- _ ->
- throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,'::=']}})
- end;
-parse_ValueAssignment(Tokens) ->
- throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,identifier]}}).
-
-%% SizeConstraint
-parse_SubtypeElements([{'SIZE',_}|Tokens]) ->
- {Constraint,Rest} = parse_Constraint(Tokens),
- {{'SizeConstraint',Constraint#constraint.c},Rest};
-%% PermittedAlphabet
-parse_SubtypeElements([{'FROM',_}|Tokens]) ->
- {Constraint,Rest} = parse_Constraint(Tokens),
- {{'PermittedAlphabet',Constraint#constraint.c},Rest};
-%% InnerTypeConstraints
-parse_SubtypeElements([{'WITH',_},{'COMPONENT',_}|Tokens]) ->
- {Constraint,Rest} = parse_Constraint(Tokens),
- {{'WITH COMPONENT',Constraint},Rest};
-parse_SubtypeElements([{'WITH',_},{'COMPONENTS',_},{'{',_},{'...',_},{',',_}|Tokens]) ->
- {Constraint,Rest} = parse_TypeConstraints(Tokens),
- case Rest of
- [{'}',_}|Rest2] ->
- {{'WITH COMPONENTS',{'PartialSpecification',Constraint}},Rest2};
- _ ->
- throw({asn1_error,{get_line(hd(Rest)),get(asn1_module),
- [got,get_token(hd(Rest)),expected,'}']}})
- end;
-parse_SubtypeElements([{'WITH',_},{'COMPONENTS',_},{'{',_}|Tokens]) ->
- {Constraint,Rest} = parse_TypeConstraints(Tokens),
- case Rest of
- [{'}',_}|Rest2] ->
- {{'WITH COMPONENTS',{'FullSpecification',Constraint}},Rest2};
- _ ->
- throw({asn1_error,{get_line(hd(Rest)),get(asn1_module),
- [got,get_token(hd(Rest)),expected,'}']}})
- end;
-%% SingleValue
-%% ContainedSubtype
-%% ValueRange
-%% TypeConstraint
-parse_SubtypeElements(Tokens) ->
- Flist = [fun parse_ContainedSubtype/1,
- fun parse_Value/1,
- fun([{'MIN',_}|T]) -> {'MIN',T} end,
- fun parse_Type/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- {asn1_error,Reason} ->
- throw(Reason);
- Result = {Val,_} when record(Val,type) ->
- Result;
- {Lower,[{'..',_}|Rest]} ->
- {Upper,Rest2} = parse_UpperEndpoint(Rest),
- {{'ValueRange',{Lower,Upper}},Rest2};
- {Lower,[{'<',_},{'..',_}|Rest]} ->
- {Upper,Rest2} = parse_UpperEndpoint(Rest),
- {{'ValueRange',{{gt,Lower},Upper}},Rest2};
- {Res={'ContainedSubtype',_Type},Rest} ->
- {Res,Rest};
- {Value,Rest} ->
- {{'SingleValue',Value},Rest}
- end.
-
-parse_ContainedSubtype([{'INCLUDES',_}|Rest]) ->
- {Type,Rest2} = parse_Type(Rest),
- {{'ContainedSubtype',Type},Rest2};
-parse_ContainedSubtype(Tokens) ->
- throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
- [got,get_token(hd(Tokens)),expected,'INCLUDES']}}).
-%%parse_ContainedSubtype(Tokens) -> %this option is moved to parse_SubtypeElements
-%% parse_Type(Tokens).
-
-parse_UpperEndpoint([{'<',_}|Rest]) ->
- parse_UpperEndpoint(lt,Rest);
-parse_UpperEndpoint(Tokens) ->
- parse_UpperEndpoint(false,Tokens).
-
-parse_UpperEndpoint(Lt,Tokens) ->
- Flist = [ fun([{'MAX',_}|T]) -> {'MAX',T} end,
- fun parse_Value/1],
- case (catch parse_or(Tokens,Flist)) of
- {'EXIT',Reason} ->
- exit(Reason);
- AsnErr = {asn1_error,_} ->
- throw(AsnErr);
- {Value,Rest2} when Lt == lt ->
- {{lt,Value},Rest2};
- {Value,Rest2} ->
- {Value,Rest2}
- end.
-
-parse_TypeConstraints(Tokens) ->
- parse_TypeConstraints(Tokens,[]).
-
-parse_TypeConstraints([{identifier,_,_}|Rest],Acc) ->
- {ComponentConstraint,Rest2} = parse_ComponentConstraint(Rest),
- case Rest2 of
- [{',',_}|Rest3] ->
- parse_TypeConstraints(Rest3,[ComponentConstraint|Acc]);
- _ ->
- {lists:reverse([ComponentConstraint|Acc]),Rest2}
- end;
-parse_TypeConstraints([H|_T],_) ->
- throw({asn1_error,{get_line(H),get(asn1_module),
- [got,get_token(H),expected,identifier]}}).
-
-parse_ComponentConstraint(Tokens = [{'(',_}|_Rest]) ->
- {ValueConstraint,Rest2} = parse_Constraint(Tokens),
- {PresenceConstraint,Rest3} = parse_PresenceConstraint(Rest2),
- {{ValueConstraint,PresenceConstraint},Rest3};
-parse_ComponentConstraint(Tokens) ->
- {PresenceConstraint,Rest} = parse_PresenceConstraint(Tokens),
- {{asn1_empty,PresenceConstraint},Rest}.
-
-parse_PresenceConstraint([{'PRESENT',_}|Rest]) ->
- {'PRESENT',Rest};
-parse_PresenceConstraint([{'ABSENT',_}|Rest]) ->
- {'ABSENT',Rest};
-parse_PresenceConstraint([{'OPTIONAL',_}|Rest]) ->
- {'OPTIONAL',Rest};
-parse_PresenceConstraint(Tokens) ->
- {asn1_empty,Tokens}.
-
-
-merge_constraints({Rlist,ExtList}) -> % extensionmarker in constraint
- {merge_constraints(Rlist,[],[]),
- merge_constraints(ExtList,[],[])};
-
-merge_constraints(Clist) ->
- merge_constraints(Clist, [], []).
-
-merge_constraints([Ch|Ct],Cacc, Eacc) ->
- NewEacc = case Ch#constraint.e of
- undefined -> Eacc;
- E -> [E|Eacc]
- end,
- merge_constraints(Ct,[fixup_constraint(Ch#constraint.c)|Cacc],NewEacc);
-
-merge_constraints([],Cacc,[]) ->
-%% lists:flatten(Cacc);
- lists:reverse(Cacc);
-merge_constraints([],Cacc,Eacc) ->
-%% lists:flatten(Cacc) ++ [{'Errors',Eacc}].
- lists:reverse(Cacc) ++ [{'Errors',Eacc}].
-
-fixup_constraint(C) ->
- case C of
- {'SingleValue',SubType} when element(1,SubType) == 'ContainedSubtype' ->
- SubType;
- {'SingleValue',V} when list(V) ->
- C;
- %% [C,{'ValueRange',{lists:min(V),lists:max(V)}}];
- %% bug, turns wrong when an element in V is a reference to a defined value
- {'PermittedAlphabet',{'SingleValue',V}} when list(V) ->
- %%sort and remove duplicates
- V2 = {'SingleValue',
- ordsets:list_to_set(lists:flatten(V))},
- {'PermittedAlphabet',V2};
- {'PermittedAlphabet',{'SingleValue',V}} ->
- V2 = {'SingleValue',[V]},
- {'PermittedAlphabet',V2};
- {'SizeConstraint',Sc} ->
- {'SizeConstraint',fixup_size_constraint(Sc)};
-
- List when list(List) -> %% In This case maybe a union or intersection
- [fixup_constraint(Xc)||Xc <- List];
- Other ->
- Other
- end.
-
-fixup_size_constraint({'ValueRange',{Lb,Ub}}) ->
- {Lb,Ub};
-fixup_size_constraint({{'ValueRange',R},[]}) ->
- {R,[]};
-fixup_size_constraint({[],{'ValueRange',R}}) ->
- {[],R};
-fixup_size_constraint({{'ValueRange',R1},{'ValueRange',R2}}) ->
- {R1,R2};
-fixup_size_constraint({'SingleValue',[Sv]}) ->
- fixup_size_constraint({'SingleValue',Sv});
-fixup_size_constraint({'SingleValue',L}) when list(L) ->
- ordsets:list_to_set(L);
-fixup_size_constraint({'SingleValue',L}) ->
- {L,L};
-fixup_size_constraint({C1,C2}) ->
- {fixup_size_constraint(C1), fixup_size_constraint(C2)}.
-
-get_line({_,Pos,Token}) when integer(Pos),atom(Token) ->
- Pos;
-get_line({Token,Pos}) when integer(Pos),atom(Token) ->
- Pos;
-get_line(_) ->
- undefined.
-
-get_token({_,Pos,Token}) when integer(Pos),atom(Token) ->
- Token;
-get_token({'$end',Pos}) when integer(Pos) ->
- undefined;
-get_token({Token,Pos}) when integer(Pos),atom(Token) ->
- Token;
-get_token(_) ->
- undefined.
-
-prioritize_error(ErrList) ->
- case lists:keymember(asn1_error,1,ErrList) of
- false -> % only asn1_assignment_error -> take the last
- lists:last(ErrList);
- true -> % contains errors from deeper in a Type
- NewErrList = [_Err={_,_}|_RestErr] =
- lists:filter(fun({asn1_error,_})->true;(_)->false end,
- ErrList),
- SplitErrs =
- lists:splitwith(fun({_,X})->
- case element(1,X) of
- Int when integer(Int) -> true;
- _ -> false
- end
- end,
- NewErrList),
- case SplitErrs of
- {[],UndefPosErrs} -> % if no error with Positon exists
- lists:last(UndefPosErrs);
- {IntPosErrs,_} ->
- IntPosReasons = lists:map(fun(X)->element(2,X) end,IntPosErrs),
- SortedReasons = lists:keysort(1,IntPosReasons),
- {asn1_error,lists:last(SortedReasons)}
- end
- end.
-
-%% most_prio_error([H={_,Reason}|T],Atom,Err) when atom(Atom) ->
-%% most_prio_error(T,element(1,Reason),H);
-%% most_prio_error([H={_,Reason}|T],Greatest,Err) ->
-%% case element(1,Reason) of
-%% Pos when integer(Pos),Pos>Greatest ->
-%% most_prio_error(
-
-
-tref2Exttref(#typereference{pos=Pos,val=Name}) ->
- #'Externaltypereference'{pos=Pos,
- module=get(asn1_module),
- type=Name}.
-
-tref2Exttref(Pos,Name) ->
- #'Externaltypereference'{pos=Pos,
- module=get(asn1_module),
- type=Name}.
-
-identifier2Extvalueref(#identifier{pos=Pos,val=Name}) ->
- #'Externalvaluereference'{pos=Pos,
- module=get(asn1_module),
- value=Name}.
-
-%% lookahead_assignment/1 checks that the next sequence of tokens
-%% in Token contain a valid assignment or the
-%% 'END' token. Otherwise an exception is thrown.
-lookahead_assignment([{'END',_}|_Rest]) ->
- ok;
-lookahead_assignment(Tokens) ->
- parse_Assignment(Tokens),
- ok.
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_pretty_format.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_pretty_format.erl
deleted file mode 100644
index e0abcd36ec..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_pretty_format.erl
+++ /dev/null
@@ -1,199 +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: asn1ct_pretty_format.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
-%%
-
-%% usage: pretty_format:term(Term) -> PNF list of characters
-%%
-%% Note: this is usually used in expressions like:
-%% io:format('~s\n',[pretty_format:term(Term)]).
-%%
-%% Uses the following simple heuristics
-%%
-%% 1) Simple tuples are printed across the page
-%% (Simple means *all* the elements are "flat")
-%% 2) The Complex tuple {Arg1, Arg2, Arg3,....} is printed thus:
-%% {Arg1,
-%% Arg2,
-%% Arg3,
-%% ...}
-%% 3) Lists are treated as for tuples
-%% 4) Lists of printable characters are treated as strings
-%%
-%% This method seems to work reasonable well for {Tag, ...} type
-%% data structures
-
--module(asn1ct_pretty_format).
-
--export([term/1]).
-
--import(io_lib, [write/1, write_string/1]).
-
-term(Term) ->
- element(2, term(Term, 0)).
-
-%%______________________________________________________________________
-%% pretty_format:term(Term, Indent} -> {Indent', Chars}
-%% Format <Term> -- use <Indent> to indent the *next* line
-%% Note: Indent' is a new indentaion level (sometimes printing <Term>
-%% the next line to need an "extra" indent!).
-
-term([], Indent) ->
- {Indent, [$[,$]]};
-term(L, Indent) when is_list(L) ->
- case is_string(L) of
- true ->
- {Indent, write_string(L)};
- false ->
- case complex_list(L) of
- true ->
- write_complex_list(L, Indent);
- false ->
- write_simple_list(L, Indent)
- end
- end;
-term(T, Indent) when is_tuple(T) ->
- case complex_tuple(T) of
- true ->
- write_complex_tuple(T, Indent);
- false ->
- write_simple_tuple(T, Indent)
- end;
-term(A, Indent) ->
- {Indent, write(A)}.
-
-%%______________________________________________________________________
-%% write_simple_list([H|T], Indent) -> {Indent', Chars}
-
-write_simple_list([H|T], Indent) ->
- {_, S1} = term(H, Indent),
- {_, S2} = write_simple_list_tail(T, Indent),
- {Indent, [$[,S1|S2]}.
-
-write_simple_list_tail([H|T], Indent) ->
- {_, S1} = term(H, Indent),
- {_, S2} = write_simple_list_tail(T, Indent),
- {Indent, [$,,S1| S2]};
-write_simple_list_tail([], Indent) ->
- {Indent, "]"};
-write_simple_list_tail(Other, Indent) ->
- {_, S} = term(Other, Indent),
- {Indent, [$|,S,$]]}.
-
-%%______________________________________________________________________
-%% write_complex_list([H|T], Indent) -> {Indent', Chars}
-
-write_complex_list([H|T], Indent) ->
- {I1, S1} = term(H, Indent+1),
- {_, S2} = write_complex_list_tail(T, I1),
- {Indent, [$[,S1|S2]}.
-
-write_complex_list_tail([H|T], Indent) ->
- {I1, S1} = term(H, Indent),
- {_, S2} = write_complex_list_tail(T, I1),
- {Indent, [$,,nl_indent(Indent),S1,S2]};
-write_complex_list_tail([], Indent) ->
- {Indent, "]"};
-write_complex_list_tail(Other, Indent) ->$,,
- {_, S} = term(Other, Indent),
- {Indent, [$|,S,$]]}.
-
-%%______________________________________________________________________
-%% complex_list(List) -> true | false
-%% returns true if the list is complex otherwise false
-
-complex_list([]) ->
- false;
-complex_list([H|T]) when is_number(H); is_atom(H) ->
- complex_list(T);
-complex_list([H|T]) ->
- case is_string(H) of
- true ->
- complex_list(T);
- false ->
- true
- end;
-complex_list(_) -> true.
-
-%%______________________________________________________________________
-%% complex_tuple(Tuple) -> true | false
-%% returns true if the tuple is complex otherwise false
-
-complex_tuple(T) ->
- complex_list(tuple_to_list(T)).
-
-%%______________________________________________________________________
-%% write_simple_tuple(Tuple, Indent} -> {Indent', Chars}
-
-write_simple_tuple({}, Indent) ->
- {Indent, "{}"};
-write_simple_tuple(Tuple, Indent) ->
- {_, S} = write_simple_tuple_args(tuple_to_list(Tuple), Indent),
- {Indent, [${, S, $}]}.
-
-write_simple_tuple_args([X], Indent) ->
- term(X, Indent);
-write_simple_tuple_args([H|T], Indent) ->
- {_, SH} = term(H, Indent),
- {_, ST} = write_simple_tuple_args(T, Indent),
- {Indent, [SH, $,, ST]}.
-
-%%______________________________________________________________________
-%% write_complex_tuple(Tuple, Indent} -> {Indent', Chars}
-
-write_complex_tuple(Tuple, Indent) ->
- [H|T] = tuple_to_list(Tuple),
- {I1, SH} = term(H, Indent+2),
- {_, ST} = write_complex_tuple_args(T, I1),
- {Indent, [${, SH, ST, $}]}.
-
-write_complex_tuple_args([X], Indent) ->
- {_, S} = term(X, Indent),
- {Indent, [$,, nl_indent(Indent), S]};
-write_complex_tuple_args([H|T], Indent) ->
- {I1, SH} = term(H, Indent),
- {_, ST} = write_complex_tuple_args(T, I1),
- {Indent, [$,, nl_indent(Indent) , SH, ST]};
-write_complex_tuple_args([], Indent) ->
- {Indent, []}.
-
-%%______________________________________________________________________
-%% utilities
-
-nl_indent(I) when I >= 0 ->
- ["\n"|indent(I)];
-nl_indent(_) ->
- [$\s].
-
-indent(I) when I >= 8 ->
- [$\t|indent(I-8)];
-indent(I) when I > 0 ->
- [$\s|indent(I-1)];
-indent(_) ->
- [].
-
-is_string([9|T]) ->
- is_string(T);
-is_string([10|T]) ->
- is_string(T);
-is_string([H|T]) when H >31, H < 127 ->
- is_string(T);
-is_string([]) ->
- true;
-is_string(_) ->
- false.
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_tok.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_tok.erl
deleted file mode 100644
index 3ac1b68b37..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_tok.erl
+++ /dev/null
@@ -1,351 +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: asn1ct_tok.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
-%%
--module(asn1ct_tok).
-
-%% Tokenize ASN.1 code (input to parser generated with yecc)
-
--export([get_name/2,tokenise/2, file/1]).
-
-
-file(File) ->
- case file:open(File, [read]) of
- {error, Reason} ->
- {error,{File,file:format_error(Reason)}};
- {ok,Stream} ->
- process0(Stream)
- end.
-
-process0(Stream) ->
- process(Stream,0,[]).
-
-process(Stream,Lno,R) ->
- process(io:get_line(Stream, ''), Stream,Lno+1,R).
-
-process(eof, Stream,Lno,R) ->
- file:close(Stream),
- lists:flatten(lists:reverse([{'$end',Lno}|R]));
-
-
-process(L, Stream,Lno,R) when list(L) ->
- %%io:format('read:~s',[L]),
- case catch tokenise(L,Lno) of
- {'ERR',Reason} ->
- io:format("Tokeniser error on line: ~w ~w~n",[Lno,Reason]),
- exit(0);
- T ->
- %%io:format('toks:~w~n',[T]),
- process(Stream,Lno,[T|R])
- end.
-
-
-tokenise([H|T],Lno) when $a =< H , H =< $z ->
- {X, T1} = get_name(T, [H]),
- [{identifier,Lno, list_to_atom(X)}|tokenise(T1,Lno)];
-
-tokenise([$&,H|T],Lno) when $A =< H , H =< $Z ->
- {Y, T1} = get_name(T, [H]),
- X = list_to_atom(Y),
- [{typefieldreference, Lno, X} | tokenise(T1, Lno)];
-
-tokenise([$&,H|T],Lno) when $a =< H , H =< $z ->
- {Y, T1} = get_name(T, [H]),
- X = list_to_atom(Y),
- [{valuefieldreference, Lno, X} | tokenise(T1, Lno)];
-
-tokenise([H|T],Lno) 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)];
- false ->
- [{typereference,Lno,X}|tokenise(T1,Lno)];
- rstrtype ->
- [{restrictedcharacterstringtype,Lno,X}|tokenise(T1,Lno)]
- end;
-
-tokenise([$-,H|T],Lno) when $0 =< H , H =< $9 ->
- {X, T1} = get_number(T, [H]),
- [{number,Lno,-1 * list_to_integer(X)}|tokenise(T1,Lno)];
-
-tokenise([H|T],Lno) when $0 =< H , H =< $9 ->
- {X, T1} = get_number(T, [H]),
- [{number,Lno,list_to_integer(X)}|tokenise(T1,Lno)];
-
-tokenise([$-,$-|T],Lno) ->
- tokenise(skip_comment(T),Lno);
-tokenise([$:,$:,$=|T],Lno) ->
- [{'::=',Lno}|tokenise(T,Lno)];
-
-tokenise([$'|T],Lno) ->
- case catch collect_quoted(T,Lno,[]) of
- {'ERR',_} ->
- throw({'ERR','bad_quote'});
- {Thing, T1} ->
- [Thing|tokenise(T1,Lno)]
- end;
-
-tokenise([$"|T],Lno) ->
- collect_string(T,Lno);
-
-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([$,|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([$.,$.|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([$||T],Lno) ->
- [{'|',Lno}|tokenise(T,Lno)];
-
-
-tokenise([H|T],Lno) ->
- case white_space(H) of
- true ->
- tokenise(T,Lno);
- false ->
- [{list_to_atom([H]),Lno}|tokenise(T,Lno)]
- end;
-tokenise([],_) ->
- [].
-
-
-collect_string(L,Lno) ->
- collect_string(L,Lno,[]).
-
-collect_string([],_,_) ->
- throw({'ERR','bad_quote found eof'});
-
-collect_string([H|T],Lno,Str) ->
- case H of
- $" ->
- [{cstring,1,lists:reverse(Str)}|tokenise(T,Lno)];
- Ch ->
- collect_string(T,Lno,[Ch|Str])
- end.
-
-
-
-% <name> is letters digits hyphens
-% hypen is not the last character. Hypen hyphen is NOT allowed
-%
-% <identifier> ::= <lowercase> <name>
-
-get_name([$-,Char|T], L) ->
- case isalnum(Char) of
- true ->
- get_name(T,[Char,$-|L]);
- false ->
- {lists:reverse(L),[$-,Char|T]}
- end;
-get_name([$-|T], L) ->
- {lists:reverse(L),[$-|T]};
-get_name([Char|T], L) ->
- case isalnum(Char) of
- true ->
- get_name(T,[Char|L]);
- false ->
- {lists:reverse(L),[Char|T]}
- end;
-get_name([], L) ->
- {lists:reverse(L), []}.
-
-
-isalnum(H) when $A =< H , H =< $Z ->
- true;
-isalnum(H) when $a =< H , H =< $z ->
- true;
-isalnum(H) when $0 =< H , H =< $9 ->
- true;
-isalnum(_) ->
- false.
-
-isdigit(H) when $0 =< H , H =< $9 ->
- true;
-isdigit(_) ->
- false.
-
-white_space(9) -> true;
-white_space(10) -> true;
-white_space(13) -> true;
-white_space(32) -> true;
-white_space(_) -> false.
-
-
-get_number([H|T], L) ->
- case isdigit(H) of
- true ->
- get_number(T, [H|L]);
- false ->
- {lists:reverse(L), [H|T]}
- end;
-get_number([], L) ->
- {lists:reverse(L), []}.
-
-skip_comment([]) ->
- [];
-skip_comment([$-,$-|T]) ->
- T;
-skip_comment([_|T]) ->
- skip_comment(T).
-
-collect_quoted([$',$B|T],Lno, L) ->
- case check_bin(L) of
- true ->
- {{bstring,Lno, lists:reverse(L)}, T};
- false ->
- throw({'ERR',{invalid_binary_number, lists:reverse(L)}})
- end;
-collect_quoted([$',$H|T],Lno, L) ->
- case check_hex(L) of
- true ->
- {{hstring,Lno, lists:reverse(L)}, T};
- false ->
- throw({'ERR',{invalid_binary_number, lists:reverse(L)}})
- end;
-collect_quoted([H|T], Lno, L) ->
- collect_quoted(T, Lno,[H|L]);
-collect_quoted([], _, _) -> % This should be allowed FIX later
- throw({'ERR',{eol_in_token}}).
-
-check_bin([$0|T]) ->
- check_bin(T);
-check_bin([$1|T]) ->
- check_bin(T);
-check_bin([]) ->
- true;
-check_bin(_) ->
- false.
-
-check_hex([H|T]) when $0 =< H , H =< $9 ->
- check_hex(T);
-check_hex([H|T]) when $A =< H , H =< $F ->
- check_hex(T);
-check_hex([]) ->
- true;
-check_hex(_) ->
- false.
-
-
-%% reserved_word(A) -> true|false|rstrtype
-%% A = atom()
-%% returns true if A is a reserved ASN.1 word
-%% returns false if A is not a reserved word
-%% returns rstrtype if A is a reserved word in the group
-%% RestrictedCharacterStringType
-reserved_word('ABSENT') -> true;
-%reserved_word('ABSTRACT-SYNTAX') -> true; % impl as predef item
-reserved_word('ALL') -> true;
-reserved_word('ANY') -> true;
-reserved_word('APPLICATION') -> true;
-reserved_word('AUTOMATIC') -> true;
-reserved_word('BEGIN') -> true;
-reserved_word('BIT') -> true;
-reserved_word('BMPString') -> rstrtype;
-reserved_word('BOOLEAN') -> true;
-reserved_word('BY') -> true;
-reserved_word('CHARACTER') -> true;
-reserved_word('CHOICE') -> true;
-reserved_word('CLASS') -> true;
-reserved_word('COMPONENT') -> true;
-reserved_word('COMPONENTS') -> true;
-reserved_word('CONSTRAINED') -> true;
-reserved_word('DEFAULT') -> true;
-reserved_word('DEFINED') -> true;
-reserved_word('DEFINITIONS') -> true;
-reserved_word('EMBEDDED') -> true;
-reserved_word('END') -> true;
-reserved_word('ENUMERATED') -> true;
-reserved_word('EXCEPT') -> true;
-reserved_word('EXPLICIT') -> true;
-reserved_word('EXPORTS') -> true;
-reserved_word('EXTERNAL') -> true;
-reserved_word('FALSE') -> true;
-reserved_word('FROM') -> true;
-reserved_word('GeneralizedTime') -> true;
-reserved_word('GeneralString') -> rstrtype;
-reserved_word('GraphicString') -> rstrtype;
-reserved_word('IA5String') -> rstrtype;
-% reserved_word('TYPE-IDENTIFIER') -> true; % impl as predef item
-reserved_word('IDENTIFIER') -> true;
-reserved_word('IMPLICIT') -> true;
-reserved_word('IMPORTS') -> true;
-reserved_word('INCLUDES') -> true;
-reserved_word('INSTANCE') -> true;
-reserved_word('INTEGER') -> true;
-reserved_word('INTERSECTION') -> true;
-reserved_word('ISO646String') -> rstrtype;
-reserved_word('MAX') -> true;
-reserved_word('MIN') -> true;
-reserved_word('MINUS-INFINITY') -> true;
-reserved_word('NULL') -> true;
-reserved_word('NumericString') -> rstrtype;
-reserved_word('OBJECT') -> true;
-reserved_word('ObjectDescriptor') -> true;
-reserved_word('OCTET') -> true;
-reserved_word('OF') -> true;
-reserved_word('OPTIONAL') -> true;
-reserved_word('PDV') -> true;
-reserved_word('PLUS-INFINITY') -> true;
-reserved_word('PRESENT') -> true;
-reserved_word('PrintableString') -> rstrtype;
-reserved_word('PRIVATE') -> true;
-reserved_word('REAL') -> true;
-reserved_word('SEQUENCE') -> true;
-reserved_word('SET') -> true;
-reserved_word('SIZE') -> true;
-reserved_word('STRING') -> true;
-reserved_word('SYNTAX') -> true;
-reserved_word('T61String') -> rstrtype;
-reserved_word('TAGS') -> true;
-reserved_word('TeletexString') -> rstrtype;
-reserved_word('TRUE') -> true;
-reserved_word('UNION') -> true;
-reserved_word('UNIQUE') -> true;
-reserved_word('UNIVERSAL') -> true;
-reserved_word('UniversalString') -> rstrtype;
-reserved_word('UTCTime') -> true;
-reserved_word('VideotexString') -> rstrtype;
-reserved_word('VisibleString') -> rstrtype;
-reserved_word('WITH') -> true;
-reserved_word(_) -> false.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_value.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_value.erl
deleted file mode 100644
index 9510e4b341..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1ct_value.erl
+++ /dev/null
@@ -1,330 +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: asn1ct_value.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
-%%
--module(asn1ct_value).
-
-%% Generate Erlang values for ASN.1 types.
-%% The value is randomized within it's constraints
-
--include("asn1_records.hrl").
-%-compile(export_all).
-
--export([get_type/3]).
-
-
-
-%% Generate examples of values ******************************
-%%****************************************x
-
-
-get_type(M,Typename,Tellname) ->
- case asn1_db:dbget(M,Typename) of
- undefined ->
- {asn1_error,{not_found,{M,Typename}}};
- Tdef when record(Tdef,typedef) ->
- Type = Tdef#typedef.typespec,
- get_type(M,[Typename],Type,Tellname);
- Err ->
- {asn1_error,{other,Err}}
- end.
-
-get_type(M,Typename,Type,Tellname) when record(Type,type) ->
- InnerType = get_inner(Type#type.def),
- case asn1ct_gen:type(InnerType) of
- #'Externaltypereference'{module=Emod,type=Etype} ->
- get_type(Emod,Etype,Tellname);
- {_,user} ->
- case Tellname of
- yes -> {Typename,get_type(M,InnerType,no)};
- no -> get_type(M,InnerType,no)
- end;
- {notype,_} ->
- true;
- {primitive,bif} ->
- get_type_prim(Type);
- 'ASN1_OPEN_TYPE' ->
- case Type#type.constraint of
- [#'Externaltypereference'{type=TrefConstraint}] ->
- get_type(M,TrefConstraint,no);
- _ ->
- "open_type"
- end;
- {constructed,bif} ->
- get_type_constructed(M,Typename,InnerType,Type)
- end;
-get_type(M,Typename,#'ComponentType'{name = Name,typespec = Type},_) ->
- get_type(M,[Name|Typename],Type,no);
-get_type(_,_,_,_) -> % 'EXTENSIONMARK'
- undefined.
-
-get_inner(A) when atom(A) -> A;
-get_inner(Ext) when record(Ext,'Externaltypereference') -> Ext;
-get_inner({typereference,_Pos,Name}) -> Name;
-get_inner(T) when tuple(T) ->
- case asn1ct_gen:get_inner(T) of
- {fixedtypevaluefield,_,Type} ->
- Type#type.def;
- {typefield,_FieldName} ->
- 'ASN1_OPEN_TYPE';
- Other ->
- Other
- end.
-%%get_inner(T) when tuple(T) -> element(1,T).
-
-
-
-get_type_constructed(M,Typename,InnerType,D) when record(D,type) ->
- case InnerType of
- 'SET' ->
- get_sequence(M,Typename,D);
- 'SEQUENCE' ->
- get_sequence(M,Typename,D);
- 'CHOICE' ->
- get_choice(M,Typename,D);
- 'SEQUENCE OF' ->
- {_,Type} = D#type.def,
- NameSuffix = asn1ct_gen:constructed_suffix(InnerType,Type#type.def),
- get_sequence_of(M,Typename,D,NameSuffix);
- 'SET OF' ->
- {_,Type} = D#type.def,
- NameSuffix = asn1ct_gen:constructed_suffix(InnerType,Type#type.def),
- get_sequence_of(M,Typename,D,NameSuffix);
- _ ->
- exit({nyi,InnerType})
- end.
-
-get_sequence(M,Typename,Type) ->
- {_SEQorSET,CompList} =
- case Type#type.def of
- #'SEQUENCE'{components=Cl} -> {'SEQUENCE',Cl};
- #'SET'{components=Cl} -> {'SET',Cl}
- end,
- case get_components(M,Typename,CompList) of
- [] ->
- {list_to_atom(asn1ct_gen:list2rname(Typename))};
- C ->
- list_to_tuple([list_to_atom(asn1ct_gen:list2rname(Typename))|C])
- end.
-
-get_components(M,Typename,{Root,Ext}) ->
- get_components(M,Typename,Root++Ext);
-
-%% Should enhance this *** HERE *** with proper handling of extensions
-
-get_components(M,Typename,[H|T]) ->
- [get_type(M,Typename,H,no)|
- get_components(M,Typename,T)];
-get_components(_,_,[]) ->
- [].
-
-get_choice(M,Typename,Type) ->
- {'CHOICE',TCompList} = Type#type.def,
- case TCompList of
- [] ->
- {asn1_EMPTY,asn1_EMPTY};
- {CompList,ExtList} -> % Should be enhanced to handle extensions too
- CList = CompList ++ ExtList,
- C = lists:nth(random(length(CList)),CList),
- {C#'ComponentType'.name,get_type(M,Typename,C,no)};
- CompList when list(CompList) ->
- C = lists:nth(random(length(CompList)),CompList),
- {C#'ComponentType'.name,get_type(M,Typename,C,no)}
- end.
-
-get_sequence_of(M,Typename,Type,TypeSuffix) ->
- %% should generate length according to constraints later
- {_,Oftype} = Type#type.def,
- C = Type#type.constraint,
- S = size_random(C),
- NewTypeName = [TypeSuffix|Typename],
- gen_list(M,NewTypeName,Oftype,no,S).
-
-gen_list(_,_,_,_,0) ->
- [];
-gen_list(M,Typename,Oftype,Tellname,N) ->
- [get_type(M,Typename,Oftype,no)|gen_list(M,Typename,Oftype,Tellname,N-1)].
-
-get_type_prim(D) ->
- C = D#type.constraint,
- case D#type.def of
- 'INTEGER' ->
- i_random(C);
- {'INTEGER',NamedNumberList} ->
- NN = [X||{X,_} <- NamedNumberList],
- case NN of
- [] ->
- i_random(C);
- _ ->
- lists:nth(random(length(NN)),NN)
- end;
- Enum when tuple(Enum),element(1,Enum)=='ENUMERATED' ->
- NamedNumberList =
- case Enum of
- {_,_,NNL} -> NNL;
- {_,NNL} -> NNL
- end,
- NNew=
- case NamedNumberList of
- {N1,N2} ->
- N1 ++ N2;
- _->
- NamedNumberList
- end,
- NN = [X||{X,_} <- NNew],
- case NN of
- [] ->
- asn1_EMPTY;
- _ ->
- lists:nth(random(length(NN)),NN)
- end;
- {'BIT STRING',NamedNumberList} ->
-%% io:format("get_type_prim 1: ~w~n",[NamedNumberList]),
- NN = [X||{X,_} <- NamedNumberList],
- case NN of
- [] ->
- Bl1 =lists:reverse(adjust_list(size_random(C),[1,0,1,1])),
- lists:reverse(lists:dropwhile(fun(0)->true;(1)->false end,Bl1));
- _ ->
-%% io:format("get_type_prim 2: ~w~n",[NN]),
- [lists:nth(random(length(NN)),NN)]
- end;
- 'ANY' ->
- exit({asn1_error,nyi,'ANY'});
- 'NULL' ->
- 'NULL';
- 'OBJECT IDENTIFIER' ->
- Len = random(3),
- Olist = [(random(1000)-1)||_X <-lists:seq(1,Len)],
- list_to_tuple([random(3)-1,random(40)-1|Olist]);
- 'ObjectDescriptor' ->
- object_descriptor_nyi;
- 'BOOLEAN' ->
- true;
- 'OCTET STRING' ->
- adjust_list(size_random(C),c_string(C,"OCTET STRING"));
- 'NumericString' ->
- adjust_list(size_random(C),c_string(C,"0123456789"));
- 'TeletexString' ->
- adjust_list(size_random(C),c_string(C,"TeletexString"));
- 'VideotexString' ->
- adjust_list(size_random(C),c_string(C,"VideotexString"));
- 'UTCTime' ->
- "97100211-0500";
- 'GeneralizedTime' ->
- "19971002103130.5";
- 'GraphicString' ->
- adjust_list(size_random(C),c_string(C,"GraphicString"));
- 'VisibleString' ->
- adjust_list(size_random(C),c_string(C,"VisibleString"));
- 'GeneralString' ->
- adjust_list(size_random(C),c_string(C,"GeneralString"));
- 'PrintableString' ->
- adjust_list(size_random(C),c_string(C,"PrintableString"));
- 'IA5String' ->
- adjust_list(size_random(C),c_string(C,"IA5String"));
- 'BMPString' ->
- adjust_list(size_random(C),c_string(C,"BMPString"));
- 'UniversalString' ->
- adjust_list(size_random(C),c_string(C,"UniversalString"));
- XX ->
- exit({asn1_error,nyi,XX})
- end.
-
-c_string(undefined,Default) ->
- Default;
-c_string(C,Default) ->
- case get_constraint(C,'PermittedAlphabet') of
- {'SingleValue',Sv} when list(Sv) ->
- Sv;
- {'SingleValue',V} when integer(V) ->
- [V];
- no ->
- Default
- end.
-
-random(Upper) ->
- {A1,A2,A3} = erlang:now(),
- random:seed(A1,A2,A3),
- random:uniform(Upper).
-
-size_random(C) ->
- case get_constraint(C,'SizeConstraint') of
- no ->
- c_random({0,5},no);
- {Lb,Ub} when Ub-Lb =< 4 ->
- c_random({Lb,Ub},no);
- {Lb,_} ->
- c_random({Lb,Lb+4},no);
- Sv ->
- c_random(no,Sv)
- end.
-
-i_random(C) ->
- c_random(get_constraint(C,'ValueRange'),get_constraint(C,'SingleValue')).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% c_random(Range,SingleValue)
-%% only called from other X_random functions
-
-c_random(VRange,Single) ->
- case {VRange,Single} of
- {no,no} ->
- random(16#fffffff) - (16#fffffff bsr 1);
- {R,no} ->
- case R of
- {Lb,Ub} when integer(Lb),integer(Ub) ->
- Range = Ub - Lb +1,
- Lb + (random(Range)-1);
- {Lb,'MAX'} ->
- Lb + random(16#fffffff)-1;
- {'MIN',Ub} ->
- Ub - random(16#fffffff)-1;
- {A,{'ASN1_OK',B}} ->
- Range = B - A +1,
- A + (random(Range)-1)
- end;
- {_,S} when integer(S) ->
- S;
- {_,S} when list(S) ->
- lists:nth(random(length(S)),S)
-%% {S1,S2} ->
-%% io:format("asn1ct_value: hejsan hoppsan~n");
-%% _ ->
-%% io:format("asn1ct_value: hejsan hoppsan 2~n")
-%% io:format("asn1ct_value: c_random/2: S1 = ~w~n"
-%% "S2 = ~w,~n",[S1,S2])
-%% exit(self(),goodbye)
- end.
-
-adjust_list(Len,Orig) ->
- adjust_list1(Len,Orig,Orig,[]).
-
-adjust_list1(0,_Orig,[_Oh|_Ot],Acc) ->
- lists:reverse(Acc);
-adjust_list1(Len,Orig,[],Acc) ->
- adjust_list1(Len,Orig,Orig,Acc);
-adjust_list1(Len,Orig,[Oh|Ot],Acc) ->
- adjust_list1(Len-1,Orig,Ot,[Oh|Acc]).
-
-
-get_constraint(C,Key) ->
- case lists:keysearch(Key,1,C) of
- false ->
- no;
- {value,{_,V}} ->
- V
- end.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt.erl
deleted file mode 100644
index 1d73927052..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt.erl
+++ /dev/null
@@ -1,69 +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: asn1rt.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
-%%
--module(asn1rt).
-
-%% Runtime functions for ASN.1 (i.e encode, decode)
-
--export([encode/2,encode/3,decode/3,load_driver/0,unload_driver/0,info/1]).
-
-encode(Module,{Type,Term}) ->
- encode(Module,Type,Term).
-
-encode(Module,Type,Term) ->
- case catch apply(Module,encode,[Type,Term]) of
- {'EXIT',undef} ->
- {error,{asn1,{undef,Module,Type}}};
- Result ->
- Result
- end.
-
-decode(Module,Type,Bytes) ->
- case catch apply(Module,decode,[Type,Bytes]) of
- {'EXIT',undef} ->
- {error,{asn1,{undef,Module,Type}}};
- Result ->
- Result
- end.
-
-load_driver() ->
- asn1rt_driver_handler:load_driver(),
- receive
- driver_ready ->
- ok;
- Err={error,_Reason} ->
- Err;
- Error ->
- {error,Error}
- end.
-
-unload_driver() ->
- case catch asn1rt_driver_handler:unload_driver() of
- ok ->
- ok;
- Error ->
- {error,Error}
- end.
-
-
-info(Module) ->
- case catch apply(Module,info,[]) of
- {'EXIT',{undef,_Reason}} ->
- {error,{asn1,{undef,Module,info}}};
- Result ->
- {ok,Result}
- end.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_ber_bin.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_ber_bin.erl
deleted file mode 100644
index 4f4574513e..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_ber_bin.erl
+++ /dev/null
@@ -1,2310 +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: asn1rt_ber_bin.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
-%%
--module(asn1rt_ber_bin).
-
-%% encoding / decoding of BER
-
--export([decode/1]).
--export([fixoptionals/2,split_list/2,cindex/3,restbytes2/3,
- list_to_record/2,
- encode_tag_val/1,decode_tag/1,peek_tag/1,
- check_tags/3, encode_tags/3]).
--export([encode_boolean/2,decode_boolean/3,
- encode_integer/3,encode_integer/4,
- decode_integer/4,decode_integer/5,encode_enumerated/2,
- encode_enumerated/4,decode_enumerated/5,
- encode_real/2,decode_real/4,
- encode_bit_string/4,decode_bit_string/6,
- decode_compact_bit_string/6,
- encode_octet_string/3,decode_octet_string/5,
- encode_null/2,decode_null/3,
- encode_object_identifier/2,decode_object_identifier/3,
- encode_restricted_string/4,decode_restricted_string/6,
- encode_universal_string/3,decode_universal_string/5,
- encode_BMP_string/3,decode_BMP_string/5,
- encode_generalized_time/3,decode_generalized_time/5,
- encode_utc_time/3,decode_utc_time/5,
- encode_length/1,decode_length/1,
- check_if_valid_tag/3,
- decode_tag_and_length/1, decode_components/6,
- decode_components/7, decode_set/6]).
-
--export([encode_open_type/1,encode_open_type/2,decode_open_type/1,decode_open_type/2,decode_open_type/3]).
--export([skipvalue/1, skipvalue/2]).
-
--include("asn1_records.hrl").
-
-% the encoding of class of tag bits 8 and 7
--define(UNIVERSAL, 0).
--define(APPLICATION, 16#40).
--define(CONTEXT, 16#80).
--define(PRIVATE, 16#C0).
-
-%%% primitive or constructed encoding % bit 6
--define(PRIMITIVE, 0).
--define(CONSTRUCTED, 2#00100000).
-
-%%% The tag-number for universal types
--define(N_BOOLEAN, 1).
--define(N_INTEGER, 2).
--define(N_BIT_STRING, 3).
--define(N_OCTET_STRING, 4).
--define(N_NULL, 5).
--define(N_OBJECT_IDENTIFIER, 6).
--define(N_OBJECT_DESCRIPTOR, 7).
--define(N_EXTERNAL, 8).
--define(N_REAL, 9).
--define(N_ENUMERATED, 10).
--define(N_EMBEDDED_PDV, 11).
--define(N_SEQUENCE, 16).
--define(N_SET, 17).
--define(N_NumericString, 18).
--define(N_PrintableString, 19).
--define(N_TeletexString, 20).
--define(N_VideotexString, 21).
--define(N_IA5String, 22).
--define(N_UTCTime, 23).
--define(N_GeneralizedTime, 24).
--define(N_GraphicString, 25).
--define(N_VisibleString, 26).
--define(N_GeneralString, 27).
--define(N_UniversalString, 28).
--define(N_BMPString, 30).
-
-
-% the complete tag-word of built-in types
--define(T_BOOLEAN, ?UNIVERSAL bor ?PRIMITIVE bor 1).
--define(T_INTEGER, ?UNIVERSAL bor ?PRIMITIVE bor 2).
--define(T_BIT_STRING, ?UNIVERSAL bor ?PRIMITIVE bor 3). % can be CONSTRUCTED
--define(T_OCTET_STRING, ?UNIVERSAL bor ?PRIMITIVE bor 4). % can be CONSTRUCTED
--define(T_NULL, ?UNIVERSAL bor ?PRIMITIVE bor 5).
--define(T_OBJECT_IDENTIFIER,?UNIVERSAL bor ?PRIMITIVE bor 6).
--define(T_OBJECT_DESCRIPTOR,?UNIVERSAL bor ?PRIMITIVE bor 7).
--define(T_EXTERNAL, ?UNIVERSAL bor ?PRIMITIVE bor 8).
--define(T_REAL, ?UNIVERSAL bor ?PRIMITIVE bor 9).
--define(T_ENUMERATED, ?UNIVERSAL bor ?PRIMITIVE bor 10).
--define(T_EMBEDDED_PDV, ?UNIVERSAL bor ?PRIMITIVE bor 11).
--define(T_SEQUENCE, ?UNIVERSAL bor ?CONSTRUCTED bor 16).
--define(T_SET, ?UNIVERSAL bor ?CONSTRUCTED bor 17).
--define(T_NumericString, ?UNIVERSAL bor ?PRIMITIVE bor 18). %can be constructed
--define(T_PrintableString, ?UNIVERSAL bor ?PRIMITIVE bor 19). %can be constructed
--define(T_TeletexString, ?UNIVERSAL bor ?PRIMITIVE bor 20). %can be constructed
--define(T_VideotexString, ?UNIVERSAL bor ?PRIMITIVE bor 21). %can be constructed
--define(T_IA5String, ?UNIVERSAL bor ?PRIMITIVE bor 22). %can be constructed
--define(T_UTCTime, ?UNIVERSAL bor ?PRIMITIVE bor 23).
--define(T_GeneralizedTime, ?UNIVERSAL bor ?PRIMITIVE bor 24).
--define(T_GraphicString, ?UNIVERSAL bor ?PRIMITIVE bor 25). %can be constructed
--define(T_VisibleString, ?UNIVERSAL bor ?PRIMITIVE bor 26). %can be constructed
--define(T_GeneralString, ?UNIVERSAL bor ?PRIMITIVE bor 27). %can be constructed
--define(T_UniversalString, ?UNIVERSAL bor ?PRIMITIVE bor 28). %can be constructed
--define(T_BMPString, ?UNIVERSAL bor ?PRIMITIVE bor 30). %can be constructed
-
-
-decode(Bin) ->
- decode_primitive(Bin).
-
-decode_primitive(Bin) ->
- {Tlv = {Tag,Len,V},<<>>} = decode_tlv(Bin),
- case element(2,Tag) of
- ?CONSTRUCTED ->
- {Tag,Len,decode_constructed(V)};
- _ ->
- Tlv
- end.
-
-decode_constructed(<<>>) ->
- [];
-decode_constructed(Bin) ->
- {Tlv = {Tag,Len,V},Rest} = decode_tlv(Bin),
- NewTlv =
- case element(2,Tag) of
- ?CONSTRUCTED ->
- {Tag,Len,decode_constructed(V)};
- _ ->
- Tlv
- end,
- [NewTlv|decode_constructed(Rest)].
-
-decode_tlv(Bin) ->
- {Tag,Bin1,_Rb1} = decode_tag(Bin),
- {{Len,Bin2},_Rb2} = decode_length(Bin1),
- <<V:Len/binary,Bin3/binary>> = Bin2,
- {{Tag,Len,V},Bin3}.
-
-
-
-%%%%%%%%%%%%%
-% split_list(List,HeadLen) -> {HeadList,TailList}
-%
-% splits List into HeadList (Length=HeadLen) and TailList
-% if HeadLen == indefinite -> return {List,indefinite}
-split_list(List,indefinite) ->
- {List, indefinite};
-split_list(Bin, Len) when binary(Bin) ->
- split_binary(Bin,Len);
-split_list(List,Len) ->
- {lists:sublist(List,Len),lists:nthtail(Len,List)}.
-
-
-%%% new function which fixes a bug regarding indefinite length decoding
-restbytes2(indefinite,<<0,0,RemBytes/binary>>,_) ->
- {RemBytes,2};
-restbytes2(indefinite,RemBytes,ext) ->
- skipvalue(indefinite,RemBytes);
-restbytes2(RemBytes,<<>>,_) ->
- {RemBytes,0};
-restbytes2(_RemBytes,Bytes,noext) ->
- exit({error,{asn1, {unexpected,Bytes}}});
-restbytes2(RemBytes,_Bytes,ext) ->
- {RemBytes,0}.
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% skipvalue(Length, Bytes) -> {RemainingBytes, RemovedNumberOfBytes}
-%%
-%% skips the one complete (could be nested) TLV from Bytes
-%% handles both definite and indefinite length encodings
-%%
-
-skipvalue(L, Bytes) ->
- skipvalue(L, Bytes, 0).
-
-skipvalue(indefinite, Bytes, Rb) ->
- {_T,Bytes2,R2} = decode_tag(Bytes),
- {{L,Bytes3},R3} = decode_length(Bytes2),
- {Bytes4,Rb4} = case L of
- indefinite ->
- skipvalue(indefinite,Bytes3,R2+R3);
- _ ->
- <<_:L/binary, RestBytes/binary>> = Bytes3,
- {RestBytes, R2+R3+L}
- end,
- case Bytes4 of
- <<0,0,Bytes5/binary>> ->
- {Bytes5,Rb+Rb4+2};
- _ -> skipvalue(indefinite,Bytes4,Rb+Rb4)
- end;
-skipvalue(L, Bytes, Rb) ->
-% <<Skip:L/binary, RestBytes/binary>> = Bytes,
- <<_:L/binary, RestBytes/binary>> = Bytes,
- {RestBytes,Rb+L}.
-
-%%skipvalue(indefinite, Bytes, Rb) ->
-%% {T,Bytes2,R2} = decode_tag(Bytes),
-%% {L,Bytes3,R3} = decode_length(Bytes2),
-%% {Bytes4,Rb4} = case L of
-%% indefinite ->
-%% skipvalue(indefinite,Bytes3,R2+R3);
-%% _ ->
-%% lists:nthtail(L,Bytes3) %% konstigt !?
-%% end,
-%% case Bytes4 of
-%% [0,0|Bytes5] ->
-%% {Bytes5,Rb4+2};
-%% _ -> skipvalue(indefinite,Bytes4,Rb4)
-%% end;
-%%skipvalue(L, Bytes, Rb) ->
-%% {lists:nthtail(L,Bytes),Rb+L}.
-
-skipvalue(Bytes) ->
- {_T,Bytes2,R2} = decode_tag(Bytes),
- {{L,Bytes3},R3} = decode_length(Bytes2),
- skipvalue(L,Bytes3,R2+R3).
-
-
-cindex(Ix,Val,Cname) ->
- case element(Ix,Val) of
- {Cname,Val2} -> Val2;
- X -> X
- end.
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Optionals, preset not filled optionals with asn1_NOVALUE
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-% converts a list to a record if necessary
-list_to_record(Name,List) when list(List) ->
- list_to_tuple([Name|List]);
-list_to_record(_Name,Tuple) when tuple(Tuple) ->
- Tuple.
-
-
-fixoptionals(OptList,Val) when list(Val) ->
- fixoptionals(OptList,Val,1,[],[]).
-
-fixoptionals([{Name,Pos}|Ot],[{Name,Val}|Vt],_Opt,Acc1,Acc2) ->
- fixoptionals(Ot,Vt,Pos+1,[1|Acc1],[{Name,Val}|Acc2]);
-fixoptionals([{_Name,Pos}|Ot],V,Pos,Acc1,Acc2) ->
- fixoptionals(Ot,V,Pos+1,[0|Acc1],[asn1_NOVALUE|Acc2]);
-fixoptionals(O,[Vh|Vt],Pos,Acc1,Acc2) ->
- fixoptionals(O,Vt,Pos+1,Acc1,[Vh|Acc2]);
-fixoptionals([],[Vh|Vt],Pos,Acc1,Acc2) ->
- fixoptionals([],Vt,Pos+1,Acc1,[Vh|Acc2]);
-fixoptionals([],[],_,_Acc1,Acc2) ->
- % return Val as a record
- list_to_tuple([asn1_RECORDNAME|lists:reverse(Acc2)]).
-
-
-%%encode_tag(TagClass(?UNI, APP etc), Form (?PRIM etx), TagInteger) ->
-%% 8bit Int | binary
-encode_tag_val({Class, Form, TagNo}) when (TagNo =< 30) ->
- <<(Class bsr 6):2,(Form bsr 5):1,TagNo:5>>;
-
-encode_tag_val({Class, Form, TagNo}) ->
- {Octets,_Len} = mk_object_val(TagNo),
- BinOct = list_to_binary(Octets),
- <<(Class bsr 6):2, (Form bsr 5):1, 31:5,BinOct/binary>>;
-
-%% asumes whole correct tag bitpattern, multiple of 8
-encode_tag_val(Tag) when (Tag =< 255) -> Tag; %% anv�nds denna funktion??!!
-%% asumes correct bitpattern of 0-5
-encode_tag_val(Tag) -> encode_tag_val2(Tag,[]).
-
-encode_tag_val2(Tag, OctAck) when (Tag =< 255) ->
- [Tag | OctAck];
-encode_tag_val2(Tag, OctAck) ->
- encode_tag_val2(Tag bsr 8, [255 band Tag | OctAck]).
-
-
-%%%encode_tag(TagClass(?UNI, APP etc), Form (?PRIM etx), TagInteger) ->
-%%% 8bit Int | [list of octets]
-%encode_tag_val({Class, Form, TagNo}) when (TagNo =< 30) ->
-%%% <<Class:2,Form:1,TagNo:5>>;
-% [Class bor Form bor TagNo];
-%encode_tag_val({Class, Form, TagNo}) ->
-% {Octets,L} = mk_object_val(TagNo),
-% [Class bor Form bor 31 | Octets];
-
-
-%%============================================================================\%% Peek on the initial tag
-%% peek_tag(Bytes) -> TagBytes
-%% interprets the first byte and possible second, third and fourth byte as
-%% a tag and returns all the bytes comprising the tag, the constructed/primitive bit (6:th bit of first byte) is normalised to 0
-%%
-
-peek_tag(<<B7_6:2,_:1,31:5,Buffer/binary>>) ->
- Bin = peek_tag(Buffer, <<>>),
- <<B7_6:2,31:6,Bin/binary>>;
-%% single tag (tagno < 31)
-peek_tag(<<B7_6:2,_:1,B4_0:5,_Buffer/binary>>) ->
- <<B7_6:2,B4_0:6>>.
-
-peek_tag(<<0:1,PartialTag:7,_Buffer/binary>>, TagAck) ->
- <<TagAck/binary,PartialTag>>;
-peek_tag(<<PartialTag,Buffer/binary>>, TagAck) ->
- peek_tag(Buffer,<<TagAck/binary,PartialTag>>);
-peek_tag(_,TagAck) ->
- exit({error,{asn1, {invalid_tag,TagAck}}}).
-%%peek_tag([Tag|Buffer]) when (Tag band 31) == 31 ->
-%% [Tag band 2#11011111 | peek_tag(Buffer,[])];
-%%%% single tag (tagno < 31)
-%%peek_tag([Tag|Buffer]) ->
-%% [Tag band 2#11011111].
-
-%%peek_tag([PartialTag|Buffer], TagAck) when (PartialTag < 128 ) ->
-%% lists:reverse([PartialTag|TagAck]);
-%%peek_tag([PartialTag|Buffer], TagAck) ->
-%% peek_tag(Buffer,[PartialTag|TagAck]);
-%%peek_tag(Buffer,TagAck) ->
-%% exit({error,{asn1, {invalid_tag,lists:reverse(TagAck)}}}).
-
-
-%%===============================================================================
-%% Decode a tag
-%%
-%% decode_tag(OctetListBuffer) -> {{Class, Form, TagNo}, RestOfBuffer, RemovedBytes}
-%%===============================================================================
-
-%% multiple octet tag
-decode_tag(<<Class:2, Form:1, 31:5, Buffer/binary>>) ->
- {TagNo, Buffer1, RemovedBytes} = decode_tag(Buffer, 0, 1),
- {{(Class bsl 6), (Form bsl 5), TagNo}, Buffer1, RemovedBytes};
-
-%% single tag (< 31 tags)
-decode_tag(<<Class:2,Form:1,TagNo:5, Buffer/binary>>) ->
- {{(Class bsl 6), (Form bsl 5), TagNo}, Buffer, 1}.
-
-%% last partial tag
-decode_tag(<<0:1,PartialTag:7, Buffer/binary>>, TagAck, RemovedBytes) ->
- TagNo = (TagAck bsl 7) bor PartialTag,
- %%<<TagNo>> = <<TagAck:1, PartialTag:7>>,
- {TagNo, Buffer, RemovedBytes+1};
-% more tags
-decode_tag(<<_:1,PartialTag:7, Buffer/binary>>, TagAck, RemovedBytes) ->
- TagAck1 = (TagAck bsl 7) bor PartialTag,
- %%<<TagAck1:16>> = <<TagAck:1, PartialTag:7,0:8>>,
- decode_tag(Buffer, TagAck1, RemovedBytes+1).
-
-%%------------------------------------------------------------------
-%% check_tags_i is the same as check_tags except that it stops and
-%% returns the remaining tags not checked when it encounters an
-%% indefinite length field
-%% only called internally within this module
-
-check_tags_i([Tag], Buffer, OptOrMand) -> % optimized very usual case
- {[],check_one_tag(Tag, Buffer, OptOrMand)};
-check_tags_i(Tags, Buffer, OptOrMand) ->
- check_tags_i(Tags, Buffer, 0, OptOrMand).
-
-check_tags_i([Tag1,Tag2|TagRest], Buffer, Rb, OptOrMand)
- when Tag1#tag.type == 'IMPLICIT' ->
- check_tags_i([Tag1#tag{type=Tag2#tag.type}|TagRest], Buffer, Rb, OptOrMand);
-
-check_tags_i([Tag1|TagRest], Buffer, Rb, OptOrMand) ->
- {Form_Length,Buffer2,Rb1} = check_one_tag(Tag1, Buffer, OptOrMand),
- case TagRest of
- [] -> {TagRest, {Form_Length, Buffer2, Rb + Rb1}};
- _ ->
- case Form_Length of
- {?CONSTRUCTED,_} ->
- {TagRest, {Form_Length, Buffer2, Rb + Rb1}};
- _ ->
- check_tags_i(TagRest, Buffer2, Rb + Rb1, mandatory)
- end
- end;
-
-check_tags_i([], Buffer, Rb, _) ->
- {[],{{0,0},Buffer,Rb}}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% This function is called from generated code
-
-check_tags([Tag], Buffer, OptOrMand) -> % optimized very usual case
- check_one_tag(Tag, Buffer, OptOrMand);
-check_tags(Tags, Buffer, OptOrMand) ->
- check_tags(Tags, Buffer, 0, OptOrMand).
-
-check_tags([Tag1,Tag2|TagRest], Buffer, Rb, OptOrMand)
- when Tag1#tag.type == 'IMPLICIT' ->
- check_tags([Tag1#tag{type=Tag2#tag.type}|TagRest], Buffer, Rb, OptOrMand);
-
-check_tags([Tag1|TagRest], Buffer, Rb, OptOrMand) ->
- {Form_Length,Buffer2,Rb1} = check_one_tag(Tag1, Buffer, OptOrMand),
- case TagRest of
- [] -> {Form_Length, Buffer2, Rb + Rb1};
- _ -> check_tags(TagRest, Buffer2, Rb + Rb1, mandatory)
- end;
-
-check_tags([], Buffer, Rb, _) ->
- {{0,0},Buffer,Rb}.
-
-check_one_tag(Tag=#tag{class=ExpectedClass,number=ExpectedNumber}, Buffer, OptOrMand) ->
- case catch decode_tag(Buffer) of
- {'EXIT',_Reason} ->
- tag_error(no_data,Tag,Buffer,OptOrMand);
- {{ExpectedClass,Form,ExpectedNumber},Buffer2,Rb} ->
- {{L,Buffer3},RemBytes2} = decode_length(Buffer2),
- {{Form,L}, Buffer3, RemBytes2+Rb};
- {ErrorTag,_,_} ->
- tag_error(ErrorTag, Tag, Buffer, OptOrMand)
- end.
-
-tag_error(ErrorTag, Tag, Buffer, OptOrMand) ->
- case OptOrMand of
- mandatory ->
- exit({error,{asn1, {invalid_tag,
- {ErrorTag, Tag, Buffer}}}});
- _ ->
- exit({error,{asn1, {no_optional_tag,
- {ErrorTag, Tag, Buffer}}}})
- end.
-%%=======================================================================
-%%
-%% Encode all tags in the list Tags and return a possibly deep list of
-%% bytes with tag and length encoded
-%%
-%% prepend_tags(Tags, BytesSoFar, LenSoFar) -> {Bytes, Len}
-encode_tags(Tags, BytesSoFar, LenSoFar) ->
- NewTags = encode_tags1(Tags, []),
- %% NewTags contains the resulting tags in reverse order
- encode_tags2(NewTags, BytesSoFar, LenSoFar).
-
-%encode_tags2([#tag{class=?UNIVERSAL,number=No}|Trest], BytesSoFar, LenSoFar) ->
-% {Bytes2,L2} = encode_length(LenSoFar),
-% encode_tags2(Trest,[[No|Bytes2],BytesSoFar], LenSoFar + 1 + L2);
-encode_tags2([Tag|Trest], BytesSoFar, LenSoFar) ->
- {Bytes1,L1} = encode_one_tag(Tag),
- {Bytes2,L2} = encode_length(LenSoFar),
- encode_tags2(Trest, [Bytes1,Bytes2|BytesSoFar],
- LenSoFar + L1 + L2);
-encode_tags2([], BytesSoFar, LenSoFar) ->
- {BytesSoFar,LenSoFar}.
-
-encode_tags1([Tag1, Tag2| Trest], Acc)
- when Tag1#tag.type == 'IMPLICIT' ->
- encode_tags1([Tag1#tag{type=Tag2#tag.type,form=Tag2#tag.form}|Trest],Acc);
-encode_tags1([Tag1 | Trest], Acc) ->
- encode_tags1(Trest, [Tag1|Acc]);
-encode_tags1([], Acc) ->
- Acc. % the resulting tags are returned in reverse order
-
-encode_one_tag(Bin) when binary(Bin) ->
- {Bin,size(Bin)};
-encode_one_tag(#tag{class=Class,number=No,type=Type, form = Form}) ->
- NewForm = case Type of
- 'EXPLICIT' ->
- ?CONSTRUCTED;
- _ ->
- Form
- end,
- Bytes = encode_tag_val({Class,NewForm,No}),
- {Bytes,size(Bytes)}.
-
-%%===============================================================================
-%% Change the tag (used when an implicit tagged type has a reference to something else)
-%% The constructed bit in the tag is taken from the tag to be replaced.
-%%
-%% change_tag(NewTag,[Tag,Buffer]) -> [NewTag,Buffer]
-%%===============================================================================
-
-%change_tag({NewClass,NewTagNr}, Buffer) ->
-% {{OldClass, OldForm, OldTagNo}, Buffer1, RemovedBytes} = decode_tag(lists:flatten(Buffer)),
-% [encode_tag_val({NewClass, OldForm, NewTagNr}) | Buffer1].
-
-
-
-
-
-
-
-%%===============================================================================
-%%
-%% This comment is valid for all the encode/decode functions
-%%
-%% C = Constraint -> typically {'ValueRange',LowerBound,UpperBound}
-%% used for PER-coding but not for BER-coding.
-%%
-%% Val = Value. If Val is an atom then it is a symbolic integer value
-%% (i.e the atom must be one of the names in the NamedNumberList).
-%% The NamedNumberList is used to translate the atom to an integer value
-%% before encoding.
-%%
-%%===============================================================================
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_open_type(Value) -> CompleteList
-%% Value = list of bytes of an already encoded value (the list must be flat)
-%% | binary
-
-%% This version does not consider Explicit tagging of the open type. It
-%% is only left because of backward compatibility.
-encode_open_type(Val) when list(Val) ->
- {Val,size(list_to_binary(Val))};
-encode_open_type(Val) ->
- {Val, size(Val)}.
-
-%%
-encode_open_type(Val, []) when list(Val) ->
- {Val,size(list_to_binary(Val))};
-encode_open_type(Val,[]) ->
- {Val, size(Val)};
-encode_open_type(Val, Tag) when list(Val) ->
- encode_tags(Tag,Val,size(list_to_binary(Val)));
-encode_open_type(Val,Tag) ->
- encode_tags(Tag,Val, size(Val)).
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_open_type(Buffer) -> Value
-%% Bytes = [byte] with BER encoded data
-%% Value = [byte] with decoded data (which must be decoded again as some type)
-%%
-decode_open_type(Bytes) ->
- {_Tag, Len, _RemainingBuffer, RemovedBytes} = decode_tag_and_length(Bytes),
- N = Len + RemovedBytes,
- <<Val:N/binary, RemainingBytes/binary>> = Bytes,
- {Val, RemainingBytes, Len + RemovedBytes}.
-
-decode_open_type(Bytes,ExplTag) ->
- {Tag, Len, RemainingBuffer, RemovedBytes} = decode_tag_and_length(Bytes),
- case {Tag,ExplTag} of
- {{Class,Form,No},[#tag{class=Class,number=No,form=Form}]} ->
- {_Tag2, Len2, _RemainingBuffer2, RemovedBytes2} = decode_tag_and_length(RemainingBuffer),
- N = Len2 + RemovedBytes2,
- <<_:RemovedBytes/unit:8,Val:N/binary,RemainingBytes/binary>> = Bytes,
- {Val, RemainingBytes, N + RemovedBytes};
- _ ->
- N = Len + RemovedBytes,
- <<Val:N/binary, RemainingBytes/binary>> = Bytes,
- {Val, RemainingBytes, Len + RemovedBytes}
- end.
-
-decode_open_type(ber_bin,Bytes,ExplTag) ->
- decode_open_type(Bytes,ExplTag);
-decode_open_type(ber,Bytes,ExplTag) ->
- {Val,RemBytes,Len}=decode_open_type(Bytes,ExplTag),
- {binary_to_list(Val),RemBytes,Len}.
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Boolean, ITU_T X.690 Chapter 8.2
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-%%===============================================================================
-%% encode_boolean(Integer, tag | notag) -> [octet list]
-%%===============================================================================
-
-encode_boolean({Name, Val}, DoTag) when atom(Name) ->
- dotag(DoTag, ?N_BOOLEAN, encode_boolean(Val));
-encode_boolean(true,[]) ->
- {[1,1,16#FF],3};
-encode_boolean(false,[]) ->
- {[1,1,0],3};
-encode_boolean(Val, DoTag) ->
- dotag(DoTag, ?N_BOOLEAN, encode_boolean(Val)).
-
-%% encode_boolean(Boolean) -> [Len, Boolean] = [1, $FF | 0]
-encode_boolean(true) -> {[16#FF],1};
-encode_boolean(false) -> {[0],1};
-encode_boolean(X) -> exit({error,{asn1, {encode_boolean, X}}}).
-
-
-%%===============================================================================
-%% decode_boolean(BuffList, HasTag, TotalLen) -> {true, Remain, RemovedBytes} |
-%% {false, Remain, RemovedBytes}
-%%===============================================================================
-
-decode_boolean(Buffer, Tags, OptOrMand) ->
- NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_BOOLEAN}),
- decode_boolean_notag(Buffer, NewTags, OptOrMand).
-
-decode_boolean_notag(Buffer, Tags, OptOrMand) ->
- {RestTags, {FormLen,Buffer0,Rb0}} =
- check_tags_i(Tags, Buffer, OptOrMand),
- case FormLen of
- {?CONSTRUCTED,Len} ->
- {Buffer00,RestBytes} = split_list(Buffer0,Len),
- {Val,Buffer1,Rb1} = decode_boolean_notag(Buffer00, RestTags, OptOrMand),
- {Buffer2, Rb2} = restbytes2(RestBytes,Buffer1,noext),
- {Val, Buffer2, Rb0+Rb1+Rb2};
- {_,_} ->
- decode_boolean2(Buffer0, Rb0)
- end.
-
-decode_boolean2(<<0:8, Buffer/binary>>, RemovedBytes) ->
- {false, Buffer, RemovedBytes + 1};
-decode_boolean2(<<_:8, Buffer/binary>>, RemovedBytes) ->
- {true, Buffer, RemovedBytes + 1};
-decode_boolean2(Buffer, _) ->
- exit({error,{asn1, {decode_boolean, Buffer}}}).
-
-
-
-
-%%===========================================================================
-%% Integer, ITU_T X.690 Chapter 8.3
-
-%% encode_integer(Constraint, Value, Tag) -> [octet list]
-%% encode_integer(Constraint, Name, NamedNumberList, Tag) -> [octet list]
-%% Value = INTEGER | {Name,INTEGER}
-%% Tag = tag | notag
-%%===========================================================================
-
-encode_integer(C, Val, []) when integer(Val) ->
- {EncVal,Len}=encode_integer(C, Val),
- dotag_universal(?N_INTEGER,EncVal,Len);
-encode_integer(C, Val, Tag) when integer(Val) ->
- dotag(Tag, ?N_INTEGER, encode_integer(C, Val));
-encode_integer(C,{Name,Val},Tag) when atom(Name) ->
- encode_integer(C,Val,Tag);
-encode_integer(_, Val, _) ->
- exit({error,{asn1, {encode_integer, Val}}}).
-
-
-
-encode_integer(C, Val, NamedNumberList, Tag) when atom(Val) ->
- case lists:keysearch(Val, 1, NamedNumberList) of
- {value,{_, NewVal}} ->
- dotag(Tag, ?N_INTEGER, encode_integer(C, NewVal));
- _ ->
- exit({error,{asn1, {encode_integer_namednumber, Val}}})
- end;
-encode_integer(C,{_,Val},NamedNumberList,Tag) ->
- encode_integer(C,Val,NamedNumberList,Tag);
-encode_integer(C, Val, _NamedNumberList, Tag) ->
- dotag(Tag, ?N_INTEGER, encode_integer(C, Val)).
-
-
-
-
-encode_integer(_C, Val) ->
- Bytes =
- if
- Val >= 0 ->
- encode_integer_pos(Val, []);
- true ->
- encode_integer_neg(Val, [])
- end,
- {Bytes,length(Bytes)}.
-
-encode_integer_pos(0, L=[B|_Acc]) when B < 128 ->
- L;
-encode_integer_pos(N, Acc) ->
- encode_integer_pos((N bsr 8), [N band 16#ff| Acc]).
-
-encode_integer_neg(-1, L=[B1|_T]) when B1 > 127 ->
- L;
-encode_integer_neg(N, Acc) ->
- encode_integer_neg(N bsr 8, [N band 16#ff|Acc]).
-
-%%===============================================================================
-%% decode integer
-%% (Buffer, Range, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
-%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
-%%===============================================================================
-
-
-decode_integer(Buffer, Range, Tags, OptOrMand) ->
- NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_INTEGER}),
- decode_integer_notag(Buffer, Range, [], NewTags, OptOrMand).
-
-decode_integer(Buffer, Range, NamedNumberList, Tags, OptOrMand) ->
- NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_INTEGER}),
- decode_integer_notag(Buffer, Range, NamedNumberList, NewTags, OptOrMand).
-
-decode_integer_notag(Buffer, Range, NamedNumberList, NewTags, OptOrMand) ->
- {RestTags, {FormLen, Buffer0, Rb0}} =
- check_tags_i(NewTags, Buffer, OptOrMand),
-% Result = {Val, Buffer2, RemovedBytes} =
- case FormLen of
- {?CONSTRUCTED,Len} ->
- {Buffer00, RestBytes} = split_list(Buffer0,Len),
- {Val01, Buffer01, Rb01} =
- decode_integer_notag(Buffer00, Range, NamedNumberList,
- RestTags, OptOrMand),
- {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
- {Val01, Buffer02, Rb0+Rb01+Rb02};
- {_, Len} ->
- Result =
- decode_integer2(Len,Buffer0,Rb0+Len),
- Result2 = check_integer_constraint(Result,Range),
- resolve_named_value(Result2,NamedNumberList)
- end.
-
-resolve_named_value(Result={Val,Buffer,RemBytes},NamedNumberList) ->
- case NamedNumberList of
- [] -> Result;
- _ ->
- NewVal = case lists:keysearch(Val, 2, NamedNumberList) of
- {value,{NamedVal, _}} ->
- NamedVal;
- _ ->
- Val
- end,
- {NewVal, Buffer, RemBytes}
- end.
-
-check_integer_constraint(Result={Val, _Buffer,_},Range) ->
- case Range of
- [] -> % No length constraint
- Result;
- {Lb,Ub} when Val >= Lb, Ub >= Val -> % variable length constraint
- Result;
- Val -> % fixed value constraint
- Result;
- {_,_} ->
- exit({error,{asn1,{integer_range,Range,Val}}});
- SingleValue when integer(SingleValue) ->
- exit({error,{asn1,{integer_range,Range,Val}}});
- _ -> % some strange constraint that we don't support yet
- Result
- end.
-
-%%============================================================================
-%% Enumerated value, ITU_T X.690 Chapter 8.4
-
-%% encode enumerated value
-%%============================================================================
-encode_enumerated(Val, []) when integer(Val)->
- {EncVal,Len} = encode_integer(false,Val),
- dotag_universal(?N_ENUMERATED,EncVal,Len);
-encode_enumerated(Val, DoTag) when integer(Val)->
- dotag(DoTag, ?N_ENUMERATED, encode_integer(false,Val));
-encode_enumerated({Name,Val}, DoTag) when atom(Name) ->
- encode_enumerated(Val, DoTag).
-
-%% The encode_enumerated functions below this line can be removed when the
-%% new code generation is stable. (the functions might have to be kept here
-%% a while longer for compatibility reasons)
-
-encode_enumerated(C, Val, {NamedNumberList,ExtList}, DoTag) when atom(Val) ->
- case catch encode_enumerated(C, Val, NamedNumberList, DoTag) of
- {'EXIT',_} -> encode_enumerated(C, Val, ExtList, DoTag);
- Result -> Result
- end;
-
-encode_enumerated(C, Val, NamedNumberList, DoTag) when atom(Val) ->
- case lists:keysearch(Val, 1, NamedNumberList) of
- {value, {_, NewVal}} when DoTag == []->
- {EncVal,Len} = encode_integer(C,NewVal),
- dotag_universal(?N_ENUMERATED,EncVal,Len);
- {value, {_, NewVal}} ->
- dotag(DoTag, ?N_ENUMERATED, encode_integer(C, NewVal));
- _ ->
- exit({error,{asn1, {enumerated_not_in_range, Val}}})
- end;
-
-encode_enumerated(C, {asn1_enum, Val}, {_,_}, DoTag) when integer(Val) ->
- dotag(DoTag, ?N_ENUMERATED, encode_integer(C,Val));
-
-encode_enumerated(C, {Name,Val}, NamedNumberList, DoTag) when atom(Name) ->
- encode_enumerated(C, Val, NamedNumberList, DoTag);
-
-encode_enumerated(_, Val, _, _) ->
- exit({error,{asn1, {enumerated_not_namednumber, Val}}}).
-
-
-
-%%============================================================================
-%% decode enumerated value
-%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) ->
-%% {Value, RemainingBuffer, RemovedBytes}
-%%===========================================================================
-decode_enumerated(Buffer, Range, NamedNumberList, Tags, OptOrMand) ->
- NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_ENUMERATED}),
- decode_enumerated_notag(Buffer, Range, NamedNumberList,
- NewTags, OptOrMand).
-
-decode_enumerated_notag(Buffer, Range, NNList = {NamedNumberList,ExtList}, Tags, OptOrMand) ->
- {RestTags, {FormLen, Buffer0, Rb0}} =
- check_tags_i(Tags, Buffer, OptOrMand),
-
- case FormLen of
- {?CONSTRUCTED,Len} ->
- {Buffer00,RestBytes} = split_list(Buffer0,Len),
- {Val01, Buffer01, Rb01} =
- decode_enumerated_notag(Buffer00, Range, NNList, RestTags, OptOrMand),
- {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
- {Val01, Buffer02, Rb0+Rb01+Rb02};
- {_,Len} ->
- {Val01, Buffer01, Rb01} =
- decode_integer2(Len, Buffer0, Rb0+Len),
- case decode_enumerated1(Val01, NamedNumberList) of
- {asn1_enum,Val01} ->
- {decode_enumerated1(Val01,ExtList), Buffer01, Rb01};
- Result01 ->
- {Result01, Buffer01, Rb01}
- end
- end;
-
-decode_enumerated_notag(Buffer, Range, NNList, Tags, OptOrMand) ->
- {RestTags, {FormLen, Buffer0, Rb0}} =
- check_tags_i(Tags, Buffer, OptOrMand),
-
- case FormLen of
- {?CONSTRUCTED,Len} ->
- {Buffer00,RestBytes} = split_list(Buffer0,Len),
- {Val01, Buffer01, Rb01} =
- decode_enumerated_notag(Buffer00, Range, NNList, RestTags, OptOrMand),
- {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
- {Val01, Buffer02, Rb0+Rb01+Rb02};
- {_,Len} ->
- {Val01, Buffer02, Rb02} =
- decode_integer2(Len, Buffer0, Rb0+Len),
- case decode_enumerated1(Val01, NNList) of
- {asn1_enum,_} ->
- exit({error,{asn1, {illegal_enumerated, Val01}}});
- Result01 ->
- {Result01, Buffer02, Rb02}
- end
- end.
-
-decode_enumerated1(Val, NamedNumberList) ->
- %% it must be a named integer
- case lists:keysearch(Val, 2, NamedNumberList) of
- {value,{NamedVal, _}} ->
- NamedVal;
- _ ->
- {asn1_enum,Val}
- end.
-
-
-%%============================================================================
-%%
-%% Real value, ITU_T X.690 Chapter 8.5
-%%============================================================================
-%%
-%% encode real value
-%%============================================================================
-
-%% only base 2 internally so far!!
-encode_real(0, DoTag) ->
- dotag(DoTag, ?N_REAL, {[],0});
-encode_real('PLUS-INFINITY', DoTag) ->
- dotag(DoTag, ?N_REAL, {[64],1});
-encode_real('MINUS-INFINITY', DoTag) ->
- dotag(DoTag, ?N_REAL, {[65],1});
-encode_real(Val, DoTag) when tuple(Val)->
- dotag(DoTag, ?N_REAL, encode_real(Val)).
-
-%%%%%%%%%%%%%%
-%% not optimal efficient..
-%% only base 2 of Mantissa encoding!
-%% only base 2 of ExpBase encoding!
-encode_real({Man, Base, Exp}) ->
-%% io:format("Mantissa: ~w Base: ~w, Exp: ~w~n",[Man, Base, Exp]),
-
- OctExp = if Exp >= 0 -> list_to_binary(encode_integer_pos(Exp, []));
- true -> list_to_binary(encode_integer_neg(Exp, []))
- end,
-%% ok = io:format("OctExp: ~w~n",[OctExp]),
- SignBit = if Man > 0 -> 0; % bit 7 is pos or neg, no Zeroval
- true -> 1
- end,
-%% ok = io:format("SignBitMask: ~w~n",[SignBitMask]),
- InBase = if Base =:= 2 -> 0; % bit 6,5: only base 2 this far!
- true ->
- exit({error,{asn1, {encode_real_non_supported_encodeing, Base}}})
- end,
- SFactor = 0, % bit 4,3: no scaling since only base 2
- OctExpLen = size(OctExp),
- if OctExpLen > 255 ->
- exit({error,{asn1, {to_big_exp_in_encode_real, OctExpLen}}});
- true -> true %% make real assert later..
- end,
- {LenCode, EOctets} = case OctExpLen of % bit 2,1
- 1 -> {0, OctExp};
- 2 -> {1, OctExp};
- 3 -> {2, OctExp};
- _ -> {3, <<OctExpLen, OctExp/binary>>}
- end,
- FirstOctet = <<1:1,SignBit:1,InBase:2,SFactor:2,LenCode:2>>,
- OctMantissa = if Man > 0 -> list_to_binary(minimum_octets(Man));
- true -> list_to_binary(minimum_octets(-(Man))) % signbit keeps track of sign
- end,
- %% ok = io:format("LenMask: ~w EOctets: ~w~nFirstOctet: ~w OctMantissa: ~w OctExpLen: ~w~n", [LenMask, EOctets, FirstOctet, OctMantissa, OctExpLen]),
- Bin = <<FirstOctet/binary, EOctets/binary, OctMantissa/binary>>,
- {Bin, size(Bin)}.
-
-
-%encode_real({Man, Base, Exp}) ->
-%% io:format("Mantissa: ~w Base: ~w, Exp: ~w~n",[Man, Base, Exp]),
-
-% OctExp = if Exp >= 0 -> encode_integer_pos(Exp, []);
-% true -> encode_integer_neg(Exp, [])
-% end,
-%% ok = io:format("OctExp: ~w~n",[OctExp]),
-% SignBitMask = if Man > 0 -> 2#00000000; % bit 7 is pos or neg, no Zeroval
-% true -> 2#01000000
-% end,
-%% ok = io:format("SignBitMask: ~w~n",[SignBitMask]),
-% InternalBaseMask = if Base =:= 2 -> 2#00000000; % bit 6,5: only base 2 this far!
-% true ->
-% exit({error,{asn1, {encode_real_non_supported_encodeing, Base}}})
-% end,
-% ScalingFactorMask =2#00000000, % bit 4,3: no scaling since only base 2
-% OctExpLen = length(OctExp),
-% if OctExpLen > 255 ->
-% exit({error,{asn1, {to_big_exp_in_encode_real, OctExpLen}}});
-% true -> true %% make real assert later..
-% end,
-% {LenMask, EOctets} = case OctExpLen of % bit 2,1
-% 1 -> {0, OctExp};
-% 2 -> {1, OctExp};
-% 3 -> {2, OctExp};
-% _ -> {3, [OctExpLen, OctExp]}
-% end,
-% FirstOctet = (SignBitMask bor InternalBaseMask bor
-% ScalingFactorMask bor LenMask bor
-% 2#10000000), % bit set for binary mantissa encoding!
-% OctMantissa = if Man > 0 -> minimum_octets(Man);
-% true -> minimum_octets(-(Man)) % signbit keeps track of sign
-% end,
-%% ok = io:format("LenMask: ~w EOctets: ~w~nFirstOctet: ~w OctMantissa: ~w OctExpLen: ~w~n", [LenMask, EOctets, FirstOctet, OctMantissa, OctExpLen]),
-% {[FirstOctet, EOctets, OctMantissa],
-% length(OctMantissa) +
-% (if OctExpLen > 3 ->
-% OctExpLen + 2;
-% true ->
-% OctExpLen + 1
-% end)
-% }.
-
-
-%%============================================================================
-%% decode real value
-%%
-%% decode_real([OctetBufferList], tuple|value, tag|notag) ->
-%% {{Mantissa, Base, Exp} | realval | PLUS-INFINITY | MINUS-INFINITY | 0,
-%% RestBuff}
-%%
-%% only for base 2 decoding sofar!!
-%%============================================================================
-
-decode_real(Buffer, Form, Tags, OptOrMand) ->
- NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_REAL}),
- decode_real_notag(Buffer, Form, NewTags, OptOrMand).
-
-decode_real_notag(Buffer, Form, Tags, OptOrMand) ->
- {RestTags, {FormLen, Buffer0, Rb0}} =
- check_tags_i(Tags, Buffer, OptOrMand),
-
- case FormLen of
- {?CONSTRUCTED,Len} ->
- {Buffer00,RestBytes} = split_list(Buffer0,Len),
- {Val01, Buffer01, Rb01} =
- decode_real_notag(Buffer00, Form, RestTags, OptOrMand),
- {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
- {Val01, Buffer02, Rb0+Rb01+Rb02};
- {_,Len} ->
- decode_real2(Buffer0, Form, Len, Rb0)
- end.
-
-decode_real2(Buffer0, Form, Len, RemBytes1) ->
- <<First, Buffer2/binary>> = Buffer0,
- if
- First =:= 2#01000000 -> {'PLUS-INFINITY', Buffer2};
- First =:= 2#01000001 -> {'MINUS-INFINITY', Buffer2};
- First =:= 2#00000000 -> {0, Buffer2};
- true ->
- %% have some check here to verify only supported bases (2)
- <<_B7:1,B6:1,B5_4:2,B3_2:2,B1_0:2>> = <<First>>,
- Sign = B6,
- Base =
- case B5_4 of
- 0 -> 2; % base 2, only one so far
- _ -> exit({error,{asn1, {non_supported_base, First}}})
- end,
-% ScalingFactor =
- case B3_2 of
- 0 -> 0; % no scaling so far
- _ -> exit({error,{asn1, {non_supported_scaling, First}}})
- end,
- % ok = io:format("Buffer2: ~w~n",[Buffer2]),
- {FirstLen, {Exp, Buffer3}, RemBytes2} =
- case B1_0 of
- 0 -> {2, decode_integer2(1, Buffer2, RemBytes1), RemBytes1+1};
- 1 -> {3, decode_integer2(2, Buffer2, RemBytes1), RemBytes1+2};
- 2 -> {4, decode_integer2(3, Buffer2, RemBytes1), RemBytes1+3};
- 3 ->
- <<ExpLen1,RestBuffer/binary>> = Buffer2,
- { ExpLen1 + 2,
- decode_integer2(ExpLen1, RestBuffer, RemBytes1),
- RemBytes1+ExpLen1}
- end,
- % io:format("FirstLen: ~w, Exp: ~w, Buffer3: ~w ~n",
- % [FirstLen, Exp, Buffer3]),
- Length = Len - FirstLen,
- <<LongInt:Length/unit:8,RestBuff/binary>> = Buffer3,
- {{Mantissa, Buffer4}, RemBytes3} =
- if Sign =:= 0 ->
- % io:format("sign plus~n"),
- {{LongInt, RestBuff}, 1 + Length};
- true ->
- % io:format("sign minus~n"),
- {{-LongInt, RestBuff}, 1 + Length}
- end,
- % io:format("Form: ~w~n",[Form]),
- case Form of
- tuple ->
- {Val,Buf,_RemB} = Exp,
- {{Mantissa, Base, {Val,Buf}}, Buffer4, RemBytes2+RemBytes3};
- _value ->
- comming
- end
- end.
-
-
-%%============================================================================
-%% Bitstring value, ITU_T X.690 Chapter 8.6
-%%
-%% encode bitstring value
-%%
-%% bitstring NamedBitList
-%% Val can be of:
-%% - [identifiers] where only named identifers are set to one,
-%% the Constraint must then have some information of the
-%% bitlength.
-%% - [list of ones and zeroes] all bits
-%% - integer value representing the bitlist
-%% C is constrint Len, only valid when identifiers
-%%============================================================================
-
-encode_bit_string(C,Bin={Unused,BinBits},NamedBitList,DoTag) when integer(Unused), binary(BinBits) ->
- encode_bin_bit_string(C,Bin,NamedBitList,DoTag);
-encode_bit_string(C, [FirstVal | RestVal], NamedBitList, DoTag) when atom(FirstVal) ->
- encode_bit_string_named(C, [FirstVal | RestVal], NamedBitList, DoTag);
-
-encode_bit_string(C, [{bit,X} | RestVal], NamedBitList, DoTag) ->
- encode_bit_string_named(C, [{bit,X} | RestVal], NamedBitList, DoTag);
-
-encode_bit_string(C, [FirstVal| RestVal], NamedBitList, DoTag) when integer(FirstVal) ->
- encode_bit_string_bits(C, [FirstVal | RestVal], NamedBitList, DoTag);
-
-encode_bit_string(_, 0, _, []) ->
- {[?N_BIT_STRING,1,0],3};
-
-encode_bit_string(_, 0, _, DoTag) ->
- dotag(DoTag, ?N_BIT_STRING, {<<0>>,1});
-
-encode_bit_string(_, [], _, []) ->
- {[?N_BIT_STRING,1,0],3};
-
-encode_bit_string(_, [], _, DoTag) ->
- dotag(DoTag, ?N_BIT_STRING, {<<0>>,1});
-
-encode_bit_string(C, IntegerVal, NamedBitList, DoTag) when integer(IntegerVal) ->
- BitListVal = int_to_bitlist(IntegerVal),
- encode_bit_string_bits(C, BitListVal, NamedBitList, DoTag);
-
-encode_bit_string(C, {Name,BitList}, NamedBitList, DoTag) when atom(Name) ->
- encode_bit_string(C, BitList, NamedBitList, DoTag).
-
-
-
-int_to_bitlist(0) ->
- [];
-int_to_bitlist(Int) when integer(Int), Int >= 0 ->
- [Int band 1 | int_to_bitlist(Int bsr 1)].
-
-
-%%=================================================================
-%% Encode BIT STRING of the form {Unused,BinBits}.
-%% Unused is the number of unused bits in the last byte in BinBits
-%% and BinBits is a binary representing the BIT STRING.
-%%=================================================================
-encode_bin_bit_string(C,{Unused,BinBits},_NamedBitList,DoTag)->
- case get_constraint(C,'SizeConstraint') of
- no ->
- remove_unused_then_dotag(DoTag,?N_BIT_STRING,Unused,BinBits);
- {_Min,Max} ->
- BBLen = (size(BinBits)*8)-Unused,
- if
- BBLen > Max ->
- exit({error,{asn1,
- {bitstring_length,
- {{was,BBLen},{maximum,Max}}}}});
- true ->
- remove_unused_then_dotag(DoTag,?N_BIT_STRING,
- Unused,BinBits)
- end;
- Size ->
- case ((size(BinBits)*8)-Unused) of
- BBSize when BBSize =< Size ->
- remove_unused_then_dotag(DoTag,?N_BIT_STRING,
- Unused,BinBits);
- BBSize ->
- exit({error,{asn1,
- {bitstring_length,
- {{was,BBSize},{should_be,Size}}}}})
- end
- end.
-
-remove_unused_then_dotag(DoTag,StringType,Unused,BinBits) ->
- case Unused of
- 0 when (size(BinBits) == 0),DoTag==[] ->
- %% time optimization of next case
- {[StringType,1,0],3};
- 0 when (size(BinBits) == 0) ->
- dotag(DoTag,StringType,{<<0>>,1});
- 0 when DoTag==[]-> % time optimization of next case
- dotag_universal(StringType,[Unused|BinBits],size(BinBits)+1);
-% {LenEnc,Len} = encode_legth(size(BinBits)+1),
-% {[StringType,LenEnc,[Unused|BinBits]],size(BinBits)+1+Len+1};
- 0 ->
- dotag(DoTag,StringType,<<Unused,BinBits/binary>>);
- Num when DoTag == [] -> % time optimization of next case
- N = (size(BinBits)-1),
- <<BBits:N/binary,LastByte>> = BinBits,
- dotag_universal(StringType,
- [Unused,BBits,(LastByte bsr Num) bsl Num],
- size(BinBits)+1);
-% {LenEnc,Len} = encode_legth(size(BinBits)+1),
-% {[StringType,LenEnc,[Unused,BBits,(LastByte bsr Num) bsl Num],
-% 1+Len+size(BinBits)+1};
- Num ->
- N = (size(BinBits)-1),
- <<BBits:N/binary,LastByte>> = BinBits,
- dotag(DoTag,StringType,{[Unused,binary_to_list(BBits) ++
- [(LastByte bsr Num) bsl Num]],
- 1+size(BinBits)})
- end.
-
-
-%%=================================================================
-%% Encode named bits
-%%=================================================================
-
-encode_bit_string_named(C, [FirstVal | RestVal], NamedBitList, DoTag) ->
- {Len,Unused,OctetList} =
- case get_constraint(C,'SizeConstraint') of
- no ->
- ToSetPos = get_all_bitposes([FirstVal | RestVal],
- NamedBitList, []),
- BitList = make_and_set_list(lists:max(ToSetPos)+1,
- ToSetPos, 0),
- encode_bitstring(BitList);
- {_Min,Max} ->
- ToSetPos = get_all_bitposes([FirstVal | RestVal],
- NamedBitList, []),
- BitList = make_and_set_list(Max, ToSetPos, 0),
- encode_bitstring(BitList);
- Size ->
- ToSetPos = get_all_bitposes([FirstVal | RestVal],
- NamedBitList, []),
- BitList = make_and_set_list(Size, ToSetPos, 0),
- encode_bitstring(BitList)
- end,
- case DoTag of
- [] ->
- dotag_universal(?N_BIT_STRING,[Unused|OctetList],Len+1);
-% {EncLen,LenLen} = encode_length(Len+1),
-% {[?N_BIT_STRING,EncLen,Unused,OctetList],1+LenLen+Len+1};
- _ ->
- dotag(DoTag, ?N_BIT_STRING, {[Unused|OctetList],Len+1})
- end.
-
-
-%%----------------------------------------
-%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
-%% [sorted_list_of_bitpositions_to_set]
-%%----------------------------------------
-
-get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
-get_all_bitposes([Val | Rest], NamedBitList, Ack) when atom(Val) ->
- case lists:keysearch(Val, 1, NamedBitList) of
- {value, {_ValName, ValPos}} ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
- _ ->
- exit({error,{asn1, {bitstring_namedbit, Val}}})
- end;
-get_all_bitposes([], _NamedBitList, Ack) ->
- lists:sort(Ack).
-
-
-%%----------------------------------------
-%% make_and_set_list(Len of list to return, [list of positions to set to 1])->
-%% returns list of Len length, with all in SetPos set.
-%% in positioning in list the first element is 0, the second 1 etc.., but
-%% Len will make a list of length Len, not Len + 1.
-%% BitList = make_and_set_list(C, ToSetPos, 0),
-%%----------------------------------------
-
-make_and_set_list(0, [], _) -> [];
-make_and_set_list(0, _, _) ->
- exit({error,{asn1,bitstring_sizeconstraint}});
-make_and_set_list(Len, [XPos|SetPos], XPos) ->
- [1 | make_and_set_list(Len - 1, SetPos, XPos + 1)];
-make_and_set_list(Len, [Pos|SetPos], XPos) ->
- [0 | make_and_set_list(Len - 1, [Pos | SetPos], XPos + 1)];
-make_and_set_list(Len, [], XPos) ->
- [0 | make_and_set_list(Len - 1, [], XPos + 1)].
-
-
-
-
-
-
-%%=================================================================
-%% Encode bit string for lists of ones and zeroes
-%%=================================================================
-encode_bit_string_bits(C, BitListVal, _NamedBitList, DoTag) when list(BitListVal) ->
- {Len,Unused,OctetList} =
- case get_constraint(C,'SizeConstraint') of
- no ->
- encode_bitstring(BitListVal);
- Constr={Min,Max} when integer(Min),integer(Max) ->
- encode_constr_bit_str_bits(Constr,BitListVal,DoTag);
- {Constr={_,_},[]} ->
- %% constraint with extension mark
- encode_constr_bit_str_bits(Constr,BitListVal,DoTag);
- Constr={{_,_},{_,_}} ->%{{Min1,Max1},{Min2,Max2}}
- %% constraint with extension mark
- encode_constr_bit_str_bits(Constr,BitListVal,DoTag);
- Size ->
- case length(BitListVal) of
- BitSize when BitSize == Size ->
- encode_bitstring(BitListVal);
- BitSize when BitSize < Size ->
- PaddedList =
- pad_bit_list(Size-BitSize,BitListVal),
- encode_bitstring(PaddedList);
- BitSize ->
- exit({error,
- {asn1,
- {bitstring_length,
- {{was,BitSize},
- {should_be,Size}}}}})
- end
- end,
- %%add unused byte to the Len
- case DoTag of
- [] ->
- dotag_universal(?N_BIT_STRING,[Unused|OctetList],Len+1);
-% {EncLen,LenLen}=encode_length(Len+1),
-% {[?N_BIT_STRING,EncLen,Unused|OctetList],1+LenLen+Len+1};
- _ ->
- dotag(DoTag, ?N_BIT_STRING,
- {[Unused | OctetList],Len+1})
- end.
-
-
-encode_constr_bit_str_bits({_Min,Max},BitListVal,_DoTag) ->
- BitLen = length(BitListVal),
- if
- BitLen > Max ->
- exit({error,{asn1,{bitstring_length,{{was,BitLen},
- {maximum,Max}}}}});
- true ->
- encode_bitstring(BitListVal)
- end;
-encode_constr_bit_str_bits({{_Min1,Max1},{Min2,Max2}},BitListVal,_DoTag) ->
- BitLen = length(BitListVal),
- case BitLen of
- Len when Len > Max2 ->
- exit({error,{asn1,{bitstring_length,{{was,BitLen},
- {maximum,Max2}}}}});
- Len when Len > Max1, Len < Min2 ->
- exit({error,{asn1,{bitstring_length,{{was,BitLen},
- {not_allowed_interval,
- Max1,Min2}}}}});
- _ ->
- encode_bitstring(BitListVal)
- end.
-
-%% returns a list of length Size + length(BitListVal), with BitListVal
-%% as the most significant elements followed by padded zero elements
-pad_bit_list(Size,BitListVal) ->
- Tail = lists:duplicate(Size,0),
- lists:append(BitListVal,Tail).
-
-%%=================================================================
-%% Do the actual encoding
-%% ([bitlist]) -> {ListLen, UnusedBits, OctetList}
-%%=================================================================
-
-encode_bitstring([B8, B7, B6, B5, B4, B3, B2, B1 | Rest]) ->
- Val = (B8 bsl 7) bor (B7 bsl 6) bor (B6 bsl 5) bor (B5 bsl 4) bor
- (B4 bsl 3) bor (B3 bsl 2) bor (B2 bsl 1) bor B1,
- encode_bitstring(Rest, [Val], 1);
-encode_bitstring(Val) ->
- {Unused, Octet} = unused_bitlist(Val, 7, 0),
- {1, Unused, [Octet]}.
-
-encode_bitstring([B8, B7, B6, B5, B4, B3, B2, B1 | Rest], Ack, Len) ->
- Val = (B8 bsl 7) bor (B7 bsl 6) bor (B6 bsl 5) bor (B5 bsl 4) bor
- (B4 bsl 3) bor (B3 bsl 2) bor (B2 bsl 1) bor B1,
- encode_bitstring(Rest, [Ack | [Val]], Len + 1);
-%%even multiple of 8 bits..
-encode_bitstring([], Ack, Len) ->
- {Len, 0, Ack};
-%% unused bits in last octet
-encode_bitstring(Rest, Ack, Len) ->
-% io:format("uneven ~w ~w ~w~n",[Rest, Ack, Len]),
- {Unused, Val} = unused_bitlist(Rest, 7, 0),
- {Len + 1, Unused, [Ack | [Val]]}.
-
-%%%%%%%%%%%%%%%%%%
-%% unused_bitlist([list of ones and zeros <= 7], 7, []) ->
-%% {Unused bits, Last octet with bits moved to right}
-unused_bitlist([], Trail, Ack) ->
- {Trail + 1, Ack};
-unused_bitlist([Bit | Rest], Trail, Ack) ->
-%% io:format("trail Bit: ~w Rest: ~w Trail: ~w Ack:~w~n",[Bit, Rest, Trail, Ack]),
- unused_bitlist(Rest, Trail - 1, (Bit bsl Trail) bor Ack).
-
-
-%%============================================================================
-%% decode bitstring value
-%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
-%%============================================================================
-
-decode_compact_bit_string(Buffer, Range, NamedNumberList, Tags, LenIn, OptOrMand) ->
-% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_BIT_STRING}),
- decode_restricted_string(Buffer, Range, ?N_BIT_STRING, Tags, LenIn,
- NamedNumberList, OptOrMand,bin).
-
-decode_bit_string(Buffer, Range, NamedNumberList, Tags, LenIn, OptOrMand) ->
-% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_BIT_STRING}),
- decode_restricted_string(Buffer, Range, ?N_BIT_STRING, Tags, LenIn,
- NamedNumberList, OptOrMand,old).
-
-
-decode_bit_string2(1,<<0 ,Buffer/binary>>,_NamedNumberList,RemovedBytes,BinOrOld) ->
- case BinOrOld of
- bin ->
- {{0,<<>>},Buffer,RemovedBytes};
- _ ->
- {[], Buffer, RemovedBytes}
- end;
-decode_bit_string2(Len,<<Unused,Buffer/binary>>,NamedNumberList,
- RemovedBytes,BinOrOld) ->
- L = Len - 1,
- <<Bits:L/binary,BufferTail/binary>> = Buffer,
- case NamedNumberList of
- [] ->
- case BinOrOld of
- bin ->
- {{Unused,Bits},BufferTail,RemovedBytes};
- _ ->
- BitString = decode_bitstring2(L, Unused, Buffer),
- {BitString,BufferTail, RemovedBytes}
- end;
- _ ->
- BitString = decode_bitstring2(L, Unused, Buffer),
- {decode_bitstring_NNL(BitString,NamedNumberList),
- BufferTail,
- RemovedBytes}
- end.
-
-%%----------------------------------------
-%% Decode the in buffer to bits
-%%----------------------------------------
-decode_bitstring2(1,Unused,<<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,_/binary>>) ->
- lists:sublist([B7,B6,B5,B4,B3,B2,B1,B0],8-Unused);
-decode_bitstring2(Len, Unused,
- <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Buffer/binary>>) ->
- [B7, B6, B5, B4, B3, B2, B1, B0 |
- decode_bitstring2(Len - 1, Unused, Buffer)].
-
-%%decode_bitstring2(1, Unused, Buffer) ->
-%% make_bits_of_int(hd(Buffer), 128, 8-Unused);
-%%decode_bitstring2(Len, Unused, [BitVal | Buffer]) ->
-%% [B7, B6, B5, B4, B3, B2, B1, B0] = make_bits_of_int(BitVal, 128, 8),
-%% [B7, B6, B5, B4, B3, B2, B1, B0 |
-%% decode_bitstring2(Len - 1, Unused, Buffer)].
-
-
-%%make_bits_of_int(_, _, 0) ->
-%% [];
-%%make_bits_of_int(BitVal, MaskVal, Unused) when Unused > 0 ->
-%% X = case MaskVal band BitVal of
-%% 0 -> 0 ;
-%% _ -> 1
-%% end,
-%% [X | make_bits_of_int(BitVal, MaskVal bsr 1, Unused - 1)].
-
-
-
-%%----------------------------------------
-%% Decode the bitlist to names
-%%----------------------------------------
-
-
-decode_bitstring_NNL(BitList,NamedNumberList) ->
- decode_bitstring_NNL(BitList,NamedNumberList,0,[]).
-
-
-decode_bitstring_NNL([],_,_No,Result) ->
- lists:reverse(Result);
-
-decode_bitstring_NNL([B|BitList],[{Name,No}|NamedNumberList],No,Result) ->
- if
- B == 0 ->
- decode_bitstring_NNL(BitList,NamedNumberList,No+1,Result);
- true ->
- decode_bitstring_NNL(BitList,NamedNumberList,No+1,[Name|Result])
- end;
-decode_bitstring_NNL([1|BitList],NamedNumberList,No,Result) ->
- decode_bitstring_NNL(BitList,NamedNumberList,No+1,[{bit,No}|Result]);
-decode_bitstring_NNL([0|BitList],NamedNumberList,No,Result) ->
- decode_bitstring_NNL(BitList,NamedNumberList,No+1,Result).
-
-
-%%============================================================================
-%% Octet string, ITU_T X.690 Chapter 8.7
-%%
-%% encode octet string
-%% The OctetList must be a flat list of integers in the range 0..255
-%% the function does not check this because it takes to much time
-%%============================================================================
-encode_octet_string(_C, OctetList, []) when binary(OctetList) ->
- dotag_universal(?N_OCTET_STRING,OctetList,size(OctetList));
-encode_octet_string(_C, OctetList, DoTag) when binary(OctetList) ->
- dotag(DoTag, ?N_OCTET_STRING, {OctetList,size(OctetList)});
-encode_octet_string(_C, OctetList, DoTag) when list(OctetList) ->
- case length(OctetList) of
- Len when DoTag == [] ->
- dotag_universal(?N_OCTET_STRING,OctetList,Len);
- Len ->
- dotag(DoTag, ?N_OCTET_STRING, {OctetList,Len})
- end;
-% encode_octet_string(C, OctetList, DoTag) when list(OctetList) ->
-% dotag(DoTag, ?N_OCTET_STRING, {OctetList,length(OctetList)});
-encode_octet_string(C, {Name,OctetList}, DoTag) when atom(Name) ->
- encode_octet_string(C, OctetList, DoTag).
-
-
-%%============================================================================
-%% decode octet string
-%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
-%%
-%% Octet string is decoded as a restricted string
-%%============================================================================
-decode_octet_string(Buffer, Range, Tags, TotalLen, OptOrMand) ->
-% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_OCTET_STRING}),
- decode_restricted_string(Buffer, Range, ?N_OCTET_STRING,
- Tags, TotalLen, [], OptOrMand,old).
-
-%%============================================================================
-%% Null value, ITU_T X.690 Chapter 8.8
-%%
-%% encode NULL value
-%%============================================================================
-
-encode_null(_, []) ->
- {[?N_NULL,0],2};
-encode_null(_, DoTag) ->
- dotag(DoTag, ?N_NULL, {[],0}).
-
-%%============================================================================
-%% decode NULL value
-%% (Buffer, HasTag, TotalLen) -> {NULL, Remain, RemovedBytes}
-%%============================================================================
-decode_null(Buffer, Tags, OptOrMand) ->
- NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_NULL}),
- decode_null_notag(Buffer, NewTags, OptOrMand).
-
-decode_null_notag(Buffer, Tags, OptOrMand) ->
- {RestTags, {FormLen, Buffer0, Rb0}} =
- check_tags_i(Tags, Buffer, OptOrMand),
-
- case FormLen of
- {?CONSTRUCTED,Len} ->
- {_Buffer00,RestBytes} = split_list(Buffer0,Len),
- {Val01, Buffer01, Rb01} = decode_null_notag(Buffer0, RestTags,
- OptOrMand),
- {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
- {Val01, Buffer02, Rb0+Rb01+Rb02};
- {_,0} ->
- {'NULL', Buffer0, Rb0};
- {_,Len} ->
- exit({error,{asn1,{invalid_length,'NULL',Len}}})
- end.
-
-
-%%============================================================================
-%% Object identifier, ITU_T X.690 Chapter 8.19
-%%
-%% encode Object Identifier value
-%%============================================================================
-
-encode_object_identifier({Name,Val}, DoTag) when atom(Name) ->
- encode_object_identifier(Val, DoTag);
-encode_object_identifier(Val, []) ->
- {EncVal,Len} = e_object_identifier(Val),
- dotag_universal(?N_OBJECT_IDENTIFIER,EncVal,Len);
-encode_object_identifier(Val, DoTag) ->
- dotag(DoTag, ?N_OBJECT_IDENTIFIER, e_object_identifier(Val)).
-
-e_object_identifier({'OBJECT IDENTIFIER', V}) ->
- e_object_identifier(V);
-e_object_identifier({Cname, V}) when atom(Cname), tuple(V) ->
- e_object_identifier(tuple_to_list(V));
-e_object_identifier({Cname, V}) when atom(Cname), list(V) ->
- e_object_identifier(V);
-e_object_identifier(V) when tuple(V) ->
- e_object_identifier(tuple_to_list(V));
-
-%%%%%%%%%%%%%%%
-%% e_object_identifier([List of Obect Identifiers]) ->
-%% {[Encoded Octetlist of ObjIds], IntLength}
-%%
-e_object_identifier([E1, E2 | Tail]) ->
- Head = 40*E1 + E2, % wow!
- {H,Lh} = mk_object_val(Head),
- {R,Lr} = enc_obj_id_tail(Tail, [], 0),
- {[H|R], Lh+Lr}.
-
-enc_obj_id_tail([], Ack, Len) ->
- {lists:reverse(Ack), Len};
-enc_obj_id_tail([H|T], Ack, Len) ->
- {B, L} = mk_object_val(H),
- enc_obj_id_tail(T, [B|Ack], Len+L).
-
-%% e_object_identifier([List of Obect Identifiers]) ->
-%% {[Encoded Octetlist of ObjIds], IntLength}
-%%
-%%e_object_identifier([E1, E2 | Tail]) ->
-%% Head = 40*E1 + E2, % wow!
-%% F = fun(Val, AckLen) ->
-%% {L, Ack} = mk_object_val(Val),
-%% {L, Ack + AckLen}
-%% end,
-%% {Octets, Len} = lists:mapfoldl(F, 0, [Head | Tail]).
-
-%%%%%%%%%%%
-%% mk_object_val(Value) -> {OctetList, Len}
-%% returns a Val as a list of octets, the 8 bit is allways set to one except
-%% for the last octet, where its 0
-%%
-
-
-mk_object_val(Val) when Val =< 127 ->
- {[255 band Val], 1};
-mk_object_val(Val) ->
- mk_object_val(Val bsr 7, [Val band 127], 1).
-mk_object_val(0, Ack, Len) ->
- {Ack, Len};
-mk_object_val(Val, Ack, Len) ->
- mk_object_val(Val bsr 7, [((Val band 127) bor 128) | Ack], Len + 1).
-
-
-
-%%============================================================================
-%% decode Object Identifier value
-%% (Buffer, HasTag, TotalLen) -> {{ObjId}, Remain, RemovedBytes}
-%%============================================================================
-
-decode_object_identifier(Buffer, Tags, OptOrMand) ->
- NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,
- number=?N_OBJECT_IDENTIFIER}),
- decode_object_identifier_notag(Buffer, NewTags, OptOrMand).
-
-decode_object_identifier_notag(Buffer, Tags, OptOrMand) ->
- {RestTags, {FormLen, Buffer0, Rb0}} =
- check_tags_i(Tags, Buffer, OptOrMand),
-
- case FormLen of
- {?CONSTRUCTED,Len} ->
- {Buffer00,RestBytes} = split_list(Buffer0,Len),
- {Val01, Buffer01, Rb01} =
- decode_object_identifier_notag(Buffer00,
- RestTags, OptOrMand),
- {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
- {Val01, Buffer02, Rb0+Rb01+Rb02};
- {_,Len} ->
- {[AddedObjVal|ObjVals],Buffer01} =
- dec_subidentifiers(Buffer0,0,[],Len),
- {Val1, Val2} = if
- AddedObjVal < 40 ->
- {0, AddedObjVal};
- AddedObjVal < 80 ->
- {1, AddedObjVal - 40};
- true ->
- {2, AddedObjVal - 80}
- end,
- {list_to_tuple([Val1, Val2 | ObjVals]), Buffer01,
- Rb0+Len}
- end.
-
-dec_subidentifiers(Buffer,_Av,Al,0) ->
- {lists:reverse(Al),Buffer};
-dec_subidentifiers(<<1:1,H:7,T/binary>>,Av,Al,Len) ->
- dec_subidentifiers(T,(Av bsl 7) + H,Al,Len-1);
-dec_subidentifiers(<<H,T/binary>>,Av,Al,Len) ->
- dec_subidentifiers(T,0,[((Av bsl 7) + H)|Al],Len-1).
-
-
-%%dec_subidentifiers(Buffer,Av,Al,0) ->
-%% {lists:reverse(Al),Buffer};
-%%dec_subidentifiers([H|T],Av,Al,Len) when H >=16#80 ->
-%% dec_subidentifiers(T,(Av bsl 7) + (H band 16#7F),Al,Len-1);
-%%dec_subidentifiers([H|T],Av,Al,Len) ->
-%% dec_subidentifiers(T,0,[(Av bsl 7) + H |Al],Len-1).
-
-
-%%============================================================================
-%% Restricted character string types, ITU_T X.690 Chapter 8.20
-%%
-%% encode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings
-%%============================================================================
-encode_restricted_string(_C, OctetList, StringType, [])
- when binary(OctetList) ->
- dotag_universal(StringType,OctetList,size(OctetList));
-encode_restricted_string(_C, OctetList, StringType, DoTag)
- when binary(OctetList) ->
- dotag(DoTag, StringType, {OctetList, size(OctetList)});
-encode_restricted_string(_C, OctetList, StringType, [])
- when list(OctetList) ->
- dotag_universal(StringType,OctetList,length(OctetList));
-encode_restricted_string(_C, OctetList, StringType, DoTag)
- when list(OctetList) ->
- dotag(DoTag, StringType, {OctetList, length(OctetList)});
-encode_restricted_string(C,{Name,OctetL},StringType,DoTag) when atom(Name)->
- encode_restricted_string(C, OctetL, StringType, DoTag).
-
-%%============================================================================
-%% decode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings
-%% (Buffer, Range, StringType, HasTag, TotalLen) ->
-%% {String, Remain, RemovedBytes}
-%%============================================================================
-
-decode_restricted_string(Buffer, Range, StringType, Tags, LenIn, OptOrMand) ->
- {Val,Buffer2,Rb} =
- decode_restricted_string_tag(Buffer, Range, StringType, Tags,
- LenIn, [], OptOrMand,old),
- {check_and_convert_restricted_string(Val,StringType,Range,[],old),
- Buffer2,Rb}.
-
-
-decode_restricted_string(Buffer, Range, StringType, Tags, LenIn, NNList, OptOrMand, BinOrOld ) ->
- {Val,Buffer2,Rb} =
- decode_restricted_string_tag(Buffer, Range, StringType, Tags,
- LenIn, NNList, OptOrMand, BinOrOld),
- {check_and_convert_restricted_string(Val,StringType,Range,NNList,BinOrOld),
- Buffer2,Rb}.
-
-decode_restricted_string_tag(Buffer, Range, StringType, TagsIn, LenIn, NNList, OptOrMand, BinOrOld ) ->
- NewTags = new_tags(TagsIn, #tag{class=?UNIVERSAL,number=StringType}),
- decode_restricted_string_notag(Buffer, Range, StringType, NewTags,
- LenIn, NNList, OptOrMand, BinOrOld).
-
-
-
-
-check_and_convert_restricted_string(Val,StringType,Range,NamedNumberList,_BinOrOld) ->
- {StrLen,NewVal} = case StringType of
- ?N_BIT_STRING when NamedNumberList /= [] ->
- {no_check,Val};
- ?N_BIT_STRING when list(Val) ->
- {length(Val),Val};
- ?N_BIT_STRING when tuple(Val) ->
- {(size(element(2,Val))*8) - element(1,Val),Val};
- _ when binary(Val) ->
- {size(Val),binary_to_list(Val)};
- _ when list(Val) ->
- {length(Val), Val}
- end,
- case Range of
- _ when StrLen == no_check ->
- NewVal;
- [] -> % No length constraint
- NewVal;
- {Lb,Ub} when StrLen >= Lb, Ub >= StrLen -> % variable length constraint
- NewVal;
- {{Lb,_Ub},[]} when StrLen >= Lb ->
- NewVal;
- {{Lb1,Ub1},{Lb2,Ub2}} when StrLen >= Lb1, StrLen =< Ub1;
- StrLen =< Ub2, StrLen >= Lb2 ->
- NewVal;
- StrLen -> % fixed length constraint
- NewVal;
- {_,_} ->
- exit({error,{asn1,{length,Range,Val}}});
- _Len when integer(_Len) ->
- exit({error,{asn1,{length,Range,Val}}});
- _ -> % some strange constraint that we don't support yet
- NewVal
- end.
-
-
-%%=============================================================================
-%% Common routines for several string types including bit string
-%% handles indefinite length
-%%=============================================================================
-
-
-decode_restricted_string_notag(Buffer, _Range, StringType, TagsIn,
- _, NamedNumberList, OptOrMand,BinOrOld) ->
- %%-----------------------------------------------------------
- %% Get inner (the implicit tag or no tag) and
- %% outer (the explicit tag) lengths.
- %%-----------------------------------------------------------
- {RestTags, {FormLength={_,_Len01}, Buffer0, Rb0}} =
- check_tags_i(TagsIn, Buffer, OptOrMand),
-
- case FormLength of
- {?CONSTRUCTED,Len} ->
- {Buffer00, RestBytes} = split_list(Buffer0,Len),
- {Val01, Buffer01, Rb01} =
- decode_restricted_parts(Buffer00, RestBytes, [], StringType,
- RestTags,
- Len, NamedNumberList,
- OptOrMand,
- BinOrOld, 0, []),
- {Val01, Buffer01, Rb0+Rb01};
- {_, Len} ->
- {Val01, Buffer01, Rb01} =
- decode_restricted(Buffer0, Len, StringType,
- NamedNumberList, BinOrOld),
- {Val01, Buffer01, Rb0+Rb01}
- end.
-
-
-decode_restricted_parts(Buffer, RestBytes, [], StringType, RestTags, Len, NNList,
- OptOrMand, BinOrOld, AccRb, AccVal) ->
- DecodeFun = case RestTags of
- [] -> fun decode_restricted_string_tag/8;
- _ -> fun decode_restricted_string_notag/8
- end,
- {Val, Buffer1, Rb} =
- DecodeFun(Buffer, [], StringType, RestTags,
- no_length, NNList,
- OptOrMand, BinOrOld),
- {Buffer2,More} =
- case Buffer1 of
- <<0,0,Buffer10/binary>> when Len == indefinite ->
- {Buffer10,false};
- <<>> ->
- {RestBytes,false};
- _ ->
- {Buffer1,true}
- end,
- {NewVal, NewRb} =
- case StringType of
- ?N_BIT_STRING when BinOrOld == bin ->
- {concat_bit_binaries(AccVal, Val), AccRb+Rb};
- _ when binary(Val),binary(AccVal) ->
- {<<AccVal/binary,Val/binary>>,AccRb+Rb};
- _ when binary(Val), AccVal==[] ->
- {Val,AccRb+Rb};
- _ ->
- {AccVal++Val, AccRb+Rb}
- end,
- case More of
- false ->
- {NewVal, Buffer2, NewRb};
- true ->
- decode_restricted_parts(Buffer2, RestBytes, [], StringType, RestTags, Len, NNList,
- OptOrMand, BinOrOld, NewRb, NewVal)
- end.
-
-
-
-decode_restricted(Buffer, InnerLen, StringType, NamedNumberList,BinOrOld) ->
-
- case StringType of
- ?N_BIT_STRING ->
- decode_bit_string2(InnerLen,Buffer,NamedNumberList,InnerLen,BinOrOld);
-
- ?N_UniversalString ->
- <<PreBuff:InnerLen/binary,RestBuff/binary>> = Buffer,%%added for binary
- UniString = mk_universal_string(binary_to_list(PreBuff)),
- {UniString,RestBuff,InnerLen};
- ?N_BMPString ->
- <<PreBuff:InnerLen/binary,RestBuff/binary>> = Buffer,%%added for binary
- BMP = mk_BMP_string(binary_to_list(PreBuff)),
- {BMP,RestBuff,InnerLen};
- _ ->
- <<PreBuff:InnerLen/binary,RestBuff/binary>> = Buffer,%%added for binary
- {PreBuff, RestBuff, InnerLen}
- end.
-
-
-
-%%============================================================================
-%% encode Universal string
-%%============================================================================
-
-encode_universal_string(C, {Name, Universal}, DoTag) when atom(Name) ->
- encode_universal_string(C, Universal, DoTag);
-encode_universal_string(_C, Universal, []) ->
- OctetList = mk_uni_list(Universal),
- dotag_universal(?N_UniversalString,OctetList,length(OctetList));
-encode_universal_string(_C, Universal, DoTag) ->
- OctetList = mk_uni_list(Universal),
- dotag(DoTag, ?N_UniversalString, {OctetList,length(OctetList)}).
-
-mk_uni_list(In) ->
- mk_uni_list(In,[]).
-
-mk_uni_list([],List) ->
- lists:reverse(List);
-mk_uni_list([{A,B,C,D}|T],List) ->
- mk_uni_list(T,[D,C,B,A|List]);
-mk_uni_list([H|T],List) ->
- mk_uni_list(T,[H,0,0,0|List]).
-
-%%===========================================================================
-%% decode Universal strings
-%% (Buffer, Range, StringType, HasTag, LenIn) ->
-%% {String, Remain, RemovedBytes}
-%%===========================================================================
-
-decode_universal_string(Buffer, Range, Tags, LenIn, OptOrMand) ->
-% NewTags = new_tags(HasTag, #tag{class=?UNIVERSAL,number=?N_UniversalString}),
- decode_restricted_string(Buffer, Range, ?N_UniversalString,
- Tags, LenIn, [], OptOrMand,old).
-
-
-mk_universal_string(In) ->
- mk_universal_string(In,[]).
-
-mk_universal_string([],Acc) ->
- lists:reverse(Acc);
-mk_universal_string([0,0,0,D|T],Acc) ->
- mk_universal_string(T,[D|Acc]);
-mk_universal_string([A,B,C,D|T],Acc) ->
- mk_universal_string(T,[{A,B,C,D}|Acc]).
-
-
-%%============================================================================
-%% encode BMP string
-%%============================================================================
-
-encode_BMP_string(C, {Name,BMPString}, DoTag) when atom(Name)->
- encode_BMP_string(C, BMPString, DoTag);
-encode_BMP_string(_C, BMPString, []) ->
- OctetList = mk_BMP_list(BMPString),
- dotag_universal(?N_BMPString,OctetList,length(OctetList));
-encode_BMP_string(_C, BMPString, DoTag) ->
- OctetList = mk_BMP_list(BMPString),
- dotag(DoTag, ?N_BMPString, {OctetList,length(OctetList)}).
-
-mk_BMP_list(In) ->
- mk_BMP_list(In,[]).
-
-mk_BMP_list([],List) ->
- lists:reverse(List);
-mk_BMP_list([{0,0,C,D}|T],List) ->
- mk_BMP_list(T,[D,C|List]);
-mk_BMP_list([H|T],List) ->
- mk_BMP_list(T,[H,0|List]).
-
-%%============================================================================
-%% decode (OctetList, Range(ignored), tag|notag) -> {ValList, RestList}
-%% (Buffer, Range, StringType, HasTag, TotalLen) ->
-%% {String, Remain, RemovedBytes}
-%%============================================================================
-decode_BMP_string(Buffer, Range, Tags, LenIn, OptOrMand) ->
-% NewTags = new_tags(HasTag, #tag{class=?UNIVERSAL,number=?N_BMPString}),
- decode_restricted_string(Buffer, Range, ?N_BMPString,
- Tags, LenIn, [], OptOrMand,old).
-
-mk_BMP_string(In) ->
- mk_BMP_string(In,[]).
-
-mk_BMP_string([],US) ->
- lists:reverse(US);
-mk_BMP_string([0,B|T],US) ->
- mk_BMP_string(T,[B|US]);
-mk_BMP_string([C,D|T],US) ->
- mk_BMP_string(T,[{0,0,C,D}|US]).
-
-
-%%============================================================================
-%% Generalized time, ITU_T X.680 Chapter 39
-%%
-%% encode Generalized time
-%%============================================================================
-
-encode_generalized_time(C, {Name,OctetList}, DoTag) when atom(Name) ->
- encode_generalized_time(C, OctetList, DoTag);
-encode_generalized_time(_C, OctetList, []) ->
- dotag_universal(?N_GeneralizedTime,OctetList,length(OctetList));
-encode_generalized_time(_C, OctetList, DoTag) ->
- dotag(DoTag, ?N_GeneralizedTime, {OctetList,length(OctetList)}).
-
-%%============================================================================
-%% decode Generalized time
-%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
-%%============================================================================
-
-decode_generalized_time(Buffer, Range, Tags, TotalLen, OptOrMand) ->
- NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,
- number=?N_GeneralizedTime}),
- decode_generalized_time_notag(Buffer, Range, NewTags, TotalLen, OptOrMand).
-
-decode_generalized_time_notag(Buffer, Range, Tags, TotalLen, OptOrMand) ->
- {RestTags, {FormLen, Buffer0, Rb0}} =
- check_tags_i(Tags, Buffer, OptOrMand),
-
- case FormLen of
- {?CONSTRUCTED,Len} ->
- {Buffer00,RestBytes} = split_list(Buffer0,Len),
- {Val01, Buffer01, Rb01} =
- decode_generalized_time_notag(Buffer00, Range,
- RestTags, TotalLen,
- OptOrMand),
- {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
- {Val01, Buffer02, Rb0+Rb01+Rb02};
- {_,Len} ->
- <<PreBuff:Len/binary,RestBuff/binary>> = Buffer0,
- {binary_to_list(PreBuff), RestBuff, Rb0+Len}
- end.
-
-%%============================================================================
-%% Universal time, ITU_T X.680 Chapter 40
-%%
-%% encode UTC time
-%%============================================================================
-
-encode_utc_time(C, {Name,OctetList}, DoTag) when atom(Name) ->
- encode_utc_time(C, OctetList, DoTag);
-encode_utc_time(_C, OctetList, []) ->
- dotag_universal(?N_UTCTime, OctetList,length(OctetList));
-encode_utc_time(_C, OctetList, DoTag) ->
- dotag(DoTag, ?N_UTCTime, {OctetList,length(OctetList)}).
-
-%%============================================================================
-%% decode UTC time
-%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
-%%============================================================================
-
-decode_utc_time(Buffer, Range, Tags, TotalLen, OptOrMand) ->
- NewTags = new_tags(Tags,#tag{class=?UNIVERSAL,number=?N_UTCTime}),
- decode_utc_time_notag(Buffer, Range, NewTags, TotalLen, OptOrMand).
-
-decode_utc_time_notag(Buffer, Range, Tags, TotalLen, OptOrMand) ->
- {RestTags, {FormLen, Buffer0, Rb0}} =
- check_tags_i(Tags, Buffer, OptOrMand),
-
- case FormLen of
- {?CONSTRUCTED,Len} ->
- {Buffer00,RestBytes} = split_list(Buffer0,Len),
- {Val01, Buffer01, Rb01} =
- decode_utc_time_notag(Buffer00, Range,
- RestTags, TotalLen,
- OptOrMand),
- {Buffer02, Rb02} = restbytes2(RestBytes,Buffer01,noext),
- {Val01, Buffer02, Rb0+Rb01+Rb02};
- {_,Len} ->
- <<PreBuff:Len/binary,RestBuff/binary>> = Buffer0,
- {binary_to_list(PreBuff), RestBuff, Rb0+Len}
- end.
-
-
-%%============================================================================
-%% Length handling
-%%
-%% Encode length
-%%
-%% encode_length(Int | indefinite) ->
-%% [<127]| [128 + Int (<127),OctetList] | [16#80]
-%%============================================================================
-
-encode_length(indefinite) ->
- {[16#80],1}; % 128
-encode_length(L) when L =< 16#7F ->
- {[L],1};
-encode_length(L) ->
- Oct = minimum_octets(L),
- Len = length(Oct),
- if
- Len =< 126 ->
- {[ (16#80+Len) | Oct ],Len+1};
- true ->
- exit({error,{asn1, to_long_length_oct, Len}})
- end.
-
-
-%% Val must be >= 0
-minimum_octets(Val) ->
- minimum_octets(Val,[]).
-
-minimum_octets(0,Acc) ->
- Acc;
-minimum_octets(Val, Acc) ->
- minimum_octets((Val bsr 8),[Val band 16#FF | Acc]).
-
-
-%%===========================================================================
-%% Decode length
-%%
-%% decode_length(OctetList) -> {{indefinite, RestOctetsL}, NoRemovedBytes} |
-%% {{Length, RestOctetsL}, NoRemovedBytes}
-%%===========================================================================
-
-decode_length(<<1:1,0:7,T/binary>>) ->
- {{indefinite, T}, 1};
-decode_length(<<0:1,Length:7,T/binary>>) ->
- {{Length,T},1};
-decode_length(<<1:1,LL:7,T/binary>>) ->
- <<Length:LL/unit:8,Rest/binary>> = T,
- {{Length,Rest}, LL+1}.
-
-%decode_length([128 | T]) ->
-% {{indefinite, T},1};
-%decode_length([H | T]) when H =< 127 ->
-% {{H, T},1};
-%decode_length([H | T]) ->
-% dec_long_length(H band 16#7F, T, 0, 1).
-
-
-%%dec_long_length(0, Buffer, Acc, Len) ->
-%% {{Acc, Buffer},Len};
-%%dec_long_length(Bytes, [H | T], Acc, Len) ->
-%% dec_long_length(Bytes - 1, T, (Acc bsl 8) + H, Len+1).
-
-%%===========================================================================
-%% Decode tag and length
-%%
-%% decode_tag_and_length(Buffer) -> {Tag, Len, RemainingBuffer, RemovedBytes}
-%%
-%%===========================================================================
-
-decode_tag_and_length(Buffer) ->
- {Tag, Buffer2, RemBytesTag} = decode_tag(Buffer),
- {{Len, Buffer3}, RemBytesLen} = decode_length(Buffer2),
- {Tag, Len, Buffer3, RemBytesTag+RemBytesLen}.
-
-
-%%============================================================================
-%% Check if valid tag
-%%
-%% check_if_valid_tag(Tag, List_of_valid_tags, OptOrMand) -> name of the tag
-%%===============================================================================
-
-check_if_valid_tag(<<0,0,_/binary>>,_,_) ->
- asn1_EOC;
-check_if_valid_tag(<<>>, _, OptOrMand) ->
- check_if_valid_tag2(false,[],[],OptOrMand);
-check_if_valid_tag(Bytes, ListOfTags, OptOrMand) when binary(Bytes) ->
- {Tag, _, _} = decode_tag(Bytes),
- check_if_valid_tag(Tag, ListOfTags, OptOrMand);
-
-%% This alternative should be removed in the near future
-%% Bytes as input should be the only necessary call
-check_if_valid_tag(Tag, ListOfTags, OptOrMand) ->
- {Class, _Form, TagNo} = Tag,
- C = code_class(Class),
- T = case C of
- 'UNIVERSAL' ->
- code_type(TagNo);
- _ ->
- TagNo
- end,
- check_if_valid_tag2({C,T}, ListOfTags, Tag, OptOrMand).
-
-check_if_valid_tag2(_Class_TagNo, [], Tag, mandatory) ->
- exit({error,{asn1,{invalid_tag,Tag}}});
-check_if_valid_tag2(_Class_TagNo, [], Tag, _) ->
- exit({error,{asn1,{no_optional_tag,Tag}}});
-
-check_if_valid_tag2(Class_TagNo, [{TagName,TagList}|T], Tag, OptOrMand) ->
- case check_if_valid_tag_loop(Class_TagNo, TagList) of
- true ->
- TagName;
- false ->
- check_if_valid_tag2(Class_TagNo, T, Tag, OptOrMand)
- end.
-
-check_if_valid_tag_loop(_Class_TagNo,[]) ->
- false;
-check_if_valid_tag_loop(Class_TagNo,[H|T]) ->
- %% It is not possible to distinguish between SEQUENCE OF and SEQUENCE, and
- %% between SET OF and SET because both are coded as 16 and 17, respectively.
- H_without_OF = case H of
- {C, 'SEQUENCE OF'} ->
- {C, 'SEQUENCE'};
- {C, 'SET OF'} ->
- {C, 'SET'};
- Else ->
- Else
- end,
-
- case H_without_OF of
- Class_TagNo ->
- true;
- {_,_} ->
- check_if_valid_tag_loop(Class_TagNo,T);
- _ ->
- check_if_valid_tag_loop(Class_TagNo,H),
- check_if_valid_tag_loop(Class_TagNo,T)
- end.
-
-
-
-code_class(0) -> 'UNIVERSAL';
-code_class(16#40) -> 'APPLICATION';
-code_class(16#80) -> 'CONTEXT';
-code_class(16#C0) -> 'PRIVATE'.
-
-
-code_type(1) -> 'BOOLEAN';
-code_type(2) -> 'INTEGER';
-code_type(3) -> 'BIT STRING';
-code_type(4) -> 'OCTET STRING';
-code_type(5) -> 'NULL';
-code_type(6) -> 'OBJECT IDENTIFIER';
-code_type(7) -> 'OBJECT DESCRIPTOR';
-code_type(8) -> 'EXTERNAL';
-code_type(9) -> 'REAL';
-code_type(10) -> 'ENUMERATED';
-code_type(11) -> 'EMBEDDED_PDV';
-code_type(16) -> 'SEQUENCE';
-code_type(16) -> 'SEQUENCE OF';
-code_type(17) -> 'SET';
-code_type(17) -> 'SET OF';
-code_type(18) -> 'NumericString';
-code_type(19) -> 'PrintableString';
-code_type(20) -> 'TeletexString';
-code_type(21) -> 'VideotexString';
-code_type(22) -> 'IA5String';
-code_type(23) -> 'UTCTime';
-code_type(24) -> 'GeneralizedTime';
-code_type(25) -> 'GraphicString';
-code_type(26) -> 'VisibleString';
-code_type(27) -> 'GeneralString';
-code_type(28) -> 'UniversalString';
-code_type(30) -> 'BMPString';
-code_type(Else) -> exit({error,{asn1,{unrecognized_type,Else}}}).
-
-%%-------------------------------------------------------------------------
-%% decoding of the components of a SET
-%%-------------------------------------------------------------------------
-
-decode_set(Rb, indefinite, <<0,0,Bytes/binary>>, _OptOrMand, _Fun3, Acc) ->
- {lists:reverse(Acc),Bytes,Rb+2};
-
-decode_set(Rb, indefinite, Bytes, OptOrMand, Fun3, Acc) ->
- {Term, Remain, Rb1} = Fun3(Bytes, OptOrMand),
- decode_set(Rb+Rb1, indefinite, Remain, OptOrMand, Fun3, [Term|Acc]);
-
-decode_set(Rb, Num, Bytes, _OptOrMand, _Fun3, Acc) when Num == 0 ->
- {lists:reverse(Acc), Bytes, Rb};
-
-decode_set(_, Num, _, _, _, _) when Num < 0 ->
- exit({error,{asn1,{length_error,'SET'}}});
-
-decode_set(Rb, Num, Bytes, OptOrMand, Fun3, Acc) ->
- {Term, Remain, Rb1} = Fun3(Bytes, OptOrMand),
- decode_set(Rb+Rb1, Num-Rb1, Remain, OptOrMand, Fun3, [Term|Acc]).
-
-
-%%-------------------------------------------------------------------------
-%% decoding of SEQUENCE OF and SET OF
-%%-------------------------------------------------------------------------
-
-decode_components(Rb, indefinite, <<0,0,Bytes/binary>>, _Fun3, _TagIn, Acc) ->
- {lists:reverse(Acc),Bytes,Rb+2};
-
-decode_components(Rb, indefinite, Bytes, Fun3, TagIn, Acc) ->
- {Term, Remain, Rb1} = Fun3(Bytes, mandatory, TagIn),
- decode_components(Rb+Rb1, indefinite, Remain, Fun3, TagIn, [Term|Acc]);
-
-decode_components(Rb, Num, Bytes, _Fun3, _TagIn, Acc) when Num == 0 ->
- {lists:reverse(Acc), Bytes, Rb};
-
-decode_components(_, Num, _, _, _, _) when Num < 0 ->
- exit({error,{asn1,{length_error,'SET/SEQUENCE OF'}}});
-
-decode_components(Rb, Num, Bytes, Fun3, TagIn, Acc) ->
- {Term, Remain, Rb1} = Fun3(Bytes, mandatory, TagIn),
- decode_components(Rb+Rb1, Num-Rb1, Remain, Fun3, TagIn, [Term|Acc]).
-
-%%decode_components(Rb, indefinite, [0,0|Bytes], _Fun3, _TagIn, Acc) ->
-%% {lists:reverse(Acc),Bytes,Rb+2};
-
-decode_components(Rb, indefinite, <<0,0,Bytes/binary>>, _Fun4, _TagIn, _Fun, Acc) ->
- {lists:reverse(Acc),Bytes,Rb+2};
-
-decode_components(Rb, indefinite, Bytes, _Fun4, TagIn, _Fun, Acc) ->
- {Term, Remain, Rb1} = _Fun4(Bytes, mandatory, TagIn, _Fun),
- decode_components(Rb+Rb1, indefinite, Remain, _Fun4, TagIn, _Fun, [Term|Acc]);
-
-decode_components(Rb, Num, Bytes, _Fun4, _TagIn, _Fun, Acc) when Num == 0 ->
- {lists:reverse(Acc), Bytes, Rb};
-
-decode_components(_, Num, _, _, _, _, _) when Num < 0 ->
- exit({error,{asn1,{length_error,'SET/SEQUENCE OF'}}});
-
-decode_components(Rb, Num, Bytes, _Fun4, TagIn, _Fun, Acc) ->
- {Term, Remain, Rb1} = _Fun4(Bytes, mandatory, TagIn, _Fun),
- decode_components(Rb+Rb1, Num-Rb1, Remain, _Fun4, TagIn, _Fun, [Term|Acc]).
-
-
-
-%%-------------------------------------------------------------------------
-%% INTERNAL HELPER FUNCTIONS (not exported)
-%%-------------------------------------------------------------------------
-
-
-%%==========================================================================
-%% Encode tag
-%%
-%% dotag(tag | notag, TagValpattern | TagValTuple, [Length, Value]) -> [Tag]
-%% TagValPattern is a correct bitpattern for a tag
-%% TagValTuple is a tuple of three bitpatterns, Class, Form and TagNo where
-%% Class = UNIVERSAL | APPLICATION | CONTEXT | PRIVATE
-%% Form = Primitive | Constructed
-%% TagNo = Number of tag
-%%==========================================================================
-
-
-dotag([], Tag, {Bytes,Len}) ->
- dotag_universal(Tag,Bytes,Len);
-dotag(Tags, Tag, {Bytes,Len}) ->
- encode_tags(Tags ++ [#tag{class=?UNIVERSAL,number=Tag,form=?PRIMITIVE}],
- Bytes, Len);
-
-dotag(Tags, Tag, Bytes) ->
- encode_tags(Tags ++ [#tag{class=?UNIVERSAL,number=Tag,form=?PRIMITIVE}],
- Bytes, size(Bytes)).
-
-dotag_universal(UniversalTag,Bytes,Len) when Len =< 16#7F->
- {[UniversalTag,Len,Bytes],2+Len};
-dotag_universal(UniversalTag,Bytes,Len) ->
- {EncLen,LenLen}=encode_length(Len),
- {[UniversalTag,EncLen,Bytes],1+LenLen+Len}.
-
-%% decoding postitive integer values.
-decode_integer2(Len,Bin = <<0:1,_:7,_Bs/binary>>,RemovedBytes) ->
- <<Int:Len/unit:8,Buffer2/binary>> = Bin,
- {Int,Buffer2,RemovedBytes};
-%% decoding negative integer values.
-decode_integer2(Len,<<1:1,B2:7,Bs/binary>>,RemovedBytes) ->
- <<N:Len/unit:8,Buffer2/binary>> = <<B2,Bs/binary>>,
- Int = N - (1 bsl (8 * Len - 1)),
- {Int,Buffer2,RemovedBytes}.
-
-%%decode_integer2(Len,Buffer,Acc,RemovedBytes) when (hd(Buffer) band 16#FF) =< 16#7F ->
-%% {decode_integer_pos(Buffer, 8 * (Len - 1)),skip(Buffer,Len),RemovedBytes};
-%%decode_integer2(Len,Buffer,Acc,RemovedBytes) ->
-%% {decode_integer_neg(Buffer, 8 * (Len - 1)),skip(Buffer,Len),RemovedBytes}.
-
-%%decode_integer_pos([Byte|Tail], Shift) ->
-%% (Byte bsl Shift) bor decode_integer_pos(Tail, Shift-8);
-%%decode_integer_pos([], _) -> 0.
-
-
-%%decode_integer_neg([Byte|Tail], Shift) ->
-%% (-128 + (Byte band 127) bsl Shift) bor decode_integer_pos(Tail, Shift-8).
-
-
-concat_bit_binaries([],Bin={_,_}) ->
- Bin;
-concat_bit_binaries({0,B1},{U2,B2}) ->
- {U2,<<B1/binary,B2/binary>>};
-concat_bit_binaries({U1,B1},{U2,B2}) ->
- S1 = (size(B1) * 8) - U1,
- S2 = (size(B2) * 8) - U2,
- PadBits = 8 - ((S1+S2) rem 8),
- {PadBits, <<B1:S1/binary-unit:1,B2:S2/binary-unit:1,0:PadBits>>};
-concat_bit_binaries(L1,L2) when list(L1),list(L2) ->
- %% this case occur when decoding with NNL
- L1 ++ L2.
-
-
-get_constraint(C,Key) ->
- case lists:keysearch(Key,1,C) of
- false ->
- no;
- {value,{_,V}} ->
- V
- end.
-
-%%skip(Buffer, 0) ->
-%% Buffer;
-%%skip([H | T], Len) ->
-%% skip(T, Len-1).
-
-new_tags([],LastTag) ->
- [LastTag];
-new_tags(Tags=[#tag{type='IMPLICIT'}],_LastTag) ->
- Tags;
-new_tags([T1 = #tag{type='IMPLICIT'},#tag{type=T2Type}|Rest],LastTag) ->
- new_tags([T1#tag{type=T2Type}|Rest],LastTag);
-new_tags(Tags,LastTag) ->
- case lists:last(Tags) of
- #tag{type='IMPLICIT'} ->
- Tags;
- _ ->
- Tags ++ [LastTag]
- end.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_ber_bin_v2.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_ber_bin_v2.erl
deleted file mode 100644
index 7f7846184a..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_ber_bin_v2.erl
+++ /dev/null
@@ -1,1869 +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: asn1rt_ber_bin_v2.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
-%%
--module(asn1rt_ber_bin_v2).
-
-%% encoding / decoding of BER
-
--export([decode/1, decode/2, match_tags/2, encode/1]).
--export([fixoptionals/2, cindex/3,
- list_to_record/2,
- encode_tag_val/1,
- encode_tags/3]).
--export([encode_boolean/2,decode_boolean/2,
- encode_integer/3,encode_integer/4,
- decode_integer/3, decode_integer/4,
- encode_enumerated/2,
- encode_enumerated/4,decode_enumerated/4,
- encode_real/2,decode_real/3,
- encode_bit_string/4,decode_bit_string/4,
- decode_compact_bit_string/4,
- encode_octet_string/3,decode_octet_string/3,
- encode_null/2,decode_null/2,
- encode_object_identifier/2,decode_object_identifier/2,
- encode_restricted_string/4,decode_restricted_string/4,
- encode_universal_string/3,decode_universal_string/3,
- encode_BMP_string/3,decode_BMP_string/3,
- encode_generalized_time/3,decode_generalized_time/3,
- encode_utc_time/3,decode_utc_time/3,
- encode_length/1,decode_length/1,
- decode_tag_and_length/1]).
-
--export([encode_open_type/1,encode_open_type/2,
- decode_open_type/2,decode_open_type_as_binary/2]).
-
--export([decode_primitive_incomplete/2]).
-
--include("asn1_records.hrl").
-
-% the encoding of class of tag bits 8 and 7
--define(UNIVERSAL, 0).
--define(APPLICATION, 16#40).
--define(CONTEXT, 16#80).
--define(PRIVATE, 16#C0).
-
-%%% primitive or constructed encoding % bit 6
--define(PRIMITIVE, 0).
--define(CONSTRUCTED, 2#00100000).
-
-%%% The tag-number for universal types
--define(N_BOOLEAN, 1).
--define(N_INTEGER, 2).
--define(N_BIT_STRING, 3).
--define(N_OCTET_STRING, 4).
--define(N_NULL, 5).
--define(N_OBJECT_IDENTIFIER, 6).
--define(N_OBJECT_DESCRIPTOR, 7).
--define(N_EXTERNAL, 8).
--define(N_REAL, 9).
--define(N_ENUMERATED, 10).
--define(N_EMBEDDED_PDV, 11).
--define(N_SEQUENCE, 16).
--define(N_SET, 17).
--define(N_NumericString, 18).
--define(N_PrintableString, 19).
--define(N_TeletexString, 20).
--define(N_VideotexString, 21).
--define(N_IA5String, 22).
--define(N_UTCTime, 23).
--define(N_GeneralizedTime, 24).
--define(N_GraphicString, 25).
--define(N_VisibleString, 26).
--define(N_GeneralString, 27).
--define(N_UniversalString, 28).
--define(N_BMPString, 30).
-
-
-% the complete tag-word of built-in types
--define(T_BOOLEAN, ?UNIVERSAL bor ?PRIMITIVE bor 1).
--define(T_INTEGER, ?UNIVERSAL bor ?PRIMITIVE bor 2).
--define(T_BIT_STRING, ?UNIVERSAL bor ?PRIMITIVE bor 3). % can be CONSTRUCTED
--define(T_OCTET_STRING, ?UNIVERSAL bor ?PRIMITIVE bor 4). % can be CONSTRUCTED
--define(T_NULL, ?UNIVERSAL bor ?PRIMITIVE bor 5).
--define(T_OBJECT_IDENTIFIER,?UNIVERSAL bor ?PRIMITIVE bor 6).
--define(T_OBJECT_DESCRIPTOR,?UNIVERSAL bor ?PRIMITIVE bor 7).
--define(T_EXTERNAL, ?UNIVERSAL bor ?PRIMITIVE bor 8).
--define(T_REAL, ?UNIVERSAL bor ?PRIMITIVE bor 9).
--define(T_ENUMERATED, ?UNIVERSAL bor ?PRIMITIVE bor 10).
--define(T_EMBEDDED_PDV, ?UNIVERSAL bor ?PRIMITIVE bor 11).
--define(T_SEQUENCE, ?UNIVERSAL bor ?CONSTRUCTED bor 16).
--define(T_SET, ?UNIVERSAL bor ?CONSTRUCTED bor 17).
--define(T_NumericString, ?UNIVERSAL bor ?PRIMITIVE bor 18). %can be constructed
--define(T_PrintableString, ?UNIVERSAL bor ?PRIMITIVE bor 19). %can be constructed
--define(T_TeletexString, ?UNIVERSAL bor ?PRIMITIVE bor 20). %can be constructed
--define(T_VideotexString, ?UNIVERSAL bor ?PRIMITIVE bor 21). %can be constructed
--define(T_IA5String, ?UNIVERSAL bor ?PRIMITIVE bor 22). %can be constructed
--define(T_UTCTime, ?UNIVERSAL bor ?PRIMITIVE bor 23).
--define(T_GeneralizedTime, ?UNIVERSAL bor ?PRIMITIVE bor 24).
--define(T_GraphicString, ?UNIVERSAL bor ?PRIMITIVE bor 25). %can be constructed
--define(T_VisibleString, ?UNIVERSAL bor ?PRIMITIVE bor 26). %can be constructed
--define(T_GeneralString, ?UNIVERSAL bor ?PRIMITIVE bor 27). %can be constructed
--define(T_UniversalString, ?UNIVERSAL bor ?PRIMITIVE bor 28). %can be constructed
--define(T_BMPString, ?UNIVERSAL bor ?PRIMITIVE bor 30). %can be constructed
-
-% encode(Tlv={_Tag={?PRIMITIVE,_},_VList}) ->
-% encode_primitive(Tlv);
-% encode(Tlv) ->
-% encode_constructed(Tlv).
-
-encode([Tlv]) ->
- encode(Tlv);
-encode({TlvTag,TlvVal}) when list(TlvVal) ->
- %% constructed form of value
- encode_tlv(TlvTag,TlvVal,?CONSTRUCTED);
-encode({TlvTag,TlvVal}) ->
- encode_tlv(TlvTag,TlvVal,?PRIMITIVE);
-encode(Bin) when binary(Bin) ->
- Bin.
-
-encode_tlv(TlvTag,TlvVal,Form) ->
- Tag = encode_tlv_tag(TlvTag,Form),
- {Val,VLen} = encode_tlv_val(TlvVal),
- {Len,_LLen} = encode_length(VLen),
- BinLen = list_to_binary(Len),
- <<Tag/binary,BinLen/binary,Val/binary>>.
-
-encode_tlv_tag(ClassTagNo,Form) ->
- Class = ClassTagNo bsr 16,
- case encode_tag_val({Class bsl 6,Form,(ClassTagNo - (Class bsl 16))}) of
- T when list(T) ->
- list_to_binary(T);
- T ->
- T
- end.
-
-encode_tlv_val(TlvL) when list(TlvL) ->
- encode_tlv_list(TlvL,[]);
-encode_tlv_val(Bin) ->
- {Bin,size(Bin)}.
-
-encode_tlv_list([Tlv|Tlvs],Acc) ->
- EncTlv = encode(Tlv),
- encode_tlv_list(Tlvs,[EncTlv|Acc]);
-encode_tlv_list([],Acc) ->
- Bin=list_to_binary(lists:reverse(Acc)),
- {Bin,size(Bin)}.
-
-% encode_primitive({{_,ClassTagNo},V}) ->
-% Len = size(V), % not sufficient as length encode
-% Class = ClassTagNo bsr 16,
-% {TagLen,Tag} =
-% case encode_tag_val({Class,?PRIMITIVE,ClassTagNo - Class}) of
-% T when list(T) ->
-% {length(T),list_to_binary(T)};
-% T ->
-% {1,T}
-% end,
-
-
-decode(B,driver) ->
- case catch port_control(drv_complete,2,B) of
- Bin when binary(Bin) ->
- binary_to_term(Bin);
- List when list(List) -> handle_error(List,B);
- {'EXIT',{badarg,Reason}} ->
- asn1rt_driver_handler:load_driver(),
- receive
- driver_ready ->
- case catch port_control(drv_complete,2,B) of
- Bin2 when binary(Bin2) -> binary_to_term(Bin2);
- List when list(List) -> handle_error(List,B);
- Error -> exit(Error)
- end;
- {error,Error} -> % error when loading driver
- %% the driver could not be loaded
- exit(Error);
- Error={port_error,Reason} ->
- exit(Error)
- end;
- {'EXIT',Reason} ->
- exit(Reason)
- end.
-
-handle_error([],_)->
- exit({error,{"memory allocation problem"}});
-handle_error([$1|_],L) -> % error in driver
- exit({error,{asn1_error,L}});
-handle_error([$2|_],L) -> % error in driver due to wrong tag
- exit({error,{asn1_error,{"bad tag",L}}});
-handle_error([$3|_],L) -> % error in driver due to length error
- exit({error,{asn1_error,{"bad length field",L}}});
-handle_error([$4|_],L) -> % error in driver due to indefinite length error
- exit({error,{asn1_error,{"indefinite length without end bytes",L}}});
-handle_error(ErrL,L) ->
- exit({error,{unknown_error,ErrL,L}}).
-
-
-decode(Bin) when binary(Bin) ->
- decode_primitive(Bin);
-decode(Tlv) -> % assume it is a tlv
- {Tlv,<<>>}.
-
-
-decode_primitive(Bin) ->
- {{Form,TagNo,Len,V},Rest} = decode_tlv(Bin),
- case Form of
- 1 when Len == indefinite -> % constructed
- {Vlist,Rest2} = decode_constructed_indefinite(V,[]),
- {{TagNo,Vlist},Rest2};
- 1 -> % constructed
- {{TagNo,decode_constructed(V)},Rest};
- 0 -> % primitive
- {{TagNo,V},Rest}
- end.
-
-decode_constructed(<<>>) ->
- [];
-decode_constructed(Bin) ->
- {Tlv,Rest} = decode_primitive(Bin),
- [Tlv|decode_constructed(Rest)].
-
-decode_constructed_indefinite(<<0,0,Rest/binary>>,Acc) ->
- {lists:reverse(Acc),Rest};
-decode_constructed_indefinite(Bin,Acc) ->
- {Tlv,Rest} = decode_primitive(Bin),
- decode_constructed_indefinite(Rest, [Tlv|Acc]).
-
-decode_tlv(Bin) ->
- {Form,TagNo,Len,Bin2} = decode_tag_and_length(Bin),
- case Len of
- indefinite ->
- {{Form,TagNo,Len,Bin2},[]};
- _ ->
- <<V:Len/binary,Bin3/binary>> = Bin2,
- {{Form,TagNo,Len,V},Bin3}
- end.
-
-%% decode_primitive_incomplete/2 decodes an encoded message incomplete
-%% by help of the pattern attribute (first argument).
-decode_primitive_incomplete([[default,TagNo]],Bin) -> %default
- case decode_tlv(Bin) of
- {{Form,TagNo,Len,V},Rest} ->
- decode_incomplete2(Form,TagNo,Len,V,[],Rest);
- _ ->
- %{asn1_DEFAULT,Bin}
- asn1_NOVALUE
- end;
-decode_primitive_incomplete([[default,TagNo,Directives]],Bin) -> %default, constructed type, Directives points into this type
- case decode_tlv(Bin) of
- {{Form,TagNo,Len,V},Rest} ->
- decode_incomplete2(Form,TagNo,Len,V,Directives,Rest);
- _ ->
- %{asn1_DEFAULT,Bin}
- asn1_NOVALUE
- end;
-decode_primitive_incomplete([[opt,TagNo]],Bin) -> %optional
- case decode_tlv(Bin) of
- {{Form,TagNo,Len,V},Rest} ->
- decode_incomplete2(Form,TagNo,Len,V,[],Rest);
- _ ->
- %{{TagNo,asn1_NOVALUE},Bin}
- asn1_NOVALUE
- end;
-decode_primitive_incomplete([[opt,TagNo,Directives]],Bin) -> %optional
- case decode_tlv(Bin) of
- {{Form,TagNo,Len,V},Rest} ->
- decode_incomplete2(Form,TagNo,Len,V,Directives,Rest);
- _ ->
- %{{TagNo,asn1_NOVALUE},Bin}
- asn1_NOVALUE
- end;
-%% A choice alternative that shall be undecoded
-decode_primitive_incomplete([[alt_undec,TagNo]|RestAlts],Bin) ->
-% decode_incomplete_bin(Bin);
- case decode_tlv(Bin) of
- {{_Form,TagNo,_Len,_V},_R} ->
- decode_incomplete_bin(Bin);
- _ ->
- decode_primitive_incomplete(RestAlts,Bin)
- end;
-decode_primitive_incomplete([[alt,TagNo]|RestAlts],Bin) ->
- case decode_tlv(Bin) of
- {{_Form,TagNo,_Len,V},Rest} ->
- {{TagNo,V},Rest};
- _ ->
- decode_primitive_incomplete(RestAlts,Bin)
- end;
-decode_primitive_incomplete([[alt,TagNo,Directives]|RestAlts],Bin) ->
- case decode_tlv(Bin) of
- {{Form,TagNo,Len,V},Rest} ->
- decode_incomplete2(Form,TagNo,Len,V,Directives,Rest);
- _ ->
- decode_primitive_incomplete(RestAlts,Bin)
- end;
-decode_primitive_incomplete([[alt_parts,TagNo]|RestAlts],Bin) ->
- case decode_tlv(Bin) of
- {{_Form,TagNo,_Len,V},Rest} ->
- {{TagNo,decode_parts_incomplete(V)},Rest};
- _ ->
- decode_primitive_incomplete(RestAlts,Bin)
- end;
-decode_primitive_incomplete([[undec,_TagNo]|_RestTag],Bin) -> %incomlete decode
- decode_incomplete_bin(Bin); %% use this if changing handling of
-decode_primitive_incomplete([[parts,TagNo]|_RestTag],Bin) ->
- case decode_tlv(Bin) of
- {{_Form,TagNo,_Len,V},Rest} ->
- {{TagNo,decode_parts_incomplete(V)},Rest};
- Err ->
- {error,{asn1,"tag failure",TagNo,Err}}
- end;
-decode_primitive_incomplete([mandatory|RestTag],Bin) ->
- case decode_tlv(Bin) of
- {{Form,TagNo,Len,V},Rest} ->
- decode_incomplete2(Form,TagNo,Len,V,RestTag,Rest);
- _ ->
- {error,{asn1,"partial incomplete decode failure"}}
- end;
-%% A choice that is a toptype or a mandatory component of a
-%% SEQUENCE or SET.
-decode_primitive_incomplete([[mandatory,Directives]],Bin) ->
- case decode_tlv(Bin) of
- {{Form,TagNo,Len,V},Rest} ->
- decode_incomplete2(Form,TagNo,Len,V,Directives,Rest);
- _ ->
- {error,{asn1,"partial incomplete decode failure"}}
- end;
-decode_primitive_incomplete([],Bin) ->
- decode_primitive(Bin).
-
-%% decode_parts_incomplete/1 receives a number of values encoded in
-%% sequence and returns the parts as unencoded binaries
-decode_parts_incomplete(<<>>) ->
- [];
-decode_parts_incomplete(Bin) ->
- {ok,Rest} = skip_tag(Bin),
- {ok,Rest2} = skip_length_and_value(Rest),
- LenPart = size(Bin) - size(Rest2),
- <<Part:LenPart/binary,RestBin/binary>> = Bin,
- [Part|decode_parts_incomplete(RestBin)].
-
-
-%% decode_incomplete2 checks if V is a value of a constructed or
-%% primitive type, and continues the decode propeerly.
-decode_incomplete2(1,TagNo,indefinite,V,TagMatch,_) ->
- %% constructed indefinite length
- {Vlist,Rest2} = decode_constr_indef_incomplete(TagMatch,V,[]),
- {{TagNo,Vlist},Rest2};
-decode_incomplete2(1,TagNo,_Len,V,TagMatch,Rest) ->
- {{TagNo,decode_constructed_incomplete(TagMatch,V)},Rest};
-decode_incomplete2(0,TagNo,_Len,V,_TagMatch,Rest) ->
- {{TagNo,V},Rest}.
-
-decode_constructed_incomplete(_TagMatch,<<>>) ->
- [];
-decode_constructed_incomplete([mandatory|RestTag],Bin) ->
- {Tlv,Rest} = decode_primitive(Bin),
- [Tlv|decode_constructed_incomplete(RestTag,Rest)];
-decode_constructed_incomplete(Directives=[[Alt,_]|_],Bin)
- when Alt == alt_undec; Alt == alt ->
- case decode_tlv(Bin) of
- {{_Form,TagNo,_Len,V},Rest} ->
- case incomplete_choice_alt(TagNo,Directives) of
- alt_undec ->
- LenA = size(Bin)-size(Rest),
- <<A:LenA/binary,Rest/binary>> = Bin,
- A;
-% {UndecBin,_}=decode_incomplete_bin(Bin),
-% UndecBin;
-% [{TagNo,V}];
- alt ->
- {Tlv,_} = decode_primitive(V),
- [{TagNo,Tlv}];
- alt_parts ->
- %{{TagNo,decode_parts_incomplete(V)},Rest}; % maybe wrong
- [{TagNo,decode_parts_incomplete(V)}];
- Err ->
- {error,{asn1,"partial incomplete decode failure",Err}}
- end;
- _ ->
- {error,{asn1,"partial incomplete decode failure"}}
- end;
-decode_constructed_incomplete([TagNo|RestTag],Bin) ->
-%% {Tlv,Rest} = decode_primitive_incomplete([TagNo],Bin),
- case decode_primitive_incomplete([TagNo],Bin) of
- {Tlv,Rest} ->
- [Tlv|decode_constructed_incomplete(RestTag,Rest)];
- asn1_NOVALUE ->
- decode_constructed_incomplete(RestTag,Bin)
- end;
-decode_constructed_incomplete([],Bin) ->
- {Tlv,_Rest}=decode_primitive(Bin),
- [Tlv].
-
-decode_constr_indef_incomplete(_TagMatch,<<0,0,Rest/binary>>,Acc) ->
- {lists:reverse(Acc),Rest};
-decode_constr_indef_incomplete([Tag|RestTags],Bin,Acc) ->
-% {Tlv,Rest} = decode_primitive_incomplete([Tag],Bin),
- case decode_primitive_incomplete([Tag],Bin) of
- {Tlv,Rest} ->
- decode_constr_indef_incomplete(RestTags,Rest,[Tlv|Acc]);
- asn1_NOVALUE ->
- decode_constr_indef_incomplete(RestTags,Bin,Acc)
- end.
-
-
-decode_incomplete_bin(Bin) ->
- {ok,Rest} = skip_tag(Bin),
- {ok,Rest2} = skip_length_and_value(Rest),
- IncLen = size(Bin) - size(Rest2),
- <<IncBin:IncLen/binary,Ret/binary>> = Bin,
- {IncBin,Ret}.
-
-incomplete_choice_alt(TagNo,[[Alt,TagNo]|_Directives]) ->
- Alt;
-incomplete_choice_alt(TagNo,[_H|Directives]) ->
- incomplete_choice_alt(TagNo,Directives);
-incomplete_choice_alt(_,[]) ->
- error.
-
-
-%% skip_tag and skip_length_and_value are rutines used both by
-%% decode_partial_incomplete and decode_partial (decode/2).
-
-skip_tag(<<_:3,31:5,Rest/binary>>)->
- skip_long_tag(Rest);
-skip_tag(<<_:3,_Tag:5,Rest/binary>>) ->
- {ok,Rest}.
-
-skip_long_tag(<<1:1,_:7,Rest/binary>>) ->
- skip_long_tag(Rest);
-skip_long_tag(<<0:1,_:7,Rest/binary>>) ->
- {ok,Rest}.
-
-skip_length_and_value(Binary) ->
- case decode_length(Binary) of
- {indefinite,RestBinary} ->
- skip_indefinite_value(RestBinary);
- {Length,RestBinary} ->
- <<_:Length/unit:8,Rest/binary>> = RestBinary,
- {ok,Rest}
- end.
-
-skip_indefinite_value(<<0,0,Rest/binary>>) ->
- {ok,Rest};
-skip_indefinite_value(Binary) ->
- {ok,RestBinary}=skip_tag(Binary),
- {ok,RestBinary2} = skip_length_and_value(RestBinary),
- skip_indefinite_value(RestBinary2).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% match_tags takes a Tlv (Tag, Length, Value) structure and matches
-%% it with the tags in TagList. If the tags does not match the function
-%% crashes otherwise it returns the remaining Tlv after that the tags have
-%% been removed.
-%%
-%% match_tags(Tlv, TagList)
-%%
-
-
-match_tags({T,V}, [T|Tt]) ->
- match_tags(V,Tt);
-match_tags([{T,V}],[T|Tt]) ->
- match_tags(V, Tt);
-match_tags(Vlist = [{T,_V}|_], [T]) ->
- Vlist;
-match_tags(Tlv, []) ->
- Tlv;
-match_tags({Tag,_V},[T|_Tt]) ->
- {error,{asn1,{wrong_tag,{Tag,T}}}}.
-
-
-cindex(Ix,Val,Cname) ->
- case element(Ix,Val) of
- {Cname,Val2} -> Val2;
- X -> X
- end.
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Optionals, preset not filled optionals with asn1_NOVALUE
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-% converts a list to a record if necessary
-list_to_record(Name,List) when list(List) ->
- list_to_tuple([Name|List]);
-list_to_record(_Name,Tuple) when tuple(Tuple) ->
- Tuple.
-
-
-fixoptionals(OptList,Val) when list(Val) ->
- fixoptionals(OptList,Val,1,[],[]).
-
-fixoptionals([{Name,Pos}|Ot],[{Name,Val}|Vt],_Opt,Acc1,Acc2) ->
- fixoptionals(Ot,Vt,Pos+1,[1|Acc1],[{Name,Val}|Acc2]);
-fixoptionals([{_Name,Pos}|Ot],V,Pos,Acc1,Acc2) ->
- fixoptionals(Ot,V,Pos+1,[0|Acc1],[asn1_NOVALUE|Acc2]);
-fixoptionals(O,[Vh|Vt],Pos,Acc1,Acc2) ->
- fixoptionals(O,Vt,Pos+1,Acc1,[Vh|Acc2]);
-fixoptionals([],[Vh|Vt],Pos,Acc1,Acc2) ->
- fixoptionals([],Vt,Pos+1,Acc1,[Vh|Acc2]);
-fixoptionals([],[],_,_Acc1,Acc2) ->
- % return Val as a record
- list_to_tuple([asn1_RECORDNAME|lists:reverse(Acc2)]).
-
-
-%%encode_tag(TagClass(?UNI, APP etc), Form (?PRIM etx), TagInteger) ->
-%% 8bit Int | binary
-encode_tag_val({Class, Form, TagNo}) when (TagNo =< 30) ->
- <<(Class bsr 6):2,(Form bsr 5):1,TagNo:5>>;
-
-encode_tag_val({Class, Form, TagNo}) ->
- {Octets,_Len} = mk_object_val(TagNo),
- BinOct = list_to_binary(Octets),
- <<(Class bsr 6):2, (Form bsr 5):1, 31:5,BinOct/binary>>;
-
-%% asumes whole correct tag bitpattern, multiple of 8
-encode_tag_val(Tag) when (Tag =< 255) -> Tag; %% anv�nds denna funktion??!!
-%% asumes correct bitpattern of 0-5
-encode_tag_val(Tag) -> encode_tag_val2(Tag,[]).
-
-encode_tag_val2(Tag, OctAck) when (Tag =< 255) ->
- [Tag | OctAck];
-encode_tag_val2(Tag, OctAck) ->
- encode_tag_val2(Tag bsr 8, [255 band Tag | OctAck]).
-
-
-%%===============================================================================
-%% Decode a tag
-%%
-%% decode_tag(OctetListBuffer) -> {{Form, (Class bsl 16)+ TagNo}, RestOfBuffer, RemovedBytes}
-%%===============================================================================
-
-decode_tag_and_length(<<Class:2, Form:1, TagNo:5, 0:1, Length:7, RestBuffer/binary>>) when TagNo < 31 ->
- {Form, (Class bsl 16) + TagNo, Length, RestBuffer};
-decode_tag_and_length(<<Class:2, Form:1, TagNo:5, 1:1, 0:7, T/binary>>) when TagNo < 31 ->
- {Form, (Class bsl 16) + TagNo, indefinite, T};
-decode_tag_and_length(<<Class:2, Form:1, TagNo:5, 1:1, LL:7, T/binary>>) when TagNo < 31 ->
- <<Length:LL/unit:8,RestBuffer/binary>> = T,
- {Form, (Class bsl 16) + TagNo, Length, RestBuffer};
-decode_tag_and_length(<<Class:2, Form:1, 31:5, 0:1, TagNo:7, 0:1, Length:7, RestBuffer/binary>>) ->
- {Form, (Class bsl 16) + TagNo, Length, RestBuffer};
-decode_tag_and_length(<<Class:2, Form:1, 31:5, 0:1, TagNo:7, 1:1, 0:7, T/binary>>) ->
- {Form, (Class bsl 16) + TagNo, indefinite, T};
-decode_tag_and_length(<<Class:2, Form:1, 31:5, 0:1, TagNo:7, 1:1, LL:7, T/binary>>) ->
- <<Length:LL/unit:8,RestBuffer/binary>> = T,
- {Form, (Class bsl 16) + TagNo, Length, RestBuffer};
-decode_tag_and_length(<<Class:2, Form:1, 31:5, Buffer/binary>>) ->
- {TagNo, Buffer1} = decode_tag(Buffer, 0),
- {Length, RestBuffer} = decode_length(Buffer1),
- {Form, (Class bsl 16) + TagNo, Length, RestBuffer}.
-
-
-
-%% last partial tag
-decode_tag(<<0:1,PartialTag:7, Buffer/binary>>, TagAck) ->
- TagNo = (TagAck bsl 7) bor PartialTag,
- %%<<TagNo>> = <<TagAck:1, PartialTag:7>>,
- {TagNo, Buffer};
-% more tags
-decode_tag(<<_:1,PartialTag:7, Buffer/binary>>, TagAck) ->
- TagAck1 = (TagAck bsl 7) bor PartialTag,
- %%<<TagAck1:16>> = <<TagAck:1, PartialTag:7,0:8>>,
- decode_tag(Buffer, TagAck1).
-
-
-%%=======================================================================
-%%
-%% Encode all tags in the list Tags and return a possibly deep list of
-%% bytes with tag and length encoded
-%% The taglist must be in reverse order (fixed by the asn1 compiler)
-%% e.g [T1,T2] will result in
-%% {[EncodedT2,EncodedT1|BytesSoFar],LenSoFar+LenT2+LenT1}
-%%
-
-encode_tags([Tag|Trest], BytesSoFar, LenSoFar) ->
-% remove {Bytes1,L1} = encode_one_tag(Tag),
- {Bytes2,L2} = encode_length(LenSoFar),
- encode_tags(Trest, [Tag,Bytes2|BytesSoFar],
- LenSoFar + size(Tag) + L2);
-encode_tags([], BytesSoFar, LenSoFar) ->
- {BytesSoFar,LenSoFar}.
-
-encode_tags(TagIn, {BytesSoFar,LenSoFar}) ->
- encode_tags(TagIn, BytesSoFar, LenSoFar).
-
-% encode_one_tag(#tag{class=Class,number=No,type=Type, form = Form}) ->
-% NewForm = case Type of
-% 'EXPLICIT' ->
-% ?CONSTRUCTED;
-% _ ->
-% Form
-% end,
-% Bytes = encode_tag_val({Class,NewForm,No}),
-% {Bytes,size(Bytes)}.
-
-
-%%===============================================================================
-%%
-%% This comment is valid for all the encode/decode functions
-%%
-%% C = Constraint -> typically {'ValueRange',LowerBound,UpperBound}
-%% used for PER-coding but not for BER-coding.
-%%
-%% Val = Value. If Val is an atom then it is a symbolic integer value
-%% (i.e the atom must be one of the names in the NamedNumberList).
-%% The NamedNumberList is used to translate the atom to an integer value
-%% before encoding.
-%%
-%%===============================================================================
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_open_type(Value) -> io_list (i.e nested list with integers, binaries)
-%% Value = list of bytes of an already encoded value (the list must be flat)
-%% | binary
-
-%%
-encode_open_type(Val) when list(Val) ->
-% {Val,length(Val)};
- encode_open_type(list_to_binary(Val));
-encode_open_type(Val) ->
- {Val, size(Val)}.
-
-%%
-encode_open_type(Val, T) when list(Val) ->
- encode_open_type(list_to_binary(Val),T);
-encode_open_type(Val,[]) ->
- {Val, size(Val)};
-encode_open_type(Val,Tag) ->
- encode_tags(Tag,Val, size(Val)).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_open_type(Tlv, TagIn) -> Value
-%% Tlv = {Tag,V} | V where V -> binary()
-%% TagIn = [TagVal] where TagVal -> int()
-%% Value = binary with decoded data (which must be decoded again as some type)
-%%
-decode_open_type(Tlv, TagIn) ->
- case match_tags(Tlv,TagIn) of
- Bin when binary(Bin) ->
- {InnerTlv,_} = decode(Bin),
- InnerTlv;
- TlvBytes -> TlvBytes
- end.
-
-
-decode_open_type_as_binary(Tlv,TagIn)->
- case match_tags(Tlv,TagIn) of
- V when binary(V) ->
- V;
- [Tlv2] -> encode(Tlv2);
- Tlv2 -> encode(Tlv2)
- end.
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Boolean, ITU_T X.690 Chapter 8.2
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-%%===============================================================================
-%% encode_boolean(Integer, ReversedTagList) -> {[Octet],Len}
-%%===============================================================================
-
-encode_boolean({Name, Val}, TagIn) when atom(Name) ->
- encode_boolean(Val, TagIn);
-encode_boolean(true, TagIn) ->
- encode_tags(TagIn, [16#FF],1);
-encode_boolean(false, TagIn) ->
- encode_tags(TagIn, [0],1);
-encode_boolean(X,_) ->
- exit({error,{asn1, {encode_boolean, X}}}).
-
-
-%%===============================================================================
-%% decode_boolean(BuffList, HasTag, TotalLen) -> {true, Remain, RemovedBytes} |
-%% {false, Remain, RemovedBytes}
-%%===============================================================================
-decode_boolean(Tlv,TagIn) ->
- Val = match_tags(Tlv, TagIn),
- case Val of
- <<0:8>> ->
- false;
- <<_:8>> ->
- true;
- _ ->
- exit({error,{asn1, {decode_boolean, Val}}})
- end.
-
-
-%%===========================================================================
-%% Integer, ITU_T X.690 Chapter 8.3
-
-%% encode_integer(Constraint, Value, Tag) -> [octet list]
-%% encode_integer(Constraint, Name, NamedNumberList, Tag) -> [octet list]
-%% Value = INTEGER | {Name,INTEGER}
-%% Tag = tag | notag
-%%===========================================================================
-
-encode_integer(C, Val, Tag) when integer(Val) ->
- encode_tags(Tag, encode_integer(C, Val));
-encode_integer(C,{Name,Val},Tag) when atom(Name) ->
- encode_integer(C,Val,Tag);
-encode_integer(_C, Val, _Tag) ->
- exit({error,{asn1, {encode_integer, Val}}}).
-
-
-
-encode_integer(C, Val, NamedNumberList, Tag) when atom(Val) ->
- case lists:keysearch(Val, 1, NamedNumberList) of
- {value,{_, NewVal}} ->
- encode_tags(Tag, encode_integer(C, NewVal));
- _ ->
- exit({error,{asn1, {encode_integer_namednumber, Val}}})
- end;
-encode_integer(C,{_Name,Val},NamedNumberList,Tag) ->
- encode_integer(C,Val,NamedNumberList,Tag);
-encode_integer(C, Val, _NamedNumberList, Tag) ->
- encode_tags(Tag, encode_integer(C, Val)).
-
-
-encode_integer(_, Val) ->
- Bytes =
- if
- Val >= 0 ->
- encode_integer_pos(Val, []);
- true ->
- encode_integer_neg(Val, [])
- end,
- {Bytes,length(Bytes)}.
-
-encode_integer_pos(0, L=[B|_Acc]) when B < 128 ->
- L;
-encode_integer_pos(N, Acc) ->
- encode_integer_pos((N bsr 8), [N band 16#ff| Acc]).
-
-encode_integer_neg(-1, L=[B1|_T]) when B1 > 127 ->
- L;
-encode_integer_neg(N, Acc) ->
- encode_integer_neg(N bsr 8, [N band 16#ff|Acc]).
-
-%%===============================================================================
-%% decode integer
-%% (Buffer, Range, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
-%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
-%%===============================================================================
-
-decode_integer(Tlv,Range,NamedNumberList,TagIn) ->
- V = match_tags(Tlv,TagIn),
- Int = decode_integer(V),
- range_check_integer(Int,Range),
- number2name(Int,NamedNumberList).
-
-decode_integer(Tlv,Range,TagIn) ->
- V = match_tags(Tlv, TagIn),
- Int = decode_integer(V),
- range_check_integer(Int,Range),
- Int.
-
-%% decoding postitive integer values.
-decode_integer(Bin = <<0:1,_:7,_/binary>>) ->
- Len = size(Bin),
-% <<Int:Len/unit:8,Buffer2/binary>> = Bin,
- <<Int:Len/unit:8>> = Bin,
- Int;
-%% decoding negative integer values.
-decode_integer(Bin = <<1:1,B2:7,Bs/binary>>) ->
- Len = size(Bin),
-% <<N:Len/unit:8,Buffer2/binary>> = <<B2,Bs/binary>>,
- <<N:Len/unit:8>> = <<B2,Bs/binary>>,
- Int = N - (1 bsl (8 * Len - 1)),
- Int.
-
-range_check_integer(Int,Range) ->
- case Range of
- [] -> % No length constraint
- Int;
- {Lb,Ub} when Int >= Lb, Ub >= Int -> % variable length constraint
- Int;
- Int -> % fixed value constraint
- Int;
- {_,_} ->
- exit({error,{asn1,{integer_range,Range,Int}}});
- SingleValue when integer(SingleValue) ->
- exit({error,{asn1,{integer_range,Range,Int}}});
- _ -> % some strange constraint that we don't support yet
- Int
- end.
-
-number2name(Int,[]) ->
- Int;
-number2name(Int,NamedNumberList) ->
- case lists:keysearch(Int, 2, NamedNumberList) of
- {value,{NamedVal, _}} ->
- NamedVal;
- _ ->
- Int
- end.
-
-
-%%============================================================================
-%% Enumerated value, ITU_T X.690 Chapter 8.4
-
-%% encode enumerated value
-%%============================================================================
-encode_enumerated(Val, TagIn) when integer(Val)->
- encode_tags(TagIn, encode_integer(false,Val));
-encode_enumerated({Name,Val}, TagIn) when atom(Name) ->
- encode_enumerated(Val, TagIn).
-
-%% The encode_enumerated functions below this line can be removed when the
-%% new code generation is stable. (the functions might have to be kept here
-%% a while longer for compatibility reasons)
-
-encode_enumerated(C, Val, {NamedNumberList,ExtList}, TagIn) when atom(Val) ->
- case catch encode_enumerated(C, Val, NamedNumberList, TagIn) of
- {'EXIT',_} -> encode_enumerated(C, Val, ExtList, TagIn);
- Result -> Result
- end;
-
-encode_enumerated(C, Val, NamedNumberList, TagIn) when atom(Val) ->
- case lists:keysearch(Val, 1, NamedNumberList) of
- {value, {_, NewVal}} ->
- encode_tags(TagIn, encode_integer(C, NewVal));
- _ ->
- exit({error,{asn1, {enumerated_not_in_range, Val}}})
- end;
-
-encode_enumerated(C, {asn1_enum, Val}, {_,_}, TagIn) when integer(Val) ->
- encode_tags(TagIn, encode_integer(C,Val));
-
-encode_enumerated(C, {Name,Val}, NamedNumberList, TagIn) when atom(Name) ->
- encode_enumerated(C, Val, NamedNumberList, TagIn);
-
-encode_enumerated(_C, Val, _NamedNumberList, _TagIn) ->
- exit({error,{asn1, {enumerated_not_namednumber, Val}}}).
-
-
-
-%%============================================================================
-%% decode enumerated value
-%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> Value
-%%===========================================================================
-decode_enumerated(Tlv, Range, NamedNumberList, Tags) ->
- Buffer = match_tags(Tlv,Tags),
- decode_enumerated_notag(Buffer, Range, NamedNumberList, Tags).
-
-decode_enumerated_notag(Buffer, _Range, {NamedNumberList,ExtList}, _Tags) ->
-
- IVal = decode_integer2(size(Buffer), Buffer),
- case decode_enumerated1(IVal, NamedNumberList) of
- {asn1_enum,IVal} ->
- decode_enumerated1(IVal,ExtList);
- EVal ->
- EVal
- end;
-decode_enumerated_notag(Buffer, _Range, NNList, _Tags) ->
- IVal = decode_integer2(size(Buffer), Buffer),
- case decode_enumerated1(IVal, NNList) of
- {asn1_enum,_} ->
- exit({error,{asn1, {illegal_enumerated, IVal}}});
- EVal ->
- EVal
- end.
-
-decode_enumerated1(Val, NamedNumberList) ->
- %% it must be a named integer
- case lists:keysearch(Val, 2, NamedNumberList) of
- {value,{NamedVal, _}} ->
- NamedVal;
- _ ->
- {asn1_enum,Val}
- end.
-
-
-%%============================================================================
-%%
-%% Real value, ITU_T X.690 Chapter 8.5
-%%============================================================================
-%%
-%% encode real value
-%%============================================================================
-
-%% only base 2 internally so far!!
-encode_real(0, TagIn) ->
- encode_tags(TagIn, {[],0});
-encode_real('PLUS-INFINITY', TagIn) ->
- encode_tags(TagIn, {[64],1});
-encode_real('MINUS-INFINITY', TagIn) ->
- encode_tags(TagIn, {[65],1});
-encode_real(Val, TagIn) when tuple(Val)->
- encode_tags(TagIn, encode_real(Val)).
-
-%%%%%%%%%%%%%%
-%% not optimal efficient..
-%% only base 2 of Mantissa encoding!
-%% only base 2 of ExpBase encoding!
-encode_real({Man, Base, Exp}) ->
-%% io:format("Mantissa: ~w Base: ~w, Exp: ~w~n",[Man, Base, Exp]),
-
- OctExp = if Exp >= 0 -> list_to_binary(encode_integer_pos(Exp, []));
- true -> list_to_binary(encode_integer_neg(Exp, []))
- end,
-%% ok = io:format("OctExp: ~w~n",[OctExp]),
- SignBit = if Man > 0 -> 0; % bit 7 is pos or neg, no Zeroval
- true -> 1
- end,
-%% ok = io:format("SignBitMask: ~w~n",[SignBitMask]),
- InBase = if Base =:= 2 -> 0; % bit 6,5: only base 2 this far!
- true ->
- exit({error,{asn1, {encode_real_non_supported_encodeing, Base}}})
- end,
- SFactor = 0, % bit 4,3: no scaling since only base 2
- OctExpLen = size(OctExp),
- if OctExpLen > 255 ->
- exit({error,{asn1, {to_big_exp_in_encode_real, OctExpLen}}});
- true -> true %% make real assert later..
- end,
- {LenCode, EOctets} = case OctExpLen of % bit 2,1
- 1 -> {0, OctExp};
- 2 -> {1, OctExp};
- 3 -> {2, OctExp};
- _ -> {3, <<OctExpLen, OctExp/binary>>}
- end,
- FirstOctet = <<1:1,SignBit:1,InBase:2,SFactor:2,LenCode:2>>,
- OctMantissa = if Man > 0 -> list_to_binary(minimum_octets(Man));
- true -> list_to_binary(minimum_octets(-(Man))) % signbit keeps track of sign
- end,
- %% ok = io:format("LenMask: ~w EOctets: ~w~nFirstOctet: ~w OctMantissa: ~w OctExpLen: ~w~n", [LenMask, EOctets, FirstOctet, OctMantissa, OctExpLen]),
- Bin = <<FirstOctet/binary, EOctets/binary, OctMantissa/binary>>,
- {Bin, size(Bin)}.
-
-
-%%============================================================================
-%% decode real value
-%%
-%% decode_real([OctetBufferList], tuple|value, tag|notag) ->
-%% {{Mantissa, Base, Exp} | realval | PLUS-INFINITY | MINUS-INFINITY | 0,
-%% RestBuff}
-%%
-%% only for base 2 decoding sofar!!
-%%============================================================================
-
-decode_real(Tlv, Form, Tags) ->
- Buffer = match_tags(Tlv,Tags),
- decode_real_notag(Buffer, Form).
-
-decode_real_notag(_Buffer, _Form) ->
- exit({error,{asn1, {unimplemented,real}}}).
-%% decode_real2(Buffer, Form, size(Buffer)).
-
-% decode_real2(Buffer, Form, Len) ->
-% <<First, Buffer2/binary>> = Buffer,
-% if
-% First =:= 2#01000000 -> {'PLUS-INFINITY', Buffer2};
-% First =:= 2#01000001 -> {'MINUS-INFINITY', Buffer2};
-% First =:= 2#00000000 -> {0, Buffer2};
-% true ->
-% %% have some check here to verify only supported bases (2)
-% <<B7:1,B6:1,B5_4:2,B3_2:2,B1_0:2>> = <<First>>,
-% Sign = B6,
-% Base =
-% case B5_4 of
-% 0 -> 2; % base 2, only one so far
-% _ -> exit({error,{asn1, {non_supported_base, First}}})
-% end,
-% ScalingFactor =
-% case B3_2 of
-% 0 -> 0; % no scaling so far
-% _ -> exit({error,{asn1, {non_supported_scaling, First}}})
-% end,
-
-% {FirstLen,Exp,Buffer3} =
-% case B1_0 of
-% 0 ->
-% <<_:1/unit:8,Buffer21/binary>> = Buffer2,
-% {2, decode_integer2(1, Buffer2),Buffer21};
-% 1 ->
-% <<_:2/unit:8,Buffer21/binary>> = Buffer2,
-% {3, decode_integer2(2, Buffer2)};
-% 2 ->
-% <<_:3/unit:8,Buffer21/binary>> = Buffer2,
-% {4, decode_integer2(3, Buffer2)};
-% 3 ->
-% <<ExpLen1,RestBuffer/binary>> = Buffer2,
-% <<_:ExpLen1/unit:8,RestBuffer2/binary>> = RestBuffer,
-% { ExpLen1 + 2,
-% decode_integer2(ExpLen1, RestBuffer, RemBytes1),
-% RestBuffer2}
-% end,
-% Length = Len - FirstLen,
-% <<LongInt:Length/unit:8,RestBuff/binary>> = Buffer3,
-% {Mantissa, Buffer4} =
-% if Sign =:= 0 ->
-
-% {LongInt, RestBuff};% sign plus,
-% true ->
-
-% {-LongInt, RestBuff}% sign minus
-% end,
-% case Form of
-% tuple ->
-% {Val,Buf,RemB} = Exp,
-% {{Mantissa, Base, {Val,Buf}}, Buffer4, RemBytes2+RemBytes3};
-% _value ->
-% comming
-% end
-% end.
-
-
-%%============================================================================
-%% Bitstring value, ITU_T X.690 Chapter 8.6
-%%
-%% encode bitstring value
-%%
-%% bitstring NamedBitList
-%% Val can be of:
-%% - [identifiers] where only named identifers are set to one,
-%% the Constraint must then have some information of the
-%% bitlength.
-%% - [list of ones and zeroes] all bits
-%% - integer value representing the bitlist
-%% C is constrint Len, only valid when identifiers
-%%============================================================================
-
-encode_bit_string(C,Bin={Unused,BinBits},NamedBitList,TagIn) when integer(Unused), binary(BinBits) ->
- encode_bin_bit_string(C,Bin,NamedBitList,TagIn);
-encode_bit_string(C, [FirstVal | RestVal], NamedBitList, TagIn) when atom(FirstVal) ->
- encode_bit_string_named(C, [FirstVal | RestVal], NamedBitList, TagIn);
-
-encode_bit_string(C, [{bit,X} | RestVal], NamedBitList, TagIn) ->
- encode_bit_string_named(C, [{bit,X} | RestVal], NamedBitList, TagIn);
-
-encode_bit_string(C, [FirstVal| RestVal], NamedBitList, TagIn) when integer(FirstVal) ->
- encode_bit_string_bits(C, [FirstVal | RestVal], NamedBitList, TagIn);
-
-encode_bit_string(_C, 0, _NamedBitList, TagIn) ->
- encode_tags(TagIn, <<0>>,1);
-
-encode_bit_string(_C, [], _NamedBitList, TagIn) ->
- encode_tags(TagIn, <<0>>,1);
-
-encode_bit_string(C, IntegerVal, NamedBitList, TagIn) when integer(IntegerVal) ->
- BitListVal = int_to_bitlist(IntegerVal),
- encode_bit_string_bits(C, BitListVal, NamedBitList, TagIn);
-
-encode_bit_string(C, {Name,BitList}, NamedBitList, TagIn) when atom(Name) ->
- encode_bit_string(C, BitList, NamedBitList, TagIn).
-
-
-
-int_to_bitlist(0) ->
- [];
-int_to_bitlist(Int) when integer(Int), Int >= 0 ->
- [Int band 1 | int_to_bitlist(Int bsr 1)].
-
-
-%%=================================================================
-%% Encode BIT STRING of the form {Unused,BinBits}.
-%% Unused is the number of unused bits in the last byte in BinBits
-%% and BinBits is a binary representing the BIT STRING.
-%%=================================================================
-encode_bin_bit_string(C,{Unused,BinBits},_NamedBitList,TagIn)->
- case get_constraint(C,'SizeConstraint') of
- no ->
- remove_unused_then_dotag(TagIn, Unused, BinBits);
- {_Min,Max} ->
- BBLen = (size(BinBits)*8)-Unused,
- if
- BBLen > Max ->
- exit({error,{asn1,
- {bitstring_length,
- {{was,BBLen},{maximum,Max}}}}});
- true ->
- remove_unused_then_dotag(TagIn, Unused, BinBits)
- end;
- Size ->
- case ((size(BinBits)*8)-Unused) of
- BBSize when BBSize =< Size ->
- remove_unused_then_dotag(TagIn, Unused, BinBits);
- BBSize ->
- exit({error,{asn1,
- {bitstring_length,
- {{was,BBSize},{should_be,Size}}}}})
- end
- end.
-
-remove_unused_then_dotag(TagIn,Unused,BinBits) ->
- case Unused of
- 0 when (size(BinBits) == 0) ->
- encode_tags(TagIn,<<0>>,1);
- 0 ->
- Bin = <<Unused,BinBits/binary>>,
- encode_tags(TagIn,Bin,size(Bin));
- Num ->
- N = (size(BinBits)-1),
- <<BBits:N/binary,LastByte>> = BinBits,
- encode_tags(TagIn,
- [Unused,binary_to_list(BBits) ++[(LastByte bsr Num) bsl Num]],
- 1+size(BinBits))
- end.
-
-
-%%=================================================================
-%% Encode named bits
-%%=================================================================
-
-encode_bit_string_named(C, [FirstVal | RestVal], NamedBitList, TagIn) ->
- ToSetPos = get_all_bitposes([FirstVal | RestVal], NamedBitList, []),
- Size =
- case get_constraint(C,'SizeConstraint') of
- no ->
- lists:max(ToSetPos)+1;
- {_Min,Max} ->
- Max;
- TSize ->
- TSize
- end,
- BitList = make_and_set_list(Size, ToSetPos, 0),
- {Len, Unused, OctetList} = encode_bitstring(BitList),
- encode_tags(TagIn, [Unused|OctetList],Len+1).
-
-
-%%----------------------------------------
-%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
-%% [sorted_list_of_bitpositions_to_set]
-%%----------------------------------------
-
-get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
-get_all_bitposes([Val | Rest], NamedBitList, Ack) when atom(Val) ->
- case lists:keysearch(Val, 1, NamedBitList) of
- {value, {_ValName, ValPos}} ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
- _ ->
- exit({error,{asn1, {bitstring_namedbit, Val}}})
- end;
-get_all_bitposes([], _NamedBitList, Ack) ->
- lists:sort(Ack).
-
-
-%%----------------------------------------
-%% make_and_set_list(Len of list to return, [list of positions to set to 1])->
-%% returns list of Len length, with all in SetPos set.
-%% in positioning in list the first element is 0, the second 1 etc.., but
-%% Len will make a list of length Len, not Len + 1.
-%% BitList = make_and_set_list(C, ToSetPos, 0),
-%%----------------------------------------
-
-make_and_set_list(0, [], _) -> [];
-make_and_set_list(0, _, _) ->
- exit({error,{asn1,bitstring_sizeconstraint}});
-make_and_set_list(Len, [XPos|SetPos], XPos) ->
- [1 | make_and_set_list(Len - 1, SetPos, XPos + 1)];
-make_and_set_list(Len, [Pos|SetPos], XPos) ->
- [0 | make_and_set_list(Len - 1, [Pos | SetPos], XPos + 1)];
-make_and_set_list(Len, [], XPos) ->
- [0 | make_and_set_list(Len - 1, [], XPos + 1)].
-
-
-
-
-
-
-%%=================================================================
-%% Encode bit string for lists of ones and zeroes
-%%=================================================================
-encode_bit_string_bits(C, BitListVal, _NamedBitList, TagIn) when list(BitListVal) ->
- case get_constraint(C,'SizeConstraint') of
- no ->
- {Len, Unused, OctetList} = encode_bitstring(BitListVal),
- %%add unused byte to the Len
- encode_tags(TagIn, [Unused | OctetList], Len+1);
- Constr={Min,Max} when integer(Min),integer(Max) ->
- encode_constr_bit_str_bits(Constr,BitListVal,TagIn);
- {Constr={_,_},[]} ->%Constr={Min,Max}
- %% constraint with extension mark
- encode_constr_bit_str_bits(Constr,BitListVal,TagIn);
- Constr={{_,_},{_,_}} ->%{{Min1,Max1},{Min2,Max2}}
- %% constraint with extension mark
- encode_constr_bit_str_bits(Constr,BitListVal,TagIn);
- Size ->
- case length(BitListVal) of
- BitSize when BitSize == Size ->
- {Len, Unused, OctetList} = encode_bitstring(BitListVal),
- %%add unused byte to the Len
- encode_tags(TagIn, [Unused | OctetList], Len+1);
- BitSize when BitSize < Size ->
- PaddedList = pad_bit_list(Size-BitSize,BitListVal),
- {Len, Unused, OctetList} = encode_bitstring(PaddedList),
- %%add unused byte to the Len
- encode_tags(TagIn, [Unused | OctetList], Len+1);
- BitSize ->
- exit({error,{asn1,
- {bitstring_length, {{was,BitSize},{should_be,Size}}}}})
- end
-
- end.
-
-encode_constr_bit_str_bits({_Min,Max},BitListVal,TagIn) ->
- BitLen = length(BitListVal),
- if
- BitLen > Max ->
- exit({error,{asn1,{bitstring_length,{{was,BitLen},
- {maximum,Max}}}}});
- true ->
- {Len, Unused, OctetList} = encode_bitstring(BitListVal),
- %%add unused byte to the Len
- encode_tags(TagIn, [Unused, OctetList], Len+1)
- end;
-encode_constr_bit_str_bits({{_Min1,Max1},{Min2,Max2}},BitListVal,TagIn) ->
- BitLen = length(BitListVal),
- case BitLen of
- Len when Len > Max2 ->
- exit({error,{asn1,{bitstring_length,{{was,BitLen},
- {maximum,Max2}}}}});
- Len when Len > Max1, Len < Min2 ->
- exit({error,{asn1,{bitstring_length,{{was,BitLen},
- {not_allowed_interval,
- Max1,Min2}}}}});
- _ ->
- {Len, Unused, OctetList} = encode_bitstring(BitListVal),
- %%add unused byte to the Len
- encode_tags(TagIn, [Unused, OctetList], Len+1)
- end.
-
-%% returns a list of length Size + length(BitListVal), with BitListVal
-%% as the most significant elements followed by padded zero elements
-pad_bit_list(Size,BitListVal) ->
- Tail = lists:duplicate(Size,0),
- lists:append(BitListVal,Tail).
-
-%%=================================================================
-%% Do the actual encoding
-%% ([bitlist]) -> {ListLen, UnusedBits, OctetList}
-%%=================================================================
-
-encode_bitstring([B8, B7, B6, B5, B4, B3, B2, B1 | Rest]) ->
- Val = (B8 bsl 7) bor (B7 bsl 6) bor (B6 bsl 5) bor (B5 bsl 4) bor
- (B4 bsl 3) bor (B3 bsl 2) bor (B2 bsl 1) bor B1,
- encode_bitstring(Rest, [Val], 1);
-encode_bitstring(Val) ->
- {Unused, Octet} = unused_bitlist(Val, 7, 0),
- {1, Unused, [Octet]}.
-
-encode_bitstring([B8, B7, B6, B5, B4, B3, B2, B1 | Rest], Ack, Len) ->
- Val = (B8 bsl 7) bor (B7 bsl 6) bor (B6 bsl 5) bor (B5 bsl 4) bor
- (B4 bsl 3) bor (B3 bsl 2) bor (B2 bsl 1) bor B1,
- encode_bitstring(Rest, [Ack | [Val]], Len + 1);
-%%even multiple of 8 bits..
-encode_bitstring([], Ack, Len) ->
- {Len, 0, Ack};
-%% unused bits in last octet
-encode_bitstring(Rest, Ack, Len) ->
-% io:format("uneven ~w ~w ~w~n",[Rest, Ack, Len]),
- {Unused, Val} = unused_bitlist(Rest, 7, 0),
- {Len + 1, Unused, [Ack | [Val]]}.
-
-%%%%%%%%%%%%%%%%%%
-%% unused_bitlist([list of ones and zeros <= 7], 7, []) ->
-%% {Unused bits, Last octet with bits moved to right}
-unused_bitlist([], Trail, Ack) ->
- {Trail + 1, Ack};
-unused_bitlist([Bit | Rest], Trail, Ack) ->
-%% io:format("trail Bit: ~w Rest: ~w Trail: ~w Ack:~w~n",[Bit, Rest, Trail, Ack]),
- unused_bitlist(Rest, Trail - 1, (Bit bsl Trail) bor Ack).
-
-
-%%============================================================================
-%% decode bitstring value
-%% (Buffer, Range, NamedNumberList, HasTag, TotalLen) -> {Integer, Remain, RemovedBytes}
-%%============================================================================
-
-decode_compact_bit_string(Buffer, Range, NamedNumberList, Tags) ->
-% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_BIT_STRING}),
- decode_restricted_string(Buffer, Range, ?N_BIT_STRING, Tags,
- NamedNumberList,bin).
-
-decode_bit_string(Buffer, Range, NamedNumberList, Tags) ->
-% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_BIT_STRING}),
- decode_restricted_string(Buffer, Range, ?N_BIT_STRING, Tags,
- NamedNumberList,old).
-
-
-decode_bit_string2(<<0>>,_NamedNumberList,BinOrOld) ->
- case BinOrOld of
- bin ->
- {0,<<>>};
- _ ->
- []
- end;
-decode_bit_string2(<<Unused,Bits/binary>>,NamedNumberList,BinOrOld) ->
- case NamedNumberList of
- [] ->
- case BinOrOld of
- bin ->
- {Unused,Bits};
- _ ->
- decode_bitstring2(size(Bits), Unused, Bits)
- end;
- _ ->
- BitString = decode_bitstring2(size(Bits), Unused, Bits),
- decode_bitstring_NNL(BitString,NamedNumberList)
- end.
-
-%%----------------------------------------
-%% Decode the in buffer to bits
-%%----------------------------------------
-decode_bitstring2(1,Unused,<<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,_/binary>>) ->
- lists:sublist([B7,B6,B5,B4,B3,B2,B1,B0],8-Unused);
-decode_bitstring2(Len, Unused,
- <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Buffer/binary>>) ->
- [B7, B6, B5, B4, B3, B2, B1, B0 |
- decode_bitstring2(Len - 1, Unused, Buffer)].
-
-%%decode_bitstring2(1, Unused, Buffer) ->
-%% make_bits_of_int(hd(Buffer), 128, 8-Unused);
-%%decode_bitstring2(Len, Unused, [BitVal | Buffer]) ->
-%% [B7, B6, B5, B4, B3, B2, B1, B0] = make_bits_of_int(BitVal, 128, 8),
-%% [B7, B6, B5, B4, B3, B2, B1, B0 |
-%% decode_bitstring2(Len - 1, Unused, Buffer)].
-
-
-%%make_bits_of_int(_, _, 0) ->
-%% [];
-%%make_bits_of_int(BitVal, MaskVal, Unused) when Unused > 0 ->
-%% X = case MaskVal band BitVal of
-%% 0 -> 0 ;
-%% _ -> 1
-%% end,
-%% [X | make_bits_of_int(BitVal, MaskVal bsr 1, Unused - 1)].
-
-
-
-%%----------------------------------------
-%% Decode the bitlist to names
-%%----------------------------------------
-
-
-decode_bitstring_NNL(BitList,NamedNumberList) ->
- decode_bitstring_NNL(BitList,NamedNumberList,0,[]).
-
-
-decode_bitstring_NNL([],_,_No,Result) ->
- lists:reverse(Result);
-
-decode_bitstring_NNL([B|BitList],[{Name,No}|NamedNumberList],No,Result) ->
- if
- B == 0 ->
- decode_bitstring_NNL(BitList,NamedNumberList,No+1,Result);
- true ->
- decode_bitstring_NNL(BitList,NamedNumberList,No+1,[Name|Result])
- end;
-decode_bitstring_NNL([1|BitList],NamedNumberList,No,Result) ->
- decode_bitstring_NNL(BitList,NamedNumberList,No+1,[{bit,No}|Result]);
-decode_bitstring_NNL([0|BitList],NamedNumberList,No,Result) ->
- decode_bitstring_NNL(BitList,NamedNumberList,No+1,Result).
-
-
-%%============================================================================
-%% Octet string, ITU_T X.690 Chapter 8.7
-%%
-%% encode octet string
-%% The OctetList must be a flat list of integers in the range 0..255
-%% the function does not check this because it takes to much time
-%%============================================================================
-encode_octet_string(_C, OctetList, TagIn) when binary(OctetList) ->
- encode_tags(TagIn, OctetList, size(OctetList));
-encode_octet_string(_C, OctetList, TagIn) when list(OctetList) ->
- encode_tags(TagIn, OctetList, length(OctetList));
-encode_octet_string(C, {Name,OctetList}, TagIn) when atom(Name) ->
- encode_octet_string(C, OctetList, TagIn).
-
-
-%%============================================================================
-%% decode octet string
-%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
-%%
-%% Octet string is decoded as a restricted string
-%%============================================================================
-decode_octet_string(Buffer, Range, Tags) ->
-% NewTags = new_tags(HasTag,#tag{class=?UNIVERSAL,number=?N_OCTET_STRING}),
- decode_restricted_string(Buffer, Range, ?N_OCTET_STRING,
- Tags, [], old).
-
-%%============================================================================
-%% Null value, ITU_T X.690 Chapter 8.8
-%%
-%% encode NULL value
-%%============================================================================
-
-encode_null({Name, _Val}, TagIn) when atom(Name) ->
- encode_tags(TagIn, [], 0);
-encode_null(_Val, TagIn) ->
- encode_tags(TagIn, [], 0).
-
-%%============================================================================
-%% decode NULL value
-%% (Buffer, HasTag, TotalLen) -> {NULL, Remain, RemovedBytes}
-%%============================================================================
-
-decode_null(Tlv, Tags) ->
- Val = match_tags(Tlv, Tags),
- case Val of
- <<>> ->
- 'NULL';
- _ ->
- exit({error,{asn1,{decode_null,Val}}})
- end.
-
-%%============================================================================
-%% Object identifier, ITU_T X.690 Chapter 8.19
-%%
-%% encode Object Identifier value
-%%============================================================================
-
-encode_object_identifier({Name,Val}, TagIn) when atom(Name) ->
- encode_object_identifier(Val, TagIn);
-encode_object_identifier(Val, TagIn) ->
- encode_tags(TagIn, e_object_identifier(Val)).
-
-e_object_identifier({'OBJECT IDENTIFIER', V}) ->
- e_object_identifier(V);
-e_object_identifier({Cname, V}) when atom(Cname), tuple(V) ->
- e_object_identifier(tuple_to_list(V));
-e_object_identifier({Cname, V}) when atom(Cname), list(V) ->
- e_object_identifier(V);
-e_object_identifier(V) when tuple(V) ->
- e_object_identifier(tuple_to_list(V));
-
-%%%%%%%%%%%%%%%
-%% e_object_identifier([List of Obect Identifiers]) ->
-%% {[Encoded Octetlist of ObjIds], IntLength}
-%%
-e_object_identifier([E1, E2 | Tail]) ->
- Head = 40*E1 + E2, % wow!
- {H,Lh} = mk_object_val(Head),
- {R,Lr} = enc_obj_id_tail(Tail, [], 0),
- {[H|R], Lh+Lr}.
-
-enc_obj_id_tail([], Ack, Len) ->
- {lists:reverse(Ack), Len};
-enc_obj_id_tail([H|T], Ack, Len) ->
- {B, L} = mk_object_val(H),
- enc_obj_id_tail(T, [B|Ack], Len+L).
-
-%% e_object_identifier([List of Obect Identifiers]) ->
-%% {[Encoded Octetlist of ObjIds], IntLength}
-%%
-%%e_object_identifier([E1, E2 | Tail]) ->
-%% Head = 40*E1 + E2, % wow!
-%% F = fun(Val, AckLen) ->
-%% {L, Ack} = mk_object_val(Val),
-%% {L, Ack + AckLen}
-%% end,
-%% {Octets, Len} = lists:mapfoldl(F, 0, [Head | Tail]).
-
-%%%%%%%%%%%
-%% mk_object_val(Value) -> {OctetList, Len}
-%% returns a Val as a list of octets, the 8 bit is allways set to one except
-%% for the last octet, where its 0
-%%
-
-
-mk_object_val(Val) when Val =< 127 ->
- {[255 band Val], 1};
-mk_object_val(Val) ->
- mk_object_val(Val bsr 7, [Val band 127], 1).
-mk_object_val(0, Ack, Len) ->
- {Ack, Len};
-mk_object_val(Val, Ack, Len) ->
- mk_object_val(Val bsr 7, [((Val band 127) bor 128) | Ack], Len + 1).
-
-
-
-%%============================================================================
-%% decode Object Identifier value
-%% (Buffer, HasTag, TotalLen) -> {{ObjId}, Remain, RemovedBytes}
-%%============================================================================
-
-decode_object_identifier(Tlv, Tags) ->
- Val = match_tags(Tlv, Tags),
- [AddedObjVal|ObjVals] = dec_subidentifiers(Val,0,[]),
- {Val1, Val2} = if
- AddedObjVal < 40 ->
- {0, AddedObjVal};
- AddedObjVal < 80 ->
- {1, AddedObjVal - 40};
- true ->
- {2, AddedObjVal - 80}
- end,
- list_to_tuple([Val1, Val2 | ObjVals]).
-
-dec_subidentifiers(<<>>,_Av,Al) ->
- lists:reverse(Al);
-dec_subidentifiers(<<1:1,H:7,T/binary>>,Av,Al) ->
- dec_subidentifiers(T,(Av bsl 7) + H,Al);
-dec_subidentifiers(<<H,T/binary>>,Av,Al) ->
- dec_subidentifiers(T,0,[((Av bsl 7) + H)|Al]).
-
-
-%%============================================================================
-%% Restricted character string types, ITU_T X.690 Chapter 8.20
-%%
-%% encode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings
-%%============================================================================
-%% The StringType arg is kept for future use but might be removed
-encode_restricted_string(_C, OctetList, _StringType, TagIn)
- when binary(OctetList) ->
- encode_tags(TagIn, OctetList, size(OctetList));
-encode_restricted_string(_C, OctetList, _StringType, TagIn)
- when list(OctetList) ->
- encode_tags(TagIn, OctetList, length(OctetList));
-encode_restricted_string(C,{Name,OctetL}, StringType, TagIn) when atom(Name)->
- encode_restricted_string(C, OctetL, StringType, TagIn).
-
-%%============================================================================
-%% decode Numeric Printable Teletex Videotex Visible IA5 Graphic General strings
-%% (Buffer, Range, StringType, HasTag, TotalLen) ->
-%% {String, Remain, RemovedBytes}
-%%============================================================================
-
-decode_restricted_string(Buffer, Range, StringType, Tags) ->
- decode_restricted_string(Buffer, Range, StringType, Tags, [], old).
-
-
-decode_restricted_string(Tlv, Range, StringType, TagsIn,
- NamedNumberList, BinOrOld) ->
- Val = match_tags(Tlv, TagsIn),
- Val2 =
- case Val of
- PartList = [_H|_T] -> % constructed val
- Bin = collect_parts(PartList),
- decode_restricted(Bin, StringType,
- NamedNumberList, BinOrOld);
- Bin ->
- decode_restricted(Bin, StringType,
- NamedNumberList, BinOrOld)
- end,
- check_and_convert_restricted_string(Val2,StringType,Range,NamedNumberList,BinOrOld).
-
-
-
-% case StringType of
-% ?N_BIT_STRING when BinOrOld == bin ->
-% {concat_bit_binaries(AccVal, Val), AccRb+Rb};
-% _ when binary(Val),binary(AccVal) ->
-% {<<AccVal/binary,Val/binary>>,AccRb+Rb};
-% _ when binary(Val), AccVal==[] ->
-% {Val,AccRb+Rb};
-% _ ->
-% {AccVal++Val, AccRb+Rb}
-% end,
-
-
-
-decode_restricted(Bin, StringType, NamedNumberList,BinOrOld) ->
- case StringType of
- ?N_BIT_STRING ->
- decode_bit_string2(Bin, NamedNumberList, BinOrOld);
- ?N_UniversalString ->
- mk_universal_string(binary_to_list(Bin));
- ?N_BMPString ->
- mk_BMP_string(binary_to_list(Bin));
- _ ->
- Bin
- end.
-
-
-check_and_convert_restricted_string(Val,StringType,Range,NamedNumberList,_BinOrOld) ->
- {StrLen,NewVal} = case StringType of
- ?N_BIT_STRING when NamedNumberList /= [] ->
- {no_check,Val};
- ?N_BIT_STRING when list(Val) ->
- {length(Val),Val};
- ?N_BIT_STRING when tuple(Val) ->
- {(size(element(2,Val))*8) - element(1,Val),Val};
- _ when binary(Val) ->
- {size(Val),binary_to_list(Val)};
- _ when list(Val) ->
- {length(Val), Val}
- end,
- case Range of
- _ when StrLen == no_check ->
- NewVal;
- [] -> % No length constraint
- NewVal;
- {Lb,Ub} when StrLen >= Lb, Ub >= StrLen -> % variable length constraint
- NewVal;
- {{Lb,_Ub},[]} when StrLen >= Lb ->
- NewVal;
- {{Lb1,Ub1},{Lb2,Ub2}} when StrLen >= Lb1, StrLen =< Ub1;
- StrLen =< Ub2, StrLen >= Lb2 ->
- NewVal;
- StrLen -> % fixed length constraint
- NewVal;
- {_,_} ->
- exit({error,{asn1,{length,Range,Val}}});
- _Len when integer(_Len) ->
- exit({error,{asn1,{length,Range,Val}}});
- _ -> % some strange constraint that we don't support yet
- NewVal
- end.
-
-
-%%============================================================================
-%% encode Universal string
-%%============================================================================
-
-encode_universal_string(C, {Name, Universal}, TagIn) when atom(Name) ->
- encode_universal_string(C, Universal, TagIn);
-encode_universal_string(_C, Universal, TagIn) ->
- OctetList = mk_uni_list(Universal),
- encode_tags(TagIn, OctetList, length(OctetList)).
-
-mk_uni_list(In) ->
- mk_uni_list(In,[]).
-
-mk_uni_list([],List) ->
- lists:reverse(List);
-mk_uni_list([{A,B,C,D}|T],List) ->
- mk_uni_list(T,[D,C,B,A|List]);
-mk_uni_list([H|T],List) ->
- mk_uni_list(T,[H,0,0,0|List]).
-
-%%===========================================================================
-%% decode Universal strings
-%% (Buffer, Range, StringType, HasTag, LenIn) ->
-%% {String, Remain, RemovedBytes}
-%%===========================================================================
-
-decode_universal_string(Buffer, Range, Tags) ->
- decode_restricted_string(Buffer, Range, ?N_UniversalString,
- Tags, [], old).
-
-
-mk_universal_string(In) ->
- mk_universal_string(In,[]).
-
-mk_universal_string([],Acc) ->
- lists:reverse(Acc);
-mk_universal_string([0,0,0,D|T],Acc) ->
- mk_universal_string(T,[D|Acc]);
-mk_universal_string([A,B,C,D|T],Acc) ->
- mk_universal_string(T,[{A,B,C,D}|Acc]).
-
-
-%%============================================================================
-%% encode BMP string
-%%============================================================================
-
-encode_BMP_string(C, {Name,BMPString}, TagIn) when atom(Name)->
- encode_BMP_string(C, BMPString, TagIn);
-encode_BMP_string(_C, BMPString, TagIn) ->
- OctetList = mk_BMP_list(BMPString),
- encode_tags(TagIn, OctetList, length(OctetList)).
-
-mk_BMP_list(In) ->
- mk_BMP_list(In,[]).
-
-mk_BMP_list([],List) ->
- lists:reverse(List);
-mk_BMP_list([{0,0,C,D}|T],List) ->
- mk_BMP_list(T,[D,C|List]);
-mk_BMP_list([H|T],List) ->
- mk_BMP_list(T,[H,0|List]).
-
-%%============================================================================
-%% decode (OctetList, Range(ignored), tag|notag) -> {ValList, RestList}
-%% (Buffer, Range, StringType, HasTag, TotalLen) ->
-%% {String, Remain, RemovedBytes}
-%%============================================================================
-decode_BMP_string(Buffer, Range, Tags) ->
- decode_restricted_string(Buffer, Range, ?N_BMPString,
- Tags, [], old).
-
-mk_BMP_string(In) ->
- mk_BMP_string(In,[]).
-
-mk_BMP_string([],US) ->
- lists:reverse(US);
-mk_BMP_string([0,B|T],US) ->
- mk_BMP_string(T,[B|US]);
-mk_BMP_string([C,D|T],US) ->
- mk_BMP_string(T,[{0,0,C,D}|US]).
-
-
-%%============================================================================
-%% Generalized time, ITU_T X.680 Chapter 39
-%%
-%% encode Generalized time
-%%============================================================================
-
-encode_generalized_time(C, {Name,OctetList}, TagIn) when atom(Name) ->
- encode_generalized_time(C, OctetList, TagIn);
-encode_generalized_time(_C, OctetList, TagIn) ->
- encode_tags(TagIn, OctetList, length(OctetList)).
-
-%%============================================================================
-%% decode Generalized time
-%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
-%%============================================================================
-
-decode_generalized_time(Tlv, _Range, Tags) ->
- Val = match_tags(Tlv, Tags),
- NewVal = case Val of
- PartList = [_H|_T] -> % constructed
- collect_parts(PartList);
- Bin ->
- Bin
- end,
- binary_to_list(NewVal).
-
-%%============================================================================
-%% Universal time, ITU_T X.680 Chapter 40
-%%
-%% encode UTC time
-%%============================================================================
-
-encode_utc_time(C, {Name,OctetList}, TagIn) when atom(Name) ->
- encode_utc_time(C, OctetList, TagIn);
-encode_utc_time(_C, OctetList, TagIn) ->
- encode_tags(TagIn, OctetList, length(OctetList)).
-
-%%============================================================================
-%% decode UTC time
-%% (Buffer, Range, HasTag, TotalLen) -> {String, Remain, RemovedBytes}
-%%============================================================================
-
-decode_utc_time(Tlv, _Range, Tags) ->
- Val = match_tags(Tlv, Tags),
- NewVal = case Val of
- PartList = [_H|_T] -> % constructed
- collect_parts(PartList);
- Bin ->
- Bin
- end,
- binary_to_list(NewVal).
-
-
-%%============================================================================
-%% Length handling
-%%
-%% Encode length
-%%
-%% encode_length(Int | indefinite) ->
-%% [<127]| [128 + Int (<127),OctetList] | [16#80]
-%%============================================================================
-
-encode_length(indefinite) ->
- {[16#80],1}; % 128
-encode_length(L) when L =< 16#7F ->
- {[L],1};
-encode_length(L) ->
- Oct = minimum_octets(L),
- Len = length(Oct),
- if
- Len =< 126 ->
- {[ (16#80+Len) | Oct ],Len+1};
- true ->
- exit({error,{asn1, to_long_length_oct, Len}})
- end.
-
-
-%% Val must be >= 0
-minimum_octets(Val) ->
- minimum_octets(Val,[]).
-
-minimum_octets(0,Acc) ->
- Acc;
-minimum_octets(Val, Acc) ->
- minimum_octets((Val bsr 8),[Val band 16#FF | Acc]).
-
-
-%%===========================================================================
-%% Decode length
-%%
-%% decode_length(OctetList) -> {{indefinite, RestOctetsL}, NoRemovedBytes} |
-%% {{Length, RestOctetsL}, NoRemovedBytes}
-%%===========================================================================
-
-decode_length(<<1:1,0:7,T/binary>>) ->
- {indefinite, T};
-decode_length(<<0:1,Length:7,T/binary>>) ->
- {Length,T};
-decode_length(<<1:1,LL:7,T/binary>>) ->
- <<Length:LL/unit:8,Rest/binary>> = T,
- {Length,Rest}.
-
-
-
-%%-------------------------------------------------------------------------
-%% INTERNAL HELPER FUNCTIONS (not exported)
-%%-------------------------------------------------------------------------
-
-
-%% decoding postitive integer values.
-decode_integer2(Len,Bin = <<0:1,_:7,_Bs/binary>>) ->
- <<Int:Len/unit:8>> = Bin,
- Int;
-%% decoding negative integer values.
-decode_integer2(Len,<<1:1,B2:7,Bs/binary>>) ->
- <<N:Len/unit:8>> = <<B2,Bs/binary>>,
- Int = N - (1 bsl (8 * Len - 1)),
- Int.
-
-get_constraint(C,Key) ->
- case lists:keysearch(Key,1,C) of
- false ->
- no;
- {value,{_,V}} ->
- V
- end.
-
-collect_parts(TlvList) ->
- collect_parts(TlvList,[]).
-
-collect_parts([{_,L}|Rest],Acc) when list(L) ->
- collect_parts(Rest,[collect_parts(L)|Acc]);
-collect_parts([{?N_BIT_STRING,<<Unused,Bits/binary>>}|Rest],_Acc) ->
- collect_parts_bit(Rest,[Bits],Unused);
-collect_parts([{_T,V}|Rest],Acc) ->
- collect_parts(Rest,[V|Acc]);
-collect_parts([],Acc) ->
- list_to_binary(lists:reverse(Acc)).
-
-collect_parts_bit([{?N_BIT_STRING,<<Unused,Bits/binary>>}|Rest],Acc,Uacc) ->
- collect_parts_bit(Rest,[Bits|Acc],Unused+Uacc);
-collect_parts_bit([],Acc,Uacc) ->
- list_to_binary([Uacc|lists:reverse(Acc)]).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_check.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_check.erl
deleted file mode 100644
index bd3d5e6d8b..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_check.erl
+++ /dev/null
@@ -1,333 +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: asn1rt_check.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
-%%
--module(asn1rt_check).
-
--include("asn1_records.hrl").
-
--export([check_bool/2,
- check_int/3,
- check_bitstring/3,
- check_octetstring/2,
- check_null/2,
- check_objectidentifier/2,
- check_objectdescriptor/2,
- check_real/2,
- check_enum/3,
- check_restrictedstring/2]).
-
--export([transform_to_EXTERNAL1990/1,
- transform_to_EXTERNAL1994/1]).
-
-
-check_bool(_Bool,asn1_DEFAULT) ->
- true;
-check_bool(Bool,Bool) when Bool == true; Bool == false ->
- true;
-check_bool(_Bool1,Bool2) ->
- throw({error,Bool2}).
-
-check_int(_,asn1_DEFAULT,_) ->
- true;
-check_int(Value,Value,_) when integer(Value) ->
- true;
-check_int(DefValue,Value,NNL) when atom(Value) ->
- case lists:keysearch(Value,1,NNL) of
- {value,{_,DefValue}} ->
- true;
- _ ->
- throw({error,DefValue})
- end;
-check_int(DefaultValue,_Value,_) ->
- throw({error,DefaultValue}).
-
-% check_bitstring([H|T],[H|T],_) when integer(H) ->
-% true;
-% check_bitstring(V,V,_) when integer(V) ->
-% true;
-%% Two equal lists or integers
-check_bitstring(_,asn1_DEFAULT,_) ->
- true;
-check_bitstring(V,V,_) ->
- true;
-%% Default value as a list of 1 and 0 and user value as an integer
-check_bitstring(L=[H|T],Int,_) when integer(Int),integer(H) ->
- case bit_list_to_int(L,length(T)) of
- Int -> true;
- _ -> throw({error,L,Int})
- end;
-%% Default value as an integer, val as list
-check_bitstring(Int,Val,NBL) when integer(Int),list(Val) ->
- BL = int_to_bit_list(Int,[],length(Val)),
- check_bitstring(BL,Val,NBL);
-%% Default value and user value as lists of ones and zeros
-check_bitstring(L1=[H1|_T1],L2=[H2|_T2],NBL=[_H|_T]) when integer(H1),integer(H2) ->
- L2new = remove_trailing_zeros(L2),
- check_bitstring(L1,L2new,NBL);
-%% Default value as a list of 1 and 0 and user value as a list of atoms
-check_bitstring(L1=[H1|_T1],L2=[H2|_T2],NBL) when integer(H1),atom(H2) ->
- case bit_list_to_nbl(L1,NBL,0,[]) of
- L3 -> check_bitstring(L3,L2,NBL);
- _ -> throw({error,L2})
- end;
-%% Both default value and user value as a list of atoms
-check_bitstring(L1=[H1|T1],L2=[H2|_T2],_) when atom(H1),atom(H2) ->
- length(L1) == length(L2),
- case lists:member(H1,L2) of
- true ->
- check_bitstring1(T1,L2);
- false -> throw({error,L2})
- end;
-%% Default value as a list of atoms and user value as a list of 1 and 0
-check_bitstring(L1=[H1|_T1],L2=[H2|_T2],NBL) when atom(H1),integer(H2) ->
- case bit_list_to_nbl(L2,NBL,0,[]) of
- L3 ->
- check_bitstring(L1,L3,NBL);
- _ -> throw({error,L2})
- end;
-%% User value in compact format
-check_bitstring(DefVal,CBS={_,_},NBL) ->
- NewVal = cbs_to_bit_list(CBS),
- check_bitstring(DefVal,NewVal,NBL);
-check_bitstring(DV,V,_) ->
- throw({error,DV,V}).
-
-
-bit_list_to_int([0|Bs],ShL)->
- bit_list_to_int(Bs,ShL-1) + 0;
-bit_list_to_int([1|Bs],ShL) ->
- bit_list_to_int(Bs,ShL-1) + (1 bsl ShL);
-bit_list_to_int([],_) ->
- 0.
-
-int_to_bit_list(0,Acc,0) ->
- Acc;
-int_to_bit_list(Int,Acc,Len) ->
- int_to_bit_list(Int bsr 1,[Int band 1|Acc],Len - 1).
-
-bit_list_to_nbl([0|T],NBL,Pos,Acc) ->
- bit_list_to_nbl(T,NBL,Pos+1,Acc);
-bit_list_to_nbl([1|T],NBL,Pos,Acc) ->
- case lists:keysearch(Pos,2,NBL) of
- {value,{N,_}} ->
- bit_list_to_nbl(T,NBL,Pos+1,[N|Acc]);
- _ ->
- throw({error,{no,named,element,at,pos,Pos}})
- end;
-bit_list_to_nbl([],_,_,Acc) ->
- Acc.
-
-remove_trailing_zeros(L2) ->
- remove_trailing_zeros1(lists:reverse(L2)).
-remove_trailing_zeros1(L) ->
- lists:reverse(lists:dropwhile(fun(0)->true;
- (_) ->false
- end,
- L)).
-
-check_bitstring1([H|T],NBL) ->
- case lists:member(H,NBL) of
- true ->
- check_bitstring1(T,NBL);
- V -> throw({error,V})
- end;
-check_bitstring1([],_) ->
- true.
-
-cbs_to_bit_list({Unused,<<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Rest/binary>>}) when size(Rest) >= 1 ->
- [B7,B6,B5,B4,B3,B2,B1,B0|cbs_to_bit_list({Unused,Rest})];
-cbs_to_bit_list({0,<<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1>>}) ->
- [B7,B6,B5,B4,B3,B2,B1,B0];
-cbs_to_bit_list({Unused,Bin}) when size(Bin) == 1 ->
- Used = 8-Unused,
- <<Int:Used,_:Unused>> = Bin,
- int_to_bit_list(Int,[],Used).
-
-
-check_octetstring(_,asn1_DEFAULT) ->
- true;
-check_octetstring(L,L) ->
- true;
-check_octetstring(L,Int) when list(L),integer(Int) ->
- case integer_to_octetlist(Int) of
- L -> true;
- V -> throw({error,V})
- end;
-check_octetstring(_,V) ->
- throw({error,V}).
-
-integer_to_octetlist(Int) ->
- integer_to_octetlist(Int,[]).
-integer_to_octetlist(0,Acc) ->
- Acc;
-integer_to_octetlist(Int,Acc) ->
- integer_to_octetlist(Int bsr 8,[(Int band 255)|Acc]).
-
-check_null(_,asn1_DEFAULT) ->
- true;
-check_null('NULL','NULL') ->
- true;
-check_null(_,V) ->
- throw({error,V}).
-
-check_objectidentifier(_,asn1_DEFAULT) ->
- true;
-check_objectidentifier(OI,OI) ->
- true;
-check_objectidentifier(DOI,OI) when tuple(DOI),tuple(OI) ->
- check_objectidentifier1(tuple_to_list(DOI),tuple_to_list(OI));
-check_objectidentifier(_,OI) ->
- throw({error,OI}).
-
-check_objectidentifier1([V|Rest1],[V|Rest2]) ->
- check_objectidentifier1(Rest1,Rest2,V);
-check_objectidentifier1([V1|Rest1],[V2|Rest2]) ->
- case reserved_objectid(V2,[]) of
- V1 ->
- check_objectidentifier1(Rest1,Rest2,[V1]);
- V ->
- throw({error,V})
- end.
-check_objectidentifier1([V|Rest1],[V|Rest2],Above) ->
- check_objectidentifier1(Rest1,Rest2,[V|Above]);
-check_objectidentifier1([V1|Rest1],[V2|Rest2],Above) ->
- case reserved_objectid(V2,Above) of
- V1 ->
- check_objectidentifier1(Rest1,Rest2,[V1|Above]);
- V ->
- throw({error,V})
- end;
-check_objectidentifier1([],[],_) ->
- true;
-check_objectidentifier1(_,V,_) ->
- throw({error,object,identifier,V}).
-
-%% ITU-T Rec. X.680 Annex B - D
-reserved_objectid('itu-t',[]) -> 0;
-reserved_objectid('ccitt',[]) -> 0;
-%% arcs below "itu-t"
-reserved_objectid('recommendation',[0]) -> 0;
-reserved_objectid('question',[0]) -> 1;
-reserved_objectid('administration',[0]) -> 2;
-reserved_objectid('network-operator',[0]) -> 3;
-reserved_objectid('identified-organization',[0]) -> 4;
-
-reserved_objectid(iso,[]) -> 1;
-%% arcs below "iso", note that number 1 is not used
-reserved_objectid('standard',[1]) -> 0;
-reserved_objectid('member-body',[1]) -> 2;
-reserved_objectid('identified-organization',[1]) -> 3;
-
-reserved_objectid('joint-iso-itu-t',[]) -> 2;
-reserved_objectid('joint-iso-ccitt',[]) -> 2;
-
-reserved_objectid(_,_) -> false.
-
-
-check_objectdescriptor(_,asn1_DEFAULT) ->
- true;
-check_objectdescriptor(OD,OD) ->
- true;
-check_objectdescriptor(OD,OD) ->
- throw({error,{not_implemented_yet,check_objectdescriptor}}).
-
-check_real(_,asn1_DEFAULT) ->
- true;
-check_real(R,R) ->
- true;
-check_real(_,_) ->
- throw({error,{not_implemented_yet,check_real}}).
-
-check_enum(_,asn1_DEFAULT,_) ->
- true;
-check_enum(Val,Val,_) ->
- true;
-check_enum(Int,Atom,Enumerations) when integer(Int),atom(Atom) ->
- case lists:keysearch(Atom,1,Enumerations) of
- {value,{_,Int}} -> true;
- _ -> throw({error,{enumerated,Int,Atom}})
- end;
-check_enum(DefVal,Val,_) ->
- throw({error,{enumerated,DefVal,Val}}).
-
-
-check_restrictedstring(_,asn1_DEFAULT) ->
- true;
-check_restrictedstring(Val,Val) ->
- true;
-check_restrictedstring([V|Rest1],[V|Rest2]) ->
- check_restrictedstring(Rest1,Rest2);
-check_restrictedstring([V1|Rest1],[V2|Rest2]) ->
- check_restrictedstring(V1,V2),
- check_restrictedstring(Rest1,Rest2);
-%% tuple format of value
-check_restrictedstring({V1,V2},[V1,V2]) ->
- true;
-check_restrictedstring([V1,V2],{V1,V2}) ->
- true;
-%% quadruple format of value
-check_restrictedstring({V1,V2,V3,V4},[V1,V2,V3,V4]) ->
- true;
-check_restrictedstring([V1,V2,V3,V4],{V1,V2,V3,V4}) ->
- true;
-%% character string list
-check_restrictedstring(V1,V2) when list(V1),tuple(V2) ->
- check_restrictedstring(V1,tuple_to_list(V2));
-check_restrictedstring(V1,V2) ->
- throw({error,{restricted,string,V1,V2}}).
-
-transform_to_EXTERNAL1990(Val) when tuple(Val),size(Val) == 4 ->
- transform_to_EXTERNAL1990(tuple_to_list(Val),[]);
-transform_to_EXTERNAL1990(Val) when tuple(Val) ->
- %% Data already in ASN1 1990 format
- Val.
-
-transform_to_EXTERNAL1990(['EXTERNAL'|Rest],Acc) ->
- transform_to_EXTERNAL1990(Rest,['EXTERNAL'|Acc]);
-transform_to_EXTERNAL1990([{syntax,Syntax}|Rest],Acc) ->
- transform_to_EXTERNAL1990(Rest,[asn1_NOVALUE,Syntax|Acc]);
-transform_to_EXTERNAL1990([{'presentation-context-id',PCid}|Rest],Acc) ->
- transform_to_EXTERNAL1990(Rest,[PCid,asn1_NOVALUE|Acc]);
-transform_to_EXTERNAL1990([{'context-negotiation',Context_negot}|Rest],Acc) ->
- {_,Presentation_Cid,Transfer_syntax} = Context_negot,
- transform_to_EXTERNAL1990(Rest,[Transfer_syntax,Presentation_Cid|Acc]);
-transform_to_EXTERNAL1990([asn1_NOVALUE|Rest],Acc) ->
- transform_to_EXTERNAL1990(Rest,[asn1_NOVALUE|Acc]);
-transform_to_EXTERNAL1990([Data_val_desc,Data_value],Acc) when list(Data_value)->
- list_to_tuple(lists:reverse([{'octet-aligned',Data_value},
- Data_val_desc|Acc]));
-transform_to_EXTERNAL1990([Data_value],Acc) when list(Data_value)->
- list_to_tuple(lists:reverse([{'octet-aligned',Data_value}|Acc])).
-
-
-transform_to_EXTERNAL1994(V={'EXTERNAL',DRef,IndRef,Data_v_desc,Encoding}) ->
- Identification =
- case {DRef,IndRef} of
- {DRef,asn1_NOVALUE} ->
- {syntax,DRef};
- {asn1_NOVALUE,IndRef} ->
- {'presentation-context-id',IndRef};
- _ ->
- {'context-negotiation',
- {'EXTERNAL_identification_context-negotiation',IndRef,DRef}}
- end,
- case Encoding of
- {_,Val} when list(Val) ->
- {'EXTERNAL',Identification,Data_v_desc,Val};
- _ ->
- V
- end.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_driver_handler.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_driver_handler.erl
deleted file mode 100644
index 7a986b5376..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_driver_handler.erl
+++ /dev/null
@@ -1,108 +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: asn1rt_driver_handler.erl,v 1.1 2008/12/17 09:53:30 mikpe Exp $
-%%
-
--module(asn1rt_driver_handler).
-
--export([init/1,load_driver/0,unload_driver/0]).
-
-
-load_driver() ->
- spawn(asn1rt_driver_handler, init, [self()]).
-
-init(From) ->
- Port=
- case load_driver("asn1_erl_drv") of
- ok ->
- open_named_port(From);
- already_done ->
- From ! driver_ready;
- Error -> % if erl_ddll:load_driver fails
- erl_ddll:unload_driver("asn1_erl_drv"),
- From ! Error
- end,
- register_and_loop(Port).
-
-load_driver(DriverName) ->
- case is_driver_loaded(DriverName) of
- false ->
- Dir = filename:join([code:priv_dir(asn1),"lib"]),
- erl_ddll:load_driver(Dir,DriverName);
- true ->
- ok
- end.
-
-
-is_driver_loaded(_Name) ->
- case whereis(asn1_driver_owner) of
- undefined ->
- false;
- _ ->
- true
- end.
-
-open_named_port(From) ->
- case is_port_open(drv_complete) of
- false ->
- case catch open_port({spawn,"asn1_erl_drv"},[]) of
- {'EXIT',Reason} ->
- From ! {port_error,Reason};
- Port ->
- register(drv_complete,Port),
- From ! driver_ready,
- Port
- end;
- _ ->
- From ! driver_ready,
- ok
- end.
-
-is_port_open(Name) ->
- case whereis(Name) of
- Port when port(Port) ->
- true;
- _ -> false
- end.
-
-register_and_loop(Port) when port(Port) ->
- register(asn1_driver_owner,self()),
- loop();
-register_and_loop(_) ->
- ok.
-
-loop() ->
- receive
- unload ->
- case whereis(drv_complete) of
- Port when port(Port) ->
- port_close(Port);
- _ -> ok
- end,
- erl_ddll:unload_driver("asn1_erl_drv"),
- ok;
- _ ->
- loop()
- end.
-
-unload_driver() ->
- case whereis(asn1_driver_owner) of
- Pid when pid(Pid) ->
- Pid ! unload,
- ok;
- _ ->
- ok
- end.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per.erl
deleted file mode 100644
index d531a165ae..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per.erl
+++ /dev/null
@@ -1,1609 +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: asn1rt_per.erl,v 1.1 2008/12/17 09:53:31 mikpe Exp $
-%%
--module(asn1rt_per).
-
-%% encoding / decoding of PER aligned
-
--include("asn1_records.hrl").
-
--export([dec_fixup/3, cindex/3, list_to_record/2]).
--export([setchoiceext/1, setext/1, fixoptionals/2, fixextensions/2, setoptionals/1,
- getext/1, getextension/2, skipextensions/3, getbit/1, getchoice/3 ]).
--export([getoptionals/3, set_choice/3, encode_integer/2, encode_integer/3 ]).
--export([decode_integer/2, decode_integer/3, encode_boolean/1,
- decode_boolean/1, encode_length/2, decode_length/1, decode_length/2,
- encode_small_length/1, decode_small_length/1]).
--export([encode_enumerated/3, decode_enumerated/3,
- encode_bit_string/3, decode_bit_string/3 ]).
--export([encode_octet_string/2, decode_octet_string/2,
- encode_restricted_string/4, encode_restricted_string/5,
- decode_restricted_string/4, decode_restricted_string/5,
- encode_null/1, decode_null/1,
- encode_object_identifier/1, decode_object_identifier/1,
- complete/1]).
-
--export([encode_open_type/2, decode_open_type/2]).
-
--export([encode_UniversalString/2, decode_UniversalString/2,
- encode_PrintableString/2, decode_PrintableString/2,
- encode_GeneralString/2, decode_GeneralString/2,
- encode_GraphicString/2, decode_GraphicString/2,
- encode_TeletexString/2, decode_TeletexString/2,
- encode_VideotexString/2, decode_VideotexString/2,
- encode_VisibleString/2, decode_VisibleString/2,
- encode_BMPString/2, decode_BMPString/2,
- encode_IA5String/2, decode_IA5String/2,
- encode_NumericString/2, decode_NumericString/2
- ]).
-
-
-dec_fixup(Terms,Cnames,RemBytes) ->
- dec_fixup(Terms,Cnames,RemBytes,[]).
-
-dec_fixup([novalue|T],[_Hc|Tc],RemBytes,Acc) ->
- dec_fixup(T,Tc,RemBytes,Acc);
-dec_fixup([{_Name,novalue}|T],[_Hc|Tc],RemBytes,Acc) ->
- dec_fixup(T,Tc,RemBytes,Acc);
-dec_fixup([H|T],[Hc|Tc],RemBytes,Acc) ->
- dec_fixup(T,Tc,RemBytes,[{Hc,H}|Acc]);
-dec_fixup([],_Cnames,RemBytes,Acc) ->
- {lists:reverse(Acc),RemBytes}.
-
-cindex(Ix,Val,Cname) ->
- case element(Ix,Val) of
- {Cname,Val2} -> Val2;
- X -> X
- end.
-
-% converts a list to a record if necessary
-list_to_record(Name,List) when list(List) ->
- list_to_tuple([Name|List]);
-list_to_record(_Name,Tuple) when tuple(Tuple) ->
- Tuple.
-
-%%--------------------------------------------------------
-%% setchoiceext(InRootSet) -> [{bit,X}]
-%% X is set to 1 when InRootSet==false
-%% X is set to 0 when InRootSet==true
-%%
-setchoiceext(true) ->
- [{debug,choiceext},{bit,0}];
-setchoiceext(false) ->
- [{debug,choiceext},{bit,1}].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% setext(true|false) -> CompleteList
-%%
-
-setext(true) ->
- [{debug,ext},{bit,1}];
-setext(false) ->
- [{debug,ext},{bit,0}].
-
-fixoptionals(OptList,Val) when tuple(Val) ->
- fixoptionals(OptList,Val,[]);
-
-fixoptionals(OptList,Val) when list(Val) ->
- fixoptionals(OptList,Val,1,[],[]).
-
-fixoptionals([],Val,Acc) ->
- % return {Val,Opt}
- {Val,lists:reverse(Acc)};
-fixoptionals([{_,Pos}|Ot],Val,Acc) ->
- case element(Pos+1,Val) of
- asn1_NOVALUE -> fixoptionals(Ot,Val,[0|Acc]);
- asn1_DEFAULT -> fixoptionals(Ot,Val,[0|Acc]);
- _ -> fixoptionals(Ot,Val,[1|Acc])
- end.
-
-
-%setoptionals(OptList,Val) ->
-% Vlist = tuple_to_list(Val),
-% setoptionals(OptList,Vlist,1,[]).
-
-fixoptionals([{Name,Pos}|Ot],[{Name,Val}|Vt],_Opt,Acc1,Acc2) ->
- fixoptionals(Ot,Vt,Pos+1,[1|Acc1],[{Name,Val}|Acc2]);
-fixoptionals([{_Name,Pos}|Ot],V,Pos,Acc1,Acc2) ->
- fixoptionals(Ot,V,Pos+1,[0|Acc1],[asn1_NOVALUE|Acc2]);
-fixoptionals(O,[Vh|Vt],Pos,Acc1,Acc2) ->
- fixoptionals(O,Vt,Pos+1,Acc1,[Vh|Acc2]);
-fixoptionals([],[Vh|Vt],Pos,Acc1,Acc2) ->
- fixoptionals([],Vt,Pos+1,Acc1,[Vh|Acc2]);
-fixoptionals([],[],_,Acc1,Acc2) ->
- % return {Val,Opt}
- {list_to_tuple([asn1_RECORDNAME|lists:reverse(Acc2)]),lists:reverse(Acc1)}.
-
-setoptionals([H|T]) ->
- [{bit,H}|setoptionals(T)];
-setoptionals([]) ->
- [{debug,optionals}].
-
-getext(Bytes) when tuple(Bytes) ->
- getbit(Bytes);
-getext(Bytes) when list(Bytes) ->
- getbit({0,Bytes}).
-
-getextension(0, Bytes) ->
- {{},Bytes};
-getextension(1, Bytes) ->
- {Len,Bytes2} = decode_small_length(Bytes),
- {Blist, Bytes3} = getbits_as_list(Len,Bytes2),
- {list_to_tuple(Blist),Bytes3}.
-
-fixextensions({ext,ExtPos,ExtNum},Val) ->
- case fixextensions(ExtPos,ExtNum+ExtPos,Val,0) of
- 0 -> [];
- ExtBits ->
- [encode_small_length(ExtNum),{bits,ExtNum,ExtBits}]
- end.
-
-fixextensions(Pos,MaxPos,_,Acc) when Pos >= MaxPos ->
- Acc;
-fixextensions(Pos,ExtPos,Val,Acc) ->
- Bit = case catch(element(Pos+1,Val)) of
- asn1_NOVALUE ->
- 0;
- asn1_NOEXTVALUE ->
- 0;
- {'EXIT',_} ->
- 0;
- _ ->
- 1
- end,
- fixextensions(Pos+1,ExtPos,Val,(Acc bsl 1)+Bit).
-
-skipextensions(Bytes,Nr,ExtensionBitPattern) ->
- case (catch element(Nr,ExtensionBitPattern)) of
- 1 ->
- {_,Bytes2} = decode_open_type(Bytes,[]),
- skipextensions(Bytes2, Nr+1, ExtensionBitPattern);
- 0 ->
- skipextensions(Bytes, Nr+1, ExtensionBitPattern);
- {'EXIT',_} -> % badarg, no more extensions
- Bytes
- end.
-
-
-getchoice(Bytes,1,0) -> % only 1 alternative is not encoded
- {0,Bytes};
-getchoice(Bytes,_NumChoices,1) ->
- decode_small_number(Bytes);
-getchoice(Bytes,NumChoices,0) ->
- decode_integer(Bytes,[{'ValueRange',{0,NumChoices-1}}]).
-
-getoptionals(Bytes,L,NumComp) when list(L) ->
- {Blist,Bytes1} = getbits_as_list(length(L),Bytes),
- {list_to_tuple(comptuple(Blist,L,NumComp,1)),Bytes1}.
-
-comptuple([Bh|Bt],[{_Name,Nr}|T],NumComp,Nr) ->
- [Bh|comptuple(Bt,T,NumComp-1,Nr+1)];
-comptuple(Bl,[{Name,Tnr}|Tl],NumComp,Nr) ->
- [0|comptuple(Bl,[{Name,Tnr}|Tl],NumComp-1,Nr+1)];
-comptuple(_B,_L,0,_Nr) ->
- [];
-comptuple(B,O,N,Nr) ->
- [0|comptuple(B,O,N-1,Nr+1)].
-
-getbits_as_list(Num,Bytes) ->
- getbits_as_list(Num,Bytes,[]).
-
-getbits_as_list(0,Bytes,Acc) ->
- {lists:reverse(Acc),Bytes};
-getbits_as_list(Num,Bytes,Acc) ->
- {Bit,NewBytes} = getbit(Bytes),
- getbits_as_list(Num-1,NewBytes,[Bit|Acc]).
-
-getbit(Bytes) ->
-% io:format("getbit:~p~n",[Bytes]),
- getbit1(Bytes).
-
-getbit1({7,[H|T]}) ->
- {H band 1,{0,T}};
-getbit1({Pos,[H|T]}) ->
- {(H bsr (7-Pos)) band 1,{(Pos+1) rem 8,[H|T]}};
-getbit1(Bytes) when list(Bytes) ->
- getbit1({0,Bytes}).
-
-%% This could be optimized
-getbits(Buffer,Num) ->
-% io:format("getbits:Buffer = ~p~nNum=~p~n",[Buffer,Num]),
- getbits(Buffer,Num,0).
-
-getbits(Buffer,0,Acc) ->
- {Acc,Buffer};
-getbits(Buffer,Num,Acc) ->
- {B,NewBuffer} = getbit(Buffer),
- getbits(NewBuffer,Num-1,B + (Acc bsl 1)).
-
-
-getoctet(Bytes) when list(Bytes) ->
- getoctet({0,Bytes});
-getoctet(Bytes) ->
-% io:format("getoctet:Buffer = ~p~n",[Bytes]),
- getoctet1(Bytes).
-
-getoctet1({0,[H|T]}) ->
- {H,{0,T}};
-getoctet1({_Pos,[_,H|T]}) ->
- {H,{0,T}}.
-
-align({0,L}) ->
- {0,L};
-align({_Pos,[_H|T]}) ->
- {0,T};
-align(Bytes) ->
- {0,Bytes}.
-
-getoctets(Buffer,Num) ->
-% io:format("getoctets:Buffer = ~p~nNum = ~p~n",[Buffer,Num]),
- getoctets(Buffer,Num,0).
-
-getoctets(Buffer,0,Acc) ->
- {Acc,Buffer};
-getoctets(Buffer,Num,Acc) ->
- {Oct,NewBuffer} = getoctet(Buffer),
- getoctets(NewBuffer,Num-1,(Acc bsl 8)+Oct).
-
-getoctets_as_list(Buffer,Num) ->
- getoctets_as_list(Buffer,Num,[]).
-
-getoctets_as_list(Buffer,0,Acc) ->
- {lists:reverse(Acc),Buffer};
-getoctets_as_list(Buffer,Num,Acc) ->
- {Oct,NewBuffer} = getoctet(Buffer),
- getoctets_as_list(NewBuffer,Num-1,[Oct|Acc]).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% set_choice(Alt,Choices,Altnum) -> ListofBitSettings
-%% Alt = atom()
-%% Altnum = integer() | {integer(),integer()}% number of alternatives
-%% Choices = [atom()] | {[atom()],[atom()]}
-%% When Choices is a tuple the first list is the Rootset and the
-%% second is the Extensions and then Altnum must also be a tuple with the
-%% lengths of the 2 lists
-%%
-set_choice(Alt,{L1,L2},{Len1,_Len2}) ->
- case set_choice_tag(Alt,L1) of
- N when integer(N), Len1 > 1 ->
- [{bit,0}, % the value is in the root set
- encode_integer([{'ValueRange',{0,Len1-1}}],N)];
- N when integer(N) ->
- [{bit,0}]; % no encoding if only 0 or 1 alternative
- false ->
- [{bit,1}, % extension value
- case set_choice_tag(Alt,L2) of
- N2 when integer(N2) ->
- encode_small_number(N2);
- false ->
- unknown_choice_alt
- end]
- end;
-set_choice(Alt,L,Len) ->
- case set_choice_tag(Alt,L) of
- N when integer(N), Len > 1 ->
- encode_integer([{'ValueRange',{0,Len-1}}],N);
- N when integer(N) ->
- []; % no encoding if only 0 or 1 alternative
- false ->
- [unknown_choice_alt]
- end.
-
-set_choice_tag(Alt,Choices) ->
- set_choice_tag(Alt,Choices,0).
-
-set_choice_tag(Alt,[Alt|_Rest],Tag) ->
- Tag;
-set_choice_tag(Alt,[_H|Rest],Tag) ->
- set_choice_tag(Alt,Rest,Tag+1);
-set_choice_tag(_,[],_) ->
- false.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_open_type(Constraint, Value) -> CompleteList
-%% Value = list of bytes of an already encoded value (the list must be flat)
-%% | binary
-%% Contraint = not used in this version
-%%
-encode_open_type(_Constraint, Val) when list(Val) ->
- [encode_length(undefined,length(Val)),align,
- {octets,Val}];
-encode_open_type(_Constraint, Val) when binary(Val) ->
- [encode_length(undefined,size(Val)),align,
- {octets,binary_to_list(Val)}].
-%% the binary_to_list is not optimal but compatible with the current solution
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_open_type(Buffer,Constraint) -> Value
-%% Constraint is not used in this version
-%% Buffer = [byte] with PER encoded data
-%% Value = [byte] with decoded data (which must be decoded again as some type)
-%%
-decode_open_type(Bytes, _Constraint) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- Bytes3 = align(Bytes2),
- getoctets_as_list(Bytes3,Len).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_integer(Constraint,Value,NamedNumberList) -> CompleteList
-%% encode_integer(Constraint,Value) -> CompleteList
-%% encode_integer(Constraint,{Name,Value}) -> CompleteList
-%%
-%%
-encode_integer(C,V,NamedNumberList) when atom(V) ->
- case lists:keysearch(V,1,NamedNumberList) of
- {value,{_,NewV}} ->
- encode_integer(C,NewV);
- _ ->
- exit({error,{asn1,{namednumber,V}}})
- end;
-encode_integer(C,V,_NamedNumberList) when integer(V) ->
- encode_integer(C,V).
-
-encode_integer(C,{Name,Val}) when atom(Name) ->
- encode_integer(C,Val);
-
-encode_integer({Rc,_Ec},Val) ->
- case (catch encode_integer(Rc,Val)) of
- {'EXIT',{error,{asn1,_}}} ->
- [{bit,1},encode_unconstrained_number(Val)];
- Encoded ->
- [{bit,0},Encoded]
- end;
-encode_integer(C,Val ) when list(C) ->
- case get_constraint(C,'SingleValue') of
- no ->
- encode_integer1(C,Val);
- V when integer(V),V == Val ->
- []; % a type restricted to a single value encodes to nothing
- V when list(V) ->
- case lists:member(Val,V) of
- true ->
- encode_integer1(C,Val);
- _ ->
- exit({error,{asn1,{illegal_value,Val}}})
- end;
- _ ->
- exit({error,{asn1,{illegal_value,Val}}})
- end.
-
-encode_integer1(C, Val) ->
- case VR = get_constraint(C,'ValueRange') of
- no ->
- encode_unconstrained_number(Val);
- {Lb,'MAX'} ->
- encode_semi_constrained_number(Lb,Val);
- %% positive with range
- {Lb,Ub} when Val >= Lb,
- Ub >= Val ->
- encode_constrained_number(VR,Val)
- end.
-
-decode_integer(Buffer,Range,NamedNumberList) ->
- {Val,Buffer2} = decode_integer(Buffer,Range),
- case lists:keysearch(Val,2,NamedNumberList) of
- {value,{NewVal,_}} -> {NewVal,Buffer2};
- _ -> {Val,Buffer2}
- end.
-
-decode_integer(Buffer,{Rc,_Ec}) ->
- {Ext,Buffer2} = getext(Buffer),
- case Ext of
- 0 -> decode_integer(Buffer2,Rc);
- 1 -> decode_unconstrained_number(Buffer2)
- end;
-decode_integer(Buffer,undefined) ->
- decode_unconstrained_number(Buffer);
-decode_integer(Buffer,C) ->
- case get_constraint(C,'SingleValue') of
- V when integer(V) ->
- {V,Buffer};
- V when list(V) ->
- {Val,Buffer2} = decode_integer1(Buffer,C),
- case lists:member(Val,V) of
- true ->
- {Val,Buffer2};
- _ ->
- exit({error,{asn1,{illegal_value,Val}}})
- end;
- _ ->
- decode_integer1(Buffer,C)
- end.
-
-decode_integer1(Buffer,C) ->
- case VR = get_constraint(C,'ValueRange') of
- no ->
- decode_unconstrained_number(Buffer);
- {Lb, 'MAX'} ->
- decode_semi_constrained_number(Buffer,Lb);
- {_,_} ->
- decode_constrained_number(Buffer,VR)
- end.
-
-% X.691:10.6 Encoding of a normally small non-negative whole number
-% Use this for encoding of CHOICE index if there is an extension marker in
-% the CHOICE
-encode_small_number({Name,Val}) when atom(Name) ->
- encode_small_number(Val);
-encode_small_number(Val) when Val =< 63 ->
- [{bit,0},{bits,6,Val}];
-encode_small_number(Val) ->
- [{bit,1},encode_semi_constrained_number(0,Val)].
-
-decode_small_number(Bytes) ->
- {Bit,Bytes2} = getbit(Bytes),
- case Bit of
- 0 ->
- getbits(Bytes2,6);
- 1 ->
- decode_semi_constrained_number(Bytes2,{0,'MAX'})
- end.
-
-% X.691:10.7 Encoding of a semi-constrained whole number
-%% might be an optimization encode_semi_constrained_number(0,Val) ->
-encode_semi_constrained_number(C,{Name,Val}) when atom(Name) ->
- encode_semi_constrained_number(C,Val);
-encode_semi_constrained_number({Lb,'MAX'},Val) ->
- encode_semi_constrained_number(Lb,Val);
-encode_semi_constrained_number(Lb,Val) ->
- Val2 = Val - Lb,
- Octs = eint_positive(Val2),
- [encode_length(undefined,length(Octs)),{octets,Octs}].
-
-decode_semi_constrained_number(Bytes,{Lb,_}) ->
- decode_semi_constrained_number(Bytes,Lb);
-decode_semi_constrained_number(Bytes,Lb) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {V,Bytes3} = getoctets(Bytes2,Len),
- {V+Lb,Bytes3}.
-
-encode_constrained_number(Range,{Name,Val}) when atom(Name) ->
- encode_constrained_number(Range,Val);
-encode_constrained_number({Lb,Ub},Val) when Val >= Lb, Ub >= Val ->
- Range = Ub - Lb + 1,
- Val2 = Val - Lb,
- if
- Range == 2 ->
- {bits,1,Val2};
- Range =< 4 ->
- {bits,2,Val2};
- Range =< 8 ->
- {bits,3,Val2};
- Range =< 16 ->
- {bits,4,Val2};
- Range =< 32 ->
- {bits,5,Val2};
- Range =< 64 ->
- {bits,6,Val2};
- Range =< 128 ->
- {bits,7,Val2};
- Range =< 255 ->
- {bits,8,Val2};
- Range =< 256 ->
- {octets,1,Val2};
- Range =< 65536 ->
- {octets,2,Val2};
- Range =< 16#1000000 ->
- Octs = eint_positive(Val2),
- [encode_length({1,3},length(Octs)),{octets,Octs}];
- Range =< 16#100000000 ->
- Octs = eint_positive(Val2),
- [encode_length({1,4},length(Octs)),{octets,Octs}];
- Range =< 16#10000000000 ->
- Octs = eint_positive(Val2),
- [encode_length({1,5},length(Octs)),{octets,Octs}];
- true ->
- exit({not_supported,{integer_range,Range}})
- end.
-
-decode_constrained_number(Buffer,{Lb,Ub}) ->
- Range = Ub - Lb + 1,
-% Val2 = Val - Lb,
- {Val,Remain} =
- if
- Range == 2 ->
- getbits(Buffer,1);
- Range =< 4 ->
- getbits(Buffer,2);
- Range =< 8 ->
- getbits(Buffer,3);
- Range =< 16 ->
- getbits(Buffer,4);
- Range =< 32 ->
- getbits(Buffer,5);
- Range =< 64 ->
- getbits(Buffer,6);
- Range =< 128 ->
- getbits(Buffer,7);
- Range =< 255 ->
- getbits(Buffer,8);
- Range =< 256 ->
- getoctets(Buffer,1);
- Range =< 65536 ->
- getoctets(Buffer,2);
- Range =< 16#1000000 ->
- {Len,Bytes2} = decode_length(Buffer,{1,3}),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- {dec_pos_integer(Octs),Bytes3};
- Range =< 16#100000000 ->
- {Len,Bytes2} = decode_length(Buffer,{1,4}),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- {dec_pos_integer(Octs),Bytes3};
- Range =< 16#10000000000 ->
- {Len,Bytes2} = decode_length(Buffer,{1,5}),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- {dec_pos_integer(Octs),Bytes3};
- true ->
- exit({not_supported,{integer_range,Range}})
- end,
- {Val+Lb,Remain}.
-
-% X.691:10.8 Encoding of an unconstrained whole number
-
-encode_unconstrained_number(Val) when Val >= 0 ->
- Oct = eint(Val,[]),
- [{debug,unconstrained_number},
- encode_length({0,'MAX'},length(Oct)),
- {octets,Oct}];
-encode_unconstrained_number(Val) -> % negative
- Oct = enint(Val,[]),
- [{debug,unconstrained_number},
- encode_length({0,'MAX'},length(Oct)),
- {octets,Oct}].
-
-%% used for positive Values which don't need a sign bit
-eint_positive(Val) ->
- case eint(Val,[]) of
- [0,B1|T] ->
- [B1|T];
- T ->
- T
- end.
-
-eint(0, [B|Acc]) when B < 128 ->
- [B|Acc];
-eint(N, Acc) ->
- eint(N bsr 8, [N band 16#ff| Acc]).
-
-enint(-1, [B1|T]) when B1 > 127 ->
- [B1|T];
-enint(N, Acc) ->
- enint(N bsr 8, [N band 16#ff|Acc]).
-
-%% used for signed positive values
-
-%eint(Val, Ack) ->
-% X = Val band 255,
-% Next = Val bsr 8,
-% if
-% Next == 0, X >= 127 ->
-% [0,X|Ack];
-% Next == 0 ->
-% [X|Ack];
-% true ->
-% eint(Next,[X|Ack])
-% end.
-
-%%% used for signed negative values
-%enint(Val, Acc) ->
-% NumOctets = if
-% -Val < 16#80 -> 1;
-% -Val < 16#8000 ->2;
-% -Val < 16#800000 ->3;
-% -Val < 16#80000000 ->4;
-% -Val < 16#8000000000 ->5;
-% -Val < 16#800000000000 ->6;
-% -Val < 16#80000000000000 ->7;
-% -Val < 16#8000000000000000 ->8;
-% -Val < 16#800000000000000000 ->9
-% end,
-% enint(Val,Acc,NumOctets).
-
-%enint(Val, Acc,0) ->
-% Acc;
-%enint(Val, Acc,NumOctets) ->
-% enint(Val bsr 8,[Val band 255|Acc],NumOctets-1).
-
-
-decode_unconstrained_number(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {Ints,Bytes3} = getoctets_as_list(Bytes2,Len),
- {dec_integer(Ints),Bytes3}.
-
-dec_pos_integer(Ints) ->
- decpint(Ints, 8 * (length(Ints) - 1)).
-dec_integer(Ints) when hd(Ints) band 255 =< 127 -> %% Positive number
- decpint(Ints, 8 * (length(Ints) - 1));
-dec_integer(Ints) -> %% Negative
- decnint(Ints, 8 * (length(Ints) - 1)).
-
-decpint([Byte|Tail], Shift) ->
- (Byte bsl Shift) bor decpint(Tail, Shift-8);
-decpint([], _) -> 0.
-
-decnint([Byte|Tail], Shift) ->
- (-128 + (Byte band 127) bsl Shift) bor decpint(Tail, Shift-8).
-
-minimum_octets(Val) ->
- minimum_octets(Val,[]).
-
-minimum_octets(Val,Acc) when Val > 0 ->
- minimum_octets((Val bsr 8),[Val band 16#FF|Acc]);
-minimum_octets(0,Acc) ->
- Acc.
-
-
-%% X.691:10.9 Encoding of a length determinant
-%%encode_small_length(undefined,Len) -> % null means no UpperBound
-%% encode_small_number(Len).
-
-%% X.691:10.9.3.5
-%% X.691:10.9.3.7
-encode_length(undefined,Len) -> % un-constrained
- if
- Len < 128 ->
- {octet,Len band 16#7F};
- Len < 16384 ->
- {octets,2,2#1000000000000000 bor Len};
- true ->
- exit({error,{asn1,{encode_length,{nyi,above_16k}}}})
- end;
-
-encode_length({0,'MAX'},Len) ->
- encode_length(undefined,Len);
-encode_length({Lb,Ub},Len) when Ub =< 65535 ,Lb >= 0 -> % constrained
- encode_constrained_number({Lb,Ub},Len);
-encode_length(SingleValue,_Len) when integer(SingleValue) ->
- [].
-
-encode_small_length(Len) when Len =< 64 ->
- [{bit,0},{bits,6,Len-1}];
-encode_small_length(Len) ->
- [{bit,1},encode_length(undefined,Len)].
-
-decode_small_length(Buffer) ->
- case getbit(Buffer) of
- {0,Remain} ->
- {Bits,Remain2} = getbits(Remain,6),
- {Bits+1,Remain2};
- {1,Remain} ->
- decode_length(Remain,undefined)
- end.
-
-decode_length(Buffer) ->
- decode_length(Buffer,undefined).
-
-decode_length(Buffer,undefined) -> % un-constrained
- Buffer2 = align(Buffer),
- {Bits,_} = getbits(Buffer2,2),
- case Bits of
- 2 ->
- {Val,Bytes3} = getoctets(Buffer2,2),
- {(Val band 16#3FFF),Bytes3};
- 3 ->
- exit({error,{asn1,{decode_length,{nyi,above_16k}}}});
- _ ->
- {Val,Bytes3} = getoctet(Buffer2),
- {Val band 16#7F,Bytes3}
- end;
-
-decode_length(Buffer,{Lb,Ub}) when Ub =< 65535 ,Lb >= 0 -> % constrained
- decode_constrained_number(Buffer,{Lb,Ub});
- % X.691:10.9.3.5
-decode_length(Buffer,{_,_Lb,_Ub}) -> %when Len =< 127 -> % Unconstrained or large Ub
- case getbit(Buffer) of
- {0,Remain} ->
- getbits(Remain,7);
- {1,_Remain} ->
- {Val,Remain2} = getoctets(Buffer,2),
- {Val band 2#0111111111111111, Remain2}
- end;
-decode_length(Buffer,SingleValue) when integer(SingleValue) ->
- {SingleValue,Buffer}.
-
-
-% X.691:11
-encode_boolean({Name,Val}) when atom(Name) ->
- encode_boolean(Val);
-encode_boolean(true) ->
- {bit,1};
-encode_boolean(false) ->
- {bit,0};
-encode_boolean(Val) ->
- exit({error,{asn1,{encode_boolean,Val}}}).
-
-
-decode_boolean(Buffer) -> %when record(Buffer,buffer)
- case getbit(Buffer) of
- {1,Remain} -> {true,Remain};
- {0,Remain} -> {false,Remain}
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% X.691:12
-%% ENUMERATED
-%%
-%% encode_enumerated(C,Value,NamedNumberTup) -> CompleteList
-%%
-%%
-
-encode_enumerated(C,{Name,Value},NamedNumberList) when
- atom(Name),list(NamedNumberList) ->
- encode_enumerated(C,Value,NamedNumberList);
-
-%% ENUMERATED with extension mark
-encode_enumerated(_C,{asn1_enum,Value},{_Nlist1,Nlist2}) when Value >= length(Nlist2) ->
- [{bit,1},encode_small_number(Value)];
-encode_enumerated(C,Value,{Nlist1,Nlist2}) ->
- case enum_search(Value,Nlist1,0) of
- NewV when integer(NewV) ->
- [{bit,0},encode_integer(C,NewV)];
- false ->
- case enum_search(Value,Nlist2,0) of
- ExtV when integer(ExtV) ->
- [{bit,1},encode_small_number(ExtV)];
- false ->
- exit({error,{asn1,{encode_enumerated,Value}}})
- end
- end;
-
-encode_enumerated(C,Value,NamedNumberList) when list(NamedNumberList) ->
- case enum_search(Value,NamedNumberList,0) of
- NewV when integer(NewV) ->
- encode_integer(C,NewV);
- false ->
- exit({error,{asn1,{encode_enumerated,Value}}})
- end.
-
-%% returns the ordinal number from 0 ,1 ... in the list where Name is found
-%% or false if not found
-%%
-enum_search(Name,[Name|_NamedNumberList],Acc) ->
- Acc;
-enum_search(Name,[_H|T],Acc) ->
- enum_search(Name,T,Acc+1);
-enum_search(_,[],_) ->
- false. % name not found !error
-
-%% ENUMERATED with extension marker
-decode_enumerated(Buffer,C,{Ntup1,Ntup2}) when tuple(Ntup1), tuple(Ntup2) ->
- {Ext,Buffer2} = getext(Buffer),
- case Ext of
- 0 -> % not an extension value
- {Val,Buffer3} = decode_integer(Buffer2,C),
- case catch (element(Val+1,Ntup1)) of
- NewVal when atom(NewVal) -> {NewVal,Buffer3};
- _Error -> exit({error,{asn1,{decode_enumerated,{Val,[Ntup1,Ntup2]}}}})
- end;
- 1 -> % this an extension value
- {Val,Buffer3} = decode_small_number(Buffer2),
- case catch (element(Val+1,Ntup2)) of
- NewVal when atom(NewVal) -> {NewVal,Buffer3};
- _ -> {{asn1_enum,Val},Buffer3}
- end
- end;
-
-decode_enumerated(Buffer,C,NamedNumberTup) when tuple(NamedNumberTup) ->
- {Val,Buffer2} = decode_integer(Buffer,C),
- case catch (element(Val+1,NamedNumberTup)) of
- NewVal when atom(NewVal) -> {NewVal,Buffer2};
- _Error -> exit({error,{asn1,{decode_enumerated,{Val,NamedNumberTup}}}})
- end.
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Bitstring value, ITU_T X.690 Chapter 8.5
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-%%===============================================================================
-%% encode bitstring value
-%%===============================================================================
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% bitstring NamedBitList
-%% Val can be of:
-%% - [identifiers] where only named identifers are set to one,
-%% the Constraint must then have some information of the
-%% bitlength.
-%% - [list of ones and zeroes] all bits
-%% - integer value representing the bitlist
-%% C is constraint Len, only valid when identifiers
-
-%% when the value is a list of named bits
-encode_bit_string(C, [FirstVal | RestVal], NamedBitList) when atom(FirstVal) ->
- ToSetPos = get_all_bitposes([FirstVal | RestVal], NamedBitList, []),
- BitList = make_and_set_list(ToSetPos,0),
- encode_bit_string(C,BitList,NamedBitList);
-
-encode_bit_string(C, [{bit,No} | RestVal], NamedBitList) ->
- ToSetPos = get_all_bitposes([{bit,No} | RestVal], NamedBitList, []),
- BitList = make_and_set_list(ToSetPos,0),
- encode_bit_string(C,BitList,NamedBitList);
-
-%% when the value is a list of ones and zeroes
-
-encode_bit_string(C, BitListValue, _NamedBitList) when list(BitListValue) ->
- %% first remove any trailing zeroes
- Bl1 = lists:dropwhile(fun(0)->true;(1)->false end,lists:reverse(BitListValue)),
- BitList = [{bit,X} || X <- lists:reverse(Bl1)],
- case get_constraint(C,'SizeConstraint') of
- 0 -> % fixed length
- []; % nothing to encode
- V when integer(V),V=<16 -> % fixed length 16 bits or less
- pad_list(V,BitList);
- V when integer(V) -> % fixed length more than 16 bits
- [align,pad_list(V,BitList)];
- {Lb,Ub} when integer(Lb),integer(Ub) ->
- [encode_length({Lb,Ub},length(BitList)),align,BitList];
- no ->
- [encode_length(undefined,length(BitList)),align,BitList]
- end;
-
-%% when the value is an integer
-encode_bit_string(C, IntegerVal, NamedBitList) ->
- BitList = int_to_bitlist(IntegerVal),
- encode_bit_string(C,BitList,NamedBitList).
-
-
-
-
-%%%%%%%%%%%%%%%
-%% The result is presented as a list of named bits (if possible)
-%% else as a list of 0 and 1.
-%%
-decode_bit_string(Buffer, C, NamedNumberList) ->
- case get_constraint(C,'SizeConstraint') of
- 0 -> % fixed length
- {[],Buffer}; % nothing to encode
- V when integer(V),V=<16 -> % fixed length 16 bits or less
- bit_list_to_named(Buffer,V,NamedNumberList);
- V when integer(V) -> % fixed length 16 bits or less
- Bytes2 = align(Buffer),
- bit_list_to_named(Bytes2,V,NamedNumberList);
- {Lb,Ub} when integer(Lb),integer(Ub) ->
- {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
- Bytes3 = align(Bytes2),
- bit_list_to_named(Bytes3,Len,NamedNumberList);
- no ->
- {Len,Bytes2} = decode_length(Buffer,undefined),
- Bytes3 = align(Bytes2),
- bit_list_to_named(Bytes3,Len,NamedNumberList)
- end.
-
-%% if no named bits are declared we will return a
-%% BitList = [0 | 1]
-
-bit_list_to_named(Buffer,Len,[]) ->
- getbits_as_list(Len,Buffer);
-
-%% if there are named bits declared we will return a named
-%% BitList where the names are atoms and unnamed bits represented
-%% as {bit,Pos}
-%% BitList = [atom() | {bit,Pos}]
-%% Pos = integer()
-
-bit_list_to_named(Buffer,Len,NamedNumberList) ->
- {BitList,Rest} = getbits_as_list(Len,Buffer),
- {bit_list_to_named1(0,BitList,NamedNumberList,[]), Rest}.
-
-bit_list_to_named1(Pos,[0|Bt],Names,Acc) ->
- bit_list_to_named1(Pos+1,Bt,Names,Acc);
-bit_list_to_named1(Pos,[1|Bt],Names,Acc) ->
- case lists:keysearch(Pos,2,Names) of
- {value,{Name,_}} ->
- bit_list_to_named1(Pos+1,Bt,Names,[Name|Acc]);
- _ ->
- bit_list_to_named1(Pos+1,Bt,Names,[{bit,Pos}|Acc])
- end;
-bit_list_to_named1(_Pos,[],_Names,Acc) ->
- lists:reverse(Acc).
-
-
-
-%%%%%%%%%%%%%%%
-%%
-
-int_to_bitlist(0) ->
- [];
-int_to_bitlist(Int) when integer(Int), Int >= 0 ->
- [Int band 1 | int_to_bitlist(Int bsr 1)].
-
-
-%%%%%%%%%%%%%%%%%%
-%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
-%% [sorted_list_of_bitpositions_to_set]
-
-get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
-
-get_all_bitposes([Val | Rest], NamedBitList, Ack) ->
- case lists:keysearch(Val, 1, NamedBitList) of
- {value, {_ValName, ValPos}} ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
- _ ->
- exit({error,{asn1, {bitstring_namedbit, Val}}})
- end;
-get_all_bitposes([], _NamedBitList, Ack) ->
- lists:sort(Ack).
-
-%%%%%%%%%%%%%%%%%%
-%% make_and_set_list([list of positions to set to 1])->
-%% returns list with all in SetPos set.
-%% in positioning in list the first element is 0, the second 1 etc.., but
-%%
-
-make_and_set_list([XPos|SetPos], XPos) ->
- [1 | make_and_set_list(SetPos, XPos + 1)];
-make_and_set_list([Pos|SetPos], XPos) ->
- [0 | make_and_set_list([Pos | SetPos], XPos + 1)];
-make_and_set_list([], _) ->
- [].
-
-%%%%%%%%%%%%%%%%%
-%% pad_list(N,BitList) -> PaddedList
-%% returns a padded (with trailing {bit,0} elements) list of length N
-%% if Bitlist contains more than N significant bits set an exit asn1_error
-%% is generated
-
-pad_list(0,BitList) ->
- case BitList of
- [] -> [];
- _ -> exit({error,{asn1,{range_error,{bit_string,BitList}}}})
- end;
-pad_list(N,[Bh|Bt]) ->
- [Bh|pad_list(N-1,Bt)];
-pad_list(N,[]) ->
- [{bit,0},pad_list(N-1,[])].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% X.691:16
-%% encode_octet_string(Constraint,ExtensionMarker,Val)
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-encode_octet_string(C,{Name,Val}) when atom(Name) ->
- encode_octet_string(C,false,Val);
-encode_octet_string(C,Val) ->
- encode_octet_string(C,false,Val).
-
-encode_octet_string(_C,true,_Val) ->
- exit({error,{asn1,{'not_supported',extensionmarker}}});
-encode_octet_string(C,false,Val) ->
- case get_constraint(C,'SizeConstraint') of
- 0 ->
- [];
- 1 ->
- [V] = Val,
- {bits,8,V};
- 2 ->
- [V1,V2] = Val,
- [{bits,8,V1},{bits,8,V2}];
- Sv when Sv =<65535, Sv == length(Val) -> % fixed length
- [align,{octets,Val}];
- {Lb,Ub} ->
- [encode_length({Lb,Ub},length(Val)),align,
- {octets,Val}];
- Sv when list(Sv) ->
- [encode_length({hd(Sv),lists:max(Sv)},length(Val)),align,
- {octets,Val}];
- no ->
- [encode_length(undefined,length(Val)),align,
- {octets,Val}]
- end.
-
-decode_octet_string(Bytes,Range) ->
- decode_octet_string(Bytes,Range,false).
-
-decode_octet_string(Bytes,C,false) ->
- case get_constraint(C,'SizeConstraint') of
- 0 ->
- {[],Bytes};
- 1 ->
- {B1,Bytes2} = getbits(Bytes,8),
- {[B1],Bytes2};
- 2 ->
- {B1,Bytes2}= getbits(Bytes,8),
- {B2,Bytes3}= getbits(Bytes2,8),
- {[B1,B2],Bytes3};
- {_,0} ->
- {[],Bytes};
- Sv when integer(Sv), Sv =<65535 -> % fixed length
- Bytes2 = align(Bytes),
- getoctets_as_list(Bytes2,Sv);
- {Lb,Ub} ->
- {Len,Bytes2} = decode_length(Bytes,{Lb,Ub}),
- Bytes3 = align(Bytes2),
- getoctets_as_list(Bytes3,Len);
- Sv when list(Sv) ->
- {Len,Bytes2} = decode_length(Bytes,{hd(Sv),lists:max(Sv)}),
- Bytes3 = align(Bytes2),
- getoctets_as_list(Bytes3,Len);
- no ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- Bytes3 = align(Bytes2),
- getoctets_as_list(Bytes3,Len)
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Restricted char string types
-%% (NumericString, PrintableString,VisibleString,IA5String,BMPString,UniversalString)
-%% X.691:26 and X.680:34-36
-%%encode_restricted_string(aligned,'BMPString',Constraints,Extension,Val)
-
-encode_restricted_string(aligned,StringType,C,Val) ->
-encode_restricted_string(aligned,StringType,C,false,Val).
-
-
-encode_restricted_string(aligned,StringType,C,_Ext,{Name,Val}) when atom(Name) ->
- encode_restricted_string(aligned,StringType,C,false,Val);
-encode_restricted_string(aligned,StringType,C,_Ext,Val) ->
- Result = chars_encode(C,StringType,Val),
- NumBits = get_NumBits(C,StringType),
- case get_constraint(C,'SizeConstraint') of
- Ub when integer(Ub), Ub*NumBits =< 16 ->
- case {StringType,Result} of
- {'BMPString',{octets,Ol}} ->
- [{bits,8,Oct}||Oct <- Ol];
- _ ->
- Result
- end;
- 0 ->
- [];
- Ub when integer(Ub),Ub =<65535 -> % fixed length
- [align,Result];
- {Ub,Lb} ->
- [encode_length({Ub,Lb},length(Val)),align,Result];
- Vl when list(Vl) ->
- [encode_length({lists:min(Vl),lists:max(Vl)},length(Val)),align,Result];
- no ->
- [encode_length(undefined,length(Val)),align,Result]
- end.
-
-decode_restricted_string(Bytes,aligned,StringType,C) ->
- decode_restricted_string(Bytes,aligned,StringType,C,false).
-
-decode_restricted_string(Bytes,aligned,StringType,C,_Ext) ->
- NumBits = get_NumBits(C,StringType),
- case get_constraint(C,'SizeConstraint') of
- Ub when integer(Ub), Ub*NumBits =< 16 ->
- chars_decode(Bytes,NumBits,StringType,C,Ub);
- Ub when integer(Ub),Ub =<65535 -> % fixed length
- Bytes1 = align(Bytes),
- chars_decode(Bytes1,NumBits,StringType,C,Ub);
- 0 ->
- {[],Bytes};
- Vl when list(Vl) ->
- {Len,Bytes1} = decode_length(Bytes,{hd(Vl),lists:max(Vl)}),
- Bytes2 = align(Bytes1),
- chars_decode(Bytes2,NumBits,StringType,C,Len);
- no ->
- {Len,Bytes1} = decode_length(Bytes,undefined),
- Bytes2 = align(Bytes1),
- chars_decode(Bytes2,NumBits,StringType,C,Len);
- {Lb,Ub}->
- {Len,Bytes1} = decode_length(Bytes,{Lb,Ub}),
- Bytes2 = align(Bytes1),
- chars_decode(Bytes2,NumBits,StringType,C,Len)
- end.
-
-
-
-encode_BMPString(C,Val) ->
- encode_restricted_string(aligned,'BMPString',C,false,Val).
-decode_BMPString(Bytes,C) ->
- decode_restricted_string(Bytes,aligned,'BMPString',C,false).
-
-encode_GeneralString(C,Val) ->
- encode_restricted_string(aligned,'GeneralString',C,false,Val).
-decode_GeneralString(Bytes,C) ->
- decode_restricted_string(Bytes,aligned,'GeneralString',C,false).
-
-encode_GraphicString(C,Val) ->
- encode_restricted_string(aligned,'GraphicString',C,false,Val).
-decode_GraphicString(Bytes,C) ->
- decode_restricted_string(Bytes,aligned,'GraphicString',C,false).
-
-encode_IA5String(C,Val) ->
- encode_restricted_string(aligned,'IA5String',C,false,Val).
-decode_IA5String(Bytes,C) ->
- decode_restricted_string(Bytes,aligned,'IA5String',C,false).
-
-encode_NumericString(C,Val) ->
- encode_restricted_string(aligned,'NumericString',C,false,Val).
-decode_NumericString(Bytes,C) ->
- decode_restricted_string(Bytes,aligned,'NumericString',C,false).
-
-encode_PrintableString(C,Val) ->
- encode_restricted_string(aligned,'PrintableString',C,false,Val).
-decode_PrintableString(Bytes,C) ->
- decode_restricted_string(Bytes,aligned,'PrintableString',C,false).
-
-encode_TeletexString(C,Val) -> % equivalent with T61String
- encode_restricted_string(aligned,'TeletexString',C,false,Val).
-decode_TeletexString(Bytes,C) ->
- decode_restricted_string(Bytes,aligned,'TeletexString',C,false).
-
-encode_UniversalString(C,Val) ->
- encode_restricted_string(aligned,'UniversalString',C,false,Val).
-decode_UniversalString(Bytes,C) ->
- decode_restricted_string(Bytes,aligned,'UniversalString',C,false).
-
-encode_VideotexString(C,Val) ->
- encode_restricted_string(aligned,'VideotexString',C,false,Val).
-decode_VideotexString(Bytes,C) ->
- decode_restricted_string(Bytes,aligned,'VideotexString',C,false).
-
-encode_VisibleString(C,Val) -> % equivalent with ISO646String
- encode_restricted_string(aligned,'VisibleString',C,false,Val).
-decode_VisibleString(Bytes,C) ->
- decode_restricted_string(Bytes,aligned,'VisibleString',C,false).
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% getBMPChars(Bytes,Len) ->{BMPcharList,RemainingBytes}
-%%
-getBMPChars(Bytes,1) ->
- {O1,Bytes2} = getbits(Bytes,8),
- {O2,Bytes3} = getbits(Bytes2,8),
- if
- O1 == 0 ->
- {[O2],Bytes3};
- true ->
- {[{O1,O2}],Bytes3}
- end;
-getBMPChars(Bytes,Len) ->
- getBMPChars(Bytes,Len,[]).
-
-getBMPChars(Bytes,0,Acc) ->
- {lists:reverse(Acc),Bytes};
-getBMPChars(Bytes,Len,Acc) ->
- {Octs,Bytes1} = getoctets_as_list(Bytes,2),
- case Octs of
- [0,O2] ->
- getBMPChars(Bytes1,Len-1,[O2|Acc]);
- [O1,O2]->
- getBMPChars(Bytes1,Len-1,[{O1,O2}|Acc])
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% chars_encode(C,StringType,Value) -> ValueList
-%%
-%% encodes chars according to the per rules taking the constraint PermittedAlphabet
-%% into account.
-%% This function does only encode the value part and NOT the length
-
-chars_encode(C,StringType,Value) ->
- case {StringType,get_constraint(C,'PermittedAlphabet')} of
- {'UniversalString',{_,_Sv}} ->
- exit({error,{asn1,{'not implemented',"UniversalString with PermittedAlphabet constraint"}}});
- {'BMPString',{_,_Sv}} ->
- exit({error,{asn1,{'not implemented',"BMPString with PermittedAlphabet constraint"}}});
- _ ->
- {NumBits,CharOutTab} = {get_NumBits(C,StringType),get_CharOutTab(C,StringType)},
- chars_encode2(Value,NumBits,CharOutTab)
- end.
-
-chars_encode2([H|T],NumBits,{Min,Max,notab}) when H =< Max, H >= Min ->
- [{bits,NumBits,H-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
-chars_encode2([H|T],NumBits,{Min,Max,Tab}) when H =< Max, H >= Min ->
- [{bits,NumBits,element(H-Min+1,Tab)}|chars_encode2(T,NumBits,{Min,Max,Tab})];
-chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,notab}) ->
- %% no value range check here (ought to be, but very expensive)
- [{bits,NumBits,(A*B*C*D)-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
-chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,Tab}) ->
- %% no value range check here (ought to be, but very expensive)
- [{bits,NumBits,element((A*B*C*D)-Min,Tab)}|chars_encode2(T,NumBits,{Min,Max,notab})];
-chars_encode2([H|_T],_NumBits,{_Min,_Max,_Tab}) ->
- exit({error,{asn1,{illegal_char_value,H}}});
-chars_encode2([],_,_) ->
- [].
-
-
-get_NumBits(C,StringType) ->
- case get_constraint(C,'PermittedAlphabet') of
- {'SingleValue',Sv} ->
- charbits(length(Sv),aligned);
- no ->
- case StringType of
- 'GeneralString' ->
- exit({error,{asn1,{not implemented,'GeneralString'}}});
- 'GraphicString' ->
- exit({error,{asn1,{not implemented,'GraphicString'}}});
- 'TeletexString' ->
- exit({error,{asn1,{not implemented,'TeletexString'}}});
- 'VideotexString' ->
- exit({error,{asn1,{not implemented,'VideotexString'}}});
- 'IA5String' ->
- charbits(128,aligned); % 16#00..16#7F
- 'VisibleString' ->
- charbits(95,aligned); % 16#20..16#7E
- 'PrintableString' ->
- charbits(74,aligned); % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
- 'NumericString' ->
- charbits(11,aligned); % $ ,"0123456789"
- 'UniversalString' ->
- 32;
- 'BMPString' ->
- 16
- end
- end.
-
-%%Maybe used later
-%%get_MaxChar(C,StringType) ->
-%% case get_constraint(C,'PermittedAlphabet') of
-%% {'SingleValue',Sv} ->
-%% lists:nth(length(Sv),Sv);
-%% no ->
-%% case StringType of
-%% 'IA5String' ->
-%% 16#7F; % 16#00..16#7F
-%% 'VisibleString' ->
-%% 16#7E; % 16#20..16#7E
-%% 'PrintableString' ->
-%% $z; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
-%% 'NumericString' ->
-%% $9; % $ ,"0123456789"
-%% 'UniversalString' ->
-%% 16#ffffffff;
-%% 'BMPString' ->
-%% 16#ffff
-%% end
-%% end.
-
-%%Maybe used later
-%%get_MinChar(C,StringType) ->
-%% case get_constraint(C,'PermittedAlphabet') of
-%% {'SingleValue',Sv} ->
-%% hd(Sv);
-%% no ->
-%% case StringType of
-%% 'IA5String' ->
-%% 16#00; % 16#00..16#7F
-%% 'VisibleString' ->
-%% 16#20; % 16#20..16#7E
-%% 'PrintableString' ->
-%% $\s; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
-%% 'NumericString' ->
-%% $\s; % $ ,"0123456789"
-%% 'UniversalString' ->
-%% 16#00;
-%% 'BMPString' ->
-%% 16#00
-%% end
-%% end.
-
-get_CharOutTab(C,StringType) ->
- get_CharTab(C,StringType,out).
-
-get_CharInTab(C,StringType) ->
- get_CharTab(C,StringType,in).
-
-get_CharTab(C,StringType,InOut) ->
- case get_constraint(C,'PermittedAlphabet') of
- {'SingleValue',Sv} ->
- get_CharTab2(C,StringType,hd(Sv),lists:max(Sv),Sv,InOut);
- no ->
- case StringType of
- 'IA5String' ->
- {0,16#7F,notab};
- 'VisibleString' ->
- get_CharTab2(C,StringType,16#20,16#7F,notab,InOut);
- 'PrintableString' ->
- Chars = lists:sort(
- " '()+,-./0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
- get_CharTab2(C,StringType,hd(Chars),lists:max(Chars),Chars,InOut);
- 'NumericString' ->
- get_CharTab2(C,StringType,16#20,$9," 0123456789",InOut);
- 'UniversalString' ->
- {0,16#FFFFFFFF,notab};
- 'BMPString' ->
- {0,16#FFFF,notab}
- end
- end.
-
-get_CharTab2(C,StringType,Min,Max,Chars,InOut) ->
- BitValMax = (1 bsl get_NumBits(C,StringType))-1,
- if
- Max =< BitValMax ->
- {0,Max,notab};
- true ->
- case InOut of
- out ->
- {Min,Max,create_char_tab(Min,Chars)};
- in ->
- {Min,Max,list_to_tuple(Chars)}
- end
- end.
-
-create_char_tab(Min,L) ->
- list_to_tuple(create_char_tab(Min,L,0)).
-create_char_tab(Min,[Min|T],V) ->
- [V|create_char_tab(Min+1,T,V+1)];
-create_char_tab(_Min,[],_V) ->
- [];
-create_char_tab(Min,L,V) ->
- [false|create_char_tab(Min+1,L,V)].
-
-%% This very inefficient and should be moved to compiletime
-charbits(NumOfChars,aligned) ->
- case charbits(NumOfChars) of
- 1 -> 1;
- 2 -> 2;
- B when B > 2, B =< 4 -> 4;
- B when B > 4, B =< 8 -> 8;
- B when B > 8, B =< 16 -> 16;
- B when B > 16, B =< 32 -> 32
- end.
-
-charbits(NumOfChars) when NumOfChars =< 2 -> 1;
-charbits(NumOfChars) when NumOfChars =< 4 -> 2;
-charbits(NumOfChars) when NumOfChars =< 8 -> 3;
-charbits(NumOfChars) when NumOfChars =< 16 -> 4;
-charbits(NumOfChars) when NumOfChars =< 32 -> 5;
-charbits(NumOfChars) when NumOfChars =< 64 -> 6;
-charbits(NumOfChars) when NumOfChars =< 128 -> 7;
-charbits(NumOfChars) when NumOfChars =< 256 -> 8;
-charbits(NumOfChars) when NumOfChars =< 512 -> 9;
-charbits(NumOfChars) when NumOfChars =< 1024 -> 10;
-charbits(NumOfChars) when NumOfChars =< 2048 -> 11;
-charbits(NumOfChars) when NumOfChars =< 4096 -> 12;
-charbits(NumOfChars) when NumOfChars =< 8192 -> 13;
-charbits(NumOfChars) when NumOfChars =< 16384 -> 14;
-charbits(NumOfChars) when NumOfChars =< 32768 -> 15;
-charbits(NumOfChars) when NumOfChars =< 65536 -> 16;
-charbits(NumOfChars) when integer(NumOfChars) ->
- 16 + charbits1(NumOfChars bsr 16).
-
-charbits1(0) ->
- 0;
-charbits1(NumOfChars) ->
- 1 + charbits1(NumOfChars bsr 1).
-
-
-chars_decode(Bytes,_,'BMPString',C,Len) ->
- case get_constraint(C,'PermittedAlphabet') of
- no ->
- getBMPChars(Bytes,Len);
- _ ->
- exit({error,{asn1,
- {'not implemented',
- "BMPString with PermittedAlphabet constraint"}}})
- end;
-chars_decode(Bytes,NumBits,StringType,C,Len) ->
- CharInTab = get_CharInTab(C,StringType),
- chars_decode2(Bytes,CharInTab,NumBits,Len).
-
-
-chars_decode2(Bytes,CharInTab,NumBits,Len) ->
- chars_decode2(Bytes,CharInTab,NumBits,Len,[]).
-
-chars_decode2(Bytes,_CharInTab,_NumBits,0,Acc) ->
- {lists:reverse(Acc),Bytes};
-chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) when NumBits > 8 ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- Result = case minimum_octets(Char+Min) of
- [NewChar] -> NewChar;
- [C1,C2] -> {0,0,C1,C2};
- [C1,C2,C3] -> {0,C1,C2,C3};
- [C1,C2,C3,C4] -> {C1,C2,C3,C4}
- end,
- chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Result|Acc]);
-chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Char+Min|Acc]);
-
-%% BMPString and UniversalString with PermittedAlphabet is currently not supported
-chars_decode2(Bytes,{Min,Max,CharInTab},NumBits,Len,Acc) ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- chars_decode2(Bytes2,{Min,Max,CharInTab},NumBits,Len -1,[element(Char+1,CharInTab)|Acc]).
-
-
- % X.691:17
-encode_null({Name,Val}) when atom(Name) ->
- encode_null(Val);
-encode_null(_) -> []. % encodes to nothing
-
-decode_null(Bytes) ->
- {'NULL',Bytes}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_object_identifier(Val) -> CompleteList
-%% encode_object_identifier({Name,Val}) -> CompleteList
-%% Val -> {Int1,Int2,...,IntN} % N >= 2
-%% Name -> atom()
-%% Int1 -> integer(0..2)
-%% Int2 -> integer(0..39) when Int1 (0..1) else integer()
-%% Int3-N -> integer()
-%% CompleteList -> [{bits,8,Val}|{octets,Ol}|align|...]
-%%
-encode_object_identifier(Val) ->
- Octets = e_object_identifier(Val,notag),
- [{debug,object_identifier},encode_length(undefined,length(Octets)),{octets,Octets}].
-
-%% This code is copied from asn1_encode.erl (BER) and corrected and modified
-
-e_object_identifier({'OBJECT IDENTIFIER',V},DoTag) ->
- e_object_identifier(V,DoTag);
-e_object_identifier({Cname,V},DoTag) when atom(Cname),tuple(V) ->
- e_object_identifier(tuple_to_list(V),DoTag);
-e_object_identifier({Cname,V},DoTag) when atom(Cname),list(V) ->
- e_object_identifier(V,DoTag);
-e_object_identifier(V,DoTag) when tuple(V) ->
- e_object_identifier(tuple_to_list(V),DoTag);
-
-% E1 = 0|1|2 and (E2 < 40 when E1 = 0|1)
-e_object_identifier([E1,E2|Tail],_DoTag) when E1 =< 2 ->
- Head = 40*E1 + E2, % weird
- Res = e_object_elements([Head|Tail]),
-% dotag(DoTag,[6],elength(length(Res)+1),[Head|Res]),
- Res.
-
-e_object_elements([]) ->
- [];
-e_object_elements([H|T]) ->
- lists:append(e_object_element(H),e_object_elements(T)).
-
-e_object_element(Num) when Num < 128 ->
- [Num];
-% must be changed to handle more than 2 octets
-e_object_element(Num) -> %% when Num < ???
- Left = ((Num band 2#11111110000000) bsr 7) bor 2#10000000,
- Right = Num band 2#1111111 ,
- [Left,Right].
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_object_identifier(Bytes) -> {ObjId,RemainingBytes}
-%% ObjId -> {integer(),integer(),...} % at least 2 integers
-%% RemainingBytes -> [integer()] when integer() (0..255)
-decode_object_identifier(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- [First|Rest] = dec_subidentifiers(Octs,0,[]),
- Idlist = if
- First < 40 ->
- [0,First|Rest];
- First < 80 ->
- [1,First - 40|Rest];
- true ->
- [2,First - 80|Rest]
- end,
- {list_to_tuple(Idlist),Bytes3}.
-
-dec_subidentifiers([H|T],Av,Al) when H >=16#80 ->
- dec_subidentifiers(T,(Av bsl 7) + (H band 16#7F),Al);
-dec_subidentifiers([H|T],Av,Al) ->
- dec_subidentifiers(T,0,[(Av bsl 7) + H |Al]);
-dec_subidentifiers([],_Av,Al) ->
- lists:reverse(Al).
-
-get_constraint(C,Key) ->
- case lists:keysearch(Key,1,C) of
- false ->
- no;
- {value,{_,V}} ->
- V
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% complete(InList) -> ByteList
-%% Takes a coded list with bits and bytes and converts it to a list of bytes
-%% Should be applied as the last step at encode of a complete ASN.1 type
-%%
-complete(InList) when list(InList) ->
- complete(InList,[],0);
-complete(InList) ->
- complete([InList],[],0).
-
-complete([{debug,_}|T], Acc, Acclen) ->
- complete(T,Acc,Acclen);
-complete([H|T],Acc,Acclen) when list(H) ->
- complete(lists:concat([H,T]),Acc,Acclen);
-
-
-complete([{octets,N,Val}|T],Acc,Acclen) when N =< 4 ,integer(Val) ->
- Newval = case N of
- 1 ->
- Val4 = Val band 16#FF,
- [Val4];
- 2 ->
- Val3 = (Val bsr 8) band 16#FF,
- Val4 = Val band 16#FF,
- [Val3,Val4];
- 3 ->
- Val2 = (Val bsr 16) band 16#FF,
- Val3 = (Val bsr 8) band 16#FF,
- Val4 = Val band 16#FF,
- [Val2,Val3,Val4];
- 4 ->
- Val1 = (Val bsr 24) band 16#FF,
- Val2 = (Val bsr 16) band 16#FF,
- Val3 = (Val bsr 8) band 16#FF,
- Val4 = Val band 16#FF,
- [Val1,Val2,Val3,Val4]
- end,
- complete([{octets,Newval}|T],Acc,Acclen);
-
-complete([{octets,Oct}|T],[],_Acclen) when list(Oct) ->
- complete(T,lists:reverse(Oct),0);
-complete([{octets,Oct}|T],[Hacc|Tacc],Acclen) when list(Oct) ->
- Rest = 8 - Acclen,
- if
- Rest == 8 ->
- complete(T,lists:concat([lists:reverse(Oct),[Hacc|Tacc]]),0);
- true ->
- complete(T,lists:concat([lists:reverse(Oct),[Hacc bsl Rest|Tacc]]),0)
- end;
-
-complete([{bit,Val}|T], Acc, Acclen) ->
- complete([{bits,1,Val}|T],Acc,Acclen);
-complete([{octet,Val}|T], Acc, Acclen) ->
- complete([{octets,1,Val}|T],Acc,Acclen);
-
-complete([{bits,N,Val}|T], Acc, 0) when N =< 8 ->
- complete(T,[Val|Acc],N);
-complete([{bits,N,Val}|T], [Hacc|Tacc], Acclen) when N =< 8 ->
- Rest = 8 - Acclen,
- if
- Rest >= N ->
- complete(T,[(Hacc bsl N) + Val|Tacc],(Acclen+N) rem 8);
- true ->
- Diff = N - Rest,
- NewHacc = (Hacc bsl Rest) + (Val bsr Diff),
- Mask = element(Diff,{1,3,7,15,31,63,127,255}),
- complete(T,[(Val band Mask),NewHacc|Tacc],(Acclen+N) rem 8)
- end;
-complete([{bits,N,Val}|T], Acc, Acclen) -> % N > 8
- complete([{bits,N-8,Val bsr 8},{bits,8,Val band 255}|T],Acc,Acclen);
-
-complete([align|T],Acc,0) ->
- complete(T,Acc,0);
-complete([align|T],[Hacc|Tacc],Acclen) ->
- Rest = 8 - Acclen,
- complete(T,[Hacc bsl Rest|Tacc],0);
-complete([{octets,_N,Val}|T],Acc,Acclen) when list(Val) -> % no security check here
- complete([{octets,Val}|T],Acc,Acclen);
-complete([],Acc,0) ->
- lists:reverse(Acc);
-complete([],[Hacc|Tacc],Acclen) when Acclen > 0->
- Rest = 8 - Acclen,
- NewHacc = Hacc bsl Rest,
- lists:reverse([NewHacc|Tacc]).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per_bin.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per_bin.erl
deleted file mode 100644
index 08a78165a2..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per_bin.erl
+++ /dev/null
@@ -1,2182 +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: asn1rt_per_bin.erl,v 1.1 2008/12/17 09:53:31 mikpe Exp $
-%%
--module(asn1rt_per_bin).
-
-%% encoding / decoding of PER aligned
-
--include("asn1_records.hrl").
-
--export([dec_fixup/3, cindex/3, list_to_record/2]).
--export([setchoiceext/1, setext/1, fixoptionals/2, fixoptionals/3,
- fixextensions/2,
- getext/1, getextension/2, skipextensions/3, getbit/1, getchoice/3 ]).
--export([getoptionals/2, getoptionals2/2, set_choice/3, encode_integer/2, encode_integer/3 ]).
--export([decode_integer/2, decode_integer/3, encode_small_number/1, encode_boolean/1,
- decode_boolean/1, encode_length/2, decode_length/1, decode_length/2,
- encode_small_length/1, decode_small_length/1,
- decode_compact_bit_string/3]).
--export([decode_enumerated/3,
- encode_bit_string/3, decode_bit_string/3 ]).
--export([encode_octet_string/2, decode_octet_string/2,
- encode_null/1, decode_null/1,
- encode_object_identifier/1, decode_object_identifier/1,
- complete/1]).
-
-
--export([encode_open_type/2, decode_open_type/2]).
-
--export([encode_UniversalString/2, decode_UniversalString/2,
- encode_PrintableString/2, decode_PrintableString/2,
- encode_GeneralString/2, decode_GeneralString/2,
- encode_GraphicString/2, decode_GraphicString/2,
- encode_TeletexString/2, decode_TeletexString/2,
- encode_VideotexString/2, decode_VideotexString/2,
- encode_VisibleString/2, decode_VisibleString/2,
- encode_BMPString/2, decode_BMPString/2,
- encode_IA5String/2, decode_IA5String/2,
- encode_NumericString/2, decode_NumericString/2,
- encode_ObjectDescriptor/2, decode_ObjectDescriptor/1
- ]).
--export([complete_bytes/1]).
-
--define('16K',16384).
--define('32K',32768).
--define('64K',65536).
-
-dec_fixup(Terms,Cnames,RemBytes) ->
- dec_fixup(Terms,Cnames,RemBytes,[]).
-
-dec_fixup([novalue|T],[_Hc|Tc],RemBytes,Acc) ->
- dec_fixup(T,Tc,RemBytes,Acc);
-dec_fixup([{_Name,novalue}|T],[_Hc|Tc],RemBytes,Acc) ->
- dec_fixup(T,Tc,RemBytes,Acc);
-dec_fixup([H|T],[Hc|Tc],RemBytes,Acc) ->
- dec_fixup(T,Tc,RemBytes,[{Hc,H}|Acc]);
-dec_fixup([],_Cnames,RemBytes,Acc) ->
- {lists:reverse(Acc),RemBytes}.
-
-cindex(Ix,Val,Cname) ->
- case element(Ix,Val) of
- {Cname,Val2} -> Val2;
- X -> X
- end.
-
-%% converts a list to a record if necessary
-list_to_record(_Name,Tuple) when tuple(Tuple) ->
- Tuple;
-list_to_record(Name,List) when list(List) ->
- list_to_tuple([Name|List]).
-
-%%--------------------------------------------------------
-%% setchoiceext(InRootSet) -> [{bit,X}]
-%% X is set to 1 when InRootSet==false
-%% X is set to 0 when InRootSet==true
-%%
-setchoiceext(true) ->
- [{debug,choiceext},{bits,1,0}];
-setchoiceext(false) ->
- [{debug,choiceext},{bits,1,1}].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% setext(true|false) -> CompleteList
-%%
-
-setext(false) ->
- [{debug,ext},{bits,1,0}];
-setext(true) ->
- [{debug,ext},{bits,1,1}].
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% This version of fixoptionals/2 are left only because of
-%% backward compatibility with older generates
-
-fixoptionals(OptList,Val) when tuple(Val) ->
- fixoptionals1(OptList,Val,[]);
-
-fixoptionals(OptList,Val) when list(Val) ->
- fixoptionals1(OptList,Val,1,[],[]).
-
-fixoptionals1([],Val,Acc) ->
- %% return {Val,Opt}
- {Val,lists:reverse(Acc)};
-fixoptionals1([{_,Pos}|Ot],Val,Acc) ->
- case element(Pos+1,Val) of
- asn1_NOVALUE -> fixoptionals1(Ot,Val,[0|Acc]);
- asn1_DEFAULT -> fixoptionals1(Ot,Val,[0|Acc]);
- _ -> fixoptionals1(Ot,Val,[1|Acc])
- end.
-
-
-fixoptionals1([{Name,Pos}|Ot],[{Name,Val}|Vt],_Opt,Acc1,Acc2) ->
- fixoptionals1(Ot,Vt,Pos+1,[1|Acc1],[{Name,Val}|Acc2]);
-fixoptionals1([{_Name,Pos}|Ot],V,Pos,Acc1,Acc2) ->
- fixoptionals1(Ot,V,Pos+1,[0|Acc1],[asn1_NOVALUE|Acc2]);
-fixoptionals1(O,[Vh|Vt],Pos,Acc1,Acc2) ->
- fixoptionals1(O,Vt,Pos+1,Acc1,[Vh|Acc2]);
-fixoptionals1([],[Vh|Vt],Pos,Acc1,Acc2) ->
- fixoptionals1([],Vt,Pos+1,Acc1,[Vh|Acc2]);
-fixoptionals1([],[],_,Acc1,Acc2) ->
- % return {Val,Opt}
- {list_to_tuple([asn1_RECORDNAME|lists:reverse(Acc2)]),lists:reverse(Acc1)}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% This is the new fixoptionals/3 which is used by the new generates
-%%
-fixoptionals(OptList,OptLength,Val) when tuple(Val) ->
- Bits = fixoptionals(OptList,Val,0),
- {Val,{bits,OptLength,Bits}};
-
-fixoptionals([],_Val,Acc) ->
- %% Optbits
- Acc;
-fixoptionals([Pos|Ot],Val,Acc) ->
- case element(Pos,Val) of
- asn1_NOVALUE -> fixoptionals(Ot,Val,Acc bsl 1);
- asn1_DEFAULT -> fixoptionals(Ot,Val,Acc bsl 1);
- _ -> fixoptionals(Ot,Val,(Acc bsl 1) + 1)
- end.
-
-
-getext(Bytes) when tuple(Bytes) ->
- getbit(Bytes);
-getext(Bytes) when binary(Bytes) ->
- getbit({0,Bytes});
-getext(Bytes) when list(Bytes) ->
- getbit({0,Bytes}).
-
-getextension(0, Bytes) ->
- {{},Bytes};
-getextension(1, Bytes) ->
- {Len,Bytes2} = decode_small_length(Bytes),
- {Blist, Bytes3} = getbits_as_list(Len,Bytes2),
- {list_to_tuple(Blist),Bytes3}.
-
-fixextensions({ext,ExtPos,ExtNum},Val) ->
- case fixextensions(ExtPos,ExtNum+ExtPos,Val,0) of
- 0 -> [];
- ExtBits ->
- [encode_small_length(ExtNum),{bits,ExtNum,ExtBits}]
- end.
-
-fixextensions(Pos,MaxPos,_,Acc) when Pos >= MaxPos ->
- Acc;
-fixextensions(Pos,ExtPos,Val,Acc) ->
- Bit = case catch(element(Pos+1,Val)) of
- asn1_NOVALUE ->
- 0;
- asn1_NOEXTVALUE ->
- 0;
- {'EXIT',_} ->
- 0;
- _ ->
- 1
- end,
- fixextensions(Pos+1,ExtPos,Val,(Acc bsl 1)+Bit).
-
-skipextensions(Bytes,Nr,ExtensionBitPattern) ->
- case (catch element(Nr,ExtensionBitPattern)) of
- 1 ->
- {_,Bytes2} = decode_open_type(Bytes,[]),
- skipextensions(Bytes2, Nr+1, ExtensionBitPattern);
- 0 ->
- skipextensions(Bytes, Nr+1, ExtensionBitPattern);
- {'EXIT',_} -> % badarg, no more extensions
- Bytes
- end.
-
-
-getchoice(Bytes,1,0) -> % only 1 alternative is not encoded
- {0,Bytes};
-getchoice(Bytes,_,1) ->
- decode_small_number(Bytes);
-getchoice(Bytes,NumChoices,0) ->
- decode_constrained_number(Bytes,{0,NumChoices-1}).
-
-%% old version kept for backward compatibility with generates from R7B
-getoptionals(Bytes,NumOpt) ->
- {Blist,Bytes1} = getbits_as_list(NumOpt,Bytes),
- {list_to_tuple(Blist),Bytes1}.
-
-%% new version used in generates from r8b_patch/3 and later
-getoptionals2(Bytes,NumOpt) ->
- getbits(Bytes,NumOpt).
-
-
-%% getbits_as_binary(Num,Bytes) -> {{Unused,BinBits},RestBytes},
-%% Num = integer(),
-%% Bytes = list() | tuple(),
-%% Unused = integer(),
-%% BinBits = binary(),
-%% RestBytes = tuple()
-getbits_as_binary(Num,Bytes) when binary(Bytes) ->
- getbits_as_binary(Num,{0,Bytes});
-getbits_as_binary(0,Buffer) ->
- {{0,<<>>},Buffer};
-getbits_as_binary(Num,{0,Bin}) when Num > 16 ->
- Used = Num rem 8,
- Pad = (8 - Used) rem 8,
-% Nbytes = Num div 8,
- <<Bits:Num,_:Pad,RestBin/binary>> = Bin,
- {{Pad,<<Bits:Num,0:Pad>>},RestBin};
-getbits_as_binary(Num,Buffer={_Used,_Bin}) -> % Unaligned buffer
- %% Num =< 16,
- {Bits2,Buffer2} = getbits(Buffer,Num),
- Pad = (8 - (Num rem 8)) rem 8,
- {{Pad,<<Bits2:Num,0:Pad>>},Buffer2}.
-
-
-% integer_from_list(Int,[],BigInt) ->
-% BigInt;
-% integer_from_list(Int,[H|T],BigInt) when Int < 8 ->
-% (BigInt bsl Int) bor (H bsr (8-Int));
-% integer_from_list(Int,[H|T],BigInt) ->
-% integer_from_list(Int-8,T,(BigInt bsl 8) bor H).
-
-getbits_as_list(Num,Bytes) when binary(Bytes) ->
- getbits_as_list(Num,{0,Bytes},[]);
-getbits_as_list(Num,Bytes) ->
- getbits_as_list(Num,Bytes,[]).
-
-%% If buffer is empty and nothing more will be picked.
-getbits_as_list(0, B, Acc) ->
- {lists:reverse(Acc),B};
-%% If first byte in buffer is full and at least one byte will be picked,
-%% then pick one byte.
-getbits_as_list(N,{0,Bin},Acc) when N >= 8 ->
- <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Rest/binary>> = Bin,
- getbits_as_list(N-8,{0,Rest},[B0,B1,B2,B3,B4,B5,B6,B7|Acc]);
-getbits_as_list(N,{Used,Bin},Acc) when N >= 4, Used =< 4 ->
- NewUsed = Used + 4,
- Rem = 8 - NewUsed,
- <<_:Used,B3:1,B2:1,B1:1,B0:1,_:Rem, Rest/binary>> = Bin,
- NewRest = case Rem of 0 -> Rest; _ -> Bin end,
- getbits_as_list(N-4,{NewUsed rem 8,NewRest},[B0,B1,B2,B3|Acc]);
-getbits_as_list(N,{Used,Bin},Acc) when N >= 2, Used =< 6 ->
- NewUsed = Used + 2,
- Rem = 8 - NewUsed,
- <<_:Used,B1:1,B0:1,_:Rem, Rest/binary>> = Bin,
- NewRest = case Rem of 0 -> Rest; _ -> Bin end,
- getbits_as_list(N-2,{NewUsed rem 8,NewRest},[B0,B1|Acc]);
-getbits_as_list(N,{Used,Bin},Acc) when Used =< 7 ->
- NewUsed = Used + 1,
- Rem = 8 - NewUsed,
- <<_:Used,B0:1,_:Rem, Rest/binary>> = Bin,
- NewRest = case Rem of 0 -> Rest; _ -> Bin end,
- getbits_as_list(N-1,{NewUsed rem 8,NewRest},[B0|Acc]).
-
-
-getbit({7,<<_:7,B:1,Rest/binary>>}) ->
- {B,{0,Rest}};
-getbit({0,Buffer = <<B:1,_:7,_/binary>>}) ->
- {B,{1,Buffer}};
-getbit({Used,Buffer}) ->
- Unused = (8 - Used) - 1,
- <<_:Used,B:1,_:Unused,_/binary>> = Buffer,
- {B,{Used+1,Buffer}};
-getbit(Buffer) when binary(Buffer) ->
- getbit({0,Buffer}).
-
-
-getbits({0,Buffer},Num) when (Num rem 8) == 0 ->
- <<Bits:Num,Rest/binary>> = Buffer,
- {Bits,{0,Rest}};
-getbits({Used,Bin},Num) ->
- NumPlusUsed = Num + Used,
- NewUsed = NumPlusUsed rem 8,
- Unused = (8-NewUsed) rem 8,
- case Unused of
- 0 ->
- <<_:Used,Bits:Num,Rest/binary>> = Bin,
- {Bits,{0,Rest}};
- _ ->
- Bytes = NumPlusUsed div 8,
- <<_:Used,Bits:Num,_UBits:Unused,_/binary>> = Bin,
- <<_:Bytes/binary,Rest/binary>> = Bin,
- {Bits,{NewUsed,Rest}}
- end;
-getbits(Bin,Num) when binary(Bin) ->
- getbits({0,Bin},Num).
-
-
-
-% getoctet(Bytes) when list(Bytes) ->
-% getoctet({0,Bytes});
-% getoctet(Bytes) ->
-% %% io:format("getoctet:Buffer = ~p~n",[Bytes]),
-% getoctet1(Bytes).
-
-% getoctet1({0,[H|T]}) ->
-% {H,{0,T}};
-% getoctet1({Pos,[_,H|T]}) ->
-% {H,{0,T}}.
-
-align({0,L}) ->
- {0,L};
-align({_Pos,<<_H,T/binary>>}) ->
- {0,T};
-align(Bytes) ->
- {0,Bytes}.
-
-%% First align buffer, then pick the first Num octets.
-%% Returns octets as an integer with bit significance as in buffer.
-getoctets({0,Buffer},Num) ->
- <<Val:Num/integer-unit:8,RestBin/binary>> = Buffer,
- {Val,{0,RestBin}};
-getoctets({U,<<_Padding,Rest/binary>>},Num) when U /= 0 ->
- getoctets({0,Rest},Num);
-getoctets(Buffer,Num) when binary(Buffer) ->
- getoctets({0,Buffer},Num).
-% getoctets(Buffer,Num) ->
-% %% io:format("getoctets:Buffer = ~p~nNum = ~p~n",[Buffer,Num]),
-% getoctets(Buffer,Num,0).
-
-% getoctets(Buffer,0,Acc) ->
-% {Acc,Buffer};
-% getoctets(Buffer,Num,Acc) ->
-% {Oct,NewBuffer} = getoctet(Buffer),
-% getoctets(NewBuffer,Num-1,(Acc bsl 8)+Oct).
-
-% getoctets_as_list(Buffer,Num) ->
-% getoctets_as_list(Buffer,Num,[]).
-
-% getoctets_as_list(Buffer,0,Acc) ->
-% {lists:reverse(Acc),Buffer};
-% getoctets_as_list(Buffer,Num,Acc) ->
-% {Oct,NewBuffer} = getoctet(Buffer),
-% getoctets_as_list(NewBuffer,Num-1,[Oct|Acc]).
-
-%% First align buffer, then pick the first Num octets.
-%% Returns octets as a binary
-getoctets_as_bin({0,Bin},Num)->
- <<Octets:Num/binary,RestBin/binary>> = Bin,
- {Octets,{0,RestBin}};
-getoctets_as_bin({_U,Bin},Num) ->
- <<_Padding,Octets:Num/binary,RestBin/binary>> = Bin,
- {Octets,{0,RestBin}};
-getoctets_as_bin(Bin,Num) when binary(Bin) ->
- getoctets_as_bin({0,Bin},Num).
-
-%% same as above but returns octets as a List
-getoctets_as_list(Buffer,Num) ->
- {Bin,Buffer2} = getoctets_as_bin(Buffer,Num),
- {binary_to_list(Bin),Buffer2}.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% set_choice(Alt,Choices,Altnum) -> ListofBitSettings
-%% Alt = atom()
-%% Altnum = integer() | {integer(),integer()}% number of alternatives
-%% Choices = [atom()] | {[atom()],[atom()]}
-%% When Choices is a tuple the first list is the Rootset and the
-%% second is the Extensions and then Altnum must also be a tuple with the
-%% lengths of the 2 lists
-%%
-set_choice(Alt,{L1,L2},{Len1,_Len2}) ->
- case set_choice_tag(Alt,L1) of
- N when integer(N), Len1 > 1 ->
- [{bits,1,0}, % the value is in the root set
- encode_integer([{'ValueRange',{0,Len1-1}}],N)];
- N when integer(N) ->
- [{bits,1,0}]; % no encoding if only 0 or 1 alternative
- false ->
- [{bits,1,1}, % extension value
- case set_choice_tag(Alt,L2) of
- N2 when integer(N2) ->
- encode_small_number(N2);
- false ->
- unknown_choice_alt
- end]
- end;
-set_choice(Alt,L,Len) ->
- case set_choice_tag(Alt,L) of
- N when integer(N), Len > 1 ->
- encode_integer([{'ValueRange',{0,Len-1}}],N);
- N when integer(N) ->
- []; % no encoding if only 0 or 1 alternative
- false ->
- [unknown_choice_alt]
- end.
-
-set_choice_tag(Alt,Choices) ->
- set_choice_tag(Alt,Choices,0).
-
-set_choice_tag(Alt,[Alt|_Rest],Tag) ->
- Tag;
-set_choice_tag(Alt,[_H|Rest],Tag) ->
- set_choice_tag(Alt,Rest,Tag+1);
-set_choice_tag(_Alt,[],_Tag) ->
- false.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_fragmented_XXX; decode of values encoded fragmented according
-%% to ITU-T X.691 clause 10.9.3.8. The unit (XXX) is either bits, octets,
-%% characters or number of components (in a choice,sequence or similar).
-%% Buffer is a buffer {Used, Bin}.
-%% C is the constrained length.
-%% If the buffer is not aligned, this function does that.
-decode_fragmented_bits({0,Buffer},C) ->
- decode_fragmented_bits(Buffer,C,[]);
-decode_fragmented_bits({_N,<<_,Bs/binary>>},C) ->
- decode_fragmented_bits(Bs,C,[]).
-
-decode_fragmented_bits(<<3:2,Len:6,Bin/binary>>,C,Acc) ->
- {Value,Bin2} = split_binary(Bin, Len * ?'16K'),
- decode_fragmented_bits(Bin2,C,[Value,Acc]);
-decode_fragmented_bits(<<0:1,0:7,Bin/binary>>,C,Acc) ->
- BinBits = list_to_binary(lists:reverse(Acc)),
- case C of
- Int when integer(Int),C == size(BinBits) ->
- {BinBits,{0,Bin}};
- Int when integer(Int) ->
- exit({error,{asn1,{illegal_value,C,BinBits}}});
- _ ->
- {BinBits,{0,Bin}}
- end;
-decode_fragmented_bits(<<0:1,Len:7,Bin/binary>>,C,Acc) ->
- Result = {BinBits,{Used,_Rest}} =
- case (Len rem 8) of
- 0 ->
- <<Value:Len/binary-unit:1,Bin2/binary>> = Bin,
- {list_to_binary(lists:reverse([Value|Acc])),{0,Bin2}};
- Rem ->
- Bytes = Len div 8,
- U = 8 - Rem,
- <<Value:Bytes/binary-unit:8,Bits1:Rem,Bits2:U,Bin2/binary>> = Bin,
- {list_to_binary(lists:reverse([Bits1 bsl U,Value|Acc])),
- {Rem,<<Bits2,Bin2/binary>>}}
- end,
- case C of
- Int when integer(Int),C == (size(BinBits) - ((8 - Used) rem 8)) ->
- Result;
- Int when integer(Int) ->
- exit({error,{asn1,{illegal_value,C,BinBits}}});
- _ ->
- Result
- end.
-
-
-decode_fragmented_octets({0,Bin},C) ->
- decode_fragmented_octets(Bin,C,[]);
-decode_fragmented_octets({_N,<<_,Bs/binary>>},C) ->
- decode_fragmented_octets(Bs,C,[]).
-
-decode_fragmented_octets(<<3:2,Len:6,Bin/binary>>,C,Acc) ->
- {Value,Bin2} = split_binary(Bin,Len * ?'16K'),
- decode_fragmented_octets(Bin2,C,[Value,Acc]);
-decode_fragmented_octets(<<0:1,0:7,Bin/binary>>,C,Acc) ->
- Octets = list_to_binary(lists:reverse(Acc)),
- case C of
- Int when integer(Int), C == size(Octets) ->
- {Octets,{0,Bin}};
- Int when integer(Int) ->
- exit({error,{asn1,{illegal_value,C,Octets}}});
- _ ->
- {Octets,{0,Bin}}
- end;
-decode_fragmented_octets(<<0:1,Len:7,Bin/binary>>,C,Acc) ->
- <<Value:Len/binary-unit:8,Bin2/binary>> = Bin,
- BinOctets = list_to_binary(lists:reverse([Value|Acc])),
- case C of
- Int when integer(Int),size(BinOctets) == Int ->
- {BinOctets,Bin2};
- Int when integer(Int) ->
- exit({error,{asn1,{illegal_value,C,BinOctets}}});
- _ ->
- {BinOctets,Bin2}
- end.
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_open_type(Constraint, Value) -> CompleteList
-%% Value = list of bytes of an already encoded value (the list must be flat)
-%% | binary
-%% Contraint = not used in this version
-%%
-encode_open_type(_C, Val) when list(Val) ->
- Bin = list_to_binary(Val),
- [encode_length(undefined,size(Bin)),{octets,Bin}]; % octets implies align
-encode_open_type(_C, Val) when binary(Val) ->
- [encode_length(undefined,size(Val)),{octets,Val}]. % octets implies align
-%% the binary_to_list is not optimal but compatible with the current solution
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_open_type(Buffer,Constraint) -> Value
-%% Constraint is not used in this version
-%% Buffer = [byte] with PER encoded data
-%% Value = [byte] with decoded data (which must be decoded again as some type)
-%%
-decode_open_type(Bytes, _C) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- getoctets_as_bin(Bytes2,Len).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_integer(Constraint,Value,NamedNumberList) -> CompleteList
-%% encode_integer(Constraint,Value) -> CompleteList
-%% encode_integer(Constraint,{Name,Value}) -> CompleteList
-%%
-%%
-encode_integer(C,V,NamedNumberList) when atom(V) ->
- case lists:keysearch(V,1,NamedNumberList) of
- {value,{_,NewV}} ->
- encode_integer(C,NewV);
- _ ->
- exit({error,{asn1,{namednumber,V}}})
- end;
-encode_integer(C,V,_NamedNumberList) when integer(V) ->
- encode_integer(C,V);
-encode_integer(C,{Name,V},NamedNumberList) when atom(Name) ->
- encode_integer(C,V,NamedNumberList).
-
-encode_integer(C,{Name,Val}) when atom(Name) ->
- encode_integer(C,Val);
-
-encode_integer([{Rc,_Ec}],Val) when tuple(Rc) -> % XXX when is this invoked? First argument most often a list,...Ok this is the extension case...but it doesn't work.
- case (catch encode_integer([Rc],Val)) of
- {'EXIT',{error,{asn1,_}}} ->
- [{bits,1,1},encode_unconstrained_number(Val)];
- Encoded ->
- [{bits,1,0},Encoded]
- end;
-encode_integer(C,Val ) when list(C) ->
- case get_constraint(C,'SingleValue') of
- no ->
- encode_integer1(C,Val);
- V when integer(V),V == Val ->
- []; % a type restricted to a single value encodes to nothing
- V when list(V) ->
- case lists:member(Val,V) of
- true ->
- encode_integer1(C,Val);
- _ ->
- exit({error,{asn1,{illegal_value,Val}}})
- end;
- _ ->
- exit({error,{asn1,{illegal_value,Val}}})
- end.
-
-encode_integer1(C, Val) ->
- case VR = get_constraint(C,'ValueRange') of
- no ->
- encode_unconstrained_number(Val);
- {Lb,'MAX'} ->
- encode_semi_constrained_number(Lb,Val);
- %% positive with range
- {Lb,Ub} when Val >= Lb,
- Ub >= Val ->
- encode_constrained_number(VR,Val);
- _ ->
- exit({error,{asn1,{illegal_value,VR,Val}}})
- end.
-
-decode_integer(Buffer,Range,NamedNumberList) ->
- {Val,Buffer2} = decode_integer(Buffer,Range),
- case lists:keysearch(Val,2,NamedNumberList) of
- {value,{NewVal,_}} -> {NewVal,Buffer2};
- _ -> {Val,Buffer2}
- end.
-
-decode_integer(Buffer,[{Rc,_Ec}]) when tuple(Rc) ->
- {Ext,Buffer2} = getext(Buffer),
- case Ext of
- 0 -> decode_integer(Buffer2,[Rc]);
- 1 -> decode_unconstrained_number(Buffer2)
- end;
-decode_integer(Buffer,undefined) ->
- decode_unconstrained_number(Buffer);
-decode_integer(Buffer,C) ->
- case get_constraint(C,'SingleValue') of
- V when integer(V) ->
- {V,Buffer};
- V when list(V) ->
- {Val,Buffer2} = decode_integer1(Buffer,C),
- case lists:member(Val,V) of
- true ->
- {Val,Buffer2};
- _ ->
- exit({error,{asn1,{illegal_value,Val}}})
- end;
- _ ->
- decode_integer1(Buffer,C)
- end.
-
-decode_integer1(Buffer,C) ->
- case VR = get_constraint(C,'ValueRange') of
- no ->
- decode_unconstrained_number(Buffer);
- {Lb, 'MAX'} ->
- decode_semi_constrained_number(Buffer,Lb);
- {_,_} ->
- decode_constrained_number(Buffer,VR)
- end.
-
- % X.691:10.6 Encoding of a normally small non-negative whole number
- % Use this for encoding of CHOICE index if there is an extension marker in
- % the CHOICE
-encode_small_number({Name,Val}) when atom(Name) ->
- encode_small_number(Val);
-encode_small_number(Val) when Val =< 63 ->
-% [{bits,1,0},{bits,6,Val}];
- [{bits,7,Val}]; % same as above but more efficient
-encode_small_number(Val) ->
- [{bits,1,1},encode_semi_constrained_number(0,Val)].
-
-decode_small_number(Bytes) ->
- {Bit,Bytes2} = getbit(Bytes),
- case Bit of
- 0 ->
- getbits(Bytes2,6);
- 1 ->
- decode_semi_constrained_number(Bytes2,0)
- end.
-
-%% X.691:10.7 Encoding of a semi-constrained whole number
-%% might be an optimization encode_semi_constrained_number(0,Val) ->
-encode_semi_constrained_number(C,{Name,Val}) when atom(Name) ->
- encode_semi_constrained_number(C,Val);
-encode_semi_constrained_number({Lb,'MAX'},Val) ->
- encode_semi_constrained_number(Lb,Val);
-encode_semi_constrained_number(Lb,Val) ->
- Val2 = Val - Lb,
- Oct = eint_positive(Val2),
- Len = length(Oct),
- if
- Len < 128 ->
- {octets,[Len|Oct]}; % equiv with encode_length(undefined,Len) but faster
- true ->
- [encode_length(undefined,Len),{octets,Oct}]
- end.
-
-decode_semi_constrained_number(Bytes,{Lb,_}) ->
- decode_semi_constrained_number(Bytes,Lb);
-decode_semi_constrained_number(Bytes,Lb) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {V,Bytes3} = getoctets(Bytes2,Len),
- {V+Lb,Bytes3}.
-
-encode_constrained_number(Range,{Name,Val}) when atom(Name) ->
- encode_constrained_number(Range,Val);
-encode_constrained_number({Lb,Ub},Val) when Val >= Lb, Ub >= Val ->
- Range = Ub - Lb + 1,
- Val2 = Val - Lb,
- if
- Range == 2 ->
- {bits,1,Val2};
- Range =< 4 ->
- {bits,2,Val2};
- Range =< 8 ->
- {bits,3,Val2};
- Range =< 16 ->
- {bits,4,Val2};
- Range =< 32 ->
- {bits,5,Val2};
- Range =< 64 ->
- {bits,6,Val2};
- Range =< 128 ->
- {bits,7,Val2};
- Range =< 255 ->
- {bits,8,Val2};
- Range =< 256 ->
- {octets,[Val2]};
- Range =< 65536 ->
- {octets,<<Val2:16>>};
- Range =< 16#1000000 ->
- Octs = eint_positive(Val2),
- [{bits,2,length(Octs)-1},{octets,Octs}];
- Range =< 16#100000000 ->
- Octs = eint_positive(Val2),
- [{bits,2,length(Octs)-1},{octets,Octs}];
- Range =< 16#10000000000 ->
- Octs = eint_positive(Val2),
- [{bits,3,length(Octs)-1},{octets,Octs}];
- true ->
- exit({not_supported,{integer_range,Range}})
- end;
-encode_constrained_number(Range,Val) ->
- exit({error,{asn1,{integer_range,Range,value,Val}}}).
-
-
-decode_constrained_number(Buffer,{Lb,Ub}) ->
- Range = Ub - Lb + 1,
- % Val2 = Val - Lb,
- {Val,Remain} =
- if
- Range == 2 ->
- getbits(Buffer,1);
- Range =< 4 ->
- getbits(Buffer,2);
- Range =< 8 ->
- getbits(Buffer,3);
- Range =< 16 ->
- getbits(Buffer,4);
- Range =< 32 ->
- getbits(Buffer,5);
- Range =< 64 ->
- getbits(Buffer,6);
- Range =< 128 ->
- getbits(Buffer,7);
- Range =< 255 ->
- getbits(Buffer,8);
- Range =< 256 ->
- getoctets(Buffer,1);
- Range =< 65536 ->
- getoctets(Buffer,2);
- Range =< 16#1000000 ->
- {Len,Bytes2} = decode_length(Buffer,{1,3}),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- {dec_pos_integer(Octs),Bytes3};
- Range =< 16#100000000 ->
- {Len,Bytes2} = decode_length(Buffer,{1,4}),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- {dec_pos_integer(Octs),Bytes3};
- Range =< 16#10000000000 ->
- {Len,Bytes2} = decode_length(Buffer,{1,5}),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- {dec_pos_integer(Octs),Bytes3};
- true ->
- exit({not_supported,{integer_range,Range}})
- end,
- {Val+Lb,Remain}.
-
-%% X.691:10.8 Encoding of an unconstrained whole number
-
-encode_unconstrained_number(Val) when Val >= 0 ->
- Oct = eint(Val,[]),
- Len = length(Oct),
- if
- Len < 128 ->
- {octets,[Len|Oct]}; % equiv with encode_length(undefined,Len) but faster
- true ->
- [encode_length(undefined,Len),{octets,Oct}]
- end;
-encode_unconstrained_number(Val) -> % negative
- Oct = enint(Val,[]),
- Len = length(Oct),
- if
- Len < 128 ->
- {octets,[Len|Oct]}; % equiv with encode_length(undefined,Len) but faster
- true ->
- [encode_length(undefined,Len),{octets,Oct}]
- end.
-
-
-%% used for positive Values which don't need a sign bit
-%% returns a binary
-eint_positive(Val) ->
- case eint(Val,[]) of
- [0,B1|T] ->
- [B1|T];
- T ->
- T
- end.
-
-
-eint(0, [B|Acc]) when B < 128 ->
- [B|Acc];
-eint(N, Acc) ->
- eint(N bsr 8, [N band 16#ff| Acc]).
-
-enint(-1, [B1|T]) when B1 > 127 ->
- [B1|T];
-enint(N, Acc) ->
- enint(N bsr 8, [N band 16#ff|Acc]).
-
-decode_unconstrained_number(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {Ints,Bytes3} = getoctets_as_list(Bytes2,Len),
- {dec_integer(Ints),Bytes3}.
-
-dec_pos_integer(Ints) ->
- decpint(Ints, 8 * (length(Ints) - 1)).
-dec_integer(Ints) when hd(Ints) band 255 =< 127 -> %% Positive number
- decpint(Ints, 8 * (length(Ints) - 1));
-dec_integer(Ints) -> %% Negative
- decnint(Ints, 8 * (length(Ints) - 1)).
-
-decpint([Byte|Tail], Shift) ->
- (Byte bsl Shift) bor decpint(Tail, Shift-8);
-decpint([], _) -> 0.
-
-decnint([Byte|Tail], Shift) ->
- (-128 + (Byte band 127) bsl Shift) bor decpint(Tail, Shift-8).
-
-% minimum_octets(Val) ->
-% minimum_octets(Val,[]).
-
-% minimum_octets(Val,Acc) when Val > 0 ->
-% minimum_octets((Val bsr 8),[Val band 16#FF|Acc]);
-% minimum_octets(0,Acc) ->
-% Acc.
-
-
-%% X.691:10.9 Encoding of a length determinant
-%%encode_small_length(undefined,Len) -> % null means no UpperBound
-%% encode_small_number(Len).
-
-%% X.691:10.9.3.5
-%% X.691:10.9.3.7
-encode_length(undefined,Len) -> % un-constrained
- if
- Len < 128 ->
- {octets,[Len]};
- Len < 16384 ->
- {octets,<<2:2,Len:14>>};
- true -> % should be able to endode length >= 16384
- exit({error,{asn1,{encode_length,{nyi,above_16k}}}})
- end;
-
-encode_length({0,'MAX'},Len) ->
- encode_length(undefined,Len);
-encode_length(Vr={Lb,Ub},Len) when Ub =< 65535 ,Lb >= 0 -> % constrained
- encode_constrained_number(Vr,Len);
-encode_length({Lb,_Ub},Len) when integer(Lb), Lb >= 0 -> % Ub > 65535
- encode_length(undefined,Len);
-encode_length({Vr={Lb,Ub},[]},Len) when Ub =< 65535 ,Lb >= 0 ->
- %% constrained extensible
- [{bits,1,0},encode_constrained_number(Vr,Len)];
-encode_length(SingleValue,_Len) when integer(SingleValue) ->
- [].
-
-%% X.691 10.9.3.4 (only used for length of bitmap that prefixes extension
-%% additions in a sequence or set
-encode_small_length(Len) when Len =< 64 ->
-%% [{bits,1,0},{bits,6,Len-1}];
- {bits,7,Len-1}; % the same as above but more efficient
-encode_small_length(Len) ->
- [{bits,1,1},encode_length(undefined,Len)].
-
-% decode_small_length({Used,<<_:Used,0:1,Num:6,_:((8-Used+1) rem 8),Rest/binary>>}) ->
-% case Buffer of
-% <<_:Used,0:1,Num:6,_:((8-Used+1) rem 8),Rest/binary>> ->
-% {Num,
-% case getbit(Buffer) of
-% {0,Remain} ->
-% {Bits,Remain2} = getbits(Remain,6),
-% {Bits+1,Remain2};
-% {1,Remain} ->
-% decode_length(Remain,undefined)
-% end.
-
-decode_small_length(Buffer) ->
- case getbit(Buffer) of
- {0,Remain} ->
- {Bits,Remain2} = getbits(Remain,6),
- {Bits+1,Remain2};
- {1,Remain} ->
- decode_length(Remain,undefined)
- end.
-
-decode_length(Buffer) ->
- decode_length(Buffer,undefined).
-
-decode_length(Buffer,undefined) -> % un-constrained
- {0,Buffer2} = align(Buffer),
- case Buffer2 of
- <<0:1,Oct:7,Rest/binary>> ->
- {Oct,{0,Rest}};
- <<2:2,Val:14,Rest/binary>> ->
- {Val,{0,Rest}};
- <<3:2,_:14,_Rest/binary>> ->
- %% this case should be fixed
- exit({error,{asn1,{decode_length,{nyi,above_16k}}}})
- end;
-%% {Bits,_} = getbits(Buffer2,2),
-% case Bits of
-% 2 ->
-% {Val,Bytes3} = getoctets(Buffer2,2),
-% {(Val band 16#3FFF),Bytes3};
-% 3 ->
-% exit({error,{asn1,{decode_length,{nyi,above_16k}}}});
-% _ ->
-% {Val,Bytes3} = getoctet(Buffer2),
-% {Val band 16#7F,Bytes3}
-% end;
-
-decode_length(Buffer,{Lb,Ub}) when Ub =< 65535 ,Lb >= 0 -> % constrained
- decode_constrained_number(Buffer,{Lb,Ub});
-decode_length(_,{Lb,_}) when integer(Lb), Lb >= 0 -> % Ub > 65535
- exit({error,{asn1,{decode_length,{nyi,above_64K}}}});
-decode_length(Buffer,{{Lb,Ub},[]}) ->
- case getbit(Buffer) of
- {0,Buffer2} ->
- decode_length(Buffer2, {Lb,Ub})
- end;
-
-
-%When does this case occur with {_,_Lb,Ub} ??
-% X.691:10.9.3.5
-decode_length({Used,Bin},{_,_Lb,_Ub}) -> %when Len =< 127 -> % Unconstrained or large Ub NOTE! this case does not cover case when Ub > 65535
- Unused = (8-Used) rem 8,
- case Bin of
- <<_:Used,0:1,Val:7,R:Unused,Rest/binary>> ->
- {Val,{Used,<<R,Rest/binary>>}};
- <<_:Used,_:Unused,2:2,Val:14,Rest/binary>> ->
- {Val, {0,Rest}};
- <<_:Used,_:Unused,3:2,_:14,_Rest/binary>> ->
- exit({error,{asn1,{decode_length,{nyi,length_above_64K}}}})
- end;
-% decode_length(Buffer,{_,_Lb,Ub}) -> %when Len =< 127 -> % Unconstrained or large Ub
-% case getbit(Buffer) of
-% {0,Remain} ->
-% getbits(Remain,7);
-% {1,Remain} ->
-% {Val,Remain2} = getoctets(Buffer,2),
-% {Val band 2#0111111111111111, Remain2}
-% end;
-decode_length(Buffer,SingleValue) when integer(SingleValue) ->
- {SingleValue,Buffer}.
-
-
- % X.691:11
-encode_boolean(true) ->
- {bits,1,1};
-encode_boolean(false) ->
- {bits,1,0};
-encode_boolean({Name,Val}) when atom(Name) ->
- encode_boolean(Val);
-encode_boolean(Val) ->
- exit({error,{asn1,{encode_boolean,Val}}}).
-
-decode_boolean(Buffer) -> %when record(Buffer,buffer)
- case getbit(Buffer) of
- {1,Remain} -> {true,Remain};
- {0,Remain} -> {false,Remain}
- end.
-
-
-%% ENUMERATED with extension marker
-decode_enumerated(Buffer,C,{Ntup1,Ntup2}) when tuple(Ntup1), tuple(Ntup2) ->
- {Ext,Buffer2} = getext(Buffer),
- case Ext of
- 0 -> % not an extension value
- {Val,Buffer3} = decode_integer(Buffer2,C),
- case catch (element(Val+1,Ntup1)) of
- NewVal when atom(NewVal) -> {NewVal,Buffer3};
- _Error -> exit({error,{asn1,{decode_enumerated,{Val,[Ntup1,Ntup2]}}}})
- end;
- 1 -> % this an extension value
- {Val,Buffer3} = decode_small_number(Buffer2),
- case catch (element(Val+1,Ntup2)) of
- NewVal when atom(NewVal) -> {NewVal,Buffer3};
- _ -> {{asn1_enum,Val},Buffer3}
- end
- end;
-
-decode_enumerated(Buffer,C,NamedNumberTup) when tuple(NamedNumberTup) ->
- {Val,Buffer2} = decode_integer(Buffer,C),
- case catch (element(Val+1,NamedNumberTup)) of
- NewVal when atom(NewVal) -> {NewVal,Buffer2};
- _Error -> exit({error,{asn1,{decode_enumerated,{Val,NamedNumberTup}}}})
- end.
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Bitstring value, ITU_T X.690 Chapter 8.5
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-%%===============================================================================
-%% encode bitstring value
-%%===============================================================================
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% bitstring NamedBitList
-%% Val can be of:
-%% - [identifiers] where only named identifers are set to one,
-%% the Constraint must then have some information of the
-%% bitlength.
-%% - [list of ones and zeroes] all bits
-%% - integer value representing the bitlist
-%% C is constraint Len, only valid when identifiers
-
-
-%% when the value is a list of {Unused,BinBits}, where
-%% Unused = integer(),
-%% BinBits = binary().
-
-encode_bit_string(C,Bin={Unused,BinBits},NamedBitList) when integer(Unused),
- binary(BinBits) ->
- encode_bin_bit_string(C,Bin,NamedBitList);
-
-%% when the value is a list of named bits
-encode_bit_string(C, LoNB=[FirstVal | _RestVal], NamedBitList) when atom(FirstVal) ->
- ToSetPos = get_all_bitposes(LoNB, NamedBitList, []),
- BitList = make_and_set_list(ToSetPos,0),
- encode_bit_string(C,BitList,NamedBitList);
-
-encode_bit_string(C, BL=[{bit,_No} | _RestVal], NamedBitList) ->
- ToSetPos = get_all_bitposes(BL, NamedBitList, []),
- BitList = make_and_set_list(ToSetPos,0),
- encode_bit_string(C,BitList,NamedBitList);
-
-%% when the value is a list of ones and zeroes
-
-% encode_bit_string(C, BitListValue, NamedBitList) when list(BitListValue) ->
-% Bl1 =
-% case NamedBitList of
-% [] -> % dont remove trailing zeroes
-% BitListValue;
-% _ -> % first remove any trailing zeroes
-% lists:reverse(lists:dropwhile(fun(0)->true;(1)->false end,
-% lists:reverse(BitListValue)))
-% end,
-% BitList = [{bit,X} || X <- Bl1],
-% %% BListLen = length(BitList),
-% case get_constraint(C,'SizeConstraint') of
-% 0 -> % fixed length
-% []; % nothing to encode
-% V when integer(V),V=<16 -> % fixed length 16 bits or less
-% pad_list(V,BitList);
-% V when integer(V) -> % fixed length 16 bits or more
-% [align,pad_list(V,BitList)]; % should be another case for V >= 65537
-% {Lb,Ub} when integer(Lb),integer(Ub) ->
-% [encode_length({Lb,Ub},length(BitList)),align,BitList];
-% no ->
-% [encode_length(undefined,length(BitList)),align,BitList];
-% Sc -> % extension marker
-% [encode_length(Sc,length(BitList)),align,BitList]
-% end;
-encode_bit_string(C, BitListValue, NamedBitList) when list(BitListValue) ->
- BitListToBinary =
- %% fun that transforms a list of 1 and 0 to a tuple:
- %% {UnusedBitsInLastByte, Binary}
- fun([H|T],Acc,N,Fun) ->
- Fun(T,(Acc bsl 1)+H,N+1,Fun);
- ([],Acc,N,_) ->
- Unused = (8 - (N rem 8)) rem 8,
- {Unused,<<Acc:N,0:Unused>>}
- end,
- UnusedAndBin =
- case NamedBitList of
- [] -> % dont remove trailing zeroes
- BitListToBinary(BitListValue,0,0,BitListToBinary);
- _ ->
- BitListToBinary(lists:reverse(
- lists:dropwhile(fun(0)->true;(1)->false end,
- lists:reverse(BitListValue))),
- 0,0,BitListToBinary)
- end,
- encode_bin_bit_string(C,UnusedAndBin,NamedBitList);
-
-%% when the value is an integer
-encode_bit_string(C, IntegerVal, NamedBitList) when integer(IntegerVal)->
- BitList = int_to_bitlist(IntegerVal),
- encode_bit_string(C,BitList,NamedBitList);
-
-%% when the value is a tuple
-encode_bit_string(C,{Name,Val}, NamedBitList) when atom(Name) ->
- encode_bit_string(C,Val,NamedBitList).
-
-
-%% encode_bin_bit_string/3, when value is a tuple of Unused and BinBits.
-%% Unused = integer(),i.e. number unused bits in least sign. byte of
-%% BinBits = binary().
-
-
-encode_bin_bit_string(C,UnusedAndBin={_Unused,_BinBits},NamedBitList) ->
- Constr = get_constraint(C,'SizeConstraint'),
- UnusedAndBin1 = {Unused1,Bin1} =
- remove_trailing_bin(NamedBitList,UnusedAndBin,lower_bound(Constr)),
- case Constr of
- 0 ->
- [];
- V when integer(V),V=<16 ->
- {Unused2,Bin2} = pad_list(V,UnusedAndBin1),
- <<BitVal:V,_:Unused2>> = Bin2,
- {bits,V,BitVal};
- V when integer(V) ->
- [align, pad_list(V, UnusedAndBin1)];
- {Lb,Ub} when integer(Lb),integer(Ub) ->
- [encode_length({Lb,Ub},size(Bin1)*8 - Unused1),
- align,UnusedAndBin1];
- no ->
- [encode_length(undefined,size(Bin1)*8 - Unused1),
- align,UnusedAndBin1];
- Sc ->
- [encode_length(Sc,size(Bin1)*8 - Unused1),
- align,UnusedAndBin1]
- end.
-
-remove_trailing_bin([], {Unused,Bin},_) ->
- {Unused,Bin};
-remove_trailing_bin(NamedNumberList, {_Unused,Bin},C) ->
- Size = size(Bin)-1,
- <<Bfront:Size/binary, LastByte:8>> = Bin,
- %% clear the Unused bits to be sure
-% LastByte1 = LastByte band (((1 bsl Unused) -1) bxor 255),
- Unused1 = trailingZeroesInNibble(LastByte band 15),
- Unused2 =
- case Unused1 of
- 4 ->
- 4 + trailingZeroesInNibble(LastByte bsr 4);
- _ -> Unused1
- end,
- case Unused2 of
- 8 ->
- remove_trailing_bin(NamedNumberList,{0,Bfront},C);
- _ ->
- case C of
- Int when integer(Int),Int > ((size(Bin)*8)-Unused2) ->
- %% this padding see OTP-4353
- pad_list(Int,{Unused2,Bin});
- _ -> {Unused2,Bin}
- end
- end.
-
-
-trailingZeroesInNibble(0) ->
- 4;
-trailingZeroesInNibble(1) ->
- 0;
-trailingZeroesInNibble(2) ->
- 1;
-trailingZeroesInNibble(3) ->
- 0;
-trailingZeroesInNibble(4) ->
- 2;
-trailingZeroesInNibble(5) ->
- 0;
-trailingZeroesInNibble(6) ->
- 1;
-trailingZeroesInNibble(7) ->
- 0;
-trailingZeroesInNibble(8) ->
- 3;
-trailingZeroesInNibble(9) ->
- 0;
-trailingZeroesInNibble(10) ->
- 1;
-trailingZeroesInNibble(11) ->
- 0;
-trailingZeroesInNibble(12) -> %#1100
- 2;
-trailingZeroesInNibble(13) ->
- 0;
-trailingZeroesInNibble(14) ->
- 1;
-trailingZeroesInNibble(15) ->
- 0.
-
-lower_bound({{Lb,_},_}) when integer(Lb) ->
- Lb;
-lower_bound({Lb,_}) when integer(Lb) ->
- Lb;
-lower_bound(C) ->
- C.
-
-%%%%%%%%%%%%%%%
-%% The result is presented as a list of named bits (if possible)
-%% else as a tuple {Unused,Bits}. Unused is the number of unused
-%% bits, least significant bits in the last byte of Bits. Bits is
-%% the BIT STRING represented as a binary.
-%%
-decode_compact_bit_string(Buffer, C, NamedNumberList) ->
- case get_constraint(C,'SizeConstraint') of
- 0 -> % fixed length
- {{8,0},Buffer};
- V when integer(V),V=<16 -> %fixed length 16 bits or less
- compact_bit_string(Buffer,V,NamedNumberList);
- V when integer(V),V=<65536 -> %fixed length > 16 bits
- Bytes2 = align(Buffer),
- compact_bit_string(Bytes2,V,NamedNumberList);
- V when integer(V) -> % V > 65536 => fragmented value
- {Bin,Buffer2} = decode_fragmented_bits(Buffer,V),
- case Buffer2 of
- {0,_} -> {{0,Bin},Buffer2};
- {U,_} -> {{8-U,Bin},Buffer2}
- end;
- {Lb,Ub} when integer(Lb),integer(Ub) ->
- %% This case may demand decoding of fragmented length/value
- {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
- Bytes3 = align(Bytes2),
- compact_bit_string(Bytes3,Len,NamedNumberList);
- no ->
- %% This case may demand decoding of fragmented length/value
- {Len,Bytes2} = decode_length(Buffer,undefined),
- Bytes3 = align(Bytes2),
- compact_bit_string(Bytes3,Len,NamedNumberList);
- Sc ->
- {Len,Bytes2} = decode_length(Buffer,Sc),
- Bytes3 = align(Bytes2),
- compact_bit_string(Bytes3,Len,NamedNumberList)
- end.
-
-
-%%%%%%%%%%%%%%%
-%% The result is presented as a list of named bits (if possible)
-%% else as a list of 0 and 1.
-%%
-decode_bit_string(Buffer, C, NamedNumberList) ->
- case get_constraint(C,'SizeConstraint') of
- {Lb,Ub} when integer(Lb),integer(Ub) ->
- {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
- Bytes3 = align(Bytes2),
- bit_list_or_named(Bytes3,Len,NamedNumberList);
- no ->
- {Len,Bytes2} = decode_length(Buffer,undefined),
- Bytes3 = align(Bytes2),
- bit_list_or_named(Bytes3,Len,NamedNumberList);
- 0 -> % fixed length
- {[],Buffer}; % nothing to encode
- V when integer(V),V=<16 -> % fixed length 16 bits or less
- bit_list_or_named(Buffer,V,NamedNumberList);
- V when integer(V),V=<65536 ->
- Bytes2 = align(Buffer),
- bit_list_or_named(Bytes2,V,NamedNumberList);
- V when integer(V) ->
- Bytes2 = align(Buffer),
- {BinBits,_} = decode_fragmented_bits(Bytes2,V),
- bit_list_or_named(BinBits,V,NamedNumberList);
- Sc -> % extension marker
- {Len,Bytes2} = decode_length(Buffer,Sc),
- Bytes3 = align(Bytes2),
- bit_list_or_named(Bytes3,Len,NamedNumberList)
- end.
-
-
-%% if no named bits are declared we will return a
-%% {Unused,Bits}. Unused = integer(),
-%% Bits = binary().
-compact_bit_string(Buffer,Len,[]) ->
- getbits_as_binary(Len,Buffer); % {{Unused,BinBits},NewBuffer}
-compact_bit_string(Buffer,Len,NamedNumberList) ->
- bit_list_or_named(Buffer,Len,NamedNumberList).
-
-
-%% if no named bits are declared we will return a
-%% BitList = [0 | 1]
-
-bit_list_or_named(Buffer,Len,[]) ->
- getbits_as_list(Len,Buffer);
-
-%% if there are named bits declared we will return a named
-%% BitList where the names are atoms and unnamed bits represented
-%% as {bit,Pos}
-%% BitList = [atom() | {bit,Pos}]
-%% Pos = integer()
-
-bit_list_or_named(Buffer,Len,NamedNumberList) ->
- {BitList,Rest} = getbits_as_list(Len,Buffer),
- {bit_list_or_named1(0,BitList,NamedNumberList,[]), Rest}.
-
-bit_list_or_named1(Pos,[0|Bt],Names,Acc) ->
- bit_list_or_named1(Pos+1,Bt,Names,Acc);
-bit_list_or_named1(Pos,[1|Bt],Names,Acc) ->
- case lists:keysearch(Pos,2,Names) of
- {value,{Name,_}} ->
- bit_list_or_named1(Pos+1,Bt,Names,[Name|Acc]);
- _ ->
- bit_list_or_named1(Pos+1,Bt,Names,[{bit,Pos}|Acc])
- end;
-bit_list_or_named1(_,[],_,Acc) ->
- lists:reverse(Acc).
-
-
-
-%%%%%%%%%%%%%%%
-%%
-
-int_to_bitlist(Int) when integer(Int), Int > 0 ->
- [Int band 1 | int_to_bitlist(Int bsr 1)];
-int_to_bitlist(0) ->
- [].
-
-
-%%%%%%%%%%%%%%%%%%
-%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
-%% [sorted_list_of_bitpositions_to_set]
-
-get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
-
-get_all_bitposes([Val | Rest], NamedBitList, Ack) ->
- case lists:keysearch(Val, 1, NamedBitList) of
- {value, {_ValName, ValPos}} ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
- _ ->
- exit({error,{asn1, {bitstring_namedbit, Val}}})
- end;
-get_all_bitposes([], _NamedBitList, Ack) ->
- lists:sort(Ack).
-
-%%%%%%%%%%%%%%%%%%
-%% make_and_set_list([list of positions to set to 1])->
-%% returns list with all in SetPos set.
-%% in positioning in list the first element is 0, the second 1 etc.., but
-%%
-
-make_and_set_list([XPos|SetPos], XPos) ->
- [1 | make_and_set_list(SetPos, XPos + 1)];
-make_and_set_list([Pos|SetPos], XPos) ->
- [0 | make_and_set_list([Pos | SetPos], XPos + 1)];
-make_and_set_list([], _) ->
- [].
-
-%%%%%%%%%%%%%%%%%
-%% pad_list(N,BitList) -> PaddedList
-%% returns a padded (with trailing {bit,0} elements) list of length N
-%% if Bitlist contains more than N significant bits set an exit asn1_error
-%% is generated
-
-pad_list(N,In={Unused,Bin}) ->
- pad_list(N, size(Bin)*8 - Unused, In).
-
-pad_list(N,Size,In={_,_}) when N < Size ->
- exit({error,{asn1,{range_error,{bit_string,In}}}});
-pad_list(N,Size,{Unused,Bin}) when N > Size, Unused > 0 ->
- pad_list(N,Size+1,{Unused-1,Bin});
-pad_list(N,Size,{_Unused,Bin}) when N > Size ->
- pad_list(N,Size+1,{7,<<Bin/binary,0>>});
-pad_list(N,N,In={_,_}) ->
- In.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% X.691:16
-%% encode_octet_string(Constraint,ExtensionMarker,Val)
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-encode_octet_string(C,Val) ->
- encode_octet_string(C,false,Val).
-
-encode_octet_string(C,Bool,{_Name,Val}) ->
- encode_octet_string(C,Bool,Val);
-encode_octet_string(_,true,_) ->
- exit({error,{asn1,{'not_supported',extensionmarker}}});
-encode_octet_string(C,false,Val) ->
- case get_constraint(C,'SizeConstraint') of
- 0 ->
- [];
- 1 ->
- [V] = Val,
- {bits,8,V};
- 2 ->
- [V1,V2] = Val,
- [{bits,8,V1},{bits,8,V2}];
- Sv when Sv =<65535, Sv == length(Val) -> % fixed length
- {octets,Val};
- {Lb,Ub} ->
- [encode_length({Lb,Ub},length(Val)),{octets,Val}];
- Sv when list(Sv) ->
- [encode_length({hd(Sv),lists:max(Sv)},length(Val)),{octets,Val}];
- no ->
- [encode_length(undefined,length(Val)),{octets,Val}]
- end.
-
-decode_octet_string(Bytes,Range) ->
- decode_octet_string(Bytes,Range,false).
-
-decode_octet_string(Bytes,C,false) ->
- case get_constraint(C,'SizeConstraint') of
- 0 ->
- {[],Bytes};
- 1 ->
- {B1,Bytes2} = getbits(Bytes,8),
- {[B1],Bytes2};
- 2 ->
- {Bs,Bytes2}= getbits(Bytes,16),
- {binary_to_list(<<Bs:16>>),Bytes2};
- {_,0} ->
- {[],Bytes};
- Sv when integer(Sv), Sv =<65535 -> % fixed length
- getoctets_as_list(Bytes,Sv);
- Sv when integer(Sv) -> % fragmented encoding
- Bytes2 = align(Bytes),
- decode_fragmented_octets(Bytes2,Sv);
- {Lb,Ub} ->
- {Len,Bytes2} = decode_length(Bytes,{Lb,Ub}),
- getoctets_as_list(Bytes2,Len);
- Sv when list(Sv) ->
- {Len,Bytes2} = decode_length(Bytes,{hd(Sv),lists:max(Sv)}),
- getoctets_as_list(Bytes2,Len);
- no ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- getoctets_as_list(Bytes2,Len)
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Restricted char string types
-%% (NumericString, PrintableString,VisibleString,IA5String,BMPString,UniversalString)
-%% X.691:26 and X.680:34-36
-%%encode_restricted_string(aligned,'BMPString',Constraints,Extension,Val)
-
-
-encode_restricted_string(aligned,{Name,Val}) when atom(Name) ->
- encode_restricted_string(aligned,Val);
-
-encode_restricted_string(aligned,Val) when list(Val)->
- [encode_length(undefined,length(Val)),{octets,Val}].
-
-encode_known_multiplier_string(aligned,StringType,C,_Ext,{Name,Val}) when atom(Name) ->
- encode_known_multiplier_string(aligned,StringType,C,false,Val);
-
-encode_known_multiplier_string(aligned,StringType,C,_Ext,Val) ->
- Result = chars_encode(C,StringType,Val),
- NumBits = get_NumBits(C,StringType),
- case get_constraint(C,'SizeConstraint') of
- Ub when integer(Ub), Ub*NumBits =< 16 ->
- case {StringType,Result} of
- {'BMPString',{octets,Ol}} ->
- [{bits,8,Oct}||Oct <- Ol];
- _ ->
- Result
- end;
- 0 ->
- [];
- Ub when integer(Ub),Ub =<65535 -> % fixed length
- [align,Result];
- {Ub,Lb} ->
- [encode_length({Ub,Lb},length(Val)),align,Result];
- Vl when list(Vl) ->
- [encode_length({lists:min(Vl),lists:max(Vl)},length(Val)),align,Result];
- no ->
- [encode_length(undefined,length(Val)),align,Result]
- end.
-
-decode_restricted_string(Bytes,aligned) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- getoctets_as_list(Bytes2,Len).
-
-decode_known_multiplier_string(Bytes,aligned,StringType,C,_Ext) ->
- NumBits = get_NumBits(C,StringType),
- case get_constraint(C,'SizeConstraint') of
- Ub when integer(Ub), Ub*NumBits =< 16 ->
- chars_decode(Bytes,NumBits,StringType,C,Ub);
- Ub when integer(Ub),Ub =<65535 -> % fixed length
- Bytes1 = align(Bytes),
- chars_decode(Bytes1,NumBits,StringType,C,Ub);
- 0 ->
- {[],Bytes};
- Vl when list(Vl) ->
- {Len,Bytes1} = decode_length(Bytes,{hd(Vl),lists:max(Vl)}),
- Bytes2 = align(Bytes1),
- chars_decode(Bytes2,NumBits,StringType,C,Len);
- no ->
- {Len,Bytes1} = decode_length(Bytes,undefined),
- Bytes2 = align(Bytes1),
- chars_decode(Bytes2,NumBits,StringType,C,Len);
- {Lb,Ub}->
- {Len,Bytes1} = decode_length(Bytes,{Lb,Ub}),
- Bytes2 = align(Bytes1),
- chars_decode(Bytes2,NumBits,StringType,C,Len)
- end.
-
-
-encode_NumericString(C,Val) ->
- encode_known_multiplier_string(aligned,'NumericString',C,false,Val).
-decode_NumericString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,aligned,'NumericString',C,false).
-
-encode_PrintableString(C,Val) ->
- encode_known_multiplier_string(aligned,'PrintableString',C,false,Val).
-decode_PrintableString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,aligned,'PrintableString',C,false).
-
-encode_VisibleString(C,Val) -> % equivalent with ISO646String
- encode_known_multiplier_string(aligned,'VisibleString',C,false,Val).
-decode_VisibleString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,aligned,'VisibleString',C,false).
-
-encode_IA5String(C,Val) ->
- encode_known_multiplier_string(aligned,'IA5String',C,false,Val).
-decode_IA5String(Bytes,C) ->
- decode_known_multiplier_string(Bytes,aligned,'IA5String',C,false).
-
-encode_BMPString(C,Val) ->
- encode_known_multiplier_string(aligned,'BMPString',C,false,Val).
-decode_BMPString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,aligned,'BMPString',C,false).
-
-encode_UniversalString(C,Val) ->
- encode_known_multiplier_string(aligned,'UniversalString',C,false,Val).
-decode_UniversalString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,aligned,'UniversalString',C,false).
-
-%% end of known-multiplier strings for which PER visible constraints are
-%% applied
-
-encode_GeneralString(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_GeneralString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_GraphicString(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_GraphicString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_ObjectDescriptor(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_ObjectDescriptor(Bytes) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_TeletexString(_C,Val) -> % equivalent with T61String
- encode_restricted_string(aligned,Val).
-decode_TeletexString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_VideotexString(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_VideotexString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% getBMPChars(Bytes,Len) ->{BMPcharList,RemainingBytes}
-%%
-getBMPChars(Bytes,1) ->
- {O1,Bytes2} = getbits(Bytes,8),
- {O2,Bytes3} = getbits(Bytes2,8),
- if
- O1 == 0 ->
- {[O2],Bytes3};
- true ->
- {[{0,0,O1,O2}],Bytes3}
- end;
-getBMPChars(Bytes,Len) ->
- getBMPChars(Bytes,Len,[]).
-
-getBMPChars(Bytes,0,Acc) ->
- {lists:reverse(Acc),Bytes};
-getBMPChars(Bytes,Len,Acc) ->
- {Octs,Bytes1} = getoctets_as_list(Bytes,2),
- case Octs of
- [0,O2] ->
- getBMPChars(Bytes1,Len-1,[O2|Acc]);
- [O1,O2]->
- getBMPChars(Bytes1,Len-1,[{0,0,O1,O2}|Acc])
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% chars_encode(C,StringType,Value) -> ValueList
-%%
-%% encodes chars according to the per rules taking the constraint PermittedAlphabet
-%% into account.
-%% This function does only encode the value part and NOT the length
-
-chars_encode(C,StringType,Value) ->
- case {StringType,get_constraint(C,'PermittedAlphabet')} of
- {'UniversalString',{_,_Sv}} ->
- exit({error,{asn1,{'not implemented',"UniversalString with PermittedAlphabet constraint"}}});
- {'BMPString',{_,_Sv}} ->
- exit({error,{asn1,{'not implemented',"BMPString with PermittedAlphabet constraint"}}});
- _ ->
- {NumBits,CharOutTab} = {get_NumBits(C,StringType),get_CharOutTab(C,StringType)},
- chars_encode2(Value,NumBits,CharOutTab)
- end.
-
-chars_encode2([H|T],NumBits,{Min,Max,notab}) when H =< Max, H >= Min ->
- [{bits,NumBits,H-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
-chars_encode2([H|T],NumBits,{Min,Max,Tab}) when H =< Max, H >= Min ->
- [{bits,NumBits,exit_if_false(H,element(H-Min+1,Tab))}|chars_encode2(T,NumBits,{Min,Max,Tab})];
-chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,notab}) ->
- %% no value range check here (ought to be, but very expensive)
-% [{bits,NumBits,(A*B*C*D)-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
- [{bits,NumBits,((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
-chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,Tab}) ->
- %% no value range check here (ought to be, but very expensive)
-% [{bits,NumBits,element((A*B*C*D)-Min,Tab)}|chars_encode2(T,NumBits,{Min,Max,notab})];
- [{bits,NumBits,exit_if_false({A,B,C,D},element(((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min,Tab))}|chars_encode2(T,NumBits,{Min,Max,notab})];
-chars_encode2([H|_T],_,{_,_,_}) ->
- exit({error,{asn1,{illegal_char_value,H}}});
-chars_encode2([],_,_) ->
- [].
-
-exit_if_false(V,false)->
- exit({error,{asn1,{"illegal value according to Permitted alphabet constraint",V}}});
-exit_if_false(_,V) ->V.
-
-
-get_NumBits(C,StringType) ->
- case get_constraint(C,'PermittedAlphabet') of
- {'SingleValue',Sv} ->
- charbits(length(Sv),aligned);
- no ->
- case StringType of
- 'IA5String' ->
- charbits(128,aligned); % 16#00..16#7F
- 'VisibleString' ->
- charbits(95,aligned); % 16#20..16#7E
- 'PrintableString' ->
- charbits(74,aligned); % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
- 'NumericString' ->
- charbits(11,aligned); % $ ,"0123456789"
- 'UniversalString' ->
- 32;
- 'BMPString' ->
- 16
- end
- end.
-
-%%Maybe used later
-%%get_MaxChar(C,StringType) ->
-%% case get_constraint(C,'PermittedAlphabet') of
-%% {'SingleValue',Sv} ->
-%% lists:nth(length(Sv),Sv);
-%% no ->
-%% case StringType of
-%% 'IA5String' ->
-%% 16#7F; % 16#00..16#7F
-%% 'VisibleString' ->
-%% 16#7E; % 16#20..16#7E
-%% 'PrintableString' ->
-%% $z; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
-%% 'NumericString' ->
-%% $9; % $ ,"0123456789"
-%% 'UniversalString' ->
-%% 16#ffffffff;
-%% 'BMPString' ->
-%% 16#ffff
-%% end
-%% end.
-
-%%Maybe used later
-%%get_MinChar(C,StringType) ->
-%% case get_constraint(C,'PermittedAlphabet') of
-%% {'SingleValue',Sv} ->
-%% hd(Sv);
-%% no ->
-%% case StringType of
-%% 'IA5String' ->
-%% 16#00; % 16#00..16#7F
-%% 'VisibleString' ->
-%% 16#20; % 16#20..16#7E
-%% 'PrintableString' ->
-%% $\s; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
-%% 'NumericString' ->
-%% $\s; % $ ,"0123456789"
-%% 'UniversalString' ->
-%% 16#00;
-%% 'BMPString' ->
-%% 16#00
-%% end
-%% end.
-
-get_CharOutTab(C,StringType) ->
- get_CharTab(C,StringType,out).
-
-get_CharInTab(C,StringType) ->
- get_CharTab(C,StringType,in).
-
-get_CharTab(C,StringType,InOut) ->
- case get_constraint(C,'PermittedAlphabet') of
- {'SingleValue',Sv} ->
- get_CharTab2(C,StringType,hd(Sv),lists:max(Sv),Sv,InOut);
- no ->
- case StringType of
- 'IA5String' ->
- {0,16#7F,notab};
- 'VisibleString' ->
- get_CharTab2(C,StringType,16#20,16#7F,notab,InOut);
- 'PrintableString' ->
- Chars = lists:sort(
- " '()+,-./0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
- get_CharTab2(C,StringType,hd(Chars),lists:max(Chars),Chars,InOut);
- 'NumericString' ->
- get_CharTab2(C,StringType,16#20,$9," 0123456789",InOut);
- 'UniversalString' ->
- {0,16#FFFFFFFF,notab};
- 'BMPString' ->
- {0,16#FFFF,notab}
- end
- end.
-
-get_CharTab2(C,StringType,Min,Max,Chars,InOut) ->
- BitValMax = (1 bsl get_NumBits(C,StringType))-1,
- if
- Max =< BitValMax ->
- {0,Max,notab};
- true ->
- case InOut of
- out ->
- {Min,Max,create_char_tab(Min,Chars)};
- in ->
- {Min,Max,list_to_tuple(Chars)}
- end
- end.
-
-create_char_tab(Min,L) ->
- list_to_tuple(create_char_tab(Min,L,0)).
-create_char_tab(Min,[Min|T],V) ->
- [V|create_char_tab(Min+1,T,V+1)];
-create_char_tab(_Min,[],_V) ->
- [];
-create_char_tab(Min,L,V) ->
- [false|create_char_tab(Min+1,L,V)].
-
-%% This very inefficient and should be moved to compiletime
-charbits(NumOfChars,aligned) ->
- case charbits(NumOfChars) of
- 1 -> 1;
- 2 -> 2;
- B when B =< 4 -> 4;
- B when B =< 8 -> 8;
- B when B =< 16 -> 16;
- B when B =< 32 -> 32
- end.
-
-charbits(NumOfChars) when NumOfChars =< 2 -> 1;
-charbits(NumOfChars) when NumOfChars =< 4 -> 2;
-charbits(NumOfChars) when NumOfChars =< 8 -> 3;
-charbits(NumOfChars) when NumOfChars =< 16 -> 4;
-charbits(NumOfChars) when NumOfChars =< 32 -> 5;
-charbits(NumOfChars) when NumOfChars =< 64 -> 6;
-charbits(NumOfChars) when NumOfChars =< 128 -> 7;
-charbits(NumOfChars) when NumOfChars =< 256 -> 8;
-charbits(NumOfChars) when NumOfChars =< 512 -> 9;
-charbits(NumOfChars) when NumOfChars =< 1024 -> 10;
-charbits(NumOfChars) when NumOfChars =< 2048 -> 11;
-charbits(NumOfChars) when NumOfChars =< 4096 -> 12;
-charbits(NumOfChars) when NumOfChars =< 8192 -> 13;
-charbits(NumOfChars) when NumOfChars =< 16384 -> 14;
-charbits(NumOfChars) when NumOfChars =< 32768 -> 15;
-charbits(NumOfChars) when NumOfChars =< 65536 -> 16;
-charbits(NumOfChars) when integer(NumOfChars) ->
- 16 + charbits1(NumOfChars bsr 16).
-
-charbits1(0) ->
- 0;
-charbits1(NumOfChars) ->
- 1 + charbits1(NumOfChars bsr 1).
-
-
-chars_decode(Bytes,_,'BMPString',C,Len) ->
- case get_constraint(C,'PermittedAlphabet') of
- no ->
- getBMPChars(Bytes,Len);
- _ ->
- exit({error,{asn1,
- {'not implemented',
- "BMPString with PermittedAlphabet constraint"}}})
- end;
-chars_decode(Bytes,NumBits,StringType,C,Len) ->
- CharInTab = get_CharInTab(C,StringType),
- chars_decode2(Bytes,CharInTab,NumBits,Len).
-
-
-chars_decode2(Bytes,CharInTab,NumBits,Len) ->
- chars_decode2(Bytes,CharInTab,NumBits,Len,[]).
-
-chars_decode2(Bytes,_CharInTab,_NumBits,0,Acc) ->
- {lists:reverse(Acc),Bytes};
-chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) when NumBits > 8 ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- Result =
- if
- Char < 256 -> Char;
- true ->
- list_to_tuple(binary_to_list(<<Char:32>>))
- end,
- chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Result|Acc]);
-% chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) when NumBits > 8 ->
-% {Char,Bytes2} = getbits(Bytes,NumBits),
-% Result = case minimum_octets(Char+Min) of
-% [NewChar] -> NewChar;
-% [C1,C2] -> {0,0,C1,C2};
-% [C1,C2,C3] -> {0,C1,C2,C3};
-% [C1,C2,C3,C4] -> {C1,C2,C3,C4}
-% end,
-% chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Result|Acc]);
-chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Char+Min|Acc]);
-
-%% BMPString and UniversalString with PermittedAlphabet is currently not supported
-chars_decode2(Bytes,{Min,Max,CharInTab},NumBits,Len,Acc) ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- chars_decode2(Bytes2,{Min,Max,CharInTab},NumBits,Len -1,[element(Char+1,CharInTab)|Acc]).
-
-
- % X.691:17
-encode_null(_) -> []; % encodes to nothing
-encode_null({Name,Val}) when atom(Name) ->
- encode_null(Val).
-
-decode_null(Bytes) ->
- {'NULL',Bytes}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_object_identifier(Val) -> CompleteList
-%% encode_object_identifier({Name,Val}) -> CompleteList
-%% Val -> {Int1,Int2,...,IntN} % N >= 2
-%% Name -> atom()
-%% Int1 -> integer(0..2)
-%% Int2 -> integer(0..39) when Int1 (0..1) else integer()
-%% Int3-N -> integer()
-%% CompleteList -> [{bits,8,Val}|{octets,Ol}|align|...]
-%%
-encode_object_identifier({Name,Val}) when atom(Name) ->
- encode_object_identifier(Val);
-encode_object_identifier(Val) ->
- OctetList = e_object_identifier(Val),
- Octets = list_to_binary(OctetList), % performs a flatten at the same time
- [{debug,object_identifier},encode_length(undefined,size(Octets)),{octets,Octets}].
-
-%% This code is copied from asn1_encode.erl (BER) and corrected and modified
-
-e_object_identifier({'OBJECT IDENTIFIER',V}) ->
- e_object_identifier(V);
-e_object_identifier({Cname,V}) when atom(Cname),tuple(V) ->
- e_object_identifier(tuple_to_list(V));
-e_object_identifier({Cname,V}) when atom(Cname),list(V) ->
- e_object_identifier(V);
-e_object_identifier(V) when tuple(V) ->
- e_object_identifier(tuple_to_list(V));
-
-%% E1 = 0|1|2 and (E2 < 40 when E1 = 0|1)
-e_object_identifier([E1,E2|Tail]) when E1 >= 0, E1 < 2, E2 < 40 ; E1==2 ->
- Head = 40*E1 + E2, % weird
- e_object_elements([Head|Tail],[]);
-e_object_identifier(Oid=[_,_|_Tail]) ->
- exit({error,{asn1,{'illegal_value',Oid}}}).
-
-e_object_elements([],Acc) ->
- lists:reverse(Acc);
-e_object_elements([H|T],Acc) ->
- e_object_elements(T,[e_object_element(H)|Acc]).
-
-e_object_element(Num) when Num < 128 ->
- Num;
-%% must be changed to handle more than 2 octets
-e_object_element(Num) -> %% when Num < ???
- Left = ((Num band 2#11111110000000) bsr 7) bor 2#10000000,
- Right = Num band 2#1111111 ,
- [Left,Right].
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_object_identifier(Bytes) -> {ObjId,RemainingBytes}
-%% ObjId -> {integer(),integer(),...} % at least 2 integers
-%% RemainingBytes -> [integer()] when integer() (0..255)
-decode_object_identifier(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- [First|Rest] = dec_subidentifiers(Octs,0,[]),
- Idlist = if
- First < 40 ->
- [0,First|Rest];
- First < 80 ->
- [1,First - 40|Rest];
- true ->
- [2,First - 80|Rest]
- end,
- {list_to_tuple(Idlist),Bytes3}.
-
-dec_subidentifiers([H|T],Av,Al) when H >=16#80 ->
- dec_subidentifiers(T,(Av bsl 7) + (H band 16#7F),Al);
-dec_subidentifiers([H|T],Av,Al) ->
- dec_subidentifiers(T,0,[(Av bsl 7) + H |Al]);
-dec_subidentifiers([],_Av,Al) ->
- lists:reverse(Al).
-
-get_constraint([{Key,V}],Key) ->
- V;
-get_constraint([],_Key) ->
- no;
-get_constraint(C,Key) ->
- case lists:keysearch(Key,1,C) of
- false ->
- no;
- {value,{_,V}} ->
- V
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% complete(InList) -> ByteList
-%% Takes a coded list with bits and bytes and converts it to a list of bytes
-%% Should be applied as the last step at encode of a complete ASN.1 type
-%%
-
-% complete(L) ->
-% case complete1(L) of
-% {[],0} ->
-% <<0>>;
-% {Acc,0} ->
-% lists:reverse(Acc);
-% {[Hacc|Tacc],Acclen} -> % Acclen >0
-% Rest = 8 - Acclen,
-% NewHacc = Hacc bsl Rest,
-% lists:reverse([NewHacc|Tacc])
-% end.
-
-
-% complete1(InList) when list(InList) ->
-% complete1(InList,[]);
-% complete1(InList) ->
-% complete1([InList],[]).
-
-% complete1([{debug,_}|T], Acc) ->
-% complete1(T,Acc);
-% complete1([H|T],Acc) when list(H) ->
-% {NewH,NewAcclen} = complete1(H,Acc),
-% complete1(T,NewH,NewAcclen);
-
-% complete1([{0,Bin}|T],Acc,0) when binary(Bin) ->
-% complete1(T,[Bin|Acc],0);
-% complete1([{Unused,Bin}|T],Acc,0) when integer(Unused),binary(Bin) ->
-% Size = size(Bin)-1,
-% <<Bs:Size/binary,B>> = Bin,
-% complete1(T,[(B bsr Unused),Bs|Acc],8-Unused);
-% complete1([{Unused,Bin}|T],[Hacc|Tacc],Acclen) when integer(Unused),binary(Bin) ->
-% Rest = 8 - Acclen,
-% Used = 8 - Unused,
-% case size(Bin) of
-% 1 ->
-% if
-% Rest >= Used ->
-% <<B:Used,_:Unused>> = Bin,
-% complete1(T,[(Hacc bsl Used) + B|Tacc],
-% (Acclen+Used) rem 8);
-% true ->
-% LeftOver = 8 - Rest - Unused,
-% <<Val2:Rest,Val1:LeftOver,_:Unused>> = Bin,
-% complete1(T,[Val1,(Hacc bsl Rest) + Val2|Tacc],
-% (Acclen+Used) rem 8)
-% end;
-% N ->
-% if
-% Rest == Used ->
-% N1 = N - 1,
-% <<B:Rest,Bs:N1/binary,_:Unused>> = Bin,
-% complete1(T,[Bs,(Hacc bsl Rest) + B|Tacc],0);
-% Rest > Used ->
-% N1 = N - 2,
-% N2 = (8 - Rest) + Used,
-% <<B1:Rest,Bytes:N1/binary,B2:N2,_:Unused>> = Bin,
-% complete1(T,[B2,Bytes,(Hacc bsl Rest) + B1|Tacc],
-% (Acclen + Used) rem 8);
-% true -> % Rest < Used
-% N1 = N - 1,
-% N2 = Used - Rest,
-% <<B1:Rest,Bytes:N1/binary,B2:N2,_:Unused>> = Bin,
-% complete1(T,[B2,Bytes,(Hacc bsl Rest) + B1|Tacc],
-% (Acclen + Used) rem 8)
-% end
-% end;
-
-% %complete1([{octets,N,Val}|T],Acc,Acclen) when N =< 4 ,integer(Val) ->
-% % complete1([{octets,<<Val:N/unit:8>>}|T],Acc,Acclen);
-% complete1([{octets,N,Val}|T],Acc,Acclen) when N =< 4 ,integer(Val) ->
-% Newval = case N of
-% 1 ->
-% Val4 = Val band 16#FF,
-% [Val4];
-% 2 ->
-% Val3 = (Val bsr 8) band 16#FF,
-% Val4 = Val band 16#FF,
-% [Val3,Val4];
-% 3 ->
-% Val2 = (Val bsr 16) band 16#FF,
-% Val3 = (Val bsr 8) band 16#FF,
-% Val4 = Val band 16#FF,
-% [Val2,Val3,Val4];
-% 4 ->
-% Val1 = (Val bsr 24) band 16#FF,
-% Val2 = (Val bsr 16) band 16#FF,
-% Val3 = (Val bsr 8) band 16#FF,
-% Val4 = Val band 16#FF,
-% [Val1,Val2,Val3,Val4]
-% end,
-% complete1([{octets,Newval}|T],Acc,Acclen);
-
-% complete1([{octets,Bin}|T],Acc,Acclen) when binary(Bin) ->
-% Rest = 8 - Acclen,
-% if
-% Rest == 8 ->
-% complete1(T,[Bin|Acc],0);
-% true ->
-% [Hacc|Tacc]=Acc,
-% complete1(T,[Bin, Hacc bsl Rest|Tacc],0)
-% end;
-
-% complete1([{octets,Oct}|T],Acc,Acclen) when list(Oct) ->
-% Rest = 8 - Acclen,
-% if
-% Rest == 8 ->
-% complete1(T,[list_to_binary(Oct)|Acc],0);
-% true ->
-% [Hacc|Tacc]=Acc,
-% complete1(T,[list_to_binary(Oct), Hacc bsl Rest|Tacc],0)
-% end;
-
-% complete1([{bit,Val}|T], Acc, Acclen) ->
-% complete1([{bits,1,Val}|T],Acc,Acclen);
-% complete1([{octet,Val}|T], Acc, Acclen) ->
-% complete1([{octets,1,Val}|T],Acc,Acclen);
-
-% complete1([{bits,N,Val}|T], Acc, 0) when N =< 8 ->
-% complete1(T,[Val|Acc],N);
-% complete1([{bits,N,Val}|T], [Hacc|Tacc], Acclen) when N =< 8 ->
-% Rest = 8 - Acclen,
-% if
-% Rest >= N ->
-% complete1(T,[(Hacc bsl N) + Val|Tacc],(Acclen+N) rem 8);
-% true ->
-% Diff = N - Rest,
-% NewHacc = (Hacc bsl Rest) + (Val bsr Diff),
-% Mask = element(Diff,{1,3,7,15,31,63,127,255}),
-% complete1(T,[(Val band Mask),NewHacc|Tacc],(Acclen+N) rem 8)
-% end;
-% complete1([{bits,N,Val}|T], Acc, Acclen) -> % N > 8
-% complete1([{bits,N-8,Val bsr 8},{bits,8,Val band 255}|T],Acc,Acclen);
-
-% complete1([align|T],Acc,0) ->
-% complete1(T,Acc,0);
-% complete1([align|T],[Hacc|Tacc],Acclen) ->
-% Rest = 8 - Acclen,
-% complete1(T,[Hacc bsl Rest|Tacc],0);
-% complete1([{octets,N,Val}|T],Acc,Acclen) when list(Val) -> % no security check here
-% complete1([{octets,Val}|T],Acc,Acclen);
-
-% complete1([],Acc,Acclen) ->
-% {Acc,Acclen}.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% complete(InList) -> ByteList
-%% Takes a coded list with bits and bytes and converts it to a list of bytes
-%% Should be applied as the last step at encode of a complete ASN.1 type
-%%
-
-complete(L) ->
- case complete1(L) of
- {[],[]} ->
- <<0>>;
- {Acc,[]} ->
- Acc;
- {Acc,Bacc} ->
- [Acc|complete_bytes(Bacc)]
- end.
-
-%% this function builds the ugly form of lists [E1|E2] to avoid having to reverse it at the end.
-%% this is done because it is efficient and that the result always will be sent on a port or
-%% converted by means of list_to_binary/1
-complete1(InList) when list(InList) ->
- complete1(InList,[],[]);
-complete1(InList) ->
- complete1([InList],[],[]).
-
-complete1([],Acc,Bacc) ->
- {Acc,Bacc};
-complete1([H|T],Acc,Bacc) when list(H) ->
- {NewH,NewBacc} = complete1(H,Acc,Bacc),
- complete1(T,NewH,NewBacc);
-
-complete1([{octets,Bin}|T],Acc,[]) ->
- complete1(T,[Acc|Bin],[]);
-
-complete1([{octets,Bin}|T],Acc,Bacc) ->
- complete1(T,[Acc|[complete_bytes(Bacc),Bin]],[]);
-
-complete1([{debug,_}|T], Acc,Bacc) ->
- complete1(T,Acc,Bacc);
-
-complete1([{bits,N,Val}|T],Acc,Bacc) ->
- complete1(T,Acc,complete_update_byte(Bacc,Val,N));
-
-complete1([{bit,Val}|T],Acc,Bacc) ->
- complete1(T,Acc,complete_update_byte(Bacc,Val,1));
-
-complete1([align|T],Acc,[]) ->
- complete1(T,Acc,[]);
-complete1([align|T],Acc,Bacc) ->
- complete1(T,[Acc|complete_bytes(Bacc)],[]);
-complete1([{0,Bin}|T],Acc,[]) when binary(Bin) ->
- complete1(T,[Acc|Bin],[]);
-complete1([{Unused,Bin}|T],Acc,[]) when integer(Unused),binary(Bin) ->
- Size = size(Bin)-1,
- <<Bs:Size/binary,B>> = Bin,
- NumBits = 8-Unused,
- complete1(T,[Acc|Bs],[[B bsr Unused]|NumBits]);
-complete1([{Unused,Bin}|T],Acc,Bacc) when integer(Unused),binary(Bin) ->
- Size = size(Bin)-1,
- <<Bs:Size/binary,B>> = Bin,
- NumBits = 8 - Unused,
- Bf = complete_bytes(Bacc),
- complete1(T,[Acc|[Bf,Bs]],[[B bsr Unused]|NumBits]).
-
-
-complete_update_byte([],Val,Len) ->
- complete_update_byte([[0]|0],Val,Len);
-complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) when NumBits + Len == 8 ->
- [[0,((Byte bsl Len) + Val) band 255|Bacc]|0];
-complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) when NumBits + Len > 8 ->
- Rem = 8 - NumBits,
- Rest = Len - Rem,
- complete_update_byte([[0,((Byte bsl Rem) + (Val bsr Rest)) band 255 |Bacc]|0],Val,Rest);
-complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) ->
- [[((Byte bsl Len) + Val) band 255|Bacc]|NumBits+Len].
-
-
-complete_bytes([[_Byte|Bacc]|0]) ->
- lists:reverse(Bacc);
-complete_bytes([[Byte|Bacc]|NumBytes]) ->
- lists:reverse([(Byte bsl (8-NumBytes)) band 255|Bacc]);
-complete_bytes([]) ->
- [].
-
-% complete_bytes(L) ->
-% complete_bytes1(lists:reverse(L),[],[],0,0).
-
-% complete_bytes1([H={V,B}|T],Acc,ReplyAcc,NumBits,NumFields) when ((NumBits+B) rem 8) == 0 ->
-% NewReplyAcc = [complete_bytes2([H|Acc],0)|ReplyAcc],
-% complete_bytes1(T,[],NewReplyAcc,0,0);
-% complete_bytes1([H={V,B}|T],Acc,ReplyAcc,NumBits,NumFields) when NumFields == 7; (NumBits+B) div 8 > 0 ->
-% Rem = (NumBits+B) rem 8,
-% NewReplyAcc = [complete_bytes2([{V bsr Rem,B - Rem}|Acc],0)|ReplyAcc],
-% complete_bytes1([{V,Rem}|T],[],NewReplyAcc,0,0);
-% complete_bytes1([H={V,B}|T],Acc,ReplyAcc,NumBits,NumFields) ->
-% complete_bytes1(T,[H|Acc],ReplyAcc,NumBits+B,NumFields+1);
-% complete_bytes1([],[],ReplyAcc,_,_) ->
-% lists:reverse(ReplyAcc);
-% complete_bytes1([],Acc,ReplyAcc,NumBits,_) ->
-% PadBits = case NumBits rem 8 of
-% 0 -> 0;
-% Rem -> 8 - Rem
-% end,
-% lists:reverse([complete_bytes2(Acc,PadBits)|ReplyAcc]).
-
-
-% complete_bytes2([{V1,B1}],PadBits) ->
-% <<V1:B1,0:PadBits>>;
-% complete_bytes2([{V2,B2},{V1,B1}],PadBits) ->
-% <<V1:B1,V2:B2,0:PadBits>>;
-% complete_bytes2([{V3,B3},{V2,B2},{V1,B1}],PadBits) ->
-% <<V1:B1,V2:B2,V3:B3,0:PadBits>>;
-% complete_bytes2([{V4,B4},{V3,B3},{V2,B2},{V1,B1}],PadBits) ->
-% <<V1:B1,V2:B2,V3:B3,V4:B4,0:PadBits>>;
-% complete_bytes2([{V5,B5},{V4,B4},{V3,B3},{V2,B2},{V1,B1}],PadBits) ->
-% <<V1:B1,V2:B2,V3:B3,V4:B4,V5:B5,0:PadBits>>;
-% complete_bytes2([{V6,B6},{V5,B5},{V4,B4},{V3,B3},{V2,B2},{V1,B1}],PadBits) ->
-% <<V1:B1,V2:B2,V3:B3,V4:B4,V5:B5,V6:B6,0:PadBits>>;
-% complete_bytes2([{V7,B7},{V6,B6},{V5,B5},{V4,B4},{V3,B3},{V2,B2},{V1,B1}],PadBits) ->
-% <<V1:B1,V2:B2,V3:B3,V4:B4,V5:B5,V6:B6,V7:B7,0:PadBits>>;
-% complete_bytes2([{V8,B8},{V7,B7},{V6,B6},{V5,B5},{V4,B4},{V3,B3},{V2,B2},{V1,B1}],PadBits) ->
-% <<V1:B1,V2:B2,V3:B3,V4:B4,V5:B5,V6:B6,V7:B7,V8:B8,0:PadBits>>.
-
-
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per_bin_rt2ct.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per_bin_rt2ct.erl
deleted file mode 100644
index 0647650ea6..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per_bin_rt2ct.erl
+++ /dev/null
@@ -1,2102 +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: asn1rt_per_bin_rt2ct.erl,v 1.1 2008/12/17 09:53:31 mikpe Exp $
-%%
--module(asn1rt_per_bin_rt2ct).
-
-%% encoding / decoding of PER aligned
-
--include("asn1_records.hrl").
-
--export([dec_fixup/3, cindex/3, list_to_record/2]).
--export([setchoiceext/1, setext/1, fixoptionals/3, fixextensions/2,
- getext/1, getextension/2, skipextensions/3, getbit/1, getchoice/3 ]).
--export([getoptionals/2, getoptionals2/2,
- set_choice/3, encode_integer/2, encode_integer/3 ]).
--export([decode_integer/2, decode_integer/3, encode_small_number/1,
- decode_boolean/1, encode_length/2, decode_length/1, decode_length/2,
- encode_small_length/1, decode_small_length/1,
- decode_compact_bit_string/3]).
--export([decode_enumerated/3,
- encode_bit_string/3, decode_bit_string/3 ]).
--export([encode_octet_string/2, decode_octet_string/2,
- encode_null/1, decode_null/1,
- encode_object_identifier/1, decode_object_identifier/1,
- complete/1]).
-
-
--export([encode_open_type/2, decode_open_type/2]).
-
--export([%encode_UniversalString/2, decode_UniversalString/2,
- %encode_PrintableString/2, decode_PrintableString/2,
- encode_GeneralString/2, decode_GeneralString/2,
- encode_GraphicString/2, decode_GraphicString/2,
- encode_TeletexString/2, decode_TeletexString/2,
- encode_VideotexString/2, decode_VideotexString/2,
- %encode_VisibleString/2, decode_VisibleString/2,
- %encode_BMPString/2, decode_BMPString/2,
- %encode_IA5String/2, decode_IA5String/2,
- %encode_NumericString/2, decode_NumericString/2,
- encode_ObjectDescriptor/2, decode_ObjectDescriptor/1
- ]).
-
--export([decode_constrained_number/2,
- decode_constrained_number/3,
- decode_unconstrained_number/1,
- decode_semi_constrained_number/2,
- encode_unconstrained_number/1,
- decode_constrained_number/4,
- encode_octet_string/3,
- decode_octet_string/3,
- encode_known_multiplier_string/5,
- decode_known_multiplier_string/5,
- getoctets/2, getbits/2
-% start_drv/1,start_drv2/1,init_drv/1
- ]).
-
-
--export([eint_positive/1]).
--export([pre_complete_bits/2]).
-
--define('16K',16384).
--define('32K',32768).
--define('64K',65536).
-
-%%-define(nodriver,true).
-
-dec_fixup(Terms,Cnames,RemBytes) ->
- dec_fixup(Terms,Cnames,RemBytes,[]).
-
-dec_fixup([novalue|T],[_Hc|Tc],RemBytes,Acc) ->
- dec_fixup(T,Tc,RemBytes,Acc);
-dec_fixup([{_Name,novalue}|T],[_Hc|Tc],RemBytes,Acc) ->
- dec_fixup(T,Tc,RemBytes,Acc);
-dec_fixup([H|T],[Hc|Tc],RemBytes,Acc) ->
- dec_fixup(T,Tc,RemBytes,[{Hc,H}|Acc]);
-dec_fixup([],_Cnames,RemBytes,Acc) ->
- {lists:reverse(Acc),RemBytes}.
-
-cindex(Ix,Val,Cname) ->
- case element(Ix,Val) of
- {Cname,Val2} -> Val2;
- X -> X
- end.
-
-%% converts a list to a record if necessary
-list_to_record(_,Tuple) when tuple(Tuple) ->
- Tuple;
-list_to_record(Name,List) when list(List) ->
- list_to_tuple([Name|List]).
-
-%%--------------------------------------------------------
-%% setchoiceext(InRootSet) -> [{bit,X}]
-%% X is set to 1 when InRootSet==false
-%% X is set to 0 when InRootSet==true
-%%
-setchoiceext(true) ->
-% [{debug,choiceext},{bits,1,0}];
- [0];
-setchoiceext(false) ->
-% [{debug,choiceext},{bits,1,1}].
- [1].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% setext(true|false) -> CompleteList
-%%
-
-setext(false) ->
-% [{debug,ext},{bits,1,0}];
- [0];
-setext(true) ->
-% [{debug,ext},{bits,1,1}];
- [1].
-
-fixoptionals(OptList,_OptLength,Val) when tuple(Val) ->
-% Bits = fixoptionals(OptList,Val,0),
-% {Val,{bits,OptLength,Bits}};
-% {Val,[10,OptLength,Bits]};
- {Val,fixoptionals(OptList,Val,[])};
-
-fixoptionals([],_,Acc) ->
- %% Optbits
- lists:reverse(Acc);
-fixoptionals([Pos|Ot],Val,Acc) ->
- case element(Pos,Val) of
-% asn1_NOVALUE -> fixoptionals(Ot,Val,Acc bsl 1);
-% asn1_DEFAULT -> fixoptionals(Ot,Val,Acc bsl 1);
-% _ -> fixoptionals(Ot,Val,(Acc bsl 1) + 1)
- asn1_NOVALUE -> fixoptionals(Ot,Val,[0|Acc]);
- asn1_DEFAULT -> fixoptionals(Ot,Val,[0|Acc]);
- _ -> fixoptionals(Ot,Val,[1|Acc])
- end.
-
-
-getext(Bytes) when tuple(Bytes) ->
- getbit(Bytes);
-getext(Bytes) when binary(Bytes) ->
- getbit({0,Bytes});
-getext(Bytes) when list(Bytes) ->
- getbit({0,Bytes}).
-
-getextension(0, Bytes) ->
- {{},Bytes};
-getextension(1, Bytes) ->
- {Len,Bytes2} = decode_small_length(Bytes),
- {Blist, Bytes3} = getbits_as_list(Len,Bytes2),
- {list_to_tuple(Blist),Bytes3}.
-
-fixextensions({ext,ExtPos,ExtNum},Val) ->
- case fixextensions(ExtPos,ExtNum+ExtPos,Val,0) of
- 0 -> [];
- ExtBits ->
-% [encode_small_length(ExtNum),{bits,ExtNum,ExtBits}]
-% [encode_small_length(ExtNum),[10,ExtNum,ExtBits]]
- [encode_small_length(ExtNum),pre_complete_bits(ExtNum,ExtBits)]
- end.
-
-fixextensions(Pos,MaxPos,_,Acc) when Pos >= MaxPos ->
- Acc;
-fixextensions(Pos,ExtPos,Val,Acc) ->
- Bit = case catch(element(Pos+1,Val)) of
- asn1_NOVALUE ->
- 0;
- asn1_NOEXTVALUE ->
- 0;
- {'EXIT',_} ->
- 0;
- _ ->
- 1
- end,
- fixextensions(Pos+1,ExtPos,Val,(Acc bsl 1)+Bit).
-
-skipextensions(Bytes,Nr,ExtensionBitPattern) ->
- case (catch element(Nr,ExtensionBitPattern)) of
- 1 ->
- {_,Bytes2} = decode_open_type(Bytes,[]),
- skipextensions(Bytes2, Nr+1, ExtensionBitPattern);
- 0 ->
- skipextensions(Bytes, Nr+1, ExtensionBitPattern);
- {'EXIT',_} -> % badarg, no more extensions
- Bytes
- end.
-
-
-getchoice(Bytes,1,0) -> % only 1 alternative is not encoded
- {0,Bytes};
-getchoice(Bytes,_,1) ->
- decode_small_number(Bytes);
-getchoice(Bytes,NumChoices,0) ->
- decode_constrained_number(Bytes,{0,NumChoices-1}).
-
-%% old version kept for backward compatibility with generates from R7B01
-getoptionals(Bytes,NumOpt) ->
- {Blist,Bytes1} = getbits_as_list(NumOpt,Bytes),
- {list_to_tuple(Blist),Bytes1}.
-
-%% new version used in generates from r8b_patch/3 and later
-getoptionals2(Bytes,NumOpt) ->
- {_,_} = getbits(Bytes,NumOpt).
-
-
-%% getbits_as_binary(Num,Bytes) -> {{Unused,BinBits},RestBytes},
-%% Num = integer(),
-%% Bytes = list() | tuple(),
-%% Unused = integer(),
-%% BinBits = binary(),
-%% RestBytes = tuple()
-getbits_as_binary(Num,Bytes) when binary(Bytes) ->
- getbits_as_binary(Num,{0,Bytes});
-getbits_as_binary(0,Buffer) ->
- {{0,<<>>},Buffer};
-getbits_as_binary(Num,{0,Bin}) when Num > 16 ->
- Used = Num rem 8,
- Pad = (8 - Used) rem 8,
-%% Nbytes = Num div 8,
- <<Bits:Num,_:Pad,RestBin/binary>> = Bin,
- {{Pad,<<Bits:Num,0:Pad>>},RestBin};
-getbits_as_binary(Num,Buffer={_Used,_Bin}) -> % Unaligned buffer
- %% Num =< 16,
- {Bits2,Buffer2} = getbits(Buffer,Num),
- Pad = (8 - (Num rem 8)) rem 8,
- {{Pad,<<Bits2:Num,0:Pad>>},Buffer2}.
-
-
-% integer_from_list(Int,[],BigInt) ->
-% BigInt;
-% integer_from_list(Int,[H|T],BigInt) when Int < 8 ->
-% (BigInt bsl Int) bor (H bsr (8-Int));
-% integer_from_list(Int,[H|T],BigInt) ->
-% integer_from_list(Int-8,T,(BigInt bsl 8) bor H).
-
-getbits_as_list(Num,Bytes) when binary(Bytes) ->
- getbits_as_list(Num,{0,Bytes},[]);
-getbits_as_list(Num,Bytes) ->
- getbits_as_list(Num,Bytes,[]).
-
-%% If buffer is empty and nothing more will be picked.
-getbits_as_list(0, B, Acc) ->
- {lists:reverse(Acc),B};
-%% If first byte in buffer is full and at least one byte will be picked,
-%% then pick one byte.
-getbits_as_list(N,{0,Bin},Acc) when N >= 8 ->
- <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1,Rest/binary>> = Bin,
- getbits_as_list(N-8,{0,Rest},[B0,B1,B2,B3,B4,B5,B6,B7|Acc]);
-getbits_as_list(N,{Used,Bin},Acc) when N >= 4, Used =< 4 ->
- NewUsed = Used + 4,
- Rem = 8 - NewUsed,
- <<_:Used,B3:1,B2:1,B1:1,B0:1,_:Rem, Rest/binary>> = Bin,
- NewRest = case Rem of 0 -> Rest; _ -> Bin end,
- getbits_as_list(N-4,{NewUsed rem 8,NewRest},[B0,B1,B2,B3|Acc]);
-getbits_as_list(N,{Used,Bin},Acc) when N >= 2, Used =< 6 ->
- NewUsed = Used + 2,
- Rem = 8 - NewUsed,
- <<_:Used,B1:1,B0:1,_:Rem, Rest/binary>> = Bin,
- NewRest = case Rem of 0 -> Rest; _ -> Bin end,
- getbits_as_list(N-2,{NewUsed rem 8,NewRest},[B0,B1|Acc]);
-getbits_as_list(N,{Used,Bin},Acc) when Used =< 7 ->
- NewUsed = Used + 1,
- Rem = 8 - NewUsed,
- <<_:Used,B0:1,_:Rem, Rest/binary>> = Bin,
- NewRest = case Rem of 0 -> Rest; _ -> Bin end,
- getbits_as_list(N-1,{NewUsed rem 8,NewRest},[B0|Acc]).
-
-
-getbit({7,<<_:7,B:1,Rest/binary>>}) ->
- {B,{0,Rest}};
-getbit({0,Buffer = <<B:1,_:7,_/binary>>}) ->
- {B,{1,Buffer}};
-getbit({Used,Buffer}) ->
- Unused = (8 - Used) - 1,
- <<_:Used,B:1,_:Unused,_/binary>> = Buffer,
- {B,{Used+1,Buffer}};
-getbit(Buffer) when binary(Buffer) ->
- getbit({0,Buffer}).
-
-
-getbits({0,Buffer},Num) when (Num rem 8) == 0 ->
- <<Bits:Num,Rest/binary>> = Buffer,
- {Bits,{0,Rest}};
-getbits({Used,Bin},Num) ->
- NumPlusUsed = Num + Used,
- NewUsed = NumPlusUsed rem 8,
- Unused = (8-NewUsed) rem 8,
- case Unused of
- 0 ->
- <<_:Used,Bits:Num,Rest/binary>> = Bin,
- {Bits,{0,Rest}};
- _ ->
- Bytes = NumPlusUsed div 8,
- <<_:Used,Bits:Num,_:Unused,_/binary>> = Bin,
- <<_:Bytes/binary,Rest/binary>> = Bin,
- {Bits,{NewUsed,Rest}}
- end;
-getbits(Bin,Num) when binary(Bin) ->
- getbits({0,Bin},Num).
-
-
-
-% getoctet(Bytes) when list(Bytes) ->
-% getoctet({0,Bytes});
-% getoctet(Bytes) ->
-% %% io:format("getoctet:Buffer = ~p~n",[Bytes]),
-% getoctet1(Bytes).
-
-% getoctet1({0,[H|T]}) ->
-% {H,{0,T}};
-% getoctet1({Pos,[_,H|T]}) ->
-% {H,{0,T}}.
-
-align({0,L}) ->
- {0,L};
-align({_Pos,<<_H,T/binary>>}) ->
- {0,T};
-align(Bytes) ->
- {0,Bytes}.
-
-%% First align buffer, then pick the first Num octets.
-%% Returns octets as an integer with bit significance as in buffer.
-getoctets({0,Buffer},Num) ->
- <<Val:Num/integer-unit:8,RestBin/binary>> = Buffer,
- {Val,{0,RestBin}};
-getoctets({U,<<_Padding,Rest/binary>>},Num) when U /= 0 ->
- getoctets({0,Rest},Num);
-getoctets(Buffer,Num) when binary(Buffer) ->
- getoctets({0,Buffer},Num).
-% getoctets(Buffer,Num) ->
-% %% io:format("getoctets:Buffer = ~p~nNum = ~p~n",[Buffer,Num]),
-% getoctets(Buffer,Num,0).
-
-% getoctets(Buffer,0,Acc) ->
-% {Acc,Buffer};
-% getoctets(Buffer,Num,Acc) ->
-% {Oct,NewBuffer} = getoctet(Buffer),
-% getoctets(NewBuffer,Num-1,(Acc bsl 8)+Oct).
-
-% getoctets_as_list(Buffer,Num) ->
-% getoctets_as_list(Buffer,Num,[]).
-
-% getoctets_as_list(Buffer,0,Acc) ->
-% {lists:reverse(Acc),Buffer};
-% getoctets_as_list(Buffer,Num,Acc) ->
-% {Oct,NewBuffer} = getoctet(Buffer),
-% getoctets_as_list(NewBuffer,Num-1,[Oct|Acc]).
-
-%% First align buffer, then pick the first Num octets.
-%% Returns octets as a binary
-getoctets_as_bin({0,Bin},Num)->
- <<Octets:Num/binary,RestBin/binary>> = Bin,
- {Octets,{0,RestBin}};
-getoctets_as_bin({_U,Bin},Num) ->
- <<_Padding,Octets:Num/binary,RestBin/binary>> = Bin,
- {Octets,{0,RestBin}};
-getoctets_as_bin(Bin,Num) when binary(Bin) ->
- getoctets_as_bin({0,Bin},Num).
-
-%% same as above but returns octets as a List
-getoctets_as_list(Buffer,Num) ->
- {Bin,Buffer2} = getoctets_as_bin(Buffer,Num),
- {binary_to_list(Bin),Buffer2}.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% set_choice(Alt,Choices,Altnum) -> ListofBitSettings
-%% Alt = atom()
-%% Altnum = integer() | {integer(),integer()}% number of alternatives
-%% Choices = [atom()] | {[atom()],[atom()]}
-%% When Choices is a tuple the first list is the Rootset and the
-%% second is the Extensions and then Altnum must also be a tuple with the
-%% lengths of the 2 lists
-%%
-set_choice(Alt,{L1,L2},{Len1,_Len2}) ->
- case set_choice_tag(Alt,L1) of
- N when integer(N), Len1 > 1 ->
-% [{bits,1,0}, % the value is in the root set
-% encode_constrained_number({0,Len1-1},N)];
- [0, % the value is in the root set
- encode_constrained_number({0,Len1-1},N)];
- N when integer(N) ->
-% [{bits,1,0}]; % no encoding if only 0 or 1 alternative
- [0]; % no encoding if only 0 or 1 alternative
- false ->
-% [{bits,1,1}, % extension value
- [1, % extension value
- case set_choice_tag(Alt,L2) of
- N2 when integer(N2) ->
- encode_small_number(N2);
- false ->
- unknown_choice_alt
- end]
- end;
-set_choice(Alt,L,Len) ->
- case set_choice_tag(Alt,L) of
- N when integer(N), Len > 1 ->
- encode_constrained_number({0,Len-1},N);
- N when integer(N) ->
- []; % no encoding if only 0 or 1 alternative
- false ->
- [unknown_choice_alt]
- end.
-
-set_choice_tag(Alt,Choices) ->
- set_choice_tag(Alt,Choices,0).
-
-set_choice_tag(Alt,[Alt|_Rest],Tag) ->
- Tag;
-set_choice_tag(Alt,[_H|Rest],Tag) ->
- set_choice_tag(Alt,Rest,Tag+1);
-set_choice_tag(_Alt,[],_Tag) ->
- false.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_fragmented_XXX; decode of values encoded fragmented according
-%% to ITU-T X.691 clause 10.9.3.8. The unit (XXX) is either bits, octets,
-%% characters or number of components (in a choice,sequence or similar).
-%% Buffer is a buffer {Used, Bin}.
-%% C is the constrained length.
-%% If the buffer is not aligned, this function does that.
-decode_fragmented_bits({0,Buffer},C) ->
- decode_fragmented_bits(Buffer,C,[]);
-decode_fragmented_bits({_N,<<_B,Bs/binary>>},C) ->
- decode_fragmented_bits(Bs,C,[]).
-
-decode_fragmented_bits(<<3:2,Len:6,Bin/binary>>,C,Acc) ->
- {Value,Bin2} = split_binary(Bin, Len * ?'16K'),
- decode_fragmented_bits(Bin2,C,[Value,Acc]);
-decode_fragmented_bits(<<0:1,0:7,Bin/binary>>,C,Acc) ->
- BinBits = list_to_binary(lists:reverse(Acc)),
- case C of
- Int when integer(Int),C == size(BinBits) ->
- {BinBits,{0,Bin}};
- Int when integer(Int) ->
- exit({error,{asn1,{illegal_value,C,BinBits}}});
- _ ->
- {BinBits,{0,Bin}}
- end;
-decode_fragmented_bits(<<0:1,Len:7,Bin/binary>>,C,Acc) ->
- Result = {BinBits,{Used,_Rest}} =
- case (Len rem 8) of
- 0 ->
- <<Value:Len/binary-unit:1,Bin2/binary>> = Bin,
- {list_to_binary(lists:reverse([Value|Acc])),{0,Bin2}};
- Rem ->
- Bytes = Len div 8,
- U = 8 - Rem,
- <<Value:Bytes/binary-unit:8,Bits1:Rem,Bits2:U,Bin2/binary>> = Bin,
- {list_to_binary(lists:reverse([Bits1 bsl U,Value|Acc])),
- {Rem,<<Bits2,Bin2/binary>>}}
- end,
- case C of
- Int when integer(Int),C == (size(BinBits) - ((8 - Used) rem 8)) ->
- Result;
- Int when integer(Int) ->
- exit({error,{asn1,{illegal_value,C,BinBits}}});
- _ ->
- Result
- end.
-
-
-decode_fragmented_octets({0,Bin},C) ->
- decode_fragmented_octets(Bin,C,[]);
-decode_fragmented_octets({_N,<<_B,Bs/binary>>},C) ->
- decode_fragmented_octets(Bs,C,[]).
-
-decode_fragmented_octets(<<3:2,Len:6,Bin/binary>>,C,Acc) ->
- {Value,Bin2} = split_binary(Bin,Len * ?'16K'),
- decode_fragmented_octets(Bin2,C,[Value,Acc]);
-decode_fragmented_octets(<<0:1,0:7,Bin/binary>>,C,Acc) ->
- Octets = list_to_binary(lists:reverse(Acc)),
- case C of
- Int when integer(Int), C == size(Octets) ->
- {Octets,{0,Bin}};
- Int when integer(Int) ->
- exit({error,{asn1,{illegal_value,C,Octets}}});
- _ ->
- {Octets,{0,Bin}}
- end;
-decode_fragmented_octets(<<0:1,Len:7,Bin/binary>>,C,Acc) ->
- <<Value:Len/binary-unit:8,Bin2/binary>> = Bin,
- BinOctets = list_to_binary(lists:reverse([Value|Acc])),
- case C of
- Int when integer(Int),size(BinOctets) == Int ->
- {BinOctets,Bin2};
- Int when integer(Int) ->
- exit({error,{asn1,{illegal_value,C,BinOctets}}});
- _ ->
- {BinOctets,Bin2}
- end.
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_open_type(Constraint, Value) -> CompleteList
-%% Value = list of bytes of an already encoded value (the list must be flat)
-%% | binary
-%% Contraint = not used in this version
-%%
-encode_open_type(_Constraint, Val) when list(Val) ->
- Bin = list_to_binary(Val),
- case size(Bin) of
- Size when Size>255 ->
- [encode_length(undefined,Size),[21,<<Size:16>>,Bin]];
- Size ->
- [encode_length(undefined,Size),[20,Size,Bin]]
- end;
-% [encode_length(undefined,size(Bin)),{octets,Bin}]; % octets implies align
-encode_open_type(_Constraint, Val) when binary(Val) ->
-% [encode_length(undefined,size(Val)),{octets,Val}]. % octets implies align
- case size(Val) of
- Size when Size>255 ->
- [encode_length(undefined,size(Val)),[21,<<Size:16>>,Val]]; % octets implies align
- Size ->
- [encode_length(undefined,Size),[20,Size,Val]]
- end.
-%% the binary_to_list is not optimal but compatible with the current solution
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_open_type(Buffer,Constraint) -> Value
-%% Constraint is not used in this version
-%% Buffer = [byte] with PER encoded data
-%% Value = [byte] with decoded data (which must be decoded again as some type)
-%%
-decode_open_type(Bytes, _Constraint) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- getoctets_as_bin(Bytes2,Len).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_integer(Constraint,Value,NamedNumberList) -> CompleteList
-%% encode_integer(Constraint,Value) -> CompleteList
-%% encode_integer(Constraint,{Name,Value}) -> CompleteList
-%%
-%%
-encode_integer(C,V,NamedNumberList) when atom(V) ->
- case lists:keysearch(V,1,NamedNumberList) of
- {value,{_,NewV}} ->
- encode_integer(C,NewV);
- _ ->
- exit({error,{asn1,{namednumber,V}}})
- end;
-encode_integer(C,V,_NamedNumberList) when integer(V) ->
- encode_integer(C,V);
-encode_integer(C,{Name,V},NamedNumberList) when atom(Name) ->
- encode_integer(C,V,NamedNumberList).
-
-encode_integer(C,{Name,Val}) when atom(Name) ->
- encode_integer(C,Val);
-
-encode_integer([{Rc,_Ec}],Val) when tuple(Rc) -> % XXX when is this invoked? First argument most often a list,...Ok this is the extension case...but it doesn't work.
- case (catch encode_integer([Rc],Val)) of
- {'EXIT',{error,{asn1,_}}} ->
-% [{bits,1,1},encode_unconstrained_number(Val)];
- [1,encode_unconstrained_number(Val)];
- Encoded ->
-% [{bits,1,0},Encoded]
- [0,Encoded]
- end;
-
-encode_integer([],Val) ->
- encode_unconstrained_number(Val);
-%% The constraint is the effective constraint, and in this case is a number
-encode_integer([{'SingleValue',V}],V) ->
- [];
-encode_integer([{'ValueRange',VR={Lb,Ub},Range,PreEnc}],Val) when Val >= Lb,
- Ub >= Val ->
- %% this case when NamedNumberList
- encode_constrained_number(VR,Range,PreEnc,Val);
-encode_integer([{'ValueRange',{Lb,'MAX'}}],Val) ->
- encode_semi_constrained_number(Lb,Val);
-encode_integer([{'ValueRange',{'MIN',_}}],Val) ->
- encode_unconstrained_number(Val);
-encode_integer([{'ValueRange',VR={_Lb,_Ub}}],Val) ->
- encode_constrained_number(VR,Val);
-encode_integer(_,Val) ->
- exit({error,{asn1,{illegal_value,Val}}}).
-
-
-
-decode_integer(Buffer,Range,NamedNumberList) ->
- {Val,Buffer2} = decode_integer(Buffer,Range),
- case lists:keysearch(Val,2,NamedNumberList) of
- {value,{NewVal,_}} -> {NewVal,Buffer2};
- _ -> {Val,Buffer2}
- end.
-
-decode_integer(Buffer,[{Rc,_Ec}]) when tuple(Rc) ->
- {Ext,Buffer2} = getext(Buffer),
- case Ext of
- 0 -> decode_integer(Buffer2,[Rc]);
- 1 -> decode_unconstrained_number(Buffer2)
- end;
-decode_integer(Buffer,undefined) ->
- decode_unconstrained_number(Buffer);
-decode_integer(Buffer,C) ->
- case get_constraint(C,'SingleValue') of
- V when integer(V) ->
- {V,Buffer};
- _ ->
- decode_integer1(Buffer,C)
- end.
-
-decode_integer1(Buffer,C) ->
- case VR = get_constraint(C,'ValueRange') of
- no ->
- decode_unconstrained_number(Buffer);
- {Lb, 'MAX'} ->
- decode_semi_constrained_number(Buffer,Lb);
- {_Lb,_Ub} ->
- decode_constrained_number(Buffer,VR)
- end.
-
-%% X.691:10.6 Encoding of a normally small non-negative whole number
-%% Use this for encoding of CHOICE index if there is an extension marker in
-%% the CHOICE
-encode_small_number({Name,Val}) when atom(Name) ->
- encode_small_number(Val);
-encode_small_number(Val) when Val =< 63 ->
-% [{bits,1,0},{bits,6,Val}];
-% [{bits,7,Val}]; % same as above but more efficient
- [10,7,Val]; % same as above but more efficient
-encode_small_number(Val) ->
-% [{bits,1,1},encode_semi_constrained_number(0,Val)].
- [1,encode_semi_constrained_number(0,Val)].
-
-decode_small_number(Bytes) ->
- {Bit,Bytes2} = getbit(Bytes),
- case Bit of
- 0 ->
- getbits(Bytes2,6);
- 1 ->
- decode_semi_constrained_number(Bytes2,0)
- end.
-
-%% X.691:10.7 Encoding of a semi-constrained whole number
-%% might be an optimization encode_semi_constrained_number(0,Val) ->
-encode_semi_constrained_number(C,{Name,Val}) when atom(Name) ->
- encode_semi_constrained_number(C,Val);
-encode_semi_constrained_number({Lb,'MAX'},Val) ->
- encode_semi_constrained_number(Lb,Val);
-encode_semi_constrained_number(Lb,Val) ->
- Val2 = Val - Lb,
- Oct = eint_positive(Val2),
- Len = length(Oct),
- if
- Len < 128 ->
- %{octets,[Len|Oct]}; % equiv with encode_length(undefined,Len) but faster
- [20,Len+1,[Len|Oct]];
- Len < 256 ->
- [encode_length(undefined,Len),[20,Len,Oct]];
- true ->
- [encode_length(undefined,Len),[21,<<Len:16>>,Oct]]
- end.
-
-decode_semi_constrained_number(Bytes,{Lb,_}) ->
- decode_semi_constrained_number(Bytes,Lb);
-decode_semi_constrained_number(Bytes,Lb) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {V,Bytes3} = getoctets(Bytes2,Len),
- {V+Lb,Bytes3}.
-
-encode_constrained_number({Lb,_Ub},_Range,{bits,N},Val) ->
- Val2 = Val-Lb,
-% {bits,N,Val2};
- [10,N,Val2];
-encode_constrained_number({Lb,_Ub},_Range,{octets,N},Val) when N < 256->
- %% N is 8 or 16 (1 or 2 octets)
- Val2 = Val-Lb,
-% {octets,<<Val2:N/unit:8>>};
- [20,N,Val2];
-encode_constrained_number({Lb,_Ub},_Range,{octets,N},Val) -> % N>255
- %% N is 8 or 16 (1 or 2 octets)
- Val2 = Val-Lb,
-% {octets,<<Val2:N/unit:8>>};
- [21,<<N:16>>,Val2];
-encode_constrained_number({Lb,_Ub},Range,_,Val) ->
- Val2 = Val-Lb,
- if
- Range =< 16#1000000 -> % max 3 octets
- Octs = eint_positive(Val2),
-% [encode_length({1,3},size(Octs)),{octets,Octs}];
- L = length(Octs),
- [encode_length({1,3},L),[20,L,Octs]];
- Range =< 16#100000000 -> % max 4 octets
- Octs = eint_positive(Val2),
-% [encode_length({1,4},size(Octs)),{octets,Octs}];
- L = length(Octs),
- [encode_length({1,4},L),[20,L,Octs]];
- Range =< 16#10000000000 -> % max 5 octets
- Octs = eint_positive(Val2),
-% [encode_length({1,5},size(Octs)),{octets,Octs}];
- L = length(Octs),
- [encode_length({1,5},L),[20,L,Octs]];
- true ->
- exit({not_supported,{integer_range,Range}})
- end.
-
-encode_constrained_number(Range,{Name,Val}) when atom(Name) ->
- encode_constrained_number(Range,Val);
-encode_constrained_number({Lb,Ub},Val) when Val >= Lb, Ub >= Val ->
- Range = Ub - Lb + 1,
- Val2 = Val - Lb,
- if
- Range == 2 ->
-% Size = {bits,1,Val2};
- [Val2];
- Range =< 4 ->
-% Size = {bits,2,Val2};
- [10,2,Val2];
- Range =< 8 ->
- [10,3,Val2];
- Range =< 16 ->
- [10,4,Val2];
- Range =< 32 ->
- [10,5,Val2];
- Range =< 64 ->
- [10,6,Val2];
- Range =< 128 ->
- [10,7,Val2];
- Range =< 255 ->
- [10,8,Val2];
- Range =< 256 ->
-% Size = {octets,[Val2]};
- [20,1,Val2];
- Range =< 65536 ->
-% Size = {octets,<<Val2:16>>};
- [20,2,<<Val2:16>>];
- Range =< 16#1000000 ->
- Octs = eint_positive(Val2),
-% [{bits,2,length(Octs)-1},{octets,Octs}];
- Len = length(Octs),
- [10,2,Len-1,20,Len,Octs];
- Range =< 16#100000000 ->
- Octs = eint_positive(Val2),
- Len = length(Octs),
- [10,2,Len-1,20,Len,Octs];
- Range =< 16#10000000000 ->
- Octs = eint_positive(Val2),
- Len = length(Octs),
- [10,3,Len-1,20,Len,Octs];
- true ->
- exit({not_supported,{integer_range,Range}})
- end;
-encode_constrained_number({_,_},Val) ->
- exit({error,{asn1,{illegal_value,Val}}}).
-
-decode_constrained_number(Buffer,VR={Lb,Ub}) ->
- Range = Ub - Lb + 1,
- decode_constrained_number(Buffer,VR,Range).
-
-decode_constrained_number(Buffer,{Lb,_Ub},_Range,{bits,N}) ->
- {Val,Remain} = getbits(Buffer,N),
- {Val+Lb,Remain};
-decode_constrained_number(Buffer,{Lb,_Ub},_Range,{octets,N}) ->
- {Val,Remain} = getoctets(Buffer,N),
- {Val+Lb,Remain}.
-
-decode_constrained_number(Buffer,{Lb,_Ub},Range) ->
- % Val2 = Val - Lb,
- {Val,Remain} =
- if
- Range == 2 ->
- getbits(Buffer,1);
- Range =< 4 ->
- getbits(Buffer,2);
- Range =< 8 ->
- getbits(Buffer,3);
- Range =< 16 ->
- getbits(Buffer,4);
- Range =< 32 ->
- getbits(Buffer,5);
- Range =< 64 ->
- getbits(Buffer,6);
- Range =< 128 ->
- getbits(Buffer,7);
- Range =< 255 ->
- getbits(Buffer,8);
- Range =< 256 ->
- getoctets(Buffer,1);
- Range =< 65536 ->
- getoctets(Buffer,2);
- Range =< 16#1000000 ->
- {Len,Bytes2} = decode_length(Buffer,{1,3}),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- {dec_pos_integer(Octs),Bytes3};
- Range =< 16#100000000 ->
- {Len,Bytes2} = decode_length(Buffer,{1,4}),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- {dec_pos_integer(Octs),Bytes3};
- Range =< 16#10000000000 ->
- {Len,Bytes2} = decode_length(Buffer,{1,5}),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- {dec_pos_integer(Octs),Bytes3};
- true ->
- exit({not_supported,{integer_range,Range}})
- end,
- {Val+Lb,Remain}.
-
-%% X.691:10.8 Encoding of an unconstrained whole number
-
-encode_unconstrained_number(Val) when Val >= 0 ->
- Oct = eint(Val,[]),
- Len = length(Oct),
- if
- Len < 128 ->
- %{octets,[Len|Oct]}; % equiv with encode_length(undefined,Len) but faster
- [20,Len+1,[Len|Oct]];
- Len < 256 ->
-% [encode_length(undefined,Len),20,Len,Oct];
- [20,Len+2,<<2:2,Len:14>>,Oct];% equiv with encode_length(undefined,Len) but faster
- true ->
-% [encode_length(undefined,Len),{octets,Oct}]
- [encode_length(undefined,Len),[21,<<Len:16>>,Oct]]
- end;
-encode_unconstrained_number(Val) -> % negative
- Oct = enint(Val,[]),
- Len = length(Oct),
- if
- Len < 128 ->
-% {octets,[Len|Oct]}; % equiv with encode_length(undefined,Len) but faster
- [20,Len+1,[Len|Oct]];% equiv with encode_length(undefined,Len) but faster
- Len < 256 ->
-% [encode_length(undefined,Len),20,Len,Oct];
- [20,Len+2,<<2:2,Len:14>>,Oct];% equiv with encode_length(undefined,Len) but faster
- true ->
- %[encode_length(undefined,Len),{octets,Oct}]
- [encode_length(undefined,Len),[21,<<Len:16>>,Oct]]
- end.
-
-
-%% used for positive Values which don't need a sign bit
-%% returns a list
-eint_positive(Val) ->
- case eint(Val,[]) of
- [0,B1|T] ->
- [B1|T];
- T ->
- T
- end.
-
-
-eint(0, [B|Acc]) when B < 128 ->
- [B|Acc];
-eint(N, Acc) ->
- eint(N bsr 8, [N band 16#ff| Acc]).
-
-enint(-1, [B1|T]) when B1 > 127 ->
- [B1|T];
-enint(N, Acc) ->
- enint(N bsr 8, [N band 16#ff|Acc]).
-
-decode_unconstrained_number(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {Ints,Bytes3} = getoctets_as_list(Bytes2,Len),
- {dec_integer(Ints),Bytes3}.
-
-dec_pos_integer(Ints) ->
- decpint(Ints, 8 * (length(Ints) - 1)).
-dec_integer(Ints) when hd(Ints) band 255 =< 127 -> %% Positive number
- decpint(Ints, 8 * (length(Ints) - 1));
-dec_integer(Ints) -> %% Negative
- decnint(Ints, 8 * (length(Ints) - 1)).
-
-decpint([Byte|Tail], Shift) ->
- (Byte bsl Shift) bor decpint(Tail, Shift-8);
-decpint([], _) -> 0.
-
-decnint([Byte|Tail], Shift) ->
- (-128 + (Byte band 127) bsl Shift) bor decpint(Tail, Shift-8).
-
-% minimum_octets(Val) ->
-% minimum_octets(Val,[]).
-
-% minimum_octets(Val,Acc) when Val > 0 ->
-% minimum_octets((Val bsr 8),[Val band 16#FF|Acc]);
-% minimum_octets(0,Acc) ->
-% Acc.
-
-
-%% X.691:10.9 Encoding of a length determinant
-%%encode_small_length(undefined,Len) -> % null means no UpperBound
-%% encode_small_number(Len).
-
-%% X.691:10.9.3.5
-%% X.691:10.9.3.7
-encode_length(undefined,Len) -> % un-constrained
- if
- Len < 128 ->
-% {octets,[Len]};
- [20,1,Len];
- Len < 16384 ->
- %{octets,<<2:2,Len:14>>};
- [20,2,<<2:2,Len:14>>];
- true -> % should be able to endode length >= 16384 i.e. fragmented length
- exit({error,{asn1,{encode_length,{nyi,above_16k}}}})
- end;
-
-encode_length({0,'MAX'},Len) ->
- encode_length(undefined,Len);
-encode_length(Vr={Lb,Ub},Len) when Ub =< 65535 ,Lb >= 0 -> % constrained
- encode_constrained_number(Vr,Len);
-encode_length({Lb,_Ub},Len) when integer(Lb), Lb >= 0 -> % Ub > 65535
- encode_length(undefined,Len);
-encode_length({Vr={Lb,Ub},[]},Len) when Ub =< 65535 ,Lb >= 0,Len=<Ub ->
- %% constrained extensible
-% [{bits,1,0},encode_constrained_number(Vr,Len)];
- [0,encode_constrained_number(Vr,Len)];
-encode_length({{Lb,_},[]},Len) ->
- [1,encode_semi_constrained_number(Lb,Len)];
-encode_length(SingleValue,_Len) when integer(SingleValue) ->
- [].
-
-%% X.691 10.9.3.4 (only used for length of bitmap that prefixes extension
-%% additions in a sequence or set
-encode_small_length(Len) when Len =< 64 ->
-%% [{bits,1,0},{bits,6,Len-1}];
-% {bits,7,Len-1}; % the same as above but more efficient
- [10,7,Len-1];
-encode_small_length(Len) ->
-% [{bits,1,1},encode_length(undefined,Len)].
- [1,encode_length(undefined,Len)].
-
-% decode_small_length({Used,<<_:Used,0:1,Num:6,_:((8-Used+1) rem 8),Rest/binary>>}) ->
-% case Buffer of
-% <<_:Used,0:1,Num:6,_:((8-Used+1) rem 8),Rest/binary>> ->
-% {Num,
-% case getbit(Buffer) of
-% {0,Remain} ->
-% {Bits,Remain2} = getbits(Remain,6),
-% {Bits+1,Remain2};
-% {1,Remain} ->
-% decode_length(Remain,undefined)
-% end.
-
-decode_small_length(Buffer) ->
- case getbit(Buffer) of
- {0,Remain} ->
- {Bits,Remain2} = getbits(Remain,6),
- {Bits+1,Remain2};
- {1,Remain} ->
- decode_length(Remain,undefined)
- end.
-
-decode_length(Buffer) ->
- decode_length(Buffer,undefined).
-
-decode_length(Buffer,undefined) -> % un-constrained
- {0,Buffer2} = align(Buffer),
- case Buffer2 of
- <<0:1,Oct:7,Rest/binary>> ->
- {Oct,{0,Rest}};
- <<2:2,Val:14,Rest/binary>> ->
- {Val,{0,Rest}};
- <<3:2,_Val:14,_Rest/binary>> ->
- %% this case should be fixed
- exit({error,{asn1,{decode_length,{nyi,above_16k}}}})
- end;
-%% {Bits,_} = getbits(Buffer2,2),
-% case Bits of
-% 2 ->
-% {Val,Bytes3} = getoctets(Buffer2,2),
-% {(Val band 16#3FFF),Bytes3};
-% 3 ->
-% exit({error,{asn1,{decode_length,{nyi,above_16k}}}});
-% _ ->
-% {Val,Bytes3} = getoctet(Buffer2),
-% {Val band 16#7F,Bytes3}
-% end;
-
-decode_length(Buffer,{Lb,Ub}) when Ub =< 65535 ,Lb >= 0 -> % constrained
- decode_constrained_number(Buffer,{Lb,Ub});
-decode_length(_Buffer,{Lb,_Ub}) when integer(Lb), Lb >= 0 -> % Ub > 65535
- exit({error,{asn1,{decode_length,{nyi,above_64K}}}});
-decode_length(Buffer,{{Lb,Ub},[]}) ->
- case getbit(Buffer) of
- {0,Buffer2} ->
- decode_length(Buffer2, {Lb,Ub})
- end;
-
-
-%When does this case occur with {_,_Lb,Ub} ??
-% X.691:10.9.3.5
-decode_length({Used,Bin},{_,_Lb,_Ub}) -> %when Len =< 127 -> % Unconstrained or large Ub NOTE! this case does not cover case when Ub > 65535
- Unused = (8-Used) rem 8,
- case Bin of
- <<_:Used,0:1,Val:7,R:Unused,Rest/binary>> ->
- {Val,{Used,<<R,Rest/binary>>}};
- <<_:Used,_:Unused,2:2,Val:14,Rest/binary>> ->
- {Val, {0,Rest}};
- <<_:Used,_:Unused,3:2,_:14,_Rest/binary>> ->
- exit({error,{asn1,{decode_length,{nyi,length_above_64K}}}})
- end;
-% decode_length(Buffer,{_,_Lb,Ub}) -> %when Len =< 127 -> % Unconstrained or large Ub
-% case getbit(Buffer) of
-% {0,Remain} ->
-% getbits(Remain,7);
-% {1,Remain} ->
-% {Val,Remain2} = getoctets(Buffer,2),
-% {Val band 2#0111111111111111, Remain2}
-% end;
-decode_length(Buffer,SingleValue) when integer(SingleValue) ->
- {SingleValue,Buffer}.
-
-
- % X.691:11
-decode_boolean(Buffer) -> %when record(Buffer,buffer)
- case getbit(Buffer) of
- {1,Remain} -> {true,Remain};
- {0,Remain} -> {false,Remain}
- end.
-
-
-%% ENUMERATED with extension marker
-decode_enumerated(Buffer,C,{Ntup1,Ntup2}) when tuple(Ntup1), tuple(Ntup2) ->
- {Ext,Buffer2} = getext(Buffer),
- case Ext of
- 0 -> % not an extension value
- {Val,Buffer3} = decode_integer(Buffer2,C),
- case catch (element(Val+1,Ntup1)) of
- NewVal when atom(NewVal) -> {NewVal,Buffer3};
- _Error -> exit({error,{asn1,{decode_enumerated,{Val,[Ntup1,Ntup2]}}}})
- end;
- 1 -> % this an extension value
- {Val,Buffer3} = decode_small_number(Buffer2),
- case catch (element(Val+1,Ntup2)) of
- NewVal when atom(NewVal) -> {NewVal,Buffer3};
- _ -> {{asn1_enum,Val},Buffer3}
- end
- end;
-
-decode_enumerated(Buffer,C,NamedNumberTup) when tuple(NamedNumberTup) ->
- {Val,Buffer2} = decode_integer(Buffer,C),
- case catch (element(Val+1,NamedNumberTup)) of
- NewVal when atom(NewVal) -> {NewVal,Buffer2};
- _Error -> exit({error,{asn1,{decode_enumerated,{Val,NamedNumberTup}}}})
- end.
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Bitstring value, ITU_T X.690 Chapter 8.5
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-%%===============================================================================
-%% encode bitstring value
-%%===============================================================================
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% bitstring NamedBitList
-%% Val can be of:
-%% - [identifiers] where only named identifers are set to one,
-%% the Constraint must then have some information of the
-%% bitlength.
-%% - [list of ones and zeroes] all bits
-%% - integer value representing the bitlist
-%% C is constraint Len, only valid when identifiers
-
-
-%% when the value is a list of {Unused,BinBits}, where
-%% Unused = integer(),
-%% BinBits = binary().
-
-encode_bit_string(C,Bin={Unused,BinBits},NamedBitList) when integer(Unused),
- binary(BinBits) ->
- encode_bin_bit_string(C,Bin,NamedBitList);
-
-%% when the value is a list of named bits
-
-encode_bit_string(C, LoNB=[FirstVal | _RestVal], NamedBitList) when atom(FirstVal) ->
- ToSetPos = get_all_bitposes(LoNB, NamedBitList, []),
- BitList = make_and_set_list(ToSetPos,0),
- encode_bit_string(C,BitList,NamedBitList);% consider the constraint
-
-encode_bit_string(C, BL=[{bit,_} | _RestVal], NamedBitList) ->
- ToSetPos = get_all_bitposes(BL, NamedBitList, []),
- BitList = make_and_set_list(ToSetPos,0),
- encode_bit_string(C,BitList,NamedBitList);
-
-%% when the value is a list of ones and zeroes
-encode_bit_string(Int, BitListValue, _)
- when list(BitListValue),integer(Int) ->
- %% The type is constrained by a single value size constraint
- [40,Int,length(BitListValue),BitListValue];
-% encode_bit_string(C, BitListValue,NamedBitList)
-% when list(BitListValue) ->
-% [encode_bit_str_length(C,BitListValue),
-% 2,45,BitListValue];
-encode_bit_string(no, BitListValue,[])
- when list(BitListValue) ->
- [encode_length(undefined,length(BitListValue)),
- 2,BitListValue];
-encode_bit_string(C, BitListValue,[])
- when list(BitListValue) ->
- [encode_length(C,length(BitListValue)),
- 2,BitListValue];
-encode_bit_string(no, BitListValue,_NamedBitList)
- when list(BitListValue) ->
- %% this case with an unconstrained BIT STRING can be made more efficient
- %% if the complete driver can take a special code so the length field
- %% is encoded there.
- NewBitLVal = lists:reverse(lists:dropwhile(fun(0)->true;(1)->false end,
- lists:reverse(BitListValue))),
- [encode_length(undefined,length(NewBitLVal)),
- 2,NewBitLVal];
-encode_bit_string(C,BitListValue,_NamedBitList)
- when list(BitListValue) ->% C = {_,'MAX'}
-% NewBitLVal = lists:reverse(lists:dropwhile(fun(0)->true;(1)->false end,
-% lists:reverse(BitListValue))),
- NewBitLVal = bit_string_trailing_zeros(BitListValue,C),
- [encode_length(C,length(NewBitLVal)),
- 2,NewBitLVal];
-
-% encode_bit_string(C, BitListValue, NamedBitList) when list(BitListValue) ->
-% BitListToBinary =
-% %% fun that transforms a list of 1 and 0 to a tuple:
-% %% {UnusedBitsInLastByte, Binary}
-% fun([H|T],Acc,N,Fun) ->
-% Fun(T,(Acc bsl 1)+H,N+1,Fun);
-% ([],Acc,N,_) -> % length fits in one byte
-% Unused = (8 - (N rem 8)) rem 8,
-% % case N/8 of
-% % _Len =< 255 ->
-% % [30,Unused,(Unused+N)/8,<<Acc:N,0:Unused>>];
-% % _Len ->
-% % Len = (Unused+N)/8,
-% % [31,Unused,<<Len:16>>,<<Acc:N,0:Unused>>]
-% % end
-% {Unused,<<Acc:N,0:Unused>>}
-% end,
-% UnusedAndBin =
-% case NamedBitList of
-% [] -> % dont remove trailing zeroes
-% BitListToBinary(BitListValue,0,0,BitListToBinary);
-% _ ->
-% BitListToBinary(lists:reverse(
-% lists:dropwhile(fun(0)->true;(1)->false end,
-% lists:reverse(BitListValue))),
-% 0,0,BitListToBinary)
-% end,
-% encode_bin_bit_string(C,UnusedAndBin,NamedBitList);
-
-%% when the value is an integer
-encode_bit_string(C, IntegerVal, NamedBitList) when integer(IntegerVal)->
- BitList = int_to_bitlist(IntegerVal),
- encode_bit_string(C,BitList,NamedBitList);
-
-%% when the value is a tuple
-encode_bit_string(C,{Name,Val}, NamedBitList) when atom(Name) ->
- encode_bit_string(C,Val,NamedBitList).
-
-bit_string_trailing_zeros(BitList,C) when integer(C) ->
- bit_string_trailing_zeros1(BitList,C,C);
-bit_string_trailing_zeros(BitList,{Lb,Ub}) when integer(Lb) ->
- bit_string_trailing_zeros1(BitList,Lb,Ub);
-bit_string_trailing_zeros(BitList,{{Lb,Ub},_}) when integer(Lb) ->
- bit_string_trailing_zeros1(BitList,Lb,Ub);
-bit_string_trailing_zeros(BitList,_) ->
- BitList.
-
-bit_string_trailing_zeros1(BitList,Lb,Ub) ->
- case length(BitList) of
- Lb -> BitList;
- B when B<Lb -> BitList++lists:duplicate(Lb-B,0);
- D -> F = fun(L,LB,LB,_,_)->lists:reverse(L);
- ([0|R],L1,LB,UB,Fun)->Fun(R,L1-1,LB,UB,Fun);
- (L,L1,_,UB,_)when L1 =< UB -> lists:reverse(L);
- (_,_L1,_,_,_) ->exit({error,{list_length_BIT_STRING,
- BitList}}) end,
- F(lists:reverse(BitList),D,Lb,Ub,F)
- end.
-
-%% encode_bin_bit_string/3, when value is a tuple of Unused and BinBits.
-%% Unused = integer(),i.e. number unused bits in least sign. byte of
-%% BinBits = binary().
-encode_bin_bit_string(C,{_,BinBits},_NamedBitList)
- when integer(C),C=<16 ->
- [45,C,size(BinBits),BinBits];
-encode_bin_bit_string(C,{_Unused,BinBits},_NamedBitList)
- when integer(C) ->
- [2,45,C,size(BinBits),BinBits];
-encode_bin_bit_string(C,UnusedAndBin={_,_},NamedBitList) ->
-% UnusedAndBin1 = {Unused1,Bin1} =
- {Unused1,Bin1} =
- %% removes all trailing bits if NamedBitList is not empty
- remove_trailing_bin(NamedBitList,UnusedAndBin),
- case C of
-% case get_constraint(C,'SizeConstraint') of
-
-% 0 ->
-% []; % borde avg�ras i compile-time
-% V when integer(V),V=<16 ->
-% {Unused2,Bin2} = pad_list(V,UnusedAndBin1),
-% <<BitVal:V,_:Unused2>> = Bin2,
-% % {bits,V,BitVal};
-% [10,V,BitVal];
-% V when integer(V) ->
-% %[align, pad_list(V, UnusedAndBin1)];
-% {Unused2,Bin2} = pad_list(V, UnusedAndBin1),
-% <<BitVal:V,_:Unused2>> = Bin2,
-% [2,octets_unused_to_complete(Unused2,size(Bin2),Bin2)];
-
- {Lb,Ub} when integer(Lb),integer(Ub) ->
-% [encode_length({Lb,Ub},size(Bin1)*8 - Unused1),
-% align,UnusedAndBin1];
- Size=size(Bin1),
- [encode_length({Lb,Ub},Size*8 - Unused1),
- 2,octets_unused_to_complete(Unused1,Size,Bin1)];
- no ->
- Size=size(Bin1),
- [encode_length(undefined,Size*8 - Unused1),
- 2,octets_unused_to_complete(Unused1,Size,Bin1)];
- Sc ->
- Size=size(Bin1),
- [encode_length(Sc,Size*8 - Unused1),
- 2,octets_unused_to_complete(Unused1,Size,Bin1)]
- end.
-
-remove_trailing_bin([], {Unused,Bin}) ->
- {Unused,Bin};
-remove_trailing_bin(NamedNumberList, {_Unused,Bin}) ->
- Size = size(Bin)-1,
- <<Bfront:Size/binary, LastByte:8>> = Bin,
- %% clear the Unused bits to be sure
-% LastByte1 = LastByte band (((1 bsl Unused) -1) bxor 255),% why this???
- Unused1 = trailingZeroesInNibble(LastByte band 15),
- Unused2 =
- case Unused1 of
- 4 ->
- 4 + trailingZeroesInNibble(LastByte bsr 4);
- _ -> Unused1
- end,
- case Unused2 of
- 8 ->
- remove_trailing_bin(NamedNumberList,{0,Bfront});
- _ ->
- {Unused2,Bin}
- end.
-
-
-trailingZeroesInNibble(0) ->
- 4;
-trailingZeroesInNibble(1) ->
- 0;
-trailingZeroesInNibble(2) ->
- 1;
-trailingZeroesInNibble(3) ->
- 0;
-trailingZeroesInNibble(4) ->
- 2;
-trailingZeroesInNibble(5) ->
- 0;
-trailingZeroesInNibble(6) ->
- 1;
-trailingZeroesInNibble(7) ->
- 0;
-trailingZeroesInNibble(8) ->
- 3;
-trailingZeroesInNibble(9) ->
- 0;
-trailingZeroesInNibble(10) ->
- 1;
-trailingZeroesInNibble(11) ->
- 0;
-trailingZeroesInNibble(12) -> %#1100
- 2;
-trailingZeroesInNibble(13) ->
- 0;
-trailingZeroesInNibble(14) ->
- 1;
-trailingZeroesInNibble(15) ->
- 0.
-
-%%%%%%%%%%%%%%%
-%% The result is presented as a list of named bits (if possible)
-%% else as a tuple {Unused,Bits}. Unused is the number of unused
-%% bits, least significant bits in the last byte of Bits. Bits is
-%% the BIT STRING represented as a binary.
-%%
-decode_compact_bit_string(Buffer, C, NamedNumberList) ->
- case get_constraint(C,'SizeConstraint') of
- 0 -> % fixed length
- {{8,0},Buffer};
- V when integer(V),V=<16 -> %fixed length 16 bits or less
- compact_bit_string(Buffer,V,NamedNumberList);
- V when integer(V),V=<65536 -> %fixed length > 16 bits
- Bytes2 = align(Buffer),
- compact_bit_string(Bytes2,V,NamedNumberList);
- V when integer(V) -> % V > 65536 => fragmented value
- {Bin,Buffer2} = decode_fragmented_bits(Buffer,V),
- case Buffer2 of
- {0,_} -> {{0,Bin},Buffer2};
- {U,_} -> {{8-U,Bin},Buffer2}
- end;
- {Lb,Ub} when integer(Lb),integer(Ub) ->
- %% This case may demand decoding of fragmented length/value
- {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
- Bytes3 = align(Bytes2),
- compact_bit_string(Bytes3,Len,NamedNumberList);
- no ->
- %% This case may demand decoding of fragmented length/value
- {Len,Bytes2} = decode_length(Buffer,undefined),
- Bytes3 = align(Bytes2),
- compact_bit_string(Bytes3,Len,NamedNumberList);
- Sc ->
- {Len,Bytes2} = decode_length(Buffer,Sc),
- Bytes3 = align(Bytes2),
- compact_bit_string(Bytes3,Len,NamedNumberList)
- end.
-
-
-%%%%%%%%%%%%%%%
-%% The result is presented as a list of named bits (if possible)
-%% else as a list of 0 and 1.
-%%
-decode_bit_string(Buffer, C, NamedNumberList) ->
- case get_constraint(C,'SizeConstraint') of
- {Lb,Ub} when integer(Lb),integer(Ub) ->
- {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
- Bytes3 = align(Bytes2),
- bit_list_or_named(Bytes3,Len,NamedNumberList);
- no ->
- {Len,Bytes2} = decode_length(Buffer,undefined),
- Bytes3 = align(Bytes2),
- bit_list_or_named(Bytes3,Len,NamedNumberList);
- 0 -> % fixed length
- {[],Buffer}; % nothing to encode
- V when integer(V),V=<16 -> % fixed length 16 bits or less
- bit_list_or_named(Buffer,V,NamedNumberList);
- V when integer(V),V=<65536 ->
- Bytes2 = align(Buffer),
- bit_list_or_named(Bytes2,V,NamedNumberList);
- V when integer(V) ->
- Bytes2 = align(Buffer),
- {BinBits,_Bytes3} = decode_fragmented_bits(Bytes2,V),
- bit_list_or_named(BinBits,V,NamedNumberList);
- Sc -> % extension marker
- {Len,Bytes2} = decode_length(Buffer,Sc),
- Bytes3 = align(Bytes2),
- bit_list_or_named(Bytes3,Len,NamedNumberList)
- end.
-
-
-%% if no named bits are declared we will return a
-%% {Unused,Bits}. Unused = integer(),
-%% Bits = binary().
-compact_bit_string(Buffer,Len,[]) ->
- getbits_as_binary(Len,Buffer); % {{Unused,BinBits},NewBuffer}
-compact_bit_string(Buffer,Len,NamedNumberList) ->
- bit_list_or_named(Buffer,Len,NamedNumberList).
-
-
-%% if no named bits are declared we will return a
-%% BitList = [0 | 1]
-
-bit_list_or_named(Buffer,Len,[]) ->
- getbits_as_list(Len,Buffer);
-
-%% if there are named bits declared we will return a named
-%% BitList where the names are atoms and unnamed bits represented
-%% as {bit,Pos}
-%% BitList = [atom() | {bit,Pos}]
-%% Pos = integer()
-
-bit_list_or_named(Buffer,Len,NamedNumberList) ->
- {BitList,Rest} = getbits_as_list(Len,Buffer),
- {bit_list_or_named1(0,BitList,NamedNumberList,[]), Rest}.
-
-bit_list_or_named1(Pos,[0|Bt],Names,Acc) ->
- bit_list_or_named1(Pos+1,Bt,Names,Acc);
-bit_list_or_named1(Pos,[1|Bt],Names,Acc) ->
- case lists:keysearch(Pos,2,Names) of
- {value,{Name,_}} ->
- bit_list_or_named1(Pos+1,Bt,Names,[Name|Acc]);
- _ ->
- bit_list_or_named1(Pos+1,Bt,Names,[{bit,Pos}|Acc])
- end;
-bit_list_or_named1(_Pos,[],_Names,Acc) ->
- lists:reverse(Acc).
-
-
-
-%%%%%%%%%%%%%%%
-%%
-
-int_to_bitlist(Int) when integer(Int), Int > 0 ->
- [Int band 1 | int_to_bitlist(Int bsr 1)];
-int_to_bitlist(0) ->
- [].
-
-
-%%%%%%%%%%%%%%%%%%
-%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
-%% [sorted_list_of_bitpositions_to_set]
-
-get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
-
-get_all_bitposes([Val | Rest], NamedBitList, Ack) ->
- case lists:keysearch(Val, 1, NamedBitList) of
- {value, {_ValName, ValPos}} ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
- _ ->
- exit({error,{asn1, {bitstring_namedbit, Val}}})
- end;
-get_all_bitposes([], _NamedBitList, Ack) ->
- lists:sort(Ack).
-
-%%%%%%%%%%%%%%%%%%
-%% make_and_set_list([list of positions to set to 1])->
-%% returns list with all in SetPos set.
-%% in positioning in list the first element is 0, the second 1 etc.., but
-%%
-
-make_and_set_list([XPos|SetPos], XPos) ->
- [1 | make_and_set_list(SetPos, XPos + 1)];
-make_and_set_list([Pos|SetPos], XPos) ->
- [0 | make_and_set_list([Pos | SetPos], XPos + 1)];
-make_and_set_list([], _) ->
- [].
-
-%%%%%%%%%%%%%%%%%
-%% pad_list(N,BitList) -> PaddedList
-%% returns a padded (with trailing {bit,0} elements) list of length N
-%% if Bitlist contains more than N significant bits set an exit asn1_error
-%% is generated
-
-% pad_list(N,In={Unused,Bin}) ->
-% pad_list(N, size(Bin)*8 - Unused, In).
-
-% pad_list(N,Size,In={Unused,Bin}) when N < Size ->
-% exit({error,{asn1,{range_error,{bit_string,In}}}});
-% pad_list(N,Size,{Unused,Bin}) when N > Size, Unused > 0 ->
-% pad_list(N,Size+1,{Unused-1,Bin});
-% pad_list(N,Size,{Unused,Bin}) when N > Size ->
-% pad_list(N,Size+1,{7,<<Bin/binary,0>>});
-% pad_list(N,N,In={Unused,Bin}) ->
-% In.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% X.691:16
-%% encode_octet_string(Constraint,ExtensionMarker,Val)
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-encode_octet_string(C,Val) ->
- encode_octet_string(C,false,Val).
-
-encode_octet_string(C,Bool,{_Name,Val}) ->
- encode_octet_string(C,Bool,Val);
-encode_octet_string(_C,true,_Val) ->
- exit({error,{asn1,{'not_supported',extensionmarker}}});
-encode_octet_string(SZ={_,_},false,Val) ->
-% [encode_length(SZ,length(Val)),align,
-% {octets,Val}];
- Len = length(Val),
- [encode_length(SZ,Len),2,
- octets_to_complete(Len,Val)];
-encode_octet_string(SZ,false,Val) when list(SZ) ->
- Len = length(Val),
- [encode_length({hd(SZ),lists:max(SZ)},Len),2,
- octets_to_complete(Len,Val)];
-encode_octet_string(no,false,Val) ->
- Len = length(Val),
- [encode_length(undefined,Len),2,
- octets_to_complete(Len,Val)];
-encode_octet_string(C,_,_) ->
- exit({error,{not_implemented,C}}).
-
-
-decode_octet_string(Bytes,Range) ->
- decode_octet_string(Bytes,Range,false).
-
-decode_octet_string(Bytes,1,false) ->
- {B1,Bytes2} = getbits(Bytes,8),
- {[B1],Bytes2};
-decode_octet_string(Bytes,2,false) ->
- {Bs,Bytes2}= getbits(Bytes,16),
- {binary_to_list(<<Bs:16>>),Bytes2};
-decode_octet_string(Bytes,Sv,false) when integer(Sv),Sv=<65535 ->
- Bytes2 = align(Bytes),
- getoctets_as_list(Bytes2,Sv);
-decode_octet_string(Bytes,Sv,false) when integer(Sv) ->
- Bytes2 = align(Bytes),
- decode_fragmented_octets(Bytes2,Sv);
-decode_octet_string(Bytes,{Lb,Ub},false) ->
- {Len,Bytes2} = decode_length(Bytes,{Lb,Ub}),
- Bytes3 = align(Bytes2),
- getoctets_as_list(Bytes3,Len);
-decode_octet_string(Bytes,Sv,false) when list(Sv) ->
- {Len,Bytes2} = decode_length(Bytes,{hd(Sv),lists:max(Sv)}),
- Bytes3 = align(Bytes2),
- getoctets_as_list(Bytes3,Len);
-decode_octet_string(Bytes,no,false) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- Bytes3 = align(Bytes2),
- getoctets_as_list(Bytes3,Len).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Restricted char string types
-%% (NumericString, PrintableString,VisibleString,IA5String,BMPString,UniversalString)
-%% X.691:26 and X.680:34-36
-%%encode_restricted_string(aligned,'BMPString',Constraints,Extension,Val)
-
-
-encode_restricted_string(aligned,{Name,Val}) when atom(Name) ->
- encode_restricted_string(aligned,Val);
-
-encode_restricted_string(aligned,Val) when list(Val)->
- Len = length(Val),
-% [encode_length(undefined,length(Val)),{octets,Val}].
- [encode_length(undefined,Len),octets_to_complete(Len,Val)].
-
-
-encode_known_multiplier_string(StringType,SizeC,NumBits,CharOutTab,{Name,Val}) when atom(Name) ->
- encode_known_multiplier_string(StringType,SizeC,NumBits,CharOutTab,Val);
-encode_known_multiplier_string(StringType,SizeC,NumBits,CharOutTab,Val) ->
- Result = chars_encode2(Val,NumBits,CharOutTab),
- case SizeC of
- Ub when integer(Ub), Ub*NumBits =< 16 ->
- case {StringType,Result} of
- {'BMPString',{octets,Ol}} -> %% this case cannot happen !!??
- [{bits,8,Oct}||Oct <- Ol];
- _ ->
- Result
- end;
- Ub when integer(Ub),Ub =<65535 -> % fixed length
-%% [align,Result];
- [2,Result];
- {Ub,Lb} ->
-% [encode_length({Ub,Lb},length(Val)),align,Result];
- [encode_length({Ub,Lb},length(Val)),2,Result];
- no ->
-% [encode_length(undefined,length(Val)),align,Result]
- [encode_length(undefined,length(Val)),2,Result]
- end.
-
-decode_restricted_string(Bytes,aligned) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- getoctets_as_list(Bytes2,Len).
-
-decode_known_multiplier_string(StringType,SizeC,NumBits,CharInTab,Bytes) ->
- case SizeC of
- Ub when integer(Ub), Ub*NumBits =< 16 ->
- chars_decode(Bytes,NumBits,StringType,CharInTab,Ub);
- Ub when integer(Ub),Ub =<65535 -> % fixed length
- Bytes1 = align(Bytes),
- chars_decode(Bytes1,NumBits,StringType,CharInTab,Ub);
- Vl when list(Vl) ->
- {Len,Bytes1} = decode_length(Bytes,{hd(Vl),lists:max(Vl)}),
- Bytes2 = align(Bytes1),
- chars_decode(Bytes2,NumBits,StringType,CharInTab,Len);
- no ->
- {Len,Bytes1} = decode_length(Bytes,undefined),
- Bytes2 = align(Bytes1),
- chars_decode(Bytes2,NumBits,StringType,CharInTab,Len);
- {Lb,Ub}->
- {Len,Bytes1} = decode_length(Bytes,{Lb,Ub}),
- Bytes2 = align(Bytes1),
- chars_decode(Bytes2,NumBits,StringType,CharInTab,Len)
- end.
-
-encode_GeneralString(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_GeneralString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_GraphicString(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_GraphicString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_ObjectDescriptor(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_ObjectDescriptor(Bytes) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_TeletexString(_C,Val) -> % equivalent with T61String
- encode_restricted_string(aligned,Val).
-decode_TeletexString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_VideotexString(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_VideotexString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% getBMPChars(Bytes,Len) ->{BMPcharList,RemainingBytes}
-%%
-getBMPChars(Bytes,1) ->
- {O1,Bytes2} = getbits(Bytes,8),
- {O2,Bytes3} = getbits(Bytes2,8),
- if
- O1 == 0 ->
- {[O2],Bytes3};
- true ->
- {[{0,0,O1,O2}],Bytes3}
- end;
-getBMPChars(Bytes,Len) ->
- getBMPChars(Bytes,Len,[]).
-
-getBMPChars(Bytes,0,Acc) ->
- {lists:reverse(Acc),Bytes};
-getBMPChars(Bytes,Len,Acc) ->
- {Octs,Bytes1} = getoctets_as_list(Bytes,2),
- case Octs of
- [0,O2] ->
- getBMPChars(Bytes1,Len-1,[O2|Acc]);
- [O1,O2]->
- getBMPChars(Bytes1,Len-1,[{0,0,O1,O2}|Acc])
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% chars_encode(C,StringType,Value) -> ValueList
-%%
-%% encodes chars according to the per rules taking the constraint PermittedAlphabet
-%% into account.
-%% This function does only encode the value part and NOT the length
-
-% chars_encode(C,StringType,Value) ->
-% case {StringType,get_constraint(C,'PermittedAlphabet')} of
-% {'UniversalString',{_,Sv}} ->
-% exit({error,{asn1,{'not implemented',"UniversalString with PermittedAlphabet constraint"}}});
-% {'BMPString',{_,Sv}} ->
-% exit({error,{asn1,{'not implemented',"BMPString with PermittedAlphabet constraint"}}});
-% _ ->
-% {NumBits,CharOutTab} = {get_NumBits(C,StringType),get_CharOutTab(C,StringType)},
-% chars_encode2(Value,NumBits,CharOutTab)
-% end.
-
-
-chars_encode2([H|T],NumBits,T1={Min,Max,notab}) when H =< Max, H >= Min ->
-% [[10,NumBits,H-Min]|chars_encode2(T,NumBits,T1)];
- [pre_complete_bits(NumBits,H-Min)|chars_encode2(T,NumBits,T1)];
-chars_encode2([H|T],NumBits,T1={Min,Max,Tab}) when H =< Max, H >= Min ->
-% [[10,NumBits,element(H-Min+1,Tab)]|chars_encode2(T,NumBits,T1)];
- [pre_complete_bits(NumBits,exit_if_false(H,element(H-Min+1,Tab)))|
- chars_encode2(T,NumBits,T1)];
-chars_encode2([{A,B,C,D}|T],NumBits,T1={Min,_Max,notab}) ->
- %% no value range check here (ought to be, but very expensive)
-% [{bits,NumBits,(A*B*C*D)-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
-% [[10,NumBits,((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min]|chars_encode2(T,NumBits,T1)];
- [pre_complete_bits(NumBits,
- ((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min)|
- chars_encode2(T,NumBits,T1)];
-chars_encode2([H={A,B,C,D}|T],NumBits,{Min,Max,Tab}) ->
- %% no value range check here (ought to be, but very expensive)
- [pre_complete_bits(NumBits,exit_if_false(H,element(((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min,Tab)))|chars_encode2(T,NumBits,{Min,Max,notab})];
-chars_encode2([H|_T],_NumBits,{_Min,_Max,_Tab}) ->
- exit({error,{asn1,{illegal_char_value,H}}});
-chars_encode2([],_,_) ->
- [].
-
-exit_if_false(V,false)->
- exit({error,{asn1,{"illegal value according to Permitted alphabet constraint",V}}});
-exit_if_false(_,V) ->V.
-
-pre_complete_bits(NumBits,Val) when NumBits =< 8 ->
- [10,NumBits,Val];
-pre_complete_bits(NumBits,Val) when NumBits =< 16 ->
- [10,NumBits-8,Val bsr 8,10,8,(Val band 255)];
-pre_complete_bits(NumBits,Val) when NumBits =< 2040 -> % 255 * 8
-% LBUsed = NumBits rem 8,
-% {Unused,Len} = case (8 - LBUsed) of
-% 8 -> {0,NumBits div 8};
-% U -> {U,(NumBits div 8) + 1}
-% end,
-% NewVal = Val bsr LBUsed,
-% [30,Unused,Len,<<NewVal:Len/unit:8,Val:LBUsed,0:Unused>>].
- Unused = (8 - (NumBits rem 8)) rem 8,
- Len = NumBits + Unused,
- [30,Unused,Len div 8,<<(Val bsl Unused):Len>>].
-
-% get_NumBits(C,StringType) ->
-% case get_constraint(C,'PermittedAlphabet') of
-% {'SingleValue',Sv} ->
-% charbits(length(Sv),aligned);
-% no ->
-% case StringType of
-% 'IA5String' ->
-% charbits(128,aligned); % 16#00..16#7F
-% 'VisibleString' ->
-% charbits(95,aligned); % 16#20..16#7E
-% 'PrintableString' ->
-% charbits(74,aligned); % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
-% 'NumericString' ->
-% charbits(11,aligned); % $ ,"0123456789"
-% 'UniversalString' ->
-% 32;
-% 'BMPString' ->
-% 16
-% end
-% end.
-
-%%Maybe used later
-%%get_MaxChar(C,StringType) ->
-%% case get_constraint(C,'PermittedAlphabet') of
-%% {'SingleValue',Sv} ->
-%% lists:nth(length(Sv),Sv);
-%% no ->
-%% case StringType of
-%% 'IA5String' ->
-%% 16#7F; % 16#00..16#7F
-%% 'VisibleString' ->
-%% 16#7E; % 16#20..16#7E
-%% 'PrintableString' ->
-%% $z; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
-%% 'NumericString' ->
-%% $9; % $ ,"0123456789"
-%% 'UniversalString' ->
-%% 16#ffffffff;
-%% 'BMPString' ->
-%% 16#ffff
-%% end
-%% end.
-
-%%Maybe used later
-%%get_MinChar(C,StringType) ->
-%% case get_constraint(C,'PermittedAlphabet') of
-%% {'SingleValue',Sv} ->
-%% hd(Sv);
-%% no ->
-%% case StringType of
-%% 'IA5String' ->
-%% 16#00; % 16#00..16#7F
-%% 'VisibleString' ->
-%% 16#20; % 16#20..16#7E
-%% 'PrintableString' ->
-%% $\s; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
-%% 'NumericString' ->
-%% $\s; % $ ,"0123456789"
-%% 'UniversalString' ->
-%% 16#00;
-%% 'BMPString' ->
-%% 16#00
-%% end
-%% end.
-
-% get_CharOutTab(C,StringType) ->
-% get_CharTab(C,StringType,out).
-
-% get_CharInTab(C,StringType) ->
-% get_CharTab(C,StringType,in).
-
-% get_CharTab(C,StringType,InOut) ->
-% case get_constraint(C,'PermittedAlphabet') of
-% {'SingleValue',Sv} ->
-% get_CharTab2(C,StringType,hd(Sv),lists:max(Sv),Sv,InOut);
-% no ->
-% case StringType of
-% 'IA5String' ->
-% {0,16#7F,notab};
-% 'VisibleString' ->
-% get_CharTab2(C,StringType,16#20,16#7F,notab,InOut);
-% 'PrintableString' ->
-% Chars = lists:sort(
-% " '()+,-./0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
-% get_CharTab2(C,StringType,hd(Chars),lists:max(Chars),Chars,InOut);
-% 'NumericString' ->
-% get_CharTab2(C,StringType,16#20,$9," 0123456789",InOut);
-% 'UniversalString' ->
-% {0,16#FFFFFFFF,notab};
-% 'BMPString' ->
-% {0,16#FFFF,notab}
-% end
-% end.
-
-% get_CharTab2(C,StringType,Min,Max,Chars,InOut) ->
-% BitValMax = (1 bsl get_NumBits(C,StringType))-1,
-% if
-% Max =< BitValMax ->
-% {0,Max,notab};
-% true ->
-% case InOut of
-% out ->
-% {Min,Max,create_char_tab(Min,Chars)};
-% in ->
-% {Min,Max,list_to_tuple(Chars)}
-% end
-% end.
-
-% create_char_tab(Min,L) ->
-% list_to_tuple(create_char_tab(Min,L,0)).
-% create_char_tab(Min,[Min|T],V) ->
-% [V|create_char_tab(Min+1,T,V+1)];
-% create_char_tab(_Min,[],_V) ->
-% [];
-% create_char_tab(Min,L,V) ->
-% [false|create_char_tab(Min+1,L,V)].
-
-%% This very inefficient and should be moved to compiletime
-% charbits(NumOfChars,aligned) ->
-% case charbits(NumOfChars) of
-% 1 -> 1;
-% 2 -> 2;
-% B when B =< 4 -> 4;
-% B when B =< 8 -> 8;
-% B when B =< 16 -> 16;
-% B when B =< 32 -> 32
-% end.
-
-% charbits(NumOfChars) when NumOfChars =< 2 -> 1;
-% charbits(NumOfChars) when NumOfChars =< 4 -> 2;
-% charbits(NumOfChars) when NumOfChars =< 8 -> 3;
-% charbits(NumOfChars) when NumOfChars =< 16 -> 4;
-% charbits(NumOfChars) when NumOfChars =< 32 -> 5;
-% charbits(NumOfChars) when NumOfChars =< 64 -> 6;
-% charbits(NumOfChars) when NumOfChars =< 128 -> 7;
-% charbits(NumOfChars) when NumOfChars =< 256 -> 8;
-% charbits(NumOfChars) when NumOfChars =< 512 -> 9;
-% charbits(NumOfChars) when NumOfChars =< 1024 -> 10;
-% charbits(NumOfChars) when NumOfChars =< 2048 -> 11;
-% charbits(NumOfChars) when NumOfChars =< 4096 -> 12;
-% charbits(NumOfChars) when NumOfChars =< 8192 -> 13;
-% charbits(NumOfChars) when NumOfChars =< 16384 -> 14;
-% charbits(NumOfChars) when NumOfChars =< 32768 -> 15;
-% charbits(NumOfChars) when NumOfChars =< 65536 -> 16;
-% charbits(NumOfChars) when integer(NumOfChars) ->
-% 16 + charbits1(NumOfChars bsr 16).
-
-% charbits1(0) ->
-% 0;
-% charbits1(NumOfChars) ->
-% 1 + charbits1(NumOfChars bsr 1).
-
-
-chars_decode(Bytes,_,'BMPString',_,Len) ->
- getBMPChars(Bytes,Len);
-chars_decode(Bytes,NumBits,_StringType,CharInTab,Len) ->
- chars_decode2(Bytes,CharInTab,NumBits,Len).
-
-
-chars_decode2(Bytes,CharInTab,NumBits,Len) ->
- chars_decode2(Bytes,CharInTab,NumBits,Len,[]).
-
-chars_decode2(Bytes,_CharInTab,_NumBits,0,Acc) ->
- {lists:reverse(Acc),Bytes};
-chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) when NumBits > 8 ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- Result =
- if
- Char < 256 -> Char;
- true ->
- list_to_tuple(binary_to_list(<<Char:32>>))
- end,
- chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Result|Acc]);
-chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Char+Min|Acc]);
-
-%% BMPString and UniversalString with PermittedAlphabet is currently not supported
-chars_decode2(Bytes,{Min,Max,CharInTab},NumBits,Len,Acc) ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- chars_decode2(Bytes2,{Min,Max,CharInTab},NumBits,Len -1,[element(Char+1,CharInTab)|Acc]).
-
-
- % X.691:17
-encode_null(_Val) -> []; % encodes to nothing
-encode_null({Name,Val}) when atom(Name) ->
- encode_null(Val).
-
-decode_null(Bytes) ->
- {'NULL',Bytes}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_object_identifier(Val) -> CompleteList
-%% encode_object_identifier({Name,Val}) -> CompleteList
-%% Val -> {Int1,Int2,...,IntN} % N >= 2
-%% Name -> atom()
-%% Int1 -> integer(0..2)
-%% Int2 -> integer(0..39) when Int1 (0..1) else integer()
-%% Int3-N -> integer()
-%% CompleteList -> [{bits,8,Val}|{octets,Ol}|align|...]
-%%
-encode_object_identifier({Name,Val}) when atom(Name) ->
- encode_object_identifier(Val);
-encode_object_identifier(Val) ->
- OctetList = e_object_identifier(Val),
- Octets = list_to_binary(OctetList), % performs a flatten at the same time
-% [{debug,object_identifier},encode_length(undefined,size(Octets)),{octets,Octets}].
- [encode_length(undefined,size(Octets)),
- octets_to_complete(size(Octets),Octets)].
-
-%% This code is copied from asn1_encode.erl (BER) and corrected and modified
-
-e_object_identifier({'OBJECT IDENTIFIER',V}) ->
- e_object_identifier(V);
-e_object_identifier({Cname,V}) when atom(Cname),tuple(V) ->
- e_object_identifier(tuple_to_list(V));
-e_object_identifier({Cname,V}) when atom(Cname),list(V) ->
- e_object_identifier(V);
-e_object_identifier(V) when tuple(V) ->
- e_object_identifier(tuple_to_list(V));
-
-%% E1 = 0|1|2 and (E2 < 40 when E1 = 0|1)
-e_object_identifier([E1,E2|Tail]) when E1 >= 0, E1 < 2, E2 < 40 ; E1==2 ->
- Head = 40*E1 + E2, % weird
- e_object_elements([Head|Tail],[]);
-e_object_identifier(Oid=[_,_|_Tail]) ->
- exit({error,{asn1,{'illegal_value',Oid}}}).
-
-e_object_elements([],Acc) ->
- lists:reverse(Acc);
-e_object_elements([H|T],Acc) ->
- e_object_elements(T,[e_object_element(H)|Acc]).
-
-e_object_element(Num) when Num < 128 ->
- Num;
-%% must be changed to handle more than 2 octets
-e_object_element(Num) -> %% when Num < ???
- Left = ((Num band 2#11111110000000) bsr 7) bor 2#10000000,
- Right = Num band 2#1111111 ,
- [Left,Right].
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_object_identifier(Bytes) -> {ObjId,RemainingBytes}
-%% ObjId -> {integer(),integer(),...} % at least 2 integers
-%% RemainingBytes -> [integer()] when integer() (0..255)
-decode_object_identifier(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- [First|Rest] = dec_subidentifiers(Octs,0,[]),
- Idlist = if
- First < 40 ->
- [0,First|Rest];
- First < 80 ->
- [1,First - 40|Rest];
- true ->
- [2,First - 80|Rest]
- end,
- {list_to_tuple(Idlist),Bytes3}.
-
-dec_subidentifiers([H|T],Av,Al) when H >=16#80 ->
- dec_subidentifiers(T,(Av bsl 7) + (H band 16#7F),Al);
-dec_subidentifiers([H|T],Av,Al) ->
- dec_subidentifiers(T,0,[(Av bsl 7) + H |Al]);
-dec_subidentifiers([],_Av,Al) ->
- lists:reverse(Al).
-
-get_constraint([{Key,V}],Key) ->
- V;
-get_constraint([],_) ->
- no;
-get_constraint(C,Key) ->
- case lists:keysearch(Key,1,C) of
- false ->
- no;
- {value,{_,V}} ->
- V
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% complete(InList) -> ByteList
-%% Takes a coded list with bits and bytes and converts it to a list of bytes
-%% Should be applied as the last step at encode of a complete ASN.1 type
-%%
-
--ifdef(nodriver).
-
-complete(L) ->
- case complete1(L) of
- {[],[]} ->
- <<0>>;
- {Acc,[]} ->
- Acc;
- {Acc,Bacc} ->
- [Acc|complete_bytes(Bacc)]
- end.
-
-
-% this function builds the ugly form of lists [E1|E2] to avoid having to reverse it at the end.
-% this is done because it is efficient and that the result always will be sent on a port or
-% converted by means of list_to_binary/1
- complete1(InList) when list(InList) ->
- complete1(InList,[],[]);
- complete1(InList) ->
- complete1([InList],[],[]).
-
- complete1([],Acc,Bacc) ->
- {Acc,Bacc};
- complete1([H|T],Acc,Bacc) when list(H) ->
- {NewH,NewBacc} = complete1(H,Acc,Bacc),
- complete1(T,NewH,NewBacc);
-
- complete1([{octets,Bin}|T],Acc,[]) ->
- complete1(T,[Acc|Bin],[]);
-
- complete1([{octets,Bin}|T],Acc,Bacc) ->
- complete1(T,[Acc|[complete_bytes(Bacc),Bin]],[]);
-
- complete1([{debug,_}|T], Acc,Bacc) ->
- complete1(T,Acc,Bacc);
-
- complete1([{bits,N,Val}|T],Acc,Bacc) ->
- complete1(T,Acc,complete_update_byte(Bacc,Val,N));
-
- complete1([{bit,Val}|T],Acc,Bacc) ->
- complete1(T,Acc,complete_update_byte(Bacc,Val,1));
-
- complete1([align|T],Acc,[]) ->
- complete1(T,Acc,[]);
- complete1([align|T],Acc,Bacc) ->
- complete1(T,[Acc|complete_bytes(Bacc)],[]);
- complete1([{0,Bin}|T],Acc,[]) when binary(Bin) ->
- complete1(T,[Acc|Bin],[]);
- complete1([{Unused,Bin}|T],Acc,[]) when integer(Unused),binary(Bin) ->
- Size = size(Bin)-1,
- <<Bs:Size/binary,B>> = Bin,
- NumBits = 8-Unused,
- complete1(T,[Acc|Bs],[[B bsr Unused]|NumBits]);
- complete1([{Unused,Bin}|T],Acc,Bacc) when integer(Unused),binary(Bin) ->
- Size = size(Bin)-1,
- <<Bs:Size/binary,B>> = Bin,
- NumBits = 8 - Unused,
- Bf = complete_bytes(Bacc),
- complete1(T,[Acc|[Bf,Bs]],[[B bsr Unused]|NumBits]).
-
-
- complete_update_byte([],Val,Len) ->
- complete_update_byte([[0]|0],Val,Len);
- complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) when NumBits + Len == 8 ->
- [[0,((Byte bsl Len) + Val) band 255|Bacc]|0];
- complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) when NumBits + Len > 8 ->
- Rem = 8 - NumBits,
- Rest = Len - Rem,
- complete_update_byte([[0,((Byte bsl Rem) + (Val bsr Rest)) band 255 |Bacc]|0],Val,Rest);
- complete_update_byte([[Byte|Bacc]|NumBits],Val,Len) ->
- [[((Byte bsl Len) + Val) band 255|Bacc]|NumBits+Len].
-
-
- complete_bytes([[Byte|Bacc]|0]) ->
- lists:reverse(Bacc);
- complete_bytes([[Byte|Bacc]|NumBytes]) ->
- lists:reverse([(Byte bsl (8-NumBytes)) band 255|Bacc]);
- complete_bytes([]) ->
- [].
-
--else.
-
-
- complete(L) ->
- case catch port_control(drv_complete,1,L) of
- Bin when binary(Bin) ->
- Bin;
- List when list(List) -> handle_error(List,L);
- {'EXIT',{badarg,Reason}} ->
- asn1rt_driver_handler:load_driver(),
- receive
- driver_ready ->
- case catch port_control(drv_complete,1,L) of
- Bin2 when binary(Bin2) -> Bin2;
- List when list(List) -> handle_error(List,L);
- Error -> exit(Error)
- end;
- {error,Error} -> % error when loading driver
- %% the driver could not be loaded
- exit(Error);
- Error={port_error,Reason} ->
- exit(Error)
- end;
- {'EXIT',Reason} ->
- exit(Reason)
- end.
-
-handle_error([],_)->
- exit({error,{"memory allocation problem"}});
-handle_error("1",L) -> % error in complete in driver
- exit({error,{asn1_error,L}});
-handle_error(ErrL,L) ->
- exit({error,{unknown_error,ErrL,L}}).
-
--endif.
-
-
-octets_to_complete(Len,Val) when Len < 256 ->
- [20,Len,Val];
-octets_to_complete(Len,Val) ->
- [21,<<Len:16>>,Val].
-
-octets_unused_to_complete(Unused,Len,Val) when Len < 256 ->
- [30,Unused,Len,Val];
-octets_unused_to_complete(Unused,Len,Val) ->
- [31,Unused,<<Len:16>>,Val].
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per_v1.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per_v1.erl
deleted file mode 100644
index ebab269f5d..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/asn1rt_per_v1.erl
+++ /dev/null
@@ -1,1843 +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: asn1rt_per_v1.erl,v 1.1 2008/12/17 09:53:31 mikpe Exp $
-%%
--module(asn1rt_per_v1).
-
-%% encoding / decoding of PER aligned
-
--include("asn1_records.hrl").
-
--export([dec_fixup/3, cindex/3, list_to_record/2]).
--export([setchoiceext/1, setext/1, fixoptionals/2, fixextensions/2,
- setoptionals/1, fixoptionals2/3, getext/1, getextension/2,
- skipextensions/3, getbit/1, getchoice/3 ]).
--export([getoptionals/2, getoptionals/3, set_choice/3,
- getoptionals2/2,
- encode_integer/2, encode_integer/3 ]).
--export([decode_integer/2, decode_integer/3, encode_small_number/1,
- encode_boolean/1, decode_boolean/1, encode_length/2,
- decode_length/1, decode_length/2,
- encode_small_length/1, decode_small_length/1,
- decode_compact_bit_string/3]).
--export([encode_enumerated/3, decode_enumerated/3,
- encode_bit_string/3, decode_bit_string/3 ]).
--export([encode_octet_string/2, decode_octet_string/2,
- encode_null/1, decode_null/1,
- encode_object_identifier/1, decode_object_identifier/1,
- complete/1]).
-
--export([encode_open_type/2, decode_open_type/2]).
-
--export([encode_UniversalString/2, decode_UniversalString/2,
- encode_PrintableString/2, decode_PrintableString/2,
- encode_GeneralString/2, decode_GeneralString/2,
- encode_GraphicString/2, decode_GraphicString/2,
- encode_TeletexString/2, decode_TeletexString/2,
- encode_VideotexString/2, decode_VideotexString/2,
- encode_VisibleString/2, decode_VisibleString/2,
- encode_BMPString/2, decode_BMPString/2,
- encode_IA5String/2, decode_IA5String/2,
- encode_NumericString/2, decode_NumericString/2,
- encode_ObjectDescriptor/2, decode_ObjectDescriptor/1
- ]).
-
-
-dec_fixup(Terms,Cnames,RemBytes) ->
- dec_fixup(Terms,Cnames,RemBytes,[]).
-
-dec_fixup([novalue|T],[_Hc|Tc],RemBytes,Acc) ->
- dec_fixup(T,Tc,RemBytes,Acc);
-dec_fixup([{_Name,novalue}|T],[_Hc|Tc],RemBytes,Acc) ->
- dec_fixup(T,Tc,RemBytes,Acc);
-dec_fixup([H|T],[Hc|Tc],RemBytes,Acc) ->
- dec_fixup(T,Tc,RemBytes,[{Hc,H}|Acc]);
-dec_fixup([],_Cnames,RemBytes,Acc) ->
- {lists:reverse(Acc),RemBytes}.
-
-cindex(Ix,Val,Cname) ->
- case element(Ix,Val) of
- {Cname,Val2} -> Val2;
- X -> X
- end.
-
-% converts a list to a record if necessary
-list_to_record(Name,List) when list(List) ->
- list_to_tuple([Name|List]);
-list_to_record(_Name,Tuple) when tuple(Tuple) ->
- Tuple.
-
-%%--------------------------------------------------------
-%% setchoiceext(InRootSet) -> [{bit,X}]
-%% X is set to 1 when InRootSet==false
-%% X is set to 0 when InRootSet==true
-%%
-setchoiceext(true) ->
- [{debug,choiceext},{bit,0}];
-setchoiceext(false) ->
- [{debug,choiceext},{bit,1}].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% setext(true|false) -> CompleteList
-%%
-
-setext(true) ->
- [{debug,ext},{bit,1}];
-setext(false) ->
- [{debug,ext},{bit,0}].
-
-%%
-
-fixoptionals2(OptList,OptLength,Val) when tuple(Val) ->
- Bits = fixoptionals2(OptList,Val,0),
- {Val,{bits,OptLength,Bits}};
-
-fixoptionals2([],_Val,Acc) ->
- %% Optbits
- Acc;
-fixoptionals2([Pos|Ot],Val,Acc) ->
- case element(Pos,Val) of
- asn1_NOVALUE -> fixoptionals2(Ot,Val,Acc bsl 1);
- asn1_DEFAULT -> fixoptionals2(Ot,Val,Acc bsl 1);
- _ -> fixoptionals2(Ot,Val,(Acc bsl 1) + 1)
- end.
-
-
-%%
-%% fixoptionals remains only for backward compatibility purpose
-fixoptionals(OptList,Val) when tuple(Val) ->
- fixoptionals(OptList,Val,[]);
-
-fixoptionals(OptList,Val) when list(Val) ->
- fixoptionals(OptList,Val,1,[],[]).
-
-fixoptionals([],Val,Acc) ->
- % return {Val,Opt}
- {Val,lists:reverse(Acc)};
-fixoptionals([{_,Pos}|Ot],Val,Acc) ->
- case element(Pos+1,Val) of
- asn1_NOVALUE -> fixoptionals(Ot,Val,[0|Acc]);
- asn1_DEFAULT -> fixoptionals(Ot,Val,[0|Acc]);
- _ -> fixoptionals(Ot,Val,[1|Acc])
- end.
-
-
-%setoptionals(OptList,Val) ->
-% Vlist = tuple_to_list(Val),
-% setoptionals(OptList,Vlist,1,[]).
-
-fixoptionals([{Name,Pos}|Ot],[{Name,Val}|Vt],_Opt,Acc1,Acc2) ->
- fixoptionals(Ot,Vt,Pos+1,[1|Acc1],[{Name,Val}|Acc2]);
-fixoptionals([{_Name,Pos}|Ot],V,Pos,Acc1,Acc2) ->
- fixoptionals(Ot,V,Pos+1,[0|Acc1],[asn1_NOVALUE|Acc2]);
-fixoptionals(O,[Vh|Vt],Pos,Acc1,Acc2) ->
- fixoptionals(O,Vt,Pos+1,Acc1,[Vh|Acc2]);
-fixoptionals([],[Vh|Vt],Pos,Acc1,Acc2) ->
- fixoptionals([],Vt,Pos+1,Acc1,[Vh|Acc2]);
-fixoptionals([],[],_,Acc1,Acc2) ->
- % return {Val,Opt}
- {list_to_tuple([asn1_RECORDNAME|lists:reverse(Acc2)]),lists:reverse(Acc1)}.
-
-setoptionals([H|T]) ->
- [{bit,H}|setoptionals(T)];
-setoptionals([]) ->
- [{debug,optionals}].
-
-getext(Bytes) when tuple(Bytes) ->
- getbit(Bytes);
-getext(Bytes) when list(Bytes) ->
- getbit({0,Bytes}).
-
-getextension(0, Bytes) ->
- {{},Bytes};
-getextension(1, Bytes) ->
- {Len,Bytes2} = decode_small_length(Bytes),
- {Blist, Bytes3} = getbits_as_list(Len,Bytes2),
- {list_to_tuple(Blist),Bytes3}.
-
-fixextensions({ext,ExtPos,ExtNum},Val) ->
- case fixextensions(ExtPos,ExtNum+ExtPos,Val,0) of
- 0 -> [];
- ExtBits ->
- [encode_small_length(ExtNum),{bits,ExtNum,ExtBits}]
- end.
-
-fixextensions(Pos,MaxPos,_,Acc) when Pos >= MaxPos ->
- Acc;
-fixextensions(Pos,ExtPos,Val,Acc) ->
- Bit = case catch(element(Pos+1,Val)) of
- asn1_NOVALUE ->
- 0;
- asn1_NOEXTVALUE ->
- 0;
- {'EXIT',_} ->
- 0;
- _ ->
- 1
- end,
- fixextensions(Pos+1,ExtPos,Val,(Acc bsl 1)+Bit).
-
-skipextensions(Bytes,Nr,ExtensionBitPattern) ->
- case (catch element(Nr,ExtensionBitPattern)) of
- 1 ->
- {_,Bytes2} = decode_open_type(Bytes,[]),
- skipextensions(Bytes2, Nr+1, ExtensionBitPattern);
- 0 ->
- skipextensions(Bytes, Nr+1, ExtensionBitPattern);
- {'EXIT',_} -> % badarg, no more extensions
- Bytes
- end.
-
-
-getchoice(Bytes,1,0) -> % only 1 alternative is not encoded
- {0,Bytes};
-getchoice(Bytes,_NumChoices,1) ->
- decode_small_number(Bytes);
-getchoice(Bytes,NumChoices,0) ->
- decode_integer(Bytes,[{'ValueRange',{0,NumChoices-1}}]).
-
-getoptionals2(Bytes,NumOpt) ->
- getbits(Bytes,NumOpt).
-
-%% getoptionals is kept only for bakwards compatibility
-getoptionals(Bytes,NumOpt) ->
- {Blist,Bytes1} = getbits_as_list(NumOpt,Bytes),
- {list_to_tuple(Blist),Bytes1}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% getoptionals/3 is only here for compatibility from 1.3.2
-%% the codegenerator uses getoptionals/2
-
-getoptionals(Bytes,L,NumComp) when list(L) ->
- {Blist,Bytes1} = getbits_as_list(length(L),Bytes),
- {list_to_tuple(comptuple(Blist,L,NumComp,1)),Bytes1}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% comptuple is only here for compatibility not used from 1.3.2
-comptuple([Bh|Bt],[{_Name,Nr}|T],NumComp,Nr) ->
- [Bh|comptuple(Bt,T,NumComp-1,Nr+1)];
-comptuple(Bl,[{Name,Tnr}|Tl],NumComp,Nr) ->
- [0|comptuple(Bl,[{Name,Tnr}|Tl],NumComp-1,Nr+1)];
-comptuple(_B,_L,0,_Nr) ->
- [];
-comptuple(B,O,N,Nr) ->
- [0|comptuple(B,O,N-1,Nr+1)].
-
-%% getbits_as_binary(Num,Bytes) -> {{Unused,BinBits},RestBytes},
-%% Num = integer(),
-%% Bytes = list() | tuple(),
-%% Unused = integer(),
-%% BinBits = binary(),
-%% RestBytes = tuple()
-getbits_as_binary(Num,Bytes) when list(Bytes) ->
- getbits_as_binary(Num,{0,Bytes});
-getbits_as_binary(_Num,{Used,[]}) ->
- {{0,<<>>},{Used,[]}};
-getbits_as_binary(Num,{Used,Bits=[H|T]}) ->
- B1 = case (Num+Used) =< 8 of
- true -> Num;
- _ -> 8-Used
- end,
- B2 = Num - B1,
- Pad = (8 - ((B1+B2) rem 8)) rem 8,% Pad /= 8
- RestBits = lists:nthtail((B1+B2) div 8,Bits),
- Int = integer_from_list(B2,T,0),
- NewUsed = (Used + Num) rem 8,
- {{Pad,<<(H bsr (8-(Used+B1))):B1,Int:B2,0:Pad>>},{NewUsed,RestBits}}.
-
-integer_from_list(_Int,[],BigInt) ->
- BigInt;
-integer_from_list(Int,[H|_T],BigInt) when Int < 8 ->
- (BigInt bsl Int) bor (H bsr (8-Int));
-integer_from_list(Int,[H|T],BigInt) ->
- integer_from_list(Int-8,T,(BigInt bsl 8) bor H).
-
-getbits_as_list(Num,Bytes) ->
- getbits_as_list(Num,Bytes,[]).
-
-getbits_as_list(0,Bytes,Acc) ->
- {lists:reverse(Acc),Bytes};
-getbits_as_list(Num,Bytes,Acc) ->
- {Bit,NewBytes} = getbit(Bytes),
- getbits_as_list(Num-1,NewBytes,[Bit|Acc]).
-
-getbit(Bytes) ->
-% io:format("getbit:~p~n",[Bytes]),
- getbit1(Bytes).
-
-getbit1({7,[H|T]}) ->
- {H band 1,{0,T}};
-getbit1({Pos,[H|T]}) ->
- {(H bsr (7-Pos)) band 1,{(Pos+1) rem 8,[H|T]}};
-getbit1(Bytes) when list(Bytes) ->
- getbit1({0,Bytes}).
-
-%% This could be optimized
-getbits(Buffer,Num) ->
-% io:format("getbits:Buffer = ~p~nNum=~p~n",[Buffer,Num]),
- getbits(Buffer,Num,0).
-
-getbits(Buffer,0,Acc) ->
- {Acc,Buffer};
-getbits(Buffer,Num,Acc) ->
- {B,NewBuffer} = getbit(Buffer),
- getbits(NewBuffer,Num-1,B + (Acc bsl 1)).
-
-
-getoctet(Bytes) when list(Bytes) ->
- getoctet({0,Bytes});
-getoctet(Bytes) ->
-% io:format("getoctet:Buffer = ~p~n",[Bytes]),
- getoctet1(Bytes).
-
-getoctet1({0,[H|T]}) ->
- {H,{0,T}};
-getoctet1({_Pos,[_,H|T]}) ->
- {H,{0,T}}.
-
-align({0,L}) ->
- {0,L};
-align({_Pos,[_H|T]}) ->
- {0,T};
-align(Bytes) ->
- {0,Bytes}.
-
-getoctets(Buffer,Num) ->
-% io:format("getoctets:Buffer = ~p~nNum = ~p~n",[Buffer,Num]),
- getoctets(Buffer,Num,0).
-
-getoctets(Buffer,0,Acc) ->
- {Acc,Buffer};
-getoctets(Buffer,Num,Acc) ->
- {Oct,NewBuffer} = getoctet(Buffer),
- getoctets(NewBuffer,Num-1,(Acc bsl 8)+Oct).
-
-getoctets_as_list(Buffer,Num) ->
- getoctets_as_list(Buffer,Num,[]).
-
-getoctets_as_list(Buffer,0,Acc) ->
- {lists:reverse(Acc),Buffer};
-getoctets_as_list(Buffer,Num,Acc) ->
- {Oct,NewBuffer} = getoctet(Buffer),
- getoctets_as_list(NewBuffer,Num-1,[Oct|Acc]).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% set_choice(Alt,Choices,Altnum) -> ListofBitSettings
-%% Alt = atom()
-%% Altnum = integer() | {integer(),integer()}% number of alternatives
-%% Choices = [atom()] | {[atom()],[atom()]}
-%% When Choices is a tuple the first list is the Rootset and the
-%% second is the Extensions and then Altnum must also be a tuple with the
-%% lengths of the 2 lists
-%%
-set_choice(Alt,{L1,L2},{Len1,_Len2}) ->
- case set_choice_tag(Alt,L1) of
- N when integer(N), Len1 > 1 ->
- [{bit,0}, % the value is in the root set
- encode_integer([{'ValueRange',{0,Len1-1}}],N)];
- N when integer(N) ->
- [{bit,0}]; % no encoding if only 0 or 1 alternative
- false ->
- [{bit,1}, % extension value
- case set_choice_tag(Alt,L2) of
- N2 when integer(N2) ->
- encode_small_number(N2);
- false ->
- unknown_choice_alt
- end]
- end;
-set_choice(Alt,L,Len) ->
- case set_choice_tag(Alt,L) of
- N when integer(N), Len > 1 ->
- encode_integer([{'ValueRange',{0,Len-1}}],N);
- N when integer(N) ->
- []; % no encoding if only 0 or 1 alternative
- false ->
- [unknown_choice_alt]
- end.
-
-set_choice_tag(Alt,Choices) ->
- set_choice_tag(Alt,Choices,0).
-
-set_choice_tag(Alt,[Alt|_Rest],Tag) ->
- Tag;
-set_choice_tag(Alt,[_H|Rest],Tag) ->
- set_choice_tag(Alt,Rest,Tag+1);
-set_choice_tag(_Alt,[],_Tag) ->
- false.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_open_type(Constraint, Value) -> CompleteList
-%% Value = list of bytes of an already encoded value (the list must be flat)
-%% | binary
-%% Contraint = not used in this version
-%%
-encode_open_type(_Constraint, Val) when list(Val) ->
- [encode_length(undefined,length(Val)),align,
- {octets,Val}];
-encode_open_type(_Constraint, Val) when binary(Val) ->
- [encode_length(undefined,size(Val)),align,
- {octets,binary_to_list(Val)}].
-%% the binary_to_list is not optimal but compatible with the current solution
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_open_type(Buffer,Constraint) -> Value
-%% Constraint is not used in this version
-%% Buffer = [byte] with PER encoded data
-%% Value = [byte] with decoded data (which must be decoded again as some type)
-%%
-decode_open_type(Bytes, _Constraint) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- Bytes3 = align(Bytes2),
- getoctets_as_list(Bytes3,Len).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_integer(Constraint,Value,NamedNumberList) -> CompleteList
-%% encode_integer(Constraint,Value) -> CompleteList
-%% encode_integer(Constraint,{Name,Value}) -> CompleteList
-%%
-%%
-encode_integer(C,V,NamedNumberList) when atom(V) ->
- case lists:keysearch(V,1,NamedNumberList) of
- {value,{_,NewV}} ->
- encode_integer(C,NewV);
- _ ->
- exit({error,{asn1,{namednumber,V}}})
- end;
-encode_integer(C,V,_) when integer(V) ->
- encode_integer(C,V);
-encode_integer(C,{Name,V},NamedNumberList) when atom(Name) ->
- encode_integer(C,V,NamedNumberList).
-
-encode_integer(C,{Name,Val}) when atom(Name) ->
- encode_integer(C,Val);
-
-encode_integer({Rc,_Ec},Val) ->
- case (catch encode_integer(Rc,Val)) of
- {'EXIT',{error,{asn1,_}}} ->
- [{bit,1},encode_unconstrained_number(Val)];
- Encoded ->
- [{bit,0},Encoded]
- end;
-encode_integer(C,Val ) when list(C) ->
- case get_constraint(C,'SingleValue') of
- no ->
- encode_integer1(C,Val);
- V when integer(V),V == Val ->
- []; % a type restricted to a single value encodes to nothing
- V when list(V) ->
- case lists:member(Val,V) of
- true ->
- encode_integer1(C,Val);
- _ ->
- exit({error,{asn1,{illegal_value,Val}}})
- end;
- _ ->
- exit({error,{asn1,{illegal_value,Val}}})
- end.
-
-encode_integer1(C, Val) ->
- case VR = get_constraint(C,'ValueRange') of
- no ->
- encode_unconstrained_number(Val);
- {Lb,'MAX'} ->
- encode_semi_constrained_number(Lb,Val);
- %% positive with range
- {Lb,Ub} when Val >= Lb,
- Ub >= Val ->
- encode_constrained_number(VR,Val);
- _ ->
- exit({error,{asn1,{illegal_value,VR,Val}}})
- end.
-
-decode_integer(Buffer,Range,NamedNumberList) ->
- {Val,Buffer2} = decode_integer(Buffer,Range),
- case lists:keysearch(Val,2,NamedNumberList) of
- {value,{NewVal,_}} -> {NewVal,Buffer2};
- _ -> {Val,Buffer2}
- end.
-
-decode_integer(Buffer,{Rc,_Ec}) ->
- {Ext,Buffer2} = getext(Buffer),
- case Ext of
- 0 -> decode_integer(Buffer2,Rc);
- 1 -> decode_unconstrained_number(Buffer2)
- end;
-decode_integer(Buffer,undefined) ->
- decode_unconstrained_number(Buffer);
-decode_integer(Buffer,C) ->
- case get_constraint(C,'SingleValue') of
- V when integer(V) ->
- {V,Buffer};
- V when list(V) ->
- {Val,Buffer2} = decode_integer1(Buffer,C),
- case lists:member(Val,V) of
- true ->
- {Val,Buffer2};
- _ ->
- exit({error,{asn1,{illegal_value,Val}}})
- end;
- _ ->
- decode_integer1(Buffer,C)
- end.
-
-decode_integer1(Buffer,C) ->
- case VR = get_constraint(C,'ValueRange') of
- no ->
- decode_unconstrained_number(Buffer);
- {Lb, 'MAX'} ->
- decode_semi_constrained_number(Buffer,Lb);
- {_,_} ->
- decode_constrained_number(Buffer,VR)
- end.
-
-% X.691:10.6 Encoding of a normally small non-negative whole number
-% Use this for encoding of CHOICE index if there is an extension marker in
-% the CHOICE
-encode_small_number({Name,Val}) when atom(Name) ->
- encode_small_number(Val);
-encode_small_number(Val) when Val =< 63 ->
- [{bit,0},{bits,6,Val}];
-encode_small_number(Val) ->
- [{bit,1},encode_semi_constrained_number(0,Val)].
-
-decode_small_number(Bytes) ->
- {Bit,Bytes2} = getbit(Bytes),
- case Bit of
- 0 ->
- getbits(Bytes2,6);
- 1 ->
- decode_semi_constrained_number(Bytes2,{0,'MAX'})
- end.
-
-% X.691:10.7 Encoding of a semi-constrained whole number
-%% might be an optimization encode_semi_constrained_number(0,Val) ->
-encode_semi_constrained_number(C,{Name,Val}) when atom(Name) ->
- encode_semi_constrained_number(C,Val);
-encode_semi_constrained_number({Lb,'MAX'},Val) ->
- encode_semi_constrained_number(Lb,Val);
-encode_semi_constrained_number(Lb,Val) ->
- Val2 = Val - Lb,
- Octs = eint_positive(Val2),
- [encode_length(undefined,length(Octs)),{octets,Octs}].
-
-decode_semi_constrained_number(Bytes,{Lb,_}) ->
- decode_semi_constrained_number(Bytes,Lb);
-decode_semi_constrained_number(Bytes,Lb) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {V,Bytes3} = getoctets(Bytes2,Len),
- {V+Lb,Bytes3}.
-
-encode_constrained_number(Range,{Name,Val}) when atom(Name) ->
- encode_constrained_number(Range,Val);
-encode_constrained_number({Lb,Ub},Val) when Val >= Lb, Ub >= Val ->
- Range = Ub - Lb + 1,
- Val2 = Val - Lb,
- if
- Range == 2 ->
- {bits,1,Val2};
- Range =< 4 ->
- {bits,2,Val2};
- Range =< 8 ->
- {bits,3,Val2};
- Range =< 16 ->
- {bits,4,Val2};
- Range =< 32 ->
- {bits,5,Val2};
- Range =< 64 ->
- {bits,6,Val2};
- Range =< 128 ->
- {bits,7,Val2};
- Range =< 255 ->
- {bits,8,Val2};
- Range =< 256 ->
- {octets,1,Val2};
- Range =< 65536 ->
- {octets,2,Val2};
- Range =< 16#1000000 ->
- Octs = eint_positive(Val2),
- [encode_length({1,3},length(Octs)),{octets,Octs}];
- Range =< 16#100000000 ->
- Octs = eint_positive(Val2),
- [encode_length({1,4},length(Octs)),{octets,Octs}];
- Range =< 16#10000000000 ->
- Octs = eint_positive(Val2),
- [encode_length({1,5},length(Octs)),{octets,Octs}];
- true ->
- exit({not_supported,{integer_range,Range}})
- end.
-
-decode_constrained_number(Buffer,{Lb,Ub}) ->
- Range = Ub - Lb + 1,
-% Val2 = Val - Lb,
- {Val,Remain} =
- if
- Range == 2 ->
- getbits(Buffer,1);
- Range =< 4 ->
- getbits(Buffer,2);
- Range =< 8 ->
- getbits(Buffer,3);
- Range =< 16 ->
- getbits(Buffer,4);
- Range =< 32 ->
- getbits(Buffer,5);
- Range =< 64 ->
- getbits(Buffer,6);
- Range =< 128 ->
- getbits(Buffer,7);
- Range =< 255 ->
- getbits(Buffer,8);
- Range =< 256 ->
- getoctets(Buffer,1);
- Range =< 65536 ->
- getoctets(Buffer,2);
- Range =< 16#1000000 ->
- {Len,Bytes2} = decode_length(Buffer,{1,3}),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- {dec_pos_integer(Octs),Bytes3};
- Range =< 16#100000000 ->
- {Len,Bytes2} = decode_length(Buffer,{1,4}),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- {dec_pos_integer(Octs),Bytes3};
- Range =< 16#10000000000 ->
- {Len,Bytes2} = decode_length(Buffer,{1,5}),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- {dec_pos_integer(Octs),Bytes3};
- true ->
- exit({not_supported,{integer_range,Range}})
- end,
- {Val+Lb,Remain}.
-
-% X.691:10.8 Encoding of an unconstrained whole number
-
-encode_unconstrained_number(Val) when Val >= 0 ->
- Oct = eint(Val,[]),
- [{debug,unconstrained_number},
- encode_length({0,'MAX'},length(Oct)),
- {octets,Oct}];
-encode_unconstrained_number(Val) -> % negative
- Oct = enint(Val,[]),
- [{debug,unconstrained_number},
- encode_length({0,'MAX'},length(Oct)),
- {octets,Oct}].
-
-%% used for positive Values which don't need a sign bit
-eint_positive(Val) ->
- case eint(Val,[]) of
- [0,B1|T] ->
- [B1|T];
- T ->
- T
- end.
-
-eint(0, [B|Acc]) when B < 128 ->
- [B|Acc];
-eint(N, Acc) ->
- eint(N bsr 8, [N band 16#ff| Acc]).
-
-enint(-1, [B1|T]) when B1 > 127 ->
- [B1|T];
-enint(N, Acc) ->
- enint(N bsr 8, [N band 16#ff|Acc]).
-
-%% used for signed positive values
-
-%eint(Val, Ack) ->
-% X = Val band 255,
-% Next = Val bsr 8,
-% if
-% Next == 0, X >= 127 ->
-% [0,X|Ack];
-% Next == 0 ->
-% [X|Ack];
-% true ->
-% eint(Next,[X|Ack])
-% end.
-
-%%% used for signed negative values
-%enint(Val, Acc) ->
-% NumOctets = if
-% -Val < 16#80 -> 1;
-% -Val < 16#8000 ->2;
-% -Val < 16#800000 ->3;
-% -Val < 16#80000000 ->4;
-% -Val < 16#8000000000 ->5;
-% -Val < 16#800000000000 ->6;
-% -Val < 16#80000000000000 ->7;
-% -Val < 16#8000000000000000 ->8;
-% -Val < 16#800000000000000000 ->9
-% end,
-% enint(Val,Acc,NumOctets).
-
-%enint(Val, Acc,0) ->
-% Acc;
-%enint(Val, Acc,NumOctets) ->
-% enint(Val bsr 8,[Val band 255|Acc],NumOctets-1).
-
-
-decode_unconstrained_number(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {Ints,Bytes3} = getoctets_as_list(Bytes2,Len),
- {dec_integer(Ints),Bytes3}.
-
-dec_pos_integer(Ints) ->
- decpint(Ints, 8 * (length(Ints) - 1)).
-dec_integer(Ints) when hd(Ints) band 255 =< 127 -> %% Positive number
- decpint(Ints, 8 * (length(Ints) - 1));
-dec_integer(Ints) -> %% Negative
- decnint(Ints, 8 * (length(Ints) - 1)).
-
-decpint([Byte|Tail], Shift) ->
- (Byte bsl Shift) bor decpint(Tail, Shift-8);
-decpint([], _) -> 0.
-
-decnint([Byte|Tail], Shift) ->
- (-128 + (Byte band 127) bsl Shift) bor decpint(Tail, Shift-8).
-
-minimum_octets(Val) ->
- minimum_octets(Val,[]).
-
-minimum_octets(Val,Acc) when Val > 0 ->
- minimum_octets((Val bsr 8),[Val band 16#FF|Acc]);
-minimum_octets(0,Acc) ->
- Acc.
-
-
-%% X.691:10.9 Encoding of a length determinant
-%%encode_small_length(undefined,Len) -> % null means no UpperBound
-%% encode_small_number(Len).
-
-%% X.691:10.9.3.5
-%% X.691:10.9.3.7
-encode_length(undefined,Len) -> % un-constrained
- if
- Len < 128 ->
- {octet,Len band 16#7F};
- Len < 16384 ->
- {octets,2,2#1000000000000000 bor Len};
- true ->
- exit({error,{asn1,{encode_length,{nyi,above_16k}}}})
- end;
-
-encode_length({0,'MAX'},Len) ->
- encode_length(undefined,Len);
-encode_length({Lb,Ub},Len) when Ub =< 65535 ,Lb >= 0 -> % constrained
- encode_constrained_number({Lb,Ub},Len);
-encode_length({{Lb,Ub},[]},Len) when Ub =< 65535 ,Lb >= 0 ->
- %% constrained extensible
- [{bit,0},encode_constrained_number({Lb,Ub},Len)];
-encode_length(SingleValue,_) when integer(SingleValue) ->
- [].
-
-encode_small_length(Len) when Len =< 64 ->
- [{bit,0},{bits,6,Len-1}];
-encode_small_length(Len) ->
- [{bit,1},encode_length(undefined,Len)].
-
-decode_small_length(Buffer) ->
- case getbit(Buffer) of
- {0,Remain} ->
- {Bits,Remain2} = getbits(Remain,6),
- {Bits+1,Remain2};
- {1,Remain} ->
- decode_length(Remain,undefined)
- end.
-
-decode_length(Buffer) ->
- decode_length(Buffer,undefined).
-
-decode_length(Buffer,undefined) -> % un-constrained
- Buffer2 = align(Buffer),
- {Bits,_} = getbits(Buffer2,2),
- case Bits of
- 2 ->
- {Val,Bytes3} = getoctets(Buffer2,2),
- {(Val band 16#3FFF),Bytes3};
- 3 ->
- exit({error,{asn1,{decode_length,{nyi,above_16k}}}});
- _ ->
- {Val,Bytes3} = getoctet(Buffer2),
- {Val band 16#7F,Bytes3}
- end;
-
-decode_length(Buffer,{Lb,Ub}) when Ub =< 65535 ,Lb >= 0 -> % constrained
- decode_constrained_number(Buffer,{Lb,Ub});
-
-decode_length(Buffer,{{Lb,Ub},[]}) ->
- case getbit(Buffer) of
- {0,Buffer2} ->
- decode_length(Buffer2, {Lb,Ub})
- end;
- % X.691:10.9.3.5
-decode_length(Buffer,{_,_Lb,_Ub}) -> %when Len =< 127 -> % Unconstrained or large Ub
- case getbit(Buffer) of
- {0,Remain} ->
- getbits(Remain,7);
- {1,_Remain} ->
- {Val,Remain2} = getoctets(Buffer,2),
- {Val band 2#0111111111111111, Remain2}
- end;
-decode_length(Buffer,SingleValue) when integer(SingleValue) ->
- {SingleValue,Buffer}.
-
-
-% X.691:11
-encode_boolean({Name,Val}) when atom(Name) ->
- encode_boolean(Val);
-encode_boolean(true) ->
- {bit,1};
-encode_boolean(false) ->
- {bit,0};
-encode_boolean(Val) ->
- exit({error,{asn1,{encode_boolean,Val}}}).
-
-
-decode_boolean(Buffer) -> %when record(Buffer,buffer)
- case getbit(Buffer) of
- {1,Remain} -> {true,Remain};
- {0,Remain} -> {false,Remain}
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% X.691:12
-%% ENUMERATED
-%%
-%% encode_enumerated(C,Value,NamedNumberTup) -> CompleteList
-%%
-%%
-
-encode_enumerated(C,{Name,Value},NamedNumberList) when
- atom(Name),list(NamedNumberList) ->
- encode_enumerated(C,Value,NamedNumberList);
-
-%% ENUMERATED with extension mark
-encode_enumerated(_C,{asn1_enum,Value},{_Nlist1,Nlist2}) when Value >= length(Nlist2) ->
- [{bit,1},encode_small_number(Value)];
-encode_enumerated(C,Value,{Nlist1,Nlist2}) ->
- case enum_search(Value,Nlist1,0) of
- NewV when integer(NewV) ->
- [{bit,0},encode_integer(C,NewV)];
- false ->
- case enum_search(Value,Nlist2,0) of
- ExtV when integer(ExtV) ->
- [{bit,1},encode_small_number(ExtV)];
- false ->
- exit({error,{asn1,{encode_enumerated,Value}}})
- end
- end;
-
-encode_enumerated(C,Value,NamedNumberList) when list(NamedNumberList) ->
- case enum_search(Value,NamedNumberList,0) of
- NewV when integer(NewV) ->
- encode_integer(C,NewV);
- false ->
- exit({error,{asn1,{encode_enumerated,Value}}})
- end.
-
-%% returns the ordinal number from 0 ,1 ... in the list where Name is found
-%% or false if not found
-%%
-enum_search(Name,[Name|_NamedNumberList],Acc) ->
- Acc;
-enum_search(Name,[_H|T],Acc) ->
- enum_search(Name,T,Acc+1);
-enum_search(_,[],_) ->
- false. % name not found !error
-
-%% ENUMERATED with extension marker
-decode_enumerated(Buffer,C,{Ntup1,Ntup2}) when tuple(Ntup1), tuple(Ntup2) ->
- {Ext,Buffer2} = getext(Buffer),
- case Ext of
- 0 -> % not an extension value
- {Val,Buffer3} = decode_integer(Buffer2,C),
- case catch (element(Val+1,Ntup1)) of
- NewVal when atom(NewVal) -> {NewVal,Buffer3};
- _Error -> exit({error,{asn1,{decode_enumerated,{Val,[Ntup1,Ntup2]}}}})
- end;
- 1 -> % this an extension value
- {Val,Buffer3} = decode_small_number(Buffer2),
- case catch (element(Val+1,Ntup2)) of
- NewVal when atom(NewVal) -> {NewVal,Buffer3};
- _ -> {{asn1_enum,Val},Buffer3}
- end
- end;
-
-decode_enumerated(Buffer,C,NamedNumberTup) when tuple(NamedNumberTup) ->
- {Val,Buffer2} = decode_integer(Buffer,C),
- case catch (element(Val+1,NamedNumberTup)) of
- NewVal when atom(NewVal) -> {NewVal,Buffer2};
- _Error -> exit({error,{asn1,{decode_enumerated,{Val,NamedNumberTup}}}})
- end.
-
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-%% Bitstring value, ITU_T X.690 Chapter 8.5
-%%===============================================================================
-%%===============================================================================
-%%===============================================================================
-
-%%===============================================================================
-%% encode bitstring value
-%%===============================================================================
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% bitstring NamedBitList
-%% Val can be of:
-%% - [identifiers] where only named identifers are set to one,
-%% the Constraint must then have some information of the
-%% bitlength.
-%% - [list of ones and zeroes] all bits
-%% - integer value representing the bitlist
-%% C is constraint Len, only valid when identifiers
-
-
-%% when the value is a list of {Unused,BinBits}, where
-%% Unused = integer(),
-%% BinBits = binary().
-encode_bit_string(C,Bin={Unused,BinBits},NamedBitList) when integer(Unused),
- binary(BinBits) ->
- encode_bin_bit_string(C,Bin,NamedBitList);
-
-%% when the value is a list of named bits
-encode_bit_string(C, [FirstVal | RestVal], NamedBitList) when atom(FirstVal) ->
- ToSetPos = get_all_bitposes([FirstVal | RestVal], NamedBitList, []),
- BitList = make_and_set_list(ToSetPos,0),
- encode_bit_string(C,BitList,NamedBitList);
-
-encode_bit_string(C, [{bit,No} | RestVal], NamedBitList) ->
- ToSetPos = get_all_bitposes([{bit,No} | RestVal], NamedBitList, []),
- BitList = make_and_set_list(ToSetPos,0),
- encode_bit_string(C,BitList,NamedBitList);
-
-%% when the value is a list of ones and zeroes
-
-encode_bit_string(C, BitListValue, NamedBitList) when list(BitListValue) ->
- Bl1 =
- case NamedBitList of
- [] -> % dont remove trailing zeroes
- BitListValue;
- _ -> % first remove any trailing zeroes
- lists:reverse(lists:dropwhile(fun(0)->true;(1)->false end,
- lists:reverse(BitListValue)))
- end,
- BitList = [{bit,X} || X <- Bl1],
- BListLen = length(BitList),
- case get_constraint(C,'SizeConstraint') of
- 0 -> % fixed length
- []; % nothing to encode
- V when integer(V),V=<16 -> % fixed length 16 bits or less
- pad_list(V,BitList);
- V when integer(V) -> % fixed length 16 bits or less
- [align,pad_list(V,BitList)];
- {Lb,Ub} when integer(Lb),integer(Ub),BListLen<Lb ->
- %% padding due to OTP-4353
- [encode_length({Lb,Ub},Lb),align,pad_list(Lb,BitList)];
- {Lb,Ub} when integer(Lb),integer(Ub) ->
- [encode_length({Lb,Ub},length(BitList)),align,BitList];
- no ->
- [encode_length(undefined,length(BitList)),align,BitList];
- Sc={{Lb,Ub},_} when integer(Lb),integer(Ub),BListLen<Lb ->
- %% padding due to OTP-4353
- [encode_length(Sc,Lb),align,pad_list(Lb,BitList)];
- Sc -> % extension marker
- [encode_length(Sc,length(BitList)),align,BitList]
- end;
-
-%% when the value is an integer
-encode_bit_string(C, IntegerVal, NamedBitList) when integer(IntegerVal)->
- BitList = int_to_bitlist(IntegerVal),
- encode_bit_string(C,BitList,NamedBitList);
-
-%% when the value is a tuple
-encode_bit_string(C,{Name,Val}, NamedBitList) when atom(Name) ->
- encode_bit_string(C,Val,NamedBitList).
-
-
-%% encode_bin_bit_string/3, when value is a tuple of Unused and BinBits.
-%% Unused = integer(),
-%% BinBits = binary().
-
-encode_bin_bit_string(C,{Unused,BinBits},NamedBitList) ->
- RemoveZerosIfNNL =
- fun({NNL,BitList}) ->
- case NNL of
- [] -> BitList;
- _ ->
- lists:reverse(
- lists:dropwhile(fun(0)->true;(1)->false end,
- lists:reverse(BitList)))
- end
- end,
- {OctetList,OLSize,LastBits} =
- case size(BinBits) of
- N when N>1 ->
- IntList = binary_to_list(BinBits),
- [H|T] = lists:reverse(IntList),
- Bl1 = RemoveZerosIfNNL({NamedBitList,lists:reverse(int_to_bitlist(H,8-Unused))}),% lists:sublist obsolete if trailing bits are zero !
- {[{octet,X} || X <- lists:reverse(T)],size(BinBits)-1,
- [{bit,X} || X <- Bl1]};
- 1 ->
- <<B7:1,B6:1,B5:1,B4:1,B3:1,B2:1,B1:1,B0:1>> = BinBits,
- {[],0,[{bit,X} || X <- lists:sublist([B7,B6,B5,B4,B3,B2,B1,B0],8-Unused)]};
- _ ->
- {[],0,[]}
- end,
- case get_constraint(C,'SizeConstraint') of
- 0 ->
- [];
- V when integer(V),V=<16 ->
- [OctetList, pad_list(V,LastBits)];
- V when integer(V) ->
-% [OctetList, align, pad_list(V rem 8,LastBits)];
- [align,OctetList, pad_list(V rem 8,LastBits)];
- {Lb,Ub} when integer(Lb),integer(Ub) ->
- NewLastBits = maybe_pad(Lb,length(LastBits)+(OLSize*8),LastBits,NamedBitList),
- [encode_length({Lb,Ub},length(NewLastBits)+(OLSize*8)),
-% OctetList,align,LastBits];
- align,OctetList,NewLastBits];
- no ->
- [encode_length(undefined,length(LastBits)+(OLSize*8)),
-% OctetList,align,LastBits];
- align,OctetList,LastBits];
- Sc={{Lb,_},_} when integer(Lb) ->
- NewLastBits = maybe_pad(Lb,length(LastBits)+(OLSize*8),LastBits,NamedBitList),
- [encode_length(Sc,length(NewLastBits)+(OLSize*8)),
- align,OctetList,NewLastBits];
- Sc ->
- [encode_length(Sc,length(LastBits)+(OLSize*8)),
-% OctetList,align,LastBits]
- align,OctetList,LastBits]
- end.
-
-maybe_pad(_,_,Bits,[]) ->
- Bits;
-maybe_pad(Lb,LenBits,Bits,_) when Lb>LenBits ->
- pad_list(Lb,Bits);
-maybe_pad(_,_,Bits,_) ->
- Bits.
-
-%%%%%%%%%%%%%%%
-%% The result is presented as a list of named bits (if possible)
-%% else as a tuple {Unused,Bits}. Unused is the number of unused
-%% bits, least significant bits in the last byte of Bits. Bits is
-%% the BIT STRING represented as a binary.
-%%
-decode_compact_bit_string(Buffer, C, NamedNumberList) ->
- case get_constraint(C,'SizeConstraint') of
- 0 -> % fixed length
- {{0,<<>>},Buffer};
- V when integer(V),V=<16 -> %fixed length 16 bits or less
- compact_bit_string(Buffer,V,NamedNumberList);
- V when integer(V) -> %fixed length > 16 bits
- Bytes2 = align(Buffer),
- compact_bit_string(Bytes2,V,NamedNumberList);
- {Lb,Ub} when integer(Lb),integer(Ub) ->
- {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
- Bytes3 = align(Bytes2),
- compact_bit_string(Bytes3,Len,NamedNumberList);
- no ->
- {Len,Bytes2} = decode_length(Buffer,undefined),
- Bytes3 = align(Bytes2),
- compact_bit_string(Bytes3,Len,NamedNumberList);
- Sc ->
- {Len,Bytes2} = decode_length(Buffer,Sc),
- Bytes3 = align(Bytes2),
- compact_bit_string(Bytes3,Len,NamedNumberList)
- end.
-
-
-%%%%%%%%%%%%%%%
-%% The result is presented as a list of named bits (if possible)
-%% else as a list of 0 and 1.
-%%
-decode_bit_string(Buffer, C, NamedNumberList) ->
- case get_constraint(C,'SizeConstraint') of
- 0 -> % fixed length
- {[],Buffer}; % nothing to encode
- V when integer(V),V=<16 -> % fixed length 16 bits or less
- bit_list_to_named(Buffer,V,NamedNumberList);
- V when integer(V) -> % fixed length 16 bits or less
- Bytes2 = align(Buffer),
- bit_list_to_named(Bytes2,V,NamedNumberList);
- {Lb,Ub} when integer(Lb),integer(Ub) ->
- {Len,Bytes2} = decode_length(Buffer,{Lb,Ub}),
- Bytes3 = align(Bytes2),
- bit_list_to_named(Bytes3,Len,NamedNumberList);
- no ->
- {Len,Bytes2} = decode_length(Buffer,undefined),
- Bytes3 = align(Bytes2),
- bit_list_to_named(Bytes3,Len,NamedNumberList);
- Sc -> % extension marker
- {Len,Bytes2} = decode_length(Buffer,Sc),
- Bytes3 = align(Bytes2),
- bit_list_to_named(Bytes3,Len,NamedNumberList)
- end.
-
-
-%% if no named bits are declared we will return a
-%% {Unused,Bits}. Unused = integer(),
-%% Bits = binary().
-compact_bit_string(Buffer,Len,[]) ->
- getbits_as_binary(Len,Buffer); % {{Unused,BinBits},NewBuffer}
-compact_bit_string(Buffer,Len,NamedNumberList) ->
- bit_list_to_named(Buffer,Len,NamedNumberList).
-
-
-%% if no named bits are declared we will return a
-%% BitList = [0 | 1]
-
-bit_list_to_named(Buffer,Len,[]) ->
- getbits_as_list(Len,Buffer);
-
-%% if there are named bits declared we will return a named
-%% BitList where the names are atoms and unnamed bits represented
-%% as {bit,Pos}
-%% BitList = [atom() | {bit,Pos}]
-%% Pos = integer()
-
-bit_list_to_named(Buffer,Len,NamedNumberList) ->
- {BitList,Rest} = getbits_as_list(Len,Buffer),
- {bit_list_to_named1(0,BitList,NamedNumberList,[]), Rest}.
-
-bit_list_to_named1(Pos,[0|Bt],Names,Acc) ->
- bit_list_to_named1(Pos+1,Bt,Names,Acc);
-bit_list_to_named1(Pos,[1|Bt],Names,Acc) ->
- case lists:keysearch(Pos,2,Names) of
- {value,{Name,_}} ->
- bit_list_to_named1(Pos+1,Bt,Names,[Name|Acc]);
- _ ->
- bit_list_to_named1(Pos+1,Bt,Names,[{bit,Pos}|Acc])
- end;
-bit_list_to_named1(_Pos,[],_Names,Acc) ->
- lists:reverse(Acc).
-
-
-
-%%%%%%%%%%%%%%%
-%%
-
-int_to_bitlist(0) ->
- [];
-int_to_bitlist(Int) when integer(Int), Int >= 0 ->
- [Int band 1 | int_to_bitlist(Int bsr 1)].
-
-int_to_bitlist(_Int,0) ->
- [];
-int_to_bitlist(0,N) ->
- [0|int_to_bitlist(0,N-1)];
-int_to_bitlist(Int,N) ->
- [Int band 1 | int_to_bitlist(Int bsr 1, N-1)].
-
-
-%%%%%%%%%%%%%%%%%%
-%% get_all_bitposes([list of named bits to set], named_bit_db, []) ->
-%% [sorted_list_of_bitpositions_to_set]
-
-get_all_bitposes([{bit,ValPos}|Rest], NamedBitList, Ack) ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack ]);
-
-get_all_bitposes([Val | Rest], NamedBitList, Ack) ->
- case lists:keysearch(Val, 1, NamedBitList) of
- {value, {_ValName, ValPos}} ->
- get_all_bitposes(Rest, NamedBitList, [ValPos | Ack]);
- _ ->
- exit({error,{asn1, {bitstring_namedbit, Val}}})
- end;
-get_all_bitposes([], _NamedBitList, Ack) ->
- lists:sort(Ack).
-
-%%%%%%%%%%%%%%%%%%
-%% make_and_set_list([list of positions to set to 1])->
-%% returns list with all in SetPos set.
-%% in positioning in list the first element is 0, the second 1 etc.., but
-%%
-
-make_and_set_list([XPos|SetPos], XPos) ->
- [1 | make_and_set_list(SetPos, XPos + 1)];
-make_and_set_list([Pos|SetPos], XPos) ->
- [0 | make_and_set_list([Pos | SetPos], XPos + 1)];
-make_and_set_list([], _XPos) ->
- [].
-
-%%%%%%%%%%%%%%%%%
-%% pad_list(N,BitList) -> PaddedList
-%% returns a padded (with trailing {bit,0} elements) list of length N
-%% if Bitlist contains more than N significant bits set an exit asn1_error
-%% is generated
-
-pad_list(0,BitList) ->
- case BitList of
- [] -> [];
- _ -> exit({error,{asn1,{range_error,{bit_string,BitList}}}})
- end;
-pad_list(N,[Bh|Bt]) ->
- [Bh|pad_list(N-1,Bt)];
-pad_list(N,[]) ->
- [{bit,0},pad_list(N-1,[])].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% X.691:16
-%% encode_octet_string(Constraint,ExtensionMarker,Val)
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-encode_octet_string(C,{Name,Val}) when atom(Name) ->
- encode_octet_string(C,false,Val);
-encode_octet_string(C,Val) ->
- encode_octet_string(C,false,Val).
-
-encode_octet_string(C,Bool,{_Name,Val}) ->
- encode_octet_string(C,Bool,Val);
-encode_octet_string(_,true,_) ->
- exit({error,{asn1,{'not_supported',extensionmarker}}});
-encode_octet_string(C,false,Val) ->
- case get_constraint(C,'SizeConstraint') of
- 0 ->
- [];
- 1 ->
- [V] = Val,
- {bits,8,V};
- 2 ->
- [V1,V2] = Val,
- [{bits,8,V1},{bits,8,V2}];
- Sv when Sv =<65535, Sv == length(Val) -> % fixed length
- [align,{octets,Val}];
- {Lb,Ub} ->
- [encode_length({Lb,Ub},length(Val)),align,
- {octets,Val}];
- Sv when list(Sv) ->
- [encode_length({hd(Sv),lists:max(Sv)},length(Val)),align,
- {octets,Val}];
- no ->
- [encode_length(undefined,length(Val)),align,
- {octets,Val}]
- end.
-
-decode_octet_string(Bytes,Range) ->
- decode_octet_string(Bytes,Range,false).
-
-decode_octet_string(Bytes,C,false) ->
- case get_constraint(C,'SizeConstraint') of
- 0 ->
- {[],Bytes};
- 1 ->
- {B1,Bytes2} = getbits(Bytes,8),
- {[B1],Bytes2};
- 2 ->
- {B1,Bytes2}= getbits(Bytes,8),
- {B2,Bytes3}= getbits(Bytes2,8),
- {[B1,B2],Bytes3};
- {_,0} ->
- {[],Bytes};
- Sv when integer(Sv), Sv =<65535 -> % fixed length
- Bytes2 = align(Bytes),
- getoctets_as_list(Bytes2,Sv);
- {Lb,Ub} ->
- {Len,Bytes2} = decode_length(Bytes,{Lb,Ub}),
- Bytes3 = align(Bytes2),
- getoctets_as_list(Bytes3,Len);
- Sv when list(Sv) ->
- {Len,Bytes2} = decode_length(Bytes,{hd(Sv),lists:max(Sv)}),
- Bytes3 = align(Bytes2),
- getoctets_as_list(Bytes3,Len);
- no ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- Bytes3 = align(Bytes2),
- getoctets_as_list(Bytes3,Len)
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Restricted char string types
-%% (NumericString, PrintableString,VisibleString,IA5String,BMPString,UniversalString)
-%% X.691:26 and X.680:34-36
-%%encode_restricted_string(aligned,'BMPString',Constraints,Extension,Val)
-
-
-encode_restricted_string(aligned,{Name,Val}) when atom(Name) ->
- encode_restricted_string(aligned,Val);
-
-encode_restricted_string(aligned,Val) when list(Val)->
- [encode_length(undefined,length(Val)),align,
- {octets,Val}].
-
-encode_known_multiplier_string(aligned,StringType,C,_Ext,{Name,Val}) when atom(Name) ->
- encode_known_multiplier_string(aligned,StringType,C,false,Val);
-
-encode_known_multiplier_string(aligned,StringType,C,_Ext,Val) ->
- Result = chars_encode(C,StringType,Val),
- NumBits = get_NumBits(C,StringType),
- case get_constraint(C,'SizeConstraint') of
- Ub when integer(Ub), Ub*NumBits =< 16 ->
- case {StringType,Result} of
- {'BMPString',{octets,Ol}} ->
- [{bits,8,Oct}||Oct <- Ol];
- _ ->
- Result
- end;
- 0 ->
- [];
- Ub when integer(Ub),Ub =<65535 -> % fixed length
- [align,Result];
- {Ub,Lb} ->
- [encode_length({Ub,Lb},length(Val)),align,Result];
- Vl when list(Vl) ->
- [encode_length({lists:min(Vl),lists:max(Vl)},length(Val)),align,Result];
- no ->
- [encode_length(undefined,length(Val)),align,Result]
- end.
-
-decode_restricted_string(Bytes,aligned) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- Bytes3 = align(Bytes2),
- getoctets_as_list(Bytes3,Len).
-
-decode_known_multiplier_string(Bytes,aligned,StringType,C,_Ext) ->
- NumBits = get_NumBits(C,StringType),
- case get_constraint(C,'SizeConstraint') of
- Ub when integer(Ub), Ub*NumBits =< 16 ->
- chars_decode(Bytes,NumBits,StringType,C,Ub);
- Ub when integer(Ub),Ub =<65535 -> % fixed length
- Bytes1 = align(Bytes),
- chars_decode(Bytes1,NumBits,StringType,C,Ub);
- 0 ->
- {[],Bytes};
- Vl when list(Vl) ->
- {Len,Bytes1} = decode_length(Bytes,{hd(Vl),lists:max(Vl)}),
- Bytes2 = align(Bytes1),
- chars_decode(Bytes2,NumBits,StringType,C,Len);
- no ->
- {Len,Bytes1} = decode_length(Bytes,undefined),
- Bytes2 = align(Bytes1),
- chars_decode(Bytes2,NumBits,StringType,C,Len);
- {Lb,Ub}->
- {Len,Bytes1} = decode_length(Bytes,{Lb,Ub}),
- Bytes2 = align(Bytes1),
- chars_decode(Bytes2,NumBits,StringType,C,Len)
- end.
-
-
-encode_NumericString(C,Val) ->
- encode_known_multiplier_string(aligned,'NumericString',C,false,Val).
-decode_NumericString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,aligned,'NumericString',C,false).
-
-encode_PrintableString(C,Val) ->
- encode_known_multiplier_string(aligned,'PrintableString',C,false,Val).
-decode_PrintableString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,aligned,'PrintableString',C,false).
-
-encode_VisibleString(C,Val) -> % equivalent with ISO646String
- encode_known_multiplier_string(aligned,'VisibleString',C,false,Val).
-decode_VisibleString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,aligned,'VisibleString',C,false).
-
-encode_IA5String(C,Val) ->
- encode_known_multiplier_string(aligned,'IA5String',C,false,Val).
-decode_IA5String(Bytes,C) ->
- decode_known_multiplier_string(Bytes,aligned,'IA5String',C,false).
-
-encode_BMPString(C,Val) ->
- encode_known_multiplier_string(aligned,'BMPString',C,false,Val).
-decode_BMPString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,aligned,'BMPString',C,false).
-
-encode_UniversalString(C,Val) ->
- encode_known_multiplier_string(aligned,'UniversalString',C,false,Val).
-decode_UniversalString(Bytes,C) ->
- decode_known_multiplier_string(Bytes,aligned,'UniversalString',C,false).
-
-%% end of known-multiplier strings for which PER visible constraints are
-%% applied
-
-encode_GeneralString(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_GeneralString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_GraphicString(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_GraphicString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_ObjectDescriptor(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_ObjectDescriptor(Bytes) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_TeletexString(_C,Val) -> % equivalent with T61String
- encode_restricted_string(aligned,Val).
-decode_TeletexString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-encode_VideotexString(_C,Val) ->
- encode_restricted_string(aligned,Val).
-decode_VideotexString(Bytes,_C) ->
- decode_restricted_string(Bytes,aligned).
-
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% getBMPChars(Bytes,Len) ->{BMPcharList,RemainingBytes}
-%%
-getBMPChars(Bytes,1) ->
- {O1,Bytes2} = getbits(Bytes,8),
- {O2,Bytes3} = getbits(Bytes2,8),
- if
- O1 == 0 ->
- {[O2],Bytes3};
- true ->
- {[{0,0,O1,O2}],Bytes3}
- end;
-getBMPChars(Bytes,Len) ->
- getBMPChars(Bytes,Len,[]).
-
-getBMPChars(Bytes,0,Acc) ->
- {lists:reverse(Acc),Bytes};
-getBMPChars(Bytes,Len,Acc) ->
- {Octs,Bytes1} = getoctets_as_list(Bytes,2),
- case Octs of
- [0,O2] ->
- getBMPChars(Bytes1,Len-1,[O2|Acc]);
- [O1,O2]->
- getBMPChars(Bytes1,Len-1,[{0,0,O1,O2}|Acc])
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% chars_encode(C,StringType,Value) -> ValueList
-%%
-%% encodes chars according to the per rules taking the constraint PermittedAlphabet
-%% into account.
-%% This function does only encode the value part and NOT the length
-
-chars_encode(C,StringType,Value) ->
- case {StringType,get_constraint(C,'PermittedAlphabet')} of
- {'UniversalString',{_,_Sv}} ->
- exit({error,{asn1,{'not implemented',"UniversalString with PermittedAlphabet constraint"}}});
- {'BMPString',{_,_Sv}} ->
- exit({error,{asn1,{'not implemented',"BMPString with PermittedAlphabet constraint"}}});
- _ ->
- {NumBits,CharOutTab} = {get_NumBits(C,StringType),get_CharOutTab(C,StringType)},
- chars_encode2(Value,NumBits,CharOutTab)
- end.
-
-chars_encode2([H|T],NumBits,{Min,Max,notab}) when H =< Max, H >= Min ->
- [{bits,NumBits,H-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
-chars_encode2([H|T],NumBits,{Min,Max,Tab}) when H =< Max, H >= Min ->
- [{bits,NumBits,element(H-Min+1,Tab)}|chars_encode2(T,NumBits,{Min,Max,Tab})];
-chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,notab}) ->
- %% no value range check here (ought to be, but very expensive)
-% [{bits,NumBits,(A*B*C*D)-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
- [{bits,NumBits,((((((A bsl 8) + B) bsl 8) + C) bsl 8) + D)-Min}|chars_encode2(T,NumBits,{Min,Max,notab})];
-chars_encode2([{A,B,C,D}|T],NumBits,{Min,Max,Tab}) ->
- %% no value range check here (ought to be, but very expensive)
-% [{bits,NumBits,element((A*B*C*D)-Min,Tab)}|chars_encode2(T,NumBits,{Min,Max,notab})];
- [{bits,NumBits,element(((((((A bsl 8)+B) bsl 8)+C) bsl 8)+D)-Min,Tab)}|chars_encode2(T,NumBits,{Min,Max,notab})];
-chars_encode2([H|_T],_,{_,_,_}) ->
- exit({error,{asn1,{illegal_char_value,H}}});
-chars_encode2([],_,_) ->
- [].
-
-
-get_NumBits(C,StringType) ->
- case get_constraint(C,'PermittedAlphabet') of
- {'SingleValue',Sv} ->
- charbits(length(Sv),aligned);
- no ->
- case StringType of
- 'IA5String' ->
- charbits(128,aligned); % 16#00..16#7F
- 'VisibleString' ->
- charbits(95,aligned); % 16#20..16#7E
- 'PrintableString' ->
- charbits(74,aligned); % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
- 'NumericString' ->
- charbits(11,aligned); % $ ,"0123456789"
- 'UniversalString' ->
- 32;
- 'BMPString' ->
- 16
- end
- end.
-
-%%Maybe used later
-%%get_MaxChar(C,StringType) ->
-%% case get_constraint(C,'PermittedAlphabet') of
-%% {'SingleValue',Sv} ->
-%% lists:nth(length(Sv),Sv);
-%% no ->
-%% case StringType of
-%% 'IA5String' ->
-%% 16#7F; % 16#00..16#7F
-%% 'VisibleString' ->
-%% 16#7E; % 16#20..16#7E
-%% 'PrintableString' ->
-%% $z; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
-%% 'NumericString' ->
-%% $9; % $ ,"0123456789"
-%% 'UniversalString' ->
-%% 16#ffffffff;
-%% 'BMPString' ->
-%% 16#ffff
-%% end
-%% end.
-
-%%Maybe used later
-%%get_MinChar(C,StringType) ->
-%% case get_constraint(C,'PermittedAlphabet') of
-%% {'SingleValue',Sv} ->
-%% hd(Sv);
-%% no ->
-%% case StringType of
-%% 'IA5String' ->
-%% 16#00; % 16#00..16#7F
-%% 'VisibleString' ->
-%% 16#20; % 16#20..16#7E
-%% 'PrintableString' ->
-%% $\s; % [$\s,$',$(,$),$+,$,,$-,$.,$/,"0123456789",$:,$=,$?,$A..$Z,$a..$z
-%% 'NumericString' ->
-%% $\s; % $ ,"0123456789"
-%% 'UniversalString' ->
-%% 16#00;
-%% 'BMPString' ->
-%% 16#00
-%% end
-%% end.
-
-get_CharOutTab(C,StringType) ->
- get_CharTab(C,StringType,out).
-
-get_CharInTab(C,StringType) ->
- get_CharTab(C,StringType,in).
-
-get_CharTab(C,StringType,InOut) ->
- case get_constraint(C,'PermittedAlphabet') of
- {'SingleValue',Sv} ->
- get_CharTab2(C,StringType,hd(Sv),lists:max(Sv),Sv,InOut);
- no ->
- case StringType of
- 'IA5String' ->
- {0,16#7F,notab};
- 'VisibleString' ->
- get_CharTab2(C,StringType,16#20,16#7F,notab,InOut);
- 'PrintableString' ->
- Chars = lists:sort(
- " '()+,-./0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
- get_CharTab2(C,StringType,hd(Chars),lists:max(Chars),Chars,InOut);
- 'NumericString' ->
- get_CharTab2(C,StringType,16#20,$9," 0123456789",InOut);
- 'UniversalString' ->
- {0,16#FFFFFFFF,notab};
- 'BMPString' ->
- {0,16#FFFF,notab}
- end
- end.
-
-get_CharTab2(C,StringType,Min,Max,Chars,InOut) ->
- BitValMax = (1 bsl get_NumBits(C,StringType))-1,
- if
- Max =< BitValMax ->
- {0,Max,notab};
- true ->
- case InOut of
- out ->
- {Min,Max,create_char_tab(Min,Chars)};
- in ->
- {Min,Max,list_to_tuple(Chars)}
- end
- end.
-
-create_char_tab(Min,L) ->
- list_to_tuple(create_char_tab(Min,L,0)).
-create_char_tab(Min,[Min|T],V) ->
- [V|create_char_tab(Min+1,T,V+1)];
-create_char_tab(_Min,[],_V) ->
- [];
-create_char_tab(Min,L,V) ->
- [false|create_char_tab(Min+1,L,V)].
-
-%% This very inefficient and should be moved to compiletime
-charbits(NumOfChars,aligned) ->
- case charbits(NumOfChars) of
- 1 -> 1;
- 2 -> 2;
- B when B > 2, B =< 4 -> 4;
- B when B > 4, B =< 8 -> 8;
- B when B > 8, B =< 16 -> 16;
- B when B > 16, B =< 32 -> 32
- end.
-
-charbits(NumOfChars) when NumOfChars =< 2 -> 1;
-charbits(NumOfChars) when NumOfChars =< 4 -> 2;
-charbits(NumOfChars) when NumOfChars =< 8 -> 3;
-charbits(NumOfChars) when NumOfChars =< 16 -> 4;
-charbits(NumOfChars) when NumOfChars =< 32 -> 5;
-charbits(NumOfChars) when NumOfChars =< 64 -> 6;
-charbits(NumOfChars) when NumOfChars =< 128 -> 7;
-charbits(NumOfChars) when NumOfChars =< 256 -> 8;
-charbits(NumOfChars) when NumOfChars =< 512 -> 9;
-charbits(NumOfChars) when NumOfChars =< 1024 -> 10;
-charbits(NumOfChars) when NumOfChars =< 2048 -> 11;
-charbits(NumOfChars) when NumOfChars =< 4096 -> 12;
-charbits(NumOfChars) when NumOfChars =< 8192 -> 13;
-charbits(NumOfChars) when NumOfChars =< 16384 -> 14;
-charbits(NumOfChars) when NumOfChars =< 32768 -> 15;
-charbits(NumOfChars) when NumOfChars =< 65536 -> 16;
-charbits(NumOfChars) when integer(NumOfChars) ->
- 16 + charbits1(NumOfChars bsr 16).
-
-charbits1(0) ->
- 0;
-charbits1(NumOfChars) ->
- 1 + charbits1(NumOfChars bsr 1).
-
-
-chars_decode(Bytes,_,'BMPString',C,Len) ->
- case get_constraint(C,'PermittedAlphabet') of
- no ->
- getBMPChars(Bytes,Len);
- _ ->
- exit({error,{asn1,
- {'not implemented',
- "BMPString with PermittedAlphabet constraint"}}})
- end;
-chars_decode(Bytes,NumBits,StringType,C,Len) ->
- CharInTab = get_CharInTab(C,StringType),
- chars_decode2(Bytes,CharInTab,NumBits,Len).
-
-
-chars_decode2(Bytes,CharInTab,NumBits,Len) ->
- chars_decode2(Bytes,CharInTab,NumBits,Len,[]).
-
-chars_decode2(Bytes,_CharInTab,_NumBits,0,Acc) ->
- {lists:reverse(Acc),Bytes};
-chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) when NumBits > 8 ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- Result = case minimum_octets(Char+Min) of
- [NewChar] -> NewChar;
- [C1,C2] -> {0,0,C1,C2};
- [C1,C2,C3] -> {0,C1,C2,C3};
- [C1,C2,C3,C4] -> {C1,C2,C3,C4}
- end,
- chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Result|Acc]);
-chars_decode2(Bytes,{Min,Max,notab},NumBits,Len,Acc) ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- chars_decode2(Bytes2,{Min,Max,notab},NumBits,Len -1,[Char+Min|Acc]);
-
-%% BMPString and UniversalString with PermittedAlphabet is currently not supported
-chars_decode2(Bytes,{Min,Max,CharInTab},NumBits,Len,Acc) ->
- {Char,Bytes2} = getbits(Bytes,NumBits),
- chars_decode2(Bytes2,{Min,Max,CharInTab},NumBits,Len -1,[element(Char+1,CharInTab)|Acc]).
-
-
- % X.691:17
-encode_null({Name,Val}) when atom(Name) ->
- encode_null(Val);
-encode_null(_) -> []. % encodes to nothing
-
-decode_null(Bytes) ->
- {'NULL',Bytes}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% encode_object_identifier(Val) -> CompleteList
-%% encode_object_identifier({Name,Val}) -> CompleteList
-%% Val -> {Int1,Int2,...,IntN} % N >= 2
-%% Name -> atom()
-%% Int1 -> integer(0..2)
-%% Int2 -> integer(0..39) when Int1 (0..1) else integer()
-%% Int3-N -> integer()
-%% CompleteList -> [{bits,8,Val}|{octets,Ol}|align|...]
-%%
-encode_object_identifier({Name,Val}) when atom(Name) ->
- encode_object_identifier(Val);
-encode_object_identifier(Val) ->
- Octets = e_object_identifier(Val,notag),
- [{debug,object_identifier},encode_length(undefined,length(Octets)),{octets,Octets}].
-
-%% This code is copied from asn1_encode.erl (BER) and corrected and modified
-
-e_object_identifier({'OBJECT IDENTIFIER',V},DoTag) ->
- e_object_identifier(V,DoTag);
-e_object_identifier({Cname,V},DoTag) when atom(Cname),tuple(V) ->
- e_object_identifier(tuple_to_list(V),DoTag);
-e_object_identifier({Cname,V},DoTag) when atom(Cname),list(V) ->
- e_object_identifier(V,DoTag);
-e_object_identifier(V,DoTag) when tuple(V) ->
- e_object_identifier(tuple_to_list(V),DoTag);
-
-% E1 = 0|1|2 and (E2 < 40 when E1 = 0|1)
-e_object_identifier([E1,E2|Tail],_DoTag) when E1 =< 2 ->
- Head = 40*E1 + E2, % weird
- Res = e_object_elements([Head|Tail]),
-% dotag(DoTag,[6],elength(length(Res)+1),[Head|Res]),
- Res.
-
-e_object_elements([]) ->
- [];
-e_object_elements([H|T]) ->
- lists:append(e_object_element(H),e_object_elements(T)).
-
-e_object_element(Num) when Num < 128 ->
- [Num];
-% must be changed to handle more than 2 octets
-e_object_element(Num) -> %% when Num < ???
- Left = ((Num band 2#11111110000000) bsr 7) bor 2#10000000,
- Right = Num band 2#1111111 ,
- [Left,Right].
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode_object_identifier(Bytes) -> {ObjId,RemainingBytes}
-%% ObjId -> {integer(),integer(),...} % at least 2 integers
-%% RemainingBytes -> [integer()] when integer() (0..255)
-decode_object_identifier(Bytes) ->
- {Len,Bytes2} = decode_length(Bytes,undefined),
- {Octs,Bytes3} = getoctets_as_list(Bytes2,Len),
- [First|Rest] = dec_subidentifiers(Octs,0,[]),
- Idlist = if
- First < 40 ->
- [0,First|Rest];
- First < 80 ->
- [1,First - 40|Rest];
- true ->
- [2,First - 80|Rest]
- end,
- {list_to_tuple(Idlist),Bytes3}.
-
-dec_subidentifiers([H|T],Av,Al) when H >=16#80 ->
- dec_subidentifiers(T,(Av bsl 7) + (H band 16#7F),Al);
-dec_subidentifiers([H|T],Av,Al) ->
- dec_subidentifiers(T,0,[(Av bsl 7) + H |Al]);
-dec_subidentifiers([],_Av,Al) ->
- lists:reverse(Al).
-
-get_constraint(C,Key) ->
- case lists:keysearch(Key,1,C) of
- false ->
- no;
- {value,{_,V}} ->
- V
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% complete(InList) -> ByteList
-%% Takes a coded list with bits and bytes and converts it to a list of bytes
-%% Should be applied as the last step at encode of a complete ASN.1 type
-%%
-complete(InList) when list(InList) ->
- complete(InList,[],0);
-complete(InList) ->
- complete([InList],[],0).
-
-complete([{debug,_}|T], Acc, Acclen) ->
- complete(T,Acc,Acclen);
-complete([H|T],Acc,Acclen) when list(H) ->
- complete(lists:concat([H,T]),Acc,Acclen);
-
-
-complete([{octets,N,Val}|T],Acc,Acclen) when N =< 4 ,integer(Val) ->
- Newval = case N of
- 1 ->
- Val4 = Val band 16#FF,
- [Val4];
- 2 ->
- Val3 = (Val bsr 8) band 16#FF,
- Val4 = Val band 16#FF,
- [Val3,Val4];
- 3 ->
- Val2 = (Val bsr 16) band 16#FF,
- Val3 = (Val bsr 8) band 16#FF,
- Val4 = Val band 16#FF,
- [Val2,Val3,Val4];
- 4 ->
- Val1 = (Val bsr 24) band 16#FF,
- Val2 = (Val bsr 16) band 16#FF,
- Val3 = (Val bsr 8) band 16#FF,
- Val4 = Val band 16#FF,
- [Val1,Val2,Val3,Val4]
- end,
- complete([{octets,Newval}|T],Acc,Acclen);
-
-complete([{octets,Oct}|T],[],_Acclen) when list(Oct) ->
- complete(T,lists:reverse(Oct),0);
-complete([{octets,Oct}|T],[Hacc|Tacc],Acclen) when list(Oct) ->
- Rest = 8 - Acclen,
- if
- Rest == 8 ->
- complete(T,lists:concat([lists:reverse(Oct),[Hacc|Tacc]]),0);
- true ->
- complete(T,lists:concat([lists:reverse(Oct),[Hacc bsl Rest|Tacc]]),0)
- end;
-
-complete([{bit,Val}|T], Acc, Acclen) ->
- complete([{bits,1,Val}|T],Acc,Acclen);
-complete([{octet,Val}|T], Acc, Acclen) ->
- complete([{octets,1,Val}|T],Acc,Acclen);
-
-complete([{bits,N,Val}|T], Acc, 0) when N =< 8 ->
- complete(T,[Val|Acc],N);
-complete([{bits,N,Val}|T], [Hacc|Tacc], Acclen) when N =< 8 ->
- Rest = 8 - Acclen,
- if
- Rest >= N ->
- complete(T,[(Hacc bsl N) + Val|Tacc],(Acclen+N) rem 8);
- true ->
- Diff = N - Rest,
- NewHacc = (Hacc bsl Rest) + (Val bsr Diff),
- Mask = element(Diff,{1,3,7,15,31,63,127,255}),
- complete(T,[(Val band Mask),NewHacc|Tacc],(Acclen+N) rem 8)
- end;
-complete([{bits,N,Val}|T], Acc, Acclen) -> % N > 8
- complete([{bits,N-8,Val bsr 8},{bits,8,Val band 255}|T],Acc,Acclen);
-
-complete([align|T],Acc,0) ->
- complete(T,Acc,0);
-complete([align|T],[Hacc|Tacc],Acclen) ->
- Rest = 8 - Acclen,
- complete(T,[Hacc bsl Rest|Tacc],0);
-complete([{octets,_N,Val}|T],Acc,Acclen) when list(Val) -> % no security check here
- complete([{octets,Val}|T],Acc,Acclen);
-
-complete([],[],0) ->
- [0]; % a complete encoding must always be at least 1 byte
-complete([],Acc,0) ->
- lists:reverse(Acc);
-complete([],[Hacc|Tacc],Acclen) when Acclen > 0->
- Rest = 8 - Acclen,
- NewHacc = Hacc bsl Rest,
- lists:reverse([NewHacc|Tacc]).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/notes_history.sgml b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/notes_history.sgml
deleted file mode 100644
index f63b3360eb..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/notes_history.sgml
+++ /dev/null
@@ -1,100 +0,0 @@
-<!doctype chapter PUBLIC "-//Stork//DTD chapter//EN">
-<!--
- ``The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance 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: notes_history.sgml,v 1.1 2008/12/17 09:53:31 mikpe Exp $
--->
-<chapter>
- <header>
- <title>ASN1 Release Notes (Old)</title>
- <prepared>Kenneth Lundin</prepared>
- <responsible>Kenneth Lundin</responsible>
- <docno></docno>
- <approved>Kenneth Lundin</approved>
- <checked>Kenneth Lundin</checked>
- <date>98-02-02</date>
- <rev>A</rev>
- <file>notes_history.sgml</file>
- </header>
-
- <p>This document describes the changes made to old versions of the <c>asn1</c> application.
-
- <section>
- <title>ASN1 0.8.1</title>
- <p>This is the first release of the ASN1 application. This version is released
- for beta-testing. Some functionality will be added until the 1.0 version is
- released. A list of missing features and restrictions can be found in the
- chapter below.
-
- <section>
- <title>Missing features and other restrictions</title>
- <list>
- <item>
- <p>The encoding rules BER and PER (aligned) is supported. <em>PER (unaligned)
- IS NOT SUPPORTED</em>.
- <item>
- <p>NOT SUPPORTED types <c>ANY</c> and <c>ANY DEFINED BY</c>
- (is not in the standard any more).
- <item>
- <p>NOT SUPPORTED types <c>EXTERNAL</c> and <c>EMBEDDED-PDV</c>.
- <item>
- <p>NOT SUPPORTED type <c>REAL</c> (planned to be implemented).
- <item>
- <p>The code generation support for value definitions in the ASN.1 notation is very limited
- (planned to be enhanced).
- <item>
- <p>The support for constraints is limited to:
- <list>
- <item><p>
- SizeConstraint SIZE(X)
- <item><p>
- SingleValue (1)
- <item><p>
- ValueRange (X..Y)
- <item><p>
- PermittedAlpabet FROM (but not for BMPString and UniversalString when generating PER).
- </list>
- <p>Complex expressions in constraints is not supported (planned to be extended).
- <item>
- <p>The current version of the compiler has very limited error checking:
- <list>
- <item><p>Stops at first syntax error.
- <item><p>Does not stop when a reference to an undefined type is found ,
- but prints an error message. Compilation of the generated
- Erlang module will then fail.
- <item><p>A whole number of other semantical controls is currently missing. This
- means that the compiler will give little or bad help to detect what's wrong
- with an ASN.1 specification, but will mostly work very well when the
- ASN.1 specification is correct.
- </list>
- <item>
- <p>The maximum INTEGER supported in this version is a signed 64 bit integer. This
- limitation is probably quite reasonable. (Planned to be extended).
- <item>
- <p>Only AUTOMATIC TAGS supported for PER.
- <item>
- <p>Only EXPLICIT and IMPLICIT TAGS supported for BER.
- <item>
- <p>The compiler supports decoding of BER-data with indefinite length but it is
- not possible to produce data with indefinite length with the encoder.
- </list>
- </section>
-
- </section>
-</chapter>
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/notes_latest.sgml b/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/notes_latest.sgml
deleted file mode 100644
index 7accc797a6..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/asn1/notes_latest.sgml
+++ /dev/null
@@ -1,100 +0,0 @@
-<!doctype chapter PUBLIC "-//Stork//DTD chapter//EN">
-<!--
- ``The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance 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: notes_latest.sgml,v 1.1 2008/12/17 09:53:31 mikpe Exp $
--->
-<chapter>
- <header>
- <title>ASN1 Release Notes</title>
- <prepared>Kenneth Lundin</prepared>
- <responsible>Kenneth Lundin</responsible>
- <docno></docno>
- <approved>Kenneth Lundin</approved>
- <checked>Kenneth Lundin</checked>
- <date>97-10-07</date>
- <rev>A</rev>
- <file>notes_latest.sgml</file>
- </header>
-
- <p>This document describes the changes made to the asn1 application.
-
- <section>
- <title>ASN1 0.8.1</title>
- <p>This is the first release of the ASN1 application. This version is released
- for beta-testing. Some functionality will be added until the 1.0 version is
- released. A list of missing features and restrictions can be found in the
- chapter below.
-
- <section>
- <title>Missing features and other restrictions</title>
- <list>
- <item>
- <p>The encoding rules BER and PER (aligned) is supported. <em>PER (unaligned)
- IS NOT SUPPORTED</em>.
- <item>
- <p>NOT SUPPORTED types <c>ANY</c> and <c>ANY DEFINED BY</c>
- (is not in the standard any more).
- <item>
- <p>NOT SUPPORTED types <c>EXTERNAL</c> and <c>EMBEDDED-PDV</c>.
- <item>
- <p>NOT SUPPORTED type <c>REAL</c> (planned to be implemented).
- <item>
- <p>The code generation support for value definitions in the ASN.1 notation is very limited
- (planned to be enhanced).
- <item>
- <p>The support for constraints is limited to:
- <list>
- <item><p>
- SizeConstraint SIZE(X)
- <item><p>
- SingleValue (1)
- <item><p>
- ValueRange (X..Y)
- <item><p>
- PermittedAlpabet FROM (but not for BMPString and UniversalString when generating PER).
- </list>
- <p>Complex expressions in constraints is not supported (planned to be extended).
- <item>
- <p>The current version of the compiler has very limited error checking:
- <list>
- <item><p>Stops at first syntax error.
- <item><p>Does not stop when a reference to an undefined type is found ,
- but prints an error message. Compilation of the generated
- Erlang module will then fail.
- <item><p>A whole number of other semantical controls is currently missing. This
- means that the compiler will give little or bad help to detect what's wrong
- with an ASN.1 specification, but will mostly work very well when the
- ASN.1 specification is correct.
- </list>
- <item>
- <p>The maximum INTEGER supported in this version is a signed 64 bit integer. This
- limitation is probably quite reasonable. (Planned to be extended).
- <item>
- <p>Only AUTOMATIC TAGS supported for PER.
- <item>
- <p>Only EXPLICIT and IMPLICIT TAGS supported for BER.
- <item>
- <p>The compiler supports decoding of BER-data with indefinite length but it is
- not possible to produce data with indefinite length with the encoder.
- </list>
- </section>
-
- </section>
-</chapter>
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/Makefile b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/Makefile
deleted file mode 100644
index ab0d7c0a63..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/Makefile
+++ /dev/null
@@ -1,178 +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: Makefile,v 1.1 2008/12/17 09:53:33 mikpe Exp $
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-
-VSN = $(INETS_VSN)
-APP_VSN = "inets-$(VSN)"
-
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/inets-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-MODULES = \
- ftp \
- http \
- http_lib \
- httpc_handler \
- httpc_manager \
- uri \
- httpd \
- httpd_acceptor \
- httpd_acceptor_sup \
- httpd_conf \
- httpd_example \
- httpd_manager \
- httpd_misc_sup \
- httpd_parse \
- httpd_request_handler \
- httpd_response \
- httpd_socket \
- httpd_sup \
- httpd_util \
- httpd_verbosity \
- inets_sup \
- mod_actions \
- mod_alias \
- mod_auth \
- mod_auth_plain \
- mod_auth_dets \
- mod_auth_mnesia \
- mod_auth_server \
- mod_browser \
- mod_cgi \
- mod_dir \
- mod_disk_log \
- mod_esi \
- mod_get \
- mod_head \
- mod_htaccess \
- mod_include \
- mod_log \
- mod_range \
- mod_responsecontrol \
- mod_trace \
- mod_security \
- mod_security_server
-
-HRL_FILES = httpd.hrl httpd_verbosity.hrl mod_auth.hrl \
- http.hrl jnets_httpd.hrl
-
-ERL_FILES = $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
-
-APP_FILE= inets.app
-APPUP_FILE= inets.appup
-
-APP_SRC= $(APP_FILE).src
-APP_TARGET= $(EBIN)/$(APP_FILE)
-
-APPUP_SRC= $(APPUP_FILE).src
-APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
-
-# ----------------------------------------------------
-# INETS FLAGS
-# ----------------------------------------------------
-# DONT_USE_VERBOSITY = -Ddont_use_verbosity=true
-INETS_FLAGS = -D'SERVER_SOFTWARE="inets/$(VSN)"' \
- -Ddefault_verbosity=silence \
- $(DONT_USE_VERBOSITY)
-
-# INETS_DEBUG_DEFAULT = d
-ifeq ($(INETS_DEBUG),)
- INETS_DEBUG = $(INETS_DEBUG_DEFAULT)
-endif
-
-ifeq ($(INETS_DEBUG),c)
- INETS_FLAGS += -Dinets_cdebug -Dinets_debug -Dinets_log -Dinets_error
-endif
-ifeq ($(INETS_DEBUG),d)
- INETS_FLAGS += -Dinets_debug -Dinets_log -Dinets_error
-endif
-ifeq ($(INETS_DEBUG),l)
- INETS_FLAGS += -Dinets_log -Dinets_error
-endif
-ifeq ($(INETS_DEBUG),e)
- INETS_FLAGS += -Dinets_error
-endif
-
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_FLAGS +=
-
-ifeq ($(WARN_UNUSED_WARS),true)
-ERL_COMPILE_FLAGS += +warn_unused_vars
-endif
-
-ERL_COMPILE_FLAGS += $(INETS_FLAGS) \
- +'{parse_transform,sys_pre_attributes}' \
- +'{attribute,insert,app_vsn,$(APP_VSN)}'
-
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt: $(TARGET_FILES)
-
-clean:
- rm -f $(TARGET_FILES)
- rm -f core
-
-docs:
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-$(APP_TARGET): $(APP_SRC) ../vsn.mk
- sed -e 's;%VSN%;$(VSN);' $< > $@
-
-$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
- sed -e 's;%VSN%;$(VSN);' $< > $@
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
-
-release_docs_spec:
-
-info:
- @echo "INETS_DEBUG = $(INETS_DEBUG)"
- @echo "INETS_FLAGS = $(INETS_FLAGS)"
- @echo "ERL_COMPILE_FLAGS = $(ERL_COMPILE_FLAGS)"
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/ftp.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/ftp.erl
deleted file mode 100644
index be06ec654c..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/ftp.erl
+++ /dev/null
@@ -1,1582 +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: ftp.erl,v 1.2 2009/03/03 01:55:01 kostis Exp $
-%%
--module(ftp).
-
--behaviour(gen_server).
-
-%% This module implements an ftp client based on socket(3)/gen_tcp(3),
-%% file(3) and filename(3).
-%%
-
-
--define(OPEN_TIMEOUT, 60*1000).
--define(BYTE_TIMEOUT, 1000). % Timeout for _ONE_ byte to arrive. (ms)
--define(OPER_TIMEOUT, 300). % Operation timeout (seconds)
--define(FTP_PORT, 21).
-
-%% Client interface
--export([cd/2, close/1, delete/2, formaterror/1, help/0,
- lcd/2, lpwd/1, ls/1, ls/2,
- mkdir/2, nlist/1, nlist/2,
- open/1, open/2, open/3,
- pwd/1,
- recv/2, recv/3, recv_bin/2,
- recv_chunk_start/2, recv_chunk/1,
- rename/3, rmdir/2,
- send/2, send/3, send_bin/3,
- send_chunk_start/2, send_chunk/2, send_chunk_end/1,
- type/2, user/3,user/4,account/2,
- append/3, append/2, append_bin/3,
- append_chunk/2, append_chunk_end/1, append_chunk_start/2]).
-
-%% Internal
--export([init/1, handle_call/3, handle_cast/2,
- handle_info/2, terminate/2,code_change/3]).
-
-
-%%
-%% CLIENT FUNCTIONS
-%%
-
-%% open(Host)
-%% open(Host, Flags)
-%%
-%% Purpose: Start an ftp client and connect to a host.
-%% Args: Host = string(),
-%% Port = integer(),
-%% Flags = [Flag],
-%% Flag = verbose | debug
-%% Returns: {ok, Pid} | {error, ehost}
-
-%%Tho only option was the host in textual form
-open({option_list,Option_list})->
- %% Dbg = {debug,[trace,log,statistics]},
- %% Options = [Dbg],
- Options = [],
- {ok,Pid1}=case lists:keysearch(flags,1,Option_list) of
- {value,{flags,Flags}}->
- {ok, Pid} = gen_server:start_link(?MODULE, [Flags], Options);
- false ->
- {ok, Pid} = gen_server:start_link(?MODULE, [], Options)
- end,
- gen_server:call(Pid1, {open, ip_comm,Option_list}, infinity);
-
-
-%%The only option was the tuple form of the ip-number
-open(Host)when tuple(Host) ->
- open(Host, ?FTP_PORT, []);
-
-%%Host is the string form of the hostname
-open(Host)->
- open(Host,?FTP_PORT,[]).
-
-
-
-open(Host, Port) when integer(Port) ->
- open(Host,Port,[]);
-
-open(Host, Flags) when list(Flags) ->
- open(Host,?FTP_PORT, Flags).
-
-open(Host,Port,Flags) when integer(Port), list(Flags) ->
- %% Dbg = {debug,[trace,log,statistics]},
- %% Options = [Dbg],
- Options = [],
- {ok, Pid} = gen_server:start_link(?MODULE, [Flags], Options),
- gen_server:call(Pid, {open, ip_comm, Host, Port}, infinity).
-
-%% user(Pid, User, Pass)
-%% Purpose: Login.
-%% Args: Pid = pid(), User = Pass = string()
-%% Returns: ok | {error, euser} | {error, econn}
-user(Pid, User, Pass) ->
- gen_server:call(Pid, {user, User, Pass}, infinity).
-
-%% user(Pid, User, Pass,Acc)
-%% Purpose: Login whith a supplied account name
-%% Args: Pid = pid(), User = Pass = Acc = string()
-%% Returns: ok | {error, euser} | {error, econn} | {error, eacct}
-user(Pid, User, Pass,Acc) ->
- gen_server:call(Pid, {user, User, Pass,Acc}, infinity).
-
-%% account(Pid,Acc)
-%% Purpose: Set a user Account.
-%% Args: Pid = pid(), Acc= string()
-%% Returns: ok | {error, eacct}
-account(Pid,Acc) ->
- gen_server:call(Pid, {account,Acc}, infinity).
-
-%% pwd(Pid)
-%%
-%% Purpose: Get the current working directory at remote server.
-%% Args: Pid = pid()
-%% Returns: {ok, Dir} | {error, elogin} | {error, econn}
-pwd(Pid) ->
- gen_server:call(Pid, pwd, infinity).
-
-%% lpwd(Pid)
-%%
-%% Purpose: Get the current working directory at local server.
-%% Args: Pid = pid()
-%% Returns: {ok, Dir} | {error, elogin}
-lpwd(Pid) ->
- gen_server:call(Pid, lpwd, infinity).
-
-%% cd(Pid, Dir)
-%%
-%% Purpose: Change current working directory at remote server.
-%% Args: Pid = pid(), Dir = string()
-%% Returns: ok | {error, epath} | {error, elogin} | {error, econn}
-cd(Pid, Dir) ->
- gen_server:call(Pid, {cd, Dir}, infinity).
-
-%% lcd(Pid, Dir)
-%%
-%% Purpose: Change current working directory for the local client.
-%% Args: Pid = pid(), Dir = string()
-%% Returns: ok | {error, epath}
-lcd(Pid, Dir) ->
- gen_server:call(Pid, {lcd, Dir}, infinity).
-
-%% ls(Pid)
-%% ls(Pid, Dir)
-%%
-%% Purpose: List the contents of current directory (ls/1) or directory
-%% Dir (ls/2) at remote server.
-%% Args: Pid = pid(), Dir = string()
-%% Returns: {ok, Listing} | {error, epath} | {error, elogin} | {error, econn}
-ls(Pid) ->
- ls(Pid, "").
-ls(Pid, Dir) ->
- gen_server:call(Pid, {dir, long, Dir}, infinity).
-
-%% nlist(Pid)
-%% nlist(Pid, Dir)
-%%
-%% Purpose: List the contents of current directory (ls/1) or directory
-%% Dir (ls/2) at remote server. The returned list is a stream
-%% of file names.
-%% Args: Pid = pid(), Dir = string()
-%% Returns: {ok, Listing} | {error, epath} | {error, elogin} | {error, econn}
-nlist(Pid) ->
- nlist(Pid, "").
-nlist(Pid, Dir) ->
- gen_server:call(Pid, {dir, short, Dir}, infinity).
-
-%% rename(Pid, CurrFile, NewFile)
-%%
-%% Purpose: Rename a file at remote server.
-%% Args: Pid = pid(), CurrFile = NewFile = string()
-%% Returns: ok | {error, epath} | {error, elogin} | {error, econn}
-rename(Pid, CurrFile, NewFile) ->
- gen_server:call(Pid, {rename, CurrFile, NewFile}, infinity).
-
-%% delete(Pid, File)
-%%
-%% Purpose: Remove file at remote server.
-%% Args: Pid = pid(), File = string()
-%% Returns: ok | {error, epath} | {error, elogin} | {error, econn}
-delete(Pid, File) ->
- gen_server:call(Pid, {delete, File}, infinity).
-
-%% mkdir(Pid, Dir)
-%%
-%% Purpose: Make directory at remote server.
-%% Args: Pid = pid(), Dir = string()
-%% Returns: ok | {error, epath} | {error, elogin} | {error, econn}
-mkdir(Pid, Dir) ->
- gen_server:call(Pid, {mkdir, Dir}, infinity).
-
-%% rmdir(Pid, Dir)
-%%
-%% Purpose: Remove directory at remote server.
-%% Args: Pid = pid(), Dir = string()
-%% Returns: ok | {error, epath} | {error, elogin} | {error, econn}
-rmdir(Pid, Dir) ->
- gen_server:call(Pid, {rmdir, Dir}, infinity).
-
-%% type(Pid, Type)
-%%
-%% Purpose: Set transfer type.
-%% Args: Pid = pid(), Type = ascii | binary
-%% Returns: ok | {error, etype} | {error, elogin} | {error, econn}
-type(Pid, Type) ->
- gen_server:call(Pid, {type, Type}, infinity).
-
-%% recv(Pid, RFile [, LFile])
-%%
-%% Purpose: Transfer file from remote server.
-%% Args: Pid = pid(), RFile = LFile = string()
-%% Returns: ok | {error, epath} | {error, elogin} | {error, econn}
-recv(Pid, RFile) ->
- recv(Pid, RFile, "").
-
-recv(Pid, RFile, LFile) ->
- gen_server:call(Pid, {recv, RFile, LFile}, infinity).
-
-%% recv_bin(Pid, RFile)
-%%
-%% Purpose: Transfer file from remote server into binary.
-%% Args: Pid = pid(), RFile = string()
-%% Returns: {ok, Bin} | {error, epath} | {error, elogin} | {error, econn}
-recv_bin(Pid, RFile) ->
- gen_server:call(Pid, {recv_bin, RFile}, infinity).
-
-%% recv_chunk_start(Pid, RFile)
-%%
-%% Purpose: Start receive of chunks of remote file.
-%% Args: Pid = pid(), RFile = string().
-%% Returns: ok | {error, elogin} | {error, epath} | {error, econn}
-recv_chunk_start(Pid, RFile) ->
- gen_server:call(Pid, {recv_chunk_start, RFile}, infinity).
-
-
-%% recv_chunk(Pid, RFile)
-%%
-%% Purpose: Transfer file from remote server into binary in chunks
-%% Args: Pid = pid(), RFile = string()
-%% Returns: Reference
-recv_chunk(Pid) ->
- gen_server:call(Pid, recv_chunk, infinity).
-
-%% send(Pid, LFile [, RFile])
-%%
-%% Purpose: Transfer file to remote server.
-%% Args: Pid = pid(), LFile = RFile = string()
-%% Returns: ok | {error, epath} | {error, elogin} | {error, econn}
-send(Pid, LFile) ->
- send(Pid, LFile, "").
-
-send(Pid, LFile, RFile) ->
- gen_server:call(Pid, {send, LFile, RFile}, infinity).
-
-%% send_bin(Pid, Bin, RFile)
-%%
-%% Purpose: Transfer a binary to a remote file.
-%% Args: Pid = pid(), Bin = binary(), RFile = string()
-%% Returns: ok | {error, epath} | {error, elogin} | {error, enotbinary}
-%% | {error, econn}
-send_bin(Pid, Bin, RFile) when binary(Bin) ->
- gen_server:call(Pid, {send_bin, Bin, RFile}, infinity);
-send_bin(Pid, Bin, RFile) ->
- {error, enotbinary}.
-
-%% send_chunk_start(Pid, RFile)
-%%
-%% Purpose: Start transfer of chunks to remote file.
-%% Args: Pid = pid(), RFile = string().
-%% Returns: ok | {error, elogin} | {error, epath} | {error, econn}
-send_chunk_start(Pid, RFile) ->
- gen_server:call(Pid, {send_chunk_start, RFile}, infinity).
-
-
-%% append_chunk_start(Pid, RFile)
-%%
-%% Purpose: Start append chunks of data to remote file.
-%% Args: Pid = pid(), RFile = string().
-%% Returns: ok | {error, elogin} | {error, epath} | {error, econn}
-append_chunk_start(Pid, RFile) ->
- gen_server:call(Pid, {append_chunk_start, RFile}, infinity).
-
-
-%% send_chunk(Pid, Bin)
-%%
-%% Purpose: Send chunk to remote file.
-%% Args: Pid = pid(), Bin = binary().
-%% Returns: ok | {error, elogin} | {error, enotbinary} | {error, echunk}
-%% | {error, econn}
-send_chunk(Pid, Bin) when binary(Bin) ->
- gen_server:call(Pid, {send_chunk, Bin}, infinity);
-send_chunk(Pid, Bin) ->
- {error, enotbinary}.
-
-%%append_chunk(Pid, Bin)
-%%
-%% Purpose: Append chunk to remote file.
-%% Args: Pid = pid(), Bin = binary().
-%% Returns: ok | {error, elogin} | {error, enotbinary} | {error, echunk}
-%% | {error, econn}
-append_chunk(Pid, Bin) when binary(Bin) ->
- gen_server:call(Pid, {append_chunk, Bin}, infinity);
-append_chunk(Pid, Bin) ->
- {error, enotbinary}.
-
-%% send_chunk_end(Pid)
-%%
-%% Purpose: End sending of chunks to remote file.
-%% Args: Pid = pid().
-%% Returns: ok | {error, elogin} | {error, echunk} | {error, econn}
-send_chunk_end(Pid) ->
- gen_server:call(Pid, send_chunk_end, infinity).
-
-%% append_chunk_end(Pid)
-%%
-%% Purpose: End appending of chunks to remote file.
-%% Args: Pid = pid().
-%% Returns: ok | {error, elogin} | {error, echunk} | {error, econn}
-append_chunk_end(Pid) ->
- gen_server:call(Pid, append_chunk_end, infinity).
-
-%% append(Pid, LFile,RFile)
-%%
-%% Purpose: Append the local file to the remote file
-%% Args: Pid = pid(), LFile = RFile = string()
-%% Returns: ok | {error, epath} | {error, elogin} | {error, econn}
-append(Pid, LFile) ->
- append(Pid, LFile, "").
-
-append(Pid, LFile, RFile) ->
- gen_server:call(Pid, {append, LFile, RFile}, infinity).
-
-%% append_bin(Pid, Bin, RFile)
-%%
-%% Purpose: Append a binary to a remote file.
-%% Args: Pid = pid(), Bin = binary(), RFile = string()
-%% Returns: ok | {error, epath} | {error, elogin} | {error, enotbinary}
-%% | {error, econn}
-append_bin(Pid, Bin, RFile) when binary(Bin) ->
- gen_server:call(Pid, {append_bin, Bin, RFile}, infinity);
-append_bin(Pid, Bin, RFile) ->
- {error, enotbinary}.
-
-
-%% close(Pid)
-%%
-%% Purpose: End the ftp session.
-%% Args: Pid = pid()
-%% Returns: ok
-close(Pid) ->
- case (catch gen_server:call(Pid, close, 30000)) of
- ok ->
- ok;
- {'EXIT',{noproc,_}} ->
- %% Already gone...
- ok;
- Res ->
- Res
- end.
-
-%% formaterror(Tag)
-%%
-%% Purpose: Return diagnostics.
-%% Args: Tag = atom() | {error, atom()}
-%% Returns: string().
-formaterror(Tag) ->
- errstr(Tag).
-
-%% help()
-%%
-%% Purpose: Print list of valid commands.
-%%
-%% Undocumented.
-%%
-help() ->
- io:format("\n Commands:\n"
- " ---------\n"
- " cd(Pid, Dir)\n"
- " close(Pid)\n"
- " delete(Pid, File)\n"
- " formaterror(Tag)\n"
- " help()\n"
- " lcd(Pid, Dir)\n"
- " lpwd(Pid)\n"
- " ls(Pid [, Dir])\n"
- " mkdir(Pid, Dir)\n"
- " nlist(Pid [, Dir])\n"
- " open(Host [Port, Flags])\n"
- " pwd(Pid)\n"
- " recv(Pid, RFile [, LFile])\n"
- " recv_bin(Pid, RFile)\n"
- " recv_chunk_start(Pid, RFile)\n"
- " recv_chunk(Pid)\n"
- " rename(Pid, CurrFile, NewFile)\n"
- " rmdir(Pid, Dir)\n"
- " send(Pid, LFile [, RFile])\n"
- " send_chunk(Pid, Bin)\n"
- " send_chunk_start(Pid, RFile)\n"
- " send_chunk_end(Pid)\n"
- " send_bin(Pid, Bin, RFile)\n"
- " append(Pid, LFile [, RFile])\n"
- " append_chunk(Pid, Bin)\n"
- " append_chunk_start(Pid, RFile)\n"
- " append_chunk_end(Pid)\n"
- " append_bin(Pid, Bin, RFile)\n"
- " type(Pid, Type)\n"
- " account(Pid,Account)\n"
- " user(Pid, User, Pass)\n"
- " user(Pid, User, Pass,Account)\n").
-
-%%
-%% INIT
-%%
-
--record(state, {csock = undefined, dsock = undefined, flags = undefined,
- ldir = undefined, type = undefined, chunk = false,
- pending = undefined}).
-
-init([Flags]) ->
- sock_start(),
- put(debug,get_debug(Flags)),
- put(verbose,get_verbose(Flags)),
- process_flag(priority, low),
- {ok, LDir} = file:get_cwd(),
- {ok, #state{flags = Flags, ldir = LDir}}.
-
-%%
-%% HANDLERS
-%%
-
-%% First group of reply code digits
--define(POS_PREL, 1).
--define(POS_COMPL, 2).
--define(POS_INTERM, 3).
--define(TRANS_NEG_COMPL, 4).
--define(PERM_NEG_COMPL, 5).
-
-%% Second group of reply code digits
--define(SYNTAX,0).
--define(INFORMATION,1).
--define(CONNECTION,2).
--define(AUTH_ACC,3).
--define(UNSPEC,4).
--define(FILE_SYSTEM,5).
-
-
--define(STOP_RET(E),{stop, normal, {error, E},
- State#state{csock = undefined}}).
-
-
-rescode(?POS_PREL,_,_) -> pos_prel; %%Positive Preleminary Reply
-rescode(?POS_COMPL,_,_) -> pos_compl; %%Positive Completion Reply
-rescode(?POS_INTERM,?AUTH_ACC,2) -> pos_interm_acct; %%Positive Intermediate Reply nedd account
-rescode(?POS_INTERM,_,_) -> pos_interm; %%Positive Intermediate Reply
-rescode(?TRANS_NEG_COMPL,?FILE_SYSTEM,2) -> trans_no_space; %%No storage area no action taken
-rescode(?TRANS_NEG_COMPL,_,_) -> trans_neg_compl;%%Temporary Error, no action taken
-rescode(?PERM_NEG_COMPL,?FILE_SYSTEM,2) -> perm_no_space; %%Permanent disk space error, the user shall not try again
-rescode(?PERM_NEG_COMPL,?FILE_SYSTEM,3) -> perm_fname_not_allowed;
-rescode(?PERM_NEG_COMPL,_,_) -> perm_neg_compl.
-
-retcode(trans_no_space,_) -> etnospc;
-retcode(perm_no_space,_) -> epnospc;
-retcode(perm_fname_not_allowed,_) -> efnamena;
-retcode(_,Otherwise) -> Otherwise.
-
-handle_call({open,ip_comm,Conn_data},From,State) ->
- case lists:keysearch(host,1,Conn_data) of
- {value,{host,Host}}->
- Port=get_key1(port,Conn_data,?FTP_PORT),
- Timeout=get_key1(timeout,Conn_data,?OPEN_TIMEOUT),
- open(Host,Port,Timeout,State);
- false ->
- ehost
- end;
-
-handle_call({open,ip_comm,Host,Port},From,State) ->
- open(Host,Port,?OPEN_TIMEOUT,State);
-
-handle_call({user, User, Pass}, _From, State) ->
- #state{csock = CSock} = State,
- case ctrl_cmd(CSock, "USER ~s", [User]) of
- pos_interm ->
- case ctrl_cmd(CSock, "PASS ~s", [Pass]) of
- pos_compl ->
- set_type(binary, CSock),
- {reply, ok, State#state{type = binary}};
- {error,enotconn} ->
- ?STOP_RET(econn);
- _ ->
- {reply, {error, euser}, State}
- end;
- pos_compl ->
- set_type(binary, CSock),
- {reply, ok, State#state{type = binary}};
- {error, enotconn} ->
- ?STOP_RET(econn);
- _ ->
- {reply, {error, euser}, State}
- end;
-
-handle_call({user, User, Pass,Acc}, _From, State) ->
- #state{csock = CSock} = State,
- case ctrl_cmd(CSock, "USER ~s", [User]) of
- pos_interm ->
- case ctrl_cmd(CSock, "PASS ~s", [Pass]) of
- pos_compl ->
- set_type(binary, CSock),
- {reply, ok, State#state{type = binary}};
- pos_interm_acct->
- case ctrl_cmd(CSock,"ACCT ~s",[Acc]) of
- pos_compl->
- set_type(binary, CSock),
- {reply, ok, State#state{type = binary}};
- {error,enotconn}->
- ?STOP_RET(econn);
- _ ->
- {reply, {error, eacct}, State}
- end;
- {error,enotconn} ->
- ?STOP_RET(econn);
- _ ->
- {reply, {error, euser}, State}
- end;
- pos_compl ->
- set_type(binary, CSock),
- {reply, ok, State#state{type = binary}};
- {error, enotconn} ->
- ?STOP_RET(econn);
- _ ->
- {reply, {error, euser}, State}
- end;
-
-%%set_account(Acc,State)->Reply
-%%Reply={reply, {error, euser}, State} | {error,enotconn}->
-handle_call({account,Acc},_From,State)->
- #state{csock = CSock} = State,
- case ctrl_cmd(CSock,"ACCT ~s",[Acc]) of
- pos_compl->
- {reply, ok,State};
- {error,enotconn}->
- ?STOP_RET(econn);
- Error ->
- debug(" error: ~p",[Error]),
- {reply, {error, eacct}, State}
- end;
-
-handle_call(pwd, _From, State) when State#state.chunk == false ->
- #state{csock = CSock} = State,
- %%
- %% NOTE: The directory string comes over the control connection.
- case sock_write(CSock, mk_cmd("PWD", [])) of
- ok ->
- {_, Line} = result_line(CSock),
- {_, Cs} = split($", Line), % XXX Ugly
- {Dir0, _} = split($", Cs),
- Dir = lists:delete($", Dir0),
- {reply, {ok, Dir}, State};
- {error, enotconn} ->
- ?STOP_RET(econn)
- end;
-
-handle_call(lpwd, _From, State) ->
- #state{csock = CSock, ldir = LDir} = State,
- {reply, {ok, LDir}, State};
-
-handle_call({cd, Dir}, _From, State) when State#state.chunk == false ->
- #state{csock = CSock} = State,
- case ctrl_cmd(CSock, "CWD ~s", [Dir]) of
- pos_compl ->
- {reply, ok, State};
- {error, enotconn} ->
- ?STOP_RET(econn);
- _ ->
- {reply, {error, epath}, State}
- end;
-
-handle_call({lcd, Dir}, _From, State) ->
- #state{csock = CSock, ldir = LDir0} = State,
- LDir = absname(LDir0, Dir),
- case file:read_file_info(LDir) of
- {ok, _ } ->
- {reply, ok, State#state{ldir = LDir}};
- _ ->
- {reply, {error, epath}, State}
- end;
-
-handle_call({dir, Len, Dir}, _From, State) when State#state.chunk == false ->
- debug(" dir : ~p: ~s~n",[Len,Dir]),
- #state{csock = CSock, type = Type} = State,
- set_type(ascii, Type, CSock),
- LSock = listen_data(CSock, raw),
- Cmd = case Len of
- short -> "NLST";
- long -> "LIST"
- end,
- Result = case Dir of
- "" ->
- ctrl_cmd(CSock, Cmd, "");
- _ ->
- ctrl_cmd(CSock, Cmd ++ " ~s", [Dir])
- end,
- debug(" ctrl : command result: ~p~n",[Result]),
- case Result of
- pos_prel ->
- debug(" dbg : await the data connection", []),
- DSock = accept_data(LSock),
- debug(" dbg : await the data", []),
- Reply0 =
- case recv_data(DSock) of
- {ok, DirData} ->
- debug(" data : DirData: ~p~n",[DirData]),
- case result(CSock) of
- pos_compl ->
- {ok, DirData};
- _ ->
- {error, epath}
- end;
- {error, Reason} ->
- sock_close(DSock),
- verbose(" data : error: ~p, ~p~n",[Reason, result(CSock)]),
- {error, epath}
- end,
-
- debug(" ctrl : reply: ~p~n",[Reply0]),
- reset_type(ascii, Type, CSock),
- {reply, Reply0, State};
- {closed, _Why} ->
- ?STOP_RET(econn);
- _ ->
- sock_close(LSock),
- {reply, {error, epath}, State}
- end;
-
-
-handle_call({rename, CurrFile, NewFile}, _From, State) when State#state.chunk == false ->
- #state{csock = CSock} = State,
- case ctrl_cmd(CSock, "RNFR ~s", [CurrFile]) of
- pos_interm ->
- case ctrl_cmd(CSock, "RNTO ~s", [NewFile]) of
- pos_compl ->
- {reply, ok, State};
- _ ->
- {reply, {error, epath}, State}
- end;
- {error, enotconn} ->
- ?STOP_RET(econn);
- _ ->
- {reply, {error, epath}, State}
- end;
-
-handle_call({delete, File}, _From, State) when State#state.chunk == false ->
- #state{csock = CSock} = State,
- case ctrl_cmd(CSock, "DELE ~s", [File]) of
- pos_compl ->
- {reply, ok, State};
- {error, enotconn} ->
- ?STOP_RET(econn);
- _ ->
- {reply, {error, epath}, State}
- end;
-
-handle_call({mkdir, Dir}, _From, State) when State#state.chunk == false ->
- #state{csock = CSock} = State,
- case ctrl_cmd(CSock, "MKD ~s", [Dir]) of
- pos_compl ->
- {reply, ok, State};
- {error, enotconn} ->
- ?STOP_RET(econn);
- _ ->
- {reply, {error, epath}, State}
- end;
-
-handle_call({rmdir, Dir}, _From, State) when State#state.chunk == false ->
- #state{csock = CSock} = State,
- case ctrl_cmd(CSock, "RMD ~s", [Dir]) of
- pos_compl ->
- {reply, ok, State};
- {error, enotconn} ->
- ?STOP_RET(econn);
- _ ->
- {reply, {error, epath}, State}
- end;
-
-handle_call({type, Type}, _From, State) when State#state.chunk == false ->
- #state{csock = CSock} = State,
- case Type of
- ascii ->
- set_type(ascii, CSock),
- {reply, ok, State#state{type = ascii}};
- binary ->
- set_type(binary, CSock),
- {reply, ok, State#state{type = binary}};
- _ ->
- {reply, {error, etype}, State}
- end;
-
-handle_call({recv, RFile, LFile}, _From, State) when State#state.chunk == false ->
- #state{csock = CSock, ldir = LDir} = State,
- ALFile = case LFile of
- "" ->
- absname(LDir, RFile);
- _ ->
- absname(LDir, LFile)
- end,
- case file_open(ALFile, write) of
- {ok, Fd} ->
- LSock = listen_data(CSock, binary),
- Ret = case ctrl_cmd(CSock, "RETR ~s", [RFile]) of
- pos_prel ->
- DSock = accept_data(LSock),
- recv_file(DSock, Fd),
- Reply0 = case result(CSock) of
- pos_compl ->
- ok;
- _ ->
- {error, epath}
- end,
- sock_close(DSock),
- {reply, Reply0, State};
- {error, enotconn} ->
- ?STOP_RET(econn);
- _ ->
- {reply, {error, epath}, State}
- end,
- file_close(Fd),
- Ret;
- {error, _What} ->
- {reply, {error, epath}, State}
- end;
-
-handle_call({recv_bin, RFile}, _From, State) when State#state.chunk == false ->
- #state{csock = CSock, ldir = LDir} = State,
- LSock = listen_data(CSock, binary),
- case ctrl_cmd(CSock, "RETR ~s", [RFile]) of
- pos_prel ->
- DSock = accept_data(LSock),
- Reply = recv_binary(DSock,CSock),
- sock_close(DSock),
- {reply, Reply, State};
- {error, enotconn} ->
- ?STOP_RET(econn);
- _ ->
- {reply, {error, epath}, State}
- end;
-
-
-handle_call({recv_chunk_start, RFile}, _From, State)
- when State#state.chunk == false ->
- start_chunk_transfer("RETR",RFile,State);
-
-handle_call(recv_chunk, _From, State)
- when State#state.chunk == true ->
- do_recv_chunk(State);
-
-
-handle_call({send, LFile, RFile}, _From, State)
- when State#state.chunk == false ->
- transfer_file("STOR",LFile,RFile,State);
-
-handle_call({append, LFile, RFile}, _From, State)
- when State#state.chunk == false ->
- transfer_file("APPE",LFile,RFile,State);
-
-
-handle_call({send_bin, Bin, RFile}, _From, State)
- when State#state.chunk == false ->
- transfer_data("STOR",Bin,RFile,State);
-
-handle_call({append_bin, Bin, RFile}, _From, State)
- when State#state.chunk == false ->
- transfer_data("APPE",Bin,RFile,State);
-
-
-
-handle_call({send_chunk_start, RFile}, _From, State)
- when State#state.chunk == false ->
- start_chunk_transfer("STOR",RFile,State);
-
-handle_call({append_chunk_start,RFile},_From,State)
- when State#state.chunk==false->
- start_chunk_transfer("APPE",RFile,State);
-
-handle_call({send_chunk, Bin}, _From, State)
- when State#state.chunk == true ->
- chunk_transfer(Bin,State);
-
-handle_call({append_chunk, Bin}, _From, State)
- when State#state.chunk == true ->
- chunk_transfer(Bin,State);
-
-handle_call(append_chunk_end, _From, State)
- when State#state.chunk == true ->
- end_chunk_transfer(State);
-
-handle_call(send_chunk_end, _From, State)
- when State#state.chunk == true ->
- end_chunk_transfer(State);
-
-
-
-handle_call(close, _From, State) when State#state.chunk == false ->
- #state{csock = CSock} = State,
- ctrl_cmd(CSock, "QUIT", []),
- sock_close(CSock),
- {stop, normal, ok, State};
-
-handle_call(_, _From, State) when State#state.chunk == true ->
- {reply, {error, echunk}, State}.
-
-
-handle_cast(Msg, State) ->
- {noreply, State}.
-
-
-handle_info({Sock, {fromsocket, Bytes}}, State) when Sock == State#state.csock ->
- put(leftovers, Bytes ++ leftovers()),
- {noreply, State};
-
-%% Data connection closed (during chunk sending)
-handle_info({Sock, {socket_closed, _Reason}}, State) when Sock == State#state.dsock ->
- {noreply, State#state{dsock = undefined}};
-
-%% Control connection closed.
-handle_info({Sock, {socket_closed, _Reason}}, State) when Sock == State#state.csock ->
- debug(" sc : ~s~n",[leftovers()]),
- {stop, ftp_server_close, State#state{csock = undefined}};
-
-handle_info(Info, State) ->
- error_logger:info_msg("ftp : ~w : Unexpected message: ~w\n", [self(),Info]),
- {noreply, State}.
-
-code_change(OldVsn,State,Extra)->
- {ok,State}.
-
-terminate(Reason, State) ->
- ok.
-%%
-%% OPEN CONNECTION
-%%
-open(Host,Port,Timeout,State)->
- case sock_connect(Host,Port,Timeout) of
- {error, What} ->
- {stop, normal, {error, What}, State};
- CSock ->
- case result(CSock, State#state.flags) of
- {error,Reason} ->
- sock_close(CSock),
- {stop,normal,{error,Reason},State};
- _ -> % We should really check this...
- {reply, {ok, self()}, State#state{csock = CSock}}
- end
- end.
-
-
-
-%%
-%% CONTROL CONNECTION
-%%
-
-ctrl_cmd(CSock, Fmt, Args) ->
- Cmd = mk_cmd(Fmt, Args),
- case sock_write(CSock, Cmd) of
- ok ->
- debug(" cmd : ~s",[Cmd]),
- result(CSock);
- {error, enotconn} ->
- {error, enotconn};
- Other ->
- Other
- end.
-
-mk_cmd(Fmt, Args) ->
- [io_lib:format(Fmt, Args)| "\r\n"]. % Deep list ok.
-
-%%
-%% TRANSFER TYPE
-%%
-
-%%
-%% set_type(NewType, CurrType, CSock)
-%% reset_type(NewType, CurrType, CSock)
-%%
-set_type(Type, Type, CSock) ->
- ok;
-set_type(NewType, _OldType, CSock) ->
- set_type(NewType, CSock).
-
-reset_type(Type, Type, CSock) ->
- ok;
-reset_type(_NewType, OldType, CSock) ->
- set_type(OldType, CSock).
-
-set_type(ascii, CSock) ->
- ctrl_cmd(CSock, "TYPE A", []);
-set_type(binary, CSock) ->
- ctrl_cmd(CSock, "TYPE I", []).
-
-%%
-%% DATA CONNECTION
-%%
-
-%% Create a listen socket for a data connection and send a PORT command
-%% containing the IP address and port number. Mode is binary or raw.
-%%
-listen_data(CSock, Mode) ->
- {IP, _} = sock_name(CSock), % IP address of control conn.
- LSock = sock_listen(Mode, IP),
- Port = sock_listen_port(LSock),
- {A1, A2, A3, A4} = IP,
- {P1, P2} = {Port div 256, Port rem 256},
- ctrl_cmd(CSock, "PORT ~w,~w,~w,~w,~w,~w", [A1, A2, A3, A4, P1, P2]),
- LSock.
-
-%%
-%% Accept the data connection and close the listen socket.
-%%
-accept_data(LSock) ->
- Sock = sock_accept(LSock),
- sock_close(LSock),
- Sock.
-
-%%
-%% DATA COLLECTION (ls, dir)
-%%
-%% Socket is a byte stream in ASCII mode.
-%%
-
-%% Receive data (from data connection).
-recv_data(Sock) ->
- recv_data(Sock, [], 0).
-recv_data(Sock, Sofar, ?OPER_TIMEOUT) ->
- sock_close(Sock),
- {ok, lists:flatten(lists:reverse(Sofar))};
-recv_data(Sock, Sofar, Retry) ->
- case sock_read(Sock) of
- {ok, Data} ->
- debug(" dbg : received some data: ~n~s", [Data]),
- recv_data(Sock, [Data| Sofar], 0);
- {error, timeout} ->
- %% Retry..
- recv_data(Sock, Sofar, Retry+1);
- {error, Reason} ->
- SoFar1 = lists:flatten(lists:reverse(Sofar)),
- {error, {socket_error, Reason, SoFar1, Retry}};
- {closed, _} ->
- {ok, lists:flatten(lists:reverse(Sofar))}
- end.
-
-%%
-%% BINARY TRANSFER
-%%
-
-%% --------------------------------------------------
-
-%% recv_binary(DSock,CSock) = {ok,Bin} | {error,Reason}
-%%
-recv_binary(DSock,CSock) ->
- recv_binary1(recv_binary2(DSock,[],0),CSock).
-
-recv_binary1(Reply,Sock) ->
- case result(Sock) of
- pos_compl -> Reply;
- _ -> {error, epath}
- end.
-
-recv_binary2(Sock, _Bs, ?OPER_TIMEOUT) ->
- sock_close(Sock),
- {error,eclosed};
-recv_binary2(Sock, Bs, Retry) ->
- case sock_read(Sock) of
- {ok, Bin} ->
- recv_binary2(Sock, [Bs, Bin], 0);
- {error, timeout} ->
- recv_binary2(Sock, Bs, Retry+1);
- {closed, _Why} ->
- {ok,list_to_binary(Bs)}
- end.
-
-%% --------------------------------------------------
-
-%%
-%% recv_chunk
-%%
-
-do_recv_chunk(#state{dsock = undefined} = State) ->
- {reply, {error,econn}, State};
-do_recv_chunk(State) ->
- recv_chunk1(recv_chunk2(State, 0), State).
-
-recv_chunk1({ok, _Bin} = Reply, State) ->
- {reply, Reply, State};
-%% Reply = ok | {error, Reason}
-recv_chunk1(Reply, #state{csock = CSock} = State) ->
- State1 = State#state{dsock = undefined, chunk = false},
- case result(CSock) of
- pos_compl ->
- {reply, Reply, State1};
- _ ->
- {reply, {error, epath}, State1}
- end.
-
-recv_chunk2(#state{dsock = DSock} = State, ?OPER_TIMEOUT) ->
- sock_close(DSock),
- {error, eclosed};
-recv_chunk2(#state{dsock = DSock} = State, Retry) ->
- case sock_read(DSock) of
- {ok, Bin} ->
- {ok, Bin};
- {error, timeout} ->
- recv_chunk2(State, Retry+1);
- {closed, Reason} ->
- debug(" dbg : socket closed: ~p", [Reason]),
- ok
- end.
-
-
-%% --------------------------------------------------
-
-%%
-%% FILE TRANSFER
-%%
-
-recv_file(Sock, Fd) ->
- recv_file(Sock, Fd, 0).
-
-recv_file(Sock, Fd, ?OPER_TIMEOUT) ->
- sock_close(Sock),
- {closed, timeout};
-recv_file(Sock, Fd, Retry) ->
- case sock_read(Sock) of
- {ok, Bin} ->
- file_write(Fd, Bin),
- recv_file(Sock, Fd);
- {error, timeout} ->
- recv_file(Sock, Fd, Retry+1);
-% {error, Reason} ->
-% SoFar1 = lists:flatten(lists:reverse(Sofar)),
-% exit({socket_error, Reason, Sock, SoFar1, Retry});
- {closed, How} ->
- {closed, How}
- end.
-
-%%
-%% send_file(Fd, Sock) = ok | {error, Why}
-%%
-
-send_file(Fd, Sock) ->
- {N, Bin} = file_read(Fd),
- if
- N > 0 ->
- case sock_write(Sock, Bin) of
- ok ->
- send_file(Fd, Sock);
- {error, Reason} ->
- {error, Reason}
- end;
- true ->
- ok
- end.
-
-
-
-%%
-%% PARSING OF RESULT LINES
-%%
-
-%% Excerpt from RFC 959:
-%%
-%% "A reply is defined to contain the 3-digit code, followed by Space
-%% <SP>, followed by one line of text (where some maximum line length
-%% has been specified), and terminated by the Telnet end-of-line
-%% code. There will be cases however, where the text is longer than
-%% a single line. In these cases the complete text must be bracketed
-%% so the User-process knows when it may stop reading the reply (i.e.
-%% stop processing input on the control connection) and go do other
-%% things. This requires a special format on the first line to
-%% indicate that more than one line is coming, and another on the
-%% last line to designate it as the last. At least one of these must
-%% contain the appropriate reply code to indicate the state of the
-%% transaction. To satisfy all factions, it was decided that both
-%% the first and last line codes should be the same.
-%%
-%% Thus the format for multi-line replies is that the first line
-%% will begin with the exact required reply code, followed
-%% immediately by a Hyphen, "-" (also known as Minus), followed by
-%% text. The last line will begin with the same code, followed
-%% immediately by Space <SP>, optionally some text, and the Telnet
-%% end-of-line code.
-%%
-%% For example:
-%% 123-First line
-%% Second line
-%% 234 A line beginning with numbers
-%% 123 The last line
-%%
-%% The user-process then simply needs to search for the second
-%% occurrence of the same reply code, followed by <SP> (Space), at
-%% the beginning of a line, and ignore all intermediary lines. If
-%% an intermediary line begins with a 3-digit number, the Server
-%% must pad the front to avoid confusion.
-%%
-%% This scheme allows standard system routines to be used for
-%% reply information (such as for the STAT reply), with
-%% "artificial" first and last lines tacked on. In rare cases
-%% where these routines are able to generate three digits and a
-%% Space at the beginning of any line, the beginning of each
-%% text line should be offset by some neutral text, like Space.
-%%
-%% This scheme assumes that multi-line replies may not be nested."
-
-%% We have to collect the stream of result characters into lines (ending
-%% in "\r\n"; we check for "\n"). When a line is assembled, left-over
-%% characters are saved in the process dictionary.
-%%
-
-%% result(Sock) = rescode()
-%%
-result(Sock) ->
- result(Sock, false).
-
-result_line(Sock) ->
- result(Sock, true).
-
-%% result(Sock, Bool) = {error,Reason} | rescode() | {rescode(), Lines}
-%% Printout if Bool = true.
-%%
-result(Sock, RetForm) ->
- case getline(Sock) of
- Line when length(Line) > 3 ->
- [D1, D2, D3| Tail] = Line,
- case Tail of
- [$-| _] ->
- parse_to_end(Sock, [D1, D2, D3, $ ]); % 3 digits + space
- _ ->
- ok
- end,
- result(D1,D2,D3,Line,RetForm);
- _ ->
- retform(rescode(?PERM_NEG_COMPL,-1,-1),[],RetForm)
- end.
-
-result(D1,_D2,_D3,Line,_RetForm) when D1 - $0 > 10 ->
- {error,{invalid_server_response,Line}};
-result(D1,_D2,_D3,Line,_RetForm) when D1 - $0 < 0 ->
- {error,{invalid_server_response,Line}};
-result(D1,D2,D3,Line,RetForm) ->
- Res1 = D1 - $0,
- Res2 = D2 - $0,
- Res3 = D3 - $0,
- verbose(" ~w : ~s", [Res1, Line]),
- retform(rescode(Res1,Res2,Res3),Line,RetForm).
-
-retform(ResCode,Line,true) ->
- {ResCode,Line};
-retform(ResCode,_,_) ->
- ResCode.
-
-leftovers() ->
- case get(leftovers) of
- undefined -> [];
- X -> X
- end.
-
-%% getline(Sock) = Line
-%%
-getline(Sock) ->
- getline(Sock, leftovers()).
-
-getline(Sock, Rest) ->
- getline1(Sock, split($\n, Rest), 0).
-
-getline1(Sock, {[], Rest}, ?OPER_TIMEOUT) ->
- sock_close(Sock),
- put(leftovers, Rest),
- [];
-getline1(Sock, {[], Rest}, Retry) ->
- case sock_read(Sock) of
- {ok, More} ->
- debug(" read : ~s~n",[More]),
- getline(Sock, Rest ++ More);
- {error, timeout} ->
- %% Retry..
- getline1(Sock, {[], Rest}, Retry+1);
- Error ->
- put(leftovers, Rest),
- []
- end;
-getline1(Sock, {Line, Rest}, Retry) ->
- put(leftovers, Rest),
- Line.
-
-parse_to_end(Sock, Prefix) ->
- Line = getline(Sock),
- case lists:prefix(Prefix, Line) of
- false ->
- parse_to_end(Sock, Prefix);
- true ->
- ok
- end.
-
-
-%% Split list after first occurence of S.
-%% Returns {Prefix, Suffix} ({[], Cs} if S not found).
-split(S, Cs) ->
- split(S, Cs, []).
-
-split(S, [S| Cs], As) ->
- {lists:reverse([S|As]), Cs};
-split(S, [C| Cs], As) ->
- split(S, Cs, [C| As]);
-split(_, [], As) ->
- {[], lists:reverse(As)}.
-
-%%
-%% FILE INTERFACE
-%%
-%% All files are opened raw in binary mode.
-%%
--define(BUFSIZE, 4096).
-
-file_open(File, Option) ->
- file:open(File, [raw, binary, Option]).
-
-file_close(Fd) ->
- file:close(Fd).
-
-
-file_read(Fd) -> % Compatible with pre R2A.
- case file:read(Fd, ?BUFSIZE) of
- {ok, {N, Bytes}} ->
- {N, Bytes};
- {ok, Bytes} ->
- {size(Bytes), Bytes};
- eof ->
- {0, []}
- end.
-
-file_write(Fd, Bytes) ->
- file:write(Fd, Bytes).
-
-absname(Dir, File) -> % Args swapped.
- filename:absname(File, Dir).
-
-
-
-%% sock_start()
-%%
-
-%%
-%% USE GEN_TCP
-%%
-
-sock_start() ->
- inet_db:start().
-
-%%
-%% Connect to FTP server at Host (default is TCP port 21) in raw mode,
-%% in order to establish a control connection.
-%%
-
-sock_connect(Host,Port,TimeOut) ->
- debug(" info : connect to server on ~p:~p~n",[Host,Port]),
- Opts = [{packet, 0}, {active, false}],
- case (catch gen_tcp:connect(Host, Port, Opts,TimeOut)) of
- {'EXIT', R1} -> % XXX Probably no longer needed.
- debug(" error: socket connectionn failed with exit reason:"
- "~n ~p",[R1]),
- {error, ehost};
- {error, R2} ->
- debug(" error: socket connectionn failed with exit reason:"
- "~n ~p",[R2]),
- {error, ehost};
- {ok, Sock} ->
- Sock
- end.
-
-%%
-%% Create a listen socket (any port) in binary or raw non-packet mode for
-%% data connection.
-%%
-sock_listen(Mode, IP) ->
- Opts = case Mode of
- binary ->
- [binary, {packet, 0}];
- raw ->
- [{packet, 0}]
- end,
- {ok, Sock} = gen_tcp:listen(0, [{ip, IP}, {active, false} | Opts]),
- Sock.
-
-sock_accept(LSock) ->
- {ok, Sock} = gen_tcp:accept(LSock),
- Sock.
-
-sock_close(undefined) ->
- ok;
-sock_close(Sock) ->
- gen_tcp:close(Sock).
-
-sock_read(Sock) ->
- case gen_tcp:recv(Sock, 0, ?BYTE_TIMEOUT) of
- {ok, Bytes} ->
- {ok, Bytes};
-
- {error, closed} ->
- {closed, closed}; % Yes
-
- %% --- OTP-4770 begin ---
- %%
- %% This seems to happen on windows
- %% "Someone" tried to close an already closed socket...
- %%
-
- {error, enotsock} ->
- {closed, enotsock};
-
- %%
- %% --- OTP-4770 end ---
-
- {error, etimedout} ->
- {error, timeout};
-
- Other ->
- Other
- end.
-
-%% receive
-%% {tcp, Sock, Bytes} ->
-%% {ok, Bytes};
-%% {tcp_closed, Sock} ->
-%% {closed, closed}
-%% end.
-
-sock_write(Sock, Bytes) ->
- gen_tcp:send(Sock, Bytes).
-
-sock_name(Sock) ->
- {ok, {IP, Port}} = inet:sockname(Sock),
- {IP, Port}.
-
-sock_listen_port(LSock) ->
- {ok, Port} = inet:port(LSock),
- Port.
-
-
-%%
-%% ERROR STRINGS
-%%
-errstr({error, Reason}) ->
- errstr(Reason);
-
-errstr(echunk) -> "Synchronisation error during chung sending.";
-errstr(eclosed) -> "Session has been closed.";
-errstr(econn) -> "Connection to remote server prematurely closed.";
-errstr(eexists) ->"File or directory already exists.";
-errstr(ehost) -> "Host not found, FTP server not found, "
-"or connection rejected.";
-errstr(elogin) -> "User not logged in.";
-errstr(enotbinary) -> "Term is not a binary.";
-errstr(epath) -> "No such file or directory, already exists, "
-"or permission denied.";
-errstr(etype) -> "No such type.";
-errstr(euser) -> "User name or password not valid.";
-errstr(etnospc) -> "Insufficient storage space in system.";
-errstr(epnospc) -> "Exceeded storage allocation "
-"(for current directory or dataset).";
-errstr(efnamena) -> "File name not allowed.";
-errstr(Reason) ->
- lists:flatten(io_lib:format("Unknown error: ~w", [Reason])).
-
-
-
-%% ----------------------------------------------------------
-
-get_verbose(Params) -> check_param(verbose,Params).
-
-get_debug(Flags) -> check_param(debug,Flags).
-
-check_param(P,Ps) -> lists:member(P,Ps).
-
-
-%% verbose -> ok
-%%
-%% Prints the string if the Flags list is non-epmty
-%%
-%% Params: F Format string
-%% A Arguments to the format string
-%%
-verbose(F,A) -> verbose(get(verbose),F,A).
-
-verbose(true,F,A) -> print(F,A);
-verbose(_,_F,_A) -> ok.
-
-
-
-
-%% debug -> ok
-%%
-%% Prints the string if debug enabled
-%%
-%% Params: F Format string
-%% A Arguments to the format string
-%%
-debug(F,A) -> debug(get(debug),F,A).
-
-debug(true,F,A) -> print(F,A);
-debug(_,_F,_A) -> ok.
-
-
-print(F,A) -> io:format(F,A).
-
-
-
-transfer_file(Cmd,LFile,RFile,State)->
- #state{csock = CSock, ldir = LDir} = State,
- ARFile = case RFile of
- "" ->
- LFile;
- _ ->
- RFile
- end,
- ALFile = absname(LDir, LFile),
- case file_open(ALFile, read) of
- {ok, Fd} ->
- LSock = listen_data(CSock, binary),
- case ctrl_cmd(CSock, "~s ~s", [Cmd,ARFile]) of
- pos_prel ->
- DSock = accept_data(LSock),
- SFreply = send_file(Fd, DSock),
- file_close(Fd),
- sock_close(DSock),
- case {SFreply,result(CSock)} of
- {ok,pos_compl} ->
- {reply, ok, State};
- {ok,Other} ->
- debug(" error: unknown reply: ~p~n",[Other]),
- {reply, {error, epath}, State};
- {{error,Why},Result} ->
- ?STOP_RET(retcode(Result,econn))
- end;
- {error, enotconn} ->
- ?STOP_RET(econn);
- Other ->
- debug(" error: ctrl failed: ~p~n",[Other]),
- {reply, {error, epath}, State}
- end;
- {error, Reason} ->
- debug(" error: file open: ~p~n",[Reason]),
- {reply, {error, epath}, State}
- end.
-
-transfer_data(Cmd,Bin,RFile,State)->
- #state{csock = CSock, ldir = LDir} = State,
- LSock = listen_data(CSock, binary),
- case ctrl_cmd(CSock, "~s ~s", [Cmd,RFile]) of
- pos_prel ->
- DSock = accept_data(LSock),
- SReply = sock_write(DSock, Bin),
- sock_close(DSock),
- case {SReply,result(CSock)} of
- {ok,pos_compl} ->
- {reply, ok, State};
- {ok,trans_no_space} ->
- ?STOP_RET(etnospc);
- {ok,perm_no_space} ->
- ?STOP_RET(epnospc);
- {ok,perm_fname_not_allowed} ->
- ?STOP_RET(efnamena);
- {ok,Other} ->
- debug(" error: unknown reply: ~p~n",[Other]),
- {reply, {error, epath}, State};
- {{error,Why},Result} ->
- ?STOP_RET(retcode(Result,econn))
- %% {{error,_Why},_Result} ->
- %% ?STOP_RET(econn)
- end;
-
- {error, enotconn} ->
- ?STOP_RET(econn);
-
- Other ->
- debug(" error: ctrl failed: ~p~n",[Other]),
- {reply, {error, epath}, State}
- end.
-
-
-start_chunk_transfer(Cmd, RFile, #state{csock = CSock} = State) ->
- LSock = listen_data(CSock, binary),
- case ctrl_cmd(CSock, "~s ~s", [Cmd,RFile]) of
- pos_prel ->
- DSock = accept_data(LSock),
- {reply, ok, State#state{dsock = DSock, chunk = true}};
- {error, enotconn} ->
- ?STOP_RET(econn);
- Otherwise ->
- debug(" error: ctrl failed: ~p~n",[Otherwise]),
- {reply, {error, epath}, State}
- end.
-
-
-chunk_transfer(Bin,State)->
- #state{dsock = DSock, csock = CSock} = State,
- case DSock of
- undefined ->
- {reply,{error,econn},State};
- _ ->
- case sock_write(DSock, Bin) of
- ok ->
- {reply, ok, State};
- Other ->
- debug(" error: chunk write error: ~p~n",[Other]),
- {reply, {error, econn}, State#state{dsock = undefined}}
- end
- end.
-
-
-
-end_chunk_transfer(State)->
- #state{csock = CSock, dsock = DSock} = State,
- case DSock of
- undefined ->
- Result = result(CSock),
- case Result of
- pos_compl ->
- {reply,ok,State#state{dsock = undefined,
- chunk = false}};
- trans_no_space ->
- ?STOP_RET(etnospc);
- perm_no_space ->
- ?STOP_RET(epnospc);
- perm_fname_not_allowed ->
- ?STOP_RET(efnamena);
- Result ->
- debug(" error: send chunk end (1): ~p~n",
- [Result]),
- {reply,{error,epath},State#state{dsock = undefined,
- chunk = false}}
- end;
- _ ->
- sock_close(DSock),
- Result = result(CSock),
- case Result of
- pos_compl ->
- {reply,ok,State#state{dsock = undefined,
- chunk = false}};
- trans_no_space ->
- sock_close(CSock),
- ?STOP_RET(etnospc);
- perm_no_space ->
- sock_close(CSock),
- ?STOP_RET(epnospc);
- perm_fname_not_allowed ->
- sock_close(CSock),
- ?STOP_RET(efnamena);
- Result ->
- debug(" error: send chunk end (2): ~p~n",
- [Result]),
- {reply,{error,epath},State#state{dsock = undefined,
- chunk = false}}
- end
- end.
-
-get_key1(Key,List,Default)->
- case lists:keysearch(Key,1,List)of
- {value,{_,Val}}->
- Val;
- false->
- Default
- end.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/http.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/http.erl
deleted file mode 100644
index 764e7fb092..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/http.erl
+++ /dev/null
@@ -1,260 +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 Mobile Arts AB
-%% Portions created by Mobile Arts are Copyright 2002, Mobile Arts AB
-%% All Rights Reserved.''
-%%
-%%
-
-%%% This version of the HTTP/1.1 client implements:
-%%% - RFC 2616 HTTP 1.1 client part
-%%% - RFC 2817 Upgrading to TLS Within HTTP/1.1 (not yet!)
-%%% - RFC 2818 HTTP Over TLS
-%%% - RFC 3229 Delta encoding in HTTP (not yet!)
-%%% - RFC 3230 Instance Digests in HTTP (not yet!)
-%%% - RFC 3310 Authentication and Key Agreement (AKA) (not yet!)
-%%% - HTTP/1.1 Specification Errata found at
-%%% http://world.std.com/~lawrence/http_errata.html
-%%% Additionaly follows the following recommendations:
-%%% - RFC 3143 Known HTTP Proxy/Caching Problems (not yet!)
-%%% - draft-nottingham-hdrreg-http-00.txt (not yet!)
-%%%
-%%% Depends on
-%%% - uri.erl for all URL parsing (except what is handled by the C driver)
-%%% - http_lib.erl for all parsing of body and headers
-%%%
-%%% Supported Settings are:
-%%% http_timeout % (int) Milliseconds before a request times out
-%%% http_useproxy % (bool) True if a proxy should be used
-%%% http_proxy % (string) Proxy
-%%% http_noproxylist % (list) List with hosts not requiring proxy
-%%% http_autoredirect % (bool) True if automatic redirection on 30X responses
-%%% http_ssl % (list) SSL settings. A non-empty list enables SSL/TLS
-%%% support in the HTTP client
-%%% http_pipelinesize % (int) Length of pipeline. 1 means no pipeline.
-%%% Only has effect when initiating a new session.
-%%% http_sessions % (int) Max number of open sessions for {Addr,Port}
-%%%
-%%% TODO: (Known bugs!)
-%% - Cache handling
-%% - Doesn't handle a bunch of entity headers properly
-%% - Better handling of status codes different from 200,30X and 50X
-%% - Many of the settings above are not implemented!
-%% - close_session/2 and cancel_request/1 doesn't work
-%% - Variable pipe size.
-%% - Due to the fact that inet_drv only has a single timer, the timeouts given
-%% for pipelined requests are not ok (too long)
-%%
-%% Note:
-%% - Some servers (e.g. Microsoft-IIS/5.0) may sometimes not return a proper
-%% 'Location' header on a redirect.
-%% The client will fail with {error,no_scheme} in these cases.
-
--module(http).
--author("[email protected]").
-
--export([start/0,
- request/3,request/4,cancel_request/1,
- request_sync/2,request_sync/3]).
-
--include("http.hrl").
--include("jnets_httpd.hrl").
-
--define(START_OPTIONS,[]).
-
-%%% HTTP Client manager. Used to store open connections.
-%%% Will be started automatically unless started explicitly.
-start() ->
- application:start(ssl),
- httpc_manager:start().
-
-%%% Asynchronous HTTP request that spawns a handler.
-%%% Method HTTPReq
-%%% options,get,head,delete,trace = {Url,Headers}
-%%% post,put = {Url,Headers,ContentType,Body}
-%%% where Url is a {Scheme,Host,Port,PathQuery} tuple, as returned by uri.erl
-%%%
-%%% Returns: {ok,ReqId} |
-%%% {error,Reason}
-%%% If {ok,Pid} was returned, the handler will return with
-%%% gen_server:cast(From,{Ref,ReqId,{error,Reason}}) |
-%%% gen_server:cast(From,{Ref,ReqId,{Status,Headers,Body}})
-%%% where Reason is an atom and Headers a #res_headers{} record
-%%% http:format_error(Reason) gives a more informative description.
-%%%
-%%% Note:
-%%% - Always try to find an open connection to a given host and port, and use
-%%% the associated socket.
-%%% - Unless a 'Connection: close' header is provided don't close the socket
-%%% after a response is given
-%%% - A given Pid, found in the database, might be terminated before the
-%%% message is sent to the Pid. This will happen e.g., if the connection is
-%%% closed by the other party and there are no pending requests.
-%%% - The HTTP connection process is spawned, if necessary, in
-%%% httpc_manager:add_connection/4
-request(Ref,Method,HTTPReqCont) ->
- request(Ref,Method,HTTPReqCont,[],self()).
-
-request(Ref,Method,HTTPReqCont,Settings) ->
- request(Ref,Method,HTTPReqCont,Settings,self()).
-
-request(Ref,Method,{{Scheme,Host,Port,PathQuery},
- Headers,ContentType,Body},Settings,From) ->
- case create_settings(Settings,#client_settings{}) of
- {error,Reason} ->
- {error,Reason};
- CS ->
- case create_headers(Headers,#req_headers{}) of
- {error,Reason} ->
- {error,Reason};
- H ->
- Req=#request{ref=Ref,from=From,
- scheme=Scheme,address={Host,Port},
- pathquery=PathQuery,method=Method,
- headers=H,content={ContentType,Body},
- settings=CS},
- httpc_manager:request(Req)
- end
- end;
-request(Ref,Method,{Url,Headers},Settings,From) ->
- request(Ref,Method,{Url,Headers,[],[]},Settings,From).
-
-%%% Cancels requests identified with ReqId.
-%%% FIXME! Doesn't work...
-cancel_request(ReqId) ->
- httpc_manager:cancel_request(ReqId).
-
-%%% Close all sessions currently open to Host:Port
-%%% FIXME! Doesn't work...
-close_session(Host,Port) ->
- httpc_manager:close_session(Host,Port).
-
-
-%%% Synchronous HTTP request that waits until a response is created
-%%% (e.g. successfull reply or timeout)
-%%% Method HTTPReq
-%%% options,get,head,delete,trace = {Url,Headers}
-%%% post,put = {Url,Headers,ContentType,Body}
-%%% where Url is a string() or a {Scheme,Host,Port,PathQuery} tuple
-%%%
-%%% Returns: {Status,Headers,Body} |
-%%% {error,Reason}
-%%% where Reason is an atom.
-%%% http:format_error(Reason) gives a more informative description.
-request_sync(Method,HTTPReqCont) ->
- request_sync(Method,HTTPReqCont,[]).
-
-request_sync(Method,{Url,Headers},Settings)
- when Method==options;Method==get;Method==head;Method==delete;Method==trace ->
- case uri:parse(Url) of
- {error,Reason} ->
- {error,Reason};
- ParsedUrl ->
- request_sync(Method,{ParsedUrl,Headers,[],[]},Settings,0)
- end;
-request_sync(Method,{Url,Headers,ContentType,Body},Settings)
- when Method==post;Method==put ->
- case uri:parse(Url) of
- {error,Reason} ->
- {error,Reason};
- ParsedUrl ->
- request_sync(Method,{ParsedUrl,Headers,ContentType,Body},Settings,0)
- end;
-request_sync(Method,Request,Settings) ->
- {error,bad_request}.
-
-request_sync(Method,HTTPCont,Settings,_Redirects) ->
- case request(request_sync,Method,HTTPCont,Settings,self()) of
- {ok,_ReqId} ->
- receive
- {'$gen_cast',{request_sync,_ReqId2,{Status,Headers,Body}}} ->
- {Status,pp_headers(Headers),binary_to_list(Body)};
- {'$gen_cast',{request_sync,_ReqId2,{error,Reason}}} ->
- {error,Reason};
- Error ->
- Error
- end;
- Error ->
- Error
- end.
-
-
-create_settings([],Out) ->
- Out;
-create_settings([{http_timeout,Val}|Settings],Out) ->
- create_settings(Settings,Out#client_settings{timeout=Val});
-create_settings([{http_useproxy,Val}|Settings],Out) ->
- create_settings(Settings,Out#client_settings{useproxy=Val});
-create_settings([{http_proxy,Val}|Settings],Out) ->
- create_settings(Settings,Out#client_settings{proxy=Val});
-create_settings([{http_noproxylist,Val}|Settings],Out) ->
- create_settings(Settings,Out#client_settings{noproxylist=Val});
-create_settings([{http_autoredirect,Val}|Settings],Out) ->
- create_settings(Settings,Out#client_settings{autoredirect=Val});
-create_settings([{http_ssl,Val}|Settings],Out) ->
- create_settings(Settings,Out#client_settings{ssl=Val});
-create_settings([{http_pipelinesize,Val}|Settings],Out)
- when integer(Val),Val>0 ->
- create_settings(Settings,Out#client_settings{max_quelength=Val});
-create_settings([{http_sessions,Val}|Settings],Out)
- when integer(Val),Val>0 ->
- create_settings(Settings,Out#client_settings{max_sessions=Val});
-create_settings([{Key,_Val}|_Settings],_Out) ->
- io:format("ERROR bad settings, got ~p~n",[Key]),
- {error,bad_settings}.
-
-
-create_headers([],Req) ->
- Req;
-create_headers([{Key,Val}|Rest],Req) ->
- case httpd_util:to_lower(Key) of
- "expect" ->
- create_headers(Rest,Req#req_headers{expect=Val});
- OtherKey ->
- create_headers(Rest,
- Req#req_headers{other=[{OtherKey,Val}|
- Req#req_headers.other]})
- end.
-
-
-pp_headers(#res_headers{connection=Connection,
- transfer_encoding=Transfer_encoding,
- retry_after=Retry_after,
- content_length=Content_length,
- content_type=Content_type,
- location=Location,
- other=Other}) ->
- H1=case Connection of
- undefined -> [];
- _ -> [{'Connection',Connection}]
- end,
- H2=case Transfer_encoding of
- undefined -> [];
- _ -> [{'Transfer-Encoding',Transfer_encoding}]
- end,
- H3=case Retry_after of
- undefined -> [];
- _ -> [{'Retry-After',Retry_after}]
- end,
- H4=case Location of
- undefined -> [];
- _ -> [{'Location',Location}]
- end,
- HCL=case Content_length of
- "0" -> [];
- _ -> [{'Content-Length',Content_length}]
- end,
- HCT=case Content_type of
- undefined -> [];
- _ -> [{'Content-Type',Content_type}]
- end,
- H1++H2++H3++H4++HCL++HCT++Other.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/http.hrl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/http.hrl
deleted file mode 100644
index f10ca47a9a..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/http.hrl
+++ /dev/null
@@ -1,127 +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 Mobile Arts AB
-%% Portions created by Mobile Arts are Copyright 2002, Mobile Arts AB
-%% All Rights Reserved.''
-%%
-%%
-
--define(HTTP_REQUEST_TIMEOUT, 5000).
--define(PIPELINE_LENGTH,3).
--define(OPEN_SESSIONS,400).
-
-
-%%% FIXME! These definitions should probably be possible to defined via
-%%% user settings
--define(MAX_REDIRECTS, 4).
-
-
-%%% Note that if not persitent the connection can be closed immediately on a
-%%% response, because new requests are not sent to this connection process.
-%%% address, % ({Host,Port}) Destination Host and Port
--record(session,{
- id, % (int) Session Id identifies session in http_manager
- clientclose, % (bool) true if client requested "close" connection
- scheme, % (atom) http (HTTP/TCP) or https (TCP/SSL/TCP)
- socket, % (socket) Open socket, used by connection
- pipeline=[], % (list) Sent requests, not yet taken care of by the
- % associated http_responder.
- quelength=1, % (int) Current length of pipeline (1 when created)
- max_quelength% (int) Max pipeline length
- }).
-
-%%% [{Pid,RequestQue,QueLength},...] list where
-%%% - RequestQue (implemented with a list) contains sent requests that
-%%% has not yet received a response (pipelined) AND is not currently
-%%% handled (awaiting data) by the session process.
-%%% - QueLength is the length of this que, but
-
-%%% Response headers
--record(res_headers,{
-%%% --- Standard "General" headers
-% cache_control,
- connection,
-% date,
-% pragma,
-% trailer,
- transfer_encoding,
-% upgrade,
-% via,
-% warning,
-%%% --- Standard "Request" headers
-% accept_ranges,
-% age,
-% etag,
- location,
-% proxy_authenticate,
- retry_after,
-% server,
-% vary,
-% www_authenticate,
-%%% --- Standard "Entity" headers
-% allow,
-% content_encoding,
-% content_language,
- content_length="0",
-% content_location,
-% content_md5,
-% content_range,
- content_type,
-% expires,
-% last_modified,
- other=[] % (list) Key/Value list with other headers
- }).
-
-%%% All data associated to a specific HTTP request
--record(request,{
- id, % (int) Request Id
- ref, % Caller specific
- from, % (pid) Caller
- redircount=0,% (int) Number of redirects made for this request
- scheme, % (http|https) (HTTP/TCP) or (TCP/SSL/TCP) connection
- address, % ({Host,Port}) Destination Host and Port
- pathquery, % (string) Rest of parsed URL
- method, % (atom) HTTP request Method
- headers, % (list) Key/Value list with Headers
- content, % ({ContentType,Body}) Current HTTP request
- settings % (#client_settings{}) User defined settings
- }).
-
--record(response,{
- scheme, % (atom) http (HTTP/TCP) or https (TCP/SSL/TCP)
- socket, % (socket) Open socket, used by connection
- status,
- http_version,
- headers=#res_headers{},
- body = <<>>
- }).
-
-
-
-
-%%% HTTP Client settings
--record(client_settings,{
- timeout=?HTTP_REQUEST_TIMEOUT,
- % (int) Milliseconds before a request times out
- useproxy=false, % (bool) True if the proxy should be used
- proxy=undefined, % (tuple) Parsed Proxy URL
- noproxylist=[], % (list) List with hosts not requiring proxy
- autoredirect=true, % (bool) True if automatic redirection on 30X
- % responses.
- max_sessions=?OPEN_SESSIONS,% (int) Max open sessions for any Adr,Port
- max_quelength=?PIPELINE_LENGTH, % (int) Max pipeline length
-% ssl=[{certfile,"/jb/server_root/ssl/ssl_client.pem"},
-% {keyfile,"/jb/server_root/ssl/ssl_client.pem"},
-% {verify,0}]
- ssl=false % (list) SSL settings. A non-empty list enables SSL/TLS
- % support in the HTTP client
- }).
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/http_lib.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/http_lib.erl
deleted file mode 100644
index eb8d7d66b1..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/http_lib.erl
+++ /dev/null
@@ -1,745 +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 Mobile Arts AB
-%% Portions created by Mobile Arts are Copyright 2002, Mobile Arts AB
-%% All Rights Reserved.''
-%%
-%%
-%%% File : http_lib.erl
-%%% Author : Johan Blom <[email protected]>
-%%% Description : Generic, HTTP specific helper functions
-%%% Created : 4 Mar 2002 by Johan Blom
-
-%%% TODO
-%%% - Check if I need to anything special when parsing
-%%% "Content-Type:multipart/form-data"
-
--module(http_lib).
--author("[email protected]").
-
--include("http.hrl").
--include("jnets_httpd.hrl").
-
--export([connection_close/1,
- accept/3,deliver/3,recv/4,recv0/3,
- connect/1,send/3,close/2,controlling_process/3,setopts/3,
- getParameterValue/2,
-% get_var/2,
- create_request_line/3]).
-
--export([read_client_headers/2,read_server_headers/2,
- get_auth_data/1,create_header_list/1,
- read_client_body/2,read_client_multipartrange_body/3,
- read_server_body/2]).
-
-
-%%% Server response:
-%%% Check "Connection" header if server requests session to be closed.
-%%% No 'close' means returns false
-%%% Client Request:
-%%% Check if 'close' in request headers
-%%% Only care about HTTP 1.1 clients!
-connection_close(Headers) when record(Headers,req_headers) ->
- case Headers#req_headers.connection of
- "close" ->
- true;
- "keep-alive" ->
- false;
- Value when list(Value) ->
- true;
- _ ->
- false
- end;
-connection_close(Headers) when record(Headers,res_headers) ->
- case Headers#res_headers.connection of
- "close" ->
- true;
- "keep-alive" ->
- false;
- Value when list(Value) ->
- true;
- _ ->
- false
- end.
-
-
-%% =============================================================================
-%%% Debugging:
-
-% format_time(TS) ->
-% {_,_,MicroSecs}=TS,
-% {{Y,Mon,D},{H,M,S}}=calendar:now_to_universal_time(TS),
-% lists:flatten(io_lib:format("~4.4.0w-~2.2.0w-~2.2.0w,~2.2.0w:~2.2.0w:~6.3.0f",
-% [Y,Mon,D,H,M,S+(MicroSecs/1000000)])).
-
-%% Time in milli seconds
-% t() ->
-% {A,B,C} = erlang:now(),
-% A*1000000000+B*1000+(C div 1000).
-
-% sz(L) when list(L) ->
-% length(L);
-% sz(B) when binary(B) ->
-% size(B);
-% sz(O) ->
-% {unknown_size,O}.
-
-
-%% =============================================================================
-
-getHeaderValue(_Attr,[]) ->
- [];
-getHeaderValue(Attr,[{Attr,Value}|_Rest]) ->
- Value;
-getHeaderValue(Attr,[_|Rest]) ->
- getHeaderValue(Attr,Rest).
-
-getParameterValue(_Attr,undefined) ->
- undefined;
-getParameterValue(Attr,List) ->
- case lists:keysearch(Attr,1,List) of
- {value,{Attr,Val}} ->
- Val;
- _ ->
- undefined
- end.
-
-create_request_line(Method,Path,{Major,Minor}) ->
- [atom_to_list(Method)," ",Path,
- " HTTP/",integer_to_list(Major),".",integer_to_list(Minor)];
-create_request_line(Method,Path,Minor) ->
- [atom_to_list(Method)," ",Path," HTTP/1.",integer_to_list(Minor)].
-
-
-%%% ============================================================================
-read_client_headers(Info,Timeout) ->
- Headers=read_response_h(Info#response.scheme,Info#response.socket,Timeout,
- Info#response.headers),
- Info#response{headers=Headers}.
-
-read_server_headers(Info,Timeout) ->
- Headers=read_request_h(Info#mod.socket_type,Info#mod.socket,Timeout,
- Info#mod.headers),
- Info#mod{headers=Headers}.
-
-
-%% Parses the header of a HTTP request and returns a key,value tuple
-%% list containing Name and Value of each header directive as of:
-%%
-%% Content-Type: multipart/mixed -> {"Content-Type", "multipart/mixed"}
-%%
-%% But in http/1.1 the field-names are case insencitive so now it must be
-%% Content-Type: multipart/mixed -> {"content-type", "multipart/mixed"}
-%% The standard furthermore says that leading and traling white space
-%% is not a part of the fieldvalue and shall therefore be removed.
-read_request_h(SType,S,Timeout,H) ->
- case recv0(SType,S,Timeout) of
- {ok,{http_header,_,'Connection',_,Value}} ->
- read_request_h(SType,S,Timeout,H#req_headers{connection=Value});
- {ok,{http_header,_,'Content-Type',_,Val}} ->
- read_request_h(SType,S,Timeout,H#req_headers{content_type=Val});
- {ok,{http_header,_,'Host',_,Value}} ->
- read_request_h(SType,S,Timeout,H#req_headers{host=Value});
- {ok,{http_header,_,'Content-Length',_,Value}} ->
- read_request_h(SType,S,Timeout,H#req_headers{content_length=Value});
-% {ok,{http_header,_,'Expect',_,Value}} -> % FIXME! Update inet_drv.c!!
-% read_request_h(SType,S,Timeout,H#req_headers{expect=Value});
- {ok,{http_header,_,'Transfer-Encoding',_,V}} ->
- read_request_h(SType,S,Timeout,H#req_headers{transfer_encoding=V});
- {ok,{http_header,_,'Authorization',_,Value}} ->
- read_request_h(SType,S,Timeout,H#req_headers{authorization=Value});
- {ok,{http_header,_,'User-Agent',_,Value}} ->
- read_request_h(SType,S,Timeout,H#req_headers{user_agent=Value});
- {ok,{http_header,_,'Range',_,Value}} ->
- read_request_h(SType,S,Timeout,H#req_headers{range=Value});
- {ok,{http_header,_,'If-Range',_,Value}} ->
- read_request_h(SType,S,Timeout,H#req_headers{if_range=Value});
- {ok,{http_header,_,'If-Match',_,Value}} ->
- read_request_h(SType,S,Timeout,H#req_headers{if_match=Value});
- {ok,{http_header,_,'If-None-Match',_,Value}} ->
- read_request_h(SType,S,Timeout,H#req_headers{if_none_match=Value});
- {ok,{http_header,_,'If-Modified-Since',_,V}} ->
- read_request_h(SType,S,Timeout,H#req_headers{if_modified_since=V});
- {ok,{http_header,_,'If-Unmodified-Since',_,V}} ->
- read_request_h(SType,S,Timeout,H#req_headers{if_unmodified_since=V});
- {ok,{http_header,_,K,_,V}} ->
- read_request_h(SType,S,Timeout,
- H#req_headers{other=H#req_headers.other++[{K,V}]});
- {ok,http_eoh} ->
- H;
- {error, timeout} when SType==http ->
- throw({error, session_local_timeout});
- {error, etimedout} when SType==https ->
- throw({error, session_local_timeout});
- {error, Reason} when Reason==closed;Reason==enotconn ->
- throw({error, session_remotely_closed});
- {error, Reason} ->
- throw({error,Reason})
- end.
-
-
-read_response_h(SType,S,Timeout,H) ->
- case recv0(SType,S,Timeout) of
- {ok,{http_header,_,'Connection',_,Val}} ->
- read_response_h(SType,S,Timeout,H#res_headers{connection=Val});
- {ok,{http_header,_,'Content-Length',_,Val}} ->
- read_response_h(SType,S,Timeout,H#res_headers{content_length=Val});
- {ok,{http_header,_,'Content-Type',_,Val}} ->
- read_response_h(SType,S,Timeout,H#res_headers{content_type=Val});
- {ok,{http_header,_,'Transfer-Encoding',_,V}} ->
- read_response_h(SType,S,Timeout,H#res_headers{transfer_encoding=V});
- {ok,{http_header,_,'Location',_,V}} ->
- read_response_h(SType,S,Timeout,H#res_headers{location=V});
- {ok,{http_header,_,'Retry-After',_,V}} ->
- read_response_h(SType,S,Timeout,H#res_headers{retry_after=V});
- {ok,{http_header,_,K,_,V}} ->
- read_response_h(SType,S,Timeout,
- H#res_headers{other=H#res_headers.other++[{K,V}]});
- {ok,http_eoh} ->
- H;
- {error, timeout} when SType==http ->
- throw({error, session_local_timeout});
- {error, etimedout} when SType==https ->
- throw({error, session_local_timeout});
- {error, Reason} when Reason==closed;Reason==enotconn ->
- throw({error, session_remotely_closed});
- {error, Reason} ->
- throw({error,Reason})
- end.
-
-
-%%% Got the headers, and maybe a part of the body, now read in the rest
-%%% Note:
-%%% - No need to check for Expect header if client
-%%% - Currently no support for setting MaxHeaderSize in client, set to
-%%% unlimited.
-%%% - Move to raw packet mode as we are finished with HTTP parsing
-read_client_body(Info,Timeout) ->
- Headers=Info#response.headers,
- case Headers#res_headers.transfer_encoding of
- "chunked" ->
- ?DEBUG("read_entity_body2()->"
- "Transfer-encoding:Chunked Data:",[]),
- read_client_chunked_body(Info,Timeout,?MAXBODYSIZE);
- Encoding when list(Encoding) ->
- ?DEBUG("read_entity_body2()->"
- "Transfer-encoding:Unknown",[]),
- throw({error,unknown_coding});
- _ ->
- ContLen=list_to_integer(Headers#res_headers.content_length),
- if
- ContLen>?MAXBODYSIZE ->
- throw({error,body_too_big});
- true ->
- ?DEBUG("read_entity_body2()->"
- "Transfer-encoding:none ",[]),
- Info#response{body=read_plain_body(Info#response.scheme,
- Info#response.socket,
- ContLen,
- Info#response.body,
- Timeout)}
- end
- end.
-
-
-%%% ----------------------------------------------------------------------
-read_server_body(Info,Timeout) ->
- MaxBodySz=httpd_util:lookup(Info#mod.config_db,max_body_size,?MAXBODYSIZE),
- ContLen=list_to_integer((Info#mod.headers)#req_headers.content_length),
- %% ?vtrace("ContentLength: ~p", [ContLen]),
- if
- integer(ContLen),integer(MaxBodySz),ContLen>MaxBodySz ->
- throw({error,body_too_big});
- true ->
- read_server_body2(Info,Timeout,ContLen,MaxBodySz)
- end.
-
-
-%%----------------------------------------------------------------------
-%% Control if the body is transfer encoded, if so decode it.
-%% Note:
-%% - MaxBodySz has an integer value or 'nolimit'
-%% - ContLen has an integer value or 'undefined'
-%% All applications MUST be able to receive and decode the "chunked"
-%% transfer-coding, see RFC 2616 Section 3.6.1
-read_server_body2(Info,Timeout,ContLen,MaxBodySz) ->
- ?DEBUG("read_entity_body2()->Max: ~p ~nLength:~p ~nSocket: ~p ~n",
- [MaxBodySz,ContLen,Info#mod.socket]),
- case (Info#mod.headers)#req_headers.transfer_encoding of
- "chunked" ->
- ?DEBUG("read_entity_body2()->"
- "Transfer-encoding:Chunked Data:",[]),
- read_server_chunked_body(Info,Timeout,MaxBodySz);
- Encoding when list(Encoding) ->
- ?DEBUG("read_entity_body2()->"
- "Transfer-encoding:Unknown",[]),
- httpd_response:send_status(Info,501,"Unknown Transfer-Encoding"),
- http_lib:close(Info#mod.socket_type,Info#mod.socket),
- throw({error,{status_sent,"Unknown Transfer-Encoding "++Encoding}});
- _ when integer(ContLen),integer(MaxBodySz),ContLen>MaxBodySz ->
- throw({error,body_too_big});
- _ when integer(ContLen) ->
- ?DEBUG("read_entity_body2()->"
- "Transfer-encoding:none ",[]),
- Info#mod{entity_body=read_plain_body(Info#mod.socket_type,
- Info#mod.socket,
- ContLen,Info#mod.entity_body,
- Timeout)}
- end.
-
-
-%%% ----------------------------------------------------------------------------
-%%% The body was plain, just read it from the socket.
-read_plain_body(_SocketType,Socket,0,Cont,_Timeout) ->
- Cont;
-read_plain_body(SocketType,Socket,ContLen,Cont,Timeout) ->
- Body=read_more_data(SocketType,Socket,ContLen,Timeout),
- <<Cont/binary,Body/binary>>.
-
-%%% ----------------------------------------------------------------------------
-%%% The body was chunked, decode it.
-%%% From RFC2616, Section 3.6.1
-%% Chunked-Body = *chunk
-%% last-chunk
-%% trailer
-%% CRLF
-%%
-%% chunk = chunk-size [ chunk-extension ] CRLF
-%% chunk-data CRLF
-%% chunk-size = 1*HEX
-%% last-chunk = 1*("0") [ chunk-extension ] CRLF
-%%
-%% chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
-%% chunk-ext-name = token
-%% chunk-ext-val = token | quoted-string
-%% chunk-data = chunk-size(OCTET)
-%% trailer = *(entity-header CRLF)
-%%
-%%% "All applications MUST ignore chunk-extension extensions they do not
-%%% understand.", see RFC 2616 Section 3.6.1
-%%% We don't understand any extension...
-read_client_chunked_body(Info,Timeout,MaxChunkSz) ->
- case read_chunk(Info#response.scheme,Info#response.socket,
- Timeout,0,MaxChunkSz) of
- {last_chunk,_ExtensionList} -> % Ignore extension
- TrailH=read_headers_old(Info#response.scheme,Info#response.socket,
- Timeout),
- H=Info#response.headers,
- OtherHeaders=H#res_headers.other++TrailH,
- Info#response{headers=H#res_headers{other=OtherHeaders}};
- {Chunk,ChunkSize,_ExtensionList} -> % Ignore extension
- Info1=Info#response{body= <<(Info#response.body)/binary,
- Chunk/binary>>},
- read_client_chunked_body(Info1,Timeout,MaxChunkSz-ChunkSize);
- {error,Reason} ->
- throw({error,Reason})
- end.
-
-
-read_server_chunked_body(Info,Timeout,MaxChunkSz) ->
- case read_chunk(Info#mod.socket_type,Info#mod.socket,
- Timeout,0,MaxChunkSz) of
- {last_chunk,_ExtensionList} -> % Ignore extension
- TrailH=read_headers_old(Info#mod.socket_type,Info#mod.socket,
- Timeout),
- H=Info#mod.headers,
- OtherHeaders=H#req_headers.other++TrailH,
- Info#mod{headers=H#req_headers{other=OtherHeaders}};
- {Chunk,ChunkSize,_ExtensionList} -> % Ignore extension
- Info1=Info#mod{entity_body= <<(Info#mod.entity_body)/binary,
- Chunk/binary>>},
- read_server_chunked_body(Info1,Timeout,MaxChunkSz-ChunkSize);
- {error,Reason} ->
- throw({error,Reason})
- end.
-
-
-read_chunk(Scheme,Socket,Timeout,Int,MaxChunkSz) when MaxChunkSz>Int ->
- case read_more_data(Scheme,Socket,1,Timeout) of
- <<C>> when $0=<C,C=<$9 ->
- read_chunk(Scheme,Socket,Timeout,16*Int+(C-$0),MaxChunkSz);
- <<C>> when $a=<C,C=<$f ->
- read_chunk(Scheme,Socket,Timeout,16*Int+10+(C-$a),MaxChunkSz);
- <<C>> when $A=<C,C=<$F ->
- read_chunk(Scheme,Socket,Timeout,16*Int+10+(C-$A),MaxChunkSz);
- <<$;>> when Int>0 ->
- ExtensionList=read_chunk_ext_name(Scheme,Socket,Timeout,[],[]),
- read_chunk_data(Scheme,Socket,Int+1,ExtensionList,Timeout);
- <<$;>> when Int==0 ->
- ExtensionList=read_chunk_ext_name(Scheme,Socket,Timeout,[],[]),
- read_data_lf(Scheme,Socket,Timeout),
- {last_chunk,ExtensionList};
- <<?CR>> when Int>0 ->
- read_chunk_data(Scheme,Socket,Int+1,[],Timeout);
- <<?CR>> when Int==0 ->
- read_data_lf(Scheme,Socket,Timeout),
- {last_chunk,[]};
- <<C>> when C==$ -> % Some servers (e.g., Apache 1.3.6) throw in
- % additional whitespace...
- read_chunk(Scheme,Socket,Timeout,Int,MaxChunkSz);
- _Other ->
- {error,unexpected_chunkdata}
- end;
-read_chunk(_Scheme,_Socket,_Timeout,_Int,_MaxChunkSz) ->
- {error,body_too_big}.
-
-
-%%% Note:
-%%% - Got the initial ?CR already!
-%%% - Bitsyntax does not allow matching of ?CR,?LF in the end of the first read
-read_chunk_data(Scheme,Socket,Int,ExtensionList,Timeout) ->
- case read_more_data(Scheme,Socket,Int,Timeout) of
- <<?LF,Chunk/binary>> ->
- case read_more_data(Scheme,Socket,2,Timeout) of
- <<?CR,?LF>> ->
- {Chunk,size(Chunk),ExtensionList};
- _ ->
- {error,bad_chunkdata}
- end;
- _ ->
- {error,bad_chunkdata}
- end.
-
-read_chunk_ext_name(Scheme,Socket,Timeout,Name,Acc) ->
- Len=length(Name),
- case read_more_data(Scheme,Socket,1,Timeout) of
- $= when Len>0 ->
- read_chunk_ext_val(Scheme,Socket,Timeout,Name,[],Acc);
- $; when Len>0 ->
- read_chunk_ext_name(Scheme,Socket,Timeout,[],
- [{lists:reverse(Name),""}|Acc]);
- ?CR when Len>0 ->
- lists:reverse([{lists:reverse(Name,"")}|Acc]);
- Token -> % FIXME Check that it is "token"
- read_chunk_ext_name(Scheme,Socket,Timeout,[Token|Name],Acc);
- _ ->
- {error,bad_chunk_extension_name}
- end.
-
-read_chunk_ext_val(Scheme,Socket,Timeout,Name,Val,Acc) ->
- Len=length(Val),
- case read_more_data(Scheme,Socket,1,Timeout) of
- $; when Len>0 ->
- read_chunk_ext_name(Scheme,Socket,Timeout,[],
- [{Name,lists:reverse(Val)}|Acc]);
- ?CR when Len>0 ->
- lists:reverse([{Name,lists:reverse(Val)}|Acc]);
- Token -> % FIXME Check that it is "token" or "quoted-string"
- read_chunk_ext_val(Scheme,Socket,Timeout,Name,[Token|Val],Acc);
- _ ->
- {error,bad_chunk_extension_value}
- end.
-
-read_data_lf(Scheme,Socket,Timeout) ->
- case read_more_data(Scheme,Socket,1,Timeout) of
- ?LF ->
- ok;
- _ ->
- {error,bad_chunkdata}
- end.
-
-%%% ----------------------------------------------------------------------------
-%%% The body was "multipart/byteranges", decode it.
-%%% Example from RFC 2616, Appendix 19.2
-%%% HTTP/1.1 206 Partial Content
-%%% Date: Wed, 15 Nov 1995 06:25:24 GMT
-%%% Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
-%%% Content-type: multipart/byteranges; boundary=THIS_STRING_SEPARATES
-%%%
-%%% --THIS_STRING_SEPARATES
-%%% Content-type: application/pdf
-%%% Content-range: bytes 500-999/8000
-%%%
-%%% ...the first range...
-%%% --THIS_STRING_SEPARATES
-%%% Content-type: application/pdf
-%%% Content-range: bytes 7000-7999/8000
-%%%
-%%% ...the second range
-%%% --THIS_STRING_SEPARATES--
-%%%
-%%% Notes:
-%%%
-%%% 1) Additional CRLFs may precede the first boundary string in the
-%%% entity.
-%%% FIXME!!
-read_client_multipartrange_body(Info,Parstr,Timeout) ->
- Boundary=get_boundary(Parstr),
- scan_boundary(Info,Boundary),
- Info#response{body=read_multipart_body(Info,Boundary,Timeout)}.
-
-read_multipart_body(Info,Boundary,Timeout) ->
- Info.
-
-% Headers=read_headers_old(Info#response.scheme,Info#response.socket,Timeout),
-% H=Info#response.headers,
-% OtherHeaders=H#res_headers.other++TrailH,
-% Info#response{headers=H#res_headers{other=OtherHeaders}}.
-
-
-scan_boundary(Info,Boundary) ->
- Info.
-
-
-get_boundary(Parstr) ->
- case skip_lwsp(Parstr) of
- [] ->
- throw({error,missing_range_boundary_parameter});
- Val ->
- get_boundary2(string:tokens(Val, ";"))
- end.
-
-get_boundary2([]) ->
- undefined;
-get_boundary2([Param|Rest]) ->
- case string:tokens(skip_lwsp(Param), "=") of
- ["boundary"++Attribute,Value] ->
- Value;
- _ ->
- get_boundary2(Rest)
- end.
-
-
-%% skip space & tab
-skip_lwsp([$ | Cs]) -> skip_lwsp(Cs);
-skip_lwsp([$\t | Cs]) -> skip_lwsp(Cs);
-skip_lwsp(Cs) -> Cs.
-
-%%% ----------------------------------------------------------------------------
-
-%%% Read the incoming data from the open socket.
-read_more_data(http,Socket,Len,Timeout) ->
- case gen_tcp:recv(Socket,Len,Timeout) of
- {ok,Val} ->
- Val;
- {error, timeout} ->
- throw({error, session_local_timeout});
- {error, Reason} when Reason==closed;Reason==enotconn ->
- throw({error, session_remotely_closed});
- {error, Reason} ->
-% httpd_response:send_status(Info,400,none),
- throw({error, Reason})
- end;
-read_more_data(https,Socket,Len,Timeout) ->
- case ssl:recv(Socket,Len,Timeout) of
- {ok,Val} ->
- Val;
- {error, etimedout} ->
- throw({error, session_local_timeout});
- {error, Reason} when Reason==closed;Reason==enotconn ->
- throw({error, session_remotely_closed});
- {error, Reason} ->
-% httpd_response:send_status(Info,400,none),
- throw({error, Reason})
- end.
-
-
-%% =============================================================================
-%%% Socket handling
-
-accept(http,ListenSocket, Timeout) ->
- gen_tcp:accept(ListenSocket, Timeout);
-accept(https,ListenSocket, Timeout) ->
- ssl:accept(ListenSocket, Timeout).
-
-
-close(http,Socket) ->
- gen_tcp:close(Socket);
-close(https,Socket) ->
- ssl:close(Socket).
-
-
-connect(#request{scheme=http,settings=Settings,address=Addr}) ->
- case proxyusage(Addr,Settings) of
- {error,Reason} ->
- {error,Reason};
- {Host,Port} ->
- Opts=[binary,{active,false},{reuseaddr,true}],
- gen_tcp:connect(Host,Port,Opts)
- end;
-connect(#request{scheme=https,settings=Settings,address=Addr}) ->
- case proxyusage(Addr,Settings) of
- {error,Reason} ->
- {error,Reason};
- {Host,Port} ->
- Opts=case Settings#client_settings.ssl of
- false ->
- [binary,{active,false}];
- SSLSettings ->
- [binary,{active,false}]++SSLSettings
- end,
- ssl:connect(Host,Port,Opts)
- end.
-
-
-%%% Check to see if the given {Host,Port} tuple is in the NoProxyList
-%%% Returns an eventually updated {Host,Port} tuple, with the proxy address
-proxyusage(HostPort,Settings) ->
- case Settings#client_settings.useproxy of
- true ->
- case noProxy(HostPort,Settings#client_settings.noproxylist) of
- true ->
- HostPort;
- _ ->
- case Settings#client_settings.proxy of
- undefined ->
- {error,no_proxy_defined};
- ProxyHostPort ->
- ProxyHostPort
- end
- end;
- _ ->
- HostPort
- end.
-
-noProxy(_HostPort,[]) ->
- false;
-noProxy({Host,Port},[{Host,Port}|Rest]) ->
- true;
-noProxy(HostPort,[_|Rest]) ->
- noProxy(HostPort,Rest).
-
-
-controlling_process(http,Socket,Pid) ->
- gen_tcp:controlling_process(Socket,Pid);
-controlling_process(https,Socket,Pid) ->
- ssl:controlling_process(Socket,Pid).
-
-
-deliver(SocketType, Socket, Message) ->
- case send(SocketType, Socket, Message) of
- {error, einval} ->
- close(SocketType, Socket),
- socket_closed;
- {error, _Reason} ->
-% ?vlog("deliver(~p) failed for reason:"
-% "~n Reason: ~p",[SocketType,_Reason]),
- close(SocketType, Socket),
- socket_closed;
- _Other ->
- ok
- end.
-
-
-recv0(http,Socket,Timeout) ->
- gen_tcp:recv(Socket,0,Timeout);
-recv0(https,Socket,Timeout) ->
- ssl:recv(Socket,0,Timeout).
-
-recv(http,Socket,Len,Timeout) ->
- gen_tcp:recv(Socket,Len,Timeout);
-recv(https,Socket,Len,Timeout) ->
- ssl:recv(Socket,Len,Timeout).
-
-
-setopts(http,Socket,Options) ->
- inet:setopts(Socket,Options);
-setopts(https,Socket,Options) ->
- ssl:setopts(Socket,Options).
-
-
-send(http,Socket,Message) ->
- gen_tcp:send(Socket,Message);
-send(https,Socket,Message) ->
- ssl:send(Socket,Message).
-
-
-%%% ============================================================================
-%%% HTTP Server only
-
-%%% Returns the Authenticating data in the HTTP request
-get_auth_data("Basic "++EncodedString) ->
- UnCodedString=httpd_util:decode_base64(EncodedString),
- case catch string:tokens(UnCodedString,":") of
- [User,PassWord] ->
- {User,PassWord};
- {error,Error}->
- {error,Error}
- end;
-get_auth_data(BadCredentials) when list(BadCredentials) ->
- {error,BadCredentials};
-get_auth_data(_) ->
- {error,nouser}.
-
-
-create_header_list(H) ->
- lookup(connection,H#req_headers.connection)++
- lookup(host,H#req_headers.host)++
- lookup(content_length,H#req_headers.content_length)++
- lookup(transfer_encoding,H#req_headers.transfer_encoding)++
- lookup(authorization,H#req_headers.authorization)++
- lookup(user_agent,H#req_headers.user_agent)++
- lookup(user_agent,H#req_headers.range)++
- lookup(user_agent,H#req_headers.if_range)++
- lookup(user_agent,H#req_headers.if_match)++
- lookup(user_agent,H#req_headers.if_none_match)++
- lookup(user_agent,H#req_headers.if_modified_since)++
- lookup(user_agent,H#req_headers.if_unmodified_since)++
- H#req_headers.other.
-
-lookup(_Key,undefined) ->
- [];
-lookup(Key,Val) ->
- [{Key,Val}].
-
-
-
-%%% ============================================================================
-%%% This code is for parsing trailer headers in chunked messages.
-%%% Will be deprecated whenever I have found an alternative working solution!
-%%% Note:
-%%% - The header names are returned slighly different from what the what
-%%% inet_drv returns
-read_headers_old(Scheme,Socket,Timeout) ->
- read_headers_old(<<>>,Scheme,Socket,Timeout,[],[]).
-
-read_headers_old(<<>>,Scheme,Socket,Timeout,Acc,AccHdrs) ->
- read_headers_old(read_more_data(Scheme,Socket,1,Timeout),
- Scheme,Socket,Timeout,Acc,AccHdrs);
-read_headers_old(<<$\r>>,Scheme,Socket,Timeout,Acc,AccHdrs) ->
- read_headers_old(<<$\r,(read_more_data(Scheme,Socket,1,Timeout))/binary>>,
- Scheme,Socket,Timeout,Acc,AccHdrs);
-read_headers_old(<<$\r,$\n>>,Scheme,Socket,Timeout,Acc,AccHdrs) ->
- if
- Acc==[] -> % Done!
- tagup_header(lists:reverse(AccHdrs));
- true ->
- read_headers_old(read_more_data(Scheme,Socket,1,Timeout),
- Scheme,Socket,
- Timeout,[],[lists:reverse(Acc)|AccHdrs])
- end;
-read_headers_old(<<C>>,Scheme,Socket,Timeout,Acc,AccHdrs) ->
- read_headers_old(read_more_data(Scheme,Socket,1,Timeout),
- Scheme,Socket,Timeout,[C|Acc],AccHdrs);
-read_headers_old(Bin,_Scheme,_Socket,_Timeout,_Acc,_AccHdrs) ->
- io:format("ERROR: Unexpected data from inet driver: ~p",[Bin]),
- throw({error,this_is_a_bug}).
-
-
-%% Parses the header of a HTTP request and returns a key,value tuple
-%% list containing Name and Value of each header directive as of:
-%%
-%% Content-Type: multipart/mixed -> {"Content-Type", "multipart/mixed"}
-%%
-%% But in http/1.1 the field-names are case insencitive so now it must be
-%% Content-Type: multipart/mixed -> {"content-type", "multipart/mixed"}
-%% The standard furthermore says that leading and traling white space
-%% is not a part of the fieldvalue and shall therefore be removed.
-tagup_header([]) -> [];
-tagup_header([Line|Rest]) -> [tag(Line, [])|tagup_header(Rest)].
-
-tag([], Tag) ->
- {httpd_util:to_lower(lists:reverse(Tag)), ""};
-tag([$:|Rest], Tag) ->
- {httpd_util:to_lower(lists:reverse(Tag)), httpd_util:strip(Rest)};
-tag([Chr|Rest], Tag) ->
- tag(Rest, [Chr|Tag]).
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpc_handler.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpc_handler.erl
deleted file mode 100644
index 5076a12aaa..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpc_handler.erl
+++ /dev/null
@@ -1,724 +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 Mobile Arts AB
-%% Portions created by Mobile Arts are Copyright 2002, Mobile Arts AB
-%% All Rights Reserved.''
-%%
-%%
-
-%%% TODO:
-%%% - If an error is returned when sending a request, don't use this
-%%% session anymore.
-%%% - Closing of sessions not properly implemented for some cases
-
-%%% File : httpc_handler.erl
-%%% Author : Johan Blom <[email protected]>
-%%% Description : Handles HTTP client responses, for a single TCP session
-%%% Created : 4 Mar 2002 by Johan Blom
-
--module(httpc_handler).
-
--include("http.hrl").
--include("jnets_httpd.hrl").
-
--export([init_connection/2,http_request/2]).
-
-%%% ==========================================================================
-%%% "Main" function in the spawned process for the session.
-init_connection(Req,Session) when record(Req,request) ->
- case catch http_lib:connect(Req) of
- {ok,Socket} ->
- case catch http_request(Req,Socket) of
- ok ->
- case Session#session.clientclose of
- true ->
- ok;
- false ->
- httpc_manager:register_socket(Req#request.address,
- Session#session.id,
- Socket)
- end,
- next_response_with_request(Req,
- Session#session{socket=Socket});
- {error,Reason} -> % Not possible to use new session
- gen_server:cast(Req#request.from,
- {Req#request.ref,Req#request.id,{error,Reason}}),
- exit_session_ok(Req#request.address,
- Session#session{socket=Socket})
- end;
- {error,Reason} -> % Not possible to set up new session
- gen_server:cast(Req#request.from,
- {Req#request.ref,Req#request.id,{error,Reason}}),
- exit_session_ok2(Req#request.address,
- Session#session.clientclose,Session#session.id)
- end.
-
-next_response_with_request(Req,Session) ->
- Timeout=(Req#request.settings)#client_settings.timeout,
- case catch read(Timeout,Session#session.scheme,Session#session.socket) of
- {Status,Headers,Body} ->
- NewReq=handle_response({Status,Headers,Body},Timeout,Req,Session),
- next_response_with_request(NewReq,Session);
- {error,Reason} ->
- gen_server:cast(Req#request.from,
- {Req#request.ref,Req#request.id,{error,Reason}}),
- exit_session(Req#request.address,Session,aborted_request);
- {'EXIT',Reason} ->
- gen_server:cast(Req#request.from,
- {Req#request.ref,Req#request.id,{error,Reason}}),
- exit_session(Req#request.address,Session,aborted_request)
- end.
-
-handle_response(Response,Timeout,Req,Session) ->
- case http_response(Response,Req,Session) of
- ok ->
- next_response(Timeout,Req#request.address,Session);
- stop ->
- exit(normal);
- {error,Reason} ->
- gen_server:cast(Req#request.from,
- {Req#request.ref,Req#request.id,{error,Reason}}),
- exit_session(Req#request.address,Session,aborted_request)
- end.
-
-
-
-%%% Wait for the next respond until
-%%% - session is closed by the other side
-%%% => set up a new a session, if there are pending requests in the que
-%%% - "Connection:close" header is received
-%%% => close the connection (release socket) then
-%%% set up a new a session, if there are pending requests in the que
-%%%
-%%% Note:
-%%% - When invoked there are no pending responses on received requests.
-%%% - Never close the session explicitly, let it timeout instead!
-next_response(Timeout,Address,Session) ->
- case httpc_manager:next_request(Address,Session#session.id) of
- no_more_requests ->
- %% There are no more pending responses, now just wait for
- %% timeout or a new response.
- case catch read(Timeout,
- Session#session.scheme,Session#session.socket) of
- {error,Reason} when Reason==session_remotely_closed;
- Reason==session_local_timeout ->
- exit_session_ok(Address,Session);
- {error,Reason} ->
- exit_session(Address,Session,aborted_request);
- {'EXIT',Reason} ->
- exit_session(Address,Session,aborted_request);
- {Status2,Headers2,Body2} ->
- case httpc_manager:next_request(Address,
- Session#session.id) of
- no_more_requests -> % Should not happen!
- exit_session(Address,Session,aborted_request);
- {error,Reason} -> % Should not happen!
- exit_session(Address,Session,aborted_request);
- NewReq ->
- handle_response({Status2,Headers2,Body2},
- Timeout,NewReq,Session)
- end
- end;
- {error,Reason} -> % The connection has been closed by httpc_manager
- exit_session(Address,Session,aborted_request);
- NewReq ->
- NewReq
- end.
-
-%% ===========================================================================
-%% Internals
-
-%%% Read in and parse response data from the socket
-read(Timeout,SockType,Socket) ->
- Info=#response{scheme=SockType,socket=Socket},
- http_lib:setopts(SockType,Socket,[{packet, http}]),
- Info1=read_response(SockType,Socket,Info,Timeout),
- http_lib:setopts(SockType,Socket,[binary,{packet, raw}]),
- case (Info1#response.headers)#res_headers.content_type of
- "multipart/byteranges"++Param ->
- range_response_body(Info1,Timeout,Param);
- _ ->
- #response{status=Status2,headers=Headers2,body=Body2}=
- http_lib:read_client_body(Info1,Timeout),
- {Status2,Headers2,Body2}
- end.
-
-
-%%% From RFC 2616:
-%%% Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
-%%% HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
-%%% Status-Code = 3DIGIT
-%%% Reason-Phrase = *<TEXT, excluding CR, LF>
-read_response(SockType,Socket,Info,Timeout) ->
- case http_lib:recv0(SockType,Socket,Timeout) of
- {ok,{http_response,{1,VerMin}, Status, _Phrase}} when VerMin==0;
- VerMin==1 ->
- Info1=Info#response{status=Status,http_version=VerMin},
- http_lib:read_client_headers(Info1,Timeout);
- {ok,{http_response,_Version, _Status, _Phrase}} ->
- throw({error,bad_status_line});
- {error, timeout} ->
- throw({error,session_local_timeout});
- {error, Reason} when Reason==closed;Reason==enotconn ->
- throw({error,session_remotely_closed});
- {error, Reason} ->
- throw({error,Reason})
- end.
-
-%%% From RFC 2616, Section 4.4, Page 34
-%% 4.If the message uses the media type "multipart/byteranges", and the
-%% transfer-length is not otherwise specified, then this self-
-%% delimiting media type defines the transfer-length. This media type
-%% MUST NOT be used unless the sender knows that the recipient can parse
-%% it; the presence in a request of a Range header with multiple byte-
-%% range specifiers from a 1.1 client implies that the client can parse
-%% multipart/byteranges responses.
-%%% FIXME !!
-range_response_body(Info,Timeout,Param) ->
- Headers=Info#response.headers,
- case {Headers#res_headers.content_length,
- Headers#res_headers.transfer_encoding} of
- {undefined,undefined} ->
- #response{status=Status2,headers=Headers2,body=Body2}=
- http_lib:read_client_multipartrange_body(Info,Param,Timeout),
- {Status2,Headers2,Body2};
- _ ->
- #response{status=Status2,headers=Headers2,body=Body2}=
- http_lib:read_client_body(Info,Timeout),
- {Status2,Headers2,Body2}
- end.
-
-
-%%% ----------------------------------------------------------------------------
-%%% Host: field is required when addressing multi-homed sites ...
-%%% It must not be present when the request is being made to a proxy.
-http_request(#request{method=Method,id=Id,
- scheme=Scheme,address={Host,Port},pathquery=PathQuery,
- headers=Headers, content={ContentType,Body},
- settings=Settings},
- Socket) ->
- PostData=
- if
- Method==post;Method==put ->
- case Headers#req_headers.expect of
- "100-continue" ->
- content_type_header(ContentType) ++
- content_length_header(length(Body)) ++
- "\r\n";
- _ ->
- content_type_header(ContentType) ++
- content_length_header(length(Body)) ++
- "\r\n" ++ Body
- end;
- true ->
- "\r\n"
- end,
- Message=
- case useProxy(Settings#client_settings.useproxy,
- {Scheme,Host,Port,PathQuery}) of
- false ->
- method(Method)++" "++PathQuery++" HTTP/1.1\r\n"++
- host_header(Host)++te_header()++
- headers(Headers) ++ PostData;
- AbsURI ->
- method(Method)++" "++AbsURI++" HTTP/1.1\r\n"++
- te_header()++
- headers(Headers)++PostData
- end,
- http_lib:send(Scheme,Socket,Message).
-
-useProxy(false,_) ->
- false;
-useProxy(true,{Scheme,Host,Port,PathQuery}) ->
- [atom_to_list(Scheme),"://",Host,":",integer_to_list(Port),PathQuery].
-
-
-
-headers(#req_headers{expect=Expect,
- other=Other}) ->
- H1=case Expect of
- undefined ->[];
- _ -> "Expect: "++Expect++"\r\n"
- end,
- H1++headers_other(Other).
-
-
-headers_other([]) ->
- [];
-headers_other([{Key,Value}|Rest]) when atom(Key) ->
- Head = atom_to_list(Key)++": "++Value++"\r\n",
- Head ++ headers_other(Rest);
-headers_other([{Key,Value}|Rest]) ->
- Head = Key++": "++Value++"\r\n",
- Head ++ headers_other(Rest).
-
-host_header(Host) ->
- "Host: "++lists:concat([Host])++"\r\n".
-content_type_header(ContentType) ->
- "Content-Type: " ++ ContentType ++ "\r\n".
-content_length_header(ContentLength) ->
- "Content-Length: "++integer_to_list(ContentLength) ++ "\r\n".
-te_header() ->
- "TE: \r\n".
-
-method(Method) ->
- httpd_util:to_upper(atom_to_list(Method)).
-
-
-%%% ----------------------------------------------------------------------------
-http_response({Status,Headers,Body},Req,Session) ->
- case Status of
- 100 ->
- status_continue(Req,Session);
- 200 ->
- gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
- {Status,Headers,Body}}),
- ServerClose=http_lib:connection_close(Headers),
- handle_connection(Session#session.clientclose,ServerClose,
- Req,Session);
- 300 -> status_multiple_choices(Headers,Body,Req,Session);
- 301 -> status_moved_permanently(Req#request.method,
- Headers,Body,Req,Session);
- 302 -> status_found(Headers,Body,Req,Session);
- 303 -> status_see_other(Headers,Body,Req,Session);
- 304 -> status_not_modified(Headers,Body,Req,Session);
- 305 -> status_use_proxy(Headers,Body,Req,Session);
- %% 306 This Status code is not used in HTTP 1.1
- 307 -> status_temporary_redirect(Headers,Body,Req,Session);
- 503 -> status_service_unavailable({Status,Headers,Body},Req,Session);
- Status50x when Status50x==500;Status50x==501;Status50x==502;
- Status50x==504;Status50x==505 ->
- status_server_error_50x({Status,Headers,Body},Req,Session);
- _ -> % FIXME May want to take some action on other Status codes as well
- gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
- {Status,Headers,Body}}),
- ServerClose=http_lib:connection_close(Headers),
- handle_connection(Session#session.clientclose,ServerClose,
- Req,Session)
- end.
-
-
-%%% Status code dependent functions.
-
-%%% Received a 100 Status code ("Continue")
-%%% From RFC2616
-%%% The client SHOULD continue with its request. This interim response is
-%%% used to inform the client that the initial part of the request has
-%%% been received and has not yet been rejected by the server. The client
-%%% SHOULD continue by sending the remainder of the request or, if the
-%%% request has already been completed, ignore this response. The server
-%%% MUST send a final response after the request has been completed. See
-%%% section 8.2.3 for detailed discussion of the use and handling of this
-%%% status code.
-status_continue(Req,Session) ->
- {_,Body}=Req#request.content,
- http_lib:send(Session#session.scheme,Session#session.socket,Body),
- next_response_with_request(Req,Session).
-
-
-%%% Received a 300 Status code ("Multiple Choices")
-%%% The resource is located in any one of a set of locations
-%%% - If a 'Location' header is present (preserved server choice), use that
-%%% to automatically redirect to the given URL
-%%% - else if the Content-Type/Body both are non-empty let the user agent make
-%%% the choice and thus return a response with status 300
-%%% Note:
-%%% - If response to a HEAD request, the Content-Type/Body both should be empty.
-%%% - The behaviour on an empty Content-Type or Body is unspecified.
-%%% However, e.g. "Apache/1.3" servers returns both empty if the header
-%%% 'if-modified-since: Date' was sent in the request and the content is
-%%% "not modified" (instead of 304). Thus implicitly giving the cache as the
-%%% only choice.
-status_multiple_choices(Headers,Body,Req,Session)
- when ((Req#request.settings)#client_settings.autoredirect)==true ->
- ServerClose=http_lib:connection_close(Headers),
- case Headers#res_headers.location of
- undefined ->
- gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
- {300,Headers,Body}}),
- handle_connection(Session#session.clientclose,ServerClose,
- Req,Session);
- RedirUrl ->
- Scheme=Session#session.scheme,
- case uri:parse(RedirUrl) of
- {error,Reason} ->
- {error,Reason};
- {Scheme,Host,Port,PathQuery} -> % Automatic redirection
- NewReq=Req#request{redircount=Req#request.redircount+1,
- address={Host,Port},pathquery=PathQuery},
- handle_redirect(Session#session.clientclose,ServerClose,
- NewReq,Session)
- end
- end;
-status_multiple_choices(Headers,Body,Req,Session) ->
- ServerClose=http_lib:connection_close(Headers),
- gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
- {300,Headers,Body}}),
- handle_connection(Session#session.clientclose,ServerClose,Req,Session).
-
-
-%%% Received a 301 Status code ("Moved Permanently")
-%%% The resource has been assigned a new permanent URI
-%%% - If a 'Location' header is present, use that to automatically redirect to
-%%% the given URL if GET or HEAD request
-%%% - else return
-%%% Note:
-%%% - The Body should contain a short hypertext note with a hyperlink to the
-%%% new URI. Return this if Content-Type acceptable (some HTTP servers doesn't
-%%% deal properly with Accept headers)
-status_moved_permanently(Method,Headers,Body,Req,Session)
- when (((Req#request.settings)#client_settings.autoredirect)==true) and
- (Method==get) or (Method==head) ->
- ServerClose=http_lib:connection_close(Headers),
- case Headers#res_headers.location of
- undefined ->
- gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
- {301,Headers,Body}}),
- handle_connection(Session#session.clientclose,ServerClose,
- Req,Session);
- RedirUrl ->
- Scheme=Session#session.scheme,
- case uri:parse(RedirUrl) of
- {error,Reason} ->
- {error,Reason};
- {Scheme,Host,Port,PathQuery} -> % Automatic redirection
- NewReq=Req#request{redircount=Req#request.redircount+1,
- address={Host,Port},pathquery=PathQuery},
- handle_redirect(Session#session.clientclose,ServerClose,
- NewReq,Session)
- end
- end;
-status_moved_permanently(_Method,Headers,Body,Req,Session) ->
- ServerClose=http_lib:connection_close(Headers),
- gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
- {301,Headers,Body}}),
- handle_connection(Session#session.clientclose,ServerClose,Req,Session).
-
-
-%%% Received a 302 Status code ("Found")
-%%% The requested resource resides temporarily under a different URI.
-%%% Note:
-%%% - Only cacheable if indicated by a Cache-Control or Expires header
-status_found(Headers,Body,Req,Session)
- when ((Req#request.settings)#client_settings.autoredirect)==true ->
- ServerClose=http_lib:connection_close(Headers),
- case Headers#res_headers.location of
- undefined ->
- gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
- {302,Headers,Body}}),
- handle_connection(Session#session.clientclose,ServerClose,
- Req,Session);
- RedirUrl ->
- Scheme=Session#session.scheme,
- case uri:parse(RedirUrl) of
- {error,Reason} ->
- {error,Reason};
- {Scheme,Host,Port,PathQuery} -> % Automatic redirection
- NewReq=Req#request{redircount=Req#request.redircount+1,
- address={Host,Port},pathquery=PathQuery},
- handle_redirect(Session#session.clientclose,ServerClose,
- NewReq,Session)
- end
- end;
-status_found(Headers,Body,Req,Session) ->
- ServerClose=http_lib:connection_close(Headers),
- gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
- {302,Headers,Body}}),
- handle_connection(Session#session.clientclose,ServerClose,Req,Session).
-
-%%% Received a 303 Status code ("See Other")
-%%% The request found under a different URI and should be retrieved using GET
-%%% Note:
-%%% - Must not be cached
-status_see_other(Headers,Body,Req,Session)
- when ((Req#request.settings)#client_settings.autoredirect)==true ->
- ServerClose=http_lib:connection_close(Headers),
- case Headers#res_headers.location of
- undefined ->
- gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
- {303,Headers,Body}}),
- handle_connection(Session#session.clientclose,ServerClose,
- Req,Session);
- RedirUrl ->
- Scheme=Session#session.scheme,
- case uri:parse(RedirUrl) of
- {error,Reason} ->
- {error,Reason};
- {Scheme,Host,Port,PathQuery} -> % Automatic redirection
- NewReq=Req#request{redircount=Req#request.redircount+1,
- method=get,
- address={Host,Port},pathquery=PathQuery},
- handle_redirect(Session#session.clientclose,ServerClose,
- NewReq,Session)
- end
- end;
-status_see_other(Headers,Body,Req,Session) ->
- ServerClose=http_lib:connection_close(Headers),
- gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
- {303,Headers,Body}}),
- handle_connection(Session#session.clientclose,ServerClose,Req,Session).
-
-
-%%% Received a 304 Status code ("Not Modified")
-%%% Note:
-%%% - The response MUST NOT contain a body.
-%%% - The response MUST include the following header fields:
-%%% - Date, unless its omission is required
-%%% - ETag and/or Content-Location, if the header would have been sent
-%%% in a 200 response to the same request
-%%% - Expires, Cache-Control, and/or Vary, if the field-value might
-%%% differ from that sent in any previous response for the same
-%%% variant
-status_not_modified(Headers,Body,Req,Session)
- when ((Req#request.settings)#client_settings.autoredirect)==true ->
- ServerClose=http_lib:connection_close(Headers),
- case Headers#res_headers.location of
- undefined ->
- gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
- {304,Headers,Body}}),
- handle_connection(Session#session.clientclose,ServerClose,
- Req,Session);
- RedirUrl ->
- Scheme=Session#session.scheme,
- case uri:parse(RedirUrl) of
- {error,Reason} ->
- {error,Reason};
- {Scheme,Host,Port,PathQuery} -> % Automatic redirection
- NewReq=Req#request{redircount=Req#request.redircount+1,
- address={Host,Port},pathquery=PathQuery},
- handle_redirect(Session#session.clientclose,ServerClose,
- NewReq,Session)
- end
- end;
-status_not_modified(Headers,Body,Req,Session) ->
- ServerClose=http_lib:connection_close(Headers),
- gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
- {304,Headers,Body}}),
- handle_connection(Session#session.clientclose,ServerClose,Req,Session).
-
-
-
-%%% Received a 305 Status code ("Use Proxy")
-%%% The requested resource MUST be accessed through the proxy given by the
-%%% Location field
-status_use_proxy(Headers,Body,Req,Session)
- when ((Req#request.settings)#client_settings.autoredirect)==true ->
- ServerClose=http_lib:connection_close(Headers),
- case Headers#res_headers.location of
- undefined ->
- gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
- {305,Headers,Body}}),
- handle_connection(Session#session.clientclose,ServerClose,
- Req,Session);
- RedirUrl ->
- Scheme=Session#session.scheme,
- case uri:parse(RedirUrl) of
- {error,Reason} ->
- {error,Reason};
- {Scheme,Host,Port,PathQuery} -> % Automatic redirection
- NewReq=Req#request{redircount=Req#request.redircount+1,
- address={Host,Port},pathquery=PathQuery},
- handle_redirect(Session#session.clientclose,ServerClose,
- NewReq,Session)
- end
- end;
-status_use_proxy(Headers,Body,Req,Session) ->
- ServerClose=http_lib:connection_close(Headers),
- gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
- {305,Headers,Body}}),
- handle_connection(Session#session.clientclose,ServerClose,Req,Session).
-
-
-%%% Received a 307 Status code ("Temporary Redirect")
-status_temporary_redirect(Headers,Body,Req,Session)
- when ((Req#request.settings)#client_settings.autoredirect)==true ->
- ServerClose=http_lib:connection_close(Headers),
- case Headers#res_headers.location of
- undefined ->
- gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
- {307,Headers,Body}}),
- handle_connection(Session#session.clientclose,ServerClose,
- Req,Session);
- RedirUrl ->
- Scheme=Session#session.scheme,
- case uri:parse(RedirUrl) of
- {error,Reason} ->
- {error,Reason};
- {Scheme,Host,Port,PathQuery} -> % Automatic redirection
- NewReq=Req#request{redircount=Req#request.redircount+1,
- address={Host,Port},pathquery=PathQuery},
- handle_redirect(Session#session.clientclose,ServerClose,
- NewReq,Session)
- end
- end;
-status_temporary_redirect(Headers,Body,Req,Session) ->
- ServerClose=http_lib:connection_close(Headers),
- gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
- {307,Headers,Body}}),
- handle_connection(Session#session.clientclose,ServerClose,Req,Session).
-
-
-
-%%% Received a 503 Status code ("Service Unavailable")
-%%% The server is currently unable to handle the request due to a
-%%% temporary overloading or maintenance of the server. The implication
-%%% is that this is a temporary condition which will be alleviated after
-%%% some delay. If known, the length of the delay MAY be indicated in a
-%%% Retry-After header. If no Retry-After is given, the client SHOULD
-%%% handle the response as it would for a 500 response.
-%% Note:
-%% - This session is now considered busy, thus cancel any requests in the
-%% pipeline and close the session.
-%% FIXME! Implement a user option to automatically retry if the 'Retry-After'
-%% header is given.
-status_service_unavailable(Resp,Req,Session) ->
-% RetryAfter=Headers#res_headers.retry_after,
- gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,Resp}),
- close_session(server_connection_close,Req,Session).
-
-
-%%% Received a 50x Status code (~ "Service Error")
-%%% Response status codes beginning with the digit "5" indicate cases in
-%%% which the server is aware that it has erred or is incapable of
-%%% performing the request.
-status_server_error_50x(Resp,Req,Session) ->
- gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,Resp}),
- close_session(server_connection_close,Req,Session).
-
-
-%%% Handles requests for redirects
-%%% The redirected request might be:
-%%% - FIXME! on another TCP session, another scheme
-%%% - on the same TCP session, same scheme
-%%% - on another TCP session , same scheme
-%%% However, in all cases treat it as a new request, with redircount updated.
-%%%
-%%% The redirect may fail, but this not a reason to close this session.
-%%% Instead return a error for this request, and continue as ok.
-handle_redirect(ClientClose,ServerClose,Req,Session) ->
- case httpc_manager:request(Req) of
- {ok,_ReqId} -> % FIXME Should I perhaps reuse the Reqid?
- handle_connection(ClientClose,ServerClose,Req,Session);
- {error,Reason} ->
- gen_server:cast(Req#request.from,{Req#request.ref,Req#request.id,
- {error,Reason}}),
- handle_connection(ClientClose,ServerClose,Req,Session)
- end.
-
-%%% Check if the persistent connection flag is false (ie client request
-%%% non-persistive connection), or if the server requires a closed connection
-%%% (by sending a "Connection: close" header). If the connection required
-%%% non-persistent, we may close the connection immediately.
-handle_connection(ClientClose,ServerClose,Req,Session) ->
- case {ClientClose,ServerClose} of
- {false,false} ->
- ok;
- {false,true} -> % The server requests this session to be closed.
- close_session(server_connection_close,Req,Session);
- {true,_} -> % The client requested a non-persistent connection
- close_session(client_connection_close,Req,Session)
- end.
-
-
-%%% Close the session.
-%%% We now have three cases:
-%%% - Client request a non-persistent connection when initiating the request.
-%%% Session info not stored in httpc_manager
-%%% - Server requests a non-persistent connection when answering a request.
-%%% No need to resend request, but there might be a pipeline.
-%%% - Some kind of error
-%%% Close the session, we may then try resending all requests in the pipeline
-%%% including the current depending on the error.
-%%% FIXME! Should not always abort the session (see close_session in
-%%% httpc_manager for more details)
-close_session(client_connection_close,_Req,Session) ->
- http_lib:close(Session#session.scheme,Session#session.socket),
- stop;
-close_session(server_connection_close,Req,Session) ->
- http_lib:close(Session#session.scheme,Session#session.socket),
- httpc_manager:abort_session(Req#request.address,Session#session.id,
- aborted_request),
- stop.
-
-exit_session(Address,Session,Reason) ->
- http_lib:close(Session#session.scheme,Session#session.socket),
- httpc_manager:abort_session(Address,Session#session.id,Reason),
- exit(normal).
-
-%%% This is the "normal" case to close a persistent connection. I.e., there are
-%%% no more requests waiting and the session was closed by the client, or
-%%% server because of a timeout or user request.
-exit_session_ok(Address,Session) ->
- http_lib:close(Session#session.scheme,Session#session.socket),
- exit_session_ok2(Address,Session#session.clientclose,Session#session.id).
-
-exit_session_ok2(Address,ClientClose,Sid) ->
- case ClientClose of
- false ->
- httpc_manager:close_session(Address,Sid);
- true ->
- ok
- end,
- exit(normal).
-
-%%% ============================================================================
-%%% This is deprecated code, to be removed
-
-format_time() ->
- {_,_,MicroSecs}=TS=now(),
- {{Y,Mon,D},{H,M,S}}=calendar:now_to_universal_time(TS),
- lists:flatten(io_lib:format("~4.4.0w-~2.2.0w-~2.2.0w,~2.2.0w:~2.2.0w:~6.3.0f",
- [Y,Mon,D,H,M,S+(MicroSecs/1000000)])).
-
-%%% Read more data from the open socket.
-%%% Two different read functions is used because for the {active, once} socket
-%%% option is (currently) not available for SSL...
-%%% FIXME
-% read_more_data(http,Socket,Timeout) ->
-% io:format("read_more_data(ip_comm) -> "
-% "~n set active = 'once' and "
-% "await a chunk data", []),
-% http_lib:setopts(Socket, [{active,once}]),
-% read_more_data_ipcomm(Socket,Timeout);
-% read_more_data(https,Socket,Timeout) ->
-% case ssl:recv(Socket,0,Timeout) of
-% {ok,MoreData} ->
-% MoreData;
-% {error,closed} ->
-% throw({error, session_remotely_closed});
-% {error,etimedout} ->
-% throw({error, session_local_timeout});
-% {error,Reason} ->
-% throw({error, Reason});
-% Other ->
-% throw({error, Other})
-% end.
-
-% %%% Send any incoming requests on the open session immediately
-% read_more_data_ipcomm(Socket,Timeout) ->
-% receive
-% {tcp,Socket,MoreData} ->
-% % ?vtrace("read_more_data(ip_comm) -> got some data:~p",
-% % [MoreData]),
-% MoreData;
-% {tcp_closed,Socket} ->
-% % ?vtrace("read_more_data(ip_comm) -> socket closed",[]),
-% throw({error,session_remotely_closed});
-% {tcp_error,Socket,Reason} ->
-% % ?vtrace("read_more_data(ip_comm) -> ~p socket error: ~p",
-% % [self(),Reason]),
-% throw({error, Reason});
-% stop ->
-% throw({error, user_req})
-% after Timeout ->
-% throw({error, session_local_timeout})
-% end.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpc_manager.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpc_manager.erl
deleted file mode 100644
index 4659749270..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpc_manager.erl
+++ /dev/null
@@ -1,542 +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 Mobile Arts AB
-%% Portions created by Mobile Arts are Copyright 2002, Mobile Arts AB
-%% All Rights Reserved.''
-%%
-%%
-%% Created : 18 Dec 2001 by Johan Blom <[email protected]>
-%%
-
--module(httpc_manager).
-
--behaviour(gen_server).
-
--include("http.hrl").
-
--define(HMACALL, ?MODULE).
--define(HMANAME, ?MODULE).
-
-%%--------------------------------------------------------------------
-%% External exports
--export([start_link/0,start/0,
- request/1,cancel_request/1,
- next_request/2,
- register_socket/3,
- abort_session/3,close_session/2,close_session/3
- ]).
-
-%% Debugging only
--export([status/0]).
-
-%% gen_server callbacks
--export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,
- code_change/3]).
-
-%%% address_db - ets() Contains mappings from a tuple {Host,Port} to a tuple
-%%% {LastSID,OpenSessions,ets()} where
-%%% LastSid is the last allocated session id,
-%%% OpenSessions is the number of currently open sessions and
-%%% ets() contains mappings from Session Id to #session{}.
-%%%
-%%% Note:
-%%% - Only persistent connections are stored in address_db
-%%% - When automatically redirecting, multiple requests are performed.
--record(state,{
- address_db, % ets()
- reqid % int() Next Request id to use (identifies request).
- }).
-
-%%====================================================================
-%% External functions
-%%====================================================================
-%%--------------------------------------------------------------------
-%% Function: start_link/0
-%% Description: Starts the server
-%%--------------------------------------------------------------------
-start() ->
- ensure_started().
-
-start_link() ->
- gen_server:start_link({local,?HMACALL}, ?HMANAME, [], []).
-
-
-%% Find available session process and store in address_db. If no
-%% available, start new handler process.
-request(Req) ->
- ensure_started(),
- ClientClose=http_lib:connection_close(Req#request.headers),
- gen_server:call(?HMACALL,{request,ClientClose,Req},infinity).
-
-cancel_request(ReqId) ->
- gen_server:call(?HMACALL,{cancel_request,ReqId},infinity).
-
-
-%%% Close Session
-close_session(Addr,Sid) ->
- gen_server:call(?HMACALL,{close_session,Addr,Sid},infinity).
-close_session(Req,Addr,Sid) ->
- gen_server:call(?HMACALL,{close_session,Req,Addr,Sid},infinity).
-
-abort_session(Addr,Sid,Msg) ->
- gen_server:call(?HMACALL,{abort_session,Addr,Sid,Msg},infinity).
-
-
-%%% Pick next in request que
-next_request(Addr,Sid) ->
- gen_server:call(?HMACALL,{next_request,Addr,Sid},infinity).
-
-%%% Session handler has succeded to set up a new session, now register
-%%% the socket
-register_socket(Addr,Sid,Socket) ->
- gen_server:cast(?HMACALL,{register_socket,Addr,Sid,Socket}).
-
-
-%%% Debugging
-status() ->
- gen_server:cast(?HMACALL,status).
-
-
-%%--------------------------------------------------------------------
-%% Function: init/1
-%% Description: Initiates the server
-%% Returns: {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%%--------------------------------------------------------------------
-init([]) ->
- process_flag(trap_exit, true),
- {ok,#state{address_db=ets:new(address_db,[private]),
- reqid=0}}.
-
-
-%%--------------------------------------------------------------------
-%% Function: handle_call/3
-%% Description: Handling call messages
-%% Returns: {reply, Reply, State} |
-%% {reply, Reply, State, Timeout} |
-%% {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, Reply, State} | (terminate/2 is called)
-%% {stop, Reason, State} (terminate/2 is called)
-%%--------------------------------------------------------------------
-%%% Note:
-%%% - We may have multiple non-persistent connections, each will be handled in
-%%% separate processes, thus don't add such connections to address_db
-handle_call({request,false,Req},_From,State) ->
- case ets:lookup(State#state.address_db,Req#request.address) of
- [] ->
- STab=ets:new(session_db,[private,{keypos,2},set]),
- case persistent_new_session_request(0,Req,STab,State) of
- {Reply,LastSid,State2} ->
- ets:insert(State2#state.address_db,
- {Req#request.address,{LastSid,1,STab}}),
- {reply,Reply,State2};
- {ErrorReply,State2} ->
- {reply,ErrorReply,State2}
- end;
- [{_,{LastSid,OpenS,STab}}] ->
- case lookup_session_entry(STab) of
- {ok,Session} ->
- old_session_request(Session,Req,STab,State);
- need_new_session when OpenS<(Req#request.settings)#client_settings.max_sessions ->
- case persistent_new_session_request(LastSid,Req,
- STab,State) of
- {Reply,LastSid2,State2} ->
- ets:insert(State2#state.address_db,
- {Req#request.address,
- {LastSid2,OpenS+1,STab}}),
- {reply,Reply,State2};
- {ErrorReply,State2} ->
- {reply,ErrorReply,State2}
- end;
- need_new_session ->
- {reply,{error,too_many_sessions},State}
- end
- end;
-handle_call({request,true,Req},_From,State) ->
- {Reply,State2}=not_persistent_new_session_request(Req,State),
- {reply,Reply,State2};
-handle_call({cancel_request,true,_ReqId},_From,State) ->
-%% FIXME Should be possible to scan through all requests made, but perhaps
-%% better to give some more hints (such as Addr etc)
- Reply=ok,
- {reply,Reply,State};
-handle_call({next_request,Addr,Sid},_From,State) ->
- case ets:lookup(State#state.address_db,Addr) of
- [] ->
- {reply,{error,no_connection},State};
- [{_,{_,_,STab}}] ->
- case ets:lookup(STab,Sid) of
- [] ->
- {reply,{error,session_not_registered},State};
- [S=#session{pipeline=[],quelength=QueLen}] ->
- if
- QueLen==1 ->
- ets:insert(STab,S#session{quelength=0});
- true ->
- ok
- end,
- {reply,no_more_requests,State};
- [S=#session{pipeline=Que}] ->
- [Req|RevQue]=lists:reverse(Que),
- ets:insert(STab,S#session{pipeline=lists:reverse(RevQue),
- quelength=S#session.quelength-1}),
- {reply,Req,State}
- end
- end;
-handle_call({close_session,Addr,Sid},_From,State) ->
- case ets:lookup(State#state.address_db,Addr) of
- [] ->
- {reply,{error,no_connection},State};
- [{_,{LastSid,OpenS,STab}}] ->
- case ets:lookup(STab,Sid) of
- [#session{pipeline=Que}] ->
- R=handle_close_session(lists:reverse(Que),STab,Sid,State),
- ets:insert(State#state.address_db,
- {Addr,{LastSid,OpenS-1,STab}}),
- {reply,R,State};
- [] ->
- {reply,{error,session_not_registered},State}
- end
- end;
-handle_call({close_session,Req,Addr,Sid},_From,State) ->
- case ets:lookup(State#state.address_db,Addr) of
- [] ->
- {reply,{error,no_connection},State};
- [{_,{LastSid,OpenS,STab}}] ->
- case ets:lookup(STab,Sid) of
- [#session{pipeline=Que}] ->
- R=handle_close_session([Req|lists:reverse(Que)],
- STab,Sid,State),
- ets:insert(State#state.address_db,
- {Addr,{LastSid,OpenS-1,STab}}),
- {reply,R,State};
- [] ->
- {reply,{error,session_not_registered},State}
- end
- end;
-handle_call({abort_session,Addr,Sid,Msg},_From,State) ->
- case ets:lookup(State#state.address_db,Addr) of
- [] ->
- {reply,{error,no_connection},State};
- [{_,{LastSid,OpenS,STab}}] ->
- case ets:lookup(STab,Sid) of
- [#session{pipeline=Que}] ->
- R=abort_request_que(Que,{error,Msg}),
- ets:delete(STab,Sid),
- ets:insert(State#state.address_db,
- {Addr,{LastSid,OpenS-1,STab}}),
- {reply,R,State};
- [] ->
- {reply,{error,session_not_registered},State}
- end
- end.
-
-
-%%--------------------------------------------------------------------
-%% Function: handle_cast/2
-%% Description: Handling cast messages
-%% Returns: {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State} (terminate/2 is called)
-%%--------------------------------------------------------------------
-handle_cast(status, State) ->
- io:format("Status:~n"),
- print_all(lists:sort(ets:tab2list(State#state.address_db))),
- {noreply, State};
-handle_cast({register_socket,Addr,Sid,Socket},State) ->
- case ets:lookup(State#state.address_db,Addr) of
- [] ->
- {noreply,State};
- [{_,{_,_,STab}}] ->
- case ets:lookup(STab,Sid) of
- [Session] ->
- ets:insert(STab,Session#session{socket=Socket}),
- {noreply,State};
- [] ->
- {noreply,State}
- end
- end.
-
-print_all([]) ->
- ok;
-print_all([{Addr,{LastSid,OpenSessions,STab}}|Rest]) ->
- io:format(" Address:~p LastSid=~p OpenSessions=~p~n",[Addr,LastSid,OpenSessions]),
- SortedList=lists:sort(fun(A,B) ->
- if
- A#session.id<B#session.id ->
- true;
- true ->
- false
- end
- end,ets:tab2list(STab)),
- print_all2(SortedList),
- print_all(Rest).
-
-print_all2([]) ->
- ok;
-print_all2([Session|Rest]) ->
- io:format(" Session:~p~n",[Session#session.id]),
- io:format(" Client close:~p~n",[Session#session.clientclose]),
- io:format(" Socket:~p~n",[Session#session.socket]),
- io:format(" Pipe: length=~p Que=~p~n",[Session#session.quelength,Session#session.pipeline]),
- print_all2(Rest).
-
-%%--------------------------------------------------------------------
-%% Function: handle_info/2
-%% Description: Handling all non call/cast messages
-%% Returns: {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State} (terminate/2 is called)
-%%--------------------------------------------------------------------
-handle_info({'EXIT',_Pid,normal}, State) ->
- {noreply, State};
-handle_info(Info, State) ->
- io:format("ERROR httpc_manager:handle_info ~p~n",[Info]),
- {noreply, State}.
-
-%%--------------------------------------------------------------------
-%% Function: terminate/2
-%% Description: Shutdown the server
-%% Returns: any (ignored by gen_server)
-%%--------------------------------------------------------------------
-terminate(_Reason, State) ->
- ets:delete(State#state.address_db).
-
-%%--------------------------------------------------------------------
-%% Func: code_change/3
-%% Purpose: Convert process state when code is changed
-%% Returns: {ok, NewState}
-%%--------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%--------------------------------------------------------------------
-%%% Internal functions
-%%--------------------------------------------------------------------
-
-%%% From RFC 2616, Section 8.1.4
-%%% A client, server, or proxy MAY close the transport connection at any
-%%% time. For example, a client might have started to send a new request
-%%% at the same time that the server has decided to close the "idle"
-%%% connection. From the server's point of view, the connection is being
-%%% closed while it was idle, but from the client's point of view, a
-%%% request is in progress.
-%%%
-%%% This means that clients, servers, and proxies MUST be able to recover
-%%% from asynchronous close events. Client software SHOULD reopen the
-%%% transport connection and retransmit the aborted sequence of requests
-%%% without user interaction so long as the request sequence is
-%%% idempotent (see section 9.1.2). Non-idempotent methods or sequences
-%%%
-%%% FIXME
-%%% Note:
-%%% - If this happen (server close because of idle) there can't be any requests
-%%% in the que.
-%%% - This is the main function for closing of sessions
-handle_close_session([],STab,Sid,_State) ->
- ets:delete(STab,Sid);
-handle_close_session(Que,STab,Sid,_State) ->
- ets:delete(STab,Sid),
- abort_request_que(Que,{error,aborted_request}).
-
-
-%%% From RFC 2616, Section 8.1.2.2
-%%% Clients which assume persistent connections and pipeline immediately
-%%% after connection establishment SHOULD be prepared to retry their
-%%% connection if the first pipelined attempt fails. If a client does
-%%% such a retry, it MUST NOT pipeline before it knows the connection is
-%%% persistent. Clients MUST also be prepared to resend their requests if
-%%% the server closes the connection before sending all of the
-%%% corresponding responses.
-%%% FIXME! I'm currently not checking if tis is the first attempt on the session
-%%% FIXME! Pipeline size must be dynamically variable (e.g. 0 if resend, 2 else)
-%%% The que contains requests that have been sent ok previously, but the session
-%%% was closed prematurely when reading the response.
-%%% Try setup a new session and resend these requests.
-%%% Note:
-%%% - This MUST be a persistent session
-% handle_closed_pipelined_session_que([],_State) ->
-% ok;
-% handle_closed_pipelined_session_que(_Que,_State) ->
-% ok.
-
-
-%%% From RFC 2616, Section 8.2.4
-%%% If an HTTP/1.1 client sends a request which includes a request body,
-%%% but which does not include an Expect request-header field with the
-%%% "100-continue" expectation, and if the client is not directly
-%%% connected to an HTTP/1.1 origin server, and if the client sees the
-%%% connection close before receiving any status from the server, the
-%%% client SHOULD retry the request. If the client does retry this
-%%% request, it MAY use the following "binary exponential backoff"
-%%% algorithm to be assured of obtaining a reliable response:
-%%% ...
-%%% FIXME! I'm currently not checking if a "Expect: 100-continue" has been sent.
-% handle_remotely_closed_session_que([],_State) ->
-% ok;
-% handle_remotely_closed_session_que(_Que,_State) ->
-% % resend_que(Que,Socket),
-% ok.
-
-%%% Resend all requests in the request que
-% resend_que([],_) ->
-% ok;
-% resend_que([Req|Que],Socket) ->
-% case catch httpc_handler:http_request(Req,Socket) of
-% ok ->
-% resend_que(Que,Socket);
-% {error,Reason} ->
-% {error,Reason}
-% end.
-
-
-%%% From RFC 2616,
-%%% Section 8.1.2.2:
-%%% Clients SHOULD NOT pipeline requests using non-idempotent methods or
-%%% non-idempotent sequences of methods (see section 9.1.2). Otherwise, a
-%%% premature termination of the transport connection could lead to
-%%% indeterminate results. A client wishing to send a non-idempotent
-%%% request SHOULD wait to send that request until it has received the
-%%% response status for the previous request.
-%%% Section 9.1.2:
-%%% Methods can also have the property of "idempotence" in that (aside
-%%% from error or expiration issues) the side-effects of N > 0 identical
-%%% requests is the same as for a single request. The methods GET, HEAD,
-%%% PUT and DELETE share this property. Also, the methods OPTIONS and
-%%% TRACE SHOULD NOT have side effects, and so are inherently idempotent.
-%%%
-%%% Note that POST and CONNECT are idempotent methods.
-%%%
-%%% Tries to find an open, free session i STab. Such a session has quelength
-%%% less than ?MAX_PIPELINE_LENGTH
-%%% Don't care about non-standard, user defined methods.
-%%%
-%%% Returns {ok,Session} or need_new_session where
-%%% Session is the session that may be used
-lookup_session_entry(STab) ->
- MS=[{#session{quelength='$1',max_quelength='$2',
- id='_',clientclose='_',socket='$3',scheme='_',pipeline='_'},
- [{'<','$1','$2'},{is_port,'$3'}],
- ['$_']}],
- case ets:select(STab,MS) of
- [] ->
- need_new_session;
- SessionList -> % Now check if any of these has an empty pipeline.
- case lists:keysearch(0,2,SessionList) of
- {value,Session} ->
- {ok,Session};
- false ->
- {ok,hd(SessionList)}
- end
- end.
-
-
-%%% Returns a tuple {Reply,State} where
-%%% Reply is the response sent back to the application
-%%%
-%%% Note:
-%%% - An {error,einval} from a send should sometimes rather be {error,closed}
-%%% - Don't close the session from here, let httpc_handler take care of that.
-%old_session_request(Session,Req,STab,State)
-% when (Req#request.settings)#client_settings.max_quelength==0 ->
-% Session1=Session#session{pipeline=[Req]},
-% ets:insert(STab,Session1),
-% {reply,{ok,ReqId},State#state{reqid=ReqId+1}};
-old_session_request(Session,Req,STab,State) ->
- ReqId=State#state.reqid,
- Req1=Req#request{id=ReqId},
- case catch httpc_handler:http_request(Req1,Session#session.socket) of
- ok ->
- Session1=Session#session{pipeline=[Req1|Session#session.pipeline],
- quelength=Session#session.quelength+1},
- ets:insert(STab,Session1),
- {reply,{ok,ReqId},State#state{reqid=ReqId+1}};
- {error,Reason} ->
- ets:insert(STab,Session#session{socket=undefined}),
-% http_lib:close(Session#session.sockettype,Session#session.socket),
- {reply,{error,Reason},State#state{reqid=ReqId+1}}
- end.
-
-%%% Returns atuple {Reply,Sid,State} where
-%%% Reply is the response sent back to the application, and
-%%% Sid is the last used Session Id
-persistent_new_session_request(Sid,Req,STab,State) ->
- ReqId=State#state.reqid,
- case setup_new_session(Req#request{id=ReqId},false,Sid) of
- {error,Reason} ->
- {{error,Reason},State#state{reqid=ReqId+1}};
- {NewSid,Session} ->
- ets:insert(STab,Session),
- {{ok,ReqId},NewSid,State#state{reqid=ReqId+1}}
- end.
-
-%%% Returns a tuple {Reply,State} where
-%%% Reply is the response sent back to the application
-not_persistent_new_session_request(Req,State) ->
- ReqId=State#state.reqid,
- case setup_new_session(Req#request{id=ReqId},true,undefined) of
- {error,Reason} ->
- {{error,Reason},State#state{reqid=ReqId+1}};
- ok ->
- {{ok,ReqId},State#state{reqid=ReqId+1}}
- end.
-
-%%% As there are no sessions available, setup a new session and send the request
-%%% on it.
-setup_new_session(Req,ClientClose,Sid) ->
- S=#session{id=Sid,clientclose=ClientClose,
- scheme=Req#request.scheme,
- max_quelength=(Req#request.settings)#client_settings.max_quelength},
- spawn_link(httpc_handler,init_connection,[Req,S]),
- case ClientClose of
- false ->
- {Sid+1,S};
- true ->
- ok
- end.
-
-
-%%% ----------------------------------------------------------------------------
-%%% Abort all requests in the request que.
-abort_request_que([],_Msg) ->
- ok;
-abort_request_que([#request{from=From,ref=Ref,id=Id}|Que],Msg) ->
- gen_server:cast(From,{Ref,Id,Msg}),
- abort_request_que(Que,Msg);
-abort_request_que(#request{from=From,ref=Ref,id=Id},Msg) ->
- gen_server:cast(From,{Ref,Id,Msg}).
-
-
-%%% --------------------------------
-% C={httpc_manager,{?MODULE,start_link,[]},permanent,1000,
-% worker,[?MODULE]},
-% supervisor:start_child(inets_sup, C),
-ensure_started() ->
- case whereis(?HMANAME) of
- undefined ->
- start_link();
- _ ->
- ok
- end.
-
-
-%%% ============================================================================
-%%% This is deprecated code, to be removed
-
-% format_time() ->
-% {_,_,MicroSecs}=TS=now(),
-% {{Y,Mon,D},{H,M,S}}=calendar:now_to_universal_time(TS),
-% lists:flatten(io_lib:format("~4.4.0w-~2.2.0w-~2.2.0w,~2.2.0w:~2.2.0w:~6.3.0f",
-% [Y,Mon,D,H,M,S+(MicroSecs/1000000)])).
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd.erl
deleted file mode 100644
index 8cc1c133e9..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd.erl
+++ /dev/null
@@ -1,596 +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: httpd.erl,v 1.1 2008/12/17 09:53:33 mikpe Exp $
-%%
--module(httpd).
--export([multi_start/1, multi_start_link/1,
- start/0, start/1, start/2,
- start_link/0, start_link/1, start_link/2,
- start_child/0,start_child/1,
- multi_stop/1,
- stop/0,stop/1,stop/2,
- stop_child/0,stop_child/1,stop_child/2,
- multi_restart/1,
- restart/0,restart/1,restart/2,
- parse_query/1]).
-
-%% Optional start related stuff...
--export([load/1, load_mime_types/1,
- start2/1, start2/2,
- start_link2/1, start_link2/2,
- stop2/1]).
-
-%% Management stuff
--export([block/0,block/1,block/2,block/3,block/4,
- unblock/0,unblock/1,unblock/2]).
-
-%% Debugging and status info stuff...
--export([verbosity/3,verbosity/4]).
--export([get_status/1,get_status/2,get_status/3,
- get_admin_state/0,get_admin_state/1,get_admin_state/2,
- get_usage_state/0,get_usage_state/1,get_usage_state/2]).
-
--include("httpd.hrl").
-
--define(D(F, A), io:format("~p:" ++ F ++ "~n", [?MODULE|A])).
-
-
-%% start
-
-start() ->
- start("/var/tmp/server_root/conf/8888.conf").
-
-start(ConfigFile) ->
- %% ?D("start(~s) -> entry", [ConfigFile]),
- start(ConfigFile, []).
-
-start(ConfigFile, Verbosity) when list(ConfigFile), list(Verbosity) ->
- httpd_sup:start(ConfigFile, Verbosity).
-
-
-%% start_link
-
-start_link() ->
- start("/var/tmp/server_root/conf/8888.conf").
-
-start_link(ConfigFile) ->
- start_link(ConfigFile, []).
-
-start_link(ConfigFile, Verbosity) when list(ConfigFile), list(Verbosity) ->
- httpd_sup:start_link(ConfigFile, Verbosity).
-
-
-%% start2 & start_link2
-
-start2(Config) ->
- start2(Config, []).
-
-start2(Config, Verbosity) when list(Config), list(Verbosity) ->
- httpd_sup:start2(Config, Verbosity).
-
-start_link2(Config) ->
- start_link2(Config, []).
-
-start_link2(Config, Verbosity) when list(Config), list(Verbosity) ->
- httpd_sup:start_link2(Config, Verbosity).
-
-
-%% stop
-
-stop() ->
- stop(8888).
-
-stop(Port) when integer(Port) ->
- stop(undefined, Port);
-stop(Pid) when pid(Pid) ->
- httpd_sup:stop(Pid);
-stop(ConfigFile) when list(ConfigFile) ->
- %% ?D("stop(~s) -> entry", [ConfigFile]),
- httpd_sup:stop(ConfigFile).
-
-stop(Addr, Port) when integer(Port) ->
- httpd_sup:stop(Addr, Port).
-
-stop2(Config) when list(Config) ->
- httpd_sup:stop2(Config).
-
-%% start_child
-
-start_child() ->
- start_child("/var/tmp/server_root/conf/8888.conf").
-
-start_child(ConfigFile) ->
- start_child(ConfigFile, []).
-
-start_child(ConfigFile, Verbosity) ->
- inets_sup:start_child(ConfigFile, Verbosity).
-
-
-%% stop_child
-
-stop_child() ->
- stop_child(8888).
-
-stop_child(Port) ->
- stop_child(undefined,Port).
-
-stop_child(Addr, Port) when integer(Port) ->
- inets_sup:stop_child(Addr, Port).
-
-
-%% multi_start
-
-multi_start(MultiConfigFile) ->
- case read_multi_file(MultiConfigFile) of
- {ok,ConfigFiles} ->
- mstart(ConfigFiles);
- Error ->
- Error
- end.
-
-mstart(ConfigFiles) ->
- mstart(ConfigFiles,[]).
-mstart([],Results) ->
- {ok,lists:reverse(Results)};
-mstart([H|T],Results) ->
- Res = start(H),
- mstart(T,[Res|Results]).
-
-
-%% multi_start_link
-
-multi_start_link(MultiConfigFile) ->
- case read_multi_file(MultiConfigFile) of
- {ok,ConfigFiles} ->
- mstart_link(ConfigFiles);
- Error ->
- Error
- end.
-
-mstart_link(ConfigFiles) ->
- mstart_link(ConfigFiles,[]).
-mstart_link([],Results) ->
- {ok,lists:reverse(Results)};
-mstart_link([H|T],Results) ->
- Res = start_link(H),
- mstart_link(T,[Res|Results]).
-
-
-%% multi_stop
-
-multi_stop(MultiConfigFile) ->
- case read_multi_file(MultiConfigFile) of
- {ok,ConfigFiles} ->
- mstop(ConfigFiles);
- Error ->
- Error
- end.
-
-mstop(ConfigFiles) ->
- mstop(ConfigFiles,[]).
-mstop([],Results) ->
- {ok,lists:reverse(Results)};
-mstop([H|T],Results) ->
- Res = stop(H),
- mstop(T,[Res|Results]).
-
-
-%% multi_restart
-
-multi_restart(MultiConfigFile) ->
- case read_multi_file(MultiConfigFile) of
- {ok,ConfigFiles} ->
- mrestart(ConfigFiles);
- Error ->
- Error
- end.
-
-mrestart(ConfigFiles) ->
- mrestart(ConfigFiles,[]).
-mrestart([],Results) ->
- {ok,lists:reverse(Results)};
-mrestart([H|T],Results) ->
- Res = restart(H),
- mrestart(T,[Res|Results]).
-
-
-%% restart
-
-restart() -> restart(undefined,8888).
-
-restart(Port) when integer(Port) ->
- restart(undefined,Port);
-restart(ConfigFile) when list(ConfigFile) ->
- case get_addr_and_port(ConfigFile) of
- {ok,Addr,Port} ->
- restart(Addr,Port);
- Error ->
- Error
- end.
-
-
-restart(Addr,Port) when integer(Port) ->
- do_restart(Addr,Port).
-
-do_restart(Addr,Port) when integer(Port) ->
- Name = make_name(Addr,Port),
- case whereis(Name) of
- Pid when pid(Pid) ->
- httpd_manager:restart(Pid);
- _ ->
- {error,not_started}
- end.
-
-
-%%% =========================================================
-%%% Function: block/0, block/1, block/2, block/3, block/4
-%%% block()
-%%% block(Port)
-%%% block(ConfigFile)
-%%% block(Addr,Port)
-%%% block(Port,Mode)
-%%% block(ConfigFile,Mode)
-%%% block(Addr,Port,Mode)
-%%% block(ConfigFile,Mode,Timeout)
-%%% block(Addr,Port,Mode,Timeout)
-%%%
-%%% Returns: ok | {error,Reason}
-%%%
-%%% Description: This function is used to block an HTTP server.
-%%% The blocking can be done in two ways,
-%%% disturbing or non-disturbing. Default is disturbing.
-%%% When a HTTP server is blocked, all requests are rejected
-%%% (status code 503).
-%%%
-%%% disturbing:
-%%% By performing a disturbing block, the server
-%%% is blocked forcefully and all ongoing requests
-%%% are terminated. No new connections are accepted.
-%%% If a timeout time is given then, on-going requests
-%%% are given this much time to complete before the
-%%% server is forcefully blocked. In this case no new
-%%% connections is accepted.
-%%%
-%%% non-disturbing:
-%%% A non-disturbing block is more gracefull. No
-%%% new connections are accepted, but the ongoing
-%%% requests are allowed to complete.
-%%% If a timeout time is given, it waits this long before
-%%% giving up (the block operation is aborted and the
-%%% server state is once more not-blocked).
-%%%
-%%% Types: Port -> integer()
-%%% Addr -> {A,B,C,D} | string() | undefined
-%%% ConfigFile -> string()
-%%% Mode -> disturbing | non_disturbing
-%%% Timeout -> integer()
-%%%
-block() -> block(undefined,8888,disturbing).
-
-block(Port) when integer(Port) ->
- block(undefined,Port,disturbing);
-
-block(ConfigFile) when list(ConfigFile) ->
- case get_addr_and_port(ConfigFile) of
- {ok,Addr,Port} ->
- block(Addr,Port,disturbing);
- Error ->
- Error
- end.
-
-block(Addr,Port) when integer(Port) ->
- block(Addr,Port,disturbing);
-
-block(Port,Mode) when integer(Port), atom(Mode) ->
- block(undefined,Port,Mode);
-
-block(ConfigFile,Mode) when list(ConfigFile), atom(Mode) ->
- case get_addr_and_port(ConfigFile) of
- {ok,Addr,Port} ->
- block(Addr,Port,Mode);
- Error ->
- Error
- end.
-
-
-block(Addr,Port,disturbing) when integer(Port) ->
- do_block(Addr,Port,disturbing);
-block(Addr,Port,non_disturbing) when integer(Port) ->
- do_block(Addr,Port,non_disturbing);
-
-block(ConfigFile,Mode,Timeout) when list(ConfigFile), atom(Mode), integer(Timeout) ->
- case get_addr_and_port(ConfigFile) of
- {ok,Addr,Port} ->
- block(Addr,Port,Mode,Timeout);
- Error ->
- Error
- end.
-
-
-block(Addr,Port,non_disturbing,Timeout) when integer(Port), integer(Timeout) ->
- do_block(Addr,Port,non_disturbing,Timeout);
-block(Addr,Port,disturbing,Timeout) when integer(Port), integer(Timeout) ->
- do_block(Addr,Port,disturbing,Timeout).
-
-do_block(Addr,Port,Mode) when integer(Port), atom(Mode) ->
- Name = make_name(Addr,Port),
- case whereis(Name) of
- Pid when pid(Pid) ->
- httpd_manager:block(Pid,Mode);
- _ ->
- {error,not_started}
- end.
-
-
-do_block(Addr,Port,Mode,Timeout) when integer(Port), atom(Mode) ->
- Name = make_name(Addr,Port),
- case whereis(Name) of
- Pid when pid(Pid) ->
- httpd_manager:block(Pid,Mode,Timeout);
- _ ->
- {error,not_started}
- end.
-
-
-%%% =========================================================
-%%% Function: unblock/0, unblock/1, unblock/2
-%%% unblock()
-%%% unblock(Port)
-%%% unblock(ConfigFile)
-%%% unblock(Addr,Port)
-%%%
-%%% Description: This function is used to reverse a previous block
-%%% operation on the HTTP server.
-%%%
-%%% Types: Port -> integer()
-%%% Addr -> {A,B,C,D} | string() | undefined
-%%% ConfigFile -> string()
-%%%
-unblock() -> unblock(undefined,8888).
-unblock(Port) when integer(Port) -> unblock(undefined,Port);
-
-unblock(ConfigFile) when list(ConfigFile) ->
- case get_addr_and_port(ConfigFile) of
- {ok,Addr,Port} ->
- unblock(Addr,Port);
- Error ->
- Error
- end.
-
-unblock(Addr,Port) when integer(Port) ->
- Name = make_name(Addr,Port),
- case whereis(Name) of
- Pid when pid(Pid) ->
- httpd_manager:unblock(Pid);
- _ ->
- {error,not_started}
- end.
-
-
-verbosity(Port,Who,Verbosity) ->
- verbosity(undefined,Port,Who,Verbosity).
-
-verbosity(Addr,Port,Who,Verbosity) ->
- Name = make_name(Addr,Port),
- case whereis(Name) of
- Pid when pid(Pid) ->
- httpd_manager:verbosity(Pid,Who,Verbosity);
- _ ->
- not_started
- end.
-
-
-%%% =========================================================
-%%% Function: get_admin_state/0, get_admin_state/1, get_admin_state/2
-%%% get_admin_state()
-%%% get_admin_state(Port)
-%%% get_admin_state(Addr,Port)
-%%%
-%%% Returns: {ok,State} | {error,Reason}
-%%%
-%%% Description: This function is used to retrieve the administrative
-%%% state of the HTTP server.
-%%%
-%%% Types: Port -> integer()
-%%% Addr -> {A,B,C,D} | string() | undefined
-%%% State -> unblocked | shutting_down | blocked
-%%% Reason -> term()
-%%%
-get_admin_state() -> get_admin_state(undefined,8888).
-get_admin_state(Port) when integer(Port) -> get_admin_state(undefined,Port);
-
-get_admin_state(ConfigFile) when list(ConfigFile) ->
- case get_addr_and_port(ConfigFile) of
- {ok,Addr,Port} ->
- unblock(Addr,Port);
- Error ->
- Error
- end.
-
-get_admin_state(Addr,Port) when integer(Port) ->
- Name = make_name(Addr,Port),
- case whereis(Name) of
- Pid when pid(Pid) ->
- httpd_manager:get_admin_state(Pid);
- _ ->
- {error,not_started}
- end.
-
-
-
-%%% =========================================================
-%%% Function: get_usage_state/0, get_usage_state/1, get_usage_state/2
-%%% get_usage_state()
-%%% get_usage_state(Port)
-%%% get_usage_state(Addr,Port)
-%%%
-%%% Returns: {ok,State} | {error,Reason}
-%%%
-%%% Description: This function is used to retrieve the usage
-%%% state of the HTTP server.
-%%%
-%%% Types: Port -> integer()
-%%% Addr -> {A,B,C,D} | string() | undefined
-%%% State -> idle | active | busy
-%%% Reason -> term()
-%%%
-get_usage_state() -> get_usage_state(undefined,8888).
-get_usage_state(Port) when integer(Port) -> get_usage_state(undefined,Port);
-
-get_usage_state(ConfigFile) when list(ConfigFile) ->
- case get_addr_and_port(ConfigFile) of
- {ok,Addr,Port} ->
- unblock(Addr,Port);
- Error ->
- Error
- end.
-
-get_usage_state(Addr,Port) when integer(Port) ->
- Name = make_name(Addr,Port),
- case whereis(Name) of
- Pid when pid(Pid) ->
- httpd_manager:get_usage_state(Pid);
- _ ->
- {error,not_started}
- end.
-
-
-
-%%% =========================================================
-%% Function: get_status(ConfigFile) -> Status
-%% get_status(Port) -> Status
-%% get_status(Addr,Port) -> Status
-%% get_status(Port,Timeout) -> Status
-%% get_status(Addr,Port,Timeout) -> Status
-%%
-%% Arguments: ConfigFile -> string()
-%% Configuration file from which Port and
-%% BindAddress will be extracted.
-%% Addr -> {A,B,C,D} | string()
-%% Bind Address of the http server
-%% Port -> integer()
-%% Port number of the http server
-%% Timeout -> integer()
-%% Timeout time for the call
-%%
-%% Returns: Status -> list()
-%%
-%% Description: This function is used when the caller runs in the
-%% same node as the http server or if calling with a
-%% program such as erl_call (see erl_interface).
-%%
-
-get_status(ConfigFile) when list(ConfigFile) ->
- case get_addr_and_port(ConfigFile) of
- {ok,Addr,Port} ->
- get_status(Addr,Port);
- Error ->
- Error
- end;
-
-get_status(Port) when integer(Port) ->
- get_status(undefined,Port,5000).
-
-get_status(Port,Timeout) when integer(Port), integer(Timeout) ->
- get_status(undefined,Port,Timeout);
-
-get_status(Addr,Port) when list(Addr), integer(Port) ->
- get_status(Addr,Port,5000).
-
-get_status(Addr,Port,Timeout) when integer(Port) ->
- Name = make_name(Addr,Port),
- case whereis(Name) of
- Pid when pid(Pid) ->
- httpd_manager:get_status(Pid,Timeout);
- _ ->
- not_started
- end.
-
-
-%% load config
-
-load(ConfigFile) ->
- httpd_conf:load(ConfigFile).
-
-load_mime_types(MimeTypesFile) ->
- httpd_conf:load_mime_types(MimeTypesFile).
-
-
-%% parse_query
-
-parse_query(String) ->
- {ok, SplitString} = regexp:split(String,"[&;]"),
- foreach(SplitString).
-
-foreach([]) ->
- [];
-foreach([KeyValue|Rest]) ->
- {ok, Plus2Space, _} = regexp:gsub(KeyValue,"[\+]"," "),
- case regexp:split(Plus2Space,"=") of
- {ok,[Key|Value]} ->
- [{httpd_util:decode_hex(Key),
- httpd_util:decode_hex(lists:flatten(Value))}|foreach(Rest)];
- {ok,_} ->
- foreach(Rest)
- end.
-
-
-%% get_addr_and_port
-
-get_addr_and_port(ConfigFile) ->
- case httpd_conf:load(ConfigFile) of
- {ok,ConfigList} ->
- Port = httpd_util:key1search(ConfigList,port,80),
- Addr = httpd_util:key1search(ConfigList,bind_address),
- {ok,Addr,Port};
- Error ->
- Error
- end.
-
-
-%% make_name
-
-make_name(Addr,Port) ->
- httpd_util:make_name("httpd",Addr,Port).
-
-
-%% Multi stuff
-%%
-
-read_multi_file(File) ->
- read_mfile(file:open(File,[read])).
-
-read_mfile({ok,Fd}) ->
- read_mfile(read_line(Fd),Fd,[]);
-read_mfile(Error) ->
- Error.
-
-read_mfile(eof,_Fd,SoFar) ->
- {ok,lists:reverse(SoFar)};
-read_mfile({error,Reason},_Fd,SoFar) ->
- {error,Reason};
-read_mfile([$#|Comment],Fd,SoFar) ->
- read_mfile(read_line(Fd),Fd,SoFar);
-read_mfile([],Fd,SoFar) ->
- read_mfile(read_line(Fd),Fd,SoFar);
-read_mfile(Line,Fd,SoFar) ->
- read_mfile(read_line(Fd),Fd,[Line|SoFar]).
-
-read_line(Fd) -> read_line1(io:get_line(Fd,[])).
-read_line1(eof) -> eof;
-read_line1(String) -> httpd_conf:clean(String).
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd.hrl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd.hrl
deleted file mode 100644
index ba21bdf638..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd.hrl
+++ /dev/null
@@ -1,77 +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: httpd.hrl,v 1.1 2008/12/17 09:53:33 mikpe Exp $
-%%
-
--include_lib("kernel/include/file.hrl").
-
--ifndef(SERVER_SOFTWARE).
--define(SERVER_SOFTWARE,"inets/develop"). % Define in Makefile!
--endif.
--define(SERVER_PROTOCOL,"HTTP/1.1").
--define(SOCKET_CHUNK_SIZE,8192).
--define(SOCKET_MAX_POLL,25).
--define(FILE_CHUNK_SIZE,64*1024).
--define(NICE(Reason),lists:flatten(atom_to_list(?MODULE)++": "++Reason)).
--define(DEFAULT_CONTEXT,
- [{errmsg,"[an error occurred while processing this directive]"},
- {timefmt,"%A, %d-%b-%y %T %Z"},
- {sizefmt,"abbrev"}]).
-
-
--ifdef(inets_error).
--define(ERROR(Format, Args), io:format("E(~p:~p:~p) : "++Format++"~n",
- [self(),?MODULE,?LINE]++Args)).
--else.
--define(ERROR(F,A),[]).
--endif.
-
--ifdef(inets_log).
--define(LOG(Format, Args), io:format("L(~p:~p:~p) : "++Format++"~n",
- [self(),?MODULE,?LINE]++Args)).
--else.
--define(LOG(F,A),[]).
--endif.
-
--ifdef(inets_debug).
--define(DEBUG(Format, Args), io:format("D(~p:~p:~p) : "++Format++"~n",
- [self(),?MODULE,?LINE]++Args)).
--else.
--define(DEBUG(F,A),[]).
--endif.
-
--ifdef(inets_cdebug).
--define(CDEBUG(Format, Args), io:format("C(~p:~p:~p) : "++Format++"~n",
- [self(),?MODULE,?LINE]++Args)).
--else.
--define(CDEBUG(F,A),[]).
--endif.
-
-
--record(init_data,{peername,resolve}).
--record(mod,{init_data,
- data=[],
- socket_type=ip_comm,
- socket,
- config_db,
- method,
- absolute_uri=[],
- request_uri,
- http_version,
- request_line,
- parsed_header=[],
- entity_body,
- connection}).
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_acceptor.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_acceptor.erl
deleted file mode 100644
index 9b88f84865..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_acceptor.erl
+++ /dev/null
@@ -1,176 +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: httpd_acceptor.erl,v 1.1 2008/12/17 09:53:33 mikpe Exp $
-%%
--module(httpd_acceptor).
-
--include("httpd.hrl").
--include("httpd_verbosity.hrl").
-
-
-%% External API
--export([start_link/6]).
-
-%% Other exports (for spawn's etc.)
--export([acceptor/4, acceptor/7]).
-
-
-%%
-%% External API
-%%
-
-%% start_link
-
-start_link(Manager, SocketType, Addr, Port, ConfigDb, Verbosity) ->
- Args = [self(), Manager, SocketType, Addr, Port, ConfigDb, Verbosity],
- proc_lib:start_link(?MODULE, acceptor, Args).
-
-
-acceptor(Parent, Manager, SocketType, Addr, Port, ConfigDb, Verbosity) ->
- put(sname,acc),
- put(verbosity,Verbosity),
- ?vlog("starting",[]),
- case (catch do_init(SocketType, Addr, Port)) of
- {ok, ListenSocket} ->
- proc_lib:init_ack(Parent, {ok, self()}),
- acceptor(Manager, SocketType, ListenSocket, ConfigDb);
- Error ->
- proc_lib:init_ack(Parent, Error),
- error
- end.
-
-do_init(SocketType, Addr, Port) ->
- do_socket_start(SocketType),
- ListenSocket = do_socket_listen(SocketType, Addr, Port),
- {ok, ListenSocket}.
-
-
-do_socket_start(SocketType) ->
- case httpd_socket:start(SocketType) of
- ok ->
- ok;
- {error, Reason} ->
- ?vinfo("failed socket start: ~p",[Reason]),
- throw({error, {socket_start_failed, Reason}})
- end.
-
-
-do_socket_listen(SocketType, Addr, Port) ->
- case httpd_socket:listen(SocketType, Addr, Port) of
- {error, Reason} ->
- ?vinfo("failed socket listen operation: ~p", [Reason]),
- throw({error, {listen, Reason}});
- ListenSocket ->
- ListenSocket
- end.
-
-
-%% acceptor
-
-acceptor(Manager, SocketType, ListenSocket, ConfigDb) ->
- ?vdebug("await connection",[]),
- case (catch httpd_socket:accept(SocketType, ListenSocket, 30000)) of
- {error, Reason} ->
- handle_error(Reason, ConfigDb, SocketType),
- ?MODULE:acceptor(Manager, SocketType, ListenSocket, ConfigDb);
-
- {'EXIT', Reason} ->
- handle_error({'EXIT', Reason}, ConfigDb, SocketType),
- ?MODULE:acceptor(Manager, SocketType, ListenSocket, ConfigDb);
-
- Socket ->
- handle_connection(Manager, ConfigDb, SocketType, Socket),
- ?MODULE:acceptor(Manager, SocketType, ListenSocket, ConfigDb)
- end.
-
-
-handle_connection(Manager, ConfigDb, SocketType, Socket) ->
- case httpd_request_handler:start_link(Manager, ConfigDb) of
- {ok, Pid} ->
- httpd_socket:controlling_process(SocketType, Socket, Pid),
- httpd_request_handler:synchronize(Pid, SocketType, Socket);
- {error, Reason} ->
- handle_connection_err(SocketType, Socket, ConfigDb, Reason)
- end.
-
-
-handle_connection_err(SocketType, Socket, ConfigDb, Reason) ->
- String =
- lists:flatten(
- io_lib:format("failed starting request handler:~n ~p", [Reason])),
- report_error(ConfigDb, String),
- httpd_socket:close(SocketType, Socket).
-
-
-handle_error(timeout, _, _) ->
- ?vtrace("Accept timeout",[]),
- ok;
-
-handle_error({enfile, _}, _, _) ->
- ?vinfo("Accept error: enfile",[]),
- %% Out of sockets...
- sleep(200);
-
-handle_error(emfile, _, _) ->
- ?vinfo("Accept error: emfile",[]),
- %% Too many open files -> Out of sockets...
- sleep(200);
-
-handle_error(closed, _, _) ->
- ?vlog("Accept error: closed",[]),
- %% This propably only means that the application is stopping,
- %% but just in case
- exit(closed);
-
-handle_error(econnaborted, _, _) ->
- ?vlog("Accept aborted",[]),
- ok;
-
-handle_error(esslaccept, _, _) ->
- %% The user has selected to cancel the installation of
- %% the certifikate, This is not a real error, so we do
- %% not write an error message.
- ok;
-
-handle_error({'EXIT', Reason}, ConfigDb, SocketType) ->
- ?vinfo("Accept exit:~n ~p",[Reason]),
- String = lists:flatten(io_lib:format("Accept exit: ~p", [Reason])),
- accept_failed(SocketType, ConfigDb, String);
-
-handle_error(Reason, ConfigDb, SocketType) ->
- ?vinfo("Accept error:~n ~p",[Reason]),
- String = lists:flatten(io_lib:format("Accept error: ~p", [Reason])),
- accept_failed(SocketType, ConfigDb, String).
-
-
-accept_failed(SocketType, ConfigDb, String) ->
- error_logger:error_report(String),
- mod_log:error_log(SocketType, undefined, ConfigDb,
- {0, "unknown"}, String),
- mod_disk_log:error_log(SocketType, undefined, ConfigDb,
- {0, "unknown"}, String),
- exit({accept_failed, String}).
-
-
-report_error(Db, String) ->
- error_logger:error_report(String),
- mod_log:report_error(Db, String),
- mod_disk_log:report_error(Db, String).
-
-
-sleep(T) -> receive after T -> ok end.
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_acceptor_sup.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_acceptor_sup.erl
deleted file mode 100644
index e408614f1c..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_acceptor_sup.erl
+++ /dev/null
@@ -1,118 +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: httpd_acceptor_sup.erl,v 1.1 2008/12/17 09:53:33 mikpe Exp $
-%%
-%%----------------------------------------------------------------------
-%% Purpose: The top supervisor for the Megaco/H.248 application
-%%----------------------------------------------------------------------
-
--module(httpd_acceptor_sup).
-
--behaviour(supervisor).
-
--include("httpd_verbosity.hrl").
-
-%% public
--export([start/3, stop/1, init/1]).
-
--export([start_acceptor/4, stop_acceptor/2]).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% supervisor callback functions
-
-
-start(Addr, Port, AccSupVerbosity) ->
- SupName = make_name(Addr, Port),
- supervisor:start_link({local, SupName}, ?MODULE, [AccSupVerbosity]).
-
-stop(StartArgs) ->
- ok.
-
-init([Verbosity]) -> % Supervisor
- do_init(Verbosity);
-init(BadArg) ->
- {error, {badarg, BadArg}}.
-
-do_init(Verbosity) ->
- put(verbosity,?vvalidate(Verbosity)),
- put(sname,acc_sup),
- ?vlog("starting", []),
- Flags = {one_for_one, 500, 100},
- KillAfter = timer:seconds(1),
- Workers = [],
- {ok, {Flags, Workers}}.
-
-
-%%----------------------------------------------------------------------
-%% Function: [start|stop]_acceptor/5
-%% Description: Starts a [auth | security] worker (child) process
-%%----------------------------------------------------------------------
-
-start_acceptor(SocketType, Addr, Port, ConfigDb) ->
- Verbosity = get_acc_verbosity(),
- start_worker(httpd_acceptor, SocketType, Addr, Port,
- ConfigDb, Verbosity, self(), []).
-
-stop_acceptor(Addr, Port) ->
- stop_worker(httpd_acceptor, Addr, Port).
-
-
-%%----------------------------------------------------------------------
-%% Function: start_worker/5
-%% Description: Starts a (permanent) worker (child) process
-%%----------------------------------------------------------------------
-
-start_worker(M, SocketType, Addr, Port, ConfigDB, Verbosity, Manager,
- Modules) ->
- SupName = make_name(Addr, Port),
- Args = [Manager, SocketType, Addr, Port, ConfigDB, Verbosity],
- Spec = {{M, Addr, Port},
- {M, start_link, Args},
- permanent, timer:seconds(1), worker, [M] ++ Modules},
- supervisor:start_child(SupName, Spec).
-
-
-%%----------------------------------------------------------------------
-%% Function: stop_permanent_worker/3
-%% Description: Stops a permanent worker (child) process
-%%----------------------------------------------------------------------
-
-stop_worker(M, Addr, Port) ->
- SupName = make_name(Addr, Port),
- Name = {M, Addr, Port},
- case supervisor:terminate_child(SupName, Name) of
- ok ->
- supervisor:delete_child(SupName, Name);
- Error ->
- Error
- end.
-
-
-make_name(Addr,Port) ->
- httpd_util:make_name("httpd_acc_sup",Addr,Port).
-
-
-
-get_acc_verbosity() ->
- get_verbosity(get(acceptor_verbosity)).
-
-get_verbosity(undefined) ->
- ?default_verbosity;
-get_verbosity(V) ->
- ?vvalidate(V).
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_conf.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_conf.erl
deleted file mode 100644
index 2c7a747d42..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_conf.erl
+++ /dev/null
@@ -1,688 +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: httpd_conf.erl,v 1.1 2008/12/17 09:53:33 mikpe Exp $
-%%
--module(httpd_conf).
--export([load/1, load_mime_types/1,
- load/2, store/1, store/2,
- remove_all/1, remove/1,
- is_directory/1, is_file/1,
- make_integer/1, clean/1, custom_clean/3, check_enum/2]).
-
-
--define(VMODULE,"CONF").
--include("httpd_verbosity.hrl").
-
-%% The configuration data is handled in three (3) phases:
-%% 1. Parse the config file and put all directives into a key-vale
-%% tuple list (load/1).
-%% 2. Traverse the key-value tuple list store it into an ETS table.
-%% Directives depending on other directives are taken care of here
-%% (store/1).
-%% 3. Traverse the ETS table and do a complete clean-up (remove/1).
-
--include("httpd.hrl").
-
-%%
-%% Phase 1: Load
-%%
-
-%% load
-
-load(ConfigFile) ->
- ?CDEBUG("load -> ConfigFile: ~p",[ConfigFile]),
- case read_config_file(ConfigFile) of
- {ok, Config} ->
- case bootstrap(Config) of
- {error, Reason} ->
- {error, Reason};
- {ok, Modules} ->
- load_config(Config, lists:append(Modules, [?MODULE]))
- end;
- {error, Reason} ->
- {error, ?NICE("Error while reading config file: "++Reason)}
- end.
-
-
-bootstrap([]) ->
- {error, ?NICE("Modules must be specified in the config file")};
-bootstrap([Line|Config]) ->
- case Line of
- [$M,$o,$d,$u,$l,$e,$s,$ |Modules] ->
- {ok, ModuleList} = regexp:split(Modules," "),
- TheMods = [list_to_atom(X) || X <- ModuleList],
- case verify_modules(TheMods) of
- ok ->
- {ok, TheMods};
- {error, Reason} ->
- ?ERROR("bootstrap -> : validation failed: ~p",[Reason]),
- {error, Reason}
- end;
- _ ->
- bootstrap(Config)
- end.
-
-
-%%
-%% verify_modules/1 -> ok | {error, Reason}
-%%
-%% Verifies that all specified modules are available.
-%%
-verify_modules([]) ->
- ok;
-verify_modules([Mod|Rest]) ->
- case code:which(Mod) of
- non_existing ->
- {error, ?NICE(atom_to_list(Mod)++" does not exist")};
- Path ->
- verify_modules(Rest)
- end.
-
-%%
-%% read_config_file/1 -> {ok, [line(), line()..]} | {error, Reason}
-%%
-%% Reads the entire configuration file and returns list of strings or
-%% and error.
-%%
-
-
-read_config_file(FileName) ->
- case file:open(FileName, [read]) of
- {ok, Stream} ->
- read_config_file(Stream, []);
- {error, Reason} ->
- {error, ?NICE("Cannot open "++FileName)}
- end.
-
-read_config_file(Stream, SoFar) ->
- case io:get_line(Stream, []) of
- eof ->
- {ok, lists:reverse(SoFar)};
- {error, Reason} ->
- {error, Reason};
- [$#|Rest] ->
- %% Ignore commented lines for efficiency later ..
- read_config_file(Stream, SoFar);
- Line ->
- {ok, NewLine, _}=regexp:sub(clean(Line),"[\t\r\f ]"," "),
- case NewLine of
- [] ->
- %% Also ignore empty lines ..
- read_config_file(Stream, SoFar);
- Other ->
- read_config_file(Stream, [NewLine|SoFar])
- end
- end.
-
-is_exported(Module, ToFind) ->
- Exports = Module:module_info(exports),
- lists:member(ToFind, Exports).
-
-%%
-%% load/4 -> {ok, ConfigList} | {error, Reason}
-%%
-%% This loads the config file into each module specified by Modules
-%% Each module has its own context that is passed to and (optionally)
-%% returned by the modules load function. The module can also return
-%% a ConfigEntry, which will be added to the global configuration
-%% list.
-%% All configuration directives are guaranteed to be passed to all
-%% modules. Each module only implements the function clauses of
-%% the load function for the configuration directives it supports,
-%% it's ok if an apply returns {'EXIT', {function_clause, ..}}.
-%%
-load_config(Config, Modules) ->
- %% Create default contexts for all modules
- Contexts = lists:duplicate(length(Modules), []),
- load_config(Config, Modules, Contexts, []).
-
-
-load_config([], _Modules, _Contexts, ConfigList) ->
- case a_must(ConfigList, [server_name,port,server_root,document_root]) of
- ok ->
- {ok, ConfigList};
- {missing, Directive} ->
- {error, ?NICE(atom_to_list(Directive)++
- " must be specified in the config file")}
- end;
-
-load_config([Line|Config], Modules, Contexts, ConfigList) ->
- ?CDEBUG("load_config -> Line: ~p",[Line]),
- case load_traverse(Line, Contexts, Modules, [], ConfigList, no) of
- {ok, NewContexts, NewConfigList} ->
- load_config(Config, Modules, NewContexts, NewConfigList);
- {error, Reason} ->
- ?ERROR("load_config -> traverse failed: ~p",[Reason]),
- {error, Reason}
- end.
-
-
-load_traverse(Line, [], [], NewContexts, ConfigList, no) ->
- ?CDEBUG("load_traverse/no -> ~n"
- " Line: ~p~n"
- " NewContexts: ~p~n"
- " ConfigList: ~p",
- [Line,NewContexts,ConfigList]),
- {error, ?NICE("Configuration directive not recognized: "++Line)};
-load_traverse(Line, [], [], NewContexts, ConfigList, yes) ->
- ?CDEBUG("load_traverse/yes -> ~n"
- " Line: ~p~n"
- " NewContexts: ~p~n"
- " ConfigList: ~p",
- [Line,NewContexts,ConfigList]),
- {ok, lists:reverse(NewContexts), ConfigList};
-load_traverse(Line, [Context|Contexts], [Module|Modules], NewContexts, ConfigList, State) ->
- ?CDEBUG("load_traverse/~p -> ~n"
- " Line: ~p~n"
- " Module: ~p~n"
- " Context: ~p~n"
- " Contexts: ~p~n"
- " NewContexts: ~p",
- [State,Line,Module,Context,Contexts,NewContexts]),
- case is_exported(Module, {load, 2}) of
- true ->
- ?CDEBUG("load_traverse -> ~p:load/2 exported",[Module]),
- case catch apply(Module, load, [Line, Context]) of
- {'EXIT', {function_clause, _}} ->
- ?CDEBUG("load_traverse -> exit: function_clause"
- "~n Module: ~p"
- "~n Line: ~s",[Module,Line]),
- load_traverse(Line, Contexts, Modules, [Context|NewContexts], ConfigList, State);
- {'EXIT', Reason} ->
- ?CDEBUG("load_traverse -> exit: ~p",[Reason]),
- error_logger:error_report({'EXIT', Reason}),
- load_traverse(Line, Contexts, Modules, [Context|NewContexts], ConfigList, State);
- {ok, NewContext} ->
- ?CDEBUG("load_traverse -> ~n"
- " NewContext: ~p",[NewContext]),
- load_traverse(Line, Contexts, Modules, [NewContext|NewContexts], ConfigList,yes);
- {ok, NewContext, ConfigEntry} when tuple(ConfigEntry) ->
- ?CDEBUG("load_traverse (tuple) -> ~n"
- " NewContext: ~p~n"
- " ConfigEntry: ~p",[NewContext,ConfigEntry]),
- load_traverse(Line, Contexts, Modules, [NewContext|NewContexts],
- [ConfigEntry|ConfigList], yes);
- {ok, NewContext, ConfigEntry} when list(ConfigEntry) ->
- ?CDEBUG("load_traverse (list) -> ~n"
- " NewContext: ~p~n"
- " ConfigEntry: ~p",[NewContext,ConfigEntry]),
- load_traverse(Line, Contexts, Modules, [NewContext|NewContexts],
- lists:append(ConfigEntry, ConfigList), yes);
- {error, Reason} ->
- ?CDEBUG("load_traverse -> error: ~p",[Reason]),
- {error, Reason}
- end;
- false ->
- ?CDEBUG("load_traverse -> ~p:load/2 not exported",[Module]),
- load_traverse(Line, Contexts, Modules, [Context|NewContexts],
- ConfigList,yes)
- end.
-
-
-load(eof, []) ->
- eof;
-
-load([$M,$a,$x,$H,$e,$a,$d,$e,$r,$S,$i,$z,$e,$ |MaxHeaderSize], []) ->
- ?DEBUG("load -> MaxHeaderSize: ~p",[MaxHeaderSize]),
- case make_integer(MaxHeaderSize) of
- {ok, Integer} ->
- {ok, [], {max_header_size,Integer}};
- {error, _} ->
- {error, ?NICE(clean(MaxHeaderSize)++
- " is an invalid number of MaxHeaderSize")}
- end;
-load([$M,$a,$x,$H,$e,$a,$d,$e,$r,$A,$c,$t,$i,$o,$n,$ |Action], []) ->
- ?DEBUG("load -> MaxHeaderAction: ~p",[Action]),
- {ok, [], {max_header_action,list_to_atom(clean(Action))}};
-load([$M,$a,$x,$B,$o,$d,$y,$S,$i,$z,$e,$ |MaxBodySize], []) ->
- ?DEBUG("load -> MaxBodySize: ~p",[MaxBodySize]),
- case make_integer(MaxBodySize) of
- {ok, Integer} ->
- {ok, [], {max_body_size,Integer}};
- {error, _} ->
- {error, ?NICE(clean(MaxBodySize)++
- " is an invalid number of MaxBodySize")}
- end;
-load([$M,$a,$x,$B,$o,$d,$y,$A,$c,$t,$i,$o,$n,$ |Action], []) ->
- ?DEBUG("load -> MaxBodyAction: ~p",[Action]),
- {ok, [], {max_body_action,list_to_atom(clean(Action))}};
-load([$S,$e,$r,$v,$e,$r,$N,$a,$m,$e,$ |ServerName], []) ->
- ?DEBUG("load -> ServerName: ~p",[ServerName]),
- {ok,[],{server_name,clean(ServerName)}};
-load([$S,$o,$c,$k,$e,$t,$T,$y,$p,$e,$ |SocketType], []) ->
- ?DEBUG("load -> SocketType: ~p",[SocketType]),
- case check_enum(clean(SocketType),["ssl","ip_comm"]) of
- {ok, ValidSocketType} ->
- {ok, [], {com_type,ValidSocketType}};
- {error,_} ->
- {error, ?NICE(clean(SocketType) ++ " is an invalid SocketType")}
- end;
-load([$P,$o,$r,$t,$ |Port], []) ->
- ?DEBUG("load -> Port: ~p",[Port]),
- case make_integer(Port) of
- {ok, Integer} ->
- {ok, [], {port,Integer}};
- {error, _} ->
- {error, ?NICE(clean(Port)++" is an invalid Port")}
- end;
-load([$B,$i,$n,$d,$A,$d,$d,$r,$e,$s,$s,$ |Address], []) ->
- ?DEBUG("load -> Address: ~p",[Address]),
- case clean(Address) of
- "*" ->
- {ok, [], {bind_address,any}};
- CAddress ->
- ?CDEBUG("load -> CAddress: ~p",[CAddress]),
- case inet:getaddr(CAddress,inet) of
- {ok, IPAddr} ->
- ?CDEBUG("load -> IPAddr: ~p",[IPAddr]),
- {ok, [], {bind_address,IPAddr}};
- {error, _} ->
- {error, ?NICE(CAddress++" is an invalid address")}
- end
- end;
-load([$K,$e,$e,$p,$A,$l,$i,$v,$e,$ |OnorOff], []) ->
- case list_to_atom(clean(OnorOff)) of
- off ->
- {ok, [], {persistent_conn, false}};
- _ ->
- {ok, [], {persistent_conn, true}}
- end;
-load([$M,$a,$x,$K,$e,$e,$p,$A,$l,$i,$v,$e,$R,$e,$q,$u,$e,$s,$t,$ |MaxRequests], []) ->
- case make_integer(MaxRequests) of
- {ok, Integer} ->
- {ok, [], {max_keep_alive_request, Integer}};
- {error, _} ->
- {error, ?NICE(clean(MaxRequests)++" is an invalid MaxKeepAliveRequest")}
- end;
-load([$K,$e,$e,$p,$A,$l,$i,$v,$e,$T,$i,$m,$e,$o,$u,$t,$ |Timeout], []) ->
- case make_integer(Timeout) of
- {ok, Integer} ->
- {ok, [], {keep_alive_timeout, Integer*1000}};
- {error, _} ->
- {error, ?NICE(clean(Timeout)++" is an invalid KeepAliveTimeout")}
- end;
-load([$M,$o,$d,$u,$l,$e,$s,$ |Modules], []) ->
- {ok, ModuleList} = regexp:split(Modules," "),
- {ok, [], {modules,[list_to_atom(X) || X <- ModuleList]}};
-load([$S,$e,$r,$v,$e,$r,$A,$d,$m,$i,$n,$ |ServerAdmin], []) ->
- {ok, [], {server_admin,clean(ServerAdmin)}};
-load([$S,$e,$r,$v,$e,$r,$R,$o,$o,$t,$ |ServerRoot], []) ->
- case is_directory(clean(ServerRoot)) of
- {ok, Directory} ->
- MimeTypesFile =
- filename:join([clean(ServerRoot),"conf", "mime.types"]),
- case load_mime_types(MimeTypesFile) of
- {ok, MimeTypesList} ->
- {ok, [], [{server_root,string:strip(Directory,right,$/)},
- {mime_types,MimeTypesList}]};
- {error, Reason} ->
- {error, Reason}
- end;
- {error, _} ->
- {error, ?NICE(clean(ServerRoot)++" is an invalid ServerRoot")}
- end;
-load([$M,$a,$x,$C,$l,$i,$e,$n,$t,$s,$ |MaxClients], []) ->
- ?DEBUG("load -> MaxClients: ~p",[MaxClients]),
- case make_integer(MaxClients) of
- {ok, Integer} ->
- {ok, [], {max_clients,Integer}};
- {error, _} ->
- {error, ?NICE(clean(MaxClients)++" is an invalid number of MaxClients")}
- end;
-load([$D,$o,$c,$u,$m,$e,$n,$t,$R,$o,$o,$t,$ |DocumentRoot],[]) ->
- case is_directory(clean(DocumentRoot)) of
- {ok, Directory} ->
- {ok, [], {document_root,string:strip(Directory,right,$/)}};
- {error, _} ->
- {error, ?NICE(clean(DocumentRoot)++"is an invalid DocumentRoot")}
- end;
-load([$D,$e,$f,$a,$u,$l,$t,$T,$y,$p,$e,$ |DefaultType], []) ->
- {ok, [], {default_type,clean(DefaultType)}};
-load([$S,$S,$L,$C,$e,$r,$t,$i,$f,$i,$c,$a,$t,$e,$F,$i,$l,$e,$ | SSLCertificateFile], []) ->
- ?DEBUG("load -> SSLCertificateFile: ~p",[SSLCertificateFile]),
- case is_file(clean(SSLCertificateFile)) of
- {ok, File} ->
- {ok, [], {ssl_certificate_file,File}};
- {error, _} ->
- {error, ?NICE(clean(SSLCertificateFile)++
- " is an invalid SSLCertificateFile")}
- end;
-load([$S,$S,$L,$C,$e,$r,$t,$i,$f,$i,$c,$a,$t,$e,$K,$e,$y,$F,$i,$l,$e,$ |
- SSLCertificateKeyFile], []) ->
- ?DEBUG("load -> SSLCertificateKeyFile: ~p",[SSLCertificateKeyFile]),
- case is_file(clean(SSLCertificateKeyFile)) of
- {ok, File} ->
- {ok, [], {ssl_certificate_key_file,File}};
- {error, _} ->
- {error, ?NICE(clean(SSLCertificateKeyFile)++
- " is an invalid SSLCertificateKeyFile")}
- end;
-load([$S,$S,$L,$V,$e,$r,$i,$f,$y,$C,$l,$i,$e,$n,$t,$ |SSLVerifyClient], []) ->
- ?DEBUG("load -> SSLVerifyClient: ~p",[SSLVerifyClient]),
- case make_integer(clean(SSLVerifyClient)) of
- {ok, Integer} when Integer >=0,Integer =< 2 ->
- {ok, [], {ssl_verify_client,Integer}};
- {ok, Integer} ->
- {error,?NICE(clean(SSLVerifyClient)++" is an invalid SSLVerifyClient")};
- {error, nomatch} ->
- {error,?NICE(clean(SSLVerifyClient)++" is an invalid SSLVerifyClient")}
- end;
-load([$S,$S,$L,$V,$e,$r,$i,$f,$y,$D,$e,$p,$t,$h,$ |
- SSLVerifyDepth], []) ->
- ?DEBUG("load -> SSLVerifyDepth: ~p",[SSLVerifyDepth]),
- case make_integer(clean(SSLVerifyDepth)) of
- {ok, Integer} when Integer > 0 ->
- {ok, [], {ssl_verify_client_depth,Integer}};
- {ok, Integer} ->
- {error,?NICE(clean(SSLVerifyDepth) ++
- " is an invalid SSLVerifyDepth")};
- {error, nomatch} ->
- {error,?NICE(clean(SSLVerifyDepth) ++
- " is an invalid SSLVerifyDepth")}
- end;
-load([$S,$S,$L,$C,$i,$p,$h,$e,$r,$s,$ | SSLCiphers], []) ->
- ?DEBUG("load -> SSLCiphers: ~p",[SSLCiphers]),
- {ok, [], {ssl_ciphers, clean(SSLCiphers)}};
-load([$S,$S,$L,$C,$A,$C,$e,$r,$t,$i,$f,$i,$c,$a,$t,$e,$F,$i,$l,$e,$ |
- SSLCACertificateFile], []) ->
- case is_file(clean(SSLCACertificateFile)) of
- {ok, File} ->
- {ok, [], {ssl_ca_certificate_file,File}};
- {error, _} ->
- {error, ?NICE(clean(SSLCACertificateFile)++
- " is an invalid SSLCACertificateFile")}
- end;
-load([$S,$S,$L,$P,$a,$s,$s,$w,$o,$r,$d,$C,$a,$l,$l,$b,$a,$c,$k,$M,$o,$d,$u,$l,$e,$ | SSLPasswordCallbackModule], []) ->
- ?DEBUG("load -> SSLPasswordCallbackModule: ~p",
- [SSLPasswordCallbackModule]),
- {ok, [], {ssl_password_callback_module,
- list_to_atom(clean(SSLPasswordCallbackModule))}};
-load([$S,$S,$L,$P,$a,$s,$s,$w,$o,$r,$d,$C,$a,$l,$l,$b,$a,$c,$k,$F,$u,$n,$c,$t,$i,$o,$n,$ | SSLPasswordCallbackFunction], []) ->
- ?DEBUG("load -> SSLPasswordCallbackFunction: ~p",
- [SSLPasswordCallbackFunction]),
- {ok, [], {ssl_password_callback_function,
- list_to_atom(clean(SSLPasswordCallbackFunction))}}.
-
-
-%%
-%% load_mime_types/1 -> {ok, MimeTypes} | {error, Reason}
-%%
-load_mime_types(MimeTypesFile) ->
- case file:open(MimeTypesFile, [read]) of
- {ok, Stream} ->
- parse_mime_types(Stream, []);
- {error, _} ->
- {error, ?NICE("Can't open " ++ MimeTypesFile)}
- end.
-
-parse_mime_types(Stream,MimeTypesList) ->
- Line=
- case io:get_line(Stream,'') of
- eof ->
- eof;
- String ->
- clean(String)
- end,
- parse_mime_types(Stream, MimeTypesList, Line).
-
-parse_mime_types(Stream, MimeTypesList, eof) ->
- file:close(Stream),
- {ok, MimeTypesList};
-parse_mime_types(Stream, MimeTypesList, "") ->
- parse_mime_types(Stream, MimeTypesList);
-parse_mime_types(Stream, MimeTypesList, [$#|_]) ->
- parse_mime_types(Stream, MimeTypesList);
-parse_mime_types(Stream, MimeTypesList, Line) ->
- case regexp:split(Line, " ") of
- {ok, [NewMimeType|Suffixes]} ->
- parse_mime_types(Stream,lists:append(suffixes(NewMimeType,Suffixes),
- MimeTypesList));
- {ok, _} ->
- {error, ?NICE(Line)}
- end.
-
-suffixes(MimeType,[]) ->
- [];
-suffixes(MimeType,[Suffix|Rest]) ->
- [{Suffix,MimeType}|suffixes(MimeType,Rest)].
-
-%%
-%% Phase 2: Store
-%%
-
-%% store
-
-store(ConfigList) ->
- Modules = httpd_util:key1search(ConfigList, modules, []),
- Port = httpd_util:key1search(ConfigList, port),
- Addr = httpd_util:key1search(ConfigList,bind_address),
- Name = httpd_util:make_name("httpd_conf",Addr,Port),
- ?CDEBUG("store -> Name = ~p",[Name]),
- ConfigDB = ets:new(Name, [named_table, bag, protected]),
- ?CDEBUG("store -> ConfigDB = ~p",[ConfigDB]),
- store(ConfigDB, ConfigList, lists:append(Modules,[?MODULE]),ConfigList).
-
-store(ConfigDB, ConfigList, Modules,[]) ->
- ?vtrace("store -> done",[]),
- ?CDEBUG("store -> done",[]),
- {ok, ConfigDB};
-store(ConfigDB, ConfigList, Modules, [ConfigListEntry|Rest]) ->
- ?vtrace("store -> entry with"
- "~n ConfigListEntry: ~p",[ConfigListEntry]),
- ?CDEBUG("store -> "
- "~n ConfigListEntry: ~p",[ConfigListEntry]),
- case store_traverse(ConfigListEntry,ConfigList,Modules) of
- {ok, ConfigDBEntry} when tuple(ConfigDBEntry) ->
- ?vtrace("store -> ConfigDBEntry(tuple): "
- "~n ~p",[ConfigDBEntry]),
- ?CDEBUG("store -> ConfigDBEntry(tuple): "
- "~n ~p",[ConfigDBEntry]),
- ets:insert(ConfigDB,ConfigDBEntry),
- store(ConfigDB,ConfigList,Modules,Rest);
- {ok, ConfigDBEntry} when list(ConfigDBEntry) ->
- ?vtrace("store -> ConfigDBEntry(list): "
- "~n ~p",[ConfigDBEntry]),
- ?CDEBUG("store -> ConfigDBEntry(list): "
- "~n ~p",[ConfigDBEntry]),
- lists:foreach(fun(Entry) ->
- ets:insert(ConfigDB,Entry)
- end,ConfigDBEntry),
- store(ConfigDB,ConfigList,Modules,Rest);
- {error, Reason} ->
- ?vlog("store -> error: ~p",[Reason]),
- ?ERROR("store -> error: ~p",[Reason]),
- {error,Reason}
- end.
-
-store_traverse(ConfigListEntry,ConfigList,[]) ->
- {error,?NICE("Unable to store configuration...")};
-store_traverse(ConfigListEntry, ConfigList, [Module|Rest]) ->
- case is_exported(Module, {store, 2}) of
- true ->
- ?CDEBUG("store_traverse -> call ~p:store/2",[Module]),
- case catch apply(Module,store,[ConfigListEntry, ConfigList]) of
- {'EXIT',{function_clause,_}} ->
- ?CDEBUG("store_traverse -> exit: function_clause",[]),
- store_traverse(ConfigListEntry,ConfigList,Rest);
- {'EXIT',Reason} ->
- ?ERROR("store_traverse -> exit: ~p",[Reason]),
- error_logger:error_report({'EXIT',Reason}),
- store_traverse(ConfigListEntry,ConfigList,Rest);
- Result ->
- ?CDEBUG("store_traverse -> ~n"
- " Result: ~p",[Result]),
- Result
- end;
- false ->
- store_traverse(ConfigListEntry,ConfigList,Rest)
- end.
-
-store({mime_types,MimeTypesList},ConfigList) ->
- Port = httpd_util:key1search(ConfigList, port),
- Addr = httpd_util:key1search(ConfigList, bind_address),
- Name = httpd_util:make_name("httpd_mime",Addr,Port),
- ?CDEBUG("store(mime_types) -> Name: ~p",[Name]),
- {ok, MimeTypesDB} = store_mime_types(Name,MimeTypesList),
- ?CDEBUG("store(mime_types) -> ~n"
- " MimeTypesDB: ~p~n"
- " MimeTypesDB info: ~p",
- [MimeTypesDB,ets:info(MimeTypesDB)]),
- {ok, {mime_types,MimeTypesDB}};
-store(ConfigListEntry,ConfigList) ->
- ?CDEBUG("store/2 -> ~n"
- " ConfigListEntry: ~p~n"
- " ConfigList: ~p",
- [ConfigListEntry,ConfigList]),
- {ok, ConfigListEntry}.
-
-
-%% store_mime_types
-store_mime_types(Name,MimeTypesList) ->
- ?CDEBUG("store_mime_types -> Name: ~p",[Name]),
- MimeTypesDB = ets:new(Name, [set, protected]),
- ?CDEBUG("store_mime_types -> MimeTypesDB: ~p",[MimeTypesDB]),
- store_mime_types1(MimeTypesDB, MimeTypesList).
-
-store_mime_types1(MimeTypesDB,[]) ->
- {ok, MimeTypesDB};
-store_mime_types1(MimeTypesDB,[Type|Rest]) ->
- ?CDEBUG("store_mime_types1 -> Type: ~p",[Type]),
- ets:insert(MimeTypesDB, Type),
- store_mime_types1(MimeTypesDB, Rest).
-
-
-%%
-%% Phase 3: Remove
-%%
-
-remove_all(ConfigDB) ->
- Modules = httpd_util:lookup(ConfigDB,modules,[]),
- remove_traverse(ConfigDB, lists:append(Modules,[?MODULE])).
-
-remove_traverse(ConfigDB,[]) ->
- ?vtrace("remove_traverse -> done", []),
- ok;
-remove_traverse(ConfigDB,[Module|Rest]) ->
- ?vtrace("remove_traverse -> call ~p:remove", [Module]),
- case (catch apply(Module,remove,[ConfigDB])) of
- {'EXIT',{undef,_}} ->
- ?vtrace("remove_traverse -> undef", []),
- remove_traverse(ConfigDB,Rest);
- {'EXIT',{function_clause,_}} ->
- ?vtrace("remove_traverse -> function_clause", []),
- remove_traverse(ConfigDB,Rest);
- {'EXIT',Reason} ->
- ?vtrace("remove_traverse -> exit: ~p", [Reason]),
- error_logger:error_report({'EXIT',Reason}),
- remove_traverse(ConfigDB,Rest);
- {error,Reason} ->
- ?vtrace("remove_traverse -> error: ~p", [Reason]),
- error_logger:error_report(Reason),
- remove_traverse(ConfigDB,Rest);
- _ ->
- remove_traverse(ConfigDB,Rest)
- end.
-
-remove(ConfigDB) ->
- ets:delete(ConfigDB),
- ok.
-
-
-%%
-%% Utility functions
-%%
-
-%% is_directory
-
-is_directory(Directory) ->
- case file:read_file_info(Directory) of
- {ok,FileInfo} ->
- #file_info{type = Type, access = Access} = FileInfo,
- is_directory(Type,Access,FileInfo,Directory);
- {error,Reason} ->
- {error,Reason}
- end.
-
-is_directory(directory,read,_FileInfo,Directory) ->
- {ok,Directory};
-is_directory(directory,read_write,_FileInfo,Directory) ->
- {ok,Directory};
-is_directory(_Type,_Access,FileInfo,_Directory) ->
- {error,FileInfo}.
-
-
-%% is_file
-
-is_file(File) ->
- case file:read_file_info(File) of
- {ok,FileInfo} ->
- #file_info{type = Type, access = Access} = FileInfo,
- is_file(Type,Access,FileInfo,File);
- {error,Reason} ->
- {error,Reason}
- end.
-
-is_file(regular,read,_FileInfo,File) ->
- {ok,File};
-is_file(regular,read_write,_FileInfo,File) ->
- {ok,File};
-is_file(_Type,_Access,FileInfo,_File) ->
- {error,FileInfo}.
-
-%% make_integer
-
-make_integer(String) ->
- case regexp:match(clean(String),"[0-9]+") of
- {match, _, _} ->
- {ok, list_to_integer(clean(String))};
- nomatch ->
- {error, nomatch}
- end.
-
-
-%% clean
-
-clean(String) ->
- {ok,CleanedString,_} = regexp:gsub(String, "^[ \t\n\r\f]*|[ \t\n\r\f]*\$",""),
- CleanedString.
-
-%% custom_clean
-
-custom_clean(String,MoreBefore,MoreAfter) ->
- {ok,CleanedString,_}=regexp:gsub(String,"^[ \t\n\r\f"++MoreBefore++
- "]*|[ \t\n\r\f"++MoreAfter++"]*\$",""),
- CleanedString.
-
-%% check_enum
-
-check_enum(Enum,[]) ->
- {error, not_valid};
-check_enum(Enum,[Enum|Rest]) ->
- {ok, list_to_atom(Enum)};
-check_enum(Enum, [NotValid|Rest]) ->
- check_enum(Enum, Rest).
-
-%% a_must
-
-a_must(ConfigList,[]) ->
- ok;
-a_must(ConfigList,[Directive|Rest]) ->
- case httpd_util:key1search(ConfigList,Directive) of
- undefined ->
- {missing,Directive};
- _ ->
- a_must(ConfigList,Rest)
- end.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_example.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_example.erl
deleted file mode 100644
index 1819650963..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_example.erl
+++ /dev/null
@@ -1,134 +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: httpd_example.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
-%%
--module(httpd_example).
--export([print/1]).
--export([get/2, post/2, yahoo/2, test1/2]).
-
--export([newformat/3]).
-%% These are used by the inets test-suite
--export([delay/1]).
-
-
-print(String) ->
- [header(),
- top("Print"),
- String++"\n",
- footer()].
-
-
-test1(Env, []) ->
- io:format("Env:~p~n",[Env]),
- ["<html>",
- "<head>",
- "<title>Test1</title>",
- "</head>",
- "<body>",
- "<h1>Erlang Body</h1>",
- "<h2>Stuff</h2>",
- "</body>",
- "</html>"].
-
-
-get(Env,[]) ->
- [header(),
- top("GET Example"),
- "<FORM ACTION=\"/cgi-bin/erl/httpd_example:get\" METHOD=GET>
-<B>Input:</B> <INPUT TYPE=\"text\" NAME=\"input1\">
-<INPUT TYPE=\"text\" NAME=\"input2\">
-<INPUT TYPE=\"submit\"><BR>
-</FORM>" ++ "\n",
- footer()];
-
-get(Env,Input) ->
- default(Env,Input).
-
-post(Env,[]) ->
- [header(),
- top("POST Example"),
- "<FORM ACTION=\"/cgi-bin/erl/httpd_example:post\" METHOD=POST>
-<B>Input:</B> <INPUT TYPE=\"text\" NAME=\"input1\">
-<INPUT TYPE=\"text\" NAME=\"input2\">
-<INPUT TYPE=\"submit\"><BR>
-</FORM>" ++ "\n",
- footer()];
-
-post(Env,Input) ->
- default(Env,Input).
-
-yahoo(Env,Input) ->
- "Location: http://www.yahoo.com\r\n\r\n".
-
-default(Env,Input) ->
- [header(),
- top("Default Example"),
- "<B>Environment:</B> ",io_lib:format("~p",[Env]),"<BR>\n",
- "<B>Input:</B> ",Input,"<BR>\n",
- "<B>Parsed Input:</B> ",
- io_lib:format("~p",[httpd:parse_query(Input)]),"\n",
- footer()].
-
-header() ->
- header("text/html").
-header(MimeType) ->
- "Content-type: " ++ MimeType ++ "\r\n\r\n".
-
-top(Title) ->
- "<HTML>
-<HEAD>
-<TITLE>" ++ Title ++ "</TITLE>
-</HEAD>
-<BODY>\n".
-
-footer() ->
- "</BODY>
-</HTML>\n".
-
-
-newformat(SessionID,Env,Input)->
- mod_esi:deliver(SessionID,"Content-Type:text/html\r\n\r\n"),
- mod_esi:deliver(SessionID,top("new esi format test")),
- mod_esi:deliver(SessionID,"This new format is nice<BR>"),
- mod_esi:deliver(SessionID,"This new format is nice<BR>"),
- mod_esi:deliver(SessionID,"This new format is nice<BR>"),
- mod_esi:deliver(SessionID,footer()).
-
-%% ------------------------------------------------------
-
-delay(Time) when integer(Time) ->
- i("httpd_example:delay(~p) -> do the delay",[Time]),
- sleep(Time),
- i("httpd_example:delay(~p) -> done, now reply",[Time]),
- delay_reply("delay ok");
-delay(Time) when list(Time) ->
- delay(httpd_conf:make_integer(Time));
-delay({ok,Time}) when integer(Time) ->
- delay(Time);
-delay({error,_Reason}) ->
- i("delay -> called with invalid time"),
- delay_reply("delay failed: invalid delay time").
-
-delay_reply(Reply) ->
- [header(),
- top("delay"),
- Reply,
- footer()].
-
-i(F) -> i(F,[]).
-i(F,A) -> io:format(F ++ "~n",A).
-
-sleep(T) -> receive after T -> ok end.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_manager.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_manager.erl
deleted file mode 100644
index 78750c32c9..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_manager.erl
+++ /dev/null
@@ -1,1030 +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: httpd_manager.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
-%%
-
--module(httpd_manager).
-
--include("httpd.hrl").
--include("httpd_verbosity.hrl").
-
--behaviour(gen_server).
-
-%% External API
--export([start/2, start/3, start_link/2, start_link/3, stop/1, restart/1]).
-
-%% Internal API
--export([new_connection/1, done_connection/1]).
-
-%% Module API
--export([config_lookup/2, config_lookup/3,
- config_multi_lookup/2, config_multi_lookup/3,
- config_match/2, config_match/3]).
-
-%% gen_server exports
--export([init/1,
- handle_call/3, handle_cast/2, handle_info/2,
- terminate/2,
- code_change/3]).
-
-
-%% Management exports
--export([block/2, block/3, unblock/1]).
--export([get_admin_state/1, get_usage_state/1]).
--export([is_busy/1,is_busy/2,is_busy_or_blocked/1,is_blocked/1]). %% ???????
--export([get_status/1, get_status/2]).
--export([verbosity/2, verbosity/3]).
-
-
--export([c/1]).
-
--record(state,{socket_type = ip_comm,
- config_file,
- config_db = null,
- connections, %% Current request handlers
- admin_state = unblocked,
- blocker_ref = undefined,
- blocking_tmr = undefined,
- status = []}).
-
-
-c(Port) ->
- Ref = httpd_util:make_name("httpd",undefined,Port),
- gen_server:call(Ref, fake_close).
-
-
-%%
-%% External API
-%%
-
-start(ConfigFile, ConfigList) ->
- start(ConfigFile, ConfigList, []).
-
-start(ConfigFile, ConfigList, Verbosity) ->
- Port = httpd_util:key1search(ConfigList,port,80),
- Addr = httpd_util:key1search(ConfigList,bind_address),
- Name = make_name(Addr,Port),
- ?LOG("start -> Name = ~p",[Name]),
- gen_server:start({local,Name},?MODULE,
- [ConfigFile, ConfigList, Addr, Port, Verbosity],[]).
-
-start_link(ConfigFile, ConfigList) ->
- start_link(ConfigFile, ConfigList, []).
-
-start_link(ConfigFile, ConfigList, Verbosity) ->
- Port = httpd_util:key1search(ConfigList,port,80),
- Addr = httpd_util:key1search(ConfigList,bind_address),
- Name = make_name(Addr,Port),
- ?LOG("start_link -> Name = ~p",[Name]),
- gen_server:start_link({local, Name},?MODULE,
- [ConfigFile, ConfigList, Addr, Port, Verbosity],[]).
-
-%% stop
-
-stop(ServerRef) ->
- gen_server:call(ServerRef, stop).
-
-%% restart
-
-restart(ServerRef) ->
- gen_server:call(ServerRef, restart).
-
-
-%%%----------------------------------------------------------------
-
-block(ServerRef, disturbing) ->
- call(ServerRef,block);
-
-block(ServerRef, non_disturbing) ->
- do_block(ServerRef, non_disturbing, infinity).
-
-block(ServerRef, Method, Timeout) ->
- do_block(ServerRef, Method, Timeout).
-
-
-%% The reason for not using call here, is that the manager cannot
-%% _wait_ for completion of the requests. It must be able to do
-%% do other things at the same time as the blocking goes on.
-do_block(ServerRef, Method, infinity) ->
- Ref = make_ref(),
- cast(ServerRef, {block, Method, infinity, self(), Ref}),
- receive
- {block_reply, Reply, Ref} ->
- Reply
- end;
-do_block(ServerRef,Method,Timeout) when Timeout > 0 ->
- Ref = make_ref(),
- cast(ServerRef,{block,Method,Timeout,self(),Ref}),
- receive
- {block_reply,Reply,Ref} ->
- Reply
- end.
-
-
-%%%----------------------------------------------------------------
-
-%% unblock
-
-unblock(ServerRef) ->
- call(ServerRef,unblock).
-
-%% get admin/usage state
-
-get_admin_state(ServerRef) ->
- call(ServerRef,get_admin_state).
-
-get_usage_state(ServerRef) ->
- call(ServerRef,get_usage_state).
-
-
-%% get_status
-
-get_status(ServerRef) ->
- gen_server:call(ServerRef,get_status).
-
-get_status(ServerRef,Timeout) ->
- gen_server:call(ServerRef,get_status,Timeout).
-
-
-verbosity(ServerRef,Verbosity) ->
- verbosity(ServerRef,all,Verbosity).
-
-verbosity(ServerRef,all,Verbosity) ->
- gen_server:call(ServerRef,{verbosity,all,Verbosity});
-verbosity(ServerRef,manager,Verbosity) ->
- gen_server:call(ServerRef,{verbosity,manager,Verbosity});
-verbosity(ServerRef,request,Verbosity) ->
- gen_server:call(ServerRef,{verbosity,request,Verbosity});
-verbosity(ServerRef,acceptor,Verbosity) ->
- gen_server:call(ServerRef,{verbosity,acceptor,Verbosity});
-verbosity(ServerRef,security,Verbosity) ->
- gen_server:call(ServerRef,{verbosity,security,Verbosity});
-verbosity(ServerRef,auth,Verbosity) ->
- gen_server:call(ServerRef,{verbosity,auth,Verbosity}).
-
-%%
-%% Internal API
-%%
-
-
-%% new_connection
-
-new_connection(Manager) ->
- gen_server:call(Manager, {new_connection, self()}).
-
-%% done
-
-done_connection(Manager) ->
- gen_server:cast(Manager, {done_connection, self()}).
-
-
-%% is_busy(ServerRef) -> true | false
-%%
-%% Tests if the server is (in usage state) busy,
-%% i.e. has rached the heavy load limit.
-%%
-
-is_busy(ServerRef) ->
- gen_server:call(ServerRef,is_busy).
-
-is_busy(ServerRef,Timeout) ->
- gen_server:call(ServerRef,is_busy,Timeout).
-
-
-%% is_busy_or_blocked(ServerRef) -> busy | blocked | false
-%%
-%% Tests if the server is busy (usage state), i.e. has rached,
-%% the heavy load limit, or blocked (admin state) .
-%%
-
-is_busy_or_blocked(ServerRef) ->
- gen_server:call(ServerRef,is_busy_or_blocked).
-
-
-%% is_blocked(ServerRef) -> true | false
-%%
-%% Tests if the server is blocked (admin state) .
-%%
-
-is_blocked(ServerRef) ->
- gen_server:call(ServerRef,is_blocked).
-
-
-%%
-%% Module API. Theese functions are intended for use from modules only.
-%%
-
-config_lookup(Port, Query) ->
- config_lookup(undefined, Port, Query).
-config_lookup(Addr, Port, Query) ->
- Name = httpd_util:make_name("httpd",Addr,Port),
- gen_server:call(whereis(Name), {config_lookup, Query}).
-
-config_multi_lookup(Port, Query) ->
- config_multi_lookup(undefined,Port,Query).
-config_multi_lookup(Addr,Port, Query) ->
- Name = httpd_util:make_name("httpd",Addr,Port),
- gen_server:call(whereis(Name), {config_multi_lookup, Query}).
-
-config_match(Port, Pattern) ->
- config_match(undefined,Port,Pattern).
-config_match(Addr, Port, Pattern) ->
- Name = httpd_util:make_name("httpd",Addr,Port),
- gen_server:call(whereis(Name), {config_match, Pattern}).
-
-
-%%
-%% Server call-back functions
-%%
-
-%% init
-
-init([ConfigFile, ConfigList, Addr, Port, Verbosity]) ->
- process_flag(trap_exit, true),
- case (catch do_init(ConfigFile, ConfigList, Addr, Port, Verbosity)) of
- {error, Reason} ->
- ?vlog("failed starting server: ~p", [Reason]),
- {stop, Reason};
- {ok, State} ->
- {ok, State}
- end.
-
-
-do_init(ConfigFile, ConfigList, Addr, Port, Verbosity) ->
- put(sname,man),
- set_verbosity(Verbosity),
- ?vlog("starting",[]),
- ConfigDB = do_initial_store(ConfigList),
- ?vtrace("config db: ~p", [ConfigDB]),
- SocketType = httpd_socket:config(ConfigDB),
- ?vtrace("socket type: ~p, now start acceptor", [SocketType]),
- case httpd_acceptor_sup:start_acceptor(SocketType, Addr, Port, ConfigDB) of
- {ok, Pid} ->
- ?vtrace("acceptor started: ~p", [Pid]),
- Status = [{max_conn,0}, {last_heavy_load,never},
- {last_connection,never}],
- State = #state{socket_type = SocketType,
- config_file = ConfigFile,
- config_db = ConfigDB,
- connections = [],
- status = Status},
- ?vdebug("started",[]),
- {ok, State};
- Else ->
- Else
- end.
-
-
-do_initial_store(ConfigList) ->
- case httpd_conf:store(ConfigList) of
- {ok, ConfigDB} ->
- ConfigDB;
- {error, Reason} ->
- ?vinfo("failed storing configuration: ~p",[Reason]),
- throw({error, Reason})
- end.
-
-
-
-%% handle_call
-
-handle_call(stop, _From, State) ->
- ?vlog("stop",[]),
- {stop, normal, ok, State};
-
-handle_call({config_lookup, Query}, _From, State) ->
- ?vlog("config lookup: Query = ~p",[Query]),
- Res = httpd_util:lookup(State#state.config_db, Query),
- ?vdebug("config lookup result: ~p",[Res]),
- {reply, Res, State};
-
-handle_call({config_multi_lookup, Query}, _From, State) ->
- ?vlog("multi config lookup: Query = ~p",[Query]),
- Res = httpd_util:multi_lookup(State#state.config_db, Query),
- ?vdebug("multi config lookup result: ~p",[Res]),
- {reply, Res, State};
-
-handle_call({config_match, Query}, _From, State) ->
- ?vlog("config match: Query = ~p",[Query]),
- Res = ets:match_object(State#state.config_db, Query),
- ?vdebug("config match result: ~p",[Res]),
- {reply, Res, State};
-
-handle_call(get_status, _From, State) ->
- ?vdebug("get status",[]),
- ManagerStatus = manager_status(self()),
- %% AuthStatus = auth_status(get(auth_server)),
- %% SecStatus = sec_status(get(sec_server)),
- %% AccStatus = sec_status(get(acceptor_server)),
- S1 = [{current_conn,length(State#state.connections)}|State#state.status]++
- [ManagerStatus],
- ?vtrace("status = ~p",[S1]),
- {reply,S1,State};
-
-handle_call(is_busy, From, State) ->
- Reply = case get_ustate(State) of
- busy ->
- true;
- _ ->
- false
- end,
- ?vlog("is busy: ~p",[Reply]),
- {reply,Reply,State};
-
-handle_call(is_busy_or_blocked, From, State) ->
- Reply =
- case get_astate(State) of
- unblocked ->
- case get_ustate(State) of
- busy ->
- busy;
- _ ->
- false
- end;
- _ ->
- blocked
- end,
- ?vlog("is busy or blocked: ~p",[Reply]),
- {reply,Reply,State};
-
-handle_call(is_blocked, From, State) ->
- Reply =
- case get_astate(State) of
- unblocked ->
- false;
- _ ->
- true
- end,
- ?vlog("is blocked: ~p",[Reply]),
- {reply,Reply,State};
-
-handle_call(get_admin_state, From, State) ->
- Reply = get_astate(State),
- ?vlog("admin state: ~p",[Reply]),
- {reply,Reply,State};
-
-handle_call(get_usage_state, From, State) ->
- Reply = get_ustate(State),
- ?vlog("usage state: ~p",[Reply]),
- {reply,Reply,State};
-
-handle_call({verbosity,Who,Verbosity}, From, State) ->
- V = ?vvalidate(Verbosity),
- ?vlog("~n Set new verbosity to ~p for ~p",[V,Who]),
- Reply = set_verbosity(Who,V,State),
- {reply,Reply,State};
-
-handle_call(restart, From, State) when State#state.admin_state == blocked ->
- ?vlog("restart",[]),
- case handle_restart(State) of
- {stop, Reply,S1} ->
- {stop, Reply, S1};
- {_, Reply, S1} ->
- {reply,Reply,S1}
- end;
-
-handle_call(restart, From, State) ->
- ?vlog("restart(~p)",[State#state.admin_state]),
- {reply,{error,{invalid_admin_state,State#state.admin_state}},State};
-
-handle_call(block, From, State) ->
- ?vlog("block(disturbing)",[]),
- {Reply,S1} = handle_block(State),
- {reply,Reply,S1};
-
-handle_call(unblock, {From,_Tag}, State) ->
- ?vlog("unblock",[]),
- {Reply,S1} = handle_unblock(State,From),
- {reply, Reply, S1};
-
-handle_call({new_connection, Pid}, From, State) ->
- ?vlog("~n New connection (~p) when connection count = ~p",
- [Pid,length(State#state.connections)]),
- {S, S1} = handle_new_connection(State, Pid),
- Reply = {S, get(request_handler_verbosity)},
- {reply, Reply, S1};
-
-handle_call(Request, From, State) ->
- ?vinfo("~n unknown request '~p' from ~p", [Request,From]),
- String =
- lists:flatten(
- io_lib:format("Unknown request "
- "~n ~p"
- "~nto manager (~p)"
- "~nfrom ~p",
- [Request, self(), From])),
- report_error(State,String),
- {reply, ok, State}.
-
-
-%% handle_cast
-
-handle_cast({done_connection, Pid}, State) ->
- ?vlog("~n Done connection (~p)", [Pid]),
- S1 = handle_done_connection(State, Pid),
- {noreply, S1};
-
-handle_cast({block, disturbing, Timeout, From, Ref}, State) ->
- ?vlog("block(disturbing,~p)",[Timeout]),
- S1 = handle_block(State, Timeout, From, Ref),
- {noreply,S1};
-
-handle_cast({block, non_disturbing, Timeout, From, Ref}, State) ->
- ?vlog("block(non-disturbing,~p)",[Timeout]),
- S1 = handle_nd_block(State, Timeout, From, Ref),
- {noreply,S1};
-
-handle_cast(Message, State) ->
- ?vinfo("~n received unknown message '~p'",[Message]),
- String =
- lists:flatten(
- io_lib:format("Unknown message "
- "~n ~p"
- "~nto manager (~p)",
- [Message, self()])),
- report_error(State, String),
- {noreply, State}.
-
-%% handle_info
-
-handle_info({block_timeout, Method}, State) ->
- ?vlog("received block_timeout event",[]),
- S1 = handle_block_timeout(State,Method),
- {noreply, S1};
-
-handle_info({'DOWN', Ref, process, _Object, Info}, State) ->
- ?vlog("~n down message for ~p",[Ref]),
- S1 =
- case State#state.blocker_ref of
- Ref ->
- handle_blocker_exit(State);
- _ ->
- %% Not our blocker, so ignore
- State
- end,
- {noreply, S1};
-
-handle_info({'EXIT', Pid, normal}, State) ->
- ?vdebug("~n Normal exit message from ~p", [Pid]),
- {noreply, State};
-
-handle_info({'EXIT', Pid, blocked}, S) ->
- ?vdebug("blocked exit signal from request handler (~p)", [Pid]),
- {noreply, S};
-
-handle_info({'EXIT', Pid, Reason}, State) ->
- ?vlog("~n Exit message from ~p for reason ~p",[Pid, Reason]),
- S1 = check_connections(State, Pid, Reason),
- {noreply, S1};
-
-handle_info(Info, State) ->
- ?vinfo("~n received unknown info '~p'",[Info]),
- String =
- lists:flatten(
- io_lib:format("Unknown info "
- "~n ~p"
- "~nto manager (~p)",
- [Info, self()])),
- report_error(State, String),
- {noreply, State}.
-
-
-%% terminate
-
-terminate(R, #state{config_db = Db}) ->
- ?vlog("Terminating for reason: ~n ~p", [R]),
- httpd_conf:remove_all(Db),
- ok.
-
-
-%% code_change({down,ToVsn}, State, Extra)
-%%
-%% NOTE:
-%% Actually upgrade from 2.5.1 to 2.5.3 and downgrade from
-%% 2.5.3 to 2.5.1 is done with an application restart, so
-%% these function is actually never used. The reason for keeping
-%% this stuff is only for future use.
-%%
-code_change({down,ToVsn},State,Extra) ->
- {ok,State};
-
-%% code_change(FromVsn, State, Extra)
-%%
-code_change(FromVsn,State,Extra) ->
- {ok,State}.
-
-
-
-%% -------------------------------------------------------------------------
-%% check_connection
-%%
-%%
-%%
-%%
-
-check_connections(#state{connections = []} = State, _Pid, _Reason) ->
- State;
-check_connections(#state{admin_state = shutting_down,
- connections = Connections} = State, Pid, Reason) ->
- %% Could be a crashing request handler
- case lists:delete(Pid, Connections) of
- [] -> % Crashing request handler => block complete
- String =
- lists:flatten(
- io_lib:format("request handler (~p) crashed:"
- "~n ~p", [Pid, Reason])),
- report_error(State, String),
- ?vlog("block complete",[]),
- demonitor_blocker(State#state.blocker_ref),
- {Tmr,From,Ref} = State#state.blocking_tmr,
- ?vlog("(possibly) stop block timer",[]),
- stop_block_tmr(Tmr),
- ?vlog("and send the reply",[]),
- From ! {block_reply,ok,Ref},
- State#state{admin_state = blocked, connections = [],
- blocker_ref = undefined};
- Connections1 ->
- State#state{connections = Connections1}
- end;
-check_connections(#state{connections = Connections} = State, Pid, Reason) ->
- case lists:delete(Pid, Connections) of
- Connections -> % Not a request handler, so ignore
- State;
- Connections1 ->
- String =
- lists:flatten(
- io_lib:format("request handler (~p) crashed:"
- "~n ~p", [Pid, Reason])),
- report_error(State, String),
- State#state{connections = lists:delete(Pid, Connections)}
- end.
-
-
-%% -------------------------------------------------------------------------
-%% handle_[new | done]_connection
-%%
-%%
-%%
-%%
-
-handle_new_connection(State, Handler) ->
- UsageState = get_ustate(State),
- AdminState = get_astate(State),
- handle_new_connection(UsageState, AdminState, State, Handler).
-
-handle_new_connection(busy, unblocked, State, Handler) ->
- Status = update_heavy_load_status(State#state.status),
- {{reject, busy},
- State#state{status = Status}};
-
-handle_new_connection(_UsageState, unblocked, State, Handler) ->
- Connections = State#state.connections,
- Status = update_connection_status(State#state.status,
- length(Connections)+1),
- link(Handler),
- {accept,
- State#state{connections = [Handler|Connections], status = Status}};
-
-handle_new_connection(_UsageState, _AdminState, State, _Handler) ->
- {{reject, blocked},
- State}.
-
-
-handle_done_connection(#state{admin_state = shutting_down,
- connections = Connections} = State, Handler) ->
- unlink(Handler),
- case lists:delete(Handler, Connections) of
- [] -> % Ok, block complete
- ?vlog("block complete",[]),
- demonitor_blocker(State#state.blocker_ref),
- {Tmr,From,Ref} = State#state.blocking_tmr,
- ?vlog("(possibly) stop block timer",[]),
- stop_block_tmr(Tmr),
- ?vlog("and send the reply",[]),
- From ! {block_reply,ok,Ref},
- State#state{admin_state = blocked, connections = [],
- blocker_ref = undefined};
- Connections1 ->
- State#state{connections = Connections1}
- end;
-
-handle_done_connection(#state{connections = Connections} = State, Handler) ->
- State#state{connections = lists:delete(Handler, Connections)}.
-
-
-%% -------------------------------------------------------------------------
-%% handle_block
-%%
-%%
-%%
-%%
-handle_block(#state{admin_state = AdminState} = S) ->
- handle_block(S, AdminState).
-
-handle_block(S,unblocked) ->
- %% Kill all connections
- ?vtrace("handle_block(unblocked) -> kill all request handlers",[]),
-%% [exit(Pid,blocked) || Pid <- S#state.connections],
- [kill_handler(Pid) || Pid <- S#state.connections],
- {ok,S#state{connections = [], admin_state = blocked}};
-handle_block(S,blocked) ->
- ?vtrace("handle_block(blocked) -> already blocked",[]),
- {ok,S};
-handle_block(S,shutting_down) ->
- ?vtrace("handle_block(shutting_down) -> ongoing...",[]),
- {{error,shutting_down},S}.
-
-
-kill_handler(Pid) ->
- ?vtrace("kill request handler: ~p",[Pid]),
- exit(Pid, blocked).
-%% exit(Pid, kill).
-
-handle_block(S,Timeout,From,Ref) when Timeout >= 0 ->
- do_block(S,Timeout,From,Ref);
-
-handle_block(S,Timeout,From,Ref) ->
- Reply = {error,{invalid_block_request,Timeout}},
- From ! {block_reply,Reply,Ref},
- S.
-
-do_block(S,Timeout,From,Ref) ->
- case S#state.connections of
- [] ->
- %% Already in idle usage state => go directly to blocked
- ?vdebug("do_block -> already in idle usage state",[]),
- From ! {block_reply,ok,Ref},
- S#state{admin_state = blocked};
- _ ->
- %% Active or Busy usage state => go to shutting_down
- ?vdebug("do_block -> active or busy usage state",[]),
- %% Make sure we get to know if blocker dies...
- ?vtrace("do_block -> create blocker monitor",[]),
- MonitorRef = monitor_blocker(From),
- ?vtrace("do_block -> (possibly) start block timer",[]),
- Tmr = {start_block_tmr(Timeout,disturbing),From,Ref},
- S#state{admin_state = shutting_down,
- blocker_ref = MonitorRef, blocking_tmr = Tmr}
- end.
-
-handle_nd_block(S,infinity,From,Ref) ->
- do_nd_block(S,infinity,From,Ref);
-
-handle_nd_block(S,Timeout,From,Ref) when Timeout >= 0 ->
- do_nd_block(S,Timeout,From,Ref);
-
-handle_nd_block(S,Timeout,From,Ref) ->
- Reply = {error,{invalid_block_request,Timeout}},
- From ! {block_reply,Reply,Ref},
- S.
-
-do_nd_block(S,Timeout,From,Ref) ->
- case S#state.connections of
- [] ->
- %% Already in idle usage state => go directly to blocked
- ?vdebug("do_nd_block -> already in idle usage state",[]),
- From ! {block_reply,ok,Ref},
- S#state{admin_state = blocked};
- _ ->
- %% Active or Busy usage state => go to shutting_down
- ?vdebug("do_nd_block -> active or busy usage state",[]),
- %% Make sure we get to know if blocker dies...
- ?vtrace("do_nd_block -> create blocker monitor",[]),
- MonitorRef = monitor_blocker(From),
- ?vtrace("do_nd_block -> (possibly) start block timer",[]),
- Tmr = {start_block_tmr(Timeout,non_disturbing),From,Ref},
- S#state{admin_state = shutting_down,
- blocker_ref = MonitorRef, blocking_tmr = Tmr}
- end.
-
-handle_block_timeout(S,Method) ->
- %% Time to take this to the road...
- demonitor_blocker(S#state.blocker_ref),
- handle_block_timeout1(S,Method,S#state.blocking_tmr).
-
-handle_block_timeout1(S,non_disturbing,{_,From,Ref}) ->
- ?vdebug("handle_block_timeout1(non-disturbing) -> send reply: timeout",[]),
- From ! {block_reply,{error,timeout},Ref},
- S#state{admin_state = unblocked,
- blocker_ref = undefined, blocking_tmr = undefined};
-
-handle_block_timeout1(S,disturbing,{_,From,Ref}) ->
- ?vdebug("handle_block_timeout1(disturbing) -> kill all connections",[]),
- [exit(Pid,blocked) || Pid <- S#state.connections],
-
- ?vdebug("handle_block_timeout1 -> send reply: ok",[]),
- From ! {block_reply,ok,Ref},
- S#state{admin_state = blocked, connections = [],
- blocker_ref = undefined, blocking_tmr = undefined};
-
-handle_block_timeout1(S,Method,{_,From,Ref}) ->
- ?vinfo("received block timeout with unknown block method:"
- "~n Method: ~p",[Method]),
- From ! {block_reply,{error,{unknown_block_method,Method}},Ref},
- S#state{admin_state = blocked, connections = [],
- blocker_ref = undefined, blocking_tmr = undefined};
-
-handle_block_timeout1(S,Method,TmrInfo) ->
- ?vinfo("received block timeout with erroneous timer info:"
- "~n Method: ~p"
- "~n TmrInfo: ~p",[Method,TmrInfo]),
- S#state{admin_state = unblocked,
- blocker_ref = undefined, blocking_tmr = undefined}.
-
-handle_unblock(S,FromA) ->
- handle_unblock(S,FromA,S#state.admin_state).
-
-handle_unblock(S,_FromA,unblocked) ->
- {ok,S};
-handle_unblock(S,FromA,_AdminState) ->
- ?vtrace("handle_unblock -> (possibly) stop block timer",[]),
- stop_block_tmr(S#state.blocking_tmr),
- case S#state.blocking_tmr of
- {Tmr,FromB,Ref} ->
- %% Another process is trying to unblock
- %% Inform the blocker
- FromB ! {block_reply, {error,{unblocked,FromA}},Ref};
- _ ->
- ok
- end,
- {ok,S#state{admin_state = unblocked, blocking_tmr = undefined}}.
-
-%% The blocker died so we give up on the block.
-handle_blocker_exit(S) ->
- {Tmr,_From,_Ref} = S#state.blocking_tmr,
- ?vtrace("handle_blocker_exit -> (possibly) stop block timer",[]),
- stop_block_tmr(Tmr),
- S#state{admin_state = unblocked,
- blocker_ref = undefined, blocking_tmr = undefined}.
-
-
-
-%% -------------------------------------------------------------------------
-%% handle_restart
-%%
-%%
-%%
-%%
-handle_restart(#state{config_file = undefined} = State) ->
- {continue, {error, undefined_config_file}, State};
-handle_restart(#state{config_db = Db, config_file = ConfigFile} = State) ->
- ?vtrace("load new configuration",[]),
- {ok, Config} = httpd_conf:load(ConfigFile),
- ?vtrace("check for illegal changes (addr, port and socket-type)",[]),
- case (catch check_constant_values(Db, Config)) of
- ok ->
- %% If something goes wrong between the remove
- %% and the store where fu-ed
- ?vtrace("remove old configuration, now hold you breath...",[]),
- httpd_conf:remove_all(Db),
- ?vtrace("store new configuration",[]),
- case httpd_conf:store(Config) of
- {ok, NewConfigDB} ->
- ?vlog("restart done, puh!",[]),
- {continue, ok, State#state{config_db = NewConfigDB}};
- Error ->
- ?vlog("failed store new config: ~n ~p",[Error]),
- {stop, Error, State}
- end;
- Error ->
- ?vlog("restart NOT performed due to:"
- "~n ~p",[Error]),
- {continue, Error, State}
- end.
-
-
-check_constant_values(Db, Config) ->
- %% Check port number
- ?vtrace("check_constant_values -> check port number",[]),
- Port = httpd_util:lookup(Db,port),
- case httpd_util:key1search(Config,port) of %% MUST be equal
- Port ->
- ok;
- OtherPort ->
- throw({error,{port_number_changed,Port,OtherPort}})
- end,
-
- %% Check bind address
- ?vtrace("check_constant_values -> check bind address",[]),
- Addr = httpd_util:lookup(Db,bind_address),
- case httpd_util:key1search(Config,bind_address) of %% MUST be equal
- Addr ->
- ok;
- OtherAddr ->
- throw({error,{addr_changed,Addr,OtherAddr}})
- end,
-
- %% Check socket type
- ?vtrace("check_constant_values -> check socket type",[]),
- SockType = httpd_util:lookup(Db, com_type),
- case httpd_util:key1search(Config, com_type) of %% MUST be equal
- SockType ->
- ok;
- OtherSockType ->
- throw({error,{sock_type_changed,SockType,OtherSockType}})
- end,
- ?vtrace("check_constant_values -> done",[]),
- ok.
-
-
-%% get_ustate(State) -> idle | active | busy
-%%
-%% Retrieve the usage state of the HTTP server:
-%% 0 active connection -> idle
-%% max_clients active connections -> busy
-%% Otherwise -> active
-%%
-get_ustate(State) ->
- get_ustate(length(State#state.connections),State).
-
-get_ustate(0,_State) ->
- idle;
-get_ustate(ConnectionCnt,State) ->
- ConfigDB = State#state.config_db,
- case httpd_util:lookup(ConfigDB, max_clients, 150) of
- ConnectionCnt ->
- busy;
- _ ->
- active
- end.
-
-
-get_astate(S) -> S#state.admin_state.
-
-
-%% Timer handling functions
-start_block_tmr(infinity,_) ->
- undefined;
-start_block_tmr(T,M) ->
- erlang:send_after(T,self(),{block_timeout,M}).
-
-stop_block_tmr(undefined) ->
- ok;
-stop_block_tmr(Ref) ->
- erlang:cancel_timer(Ref).
-
-
-%% Monitor blocker functions
-monitor_blocker(Pid) when pid(Pid) ->
- case (catch erlang:monitor(process,Pid)) of
- MonitorRef ->
- MonitorRef;
- {'EXIT',Reason} ->
- undefined
- end;
-monitor_blocker(_) ->
- undefined.
-
-demonitor_blocker(undefined) ->
- ok;
-demonitor_blocker(Ref) ->
- (catch erlang:demonitor(Ref)).
-
-
-%% Some status utility functions
-
-update_heavy_load_status(Status) ->
- update_status_with_time(Status,last_heavy_load).
-
-update_connection_status(Status,ConnCount) ->
- S1 = case lists:keysearch(max_conn,1,Status) of
- {value,{max_conn,C1}} when ConnCount > C1 ->
- lists:keyreplace(max_conn,1,Status,{max_conn,ConnCount});
- {value,{max_conn,C2}} ->
- Status;
- false ->
- [{max_conn,ConnCount}|Status]
- end,
- update_status_with_time(S1,last_connection).
-
-update_status_with_time(Status,Key) ->
- lists:keyreplace(Key,1,Status,{Key,universal_time()}).
-
-universal_time() -> calendar:universal_time().
-
-
-auth_status(P) when pid(P) ->
- Items = [status, message_queue_len, reductions,
- heap_size, stack_size, current_function],
- {auth_status, process_status(P,Items,[])};
-auth_status(_) ->
- {auth_status, undefined}.
-
-sec_status(P) when pid(P) ->
- Items = [status, message_queue_len, reductions,
- heap_size, stack_size, current_function],
- {security_status, process_status(P,Items,[])};
-sec_status(_) ->
- {security_status, undefined}.
-
-acceptor_status(P) when pid(P) ->
- Items = [status, message_queue_len, reductions,
- heap_size, stack_size, current_function],
- {acceptor_status, process_status(P,Items,[])};
-acceptor_status(_) ->
- {acceptor_status, undefined}.
-
-
-manager_status(P) ->
- Items = [status, message_queue_len, reductions,
- heap_size, stack_size],
- {manager_status, process_status(P,Items,[])}.
-
-
-process_status(P,[],L) ->
- [{pid,P}|lists:reverse(L)];
-process_status(P,[H|T],L) ->
- case (catch process_info(P,H)) of
- {H, Value} ->
- process_status(P,T,[{H,Value}|L]);
- _ ->
- process_status(P,T,[{H,undefined}|L])
- end.
-
-make_name(Addr,Port) ->
- httpd_util:make_name("httpd",Addr,Port).
-
-
-report_error(State,String) ->
- Cdb = State#state.config_db,
- error_logger:error_report(String),
- mod_log:report_error(Cdb,String),
- mod_disk_log:report_error(Cdb,String).
-
-
-set_verbosity(V) ->
- Units = [manager_verbosity,
- acceptor_verbosity, request_handler_verbosity,
- security_verbosity, auth_verbosity],
- case httpd_util:key1search(V, all) of
- undefined ->
- set_verbosity(V, Units);
- Verbosity when atom(Verbosity) ->
- V1 = [{Unit, Verbosity} || Unit <- Units],
- set_verbosity(V1, Units)
- end.
-
-set_verbosity(_V, []) ->
- ok;
-set_verbosity(V, [manager_verbosity = Unit|Units]) ->
- Verbosity = httpd_util:key1search(V, Unit, ?default_verbosity),
- put(verbosity, ?vvalidate(Verbosity)),
- set_verbosity(V, Units);
-set_verbosity(V, [Unit|Units]) ->
- Verbosity = httpd_util:key1search(V, Unit, ?default_verbosity),
- put(Unit, ?vvalidate(Verbosity)),
- set_verbosity(V, Units).
-
-
-set_verbosity(manager,V,_S) ->
- put(verbosity,V);
-set_verbosity(acceptor,V,_S) ->
- put(acceptor_verbosity,V);
-set_verbosity(request,V,_S) ->
- put(request_handler_verbosity,V);
-set_verbosity(security,V,S) ->
- OldVerbosity = put(security_verbosity,V),
- Addr = httpd_util:lookup(S#state.config_db, bind_address),
- Port = httpd_util:lookup(S#state.config_db, port),
- mod_security_server:verbosity(Addr,Port,V),
- OldVerbosity;
-set_verbosity(auth,V,S) ->
- OldVerbosity = put(auth_verbosity,V),
- Addr = httpd_util:lookup(S#state.config_db, bind_address),
- Port = httpd_util:lookup(S#state.config_db, port),
- mod_auth_server:verbosity(Addr,Port,V),
- OldVerbosity;
-
-set_verbosity(all,V,S) ->
- OldMv = put(verbosity,V),
- OldAv = put(acceptor_verbosity,V),
- OldRv = put(request_handler_verbosity,V),
- OldSv = put(security_verbosity,V),
- OldAv = put(auth_verbosity,V),
- Addr = httpd_util:lookup(S#state.config_db, bind_address),
- Port = httpd_util:lookup(S#state.config_db, port),
- mod_security_server:verbosity(Addr,Port,V),
- mod_auth_server:verbosity(Addr,Port,V),
- [{manager,OldMv}, {request,OldRv}, {security,OldSv}, {auth, OldAv}].
-
-
-%%
-call(ServerRef,Request) ->
- gen_server:call(ServerRef,Request).
-
-cast(ServerRef,Message) ->
- gen_server:cast(ServerRef,Message).
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_misc_sup.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_misc_sup.erl
deleted file mode 100644
index 5921c5db60..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_misc_sup.erl
+++ /dev/null
@@ -1,116 +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: httpd_misc_sup.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
-%%
-%%----------------------------------------------------------------------
-%% Purpose: The top supervisor for the Megaco/H.248 application
-%%----------------------------------------------------------------------
-
--module(httpd_misc_sup).
-
--behaviour(supervisor).
-
--include("httpd_verbosity.hrl").
-
-%% public
--export([start/3, stop/1, init/1]).
-
--export([start_auth_server/3, stop_auth_server/2,
- start_sec_server/3, stop_sec_server/2]).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% supervisor callback functions
-
-
-start(Addr, Port, MiscSupVerbosity) ->
- SupName = make_name(Addr, Port),
- supervisor:start_link({local, SupName}, ?MODULE, [MiscSupVerbosity]).
-
-stop(StartArgs) ->
- ok.
-
-init([Verbosity]) -> % Supervisor
- do_init(Verbosity);
-init(BadArg) ->
- {error, {badarg, BadArg}}.
-
-do_init(Verbosity) ->
- put(verbosity,?vvalidate(Verbosity)),
- put(sname,misc_sup),
- ?vlog("starting", []),
- Flags = {one_for_one, 0, 1},
- KillAfter = timer:seconds(1),
- Workers = [],
- {ok, {Flags, Workers}}.
-
-
-%%----------------------------------------------------------------------
-%% Function: [start|stop]_[auth|sec]_server/3
-%% Description: Starts a [auth | security] worker (child) process
-%%----------------------------------------------------------------------
-
-start_auth_server(Addr, Port, Verbosity) ->
- start_permanent_worker(mod_auth_server, Addr, Port,
- Verbosity, [gen_server]).
-
-stop_auth_server(Addr, Port) ->
- stop_permanent_worker(mod_auth_server, Addr, Port).
-
-
-start_sec_server(Addr, Port, Verbosity) ->
- start_permanent_worker(mod_security_server, Addr, Port,
- Verbosity, [gen_server]).
-
-stop_sec_server(Addr, Port) ->
- stop_permanent_worker(mod_security_server, Addr, Port).
-
-
-
-%%----------------------------------------------------------------------
-%% Function: start_permanent_worker/5
-%% Description: Starts a permanent worker (child) process
-%%----------------------------------------------------------------------
-
-start_permanent_worker(Mod, Addr, Port, Verbosity, Modules) ->
- SupName = make_name(Addr, Port),
- Spec = {{Mod, Addr, Port},
- {Mod, start_link, [Addr, Port, Verbosity]},
- permanent, timer:seconds(1), worker, [Mod] ++ Modules},
- supervisor:start_child(SupName, Spec).
-
-
-%%----------------------------------------------------------------------
-%% Function: stop_permanent_worker/3
-%% Description: Stops a permanent worker (child) process
-%%----------------------------------------------------------------------
-
-stop_permanent_worker(Mod, Addr, Port) ->
- SupName = make_name(Addr, Port),
- Name = {Mod, Addr, Port},
- case supervisor:terminate_child(SupName, Name) of
- ok ->
- supervisor:delete_child(SupName, Name);
- Error ->
- Error
- end.
-
-
-make_name(Addr,Port) ->
- httpd_util:make_name("httpd_misc_sup",Addr,Port).
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_parse.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_parse.erl
deleted file mode 100644
index 3f8f0837f9..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_parse.erl
+++ /dev/null
@@ -1,348 +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: httpd_parse.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
-%%
--module(httpd_parse).
--export([
- request_header/1,
- hsplit/2,
- get_request_record/10,
- split_lines/1,
- tagup_header/1]).
--include("httpd.hrl").
-
-
-%%----------------------------------------------------------------------
-%% request_header
-%%
-%% Input: The request as sent from the client (list of characters)
-%% (may include part of the entity body)
-%%
-%% Returns:
-%% {ok, Info#mod}
-%% {not_implemented,Info#mod}
-%% {bad_request, Reason}
-%%----------------------------------------------------------------------
-
-request_header(Header)->
- [RequestLine|HeaderFields] = split_lines(Header),
- ?DEBUG("request ->"
- "~n RequestLine: ~p"
- "~n Header: ~p",[RequestLine,Header]),
- ParsedHeader = tagup_header(HeaderFields),
- ?DEBUG("request ->"
- "~n ParseHeader: ~p",[ParsedHeader]),
- case verify_request(string:tokens(RequestLine," ")) of
- ["HEAD", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N]] ->
- {ok, ["HEAD", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N], RequestLine,
- ParsedHeader]};
- ["GET", RequestURI, "HTTP/0.9"] ->
- {ok, ["GET", RequestURI, "HTTP/0.9", RequestLine, ParsedHeader]};
- ["GET", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N]] ->
- {ok, ["GET", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N], RequestLine,
- ParsedHeader]};
- ["POST", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N]] ->
- {ok, ["POST", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N], RequestLine,
- ParsedHeader]};
- %%HTTP must be 1.1 or higher
- ["TRACE", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N]] when N>48->
- {ok, ["TRACE", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N], RequestLine,
- ParsedHeader]};
- [Method, RequestURI] ->
- {not_implemented, RequestLine, Method, RequestURI,ParsedHeader,"HTTP/0.9"};
- [Method, RequestURI, HTTPVersion] ->
- {not_implemented, RequestLine, Method, RequestURI,ParsedHeader, HTTPVersion};
- {bad_request, Reason} ->
- {bad_request, Reason};
- Reason ->
- {bad_request, "Unknown request method"}
- end.
-
-
-
-
-
-
-%%----------------------------------------------------------------------
-%% The request is passed through the server as a record of type mod get it
-%% ----------------------------------------------------------------------
-
-get_request_record(Socket,SocketType,ConfigDB,Method,RequestURI,
- HTTPVersion,RequestLine,ParsedHeader,EntityBody,InitData)->
- PersistentConn=get_persistens(HTTPVersion,ParsedHeader,ConfigDB),
- Info=#mod{init_data=InitData,
- data=[],
- socket_type=SocketType,
- socket=Socket,
- config_db=ConfigDB,
- method=Method,
- absolute_uri=formatAbsoluteURI(RequestURI,ParsedHeader),
- request_uri=formatRequestUri(RequestURI),
- http_version=HTTPVersion,
- request_line=RequestLine,
- parsed_header=ParsedHeader,
- entity_body=maybe_remove_nl(ParsedHeader,EntityBody),
- connection=PersistentConn},
- {ok,Info}.
-
-%%----------------------------------------------------------------------
-%% Conmtrol wheater we shall maintain a persistent connection or not
-%%----------------------------------------------------------------------
-get_persistens(HTTPVersion,ParsedHeader,ConfigDB)->
- case httpd_util:lookup(ConfigDB,persistent_conn,true) of
- true->
- case HTTPVersion of
- %%If it is version prio to 1.1 kill the conneciton
- [$H, $T, $T, $P, $\/, $1, $.,N] ->
- case httpd_util:key1search(ParsedHeader,"connection","keep-alive")of
- %%if the connection isnt ordered to go down let it live
- %%The keep-alive value is the older http/1.1 might be older
- %%Clients that use it.
- "keep-alive" when N >= 49 ->
- ?DEBUG("CONNECTION MODE: ~p",[true]),
- true;
- "close" ->
- ?DEBUG("CONNECTION MODE: ~p",[false]),
- false;
- Connect ->
- ?DEBUG("CONNECTION MODE: ~p VALUE: ~p",[false,Connect]),
- false
- end;
- _ ->
- ?DEBUG("CONNECTION MODE: ~p VERSION: ~p",[false,HTTPVersion]),
- false
-
- end;
- _ ->
- false
- end.
-
-
-
-
-%%----------------------------------------------------------------------
-%% Control whether the last newline of the body is a part of the message or
-%%it is a part of the multipart message.
-%%----------------------------------------------------------------------
-maybe_remove_nl(Header,Rest) ->
- case find_content_type(Header) of
- false ->
- {ok,EntityBody,_}=regexp:sub(Rest,"\r\n\$",""),
- EntityBody;
- {ok, Value} ->
- case string:str(Value, "multipart/form-data") of
- 0 ->
- {ok,EntityBody,_}=regexp:sub(Rest,"\r\n\$",""),
- EntityBody;
- _ ->
- Rest
- end
- end.
-
-%%----------------------------------------------------------------------
-%% Cet the content type of the incomming request
-%%----------------------------------------------------------------------
-
-
-find_content_type([]) ->
- false;
-find_content_type([{Name,Value}|Tail]) ->
- case httpd_util:to_lower(Name) of
- "content-type" ->
- {ok, Value};
- _ ->
- find_content_type(Tail)
- end.
-
-%%----------------------------------------------------------------------
-%% Split the header to a list of strings where each string represents a
-%% HTTP header-field
-%%----------------------------------------------------------------------
-split_lines(Request) ->
- split_lines(Request, [], []).
-split_lines([], CAcc, Acc) ->
- lists:reverse([lists:reverse(CAcc)|Acc]);
-
-%%White space in the header fields are allowed but the new line must begin with LWS se
-%%rfc2616 chap 4.2. The rfc do not say what to
-split_lines([$\r, $\n, $\t |Rest], CAcc, Acc) ->
- split_lines(Rest, [$\r, $\n |CAcc], Acc);
-
-split_lines([$\r, $\n, $\s |Rest], CAcc, Acc) ->
- split_lines(Rest, [$\r, $\n |CAcc], Acc);
-
-split_lines([$\r, $\n|Rest], CAcc, Acc) ->
- split_lines(Rest, [], [lists:reverse(CAcc)|Acc]);
-split_lines([Chr|Rest], CAcc, Acc) ->
- split_lines(Rest, [Chr|CAcc], Acc).
-
-
-%%----------------------------------------------------------------------
-%% This is a 'hack' to stop people from trying to access directories/files
-%% relative to the ServerRoot.
-%%----------------------------------------------------------------------
-
-
-verify_request([Request, RequestURI]) ->
- verify_request([Request, RequestURI, "HTTP/0.9"]);
-
-verify_request([Request, RequestURI, Protocol]) ->
- NewRequestURI =
- case string:str(RequestURI, "?") of
- 0 ->
- RequestURI;
- Ndx ->
- string:left(RequestURI, Ndx)
- end,
- case string:str(NewRequestURI, "..") of
- 0 ->
- [Request, RequestURI, Protocol];
- _ ->
- {bad_request, {forbidden, RequestURI}}
- end;
-verify_request(Request) ->
- Request.
-
-%%----------------------------------------------------------------------
-%% tagup_header
-%%
-%% Parses the header of a HTTP request and returns a key,value tuple
-%% list containing Name and Value of each header directive as of:
-%%
-%% Content-Type: multipart/mixed -> {"Content-Type", "multipart/mixed"}
-%%
-%% But in http/1.1 the field-names are case insencitive so now it must be
-%% Content-Type: multipart/mixed -> {"content-type", "multipart/mixed"}
-%% The standard furthermore says that leading and traling white space
-%% is not a part of the fieldvalue and shall therefore be removed.
-%%----------------------------------------------------------------------
-
-tagup_header([]) -> [];
-tagup_header([Line|Rest]) -> [tag(Line, [])|tagup_header(Rest)].
-
-tag([], Tag) ->
- {httpd_util:to_lower(lists:reverse(Tag)), ""};
-tag([$:|Rest], Tag) ->
- {httpd_util:to_lower(lists:reverse(Tag)), httpd_util:strip(Rest)};
-tag([Chr|Rest], Tag) ->
- tag(Rest, [Chr|Tag]).
-
-
-%%----------------------------------------------------------------------
-%% There are 3 possible forms of the reuqest URI
-%%
-%% 1. * When the request is not for a special assset. is is instead
-%% to the server itself
-%%
-%% 2. absoluteURI the whole servername port and asset is in the request
-%%
-%% 3. The most common form that http/1.0 used abs path that is a path
-%% to the requested asset.
-%5----------------------------------------------------------------------
-formatRequestUri("*")->
- "*";
-formatRequestUri([$h,$t,$t,$p,$:,$\/,$\/|ServerAndPath]) ->
- removeServer(ServerAndPath);
-
-formatRequestUri([$H,$T,$T,$P,$:,$\/,$\/|ServerAndPath]) ->
- removeServer(ServerAndPath);
-
-formatRequestUri(ABSPath) ->
- ABSPath.
-
-removeServer([$\/|Url])->
- case Url of
- []->
- "/";
- _->
- [$\/|Url]
- end;
-removeServer([N|Url]) ->
- removeServer(Url).
-
-
-formatAbsoluteURI([$h,$t,$t,$p,$:,$\/,$\/|Uri],ParsedHeader)->
- [$H,$T,$T,$P,$:,$\/,$\/|Uri];
-
-formatAbsoluteURI([$H,$T,$T,$P,$:,$\/,$\/|Uri],ParsedHeader)->
- [$H,$T,$T,$P,$:,$\/,$\/|Uri];
-
-formatAbsoluteURI(Uri,ParsedHeader)->
- case httpd_util:key1search(ParsedHeader,"host") of
- undefined ->
- nohost;
- Host ->
- Host++Uri
- end.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%Code below is crap from an older version shall be removed when
-%%transformation to http/1.1 is finished
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-
-%request(Request) ->
-% ?DEBUG("request -> entry with:"
-% "~n Request: ~s",[Request]),
- % {BeforeEntityBody, Rest} = hsplit([], Request),
- % ?DEBUG("request ->"
-% "~n BeforeEntityBody: ~p"
-% "~n Rest: ~p",[BeforeEntityBody, Rest]),
-% [RequestLine|Header] = split_lines(BeforeEntityBody),
-% ?DEBUG("request ->"
-% "~n RequestLine: ~p"
-% "~n Header: ~p",[RequestLine,Header]),
-% ParsedHeader = tagup_header(Header),
-% ?DEBUG("request ->"
-% "~n ParseHeader: ~p",[ParsedHeader]),
-% EntityBody = maybe_remove_nl(ParsedHeader,Rest),
-% ?DEBUG("request ->"
-% "~n EntityBody: ~p",[EntityBody]),
-% case verify_request(string:tokens(RequestLine," ")) of
-% ["HEAD", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N]] ->
-% {ok, ["HEAD", formatRequestUri(RequestURI), [$H,$T,$T,$P,$/,$1,$.,N], RequestLine,
-% ParsedHeader, EntityBody]};
-% ["GET", RequestURI, "HTTP/0.9"] ->
-% {ok, ["GET", RequestURI, "HTTP/0.9", RequestLine, ParsedHeader,
-% EntityBody]};
-% ["GET", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N]] ->
-% {ok, ["GET", formatRequestUri(RequestURI), [$H,$T,$T,$P,$/,$1,$.,N], RequestLine,
-% ParsedHeader,EntityBody]};
-%% ["POST", RequestURI, [$H,$T,$T,$P,$/,$1,$.,N]] ->
-% {ok, ["POST", formatRequestUri(RequestURI), [$H,$T,$T,$P,$/,$1,$.,N], RequestLine,
-% ParsedHeader, EntityBody]};
-% [Method, RequestURI] ->
-% {not_implemented, RequestLine, Method, RequestURI,ParsedHeader,"HTTP/0.9"};
-% [Method, RequestURI, HTTPVersion] ->
-% {not_implemented, RequestLine, Method, RequestURI,ParsedHeader, HTTPVersion};
-% {bad_request, Reason} ->
-% {bad_request, Reason};
-% Reason ->
-% {bad_request, "Unknown request method"}
-% end.
-
-hsplit(Accu,[]) ->
- {lists:reverse(Accu), []};
-hsplit(Accu, [ $\r, $\n, $\r, $\n | Tail]) ->
- {lists:reverse(Accu), Tail};
-hsplit(Accu, [H|T]) ->
- hsplit([H|Accu],T).
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_request_handler.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_request_handler.erl
deleted file mode 100644
index 5008e6022e..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_request_handler.erl
+++ /dev/null
@@ -1,995 +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: httpd_request_handler.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
-%%
--module(httpd_request_handler).
-
-%% app internal api
--export([start_link/2, synchronize/3]).
-
-%% module internal api
--export([connection/2, do_next_connection/6, read_header/7]).
--export([parse_trailers/1, newline/1]).
-
--include("httpd.hrl").
--include("httpd_verbosity.hrl").
-
-
-%% start_link
-
-start_link(Manager, ConfigDB) ->
- Pid = proc_lib:spawn(?MODULE, connection, [Manager, ConfigDB]),
- {ok, Pid}.
-
-
-%% synchronize
-
-synchronize(Pid, SocketType, Socket) ->
- Pid ! {synchronize, SocketType, Socket}.
-
-% connection
-
-connection(Manager, ConfigDB) ->
- {SocketType, Socket, {Status, Verbosity}} = await_synchronize(Manager),
- put(sname,self()),
- put(verbosity,?vvalidate(Verbosity)),
- connection1(Status, Manager, ConfigDB, SocketType, Socket).
-
-
-connection1({reject, busy}, Manager, ConfigDB, SocketType, Socket) ->
- handle_busy(Manager, ConfigDB, SocketType, Socket);
-
-connection1({reject, blocked}, Manager, ConfigDB, SocketType, Socket) ->
- handle_blocked(Manager, ConfigDB, SocketType, Socket);
-
-connection1(accept, Manager, ConfigDB, SocketType, Socket) ->
- handle_connection(Manager, ConfigDB, SocketType, Socket).
-
-
-%% await_synchronize
-
-await_synchronize(Manager) ->
- receive
- {synchronize, SocketType, Socket} ->
- ?vlog("received syncronize: "
- "~n SocketType: ~p"
- "~n Socket: ~p", [SocketType, Socket]),
- {SocketType, Socket, httpd_manager:new_connection(Manager)}
- after 5000 ->
- exit(synchronize_timeout)
- end.
-
-
-% handle_busy
-
-handle_busy(Manager, ConfigDB, SocketType, Socket) ->
- ?vlog("handle busy: ~p", [Socket]),
- MaxClients = httpd_util:lookup(ConfigDB, max_clients, 150),
- String = io_lib:format("heavy load (>~w processes)", [MaxClients]),
- reject_connection(Manager, ConfigDB, SocketType, Socket, String).
-
-
-% handle_blocked
-
-handle_blocked(Manager, ConfigDB, SocketType, Socket) ->
- ?vlog("handle blocked: ~p", [Socket]),
- String = "Server maintenance performed, try again later",
- reject_connection(Manager, ConfigDB, SocketType, Socket, String).
-
-
-% reject_connection
-
-reject_connection(Manager, ConfigDB, SocketType, Socket, Info) ->
- String = lists:flatten(Info),
- ?vtrace("send status (503) message", []),
- httpd_response:send_status(SocketType, Socket, 503, String, ConfigDB),
- %% This ugly thing is to make ssl deliver the message, before the close...
- close_sleep(SocketType, 1000),
- ?vtrace("close the socket", []),
- close(SocketType, Socket, ConfigDB).
-
-
-% handle_connection
-
-handle_connection(Manager, ConfigDB, SocketType, Socket) ->
- ?vlog("handle connection: ~p", [Socket]),
- Resolve = httpd_socket:resolve(SocketType),
- Peername = httpd_socket:peername(SocketType, Socket),
- InitData = #init_data{peername=Peername, resolve=Resolve},
- TimeOut = httpd_util:lookup(ConfigDB, keep_alive_timeout, 150000),
- NrOfRequest = httpd_util:lookup(ConfigDB, max_keep_alive_request, forever),
- ?MODULE:do_next_connection(ConfigDB, InitData,
- SocketType, Socket,NrOfRequest,TimeOut),
- ?vlog("handle connection: done", []),
- httpd_manager:done_connection(Manager),
- ?vlog("handle connection: close socket", []),
- close(SocketType, Socket, ConfigDB).
-
-
-% do_next_connection
-do_next_connection(_ConfigDB, _InitData, _SocketType, _Socket, NrOfRequests,
- _Timeout) when NrOfRequests < 1 ->
- ?vtrace("do_next_connection: done", []),
- ok;
-do_next_connection(ConfigDB, InitData, SocketType, Socket, NrOfRequests,
- Timeout) ->
- Peername = InitData#init_data.peername,
- case (catch read(ConfigDB, SocketType, Socket, InitData, Timeout)) of
- {'EXIT', Reason} ->
- ?vlog("exit reading from socket: ~p",[Reason]),
- error_logger:error_report({'EXIT',Reason}),
- String =
- lists:flatten(
- io_lib:format("exit reading from socket: ~p => ~n~p~n",
- [Socket, Reason])),
- error_log(mod_log,
- SocketType, Socket, ConfigDB, Peername, String),
- error_log(mod_disk_log,
- SocketType, Socket, ConfigDB, Peername, String);
- {error, Reason} ->
- handle_read_error(Reason,SocketType,Socket,ConfigDB,Peername);
- Info when record(Info, mod) ->
- case Info#mod.connection of
- true ->
- ReqTimeout = httpd_util:lookup(ConfigDB,
- keep_alive_timeout, 150000),
- ?MODULE:do_next_connection(ConfigDB, InitData,
- SocketType, Socket,
- dec(NrOfRequests), ReqTimeout);
- _ ->
- ok
- end;
- _ ->
- ok
- end.
-
-
-
-%% read
-read(ConfigDB, SocketType, Socket, InitData, Timeout) ->
- ?vdebug("read from socket ~p with Timeout ~p",[Socket, Timeout]),
- MaxHdrSz = httpd_util:lookup(ConfigDB, max_header_size, 10240),
- case ?MODULE:read_header(SocketType, Socket, Timeout, MaxHdrSz,
- ConfigDB, InitData, []) of
- {socket_closed, Reason} ->
- ?vlog("Socket closed while reading request header: "
- "~n ~p", [Reason]),
- socket_close;
- {error, Error} ->
- {error, Error};
- {ok, Info, EntityBodyPart} ->
- read1(SocketType, Socket, ConfigDB, InitData, Timeout, Info,
- EntityBodyPart)
- end.
-
-%% Got the head and maybe a part of the body: read in the rest
-read1(SocketType, Socket, ConfigDB, InitData, Timeout, Info, BodyPart)->
- MaxBodySz = httpd_util:lookup(ConfigDB, max_body_size, nolimit),
- ContentLength = content_length(Info),
- ?vtrace("ContentLength: ~p", [ContentLength]),
- case read_entity_body(SocketType, Socket, Timeout, MaxBodySz,
- ContentLength, BodyPart, Info, ConfigDB) of
- {socket_closed, Reason} ->
- ?vlog("Socket closed while reading request body: "
- "~n ~p", [Reason]),
- socket_close;
- {ok, EntityBody} ->
- finish_request(EntityBody, [], Info);
- {ok, ExtraHeader, EntityBody} ->
- finish_request(EntityBody, ExtraHeader, Info);
- Response ->
- httpd_socket:close(SocketType, Socket),
- socket_closed
- %% Catch up all bad return values
- end.
-
-
-%% The request is read in send it forward to the module that
-%% generates the response
-
-finish_request(EntityBody, ExtraHeader,
- #mod{parsed_header = ParsedHeader} = Info)->
- ?DEBUG("finish_request -> ~n"
- " EntityBody: ~p~n"
- " ExtraHeader: ~p~n"
- " ParsedHeader: ~p~n",
- [EntityBody, ExtraHeader, ParsedHeader]),
- httpd_response:send(Info#mod{parsed_header = ParsedHeader ++ ExtraHeader,
- entity_body = EntityBody}).
-
-
-%% read_header
-
-%% This algorithm rely on the buffer size of the inet driver together
-%% with the {active, once} socket option. Atmost one message of this
-%% size will be received at a given time. When a full header has been
-%% read, the body is read with the recv function (the body size is known).
-%%
-read_header(SocketType, Socket, Timeout, MaxHdrSz, ConfigDB,
- InitData, SoFar0) ->
- T = t(),
- %% remove any newlines at the begining, they might be crap from ?
- SoFar = remove_newline(SoFar0),
-
- case terminated_header(MaxHdrSz, SoFar) of
- {true, Header, EntityBodyPart} ->
- ?vdebug("read_header -> done reading header: "
- "~n length(Header): ~p"
- "~n length(EntityBodyPart): ~p",
- [length(Header), length(EntityBodyPart)]),
- transform_header(SocketType, Socket, Header, ConfigDB, InitData,
- EntityBodyPart);
- false ->
- ?vtrace("read_header -> "
- "~n set active = 'once' and "
- "await a chunk of the header", []),
-
- case httpd_socket:active_once(SocketType, Socket) of
- ok ->
- receive
- %%
- %% TCP
- %%
- {tcp, Socket, Data} ->
- ?vtrace("read_header(ip) -> got some data: ~p",
- [sz(Data)]),
- ?MODULE:read_header(SocketType, Socket,
- Timeout - (t()-T),
- MaxHdrSz, ConfigDB,
- InitData, SoFar ++ Data);
- {tcp_closed, Socket} ->
- ?vtrace("read_header(ip) -> socket closed",[]),
- {socket_closed,normal};
- {tcp_error, Socket, Reason} ->
- ?vtrace("read_header(ip) -> socket error: ~p",
- [Reason]),
- {socket_closed, Reason};
-
- %%
- %% SSL
- %%
- {ssl, Socket, Data} ->
- ?vtrace("read_header(ssl) -> got some data: ~p",
- [sz(Data)]),
- ?MODULE:read_header(SocketType, Socket,
- Timeout - (t()-T),
- MaxHdrSz, ConfigDB,
- InitData, SoFar ++ Data);
- {ssl_closed, Socket} ->
- ?vtrace("read_header(ssl) -> socket closed", []),
- {socket_closed, normal};
- {ssl_error, Socket, Reason} ->
- ?vtrace("read_header(ssl) -> socket error: ~p",
- [Reason]),
- {socket_closed, Reason}
-
- after Timeout ->
- ?vlog("read_header -> timeout", []),
- {socket_closed, timeout}
- end;
-
- Error ->
- httpd_response:send_status(SocketType, Socket,
- 500, none, ConfigDB),
- Error
- end
- end.
-
-
-terminated_header(MaxHdrSz, Data) ->
- D1 = lists:flatten(Data),
- ?vtrace("terminated_header -> Data size: ~p",[sz(D1)]),
- case hsplit(MaxHdrSz,[],D1) of
- not_terminated ->
- false;
- [Header, EntityBodyPart] ->
- {true, Header++"\r\n\r\n",EntityBodyPart}
- end.
-
-
-transform_header(SocketType, Socket, Request, ConfigDB, InitData, BodyPart) ->
- case httpd_parse:request_header(Request) of
- {not_implemented, RequestLine, Method, RequestURI, ParsedHeader,
- HTTPVersion} ->
- httpd_response:send_status(SocketType, Socket, 501,
- {Method, RequestURI, HTTPVersion},
- ConfigDB),
- {error,"Not Implemented"};
- {bad_request, {forbidden, URI}} ->
- httpd_response:send_status(SocketType, Socket, 403, URI, ConfigDB),
- {error,"Forbidden Request"};
- {bad_request, Reason} ->
- httpd_response:send_status(SocketType, Socket, 400, none,
- ConfigDB),
- {error,"Malformed request"};
- {ok,[Method, RequestURI, HTTPVersion, RequestLine, ParsedHeader]} ->
- ?DEBUG("send -> ~n"
- " Method: ~p~n"
- " RequestURI: ~p~n"
- " HTTPVersion: ~p~n"
- " RequestLine: ~p~n",
- [Method, RequestURI, HTTPVersion, RequestLine]),
- {ok, Info} =
- httpd_parse:get_request_record(Socket, SocketType, ConfigDB,
- Method, RequestURI, HTTPVersion,
- RequestLine, ParsedHeader,
- [], InitData),
- %% Control that the Host header field is provided
- case Info#mod.absolute_uri of
- nohost ->
- case Info#mod.http_version of
- "HTTP/1.1" ->
- httpd_response:send_status(Info, 400, none),
- {error,"No host specified"};
- _ ->
- {ok, Info, BodyPart}
- end;
- _ ->
- {ok, Info, BodyPart}
- end
- end.
-
-
-hsplit(_MaxHdrSz, Accu,[]) ->
- not_terminated;
-hsplit(_MaxHdrSz, Accu, [ $\r, $\n, $\r, $\n | Tail]) ->
- [lists:reverse(Accu), Tail];
-hsplit(nolimit, Accu, [H|T]) ->
- hsplit(nolimit,[H|Accu],T);
-hsplit(MaxHdrSz, Accu, [H|T]) when length(Accu) < MaxHdrSz ->
- hsplit(MaxHdrSz,[H|Accu],T);
-hsplit(MaxHdrSz, Accu, D) ->
- throw({error,{header_too_long,length(Accu),length(D)}}).
-
-
-
-%%----------------------------------------------------------------------
-%% The http/1.1 standard chapter 8.2.3 says that a request containing
-%% An Except header-field must be responded to by 100 (Continue) by
-%% the server before the client sends the body.
-%%----------------------------------------------------------------------
-
-read_entity_body(SocketType, Socket, Timeout, Max, Length, BodyPart, Info,
- ConfigDB) when integer(Max) ->
- case expect(Info#mod.http_version, Info#mod.parsed_header, ConfigDB) of
- continue when Max > Length ->
- ?DEBUG("read_entity_body()->100 Continue ~n", []),
- httpd_response:send_status(Info, 100, ""),
- read_entity_body2(SocketType, Socket, Timeout, Max, Length,
- BodyPart, Info, ConfigDB);
- continue when Max < Length ->
- httpd_response:send_status(Info, 417, "Body to big"),
- httpd_socket:close(SocketType, Socket),
- {socket_closed,"Expect denied according to size"};
- break ->
- httpd_response:send_status(Info, 417, "Method not allowed"),
- httpd_socket:close(SocketType, Socket),
- {socket_closed,"Expect conditions was not fullfilled"};
- no_expect_header ->
- read_entity_body2(SocketType, Socket, Timeout, Max, Length,
- BodyPart, Info, ConfigDB);
- http_1_0_expect_header ->
- httpd_response:send_status(Info, 400,
- "Only HTTP/1.1 Clients "
- "may use the Expect Header"),
- httpd_socket:close(SocketType, Socket),
- {socket_closed,"Due to a HTTP/1.0 expect header"}
- end;
-
-read_entity_body(SocketType, Socket, Timeout, Max, Length, BodyPart,
- Info, ConfigDB) ->
- case expect(Info#mod.http_version, Info#mod.parsed_header, ConfigDB) of
- continue ->
- ?DEBUG("read_entity_body() -> 100 Continue ~n", []),
- httpd_response:send_status(Info, 100, ""),
- read_entity_body2(SocketType, Socket, Timeout, Max, Length,
- BodyPart, Info, ConfigDB);
- break->
- httpd_response:send_status(Info, 417, "Method not allowed"),
- httpd_socket:close(SocketType, Socket),
- {socket_closed,"Expect conditions was not fullfilled"};
- no_expect_header ->
- read_entity_body2(SocketType, Socket, Timeout, Max, Length,
- BodyPart, Info, ConfigDB);
- http_1_0_expect_header ->
- httpd_response:send_status(Info, 400,
- "HTTP/1.0 Clients are not allowed "
- "to use the Expect Header"),
- httpd_socket:close(SocketType, Socket),
- {socket_closed,"Expect header field in an HTTP/1.0 request"}
- end.
-
-%%----------------------------------------------------------------------
-%% control if the body is transfer encoded
-%%----------------------------------------------------------------------
-read_entity_body2(SocketType, Socket, Timeout, Max, Length, BodyPart,
- Info, ConfigDB) ->
- ?DEBUG("read_entity_body2() -> "
- "~n Max: ~p"
- "~n Length: ~p"
- "~n Socket: ~p", [Max, Length, Socket]),
-
- case transfer_coding(Info) of
- {chunked, ChunkedData} ->
- ?DEBUG("read_entity_body2() -> "
- "Transfer-encoding: Chunked Data: BodyPart ~s", [BodyPart]),
- read_chunked_entity(Info, Timeout, Max, Length, ChunkedData, [],
- BodyPart);
- unknown_coding ->
- ?DEBUG("read_entity_body2() -> Transfer-encoding: Unknown",[]),
- httpd_response:send_status(Info, 501, "Unknown Transfer-Encoding"),
- httpd_socket:close(SocketType, Socket),
- {socket_closed,"Expect conditions was not fullfilled"};
- none ->
- ?DEBUG("read_entity_body2() -> Transfer-encoding: none",[]),
- read_entity_body(SocketType, Socket, Timeout, Max, Length,
- BodyPart)
- end.
-
-
-%%----------------------------------------------------------------------
-%% The body was plain read it from the socket
-%% ----------------------------------------------------------------------
-read_entity_body(_SocketType, _Socket, _Timeout, _Max, 0, _BodyPart) ->
- {ok, []};
-
-read_entity_body(_SocketType, _Socket, _Timeout, Max, Len, _BodyPart)
- when Max < Len ->
- ?vlog("body to long: "
- "~n Max: ~p"
- "~n Len: ~p", [Max,Len]),
- throw({error,{body_too_long,Max,Len}});
-
-%% OTP-4409: Fixing POST problem
-read_entity_body(_,_,_,_, Len, BodyPart) when Len == length(BodyPart) ->
- ?vtrace("read_entity_body -> done when"
- "~n Len = length(BodyPart): ~p", [Len]),
- {ok, BodyPart};
-
-%% OTP-4550: Fix problem with trailing garbage produced by some clients.
-read_entity_body(_, _, _, _, Len, BodyPart) when Len < length(BodyPart) ->
- ?vtrace("read_entity_body -> done when"
- "~n Len: ~p"
- "~n length(BodyPart): ~p", [Len, length(BodyPart)]),
- {ok, lists:sublist(BodyPart,Len)};
-
-read_entity_body(SocketType, Socket, Timeout, Max, Len, BodyPart) ->
- ?vtrace("read_entity_body -> entry when"
- "~n Len: ~p"
- "~n length(BodyPart): ~p", [Len, length(BodyPart)]),
- %% OTP-4548:
- %% The length calculation was previously (inets-2.*) done in the
- %% read function. As of 3.0 it was removed from read but not
- %% included here.
- L = Len - length(BodyPart),
- case httpd_socket:recv(SocketType, Socket, L, Timeout) of
- {ok, Body} ->
- ?vtrace("read_entity_body -> received some data:"
- "~n length(Body): ~p", [length(Body)]),
- {ok, BodyPart ++ Body};
- {error,closed} ->
- {socket_closed,normal};
- {error,etimedout} ->
- {socket_closed, timeout};
- {error,Reason} ->
- {socket_closed, Reason};
- Other ->
- {socket_closed, Other}
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% If the body of the message is encoded used the chunked transfer encoding
-%% it looks somethin like this:
-%% METHOD URI HTTP/VSN
-%% Transfer-Encoding: chunked
-%% CRLF
-%% ChunkSize
-%% Chunk
-%% ChunkSize
-%% Chunk
-%% 0
-%% Trailer
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-read_chunked_entity(Info, Timeout, Max, Length, ChunkedData, Body, []) ->
- ?DEBUG("read_chunked_entity()->:no_chunks ~n", []),
- read_chunked_entity(Info#mod.socket_type, Info#mod.socket,
- Timeout, Max, Length, ChunkedData, Body,
- Info#mod.config_db, Info);
-
-read_chunked_entity(Info, Timeout, Max, Length, ChunkedData, Body, BodyPart) ->
- %% Get the size
- ?DEBUG("read_chunked_entity() -> PrefetchedBodyPart: ~p ~n",[BodyPart]),
- case parse_chunk_size(Info, Timeout, BodyPart) of
- {ok, Size, NewBodyPart} when Size > 0 ->
- ?DEBUG("read_chunked_entity() -> Size: ~p ~n", [Size]),
- case parse_chunked_entity_body(Info, Timeout, Max, length(Body),
- Size, NewBodyPart) of
- {ok, Chunk, NewBodyPart1} ->
- ?DEBUG("read_chunked_entity()->Size: ~p ~n", [Size]),
- read_chunked_entity(Info, Timeout, Max, Length,
- ChunkedData, Body ++ Chunk,
- NewBodyPart1);
- OK ->
- httpd_socket:close(Info#mod.socket_type, Info#mod.socket),
- {socket_closed, error}
- end;
- {ok, 0, Trailers} ->
- ?DEBUG("read_chunked_entity()->Size: 0, Trailers: ~s Body: ~s ~n",
- [Trailers, Body]),
- case parse_chunk_trailer(Info, Timeout, Info#mod.config_db,
- Trailers) of
- {ok, TrailerFields} ->
- {ok, TrailerFields, Body};
- _->
- {ok, []}
- end;
- Error ->
- Error
- end.
-
-
-parse_chunk_size(Info, Timeout, BodyPart) ->
- case httpd_util:split(remove_newline(BodyPart), "\r\n", 2) of
- {ok, [Size, Body]} ->
- ?DEBUG("parse_chunk_size()->Size: ~p ~n", [Size]),
- {ok, httpd_util:hexlist_to_integer(Size), Body};
- {ok, [Size]} ->
- ?DEBUG("parse_chunk_size()->Size: ~p ~n", [Size]),
- Sz = get_chunk_size(Info#mod.socket_type,
- Info#mod.socket, Timeout,
- lists:reverse(Size)),
- {ok, Sz, []}
- end.
-
-%%----------------------------------------------------------------------
-%% We got the chunk size get the chunk
-%%
-%% Max: Max numbers of bytes to read may also be undefined
-%% Length: Numbers of bytes already read
-%% Size Numbers of byte to read for the chunk
-%%----------------------------------------------------------------------
-
-%% body to big
-parse_chunked_entity_body(Info, Timeout, Max, Length, Size, BodyPart)
- when Max =< (Length + Size) ->
- {error, body_to_big};
-
-%% Prefetched body part is bigger than the current chunk
-%% (i.e. BodyPart includes more than one chunk)
-parse_chunked_entity_body(Info, Timeout, Max, Length, Size, BodyPart)
- when (Size+2) =< length(BodyPart) ->
- Chunk = string:substr(BodyPart, 1, Size),
- Rest = string:substr(BodyPart, Size+3),
- ?DEBUG("parse_chunked_entity_body() -> ~nChunk: ~s ~nRest: ~s ~n",
- [Chunk, Rest]),
- {ok, Chunk, Rest};
-
-
-%% We just got a part of the current chunk
-parse_chunked_entity_body(Info, Timeout, Max, Length, Size, BodyPart) ->
- %% OTP-4551:
- %% Subtracting BodyPart from Size does not produce an integer
- %% when BodyPart is a list...
- Remaining = Size - length(BodyPart),
- LastPartOfChunk = read_chunked_entity_body(Info#mod.socket_type,
- Info#mod.socket,
- Timeout, Max,
- Length, Remaining),
- %% Remove newline
- httpd_socket:recv(Info#mod.socket_type, Info#mod.socket, 2, Timeout),
- ?DEBUG("parse_chunked_entity_body() -> "
- "~nBodyPart: ~s"
- "~nLastPartOfChunk: ~s ~n",
- [BodyPart, LastPartOfChunk]),
- {ok, BodyPart ++ LastPartOfChunk, []}.
-
-
-%%----------------------------------------------------------------------
-%% If the data we got along with the header contained the whole chunked body
-%% It may aswell contain the trailer :-(
-%%----------------------------------------------------------------------
-%% Either trailer begins with \r\n and then all data is there or
-%% The trailer has data then read upto \r\n\r\n
-parse_chunk_trailer(Info,Timeout,ConfigDB,"\r\n")->
- {ok,[]};
-parse_chunk_trailer(Info,Timeout,ConfigDB,Trailers) ->
- ?DEBUG("parse_chunk_trailer()->Trailers: ~s ~n", [Trailers]),
- case string:rstr(Trailers,"\r\n\r\n") of
- 0 ->
- MaxHdrSz=httpd_util:lookup(ConfigDB, max_header_size, 10240),
- read_trailer_end(Info,Timeout,MaxHdrSz,Trailers);
- _->
- %%We got the whole header parse it up
- parse_trailers(Trailers)
- end.
-
-parse_trailers(Trailer)->
- ?DEBUG("parse_trailer()->Trailer: ~s",[Trailer]),
- {ok,[Fields0|Crap]}=httpd_util:split(Trailer,"\r\n\r\n",2),
- Fields=string:tokens(Fields0,"\r\n"),
- [getTrailerField(X)||X<-Fields,lists:member($:,X)].
-
-
-read_trailer_end(Info,Timeout,MaxHdrSz,[])->
- ?DEBUG("read_trailer_end()->[]",[]),
- case read_trailer(Info#mod.socket_type,Info#mod.socket,
- Timeout,MaxHdrSz,[],[],
- httpd_util:key1search(Info#mod.parsed_header,"trailer",[])) of
- {ok,Trailers}->
- Trailers;
- _->
- []
- end;
-read_trailer_end(Info,Timeout,MaxHdrSz,Trailers)->
- ?DEBUG("read_trailer_end()->Trailers: ~s ~n ",[Trailers]),
- %% Get the last paart of the the last headerfield
- End=lists:reverse(lists:takewhile(fun(X)->case X of 10 ->false;13->false;_ ->true end end,lists:reverse(Trailers))),
- Fields0=regexp:split(Trailers,"\r\n"),
- %%Get rid of the last header field
- [_Last|Fields]=lists:reverse(Fields0),
- Headers=[getTrailerField(X)||X<-Fields,lists:member($:,X)],
- case read_trailer(Info#mod.socket_type,Info#mod.socket,
- Timeout,MaxHdrSz,Headers,End,
- httpd_util:key1search(Info#mod.parsed_header,"trailer",[])) of
- {ok,Trailers}->
- Trailers;
- _->
- []
- end.
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% The code below is a a good way to read in chunked encoding but
-%% that require that the encoding comes from a stream and not from a list
-%%&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-
-%%----------------------------------------------------------------------
-%% The body is encoded by chubnked encoding read it in
-%% ChunkedData= Chunked extensions
-%% Body= the inread chunked body
-%% Max: Max numbers of bytes to read
-%% Length: Numbers of bytes already readed
-%% Size Numbers of byte to read for the chunk
-%%----------------------------------------------------------------------
-
-
-
-read_chunked_entity(SocketType, Socket, Timeout, Max, Length, ChunkedData,
- Body, ConfigDB, Info) ->
- T = t(),
- case get_chunk_size(SocketType,Socket,Timeout,[]) of
- Size when integer(Size), Size>0 ->
- case read_chunked_entity_body(SocketType, Socket,
- Timeout-(t()-T),
- Max, length(Body), Size) of
- {ok,Chunk} ->
- ?DEBUG("read_chunked_entity/9 Got a chunk: ~p " ,[Chunk]),
- %% Two bytes are left of the chunk, that is the CRLF
- %% at the end that is not a part of the message
- %% So we read it and do nothing with it.
- httpd_socket:recv(SocketType,Socket,2,Timeout-(t()-T)),
- read_chunked_entity(SocketType, Socket, Timeout-(t()-T),
- Max, Length, ChunkedData, Body++Chunk,
- ConfigDB, Info);
- Error ->
- ?DEBUG("read_chunked_entity/9 Error: ~p " ,[Error]),
- httpd_socket:close(SocketType,Socket),
- {socket_closed,error}
- end;
- Size when integer(Size), Size == 0 ->
- %% Must read in any trailer fields here
- read_chunk_trailer(SocketType, Socket, Timeout,
- Max, Info, ChunkedData, Body, ConfigDB);
- Error ->
- Error
- end.
-
-
-%% If a user wants to send header data after the chunked data we
-%% must pick it out
-read_chunk_trailer(SocketType, Socket, Timeout, Max, Info, ChunkedData,
- Body, ConfigDB) ->
- ?DEBUG("read_chunk_trailer/8: ~p " ,[Body]),
- MaxHdrSz = httpd_util:lookup(ConfigDB,max_header_size,10240),
- case httpd_util:key1search(Info#mod.parsed_header,"trailer")of
- undefined ->
- {ok,Body};
- Fields ->
- case read_trailer(SocketType, Socket, Timeout,
- MaxHdrSz, [], [],
- string:tokens(
- httpd_util:to_lower(Fields),",")) of
- {ok,[]} ->
- {ok,Body};
- {ok,HeaderFields} ->
- % ParsedExtraHeaders =
- % httpd_parse:tagup_header(httpd_parse:split_lines(HeaderFields)),
- {ok,HeaderFields,Body};
- Error ->
- Error
- end
- end.
-
-read_chunked_entity_body(SocketType, Socket, Timeout, Max, Length, Size)
- when integer(Max) ->
- read_entity_body(SocketType, Socket, Timeout, Max-Length, Size, []);
-
-read_chunked_entity_body(SocketType, Socket, Timeout, Max, _Length, Size) ->
- read_entity_body(SocketType, Socket, Timeout, Max, Size, []).
-
-%% If we read in the \r\n the httpd_util:hexlist_to_integer
-%% Will remove it and we get rid of it emmediatly :-)
-get_chunk_size(SocketType, Socket, Timeout, Size) ->
- T = t(),
- ?DEBUG("get_chunk_size: ~p " ,[Size]),
- case httpd_socket:recv(SocketType,Socket,1,Timeout) of
- {ok,[Digit]} when Digit==$\n ->
- httpd_util:hexlist_to_integer(lists:reverse(Size));
- {ok,[Digit]} ->
- get_chunk_size(SocketType,Socket,Timeout-(t()-T),[Digit|Size]);
- {error,closed} ->
- {socket_closed,normal};
- {error,etimedout} ->
- {socket_closed, timeout};
- {error,Reason} ->
- {socket_closed, Reason};
- Other ->
- {socket_closed,Other}
- end.
-
-
-
-
-%%----------------------------------------------------------------------
-%% Reads the HTTP-trailer
-%% Would be easy to tweak the read_head to do this but in this way
-%% the chunked encoding can be updated better.
-%%----------------------------------------------------------------------
-
-
-%% When end is reached
-%% read_trailer(SocketType,Socket,Timeout,MaxHdrSz,Headers,Last,[]) ->
-%% {ok,Headers};
-
-%% When header to big
-read_trailer(_,_,_,MaxHdrSz,Headers,Bs,_Fields)
- when MaxHdrSz < length(Headers) ->
- ?vlog("header to long: "
- "~n MaxHdrSz: ~p"
- "~n length(Bs): ~p", [MaxHdrSz,length(Bs)]),
- throw({error,{header_too_long,MaxHdrSz,length(Bs)}});
-
-%% The last Crlf is there
-read_trailer(_, _, _, _, Headers, [$\n, $\r], _) ->
- {ok,Headers};
-
-read_trailer(SocketType, Socket, Timeout, MaxHdrSz, Headers,
- [$\n, $\r|Rest], Fields) ->
- case getTrailerField(lists:reverse(Rest))of
- {error,Reason}->
- {error,"Bad trailer"};
- {HeaderField,Value}->
- case lists:member(HeaderField,Fields) of
- true ->
- read_trailer(SocketType,Socket,Timeout,MaxHdrSz,
- [{HeaderField,Value} |Headers],[],
- lists:delete(HeaderField,Fields));
- false ->
- read_trailer(SocketType,Socket,Timeout,MaxHdrSz,
- Headers,[],Fields)
- end
- end;
-
-% read_trailer(SocketType,Socket,Timeout,MaxHdrSz,Headers,[$\n, $\r|Rest],Fields) ->
-% case Rest of
-% [] ->
-% read_trailer(SocketType,Socket,Timeout,MaxHdrSz,Headers,Rest,Fields);
-% Field ->
-% case getTrailerField(lists:reverse(Rest))of
-% {error,Reason}->
-% {error,"Bad trailer"};
-% {HeaderField,Value}->
-% case lists:member(HeaderField,Fields) of
-% true ->
-% read_trailer(SocketType,Socket,Timeout,MaxHdrSz,
-% [{HeaderField,Value} |Headers],[],
-% lists:delete(HeaderField,Fields));
-% false ->
-% read_trailer(SocketType,Socket,Timeout,MaxHdrSz,
-% Headers,[],Fields)
-% end
-% end
-% end;
-
-read_trailer(SocketType,Socket,Timeout,MaxHdrSz,Headers,Bs,Fields) ->
- %% ?vlog("read_header -> entry with Timeout: ~p",[Timeout]),
- T = t(),
- case (catch httpd_socket:recv(SocketType,Socket,1,Timeout)) of
- {ok,[B]} ->
- read_trailer(SocketType, Socket, Timeout-(t()-T),
- MaxHdrSz, Headers, [B|Bs], Fields);
- {error,closed} ->
- {socket_closed,normal};
- {error,etimedout} ->
- {socket_closed, timeout};
- {error,Reason} ->
- {socket_closed, Reason};
- Other ->
- {socket_closed,Other}
- end.
-
-getTrailerField(HeaderField)->
- case string:str(HeaderField,":") of
- 0->
- {error,"badheaderfield"};
- Number ->
- {httpd_util:to_lower(string:substr(HeaderField,1,Number-1)),
- httpd_util:to_lower(string:substr(HeaderField,Number+1))}
- end.
-
-
-
-
-%% Time in milli seconds
-t() ->
- {A,B,C} = erlang:now(),
- A*1000000000+B*1000+(C div 1000).
-
-%%----------------------------------------------------------------------
-%% If the user sends an expect header-field with the value 100-continue
-%% We must send a 100 status message if he is a HTTP/1.1 client.
-
-%% If it is an HTTP/1.0 client it's little more difficult.
-%% If expect is not defined it is easy but in the other case shall we
-%% Break or the transmission or let it continue the standard is not clear
-%% if to break connection or wait for data.
-%%----------------------------------------------------------------------
-expect(HTTPVersion,ParsedHeader,ConfigDB)->
- case HTTPVersion of
- [$H,$T,$T,$P,$\/,$1,$.,N|_Whatever]when N>=1->
- case httpd_util:key1search(ParsedHeader,"expect") of
- "100-continue" ->
- continue;
- undefined ->
- no_expect_header;
- NewValue ->
- break
- end;
- _OldVersion ->
- case httpd_util:key1search(ParsedHeader,"expect") of
- undefined ->
- no_expect_header;
- NewValue ->
- case httpd_util:lookup(ConfigDB,expect,continue) of
- continue->
- no_expect_header;
- _ ->
- http_1_0_expect_header
- end
- end
- end.
-
-
-%%----------------------------------------------------------------------
-%% According to the http/1.1 standard all applications must understand
-%% Chunked encoded data. (Last line chapter 3.6.1).
-transfer_coding(#mod{parsed_header = Ph}) ->
- case httpd_util:key1search(Ph, "transfer-encoding", none) of
- none ->
- none;
- [$c,$h,$u,$n,$k,$e,$d|Data]->
- {chunked,Data};
- _ ->
- unknown_coding
- end.
-
-
-
-handle_read_error({header_too_long,Max,Rem},
- SocketType,Socket,ConfigDB,Peername) ->
- String = io_lib:format("header too long: ~p : ~p",[Max,Rem]),
- handle_read_error(ConfigDB,String,SocketType,Socket,Peername,
- max_header_action,close);
-handle_read_error({body_too_long,Max,Actual},
- SocketType,Socket,ConfigDB,Peername) ->
- String = io_lib:format("body too long: ~p : ~p",[Max,Actual]),
- handle_read_error(ConfigDB,String,SocketType,Socket,Peername,
- max_body_action,close);
-handle_read_error(Error,SocketType,Socket,ConfigDB,Peername) ->
- ok.
-
-
-handle_read_error(ConfigDB, ReasonString, SocketType, Socket, Peername,
- Item, Default) ->
- ?vlog("error reading request: ~s",[ReasonString]),
- E = lists:flatten(
- io_lib:format("Error reading request: ~s",[ReasonString])),
- error_log(mod_log, SocketType, Socket, ConfigDB, Peername, E),
- error_log(mod_disk_log, SocketType, Socket, ConfigDB, Peername, E),
- case httpd_util:lookup(ConfigDB,Item,Default) of
- reply414 ->
- send_read_status(SocketType, Socket, 414, ReasonString, ConfigDB);
- _ ->
- ok
- end.
-
-send_read_status(SocketType, Socket, Code, ReasonString, ConfigDB) ->
- httpd_response:send_status(SocketType, Socket, Code, ReasonString,
- ConfigDB).
-
-
-error_log(Mod, SocketType, Socket, ConfigDB, Peername, String) ->
- Modules = httpd_util:lookup(ConfigDB, modules,
- [mod_get, mod_head, mod_log]),
- case lists:member(Mod, Modules) of
- true ->
- Mod:error_log(SocketType, Socket, ConfigDB, Peername, String);
- _ ->
- ok
- end.
-
-
-sz(L) when list(L) ->
- length(L);
-sz(B) when binary(B) ->
- size(B);
-sz(O) ->
- {unknown_size,O}.
-
-
-%% Socket utility functions:
-
-close(SocketType, Socket, ConfigDB) ->
- case httpd_socket:close(SocketType, Socket) of
- ok ->
- ok;
- {error, Reason} ->
- ?vlog("error while closing socket: ~p",[Reason]),
- ok
- end.
-
-close_sleep({ssl, _}, Time) ->
- sleep(Time);
-close_sleep(_, _) ->
- ok.
-
-
-sleep(T) -> receive after T -> ok end.
-
-
-dec(N) when integer(N) ->
- N-1;
-dec(N) ->
- N.
-
-
-content_length(#mod{parsed_header = Ph}) ->
- list_to_integer(httpd_util:key1search(Ph, "content-length","0")).
-
-
-remove_newline(List)->
- lists:dropwhile(fun newline/1,List).
-
-newline($\r) ->
- true;
-newline($\n) ->
- true;
-newline(_Sign) ->
- false.
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_response.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_response.erl
deleted file mode 100644
index 4c7f8e0c8f..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_response.erl
+++ /dev/null
@@ -1,437 +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: httpd_response.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
-%%
--module(httpd_response).
--export([send/1, send_status/3, send_status/5]).
-
-%%code is the key for the statuscode ex: 200 404 ...
--define(HTTP11HEADERFIELDS,[content_length, accept_ranges, cache_control, date,
- pragma, trailer, transfer_encoding, etag, location,
- retry_after, server, allow,
- content_encoding, content_language,
- content_location, content_MD5, content_range,
- content_type, expires, last_modified]).
-
--define(HTTP10HEADERFIELDS,[content_length, date, pragma, transfer_encoding,
- location, server, allow, content_encoding,
- content_type, last_modified]).
-
--define(PROCEED_RESPONSE(StatusCode, Info),
- {proceed,
- [{response,{already_sent, StatusCode,
- httpd_util:key1search(Info#mod.data,content_lenght)}}]}).
-
-
--include("httpd.hrl").
-
--define(VMODULE,"RESPONSE").
--include("httpd_verbosity.hrl").
-
-%% send
-
-send(#mod{config_db = ConfigDB} = Info) ->
- ?vtrace("send -> Request line: ~p", [Info#mod.request_line]),
- Modules = httpd_util:lookup(ConfigDB,modules,[mod_get, mod_head, mod_log]),
- case traverse_modules(Info, Modules) of
- done ->
- Info;
- {proceed, Data} ->
- case httpd_util:key1search(Data, status) of
- {StatusCode, PhraseArgs, Reason} ->
- ?vdebug("send -> proceed/status: ~n"
- "~n StatusCode: ~p"
- "~n PhraseArgs: ~p"
- "~n Reason: ~p",
- [StatusCode, PhraseArgs, Reason]),
- send_status(Info, StatusCode, PhraseArgs),
- Info;
-
- undefined ->
- case httpd_util:key1search(Data, response) of
- {already_sent, StatusCode, Size} ->
- ?vtrace("send -> already sent: "
- "~n StatusCode: ~p"
- "~n Size: ~p",
- [StatusCode, Size]),
- Info;
- {response, Header, Body} -> %% New way
- send_response(Info, Header, Body),
- Info;
- {StatusCode, Response} -> %% Old way
- send_response_old(Info, StatusCode, Response),
- Info;
- undefined ->
- ?vtrace("send -> undefined response", []),
- send_status(Info, 500, none),
- Info
- end
- end
- end.
-
-
-%% traverse_modules
-
-traverse_modules(Info,[]) ->
- {proceed,Info#mod.data};
-traverse_modules(Info,[Module|Rest]) ->
- case (catch apply(Module,do,[Info])) of
- {'EXIT', Reason} ->
- ?vlog("traverse_modules -> exit reason: ~p",[Reason]),
- String =
- lists:flatten(
- io_lib:format("traverse exit from apply: ~p:do => ~n~p",
- [Module, Reason])),
- report_error(mod_log, Info#mod.config_db, String),
- report_error(mod_disk_log, Info#mod.config_db, String),
- done;
- done ->
- done;
- {break,NewData} ->
- {proceed,NewData};
- {proceed,NewData} ->
- traverse_modules(Info#mod{data=NewData},Rest)
- end.
-
-%% send_status %%
-
-
-send_status(#mod{socket_type = SocketType,
- socket = Socket,
- connection = Conn} = Info, 100, _PhraseArgs) ->
- ?DEBUG("send_status -> StatusCode: ~p~n",[100]),
- Header = httpd_util:header(100, Conn),
- httpd_socket:deliver(SocketType, Socket,
- [Header, "Content-Length:0\r\n\r\n"]);
-
-send_status(#mod{socket_type = SocketType,
- socket = Socket,
- config_db = ConfigDB} = Info, StatusCode, PhraseArgs) ->
- send_status(SocketType, Socket, StatusCode, PhraseArgs, ConfigDB).
-
-send_status(SocketType, Socket, StatusCode, PhraseArgs, ConfigDB) ->
- ?DEBUG("send_status -> ~n"
- " StatusCode: ~p~n"
- " PhraseArgs: ~p",
- [StatusCode, PhraseArgs]),
- Header = httpd_util:header(StatusCode, "text/html", false),
- ReasonPhrase = httpd_util:reason_phrase(StatusCode),
- Message = httpd_util:message(StatusCode, PhraseArgs, ConfigDB),
- Body = get_body(ReasonPhrase, Message),
- Header1 =
- Header ++
- "Content-Length:" ++
- integer_to_list(length(Body)) ++
- "\r\n\r\n",
- httpd_socket:deliver(SocketType, Socket, [Header1, Body]).
-
-
-get_body(ReasonPhrase, Message)->
- "<HTML>
- <HEAD>
- <TITLE>"++ReasonPhrase++"</TITLE>
- </HEAD>
- <BODY>
- <H1>"++ReasonPhrase++"</H1>\n"++Message++"\n</BODY>
- </HTML>\n".
-
-
-%%% Create a response from the Key/Val tuples In the Head List
-%%% Body is a tuple {body,Fun(),Args}
-
-%% send_response
-%% Allowed Fields
-
-% HTTP-Version StatusCode Reason-Phrase
-% *((general-headers
-% response-headers
-% entity-headers)CRLF)
-% CRLF
-% ?(BODY)
-
-% General Header fields
-% ======================
-% Cache-Control cache_control
-% Connection %%Is set dependiong on the request
-% Date
-% Pramga
-% Trailer
-% Transfer-Encoding
-
-% Response Header field
-% =====================
-% Accept-Ranges
-% (Age) Mostly for proxys
-% Etag
-% Location
-% (Proxy-Authenticate) Only for proxies
-% Retry-After
-% Server
-% Vary
-% WWW-Authenticate
-%
-% Entity Header Fields
-% ====================
-% Allow
-% Content-Encoding
-% Content-Language
-% Content-Length
-% Content-Location
-% Content-MD5
-% Content-Range
-% Content-Type
-% Expires
-% Last-Modified
-
-
-send_response(Info, Header, Body) ->
- ?vtrace("send_response -> (new) entry with"
- "~n Header: ~p", [Header]),
- case httpd_util:key1search(Header, code) of
- undefined ->
- %% No status code
- %% Ooops this must be very bad:
- %% generate a 404 content not availible
- send_status(Info, 404, "The file is not availible");
- StatusCode ->
- case send_header(Info, StatusCode, Header) of
- ok ->
- send_body(Info, StatusCode, Body);
- Error ->
- ?vlog("head delivery failure: ~p", [Error]),
- done
- end
- end.
-
-
-send_header(#mod{socket_type = Type, socket = Sock,
- http_version = Ver, connection = Conn} = Info,
- StatusCode, Head0) ->
- ?vtrace("send_haeder -> entry with"
- "~n Ver: ~p"
- "~n Conn: ~p", [Ver, Conn]),
- Head1 = create_header(Ver, Head0),
- StatusLine = [Ver, " ",
- io_lib:write(StatusCode), " ",
- httpd_util:reason_phrase(StatusCode), "\r\n"],
- Connection = get_connection(Conn, Ver),
- Head = list_to_binary([StatusLine, Head1, Connection,"\r\n"]),
- ?vtrace("deliver head", []),
- httpd_socket:deliver(Type, Sock, Head).
-
-
-send_body(_, _, nobody) ->
- ?vtrace("send_body -> no body", []),
- ok;
-
-send_body(#mod{socket_type = Type, socket = Sock},
- StatusCode, Body) when list(Body) ->
- ?vtrace("deliver body of size ~p", [length(Body)]),
- httpd_socket:deliver(Type, Sock, Body);
-
-send_body(#mod{socket_type = Type, socket = Sock} = Info,
- StatusCode, {Fun, Args}) ->
- case (catch apply(Fun, Args)) of
- close ->
- httpd_socket:close(Type, Sock),
- done;
-
- sent ->
- ?PROCEED_RESPONSE(StatusCode, Info);
-
- {ok, Body} ->
- ?vtrace("deliver body", []),
- case httpd_socket:deliver(Type, Sock, Body) of
- ok ->
- ?PROCEED_RESPONSE(StatusCode, Info);
- Error ->
- ?vlog("body delivery failure: ~p", [Error]),
- done
- end;
-
- Error ->
- ?vlog("failure of apply(~p,~p): ~p", [Fun, Args, Error]),
- done
- end;
-send_body(I, S, B) ->
- ?vinfo("BAD ARGS: "
- "~n I: ~p"
- "~n S: ~p"
- "~n B: ~p", [I, S, B]),
- exit({bad_args, {I, S, B}}).
-
-
-%% Return a HTTP-header field that indicates that the
-%% connection will be inpersistent
-get_connection(true,"HTTP/1.0")->
- "Connection:close\r\n";
-get_connection(false,"HTTP/1.1") ->
- "Connection:close\r\n";
-get_connection(_,_) ->
- "".
-
-
-create_header("HTTP/1.1", Data) ->
- create_header1(?HTTP11HEADERFIELDS, Data);
-create_header(_, Data) ->
- create_header1(?HTTP10HEADERFIELDS, Data).
-
-create_header1(Fields, Data) ->
- ?DEBUG("create_header() -> "
- "~n Fields :~p~n Data: ~p ~n", [Fields, Data]),
- mapfilter(fun(Field)->
- transform({Field, httpd_util:key1search(Data, Field)})
- end, Fields, undefined).
-
-
-%% Do a map and removes the values that evaluates to RemoveVal
-mapfilter(Fun,List,RemoveVal)->
- mapfilter(Fun,List,[],RemoveVal).
-
-mapfilter(Fun,[],[RemoveVal|Acc],RemoveVal)->
- Acc;
-mapfilter(Fun,[],Acc,_RemoveVal)->
- Acc;
-
-mapfilter(Fun,[Elem|Rest],[RemoveVal|Acc],RemoveVal)->
- mapfilter(Fun,Rest,[Fun(Elem)|Acc],RemoveVal);
-mapfilter(Fun,[Elem|Rest],Acc,RemoveVal)->
- mapfilter(Fun,Rest,[Fun(Elem)|Acc],RemoveVal).
-
-
-transform({content_type,undefined})->
- ["Content-Type:text/plain\r\n"];
-
-transform({date,undefined})->
- ["Date:",httpd_util:rfc1123_date(),"\r\n"];
-
-transform({date,RFCDate})->
- ["Date:",RFCDate,"\r\n"];
-
-
-transform({_Key,undefined})->
- undefined;
-transform({accept_ranges,Value})->
- ["Accept-Ranges:",Value,"\r\n"];
-transform({cache_control,Value})->
- ["Cache-Control:",Value,"\r\n"];
-transform({pragma,Value})->
- ["Pragma:",Value,"\r\n"];
-transform({trailer,Value})->
- ["Trailer:",Value,"\r\n"];
-transform({transfer_encoding,Value})->
- ["Pragma:",Value,"\r\n"];
-transform({etag,Value})->
- ["ETag:",Value,"\r\n"];
-transform({location,Value})->
- ["Retry-After:",Value,"\r\n"];
-transform({server,Value})->
- ["Server:",Value,"\r\n"];
-transform({allow,Value})->
- ["Allow:",Value,"\r\n"];
-transform({content_encoding,Value})->
- ["Content-Encoding:",Value,"\r\n"];
-transform({content_language,Value})->
- ["Content-Language:",Value,"\r\n"];
-transform({retry_after,Value})->
- ["Retry-After:",Value,"\r\n"];
-transform({server,Value})->
- ["Server:",Value,"\r\n"];
-transform({allow,Value})->
- ["Allow:",Value,"\r\n"];
-transform({content_encoding,Value})->
- ["Content-Encoding:",Value,"\r\n"];
-transform({content_language,Value})->
- ["Content-Language:",Value,"\r\n"];
-transform({content_location,Value})->
- ["Content-Location:",Value,"\r\n"];
-transform({content_length,Value})->
- ["Content-Length:",Value,"\r\n"];
-transform({content_MD5,Value})->
- ["Content-MD5:",Value,"\r\n"];
-transform({content_range,Value})->
- ["Content-Range:",Value,"\r\n"];
-transform({content_type,Value})->
- ["Content-Type:",Value,"\r\n"];
-transform({expires,Value})->
- ["Expires:",Value,"\r\n"];
-transform({last_modified,Value})->
- ["Last-Modified:",Value,"\r\n"].
-
-
-
-%%----------------------------------------------------------------------
-%% This is the old way of sending data it is strongly encouraged to
-%% Leave this method and go on to the newer form of response
-%% OTP-4408
-%%----------------------------------------------------------------------
-
-send_response_old(#mod{socket_type = Type,
- socket = Sock,
- method = "HEAD"} = Info,
- StatusCode, Response) ->
- ?vtrace("send_response_old(HEAD) -> entry with"
- "~n StatusCode: ~p"
- "~n Response: ~p",
- [StatusCode,Response]),
- case httpd_util:split(lists:flatten(Response),"\r\n\r\n|\n\n",2) of
- {ok, [Head, Body]} ->
- Header =
- httpd_util:header(StatusCode,Info#mod.connection) ++
- "Content-Length:" ++ content_length(Body),
- httpd_socket:deliver(Type, Sock, [Header,Head,"\r\n"]);
-
- Error ->
- send_status(Info, 500, "Internal Server Error")
- end;
-
-send_response_old(#mod{socket_type = Type,
- socket = Sock} = Info,
- StatusCode, Response) ->
- ?vtrace("send_response_old -> entry with"
- "~n StatusCode: ~p"
- "~n Response: ~p",
- [StatusCode,Response]),
- case httpd_util:split(lists:flatten(Response),"\r\n\r\n|\n\n",2) of
- {ok, [_Head, Body]} ->
- Header =
- httpd_util:header(StatusCode,Info#mod.connection) ++
- "Content-Length:" ++ content_length(Body),
- httpd_socket:deliver(Type, Sock, [Header, Response]);
-
- {ok, Body} ->
- Header =
- httpd_util:header(StatusCode,Info#mod.connection) ++
- "Content-Length:" ++ content_length(Body) ++ "\r\n",
- httpd_socket:deliver(Type, Sock, [Header, Response]);
-
- {error, Reason} ->
- send_status(Info, 500, "Internal Server Error")
- end.
-
-content_length(Body)->
- integer_to_list(httpd_util:flatlength(Body))++"\r\n".
-
-
-report_error(Mod, ConfigDB, Error) ->
- Modules = httpd_util:lookup(ConfigDB, modules,
- [mod_get, mod_head, mod_log]),
- case lists:member(Mod, Modules) of
- true ->
- Mod:report_error(ConfigDB, Error);
- _ ->
- ok
- end.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_socket.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_socket.erl
deleted file mode 100644
index 95dfc5e824..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_socket.erl
+++ /dev/null
@@ -1,381 +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: httpd_socket.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
-%%
--module(httpd_socket).
--export([start/1,
- listen/2, listen/3, accept/2, accept/3,
- deliver/3, send/3, recv/4,
- close/2,
- peername/2, resolve/1, config/1,
- controlling_process/3,
- active_once/2]).
-
--include("httpd.hrl").
-
--define(VMODULE,"SOCKET").
--include("httpd_verbosity.hrl").
-
--include_lib("kernel/include/inet.hrl").
-
-%% start -> ok | {error,Reason}
-
-start(ip_comm) ->
- case inet_db:start() of
- {ok,_Pid} ->
- ok;
- {error,{already_started,_Pid}} ->
- ok;
- Error ->
- Error
- end;
-start({ssl,_SSLConfig}) ->
- case ssl:start() of
- ok ->
- ok;
- {ok, _} ->
- ok;
- {error,{already_started,_}} ->
- ok;
- Error ->
- Error
- end.
-
-%% listen
-
-listen(SocketType,Port) ->
- listen(SocketType,undefined,Port).
-
-listen(ip_comm,Addr,Port) ->
- ?DEBUG("listening(ip_comm) to port ~p", [Port]),
- Opt = sock_opt(Addr,[{backlog,128},{reuseaddr,true}]),
- case gen_tcp:listen(Port,Opt) of
- {ok,ListenSocket} ->
- ListenSocket;
- Error ->
- Error
- end;
-listen({ssl,SSLConfig},Addr,Port) ->
- ?DEBUG("listening(ssl) to port ~p"
- "~n SSLConfig: ~p", [Port,SSLConfig]),
- Opt = sock_opt(Addr,SSLConfig),
- case ssl:listen(Port, Opt) of
- {ok,ListenSocket} ->
- ListenSocket;
- Error ->
- Error
- end.
-
-
-sock_opt(undefined,Opt) -> [{packet,0},{active,false}|Opt];
-sock_opt(Addr,Opt) -> [{ip, Addr},{packet,0},{active,false}|Opt].
-
-%% -define(packet_type_http,true).
-%% -define(packet_type_httph,true).
-
-%% -ifdef(packet_type_http).
-%% sock_opt(undefined,Opt) -> [{packet,http},{active,false}|Opt];
-%% sock_opt(Addr,Opt) -> [{ip, Addr},{packet,http},{active,false}|Opt].
-%% -elif(packet_type_httph).
-%% sock_opt(undefined,Opt) -> [{packet,httph},{active,false}|Opt];
-%% sock_opt(Addr,Opt) -> [{ip, Addr},{packet,httph},{active,false}|Opt].
-%% -else.
-%% sock_opt(undefined,Opt) -> [{packet,0},{active,false}|Opt];
-%% sock_opt(Addr,Opt) -> [{ip, Addr},{packet,0},{active,false}|Opt].
-%% -endif.
-
-
-%% active_once
-
-active_once(Type, Sock) ->
- active(Type, Sock, once).
-
-active(ip_comm, Sock, Active) ->
- inet:setopts(Sock, [{active, Active}]);
-active({ssl, _SSLConfig}, Sock, Active) ->
- ssl:setopts(Sock, [{active, Active}]).
-
-%% accept
-
-accept(A, B) ->
- accept(A, B, infinity).
-
-
-accept(ip_comm,ListenSocket, T) ->
- ?DEBUG("accept(ip_comm) on socket ~p", [ListenSocket]),
- case gen_tcp:accept(ListenSocket, T) of
- {ok,Socket} ->
- Socket;
- Error ->
- ?vtrace("accept(ip_comm) failed for reason:"
- "~n Error: ~p",[Error]),
- Error
- end;
-accept({ssl,_SSLConfig},ListenSocket, T) ->
- ?DEBUG("accept(ssl) on socket ~p", [ListenSocket]),
- case ssl:accept(ListenSocket, T) of
- {ok,Socket} ->
- Socket;
- Error ->
- ?vtrace("accept(ssl) failed for reason:"
- "~n Error: ~p",[Error]),
- Error
- end.
-
-
-%% controlling_process
-
-controlling_process(ip_comm, Socket, Pid) ->
- gen_tcp:controlling_process(Socket, Pid);
-controlling_process({ssl, _}, Socket, Pid) ->
- ssl:controlling_process(Socket, Pid).
-
-
-%% deliver
-
-deliver(SocketType, Socket, IOListOrBinary) ->
- case send(SocketType, Socket, IOListOrBinary) of
-% {error, einval} ->
-% ?vlog("deliver failed for reason: einval"
-% "~n SocketType: ~p"
-% "~n Socket: ~p"
-% "~n Data: ~p",
-% [SocketType, Socket, type(IOListOrBinary)]),
-% (catch close(SocketType, Socket)),
-% socket_closed;
- {error, _Reason} ->
- ?vlog("deliver(~p) failed for reason:"
- "~n Reason: ~p",[SocketType,_Reason]),
- (catch close(SocketType, Socket)),
- socket_closed;
- _ ->
- ok
- end.
-
-% type(L) when list(L) ->
-% {list, L};
-% type(B) when binary(B) ->
-% Decoded =
-% case (catch binary_to_term(B)) of
-% {'EXIT', _} ->
-% %% Oups, not a term, try list
-% case (catch binary_to_list(B)) of
-% %% Oups, not a list either, give up
-% {'EXIT', _} ->
-% {size, size(B)};
-% L ->
-% {list, L}
-% end;
-
-% T ->
-% {term, T}
-% end,
-% {binary, Decoded};
-% type(T) when tuple(T) ->
-% {tuple, T};
-% type(I) when integer(I) ->
-% {integer, I};
-% type(F) when float(F) ->
-% {float, F};
-% type(P) when pid(P) ->
-% {pid, P};
-% type(P) when port(P) ->
-% {port, P};
-% type(R) when reference(R) ->
-% {reference, R};
-% type(T) ->
-% {term, T}.
-
-
-
-send(ip_comm,Socket,Data) ->
- ?DEBUG("send(ip_comm) -> ~p bytes on socket ~p",[data_size(Data),Socket]),
- gen_tcp:send(Socket,Data);
-send({ssl,SSLConfig},Socket,Data) ->
- ?DEBUG("send(ssl) -> ~p bytes on socket ~p",[data_size(Data),Socket]),
- ssl:send(Socket, Data).
-
-recv(ip_comm,Socket,Length,Timeout) ->
- ?DEBUG("recv(ip_comm) -> read from socket ~p",[Socket]),
- gen_tcp:recv(Socket,Length,Timeout);
-recv({ssl,SSLConfig},Socket,Length,Timeout) ->
- ?DEBUG("recv(ssl) -> read from socket ~p",[Socket]),
- ssl:recv(Socket,Length,Timeout).
-
--ifdef(inets_debug).
-data_size(L) when list(L) ->
- httpd_util:flatlength(L);
-data_size(B) when binary(B) ->
- size(B);
-data_size(O) ->
- {unknown_size,O}.
--endif.
-
-
-%% peername
-
-peername(ip_comm, Socket) ->
- case inet:peername(Socket) of
- {ok,{{A,B,C,D},Port}} ->
- PeerName = integer_to_list(A)++"."++integer_to_list(B)++"."++
- integer_to_list(C)++"."++integer_to_list(D),
- ?DEBUG("peername(ip_comm) on socket ~p: ~p",
- [Socket,{Port,PeerName}]),
- {Port,PeerName};
- {error,Reason} ->
- ?vlog("failed getting peername:"
- "~n Reason: ~p"
- "~n Socket: ~p",
- [Reason,Socket]),
- {-1,"unknown"}
- end;
-peername({ssl,_SSLConfig},Socket) ->
- case ssl:peername(Socket) of
- {ok,{{A,B,C,D},Port}} ->
- PeerName = integer_to_list(A)++"."++integer_to_list(B)++"."++
- integer_to_list(C)++"."++integer_to_list(D),
- ?DEBUG("peername(ssl) on socket ~p: ~p",
- [Socket, {Port,PeerName}]),
- {Port,PeerName};
- {error,_Reason} ->
- {-1,"unknown"}
- end.
-
-%% resolve
-
-resolve(_) ->
- {ok,Name} = inet:gethostname(),
- Name.
-
-%% close
-
-close(ip_comm,Socket) ->
- Res =
- case (catch gen_tcp:close(Socket)) of
- ok -> ok;
- {error,Reason} -> {error,Reason};
- {'EXIT',{noproc,_}} -> {error,closed};
- {'EXIT',Reason} -> {error,Reason};
- Otherwise -> {error,Otherwise}
- end,
- ?vtrace("close(ip_comm) result: ~p",[Res]),
- Res;
-close({ssl,_SSLConfig},Socket) ->
- Res =
- case (catch ssl:close(Socket)) of
- ok -> ok;
- {error,Reason} -> {error,Reason};
- {'EXIT',{noproc,_}} -> {error,closed};
- {'EXIT',Reason} -> {error,Reason};
- Otherwise -> {error,Otherwise}
- end,
- ?vtrace("close(ssl) result: ~p",[Res]),
- Res.
-
-%% config (debug: {certfile, "/var/tmp/server_root/conf/ssl_server.pem"})
-
-config(ConfigDB) ->
- case httpd_util:lookup(ConfigDB,com_type,ip_comm) of
- ssl ->
- case ssl_certificate_file(ConfigDB) of
- undefined ->
- {error,
- ?NICE("Directive SSLCertificateFile "
- "not found in the config file")};
- SSLCertificateFile ->
- {ssl,
- SSLCertificateFile++
- ssl_certificate_key_file(ConfigDB)++
- ssl_verify_client(ConfigDB)++
- ssl_ciphers(ConfigDB)++
- ssl_password(ConfigDB)++
- ssl_verify_depth(ConfigDB)++
- ssl_ca_certificate_file(ConfigDB)}
- end;
- ip_comm ->
- ip_comm
- end.
-
-ssl_certificate_file(ConfigDB) ->
- case httpd_util:lookup(ConfigDB,ssl_certificate_file) of
- undefined ->
- undefined;
- SSLCertificateFile ->
- [{certfile,SSLCertificateFile}]
- end.
-
-ssl_certificate_key_file(ConfigDB) ->
- case httpd_util:lookup(ConfigDB,ssl_certificate_key_file) of
- undefined ->
- [];
- SSLCertificateKeyFile ->
- [{keyfile,SSLCertificateKeyFile}]
- end.
-
-ssl_verify_client(ConfigDB) ->
- case httpd_util:lookup(ConfigDB,ssl_verify_client) of
- undefined ->
- [];
- SSLVerifyClient ->
- [{verify,SSLVerifyClient}]
- end.
-
-ssl_ciphers(ConfigDB) ->
- case httpd_util:lookup(ConfigDB,ssl_ciphers) of
- undefined ->
- [];
- Ciphers ->
- [{ciphers, Ciphers}]
- end.
-
-ssl_password(ConfigDB) ->
- case httpd_util:lookup(ConfigDB,ssl_password_callback_module) of
- undefined ->
- [];
- Module ->
- case httpd_util:lookup(ConfigDB, ssl_password_callback_function) of
- undefined ->
- [];
- Function ->
- case catch apply(Module, Function, []) of
- Password when list(Password) ->
- [{password, Password}];
- Error ->
- error_report(ssl_password,Module,Function,Error),
- []
- end
- end
- end.
-
-ssl_verify_depth(ConfigDB) ->
- case httpd_util:lookup(ConfigDB, ssl_verify_client_depth) of
- undefined ->
- [];
- Depth ->
- [{depth, Depth}]
- end.
-
-ssl_ca_certificate_file(ConfigDB) ->
- case httpd_util:lookup(ConfigDB, ssl_ca_certificate_file) of
- undefined ->
- [];
- File ->
- [{cacertfile, File}]
- end.
-
-
-error_report(Where,M,F,Error) ->
- error_logger:error_report([{?MODULE, Where}, {apply, {M, F, []}}, Error]).
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_sup.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_sup.erl
deleted file mode 100644
index fd557c30db..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_sup.erl
+++ /dev/null
@@ -1,203 +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: httpd_sup.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
-%%
-%%----------------------------------------------------------------------
-%% Purpose: The top supervisor for the inets application
-%%----------------------------------------------------------------------
-
--module(httpd_sup).
-
--behaviour(supervisor).
-
--include("httpd_verbosity.hrl").
-
-%% public
--export([start/2, start_link/2, start2/2, start_link2/2, stop/1, stop/2, stop2/1]).
--export([init/1]).
-
-
--define(D(F, A), io:format("~p:" ++ F ++ "~n", [?MODULE|A])).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% supervisor callback functions
-
-start(ConfigFile, Verbosity) ->
- case start_link(ConfigFile, Verbosity) of
- {ok, Pid} ->
- unlink(Pid),
- {ok, Pid};
-
- Else ->
- Else
- end.
-
-
-start_link(ConfigFile, Verbosity) ->
- case get_addr_and_port(ConfigFile) of
- {ok, ConfigList, Addr, Port} ->
- Name = make_name(Addr, Port),
- SupName = {local, Name},
- supervisor:start_link(SupName, ?MODULE,
- [ConfigFile, ConfigList,
- Verbosity, Addr, Port]);
-
- {error, Reason} ->
- error_logger:error_report(Reason),
- {stop, Reason};
-
- Else ->
- error_logger:error_report(Else),
- {stop, Else}
- end.
-
-
-start2(ConfigList, Verbosity) ->
- case start_link2(ConfigList, Verbosity) of
- {ok, Pid} ->
- unlink(Pid),
- {ok, Pid};
-
- Else ->
- Else
- end.
-
-
-start_link2(ConfigList, Verbosity) ->
- case get_addr_and_port2(ConfigList) of
- {ok, Addr, Port} ->
- Name = make_name(Addr, Port),
- SupName = {local, Name},
- supervisor:start_link(SupName, ?MODULE,
- [undefined, ConfigList, Verbosity, Addr, Port]);
-
- {error, Reason} ->
- error_logger:error_report(Reason),
- {stop, Reason};
-
- Else ->
- error_logger:error_report(Else),
- {stop, Else}
- end.
-
-
-
-stop(Pid) when pid(Pid) ->
- do_stop(Pid);
-stop(ConfigFile) when list(ConfigFile) ->
- case get_addr_and_port(ConfigFile) of
- {ok, _, Addr, Port} ->
- stop(Addr, Port);
-
- Error ->
- Error
- end;
-stop(StartArgs) ->
- ok.
-
-
-stop(Addr, Port) when integer(Port) ->
- Name = make_name(Addr, Port),
- case whereis(Name) of
- Pid when pid(Pid) ->
- do_stop(Pid),
- ok;
- _ ->
- not_started
- end.
-
-stop2(ConfigList) when list(ConfigList) ->
- {ok, Addr, Port} = get_addr_and_port2(ConfigList),
- stop(Addr, Port).
-
-
-do_stop(Pid) ->
- exit(Pid, shutdown).
-
-
-init([ConfigFile, ConfigList, Verbosity, Addr, Port]) ->
- init(ConfigFile, ConfigList, Verbosity, Addr, Port);
-init(BadArg) ->
- {error, {badarg, BadArg}}.
-
-init(ConfigFile, ConfigList, Verbosity, Addr, Port) ->
- Flags = {one_for_one, 0, 1},
- AccSupVerbosity = get_acc_sup_verbosity(Verbosity),
- MiscSupVerbosity = get_misc_sup_verbosity(Verbosity),
- Sups = [sup_spec(httpd_acceptor_sup, Addr, Port, AccSupVerbosity),
- sup_spec(httpd_misc_sup, Addr, Port, MiscSupVerbosity),
- worker_spec(httpd_manager, Addr, Port, ConfigFile, ConfigList,
- Verbosity, [gen_server])],
- {ok, {Flags, Sups}}.
-
-
-sup_spec(Name, Addr, Port, Verbosity) ->
- {{Name, Addr, Port},
- {Name, start, [Addr, Port, Verbosity]},
- permanent, 2000, supervisor, [Name, supervisor]}.
-
-worker_spec(Name, Addr, Port, ConfigFile, ConfigList, Verbosity, Modules) ->
- {{Name, Addr, Port},
- {Name, start_link, [ConfigFile, ConfigList, Verbosity]},
- permanent, 2000, worker, [Name] ++ Modules}.
-
-
-make_name(Addr,Port) ->
- httpd_util:make_name("httpd_sup",Addr,Port).
-
-
-%% get_addr_and_port
-
-get_addr_and_port(ConfigFile) ->
- case httpd_conf:load(ConfigFile) of
- {ok, ConfigList} ->
- {ok, Addr, Port} = get_addr_and_port2(ConfigList),
- {ok, ConfigList, Addr, Port};
- Error ->
- Error
- end.
-
-
-get_addr_and_port2(ConfigList) ->
- Port = httpd_util:key1search(ConfigList, port, 80),
- Addr = httpd_util:key1search(ConfigList, bind_address),
- {ok, Addr, Port}.
-
-get_acc_sup_verbosity(V) ->
- case key1search(V, all) of
- undefined ->
- key1search(V, acceptor_sup_verbosity, ?default_verbosity);
- Verbosity ->
- Verbosity
- end.
-
-
-get_misc_sup_verbosity(V) ->
- case key1search(V, all) of
- undefined ->
- key1search(V, misc_sup_verbosity, ?default_verbosity);
- Verbosity ->
- Verbosity
- end.
-
-
-key1search(L, K) ->
- httpd_util:key1search(L, K).
-
-key1search(L, K, D) ->
- httpd_util:key1search(L, K, D).
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_util.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_util.erl
deleted file mode 100644
index 05064a8d38..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_util.erl
+++ /dev/null
@@ -1,777 +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: httpd_util.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
-%%
--module(httpd_util).
--export([key1search/2, key1search/3, lookup/2, lookup/3, multi_lookup/2,
- lookup_mime/2, lookup_mime/3, lookup_mime_default/2,
- lookup_mime_default/3, reason_phrase/1, message/3, rfc1123_date/0,
- rfc1123_date/1, day/1, month/1, decode_hex/1, decode_base64/1, encode_base64/1,
- flatlength/1, split_path/1, split_script_path/1, suffix/1, to_upper/1,
- to_lower/1, split/3, header/2, header/3, header/4, uniq/1,
- make_name/2,make_name/3,make_name/4,strip/1,
- hexlist_to_integer/1,integer_to_hexlist/1,
- convert_request_date/1,create_etag/1,create_etag/2,getSize/1,
- response_generated/1]).
-
-%%Since hexlist_to_integer is a lousy name make a name convert
--export([encode_hex/1]).
--include("httpd.hrl").
-
-%% key1search
-
-key1search(TupleList,Key) ->
- key1search(TupleList,Key,undefined).
-
-key1search(TupleList,Key,Undefined) ->
- case lists:keysearch(Key,1,TupleList) of
- {value,{Key,Value}} ->
- Value;
- false ->
- Undefined
- end.
-
-%% lookup
-
-lookup(Table,Key) ->
- lookup(Table,Key,undefined).
-
-lookup(Table,Key,Undefined) ->
- case catch ets:lookup(Table,Key) of
- [{Key,Value}|_] ->
- Value;
- _->
- Undefined
- end.
-
-%% multi_lookup
-
-multi_lookup(Table,Key) ->
- remove_key(ets:lookup(Table,Key)).
-
-remove_key([]) ->
- [];
-remove_key([{_Key,Value}|Rest]) ->
- [Value|remove_key(Rest)].
-
-%% lookup_mime
-
-lookup_mime(ConfigDB,Suffix) ->
- lookup_mime(ConfigDB,Suffix,undefined).
-
-lookup_mime(ConfigDB,Suffix,Undefined) ->
- [{mime_types,MimeTypesDB}|_]=ets:lookup(ConfigDB,mime_types),
- case ets:lookup(MimeTypesDB,Suffix) of
- [] ->
- Undefined;
- [{Suffix,MimeType}|_] ->
- MimeType
- end.
-
-%% lookup_mime_default
-
-lookup_mime_default(ConfigDB,Suffix) ->
- lookup_mime_default(ConfigDB,Suffix,undefined).
-
-lookup_mime_default(ConfigDB,Suffix,Undefined) ->
- [{mime_types,MimeTypesDB}|_]=ets:lookup(ConfigDB,mime_types),
- case ets:lookup(MimeTypesDB,Suffix) of
- [] ->
- case ets:lookup(ConfigDB,default_type) of
- [] ->
- Undefined;
- [{default_type,DefaultType}|_] ->
- DefaultType
- end;
- [{Suffix,MimeType}|_] ->
- MimeType
- end.
-
-%% reason_phrase
-reason_phrase(100) -> "Continue";
-reason_phrase(101) -> "Swithing protocol";
-reason_phrase(200) -> "OK";
-reason_phrase(201) -> "Created";
-reason_phrase(202) -> "Accepted";
-reason_phrase(204) -> "No Content";
-reason_phrase(205) -> "Reset Content";
-reason_phrase(206) -> "Partial Content";
-reason_phrase(301) -> "Moved Permanently";
-reason_phrase(302) -> "Moved Temporarily";
-reason_phrase(304) -> "Not Modified";
-reason_phrase(400) -> "Bad Request";
-reason_phrase(401) -> "Unauthorized";
-reason_phrase(402) -> "Payment Required";
-reason_phrase(403) -> "Forbidden";
-reason_phrase(404) -> "Not Found";
-reason_phrase(405) -> "Method Not Allowed";
-reason_phrase(408) -> "Request Timeout";
-reason_phrase(411) -> "Length Required";
-reason_phrase(414) -> "Request-URI Too Long";
-reason_phrase(412) -> "Precondition Failed";
-reason_phrase(416) -> "request Range Not Satisfiable";
-reason_phrase(417) -> "Expectation failed";
-reason_phrase(500) -> "Internal Server Error";
-reason_phrase(501) -> "Not Implemented";
-reason_phrase(502) -> "Bad Gateway";
-reason_phrase(503) -> "Service Unavailable";
-reason_phrase(_) -> "Internal Server Error".
-
-%% message
-
-message(301,URL,_) ->
- "The document has moved <A HREF=\""++URL++"\">here</A>.";
-message(304,_URL,_) ->
- "The document has not been changed.";
-message(400,none,_) ->
- "Your browser sent a query that this server could not understand.";
-message(401,none,_) ->
- "This server could not verify that you
-are authorized to access the document you
-requested. Either you supplied the wrong
-credentials (e.g., bad password), or your
-browser does not understand how to supply
-the credentials required.";
-message(403,RequestURI,_) ->
- "You do not have permission to access "++RequestURI++" on this server.";
-message(404,RequestURI,_) ->
- "The requested URL "++RequestURI++" was not found on this server.";
-message(412,none,_) ->
- "The requested preconditions where false";
-message(414,ReasonPhrase,_) ->
- "Message "++ReasonPhrase++".";
-message(416,ReasonPhrase,_) ->
- ReasonPhrase;
-
-message(500,none,ConfigDB) ->
- ServerAdmin=lookup(ConfigDB,server_admin,"unknown@unknown"),
- "The server encountered an internal error or
-misconfiguration and was unable to complete
-your request.
-<P>Please contact the server administrator "++ServerAdmin++",
-and inform them of the time the error occurred
-and anything you might have done that may have
-caused the error.";
-message(501,{Method,RequestURI,HTTPVersion},_ConfigDB) ->
- Method++" to "++RequestURI++" ("++HTTPVersion++") not supported.";
-message(503,String,_ConfigDB) ->
- "This service in unavailable due to: "++String.
-
-%%convert_rfc_date(Date)->{{YYYY,MM,DD},{HH,MIN,SEC}}
-
-convert_request_date([D,A,Y,DateType|Rest]) ->
- Func=case DateType of
- $\, ->
- fun convert_rfc1123_date/1;
- $\ ->
- fun convert_ascii_date/1;
- _ ->
- fun convert_rfc850_date/1
- end,
- case catch Func([D,A,Y,DateType|Rest])of
- {ok,Date} ->
- Date;
- _Error ->
- bad_date
- end.
-
-convert_rfc850_date(DateStr) ->
- case string:tokens(DateStr," ") of
- [_WeekDay,Date,Time,_TimeZone|_Rest] ->
- convert_rfc850_date(Date,Time);
- _Error ->
- bad_date
- end.
-
-convert_rfc850_date([D1,D2,_,M,O,N,_,Y1,Y2|_Rest],[H1,H2,_Col,M1,M2,_Col,S1,S2|_Rest2])->
- Year=list_to_integer([50,48,Y1,Y2]),
- Day=list_to_integer([D1,D2]),
- Month=convert_month([M,O,N]),
- Hour=list_to_integer([H1,H2]),
- Min=list_to_integer([M1,M2]),
- Sec=list_to_integer([S1,S2]),
- {ok,{{Year,Month,Day},{Hour,Min,Sec}}};
-convert_rfc850_date(_BadDate,_BadTime)->
- bad_date.
-
-convert_ascii_date([_D,_A,_Y,_SP,M,O,N,_SP,D1,D2,_SP,H1,H2,_Col,M1,M2,_Col,S1,S2,_SP,Y1,Y2,Y3,Y4|_Rest])->
- Year=list_to_integer([Y1,Y2,Y3,Y4]),
- Day=case D1 of
- $\ ->
- list_to_integer([D2]);
- _->
- list_to_integer([D1,D2])
- end,
- Month=convert_month([M,O,N]),
- Hour=list_to_integer([H1,H2]),
- Min=list_to_integer([M1,M2]),
- Sec=list_to_integer([S1,S2]),
- {ok,{{Year,Month,Day},{Hour,Min,Sec}}};
-convert_ascii_date(BadDate)->
- bad_date.
-convert_rfc1123_date([_D,_A,_Y,_C,_SP,D1,D2,_SP,M,O,N,_SP,Y1,Y2,Y3,Y4,_SP,H1,H2,_Col,M1,M2,_Col,S1,S2|Rest])->
- Year=list_to_integer([Y1,Y2,Y3,Y4]),
- Day=list_to_integer([D1,D2]),
- Month=convert_month([M,O,N]),
- Hour=list_to_integer([H1,H2]),
- Min=list_to_integer([M1,M2]),
- Sec=list_to_integer([S1,S2]),
- {ok,{{Year,Month,Day},{Hour,Min,Sec}}};
-convert_rfc1123_date(BadDate)->
- bad_date.
-
-convert_month("Jan")->1;
-convert_month("Feb") ->2;
-convert_month("Mar") ->3;
-convert_month("Apr") ->4;
-convert_month("May") ->5;
-convert_month("Jun") ->6;
-convert_month("Jul") ->7;
-convert_month("Aug") ->8;
-convert_month("Sep") ->9;
-convert_month("Oct") ->10;
-convert_month("Nov") ->11;
-convert_month("Dec") ->12.
-
-
-%% rfc1123_date
-
-rfc1123_date() ->
- {{YYYY,MM,DD},{Hour,Min,Sec}}=calendar:universal_time(),
- DayNumber=calendar:day_of_the_week({YYYY,MM,DD}),
- lists:flatten(io_lib:format("~s, ~2.2.0w ~3.s ~4.4.0w ~2.2.0w:~2.2.0w:~2.2.0w GMT",
- [day(DayNumber),DD,month(MM),YYYY,Hour,Min,Sec])).
-
-rfc1123_date({{YYYY,MM,DD},{Hour,Min,Sec}}) ->
- DayNumber=calendar:day_of_the_week({YYYY,MM,DD}),
- lists:flatten(io_lib:format("~s, ~2.2.0w ~3.s ~4.4.0w ~2.2.0w:~2.2.0w:~2.2.0w GMT",
- [day(DayNumber),DD,month(MM),YYYY,Hour,Min,Sec])).
-
-%% uniq
-
-uniq([]) ->
- [];
-uniq([First,First|Rest]) ->
- uniq([First|Rest]);
-uniq([First|Rest]) ->
- [First|uniq(Rest)].
-
-
-%% day
-
-day(1) -> "Mon";
-day(2) -> "Tue";
-day(3) -> "Wed";
-day(4) -> "Thu";
-day(5) -> "Fri";
-day(6) -> "Sat";
-day(7) -> "Sun".
-
-%% month
-
-month(1) -> "Jan";
-month(2) -> "Feb";
-month(3) -> "Mar";
-month(4) -> "Apr";
-month(5) -> "May";
-month(6) -> "Jun";
-month(7) -> "Jul";
-month(8) -> "Aug";
-month(9) -> "Sep";
-month(10) -> "Oct";
-month(11) -> "Nov";
-month(12) -> "Dec".
-
-%% decode_hex
-
-decode_hex([$%,Hex1,Hex2|Rest]) ->
- [hex2dec(Hex1)*16+hex2dec(Hex2)|decode_hex(Rest)];
-decode_hex([First|Rest]) ->
- [First|decode_hex(Rest)];
-decode_hex([]) ->
- [].
-
-hex2dec(X) when X>=$0,X=<$9 -> X-$0;
-hex2dec(X) when X>=$A,X=<$F -> X-$A+10;
-hex2dec(X) when X>=$a,X=<$f -> X-$a+10.
-
-%% decode_base64 (DEBUG STRING: QWxhZGRpbjpvcGVuIHNlc2FtZQ==)
-
-decode_base64([]) ->
- [];
-decode_base64([Sextet1,Sextet2,$=,$=|Rest]) ->
- Bits2x6=
- (d(Sextet1) bsl 18) bor
- (d(Sextet2) bsl 12),
- Octet1=Bits2x6 bsr 16,
- [Octet1|decode_base64(Rest)];
-decode_base64([Sextet1,Sextet2,Sextet3,$=|Rest]) ->
- Bits3x6=
- (d(Sextet1) bsl 18) bor
- (d(Sextet2) bsl 12) bor
- (d(Sextet3) bsl 6),
- Octet1=Bits3x6 bsr 16,
- Octet2=(Bits3x6 bsr 8) band 16#ff,
- [Octet1,Octet2|decode_base64(Rest)];
-decode_base64([Sextet1,Sextet2,Sextet3,Sextet4|Rest]) ->
- Bits4x6=
- (d(Sextet1) bsl 18) bor
- (d(Sextet2) bsl 12) bor
- (d(Sextet3) bsl 6) bor
- d(Sextet4),
- Octet1=Bits4x6 bsr 16,
- Octet2=(Bits4x6 bsr 8) band 16#ff,
- Octet3=Bits4x6 band 16#ff,
- [Octet1,Octet2,Octet3|decode_base64(Rest)];
-decode_base64(CatchAll) ->
- "BAD!".
-
-d(X) when X >= $A, X =<$Z ->
- X-65;
-d(X) when X >= $a, X =<$z ->
- X-71;
-d(X) when X >= $0, X =<$9 ->
- X+4;
-d($+) -> 62;
-d($/) -> 63;
-d(_) -> 63.
-
-
-encode_base64([]) ->
- [];
-encode_base64([A]) ->
- [e(A bsr 2), e((A band 3) bsl 4), $=, $=];
-encode_base64([A,B]) ->
- [e(A bsr 2), e(((A band 3) bsl 4) bor (B bsr 4)), e((B band 15) bsl 2), $=];
-encode_base64([A,B,C|Ls]) ->
- encode_base64_do(A,B,C, Ls).
-encode_base64_do(A,B,C, Rest) ->
- BB = (A bsl 16) bor (B bsl 8) bor C,
- [e(BB bsr 18), e((BB bsr 12) band 63),
- e((BB bsr 6) band 63), e(BB band 63)|encode_base64(Rest)].
-
-e(X) when X >= 0, X < 26 -> X+65;
-e(X) when X>25, X<52 -> X+71;
-e(X) when X>51, X<62 -> X-4;
-e(62) -> $+;
-e(63) -> $/;
-e(X) -> exit({bad_encode_base64_token, X}).
-
-
-%% flatlength
-
-flatlength(List) ->
- flatlength(List, 0).
-
-flatlength([H|T],L) when list(H) ->
- flatlength(H,flatlength(T,L));
-flatlength([H|T],L) when binary(H) ->
- flatlength(T,L+size(H));
-flatlength([H|T],L) ->
- flatlength(T,L+1);
-flatlength([],L) ->
- L.
-
-%% split_path
-
-split_path(Path) ->
- case regexp:match(Path,"[\?].*\$") of
- %% A QUERY_STRING exists!
- {match,Start,Length} ->
- {httpd_util:decode_hex(string:substr(Path,1,Start-1)),
- string:substr(Path,Start,Length)};
- %% A possible PATH_INFO exists!
- nomatch ->
- split_path(Path,[])
- end.
-
-split_path([],SoFar) ->
- {httpd_util:decode_hex(lists:reverse(SoFar)),[]};
-split_path([$/|Rest],SoFar) ->
- Path=httpd_util:decode_hex(lists:reverse(SoFar)),
- case file:read_file_info(Path) of
- {ok,FileInfo} when FileInfo#file_info.type == regular ->
- {Path,[$/|Rest]};
- {ok,FileInfo} ->
- split_path(Rest,[$/|SoFar]);
- {error,Reason} ->
- split_path(Rest,[$/|SoFar])
- end;
-split_path([C|Rest],SoFar) ->
- split_path(Rest,[C|SoFar]).
-
-%% split_script_path
-
-split_script_path(Path) ->
- case split_script_path(Path, []) of
- {Script, AfterPath} ->
- {PathInfo, QueryString} = pathinfo_querystring(AfterPath),
- {Script, {PathInfo, QueryString}};
- not_a_script ->
- not_a_script
- end.
-
-pathinfo_querystring(Str) ->
- pathinfo_querystring(Str, []).
-pathinfo_querystring([], SoFar) ->
- {lists:reverse(SoFar), []};
-pathinfo_querystring([$?|Rest], SoFar) ->
- {lists:reverse(SoFar), Rest};
-pathinfo_querystring([C|Rest], SoFar) ->
- pathinfo_querystring(Rest, [C|SoFar]).
-
-split_script_path([$?|QueryString], SoFar) ->
- Path = httpd_util:decode_hex(lists:reverse(SoFar)),
- case file:read_file_info(Path) of
- {ok,FileInfo} when FileInfo#file_info.type == regular ->
- {Path, [$?|QueryString]};
- {ok,FileInfo} ->
- not_a_script;
- {error,Reason} ->
- not_a_script
- end;
-split_script_path([], SoFar) ->
- Path = httpd_util:decode_hex(lists:reverse(SoFar)),
- case file:read_file_info(Path) of
- {ok,FileInfo} when FileInfo#file_info.type == regular ->
- {Path, []};
- {ok,FileInfo} ->
- not_a_script;
- {error,Reason} ->
- not_a_script
- end;
-split_script_path([$/|Rest], SoFar) ->
- Path = httpd_util:decode_hex(lists:reverse(SoFar)),
- case file:read_file_info(Path) of
- {ok, FileInfo} when FileInfo#file_info.type == regular ->
- {Path, [$/|Rest]};
- {ok, _FileInfo} ->
- split_script_path(Rest, [$/|SoFar]);
- {error, _Reason} ->
- split_script_path(Rest, [$/|SoFar])
- end;
-split_script_path([C|Rest], SoFar) ->
- split_script_path(Rest,[C|SoFar]).
-
-%% suffix
-
-suffix(Path) ->
- case filename:extension(Path) of
- [] ->
- [];
- Extension ->
- tl(Extension)
- end.
-
-%% to_upper
-
-to_upper([C|Cs]) when C >= $a, C =< $z ->
- [C-($a-$A)|to_upper(Cs)];
-to_upper([C|Cs]) ->
- [C|to_upper(Cs)];
-to_upper([]) ->
- [].
-
-%% to_lower
-
-to_lower([C|Cs]) when C >= $A, C =< $Z ->
- [C+($a-$A)|to_lower(Cs)];
-to_lower([C|Cs]) ->
- [C|to_lower(Cs)];
-to_lower([]) ->
- [].
-
-
-%% strip
-strip(Value)->
- lists:reverse(remove_ws(lists:reverse(remove_ws(Value)))).
-
-remove_ws([$\s|Rest])->
- remove_ws(Rest);
-remove_ws([$\t|Rest]) ->
- remove_ws(Rest);
-remove_ws(Rest) ->
- Rest.
-
-%% split
-
-split(String,RegExp,Limit) ->
- case regexp:parse(RegExp) of
- {error,Reason} ->
- {error,Reason};
- {ok,_} ->
- {ok,do_split(String,RegExp,Limit)}
- end.
-
-do_split(String,RegExp,1) ->
- [String];
-
-do_split(String,RegExp,Limit) ->
- case regexp:first_match(String,RegExp) of
- {match,Start,Length} ->
- [string:substr(String,1,Start-1)|
- do_split(lists:nthtail(Start+Length-1,String),RegExp,Limit-1)];
- nomatch ->
- [String]
- end.
-
-%% header
-header(StatusCode,Date)when list(Date)->
- header(StatusCode,"text/plain",false);
-
-header(StatusCode, PersistentConnection) when integer(StatusCode)->
- Date = rfc1123_date(),
- Connection =
- case PersistentConnection of
- true ->
- "";
- _ ->
- "Connection: close \r\n"
- end,
- io_lib:format("HTTP/1.1 ~w ~s \r\nDate: ~s\r\nServer: ~s\r\n~s",
- [StatusCode, httpd_util:reason_phrase(StatusCode),
- Date, ?SERVER_SOFTWARE, Connection]).
-
-%%----------------------------------------------------------------------
-
-header(StatusCode, MimeType, Date) when list(Date) ->
- header(StatusCode, MimeType, false,rfc1123_date());
-
-
-header(StatusCode, MimeType, PersistentConnection) when integer(StatusCode) ->
- header(StatusCode, MimeType, PersistentConnection,rfc1123_date()).
-
-
-%%----------------------------------------------------------------------
-
-header(416, MimeType,PersistentConnection,Date)->
- Connection =
- case PersistentConnection of
- true ->
- "";
- _ ->
- "Connection: close \r\n"
- end,
- io_lib:format("HTTP/1.1 ~w ~s \r\nDate: ~s\r\nServer: ~s\r\n"
- "Content-Range:bytes *"
- "Content-Type: ~s\r\n~s",
- [416, httpd_util:reason_phrase(416),
- Date, ?SERVER_SOFTWARE, MimeType, Connection]);
-
-
-header(StatusCode, MimeType,PersistentConnection,Date) when integer(StatusCode)->
- Connection =
- case PersistentConnection of
- true ->
- "";
- _ ->
- "Connection: close \r\n"
- end,
- io_lib:format("HTTP/1.1 ~w ~s \r\nDate: ~s\r\nServer: ~s\r\n"
- "Content-Type: ~s\r\n~s",
- [StatusCode, httpd_util:reason_phrase(StatusCode),
- Date, ?SERVER_SOFTWARE, MimeType, Connection]).
-
-
-
-%% make_name/2, make_name/3
-%% Prefix -> string()
-%% First part of the name, e.g. "httpd"
-%% Addr -> {A,B,C,D} | string() | undefined
-%% The address part of the name.
-%% e.g. "123.234.55.66" or {123,234,55,66} or "otp.ericsson.se"
-%% for a host address or undefined if local host.
-%% Port -> integer()
-%% Last part of the name, such as the HTTPD server port
-%% number (80).
-%% Postfix -> Any string that will be added last to the name
-%%
-%% Example:
-%% make_name("httpd","otp.ericsson.se",80) => httpd__otp_ericsson_se__80
-%% make_name("httpd",undefined,8088) => httpd_8088
-
-make_name(Prefix,Port) ->
- make_name(Prefix,undefined,Port,"").
-
-make_name(Prefix,Addr,Port) ->
- make_name(Prefix,Addr,Port,"").
-
-make_name(Prefix,"*",Port,Postfix) ->
- make_name(Prefix,undefined,Port,Postfix);
-
-make_name(Prefix,any,Port,Postfix) ->
- make_name1(io_lib:format("~s_~w~s",[Prefix,Port,Postfix]));
-
-make_name(Prefix,undefined,Port,Postfix) ->
- make_name1(io_lib:format("~s_~w~s",[Prefix,Port,Postfix]));
-
-make_name(Prefix,Addr,Port,Postfix) ->
- NameString =
- Prefix ++ "__" ++ make_name2(Addr) ++ "__" ++
- integer_to_list(Port) ++ Postfix,
- make_name1(NameString).
-
-make_name1(String) ->
- list_to_atom(lists:flatten(String)).
-
-make_name2({A,B,C,D}) ->
- io_lib:format("~w_~w_~w_~w",[A,B,C,D]);
-make_name2(Addr) ->
- search_and_replace(Addr,$.,$_).
-
-search_and_replace(S,A,B) ->
- Fun = fun(What) ->
- case What of
- A -> B;
- O -> O
- end
- end,
- lists:map(Fun,S).
-
-
-
-%%----------------------------------------------------------------------
-%% Converts a string that constists of 0-9,A-F,a-f to a
-%% integer
-%%----------------------------------------------------------------------
-
-hexlist_to_integer([])->
- empty;
-
-
-%%When the string only contains one value its eaasy done.
-%% 0-9
-hexlist_to_integer([Size]) when Size>=48 , Size=<57 ->
- Size-48;
-%% A-F
-hexlist_to_integer([Size]) when Size>=65 , Size=<70 ->
- Size-55;
-%% a-f
-hexlist_to_integer([Size]) when Size>=97 , Size=<102 ->
- Size-87;
-hexlist_to_integer([Size]) ->
- not_a_num;
-
-hexlist_to_integer(Size) ->
- Len=string:span(Size,"1234567890abcdefABCDEF"),
- hexlist_to_integer2(Size,16 bsl (4 *(Len-2)),0).
-
-hexlist_to_integer2([],_Pos,Sum)->
- Sum;
-hexlist_to_integer2([HexVal|HexString],Pos,Sum)when HexVal>=48,HexVal=<57->
- hexlist_to_integer2(HexString,Pos bsr 4,Sum+((HexVal-48)*Pos));
-
-hexlist_to_integer2([HexVal|HexString],Pos,Sum)when HexVal>=65,HexVal=<70->
- hexlist_to_integer2(HexString,Pos bsr 4,Sum+((HexVal-55)*Pos));
-
-hexlist_to_integer2([HexVal|HexString],Pos,Sum)when HexVal>=97,HexVal=<102->
- hexlist_to_integer2(HexString,Pos bsr 4,Sum+((HexVal-87)*Pos));
-
-hexlist_to_integer2(_AfterHexString,_Pos,Sum)->
- Sum.
-
-%%----------------------------------------------------------------------
-%%Converts an integer to an hexlist
-%%----------------------------------------------------------------------
-encode_hex(Num)->
- integer_to_hexlist(Num).
-
-
-integer_to_hexlist(Num)->
- integer_to_hexlist(Num,getSize(Num),[]).
-
-integer_to_hexlist(Num,Pot,Res) when Pot<0 ->
- convert_to_ascii([Num|Res]);
-
-integer_to_hexlist(Num,Pot,Res) ->
- Position=(16 bsl (Pot*4)),
- PosVal=Num div Position,
- integer_to_hexlist(Num-(PosVal*Position),Pot-1,[PosVal|Res]).
-convert_to_ascii(RevesedNum)->
- convert_to_ascii(RevesedNum,[]).
-
-convert_to_ascii([],Num)->
- Num;
-convert_to_ascii([Num|Reversed],Number)when Num>-1, Num<10 ->
- convert_to_ascii(Reversed,[Num+48|Number]);
-convert_to_ascii([Num|Reversed],Number)when Num>9, Num<16 ->
- convert_to_ascii(Reversed,[Num+55|Number]);
-convert_to_ascii(NumReversed,Number) ->
- error.
-
-
-
-getSize(Num)->
- getSize(Num,0).
-
-getSize(Num,Pot)when Num<(16 bsl(Pot *4)) ->
- Pot-1;
-
-getSize(Num,Pot) ->
- getSize(Num,Pot+1).
-
-
-
-
-
-create_etag(FileInfo)->
- create_etag(FileInfo#file_info.mtime,FileInfo#file_info.size).
-
-create_etag({{Year,Month,Day},{Hour,Min,Sec}},Size)->
- create_part([Year,Month,Day,Hour,Min,Sec])++io_lib:write(Size);
-
-create_etag(FileInfo,Size)->
- create_etag(FileInfo#file_info.mtime,Size).
-
-create_part(Values)->
- lists:map(fun(Val0)->
- Val=Val0 rem 60,
- if
- Val=<25 ->
- 65+Val; % A-Z
- Val=<50 ->
- 72+Val; % a-z
- %%Since no date s
- true ->
- Val-3
- end
- end,Values).
-
-
-
-%%----------------------------------------------------------------------
-%%Function that controls whether a response is generated or not
-%%----------------------------------------------------------------------
-response_generated(Info)->
- case httpd_util:key1search(Info#mod.data,status) of
- %% A status code has been generated!
- {StatusCode,PhraseArgs,Reason}->
- true;
- %%No status code control repsonsxe
- undefined ->
- case httpd_util:key1search(Info#mod.data, response) of
- %% No response has been generated!
- undefined ->
- false;
- %% A response has been generated or sent!
- Response ->
- true
- end
- end.
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_verbosity.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_verbosity.erl
deleted file mode 100644
index c772a11dd1..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_verbosity.erl
+++ /dev/null
@@ -1,94 +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: httpd_verbosity.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
-%%
--module(httpd_verbosity).
-
--include_lib("stdlib/include/erl_compile.hrl").
-
--export([print/4,print/5,printc/4,validate/1]).
-
-print(silence,_Severity,_Format,_Arguments) ->
- ok;
-print(Verbosity,Severity,Format,Arguments) ->
- print1(printable(Verbosity,Severity),Format,Arguments).
-
-
-print(silence,_Severity,_Module,_Format,_Arguments) ->
- ok;
-print(Verbosity,Severity,Module,Format,Arguments) ->
- print1(printable(Verbosity,Severity),Module,Format,Arguments).
-
-
-printc(silence,Severity,Format,Arguments) ->
- ok;
-printc(Verbosity,Severity,Format,Arguments) ->
- print2(printable(Verbosity,Severity),Format,Arguments).
-
-
-print1(false,_Format,_Arguments) -> ok;
-print1(Verbosity,Format,Arguments) ->
- V = image_of_verbosity(Verbosity),
- S = image_of_sname(get(sname)),
- io:format("** HTTPD ~s ~s: " ++ Format ++ "~n",[S,V]++Arguments).
-
-print1(false,_Module,_Format,_Arguments) -> ok;
-print1(Verbosity,Module,Format,Arguments) ->
- V = image_of_verbosity(Verbosity),
- S = image_of_sname(get(sname)),
- io:format("** HTTPD ~s ~s ~s: " ++ Format ++ "~n",[S,Module,V]++Arguments).
-
-
-print2(false,_Format,_Arguments) -> ok;
-print2(_Verbosity,Format,Arguments) ->
- io:format(Format ++ "~n",Arguments).
-
-
-%% printable(Verbosity,Severity)
-printable(info,info) -> info;
-printable(log,info) -> info;
-printable(log,log) -> log;
-printable(debug,info) -> info;
-printable(debug,log) -> log;
-printable(debug,debug) -> debug;
-printable(trace,V) -> V;
-printable(_Verb,_Sev) -> false.
-
-
-image_of_verbosity(info) -> "INFO";
-image_of_verbosity(log) -> "LOG";
-image_of_verbosity(debug) -> "DEBUG";
-image_of_verbosity(trace) -> "TRACE";
-image_of_verbosity(_) -> "".
-
-%% ShortName
-image_of_sname(acc) -> "ACCEPTOR";
-image_of_sname(acc_sup) -> "ACCEPTOR_SUP";
-image_of_sname(auth) -> "AUTH";
-image_of_sname(man) -> "MANAGER";
-image_of_sname(misc_sup) -> "MISC_SUP";
-image_of_sname(sec) -> "SECURITY";
-image_of_sname(P) when pid(P) -> io_lib:format("REQUEST_HANDLER(~p)",[P]);
-image_of_sname(undefined) -> "";
-image_of_sname(V) -> io_lib:format("~p",[V]).
-
-
-validate(info) -> info;
-validate(log) -> log;
-validate(debug) -> debug;
-validate(trace) -> trace;
-validate(_) -> silence.
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_verbosity.hrl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_verbosity.hrl
deleted file mode 100644
index caafd8ef18..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/httpd_verbosity.hrl
+++ /dev/null
@@ -1,65 +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: httpd_verbosity.hrl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
-%%
-
--ifndef(dont_use_verbosity).
-
--ifndef(default_verbosity).
--define(default_verbosity,silence).
--endif.
-
--define(vvalidate(V), httpd_verbosity:validate(V)).
-
--ifdef(VMODULE).
-
--define(vinfo(F,A), httpd_verbosity:print(get(verbosity),info, ?VMODULE,F,A)).
--define(vlog(F,A), httpd_verbosity:print(get(verbosity),log, ?VMODULE,F,A)).
--define(vdebug(F,A),httpd_verbosity:print(get(verbosity),debug,?VMODULE,F,A)).
--define(vtrace(F,A),httpd_verbosity:print(get(verbosity),trace,?VMODULE,F,A)).
-
--else.
-
--define(vinfo(F,A), httpd_verbosity:print(get(verbosity),info, F,A)).
--define(vlog(F,A), httpd_verbosity:print(get(verbosity),log, F,A)).
--define(vdebug(F,A),httpd_verbosity:print(get(verbosity),debug,F,A)).
--define(vtrace(F,A),httpd_verbosity:print(get(verbosity),trace,F,A)).
-
--endif.
-
--define(vinfoc(F,A), httpd_verbosity:printc(get(verbosity),info, F,A)).
--define(vlogc(F,A), httpd_verbosity:printc(get(verbosity),log, F,A)).
--define(vdebugc(F,A),httpd_verbosity:printc(get(verbosity),debug,F,A)).
--define(vtracec(F,A),httpd_verbosity:printc(get(verbosity),trace,F,A)).
-
--else.
-
--define(vvalidate(V),ok).
-
--define(vinfo(F,A),ok).
--define(vlog(F,A),ok).
--define(vdebug(F,A),ok).
--define(vtrace(F,A),ok).
-
--define(vinfoc(F,A),ok).
--define(vlogc(F,A),ok).
--define(vdebugc(F,A),ok).
--define(vtracec(F,A),ok).
-
--endif.
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/inets.app.src b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/inets.app.src
deleted file mode 100644
index 1bf5fcc56e..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/inets.app.src
+++ /dev/null
@@ -1,56 +0,0 @@
-{application,inets,
- [{description,"INETS CXC 138 49"},
- {vsn,"%VSN%"},
- {modules,[
- %% FTP
- ftp,
-
- %% HTTP client:
- http,
- http_lib,
- httpc_handler,
- httpc_manager,
- uri,
-
- %% HTTP server:
- httpd,
- httpd_acceptor,
- httpd_acceptor_sup,
- httpd_conf,
- httpd_example,
- httpd_manager,
- httpd_misc_sup,
- httpd_parse,
- httpd_request_handler,
- httpd_response,
- httpd_socket,
- httpd_sup,
- httpd_util,
- httpd_verbosity,
- inets_sup,
- mod_actions,
- mod_alias,
- mod_auth,
- mod_auth_dets,
- mod_auth_mnesia,
- mod_auth_plain,
- mod_auth_server,
- mod_browser,
- mod_cgi,
- mod_dir,
- mod_disk_log,
- mod_esi,
- mod_get,
- mod_head,
- mod_htaccess,
- mod_include,
- mod_log,
- mod_range,
- mod_responsecontrol,
- mod_security,
- mod_security_server,
- mod_trace
- ]},
- {registered,[inets_sup]},
- {applications,[kernel,stdlib]},
- {mod,{inets_sup,[]}}]}.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/inets.appup.src b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/inets.appup.src
deleted file mode 100644
index f612dc5b91..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/inets.appup.src
+++ /dev/null
@@ -1,135 +0,0 @@
-{"%VSN%",
- [{"3.0.5",
- [
- {load_module, ftp, soft_purge, soft_purge, []}
- ]
- },
- {"3.0.4",
- [
- {update, httpd_acceptor, soft, soft_purge, soft_purge, []}
- ]
- },
- {"3.0.3",
- [{load_module, httpd, soft_purge, soft_purge, [httpd_conf, httpd_sup]},
- {load_module, httpd_conf, soft_purge, soft_purge, []},
- {load_module, httpd_socket, soft_purge, soft_purge, []},
- {load_module, httpd_response, soft_purge, soft_purge, [mod_disk_log]},
- {load_module, mod_disk_log, soft_purge, soft_purge, []},
- {update, httpd_acceptor, soft, soft_purge, soft_purge, []},
- {update, httpd_sup, soft, soft_purge, soft_purge, [httpd_manager]},
- {update, httpd_manager, soft, soft_purge, soft_purge,
- [mod_disk_log, httpd_conf, httpd_socket]}]
- },
- {"3.0.2",
- [{load_module, httpd, soft_purge, soft_purge, [httpd_conf, httpd_sup]},
- {load_module, httpd_conf, soft_purge, soft_purge, []},
- {load_module, httpd_socket, soft_purge, soft_purge, []},
- {load_module, mod_disk_log, soft_purge, soft_purge, []},
- {load_module, httpd_response, soft_purge, soft_purge, [mod_disk_log]},
- {update, httpd_sup, soft, soft_purge, soft_purge, [httpd_manager]},
- {update, httpd_acceptor, soft, soft_purge, soft_purge, []},
- {update, httpd_manager, soft, soft_purge, soft_purge,
- [httpd_request_handler, httpd_conf, httpd_socket]},
- {update, httpd_request_handler, soft, soft_purge, soft_purge,
- [httpd_response]}]
- },
- {"3.0.1",
- [{load_module, httpd, soft_purge, soft_purge, [httpd_conf, httpd_sup]},
- {load_module, httpd_conf, soft_purge, soft_purge, []},
- {load_module, httpd_socket, soft_purge, soft_purge, []},
- {load_module, httpd_response, soft_purge, soft_purge,
- [mod_auth, mod_disk_log]},
- {load_module, mod_disk_log, soft_purge, soft_purge, []},
- {load_module, mod_auth, soft_purge, soft_purge, []},
- {update, httpd_sup, soft, soft_purge, soft_purge, [httpd_manager]},
- {update, httpd_acceptor, soft, soft_purge, soft_purge, []},
- {update, httpd_manager, soft, soft_purge, soft_purge,
- [httpd_request_handler, httpd_conf, httpd_socket]},
- {update, httpd_request_handler, soft, soft_purge, soft_purge,
- [httpd_response]}]
- },
- {"3.0",
- [{load_module, httpd, soft_purge, soft_purge, [httpd_conf, httpd_sup]},
- {load_module, httpd_conf, soft_purge, soft_purge, []},
- {load_module, httpd_socket, soft_purge, soft_purge, []},
- {load_module, httpd_response, soft_purge, soft_purge,
- [mod_auth, mod_disk_log]},
- {load_module, mod_disk_log, soft_purge, soft_purge, []},
- {load_module, mod_auth, soft_purge, soft_purge, []},
- {update, httpd_sup, soft, soft_purge, soft_purge,
- [httpd_manager, httpd_misc_sup]},
- {update, httpd_misc_sup, soft, soft_purge, soft_purge, []},
- {update, httpd_acceptor, soft, soft_purge, soft_purge, []},
- {update, httpd_manager, soft, soft_purge, soft_purge,
- [httpd_request_handler, httpd_conf, httpd_socket]},
- {update, httpd_request_handler, soft, soft_purge, soft_purge,
- [httpd_response]}]
- }
- ],
- [{"3.0.5",
- [
- {load_module, ftp, soft_purge, soft_purge, []}
- ]
- },
- {"3.0.4",
- [{update, httpd_acceptor, soft, soft_purge, soft_purge, []}]
- },
- {"3.0.3",
- [{load_module, httpd, soft_purge, soft_purge, [httpd_conf, httpd_sup]},
- {load_module, httpd_conf, soft_purge, soft_purge, []},
- {load_module, httpd_socket, soft_purge, soft_purge, []},
- {load_module, httpd_response, soft_purge, soft_purge, [mod_disk_log]},
- {load_module, mod_disk_log, soft_purge, soft_purge, []},
- {update, httpd_sup, soft, soft_purge, soft_purge, [httpd_manager]},
- {update, httpd_manager, soft, soft_purge, soft_purge,
- [mod_disk_log, httpd_conf, httpd_socket]}]
- },
- {"3.0.2",
- [{load_module, httpd, soft_purge, soft_purge, [httpd_conf, httpd_sup]},
- {load_module, httpd_conf, soft_purge, soft_purge, []},
- {load_module, httpd_socket, soft_purge, soft_purge, []},
- {load_module, httpd_response, soft_purge, soft_purge, [mod_disk_log]},
- {load_module, mod_disk_log, soft_purge, soft_purge, []},
- {update, httpd_sup, soft, soft_purge, soft_purge, [httpd_manager]},
- {update, httpd_acceptor, soft, soft_purge, soft_purge, []},
- {update, httpd_manager, soft, soft_purge, soft_purge,
- [httpd_request_handler, httpd_conf, httpd_socket]},
- {update, httpd_request_handler, soft, soft_purge, soft_purge,
- [httpd_response]}]
- },
- {"3.0.1",
- [{load_module, httpd, soft_purge, soft_purge, [httpd_conf, httpd_sup]},
- {load_module, httpd_conf, soft_purge, soft_purge, []},
- {load_module, httpd_socket, soft_purge, soft_purge, []},
- {load_module, httpd_response, soft_purge, soft_purge,
- [mod_auth, mod_disk_log]},
- {load_module, mod_disk_log, soft_purge, soft_purge, []},
- {load_module, mod_auth, soft_purge, soft_purge, []},
- {update, httpd_sup, soft, soft_purge, soft_purge, [httpd_manager]},
- {update, httpd_acceptor, soft, soft_purge, soft_purge, []},
- {update, httpd_manager, soft, soft_purge, soft_purge,
- [httpd_request_handler, httpd_conf, httpd_socket]},
- {update, httpd_request_handler, soft, soft_purge, soft_purge,
- [httpd_response]}]
- },
- {"3.0",
- [{load_module, httpd, soft_purge, soft_purge, [httpd_conf, httpd_sup]},
- {load_module, httpd_conf, soft_purge, soft_purge, []},
- {load_module, httpd_socket, soft_purge, soft_purge, []},
- {load_module, httpd_response, soft_purge, soft_purge,
- [mod_auth, mod_disk_log]},
- {load_module, mod_disk_log, soft_purge, soft_purge, []},
- {load_module, mod_auth, soft_purge, soft_purge, []},
- {update, httpd_sup, soft, soft_purge, soft_purge,
- [httpd_manager, httpd_misc_sup]},
- {update, httpd_misc_sup, soft, soft_purge, soft_purge, []},
- {update, httpd_acceptor, soft, soft_purge, soft_purge, []},
- {update, httpd_manager, soft, soft_purge, soft_purge,
- [httpd_request_handler, httpd_conf, httpd_socket]},
- {update, httpd_request_handler, soft, soft_purge, soft_purge,
- [httpd_response]}]
- }
- ]
-}.
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/inets.config b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/inets.config
deleted file mode 100644
index adf0e3ecf1..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/inets.config
+++ /dev/null
@@ -1,2 +0,0 @@
-[{inets,[{services,[{httpd,"/var/tmp/server_root/conf/8888.conf"},
- {httpd,"/var/tmp/server_root/conf/8080.conf"}]}]}].
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/inets_sup.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/inets_sup.erl
deleted file mode 100644
index 6bda87148c..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/inets_sup.erl
+++ /dev/null
@@ -1,158 +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: inets_sup.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
-%%
--module(inets_sup).
-
--export([crock/0]).
--export([start/2, stop/1, init/1]).
--export([start_child/2, stop_child/2, which_children/0]).
-
-
-%% crock (Used for debugging!)
-
-crock() ->
- application:start(sasl),
- application:start(inets).
-
-
-%% start
-
-start(Type, State) ->
- supervisor:start_link({local, ?MODULE}, ?MODULE, []).
-
-
-%% stop
-
-stop(State) ->
- ok.
-
-
-%% start_child
-
-start_child(ConfigFile, Verbosity) ->
- {ok, Spec} = httpd_child_spec(ConfigFile, Verbosity),
- supervisor:start_child(?MODULE, Spec).
-
-
-%% stop_child
-
-stop_child(Addr, Port) ->
- Name = {httpd_sup, Addr, Port},
- case supervisor:terminate_child(?MODULE, Name) of
- ok ->
- supervisor:delete_child(?MODULE, Name);
- Error ->
- Error
- end.
-
-
-%% which_children
-
-which_children() ->
- supervisor:which_children(?MODULE).
-
-
-%% init
-
-init([]) ->
- case get_services() of
- {error, Reason} ->
- {error,Reason};
- Services ->
- SupFlags = {one_for_one, 10, 3600},
- {ok, {SupFlags, child_spec(Services, [])}}
- end.
-
-get_services() ->
- case (catch application:get_env(inets, services)) of
- {ok, Services} ->
- Services;
- _ ->
- []
- end.
-
-
-child_spec([], Acc) ->
- Acc;
-child_spec([{httpd, ConfigFile, Verbosity}|Rest], Acc) ->
- case httpd_child_spec(ConfigFile, Verbosity) of
- {ok, Spec} ->
- child_spec(Rest, [Spec | Acc]);
- {error, Reason} ->
- error_msg("Failed creating child spec "
- "using ~p for reason: ~p", [ConfigFile, Reason]),
- child_spec(Rest, Acc)
- end;
-child_spec([{httpd, ConfigFile}|Rest], Acc) ->
- case httpd_child_spec(ConfigFile, []) of
- {ok, Spec} ->
- child_spec(Rest, [Spec | Acc]);
- {error, Reason} ->
- error_msg("Failed creating child spec "
- "using ~p for reason: ~p", [ConfigFile, Reason]),
- child_spec(Rest, Acc)
- end.
-
-
-httpd_child_spec(ConfigFile, Verbosity) ->
- case httpd_conf:load(ConfigFile) of
- {ok, ConfigList} ->
- Port = httpd_util:key1search(ConfigList, port, 80),
- Addr = httpd_util:key1search(ConfigList, bind_address),
- {ok, httpd_child_spec(ConfigFile, Addr, Port, Verbosity)};
- Error ->
- Error
- end.
-
-
-httpd_child_spec(ConfigFile, Addr, Port, Verbosity) ->
- {{httpd_sup, Addr, Port},{httpd_sup, start_link,[ConfigFile, Verbosity]},
- permanent, 20000, supervisor,
- [ftp,
- httpd,
- httpd_conf,
- httpd_example,
- httpd_manager,
- httpd_misc_sup,
- httpd_listener,
- httpd_parse,
- httpd_request,
- httpd_response,
- httpd_socket,
- httpd_sup,
- httpd_util,
- httpd_verbosity,
- inets_sup,
- mod_actions,
- mod_alias,
- mod_auth,
- mod_cgi,
- mod_dir,
- mod_disk_log,
- mod_esi,
- mod_get,
- mod_head,
- mod_include,
- mod_log,
- mod_auth_mnesia,
- mod_auth_plain,
- mod_auth_dets,
- mod_security]}.
-
-
-error_msg(F, A) ->
- error_logger:error_msg(F ++ "~n", A).
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/jnets_httpd.hrl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/jnets_httpd.hrl
deleted file mode 100644
index 721a6b991d..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/jnets_httpd.hrl
+++ /dev/null
@@ -1,138 +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 Mobile Arts AB
-%% Portions created by Mobile Arts are Copyright 2002, Mobile Arts AB
-%% All Rights Reserved.''
-%%
-%%
-
--include_lib("kernel/include/file.hrl").
-
--define(SOCKET_CHUNK_SIZE,8192).
--define(SOCKET_MAX_POLL,25).
--define(FILE_CHUNK_SIZE,64*1024).
--define(NICE(Reason),lists:flatten(atom_to_list(?MODULE)++": "++Reason)).
--define(DEFAULT_CONTEXT,
- [{errmsg,"[an error occurred while processing this directive]"},
- {timefmt,"%A, %d-%b-%y %T %Z"},
- {sizefmt,"abbrev"}]).
-
-
--ifdef(inets_debug).
--define(DEBUG(Format, Args), io:format("D(~p:~p:~p) : "++Format++"~n",
- [self(),?MODULE,?LINE]++Args)).
--else.
--define(DEBUG(F,A),[]).
--endif.
-
--define(MAXBODYSIZE,16#ffffffff).
-
--define(HTTP_VERSION_10,0).
--define(HTTP_VERSION_11,1).
-
--define(CR,13).
--define(LF,10).
-
-
--record(init_data,{peername,resolve}).
-
-
--record(mod,{
- init_data, %
- data= [], % list() Used to propagate data between modules
- socket_type=ip_comm, % socket_type() IP or SSL socket
- socket, % socket() Actual socket
- config_db, % ets() {key,val} db with config entries
- method, % atom() HTTP method, e.g. 'GET'
-% request_uri, % string() Request URI
- path, % string() Absolute path. May include query etc
- http_version, % int() HTTP minor version number, e.g. 0 or 1
-% request_line, % string() Request Line
- headers, % #req_headers{} Parsed request headers
- entity_body= <<>>, % binary() Body of request
- connection, % boolean() true if persistant connection
- status_code, % int() Status code
- logging % int() 0=No logging
- % 1=Only mod_log present
- % 2=Only mod_disk_log present
- % 3=Both mod_log and mod_disk_log present
- }).
-
-% -record(ssl,{
-% certfile, %
-% keyfile, %
-% verify= 0, %
-% ciphers, %
-% password, %
-% depth = 1, %
-% cacertfile, %
-
-% cachetimeout % Found in yaws....
-% }).
-
-
--record(http_request,{
- method, % atom() if known else string() HTTP methd
- path, % {abs_path,string()} URL path
- version % {int(),int()} {Major,Minor} HTTP version
- }).
-
--record(http_response,{
- version, % {int(),int()} {Major,Minor} HTTP version
- status, % int() Status code
- phrase % string() HTTP Reason phrase
- }).
-
-
-%%% Request headers
--record(req_headers,{
-%%% --- Standard "General" headers
-% cache_control,
- connection="keep-alive",
-% date,
-% pragma,
-% trailer,
- transfer_encoding,
-% upgrade,
-% via,
-% warning,
-%%% --- Standard "Request" headers
-% accept,
-% accept_charset,
-% accept_encoding,
-% accept_language,
- authorization,
- expect, %% FIXME! Update inet_drv.c!!
-% from,
- host,
- if_match,
- if_modified_since,
- if_none_match,
- if_range,
- if_unmodified_since,
-% max_forwards,
-% proxy_authorization,
- range,
-% referer,
-% te, %% FIXME! Update inet_drv.c!!
- user_agent,
-%%% --- Standard "Entity" headers
-% content_encoding,
-% content_language,
- content_length="0",
-% content_location,
-% content_md5,
-% content_range,
- content_type,
-% last_modified,
- other=[] % (list) Key/Value list with other headers
- }).
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_actions.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_actions.erl
deleted file mode 100644
index 93bdb9fb40..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_actions.erl
+++ /dev/null
@@ -1,92 +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: mod_actions.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
-%%
--module(mod_actions).
--export([do/1,load/2]).
-
--include("httpd.hrl").
-
-%% do
-
-do(Info) ->
- case httpd_util:key1search(Info#mod.data,status) of
- %% A status code has been generated!
- {StatusCode,PhraseArgs,Reason} ->
- {proceed,Info#mod.data};
- %% No status code has been generated!
- undefined ->
- case httpd_util:key1search(Info#mod.data,response) of
- %% No response has been generated!
- undefined ->
- Path=mod_alias:path(Info#mod.data,Info#mod.config_db,
- Info#mod.request_uri),
- Suffix=httpd_util:suffix(Path),
- MimeType=httpd_util:lookup_mime(Info#mod.config_db,Suffix,
- "text/plain"),
- Actions=httpd_util:multi_lookup(Info#mod.config_db,action),
- case action(Info#mod.request_uri,MimeType,Actions) of
- {yes,RequestURI} ->
- {proceed,[{new_request_uri,RequestURI}|Info#mod.data]};
- no ->
- Scripts=httpd_util:multi_lookup(Info#mod.config_db,script),
- case script(Info#mod.request_uri,Info#mod.method,Scripts) of
- {yes,RequestURI} ->
- {proceed,[{new_request_uri,RequestURI}|Info#mod.data]};
- no ->
- {proceed,Info#mod.data}
- end
- end;
- %% A response has been generated or sent!
- Response ->
- {proceed,Info#mod.data}
- end
- end.
-
-action(RequestURI,MimeType,[]) ->
- no;
-action(RequestURI,MimeType,[{MimeType,CGIScript}|Rest]) ->
- {yes,CGIScript++RequestURI};
-action(RequestURI,MimeType,[_|Rest]) ->
- action(RequestURI,MimeType,Rest).
-
-script(RequestURI,Method,[]) ->
- no;
-script(RequestURI,Method,[{Method,CGIScript}|Rest]) ->
- {yes,CGIScript++RequestURI};
-script(RequestURI,Method,[_|Rest]) ->
- script(RequestURI,Method,Rest).
-
-%%
-%% Configuration
-%%
-
-%% load
-
-load([$A,$c,$t,$i,$o,$n,$ |Action],[]) ->
- case regexp:split(Action," ") of
- {ok,[MimeType,CGIScript]} ->
- {ok,[],{action,{MimeType,CGIScript}}};
- {ok,_} ->
- {error,?NICE(httpd_conf:clean(Action)++" is an invalid Action")}
- end;
-load([$S,$c,$r,$i,$p,$t,$ |Script],[]) ->
- case regexp:split(Script," ") of
- {ok,[Method,CGIScript]} ->
- {ok,[],{script,{Method,CGIScript}}};
- {ok,_} ->
- {error,?NICE(httpd_conf:clean(Script)++" is an invalid Script")}
- end.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_alias.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_alias.erl
deleted file mode 100644
index e01c18b3d6..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_alias.erl
+++ /dev/null
@@ -1,175 +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: mod_alias.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
-%%
--module(mod_alias).
--export([do/1,real_name/3,real_script_name/3,default_index/2,load/2,path/3]).
-
--include("httpd.hrl").
-
-%% do
-
-do(Info) ->
- ?DEBUG("do -> entry",[]),
- case httpd_util:key1search(Info#mod.data,status) of
- %% A status code has been generated!
- {StatusCode,PhraseArgs,Reason} ->
- {proceed,Info#mod.data};
- %% No status code has been generated!
- undefined ->
- case httpd_util:key1search(Info#mod.data,response) of
- %% No response has been generated!
- undefined ->
- do_alias(Info);
- %% A response has been generated or sent!
- Response ->
- {proceed,Info#mod.data}
- end
- end.
-
-do_alias(Info) ->
- ?DEBUG("do_alias -> Request URI: ~p",[Info#mod.request_uri]),
- {ShortPath,Path,AfterPath} =
- real_name(Info#mod.config_db,Info#mod.request_uri,
- httpd_util:multi_lookup(Info#mod.config_db,alias)),
- %% Relocate if a trailing slash is missing else proceed!
- LastChar = lists:last(ShortPath),
- case file:read_file_info(ShortPath) of
- {ok,FileInfo} when FileInfo#file_info.type == directory,LastChar /= $/ ->
- ?LOG("do_alias -> ~n"
- " ShortPath: ~p~n"
- " LastChar: ~p~n"
- " FileInfo: ~p",
- [ShortPath,LastChar,FileInfo]),
- ServerName = httpd_util:lookup(Info#mod.config_db,server_name),
- Port = port_string(httpd_util:lookup(Info#mod.config_db,port,80)),
- URL = "http://"++ServerName++Port++Info#mod.request_uri++"/",
- ReasonPhrase = httpd_util:reason_phrase(301),
- Message = httpd_util:message(301,URL,Info#mod.config_db),
- {proceed,
- [{response,
- {301, ["Location: ", URL, "\r\n"
- "Content-Type: text/html\r\n",
- "\r\n",
- "<HTML>\n<HEAD>\n<TITLE>",ReasonPhrase,
- "</TITLE>\n</HEAD>\n"
- "<BODY>\n<H1>",ReasonPhrase,
- "</H1>\n", Message,
- "\n</BODY>\n</HTML>\n"]}}|
- [{real_name,{Path,AfterPath}}|Info#mod.data]]};
- NoFile ->
- {proceed,[{real_name,{Path,AfterPath}}|Info#mod.data]}
- end.
-
-port_string(80) ->
- "";
-port_string(Port) ->
- ":"++integer_to_list(Port).
-
-%% real_name
-
-real_name(ConfigDB, RequestURI,[]) ->
- DocumentRoot = httpd_util:lookup(ConfigDB, document_root, ""),
- RealName = DocumentRoot++RequestURI,
- {ShortPath, _AfterPath} = httpd_util:split_path(RealName),
- {Path, AfterPath}=httpd_util:split_path(default_index(ConfigDB,RealName)),
- {ShortPath, Path, AfterPath};
-real_name(ConfigDB, RequestURI, [{FakeName,RealName}|Rest]) ->
- case regexp:match(RequestURI, "^"++FakeName) of
- {match, _, _} ->
- {ok, ActualName, _} = regexp:sub(RequestURI,
- "^"++FakeName, RealName),
- {ShortPath, _AfterPath} = httpd_util:split_path(ActualName),
- {Path, AfterPath} =
- httpd_util:split_path(default_index(ConfigDB, ActualName)),
- {ShortPath, Path, AfterPath};
- nomatch ->
- real_name(ConfigDB,RequestURI,Rest)
- end.
-
-%% real_script_name
-
-real_script_name(ConfigDB,RequestURI,[]) ->
- not_a_script;
-real_script_name(ConfigDB,RequestURI,[{FakeName,RealName}|Rest]) ->
- case regexp:match(RequestURI,"^"++FakeName) of
- {match,_,_} ->
- {ok,ActualName,_}=regexp:sub(RequestURI,"^"++FakeName,RealName),
- httpd_util:split_script_path(default_index(ConfigDB,ActualName));
- nomatch ->
- real_script_name(ConfigDB,RequestURI,Rest)
- end.
-
-%% default_index
-
-default_index(ConfigDB, Path) ->
- case file:read_file_info(Path) of
- {ok, FileInfo} when FileInfo#file_info.type == directory ->
- DirectoryIndex = httpd_util:lookup(ConfigDB, directory_index, []),
- append_index(Path, DirectoryIndex);
- _ ->
- Path
- end.
-
-append_index(RealName, []) ->
- RealName;
-append_index(RealName, [Index|Rest]) ->
- case file:read_file_info(filename:join(RealName, Index)) of
- {error,Reason} ->
- append_index(RealName, Rest);
- _ ->
- filename:join(RealName,Index)
- end.
-
-%% path
-
-path(Data, ConfigDB, RequestURI) ->
- case httpd_util:key1search(Data,real_name) of
- undefined ->
- DocumentRoot = httpd_util:lookup(ConfigDB, document_root, ""),
- {Path,AfterPath} =
- httpd_util:split_path(DocumentRoot++RequestURI),
- Path;
- {Path,AfterPath} ->
- Path
- end.
-
-%%
-%% Configuration
-%%
-
-%% load
-
-load([$D,$i,$r,$e,$c,$t,$o,$r,$y,$I,$n,$d,$e,$x,$ |DirectoryIndex],[]) ->
- {ok, DirectoryIndexes} = regexp:split(DirectoryIndex," "),
- {ok,[], {directory_index, DirectoryIndexes}};
-load([$A,$l,$i,$a,$s,$ |Alias],[]) ->
- case regexp:split(Alias," ") of
- {ok, [FakeName, RealName]} ->
- {ok,[],{alias,{FakeName,RealName}}};
- {ok, _} ->
- {error,?NICE(httpd_conf:clean(Alias)++" is an invalid Alias")}
- end;
-load([$S,$c,$r,$i,$p,$t,$A,$l,$i,$a,$s,$ |ScriptAlias],[]) ->
- case regexp:split(ScriptAlias," ") of
- {ok, [FakeName, RealName]} ->
- %% Make sure the path always has a trailing slash..
- RealName1 = filename:join(filename:split(RealName)),
- {ok, [], {script_alias,{FakeName, RealName1++"/"}}};
- {ok, _} ->
- {error, ?NICE(httpd_conf:clean(ScriptAlias)++
- " is an invalid ScriptAlias")}
- end.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth.erl
deleted file mode 100644
index dadb64e3c1..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth.erl
+++ /dev/null
@@ -1,750 +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: mod_auth.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
-%%
--module(mod_auth).
-
-
-%% The functions that the webbserver call on startup stop
-%% and when the server traverse the modules.
--export([do/1, load/2, store/2, remove/1]).
-
-%% User entries to the gen-server.
--export([add_user/2, add_user/5, add_user/6,
- add_group_member/3, add_group_member/4, add_group_member/5,
- list_users/1, list_users/2, list_users/3,
- delete_user/2, delete_user/3, delete_user/4,
- delete_group_member/3, delete_group_member/4, delete_group_member/5,
- list_groups/1, list_groups/2, list_groups/3,
- delete_group/2, delete_group/3, delete_group/4,
- get_user/2, get_user/3, get_user/4,
- list_group_members/2, list_group_members/3, list_group_members/4,
- update_password/6, update_password/5]).
-
--include("httpd.hrl").
--include("mod_auth.hrl").
-
--define(VMODULE,"AUTH").
--include("httpd_verbosity.hrl").
-
--define(NOPASSWORD,"NoPassword").
-
-
-%% do
-do(Info) ->
- ?vtrace("do", []),
- case httpd_util:key1search(Info#mod.data,status) of
- %% A status code has been generated!
- {StatusCode,PhraseArgs,Reason} ->
- {proceed, Info#mod.data};
- %% No status code has been generated!
- undefined ->
- case httpd_util:key1search(Info#mod.data,response) of
- %% No response has been generated!
- undefined ->
- Path = mod_alias:path(Info#mod.data,Info#mod.config_db,
- Info#mod.request_uri),
- %% Is it a secret area?
- case secretp(Path,Info#mod.config_db) of
- {yes, Directory, DirectoryData} ->
- %% Authenticate (allow)
- case allow((Info#mod.init_data)#init_data.peername,
- Info#mod.socket_type,Info#mod.socket,
- DirectoryData) of
- allowed ->
- case deny((Info#mod.init_data)#init_data.peername,
- Info#mod.socket_type, Info#mod.socket,
- DirectoryData) of
- not_denied ->
- case httpd_util:key1search(DirectoryData,
- auth_type) of
- undefined ->
- {proceed, Info#mod.data};
- none ->
- {proceed, Info#mod.data};
- AuthType ->
- do_auth(Info,
- Directory,
- DirectoryData,
- AuthType)
- end;
- {denied, Reason} ->
- {proceed,
- [{status,{403,Info#mod.request_uri,Reason}}|
- Info#mod.data]}
- end;
- {not_allowed, Reason} ->
- {proceed,[{status,{403,Info#mod.request_uri,Reason}}|
- Info#mod.data]}
- end;
- no ->
- {proceed, Info#mod.data}
- end;
- %% A response has been generated or sent!
- Response ->
- {proceed, Info#mod.data}
- end
- end.
-
-
-do_auth(Info, Directory, DirectoryData, AuthType) ->
- %% Authenticate (require)
- case require(Info, Directory, DirectoryData) of
- authorized ->
- {proceed,Info#mod.data};
- {authorized, User} ->
- {proceed, [{remote_user,User}|Info#mod.data]};
- {authorization_failed, Reason} ->
- ?vtrace("do_auth -> authorization_failed: ~p",[Reason]),
- {proceed, [{status,{401,none,Reason}}|Info#mod.data]};
- {authorization_required, Realm} ->
- ?vtrace("do_auth -> authorization_required: ~p",[Realm]),
- ReasonPhrase = httpd_util:reason_phrase(401),
- Message = httpd_util:message(401,none,Info#mod.config_db),
- {proceed,
- [{response,
- {401,
- ["WWW-Authenticate: Basic realm=\"",Realm,
- "\"\r\n\r\n","<HTML>\n<HEAD>\n<TITLE>",
- ReasonPhrase,"</TITLE>\n",
- "</HEAD>\n<BODY>\n<H1>",ReasonPhrase,
- "</H1>\n",Message,"\n</BODY>\n</HTML>\n"]}}|
- Info#mod.data]};
- {status, {StatusCode,PhraseArgs,Reason}} ->
- {proceed, [{status,{StatusCode,PhraseArgs,Reason}}|
- Info#mod.data]}
- end.
-
-
-%% require
-
-require(Info, Directory, DirectoryData) ->
- ParsedHeader = Info#mod.parsed_header,
- ValidUsers = httpd_util:key1search(DirectoryData, require_user),
- ValidGroups = httpd_util:key1search(DirectoryData, require_group),
-
- %% Any user or group restrictions?
- case ValidGroups of
- undefined when ValidUsers == undefined ->
- authorized;
- _ ->
- case httpd_util:key1search(ParsedHeader, "authorization") of
- %% Authorization required!
- undefined ->
- case httpd_util:key1search(DirectoryData, auth_name) of
- undefined ->
- {status,{500,none,?NICE("AuthName directive not specified")}};
- Realm ->
- {authorization_required, Realm}
- end;
- %% Check credentials!
- [$B,$a,$s,$i,$c,$ | EncodedString] ->
- DecodedString = httpd_util:decode_base64(EncodedString),
- case a_valid_user(Info, DecodedString,
- ValidUsers, ValidGroups,
- Directory, DirectoryData) of
- {yes, User} ->
- {authorized, User};
- {no, Reason} ->
- {authorization_failed, Reason};
- {status, {StatusCode,PhraseArgs,Reason}} ->
- {status,{StatusCode,PhraseArgs,Reason}}
- end;
- %% Bad credentials!
- BadCredentials ->
- {status,{401,none,?NICE("Bad credentials "++BadCredentials)}}
- end
- end.
-
-a_valid_user(Info,DecodedString,ValidUsers,ValidGroups,Dir,DirData) ->
- case httpd_util:split(DecodedString,":",2) of
- {ok,[SupposedUser, Password]} ->
- case user_accepted(SupposedUser, ValidUsers) of
- true ->
- check_password(SupposedUser, Password, Dir, DirData);
- false ->
- case group_accepted(Info,SupposedUser,ValidGroups,Dir,DirData) of
- true ->
- check_password(SupposedUser,Password,Dir,DirData);
- false ->
- {no,?NICE("No such user exists")}
- end
- end;
- {ok,BadCredentials} ->
- {status,{401,none,?NICE("Bad credentials "++BadCredentials)}}
- end.
-
-user_accepted(SupposedUser, undefined) ->
- false;
-user_accepted(SupposedUser, ValidUsers) ->
- lists:member(SupposedUser, ValidUsers).
-
-
-group_accepted(Info, User, undefined, Dir, DirData) ->
- false;
-group_accepted(Info, User, [], Dir, DirData) ->
- false;
-group_accepted(Info, User, [Group|Rest], Dir, DirData) ->
- Ret = int_list_group_members(Group, Dir, DirData),
- case Ret of
- {ok, UserList} ->
- case lists:member(User, UserList) of
- true ->
- true;
- false ->
- group_accepted(Info, User, Rest, Dir, DirData)
- end;
- Other ->
- false
- end.
-
-check_password(User, Password, Dir, DirData) ->
- case int_get_user(DirData, User) of
- {ok, UStruct} ->
- case UStruct#httpd_user.password of
- Password ->
- %% FIXME
- {yes, UStruct#httpd_user.username};
- Other ->
- {no, "No such user"} % Don't say 'Bad Password' !!!
- end;
- _ ->
- {no, "No such user"}
- end.
-
-
-%% Middle API. Theese functions call the appropriate authentication module.
-int_get_user(DirData, User) ->
- AuthMod = auth_mod_name(DirData),
- apply(AuthMod, get_user, [DirData, User]).
-
-int_list_group_members(Group, Dir, DirData) ->
- AuthMod = auth_mod_name(DirData),
- apply(AuthMod, list_group_members, [DirData, Group]).
-
-auth_mod_name(DirData) ->
- case httpd_util:key1search(DirData, auth_type, plain) of
- plain -> mod_auth_plain;
- mnesia -> mod_auth_mnesia;
- dets -> mod_auth_dets
- end.
-
-
-%%
-%% Is it a secret area?
-%%
-
-%% secretp
-
-secretp(Path,ConfigDB) ->
- Directories = ets:match(ConfigDB,{directory,'$1','_'}),
- case secret_path(Path, Directories) of
- {yes,Directory} ->
- {yes,Directory,
- lists:flatten(ets:match(ConfigDB,{directory,Directory,'$1'}))};
- no ->
- no
- end.
-
-secret_path(Path,Directories) ->
- secret_path(Path, httpd_util:uniq(lists:sort(Directories)),to_be_found).
-
-secret_path(Path,[],to_be_found) ->
- no;
-secret_path(Path,[],Directory) ->
- {yes,Directory};
-secret_path(Path,[[NewDirectory]|Rest],Directory) ->
- case regexp:match(Path,NewDirectory) of
- {match,_,_} when Directory == to_be_found ->
- secret_path(Path,Rest,NewDirectory);
- {match,_,Length} when Length > length(Directory)->
- secret_path(Path,Rest,NewDirectory);
- {match,_,Length} ->
- secret_path(Path,Rest,Directory);
- nomatch ->
- secret_path(Path,Rest,Directory)
- end.
-
-%%
-%% Authenticate
-%%
-
-%% allow
-
-allow({_,RemoteAddr},SocketType,Socket,DirectoryData) ->
- Hosts = httpd_util:key1search(DirectoryData, allow_from, all),
- case validate_addr(RemoteAddr,Hosts) of
- true ->
- allowed;
- false ->
- {not_allowed, ?NICE("Connection from your host is not allowed")}
- end.
-
-validate_addr(RemoteAddr,all) -> % When called from 'allow'
- true;
-validate_addr(RemoteAddr,none) -> % When called from 'deny'
- false;
-validate_addr(RemoteAddr,[]) ->
- false;
-validate_addr(RemoteAddr,[HostRegExp|Rest]) ->
- ?DEBUG("validate_addr -> RemoteAddr: ~p HostRegExp: ~p",
- [RemoteAddr, HostRegExp]),
- case regexp:match(RemoteAddr, HostRegExp) of
- {match,_,_} ->
- true;
- nomatch ->
- validate_addr(RemoteAddr,Rest)
- end.
-
-%% deny
-
-deny({_,RemoteAddr},SocketType,Socket,DirectoryData) ->
- ?DEBUG("deny -> RemoteAddr: ~p",[RemoteAddr]),
- Hosts = httpd_util:key1search(DirectoryData, deny_from, none),
- ?DEBUG("deny -> Hosts: ~p",[Hosts]),
- case validate_addr(RemoteAddr,Hosts) of
- true ->
- {denied, ?NICE("Connection from your host is not allowed")};
- false ->
- not_denied
- end.
-
-%%
-%% Configuration
-%%
-
-%% load/2
-%%
-
-%% mod_auth recognizes the following Configuration Directives:
-%% <Directory /path/to/directory>
-%% AuthDBType
-%% AuthName
-%% AuthUserFile
-%% AuthGroupFile
-%% AuthAccessPassword
-%% require
-%% allow
-%% </Directory>
-
-%% When a <Directory> directive is found, a new context is set to
-%% [{directory, Directory, DirData}|OtherContext]
-%% DirData in this case is a key-value list of data belonging to the
-%% directory in question.
-%%
-%% When the </Directory> statement is found, the Context created earlier
-%% will be returned as a ConfigList and the context will return to the
-%% state it was previously.
-
-load([$<,$D,$i,$r,$e,$c,$t,$o,$r,$y,$ |Directory],[]) ->
- Dir = httpd_conf:custom_clean(Directory,"",">"),
- {ok,[{directory, Dir, [{path, Dir}]}]};
-load(eof,[{directory,Directory, DirData}|_]) ->
- {error, ?NICE("Premature end-of-file in "++Directory)};
-
-load([$A,$u,$t,$h,$N,$a,$m,$e,$ |AuthName], [{directory,Directory, DirData}|Rest]) ->
- {ok, [{directory,Directory,
- [ {auth_name, httpd_conf:clean(AuthName)}|DirData]} | Rest ]};
-
-load([$A,$u,$t,$h,$U,$s,$e,$r,$F,$i,$l,$e,$ |AuthUserFile0],
- [{directory, Directory, DirData}|Rest]) ->
- AuthUserFile = httpd_conf:clean(AuthUserFile0),
- {ok,[{directory,Directory,
- [ {auth_user_file, AuthUserFile}|DirData]} | Rest ]};
-
-load([$A,$u,$t,$h,$G,$r,$o,$u,$p,$F,$i,$l,$e,$ |AuthGroupFile0],
- [{directory,Directory, DirData}|Rest]) ->
- AuthGroupFile = httpd_conf:clean(AuthGroupFile0),
- {ok,[{directory,Directory,
- [ {auth_group_file, AuthGroupFile}|DirData]} | Rest]};
-
-%AuthAccessPassword
-load([$A,$u,$t,$h,$A,$c,$c,$e,$s,$s,$P,$a,$s,$s,$w,$o,$r,$d,$ |AuthAccessPassword0],
- [{directory,Directory, DirData}|Rest]) ->
- AuthAccessPassword = httpd_conf:clean(AuthAccessPassword0),
- {ok,[{directory,Directory,
- [{auth_access_password, AuthAccessPassword}|DirData]} | Rest]};
-
-
-
-
-load([$A,$u,$t,$h,$D,$B,$T,$y,$p,$e,$ |Type],
- [{directory, Dir, DirData}|Rest]) ->
- case httpd_conf:clean(Type) of
- "plain" ->
- {ok, [{directory, Dir, [{auth_type, plain}|DirData]} | Rest ]};
- "mnesia" ->
- {ok, [{directory, Dir, [{auth_type, mnesia}|DirData]} | Rest ]};
- "dets" ->
- {ok, [{directory, Dir, [{auth_type, dets}|DirData]} | Rest ]};
- _ ->
- {error, ?NICE(httpd_conf:clean(Type)++" is an invalid AuthDBType")}
- end;
-
-load([$r,$e,$q,$u,$i,$r,$e,$ |Require],[{directory,Directory, DirData}|Rest]) ->
- case regexp:split(Require," ") of
- {ok,["user"|Users]} ->
- {ok,[{directory,Directory,
- [{require_user,Users}|DirData]} | Rest]};
- {ok,["group"|Groups]} ->
- {ok,[{directory,Directory,
- [{require_group,Groups}|DirData]} | Rest]};
- {ok,_} ->
- {error,?NICE(httpd_conf:clean(Require)++" is an invalid require")}
- end;
-
-load([$a,$l,$l,$o,$w,$ |Allow],[{directory,Directory, DirData}|Rest]) ->
- case regexp:split(Allow," ") of
- {ok,["from","all"]} ->
- {ok,[{directory,Directory,
- [{allow_from,all}|DirData]} | Rest]};
- {ok,["from"|Hosts]} ->
- {ok,[{directory,Directory,
- [{allow_from,Hosts}|DirData]} | Rest]};
- {ok,_} ->
- {error,?NICE(httpd_conf:clean(Allow)++" is an invalid allow")}
- end;
-
-load([$d,$e,$n,$y,$ |Deny],[{directory,Directory, DirData}|Rest]) ->
- case regexp:split(Deny," ") of
- {ok, ["from", "all"]} ->
- {ok,[{directory, Directory,
- [{deny_from, all}|DirData]} | Rest]};
- {ok, ["from"|Hosts]} ->
- {ok,[{directory, Directory,
- [{deny_from, Hosts}|DirData]} | Rest]};
- {ok, _} ->
- {error,?NICE(httpd_conf:clean(Deny)++" is an invalid deny")}
- end;
-
-load("</Directory>",[{directory,Directory, DirData}|Rest]) ->
- {ok, Rest, {directory, Directory, DirData}};
-
-load([$A,$u,$t,$h,$M,$n,$e,$s,$i,$a,$D,$B,$ |AuthMnesiaDB],
- [{directory, Dir, DirData}|Rest]) ->
- case httpd_conf:clean(AuthMnesiaDB) of
- "On" ->
- {ok,[{directory,Dir,[{auth_type,mnesia}|DirData]}|Rest]};
- "Off" ->
- {ok,[{directory,Dir,[{auth_type,plain}|DirData]}|Rest]};
- _ ->
- {error, ?NICE(httpd_conf:clean(AuthMnesiaDB)++" is an invalid AuthMnesiaDB")}
- end.
-
-%% store
-
-store({directory,Directory0, DirData0}, ConfigList) ->
- Port = httpd_util:key1search(ConfigList, port),
- DirData = case httpd_util:key1search(ConfigList, bind_address) of
- undefined ->
- [{port, Port}|DirData0];
- Addr ->
- [{port, Port},{bind_address,Addr}|DirData0]
- end,
- Directory =
- case filename:pathtype(Directory0) of
- relative ->
- SR = httpd_util:key1search(ConfigList, server_root),
- filename:join(SR, Directory0);
- _ ->
- Directory0
- end,
- AuthMod =
- case httpd_util:key1search(DirData0, auth_type) of
- mnesia -> mod_auth_mnesia;
- dets -> mod_auth_dets;
- plain -> mod_auth_plain;
- _ -> no_module_at_all
- end,
- case AuthMod of
- no_module_at_all ->
- {ok, {directory, Directory, DirData}};
- _ ->
- %% Control that there are a password or add a standard password:
- %% "NoPassword"
- %% In this way a user must select to use a noPassword
- Pwd = case httpd_util:key1search(DirData,auth_access_password)of
- undefined->
- ?NOPASSWORD;
- PassW->
- PassW
- end,
- DirDataLast = lists:keydelete(auth_access_password,1,DirData),
- case catch AuthMod:store_directory_data(Directory, DirDataLast) of
- ok ->
- add_auth_password(Directory,Pwd,ConfigList),
- {ok, {directory, Directory, DirDataLast}};
- {ok, NewDirData} ->
- add_auth_password(Directory,Pwd,ConfigList),
- {ok, {directory, Directory, NewDirData}};
- {error, Reason} ->
- {error, Reason};
- Other ->
- ?ERROR("unexpected result: ~p",[Other]),
- {error, Other}
- end
- end.
-
-
-add_auth_password(Dir, Pwd0, ConfigList) ->
- Addr = httpd_util:key1search(ConfigList, bind_address),
- Port = httpd_util:key1search(ConfigList, port),
- mod_auth_server:start(Addr, Port),
- mod_auth_server:add_password(Addr, Port, Dir, Pwd0).
-
-%% remove
-
-
-remove(ConfigDB) ->
- lists:foreach(fun({directory, Dir, DirData}) ->
- AuthMod = auth_mod_name(DirData),
- (catch apply(AuthMod, remove, [DirData]))
- end,
- ets:match_object(ConfigDB,{directory,'_','_'})),
- Addr = case lookup(ConfigDB, bind_address) of
- [] ->
- undefined;
- [{bind_address, Address}] ->
- Address
- end,
- [{port, Port}] = lookup(ConfigDB, port),
- mod_auth_server:stop(Addr, Port),
- ok.
-
-
-
-
-%% --------------------------------------------------------------------
-
-%% update_password
-
-update_password(Port, Dir, Old, New, New)->
- update_password(undefined, Port, Dir, Old, New, New).
-
-update_password(Addr, Port, Dir, Old, New, New) when list(New) ->
- mod_auth_server:update_password(Addr, Port, Dir, Old, New);
-
-update_password(_Addr, _Port, _Dir, _Old, New, New) ->
- {error, badtype};
-update_password(_Addr, _Port, _Dir, _Old, New, New1) ->
- {error, notqeual}.
-
-
-%% add_user
-
-add_user(UserName, Opt) ->
- case get_options(Opt, mandatory) of
- {Addr, Port, Dir, AuthPwd}->
- case get_options(Opt, userData) of
- {error, Reason}->
- {error, Reason};
- {UserData, Password}->
- User = [#httpd_user{username = UserName,
- password = Password,
- user_data = UserData}],
- mod_auth_server:add_user(Addr, Port, Dir, User, AuthPwd);
- {error, Reason} ->
- {error, Reason}
- end
- end.
-
-
-add_user(UserName, Password, UserData, Port, Dir) ->
- add_user(UserName, Password, UserData, undefined, Port, Dir).
-add_user(UserName, Password, UserData, Addr, Port, Dir) ->
- User = [#httpd_user{username = UserName,
- password = Password,
- user_data = UserData}],
- mod_auth_server:add_user(Addr, Port, Dir, User, ?NOPASSWORD).
-
-
-%% get_user
-
-get_user(UserName, Opt) ->
- case get_options(Opt, mandatory) of
- {Addr, Port, Dir, AuthPwd} ->
- mod_auth_server:get_user(Addr, Port, Dir, UserName, AuthPwd);
- {error, Reason} ->
- {error, Reason}
- end.
-
-get_user(UserName, Port, Dir) ->
- get_user(UserName, undefined, Port, Dir).
-get_user(UserName, Addr, Port, Dir) ->
- mod_auth_server:get_user(Addr, Port, Dir, UserName, ?NOPASSWORD).
-
-
-%% add_group_member
-
-add_group_member(GroupName, UserName, Opt)->
- case get_options(Opt, mandatory) of
- {Addr, Port, Dir, AuthPwd}->
- mod_auth_server:add_group_member(Addr, Port, Dir,
- GroupName, UserName, AuthPwd);
- {error, Reason} ->
- {error, Reason}
- end.
-
-add_group_member(GroupName, UserName, Port, Dir) ->
- add_group_member(GroupName, UserName, undefined, Port, Dir).
-
-add_group_member(GroupName, UserName, Addr, Port, Dir) ->
- mod_auth_server:add_group_member(Addr, Port, Dir,
- GroupName, UserName, ?NOPASSWORD).
-
-
-%% delete_group_member
-
-delete_group_member(GroupName, UserName, Opt) ->
- case get_options(Opt, mandatory) of
- {Addr, Port, Dir, AuthPwd} ->
- mod_auth_server:delete_group_member(Addr, Port, Dir,
- GroupName, UserName, AuthPwd);
- {error, Reason} ->
- {error, Reason}
- end.
-
-delete_group_member(GroupName, UserName, Port, Dir) ->
- delete_group_member(GroupName, UserName, undefined, Port, Dir).
-delete_group_member(GroupName, UserName, Addr, Port, Dir) ->
- mod_auth_server:delete_group_member(Addr, Port, Dir,
- GroupName, UserName, ?NOPASSWORD).
-
-
-%% list_users
-
-list_users(Opt) ->
- case get_options(Opt, mandatory) of
- {Addr, Port, Dir, AuthPwd} ->
- mod_auth_server:list_users(Addr, Port, Dir, AuthPwd);
- {error, Reason} ->
- {error, Reason}
- end.
-
-list_users(Port, Dir) ->
- list_users(undefined, Port, Dir).
-list_users(Addr, Port, Dir) ->
- mod_auth_server:list_users(Addr, Port, Dir, ?NOPASSWORD).
-
-
-%% delete_user
-
-delete_user(UserName, Opt) ->
- case get_options(Opt, mandatory) of
- {Addr, Port, Dir, AuthPwd} ->
- mod_auth_server:delete_user(Addr, Port, Dir, UserName, AuthPwd);
- {error, Reason} ->
- {error, Reason}
- end.
-
-delete_user(UserName, Port, Dir) ->
- delete_user(UserName, undefined, Port, Dir).
-delete_user(UserName, Addr, Port, Dir) ->
- mod_auth_server:delete_user(Addr, Port, Dir, UserName, ?NOPASSWORD).
-
-
-%% delete_group
-
-delete_group(GroupName, Opt) ->
- case get_options(Opt, mandatory) of
- {Addr, Port, Dir, AuthPwd}->
- mod_auth_server:delete_group(Addr, Port, Dir, GroupName, AuthPwd);
- {error, Reason} ->
- {error, Reason}
- end.
-
-delete_group(GroupName, Port, Dir) ->
- delete_group(GroupName, undefined, Port, Dir).
-delete_group(GroupName, Addr, Port, Dir) ->
- mod_auth_server:delete_group(Addr, Port, Dir, GroupName, ?NOPASSWORD).
-
-
-%% list_groups
-
-list_groups(Opt) ->
- case get_options(Opt, mandatory) of
- {Addr, Port, Dir, AuthPwd}->
- mod_auth_server:list_groups(Addr, Port, Dir, AuthPwd);
- {error, Reason} ->
- {error, Reason}
- end.
-
-list_groups(Port, Dir) ->
- list_groups(undefined, Port, Dir).
-list_groups(Addr, Port, Dir) ->
- mod_auth_server:list_groups(Addr, Port, Dir, ?NOPASSWORD).
-
-
-%% list_group_members
-
-list_group_members(GroupName,Opt) ->
- case get_options(Opt, mandatory) of
- {Addr, Port, Dir, AuthPwd} ->
- mod_auth_server:list_group_members(Addr, Port, Dir, GroupName,
- AuthPwd);
- {error, Reason} ->
- {error, Reason}
- end.
-
-list_group_members(GroupName, Port, Dir) ->
- list_group_members(GroupName, undefined, Port, Dir).
-list_group_members(GroupName, Addr, Port, Dir) ->
- mod_auth_server:list_group_members(Addr, Port, Dir, GroupName, ?NOPASSWORD).
-
-
-
-%% Opt = [{port, Port},
-%% {addr, Addr},
-%% {dir, Dir},
-%% {authPassword, AuthPassword} | FunctionSpecificData]
-get_options(Opt, mandatory)->
- case httpd_util:key1search(Opt, port, undefined) of
- Port when integer(Port) ->
- case httpd_util:key1search(Opt, dir, undefined) of
- Dir when list(Dir) ->
- Addr = httpd_util:key1search(Opt,
- addr,
- undefined),
- AuthPwd = httpd_util:key1search(Opt,
- authPassword,
- ?NOPASSWORD),
- {Addr, Port, Dir, AuthPwd};
- _->
- {error, bad_dir}
- end;
- _ ->
- {error, bad_dir}
- end;
-
-%% FunctionSpecificData = {userData, UserData} | {password, Password}
-get_options(Opt, userData)->
- case httpd_util:key1search(Opt, userData, undefined) of
- undefined ->
- {error, no_userdata};
- UserData ->
- case httpd_util:key1search(Opt, password, undefined) of
- undefined->
- {error, no_password};
- Pwd ->
- {UserData, Pwd}
- end
- end.
-
-
-lookup(Db, Key) ->
- ets:lookup(Db, Key).
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth.hrl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth.hrl
deleted file mode 100644
index ed3f437e60..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth.hrl
+++ /dev/null
@@ -1,27 +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: mod_auth.hrl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
-%%
-
--record(httpd_user,
- {username,
- password,
- user_data}).
-
--record(httpd_group,
- {name,
- userlist}).
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth_dets.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth_dets.erl
deleted file mode 100644
index 89d8574e83..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth_dets.erl
+++ /dev/null
@@ -1,222 +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: mod_auth_dets.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
-%%
--module(mod_auth_dets).
-
-%% dets authentication storage
-
--export([get_user/2,
- list_group_members/2,
- add_user/2,
- add_group_member/3,
- list_users/1,
- delete_user/2,
- list_groups/1,
- delete_group_member/3,
- delete_group/2,
- remove/1]).
-
--export([store_directory_data/2]).
-
--include("httpd.hrl").
--include("mod_auth.hrl").
-
-store_directory_data(Directory, DirData) ->
- ?CDEBUG("store_directory_data -> ~n"
- " Directory: ~p~n"
- " DirData: ~p",
- [Directory, DirData]),
-
- PWFile = httpd_util:key1search(DirData, auth_user_file),
- GroupFile = httpd_util:key1search(DirData, auth_group_file),
- Addr = httpd_util:key1search(DirData, bind_address),
- Port = httpd_util:key1search(DirData, port),
-
- PWName = httpd_util:make_name("httpd_dets_pwdb",Addr,Port),
- case dets:open_file(PWName,[{type,set},{file,PWFile},{repair,true}]) of
- {ok, PWDB} ->
- GDBName = httpd_util:make_name("httpd_dets_groupdb",Addr,Port),
- case dets:open_file(GDBName,[{type,set},{file,GroupFile},{repair,true}]) of
- {ok, GDB} ->
- NDD1 = lists:keyreplace(auth_user_file, 1, DirData,
- {auth_user_file, PWDB}),
- NDD2 = lists:keyreplace(auth_group_file, 1, NDD1,
- {auth_group_file, GDB}),
- {ok, NDD2};
- {error, Err}->
- {error, {{file, GroupFile},Err}}
- end;
- {error, Err2} ->
- {error, {{file, PWFile},Err2}}
- end.
-
-%%
-%% Storage format of users in the dets table:
-%% {{UserName, Addr, Port, Dir}, Password, UserData}
-%%
-
-add_user(DirData, UStruct) ->
- {Addr, Port, Dir} = lookup_common(DirData),
- PWDB = httpd_util:key1search(DirData, auth_user_file),
- Record = {{UStruct#httpd_user.username, Addr, Port, Dir},
- UStruct#httpd_user.password, UStruct#httpd_user.user_data},
- case dets:lookup(PWDB, UStruct#httpd_user.username) of
- [Record] ->
- {error, user_already_in_db};
- _ ->
- dets:insert(PWDB, Record),
- true
- end.
-
-get_user(DirData, UserName) ->
- {Addr, Port, Dir} = lookup_common(DirData),
- PWDB = httpd_util:key1search(DirData, auth_user_file),
- User = {UserName, Addr, Port, Dir},
- case dets:lookup(PWDB, User) of
- [{User, Password, UserData}] ->
- {ok, #httpd_user{username=UserName, password=Password, user_data=UserData}};
- Other ->
- {error, no_such_user}
- end.
-
-list_users(DirData) ->
- ?DEBUG("list_users -> ~n"
- " DirData: ~p", [DirData]),
- {Addr, Port, Dir} = lookup_common(DirData),
- PWDB = httpd_util:key1search(DirData, auth_user_file),
- case dets:traverse(PWDB, fun(X) -> {continue, X} end) of %% SOOOO Ugly !
- Records when list(Records) ->
- ?DEBUG("list_users -> ~n"
- " Records: ~p", [Records]),
- {ok, [UserName || {{UserName, AnyAddr, AnyPort, AnyDir}, Password, _Data} <- Records,
- AnyAddr == Addr, AnyPort == Port, AnyDir == Dir]};
- O ->
- ?DEBUG("list_users -> ~n"
- " O: ~p", [O]),
- {ok, []}
- end.
-
-delete_user(DirData, UserName) ->
- {Addr, Port, Dir} = lookup_common(DirData),
- PWDB = httpd_util:key1search(DirData, auth_user_file),
- User = {UserName, Addr, Port, Dir},
- case dets:lookup(PWDB, User) of
- [{User, SomePassword, UserData}] ->
- dets:delete(PWDB, User),
- lists:foreach(fun(Group) -> delete_group_member(DirData, Group, UserName) end,
- list_groups(DirData)),
- true;
- _ ->
- {error, no_such_user}
- end.
-
-%%
-%% Storage of groups in the dets table:
-%% {Group, UserList} where UserList is a list of strings.
-%%
-add_group_member(DirData, GroupName, UserName) ->
- {Addr, Port, Dir} = lookup_common(DirData),
- GDB = httpd_util:key1search(DirData, auth_group_file),
- Group = {GroupName, Addr, Port, Dir},
- case dets:lookup(GDB, Group) of
- [{Group, Users}] ->
- case lists:member(UserName, Users) of
- true ->
- true;
- false ->
- dets:insert(GDB, {Group, [UserName|Users]}),
- true
- end;
- [] ->
- dets:insert(GDB, {Group, [UserName]}),
- true;
- Other ->
- {error, Other}
- end.
-
-list_group_members(DirData, GroupName) ->
- {Addr, Port, Dir} = lookup_common(DirData),
- GDB = httpd_util:key1search(DirData, auth_group_file),
- Group = {GroupName, Addr, Port, Dir},
- case dets:lookup(GDB, Group) of
- [{Group, Users}] ->
- {ok, Users};
- Other ->
- {error, no_such_group}
- end.
-
-list_groups(DirData) ->
- {Addr, Port, Dir} = lookup_common(DirData),
- GDB = httpd_util:key1search(DirData, auth_group_file),
- case dets:match(GDB, {'$1', '_'}) of
- [] ->
- {ok, []};
- List when list(List) ->
- Groups = lists:flatten(List),
- {ok, [GroupName || {GroupName, AnyAddr, AnyPort, AnyDir} <- Groups,
- AnyAddr == Addr, AnyPort == Port, AnyDir == Dir]};
- _ ->
- {ok, []}
- end.
-
-delete_group_member(DirData, GroupName, UserName) ->
- {Addr, Port, Dir} = lookup_common(DirData),
- GDB = httpd_util:key1search(DirData, auth_group_file),
- Group = {GroupName, Addr, Port, Dir},
- case dets:lookup(GDB, GroupName) of
- [{Group, Users}] ->
- case lists:member(UserName, Users) of
- true ->
- dets:delete(GDB, Group),
- dets:insert(GDB, {Group,
- lists:delete(UserName, Users)}),
- true;
- false ->
- {error, no_such_group_member}
- end;
- _ ->
- {error, no_such_group}
- end.
-
-delete_group(DirData, GroupName) ->
- {Addr, Port, Dir} = lookup_common(DirData),
- GDB = httpd_util:key1search(DirData, auth_group_file),
- Group = {GroupName, Addr, Port, Dir},
- case dets:lookup(GDB, Group) of
- [{Group, Users}] ->
- dets:delete(GDB, Group),
- true;
- _ ->
- {error, no_such_group}
- end.
-
-lookup_common(DirData) ->
- Dir = httpd_util:key1search(DirData, path),
- Port = httpd_util:key1search(DirData, port),
- Addr = httpd_util:key1search(DirData, bind_address),
- {Addr, Port, Dir}.
-
-%% remove/1
-%%
-%% Closes dets tables used by this auth mod.
-%%
-remove(DirData) ->
- PWDB = httpd_util:key1search(DirData, auth_user_file),
- GDB = httpd_util:key1search(DirData, auth_group_file),
- dets:close(GDB),
- dets:close(PWDB),
- ok.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth_mnesia.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth_mnesia.erl
deleted file mode 100644
index ec29022da0..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth_mnesia.erl
+++ /dev/null
@@ -1,276 +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: mod_auth_mnesia.erl,v 1.2 2010/03/04 13:54:19 maria Exp $
-%%
--module(mod_auth_mnesia).
--export([get_user/2,
- list_group_members/2,
- add_user/2,
- add_group_member/3,
- list_users/1,
- delete_user/2,
- list_groups/1,
- delete_group_member/3,
- delete_group/2]).
-
--export([store_user/5, store_user/6,
- store_group_member/5, store_group_member/6,
- list_group_members/3, list_group_members/4,
- list_groups/2, list_groups/3,
- list_users/2, list_users/3,
- remove_user/4, remove_user/5,
- remove_group_member/5, remove_group_member/6,
- remove_group/4, remove_group/5]).
-
--export([store_directory_data/2]).
-
--include("httpd.hrl").
--include("mod_auth.hrl").
-
-
-
-store_directory_data(Directory, DirData) ->
- %% We don't need to do anything here, we could ofcourse check that the appropriate
- %% mnesia tables has been created prior to starting the http server.
- ok.
-
-
-%%
-%% API
-%%
-
-%% Compability API
-
-
-store_user(UserName, Password, Port, Dir, AccessPassword) ->
- %% AccessPassword is ignored - was not used in previous version
- DirData = [{path,Dir},{port,Port}],
- UStruct = #httpd_user{username = UserName,
- password = Password},
- add_user(DirData, UStruct).
-
-store_user(UserName, Password, Addr, Port, Dir, AccessPassword) ->
- %% AccessPassword is ignored - was not used in previous version
- DirData = [{path,Dir},{bind_address,Addr},{port,Port}],
- UStruct = #httpd_user{username = UserName,
- password = Password},
- add_user(DirData, UStruct).
-
-store_group_member(GroupName, UserName, Port, Dir, AccessPassword) ->
- DirData = [{path,Dir},{port,Port}],
- add_group_member(DirData, GroupName, UserName).
-
-store_group_member(GroupName, UserName, Addr, Port, Dir, AccessPassword) ->
- DirData = [{path,Dir},{bind_address,Addr},{port,Port}],
- add_group_member(DirData, GroupName, UserName).
-
-list_group_members(GroupName, Port, Dir) ->
- DirData = [{path,Dir},{port,Port}],
- list_group_members(DirData, GroupName).
-
-list_group_members(GroupName, Addr, Port, Dir) ->
- DirData = [{path,Dir},{bind_address,Addr},{port,Port}],
- list_group_members(DirData, GroupName).
-
-list_groups(Port, Dir) ->
- DirData = [{path,Dir},{port,Port}],
- list_groups(DirData).
-
-list_groups(Addr, Port, Dir) ->
- DirData = [{path,Dir},{bind_address,Addr},{port,Port}],
- list_groups(DirData).
-
-list_users(Port, Dir) ->
- DirData = [{path,Dir},{port,Port}],
- list_users(DirData).
-
-list_users(Addr, Port, Dir) ->
- DirData = [{path,Dir},{bind_address,Addr},{port,Port}],
- list_users(DirData).
-
-remove_user(UserName, Port, Dir, _AccessPassword) ->
- DirData = [{path,Dir},{port,Port}],
- delete_user(DirData, UserName).
-
-remove_user(UserName, Addr, Port, Dir, _AccessPassword) ->
- DirData = [{path,Dir},{bind_address,Addr},{port,Port}],
- delete_user(DirData, UserName).
-
-remove_group_member(GroupName,UserName,Port,Dir,_AccessPassword) ->
- DirData = [{path,Dir},{port,Port}],
- delete_group_member(DirData, GroupName, UserName).
-
-remove_group_member(GroupName,UserName,Addr,Port,Dir,_AccessPassword) ->
- DirData = [{path,Dir},{bind_address,Addr},{port,Port}],
- delete_group_member(DirData, GroupName, UserName).
-
-remove_group(GroupName,Port,Dir,_AccessPassword) ->
- DirData = [{path,Dir},{port,Port}],
- delete_group(DirData, GroupName).
-
-remove_group(GroupName,Addr,Port,Dir,_AccessPassword) ->
- DirData = [{path,Dir},{bind_address,Addr},{port,Port}],
- delete_group(DirData, GroupName).
-
-%%
-%% Storage format of users in the mnesia table:
-%% httpd_user records
-%%
-
-add_user(DirData, UStruct) ->
- {Addr, Port, Dir} = lookup_common(DirData),
- UserName = UStruct#httpd_user.username,
- Password = UStruct#httpd_user.password,
- Data = UStruct#httpd_user.user_data,
- User=#httpd_user{username={UserName,Addr,Port,Dir},
- password=Password,
- user_data=Data},
- case mnesia:transaction(fun() -> mnesia:write(User) end) of
- {aborted,Reason} ->
- {error,Reason};
- _ ->
- true
- end.
-
-get_user(DirData, UserName) ->
- {Addr, Port, Dir} = lookup_common(DirData),
- case mnesia:transaction(fun() ->
- mnesia:read({httpd_user,
- {UserName,Addr,Port,Dir}})
- end) of
- {aborted,Reason} ->
- {error, Reason};
- {'atomic',[]} ->
- {error, no_such_user};
- {'atomic', [Record]} when record(Record, httpd_user) ->
- {ok, Record#httpd_user{username=UserName}};
- Other ->
- {error, no_such_user}
- end.
-
-list_users(DirData) ->
- {Addr, Port, Dir} = lookup_common(DirData),
- case mnesia:transaction(fun() ->
- mnesia:match_object({httpd_user,
- {'_',Addr,Port,Dir},'_','_'})
- end) of
- {aborted,Reason} ->
- {error,Reason};
- {'atomic',Users} ->
- {ok,
- lists:foldr(fun({httpd_user, {UserName, AnyAddr, AnyPort, AnyDir},
- Password, Data}, Acc) ->
- [UserName|Acc]
- end,
- [], Users)}
- end.
-
-delete_user(DirData, UserName) ->
- {Addr, Port, Dir} = lookup_common(DirData),
- case mnesia:transaction(fun() ->
- mnesia:delete({httpd_user,
- {UserName,Addr,Port,Dir}})
- end) of
- {aborted,Reason} ->
- {error,Reason};
- _ ->
- true
- end.
-
-%%
-%% Storage of groups in the mnesia table:
-%% Multiple instances of {#httpd_group, User}
-%%
-
-add_group_member(DirData, GroupName, User) ->
- {Addr, Port, Dir} = lookup_common(DirData),
- Group=#httpd_group{name={GroupName, Addr, Port, Dir}, userlist=User},
- case mnesia:transaction(fun() -> mnesia:write(Group) end) of
- {aborted,Reason} ->
- {error,Reason};
- _ ->
- true
- end.
-
-list_group_members(DirData, GroupName) ->
- {Addr, Port, Dir} = lookup_common(DirData),
- case mnesia:transaction(fun() ->
- mnesia:read({httpd_group,
- {GroupName,Addr,Port,Dir}})
- end) of
- {aborted, Reason} ->
- {error,Reason};
- {'atomic', Members} ->
- {ok,[UserName || {httpd_group,{AnyGroupName,AnyAddr,AnyPort,AnyDir},UserName} <- Members,
- AnyGroupName == GroupName, AnyAddr == Addr,
- AnyPort == Port, AnyDir == Dir]}
- end.
-
-list_groups(DirData) ->
- {Addr, Port, Dir} = lookup_common(DirData),
- case mnesia:transaction(fun() ->
- mnesia:match_object({httpd_group,
- {'_',Addr,Port,Dir},'_'})
- end) of
- {aborted, Reason} ->
- {error, Reason};
- {'atomic', Groups} ->
- GroupNames=
- [GroupName || {httpd_group,{GroupName,AnyAddr,AnyPort,AnyDir}, UserName} <- Groups,
- AnyAddr == Addr, AnyPort == AnyPort, AnyDir == Dir],
- {ok, httpd_util:uniq(lists:sort(GroupNames))}
- end.
-
-delete_group_member(DirData, GroupName, UserName) ->
- {Addr, Port, Dir} = lookup_common(DirData),
- Group = #httpd_group{name={GroupName, Addr, Port, Dir}, userlist=UserName},
- case mnesia:transaction(fun() -> mnesia:delete_object(Group) end) of
- {aborted,Reason} ->
- {error,Reason};
- _ ->
- true
- end.
-
-%% THIS IS WRONG (?) !
-%% Should first match out all httpd_group records for this group and then
-%% do mnesia:delete on those. Or ?
-
-delete_group(DirData, GroupName) ->
- {Addr, Port, Dir} = lookup_common(DirData),
- case mnesia:transaction(fun() ->
- mnesia:delete({httpd_group,
- {GroupName,Addr,Port,Dir}})
- end) of
- {aborted,Reason} ->
- {error,Reason};
- _ ->
- true
- end.
-
-%% Utility functions.
-
-lookup_common(DirData) ->
- Dir = httpd_util:key1search(DirData, path),
- Port = httpd_util:key1search(DirData, port),
- Addr = httpd_util:key1search(DirData, bind_address),
- {Addr, Port, Dir}.
-
-
-
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth_plain.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth_plain.erl
deleted file mode 100644
index 2f92dcb446..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth_plain.erl
+++ /dev/null
@@ -1,344 +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: mod_auth_plain.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
-%%
--module(mod_auth_plain).
-
--include("httpd.hrl").
--include("mod_auth.hrl").
-
--define(VMODULE,"AUTH_PLAIN").
--include("httpd_verbosity.hrl").
-
-
-%% Internal API
--export([store_directory_data/2]).
-
-
--export([get_user/2,
- list_group_members/2,
- add_user/2,
- add_group_member/3,
- list_users/1,
- delete_user/2,
- list_groups/1,
- delete_group_member/3,
- delete_group/2,
- remove/1]).
-
-%%
-%% API
-%%
-
-%%
-%% Storage format of users in the ets table:
-%% {UserName, Password, UserData}
-%%
-
-add_user(DirData, #httpd_user{username = User} = UStruct) ->
- ?vtrace("add_user -> entry with:"
- "~n User: ~p",[User]),
- PWDB = httpd_util:key1search(DirData, auth_user_file),
- Record = {User,
- UStruct#httpd_user.password,
- UStruct#httpd_user.user_data},
- case ets:lookup(PWDB, User) of
- [{User, _SomePassword, _SomeData}] ->
- {error, user_already_in_db};
- _ ->
- ets:insert(PWDB, Record),
- true
- end.
-
-get_user(DirData, User) ->
- ?vtrace("get_user -> entry with:"
- "~n User: ~p",[User]),
- PWDB = httpd_util:key1search(DirData, auth_user_file),
- case ets:lookup(PWDB, User) of
- [{User, PassWd, Data}] ->
- {ok, #httpd_user{username=User, password=PassWd, user_data=Data}};
- _ ->
- {error, no_such_user}
- end.
-
-list_users(DirData) ->
- PWDB = httpd_util:key1search(DirData, auth_user_file),
- case ets:match(PWDB, '$1') of
- Records when list(Records) ->
- {ok, lists:foldr(fun({User,PassWd,Data}, A) -> [User|A] end,
- [], lists:flatten(Records))};
- O ->
- {ok, []}
- end.
-
-delete_user(DirData, UserName) ->
- ?vtrace("delete_user -> entry with:"
- "~n UserName: ~p",[UserName]),
- PWDB = httpd_util:key1search(DirData, auth_user_file),
- case ets:lookup(PWDB, UserName) of
- [{UserName, SomePassword, SomeData}] ->
- ets:delete(PWDB, UserName),
- case list_groups(DirData) of
- {ok,Groups}->
- lists:foreach(fun(Group) ->
- delete_group_member(DirData, Group, UserName)
- end,Groups),
- true;
- _->
- true
- end;
- _ ->
- {error, no_such_user}
- end.
-
-%%
-%% Storage of groups in the ets table:
-%% {Group, UserList} where UserList is a list of strings.
-%%
-
-add_group_member(DirData, Group, UserName) ->
- ?DEBUG("add_group_members -> ~n"
- " Group: ~p~n"
- " UserName: ~p",[Group,UserName]),
- GDB = httpd_util:key1search(DirData, auth_group_file),
- case ets:lookup(GDB, Group) of
- [{Group, Users}] ->
- case lists:member(UserName, Users) of
- true ->
- ?DEBUG("add_group_members -> already member in group",[]),
- true;
- false ->
- ?DEBUG("add_group_members -> add",[]),
- ets:insert(GDB, {Group, [UserName|Users]}),
- true
- end;
- [] ->
- ?DEBUG("add_group_members -> create grouo",[]),
- ets:insert(GDB, {Group, [UserName]}),
- true;
- Other ->
- ?ERROR("add_group_members -> Other: ~p",[Other]),
- {error, Other}
- end.
-
-list_group_members(DirData, Group) ->
- ?DEBUG("list_group_members -> Group: ~p",[Group]),
- GDB = httpd_util:key1search(DirData, auth_group_file),
- case ets:lookup(GDB, Group) of
- [{Group, Users}] ->
- ?DEBUG("list_group_members -> Users: ~p",[Users]),
- {ok, Users};
- _ ->
- {error, no_such_group}
- end.
-
-list_groups(DirData) ->
- ?DEBUG("list_groups -> entry",[]),
- GDB = httpd_util:key1search(DirData, auth_group_file),
- case ets:match(GDB, '$1') of
- [] ->
- ?DEBUG("list_groups -> []",[]),
- {ok, []};
- Groups0 when list(Groups0) ->
- ?DEBUG("list_groups -> Groups0: ~p",[Groups0]),
- {ok, httpd_util:uniq(lists:foldr(fun({G, U}, A) -> [G|A] end,
- [], lists:flatten(Groups0)))};
- _ ->
- {ok, []}
- end.
-
-delete_group_member(DirData, Group, User) ->
- ?DEBUG("list_group_members -> ~n"
- " Group: ~p~n"
- " User: ~p",[Group,User]),
- GDB = httpd_util:key1search(DirData, auth_group_file),
- UDB = httpd_util:key1search(DirData, auth_user_file),
- case ets:lookup(GDB, Group) of
- [{Group, Users}] when list(Users) ->
- case lists:member(User, Users) of
- true ->
- ?DEBUG("list_group_members -> deleted from group",[]),
- ets:delete(GDB, Group),
- ets:insert(GDB, {Group, lists:delete(User, Users)}),
- true;
- false ->
- ?DEBUG("list_group_members -> not member",[]),
- {error, no_such_group_member}
- end;
- _ ->
- ?ERROR("list_group_members -> no such group",[]),
- {error, no_such_group}
- end.
-
-delete_group(DirData, Group) ->
- ?DEBUG("list_group_members -> Group: ~p",[Group]),
- GDB = httpd_util:key1search(DirData, auth_group_file),
- case ets:lookup(GDB, Group) of
- [{Group, Users}] ->
- ?DEBUG("list_group_members -> delete",[]),
- ets:delete(GDB, Group),
- true;
- _ ->
- ?ERROR("delete_group -> no such group",[]),
- {error, no_such_group}
- end.
-
-
-store_directory_data(Directory, DirData) ->
- PWFile = httpd_util:key1search(DirData, auth_user_file),
- GroupFile = httpd_util:key1search(DirData, auth_group_file),
- case load_passwd(PWFile) of
- {ok, PWDB} ->
- case load_group(GroupFile) of
- {ok, GRDB} ->
- %% Address and port is included in the file names...
- Addr = httpd_util:key1search(DirData, bind_address),
- Port = httpd_util:key1search(DirData, port),
- {ok, PasswdDB} = store_passwd(Addr,Port,PWDB),
- {ok, GroupDB} = store_group(Addr,Port,GRDB),
- NDD1 = lists:keyreplace(auth_user_file, 1, DirData,
- {auth_user_file, PasswdDB}),
- NDD2 = lists:keyreplace(auth_group_file, 1, NDD1,
- {auth_group_file, GroupDB}),
- {ok, NDD2};
- Err ->
- ?ERROR("failed storing directory data: "
- "load group error: ~p",[Err]),
- {error, Err}
- end;
- Err2 ->
- ?ERROR("failed storing directory data: "
- "load passwd error: ~p",[Err2]),
- {error, Err2}
- end.
-
-
-
-%% load_passwd
-
-load_passwd(AuthUserFile) ->
- case file:open(AuthUserFile, [read]) of
- {ok,Stream} ->
- parse_passwd(Stream, []);
- {error, _} ->
- {error, ?NICE("Can't open "++AuthUserFile)}
- end.
-
-parse_passwd(Stream,PasswdList) ->
- Line =
- case io:get_line(Stream, '') of
- eof ->
- eof;
- String ->
- httpd_conf:clean(String)
- end,
- parse_passwd(Stream, PasswdList, Line).
-
-parse_passwd(Stream, PasswdList, eof) ->
- file:close(Stream),
- {ok, PasswdList};
-parse_passwd(Stream, PasswdList, "") ->
- parse_passwd(Stream, PasswdList);
-parse_passwd(Stream, PasswdList, [$#|_]) ->
- parse_passwd(Stream, PasswdList);
-parse_passwd(Stream, PasswdList, Line) ->
- case regexp:split(Line,":") of
- {ok, [User,Password]} ->
- parse_passwd(Stream, [{User,Password, []}|PasswdList]);
- {ok,_} ->
- {error, ?NICE(Line)}
- end.
-
-%% load_group
-
-load_group(AuthGroupFile) ->
- case file:open(AuthGroupFile, [read]) of
- {ok, Stream} ->
- parse_group(Stream,[]);
- {error, _} ->
- {error, ?NICE("Can't open "++AuthGroupFile)}
- end.
-
-parse_group(Stream, GroupList) ->
- Line=
- case io:get_line(Stream,'') of
- eof ->
- eof;
- String ->
- httpd_conf:clean(String)
- end,
- parse_group(Stream, GroupList, Line).
-
-parse_group(Stream, GroupList, eof) ->
- file:close(Stream),
- {ok, GroupList};
-parse_group(Stream, GroupList, "") ->
- parse_group(Stream, GroupList);
-parse_group(Stream, GroupList, [$#|_]) ->
- parse_group(Stream, GroupList);
-parse_group(Stream, GroupList, Line) ->
- case regexp:split(Line, ":") of
- {ok, [Group,Users]} ->
- {ok, UserList} = regexp:split(Users," "),
- parse_group(Stream, [{Group,UserList}|GroupList]);
- {ok, _} ->
- {error, ?NICE(Line)}
- end.
-
-
-%% store_passwd
-
-store_passwd(Addr,Port,PasswdList) ->
- Name = httpd_util:make_name("httpd_passwd",Addr,Port),
- PasswdDB = ets:new(Name, [set, public]),
- store_passwd(PasswdDB, PasswdList).
-
-store_passwd(PasswdDB, []) ->
- {ok, PasswdDB};
-store_passwd(PasswdDB, [User|Rest]) ->
- ets:insert(PasswdDB, User),
- store_passwd(PasswdDB, Rest).
-
-%% store_group
-
-store_group(Addr,Port,GroupList) ->
- Name = httpd_util:make_name("httpd_group",Addr,Port),
- GroupDB = ets:new(Name, [set, public]),
- store_group(GroupDB, GroupList).
-
-
-store_group(GroupDB,[]) ->
- {ok, GroupDB};
-store_group(GroupDB,[User|Rest]) ->
- ets:insert(GroupDB, User),
- store_group(GroupDB, Rest).
-
-
-%% remove/1
-%%
-%% Deletes ets tables used by this auth mod.
-%%
-remove(DirData) ->
- PWDB = httpd_util:key1search(DirData, auth_user_file),
- GDB = httpd_util:key1search(DirData, auth_group_file),
- ets:delete(PWDB),
- ets:delete(GDB).
-
-
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth_server.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth_server.erl
deleted file mode 100644
index 6694ed7eac..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_auth_server.erl
+++ /dev/null
@@ -1,424 +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: mod_auth_server.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
-%%
-
--module(mod_auth_server).
-
--include("httpd.hrl").
-%% -include("mod_auth.hrl").
--include("httpd_verbosity.hrl").
-
--behaviour(gen_server).
-
-
-%% mod_auth exports
--export([start/2, stop/2,
- add_password/4, update_password/5,
- add_user/5, delete_user/5, get_user/5, list_users/4,
- add_group_member/6, delete_group_member/6, list_group_members/5,
- delete_group/5, list_groups/4]).
-
-%% Management exports
--export([verbosity/3]).
-
-%% gen_server exports
--export([start_link/3,
- init/1,
- handle_call/3, handle_cast/2, handle_info/2,
- terminate/2, code_change/3]).
-
-
--record(state,{tab}).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% External API %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% start_link/3
-%%
-%% NOTE: This is called by httpd_misc_sup when the process is started
-%%
-start_link(Addr, Port, Verbosity)->
- ?vlog("start_link -> entry with"
- "~n Addr: ~p"
- "~n Port: ~p", [Addr, Port]),
- Name = make_name(Addr, Port),
- gen_server:start_link({local, Name}, ?MODULE, [Verbosity],
- [{timeout, infinity}]).
-
-
-%% start/2
-
-start(Addr, Port)->
- ?vtrace("start -> entry with"
- "~n Addr: ~p"
- "~n Port: ~p", [Addr, Port]),
- Name = make_name(Addr, Port),
- case whereis(Name) of
- undefined ->
- Verbosity = get(auth_verbosity),
- case (catch httpd_misc_sup:start_auth_server(Addr, Port,
- Verbosity)) of
- {ok, Pid} ->
- put(auth_server, Pid),
- ok;
- {error, Reason} ->
- exit({failed_start_auth_server, Reason});
- Error ->
- exit({failed_start_auth_server, Error})
- end;
- _ -> %% Already started...
- ok
- end.
-
-
-%% stop/2
-
-stop(Addr, Port)->
- ?vtrace("stop -> entry with"
- "~n Addr: ~p"
- "~n Port: ~p", [Addr, Port]),
- Name = make_name(Addr, Port),
- case whereis(Name) of
- undefined -> %% Already stopped
- ok;
- _ ->
- (catch httpd_misc_sup:stop_auth_server(Addr, Port))
- end.
-
-
-%% verbosity/3
-
-verbosity(Addr, Port, Verbosity) ->
- Name = make_name(Addr, Port),
- Req = {verbosity, Verbosity},
- call(Name, Req).
-
-
-%% add_password/4
-
-add_password(Addr, Port, Dir, Password)->
- Name = make_name(Addr, Port),
- Req = {add_password, Dir, Password},
- call(Name, Req).
-
-
-%% update_password/6
-
-update_password(Addr, Port, Dir, Old, New) when list(New) ->
- Name = make_name(Addr, Port),
- Req = {update_password, Dir, Old, New},
- call(Name, Req).
-
-
-%% add_user/5
-
-add_user(Addr, Port, Dir, User, Password) ->
- Name = make_name(Addr, Port),
- Req = {add_user, Addr, Port, Dir, User, Password},
- call(Name, Req).
-
-
-%% delete_user/5
-
-delete_user(Addr, Port, Dir, UserName, Password) ->
- Name = make_name(Addr, Port),
- Req = {delete_user, Addr, Port, Dir, UserName, Password},
- call(Name, Req).
-
-
-%% get_user/5
-
-get_user(Addr, Port, Dir, UserName, Password) ->
- Name = make_name(Addr, Port),
- Req = {get_user, Addr, Port, Dir, UserName, Password},
- call(Name, Req).
-
-
-%% list_users/4
-
-list_users(Addr, Port, Dir, Password) ->
- Name = make_name(Addr,Port),
- Req = {list_users, Addr, Port, Dir, Password},
- call(Name, Req).
-
-
-%% add_group_member/6
-
-add_group_member(Addr, Port, Dir, GroupName, UserName, Password) ->
- Name = make_name(Addr,Port),
- Req = {add_group_member, Addr, Port, Dir, GroupName, UserName, Password},
- call(Name, Req).
-
-
-%% delete_group_member/6
-
-delete_group_member(Addr, Port, Dir, GroupName, UserName, Password) ->
- Name = make_name(Addr,Port),
- Req = {delete_group_member, Addr, Port, Dir, GroupName, UserName, Password},
- call(Name, Req).
-
-
-%% list_group_members/4
-
-list_group_members(Addr, Port, Dir, Group, Password) ->
- Name = make_name(Addr, Port),
- Req = {list_group_members, Addr, Port, Dir, Group, Password},
- call(Name, Req).
-
-
-%% delete_group/5
-
-delete_group(Addr, Port, Dir, GroupName, Password) ->
- Name = make_name(Addr, Port),
- Req = {delete_group, Addr, Port, Dir, GroupName, Password},
- call(Name, Req).
-
-
-%% list_groups/4
-
-list_groups(Addr, Port, Dir, Password) ->
- Name = make_name(Addr, Port),
- Req = {list_groups, Addr, Port, Dir, Password},
- call(Name, Req).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% Server call-back functions %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% init
-
-init([undefined]) ->
- init([?default_verbosity]);
-
-init([Verbosity]) ->
- put(sname,auth),
- put(verbosity,Verbosity),
- ?vlog("starting",[]),
- {ok,#state{tab = ets:new(auth_pwd,[set,protected])}}.
-
-
-%% handle_call
-
-%% Add a user
-handle_call({add_user, Addr, Port, Dir, User, AuthPwd}, _From, State) ->
- Reply = api_call(Addr, Port, Dir, add_user, User, AuthPwd, State),
- {reply, Reply, State};
-
-%% Get data about a user
-handle_call({get_user, Addr, Port, Dir, User, AuthPwd}, _From, State) ->
- Reply = api_call(Addr, Port, Dir, get_user, [User], AuthPwd, State),
- {reply, Reply, State};
-
-%% Add a group member
-handle_call({add_group_member, Addr, Port, Dir, Group, User, AuthPwd},
- _From, State) ->
- Reply = api_call(Addr, Port, Dir, add_group_member, [Group, User],
- AuthPwd, State),
- {reply, Reply, State};
-
-%% delete a group
-handle_call({delete_group_member, Addr, Port, Dir, Group, User, AuthPwd},
- _From, State)->
- Reply = api_call(Addr, Port, Dir, delete_group_member, [Group, User],
- AuthPwd, State),
- {reply, Reply, State};
-
-%% List all users thats standalone users
-handle_call({list_users, Addr, Port, Dir, AuthPwd}, _From, State)->
- Reply = api_call(Addr, Port, Dir, list_users, [], AuthPwd, State),
- {reply, Reply, State};
-
-%% Delete a user
-handle_call({delete_user, Addr, Port, Dir, User, AuthPwd}, _From, State)->
- Reply = api_call(Addr, Port, Dir, delete_user, [User], AuthPwd, State),
- {reply, Reply, State};
-
-%% Delete a group
-handle_call({delete_group, Addr, Port, Dir, Group, AuthPwd}, _From, State)->
- Reply = api_call(Addr, Port, Dir, delete_group, [Group], AuthPwd, State),
- {reply, Reply, State};
-
-%% List the current groups
-handle_call({list_groups, Addr, Port, Dir, AuthPwd}, _From, State)->
- Reply = api_call(Addr, Port, Dir, list_groups, [], AuthPwd, State),
- {reply, Reply, State};
-
-%% List the members of the given group
-handle_call({list_group_members, Addr, Port, Dir, Group, AuthPwd},
- _From, State)->
- Reply = api_call(Addr, Port, Dir, list_group_members, [Group],
- AuthPwd, State),
- {reply, Reply, State};
-
-
-%% Add password for a directory
-handle_call({add_password, Dir, Password}, _From, State)->
- Reply = do_add_password(Dir, Password, State),
- {reply, Reply, State};
-
-
-%% Update the password for a directory
-
-handle_call({update_password, Dir, Old, New},_From,State)->
- Reply =
- case getPassword(State, Dir) of
- OldPwd when binary(OldPwd)->
- case erlang:md5(Old) of
- OldPwd ->
- %% The old password is right =>
- %% update the password to the new
- do_update_password(Dir,New,State),
- ok;
- _->
- {error, error_new}
- end;
- _->
- {error, error_old}
- end,
- {reply, Reply, State};
-
-handle_call(stop, _From, State)->
- {stop, normal, State};
-
-handle_call({verbosity,Verbosity},_From,State)->
- OldVerbosity = put(verbosity,Verbosity),
- ?vlog("set verbosity: ~p -> ~p",[Verbosity,OldVerbosity]),
- {reply,OldVerbosity,State}.
-
-handle_info(Info,State)->
- {noreply,State}.
-
-handle_cast(Request,State)->
- {noreply,State}.
-
-
-terminate(Reason,State) ->
- ets:delete(State#state.tab),
- ok.
-
-
-%% code_change({down, ToVsn}, State, Extra)
-%%
-code_change({down, _}, #state{tab = Tab}, downgrade_to_2_6_0) ->
- ?vlog("downgrade to 2.6.0", []),
- {ok, {state, Tab, undefined}};
-
-
-%% code_change(FromVsn, State, Extra)
-%%
-code_change(_, {state, Tab, _}, upgrade_from_2_6_0) ->
- ?vlog("upgrade from 2.6.0", []),
- {ok, #state{tab = Tab}}.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% The functions that really changes the data in the database %%
-%% of users to different directories %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% API gateway
-
-api_call(Addr, Port, Dir, Func, Args,Password,State) ->
- case controlPassword(Password,State,Dir) of
- ok->
- ConfigName = httpd_util:make_name("httpd_conf",Addr,Port),
- case ets:match_object(ConfigName, {directory, Dir, '$1'}) of
- [{directory, Dir, DirData}] ->
- AuthMod = auth_mod_name(DirData),
- ?DEBUG("api_call -> call ~p:~p",[AuthMod,Func]),
- Ret = (catch apply(AuthMod, Func, [DirData|Args])),
- ?DEBUG("api_call -> Ret: ~p",[ret]),
- Ret;
- O ->
- ?DEBUG("api_call -> O: ~p",[O]),
- {error, no_such_directory}
- end;
- bad_password ->
- {error,bad_password}
- end.
-
-controlPassword(Password,State,Dir)when Password=:="DummyPassword"->
- bad_password;
-
-controlPassword(Password,State,Dir)->
- case getPassword(State,Dir) of
- Pwd when binary(Pwd)->
- case erlang:md5(Password) of
- Pwd ->
- ok;
- _->
- bad_password
- end;
- _ ->
- bad_password
- end.
-
-
-getPassword(State,Dir)->
- case lookup(State#state.tab, Dir) of
- [{_,Pwd}]->
- Pwd;
- _ ->
- {error,bad_password}
- end.
-
-do_update_password(Dir, New, State) ->
- ets:insert(State#state.tab, {Dir, erlang:md5(New)}).
-
-do_add_password(Dir, Password, State) ->
- case getPassword(State,Dir) of
- PwdExists when binary(PwdExists) ->
- {error, dir_protected};
- {error, _} ->
- do_update_password(Dir, Password, State)
- end.
-
-
-auth_mod_name(DirData) ->
- case httpd_util:key1search(DirData, auth_type, plain) of
- plain -> mod_auth_plain;
- mnesia -> mod_auth_mnesia;
- dets -> mod_auth_dets
- end.
-
-
-lookup(Db, Key) ->
- ets:lookup(Db, Key).
-
-
-make_name(Addr,Port) ->
- httpd_util:make_name("httpd_auth",Addr,Port).
-
-
-call(Name, Req) ->
- case (catch gen_server:call(Name, Req)) of
- {'EXIT', Reason} ->
- {error, Reason};
- Reply ->
- Reply
- end.
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_browser.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_browser.erl
deleted file mode 100644
index 62ffba0e5b..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_browser.erl
+++ /dev/null
@@ -1,214 +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: mod_browser.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
-%%
-%% ----------------------------------------------------------------------
-%%
-%% Browsers sends a string to the webbserver
-%% to identify themsevles. They are a bit nasty
-%% since the only thing that the specification really
-%% is strict about is that they shall be short
-%% tree axamples:
-%%
-%% Netscape Mozilla/4.75 [en] (X11; U; SunOS 5.8 sun4u)
-%% IE5 Mozilla/4.0 (compatible; MSIE 5.0; SP1B; SunOS 5.8 sun4u; X11)
-%% Lynx Lynx/2.8.3rel.1 libwww-FM/2.142
-%%
-%% ----------------------------------------------------------------------
-
--module(mod_browser).
-
-%% Remember that the order of the mozilla browsers are
-%% important since some browsers include others to behave
-%% as they were something else
--define(MOZILLA_BROWSERS,[{opera,"opera"},{msie,"msie"}]).
-
-
-%% If your operatingsystem is not recognized add it to this list.
--define(OPERATIVE_SYSTEMS,[{win3x,["win16","windows 3","windows 16-bit"]},
- {win95,["win95","windows 95"]},
- {win98,["win98", "windows 98"]},
- {winnt,["winnt", "windows nt"]},
- {win2k,["nt 5"]},
- {sunos4,["sunos 4"]},
- {sunos5,["sunos 5"]},
- {sun,["sunos"]},
- {aix,["aix"]},
- {linux,["linux"]},
- {sco,["sco","unix_sv"]},
- {freebsd,["freebsd"]},
- {bsd,["bsd"]}]).
-
--define(LYNX,lynx).
--define(MOZILLA,mozilla).
--define(EMACS,emacs).
--define(STAROFFICE,soffice).
--define(MOSAIC,mosaic).
--define(NETSCAPE,netscape).
--define(UNKOWN,unknown).
-
--include("httpd.hrl").
-
--export([do/1, test/0, getBrowser/1]).
-
-
-do(Info) ->
- case httpd_util:key1search(Info#mod.data,status) of
- {Status_code,PhraseArgs,Reason} ->
- {proceed,Info#mod.data};
- undefined ->
- {proceed,[{'user-agent',getBrowser1(Info)}|Info#mod.data]}
- end.
-
-getBrowser1(Info) ->
- PHead=Info#mod.parsed_header,
- case httpd_util:key1search(PHead,"User-Agent") of
- undefined->
- undefined;
- AgentString ->
- getBrowser(AgentString)
- end.
-
-getBrowser(AgentString) ->
- LAgentString = httpd_util:to_lower(AgentString),
- case regexp:first_match(LAgentString,"^[^ ]*") of
- {match,Start,Length} ->
- Browser=lists:sublist(LAgentString,Start,Length),
- case browserType(Browser) of
- {mozilla,Vsn} ->
- {getMozilla(LAgentString,
- ?MOZILLA_BROWSERS,{?NETSCAPE,Vsn}),
- operativeSystem(LAgentString)};
- AnyBrowser ->
- {AnyBrowser,operativeSystem(LAgentString)}
- end;
- nomatch ->
- browserType(LAgentString)
- end.
-
-browserType([$l,$y,$n,$x|Version]) ->
- {?LYNX,browserVersion(Version)};
-browserType([$m,$o,$z,$i,$l,$l,$a|Version]) ->
- {?MOZILLA,browserVersion(Version)};
-browserType([$e,$m,$a,$c,$s|Version]) ->
- {?EMACS,browserVersion(Version)};
-browserType([$e,$t,$a,$r,$o,$f,$f,$i,$c,$e|Version]) ->
- {?STAROFFICE,browserVersion(Version)};
-browserType([$m,$o,$s,$a,$i,$c|Version]) ->
- {?MOSAIC,browserVersion(Version)};
-browserType(Unknown)->
- unknown.
-
-
-browserVersion([$/|VsnString]) ->
- case catch list_to_float(VsnString) of
- Number when float(Number) ->
- Number;
- Whatever ->
- case string:span(VsnString,"1234567890.") of
- 0 ->
- unknown;
- VLength ->
- Vsn = string:substr(VsnString,1,VLength),
- case string:tokens(Vsn,".") of
- [Number] ->
- list_to_float(Number++".0");
- [Major,Minor|_MinorMinor] ->
- list_to_float(Major++"."++Minor)
- end
- end
- end;
-browserVersion(VsnString) ->
- browserVersion([$/|VsnString]).
-
-operativeSystem(OpString) ->
- operativeSystem(OpString, ?OPERATIVE_SYSTEMS).
-
-operativeSystem(OpString,[]) ->
- unknown;
-operativeSystem(OpString,[{RetVal,RegExps}|Rest]) ->
- case controlOperativeSystem(OpString,RegExps) of
- true->
- RetVal;
- _ ->
- operativeSystem(OpString,Rest)
- end.
-
-controlOperativeSystem(OpString,[]) ->
- false;
-controlOperativeSystem(OpString,[Regexp|Regexps]) ->
- case regexp:match(OpString,Regexp) of
- {match,_,_}->
- true;
- nomatch->
- controlOperativeSystem(OpString,Regexps)
- end.
-
-
-%% OK this is ugly but thats the only way since
-%% all browsers dont conform to the name/vsn standard
-%% First we check if it is one of the browsers that
-%% not are the default mozillaborwser against the regexp
-%% for the different browsers. if no match it a mozilla
-%% browser i.e opera netscape or internet explorer
-
-getMozilla(AgentString,[],Default) ->
- Default;
-getMozilla(AgentString,[{Agent,AgentRegExp}|Rest],Default) ->
- case regexp:match(AgentString,AgentRegExp) of
- {match,_,_} ->
- {Agent,getVersion(AgentString,AgentRegExp)};
- nomatch ->
- getMozilla(AgentString,Rest,Default)
- end.
-
-getVersion(AgentString,AgentRegExp) ->
- case regexp:match(AgentString,AgentRegExp++"[0-9\.\ ]*") of
- {match,Start,Length} when length(AgentRegExp) < Length ->
- %% Ok we got the number split it out
- RealStart=Start+length(AgentRegExp),
- RealLength=Length-length(AgentRegExp),
- VsnString=string:substr(AgentString,RealStart,RealLength),
- case string:strip(VsnString,both,$\ ) of
- [] ->
- unknown;
- Vsn ->
- case string:tokens(Vsn,".") of
- [Number]->
- list_to_float(Number++".0");
- [Major,Minor|_MinorMinor]->
- list_to_float(Major++"."++Minor)
- end
- end;
- nomatch ->
- unknown
- end.
-
-
-test()->
- io:format("~n--------------------------------------------------------~n"),
- Res1=getBrowser("Mozilla/4.75 [en] (X11; U; SunOS 5.8 sun4u)"),
- io:format("~p",[Res1]),
- io:format("~n--------------------------------------------------------~n"),
- io:format("~n--------------------------------------------------------~n"),
- Res2=getBrowser("Mozilla/4.0 (compatible; MSIE 5.0; SP1B; SunOS 5.8 sun4u; X11)"),
- io:format("~p",[Res2]),
- io:format("~n--------------------------------------------------------~n"),
- io:format("~n--------------------------------------------------------~n"),
- Res3=getBrowser("Lynx/2.8.3rel.1 libwww-FM/2.142"),
- io:format("~p",[Res3]),
- io:format("~n--------------------------------------------------------~n").
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_cgi.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_cgi.erl
deleted file mode 100644
index d9070b8860..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_cgi.erl
+++ /dev/null
@@ -1,694 +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: mod_cgi.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
-%%
--module(mod_cgi).
--export([do/1,env/3,status_code/1,load/2]).
-
-%%Exports to the interface for sending chunked data
-%% to http/1.1 users and full responses to http/1.0
--export([send/5,final_send/4, update_status_code/2,get_new_size/2]).
--include("httpd.hrl").
-
--define(VMODULE,"CGI").
--include("httpd_verbosity.hrl").
-
--define(GATEWAY_INTERFACE,"CGI/1.1").
--define(DEFAULT_CGI_TIMEOUT,15000).
-
-%% do
-
-do(Info) ->
- ?vtrace("do",[]),
- case httpd_util:key1search(Info#mod.data,status) of
- %% A status code has been generated!
- {StatusCode, PhraseArgs, Reason} ->
- {proceed, Info#mod.data};
- %% No status code has been generated!
- undefined ->
- ?vtrace("do -> no status code has been generated", []),
- case httpd_util:key1search(Info#mod.data,response) of
- %% No response has been generated!
- undefined ->
- ?vtrace("do -> no response has been generated", []),
- RequestURI =
- case httpd_util:key1search(Info#mod.data,
- new_request_uri) of
- undefined ->
- Info#mod.request_uri;
- Value ->
- Value
- end,
- ?vtrace("do -> RequestURI: ~p", [RequestURI]),
- ScriptAliases =
- httpd_util:multi_lookup(Info#mod.config_db,
- script_alias),
- ?vtrace("do -> ScriptAliases: ~p", [ScriptAliases]),
- case mod_alias:real_script_name(Info#mod.config_db,
- RequestURI,
- ScriptAliases) of
- {Script, AfterScript} ->
- exec_script(Info, Script, AfterScript, RequestURI);
- not_a_script ->
- {proceed,Info#mod.data}
- end;
- %% A response has been generated or sent!
- Response ->
- {proceed,Info#mod.data}
- end
- end.
-
-
-%% is_executable(File) ->
-%% ?DEBUG("is_executable -> entry with~n"
-%% " File: ~s",[File]),
-%% Dir = filename:dirname(File),
-%% FileName = filename:basename(File),
-%% is_executable(FileName,Dir).
-%%
-%% is_executable(FileName,Dir) ->
-%% ?DEBUG("is_executable -> entry with~n"
-%% " Dir: ~s~n"
-%% " FileName: ~s",[Dir,FileName]),
-%% case os:find_executable(FileName, Dir) of
-%% false ->
-%% false;
-%% _ ->
-%% true
-%% end.
-
-
-%% -------------------------
-%% Start temporary (hopefully) fix for win32
-%% OTP-3627
-%%
-
-is_executable(File) ->
- Dir = filename:dirname(File),
- FileName = filename:basename(File),
- case os:type() of
- {win32,_} ->
- is_win32_executable(Dir,FileName);
- _ ->
- is_other_executable(Dir,FileName)
- end.
-
-
-is_win32_executable(D,F) ->
- case ends_with(F,[".bat",".exe",".com"]) of
- false ->
- %% This is why we cant use 'os:find_executable' directly.
- %% It assumes that executable files is given without extension
- case os:find_executable(F,D) of
- false ->
- false;
- _ ->
- true
- end;
- true ->
- case file:read_file_info(D ++ "/" ++ F) of
- {ok,_} ->
- true;
- _ ->
- false
- end
- end.
-
-
-is_other_executable(D,F) ->
- case os:find_executable(F,D) of
- false ->
- false;
- _ ->
- true
- end.
-
-
-ends_with(File,[]) ->
- false;
-ends_with(File,[Ext|Rest]) ->
- case ends_with1(File,Ext) of
- true ->
- true;
- false ->
- ends_with(File,Rest)
- end.
-
-ends_with1(S,E) when length(S) >= length(E) ->
- case to_lower(string:right(S,length(E))) of
- E ->
- true;
- _ ->
- false
- end;
-ends_with1(_S,_E) ->
- false.
-
-
-to_lower(S) -> to_lower(S,[]).
-
-to_lower([],L) -> lists:reverse(L);
-to_lower([H|T],L) -> to_lower(T,[to_lower1(H)|L]).
-
-to_lower1(C) when C >= $A, C =< $Z ->
- C + ($a - $A);
-to_lower1(C) ->
- C.
-
-%%
-%% End fix
-%% ---------------------------------
-
-
-env(VarName, Value) ->
- {VarName, Value}.
-
-env(Info, Script, AfterScript) ->
- ?vtrace("env -> entry with"
- "~n Script: ~p"
- "~n AfterScript: ~p",
- [Script, AfterScript]),
- {_, RemoteAddr} = (Info#mod.init_data)#init_data.peername,
- ServerName = (Info#mod.init_data)#init_data.resolve,
- PH = parsed_header(Info#mod.parsed_header),
- Env =
- [env("SERVER_SOFTWARE",?SERVER_SOFTWARE),
- env("SERVER_NAME",ServerName),
- env("GATEWAY_INTERFACE",?GATEWAY_INTERFACE),
- env("SERVER_PROTOCOL",?SERVER_PROTOCOL),
- env("SERVER_PORT",
- integer_to_list(httpd_util:lookup(Info#mod.config_db,port,80))),
- env("REQUEST_METHOD",Info#mod.method),
- env("REMOTE_ADDR",RemoteAddr),
- env("SCRIPT_NAME",Script)],
- Env1 =
- case Info#mod.method of
- "GET" ->
- case AfterScript of
- {[], QueryString} ->
- [env("QUERY_STRING", QueryString)|Env];
- {PathInfo, []} ->
- Aliases = httpd_util:multi_lookup(
- Info#mod.config_db,alias),
- {_, PathTranslated, _} =
- mod_alias:real_name(
- Info#mod.config_db, PathInfo, Aliases),
- [Env|
- [env("PATH_INFO","/"++httpd_util:decode_hex(PathInfo)),
- env("PATH_TRANSLATED",PathTranslated)]];
- {PathInfo, QueryString} ->
- Aliases = httpd_util:multi_lookup(
- Info#mod.config_db,alias),
- {_, PathTranslated, _} =
- mod_alias:real_name(
- Info#mod.config_db, PathInfo, Aliases),
- [Env|
- [env("PATH_INFO",
- httpd_util:decode_hex(PathInfo)),
- env("PATH_TRANSLATED",PathTranslated),
- env("QUERY_STRING", QueryString)]];
- [] ->
- Env
- end;
- "POST" ->
- [env("CONTENT_LENGTH",
- integer_to_list(httpd_util:flatlength(
- Info#mod.entity_body)))|Env];
- _ ->
- Env
- end,
- Env2 =
- case httpd_util:key1search(Info#mod.data,remote_user) of
- undefined ->
- Env1;
- RemoteUser ->
- [env("REMOTE_USER",RemoteUser)|Env1] %% OTP-4416
- end,
- lists:flatten([Env2|PH]).
-
-
-parsed_header(List) ->
- parsed_header(List, []).
-
-parsed_header([], SoFar) ->
- SoFar;
-parsed_header([{Name,[Value|R1]}|R2], SoFar) when list(Value)->
- NewName=lists:map(fun(X) -> if X == $- -> $_; true -> X end end,Name),
- Env = env("HTTP_"++httpd_util:to_upper(NewName),
- multi_value([Value|R1])),
- parsed_header(R2, [Env|SoFar]);
-
-parsed_header([{Name,Value}|Rest], SoFar) ->
- {ok,NewName,_} = regexp:gsub(Name, "-", "_"),
- Env=env("HTTP_"++httpd_util:to_upper(NewName),Value),
- parsed_header(Rest, [Env|SoFar]).
-
-
-multi_value([]) ->
- [];
-multi_value([Value]) ->
- Value;
-multi_value([Value|Rest]) ->
- Value++", "++multi_value(Rest).
-
-
-exec_script(Info, Script, AfterScript, RequestURI) ->
- ?vdebug("exec_script -> entry with"
- "~n Script: ~p"
- "~n AfterScript: ~p",
- [Script,AfterScript]),
- exec_script(is_executable(Script),Info,Script,AfterScript,RequestURI).
-
-exec_script(true, Info, Script, AfterScript, RequestURI) ->
- ?vtrace("exec_script -> entry when script is executable",[]),
- process_flag(trap_exit,true),
- Dir = filename:dirname(Script),
- [Script_Name|_] = string:tokens(RequestURI, "?"),
- Env = env(Info, Script_Name, AfterScript),
- Port = (catch open_port({spawn,Script},[stream,{cd, Dir},{env, Env}])),
- ?vtrace("exec_script -> Port: ~w",[Port]),
- case Port of
- P when port(P) ->
- %% Send entity_body to port.
- Res = case Info#mod.entity_body of
- [] ->
- true;
- EntityBody ->
- (catch port_command(Port, EntityBody))
- end,
- case Res of
- {'EXIT',Reason} ->
- ?vlog("port send failed:"
- "~n Port: ~p"
- "~n URI: ~p"
- "~n Reason: ~p",
- [Port,Info#mod.request_uri,Reason]),
- exit({open_cmd_failed,Reason,
- [{mod,?MODULE},{port,Port},
- {uri,Info#mod.request_uri},
- {script,Script},{env,Env},{dir,Dir},
- {ebody_size,sz(Info#mod.entity_body)}]});
- true ->
- proxy(Info, Port)
- end;
- {'EXIT',Reason} ->
- ?vlog("open port failed: exit"
- "~n URI: ~p"
- "~n Reason: ~p",
- [Info#mod.request_uri,Reason]),
- exit({open_port_failed,Reason,
- [{mod,?MODULE},{uri,Info#mod.request_uri},{script,Script},
- {env,Env},{dir,Dir}]});
- O ->
- ?vlog("open port failed: unknown result"
- "~n URI: ~p"
- "~n O: ~p",
- [Info#mod.request_uri,O]),
- exit({open_port_failed,O,
- [{mod,?MODULE},{uri,Info#mod.request_uri},{script,Script},
- {env,Env},{dir,Dir}]})
- end;
-
-exec_script(false,Info,Script,_AfterScript,_RequestURI) ->
- ?vlog("script ~s not executable",[Script]),
- {proceed,
- [{status,
- {404,Info#mod.request_uri,
- ?NICE("You don't have permission to execute " ++
- Info#mod.request_uri ++ " on this server")}}|
- Info#mod.data]}.
-
-
-
-%%
-%% Socket <-> Port communication
-%%
-
-proxy(#mod{config_db = ConfigDb} = Info, Port) ->
- Timeout = httpd_util:lookup(ConfigDb, cgi_timeout, ?DEFAULT_CGI_TIMEOUT),
- proxy(Info, Port, 0, undefined,[], Timeout).
-
-proxy(Info, Port, Size, StatusCode, AccResponse, Timeout) ->
- ?vdebug("proxy -> entry with"
- "~n Size: ~p"
- "~n StatusCode ~p"
- "~n Timeout: ~p",
- [Size, StatusCode, Timeout]),
- receive
- {Port, {data, Response}} when port(Port) ->
- ?vtrace("proxy -> got some data from the port",[]),
-
- NewStatusCode = update_status_code(StatusCode, Response),
-
- ?vtrace("proxy -> NewStatusCode: ~p",[NewStatusCode]),
- case send(Info, NewStatusCode, Response, Size, AccResponse) of
- socket_closed ->
- ?vtrace("proxy -> socket closed: kill port",[]),
- (catch port_close(Port)), % KILL the port !!!!
- process_flag(trap_exit,false),
- {proceed,
- [{response,{already_sent,200,Size}}|Info#mod.data]};
-
- head_sent ->
- ?vtrace("proxy -> head sent: kill port",[]),
- (catch port_close(Port)), % KILL the port !!!!
- process_flag(trap_exit,false),
- {proceed,
- [{response,{already_sent,200,Size}}|Info#mod.data]};
-
- {http_response, NewAccResponse} ->
- ?vtrace("proxy -> head response: continue",[]),
- NewSize = get_new_size(Size, Response),
- proxy(Info, Port, NewSize, NewStatusCode,
- NewAccResponse, Timeout);
-
- _ ->
- ?vtrace("proxy -> continue",[]),
- %% The data is sent and the socket is not closed, continue
- NewSize = get_new_size(Size, Response),
- proxy(Info, Port, NewSize, NewStatusCode,
- "nonempty", Timeout)
- end;
-
- {'EXIT', Port, normal} when port(Port) ->
- ?vtrace("proxy -> exit signal from port: normal",[]),
- NewStatusCode = update_status_code(StatusCode,AccResponse),
- final_send(Info,NewStatusCode,Size,AccResponse),
- process_flag(trap_exit,false),
- {proceed, [{response,{already_sent,200,Size}}|Info#mod.data]};
-
- {'EXIT', Port, Reason} when port(Port) ->
- ?vtrace("proxy -> exit signal from port: ~p",[Reason]),
- process_flag(trap_exit, false),
- {proceed, [{status,{400,none,reason(Reason)}}|Info#mod.data]};
-
- {'EXIT', Pid, Reason} when pid(Pid) ->
- %% This is the case that a linked process has died,
- %% It would be nice to response with a server error
- %% but since the heade alredy is sent
- ?vtrace("proxy -> exit signal from ~p: ~p",[Pid, Reason]),
- proxy(Info, Port, Size, StatusCode, AccResponse, Timeout);
-
- %% This should not happen
- WhatEver ->
- ?vinfo("proxy -> received garbage: ~n~p", [WhatEver]),
- NewStatusCode = update_status_code(StatusCode, AccResponse),
- final_send(Info, StatusCode, Size, AccResponse),
- process_flag(trap_exit, false),
- {proceed, [{response,{already_sent,200,Size}}|Info#mod.data]}
-
- after Timeout ->
- ?vlog("proxy -> timeout",[]),
- (catch port_close(Port)), % KILL the port !!!!
- httpd_socket:close(Info#mod.socket_type, Info#mod.socket),
- process_flag(trap_exit,false),
- {proceed,[{response,{already_sent,200,Size}}|Info#mod.data]}
- end.
-
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% The functions that handles the sending of the data to the client %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%%----------------------------------------------------------------------
-%% Send the header the first time the size of the body is Zero
-%%----------------------------------------------------------------------
-
-send(#mod{method = "HEAD"} = Info, StatusCode, Response, 0, []) ->
- first_handle_head_request(Info, StatusCode, Response);
-send(Info, StatusCode, Response, 0, []) ->
- first_handle_other_request(Info, StatusCode, Response);
-
-%%----------------------------------------------------------------------
-%% The size of the body is bigger than zero =>
-%% we have a part of the body to send
-%%----------------------------------------------------------------------
-send(Info, StatusCode, Response, Size, AccResponse) ->
- handle_other_request(Info, StatusCode, Response).
-
-
-%%----------------------------------------------------------------------
-%% The function is called the last time when the port has closed
-%%----------------------------------------------------------------------
-
-final_send(Info, StatusCode, Size, AccResponse)->
- final_handle_other_request(Info, StatusCode).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% The code that handles the head requests %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%----------------------------------------------------------------------
-%% The request is a head request if its a HTPT/1.1 request answer to it
-%% otherwise we must collect the size of hte body before we can answer.
-%% Return Values:
-%% head_sent
-%%----------------------------------------------------------------------
-first_handle_head_request(Info, StatusCode, Response)->
- case Info#mod.http_version of
- "HTTP/1.1" ->
- %% Since we have all we need to create the header create it
- %% send it and return head_sent.
- case httpd_util:split(Response,"\r\n\r\n|\n\n",2) of
- {ok, [HeadEnd, Rest]} ->
- HeadEnd1 = removeStatus(HeadEnd),
- httpd_socket:deliver(Info#mod.socket_type,Info#mod.socket,
- [create_header(Info,StatusCode),
- HeadEnd1,"\r\n\r\n"]);
- _ ->
- httpd_socket:deliver(Info#mod.socket_type,Info#mod.socket,
- [create_header(Info, StatusCode),
- "Content-Type:text/html\r\n\r\n"])
- end;
- _ ->
- Response1= case regexp:split(Response,"\r\n\r\n|\n\n") of
- {ok,[HeadEnd|Rest]} ->
- removeStatus(HeadEnd);
- _ ->
- ["Content-Type:text/html"]
- end,
- H1 = httpd_util:header(StatusCode,Info#mod.connection),
- httpd_socket:deliver(Info#mod.socket_type,Info#mod.socket,
- [H1,Response1,"\r\n\r\n"])
- end,
- head_sent.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% Handle the requests that is to the other methods %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%----------------------------------------------------------------------
-%% Create the http-response header and send it to the user if it is
-%% a http/1.1 request otherwise we must accumulate it
-%%----------------------------------------------------------------------
-first_handle_other_request(Info,StatusCode,Response)->
- Header = create_header(Info,StatusCode),
- Response1 =
- case httpd_util:split(Response,"\r\n\r\n|\n\n",2) of
- {ok,[HeadPart,[]]} ->
- [Header, removeStatus(HeadPart),"\r\n\r\n"];
-
- {ok,[HeadPart,BodyPart]} ->
- [Header, removeStatus(HeadPart), "\r\n\r\n",
- httpd_util:integer_to_hexlist(length(BodyPart)),
- "\r\n", BodyPart];
- _WhatEver ->
- %% No response header field from the cgi-script,
- %% Just a body
- [Header, "Content-Type:text/html","\r\n\r\n",
- httpd_util:integer_to_hexlist(length(Response)),
- "\r\n", Response]
- end,
- httpd_socket:deliver(Info#mod.socket_type,Info#mod.socket, Response1).
-
-
-handle_other_request(#mod{http_version = "HTTP/1.1",
- socket_type = Type, socket = Sock} = Info,
- StatusCode, Response0) ->
- Response = create_chunk(Info, Response0),
- httpd_socket:deliver(Type, Sock, Response);
-handle_other_request(#mod{socket_type = Type, socket = Sock} = Info,
- StatusCode, Response) ->
- httpd_socket:deliver(Type, Sock, Response).
-
-
-final_handle_other_request(#mod{http_version = "HTTP/1.1",
- socket_type = Type, socket = Sock},
- StatusCode) ->
- httpd_socket:deliver(Type, Sock, "0\r\n");
-final_handle_other_request(#mod{socket_type = Type, socket = Sock},
- StatusCode) ->
- httpd_socket:close(Type, Sock),
- socket_closed.
-
-
-create_chunk(_Info, Response) ->
- HEXSize = httpd_util:integer_to_hexlist(length(lists:flatten(Response))),
- HEXSize++"\r\n"++Response++"\r\n".
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% The various helper functions %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-update_status_code(undefined, Response) ->
- case status_code(Response) of
- {ok, StatusCode1} ->
- StatusCode1;
- _ ->
- ?vlog("invalid response from script:~n~p", [Response]),
- 500
- end;
-update_status_code(StatusCode,_Response)->
- StatusCode.
-
-
-get_new_size(0,Response)->
- case httpd_util:split(Response,"\r\n\r\n|\n\n",2) of
- {ok,[Head,Body]}->
- length(lists:flatten(Body));
- _ ->
- %%No header in the respone
- length(lists:flatten(Response))
- end;
-
-get_new_size(Size,Response)->
- Size+length(lists:flatten(Response)).
-
-%%----------------------------------------------------------------------
-%% Creates the http-header for a response
-%%----------------------------------------------------------------------
-create_header(Info,StatusCode)->
- Cache=case httpd_util:lookup(Info#mod.config_db,script_nocache,false) of
- true->
- Date=httpd_util:rfc1123_date(),
- "Cache-Control:no-cache\r\nPragma:no-cache\r\nExpires:"++ Date ++ "\r\n";
- false ->
- []
- end,
- case Info#mod.http_version of
- "HTTP/1.1" ->
- Header=httpd_util:header(StatusCode, Info#mod.connection),
- Header++"Transfer-encoding:chunked\r\n"++Cache;
- _ ->
- httpd_util:header(StatusCode,Info#mod.connection)++Cache
- end.
-
-
-
-%% status_code
-
-status_code(Response) ->
- case httpd_util:split(Response,"\n\n|\r\n\r\n",2) of
- {ok,[Header,Body]} ->
- case regexp:split(Header,"\n|\r\n") of
- {ok,HeaderFields} ->
- {ok,extract_status_code(HeaderFields)};
- {error,_} ->
- {error, bad_script_output(Response)}
- end;
- _ ->
- %% No header field in the returned data return 200 the standard code
- {ok, 200}
- end.
-
-bad_script_output(Bad) ->
- lists:flatten(io_lib:format("Bad script output ~s",[Bad])).
-
-
-extract_status_code([]) ->
- 200;
-extract_status_code([[$L,$o,$c,$a,$t,$i,$o,$n,$:,$ |_]|_]) ->
- 302;
-extract_status_code([[$S,$t,$a,$t,$u,$s,$:,$ |CodeAndReason]|_]) ->
- case httpd_util:split(CodeAndReason," ",2) of
- {ok,[Code,_]} ->
- list_to_integer(Code);
- {ok,_} ->
- 200
- end;
-extract_status_code([_|Rest]) ->
- extract_status_code(Rest).
-
-
-sz(B) when binary(B) -> {binary,size(B)};
-sz(L) when list(L) -> {list,length(L)};
-sz(_) -> undefined.
-
-
-%% Convert error to printable string
-%%
-reason({error,emfile}) -> ": To many open files";
-reason({error,{enfile,_}}) -> ": File/port table overflow";
-reason({error,enomem}) -> ": Not enough memory";
-reason({error,eagain}) -> ": No more available OS processes";
-reason(_) -> "".
-
-removeStatus(Head)->
- case httpd_util:split(Head,"Status:.\r\n",2) of
- {ok,[HeadPart,HeadEnd]}->
- HeadPart++HeadEnd;
- _ ->
- Head
- end.
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% There are 2 config directives for mod_cgi: %%
-%% ScriptNoCache true|false, defines whether the server shall add %%
-%% header fields to stop proxies and %%
-%% clients from saving the page in history %%
-%% or cache %%
-%% %%
-%% ScriptTimeout Seconds, The number of seconds that the server %%
-%% maximum will wait for the script to %%
-%% generate a part of the document %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-load([$S,$c,$r,$i,$p,$t,$N,$o,$C,$a,$c,$h,$e |CacheArg],[])->
- case catch list_to_atom(httpd_conf:clean(CacheArg)) of
- true ->
- {ok, [], {script_nocache,true}};
- false ->
- {ok, [], {script_nocache,false}};
- _ ->
- {error, ?NICE(httpd_conf:clean(CacheArg)++
- " is an invalid ScriptNoCache directive")}
- end;
-
-load([$S,$c,$r,$i,$p,$t,$T,$i,$m,$e,$o,$u,$t,$ |Timeout],[])->
- case catch list_to_integer(httpd_conf:clean(Timeout)) of
- TimeoutSec when integer(TimeoutSec) ->
- {ok, [], {script_timeout,TimeoutSec*1000}};
- _ ->
- {error, ?NICE(httpd_conf:clean(Timeout)++
- " is an invalid ScriptTimeout")}
- end.
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_dir.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_dir.erl
deleted file mode 100644
index 449b088055..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_dir.erl
+++ /dev/null
@@ -1,266 +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: mod_dir.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
-%%
--module(mod_dir).
--export([do/1]).
-
--include("httpd.hrl").
-
-%% do
-
-do(Info) ->
- ?DEBUG("do -> entry",[]),
- case Info#mod.method of
- "GET" ->
- case httpd_util:key1search(Info#mod.data,status) of
- %% A status code has been generated!
- {StatusCode,PhraseArgs,Reason} ->
- {proceed,Info#mod.data};
- %% No status code has been generated!
- undefined ->
- case httpd_util:key1search(Info#mod.data,response) of
- %% No response has been generated!
- undefined ->
- do_dir(Info);
- %% A response has been generated or sent!
- Response ->
- {proceed,Info#mod.data}
- end
- end;
- %% Not a GET method!
- _ ->
- {proceed,Info#mod.data}
- end.
-
-do_dir(Info) ->
- ?DEBUG("do_dir -> Request URI: ~p",[Info#mod.request_uri]),
- Path = mod_alias:path(Info#mod.data,Info#mod.config_db,
- Info#mod.request_uri),
- DefaultPath = mod_alias:default_index(Info#mod.config_db,Path),
- %% Is it a directory?
- case file:read_file_info(DefaultPath) of
- {ok,FileInfo} when FileInfo#file_info.type == directory ->
- DecodedRequestURI =
- httpd_util:decode_hex(Info#mod.request_uri),
- ?DEBUG("do_dir -> ~n"
- " Path: ~p~n"
- " DefaultPath: ~p~n"
- " DecodedRequestURI: ~p",
- [Path,DefaultPath,DecodedRequestURI]),
- case dir(DefaultPath,string:strip(DecodedRequestURI,right,$/),Info#mod.config_db) of
- {ok, Dir} ->
- Head=[{content_type,"text/html"},
- {content_length,integer_to_list(httpd_util:flatlength(Dir))},
- {date,httpd_util:rfc1123_date(FileInfo#file_info.mtime)},
- {code,200}],
- {proceed,[{response,{response,Head,Dir}},
- {mime_type,"text/html"}|Info#mod.data]};
- {error, Reason} ->
- ?ERROR("do_dir -> dir operation failed: ~p",[Reason]),
- {proceed,
- [{status,{404,Info#mod.request_uri,Reason}}|
- Info#mod.data]}
- end;
- {ok,FileInfo} ->
- ?DEBUG("do_dir -> ~n"
- " Path: ~p~n"
- " DefaultPath: ~p~n"
- " FileInfo: ~p",
- [Path,DefaultPath,FileInfo]),
- {proceed,Info#mod.data};
- {error,Reason} ->
- ?LOG("do_dir -> failed reading file info (~p) for: ~p",
- [Reason,DefaultPath]),
- {proceed,
- [{status,read_file_info_error(Reason,Info,DefaultPath)}|
- Info#mod.data]}
- end.
-
-dir(Path,RequestURI,ConfigDB) ->
- case file:list_dir(Path) of
- {ok,FileList} ->
- SortedFileList=lists:sort(FileList),
- {ok,[header(Path,RequestURI),
- body(Path,RequestURI,ConfigDB,SortedFileList),
- footer(Path,SortedFileList)]};
- {error,Reason} ->
- {error,?NICE("Can't open directory "++Path++": "++Reason)}
- end.
-
-%% header
-
-header(Path,RequestURI) ->
- Header=
- "<HTML>\n<HEAD>\n<TITLE>Index of "++RequestURI++"</TITLE>\n</HEAD>\n<BODY>\n<H1>Index of "++
- RequestURI++"</H1>\n<PRE><IMG SRC=\""++icon(blank)++
- "\" ALT=" "> Name Last modified Size Description
-<HR>\n",
- case regexp:sub(RequestURI,"[^/]*\$","") of
- {ok,"/",_} ->
- Header;
- {ok,ParentRequestURI,_} ->
- {ok,ParentPath,_}=regexp:sub(string:strip(Path,right,$/),"[^/]*\$",""),
- Header++format(ParentPath,ParentRequestURI)
- end.
-
-format(Path,RequestURI) ->
- {ok,FileInfo}=file:read_file_info(Path),
- {{Year,Month,Day},{Hour,Minute,Second}}=FileInfo#file_info.mtime,
- io_lib:format("<IMG SRC=\"~s\" ALT=\"[~s]\"> <A HREF=\"~s\">Parent directory</A> ~2.2.0w-~s-~w ~2.2.0w:~2.2.0w -\n",
- [icon(back),"DIR",RequestURI,Day,
- httpd_util:month(Month),Year,Hour,Minute]).
-
-%% body
-
-body(Path,RequestURI,ConfigDB,[]) ->
- [];
-body(Path,RequestURI,ConfigDB,[Entry|Rest]) ->
- [format(Path,RequestURI,ConfigDB,Entry)|body(Path,RequestURI,ConfigDB,Rest)].
-
-format(Path,RequestURI,ConfigDB,Entry) ->
- case file:read_file_info(Path++"/"++Entry) of
- {ok,FileInfo} when FileInfo#file_info.type == directory ->
- {{Year,Month,Day},{Hour,Minute,Second}}=FileInfo#file_info.mtime,
- EntryLength=length(Entry),
- if
- EntryLength > 21 ->
- io_lib:format("<IMG SRC=\"~s\" ALT=\"[~s]\"> <A HREF=\"~s\">~-21.s..</A>~2.2.0w-~s-~w ~2.2.0w:~2.2.0w -\n",
- [icon(folder),"DIR",RequestURI++"/"++Entry++"/",Entry,
- Day,httpd_util:month(Month),Year,Hour,Minute]);
- true ->
- io_lib:format("<IMG SRC=\"~s\" ALT=\"[~s]\"> <A HREF=\"~s\">~s</A>~*.*c~2.2.0w-~s-~w ~2.2.0w:~2.2.0w -\n",
- [icon(folder),"DIR",RequestURI++"/"++Entry++"/",Entry,
- 23-EntryLength,23-EntryLength,$ ,Day,
- httpd_util:month(Month),Year,Hour,Minute])
- end;
- {ok,FileInfo} ->
- {{Year,Month,Day},{Hour,Minute,Second}}=FileInfo#file_info.mtime,
- Suffix=httpd_util:suffix(Entry),
- MimeType=httpd_util:lookup_mime(ConfigDB,Suffix,""),
- EntryLength=length(Entry),
- if
- EntryLength > 21 ->
- io_lib:format("<IMG SRC=\"~s\" ALT=\"[~s]\"> <A HREF=\"~s\">~-21.s..</A>~2.2.0w-~s-~w ~2.2.0w:~2.2.0w~8wk ~s\n",
- [icon(Suffix,MimeType),Suffix,RequestURI++"/"++Entry,
- Entry,Day,httpd_util:month(Month),Year,Hour,Minute,
- trunc(FileInfo#file_info.size/1024+1),MimeType]);
- true ->
- io_lib:format("<IMG SRC=\"~s\" ALT=\"[~s]\"> <A HREF=\"~s\">~s</A>~*.*c~2.2.0w-~s-~w ~2.2.0w:~2.2.0w~8wk ~s\n",
- [icon(Suffix,MimeType),Suffix,RequestURI++"/"++Entry,
- Entry,23-EntryLength,23-EntryLength,$ ,Day,
- httpd_util:month(Month),Year,Hour,Minute,
- trunc(FileInfo#file_info.size/1024+1),MimeType])
- end;
- {error,Reason} ->
- ""
- end.
-
-%% footer
-
-footer(Path,FileList) ->
- case lists:member("README",FileList) of
- true ->
- {ok,Body}=file:read_file(Path++"/README"),
- "</PRE>\n<HR>\n<PRE>\n"++binary_to_list(Body)++
- "\n</PRE>\n</BODY>\n</HTML>\n";
- false ->
- "</PRE>\n</BODY>\n</HTML>\n"
- end.
-
-%%
-%% Icon mappings are hard-wired ala default Apache (Ugly!)
-%%
-
-icon(Suffix,MimeType) ->
- case icon(Suffix) of
- undefined ->
- case MimeType of
- [$t,$e,$x,$t,$/|_] ->
- "/icons/text.gif";
- [$i,$m,$a,$g,$e,$/|_] ->
- "/icons/image2.gif";
- [$a,$u,$d,$i,$o,$/|_] ->
- "/icons/sound2.gif";
- [$v,$i,$d,$e,$o,$/|_] ->
- "/icons/movie.gif";
- _ ->
- "/icons/unknown.gif"
- end;
- Icon ->
- Icon
- end.
-
-icon(blank) -> "/icons/blank.gif";
-icon(back) -> "/icons/back.gif";
-icon(folder) -> "/icons/folder.gif";
-icon("bin") -> "/icons/binary.gif";
-icon("exe") -> "/icons/binary.gif";
-icon("hqx") -> "/icons/binhex.gif";
-icon("tar") -> "/icons/tar.gif";
-icon("wrl") -> "/icons/world2.gif";
-icon("wrl.gz") -> "/icons/world2.gif";
-icon("vrml") -> "/icons/world2.gif";
-icon("vrm") -> "/icons/world2.gif";
-icon("iv") -> "/icons/world2.gif";
-icon("Z") -> "/icons/compressed.gif";
-icon("z") -> "/icons/compressed.gif";
-icon("tgz") -> "/icons/compressed.gif";
-icon("gz") -> "/icons/compressed.gif";
-icon("zip") -> "/icons/compressed.gif";
-icon("ps") -> "/icons/a.gif";
-icon("ai") -> "/icons/a.gif";
-icon("eps") -> "/icons/a.gif";
-icon("html") -> "/icons/layout.gif";
-icon("shtml") -> "/icons/layout.gif";
-icon("htm") -> "/icons/layout.gif";
-icon("pdf") -> "/icons/layout.gif";
-icon("txt") -> "/icons/text.gif";
-icon("erl") -> "/icons/burst.gif";
-icon("c") -> "/icons/c.gif";
-icon("pl") -> "/icons/p.gif";
-icon("py") -> "/icons/p.gif";
-icon("for") -> "/icons/f.gif";
-icon("dvi") -> "/icons/dvi.gif";
-icon("uu") -> "/icons/uuencoded.gif";
-icon("conf") -> "/icons/script.gif";
-icon("sh") -> "/icons/script.gif";
-icon("shar") -> "/icons/script.gif";
-icon("csh") -> "/icons/script.gif";
-icon("ksh") -> "/icons/script.gif";
-icon("tcl") -> "/icons/script.gif";
-icon("tex") -> "/icons/tex.gif";
-icon("core") -> "/icons/tex.gif";
-icon(_) -> undefined.
-
-
-read_file_info_error(eacces,Info,Path) ->
- read_file_info_error(403,Info,Path,
- ": Missing search permissions for one "
- "of the parent directories");
-read_file_info_error(enoent,Info,Path) ->
- read_file_info_error(404,Info,Path,"");
-read_file_info_error(enotdir,Info,Path) ->
- read_file_info_error(404,Info,Path,
- ": A component of the file name is not a directory");
-read_file_info_error(_,Info,Path) ->
- read_file_info_error(500,none,Path,"").
-
-read_file_info_error(StatusCode,none,Path,Reason) ->
- {StatusCode,none,?NICE("Can't access "++Path++Reason)};
-read_file_info_error(StatusCode,Info,Path,Reason) ->
- {StatusCode,Info#mod.request_uri,
- ?NICE("Can't access "++Path++Reason)}.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_disk_log.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_disk_log.erl
deleted file mode 100644
index c5d110ee4b..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_disk_log.erl
+++ /dev/null
@@ -1,405 +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: mod_disk_log.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
-%%
--module(mod_disk_log).
--export([do/1,error_log/5,security_log/2,load/2,store/2,remove/1]).
-
--export([report_error/2]).
-
--define(VMODULE,"DISK_LOG").
--include("httpd_verbosity.hrl").
-
--include("httpd.hrl").
-
-%% do
-
-do(Info) ->
- AuthUser = auth_user(Info#mod.data),
- Date = custom_date(),
- log_internal_info(Info,Date,Info#mod.data),
- LogFormat = get_log_format(Info#mod.config_db),
- case httpd_util:key1search(Info#mod.data,status) of
- %% A status code has been generated!
- {StatusCode,PhraseArgs,Reason} ->
- transfer_log(Info, "-", AuthUser, Date, StatusCode, 0, LogFormat),
- if
- StatusCode >= 400 ->
- error_log(Info, Date, Reason, LogFormat);
- true ->
- not_an_error
- end,
- {proceed,Info#mod.data};
- %% No status code has been generated!
- undefined ->
- case httpd_util:key1search(Info#mod.data,response) of
- {already_sent,StatusCode,Size} ->
- transfer_log(Info, "-", AuthUser, Date, StatusCode,
- Size, LogFormat),
- {proceed,Info#mod.data};
-
- {response, Head, Body} ->
- Size = httpd_util:key1search(Head, content_length, 0),
- Code = httpd_util:key1search(Head, code, 200),
- transfer_log(Info, "-", AuthUser, Date, Code,
- Size, LogFormat),
- {proceed,Info#mod.data};
-
- {StatusCode,Response} ->
- transfer_log(Info, "-", AuthUser, Date, 200,
- httpd_util:flatlength(Response), LogFormat),
- {proceed,Info#mod.data};
- undefined ->
- transfer_log(Info, "-", AuthUser, Date, 200,
- 0, LogFormat),
- {proceed,Info#mod.data}
- end
- end.
-
-custom_date() ->
- LocalTime = calendar:local_time(),
- UniversalTime = calendar:universal_time(),
- Minutes = round(diff_in_minutes(LocalTime,UniversalTime)),
- {{YYYY,MM,DD},{Hour,Min,Sec}} = LocalTime,
- Date =
- io_lib:format("~.2.0w/~.3s/~.4w:~.2.0w:~.2.0w:~.2.0w ~c~.2.0w~.2.0w",
- [DD,httpd_util:month(MM),YYYY,Hour,Min,Sec,sign(Minutes),
- abs(Minutes) div 60,abs(Minutes) rem 60]),
- lists:flatten(Date).
-
-diff_in_minutes(L,U) ->
- (calendar:datetime_to_gregorian_seconds(L) -
- calendar:datetime_to_gregorian_seconds(U))/60.
-
-sign(Minutes) when Minutes > 0 ->
- $+;
-sign(Minutes) ->
- $-.
-
-auth_user(Data) ->
- case httpd_util:key1search(Data,remote_user) of
- undefined ->
- "-";
- RemoteUser ->
- RemoteUser
- end.
-
-%% log_internal_info
-
-log_internal_info(Info,Date,[]) ->
- ok;
-log_internal_info(Info,Date,[{internal_info,Reason}|Rest]) ->
- Format = get_log_format(Info#mod.config_db),
- error_log(Info,Date,Reason,Format),
- log_internal_info(Info,Date,Rest);
-log_internal_info(Info,Date,[_|Rest]) ->
- log_internal_info(Info,Date,Rest).
-
-
-%% transfer_log
-
-transfer_log(Info,RFC931,AuthUser,Date,StatusCode,Bytes,Format) ->
- case httpd_util:lookup(Info#mod.config_db,transfer_disk_log) of
- undefined ->
- no_transfer_log;
- TransferDiskLog ->
- {PortNumber,RemoteHost}=(Info#mod.init_data)#init_data.peername,
- Entry = io_lib:format("~s ~s ~s [~s] \"~s\" ~w ~w~n",
- [RemoteHost,RFC931,AuthUser,Date,
- Info#mod.request_line,StatusCode,Bytes]),
- write(TransferDiskLog, Entry, Format)
- end.
-
-
-%% error_log
-
-error_log(Info, Date, Reason, Format) ->
- Format=get_log_format(Info#mod.config_db),
- case httpd_util:lookup(Info#mod.config_db,error_disk_log) of
- undefined ->
- no_error_log;
- ErrorDiskLog ->
- {PortNumber,RemoteHost}=(Info#mod.init_data)#init_data.peername,
- Entry =
- io_lib:format("[~s] access to ~s failed for ~s, reason: ~p~n",
- [Date, Info#mod.request_uri,
- RemoteHost, Reason]),
- write(ErrorDiskLog, Entry, Format)
- end.
-
-error_log(SocketType, Socket, ConfigDB, {PortNumber, RemoteHost}, Reason) ->
- Format = get_log_format(ConfigDB),
- case httpd_util:lookup(ConfigDB,error_disk_log) of
- undefined ->
- no_error_log;
- ErrorDiskLog ->
- Date = custom_date(),
- Entry =
- io_lib:format("[~s] server crash for ~s, reason: ~p~n",
- [Date,RemoteHost,Reason]),
- write(ErrorDiskLog, Entry, Format),
- ok
- end.
-
-
-%% security_log
-
-security_log(ConfigDB, Event) ->
- Format = get_log_format(ConfigDB),
- case httpd_util:lookup(ConfigDB,security_disk_log) of
- undefined ->
- no_error_log;
- DiskLog ->
- Date = custom_date(),
- Entry = io_lib:format("[~s] ~s ~n", [Date, Event]),
- write(DiskLog, Entry, Format),
- ok
- end.
-
-report_error(ConfigDB, Error) ->
- Format = get_log_format(ConfigDB),
- case httpd_util:lookup(ConfigDB, error_disk_log) of
- undefined ->
- no_error_log;
- ErrorDiskLog ->
- Date = custom_date(),
- Entry = io_lib:format("[~s] reporting error: ~s",[Date,Error]),
- write(ErrorDiskLog, Entry, Format),
- ok
- end.
-
-%%----------------------------------------------------------------------
-%% Get the current format of the disklog
-%%----------------------------------------------------------------------
-get_log_format(ConfigDB)->
- httpd_util:lookup(ConfigDB,disk_log_format,external).
-
-
-%%
-%% Configuration
-%%
-
-%% load
-
-load([$T,$r,$a,$n,$s,$f,$e,$r,$D,$i,$s,$k,$L,$o,$g,$S,$i,$z,$e,$ |
- TransferDiskLogSize],[]) ->
- case regexp:split(TransferDiskLogSize," ") of
- {ok,[MaxBytes,MaxFiles]} ->
- case httpd_conf:make_integer(MaxBytes) of
- {ok,MaxBytesInteger} ->
- case httpd_conf:make_integer(MaxFiles) of
- {ok,MaxFilesInteger} ->
- {ok,[],{transfer_disk_log_size,
- {MaxBytesInteger,MaxFilesInteger}}};
- {error,_} ->
- {error,
- ?NICE(httpd_conf:clean(TransferDiskLogSize)++
- " is an invalid TransferDiskLogSize")}
- end;
- {error,_} ->
- {error,?NICE(httpd_conf:clean(TransferDiskLogSize)++
- " is an invalid TransferDiskLogSize")}
- end
- end;
-load([$T,$r,$a,$n,$s,$f,$e,$r,$D,$i,$s,$k,$L,$o,$g,$ |TransferDiskLog],[]) ->
- {ok,[],{transfer_disk_log,httpd_conf:clean(TransferDiskLog)}};
-
-load([$E,$r,$r,$o,$r,$D,$i,$s,$k,$L,$o,$g,$S,$i,$z,$e,$ | ErrorDiskLogSize],[]) ->
- case regexp:split(ErrorDiskLogSize," ") of
- {ok,[MaxBytes,MaxFiles]} ->
- case httpd_conf:make_integer(MaxBytes) of
- {ok,MaxBytesInteger} ->
- case httpd_conf:make_integer(MaxFiles) of
- {ok,MaxFilesInteger} ->
- {ok,[],{error_disk_log_size,
- {MaxBytesInteger,MaxFilesInteger}}};
- {error,_} ->
- {error,?NICE(httpd_conf:clean(ErrorDiskLogSize)++
- " is an invalid ErrorDiskLogSize")}
- end;
- {error,_} ->
- {error,?NICE(httpd_conf:clean(ErrorDiskLogSize)++
- " is an invalid ErrorDiskLogSize")}
- end
- end;
-load([$E,$r,$r,$o,$r,$D,$i,$s,$k,$L,$o,$g,$ |ErrorDiskLog],[]) ->
- {ok, [], {error_disk_log, httpd_conf:clean(ErrorDiskLog)}};
-
-load([$S,$e,$c,$u,$r,$i,$t,$y,$D,$i,$s,$k,$L,$o,$g,$S,$i,$z,$e,$ |SecurityDiskLogSize],[]) ->
- case regexp:split(SecurityDiskLogSize, " ") of
- {ok, [MaxBytes, MaxFiles]} ->
- case httpd_conf:make_integer(MaxBytes) of
- {ok, MaxBytesInteger} ->
- case httpd_conf:make_integer(MaxFiles) of
- {ok, MaxFilesInteger} ->
- {ok, [], {security_disk_log_size,
- {MaxBytesInteger, MaxFilesInteger}}};
- {error,_} ->
- {error, ?NICE(httpd_conf:clean(SecurityDiskLogSize)++
- " is an invalid SecurityDiskLogSize")}
- end;
- {error, _} ->
- {error, ?NICE(httpd_conf:clean(SecurityDiskLogSize)++
- " is an invalid SecurityDiskLogSize")}
- end
- end;
-load([$S,$e,$c,$u,$r,$i,$t,$y,$D,$i,$s,$k,$L,$o,$g,$ |SecurityDiskLog],[]) ->
- {ok, [], {security_disk_log, httpd_conf:clean(SecurityDiskLog)}};
-
-load([$D,$i,$s,$k,$L,$o,$g,$F,$o,$r,$m,$a,$t,$ |Format],[]) ->
- case httpd_conf:clean(Format) of
- "internal" ->
- {ok, [], {disk_log_format,internal}};
- "external" ->
- {ok, [], {disk_log_format,external}};
- _Default ->
- {ok, [], {disk_log_format,external}}
- end.
-
-%% store
-
-store({transfer_disk_log,TransferDiskLog},ConfigList) ->
- case create_disk_log(TransferDiskLog, transfer_disk_log_size, ConfigList) of
- {ok,TransferDB} ->
- {ok,{transfer_disk_log,TransferDB}};
- {error,Reason} ->
- {error,Reason}
- end;
-store({security_disk_log,SecurityDiskLog},ConfigList) ->
- case create_disk_log(SecurityDiskLog, security_disk_log_size, ConfigList) of
- {ok,SecurityDB} ->
- {ok,{security_disk_log,SecurityDB}};
- {error,Reason} ->
- {error,Reason}
- end;
-store({error_disk_log,ErrorDiskLog},ConfigList) ->
- case create_disk_log(ErrorDiskLog, error_disk_log_size, ConfigList) of
- {ok,ErrorDB} ->
- {ok,{error_disk_log,ErrorDB}};
- {error,Reason} ->
- {error,Reason}
- end.
-
-
-%%----------------------------------------------------------------------
-%% Open or creates the disklogs
-%%----------------------------------------------------------------------
-log_size(ConfigList, Tag) ->
- httpd_util:key1search(ConfigList, Tag, {500*1024,8}).
-
-create_disk_log(LogFile, SizeTag, ConfigList) ->
- Filename = httpd_conf:clean(LogFile),
- {MaxBytes, MaxFiles} = log_size(ConfigList, SizeTag),
- case filename:pathtype(Filename) of
- absolute ->
- create_disk_log(Filename, MaxBytes, MaxFiles, ConfigList);
- volumerelative ->
- create_disk_log(Filename, MaxBytes, MaxFiles, ConfigList);
- relative ->
- case httpd_util:key1search(ConfigList,server_root) of
- undefined ->
- {error,
- ?NICE(Filename++
- " is an invalid ErrorLog beacuse ServerRoot is not defined")};
- ServerRoot ->
- AbsoluteFilename = filename:join(ServerRoot,Filename),
- create_disk_log(AbsoluteFilename, MaxBytes, MaxFiles,
- ConfigList)
- end
- end.
-
-create_disk_log(Filename, MaxBytes, MaxFiles, ConfigList) ->
- Format = httpd_util:key1search(ConfigList, disk_log_format, external),
- open(Filename, MaxBytes, MaxFiles, Format).
-
-
-
-%% remove
-remove(ConfigDB) ->
- lists:foreach(fun([DiskLog]) -> close(DiskLog) end,
- ets:match(ConfigDB,{transfer_disk_log,'$1'})),
- lists:foreach(fun([DiskLog]) -> close(DiskLog) end,
- ets:match(ConfigDB,{error_disk_log,'$1'})),
- ok.
-
-
-%%
-%% Some disk_log wrapper functions:
-%%
-
-%%----------------------------------------------------------------------
-%% Function: open/4
-%% Description: Open a disk log file.
-%% Control which format the disk log will be in. The external file
-%% format is used as default since that format was used by older
-%% implementations of inets.
-%%
-%% When the internal disk log format is used, we will do some extra
-%% controls. If the files are valid, try to repair them and if
-%% thats not possible, truncate.
-%%----------------------------------------------------------------------
-
-open(Filename, MaxBytes, MaxFiles, internal) ->
- Opts = [{format, internal}, {repair, truncate}],
- open1(Filename, MaxBytes, MaxFiles, Opts);
-open(Filename, MaxBytes, MaxFiles, _) ->
- Opts = [{format, external}],
- open1(Filename, MaxBytes, MaxFiles, Opts).
-
-open1(Filename, MaxBytes, MaxFiles, Opts0) ->
- Opts1 = [{name, Filename}, {file, Filename}, {type, wrap}] ++ Opts0,
- case open2(Opts1, {MaxBytes, MaxFiles}) of
- {ok, LogDB} ->
- {ok, LogDB};
- {error, Reason} ->
- ?vlog("failed opening disk log with args:"
- "~n Filename: ~p"
- "~n MaxBytes: ~p"
- "~n MaxFiles: ~p"
- "~n Opts0: ~p"
- "~nfor reason:"
- "~n ~p", [Filename, MaxBytes, MaxFiles, Opts0, Reason]),
- {error,
- ?NICE("Can't create " ++ Filename ++
- lists:flatten(io_lib:format(", ~p",[Reason])))};
- _ ->
- {error, ?NICE("Can't create "++Filename)}
- end.
-
-open2(Opts, Size) ->
- case disk_log:open(Opts) of
- {error, {badarg, size}} ->
- %% File did not exist, add the size option and try again
- disk_log:open([{size, Size} | Opts]);
- Else ->
- Else
- end.
-
-
-%%----------------------------------------------------------------------
-%% Actually writes the entry to the disk_log. If the log is an
-%% internal disk_log write it with log otherwise with blog.
-%%----------------------------------------------------------------------
-write(Log, Entry, internal) ->
- disk_log:log(Log, Entry);
-
-write(Log, Entry, _) ->
- disk_log:blog(Log, Entry).
-
-%% Close the log file
-close(Log) ->
- disk_log:close(Log).
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_esi.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_esi.erl
deleted file mode 100644
index d527f36788..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_esi.erl
+++ /dev/null
@@ -1,490 +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: mod_esi.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
-%%
--module(mod_esi).
--export([do/1,load/2]).
-
-%%Functions provided to help erl scheme alias programmer to
-%%Create dynamic webpages that are sent back to the user during
-%%Generation
--export([deliver/2]).
-
-
--include("httpd.hrl").
-
--define(VMODULE,"ESI").
--include("httpd_verbosity.hrl").
-
--define(GATEWAY_INTERFACE,"CGI/1.1").
--define(DEFAULT_ERL_TIMEOUT,15000).
-%% do
-
-do(Info) ->
- ?vtrace("do",[]),
- case httpd_util:key1search(Info#mod.data,status) of
- %% A status code has been generated!
- {StatusCode,PhraseArgs,Reason} ->
- {proceed,Info#mod.data};
- %% No status code has been generated!
- undefined ->
- case httpd_util:key1search(Info#mod.data,response) of
- %% No response has been generated!
- undefined ->
- case erl_or_eval(Info#mod.request_uri,
- Info#mod.config_db) of
- {eval,CGIBody,Modules} ->
- eval(Info,Info#mod.method,CGIBody,Modules);
- {erl,CGIBody,Modules} ->
- erl(Info,Info#mod.method,CGIBody,Modules);
- proceed ->
- {proceed,Info#mod.data}
- end;
- %% A response has been generated or sent!
- Response ->
- {proceed,Info#mod.data}
- end
- end.
-
-
-
-%% erl_or_eval
-
-erl_or_eval(RequestURI, ConfigDB) ->
- case erlp(RequestURI, ConfigDB) of
- false ->
- case evalp(RequestURI, ConfigDB) of
- false ->
- ?vtrace("neither erl nor eval",[]),
- proceed;
- Other ->
- Other
- end;
- Other ->
- Other
- end.
-
-erlp(RequestURI, ConfigDB) ->
- case httpd_util:multi_lookup(ConfigDB, erl_script_alias) of
- [] ->
- false;
- AliasMods ->
- erlp_find_alias(RequestURI,AliasMods)
- end.
-
-erlp_find_alias(_RequestURI,[]) ->
- ?vtrace("erlp_find_alias -> no match",[]),
- false;
-erlp_find_alias(RequestURI,[{Alias,Modules}|Rest]) ->
- case regexp:first_match(RequestURI,"^"++Alias++"/") of
- {match,1,Length} ->
- ?vtrace("erlp -> match with Length: ~p",[Length]),
- {erl,string:substr(RequestURI,Length+1),Modules};
- nomatch ->
- erlp_find_alias(RequestURI,Rest)
- end.
-
-evalp(RequestURI, ConfigDB) ->
- case httpd_util:multi_lookup(ConfigDB, eval_script_alias) of
- [] ->
- false;
- AliasMods ->
- evalp_find_alias(RequestURI,AliasMods)
- end.
-
-evalp_find_alias(_RequestURI,[]) ->
- ?vtrace("evalp_find_alias -> no match",[]),
- false;
-evalp_find_alias(RequestURI,[{Alias,Modules}|Rest]) ->
- case regexp:first_match(RequestURI,"^"++Alias++"\\?") of
- {match, 1, Length} ->
- ?vtrace("evalp_find_alias -> match with Length: ~p",[Length]),
- {eval, string:substr(RequestURI,Length+1),Modules};
- nomatch ->
- evalp_find_alias(RequestURI,Rest)
- end.
-
-
-%%
-%% Erl mechanism
-%%
-
-%%This is exactly the same as the GET method the difference is that
-%%The response must not contain any data expect the response header
-
-
-erl(Info,"HEAD",CGIBody,Modules) ->
- erl(Info,"GET",CGIBody,Modules);
-
-erl(Info,"GET",CGIBody,Modules) ->
- ?vtrace("erl GET request",[]),
- case httpd_util:split(CGIBody,":|%3A|/",2) of
- {ok, [Mod,FuncAndInput]} ->
- ?vtrace("~n Mod: ~p"
- "~n FuncAndInput: ~p",[Mod,FuncAndInput]),
- case httpd_util:split(FuncAndInput,"[\?/]",2) of
- {ok, [Func,Input]} ->
- ?vtrace("~n Func: ~p"
- "~n Input: ~p",[Func,Input]),
- exec(Info,"GET",CGIBody,Modules,Mod,Func,
- {input_type(FuncAndInput),Input});
- {ok, [Func]} ->
- exec(Info,"GET",CGIBody,Modules,Mod,Func,{no_input,""});
- {ok, BadRequest} ->
- {proceed,[{status,{400,none,BadRequest}}|Info#mod.data]}
- end;
- {ok, BadRequest} ->
- ?vlog("erl BAD (GET-) request",[]),
- {proceed, [{status,{400,none,BadRequest}}|Info#mod.data]}
- end;
-
-erl(Info, "POST", CGIBody, Modules) ->
- ?vtrace("erl POST request",[]),
- case httpd_util:split(CGIBody,":|%3A|/",2) of
- {ok,[Mod,Func]} ->
- ?vtrace("~n Mod: ~p"
- "~n Func: ~p",[Mod,Func]),
- exec(Info,"POST",CGIBody,Modules,Mod,Func,
- {entity_body,Info#mod.entity_body});
- {ok,BadRequest} ->
- ?vlog("erl BAD (POST-) request",[]),
- {proceed,[{status,{400,none,BadRequest}}|Info#mod.data]}
- end.
-
-input_type([]) ->
- no_input;
-input_type([$/|Rest]) ->
- path_info;
-input_type([$?|Rest]) ->
- query_string;
-input_type([First|Rest]) ->
- input_type(Rest).
-
-
-%% exec
-
-exec(Info,Method,CGIBody,["all"],Mod,Func,{Type,Input}) ->
- ?vtrace("exec ~s 'all'",[Method]),
- exec(Info,Method,CGIBody,[Mod],Mod,Func,{Type,Input});
-exec(Info,Method,CGIBody,Modules,Mod,Func,{Type,Input}) ->
- ?vtrace("exec ~s request with:"
- "~n Modules: ~p"
- "~n Mod: ~p"
- "~n Func: ~p"
- "~n Type: ~p"
- "~n Input: ~p",
- [Method,Modules,Mod,Func,Type,Input]),
- case lists:member(Mod,Modules) of
- true ->
- {_,RemoteAddr}=(Info#mod.init_data)#init_data.peername,
- ServerName=(Info#mod.init_data)#init_data.resolve,
- Env=get_environment(Info,ServerName,Method,RemoteAddr,Type,Input),
- ?vtrace("and now call the module",[]),
- case try_new_erl_scheme_method(Info,Env,Input,list_to_atom(Mod),list_to_atom(Func)) of
- {error,not_new_method}->
- case catch apply(list_to_atom(Mod),list_to_atom(Func),[Env,Input]) of
- {'EXIT',Reason} ->
- ?vlog("exit with Reason: ~p",[Reason]),
- {proceed,[{status,{500,none,Reason}}|Info#mod.data]};
- Response ->
- control_response_header(Info,Mod,Func,Response)
- end;
- ResponseResult->
- ResponseResult
- end;
- false ->
- ?vlog("unknown module",[]),
- {proceed,[{status,{403,Info#mod.request_uri,
- ?NICE("Client not authorized to evaluate: "++CGIBody)}}|Info#mod.data]}
- end.
-
-control_response_header(Info,Mod,Func,Response)->
- case control_response(Response,Info,Mod,Func) of
- {proceed,[{response,{StatusCode,Response}}|Rest]} ->
- case httpd_util:lookup(Info#mod.config_db,erl_script_nocache,false) of
- true ->
- case httpd_util:split(Response,"\r\n\r\n|\n\n",2) of
- {ok,[Head,Body]}->
- Date=httpd_util:rfc1123_date(),
- Cache="Cache-Control:no-cache\r\nPragma:no-cache\r\nExpires:"++ Date ++ "\r\n",
- {proceed,[{response,{StatusCode,[Head,"\r\n",Cache,"\r\n",Body]}}|Rest]};
- _->
- {proceed,[{response,{StatusCode,Response}}|Rest]}
- end;
- WhatEver->
- {proceed,[{response,{StatusCode,Response}}|Rest]}
- end;
- WhatEver->
- WhatEver
- end.
-
-control_response(Response,Info,Mod,Func)->
- ?vdebug("Response: ~n~p",[Response]),
- case mod_cgi:status_code(lists:flatten(Response)) of
- {ok,StatusCode} ->
- {proceed,[{response,{StatusCode,Response}}|Info#mod.data]};
- {error,Reason} ->
- {proceed,
- [{status,{400,none,
- ?NICE("Error in "++Mod++":"++Func++"/2: "++
- lists:flatten(io_lib:format("~p",[Reason])))}}|
- Info#mod.data]}
- end.
-
-parsed_header([]) ->
- [];
-parsed_header([{Name,[Value|R1]}|R2]) when list(Value) ->
- NewName=lists:map(fun(X) -> if X == $- -> $_; true -> X end end,Name),
- [{list_to_atom("http_"++httpd_util:to_lower(NewName)),
- multi_value([Value|R1])}|parsed_header(R2)];
-parsed_header([{Name,Value}|Rest]) when list(Value)->
- {ok,NewName,_}=regexp:gsub(Name,"-","_"),
- [{list_to_atom("http_"++httpd_util:to_lower(NewName)),Value}|
- parsed_header(Rest)].
-
-multi_value([]) ->
- [];
-multi_value([Value]) ->
- Value;
-multi_value([Value|Rest]) ->
- Value++", "++multi_value(Rest).
-
-%%
-%% Eval mechanism
-%%
-
-
-eval(Info,"POST",CGIBody,Modules) ->
- ?vtrace("eval(POST) -> method not supported",[]),
- {proceed,[{status,{501,{"POST",Info#mod.request_uri,Info#mod.http_version},
- ?NICE("Eval mechanism doesn't support method POST")}}|
- Info#mod.data]};
-
-eval(Info,"HEAD",CGIBody,Modules) ->
- %%The function that sends the data in httpd_response handles HEAD reqest by not
- %% Sending the body
- eval(Info,"GET",CGIBody,Modules);
-
-
-eval(Info,"GET",CGIBody,Modules) ->
- ?vtrace("eval(GET) -> entry when"
- "~n Modules: ~p",[Modules]),
- case auth(CGIBody,Modules) of
- true ->
- case lib:eval_str(string:concat(CGIBody,". ")) of
- {error,Reason} ->
- ?vlog("eval -> error:"
- "~n Reason: ~p",[Reason]),
- {proceed,[{status,{500,none,Reason}}|Info#mod.data]};
- {ok,Response} ->
- ?vtrace("eval -> ok:"
- "~n Response: ~p",[Response]),
- case mod_cgi:status_code(lists:flatten(Response)) of
- {ok,StatusCode} ->
- {proceed,[{response,{StatusCode,Response}}|Info#mod.data]};
- {error,Reason} ->
- {proceed,[{status,{400,none,Reason}}|Info#mod.data]}
- end
- end;
- false ->
- ?vlog("eval -> auth failed",[]),
- {proceed,[{status,
- {403,Info#mod.request_uri,
- ?NICE("Client not authorized to evaluate: "++CGIBody)}}|
- Info#mod.data]}
- end.
-
-auth(CGIBody,["all"]) ->
- true;
-auth(CGIBody,Modules) ->
- case regexp:match(CGIBody,"^[^\:(%3A)]*") of
- {match,Start,Length} ->
- lists:member(string:substr(CGIBody,Start,Length),Modules);
- nomatch ->
- false
- end.
-
-%%----------------------------------------------------------------------
-%%Creates the environment list that will be the first arg to the
-%%Functions that is called through the ErlScript Schema
-%%----------------------------------------------------------------------
-
-get_environment(Info,ServerName,Method,RemoteAddr,Type,Input)->
- Env=[{server_software,?SERVER_SOFTWARE},
- {server_name,ServerName},
- {gateway_interface,?GATEWAY_INTERFACE},
- {server_protocol,?SERVER_PROTOCOL},
- {server_port,httpd_util:lookup(Info#mod.config_db,port,80)},
- {request_method,Method},
- {remote_addr,RemoteAddr},
- {script_name,Info#mod.request_uri}|
- parsed_header(Info#mod.parsed_header)],
- get_environment(Type,Input,Env,Info).
-
-
-get_environment(Type,Input,Env,Info)->
- Env1=case Type of
- query_string ->
- [{query_string,Input}|Env];
- path_info ->
- Aliases=httpd_util:multi_lookup(Info#mod.config_db,alias),
- {_,PathTranslated,_}=mod_alias:real_name(Info#mod.config_db,[$/|Input],Aliases),
- [{path_info,"/"++httpd_util:decode_hex(Input)},
- {path_translated,PathTranslated}|Env];
- entity_body ->
- [{content_length,httpd_util:flatlength(Input)}|Env];
- no_input ->
- Env
- end,
- get_environment(Info,Env1).
-
-get_environment(Info,Env)->
- case httpd_util:key1search(Info#mod.data,remote_user) of
- undefined ->
- Env;
- RemoteUser ->
- [{remote_user,RemoteUser}|Env]
- end.
-%%
-%% Configuration
-%%
-
-%% load
-
-load([$E,$r,$l,$S,$c,$r,$i,$p,$t,$A,$l,$i,$a,$s,$ |ErlScriptAlias],[]) ->
- case regexp:split(ErlScriptAlias," ") of
- {ok, [ErlName|Modules]} ->
- {ok, [], {erl_script_alias, {ErlName,Modules}}};
- {ok, _} ->
- {error,?NICE(httpd_conf:clean(ErlScriptAlias)++
- " is an invalid ErlScriptAlias")}
- end;
-load([$E,$v,$a,$l,$S,$c,$r,$i,$p,$t,$A,$l,$i,$a,$s,$ |EvalScriptAlias],[]) ->
- case regexp:split(EvalScriptAlias, " ") of
- {ok, [EvalName|Modules]} ->
- {ok, [], {eval_script_alias, {EvalName,Modules}}};
- {ok, _} ->
- {error, ?NICE(httpd_conf:clean(EvalScriptAlias)++
- " is an invalid EvalScriptAlias")}
- end;
-load([$E,$r,$l,$S,$c,$r,$i,$p,$t,$T,$i,$m,$e,$o,$u,$t,$ |Timeout],[])->
- case catch list_to_integer(httpd_conf:clean(Timeout)) of
- TimeoutSec when integer(TimeoutSec) ->
- {ok, [], {erl_script_timeout,TimeoutSec*1000}};
- _ ->
- {error, ?NICE(httpd_conf:clean(Timeout)++
- " is an invalid ErlScriptTimeout")}
- end;
-load([$E,$r,$l,$S,$c,$r,$i,$p,$t,$N,$o,$C,$a,$c,$h,$e |CacheArg],[])->
- case catch list_to_atom(httpd_conf:clean(CacheArg)) of
- true ->
- {ok, [], {erl_script_nocache,true}};
- false ->
- {ok, [], {erl_script_nocache,false}};
- _ ->
- {error, ?NICE(httpd_conf:clean(CacheArg)++
- " is an invalid ErlScriptNoCache directive")}
- end.
-
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% Functions below handles the data from the dynamic webpages %%
-%% That sends data back to the user part by part %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%%----------------------------------------------------------------------
-%%Deliver is the callback function users can call to deliver back data to the
-%%client
-%%----------------------------------------------------------------------
-
-deliver(SessionID,Data)when pid(SessionID) ->
- SessionID ! {ok,Data},
- ok;
-deliver(SessionID,Data) ->
- {error,bad_sessionID}.
-
-
-%%----------------------------------------------------------------------
-%% The method that tries to execute the new format
-%%----------------------------------------------------------------------
-
-%%It would be nicer to use erlang:function_exported/3 but if the
-%%Module isn't loaded the function says that it is not loaded
-
-
-try_new_erl_scheme_method(Info,Env,Input,Mod,Func)->
- process_flag(trap_exit,true),
- Pid=spawn_link(Mod,Func,[self(),Env,Input]),
- Timeout=httpd_util:lookup(Info#mod.config_db,erl_script_timeout,?DEFAULT_ERL_TIMEOUT),
- RetVal=receive_response_data(Info,Pid,0,undefined,[],Timeout),
- process_flag(trap_exit,false),
- RetVal.
-
-
-%%----------------------------------------------------------------------
-%%The function recieves the data from the process that generates the page
-%%and send the data to the client through the mod_cgi:send function
-%%----------------------------------------------------------------------
-
-receive_response_data(Info,Pid,Size,StatusCode,AccResponse,Timeout) ->
- ?DEBUG("receive_response_data()-> Script Size: ~p,StatusCode ~p ,Timeout: ~p ~n",[Size,StatusCode,Timeout]),
- receive
- {ok, Response} ->
- NewStatusCode=mod_cgi:update_status_code(StatusCode,Response),
-
- ?DEBUG("receive_response_data/2 NewStatusCode: ~p~n",[NewStatusCode]),
- case mod_cgi:send(Info, NewStatusCode,Response, Size,AccResponse) of
- socket_closed ->
- (catch exit(Pid,final)),
- {proceed,[{response,{already_sent,200,Size}}|Info#mod.data]};
- head_sent->
- (catch exit(Pid,final)),
- {proceed,[{response,{already_sent,200,Size}}|Info#mod.data]};
- _ ->
- %%The data is sent and the socket is not closed contine
- NewSize = mod_cgi:get_new_size(Size,Response),
- receive_response_data(Info,Pid,NewSize,NewStatusCode,"notempty",Timeout)
- end;
- {'EXIT', Pid, Reason} when AccResponse==[] ->
- {error,not_new_method};
- {'EXIT', Pid, Reason} when pid(Pid) ->
- NewStatusCode=mod_cgi:update_status_code(StatusCode,AccResponse),
- mod_cgi:final_send(Info,NewStatusCode,Size,AccResponse),
- {proceed, [{response,{already_sent,200,Size}}|Info#mod.data]};
- %% This should not happen!
- WhatEver ->
- NewStatusCode=mod_cgi:update_status_code(StatusCode,AccResponse),
- mod_cgi:final_send(Info,StatusCode,Size,AccResponse),
- {proceed, [{response,{already_sent,200,Size}}|Info#mod.data]}
- after
- Timeout ->
- (catch exit(Pid,timeout)), % KILL the port !!!!
- httpd_socket:close(Info#mod.socket_type,Info#mod.socket),
- {proceed,[{response,{already_sent,200,Size}}|Info#mod.data]}
- end.
-
-
-
-
-
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_get.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_get.erl
deleted file mode 100644
index 02f708f85b..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_get.erl
+++ /dev/null
@@ -1,179 +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: mod_get.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
-%%
--module(mod_get).
--export([do/1]).
--include("httpd.hrl").
-
-%% do
-
-do(Info) ->
- ?DEBUG("do -> entry",[]),
- case Info#mod.method of
- "GET" ->
- case httpd_util:key1search(Info#mod.data,status) of
- %% A status code has been generated!
- {StatusCode,PhraseArgs,Reason} ->
- {proceed,Info#mod.data};
- %% No status code has been generated!
- undefined ->
- case httpd_util:key1search(Info#mod.data,response) of
- %% No response has been generated!
- undefined ->
- do_get(Info);
- %% A response has been generated or sent!
- Response ->
- {proceed,Info#mod.data}
- end
- end;
- %% Not a GET method!
- _ ->
- {proceed,Info#mod.data}
- end.
-
-
-do_get(Info) ->
- ?DEBUG("do_get -> Request URI: ~p",[Info#mod.request_uri]),
- Path = mod_alias:path(Info#mod.data, Info#mod.config_db,
- Info#mod.request_uri),
- {FileInfo, LastModified} =get_modification_date(Path),
-
- send_response(Info#mod.socket,Info#mod.socket_type,Path,Info,FileInfo,LastModified).
-
-
-%%The common case when no range is specified
-send_response(Socket,SocketType,Path,Info,FileInfo,LastModified)->
- %% Send the file!
- %% Find the modification date of the file
- case file:open(Path,[raw,binary]) of
- {ok, FileDescriptor} ->
- ?DEBUG("do_get -> FileDescriptor: ~p",[FileDescriptor]),
- Suffix = httpd_util:suffix(Path),
- MimeType = httpd_util:lookup_mime_default(Info#mod.config_db,
- Suffix,"text/plain"),
- %FileInfo=file:read_file_info(Path),
- Date = httpd_util:rfc1123_date(),
- Size = integer_to_list(FileInfo#file_info.size),
- Header=case Info#mod.http_version of
- "HTTP/1.1" ->
- [httpd_util:header(200, MimeType, Info#mod.connection),
- "Last-Modified: ", LastModified, "\r\n",
- "Etag: ",httpd_util:create_etag(FileInfo),"\r\n",
- "Content-Length: ",Size,"\r\n\r\n"];
- "HTTP/1.0" ->
- [httpd_util:header(200, MimeType, Info#mod.connection),
- "Last-Modified: ", LastModified, "\r\n",
- "Content-Length: ",Size,"\r\n\r\n"]
- end,
-
- send(Info#mod.socket_type, Info#mod.socket,
- Header, FileDescriptor),
- file:close(FileDescriptor),
- {proceed,[{response,{already_sent,200,
- FileInfo#file_info.size}},
- {mime_type,MimeType}|Info#mod.data]};
- {error, Reason} ->
-
- {proceed,
- [{status,open_error(Reason,Info,Path)}|Info#mod.data]}
- end.
-
-%% send
-
-send(SocketType,Socket,Header,FileDescriptor) ->
- ?DEBUG("send -> send header",[]),
- case httpd_socket:deliver(SocketType,Socket,Header) of
- socket_closed ->
- ?LOG("send -> socket closed while sending header",[]),
- socket_close;
- _ ->
- send_body(SocketType,Socket,FileDescriptor)
- end.
-
-send_body(SocketType,Socket,FileDescriptor) ->
- case file:read(FileDescriptor,?FILE_CHUNK_SIZE) of
- {ok,Binary} ->
- ?DEBUG("send_body -> send another chunk: ~p",[size(Binary)]),
- case httpd_socket:deliver(SocketType,Socket,Binary) of
- socket_closed ->
- ?LOG("send_body -> socket closed while sending",[]),
- socket_close;
- _ ->
- send_body(SocketType,Socket,FileDescriptor)
- end;
- eof ->
- ?DEBUG("send_body -> done with this file",[]),
- eof
- end.
-
-
-%% open_error - Handle file open failure
-%%
-open_error(eacces,Info,Path) ->
- open_error(403,Info,Path,"");
-open_error(enoent,Info,Path) ->
- open_error(404,Info,Path,"");
-open_error(enotdir,Info,Path) ->
- open_error(404,Info,Path,
- ": A component of the file name is not a directory");
-open_error(emfile,_Info,Path) ->
- open_error(500,none,Path,": To many open files");
-open_error({enfile,_},_Info,Path) ->
- open_error(500,none,Path,": File table overflow");
-open_error(_Reason,_Info,Path) ->
- open_error(500,none,Path,"").
-
-open_error(StatusCode,none,Path,Reason) ->
- {StatusCode,none,?NICE("Can't open "++Path++Reason)};
-open_error(StatusCode,Info,Path,Reason) ->
- {StatusCode,Info#mod.request_uri,?NICE("Can't open "++Path++Reason)}.
-
-get_modification_date(Path)->
- case file:read_file_info(Path) of
- {ok, FileInfo0} ->
- {FileInfo0, httpd_util:rfc1123_date(FileInfo0#file_info.mtime)};
- _ ->
- {#file_info{},""}
- end.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_head.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_head.erl
deleted file mode 100644
index 542604e092..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_head.erl
+++ /dev/null
@@ -1,89 +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: mod_head.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
-%%
--module(mod_head).
--export([do/1]).
-
--include("httpd.hrl").
-
-%% do
-
-do(Info) ->
- ?DEBUG("do -> entry",[]),
- case Info#mod.method of
- "HEAD" ->
- case httpd_util:key1search(Info#mod.data,status) of
- %% A status code has been generated!
- {StatusCode,PhraseArgs,Reason} ->
- {proceed,Info#mod.data};
- %% No status code has been generated!
- _undefined ->
- case httpd_util:key1search(Info#mod.data,response) of
- %% No response has been generated!
- undefined ->
- do_head(Info);
- %% A response has been sent! Nothing to do about it!
- {already_sent,StatusCode,Size} ->
- {proceed,Info#mod.data};
- %% A response has been generated!
- {StatusCode,Response} ->
- {proceed,Info#mod.data}
- end
- end;
- %% Not a HEAD method!
- _ ->
- {proceed,Info#mod.data}
- end.
-
-do_head(Info) ->
- ?DEBUG("do_head -> Request URI: ~p",[Info#mod.request_uri]),
- Path = mod_alias:path(Info#mod.data,Info#mod.config_db,
- Info#mod.request_uri),
- Suffix = httpd_util:suffix(Path),
- %% Does the file exists?
- case file:read_file_info(Path) of
- {ok,FileInfo} ->
- MimeType=httpd_util:lookup_mime_default(Info#mod.config_db,Suffix,"text/plain"),
- Length=io_lib:write(FileInfo#file_info.size),
- Head=[{content_type,MimeType},{content_length,Length},{code,200}],
- {proceed,[{response,{response,Head,nobody}}|Info#mod.data]};
- {error,Reason} ->
- {proceed,
- [{status,read_file_info_error(Reason,Info,Path)}|Info#mod.data]}
- end.
-
-%% read_file_info_error - Handle file info read failure
-%%
-read_file_info_error(eacces,Info,Path) ->
- read_file_info_error(403,Info,Path,"");
-read_file_info_error(enoent,Info,Path) ->
- read_file_info_error(404,Info,Path,"");
-read_file_info_error(enotdir,Info,Path) ->
- read_file_info_error(404,Info,Path,
- ": A component of the file name is not a directory");
-read_file_info_error(emfile,_Info,Path) ->
- read_file_info_error(500,none,Path,": To many open files");
-read_file_info_error({enfile,_},_Info,Path) ->
- read_file_info_error(500,none,Path,": File table overflow");
-read_file_info_error(_Reason,_Info,Path) ->
- read_file_info_error(500,none,Path,"").
-
-read_file_info_error(StatusCode,none,Path,Reason) ->
- {StatusCode,none,?NICE("Can't access "++Path++Reason)};
-read_file_info_error(StatusCode,Info,Path,Reason) ->
- {StatusCode,Info#mod.request_uri,
- ?NICE("Can't access "++Path++Reason)}.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_htaccess.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_htaccess.erl
deleted file mode 100644
index 069e4ad3a9..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_htaccess.erl
+++ /dev/null
@@ -1,1150 +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: mod_htaccess.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
-%%
-
--module(mod_htaccess).
-
--export([do/1, load/2]).
--export([debug/0]).
-
--include("httpd.hrl").
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Public methods that interface the eswapi %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%----------------------------------------------------------------------
-% Public method called by the webbserver to insert the data about
-% Names on accessfiles
-%----------------------------------------------------------------------
-load([$A,$c,$c,$e,$s,$s,$F,$i,$l,$e,$N,$a,$m,$e|FileNames],Context)->
- CleanFileNames=httpd_conf:clean(FileNames),
- %%io:format("\n The filenames is:" ++ FileNames ++ "\n"),
- {ok,[],{access_files,string:tokens(CleanFileNames," ")}}.
-
-
-%----------------------------------------------------------------------
-% Public method that the webbserver calls to control the page
-%----------------------------------------------------------------------
-do(Info)->
- case httpd_util:key1search(Info#mod.data,status) of
- {Status_code,PhraseArgs,Reason}->
- {proceed,Info#mod.data};
- undefined ->
- control_path(Info)
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% The functions that start the control if there is a accessfile %%
-%% and if so controls if the dir is allowed or not %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%----------------------------------------------------------------------
-%Info = record mod as specified in httpd.hrl
-%returns either {proceed,Info#mod.data}
-%{proceed,[{status,403....}|Info#mod.data]}
-%{proceed,[{status,401....}|Info#mod.data]}
-%{proceed,[{status,500....}|Info#mod.data]}
-%----------------------------------------------------------------------
-control_path(Info) ->
- Path = mod_alias:path(Info#mod.data,
- Info#mod.config_db,
- Info#mod.request_uri),
- case isErlScriptOrNotAccessibleFile(Path,Info) of
- true->
- {proceed,Info#mod.data};
- false->
- case getHtAccessData(Path,Info)of
- {ok,public}->
- %%There was no restrictions on the page continue
- {proceed,Info#mod.data};
- {error,Reason} ->
- %Something got wrong continue or quit??????????????????/
- {proceed,Info#mod.data};
- {accessData,AccessData}->
- controlAllowedMethod(Info,AccessData)
- end
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% These methods controls that the method the client used in the %%
-%% request is one of the limited %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%----------------------------------------------------------------------
-%Control that if the accessmethod used is in the list of modes to challenge
-%
-%Info is the mod record as specified in httpd.hrl
-%AccessData is an ets table whit the data in the .htaccessfiles
-%----------------------------------------------------------------------
-controlAllowedMethod(Info,AccessData)->
- case allowedRequestMethod(Info,AccessData) of
- allow->
- %%The request didnt use one of the limited methods
- ets:delete(AccessData),
- {proceed,Info#mod.data};
- challenge->
- authenticateUser(Info,AccessData)
- end.
-
-%----------------------------------------------------------------------
-%Check the specified access method in the .htaccessfile
-%----------------------------------------------------------------------
-allowedRequestMethod(Info,AccessData)->
- case ets:lookup(AccessData,limit) of
- [{limit,all}]->
- challenge;
- [{limit,Methods}]->
- isLimitedRequestMethod(Info,Methods)
- end.
-
-
-%----------------------------------------------------------------------
-%Check the specified accessmethods in the .htaccesfile against the users
-%accessmethod
-%
-%Info is the record from the do call
-%Methods is a list of the methods specified in the .htaccessfile
-%----------------------------------------------------------------------
-isLimitedRequestMethod(Info,Methods)->
- case lists:member(Info#mod.method,Methods) of
- true->
- challenge;
- false ->
- allow
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% These methods controls that the user comes from an allowwed net %%
-%% and if so wheather its a valid user or a challenge shall be %%
-%% generated %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%----------------------------------------------------------------------
-%The first thing to control is that the user is from a network
-%that has access to the page
-%----------------------------------------------------------------------
-authenticateUser(Info,AccessData)->
- case controlNet(Info,AccessData) of
- allow->
- %the network is ok control that it is an allowed user
- authenticateUser2(Info,AccessData);
- deny->
- %The user isnt allowed to access the pages from that network
- ets:delete(AccessData),
- {proceed,[{status,{403,Info#mod.request_uri,
- "Restricted area not allowed from your network"}}|Info#mod.data]}
- end.
-
-
-%----------------------------------------------------------------------
-%The network the user comes from is allowed to view the resources
-%control whether the user needsto supply a password or not
-%----------------------------------------------------------------------
-authenticateUser2(Info,AccessData)->
- case ets:lookup(AccessData,require) of
- [{require,AllowedUsers}]->
- case ets:lookup(AccessData,auth_name) of
- [{auth_name,Realm}]->
- authenticateUser2(Info,AccessData,Realm,AllowedUsers);
- _NoAuthName->
- ets:delete(AccessData),
- {break,[{status,{500,none,
- ?NICE("mod_htaccess:AuthName directive not specified")}}]}
- end;
- [] ->
- %%No special user is required the network is ok so let
- %%the user in
- ets:delete(AccessData),
- {proceed,Info#mod.data}
- end.
-
-
-%----------------------------------------------------------------------
-%The user must send a userId and a password to get the resource
-%Control if its already in the http-request
-%if the file with users is bad send an 500 response
-%----------------------------------------------------------------------
-authenticateUser2(Info,AccessData,Realm,AllowedUsers)->
- case authenticateUser(Info,AccessData,AllowedUsers) of
- allow ->
- ets:delete(AccessData),
- {user,Name,Pwd}=getAuthenticatingDataFromHeader(Info),
- {proceed, [{remote_user_name,Name}|Info#mod.data]};
- challenge->
- ets:delete(AccessData),
- ReasonPhrase = httpd_util:reason_phrase(401),
- Message = httpd_util:message(401,none,Info#mod.config_db),
- {proceed,
- [{response,
- {401,
- ["WWW-Authenticate: Basic realm=\"",Realm,
- "\"\r\n\r\n","<HTML>\n<HEAD>\n<TITLE>",
- ReasonPhrase,"</TITLE>\n",
- "</HEAD>\n<BODY>\n<H1>",ReasonPhrase,
- "</H1>\n",Message,"\n</BODY>\n</HTML>\n"]}}|
- Info#mod.data]};
- deny->
- ets:delete(AccessData),
- {break,[{status,{500,none,
- ?NICE("mod_htaccess:Bad path to user or group file")}}]}
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% Methods that validate the netwqork the user comes from %%
-%% according to the allowed networks %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%---------------------------------------------------------------------
-%Controls the users networkaddress agains the specifed networks to
-%allow or deny
-%
-%returns either allow or deny
-%----------------------------------------------------------------------
-controlNet(Info,AccessData)->
- UserNetwork=getUserNetworkAddress(Info),
- case getAllowDenyOrder(AccessData) of
- {_deny,[],_allow,[]}->
- allow;
- {deny,[],allow,AllowedNetworks}->
- controlIfAllowed(AllowedNetworks,UserNetwork,allow,deny);
- {allow,AllowedNetworks,deny,[]}->
- controlIfAllowed(AllowedNetworks,UserNetwork,allow,deny);
-
- {deny,DeniedNetworks,allow,[]}->
- controlIfAllowed(DeniedNetworks,UserNetwork,allow,deny);
- {allow,[],deny,DeniedNetworks}->
- controlIfAllowed(DeniedNetworks,UserNetwork,allow,deny);
-
- {deny,DeniedNetworks,allow,AllowedNetworks}->
- controlDenyAllow(DeniedNetworks,AllowedNetworks,UserNetwork);
- {allow,AllowedNetworks,deny,DeniedNetworks}->
- controlAllowDeny(AllowedNetworks,DeniedNetworks,UserNetwork)
- end.
-
-
-%----------------------------------------------------------------------
-%Returns the users IP-Number
-%----------------------------------------------------------------------
-getUserNetworkAddress(Info)->
- {_Socket,Address}=(Info#mod.init_data)#init_data.peername,
- Address.
-
-
-%----------------------------------------------------------------------
-%Control the users Ip-number against the ip-numbers in the .htaccessfile
-%----------------------------------------------------------------------
-controlIfAllowed(AllowedNetworks,UserNetwork,IfAllowed,IfDenied)->
- case AllowedNetworks of
- [{allow,all}]->
- IfAllowed;
- [{deny,all}]->
- IfDenied;
- [{deny,Networks}]->
- memberNetwork(Networks,UserNetwork,IfDenied,IfAllowed);
- [{allow,Networks}]->
- memberNetwork(Networks,UserNetwork,IfAllowed,IfDenied);
- _Error->
- IfDenied
- end.
-
-
-%---------------------------------------------------------------------%
-%The Denycontrol isn't neccessary to preform since the allow control %
-%override the deny control %
-%---------------------------------------------------------------------%
-controlDenyAllow(DeniedNetworks,AllowedNetworks,UserNetwork)->
- case AllowedNetworks of
- [{allow,all}]->
- allow;
- [{allow,Networks}]->
- case memberNetwork(Networks,UserNetwork) of
- true->
- allow;
- false->
- deny
- end
- end.
-
-
-%----------------------------------------------------------------------%
-%Control that the user is in the allowed list if so control that the %
-%network is in the denied list
-%----------------------------------------------------------------------%
-controlAllowDeny(AllowedNetworks,DeniedNetworks,UserNetwork)->
- case controlIfAllowed(AllowedNetworks,UserNetwork,allow,deny) of
- allow->
- controlIfAllowed(DeniedNetworks,UserNetwork,deny,allow);
- deny ->
- deny
- end.
-
-%----------------------------------------------------------------------
-%Controls if the users Ipnumber is in the list of either denied or
-%allowed networks
-%----------------------------------------------------------------------
-memberNetwork(Networks,UserNetwork,IfTrue,IfFalse)->
- case memberNetwork(Networks,UserNetwork) of
- true->
- IfTrue;
- false->
- IfFalse
- end.
-
-
-%----------------------------------------------------------------------
-%regexp match the users ip-address against the networks in the list of
-%ipadresses or subnet addresses.
-memberNetwork(Networks,UserNetwork)->
- case lists:filter(fun(Net)->
- case regexp:match(UserNetwork,
- formatRegexp(Net)) of
- {match,1,_}->
- true;
- _NotSubNet ->
- false
- end
- end,Networks) of
- []->
- false;
- MemberNetWork ->
- true
- end.
-
-
-%----------------------------------------------------------------------
-%Creates a regexp from an ip-number i.e "127.0.0-> "^127[.]0[.]0.*"
-%"127.0.0.-> "^127[.]0[.]0[.].*"
-%----------------------------------------------------------------------
-formatRegexp(Net)->
- [SubNet1|SubNets]=string:tokens(Net,"."),
- NetRegexp=lists:foldl(fun(SubNet,Newnet)->
- Newnet ++ "[.]" ++SubNet
- end,"^"++SubNet1,SubNets),
- case string:len(Net)-string:rchr(Net,$.) of
- 0->
- NetRegexp++"[.].*";
- _->
- NetRegexp++".*"
- end.
-
-
-%----------------------------------------------------------------------
-%If the user has specified if the allow or deny check shall be preformed
-%first get that order if no order is specified take
-%allow - deny since its harder that deny - allow
-%----------------------------------------------------------------------
-getAllowDenyOrder(AccessData)->
- case ets:lookup(AccessData,order) of
- [{order,{deny,allow}}]->
- {deny,ets:lookup(AccessData,deny),
- allow,ets:lookup(AccessData,allow)};
- _DefaultOrder->
- {allow,ets:lookup(AccessData,allow),
- deny,ets:lookup(AccessData,deny)}
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% The methods that validates the user %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%----------------------------------------------------------------------
-%Control if there is anyu autheticating data in threquest header
-%if so it controls it against the users in the list Allowed Users
-%----------------------------------------------------------------------
-authenticateUser(Info,AccessData,AllowedUsers)->
- case getAuthenticatingDataFromHeader(Info) of
- {user,User,PassWord}->
- authenticateUser(Info,AccessData,AllowedUsers,
- {user,User,PassWord});
- {error,nouser}->
- challenge;
- {error,BadData}->
- challenge
- end.
-
-
-%----------------------------------------------------------------------
-%Returns the Autheticating data in the http-request
-%----------------------------------------------------------------------
-getAuthenticatingDataFromHeader(Info)->
- PrsedHeader=Info#mod.parsed_header,
- case httpd_util:key1search(PrsedHeader,"authorization" ) of
- undefined->
- {error,nouser};
- [$B,$a,$s,$i,$c,$\ |EncodedString]->
- UnCodedString=httpd_util:decode_base64(EncodedString),
- case httpd_util:split(UnCodedString,":",2) of
- {ok,[User,PassWord]}->
- {user,User,PassWord};
- {error,Error}->
- {error,Error}
- end;
- BadCredentials ->
- {error,BadCredentials}
- end.
-
-
-%----------------------------------------------------------------------
-%Returns a list of all members of the allowed groups
-%----------------------------------------------------------------------
-getGroupMembers(Groups,AllowedGroups)->
- Allowed=lists:foldl(fun({group,Name,Members},AllowedMembers)->
- case lists:member(Name,AllowedGroups) of
- true->
- AllowedMembers++Members;
- false ->
- AllowedMembers
- end
- end,[],Groups),
- {ok,Allowed}.
-
-authenticateUser(Info,AccessData,{{users,[]},{groups,Groups}},User)->
- authenticateUser(Info,AccessData,{groups,Groups},User);
-authenticateUser(Info,AccessData,{{users,Users},{groups,[]}},User)->
- authenticateUser(Info,AccessData,{users,Users},User);
-
-authenticateUser(Info,AccessData,{{users,Users},{groups,Groups}},User)->
- AllowUser=authenticateUser(Info,AccessData,{users,Users},User),
- AllowGroup=authenticateUser(Info,AccessData,{groups,Groups},User),
- case {AllowGroup,AllowUser} of
- {_,allow}->
- allow;
- {allow,_}->
- allow;
- {challenge,_}->
- challenge;
- {_,challenge}->
- challenge;
- {_deny,_deny}->
- deny
- end;
-
-
-%----------------------------------------------------------------------
-%Controls that the user is a member in one of the allowed group
-%----------------------------------------------------------------------
-authenticateUser(Info,AccessData,{groups,AllowedGroups},{user,User,PassWord})->
- case getUsers(AccessData,group_file) of
- {group_data,Groups}->
- case getGroupMembers(Groups,AllowedGroups) of
- {ok,Members}->
- authenticateUser(Info,AccessData,{users,Members},
- {user,User,PassWord});
- {error,BadData}->
- deny
- end;
- {error,BadData}->
- deny
- end;
-
-
-%----------------------------------------------------------------------
-%Control that the user is one of the allowed users and that the passwd is ok
-%----------------------------------------------------------------------
-authenticateUser(Info,AccessData,{users,AllowedUsers},{user,User,PassWord})->
- case lists:member(User,AllowedUsers) of
- true->
- %Get the usernames and passwords from the file
- case getUsers(AccessData,user_file) of
- {error,BadData}->
- deny;
- {user_data,Users}->
- %Users is a list of the users in
- %the userfile [{user,User,Passwd}]
- checkPassWord(Users,{user,User,PassWord})
- end;
- false ->
- challenge
- end.
-
-
-%----------------------------------------------------------------------
-%Control that the user User={user,"UserName","PassWd"} is
-%member of the list of Users
-%----------------------------------------------------------------------
-checkPassWord(Users,User)->
- case lists:member(User,Users) of
- true->
- allow;
- false->
- challenge
- end.
-
-
-%----------------------------------------------------------------------
-%Get the users in the specified file
-%UserOrGroup is an atom that specify if its a group file or a user file
-%i.e. group_file or user_file
-%----------------------------------------------------------------------
-getUsers({file,FileName},UserOrGroup)->
- case file:open(FileName,[read]) of
- {ok,AccessFileHandle} ->
- getUsers({stream,AccessFileHandle},[],UserOrGroup);
- {error,Reason} ->
- {error,{Reason,FileName}}
- end;
-
-
-%----------------------------------------------------------------------
-%The method that starts the lokkong for user files
-%----------------------------------------------------------------------
-
-getUsers(AccessData,UserOrGroup)->
- case ets:lookup(AccessData,UserOrGroup) of
- [{UserOrGroup,File}]->
- getUsers({file,File},UserOrGroup);
- _ ->
- {error,noUsers}
- end.
-
-
-%----------------------------------------------------------------------
-%Reads data from the filehandle File to the list FileData and when its
-%reach the end it returns the list in a tuple {user_file|group_file,FileData}
-%----------------------------------------------------------------------
-getUsers({stream,File},FileData,UserOrGroup)->
- case io:get_line(File,[]) of
- eof when UserOrGroup==user_file->
- {user_data,FileData};
- eof when UserOrGroup ==group_file->
- {group_data,FileData};
- Line ->
- getUsers({stream,File},
- formatUser(Line,FileData,UserOrGroup),UserOrGroup)
- end.
-
-
-%----------------------------------------------------------------------
-%If the line is a comment remove it
-%----------------------------------------------------------------------
-formatUser([$#|UserDataComment],FileData,_UserOrgroup)->
- FileData;
-
-
-%----------------------------------------------------------------------
-%The user name in the file is Username:Passwd\n
-%Remove the newline sign and split the user name in
-%UserName and Password
-%----------------------------------------------------------------------
-formatUser(UserData,FileData,UserOrGroup)->
- case string:tokens(UserData," \r\n")of
- [User|Whitespace] when UserOrGroup==user_file->
- case string:tokens(User,":") of
- [Name,PassWord]->
- [{user,Name,PassWord}|FileData];
- _Error->
- FileData
- end;
- GroupData when UserOrGroup==group_file ->
- parseGroupData(GroupData,FileData);
- _Error ->
- FileData
- end.
-
-
-%----------------------------------------------------------------------
-%if everything is right GroupData is on the form
-% ["groupName:", "Member1", "Member2", "Member2"
-%----------------------------------------------------------------------
-parseGroupData([GroupName|GroupData],FileData)->
- [{group,formatGroupName(GroupName),GroupData}|FileData].
-
-
-%----------------------------------------------------------------------
-%the line in the file is GroupName: Member1 Member2 .....MemberN
-%Remove the : from the group name
-%----------------------------------------------------------------------
-formatGroupName(GroupName)->
- string:strip(GroupName,right,$:).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% Functions that parses the accessfiles %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%----------------------------------------------------------------------
-%Control that the asset is a real file and not a request for an virtual
-%asset
-%----------------------------------------------------------------------
-isErlScriptOrNotAccessibleFile(Path,Info)->
- case file:read_file_info(Path) of
- {ok,_fileInfo}->
- false;
- {error,_Reason} ->
- true
- end.
-
-
-%----------------------------------------------------------------------
-%Path=PathToTheRequestedFile=String
-%Innfo=record#mod
-%----------------------------------------------------------------------
-getHtAccessData(Path,Info)->
- HtAccessFileNames=getHtAccessFileNames(Info),
- case getData(Path,Info,HtAccessFileNames) of
- {ok,public}->
- {ok,public};
- {accessData,AccessData}->
- {accessData,AccessData};
- {error,Reason} ->
- {error,Reason}
- end.
-
-
-%----------------------------------------------------------------------
-%returns the names of the accessfiles
-%----------------------------------------------------------------------
-getHtAccessFileNames(Info)->
- case httpd_util:lookup(Info#mod.config_db,access_files) of
- undefined->
- [".htaccess"];
- Files->
- Files
- end.
-%----------------------------------------------------------------------
-%HtAccessFileNames=["accessfileName1",..."AccessFileName2"]
-%----------------------------------------------------------------------
-getData(Path,Info,HtAccessFileNames)->
- case regexp:split(Path,"/") of
- {error,Error}->
- {error,Error};
- {ok,SplittedPath}->
- getData2(HtAccessFileNames,SplittedPath,Info)
- end.
-
-
-%----------------------------------------------------------------------
-%Add to together the data in the Splittedpath up to the path
-%that is the alias or the document root
-%Since we do not need to control after any accessfiles before here
-%----------------------------------------------------------------------
-getData2(HtAccessFileNames,SplittedPath,Info)->
- case getRootPath(SplittedPath,Info) of
- {error,Path}->
- {error,Path};
- {ok,StartPath,RestOfSplittedPath} ->
- getData2(HtAccessFileNames,StartPath,RestOfSplittedPath,Info)
- end.
-
-
-%----------------------------------------------------------------------
-%HtAccessFilenames is a list the names the accesssfiles can have
-%Path is the shortest match agains all alias and documentroot
-%rest of splitted path is a list of the parts of the path
-%Info is the mod recod from the server
-%----------------------------------------------------------------------
-getData2(HtAccessFileNames,StartPath,RestOfSplittedPath,Info)->
- case getHtAccessFiles(HtAccessFileNames,StartPath,RestOfSplittedPath) of
- []->
- %No accessfile qiut its a public directory
- {ok,public};
- Files ->
- loadAccessFilesData(Files)
- end.
-
-
-%----------------------------------------------------------------------
-%Loads the data in the accessFiles specifiied by
-% AccessFiles=["/hoem/public/html/accefile",
-% "/home/public/html/priv/accessfile"]
-%----------------------------------------------------------------------
-loadAccessFilesData(AccessFiles)->
- loadAccessFilesData(AccessFiles,ets:new(accessData,[])).
-
-
-%----------------------------------------------------------------------
-%Returns the found data
-%----------------------------------------------------------------------
-contextToValues(AccessData)->
- case ets:lookup(AccessData,context) of
- [{context,Values}]->
- ets:delete(AccessData,context),
- insertContext(AccessData,Values),
- {accessData,AccessData};
- _Error->
- {error,errorInAccessFile}
- end.
-
-
-insertContext(AccessData,[])->
- ok;
-
-insertContext(AccessData,[{allow,From}|Values])->
- insertDenyAllowContext(AccessData,{allow,From}),
- insertContext(AccessData,Values);
-
-insertContext(AccessData,[{deny,From}|Values])->
- insertDenyAllowContext(AccessData,{deny,From}),
- insertContext(AccessData,Values);
-
-insertContext(AccessData,[{require,{GrpOrUsr,Members}}|Values])->
- case ets:lookup(AccessData,require) of
- []when GrpOrUsr==users->
- ets:insert(AccessData,{require,{{users,Members},{groups,[]}}});
-
- [{require,{{users,Users},{groups,Groups}}}]when GrpOrUsr==users ->
- ets:insert(AccessData,{require,{{users,Users++Members},
- {groups,Groups}}});
- []when GrpOrUsr==groups->
- ets:insert(AccessData,{require,{{users,[]},{groups,Members}}});
-
- [{require,{{users,Users},{groups,Groups}}}]when GrpOrUsr==groups ->
- ets:insert(AccessData,{require,{{users,Users},
- {groups,Groups++Members}}})
- end,
- insertContext(AccessData,Values);
-
-
-
-%%limit and order directive need no transforming they areis just to insert
-insertContext(AccessData,[Elem|Values])->
- ets:insert(AccessData,Elem),
- insertContext(AccessData,Values).
-
-
-insertDenyAllowContext(AccessData,{AllowDeny,From})->
- case From of
- all->
- ets:insert(AccessData,{AllowDeny,all});
- AllowedSubnets->
- case ets:lookup(AccessData,AllowDeny) of
- []->
- ets:insert(AccessData,{AllowDeny,From});
- [{AllowDeny,all}]->
- ok;
- [{AllowDeny,Networks}]->
- ets:insert(AccessData,{allow,Networks++From})
- end
- end.
-
-loadAccessFilesData([],AccessData)->
- %preform context to limits
- contextToValues(AccessData),
- {accessData,AccessData};
-
-%----------------------------------------------------------------------
-%Takes each file in the list and load the data to the ets table
-%AccessData
-%----------------------------------------------------------------------
-loadAccessFilesData([FileName|FileNames],AccessData)->
- case loadAccessFileData({file,FileName},AccessData) of
- overRide->
- loadAccessFilesData(FileNames,AccessData);
- noOverRide ->
- {accessData,AccessData};
- error->
- ets:delete(AccessData),
- {error,errorInAccessFile}
- end.
-
-%----------------------------------------------------------------------
-%opens the filehandle to the specified file
-%----------------------------------------------------------------------
-loadAccessFileData({file,FileName},AccessData)->
- case file:open(FileName,[read]) of
- {ok,AccessFileHandle}->
- loadAccessFileData({stream,AccessFileHandle},AccessData,[]);
- {error,Reason} ->
- overRide
- end.
-
-%----------------------------------------------------------------------
-%%look att each line in the file and add them to the database
-%%When end of file is reached control i overrride is allowed
-%% if so return
-%----------------------------------------------------------------------
-loadAccessFileData({stream,File},AccessData,FileData)->
- case io:get_line(File,[]) of
- eof->
- insertData(AccessData,FileData),
- case ets:match_object(AccessData,{'_',error}) of
- []->
- %Case we got no error control that we can override a
- %at least some of the values
- case ets:match_object(AccessData,
- {allow_over_ride,none}) of
- []->
- overRide;
- _NoOverride->
- noOverRide
- end;
- Errors->
- error
- end;
- Line ->
- loadAccessFileData({stream,File},AccessData,
- insertLine(string:strip(Line,left),FileData))
- end.
-
-%----------------------------------------------------------------------
-%AccessData is a ets table where the previous found data is inserted
-%FileData is a list of the directives in the last parsed file
-%before insertion a control is done that the directive is allowed to
-%override
-%----------------------------------------------------------------------
-insertData(AccessData,{{context,Values},FileData})->
- insertData(AccessData,[{context,Values}|FileData]);
-
-insertData(AccessData,FileData)->
- case ets:lookup(AccessData,allow_over_ride) of
- [{allow_over_ride,all}]->
- lists:foreach(fun(Elem)->
- ets:insert(AccessData,Elem)
- end,FileData);
- []->
- lists:foreach(fun(Elem)->
- ets:insert(AccessData,Elem)
- end,FileData);
- [{allow_over_ride,Directives}]when list(Directives)->
- lists:foreach(fun({Key,Value})->
- case lists:member(Key,Directives) of
- true->
- ok;
- false ->
- ets:insert(AccessData,{Key,Value})
- end
- end,FileData);
- [{allow_over_ride,_}]->
- %Will never appear if the user
- %aint doing very strang econfig files
- ok
- end.
-%----------------------------------------------------------------------
-%Take a line in the accessfile and transform it into a tuple that
-%later can be inserted in to the ets:table
-%----------------------------------------------------------------------
-%%%Here is the alternatives that resides inside the limit context
-
-insertLine([$o,$r,$d,$e,$r|Order],{{context,Values},FileData})->
- {{context,[{order,getOrder(Order)}|Values]},FileData};
-%%Let the user place a tab in the beginning
-insertLine([$\t,$o,$r,$d,$e,$r|Order],{{context,Values},FileData})->
- {{context,[{order,getOrder(Order)}|Values]},FileData};
-
-insertLine([$a,$l,$l,$o,$w|Allow],{{context,Values},FileData})->
- {{context,[{allow,getAllowDenyData(Allow)}|Values]},FileData};
-insertLine([$\t,$a,$l,$l,$o,$w|Allow],{{context,Values},FileData})->
- {{context,[{allow,getAllowDenyData(Allow)}|Values]},FileData};
-
-insertLine([$d,$e,$n,$y|Deny],{{context,Values},FileData})->
- {{context,[{deny,getAllowDenyData(Deny)}|Values]},FileData};
-insertLine([$\t,$d,$e,$n,$y|Deny],{{context,Values},FileData})->
- {{context,[{deny,getAllowDenyData(Deny)}|Values]},FileData};
-
-
-insertLine([$r,$e,$q,$u,$i,$r,$e|Require],{{context,Values},FileData})->
- {{context,[{require,getRequireData(Require)}|Values]},FileData};
-insertLine([$\t,$r,$e,$q,$u,$i,$r,$e|Require],{{context,Values},FileData})->
- {{context,[{require,getRequireData(Require)}|Values]},FileData};
-
-
-insertLine([$<,$/,$L,$i,$m,$i,$t|EndLimit],{Context,FileData})->
- [Context|FileData];
-
-insertLine([$<,$L,$i,$m,$i,$t|Limit],FileData)->
- {{context,[{limit,getLimits(Limit)}]}, FileData};
-
-
-
-insertLine([$A,$u,$t,$h,$U,$s,$e,$r,$F,$i,$l,$e,$\ |AuthUserFile],FileData)->
- [{user_file,string:strip(AuthUserFile,right,$\n)}|FileData];
-
-insertLine([$A,$u,$t,$h,$G,$r,$o,$u,$p,$F,$i,$l,$e,$\ |AuthGroupFile],
- FileData)->
- [{group_file,string:strip(AuthGroupFile,right,$\n)}|FileData];
-
-insertLine([$A,$l,$l,$o,$w,$O,$v,$e,$r,$R,$i,$d,$e|AllowOverRide],FileData)->
- [{allow_over_ride,getAllowOverRideData(AllowOverRide)}
- |FileData];
-
-insertLine([$A,$u,$t,$h,$N,$a,$m,$e,$\ |AuthName],FileData)->
- [{auth_name,string:strip(AuthName,right,$\n)}|FileData];
-
-insertLine([$A,$u,$t,$h,$T,$y,$p,$e|AuthType],FileData)->
- [{auth_type,getAuthorizationType(AuthType)}|FileData];
-
-insertLine(_BadDirectiveOrComment,FileData)->
- FileData.
-
-%----------------------------------------------------------------------
-%transform the Data specified about override to a form that is ieasier
-%handled later
-%Override data="all"|"md5"|"Directive1 .... DirectioveN"
-%----------------------------------------------------------------------
-
-getAllowOverRideData(OverRideData)->
- case string:tokens(OverRideData," \r\n") of
- [[$a,$l,$l]|_]->
- all;
- [[$n,$o,$n,$e]|_]->
- none;
- Directives ->
- getOverRideDirectives(Directives)
- end.
-
-getOverRideDirectives(Directives)->
- lists:map(fun(Directive)->
- transformDirective(Directive)
- end,Directives).
-transformDirective([$A,$u,$t,$h,$U,$s,$e,$r,$F,$i,$l,$e|_])->
- user_file;
-transformDirective([$A,$u,$t,$h,$G,$r,$o,$u,$p,$F,$i,$l,$e|_]) ->
- group_file;
-transformDirective([$A,$u,$t,$h,$N,$a,$m,$e|_])->
- auth_name;
-transformDirective([$A,$u,$t,$h,$T,$y,$p,$e|_])->
- auth_type;
-transformDirective(_UnAllowedOverRideDirective) ->
- unallowed.
-%----------------------------------------------------------------------
-%Replace the string that specify which method to use for authentication
-%and replace it with the atom for easier mathing
-%----------------------------------------------------------------------
-getAuthorizationType(AuthType)->
- [Arg|Crap]=string:tokens(AuthType,"\n\r\ "),
- case Arg of
- [$B,$a,$s,$i,$c]->
- basic;
- [$M,$D,$5] ->
- md5;
- _What ->
- error
- end.
-%----------------------------------------------------------------------
-%Returns a list of the specified methods to limit or the atom all
-%----------------------------------------------------------------------
-getLimits(Limits)->
- case regexp:split(Limits,">")of
- {ok,[_NoEndOnLimit]}->
- error;
- {ok,[Methods|Crap]}->
- case regexp:split(Methods," ")of
- {ok,[]}->
- all;
- {ok,SplittedMethods}->
- SplittedMethods;
- {error,Error}->
- error
- end;
- {error,_Error}->
- error
- end.
-
-
-%----------------------------------------------------------------------
-% Transform the order to prefrom deny allow control to a tuple of atoms
-%----------------------------------------------------------------------
-getOrder(Order)->
- [First|Rest]=lists:map(fun(Part)->
- list_to_atom(Part)
- end,string:tokens(Order," \n\r")),
- case First of
- deny->
- {deny,allow};
- allow->
- {allow,deny};
- _Error->
- error
- end.
-
-%----------------------------------------------------------------------
-% The string AllowDeny is "from all" or "from Subnet1 Subnet2...SubnetN"
-%----------------------------------------------------------------------
-getAllowDenyData(AllowDeny)->
- case string:tokens(AllowDeny," \n\r") of
- [_From|AllowDenyData] when length(AllowDenyData)>=1->
- case lists:nth(1,AllowDenyData) of
- [$a,$l,$l]->
- all;
- Hosts->
- AllowDenyData
- end;
- Error->
- errror
- end.
-%----------------------------------------------------------------------
-% Fix the string that describes who is allowed to se the page
-%----------------------------------------------------------------------
-getRequireData(Require)->
- [UserOrGroup|UserData]=string:tokens(Require," \n\r"),
- case UserOrGroup of
- [$u,$s,$e,$r]->
- {users,UserData};
- [$g,$r,$o,$u,$p] ->
- {groups,UserData};
- _Whatever ->
- error
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% Methods that collects the searchways to the accessfiles %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%----------------------------------------------------------------------
-% Get the whole path to the different accessfiles
-%----------------------------------------------------------------------
-getHtAccessFiles(HtAccessFileNames,Path,RestOfSplittedPath)->
- getHtAccessFiles(HtAccessFileNames,Path,RestOfSplittedPath,[]).
-
-getHtAccessFiles(HtAccessFileNames,Path,[[]],HtAccessFiles)->
- HtAccessFiles ++ accessFilesOfPath(HtAccessFileNames,Path++"/");
-
-getHtAccessFiles(HtAccessFileNames,Path,[],HtAccessFiles)->
- HtAccessFiles;
-getHtAccessFiles(HtAccessFileNames,Path,[NextDir|RestOfSplittedPath],
- AccessFiles)->
- getHtAccessFiles(HtAccessFileNames,Path++"/"++NextDir,RestOfSplittedPath,
- AccessFiles ++
- accessFilesOfPath(HtAccessFileNames,Path++"/")).
-
-
-%----------------------------------------------------------------------
-%Control if therer are any accessfies in the path
-%----------------------------------------------------------------------
-accessFilesOfPath(HtAccessFileNames,Path)->
- lists:foldl(fun(HtAccessFileName,Files)->
- case file:read_file_info(Path++HtAccessFileName) of
- {ok,FileInfo}->
- [Path++HtAccessFileName|Files];
- {error,_Error} ->
- Files
- end
- end,[],HtAccessFileNames).
-
-
-%----------------------------------------------------------------------
-%Sake the splitted path and joins it up to the documentroot or the alias
-%that match first
-%----------------------------------------------------------------------
-
-getRootPath(SplittedPath,Info)->
- DocRoot=httpd_util:lookup(Info#mod.config_db,document_root,"/"),
- PresumtiveRootPath=
- [DocRoot|lists:map(fun({Alias,RealPath})->
- RealPath
- end,
- httpd_util:multi_lookup(Info#mod.config_db,alias))],
- getRootPath(PresumtiveRootPath,SplittedPath,Info).
-
-
-getRootPath(PresumtiveRootPath,[[],Splittedpath],Info)->
- getRootPath(PresumtiveRootPath,["/",Splittedpath],Info);
-
-
-getRootPath(PresumtiveRootPath,[Part,NextPart|SplittedPath],Info)->
- case lists:member(Part,PresumtiveRootPath)of
- true->
- {ok,Part,[NextPart|SplittedPath]};
- false ->
- getRootPath(PresumtiveRootPath,
- [Part++"/"++NextPart|SplittedPath],Info)
- end;
-
-getRootPath(PresumtiveRootPath,[Part],Info)->
- case lists:member(Part,PresumtiveRootPath)of
- true->
- {ok,Part,[]};
- false ->
- {error,Part}
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%Debug methods %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%----------------------------------------------------------------------
-% Simulate the webserver by calling do/1 with apropiate parameters
-%----------------------------------------------------------------------
-debug()->
- Conf=getConfigData(),
- Uri=getUri(),
- {_Proceed,Data}=getDataFromAlias(Conf,Uri),
- Init_data=#init_data{peername={socket,"127.0.0.1"}},
- ParsedHeader=headerparts(),
- do(#mod{init_data=Init_data,
- data=Data,
- config_db=Conf,
- request_uri=Uri,
- parsed_header=ParsedHeader,
- method="GET"}).
-
-%----------------------------------------------------------------------
-%Add authenticate data to the fake http-request header
-%----------------------------------------------------------------------
-headerparts()->
- [{"authorization","Basic " ++ httpd_util:encode_base64("lotta:potta")}].
-
-getDataFromAlias(Conf,Uri)->
- mod_alias:do(#mod{config_db=Conf,request_uri=Uri}).
-
-getUri()->
- "/appmon/test/test.html".
-
-getConfigData()->
- Tab=ets:new(test_inets,[bag,public]),
- ets:insert(Tab,{server_name,"localhost"}),
- ets:insert(Tab,{bind_addresss,{127,0,0,1}}),
- ets:insert(Tab,{erl_script_alias,{"/webcover/erl",["webcover"]}}),
- ets:insert(Tab,{erl_script_alias,{"/erl",["webappmon"]}}),
- ets:insert(Tab,{com_type,ip_comm}),
- ets:insert(Tab,{modules,[mod_alias,mod_auth,mod_header]}),
- ets:insert(Tab,{default_type,"text/plain"}),
- ets:insert(Tab,{server_root,
- "/home/gandalf/marting/exjobb/webtool-1.0/priv/root"}),
- ets:insert(Tab,{port,8888}),
- ets:insert(Tab,{document_root,
- "/home/gandalf/marting/exjobb/webtool-1.0/priv/root"}),
- ets:insert(Tab,
- {alias,
- {"/appmon"
- ,"/home/gandalf/marting/exjobb/webappmon-1.0/priv"}}),
- ets:insert(Tab,{alias,
- {"/webcover"
- ,"/home/gandalf/marting/exjobb/webcover-1.0/priv"}}),
- ets:insert(Tab,{access_file,[".htaccess","kalle","pelle"]}),
- Tab.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_include.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_include.erl
deleted file mode 100644
index c93e0a4f59..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_include.erl
+++ /dev/null
@@ -1,726 +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: mod_include.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
-%%
--module(mod_include).
--export([do/1,parse/2,config/6,include/6,echo/6,fsize/6,flastmod/6,exec/6]).
-
--include("httpd.hrl").
-
--define(VMODULE,"INCLUDE").
--include("httpd_verbosity.hrl").
-
-%% do
-
-do(Info) ->
- ?vtrace("do",[]),
- case Info#mod.method of
- "GET" ->
- case httpd_util:key1search(Info#mod.data,status) of
- %% A status code has been generated!
- {StatusCode,PhraseArgs,Reason} ->
- {proceed,Info#mod.data};
- %% No status code has been generated!
- undefined ->
- case httpd_util:key1search(Info#mod.data, response) of
- %% No response has been generated!
- undefined ->
- do_include(Info);
- %% A response has been generated or sent!
- Response ->
- {proceed,Info#mod.data}
- end
- end;
- %% Not a GET method!
- _ ->
- {proceed,Info#mod.data}
- end.
-
-do_include(Info) ->
- ?vtrace("do_include -> entry with"
- "~n URI: ~p",[Info#mod.request_uri]),
- Path = mod_alias:path(Info#mod.data,Info#mod.config_db,
- Info#mod.request_uri),
- Suffix = httpd_util:suffix(Path),
- case httpd_util:lookup_mime_default(Info#mod.config_db,Suffix) of
- "text/x-server-parsed-html" ->
- HeaderStart =
- httpd_util:header(200, "text/html", Info#mod.connection),
- ?vtrace("do_include -> send ~p", [Path]),
- case send_in(Info,Path,HeaderStart,file:read_file_info(Path)) of
- {ok, ErrorLog, Size} ->
- ?vtrace("do_include -> sent ~w bytes", [Size]),
- {proceed,[{response,{already_sent,200,Size}},
- {mime_type,"text/html"}|
- lists:append(ErrorLog,Info#mod.data)]};
- {error, Reason} ->
- ?vlog("send in failed:"
- "~n Reason: ~p"
- "~n Path: ~p"
- "~n Info: ~p",
- [Reason,Info,Path]),
- {proceed,
- [{status,send_error(Reason,Info,Path)}|Info#mod.data]}
- end;
- _ -> %% Unknown mime type, ignore
- {proceed,Info#mod.data}
- end.
-
-
-%%
-%% config directive
-%%
-
-config(Info, Context, ErrorLog, TagList, ValueList, R) ->
- case verify_tags("config",[errmsg,timefmt,sizefmt],
- TagList,ValueList) of
- ok ->
- {ok,update_context(TagList,ValueList,Context),ErrorLog,"",R};
- {error,Reason} ->
- {ok,Context,[{internal_info,Reason}|ErrorLog],
- httpd_util:key1search(Context,errmsg,""),R}
- end.
-
-update_context([],[],Context) ->
- Context;
-update_context([Tag|R1],[Value|R2],Context) ->
- update_context(R1,R2,[{Tag,Value}|Context]).
-
-verify_tags(Command,ValidTags,TagList,ValueList) when length(TagList)==length(ValueList) ->
- verify_tags(Command,ValidTags,TagList);
-verify_tags(Command,ValidTags,TagList,ValueList) ->
- {error,?NICE(Command++" directive has spurious tags")}.
-
-verify_tags(Command, ValidTags, []) ->
- ok;
-verify_tags(Command, ValidTags, [Tag|Rest]) ->
- case lists:member(Tag, ValidTags) of
- true ->
- verify_tags(Command, ValidTags, Rest);
- false ->
- {error,?NICE(Command++" directive has a spurious tag ("++
- atom_to_list(Tag)++")")}
- end.
-
-%%
-%% include directive
-%%
-
-include(Info,Context,ErrorLog,[virtual],[VirtualPath],R) ->
- Aliases = httpd_util:multi_lookup(Info#mod.config_db,alias),
- {_, Path, _AfterPath} =
- mod_alias:real_name(Info#mod.config_db, VirtualPath, Aliases),
- include(Info,Context,ErrorLog,R,Path);
-include(Info, Context, ErrorLog, [file], [FileName], R) ->
- Path = file(Info#mod.config_db, Info#mod.request_uri, FileName),
- include(Info, Context, ErrorLog, R, Path);
-include(Info, Context, ErrorLog, TagList, ValueList, R) ->
- {ok, Context,
- [{internal_info,?NICE("include directive has a spurious tag")}|
- ErrorLog], httpd_util:key1search(Context, errmsg, ""), R}.
-
-include(Info, Context, ErrorLog, R, Path) ->
- ?DEBUG("include -> read file: ~p",[Path]),
- case file:read_file(Path) of
- {ok, Body} ->
- ?DEBUG("include -> size(Body): ~p",[size(Body)]),
- {ok, NewContext, NewErrorLog, Result} =
- parse(Info, binary_to_list(Body), Context, ErrorLog, []),
- {ok, Context, NewErrorLog, Result, R};
- {error, Reason} ->
- {ok, Context,
- [{internal_info, ?NICE("Can't open "++Path)}|ErrorLog],
- httpd_util:key1search(Context, errmsg, ""), R}
- end.
-
-file(ConfigDB, RequestURI, FileName) ->
- Aliases = httpd_util:multi_lookup(ConfigDB, alias),
- {_, Path, _AfterPath}
- = mod_alias:real_name(ConfigDB, RequestURI, Aliases),
- Pwd = filename:dirname(Path),
- filename:join(Pwd, FileName).
-
-%%
-%% echo directive
-%%
-
-echo(Info,Context,ErrorLog,[var],["DOCUMENT_NAME"],R) ->
- {ok,Context,ErrorLog,document_name(Info#mod.data,Info#mod.config_db,
- Info#mod.request_uri),R};
-echo(Info,Context,ErrorLog,[var],["DOCUMENT_URI"],R) ->
- {ok,Context,ErrorLog,document_uri(Info#mod.config_db,
- Info#mod.request_uri),R};
-echo(Info,Context,ErrorLog,[var],["QUERY_STRING_UNESCAPED"],R) ->
- {ok,Context,ErrorLog,query_string_unescaped(Info#mod.request_uri),R};
-echo(Info,Context,ErrorLog,[var],["DATE_LOCAL"],R) ->
- {ok,Context,ErrorLog,date_local(),R};
-echo(Info,Context,ErrorLog,[var],["DATE_GMT"],R) ->
- {ok,Context,ErrorLog,date_gmt(),R};
-echo(Info,Context,ErrorLog,[var],["LAST_MODIFIED"],R) ->
- {ok,Context,ErrorLog,last_modified(Info#mod.data,Info#mod.config_db,
- Info#mod.request_uri),R};
-echo(Info,Context,ErrorLog,TagList,ValueList,R) ->
- {ok,Context,
- [{internal_info,?NICE("echo directive has a spurious tag")}|
- ErrorLog],"(none)",R}.
-
-document_name(Data,ConfigDB,RequestURI) ->
- Path = mod_alias:path(Data,ConfigDB,RequestURI),
- case regexp:match(Path,"[^/]*\$") of
- {match,Start,Length} ->
- string:substr(Path,Start,Length);
- nomatch ->
- "(none)"
- end.
-
-document_uri(ConfigDB, RequestURI) ->
- Aliases = httpd_util:multi_lookup(ConfigDB, alias),
- {Path, AfterPath} =
- case mod_alias:real_name(ConfigDB, RequestURI, Aliases) of
- {_, Name, {[], []}} ->
- {Name, ""};
- {_, Name, {PathInfo, []}} ->
- {Name, "/"++PathInfo};
- {_, Name, {PathInfo, QueryString}} ->
- {Name, "/"++PathInfo++"?"++QueryString};
- {_, Name, _} ->
- {Name, ""};
- Gurka ->
- io:format("Gurka: ~p~n", [Gurka])
- end,
- VirtualPath = string:substr(RequestURI, 1,
- length(RequestURI)-length(AfterPath)),
- {match, Start, Length} = regexp:match(Path,"[^/]*\$"),
- FileName = string:substr(Path,Start,Length),
- case regexp:match(VirtualPath, FileName++"\$") of
- {match, _, _} ->
- httpd_util:decode_hex(VirtualPath)++AfterPath;
- nomatch ->
- string:strip(httpd_util:decode_hex(VirtualPath),right,$/)++
- "/"++FileName++AfterPath
- end.
-
-query_string_unescaped(RequestURI) ->
- case regexp:match(RequestURI,"[\?].*\$") of
- {match,Start,Length} ->
- %% Escape all shell-special variables with \
- escape(string:substr(RequestURI,Start+1,Length-1));
- nomatch ->
- "(none)"
- end.
-
-escape([]) -> [];
-escape([$;|R]) -> [$\\,$;|escape(R)];
-escape([$&|R]) -> [$\\,$&|escape(R)];
-escape([$(|R]) -> [$\\,$(|escape(R)];
-escape([$)|R]) -> [$\\,$)|escape(R)];
-escape([$||R]) -> [$\\,$||escape(R)];
-escape([$^|R]) -> [$\\,$^|escape(R)];
-escape([$<|R]) -> [$\\,$<|escape(R)];
-escape([$>|R]) -> [$\\,$>|escape(R)];
-escape([$\n|R]) -> [$\\,$\n|escape(R)];
-escape([$ |R]) -> [$\\,$ |escape(R)];
-escape([$\t|R]) -> [$\\,$\t|escape(R)];
-escape([C|R]) -> [C|escape(R)].
-
-date_local() ->
- {{Year,Month,Day},{Hour,Minute,Second}}=calendar:local_time(),
- %% Time format hard-wired to: "%a %b %e %T %Y" according to strftime(3)
- io_lib:format("~s ~s ~2w ~2.2.0w:~2.2.0w:~2.2.0w ~w",
- [httpd_util:day(calendar:day_of_the_week(Year,Month,Day)),
- httpd_util:month(Month),Day,Hour,Minute,Second,Year]).
-
-date_gmt() ->
- {{Year,Month,Day},{Hour,Minute,Second}}=calendar:universal_time(),
- %% Time format hard-wired to: "%a %b %e %T %Z %Y" according to strftime(3)
- io_lib:format("~s ~s ~2w ~2.2.0w:~2.2.0w:~2.2.0w GMT ~w",
- [httpd_util:day(calendar:day_of_the_week(Year,Month,Day)),
- httpd_util:month(Month),Day,Hour,Minute,Second,Year]).
-
-last_modified(Data,ConfigDB,RequestURI) ->
- {ok,FileInfo}=file:read_file_info(mod_alias:path(Data,ConfigDB,RequestURI)),
- {{Year,Month,Day},{Hour,Minute,Second}}=FileInfo#file_info.mtime,
- io_lib:format("~s ~s ~2w ~2.2.0w:~2.2.0w:~2.2.0w ~w",
- [httpd_util:day(calendar:day_of_the_week(Year,Month,Day)),
- httpd_util:month(Month),Day,Hour,Minute,Second,Year]).
-
-%%
-%% fsize directive
-%%
-
-fsize(Info,Context,ErrorLog,[virtual],[VirtualPath],R) ->
- Aliases=httpd_util:multi_lookup(Info#mod.config_db,alias),
- {_,Path,AfterPath}=
- mod_alias:real_name(Info#mod.config_db,VirtualPath,Aliases),
- fsize(Info, Context, ErrorLog, R, Path);
-fsize(Info,Context,ErrorLog,[file],[FileName],R) ->
- Path=file(Info#mod.config_db,Info#mod.request_uri,FileName),
- fsize(Info,Context,ErrorLog,R,Path);
-fsize(Info,Context,ErrorLog,TagList,ValueList,R) ->
- {ok,Context,[{internal_info,?NICE("fsize directive has a spurious tag")}|
- ErrorLog],httpd_util:key1search(Context,errmsg,""),R}.
-
-fsize(Info,Context,ErrorLog,R,Path) ->
- case file:read_file_info(Path) of
- {ok,FileInfo} ->
- case httpd_util:key1search(Context,sizefmt) of
- "bytes" ->
- {ok,Context,ErrorLog,
- integer_to_list(FileInfo#file_info.size),R};
- "abbrev" ->
- Size = integer_to_list(trunc(FileInfo#file_info.size/1024+1))++"k",
- {ok,Context,ErrorLog,Size,R};
- Value->
- {ok,Context,
- [{internal_info,
- ?NICE("fsize directive has a spurious tag value ("++
- Value++")")}|
- ErrorLog],
- httpd_util:key1search(Context, errmsg, ""), R}
- end;
- {error,Reason} ->
- {ok,Context,[{internal_info,?NICE("Can't open "++Path)}|ErrorLog],
- httpd_util:key1search(Context,errmsg,""),R}
- end.
-
-%%
-%% flastmod directive
-%%
-
-flastmod(Info, Context, ErrorLog, [virtual], [VirtualPath],R) ->
- Aliases=httpd_util:multi_lookup(Info#mod.config_db,alias),
- {_,Path,AfterPath}=
- mod_alias:real_name(Info#mod.config_db,VirtualPath,Aliases),
- flastmod(Info,Context,ErrorLog,R,Path);
-flastmod(Info, Context, ErrorLog, [file], [FileName], R) ->
- Path = file(Info#mod.config_db, Info#mod.request_uri, FileName),
- flastmod(Info, Context, ErrorLog, R, Path);
-flastmod(Info,Context,ErrorLog,TagList,ValueList,R) ->
- {ok,Context,[{internal_info,?NICE("flastmod directive has a spurious tag")}|
- ErrorLog],httpd_util:key1search(Context,errmsg,""),R}.
-
-flastmod(Info,Context,ErrorLog,R,File) ->
- case file:read_file_info(File) of
- {ok,FileInfo} ->
- {{Yr,Mon,Day},{Hour,Minute,Second}}=FileInfo#file_info.mtime,
- Result=
- io_lib:format("~s ~s ~2w ~w:~w:~w ~w",
- [httpd_util:day(
- calendar:day_of_the_week(Yr,Mon, Day)),
- httpd_util:month(Mon),Day,Hour,Minute,Second, Yr]),
- {ok,Context,ErrorLog,Result,R};
- {error,Reason} ->
- {ok,Context,[{internal_info,?NICE("Can't open "++File)}|ErrorLog],
- httpd_util:key1search(Context,errmsg,""),R}
- end.
-
-%%
-%% exec directive
-%%
-
-exec(Info,Context,ErrorLog,[cmd],[Command],R) ->
- ?vtrace("exec cmd:~n Command: ~p",[Command]),
- cmd(Info,Context,ErrorLog,R,Command);
-exec(Info,Context,ErrorLog,[cgi],[RequestURI],R) ->
- ?vtrace("exec cgi:~n RequestURI: ~p",[RequestURI]),
- cgi(Info,Context,ErrorLog,R,RequestURI);
-exec(Info,Context,ErrorLog,TagList,ValueList,R) ->
- ?vtrace("exec with spurious tag:"
- "~n TagList: ~p"
- "~n ValueList: ~p",
- [TagList,ValueList]),
- {ok, Context,
- [{internal_info,?NICE("exec directive has a spurious tag")}|
- ErrorLog], httpd_util:key1search(Context,errmsg,""),R}.
-
-%% cmd
-
-cmd(Info, Context, ErrorLog, R, Command) ->
- process_flag(trap_exit,true),
- Env = env(Info),
- Dir = filename:dirname(Command),
- Port = (catch open_port({spawn,Command},[stream,{cd,Dir},{env,Env}])),
- case Port of
- P when port(P) ->
- {NewErrorLog, Result} = proxy(Port, ErrorLog),
- {ok, Context, NewErrorLog, Result, R};
- {'EXIT', Reason} ->
- ?vlog("open port failed: exit"
- "~n URI: ~p"
- "~n Reason: ~p",
- [Info#mod.request_uri,Reason]),
- exit({open_port_failed,Reason,
- [{uri,Info#mod.request_uri},{script,Command},
- {env,Env},{dir,Dir}]});
- O ->
- ?vlog("open port failed: unknown result"
- "~n URI: ~p"
- "~n O: ~p",
- [Info#mod.request_uri,O]),
- exit({open_port_failed,O,
- [{uri,Info#mod.request_uri},{script,Command},
- {env,Env},{dir,Dir}]})
- end.
-
-env(Info) ->
- [{"DOCUMENT_NAME",document_name(Info#mod.data,Info#mod.config_db,
- Info#mod.request_uri)},
- {"DOCUMENT_URI", document_uri(Info#mod.config_db, Info#mod.request_uri)},
- {"QUERY_STRING_UNESCAPED", query_string_unescaped(Info#mod.request_uri)},
- {"DATE_LOCAL", date_local()},
- {"DATE_GMT", date_gmt()},
- {"LAST_MODIFIED", last_modified(Info#mod.data, Info#mod.config_db,
- Info#mod.request_uri)}
- ].
-
-%% cgi
-
-cgi(Info, Context, ErrorLog, R, RequestURI) ->
- ScriptAliases = httpd_util:multi_lookup(Info#mod.config_db, script_alias),
- case mod_alias:real_script_name(Info#mod.config_db, RequestURI,
- ScriptAliases) of
- {Script, AfterScript} ->
- exec_script(Info,Script,AfterScript,ErrorLog,Context,R);
- not_a_script ->
- {ok, Context,
- [{internal_info, ?NICE(RequestURI++" is not a script")}|
- ErrorLog], httpd_util:key1search(Context, errmsg, ""),R}
- end.
-
-remove_header([]) ->
- [];
-remove_header([$\n,$\n|Rest]) ->
- Rest;
-remove_header([C|Rest]) ->
- remove_header(Rest).
-
-
-exec_script(Info,Script,AfterScript,ErrorLog,Context,R) ->
- process_flag(trap_exit,true),
- Aliases = httpd_util:multi_lookup(Info#mod.config_db, alias),
- {_, Path, AfterPath} = mod_alias:real_name(Info#mod.config_db,
- Info#mod.request_uri,
- Aliases),
- Env = env(Info)++mod_cgi:env(Info, Path, AfterPath),
- Dir = filename:dirname(Path),
- Port = (catch open_port({spawn,Script},[stream,{env, Env},{cd, Dir}])),
- case Port of
- P when port(P) ->
- %% Send entity body to port.
- Res = case Info#mod.entity_body of
- [] ->
- true;
- EntityBody ->
- (catch port_command(Port,EntityBody))
- end,
- case Res of
- {'EXIT', Reason} ->
- ?vlog("port send failed:"
- "~n Port: ~p"
- "~n URI: ~p"
- "~n Reason: ~p",
- [Port,Info#mod.request_uri,Reason]),
- exit({open_cmd_failed,Reason,
- [{mod,?MODULE},{port,Port},
- {uri,Info#mod.request_uri},
- {script,Script},{env,Env},{dir,Dir},
- {ebody_size,sz(Info#mod.entity_body)}]});
- true ->
- {NewErrorLog, Result} = proxy(Port, ErrorLog),
- {ok, Context, NewErrorLog, remove_header(Result), R}
- end;
- {'EXIT', Reason} ->
- ?vlog("open port failed: exit"
- "~n URI: ~p"
- "~n Reason: ~p",
- [Info#mod.request_uri,Reason]),
- exit({open_port_failed,Reason,
- [{mod,?MODULE},{uri,Info#mod.request_uri},{script,Script},
- {env,Env},{dir,Dir}]});
- O ->
- ?vlog("open port failed: unknown result"
- "~n URI: ~p"
- "~n O: ~p",
- [Info#mod.request_uri,O]),
- exit({open_port_failed,O,
- [{mod,?MODULE},{uri,Info#mod.request_uri},{script,Script},
- {env,Env},{dir,Dir}]})
- end.
-
-
-%%
-%% Port communication
-%%
-
-proxy(Port,ErrorLog) ->
- process_flag(trap_exit, true),
- proxy(Port, ErrorLog, []).
-
-proxy(Port, ErrorLog, Result) ->
- receive
- {Port, {data, Response}} ->
- proxy(Port, ErrorLog, lists:append(Result,Response));
- {'EXIT', Port, normal} when port(Port) ->
- process_flag(trap_exit, false),
- {ErrorLog, Result};
- {'EXIT', Port, Reason} when port(Port) ->
- process_flag(trap_exit, false),
- {[{internal_info,
- ?NICE("Scrambled output from CGI-script")}|ErrorLog],
- Result};
- {'EXIT', Pid, Reason} when pid(Pid) ->
- process_flag(trap_exit, false),
- {'EXIT', Pid, Reason};
- %% This should not happen!
- WhatEver ->
- process_flag(trap_exit, false),
- {ErrorLog, Result}
- end.
-
-
-%% ------
-%% Temporary until I figure out a way to fix send_in_chunks
-%% (comments and directives that start in one chunk but end
-%% in another is not handled).
-%%
-
-send_in(Info, Path,Head, {ok,FileInfo}) ->
- case file:read_file(Path) of
- {ok, Bin} ->
- send_in1(Info, binary_to_list(Bin), Head, FileInfo);
- {error, Reason} ->
- ?vlog("failed reading file: ~p",[Reason]),
- {error, {open,Reason}}
- end;
-send_in(Info,Path,Head,{error,Reason}) ->
- ?vlog("failed open file: ~p",[Reason]),
- {error, {open,Reason}}.
-
-send_in1(Info, Data,Head,FileInfo) ->
- {ok, _Context, Err, ParsedBody} = parse(Info,Data,?DEFAULT_CONTEXT,[],[]),
- Size = length(ParsedBody),
- ?vdebug("send_in1 -> Size: ~p",[Size]),
- Head1 = case Info#mod.http_version of
- "HTTP/1.1"->
- Head ++
- "Content-Length: " ++
- integer_to_list(Size) ++
- "\r\nEtag:" ++
- httpd_util:create_etag(FileInfo,Size) ++"\r\n" ++
- "Last-Modified: " ++
- httpd_util:rfc1123_date(FileInfo#file_info.mtime) ++
- "\r\n\r\n";
- _->
- %% i.e http/1.0 and http/0.9
- Head ++
- "Content-Length: " ++
- integer_to_list(Size) ++
- "\r\nLast-Modified: " ++
- httpd_util:rfc1123_date(FileInfo#file_info.mtime) ++
- "\r\n\r\n"
- end,
- httpd_socket:deliver(Info#mod.socket_type,Info#mod.socket,
- [Head1,ParsedBody]),
- {ok, Err, Size}.
-
-
-
-%%
-%% Addition to "Fuzzy" HTML parser. This is actually a ugly hack to
-%% avoid putting to much data on the heap. To be rewritten...
-%%
-
-% -define(CHUNK_SIZE, 4096).
-
-% send_in_chunks(Info, Path) ->
-% ?DEBUG("send_in_chunks -> Path: ~p",[Path]),
-% case file:open(Path, [read, raw]) of
-% {ok, Stream} ->
-% send_in_chunks(Info, Stream, ?DEFAULT_CONTEXT,[]);
-% {error, Reason} ->
-% ?ERROR("Failed open file: ~p",[Reason]),
-% {error, {open,Reason}}
-% end.
-
-% send_in_chunks(Info, Stream, Context, ErrorLog) ->
-% case file:read(Stream, ?CHUNK_SIZE) of
-% {ok, Data} ->
-% ?DEBUG("send_in_chunks -> read ~p bytes",[length(Data)]),
-% {ok, NewContext, NewErrorLog, ParsedBody}=
-% parse(Info, Data, Context, ErrorLog, []),
-% httpd_socket:deliver(Info#mod.socket_type,
-% Info#mod.socket, ParsedBody),
-% send_in_chunks(Info,Stream,NewContext,NewErrorLog);
-% eof ->
-% {ok, ErrorLog};
-% {error, Reason} ->
-% ?ERROR("Failed read from file: ~p",[Reason]),
-% {error, {read,Reason}}
-% end.
-
-
-%%
-%% "Fuzzy" HTML parser
-%%
-
-parse(Info,Body) ->
- parse(Info, Body, ?DEFAULT_CONTEXT, [], []).
-
-parse(Info, [], Context, ErrorLog, Result) ->
- {ok, Context, lists:reverse(ErrorLog), lists:reverse(Result)};
-parse(Info,[$<,$!,$-,$-,$#|R1],Context,ErrorLog,Result) ->
- ?DEBUG("parse -> start command directive when length(R1): ~p",[length(R1)]),
- case catch parse0(R1,Context) of
- {parse_error,Reason} ->
- parse(Info,R1,Context,[{internal_info,?NICE(Reason)}|ErrorLog],
- [$#,$-,$-,$!,$<|Result]);
- {ok,Context,Command,TagList,ValueList,R2} ->
- ?DEBUG("parse -> Command: ~p",[Command]),
- {ok,NewContext,NewErrorLog,MoreResult,R3}=
- handle(Info,Context,ErrorLog,Command,TagList,ValueList,R2),
- parse(Info,R3,NewContext,NewErrorLog,lists:reverse(MoreResult)++Result)
- end;
-parse(Info,[$<,$!,$-,$-|R1],Context,ErrorLog,Result) ->
- ?DEBUG("parse -> start comment when length(R1) = ~p",[length(R1)]),
- case catch parse5(R1,[],0) of
- {parse_error,Reason} ->
- ?ERROR("parse -> parse error: ~p",[Reason]),
- parse(Info,R1,Context,[{internal_info,?NICE(Reason)}|ErrorLog],Result);
- {Comment,R2} ->
- ?DEBUG("parse -> length(Comment) = ~p, length(R2) = ~p",
- [length(Comment),length(R2)]),
- parse(Info,R2,Context,ErrorLog,Comment++Result)
- end;
-parse(Info,[C|R],Context,ErrorLog,Result) ->
- parse(Info,R,Context,ErrorLog,[C|Result]).
-
-handle(Info,Context,ErrorLog,Command,TagList,ValueList,R) ->
- case catch apply(?MODULE,Command,[Info,Context,ErrorLog,TagList,ValueList,
- R]) of
- {'EXIT',{undef,_}} ->
- throw({parse_error,"Unknown command "++atom_to_list(Command)++
- " in parsed doc"});
- Result ->
- Result
- end.
-
-parse0([],Context) ->
- throw({parse_error,"Premature EOF in parsed file"});
-parse0([$-,$-,$>|R],Context) ->
- throw({parse_error,"Premature EOF in parsed file"});
-parse0([$ |R],Context) ->
- parse0(R,Context);
-parse0(String,Context) ->
- parse1(String,Context,"").
-
-parse1([],Context,Command) ->
- throw({parse_error,"Premature EOF in parsed file"});
-parse1([$-,$-,$>|R],Context,Command) ->
- throw({parse_error,"Premature EOF in parsed file"});
-parse1([$ |R],Context,Command) ->
- parse2(R,Context,list_to_atom(lists:reverse(Command)),[],[],"");
-parse1([C|R],Context,Command) ->
- parse1(R,Context,[C|Command]).
-
-parse2([],Context,Command,TagList,ValueList,Tag) ->
- throw({parse_error,"Premature EOF in parsed file"});
-parse2([$-,$-,$>|R],Context,Command,TagList,ValueList,Tag) ->
- {ok,Context,Command,TagList,ValueList,R};
-parse2([$ |R],Context,Command,TagList,ValueList,Tag) ->
- parse2(R,Context,Command,TagList,ValueList,Tag);
-parse2([$=|R],Context,Command,TagList,ValueList,Tag) ->
- parse3(R,Context,Command,[list_to_atom(lists:reverse(Tag))|TagList],
- ValueList);
-parse2([C|R],Context,Command,TagList,ValueList,Tag) ->
- parse2(R,Context,Command,TagList,ValueList,[C|Tag]).
-
-parse3([],Context,Command,TagList,ValueList) ->
- throw({parse_error,"Premature EOF in parsed file"});
-parse3([$-,$-,$>|R],Context,Command,TagList,ValueList) ->
- throw({parse_error,"Premature EOF in parsed file"});
-parse3([$ |R],Context,Command,TagList,ValueList) ->
- parse3(R,Context,Command,TagList,ValueList);
-parse3([$"|R],Context,Command,TagList,ValueList) ->
- parse4(R,Context,Command,TagList,ValueList,"");
-parse3(String,Context,Command,TagList,ValueList) ->
- throw({parse_error,"Premature EOF in parsed file"}).
-
-parse4([],Context,Command,TagList,ValueList,Value) ->
- throw({parse_error,"Premature EOF in parsed file"});
-parse4([$-,$-,$>|R],Context,Command,TagList,ValueList,Value) ->
- throw({parse_error,"Premature EOF in parsed file"});
-parse4([$"|R],Context,Command,TagList,ValueList,Value) ->
- parse2(R,Context,Command,TagList,[lists:reverse(Value)|ValueList],"");
-parse4([C|R],Context,Command,TagList,ValueList,Value) ->
- parse4(R,Context,Command,TagList,ValueList,[C|Value]).
-
-parse5([],Comment,Depth) ->
- ?ERROR("parse5 -> unterminated comment of ~p bytes when Depth = ~p",
- [length(Comment),Depth]),
- throw({parse_error,"Premature EOF in parsed file"});
-parse5([$<,$!,$-,$-|R],Comment,Depth) ->
- parse5(R,[$-,$-,$!,$<|Comment],Depth+1);
-parse5([$-,$-,$>|R],Comment,0) ->
- {">--"++Comment++"--!<",R};
-parse5([$-,$-,$>|R],Comment,Depth) ->
- parse5(R,[$>,$-,$-|Comment],Depth-1);
-parse5([C|R],Comment,Depth) ->
- parse5(R,[C|Comment],Depth).
-
-
-sz(B) when binary(B) -> {binary,size(B)};
-sz(L) when list(L) -> {list,length(L)};
-sz(_) -> undefined.
-
-
-%% send_error - Handle failure to send the file
-%%
-send_error({open,Reason},Info,Path) -> open_error(Reason,Info,Path);
-send_error({read,Reason},Info,Path) -> read_error(Reason,Info,Path).
-
-
-%% open_error - Handle file open failure
-%%
-open_error(eacces,Info,Path) ->
- open_error(403,Info,Path,"");
-open_error(enoent,Info,Path) ->
- open_error(404,Info,Path,"");
-open_error(enotdir,Info,Path) ->
- open_error(404,Info,Path,
- ": A component of the file name is not a directory");
-open_error(emfile,_Info,Path) ->
- open_error(500,none,Path,": To many open files");
-open_error({enfile,_},_Info,Path) ->
- open_error(500,none,Path,": File table overflow");
-open_error(_Reason,_Info,Path) ->
- open_error(500,none,Path,"").
-
-open_error(StatusCode,none,Path,Reason) ->
- {StatusCode,none,?NICE("Can't open "++Path++Reason)};
-open_error(StatusCode,Info,Path,Reason) ->
- {StatusCode,Info#mod.request_uri,?NICE("Can't open "++Path++Reason)}.
-
-read_error(_Reason,_Info,Path) ->
- read_error(500,none,Path,"").
-
-read_error(StatusCode,none,Path,Reason) ->
- {StatusCode,none,?NICE("Can't read "++Path++Reason)};
-read_error(StatusCode,Info,Path,Reason) ->
- {StatusCode,Info#mod.request_uri,?NICE("Can't read "++Path++Reason)}.
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_log.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_log.erl
deleted file mode 100644
index 29fa2cfd11..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_log.erl
+++ /dev/null
@@ -1,250 +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: mod_log.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
-%%
--module(mod_log).
--export([do/1,error_log/5,security_log/2,load/2,store/2,remove/1]).
-
--export([report_error/2]).
-
--include("httpd.hrl").
-
--define(VMODULE,"LOG").
--include("httpd_verbosity.hrl").
-
-%% do
-
-do(Info) ->
- AuthUser = auth_user(Info#mod.data),
- Date = custom_date(),
- log_internal_info(Info,Date,Info#mod.data),
- case httpd_util:key1search(Info#mod.data,status) of
- %% A status code has been generated!
- {StatusCode,PhraseArgs,Reason} ->
- transfer_log(Info,"-",AuthUser,Date,StatusCode,0),
- if
- StatusCode >= 400 ->
- error_log(Info,Date,Reason);
- true ->
- not_an_error
- end,
- {proceed,Info#mod.data};
- %% No status code has been generated!
- undefined ->
- case httpd_util:key1search(Info#mod.data,response) of
- {already_sent,StatusCode,Size} ->
- transfer_log(Info,"-",AuthUser,Date,StatusCode,Size),
- {proceed,Info#mod.data};
- {response,Head,Body} ->
- Size=httpd_util:key1search(Head,content_length,unknown),
- Code=httpd_util:key1search(Head,code,unknown),
- transfer_log(Info,"-",AuthUser,Date,Code,Size),
- {proceed,Info#mod.data};
- {StatusCode,Response} ->
- transfer_log(Info,"-",AuthUser,Date,200,
- httpd_util:flatlength(Response)),
- {proceed,Info#mod.data};
- undefined ->
- transfer_log(Info,"-",AuthUser,Date,200,0),
- {proceed,Info#mod.data}
- end
- end.
-
-custom_date() ->
- LocalTime=calendar:local_time(),
- UniversalTime=calendar:universal_time(),
- Minutes=round(diff_in_minutes(LocalTime,UniversalTime)),
- {{YYYY,MM,DD},{Hour,Min,Sec}}=LocalTime,
- Date =
- io_lib:format("~.2.0w/~.3s/~.4w:~.2.0w:~.2.0w:~.2.0w ~c~.2.0w~.2.0w",
- [DD, httpd_util:month(MM), YYYY, Hour, Min, Sec,
- sign(Minutes),
- abs(Minutes) div 60, abs(Minutes) rem 60]),
- lists:flatten(Date).
-
-diff_in_minutes(L,U) ->
- (calendar:datetime_to_gregorian_seconds(L) -
- calendar:datetime_to_gregorian_seconds(U))/60.
-
-sign(Minutes) when Minutes > 0 ->
- $+;
-sign(Minutes) ->
- $-.
-
-auth_user(Data) ->
- case httpd_util:key1search(Data,remote_user) of
- undefined ->
- "-";
- RemoteUser ->
- RemoteUser
- end.
-
-%% log_internal_info
-
-log_internal_info(Info,Date,[]) ->
- ok;
-log_internal_info(Info,Date,[{internal_info,Reason}|Rest]) ->
- error_log(Info,Date,Reason),
- log_internal_info(Info,Date,Rest);
-log_internal_info(Info,Date,[_|Rest]) ->
- log_internal_info(Info,Date,Rest).
-
-%% transfer_log
-
-transfer_log(Info,RFC931,AuthUser,Date,StatusCode,Bytes) ->
- case httpd_util:lookup(Info#mod.config_db,transfer_log) of
- undefined ->
- no_transfer_log;
- TransferLog ->
- {PortNumber,RemoteHost}=(Info#mod.init_data)#init_data.peername,
- case (catch io:format(TransferLog, "~s ~s ~s [~s] \"~s\" ~w ~w~n",
- [RemoteHost, RFC931, AuthUser,
- Date, Info#mod.request_line,
- StatusCode, Bytes])) of
- ok ->
- ok;
- Error ->
- error_logger:error_report(Error)
- end
- end.
-
-%% security log
-
-security_log(Info, Reason) ->
- case httpd_util:lookup(Info#mod.config_db, security_log) of
- undefined ->
- no_security_log;
- SecurityLog ->
- io:format(SecurityLog,"[~s] ~s~n", [custom_date(), Reason])
- end.
-
-%% error_log
-
-error_log(Info,Date,Reason) ->
- case httpd_util:lookup(Info#mod.config_db, error_log) of
- undefined ->
- no_error_log;
- ErrorLog ->
- {PortNumber,RemoteHost}=(Info#mod.init_data)#init_data.peername,
- io:format(ErrorLog,"[~s] access to ~s failed for ~s, reason: ~p~n",
- [Date,Info#mod.request_uri,RemoteHost,Reason])
- end.
-
-error_log(SocketType,Socket,ConfigDB,{PortNumber,RemoteHost},Reason) ->
- case httpd_util:lookup(ConfigDB,error_log) of
- undefined ->
- no_error_log;
- ErrorLog ->
- Date=custom_date(),
- io:format(ErrorLog,"[~s] server crash for ~s, reason: ~p~n",
- [Date,RemoteHost,Reason]),
- ok
- end.
-
-report_error(ConfigDB,Error) ->
- case httpd_util:lookup(ConfigDB,error_log) of
- undefined ->
- no_error_log;
- ErrorLog ->
- Date=custom_date(),
- io:format(ErrorLog,"[~s] reporting error: ~s~n",[Date,Error]),
- ok
- end.
-
-%%
-%% Configuration
-%%
-
-%% load
-
-load([$T,$r,$a,$n,$s,$f,$e,$r,$L,$o,$g,$ |TransferLog],[]) ->
- {ok,[],{transfer_log,httpd_conf:clean(TransferLog)}};
-load([$E,$r,$r,$o,$r,$L,$o,$g,$ |ErrorLog],[]) ->
- {ok,[],{error_log,httpd_conf:clean(ErrorLog)}};
-load([$S,$e,$c,$u,$r,$i,$t,$y,$L,$o,$g,$ |SecurityLog], []) ->
- {ok, [], {security_log, httpd_conf:clean(SecurityLog)}}.
-
-%% store
-
-store({transfer_log,TransferLog},ConfigList) ->
- case create_log(TransferLog,ConfigList) of
- {ok,TransferLogStream} ->
- {ok,{transfer_log,TransferLogStream}};
- {error,Reason} ->
- {error,Reason}
- end;
-store({error_log,ErrorLog},ConfigList) ->
- case create_log(ErrorLog,ConfigList) of
- {ok,ErrorLogStream} ->
- {ok,{error_log,ErrorLogStream}};
- {error,Reason} ->
- {error,Reason}
- end;
-store({security_log, SecurityLog},ConfigList) ->
- case create_log(SecurityLog, ConfigList) of
- {ok, SecurityLogStream} ->
- {ok, {security_log, SecurityLogStream}};
- {error, Reason} ->
- {error, Reason}
- end.
-
-create_log(LogFile,ConfigList) ->
- Filename = httpd_conf:clean(LogFile),
- case filename:pathtype(Filename) of
- absolute ->
- case file:open(Filename, [read,write]) of
- {ok,LogStream} ->
- file:position(LogStream,{eof,0}),
- {ok,LogStream};
- {error,_} ->
- {error,?NICE("Can't create "++Filename)}
- end;
- volumerelative ->
- case file:open(Filename, [read,write]) of
- {ok,LogStream} ->
- file:position(LogStream,{eof,0}),
- {ok,LogStream};
- {error,_} ->
- {error,?NICE("Can't create "++Filename)}
- end;
- relative ->
- case httpd_util:key1search(ConfigList,server_root) of
- undefined ->
- {error,
- ?NICE(Filename++
- " is an invalid logfile name beacuse ServerRoot is not defined")};
- ServerRoot ->
- AbsoluteFilename=filename:join(ServerRoot,Filename),
- case file:open(AbsoluteFilename, [read,write]) of
- {ok,LogStream} ->
- file:position(LogStream,{eof,0}),
- {ok,LogStream};
- {error,Reason} ->
- {error,?NICE("Can't create "++AbsoluteFilename)}
- end
- end
- end.
-
-%% remove
-
-remove(ConfigDB) ->
- lists:foreach(fun([Stream]) -> file:close(Stream) end,
- ets:match(ConfigDB,{transfer_log,'$1'})),
- lists:foreach(fun([Stream]) -> file:close(Stream) end,
- ets:match(ConfigDB,{error_log,'$1'})),
- lists:foreach(fun([Stream]) -> file:close(Stream) end,
- ets:match(ConfigDB,{security_log,'$1'})),
- ok.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_range.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_range.erl
deleted file mode 100644
index 0728bd2d91..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_range.erl
+++ /dev/null
@@ -1,397 +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: mod_range.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
-%%
--module(mod_range).
--export([do/1]).
--include("httpd.hrl").
-
-%% do
-
-
-
-do(Info) ->
- ?DEBUG("do -> entry",[]),
- case Info#mod.method of
- "GET" ->
- case httpd_util:key1search(Info#mod.data,status) of
- %% A status code has been generated!
- {StatusCode,PhraseArgs,Reason} ->
- {proceed,Info#mod.data};
- %% No status code has been generated!
- undefined ->
- case httpd_util:key1search(Info#mod.data,response) of
- %% No response has been generated!
- undefined ->
- case httpd_util:key1search(Info#mod.parsed_header,"range") of
- undefined ->
- %Not a range response
- {proceed,Info#mod.data};
- Range ->
- %%Control that there weren't a if-range field that stopped
- %%The range request in favor for the whole file
- case httpd_util:key1search(Info#mod.data,if_range) of
- send_file ->
- {proceed,Info#mod.data};
- _undefined ->
- do_get_range(Info,Range)
- end
- end;
- %% A response has been generated or sent!
- Response ->
- {proceed,Info#mod.data}
- end
- end;
- %% Not a GET method!
- _ ->
- {proceed,Info#mod.data}
- end.
-
-do_get_range(Info,Ranges) ->
- ?DEBUG("do_get_range -> Request URI: ~p",[Info#mod.request_uri]),
- Path = mod_alias:path(Info#mod.data, Info#mod.config_db,
- Info#mod.request_uri),
- {FileInfo, LastModified} =get_modification_date(Path),
- send_range_response(Path,Info,Ranges,FileInfo,LastModified).
-
-
-send_range_response(Path,Info,Ranges,FileInfo,LastModified)->
- case parse_ranges(Ranges) of
- error->
- ?ERROR("send_range_response-> Unparsable range request",[]),
- {proceed,Info#mod.data};
- {multipart,RangeList}->
- send_multi_range_response(Path,Info,RangeList);
- {Start,Stop}->
- send_range_response(Path,Info,Start,Stop,FileInfo,LastModified)
- end.
-%%More than one range specified
-%%Send a multipart reponse to the user
-%
-%%An example of an multipart range response
-
-% HTTP/1.1 206 Partial Content
-% Date:Wed 15 Nov 1995 04:08:23 GMT
-% Last-modified:Wed 14 Nov 1995 04:08:23 GMT
-% Content-type: multipart/byteranges; boundary="SeparatorString"
-%
-% --"SeparatorString"
-% Content-Type: application/pdf
-% Content-Range: bytes 500-600/1010
-% .... The data..... 101 bytes
-%
-% --"SeparatorString"
-% Content-Type: application/pdf
-% Content-Range: bytes 700-1009/1010
-% .... The data.....
-
-
-
-send_multi_range_response(Path,Info,RangeList)->
- case file:open(Path, [raw,binary]) of
- {ok, FileDescriptor} ->
- file:close(FileDescriptor),
- ?DEBUG("send_multi_range_response -> FileDescriptor: ~p",[FileDescriptor]),
- Suffix = httpd_util:suffix(Path),
- PartMimeType = httpd_util:lookup_mime_default(Info#mod.config_db,Suffix,"text/plain"),
- Date = httpd_util:rfc1123_date(),
- {FileInfo,LastModified}=get_modification_date(Path),
- case valid_ranges(RangeList,Path,FileInfo) of
- {ValidRanges,true}->
- ?DEBUG("send_multi_range_response -> Ranges are valid:",[]),
- %Apache breaks the standard by sending the size field in the Header.
- Header = [{code,206},
- {content_type,"multipart/byteranges;boundary=RangeBoundarySeparator"},
- {etag,httpd_util:create_etag(FileInfo)},
- {last_modified,LastModified}
- ],
- ?DEBUG("send_multi_range_response -> Valid Ranges: ~p",[RagneList]),
- Body={fun send_multiranges/4,[ValidRanges,Info,PartMimeType,Path]},
- {proceed,[{response,{response,Header,Body}}|Info#mod.data]};
- _ ->
- {proceed, [{status, {416,"Range not valid",bad_range_boundaries }}]}
- end;
- {error, Reason} ->
- ?ERROR("do_get -> failed open file: ~p",[Reason]),
- {proceed,Info#mod.data}
- end.
-
-send_multiranges(ValidRanges,Info,PartMimeType,Path)->
- ?DEBUG("send_multiranges -> Start sending the ranges",[]),
- case file:open(Path, [raw,binary]) of
- {ok,FileDescriptor} ->
- lists:foreach(fun(Range)->
- send_multipart_start(Range,Info,PartMimeType,FileDescriptor)
- end,ValidRanges),
- file:close(FileDescriptor),
- %%Sends an end of the multipart
- httpd_socket:deliver(Info#mod.socket_type,Info#mod.socket,"\r\n--RangeBoundarySeparator--"),
- sent;
- _ ->
- close
- end.
-
-send_multipart_start({{Start,End},{StartByte,EndByte,Size}},Info,PartMimeType,FileDescriptor)when StartByte<Size->
- PartHeader=["\r\n--RangeBoundarySeparator\r\n","Content-type: ",PartMimeType,"\r\n",
- "Content-Range:bytes=",integer_to_list(StartByte),"-",integer_to_list(EndByte),"/",
- integer_to_list(Size),"\r\n\r\n"],
- send_part_start(Info#mod.socket_type,Info#mod.socket,PartHeader,FileDescriptor,Start,End);
-
-
-send_multipart_start({{Start,End},{StartByte,EndByte,Size}},Info,PartMimeType,FileDescriptor)->
- PartHeader=["\r\n--RangeBoundarySeparator\r\n","Content-type: ",PartMimeType,"\r\n",
- "Content-Range:bytes=",integer_to_list(Size-(StartByte-Size)),"-",integer_to_list(EndByte),"/",
- integer_to_list(Size),"\r\n\r\n"],
- send_part_start(Info#mod.socket_type,Info#mod.socket,PartHeader,FileDescriptor,Start,End).
-
-send_part_start(SocketType,Socket,PartHeader,FileDescriptor,Start,End)->
- case httpd_socket:deliver(SocketType,Socket,PartHeader) of
- ok ->
- send_part_start(SocketType,Socket,FileDescriptor,Start,End);
- _ ->
- close
- end.
-
-send_range_response(Path,Info,Start,Stop,FileInfo,LastModified)->
- case file:open(Path, [raw,binary]) of
- {ok, FileDescriptor} ->
- file:close(FileDescriptor),
- ?DEBUG("send_range_response -> FileDescriptor: ~p",[FileDescriptor]),
- Suffix = httpd_util:suffix(Path),
- MimeType = httpd_util:lookup_mime_default(Info#mod.config_db,Suffix,"text/plain"),
- Date = httpd_util:rfc1123_date(),
- Size = get_range_size(Start,Stop,FileInfo),
- case valid_range(Start,Stop,FileInfo) of
- {true,StartByte,EndByte,TotByte}->
- Head=[{code,206},{content_type, MimeType},
- {last_modified, LastModified},
- {etag,httpd_util:create_etag(FileInfo)},
- {content_range,["bytes=",integer_to_list(StartByte),"-",
- integer_to_list(EndByte),"/",integer_to_list(TotByte)]},
- {content_length,Size}],
- BodyFunc=fun send_range_body/5,
- Arg=[Info#mod.socket_type, Info#mod.socket,Path,Start,Stop],
- {proceed,[{response,{response,Head,{BodyFunc,Arg}}}|Info#mod.data]};
- {false,Reason} ->
- {proceed, [{status, {416,Reason,bad_range_boundaries }}]}
- end;
- {error, Reason} ->
- ?ERROR("send_range_response -> failed open file: ~p",[Reason]),
- {proceed,Info#mod.data}
- end.
-
-
-send_range_body(SocketType,Socket,Path,Start,End) ->
- ?DEBUG("mod_range -> send_range_body",[]),
- case file:open(Path, [raw,binary]) of
- {ok,FileDescriptor} ->
- send_part_start(SocketType,Socket,FileDescriptor,Start,End),
- file:close(FileDescriptor);
- _ ->
- close
- end.
-
-send_part_start(SocketType,Socket,FileDescriptor,Start,End) ->
- case Start of
- from_end ->
- file:position(FileDescriptor,{eof,End}),
- send_body(SocketType,Socket,FileDescriptor);
- from_start ->
- file:position(FileDescriptor,{bof,End}),
- send_body(SocketType,Socket,FileDescriptor);
- Byte when integer(Byte) ->
- file:position(FileDescriptor,{bof,Start}),
- send_part(SocketType,Socket,FileDescriptor,End)
- end,
- sent.
-
-
-%%This function could replace send_body by calling it with Start=0 end =FileSize
-%% But i gues it would be stupid when we look at performance
-send_part(SocketType,Socket,FileDescriptor,End)->
- case file:position(FileDescriptor,{cur,0}) of
- {ok,NewPos} ->
- if
- NewPos > End ->
- ok;
- true ->
- Size=get_file_chunk_size(NewPos,End,?FILE_CHUNK_SIZE),
- case file:read(FileDescriptor,Size) of
- eof ->
- ok;
- {error,Reason} ->
- ok;
- {ok,Binary} ->
- case httpd_socket:deliver(SocketType,Socket,Binary) of
- socket_closed ->
- ?LOG("send_range of body -> socket closed while sending",[]),
- socket_close;
- _ ->
- send_part(SocketType,Socket,FileDescriptor,End)
- end
- end
- end;
- _->
- ok
- end.
-
-%% validate that the range is in the limits of the file
-valid_ranges(RangeList,Path,FileInfo)->
- lists:mapfoldl(fun({Start,End},Acc)->
- case Acc of
- true ->
- case valid_range(Start,End,FileInfo) of
- {true,StartB,EndB,Size}->
- {{{Start,End},{StartB,EndB,Size}},true};
- _ ->
- false
- end;
- _ ->
- {false,false}
- end
- end,true,RangeList).
-
-
-
-valid_range(from_end,End,FileInfo)->
- Size=FileInfo#file_info.size,
- if
- End < Size ->
- {true,(Size+End),Size-1,Size};
- true ->
- false
- end;
-valid_range(from_start,End,FileInfo)->
- Size=FileInfo#file_info.size,
- if
- End < Size ->
- {true,End,Size-1,Size};
- true ->
- false
- end;
-
-valid_range(Start,End,FileInfo)when Start=<End->
- case FileInfo#file_info.size of
- FileSize when Start< FileSize ->
- case FileInfo#file_info.size of
- Size when End<Size ->
- {true,Start,End,FileInfo#file_info.size};
- Size ->
- {true,Start,Size-1,Size}
- end;
- _->
- {false,"The size of the range is negative"}
- end;
-
-valid_range(Start,End,FileInfo)->
- {false,"Range starts out of file boundaries"}.
-%% Find the modification date of the file
-get_modification_date(Path)->
- case file:read_file_info(Path) of
- {ok, FileInfo0} ->
- {FileInfo0, httpd_util:rfc1123_date(FileInfo0#file_info.mtime)};
- _ ->
- {#file_info{},""}
- end.
-
-%Calculate the size of the chunk to read
-
-get_file_chunk_size(Position,End,DefaultChunkSize)when (Position+DefaultChunkSize) =< End->
- DefaultChunkSize;
-get_file_chunk_size(Position,End,DefaultChunkSize)->
- (End-Position) +1.
-
-
-
-%Get the size of the range to send. Remember that
-%A range is from startbyte up to endbyte which means that
-%the nuber of byte in a range is (StartByte-EndByte)+1
-
-get_range_size(from_end,Stop,FileInfo)->
- integer_to_list(-1*Stop);
-
-get_range_size(from_start,StartByte,FileInfo) ->
- integer_to_list((((FileInfo#file_info.size)-StartByte)));
-
-get_range_size(StartByte,EndByte,FileInfo) ->
- integer_to_list((EndByte-StartByte)+1).
-
-parse_ranges([$\ ,$b,$y,$t,$e,$s,$\=|Ranges])->
- parse_ranges([$b,$y,$t,$e,$s,$\=|Ranges]);
-parse_ranges([$b,$y,$t,$e,$s,$\=|Ranges])->
- case string:tokens(Ranges,", ") of
- [Range] ->
- parse_range(Range);
- [Range1|SplittedRanges]->
- {multipart,lists:map(fun parse_range/1,[Range1|SplittedRanges])}
- end;
-%Bad unit
-parse_ranges(Ranges)->
- io:format("Bad Ranges : ~p",[Ranges]),
- error.
-%Parse the range specification from the request to {Start,End}
-%Start=End : Numreric string | []
-
-parse_range(Range)->
- format_range(split_range(Range,[],[])).
-format_range({[],BytesFromEnd})->
- {from_end,-1*(list_to_integer(BytesFromEnd))};
-format_range({StartByte,[]})->
- {from_start,list_to_integer(StartByte)};
-format_range({StartByte,EndByte})->
- {list_to_integer(StartByte),list_to_integer(EndByte)}.
-%Last case return the splitted range
-split_range([],Current,Other)->
- {lists:reverse(Other),lists:reverse(Current)};
-
-split_range([$-|Rest],Current,Other)->
- split_range(Rest,Other,Current);
-
-split_range([N|Rest],Current,End) ->
- split_range(Rest,[N|Current],End).
-
-send_body(SocketType,Socket,FileDescriptor) ->
- case file:read(FileDescriptor,?FILE_CHUNK_SIZE) of
- {ok,Binary} ->
- ?DEBUG("send_body -> send another chunk: ~p",[size(Binary)]),
- case httpd_socket:deliver(SocketType,Socket,Binary) of
- socket_closed ->
- ?LOG("send_body -> socket closed while sending",[]),
- socket_close;
- _ ->
- send_body(SocketType,Socket,FileDescriptor)
- end;
- eof ->
- ?DEBUG("send_body -> done with this file",[]),
- eof
- end.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_responsecontrol.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_responsecontrol.erl
deleted file mode 100644
index c946098120..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_responsecontrol.erl
+++ /dev/null
@@ -1,337 +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: mod_responsecontrol.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
-%%
-
--module(mod_responsecontrol).
--export([do/1]).
-
--include("httpd.hrl").
-
-
-do(Info) ->
- ?DEBUG("do -> response_control",[]),
- case httpd_util:key1search(Info#mod.data,status) of
- %% A status code has been generated!
- {StatusCode,PhraseArgs,Reason} ->
- {proceed,Info#mod.data};
- %% No status code has been generated!
- undefined ->
- case httpd_util:key1search(Info#mod.data,response) of
- %% No response has been generated!
- undefined ->
- case do_responsecontrol(Info) of
- continue ->
- {proceed,Info#mod.data};
- Response ->
- {proceed,[Response|Info#mod.data]}
- end;
- %% A response has been generated or sent!
- Response ->
- {proceed,Info#mod.data}
- end
- end.
-
-
-%%----------------------------------------------------------------------
-%%Control that the request header did not contians any limitations
-%%wheather a response shall be createed or not
-%%----------------------------------------------------------------------
-
-do_responsecontrol(Info) ->
- ?DEBUG("do_response_control -> Request URI: ~p",[Info#mod.request_uri]),
- Path = mod_alias:path(Info#mod.data, Info#mod.config_db,
- Info#mod.request_uri),
- case file:read_file_info(Path) of
- {ok, FileInfo} ->
- control(Path,Info,FileInfo);
- _ ->
- %% The requested asset is not a plain file and then it must
- %% be generated everytime its requested
- continue
- end.
-
-%%----------------------------------------------------------------------
-%%Control the If-Match, If-None-Match, and If-Modified-Since
-%%----------------------------------------------------------------------
-
-
-%% If a client sends more then one of the if-XXXX fields in a request
-%% The standard says it does not specify the behaviuor so I specified it :-)
-%% The priority between the fields is
-%% 1.If-modified
-%% 2.If-Unmodified
-%% 3.If-Match
-%% 4.If-Nomatch
-
-%% This means if more than one of the fields are in the request the
-%% field with highest priority will be used
-
-%%If the request is a range request the If-Range field will be the winner.
-
-control(Path,Info,FileInfo)->
- case control_range(Path,Info,FileInfo) of
- undefined ->
- case control_Etag(Path,Info,FileInfo) of
- undefined ->
- case control_modification(Path,Info,FileInfo) of
- continue ->
- continue;
- ReturnValue ->
- send_return_value(ReturnValue,FileInfo)
- end;
- continue ->
- continue;
- ReturnValue ->
- send_return_value(ReturnValue,FileInfo)
- end;
- Response->
- Response
- end.
-
-%%----------------------------------------------------------------------
-%%If there are both a range and an if-range field control if
-%%----------------------------------------------------------------------
-control_range(Path,Info,FileInfo) ->
- case httpd_util:key1search(Info#mod.parsed_header,"range") of
- undefined->
- undefined;
- _Range ->
- case httpd_util:key1search(Info#mod.parsed_header,"if-range") of
- undefined ->
- undefined;
- EtagOrDate ->
- control_if_range(Path,Info,FileInfo,EtagOrDate)
- end
- end.
-
-control_if_range(Path,Info,FileInfo,EtagOrDate) ->
- case httpd_util:convert_request_date(strip_date(EtagOrDate)) of
- bad_date ->
- FileEtag=httpd_util:create_etag(FileInfo),
- case FileEtag of
- EtagOrDate ->
- continue;
- _ ->
- {if_range,send_file}
- end;
- ErlDate ->
- %%We got the date in the request if it is
- case control_modification_data(Info,FileInfo#file_info.mtime,"if-range") of
- modified ->
- {if_range,send_file};
- _UnmodifiedOrUndefined->
- continue
- end
- end.
-
-%%----------------------------------------------------------------------
-%%Controls the values of the If-Match and I-None-Mtch
-%%----------------------------------------------------------------------
-control_Etag(Path,Info,FileInfo)->
- FileEtag=httpd_util:create_etag(FileInfo),
- %%Control if the E-Tag for the resource matches one of the Etags in
- %%the -if-match header field
- case control_match(Info,FileInfo,"if-match",FileEtag) of
- nomatch ->
- %%None of the Etags in the if-match field matched the current
- %%Etag for the resource return a 304
- {412,Info,Path};
- match ->
- continue;
- undefined ->
- case control_match(Info,FileInfo,"if-none-match",FileEtag) of
- nomatch ->
- continue;
- match ->
- case Info#mod.method of
- "GET" ->
- {304,Info,Path};
- "HEAD" ->
- {304,Info,Path};
- _OtherrequestMethod ->
- {412,Info,Path}
- end;
- undefined ->
- undefined
- end
- end.
-
-%%----------------------------------------------------------------------
-%%Control if there are any Etags for HeaderField in the request if so
-%%Control if they match the Etag for the requested file
-%%----------------------------------------------------------------------
-control_match(Info,FileInfo,HeaderField,FileEtag)->
- case split_etags(httpd_util:key1search(Info#mod.parsed_header,HeaderField)) of
- undefined->
- undefined;
- Etags->
- %%Control that the match any star not is availible
- case lists:member("*",Etags) of
- true->
- match;
- false->
- compare_etags(FileEtag,Etags)
- end
- end.
-
-%%----------------------------------------------------------------------
-%%Split the etags from the request
-%%----------------------------------------------------------------------
-split_etags(undefined)->
- undefined;
-split_etags(Tags) ->
- string:tokens(Tags,", ").
-
-%%----------------------------------------------------------------------
-%%Control if the etag for the file is in the list
-%%----------------------------------------------------------------------
-compare_etags(Tag,Etags) ->
- case lists:member(Tag,Etags) of
- true ->
- match;
- _ ->
- nomatch
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%%Control if the file is modificated %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%%----------------------------------------------------------------------
-%%Control the If-Modified-Since and If-Not-Modified-Since header fields
-%%----------------------------------------------------------------------
-control_modification(Path,Info,FileInfo)->
- ?DEBUG("control_modification() -> entry",[]),
- case control_modification_data(Info,FileInfo#file_info.mtime,"if-modified-since") of
- modified->
- continue;
- unmodified->
- {304,Info,Path};
- undefined ->
- case control_modification_data(Info,FileInfo#file_info.mtime,"if-unmodified-since") of
- modified ->
- {412,Info,Path};
- _ContinueUndefined ->
- continue
- end
- end.
-
-%%----------------------------------------------------------------------
-%%Controls the date from the http-request if-modified-since and
-%%if-not-modified-since against the modification data of the
-%%File
-%%----------------------------------------------------------------------
-%%Info is the record about the request
-%%ModificationTime is the time the file was edited last
-%%Header Field is the name of the field to control
-
-control_modification_data(Info,ModificationTime,HeaderField)->
- case strip_date(httpd_util:key1search(Info#mod.parsed_header,HeaderField)) of
- undefined->
- undefined;
- LastModified0 ->
- LastModified=httpd_util:convert_request_date(LastModified0),
- ?DEBUG("control_modification_data() -> "
- "~n Request-Field: ~s"
- "~n FileLastModified: ~p"
- "~n FieldValue: ~p",
- [HeaderField,ModificationTime,LastModified]),
- case LastModified of
- bad_date ->
- undefined;
- _ ->
- FileTime=calendar:datetime_to_gregorian_seconds(ModificationTime),
- FieldTime=calendar:datetime_to_gregorian_seconds(LastModified),
- if
- FileTime=<FieldTime ->
- ?DEBUG("File unmodified~n", []),
- unmodified;
- FileTime>=FieldTime ->
- ?DEBUG("File modified~n", []),
- modified
- end
- end
- end.
-
-%%----------------------------------------------------------------------
-%%Compare to dates on the form {{YYYY,MM,DD},{HH,MIN,SS}}
-%%If the first date is the biggest returns biggest1 (read biggestFirst)
-%%If the first date is smaller
-% compare_date(Date,bad_date)->
-% bad_date;
-
-% compare_date({D1,T1},{D2,T2})->
-% case compare_date1(D1,D2) of
-% equal ->
-% compare_date1(T1,T2);
-% GTorLT->
-% GTorLT
-% end.
-
-% compare_date1({T1,T2,T3},{T12,T22,T32}) when T1>T12 ->
-% bigger1;
-% compare_date1({T1,T2,T3},{T1,T22,T32}) when T2>T22 ->
-% bigger1;
-% compare_date1({T1,T2,T3},{T1,T2,T32}) when T3>T32 ->
-% bigger1;
-% compare_date1({T1,T2,T3},{T1,T2,T3})->
-% equal;
-% compare_date1(_D1,_D2)->
-% smaller1.
-
-
-%% IE4 & NS4 sends an extra '; length=xxxx' string at the end of the If-Modified-Since
-%% header, we detect this and ignore it (the RFCs does not mention this).
-strip_date(undefined) ->
- undefined;
-strip_date([]) ->
- [];
-strip_date([$;,$ |Rest]) ->
- [];
-strip_date([C|Rest]) ->
- [C|strip_date(Rest)].
-
-send_return_value({412,_,_},FileInfo)->
- {status,{412,none,"Precondition Failed"}};
-
-send_return_value({304,Info,Path},FileInfo)->
- Suffix=httpd_util:suffix(Path),
- MimeType = httpd_util:lookup_mime_default(Info#mod.config_db,Suffix,"text/plain"),
- Header = [{code,304},
- {etag,httpd_util:create_etag(FileInfo)},
- {content_length,0},
- {last_modified,httpd_util:rfc1123_date(FileInfo#file_info.mtime)}],
- {response,{response,Header,nobody}}.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_security.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_security.erl
deleted file mode 100644
index 14197979d1..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_security.erl
+++ /dev/null
@@ -1,307 +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: mod_security.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $
-%%
--module(mod_security).
-
-%% Security Audit Functionality
-
-%% User API exports
--export([list_blocked_users/1, list_blocked_users/2, list_blocked_users/3,
- block_user/4, block_user/5,
- unblock_user/2, unblock_user/3, unblock_user/4,
- list_auth_users/1, list_auth_users/2, list_auth_users/3]).
-
-%% module API exports
--export([do/1, load/2, store/2, remove/1]).
-
--include("httpd.hrl").
-
--define(VMODULE,"SEC").
--include("httpd_verbosity.hrl").
-
-
-%% do/1
-do(Info) ->
- ?vdebug("~n do with ~n Info: ~p",[Info]),
- %% Check and see if any user has been authorized.
- case httpd_util:key1search(Info#mod.data,remote_user,not_defined_user) of
- not_defined_user ->
- %% No user has been authorized.
- case httpd_util:key1search(Info#mod.data, status) of
- %% A status code has been generated!
- {401, PhraseArgs, Reason} ->
- case httpd_util:key1search(Info#mod.parsed_header,
- "authorization") of
- undefined ->
- %% Not an authorization attempt (server just replied to
- %% challenge for authentication)
- {proceed, Info#mod.data};
- [$B,$a,$s,$i,$c,$ |EncodedString] ->
- %% Someone tried to authenticate, and obviously failed!
- ?vlog("~n Authentication failed: ~s",
- [EncodedString]),
- report_failed(Info, EncodedString,"Failed authentication"),
- take_failed_action(Info, EncodedString),
- {proceed, Info#mod.data}
- end;
- _ ->
- {proceed, Info#mod.data}
- end;
- User ->
- %% A user has been authenticated, now is he blocked ?
- ?vtrace("user '~p' authentication",[User]),
- Path = mod_alias:path(Info#mod.data,
- Info#mod.config_db,
- Info#mod.request_uri),
- {Dir, SDirData} = secretp(Path, Info#mod.config_db),
- Addr = httpd_util:lookup(Info#mod.config_db, bind_address),
- Port = httpd_util:lookup(Info#mod.config_db, port),
- DF = httpd_util:key1search(SDirData, data_file),
- case mod_security_server:check_blocked_user(Info, User,
- SDirData,
- Addr, Port) of
- true ->
- ?vtrace("user blocked",[]),
- report_failed(Info,httpd_util:decode_base64(User) ,"User Blocked"),
- {proceed, [{status, {403, Info#mod.request_uri, ""}}|Info#mod.data]};
- false ->
- ?vtrace("user not blocked",[]),
- EncodedUser=httpd_util:decode_base64(User),
- report_failed(Info, EncodedUser,"Authentication Succedded"),
- mod_security_server:store_successful_auth(Addr, Port,
- User, SDirData),
- {proceed, Info#mod.data}
- end
- end.
-
-
-
-report_failed(Info, EncodedString,Event) ->
- Request = Info#mod.request_line,
- Decoded = httpd_util:decode_base64(EncodedString),
- {PortNumber,RemoteHost}=(Info#mod.init_data)#init_data.peername,
- String = RemoteHost++" : " ++ Event ++ " : "++Request++" : "++Decoded,
- mod_disk_log:security_log(Info,String),
- mod_log:security_log(Info, String).
-
-take_failed_action(Info, EncodedString) ->
- Path = mod_alias:path(Info#mod.data,Info#mod.config_db, Info#mod.request_uri),
- {Dir, SDirData} = secretp(Path, Info#mod.config_db),
- Addr = httpd_util:lookup(Info#mod.config_db, bind_address),
- Port = httpd_util:lookup(Info#mod.config_db, port),
- DecodedString = httpd_util:decode_base64(EncodedString),
- mod_security_server:store_failed_auth(Info, Addr, Port,
- DecodedString, SDirData).
-
-secretp(Path, ConfigDB) ->
- Directories = ets:match(ConfigDB,{directory,'$1','_'}),
- case secret_path(Path, Directories) of
- {yes, Directory} ->
- SDirs0 = httpd_util:multi_lookup(ConfigDB, security_directory),
- SDir = lists:filter(fun(X) ->
- lists:member({path, Directory}, X)
- end, SDirs0),
- {Directory, lists:flatten(SDir)};
- no ->
- error_report({internal_error_secretp, ?MODULE}),
- {[], []}
- end.
-
-secret_path(Path,Directories) ->
- secret_path(Path, httpd_util:uniq(lists:sort(Directories)), to_be_found).
-
-secret_path(Path, [], to_be_found) ->
- no;
-secret_path(Path, [], Directory) ->
- {yes, Directory};
-secret_path(Path, [[NewDirectory]|Rest], Directory) ->
- case regexp:match(Path, NewDirectory) of
- {match, _, _} when Directory == to_be_found ->
- secret_path(Path, Rest, NewDirectory);
- {match, _, Length} when Length > length(Directory)->
- secret_path(Path, Rest, NewDirectory);
- {match, _, Length} ->
- secret_path(Path, Rest, Directory);
- nomatch ->
- secret_path(Path, Rest, Directory)
- end.
-
-
-load([$<,$D,$i,$r,$e,$c,$t,$o,$r,$y,$ |Directory],[]) ->
- Dir = httpd_conf:custom_clean(Directory,"",">"),
- {ok, [{security_directory, Dir, [{path, Dir}]}]};
-load(eof,[{security_directory,Directory, DirData}|_]) ->
- {error, ?NICE("Premature end-of-file in "++Directory)};
-load([$S,$e,$c,$u,$r,$i,$t,$y,$D,$a,$t,$a,$F,$i,$l,$e,$ |FileName],
- [{security_directory, Dir, DirData}]) ->
- File = httpd_conf:clean(FileName),
- {ok, [{security_directory, Dir, [{data_file, File}|DirData]}]};
-load([$S,$e,$c,$u,$r,$i,$t,$y,$C,$a,$l,$l,$b,$a,$c,$k,$M,$o,$d,$u,$l,$e,$ |ModuleName],
- [{security_directory, Dir, DirData}]) ->
- Mod = list_to_atom(httpd_conf:clean(ModuleName)),
- {ok, [{security_directory, Dir, [{callback_module, Mod}|DirData]}]};
-load([$S,$e,$c,$u,$r,$i,$t,$y,$M,$a,$x,$R,$e,$t,$r,$i,$e,$s,$ |Retries],
- [{security_directory, Dir, DirData}]) ->
- MaxRetries = httpd_conf:clean(Retries),
- load_return_int_tag("SecurityMaxRetries", max_retries,
- httpd_conf:clean(Retries), Dir, DirData);
-load([$S,$e,$c,$u,$r,$i,$t,$y,$B,$l,$o,$c,$k,$T,$i,$m,$e,$ |Time],
- [{security_directory, Dir, DirData}]) ->
- load_return_int_tag("SecurityBlockTime", block_time,
- httpd_conf:clean(Time), Dir, DirData);
-load([$S,$e,$c,$u,$r,$i,$t,$y,$F,$a,$i,$l,$E,$x,$p,$i,$r,$e,$T,$i,$m,$e,$ |Time],
- [{security_directory, Dir, DirData}]) ->
- load_return_int_tag("SecurityFailExpireTime", fail_expire_time,
- httpd_conf:clean(Time), Dir, DirData);
-load([$S,$e,$c,$u,$r,$i,$t,$y,$A,$u,$t,$h,$T,$i,$m,$e,$o,$u,$t,$ |Time0],
- [{security_directory, Dir, DirData}]) ->
- Time = httpd_conf:clean(Time0),
- load_return_int_tag("SecurityAuthTimeout", auth_timeout,
- httpd_conf:clean(Time), Dir, DirData);
-load([$A,$u,$t,$h,$N,$a,$m,$e,$ |Name0],
- [{security_directory, Dir, DirData}]) ->
- Name = httpd_conf:clean(Name0),
- {ok, [{security_directory, Dir, [{auth_name, Name}|DirData]}]};
-load("</Directory>",[{security_directory,Directory, DirData}]) ->
- {ok, [], {security_directory, Directory, DirData}}.
-
-load_return_int_tag(Name, Atom, Time, Dir, DirData) ->
- case Time of
- "infinity" ->
- {ok, [{security_directory, Dir, [{Atom, 99999999999999999999999999999}|DirData]}]};
- Int ->
- case catch list_to_integer(Time) of
- {'EXIT', _} ->
- {error, Time++" is an invalid "++Name};
- Val ->
- {ok, [{security_directory, Dir, [{Atom, Val}|DirData]}]}
- end
- end.
-
-store({security_directory, Dir0, DirData}, ConfigList) ->
- ?CDEBUG("store(security_directory) -> ~n"
- " Dir0: ~p~n"
- " DirData: ~p",
- [Dir0, DirData]),
- Addr = httpd_util:key1search(ConfigList, bind_address),
- Port = httpd_util:key1search(ConfigList, port),
- mod_security_server:start(Addr, Port),
- SR = httpd_util:key1search(ConfigList, server_root),
- Dir =
- case filename:pathtype(Dir0) of
- relative ->
- filename:join(SR, Dir0);
- _ ->
- Dir0
- end,
- case httpd_util:key1search(DirData, data_file, no_data_file) of
- no_data_file ->
- {error, no_security_data_file};
- DataFile0 ->
- DataFile =
- case filename:pathtype(DataFile0) of
- relative ->
- filename:join(SR, DataFile0);
- _ ->
- DataFile0
- end,
- case mod_security_server:new_table(Addr, Port, DataFile) of
- {ok, TwoTables} ->
- NewDirData0 = lists:keyreplace(data_file, 1, DirData,
- {data_file, TwoTables}),
- NewDirData1 = case Addr of
- undefined ->
- [{port,Port}|NewDirData0];
- _ ->
- [{port,Port},{bind_address,Addr}|
- NewDirData0]
- end,
- {ok, {security_directory,NewDirData1}};
- {error, Err} ->
- {error, {{open_data_file, DataFile}, Err}}
- end
- end.
-
-
-remove(ConfigDB) ->
- Addr = case ets:lookup(ConfigDB, bind_address) of
- [] ->
- undefined;
- [{bind_address, Address}] ->
- Address
- end,
- [{port, Port}] = ets:lookup(ConfigDB, port),
- mod_security_server:delete_tables(Addr, Port),
- mod_security_server:stop(Addr, Port).
-
-
-%%
-%% User API
-%%
-
-%% list_blocked_users
-
-list_blocked_users(Port) ->
- list_blocked_users(undefined, Port).
-
-list_blocked_users(Port, Dir) when integer(Port) ->
- list_blocked_users(undefined,Port,Dir);
-list_blocked_users(Addr, Port) when integer(Port) ->
- mod_security_server:list_blocked_users(Addr, Port).
-
-list_blocked_users(Addr, Port, Dir) ->
- mod_security_server:list_blocked_users(Addr, Port, Dir).
-
-
-%% block_user
-
-block_user(User, Port, Dir, Time) ->
- block_user(User, undefined, Port, Dir, Time).
-block_user(User, Addr, Port, Dir, Time) ->
- mod_security_server:block_user(User, Addr, Port, Dir, Time).
-
-
-%% unblock_user
-
-unblock_user(User, Port) ->
- unblock_user(User, undefined, Port).
-
-unblock_user(User, Port, Dir) when integer(Port) ->
- unblock_user(User, undefined, Port, Dir);
-unblock_user(User, Addr, Port) when integer(Port) ->
- mod_security_server:unblock_user(User, Addr, Port).
-
-unblock_user(User, Addr, Port, Dir) ->
- mod_security_server:unblock_user(User, Addr, Port, Dir).
-
-
-%% list_auth_users
-
-list_auth_users(Port) ->
- list_auth_users(undefined,Port).
-
-list_auth_users(Port, Dir) when integer(Port) ->
- list_auth_users(undefined, Port, Dir);
-list_auth_users(Addr, Port) when integer(Port) ->
- mod_security_server:list_auth_users(Addr, Port).
-
-list_auth_users(Addr, Port, Dir) ->
- mod_security_server:list_auth_users(Addr, Port, Dir).
-
-
-error_report(M) ->
- error_logger:error_report(M).
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_security_server.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_security_server.erl
deleted file mode 100644
index 7df61df63e..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_security_server.erl
+++ /dev/null
@@ -1,728 +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: mod_security_server.erl,v 1.1 2008/12/17 09:53:36 mikpe Exp $
-%%
-%% Security Audit Functionality
-
-%%
-%% The gen_server code.
-%%
-%% A gen_server is needed in this module to take care of shared access to the
-%% data file used to store failed and successful authentications aswell as
-%% user blocks.
-%%
-%% The storage model is a write-through model with both an ets and a dets
-%% table. Writes are done to both the ets and then the dets table, but reads
-%% are only done from the ets table.
-%%
-%% This approach also enables parallelism when using dets by returning the
-%% same dets table identifier when opening several files with the same
-%% physical location.
-%%
-%% NOTE: This could be implemented using a single dets table, as it is
-%% possible to open a dets file with the ram_file flag, but this
-%% would require periodical sync's to disk, and it would be hard
-%% to decide when such an operation should occur.
-%%
-
-
--module(mod_security_server).
-
--include("httpd.hrl").
--include("httpd_verbosity.hrl").
-
-
--behaviour(gen_server).
-
-
-%% User API exports (called via mod_security)
--export([list_blocked_users/2, list_blocked_users/3,
- block_user/5,
- unblock_user/3, unblock_user/4,
- list_auth_users/2, list_auth_users/3]).
-
-%% Internal exports (for mod_security only)
--export([start/2, stop/1, stop/2,
- new_table/3, delete_tables/2,
- store_failed_auth/5, store_successful_auth/4,
- check_blocked_user/5]).
-
-%% gen_server exports
--export([start_link/3,
- init/1,
- handle_info/2, handle_call/3, handle_cast/2,
- terminate/2,
- code_change/3]).
-
--export([verbosity/3]).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% External API %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% start_link/3
-%%
-%% NOTE: This is called by httpd_misc_sup when the process is started
-%%
-
-start_link(Addr, Port, Verbosity) ->
- ?vtrace("start_link -> entry with"
- "~n Addr: ~p"
- "~n Port: ~p", [Addr, Port]),
- Name = make_name(Addr, Port),
- gen_server:start_link({local, Name}, ?MODULE, [Verbosity],
- [{timeout, infinity}]).
-
-
-%% start/2
-%% Called by the mod_security module.
-
-start(Addr, Port) ->
- Name = make_name(Addr, Port),
- case whereis(Name) of
- undefined ->
- Verbosity = get(security_verbosity),
- case httpd_misc_sup:start_sec_server(Addr, Port, Verbosity) of
- {ok, Pid} ->
- put(security_server, Pid),
- ok;
- Error ->
- exit({failed_start_security_server, Error})
- end;
- _ -> %% Already started...
- ok
- end.
-
-
-%% stop
-
-stop(Port) ->
- stop(undefined, Port).
-stop(Addr, Port) ->
- Name = make_name(Addr, Port),
- case whereis(Name) of
- undefined ->
- ok;
- _ ->
- httpd_misc_sup:stop_sec_server(Addr, Port)
- end.
-
-
-%% verbosity
-
-verbosity(Addr, Port, Verbosity) ->
- Name = make_name(Addr, Port),
- Req = {verbosity, Verbosity},
- call(Name, Req).
-
-
-%% list_blocked_users
-
-list_blocked_users(Addr, Port) ->
- Name = make_name(Addr,Port),
- Req = {list_blocked_users, Addr, Port, '_'},
- call(Name, Req).
-
-list_blocked_users(Addr, Port, Dir) ->
- Name = make_name(Addr, Port),
- Req = {list_blocked_users, Addr, Port, Dir},
- call(Name, Req).
-
-
-%% block_user
-
-block_user(User, Addr, Port, Dir, Time) ->
- Name = make_name(Addr, Port),
- Req = {block_user, User, Addr, Port, Dir, Time},
- call(Name, Req).
-
-
-%% unblock_user
-
-unblock_user(User, Addr, Port) ->
- Name = make_name(Addr, Port),
- Req = {unblock_user, User, Addr, Port, '_'},
- call(Name, Req).
-
-unblock_user(User, Addr, Port, Dir) ->
- Name = make_name(Addr, Port),
- Req = {unblock_user, User, Addr, Port, Dir},
- call(Name, Req).
-
-
-%% list_auth_users
-
-list_auth_users(Addr, Port) ->
- Name = make_name(Addr, Port),
- Req = {list_auth_users, Addr, Port, '_'},
- call(Name, Req).
-
-list_auth_users(Addr, Port, Dir) ->
- Name = make_name(Addr,Port),
- Req = {list_auth_users, Addr, Port, Dir},
- call(Name, Req).
-
-
-%% new_table
-
-new_table(Addr, Port, TabName) ->
- Name = make_name(Addr,Port),
- Req = {new_table, Addr, Port, TabName},
- call(Name, Req).
-
-
-%% delete_tables
-
-delete_tables(Addr, Port) ->
- Name = make_name(Addr, Port),
- case whereis(Name) of
- undefined ->
- ok;
- _ ->
- call(Name, delete_tables)
- end.
-
-
-%% store_failed_auth
-
-store_failed_auth(Info, Addr, Port, DecodedString, SDirData) ->
- Name = make_name(Addr,Port),
- Msg = {store_failed_auth,[Info,DecodedString,SDirData]},
- cast(Name, Msg).
-
-
-%% store_successful_auth
-
-store_successful_auth(Addr, Port, User, SDirData) ->
- Name = make_name(Addr,Port),
- Msg = {store_successful_auth, [User,Addr,Port,SDirData]},
- cast(Name, Msg).
-
-
-%% check_blocked_user
-
-check_blocked_user(Info, User, SDirData, Addr, Port) ->
- Name = make_name(Addr, Port),
- Req = {check_blocked_user, [Info, User, SDirData]},
- call(Name, Req).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% Server call-back functions %%
-%% %%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% init
-
-init([undefined]) ->
- init([?default_verbosity]);
-init([Verbosity]) ->
- ?DEBUG("init -> entry with Verbosity: ~p",[Verbosity]),
- process_flag(trap_exit, true),
- put(sname, sec),
- put(verbosity, Verbosity),
- ?vlog("starting",[]),
- {ok, []}.
-
-
-%% handle_call
-
-handle_call(stop, _From, Tables) ->
- ?vlog("stop",[]),
- {stop, normal, ok, []};
-
-
-handle_call({verbosity,Verbosity}, _From, Tables) ->
- ?vlog("set verbosity to ~p",[Verbosity]),
- OldVerbosity = get(verbosity),
- put(verbosity,Verbosity),
- ?vdebug("old verbosity: ~p",[OldVerbosity]),
- {reply,OldVerbosity,Tables};
-
-
-handle_call({block_user, User, Addr, Port, Dir, Time}, _From, Tables) ->
- ?vlog("block user '~p' for ~p",[User,Dir]),
- Ret = block_user_int({User, Addr, Port, Dir, Time}),
- ?vdebug("block user result: ~p",[Ret]),
- {reply, Ret, Tables};
-
-
-handle_call({list_blocked_users, Addr, Port, Dir}, _From, Tables) ->
- ?vlog("list blocked users for ~p",[Dir]),
- Blocked = list_blocked(Tables, Addr, Port, Dir, []),
- ?vdebug("list blocked users: ~p",[Blocked]),
- {reply, Blocked, Tables};
-
-
-handle_call({unblock_user, User, Addr, Port, Dir}, _From, Tables) ->
- ?vlog("unblock user '~p' for ~p",[User,Dir]),
- Ret = unblock_user_int({User, Addr, Port, Dir}),
- ?vdebug("unblock user result: ~p",[Ret]),
- {reply, Ret, Tables};
-
-
-handle_call({list_auth_users, Addr, Port, Dir}, _From, Tables) ->
- ?vlog("list auth users for ~p",[Dir]),
- Auth = list_auth(Tables, Addr, Port, Dir, []),
- ?vdebug("list auth users result: ~p",[Auth]),
- {reply, Auth, Tables};
-
-
-handle_call({new_table, Addr, Port, Name}, _From, Tables) ->
- case lists:keysearch(Name, 1, Tables) of
- {value, {Name, {Ets, Dets}}} ->
- ?DEBUG("handle_call(new_table) -> we already have this table: ~p",
- [Name]),
- ?vdebug("new table; we already have this one: ~p",[Name]),
- {reply, {ok, {Ets, Dets}}, Tables};
- false ->
- ?LOG("handle_call(new_table) -> new_table: Name = ~p",[Name]),
- ?vlog("new table: ~p",[Name]),
- TName = make_name(Addr,Port,length(Tables)),
- ?DEBUG("handle_call(new_table) -> TName: ~p",[TName]),
- ?vdebug("new table: ~p",[TName]),
- case dets:open_file(TName, [{type, bag}, {file, Name},
- {repair, true},
- {access, read_write}]) of
- {ok, DFile} ->
- ETS = ets:new(TName, [bag, private]),
- sync_dets_to_ets(DFile, ETS),
- NewTables = [{Name, {ETS, DFile}}|Tables],
- ?DEBUG("handle_call(new_table) -> ~n"
- " NewTables: ~p",[NewTables]),
- ?vtrace("new tables: ~p",[NewTables]),
- {reply, {ok, {ETS, DFile}}, NewTables};
- {error, Err} ->
- ?LOG("handle_call -> Err: ~p",[Err]),
- ?vinfo("failed open dets file: ~p",[Err]),
- {reply, {error, {create_dets, Err}}, Tables}
- end
- end;
-
-handle_call(delete_tables, _From, Tables) ->
- ?vlog("delete tables",[]),
- lists:foreach(fun({Name, {ETS, DETS}}) ->
- dets:close(DETS),
- ets:delete(ETS)
- end, Tables),
- {reply, ok, []};
-
-handle_call({check_blocked_user, [Info, User, SDirData]}, _From, Tables) ->
- ?vlog("check blocked user '~p'",[User]),
- {ETS, DETS} = httpd_util:key1search(SDirData, data_file),
- Dir = httpd_util:key1search(SDirData, path),
- Addr = httpd_util:key1search(SDirData, bind_address),
- Port = httpd_util:key1search(SDirData, port),
- CBModule = httpd_util:key1search(SDirData, callback_module, no_module_at_all),
- ?vdebug("call back module: ~p",[CBModule]),
- Ret = check_blocked_user(Info, User, Dir, Addr, Port, ETS, DETS, CBModule),
- ?vdebug("check result: ~p",[Ret]),
- {reply, Ret, Tables};
-handle_call(Request,From,Tables) ->
- ?vinfo("~n unknown call '~p' from ~p",[Request,From]),
- {reply,ok,Tables}.
-
-
-%% handle_cast
-
-handle_cast({store_failed_auth, [Info, DecodedString, SDirData]}, Tables) ->
- ?vlog("store failed auth",[]),
- {ETS, DETS} = httpd_util:key1search(SDirData, data_file),
- Dir = httpd_util:key1search(SDirData, path),
- Addr = httpd_util:key1search(SDirData, bind_address),
- Port = httpd_util:key1search(SDirData, port),
- {ok, [User,Password]} = httpd_util:split(DecodedString,":",2),
- ?vdebug("user '~p' and password '~p'",[User,Password]),
- Seconds = universal_time(),
- Key = {User, Dir, Addr, Port},
-
- %% Event
- CBModule = httpd_util:key1search(SDirData, callback_module, no_module_at_all),
- ?vtrace("call back module: ~p",[CBModule]),
- auth_fail_event(CBModule,Addr,Port,Dir,User,Password),
-
- %% Find out if any of this user's other failed logins are too old to keep..
- ?vtrace("remove old login failures",[]),
- case ets:match_object(ETS, {failed, {Key, '_', '_'}}) of
- [] ->
- ?vtrace("no old login failures",[]),
- no;
- List when list(List) ->
- ?vtrace("~p old login failures",[length(List)]),
- ExpireTime = httpd_util:key1search(SDirData, fail_expire_time, 30)*60,
- ?vtrace("expire time ~p",[ExpireTime]),
- lists:map(fun({failed, {TheKey, LS, Gen}}) ->
- Diff = Seconds-LS,
- if
- Diff > ExpireTime ->
- ?vtrace("~n '~p' is to old to keep: ~p",
- [TheKey,Gen]),
- ets:match_delete(ETS, {failed, {TheKey, LS, Gen}}),
- dets:match_delete(DETS, {failed, {TheKey, LS, Gen}});
- true ->
- ?vtrace("~n '~p' is not old enough: ~p",
- [TheKey,Gen]),
- ok
- end
- end,
- List);
- O ->
- ?vlog("~n unknown login failure search resuylt: ~p",[O]),
- no
- end,
-
- %% Insert the new failure..
- Generation = length(ets:match_object(ETS, {failed, {Key, '_', '_'}})),
- ?vtrace("insert ('~p') new login failure: ~p",[Key,Generation]),
- ets:insert(ETS, {failed, {Key, Seconds, Generation}}),
- dets:insert(DETS, {failed, {Key, Seconds, Generation}}),
-
- %% See if we should block this user..
- MaxRetries = httpd_util:key1search(SDirData, max_retries, 3),
- BlockTime = httpd_util:key1search(SDirData, block_time, 60),
- ?vtrace("~n Max retries ~p, block time ~p",[MaxRetries,BlockTime]),
- case ets:match_object(ETS, {failed, {Key, '_', '_'}}) of
- List1 ->
- ?vtrace("~n ~p tries so far",[length(List1)]),
- if
- length(List1) >= MaxRetries ->
- %% Block this user until Future
- ?vtrace("block user '~p'",[User]),
- Future = Seconds+BlockTime*60,
- ?vtrace("future: ~p",[Future]),
- Reason = io_lib:format("Blocking user ~s from dir ~s "
- "for ~p minutes",
- [User, Dir, BlockTime]),
- mod_log:security_log(Info, lists:flatten(Reason)),
-
- %% Event
- user_block_event(CBModule,Addr,Port,Dir,User),
-
- ets:match_delete(ETS,{blocked_user,
- {User, Addr, Port, Dir, '$1'}}),
- dets:match_delete(DETS, {blocked_user,
- {User, Addr, Port, Dir, '$1'}}),
- BlockRecord = {blocked_user,
- {User, Addr, Port, Dir, Future}},
- ets:insert(ETS, BlockRecord),
- dets:insert(DETS, BlockRecord),
- %% Remove previous failed requests.
- ets:match_delete(ETS, {failed, {Key, '_', '_'}}),
- dets:match_delete(DETS, {failed, {Key, '_', '_'}});
- true ->
- ?vtrace("still some tries to go",[]),
- no
- end;
- Other ->
- no
- end,
- {noreply, Tables};
-
-handle_cast({store_successful_auth, [User, Addr, Port, SDirData]}, Tables) ->
- ?vlog("store successfull auth",[]),
- {ETS, DETS} = httpd_util:key1search(SDirData, data_file),
- AuthTimeOut = httpd_util:key1search(SDirData, auth_timeout, 30),
- Dir = httpd_util:key1search(SDirData, path),
- Key = {User, Dir, Addr, Port},
-
- %% Remove failed entries for this Key
- dets:match_delete(DETS, {failed, {Key, '_', '_'}}),
- ets:match_delete(ETS, {failed, {Key, '_', '_'}}),
-
- %% Keep track of when the last successful login took place.
- Seconds = universal_time()+AuthTimeOut,
- ets:match_delete(ETS, {success, {Key, '_'}}),
- dets:match_delete(DETS, {success, {Key, '_'}}),
- ets:insert(ETS, {success, {Key, Seconds}}),
- dets:insert(DETS, {success, {Key, Seconds}}),
- {noreply, Tables};
-
-handle_cast(Req, Tables) ->
- ?vinfo("~n unknown cast '~p'",[Req]),
- error_msg("security server got unknown cast: ~p",[Req]),
- {noreply, Tables}.
-
-
-%% handle_info
-
-handle_info(Info, State) ->
- ?vinfo("~n unknown info '~p'",[Info]),
- {noreply, State}.
-
-
-%% terminate
-
-terminate(Reason, _Tables) ->
- ?vlog("~n Terminating for reason: ~p",[Reason]),
- ok.
-
-
-%% code_change({down, ToVsn}, State, Extra)
-%%
-code_change({down, _}, State, _Extra) ->
- ?vlog("downgrade", []),
- {ok, State};
-
-
-%% code_change(FromVsn, State, Extra)
-%%
-code_change(_, State, Extra) ->
- ?vlog("upgrade", []),
- {ok, State}.
-
-
-
-
-%% block_user_int/2
-block_user_int({User, Addr, Port, Dir, Time}) ->
- Dirs = httpd_manager:config_match(Addr, Port, {security_directory, '_'}),
- ?vtrace("block '~p' for ~p during ~p",[User,Dir,Time]),
- case find_dirdata(Dirs, Dir) of
- {ok, DirData, {ETS, DETS}} ->
- Time1 =
- case Time of
- infinity ->
- 99999999999999999999999999999;
- _ ->
- Time
- end,
- Future = universal_time()+Time1,
- ets:match_delete(ETS, {blocked_user, {User,Addr,Port,Dir,'_'}}),
- dets:match_delete(DETS, {blocked_user, {User,Addr,Port,Dir,'_'}}),
- ets:insert(ETS, {blocked_user, {User,Addr,Port,Dir,Future}}),
- dets:insert(DETS, {blocked_user, {User,Addr,Port,Dir,Future}}),
- CBModule = httpd_util:key1search(DirData, callback_module,
- no_module_at_all),
- ?vtrace("call back module ~p",[CBModule]),
- user_block_event(CBModule,Addr,Port,Dir,User),
- true;
- _ ->
- {error, no_such_directory}
- end.
-
-
-find_dirdata([], _Dir) ->
- false;
-find_dirdata([{security_directory, DirData}|SDirs], Dir) ->
- case lists:keysearch(path, 1, DirData) of
- {value, {path, Dir}} ->
- {value, {data_file, {ETS, DETS}}} =
- lists:keysearch(data_file, 1, DirData),
- {ok, DirData, {ETS, DETS}};
- _ ->
- find_dirdata(SDirs, Dir)
- end.
-
-%% unblock_user_int/2
-
-unblock_user_int({User, Addr, Port, Dir}) ->
- ?vtrace("unblock user '~p' for ~p",[User,Dir]),
- Dirs = httpd_manager:config_match(Addr, Port, {security_directory, '_'}),
- ?vtrace("~n dirs: ~p",[Dirs]),
- case find_dirdata(Dirs, Dir) of
- {ok, DirData, {ETS, DETS}} ->
- case ets:match_object(ETS,{blocked_user,{User,Addr,Port,Dir,'_'}}) of
- [] ->
- ?vtrace("not blocked",[]),
- {error, not_blocked};
- Objects ->
- ets:match_delete(ETS, {blocked_user,
- {User, Addr, Port, Dir, '_'}}),
- dets:match_delete(DETS, {blocked_user,
- {User, Addr, Port, Dir, '_'}}),
- CBModule = httpd_util:key1search(DirData, callback_module,
- no_module_at_all),
- user_unblock_event(CBModule,Addr,Port,Dir,User),
- true
- end;
- _ ->
- ?vlog("~n cannot unblock: no such directory '~p'",[Dir]),
- {error, no_such_directory}
- end.
-
-
-
-%% list_auth/2
-
-list_auth([], _Addr, _Port, Dir, Acc) ->
- Acc;
-list_auth([{Name, {ETS, DETS}}|Tables], Addr, Port, Dir, Acc) ->
- case ets:match_object(ETS, {success, {{'_', Dir, Addr, Port}, '_'}}) of
- [] ->
- list_auth(Tables, Addr, Port, Dir, Acc);
- List when list(List) ->
- TN = universal_time(),
- NewAcc = lists:foldr(fun({success,{{U,Ad,P,D},T}},Ac) ->
- if
- T-TN > 0 ->
- [U|Ac];
- true ->
- Rec = {success,{{U,Ad,P,D},T}},
- ets:match_delete(ETS,Rec),
- dets:match_delete(DETS,Rec),
- Ac
- end
- end,
- Acc, List),
- list_auth(Tables, Addr, Port, Dir, NewAcc);
- _ ->
- list_auth(Tables, Addr, Port, Dir, Acc)
- end.
-
-
-%% list_blocked/2
-
-list_blocked([], Addr, Port, Dir, Acc) ->
- TN = universal_time(),
- lists:foldl(fun({U,Ad,P,D,T}, Ac) ->
- if
- T-TN > 0 ->
- [{U,Ad,P,D,local_time(T)}|Ac];
- true ->
- Ac
- end
- end,
- [], Acc);
-list_blocked([{Name, {ETS, DETS}}|Tables], Addr, Port, Dir, Acc) ->
- NewBlocked =
- case ets:match_object(ETS, {blocked_user, {'_',Addr,Port,Dir,'_'}}) of
- List when list(List) ->
- lists:foldl(fun({blocked_user, X}, A) -> [X|A] end, Acc, List);
- _ ->
- Acc
- end,
- list_blocked(Tables, Addr, Port, Dir, NewBlocked).
-
-
-%%
-%% sync_dets_to_ets/2
-%%
-%% Reads dets-table DETS and syncronizes it with the ets-table ETS.
-%%
-sync_dets_to_ets(DETS, ETS) ->
- dets:traverse(DETS, fun(X) ->
- ets:insert(ETS, X),
- continue
- end).
-
-%%
-%% check_blocked_user/7 -> true | false
-%%
-%% Check if a specific user is blocked from access.
-%%
-%% The sideeffect of this routine is that it unblocks also other users
-%% whos blocking time has expired. This to keep the tables as small
-%% as possible.
-%%
-check_blocked_user(Info, User, Dir, Addr, Port, ETS, DETS, CBModule) ->
- TN = universal_time(),
- case ets:match_object(ETS, {blocked_user, {User, '_', '_', '_', '_'}}) of
- List when list(List) ->
- Blocked = lists:foldl(fun({blocked_user, X}, A) ->
- [X|A] end, [], List),
- check_blocked_user(Info,User,Dir,Addr,Port,ETS,DETS,TN,Blocked,CBModule);
- _ ->
- false
- end.
-check_blocked_user(Info, User, Dir, Addr, Port, ETS, DETS, TN, [], CBModule) ->
- false;
-check_blocked_user(Info, User, Dir, Addr, Port, ETS, DETS, TN,
- [{User,Addr,Port,Dir,T}|Ls], CBModule) ->
- TD = T-TN,
- if
- TD =< 0 ->
- %% Blocking has expired, remove and grant access.
- unblock_user(Info, User, Dir, Addr, Port, ETS, DETS, CBModule),
- false;
- true ->
- true
- end;
-check_blocked_user(Info, User, Dir, Addr, Port, ETS, DETS, TN,
- [{OUser,ODir,OAddr,OPort,T}|Ls], CBModule) ->
- TD = T-TN,
- if
- TD =< 0 ->
- %% Blocking has expired, remove.
- unblock_user(Info, OUser, ODir, OAddr, OPort, ETS, DETS, CBModule);
- true ->
- true
- end,
- check_blocked_user(Info, User, Dir, Addr, Port, ETS, DETS, TN, Ls, CBModule).
-
-unblock_user(Info, User, Dir, Addr, Port, ETS, DETS, CBModule) ->
- Reason=io_lib:format("User ~s was removed from the block list for dir ~s",
- [User, Dir]),
- mod_log:security_log(Info, lists:flatten(Reason)),
- user_unblock_event(CBModule,Addr,Port,Dir,User),
- dets:match_delete(DETS, {blocked_user, {User, Addr, Port, Dir, '_'}}),
- ets:match_delete(ETS, {blocked_user, {User, Addr, Port, Dir, '_'}}).
-
-
-make_name(Addr,Port) ->
- httpd_util:make_name("httpd_security",Addr,Port).
-
-make_name(Addr,Port,Num) ->
- httpd_util:make_name("httpd_security",Addr,Port,
- "__" ++ integer_to_list(Num)).
-
-
-auth_fail_event(Mod,Addr,Port,Dir,User,Passwd) ->
- event(auth_fail,Mod,Addr,Port,Dir,[{user,User},{password,Passwd}]).
-
-user_block_event(Mod,Addr,Port,Dir,User) ->
- event(user_block,Mod,Addr,Port,Dir,[{user,User}]).
-
-user_unblock_event(Mod,Addr,Port,Dir,User) ->
- event(user_unblock,Mod,Addr,Port,Dir,[{user,User}]).
-
-event(Event,Mod,undefined,Port,Dir,Info) ->
- (catch Mod:event(Event,Port,Dir,Info));
-event(Event,Mod,Addr,Port,Dir,Info) ->
- (catch Mod:event(Event,Addr,Port,Dir,Info)).
-
-universal_time() ->
- calendar:datetime_to_gregorian_seconds(calendar:universal_time()).
-
-local_time(T) ->
- calendar:universal_time_to_local_time(
- calendar:gregorian_seconds_to_datetime(T)).
-
-
-error_msg(F, A) ->
- error_logger:error_msg(F, A).
-
-
-call(Name, Req) ->
- case (catch gen_server:call(Name, Req)) of
- {'EXIT', Reason} ->
- {error, Reason};
- Reply ->
- Reply
- end.
-
-
-cast(Name, Msg) ->
- case (catch gen_server:cast(Name, Msg)) of
- {'EXIT', Reason} ->
- {error, Reason};
- Result ->
- Result
- end.
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_trace.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_trace.erl
deleted file mode 100644
index 51fe6d283a..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/mod_trace.erl
+++ /dev/null
@@ -1,69 +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: mod_trace.erl,v 1.1 2008/12/17 09:53:36 mikpe Exp $
-%%
--module(mod_trace).
-
--export([do/1]).
-
--include("httpd.hrl").
-
-
-do(Info) ->
- %%?vtrace("do",[]),
- case Info#mod.method of
- "TRACE" ->
- case httpd_util:response_generated(Info) of
- false->
- generate_trace_response(Info);
- true->
- {proceed,Info#mod.data}
- end;
- _ ->
- {proceed,Info#mod.data}
- end.
-
-
-%%---------------------------------------------------------------------
-%%Generate the trace response the trace response consists of a
-%%http-header and the body will be the request.
-%5----------------------------------------------------------------------
-
-generate_trace_response(Info)->
- RequestHead=Info#mod.parsed_header,
- Body=generate_trace_response_body(RequestHead),
- Len=length(Body),
- Response=["HTTP/1.1 200 OK\r\n",
- "Content-Type:message/http\r\n",
- "Content-Length:",integer_to_list(Len),"\r\n\r\n",
- Info#mod.request_line,Body],
- httpd_socket:deliver(Info#mod.socket_type,Info#mod.socket,Response),
- {proceed,[{response,{already_sent,200,Len}}|Info#mod.data]}.
-
-generate_trace_response_body(Parsed_header)->
- generate_trace_response_body(Parsed_header,[]).
-
-generate_trace_response_body([],Head)->
- lists:flatten(Head);
-generate_trace_response_body([{[],[]}|Rest],Head) ->
- generate_trace_response_body(Rest,Head);
-generate_trace_response_body([{Field,Value}|Rest],Head) ->
- generate_trace_response_body(Rest,[Field ++ ":" ++ Value ++ "\r\n"|Head]).
-
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/uri.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/uri.erl
deleted file mode 100644
index e1acd62a31..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/inets/uri.erl
+++ /dev/null
@@ -1,349 +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 Mobile Arts AB
-%% Portions created by Mobile Arts are Copyright 2002, Mobile Arts AB
-%% All Rights Reserved.''
-%%
-%%
-%% Author : Johan Blom <[email protected]>
-%% Description :
-%% Implements various scheme dependent subsets (e.g. HTTP, FTP etc) based on
-%% RFC 2396, Uniform Resource Identifiers (URI): Generic Syntax
-%% Created : 27 Jul 2001 by Johan Blom <[email protected]>
-%%
-
--module(uri).
-
--author('[email protected]').
-
--export([parse/1,resolve/2]).
-
-
-%%% Parse URI and return {Scheme,Path}
-%%% Note that Scheme specific parsing/validation is not handled here!
-resolve(Root,Rel) ->
- ok.
-
-%%% See "http://www.isi.edu/in-notes/iana/assignments/url-schemes" for a list of
-%%% defined URL schemes and references to its sources.
-
-parse(URI) ->
- case parse_scheme(URI) of
- {http,Cont} -> parse_http(Cont,http);
- {https,Cont} -> parse_http(Cont,https);
- {ftp,Cont} -> parse_ftp(Cont,ftp);
- {sip,Cont} -> parse_sip(Cont,sip);
- {sms,Cont} -> parse_sms(Cont,sip);
- {error,Error} -> {error,Error};
- {Scheme,Cont} -> {Scheme,Cont}
- end.
-
-
-%%% Parse the scheme.
-parse_scheme(URI) ->
- parse_scheme(URI,[]).
-
-parse_scheme([H|URI],Acc) when $a=<H,H=<$z; $A=<H,H=<$Z ->
- parse_scheme2(URI,[H|Acc]);
-parse_scheme(_,_) ->
- {error,no_scheme}.
-
-parse_scheme2([H|URI],Acc)
- when $a=<H,H=<$z; $A=<H,H=<$Z; $0=<H,H=<$9; H==$-;H==$+;H==$. ->
- parse_scheme2(URI,[H|Acc]);
-parse_scheme2([$:|URI],Acc) ->
- {list_to_atom(lists:reverse(Acc)),URI};
-parse_scheme2(_,_) ->
- {error,no_scheme}.
-
-
-%%% ............................................................................
--define(HTTP_DEFAULT_PORT, 80).
--define(HTTPS_DEFAULT_PORT, 443).
-
-%%% HTTP (Source RFC 2396, RFC 2616)
-%%% http_URL = "*" | absoluteURI | abs_path [ "?" query ] | authority
-
-%%% http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]
-%%% Returns a tuple {http,Host,Port,PathQuery} where
-%%% Host = string() Host value
-%%% Port = string() Port value
-%%% PathQuery= string() Combined absolute path and query value
-parse_http("//"++C0,Scheme) ->
- case scan_hostport(C0,Scheme) of
- {C1,Host,Port} ->
- case scan_pathquery(C1) of
- {error,Error} ->
- {error,Error};
- PathQuery ->
- {Scheme,Host,Port,PathQuery}
- end;
- {error,Error} ->
- {error,Error}
- end;
-parse_http(_,_) ->
- {error,invalid_url}.
-
-scan_pathquery(C0) ->
- case scan_abspath(C0) of
- {error,Error} ->
- {error,Error};
- {[],[]} -> % Add implicit path
- "/";
- {"?"++C1,Path} ->
- case scan_query(C1,[]) of
- {error,Error} ->
- {error,Error};
- Query ->
- Path++"?"++Query
- end;
- {[],Path} ->
- Path
- end.
-
-
-%%% ............................................................................
-%%% FIXME!!! This is just a quick hack that doesn't work!
--define(FTP_DEFAULT_PORT, 80).
-
-%%% FTP (Source RFC 2396, RFC 1738, RFC 959)
-%%% Note: This BNF has been modified to better fit with RFC 2396
-%%% ftp_URL = "ftp:" "//" [ ftp_userinfo ] host [ ":" port ] ftp_abs_path
-%%% ftp_userinfo = ftp_user [ ":" ftp_password ]
-%%% ftp_abs_path = "/" ftp_path_segments [ ";type=" ftp_type ]
-%%% ftp_path_segments = ftp_segment *( "/" ftp_segment)
-%%% ftp_segment = *[ ftp_uchar | "?" | ":" | "@" | "&" | "=" ]
-%%% ftp_type = "A" | "I" | "D" | "a" | "i" | "d"
-%%% ftp_user = *[ ftp_uchar | ";" | "?" | "&" | "=" ]
-%%% ftp_password = *[ ftp_uchar | ";" | "?" | "&" | "=" ]
-%%% ftp_uchar = ftp_unreserved | escaped
-%%% ftp_unreserved = alphanum | mark | "$" | "+" | ","
-parse_ftp("//"++C0,Scheme) ->
- case ftp_userinfo(C0) of
- {C1,Creds} ->
- case scan_hostport(C1,Scheme) of
- {C2,Host,Port} ->
- case scan_abspath(C2) of
- {error,Error} ->
- {error,Error};
- {[],[]} -> % Add implicit path
- {Scheme,Creds,Host,Port,"/"};
- {[],Path} ->
- {Scheme,Creds,Host,Port,Path}
- end;
- {error,Error} ->
- {error,Error}
- end;
- {error,Error} ->
- {error,Error}
- end.
-
-ftp_userinfo(C0) ->
- User="",
- Password="",
- {C0,{User,Password}}.
-
-
-%%% ............................................................................
-%%% SIP (Source RFC 2396, RFC 2543)
-%%% sip_URL = "sip:" [ sip_userinfo "@" ] host [ ":" port ]
-%%% sip_url-parameters [ sip_headers ]
-%%% sip_userinfo = sip_user [ ":" sip_password ]
-%%% sip_user = *( unreserved | escaped | "&" | "=" | "+" | "$" | "," )
-%%% sip_password = *( unreserved | escaped | "&" | "=" | "+" | "$" | "," )
-%%% sip_url-parameters = *( ";" sip_url-parameter )
-%%% sip_url-parameter = sip_transport-param | sip_user-param |
-%%% sip_method-param | sip_ttl-param |
-%%% sip_maddr-param | sip_other-param
-%%% sip_transport-param = "transport=" ( "udp" | "tcp" )
-%%% sip_ttl-param = "ttl=" sip_ttl
-%%% sip_ttl = 1*3DIGIT ; 0 to 255
-%%% sip_maddr-param = "maddr=" host
-%%% sip_user-param = "user=" ( "phone" | "ip" )
-%%% sip_method-param = "method=" sip_Method
-%%% sip_tag-param = "tag=" sip_UUID
-%%% sip_UUID = 1*( hex | "-" )
-%%% sip_other-param = ( token | ( token "=" ( token | quoted-string )))
-%%% sip_Method = "INVITE" | "ACK" | "OPTIONS" | "BYE" |
-%%% "CANCEL" | "REGISTER"
-%%% sip_token = 1*< any CHAR except CTL's or separators>
-%%% sip_quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
-%%% sip_qdtext = <any TEXT-UTF8 except <">>
-%%% sip_quoted-pair = " \ " CHAR
-parse_sip(Cont,Scheme) ->
- {Scheme,Cont}.
-
-
-
-
-%%% ............................................................................
-%%% SMS (Source draft-wilde-sms-uri-01, January 24 2002 and
-%%% draft-allocchio-gstn-01, November 2001)
-%%% The syntax definition for "gstn-phone" is taken from
-%%% [draft-allocchio-gstn-01], allowing global as well as local telephone
-%%% numbers.
-%%% Note: This BNF has been modified to better fit with RFC 2396
-%%% sms_URI = sms ":" 1*( sms-recipient ) [ sms-body ]
-%%% sms-recipient = gstn-phone sms-qualifier
-%%% [ "," sms-recipient ]
-%%% sms-qualifier = *( smsc-qualifier / pid-qualifier )
-%%% smsc-qualifier = ";smsc=" SMSC-sub-addr
-%%% pid-qualifier = ";pid=" PID-sub-addr
-%%% sms-body = ";body=" *urlc
-%%% gstn-phone = ( global-phone / local-phone )
-%%% global-phone = "+" 1*( DIGIT / written-sep )
-%%% local-phone = [ exit-code ] dial-number / exit-code [ dial-number ]
-%%% exit-code = phone-string
-%%% dial-number = phone-string
-%%% subaddr-string = phone-string
-%%% post-dial = phone-string
-%%% phone-string = 1*( DTMF / pause / tonewait / written-sep )
-%%% DTMF = ( DIGIT / "#" / "*" / "A" / "B" / "C" / "D" )
-%%% written-sep = ( "-" / "." )
-%%% pause = "p"
-%%% tonewait = "w"
-parse_sms(Cont,Scheme) ->
- {Scheme,Cont}.
-
-
-%%% ============================================================================
-%%% Generic URI parsing. BNF rules from RFC 2396
-
-%%% hostport = host [ ":" port ]
-scan_hostport(C0,Scheme) ->
- case scan_host(C0) of
- {error,Error} ->
- {error,Error};
- {":"++C1,Host} ->
- {C2,Port}=scan_port(C1,[]),
- {C2,Host,list_to_integer(Port)};
- {C1,Host} when Scheme==http ->
- {C1,Host,?HTTP_DEFAULT_PORT};
- {C1,Host} when Scheme==https ->
- {C1,Host,?HTTPS_DEFAULT_PORT};
- {C1,Host} when Scheme==ftp ->
- {C1,Host,?FTP_DEFAULT_PORT}
- end.
-
-
-%%% host = hostname | IPv4address
-%%% hostname = *( domainlabel "." ) toplabel [ "." ]
-%%% domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
-%%% toplabel = alpha | alpha *( alphanum | "-" ) alphanum
-%%% IPv4address = 1*digit "." 1*digit "." 1*digit "." 1*digit
-
--define(ALPHA, 1).
--define(DIGIT, 2).
-
-scan_host(C0) ->
- case scan_host2(C0,[],0,[],[]) of
- {C1,IPv4address,[?DIGIT,?DIGIT,?DIGIT,?DIGIT]} ->
- {C1,lists:reverse(lists:append(IPv4address))};
- {C1,Hostname,[?ALPHA|HostF]} ->
- {C1,lists:reverse(lists:append(Hostname))};
- _ ->
- {error,no_host}
- end.
-
-scan_host2([H|C0],Acc,CurF,Host,HostF) when $0=<H,H=<$9 ->
- scan_host2(C0,[H|Acc],CurF bor ?DIGIT,Host,HostF);
-scan_host2([H|C0],Acc,CurF,Host,HostF) when $a=<H,H=<$z; $A=<H,H=<$Z ->
- scan_host2(C0,[H|Acc],CurF bor ?ALPHA,Host,HostF);
-scan_host2([$-|C0],Acc,CurF,Host,HostF) when CurF=/=0 ->
- scan_host2(C0,[$-|Acc],CurF,Host,HostF);
-scan_host2([$.|C0],Acc,CurF,Host,HostF) when CurF=/=0 ->
- scan_host2(C0,[],0,[".",Acc|Host],[CurF|HostF]);
-scan_host2(C0,Acc,CurF,Host,HostF) ->
- {C0,[Acc|Host],[CurF|HostF]}.
-
-
-%%% port = *digit
-scan_port([H|C0],Acc) when $0=<H,H=<$9 ->
- scan_port(C0,[H|Acc]);
-scan_port(C0,Acc) ->
- {C0,lists:reverse(Acc)}.
-
-%%% abs_path = "/" path_segments
-scan_abspath([]) ->
- {[],[]};
-scan_abspath("/"++C0) ->
- scan_pathsegments(C0,["/"]);
-scan_abspath(_) ->
- {error,no_abspath}.
-
-%%% path_segments = segment *( "/" segment )
-scan_pathsegments(C0,Acc) ->
- case scan_segment(C0,[]) of
- {"/"++C1,Segment} ->
- scan_pathsegments(C1,["/",Segment|Acc]);
- {C1,Segment} ->
- {C1,lists:reverse(lists:append([Segment|Acc]))}
- end.
-
-
-%%% segment = *pchar *( ";" param )
-%%% param = *pchar
-scan_segment(";"++C0,Acc) ->
- {C1,ParamAcc}=scan_pchars(C0,";"++Acc),
- scan_segment(C1,ParamAcc);
-scan_segment(C0,Acc) ->
- case scan_pchars(C0,Acc) of
- {";"++C1,Segment} ->
- {C2,ParamAcc}=scan_pchars(C1,";"++Segment),
- scan_segment(C2,ParamAcc);
- {C1,Segment} ->
- {C1,Segment}
- end.
-
-%%% query = *uric
-%%% uric = reserved | unreserved | escaped
-%%% reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
-%%% "$" | ","
-%%% unreserved = alphanum | mark
-%%% mark = "-" | "_" | "." | "!" | "~" | "*" | "'" |
-%%% "(" | ")"
-%%% escaped = "%" hex hex
-scan_query([],Acc) ->
- lists:reverse(Acc);
-scan_query([$%,H1,H2|C0],Acc) -> % escaped
- scan_query(C0,[hex2dec(H1)*16+hex2dec(H2)|Acc]);
-scan_query([H|C0],Acc) when $a=<H,H=<$z;$A=<H,H=<$Z;$0=<H,H=<$9 -> % alphanum
- scan_query(C0,[H|Acc]);
-scan_query([H|C0],Acc) when H==$;; H==$/; H==$?; H==$:; H==$@;
- H==$&; H==$=; H==$+; H==$$; H==$, -> % reserved
- scan_query(C0,[H|Acc]);
-scan_query([H|C0],Acc) when H==$-; H==$_; H==$.; H==$!; H==$~;
- H==$*; H==$'; H==$(; H==$) -> % mark
- scan_query(C0,[H|Acc]);
-scan_query([H|C0],Acc) ->
- {error,no_query}.
-
-
-%%% pchar = unreserved | escaped |
-%%% ":" | "@" | "&" | "=" | "+" | "$" | ","
-scan_pchars([],Acc) ->
- {[],Acc};
-scan_pchars([$%,H1,H2|C0],Acc) -> % escaped
- scan_pchars(C0,[hex2dec(H1)*16+hex2dec(H2)|Acc]);
-scan_pchars([H|C0],Acc) when $a=<H,H=<$z;$A=<H,H=<$Z;$0=<H,H=<$9 -> % alphanum
- scan_pchars(C0,[H|Acc]);
-scan_pchars([H|C0],Acc) when H==$-; H==$_; H==$.; H==$!; H==$~;
- H==$*; H==$'; H==$(; H==$) -> % mark
- scan_pchars(C0,[H|Acc]);
-scan_pchars([H|C0],Acc) when H==$:; H==$@; H==$&; H==$=; H==$+; H==$$; H==$, ->
- scan_pchars(C0,[H|Acc]);
-scan_pchars(C0,Acc) ->
- {C0,Acc}.
-
-hex2dec(X) when X>=$0,X=<$9 -> X-$0;
-hex2dec(X) when X>=$A,X=<$F -> X-$A+10;
-hex2dec(X) when X>=$a,X=<$f -> X-$a+10.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/Makefile b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/Makefile
deleted file mode 100644
index 461dc82155..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/Makefile
+++ /dev/null
@@ -1,137 +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: Makefile,v 1.1 2008/12/17 09:53:37 mikpe Exp $
-#
-include $(ERL_TOP)/make/target.mk
-
-ifeq ($(TYPE),debug)
-ERL_COMPILE_FLAGS += -Ddebug -W
-endif
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(MNESIA_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/mnesia-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-MODULES= \
- mnesia \
- mnesia_backup \
- mnesia_bup \
- mnesia_checkpoint \
- mnesia_checkpoint_sup \
- mnesia_controller \
- mnesia_dumper\
- mnesia_event \
- mnesia_frag \
- mnesia_frag_hash \
- mnesia_frag_old_hash \
- mnesia_index \
- mnesia_kernel_sup \
- mnesia_late_loader \
- mnesia_lib\
- mnesia_loader \
- mnesia_locker \
- mnesia_log \
- mnesia_monitor \
- mnesia_recover \
- mnesia_registry \
- mnesia_schema\
- mnesia_snmp_hook \
- mnesia_snmp_sup \
- mnesia_subscr \
- mnesia_sup \
- mnesia_sp \
- mnesia_text \
- mnesia_tm
-
-HRL_FILES= mnesia.hrl
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
-
-APP_FILE= mnesia.app
-
-APP_SRC= $(APP_FILE).src
-APP_TARGET= $(EBIN)/$(APP_FILE)
-
-APPUP_FILE= mnesia.appup
-
-APPUP_SRC= $(APPUP_FILE).src
-APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
-
-
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_FLAGS +=
-ERL_COMPILE_FLAGS += \
- +warn_unused_vars \
- +'{parse_transform,sys_pre_attributes}' \
- +'{attribute,insert,vsn,"mnesia_$(MNESIA_VSN)"}' \
- -W
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-opt: $(TARGET_FILES)
-
-debug:
- @${MAKE} TYPE=debug
-
-clean:
- rm -f $(TARGET_FILES)
- rm -f core
-
-docs:
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-$(APP_TARGET): $(APP_SRC) ../vsn.mk
- sed -e 's;%VSN%;$(VSN);' $< > $@
-
-$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
- sed -e 's;%VSN%;$(VSN);' $< > $@
-
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
-
-release_docs_spec:
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia.app.src b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia.app.src
deleted file mode 100644
index 3715488ec2..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia.app.src
+++ /dev/null
@@ -1,52 +0,0 @@
-{application, mnesia,
- [{description, "MNESIA CXC 138 12"},
- {vsn, "%VSN%"},
- {modules, [
- mnesia,
- mnesia_backup,
- mnesia_bup,
- mnesia_checkpoint,
- mnesia_checkpoint_sup,
- mnesia_controller,
- mnesia_dumper,
- mnesia_event,
- mnesia_frag,
- mnesia_frag_hash,
- mnesia_frag_old_hash,
- mnesia_index,
- mnesia_kernel_sup,
- mnesia_late_loader,
- mnesia_lib,
- mnesia_loader,
- mnesia_locker,
- mnesia_log,
- mnesia_monitor,
- mnesia_recover,
- mnesia_registry,
- mnesia_schema,
- mnesia_snmp_hook,
- mnesia_snmp_sup,
- mnesia_subscr,
- mnesia_sup,
- mnesia_sp,
- mnesia_text,
- mnesia_tm
- ]},
- {registered, [
- mnesia_dumper_load_regulator,
- mnesia_event,
- mnesia_fallback,
- mnesia_controller,
- mnesia_kernel_sup,
- mnesia_late_loader,
- mnesia_locker,
- mnesia_monitor,
- mnesia_recover,
- mnesia_substr,
- mnesia_sup,
- mnesia_tm
- ]},
- {applications, [kernel, stdlib]},
- {mod, {mnesia_sup, []}}]}.
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia.appup.src b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia.appup.src
deleted file mode 100644
index 502ddb02fc..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia.appup.src
+++ /dev/null
@@ -1,6 +0,0 @@
-{"%VSN%",
- [
- ],
- [
- ]
-}.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia.erl
deleted file mode 100644
index 956f4f5395..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia.erl
+++ /dev/null
@@ -1,2191 +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: mnesia.erl,v 1.2 2010/03/04 13:54:19 maria Exp $
-%%
-%% This module exports the public interface of the Mnesia DBMS engine
-
--module(mnesia).
-%-behaviour(mnesia_access).
-
--export([
- %% Start, stop and debugging
- start/0, start/1, stop/0, % Not for public use
- set_debug_level/1, lkill/0, kill/0, % Not for public use
- ms/0, nc/0, nc/1, ni/0, ni/1, % Not for public use
- change_config/2,
-
- %% Activity mgt
- abort/1, transaction/1, transaction/2, transaction/3,
- sync_transaction/1, sync_transaction/2, sync_transaction/3,
- async_dirty/1, async_dirty/2, sync_dirty/1, sync_dirty/2, ets/1, ets/2,
- activity/2, activity/3, activity/4, % Not for public use
-
- %% Access within an activity - Lock acquisition
- lock/2, lock/4,
- read_lock_table/1,
- write_lock_table/1,
-
- %% Access within an activity - Updates
- write/1, s_write/1, write/3, write/5,
- delete/1, s_delete/1, delete/3, delete/5,
- delete_object/1, s_delete_object/1, delete_object/3, delete_object/5,
-
- %% Access within an activity - Reads
- read/1, wread/1, read/3, read/5,
- match_object/1, match_object/3, match_object/5,
- select/2, select/3, select/5,
- all_keys/1, all_keys/4,
- index_match_object/2, index_match_object/4, index_match_object/6,
- index_read/3, index_read/6,
-
- %% Iterators within an activity
- foldl/3, foldl/4, foldr/3, foldr/4,
-
- %% Dirty access regardless of activities - Updates
- dirty_write/1, dirty_write/2,
- dirty_delete/1, dirty_delete/2,
- dirty_delete_object/1, dirty_delete_object/2,
- dirty_update_counter/2, dirty_update_counter/3,
-
- %% Dirty access regardless of activities - Read
- dirty_read/1, dirty_read/2,
- dirty_select/2,
- dirty_match_object/1, dirty_match_object/2, dirty_all_keys/1,
- dirty_index_match_object/2, dirty_index_match_object/3,
- dirty_index_read/3, dirty_slot/2,
- dirty_first/1, dirty_next/2, dirty_last/1, dirty_prev/2,
-
- %% Info
- table_info/2, table_info/4, schema/0, schema/1,
- error_description/1, info/0, system_info/1,
- system_info/0, % Not for public use
-
- %% Database mgt
- create_schema/1, delete_schema/1,
- backup/1, backup/2, traverse_backup/4, traverse_backup/6,
- install_fallback/1, install_fallback/2,
- uninstall_fallback/0, uninstall_fallback/1,
- activate_checkpoint/1, deactivate_checkpoint/1,
- backup_checkpoint/2, backup_checkpoint/3, restore/2,
-
- %% Table mgt
- create_table/1, create_table/2, delete_table/1,
- add_table_copy/3, del_table_copy/2, move_table_copy/3,
- add_table_index/2, del_table_index/2,
- transform_table/3, transform_table/4,
- change_table_copy_type/3,
- read_table_property/2, write_table_property/2, delete_table_property/2,
- change_table_frag/2,
- clear_table/1,
-
- %% Table load
- dump_tables/1, wait_for_tables/2, force_load_table/1,
- change_table_access_mode/2, change_table_load_order/2,
- set_master_nodes/1, set_master_nodes/2,
-
- %% Misc admin
- dump_log/0, subscribe/1, unsubscribe/1, report_event/1,
-
- %% Snmp
- snmp_open_table/2, snmp_close_table/1,
- snmp_get_row/2, snmp_get_next_index/2, snmp_get_mnesia_key/2,
-
- %% Textfile access
- load_textfile/1, dump_to_textfile/1,
-
- %% Mnemosyne exclusive
- get_activity_id/0, put_activity_id/1, % Not for public use
-
- %% Mnesia internal functions
- dirty_rpc/4, % Not for public use
- has_var/1, fun_select/7,
- foldl/6, foldr/6,
-
- %% Module internal callback functions
- remote_dirty_match_object/2, % Not for public use
- remote_dirty_select/2 % Not for public use
- ]).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
--include("mnesia.hrl").
--import(mnesia_lib, [verbose/2]).
-
--define(DEFAULT_ACCESS, ?MODULE).
-
-%% Select
--define(PATTERN_TO_OBJECT_MATCH_SPEC(Pat), [{Pat,[],['$_']}]).
--define(PATTERN_TO_BINDINGS_MATCH_SPEC(Pat), [{Pat,[],['$$']}]).
-
-%% Local function in order to avoid external function call
-val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
- Value -> Value
- end.
-
-is_dollar_digits(Var) ->
- case atom_to_list(Var) of
- [$$ | Digs] ->
- is_digits(Digs);
- _ ->
- false
- end.
-
-is_digits([Dig | Tail]) ->
- if
- $0 =< Dig, Dig =< $9 ->
- is_digits(Tail);
- true ->
- false
- end;
-is_digits([]) ->
- true.
-
-has_var(X) when atom(X) ->
- if
- X == '_' ->
- true;
- atom(X) ->
- is_dollar_digits(X);
- true ->
- false
- end;
-has_var(X) when tuple(X) ->
- e_has_var(X, size(X));
-has_var([H|T]) ->
- case has_var(H) of
- false -> has_var(T);
- Other -> Other
- end;
-has_var(_) -> false.
-
-e_has_var(_, 0) -> false;
-e_has_var(X, Pos) ->
- case has_var(element(Pos, X))of
- false -> e_has_var(X, Pos-1);
- Other -> Other
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Start and stop
-
-start() ->
- {Time , Res} = timer:tc(application, start, [?APPLICATION, temporary]),
-
- Secs = Time div 1000000,
- case Res of
- ok ->
- verbose("Mnesia started, ~p seconds~n",[ Secs]),
- ok;
- {error, {already_started, mnesia}} ->
- verbose("Mnesia already started, ~p seconds~n",[ Secs]),
- ok;
- {error, R} ->
- verbose("Mnesia failed to start, ~p seconds: ~p~n",[ Secs, R]),
- {error, R}
- end.
-
-start(ExtraEnv) when list(ExtraEnv) ->
- case mnesia_lib:ensure_loaded(?APPLICATION) of
- ok ->
- patched_start(ExtraEnv);
- Error ->
- Error
- end;
-start(ExtraEnv) ->
- {error, {badarg, ExtraEnv}}.
-
-patched_start([{Env, Val} | Tail]) when atom(Env) ->
- case mnesia_monitor:patch_env(Env, Val) of
- {error, Reason} ->
- {error, Reason};
- _NewVal ->
- patched_start(Tail)
- end;
-patched_start([Head | _]) ->
- {error, {bad_type, Head}};
-patched_start([]) ->
- start().
-
-stop() ->
- case application:stop(?APPLICATION) of
- ok -> stopped;
- {error, {not_started, ?APPLICATION}} -> stopped;
- Other -> Other
- end.
-
-change_config(extra_db_nodes, Ns) when list(Ns) ->
- mnesia_controller:connect_nodes(Ns);
-change_config(BadKey, _BadVal) ->
- {error, {badarg, BadKey}}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Debugging
-
-set_debug_level(Level) ->
- mnesia_subscr:set_debug_level(Level).
-
-lkill() ->
- mnesia_sup:kill().
-
-kill() ->
- rpc:multicall(mnesia_sup, kill, []).
-
-ms() ->
- [
- mnesia,
- mnesia_backup,
- mnesia_bup,
- mnesia_checkpoint,
- mnesia_checkpoint_sup,
- mnesia_controller,
- mnesia_dumper,
- mnesia_loader,
- mnesia_frag,
- mnesia_frag_hash,
- mnesia_frag_old_hash,
- mnesia_index,
- mnesia_kernel_sup,
- mnesia_late_loader,
- mnesia_lib,
- mnesia_log,
- mnesia_registry,
- mnesia_schema,
- mnesia_snmp_hook,
- mnesia_snmp_sup,
- mnesia_subscr,
- mnesia_sup,
- mnesia_text,
- mnesia_tm,
- mnesia_recover,
- mnesia_locker,
-
- %% Keep these last in the list, so
- %% mnesia_sup kills these last
- mnesia_monitor,
- mnesia_event
- ].
-
-nc() ->
- Mods = ms(),
- nc(Mods).
-
-nc(Mods) when list(Mods)->
- [Mod || Mod <- Mods, ok /= load(Mod, compile)].
-
-ni() ->
- Mods = ms(),
- ni(Mods).
-
-ni(Mods) when list(Mods) ->
- [Mod || Mod <- Mods, ok /= load(Mod, interpret)].
-
-load(Mod, How) when atom(Mod) ->
- case try_load(Mod, How) of
- ok ->
- ok;
- _ ->
- mnesia_lib:show( "~n RETRY ~p FROM: ", [Mod]),
- Abs = mod2abs(Mod),
- load(Abs, How)
- end;
-load(Abs, How) ->
- case try_load(Abs, How) of
- ok ->
- ok;
- {error, Reason} ->
- mnesia_lib:show( " *** ERROR *** ~p~n", [Reason]),
- {error, Reason}
- end.
-
-try_load(Mod, How) ->
- mnesia_lib:show( " ~p ", [Mod]),
- Flags = [{d, debug}],
- case How of
- compile ->
- case catch c:nc(Mod, Flags) of
- {ok, _} -> ok;
- Other -> {error, Other}
- end;
- interpret ->
- case catch int:ni(Mod, Flags) of
- {module, _} -> ok;
- Other -> {error, Other}
- end
- end.
-
-mod2abs(Mod) ->
- ModString = atom_to_list(Mod),
- SubDir =
- case lists:suffix("test", ModString) of
- true -> test;
- false -> src
- end,
- filename:join([code:lib_dir(?APPLICATION), SubDir, ModString]).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Activity mgt
-
-abort(Reason) ->
- exit({aborted, Reason}).
-
-transaction(Fun) ->
- transaction(get(mnesia_activity_state), Fun, [], infinity, ?DEFAULT_ACCESS, async).
-transaction(Fun, Retries) when integer(Retries), Retries >= 0 ->
- transaction(get(mnesia_activity_state), Fun, [], Retries, ?DEFAULT_ACCESS, async);
-transaction(Fun, Retries) when Retries == infinity ->
- transaction(get(mnesia_activity_state), Fun, [], Retries, ?DEFAULT_ACCESS, async);
-transaction(Fun, Args) ->
- transaction(get(mnesia_activity_state), Fun, Args, infinity, ?DEFAULT_ACCESS, async).
-transaction(Fun, Args, Retries) ->
- transaction(get(mnesia_activity_state), Fun, Args, Retries, ?DEFAULT_ACCESS, async).
-
-sync_transaction(Fun) ->
- transaction(get(mnesia_activity_state), Fun, [], infinity, ?DEFAULT_ACCESS, sync).
-sync_transaction(Fun, Retries) when integer(Retries), Retries >= 0 ->
- transaction(get(mnesia_activity_state), Fun, [], Retries, ?DEFAULT_ACCESS, sync);
-sync_transaction(Fun, Retries) when Retries == infinity ->
- transaction(get(mnesia_activity_state), Fun, [], Retries, ?DEFAULT_ACCESS, sync);
-sync_transaction(Fun, Args) ->
- transaction(get(mnesia_activity_state), Fun, Args, infinity, ?DEFAULT_ACCESS, sync).
-sync_transaction(Fun, Args, Retries) ->
- transaction(get(mnesia_activity_state), Fun, Args, Retries, ?DEFAULT_ACCESS, sync).
-
-
-transaction(State, Fun, Args, Retries, Mod, Kind)
- when function(Fun), list(Args), Retries == infinity, atom(Mod) ->
- mnesia_tm:transaction(State, Fun, Args, Retries, Mod, Kind);
-transaction(State, Fun, Args, Retries, Mod, Kind)
- when function(Fun), list(Args), integer(Retries), Retries >= 0, atom(Mod) ->
- mnesia_tm:transaction(State, Fun, Args, Retries, Mod, Kind);
-transaction(_State, Fun, Args, Retries, Mod, _Kind) ->
- {aborted, {badarg, Fun, Args, Retries, Mod}}.
-
-non_transaction(State, Fun, Args, ActivityKind, Mod)
- when function(Fun), list(Args), atom(Mod) ->
- mnesia_tm:non_transaction(State, Fun, Args, ActivityKind, Mod);
-non_transaction(_State, Fun, Args, _ActivityKind, _Mod) ->
- {aborted, {badarg, Fun, Args}}.
-
-async_dirty(Fun) ->
- async_dirty(Fun, []).
-async_dirty(Fun, Args) ->
- non_transaction(get(mnesia_activity_state), Fun, Args, async_dirty, ?DEFAULT_ACCESS).
-
-sync_dirty(Fun) ->
- sync_dirty(Fun, []).
-sync_dirty(Fun, Args) ->
- non_transaction(get(mnesia_activity_state), Fun, Args, sync_dirty, ?DEFAULT_ACCESS).
-
-ets(Fun) ->
- ets(Fun, []).
-ets(Fun, Args) ->
- non_transaction(get(mnesia_activity_state), Fun, Args, ets, ?DEFAULT_ACCESS).
-
-activity(Kind, Fun) ->
- activity(Kind, Fun, []).
-activity(Kind, Fun, Args) when list(Args) ->
- activity(Kind, Fun, Args, mnesia_monitor:get_env(access_module));
-activity(Kind, Fun, Mod) ->
- activity(Kind, Fun, [], Mod).
-
-activity(Kind, Fun, Args, Mod) ->
- State = get(mnesia_activity_state),
- case Kind of
- ets -> non_transaction(State, Fun, Args, Kind, Mod);
- async_dirty -> non_transaction(State, Fun, Args, Kind, Mod);
- sync_dirty -> non_transaction(State, Fun, Args, Kind, Mod);
- transaction -> wrap_trans(State, Fun, Args, infinity, Mod, async);
- {transaction, Retries} -> wrap_trans(State, Fun, Args, Retries, Mod, async);
- sync_transaction -> wrap_trans(State, Fun, Args, infinity, Mod, sync);
- {sync_transaction, Retries} -> wrap_trans(State, Fun, Args, Retries, Mod, sync);
- _ -> {aborted, {bad_type, Kind}}
- end.
-
-wrap_trans(State, Fun, Args, Retries, Mod, Kind) ->
- case transaction(State, Fun, Args, Retries, Mod, Kind) of
- {'atomic', GoodRes} -> GoodRes;
- BadRes -> exit(BadRes)
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Access within an activity - lock acquisition
-
-%% Grab a lock on an item in the global lock table
-%% Item may be any term. Lock may be write or read.
-%% write lock is set on all the given nodes
-%% read lock is only set on the first node
-%% Nodes may either be a list of nodes or one node as an atom
-%% Mnesia on all Nodes must be connected to each other, but
-%% it is not neccessary that they are up and running.
-
-lock(LockItem, LockKind) ->
- case get(mnesia_activity_state) of
- {?DEFAULT_ACCESS, Tid, Ts} ->
- lock(Tid, Ts, LockItem, LockKind);
- {Mod, Tid, Ts} ->
- Mod:lock(Tid, Ts, LockItem, LockKind);
- _ ->
- abort(no_transaction)
- end.
-
-lock(Tid, Ts, LockItem, LockKind) ->
- case element(1, Tid) of
- tid ->
- case LockItem of
- {record, Tab, Key} ->
- lock_record(Tid, Ts, Tab, Key, LockKind);
- {table, Tab} ->
- lock_table(Tid, Ts, Tab, LockKind);
- {global, GlobalKey, Nodes} ->
- global_lock(Tid, Ts, GlobalKey, LockKind, Nodes);
- _ ->
- abort({bad_type, LockItem})
- end;
- _Protocol ->
- []
- end.
-
-%% Grab a read lock on a whole table
-read_lock_table(Tab) ->
- lock({table, Tab}, read),
- ok.
-
-%% Grab a write lock on a whole table
-write_lock_table(Tab) ->
- lock({table, Tab}, write),
- ok.
-
-lock_record(Tid, Ts, Tab, Key, LockKind) when atom(Tab) ->
- Store = Ts#tidstore.store,
- Oid = {Tab, Key},
- case LockKind of
- read ->
- mnesia_locker:rlock(Tid, Store, Oid);
- write ->
- mnesia_locker:wlock(Tid, Store, Oid);
- sticky_write ->
- mnesia_locker:sticky_wlock(Tid, Store, Oid);
- none ->
- [];
- _ ->
- abort({bad_type, Tab, LockKind})
- end;
-lock_record(_Tid, _Ts, Tab, _Key, _LockKind) ->
- abort({bad_type, Tab}).
-
-lock_table(Tid, Ts, Tab, LockKind) when atom(Tab) ->
- Store = Ts#tidstore.store,
- case LockKind of
- read ->
- mnesia_locker:rlock_table(Tid, Store, Tab);
- write ->
- mnesia_locker:wlock_table(Tid, Store, Tab);
- sticky_write ->
- mnesia_locker:sticky_wlock_table(Tid, Store, Tab);
- none ->
- [];
- _ ->
- abort({bad_type, Tab, LockKind})
- end;
-lock_table(_Tid, _Ts, Tab, _LockKind) ->
- abort({bad_type, Tab}).
-
-global_lock(Tid, Ts, Item, Kind, Nodes) when list(Nodes) ->
- case element(1, Tid) of
- tid ->
- Store = Ts#tidstore.store,
- GoodNs = good_global_nodes(Nodes),
- if
- Kind /= read, Kind /= write ->
- abort({bad_type, Kind});
- true ->
- mnesia_locker:global_lock(Tid, Store, Item, Kind, GoodNs)
- end;
- _Protocol ->
- []
- end;
-global_lock(_Tid, _Ts, _Item, _Kind, Nodes) ->
- abort({bad_type, Nodes}).
-
-good_global_nodes(Nodes) ->
- Recover = [node() | val(recover_nodes)],
- mnesia_lib:intersect(Nodes, Recover).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Access within an activity - updates
-
-write(Val) when tuple(Val), size(Val) > 2 ->
- Tab = element(1, Val),
- write(Tab, Val, write);
-write(Val) ->
- abort({bad_type, Val}).
-
-s_write(Val) when tuple(Val), size(Val) > 2 ->
- Tab = element(1, Val),
- write(Tab, Val, sticky_write).
-
-write(Tab, Val, LockKind) ->
- case get(mnesia_activity_state) of
- {?DEFAULT_ACCESS, Tid, Ts} ->
- write(Tid, Ts, Tab, Val, LockKind);
- {Mod, Tid, Ts} ->
- Mod:write(Tid, Ts, Tab, Val, LockKind);
- _ ->
- abort(no_transaction)
- end.
-
-write(Tid, Ts, Tab, Val, LockKind)
- when atom(Tab), Tab /= schema, tuple(Val), size(Val) > 2 ->
- case element(1, Tid) of
- ets ->
- ?ets_insert(Tab, Val),
- ok;
- tid ->
- Store = Ts#tidstore.store,
- Oid = {Tab, element(2, Val)},
- case LockKind of
- write ->
- mnesia_locker:wlock(Tid, Store, Oid);
- sticky_write ->
- mnesia_locker:sticky_wlock(Tid, Store, Oid);
- _ ->
- abort({bad_type, Tab, LockKind})
- end,
- write_to_store(Tab, Store, Oid, Val);
- Protocol ->
- do_dirty_write(Protocol, Tab, Val)
- end;
-write(_Tid, _Ts, Tab, Val, LockKind) ->
- abort({bad_type, Tab, Val, LockKind}).
-
-write_to_store(Tab, Store, Oid, Val) ->
- case ?catch_val({Tab, record_validation}) of
- {RecName, Arity, Type}
- when size(Val) == Arity, RecName == element(1, Val) ->
- case Type of
- bag ->
- ?ets_insert(Store, {Oid, Val, write});
- _ ->
- ?ets_delete(Store, Oid),
- ?ets_insert(Store, {Oid, Val, write})
- end,
- ok;
- {'EXIT', _} ->
- abort({no_exists, Tab});
- _ ->
- abort({bad_type, Val})
- end.
-
-delete({Tab, Key}) ->
- delete(Tab, Key, write);
-delete(Oid) ->
- abort({bad_type, Oid}).
-
-s_delete({Tab, Key}) ->
- delete(Tab, Key, sticky_write);
-s_delete(Oid) ->
- abort({bad_type, Oid}).
-
-delete(Tab, Key, LockKind) ->
- case get(mnesia_activity_state) of
- {?DEFAULT_ACCESS, Tid, Ts} ->
- delete(Tid, Ts, Tab, Key, LockKind);
- {Mod, Tid, Ts} ->
- Mod:delete(Tid, Ts, Tab, Key, LockKind);
- _ ->
- abort(no_transaction)
- end.
-
-delete(Tid, Ts, Tab, Key, LockKind)
- when atom(Tab), Tab /= schema ->
- case element(1, Tid) of
- ets ->
- ?ets_delete(Tab, Key),
- ok;
- tid ->
- Store = Ts#tidstore.store,
- Oid = {Tab, Key},
- case LockKind of
- write ->
- mnesia_locker:wlock(Tid, Store, Oid);
- sticky_write ->
- mnesia_locker:sticky_wlock(Tid, Store, Oid);
- _ ->
- abort({bad_type, Tab, LockKind})
- end,
- ?ets_delete(Store, Oid),
- ?ets_insert(Store, {Oid, Oid, delete}),
- ok;
- Protocol ->
- do_dirty_delete(Protocol, Tab, Key)
- end;
-delete(_Tid, _Ts, Tab, _Key, _LockKind) ->
- abort({bad_type, Tab}).
-
-delete_object(Val) when tuple(Val), size(Val) > 2 ->
- Tab = element(1, Val),
- delete_object(Tab, Val, write);
-delete_object(Val) ->
- abort({bad_type, Val}).
-
-s_delete_object(Val) when tuple(Val), size(Val) > 2 ->
- Tab = element(1, Val),
- delete_object(Tab, Val, sticky_write);
-s_delete_object(Val) ->
- abort({bad_type, Val}).
-
-delete_object(Tab, Val, LockKind) ->
- case get(mnesia_activity_state) of
- {?DEFAULT_ACCESS, Tid, Ts} ->
- delete_object(Tid, Ts, Tab, Val, LockKind);
- {Mod, Tid, Ts} ->
- Mod:delete_object(Tid, Ts, Tab, Val, LockKind);
- _ ->
- abort(no_transaction)
- end.
-
-delete_object(Tid, Ts, Tab, Val, LockKind)
- when atom(Tab), Tab /= schema, tuple(Val), size(Val) > 2 ->
- case element(1, Tid) of
- ets ->
- ?ets_match_delete(Tab, Val),
- ok;
- tid ->
- Store = Ts#tidstore.store,
- Oid = {Tab, element(2, Val)},
- case LockKind of
- write ->
- mnesia_locker:wlock(Tid, Store, Oid);
- sticky_write ->
- mnesia_locker:sticky_wlock(Tid, Store, Oid);
- _ ->
- abort({bad_type, Tab, LockKind})
- end,
- case val({Tab, setorbag}) of
- bag ->
- ?ets_match_delete(Store, {Oid, Val, '_'}),
- ?ets_insert(Store, {Oid, Val, delete_object});
- _ ->
- case ?ets_match_object(Store, {Oid, '_', write}) of
- [] ->
- ?ets_match_delete(Store, {Oid, Val, '_'}),
- ?ets_insert(Store, {Oid, Val, delete_object});
- _ ->
- ?ets_delete(Store, Oid),
- ?ets_insert(Store, {Oid, Oid, delete})
- end
- end,
- ok;
- Protocol ->
- do_dirty_delete_object(Protocol, Tab, Val)
- end;
-delete_object(_Tid, _Ts, Tab, _Key, _LockKind) ->
- abort({bad_type, Tab}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Access within an activity - read
-
-read({Tab, Key}) ->
- read(Tab, Key, read);
-read(Oid) ->
- abort({bad_type, Oid}).
-
-wread({Tab, Key}) ->
- read(Tab, Key, write);
-wread(Oid) ->
- abort({bad_type, Oid}).
-
-read(Tab, Key, LockKind) ->
- case get(mnesia_activity_state) of
- {?DEFAULT_ACCESS, Tid, Ts} ->
- read(Tid, Ts, Tab, Key, LockKind);
- {Mod, Tid, Ts} ->
- Mod:read(Tid, Ts, Tab, Key, LockKind);
- _ ->
- abort(no_transaction)
- end.
-
-read(Tid, Ts, Tab, Key, LockKind)
- when atom(Tab), Tab /= schema ->
- case element(1, Tid) of
- ets ->
- ?ets_lookup(Tab, Key);
- tid ->
- Store = Ts#tidstore.store,
- Oid = {Tab, Key},
- Objs =
- case LockKind of
- read ->
- mnesia_locker:rlock(Tid, Store, Oid);
- write ->
- mnesia_locker:rwlock(Tid, Store, Oid);
- sticky_write ->
- mnesia_locker:sticky_rwlock(Tid, Store, Oid);
- _ ->
- abort({bad_type, Tab, LockKind})
- end,
- add_written(?ets_lookup(Store, Oid), Tab, Objs);
- _Protocol ->
- dirty_read(Tab, Key)
- end;
-read(_Tid, _Ts, Tab, _Key, _LockKind) ->
- abort({bad_type, Tab}).
-
-%%%%%%%%%%%%%%%%%%%%%
-%% Iterators
-
-foldl(Fun, Acc, Tab) ->
- foldl(Fun, Acc, Tab, read).
-
-foldl(Fun, Acc, Tab, LockKind) when function(Fun) ->
- case get(mnesia_activity_state) of
- {?DEFAULT_ACCESS, Tid, Ts} ->
- foldl(Tid, Ts, Fun, Acc, Tab, LockKind);
- {Mod, Tid, Ts} ->
- Mod:foldl(Tid, Ts, Fun, Acc, Tab, LockKind);
- _ ->
- abort(no_transaction)
- end.
-
-foldl(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
- {Type, Prev} = init_iteration(ActivityId, Opaque, Tab, LockKind),
- Res = (catch do_foldl(ActivityId, Opaque, Tab, dirty_first(Tab), Fun, Acc, Type, Prev)),
- close_iteration(Res, Tab).
-
-do_foldl(A, O, Tab, '$end_of_table', Fun, RAcc, _Type, Stored) ->
- lists:foldl(fun(Key, Acc) ->
- lists:foldl(Fun, Acc, read(A, O, Tab, Key, read))
- end, RAcc, Stored);
-do_foldl(A, O, Tab, Key, Fun, Acc, ordered_set, [H | Stored]) when H == Key ->
- NewAcc = lists:foldl(Fun, Acc, read(A, O, Tab, Key, read)),
- do_foldl(A, O, Tab, dirty_next(Tab, Key), Fun, NewAcc, ordered_set, Stored);
-do_foldl(A, O, Tab, Key, Fun, Acc, ordered_set, [H | Stored]) when H < Key ->
- NewAcc = lists:foldl(Fun, Acc, read(A, O, Tab, H, read)),
- do_foldl(A, O, Tab, Key, Fun, NewAcc, ordered_set, Stored);
-do_foldl(A, O, Tab, Key, Fun, Acc, ordered_set, [H | Stored]) when H > Key ->
- NewAcc = lists:foldl(Fun, Acc, read(A, O, Tab, Key, read)),
- do_foldl(A, O, Tab, dirty_next(Tab, Key), Fun, NewAcc, ordered_set, [H |Stored]);
-do_foldl(A, O, Tab, Key, Fun, Acc, Type, Stored) -> %% Type is set or bag
- NewAcc = lists:foldl(Fun, Acc, read(A, O, Tab, Key, read)),
- NewStored = ordsets:del_element(Key, Stored),
- do_foldl(A, O, Tab, dirty_next(Tab, Key), Fun, NewAcc, Type, NewStored).
-
-foldr(Fun, Acc, Tab) ->
- foldr(Fun, Acc, Tab, read).
-foldr(Fun, Acc, Tab, LockKind) when function(Fun) ->
- case get(mnesia_activity_state) of
- {?DEFAULT_ACCESS, Tid, Ts} ->
- foldr(Tid, Ts, Fun, Acc, Tab, LockKind);
- {Mod, Tid, Ts} ->
- Mod:foldr(Tid, Ts, Fun, Acc, Tab, LockKind);
- _ ->
- abort(no_transaction)
- end.
-
-foldr(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
- {Type, TempPrev} = init_iteration(ActivityId, Opaque, Tab, LockKind),
- Prev =
- if
- Type == ordered_set ->
- lists:reverse(TempPrev);
- true -> %% Order doesn't matter for set and bag
- TempPrev %% Keep the order so we can use ordsets:del_element
- end,
- Res = (catch do_foldr(ActivityId, Opaque, Tab, dirty_last(Tab), Fun, Acc, Type, Prev)),
- close_iteration(Res, Tab).
-
-do_foldr(A, O, Tab, '$end_of_table', Fun, RAcc, _Type, Stored) ->
- lists:foldl(fun(Key, Acc) ->
- lists:foldl(Fun, Acc, read(A, O, Tab, Key, read))
- end, RAcc, Stored);
-do_foldr(A, O, Tab, Key, Fun, Acc, ordered_set, [H | Stored]) when H == Key ->
- NewAcc = lists:foldl(Fun, Acc, read(A, O, Tab, Key, read)),
- do_foldr(A, O, Tab, dirty_prev(Tab, Key), Fun, NewAcc, ordered_set, Stored);
-do_foldr(A, O, Tab, Key, Fun, Acc, ordered_set, [H | Stored]) when H > Key ->
- NewAcc = lists:foldl(Fun, Acc, read(A, O, Tab, H, read)),
- do_foldr(A, O, Tab, Key, Fun, NewAcc, ordered_set, Stored);
-do_foldr(A, O, Tab, Key, Fun, Acc, ordered_set, [H | Stored]) when H < Key ->
- NewAcc = lists:foldl(Fun, Acc, read(A, O, Tab, Key, read)),
- do_foldr(A, O, Tab, dirty_prev(Tab, Key), Fun, NewAcc, ordered_set, [H |Stored]);
-do_foldr(A, O, Tab, Key, Fun, Acc, Type, Stored) -> %% Type is set or bag
- NewAcc = lists:foldl(Fun, Acc, read(A, O, Tab, Key, read)),
- NewStored = ordsets:del_element(Key, Stored),
- do_foldr(A, O, Tab, dirty_prev(Tab, Key), Fun, NewAcc, Type, NewStored).
-
-init_iteration(ActivityId, Opaque, Tab, LockKind) ->
- lock(ActivityId, Opaque, {table, Tab}, LockKind),
- Type = val({Tab, setorbag}),
- Previous = add_previous(ActivityId, Opaque, Type, Tab),
- St = val({Tab, storage_type}),
- if
- St == unknown ->
- ignore;
- true ->
- mnesia_lib:db_fixtable(St, Tab, true)
- end,
- {Type, Previous}.
-
-close_iteration(Res, Tab) ->
- case val({Tab, storage_type}) of
- unknown ->
- ignore;
- St ->
- mnesia_lib:db_fixtable(St, Tab, false)
- end,
- case Res of
- {'EXIT', {aborted, What}} ->
- abort(What);
- {'EXIT', What} ->
- abort(What);
- _ ->
- Res
- end.
-
-add_previous(_ActivityId, non_transaction, _Type, _Tab) ->
- [];
-add_previous(_Tid, Ts, _Type, Tab) ->
- Previous = ?ets_match(Ts#tidstore.store, {{Tab, '$1'}, '_', write}),
- lists:sort(lists:concat(Previous)).
-
-%% This routine fixes up the return value from read/1 so that
-%% it is correct with respect to what this particular transaction
-%% has already written, deleted .... etc
-
-add_written([], _Tab, Objs) ->
- Objs; % standard normal fast case
-add_written(Written, Tab, Objs) ->
- case val({Tab, setorbag}) of
- bag ->
- add_written_to_bag(Written, Objs, []);
- _ ->
- add_written_to_set(Written)
- end.
-
-add_written_to_set(Ws) ->
- case lists:last(Ws) of
- {_, _, delete} -> [];
- {_, Val, write} -> [Val];
- {_, _, delete_object} -> []
- end.
-
-add_written_to_bag([{_, Val, write} | Tail], Objs, Ack) ->
- add_written_to_bag(Tail, lists:delete(Val, Objs), [Val | Ack]);
-add_written_to_bag([], Objs, Ack) ->
- Objs ++ lists:reverse(Ack); %% Oldest write first as in ets
-add_written_to_bag([{_, _ , delete} | Tail], _Objs, _Ack) ->
- %% This transaction just deleted all objects
- %% with this key
- add_written_to_bag(Tail, [], []);
-add_written_to_bag([{_, Val, delete_object} | Tail], Objs, Ack) ->
- add_written_to_bag(Tail, lists:delete(Val, Objs), lists:delete(Val, Ack)).
-
-match_object(Pat) when tuple(Pat), size(Pat) > 2 ->
- Tab = element(1, Pat),
- match_object(Tab, Pat, read);
-match_object(Pat) ->
- abort({bad_type, Pat}).
-
-match_object(Tab, Pat, LockKind) ->
- case get(mnesia_activity_state) of
- {?DEFAULT_ACCESS, Tid, Ts} ->
- match_object(Tid, Ts, Tab, Pat, LockKind);
- {Mod, Tid, Ts} ->
- Mod:match_object(Tid, Ts, Tab, Pat, LockKind);
- _ ->
- abort(no_transaction)
- end.
-
-match_object(Tid, Ts, Tab, Pat, LockKind)
- when atom(Tab), Tab /= schema, tuple(Pat), size(Pat) > 2 ->
- case element(1, Tid) of
- ets ->
- mnesia_lib:db_match_object(ram_copies, Tab, Pat);
- tid ->
- Key = element(2, Pat),
- case has_var(Key) of
- false -> lock_record(Tid, Ts, Tab, Key, LockKind);
- true -> lock_table(Tid, Ts, Tab, LockKind)
- end,
- Objs = dirty_match_object(Tab, Pat),
- add_written_match(Ts#tidstore.store, Pat, Tab, Objs);
- _Protocol ->
- dirty_match_object(Tab, Pat)
- end;
-match_object(_Tid, _Ts, Tab, Pat, _LockKind) ->
- abort({bad_type, Tab, Pat}).
-
-add_written_match(S, Pat, Tab, Objs) ->
- Ops = find_ops(S, Tab, Pat),
- add_match(Ops, Objs, val({Tab, setorbag})).
-
-find_ops(S, Tab, Pat) ->
- GetWritten = [{{{Tab, '_'}, Pat, write}, [], ['$_']},
- {{{Tab, '_'}, '_', delete}, [], ['$_']},
- {{{Tab, '_'}, Pat, delete_object}, [], ['$_']}],
- ets:select(S, GetWritten).
-
-add_match([], Objs, _Type) ->
- Objs;
-add_match(Written, Objs, ordered_set) ->
- %% Must use keysort which is stable
- add_ordered_match(lists:keysort(1,Written), Objs, []);
-add_match([{Oid, _, delete}|R], Objs, Type) ->
- add_match(R, deloid(Oid, Objs), Type);
-add_match([{_Oid, Val, delete_object}|R], Objs, Type) ->
- add_match(R, lists:delete(Val, Objs), Type);
-add_match([{_Oid, Val, write}|R], Objs, bag) ->
- add_match(R, [Val | lists:delete(Val, Objs)], bag);
-add_match([{Oid, Val, write}|R], Objs, set) ->
- add_match(R, [Val | deloid(Oid,Objs)],set).
-
-%% For ordered_set only !!
-add_ordered_match(Written = [{{_, Key}, _, _}|_], [Obj|Objs], Acc)
- when Key > element(2, Obj) ->
- add_ordered_match(Written, Objs, [Obj|Acc]);
-add_ordered_match([{{_, Key}, Val, write}|Rest], Objs =[Obj|_], Acc)
- when Key < element(2, Obj) ->
- add_ordered_match(Rest, [Val|Objs],Acc);
-add_ordered_match([{{_, Key}, _, _DelOP}|Rest], Objs =[Obj|_], Acc)
- when Key < element(2, Obj) ->
- add_ordered_match(Rest,Objs,Acc);
-%% Greater than last object
-add_ordered_match([{_, Val, write}|Rest], [], Acc) ->
- add_ordered_match(Rest, [Val], Acc);
-add_ordered_match([_|Rest], [], Acc) ->
- add_ordered_match(Rest, [], Acc);
-%% Keys are equal from here
-add_ordered_match([{_, Val, write}|Rest], [_Obj|Objs], Acc) ->
- add_ordered_match(Rest, [Val|Objs], Acc);
-add_ordered_match([{_, _Val, delete}|Rest], [_Obj|Objs], Acc) ->
- add_ordered_match(Rest, Objs, Acc);
-add_ordered_match([{_, Val, delete_object}|Rest], [Val|Objs], Acc) ->
- add_ordered_match(Rest, Objs, Acc);
-add_ordered_match([{_, _, delete_object}|Rest], Objs, Acc) ->
- add_ordered_match(Rest, Objs, Acc);
-add_ordered_match([], Objs, Acc) ->
- lists:reverse(Acc, Objs).
-
-
-%%%%%%%%%%%%%%%%%%
-% select
-
-select(Tab, Pat) ->
- select(Tab, Pat, read).
-select(Tab, Pat, LockKind)
- when atom(Tab), Tab /= schema, list(Pat) ->
- case get(mnesia_activity_state) of
- {?DEFAULT_ACCESS, Tid, Ts} ->
- select(Tid, Ts, Tab, Pat, LockKind);
- {Mod, Tid, Ts} ->
- Mod:select(Tid, Ts, Tab, Pat, LockKind);
- _ ->
- abort(no_transaction)
- end;
-select(Tab, Pat, _Lock) ->
- abort({badarg, Tab, Pat}).
-
-select(Tid, Ts, Tab, Spec, LockKind) ->
- SelectFun = fun(FixedSpec) -> dirty_select(Tab, FixedSpec) end,
- fun_select(Tid, Ts, Tab, Spec, LockKind, Tab, SelectFun).
-
-fun_select(Tid, Ts, Tab, Spec, LockKind, TabPat, SelectFun) ->
- case element(1, Tid) of
- ets ->
- mnesia_lib:db_select(ram_copies, Tab, Spec);
- tid ->
- Store = Ts#tidstore.store,
- Written = ?ets_match_object(Store, {{TabPat, '_'}, '_', '_'}),
- %% Avoid table lock if possible
- case Spec of
- [{HeadPat,_, _}] when tuple(HeadPat), size(HeadPat) > 2 ->
- Key = element(2, HeadPat),
- case has_var(Key) of
- false -> lock_record(Tid, Ts, Tab, Key, LockKind);
- true -> lock_table(Tid, Ts, Tab, LockKind)
- end;
- _ ->
- lock_table(Tid, Ts, Tab, LockKind)
- end,
- case Written of
- [] ->
- %% Nothing changed in the table during this transaction,
- %% Simple case get results from [d]ets
- SelectFun(Spec);
- _ ->
- %% Hard (slow case) records added or deleted earlier
- %% in the transaction, have to cope with that.
- Type = val({Tab, setorbag}),
- FixedSpec = get_record_pattern(Spec),
- TabRecs = SelectFun(FixedSpec),
- FixedRes = add_match(Written, TabRecs, Type),
- CMS = ets:match_spec_compile(Spec),
-% case Type of
-% ordered_set ->
-% ets:match_spec_run(lists:sort(FixedRes), CMS);
-% _ ->
-% ets:match_spec_run(FixedRes, CMS)
-% end
- ets:match_spec_run(FixedRes, CMS)
- end;
- _Protocol ->
- SelectFun(Spec)
- end.
-
-get_record_pattern([]) ->
- [];
-get_record_pattern([{M,C,_B}|R]) ->
- [{M,C,['$_']} | get_record_pattern(R)].
-
-deloid(_Oid, []) ->
- [];
-deloid({Tab, Key}, [H | T]) when element(2, H) == Key ->
- deloid({Tab, Key}, T);
-deloid(Oid, [H | T]) ->
- [H | deloid(Oid, T)].
-
-all_keys(Tab) ->
- case get(mnesia_activity_state) of
- {?DEFAULT_ACCESS, Tid, Ts} ->
- all_keys(Tid, Ts, Tab, read);
- {Mod, Tid, Ts} ->
- Mod:all_keys(Tid, Ts, Tab, read);
- _ ->
- abort(no_transaction)
- end.
-
-all_keys(Tid, Ts, Tab, LockKind)
- when atom(Tab), Tab /= schema ->
- Pat0 = val({Tab, wild_pattern}),
- Pat = setelement(2, Pat0, '$1'),
- Keys = select(Tid, Ts, Tab, [{Pat, [], ['$1']}], LockKind),
- case val({Tab, setorbag}) of
- bag ->
- mnesia_lib:uniq(Keys);
- _ ->
- Keys
- end;
-all_keys(_Tid, _Ts, Tab, _LockKind) ->
- abort({bad_type, Tab}).
-
-index_match_object(Pat, Attr) when tuple(Pat), size(Pat) > 2 ->
- Tab = element(1, Pat),
- index_match_object(Tab, Pat, Attr, read);
-index_match_object(Pat, _Attr) ->
- abort({bad_type, Pat}).
-
-index_match_object(Tab, Pat, Attr, LockKind) ->
- case get(mnesia_activity_state) of
- {?DEFAULT_ACCESS, Tid, Ts} ->
- index_match_object(Tid, Ts, Tab, Pat, Attr, LockKind);
- {Mod, Tid, Ts} ->
- Mod:index_match_object(Tid, Ts, Tab, Pat, Attr, LockKind);
- _ ->
- abort(no_transaction)
- end.
-
-index_match_object(Tid, Ts, Tab, Pat, Attr, LockKind)
- when atom(Tab), Tab /= schema, tuple(Pat), size(Pat) > 2 ->
- case element(1, Tid) of
- ets ->
- dirty_index_match_object(Tab, Pat, Attr); % Should be optimized?
- tid ->
- case mnesia_schema:attr_tab_to_pos(Tab, Attr) of
- Pos when Pos =< size(Pat) ->
- case LockKind of
- read ->
- Store = Ts#tidstore.store,
- mnesia_locker:rlock_table(Tid, Store, Tab),
- Objs = dirty_index_match_object(Tab, Pat, Attr),
- add_written_match(Store, Pat, Tab, Objs);
- _ ->
- abort({bad_type, Tab, LockKind})
- end;
- BadPos ->
- abort({bad_type, Tab, BadPos})
- end;
- _Protocol ->
- dirty_index_match_object(Tab, Pat, Attr)
- end;
-index_match_object(_Tid, _Ts, Tab, Pat, _Attr, _LockKind) ->
- abort({bad_type, Tab, Pat}).
-
-index_read(Tab, Key, Attr) ->
- case get(mnesia_activity_state) of
- {?DEFAULT_ACCESS, Tid, Ts} ->
- index_read(Tid, Ts, Tab, Key, Attr, read);
- {Mod, Tid, Ts} ->
- Mod:index_read(Tid, Ts, Tab, Key, Attr, read);
- _ ->
- abort(no_transaction)
- end.
-
-index_read(Tid, Ts, Tab, Key, Attr, LockKind)
- when atom(Tab), Tab /= schema ->
- case element(1, Tid) of
- ets ->
- dirty_index_read(Tab, Key, Attr); % Should be optimized?
- tid ->
- Pos = mnesia_schema:attr_tab_to_pos(Tab, Attr),
- case LockKind of
- read ->
- case has_var(Key) of
- false ->
- Store = Ts#tidstore.store,
- Objs = mnesia_index:read(Tid, Store, Tab, Key, Pos),
- Pat = setelement(Pos, val({Tab, wild_pattern}), Key),
- add_written_match(Store, Pat, Tab, Objs);
- true ->
- abort({bad_type, Tab, Attr, Key})
- end;
- _ ->
- abort({bad_type, Tab, LockKind})
- end;
- _Protocol ->
- dirty_index_read(Tab, Key, Attr)
- end;
-index_read(_Tid, _Ts, Tab, _Key, _Attr, _LockKind) ->
- abort({bad_type, Tab}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Dirty access regardless of activities - updates
-
-dirty_write(Val) when tuple(Val), size(Val) > 2 ->
- Tab = element(1, Val),
- dirty_write(Tab, Val);
-dirty_write(Val) ->
- abort({bad_type, Val}).
-
-dirty_write(Tab, Val) ->
- do_dirty_write(async_dirty, Tab, Val).
-
-do_dirty_write(SyncMode, Tab, Val)
- when atom(Tab), Tab /= schema, tuple(Val), size(Val) > 2 ->
- case ?catch_val({Tab, record_validation}) of
- {RecName, Arity, _Type}
- when size(Val) == Arity, RecName == element(1, Val) ->
- Oid = {Tab, element(2, Val)},
- mnesia_tm:dirty(SyncMode, {Oid, Val, write});
- {'EXIT', _} ->
- abort({no_exists, Tab});
- _ ->
- abort({bad_type, Val})
- end;
-do_dirty_write(_SyncMode, Tab, Val) ->
- abort({bad_type, Tab, Val}).
-
-dirty_delete({Tab, Key}) ->
- dirty_delete(Tab, Key);
-dirty_delete(Oid) ->
- abort({bad_type, Oid}).
-
-dirty_delete(Tab, Key) ->
- do_dirty_delete(async_dirty, Tab, Key).
-
-do_dirty_delete(SyncMode, Tab, Key) when atom(Tab), Tab /= schema ->
- Oid = {Tab, Key},
- mnesia_tm:dirty(SyncMode, {Oid, Oid, delete});
-do_dirty_delete(_SyncMode, Tab, _Key) ->
- abort({bad_type, Tab}).
-
-dirty_delete_object(Val) when tuple(Val), size(Val) > 2 ->
- Tab = element(1, Val),
- dirty_delete_object(Tab, Val);
-dirty_delete_object(Val) ->
- abort({bad_type, Val}).
-
-dirty_delete_object(Tab, Val) ->
- do_dirty_delete_object(async_dirty, Tab, Val).
-
-do_dirty_delete_object(SyncMode, Tab, Val)
- when atom(Tab), Tab /= schema, tuple(Val), size(Val) > 2 ->
- Oid = {Tab, element(2, Val)},
- mnesia_tm:dirty(SyncMode, {Oid, Val, delete_object});
-do_dirty_delete_object(_SyncMode, Tab, Val) ->
- abort({bad_type, Tab, Val}).
-
-%% A Counter is an Oid being {CounterTab, CounterName}
-
-dirty_update_counter({Tab, Key}, Incr) ->
- dirty_update_counter(Tab, Key, Incr);
-dirty_update_counter(Counter, _Incr) ->
- abort({bad_type, Counter}).
-
-dirty_update_counter(Tab, Key, Incr) ->
- do_dirty_update_counter(async_dirty, Tab, Key, Incr).
-
-do_dirty_update_counter(SyncMode, Tab, Key, Incr)
- when atom(Tab), Tab /= schema, integer(Incr) ->
- case ?catch_val({Tab, record_validation}) of
- {RecName, 3, set} ->
- Oid = {Tab, Key},
- mnesia_tm:dirty(SyncMode, {Oid, {RecName, Incr}, update_counter});
- _ ->
- abort({combine_error, Tab, update_counter})
- end;
-do_dirty_update_counter(_SyncMode, Tab, _Key, Incr) ->
- abort({bad_type, Tab, Incr}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Dirty access regardless of activities - read
-
-dirty_read({Tab, Key}) ->
- dirty_read(Tab, Key);
-dirty_read(Oid) ->
- abort({bad_type, Oid}).
-
-dirty_read(Tab, Key)
- when atom(Tab), Tab /= schema ->
-%% case catch ?ets_lookup(Tab, Key) of
-%% {'EXIT', _} ->
- %% Bad luck, we have to perform a real lookup
- dirty_rpc(Tab, mnesia_lib, db_get, [Tab, Key]);
-%% Val ->
-%% Val
-%% end;
-dirty_read(Tab, _Key) ->
- abort({bad_type, Tab}).
-
-dirty_match_object(Pat) when tuple(Pat), size(Pat) > 2 ->
- Tab = element(1, Pat),
- dirty_match_object(Tab, Pat);
-dirty_match_object(Pat) ->
- abort({bad_type, Pat}).
-
-dirty_match_object(Tab, Pat)
- when atom(Tab), Tab /= schema, tuple(Pat), size(Pat) > 2 ->
- dirty_rpc(Tab, ?MODULE, remote_dirty_match_object, [Tab, Pat]);
-dirty_match_object(Tab, Pat) ->
- abort({bad_type, Tab, Pat}).
-
-remote_dirty_match_object(Tab, Pat) ->
- Key = element(2, Pat),
- case has_var(Key) of
- false ->
- mnesia_lib:db_match_object(Tab, Pat);
- true ->
- PosList = val({Tab, index}),
- remote_dirty_match_object(Tab, Pat, PosList)
- end.
-
-remote_dirty_match_object(Tab, Pat, [Pos | Tail]) when Pos =< size(Pat) ->
- IxKey = element(Pos, Pat),
- case has_var(IxKey) of
- false ->
- mnesia_index:dirty_match_object(Tab, Pat, Pos);
- true ->
- remote_dirty_match_object(Tab, Pat, Tail)
- end;
-remote_dirty_match_object(Tab, Pat, []) ->
- mnesia_lib:db_match_object(Tab, Pat);
-remote_dirty_match_object(Tab, Pat, _PosList) ->
- abort({bad_type, Tab, Pat}).
-
-dirty_select(Tab, Spec) when atom(Tab), Tab /= schema, list(Spec) ->
- dirty_rpc(Tab, ?MODULE, remote_dirty_select, [Tab, Spec]);
-dirty_select(Tab, Spec) ->
- abort({bad_type, Tab, Spec}).
-
-remote_dirty_select(Tab, Spec) ->
- case Spec of
- [{HeadPat, _, _}] when tuple(HeadPat), size(HeadPat) > 2 ->
- Key = element(2, HeadPat),
- case has_var(Key) of
- false ->
- mnesia_lib:db_select(Tab, Spec);
- true ->
- PosList = val({Tab, index}),
- remote_dirty_select(Tab, Spec, PosList)
- end;
- _ ->
- mnesia_lib:db_select(Tab, Spec)
- end.
-
-remote_dirty_select(Tab, [{HeadPat,_, _}] = Spec, [Pos | Tail])
- when tuple(HeadPat), size(HeadPat) > 2, Pos =< size(Spec) ->
- Key = element(Pos, HeadPat),
- case has_var(Key) of
- false ->
- Recs = mnesia_index:dirty_select(Tab, Spec, Pos),
- %% Returns the records without applying the match spec
- %% The actual filtering is handled by the caller
- CMS = ets:match_spec_compile(Spec),
- case val({Tab, setorbag}) of
- ordered_set ->
- ets:match_spec_run(lists:sort(Recs), CMS);
- _ ->
- ets:match_spec_run(Recs, CMS)
- end;
- true ->
- remote_dirty_select(Tab, Spec, Tail)
- end;
-remote_dirty_select(Tab, Spec, _) ->
- mnesia_lib:db_select(Tab, Spec).
-
-dirty_all_keys(Tab) when atom(Tab), Tab /= schema ->
- case ?catch_val({Tab, wild_pattern}) of
- {'EXIT', _} ->
- abort({no_exists, Tab});
- Pat0 ->
- Pat = setelement(2, Pat0, '$1'),
- Keys = dirty_select(Tab, [{Pat, [], ['$1']}]),
- case val({Tab, setorbag}) of
- bag -> mnesia_lib:uniq(Keys);
- _ -> Keys
- end
- end;
-dirty_all_keys(Tab) ->
- abort({bad_type, Tab}).
-
-dirty_index_match_object(Pat, Attr) when tuple(Pat), size(Pat) > 2 ->
- Tab = element(1, Pat),
- dirty_index_match_object(Tab, Pat, Attr);
-dirty_index_match_object(Pat, _Attr) ->
- abort({bad_type, Pat}).
-
-dirty_index_match_object(Tab, Pat, Attr)
- when atom(Tab), Tab /= schema, tuple(Pat), size(Pat) > 2 ->
- case mnesia_schema:attr_tab_to_pos(Tab, Attr) of
- Pos when Pos =< size(Pat) ->
- case has_var(element(2, Pat)) of
- false ->
- dirty_match_object(Tab, Pat);
- true ->
- Elem = element(Pos, Pat),
- case has_var(Elem) of
- false ->
- dirty_rpc(Tab, mnesia_index, dirty_match_object,
- [Tab, Pat, Pos]);
- true ->
- abort({bad_type, Tab, Attr, Elem})
- end
- end;
- BadPos ->
- abort({bad_type, Tab, BadPos})
- end;
-dirty_index_match_object(Tab, Pat, _Attr) ->
- abort({bad_type, Tab, Pat}).
-
-dirty_index_read(Tab, Key, Attr) when atom(Tab), Tab /= schema ->
- Pos = mnesia_schema:attr_tab_to_pos(Tab, Attr),
- case has_var(Key) of
- false ->
- mnesia_index:dirty_read(Tab, Key, Pos);
- true ->
- abort({bad_type, Tab, Attr, Key})
- end;
-dirty_index_read(Tab, _Key, _Attr) ->
- abort({bad_type, Tab}).
-
-dirty_slot(Tab, Slot) when atom(Tab), Tab /= schema, integer(Slot) ->
- dirty_rpc(Tab, mnesia_lib, db_slot, [Tab, Slot]);
-dirty_slot(Tab, Slot) ->
- abort({bad_type, Tab, Slot}).
-
-dirty_first(Tab) when atom(Tab), Tab /= schema ->
- dirty_rpc(Tab, mnesia_lib, db_first, [Tab]);
-dirty_first(Tab) ->
- abort({bad_type, Tab}).
-
-dirty_last(Tab) when atom(Tab), Tab /= schema ->
- dirty_rpc(Tab, mnesia_lib, db_last, [Tab]);
-dirty_last(Tab) ->
- abort({bad_type, Tab}).
-
-dirty_next(Tab, Key) when atom(Tab), Tab /= schema ->
- dirty_rpc(Tab, mnesia_lib, db_next_key, [Tab, Key]);
-dirty_next(Tab, _Key) ->
- abort({bad_type, Tab}).
-
-dirty_prev(Tab, Key) when atom(Tab), Tab /= schema ->
- dirty_rpc(Tab, mnesia_lib, db_prev_key, [Tab, Key]);
-dirty_prev(Tab, _Key) ->
- abort({bad_type, Tab}).
-
-
-dirty_rpc(Tab, M, F, Args) ->
- Node = val({Tab, where_to_read}),
- do_dirty_rpc(Tab, Node, M, F, Args).
-
-do_dirty_rpc(_Tab, nowhere, _, _, Args) ->
- mnesia:abort({no_exists, Args});
-do_dirty_rpc(Tab, Node, M, F, Args) ->
- case rpc:call(Node, M, F, Args) of
- {badrpc,{'EXIT', {undef, [{ M, F, _} | _]}}}
- when M == ?MODULE, F == remote_dirty_select ->
- %% Oops, the other node has not been upgraded
- %% to 4.0.3 yet. Lets do it the old way.
- %% Remove this in next release.
- do_dirty_rpc(Tab, Node, mnesia_lib, db_select, Args);
- {badrpc, Reason} ->
- erlang:yield(), %% Do not be too eager
- case mnesia_controller:call({check_w2r, Node, Tab}) of % Sync
- NewNode when NewNode == Node ->
- ErrorTag = mnesia_lib:dirty_rpc_error_tag(Reason),
- mnesia:abort({ErrorTag, Args});
- NewNode ->
- case get(mnesia_activity_state) of
- {_Mod, Tid, _Ts} when record(Tid, tid) ->
- %% In order to perform a consistent
- %% retry of a transaction we need
- %% to acquire the lock on the NewNode.
- %% In this context we do neither know
- %% the kind or granularity of the lock.
- %% --> Abort the transaction
- mnesia:abort({node_not_running, Node});
- _ ->
- %% Splendid! A dirty retry is safe
- %% 'Node' probably went down now
- %% Let mnesia_controller get broken link message first
- do_dirty_rpc(Tab, NewNode, M, F, Args)
- end
- end;
- Other ->
- Other
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Info
-
-%% Info about one table
-table_info(Tab, Item) ->
- case get(mnesia_activity_state) of
- undefined ->
- any_table_info(Tab, Item);
- {?DEFAULT_ACCESS, _Tid, _Ts} ->
- any_table_info(Tab, Item);
- {Mod, Tid, Ts} ->
- Mod:table_info(Tid, Ts, Tab, Item);
- _ ->
- abort(no_transaction)
- end.
-
-table_info(_Tid, _Ts, Tab, Item) ->
- any_table_info(Tab, Item).
-
-
-any_table_info(Tab, Item) when atom(Tab) ->
- case Item of
- master_nodes ->
- mnesia_recover:get_master_nodes(Tab);
-% checkpoints ->
-% case ?catch_val({Tab, commit_work}) of
-% [{checkpoints, List} | _] -> List;
-% No_chk when list(No_chk) -> [];
-% Else -> info_reply(Else, Tab, Item)
-% end;
- size ->
- raw_table_info(Tab, Item);
- memory ->
- raw_table_info(Tab, Item);
- type ->
- case ?catch_val({Tab, setorbag}) of
- {'EXIT', _} ->
- bad_info_reply(Tab, Item);
- Val ->
- Val
- end;
- all ->
- case mnesia_schema:get_table_properties(Tab) of
- [] ->
- abort({no_exists, Tab, Item});
- Props ->
- lists:map(fun({setorbag, Type}) -> {type, Type};
- (Prop) -> Prop end,
- Props)
- end;
- _ ->
- case ?catch_val({Tab, Item}) of
- {'EXIT', _} ->
- bad_info_reply(Tab, Item);
- Val ->
- Val
- end
- end;
-any_table_info(Tab, _Item) ->
- abort({bad_type, Tab}).
-
-raw_table_info(Tab, Item) ->
- case ?catch_val({Tab, storage_type}) of
- ram_copies ->
- info_reply(catch ?ets_info(Tab, Item), Tab, Item);
- disc_copies ->
- info_reply(catch ?ets_info(Tab, Item), Tab, Item);
- disc_only_copies ->
- info_reply(catch dets:info(Tab, Item), Tab, Item);
- unknown ->
- bad_info_reply(Tab, Item);
- {'EXIT', _} ->
- bad_info_reply(Tab, Item)
- end.
-
-info_reply({'EXIT', _Reason}, Tab, Item) ->
- bad_info_reply(Tab, Item);
-info_reply({error, _Reason}, Tab, Item) ->
- bad_info_reply(Tab, Item);
-info_reply(Val, _Tab, _Item) ->
- Val.
-
-bad_info_reply(_Tab, size) -> 0;
-bad_info_reply(_Tab, memory) -> 0;
-bad_info_reply(Tab, Item) -> abort({no_exists, Tab, Item}).
-
-%% Raw info about all tables
-schema() ->
- mnesia_schema:info().
-
-%% Raw info about one tables
-schema(Tab) ->
- mnesia_schema:info(Tab).
-
-error_description(Err) ->
- mnesia_lib:error_desc(Err).
-
-info() ->
- case mnesia_lib:is_running() of
- yes ->
- TmInfo = mnesia_tm:get_info(10000),
- Held = system_info(held_locks),
- Queued = system_info(lock_queue),
-
- io:format("---> Processes holding locks <--- ~n", []),
- lists:foreach(fun(L) -> io:format("Lock: ~p~n", [L]) end,
- Held),
-
- io:format( "---> Processes waiting for locks <--- ~n", []),
- lists:foreach(fun({Oid, Op, _Pid, Tid, OwnerTid}) ->
- io:format("Tid ~p waits for ~p lock "
- "on oid ~p owned by ~p ~n",
- [Tid, Op, Oid, OwnerTid])
- end, Queued),
- mnesia_tm:display_info(group_leader(), TmInfo),
-
- Pat = {'_', unclear, '_'},
- Uncertain = ets:match_object(mnesia_decision, Pat),
-
- io:format( "---> Uncertain transactions <--- ~n", []),
- lists:foreach(fun({Tid, _, Nodes}) ->
- io:format("Tid ~w waits for decision "
- "from ~w~n",
- [Tid, Nodes])
- end, Uncertain),
-
- mnesia_controller:info(),
- display_system_info(Held, Queued, TmInfo, Uncertain);
- _ ->
- mini_info()
- end,
- ok.
-
-mini_info() ->
- io:format("===> System info in version ~p, debug level = ~p <===~n",
- [system_info(version), system_info(debug)]),
- Not =
- case system_info(use_dir) of
- true -> "";
- false -> "NOT "
- end,
-
- io:format("~w. Directory ~p is ~sused.~n",
- [system_info(schema_location), system_info(directory), Not]),
- io:format("use fallback at restart = ~w~n",
- [system_info(fallback_activated)]),
- Running = system_info(running_db_nodes),
- io:format("running db nodes = ~w~n", [Running]),
- All = mnesia_lib:all_nodes(),
- io:format("stopped db nodes = ~w ~n", [All -- Running]).
-
-display_system_info(Held, Queued, TmInfo, Uncertain) ->
- mini_info(),
- display_tab_info(),
- S = fun(Items) -> [system_info(I) || I <- Items] end,
-
- io:format("~w transactions committed, ~w aborted, "
- "~w restarted, ~w logged to disc~n",
- S([transaction_commits, transaction_failures,
- transaction_restarts, transaction_log_writes])),
-
- {Active, Pending} =
- case TmInfo of
- {timeout, _} -> {infinity, infinity};
- {info, P, A} -> {length(A), length(P)}
- end,
- io:format("~w held locks, ~w in queue; "
- "~w local transactions, ~w remote~n",
- [length(Held), length(Queued), Active, Pending]),
-
- Ufold = fun({_, _, Ns}, {C, Old}) ->
- New = [N || N <- Ns, not lists:member(N, Old)],
- {C + 1, New ++ Old}
- end,
- {Ucount, Unodes} = lists:foldl(Ufold, {0, []}, Uncertain),
- io:format("~w transactions waits for other nodes: ~p~n",
- [Ucount, Unodes]).
-
-display_tab_info() ->
- MasterTabs = mnesia_recover:get_master_node_tables(),
- io:format("master node tables = ~p~n", [lists:sort(MasterTabs)]),
-
- Tabs = system_info(tables),
-
- {Unknown, Ram, Disc, DiscOnly} =
- lists:foldl(fun storage_count/2, {[], [], [], []}, Tabs),
-
- io:format("remote = ~p~n", [lists:sort(Unknown)]),
- io:format("ram_copies = ~p~n", [lists:sort(Ram)]),
- io:format("disc_copies = ~p~n", [lists:sort(Disc)]),
- io:format("disc_only_copies = ~p~n", [lists:sort(DiscOnly)]),
-
- Rfoldl = fun(T, Acc) ->
- Rpat =
- case val({T, access_mode}) of
- read_only ->
- lists:sort([{A, read_only} || A <- val({T, active_replicas})]);
- read_write ->
- table_info(T, where_to_commit)
- end,
- case lists:keysearch(Rpat, 1, Acc) of
- {value, {_Rpat, Rtabs}} ->
- lists:keyreplace(Rpat, 1, Acc, {Rpat, [T | Rtabs]});
- false ->
- [{Rpat, [T]} | Acc]
- end
- end,
- Repl = lists:foldl(Rfoldl, [], Tabs),
- Rdisp = fun({Rpat, Rtabs}) -> io:format("~p = ~p~n", [Rpat, Rtabs]) end,
- lists:foreach(Rdisp, lists:sort(Repl)).
-
-storage_count(T, {U, R, D, DO}) ->
- case table_info(T, storage_type) of
- unknown -> {[T | U], R, D, DO};
- ram_copies -> {U, [T | R], D, DO};
- disc_copies -> {U, R, [T | D], DO};
- disc_only_copies -> {U, R, D, [T | DO]}
- end.
-
-system_info(Item) ->
- case catch system_info2(Item) of
- {'EXIT',Error} -> abort(Error);
- Other -> Other
- end.
-
-system_info2(all) ->
- Items = system_info_items(mnesia_lib:is_running()),
- [{I, system_info(I)} || I <- Items];
-
-system_info2(db_nodes) ->
- DiscNs = ?catch_val({schema, disc_copies}),
- RamNs = ?catch_val({schema, ram_copies}),
- if
- list(DiscNs), list(RamNs) ->
- DiscNs ++ RamNs;
- true ->
- case mnesia_schema:read_nodes() of
- {ok, Nodes} -> Nodes;
- {error,Reason} -> exit(Reason)
- end
- end;
-system_info2(running_db_nodes) ->
- case ?catch_val({current, db_nodes}) of
- {'EXIT',_} ->
- %% Ensure that we access the intended Mnesia
- %% directory. This function may not be called
- %% during startup since it will cause the
- %% application_controller to get into deadlock
- load_mnesia_or_abort(),
- mnesia_lib:running_nodes();
- Other ->
- Other
- end;
-
-system_info2(extra_db_nodes) ->
- case ?catch_val(extra_db_nodes) of
- {'EXIT',_} ->
- %% Ensure that we access the intended Mnesia
- %% directory. This function may not be called
- %% during startup since it will cause the
- %% application_controller to get into deadlock
- load_mnesia_or_abort(),
- mnesia_monitor:get_env(extra_db_nodes);
- Other ->
- Other
- end;
-
-system_info2(directory) ->
- case ?catch_val(directory) of
- {'EXIT',_} ->
- %% Ensure that we access the intended Mnesia
- %% directory. This function may not be called
- %% during startup since it will cause the
- %% application_controller to get into deadlock
- load_mnesia_or_abort(),
- mnesia_monitor:get_env(dir);
- Other ->
- Other
- end;
-
-system_info2(use_dir) ->
- case ?catch_val(use_dir) of
- {'EXIT',_} ->
- %% Ensure that we access the intended Mnesia
- %% directory. This function may not be called
- %% during startup since it will cause the
- %% application_controller to get into deadlock
- load_mnesia_or_abort(),
- mnesia_monitor:use_dir();
- Other ->
- Other
- end;
-
-system_info2(schema_location) ->
- case ?catch_val(schema_location) of
- {'EXIT',_} ->
- %% Ensure that we access the intended Mnesia
- %% directory. This function may not be called
- %% during startup since it will cause the
- %% application_controller to get into deadlock
- load_mnesia_or_abort(),
- mnesia_monitor:get_env(schema_location);
- Other ->
- Other
- end;
-
-system_info2(fallback_activated) ->
- case ?catch_val(fallback_activated) of
- {'EXIT',_} ->
- %% Ensure that we access the intended Mnesia
- %% directory. This function may not be called
- %% during startup since it will cause the
- %% application_controller to get into deadlock
- load_mnesia_or_abort(),
- mnesia_bup:fallback_exists();
- Other ->
- Other
- end;
-
-system_info2(version) ->
- case ?catch_val(version) of
- {'EXIT', _} ->
- Apps = application:loaded_applications(),
- case lists:keysearch(?APPLICATION, 1, Apps) of
- {value, {_Name, _Desc, Version}} ->
- Version;
- false ->
- %% Ensure that it does not match
- {mnesia_not_loaded, node(), now()}
- end;
- Version ->
- Version
- end;
-
-system_info2(access_module) -> mnesia_monitor:get_env(access_module);
-system_info2(auto_repair) -> mnesia_monitor:get_env(auto_repair);
-system_info2(is_running) -> mnesia_lib:is_running();
-system_info2(backup_module) -> mnesia_monitor:get_env(backup_module);
-system_info2(event_module) -> mnesia_monitor:get_env(event_module);
-system_info2(debug) -> mnesia_monitor:get_env(debug);
-system_info2(dump_log_load_regulation) -> mnesia_monitor:get_env(dump_log_load_regulation);
-system_info2(dump_log_write_threshold) -> mnesia_monitor:get_env(dump_log_write_threshold);
-system_info2(dump_log_time_threshold) -> mnesia_monitor:get_env(dump_log_time_threshold);
-system_info2(dump_log_update_in_place) ->
- mnesia_monitor:get_env(dump_log_update_in_place);
-system_info2(dump_log_update_in_place) ->
- mnesia_monitor:get_env(dump_log_update_in_place);
-system_info2(max_wait_for_decision) -> mnesia_monitor:get_env(max_wait_for_decision);
-system_info2(embedded_mnemosyne) -> mnesia_monitor:get_env(embedded_mnemosyne);
-system_info2(ignore_fallback_at_startup) -> mnesia_monitor:get_env(ignore_fallback_at_startup);
-system_info2(fallback_error_function) -> mnesia_monitor:get_env(fallback_error_function);
-system_info2(log_version) -> mnesia_log:version();
-system_info2(protocol_version) -> mnesia_monitor:protocol_version();
-system_info2(schema_version) -> mnesia_schema:version(); %backward compatibility
-system_info2(tables) -> val({schema, tables});
-system_info2(local_tables) -> val({schema, local_tables});
-system_info2(master_node_tables) -> mnesia_recover:get_master_node_tables();
-system_info2(subscribers) -> mnesia_subscr:subscribers();
-system_info2(checkpoints) -> mnesia_checkpoint:checkpoints();
-system_info2(held_locks) -> mnesia_locker:get_held_locks();
-system_info2(lock_queue) -> mnesia_locker:get_lock_queue();
-system_info2(transactions) -> mnesia_tm:get_transactions();
-system_info2(transaction_failures) -> mnesia_lib:read_counter(trans_failures);
-system_info2(transaction_commits) -> mnesia_lib:read_counter(trans_commits);
-system_info2(transaction_restarts) -> mnesia_lib:read_counter(trans_restarts);
-system_info2(transaction_log_writes) -> mnesia_dumper:get_log_writes();
-
-system_info2(Item) -> exit({badarg, Item}).
-
-system_info_items(yes) ->
- [
- access_module,
- auto_repair,
- backup_module,
- checkpoints,
- db_nodes,
- debug,
- directory,
- dump_log_load_regulation,
- dump_log_time_threshold,
- dump_log_update_in_place,
- dump_log_write_threshold,
- embedded_mnemosyne,
- event_module,
- extra_db_nodes,
- fallback_activated,
- held_locks,
- ignore_fallback_at_startup,
- fallback_error_function,
- is_running,
- local_tables,
- lock_queue,
- log_version,
- master_node_tables,
- max_wait_for_decision,
- protocol_version,
- running_db_nodes,
- schema_location,
- schema_version,
- subscribers,
- tables,
- transaction_commits,
- transaction_failures,
- transaction_log_writes,
- transaction_restarts,
- transactions,
- use_dir,
- version
- ];
-system_info_items(no) ->
- [
- auto_repair,
- backup_module,
- db_nodes,
- debug,
- directory,
- dump_log_load_regulation,
- dump_log_time_threshold,
- dump_log_update_in_place,
- dump_log_write_threshold,
- event_module,
- extra_db_nodes,
- ignore_fallback_at_startup,
- fallback_error_function,
- is_running,
- log_version,
- max_wait_for_decision,
- protocol_version,
- running_db_nodes,
- schema_location,
- schema_version,
- use_dir,
- version
- ].
-
-system_info() ->
- IsRunning = mnesia_lib:is_running(),
- case IsRunning of
- yes ->
- TmInfo = mnesia_tm:get_info(10000),
- Held = system_info(held_locks),
- Queued = system_info(lock_queue),
- Pat = {'_', unclear, '_'},
- Uncertain = ets:match_object(mnesia_decision, Pat),
- display_system_info(Held, Queued, TmInfo, Uncertain);
- _ ->
- mini_info()
- end,
- IsRunning.
-
-load_mnesia_or_abort() ->
- case mnesia_lib:ensure_loaded(?APPLICATION) of
- ok ->
- ok;
- {error, Reason} ->
- abort(Reason)
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Database mgt
-
-create_schema(Ns) ->
- mnesia_bup:create_schema(Ns).
-
-delete_schema(Ns) ->
- mnesia_schema:delete_schema(Ns).
-
-backup(Opaque) ->
- mnesia_log:backup(Opaque).
-
-backup(Opaque, Mod) ->
- mnesia_log:backup(Opaque, Mod).
-
-traverse_backup(S, T, Fun, Acc) ->
- mnesia_bup:traverse_backup(S, T, Fun, Acc).
-
-traverse_backup(S, SM, T, TM, F, A) ->
- mnesia_bup:traverse_backup(S, SM, T, TM, F, A).
-
-install_fallback(Opaque) ->
- mnesia_bup:install_fallback(Opaque).
-
-install_fallback(Opaque, Mod) ->
- mnesia_bup:install_fallback(Opaque, Mod).
-
-uninstall_fallback() ->
- mnesia_bup:uninstall_fallback().
-
-uninstall_fallback(Args) ->
- mnesia_bup:uninstall_fallback(Args).
-
-activate_checkpoint(Args) ->
- mnesia_checkpoint:activate(Args).
-
-deactivate_checkpoint(Name) ->
- mnesia_checkpoint:deactivate(Name).
-
-backup_checkpoint(Name, Opaque) ->
- mnesia_log:backup_checkpoint(Name, Opaque).
-
-backup_checkpoint(Name, Opaque, Mod) ->
- mnesia_log:backup_checkpoint(Name, Opaque, Mod).
-
-restore(Opaque, Args) ->
- mnesia_schema:restore(Opaque, Args).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Table mgt
-
-create_table(Arg) ->
- mnesia_schema:create_table(Arg).
-create_table(Name, Arg) when list(Arg) ->
- mnesia_schema:create_table([{name, Name}| Arg]);
-create_table(Name, Arg) ->
- {aborted, badarg, Name, Arg}.
-
-delete_table(Tab) ->
- mnesia_schema:delete_table(Tab).
-
-add_table_copy(Tab, N, S) ->
- mnesia_schema:add_table_copy(Tab, N, S).
-del_table_copy(Tab, N) ->
- mnesia_schema:del_table_copy(Tab, N).
-
-move_table_copy(Tab, From, To) ->
- mnesia_schema:move_table(Tab, From, To).
-
-add_table_index(Tab, Ix) ->
- mnesia_schema:add_table_index(Tab, Ix).
-del_table_index(Tab, Ix) ->
- mnesia_schema:del_table_index(Tab, Ix).
-
-transform_table(Tab, Fun, NewA) ->
- case catch val({Tab, record_name}) of
- {'EXIT', Reason} ->
- mnesia:abort(Reason);
- OldRN ->
- mnesia_schema:transform_table(Tab, Fun, NewA, OldRN)
- end.
-
-transform_table(Tab, Fun, NewA, NewRN) ->
- mnesia_schema:transform_table(Tab, Fun, NewA, NewRN).
-
-change_table_copy_type(T, N, S) ->
- mnesia_schema:change_table_copy_type(T, N, S).
-
-clear_table(Tab) ->
- mnesia_schema:clear_table(Tab).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Table mgt - user properties
-
-read_table_property(Tab, PropKey) ->
- val({Tab, user_property, PropKey}).
-
-write_table_property(Tab, Prop) ->
- mnesia_schema:write_table_property(Tab, Prop).
-
-delete_table_property(Tab, PropKey) ->
- mnesia_schema:delete_table_property(Tab, PropKey).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Table mgt - user properties
-
-change_table_frag(Tab, FragProp) ->
- mnesia_schema:change_table_frag(Tab, FragProp).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Table mgt - table load
-
-%% Dump a ram table to disc
-dump_tables(Tabs) ->
- mnesia_schema:dump_tables(Tabs).
-
-%% allow the user to wait for some tables to be loaded
-wait_for_tables(Tabs, Timeout) ->
- mnesia_controller:wait_for_tables(Tabs, Timeout).
-
-force_load_table(Tab) ->
- case mnesia_controller:force_load_table(Tab) of
- ok -> yes; % Backwards compatibility
- Other -> Other
- end.
-
-change_table_access_mode(T, Access) ->
- mnesia_schema:change_table_access_mode(T, Access).
-
-change_table_load_order(T, O) ->
- mnesia_schema:change_table_load_order(T, O).
-
-set_master_nodes(Nodes) when list(Nodes) ->
- UseDir = system_info(use_dir),
- IsRunning = system_info(is_running),
- case IsRunning of
- yes ->
- CsPat = {{'_', cstruct}, '_'},
- Cstructs0 = ?ets_match_object(mnesia_gvar, CsPat),
- Cstructs = [Cs || {_, Cs} <- Cstructs0],
- log_valid_master_nodes(Cstructs, Nodes, UseDir, IsRunning);
- _NotRunning ->
- case UseDir of
- true ->
- mnesia_lib:lock_table(schema),
- Res =
- case mnesia_schema:read_cstructs_from_disc() of
- {ok, Cstructs} ->
- log_valid_master_nodes(Cstructs, Nodes, UseDir, IsRunning);
- {error, Reason} ->
- {error, Reason}
- end,
- mnesia_lib:unlock_table(schema),
- Res;
- false ->
- ok
- end
- end;
-set_master_nodes(Nodes) ->
- {error, {bad_type, Nodes}}.
-
-log_valid_master_nodes(Cstructs, Nodes, UseDir, IsRunning) ->
- Fun = fun(Cs) ->
- Copies = mnesia_lib:copy_holders(Cs),
- Valid = mnesia_lib:intersect(Nodes, Copies),
- {Cs#cstruct.name, Valid}
- end,
- Args = lists:map(Fun, Cstructs),
- mnesia_recover:log_master_nodes(Args, UseDir, IsRunning).
-
-set_master_nodes(Tab, Nodes) when list(Nodes) ->
- UseDir = system_info(use_dir),
- IsRunning = system_info(is_running),
- case IsRunning of
- yes ->
- case ?catch_val({Tab, cstruct}) of
- {'EXIT', _} ->
- {error, {no_exists, Tab}};
- Cs ->
- case Nodes -- mnesia_lib:copy_holders(Cs) of
- [] ->
- Args = [{Tab , Nodes}],
- mnesia_recover:log_master_nodes(Args, UseDir, IsRunning);
- BadNodes ->
- {error, {no_exists, Tab, BadNodes}}
- end
- end;
- _NotRunning ->
- case UseDir of
- true ->
- mnesia_lib:lock_table(schema),
- Res =
- case mnesia_schema:read_cstructs_from_disc() of
- {ok, Cstructs} ->
- case lists:keysearch(Tab, 2, Cstructs) of
- {value, Cs} ->
- case Nodes -- mnesia_lib:copy_holders(Cs) of
- [] ->
- Args = [{Tab , Nodes}],
- mnesia_recover:log_master_nodes(Args, UseDir, IsRunning);
- BadNodes ->
- {error, {no_exists, Tab, BadNodes}}
- end;
- false ->
- {error, {no_exists, Tab}}
- end;
- {error, Reason} ->
- {error, Reason}
- end,
- mnesia_lib:unlock_table(schema),
- Res;
- false ->
- ok
- end
- end;
-set_master_nodes(Tab, Nodes) ->
- {error, {bad_type, Tab, Nodes}}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Misc admin
-
-dump_log() ->
- mnesia_controller:sync_dump_log(user).
-
-subscribe(What) ->
- mnesia_subscr:subscribe(self(), What).
-
-unsubscribe(What) ->
- mnesia_subscr:unsubscribe(self(), What).
-
-report_event(Event) ->
- mnesia_lib:report_system_event({mnesia_user, Event}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Snmp
-
-snmp_open_table(Tab, Us) ->
- mnesia_schema:add_snmp(Tab, Us).
-
-snmp_close_table(Tab) ->
- mnesia_schema:del_snmp(Tab).
-
-snmp_get_row(Tab, RowIndex) when atom(Tab), Tab /= schema ->
- dirty_rpc(Tab, mnesia_snmp_hook, get_row, [Tab, RowIndex]);
-snmp_get_row(Tab, _RowIndex) ->
- abort({bad_type, Tab}).
-
-snmp_get_next_index(Tab, RowIndex) when atom(Tab), Tab /= schema ->
- dirty_rpc(Tab, mnesia_snmp_hook, get_next_index, [Tab, RowIndex]);
-snmp_get_next_index(Tab, _RowIndex) ->
- abort({bad_type, Tab}).
-
-snmp_get_mnesia_key(Tab, RowIndex) when atom(Tab), Tab /= schema ->
- dirty_rpc(Tab, mnesia_snmp_hook, get_mnesia_key, [Tab, RowIndex]);
-snmp_get_mnesia_key(Tab, _RowIndex) ->
- abort({bad_type, Tab}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Textfile access
-
-load_textfile(F) ->
- mnesia_text:load_textfile(F).
-dump_to_textfile(F) ->
- mnesia_text:dump_to_textfile(F).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Mnemosyne exclusive
-
-get_activity_id() ->
- get(mnesia_activity_state).
-
-put_activity_id(Activity) ->
- mnesia_tm:put_activity_id(Activity).
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia.hrl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia.hrl
deleted file mode 100644
index b9715ad927..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia.hrl
+++ /dev/null
@@ -1,118 +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: mnesia.hrl,v 1.1 2008/12/17 09:53:37 mikpe Exp $
-%%
-
--define(APPLICATION, mnesia).
-
--define(ets_lookup(Tab, Key), ets:lookup(Tab, Key)).
--define(ets_lookup_element(Tab, Key, Pos), ets:lookup_element(Tab, Key, Pos)).
--define(ets_insert(Tab, Rec), ets:insert(Tab, Rec)).
--define(ets_delete(Tab, Key), ets:delete(Tab, Key)).
--define(ets_match_delete(Tab, Pat), ets:match_delete(Tab, Pat)).
--define(ets_match_object(Tab, Pat), ets:match_object(Tab, Pat)).
--define(ets_match(Tab, Pat), ets:match(Tab, Pat)).
--define(ets_info(Tab, Item), ets:info(Tab, Item)).
--define(ets_update_counter(Tab, Key, Incr), ets:update_counter(Tab, Key, Incr)).
--define(ets_first(Tab), ets:first(Tab)).
--define(ets_next(Tab, Key), ets:next(Tab, Key)).
--define(ets_last(Tab), ets:last(Tab)).
--define(ets_prev(Tab, Key), ets:prev(Tab, Key)).
--define(ets_slot(Tab, Pos), ets:slot(Tab, Pos)).
--define(ets_new_table(Tab, Props), ets:new(Tab, Props)).
--define(ets_delete_table(Tab), ets:delete(Tab)).
--define(ets_fixtable(Tab, Bool), ets:fixtable(Tab, Bool)).
-
--define(catch_val(Var), (catch ?ets_lookup_element(mnesia_gvar, Var, 2))).
-
-%% It's important that counter is first, since we compare tid's
-
--record(tid,
- {counter, %% serial no for tid
- pid}). %% owner of tid
-
-
--record(tidstore,
- {store, %% current ets table for tid
- up_stores = [], %% list of upper layer stores for nested trans
- level = 1}). %% transaction level
-
--define(unique_cookie, {erlang:now(), node()}).
-
--record(cstruct, {name, % Atom
- type = set, % set | bag
- ram_copies = [], % [Node]
- disc_copies = [], % [Node]
- disc_only_copies = [], % [Node]
- load_order = 0, % Integer
- access_mode = read_write, % read_write | read_only
- index = [], % [Integer]
- snmp = [], % Snmp Ustruct
- local_content = false, % true | false
- record_name = {bad_record_name}, % Atom (Default = Name)
- attributes = [key, val], % [Atom]
- user_properties = [], % [Record]
- frag_properties = [], % [{Key, Val]
- cookie = ?unique_cookie, % Term
- version = {{2, 0}, []}}). % {{Integer, Integer}, [Node]}
-
-%% Record for the head structure in Mnesia's log files
-%%
-%% The definition of this record may *NEVER* be changed
-%% since it may be written to very old backup files.
-%% By holding this record definition stable we can be
-%% able to comprahend backups from timepoint 0. It also
-%% allows us to use the backup format as an interchange
-%% format between Mnesia releases.
-
--record(log_header,{log_kind,
- log_version,
- mnesia_version,
- node,
- now}).
-
-%% Commit records stored in the transaction log
--record(commit, {node,
- decision, % presume_commit | Decision
- ram_copies = [],
- disc_copies = [],
- disc_only_copies = [],
- snmp = [],
- schema_ops = []
- }).
-
--record(decision, {tid,
- outcome, % presume_abort | committed
- disc_nodes,
- ram_nodes}).
-
-%% Maybe cyclic wait
--record(cyclic, {node = node(),
- oid, % {Tab, Key}
- op, % read | write
- lock, % read | write
- lucky
- }).
-
-%% Managing conditional debug functions
-
--ifdef(debug).
- -define(eval_debug_fun(I, C),
- mnesia_lib:eval_debug_fun(I, C, ?FILE, ?LINE)).
--else.
- -define(eval_debug_fun(I, C), ok).
--endif.
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_backup.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_backup.erl
deleted file mode 100644
index a1fbb21d94..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_backup.erl
+++ /dev/null
@@ -1,195 +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: mnesia_backup.erl,v 1.1 2008/12/17 09:53:37 mikpe Exp $
-%%
-%0
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% This module contains one implementation of callback functions
-%% used by Mnesia at backup and restore. The user may however
-%% write an own module the same interface as mnesia_backup and
-%% configure Mnesia so the alternate module performs the actual
-%% accesses to the backup media. This means that the user may put
-%% the backup on medias that Mnesia does not know about, possibly
-%% on hosts where Erlang is not running.
-%%
-%% The OpaqueData argument is never interpreted by other parts of
-%% Mnesia. It is the property of this module. Alternate implementations
-%% of this module may have different interpretations of OpaqueData.
-%% The OpaqueData argument given to open_write/1 and open_read/1
-%% are forwarded directly from the user.
-%%
-%% All functions must return {ok, NewOpaqueData} or {error, Reason}.
-%%
-%% The NewOpaqueData arguments returned by backup callback functions will
-%% be given as input when the next backup callback function is invoked.
-%% If any return value does not match {ok, _} the backup will be aborted.
-%%
-%% The NewOpaqueData arguments returned by restore callback functions will
-%% be given as input when the next restore callback function is invoked
-%% If any return value does not match {ok, _} the restore will be aborted.
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
--module(mnesia_backup).
--behaviour(mnesia_backup).
-
--include_lib("kernel/include/file.hrl").
-
--export([
- %% Write access
- open_write/1,
- write/2,
- commit_write/1,
- abort_write/1,
-
- %% Read access
- open_read/1,
- read/1,
- close_read/1
- ]).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Backup callback interface
--record(backup, {tmp_file, file, file_desc}).
-
-%% Opens backup media for write
-%%
-%% Returns {ok, OpaqueData} or {error, Reason}
-open_write(OpaqueData) ->
- File = OpaqueData,
- Tmp = lists:concat([File,".BUPTMP"]),
- file:delete(Tmp),
- file:delete(File),
- case disk_log:open([{name, make_ref()},
- {file, Tmp},
- {repair, false},
- {linkto, self()}]) of
- {ok, Fd} ->
- {ok, #backup{tmp_file = Tmp, file = File, file_desc = Fd}};
- {error, Reason} ->
- {error, Reason}
- end.
-
-%% Writes BackupItems to the backup media
-%%
-%% Returns {ok, OpaqueData} or {error, Reason}
-write(OpaqueData, BackupItems) ->
- B = OpaqueData,
- case disk_log:log_terms(B#backup.file_desc, BackupItems) of
- ok ->
- {ok, B};
- {error, Reason} ->
- abort_write(B),
- {error, Reason}
- end.
-
-%% Closes the backup media after a successful backup
-%%
-%% Returns {ok, ReturnValueToUser} or {error, Reason}
-commit_write(OpaqueData) ->
- B = OpaqueData,
- case disk_log:sync(B#backup.file_desc) of
- ok ->
- case disk_log:close(B#backup.file_desc) of
- ok ->
- case file:rename(B#backup.tmp_file, B#backup.file) of
- ok ->
- {ok, B#backup.file};
- {error, Reason} ->
- {error, Reason}
- end;
- {error, Reason} ->
- {error, Reason}
- end;
- {error, Reason} ->
- {error, Reason}
- end.
-
-%% Closes the backup media after an interrupted backup
-%%
-%% Returns {ok, ReturnValueToUser} or {error, Reason}
-abort_write(BackupRef) ->
- Res = disk_log:close(BackupRef#backup.file_desc),
- file:delete(BackupRef#backup.tmp_file),
- case Res of
- ok ->
- {ok, BackupRef#backup.file};
- {error, Reason} ->
- {error, Reason}
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Restore callback interface
-
--record(restore, {file, file_desc, cont}).
-
-%% Opens backup media for read
-%%
-%% Returns {ok, OpaqueData} or {error, Reason}
-open_read(OpaqueData) ->
- File = OpaqueData,
- case file:read_file_info(File) of
- {error, Reason} ->
- {error, Reason};
- _FileInfo -> %% file exists
- case disk_log:open([{file, File},
- {name, make_ref()},
- {repair, false},
- {mode, read_only},
- {linkto, self()}]) of
- {ok, Fd} ->
- {ok, #restore{file = File, file_desc = Fd, cont = start}};
- {repaired, Fd, _, {badbytes, 0}} ->
- {ok, #restore{file = File, file_desc = Fd, cont = start}};
- {repaired, Fd, _, _} ->
- {ok, #restore{file = File, file_desc = Fd, cont = start}};
- {error, Reason} ->
- {error, Reason}
- end
- end.
-
-%% Reads BackupItems from the backup media
-%%
-%% Returns {ok, OpaqueData, BackupItems} or {error, Reason}
-%%
-%% BackupItems == [] is interpreted as eof
-read(OpaqueData) ->
- R = OpaqueData,
- Fd = R#restore.file_desc,
- case disk_log:chunk(Fd, R#restore.cont) of
- {error, Reason} ->
- {error, {"Possibly truncated", Reason}};
- eof ->
- {ok, R, []};
- {Cont, []} ->
- read(R#restore{cont = Cont});
- {Cont, BackupItems} ->
- {ok, R#restore{cont = Cont}, BackupItems}
- end.
-
-%% Closes the backup media after restore
-%%
-%% Returns {ok, ReturnValueToUser} or {error, Reason}
-close_read(OpaqueData) ->
- R = OpaqueData,
- case disk_log:close(R#restore.file_desc) of
- ok -> {ok, R#restore.file};
- {error, Reason} -> {error, Reason}
- end.
-%0
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_bup.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_bup.erl
deleted file mode 100644
index f03dc029cc..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_bup.erl
+++ /dev/null
@@ -1,1169 +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: mnesia_bup.erl,v 1.1 2008/12/17 09:53:37 mikpe Exp $
-%%
--module(mnesia_bup).
--export([
- %% Public interface
- iterate/4,
- read_schema/2,
- fallback_bup/0,
- fallback_exists/0,
- tm_fallback_start/1,
- create_schema/1,
- install_fallback/1,
- install_fallback/2,
- uninstall_fallback/0,
- uninstall_fallback/1,
- traverse_backup/4,
- traverse_backup/6,
- make_initial_backup/3,
- fallback_to_schema/0,
- lookup_schema/2,
- schema2bup/1,
- refresh_cookie/2,
-
- %% Internal
- fallback_receiver/2,
- install_fallback_master/2,
- uninstall_fallback_master/2,
- local_uninstall_fallback/2,
- do_traverse_backup/7,
- trav_apply/4
- ]).
-
--include("mnesia.hrl").
--import(mnesia_lib, [verbose/2, dbg_out/2]).
-
--record(restore, {mode, bup_module, bup_data}).
-
--record(fallback_args, {opaque,
- scope = global,
- module = mnesia_monitor:get_env(backup_module),
- use_default_dir = true,
- mnesia_dir,
- fallback_bup,
- fallback_tmp,
- skip_tables = [],
- keep_tables = [],
- default_op = keep_tables
- }).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Backup iterator
-
-%% Reads schema section and iterates over all records in a backup.
-%%
-%% Fun(BunchOfRecords, Header, Schema, Acc) is applied when a suitable amount
-%% of records has been collected.
-%%
-%% BunchOfRecords will be [] when the iteration is done.
-iterate(Mod, Fun, Opaque, Acc) ->
- R = #restore{bup_module = Mod, bup_data = Opaque},
- case catch read_schema_section(R) of
- {error, Reason} ->
- {error, Reason};
- {R2, {Header, Schema, Rest}} ->
- case catch iter(R2, Header, Schema, Fun, Acc, Rest) of
- {ok, R3, Res} ->
- catch safe_apply(R3, close_read, [R3#restore.bup_data]),
- {ok, Res};
- {error, Reason} ->
- catch safe_apply(R2, close_read, [R2#restore.bup_data]),
- {error, Reason};
- {'EXIT', Pid, Reason} ->
- catch safe_apply(R2, close_read, [R2#restore.bup_data]),
- {error, {'EXIT', Pid, Reason}};
- {'EXIT', Reason} ->
- catch safe_apply(R2, close_read, [R2#restore.bup_data]),
- {error, {'EXIT', Reason}}
- end
- end.
-
-iter(R, Header, Schema, Fun, Acc, []) ->
- case safe_apply(R, read, [R#restore.bup_data]) of
- {R2, []} ->
- Res = Fun([], Header, Schema, Acc),
- {ok, R2, Res};
- {R2, BupItems} ->
- iter(R2, Header, Schema, Fun, Acc, BupItems)
- end;
-iter(R, Header, Schema, Fun, Acc, BupItems) ->
- Acc2 = Fun(BupItems, Header, Schema, Acc),
- iter(R, Header, Schema, Fun, Acc2, []).
-
-safe_apply(R, write, [_, Items]) when Items == [] ->
- R;
-safe_apply(R, What, Args) ->
- Abort = fun(Re) -> abort_restore(R, What, Args, Re) end,
- receive
- {'EXIT', Pid, Re} -> Abort({'EXIT', Pid, Re})
- after 0 ->
- Mod = R#restore.bup_module,
- case catch apply(Mod, What, Args) of
- {ok, Opaque, Items} when What == read ->
- {R#restore{bup_data = Opaque}, Items};
- {ok, Opaque} when What /= read->
- R#restore{bup_data = Opaque};
- {error, Re} ->
- Abort(Re);
- Re ->
- Abort(Re)
- end
- end.
-
-abort_restore(R, What, Args, Reason) ->
- Mod = R#restore.bup_module,
- Opaque = R#restore.bup_data,
- dbg_out("Restore aborted. ~p:~p~p -> ~p~n",
- [Mod, What, Args, Reason]),
- catch apply(Mod, close_read, [Opaque]),
- throw({error, Reason}).
-
-fallback_to_schema() ->
- Fname = fallback_bup(),
- fallback_to_schema(Fname).
-
-fallback_to_schema(Fname) ->
- Mod = mnesia_backup,
- case read_schema(Mod, Fname) of
- {error, Reason} ->
- {error, Reason};
- Schema ->
- case catch lookup_schema(schema, Schema) of
- {error, _} ->
- {error, "No schema in fallback"};
- List ->
- {ok, fallback, List}
- end
- end.
-
-%% Opens Opaque reads schema and then close
-read_schema(Mod, Opaque) ->
- R = #restore{bup_module = Mod, bup_data = Opaque},
- case catch read_schema_section(R) of
- {error, Reason} ->
- {error, Reason};
- {R2, {_Header, Schema, _}} ->
- catch safe_apply(R2, close_read, [R2#restore.bup_data]),
- Schema
- end.
-
-%% Open backup media and extract schema
-%% rewind backup media and leave it open
-%% Returns {R, {Header, Schema}}
-read_schema_section(R) ->
- case catch do_read_schema_section(R) of
- {'EXIT', Reason} ->
- catch safe_apply(R, close_read, [R#restore.bup_data]),
- {error, {'EXIT', Reason}};
- {error, Reason} ->
- catch safe_apply(R, close_read, [R#restore.bup_data]),
- {error, Reason};
- {R2, {H, Schema, Rest}} ->
- Schema2 = convert_schema(H#log_header.log_version, Schema),
- {R2, {H, Schema2, Rest}}
- end.
-
-do_read_schema_section(R) ->
- R2 = safe_apply(R, open_read, [R#restore.bup_data]),
- {R3, RawSchema} = safe_apply(R2, read, [R2#restore.bup_data]),
- do_read_schema_section(R3, verify_header(RawSchema), []).
-
-do_read_schema_section(R, {ok, B, C, []}, Acc) ->
- case safe_apply(R, read, [R#restore.bup_data]) of
- {R2, []} ->
- {R2, {B, Acc, []}};
- {R2, RawSchema} ->
- do_read_schema_section(R2, {ok, B, C, RawSchema}, Acc)
- end;
-
-do_read_schema_section(R, {ok, B, C, [Head | Tail]}, Acc)
- when element(1, Head) == schema ->
- do_read_schema_section(R, {ok, B, C, Tail}, Acc ++ [Head]);
-
-do_read_schema_section(R, {ok, B, _C, Rest}, Acc) ->
- {R, {B, Acc, Rest}};
-
-do_read_schema_section(_R, {error, Reason}, _Acc) ->
- {error, Reason}.
-
-verify_header([H | RawSchema]) when record(H, log_header) ->
- Current = mnesia_log:backup_log_header(),
- if
- H#log_header.log_kind == Current#log_header.log_kind ->
- Versions = ["0.1", "1.1", Current#log_header.log_version],
- case lists:member(H#log_header.log_version, Versions) of
- true ->
- {ok, H, Current, RawSchema};
- false ->
- {error, {"Bad header version. Cannot be used as backup.", H}}
- end;
- true ->
- {error, {"Bad kind of header. Cannot be used as backup.", H}}
- end;
-verify_header(RawSchema) ->
- {error, {"Missing header. Cannot be used as backup.", catch hd(RawSchema)}}.
-
-refresh_cookie(Schema, NewCookie) ->
- case lists:keysearch(schema, 2, Schema) of
- {value, {schema, schema, List}} ->
- Cs = mnesia_schema:list2cs(List),
- Cs2 = Cs#cstruct{cookie = NewCookie},
- Item = {schema, schema, mnesia_schema:cs2list(Cs2)},
- lists:keyreplace(schema, 2, Schema, Item);
-
- false ->
- Reason = "No schema found. Cannot be used as backup.",
- throw({error, {Reason, Schema}})
- end.
-
-%% Convert schema items from an external backup
-%% If backup format is the latest, no conversion is needed
-%% All supported backup formats should have their converters
-%% here as separate function clauses.
-convert_schema("0.1", Schema) ->
- convert_0_1(Schema);
-convert_schema("1.1", Schema) ->
- %% The new backup format is a pure extension of the old one
- Current = mnesia_log:backup_log_header(),
- convert_schema(Current#log_header.log_version, Schema);
-convert_schema(Latest, Schema) ->
- H = mnesia_log:backup_log_header(),
- if
- H#log_header.log_version == Latest ->
- Schema;
- true ->
- Reason = "Bad backup header version. Cannot convert schema.",
- throw({error, {Reason, H}})
- end.
-
-%% Backward compatibility for 0.1
-convert_0_1(Schema) ->
- case lists:keysearch(schema, 2, Schema) of
- {value, {schema, schema, List}} ->
- Schema2 = lists:keydelete(schema, 2, Schema),
- Cs = mnesia_schema:list2cs(List),
- convert_0_1(Schema2, [], Cs);
- false ->
- List = mnesia_schema:get_initial_schema(disc_copies, [node()]),
- Cs = mnesia_schema:list2cs(List),
- convert_0_1(Schema, [], Cs)
- end.
-
-convert_0_1([{schema, cookie, Cookie} | Schema], Acc, Cs) ->
- convert_0_1(Schema, Acc, Cs#cstruct{cookie = Cookie});
-convert_0_1([{schema, db_nodes, DbNodes} | Schema], Acc, Cs) ->
- convert_0_1(Schema, Acc, Cs#cstruct{disc_copies = DbNodes});
-convert_0_1([{schema, version, Version} | Schema], Acc, Cs) ->
- convert_0_1(Schema, Acc, Cs#cstruct{version = Version});
-convert_0_1([{schema, Tab, Def} | Schema], Acc, Cs) ->
- Head =
- case lists:keysearch(index, 1, Def) of
- {value, {index, PosList}} ->
- %% Remove the snmp "index"
- P = PosList -- [snmp],
- Def2 = lists:keyreplace(index, 1, Def, {index, P}),
- {schema, Tab, Def2};
- false ->
- {schema, Tab, Def}
- end,
- convert_0_1(Schema, [Head | Acc], Cs);
-convert_0_1([Head | Schema], Acc, Cs) ->
- convert_0_1(Schema, [Head | Acc], Cs);
-convert_0_1([], Acc, Cs) ->
- [schema2bup({schema, schema, Cs}) | Acc].
-
-%% Returns Val or throw error
-lookup_schema(Key, Schema) ->
- case lists:keysearch(Key, 2, Schema) of
- {value, {schema, Key, Val}} -> Val;
- false -> throw({error, {"Cannot lookup", Key}})
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Backup compatibility
-
-%% Convert internal schema items to backup dito
-schema2bup({schema, Tab}) ->
- {schema, Tab};
-schema2bup({schema, Tab, TableDef}) ->
- {schema, Tab, mnesia_schema:cs2list(TableDef)}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Create schema on the given nodes
-%% Requires that old schemas has been deleted
-%% Returns ok | {error, Reason}
-create_schema([]) ->
- create_schema([node()]);
-create_schema(Ns) when list(Ns) ->
- case is_set(Ns) of
- true ->
- create_schema(Ns, mnesia_schema:ensure_no_schema(Ns));
- false ->
- {error, {combine_error, Ns}}
- end;
-create_schema(Ns) ->
- {error, {badarg, Ns}}.
-
-is_set(List) when list(List) ->
- ordsets:is_set(lists:sort(List));
-is_set(_) ->
- false.
-
-create_schema(Ns, ok) ->
- %% Ensure that we access the intended Mnesia
- %% directory. This function may not be called
- %% during startup since it will cause the
- %% application_controller to get into deadlock
- case mnesia_lib:ensure_loaded(?APPLICATION) of
- ok ->
- case mnesia_monitor:get_env(schema_location) of
- ram ->
- {error, {has_no_disc, node()}};
- _ ->
- case mnesia_schema:opt_create_dir(true, mnesia_lib:dir()) of
- {error, What} ->
- {error, What};
- ok ->
- Mod = mnesia_backup,
- Str = mk_str(),
- File = mnesia_lib:dir(Str),
- file:delete(File),
- case catch make_initial_backup(Ns, File, Mod) of
- {ok, _Res} ->
- case do_install_fallback(File, Mod) of
- ok ->
- file:delete(File),
- ok;
- {error, Reason} ->
- {error, Reason}
- end;
- {error, Reason} ->
- {error, Reason}
- end
- end
- end;
- {error, Reason} ->
- {error, Reason}
- end;
-create_schema(_Ns, {error, Reason}) ->
- {error, Reason};
-create_schema(_Ns, Reason) ->
- {error, Reason}.
-
-mk_str() ->
- Now = [integer_to_list(I) || I <- tuple_to_list(now())],
- lists:concat([node()] ++ Now ++ ".TMP").
-
-make_initial_backup(Ns, Opaque, Mod) ->
- Schema = [{schema, schema, mnesia_schema:get_initial_schema(disc_copies, Ns)}],
- O2 = do_apply(Mod, open_write, [Opaque], Opaque),
- O3 = do_apply(Mod, write, [O2, [mnesia_log:backup_log_header()]], O2),
- O4 = do_apply(Mod, write, [O3, Schema], O3),
- O5 = do_apply(Mod, commit_write, [O4], O4),
- {ok, O5}.
-
-do_apply(_, write, [_, Items], Opaque) when Items == [] ->
- Opaque;
-do_apply(Mod, What, Args, _Opaque) ->
- case catch apply(Mod, What, Args) of
- {ok, Opaque2} -> Opaque2;
- {error, Reason} -> throw({error, Reason});
- {'EXIT', Reason} -> throw({error, {'EXIT', Reason}})
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Restore
-
-%% Restore schema and possibly other tables from a backup
-%% and replicate them to the necessary nodes
-%% Requires that old schemas has been deleted
-%% Returns ok | {error, Reason}
-install_fallback(Opaque) ->
- install_fallback(Opaque, []).
-
-install_fallback(Opaque, Args) ->
- %% Ensure that we access the intended Mnesia
- %% directory. This function may not be called
- %% during startup since it will cause the
- %% application_controller to get into deadlock
- case mnesia_lib:ensure_loaded(?APPLICATION) of
- ok ->
- do_install_fallback(Opaque, Args);
- {error, Reason} ->
- {error, Reason}
- end.
-
-do_install_fallback(Opaque, Mod) when atom(Mod) ->
- do_install_fallback(Opaque, [{module, Mod}]);
-do_install_fallback(Opaque, Args) when list(Args) ->
- case check_fallback_args(Args, #fallback_args{opaque = Opaque}) of
- {ok, FA} ->
- do_install_fallback(FA);
- {error, Reason} ->
- {error, Reason}
- end;
-do_install_fallback(_Opaque, Args) ->
- {error, {badarg, Args}}.
-
-check_fallback_args([Arg | Tail], FA) ->
- case catch check_fallback_arg_type(Arg, FA) of
- {'EXIT', _Reason} ->
- {error, {badarg, Arg}};
- FA2 ->
- check_fallback_args(Tail, FA2)
- end;
-check_fallback_args([], FA) ->
- {ok, FA}.
-
-check_fallback_arg_type(Arg, FA) ->
- case Arg of
- {scope, global} ->
- FA#fallback_args{scope = global};
- {scope, local} ->
- FA#fallback_args{scope = local};
- {module, Mod} ->
- Mod2 = mnesia_monitor:do_check_type(backup_module, Mod),
- FA#fallback_args{module = Mod2};
- {mnesia_dir, Dir} ->
- FA#fallback_args{mnesia_dir = Dir,
- use_default_dir = false};
- {keep_tables, Tabs} ->
- atom_list(Tabs),
- FA#fallback_args{keep_tables = Tabs};
- {skip_tables, Tabs} ->
- atom_list(Tabs),
- FA#fallback_args{skip_tables = Tabs};
- {default_op, keep_tables} ->
- FA#fallback_args{default_op = keep_tables};
- {default_op, skip_tables} ->
- FA#fallback_args{default_op = skip_tables}
- end.
-
-atom_list([H | T]) when atom(H) ->
- atom_list(T);
-atom_list([]) ->
- ok.
-
-do_install_fallback(FA) ->
- Pid = spawn_link(?MODULE, install_fallback_master, [self(), FA]),
- Res =
- receive
- {'EXIT', Pid, Reason} -> % if appl has trapped exit
- {error, {'EXIT', Reason}};
- {Pid, Res2} ->
- case Res2 of
- {ok, _} ->
- ok;
- {error, Reason} ->
- {error, {"Cannot install fallback", Reason}}
- end
- end,
- Res.
-
-install_fallback_master(ClientPid, FA) ->
- process_flag(trap_exit, true),
- State = {start, FA},
- Opaque = FA#fallback_args.opaque,
- Mod = FA#fallback_args.module,
- Res = (catch iterate(Mod, fun restore_recs/4, Opaque, State)),
- unlink(ClientPid),
- ClientPid ! {self(), Res},
- exit(shutdown).
-
-restore_recs(_, _, _, stop) ->
- throw({error, "restore_recs already stopped"});
-
-restore_recs(Recs, Header, Schema, {start, FA}) ->
- %% No records in backup
- Schema2 = convert_schema(Header#log_header.log_version, Schema),
- CreateList = lookup_schema(schema, Schema2),
- case catch mnesia_schema:list2cs(CreateList) of
- {'EXIT', Reason} ->
- throw({error, {"Bad schema in restore_recs", Reason}});
- Cs ->
- Ns = get_fallback_nodes(FA, Cs#cstruct.disc_copies),
- global:set_lock({{mnesia_table_lock, schema}, self()}, Ns, infinity),
- Args = [self(), FA],
- Pids = [spawn_link(N, ?MODULE, fallback_receiver, Args) || N <- Ns],
- send_fallback(Pids, {start, Header, Schema2}),
- Res = restore_recs(Recs, Header, Schema2, Pids),
- global:del_lock({{mnesia_table_lock, schema}, self()}, Ns),
- Res
- end;
-
-restore_recs([], _Header, _Schema, Pids) ->
- send_fallback(Pids, swap),
- send_fallback(Pids, stop),
- stop;
-
-restore_recs(Recs, _, _, Pids) ->
- send_fallback(Pids, {records, Recs}),
- Pids.
-
-get_fallback_nodes(FA, Ns) ->
- This = node(),
- case lists:member(This, Ns) of
- true ->
- case FA#fallback_args.scope of
- global -> Ns;
- local -> [This]
- end;
- false ->
- throw({error, {"No disc resident schema on local node", Ns}})
- end.
-
-send_fallback(Pids, Msg) when list(Pids), Pids /= [] ->
- lists:foreach(fun(Pid) -> Pid ! {self(), Msg} end, Pids),
- rec_answers(Pids, []).
-
-rec_answers([], Acc) ->
- case {lists:keysearch(error, 1, Acc), mnesia_lib:uniq(Acc)} of
- {{value, {error, Val}}, _} -> throw({error, Val});
- {_, [SameAnswer]} -> SameAnswer;
- {_, Other} -> throw({error, {"Different answers", Other}})
- end;
-rec_answers(Pids, Acc) ->
- receive
- {'EXIT', Pid, stopped} ->
- Pids2 = lists:delete(Pid, Pids),
- rec_answers(Pids2, [stopped|Acc]);
- {'EXIT', Pid, Reason} ->
- Pids2 = lists:delete(Pid, Pids),
- rec_answers(Pids2, [{error, {'EXIT', Pid, Reason}}|Acc]);
- {Pid, Reply} ->
- Pids2 = lists:delete(Pid, Pids),
- rec_answers(Pids2, [Reply|Acc])
- end.
-
-fallback_exists() ->
- Fname = fallback_bup(),
- fallback_exists(Fname).
-
-fallback_exists(Fname) ->
- case mnesia_monitor:use_dir() of
- true ->
- mnesia_lib:exists(Fname);
- false ->
- case ?catch_val(active_fallback) of
- {'EXIT', _} -> false;
- Bool -> Bool
- end
- end.
-
-fallback_name() -> "FALLBACK.BUP".
-fallback_bup() -> mnesia_lib:dir(fallback_name()).
-
-fallback_tmp_name() -> "FALLBACK.TMP".
-%% fallback_full_tmp_name() -> mnesia_lib:dir(fallback_tmp_name()).
-
-fallback_receiver(Master, FA) ->
- process_flag(trap_exit, true),
-
- case catch register(mnesia_fallback, self()) of
- {'EXIT', _} ->
- Reason = {already_exists, node()},
- local_fallback_error(Master, Reason);
- true ->
- FA2 = check_fallback_dir(Master, FA),
- Bup = FA2#fallback_args.fallback_bup,
- case mnesia_lib:exists(Bup) of
- true ->
- Reason2 = {already_exists, node()},
- local_fallback_error(Master, Reason2);
- false ->
- Mod = mnesia_backup,
- Tmp = FA2#fallback_args.fallback_tmp,
- R = #restore{mode = replace,
- bup_module = Mod,
- bup_data = Tmp},
- file:delete(Tmp),
- case catch fallback_receiver_loop(Master, R, FA2, schema) of
- {error, Reason} ->
- local_fallback_error(Master, Reason);
- Other ->
- exit(Other)
- end
- end
- end.
-
-local_fallback_error(Master, Reason) ->
- Master ! {self(), {error, Reason}},
- unlink(Master),
- exit(Reason).
-
-check_fallback_dir(Master, FA) ->
- case mnesia:system_info(schema_location) of
- ram ->
- Reason = {has_no_disc, node()},
- local_fallback_error(Master, Reason);
- _ ->
- Dir = check_fallback_dir_arg(Master, FA),
- Bup = filename:join([Dir, fallback_name()]),
- Tmp = filename:join([Dir, fallback_tmp_name()]),
- FA#fallback_args{fallback_bup = Bup,
- fallback_tmp = Tmp,
- mnesia_dir = Dir}
- end.
-
-check_fallback_dir_arg(Master, FA) ->
- case FA#fallback_args.use_default_dir of
- true ->
- mnesia_lib:dir();
- false when FA#fallback_args.scope == local ->
- Dir = FA#fallback_args.mnesia_dir,
- case catch mnesia_monitor:do_check_type(dir, Dir) of
- {'EXIT', _R} ->
- Reason = {badarg, {dir, Dir}, node()},
- local_fallback_error(Master, Reason);
- AbsDir->
- AbsDir
- end;
- false when FA#fallback_args.scope == global ->
- Reason = {combine_error, global, dir, node()},
- local_fallback_error(Master, Reason)
- end.
-
-fallback_receiver_loop(Master, R, FA, State) ->
- receive
- {Master, {start, Header, Schema}} when State == schema ->
- Dir = FA#fallback_args.mnesia_dir,
- throw_bad_res(ok, mnesia_schema:opt_create_dir(true, Dir)),
- R2 = safe_apply(R, open_write, [R#restore.bup_data]),
- R3 = safe_apply(R2, write, [R2#restore.bup_data, [Header]]),
- BupSchema = [schema2bup(S) || S <- Schema],
- R4 = safe_apply(R3, write, [R3#restore.bup_data, BupSchema]),
- Master ! {self(), ok},
- fallback_receiver_loop(Master, R4, FA, records);
-
- {Master, {records, Recs}} when State == records ->
- R2 = safe_apply(R, write, [R#restore.bup_data, Recs]),
- Master ! {self(), ok},
- fallback_receiver_loop(Master, R2, FA, records);
-
- {Master, swap} when State /= schema ->
- ?eval_debug_fun({?MODULE, fallback_receiver_loop, pre_swap}, []),
- safe_apply(R, commit_write, [R#restore.bup_data]),
- Bup = FA#fallback_args.fallback_bup,
- Tmp = FA#fallback_args.fallback_tmp,
- throw_bad_res(ok, file:rename(Tmp, Bup)),
- catch mnesia_lib:set(active_fallback, true),
- ?eval_debug_fun({?MODULE, fallback_receiver_loop, post_swap}, []),
- Master ! {self(), ok},
- fallback_receiver_loop(Master, R, FA, stop);
-
- {Master, stop} when State == stop ->
- stopped;
-
- Msg ->
- safe_apply(R, abort_write, [R#restore.bup_data]),
- Tmp = FA#fallback_args.fallback_tmp,
- file:delete(Tmp),
- throw({error, "Unexpected msg fallback_receiver_loop", Msg})
- end.
-
-throw_bad_res(Expected, Expected) -> Expected;
-throw_bad_res(_Expected, {error, Actual}) -> throw({error, Actual});
-throw_bad_res(_Expected, Actual) -> throw({error, Actual}).
-
--record(local_tab, {name, storage_type, dets_args, open, close, add, record_name}).
-
-tm_fallback_start(IgnoreFallback) ->
- mnesia_schema:lock_schema(),
- Res = do_fallback_start(fallback_exists(), IgnoreFallback),
- mnesia_schema: unlock_schema(),
- case Res of
- ok -> ok;
- {error, Reason} -> exit(Reason)
- end.
-
-do_fallback_start(false, _IgnoreFallback) ->
- ok;
-do_fallback_start(true, true) ->
- verbose("Ignoring fallback at startup, but leaving it active...~n", []),
- mnesia_lib:set(active_fallback, true),
- ok;
-do_fallback_start(true, false) ->
- verbose("Starting from fallback...~n", []),
-
- Fname = fallback_bup(),
- Mod = mnesia_backup,
- Ets = ?ets_new_table(mnesia_local_tables, [set, public, {keypos, 2}]),
- case catch iterate(Mod, fun restore_tables/4, Fname, {start, Ets}) of
- {ok, Res} ->
- case Res of
- {local, _, LT} -> %% Close the last file
- (LT#local_tab.close)(LT);
- _ ->
- ignore
- end,
- List = ?ets_match_object(Ets, '_'),
- Tabs = [L#local_tab.name || L <- List, L#local_tab.name /= schema],
- ?ets_delete_table(Ets),
- mnesia_lib:swap_tmp_files(Tabs),
- catch dets:close(schema),
- Tmp = mnesia_lib:tab2tmp(schema),
- Dat = mnesia_lib:tab2dat(schema),
- case file:rename(Tmp, Dat) of
- ok ->
- file:delete(Fname),
- ok;
- {error, Reason} ->
- file:delete(Tmp),
- {error, {"Cannot start from fallback. Rename error.", Reason}}
- end;
- {error, Reason} ->
- {error, {"Cannot start from fallback", Reason}};
- {'EXIT', Reason} ->
- {error, {"Cannot start from fallback", Reason}}
- end.
-
-restore_tables(Recs, Header, Schema, {start, LocalTabs}) ->
- Dir = mnesia_lib:dir(),
- OldDir = filename:join([Dir, "OLD_DIR"]),
- mnesia_schema:purge_dir(OldDir, []),
- mnesia_schema:purge_dir(Dir, [fallback_name()]),
- init_dat_files(Schema, LocalTabs),
- State = {new, LocalTabs},
- restore_tables(Recs, Header, Schema, State);
-restore_tables([Rec | Recs], Header, Schema, {new, LocalTabs}) ->
- Tab = element(1, Rec),
- case ?ets_lookup(LocalTabs, Tab) of
- [] ->
- State = {not_local, LocalTabs, Tab},
- restore_tables(Recs, Header, Schema, State);
- [L] when record(L, local_tab) ->
- (L#local_tab.open)(Tab, L),
- State = {local, LocalTabs, L},
- restore_tables([Rec | Recs], Header, Schema, State)
- end;
-restore_tables([Rec | Recs], Header, Schema, S = {not_local, LocalTabs, PrevTab}) ->
- Tab = element(1, Rec),
- if
- Tab == PrevTab ->
- restore_tables(Recs, Header, Schema, S);
- true ->
- State = {new, LocalTabs},
- restore_tables([Rec | Recs], Header, Schema, State)
- end;
-restore_tables([Rec | Recs], Header, Schema, State = {local, LocalTabs, L}) ->
- Tab = element(1, Rec),
- if
- Tab == L#local_tab.name ->
- Key = element(2, Rec),
- (L#local_tab.add)(Tab, Key, Rec, L),
- restore_tables(Recs, Header, Schema, State);
- true ->
- (L#local_tab.close)(L),
- NState = {new, LocalTabs},
- restore_tables([Rec | Recs], Header, Schema, NState)
- end;
-restore_tables([], _Header, _Schema, State) ->
- State.
-
-%% Creates all neccessary dat files and inserts
-%% the table definitions in the schema table
-%%
-%% Returns a list of local_tab tuples for all local tables
-init_dat_files(Schema, LocalTabs) ->
- Fname = mnesia_lib:tab2tmp(schema),
- Args = [{file, Fname}, {keypos, 2}, {type, set}],
- case dets:open_file(schema, Args) of % Assume schema lock
- {ok, _} ->
- create_dat_files(Schema, LocalTabs),
- dets:close(schema),
- LocalTab = #local_tab{name = schema,
- storage_type = disc_copies,
- dets_args = Args,
- open = fun open_media/2,
- close = fun close_media/1,
- add = fun add_to_media/4,
- record_name = schema},
- ?ets_insert(LocalTabs, LocalTab);
- {error, Reason} ->
- throw({error, {"Cannot open file", schema, Args, Reason}})
- end.
-
-create_dat_files([{schema, schema, TabDef} | Tail], LocalTabs) ->
- ok = dets:insert(schema, {schema, schema, TabDef}),
- create_dat_files(Tail, LocalTabs);
-create_dat_files([{schema, Tab, TabDef} | Tail], LocalTabs) ->
- Cs = mnesia_schema:list2cs(TabDef),
- ok = dets:insert(schema, {schema, Tab, TabDef}),
- RecName = Cs#cstruct.record_name,
- case mnesia_lib:cs_to_storage_type(node(), Cs) of
- unknown ->
- cleanup_dat_file(Tab),
- create_dat_files(Tail, LocalTabs);
- disc_only_copies ->
- Fname = mnesia_lib:tab2tmp(Tab),
- Args = [{file, Fname}, {keypos, 2},
- {type, mnesia_lib:disk_type(Tab, Cs#cstruct.type)}],
- case mnesia_lib:dets_sync_open(Tab, Args) of
- {ok, _} ->
- mnesia_lib:dets_sync_close(Tab),
- LocalTab = #local_tab{name = Tab,
- storage_type = disc_only_copies,
- dets_args = Args,
- open = fun open_media/2,
- close = fun close_media/1,
- add = fun add_to_media/4,
- record_name = RecName},
- ?ets_insert(LocalTabs, LocalTab),
- create_dat_files(Tail, LocalTabs);
- {error, Reason} ->
- throw({error, {"Cannot open file", Tab, Args, Reason}})
- end;
- ram_copies ->
- %% Create .DCD if needed in open_media in case any ram_copies
- %% are backed up.
- LocalTab = #local_tab{name = Tab,
- storage_type = ram_copies,
- dets_args = ignore,
- open = fun open_media/2,
- close = fun close_media/1,
- add = fun add_to_media/4,
- record_name = RecName},
- ?ets_insert(LocalTabs, LocalTab),
- create_dat_files(Tail, LocalTabs);
- Storage ->
- %% Create DCD
- Fname = mnesia_lib:tab2dcd(Tab),
- file:delete(Fname),
- Log = mnesia_log:open_log(fallback_tab, mnesia_log:dcd_log_header(),
- Fname, false),
- LocalTab = #local_tab{name = Tab,
- storage_type = Storage,
- dets_args = ignore,
- open = fun open_media/2,
- close = fun close_media/1,
- add = fun add_to_media/4,
- record_name = RecName},
- mnesia_log:close_log(Log),
- ?ets_insert(LocalTabs, LocalTab),
- create_dat_files(Tail, LocalTabs)
- end;
-create_dat_files([{schema, Tab} | Tail], LocalTabs) ->
- cleanup_dat_file(Tab),
- create_dat_files(Tail, LocalTabs);
-create_dat_files([], _LocalTabs) ->
- ok.
-
-cleanup_dat_file(Tab) ->
- ok = dets:delete(schema, {schema, Tab}),
- mnesia_lib:cleanup_tmp_files([Tab]).
-
-open_media(Tab, LT) ->
- case LT#local_tab.storage_type of
- disc_only_copies ->
- Args = LT#local_tab.dets_args,
- case mnesia_lib:dets_sync_open(Tab, Args) of
- {ok, _} -> ok;
- {error, Reason} ->
- throw({error, {"Cannot open file", Tab, Args, Reason}})
- end;
- ram_copies ->
- %% Create .DCD as ram_copies backed up.
- FnameDCD = mnesia_lib:tab2dcd(Tab),
- file:delete(FnameDCD),
- Log = mnesia_log:open_log(fallback_tab,
- mnesia_log:dcd_log_header(),
- FnameDCD, false),
- mnesia_log:close_log(Log),
-
- %% Create .DCL
- Fname = mnesia_lib:tab2dcl(Tab),
- file:delete(Fname),
- mnesia_log:open_log({?MODULE,Tab},
- mnesia_log:dcl_log_header(),
- Fname, false, false,
- read_write);
- _ ->
- Fname = mnesia_lib:tab2dcl(Tab),
- file:delete(Fname),
- mnesia_log:open_log({?MODULE,Tab},
- mnesia_log:dcl_log_header(),
- Fname, false, false,
- read_write)
- end.
-close_media(L) ->
- Tab = L#local_tab.name,
- case L#local_tab.storage_type of
- disc_only_copies ->
- mnesia_lib:dets_sync_close(Tab);
- _ ->
- mnesia_log:close_log({?MODULE,Tab})
- end.
-
-add_to_media(Tab, Key, Rec, L) ->
- RecName = L#local_tab.record_name,
- case L#local_tab.storage_type of
- disc_only_copies ->
- case Rec of
- {Tab, Key} ->
- ok = dets:delete(Tab, Key);
- (Rec) when Tab == RecName ->
- ok = dets:insert(Tab, Rec);
- (Rec) ->
- Rec2 = setelement(1, Rec, RecName),
- ok = dets:insert(Tab, Rec2)
- end;
- _ ->
- Log = {?MODULE, Tab},
- case Rec of
- {Tab, Key} ->
- mnesia_log:append(Log, {{Tab, Key}, {Tab, Key}, delete});
- (Rec) when Tab == RecName ->
- mnesia_log:append(Log, {{Tab, Key}, Rec, write});
- (Rec) ->
- Rec2 = setelement(1, Rec, RecName),
- mnesia_log:append(Log, {{Tab, Key}, Rec2, write})
- end
- end.
-
-uninstall_fallback() ->
- uninstall_fallback([{scope, global}]).
-
-uninstall_fallback(Args) ->
- case check_fallback_args(Args, #fallback_args{}) of
- {ok, FA} ->
- do_uninstall_fallback(FA);
- {error, Reason} ->
- {error, Reason}
- end.
-
-do_uninstall_fallback(FA) ->
- %% Ensure that we access the intended Mnesia
- %% directory. This function may not be called
- %% during startup since it will cause the
- %% application_controller to get into deadlock
- case mnesia_lib:ensure_loaded(?APPLICATION) of
- ok ->
- Pid = spawn_link(?MODULE, uninstall_fallback_master, [self(), FA]),
- receive
- {'EXIT', Pid, Reason} -> % if appl has trapped exit
- {error, {'EXIT', Reason}};
- {Pid, Res} ->
- Res
- end;
- {error, Reason} ->
- {error, Reason}
- end.
-
-uninstall_fallback_master(ClientPid, FA) ->
- process_flag(trap_exit, true),
-
- FA2 = check_fallback_dir(ClientPid, FA), % May exit
- Bup = FA2#fallback_args.fallback_bup,
- case fallback_to_schema(Bup) of
- {ok, fallback, List} ->
- Cs = mnesia_schema:list2cs(List),
- case catch get_fallback_nodes(FA, Cs#cstruct.disc_copies) of
- Ns when list(Ns) ->
- do_uninstall(ClientPid, Ns, FA);
- {error, Reason} ->
- local_fallback_error(ClientPid, Reason)
- end;
- {error, Reason} ->
- local_fallback_error(ClientPid, Reason)
- end.
-
-do_uninstall(ClientPid, Ns, FA) ->
- Args = [self(), FA],
- global:set_lock({{mnesia_table_lock, schema}, self()}, Ns, infinity),
- Pids = [spawn_link(N, ?MODULE, local_uninstall_fallback, Args) || N <- Ns],
- Res = do_uninstall(ClientPid, Pids, [], [], ok),
- global:del_lock({{mnesia_table_lock, schema}, self()}, Ns),
- ClientPid ! {self(), Res},
- unlink(ClientPid),
- exit(shutdown).
-
-do_uninstall(ClientPid, [Pid | Pids], GoodPids, BadNodes, Res) ->
- receive
- %% {'EXIT', ClientPid, _} ->
- %% client_exit;
- {'EXIT', Pid, Reason} ->
- BadNode = node(Pid),
- BadRes = {error, {"Uninstall fallback", BadNode, Reason}},
- do_uninstall(ClientPid, Pids, GoodPids, [BadNode | BadNodes], BadRes);
- {Pid, {error, Reason}} ->
- BadNode = node(Pid),
- BadRes = {error, {"Uninstall fallback", BadNode, Reason}},
- do_uninstall(ClientPid, Pids, GoodPids, [BadNode | BadNodes], BadRes);
- {Pid, started} ->
- do_uninstall(ClientPid, Pids, [Pid | GoodPids], BadNodes, Res)
- end;
-do_uninstall(ClientPid, [], GoodPids, [], ok) ->
- lists:foreach(fun(Pid) -> Pid ! {self(), do_uninstall} end, GoodPids),
- rec_uninstall(ClientPid, GoodPids, ok);
-do_uninstall(_ClientPid, [], GoodPids, BadNodes, BadRes) ->
- lists:foreach(fun(Pid) -> exit(Pid, shutdown) end, GoodPids),
- {error, {node_not_running, BadNodes, BadRes}}.
-
-local_uninstall_fallback(Master, FA) ->
- %% Don't trap exit
-
- register(mnesia_fallback, self()), % May exit
- FA2 = check_fallback_dir(Master, FA), % May exit
- Master ! {self(), started},
-
- receive
- {Master, do_uninstall} ->
- ?eval_debug_fun({?MODULE, uninstall_fallback2, pre_delete}, []),
- catch mnesia_lib:set(active_fallback, false),
- Tmp = FA2#fallback_args.fallback_tmp,
- Bup = FA2#fallback_args.fallback_bup,
- file:delete(Tmp),
- Res =
- case fallback_exists(Bup) of
- true -> file:delete(Bup);
- false -> ok
- end,
- ?eval_debug_fun({?MODULE, uninstall_fallback2, post_delete}, []),
- Master ! {self(), Res},
- unlink(Master),
- exit(normal)
- end.
-
-rec_uninstall(ClientPid, [Pid | Pids], AccRes) ->
- receive
- %% {'EXIT', ClientPid, _} ->
- %% exit(shutdown);
- {'EXIT', Pid, R} ->
- Reason = {node_not_running, {node(Pid), R}},
- rec_uninstall(ClientPid, Pids, {error, Reason});
- {Pid, ok} ->
- rec_uninstall(ClientPid, Pids, AccRes);
- {Pid, BadRes} ->
- rec_uninstall(ClientPid, Pids, BadRes)
- end;
-rec_uninstall(ClientPid, [], Res) ->
- ClientPid ! {self(), Res},
- unlink(ClientPid),
- exit(normal).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Backup traversal
-
-%% Iterate over a backup and produce a new backup.
-%% Fun(BackupItem, Acc) is applied for each BackupItem.
-%%
-%% Valid BackupItems are:
-%%
-%% {schema, Tab} Table to be deleted
-%% {schema, Tab, CreateList} Table to be created, CreateList may be empty
-%% {schema, db_nodes, DbNodes}List of nodes, defaults to [node()] OLD
-%% {schema, version, Version} Schema version OLD
-%% {schema, cookie, Cookie} Unique schema cookie OLD
-%% {Tab, Key} Oid for record to be deleted
-%% Record Record to be inserted.
-%%
-%% The Fun must return a tuple {BackupItems, NewAcc}
-%% where BackupItems is a list of valid BackupItems and
-%% NewAcc is a new accumulator value. Once BackupItems
-%% that not are schema related has been returned, no more schema
-%% items may be returned. The schema related items must always be
-%% first in the backup.
-%%
-%% If TargetMod == read_only, no new backup will be created.
-%%
-%% Opening of the source media will be performed by
-%% to SourceMod:open_read(Source)
-%%
-%% Opening of the target media will be performed by
-%% to TargetMod:open_write(Target)
-traverse_backup(Source, Target, Fun, Acc) ->
- Mod = mnesia_monitor:get_env(backup_module),
- traverse_backup(Source, Mod, Target, Mod, Fun, Acc).
-
-traverse_backup(Source, SourceMod, Target, TargetMod, Fun, Acc) ->
- Args = [self(), Source, SourceMod, Target, TargetMod, Fun, Acc],
- Pid = spawn_link(?MODULE, do_traverse_backup, Args),
- receive
- {'EXIT', Pid, Reason} ->
- {error, {"Backup traversal crashed", Reason}};
- {iter_done, Pid, Res} ->
- Res
- end.
-
-do_traverse_backup(ClientPid, Source, SourceMod, Target, TargetMod, Fun, Acc) ->
- process_flag(trap_exit, true),
- Iter =
- if
- TargetMod /= read_only ->
- case catch do_apply(TargetMod, open_write, [Target], Target) of
- {error, Error} ->
- unlink(ClientPid),
- ClientPid ! {iter_done, self(), {error, Error}},
- exit(Error);
- Else -> Else
- end;
- true ->
- ignore
- end,
- A = {start, Fun, Acc, TargetMod, Iter},
- Res =
- case iterate(SourceMod, fun trav_apply/4, Source, A) of
- {ok, {iter, _, Acc2, _, Iter2}} when TargetMod /= read_only ->
- case catch do_apply(TargetMod, commit_write, [Iter2], Iter2) of
- {error, Reason} ->
- {error, Reason};
- _ ->
- {ok, Acc2}
- end;
- {ok, {iter, _, Acc2, _, _}} ->
- {ok, Acc2};
- {error, Reason} when TargetMod /= read_only->
- catch do_apply(TargetMod, abort_write, [Iter], Iter),
- {error, {"Backup traversal failed", Reason}};
- {error, Reason} ->
- {error, {"Backup traversal failed", Reason}}
- end,
- unlink(ClientPid),
- ClientPid ! {iter_done, self(), Res}.
-
-trav_apply(Recs, _Header, _Schema, {iter, Fun, Acc, Mod, Iter}) ->
- {NewRecs, Acc2} = filter_foldl(Fun, Acc, Recs),
- if
- Mod /= read_only, NewRecs /= [] ->
- Iter2 = do_apply(Mod, write, [Iter, NewRecs], Iter),
- {iter, Fun, Acc2, Mod, Iter2};
- true ->
- {iter, Fun, Acc2, Mod, Iter}
- end;
-trav_apply(Recs, Header, Schema, {start, Fun, Acc, Mod, Iter}) ->
- Iter2 =
- if
- Mod /= read_only ->
- do_apply(Mod, write, [Iter, [Header]], Iter);
- true ->
- Iter
- end,
- TravAcc = trav_apply(Schema, Header, Schema, {iter, Fun, Acc, Mod, Iter2}),
- trav_apply(Recs, Header, Schema, TravAcc).
-
-filter_foldl(Fun, Acc, [Head|Tail]) ->
- case Fun(Head, Acc) of
- {HeadItems, HeadAcc} when list(HeadItems) ->
- {TailItems, TailAcc} = filter_foldl(Fun, HeadAcc, Tail),
- {HeadItems ++ TailItems, TailAcc};
- Other ->
- throw({error, {"Fun must return a list", Other}})
- end;
-filter_foldl(_Fun, Acc, []) ->
- {[], Acc}.
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_checkpoint.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_checkpoint.erl
deleted file mode 100644
index aa2e99642b..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_checkpoint.erl
+++ /dev/null
@@ -1,1284 +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: mnesia_checkpoint.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
-%%
--module(mnesia_checkpoint).
-
-%% TM callback interface
--export([
- tm_add_copy/2,
- tm_change_table_copy_type/3,
- tm_del_copy/2,
- tm_mnesia_down/1,
- tm_prepare/1,
- tm_retain/4,
- tm_retain/5,
- tm_enter_pending/1,
- tm_enter_pending/3,
- tm_exit_pending/1,
- convert_cp_record/1
- ]).
-
-%% Public interface
--export([
- activate/1,
- checkpoints/0,
- deactivate/1,
- deactivate/2,
- iterate/6,
- most_local_node/2,
- really_retain/2,
- stop/0,
- stop_iteration/1,
- tables_and_cookie/1
- ]).
-
-%% Internal
--export([
- call/2,
- cast/2,
- init/1,
- remote_deactivate/1,
- start/1
- ]).
-
-%% sys callback interface
--export([
- system_code_change/4,
- system_continue/3,
- system_terminate/4
- ]).
-
--include("mnesia.hrl").
--import(mnesia_lib, [add/2, del/2, set/2, unset/1]).
--import(mnesia_lib, [dbg_out/2]).
-
--record(tm, {log, pending, transactions, checkpoints}).
-
--record(checkpoint_args, {name = {now(), node()},
- allow_remote = true,
- ram_overrides_dump = false,
- nodes = [],
- node = node(),
- now = now(),
- cookie = ?unique_cookie,
- min = [],
- max = [],
- pending_tab,
- wait_for_old, % Initially undefined then List
- is_activated = false,
- ignore_new = [],
- retainers = [],
- iterators = [],
- supervisor,
- pid
- }).
-
-%% Old record definition
--record(checkpoint, {name,
- allow_remote,
- ram_overrides_dump,
- nodes,
- node,
- now,
- min,
- max,
- pending_tab,
- wait_for_old,
- is_activated,
- ignore_new,
- retainers,
- iterators,
- supervisor,
- pid
- }).
-
--record(retainer, {cp_name, tab_name, store, writers = [], really_retain = true}).
-
--record(iter, {tab_name, oid_tab, main_tab, retainer_tab, source, val, pid}).
-
--record(pending, {tid, disc_nodes = [], ram_nodes = []}).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% TM callback functions
-
-stop() ->
- lists:foreach(fun(Name) -> call(Name, stop) end,
- checkpoints()),
- ok.
-
-tm_prepare(Cp) when record(Cp, checkpoint_args) ->
- Name = Cp#checkpoint_args.name,
- case lists:member(Name, checkpoints()) of
- false ->
- start_retainer(Cp);
- true ->
- {error, {already_exists, Name, node()}}
- end;
-tm_prepare(Cp) when record(Cp, checkpoint) ->
- %% Node with old protocol sent an old checkpoint record
- %% and we have to convert it
- case convert_cp_record(Cp) of
- {ok, NewCp} ->
- tm_prepare(NewCp);
- {error, Reason} ->
- {error, Reason}
- end.
-
-tm_mnesia_down(Node) ->
- lists:foreach(fun(Name) -> cast(Name, {mnesia_down, Node}) end,
- checkpoints()).
-
-%% Returns pending
-tm_enter_pending(Tid, DiscNs, RamNs) ->
- Pending = #pending{tid = Tid, disc_nodes = DiscNs, ram_nodes = RamNs},
- tm_enter_pending(Pending).
-
-tm_enter_pending(Pending) ->
- PendingTabs = val(pending_checkpoints),
- tm_enter_pending(PendingTabs, Pending).
-
-tm_enter_pending([], Pending) ->
- Pending;
-tm_enter_pending([Tab | Tabs], Pending) ->
- catch ?ets_insert(Tab, Pending),
- tm_enter_pending(Tabs, Pending).
-
-tm_exit_pending(Tid) ->
- Pids = val(pending_checkpoint_pids),
- tm_exit_pending(Pids, Tid).
-
-tm_exit_pending([], Tid) ->
- Tid;
-tm_exit_pending([Pid | Pids], Tid) ->
- Pid ! {self(), {exit_pending, Tid}},
- tm_exit_pending(Pids, Tid).
-
-enter_still_pending([Tid | Tids], Tab) ->
- ?ets_insert(Tab, #pending{tid = Tid}),
- enter_still_pending(Tids, Tab);
-enter_still_pending([], _Tab) ->
- ok.
-
-
-%% Looks up checkpoints for functions in mnesia_tm.
-tm_retain(Tid, Tab, Key, Op) ->
- case val({Tab, commit_work}) of
- [{checkpoints, Checkpoints} | _ ] ->
- tm_retain(Tid, Tab, Key, Op, Checkpoints);
- _ ->
- undefined
- end.
-
-tm_retain(Tid, Tab, Key, Op, Checkpoints) ->
- case Op of
- clear_table ->
- OldRecs = mnesia_lib:db_match_object(Tab, '_'),
- send_group_retain(OldRecs, Checkpoints, Tid, Tab, []),
- OldRecs;
- _ ->
- OldRecs = mnesia_lib:db_get(Tab, Key),
- send_retain(Checkpoints, {retain, Tid, Tab, Key, OldRecs}),
- OldRecs
- end.
-
-send_group_retain([Rec | Recs], Checkpoints, Tid, Tab, [PrevRec | PrevRecs])
- when element(2, Rec) /= element(2, PrevRec) ->
- Key = element(2, PrevRec),
- OldRecs = lists:reverse([PrevRec | PrevRecs]),
- send_retain(Checkpoints, {retain, Tid, Tab, Key, OldRecs}),
- send_group_retain(Recs, Checkpoints, Tid, Tab, [Rec]);
-send_group_retain([Rec | Recs], Checkpoints, Tid, Tab, Acc) ->
- send_group_retain(Recs, Checkpoints, Tid, Tab, [Rec | Acc]);
-send_group_retain([], Checkpoints, Tid, Tab, [PrevRec | PrevRecs]) ->
- Key = element(2, PrevRec),
- OldRecs = lists:reverse([PrevRec | PrevRecs]),
- send_retain(Checkpoints, {retain, Tid, Tab, Key, OldRecs}),
- ok;
-send_group_retain([], _Checkpoints, _Tid, _Tab, []) ->
- ok.
-
-send_retain([Name | Names], Msg) ->
- cast(Name, Msg),
- send_retain(Names, Msg);
-send_retain([], _Msg) ->
- ok.
-
-tm_add_copy(Tab, Node) when Node /= node() ->
- case val({Tab, commit_work}) of
- [{checkpoints, Checkpoints} | _ ] ->
- Fun = fun(Name) -> call(Name, {add_copy, Tab, Node}) end,
- map_call(Fun, Checkpoints, ok);
- _ ->
- ok
- end.
-
-tm_del_copy(Tab, Node) when Node == node() ->
- mnesia_subscr:unsubscribe_table(Tab),
- case val({Tab, commit_work}) of
- [{checkpoints, Checkpoints} | _ ] ->
- Fun = fun(Name) -> call(Name, {del_copy, Tab, Node}) end,
- map_call(Fun, Checkpoints, ok);
- _ ->
- ok
- end.
-
-tm_change_table_copy_type(Tab, From, To) ->
- case val({Tab, commit_work}) of
- [{checkpoints, Checkpoints} | _ ] ->
- Fun = fun(Name) -> call(Name, {change_copy, Tab, From, To}) end,
- map_call(Fun, Checkpoints, ok);
- _ ->
- ok
- end.
-
-map_call(Fun, [Name | Names], Res) ->
- case Fun(Name) of
- ok ->
- map_call(Fun, Names, Res);
- {error, {no_exists, Name}} ->
- map_call(Fun, Names, Res);
- {error, Reason} ->
- %% BUGBUG: We may end up with some checkpoint retainers
- %% too much in the add_copy case. How do we remove them?
- map_call(Fun, Names, {error, Reason})
- end;
-map_call(_Fun, [], Res) ->
- Res.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Public functions
-
-deactivate(Name) ->
- case call(Name, get_checkpoint) of
- {error, Reason} ->
- {error, Reason};
- Cp ->
- deactivate(Cp#checkpoint_args.nodes, Name)
- end.
-
-deactivate(Nodes, Name) ->
- rpc:multicall(Nodes, ?MODULE, remote_deactivate, [Name]),
- ok.
-
-remote_deactivate(Name) ->
- call(Name, deactivate).
-
-checkpoints() -> val(checkpoints).
-
-tables_and_cookie(Name) ->
- case call(Name, get_checkpoint) of
- {error, Reason} ->
- {error, Reason};
- Cp ->
- Tabs = Cp#checkpoint_args.min ++ Cp#checkpoint_args.max,
- Cookie = Cp#checkpoint_args.cookie,
- {ok, Tabs, Cookie}
- end.
-
-most_local_node(Name, Tab) ->
- case ?catch_val({Tab, {retainer, Name}}) of
- {'EXIT', _} ->
- {error, {"No retainer attached to table", [Tab, Name]}};
- R ->
- Writers = R#retainer.writers,
- LocalWriter = lists:member(node(), Writers),
- if
- LocalWriter == true ->
- {ok, node()};
- Writers /= [] ->
- {ok, hd(Writers)};
- true ->
- {error, {"No retainer attached to table", [Tab, Name]}}
- end
- end.
-
-really_retain(Name, Tab) ->
- R = val({Tab, {retainer, Name}}),
- R#retainer.really_retain.
-
-%% Activate a checkpoint.
-%%
-%% A checkpoint is a transaction consistent state that may be used to
-%% perform a distributed backup or to rollback the involved tables to
-%% their old state. Backups may also be used to restore tables to
-%% their old state. Args is a list of the following tuples:
-%%
-%% {name, Name}
-%% Name of checkpoint. Each checkpoint must have a name which
-%% is unique on the reachable nodes. The name may be reused when
-%% the checkpoint has been deactivated.
-%% By default a probably unique name is generated.
-%% Multiple checkpoints may be set on the same table.
-%%
-%% {allow_remote, Bool}
-%% false means that all retainers must be local. If the
-%% table does not reside locally, the checkpoint fails.
-%% true allows retainers on other nodes.
-%%
-%% {min, MinTabs}
-%% Minimize redundancy and only keep checkpoint info together with
-%% one replica, preferrably at the local node. If any node involved
-%% the checkpoint goes down, the checkpoint is deactivated.
-%%
-%% {max, MaxTabs}
-%% Maximize redundancy and keep checkpoint info together with all
-%% replicas. The checkpoint becomes more fault tolerant if the
-%% tables has several replicas. When new replicas are added, they
-%% will also get a retainer attached to them.
-%%
-%% {ram_overrides_dump, Bool}
-%% {ram_overrides_dump, Tabs}
-%% Only applicable for ram_copies. Bool controls which versions of
-%% the records that should be included in the checkpoint state.
-%% true means that the latest comitted records in ram (i.e. the
-%% records that the application accesses) should be included
-%% in the checkpoint. false means that the records dumped to
-%% dat-files (the records that will be loaded at startup) should
-%% be included in the checkpoint. Tabs is a list of tables.
-%% Default is false.
-%%
-%% {ignore_new, TidList}
-%% Normally we wait for all pending transactions to complete
-%% before we allow iteration over the checkpoint. But in order
-%% to cope with checkpoint activation inside a transaction that
-%% currently prepares commit (mnesia_init:get_net_work_copy) we
-%% need to have the ability to ignore the enclosing transaction.
-%% We do not wait for the transactions in TidList to end. The
-%% transactions in TidList are regarded as newer than the checkpoint.
-
-activate(Args) ->
- case args2cp(Args) of
- {ok, Cp} ->
- do_activate(Cp);
- {error, Reason} ->
- {error, Reason}
- end.
-
-args2cp(Args) when list(Args)->
- case catch lists:foldl(fun check_arg/2, #checkpoint_args{}, Args) of
- {'EXIT', Reason} ->
- {error, Reason};
- Cp ->
- case check_tables(Cp) of
- {error, Reason} ->
- {error, Reason};
- {ok, Overriders, AllTabs} ->
- arrange_retainers(Cp, Overriders, AllTabs)
- end
- end;
-args2cp(Args) ->
- {error, {badarg, Args}}.
-
-check_arg({name, Name}, Cp) ->
- case lists:member(Name, checkpoints()) of
- true ->
- exit({already_exists, Name});
- false ->
- case catch tab2retainer({foo, Name}) of
- List when list(List) ->
- Cp#checkpoint_args{name = Name};
- _ ->
- exit({badarg, Name})
- end
- end;
-check_arg({allow_remote, true}, Cp) ->
- Cp#checkpoint_args{allow_remote = true};
-check_arg({allow_remote, false}, Cp) ->
- Cp#checkpoint_args{allow_remote = false};
-check_arg({ram_overrides_dump, true}, Cp) ->
- Cp#checkpoint_args{ram_overrides_dump = true};
-check_arg({ram_overrides_dump, false}, Cp) ->
- Cp#checkpoint_args{ram_overrides_dump = false};
-check_arg({ram_overrides_dump, Tabs}, Cp) when list(Tabs) ->
- Cp#checkpoint_args{ram_overrides_dump = Tabs};
-check_arg({min, Tabs}, Cp) when list(Tabs) ->
- Cp#checkpoint_args{min = Tabs};
-check_arg({max, Tabs}, Cp) when list(Tabs) ->
- Cp#checkpoint_args{max = Tabs};
-check_arg({ignore_new, Tids}, Cp) when list(Tids) ->
- Cp#checkpoint_args{ignore_new = Tids};
-check_arg(Arg, _) ->
- exit({badarg, Arg}).
-
-check_tables(Cp) ->
- Min = Cp#checkpoint_args.min,
- Max = Cp#checkpoint_args.max,
- AllTabs = Min ++ Max,
- DoubleTabs = [T || T <- Min, lists:member(T, Max)],
- Overriders = Cp#checkpoint_args.ram_overrides_dump,
- if
- DoubleTabs /= [] ->
- {error, {combine_error, Cp#checkpoint_args.name,
- [{min, DoubleTabs}, {max, DoubleTabs}]}};
- Min == [], Max == [] ->
- {error, {combine_error, Cp#checkpoint_args.name,
- [{min, Min}, {max, Max}]}};
- Overriders == false ->
- {ok, [], AllTabs};
- Overriders == true ->
- {ok, AllTabs, AllTabs};
- list(Overriders) ->
- case [T || T <- Overriders, not lists:member(T, Min)] of
- [] ->
- case [T || T <- Overriders, not lists:member(T, Max)] of
- [] ->
- {ok, Overriders, AllTabs};
- Outsiders ->
- {error, {combine_error, Cp#checkpoint_args.name,
- [{ram_overrides_dump, Outsiders},
- {max, Outsiders}]}}
- end;
- Outsiders ->
- {error, {combine_error, Cp#checkpoint_args.name,
- [{ram_overrides_dump, Outsiders},
- {min, Outsiders}]}}
- end
- end.
-
-arrange_retainers(Cp, Overriders, AllTabs) ->
- R = #retainer{cp_name = Cp#checkpoint_args.name},
- case catch [R#retainer{tab_name = Tab,
- writers = select_writers(Cp, Tab)}
- || Tab <- AllTabs] of
- {'EXIT', Reason} ->
- {error, Reason};
- Retainers ->
- {ok, Cp#checkpoint_args{ram_overrides_dump = Overriders,
- retainers = Retainers,
- nodes = writers(Retainers)}}
- end.
-
-select_writers(Cp, Tab) ->
- case filter_remote(Cp, val({Tab, active_replicas})) of
- [] ->
- exit({"Cannot prepare checkpoint (replica not available)",
- [Tab, Cp#checkpoint_args.name]});
- Writers ->
- This = node(),
- case {lists:member(Tab, Cp#checkpoint_args.max),
- lists:member(This, Writers)} of
- {true, _} -> Writers; % Max
- {false, true} -> [This];
- {false, false} -> [hd(Writers)]
- end
- end.
-
-filter_remote(Cp, Writers) when Cp#checkpoint_args.allow_remote == true ->
- Writers;
-filter_remote(_Cp, Writers) ->
- This = node(),
- case lists:member(This, Writers) of
- true -> [This];
- false -> []
- end.
-
-writers(Retainers) ->
- Fun = fun(R, Acc) -> R#retainer.writers ++ Acc end,
- Writers = lists:foldl(Fun, [], Retainers),
- mnesia_lib:uniq(Writers).
-
-do_activate(Cp) ->
- Name = Cp#checkpoint_args.name,
- Nodes = Cp#checkpoint_args.nodes,
- case mnesia_tm:prepare_checkpoint(Nodes, Cp) of
- {Replies, []} ->
- check_prep(Replies, Name, Nodes, Cp#checkpoint_args.ignore_new);
- {_, BadNodes} ->
- {error, {"Cannot prepare checkpoint (bad nodes)",
- [Name, BadNodes]}}
- end.
-
-check_prep([{ok, Name, IgnoreNew, _Node} | Replies], Name, Nodes, IgnoreNew) ->
- check_prep(Replies, Name, Nodes, IgnoreNew);
-check_prep([{error, Reason} | _Replies], Name, _Nodes, _IgnoreNew) ->
- {error, {"Cannot prepare checkpoint (bad reply)",
- [Name, Reason]}};
-check_prep([{badrpc, Reason} | _Replies], Name, _Nodes, _IgnoreNew) ->
- {error, {"Cannot prepare checkpoint (badrpc)",
- [Name, Reason]}};
-check_prep([], Name, Nodes, IgnoreNew) ->
- collect_pending(Name, Nodes, IgnoreNew).
-
-collect_pending(Name, Nodes, IgnoreNew) ->
- case rpc:multicall(Nodes, ?MODULE, call, [Name, collect_pending]) of
- {Replies, []} ->
- case catch ?ets_new_table(mnesia_union, [bag]) of
- {'EXIT', Reason} -> %% system limit
- Msg = "Cannot create an ets table pending union",
- {error, {system_limit, Msg, Reason}};
- UnionTab ->
- compute_union(Replies, Nodes, Name, UnionTab, IgnoreNew)
- end;
- {_, BadNodes} ->
- deactivate(Nodes, Name),
- {error, {"Cannot collect from pending checkpoint", Name, BadNodes}}
- end.
-
-compute_union([{ok, Pending} | Replies], Nodes, Name, UnionTab, IgnoreNew) ->
- add_pending(Pending, UnionTab),
- compute_union(Replies, Nodes, Name, UnionTab, IgnoreNew);
-compute_union([{error, Reason} | _Replies], Nodes, Name, UnionTab, _IgnoreNew) ->
- deactivate(Nodes, Name),
- ?ets_delete_table(UnionTab),
- {error, Reason};
-compute_union([{badrpc, Reason} | _Replies], Nodes, Name, UnionTab, _IgnoreNew) ->
- deactivate(Nodes, Name),
- ?ets_delete_table(UnionTab),
- {error, {badrpc, Reason}};
-compute_union([], Nodes, Name, UnionTab, IgnoreNew) ->
- send_activate(Nodes, Nodes, Name, UnionTab, IgnoreNew).
-
-add_pending([P | Pending], UnionTab) ->
- add_pending_node(P#pending.disc_nodes, P#pending.tid, UnionTab),
- add_pending_node(P#pending.ram_nodes, P#pending.tid, UnionTab),
- add_pending(Pending, UnionTab);
-add_pending([], _UnionTab) ->
- ok.
-
-add_pending_node([Node | Nodes], Tid, UnionTab) ->
- ?ets_insert(UnionTab, {Node, Tid}),
- add_pending_node(Nodes, Tid, UnionTab);
-add_pending_node([], _Tid, _UnionTab) ->
- ok.
-
-send_activate([Node | Nodes], AllNodes, Name, UnionTab, IgnoreNew) ->
- Pending = [Tid || {_, Tid} <- ?ets_lookup(UnionTab, Node),
- not lists:member(Tid, IgnoreNew)],
- case rpc:call(Node, ?MODULE, call, [Name, {activate, Pending}]) of
- activated ->
- send_activate(Nodes, AllNodes, Name, UnionTab, IgnoreNew);
- {badrpc, Reason} ->
- deactivate(Nodes, Name),
- ?ets_delete_table(UnionTab),
- {error, {"Activation failed (bad node)", Name, Node, Reason}};
- {error, Reason} ->
- deactivate(Nodes, Name),
- ?ets_delete_table(UnionTab),
- {error, {"Activation failed", Name, Node, Reason}}
- end;
-send_activate([], AllNodes, Name, UnionTab, _IgnoreNew) ->
- ?ets_delete_table(UnionTab),
- {ok, Name, AllNodes}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Checkpoint server
-
-cast(Name, Msg) ->
- case ?catch_val({checkpoint, Name}) of
- {'EXIT', _} ->
- {error, {no_exists, Name}};
-
- Pid when pid(Pid) ->
- Pid ! {self(), Msg},
- {ok, Pid}
- end.
-
-call(Name, Msg) ->
- case cast(Name, Msg) of
- {ok, Pid} ->
- catch link(Pid), % Always local
- Self = self(),
- receive
- {'EXIT', Pid, Reason} ->
- {error, {"Got exit", [Name, Reason]}};
- {Name, Self, Reply} ->
- unlink(Pid),
- Reply
- end;
- Error ->
- Error
- end.
-
-abcast(Nodes, Name, Msg) ->
- rpc:eval_everywhere(Nodes, ?MODULE, cast, [Name, Msg]).
-
-reply(nopid, _Name, _Reply) ->
- ignore;
-reply(ReplyTo, Name, Reply) ->
- ReplyTo ! {Name, ReplyTo, Reply}.
-
-%% Returns {ok, NewCp} or {error, Reason}
-start_retainer(Cp) ->
- % Will never be restarted
- Name = Cp#checkpoint_args.name,
- case supervisor:start_child(mnesia_checkpoint_sup, [Cp]) of
- {ok, _Pid} ->
- {ok, Name, Cp#checkpoint_args.ignore_new, node()};
- {error, Reason} ->
- {error, {"Cannot create checkpoint retainer",
- Name, node(), Reason}}
- end.
-
-start(Cp) ->
- Name = Cp#checkpoint_args.name,
- Args = [Cp#checkpoint_args{supervisor = self()}],
- mnesia_monitor:start_proc({?MODULE, Name}, ?MODULE, init, Args).
-
-init(Cp) ->
- process_flag(trap_exit, true),
- Name = Cp#checkpoint_args.name,
- Props = [set, public, {keypos, 2}],
- case catch ?ets_new_table(mnesia_pending_checkpoint, Props) of
- {'EXIT', Reason} -> %% system limit
- Msg = "Cannot create an ets table for pending transactions",
- Error = {error, {system_limit, Name, Msg, Reason}},
- proc_lib:init_ack(Cp#checkpoint_args.supervisor, Error);
- PendingTab ->
- Rs = [prepare_tab(Cp, R) || R <- Cp#checkpoint_args.retainers],
- Cp2 = Cp#checkpoint_args{retainers = Rs,
- pid = self(),
- pending_tab = PendingTab},
- add(pending_checkpoint_pids, self()),
- add(pending_checkpoints, PendingTab),
- set({checkpoint, Name}, self()),
- add(checkpoints, Name),
- dbg_out("Checkpoint ~p (~p) started~n", [Name, self()]),
- proc_lib:init_ack(Cp2#checkpoint_args.supervisor, {ok, self()}),
- retainer_loop(Cp2)
- end.
-
-prepare_tab(Cp, R) ->
- Tab = R#retainer.tab_name,
- prepare_tab(Cp, R, val({Tab, storage_type})).
-
-prepare_tab(Cp, R, Storage) ->
- Tab = R#retainer.tab_name,
- Name = R#retainer.cp_name,
- case lists:member(node(), R#retainer.writers) of
- true ->
- R2 = retainer_create(Cp, R, Tab, Name, Storage),
- set({Tab, {retainer, Name}}, R2),
- add({Tab, checkpoints}, Name), %% Keep checkpoint info for table_info & mnesia_session
- add_chkp_info(Tab, Name),
- R2;
- false ->
- set({Tab, {retainer, Name}}, R#retainer{store = undefined}),
- R
- end.
-
-add_chkp_info(Tab, Name) ->
- case val({Tab, commit_work}) of
- [{checkpoints, OldList} | CommitList] ->
- case lists:member(Name, OldList) of
- true ->
- ok;
- false ->
- NewC = [{checkpoints, [Name | OldList]} | CommitList],
- mnesia_lib:set({Tab, commit_work}, NewC)
- end;
- CommitList ->
- Chkp = {checkpoints, [Name]},
- %% OBS checkpoints needs to be first in the list!
- mnesia_lib:set({Tab, commit_work}, [Chkp | CommitList])
- end.
-
-tab2retainer({Tab, Name}) ->
- FlatName = lists:flatten(io_lib:write(Name)),
- mnesia_lib:dir(lists:concat([?MODULE, "_", Tab, "_", FlatName, ".RET"])).
-
-retainer_create(_Cp, R, Tab, Name, disc_only_copies) ->
- Fname = tab2retainer({Tab, Name}),
- file:delete(Fname),
- Args = [{file, Fname}, {type, set}, {keypos, 2}, {repair, false}],
- {ok, _} = mnesia_lib:dets_sync_open({Tab, Name}, Args),
- dbg_out("Checkpoint retainer created ~p ~p~n", [Name, Tab]),
- R#retainer{store = {dets, {Tab, Name}}, really_retain = true};
-retainer_create(Cp, R, Tab, Name, Storage) ->
- T = ?ets_new_table(mnesia_retainer, [set, public, {keypos, 2}]),
- Overriders = Cp#checkpoint_args.ram_overrides_dump,
- ReallyR = R#retainer.really_retain,
- ReallyCp = lists:member(Tab, Overriders),
- ReallyR2 = prepare_ram_tab(Tab, T, Storage, ReallyR, ReallyCp),
- dbg_out("Checkpoint retainer created ~p ~p~n", [Name, Tab]),
- R#retainer{store = {ets, T}, really_retain = ReallyR2}.
-
-%% Copy the dumped table into retainer if needed
-%% If the really_retain flag already has been set to false,
-%% it should remain false even if we change storage type
-%% while the checkpoint is activated.
-prepare_ram_tab(Tab, T, ram_copies, true, false) ->
- Fname = mnesia_lib:tab2dcd(Tab),
- case mnesia_lib:exists(Fname) of
- true ->
- Log = mnesia_log:open_log(prepare_ram_tab,
- mnesia_log:dcd_log_header(),
- Fname, true,
- mnesia_monitor:get_env(auto_repair),
- read_only),
- Add = fun(Rec) ->
- Key = element(2, Rec),
- Recs =
- case ?ets_lookup(T, Key) of
- [] -> [];
- [{_, _, Old}] -> Old
- end,
- ?ets_insert(T, {Tab, Key, [Rec | Recs]}),
- continue
- end,
- traverse_dcd(mnesia_log:chunk_log(Log, start), Log, Add),
- mnesia_log:close_log(Log);
- false ->
- ok
- end,
- false;
-prepare_ram_tab(_, _, _, ReallyRetain, _) ->
- ReallyRetain.
-
-traverse_dcd({Cont, [LogH | Rest]}, Log, Fun)
- when record(LogH, log_header),
- LogH#log_header.log_kind == dcd_log,
- LogH#log_header.log_version >= "1.0" ->
- traverse_dcd({Cont, Rest}, Log, Fun); %% BUGBUG Error handling repaired files
-traverse_dcd({Cont, Recs}, Log, Fun) -> %% trashed data??
- lists:foreach(Fun, Recs),
- traverse_dcd(mnesia_log:chunk_log(Log, Cont), Log, Fun);
-traverse_dcd(eof, _Log, _Fun) ->
- ok.
-
-retainer_get({ets, Store}, Key) -> ?ets_lookup(Store, Key);
-retainer_get({dets, Store}, Key) -> dets:lookup(Store, Key).
-
-retainer_put({ets, Store}, Val) -> ?ets_insert(Store, Val);
-retainer_put({dets, Store}, Val) -> dets:insert(Store, Val).
-
-retainer_first({ets, Store}) -> ?ets_first(Store);
-retainer_first({dets, Store}) -> dets:first(Store).
-
-retainer_next({ets, Store}, Key) -> ?ets_next(Store, Key);
-retainer_next({dets, Store}, Key) -> dets:next(Store, Key).
-
-%% retainer_next_slot(Tab, Pos) ->
-%% case retainer_slot(Tab, Pos) of
-%% '$end_of_table' ->
-%% '$end_of_table';
-%% [] ->
-%% retainer_next_slot(Tab, Pos + 1);
-%% Recs when list(Recs) ->
-%% {Pos, Recs}
-%% end.
-%%
-%% retainer_slot({ets, Store}, Pos) -> ?ets_next(Store, Pos);
-%% retainer_slot({dets, Store}, Pos) -> dets:slot(Store, Pos).
-
-retainer_fixtable(Tab, Bool) when atom(Tab) ->
- mnesia_lib:db_fixtable(val({Tab, storage_type}), Tab, Bool);
-retainer_fixtable({ets, Tab}, Bool) ->
- mnesia_lib:db_fixtable(ram_copies, Tab, Bool);
-retainer_fixtable({dets, Tab}, Bool) ->
- mnesia_lib:db_fixtable(disc_only_copies, Tab, Bool).
-
-retainer_delete({ets, Store}) ->
- ?ets_delete_table(Store);
-retainer_delete({dets, Store}) ->
- mnesia_lib:dets_sync_close(Store),
- Fname = tab2retainer(Store),
- file:delete(Fname).
-
-retainer_loop(Cp) ->
- Name = Cp#checkpoint_args.name,
- receive
- {_From, {retain, Tid, Tab, Key, OldRecs}}
- when Cp#checkpoint_args.wait_for_old == [] ->
- R = val({Tab, {retainer, Name}}),
- case R#retainer.really_retain of
- true ->
- PendingTab = Cp#checkpoint_args.pending_tab,
- case catch ?ets_lookup_element(PendingTab, Tid, 1) of
- {'EXIT', _} ->
- Store = R#retainer.store,
- case retainer_get(Store, Key) of
- [] ->
- retainer_put(Store, {Tab, Key, OldRecs});
- _ ->
- already_retained
- end;
- pending ->
- ignore
- end;
- false ->
- ignore
- end,
- retainer_loop(Cp);
-
- %% Adm
- {From, deactivate} ->
- do_stop(Cp),
- reply(From, Name, deactivated),
- unlink(From),
- exit(shutdown);
-
- {'EXIT', Parent, _} when Parent == Cp#checkpoint_args.supervisor ->
- %% do_stop(Cp),
- %% assume that entire Mnesia is terminating
- exit(shutdown);
-
- {_From, {mnesia_down, Node}} ->
- Cp2 = do_del_retainers(Cp, Node),
- retainer_loop(Cp2);
- {From, get_checkpoint} ->
- reply(From, Name, Cp),
- retainer_loop(Cp);
- {From, {add_copy, Tab, Node}} when Cp#checkpoint_args.wait_for_old == [] ->
- {Res, Cp2} = do_add_copy(Cp, Tab, Node),
- reply(From, Name, Res),
- retainer_loop(Cp2);
- {From, {del_copy, Tab, Node}} when Cp#checkpoint_args.wait_for_old == [] ->
- Cp2 = do_del_copy(Cp, Tab, Node),
- reply(From, Name, ok),
- retainer_loop(Cp2);
- {From, {change_copy, Tab, From, To}} when Cp#checkpoint_args.wait_for_old == [] ->
- Cp2 = do_change_copy(Cp, Tab, From, To),
- reply(From, Name, ok),
- retainer_loop(Cp2);
- {_From, {add_retainer, R, Node}} ->
- Cp2 = do_add_retainer(Cp, R, Node),
- retainer_loop(Cp2);
- {_From, {del_retainer, R, Node}} when Cp#checkpoint_args.wait_for_old == [] ->
- Cp2 = do_del_retainer(Cp, R, Node),
- retainer_loop(Cp2);
-
- %% Iteration
- {From, {iter_begin, Iter}} when Cp#checkpoint_args.wait_for_old == [] ->
- Cp2 = iter_begin(Cp, From, Iter),
- retainer_loop(Cp2);
-
- {From, {iter_end, Iter}} when Cp#checkpoint_args.wait_for_old == [] ->
- retainer_fixtable(Iter#iter.oid_tab, false),
- Iters = Cp#checkpoint_args.iterators -- [Iter],
- reply(From, Name, ok),
- retainer_loop(Cp#checkpoint_args{iterators = Iters});
-
- {_From, {exit_pending, Tid}}
- when list(Cp#checkpoint_args.wait_for_old) ->
- StillPending = lists:delete(Tid, Cp#checkpoint_args.wait_for_old),
- Cp2 = Cp#checkpoint_args{wait_for_old = StillPending},
- Cp3 = maybe_activate(Cp2),
- retainer_loop(Cp3);
-
- {From, collect_pending} ->
- PendingTab = Cp#checkpoint_args.pending_tab,
- del(pending_checkpoints, PendingTab),
- Pending = ?ets_match_object(PendingTab, '_'),
- reply(From, Name, {ok, Pending}),
- retainer_loop(Cp);
-
- {From, {activate, Pending}} ->
- StillPending = mnesia_recover:still_pending(Pending),
- enter_still_pending(StillPending, Cp#checkpoint_args.pending_tab),
- Cp2 = maybe_activate(Cp#checkpoint_args{wait_for_old = StillPending}),
- reply(From, Name, activated),
- retainer_loop(Cp2);
-
- {'EXIT', From, _Reason} ->
- Iters = [Iter || Iter <- Cp#checkpoint_args.iterators,
- check_iter(From, Iter)],
- retainer_loop(Cp#checkpoint_args{iterators = Iters});
-
- {system, From, Msg} ->
- dbg_out("~p got {system, ~p, ~p}~n", [?MODULE, From, Msg]),
- sys:handle_system_msg(Msg, From, no_parent, ?MODULE, [], Cp)
- end.
-
-maybe_activate(Cp)
- when Cp#checkpoint_args.wait_for_old == [],
- Cp#checkpoint_args.is_activated == false ->
- Cp#checkpoint_args{pending_tab = undefined, is_activated = true};
-maybe_activate(Cp) ->
- Cp.
-
-iter_begin(Cp, From, Iter) ->
- Name = Cp#checkpoint_args.name,
- R = val({Iter#iter.tab_name, {retainer, Name}}),
- Iter2 = init_tabs(R, Iter),
- Iter3 = Iter2#iter{pid = From},
- retainer_fixtable(Iter3#iter.oid_tab, true),
- Iters = [Iter3 | Cp#checkpoint_args.iterators],
- reply(From, Name, {ok, Iter3, self()}),
- Cp#checkpoint_args{iterators = Iters}.
-
-do_stop(Cp) ->
- Name = Cp#checkpoint_args.name,
- del(pending_checkpoints, Cp#checkpoint_args.pending_tab),
- del(pending_checkpoint_pids, self()),
- del(checkpoints, Name),
- unset({checkpoint, Name}),
- lists:foreach(fun deactivate_tab/1, Cp#checkpoint_args.retainers),
- Iters = Cp#checkpoint_args.iterators,
- lists:foreach(fun(I) -> retainer_fixtable(I#iter.oid_tab, false) end, Iters).
-
-deactivate_tab(R) ->
- Name = R#retainer.cp_name,
- Tab = R#retainer.tab_name,
- del({Tab, checkpoints}, Name), %% Keep checkpoint info for table_info & mnesia_session
- del_chkp_info(Tab, Name),
- unset({Tab, {retainer, Name}}),
- Active = lists:member(node(), R#retainer.writers),
- case R#retainer.store of
- undefined ->
- ignore;
- Store when Active == true ->
- retainer_delete(Store);
- _ ->
- ignore
- end.
-
-del_chkp_info(Tab, Name) ->
- case val({Tab, commit_work}) of
- [{checkpoints, ChkList} | Rest] ->
- case lists:delete(Name, ChkList) of
- [] ->
- %% The only checkpoint was deleted
- mnesia_lib:set({Tab, commit_work}, Rest);
- NewList ->
- mnesia_lib:set({Tab, commit_work},
- [{checkpoints, NewList} | Rest])
- end;
- _ -> ignore
- end.
-
-do_del_retainers(Cp, Node) ->
- Rs = [do_del_retainer2(Cp, R, Node) || R <- Cp#checkpoint_args.retainers],
- Cp#checkpoint_args{retainers = Rs, nodes = writers(Rs)}.
-
-do_del_retainer2(Cp, R, Node) ->
- Writers = R#retainer.writers -- [Node],
- R2 = R#retainer{writers = Writers},
- set({R2#retainer.tab_name, {retainer, R2#retainer.cp_name}}, R2),
- if
- Writers == [] ->
- Event = {mnesia_checkpoint_deactivated, Cp#checkpoint_args.name},
- mnesia_lib:report_system_event(Event),
- do_stop(Cp),
- exit(shutdown);
- Node == node() ->
- deactivate_tab(R), % Avoids unnecessary tm_retain accesses
- set({R2#retainer.tab_name, {retainer, R2#retainer.cp_name}}, R2),
- R2;
- true ->
- R2
- end.
-
-do_del_retainer(Cp, R0, Node) ->
- {R, Rest} = find_retainer(R0, Cp#checkpoint_args.retainers, []),
- R2 = do_del_retainer2(Cp, R, Node),
- Rs = [R2|Rest],
- Cp#checkpoint_args{retainers = Rs, nodes = writers(Rs)}.
-
-do_del_copy(Cp, Tab, ThisNode) when ThisNode == node() ->
- Name = Cp#checkpoint_args.name,
- Others = Cp#checkpoint_args.nodes -- [ThisNode],
- R = val({Tab, {retainer, Name}}),
- abcast(Others, Name, {del_retainer, R, ThisNode}),
- do_del_retainer(Cp, R, ThisNode).
-
-do_add_copy(Cp, Tab, Node) when Node /= node()->
- case lists:member(Tab, Cp#checkpoint_args.max) of
- false ->
- {ok, Cp};
- true ->
- Name = Cp#checkpoint_args.name,
- R0 = val({Tab, {retainer, Name}}),
- W = R0#retainer.writers,
- R = R0#retainer{writers = W ++ [Node]},
-
- case lists:member(Node, Cp#checkpoint_args.nodes) of
- true ->
- send_retainer(Cp, R, Node);
- false ->
- case tm_remote_prepare(Node, Cp) of
- {ok, Name, _IgnoreNew, Node} ->
- case lists:member(schema, Cp#checkpoint_args.max) of
- true ->
- %% We need to send schema retainer somewhere
- RS0 = val({schema, {retainer, Name}}),
- W = RS0#retainer.writers,
- RS1 = RS0#retainer{writers = W ++ [Node]},
- case send_retainer(Cp, RS1, Node) of
- {ok, Cp1} ->
- send_retainer(Cp1, R, Node);
- Error ->
- Error
- end;
- false ->
- send_retainer(Cp, R, Node)
- end;
- {badrpc, Reason} ->
- {{error, {badrpc, Reason}}, Cp};
- {error, Reason} ->
- {{error, Reason}, Cp}
- end
- end
- end.
-
-tm_remote_prepare(Node, Cp) ->
- rpc:call(Node, ?MODULE, tm_prepare, [Cp]).
-
-do_add_retainer(Cp, R0, Node) ->
- Writers = R0#retainer.writers,
- {R, Rest} = find_retainer(R0, Cp#checkpoint_args.retainers, []),
- NewRet =
- if
- Node == node() ->
- prepare_tab(Cp, R#retainer{writers = Writers});
- true ->
- R#retainer{writers = Writers}
- end,
- Rs = [NewRet | Rest],
- set({NewRet#retainer.tab_name, {retainer, NewRet#retainer.cp_name}}, NewRet),
- Cp#checkpoint_args{retainers = Rs, nodes = writers(Rs)}.
-
-find_retainer(#retainer{cp_name = CP, tab_name = Tab},
- [Ret = #retainer{cp_name = CP, tab_name = Tab} | R], Acc) ->
- {Ret, R ++ Acc};
-find_retainer(Ret, [H|R], Acc) ->
- find_retainer(Ret, R, [H|Acc]).
-
-send_retainer(Cp, R, Node) ->
- Name = Cp#checkpoint_args.name,
- Nodes0 = Cp#checkpoint_args.nodes -- [Node],
- Nodes1 = Nodes0 ++ [Node],
- Nodes = Nodes1 -- [node()],
- abcast(Nodes, Name, {add_retainer, R, Node}),
- Store = R#retainer.store,
-%% send_retainer2(Node, Name, Store, retainer_next_slot(Store, 0)),
- send_retainer2(Node, Name, Store, retainer_first(Store)),
- Cp2 = do_add_retainer(Cp, R, Node),
- {ok, Cp2}.
-
-send_retainer2(_, _, _, '$end_of_table') ->
- ok;
-%%send_retainer2(Node, Name, Store, {Slot, Records}) ->
-send_retainer2(Node, Name, Store, Key) ->
- [{Tab, _, Records}] = retainer_get(Store, Key),
- abcast([Node], Name, {retain, {dirty, send_retainer}, Tab, Key, Records}),
- send_retainer2(Node, Name, Store, retainer_next(Store, Key)).
-
-do_change_copy(Cp, Tab, FromType, ToType) ->
- Name = Cp#checkpoint_args.name,
- R = val({Tab, {retainer, Name}}),
- R2 = prepare_tab(Cp, R, ToType),
- {_, Old} = R#retainer.store,
- {_, New} = R2#retainer.store,
-
- Fname = tab2retainer({Tab, Name}),
- if
- FromType == disc_only_copies ->
- mnesia_lib:dets_sync_close(Old),
- loaded = mnesia_lib:dets_to_ets(Old, New, Fname, set, no, yes),
- ok = file:delete(Fname);
- ToType == disc_only_copies ->
- TabSize = ?ets_info(Old, size),
- Props = [{file, Fname},
- {type, set},
- {keypos, 2},
-%% {ram_file, true},
- {estimated_no_objects, TabSize + 256},
- {repair, false}],
- {ok, _} = mnesia_lib:dets_sync_open(New, Props),
- ok = mnesia_dumper:raw_dump_table(New, Old),
- ?ets_delete_table(Old);
- true ->
- ignore
- end,
- Pos = #retainer.tab_name,
- Rs = lists:keyreplace(Tab, Pos, Cp#checkpoint_args.retainers, R2),
- Cp#checkpoint_args{retainers = Rs, nodes = writers(Rs)}.
-
-check_iter(From, Iter) when Iter#iter.pid == From ->
- retainer_fixtable(Iter#iter.oid_tab, false),
- false;
-check_iter(_From, _Iter) ->
- true.
-
-init_tabs(R, Iter) ->
- {Kind, _} = Store = R#retainer.store,
- Main = {Kind, Iter#iter.tab_name},
- Ret = Store,
- Iter2 = Iter#iter{main_tab = Main, retainer_tab = Ret},
- case Iter#iter.source of
- table -> Iter2#iter{oid_tab = Main};
- retainer -> Iter2#iter{oid_tab = Ret}
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Iteration
-%%
-%% Iterates over a table and applies Fun(ListOfRecords)
-%% with a suitable amount of records, e.g. 1000 or so.
-%% ListOfRecords is [] when the iteration is over.
-%%
-%% OidKind affects which internal table to be iterated over and
-%% ValKind affects which table to pick the actual records from. Legal
-%% values for OidKind and ValKind is the atom table or the atom
-%% retainer.
-%%
-%% The iteration may either be performed over the main table (which
-%% contains the latest values of the records, i.e. the values that
-%% are visible to the applications) or over the checkpoint retainer
-%% (which contains the values as the looked like the timepoint when
-%% the checkpoint was activated).
-%%
-%% It is possible to iterate over the main table and pick values
-%% from the retainer and vice versa.
-
-iterate(Name, Tab, Fun, Acc, Source, Val) ->
- Iter0 = #iter{tab_name = Tab, source = Source, val = Val},
- case call(Name, {iter_begin, Iter0}) of
- {error, Reason} ->
- {error, Reason};
- {ok, Iter, Pid} ->
- link(Pid), % We don't want any pending fixtable's
- Res = (catch iter(Fun, Acc, Iter)),
- unlink(Pid),
- call(Name, {iter_end, Iter}),
- case Res of
- {'EXIT', Reason} -> {error, Reason};
- {error, Reason} -> {error, Reason};
- Acc2 -> {ok, Acc2}
- end
- end.
-
-iter(Fun, Acc, Iter)->
- iter(Fun, Acc, Iter, retainer_first(Iter#iter.oid_tab)).
-
-iter(Fun, Acc, Iter, Key) ->
- case get_records(Iter, Key) of
- {'$end_of_table', []} ->
- Fun([], Acc);
- {'$end_of_table', Records} ->
- Acc2 = Fun(Records, Acc),
- Fun([], Acc2);
- {Next, Records} ->
- Acc2 = Fun(Records, Acc),
- iter(Fun, Acc2, Iter, Next)
- end.
-
-stop_iteration(Reason) ->
- throw({error, {stopped, Reason}}).
-
-get_records(Iter, Key) ->
- get_records(Iter, Key, 500, []). % 500 keys
-
-get_records(_Iter, Key, 0, Acc) ->
- {Key, lists:append(lists:reverse(Acc))};
-get_records(_Iter, '$end_of_table', _I, Acc) ->
- {'$end_of_table', lists:append(lists:reverse(Acc))};
-get_records(Iter, Key, I, Acc) ->
- Recs = get_val(Iter, Key),
- Next = retainer_next(Iter#iter.oid_tab, Key),
- get_records(Iter, Next, I-1, [Recs | Acc]).
-
-get_val(Iter, Key) when Iter#iter.val == latest ->
- get_latest_val(Iter, Key);
-get_val(Iter, Key) when Iter#iter.val == checkpoint ->
- get_checkpoint_val(Iter, Key).
-
-get_latest_val(Iter, Key) when Iter#iter.source == table ->
- retainer_get(Iter#iter.main_tab, Key);
-get_latest_val(Iter, Key) when Iter#iter.source == retainer ->
- DeleteOid = {Iter#iter.tab_name, Key},
- [DeleteOid | retainer_get(Iter#iter.main_tab, Key)].
-
-get_checkpoint_val(Iter, Key) when Iter#iter.source == table ->
- retainer_get(Iter#iter.main_tab, Key);
-get_checkpoint_val(Iter, Key) when Iter#iter.source == retainer ->
- DeleteOid = {Iter#iter.tab_name, Key},
- case retainer_get(Iter#iter.retainer_tab, Key) of
- [{_, _, []}] -> [DeleteOid];
- [{_, _, Records}] -> [DeleteOid | Records]
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% System upgrade
-
-system_continue(_Parent, _Debug, Cp) ->
- retainer_loop(Cp).
-
-system_terminate(_Reason, _Parent,_Debug, Cp) ->
- do_stop(Cp).
-
-system_code_change(Cp, _Module, _OldVsn, _Extra) ->
- {ok, Cp}.
-
-convert_cp_record(Cp) when record(Cp, checkpoint) ->
- ROD =
- case Cp#checkpoint.ram_overrides_dump of
- true -> Cp#checkpoint.min ++ Cp#checkpoint.max;
- false -> []
- end,
-
- {ok, #checkpoint_args{name = Cp#checkpoint.name,
- allow_remote = Cp#checkpoint.name,
- ram_overrides_dump = ROD,
- nodes = Cp#checkpoint.nodes,
- node = Cp#checkpoint.node,
- now = Cp#checkpoint.now,
- cookie = ?unique_cookie,
- min = Cp#checkpoint.min,
- max = Cp#checkpoint.max,
- pending_tab = Cp#checkpoint.pending_tab,
- wait_for_old = Cp#checkpoint.wait_for_old,
- is_activated = Cp#checkpoint.is_activated,
- ignore_new = Cp#checkpoint.ignore_new,
- retainers = Cp#checkpoint.retainers,
- iterators = Cp#checkpoint.iterators,
- supervisor = Cp#checkpoint.supervisor,
- pid = Cp#checkpoint.pid
- }};
-convert_cp_record(Cp) when record(Cp, checkpoint_args) ->
- AllTabs = Cp#checkpoint_args.min ++ Cp#checkpoint_args.max,
- ROD = case Cp#checkpoint_args.ram_overrides_dump of
- [] ->
- false;
- AllTabs ->
- true;
- _ ->
- error
- end,
- if
- ROD == error ->
- {error, {"Old node cannot handle new checkpoint protocol",
- ram_overrides_dump}};
- true ->
- {ok, #checkpoint{name = Cp#checkpoint_args.name,
- allow_remote = Cp#checkpoint_args.name,
- ram_overrides_dump = ROD,
- nodes = Cp#checkpoint_args.nodes,
- node = Cp#checkpoint_args.node,
- now = Cp#checkpoint_args.now,
- min = Cp#checkpoint_args.min,
- max = Cp#checkpoint_args.max,
- pending_tab = Cp#checkpoint_args.pending_tab,
- wait_for_old = Cp#checkpoint_args.wait_for_old,
- is_activated = Cp#checkpoint_args.is_activated,
- ignore_new = Cp#checkpoint_args.ignore_new,
- retainers = Cp#checkpoint_args.retainers,
- iterators = Cp#checkpoint_args.iterators,
- supervisor = Cp#checkpoint_args.supervisor,
- pid = Cp#checkpoint_args.pid
- }}
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _ReASoN_} -> mnesia_lib:other_val(Var, _ReASoN_);
- _VaLuE_ -> _VaLuE_
- end.
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_checkpoint_sup.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_checkpoint_sup.erl
deleted file mode 100644
index 29e31f15a6..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_checkpoint_sup.erl
+++ /dev/null
@@ -1,39 +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: mnesia_checkpoint_sup.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
-%%
--module(mnesia_checkpoint_sup).
-
--behaviour(supervisor).
-
--export([start/0, init/1]).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% top supervisor callback functions
-
-start() ->
- supervisor:start_link({local, ?MODULE}, ?MODULE, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% sub supervisor callback functions
-
-init([]) ->
- Flags = {simple_one_for_one, 0, timer:hours(24)}, % Trust the top supervisor
- MFA = {mnesia_checkpoint, start, []},
- Modules = [?MODULE, mnesia_checkpoint, supervisor],
- KillAfter = mnesia_kernel_sup:supervisor_timeout(timer:seconds(3)),
- Workers = [{?MODULE, MFA, transient, KillAfter, worker, Modules}],
- {ok, {Flags, Workers}}.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_controller.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_controller.erl
deleted file mode 100644
index b6f865f0d4..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_controller.erl
+++ /dev/null
@@ -1,2012 +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: mnesia_controller.erl,v 1.3 2010/03/04 13:54:19 maria Exp $
-%%
-%% The mnesia_init process loads tables from local disc or from
-%% another nodes. It also coordinates updates of the info about
-%% where we can read and write tables.
-%%
-%% Tables may need to be loaded initially at startup of the local
-%% node or when other nodes announces that they already have loaded
-%% tables that we also want.
-%%
-%% Initially we set the load request queue to those tables that we
-%% safely can load locally, i.e. tables where we have the last
-%% consistent replica and we have received mnesia_down from all
-%% other nodes holding the table. Then we let the mnesia_init
-%% process enter its normal working state.
-%%
-%% When we need to load a table we append a request to the load
-%% request queue. All other requests are regarded as high priority
-%% and are processed immediately (e.g. update table whereabouts).
-%% We processes the load request queue as a "background" job..
-
--module(mnesia_controller).
-
--behaviour(gen_server).
-
-%% Mnesia internal stuff
--export([
- start/0,
- i_have_tab/1,
- info/0,
- get_info/1,
- get_workers/1,
- force_load_table/1,
- async_dump_log/1,
- sync_dump_log/1,
- connect_nodes/1,
- wait_for_schema_commit_lock/0,
- release_schema_commit_lock/0,
- create_table/1,
- get_disc_copy/1,
- get_cstructs/0,
- sync_and_block_table_whereabouts/4,
- sync_del_table_copy_whereabouts/2,
- block_table/1,
- unblock_table/1,
- block_controller/0,
- unblock_controller/0,
- unannounce_add_table_copy/2,
- master_nodes_updated/2,
- mnesia_down/1,
- add_active_replica/2,
- add_active_replica/3,
- add_active_replica/4,
- change_table_access_mode/1,
- del_active_replica/2,
- wait_for_tables/2,
- get_network_copy/2,
- merge_schema/0,
- start_remote_sender/4,
- schedule_late_disc_load/2
- ]).
-
-%% gen_server callbacks
--export([init/1,
- handle_call/3,
- handle_cast/2,
- handle_info/2,
- terminate/2,
- code_change/3]).
-
-%% Module internal stuff
--export([call/1,
- cast/1,
- dump_and_reply/2,
- load_and_reply/2,
- send_and_reply/2,
- wait_for_tables_init/2
- ]).
-
--import(mnesia_lib, [set/2, add/2]).
--import(mnesia_lib, [fatal/2, error/2, verbose/2, dbg_out/2]).
-
--include("mnesia.hrl").
-
--define(SERVER_NAME, ?MODULE).
-
--record(state, {supervisor,
- schema_is_merged = false,
- early_msgs = [],
- loader_pid,
- loader_queue = [],
- sender_pid,
- sender_queue = [],
- late_loader_queue = [],
- dumper_pid, % Dumper or schema commit pid
- dumper_queue = [], % Dumper or schema commit queue
- dump_log_timer_ref,
- is_stopping = false
- }).
-
--record(worker_reply, {what,
- pid,
- result
- }).
-
--record(schema_commit_lock, {owner}).
--record(block_controller, {owner}).
-
--record(dump_log, {initiated_by,
- opt_reply_to
- }).
-
--record(net_load, {table,
- reason,
- opt_reply_to,
- cstruct = unknown
- }).
-
--record(send_table, {table,
- receiver_pid,
- remote_storage
- }).
-
--record(disc_load, {table,
- reason,
- opt_reply_to
- }).
-
--record(late_load, {table,
- reason,
- opt_reply_to,
- loaders
- }).
-
--record(loader_done, {worker_pid,
- is_loaded,
- table_name,
- needs_announce,
- needs_sync,
- needs_reply,
- reply_to,
- reply}).
-
--record(sender_done, {worker_pid,
- worker_res,
- table_name
- }).
-
--record(dumper_done, {worker_pid,
- worker_res
- }).
-
-val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
- Value -> Value
- end.
-
-start() ->
- gen_server:start_link({local, ?SERVER_NAME}, ?MODULE, [self()],
- [{timeout, infinity}
- %% ,{debug, [trace]}
- ]).
-
-sync_dump_log(InitBy) ->
- call({sync_dump_log, InitBy}).
-
-async_dump_log(InitBy) ->
- ?SERVER_NAME ! {async_dump_log, InitBy}.
-
-%% Wait for tables to be active
-%% If needed, we will wait for Mnesia to start
-%% If Mnesia stops, we will wait for Mnesia to restart
-%% We will wait even if the list of tables is empty
-%%
-wait_for_tables(Tabs, Timeout) when list(Tabs), Timeout == infinity ->
- do_wait_for_tables(Tabs, Timeout);
-wait_for_tables(Tabs, Timeout) when list(Tabs),
- integer(Timeout), Timeout >= 0 ->
- do_wait_for_tables(Tabs, Timeout);
-wait_for_tables(Tabs, Timeout) ->
- {error, {badarg, Tabs, Timeout}}.
-
-do_wait_for_tables(Tabs, 0) ->
- reply_wait(Tabs);
-do_wait_for_tables(Tabs, Timeout) ->
- Pid = spawn_link(?MODULE, wait_for_tables_init, [self(), Tabs]),
- receive
- {?SERVER_NAME, Pid, Res} ->
- Res;
-
- {'EXIT', Pid, _} ->
- reply_wait(Tabs)
-
- after Timeout ->
- unlink(Pid),
- exit(Pid, timeout),
- reply_wait(Tabs)
- end.
-
-reply_wait(Tabs) ->
- case catch mnesia_lib:active_tables() of
- {'EXIT', _} ->
- {error, {node_not_running, node()}};
- Active when list(Active) ->
- case Tabs -- Active of
- [] ->
- ok;
- BadTabs ->
- {timeout, BadTabs}
- end
- end.
-
-wait_for_tables_init(From, Tabs) ->
- process_flag(trap_exit, true),
- Res = wait_for_init(From, Tabs, whereis(?SERVER_NAME)),
- From ! {?SERVER_NAME, self(), Res},
- unlink(From),
- exit(normal).
-
-wait_for_init(From, Tabs, Init) ->
- case catch link(Init) of
- {'EXIT', _} ->
- %% Mnesia is not started
- {error, {node_not_running, node()}};
- true when pid(Init) ->
- cast({sync_tabs, Tabs, self()}),
- rec_tabs(Tabs, Tabs, From, Init)
- end.
-
-sync_reply(Waiter, Tab) ->
- Waiter ! {?SERVER_NAME, {tab_synced, Tab}}.
-
-rec_tabs([Tab | Tabs], AllTabs, From, Init) ->
- receive
- {?SERVER_NAME, {tab_synced, Tab}} ->
- rec_tabs(Tabs, AllTabs, From, Init);
-
- {'EXIT', From, _} ->
- %% This will trigger an exit signal
- %% to mnesia_init
- exit(wait_for_tables_timeout);
-
- {'EXIT', Init, _} ->
- %% Oops, mnesia_init stopped,
- exit(mnesia_stopped)
- end;
-rec_tabs([], _, _, Init) ->
- unlink(Init),
- ok.
-
-get_cstructs() ->
- call(get_cstructs).
-
-mnesia_down(Node) ->
- case cast({mnesia_down, Node}) of
- {error, _} -> mnesia_monitor:mnesia_down(?SERVER_NAME, Node);
- _Pid -> ok
- end.
-wait_for_schema_commit_lock() ->
- link(whereis(?SERVER_NAME)),
- unsafe_call(wait_for_schema_commit_lock).
-
-block_controller() ->
- call(block_controller).
-
-unblock_controller() ->
- cast(unblock_controller).
-
-release_schema_commit_lock() ->
- cast({release_schema_commit_lock, self()}),
- unlink(whereis(?SERVER_NAME)).
-
-%% Special for preparation of add table copy
-get_network_copy(Tab, Cs) ->
- Work = #net_load{table = Tab,
- reason = {dumper, add_table_copy},
- cstruct = Cs
- },
- Res = (catch load_table(Work)),
- if Res#loader_done.is_loaded == true ->
- Tab = Res#loader_done.table_name,
- case Res#loader_done.needs_announce of
- true ->
- i_have_tab(Tab);
- false ->
- ignore
- end;
- true -> ignore
- end,
-
- receive %% Flush copier done message
- {copier_done, _Node} ->
- ok
- after 500 -> %% avoid hanging if something is wrong and we shall fail.
- ignore
- end,
- Res#loader_done.reply.
-
-%% This functions is invoked from the dumper
-%%
-%% There are two cases here:
-%% startup ->
-%% no need for sync, since mnesia_controller not started yet
-%% schema_trans ->
-%% already synced with mnesia_controller since the dumper
-%% is syncronously started from mnesia_controller
-
-create_table(Tab) ->
- {loaded, ok} = mnesia_loader:disc_load_table(Tab, {dumper,create_table}).
-
-get_disc_copy(Tab) ->
- disc_load_table(Tab, {dumper,change_table_copy_type}, undefined).
-
-%% Returns ok instead of yes
-force_load_table(Tab) when atom(Tab), Tab /= schema ->
- case ?catch_val({Tab, storage_type}) of
- ram_copies ->
- do_force_load_table(Tab);
- disc_copies ->
- do_force_load_table(Tab);
- disc_only_copies ->
- do_force_load_table(Tab);
- unknown ->
- set({Tab, load_by_force}, true),
- cast({force_load_updated, Tab}),
- wait_for_tables([Tab], infinity);
- {'EXIT', _} ->
- {error, {no_exists, Tab}}
- end;
-force_load_table(Tab) ->
- {error, {bad_type, Tab}}.
-
-do_force_load_table(Tab) ->
- Loaded = ?catch_val({Tab, load_reason}),
- case Loaded of
- unknown ->
- set({Tab, load_by_force}, true),
- mnesia_late_loader:async_late_disc_load(node(), [Tab], forced_by_user),
- wait_for_tables([Tab], infinity);
- {'EXIT', _} ->
- set({Tab, load_by_force}, true),
- mnesia_late_loader:async_late_disc_load(node(), [Tab], forced_by_user),
- wait_for_tables([Tab], infinity);
- _ ->
- ok
- end.
-master_nodes_updated(schema, _Masters) ->
- ignore;
-master_nodes_updated(Tab, Masters) ->
- cast({master_nodes_updated, Tab, Masters}).
-
-schedule_late_disc_load(Tabs, Reason) ->
- MsgTag = late_disc_load,
- try_schedule_late_disc_load(Tabs, Reason, MsgTag).
-
-try_schedule_late_disc_load(Tabs, _Reason, MsgTag)
- when Tabs == [], MsgTag /= schema_is_merged ->
- ignore;
-try_schedule_late_disc_load(Tabs, Reason, MsgTag) ->
- GetIntents =
- fun() ->
- Item = mnesia_late_disc_load,
- Nodes = val({current, db_nodes}),
- mnesia:lock({global, Item, Nodes}, write),
- case multicall(Nodes -- [node()], disc_load_intents) of
- {Replies, []} ->
- call({MsgTag, Tabs, Reason, Replies}),
- done;
- {_, BadNodes} ->
- %% Some nodes did not respond, lets try again
- {retry, BadNodes}
- end
- end,
- case mnesia:transaction(GetIntents) of
- {'atomic', done} ->
- done;
- {'atomic', {retry, BadNodes}} ->
- verbose("Retry late_load_tables because bad nodes: ~p~n",
- [BadNodes]),
- try_schedule_late_disc_load(Tabs, Reason, MsgTag);
- {aborted, AbortReason} ->
- fatal("Cannot late_load_tables~p: ~p~n",
- [[Tabs, Reason, MsgTag], AbortReason])
- end.
-
-connect_nodes(Ns) ->
- case mnesia:system_info(is_running) of
- no ->
- {error, {node_not_running, node()}};
- yes ->
- {NewC, OldC} = mnesia_recover:connect_nodes(Ns),
- Connected = NewC ++OldC,
- New1 = mnesia_lib:intersect(Ns, Connected),
- New = New1 -- val({current, db_nodes}),
-
- case try_merge_schema(New) of
- ok ->
- mnesia_lib:add_list(extra_db_nodes, New),
- {ok, New};
- {aborted, {throw, Str}} when list(Str) ->
- %%mnesia_recover:disconnect_nodes(New),
- {error, {merge_schema_failed, lists:flatten(Str)}};
- Else ->
- %% Unconnect nodes where merge failed!!
- %% mnesia_recover:disconnect_nodes(New),
- {error, Else}
- end
- end.
-
-%% Merge the local schema with the schema on other nodes.
-%% But first we must let all processes that want to force
-%% load tables wait until the schema merge is done.
-
-merge_schema() ->
- AllNodes = mnesia_lib:all_nodes(),
- case try_merge_schema(AllNodes) of
- ok ->
- schema_is_merged();
- {aborted, {throw, Str}} when list(Str) ->
- fatal("Failed to merge schema: ~s~n", [Str]);
- Else ->
- fatal("Failed to merge schema: ~p~n", [Else])
- end.
-
-try_merge_schema(Nodes) ->
- case mnesia_schema:merge_schema() of
- {'atomic', not_merged} ->
- %% No more nodes that we need to merge the schema with
- ok;
- {'atomic', {merged, OldFriends, NewFriends}} ->
- %% Check if new nodes has been added to the schema
- Diff = mnesia_lib:all_nodes() -- [node() | Nodes],
- mnesia_recover:connect_nodes(Diff),
-
- %% Tell everybody to adopt orphan tables
- im_running(OldFriends, NewFriends),
- im_running(NewFriends, OldFriends),
-
- try_merge_schema(Nodes);
- {'atomic', {"Cannot get cstructs", Node, Reason}} ->
- dbg_out("Cannot get cstructs, Node ~p ~p~n", [Node, Reason]),
- timer:sleep(1000), % Avoid a endless loop look alike
- try_merge_schema(Nodes);
- Other ->
- Other
- end.
-
-im_running(OldFriends, NewFriends) ->
- abcast(OldFriends, {im_running, node(), NewFriends}).
-
-schema_is_merged() ->
- MsgTag = schema_is_merged,
- SafeLoads = initial_safe_loads(),
-
- %% At this point we do not know anything about
- %% which tables that the other nodes already
- %% has loaded and therefore we let the normal
- %% processing of the loader_queue take care
- %% of it, since we at that time point will
- %% know the whereabouts. We rely on the fact
- %% that all nodes tells each other directly
- %% when they have loaded a table and are
- %% willing to share it.
-
- try_schedule_late_disc_load(SafeLoads, initial, MsgTag).
-
-
-cast(Msg) ->
- case whereis(?SERVER_NAME) of
- undefined ->{error, {node_not_running, node()}};
- Pid -> gen_server:cast(Pid, Msg)
- end.
-
-abcast(Nodes, Msg) ->
- gen_server:abcast(Nodes, ?SERVER_NAME, Msg).
-
-unsafe_call(Msg) ->
- case whereis(?SERVER_NAME) of
- undefined -> {error, {node_not_running, node()}};
- Pid -> gen_server:call(Pid, Msg, infinity)
- end.
-
-call(Msg) ->
- case whereis(?SERVER_NAME) of
- undefined ->
- {error, {node_not_running, node()}};
- Pid ->
- link(Pid),
- Res = gen_server:call(Pid, Msg, infinity),
- unlink(Pid),
-
- %% We get an exit signal if server dies
- receive
- {'EXIT', Pid, _Reason} ->
- {error, {node_not_running, node()}}
- after 0 ->
- ignore
- end,
- Res
- end.
-
-remote_call(Node, Func, Args) ->
- case catch gen_server:call({?MODULE, Node}, {Func, Args, self()}, infinity) of
- {'EXIT', Error} ->
- {error, Error};
- Else ->
- Else
- end.
-
-multicall(Nodes, Msg) ->
- {Good, Bad} = gen_server:multi_call(Nodes, ?MODULE, Msg, infinity),
- PatchedGood = [Reply || {_Node, Reply} <- Good],
- {PatchedGood, Bad}. %% Make the replies look like rpc:multicalls..
-%% rpc:multicall(Nodes, ?MODULE, call, [Msg]).
-
-%%%----------------------------------------------------------------------
-%%% Callback functions from gen_server
-%%%----------------------------------------------------------------------
-
-%%----------------------------------------------------------------------
-%% Func: init/1
-%% Returns: {ok, State} |
-%% {ok, State, Timeout} |
-%% {stop, Reason}
-%%----------------------------------------------------------------------
-init([Parent]) ->
- process_flag(trap_exit, true),
- mnesia_lib:verbose("~p starting: ~p~n", [?SERVER_NAME, self()]),
-
- %% Handshake and initialize transaction recovery
- %% for new nodes detected in the schema
- All = mnesia_lib:all_nodes(),
- Diff = All -- [node() | val(original_nodes)],
- mnesia_lib:unset(original_nodes),
- mnesia_recover:connect_nodes(Diff),
-
- Interval = mnesia_monitor:get_env(dump_log_time_threshold),
- Msg = {async_dump_log, time_threshold},
- {ok, Ref} = timer:send_interval(Interval, Msg),
- mnesia_dumper:start_regulator(),
-
- {ok, #state{supervisor = Parent, dump_log_timer_ref = Ref}}.
-
-%%----------------------------------------------------------------------
-%% Func: handle_call/3
-%% Returns: {reply, Reply, State} |
-%% {reply, Reply, State, Timeout} |
-%% {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, Reply, State} | (terminate/2 is called)
-%% {stop, Reason, Reply, State} (terminate/2 is called)
-%%----------------------------------------------------------------------
-
-handle_call({sync_dump_log, InitBy}, From, State) ->
- Worker = #dump_log{initiated_by = InitBy,
- opt_reply_to = From
- },
- State2 = add_worker(Worker, State),
- noreply(State2);
-
-handle_call(wait_for_schema_commit_lock, From, State) ->
- Worker = #schema_commit_lock{owner = From},
- State2 = add_worker(Worker, State),
- noreply(State2);
-
-handle_call(block_controller, From, State) ->
- Worker = #block_controller{owner = From},
- State2 = add_worker(Worker, State),
- noreply(State2);
-
-
-handle_call(get_cstructs, From, State) ->
- Tabs = val({schema, tables}),
- Cstructs = [val({T, cstruct}) || T <- Tabs],
- Running = val({current, db_nodes}),
- reply(From, {cstructs, Cstructs, Running}),
- noreply(State);
-
-handle_call({schema_is_merged, TabsR, Reason, RemoteLoaders}, From, State) ->
- State2 = late_disc_load(TabsR, Reason, RemoteLoaders, From, State),
-
- %% Handle early messages
- Msgs = State2#state.early_msgs,
- State3 = State2#state{early_msgs = [], schema_is_merged = true},
- Ns = val({current, db_nodes}),
- dbg_out("Schema is merged ~w, State ~w~n", [Ns, State3]),
-%% dbg_out("handle_early_msgs ~p ~n", [Msgs]), % qqqq
- handle_early_msgs(lists:reverse(Msgs), State3);
-
-handle_call(disc_load_intents, From, State) ->
- Tabs = disc_load_intents(State#state.loader_queue) ++
- disc_load_intents(State#state.late_loader_queue),
- ActiveTabs = mnesia_lib:local_active_tables(),
- reply(From, {ok, node(), mnesia_lib:union(Tabs, ActiveTabs)}),
- noreply(State);
-
-handle_call({update_where_to_write, [add, Tab, AddNode], _From}, _Dummy, State) ->
-%%% dbg_out("update_w2w ~p", [[add, Tab, AddNode]]), %%% qqqq
- Current = val({current, db_nodes}),
- Res =
- case lists:member(AddNode, Current) and
- State#state.schema_is_merged == true of
- true ->
- mnesia_lib:add({Tab, where_to_write}, AddNode);
- false ->
- ignore
- end,
- {reply, Res, State};
-
-handle_call({add_active_replica, [Tab, ToNode, RemoteS, AccessMode], From},
- ReplyTo, State) ->
- KnownNode = lists:member(ToNode, val({current, db_nodes})),
- Merged = State#state.schema_is_merged,
- if
- KnownNode == false ->
- reply(ReplyTo, ignore),
- noreply(State);
- Merged == true ->
- Res = add_active_replica(Tab, ToNode, RemoteS, AccessMode),
- reply(ReplyTo, Res),
- noreply(State);
- true -> %% Schema is not merged
- Msg = {add_active_replica, [Tab, ToNode, RemoteS, AccessMode], From},
- Msgs = State#state.early_msgs,
- reply(ReplyTo, ignore), %% Reply ignore and add data after schema merge
- noreply(State#state{early_msgs = [{call, Msg, undefined} | Msgs]})
- end;
-
-handle_call({unannounce_add_table_copy, [Tab, Node], From}, ReplyTo, State) ->
- KnownNode = lists:member(node(From), val({current, db_nodes})),
- Merged = State#state.schema_is_merged,
- if
- KnownNode == false ->
- reply(ReplyTo, ignore),
- noreply(State);
- Merged == true ->
- Res = unannounce_add_table_copy(Tab, Node),
- reply(ReplyTo, Res),
- noreply(State);
- true -> %% Schema is not merged
- Msg = {unannounce_add_table_copy, [Tab, Node], From},
- Msgs = State#state.early_msgs,
- reply(ReplyTo, ignore), %% Reply ignore and add data after schema merge
- %% Set ReplyTO to undefined so we don't reply twice
- noreply(State#state{early_msgs = [{call, Msg, undefined} | Msgs]})
- end;
-
-handle_call(Msg, From, State) when State#state.schema_is_merged == false ->
- %% Buffer early messages
-%% dbg_out("Buffered early msg ~p ~n", [Msg]), %% qqqq
- Msgs = State#state.early_msgs,
- noreply(State#state{early_msgs = [{call, Msg, From} | Msgs]});
-
-handle_call({net_load, Tab, Cs}, From, State) ->
- Worker = #net_load{table = Tab,
- opt_reply_to = From,
- reason = add_table_copy,
- cstruct = Cs
- },
- State2 = add_worker(Worker, State),
- noreply(State2);
-
-handle_call({late_disc_load, Tabs, Reason, RemoteLoaders}, From, State) ->
- State2 = late_disc_load(Tabs, Reason, RemoteLoaders, From, State),
- noreply(State2);
-
-handle_call({block_table, [Tab], From}, _Dummy, State) ->
- case lists:member(node(From), val({current, db_nodes})) of
- true ->
- block_table(Tab);
- false ->
- ignore
- end,
- {reply, ok, State};
-
-handle_call({check_w2r, _Node, Tab}, _From, State) ->
- {reply, val({Tab, where_to_read}), State};
-
-handle_call(Msg, _From, State) ->
- error("~p got unexpected call: ~p~n", [?SERVER_NAME, Msg]),
- noreply(State).
-
-disc_load_intents([H | T]) when record(H, disc_load) ->
- [H#disc_load.table | disc_load_intents(T)];
-disc_load_intents([H | T]) when record(H, late_load) ->
- [H#late_load.table | disc_load_intents(T)];
-disc_load_intents( [H | T]) when record(H, net_load) ->
- disc_load_intents(T);
-disc_load_intents([]) ->
- [].
-
-late_disc_load(TabsR, Reason, RemoteLoaders, From, State) ->
- verbose("Intend to load tables: ~p~n", [TabsR]),
- ?eval_debug_fun({?MODULE, late_disc_load},
- [{tabs, TabsR},
- {reason, Reason},
- {loaders, RemoteLoaders}]),
-
- reply(From, queued),
- %% RemoteLoaders is a list of {ok, Node, Tabs} tuples
-
- %% Remove deleted tabs
- LocalTabs = mnesia_lib:val({schema, local_tables}),
- Filter = fun({Tab, Reas}, Acc) ->
- case lists:member(Tab, LocalTabs) of
- true -> [{Tab, Reas} | Acc];
- false -> Acc
- end;
- (Tab, Acc) ->
- case lists:member(Tab, LocalTabs) of
- true -> [Tab | Acc];
- false -> Acc
- end
- end,
-
- Tabs = lists:foldl(Filter, [], TabsR),
-
- Nodes = val({current, db_nodes}),
- LateLoaders = late_loaders(Tabs, Reason, RemoteLoaders, Nodes),
- LateQueue = State#state.late_loader_queue ++ LateLoaders,
- State#state{late_loader_queue = LateQueue}.
-
-late_loaders([{Tab, Reason} | Tabs], DefaultReason, RemoteLoaders, Nodes) ->
- LoadNodes = late_load_filter(RemoteLoaders, Tab, Nodes, []),
- case LoadNodes of
- [] ->
- cast({disc_load, Tab, Reason}); % Ugly cast
- _ ->
- ignore
- end,
- LateLoad = #late_load{table = Tab, loaders = LoadNodes, reason = Reason},
- [LateLoad | late_loaders(Tabs, DefaultReason, RemoteLoaders, Nodes)];
-
-late_loaders([Tab | Tabs], Reason, RemoteLoaders, Nodes) ->
- Loaders = late_load_filter(RemoteLoaders, Tab, Nodes, []),
- case Loaders of
- [] ->
- cast({disc_load, Tab, Reason}); % Ugly cast
- _ ->
- ignore
- end,
- LateLoad = #late_load{table = Tab, loaders = Loaders, reason = Reason},
- [LateLoad | late_loaders(Tabs, Reason, RemoteLoaders, Nodes)];
-late_loaders([], _Reason, _RemoteLoaders, _Nodes) ->
- [].
-
-late_load_filter([{error, _} | RemoteLoaders], Tab, Nodes, Acc) ->
- late_load_filter(RemoteLoaders, Tab, Nodes, Acc);
-late_load_filter([{badrpc, _} | RemoteLoaders], Tab, Nodes, Acc) ->
- late_load_filter(RemoteLoaders, Tab, Nodes, Acc);
-late_load_filter([RL | RemoteLoaders], Tab, Nodes, Acc) ->
- {ok, Node, Intents} = RL,
- Access = val({Tab, access_mode}),
- LocalC = val({Tab, local_content}),
- StillActive = lists:member(Node, Nodes),
- RemoteIntent = lists:member(Tab, Intents),
- if
- Access == read_write,
- LocalC == false,
- StillActive == true,
- RemoteIntent == true ->
- Masters = mnesia_recover:get_master_nodes(Tab),
- case lists:member(Node, Masters) of
- true ->
- %% The other node is master node for
- %% the table, accept his load intent
- late_load_filter(RemoteLoaders, Tab, Nodes, [Node | Acc]);
- false when Masters == [] ->
- %% The table has no master nodes
- %% accept his load intent
- late_load_filter(RemoteLoaders, Tab, Nodes, [Node | Acc]);
- false ->
- %% Some one else is master node for
- %% the table, ignore his load intent
- late_load_filter(RemoteLoaders, Tab, Nodes, Acc)
- end;
- true ->
- late_load_filter(RemoteLoaders, Tab, Nodes, Acc)
- end;
-late_load_filter([], _Tab, _Nodes, Acc) ->
- Acc.
-
-%%----------------------------------------------------------------------
-%% Func: handle_cast/2
-%% Returns: {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State} (terminate/2 is called)
-%%----------------------------------------------------------------------
-
-handle_cast({release_schema_commit_lock, _Owner}, State) ->
- if
- State#state.is_stopping == true ->
- {stop, shutdown, State};
- true ->
- case State#state.dumper_queue of
- [#schema_commit_lock{}|Rest] ->
- [_Worker | Rest] = State#state.dumper_queue,
- State2 = State#state{dumper_pid = undefined,
- dumper_queue = Rest},
- State3 = opt_start_worker(State2),
- noreply(State3);
- _ ->
- noreply(State)
- end
- end;
-
-handle_cast(unblock_controller, State) ->
- if
- State#state.is_stopping == true ->
- {stop, shutdown, State};
- record(hd(State#state.dumper_queue), block_controller) ->
- [_Worker | Rest] = State#state.dumper_queue,
- State2 = State#state{dumper_pid = undefined,
- dumper_queue = Rest},
- State3 = opt_start_worker(State2),
- noreply(State3)
- end;
-
-handle_cast({mnesia_down, Node}, State) ->
- maybe_log_mnesia_down(Node),
- mnesia_lib:del({current, db_nodes}, Node),
- mnesia_checkpoint:tm_mnesia_down(Node),
- Alltabs = val({schema, tables}),
- State2 = reconfigure_tables(Node, State, Alltabs),
- case State#state.sender_pid of
- undefined -> ignore;
- Pid when pid(Pid) -> Pid ! {copier_done, Node}
- end,
- case State#state.loader_pid of
- undefined -> ignore;
- Pid2 when pid(Pid2) -> Pid2 ! {copier_done, Node}
- end,
- NewSenders =
- case State#state.sender_queue of
- [OldSender | RestSenders] ->
- Remove = fun(ST) ->
- node(ST#send_table.receiver_pid) /= Node
- end,
- NewS = lists:filter(Remove, RestSenders),
- %% Keep old sender it will be removed by sender_done
- [OldSender | NewS];
- [] ->
- []
- end,
- Early = remove_early_messages(State2#state.early_msgs, Node),
- mnesia_monitor:mnesia_down(?SERVER_NAME, Node),
- noreply(State2#state{sender_queue = NewSenders, early_msgs = Early});
-
-handle_cast({im_running, _Node, NewFriends}, State) ->
- Tabs = mnesia_lib:local_active_tables() -- [schema],
- Ns = mnesia_lib:intersect(NewFriends, val({current, db_nodes})),
- abcast(Ns, {adopt_orphans, node(), Tabs}),
- noreply(State);
-
-handle_cast(Msg, State) when State#state.schema_is_merged == false ->
- %% Buffer early messages
- Msgs = State#state.early_msgs,
- noreply(State#state{early_msgs = [{cast, Msg} | Msgs]});
-
-handle_cast({disc_load, Tab, Reason}, State) ->
- Worker = #disc_load{table = Tab, reason = Reason},
- State2 = add_worker(Worker, State),
- noreply(State2);
-
-handle_cast(Worker, State) when record(Worker, send_table) ->
- State2 = add_worker(Worker, State),
- noreply(State2);
-
-handle_cast({sync_tabs, Tabs, From}, State) ->
- %% user initiated wait_for_tables
- handle_sync_tabs(Tabs, From),
- noreply(State);
-
-handle_cast({i_have_tab, Tab, Node}, State) ->
- case lists:member(Node, val({current, db_nodes})) of
- true ->
- State2 = node_has_tabs([Tab], Node, State),
- noreply(State2);
- false ->
- noreply(State)
- end;
-
-handle_cast({force_load_updated, Tab}, State) ->
- case val({Tab, active_replicas}) of
- [] ->
- %% No valid replicas
- noreply(State);
- [SomeNode | _] ->
- State2 = node_has_tabs([Tab], SomeNode, State),
- noreply(State2)
- end;
-
-handle_cast({master_nodes_updated, Tab, Masters}, State) ->
- Active = val({Tab, active_replicas}),
- Valid =
- case val({Tab, load_by_force}) of
- true ->
- Active;
- false ->
- if
- Masters == [] ->
- Active;
- true ->
- mnesia_lib:intersect(Masters, Active)
- end
- end,
- case Valid of
- [] ->
- %% No valid replicas
- noreply(State);
- [SomeNode | _] ->
- State2 = node_has_tabs([Tab], SomeNode, State),
- noreply(State2)
- end;
-
-handle_cast({adopt_orphans, Node, Tabs}, State) ->
-
- State2 = node_has_tabs(Tabs, Node, State),
-
- %% Register the other node as up and running
- mnesia_recover:log_mnesia_up(Node),
- verbose("Logging mnesia_up ~w~n", [Node]),
- mnesia_lib:report_system_event({mnesia_up, Node}),
-
- %% Load orphan tables
- LocalTabs = val({schema, local_tables}) -- [schema],
- Nodes = val({current, db_nodes}),
- {LocalOrphans, RemoteMasters} =
- orphan_tables(LocalTabs, Node, Nodes, [], []),
- Reason = {adopt_orphan, node()},
- mnesia_late_loader:async_late_disc_load(node(), LocalOrphans, Reason),
-
- Fun =
- fun(N) ->
- RemoteOrphans =
- [Tab || {Tab, Ns} <- RemoteMasters,
- lists:member(N, Ns)],
- mnesia_late_loader:maybe_async_late_disc_load(N, RemoteOrphans, Reason)
- end,
- lists:foreach(Fun, Nodes),
-
- Queue = State2#state.loader_queue,
- State3 = State2#state{loader_queue = Queue},
- noreply(State3);
-
-handle_cast(Msg, State) ->
- error("~p got unexpected cast: ~p~n", [?SERVER_NAME, Msg]),
- noreply(State).
-
-handle_sync_tabs([Tab | Tabs], From) ->
- case val({Tab, where_to_read}) of
- nowhere ->
- case get({sync_tab, Tab}) of
- undefined ->
- put({sync_tab, Tab}, [From]);
- Pids ->
- put({sync_tab, Tab}, [From | Pids])
- end;
- _ ->
- sync_reply(From, Tab)
- end,
- handle_sync_tabs(Tabs, From);
-handle_sync_tabs([], _From) ->
- ok.
-
-%%----------------------------------------------------------------------
-%% Func: handle_info/2
-%% Returns: {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State} (terminate/2 is called)
-%%----------------------------------------------------------------------
-
-handle_info({async_dump_log, InitBy}, State) ->
- Worker = #dump_log{initiated_by = InitBy},
- State2 = add_worker(Worker, State),
- noreply(State2);
-
-handle_info(Done, State) when record(Done, dumper_done) ->
- Pid = Done#dumper_done.worker_pid,
- Res = Done#dumper_done.worker_res,
- if
- State#state.is_stopping == true ->
- {stop, shutdown, State};
- Res == dumped, Pid == State#state.dumper_pid ->
- [Worker | Rest] = State#state.dumper_queue,
- reply(Worker#dump_log.opt_reply_to, Res),
- State2 = State#state{dumper_pid = undefined,
- dumper_queue = Rest},
- State3 = opt_start_worker(State2),
- noreply(State3);
- true ->
- fatal("Dumper failed: ~p~n state: ~p~n", [Res, State]),
- {stop, fatal, State}
- end;
-
-handle_info(Done, State) when record(Done, loader_done) ->
- if
- %% Assertion
- Done#loader_done.worker_pid == State#state.loader_pid -> ok
- end,
-
- [_Worker | Rest] = LoadQ0 = State#state.loader_queue,
- LateQueue0 = State#state.late_loader_queue,
- {LoadQ, LateQueue} =
- case Done#loader_done.is_loaded of
- true ->
- Tab = Done#loader_done.table_name,
-
- %% Optional user sync
- case Done#loader_done.needs_sync of
- true -> user_sync_tab(Tab);
- false -> ignore
- end,
-
- %% Optional table announcement
- case Done#loader_done.needs_announce of
- true ->
- i_have_tab(Tab),
- case Tab of
- schema ->
- ignore;
- _ ->
- %% Local node needs to perform user_sync_tab/1
- Ns = val({current, db_nodes}),
- abcast(Ns, {i_have_tab, Tab, node()})
- end;
- false ->
- case Tab of
- schema ->
- ignore;
- _ ->
- %% Local node needs to perform user_sync_tab/1
- Ns = val({current, db_nodes}),
- AlreadyKnows = val({Tab, active_replicas}),
- abcast(Ns -- AlreadyKnows, {i_have_tab, Tab, node()})
- end
- end,
-
- %% Optional client reply
- case Done#loader_done.needs_reply of
- true ->
- reply(Done#loader_done.reply_to,
- Done#loader_done.reply);
- false ->
- ignore
- end,
- {Rest, reply_late_load(Tab, LateQueue0)};
- false ->
- case Done#loader_done.reply of
- restart ->
- {LoadQ0, LateQueue0};
- _ ->
- {Rest, LateQueue0}
- end
- end,
-
- State2 = State#state{loader_pid = undefined,
- loader_queue = LoadQ,
- late_loader_queue = LateQueue},
-
- State3 = opt_start_worker(State2),
- noreply(State3);
-
-handle_info(Done, State) when record(Done, sender_done) ->
- Pid = Done#sender_done.worker_pid,
- Res = Done#sender_done.worker_res,
- if
- Res == ok, Pid == State#state.sender_pid ->
- [Worker | Rest] = State#state.sender_queue,
- Worker#send_table.receiver_pid ! {copier_done, node()},
- State2 = State#state{sender_pid = undefined,
- sender_queue = Rest},
- State3 = opt_start_worker(State2),
- noreply(State3);
- true ->
- %% No need to send any message to the table receiver
- %% since it will soon get a mnesia_down anyway
- fatal("Sender failed: ~p~n state: ~p~n", [Res, State]),
- {stop, fatal, State}
- end;
-
-handle_info({'EXIT', Pid, R}, State) when Pid == State#state.supervisor ->
- catch set(mnesia_status, stopping),
- case State#state.dumper_pid of
- undefined ->
- dbg_out("~p was ~p~n", [?SERVER_NAME, R]),
- {stop, shutdown, State};
- _ ->
- noreply(State#state{is_stopping = true})
- end;
-
-handle_info({'EXIT', Pid, R}, State) when Pid == State#state.dumper_pid ->
- case State#state.dumper_queue of
- [#schema_commit_lock{}|Workers] -> %% Schema trans crashed or was killed
- State2 = State#state{dumper_queue = Workers, dumper_pid = undefined},
- State3 = opt_start_worker(State2),
- noreply(State3);
- _Other ->
- fatal("Dumper or schema commit crashed: ~p~n state: ~p~n", [R, State]),
- {stop, fatal, State}
- end;
-
-handle_info({'EXIT', Pid, R}, State) when Pid == State#state.loader_pid ->
- fatal("Loader crashed: ~p~n state: ~p~n", [R, State]),
- {stop, fatal, State};
-
-handle_info({'EXIT', Pid, R}, State) when Pid == State#state.sender_pid ->
- %% No need to send any message to the table receiver
- %% since it will soon get a mnesia_down anyway
- fatal("Sender crashed: ~p~n state: ~p~n", [R, State]),
- {stop, fatal, State};
-
-handle_info({From, get_state}, State) ->
- From ! {?SERVER_NAME, State},
- noreply(State);
-
-%% No real need for buffering
-handle_info(Msg, State) when State#state.schema_is_merged == false ->
- %% Buffer early messages
- Msgs = State#state.early_msgs,
- noreply(State#state{early_msgs = [{info, Msg} | Msgs]});
-
-handle_info({'EXIT', Pid, wait_for_tables_timeout}, State) ->
- sync_tab_timeout(Pid, get()),
- noreply(State);
-
-handle_info(Msg, State) ->
- error("~p got unexpected info: ~p~n", [?SERVER_NAME, Msg]),
- noreply(State).
-
-reply_late_load(Tab, [H | T]) when H#late_load.table == Tab ->
- reply(H#late_load.opt_reply_to, ok),
- reply_late_load(Tab, T);
-reply_late_load(Tab, [H | T]) ->
- [H | reply_late_load(Tab, T)];
-reply_late_load(_Tab, []) ->
- [].
-
-sync_tab_timeout(Pid, [{{sync_tab, Tab}, Pids} | Tail]) ->
- case lists:delete(Pid, Pids) of
- [] ->
- erase({sync_tab, Tab});
- Pids2 ->
- put({sync_tab, Tab}, Pids2)
- end,
- sync_tab_timeout(Pid, Tail);
-sync_tab_timeout(Pid, [_ | Tail]) ->
- sync_tab_timeout(Pid, Tail);
-sync_tab_timeout(_Pid, []) ->
- ok.
-
-%% Pick the load record that has the highest load order
-%% Returns {BestLoad, RemainingQueue} or {none, []} if queue is empty
-pick_next(Queue) ->
- pick_next(Queue, none, none, []).
-
-pick_next([Head | Tail], Load, Order, Rest) when record(Head, net_load) ->
- Tab = Head#net_load.table,
- select_best(Head, Tail, val({Tab, load_order}), Load, Order, Rest);
-pick_next([Head | Tail], Load, Order, Rest) when record(Head, disc_load) ->
- Tab = Head#disc_load.table,
- select_best(Head, Tail, val({Tab, load_order}), Load, Order, Rest);
-pick_next([], Load, _Order, Rest) ->
- {Load, Rest}.
-
-select_best(Load, Tail, Order, none, none, Rest) ->
- pick_next(Tail, Load, Order, Rest);
-select_best(Load, Tail, Order, OldLoad, OldOrder, Rest) when Order > OldOrder ->
- pick_next(Tail, Load, Order, [OldLoad | Rest]);
-select_best(Load, Tail, _Order, OldLoad, OldOrder, Rest) ->
- pick_next(Tail, OldLoad, OldOrder, [Load | Rest]).
-
-%%----------------------------------------------------------------------
-%% Func: terminate/2
-%% Purpose: Shutdown the server
-%% Returns: any (ignored by gen_server)
-%%----------------------------------------------------------------------
-terminate(Reason, State) ->
- mnesia_monitor:terminate_proc(?SERVER_NAME, Reason, State).
-
-%%----------------------------------------------------------------------
-%% Func: code_change/3
-%% Purpose: Upgrade process when its code is to be changed
-%% Returns: {ok, NewState}
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%%----------------------------------------------------------------------
-%%% Internal functions
-%%%----------------------------------------------------------------------
-
-maybe_log_mnesia_down(N) ->
- %% We use mnesia_down when deciding which tables to load locally,
- %% so if we are not running (i.e haven't decided which tables
- %% to load locally), don't log mnesia_down yet.
- case mnesia_lib:is_running() of
- yes ->
- verbose("Logging mnesia_down ~w~n", [N]),
- mnesia_recover:log_mnesia_down(N),
- ok;
- _ ->
- Filter = fun(Tab) ->
- inactive_copy_holders(Tab, N)
- end,
- HalfLoadedTabs = lists:any(Filter, val({schema, local_tables}) -- [schema]),
- if
- HalfLoadedTabs == true ->
- verbose("Logging mnesia_down ~w~n", [N]),
- mnesia_recover:log_mnesia_down(N),
- ok;
- true ->
- %% Unfortunately we have not loaded some common
- %% tables yet, so we cannot rely on the nodedown
- log_later %% BUGBUG handle this case!!!
- end
- end.
-
-inactive_copy_holders(Tab, Node) ->
- Cs = val({Tab, cstruct}),
- case mnesia_lib:cs_to_storage_type(Node, Cs) of
- unknown ->
- false;
- _Storage ->
- mnesia_lib:not_active_here(Tab)
- end.
-
-orphan_tables([Tab | Tabs], Node, Ns, Local, Remote) ->
- Cs = val({Tab, cstruct}),
- CopyHolders = mnesia_lib:copy_holders(Cs),
- RamCopyHolders = Cs#cstruct.ram_copies,
- DiscCopyHolders = CopyHolders -- RamCopyHolders,
- DiscNodes = val({schema, disc_copies}),
- LocalContent = Cs#cstruct.local_content,
- RamCopyHoldersOnDiscNodes = mnesia_lib:intersect(RamCopyHolders, DiscNodes),
- Active = val({Tab, active_replicas}),
- case lists:member(Node, DiscCopyHolders) of
- true when Active == [] ->
- case DiscCopyHolders -- Ns of
- [] ->
- %% We're last up and the other nodes have not
- %% loaded the table. Lets load it if we are
- %% the smallest node.
- case lists:min(DiscCopyHolders) of
- Min when Min == node() ->
- case mnesia_recover:get_master_nodes(Tab) of
- [] ->
- L = [Tab | Local],
- orphan_tables(Tabs, Node, Ns, L, Remote);
- Masters ->
- R = [{Tab, Masters} | Remote],
- orphan_tables(Tabs, Node, Ns, Local, R)
- end;
- _ ->
- orphan_tables(Tabs, Node, Ns, Local, Remote)
- end;
- _ ->
- orphan_tables(Tabs, Node, Ns, Local, Remote)
- end;
- false when Active == [], DiscCopyHolders == [], RamCopyHoldersOnDiscNodes == [] ->
- %% Special case when all replicas resides on disc less nodes
- orphan_tables(Tabs, Node, Ns, [Tab | Local], Remote);
- _ when LocalContent == true ->
- orphan_tables(Tabs, Node, Ns, [Tab | Local], Remote);
- _ ->
- orphan_tables(Tabs, Node, Ns, Local, Remote)
- end;
-orphan_tables([], _, _, LocalOrphans, RemoteMasters) ->
- {LocalOrphans, RemoteMasters}.
-
-node_has_tabs([Tab | Tabs], Node, State) when Node /= node() ->
- State2 = update_whereabouts(Tab, Node, State),
- node_has_tabs(Tabs, Node, State2);
-node_has_tabs([Tab | Tabs], Node, State) ->
- user_sync_tab(Tab),
- node_has_tabs(Tabs, Node, State);
-node_has_tabs([], _Node, State) ->
- State.
-
-update_whereabouts(Tab, Node, State) ->
- Storage = val({Tab, storage_type}),
- Read = val({Tab, where_to_read}),
- LocalC = val({Tab, local_content}),
- BeingCreated = (?catch_val({Tab, create_table}) == true),
- Masters = mnesia_recover:get_master_nodes(Tab),
- ByForce = val({Tab, load_by_force}),
- GoGetIt =
- if
- ByForce == true ->
- true;
- Masters == [] ->
- true;
- true ->
- lists:member(Node, Masters)
- end,
-
- dbg_out("Table ~w is loaded on ~w. s=~w, r=~w, lc=~w, f=~w, m=~w~n",
- [Tab, Node, Storage, Read, LocalC, ByForce, GoGetIt]),
- if
- LocalC == true ->
- %% Local contents, don't care about other node
- State;
- Storage == unknown, Read == nowhere ->
- %% No own copy, time to read remotely
- %% if the other node is a good node
- add_active_replica(Tab, Node),
- case GoGetIt of
- true ->
- set({Tab, where_to_read}, Node),
- user_sync_tab(Tab),
- State;
- false ->
- State
- end;
- Storage == unknown ->
- %% No own copy, continue to read remotely
- add_active_replica(Tab, Node),
- NodeST = mnesia_lib:storage_type_at_node(Node, Tab),
- ReadST = mnesia_lib:storage_type_at_node(Read, Tab),
- if %% Avoid reading from disc_only_copies
- NodeST == disc_only_copies ->
- ignore;
- ReadST == disc_only_copies ->
- mnesia_lib:set_remote_where_to_read(Tab);
- true ->
- ignore
- end,
- user_sync_tab(Tab),
- State;
- BeingCreated == true ->
- %% The table is currently being created
- %% and we shall have an own copy of it.
- %% We will load the (empty) table locally.
- add_active_replica(Tab, Node),
- State;
- Read == nowhere ->
- %% Own copy, go and get a copy of the table
- %% if the other node is master or if there
- %% are no master at all
- add_active_replica(Tab, Node),
- case GoGetIt of
- true ->
- Worker = #net_load{table = Tab,
- reason = {active_remote, Node}},
- add_worker(Worker, State);
- false ->
- State
- end;
- true ->
- %% We already have an own copy
- add_active_replica(Tab, Node),
- user_sync_tab(Tab),
- State
- end.
-
-initial_safe_loads() ->
- case val({schema, storage_type}) of
- ram_copies ->
- Downs = [],
- Tabs = val({schema, local_tables}) -- [schema],
- LastC = fun(T) -> last_consistent_replica(T, Downs) end,
- lists:zf(LastC, Tabs);
-
- disc_copies ->
- Downs = mnesia_recover:get_mnesia_downs(),
- dbg_out("mnesia_downs = ~p~n", [Downs]),
-
- Tabs = val({schema, local_tables}) -- [schema],
- LastC = fun(T) -> last_consistent_replica(T, Downs) end,
- lists:zf(LastC, Tabs)
- end.
-
-last_consistent_replica(Tab, Downs) ->
- Cs = val({Tab, cstruct}),
- Storage = mnesia_lib:cs_to_storage_type(node(), Cs),
- Ram = Cs#cstruct.ram_copies,
- Disc = Cs#cstruct.disc_copies,
- DiscOnly = Cs#cstruct.disc_only_copies,
- BetterCopies0 = mnesia_lib:remote_copy_holders(Cs) -- Downs,
- BetterCopies = BetterCopies0 -- Ram,
- AccessMode = Cs#cstruct.access_mode,
- Copies = mnesia_lib:copy_holders(Cs),
- Masters = mnesia_recover:get_master_nodes(Tab),
- LocalMaster0 = lists:member(node(), Masters),
- LocalContent = Cs#cstruct.local_content,
- RemoteMaster =
- if
- Masters == [] -> false;
- true -> not LocalMaster0
- end,
- LocalMaster =
- if
- Masters == [] -> false;
- true -> LocalMaster0
- end,
- if
- Copies == [node()] ->
- %% Only one copy holder and it is local.
- %% It may also be a local contents table
- {true, {Tab, local_only}};
- LocalContent == true ->
- {true, {Tab, local_content}};
- LocalMaster == true ->
- %% We have a local master
- {true, {Tab, local_master}};
- RemoteMaster == true ->
- %% Wait for remote master copy
- false;
- Storage == ram_copies ->
- if
- Disc == [], DiscOnly == [] ->
- %% Nobody has copy on disc
- {true, {Tab, ram_only}};
- true ->
- %% Some other node has copy on disc
- false
- end;
- AccessMode == read_only ->
- %% No one has been able to update the table,
- %% i.e. all disc resident copies are equal
- {true, {Tab, read_only}};
- BetterCopies /= [], Masters /= [node()] ->
- %% There are better copies on other nodes
- %% and we do not have the only master copy
- false;
- true ->
- {true, {Tab, initial}}
- end.
-
-reconfigure_tables(N, State, [Tab |Tail]) ->
- del_active_replica(Tab, N),
- case val({Tab, where_to_read}) of
- N -> mnesia_lib:set_remote_where_to_read(Tab);
- _ -> ignore
- end,
- LateQ = drop_loaders(Tab, N, State#state.late_loader_queue),
- reconfigure_tables(N, State#state{late_loader_queue = LateQ}, Tail);
-
-reconfigure_tables(_, State, []) ->
- State.
-
-remove_early_messages([], _Node) ->
- [];
-remove_early_messages([{call, {add_active_replica, [_, Node, _, _], _}, _}|R], Node) ->
- remove_early_messages(R, Node); %% Does a reply before queuing
-remove_early_messages([{call, {block_table, _, From}, ReplyTo}|R], Node)
- when node(From) == Node ->
- reply(ReplyTo, ok), %% Remove gen:server waits..
- remove_early_messages(R, Node);
-remove_early_messages([{cast, {i_have_tab, _Tab, Node}}|R], Node) ->
- remove_early_messages(R, Node);
-remove_early_messages([{cast, {adopt_orphans, Node, _Tabs}}|R], Node) ->
- remove_early_messages(R, Node);
-remove_early_messages([M|R],Node) ->
- [M|remove_early_messages(R,Node)].
-
-%% Drop loader from late load queue and possibly trigger a disc_load
-drop_loaders(Tab, Node, [H | T]) when H#late_load.table == Tab ->
- %% Check if it is time to issue a disc_load request
- case H#late_load.loaders of
- [Node] ->
- Reason = {H#late_load.reason, last_loader_down, Node},
- cast({disc_load, Tab, Reason}); % Ugly cast
- _ ->
- ignore
- end,
- %% Drop the node from the list of loaders
- H2 = H#late_load{loaders = H#late_load.loaders -- [Node]},
- [H2 | drop_loaders(Tab, Node, T)];
-drop_loaders(Tab, Node, [H | T]) ->
- [H | drop_loaders(Tab, Node, T)];
-drop_loaders(_, _, []) ->
- [].
-
-add_active_replica(Tab, Node) ->
- add_active_replica(Tab, Node, val({Tab, cstruct})).
-
-add_active_replica(Tab, Node, Cs) when record(Cs, cstruct) ->
- Storage = mnesia_lib:schema_cs_to_storage_type(Node, Cs),
- AccessMode = Cs#cstruct.access_mode,
- add_active_replica(Tab, Node, Storage, AccessMode).
-
-%% Block table primitives
-
-block_table(Tab) ->
- Var = {Tab, where_to_commit},
- Old = val(Var),
- New = {blocked, Old},
- set(Var, New). % where_to_commit
-
-unblock_table(Tab) ->
- Var = {Tab, where_to_commit},
- New =
- case val(Var) of
- {blocked, List} ->
- List;
- List ->
- List
- end,
- set(Var, New). % where_to_commit
-
-is_tab_blocked(W2C) when list(W2C) ->
- {false, W2C};
-is_tab_blocked({blocked, W2C}) when list(W2C) ->
- {true, W2C}.
-
-mark_blocked_tab(true, Value) ->
- {blocked, Value};
-mark_blocked_tab(false, Value) ->
- Value.
-
-%%
-
-add_active_replica(Tab, Node, Storage, AccessMode) ->
- Var = {Tab, where_to_commit},
- {Blocked, Old} = is_tab_blocked(val(Var)),
- Del = lists:keydelete(Node, 1, Old),
- case AccessMode of
- read_write ->
- New = lists:sort([{Node, Storage} | Del]),
- set(Var, mark_blocked_tab(Blocked, New)), % where_to_commit
- add({Tab, where_to_write}, Node);
- read_only ->
- set(Var, mark_blocked_tab(Blocked, Del)),
- mnesia_lib:del({Tab, where_to_write}, Node)
- end,
- add({Tab, active_replicas}, Node).
-
-del_active_replica(Tab, Node) ->
- Var = {Tab, where_to_commit},
- {Blocked, Old} = is_tab_blocked(val(Var)),
- Del = lists:keydelete(Node, 1, Old),
- New = lists:sort(Del),
- set(Var, mark_blocked_tab(Blocked, New)), % where_to_commit
- mnesia_lib:del({Tab, active_replicas}, Node),
- mnesia_lib:del({Tab, where_to_write}, Node).
-
-change_table_access_mode(Cs) ->
- Tab = Cs#cstruct.name,
- lists:foreach(fun(N) -> add_active_replica(Tab, N, Cs) end,
- val({Tab, active_replicas})).
-
-%% node To now has tab loaded, but this must be undone
-%% This code is rpc:call'ed from the tab_copier process
-%% when it has *not* released it's table lock
-unannounce_add_table_copy(Tab, To) ->
- del_active_replica(Tab, To),
- case val({Tab , where_to_read}) of
- To ->
- mnesia_lib:set_remote_where_to_read(Tab);
- _ ->
- ignore
- end.
-
-user_sync_tab(Tab) ->
- case val(debug) of
- trace ->
- mnesia_subscr:subscribe(whereis(mnesia_event), {table, Tab});
- _ ->
- ignore
- end,
-
- case erase({sync_tab, Tab}) of
- undefined ->
- ok;
- Pids ->
- lists:foreach(fun(Pid) -> sync_reply(Pid, Tab) end, Pids)
- end.
-
-i_have_tab(Tab) ->
- case val({Tab, local_content}) of
- true ->
- mnesia_lib:set_local_content_whereabouts(Tab);
- false ->
- set({Tab, where_to_read}, node())
- end,
- add_active_replica(Tab, node()).
-
-sync_and_block_table_whereabouts(Tab, ToNode, RemoteS, AccessMode) when Tab /= schema ->
- Current = val({current, db_nodes}),
- Ns =
- case lists:member(ToNode, Current) of
- true -> Current -- [ToNode];
- false -> Current
- end,
- remote_call(ToNode, block_table, [Tab]),
- [remote_call(Node, add_active_replica, [Tab, ToNode, RemoteS, AccessMode]) ||
- Node <- [ToNode | Ns]],
- ok.
-
-sync_del_table_copy_whereabouts(Tab, ToNode) when Tab /= schema ->
- Current = val({current, db_nodes}),
- Ns =
- case lists:member(ToNode, Current) of
- true -> Current;
- false -> [ToNode | Current]
- end,
- Args = [Tab, ToNode],
- [remote_call(Node, unannounce_add_table_copy, Args) || Node <- Ns],
- ok.
-
-get_info(Timeout) ->
- case whereis(?SERVER_NAME) of
- undefined ->
- {timeout, Timeout};
- Pid ->
- Pid ! {self(), get_state},
- receive
- {?SERVER_NAME, State} when record(State, state) ->
- {info,State}
- after Timeout ->
- {timeout, Timeout}
- end
- end.
-
-get_workers(Timeout) ->
- case whereis(?SERVER_NAME) of
- undefined ->
- {timeout, Timeout};
- Pid ->
- Pid ! {self(), get_state},
- receive
- {?SERVER_NAME, State} when record(State, state) ->
- {workers, State#state.loader_pid, State#state.sender_pid, State#state.dumper_pid}
- after Timeout ->
- {timeout, Timeout}
- end
- end.
-
-info() ->
- Tabs = mnesia_lib:local_active_tables(),
- io:format( "---> Active tables <--- ~n", []),
- info(Tabs).
-
-info([Tab | Tail]) ->
- case val({Tab, storage_type}) of
- disc_only_copies ->
- info_format(Tab,
- dets:info(Tab, size),
- dets:info(Tab, file_size),
- "bytes on disc");
- _ ->
- info_format(Tab,
- ?ets_info(Tab, size),
- ?ets_info(Tab, memory),
- "words of mem")
- end,
- info(Tail);
-info([]) -> ok;
-info(Tab) -> info([Tab]).
-
-info_format(Tab, Size, Mem, Media) ->
- StrT = mnesia_lib:pad_name(atom_to_list(Tab), 15, []),
- StrS = mnesia_lib:pad_name(integer_to_list(Size), 8, []),
- StrM = mnesia_lib:pad_name(integer_to_list(Mem), 8, []),
- io:format("~s: with ~s records occupying ~s ~s~n",
- [StrT, StrS, StrM, Media]).
-
-%% Handle early arrived messages
-handle_early_msgs([Msg | Msgs], State) ->
- %% The messages are in reverse order
- case handle_early_msg(Msg, State) of
- {stop, Reason, Reply, State2} ->
- {stop, Reason, Reply, State2};
- {stop, Reason, State2} ->
- {stop, Reason, State2};
- {noreply, State2} ->
- handle_early_msgs(Msgs, State2);
- {noreply, State2, _Timeout} ->
- handle_early_msgs(Msgs, State2);
- Else ->
- dbg_out("handle_early_msgs case clause ~p ~n", [Else]),
- erlang:error(Else, [[Msg | Msgs], State])
- end;
-handle_early_msgs([], State) ->
- noreply(State).
-
-handle_early_msg({call, Msg, From}, State) ->
- handle_call(Msg, From, State);
-handle_early_msg({cast, Msg}, State) ->
- handle_cast(Msg, State);
-handle_early_msg({info, Msg}, State) ->
- handle_info(Msg, State).
-
-noreply(State) ->
- {noreply, State}.
-
-reply(undefined, Reply) ->
- Reply;
-reply(ReplyTo, Reply) ->
- gen_server:reply(ReplyTo, Reply),
- Reply.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Worker management
-
-%% Returns new State
-add_worker(Worker, State) when record(Worker, dump_log) ->
- InitBy = Worker#dump_log.initiated_by,
- Queue = State#state.dumper_queue,
- case lists:keymember(InitBy, #dump_log.initiated_by, Queue) of
- false ->
- ignore;
- true when Worker#dump_log.opt_reply_to == undefined ->
- %% The same threshold has been exceeded again,
- %% before we have had the possibility to
- %% process the older one.
- DetectedBy = {dump_log, InitBy},
- Event = {mnesia_overload, DetectedBy},
- mnesia_lib:report_system_event(Event)
- end,
- Queue2 = Queue ++ [Worker],
- State2 = State#state{dumper_queue = Queue2},
- opt_start_worker(State2);
-add_worker(Worker, State) when record(Worker, schema_commit_lock) ->
- Queue = State#state.dumper_queue,
- Queue2 = Queue ++ [Worker],
- State2 = State#state{dumper_queue = Queue2},
- opt_start_worker(State2);
-add_worker(Worker, State) when record(Worker, net_load) ->
- Queue = State#state.loader_queue,
- State2 = State#state{loader_queue = Queue ++ [Worker]},
- opt_start_worker(State2);
-add_worker(Worker, State) when record(Worker, send_table) ->
- Queue = State#state.sender_queue,
- State2 = State#state{sender_queue = Queue ++ [Worker]},
- opt_start_worker(State2);
-add_worker(Worker, State) when record(Worker, disc_load) ->
- Queue = State#state.loader_queue,
- State2 = State#state{loader_queue = Queue ++ [Worker]},
- opt_start_worker(State2);
-% Block controller should be used for upgrading mnesia.
-add_worker(Worker, State) when record(Worker, block_controller) ->
- Queue = State#state.dumper_queue,
- Queue2 = [Worker | Queue],
- State2 = State#state{dumper_queue = Queue2},
- opt_start_worker(State2).
-
-%% Optionally start a worker
-%%
-%% Dumpers and loaders may run simultaneously
-%% but neither of them may run during schema commit.
-%% Loaders may not start if a schema commit is enqueued.
-opt_start_worker(State) when State#state.is_stopping == true ->
- State;
-opt_start_worker(State) ->
- %% Prioritize dumper and schema commit
- %% by checking them first
- case State#state.dumper_queue of
- [Worker | _Rest] when State#state.dumper_pid == undefined ->
- %% Great, a worker in queue and neither
- %% a schema transaction is being
- %% committed and nor a dumper is running
-
- %% Start worker but keep him in the queue
- if
- record(Worker, schema_commit_lock) ->
- ReplyTo = Worker#schema_commit_lock.owner,
- reply(ReplyTo, granted),
- {Owner, _Tag} = ReplyTo,
- State#state{dumper_pid = Owner};
-
- record(Worker, dump_log) ->
- Pid = spawn_link(?MODULE, dump_and_reply, [self(), Worker]),
- State2 = State#state{dumper_pid = Pid},
-
- %% If the worker was a dumper we may
- %% possibly be able to start a loader
- %% or sender
- State3 = opt_start_sender(State2),
- opt_start_loader(State3);
-
- record(Worker, block_controller) ->
- case {State#state.sender_pid, State#state.loader_pid} of
- {undefined, undefined} ->
- ReplyTo = Worker#block_controller.owner,
- reply(ReplyTo, granted),
- {Owner, _Tag} = ReplyTo,
- State#state{dumper_pid = Owner};
- _ ->
- State
- end
- end;
- _ ->
- %% Bad luck, try with a loader or sender instead
- State2 = opt_start_sender(State),
- opt_start_loader(State2)
- end.
-
-opt_start_sender(State) ->
- case State#state.sender_queue of
- []->
- %% No need
- State;
-
- _ when State#state.sender_pid /= undefined ->
- %% Bad luck, a sender is already running
- State;
-
- [Sender | _SenderRest] ->
- case State#state.loader_queue of
- [Loader | _LoaderRest]
- when State#state.loader_pid /= undefined,
- Loader#net_load.table == Sender#send_table.table ->
- %% A conflicting loader is running
- State;
- _ ->
- SchemaQueue = State#state.dumper_queue,
- case lists:keymember(schema_commit, 1, SchemaQueue) of
- false ->
-
- %% Start worker but keep him in the queue
- Pid = spawn_link(?MODULE, send_and_reply,
- [self(), Sender]),
- State#state{sender_pid = Pid};
- true ->
- %% Bad luck, we must wait for the schema commit
- State
- end
- end
- end.
-
-opt_start_loader(State) ->
- LoaderQueue = State#state.loader_queue,
- if
- LoaderQueue == [] ->
- %% No need
- State;
-
- State#state.loader_pid /= undefined ->
- %% Bad luck, an loader is already running
- State;
-
- true ->
- SchemaQueue = State#state.dumper_queue,
- case lists:keymember(schema_commit, 1, SchemaQueue) of
- false ->
- {Worker, Rest} = pick_next(LoaderQueue),
-
- %% Start worker but keep him in the queue
- Pid = spawn_link(?MODULE, load_and_reply, [self(), Worker]),
- State#state{loader_pid = Pid,
- loader_queue = [Worker | Rest]};
- true ->
- %% Bad luck, we must wait for the schema commit
- State
- end
- end.
-
-start_remote_sender(Node, Tab, Receiver, Storage) ->
- Msg = #send_table{table = Tab,
- receiver_pid = Receiver,
- remote_storage = Storage},
- gen_server:cast({?SERVER_NAME, Node}, Msg).
-
-dump_and_reply(ReplyTo, Worker) ->
- %% No trap_exit, die intentionally instead
- Res = mnesia_dumper:opt_dump_log(Worker#dump_log.initiated_by),
- ReplyTo ! #dumper_done{worker_pid = self(),
- worker_res = Res},
- unlink(ReplyTo),
- exit(normal).
-
-send_and_reply(ReplyTo, Worker) ->
- %% No trap_exit, die intentionally instead
- Res = mnesia_loader:send_table(Worker#send_table.receiver_pid,
- Worker#send_table.table,
- Worker#send_table.remote_storage),
- ReplyTo ! #sender_done{worker_pid = self(),
- worker_res = Res},
- unlink(ReplyTo),
- exit(normal).
-
-
-load_and_reply(ReplyTo, Worker) ->
- process_flag(trap_exit, true),
- Done = load_table(Worker),
- ReplyTo ! Done#loader_done{worker_pid = self()},
- unlink(ReplyTo),
- exit(normal).
-
-%% Now it is time to load the table
-%% but first we must check if it still is neccessary
-load_table(Load) when record(Load, net_load) ->
- Tab = Load#net_load.table,
- ReplyTo = Load#net_load.opt_reply_to,
- Reason = Load#net_load.reason,
- LocalC = val({Tab, local_content}),
- AccessMode = val({Tab, access_mode}),
- ReadNode = val({Tab, where_to_read}),
- Active = filter_active(Tab),
- Done = #loader_done{is_loaded = true,
- table_name = Tab,
- needs_announce = false,
- needs_sync = false,
- needs_reply = true,
- reply_to = ReplyTo,
- reply = {loaded, ok}
- },
- if
- ReadNode == node() ->
- %% Already loaded locally
- Done;
- LocalC == true ->
- Res = mnesia_loader:disc_load_table(Tab, load_local_content),
- Done#loader_done{reply = Res, needs_announce = true, needs_sync = true};
- AccessMode == read_only ->
- disc_load_table(Tab, Reason, ReplyTo);
- true ->
- %% Either we cannot read the table yet
- %% or someone is moving a replica between
- %% two nodes
- Cs = Load#net_load.cstruct,
- Res = mnesia_loader:net_load_table(Tab, Reason, Active, Cs),
- case Res of
- {loaded, ok} ->
- Done#loader_done{needs_sync = true,
- reply = Res};
- {not_loaded, storage_unknown} ->
- Done#loader_done{reply = Res};
- {not_loaded, _} ->
- Done#loader_done{is_loaded = false,
- needs_reply = false,
- reply = Res}
- end
- end;
-
-load_table(Load) when record(Load, disc_load) ->
- Tab = Load#disc_load.table,
- Reason = Load#disc_load.reason,
- ReplyTo = Load#disc_load.opt_reply_to,
- ReadNode = val({Tab, where_to_read}),
- Active = filter_active(Tab),
- Done = #loader_done{is_loaded = true,
- table_name = Tab,
- needs_announce = false,
- needs_sync = false,
- needs_reply = false
- },
- if
- Active == [], ReadNode == nowhere ->
- %% Not loaded anywhere, lets load it from disc
- disc_load_table(Tab, Reason, ReplyTo);
- ReadNode == nowhere ->
- %% Already loaded on other node, lets get it
- Cs = val({Tab, cstruct}),
- case mnesia_loader:net_load_table(Tab, Reason, Active, Cs) of
- {loaded, ok} ->
- Done#loader_done{needs_sync = true};
- {not_loaded, storage_unknown} ->
- Done#loader_done{is_loaded = false};
- {not_loaded, ErrReason} ->
- Done#loader_done{is_loaded = false,
- reply = {not_loaded,ErrReason}}
- end;
- true ->
- %% Already readable, do not worry be happy
- Done
- end.
-
-disc_load_table(Tab, Reason, ReplyTo) ->
- Done = #loader_done{is_loaded = true,
- table_name = Tab,
- needs_announce = false,
- needs_sync = false,
- needs_reply = true,
- reply_to = ReplyTo,
- reply = {loaded, ok}
- },
- Res = mnesia_loader:disc_load_table(Tab, Reason),
- if
- Res == {loaded, ok} ->
- Done#loader_done{needs_announce = true,
- needs_sync = true,
- reply = Res};
- ReplyTo /= undefined ->
- Done#loader_done{is_loaded = false,
- reply = Res};
- true ->
- fatal("Cannot load table ~p from disc: ~p~n", [Tab, Res])
- end.
-
-filter_active(Tab) ->
- ByForce = val({Tab, load_by_force}),
- Active = val({Tab, active_replicas}),
- Masters = mnesia_recover:get_master_nodes(Tab),
- do_filter_active(ByForce, Active, Masters).
-
-do_filter_active(true, Active, _Masters) ->
- Active;
-do_filter_active(false, Active, []) ->
- Active;
-do_filter_active(false, Active, Masters) ->
- mnesia_lib:intersect(Active, Masters).
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_dumper.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_dumper.erl
deleted file mode 100644
index bbdb04589b..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_dumper.erl
+++ /dev/null
@@ -1,1092 +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: mnesia_dumper.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
-%%
--module(mnesia_dumper).
-
-%% The InitBy arg may be one of the following:
-%% scan_decisions Initial scan for decisions
-%% startup Initial dump during startup
-%% schema_prepare Dump initiated during schema transaction preparation
-%% schema_update Dump initiated during schema transaction commit
-%% fast_schema_update A schema_update, but ignores the log file
-%% user Dump initiated by user
-%% write_threshold Automatic dump caused by too many log writes
-%% time_threshold Automatic dump caused by timeout
-
-%% Public interface
--export([
- get_log_writes/0,
- incr_log_writes/0,
- raw_dump_table/2,
- raw_named_dump_table/2,
- start_regulator/0,
- opt_dump_log/1,
- update/3
- ]).
-
- %% Internal stuff
--export([regulator_init/1]).
-
--include("mnesia.hrl").
--include_lib("kernel/include/file.hrl").
-
--import(mnesia_lib, [fatal/2, dbg_out/2]).
-
--define(REGULATOR_NAME, mnesia_dumper_load_regulator).
--define(DumpToEtsMultiplier, 4).
-
--record(state, {initiated_by = nobody,
- dumper = nopid,
- regulator_pid,
- supervisor_pid,
- queue = [],
- timeout}).
-
-get_log_writes() ->
- Max = mnesia_monitor:get_env(dump_log_write_threshold),
- Prev = mnesia_lib:read_counter(trans_log_writes),
- Left = mnesia_lib:read_counter(trans_log_writes_left),
- Diff = Max - Left,
- Prev + Diff.
-
-incr_log_writes() ->
- Left = mnesia_lib:incr_counter(trans_log_writes_left, -1),
- if
- Left > 0 ->
- ignore;
- true ->
- adjust_log_writes(true)
- end.
-
-adjust_log_writes(DoCast) ->
- Token = {mnesia_adjust_log_writes, self()},
- case global:set_lock(Token, [node()], 1) of
- false ->
- ignore; %% Somebody else is sending a dump request
- true ->
- case DoCast of
- false ->
- ignore;
- true ->
- mnesia_controller:async_dump_log(write_threshold)
- end,
- Max = mnesia_monitor:get_env(dump_log_write_threshold),
- Left = mnesia_lib:read_counter(trans_log_writes_left),
- %% Don't care if we lost a few writes
- mnesia_lib:set_counter(trans_log_writes_left, Max),
- Diff = Max - Left,
- mnesia_lib:incr_counter(trans_log_writes, Diff),
- global:del_lock(Token, [node()])
- end.
-
-%% Returns 'ok' or exits
-opt_dump_log(InitBy) ->
- Reg = case whereis(?REGULATOR_NAME) of
- undefined ->
- nopid;
- Pid when pid(Pid) ->
- Pid
- end,
- perform_dump(InitBy, Reg).
-
-%% Scan for decisions
-perform_dump(InitBy, Regulator) when InitBy == scan_decisions ->
- ?eval_debug_fun({?MODULE, perform_dump}, [InitBy]),
-
- dbg_out("Transaction log dump initiated by ~w~n", [InitBy]),
- scan_decisions(mnesia_log:previous_log_file(), InitBy, Regulator),
- scan_decisions(mnesia_log:latest_log_file(), InitBy, Regulator);
-
-%% Propagate the log into the DAT-files
-perform_dump(InitBy, Regulator) ->
- ?eval_debug_fun({?MODULE, perform_dump}, [InitBy]),
- LogState = mnesia_log:prepare_log_dump(InitBy),
- dbg_out("Transaction log dump initiated by ~w: ~w~n",
- [InitBy, LogState]),
- adjust_log_writes(false),
- mnesia_recover:allow_garb(),
- case LogState of
- already_dumped ->
- dumped;
- {needs_dump, Diff} ->
- U = mnesia_monitor:get_env(dump_log_update_in_place),
- Cont = mnesia_log:init_log_dump(),
- case catch do_perform_dump(Cont, U, InitBy, Regulator, undefined) of
- ok ->
- ?eval_debug_fun({?MODULE, post_dump}, [InitBy]),
- case mnesia_monitor:use_dir() of
- true ->
- mnesia_recover:dump_decision_tab();
- false ->
- mnesia_log:purge_some_logs()
- end,
- %% And now to the crucial point...
- mnesia_log:confirm_log_dump(Diff);
- {error, Reason} ->
- {error, Reason};
- {'EXIT', {Desc, Reason}} ->
- case mnesia_monitor:get_env(auto_repair) of
- true ->
- mnesia_lib:important(Desc, Reason),
- %% Ignore rest of the log
- mnesia_log:confirm_log_dump(Diff);
- false ->
- fatal(Desc, Reason)
- end
- end;
- {error, Reason} ->
- {error, {"Cannot prepare log dump", Reason}}
- end.
-
-scan_decisions(Fname, InitBy, Regulator) ->
- Exists = mnesia_lib:exists(Fname),
- case Exists of
- false ->
- ok;
- true ->
- Header = mnesia_log:trans_log_header(),
- Name = previous_log,
- mnesia_log:open_log(Name, Header, Fname, Exists,
- mnesia_monitor:get_env(auto_repair), read_only),
- Cont = start,
- Res = (catch do_perform_dump(Cont, false, InitBy, Regulator, undefined)),
- mnesia_log:close_log(Name),
- case Res of
- ok -> ok;
- {'EXIT', Reason} -> {error, Reason}
- end
- end.
-
-do_perform_dump(Cont, InPlace, InitBy, Regulator, OldVersion) ->
- case mnesia_log:chunk_log(Cont) of
- {C2, Recs} ->
- case catch insert_recs(Recs, InPlace, InitBy, Regulator, OldVersion) of
- {'EXIT', R} ->
- Reason = {"Transaction log dump error: ~p~n", [R]},
- close_files(InPlace, {error, Reason}, InitBy),
- exit(Reason);
- Version ->
- do_perform_dump(C2, InPlace, InitBy, Regulator, Version)
- end;
- eof ->
- close_files(InPlace, ok, InitBy),
- ok
- end.
-
-insert_recs([Rec | Recs], InPlace, InitBy, Regulator, LogV) ->
- regulate(Regulator),
- case insert_rec(Rec, InPlace, InitBy, LogV) of
- LogH when record(LogH, log_header) ->
- insert_recs(Recs, InPlace, InitBy, Regulator, LogH#log_header.log_version);
- _ ->
- insert_recs(Recs, InPlace, InitBy, Regulator, LogV)
- end;
-
-insert_recs([], _InPlace, _InitBy, _Regulator, Version) ->
- Version.
-
-insert_rec(Rec, _InPlace, scan_decisions, _LogV) ->
- if
- record(Rec, commit) ->
- ignore;
- record(Rec, log_header) ->
- ignore;
- true ->
- mnesia_recover:note_log_decision(Rec, scan_decisions)
- end;
-insert_rec(Rec, InPlace, InitBy, LogV) when record(Rec, commit) ->
- %% Determine the Outcome of the transaction and recover it
- D = Rec#commit.decision,
- case mnesia_recover:wait_for_decision(D, InitBy) of
- {Tid, committed} ->
- do_insert_rec(Tid, Rec, InPlace, InitBy, LogV);
- {Tid, aborted} ->
- mnesia_schema:undo_prepare_commit(Tid, Rec)
- end;
-insert_rec(H, _InPlace, _InitBy, _LogV) when record(H, log_header) ->
- CurrentVersion = mnesia_log:version(),
- if
- H#log_header.log_kind /= trans_log ->
- exit({"Bad kind of transaction log", H});
- H#log_header.log_version == CurrentVersion ->
- ok;
- H#log_header.log_version == "4.2" ->
- ok;
- H#log_header.log_version == "4.1" ->
- ok;
- H#log_header.log_version == "4.0" ->
- ok;
- true ->
- fatal("Bad version of transaction log: ~p~n", [H])
- end,
- H;
-
-insert_rec(_Rec, _InPlace, _InitBy, _LogV) ->
- ok.
-
-do_insert_rec(Tid, Rec, InPlace, InitBy, LogV) ->
- case Rec#commit.schema_ops of
- [] ->
- ignore;
- SchemaOps ->
- case val({schema, storage_type}) of
- ram_copies ->
- insert_ops(Tid, schema_ops, SchemaOps, InPlace, InitBy, LogV);
- Storage ->
- true = open_files(schema, Storage, InPlace, InitBy),
- insert_ops(Tid, schema_ops, SchemaOps, InPlace, InitBy, LogV)
- end
- end,
- D = Rec#commit.disc_copies,
- insert_ops(Tid, disc_copies, D, InPlace, InitBy, LogV),
- case InitBy of
- startup ->
- DO = Rec#commit.disc_only_copies,
- insert_ops(Tid, disc_only_copies, DO, InPlace, InitBy, LogV);
- _ ->
- ignore
- end.
-
-
-update(_Tid, [], _DumperMode) ->
- dumped;
-update(Tid, SchemaOps, DumperMode) ->
- UseDir = mnesia_monitor:use_dir(),
- Res = perform_update(Tid, SchemaOps, DumperMode, UseDir),
- mnesia_controller:release_schema_commit_lock(),
- Res.
-
-perform_update(_Tid, _SchemaOps, mandatory, true) ->
- %% Force a dump of the transaction log in order to let the
- %% dumper perform needed updates
-
- InitBy = schema_update,
- ?eval_debug_fun({?MODULE, dump_schema_op}, [InitBy]),
- opt_dump_log(InitBy);
-perform_update(Tid, SchemaOps, _DumperMode, _UseDir) ->
- %% No need for a full transaction log dump.
- %% Ignore the log file and perform only perform
- %% the corresponding updates.
-
- InitBy = fast_schema_update,
- InPlace = mnesia_monitor:get_env(dump_log_update_in_place),
- ?eval_debug_fun({?MODULE, dump_schema_op}, [InitBy]),
- case catch insert_ops(Tid, schema_ops, SchemaOps, InPlace, InitBy,
- mnesia_log:version()) of
- {'EXIT', Reason} ->
- Error = {error, {"Schema update error", Reason}},
- close_files(InPlace, Error, InitBy),
- fatal("Schema update error ~p ~p", [Reason, SchemaOps]);
- _ ->
- ?eval_debug_fun({?MODULE, post_dump}, [InitBy]),
- close_files(InPlace, ok, InitBy),
- ok
- end.
-
-insert_ops(_Tid, _Storage, [], _InPlace, _InitBy, _) -> ok;
-insert_ops(Tid, Storage, [Op], InPlace, InitBy, Ver) when Ver >= "4.3"->
- insert_op(Tid, Storage, Op, InPlace, InitBy),
- ok;
-insert_ops(Tid, Storage, [Op | Ops], InPlace, InitBy, Ver) when Ver >= "4.3"->
- insert_op(Tid, Storage, Op, InPlace, InitBy),
- insert_ops(Tid, Storage, Ops, InPlace, InitBy, Ver);
-insert_ops(Tid, Storage, [Op | Ops], InPlace, InitBy, Ver) when Ver < "4.3" ->
- insert_ops(Tid, Storage, Ops, InPlace, InitBy, Ver),
- insert_op(Tid, Storage, Op, InPlace, InitBy).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Normal ops
-
-disc_insert(_Tid, Storage, Tab, Key, Val, Op, InPlace, InitBy) ->
- case open_files(Tab, Storage, InPlace, InitBy) of
- true ->
- case Storage of
- disc_copies when Tab /= schema ->
- mnesia_log:append({?MODULE,Tab}, {{Tab, Key}, Val, Op}),
- ok;
- _ ->
- case Op of
- write ->
- ok = dets:insert(Tab, Val);
- delete ->
- ok = dets:delete(Tab, Key);
- update_counter ->
- {RecName, Incr} = Val,
- case catch dets:update_counter(Tab, Key, Incr) of
- CounterVal when integer(CounterVal) ->
- ok;
- _ ->
- Zero = {RecName, Key, 0},
- ok = dets:insert(Tab, Zero)
- end;
- delete_object ->
- ok = dets:delete_object(Tab, Val);
- clear_table ->
- ok = dets:match_delete(Tab, '_')
- end
- end;
- false ->
- ignore
- end.
-
-insert(Tid, Storage, Tab, Key, [Val | Tail], Op, InPlace, InitBy) ->
- insert(Tid, Storage, Tab, Key, Val, Op, InPlace, InitBy),
- insert(Tid, Storage, Tab, Key, Tail, Op, InPlace, InitBy);
-
-insert(_Tid, _Storage, _Tab, _Key, [], _Op, _InPlace, _InitBy) ->
- ok;
-
-insert(Tid, Storage, Tab, Key, Val, Op, InPlace, InitBy) ->
- Item = {{Tab, Key}, Val, Op},
- case InitBy of
- startup ->
- disc_insert(Tid, Storage, Tab, Key, Val, Op, InPlace, InitBy);
-
- _ when Storage == ram_copies ->
- mnesia_tm:do_update_op(Tid, Storage, Item),
- Snmp = mnesia_tm:prepare_snmp(Tab, Key, [Item]),
- mnesia_tm:do_snmp(Tid, Snmp);
-
- _ when Storage == disc_copies ->
- disc_insert(Tid, Storage, Tab, Key, Val, Op, InPlace, InitBy),
- mnesia_tm:do_update_op(Tid, Storage, Item),
- Snmp = mnesia_tm:prepare_snmp(Tab, Key, [Item]),
- mnesia_tm:do_snmp(Tid, Snmp);
-
- _ when Storage == disc_only_copies ->
- mnesia_tm:do_update_op(Tid, Storage, Item),
- Snmp = mnesia_tm:prepare_snmp(Tab, Key, [Item]),
- mnesia_tm:do_snmp(Tid, Snmp);
-
- _ when Storage == unknown ->
- ignore
- end.
-
-disc_delete_table(Tab, Storage) ->
- case mnesia_monitor:use_dir() of
- true ->
- if
- Storage == disc_only_copies; Tab == schema ->
- mnesia_monitor:unsafe_close_dets(Tab),
- Dat = mnesia_lib:tab2dat(Tab),
- file:delete(Dat);
- true ->
- DclFile = mnesia_lib:tab2dcl(Tab),
- case get({?MODULE,Tab}) of
- {opened_dumper, dcl} ->
- del_opened_tab(Tab),
- mnesia_log:unsafe_close_log(Tab);
- _ ->
- ok
- end,
- file:delete(DclFile),
- DcdFile = mnesia_lib:tab2dcd(Tab),
- file:delete(DcdFile),
- ok
- end,
- erase({?MODULE, Tab});
- false ->
- ignore
- end.
-
-disc_delete_indecies(_Tab, _Cs, Storage) when Storage /= disc_only_copies ->
- ignore;
-disc_delete_indecies(Tab, Cs, disc_only_copies) ->
- Indecies = Cs#cstruct.index,
- mnesia_index:del_transient(Tab, Indecies, disc_only_copies).
-
-insert_op(Tid, Storage, {{Tab, Key}, Val, Op}, InPlace, InitBy) ->
- %% Propagate to disc only
- disc_insert(Tid, Storage, Tab, Key, Val, Op, InPlace, InitBy);
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% NOTE that all operations below will only
-%% be performed if the dump is initiated by
-%% startup or fast_schema_update
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-insert_op(_Tid, schema_ops, _OP, _InPlace, Initby)
- when Initby /= startup,
- Initby /= fast_schema_update,
- Initby /= schema_update ->
- ignore;
-
-insert_op(Tid, _, {op, rec, Storage, Item}, InPlace, InitBy) ->
- {{Tab, Key}, ValList, Op} = Item,
- insert(Tid, Storage, Tab, Key, ValList, Op, InPlace, InitBy);
-
-insert_op(Tid, _, {op, change_table_copy_type, N, FromS, ToS, TabDef}, InPlace, InitBy) ->
- Cs = mnesia_schema:list2cs(TabDef),
- Val = mnesia_schema:insert_cstruct(Tid, Cs, true), % Update ram only
- {schema, Tab, _} = Val,
- if
- InitBy /= startup ->
- mnesia_controller:add_active_replica(Tab, N, Cs);
- true ->
- ignore
- end,
- if
- N == node() ->
- Dmp = mnesia_lib:tab2dmp(Tab),
- Dat = mnesia_lib:tab2dat(Tab),
- Dcd = mnesia_lib:tab2dcd(Tab),
- Dcl = mnesia_lib:tab2dcl(Tab),
- case {FromS, ToS} of
- {ram_copies, disc_copies} when Tab == schema ->
- ok = ensure_rename(Dmp, Dat);
- {ram_copies, disc_copies} ->
- file:delete(Dcl),
- ok = ensure_rename(Dmp, Dcd);
- {disc_copies, ram_copies} when Tab == schema ->
- mnesia_lib:set(use_dir, false),
- mnesia_monitor:unsafe_close_dets(Tab),
- file:delete(Dat);
- {disc_copies, ram_copies} ->
- file:delete(Dcl),
- file:delete(Dcd);
- {ram_copies, disc_only_copies} ->
- ok = ensure_rename(Dmp, Dat),
- true = open_files(Tab, disc_only_copies, InPlace, InitBy),
- %% ram_delete_table must be done before init_indecies,
- %% it uses info which is reset in init_indecies,
- %% it doesn't matter, because init_indecies don't use
- %% the ram replica of the table when creating the disc
- %% index; Could be improved :)
- mnesia_schema:ram_delete_table(Tab, FromS),
- PosList = Cs#cstruct.index,
- mnesia_index:init_indecies(Tab, disc_only_copies, PosList);
- {disc_only_copies, ram_copies} ->
- mnesia_monitor:unsafe_close_dets(Tab),
- disc_delete_indecies(Tab, Cs, disc_only_copies),
- case InitBy of
- startup ->
- ignore;
- _ ->
- mnesia_controller:get_disc_copy(Tab)
- end,
- disc_delete_table(Tab, disc_only_copies);
- {disc_copies, disc_only_copies} ->
- ok = ensure_rename(Dmp, Dat),
- true = open_files(Tab, disc_only_copies, InPlace, InitBy),
- mnesia_schema:ram_delete_table(Tab, FromS),
- PosList = Cs#cstruct.index,
- mnesia_index:init_indecies(Tab, disc_only_copies, PosList),
- file:delete(Dcl),
- file:delete(Dcd);
- {disc_only_copies, disc_copies} ->
- mnesia_monitor:unsafe_close_dets(Tab),
- disc_delete_indecies(Tab, Cs, disc_only_copies),
- case InitBy of
- startup ->
- ignore;
- _ ->
- mnesia_log:ets2dcd(Tab),
- mnesia_controller:get_disc_copy(Tab),
- disc_delete_table(Tab, disc_only_copies)
- end
- end;
- true ->
- ignore
- end,
- S = val({schema, storage_type}),
- disc_insert(Tid, S, schema, Tab, Val, write, InPlace, InitBy);
-
-insert_op(Tid, _, {op, transform, _Fun, TabDef}, InPlace, InitBy) ->
- Cs = mnesia_schema:list2cs(TabDef),
- case mnesia_lib:cs_to_storage_type(node(), Cs) of
- disc_copies ->
- open_dcl(Cs#cstruct.name);
- _ ->
- ignore
- end,
- insert_cstruct(Tid, Cs, true, InPlace, InitBy);
-
-%%% Operations below this are handled without using the logg.
-
-insert_op(Tid, _, {op, restore_recreate, TabDef}, InPlace, InitBy) ->
- Cs = mnesia_schema:list2cs(TabDef),
- Tab = Cs#cstruct.name,
- Type = Cs#cstruct.type,
- Storage = mnesia_lib:cs_to_storage_type(node(), Cs),
- %% Delete all possbibly existing files and tables
- disc_delete_table(Tab, Storage),
- disc_delete_indecies(Tab, Cs, Storage),
- case InitBy of
- startup ->
- ignore;
- _ ->
- mnesia_schema:ram_delete_table(Tab, Storage),
- mnesia_checkpoint:tm_del_copy(Tab, node())
- end,
- %% delete_cstruct(Tid, Cs, InPlace, InitBy),
- %% And create new ones..
- if
- (InitBy == startup) or (Storage == unknown) ->
- ignore;
- Storage == ram_copies ->
- Args = [{keypos, 2}, public, named_table, Type],
- mnesia_monitor:mktab(Tab, Args);
- Storage == disc_copies ->
- Args = [{keypos, 2}, public, named_table, Type],
- mnesia_monitor:mktab(Tab, Args),
- File = mnesia_lib:tab2dcd(Tab),
- FArg = [{file, File}, {name, {mnesia,create}},
- {repair, false}, {mode, read_write}],
- {ok, Log} = mnesia_monitor:open_log(FArg),
- mnesia_monitor:unsafe_close_log(Log);
- Storage == disc_only_copies ->
- File = mnesia_lib:tab2dat(Tab),
- file:delete(File),
- Args = [{file, mnesia_lib:tab2dat(Tab)},
- {type, mnesia_lib:disk_type(Tab, Type)},
- {keypos, 2},
- {repair, mnesia_monitor:get_env(auto_repair)}],
- mnesia_monitor:open_dets(Tab, Args)
- end,
- insert_op(Tid, ignore, {op, create_table, TabDef}, InPlace, InitBy);
-
-insert_op(Tid, _, {op, create_table, TabDef}, InPlace, InitBy) ->
- Cs = mnesia_schema:list2cs(TabDef),
- insert_cstruct(Tid, Cs, false, InPlace, InitBy),
- Tab = Cs#cstruct.name,
- Storage = mnesia_lib:cs_to_storage_type(node(), Cs),
- case InitBy of
- startup ->
- case Storage of
- unknown ->
- ignore;
- ram_copies ->
- ignore;
- disc_copies ->
- Dcd = mnesia_lib:tab2dcd(Tab),
- case mnesia_lib:exists(Dcd) of
- true -> ignore;
- false ->
- mnesia_log:open_log(temp,
- mnesia_log:dcl_log_header(),
- Dcd,
- false,
- false,
- read_write),
- mnesia_log:unsafe_close_log(temp)
- end;
- _ ->
- Args = [{file, mnesia_lib:tab2dat(Tab)},
- {type, mnesia_lib:disk_type(Tab, Cs#cstruct.type)},
- {keypos, 2},
- {repair, mnesia_monitor:get_env(auto_repair)}],
- case mnesia_monitor:open_dets(Tab, Args) of
- {ok, _} ->
- mnesia_monitor:unsafe_close_dets(Tab);
- {error, Error} ->
- exit({"Failed to create dets table", Error})
- end
- end;
- _ ->
- Copies = mnesia_lib:copy_holders(Cs),
- Active = mnesia_lib:intersect(Copies, val({current, db_nodes})),
- [mnesia_controller:add_active_replica(Tab, N, Cs) || N <- Active],
-
- case Storage of
- unknown ->
- case Cs#cstruct.local_content of
- true ->
- ignore;
- false ->
- mnesia_lib:set_remote_where_to_read(Tab)
- end;
- _ ->
- case Cs#cstruct.local_content of
- true ->
- mnesia_lib:set_local_content_whereabouts(Tab);
- false ->
- mnesia_lib:set({Tab, where_to_read}, node())
- end,
- case Storage of
- ram_copies ->
- ignore;
- _ ->
- %% Indecies are still created by loader
- disc_delete_indecies(Tab, Cs, Storage)
- %% disc_delete_table(Tab, Storage)
- end,
-
- %% Update whereabouts and create table
- mnesia_controller:create_table(Tab)
- end
- end;
-
-insert_op(_Tid, _, {op, dump_table, Size, TabDef}, _InPlace, _InitBy) ->
- case Size of
- unknown ->
- ignore;
- _ ->
- Cs = mnesia_schema:list2cs(TabDef),
- Tab = Cs#cstruct.name,
- Dmp = mnesia_lib:tab2dmp(Tab),
- Dat = mnesia_lib:tab2dcd(Tab),
- case Size of
- 0 ->
- %% Assume that table files already are closed
- file:delete(Dmp),
- file:delete(Dat);
- _ ->
- ok = ensure_rename(Dmp, Dat)
- end
- end;
-
-insert_op(Tid, _, {op, delete_table, TabDef}, InPlace, InitBy) ->
- Cs = mnesia_schema:list2cs(TabDef),
- Tab = Cs#cstruct.name,
- case mnesia_lib:cs_to_storage_type(node(), Cs) of
- unknown ->
- ignore;
- Storage ->
- disc_delete_table(Tab, Storage),
- disc_delete_indecies(Tab, Cs, Storage),
- case InitBy of
- startup ->
- ignore;
- _ ->
- mnesia_schema:ram_delete_table(Tab, Storage),
- mnesia_checkpoint:tm_del_copy(Tab, node())
- end
- end,
- delete_cstruct(Tid, Cs, InPlace, InitBy);
-
-insert_op(Tid, _, {op, clear_table, TabDef}, InPlace, InitBy) ->
- Cs = mnesia_schema:list2cs(TabDef),
- Tab = Cs#cstruct.name,
- case mnesia_lib:cs_to_storage_type(node(), Cs) of
- unknown ->
- ignore;
- Storage ->
- Oid = '_', %%val({Tab, wild_pattern}),
- if Storage == disc_copies ->
- open_dcl(Cs#cstruct.name);
- true ->
- ignore
- end,
- insert(Tid, Storage, Tab, '_', Oid, clear_table, InPlace, InitBy)
- end;
-
-insert_op(Tid, _, {op, merge_schema, TabDef}, InPlace, InitBy) ->
- Cs = mnesia_schema:list2cs(TabDef),
- insert_cstruct(Tid, Cs, false, InPlace, InitBy);
-
-insert_op(Tid, _, {op, del_table_copy, Storage, Node, TabDef}, InPlace, InitBy) ->
- Cs = mnesia_schema:list2cs(TabDef),
- Tab = Cs#cstruct.name,
- if
- Tab == schema, Storage == ram_copies ->
- insert_cstruct(Tid, Cs, true, InPlace, InitBy);
- Tab /= schema ->
- mnesia_controller:del_active_replica(Tab, Node),
- mnesia_lib:del({Tab, Storage}, Node),
- if
- Node == node() ->
- case Cs#cstruct.local_content of
- true -> mnesia_lib:set({Tab, where_to_read}, nowhere);
- false -> mnesia_lib:set_remote_where_to_read(Tab)
- end,
- mnesia_lib:del({schema, local_tables}, Tab),
- mnesia_lib:set({Tab, storage_type}, unknown),
- insert_cstruct(Tid, Cs, true, InPlace, InitBy),
- disc_delete_table(Tab, Storage),
- disc_delete_indecies(Tab, Cs, Storage),
- mnesia_schema:ram_delete_table(Tab, Storage),
- mnesia_checkpoint:tm_del_copy(Tab, Node);
- true ->
- case val({Tab, where_to_read}) of
- Node ->
- mnesia_lib:set_remote_where_to_read(Tab);
- _ ->
- ignore
- end,
- insert_cstruct(Tid, Cs, true, InPlace, InitBy)
- end
- end;
-
-insert_op(Tid, _, {op, add_table_copy, _Storage, _Node, TabDef}, InPlace, InitBy) ->
- %% During prepare commit, the files was created
- %% and the replica was announced
- Cs = mnesia_schema:list2cs(TabDef),
- insert_cstruct(Tid, Cs, true, InPlace, InitBy);
-
-insert_op(Tid, _, {op, add_snmp, _Us, TabDef}, InPlace, InitBy) ->
- Cs = mnesia_schema:list2cs(TabDef),
- insert_cstruct(Tid, Cs, true, InPlace, InitBy);
-
-insert_op(Tid, _, {op, del_snmp, TabDef}, InPlace, InitBy) ->
- Cs = mnesia_schema:list2cs(TabDef),
- Tab = Cs#cstruct.name,
- Storage = mnesia_lib:cs_to_storage_type(node(), Cs),
- if
- InitBy /= startup,
- Storage /= unknown ->
- case ?catch_val({Tab, {index, snmp}}) of
- {'EXIT', _} ->
- ignore;
- Stab ->
- mnesia_snmp_hook:delete_table(Tab, Stab),
- mnesia_lib:unset({Tab, {index, snmp}})
- end;
- true ->
- ignore
- end,
- insert_cstruct(Tid, Cs, true, InPlace, InitBy);
-
-insert_op(Tid, _, {op, add_index, Pos, TabDef}, InPlace, InitBy) ->
- Cs = mnesia_schema:list2cs(TabDef),
- Tab = insert_cstruct(Tid, Cs, true, InPlace, InitBy),
- Storage = mnesia_lib:cs_to_storage_type(node(), Cs),
- case InitBy of
- startup when Storage == disc_only_copies ->
- mnesia_index:init_indecies(Tab, Storage, [Pos]);
- startup ->
- ignore;
- _ ->
- mnesia_index:init_indecies(Tab, Storage, [Pos])
- end;
-
-insert_op(Tid, _, {op, del_index, Pos, TabDef}, InPlace, InitBy) ->
- Cs = mnesia_schema:list2cs(TabDef),
- Tab = Cs#cstruct.name,
- Storage = mnesia_lib:cs_to_storage_type(node(), Cs),
- case InitBy of
- startup when Storage == disc_only_copies ->
- mnesia_index:del_index_table(Tab, Storage, Pos);
- startup ->
- ignore;
- _ ->
- mnesia_index:del_index_table(Tab, Storage, Pos)
- end,
- insert_cstruct(Tid, Cs, true, InPlace, InitBy);
-
-insert_op(Tid, _, {op, change_table_access_mode,TabDef, _OldAccess, _Access}, InPlace, InitBy) ->
- Cs = mnesia_schema:list2cs(TabDef),
- case InitBy of
- startup -> ignore;
- _ -> mnesia_controller:change_table_access_mode(Cs)
- end,
- insert_cstruct(Tid, Cs, true, InPlace, InitBy);
-
-insert_op(Tid, _, {op, change_table_load_order, TabDef, _OldLevel, _Level}, InPlace, InitBy) ->
- Cs = mnesia_schema:list2cs(TabDef),
- insert_cstruct(Tid, Cs, true, InPlace, InitBy);
-
-insert_op(Tid, _, {op, delete_property, TabDef, PropKey}, InPlace, InitBy) ->
- Cs = mnesia_schema:list2cs(TabDef),
- Tab = Cs#cstruct.name,
- mnesia_lib:unset({Tab, user_property, PropKey}),
- insert_cstruct(Tid, Cs, true, InPlace, InitBy);
-
-insert_op(Tid, _, {op, write_property, TabDef, _Prop}, InPlace, InitBy) ->
- Cs = mnesia_schema:list2cs(TabDef),
- insert_cstruct(Tid, Cs, true, InPlace, InitBy);
-
-insert_op(Tid, _, {op, change_table_frag, _Change, TabDef}, InPlace, InitBy) ->
- Cs = mnesia_schema:list2cs(TabDef),
- insert_cstruct(Tid, Cs, true, InPlace, InitBy).
-
-open_files(Tab, Storage, UpdateInPlace, InitBy)
- when Storage /= unknown, Storage /= ram_copies ->
- case get({?MODULE, Tab}) of
- undefined ->
- case ?catch_val({Tab, setorbag}) of
- {'EXIT', _} ->
- false;
- Type ->
- case Storage of
- disc_copies when Tab /= schema ->
- Bool = open_disc_copies(Tab, InitBy),
- Bool;
- _ ->
- Fname = prepare_open(Tab, UpdateInPlace),
- Args = [{file, Fname},
- {keypos, 2},
- {repair, mnesia_monitor:get_env(auto_repair)},
- {type, mnesia_lib:disk_type(Tab, Type)}],
- {ok, _} = mnesia_monitor:open_dets(Tab, Args),
- put({?MODULE, Tab}, {opened_dumper, dat}),
- true
- end
- end;
- already_dumped ->
- false;
- {opened_dumper, _} ->
- true
- end;
-open_files(_Tab, _Storage, _UpdateInPlace, _InitBy) ->
- false.
-
-open_disc_copies(Tab, InitBy) ->
- DclF = mnesia_lib:tab2dcl(Tab),
- DumpEts =
- case file:read_file_info(DclF) of
- {error, enoent} ->
- false;
- {ok, DclInfo} ->
- DcdF = mnesia_lib:tab2dcd(Tab),
- case file:read_file_info(DcdF) of
- {error, Reason} ->
- mnesia_lib:dbg_out("File ~p info_error ~p ~n",
- [DcdF, Reason]),
- true;
- {ok, DcdInfo} ->
- DcdInfo#file_info.size =<
- (DclInfo#file_info.size *
- ?DumpToEtsMultiplier)
- end
- end,
- if
- DumpEts == false; InitBy == startup ->
- mnesia_log:open_log({?MODULE,Tab},
- mnesia_log:dcl_log_header(),
- DclF,
- mnesia_lib:exists(DclF),
- mnesia_monitor:get_env(auto_repair),
- read_write),
- put({?MODULE, Tab}, {opened_dumper, dcl}),
- true;
- true ->
- mnesia_log:ets2dcd(Tab),
- put({?MODULE, Tab}, already_dumped),
- false
- end.
-
-%% Always opens the dcl file for writing overriding already_dumped
-%% mechanismen, used for schema transactions.
-open_dcl(Tab) ->
- case get({?MODULE, Tab}) of
- {opened_dumper, _} ->
- true;
- _ -> %% undefined or already_dumped
- DclF = mnesia_lib:tab2dcl(Tab),
- mnesia_log:open_log({?MODULE,Tab},
- mnesia_log:dcl_log_header(),
- DclF,
- mnesia_lib:exists(DclF),
- mnesia_monitor:get_env(auto_repair),
- read_write),
- put({?MODULE, Tab}, {opened_dumper, dcl}),
- true
- end.
-
-prepare_open(Tab, UpdateInPlace) ->
- Dat = mnesia_lib:tab2dat(Tab),
- case UpdateInPlace of
- true ->
- Dat;
- false ->
- Tmp = mnesia_lib:tab2tmp(Tab),
- case catch mnesia_lib:copy_file(Dat, Tmp) of
- ok ->
- Tmp;
- Error ->
- fatal("Cannot copy dets file ~p to ~p: ~p~n",
- [Dat, Tmp, Error])
- end
- end.
-
-del_opened_tab(Tab) ->
- erase({?MODULE, Tab}).
-
-close_files(UpdateInPlace, Outcome, InitBy) -> % Update in place
- close_files(UpdateInPlace, Outcome, InitBy, get()).
-
-close_files(InPlace, Outcome, InitBy, [{{?MODULE, Tab}, already_dumped} | Tail]) ->
- erase({?MODULE, Tab}),
- close_files(InPlace, Outcome, InitBy, Tail);
-close_files(InPlace, Outcome, InitBy, [{{?MODULE, Tab}, {opened_dumper, Type}} | Tail]) ->
- erase({?MODULE, Tab}),
- case val({Tab, storage_type}) of
- disc_only_copies when InitBy /= startup ->
- ignore;
- disc_copies when Tab /= schema ->
- mnesia_log:close_log({?MODULE,Tab});
- Storage ->
- do_close(InPlace, Outcome, Tab, Type, Storage)
- end,
- close_files(InPlace, Outcome, InitBy, Tail);
-
-close_files(InPlace, Outcome, InitBy, [_ | Tail]) ->
- close_files(InPlace, Outcome, InitBy, Tail);
-close_files(_, _, _InitBy, []) ->
- ok.
-
-%% If storage is unknown during close clean up files, this can happen if timing
-%% is right and dirty_write conflicts with schema operations.
-do_close(_, _, Tab, dcl, unknown) ->
- mnesia_log:close_log({?MODULE,Tab}),
- file:delete(mnesia_lib:tab2dcl(Tab));
-do_close(_, _, Tab, dcl, _) -> %% To be safe, can it happen?
- mnesia_log:close_log({?MODULE,Tab});
-
-do_close(InPlace, Outcome, Tab, dat, Storage) ->
- mnesia_monitor:close_dets(Tab),
- if
- Storage == unknown, InPlace == true ->
- file:delete(mnesia_lib:tab2dat(Tab));
- InPlace == true ->
- %% Update in place
- ok;
- Outcome == ok, Storage /= unknown ->
- %% Success: swap tmp files with dat files
- TabDat = mnesia_lib:tab2dat(Tab),
- ok = file:rename(mnesia_lib:tab2tmp(Tab), TabDat);
- true ->
- file:delete(mnesia_lib:tab2tmp(Tab))
- end.
-
-
-ensure_rename(From, To) ->
- case mnesia_lib:exists(From) of
- true ->
- file:rename(From, To);
- false ->
- case mnesia_lib:exists(To) of
- true ->
- ok;
- false ->
- {error, {rename_failed, From, To}}
- end
- end.
-
-insert_cstruct(Tid, Cs, KeepWhereabouts, InPlace, InitBy) ->
- Val = mnesia_schema:insert_cstruct(Tid, Cs, KeepWhereabouts),
- {schema, Tab, _} = Val,
- S = val({schema, storage_type}),
- disc_insert(Tid, S, schema, Tab, Val, write, InPlace, InitBy),
- Tab.
-
-delete_cstruct(Tid, Cs, InPlace, InitBy) ->
- Val = mnesia_schema:delete_cstruct(Tid, Cs),
- {schema, Tab, _} = Val,
- S = val({schema, storage_type}),
- disc_insert(Tid, S, schema, Tab, Val, delete, InPlace, InitBy),
- Tab.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Raw dump of table. Dumper must have unique access to the ets table.
-
-raw_named_dump_table(Tab, Ftype) ->
- case mnesia_monitor:use_dir() of
- true ->
- mnesia_lib:lock_table(Tab),
- TmpFname = mnesia_lib:tab2tmp(Tab),
- Fname =
- case Ftype of
- dat -> mnesia_lib:tab2dat(Tab);
- dmp -> mnesia_lib:tab2dmp(Tab)
- end,
- file:delete(TmpFname),
- file:delete(Fname),
- TabSize = ?ets_info(Tab, size),
- TabRef = Tab,
- DiskType = mnesia_lib:disk_type(Tab),
- Args = [{file, TmpFname},
- {keypos, 2},
- %% {ram_file, true},
- {estimated_no_objects, TabSize + 256},
- {repair, mnesia_monitor:get_env(auto_repair)},
- {type, DiskType}],
- case mnesia_lib:dets_sync_open(TabRef, Args) of
- {ok, TabRef} ->
- Storage = ram_copies,
- mnesia_lib:db_fixtable(Storage, Tab, true),
-
- case catch raw_dump_table(TabRef, Tab) of
- {'EXIT', Reason} ->
- mnesia_lib:db_fixtable(Storage, Tab, false),
- mnesia_lib:dets_sync_close(Tab),
- file:delete(TmpFname),
- mnesia_lib:unlock_table(Tab),
- exit({"Dump of table to disc failed", Reason});
- ok ->
- mnesia_lib:db_fixtable(Storage, Tab, false),
- mnesia_lib:dets_sync_close(Tab),
- mnesia_lib:unlock_table(Tab),
- ok = file:rename(TmpFname, Fname)
- end;
- {error, Reason} ->
- mnesia_lib:unlock_table(Tab),
- exit({"Open of file before dump to disc failed", Reason})
- end;
- false ->
- exit({has_no_disc, node()})
- end.
-
-raw_dump_table(DetsRef, EtsRef) ->
- dets:from_ets(DetsRef, EtsRef).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Load regulator
-%%
-%% This is a poor mans substitute for a fair scheduler algorithm
-%% in the Erlang emulator. The mnesia_dumper process performs many
-%% costly BIF invokations and must pay for this. But since the
-%% Emulator does not handle this properly we must compensate for
-%% this with some form of load regulation of ourselves in order to
-%% not steal all computation power in the Erlang Emulator ans make
-%% other processes starve. Hopefully this is a temporary solution.
-
-start_regulator() ->
- case mnesia_monitor:get_env(dump_log_load_regulation) of
- false ->
- nopid;
- true ->
- N = ?REGULATOR_NAME,
- case mnesia_monitor:start_proc(N, ?MODULE, regulator_init, [self()]) of
- {ok, Pid} ->
- Pid;
- {error, Reason} ->
- fatal("Failed to start ~n: ~p~n", [N, Reason])
- end
- end.
-
-regulator_init(Parent) ->
- %% No need for trapping exits.
- %% Using low priority causes the regulation
- process_flag(priority, low),
- register(?REGULATOR_NAME, self()),
- proc_lib:init_ack(Parent, {ok, self()}),
- regulator_loop().
-
-regulator_loop() ->
- receive
- {regulate, From} ->
- From ! {regulated, self()},
- regulator_loop();
- {stop, From} ->
- From ! {stopped, self()},
- exit(normal)
- end.
-
-regulate(nopid) ->
- ok;
-regulate(RegulatorPid) ->
- RegulatorPid ! {regulate, self()},
- receive
- {regulated, RegulatorPid} -> ok
- end.
-
-val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
- Value -> Value
- end.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_event.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_event.erl
deleted file mode 100644
index fc0638e1ad..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_event.erl
+++ /dev/null
@@ -1,263 +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: mnesia_event.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
-%%
--module(mnesia_event).
-
--behaviour(gen_event).
-%-behaviour(mnesia_event).
-
-%% gen_event callback interface
--export([init/1,
- handle_event/2,
- handle_call/2,
- handle_info/2,
- terminate/2,
- code_change/3]).
-
--record(state, {nodes = [],
- dumped_core = false, %% only dump fatal core once
- args}).
-
-%%%----------------------------------------------------------------
-%%% Callback functions from gen_server
-%%%----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% init(Args) ->
-%% {ok, State} | Error
-%%-----------------------------------------------------------------
-
-init(Args) ->
- {ok, #state{args = Args}}.
-
-%%-----------------------------------------------------------------
-%% handle_event(Event, State) ->
-%% {ok, NewState} | remove_handler |
-%% {swap_handler, Args1, State1, Mod2, Args2}
-%%-----------------------------------------------------------------
-
-handle_event(Event, State) ->
- handle_any_event(Event, State).
-
-%%-----------------------------------------------------------------
-%% handle_info(Msg, State) ->
-%% {ok, NewState} | remove_handler |
-%% {swap_handler, Args1, State1, Mod2, Args2}
-%%-----------------------------------------------------------------
-
-handle_info(Msg, State) ->
- handle_any_event(Msg, State),
- {ok, State}.
-
-%%-----------------------------------------------------------------
-%% handle_call(Event, State) ->
-%% {ok, Reply, NewState} | {remove_handler, Reply} |
-%% {swap_handler, Reply, Args1, State1, Mod2, Args2}
-%%-----------------------------------------------------------------
-
-handle_call(Msg, State) ->
- Reply = ok,
- case handle_any_event(Msg, State) of
- {ok, NewState} ->
- {ok, Reply, NewState};
- remove_handler ->
- {remove_handler, Reply};
- {swap_handler,Args1, State1, Mod2, Args2} ->
- {swap_handler, Reply, Args1, State1, Mod2, Args2}
- end.
-
-%%-----------------------------------------------------------------
-%% terminate(Reason, State) ->
-%% AnyVal
-%%-----------------------------------------------------------------
-
-terminate(_Reason, _State) ->
- ok.
-
-%%----------------------------------------------------------------------
-%% Func: code_change/3
-%% Purpose: Upgrade process when its code is to be changed
-%% Returns: {ok, NewState}
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-
-handle_any_event({mnesia_system_event, Event}, State) ->
- handle_system_event(Event, State);
-handle_any_event({mnesia_table_event, Event}, State) ->
- handle_table_event(Event, State);
-handle_any_event(Msg, State) ->
- report_error("~p got unexpected event: ~p~n", [?MODULE, Msg]),
- {ok, State}.
-
-handle_table_event({Oper, Record, TransId}, State) ->
- report_info("~p performed by ~p on record:~n\t~p~n",
- [Oper, TransId, Record]),
- {ok, State}.
-
-handle_system_event({mnesia_checkpoint_activated, _Checkpoint}, State) ->
- {ok, State};
-
-handle_system_event({mnesia_checkpoint_deactivated, _Checkpoint}, State) ->
- {ok, State};
-
-handle_system_event({mnesia_up, Node}, State) ->
- Nodes = [Node | State#state.nodes],
- {ok, State#state{nodes = Nodes}};
-
-handle_system_event({mnesia_down, Node}, State) ->
- case mnesia:system_info(fallback_activated) of
- true ->
- case mnesia_monitor:get_env(fallback_error_function) of
- {mnesia, lkill} ->
- Msg = "A fallback is installed and Mnesia "
- "must be restarted. Forcing shutdown "
- "after mnesia_down from ~p...~n",
- report_fatal(Msg, [Node], nocore, State#state.dumped_core),
- mnesia:lkill(),
- exit(fatal);
- {UserMod, UserFunc} ->
- Msg = "Warning: A fallback is installed and Mnesia got mnesia_down "
- "from ~p. ~n",
- report_info(Msg, [Node]),
- case catch apply(UserMod, UserFunc, [Node]) of
- {'EXIT', {undef, _Reason}} ->
- %% Backward compatibility
- apply(UserMod, UserFunc, []);
- {'EXIT', Reason} ->
- exit(Reason);
- _ ->
- ok
- end,
- Nodes = lists:delete(Node, State#state.nodes),
- {ok, State#state{nodes = Nodes}}
- end;
- false ->
- Nodes = lists:delete(Node, State#state.nodes),
- {ok, State#state{nodes = Nodes}}
- end;
-
-handle_system_event({mnesia_overload, Details}, State) ->
- report_warning("Mnesia is overloaded: ~p~n", [Details]),
- {ok, State};
-
-handle_system_event({mnesia_info, Format, Args}, State) ->
- report_info(Format, Args),
- {ok, State};
-
-handle_system_event({mnesia_warning, Format, Args}, State) ->
- report_warning(Format, Args),
- {ok, State};
-
-handle_system_event({mnesia_error, Format, Args}, State) ->
- report_error(Format, Args),
- {ok, State};
-
-handle_system_event({mnesia_fatal, Format, Args, BinaryCore}, State) ->
- report_fatal(Format, Args, BinaryCore, State#state.dumped_core),
- {ok, State#state{dumped_core = true}};
-
-handle_system_event({inconsistent_database, Reason, Node}, State) ->
- report_error("mnesia_event got {inconsistent_database, ~w, ~w}~n",
- [Reason, Node]),
- {ok, State};
-
-handle_system_event({mnesia_user, Event}, State) ->
- report_info("User event: ~p~n", [Event]),
- {ok, State};
-
-handle_system_event(Msg, State) ->
- report_error("mnesia_event got unexpected system event: ~p~n", [Msg]),
- {ok, State}.
-
-report_info(Format0, Args0) ->
- Format = "Mnesia(~p): " ++ Format0,
- Args = [node() | Args0],
- case global:whereis_name(mnesia_global_logger) of
- undefined ->
- io:format(Format, Args);
- Pid ->
- io:format(Pid, Format, Args)
- end.
-
-report_warning(Format0, Args0) ->
- Format = "Mnesia(~p): ** WARNING ** " ++ Format0,
- Args = [node() | Args0],
- case erlang:function_exported(error_logger, warning_msg, 2) of
- true ->
- error_logger:warning_msg(Format, Args);
- false ->
- error_logger:format(Format, Args)
- end,
- case global:whereis_name(mnesia_global_logger) of
- undefined ->
- ok;
- Pid ->
- io:format(Pid, Format, Args)
- end.
-
-report_error(Format0, Args0) ->
- Format = "Mnesia(~p): ** ERROR ** " ++ Format0,
- Args = [node() | Args0],
- error_logger:format(Format, Args),
- case global:whereis_name(mnesia_global_logger) of
- undefined ->
- ok;
- Pid ->
- io:format(Pid, Format, Args)
- end.
-
-report_fatal(Format, Args, BinaryCore, CoreDumped) ->
- UseDir = mnesia_monitor:use_dir(),
- CoreDir = mnesia_monitor:get_env(core_dir),
- if
- list(CoreDir),CoreDumped == false,binary(BinaryCore) ->
- core_file(CoreDir,BinaryCore,Format,Args);
- (UseDir == true),CoreDumped == false,binary(BinaryCore) ->
- core_file(CoreDir,BinaryCore,Format,Args);
- true ->
- report_error("(ignoring core) ** FATAL ** " ++ Format, Args)
- end.
-
-core_file(CoreDir,BinaryCore,Format,Args) ->
- %% Integers = tuple_to_list(date()) ++ tuple_to_list(time()),
- Integers = tuple_to_list(now()),
- Fun = fun(I) when I < 10 -> ["_0",I];
- (I) -> ["_",I]
- end,
- List = lists:append([Fun(I) || I <- Integers]),
- CoreFile = if list(CoreDir) ->
- filename:absname(lists:concat(["MnesiaCore.", node()] ++ List),
- CoreDir);
- true ->
- filename:absname(lists:concat(["MnesiaCore.", node()] ++ List))
- end,
- case file:write_file(CoreFile, BinaryCore) of
- ok ->
- report_error("(core dumped to file: ~p)~n ** FATAL ** " ++ Format,
- [CoreFile] ++ Args);
- {error, Reason} ->
- report_error("(could not write core file: ~p)~n ** FATAL ** " ++ Format,
- [Reason] ++ Args)
- end.
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_frag.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_frag.erl
deleted file mode 100644
index e1f4e96a95..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_frag.erl
+++ /dev/null
@@ -1,1201 +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: mnesia_frag.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
-%%%
-%%%----------------------------------------------------------------------
-%%% Purpose : Support tables so large that they need
-%%% to be divided into several fragments.
-%%%----------------------------------------------------------------------
-
-%header_doc_include
-
--module(mnesia_frag).
--behaviour(mnesia_access).
-
-%% Callback functions when accessed within an activity
--export([
- lock/4,
- write/5, delete/5, delete_object/5,
- read/5, match_object/5, all_keys/4,
- select/5,
- index_match_object/6, index_read/6,
- foldl/6, foldr/6,
- table_info/4
- ]).
-
-%header_doc_include
-
--export([
- change_table_frag/2,
- remove_node/2,
- expand_cstruct/1,
- lookup_frag_hash/1,
- lookup_foreigners/1,
- frag_names/1,
- set_frag_hash/2,
- local_select/4,
- remote_select/4
- ]).
-
--include("mnesia.hrl").
-
--define(OLD_HASH_MOD, mnesia_frag_old_hash).
--define(DEFAULT_HASH_MOD, mnesia_frag_hash).
-%%-define(DEFAULT_HASH_MOD, ?OLD_HASH_MOD). %% BUGBUG: New should be default
-
--record(frag_state,
- {foreign_key,
- n_fragments,
- hash_module,
- hash_state}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Access functions
-
-%impl_doc_include
-
-%% Callback functions which provides transparent
-%% access of fragmented tables from any activity
-%% access context.
-
-lock(ActivityId, Opaque, {table , Tab}, LockKind) ->
- case frag_names(Tab) of
- [Tab] ->
- mnesia:lock(ActivityId, Opaque, {table, Tab}, LockKind);
- Frags ->
- DeepNs = [mnesia:lock(ActivityId, Opaque, {table, F}, LockKind) ||
- F <- Frags],
- mnesia_lib:uniq(lists:append(DeepNs))
- end;
-
-lock(ActivityId, Opaque, LockItem, LockKind) ->
- mnesia:lock(ActivityId, Opaque, LockItem, LockKind).
-
-write(ActivityId, Opaque, Tab, Rec, LockKind) ->
- Frag = record_to_frag_name(Tab, Rec),
- mnesia:write(ActivityId, Opaque, Frag, Rec, LockKind).
-
-delete(ActivityId, Opaque, Tab, Key, LockKind) ->
- Frag = key_to_frag_name(Tab, Key),
- mnesia:delete(ActivityId, Opaque, Frag, Key, LockKind).
-
-delete_object(ActivityId, Opaque, Tab, Rec, LockKind) ->
- Frag = record_to_frag_name(Tab, Rec),
- mnesia:delete_object(ActivityId, Opaque, Frag, Rec, LockKind).
-
-read(ActivityId, Opaque, Tab, Key, LockKind) ->
- Frag = key_to_frag_name(Tab, Key),
- mnesia:read(ActivityId, Opaque, Frag, Key, LockKind).
-
-match_object(ActivityId, Opaque, Tab, HeadPat, LockKind) ->
- MatchSpec = [{HeadPat, [], ['$_']}],
- select(ActivityId, Opaque, Tab, MatchSpec, LockKind).
-
-select(ActivityId, Opaque, Tab, MatchSpec, LockKind) ->
- do_select(ActivityId, Opaque, Tab, MatchSpec, LockKind).
-
-all_keys(ActivityId, Opaque, Tab, LockKind) ->
- Match = [mnesia:all_keys(ActivityId, Opaque, Frag, LockKind)
- || Frag <- frag_names(Tab)],
- lists:append(Match).
-
-index_match_object(ActivityId, Opaque, Tab, Pat, Attr, LockKind) ->
- Match =
- [mnesia:index_match_object(ActivityId, Opaque, Frag, Pat, Attr, LockKind)
- || Frag <- frag_names(Tab)],
- lists:append(Match).
-
-index_read(ActivityId, Opaque, Tab, Key, Attr, LockKind) ->
- Match =
- [mnesia:index_read(ActivityId, Opaque, Frag, Key, Attr, LockKind)
- || Frag <- frag_names(Tab)],
- lists:append(Match).
-
-foldl(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
- Fun2 = fun(Frag, A) ->
- mnesia:foldl(ActivityId, Opaque, Fun, A, Frag, LockKind)
- end,
- lists:foldl(Fun2, Acc, frag_names(Tab)).
-
-foldr(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
- Fun2 = fun(Frag, A) ->
- mnesia:foldr(ActivityId, Opaque, Fun, A, Frag, LockKind)
- end,
- lists:foldr(Fun2, Acc, frag_names(Tab)).
-
-table_info(ActivityId, Opaque, {Tab, Key}, Item) ->
- Frag = key_to_frag_name(Tab, Key),
- table_info2(ActivityId, Opaque, Tab, Frag, Item);
-table_info(ActivityId, Opaque, Tab, Item) ->
- table_info2(ActivityId, Opaque, Tab, Tab, Item).
-
-table_info2(ActivityId, Opaque, Tab, Frag, Item) ->
- case Item of
- size ->
- SumFun = fun({_, Size}, Acc) -> Acc + Size end,
- lists:foldl(SumFun, 0, frag_size(ActivityId, Opaque, Tab));
- memory ->
- SumFun = fun({_, Size}, Acc) -> Acc + Size end,
- lists:foldl(SumFun, 0, frag_memory(ActivityId, Opaque, Tab));
- base_table ->
- lookup_prop(Tab, base_table);
- node_pool ->
- lookup_prop(Tab, node_pool);
- n_fragments ->
- FH = lookup_frag_hash(Tab),
- FH#frag_state.n_fragments;
- foreign_key ->
- FH = lookup_frag_hash(Tab),
- FH#frag_state.foreign_key;
- foreigners ->
- lookup_foreigners(Tab);
- n_ram_copies ->
- length(val({Tab, ram_copies}));
- n_disc_copies ->
- length(val({Tab, disc_copies}));
- n_disc_only_copies ->
- length(val({Tab, disc_only_copies}));
-
- frag_names ->
- frag_names(Tab);
- frag_dist ->
- frag_dist(Tab);
- frag_size ->
- frag_size(ActivityId, Opaque, Tab);
- frag_memory ->
- frag_memory(ActivityId, Opaque, Tab);
- _ ->
- mnesia:table_info(ActivityId, Opaque, Frag, Item)
- end.
-%impl_doc_include
-
-frag_size(ActivityId, Opaque, Tab) ->
- [{F, remote_table_info(ActivityId, Opaque, F, size)} || F <- frag_names(Tab)].
-
-frag_memory(ActivityId, Opaque, Tab) ->
- [{F, remote_table_info(ActivityId, Opaque, F, memory)} || F <- frag_names(Tab)].
-
-
-
-remote_table_info(ActivityId, Opaque, Tab, Item) ->
- N = val({Tab, where_to_read}),
- case rpc:call(N, mnesia, table_info, [ActivityId, Opaque, Tab, Item]) of
- {badrpc, _} ->
- mnesia:abort({no_exists, Tab, Item});
- Info ->
- Info
- end.
-
-do_select(ActivityId, Opaque, Tab, MatchSpec, LockKind) ->
- case ?catch_val({Tab, frag_hash}) of
- {'EXIT', _} ->
- mnesia:select(ActivityId, Opaque, Tab, MatchSpec, LockKind);
- FH ->
- HashState = FH#frag_state.hash_state,
- FragNumbers =
- case FH#frag_state.hash_module of
- HashMod when HashMod == ?DEFAULT_HASH_MOD ->
- ?DEFAULT_HASH_MOD:match_spec_to_frag_numbers(HashState, MatchSpec);
- HashMod ->
- HashMod:match_spec_to_frag_numbers(HashState, MatchSpec)
- end,
- N = FH#frag_state.n_fragments,
- VerifyFun = fun(F) when integer(F), F >= 1, F =< N -> false;
- (_F) -> true
- end,
- case catch lists:filter(VerifyFun, FragNumbers) of
- [] ->
- Fun = fun(Num) ->
- Name = n_to_frag_name(Tab, Num),
- Node = val({Name, where_to_read}),
- mnesia:lock(ActivityId, Opaque, {table, Name}, LockKind),
- {Name, Node}
- end,
- NameNodes = lists:map(Fun, FragNumbers),
- SelectAllFun =
- fun(PatchedMatchSpec) ->
- Match = [mnesia:dirty_select(Name, PatchedMatchSpec)
- || {Name, _Node} <- NameNodes],
- lists:append(Match)
- end,
- case [{Name, Node} || {Name, Node} <- NameNodes, Node /= node()] of
- [] ->
- %% All fragments are local
- mnesia:fun_select(ActivityId, Opaque, Tab, MatchSpec, none, '_', SelectAllFun);
- RemoteNameNodes ->
- SelectFun =
- fun(PatchedMatchSpec) ->
- Ref = make_ref(),
- Args = [self(), Ref, RemoteNameNodes, PatchedMatchSpec],
- Pid = spawn_link(?MODULE, local_select, Args),
- LocalMatch = [mnesia:dirty_select(Name, PatchedMatchSpec)
- || {Name, Node} <- NameNodes, Node == node()],
- OldSelectFun = fun() -> SelectAllFun(PatchedMatchSpec) end,
- local_collect(Ref, Pid, lists:append(LocalMatch), OldSelectFun)
- end,
- mnesia:fun_select(ActivityId, Opaque, Tab, MatchSpec, none, '_', SelectFun)
- end;
- BadFrags ->
- mnesia:abort({"match_spec_to_frag_numbers: Fragment numbers out of range",
- BadFrags, {range, 1, N}})
- end
- end.
-
-local_select(ReplyTo, Ref, RemoteNameNodes, MatchSpec) ->
- RemoteNodes = mnesia_lib:uniq([Node || {_Name, Node} <- RemoteNameNodes]),
- Args = [ReplyTo, Ref, RemoteNameNodes, MatchSpec],
- {Replies, BadNodes} = rpc:multicall(RemoteNodes, ?MODULE, remote_select, Args),
- case mnesia_lib:uniq(Replies) -- [ok] of
- [] when BadNodes == [] ->
- ReplyTo ! {local_select, Ref, ok};
- _ when BadNodes /= [] ->
- ReplyTo ! {local_select, Ref, {error, {node_not_running, hd(BadNodes)}}};
- [{badrpc, {'EXIT', Reason}} | _] ->
- ReplyTo ! {local_select, Ref, {error, Reason}};
- [Reason | _] ->
- ReplyTo ! {local_select, Ref, {error, Reason}}
- end,
- unlink(ReplyTo),
- exit(normal).
-
-remote_select(ReplyTo, Ref, NameNodes, MatchSpec) ->
- do_remote_select(ReplyTo, Ref, NameNodes, MatchSpec).
-
-do_remote_select(ReplyTo, Ref, [{Name, Node} | NameNodes], MatchSpec) ->
- if
- Node == node() ->
- Res = (catch {ok, mnesia:dirty_select(Name, MatchSpec)}),
- ReplyTo ! {remote_select, Ref, Node, Res},
- do_remote_select(ReplyTo, Ref, NameNodes, MatchSpec);
- true ->
- do_remote_select(ReplyTo, Ref, NameNodes, MatchSpec)
- end;
-do_remote_select(_ReplyTo, _Ref, [], _MatchSpec) ->
- ok.
-
-local_collect(Ref, Pid, LocalMatch, OldSelectFun) ->
- receive
- {local_select, Ref, LocalRes} ->
- remote_collect(Ref, LocalRes, LocalMatch, OldSelectFun);
- {'EXIT', Pid, Reason} ->
- remote_collect(Ref, {error, Reason}, [], OldSelectFun)
- end.
-
-remote_collect(Ref, LocalRes = ok, Acc, OldSelectFun) ->
- receive
- {remote_select, Ref, Node, RemoteRes} ->
- case RemoteRes of
- {ok, RemoteMatch} ->
- remote_collect(Ref, LocalRes, RemoteMatch ++ Acc, OldSelectFun);
- _ ->
- remote_collect(Ref, {error, {node_not_running, Node}}, [], OldSelectFun)
- end
- after 0 ->
- Acc
- end;
-remote_collect(Ref, LocalRes = {error, Reason}, _Acc, OldSelectFun) ->
- receive
- {remote_select, Ref, _Node, _RemoteRes} ->
- remote_collect(Ref, LocalRes, [], OldSelectFun)
- after 0 ->
- mnesia:abort(Reason)
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Returns a list of cstructs
-
-expand_cstruct(Cs) ->
- expand_cstruct(Cs, create).
-
-expand_cstruct(Cs, Mode) ->
- Tab = Cs#cstruct.name,
- Props = Cs#cstruct.frag_properties,
- mnesia_schema:verify({alt, [nil, list]}, mnesia_lib:etype(Props),
- {badarg, Tab, Props}),
- %% Verify keys
- ValidKeys = [foreign_key, n_fragments, node_pool,
- n_ram_copies, n_disc_copies, n_disc_only_copies,
- hash_module, hash_state],
- Keys = mnesia_schema:check_keys(Tab, Props, ValidKeys),
- mnesia_schema:check_duplicates(Tab, Keys),
-
- %% Pick fragmentation props
- ForeignKey = mnesia_schema:pick(Tab, foreign_key, Props, undefined),
- {ForeignKey2, N, Pool, DefaultNR, DefaultND, DefaultNDO} =
- pick_props(Tab, Cs, ForeignKey),
-
- %% Verify node_pool
- BadPool = {bad_type, Tab, {node_pool, Pool}},
- mnesia_schema:verify(list, mnesia_lib:etype(Pool), BadPool),
- NotAtom = fun(A) when atom(A) -> false;
- (_A) -> true
- end,
- mnesia_schema:verify([], [P || P <- Pool, NotAtom(P)], BadPool),
-
- NR = mnesia_schema:pick(Tab, n_ram_copies, Props, 0),
- ND = mnesia_schema:pick(Tab, n_disc_copies, Props, 0),
- NDO = mnesia_schema:pick(Tab, n_disc_only_copies, Props, 0),
-
- PosInt = fun(I) when integer(I), I >= 0 -> true;
- (_I) -> false
- end,
- mnesia_schema:verify(true, PosInt(NR),
- {bad_type, Tab, {n_ram_copies, NR}}),
- mnesia_schema:verify(true, PosInt(ND),
- {bad_type, Tab, {n_disc_copies, ND}}),
- mnesia_schema:verify(true, PosInt(NDO),
- {bad_type, Tab, {n_disc_only_copies, NDO}}),
-
- %% Verify n_fragments
- Cs2 = verify_n_fragments(N, Cs, Mode),
-
- %% Verify hash callback
- HashMod = mnesia_schema:pick(Tab, hash_module, Props, ?DEFAULT_HASH_MOD),
- HashState = mnesia_schema:pick(Tab, hash_state, Props, undefined),
- HashState2 = HashMod:init_state(Tab, HashState), %% BUGBUG: Catch?
-
- FH = #frag_state{foreign_key = ForeignKey2,
- n_fragments = 1,
- hash_module = HashMod,
- hash_state = HashState2},
- if
- NR == 0, ND == 0, NDO == 0 ->
- do_expand_cstruct(Cs2, FH, N, Pool, DefaultNR, DefaultND, DefaultNDO, Mode);
- true ->
- do_expand_cstruct(Cs2, FH, N, Pool, NR, ND, NDO, Mode)
- end.
-
-do_expand_cstruct(Cs, FH, N, Pool, NR, ND, NDO, Mode) ->
- Tab = Cs#cstruct.name,
-
- LC = Cs#cstruct.local_content,
- mnesia_schema:verify(false, LC,
- {combine_error, Tab, {local_content, LC}}),
-
- Snmp = Cs#cstruct.snmp,
- mnesia_schema:verify([], Snmp,
- {combine_error, Tab, {snmp, Snmp}}),
-
- %% Add empty fragments
- CommonProps = [{base_table, Tab}],
- Cs2 = Cs#cstruct{frag_properties = lists:sort(CommonProps)},
- expand_frag_cstructs(N, NR, ND, NDO, Cs2, Pool, Pool, FH, Mode).
-
-verify_n_fragments(N, Cs, Mode) when integer(N), N >= 1 ->
- case Mode of
- create ->
- Cs#cstruct{ram_copies = [],
- disc_copies = [],
- disc_only_copies = []};
- activate ->
- Reason = {combine_error, Cs#cstruct.name, {n_fragments, N}},
- mnesia_schema:verify(1, N, Reason),
- Cs
- end;
-verify_n_fragments(N, Cs, _Mode) ->
- mnesia:abort({bad_type, Cs#cstruct.name, {n_fragments, N}}).
-
-pick_props(Tab, Cs, {ForeignTab, Attr}) ->
- mnesia_schema:verify(true, ForeignTab /= Tab,
- {combine_error, Tab, {ForeignTab, Attr}}),
- Props = Cs#cstruct.frag_properties,
- Attrs = Cs#cstruct.attributes,
-
- ForeignKey = lookup_prop(ForeignTab, foreign_key),
- ForeignN = lookup_prop(ForeignTab, n_fragments),
- ForeignPool = lookup_prop(ForeignTab, node_pool),
- N = mnesia_schema:pick(Tab, n_fragments, Props, ForeignN),
- Pool = mnesia_schema:pick(Tab, node_pool, Props, ForeignPool),
-
- mnesia_schema:verify(ForeignN, N,
- {combine_error, Tab, {n_fragments, N},
- ForeignTab, {n_fragments, ForeignN}}),
-
- mnesia_schema:verify(ForeignPool, Pool,
- {combine_error, Tab, {node_pool, Pool},
- ForeignTab, {node_pool, ForeignPool}}),
-
- mnesia_schema:verify(undefined, ForeignKey,
- {combine_error, Tab,
- "Multiple levels of foreign_key dependencies",
- {ForeignTab, Attr}, ForeignKey}),
-
- Key = {ForeignTab, mnesia_schema:attr_to_pos(Attr, Attrs)},
- DefaultNR = length(val({ForeignTab, ram_copies})),
- DefaultND = length(val({ForeignTab, disc_copies})),
- DefaultNDO = length(val({ForeignTab, disc_only_copies})),
- {Key, N, Pool, DefaultNR, DefaultND, DefaultNDO};
-pick_props(Tab, Cs, undefined) ->
- Props = Cs#cstruct.frag_properties,
- DefaultN = 1,
- DefaultPool = mnesia:system_info(db_nodes),
- N = mnesia_schema:pick(Tab, n_fragments, Props, DefaultN),
- Pool = mnesia_schema:pick(Tab, node_pool, Props, DefaultPool),
- DefaultNR = 1,
- DefaultND = 0,
- DefaultNDO = 0,
- {undefined, N, Pool, DefaultNR, DefaultND, DefaultNDO};
-pick_props(Tab, _Cs, BadKey) ->
- mnesia:abort({bad_type, Tab, {foreign_key, BadKey}}).
-
-expand_frag_cstructs(N, NR, ND, NDO, CommonCs, Dist, Pool, FH, Mode)
- when N > 1, Mode == create ->
- Frag = n_to_frag_name(CommonCs#cstruct.name, N),
- Cs = CommonCs#cstruct{name = Frag},
- {Cs2, RevModDist, RestDist} = set_frag_nodes(NR, ND, NDO, Cs, Dist, []),
- ModDist = lists:reverse(RevModDist),
- Dist2 = rearrange_dist(Cs, ModDist, RestDist, Pool),
- %% Adjusts backwards, but it doesn't matter.
- {FH2, _FromFrags, _AdditionalWriteFrags} = adjust_before_split(FH),
- CsList = expand_frag_cstructs(N - 1, NR, ND, NDO, CommonCs, Dist2, Pool, FH2, Mode),
- [Cs2 | CsList];
-expand_frag_cstructs(1, NR, ND, NDO, CommonCs, Dist, Pool, FH, Mode) ->
- BaseProps = CommonCs#cstruct.frag_properties ++
- [{foreign_key, FH#frag_state.foreign_key},
- {hash_module, FH#frag_state.hash_module},
- {hash_state, FH#frag_state.hash_state},
- {n_fragments, FH#frag_state.n_fragments},
- {node_pool, Pool}
- ],
- BaseCs = CommonCs#cstruct{frag_properties = lists:sort(BaseProps)},
- case Mode of
- activate ->
- [BaseCs];
- create ->
- {BaseCs2, _, _} = set_frag_nodes(NR, ND, NDO, BaseCs, Dist, []),
- [BaseCs2]
- end.
-
-set_frag_nodes(NR, ND, NDO, Cs, [Head | Tail], Acc) when NR > 0 ->
- Pos = #cstruct.ram_copies,
- {Cs2, Head2} = set_frag_node(Cs, Pos, Head),
- set_frag_nodes(NR - 1, ND, NDO, Cs2, Tail, [Head2 | Acc]);
-set_frag_nodes(NR, ND, NDO, Cs, [Head | Tail], Acc) when ND > 0 ->
- Pos = #cstruct.disc_copies,
- {Cs2, Head2} = set_frag_node(Cs, Pos, Head),
- set_frag_nodes(NR, ND - 1, NDO, Cs2, Tail, [Head2 | Acc]);
-set_frag_nodes(NR, ND, NDO, Cs, [Head | Tail], Acc) when NDO > 0 ->
- Pos = #cstruct.disc_only_copies,
- {Cs2, Head2} = set_frag_node(Cs, Pos, Head),
- set_frag_nodes(NR, ND, NDO - 1, Cs2, Tail, [Head2 | Acc]);
-set_frag_nodes(0, 0, 0, Cs, RestDist, ModDist) ->
- {Cs, ModDist, RestDist};
-set_frag_nodes(_, _, _, Cs, [], _) ->
- mnesia:abort({combine_error, Cs#cstruct.name, "Too few nodes in node_pool"}).
-
-set_frag_node(Cs, Pos, Head) ->
- Ns = element(Pos, Cs),
- {Node, Count2} =
- case Head of
- {N, Count} when atom(N), integer(Count), Count >= 0 ->
- {N, Count + 1};
- N when atom(N) ->
- {N, 1};
- BadNode ->
- mnesia:abort({bad_type, Cs#cstruct.name, BadNode})
- end,
- Cs2 = setelement(Pos, Cs, [Node | Ns]),
- {Cs2, {Node, Count2}}.
-
-rearrange_dist(Cs, [{Node, Count} | ModDist], Dist, Pool) ->
- Dist2 = insert_dist(Cs, Node, Count, Dist, Pool),
- rearrange_dist(Cs, ModDist, Dist2, Pool);
-rearrange_dist(_Cs, [], Dist, _) ->
- Dist.
-
-insert_dist(Cs, Node, Count, [Head | Tail], Pool) ->
- case Head of
- {Node2, Count2} when atom(Node2), integer(Count2), Count2 >= 0 ->
- case node_diff(Node, Count, Node2, Count2, Pool) of
- less ->
- [{Node, Count}, Head | Tail];
- greater ->
- [Head | insert_dist(Cs, Node, Count, Tail, Pool)]
- end;
- Node2 when atom(Node2) ->
- insert_dist(Cs, Node, Count, [{Node2, 0} | Tail], Pool);
- BadNode ->
- mnesia:abort({bad_type, Cs#cstruct.name, BadNode})
- end;
-insert_dist(_Cs, Node, Count, [], _Pool) ->
- [{Node, Count}];
-insert_dist(_Cs, _Node, _Count, Dist, _Pool) ->
- mnesia:abort({bad_type, Dist}).
-
-node_diff(_Node, Count, _Node2, Count2, _Pool) when Count < Count2 ->
- less;
-node_diff(Node, Count, Node2, Count2, Pool) when Count == Count2 ->
- Pos = list_pos(Node, Pool, 1),
- Pos2 = list_pos(Node2, Pool, 1),
- if
- Pos < Pos2 ->
- less;
- Pos > Pos2 ->
- greater
- end;
-node_diff(_Node, Count, _Node2, Count2, _Pool) when Count > Count2 ->
- greater.
-
-%% Returns position of element in list
-list_pos(H, [H | _T], Pos) ->
- Pos;
-list_pos(E, [_H | T], Pos) ->
- list_pos(E, T, Pos + 1).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Switch function for changing of table fragmentation
-%%
-%% Returns a list of lists of schema ops
-
-change_table_frag(Tab, {activate, FragProps}) ->
- make_activate(Tab, FragProps);
-change_table_frag(Tab, deactivate) ->
- make_deactivate(Tab);
-change_table_frag(Tab, {add_frag, SortedNodes}) ->
- make_multi_add_frag(Tab, SortedNodes);
-change_table_frag(Tab, del_frag) ->
- make_multi_del_frag(Tab);
-change_table_frag(Tab, {add_node, Node}) ->
- make_multi_add_node(Tab, Node);
-change_table_frag(Tab, {del_node, Node}) ->
- make_multi_del_node(Tab, Node);
-change_table_frag(Tab, Change) ->
- mnesia:abort({bad_type, Tab, Change}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Turn a normal table into a fragmented table
-%%
-%% The storage type must be the same on all nodes
-
-make_activate(Tab, Props) ->
- Cs = mnesia_schema:incr_version(val({Tab, cstruct})),
- mnesia_schema:ensure_active(Cs),
- case Cs#cstruct.frag_properties of
- [] ->
- Cs2 = Cs#cstruct{frag_properties = Props},
- [Cs3] = expand_cstruct(Cs2, activate),
- TabDef = mnesia_schema:cs2list(Cs3),
- Op = {op, change_table_frag, activate, TabDef},
- [[Op]];
- BadProps ->
- mnesia:abort({already_exists, Tab, {frag_properties, BadProps}})
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Turn a table into a normal defragmented table
-
-make_deactivate(Tab) ->
- Cs = mnesia_schema:incr_version(val({Tab, cstruct})),
- mnesia_schema:ensure_active(Cs),
- Foreigners = lookup_foreigners(Tab),
- BaseTab = lookup_prop(Tab, base_table),
- FH = lookup_frag_hash(Tab),
- if
- BaseTab /= Tab ->
- mnesia:abort({combine_error, Tab, "Not a base table"});
- Foreigners /= [] ->
- mnesia:abort({combine_error, Tab, "Too many foreigners", Foreigners});
- FH#frag_state.n_fragments > 1 ->
- mnesia:abort({combine_error, Tab, "Too many fragments"});
- true ->
- Cs2 = Cs#cstruct{frag_properties = []},
- TabDef = mnesia_schema:cs2list(Cs2),
- Op = {op, change_table_frag, deactivate, TabDef},
- [[Op]]
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Add a fragment to a fragmented table and fill it with half of
-%% the records from one of the old fragments
-
-make_multi_add_frag(Tab, SortedNs) when list(SortedNs) ->
- verify_multi(Tab),
- Ops = make_add_frag(Tab, SortedNs),
-
- %% Propagate to foreigners
- MoreOps = [make_add_frag(T, SortedNs) || T <- lookup_foreigners(Tab)],
- [Ops | MoreOps];
-make_multi_add_frag(Tab, SortedNs) ->
- mnesia:abort({bad_type, Tab, SortedNs}).
-
-verify_multi(Tab) ->
- FH = lookup_frag_hash(Tab),
- ForeignKey = FH#frag_state.foreign_key,
- mnesia_schema:verify(undefined, ForeignKey,
- {combine_error, Tab,
- "Op only allowed via foreign table",
- {foreign_key, ForeignKey}}).
-
-make_frag_names_and_acquire_locks(Tab, N, FragIndecies, DoNotLockN) ->
- mnesia_schema:get_tid_ts_and_lock(Tab, write),
- Fun = fun(Index, FN) ->
- if
- DoNotLockN == true, Index == N ->
- Name = n_to_frag_name(Tab, Index),
- setelement(Index, FN, Name);
- true ->
- Name = n_to_frag_name(Tab, Index),
- mnesia_schema:get_tid_ts_and_lock(Name, write),
- setelement(Index , FN, Name)
- end
- end,
- FragNames = erlang:make_tuple(N, undefined),
- lists:foldl(Fun, FragNames, FragIndecies).
-
-make_add_frag(Tab, SortedNs) ->
- Cs = mnesia_schema:incr_version(val({Tab, cstruct})),
- mnesia_schema:ensure_active(Cs),
- FH = lookup_frag_hash(Tab),
- {FH2, FromIndecies, WriteIndecies} = adjust_before_split(FH),
- N = FH2#frag_state.n_fragments,
- FragNames = make_frag_names_and_acquire_locks(Tab, N, WriteIndecies, true),
- NewFrag = element(N, FragNames),
-
- NR = length(Cs#cstruct.ram_copies),
- ND = length(Cs#cstruct.disc_copies),
- NDO = length(Cs#cstruct.disc_only_copies),
- NewCs = Cs#cstruct{name = NewFrag,
- frag_properties = [{base_table, Tab}],
- ram_copies = [],
- disc_copies = [],
- disc_only_copies = []},
- {NewCs2, _, _} = set_frag_nodes(NR, ND, NDO, NewCs, SortedNs, []),
- [NewOp] = mnesia_schema:make_create_table(NewCs2),
-
- SplitOps = split(Tab, FH2, FromIndecies, FragNames, []),
-
- Cs2 = replace_frag_hash(Cs, FH2),
- TabDef = mnesia_schema:cs2list(Cs2),
- BaseOp = {op, change_table_frag, {add_frag, SortedNs}, TabDef},
-
- [BaseOp, NewOp | SplitOps].
-
-replace_frag_hash(Cs, FH) when record(FH, frag_state) ->
- Fun = fun(Prop) ->
- case Prop of
- {n_fragments, _} ->
- {true, {n_fragments, FH#frag_state.n_fragments}};
- {hash_module, _} ->
- {true, {hash_module, FH#frag_state.hash_module}};
- {hash_state, _} ->
- {true, {hash_state, FH#frag_state.hash_state}};
- {next_n_to_split, _} ->
- false;
- {n_doubles, _} ->
- false;
- _ ->
- true
- end
- end,
- Props = lists:zf(Fun, Cs#cstruct.frag_properties),
- Cs#cstruct{frag_properties = Props}.
-
-%% Adjust table info before split
-adjust_before_split(FH) ->
- HashState = FH#frag_state.hash_state,
- {HashState2, FromFrags, AdditionalWriteFrags} =
- case FH#frag_state.hash_module of
- HashMod when HashMod == ?DEFAULT_HASH_MOD ->
- ?DEFAULT_HASH_MOD:add_frag(HashState);
- HashMod ->
- HashMod:add_frag(HashState)
- end,
- N = FH#frag_state.n_fragments + 1,
- FromFrags2 = (catch lists:sort(FromFrags)),
- UnionFrags = (catch lists:merge(FromFrags2, lists:sort(AdditionalWriteFrags))),
- VerifyFun = fun(F) when integer(F), F >= 1, F =< N -> false;
- (_F) -> true
- end,
- case catch lists:filter(VerifyFun, UnionFrags) of
- [] ->
- FH2 = FH#frag_state{n_fragments = N,
- hash_state = HashState2},
- {FH2, FromFrags2, UnionFrags};
- BadFrags ->
- mnesia:abort({"add_frag: Fragment numbers out of range",
- BadFrags, {range, 1, N}})
- end.
-
-split(Tab, FH, [SplitN | SplitNs], FragNames, Ops) ->
- SplitFrag = element(SplitN, FragNames),
- Pat = mnesia:table_info(SplitFrag, wild_pattern),
- {_Mod, Tid, Ts} = mnesia_schema:get_tid_ts_and_lock(Tab, none),
- Recs = mnesia:match_object(Tid, Ts, SplitFrag, Pat, read),
- Ops2 = do_split(FH, SplitN, FragNames, Recs, Ops),
- split(Tab, FH, SplitNs, FragNames, Ops2);
-split(_Tab, _FH, [], _FragNames, Ops) ->
- Ops.
-
-%% Perform the split of the table
-do_split(FH, OldN, FragNames, [Rec | Recs], Ops) ->
- Pos = key_pos(FH),
- HashKey = element(Pos, Rec),
- case key_to_n(FH, HashKey) of
- NewN when NewN == OldN ->
- %% Keep record in the same fragment. No need to move it.
- do_split(FH, OldN, FragNames, Recs, Ops);
- NewN ->
- case element(NewN, FragNames) of
- NewFrag when NewFrag /= undefined ->
- OldFrag = element(OldN, FragNames),
- Key = element(2, Rec),
- NewOid = {NewFrag, Key},
- OldOid = {OldFrag, Key},
- Ops2 = [{op, rec, unknown, {NewOid, [Rec], write}},
- {op, rec, unknown, {OldOid, [OldOid], delete}} | Ops],
- do_split(FH, OldN, FragNames, Recs, Ops2);
- _NewFrag ->
- %% Tried to move record to fragment that not is locked
- mnesia:abort({"add_frag: Fragment not locked", NewN})
- end
- end;
-do_split(_FH, _OldN, _FragNames, [], Ops) ->
- Ops.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Delete a fragment from a fragmented table
-%% and merge its records with an other fragment
-
-make_multi_del_frag(Tab) ->
- verify_multi(Tab),
- Ops = make_del_frag(Tab),
-
- %% Propagate to foreigners
- MoreOps = [make_del_frag(T) || T <- lookup_foreigners(Tab)],
- [Ops | MoreOps].
-
-make_del_frag(Tab) ->
- FH = lookup_frag_hash(Tab),
- case FH#frag_state.n_fragments of
- N when N > 1 ->
- Cs = mnesia_schema:incr_version(val({Tab, cstruct})),
- mnesia_schema:ensure_active(Cs),
- {FH2, FromIndecies, WriteIndecies} = adjust_before_merge(FH),
- FragNames = make_frag_names_and_acquire_locks(Tab, N, WriteIndecies, false),
-
- MergeOps = merge(Tab, FH2, FromIndecies, FragNames, []),
- LastFrag = element(N, FragNames),
- [LastOp] = mnesia_schema:make_delete_table(LastFrag, single_frag),
- Cs2 = replace_frag_hash(Cs, FH2),
- TabDef = mnesia_schema:cs2list(Cs2),
- BaseOp = {op, change_table_frag, del_frag, TabDef},
- [BaseOp, LastOp | MergeOps];
- _ ->
- %% Cannot remove the last fragment
- mnesia:abort({no_exists, Tab})
- end.
-
-%% Adjust tab info before merge
-adjust_before_merge(FH) ->
- HashState = FH#frag_state.hash_state,
- {HashState2, FromFrags, AdditionalWriteFrags} =
- case FH#frag_state.hash_module of
- HashMod when HashMod == ?DEFAULT_HASH_MOD ->
- ?DEFAULT_HASH_MOD:del_frag(HashState);
- HashMod ->
- HashMod:del_frag(HashState)
- end,
- N = FH#frag_state.n_fragments,
- FromFrags2 = (catch lists:sort(FromFrags)),
- UnionFrags = (catch lists:merge(FromFrags2, lists:sort(AdditionalWriteFrags))),
- VerifyFun = fun(F) when integer(F), F >= 1, F =< N -> false;
- (_F) -> true
- end,
- case catch lists:filter(VerifyFun, UnionFrags) of
- [] ->
- case lists:member(N, FromFrags2) of
- true ->
- FH2 = FH#frag_state{n_fragments = N - 1,
- hash_state = HashState2},
- {FH2, FromFrags2, UnionFrags};
- false ->
- mnesia:abort({"del_frag: Last fragment number not included", N})
- end;
- BadFrags ->
- mnesia:abort({"del_frag: Fragment numbers out of range",
- BadFrags, {range, 1, N}})
- end.
-
-merge(Tab, FH, [FromN | FromNs], FragNames, Ops) ->
- FromFrag = element(FromN, FragNames),
- Pat = mnesia:table_info(FromFrag, wild_pattern),
- {_Mod, Tid, Ts} = mnesia_schema:get_tid_ts_and_lock(Tab, none),
- Recs = mnesia:match_object(Tid, Ts, FromFrag, Pat, read),
- Ops2 = do_merge(FH, FromN, FragNames, Recs, Ops),
- merge(Tab, FH, FromNs, FragNames, Ops2);
-merge(_Tab, _FH, [], _FragNames, Ops) ->
- Ops.
-
-%% Perform the merge of the table
-do_merge(FH, OldN, FragNames, [Rec | Recs], Ops) ->
- Pos = key_pos(FH),
- LastN = FH#frag_state.n_fragments + 1,
- HashKey = element(Pos, Rec),
- case key_to_n(FH, HashKey) of
- NewN when NewN == LastN ->
- %% Tried to leave a record in the fragment that is to be deleted
- mnesia:abort({"del_frag: Fragment number out of range",
- NewN, {range, 1, LastN}});
- NewN when NewN == OldN ->
- %% Keep record in the same fragment. No need to move it.
- do_merge(FH, OldN, FragNames, Recs, Ops);
- NewN when OldN == LastN ->
- %% Move record from the fragment that is to be deleted
- %% No need to create a delete op for each record.
- case element(NewN, FragNames) of
- NewFrag when NewFrag /= undefined ->
- Key = element(2, Rec),
- NewOid = {NewFrag, Key},
- Ops2 = [{op, rec, unknown, {NewOid, [Rec], write}} | Ops],
- do_merge(FH, OldN, FragNames, Recs, Ops2);
- _NewFrag ->
- %% Tried to move record to fragment that not is locked
- mnesia:abort({"del_frag: Fragment not locked", NewN})
- end;
- NewN ->
- case element(NewN, FragNames) of
- NewFrag when NewFrag /= undefined ->
- OldFrag = element(OldN, FragNames),
- Key = element(2, Rec),
- NewOid = {NewFrag, Key},
- OldOid = {OldFrag, Key},
- Ops2 = [{op, rec, unknown, {NewOid, [Rec], write}},
- {op, rec, unknown, {OldOid, [OldOid], delete}} | Ops],
- do_merge(FH, OldN, FragNames, Recs, Ops2);
- _NewFrag ->
- %% Tried to move record to fragment that not is locked
- mnesia:abort({"del_frag: Fragment not locked", NewN})
- end
- end;
- do_merge(_FH, _OldN, _FragNames, [], Ops) ->
- Ops.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Add a node to the node pool of a fragmented table
-
-make_multi_add_node(Tab, Node) ->
- verify_multi(Tab),
- Ops = make_add_node(Tab, Node),
-
- %% Propagate to foreigners
- MoreOps = [make_add_node(T, Node) || T <- lookup_foreigners(Tab)],
- [Ops | MoreOps].
-
-make_add_node(Tab, Node) when atom(Node) ->
- Pool = lookup_prop(Tab, node_pool),
- case lists:member(Node, Pool) of
- false ->
- Cs = mnesia_schema:incr_version(val({Tab, cstruct})),
- Pool2 = Pool ++ [Node],
- Props = Cs#cstruct.frag_properties,
- Props2 = lists:keyreplace(node_pool, 1, Props, {node_pool, Pool2}),
- Cs2 = Cs#cstruct{frag_properties = Props2},
- TabDef = mnesia_schema:cs2list(Cs2),
- Op = {op, change_table_frag, {add_node, Node}, TabDef},
- [Op];
- true ->
- mnesia:abort({already_exists, Tab, Node})
- end;
-make_add_node(Tab, Node) ->
- mnesia:abort({bad_type, Tab, Node}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Delet a node from the node pool of a fragmented table
-
-make_multi_del_node(Tab, Node) ->
- verify_multi(Tab),
- Ops = make_del_node(Tab, Node),
-
- %% Propagate to foreigners
- MoreOps = [make_del_node(T, Node) || T <- lookup_foreigners(Tab)],
- [Ops | MoreOps].
-
-make_del_node(Tab, Node) when atom(Node) ->
- Cs = mnesia_schema:incr_version(val({Tab, cstruct})),
- mnesia_schema:ensure_active(Cs),
- Pool = lookup_prop(Tab, node_pool),
- case lists:member(Node, Pool) of
- true ->
- Pool2 = Pool -- [Node],
- Props = lists:keyreplace(node_pool, 1, Cs#cstruct.frag_properties, {node_pool, Pool2}),
- Cs2 = Cs#cstruct{frag_properties = Props},
- TabDef = mnesia_schema:cs2list(Cs2),
- Op = {op, change_table_frag, {del_node, Node}, TabDef},
- [Op];
- false ->
- mnesia:abort({no_exists, Tab, Node})
- end;
-make_del_node(Tab, Node) ->
- mnesia:abort({bad_type, Tab, Node}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Special case used to remove all references to a node during
-%% mnesia:del_table_copy(schema, Node)
-
-remove_node(Node, Cs) ->
- Tab = Cs#cstruct.name,
- case is_top_frag(Tab) of
- false ->
- {Cs, false};
- true ->
- Pool = lookup_prop(Tab, node_pool),
- case lists:member(Node, Pool) of
- true ->
- Pool2 = Pool -- [Node],
- Props = lists:keyreplace(node_pool, 1,
- Cs#cstruct.frag_properties,
- {node_pool, Pool2}),
- {Cs#cstruct{frag_properties = Props}, true};
- false ->
- {Cs, false}
- end
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Helpers
-
-val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
- Value -> Value
- end.
-
-set_frag_hash(Tab, Props) ->
- case props_to_frag_hash(Tab, Props) of
- FH when record(FH, frag_state) ->
- mnesia_lib:set({Tab, frag_hash}, FH);
- no_hash ->
- mnesia_lib:unset({Tab, frag_hash})
- end.
-
-props_to_frag_hash(_Tab, []) ->
- no_hash;
-props_to_frag_hash(Tab, Props) ->
- case mnesia_schema:pick(Tab, base_table, Props, undefined) of
- T when T == Tab ->
- Foreign = mnesia_schema:pick(Tab, foreign_key, Props, must),
- N = mnesia_schema:pick(Tab, n_fragments, Props, must),
-
- case mnesia_schema:pick(Tab, hash_module, Props, undefined) of
- undefined ->
- Split = mnesia_schema:pick(Tab, next_n_to_split, Props, must),
- Doubles = mnesia_schema:pick(Tab, n_doubles, Props, must),
- FH = {frag_hash, Foreign, N, Split, Doubles},
- HashState = ?OLD_HASH_MOD:init_state(Tab, FH),
- #frag_state{foreign_key = Foreign,
- n_fragments = N,
- hash_module = ?OLD_HASH_MOD,
- hash_state = HashState};
- HashMod ->
- HashState = mnesia_schema:pick(Tab, hash_state, Props, must),
- #frag_state{foreign_key = Foreign,
- n_fragments = N,
- hash_module = HashMod,
- hash_state = HashState}
- %% Old style. Kept for backwards compatibility.
- end;
- _ ->
- no_hash
- end.
-
-lookup_prop(Tab, Prop) ->
- Props = val({Tab, frag_properties}),
- case lists:keysearch(Prop, 1, Props) of
- {value, {Prop, Val}} ->
- Val;
- false ->
- mnesia:abort({no_exists, Tab, Prop, {frag_properties, Props}})
- end.
-
-lookup_frag_hash(Tab) ->
- case ?catch_val({Tab, frag_hash}) of
- FH when record(FH, frag_state) ->
- FH;
- {frag_hash, K, N, _S, _D} = FH ->
- %% Old style. Kept for backwards compatibility.
- HashState = ?OLD_HASH_MOD:init_state(Tab, FH),
- #frag_state{foreign_key = K,
- n_fragments = N,
- hash_module = ?OLD_HASH_MOD,
- hash_state = HashState};
- {'EXIT', _} ->
- mnesia:abort({no_exists, Tab, frag_properties, frag_hash})
- end.
-
-is_top_frag(Tab) ->
- case ?catch_val({Tab, frag_hash}) of
- {'EXIT', _} ->
- false;
- _ ->
- [] == lookup_foreigners(Tab)
- end.
-
-%% Returns a list of tables
-lookup_foreigners(Tab) ->
- %% First field in HashPat is either frag_hash or frag_state
- HashPat = {'_', {Tab, '_'}, '_', '_', '_'},
- [T || [T] <- ?ets_match(mnesia_gvar, {{'$1', frag_hash}, HashPat})].
-
-%% Returns name of fragment table
-record_to_frag_name(Tab, Rec) ->
- case ?catch_val({Tab, frag_hash}) of
- {'EXIT', _} ->
- Tab;
- FH ->
- Pos = key_pos(FH),
- Key = element(Pos, Rec),
- N = key_to_n(FH, Key),
- n_to_frag_name(Tab, N)
- end.
-
-key_pos(FH) ->
- case FH#frag_state.foreign_key of
- undefined ->
- 2;
- {_ForeignTab, Pos} ->
- Pos
- end.
-
-%% Returns name of fragment table
-key_to_frag_name({BaseTab, _} = Tab, Key) ->
- N = key_to_frag_number(Tab, Key),
- n_to_frag_name(BaseTab, N);
-key_to_frag_name(Tab, Key) ->
- N = key_to_frag_number(Tab, Key),
- n_to_frag_name(Tab, N).
-
-%% Returns name of fragment table
-n_to_frag_name(Tab, 1) ->
- Tab;
-n_to_frag_name(Tab, N) when atom(Tab), integer(N) ->
- list_to_atom(atom_to_list(Tab) ++ "_frag" ++ integer_to_list(N));
-n_to_frag_name(Tab, N) ->
- mnesia:abort({bad_type, Tab, N}).
-
-%% Returns name of fragment table
-key_to_frag_number({Tab, ForeignKey}, _Key) ->
- FH = val({Tab, frag_hash}),
- case FH#frag_state.foreign_key of
- {_ForeignTab, _Pos} ->
- key_to_n(FH, ForeignKey);
- undefined ->
- mnesia:abort({combine_error, Tab, frag_properties,
- {foreign_key, undefined}})
- end;
-key_to_frag_number(Tab, Key) ->
- case ?catch_val({Tab, frag_hash}) of
- {'EXIT', _} ->
- 1;
- FH ->
- key_to_n(FH, Key)
- end.
-
-%% Returns fragment number
-key_to_n(FH, Key) ->
- HashState = FH#frag_state.hash_state,
- N =
- case FH#frag_state.hash_module of
- HashMod when HashMod == ?DEFAULT_HASH_MOD ->
- ?DEFAULT_HASH_MOD:key_to_frag_number(HashState, Key);
- HashMod ->
- HashMod:key_to_frag_number(HashState, Key)
- end,
- if
- integer(N), N >= 1, N =< FH#frag_state.n_fragments ->
- N;
- true ->
- mnesia:abort({"key_to_frag_number: Fragment number out of range",
- N, {range, 1, FH#frag_state.n_fragments}})
- end.
-
-%% Returns a list of frament table names
-frag_names(Tab) ->
- case ?catch_val({Tab, frag_hash}) of
- {'EXIT', _} ->
- [Tab];
- FH ->
- N = FH#frag_state.n_fragments,
- frag_names(Tab, N, [])
- end.
-
-frag_names(Tab, 1, Acc) ->
- [Tab | Acc];
-frag_names(Tab, N, Acc) ->
- Frag = n_to_frag_name(Tab, N),
- frag_names(Tab, N - 1, [Frag | Acc]).
-
-%% Returns a list of {Node, FragCount} tuples
-%% sorted on FragCounts
-frag_dist(Tab) ->
- Pool = lookup_prop(Tab, node_pool),
- Dist = [{good, Node, 0} || Node <- Pool],
- Dist2 = count_frag(frag_names(Tab), Dist),
- sort_dist(Dist2).
-
-count_frag([Frag | Frags], Dist) ->
- Dist2 = incr_nodes(val({Frag, ram_copies}), Dist),
- Dist3 = incr_nodes(val({Frag, disc_copies}), Dist2),
- Dist4 = incr_nodes(val({Frag, disc_only_copies}), Dist3),
- count_frag(Frags, Dist4);
-count_frag([], Dist) ->
- Dist.
-
-incr_nodes([Node | Nodes], Dist) ->
- Dist2 = incr_node(Node, Dist),
- incr_nodes(Nodes, Dist2);
-incr_nodes([], Dist) ->
- Dist.
-
-incr_node(Node, [{Kind, Node, Count} | Tail]) ->
- [{Kind, Node, Count + 1} | Tail];
-incr_node(Node, [Head | Tail]) ->
- [Head | incr_node(Node, Tail)];
-incr_node(Node, []) ->
- [{bad, Node, 1}].
-
-%% Sorts dist according in decreasing count order
-sort_dist(Dist) ->
- Dist2 = deep_dist(Dist, []),
- Dist3 = lists:keysort(1, Dist2),
- shallow_dist(Dist3).
-
-deep_dist([Head | Tail], Deep) ->
- {Kind, _Node, Count} = Head,
- {Tag, Same, Other} = pick_count(Kind, Count, [Head | Tail]),
- deep_dist(Other, [{Tag, Same} | Deep]);
-deep_dist([], Deep) ->
- Deep.
-
-pick_count(Kind, Count, [{Kind2, Node2, Count2} | Tail]) ->
- Head = {Node2, Count2},
- {_, Same, Other} = pick_count(Kind, Count, Tail),
- if
- Kind == bad ->
- {bad, [Head | Same], Other};
- Kind2 == bad ->
- {Count, Same, [{Kind2, Node2, Count2} | Other]};
- Count == Count2 ->
- {Count, [Head | Same], Other};
- true ->
- {Count, Same, [{Kind2, Node2, Count2} | Other]}
- end;
-pick_count(_Kind, Count, []) ->
- {Count, [], []}.
-
-shallow_dist([{_Tag, Shallow} | Deep]) ->
- Shallow ++ shallow_dist(Deep);
-shallow_dist([]) ->
- [].
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_frag_hash.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_frag_hash.erl
deleted file mode 100644
index 19b97f8d61..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_frag_hash.erl
+++ /dev/null
@@ -1,118 +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: mnesia_frag_hash.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
-%%
-%%%----------------------------------------------------------------------
-%%% Purpose : Implements hashing functionality for fragmented tables
-%%%----------------------------------------------------------------------
-
-%header_doc_include
--module(mnesia_frag_hash).
--behaviour(mnesia_frag_hash).
-
-%% Fragmented Table Hashing callback functions
--export([
- init_state/2,
- add_frag/1,
- del_frag/1,
- key_to_frag_number/2,
- match_spec_to_frag_numbers/2
- ]).
-
-%header_doc_include
-
-%impl_doc_include
--record(hash_state, {n_fragments, next_n_to_split, n_doubles}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-init_state(_Tab, State) when State == undefined ->
- #hash_state{n_fragments = 1,
- next_n_to_split = 1,
- n_doubles = 0}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-add_frag(State) when record(State, hash_state) ->
- SplitN = State#hash_state.next_n_to_split,
- P = SplitN + 1,
- L = State#hash_state.n_doubles,
- NewN = State#hash_state.n_fragments + 1,
- State2 = case trunc(math:pow(2, L)) + 1 of
- P2 when P2 == P ->
- State#hash_state{n_fragments = NewN,
- n_doubles = L + 1,
- next_n_to_split = 1};
- _ ->
- State#hash_state{n_fragments = NewN,
- next_n_to_split = P}
- end,
- {State2, [SplitN], [NewN]}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-del_frag(State) when record(State, hash_state) ->
- P = State#hash_state.next_n_to_split - 1,
- L = State#hash_state.n_doubles,
- N = State#hash_state.n_fragments,
- if
- P < 1 ->
- L2 = L - 1,
- MergeN = trunc(math:pow(2, L2)),
- State2 = State#hash_state{n_fragments = N - 1,
- next_n_to_split = MergeN,
- n_doubles = L2},
- {State2, [N], [MergeN]};
- true ->
- MergeN = P,
- State2 = State#hash_state{n_fragments = N - 1,
- next_n_to_split = MergeN},
- {State2, [N], [MergeN]}
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-key_to_frag_number(State, Key) when record(State, hash_state) ->
- L = State#hash_state.n_doubles,
- A = erlang:phash(Key, trunc(math:pow(2, L))),
- P = State#hash_state.next_n_to_split,
- if
- A < P ->
- erlang:phash(Key, trunc(math:pow(2, L + 1)));
- true ->
- A
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-match_spec_to_frag_numbers(State, MatchSpec) when record(State, hash_state) ->
- case MatchSpec of
- [{HeadPat, _, _}] when tuple(HeadPat), size(HeadPat) > 2 ->
- KeyPat = element(2, HeadPat),
- case has_var(KeyPat) of
- false ->
- [key_to_frag_number(State, KeyPat)];
- true ->
- lists:seq(1, State#hash_state.n_fragments)
- end;
- _ ->
- lists:seq(1, State#hash_state.n_fragments)
- end.
-
-%impl_doc_include
-
-has_var(Pat) ->
- mnesia:has_var(Pat).
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_frag_old_hash.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_frag_old_hash.erl
deleted file mode 100644
index 6560613302..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_frag_old_hash.erl
+++ /dev/null
@@ -1,127 +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: mnesia_frag_old_hash.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
-%%
-%%%----------------------------------------------------------------------
-%%% Purpose : Implements hashing functionality for fragmented tables
-%%%----------------------------------------------------------------------
-
--module(mnesia_frag_old_hash).
--behaviour(mnesia_frag_hash).
-
-%% Hashing callback functions
--export([
- init_state/2,
- add_frag/1,
- del_frag/1,
- key_to_frag_number/2,
- match_spec_to_frag_numbers/2
- ]).
-
--record(old_hash_state,
- {n_fragments,
- next_n_to_split,
- n_doubles}).
-
-%% Old style. Kept for backwards compatibility.
--record(frag_hash,
- {foreign_key,
- n_fragments,
- next_n_to_split,
- n_doubles}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-init_state(_Tab, InitialState) when InitialState == undefined ->
- #old_hash_state{n_fragments = 1,
- next_n_to_split = 1,
- n_doubles = 0};
-init_state(_Tab, FH) when record(FH, frag_hash) ->
- %% Old style. Kept for backwards compatibility.
- #old_hash_state{n_fragments = FH#frag_hash.n_fragments,
- next_n_to_split = FH#frag_hash.next_n_to_split,
- n_doubles = FH#frag_hash.n_doubles}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-add_frag(State) when record(State, old_hash_state) ->
- SplitN = State#old_hash_state.next_n_to_split,
- P = SplitN + 1,
- L = State#old_hash_state.n_doubles,
- NewN = State#old_hash_state.n_fragments + 1,
- State2 = case trunc(math:pow(2, L)) + 1 of
- P2 when P2 == P ->
- State#old_hash_state{n_fragments = NewN,
- next_n_to_split = 1,
- n_doubles = L + 1};
- _ ->
- State#old_hash_state{n_fragments = NewN,
- next_n_to_split = P}
- end,
- {State2, [SplitN], [NewN]}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-del_frag(State) when record(State, old_hash_state) ->
- P = State#old_hash_state.next_n_to_split - 1,
- L = State#old_hash_state.n_doubles,
- N = State#old_hash_state.n_fragments,
- if
- P < 1 ->
- L2 = L - 1,
- MergeN = trunc(math:pow(2, L2)),
- State2 = State#old_hash_state{n_fragments = N - 1,
- next_n_to_split = MergeN,
- n_doubles = L2},
- {State2, [N], [MergeN]};
- true ->
- MergeN = P,
- State2 = State#old_hash_state{n_fragments = N - 1,
- next_n_to_split = MergeN},
- {State2, [N], [MergeN]}
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-key_to_frag_number(State, Key) when record(State, old_hash_state) ->
- L = State#old_hash_state.n_doubles,
- A = erlang:hash(Key, trunc(math:pow(2, L))),
- P = State#old_hash_state.next_n_to_split,
- if
- A < P ->
- erlang:hash(Key, trunc(math:pow(2, L + 1)));
- true ->
- A
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-match_spec_to_frag_numbers(State, MatchSpec) when record(State, old_hash_state) ->
- case MatchSpec of
- [{HeadPat, _, _}] when tuple(HeadPat), size(HeadPat) > 2 ->
- KeyPat = element(2, HeadPat),
- case has_var(KeyPat) of
- false ->
- [key_to_frag_number(State, KeyPat)];
- true ->
- lists:seq(1, State#old_hash_state.n_fragments)
- end;
- _ ->
- lists:seq(1, State#old_hash_state.n_fragments)
- end.
-
-has_var(Pat) ->
- mnesia:has_var(Pat).
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_index.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_index.erl
deleted file mode 100644
index 3455a4808a..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_index.erl
+++ /dev/null
@@ -1,380 +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: mnesia_index.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
-%%
-%% Purpose: Handles index functionality in mnesia
-
--module(mnesia_index).
--export([read/5,
- add_index/5,
- delete_index/3,
- del_object_index/5,
- clear_index/4,
- dirty_match_object/3,
- dirty_select/3,
- dirty_read/3,
- dirty_read2/3,
-
- db_put/2,
- db_get/2,
- db_match_erase/2,
- get_index_table/2,
- get_index_table/3,
-
- tab2filename/2,
- tab2tmp_filename/2,
- init_index/2,
- init_indecies/3,
- del_transient/2,
- del_transient/3,
- del_index_table/3]).
-
--import(mnesia_lib, [verbose/2]).
--include("mnesia.hrl").
-
--record(index, {setorbag, pos_list}).
-
-val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _ReASoN_} -> mnesia_lib:other_val(Var, _ReASoN_);
- _VaLuE_ -> _VaLuE_
- end.
-
-%% read an object list throuh its index table
-%% we assume that table Tab has index on attribute number Pos
-
-read(Tid, Store, Tab, IxKey, Pos) ->
- ResList = mnesia_locker:ixrlock(Tid, Store, Tab, IxKey, Pos),
- %% Remove all tuples which don't include Ixkey, happens when Tab is a bag
- case val({Tab, setorbag}) of
- bag ->
- mnesia_lib:key_search_all(IxKey, Pos, ResList);
- _ ->
- ResList
- end.
-
-add_index(Index, Tab, Key, Obj, Old) ->
- add_index2(Index#index.pos_list, Index#index.setorbag, Tab, Key, Obj, Old).
-
-add_index2([{Pos, Ixt} |Tail], bag, Tab, K, Obj, OldRecs) ->
- db_put(Ixt, {element(Pos, Obj), K}),
- add_index2(Tail, bag, Tab, K, Obj, OldRecs);
-add_index2([{Pos, Ixt} |Tail], Type, Tab, K, Obj, OldRecs) ->
- %% Remove old tuples in index if Tab is updated
- case OldRecs of
- undefined ->
- Old = mnesia_lib:db_get(Tab, K),
- del_ixes(Ixt, Old, Pos, K);
- Old ->
- del_ixes(Ixt, Old, Pos, K)
- end,
- db_put(Ixt, {element(Pos, Obj), K}),
- add_index2(Tail, Type, Tab, K, Obj, OldRecs);
-add_index2([], _, _Tab, _K, _Obj, _) -> ok.
-
-delete_index(Index, Tab, K) ->
- delete_index2(Index#index.pos_list, Tab, K).
-
-delete_index2([{Pos, Ixt} | Tail], Tab, K) ->
- DelObjs = mnesia_lib:db_get(Tab, K),
- del_ixes(Ixt, DelObjs, Pos, K),
- delete_index2(Tail, Tab, K);
-delete_index2([], _Tab, _K) -> ok.
-
-
-del_ixes(_Ixt, [], _Pos, _L) -> ok;
-del_ixes(Ixt, [Obj | Tail], Pos, Key) ->
- db_match_erase(Ixt, {element(Pos, Obj), Key}),
- del_ixes(Ixt, Tail, Pos, Key).
-
-del_object_index(Index, Tab, K, Obj, Old) ->
- del_object_index2(Index#index.pos_list, Index#index.setorbag, Tab, K, Obj, Old).
-
-del_object_index2([], _, _Tab, _K, _Obj, _Old) -> ok;
-del_object_index2([{Pos, Ixt} | Tail], SoB, Tab, K, Obj, Old) ->
- case SoB of
- bag ->
- del_object_bag(Tab, K, Obj, Pos, Ixt, Old);
- _ -> %% If set remove the tuple in index table
- del_ixes(Ixt, [Obj], Pos, K)
- end,
- del_object_index2(Tail, SoB, Tab, K, Obj, Old).
-
-del_object_bag(Tab, Key, Obj, Pos, Ixt, undefined) ->
- Old = mnesia_lib:db_get(Tab, Key),
- del_object_bag(Tab, Key, Obj, Pos, Ixt, Old);
-%% If Tab type is bag we need remove index identifier if Tab
-%% contains less than 2 elements.
-del_object_bag(_Tab, Key, Obj, Pos, Ixt, Old) when length(Old) < 2 ->
- del_ixes(Ixt, [Obj], Pos, Key);
-del_object_bag(_Tab, _Key, _Obj, _Pos, _Ixt, _Old) -> ok.
-
-clear_index(Index, Tab, K, Obj) ->
- clear_index2(Index#index.pos_list, Tab, K, Obj).
-
-clear_index2([], _Tab, _K, _Obj) -> ok;
-clear_index2([{_Pos, Ixt} | Tail], Tab, K, Obj) ->
- db_match_erase(Ixt, Obj),
- clear_index2(Tail, Tab, K, Obj).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-dirty_match_object(Tab, Pat, Pos) ->
- %% Assume that we are on the node where the replica is
- case element(2, Pat) of
- '_' ->
- IxKey = element(Pos, Pat),
- RealKeys = realkeys(Tab, Pos, IxKey),
- merge(RealKeys, Tab, Pat, []);
- _Else ->
- mnesia_lib:db_match_object(Tab, Pat)
- end.
-
-merge([{_IxKey, RealKey} | Tail], Tab, Pat, Ack) ->
- %% Assume that we are on the node where the replica is
- Pat2 = setelement(2, Pat, RealKey),
- Recs = mnesia_lib:db_match_object(Tab, Pat2),
- merge(Tail, Tab, Pat, Recs ++ Ack);
-merge([], _, _, Ack) ->
- Ack.
-
-realkeys(Tab, Pos, IxKey) ->
- Index = get_index_table(Tab, Pos),
- db_get(Index, IxKey). % a list on the form [{IxKey, RealKey1} , ....
-
-dirty_select(Tab, Spec, Pos) ->
- %% Assume that we are on the node where the replica is
- %% Returns the records without applying the match spec
- %% The actual filtering is handled by the caller
- IxKey = element(Pos, Spec),
- RealKeys = realkeys(Tab, Pos, IxKey),
- StorageType = val({Tab, storage_type}),
- lists:append([mnesia_lib:db_get(StorageType, Tab, Key) || Key <- RealKeys]).
-
-dirty_read(Tab, IxKey, Pos) ->
- ResList = mnesia:dirty_rpc(Tab, ?MODULE, dirty_read2,
- [Tab, IxKey, Pos]),
- case val({Tab, setorbag}) of
- bag ->
- %% Remove all tuples which don't include Ixkey
- mnesia_lib:key_search_all(IxKey, Pos, ResList);
- _ ->
- ResList
- end.
-
-dirty_read2(Tab, IxKey, Pos) ->
- Ix = get_index_table(Tab, Pos),
- Keys = db_match(Ix, {IxKey, '$1'}),
- r_keys(Keys, Tab, []).
-
-r_keys([[H]|T],Tab,Ack) ->
- V = mnesia_lib:db_get(Tab, H),
- r_keys(T, Tab, V ++ Ack);
-r_keys([], _, Ack) ->
- Ack.
-
-
-%%%%%%% Creation, Init and deletion routines for index tables
-%% We can have several indexes on the same table
-%% this can be a fairly costly operation if table is *very* large
-
-tab2filename(Tab, Pos) ->
- mnesia_lib:dir(Tab) ++ "_" ++ integer_to_list(Pos) ++ ".DAT".
-
-tab2tmp_filename(Tab, Pos) ->
- mnesia_lib:dir(Tab) ++ "_" ++ integer_to_list(Pos) ++ ".TMP".
-
-init_index(Tab, Storage) ->
- PosList = val({Tab, index}),
- init_indecies(Tab, Storage, PosList).
-
-init_indecies(Tab, Storage, PosList) ->
- case Storage of
- unknown ->
- ignore;
- disc_only_copies ->
- init_disc_index(Tab, PosList);
- ram_copies ->
- make_ram_index(Tab, PosList);
- disc_copies ->
- make_ram_index(Tab, PosList)
- end.
-
-%% works for both ram and disc indexes
-
-del_index_table(_, unknown, _) ->
- ignore;
-del_index_table(Tab, Storage, Pos) ->
- delete_transient_index(Tab, Pos, Storage),
- mnesia_lib:del({Tab, index}, Pos).
-
-del_transient(Tab, Storage) ->
- PosList = val({Tab, index}),
- del_transient(Tab, PosList, Storage).
-
-del_transient(_, [], _) -> done;
-del_transient(Tab, [Pos | Tail], Storage) ->
- delete_transient_index(Tab, Pos, Storage),
- del_transient(Tab, Tail, Storage).
-
-delete_transient_index(Tab, Pos, disc_only_copies) ->
- Tag = {Tab, index, Pos},
- mnesia_monitor:unsafe_close_dets(Tag),
- file:delete(tab2filename(Tab, Pos)),
- del_index_info(Tab, Pos), %% Uses val(..)
- mnesia_lib:unset({Tab, {index, Pos}});
-
-delete_transient_index(Tab, Pos, _Storage) ->
- Ixt = val({Tab, {index, Pos}}),
- ?ets_delete_table(Ixt),
- del_index_info(Tab, Pos),
- mnesia_lib:unset({Tab, {index, Pos}}).
-
-%%%%% misc functions for the index create/init/delete functions above
-
-%% assuming that the file exists.
-init_disc_index(_Tab, []) ->
- done;
-init_disc_index(Tab, [Pos | Tail]) when integer(Pos) ->
- Fn = tab2filename(Tab, Pos),
- IxTag = {Tab, index, Pos},
- file:delete(Fn),
- Args = [{file, Fn}, {keypos, 1}, {type, bag}],
- mnesia_monitor:open_dets(IxTag, Args),
- Storage = disc_only_copies,
- Key = mnesia_lib:db_first(Storage, Tab),
- Recs = mnesia_lib:db_get(Storage, Tab, Key),
- BinSize = size(term_to_binary(Recs)),
- KeysPerChunk = (4000 div BinSize) + 1,
- Init = {start, KeysPerChunk},
- mnesia_lib:db_fixtable(Storage, Tab, true),
- ok = dets:init_table(IxTag, create_fun(Init, Tab, Pos)),
- mnesia_lib:db_fixtable(Storage, Tab, false),
- mnesia_lib:set({Tab, {index, Pos}}, IxTag),
- add_index_info(Tab, val({Tab, setorbag}), {Pos, {dets, IxTag}}),
- init_disc_index(Tab, Tail).
-
-create_fun(Cont, Tab, Pos) ->
- fun(read) ->
- Data =
- case Cont of
- {start, KeysPerChunk} ->
- mnesia_lib:db_init_chunk(disc_only_copies, Tab, KeysPerChunk);
- '$end_of_table' ->
- '$end_of_table';
- _Else ->
- mnesia_lib:db_chunk(disc_only_copies, Cont)
- end,
- case Data of
- '$end_of_table' ->
- end_of_input;
- {Recs, Next} ->
- IdxElems = [{element(Pos, Obj), element(2, Obj)} || Obj <- Recs],
- {IdxElems, create_fun(Next, Tab, Pos)}
- end;
- (close) ->
- ok
- end.
-
-make_ram_index(_, []) ->
- done;
-make_ram_index(Tab, [Pos | Tail]) ->
- add_ram_index(Tab, Pos),
- make_ram_index(Tab, Tail).
-
-add_ram_index(Tab, Pos) when integer(Pos) ->
- verbose("Creating index for ~w ~n", [Tab]),
- Index = mnesia_monitor:mktab(mnesia_index, [bag, public]),
- Insert = fun(Rec, _Acc) ->
- true = ?ets_insert(Index, {element(Pos, Rec), element(2, Rec)})
- end,
- mnesia_lib:db_fixtable(ram_copies, Tab, true),
- true = ets:foldl(Insert, true, Tab),
- mnesia_lib:db_fixtable(ram_copies, Tab, false),
- mnesia_lib:set({Tab, {index, Pos}}, Index),
- add_index_info(Tab, val({Tab, setorbag}), {Pos, {ram, Index}});
-add_ram_index(_Tab, snmp) ->
- ok.
-
-add_index_info(Tab, Type, IxElem) ->
- Commit = val({Tab, commit_work}),
- case lists:keysearch(index, 1, Commit) of
- false ->
- Index = #index{setorbag = Type,
- pos_list = [IxElem]},
- %% Check later if mnesia_tm is sensative about the order
- mnesia_lib:set({Tab, commit_work},
- mnesia_lib:sort_commit([Index | Commit]));
- {value, Old} ->
- %% We could check for consistency here
- Index = Old#index{pos_list = [IxElem | Old#index.pos_list]},
- NewC = lists:keyreplace(index, 1, Commit, Index),
- mnesia_lib:set({Tab, commit_work},
- mnesia_lib:sort_commit(NewC))
- end.
-
-del_index_info(Tab, Pos) ->
- Commit = val({Tab, commit_work}),
- case lists:keysearch(index, 1, Commit) of
- false ->
- %% Something is wrong ignore
- skip;
- {value, Old} ->
- case lists:keydelete(Pos, 1, Old#index.pos_list) of
- [] ->
- NewC = lists:keydelete(index, 1, Commit),
- mnesia_lib:set({Tab, commit_work},
- mnesia_lib:sort_commit(NewC));
- New ->
- Index = Old#index{pos_list = New},
- NewC = lists:keyreplace(index, 1, Commit, Index),
- mnesia_lib:set({Tab, commit_work},
- mnesia_lib:sort_commit(NewC))
- end
- end.
-
-db_put({ram, Ixt}, V) ->
- true = ?ets_insert(Ixt, V);
-db_put({dets, Ixt}, V) ->
- ok = dets:insert(Ixt, V).
-
-db_get({ram, Ixt}, K) ->
- ?ets_lookup(Ixt, K);
-db_get({dets, Ixt}, K) ->
- dets:lookup(Ixt, K).
-
-db_match_erase({ram, Ixt}, Pat) ->
- true = ?ets_match_delete(Ixt, Pat);
-db_match_erase({dets, Ixt}, Pat) ->
- ok = dets:match_delete(Ixt, Pat).
-
-db_match({ram, Ixt}, Pat) ->
- ?ets_match(Ixt, Pat);
-db_match({dets, Ixt}, Pat) ->
- dets:match(Ixt, Pat).
-
-get_index_table(Tab, Pos) ->
- get_index_table(Tab, val({Tab, storage_type}), Pos).
-
-get_index_table(Tab, ram_copies, Pos) ->
- {ram, val({Tab, {index, Pos}})};
-get_index_table(Tab, disc_copies, Pos) ->
- {ram, val({Tab, {index, Pos}})};
-get_index_table(Tab, disc_only_copies, Pos) ->
- {dets, val({Tab, {index, Pos}})};
-get_index_table(_Tab, unknown, _Pos) ->
- unknown.
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_kernel_sup.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_kernel_sup.erl
deleted file mode 100644
index 899d434fdd..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_kernel_sup.erl
+++ /dev/null
@@ -1,62 +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: mnesia_kernel_sup.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
-%%
--module(mnesia_kernel_sup).
-
--behaviour(supervisor).
-
--export([start/0, init/1, supervisor_timeout/1]).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% top supervisor callback functions
-
-start() ->
- supervisor:start_link({local, mnesia_kernel_sup}, ?MODULE, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% sub supervisor callback functions
-
-init([]) ->
- ProcLib = [mnesia_monitor, proc_lib],
- Flags = {one_for_all, 0, timer:hours(24)}, % Trust the top supervisor
- Workers = [worker_spec(mnesia_monitor, timer:seconds(3), [gen_server]),
- worker_spec(mnesia_subscr, timer:seconds(3), [gen_server]),
- worker_spec(mnesia_locker, timer:seconds(3), ProcLib),
- worker_spec(mnesia_recover, timer:minutes(3), [gen_server]),
- worker_spec(mnesia_tm, timer:seconds(30), ProcLib),
- supervisor_spec(mnesia_checkpoint_sup),
- supervisor_spec(mnesia_snmp_sup),
- worker_spec(mnesia_controller, timer:seconds(3), [gen_server]),
- worker_spec(mnesia_late_loader, timer:seconds(3), ProcLib)
- ],
- {ok, {Flags, Workers}}.
-
-worker_spec(Name, KillAfter, Modules) ->
- KA = supervisor_timeout(KillAfter),
- {Name, {Name, start, []}, permanent, KA, worker, [Name] ++ Modules}.
-
-supervisor_spec(Name) ->
- {Name, {Name, start, []}, permanent, infinity, supervisor,
- [Name, supervisor]}.
-
--ifdef(debug_shutdown).
-supervisor_timeout(_KillAfter) -> timer:hours(24).
--else.
-supervisor_timeout(KillAfter) -> KillAfter.
--endif.
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_late_loader.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_late_loader.erl
deleted file mode 100644
index 96d00f6e81..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_late_loader.erl
+++ /dev/null
@@ -1,95 +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: mnesia_late_loader.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
-%%
--module(mnesia_late_loader).
-
--export([
- async_late_disc_load/3,
- maybe_async_late_disc_load/3,
- init/1,
- start/0
- ]).
-
-%% sys callback functions
--export([
- system_continue/3,
- system_terminate/4,
- system_code_change/4
- ]).
-
--define(SERVER_NAME, ?MODULE).
-
--record(state, {supervisor}).
-
-async_late_disc_load(Node, Tabs, Reason) ->
- Msg = {async_late_disc_load, Tabs, Reason},
- catch ({?SERVER_NAME, Node} ! {self(), Msg}).
-
-maybe_async_late_disc_load(Node, Tabs, Reason) ->
- Msg = {maybe_async_late_disc_load, Tabs, Reason},
- catch ({?SERVER_NAME, Node} ! {self(), Msg}).
-
-start() ->
- mnesia_monitor:start_proc(?SERVER_NAME, ?MODULE, init, [self()]).
-
-init(Parent) ->
- %% Trap exit omitted intentionally
- register(?SERVER_NAME, self()),
- link(whereis(mnesia_controller)), %% We may not hang
- mnesia_controller:merge_schema(),
- unlink(whereis(mnesia_controller)),
- mnesia_lib:set(mnesia_status, running),
- proc_lib:init_ack(Parent, {ok, self()}),
- loop(#state{supervisor = Parent}).
-
-loop(State) ->
- receive
- {_From, {async_late_disc_load, Tabs, Reason}} ->
- mnesia_controller:schedule_late_disc_load(Tabs, Reason),
- loop(State);
-
- {_From, {maybe_async_late_disc_load, Tabs, Reason}} ->
- GoodTabs =
- [T || T <- Tabs,
- lists:member(node(),
- mnesia_recover:get_master_nodes(T))],
- mnesia_controller:schedule_late_disc_load(GoodTabs, Reason),
- loop(State);
-
- {system, From, Msg} ->
- mnesia_lib:dbg_out("~p got {system, ~p, ~p}~n",
- [?SERVER_NAME, From, Msg]),
- Parent = State#state.supervisor,
- sys:handle_system_msg(Msg, From, Parent, ?MODULE, [], State);
-
- Msg ->
- mnesia_lib:error("~p got unexpected message: ~p~n",
- [?SERVER_NAME, Msg]),
- loop(State)
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% System upgrade
-
-system_continue(_Parent, _Debug, State) ->
- loop(State).
-
-system_terminate(Reason, _Parent, _Debug, _State) ->
- exit(Reason).
-
-system_code_change(State, _Module, _OldVsn, _Extra) ->
- {ok, State}.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_lib.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_lib.erl
deleted file mode 100644
index 2c9e4d4fcf..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_lib.erl
+++ /dev/null
@@ -1,1278 +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: mnesia_lib.erl,v 1.3 2009/07/01 15:45:40 kostis Exp $
-%%
-%% This module contains all sorts of various which doesn't fit
-%% anywhere else. Basically everything is exported.
-
--module(mnesia_lib).
-
--include("mnesia.hrl").
--include_lib("kernel/include/file.hrl").
-
--export([core_file/0]).
-
--export([
- active_tables/0,
- add/2,
- add_list/2,
- all_nodes/0,
-%% catch_val/1,
- cleanup_tmp_files/1,
- copy_file/2,
- copy_holders/1,
- coredump/0,
- coredump/1,
- create_counter/1,
- cs_to_nodes/1,
- cs_to_storage_type/2,
- dets_to_ets/6,
- db_chunk/2,
- db_init_chunk/1,
- db_init_chunk/2,
- db_init_chunk/3,
- db_erase/2,
- db_erase/3,
- db_erase_tab/1,
- db_erase_tab/2,
- db_first/1,
- db_first/2,
- db_last/1,
- db_last/2,
- db_fixtable/3,
- db_get/2,
- db_get/3,
- db_match_erase/2,
- db_match_erase/3,
- db_match_object/2,
- db_match_object/3,
- db_next_key/2,
- db_next_key/3,
- db_prev_key/2,
- db_prev_key/3,
- db_put/2,
- db_put/3,
- db_select/2,
- db_select/3,
- db_slot/2,
- db_slot/3,
- db_update_counter/3,
- db_update_counter/4,
- dbg_out/2,
- del/2,
- dets_sync_close/1,
- dets_sync_open/2,
- dets_sync_open/3,
- dir/0,
- dir/1,
- dir_info/0,
- dirty_rpc_error_tag/1,
- dist_coredump/0,
- disk_type/1,
- disk_type/2,
- elems/2,
- ensure_loaded/1,
- error/2,
- error_desc/1,
- etype/1,
- exists/1,
- fatal/2,
- get_node_number/0,
- fix_error/1,
- important/2,
- incr_counter/1,
- incr_counter/2,
- intersect/2,
- is_running/0,
- is_running/1,
- is_running_remote/0,
- is_string/1,
- key_search_delete/3,
- key_search_all/3,
- last_error/0,
- local_active_tables/0,
- lock_table/1,
- mkcore/1,
- not_active_here/1,
- other_val/2,
- pad_name/3,
- random_time/2,
- read_counter/1,
- readable_indecies/1,
- remote_copy_holders/1,
- report_fatal/2,
- report_system_event/1,
- running_nodes/0,
- running_nodes/1,
- schema_cs_to_storage_type/2,
- search_delete/2,
- set/2,
- set_counter/2,
- set_local_content_whereabouts/1,
- set_remote_where_to_read/1,
- set_remote_where_to_read/2,
- show/1,
- show/2,
- sort_commit/1,
- storage_type_at_node/2,
- swap_tmp_files/1,
- tab2dat/1,
- tab2dmp/1,
- tab2tmp/1,
- tab2dcd/1,
- tab2dcl/1,
- to_list/1,
- union/2,
- uniq/1,
- unlock_table/1,
- unset/1,
- update_counter/2,
- val/1,
- vcore/0,
- vcore/1,
- verbose/2,
- view/0,
- view/1,
- view/2,
- warning/2,
-
- is_debug_compiled/0,
- activate_debug_fun/5,
- deactivate_debug_fun/3,
- eval_debug_fun/4,
- scratch_debug_fun/0
- ]).
-
-
-search_delete(Obj, List) ->
- search_delete(Obj, List, [], none).
-search_delete(Obj, [Obj|Tail], Ack, _Res) ->
- search_delete(Obj, Tail, Ack, Obj);
-search_delete(Obj, [H|T], Ack, Res) ->
- search_delete(Obj, T, [H|Ack], Res);
-search_delete(_, [], Ack, Res) ->
- {Res, Ack}.
-
-key_search_delete(Key, Pos, TupleList) ->
- key_search_delete(Key, Pos, TupleList, none, []).
-key_search_delete(Key, Pos, [H|T], _Obj, Ack) when element(Pos, H) == Key ->
- key_search_delete(Key, Pos, T, H, Ack);
-key_search_delete(Key, Pos, [H|T], Obj, Ack) ->
- key_search_delete(Key, Pos, T, Obj, [H|Ack]);
-key_search_delete(_, _, [], Obj, Ack) ->
- {Obj, Ack}.
-
-key_search_all(Key, Pos, TupleList) ->
- key_search_all(Key, Pos, TupleList, []).
-key_search_all(Key, N, [H|T], Ack) when element(N, H) == Key ->
- key_search_all(Key, N, T, [H|Ack]);
-key_search_all(Key, N, [_|T], Ack) ->
- key_search_all(Key, N, T, Ack);
-key_search_all(_, _, [], Ack) -> Ack.
-
-intersect(L1, L2) ->
- L2 -- (L2 -- L1).
-
-elems(I, [H|T]) ->
- [element(I, H) | elems(I, T)];
-elems(_, []) ->
- [].
-
-%% sort_commit see to that checkpoint info is always first in
-%% commit_work structure the other info don't need to be sorted.
-sort_commit(List) ->
- sort_commit2(List, []).
-
-sort_commit2([{checkpoints, ChkpL}| Rest], Acc) ->
- [{checkpoints, ChkpL}| Rest] ++ Acc;
-sort_commit2([H | R], Acc) ->
- sort_commit2(R, [H | Acc]);
-sort_commit2([], Acc) -> Acc.
-
-is_string([H|T]) ->
- if
- 0 =< H, H < 256, integer(H) -> is_string(T);
- true -> false
- end;
-is_string([]) -> true.
-
-%%%
-
-union([H|L1], L2) ->
- case lists:member(H, L2) of
- true -> union(L1, L2);
- false -> [H | union(L1, L2)]
- end;
-union([], L2) -> L2.
-
-uniq([]) ->
- [];
-uniq(List) ->
- [H|T] = lists:sort(List),
- uniq1(H, T, []).
-
-uniq1(H, [H|R], Ack) ->
- uniq1(H, R, Ack);
-uniq1(Old, [H|R], Ack) ->
- uniq1(H, R, [Old|Ack]);
-uniq1(Old, [], Ack) ->
- [Old| Ack].
-
-to_list(X) when list(X) -> X;
-to_list(X) -> atom_to_list(X).
-
-all_nodes() ->
- Ns = mnesia:system_info(db_nodes) ++
- mnesia:system_info(extra_db_nodes),
- mnesia_lib:uniq(Ns).
-
-running_nodes() ->
- running_nodes(all_nodes()).
-
-running_nodes(Ns) ->
- {Replies, _BadNs} = rpc:multicall(Ns, ?MODULE, is_running_remote, []),
- [N || {GoodState, N} <- Replies, GoodState == true].
-
-is_running_remote() ->
- IsRunning = is_running(),
- {IsRunning == yes, node()}.
-
-is_running(Node) when atom(Node) ->
- case rpc:call(Node, ?MODULE, is_running, []) of
- {badrpc, _} -> no;
- X -> X
- end.
-
-is_running() ->
- case ?catch_val(mnesia_status) of
- {'EXIT', _} -> no;
- running -> yes;
- starting -> starting;
- stopping -> stopping
- end.
-
-show(X) ->
- show(X, []).
-show(F, A) ->
- io:format(user, F, A).
-
-
-pad_name([Char | Chars], Len, Tail) ->
- [Char | pad_name(Chars, Len - 1, Tail)];
-pad_name([], Len, Tail) when Len =< 0 ->
- Tail;
-pad_name([], Len, Tail) ->
- [$ | pad_name([], Len - 1, Tail)].
-
-%% Some utility functions .....
-active_here(Tab) ->
- case val({Tab, where_to_read}) of
- Node when Node == node() -> true;
- _ -> false
- end.
-
-not_active_here(Tab) ->
- not active_here(Tab).
-
-exists(Fname) ->
- case file:open(Fname, [raw,read]) of
- {ok, F} ->file:close(F), true;
- _ -> false
- end.
-
-dir() -> mnesia_monitor:get_env(dir).
-
-dir(Fname) ->
- filename:join([dir(), to_list(Fname)]).
-
-tab2dat(Tab) -> %% DETS files
- dir(lists:concat([Tab, ".DAT"])).
-
-tab2tmp(Tab) ->
- dir(lists:concat([Tab, ".TMP"])).
-
-tab2dmp(Tab) -> %% Dumped ets tables
- dir(lists:concat([Tab, ".DMP"])).
-
-tab2dcd(Tab) -> %% Disc copies data
- dir(lists:concat([Tab, ".DCD"])).
-
-tab2dcl(Tab) -> %% Disc copies log
- dir(lists:concat([Tab, ".DCL"])).
-
-storage_type_at_node(Node, Tab) ->
- search_key(Node, [{disc_copies, val({Tab, disc_copies})},
- {ram_copies, val({Tab, ram_copies})},
- {disc_only_copies, val({Tab, disc_only_copies})}]).
-
-cs_to_storage_type(Node, Cs) ->
- search_key(Node, [{disc_copies, Cs#cstruct.disc_copies},
- {ram_copies, Cs#cstruct.ram_copies},
- {disc_only_copies, Cs#cstruct.disc_only_copies}]).
-
-schema_cs_to_storage_type(Node, Cs) ->
- case cs_to_storage_type(Node, Cs) of
- unknown when Cs#cstruct.name == schema -> ram_copies;
- Other -> Other
- end.
-
-
-search_key(Key, [{Val, List} | Tail]) ->
- case lists:member(Key, List) of
- true -> Val;
- false -> search_key(Key, Tail)
- end;
-search_key(_Key, []) ->
- unknown.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% ops, we've got some global variables here :-)
-
-%% They are
-%%
-%% {Tab, setorbag}, -> set | bag
-%% {Tab, storage_type} -> disc_copies |ram_copies | unknown (**)
-%% {Tab, disc_copies} -> node list (from schema)
-%% {Tab, ram_copies}, -> node list (from schema)
-%% {Tab, arity}, -> number
-%% {Tab, attributes}, -> atom list
-%% {Tab, wild_pattern}, -> record tuple with '_'s
-%% {Tab, {index, Pos}} -> ets table
-%% {Tab, index} -> integer list
-%% {Tab, cstruct} -> cstruct structure
-%%
-
-%% The following fields are dynamic according to the
-%% the current node/table situation
-
-%% {Tab, where_to_write} -> node list
-%% {Tab, where_to_read} -> node | nowhere
-%%
-%% {schema, tables} -> tab list
-%% {schema, local_tables} -> tab list (**)
-%%
-%% {current, db_nodes} -> node list
-%%
-%% dir -> directory path (**)
-%% mnesia_status -> status | running | stopping (**)
-%% (**) == (Different on all nodes)
-%%
-
-val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _ReASoN_} -> mnesia_lib:other_val(Var, _ReASoN_);
- _VaLuE_ -> _VaLuE_
- end.
-
-set(Var, Val) ->
- ?ets_insert(mnesia_gvar, {Var, Val}).
-
-unset(Var) ->
- ?ets_delete(mnesia_gvar, Var).
-
-other_val(Var, Other) ->
- case Var of
- {_, where_to_read} -> nowhere;
- {_, where_to_write} -> [];
- {_, active_replicas} -> [];
- _ ->
- pr_other(Var, Other)
- end.
-
-pr_other(Var, Other) ->
- Why =
- case is_running() of
- no -> {node_not_running, node()};
- _ -> {no_exists, Var}
- end,
- verbose("~p (~p) val(mnesia_gvar, ~w) -> ~p ~p ~n",
- [self(), process_info(self(), registered_name),
- Var, Other, Why]),
- case Other of
- {badarg, [{ets, lookup_element, _}|_]} ->
- exit(Why);
- _ ->
- erlang:error(Why)
- end.
-
-%% Some functions for list valued variables
-add(Var, Val) ->
- L = val(Var),
- set(Var, [Val | lists:delete(Val, L)]).
-
-add_list(Var, List) ->
- L = val(Var),
- set(Var, union(L, List)).
-
-del(Var, Val) ->
- L = val(Var),
- set(Var, lists:delete(Val, L)).
-
-%% This function is needed due to the fact
-%% that the application_controller enters
-%% a deadlock now and then. ac is implemented
-%% as a rather naive server.
-ensure_loaded(Appl) ->
- case application_controller:get_loaded(Appl) of
- {true, _} ->
- ok;
- false ->
- case application:load(Appl) of
- ok ->
- ok;
- {error, {already_loaded, Appl}} ->
- ok;
- {error, Reason} ->
- {error, {application_load_error, Reason}}
- end
- end.
-
-local_active_tables() ->
- Tabs = val({schema, local_tables}),
- lists:zf(fun(Tab) -> active_here(Tab) end, Tabs).
-
-active_tables() ->
- Tabs = val({schema, tables}),
- F = fun(Tab) ->
- case val({Tab, where_to_read}) of
- nowhere -> false;
- _ -> {true, Tab}
- end
- end,
- lists:zf(F, Tabs).
-
-etype(X) when integer(X) -> integer;
-etype([]) -> nil;
-etype(X) when list(X) -> list;
-etype(X) when tuple(X) -> tuple;
-etype(X) when atom(X) -> atom;
-etype(_) -> othertype.
-
-remote_copy_holders(Cs) ->
- copy_holders(Cs) -- [node()].
-
-copy_holders(Cs) when Cs#cstruct.local_content == false ->
- cs_to_nodes(Cs);
-copy_holders(Cs) when Cs#cstruct.local_content == true ->
- case lists:member(node(), cs_to_nodes(Cs)) of
- true -> [node()];
- false -> []
- end.
-
-
-set_remote_where_to_read(Tab) ->
- set_remote_where_to_read(Tab, []).
-
-set_remote_where_to_read(Tab, Ignore) ->
- Active = val({Tab, active_replicas}),
- Valid =
- case mnesia_recover:get_master_nodes(Tab) of
- [] -> Active;
- Masters -> mnesia_lib:intersect(Masters, Active)
- end,
- Available = mnesia_lib:intersect(val({current, db_nodes}), Valid -- Ignore),
- DiscOnlyC = val({Tab, disc_only_copies}),
- Prefered = Available -- DiscOnlyC,
- if
- Prefered /= [] ->
- set({Tab, where_to_read}, hd(Prefered));
- Available /= [] ->
- set({Tab, where_to_read}, hd(Available));
- true ->
- set({Tab, where_to_read}, nowhere)
- end.
-
-%%% Local only
-set_local_content_whereabouts(Tab) ->
- add({schema, local_tables}, Tab),
- add({Tab, active_replicas}, node()),
- set({Tab, where_to_write}, [node()]),
- set({Tab, where_to_read}, node()).
-
-%%% counter routines
-
-create_counter(Name) ->
- set_counter(Name, 0).
-
-set_counter(Name, Val) ->
- ?ets_insert(mnesia_gvar, {Name, Val}).
-
-incr_counter(Name) ->
- ?ets_update_counter(mnesia_gvar, Name, 1).
-
-incr_counter(Name, I) ->
- ?ets_update_counter(mnesia_gvar, Name, I).
-
-update_counter(Name, Val) ->
- ?ets_update_counter(mnesia_gvar, Name, Val).
-
-read_counter(Name) ->
- ?ets_lookup_element(mnesia_gvar, Name, 2).
-
-cs_to_nodes(Cs) ->
- Cs#cstruct.disc_only_copies ++
- Cs#cstruct.disc_copies ++
- Cs#cstruct.ram_copies.
-
-dist_coredump() ->
- dist_coredump(all_nodes()).
-dist_coredump(Ns) ->
- {Replies, _} = rpc:multicall(Ns, ?MODULE, coredump, []),
- Replies.
-
-coredump() ->
- coredump({crashinfo, {"user initiated~n", []}}).
-coredump(CrashInfo) ->
- Core = mkcore(CrashInfo),
- Out = core_file(),
- important("Writing Mnesia core to file: ~p...~p~n", [Out, CrashInfo]),
- file:write_file(Out, Core),
- Out.
-
-core_file() ->
- Integers = tuple_to_list(date()) ++ tuple_to_list(time()),
- Fun = fun(I) when I < 10 -> ["_0", I];
- (I) -> ["_", I]
- end,
- List = lists:append([Fun(I) || I <- Integers]),
- filename:absname(lists:concat(["MnesiaCore.", node()] ++ List)).
-
-mkcore(CrashInfo) ->
-% dbg_out("Making a Mnesia core dump...~p~n", [CrashInfo]),
- Nodes = [node() |nodes()],
- TidLocks = (catch ets:tab2list(mnesia_tid_locks)),
- Core = [
- CrashInfo,
- {time, {date(), time()}},
- {self, catch process_info(self())},
- {nodes, catch rpc:multicall(Nodes, ?MODULE, get_node_number, [])},
- {applications, catch lists:sort(application:loaded_applications())},
- {flags, catch init:get_arguments()},
- {code_path, catch code:get_path()},
- {code_loaded, catch lists:sort(code:all_loaded())},
- {etsinfo, catch ets_info(ets:all())},
-
- {version, catch mnesia:system_info(version)},
- {schema, catch ets:tab2list(schema)},
- {gvar, catch ets:tab2list(mnesia_gvar)},
- {master_nodes, catch mnesia_recover:get_master_node_info()},
-
- {processes, catch procs()},
- {relatives, catch relatives()},
- {workers, catch workers(mnesia_controller:get_workers(2000))},
- {locking_procs, catch locking_procs(TidLocks)},
-
- {held_locks, catch mnesia:system_info(held_locks)},
- {tid_locks, TidLocks},
- {lock_queue, catch mnesia:system_info(lock_queue)},
- {load_info, catch mnesia_controller:get_info(2000)},
- {trans_info, catch mnesia_tm:get_info(2000)},
-
- {schema_file, catch file:read_file(tab2dat(schema))},
- {dir_info, catch dir_info()},
- {logfile, catch {ok, read_log_files()}}
- ],
- term_to_binary(Core).
-
-procs() ->
- Fun = fun(P) -> {P, (catch lists:zf(fun proc_info/1, process_info(P)))} end,
- lists:map(Fun, processes()).
-
-proc_info({registered_name, Val}) -> {true, Val};
-proc_info({message_queue_len, Val}) -> {true, Val};
-proc_info({status, Val}) -> {true, Val};
-proc_info({current_function, Val}) -> {true, Val};
-proc_info(_) -> false.
-
-get_node_number() ->
- {node(), self()}.
-
-read_log_files() ->
- [{F, catch file:read_file(F)} || F <- mnesia_log:log_files()].
-
-dir_info() ->
- {ok, Cwd} = file:get_cwd(),
- Dir = dir(),
- [{cwd, Cwd, file:read_file_info(Cwd)},
- {mnesia_dir, Dir, file:read_file_info(Dir)}] ++
- case file:list_dir(Dir) of
- {ok, Files} ->
- [{mnesia_file, F, catch file:read_file_info(dir(F))} || F <- Files];
- Other ->
- [Other]
- end.
-
-ets_info([H|T]) ->
- [{table, H, ets:info(H)} | ets_info(T)];
-ets_info([]) -> [].
-
-relatives() ->
- Info = fun(Name) ->
- case whereis(Name) of
- undefined -> false;
- Pid -> {true, {Name, Pid, catch process_info(Pid)}}
- end
- end,
- lists:zf(Info, mnesia:ms()).
-
-workers({workers, Loader, Sender, Dumper}) ->
- Info = fun({Name, Pid}) ->
- case Pid of
- undefined -> false;
- Pid -> {true, {Name, Pid, catch process_info(Pid)}}
- end
- end,
- lists:zf(Info, [{loader, Loader}, {sender, Sender}, {dumper, Dumper}]).
-
-locking_procs(LockList) when list(LockList) ->
- Tids = [element(1, Lock) || Lock <- LockList],
- UT = uniq(Tids),
- Info = fun(Tid) ->
- Pid = Tid#tid.pid,
- case node(Pid) == node() of
- true ->
- {true, {Pid, catch process_info(Pid)}};
- _ ->
- false
- end
- end,
- lists:zf(Info, UT).
-
-view() ->
- Bin = mkcore({crashinfo, {"view only~n", []}}),
- vcore(Bin).
-
-%% Displays a Mnesia file on the tty. The file may be repaired.
-view(File) ->
- case suffix([".DAT", ".RET", ".DMP", ".TMP"], File) of
- true ->
- view(File, dat);
- false ->
- case suffix([".LOG", ".BUP", ".ETS"], File) of
- true ->
- view(File, log);
- false ->
- case lists:prefix("MnesiaCore.", File) of
- true ->
- view(File, core);
- false ->
- {error, "Unknown file name"}
- end
- end
- end.
-
-view(File, dat) ->
- dets:view(File);
-view(File, log) ->
- mnesia_log:view(File);
-view(File, core) ->
- vcore(File).
-
-suffix(Suffixes, File) ->
- Fun = fun(S) -> lists:suffix(S, File) end,
- lists:any(Fun, Suffixes).
-
-%% View a core file
-
-vcore() ->
- Prefix = lists:concat(["MnesiaCore.", node()]),
- Filter = fun(F) -> lists:prefix(Prefix, F) end,
- {ok, Cwd} = file:get_cwd(),
- case file:list_dir(Cwd) of
- {ok, Files}->
- CoreFiles = lists:sort(lists:zf(Filter, Files)),
- show("Mnesia core files: ~p~n", [CoreFiles]),
- vcore(lists:last(CoreFiles));
- Error ->
- Error
- end.
-
-vcore(Bin) when binary(Bin) ->
- Core = binary_to_term(Bin),
- Fun = fun({Item, Info}) ->
- show("***** ~p *****~n", [Item]),
- case catch vcore_elem({Item, Info}) of
- {'EXIT', Reason} ->
- show("{'EXIT', ~p}~n", [Reason]);
- _ -> ok
- end
- end,
- lists:foreach(Fun, Core);
-
-vcore(File) ->
- show("~n***** Mnesia core: ~p *****~n", [File]),
- case file:read_file(File) of
- {ok, Bin} ->
- vcore(Bin);
- _ ->
- nocore
- end.
-
-vcore_elem({schema_file, {ok, B}}) ->
- Fname = "/tmp/schema.DAT",
- file:write_file(Fname, B),
- dets:view(Fname),
- file:delete(Fname);
-
-vcore_elem({logfile, {ok, BinList}}) ->
- Fun = fun({F, Info}) ->
- show("----- logfile: ~p -----~n", [F]),
- case Info of
- {ok, B} ->
- Fname = "/tmp/mnesia_vcore_elem.TMP",
- file:write_file(Fname, B),
- mnesia_log:view(Fname),
- file:delete(Fname);
- _ ->
- show("~p~n", [Info])
- end
- end,
- lists:foreach(Fun, BinList);
-
-vcore_elem({crashinfo, {Format, Args}}) ->
- show(Format, Args);
-vcore_elem({gvar, L}) ->
- show("~p~n", [lists:sort(L)]);
-vcore_elem({transactions, Info}) ->
- mnesia_tm:display_info(user, Info);
-
-vcore_elem({_Item, Info}) ->
- show("~p~n", [Info]).
-
-fix_error(X) ->
- set(last_error, X), %% for debugabililty
- case X of
- {aborted, Reason} -> Reason;
- {abort, Reason} -> Reason;
- Y when atom(Y) -> Y;
- {'EXIT', {_Reason, {Mod, _, _}}} when atom(Mod) ->
- save(X),
- case atom_to_list(Mod) of
- [$m, $n, $e|_] -> badarg;
- _ -> X
- end;
- _ -> X
- end.
-
-last_error() ->
- val(last_error).
-
-%% The following is a list of possible mnesia errors and what they
-%% actually mean
-
-error_desc(nested_transaction) -> "Nested transactions are not allowed";
-error_desc(badarg) -> "Bad or invalid argument, possibly bad type";
-error_desc(no_transaction) -> "Operation not allowed outside transactions";
-error_desc(combine_error) -> "Table options were ilegally combined";
-error_desc(bad_index) -> "Index already exists or was out of bounds";
-error_desc(already_exists) -> "Some schema option we try to set is already on";
-error_desc(index_exists)-> "Some ops can not be performed on tabs with index";
-error_desc(no_exists)-> "Tried to perform op on non-existing (non alive) item";
-error_desc(system_limit) -> "Some system_limit was exhausted";
-error_desc(mnesia_down) -> "A transaction involving objects at some remote "
- "node which died while transaction was executing"
- "*and* object(s) are no longer available elsewhere"
- "in the network";
-error_desc(not_a_db_node) -> "A node which is non existant in "
- "the schema was mentioned";
-error_desc(bad_type) -> "Bad type on some provided arguments";
-error_desc(node_not_running) -> "Node not running";
-error_desc(truncated_binary_file) -> "Truncated binary in file";
-error_desc(active) -> "Some delete ops require that "
- "all active objects are removed";
-error_desc(illegal) -> "Operation not supported on object";
-error_desc({'EXIT', Reason}) ->
- error_desc(Reason);
-error_desc({error, Reason}) ->
- error_desc(Reason);
-error_desc({aborted, Reason}) ->
- error_desc(Reason);
-error_desc(Reason) when tuple(Reason), size(Reason) > 0 ->
- setelement(1, Reason, error_desc(element(1, Reason)));
-error_desc(Reason) ->
- Reason.
-
-dirty_rpc_error_tag(Reason) ->
- case Reason of
- {'EXIT', _} -> badarg;
- no_variable -> badarg;
- _ -> no_exists
- end.
-
-fatal(Format, Args) ->
- catch set(mnesia_status, stopping),
- Core = mkcore({crashinfo, {Format, Args}}),
- report_fatal(Format, Args, Core),
- timer:sleep(10000), % Enough to write the core dump to disc?
- mnesia:lkill(),
- exit(fatal).
-
-report_fatal(Format, Args) ->
- report_fatal(Format, Args, nocore).
-
-report_fatal(Format, Args, Core) ->
- report_system_event({mnesia_fatal, Format, Args, Core}),
- catch exit(whereis(mnesia_monitor), fatal).
-
-%% We sleep longer and longer the more we try
-%% Made some testing and came up with the following constants
-random_time(Retries, _Counter0) ->
-% UpperLimit = 2000,
-% MaxIntv = trunc(UpperLimit * (1-(4/((Retries*Retries)+4)))),
- UpperLimit = 500,
- Dup = Retries * Retries,
- MaxIntv = trunc(UpperLimit * (1-(50/((Dup)+50)))),
-
- case get(random_seed) of
- undefined ->
- {X, Y, Z} = erlang:now(), %% time()
- random:seed(X, Y, Z),
- Time = Dup + random:uniform(MaxIntv),
- %% dbg_out("---random_test rs ~w max ~w val ~w---~n", [Retries, MaxIntv, Time]),
- Time;
- _ ->
- Time = Dup + random:uniform(MaxIntv),
- %% dbg_out("---random_test rs ~w max ~w val ~w---~n", [Retries, MaxIntv, Time]),
- Time
- end.
-
-report_system_event(Event0) ->
- Event = {mnesia_system_event, Event0},
- report_system_event(catch_notify(Event), Event),
- case ?catch_val(subscribers) of
- {'EXIT', _} -> ignore;
- Pids -> lists:foreach(fun(Pid) -> Pid ! Event end, Pids)
- end,
- ok.
-
-catch_notify(Event) ->
- case whereis(mnesia_event) of
- undefined ->
- {'EXIT', {badarg, {mnesia_event, Event}}};
- Pid ->
- gen_event:notify(Pid, Event)
- end.
-
-report_system_event({'EXIT', Reason}, Event) ->
- Mod = mnesia_monitor:get_env(event_module),
- case mnesia_sup:start_event() of
- {ok, Pid} ->
- link(Pid),
- gen_event:call(mnesia_event, Mod, Event, infinity),
- unlink(Pid),
-
- %% We get an exit signal if server dies
- receive
- {'EXIT', Pid, _Reason} ->
- {error, {node_not_running, node()}}
- after 0 ->
- gen_event:stop(mnesia_event),
- ok
- end;
-
- Error ->
- Msg = "Mnesia(~p): Cannot report event ~p: ~p (~p)~n",
- error_logger:format(Msg, [node(), Event, Reason, Error])
- end;
-report_system_event(_Res, _Event) ->
- ignore.
-
-%% important messages are reported regardless of debug level
-important(Format, Args) ->
- save({Format, Args}),
- report_system_event({mnesia_info, Format, Args}).
-
-%% Warning messages are reported regardless of debug level
-warning(Format, Args) ->
- save({Format, Args}),
- report_system_event({mnesia_warning, Format, Args}).
-
-%% error messages are reported regardless of debug level
-error(Format, Args) ->
- save({Format, Args}),
- report_system_event({mnesia_error, Format, Args}).
-
-%% verbose messages are reported if debug level == debug or verbose
-verbose(Format, Args) ->
- case mnesia_monitor:get_env(debug) of
- none -> save({Format, Args});
- verbose -> important(Format, Args);
- debug -> important(Format, Args);
- trace -> important(Format, Args)
- end.
-
-%% debug message are display if debug level == 2
-dbg_out(Format, Args) ->
- case mnesia_monitor:get_env(debug) of
- none -> ignore;
- verbose -> save({Format, Args});
- _ -> report_system_event({mnesia_info, Format, Args})
- end.
-
-%% Keep the last 10 debug print outs
-save(DbgInfo) ->
- catch save2(DbgInfo).
-
-save2(DbgInfo) ->
- Key = {'$$$_report', current_pos},
- P =
- case ?ets_lookup_element(mnesia_gvar, Key, 2) of
- 30 -> -1;
- I -> I
- end,
- set({'$$$_report', current_pos}, P+1),
- set({'$$$_report', P+1}, {date(), time(), DbgInfo}).
-
-copy_file(From, To) ->
- case file:open(From, [raw, binary, read]) of
- {ok, F} ->
- case file:open(To, [raw, binary, write]) of
- {ok, T} ->
- Res = copy_file_loop(F, T, 8000),
- file:close(F),
- file:close(T),
- Res;
- {error, Reason} ->
- {error, Reason}
- end;
- {error, Reason} ->
- {error, Reason}
- end.
-
-copy_file_loop(F, T, ChunkSize) ->
- case file:read(F, ChunkSize) of
- {ok, {0, _}} ->
- ok;
- {ok, {_, Bin}} ->
- file:write(T, Bin),
- copy_file_loop(F, T, ChunkSize);
- {ok, Bin} ->
- file:write(T, Bin),
- copy_file_loop(F, T, ChunkSize);
- eof ->
- ok;
- {error, Reason} ->
- {error, Reason}
- end.
-
-
-%%%%%%%%%%%%
-%% versions of all the lowlevel db funcs that determine whether we
-%% shall go to disc or ram to do the actual operation.
-
-db_get(Tab, Key) ->
- db_get(val({Tab, storage_type}), Tab, Key).
-db_get(ram_copies, Tab, Key) -> ?ets_lookup(Tab, Key);
-db_get(disc_copies, Tab, Key) -> ?ets_lookup(Tab, Key);
-db_get(disc_only_copies, Tab, Key) -> dets:lookup(Tab, Key).
-
-db_init_chunk(Tab) ->
- db_init_chunk(val({Tab, storage_type}), Tab, 1000).
-db_init_chunk(Tab, N) ->
- db_init_chunk(val({Tab, storage_type}), Tab, N).
-
-db_init_chunk(disc_only_copies, Tab, N) ->
- dets:select(Tab, [{'_', [], ['$_']}], N);
-db_init_chunk(_, Tab, N) ->
- ets:select(Tab, [{'_', [], ['$_']}], N).
-
-db_chunk(disc_only_copies, State) ->
- dets:select(State);
-db_chunk(_, State) ->
- ets:select(State).
-
-db_put(Tab, Val) ->
- db_put(val({Tab, storage_type}), Tab, Val).
-
-db_put(ram_copies, Tab, Val) -> ?ets_insert(Tab, Val), ok;
-db_put(disc_copies, Tab, Val) -> ?ets_insert(Tab, Val), ok;
-db_put(disc_only_copies, Tab, Val) -> dets:insert(Tab, Val).
-
-db_match_object(Tab, Pat) ->
- db_match_object(val({Tab, storage_type}), Tab, Pat).
-db_match_object(Storage, Tab, Pat) ->
- db_fixtable(Storage, Tab, true),
- Res = catch_match_object(Storage, Tab, Pat),
- db_fixtable(Storage, Tab, false),
- case Res of
- {'EXIT', Reason} -> exit(Reason);
- _ -> Res
- end.
-
-catch_match_object(disc_only_copies, Tab, Pat) ->
- catch dets:match_object(Tab, Pat);
-catch_match_object(_, Tab, Pat) ->
- catch ets:match_object(Tab, Pat).
-
-db_select(Tab, Pat) ->
- db_select(val({Tab, storage_type}), Tab, Pat).
-
-db_select(Storage, Tab, Pat) ->
- db_fixtable(Storage, Tab, true),
- Res = catch_select(Storage, Tab, Pat),
- db_fixtable(Storage, Tab, false),
- case Res of
- {'EXIT', Reason} -> exit(Reason);
- _ -> Res
- end.
-
-catch_select(disc_only_copies, Tab, Pat) ->
- dets:select(Tab, Pat);
-catch_select(_, Tab, Pat) ->
- ets:select(Tab, Pat).
-
-db_fixtable(ets, Tab, Bool) ->
- ets:safe_fixtable(Tab, Bool);
-db_fixtable(ram_copies, Tab, Bool) ->
- ets:safe_fixtable(Tab, Bool);
-db_fixtable(disc_copies, Tab, Bool) ->
- ets:safe_fixtable(Tab, Bool);
-db_fixtable(dets, Tab, Bool) ->
- dets:safe_fixtable(Tab, Bool);
-db_fixtable(disc_only_copies, Tab, Bool) ->
- dets:safe_fixtable(Tab, Bool).
-
-db_erase(Tab, Key) ->
- db_erase(val({Tab, storage_type}), Tab, Key).
-db_erase(ram_copies, Tab, Key) -> ?ets_delete(Tab, Key), ok;
-db_erase(disc_copies, Tab, Key) -> ?ets_delete(Tab, Key), ok;
-db_erase(disc_only_copies, Tab, Key) -> dets:delete(Tab, Key).
-
-db_match_erase(Tab, Pat) ->
- db_match_erase(val({Tab, storage_type}), Tab, Pat).
-db_match_erase(ram_copies, Tab, Pat) -> ?ets_match_delete(Tab, Pat), ok;
-db_match_erase(disc_copies, Tab, Pat) -> ?ets_match_delete(Tab, Pat), ok;
-db_match_erase(disc_only_copies, Tab, Pat) -> dets:match_delete(Tab, Pat).
-
-db_first(Tab) ->
- db_first(val({Tab, storage_type}), Tab).
-db_first(ram_copies, Tab) -> ?ets_first(Tab);
-db_first(disc_copies, Tab) -> ?ets_first(Tab);
-db_first(disc_only_copies, Tab) -> dets:first(Tab).
-
-db_next_key(Tab, Key) ->
- db_next_key(val({Tab, storage_type}), Tab, Key).
-db_next_key(ram_copies, Tab, Key) -> ?ets_next(Tab, Key);
-db_next_key(disc_copies, Tab, Key) -> ?ets_next(Tab, Key);
-db_next_key(disc_only_copies, Tab, Key) -> dets:next(Tab, Key).
-
-db_last(Tab) ->
- db_last(val({Tab, storage_type}), Tab).
-db_last(ram_copies, Tab) -> ?ets_last(Tab);
-db_last(disc_copies, Tab) -> ?ets_last(Tab);
-db_last(disc_only_copies, Tab) -> dets:first(Tab). %% Dets don't have order
-
-db_prev_key(Tab, Key) ->
- db_prev_key(val({Tab, storage_type}), Tab, Key).
-db_prev_key(ram_copies, Tab, Key) -> ?ets_prev(Tab, Key);
-db_prev_key(disc_copies, Tab, Key) -> ?ets_prev(Tab, Key);
-db_prev_key(disc_only_copies, Tab, Key) -> dets:next(Tab, Key). %% Dets don't have order
-
-db_slot(Tab, Pos) ->
- db_slot(val({Tab, storage_type}), Tab, Pos).
-db_slot(ram_copies, Tab, Pos) -> ?ets_slot(Tab, Pos);
-db_slot(disc_copies, Tab, Pos) -> ?ets_slot(Tab, Pos);
-db_slot(disc_only_copies, Tab, Pos) -> dets:slot(Tab, Pos).
-
-db_update_counter(Tab, C, Val) ->
- db_update_counter(val({Tab, storage_type}), Tab, C, Val).
-db_update_counter(ram_copies, Tab, C, Val) ->
- ?ets_update_counter(Tab, C, Val);
-db_update_counter(disc_copies, Tab, C, Val) ->
- ?ets_update_counter(Tab, C, Val);
-db_update_counter(disc_only_copies, Tab, C, Val) ->
- dets:update_counter(Tab, C, Val).
-
-db_erase_tab(Tab) ->
- db_erase_tab(val({Tab, storage_type}), Tab).
-db_erase_tab(ram_copies, Tab) -> ?ets_delete_table(Tab);
-db_erase_tab(disc_copies, Tab) -> ?ets_delete_table(Tab);
-db_erase_tab(disc_only_copies, _Tab) -> ignore.
-
-%% assuming that Tab is a valid ets-table
-dets_to_ets(Tabname, Tab, File, Type, Rep, Lock) ->
- {Open, Close} = mkfuns(Lock),
- case Open(Tabname, [{file, File}, {type, disk_type(Tab, Type)},
- {keypos, 2}, {repair, Rep}]) of
- {ok, Tabname} ->
- Res = dets:to_ets(Tabname, Tab),
- Close(Tabname),
- trav_ret(Res, Tab);
- Other ->
- Other
- end.
-
-trav_ret(Tabname, Tabname) -> loaded;
-trav_ret(Other, _Tabname) -> Other.
-
-mkfuns(yes) ->
- {fun(Tab, Args) -> dets_sync_open(Tab, Args) end,
- fun(Tab) -> dets_sync_close(Tab) end};
-mkfuns(no) ->
- {fun(Tab, Args) -> dets:open_file(Tab, Args) end,
- fun(Tab) -> dets:close(Tab) end}.
-
-disk_type(Tab) ->
- disk_type(Tab, val({Tab, setorbag})).
-
-disk_type(_Tab, ordered_set) ->
- set;
-disk_type(_, Type) ->
- Type.
-
-dets_sync_open(Tab, Ref, File) ->
- Args = [{file, File},
- {keypos, 2},
- {repair, mnesia_monitor:get_env(auto_repair)},
- {type, disk_type(Tab)}],
- dets_sync_open(Ref, Args).
-
-lock_table(Tab) ->
- global:set_lock({{mnesia_table_lock, Tab}, self()}, [node()], infinity).
-% dbg_out("dets_sync_open: ~p ~p~n", [T, self()]),
-
-unlock_table(Tab) ->
- global:del_lock({{mnesia_table_lock, Tab}, self()}, [node()]).
-% dbg_out("unlock_table: ~p ~p~n", [T, self()]),
-
-dets_sync_open(Tab, Args) ->
- lock_table(Tab),
- case dets:open_file(Tab, Args) of
- {ok, Tab} ->
- {ok, Tab};
- Other ->
- dets_sync_close(Tab),
- Other
- end.
-
-dets_sync_close(Tab) ->
- catch dets:close(Tab),
- unlock_table(Tab),
- ok.
-
-cleanup_tmp_files([Tab | Tabs]) ->
- dets_sync_close(Tab),
- file:delete(tab2tmp(Tab)),
- cleanup_tmp_files(Tabs);
-cleanup_tmp_files([]) ->
- ok.
-
-%% Returns a list of bad tables
-swap_tmp_files([Tab | Tabs]) ->
- dets_sync_close(Tab),
- Tmp = tab2tmp(Tab),
- Dat = tab2dat(Tab),
- case file:rename(Tmp, Dat) of
- ok ->
- swap_tmp_files(Tabs);
- _ ->
- file:delete(Tmp),
- [Tab | swap_tmp_files(Tabs)]
- end;
-swap_tmp_files([]) ->
- [].
-
-readable_indecies(Tab) ->
- val({Tab, index}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Managing conditional debug functions
-%%
-%% The main idea with the debug_fun's is to allow test programs
-%% to control the internal behaviour of Mnesia. This is needed
-%% to make the test programs independent of system load, swapping
-%% and other circumstances that may affect the behaviour of Mnesia.
-%%
-%% First should calls to ?eval_debug_fun be inserted at well
-%% defined places in Mnesia's code. E.g. in critical situations
-%% of startup, transaction commit, backups etc.
-%%
-%% Then compile Mnesia with the compiler option 'debug'.
-%%
-%% In test programs ?activate_debug_fun should be called
-%% in order to bind a fun to the debug identifier stated
-%% in the call to ?eval_debug_fun.
-%%
-%% If eval_debug_fun finds that the fun is activated it
-%% invokes the fun as NewContext = Fun(PreviousContext, EvalContext)
-%% and replaces the PreviousContext with the NewContext.
-%% The initial context of a debug_fun is given as argument to
-%% activate_debug_fun.
-
--define(DEBUG_TAB, mnesia_debug).
--record(debug_info, {id, function, context, file, line}).
-
-scratch_debug_fun() ->
- dbg_out("scratch_debug_fun(): ~p~n", [?DEBUG_TAB]),
- (catch ?ets_delete_table(?DEBUG_TAB)),
- ?ets_new_table(?DEBUG_TAB, [set, public, named_table, {keypos, 2}]).
-
-activate_debug_fun(FunId, Fun, InitialContext, File, Line) ->
- Info = #debug_info{id = FunId,
- function = Fun,
- context = InitialContext,
- file = File,
- line = Line
- },
- update_debug_info(Info).
-
-update_debug_info(Info) ->
- case catch ?ets_insert(?DEBUG_TAB, Info) of
- {'EXIT', _} ->
- scratch_debug_fun(),
- ?ets_insert(?DEBUG_TAB, Info);
- _ ->
- ok
- end,
- dbg_out("update_debug_info(~p)~n", [Info]),
- ok.
-
-deactivate_debug_fun(FunId, _File, _Line) ->
- catch ?ets_delete(?DEBUG_TAB, FunId),
- ok.
-
-eval_debug_fun(FunId, EvalContext, EvalFile, EvalLine) ->
- case catch ?ets_lookup(?DEBUG_TAB, FunId) of
- [] ->
- ok;
- [Info] ->
- OldContext = Info#debug_info.context,
- dbg_out("~s(~p): ~w "
- "activated in ~s(~p)~n "
- "eval_debug_fun(~w, ~w)~n",
- [filename:basename(EvalFile), EvalLine, Info#debug_info.id,
- filename:basename(Info#debug_info.file), Info#debug_info.line,
- OldContext, EvalContext]),
- Fun = Info#debug_info.function,
- NewContext = Fun(OldContext, EvalContext),
-
- case catch ?ets_lookup(?DEBUG_TAB, FunId) of
- [Info] when NewContext /= OldContext ->
- NewInfo = Info#debug_info{context = NewContext},
- update_debug_info(NewInfo);
- _ ->
- ok
- end;
- {'EXIT', _} -> ok
- end.
-
--ifdef(debug).
- is_debug_compiled() -> true.
--else.
- is_debug_compiled() -> false.
--endif.
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_loader.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_loader.erl
deleted file mode 100644
index df3309cfa6..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_loader.erl
+++ /dev/null
@@ -1,805 +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: mnesia_loader.erl,v 1.2 2010/03/04 13:54:19 maria Exp $
-%%
-%%% Purpose : Loads tables from local disc or from remote node
-
--module(mnesia_loader).
-
-%% Mnesia internal stuff
--export([disc_load_table/2,
- net_load_table/4,
- send_table/3]).
-
--export([old_node_init_table/6]). %% Spawned old node protocol conversion hack
--export([spawned_receiver/8]). %% Spawned lock taking process
-
--import(mnesia_lib, [set/2, fatal/2, verbose/2, dbg_out/2]).
-
--include("mnesia.hrl").
-
-val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
- Value -> Value
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Load a table from local disc
-
-disc_load_table(Tab, Reason) ->
- Storage = val({Tab, storage_type}),
- Type = val({Tab, setorbag}),
- dbg_out("Getting table ~p (~p) from disc: ~p~n",
- [Tab, Storage, Reason]),
- ?eval_debug_fun({?MODULE, do_get_disc_copy},
- [{tab, Tab},
- {reason, Reason},
- {storage, Storage},
- {type, Type}]),
- do_get_disc_copy2(Tab, Reason, Storage, Type).
-
-do_get_disc_copy2(Tab, _Reason, Storage, _Type) when Storage == unknown ->
- verbose("Local table copy of ~p has recently been deleted, ignored.~n",
- [Tab]),
- {loaded, ok}; %% ?
-do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_copies ->
- %% NOW we create the actual table
- Repair = mnesia_monitor:get_env(auto_repair),
- Args = [{keypos, 2}, public, named_table, Type],
- case Reason of
- {dumper, _} -> %% Resources allready allocated
- ignore;
- _ ->
- mnesia_monitor:mktab(Tab, Args),
- Count = mnesia_log:dcd2ets(Tab, Repair),
- case ets:info(Tab, size) of
- X when X < Count * 4 ->
- ok = mnesia_log:ets2dcd(Tab);
- _ ->
- ignore
- end
- end,
- mnesia_index:init_index(Tab, Storage),
- snmpify(Tab, Storage),
- set({Tab, load_node}, node()),
- set({Tab, load_reason}, Reason),
- {loaded, ok};
-
-do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == ram_copies ->
- Args = [{keypos, 2}, public, named_table, Type],
- case Reason of
- {dumper, _} -> %% Resources allready allocated
- ignore;
- _ ->
- mnesia_monitor:mktab(Tab, Args),
- Fname = mnesia_lib:tab2dcd(Tab),
- Datname = mnesia_lib:tab2dat(Tab),
- Repair = mnesia_monitor:get_env(auto_repair),
- case mnesia_monitor:use_dir() of
- true ->
- case mnesia_lib:exists(Fname) of
- true -> mnesia_log:dcd2ets(Tab, Repair);
- false ->
- case mnesia_lib:exists(Datname) of
- true ->
- mnesia_lib:dets_to_ets(Tab, Tab, Datname,
- Type, Repair, no);
- false ->
- false
- end
- end;
- false ->
- false
- end
- end,
- mnesia_index:init_index(Tab, Storage),
- snmpify(Tab, Storage),
- set({Tab, load_node}, node()),
- set({Tab, load_reason}, Reason),
- {loaded, ok};
-
-do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_only_copies ->
- Args = [{file, mnesia_lib:tab2dat(Tab)},
- {type, mnesia_lib:disk_type(Tab, Type)},
- {keypos, 2},
- {repair, mnesia_monitor:get_env(auto_repair)}],
- case Reason of
- {dumper, _} ->
- mnesia_index:init_index(Tab, Storage),
- snmpify(Tab, Storage),
- set({Tab, load_node}, node()),
- set({Tab, load_reason}, Reason),
- {loaded, ok};
- _ ->
- case mnesia_monitor:open_dets(Tab, Args) of
- {ok, _} ->
- mnesia_index:init_index(Tab, Storage),
- snmpify(Tab, Storage),
- set({Tab, load_node}, node()),
- set({Tab, load_reason}, Reason),
- {loaded, ok};
- {error, Error} ->
- {not_loaded, {"Failed to create dets table", Error}}
- end
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Load a table from a remote node
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Receiver Sender
-%% -------- ------
-%% Grab schema lock on table
-%% Determine table size
-%% Create empty pre-grown table
-%% Grab read lock on table
-%% Let receiver subscribe on updates done on sender node
-%% Disable rehashing of table
-%% Release read lock on table
-%% Send table to receiver in chunks
-%%
-%% Grab read lock on table
-%% Block dirty updates
-%% Update wherabouts
-%%
-%% Cancel the update subscription
-%% Process the subscription events
-%% Optionally dump to disc
-%% Unblock dirty updates
-%% Release read lock on table
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
--define(MAX_TRANSFER_SIZE, 7500).
--define(MAX_RAM_FILE_SIZE, 1000000).
--define(MAX_RAM_TRANSFERS, (?MAX_RAM_FILE_SIZE div ?MAX_TRANSFER_SIZE) + 1).
--define(MAX_NOPACKETS, 20).
-
-net_load_table(Tab, Reason, Ns, Cs)
- when Reason == {dumper,add_table_copy} ->
- try_net_load_table(Tab, Reason, Ns, Cs);
-net_load_table(Tab, Reason, Ns, _Cs) ->
- try_net_load_table(Tab, Reason, Ns, val({Tab, cstruct})).
-
-try_net_load_table(Tab, _Reason, [], _Cs) ->
- verbose("Copy failed. No active replicas of ~p are available.~n", [Tab]),
- {not_loaded, none_active};
-try_net_load_table(Tab, Reason, Ns, Cs) ->
- Storage = mnesia_lib:cs_to_storage_type(node(), Cs),
- do_get_network_copy(Tab, Reason, Ns, Storage, Cs).
-
-do_get_network_copy(Tab, _Reason, _Ns, unknown, _Cs) ->
- verbose("Local table copy of ~p has recently been deleted, ignored.~n", [Tab]),
- {not_loaded, storage_unknown};
-do_get_network_copy(Tab, Reason, Ns, Storage, Cs) ->
- [Node | Tail] = Ns,
- dbg_out("Getting table ~p (~p) from node ~p: ~p~n",
- [Tab, Storage, Node, Reason]),
- ?eval_debug_fun({?MODULE, do_get_network_copy},
- [{tab, Tab}, {reason, Reason},
- {nodes, Ns}, {storage, Storage}]),
- mnesia_controller:start_remote_sender(Node, Tab, self(), Storage),
- put(mnesia_table_sender_node, {Tab, Node}),
- case init_receiver(Node, Tab, Storage, Cs, Reason) of
- ok ->
- set({Tab, load_node}, Node),
- set({Tab, load_reason}, Reason),
- mnesia_controller:i_have_tab(Tab),
- dbg_out("Table ~p copied from ~p to ~p~n", [Tab, Node, node()]),
- {loaded, ok};
- Err = {error, _} when element(1, Reason) == dumper ->
- {not_loaded,Err};
- restart ->
- try_net_load_table(Tab, Reason, Tail, Cs);
- down ->
- try_net_load_table(Tab, Reason, Tail, Cs)
- end.
-
-snmpify(Tab, Storage) ->
- do_snmpify(Tab, val({Tab, snmp}), Storage).
-
-do_snmpify(_Tab, [], _Storage) ->
- ignore;
-do_snmpify(Tab, Us, Storage) ->
- Snmp = mnesia_snmp_hook:create_table(Us, Tab, Storage),
- set({Tab, {index, snmp}}, Snmp).
-
-%% Start the recieiver
-%% Sender should be started first, so we don't have the schema-read
-%% lock to long (or get stuck in a deadlock)
-init_receiver(Node, Tab, Storage, Cs, Reason) ->
- receive
- {SenderPid, {first, TabSize}} ->
- spawn_receiver(Tab,Storage,Cs,SenderPid,
- TabSize,false,Reason);
- {SenderPid, {first, TabSize, DetsData}} ->
- spawn_receiver(Tab,Storage,Cs,SenderPid,
- TabSize,DetsData,Reason);
- %% Protocol conversion hack
- {copier_done, Node} ->
- dbg_out("Sender of table ~p crashed on node ~p ~n", [Tab, Node]),
- down(Tab, Storage)
- end.
-
-
-table_init_fun(SenderPid) ->
- PConv = mnesia_monitor:needs_protocol_conversion(node(SenderPid)),
- MeMyselfAndI = self(),
- fun(read) ->
- Receiver =
- if
- PConv == true ->
- MeMyselfAndI ! {actual_tabrec, self()},
- MeMyselfAndI; %% Old mnesia
- PConv == false -> self()
- end,
- SenderPid ! {Receiver, more},
- get_data(SenderPid, Receiver)
- end.
-
-
-%% Add_table_copy get's it's own locks.
-spawn_receiver(Tab,Storage,Cs,SenderPid,TabSize,DetsData,{dumper,add_table_copy}) ->
- Init = table_init_fun(SenderPid),
- case do_init_table(Tab,Storage,Cs,SenderPid,TabSize,DetsData,self(), Init) of
- Err = {error, _} ->
- SenderPid ! {copier_done, node()},
- Err;
- Else ->
- Else
- end;
-
-spawn_receiver(Tab,Storage,Cs,SenderPid,
- TabSize,DetsData,Reason) ->
- %% Grab a schema lock to avoid deadlock between table_loader and schema_commit dumping.
- %% Both may grab tables-locks in different order.
- Load = fun() ->
- {_,Tid,Ts} = get(mnesia_activity_state),
- mnesia_locker:rlock(Tid, Ts#tidstore.store,
- {schema, Tab}),
- Init = table_init_fun(SenderPid),
- Pid = spawn_link(?MODULE, spawned_receiver,
- [self(),Tab,Storage,Cs,
- SenderPid,TabSize,DetsData,
- Init]),
- put(mnesia_real_loader, Pid),
- wait_on_load_complete(Pid)
- end,
- Res = case mnesia:transaction(Load, 20) of
- {'atomic', {error,Result}} when element(1,Reason) == dumper ->
- SenderPid ! {copier_done, node()},
- {error,Result};
- {'atomic', {error,Result}} ->
- SenderPid ! {copier_done, node()},
- fatal("Cannot create table ~p: ~p~n",
- [[Tab, Storage], Result]);
- {'atomic', Result} -> Result;
- {aborted, nomore} ->
- SenderPid ! {copier_done, node()},
- restart;
- {aborted, _ } ->
- SenderPid ! {copier_done, node()},
- down %% either this node or sender is dying
- end,
- unlink(whereis(mnesia_tm)), %% Avoid late unlink from tm
- Res.
-
-spawned_receiver(ReplyTo,Tab,Storage,Cs,
- SenderPid,TabSize,DetsData, Init) ->
- process_flag(trap_exit, true),
- Done = do_init_table(Tab,Storage,Cs,
- SenderPid,TabSize,DetsData,
- ReplyTo, Init),
- ReplyTo ! {self(),Done},
- unlink(ReplyTo),
- unlink(whereis(mnesia_controller)),
- exit(normal).
-
-wait_on_load_complete(Pid) ->
- receive
- {Pid, Res} ->
- Res;
- {'EXIT', Pid, Reason} ->
- exit(Reason);
- Else ->
- Pid ! Else,
- wait_on_load_complete(Pid)
- end.
-
-tab_receiver(Node, Tab, Storage, Cs, PConv, OrigTabRec) ->
- receive
- {SenderPid, {no_more, DatBin}} when PConv == false ->
- finish_copy(Storage,Tab,Cs,SenderPid,DatBin,OrigTabRec);
-
- %% Protocol conversion hack
- {SenderPid, {no_more, DatBin}} when pid(PConv) ->
- PConv ! {SenderPid, no_more},
- receive
- {old_init_table_complete, ok} ->
- finish_copy(Storage, Tab, Cs, SenderPid, DatBin,OrigTabRec);
- {old_init_table_complete, Reason} ->
- Msg = "OLD: [d]ets:init table failed",
- dbg_out("~s: ~p: ~p~n", [Msg, Tab, Reason]),
- down(Tab, Storage)
- end;
-
- {actual_tabrec, Pid} ->
- tab_receiver(Node, Tab, Storage, Cs, Pid,OrigTabRec);
-
- {SenderPid, {more, [Recs]}} when pid(PConv) ->
- PConv ! {SenderPid, {more, Recs}}, %% Forward Msg to OldNodes
- tab_receiver(Node, Tab, Storage, Cs, PConv,OrigTabRec);
-
- {'EXIT', PConv, Reason} -> %% [d]ets:init process crashed
- Msg = "Receiver crashed",
- dbg_out("~s: ~p: ~p~n", [Msg, Tab, Reason]),
- down(Tab, Storage);
-
- %% Protocol conversion hack
- {copier_done, Node} ->
- dbg_out("Sender of table ~p crashed on node ~p ~n", [Tab, Node]),
- down(Tab, Storage);
-
- {'EXIT', Pid, Reason} ->
- handle_exit(Pid, Reason),
- tab_receiver(Node, Tab, Storage, Cs, PConv,OrigTabRec)
- end.
-
-create_table(Tab, TabSize, Storage, Cs) ->
- if
- Storage == disc_only_copies ->
- mnesia_lib:lock_table(Tab),
- Tmp = mnesia_lib:tab2tmp(Tab),
- Size = lists:max([TabSize, 256]),
- Args = [{file, Tmp},
- {keypos, 2},
-%% {ram_file, true},
- {estimated_no_objects, Size},
- {repair, mnesia_monitor:get_env(auto_repair)},
- {type, mnesia_lib:disk_type(Tab, Cs#cstruct.type)}],
- file:delete(Tmp),
- case mnesia_lib:dets_sync_open(Tab, Args) of
- {ok, _} ->
- mnesia_lib:unlock_table(Tab),
- {Storage, Tab};
- Else ->
- mnesia_lib:unlock_table(Tab),
- Else
- end;
- (Storage == ram_copies) or (Storage == disc_copies) ->
- Args = [{keypos, 2}, public, named_table, Cs#cstruct.type],
- case mnesia_monitor:unsafe_mktab(Tab, Args) of
- Tab ->
- {Storage, Tab};
- Else ->
- Else
- end
- end.
-
-do_init_table(Tab,Storage,Cs,SenderPid,
- TabSize,DetsInfo,OrigTabRec,Init) ->
- case create_table(Tab, TabSize, Storage, Cs) of
- {Storage,Tab} ->
- %% Debug info
- Node = node(SenderPid),
- put(mnesia_table_receiver, {Tab, Node, SenderPid}),
- mnesia_tm:block_tab(Tab),
- PConv = mnesia_monitor:needs_protocol_conversion(Node),
-
- case init_table(Tab,Storage,Init,PConv,DetsInfo,SenderPid) of
- ok ->
- tab_receiver(Node,Tab,Storage,Cs,PConv,OrigTabRec);
- Reason ->
- Msg = "[d]ets:init table failed",
- dbg_out("~s: ~p: ~p~n", [Msg, Tab, Reason]),
- down(Tab, Storage)
- end;
- Error ->
- Error
- end.
-
-make_table_fun(Pid, TabRec) ->
- fun(close) ->
- ok;
- (read) ->
- get_data(Pid, TabRec)
- end.
-
-get_data(Pid, TabRec) ->
- receive
- {Pid, {more, Recs}} ->
- Pid ! {TabRec, more},
- {Recs, make_table_fun(Pid,TabRec)};
- {Pid, no_more} ->
- end_of_input;
- {copier_done, Node} ->
- case node(Pid) of
- Node ->
- {copier_done, Node};
- _ ->
- get_data(Pid, TabRec)
- end;
- {'EXIT', Pid, Reason} ->
- handle_exit(Pid, Reason),
- get_data(Pid, TabRec)
- end.
-
-init_table(Tab, disc_only_copies, Fun, false, DetsInfo,Sender) ->
- ErtsVer = erlang:system_info(version),
- case DetsInfo of
- {ErtsVer, DetsData} ->
- Res = (catch dets:is_compatible_bchunk_format(Tab, DetsData)),
- case Res of
- {'EXIT',{undef,[{dets,_,_}|_]}} ->
- Sender ! {self(), {old_protocol, Tab}},
- dets:init_table(Tab, Fun); %% Old dets version
- {'EXIT', What} ->
- exit(What);
- false ->
- Sender ! {self(), {old_protocol, Tab}},
- dets:init_table(Tab, Fun); %% Old dets version
- true ->
- dets:init_table(Tab, Fun, [{format, bchunk}])
- end;
- Old when Old /= false ->
- Sender ! {self(), {old_protocol, Tab}},
- dets:init_table(Tab, Fun); %% Old dets version
- _ ->
- dets:init_table(Tab, Fun)
- end;
-init_table(Tab, _, Fun, false, _DetsInfo,_) ->
- case catch ets:init_table(Tab, Fun) of
- true ->
- ok;
- {'EXIT', Else} -> Else
- end;
-init_table(Tab, Storage, Fun, true, _DetsInfo, Sender) -> %% Old Nodes
- spawn_link(?MODULE, old_node_init_table,
- [Tab, Storage, Fun, self(), false, Sender]),
- ok.
-
-old_node_init_table(Tab, Storage, Fun, TabReceiver, DetsInfo,Sender) ->
- Res = init_table(Tab, Storage, Fun, false, DetsInfo,Sender),
- TabReceiver ! {old_init_table_complete, Res},
- unlink(TabReceiver),
- ok.
-
-finish_copy(Storage,Tab,Cs,SenderPid,DatBin,OrigTabRec) ->
- TabRef = {Storage, Tab},
- subscr_receiver(TabRef, Cs#cstruct.record_name),
- case handle_last(TabRef, Cs#cstruct.type, DatBin) of
- ok ->
- mnesia_index:init_index(Tab, Storage),
- snmpify(Tab, Storage),
- %% OrigTabRec must not be the spawned tab-receiver
- %% due to old protocol.
- SenderPid ! {OrigTabRec, no_more},
- mnesia_tm:unblock_tab(Tab),
- ok;
- {error, Reason} ->
- Msg = "Failed to handle last",
- dbg_out("~s: ~p: ~p~n", [Msg, Tab, Reason]),
- down(Tab, Storage)
- end.
-
-subscr_receiver(TabRef = {_, Tab}, RecName) ->
- receive
- {mnesia_table_event, {Op, Val, _Tid}} ->
- if
- Tab == RecName ->
- handle_event(TabRef, Op, Val);
- true ->
- handle_event(TabRef, Op, setelement(1, Val, RecName))
- end,
- subscr_receiver(TabRef, RecName);
-
- {'EXIT', Pid, Reason} ->
- handle_exit(Pid, Reason),
- subscr_receiver(TabRef, RecName)
- after 0 ->
- ok
- end.
-
-handle_event(TabRef, write, Rec) ->
- db_put(TabRef, Rec);
-handle_event(TabRef, delete, {_Tab, Key}) ->
- db_erase(TabRef, Key);
-handle_event(TabRef, delete_object, OldRec) ->
- db_match_erase(TabRef, OldRec);
-handle_event(TabRef, clear_table, {_Tab, _Key}) ->
- db_match_erase(TabRef, '_').
-
-handle_last({disc_copies, Tab}, _Type, nobin) ->
- Ret = mnesia_log:ets2dcd(Tab),
- Fname = mnesia_lib:tab2dat(Tab),
- case mnesia_lib:exists(Fname) of
- true -> %% Remove old .DAT files.
- file:delete(Fname);
- false ->
- ok
- end,
- Ret;
-
-handle_last({disc_only_copies, Tab}, Type, nobin) ->
- case mnesia_lib:swap_tmp_files([Tab]) of
- [] ->
- Args = [{file, mnesia_lib:tab2dat(Tab)},
- {type, mnesia_lib:disk_type(Tab, Type)},
- {keypos, 2},
- {repair, mnesia_monitor:get_env(auto_repair)}],
- mnesia_monitor:open_dets(Tab, Args),
- ok;
- L when list(L) ->
- {error, {"Cannot swap tmp files", Tab, L}}
- end;
-
-handle_last({ram_copies, _Tab}, _Type, nobin) ->
- ok;
-handle_last({ram_copies, Tab}, _Type, DatBin) ->
- case mnesia_monitor:use_dir() of
- true ->
- mnesia_lib:lock_table(Tab),
- Tmp = mnesia_lib:tab2tmp(Tab),
- ok = file:write_file(Tmp, DatBin),
- ok = file:rename(Tmp, mnesia_lib:tab2dcd(Tab)),
- mnesia_lib:unlock_table(Tab),
- ok;
- false ->
- ok
- end.
-
-down(Tab, Storage) ->
- case Storage of
- ram_copies ->
- catch ?ets_delete_table(Tab);
- disc_copies ->
- catch ?ets_delete_table(Tab);
- disc_only_copies ->
- mnesia_lib:cleanup_tmp_files([Tab])
- end,
- mnesia_checkpoint:tm_del_copy(Tab, node()),
- mnesia_controller:sync_del_table_copy_whereabouts(Tab, node()),
- mnesia_tm:unblock_tab(Tab),
- flush_subcrs(),
- down.
-
-flush_subcrs() ->
- receive
- {mnesia_table_event, _} ->
- flush_subcrs();
-
- {'EXIT', Pid, Reason} ->
- handle_exit(Pid, Reason),
- flush_subcrs()
- after 0 ->
- done
- end.
-
-db_erase({ram_copies, Tab}, Key) ->
- true = ?ets_delete(Tab, Key);
-db_erase({disc_copies, Tab}, Key) ->
- true = ?ets_delete(Tab, Key);
-db_erase({disc_only_copies, Tab}, Key) ->
- ok = dets:delete(Tab, Key).
-
-db_match_erase({ram_copies, Tab} , Pat) ->
- true = ?ets_match_delete(Tab, Pat);
-db_match_erase({disc_copies, Tab} , Pat) ->
- true = ?ets_match_delete(Tab, Pat);
-db_match_erase({disc_only_copies, Tab}, Pat) ->
- ok = dets:match_delete(Tab, Pat).
-
-db_put({ram_copies, Tab}, Val) ->
- true = ?ets_insert(Tab, Val);
-db_put({disc_copies, Tab}, Val) ->
- true = ?ets_insert(Tab, Val);
-db_put({disc_only_copies, Tab}, Val) ->
- ok = dets:insert(Tab, Val).
-
-%% This code executes at the remote site where the data is
-%% executes in a special copier process.
-
-calc_nokeys(Storage, Tab) ->
- %% Calculate #keys per transfer
- Key = mnesia_lib:db_first(Storage, Tab),
- Recs = mnesia_lib:db_get(Storage, Tab, Key),
- BinSize = size(term_to_binary(Recs)),
- (?MAX_TRANSFER_SIZE div BinSize) + 1.
-
-send_table(Pid, Tab, RemoteS) ->
- case ?catch_val({Tab, storage_type}) of
- {'EXIT', _} ->
- {error, {no_exists, Tab}};
- unknown ->
- {error, {no_exists, Tab}};
- Storage ->
- %% Send first
- TabSize = mnesia:table_info(Tab, size),
- Pconvert = mnesia_monitor:needs_protocol_conversion(node(Pid)),
- KeysPerTransfer = calc_nokeys(Storage, Tab),
- ChunkData = dets:info(Tab, bchunk_format),
-
- UseDetsChunk =
- Storage == RemoteS andalso
- Storage == disc_only_copies andalso
- ChunkData /= undefined andalso
- Pconvert == false,
- if
- UseDetsChunk == true ->
- DetsInfo = erlang:system_info(version),
- Pid ! {self(), {first, TabSize, {DetsInfo, ChunkData}}};
- true ->
- Pid ! {self(), {first, TabSize}}
- end,
-
- %% Debug info
- put(mnesia_table_sender, {Tab, node(Pid), Pid}),
- {Init, Chunk} = reader_funcs(UseDetsChunk, Tab, Storage, KeysPerTransfer),
-
- SendIt = fun() ->
- prepare_copy(Pid, Tab, Storage),
- send_more(Pid, 1, Chunk, Init(), Tab, Pconvert),
- finish_copy(Pid, Tab, Storage, RemoteS)
- end,
-
- case catch SendIt() of
- receiver_died ->
- cleanup_tab_copier(Pid, Storage, Tab),
- unlink(whereis(mnesia_tm)),
- ok;
- {_, receiver_died} ->
- unlink(whereis(mnesia_tm)),
- ok;
- {'atomic', no_more} ->
- unlink(whereis(mnesia_tm)),
- ok;
- Reason ->
- cleanup_tab_copier(Pid, Storage, Tab),
- unlink(whereis(mnesia_tm)),
- {error, Reason}
- end
- end.
-
-prepare_copy(Pid, Tab, Storage) ->
- Trans =
- fun() ->
- mnesia:write_lock_table(Tab),
- mnesia_subscr:subscribe(Pid, {table, Tab}),
- update_where_to_write(Tab, node(Pid)),
- mnesia_lib:db_fixtable(Storage, Tab, true),
- ok
- end,
- case mnesia:transaction(Trans) of
- {'atomic', ok} ->
- ok;
- {aborted, Reason} ->
- exit({tab_copier_prepare, Tab, Reason})
- end.
-
-update_where_to_write(Tab, Node) ->
- case val({Tab, access_mode}) of
- read_only ->
- ignore;
- read_write ->
- Current = val({current, db_nodes}),
- Ns =
- case lists:member(Node, Current) of
- true -> Current;
- false -> [Node | Current]
- end,
- update_where_to_write(Ns, Tab, Node)
- end.
-
-update_where_to_write([], _, _) ->
- ok;
-update_where_to_write([H|T], Tab, AddNode) ->
- rpc:call(H, mnesia_controller, call,
- [{update_where_to_write, [add, Tab, AddNode], self()}]),
- update_where_to_write(T, Tab, AddNode).
-
-send_more(Pid, N, Chunk, DataState, Tab, OldNode) ->
- receive
- {NewPid, more} ->
- case send_packet(N - 1, NewPid, Chunk, DataState, OldNode) of
- New when integer(New) ->
- New - 1;
- NewData ->
- send_more(NewPid, ?MAX_NOPACKETS, Chunk, NewData, Tab, OldNode)
- end;
- {_NewPid, {old_protocol, Tab}} ->
- Storage = val({Tab, storage_type}),
- {Init, NewChunk} =
- reader_funcs(false, Tab, Storage, calc_nokeys(Storage, Tab)),
- send_more(Pid, 1, NewChunk, Init(), Tab, OldNode);
-
- {copier_done, Node} when Node == node(Pid)->
- verbose("Receiver of table ~p crashed on ~p (more)~n", [Tab, Node]),
- throw(receiver_died)
- end.
-
-reader_funcs(UseDetsChunk, Tab, Storage, KeysPerTransfer) ->
- case UseDetsChunk of
- false ->
- {fun() -> mnesia_lib:db_init_chunk(Storage, Tab, KeysPerTransfer) end,
- fun(Cont) -> mnesia_lib:db_chunk(Storage, Cont) end};
- true ->
- {fun() -> dets_bchunk(Tab, start) end,
- fun(Cont) -> dets_bchunk(Tab, Cont) end}
- end.
-
-dets_bchunk(Tab, Chunk) -> %% Arrg
- case dets:bchunk(Tab, Chunk) of
- {Cont, Data} -> {Data, Cont};
- Else -> Else
- end.
-
-send_packet(N, Pid, _Chunk, '$end_of_table', OldNode) ->
- case OldNode of
- true -> ignore; %% Old nodes can't handle the new no_more
- false -> Pid ! {self(), no_more}
- end,
- N;
-send_packet(N, Pid, Chunk, {[], Cont}, OldNode) ->
- send_packet(N, Pid, Chunk, Chunk(Cont), OldNode);
-send_packet(N, Pid, Chunk, {Recs, Cont}, OldNode) when N < ?MAX_NOPACKETS ->
- case OldNode of
- true -> Pid ! {self(), {more, [Recs]}}; %% Old need's wrapping list
- false -> Pid ! {self(), {more, Recs}}
- end,
- send_packet(N+1, Pid, Chunk, Chunk(Cont), OldNode);
-send_packet(_N, _Pid, _Chunk, DataState, _OldNode) ->
- DataState.
-
-finish_copy(Pid, Tab, Storage, RemoteS) ->
- RecNode = node(Pid),
- DatBin = dat2bin(Tab, Storage, RemoteS),
- Trans =
- fun() ->
- mnesia:read_lock_table(Tab),
- A = val({Tab, access_mode}),
- mnesia_controller:sync_and_block_table_whereabouts(Tab, RecNode, RemoteS, A),
- cleanup_tab_copier(Pid, Storage, Tab),
- mnesia_checkpoint:tm_add_copy(Tab, RecNode),
- Pid ! {self(), {no_more, DatBin}},
- receive
- {Pid, no_more} -> % Dont bother about the spurious 'more' message
- no_more;
- {copier_done, Node} when Node == node(Pid)->
- verbose("Tab receiver ~p crashed (more): ~p~n", [Tab, Node]),
- receiver_died
- end
- end,
- mnesia:transaction(Trans).
-
-cleanup_tab_copier(Pid, Storage, Tab) ->
- mnesia_lib:db_fixtable(Storage, Tab, false),
- mnesia_subscr:unsubscribe(Pid, {table, Tab}).
-
-dat2bin(Tab, ram_copies, ram_copies) ->
- mnesia_lib:lock_table(Tab),
- Res = file:read_file(mnesia_lib:tab2dcd(Tab)),
- mnesia_lib:unlock_table(Tab),
- case Res of
- {ok, DatBin} -> DatBin;
- _ -> nobin
- end;
-dat2bin(_Tab, _LocalS, _RemoteS) ->
- nobin.
-
-handle_exit(Pid, Reason) when node(Pid) == node() ->
- exit(Reason);
-handle_exit(_Pid, _Reason) -> %% Not from our node, this will be handled by
- ignore. %% mnesia_down soon.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_locker.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_locker.erl
deleted file mode 100644
index 8fe08414d0..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_locker.erl
+++ /dev/null
@@ -1,1022 +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: mnesia_locker.erl,v 1.2 2009/07/01 15:45:40 kostis Exp $
-%%
--module(mnesia_locker).
-
--export([
- get_held_locks/0,
- get_lock_queue/0,
- global_lock/5,
- ixrlock/5,
- init/1,
- mnesia_down/2,
- release_tid/1,
- async_release_tid/2,
- send_release_tid/2,
- receive_release_tid_acc/2,
- rlock/3,
- rlock_table/3,
- rwlock/3,
- sticky_rwlock/3,
- start/0,
- sticky_wlock/3,
- sticky_wlock_table/3,
- wlock/3,
- wlock_no_exist/4,
- wlock_table/3
- ]).
-
-%% sys callback functions
--export([system_continue/3,
- system_terminate/4,
- system_code_change/4
- ]).
-
--include("mnesia.hrl").
--import(mnesia_lib, [dbg_out/2, error/2, verbose/2]).
-
--define(dbg(S,V), ok).
-%-define(dbg(S,V), dbg_out("~p:~p: " ++ S, [?MODULE, ?LINE] ++ V)).
-
--define(ALL, '______WHOLETABLE_____').
--define(STICK, '______STICK_____').
--define(GLOBAL, '______GLOBAL_____').
-
--record(state, {supervisor}).
-
--record(queue, {oid, tid, op, pid, lucky}).
-
-%% mnesia_held_locks: contain {Oid, Op, Tid} entries (bag)
--define(match_oid_held_locks(Oid), {Oid, '_', '_'}).
-%% mnesia_tid_locks: contain {Tid, Oid, Op} entries (bag)
--define(match_oid_tid_locks(Tid), {Tid, '_', '_'}).
-%% mnesia_sticky_locks: contain {Oid, Node} entries and {Tab, Node} entries (set)
--define(match_oid_sticky_locks(Oid),{Oid, '_'}).
-%% mnesia_lock_queue: contain {queue, Oid, Tid, Op, ReplyTo, WaitForTid} entries (ordered_set)
--define(match_oid_lock_queue(Oid), #queue{oid=Oid, tid='_', op = '_', pid = '_', lucky = '_'}).
-%% mnesia_lock_counter: {{write, Tab}, Number} &&
-%% {{read, Tab}, Number} entries (set)
-
-start() ->
- mnesia_monitor:start_proc(?MODULE, ?MODULE, init, [self()]).
-
-init(Parent) ->
- register(?MODULE, self()),
- process_flag(trap_exit, true),
- proc_lib:init_ack(Parent, {ok, self()}),
- loop(#state{supervisor = Parent}).
-
-val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _ReASoN_} -> mnesia_lib:other_val(Var, _ReASoN_);
- _VaLuE_ -> _VaLuE_
- end.
-
-reply(From, R) ->
- From ! {?MODULE, node(), R}.
-
-l_request(Node, X, Store) ->
- {?MODULE, Node} ! {self(), X},
- l_req_rec(Node, Store).
-
-l_req_rec(Node, Store) ->
- ?ets_insert(Store, {nodes, Node}),
- receive
- {?MODULE, Node, {switch, Node2, Req}} ->
- ?ets_insert(Store, {nodes, Node2}),
- {?MODULE, Node2} ! Req,
- {switch, Node2, Req};
- {?MODULE, Node, Reply} ->
- Reply;
- {mnesia_down, Node} ->
- {not_granted, {node_not_running, Node}}
- end.
-
-release_tid(Tid) ->
- ?MODULE ! {release_tid, Tid}.
-
-async_release_tid(Nodes, Tid) ->
- rpc:abcast(Nodes, ?MODULE, {release_tid, Tid}).
-
-send_release_tid(Nodes, Tid) ->
- rpc:abcast(Nodes, ?MODULE, {self(), {sync_release_tid, Tid}}).
-
-receive_release_tid_acc([Node | Nodes], Tid) ->
- receive
- {?MODULE, Node, {tid_released, Tid}} ->
- receive_release_tid_acc(Nodes, Tid);
- {mnesia_down, Node} ->
- receive_release_tid_acc(Nodes, Tid)
- end;
-receive_release_tid_acc([], _Tid) ->
- ok.
-
-loop(State) ->
- receive
- {From, {write, Tid, Oid}} ->
- try_sticky_lock(Tid, write, From, Oid),
- loop(State);
-
- %% If Key == ?ALL it's a request to lock the entire table
- %%
-
- {From, {read, Tid, Oid}} ->
- try_sticky_lock(Tid, read, From, Oid),
- loop(State);
-
- %% Really do a read, but get hold of a write lock
- %% used by mnesia:wread(Oid).
-
- {From, {read_write, Tid, Oid}} ->
- try_sticky_lock(Tid, read_write, From, Oid),
- loop(State);
-
- %% Tid has somehow terminated, clear up everything
- %% and pass locks on to queued processes.
- %% This is the purpose of the mnesia_tid_locks table
-
- {release_tid, Tid} ->
- do_release_tid(Tid),
- loop(State);
-
- %% stick lock, first tries this to the where_to_read Node
- {From, {test_set_sticky, Tid, {Tab, _} = Oid, Lock}} ->
- case ?ets_lookup(mnesia_sticky_locks, Tab) of
- [] ->
- reply(From, not_stuck),
- loop(State);
- [{_,Node}] when Node == node() ->
- %% Lock is stuck here, see now if we can just set
- %% a regular write lock
- try_lock(Tid, Lock, From, Oid),
- loop(State);
- [{_,Node}] ->
- reply(From, {stuck_elsewhere, Node}),
- loop(State)
- end;
-
- %% If test_set_sticky fails, we send this to all nodes
- %% after aquiring a real write lock on Oid
-
- {stick, {Tab, _}, N} ->
- ?ets_insert(mnesia_sticky_locks, {Tab, N}),
- loop(State);
-
- %% The caller which sends this message, must have first
- %% aquired a write lock on the entire table
- {unstick, Tab} ->
- ?ets_delete(mnesia_sticky_locks, Tab),
- loop(State);
-
- {From, {ix_read, Tid, Tab, IxKey, Pos}} ->
- case catch mnesia_index:get_index_table(Tab, Pos) of
- {'EXIT', _} ->
- reply(From, {not_granted, {no_exists, Tab, {index, [Pos]}}}),
- loop(State);
- Index ->
- Rk = mnesia_lib:elems(2,mnesia_index:db_get(Index, IxKey)),
- %% list of real keys
- case ?ets_lookup(mnesia_sticky_locks, Tab) of
- [] ->
- set_read_lock_on_all_keys(Tid, From,Tab,Rk,Rk,
- []),
- loop(State);
- [{_,N}] when N == node() ->
- set_read_lock_on_all_keys(Tid, From,Tab,Rk,Rk,
- []),
- loop(State);
- [{_,N}] ->
- Req = {From, {ix_read, Tid, Tab, IxKey, Pos}},
- From ! {?MODULE, node(), {switch, N, Req}},
- loop(State)
- end
- end;
-
- {From, {sync_release_tid, Tid}} ->
- do_release_tid(Tid),
- reply(From, {tid_released, Tid}),
- loop(State);
-
- {release_remote_non_pending, Node, Pending} ->
- release_remote_non_pending(Node, Pending),
- mnesia_monitor:mnesia_down(?MODULE, Node),
- loop(State);
-
- {'EXIT', Pid, _} when Pid == State#state.supervisor ->
- do_stop();
-
- {system, From, Msg} ->
- verbose("~p got {system, ~p, ~p}~n", [?MODULE, From, Msg]),
- Parent = State#state.supervisor,
- sys:handle_system_msg(Msg, From, Parent, ?MODULE, [], State);
-
- Msg ->
- error("~p got unexpected message: ~p~n", [?MODULE, Msg]),
- loop(State)
- end.
-
-set_lock(Tid, Oid, Op) ->
- ?dbg("Granted ~p ~p ~p~n", [Tid,Oid,Op]),
- ?ets_insert(mnesia_held_locks, {Oid, Op, Tid}),
- ?ets_insert(mnesia_tid_locks, {Tid, Oid, Op}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Acquire locks
-
-try_sticky_lock(Tid, Op, Pid, {Tab, _} = Oid) ->
- case ?ets_lookup(mnesia_sticky_locks, Tab) of
- [] ->
- try_lock(Tid, Op, Pid, Oid);
- [{_,N}] when N == node() ->
- try_lock(Tid, Op, Pid, Oid);
- [{_,N}] ->
- Req = {Pid, {Op, Tid, Oid}},
- Pid ! {?MODULE, node(), {switch, N, Req}}
- end.
-
-try_lock(Tid, read_write, Pid, Oid) ->
- try_lock(Tid, read_write, read, write, Pid, Oid);
-try_lock(Tid, Op, Pid, Oid) ->
- try_lock(Tid, Op, Op, Op, Pid, Oid).
-
-try_lock(Tid, Op, SimpleOp, Lock, Pid, Oid) ->
- case can_lock(Tid, Lock, Oid, {no, bad_luck}) of
- yes ->
- Reply = grant_lock(Tid, SimpleOp, Lock, Oid),
- reply(Pid, Reply);
- {no, Lucky} ->
- C = #cyclic{op = SimpleOp, lock = Lock, oid = Oid, lucky = Lucky},
- ?dbg("Rejected ~p ~p ~p ~p ~n", [Tid, Oid, Lock, Lucky]),
- reply(Pid, {not_granted, C});
- {queue, Lucky} ->
- ?dbg("Queued ~p ~p ~p ~p ~n", [Tid, Oid, Lock, Lucky]),
- %% Append to queue: Nice place for trace output
- ?ets_insert(mnesia_lock_queue,
- #queue{oid = Oid, tid = Tid, op = Op,
- pid = Pid, lucky = Lucky}),
- ?ets_insert(mnesia_tid_locks, {Tid, Oid, {queued, Op}})
- end.
-
-grant_lock(Tid, read, Lock, {Tab, Key})
- when Key /= ?ALL, Tab /= ?GLOBAL ->
- case node(Tid#tid.pid) == node() of
- true ->
- set_lock(Tid, {Tab, Key}, Lock),
- {granted, lookup_in_client};
- false ->
- case catch mnesia_lib:db_get(Tab, Key) of %% lookup as well
- {'EXIT', _Reason} ->
- %% Table has been deleted from this node,
- %% restart the transaction.
- C = #cyclic{op = read, lock = Lock, oid = {Tab, Key},
- lucky = nowhere},
- {not_granted, C};
- Val ->
- set_lock(Tid, {Tab, Key}, Lock),
- {granted, Val}
- end
- end;
-grant_lock(Tid, read, Lock, Oid) ->
- set_lock(Tid, Oid, Lock),
- {granted, ok};
-grant_lock(Tid, write, Lock, Oid) ->
- set_lock(Tid, Oid, Lock),
- granted.
-
-%% 1) Impose an ordering on all transactions favour old (low tid) transactions
-%% newer (higher tid) transactions may never wait on older ones,
-%% 2) When releasing the tids from the queue always begin with youngest (high tid)
-%% because of 1) it will avoid the deadlocks.
-%% 3) TabLocks is the problem :-) They should not starve and not deadlock
-%% handle tablocks in queue as they had locks on unlocked records.
-
-can_lock(Tid, read, {Tab, Key}, AlreadyQ) when Key /= ?ALL ->
- %% The key is bound, no need for the other BIF
- Oid = {Tab, Key},
- ObjLocks = ?ets_match_object(mnesia_held_locks, {Oid, write, '_'}),
- TabLocks = ?ets_match_object(mnesia_held_locks, {{Tab, ?ALL}, write, '_'}),
- check_lock(Tid, Oid, ObjLocks, TabLocks, yes, AlreadyQ, read);
-
-can_lock(Tid, read, Oid, AlreadyQ) -> % Whole tab
- Tab = element(1, Oid),
- ObjLocks = ?ets_match_object(mnesia_held_locks, {{Tab, '_'}, write, '_'}),
- check_lock(Tid, Oid, ObjLocks, [], yes, AlreadyQ, read);
-
-can_lock(Tid, write, {Tab, Key}, AlreadyQ) when Key /= ?ALL ->
- Oid = {Tab, Key},
- ObjLocks = ?ets_lookup(mnesia_held_locks, Oid),
- TabLocks = ?ets_lookup(mnesia_held_locks, {Tab, ?ALL}),
- check_lock(Tid, Oid, ObjLocks, TabLocks, yes, AlreadyQ, write);
-
-can_lock(Tid, write, Oid, AlreadyQ) -> % Whole tab
- Tab = element(1, Oid),
- ObjLocks = ?ets_match_object(mnesia_held_locks, ?match_oid_held_locks({Tab, '_'})),
- check_lock(Tid, Oid, ObjLocks, [], yes, AlreadyQ, write).
-
-%% Check held locks for conflicting locks
-check_lock(Tid, Oid, [Lock | Locks], TabLocks, X, AlreadyQ, Type) ->
- case element(3, Lock) of
- Tid ->
- check_lock(Tid, Oid, Locks, TabLocks, X, AlreadyQ, Type);
- WaitForTid when WaitForTid > Tid -> % Important order
- check_lock(Tid, Oid, Locks, TabLocks, {queue, WaitForTid}, AlreadyQ, Type);
- WaitForTid when Tid#tid.pid == WaitForTid#tid.pid ->
- dbg_out("Spurious lock conflict ~w ~w: ~w -> ~w~n",
- [Oid, Lock, Tid, WaitForTid]),
-%% check_lock(Tid, Oid, Locks, TabLocks, {queue, WaitForTid}, AlreadyQ);
- %% BUGBUG Fix this if possible
- {no, WaitForTid};
- WaitForTid ->
- {no, WaitForTid}
- end;
-
-check_lock(_, _, [], [], X, {queue, bad_luck}, _) ->
- X; %% The queue should be correct already no need to check it again
-
-check_lock(_, _, [], [], X = {queue, _Tid}, _AlreadyQ, _) ->
- X;
-
-check_lock(Tid, Oid, [], [], X, AlreadyQ, Type) ->
- {Tab, Key} = Oid,
- if
- Type == write ->
- check_queue(Tid, Tab, X, AlreadyQ);
- Key == ?ALL ->
- %% hmm should be solvable by a clever select expr but not today...
- check_queue(Tid, Tab, X, AlreadyQ);
- true ->
- %% If there is a queue on that object, read_lock shouldn't be granted
- ObjLocks = ets:lookup(mnesia_lock_queue, Oid),
- Greatest = max(ObjLocks),
- case Greatest of
- empty ->
- check_queue(Tid, Tab, X, AlreadyQ);
- ObjL when Tid > ObjL ->
- {no, ObjL}; %% Starvation Preemption (write waits for read)
- ObjL ->
- check_queue(Tid, Tab, {queue, ObjL}, AlreadyQ)
- end
- end;
-
-check_lock(Tid, Oid, [], TabLocks, X, AlreadyQ, Type) ->
- check_lock(Tid, Oid, TabLocks, [], X, AlreadyQ, Type).
-
-%% Check queue for conflicting locks
-%% Assume that all queued locks belongs to other tid's
-
-check_queue(Tid, Tab, X, AlreadyQ) ->
- TabLocks = ets:lookup(mnesia_lock_queue, {Tab,?ALL}),
- Greatest = max(TabLocks),
- case Greatest of
- empty ->
- X;
- Tid ->
- X;
- WaitForTid when WaitForTid#queue.tid > Tid -> % Important order
- {queue, WaitForTid};
- WaitForTid ->
- case AlreadyQ of
- {no, bad_luck} -> {no, WaitForTid};
- _ ->
- erlang:error({mnesia_locker, assert, AlreadyQ})
- end
- end.
-
-max([]) ->
- empty;
-max([H|R]) ->
- max(R, H#queue.tid).
-
-max([H|R], Tid) when H#queue.tid > Tid ->
- max(R, H#queue.tid);
-max([_|R], Tid) ->
- max(R, Tid);
-max([], Tid) ->
- Tid.
-
-%% We can't queue the ixlock requests since it
-%% becomes to complivated for little me :-)
-%% If we encounter an object with a wlock we reject the
-%% entire lock request
-%%
-%% BUGBUG: this is actually a bug since we may starve
-
-set_read_lock_on_all_keys(Tid, From, Tab, [RealKey | Tail], Orig, Ack) ->
- Oid = {Tab, RealKey},
- case can_lock(Tid, read, Oid, {no, bad_luck}) of
- yes ->
- {granted, Val} = grant_lock(Tid, read, read, Oid),
- case opt_lookup_in_client(Val, Oid, read) of % Ought to be invoked
- C when record(C, cyclic) -> % in the client
- reply(From, {not_granted, C});
- Val2 ->
- Ack2 = lists:append(Val2, Ack),
- set_read_lock_on_all_keys(Tid, From, Tab, Tail, Orig, Ack2)
- end;
- {no, Lucky} ->
- C = #cyclic{op = read, lock = read, oid = Oid, lucky = Lucky},
- reply(From, {not_granted, C});
- {queue, Lucky} ->
- C = #cyclic{op = read, lock = read, oid = Oid, lucky = Lucky},
- reply(From, {not_granted, C})
- end;
-set_read_lock_on_all_keys(_Tid, From, _Tab, [], Orig, Ack) ->
- reply(From, {granted, Ack, Orig}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Release of locks
-
-%% Release remote non-pending nodes
-release_remote_non_pending(Node, Pending) ->
- %% Clear the mnesia_sticky_locks table first, to avoid
- %% unnecessary requests to the failing node
- ?ets_match_delete(mnesia_sticky_locks, {'_' , Node}),
-
- %% Then we have to release all locks held by processes
- %% running at the failed node and also simply remove all
- %% queue'd requests back to the failed node
-
- AllTids = ?ets_match(mnesia_tid_locks, {'$1', '_', '_'}),
- Tids = [T || [T] <- AllTids, Node == node(T#tid.pid), not lists:member(T, Pending)],
- do_release_tids(Tids).
-
-do_release_tids([Tid | Tids]) ->
- do_release_tid(Tid),
- do_release_tids(Tids);
-do_release_tids([]) ->
- ok.
-
-do_release_tid(Tid) ->
- Locks = ?ets_lookup(mnesia_tid_locks, Tid),
- ?dbg("Release ~p ~p ~n", [Tid, Locks]),
- ?ets_delete(mnesia_tid_locks, Tid),
- release_locks(Locks),
- %% Removed queued locks which has had locks
- UniqueLocks = keyunique(lists:sort(Locks),[]),
- rearrange_queue(UniqueLocks).
-
-keyunique([{_Tid, Oid, _Op}|R], Acc = [{_, Oid, _}|_]) ->
- keyunique(R, Acc);
-keyunique([H|R], Acc) ->
- keyunique(R, [H|Acc]);
-keyunique([], Acc) ->
- Acc.
-
-release_locks([Lock | Locks]) ->
- release_lock(Lock),
- release_locks(Locks);
-release_locks([]) ->
- ok.
-
-release_lock({Tid, Oid, {queued, _}}) ->
- ?ets_match_delete(mnesia_lock_queue,
- #queue{oid=Oid, tid = Tid, op = '_',
- pid = '_', lucky = '_'});
-release_lock({Tid, Oid, Op}) ->
- if
- Op == write ->
- ?ets_delete(mnesia_held_locks, Oid);
- Op == read ->
- ?ets_match_delete(mnesia_held_locks, {Oid, Op, Tid})
- end.
-
-rearrange_queue([{_Tid, {Tab, Key}, _} | Locks]) ->
- if
- Key /= ?ALL->
- Queue =
- ets:lookup(mnesia_lock_queue, {Tab, ?ALL}) ++
- ets:lookup(mnesia_lock_queue, {Tab, Key}),
- case Queue of
- [] ->
- ok;
- _ ->
- Sorted = lists:reverse(lists:keysort(#queue.tid, Queue)),
- try_waiters_obj(Sorted)
- end;
- true ->
- Pat = ?match_oid_lock_queue({Tab, '_'}),
- Queue = ?ets_match_object(mnesia_lock_queue, Pat),
- Sorted = lists:reverse(lists:keysort(#queue.tid, Queue)),
- try_waiters_tab(Sorted)
- end,
- ?dbg("RearrQ ~p~n", [Queue]),
- rearrange_queue(Locks);
-rearrange_queue([]) ->
- ok.
-
-try_waiters_obj([W | Waiters]) ->
- case try_waiter(W) of
- queued ->
- no;
- _ ->
- try_waiters_obj(Waiters)
- end;
-try_waiters_obj([]) ->
- ok.
-
-try_waiters_tab([W | Waiters]) ->
- case W#queue.oid of
- {_Tab, ?ALL} ->
- case try_waiter(W) of
- queued ->
- no;
- _ ->
- try_waiters_tab(Waiters)
- end;
- Oid ->
- case try_waiter(W) of
- queued ->
- Rest = key_delete_all(Oid, #queue.oid, Waiters),
- try_waiters_tab(Rest);
- _ ->
- try_waiters_tab(Waiters)
- end
- end;
-try_waiters_tab([]) ->
- ok.
-
-try_waiter({queue, Oid, Tid, read_write, ReplyTo, _}) ->
- try_waiter(Oid, read_write, read, write, ReplyTo, Tid);
-try_waiter({queue, Oid, Tid, Op, ReplyTo, _}) ->
- try_waiter(Oid, Op, Op, Op, ReplyTo, Tid).
-
-try_waiter(Oid, Op, SimpleOp, Lock, ReplyTo, Tid) ->
- case can_lock(Tid, Lock, Oid, {queue, bad_luck}) of
- yes ->
- %% Delete from queue: Nice place for trace output
- ?ets_match_delete(mnesia_lock_queue,
- #queue{oid=Oid, tid = Tid, op = Op,
- pid = ReplyTo, lucky = '_'}),
- Reply = grant_lock(Tid, SimpleOp, Lock, Oid),
- ReplyTo ! {?MODULE, node(), Reply},
- locked;
- {queue, _Why} ->
- ?dbg("Keep ~p ~p ~p ~p~n", [Tid, Oid, Lock, _Why]),
- queued; % Keep waiter in queue
- {no, Lucky} ->
- C = #cyclic{op = SimpleOp, lock = Lock, oid = Oid, lucky = Lucky},
- verbose("** WARNING ** Restarted transaction, possible deadlock in lock queue ~w: cyclic = ~w~n",
- [Tid, C]),
- ?ets_match_delete(mnesia_lock_queue,
- #queue{oid=Oid, tid = Tid, op = Op,
- pid = ReplyTo, lucky = '_'}),
- Reply = {not_granted, C},
- ReplyTo ! {?MODULE, node(), Reply},
- removed
- end.
-
-key_delete_all(Key, Pos, TupleList) ->
- key_delete_all(Key, Pos, TupleList, []).
-key_delete_all(Key, Pos, [H|T], Ack) when element(Pos, H) == Key ->
- key_delete_all(Key, Pos, T, Ack);
-key_delete_all(Key, Pos, [H|T], Ack) ->
- key_delete_all(Key, Pos, T, [H|Ack]);
-key_delete_all(_, _, [], Ack) ->
- lists:reverse(Ack).
-
-
-%% ********************* end server code ********************
-%% The following code executes at the client side of a transactions
-
-mnesia_down(N, Pending) ->
- case whereis(?MODULE) of
- undefined ->
- %% Takes care of mnesia_down's in early startup
- mnesia_monitor:mnesia_down(?MODULE, N);
- Pid ->
- %% Syncronously call needed in order to avoid
- %% race with mnesia_tm's coordinator processes
- %% that may restart and acquire new locks.
- %% mnesia_monitor ensures the sync.
- Pid ! {release_remote_non_pending, N, Pending}
- end.
-
-%% Aquire a write lock, but do a read, used by
-%% mnesia:wread/1
-
-rwlock(Tid, Store, Oid) ->
- {Tab, Key} = Oid,
- case val({Tab, where_to_read}) of
- nowhere ->
- mnesia:abort({no_exists, Tab});
- Node ->
- Lock = write,
- case need_lock(Store, Tab, Key, Lock) of
- yes ->
- Ns = w_nodes(Tab),
- Res = get_rwlocks_on_nodes(Ns, Ns, Node, Store, Tid, Oid),
- ?ets_insert(Store, {{locks, Tab, Key}, Lock}),
- Res;
- no ->
- if
- Key == ?ALL ->
- w_nodes(Tab);
- Tab == ?GLOBAL ->
- w_nodes(Tab);
- true ->
- dirty_rpc(Node, Tab, Key, Lock)
- end
- end
- end.
-
-get_rwlocks_on_nodes([Node | Tail], Orig, Node, Store, Tid, Oid) ->
- Op = {self(), {read_write, Tid, Oid}},
- {?MODULE, Node} ! Op,
- ?ets_insert(Store, {nodes, Node}),
- add_debug(Node),
- get_rwlocks_on_nodes(Tail, Orig, Node, Store, Tid, Oid);
-get_rwlocks_on_nodes([Node | Tail], Orig, OtherNode, Store, Tid, Oid) ->
- Op = {self(), {write, Tid, Oid}},
- {?MODULE, Node} ! Op,
- add_debug(Node),
- ?ets_insert(Store, {nodes, Node}),
- get_rwlocks_on_nodes(Tail, Orig, OtherNode, Store, Tid, Oid);
-get_rwlocks_on_nodes([], Orig, _Node, Store, _Tid, Oid) ->
- receive_wlocks(Orig, read_write_lock, Store, Oid).
-
-%% Return a list of nodes or abort transaction
-%% WE also insert any additional where_to_write nodes
-%% in the local store under the key == nodes
-
-w_nodes(Tab) ->
- Nodes = ?catch_val({Tab, where_to_write}),
- case Nodes of
- [_ | _] -> Nodes;
- _ -> mnesia:abort({no_exists, Tab})
- end.
-
-%% aquire a sticky wlock, a sticky lock is a lock
-%% which remains at this node after the termination of the
-%% transaction.
-
-sticky_wlock(Tid, Store, Oid) ->
- sticky_lock(Tid, Store, Oid, write).
-
-sticky_rwlock(Tid, Store, Oid) ->
- sticky_lock(Tid, Store, Oid, read_write).
-
-sticky_lock(Tid, Store, {Tab, Key} = Oid, Lock) ->
- N = val({Tab, where_to_read}),
- if
- node() == N ->
- case need_lock(Store, Tab, Key, write) of
- yes ->
- do_sticky_lock(Tid, Store, Oid, Lock);
- no ->
- dirty_sticky_lock(Tab, Key, [N], Lock)
- end;
- true ->
- mnesia:abort({not_local, Tab})
- end.
-
-do_sticky_lock(Tid, Store, {Tab, Key} = Oid, Lock) ->
- ?MODULE ! {self(), {test_set_sticky, Tid, Oid, Lock}},
- receive
- {?MODULE, _N, granted} ->
- ?ets_insert(Store, {{locks, Tab, Key}, write}),
- granted;
- {?MODULE, _N, {granted, Val}} -> %% for rwlocks
- case opt_lookup_in_client(Val, Oid, write) of
- C when record(C, cyclic) ->
- exit({aborted, C});
- Val2 ->
- ?ets_insert(Store, {{locks, Tab, Key}, write}),
- Val2
- end;
- {?MODULE, _N, {not_granted, Reason}} ->
- exit({aborted, Reason});
- {?MODULE, N, not_stuck} ->
- not_stuck(Tid, Store, Tab, Key, Oid, Lock, N),
- dirty_sticky_lock(Tab, Key, [N], Lock);
- {mnesia_down, N} ->
- exit({aborted, {node_not_running, N}});
- {?MODULE, N, {stuck_elsewhere, _N2}} ->
- stuck_elsewhere(Tid, Store, Tab, Key, Oid, Lock),
- dirty_sticky_lock(Tab, Key, [N], Lock)
- end.
-
-not_stuck(Tid, Store, Tab, _Key, Oid, _Lock, N) ->
- rlock(Tid, Store, {Tab, ?ALL}), %% needed?
- wlock(Tid, Store, Oid), %% perfect sync
- wlock(Tid, Store, {Tab, ?STICK}), %% max one sticker/table
- Ns = val({Tab, where_to_write}),
- rpc:abcast(Ns, ?MODULE, {stick, Oid, N}).
-
-stuck_elsewhere(Tid, Store, Tab, _Key, Oid, _Lock) ->
- rlock(Tid, Store, {Tab, ?ALL}), %% needed?
- wlock(Tid, Store, Oid), %% perfect sync
- wlock(Tid, Store, {Tab, ?STICK}), %% max one sticker/table
- Ns = val({Tab, where_to_write}),
- rpc:abcast(Ns, ?MODULE, {unstick, Tab}).
-
-dirty_sticky_lock(Tab, Key, Nodes, Lock) ->
- if
- Lock == read_write ->
- mnesia_lib:db_get(Tab, Key);
- Key == ?ALL ->
- Nodes;
- Tab == ?GLOBAL ->
- Nodes;
- true ->
- ok
- end.
-
-sticky_wlock_table(Tid, Store, Tab) ->
- sticky_lock(Tid, Store, {Tab, ?ALL}, write).
-
-%% aquire a wlock on Oid
-%% We store a {Tabname, write, Tid} in all locktables
-%% on all nodes containing a copy of Tabname
-%% We also store an item {{locks, Tab, Key}, write} in the
-%% local store when we have aquired the lock.
-%%
-wlock(Tid, Store, Oid) ->
- {Tab, Key} = Oid,
- case need_lock(Store, Tab, Key, write) of
- yes ->
- Ns = w_nodes(Tab),
- Op = {self(), {write, Tid, Oid}},
- ?ets_insert(Store, {{locks, Tab, Key}, write}),
- get_wlocks_on_nodes(Ns, Ns, Store, Op, Oid);
- no when Key /= ?ALL, Tab /= ?GLOBAL ->
- [];
- no ->
- w_nodes(Tab)
- end.
-
-wlock_table(Tid, Store, Tab) ->
- wlock(Tid, Store, {Tab, ?ALL}).
-
-%% Write lock even if the table does not exist
-
-wlock_no_exist(Tid, Store, Tab, Ns) ->
- Oid = {Tab, ?ALL},
- Op = {self(), {write, Tid, Oid}},
- get_wlocks_on_nodes(Ns, Ns, Store, Op, Oid).
-
-need_lock(Store, Tab, Key, LockPattern) ->
- TabL = ?ets_match_object(Store, {{locks, Tab, ?ALL}, LockPattern}),
- if
- TabL == [] ->
- KeyL = ?ets_match_object(Store, {{locks, Tab, Key}, LockPattern}),
- if
- KeyL == [] ->
- yes;
- true ->
- no
- end;
- true ->
- no
- end.
-
-add_debug(Node) -> % Use process dictionary for debug info
- case get(mnesia_wlock_nodes) of
- undefined ->
- put(mnesia_wlock_nodes, [Node]);
- NodeList ->
- put(mnesia_wlock_nodes, [Node|NodeList])
- end.
-
-del_debug(Node) ->
- case get(mnesia_wlock_nodes) of
- undefined -> % Shouldn't happen
- ignore;
- [Node] ->
- erase(mnesia_wlock_nodes);
- List ->
- put(mnesia_wlock_nodes, lists:delete(Node, List))
- end.
-
-%% We first send lock requests to the lockmanagers on all
-%% nodes holding a copy of the table
-
-get_wlocks_on_nodes([Node | Tail], Orig, Store, Request, Oid) ->
- {?MODULE, Node} ! Request,
- ?ets_insert(Store, {nodes, Node}),
- add_debug(Node),
- get_wlocks_on_nodes(Tail, Orig, Store, Request, Oid);
-get_wlocks_on_nodes([], Orig, Store, _Request, Oid) ->
- receive_wlocks(Orig, Orig, Store, Oid).
-
-receive_wlocks([Node | Tail], Res, Store, Oid) ->
- receive
- {?MODULE, Node, granted} ->
- del_debug(Node),
- receive_wlocks(Tail, Res, Store, Oid);
- {?MODULE, Node, {granted, Val}} -> %% for rwlocks
- del_debug(Node),
- case opt_lookup_in_client(Val, Oid, write) of
- C when record(C, cyclic) ->
- flush_remaining(Tail, Node, {aborted, C});
- Val2 ->
- receive_wlocks(Tail, Val2, Store, Oid)
- end;
- {?MODULE, Node, {not_granted, Reason}} ->
- del_debug(Node),
- Reason1 = {aborted, Reason},
- flush_remaining(Tail, Node, Reason1);
- {mnesia_down, Node} ->
- del_debug(Node),
- Reason1 = {aborted, {node_not_running, Node}},
- flush_remaining(Tail, Node, Reason1);
- {?MODULE, Node, {switch, Node2, Req}} -> %% for rwlocks
- del_debug(Node),
- add_debug(Node2),
- ?ets_insert(Store, {nodes, Node2}),
- {?MODULE, Node2} ! Req,
- receive_wlocks([Node2 | Tail], Res, Store, Oid)
- end;
-
-receive_wlocks([], Res, _Store, _Oid) ->
- Res.
-
-flush_remaining([], _SkipNode, Res) ->
- exit(Res);
-flush_remaining([SkipNode | Tail ], SkipNode, Res) ->
- del_debug(SkipNode),
- flush_remaining(Tail, SkipNode, Res);
-flush_remaining([Node | Tail], SkipNode, Res) ->
- receive
- {?MODULE, Node, _} ->
- del_debug(Node),
- flush_remaining(Tail, SkipNode, Res);
- {mnesia_down, Node} ->
- del_debug(Node),
- flush_remaining(Tail, SkipNode, {aborted, {node_not_running, Node}})
- end.
-
-opt_lookup_in_client(lookup_in_client, Oid, Lock) ->
- {Tab, Key} = Oid,
- case catch mnesia_lib:db_get(Tab, Key) of
- {'EXIT', _} ->
- %% Table has been deleted from this node,
- %% restart the transaction.
- #cyclic{op = read, lock = Lock, oid = Oid, lucky = nowhere};
- Val ->
- Val
- end;
-opt_lookup_in_client(Val, _Oid, _Lock) ->
- Val.
-
-return_granted_or_nodes({_, ?ALL} , Nodes) -> Nodes;
-return_granted_or_nodes({?GLOBAL, _}, Nodes) -> Nodes;
-return_granted_or_nodes(_ , _Nodes) -> granted.
-
-%% We store a {Tab, read, From} item in the
-%% locks table on the node where we actually do pick up the object
-%% and we also store an item {lock, Oid, read} in our local store
-%% so that we can release any locks we hold when we commit.
-%% This function not only aquires a read lock, but also reads the object
-
-%% Oid's are always {Tab, Key} tuples
-rlock(Tid, Store, Oid) ->
- {Tab, Key} = Oid,
- case val({Tab, where_to_read}) of
- nowhere ->
- mnesia:abort({no_exists, Tab});
- Node ->
- case need_lock(Store, Tab, Key, '_') of
- yes ->
- R = l_request(Node, {read, Tid, Oid}, Store),
- rlock_get_reply(Node, Store, Oid, R);
- no ->
- if
- Key == ?ALL ->
- [Node];
- Tab == ?GLOBAL ->
- [Node];
- true ->
- dirty_rpc(Node, Tab, Key, read)
- end
- end
- end.
-
-dirty_rpc(nowhere, Tab, Key, _Lock) ->
- mnesia:abort({no_exists, {Tab, Key}});
-dirty_rpc(Node, _Tab, ?ALL, _Lock) ->
- [Node];
-dirty_rpc(Node, ?GLOBAL, _Key, _Lock) ->
- [Node];
-dirty_rpc(Node, Tab, Key, Lock) ->
- Args = [Tab, Key],
- case rpc:call(Node, mnesia_lib, db_get, Args) of
- {badrpc, Reason} ->
- case val({Tab, where_to_read}) of
- Node ->
- ErrorTag = mnesia_lib:dirty_rpc_error_tag(Reason),
- mnesia:abort({ErrorTag, Args});
- _NewNode ->
- %% Table has been deleted from the node,
- %% restart the transaction.
- C = #cyclic{op = read, lock = Lock, oid = {Tab, Key}, lucky = nowhere},
- exit({aborted, C})
- end;
- Other ->
- Other
- end.
-
-rlock_get_reply(Node, Store, Oid, {granted, V}) ->
- {Tab, Key} = Oid,
- ?ets_insert(Store, {{locks, Tab, Key}, read}),
- ?ets_insert(Store, {nodes, Node}),
- case opt_lookup_in_client(V, Oid, read) of
- C when record(C, cyclic) ->
- mnesia:abort(C);
- Val ->
- Val
- end;
-rlock_get_reply(Node, Store, Oid, granted) ->
- {Tab, Key} = Oid,
- ?ets_insert(Store, {{locks, Tab, Key}, read}),
- ?ets_insert(Store, {nodes, Node}),
- return_granted_or_nodes(Oid, [Node]);
-rlock_get_reply(Node, Store, Tab, {granted, V, RealKeys}) ->
- L = fun(K) -> ?ets_insert(Store, {{locks, Tab, K}, read}) end,
- lists:foreach(L, RealKeys),
- ?ets_insert(Store, {nodes, Node}),
- V;
-rlock_get_reply(_Node, _Store, _Oid, {not_granted , Reason}) ->
- exit({aborted, Reason});
-
-rlock_get_reply(_Node, Store, Oid, {switch, N2, Req}) ->
- ?ets_insert(Store, {nodes, N2}),
- {?MODULE, N2} ! Req,
- rlock_get_reply(N2, Store, Oid, l_req_rec(N2, Store)).
-
-
-rlock_table(Tid, Store, Tab) ->
- rlock(Tid, Store, {Tab, ?ALL}).
-
-ixrlock(Tid, Store, Tab, IxKey, Pos) ->
- case val({Tab, where_to_read}) of
- nowhere ->
- mnesia:abort({no_exists, Tab});
- Node ->
- R = l_request(Node, {ix_read, Tid, Tab, IxKey, Pos}, Store),
- rlock_get_reply(Node, Store, Tab, R)
- end.
-
-%% Grabs the locks or exits
-global_lock(Tid, Store, Item, write, Ns) ->
- Oid = {?GLOBAL, Item},
- Op = {self(), {write, Tid, Oid}},
- get_wlocks_on_nodes(Ns, Ns, Store, Op, Oid);
-global_lock(Tid, Store, Item, read, Ns) ->
- Oid = {?GLOBAL, Item},
- send_requests(Ns, {read, Tid, Oid}),
- rec_requests(Ns, Oid, Store),
- Ns.
-
-send_requests([Node | Nodes], X) ->
- {?MODULE, Node} ! {self(), X},
- send_requests(Nodes, X);
-send_requests([], _X) ->
- ok.
-
-rec_requests([Node | Nodes], Oid, Store) ->
- Res = l_req_rec(Node, Store),
- case catch rlock_get_reply(Node, Store, Oid, Res) of
- {'EXIT', Reason} ->
- flush_remaining(Nodes, Node, Reason);
- _ ->
- rec_requests(Nodes, Oid, Store)
- end;
-rec_requests([], _Oid, _Store) ->
- ok.
-
-get_held_locks() ->
- ?ets_match_object(mnesia_held_locks, '_').
-
-get_lock_queue() ->
- Q = ?ets_match_object(mnesia_lock_queue, '_'),
- [{Oid, Op, Pid, Tid, WFT} || {queue, Oid, Tid, Op, Pid, WFT} <- Q].
-
-do_stop() ->
- exit(shutdown).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% System upgrade
-
-system_continue(_Parent, _Debug, State) ->
- loop(State).
-
-system_terminate(_Reason, _Parent, _Debug, _State) ->
- do_stop().
-
-system_code_change(State, _Module, _OldVsn, _Extra) ->
- {ok, State}.
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_log.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_log.erl
deleted file mode 100644
index 79bd8d3812..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_log.erl
+++ /dev/null
@@ -1,1019 +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: mnesia_log.erl,v 1.2 2009/07/01 15:45:40 kostis Exp $
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% This module administers three kinds of log files:
-%%
-%% 1 The transaction log
-%% mnesia_tm appends to the log (via mnesia_log) at the
-%% end of each transaction (or dirty write) and
-%% mnesia_dumper reads the log and performs the ops in
-%% the dat files. The dump_log is done at startup and
-%% at intervals controlled by the user.
-%%
-%% 2 The mnesia_down log
-%% mnesia_tm appends to the log (via mnesia_log) when it
-%% realizes that mnesia goes up or down on another node.
-%% mnesia_init reads the log (via mnesia_log) at startup.
-%%
-%% 3 The backup log
-%% mnesia_schema produces one tiny log when the schema is
-%% initially created. mnesia_schema also reads the log
-%% when the user wants tables (possibly incl the schema)
-%% to be restored. mnesia_log appends to the log when the
-%% user wants to produce a real backup.
-%%
-%% The actual access to the backup media is performed via the
-%% mnesia_backup module for both read and write. mnesia_backup
-%% uses the disk_log (*), BUT the user may write an own module
-%% with the same interface as mnesia_backup and configure
-%% Mnesia so the alternate module performs the actual accesses
-%% to the backup media. This means that the user may put the
-%% backup on medias that Mnesia does not know about possibly on
-%% hosts where Erlang is not running.
-%%
-%% All these logs have to some extent a common structure.
-%% They are all using the disk_log module (*) for the basic
-%% file structure. The disk_log has a repair feature that
-%% can be used to skip erroneous log records if one comes to
-%% the conclusion that it is more important to reuse some
-%% of the log records than the risque of obtaining inconsistent
-%% data. If the data becomes inconsistent it is solely up to the
-%% application to make it consistent again. The automatic
-%% reparation of the disk_log is very powerful, but use it
-%% with extreme care.
-%%
-%% First in all Mnesia's log file is a mnesia log header.
-%% It contains a list with a log_header record as single
-%% element. The structure of the log_header may never be
-%% changed since it may be written to very old backup files.
-%% By holding this record definition stable we can be
-%% able to comprahend backups from timepoint 0. It also
-%% allows us to use the backup format as an interchange
-%% format between Mnesia releases.
-%%
-%% An op-list is a list of tuples with arity 3. Each tuple
-%% has this structure: {Oid, Recs, Op} where Oid is the tuple
-%% {Tab, Key}, Recs is a (possibly empty) list of records and
-%% Op is an atom.
-%%
-%% The log file structure for the transaction log is as follows.
-%%
-%% After the mnesia log section follows an extended record section
-%% containing op-lists. There are several values that Op may
-%% have, such as write, delete, update_counter, delete_object,
-%% and replace. There is no special end of section marker.
-%%
-%% +-----------------+
-%% | mnesia log head |
-%% +-----------------+
-%% | extended record |
-%% | section |
-%% +-----------------+
-%%
-%% The log file structure for the mnesia_down log is as follows.
-%%
-%% After the mnesia log section follows a mnesia_down section
-%% containg lists with yoyo records as single element.
-%%
-%% +-----------------+
-%% | mnesia log head |
-%% +-----------------+
-%% | mnesia_down |
-%% | section |
-%% +-----------------+
-%%
-%% The log file structure for the backup log is as follows.
-%%
-%% After the mnesia log section follows a schema section
-%% containing record lists. A record list is a list of tuples
-%% where {schema, Tab} is interpreted as a delete_table(Tab) and
-%% {schema, Tab, CreateList} are interpreted as create_table.
-%%
-%% The record section also contains record lists. In this section
-%% {Tab, Key} is interpreted as delete({Tab, Key}) and other tuples
-%% as write(Tuple). There is no special end of section marker.
-%%
-%% +-----------------+
-%% | mnesia log head |
-%% +-----------------+
-%% | schema section |
-%% +-----------------+
-%% | record section |
-%% +-----------------+
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
--module(mnesia_log).
-
--export([
- append/2,
- backup/1,
- backup/2,
- backup_checkpoint/2,
- backup_checkpoint/3,
- backup_log_header/0,
- backup_master/2,
- chunk_decision_log/1,
- chunk_decision_tab/1,
- chunk_log/1,
- chunk_log/2,
- close_decision_log/0,
- close_decision_tab/0,
- close_log/1,
- unsafe_close_log/1,
- confirm_log_dump/1,
- confirm_decision_log_dump/0,
- previous_log_file/0,
- previous_decision_log_file/0,
- latest_log_file/0,
- decision_log_version/0,
- decision_log_file/0,
- decision_tab_file/0,
- decision_tab_version/0,
- dcl_version/0,
- dcd_version/0,
- ets2dcd/1,
- ets2dcd/2,
- dcd2ets/1,
- dcd2ets/2,
- init/0,
- init_log_dump/0,
- log/1,
- slog/1,
- log_decision/1,
- log_files/0,
- open_decision_log/0,
- trans_log_header/0,
- open_decision_tab/0,
- dcl_log_header/0,
- dcd_log_header/0,
- open_log/4,
- open_log/6,
- prepare_decision_log_dump/0,
- prepare_log_dump/1,
- save_decision_tab/1,
- purge_all_logs/0,
- purge_some_logs/0,
- stop/0,
- tab_copier/3,
- version/0,
- view/0,
- view/1,
- write_trans_log_header/0
- ]).
-
-
--include("mnesia.hrl").
--import(mnesia_lib, [val/1, dir/1]).
--import(mnesia_lib, [exists/1, fatal/2, error/2, dbg_out/2]).
-
-trans_log_header() -> log_header(trans_log, version()).
-backup_log_header() -> log_header(backup_log, "1.2").
-decision_log_header() -> log_header(decision_log, decision_log_version()).
-decision_tab_header() -> log_header(decision_tab, decision_tab_version()).
-dcl_log_header() -> log_header(dcl_log, dcl_version()).
-dcd_log_header() -> log_header(dcd_log, dcd_version()).
-
-log_header(Kind, Version) ->
- #log_header{log_version=Version,
- log_kind=Kind,
- mnesia_version=mnesia:system_info(version),
- node=node(),
- now=now()}.
-
-version() -> "4.3".
-
-decision_log_version() -> "3.0".
-
-decision_tab_version() -> "1.0".
-
-dcl_version() -> "1.0".
-dcd_version() -> "1.0".
-
-append(Log, Bin) when binary(Bin) ->
- disk_log:balog(Log, Bin);
-append(Log, Term) ->
- disk_log:alog(Log, Term).
-
-%% Synced append
-sappend(Log, Bin) when binary(Bin) ->
- ok = disk_log:blog(Log, Bin);
-sappend(Log, Term) ->
- ok = disk_log:log(Log, Term).
-
-%% Write commit records to the latest_log
-log(C) when C#commit.disc_copies == [],
- C#commit.disc_only_copies == [],
- C#commit.schema_ops == [] ->
- ignore;
-log(C) ->
- case mnesia_monitor:use_dir() of
- true ->
- if
- record(C, commit) ->
- C2 = C#commit{ram_copies = [], snmp = []},
- append(latest_log, C2);
- true ->
- %% Either a commit record as binary
- %% or some decision related info
- append(latest_log, C)
- end,
- mnesia_dumper:incr_log_writes();
- false ->
- ignore
- end.
-
-%% Synced
-
-slog(C) when C#commit.disc_copies == [],
- C#commit.disc_only_copies == [],
- C#commit.schema_ops == [] ->
- ignore;
-slog(C) ->
- case mnesia_monitor:use_dir() of
- true ->
- if
- record(C, commit) ->
- C2 = C#commit{ram_copies = [], snmp = []},
- sappend(latest_log, C2);
- true ->
- %% Either a commit record as binary
- %% or some decision related info
- sappend(latest_log, C)
- end,
- mnesia_dumper:incr_log_writes();
- false ->
- ignore
- end.
-
-
-%% Stuff related to the file LOG
-
-%% Returns a list of logfiles. The oldest is first.
-log_files() -> [previous_log_file(),
- latest_log_file(),
- decision_tab_file()
- ].
-
-latest_log_file() -> dir(latest_log_name()).
-
-previous_log_file() -> dir("PREVIOUS.LOG").
-
-decision_log_file() -> dir(decision_log_name()).
-
-decision_tab_file() -> dir(decision_tab_name()).
-
-previous_decision_log_file() -> dir("PDECISION.LOG").
-
-latest_log_name() -> "LATEST.LOG".
-
-decision_log_name() -> "DECISION.LOG".
-
-decision_tab_name() -> "DECISION_TAB.LOG".
-
-init() ->
- case mnesia_monitor:use_dir() of
- true ->
- Prev = previous_log_file(),
- verify_no_exists(Prev),
-
- Latest = latest_log_file(),
- verify_no_exists(Latest),
-
- Header = trans_log_header(),
- open_log(latest_log, Header, Latest);
- false ->
- ok
- end.
-
-verify_no_exists(Fname) ->
- case exists(Fname) of
- false ->
- ok;
- true ->
- fatal("Log file exists: ~p~n", [Fname])
- end.
-
-open_log(Name, Header, Fname) ->
- Exists = exists(Fname),
- open_log(Name, Header, Fname, Exists).
-
-open_log(Name, Header, Fname, Exists) ->
- Repair = mnesia_monitor:get_env(auto_repair),
- open_log(Name, Header, Fname, Exists, Repair).
-
-open_log(Name, Header, Fname, Exists, Repair) ->
- case Name == previous_log of
- true ->
- open_log(Name, Header, Fname, Exists, Repair, read_only);
- false ->
- open_log(Name, Header, Fname, Exists, Repair, read_write)
- end.
-
-open_log(Name, Header, Fname, Exists, Repair, Mode) ->
- Args = [{file, Fname}, {name, Name}, {repair, Repair}, {mode, Mode}],
-%% io:format("~p:open_log: ~p ~p~n", [?MODULE, Name, Fname]),
- case mnesia_monitor:open_log(Args) of
- {ok, Log} when Exists == true ->
- Log;
- {ok, Log} ->
- write_header(Log, Header),
- Log;
- {repaired, Log, _, {badbytes, 0}} when Exists == true ->
- Log;
- {repaired, Log, _, {badbytes, 0}} ->
- write_header(Log, Header),
- Log;
- {repaired, Log, _Recover, BadBytes} ->
- mnesia_lib:important("Data may be missing, log ~p repaired: Lost ~p bytes~n",
- [Fname, BadBytes]),
- Log;
- {error, Reason} when Repair == true ->
- file:delete(Fname),
- mnesia_lib:important("Data may be missing, Corrupt logfile deleted: ~p, ~p ~n",
- [Fname, Reason]),
- %% Create a new
- open_log(Name, Header, Fname, false, false, read_write);
- {error, Reason} ->
- fatal("Cannot open log file ~p: ~p~n", [Fname, Reason])
- end.
-
-write_header(Log, Header) ->
- append(Log, Header).
-
-write_trans_log_header() ->
- write_header(latest_log, trans_log_header()).
-
-stop() ->
- case mnesia_monitor:use_dir() of
- true ->
- close_log(latest_log);
- false ->
- ok
- end.
-
-close_log(Log) ->
-%% io:format("mnesia_log:close_log ~p~n", [Log]),
-%% io:format("mnesia_log:close_log ~p~n", [Log]),
- case disk_log:sync(Log) of
- ok -> ok;
- {error, {read_only_mode, Log}} ->
- ok;
- {error, Reason} ->
- mnesia_lib:important("Failed syncing ~p to_disk reason ~p ~n",
- [Log, Reason])
- end,
- mnesia_monitor:close_log(Log).
-
-unsafe_close_log(Log) ->
-%% io:format("mnesia_log:close_log ~p~n", [Log]),
- mnesia_monitor:unsafe_close_log(Log).
-
-
-purge_some_logs() ->
- mnesia_monitor:unsafe_close_log(latest_log),
- file:delete(latest_log_file()),
- file:delete(decision_tab_file()).
-
-purge_all_logs() ->
- file:delete(previous_log_file()),
- file:delete(latest_log_file()),
- file:delete(decision_tab_file()).
-
-%% Prepare dump by renaming the open logfile if possible
-%% Returns a tuple on the following format: {Res, OpenLog}
-%% where OpenLog is the file descriptor to log file, ready for append
-%% and Res is one of the following: already_dumped, needs_dump or {error, Reason}
-prepare_log_dump(InitBy) ->
- Diff = mnesia_dumper:get_log_writes() -
- mnesia_lib:read_counter(trans_log_writes_prev),
- if
- Diff == 0, InitBy /= startup ->
- already_dumped;
- true ->
- case mnesia_monitor:use_dir() of
- true ->
- Prev = previous_log_file(),
- prepare_prev(Diff, InitBy, Prev, exists(Prev));
- false ->
- already_dumped
- end
- end.
-
-prepare_prev(Diff, _, _, true) ->
- {needs_dump, Diff};
-prepare_prev(Diff, startup, Prev, false) ->
- Latest = latest_log_file(),
- case exists(Latest) of
- true ->
- case file:rename(Latest, Prev) of
- ok ->
- {needs_dump, Diff};
- {error, Reason} ->
- {error, Reason}
- end;
- false ->
- already_dumped
- end;
-prepare_prev(Diff, _InitBy, Prev, false) ->
- Head = trans_log_header(),
- case mnesia_monitor:reopen_log(latest_log, Prev, Head) of
- ok ->
- {needs_dump, Diff};
- {error, Reason} ->
- Latest = latest_log_file(),
- {error, {"Cannot rename log file",
- [Latest, Prev, Reason]}}
- end.
-
-%% Init dump and return PrevLogFileDesc or exit.
-init_log_dump() ->
- Fname = previous_log_file(),
- open_log(previous_log, trans_log_header(), Fname),
- start.
-
-
-chunk_log(Cont) ->
- chunk_log(previous_log, Cont).
-
-chunk_log(_Log, eof) ->
- eof;
-chunk_log(Log, Cont) ->
- case catch disk_log:chunk(Log, Cont) of
- {error, Reason} ->
- fatal("Possibly truncated ~p file: ~p~n",
- [Log, Reason]);
- {C2, Chunk, _BadBytes} ->
- %% Read_only case, should we warn about the bad log file?
- %% BUGBUG Should we crash if Repair == false ??
- %% We got to check this !!
- mnesia_lib:important("~p repaired, lost ~p bad bytes~n", [Log, _BadBytes]),
- {C2, Chunk};
- Other ->
- Other
- end.
-
-%% Confirms the dump by closing prev log and delete the file
-confirm_log_dump(Updates) ->
- case mnesia_monitor:close_log(previous_log) of
- ok ->
- file:delete(previous_log_file()),
- mnesia_lib:incr_counter(trans_log_writes_prev, Updates),
- dumped;
- {error, Reason} ->
- {error, Reason}
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Decision log
-
-open_decision_log() ->
- Latest = decision_log_file(),
- open_log(decision_log, decision_log_header(), Latest),
- start.
-
-prepare_decision_log_dump() ->
- Prev = previous_decision_log_file(),
- prepare_decision_log_dump(exists(Prev), Prev).
-
-prepare_decision_log_dump(false, Prev) ->
- Head = decision_log_header(),
- case mnesia_monitor:reopen_log(decision_log, Prev, Head) of
- ok ->
- prepare_decision_log_dump(true, Prev);
- {error, Reason} ->
- fatal("Cannot rename decision log file ~p -> ~p: ~p~n",
- [decision_log_file(), Prev, Reason])
- end;
-prepare_decision_log_dump(true, Prev) ->
- open_log(previous_decision_log, decision_log_header(), Prev),
- start.
-
-chunk_decision_log(Cont) ->
- %% dbg_out("chunk log ~p~n", [Cont]),
- chunk_log(previous_decision_log, Cont).
-
-%% Confirms dump of the decision log
-confirm_decision_log_dump() ->
- case mnesia_monitor:close_log(previous_decision_log) of
- ok ->
- file:delete(previous_decision_log_file());
- {error, Reason} ->
- fatal("Cannot confirm decision log dump: ~p~n",
- [Reason])
- end.
-
-save_decision_tab(Decisions) ->
- Log = decision_tab,
- Tmp = mnesia_lib:dir("DECISION_TAB.TMP"),
- file:delete(Tmp),
- open_log(Log, decision_tab_header(), Tmp),
- append(Log, Decisions),
- close_log(Log),
- TabFile = decision_tab_file(),
- ok = file:rename(Tmp, TabFile).
-
-open_decision_tab() ->
- TabFile = decision_tab_file(),
- open_log(decision_tab, decision_tab_header(), TabFile),
- start.
-
-close_decision_tab() ->
- close_log(decision_tab).
-
-chunk_decision_tab(Cont) ->
- %% dbg_out("chunk tab ~p~n", [Cont]),
- chunk_log(decision_tab, Cont).
-
-close_decision_log() ->
- close_log(decision_log).
-
-log_decision(Decision) ->
- append(decision_log, Decision).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Debug functions
-
-view() ->
- lists:foreach(fun(F) -> view(F) end, log_files()).
-
-view(File) ->
- mnesia_lib:show("***** ~p ***** ~n", [File]),
- case exists(File) of
- false ->
- nolog;
- true ->
- N = view_only,
- Args = [{file, File}, {name, N}, {mode, read_only}],
- case disk_log:open(Args) of
- {ok, N} ->
- view_file(start, N);
- {repaired, _, _, _} ->
- view_file(start, N);
- {error, Reason} ->
- error("Cannot open log ~p: ~p~n", [File, Reason])
- end
- end.
-
-view_file(C, Log) ->
- case disk_log:chunk(Log, C) of
- {error, Reason} ->
- error("** Possibly truncated FILE ~p~n", [Reason]),
- error;
- eof ->
- disk_log:close(Log),
- eof;
- {C2, Terms, _BadBytes} ->
- dbg_out("Lost ~p bytes in ~p ~n", [_BadBytes, Log]),
- lists:foreach(fun(X) -> mnesia_lib:show("~p~n", [X]) end,
- Terms),
- view_file(C2, Log);
- {C2, Terms} ->
- lists:foreach(fun(X) -> mnesia_lib:show("~p~n", [X]) end,
- Terms),
- view_file(C2, Log)
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Backup
-
--record(backup_args, {name, module, opaque, scope, prev_name, tables, cookie}).
-
-backup(Opaque) ->
- backup(Opaque, []).
-
-backup(Opaque, Mod) when atom(Mod) ->
- backup(Opaque, [{module, Mod}]);
-backup(Opaque, Args) when list(Args) ->
- %% Backup all tables with max redundancy
- CpArgs = [{ram_overrides_dump, false}, {max, val({schema, tables})}],
- case mnesia_checkpoint:activate(CpArgs) of
- {ok, Name, _Nodes} ->
- Res = backup_checkpoint(Name, Opaque, Args),
- mnesia_checkpoint:deactivate(Name),
- Res;
- {error, Reason} ->
- {error, Reason}
- end.
-
-backup_checkpoint(Name, Opaque) ->
- backup_checkpoint(Name, Opaque, []).
-
-backup_checkpoint(Name, Opaque, Mod) when atom(Mod) ->
- backup_checkpoint(Name, Opaque, [{module, Mod}]);
-backup_checkpoint(Name, Opaque, Args) when list(Args) ->
- DefaultMod = mnesia_monitor:get_env(backup_module),
- B = #backup_args{name = Name,
- module = DefaultMod,
- opaque = Opaque,
- scope = global,
- tables = all,
- prev_name = Name},
- case check_backup_args(Args, B) of
- {ok, B2} ->
- %% Decentralized backup
- %% Incremental
-
- Self = self(),
- Pid = spawn_link(?MODULE, backup_master, [Self, B2]),
- receive
- {Pid, Self, Res} -> Res
- end;
- {error, Reason} ->
- {error, Reason}
- end.
-
-check_backup_args([Arg | Tail], B) ->
- case catch check_backup_arg_type(Arg, B) of
- {'EXIT', _Reason} ->
- {error, {badarg, Arg}};
- B2 ->
- check_backup_args(Tail, B2)
- end;
-
-check_backup_args([], B) ->
- {ok, B}.
-
-check_backup_arg_type(Arg, B) ->
- case Arg of
- {scope, global} ->
- B#backup_args{scope = global};
- {scope, local} ->
- B#backup_args{scope = local};
- {module, Mod} ->
- Mod2 = mnesia_monitor:do_check_type(backup_module, Mod),
- B#backup_args{module = Mod2};
- {incremental, Name} ->
- B#backup_args{prev_name = Name};
- {tables, Tabs} when list(Tabs) ->
- B#backup_args{tables = Tabs}
- end.
-
-backup_master(ClientPid, B) ->
- process_flag(trap_exit, true),
- case catch do_backup_master(B) of
- {'EXIT', Reason} ->
- ClientPid ! {self(), ClientPid, {error, {'EXIT', Reason}}};
- Res ->
- ClientPid ! {self(), ClientPid, Res}
- end,
- unlink(ClientPid),
- exit(normal).
-
-do_backup_master(B) ->
- Name = B#backup_args.name,
- B2 = safe_apply(B, open_write, [B#backup_args.opaque]),
- B3 = safe_write(B2, [backup_log_header()]),
- case mnesia_checkpoint:tables_and_cookie(Name) of
- {ok, AllTabs, Cookie} ->
- Tabs = select_tables(AllTabs, B3),
- B4 = B3#backup_args{cookie = Cookie},
- %% Always put schema first in backup file
- B5 = backup_schema(B4, Tabs),
- B6 = lists:foldl(fun backup_tab/2, B5, Tabs -- [schema]),
- safe_apply(B6, commit_write, [B6#backup_args.opaque]),
- ok;
- {error, Reason} ->
- abort_write(B3, {?MODULE, backup_master}, [B], {error, Reason})
- end.
-
-select_tables(AllTabs, B) ->
- Tabs =
- case B#backup_args.tables of
- all -> AllTabs;
- SomeTabs when list(SomeTabs) -> SomeTabs
- end,
- case B#backup_args.scope of
- global ->
- Tabs;
- local ->
- Name = B#backup_args.name,
- [T || T <- Tabs, mnesia_checkpoint:most_local_node(Name, T) == node()]
- end.
-
-safe_write(B, []) ->
- B;
-safe_write(B, Recs) ->
- safe_apply(B, write, [B#backup_args.opaque, Recs]).
-
-backup_schema(B, Tabs) ->
- case lists:member(schema, Tabs) of
- true ->
- backup_tab(schema, B);
- false ->
- Defs = [{schema, T, mnesia_schema:get_create_list(T)} || T <- Tabs],
- safe_write(B, Defs)
- end.
-
-safe_apply(B, write, [_, Items]) when Items == [] ->
- B;
-safe_apply(B, What, Args) ->
- Abort = fun(R) -> abort_write(B, What, Args, R) end,
- receive
- {'EXIT', Pid, R} -> Abort({'EXIT', Pid, R})
- after 0 ->
- Mod = B#backup_args.module,
- case catch apply(Mod, What, Args) of
- {ok, Opaque} -> B#backup_args{opaque=Opaque};
- {error, R} -> Abort(R);
- R -> Abort(R)
- end
- end.
-
-abort_write(B, What, Args, Reason) ->
- Mod = B#backup_args.module,
- Opaque = B#backup_args.opaque,
- dbg_out("Failed to perform backup. M=~p:F=~p:A=~p -> ~p~n",
- [Mod, What, Args, Reason]),
- case catch apply(Mod, abort_write, [Opaque]) of
- {ok, _Res} ->
- throw({error, Reason});
- Other ->
- error("Failed to abort backup. ~p:~p~p -> ~p~n",
- [Mod, abort_write, [Opaque], Other]),
- throw({error, Reason})
- end.
-
-backup_tab(Tab, B) ->
- Name = B#backup_args.name,
- case mnesia_checkpoint:most_local_node(Name, Tab) of
- {ok, Node} when Node == node() ->
- tab_copier(self(), B, Tab);
- {ok, Node} ->
- RemoteB = B,
- Pid = spawn_link(Node, ?MODULE, tab_copier, [self(), RemoteB, Tab]),
- RecName = val({Tab, record_name}),
- tab_receiver(Pid, B, Tab, RecName, 0);
- {error, Reason} ->
- abort_write(B, {?MODULE, backup_tab}, [Tab, B], {error, Reason})
- end.
-
-tab_copier(Pid, B, Tab) when record(B, backup_args) ->
- %% Intentional crash at exit
- Name = B#backup_args.name,
- PrevName = B#backup_args.prev_name,
- {FirstName, FirstSource} = select_source(Tab, Name, PrevName),
-
- ?eval_debug_fun({?MODULE, tab_copier, pre}, [{name, Name}, {tab, Tab}]),
- Res = handle_more(Pid, B, Tab, FirstName, FirstSource, Name),
- ?eval_debug_fun({?MODULE, tab_copier, post}, [{name, Name}, {tab, Tab}]),
-
- handle_last(Pid, Res).
-
-select_source(Tab, Name, PrevName) ->
- if
- Tab == schema ->
- %% Always full backup of schema
- {Name, table};
- Name == PrevName ->
- %% Full backup
- {Name, table};
- true ->
- %% Wants incremental backup
- case mnesia_checkpoint:most_local_node(PrevName, Tab) of
- {ok, Node} when Node == node() ->
- %% Accept incremental backup
- {PrevName, retainer};
- _ ->
- %% Do a full backup anyway
- dbg_out("Incremental backup escalated to full backup: ~p~n", [Tab]),
- {Name, table}
- end
- end.
-
-handle_more(Pid, B, Tab, FirstName, FirstSource, Name) ->
- Acc = {0, B},
- case {mnesia_checkpoint:really_retain(Name, Tab),
- mnesia_checkpoint:really_retain(FirstName, Tab)} of
- {true, true} ->
- Acc2 = iterate(B, FirstName, Tab, Pid, FirstSource, latest, first, Acc),
- iterate(B, Name, Tab, Pid, retainer, checkpoint, last, Acc2);
- {false, false}->
- %% Put the dumped file in the backup
- %% instead of the ram table. Does
- %% only apply to ram_copies.
- iterate(B, Name, Tab, Pid, retainer, checkpoint, last, Acc);
- Bad ->
- Reason = {"Checkpoints for incremental backup must have same "
- "setting of ram_overrides_dump",
- Tab, Name, FirstName, Bad},
- abort_write(B, {?MODULE, backup_tab}, [Tab, B], {error, Reason})
- end.
-
-handle_last(Pid, {_Count, B}) when Pid == self() ->
- B;
-handle_last(Pid, _Acc) ->
- unlink(Pid),
- Pid ! {self(), {last, {ok, dummy}}},
- exit(normal).
-
-iterate(B, Name, Tab, Pid, Source, Age, Pass, Acc) ->
- Fun =
- if
- Pid == self() ->
- RecName = val({Tab, record_name}),
- fun(Recs, A) -> copy_records(RecName, Tab, Recs, A) end;
- true ->
- fun(Recs, A) -> send_records(Pid, Tab, Recs, Pass, A) end
- end,
- case mnesia_checkpoint:iterate(Name, Tab, Fun, Acc, Source, Age) of
- {ok, Acc2} ->
- Acc2;
- {error, Reason} ->
- R = {error, {"Tab copier iteration failed", Reason}},
- abort_write(B, {?MODULE, iterate}, [self(), B, Tab], R)
- end.
-
-copy_records(_RecName, _Tab, [], Acc) ->
- Acc;
-copy_records(RecName, Tab, Recs, {Count, B}) ->
- Recs2 = rec_filter(B, Tab, RecName, Recs),
- B2 = safe_write(B, Recs2),
- {Count + 1, B2}.
-
-send_records(Pid, Tab, Recs, Pass, {Count, B}) ->
- receive
- {Pid, more, Count} ->
- if
- Pass == last, Recs == [] ->
- {Count, B};
- true ->
- Next = Count + 1,
- Pid ! {self(), {more, Next, Recs}},
- {Next, B}
- end;
- Msg ->
- exit({send_records_unexpected_msg, Tab, Msg})
- end.
-
-tab_receiver(Pid, B, Tab, RecName, Slot) ->
- Pid ! {self(), more, Slot},
- receive
- {Pid, {more, Next, Recs}} ->
- Recs2 = rec_filter(B, Tab, RecName, Recs),
- B2 = safe_write(B, Recs2),
- tab_receiver(Pid, B2, Tab, RecName, Next);
-
- {Pid, {last, {ok,_}}} ->
- B;
-
- {'EXIT', Pid, {error, R}} ->
- Reason = {error, {"Tab copier crashed", R}},
- abort_write(B, {?MODULE, remote_tab_sender}, [self(), B, Tab], Reason);
- {'EXIT', Pid, R} ->
- Reason = {error, {"Tab copier crashed", {'EXIT', R}}},
- abort_write(B, {?MODULE, remote_tab_sender}, [self(), B, Tab], Reason);
- Msg ->
- R = {error, {"Tab receiver got unexpected msg", Msg}},
- abort_write(B, {?MODULE, remote_tab_sender}, [self(), B, Tab], R)
- end.
-
-rec_filter(B, schema, _RecName, Recs) ->
- case catch mnesia_bup:refresh_cookie(Recs, B#backup_args.cookie) of
- Recs2 when list(Recs2) ->
- Recs2;
- {error, _Reason} ->
- %% No schema table cookie
- Recs
- end;
-rec_filter(_B, Tab, Tab, Recs) ->
- Recs;
-rec_filter(_B, Tab, _RecName, Recs) ->
- [setelement(1, Rec, Tab) || Rec <- Recs].
-
-ets2dcd(Tab) ->
- ets2dcd(Tab, dcd).
-
-ets2dcd(Tab, Ftype) ->
- Fname =
- case Ftype of
- dcd -> mnesia_lib:tab2dcd(Tab);
- dmp -> mnesia_lib:tab2dmp(Tab)
- end,
- TmpF = mnesia_lib:tab2tmp(Tab),
- file:delete(TmpF),
- Log = open_log({Tab, ets2dcd}, dcd_log_header(), TmpF, false),
- mnesia_lib:db_fixtable(ram_copies, Tab, true),
- ok = ets2dcd(mnesia_lib:db_init_chunk(ram_copies, Tab, 1000), Tab, Log),
- mnesia_lib:db_fixtable(ram_copies, Tab, false),
- close_log(Log),
- ok = file:rename(TmpF, Fname),
- %% Remove old log data which is now in the new dcd.
- %% No one else should be accessing this file!
- file:delete(mnesia_lib:tab2dcl(Tab)),
- ok.
-
-ets2dcd('$end_of_table', _Tab, _Log) ->
- ok;
-ets2dcd({Recs, Cont}, Tab, Log) ->
- ok = disk_log:alog_terms(Log, Recs),
- ets2dcd(mnesia_lib:db_chunk(ram_copies, Cont), Tab, Log).
-
-dcd2ets(Tab) ->
- dcd2ets(Tab, mnesia_monitor:get_env(auto_repair)).
-
-dcd2ets(Tab, Rep) ->
- Dcd = mnesia_lib:tab2dcd(Tab),
- case mnesia_lib:exists(Dcd) of
- true ->
- Log = open_log({Tab, dcd2ets}, dcd_log_header(), Dcd,
- true, Rep, read_only),
- Data = chunk_log(Log, start),
- ok = insert_dcdchunk(Data, Log, Tab),
- close_log(Log),
- load_dcl(Tab, Rep);
- false -> %% Handle old dets files, and conversion from disc_only to disc.
- Fname = mnesia_lib:tab2dat(Tab),
- Type = val({Tab, setorbag}),
- case mnesia_lib:dets_to_ets(Tab, Tab, Fname, Type, Rep, yes) of
- loaded ->
- ets2dcd(Tab),
- file:delete(Fname),
- 0;
- {error, Error} ->
- erlang:error({"Failed to load table from disc", [Tab, Error]})
- end
- end.
-
-insert_dcdchunk({Cont, [LogH | Rest]}, Log, Tab)
- when record(LogH, log_header),
- LogH#log_header.log_kind == dcd_log,
- LogH#log_header.log_version >= "1.0" ->
- insert_dcdchunk({Cont, Rest}, Log, Tab);
-
-insert_dcdchunk({Cont, Recs}, Log, Tab) ->
- true = ets:insert(Tab, Recs),
- insert_dcdchunk(chunk_log(Log, Cont), Log, Tab);
-insert_dcdchunk(eof, _Log, _Tab) ->
- ok.
-
-load_dcl(Tab, Rep) ->
- FName = mnesia_lib:tab2dcl(Tab),
- case mnesia_lib:exists(FName) of
- true ->
- Name = {load_dcl,Tab},
- open_log(Name,
- dcl_log_header(),
- FName,
- true,
- Rep,
- read_only),
- FirstChunk = chunk_log(Name, start),
- N = insert_logchunk(FirstChunk, Name, 0),
- close_log(Name),
- N;
- false ->
- 0
- end.
-
-insert_logchunk({C2, Recs}, Tab, C) ->
- N = add_recs(Recs, C),
- insert_logchunk(chunk_log(Tab, C2), Tab, C+N);
-insert_logchunk(eof, _Tab, C) ->
- C.
-
-add_recs([{{Tab, _Key}, Val, write} | Rest], N) ->
- true = ets:insert(Tab, Val),
- add_recs(Rest, N+1);
-add_recs([{{Tab, Key}, _Val, delete} | Rest], N) ->
- true = ets:delete(Tab, Key),
- add_recs(Rest, N+1);
-add_recs([{{Tab, _Key}, Val, delete_object} | Rest], N) ->
- true = ets:match_delete(Tab, Val),
- add_recs(Rest, N+1);
-add_recs([{{Tab, Key}, Val, update_counter} | Rest], N) ->
- {RecName, Incr} = Val,
- case catch ets:update_counter(Tab, Key, Incr) of
- CounterVal when integer(CounterVal) ->
- ok;
- _ ->
- Zero = {RecName, Key, 0},
- true = ets:insert(Tab, Zero)
- end,
- add_recs(Rest, N+1);
-add_recs([LogH|Rest], N)
- when record(LogH, log_header),
- LogH#log_header.log_kind == dcl_log,
- LogH#log_header.log_version >= "1.0" ->
- add_recs(Rest, N);
-add_recs([{{Tab, _Key}, _Val, clear_table} | Rest], N) ->
- true = ets:match_delete(Tab, '_'),
- add_recs(Rest, N+ets:info(Tab, size));
-add_recs([], N) ->
- N.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_monitor.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_monitor.erl
deleted file mode 100644
index 554f020ffb..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_monitor.erl
+++ /dev/null
@@ -1,776 +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: mnesia_monitor.erl,v 1.1 2008/12/17 09:53:38 mikpe Exp $
-%%
--module(mnesia_monitor).
-
--behaviour(gen_server).
-
-%% Public exports
--export([
- close_dets/1,
- close_log/1,
- detect_inconcistency/2,
- get_env/1,
- init/0,
- mktab/2,
- unsafe_mktab/2,
- mnesia_down/2,
- needs_protocol_conversion/1,
- negotiate_protocol/1,
- disconnect/1,
- open_dets/2,
- unsafe_open_dets/2,
- open_log/1,
- patch_env/2,
- protocol_version/0,
- reopen_log/3,
- set_env/2,
- start/0,
- start_proc/4,
- terminate_proc/3,
- unsafe_close_dets/1,
- unsafe_close_log/1,
- use_dir/0,
- do_check_type/2
- ]).
-
-%% gen_server callbacks
--export([
- init/1,
- handle_call/3,
- handle_cast/2,
- handle_info/2,
- terminate/2,
- code_change/3
- ]).
-
-%% Internal exports
--export([
- call/1,
- cast/1,
- detect_partitioned_network/2,
- has_remote_mnesia_down/1
- ]).
-
--import(mnesia_lib, [dbg_out/2, verbose/2, error/2, fatal/2, set/2]).
-
--include("mnesia.hrl").
-
--record(state, {supervisor, pending_negotiators = [],
- going_down = [], tm_started = false, early_connects = []}).
-
--define(current_protocol_version, {7,6}).
-
--define(previous_protocol_version, {7,5}).
-
-start() ->
- gen_server:start_link({local, ?MODULE}, ?MODULE,
- [self()], [{timeout, infinity}
- %% ,{debug, [trace]}
- ]).
-
-init() ->
- call(init).
-
-mnesia_down(From, Node) ->
- cast({mnesia_down, From, Node}).
-
-mktab(Tab, Args) ->
- unsafe_call({mktab, Tab, Args}).
-unsafe_mktab(Tab, Args) ->
- unsafe_call({unsafe_mktab, Tab, Args}).
-
-open_dets(Tab, Args) ->
- unsafe_call({open_dets, Tab, Args}).
-unsafe_open_dets(Tab, Args) ->
- unsafe_call({unsafe_open_dets, Tab, Args}).
-
-close_dets(Tab) ->
- unsafe_call({close_dets, Tab}).
-
-unsafe_close_dets(Name) ->
- unsafe_call({unsafe_close_dets, Name}).
-
-open_log(Args) ->
- unsafe_call({open_log, Args}).
-
-reopen_log(Name, Fname, Head) ->
- unsafe_call({reopen_log, Name, Fname, Head}).
-
-close_log(Name) ->
- unsafe_call({close_log, Name}).
-
-unsafe_close_log(Name) ->
- unsafe_call({unsafe_close_log, Name}).
-
-
-disconnect(Node) ->
- cast({disconnect, Node}).
-
-%% Returns GoodNoodes
-%% Creates a link to each compatible monitor and
-%% protocol_version to agreed version upon success
-
-negotiate_protocol(Nodes) ->
- Version = mnesia:system_info(version),
- Protocols = acceptable_protocol_versions(),
- MonitorPid = whereis(?MODULE),
- Msg = {negotiate_protocol, MonitorPid, Version, Protocols},
- {Replies, _BadNodes} = multicall(Nodes, Msg),
- check_protocol(Replies, Protocols).
-
-check_protocol([{Node, {accept, Mon, _Version, Protocol}} | Tail], Protocols) ->
- case lists:member(Protocol, Protocols) of
- true ->
- case Protocol == protocol_version() of
- true ->
- set({protocol, Node}, {Protocol, false});
- false ->
- set({protocol, Node}, {Protocol, true})
- end,
- [node(Mon) | check_protocol(Tail, Protocols)];
- false ->
- unlink(Mon), % Get rid of unneccessary link
- check_protocol(Tail, Protocols)
- end;
-check_protocol([{Node, {reject, _Mon, Version, Protocol}} | Tail], Protocols) ->
- verbose("Failed to connect with ~p. ~p protocols rejected. "
- "expected version = ~p, expected protocol = ~p~n",
- [Node, Protocols, Version, Protocol]),
- check_protocol(Tail, Protocols);
-check_protocol([{error, _Reason} | Tail], Protocols) ->
- check_protocol(Tail, Protocols);
-check_protocol([{badrpc, _Reason} | Tail], Protocols) ->
- check_protocol(Tail, Protocols);
-check_protocol([], [Protocol | _Protocols]) ->
- set(protocol_version, Protocol),
- [];
-check_protocol([], []) ->
- set(protocol_version, protocol_version()),
- [].
-
-protocol_version() ->
- case ?catch_val(protocol_version) of
- {'EXIT', _} -> ?current_protocol_version;
- Version -> Version
- end.
-
-%% A sorted list of acceptable protocols the
-%% preferred protocols are first in the list
-acceptable_protocol_versions() ->
- [protocol_version(), ?previous_protocol_version].
-
-needs_protocol_conversion(Node) ->
- case {?catch_val({protocol, Node}), protocol_version()} of
- {{'EXIT', _}, _} ->
- false;
- {{_, Bool}, ?current_protocol_version} ->
- Bool;
- {{_, Bool}, _} ->
- not Bool
- end.
-
-cast(Msg) ->
- case whereis(?MODULE) of
- undefined -> ignore;
- Pid -> gen_server:cast(Pid, Msg)
- end.
-
-unsafe_call(Msg) ->
- case whereis(?MODULE) of
- undefined -> {error, {node_not_running, node()}};
- Pid -> gen_server:call(Pid, Msg, infinity)
- end.
-
-call(Msg) ->
- case whereis(?MODULE) of
- undefined ->
- {error, {node_not_running, node()}};
- Pid ->
- link(Pid),
- Res = gen_server:call(Pid, Msg, infinity),
- unlink(Pid),
-
- %% We get an exit signal if server dies
- receive
- {'EXIT', Pid, _Reason} ->
- {error, {node_not_running, node()}}
- after 0 ->
- ignore
- end,
- Res
- end.
-
-multicall(Nodes, Msg) ->
- rpc:multicall(Nodes, ?MODULE, call, [Msg]).
-
-start_proc(Who, Mod, Fun, Args) ->
- Args2 = [Who, Mod, Fun, Args],
- proc_lib:start_link(mnesia_sp, init_proc, Args2, infinity).
-
-terminate_proc(Who, R, State) when R /= shutdown, R /= killed ->
- fatal("~p crashed: ~p state: ~p~n", [Who, R, State]);
-
-terminate_proc(Who, Reason, _State) ->
- mnesia_lib:verbose("~p terminated: ~p~n", [Who, Reason]),
- ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%% Callback functions from gen_server
-
-%%----------------------------------------------------------------------
-%% Func: init/1
-%% Returns: {ok, State} |
-%% {ok, State, Timeout} |
-%% {stop, Reason}
-%%----------------------------------------------------------------------
-init([Parent]) ->
- process_flag(trap_exit, true),
- ?ets_new_table(mnesia_gvar, [set, public, named_table]),
- set(subscribers, []),
- mnesia_lib:verbose("~p starting: ~p~n", [?MODULE, self()]),
- Version = mnesia:system_info(version),
- set(version, Version),
- dbg_out("Version: ~p~n", [Version]),
-
- case catch process_config_args(env()) of
- ok ->
- mnesia_lib:set({'$$$_report', current_pos}, 0),
- Level = mnesia_lib:val(debug),
- mnesia_lib:verbose("Mnesia debug level set to ~p\n", [Level]),
- set(mnesia_status, starting), %% set start status
- set({current, db_nodes}, [node()]),
- set(use_dir, use_dir()),
- mnesia_lib:create_counter(trans_aborts),
- mnesia_lib:create_counter(trans_commits),
- mnesia_lib:create_counter(trans_log_writes),
- Left = get_env(dump_log_write_threshold),
- mnesia_lib:set_counter(trans_log_writes_left, Left),
- mnesia_lib:create_counter(trans_log_writes_prev),
- mnesia_lib:create_counter(trans_restarts),
- mnesia_lib:create_counter(trans_failures),
- ?ets_new_table(mnesia_held_locks, [bag, public, named_table]),
- ?ets_new_table(mnesia_tid_locks, [bag, public, named_table]),
- ?ets_new_table(mnesia_sticky_locks, [set, public, named_table]),
- ?ets_new_table(mnesia_lock_queue,
- [bag, public, named_table, {keypos, 2}]),
- ?ets_new_table(mnesia_lock_counter, [set, public, named_table]),
- set(checkpoints, []),
- set(pending_checkpoints, []),
- set(pending_checkpoint_pids, []),
-
- {ok, #state{supervisor = Parent}};
- {'EXIT', Reason} ->
- mnesia_lib:report_fatal("Bad configuration: ~p~n", [Reason]),
- {stop, {bad_config, Reason}}
- end.
-
-use_dir() ->
- case ?catch_val(use_dir) of
- {'EXIT', _} ->
- case get_env(schema_location) of
- disc -> true;
- opt_disc -> non_empty_dir();
- ram -> false
- end;
- Bool ->
- Bool
- end.
-
-%% Returns true if the Mnesia directory contains
-%% important files
-non_empty_dir() ->
- mnesia_lib:exists(mnesia_bup:fallback_bup()) or
- mnesia_lib:exists(mnesia_lib:tab2dmp(schema)) or
- mnesia_lib:exists(mnesia_lib:tab2dat(schema)).
-
-%%----------------------------------------------------------------------
-%% Func: handle_call/3
-%% Returns: {reply, Reply, State} |
-%% {reply, Reply, State, Timeout} |
-%% {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, Reply, State} | (terminate/2 is called)
-%%----------------------------------------------------------------------
-
-handle_call({mktab, Tab, Args}, _From, State) ->
- case catch ?ets_new_table(Tab, Args) of
- {'EXIT', ExitReason} ->
- Msg = "Cannot create ets table",
- Reason = {system_limit, Msg, Tab, Args, ExitReason},
- fatal("~p~n", [Reason]),
- {noreply, State};
- Reply ->
- {reply, Reply, State}
- end;
-
-handle_call({unsafe_mktab, Tab, Args}, _From, State) ->
- case catch ?ets_new_table(Tab, Args) of
- {'EXIT', ExitReason} ->
- {reply, {error, ExitReason}, State};
- Reply ->
- {reply, Reply, State}
- end;
-
-
-handle_call({open_dets, Tab, Args}, _From, State) ->
- case mnesia_lib:dets_sync_open(Tab, Args) of
- {ok, Tab} ->
- {reply, {ok, Tab}, State};
-
- {error, Reason} ->
- Msg = "Cannot open dets table",
- Error = {error, {Msg, Tab, Args, Reason}},
- fatal("~p~n", [Error]),
- {noreply, State}
- end;
-
-handle_call({unsafe_open_dets, Tab, Args}, _From, State) ->
- case mnesia_lib:dets_sync_open(Tab, Args) of
- {ok, Tab} ->
- {reply, {ok, Tab}, State};
- {error, Reason} ->
- {reply, {error,Reason}, State}
- end;
-
-handle_call({close_dets, Tab}, _From, State) ->
- case mnesia_lib:dets_sync_close(Tab) of
- ok ->
- {reply, ok, State};
- {error, Reason} ->
- Msg = "Cannot close dets table",
- Error = {error, {Msg, Tab, Reason}},
- fatal("~p~n", [Error]),
- {noreply, State}
- end;
-
-handle_call({unsafe_close_dets, Tab}, _From, State) ->
- mnesia_lib:dets_sync_close(Tab),
- {reply, ok, State};
-
-handle_call({open_log, Args}, _From, State) ->
- Res = disk_log:open([{notify, true}|Args]),
- {reply, Res, State};
-
-handle_call({reopen_log, Name, Fname, Head}, _From, State) ->
- case disk_log:reopen(Name, Fname, Head) of
- ok ->
- {reply, ok, State};
-
- {error, Reason} ->
- Msg = "Cannot rename disk_log file",
- Error = {error, {Msg, Name, Fname, Head, Reason}},
- fatal("~p~n", [Error]),
- {noreply, State}
- end;
-
-handle_call({close_log, Name}, _From, State) ->
- case disk_log:close(Name) of
- ok ->
- {reply, ok, State};
-
- {error, Reason} ->
- Msg = "Cannot close disk_log file",
- Error = {error, {Msg, Name, Reason}},
- fatal("~p~n", [Error]),
- {noreply, State}
- end;
-
-handle_call({unsafe_close_log, Name}, _From, State) ->
- disk_log:close(Name),
- {reply, ok, State};
-
-handle_call({negotiate_protocol, Mon, _Version, _Protocols}, _From, State)
- when State#state.tm_started == false ->
- State2 = State#state{early_connects = [node(Mon) | State#state.early_connects]},
- {reply, {node(), {reject, self(), uninitialized, uninitialized}}, State2};
-
-handle_call({negotiate_protocol, Mon, Version, Protocols}, From, State)
- when node(Mon) /= node() ->
- Protocol = protocol_version(),
- MyVersion = mnesia:system_info(version),
- case lists:member(Protocol, Protocols) of
- true ->
- accept_protocol(Mon, MyVersion, Protocol, From, State);
- false ->
- %% in this release we should be able to handle the previous
- %% protocol
- case hd(Protocols) of
- ?previous_protocol_version ->
- accept_protocol(Mon, MyVersion, ?previous_protocol_version, From, State);
- _ ->
- verbose("Connection with ~p rejected. "
- "version = ~p, protocols = ~p, "
- "expected version = ~p, expected protocol = ~p~n",
- [node(Mon), Version, Protocols, MyVersion, Protocol]),
- {reply, {node(), {reject, self(), MyVersion, Protocol}}, State}
- end
- end;
-
-handle_call(init, _From, State) ->
- net_kernel:monitor_nodes(true),
- EarlyNodes = State#state.early_connects,
- State2 = State#state{tm_started = true},
- {reply, EarlyNodes, State2};
-
-handle_call(Msg, _From, State) ->
- error("~p got unexpected call: ~p~n", [?MODULE, Msg]),
- {noreply, State}.
-
-accept_protocol(Mon, Version, Protocol, From, State) ->
- Reply = {node(), {accept, self(), Version, Protocol}},
- Node = node(Mon),
- Pending0 = State#state.pending_negotiators,
- Pending = lists:keydelete(Node, 1, Pending0),
- case lists:member(Node, State#state.going_down) of
- true ->
- %% Wait for the mnesia_down to be processed,
- %% before we reply
- P = Pending ++ [{Node, Mon, From, Reply}],
- {noreply, State#state{pending_negotiators = P}};
- false ->
- %% No need for wait
- link(Mon), %% link to remote Monitor
- case Protocol == protocol_version() of
- true ->
- set({protocol, Node}, {Protocol, false});
- false ->
- set({protocol, Node}, {Protocol, true})
- end,
- {reply, Reply, State#state{pending_negotiators = Pending}}
- end.
-
-%%----------------------------------------------------------------------
-%% Func: handle_cast/2
-%% Returns: {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State} (terminate/2 is called)
-%%----------------------------------------------------------------------
-
-handle_cast({mnesia_down, mnesia_controller, Node}, State) ->
- mnesia_tm:mnesia_down(Node),
- {noreply, State};
-
-handle_cast({mnesia_down, mnesia_tm, {Node, Pending}}, State) ->
- mnesia_locker:mnesia_down(Node, Pending),
- {noreply, State};
-
-handle_cast({mnesia_down, mnesia_locker, Node}, State) ->
- Down = {mnesia_down, Node},
- mnesia_lib:report_system_event(Down),
- GoingDown = lists:delete(Node, State#state.going_down),
- State2 = State#state{going_down = GoingDown},
- Pending = State#state.pending_negotiators,
- case lists:keysearch(Node, 1, Pending) of
- {value, {Node, Mon, ReplyTo, Reply}} ->
- %% Late reply to remote monitor
- link(Mon), %% link to remote Monitor
- gen_server:reply(ReplyTo, Reply),
- P2 = lists:keydelete(Node, 1,Pending),
- State3 = State2#state{pending_negotiators = P2},
- {noreply, State3};
- false ->
- %% No pending remote monitors
- {noreply, State2}
- end;
-
-handle_cast({disconnect, Node}, State) ->
- case rpc:call(Node, erlang, whereis, [?MODULE]) of
- {badrpc, _} ->
- ignore;
- RemoteMon when pid(RemoteMon) ->
- unlink(RemoteMon)
- end,
- {noreply, State};
-
-handle_cast({inconsistent_database, Context, Node}, State) ->
- Msg = {inconsistent_database, Context, Node},
- mnesia_lib:report_system_event(Msg),
- {noreply, State};
-
-handle_cast(Msg, State) ->
- error("~p got unexpected cast: ~p~n", [?MODULE, Msg]),
- {noreply, State}.
-
-%%----------------------------------------------------------------------
-%% Func: handle_info/2
-%% Returns: {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State} (terminate/2 is called)
-%%----------------------------------------------------------------------
-
-handle_info({'EXIT', Pid, R}, State) when Pid == State#state.supervisor ->
- dbg_out("~p was ~p by supervisor~n",[?MODULE, R]),
- {stop, R, State};
-
-handle_info({'EXIT', Pid, fatal}, State) when node(Pid) == node() ->
- dbg_out("~p got FATAL ERROR from: ~p~n",[?MODULE, Pid]),
- exit(State#state.supervisor, shutdown),
- {noreply, State};
-
-handle_info({'EXIT', Pid, Reason}, State) ->
- Node = node(Pid),
- if
- Node /= node() ->
- %% Remotly linked process died, assume that it was a mnesia_monitor
- mnesia_recover:mnesia_down(Node),
- mnesia_controller:mnesia_down(Node),
- {noreply, State#state{going_down = [Node | State#state.going_down]}};
- true ->
- %% We have probably got an exit signal from from
- %% disk_log or dets
- Hint = "Hint: check that the disk still is writable",
- Msg = {'EXIT', Pid, Reason},
- fatal("~p got unexpected info: ~p; ~p~n",
- [?MODULE, Msg, Hint])
- end;
-
-handle_info({nodeup, Node}, State) ->
- %% Ok, we are connected to yet another Erlang node
- %% Let's check if Mnesia is running there in order
- %% to detect if the network has been partitioned
- %% due to communication failure.
-
- HasDown = mnesia_recover:has_mnesia_down(Node),
- ImRunning = mnesia_lib:is_running(),
-
- if
- %% If I'm not running the test will be made later.
- HasDown == true, ImRunning == yes ->
- spawn_link(?MODULE, detect_partitioned_network, [self(), Node]);
- true ->
- ignore
- end,
- {noreply, State};
-
-handle_info({nodedown, _Node}, State) ->
- %% Ignore, we are only caring about nodeup's
- {noreply, State};
-
-handle_info({disk_log, _Node, Log, Info}, State) ->
- case Info of
- {truncated, _No} ->
- ok;
- _ ->
- mnesia_lib:important("Warning Log file ~p error reason ~s~n",
- [Log, disk_log:format_error(Info)])
- end,
- {noreply, State};
-
-handle_info(Msg, State) ->
- error("~p got unexpected info (~p): ~p~n", [?MODULE, State, Msg]).
-
-%%----------------------------------------------------------------------
-%% Func: terminate/2
-%% Purpose: Shutdown the server
-%% Returns: any (ignored by gen_server)
-%%----------------------------------------------------------------------
-terminate(Reason, State) ->
- terminate_proc(?MODULE, Reason, State).
-
-%%----------------------------------------------------------------------
-%% Func: code_change/3
-%% Purpose: Upgrade process when its code is to be changed
-%% Returns: {ok, NewState}
-%%----------------------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%%----------------------------------------------------------------------
-%%% Internal functions
-%%%----------------------------------------------------------------------
-
-process_config_args([]) ->
- ok;
-process_config_args([C|T]) ->
- V = get_env(C),
- dbg_out("Env ~p: ~p~n", [C, V]),
- mnesia_lib:set(C, V),
- process_config_args(T).
-
-set_env(E,Val) ->
- mnesia_lib:set(E, check_type(E,Val)),
- ok.
-
-get_env(E) ->
- case ?catch_val(E) of
- {'EXIT', _} ->
- case application:get_env(mnesia, E) of
- {ok, Val} ->
- check_type(E, Val);
- undefined ->
- check_type(E, default_env(E))
- end;
- Val ->
- Val
- end.
-
-env() ->
- [
- access_module,
- auto_repair,
- backup_module,
- debug,
- dir,
- dump_log_load_regulation,
- dump_log_time_threshold,
- dump_log_update_in_place,
- dump_log_write_threshold,
- embedded_mnemosyne,
- event_module,
- extra_db_nodes,
- ignore_fallback_at_startup,
- fallback_error_function,
- max_wait_for_decision,
- schema_location,
- core_dir
- ].
-
-default_env(access_module) ->
- mnesia;
-default_env(auto_repair) ->
- true;
-default_env(backup_module) ->
- mnesia_backup;
-default_env(debug) ->
- none;
-default_env(dir) ->
- Name = lists:concat(["Mnesia.", node()]),
- filename:absname(Name);
-default_env(dump_log_load_regulation) ->
- false;
-default_env(dump_log_time_threshold) ->
- timer:minutes(3);
-default_env(dump_log_update_in_place) ->
- true;
-default_env(dump_log_write_threshold) ->
- 1000;
-default_env(embedded_mnemosyne) ->
- false;
-default_env(event_module) ->
- mnesia_event;
-default_env(extra_db_nodes) ->
- [];
-default_env(ignore_fallback_at_startup) ->
- false;
-default_env(fallback_error_function) ->
- {mnesia, lkill};
-default_env(max_wait_for_decision) ->
- infinity;
-default_env(schema_location) ->
- opt_disc;
-default_env(core_dir) ->
- false.
-
-check_type(Env, Val) ->
- case catch do_check_type(Env, Val) of
- {'EXIT', _Reason} ->
- exit({bad_config, Env, Val});
- NewVal ->
- NewVal
- end.
-
-do_check_type(access_module, A) when atom(A) -> A;
-do_check_type(auto_repair, B) -> bool(B);
-do_check_type(backup_module, B) when atom(B) -> B;
-do_check_type(debug, debug) -> debug;
-do_check_type(debug, false) -> none;
-do_check_type(debug, none) -> none;
-do_check_type(debug, trace) -> trace;
-do_check_type(debug, true) -> debug;
-do_check_type(debug, verbose) -> verbose;
-do_check_type(dir, V) -> filename:absname(V);
-do_check_type(dump_log_load_regulation, B) -> bool(B);
-do_check_type(dump_log_time_threshold, I) when integer(I), I > 0 -> I;
-do_check_type(dump_log_update_in_place, B) -> bool(B);
-do_check_type(dump_log_write_threshold, I) when integer(I), I > 0 -> I;
-do_check_type(event_module, A) when atom(A) -> A;
-do_check_type(ignore_fallback_at_startup, B) -> bool(B);
-do_check_type(fallback_error_function, {Mod, Func})
- when atom(Mod), atom(Func) -> {Mod, Func};
-do_check_type(embedded_mnemosyne, B) -> bool(B);
-do_check_type(extra_db_nodes, L) when list(L) ->
- Fun = fun(N) when N == node() -> false;
- (A) when atom(A) -> true
- end,
- lists:filter(Fun, L);
-do_check_type(max_wait_for_decision, infinity) -> infinity;
-do_check_type(max_wait_for_decision, I) when integer(I), I > 0 -> I;
-do_check_type(schema_location, M) -> media(M);
-do_check_type(core_dir, "false") -> false;
-do_check_type(core_dir, false) -> false;
-do_check_type(core_dir, Dir) when list(Dir) -> Dir.
-
-
-bool(true) -> true;
-bool(false) -> false.
-
-media(disc) -> disc;
-media(opt_disc) -> opt_disc;
-media(ram) -> ram.
-
-patch_env(Env, Val) ->
- case catch do_check_type(Env, Val) of
- {'EXIT', _Reason} ->
- {error, {bad_type, Env, Val}};
- NewVal ->
- application_controller:set_env(mnesia, Env, NewVal),
- NewVal
- end.
-
-detect_partitioned_network(Mon, Node) ->
- GoodNodes = negotiate_protocol([Node]),
- detect_inconcistency(GoodNodes, running_partitioned_network),
- unlink(Mon),
- exit(normal).
-
-detect_inconcistency([], _Context) ->
- ok;
-detect_inconcistency(Nodes, Context) ->
- Downs = [N || N <- Nodes, mnesia_recover:has_mnesia_down(N)],
- {Replies, _BadNodes} =
- rpc:multicall(Downs, ?MODULE, has_remote_mnesia_down, [node()]),
- report_inconsistency(Replies, Context, ok).
-
-has_remote_mnesia_down(Node) ->
- HasDown = mnesia_recover:has_mnesia_down(Node),
- Master = mnesia_recover:get_master_nodes(schema),
- if
- HasDown == true, Master == [] ->
- {true, node()};
- true ->
- {false, node()}
- end.
-
-report_inconsistency([{true, Node} | Replies], Context, _Status) ->
- %% Oops, Mnesia is already running on the
- %% other node AND we both regard each
- %% other as down. The database is
- %% potentially inconsistent and we has to
- %% do tell the applications about it, so
- %% they may perform some clever recovery
- %% action.
- Msg = {inconsistent_database, Context, Node},
- mnesia_lib:report_system_event(Msg),
- report_inconsistency(Replies, Context, inconsistent_database);
-report_inconsistency([{false, _Node} | Replies], Context, Status) ->
- report_inconsistency(Replies, Context, Status);
-report_inconsistency([{badrpc, _Reason} | Replies], Context, Status) ->
- report_inconsistency(Replies, Context, Status);
-report_inconsistency([], _Context, Status) ->
- Status.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_recover.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_recover.erl
deleted file mode 100644
index b3e8f1c386..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_recover.erl
+++ /dev/null
@@ -1,1175 +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: mnesia_recover.erl,v 1.1 2008/12/17 09:53:39 mikpe Exp $
-%%
--module(mnesia_recover).
-
--behaviour(gen_server).
-
--export([
- allow_garb/0,
- call/1,
- connect_nodes/1,
- disconnect/1,
- dump_decision_tab/0,
- get_master_node_info/0,
- get_master_node_tables/0,
- get_master_nodes/1,
- get_mnesia_downs/0,
- has_mnesia_down/1,
- incr_trans_tid_serial/0,
- init/0,
- log_decision/1,
- log_master_nodes/3,
- log_mnesia_down/1,
- log_mnesia_up/1,
- mnesia_down/1,
- note_decision/2,
- note_log_decision/2,
- outcome/2,
- start/0,
- start_garb/0,
- still_pending/1,
- sync_trans_tid_serial/1,
- wait_for_decision/2,
- what_happened/3
- ]).
-
-%% gen_server callbacks
--export([init/1,
- handle_call/3,
- handle_cast/2,
- handle_info/2,
- terminate/2,
- code_change/3
- ]).
-
-
--include("mnesia.hrl").
--import(mnesia_lib, [set/2, verbose/2, error/2, fatal/2]).
-
--record(state, {supervisor,
- unclear_pid,
- unclear_decision,
- unclear_waitfor,
- tm_queue_len = 0,
- initiated = false,
- early_msgs = []
- }).
-
-%%-define(DBG(F, A), mnesia:report_event(list_to_atom(lists:flatten(io_lib:format(F, A))))).
-%%-define(DBG(F, A), io:format("DBG: " ++ F, A)).
-
--record(transient_decision, {tid, outcome}).
-
-start() ->
- gen_server:start_link({local, ?MODULE}, ?MODULE, [self()],
- [{timeout, infinity}
- %%, {debug, [trace]}
- ]).
-
-init() ->
- call(init).
-
-start_garb() ->
- Pid = whereis(mnesia_recover),
- {ok, _} = timer:send_interval(timer:minutes(2), Pid, garb_decisions),
- {ok, _} = timer:send_interval(timer:seconds(10), Pid, check_overload).
-
-allow_garb() ->
- cast(allow_garb).
-
-
-%% The transaction log has either been swiched (latest -> previous) or
-%% there is nothing to be dumped. This means that the previous
-%% transaction log only may contain commit records which refers to
-%% transactions noted in the last two of the 'Prev' tables. All other
-%% tables may now be garbed by 'garb_decisions' (after 2 minutes).
-%% Max 10 tables are kept.
-do_allow_garb() ->
- %% The order of the following stuff is important!
- Curr = val(latest_transient_decision),
- Old = val(previous_transient_decisions),
- Next = create_transient_decision(),
- {Prev, ReallyOld} = sublist([Curr | Old], 10, []),
- [?ets_delete_table(Tab) || Tab <- ReallyOld],
- set(previous_transient_decisions, Prev),
- set(latest_transient_decision, Next).
-
-sublist([H|R], N, Acc) when N > 0 ->
- sublist(R, N-1, [H| Acc]);
-sublist(List, _N, Acc) ->
- {lists:reverse(Acc), List}.
-
-do_garb_decisions() ->
- case val(previous_transient_decisions) of
- [First, Second | Rest] ->
- set(previous_transient_decisions, [First, Second]),
- [?ets_delete_table(Tab) || Tab <- Rest];
- _ ->
- ignore
- end.
-
-connect_nodes([]) ->
- [];
-connect_nodes(Ns) ->
- %% Determine which nodes we should try to connect
- AlreadyConnected = val(recover_nodes),
- {_, Nodes} = mnesia_lib:search_delete(node(), Ns),
- Check = Nodes -- AlreadyConnected,
- GoodNodes = mnesia_monitor:negotiate_protocol(Check),
- if
- GoodNodes == [] ->
- %% No good noodes to connect to
- ignore;
- true ->
- %% Now we have agreed upon a protocol with some new nodes
- %% and we may use them when we recover transactions
- mnesia_lib:add_list(recover_nodes, GoodNodes),
- cast({announce_all, GoodNodes}),
- case get_master_nodes(schema) of
- [] ->
- Context = starting_partitioned_network,
- mnesia_monitor:detect_inconcistency(GoodNodes, Context);
- _ -> %% If master_nodes is set ignore old inconsistencies
- ignore
- end
- end,
- {GoodNodes, AlreadyConnected}.
-
-disconnect(Node) ->
- mnesia_monitor:disconnect(Node),
- mnesia_lib:del(recover_nodes, Node).
-
-val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
- Value -> Value
- end.
-
-call(Msg) ->
- Pid = whereis(?MODULE),
- case Pid of
- undefined ->
- {error, {node_not_running, node()}};
- Pid ->
- link(Pid),
- Res = gen_server:call(Pid, Msg, infinity),
- unlink(Pid),
-
- %% We get an exit signal if server dies
- receive
- {'EXIT', Pid, _Reason} ->
- {error, {node_not_running, node()}}
- after 0 ->
- ignore
- end,
- Res
- end.
-
-multicall(Nodes, Msg) ->
- rpc:multicall(Nodes, ?MODULE, call, [Msg]).
-
-cast(Msg) ->
- case whereis(?MODULE) of
- undefined -> ignore;
- Pid -> gen_server:cast(Pid, Msg)
- end.
-
-abcast(Nodes, Msg) ->
- gen_server:abcast(Nodes, ?MODULE, Msg).
-
-note_decision(Tid, Outcome) ->
- Tab = val(latest_transient_decision),
- ?ets_insert(Tab, #transient_decision{tid = Tid, outcome = Outcome}).
-
-note_up(Node, _Date, _Time) ->
- ?ets_delete(mnesia_decision, Node).
-
-note_down(Node, Date, Time) ->
- ?ets_insert(mnesia_decision, {mnesia_down, Node, Date, Time}).
-
-note_master_nodes(Tab, []) ->
- ?ets_delete(mnesia_decision, Tab);
-note_master_nodes(Tab, Nodes) when list(Nodes) ->
- Master = {master_nodes, Tab, Nodes},
- ?ets_insert(mnesia_decision, Master).
-
-note_outcome(D) when D#decision.disc_nodes == [] ->
-%% ?DBG("~w: note_tmp_decision: ~w~n", [node(), D]),
- note_decision(D#decision.tid, filter_outcome(D#decision.outcome)),
- ?ets_delete(mnesia_decision, D#decision.tid);
-note_outcome(D) when D#decision.disc_nodes /= [] ->
-%% ?DBG("~w: note_decision: ~w~n", [node(), D]),
- ?ets_insert(mnesia_decision, D).
-
-log_decision(D) when D#decision.outcome /= unclear ->
- OldD = decision(D#decision.tid),
- MergedD = merge_decisions(node(), OldD, D),
- do_log_decision(MergedD, true);
-log_decision(D) ->
- do_log_decision(D, false).
-
-do_log_decision(D, DoTell) ->
- RamNs = D#decision.ram_nodes,
- DiscNs = D#decision.disc_nodes -- [node()],
- Outcome = D#decision.outcome,
- D2 =
- case Outcome of
- aborted -> D#decision{disc_nodes = DiscNs};
- committed -> D#decision{disc_nodes = DiscNs};
- _ -> D
- end,
- note_outcome(D2),
- case mnesia_monitor:use_dir() of
- true ->
- mnesia_log:append(latest_log, D2),
- if
- DoTell == true, Outcome /= unclear ->
- tell_im_certain(DiscNs, D2),
- tell_im_certain(RamNs, D2);
- true ->
- ignore
- end;
- false ->
- ignore
- end.
-
-tell_im_certain([], _D) ->
- ignore;
-tell_im_certain(Nodes, D) ->
- Msg = {im_certain, node(), D},
-%% ?DBG("~w: ~w: tell: ~w~n", [node(), Msg, Nodes]),
- abcast(Nodes, Msg).
-
-log_mnesia_up(Node) ->
- call({log_mnesia_up, Node}).
-
-log_mnesia_down(Node) ->
- call({log_mnesia_down, Node}).
-
-get_mnesia_downs() ->
- Tab = mnesia_decision,
- Pat = {mnesia_down, '_', '_', '_'},
- Downs = ?ets_match_object(Tab, Pat),
- [Node || {mnesia_down, Node, _Date, _Time} <- Downs].
-
-%% Check if we have got a mnesia_down from Node
-has_mnesia_down(Node) ->
- case ?ets_lookup(mnesia_decision, Node) of
- [{mnesia_down, Node, _Date, _Time}] ->
- true;
- [] ->
- false
- end.
-
-mnesia_down(Node) ->
- case ?catch_val(recover_nodes) of
- {'EXIT', _} ->
- %% Not started yet
- ignore;
- _ ->
- mnesia_lib:del(recover_nodes, Node),
- cast({mnesia_down, Node})
- end.
-
-log_master_nodes(Args, UseDir, IsRunning) ->
- if
- IsRunning == yes ->
- log_master_nodes2(Args, UseDir, IsRunning, ok);
- UseDir == false ->
- ok;
- true ->
- Name = latest_log,
- Fname = mnesia_log:latest_log_file(),
- Exists = mnesia_lib:exists(Fname),
- Repair = mnesia:system_info(auto_repair),
- OpenArgs = [{file, Fname}, {name, Name}, {repair, Repair}],
- case disk_log:open(OpenArgs) of
- {ok, Name} ->
- log_master_nodes2(Args, UseDir, IsRunning, ok);
- {repaired, Name, {recovered, _R}, {badbytes, _B}}
- when Exists == true ->
- log_master_nodes2(Args, UseDir, IsRunning, ok);
- {repaired, Name, {recovered, _R}, {badbytes, _B}}
- when Exists == false ->
- mnesia_log:write_trans_log_header(),
- log_master_nodes2(Args, UseDir, IsRunning, ok);
- {error, Reason} ->
- {error, Reason}
- end
- end.
-
-log_master_nodes2([{Tab, Nodes} | Tail], UseDir, IsRunning, WorstRes) ->
- Res =
- case IsRunning of
- yes ->
- R = call({log_master_nodes, Tab, Nodes, UseDir, IsRunning}),
- mnesia_controller:master_nodes_updated(Tab, Nodes),
- R;
- _ ->
- do_log_master_nodes(Tab, Nodes, UseDir, IsRunning)
- end,
- case Res of
- ok ->
- log_master_nodes2(Tail, UseDir, IsRunning, WorstRes);
- {error, Reason} ->
- log_master_nodes2(Tail, UseDir, IsRunning, {error, Reason})
- end;
-log_master_nodes2([], _UseDir, IsRunning, WorstRes) ->
- case IsRunning of
- yes ->
- WorstRes;
- _ ->
- disk_log:close(latest_log),
- WorstRes
- end.
-
-get_master_node_info() ->
- Tab = mnesia_decision,
- Pat = {master_nodes, '_', '_'},
- case catch mnesia_lib:db_match_object(ram_copies,Tab, Pat) of
- {'EXIT', _} ->
- [];
- Masters ->
- Masters
- end.
-
-get_master_node_tables() ->
- Masters = get_master_node_info(),
- [Tab || {master_nodes, Tab, _Nodes} <- Masters].
-
-get_master_nodes(Tab) ->
- case catch ?ets_lookup_element(mnesia_decision, Tab, 3) of
- {'EXIT', _} -> [];
- Nodes -> Nodes
- end.
-
-%% Determine what has happened to the transaction
-what_happened(Tid, Protocol, Nodes) ->
- Default =
- case Protocol of
- asym_trans -> aborted;
- _ -> unclear %% sym_trans and sync_sym_trans
- end,
- This = node(),
- case lists:member(This, Nodes) of
- true ->
- {ok, Outcome} = call({what_happened, Default, Tid}),
- Others = Nodes -- [This],
- case filter_outcome(Outcome) of
- unclear -> what_happened_remotely(Tid, Default, Others);
- aborted -> aborted;
- committed -> committed
- end;
- false ->
- what_happened_remotely(Tid, Default, Nodes)
- end.
-
-what_happened_remotely(Tid, Default, Nodes) ->
- {Replies, _} = multicall(Nodes, {what_happened, Default, Tid}),
- check_what_happened(Replies, 0, 0).
-
-check_what_happened([H | T], Aborts, Commits) ->
- case H of
- {ok, R} ->
- case filter_outcome(R) of
- committed ->
- check_what_happened(T, Aborts, Commits + 1);
- aborted ->
- check_what_happened(T, Aborts + 1, Commits);
- unclear ->
- check_what_happened(T, Aborts, Commits)
- end;
- {error, _} ->
- check_what_happened(T, Aborts, Commits);
- {badrpc, _} ->
- check_what_happened(T, Aborts, Commits)
- end;
-check_what_happened([], Aborts, Commits) ->
- if
- Aborts == 0, Commits == 0 -> aborted; % None of the active nodes knows
- Aborts > 0 -> aborted; % Someody has aborted
- Aborts == 0, Commits > 0 -> committed % All has committed
- end.
-
-%% Determine what has happened to the transaction
-%% and possibly wait forever for the decision.
-wait_for_decision(presume_commit, _InitBy) ->
- %% sym_trans
- {{presume_commit, self()}, committed};
-
-wait_for_decision(D, InitBy) when D#decision.outcome == presume_abort ->
- %% asym_trans
- Tid = D#decision.tid,
- Outcome = filter_outcome(outcome(Tid, D#decision.outcome)),
- if
- Outcome /= unclear ->
- {Tid, Outcome};
-
- InitBy /= startup ->
- %% Wait a while for active transactions
- %% to end and try again
- timer:sleep(200),
- wait_for_decision(D, InitBy);
-
- InitBy == startup ->
- {ok, Res} = call({wait_for_decision, D}),
- {Tid, Res}
- end.
-
-still_pending([Tid | Pending]) ->
- case filter_outcome(outcome(Tid, unclear)) of
- unclear -> [Tid | still_pending(Pending)];
- _ -> still_pending(Pending)
- end;
-still_pending([]) ->
- [].
-
-load_decision_tab() ->
- Cont = mnesia_log:open_decision_tab(),
- load_decision_tab(Cont, load_decision_tab),
- mnesia_log:close_decision_tab().
-
-load_decision_tab(eof, _InitBy) ->
- ok;
-load_decision_tab(Cont, InitBy) ->
- case mnesia_log:chunk_decision_tab(Cont) of
- {Cont2, Decisions} ->
- note_log_decisions(Decisions, InitBy),
- load_decision_tab(Cont2, InitBy);
- eof ->
- ok
- end.
-
-%% Dumps DECISION.LOG and PDECISION.LOG and removes them.
-%% From now on all decisions are logged in the transaction log file
-convert_old() ->
- HasOldStuff =
- mnesia_lib:exists(mnesia_log:previous_decision_log_file()) or
- mnesia_lib:exists(mnesia_log:decision_log_file()),
- case HasOldStuff of
- true ->
- mnesia_log:open_decision_log(),
- dump_decision_log(startup),
- dump_decision_log(startup),
- mnesia_log:close_decision_log(),
- Latest = mnesia_log:decision_log_file(),
- ok = file:delete(Latest);
- false ->
- ignore
- end.
-
-dump_decision_log(InitBy) ->
- %% Assumed to be run in transaction log dumper process
- Cont = mnesia_log:prepare_decision_log_dump(),
- perform_dump_decision_log(Cont, InitBy).
-
-perform_dump_decision_log(eof, _InitBy) ->
- confirm_decision_log_dump();
-perform_dump_decision_log(Cont, InitBy) when InitBy == startup ->
- case mnesia_log:chunk_decision_log(Cont) of
- {Cont2, Decisions} ->
- note_log_decisions(Decisions, InitBy),
- perform_dump_decision_log(Cont2, InitBy);
- eof ->
- confirm_decision_log_dump()
- end;
-perform_dump_decision_log(_Cont, _InitBy) ->
- confirm_decision_log_dump().
-
-confirm_decision_log_dump() ->
- dump_decision_tab(),
- mnesia_log:confirm_decision_log_dump().
-
-dump_decision_tab() ->
- Tab = mnesia_decision,
- All = mnesia_lib:db_match_object(ram_copies,Tab, '_'),
- mnesia_log:save_decision_tab({decision_list, All}).
-
-note_log_decisions([What | Tail], InitBy) ->
- note_log_decision(What, InitBy),
- note_log_decisions(Tail, InitBy);
-note_log_decisions([], _InitBy) ->
- ok.
-
-note_log_decision(NewD, InitBy) when NewD#decision.outcome == pre_commit ->
- note_log_decision(NewD#decision{outcome = unclear}, InitBy);
-
-note_log_decision(NewD, _InitBy) when record(NewD, decision) ->
- Tid = NewD#decision.tid,
- sync_trans_tid_serial(Tid),
- OldD = decision(Tid),
- MergedD = merge_decisions(node(), OldD, NewD),
- note_outcome(MergedD);
-
-note_log_decision({trans_tid, serial, _Serial}, startup) ->
- ignore;
-
-note_log_decision({trans_tid, serial, Serial}, _InitBy) ->
- sync_trans_tid_serial(Serial);
-
-note_log_decision({mnesia_up, Node, Date, Time}, _InitBy) ->
- note_up(Node, Date, Time);
-
-note_log_decision({mnesia_down, Node, Date, Time}, _InitBy) ->
- note_down(Node, Date, Time);
-
-note_log_decision({master_nodes, Tab, Nodes}, _InitBy) ->
- note_master_nodes(Tab, Nodes);
-
-note_log_decision(H, _InitBy) when H#log_header.log_kind == decision_log ->
- V = mnesia_log:decision_log_version(),
- if
- H#log_header.log_version == V->
- ok;
- H#log_header.log_version == "2.0" ->
- verbose("Accepting an old version format of decision log: ~p~n",
- [V]),
- ok;
- true ->
- fatal("Bad version of decision log: ~p~n", [H])
- end;
-
-note_log_decision(H, _InitBy) when H#log_header.log_kind == decision_tab ->
- V = mnesia_log:decision_tab_version(),
- if
- V == H#log_header.log_version ->
- ok;
- true ->
- fatal("Bad version of decision tab: ~p~n", [H])
- end;
-note_log_decision({decision_list, ItemList}, InitBy) ->
- note_log_decisions(ItemList, InitBy);
-note_log_decision(BadItem, InitBy) ->
- exit({"Bad decision log item", BadItem, InitBy}).
-
-trans_tid_serial() ->
- ?ets_lookup_element(mnesia_decision, serial, 3).
-
-set_trans_tid_serial(Val) ->
- ?ets_insert(mnesia_decision, {trans_tid, serial, Val}).
-
-incr_trans_tid_serial() ->
- ?ets_update_counter(mnesia_decision, serial, 1).
-
-sync_trans_tid_serial(ThatCounter) when integer(ThatCounter) ->
- ThisCounter = trans_tid_serial(),
- if
- ThatCounter > ThisCounter ->
- set_trans_tid_serial(ThatCounter + 1);
- true ->
- ignore
- end;
-sync_trans_tid_serial(Tid) ->
- sync_trans_tid_serial(Tid#tid.counter).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%% Callback functions from gen_server
-
-%%----------------------------------------------------------------------
-%% Func: init/1
-%% Returns: {ok, State} |
-%% {ok, State, Timeout} |
-%% {stop, Reason}
-%%----------------------------------------------------------------------
-init([Parent]) ->
- process_flag(trap_exit, true),
- mnesia_lib:verbose("~p starting: ~p~n", [?MODULE, self()]),
- set(latest_transient_decision, create_transient_decision()),
- set(previous_transient_decisions, []),
- set(recover_nodes, []),
- State = #state{supervisor = Parent},
- {ok, State}.
-
-create_transient_decision() ->
- ?ets_new_table(mnesia_transient_decision, [{keypos, 2}, set, public]).
-
-%%----------------------------------------------------------------------
-%% Func: handle_call/3
-%% Returns: {reply, Reply, State} |
-%% {reply, Reply, State, Timeout} |
-%% {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, Reply, State} | (terminate/2 is called)
-%%----------------------------------------------------------------------
-
-handle_call(init, From, State) when State#state.initiated == false ->
- Args = [{keypos, 2}, set, public, named_table],
- case mnesia_monitor:use_dir() of
- true ->
- ?ets_new_table(mnesia_decision, Args),
- set_trans_tid_serial(0),
- TabFile = mnesia_log:decision_tab_file(),
- case mnesia_lib:exists(TabFile) of
- true ->
- load_decision_tab();
- false ->
- ignore
- end,
- convert_old(),
- mnesia_dumper:opt_dump_log(scan_decisions);
- false ->
- ?ets_new_table(mnesia_decision, Args),
- set_trans_tid_serial(0)
- end,
- handle_early_msgs(State, From);
-
-handle_call(Msg, From, State) when State#state.initiated == false ->
- %% Buffer early messages
- Msgs = State#state.early_msgs,
- {noreply, State#state{early_msgs = [{call, Msg, From} | Msgs]}};
-
-handle_call({what_happened, Default, Tid}, _From, State) ->
- sync_trans_tid_serial(Tid),
- Outcome = outcome(Tid, Default),
- {reply, {ok, Outcome}, State};
-
-handle_call({wait_for_decision, D}, From, State) ->
- Recov = val(recover_nodes),
- AliveRam = (mnesia_lib:intersect(D#decision.ram_nodes, Recov) -- [node()]),
- RemoteDisc = D#decision.disc_nodes -- [node()],
- if
- AliveRam == [], RemoteDisc == [] ->
- %% No more else to wait for and we may safely abort
- {reply, {ok, aborted}, State};
- true ->
- verbose("Transaction ~p is unclear. "
- "Wait for disc nodes: ~w ram: ~w~n",
- [D#decision.tid, RemoteDisc, AliveRam]),
- AliveDisc = mnesia_lib:intersect(RemoteDisc, Recov),
- Msg = {what_decision, node(), D},
- abcast(AliveRam, Msg),
- abcast(AliveDisc, Msg),
- case val(max_wait_for_decision) of
- infinity ->
- ignore;
- MaxWait ->
- ForceMsg = {force_decision, D#decision.tid},
- {ok, _} = timer:send_after(MaxWait, ForceMsg)
- end,
- State2 = State#state{unclear_pid = From,
- unclear_decision = D,
- unclear_waitfor = (RemoteDisc ++ AliveRam)},
- {noreply, State2}
- end;
-
-handle_call({log_mnesia_up, Node}, _From, State) ->
- do_log_mnesia_up(Node),
- {reply, ok, State};
-
-handle_call({log_mnesia_down, Node}, _From, State) ->
- do_log_mnesia_down(Node),
- {reply, ok, State};
-
-handle_call({log_master_nodes, Tab, Nodes, UseDir, IsRunning}, _From, State) ->
- do_log_master_nodes(Tab, Nodes, UseDir, IsRunning),
- {reply, ok, State};
-
-handle_call(Msg, _From, State) ->
- error("~p got unexpected call: ~p~n", [?MODULE, Msg]),
- {noreply, State}.
-
-do_log_mnesia_up(Node) ->
- Yoyo = {mnesia_up, Node, Date = date(), Time = time()},
- case mnesia_monitor:use_dir() of
- true ->
- mnesia_log:append(latest_log, Yoyo),
- disk_log:sync(latest_log);
- false ->
- ignore
- end,
- note_up(Node, Date, Time).
-
-do_log_mnesia_down(Node) ->
- Yoyo = {mnesia_down, Node, Date = date(), Time = time()},
- case mnesia_monitor:use_dir() of
- true ->
- mnesia_log:append(latest_log, Yoyo),
- disk_log:sync(latest_log);
- false ->
- ignore
- end,
- note_down(Node, Date, Time).
-
-do_log_master_nodes(Tab, Nodes, UseDir, IsRunning) ->
- Master = {master_nodes, Tab, Nodes},
- Res =
- case UseDir of
- true ->
- LogRes = mnesia_log:append(latest_log, Master),
- disk_log:sync(latest_log),
- LogRes;
- false ->
- ok
- end,
- case IsRunning of
- yes ->
- note_master_nodes(Tab, Nodes);
- _NotRunning ->
- ignore
- end,
- Res.
-
-%%----------------------------------------------------------------------
-%% Func: handle_cast/2
-%% Returns: {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State} (terminate/2 is called)
-%%----------------------------------------------------------------------
-
-handle_cast(Msg, State) when State#state.initiated == false ->
- %% Buffer early messages
- Msgs = State#state.early_msgs,
- {noreply, State#state{early_msgs = [{cast, Msg} | Msgs]}};
-
-handle_cast({im_certain, Node, NewD}, State) ->
- OldD = decision(NewD#decision.tid),
- MergedD = merge_decisions(Node, OldD, NewD),
- do_log_decision(MergedD, false),
- {noreply, State};
-
-handle_cast(allow_garb, State) ->
- do_allow_garb(),
- {noreply, State};
-
-handle_cast({decisions, Node, Decisions}, State) ->
- mnesia_lib:add(recover_nodes, Node),
- State2 = add_remote_decisions(Node, Decisions, State),
- {noreply, State2};
-
-handle_cast({what_decision, Node, OtherD}, State) ->
- Tid = OtherD#decision.tid,
- sync_trans_tid_serial(Tid),
- Decision =
- case decision(Tid) of
- no_decision -> OtherD;
- MyD when record(MyD, decision) -> MyD
- end,
- announce([Node], [Decision], [], true),
- {noreply, State};
-
-handle_cast({mnesia_down, Node}, State) ->
- case State#state.unclear_decision of
- undefined ->
- {noreply, State};
- D ->
- case lists:member(Node, D#decision.ram_nodes) of
- false ->
- {noreply, State};
- true ->
- State2 = add_remote_decision(Node, D, State),
- {noreply, State2}
- end
- end;
-
-handle_cast({announce_all, Nodes}, State) ->
- announce_all(Nodes, tabs()),
- {noreply, State};
-
-handle_cast(Msg, State) ->
- error("~p got unexpected cast: ~p~n", [?MODULE, Msg]),
- {noreply, State}.
-
-%%----------------------------------------------------------------------
-%% Func: handle_info/2
-%% Returns: {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State} (terminate/2 is called)
-%%----------------------------------------------------------------------
-
-%% No need for buffering
-%% handle_info(Msg, State) when State#state.initiated == false ->
-%% %% Buffer early messages
-%% Msgs = State#state.early_msgs,
-%% {noreply, State#state{early_msgs = [{info, Msg} | Msgs]}};
-
-handle_info(check_overload, S) ->
- %% Time to check if mnesia_tm is overloaded
- case whereis(mnesia_tm) of
- Pid when pid(Pid) ->
-
- Threshold = 100,
- Prev = S#state.tm_queue_len,
- {message_queue_len, Len} =
- process_info(Pid, message_queue_len),
- if
- Len > Threshold, Prev > Threshold ->
- What = {mnesia_tm, message_queue_len, [Prev, Len]},
- mnesia_lib:report_system_event({mnesia_overload, What}),
- {noreply, S#state{tm_queue_len = 0}};
-
- Len > Threshold ->
- {noreply, S#state{tm_queue_len = Len}};
-
- true ->
- {noreply, S#state{tm_queue_len = 0}}
- end;
- undefined ->
- {noreply, S}
- end;
-
-handle_info(garb_decisions, State) ->
- do_garb_decisions(),
- {noreply, State};
-
-handle_info({force_decision, Tid}, State) ->
- %% Enforce a transaction recovery decision,
- %% if we still are waiting for the outcome
-
- case State#state.unclear_decision of
- U when U#decision.tid == Tid ->
- verbose("Decided to abort transaction ~p since "
- "max_wait_for_decision has been exceeded~n",
- [Tid]),
- D = U#decision{outcome = aborted},
- State2 = add_remote_decision(node(), D, State),
- {noreply, State2};
- _ ->
- {noreply, State}
- end;
-
-handle_info({'EXIT', Pid, R}, State) when Pid == State#state.supervisor ->
- mnesia_lib:dbg_out("~p was ~p~n",[?MODULE, R]),
- {stop, shutdown, State};
-
-handle_info(Msg, State) ->
- error("~p got unexpected info: ~p~n", [?MODULE, Msg]),
- {noreply, State}.
-
-%%----------------------------------------------------------------------
-%% Func: terminate/2
-%% Purpose: Shutdown the server
-%% Returns: any (ignored by gen_server)
-%%----------------------------------------------------------------------
-
-terminate(Reason, State) ->
- mnesia_monitor:terminate_proc(?MODULE, Reason, State).
-
-%%----------------------------------------------------------------------
-%% Func: code_change/3
-%% Purpose: Upgrade process when its code is to be changed
-%% Returns: {ok, NewState}
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%%----------------------------------------------------------------------
-%%% Internal functions
-%%%----------------------------------------------------------------------
-
-handle_early_msgs(State, From) ->
- Res = do_handle_early_msgs(State#state.early_msgs,
- State#state{early_msgs = [],
- initiated = true}),
- gen_server:reply(From, ok),
- Res.
-
-do_handle_early_msgs([Msg | Msgs], State) ->
- %% The messages are in reverted order
- case do_handle_early_msgs(Msgs, State) of
- {stop, Reason, Reply, State2} ->
- {stop, Reason, Reply, State2};
- {stop, Reason, State2} ->
- {stop, Reason, State2};
- {noreply, State2} ->
- handle_early_msg(Msg, State2)
- end;
-
-do_handle_early_msgs([], State) ->
- {noreply, State}.
-
-handle_early_msg({call, Msg, From}, State) ->
- case handle_call(Msg, From, State) of
- {reply, R, S} ->
- gen_server:reply(From, R),
- {noreply, S};
- Other ->
- Other
- end;
-handle_early_msg({cast, Msg}, State) ->
- handle_cast(Msg, State);
-handle_early_msg({info, Msg}, State) ->
- handle_info(Msg, State).
-
-tabs() ->
- Curr = val(latest_transient_decision), % Do not miss any trans even
- Prev = val(previous_transient_decisions), % if the tabs are switched
- [Curr, mnesia_decision | Prev]. % Ordered by hit probability
-
-decision(Tid) ->
- decision(Tid, tabs()).
-
-decision(Tid, [Tab | Tabs]) ->
- case catch ?ets_lookup(Tab, Tid) of
- [D] when record(D, decision) ->
- D;
- [C] when record(C, transient_decision) ->
- #decision{tid = C#transient_decision.tid,
- outcome = C#transient_decision.outcome,
- disc_nodes = [],
- ram_nodes = []
- };
- [] ->
- decision(Tid, Tabs);
- {'EXIT', _} ->
- %% Recently switched transient decision table
- decision(Tid, Tabs)
- end;
-decision(_Tid, []) ->
- no_decision.
-
-outcome(Tid, Default) ->
- outcome(Tid, Default, tabs()).
-
-outcome(Tid, Default, [Tab | Tabs]) ->
- case catch ?ets_lookup_element(Tab, Tid, 3) of
- {'EXIT', _} ->
- outcome(Tid, Default, Tabs);
- Val ->
- Val
- end;
-outcome(_Tid, Default, []) ->
- Default.
-
-filter_outcome(Val) ->
- case Val of
- unclear -> unclear;
- aborted -> aborted;
- presume_abort -> aborted;
- committed -> committed;
- pre_commit -> unclear
- end.
-
-filter_aborted(D) when D#decision.outcome == presume_abort ->
- D#decision{outcome = aborted};
-filter_aborted(D) ->
- D.
-
-%% Merge old decision D with new (probably remote) decision
-merge_decisions(Node, D, NewD0) ->
- NewD = filter_aborted(NewD0),
- if
- D == no_decision, node() /= Node ->
- %% We did not know anything about this txn
- NewD#decision{disc_nodes = []};
- D == no_decision ->
- NewD;
- record(D, decision) ->
- DiscNs = D#decision.disc_nodes -- ([node(), Node]),
- OldD = filter_aborted(D#decision{disc_nodes = DiscNs}),
-%% mnesia_lib:dbg_out("merge ~w: NewD = ~w~n D = ~w~n OldD = ~w~n",
-%% [Node, NewD, D, OldD]),
- if
- OldD#decision.outcome == unclear,
- NewD#decision.outcome == unclear ->
- D;
-
- OldD#decision.outcome == NewD#decision.outcome ->
- %% We have come to the same decision
- OldD;
-
- OldD#decision.outcome == committed,
- NewD#decision.outcome == aborted ->
- %% Interesting! We have already committed,
- %% but someone else has aborted. Now we
- %% have a nice little inconcistency. The
- %% other guy (or some one else) has
- %% enforced a recovery decision when
- %% max_wait_for_decision was exceeded.
- %% We will pretend that we have obeyed
- %% the forced recovery decision, but we
- %% will also generate an event in case the
- %% application wants to do something clever.
- Msg = {inconsistent_database, bad_decision, Node},
- mnesia_lib:report_system_event(Msg),
- OldD#decision{outcome = aborted};
-
- OldD#decision.outcome == aborted ->
- %% aborted overrrides anything
- OldD#decision{outcome = aborted};
-
- NewD#decision.outcome == aborted ->
- %% aborted overrrides anything
- OldD#decision{outcome = aborted};
-
- OldD#decision.outcome == committed,
- NewD#decision.outcome == unclear ->
- %% committed overrides unclear
- OldD#decision{outcome = committed};
-
- OldD#decision.outcome == unclear,
- NewD#decision.outcome == committed ->
- %% committed overrides unclear
- OldD#decision{outcome = committed}
- end
- end.
-
-add_remote_decisions(Node, [D | Tail], State) when record(D, decision) ->
- State2 = add_remote_decision(Node, D, State),
- add_remote_decisions(Node, Tail, State2);
-
-add_remote_decisions(Node, [C | Tail], State)
- when record(C, transient_decision) ->
- D = #decision{tid = C#transient_decision.tid,
- outcome = C#transient_decision.outcome,
- disc_nodes = [],
- ram_nodes = []},
- State2 = add_remote_decision(Node, D, State),
- add_remote_decisions(Node, Tail, State2);
-
-add_remote_decisions(Node, [{mnesia_down, _, _, _} | Tail], State) ->
- add_remote_decisions(Node, Tail, State);
-
-add_remote_decisions(Node, [{trans_tid, serial, Serial} | Tail], State) ->
- sync_trans_tid_serial(Serial),
- case State#state.unclear_decision of
- undefined ->
- ignored;
- D ->
- case lists:member(Node, D#decision.ram_nodes) of
- true ->
- ignore;
- false ->
- abcast([Node], {what_decision, node(), D})
- end
- end,
- add_remote_decisions(Node, Tail, State);
-
-add_remote_decisions(_Node, [], State) ->
- State.
-
-add_remote_decision(Node, NewD, State) ->
- Tid = NewD#decision.tid,
- OldD = decision(Tid),
- D = merge_decisions(Node, OldD, NewD),
- do_log_decision(D, false),
- Outcome = D#decision.outcome,
- if
- OldD == no_decision ->
- ignore;
- Outcome == unclear ->
- ignore;
- true ->
- case lists:member(node(), NewD#decision.disc_nodes) or
- lists:member(node(), NewD#decision.ram_nodes) of
- true ->
- tell_im_certain([Node], D);
- false ->
- ignore
- end
- end,
- case State#state.unclear_decision of
- U when U#decision.tid == Tid ->
- WaitFor = State#state.unclear_waitfor -- [Node],
- if
- Outcome == unclear, WaitFor == [] ->
- %% Everybody are uncertain, lets abort
- NewOutcome = aborted,
- CertainD = D#decision{outcome = NewOutcome,
- disc_nodes = [],
- ram_nodes = []},
- tell_im_certain(D#decision.disc_nodes, CertainD),
- tell_im_certain(D#decision.ram_nodes, CertainD),
- do_log_decision(CertainD, false),
- verbose("Decided to abort transaction ~p "
- "since everybody are uncertain ~p~n",
- [Tid, CertainD]),
- gen_server:reply(State#state.unclear_pid, {ok, NewOutcome}),
- State#state{unclear_pid = undefined,
- unclear_decision = undefined,
- unclear_waitfor = undefined};
- Outcome /= unclear ->
- verbose("~p told us that transaction ~p was ~p~n",
- [Node, Tid, Outcome]),
- gen_server:reply(State#state.unclear_pid, {ok, Outcome}),
- State#state{unclear_pid = undefined,
- unclear_decision = undefined,
- unclear_waitfor = undefined};
- Outcome == unclear ->
- State#state{unclear_waitfor = WaitFor}
- end;
- _ ->
- State
- end.
-
-announce_all([], _Tabs) ->
- ok;
-announce_all(ToNodes, [Tab | Tabs]) ->
- case catch mnesia_lib:db_match_object(ram_copies, Tab, '_') of
- {'EXIT', _} ->
- %% Oops, we are in the middle of a 'garb_decisions'
- announce_all(ToNodes, Tabs);
- List ->
- announce(ToNodes, List, [], false),
- announce_all(ToNodes, Tabs)
- end;
-announce_all(_ToNodes, []) ->
- ok.
-
-announce(ToNodes, [Head | Tail], Acc, ForceSend) ->
- Acc2 = arrange(ToNodes, Head, Acc, ForceSend),
- announce(ToNodes, Tail, Acc2, ForceSend);
-
-announce(_ToNodes, [], Acc, _ForceSend) ->
- send_decisions(Acc).
-
-send_decisions([{Node, Decisions} | Tail]) ->
- abcast([Node], {decisions, node(), Decisions}),
- send_decisions(Tail);
-send_decisions([]) ->
- ok.
-
-arrange([To | ToNodes], D, Acc, ForceSend) when record(D, decision) ->
- NeedsAdd = (ForceSend or
- lists:member(To, D#decision.disc_nodes) or
- lists:member(To, D#decision.ram_nodes)),
- case NeedsAdd of
- true ->
- Acc2 = add_decision(To, D, Acc),
- arrange(ToNodes, D, Acc2, ForceSend);
- false ->
- arrange(ToNodes, D, Acc, ForceSend)
- end;
-
-arrange([To | ToNodes], C, Acc, ForceSend) when record(C, transient_decision) ->
- Acc2 = add_decision(To, C, Acc),
- arrange(ToNodes, C, Acc2, ForceSend);
-
-arrange([_To | _ToNodes], {mnesia_down, _Node, _Date, _Time}, Acc, _ForceSend) ->
- %% The others have their own info about this
- Acc;
-
-arrange([_To | _ToNodes], {master_nodes, _Tab, _Nodes}, Acc, _ForceSend) ->
- %% The others have their own info about this
- Acc;
-
-arrange([To | ToNodes], {trans_tid, serial, Serial}, Acc, ForceSend) ->
- %% Do the lamport thing plus release the others
- %% from uncertainity.
- Acc2 = add_decision(To, {trans_tid, serial, Serial}, Acc),
- arrange(ToNodes, {trans_tid, serial, Serial}, Acc2, ForceSend);
-
-arrange([], _Decision, Acc, _ForceSend) ->
- Acc.
-
-add_decision(Node, Decision, [{Node, Decisions} | Tail]) ->
- [{Node, [Decision | Decisions]} | Tail];
-add_decision(Node, Decision, [Head | Tail]) ->
- [Head | add_decision(Node, Decision, Tail)];
-add_decision(Node, Decision, []) ->
- [{Node, [Decision]}].
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_registry.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_registry.erl
deleted file mode 100644
index c16603f344..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_registry.erl
+++ /dev/null
@@ -1,277 +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: mnesia_registry.erl,v 1.2 2010/03/04 13:54:19 maria Exp $
-%%
--module(mnesia_registry).
-
-%%%----------------------------------------------------------------------
-%%% File : mnesia_registry.erl
-%%% Purpose : Support dump and restore of a registry on a C-node
-%%% This is an OTP internal module and is not public available.
-%%%
-%%% Example : Dump some hardcoded records into the Mnesia table Tab
-%%%
-%%% case rpc:call(Node, mnesia_registry, start_dump, [Tab, self()]) of
-%%% Pid when pid(Pid) ->
-%%% Pid ! {write, key1, key_size1, val_type1, val_size1, val1},
-%%% Pid ! {delete, key3},
-%%% Pid ! {write, key2, key_size2, val_type2, val_size2, val2},
-%%% Pid ! {write, key4, key_size4, val_type4, val_size4, val4},
-%%% Pid ! {commit, self()},
-%%% receive
-%%% {ok, Pid} ->
-%%% ok;
-%%% {'EXIT', Pid, Reason} ->
-%%% exit(Reason)
-%%% end;
-%%% {badrpc, Reason} ->
-%%% exit(Reason)
-%%% end.
-%%%
-%%% Example : Restore the corresponding Mnesia table Tab
-%%%
-%%% case rpc:call(Node, mnesia_registry, start_restore, [Tab, self()]) of
-%%% {size, Pid, N, LargestKey, LargestVal} ->
-%%% Pid ! {send_records, self()},
-%%% Fun = fun() ->
-%%% receive
-%%% {restore, KeySize, ValSize, ValType, Key, Val} ->
-%%% {Key, Val};
-%%% {'EXIT', Pid, Reason} ->
-%%% exit(Reason)
-%%% end
-%%% end,
-%%% lists:map(Fun, lists:seq(1, N));
-%%% {badrpc, Reason} ->
-%%% exit(Reason)
-%%% end.
-%%%
-%%%----------------------------------------------------------------------
-
-%% External exports
--export([start_dump/2, start_restore/2]).
--export([create_table/1, create_table/2]).
-
-%% Internal exports
--export([init/4]).
-
--record(state, {table, ops = [], link_to}).
-
--record(registry_entry, {key, key_size, val_type, val_size, val}).
-
--record(size, {pid = self(), n_values = 0, largest_key = 0, largest_val = 0}).
-
-%%%----------------------------------------------------------------------
-%%% Client
-%%%----------------------------------------------------------------------
-
-start(Type, Tab, LinkTo) ->
- Starter = self(),
- Args = [Type, Starter, LinkTo, Tab],
- Pid = spawn_link(?MODULE, init, Args),
- %% The receiver process may unlink the current process
- receive
- {ok, Res} ->
- Res;
- {'EXIT', Pid, Reason} when LinkTo == Starter ->
- exit(Reason)
- end.
-
-%% Starts a receiver process and optionally creates a Mnesia table
-%% with suitable default values. Returns the Pid of the receiver process
-%%
-%% The receiver process accumulates Mnesia operations and performs
-%% all operations or none at commit. The understood messages are:
-%%
-%% {write, Key, KeySize, ValType, ValSize, Val} ->
-%% accumulates mnesia:write({Tab, Key, KeySize, ValType, ValSize, Val})
-%% (no reply)
-%% {delete, Key} ->
-%% accumulates mnesia:delete({Tab, Key}) (no reply)
-%% {commit, ReplyTo} ->
-%% commits all accumulated operations
-%% and stops the process (replies {ok, Pid})
-%% abort ->
-%% stops the process (no reply)
-%%
-%% The receiver process is linked to the process with the process identifier
-%% LinkTo. If some error occurs the receiver process will invoke exit(Reason)
-%% and it is up to he LinkTo process to act properly when it receives an exit
-%% signal.
-
-start_dump(Tab, LinkTo) ->
- start(dump, Tab, LinkTo).
-
-%% Starts a sender process which sends restore messages back to the
-%% LinkTo process. But first are some statistics about the table
-%% determined and returned as a 5-tuple:
-%%
-%% {size, SenderPid, N, LargestKeySize, LargestValSize}
-%%
-%% where N is the number of records in the table. Then the sender process
-%% waits for a 2-tuple message:
-%%
-%% {send_records, ReplyTo}
-%%
-%% At last N 6-tuple messages is sent to the ReplyTo process:
-%%
-%% ReplyTo ! {restore, KeySize, ValSize, ValType, Key, Val}
-%%
-%% If some error occurs the receiver process will invoke exit(Reason)
-%% and it is up to he LinkTo process to act properly when it receives an
-%% exit signal.
-
-start_restore(Tab, LinkTo) ->
- start(restore, Tab, LinkTo).
-
-
-%% Optionally creates the Mnesia table Tab with suitable default values.
-%% Returns ok or EXIT's
-create_table(Tab) ->
- Storage = mnesia:table_info(schema, storage_type),
- create_table(Tab, [{Storage, [node()]}]).
-
-create_table(Tab, TabDef) ->
- Attrs = record_info(fields, registry_entry),
- case mnesia:create_table(Tab, [{attributes, Attrs} | TabDef]) of
- {'atomic', ok} ->
- ok;
- {aborted, {already_exists, Tab}} ->
- ok;
- {aborted, Reason} ->
- exit(Reason)
- end.
-
-%%%----------------------------------------------------------------------
-%%% Server
-%%%----------------------------------------------------------------------
-
-init(Type, Starter, LinkTo, Tab) ->
- if
- LinkTo /= Starter ->
- link(LinkTo),
- unlink(Starter);
- true ->
- ignore
- end,
- case Type of
- dump ->
- Starter ! {ok, self()},
- dump_loop(#state{table = Tab, link_to = LinkTo});
- restore ->
- restore_table(Tab, Starter, LinkTo)
- end.
-
-%%%----------------------------------------------------------------------
-%%% Dump loop
-%%%----------------------------------------------------------------------
-
-dump_loop(S) ->
- Tab = S#state.table,
- Ops = S#state.ops,
- receive
- {write, Key, KeySize, ValType, ValSize, Val} ->
- RE = #registry_entry{key = Key,
- key_size = KeySize,
- val_type = ValType,
- val_size = ValSize,
- val = Val},
- dump_loop(S#state{ops = [{write, RE} | Ops]});
- {delete, Key} ->
- dump_loop(S#state{ops = [{delete, Key} | Ops]});
- {commit, ReplyTo} ->
- create_table(Tab),
- RecName = mnesia:table_info(Tab, record_name),
- %% The Ops are in reverse order, but there is no need
- %% for reversing the list of accumulated operations
- case mnesia:transaction(fun handle_ops/3, [Tab, RecName, Ops]) of
- {'atomic', ok} ->
- ReplyTo ! {ok, self()},
- stop(S#state.link_to);
- {aborted, Reason} ->
- exit({aborted, Reason})
- end;
- abort ->
- stop(S#state.link_to);
- BadMsg ->
- exit({bad_message, BadMsg})
- end.
-
-stop(LinkTo) ->
- unlink(LinkTo),
- exit(normal).
-
-%% Grab a write lock for the entire table
-%% and iterate over all accumulated operations
-handle_ops(Tab, RecName, Ops) ->
- mnesia:write_lock_table(Tab),
- do_handle_ops(Tab, RecName, Ops).
-
-do_handle_ops(Tab, RecName, [{write, RegEntry} | Ops]) ->
- Record = setelement(1, RegEntry, RecName),
- mnesia:write(Tab, Record, write),
- do_handle_ops(Tab, RecName, Ops);
-do_handle_ops(Tab, RecName, [{delete, Key} | Ops]) ->
- mnesia:delete(Tab, Key, write),
- do_handle_ops(Tab, RecName, Ops);
-do_handle_ops(_Tab, _RecName, []) ->
- ok.
-
-%%%----------------------------------------------------------------------
-%%% Restore table
-%%%----------------------------------------------------------------------
-
-restore_table(Tab, Starter, LinkTo) ->
- Pat = mnesia:table_info(Tab, wild_pattern),
- Fun = fun() -> mnesia:match_object(Tab, Pat, read) end,
- case mnesia:transaction(Fun) of
- {'atomic', AllRecords} ->
- Size = calc_size(AllRecords, #size{}),
- Starter ! {ok, Size},
- receive
- {send_records, ReplyTo} ->
- send_records(AllRecords, ReplyTo),
- unlink(LinkTo),
- exit(normal);
- BadMsg ->
- exit({bad_message, BadMsg})
- end;
- {aborted, Reason} ->
- exit(Reason)
- end.
-
-calc_size([H | T], S) ->
- KeySize = max(element(#registry_entry.key_size, H), S#size.largest_key),
- ValSize = max(element(#registry_entry.val_size, H), S#size.largest_val),
- N = S#size.n_values + 1,
- calc_size(T, S#size{n_values = N, largest_key = KeySize, largest_val = ValSize});
-calc_size([], Size) ->
- Size.
-
-max(New, Old) when New > Old -> New;
-max(_New, Old) -> Old.
-
-send_records([H | T], ReplyTo) ->
- KeySize = element(#registry_entry.key_size, H),
- ValSize = element(#registry_entry.val_size, H),
- ValType = element(#registry_entry.val_type, H),
- Key = element(#registry_entry.key, H),
- Val = element(#registry_entry.val, H),
- ReplyTo ! {restore, KeySize, ValSize, ValType, Key, Val},
- send_records(T, ReplyTo);
-send_records([], _ReplyTo) ->
- ok.
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_schema.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_schema.erl
deleted file mode 100644
index cceb6bf0d1..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_schema.erl
+++ /dev/null
@@ -1,2899 +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: mnesia_schema.erl,v 1.2 2010/03/04 13:54:20 maria Exp $
-%%
-%% In this module we provide a number of explicit functions
-%% to maninpulate the schema. All these functions are called
-%% within a special schema transaction.
-%%
-%% We also have an init/1 function defined here, this func is
-%% used by mnesia:start() to initialize the entire schema.
-
--module(mnesia_schema).
-
--export([
- add_snmp/2,
- add_table_copy/3,
- add_table_index/2,
- arrange_restore/3,
- attr_tab_to_pos/2,
- attr_to_pos/2,
- change_table_copy_type/3,
- change_table_access_mode/2,
- change_table_load_order/2,
- change_table_frag/2,
- clear_table/1,
- create_table/1,
- cs2list/1,
- del_snmp/1,
- del_table_copy/2,
- del_table_index/2,
- delete_cstruct/2,
- delete_schema/1,
- delete_schema2/0,
- delete_table/1,
- delete_table_property/2,
- dump_tables/1,
- ensure_no_schema/1,
- get_create_list/1,
- get_initial_schema/2,
- get_table_properties/1,
- info/0,
- info/1,
- init/1,
- insert_cstruct/3,
- is_remote_member/1,
- list2cs/1,
- lock_schema/0,
- lock_del_table/4, % Spawned
- merge_schema/0,
- move_table/3,
- opt_create_dir/2,
- prepare_commit/3,
- purge_dir/2,
- purge_tmp_files/0,
- ram_delete_table/2,
-% ram_delete_table/3,
- read_cstructs_from_disc/0,
- read_nodes/0,
- remote_read_schema/0,
- restore/1,
- restore/2,
- restore/3,
- schema_coordinator/3,
- set_where_to_read/3,
- transform_table/4,
- undo_prepare_commit/2,
- unlock_schema/0,
- version/0,
- write_table_property/2
- ]).
-
-%% Exports for mnesia_frag
--export([
- get_tid_ts_and_lock/2,
- make_create_table/1,
- ensure_active/1,
- pick/4,
- verify/3,
- incr_version/1,
- check_keys/3,
- check_duplicates/2,
- make_delete_table/2
- ]).
-
-%% Needed outside to be able to use/set table_properties
-%% from user (not supported)
--export([schema_transaction/1,
- insert_schema_ops/2,
- do_create_table/1,
- do_delete_table/1,
- do_delete_table_property/2,
- do_write_table_property/2]).
-
--include("mnesia.hrl").
--include_lib("kernel/include/file.hrl").
-
--import(mnesia_lib, [set/2, del/2, verbose/2, dbg_out/2]).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Here comes the init function which also resides in
-%% this module, it is called upon by the trans server
-%% at startup of the system
-%%
-%% We have a meta table which looks like
-%% {table, schema,
-%% {type, set},
-%% {disc_copies, all},
-%% {arity, 2}
-%% {attributes, [key, val]}
-%%
-%% This means that we have a series of {schema, Name, Cs} tuples
-%% in a table called schema !!
-
-init(IgnoreFallback) ->
- Res = read_schema(true, false, IgnoreFallback),
- {ok, Source, _CreateList} = exit_on_error(Res),
- verbose("Schema initiated from: ~p~n", [Source]),
- set({schema, tables}, []),
- set({schema, local_tables}, []),
- Tabs = set_schema(?ets_first(schema)),
- lists:foreach(fun(Tab) -> clear_whereabouts(Tab) end, Tabs),
- set({schema, where_to_read}, node()),
- set({schema, load_node}, node()),
- set({schema, load_reason}, initial),
- mnesia_controller:add_active_replica(schema, node()).
-
-exit_on_error({error, Reason}) ->
- exit(Reason);
-exit_on_error(GoodRes) ->
- GoodRes.
-
-val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
- Value -> Value
- end.
-
-%% This function traverses all cstructs in the schema and
-%% sets all values in mnesia_gvar accordingly for each table/cstruct
-
-set_schema('$end_of_table') ->
- [];
-set_schema(Tab) ->
- do_set_schema(Tab),
- [Tab | set_schema(?ets_next(schema, Tab))].
-
-get_create_list(Tab) ->
- ?ets_lookup_element(schema, Tab, 3).
-
-do_set_schema(Tab) ->
- List = get_create_list(Tab),
- Cs = list2cs(List),
- do_set_schema(Tab, Cs).
-
-do_set_schema(Tab, Cs) ->
- Type = Cs#cstruct.type,
- set({Tab, setorbag}, Type),
- set({Tab, local_content}, Cs#cstruct.local_content),
- set({Tab, ram_copies}, Cs#cstruct.ram_copies),
- set({Tab, disc_copies}, Cs#cstruct.disc_copies),
- set({Tab, disc_only_copies}, Cs#cstruct.disc_only_copies),
- set({Tab, load_order}, Cs#cstruct.load_order),
- set({Tab, access_mode}, Cs#cstruct.access_mode),
- set({Tab, snmp}, Cs#cstruct.snmp),
- set({Tab, user_properties}, Cs#cstruct.user_properties),
- [set({Tab, user_property, element(1, P)}, P) || P <- Cs#cstruct.user_properties],
- set({Tab, frag_properties}, Cs#cstruct.frag_properties),
- mnesia_frag:set_frag_hash(Tab, Cs#cstruct.frag_properties),
- set({Tab, attributes}, Cs#cstruct.attributes),
- Arity = length(Cs#cstruct.attributes) + 1,
- set({Tab, arity}, Arity),
- RecName = Cs#cstruct.record_name,
- set({Tab, record_name}, RecName),
- set({Tab, record_validation}, {RecName, Arity, Type}),
- set({Tab, wild_pattern}, wild(RecName, Arity)),
- set({Tab, index}, Cs#cstruct.index),
- %% create actual index tabs later
- set({Tab, cookie}, Cs#cstruct.cookie),
- set({Tab, version}, Cs#cstruct.version),
- set({Tab, cstruct}, Cs),
- Storage = mnesia_lib:schema_cs_to_storage_type(node(), Cs),
- set({Tab, storage_type}, Storage),
- mnesia_lib:add({schema, tables}, Tab),
- Ns = mnesia_lib:cs_to_nodes(Cs),
- case lists:member(node(), Ns) of
- true ->
- mnesia_lib:add({schema, local_tables}, Tab);
- false when Tab == schema ->
- mnesia_lib:add({schema, local_tables}, Tab);
- false ->
- ignore
- end.
-
-wild(RecName, Arity) ->
- Wp0 = list_to_tuple(lists:duplicate(Arity, '_')),
- setelement(1, Wp0, RecName).
-
-%% Temporarily read the local schema and return a list
-%% of all nodes mentioned in the schema.DAT file
-read_nodes() ->
- %% Ensure that we access the intended Mnesia
- %% directory. This function may not be called
- %% during startup since it will cause the
- %% application_controller to get into deadlock
- case mnesia_lib:ensure_loaded(?APPLICATION) of
- ok ->
- case read_schema(false, false) of
- {ok, _Source, CreateList} ->
- Cs = list2cs(CreateList),
- {ok, Cs#cstruct.disc_copies ++ Cs#cstruct.ram_copies};
- {error, Reason} ->
- {error, Reason}
- end;
- {error, Reason} ->
- {error, Reason}
- end.
-
-%% Returns Version from the tuple {Version,MasterNodes}
-version() ->
- case read_schema(false, false) of
- {ok, Source, CreateList} when Source /= default ->
- Cs = list2cs(CreateList),
- {Version, _Details} = Cs#cstruct.version,
- Version;
- _ ->
- case dir_exists(mnesia_lib:dir()) of
- true -> {1,0};
- false -> {0,0}
- end
- end.
-
-%% Calculate next table version from old cstruct
-incr_version(Cs) ->
- {{Major, Minor}, _} = Cs#cstruct.version,
- Nodes = mnesia_lib:intersect(val({schema, disc_copies}),
- mnesia_lib:cs_to_nodes(Cs)),
- V =
- case Nodes -- val({Cs#cstruct.name, active_replicas}) of
- [] -> {Major + 1, 0}; % All replicas are active
- _ -> {Major, Minor + 1} % Some replicas are inactive
- end,
- Cs#cstruct{version = {V, {node(), now()}}}.
-
-%% Returns table name
-insert_cstruct(Tid, Cs, KeepWhereabouts) ->
- Tab = Cs#cstruct.name,
- TabDef = cs2list(Cs),
- Val = {schema, Tab, TabDef},
- mnesia_checkpoint:tm_retain(Tid, schema, Tab, write),
- mnesia_subscr:report_table_event(schema, Tid, Val, write),
- Active = val({Tab, active_replicas}),
-
- case KeepWhereabouts of
- true ->
- ignore;
- false when Active == [] ->
- clear_whereabouts(Tab);
- false ->
- %% Someone else has initiated table
- ignore
- end,
- set({Tab, cstruct}, Cs),
- ?ets_insert(schema, Val),
- do_set_schema(Tab, Cs),
- Val.
-
-clear_whereabouts(Tab) ->
- set({Tab, checkpoints}, []),
- set({Tab, subscribers}, []),
- set({Tab, where_to_read}, nowhere),
- set({Tab, active_replicas}, []),
- set({Tab, commit_work}, []),
- set({Tab, where_to_write}, []),
- set({Tab, where_to_commit}, []),
- set({Tab, load_by_force}, false),
- set({Tab, load_node}, unknown),
- set({Tab, load_reason}, unknown).
-
-%% Returns table name
-delete_cstruct(Tid, Cs) ->
- Tab = Cs#cstruct.name,
- TabDef = cs2list(Cs),
- Val = {schema, Tab, TabDef},
- mnesia_checkpoint:tm_retain(Tid, schema, Tab, delete),
- mnesia_subscr:report_table_event(schema, Tid, Val, delete),
- ?ets_match_delete(mnesia_gvar, {{Tab, '_'}, '_'}),
- ?ets_match_delete(mnesia_gvar, {{Tab, '_', '_'}, '_'}),
- del({schema, local_tables}, Tab),
- del({schema, tables}, Tab),
- ?ets_delete(schema, Tab),
- Val.
-
-%% Delete the Mnesia directory on all given nodes
-%% Requires that Mnesia is not running anywhere
-%% Returns ok | {error,Reason}
-delete_schema(Ns) when list(Ns), Ns /= [] ->
- RunningNs = mnesia_lib:running_nodes(Ns),
- Reason = "Cannot delete schema on all nodes",
- if
- RunningNs == [] ->
- case rpc:multicall(Ns, ?MODULE, delete_schema2, []) of
- {Replies, []} ->
- case [R || R <- Replies, R /= ok] of
- [] ->
- ok;
- BadReplies ->
- verbose("~s: ~p~n", [Reason, BadReplies]),
- {error, {"All nodes not running", BadReplies}}
- end;
- {_Replies, BadNs} ->
- verbose("~s: ~p~n", [Reason, BadNs]),
- {error, {"All nodes not running", BadNs}}
- end;
- true ->
- verbose("~s: ~p~n", [Reason, RunningNs]),
- {error, {"Mnesia is not stopped everywhere", RunningNs}}
- end;
-delete_schema(Ns) ->
- {error, {badarg, Ns}}.
-
-delete_schema2() ->
- %% Ensure that we access the intended Mnesia
- %% directory. This function may not be called
- %% during startup since it will cause the
- %% application_controller to get into deadlock
- case mnesia_lib:ensure_loaded(?APPLICATION) of
- ok ->
- case mnesia_lib:is_running() of
- no ->
- Dir = mnesia_lib:dir(),
- purge_dir(Dir, []),
- ok;
- _ ->
- {error, {"Mnesia still running", node()}}
- end;
- {error, Reason} ->
- {error, Reason}
- end.
-
-ensure_no_schema([H|T]) when atom(H) ->
- case rpc:call(H, ?MODULE, remote_read_schema, []) of
- {badrpc, Reason} ->
- {H, {"All nodes not running", H, Reason}};
- {ok,Source, _} when Source /= default ->
- {H, {already_exists, H}};
- _ ->
- ensure_no_schema(T)
- end;
-ensure_no_schema([H|_]) ->
- {error,{badarg, H}};
-ensure_no_schema([]) ->
- ok.
-
-remote_read_schema() ->
- %% Ensure that we access the intended Mnesia
- %% directory. This function may not be called
- %% during startup since it will cause the
- %% application_controller to get into deadlock
- case mnesia_lib:ensure_loaded(?APPLICATION) of
- ok ->
- case mnesia_monitor:get_env(schema_location) of
- opt_disc ->
- read_schema(false, true);
- _ ->
- read_schema(false, false)
- end;
- {error, Reason} ->
- {error, Reason}
- end.
-
-dir_exists(Dir) ->
- dir_exists(Dir, mnesia_monitor:use_dir()).
-dir_exists(Dir, true) ->
- case file:read_file_info(Dir) of
- {ok, _} -> true;
- _ -> false
- end;
-dir_exists(_Dir, false) ->
- false.
-
-opt_create_dir(UseDir, Dir) when UseDir == true->
- case dir_exists(Dir, UseDir) of
- true ->
- check_can_write(Dir);
- false ->
- case file:make_dir(Dir) of
- ok ->
- verbose("Create Directory ~p~n", [Dir]),
- ok;
- {error, Reason} ->
- verbose("Cannot create mnesia dir ~p~n", [Reason]),
- {error, {"Cannot create Mnesia dir", Dir, Reason}}
- end
- end;
-opt_create_dir(false, _) ->
- {error, {has_no_disc, node()}}.
-
-check_can_write(Dir) ->
- case file:read_file_info(Dir) of
- {ok, FI} when FI#file_info.type == directory,
- FI#file_info.access == read_write ->
- ok;
- {ok, _} ->
- {error, "Not allowed to write in Mnesia dir", Dir};
- _ ->
- {error, "Non existent Mnesia dir", Dir}
- end.
-
-lock_schema() ->
- mnesia_lib:lock_table(schema).
-
-unlock_schema() ->
- mnesia_lib:unlock_table(schema).
-
-read_schema(Keep, _UseDirAnyway) ->
- read_schema(Keep, false, false).
-
-%% The schema may be read for several reasons.
-%% If Mnesia is not already started the read intention
-%% we normally do not want the ets table named schema
-%% be left around.
-%% If Keep == true, the ets table schema is kept
-%% If Keep == false, the ets table schema is removed
-%%
-%% Returns {ok, Source, SchemaCstruct} or {error, Reason}
-%% Source may be: default | ram | disc | fallback
-
-read_schema(Keep, UseDirAnyway, IgnoreFallback) ->
- lock_schema(),
- Res =
- case mnesia:system_info(is_running) of
- yes ->
- {ok, ram, get_create_list(schema)};
- _IsRunning ->
- case mnesia_monitor:use_dir() of
- true ->
- read_disc_schema(Keep, IgnoreFallback);
- false when UseDirAnyway == true ->
- read_disc_schema(Keep, IgnoreFallback);
- false when Keep == true ->
- Args = [{keypos, 2}, public, named_table, set],
- mnesia_monitor:mktab(schema, Args),
- CreateList = get_initial_schema(ram_copies, []),
- ?ets_insert(schema,{schema, schema, CreateList}),
- {ok, default, CreateList};
- false when Keep == false ->
- CreateList = get_initial_schema(ram_copies, []),
- {ok, default, CreateList}
- end
- end,
- unlock_schema(),
- Res.
-
-read_disc_schema(Keep, IgnoreFallback) ->
- Running = mnesia:system_info(is_running),
- case mnesia_bup:fallback_exists() of
- true when IgnoreFallback == false, Running /= yes ->
- mnesia_bup:fallback_to_schema();
- _ ->
- %% If we're running, we read the schema file even
- %% if fallback exists
- Dat = mnesia_lib:tab2dat(schema),
- case mnesia_lib:exists(Dat) of
- true ->
- do_read_disc_schema(Dat, Keep);
- false ->
- Dmp = mnesia_lib:tab2dmp(schema),
- case mnesia_lib:exists(Dmp) of
- true ->
- %% May only happen when toggling of
- %% schema storage type has been
- %% interrupted
- do_read_disc_schema(Dmp, Keep);
- false ->
- {error, "No schema file exists"}
- end
- end
- end.
-
-do_read_disc_schema(Fname, Keep) ->
- T =
- case Keep of
- false ->
- Args = [{keypos, 2}, public, set],
- ?ets_new_table(schema, Args);
- true ->
- Args = [{keypos, 2}, public, named_table, set],
- mnesia_monitor:mktab(schema, Args)
- end,
- Repair = mnesia_monitor:get_env(auto_repair),
- Res = % BUGBUG Fixa till dcl!
- case mnesia_lib:dets_to_ets(schema, T, Fname, set, Repair, no) of
- loaded -> {ok, disc, ?ets_lookup_element(T, schema, 3)};
- Other -> {error, {"Cannot read schema", Fname, Other}}
- end,
- case Keep of
- true -> ignore;
- false -> ?ets_delete_table(T)
- end,
- Res.
-
-get_initial_schema(SchemaStorage, Nodes) ->
- Cs = #cstruct{name = schema,
- record_name = schema,
- attributes = [table, cstruct]},
- Cs2 =
- case SchemaStorage of
- ram_copies -> Cs#cstruct{ram_copies = Nodes};
- disc_copies -> Cs#cstruct{disc_copies = Nodes}
- end,
- cs2list(Cs2).
-
-read_cstructs_from_disc() ->
- %% Assumptions:
- %% - local schema lock in global
- %% - use_dir is true
- %% - Mnesia is not running
- %% - Ignore fallback
-
- Fname = mnesia_lib:tab2dat(schema),
- case mnesia_lib:exists(Fname) of
- true ->
- Args = [{file, Fname},
- {keypos, 2},
- {repair, mnesia_monitor:get_env(auto_repair)},
- {type, set}],
- case dets:open_file(make_ref(), Args) of
- {ok, Tab} ->
- Fun = fun({_, _, List}) ->
- {continue, list2cs(List)}
- end,
- Cstructs = dets:traverse(Tab, Fun),
- dets:close(Tab),
- {ok, Cstructs};
- {error, Reason} ->
- {error, Reason}
- end;
- false ->
- {error, "No schema file exists"}
- end.
-
-%% We run a very special type of transactions when we
-%% we want to manipulate the schema.
-
-get_tid_ts_and_lock(Tab, Intent) ->
- TidTs = get(mnesia_activity_state),
- case TidTs of
- {_Mod, Tid, Ts} when record(Ts, tidstore)->
- Store = Ts#tidstore.store,
- case Intent of
- read -> mnesia_locker:rlock_table(Tid, Store, Tab);
- write -> mnesia_locker:wlock_table(Tid, Store, Tab);
- none -> ignore
- end,
- TidTs;
- _ ->
- mnesia:abort(no_transaction)
- end.
-
-schema_transaction(Fun) ->
- case get(mnesia_activity_state) of
- undefined ->
- Args = [self(), Fun, whereis(mnesia_controller)],
- Pid = spawn_link(?MODULE, schema_coordinator, Args),
- receive
- {transaction_done, Res, Pid} -> Res;
- {'EXIT', Pid, R} -> {aborted, {transaction_crashed, R}}
- end;
- _ ->
- {aborted, nested_transaction}
- end.
-
-%% This process may dump the transaction log, and should
-%% therefore not be run in an application process
-%%
-schema_coordinator(Client, _Fun, undefined) ->
- Res = {aborted, {node_not_running, node()}},
- Client ! {transaction_done, Res, self()},
- unlink(Client);
-
-schema_coordinator(Client, Fun, Controller) when pid(Controller) ->
- %% Do not trap exit in order to automatically die
- %% when the controller dies
-
- link(Controller),
- unlink(Client),
-
- %% Fulfull the transaction even if the client dies
- Res = mnesia:transaction(Fun),
- Client ! {transaction_done, Res, self()},
- unlink(Controller), % Avoids spurious exit message
- unlink(whereis(mnesia_tm)), % Avoids spurious exit message
- exit(normal).
-
-%% The make* rotines return a list of ops, this function
-%% inserts em all in the Store and maintains the local order
-%% of ops.
-
-insert_schema_ops({_Mod, _Tid, Ts}, SchemaIOps) ->
- do_insert_schema_ops(Ts#tidstore.store, SchemaIOps).
-
-do_insert_schema_ops(Store, [Head | Tail]) ->
- ?ets_insert(Store, Head),
- do_insert_schema_ops(Store, Tail);
-do_insert_schema_ops(_Store, []) ->
- ok.
-
-cs2list(Cs) when record(Cs, cstruct) ->
- Tags = record_info(fields, cstruct),
- rec2list(Tags, 2, Cs);
-cs2list(CreateList) when list(CreateList) ->
- CreateList.
-
-rec2list([Tag | Tags], Pos, Rec) ->
- Val = element(Pos, Rec),
- [{Tag, Val} | rec2list(Tags, Pos + 1, Rec)];
-rec2list([], _Pos, _Rec) ->
- [].
-
-list2cs(List) when list(List) ->
- Name = pick(unknown, name, List, must),
- Type = pick(Name, type, List, set),
- Rc0 = pick(Name, ram_copies, List, []),
- Dc = pick(Name, disc_copies, List, []),
- Doc = pick(Name, disc_only_copies, List, []),
- Rc = case {Rc0, Dc, Doc} of
- {[], [], []} -> [node()];
- _ -> Rc0
- end,
- LC = pick(Name, local_content, List, false),
- RecName = pick(Name, record_name, List, Name),
- Attrs = pick(Name, attributes, List, [key, val]),
- Snmp = pick(Name, snmp, List, []),
- LoadOrder = pick(Name, load_order, List, 0),
- AccessMode = pick(Name, access_mode, List, read_write),
- UserProps = pick(Name, user_properties, List, []),
- verify({alt, [nil, list]}, mnesia_lib:etype(UserProps),
- {bad_type, Name, {user_properties, UserProps}}),
- Cookie = pick(Name, cookie, List, ?unique_cookie),
- Version = pick(Name, version, List, {{2, 0}, []}),
- Ix = pick(Name, index, List, []),
- verify({alt, [nil, list]}, mnesia_lib:etype(Ix),
- {bad_type, Name, {index, [Ix]}}),
- Ix2 = [attr_to_pos(I, Attrs) || I <- Ix],
-
- Frag = pick(Name, frag_properties, List, []),
- verify({alt, [nil, list]}, mnesia_lib:etype(Frag),
- {badarg, Name, {frag_properties, Frag}}),
-
- Keys = check_keys(Name, List, record_info(fields, cstruct)),
- check_duplicates(Name, Keys),
- #cstruct{name = Name,
- ram_copies = Rc,
- disc_copies = Dc,
- disc_only_copies = Doc,
- type = Type,
- index = Ix2,
- snmp = Snmp,
- load_order = LoadOrder,
- access_mode = AccessMode,
- local_content = LC,
- record_name = RecName,
- attributes = Attrs,
- user_properties = lists:sort(UserProps),
- frag_properties = lists:sort(Frag),
- cookie = Cookie,
- version = Version};
-list2cs(Other) ->
- mnesia:abort({badarg, Other}).
-
-pick(Tab, Key, List, Default) ->
- case lists:keysearch(Key, 1, List) of
- false when Default == must ->
- mnesia:abort({badarg, Tab, "Missing key", Key, List});
- false ->
- Default;
- {value, {Key, Value}} ->
- Value;
- {value, BadArg} ->
- mnesia:abort({bad_type, Tab, BadArg})
- end.
-
-%% Convert attribute name to integer if neccessary
-attr_tab_to_pos(_Tab, Pos) when integer(Pos) ->
- Pos;
-attr_tab_to_pos(Tab, Attr) ->
- attr_to_pos(Attr, val({Tab, attributes})).
-
-%% Convert attribute name to integer if neccessary
-attr_to_pos(Pos, _Attrs) when integer(Pos) ->
- Pos;
-attr_to_pos(Attr, Attrs) when atom(Attr) ->
- attr_to_pos(Attr, Attrs, 2);
-attr_to_pos(Attr, _) ->
- mnesia:abort({bad_type, Attr}).
-
-attr_to_pos(Attr, [Attr | _Attrs], Pos) ->
- Pos;
-attr_to_pos(Attr, [_ | Attrs], Pos) ->
- attr_to_pos(Attr, Attrs, Pos + 1);
-attr_to_pos(Attr, _, _) ->
- mnesia:abort({bad_type, Attr}).
-
-check_keys(Tab, [{Key, _Val} | Tail], Items) ->
- case lists:member(Key, Items) of
- true -> [Key | check_keys(Tab, Tail, Items)];
- false -> mnesia:abort({badarg, Tab, Key})
- end;
-check_keys(_, [], _) ->
- [];
-check_keys(Tab, Arg, _) ->
- mnesia:abort({badarg, Tab, Arg}).
-
-check_duplicates(Tab, Keys) ->
- case has_duplicates(Keys) of
- false -> ok;
- true -> mnesia:abort({badarg, Tab, "Duplicate keys", Keys})
- end.
-
-has_duplicates([H | T]) ->
- case lists:member(H, T) of
- true -> true;
- false -> has_duplicates(T)
- end;
-has_duplicates([]) ->
- false.
-
-%% This is the only place where we check the validity of data
-verify_cstruct(Cs) when record(Cs, cstruct) ->
- verify_nodes(Cs),
-
- Tab = Cs#cstruct.name,
- verify(atom, mnesia_lib:etype(Tab), {bad_type, Tab}),
- Type = Cs#cstruct.type,
- verify(true, lists:member(Type, [set, bag, ordered_set]),
- {bad_type, Tab, {type, Type}}),
-
- %% Currently ordered_set is not supported for disk_only_copies.
- if
- Type == ordered_set, Cs#cstruct.disc_only_copies /= [] ->
- mnesia:abort({bad_type, Tab, {not_supported, Type, disc_only_copies}});
- true ->
- ok
- end,
-
- RecName = Cs#cstruct.record_name,
- verify(atom, mnesia_lib:etype(RecName),
- {bad_type, Tab, {record_name, RecName}}),
-
- Attrs = Cs#cstruct.attributes,
- verify(list, mnesia_lib:etype(Attrs),
- {bad_type, Tab, {attributes, Attrs}}),
-
- Arity = length(Attrs) + 1,
- verify(true, Arity > 2, {bad_type, Tab, {attributes, Attrs}}),
-
- lists:foldl(fun(Attr,_Other) when Attr == snmp ->
- mnesia:abort({bad_type, Tab, {attributes, [Attr]}});
- (Attr,Other) ->
- verify(atom, mnesia_lib:etype(Attr),
- {bad_type, Tab, {attributes, [Attr]}}),
- verify(false, lists:member(Attr, Other),
- {combine_error, Tab, {attributes, [Attr | Other]}}),
- [Attr | Other]
- end,
- [],
- Attrs),
-
- Index = Cs#cstruct.index,
- verify({alt, [nil, list]}, mnesia_lib:etype(Index),
- {bad_type, Tab, {index, Index}}),
-
- IxFun =
- fun(Pos) ->
- verify(true, fun() ->
- if
- integer(Pos),
- Pos > 2,
- Pos =< Arity ->
- true;
- true -> false
- end
- end,
- {bad_type, Tab, {index, [Pos]}})
- end,
- lists:foreach(IxFun, Index),
-
- LC = Cs#cstruct.local_content,
- verify({alt, [true, false]}, LC,
- {bad_type, Tab, {local_content, LC}}),
- Access = Cs#cstruct.access_mode,
- verify({alt, [read_write, read_only]}, Access,
- {bad_type, Tab, {access_mode, Access}}),
-
- Snmp = Cs#cstruct.snmp,
- verify(true, mnesia_snmp_hook:check_ustruct(Snmp),
- {badarg, Tab, {snmp, Snmp}}),
-
- CheckProp = fun(Prop) when tuple(Prop), size(Prop) >= 1 -> ok;
- (Prop) -> mnesia:abort({bad_type, Tab, {user_properties, [Prop]}})
- end,
- lists:foreach(CheckProp, Cs#cstruct.user_properties),
-
- case Cs#cstruct.cookie of
- {{MegaSecs, Secs, MicroSecs}, _Node}
- when integer(MegaSecs), integer(Secs),
- integer(MicroSecs), atom(node) ->
- ok;
- Cookie ->
- mnesia:abort({bad_type, Tab, {cookie, Cookie}})
- end,
- case Cs#cstruct.version of
- {{Major, Minor}, _Detail}
- when integer(Major), integer(Minor) ->
- ok;
- Version ->
- mnesia:abort({bad_type, Tab, {version, Version}})
- end.
-
-verify_nodes(Cs) ->
- Tab = Cs#cstruct.name,
- Ram = Cs#cstruct.ram_copies,
- Disc = Cs#cstruct.disc_copies,
- DiscOnly = Cs#cstruct.disc_only_copies,
- LoadOrder = Cs#cstruct.load_order,
-
- verify({alt, [nil, list]}, mnesia_lib:etype(Ram),
- {bad_type, Tab, {ram_copies, Ram}}),
- verify({alt, [nil, list]}, mnesia_lib:etype(Disc),
- {bad_type, Tab, {disc_copies, Disc}}),
- case Tab of
- schema ->
- verify([], DiscOnly, {bad_type, Tab, {disc_only_copies, DiscOnly}});
- _ ->
- verify({alt, [nil, list]},
- mnesia_lib:etype(DiscOnly),
- {bad_type, Tab, {disc_only_copies, DiscOnly}})
- end,
- verify(integer, mnesia_lib:etype(LoadOrder),
- {bad_type, Tab, {load_order, LoadOrder}}),
-
- Nodes = Ram ++ Disc ++ DiscOnly,
- verify(list, mnesia_lib:etype(Nodes),
- {combine_error, Tab,
- [{ram_copies, []}, {disc_copies, []}, {disc_only_copies, []}]}),
- verify(false, has_duplicates(Nodes), {combine_error, Tab, Nodes}),
- AtomCheck = fun(N) -> verify(atom, mnesia_lib:etype(N), {bad_type, Tab, N}) end,
- lists:foreach(AtomCheck, Nodes).
-
-verify(Expected, Fun, Error) when function(Fun) ->
- do_verify(Expected, catch Fun(), Error);
-verify(Expected, Actual, Error) ->
- do_verify(Expected, Actual, Error).
-
-do_verify({alt, Values}, Value, Error) ->
- case lists:member(Value, Values) of
- true -> ok;
- false -> mnesia:abort(Error)
- end;
-do_verify(Value, Value, _) ->
- ok;
-do_verify(_Value, _, Error) ->
- mnesia:abort(Error).
-
-ensure_writable(Tab) ->
- case val({Tab, where_to_write}) of
- [] -> mnesia:abort({read_only, Tab});
- _ -> ok
- end.
-
-%% Ensure that all replicas on disk full nodes are active
-ensure_active(Cs) ->
- ensure_active(Cs, active_replicas).
-
-ensure_active(Cs, What) ->
- Tab = Cs#cstruct.name,
- case val({Tab, What}) of
- [] -> mnesia:abort({no_exists, Tab});
- _ -> ok
- end,
- Nodes = mnesia_lib:intersect(val({schema, disc_copies}),
- mnesia_lib:cs_to_nodes(Cs)),
- W = {Tab, What},
- case Nodes -- val(W) of
- [] ->
- ok;
- Ns ->
- Expl = "All replicas on diskfull nodes are not active yet",
- case val({Tab, local_content}) of
- true ->
- case rpc:multicall(Ns, ?MODULE, is_remote_member, [W]) of
- {Replies, []} ->
- check_active(Replies, Expl, Tab);
- {_Replies, BadNs} ->
- mnesia:abort({not_active, Expl, Tab, BadNs})
- end;
- false ->
- mnesia:abort({not_active, Expl, Tab, Ns})
- end
- end.
-
-ensure_not_active(schema, Node) ->
- case lists:member(Node, val({schema, active_replicas})) of
- false ->
- ok;
- true ->
- Expl = "Mnesia is running",
- mnesia:abort({active, Expl, Node})
- end.
-
-is_remote_member(Key) ->
- IsActive = lists:member(node(), val(Key)),
- {IsActive, node()}.
-
-check_active([{true, _Node} | Replies], Expl, Tab) ->
- check_active(Replies, Expl, Tab);
-check_active([{false, Node} | _Replies], Expl, Tab) ->
- mnesia:abort({not_active, Expl, Tab, [Node]});
-check_active([{badrpc, Reason} | _Replies], Expl, Tab) ->
- mnesia:abort({not_active, Expl, Tab, Reason});
-check_active([], _Expl, _Tab) ->
- ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Here's the real interface function to create a table
-
-create_table(TabDef) ->
- schema_transaction(fun() -> do_multi_create_table(TabDef) end).
-
-%% And the corresponding do routines ....
-
-do_multi_create_table(TabDef) ->
- get_tid_ts_and_lock(schema, write),
- ensure_writable(schema),
- Cs = list2cs(TabDef),
- case Cs#cstruct.frag_properties of
- [] ->
- do_create_table(Cs);
- _Props ->
- CsList = mnesia_frag:expand_cstruct(Cs),
- lists:foreach(fun do_create_table/1, CsList)
- end,
- ok.
-
-do_create_table(Cs) ->
- {_Mod, _Tid, Ts} = get_tid_ts_and_lock(schema, none),
- Store = Ts#tidstore.store,
- do_insert_schema_ops(Store, make_create_table(Cs)).
-
-make_create_table(Cs) ->
- Tab = Cs#cstruct.name,
- verify('EXIT', element(1, ?catch_val({Tab, cstruct})),
- {already_exists, Tab}),
- unsafe_make_create_table(Cs).
-
-% unsafe_do_create_table(Cs) ->
-% {_Mod, Tid, Ts} = get_tid_ts_and_lock(schema, none),
-% Store = Ts#tidstore.store,
-% do_insert_schema_ops(Store, unsafe_make_create_table(Cs)).
-
-unsafe_make_create_table(Cs) ->
- {_Mod, Tid, Ts} = get_tid_ts_and_lock(schema, none),
- verify_cstruct(Cs),
- Tab = Cs#cstruct.name,
-
- %% Check that we have all disc replica nodes running
- DiscNodes = Cs#cstruct.disc_copies ++ Cs#cstruct.disc_only_copies,
- RunningNodes = val({current, db_nodes}),
- CheckDisc = fun(N) ->
- verify(true, lists:member(N, RunningNodes),
- {not_active, Tab, N})
- end,
- lists:foreach(CheckDisc, DiscNodes),
-
- Nodes = mnesia_lib:intersect(mnesia_lib:cs_to_nodes(Cs), RunningNodes),
- Store = Ts#tidstore.store,
- mnesia_locker:wlock_no_exist(Tid, Store, Tab, Nodes),
- [{op, create_table, cs2list(Cs)}].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Delete a table entirely on all nodes.
-
-delete_table(Tab) ->
- schema_transaction(fun() -> do_delete_table(Tab) end).
-
-do_delete_table(schema) ->
- mnesia:abort({bad_type, schema});
-do_delete_table(Tab) ->
- TidTs = get_tid_ts_and_lock(schema, write),
- ensure_writable(schema),
- insert_schema_ops(TidTs, make_delete_table(Tab, whole_table)).
-
-make_delete_table(Tab, Mode) ->
- case Mode of
- whole_table ->
- case val({Tab, frag_properties}) of
- [] ->
- [make_delete_table2(Tab)];
- _Props ->
- %% Check if it is a base table
- mnesia_frag:lookup_frag_hash(Tab),
-
- %% Check for foreigners
- F = mnesia_frag:lookup_foreigners(Tab),
- verify([], F, {combine_error, Tab, "Too many foreigners", F}),
- [make_delete_table2(T) || T <- mnesia_frag:frag_names(Tab)]
- end;
- single_frag ->
- [make_delete_table2(Tab)]
- end.
-
-make_delete_table2(Tab) ->
- get_tid_ts_and_lock(Tab, write),
- Cs = val({Tab, cstruct}),
- ensure_active(Cs),
- ensure_writable(Tab),
- {op, delete_table, cs2list(Cs)}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Change fragmentation of a table
-
-change_table_frag(Tab, Change) ->
- schema_transaction(fun() -> do_change_table_frag(Tab, Change) end).
-
-do_change_table_frag(Tab, Change) when atom(Tab), Tab /= schema ->
- TidTs = get_tid_ts_and_lock(schema, write),
- Ops = mnesia_frag:change_table_frag(Tab, Change),
- [insert_schema_ops(TidTs, Op) || Op <- Ops],
- ok;
-do_change_table_frag(Tab, _Change) ->
- mnesia:abort({bad_type, Tab}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Clear a table
-
-clear_table(Tab) ->
- schema_transaction(fun() -> do_clear_table(Tab) end).
-
-do_clear_table(schema) ->
- mnesia:abort({bad_type, schema});
-do_clear_table(Tab) ->
- TidTs = get_tid_ts_and_lock(schema, write),
- get_tid_ts_and_lock(Tab, write),
- insert_schema_ops(TidTs, make_clear_table(Tab)).
-
-make_clear_table(Tab) ->
- ensure_writable(schema),
- Cs = val({Tab, cstruct}),
- ensure_active(Cs),
- ensure_writable(Tab),
- [{op, clear_table, cs2list(Cs)}].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-add_table_copy(Tab, Node, Storage) ->
- schema_transaction(fun() -> do_add_table_copy(Tab, Node, Storage) end).
-
-do_add_table_copy(Tab, Node, Storage) when atom(Tab), atom(Node) ->
- TidTs = get_tid_ts_and_lock(schema, write),
- insert_schema_ops(TidTs, make_add_table_copy(Tab, Node, Storage));
-do_add_table_copy(Tab,Node,_) ->
- mnesia:abort({badarg, Tab, Node}).
-
-make_add_table_copy(Tab, Node, Storage) ->
- ensure_writable(schema),
- Cs = incr_version(val({Tab, cstruct})),
- Ns = mnesia_lib:cs_to_nodes(Cs),
- verify(false, lists:member(Node, Ns), {already_exists, Tab, Node}),
- Cs2 = new_cs(Cs, Node, Storage, add),
- verify_cstruct(Cs2),
-
- %% Check storage and if node is running
- IsRunning = lists:member(Node, val({current, db_nodes})),
- if
- Storage == unknown ->
- mnesia:abort({badarg, Tab, Storage});
- Tab == schema ->
- if
- Storage /= ram_copies ->
- mnesia:abort({badarg, Tab, Storage});
- IsRunning == true ->
- mnesia:abort({already_exists, Tab, Node});
- true ->
- ignore
- end;
- Storage == ram_copies ->
- ignore;
- IsRunning == true ->
- ignore;
- IsRunning == false ->
- mnesia:abort({not_active, schema, Node})
- end,
- [{op, add_table_copy, Storage, Node, cs2list(Cs2)}].
-
-del_table_copy(Tab, Node) ->
- schema_transaction(fun() -> do_del_table_copy(Tab, Node) end).
-
-do_del_table_copy(Tab, Node) when atom(Node) ->
- TidTs = get_tid_ts_and_lock(schema, write),
-%% get_tid_ts_and_lock(Tab, write),
- insert_schema_ops(TidTs, make_del_table_copy(Tab, Node));
-do_del_table_copy(Tab, Node) ->
- mnesia:abort({badarg, Tab, Node}).
-
-make_del_table_copy(Tab, Node) ->
- ensure_writable(schema),
- Cs = incr_version(val({Tab, cstruct})),
- Storage = mnesia_lib:schema_cs_to_storage_type(Node, Cs),
- Cs2 = new_cs(Cs, Node, Storage, del),
- case mnesia_lib:cs_to_nodes(Cs2) of
- [] when Tab == schema ->
- mnesia:abort({combine_error, Tab, "Last replica"});
- [] ->
- ensure_active(Cs),
- dbg_out("Last replica deleted in table ~p~n", [Tab]),
- make_delete_table(Tab, whole_table);
- _ when Tab == schema ->
- ensure_active(Cs2),
- ensure_not_active(Tab, Node),
- verify_cstruct(Cs2),
- Ops = remove_node_from_tabs(val({schema, tables}), Node),
- [{op, del_table_copy, ram_copies, Node, cs2list(Cs2)} | Ops];
- _ ->
- ensure_active(Cs),
- verify_cstruct(Cs2),
- [{op, del_table_copy, Storage, Node, cs2list(Cs2)}]
- end.
-
-remove_node_from_tabs([], _Node) ->
- [];
-remove_node_from_tabs([schema|Rest], Node) ->
- remove_node_from_tabs(Rest, Node);
-remove_node_from_tabs([Tab|Rest], Node) ->
- {Cs, IsFragModified} =
- mnesia_frag:remove_node(Node, incr_version(val({Tab, cstruct}))),
- case mnesia_lib:schema_cs_to_storage_type(Node, Cs) of
- unknown ->
- case IsFragModified of
- true ->
- [{op, change_table_frag, {del_node, Node}, cs2list(Cs)} |
- remove_node_from_tabs(Rest, Node)];
- false ->
- remove_node_from_tabs(Rest, Node)
- end;
- Storage ->
- Cs2 = new_cs(Cs, Node, Storage, del),
- case mnesia_lib:cs_to_nodes(Cs2) of
- [] ->
- [{op, delete_table, cs2list(Cs)} |
- remove_node_from_tabs(Rest, Node)];
- _Ns ->
- verify_cstruct(Cs2),
- [{op, del_table_copy, ram_copies, Node, cs2list(Cs2)}|
- remove_node_from_tabs(Rest, Node)]
- end
- end.
-
-new_cs(Cs, Node, ram_copies, add) ->
- Cs#cstruct{ram_copies = opt_add(Node, Cs#cstruct.ram_copies)};
-new_cs(Cs, Node, disc_copies, add) ->
- Cs#cstruct{disc_copies = opt_add(Node, Cs#cstruct.disc_copies)};
-new_cs(Cs, Node, disc_only_copies, add) ->
- Cs#cstruct{disc_only_copies = opt_add(Node, Cs#cstruct.disc_only_copies)};
-new_cs(Cs, Node, ram_copies, del) ->
- Cs#cstruct{ram_copies = lists:delete(Node , Cs#cstruct.ram_copies)};
-new_cs(Cs, Node, disc_copies, del) ->
- Cs#cstruct{disc_copies = lists:delete(Node , Cs#cstruct.disc_copies)};
-new_cs(Cs, Node, disc_only_copies, del) ->
- Cs#cstruct{disc_only_copies =
- lists:delete(Node , Cs#cstruct.disc_only_copies)};
-new_cs(Cs, _Node, Storage, _Op) ->
- mnesia:abort({badarg, Cs#cstruct.name, Storage}).
-
-
-opt_add(N, L) -> [N | lists:delete(N, L)].
-
-move_table(Tab, FromNode, ToNode) ->
- schema_transaction(fun() -> do_move_table(Tab, FromNode, ToNode) end).
-
-do_move_table(schema, _FromNode, _ToNode) ->
- mnesia:abort({bad_type, schema});
-do_move_table(Tab, FromNode, ToNode) when atom(FromNode), atom(ToNode) ->
- TidTs = get_tid_ts_and_lock(schema, write),
- insert_schema_ops(TidTs, make_move_table(Tab, FromNode, ToNode));
-do_move_table(Tab, FromNode, ToNode) ->
- mnesia:abort({badarg, Tab, FromNode, ToNode}).
-
-make_move_table(Tab, FromNode, ToNode) ->
- ensure_writable(schema),
- Cs = incr_version(val({Tab, cstruct})),
- Ns = mnesia_lib:cs_to_nodes(Cs),
- verify(false, lists:member(ToNode, Ns), {already_exists, Tab, ToNode}),
- verify(true, lists:member(FromNode, val({Tab, where_to_write})),
- {not_active, Tab, FromNode}),
- verify(false, val({Tab,local_content}),
- {"Cannot move table with local content", Tab}),
- ensure_active(Cs),
- Running = val({current, db_nodes}),
- Storage = mnesia_lib:schema_cs_to_storage_type(FromNode, Cs),
- verify(true, lists:member(ToNode, Running), {not_active, schema, ToNode}),
-
- Cs2 = new_cs(Cs, ToNode, Storage, add),
- Cs3 = new_cs(Cs2, FromNode, Storage, del),
- verify_cstruct(Cs3),
- [{op, add_table_copy, Storage, ToNode, cs2list(Cs2)},
- {op, sync_trans},
- {op, del_table_copy, Storage, FromNode, cs2list(Cs3)}].
-
-%% end of functions to add and delete nodes to tables
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-
-change_table_copy_type(Tab, Node, ToS) ->
- schema_transaction(fun() -> do_change_table_copy_type(Tab, Node, ToS) end).
-
-do_change_table_copy_type(Tab, Node, ToS) when atom(Node) ->
- TidTs = get_tid_ts_and_lock(schema, write),
- get_tid_ts_and_lock(Tab, write), % ensure global sync
- %% get_tid_ts_and_lock(Tab, read),
- insert_schema_ops(TidTs, make_change_table_copy_type(Tab, Node, ToS));
-do_change_table_copy_type(Tab, Node, _ToS) ->
- mnesia:abort({badarg, Tab, Node}).
-
-make_change_table_copy_type(Tab, Node, unknown) ->
- make_del_table_copy(Tab, Node);
-make_change_table_copy_type(Tab, Node, ToS) ->
- ensure_writable(schema),
- Cs = incr_version(val({Tab, cstruct})),
- FromS = mnesia_lib:storage_type_at_node(Node, Tab),
-
- case compare_storage_type(false, FromS, ToS) of
- {same, _} ->
- mnesia:abort({already_exists, Tab, Node, ToS});
- {diff, _} ->
- ignore;
- incompatible ->
- ensure_active(Cs)
- end,
-
- Cs2 = new_cs(Cs, Node, FromS, del),
- Cs3 = new_cs(Cs2, Node, ToS, add),
- verify_cstruct(Cs3),
-
- if
- FromS == unknown ->
- make_add_table_copy(Tab, Node, ToS);
- true ->
- ignore
- end,
-
- [{op, change_table_copy_type, Node, FromS, ToS, cs2list(Cs3)}].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% change index functions ....
-%% Pos is allready added by 1 in both of these functions
-
-add_table_index(Tab, Pos) ->
- schema_transaction(fun() -> do_add_table_index(Tab, Pos) end).
-
-do_add_table_index(schema, _Attr) ->
- mnesia:abort({bad_type, schema});
-do_add_table_index(Tab, Attr) ->
- TidTs = get_tid_ts_and_lock(schema, write),
- get_tid_ts_and_lock(Tab, read),
- Pos = attr_tab_to_pos(Tab, Attr),
- insert_schema_ops(TidTs, make_add_table_index(Tab, Pos)).
-
-make_add_table_index(Tab, Pos) ->
- ensure_writable(schema),
- Cs = incr_version(val({Tab, cstruct})),
- ensure_active(Cs),
- Ix = Cs#cstruct.index,
- verify(false, lists:member(Pos, Ix), {already_exists, Tab, Pos}),
- Ix2 = lists:sort([Pos | Ix]),
- Cs2 = Cs#cstruct{index = Ix2},
- verify_cstruct(Cs2),
- [{op, add_index, Pos, cs2list(Cs2)}].
-
-del_table_index(Tab, Pos) ->
- schema_transaction(fun() -> do_del_table_index(Tab, Pos) end).
-
-do_del_table_index(schema, _Attr) ->
- mnesia:abort({bad_type, schema});
-do_del_table_index(Tab, Attr) ->
- TidTs = get_tid_ts_and_lock(schema, write),
- get_tid_ts_and_lock(Tab, read),
- Pos = attr_tab_to_pos(Tab, Attr),
- insert_schema_ops(TidTs, make_del_table_index(Tab, Pos)).
-
-make_del_table_index(Tab, Pos) ->
- ensure_writable(schema),
- Cs = incr_version(val({Tab, cstruct})),
- ensure_active(Cs),
- Ix = Cs#cstruct.index,
- verify(true, lists:member(Pos, Ix), {no_exists, Tab, Pos}),
- Cs2 = Cs#cstruct{index = lists:delete(Pos, Ix)},
- verify_cstruct(Cs2),
- [{op, del_index, Pos, cs2list(Cs2)}].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-add_snmp(Tab, Ustruct) ->
- schema_transaction(fun() -> do_add_snmp(Tab, Ustruct) end).
-
-do_add_snmp(schema, _Ustruct) ->
- mnesia:abort({bad_type, schema});
-do_add_snmp(Tab, Ustruct) ->
- TidTs = get_tid_ts_and_lock(schema, write),
- get_tid_ts_and_lock(Tab, read),
- insert_schema_ops(TidTs, make_add_snmp(Tab, Ustruct)).
-
-make_add_snmp(Tab, Ustruct) ->
- ensure_writable(schema),
- Cs = incr_version(val({Tab, cstruct})),
- ensure_active(Cs),
- verify([], Cs#cstruct.snmp, {already_exists, Tab, snmp}),
- Error = {badarg, Tab, snmp, Ustruct},
- verify(true, mnesia_snmp_hook:check_ustruct(Ustruct), Error),
- Cs2 = Cs#cstruct{snmp = Ustruct},
- verify_cstruct(Cs2),
- [{op, add_snmp, Ustruct, cs2list(Cs2)}].
-
-del_snmp(Tab) ->
- schema_transaction(fun() -> do_del_snmp(Tab) end).
-
-do_del_snmp(schema) ->
- mnesia:abort({bad_type, schema});
-do_del_snmp(Tab) ->
- TidTs = get_tid_ts_and_lock(schema, write),
- get_tid_ts_and_lock(Tab, read),
- insert_schema_ops(TidTs, make_del_snmp(Tab)).
-
-make_del_snmp(Tab) ->
- ensure_writable(schema),
- Cs = incr_version(val({Tab, cstruct})),
- ensure_active(Cs),
- Cs2 = Cs#cstruct{snmp = []},
- verify_cstruct(Cs2),
- [{op, del_snmp, cs2list(Cs2)}].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-
-transform_table(Tab, Fun, NewAttrs, NewRecName)
- when function(Fun), list(NewAttrs), atom(NewRecName) ->
- schema_transaction(fun() -> do_transform_table(Tab, Fun, NewAttrs, NewRecName) end);
-
-transform_table(Tab, ignore, NewAttrs, NewRecName)
- when list(NewAttrs), atom(NewRecName) ->
- schema_transaction(fun() -> do_transform_table(Tab, ignore, NewAttrs, NewRecName) end);
-
-transform_table(Tab, Fun, NewAttrs, NewRecName) ->
- {aborted,{bad_type, Tab, Fun, NewAttrs, NewRecName}}.
-
-do_transform_table(schema, _Fun, _NewAttrs, _NewRecName) ->
- mnesia:abort({bad_type, schema});
-do_transform_table(Tab, Fun, NewAttrs, NewRecName) ->
- TidTs = get_tid_ts_and_lock(schema, write),
- get_tid_ts_and_lock(Tab, write),
- insert_schema_ops(TidTs, make_transform(Tab, Fun, NewAttrs, NewRecName)).
-
-make_transform(Tab, Fun, NewAttrs, NewRecName) ->
- ensure_writable(schema),
- Cs = incr_version(val({Tab, cstruct})),
- ensure_active(Cs),
- ensure_writable(Tab),
- case mnesia_lib:val({Tab, index}) of
- [] ->
- Cs2 = Cs#cstruct{attributes = NewAttrs, record_name = NewRecName},
- verify_cstruct(Cs2),
- [{op, transform, Fun, cs2list(Cs2)}];
- PosList ->
- DelIdx = fun(Pos, Ncs) ->
- Ix = Ncs#cstruct.index,
- Ncs1 = Ncs#cstruct{index = lists:delete(Pos, Ix)},
- Op = {op, del_index, Pos, cs2list(Ncs1)},
- {Op, Ncs1}
- end,
- AddIdx = fun(Pos, Ncs) ->
- Ix = Ncs#cstruct.index,
- Ix2 = lists:sort([Pos | Ix]),
- Ncs1 = Ncs#cstruct{index = Ix2},
- Op = {op, add_index, Pos, cs2list(Ncs1)},
- {Op, Ncs1}
- end,
- {DelOps, Cs1} = lists:mapfoldl(DelIdx, Cs, PosList),
- Cs2 = Cs1#cstruct{attributes = NewAttrs, record_name = NewRecName},
- {AddOps, Cs3} = lists:mapfoldl(AddIdx, Cs2, PosList),
- verify_cstruct(Cs3),
- lists:flatten([DelOps, {op, transform, Fun, cs2list(Cs2)}, AddOps])
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-
-change_table_access_mode(Tab, Mode) ->
- schema_transaction(fun() -> do_change_table_access_mode(Tab, Mode) end).
-
-do_change_table_access_mode(Tab, Mode) ->
- {_Mod, Tid, Ts} = get_tid_ts_and_lock(schema, write),
- Store = Ts#tidstore.store,
- mnesia_locker:wlock_no_exist(Tid, Store, schema, val({schema, active_replicas})),
- mnesia_locker:wlock_no_exist(Tid, Store, Tab, val({Tab, active_replicas})),
- do_insert_schema_ops(Store, make_change_table_access_mode(Tab, Mode)).
-
-make_change_table_access_mode(Tab, Mode) ->
- ensure_writable(schema),
- Cs = incr_version(val({Tab, cstruct})),
- ensure_active(Cs),
- OldMode = Cs#cstruct.access_mode,
- verify(false, OldMode == Mode, {already_exists, Tab, Mode}),
- Cs2 = Cs#cstruct{access_mode = Mode},
- verify_cstruct(Cs2),
- [{op, change_table_access_mode, cs2list(Cs2), OldMode, Mode}].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-change_table_load_order(Tab, LoadOrder) ->
- schema_transaction(fun() -> do_change_table_load_order(Tab, LoadOrder) end).
-
-do_change_table_load_order(schema, _LoadOrder) ->
- mnesia:abort({bad_type, schema});
-do_change_table_load_order(Tab, LoadOrder) ->
- TidTs = get_tid_ts_and_lock(schema, write),
- get_tid_ts_and_lock(Tab, none),
- insert_schema_ops(TidTs, make_change_table_load_order(Tab, LoadOrder)).
-
-make_change_table_load_order(Tab, LoadOrder) ->
- ensure_writable(schema),
- Cs = incr_version(val({Tab, cstruct})),
- ensure_active(Cs),
- OldLoadOrder = Cs#cstruct.load_order,
- Cs2 = Cs#cstruct{load_order = LoadOrder},
- verify_cstruct(Cs2),
- [{op, change_table_load_order, cs2list(Cs2), OldLoadOrder, LoadOrder}].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-write_table_property(Tab, Prop) when tuple(Prop), size(Prop) >= 1 ->
- schema_transaction(fun() -> do_write_table_property(Tab, Prop) end);
-write_table_property(Tab, Prop) ->
- {aborted, {bad_type, Tab, Prop}}.
-do_write_table_property(Tab, Prop) ->
- TidTs = get_tid_ts_and_lock(schema, write),
- {_, _, Ts} = TidTs,
- Store = Ts#tidstore.store,
- case change_prop_in_existing_op(Tab, Prop, write_property, Store) of
- true ->
- dbg_out("change_prop_in_existing_op"
- "(~p,~p,write_property,Store) -> true~n",
- [Tab,Prop]),
- %% we have merged the table prop into the create_table op
- ok;
- false ->
- dbg_out("change_prop_in_existing_op"
- "(~p,~p,write_property,Store) -> false~n",
- [Tab,Prop]),
- %% this must be an existing table
- get_tid_ts_and_lock(Tab, none),
- insert_schema_ops(TidTs, make_write_table_properties(Tab, [Prop]))
- end.
-
-make_write_table_properties(Tab, Props) ->
- ensure_writable(schema),
- Cs = incr_version(val({Tab, cstruct})),
- ensure_active(Cs),
- make_write_table_properties(Tab, Props, Cs).
-
-make_write_table_properties(Tab, [Prop | Props], Cs) ->
- OldProps = Cs#cstruct.user_properties,
- PropKey = element(1, Prop),
- DelProps = lists:keydelete(PropKey, 1, OldProps),
- MergedProps = lists:merge(DelProps, [Prop]),
- Cs2 = Cs#cstruct{user_properties = MergedProps},
- verify_cstruct(Cs2),
- [{op, write_property, cs2list(Cs2), Prop} |
- make_write_table_properties(Tab, Props, Cs2)];
-make_write_table_properties(_Tab, [], _Cs) ->
- [].
-
-change_prop_in_existing_op(Tab, Prop, How, Store) ->
- Ops = ets:match_object(Store, '_'),
- case update_existing_op(Ops, Tab, Prop, How, []) of
- {true, Ops1} ->
- ets:match_delete(Store, '_'),
- [ets:insert(Store, Op) || Op <- Ops1],
- true;
- false ->
- false
- end.
-
-update_existing_op([{op, Op, L = [{name,Tab}|_], _OldProp}|Ops],
- Tab, Prop, How, Acc) when Op == write_property;
- Op == delete_property ->
- %% Apparently, mnesia_dumper doesn't care about OldProp here -- just L,
- %% so we will throw away OldProp (not that it matters...) and insert Prop.
- %% as element 3.
- L1 = insert_prop(Prop, L, How),
- NewOp = {op, How, L1, Prop},
- {true, lists:reverse(Acc) ++ [NewOp|Ops]};
-update_existing_op([Op = {op, create_table, L}|Ops], Tab, Prop, How, Acc) ->
- case lists:keysearch(name, 1, L) of
- {value, {_, Tab}} ->
- %% Tab is being created here -- insert Prop into L
- L1 = insert_prop(Prop, L, How),
- {true, lists:reverse(Acc) ++ [{op, create_table, L1}|Ops]};
- _ ->
- update_existing_op(Ops, Tab, Prop, How, [Op|Acc])
- end;
-update_existing_op([Op|Ops], Tab, Prop, How, Acc) ->
- update_existing_op(Ops, Tab, Prop, How, [Op|Acc]);
-update_existing_op([], _, _, _, _) ->
- false.
-
-%% perhaps a misnomer. How could also be delete_property... never mind.
-%% Returns the modified L.
-insert_prop(Prop, L, How) ->
- Prev = find_props(L),
- MergedProps = merge_with_previous(How, Prop, Prev),
- replace_props(L, MergedProps).
-
-
-find_props([{user_properties, P}|_]) -> P;
-find_props([_H|T]) -> find_props(T).
-%% we shouldn't reach []
-
-replace_props([{user_properties, _}|T], P) -> [{user_properties, P}|T];
-replace_props([H|T], P) -> [H|replace_props(T, P)].
-%% again, we shouldn't reach []
-
-merge_with_previous(write_property, Prop, Prev) ->
- Key = element(1, Prop),
- Prev1 = lists:keydelete(Key, 1, Prev),
- lists:sort([Prop|Prev1]);
-merge_with_previous(delete_property, PropKey, Prev) ->
- lists:keydelete(PropKey, 1, Prev).
-
-delete_table_property(Tab, PropKey) ->
- schema_transaction(fun() -> do_delete_table_property(Tab, PropKey) end).
-
-do_delete_table_property(Tab, PropKey) ->
- TidTs = get_tid_ts_and_lock(schema, write),
- {_, _, Ts} = TidTs,
- Store = Ts#tidstore.store,
- case change_prop_in_existing_op(Tab, PropKey, delete_property, Store) of
- true ->
- dbg_out("change_prop_in_existing_op"
- "(~p,~p,delete_property,Store) -> true~n",
- [Tab,PropKey]),
- %% we have merged the table prop into the create_table op
- ok;
- false ->
- dbg_out("change_prop_in_existing_op"
- "(~p,~p,delete_property,Store) -> false~n",
- [Tab,PropKey]),
- %% this must be an existing table
- get_tid_ts_and_lock(Tab, none),
- insert_schema_ops(TidTs,
- make_delete_table_properties(Tab, [PropKey]))
- end.
-
-make_delete_table_properties(Tab, PropKeys) ->
- ensure_writable(schema),
- Cs = incr_version(val({Tab, cstruct})),
- ensure_active(Cs),
- make_delete_table_properties(Tab, PropKeys, Cs).
-
-make_delete_table_properties(Tab, [PropKey | PropKeys], Cs) ->
- OldProps = Cs#cstruct.user_properties,
- Props = lists:keydelete(PropKey, 1, OldProps),
- Cs2 = Cs#cstruct{user_properties = Props},
- verify_cstruct(Cs2),
- [{op, delete_property, cs2list(Cs2), PropKey} |
- make_delete_table_properties(Tab, PropKeys, Cs2)];
-make_delete_table_properties(_Tab, [], _Cs) ->
- [].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% Ensure that the transaction can be committed even
-%% if the node crashes and Mnesia is restarted
-prepare_commit(Tid, Commit, WaitFor) ->
- case Commit#commit.schema_ops of
- [] ->
- {false, Commit, optional};
- OrigOps ->
- {Modified, Ops, DumperMode} =
- prepare_ops(Tid, OrigOps, WaitFor, false, [], optional),
- InitBy = schema_prepare,
- GoodRes = {Modified,
- Commit#commit{schema_ops = lists:reverse(Ops)},
- DumperMode},
- case DumperMode of
- optional ->
- dbg_out("Transaction log dump skipped (~p): ~w~n",
- [DumperMode, InitBy]);
- mandatory ->
- case mnesia_controller:sync_dump_log(InitBy) of
- dumped ->
- GoodRes;
- {error, Reason} ->
- mnesia:abort(Reason)
- end
- end,
- case Ops of
- [] ->
- ignore;
- _ ->
- %% We need to grab a dumper lock here, the log may not
- %% be dumped by others, during the schema commit phase.
- mnesia_controller:wait_for_schema_commit_lock()
- end,
- GoodRes
- end.
-
-prepare_ops(Tid, [Op | Ops], WaitFor, Changed, Acc, DumperMode) ->
- case prepare_op(Tid, Op, WaitFor) of
- {true, mandatory} ->
- prepare_ops(Tid, Ops, WaitFor, Changed, [Op | Acc], mandatory);
- {true, optional} ->
- prepare_ops(Tid, Ops, WaitFor, Changed, [Op | Acc], DumperMode);
- {true, Ops2, mandatory} ->
- prepare_ops(Tid, Ops, WaitFor, true, Ops2 ++ Acc, mandatory);
- {true, Ops2, optional} ->
- prepare_ops(Tid, Ops, WaitFor, true, Ops2 ++ Acc, DumperMode);
- {false, mandatory} ->
- prepare_ops(Tid, Ops, WaitFor, true, Acc, mandatory);
- {false, optional} ->
- prepare_ops(Tid, Ops, WaitFor, true, Acc, DumperMode)
- end;
-prepare_ops(_Tid, [], _WaitFor, Changed, Acc, DumperMode) ->
- {Changed, Acc, DumperMode}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Prepare for commit
-%% returns true if Op should be included, i.e. unmodified
-%% {true, Operation} if NewRecs should be included, i.e. modified
-%% false if Op should NOT be included, i.e. modified
-%%
-prepare_op(_Tid, {op, rec, unknown, Rec}, _WaitFor) ->
- {{Tab, Key}, Items, _Op} = Rec,
- case val({Tab, storage_type}) of
- unknown ->
- {false, optional};
- Storage ->
- mnesia_tm:prepare_snmp(Tab, Key, Items), % May exit
- {true, [{op, rec, Storage, Rec}], optional}
- end;
-
-prepare_op(_Tid, {op, announce_im_running, _Node, SchemaDef, Running, RemoteRunning}, _WaitFor) ->
- SchemaCs = list2cs(SchemaDef),
- case lists:member(node(), Running) of
- true ->
- announce_im_running(RemoteRunning -- Running, SchemaCs);
- false ->
- announce_im_running(Running -- RemoteRunning, SchemaCs)
- end,
- {false, optional};
-
-prepare_op(_Tid, {op, sync_trans}, {part, CoordPid}) ->
- CoordPid ! {sync_trans, self()},
- receive
- {sync_trans, CoordPid} ->
- {false, optional};
- Else ->
- mnesia_lib:verbose("sync_op terminated due to ~p~n", [Else]),
- mnesia:abort(Else)
- end;
-
-prepare_op(_Tid, {op, sync_trans}, {coord, Nodes}) ->
- case receive_sync(Nodes, []) of
- {abort, Reason} ->
- mnesia_lib:verbose("sync_op terminated due to ~p~n", [Reason]),
- mnesia:abort(Reason);
- Pids ->
- [Pid ! {sync_trans, self()} || Pid <- Pids],
- {false, optional}
- end;
-prepare_op(Tid, {op, create_table, TabDef}, _WaitFor) ->
- Cs = list2cs(TabDef),
- Storage = mnesia_lib:cs_to_storage_type(node(), Cs),
- UseDir = mnesia_monitor:use_dir(),
- Tab = Cs#cstruct.name,
- case Storage of
- disc_copies when UseDir == false ->
- UseDirReason = {bad_type, Tab, Storage, node()},
- mnesia:abort(UseDirReason);
- disc_only_copies when UseDir == false ->
- UseDirReason = {bad_type, Tab, Storage, node()},
- mnesia:abort(UseDirReason);
- ram_copies ->
- create_ram_table(Tab, Cs#cstruct.type),
- insert_cstruct(Tid, Cs, false),
- {true, optional};
- disc_copies ->
- create_ram_table(Tab, Cs#cstruct.type),
- create_disc_table(Tab),
- insert_cstruct(Tid, Cs, false),
- {true, optional};
- disc_only_copies ->
- create_disc_only_table(Tab,Cs#cstruct.type),
- insert_cstruct(Tid, Cs, false),
- {true, optional};
- unknown -> %% No replica on this node
- insert_cstruct(Tid, Cs, false),
- {true, optional}
- end;
-
-prepare_op(Tid, {op, add_table_copy, Storage, Node, TabDef}, _WaitFor) ->
- Cs = list2cs(TabDef),
- Tab = Cs#cstruct.name,
-
- if
- Tab == schema ->
- {true, optional}; % Nothing to prepare
- Node == node() ->
- case mnesia_lib:val({schema, storage_type}) of
- ram_copies when Storage /= ram_copies ->
- Error = {combine_error, Tab, "has no disc", Node},
- mnesia:abort(Error);
- _ ->
- ok
- end,
- %% Tables are created by mnesia_loader get_network code
- insert_cstruct(Tid, Cs, true),
- case mnesia_controller:get_network_copy(Tab, Cs) of
- {loaded, ok} ->
- {true, optional};
- {not_loaded, ErrReason} ->
- Reason = {system_limit, Tab, {Node, ErrReason}},
- mnesia:abort(Reason)
- end;
- Node /= node() ->
- %% Verify that ram table not has been dumped to disc
- if
- Storage /= ram_copies ->
- case mnesia_lib:schema_cs_to_storage_type(node(), Cs) of
- ram_copies ->
- Dat = mnesia_lib:tab2dcd(Tab),
- case mnesia_lib:exists(Dat) of
- true ->
- mnesia:abort({combine_error, Tab, Storage,
- "Table dumped to disc", node()});
- false ->
- ok
- end;
- _ ->
- ok
- end;
- true ->
- ok
- end,
- insert_cstruct(Tid, Cs, true),
- {true, optional}
- end;
-
-prepare_op(Tid, {op, del_table_copy, _Storage, Node, TabDef}, _WaitFor) ->
- Cs = list2cs(TabDef),
- Tab = Cs#cstruct.name,
-
- if
- %% Schema table lock is always required to run a schema op.
- %% No need to look it.
- node(Tid#tid.pid) == node(), Tab /= schema ->
- Pid = spawn_link(?MODULE, lock_del_table, [Tab, Node, Cs, self()]),
- receive
- {Pid, updated} ->
- {true, optional};
- {Pid, FailReason} ->
- mnesia:abort(FailReason);
- {'EXIT', Pid, Reason} ->
- mnesia:abort(Reason)
- end;
- true ->
- {true, optional}
- end;
-
-prepare_op(_Tid, {op, change_table_copy_type, N, FromS, ToS, TabDef}, _WaitFor)
- when N == node() ->
- Cs = list2cs(TabDef),
- Tab = Cs#cstruct.name,
-
- NotActive = mnesia_lib:not_active_here(Tab),
-
- if
- NotActive == true ->
- mnesia:abort({not_active, Tab, node()});
-
- Tab == schema ->
- case {FromS, ToS} of
- {ram_copies, disc_copies} ->
- case mnesia:system_info(schema_location) of
- opt_disc ->
- ignore;
- _ ->
- mnesia:abort({combine_error, Tab, node(),
- "schema_location must be opt_disc"})
- end,
- Dir = mnesia_lib:dir(),
- case opt_create_dir(true, Dir) of
- ok ->
- purge_dir(Dir, []),
- mnesia_log:purge_all_logs(),
- set(use_dir, true),
- mnesia_log:init(),
- Ns = val({current, db_nodes}), %mnesia_lib:running_nodes(),
- F = fun(U) -> mnesia_recover:log_mnesia_up(U) end,
- lists:foreach(F, Ns),
-
- mnesia_dumper:raw_named_dump_table(Tab, dmp),
- mnesia_checkpoint:tm_change_table_copy_type(Tab, FromS, ToS);
- {error, Reason} ->
- mnesia:abort(Reason)
- end;
- {disc_copies, ram_copies} ->
- Ltabs = val({schema, local_tables}) -- [schema],
- Dtabs = [L || L <- Ltabs,
- val({L, storage_type}) /= ram_copies],
- verify([], Dtabs, {"Disc resident tables", Dtabs, N});
- _ ->
- mnesia:abort({combine_error, Tab, ToS})
- end;
-
- FromS == ram_copies ->
- case mnesia_monitor:use_dir() of
- true ->
- Dat = mnesia_lib:tab2dcd(Tab),
- case mnesia_lib:exists(Dat) of
- true ->
- mnesia:abort({combine_error, Tab, node(),
- "Table dump exists"});
- false ->
- case ToS of
- disc_copies ->
- mnesia_log:ets2dcd(Tab, dmp);
- disc_only_copies ->
- mnesia_dumper:raw_named_dump_table(Tab, dmp)
- end,
- mnesia_checkpoint:tm_change_table_copy_type(Tab, FromS, ToS)
- end;
- false ->
- mnesia:abort({has_no_disc, node()})
- end;
-
- FromS == disc_copies, ToS == disc_only_copies ->
- mnesia_dumper:raw_named_dump_table(Tab, dmp);
- FromS == disc_only_copies ->
- Type = Cs#cstruct.type,
- create_ram_table(Tab, Type),
- Datname = mnesia_lib:tab2dat(Tab),
- Repair = mnesia_monitor:get_env(auto_repair),
- case mnesia_lib:dets_to_ets(Tab, Tab, Datname, Type, Repair, no) of
- loaded -> ok;
- Reason ->
- Err = "Failed to copy disc data to ram",
- mnesia:abort({system_limit, Tab, {Err,Reason}})
- end;
- true ->
- ignore
- end,
- {true, mandatory};
-
-prepare_op(_Tid, {op, change_table_copy_type, N, _FromS, _ToS, _TabDef}, _WaitFor)
- when N /= node() ->
- {true, mandatory};
-
-prepare_op(_Tid, {op, delete_table, _TabDef}, _WaitFor) ->
- {true, mandatory};
-
-prepare_op(_Tid, {op, dump_table, unknown, TabDef}, _WaitFor) ->
- Cs = list2cs(TabDef),
- Tab = Cs#cstruct.name,
- case lists:member(node(), Cs#cstruct.ram_copies) of
- true ->
- case mnesia_monitor:use_dir() of
- true ->
- mnesia_log:ets2dcd(Tab, dmp),
- Size = mnesia:table_info(Tab, size),
- {true, [{op, dump_table, Size, TabDef}], optional};
- false ->
- mnesia:abort({has_no_disc, node()})
- end;
- false ->
- {false, optional}
- end;
-
-prepare_op(_Tid, {op, add_snmp, Ustruct, TabDef}, _WaitFor) ->
- Cs = list2cs(TabDef),
- case mnesia_lib:cs_to_storage_type(node(), Cs) of
- unknown ->
- {true, optional};
- Storage ->
- Tab = Cs#cstruct.name,
- Stab = mnesia_snmp_hook:create_table(Ustruct, Tab, Storage),
- mnesia_lib:set({Tab, {index, snmp}}, Stab),
- {true, optional}
- end;
-
-prepare_op(_Tid, {op, transform, ignore, _TabDef}, _WaitFor) ->
- {true, mandatory}; %% Apply schema changes only.
-prepare_op(_Tid, {op, transform, Fun, TabDef}, _WaitFor) ->
- Cs = list2cs(TabDef),
- case mnesia_lib:cs_to_storage_type(node(), Cs) of
- unknown ->
- {true, mandatory};
- Storage ->
- Tab = Cs#cstruct.name,
- RecName = Cs#cstruct.record_name,
- Type = Cs#cstruct.type,
- NewArity = length(Cs#cstruct.attributes) + 1,
- mnesia_lib:db_fixtable(Storage, Tab, true),
- Key = mnesia_lib:db_first(Tab),
- Op = {op, transform, Fun, TabDef},
- case catch transform_objs(Fun, Tab, RecName,
- Key, NewArity, Storage, Type, [Op]) of
- {'EXIT', Reason} ->
- mnesia_lib:db_fixtable(Storage, Tab, false),
- exit({"Bad transform function", Tab, Fun, node(), Reason});
- Objs ->
- mnesia_lib:db_fixtable(Storage, Tab, false),
- {true, Objs, mandatory}
- end
- end;
-
-prepare_op(_Tid, _Op, _WaitFor) ->
- {true, optional}.
-
-
-create_ram_table(Tab, Type) ->
- Args = [{keypos, 2}, public, named_table, Type],
- case mnesia_monitor:unsafe_mktab(Tab, Args) of
- Tab ->
- ok;
- {error,Reason} ->
- Err = "Failed to create ets table",
- mnesia:abort({system_limit, Tab, {Err,Reason}})
- end.
-create_disc_table(Tab) ->
- File = mnesia_lib:tab2dcd(Tab),
- file:delete(File),
- FArg = [{file, File}, {name, {mnesia,create}},
- {repair, false}, {mode, read_write}],
- case mnesia_monitor:open_log(FArg) of
- {ok,Log} ->
- mnesia_monitor:unsafe_close_log(Log),
- ok;
- {error,Reason} ->
- Err = "Failed to create disc table",
- mnesia:abort({system_limit, Tab, {Err,Reason}})
- end.
-create_disc_only_table(Tab,Type) ->
- File = mnesia_lib:tab2dat(Tab),
- file:delete(File),
- Args = [{file, mnesia_lib:tab2dat(Tab)},
- {type, mnesia_lib:disk_type(Tab, Type)},
- {keypos, 2},
- {repair, mnesia_monitor:get_env(auto_repair)}],
- case mnesia_monitor:unsafe_open_dets(Tab, Args) of
- {ok, _} ->
- ok;
- {error,Reason} ->
- Err = "Failed to create disc table",
- mnesia:abort({system_limit, Tab, {Err,Reason}})
- end.
-
-
-receive_sync([], Pids) ->
- Pids;
-receive_sync(Nodes, Pids) ->
- receive
- {sync_trans, Pid} ->
- Node = node(Pid),
- receive_sync(lists:delete(Node, Nodes), [Pid | Pids]);
- Else ->
- {abort, Else}
- end.
-
-lock_del_table(Tab, Node, Cs, Father) ->
- Ns = val({schema, active_replicas}),
- Lock = fun() ->
- mnesia:write_lock_table(Tab),
- {Res, []} = rpc:multicall(Ns, ?MODULE, set_where_to_read, [Tab, Node, Cs]),
- Filter = fun(ok) ->
- false;
- ({badrpc, {'EXIT', {undef, _}}}) ->
- %% This will be the case we talks with elder nodes
- %% than 3.8.2, they will set where_to_read without
- %% getting a lock.
- false;
- (_) ->
- true
- end,
- [] = lists:filter(Filter, Res),
- ok
- end,
- case mnesia:transaction(Lock) of
- {'atomic', ok} ->
- Father ! {self(), updated};
- {aborted, R} ->
- Father ! {self(), R}
- end,
- unlink(Father),
- exit(normal).
-
-set_where_to_read(Tab, Node, Cs) ->
- case mnesia_lib:val({Tab, where_to_read}) of
- Node ->
- case Cs#cstruct.local_content of
- true ->
- ok;
- false ->
- mnesia_lib:set_remote_where_to_read(Tab, [Node]),
- ok
- end;
- _ ->
- ok
- end.
-
-%% Build up the list in reverse order.
-transform_objs(_Fun, _Tab, _RT, '$end_of_table', _NewArity, _Storage, _Type, Acc) ->
- Acc;
-transform_objs(Fun, Tab, RecName, Key, A, Storage, Type, Acc) ->
- Objs = mnesia_lib:db_get(Tab, Key),
- NextKey = mnesia_lib:db_next_key(Tab, Key),
- Oid = {Tab, Key},
- NewObjs = {Ws, Ds} = transform_obj(Tab, RecName, Key, Fun, Objs, A, Type, [], []),
- if
- NewObjs == {[], []} ->
- transform_objs(Fun, Tab, RecName, NextKey, A, Storage, Type, Acc);
- Type == bag ->
- transform_objs(Fun, Tab, RecName, NextKey, A, Storage, Type,
- [{op, rec, Storage, {Oid, Ws, write}},
- {op, rec, Storage, {Oid, [Oid], delete}} | Acc]);
- Ds == [] ->
- %% Type is set or ordered_set, no need to delete the record first
- transform_objs(Fun, Tab, RecName, NextKey, A, Storage, Type,
- [{op, rec, Storage, {Oid, Ws, write}} | Acc]);
- Ws == [] ->
- transform_objs(Fun, Tab, RecName, NextKey, A, Storage, Type,
- [{op, rec, Storage, {Oid, Ds, write}} | Acc]);
- true ->
- transform_objs(Fun, Tab, RecName, NextKey, A, Storage, Type,
- [{op, rec, Storage, {Oid, Ws, write}},
- {op, rec, Storage, {Oid, Ds, delete}} | Acc])
- end.
-
-transform_obj(Tab, RecName, Key, Fun, [Obj|Rest], NewArity, Type, Ws, Ds) ->
- NewObj = Fun(Obj),
- if
- size(NewObj) /= NewArity ->
- exit({"Bad arity", Obj, NewObj});
- NewObj == Obj ->
- transform_obj(Tab, RecName, Key, Fun, Rest, NewArity, Type, Ws, Ds);
- RecName == element(1, NewObj), Key == element(2, NewObj) ->
- transform_obj(Tab, RecName, Key, Fun, Rest, NewArity,
- Type, [NewObj | Ws], Ds);
- NewObj == delete ->
- case Type of
- bag -> %% Just don't write that object
- transform_obj(Tab, RecName, Key, Fun, Rest,
- NewArity, Type, Ws, Ds);
- _ ->
- transform_obj(Tab, RecName, Key, Fun, Rest, NewArity,
- Type, Ws, [NewObj | Ds])
- end;
- true ->
- exit({"Bad key or Record Name", Obj, NewObj})
- end;
-transform_obj(_Tab, _RecName, _Key, _Fun, [], _NewArity, _Type, Ws, Ds) ->
- {lists:reverse(Ws), lists:reverse(Ds)}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Undo prepare of commit
-undo_prepare_commit(Tid, Commit) ->
- case Commit#commit.schema_ops of
- [] ->
- ignore;
- Ops ->
- %% Catch to allow failure mnesia_controller may not be started
- catch mnesia_controller:release_schema_commit_lock(),
- undo_prepare_ops(Tid, Ops)
- end,
- Commit.
-
-%% Undo in reverse order
-undo_prepare_ops(Tid, [Op | Ops]) ->
- case element(1, Op) of
- TheOp when TheOp /= op, TheOp /= restore_op ->
- undo_prepare_ops(Tid, Ops);
- _ ->
- undo_prepare_ops(Tid, Ops),
- undo_prepare_op(Tid, Op)
- end;
-undo_prepare_ops(_Tid, []) ->
- [].
-
-undo_prepare_op(_Tid, {op, announce_im_running, _, _, Running, RemoteRunning}) ->
- case lists:member(node(), Running) of
- true ->
- unannounce_im_running(RemoteRunning -- Running);
- false ->
- unannounce_im_running(Running -- RemoteRunning)
- end;
-
-undo_prepare_op(_Tid, {op, sync_trans}) ->
- ok;
-
-undo_prepare_op(Tid, {op, create_table, TabDef}) ->
- Cs = list2cs(TabDef),
- Tab = Cs#cstruct.name,
- mnesia_lib:unset({Tab, create_table}),
- delete_cstruct(Tid, Cs),
- case mnesia_lib:cs_to_storage_type(node(), Cs) of
- unknown ->
- ok;
- ram_copies ->
- ram_delete_table(Tab, ram_copies);
- disc_copies ->
- ram_delete_table(Tab, disc_copies),
- DcdFile = mnesia_lib:tab2dcd(Tab),
- %% disc_delete_table(Tab, Storage),
- file:delete(DcdFile);
- disc_only_copies ->
- mnesia_monitor:unsafe_close_dets(Tab),
- Dat = mnesia_lib:tab2dat(Tab),
- %% disc_delete_table(Tab, Storage),
- file:delete(Dat)
- end;
-
-undo_prepare_op(Tid, {op, add_table_copy, Storage, Node, TabDef}) ->
- Cs = list2cs(TabDef),
- Tab = Cs#cstruct.name,
- if
- Tab == schema ->
- true; % Nothing to prepare
- Node == node() ->
- mnesia_checkpoint:tm_del_copy(Tab, Node),
- mnesia_controller:unannounce_add_table_copy(Tab, Node),
- if
- Storage == disc_only_copies; Tab == schema ->
- mnesia_monitor:close_dets(Tab),
- file:delete(mnesia_lib:tab2dat(Tab));
- true ->
- file:delete(mnesia_lib:tab2dcd(Tab))
- end,
- ram_delete_table(Tab, Storage),
- Cs2 = new_cs(Cs, Node, Storage, del),
- insert_cstruct(Tid, Cs2, true); % Don't care about the version
- Node /= node() ->
- mnesia_controller:unannounce_add_table_copy(Tab, Node),
- Cs2 = new_cs(Cs, Node, Storage, del),
- insert_cstruct(Tid, Cs2, true) % Don't care about the version
- end;
-
-undo_prepare_op(_Tid, {op, del_table_copy, _, Node, TabDef})
- when Node == node() ->
- Cs = list2cs(TabDef),
- Tab = Cs#cstruct.name,
- mnesia_lib:set({Tab, where_to_read}, Node);
-
-
-undo_prepare_op(_Tid, {op, change_table_copy_type, N, FromS, ToS, TabDef})
- when N == node() ->
- Cs = list2cs(TabDef),
- Tab = Cs#cstruct.name,
- mnesia_checkpoint:tm_change_table_copy_type(Tab, ToS, FromS),
- Dmp = mnesia_lib:tab2dmp(Tab),
-
- case {FromS, ToS} of
- {ram_copies, disc_copies} when Tab == schema ->
- file:delete(Dmp),
- mnesia_log:purge_some_logs(),
- set(use_dir, false);
- {ram_copies, disc_copies} ->
- file:delete(Dmp);
- {ram_copies, disc_only_copies} ->
- file:delete(Dmp);
- {disc_only_copies, _} ->
- ram_delete_table(Tab, ram_copies);
- _ ->
- ignore
- end;
-
-undo_prepare_op(_Tid, {op, dump_table, _Size, TabDef}) ->
- Cs = list2cs(TabDef),
- case lists:member(node(), Cs#cstruct.ram_copies) of
- true ->
- Tab = Cs#cstruct.name,
- Dmp = mnesia_lib:tab2dmp(Tab),
- file:delete(Dmp);
- false ->
- ignore
- end;
-
-undo_prepare_op(_Tid, {op, add_snmp, _Ustruct, TabDef}) ->
- Cs = list2cs(TabDef),
- case mnesia_lib:cs_to_storage_type(node(), Cs) of
- unknown ->
- true;
- _Storage ->
- Tab = Cs#cstruct.name,
- case ?catch_val({Tab, {index, snmp}}) of
- {'EXIT',_} ->
- ignore;
- Stab ->
- mnesia_snmp_hook:delete_table(Tab, Stab),
- mnesia_lib:unset({Tab, {index, snmp}})
- end
- end;
-
-undo_prepare_op(_Tid, _Op) ->
- ignore.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-ram_delete_table(Tab, Storage) ->
- case Storage of
- unknown ->
- ignore;
- disc_only_copies ->
- ignore;
- _Else ->
- %% delete possible index files and data .....
- %% Got to catch this since if no info has been set in the
- %% mnesia_gvar it will crash
- catch mnesia_index:del_transient(Tab, Storage),
- case ?catch_val({Tab, {index, snmp}}) of
- {'EXIT', _} ->
- ignore;
- Etab ->
- catch mnesia_snmp_hook:delete_table(Tab, Etab)
- end,
- catch ?ets_delete_table(Tab)
- end.
-
-purge_dir(Dir, KeepFiles) ->
- Suffixes = known_suffixes(),
- purge_dir(Dir, KeepFiles, Suffixes).
-
-purge_dir(Dir, KeepFiles, Suffixes) ->
- case dir_exists(Dir) of
- true ->
- {ok, AllFiles} = file:list_dir(Dir),
- purge_known_files(AllFiles, KeepFiles, Dir, Suffixes);
- false ->
- ok
- end.
-
-purge_tmp_files() ->
- case mnesia_monitor:use_dir() of
- true ->
- Dir = mnesia_lib:dir(),
- KeepFiles = [],
- Exists = mnesia_lib:exists(mnesia_lib:tab2dat(schema)),
- case Exists of
- true ->
- Suffixes = tmp_suffixes(),
- purge_dir(Dir, KeepFiles, Suffixes);
- false ->
- %% Interrupted change of storage type
- %% for schema table
- Suffixes = known_suffixes(),
- purge_dir(Dir, KeepFiles, Suffixes),
- mnesia_lib:set(use_dir, false)
- end;
-
- false ->
- ok
- end.
-
-purge_known_files([File | Tail], KeepFiles, Dir, Suffixes) ->
- case lists:member(File, KeepFiles) of
- true ->
- ignore;
- false ->
- case has_known_suffix(File, Suffixes, false) of
- false ->
- ignore;
- true ->
- AbsFile = filename:join([Dir, File]),
- file:delete(AbsFile)
- end
- end,
- purge_known_files(Tail, KeepFiles, Dir, Suffixes);
-purge_known_files([], _KeepFiles, _Dir, _Suffixes) ->
- ok.
-
-has_known_suffix(_File, _Suffixes, true) ->
- true;
-has_known_suffix(File, [Suffix | Tail], false) ->
- has_known_suffix(File, Tail, lists:suffix(Suffix, File));
-has_known_suffix(_File, [], Bool) ->
- Bool.
-
-known_suffixes() -> real_suffixes() ++ tmp_suffixes().
-
-real_suffixes() -> [".DAT", ".LOG", ".BUP", ".DCL", ".DCD"].
-
-tmp_suffixes() -> [".TMP", ".BUPTMP", ".RET", ".DMP"].
-
-info() ->
- Tabs = lists:sort(val({schema, tables})),
- lists:foreach(fun(T) -> info(T) end, Tabs),
- ok.
-
-info(Tab) ->
- Props = get_table_properties(Tab),
- io:format("-- Properties for ~w table --- ~n",[Tab]),
- info2(Tab, Props).
-info2(Tab, [{cstruct, _V} | Tail]) -> % Ignore cstruct
- info2(Tab, Tail);
-info2(Tab, [{frag_hash, _V} | Tail]) -> % Ignore frag_hash
- info2(Tab, Tail);
-info2(Tab, [{P, V} | Tail]) ->
- io:format("~-20w -> ~p~n",[P,V]),
- info2(Tab, Tail);
-info2(_, []) ->
- io:format("~n", []).
-
-get_table_properties(Tab) ->
- case catch mnesia_lib:db_match_object(ram_copies,
- mnesia_gvar, {{Tab, '_'}, '_'}) of
- {'EXIT', _} ->
- mnesia:abort({no_exists, Tab, all});
- RawGvar ->
- case [{Item, Val} || {{_Tab, Item}, Val} <- RawGvar] of
- [] ->
- [];
- Gvar ->
- Size = {size, mnesia:table_info(Tab, size)},
- Memory = {memory, mnesia:table_info(Tab, memory)},
- Master = {master_nodes, mnesia:table_info(Tab, master_nodes)},
- lists:sort([Size, Memory, Master | Gvar])
- end
- end.
-
-%%%%%%%%%%% RESTORE %%%%%%%%%%%
-
--record(r, {iter = schema,
- module,
- table_options = [],
- default_op = clear_tables,
- tables = [],
- opaque,
- insert_op = error_fun,
- recs = error_recs
- }).
-
-restore(Opaque) ->
- restore(Opaque, [], mnesia_monitor:get_env(backup_module)).
-restore(Opaque, Args) when list(Args) ->
- restore(Opaque, Args, mnesia_monitor:get_env(backup_module));
-restore(_Opaque, BadArg) ->
- {aborted, {badarg, BadArg}}.
-restore(Opaque, Args, Module) when list(Args), atom(Module) ->
- InitR = #r{opaque = Opaque, module = Module},
- case catch lists:foldl(fun check_restore_arg/2, InitR, Args) of
- R when record(R, r) ->
- case mnesia_bup:read_schema(Module, Opaque) of
- {error, Reason} ->
- {aborted, Reason};
- BupSchema ->
- schema_transaction(fun() -> do_restore(R, BupSchema) end)
- end;
- {'EXIT', Reason} ->
- {aborted, Reason}
- end;
-restore(_Opaque, Args, Module) ->
- {aborted, {badarg, Args, Module}}.
-
-check_restore_arg({module, Mod}, R) when atom(Mod) ->
- R#r{module = Mod};
-
-check_restore_arg({clear_tables, List}, R) when list(List) ->
- case lists:member(schema, List) of
- false ->
- TableList = [{Tab, clear_tables} || Tab <- List],
- R#r{table_options = R#r.table_options ++ TableList};
- true ->
- exit({badarg, {clear_tables, schema}})
- end;
-check_restore_arg({recreate_tables, List}, R) when list(List) ->
- case lists:member(schema, List) of
- false ->
- TableList = [{Tab, recreate_tables} || Tab <- List],
- R#r{table_options = R#r.table_options ++ TableList};
- true ->
- exit({badarg, {recreate_tables, schema}})
- end;
-check_restore_arg({keep_tables, List}, R) when list(List) ->
- TableList = [{Tab, keep_tables} || Tab <- List],
- R#r{table_options = R#r.table_options ++ TableList};
-check_restore_arg({skip_tables, List}, R) when list(List) ->
- TableList = [{Tab, skip_tables} || Tab <- List],
- R#r{table_options = R#r.table_options ++ TableList};
-check_restore_arg({default_op, Op}, R) ->
- case Op of
- clear_tables -> ok;
- recreate_tables -> ok;
- keep_tables -> ok;
- skip_tables -> ok;
- Else ->
- exit({badarg, {bad_default_op, Else}})
- end,
- R#r{default_op = Op};
-
-check_restore_arg(BadArg,_) ->
- exit({badarg, BadArg}).
-
-do_restore(R, BupSchema) ->
- TidTs = get_tid_ts_and_lock(schema, write),
- R2 = restore_schema(BupSchema, R),
- insert_schema_ops(TidTs, [{restore_op, R2}]),
- [element(1, TabStruct) || TabStruct <- R2#r.tables].
-
-arrange_restore(R, Fun, Recs) ->
- R2 = R#r{insert_op = Fun, recs = Recs},
- case mnesia_bup:iterate(R#r.module, fun restore_items/4, R#r.opaque, R2) of
- {ok, R3} -> R3#r.recs;
- {error, Reason} -> mnesia:abort(Reason);
- Reason -> mnesia:abort(Reason)
- end.
-
-restore_items([Rec | Recs], Header, Schema, R) ->
- Tab = element(1, Rec),
- case lists:keysearch(Tab, 1, R#r.tables) of
- {value, {Tab, Where, Snmp, RecName}} ->
- {Rest, NRecs} =
- restore_tab_items([Rec | Recs], Tab, RecName, Where, Snmp,
- R#r.recs, R#r.insert_op),
- restore_items(Rest, Header, Schema, R#r{recs = NRecs});
- false ->
- Rest = skip_tab_items(Recs, Tab),
- restore_items(Rest, Header, Schema, R)
- end;
-
-restore_items([], _Header, _Schema, R) ->
- R.
-
-restore_func(Tab, R) ->
- case lists:keysearch(Tab, 1, R#r.table_options) of
- {value, {Tab, OP}} ->
- OP;
- false ->
- R#r.default_op
- end.
-
-where_to_commit(Tab, CsList) ->
- Ram = [{N, ram_copies} || N <- pick(Tab, ram_copies, CsList, [])],
- Disc = [{N, disc_copies} || N <- pick(Tab, disc_copies, CsList, [])],
- DiscO = [{N, disc_only_copies} || N <- pick(Tab, disc_only_copies, CsList, [])],
- Ram ++ Disc ++ DiscO.
-
-%% Changes of the Meta info of schema itself is not allowed
-restore_schema([{schema, schema, _List} | Schema], R) ->
- restore_schema(Schema, R);
-restore_schema([{schema, Tab, List} | Schema], R) ->
- case restore_func(Tab, R) of
- clear_tables ->
- do_clear_table(Tab),
- Where = val({Tab, where_to_commit}),
- Snmp = val({Tab, snmp}),
- RecName = val({Tab, record_name}),
- R2 = R#r{tables = [{Tab, Where, Snmp, RecName} | R#r.tables]},
- restore_schema(Schema, R2);
- recreate_tables ->
- TidTs = get_tid_ts_and_lock(Tab, write),
- NC = {cookie, ?unique_cookie},
- List2 = lists:keyreplace(cookie, 1, List, NC),
- Where = where_to_commit(Tab, List2),
- Snmp = pick(Tab, snmp, List2, []),
- RecName = pick(Tab, record_name, List2, Tab),
-% case ?catch_val({Tab, cstruct}) of
-% {'EXIT', _} ->
-% ignore;
-% OldCs when record(OldCs, cstruct) ->
-% do_delete_table(Tab)
-% end,
-% unsafe_do_create_table(list2cs(List2)),
- insert_schema_ops(TidTs, [{op, restore_recreate, List2}]),
- R2 = R#r{tables = [{Tab, Where, Snmp, RecName} | R#r.tables]},
- restore_schema(Schema, R2);
- keep_tables ->
- get_tid_ts_and_lock(Tab, write),
- Where = val({Tab, where_to_commit}),
- Snmp = val({Tab, snmp}),
- RecName = val({Tab, record_name}),
- R2 = R#r{tables = [{Tab, Where, Snmp, RecName} | R#r.tables]},
- restore_schema(Schema, R2);
- skip_tables ->
- restore_schema(Schema, R)
- end;
-
-restore_schema([{schema, Tab} | Schema], R) ->
- do_delete_table(Tab),
- Tabs = lists:delete(Tab,R#r.tables),
- restore_schema(Schema, R#r{tables = Tabs});
-restore_schema([], R) ->
- R.
-
-restore_tab_items([Rec | Rest], Tab, RecName, Where, Snmp, Recs, Op)
- when element(1, Rec) == Tab ->
- NewRecs = Op(Rec, Recs, RecName, Where, Snmp),
- restore_tab_items(Rest, Tab, RecName, Where, Snmp, NewRecs, Op);
-
-restore_tab_items(Rest, _Tab, _RecName, _Where, _Snmp, Recs, _Op) ->
- {Rest, Recs}.
-
-skip_tab_items([Rec| Rest], Tab)
- when element(1, Rec) == Tab ->
- skip_tab_items(Rest, Tab);
-skip_tab_items(Recs, _) ->
- Recs.
-
-%%%%%%%%% Dump tables %%%%%%%%%%%%%
-dump_tables(Tabs) when list(Tabs) ->
- schema_transaction(fun() -> do_dump_tables(Tabs) end);
-dump_tables(Tabs) ->
- {aborted, {bad_type, Tabs}}.
-
-do_dump_tables(Tabs) ->
- TidTs = get_tid_ts_and_lock(schema, write),
- insert_schema_ops(TidTs, make_dump_tables(Tabs)).
-
-make_dump_tables([schema | _Tabs]) ->
- mnesia:abort({bad_type, schema});
-make_dump_tables([Tab | Tabs]) ->
- get_tid_ts_and_lock(Tab, read),
- TabDef = get_create_list(Tab),
- DiscResident = val({Tab, disc_copies}) ++ val({Tab, disc_only_copies}),
- verify([], DiscResident,
- {"Only allowed on ram_copies", Tab, DiscResident}),
- [{op, dump_table, unknown, TabDef} | make_dump_tables(Tabs)];
-make_dump_tables([]) ->
- [].
-
-%% Merge the local schema with the schema on other nodes
-merge_schema() ->
- schema_transaction(fun() -> do_merge_schema() end).
-
-do_merge_schema() ->
- {_Mod, Tid, Ts} = get_tid_ts_and_lock(schema, write),
- Connected = val(recover_nodes),
- Running = val({current, db_nodes}),
- Store = Ts#tidstore.store,
- case Connected -- Running of
- [Node | _] ->
- %% Time for a schema merging party!
- mnesia_locker:wlock_no_exist(Tid, Store, schema, [Node]),
-
- case rpc:call(Node, mnesia_controller, get_cstructs, []) of
- {cstructs, Cstructs, RemoteRunning1} ->
- LockedAlready = Running ++ [Node],
- {New, Old} = mnesia_recover:connect_nodes(RemoteRunning1),
- RemoteRunning = mnesia_lib:intersect(New ++ Old, RemoteRunning1),
- if
- RemoteRunning /= RemoteRunning1 ->
- mnesia_lib:error("Mnesia on ~p could not connect to node(s) ~p~n",
- [node(), RemoteRunning1 -- RemoteRunning]);
- true -> ok
- end,
- NeedsLock = RemoteRunning -- LockedAlready,
- mnesia_locker:wlock_no_exist(Tid, Store, schema, NeedsLock),
-
- {value, SchemaCs} =
- lists:keysearch(schema, #cstruct.name, Cstructs),
-
- %% Announce that Node is running
- A = [{op, announce_im_running, node(),
- cs2list(SchemaCs), Running, RemoteRunning}],
- do_insert_schema_ops(Store, A),
-
- %% Introduce remote tables to local node
- do_insert_schema_ops(Store, make_merge_schema(Node, Cstructs)),
-
- %% Introduce local tables to remote nodes
- Tabs = val({schema, tables}),
- Ops = [{op, merge_schema, get_create_list(T)}
- || T <- Tabs,
- not lists:keymember(T, #cstruct.name, Cstructs)],
- do_insert_schema_ops(Store, Ops),
-
- %% Ensure that the txn will be committed on all nodes
- announce_im_running(RemoteRunning, SchemaCs),
- {merged, Running, RemoteRunning};
- {error, Reason} ->
- {"Cannot get cstructs", Node, Reason};
- {badrpc, Reason} ->
- {"Cannot get cstructs", Node, {badrpc, Reason}}
- end;
- [] ->
- %% No more nodes to merge schema with
- not_merged
- end.
-
-make_merge_schema(Node, [Cs | Cstructs]) ->
- Ops = do_make_merge_schema(Node, Cs),
- Ops ++ make_merge_schema(Node, Cstructs);
-make_merge_schema(_Node, []) ->
- [].
-
-%% Merge definitions of schema table
-do_make_merge_schema(Node, RemoteCs)
- when RemoteCs#cstruct.name == schema ->
- Cs = val({schema, cstruct}),
- Masters = mnesia_recover:get_master_nodes(schema),
- HasRemoteMaster = lists:member(Node, Masters),
- HasLocalMaster = lists:member(node(), Masters),
- Force = HasLocalMaster or HasRemoteMaster,
- %% What is the storage types opinions?
- StCsLocal = mnesia_lib:cs_to_storage_type(node(), Cs),
- StRcsLocal = mnesia_lib:cs_to_storage_type(node(), RemoteCs),
- StCsRemote = mnesia_lib:cs_to_storage_type(Node, Cs),
- StRcsRemote = mnesia_lib:cs_to_storage_type(Node, RemoteCs),
-
- if
- Cs#cstruct.cookie == RemoteCs#cstruct.cookie,
- Cs#cstruct.version == RemoteCs#cstruct.version ->
- %% Great, we have the same cookie and version
- %% and do not need to merge cstructs
- [];
-
- Cs#cstruct.cookie /= RemoteCs#cstruct.cookie,
- Cs#cstruct.disc_copies /= [],
- RemoteCs#cstruct.disc_copies /= [] ->
- %% Both cstructs involves disc nodes
- %% and we cannot merge them
- if
- HasLocalMaster == true,
- HasRemoteMaster == false ->
- %% Choose local cstruct,
- %% since it's the master
- [{op, merge_schema, cs2list(Cs)}];
-
- HasRemoteMaster == true,
- HasLocalMaster == false ->
- %% Choose remote cstruct,
- %% since it's the master
- [{op, merge_schema, cs2list(RemoteCs)}];
-
- true ->
- Str = io_lib:format("Incompatible schema cookies. "
- "Please, restart from old backup."
- "~w = ~w, ~w = ~w~n",
- [Node, cs2list(RemoteCs), node(), cs2list(Cs)]),
- throw(Str)
- end;
-
- StCsLocal /= StRcsLocal, StRcsLocal /= unknown ->
- Str = io_lib:format("Incompatible schema storage types. "
- "on ~w storage ~w, on ~w storage ~w~n",
- [node(), StCsLocal, Node, StRcsLocal]),
- throw(Str);
- StCsRemote /= StRcsRemote, StCsRemote /= unknown ->
- Str = io_lib:format("Incompatible schema storage types. "
- "on ~w storage ~w, on ~w storage ~w~n",
- [node(), StCsRemote, Node, StRcsRemote]),
- throw(Str);
-
- Cs#cstruct.disc_copies /= [] ->
- %% Choose local cstruct,
- %% since it involves disc nodes
- MergedCs = merge_cstructs(Cs, RemoteCs, Force),
- [{op, merge_schema, cs2list(MergedCs)}];
-
- RemoteCs#cstruct.disc_copies /= [] ->
- %% Choose remote cstruct,
- %% since it involves disc nodes
- MergedCs = merge_cstructs(RemoteCs, Cs, Force),
- [{op, merge_schema, cs2list(MergedCs)}];
-
- Cs > RemoteCs ->
- %% Choose remote cstruct
- MergedCs = merge_cstructs(RemoteCs, Cs, Force),
- [{op, merge_schema, cs2list(MergedCs)}];
-
- true ->
- %% Choose local cstruct
- MergedCs = merge_cstructs(Cs, RemoteCs, Force),
- [{op, merge_schema, cs2list(MergedCs)}]
- end;
-
-%% Merge definitions of normal table
-do_make_merge_schema(Node, RemoteCs) ->
- Tab = RemoteCs#cstruct.name,
- Masters = mnesia_recover:get_master_nodes(schema),
- HasRemoteMaster = lists:member(Node, Masters),
- HasLocalMaster = lists:member(node(), Masters),
- Force = HasLocalMaster or HasRemoteMaster,
- case ?catch_val({Tab, cstruct}) of
- {'EXIT', _} ->
- %% A completely new table, created while Node was down
- [{op, merge_schema, cs2list(RemoteCs)}];
- Cs when Cs#cstruct.cookie == RemoteCs#cstruct.cookie ->
- if
- Cs#cstruct.version == RemoteCs#cstruct.version ->
- %% We have exactly the same version of the
- %% table def
- [];
-
- Cs#cstruct.version > RemoteCs#cstruct.version ->
- %% Oops, we have different versions
- %% of the table def, lets merge them.
- %% The only changes that may have occurred
- %% is that new replicas may have been added.
- MergedCs = merge_cstructs(Cs, RemoteCs, Force),
- [{op, merge_schema, cs2list(MergedCs)}];
-
- Cs#cstruct.version < RemoteCs#cstruct.version ->
- %% Oops, we have different versions
- %% of the table def, lets merge them
- MergedCs = merge_cstructs(RemoteCs, Cs, Force),
- [{op, merge_schema, cs2list(MergedCs)}]
- end;
- Cs ->
- %% Different cookies, not possible to merge
- if
- HasLocalMaster == true,
- HasRemoteMaster == false ->
- %% Choose local cstruct,
- %% since it's the master
- [{op, merge_schema, cs2list(Cs)}];
-
- HasRemoteMaster == true,
- HasLocalMaster == false ->
- %% Choose remote cstruct,
- %% since it's the master
- [{op, merge_schema, cs2list(RemoteCs)}];
-
- true ->
- Str = io_lib:format("Bad cookie in table definition"
- " ~w: ~w = ~w, ~w = ~w~n",
- [Tab, node(), Cs, Node, RemoteCs]),
- throw(Str)
- end
- end.
-
-%% Change of table definitions (cstructs) requires all replicas
-%% of the table to be active. New replicas, db_nodes and tables
-%% may however be added even if some replica is inactive. These
-%% invariants must be enforced in order to allow merge of cstructs.
-%%
-%% Returns a new cstruct or issues a fatal error
-merge_cstructs(Cs, RemoteCs, Force) ->
- verify_cstruct(Cs),
- case catch do_merge_cstructs(Cs, RemoteCs, Force) of
- {'EXIT', {aborted, _Reason}} when Force == true ->
- Cs;
- {'EXIT', Reason} ->
- exit(Reason);
- MergedCs when record(MergedCs, cstruct) ->
- MergedCs;
- Other ->
- throw(Other)
- end.
-
-do_merge_cstructs(Cs, RemoteCs, Force) ->
- verify_cstruct(RemoteCs),
- Ns = mnesia_lib:uniq(mnesia_lib:cs_to_nodes(Cs) ++
- mnesia_lib:cs_to_nodes(RemoteCs)),
- {AnythingNew, MergedCs} =
- merge_storage_type(Ns, false, Cs, RemoteCs, Force),
- MergedCs2 = merge_versions(AnythingNew, MergedCs, RemoteCs, Force),
- verify_cstruct(MergedCs2),
- MergedCs2.
-
-merge_storage_type([N | Ns], AnythingNew, Cs, RemoteCs, Force) ->
- Local = mnesia_lib:cs_to_storage_type(N, Cs),
- Remote = mnesia_lib:cs_to_storage_type(N, RemoteCs),
- case compare_storage_type(true, Local, Remote) of
- {same, _Storage} ->
- merge_storage_type(Ns, AnythingNew, Cs, RemoteCs, Force);
- {diff, Storage} ->
- Cs2 = change_storage_type(N, Storage, Cs),
- merge_storage_type(Ns, true, Cs2, RemoteCs, Force);
- incompatible when Force == true ->
- merge_storage_type(Ns, AnythingNew, Cs, RemoteCs, Force);
- Other ->
- Str = io_lib:format("Cannot merge storage type for node ~w "
- "in cstruct ~w with remote cstruct ~w (~w)~n",
- [N, Cs, RemoteCs, Other]),
- throw(Str)
- end;
-merge_storage_type([], AnythingNew, MergedCs, _RemoteCs, _Force) ->
- {AnythingNew, MergedCs}.
-
-compare_storage_type(_Retry, Any, Any) ->
- {same, Any};
-compare_storage_type(_Retry, unknown, Any) ->
- {diff, Any};
-compare_storage_type(_Retry, ram_copies, disc_copies) ->
- {diff, disc_copies};
-compare_storage_type(_Retry, disc_copies, disc_only_copies) ->
- {diff, disc_only_copies};
-compare_storage_type(true, One, Another) ->
- compare_storage_type(false, Another, One);
-compare_storage_type(false, _One, _Another) ->
- incompatible.
-
-change_storage_type(N, ram_copies, Cs) ->
- Nodes = [N | Cs#cstruct.ram_copies],
- Cs#cstruct{ram_copies = mnesia_lib:uniq(Nodes)};
-change_storage_type(N, disc_copies, Cs) ->
- Nodes = [N | Cs#cstruct.disc_copies],
- Cs#cstruct{disc_copies = mnesia_lib:uniq(Nodes)};
-change_storage_type(N, disc_only_copies, Cs) ->
- Nodes = [N | Cs#cstruct.disc_only_copies],
- Cs#cstruct{disc_only_copies = mnesia_lib:uniq(Nodes)}.
-
-%% BUGBUG: Verify match of frag info; equalit demanded for all but add_node
-
-merge_versions(AnythingNew, Cs, RemoteCs, Force) ->
- if
- Cs#cstruct.name == schema ->
- ok;
- Cs#cstruct.name /= schema,
- Cs#cstruct.cookie == RemoteCs#cstruct.cookie ->
- ok;
- Force == true ->
- ok;
- true ->
- Str = io_lib:format("Bad cookies. Cannot merge definitions of "
- "table ~w. Local = ~w, Remote = ~w~n",
- [Cs#cstruct.name, Cs, RemoteCs]),
- throw(Str)
- end,
- if
- Cs#cstruct.name == RemoteCs#cstruct.name,
- Cs#cstruct.type == RemoteCs#cstruct.type,
- Cs#cstruct.local_content == RemoteCs#cstruct.local_content,
- Cs#cstruct.attributes == RemoteCs#cstruct.attributes,
- Cs#cstruct.index == RemoteCs#cstruct.index,
- Cs#cstruct.snmp == RemoteCs#cstruct.snmp,
- Cs#cstruct.access_mode == RemoteCs#cstruct.access_mode,
- Cs#cstruct.load_order == RemoteCs#cstruct.load_order,
- Cs#cstruct.user_properties == RemoteCs#cstruct.user_properties ->
- do_merge_versions(AnythingNew, Cs, RemoteCs);
- Force == true ->
- do_merge_versions(AnythingNew, Cs, RemoteCs);
- true ->
- Str1 = io_lib:format("Cannot merge definitions of "
- "table ~w. Local = ~w, Remote = ~w~n",
- [Cs#cstruct.name, Cs, RemoteCs]),
- throw(Str1)
- end.
-
-do_merge_versions(AnythingNew, MergedCs, RemoteCs) ->
- {{Major1, Minor1}, _Detail1} = MergedCs#cstruct.version,
- {{Major2, Minor2}, _Detail2} = RemoteCs#cstruct.version,
- if
- MergedCs#cstruct.version == RemoteCs#cstruct.version ->
- MergedCs;
- AnythingNew == false ->
- MergedCs;
- Major1 == Major2 ->
- Minor = lists:max([Minor1, Minor2]),
- V = {{Major1, Minor}, dummy},
- incr_version(MergedCs#cstruct{version = V});
- Major1 /= Major2 ->
- Major = lists:max([Major1, Major2]),
- V = {{Major, 0}, dummy},
- incr_version(MergedCs#cstruct{version = V})
- end.
-
-announce_im_running([N | Ns], SchemaCs) ->
- {L1, L2} = mnesia_recover:connect_nodes([N]),
- case lists:member(N, L1) or lists:member(N, L2) of
- true ->
-%% dbg_out("Adding ~p to {current db_nodes} ~n", [N]), %% qqqq
- mnesia_lib:add({current, db_nodes}, N),
- mnesia_controller:add_active_replica(schema, N, SchemaCs);
- false ->
- ignore
- end,
- announce_im_running(Ns, SchemaCs);
-announce_im_running([], _) ->
- [].
-
-unannounce_im_running([N | Ns]) ->
- mnesia_lib:del({current, db_nodes}, N),
- mnesia_controller:del_active_replica(schema, N),
- mnesia_recover:disconnect(N),
- unannounce_im_running(Ns);
-unannounce_im_running([]) ->
- [].
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_snmp_hook.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_snmp_hook.erl
deleted file mode 100644
index 458323c0e4..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_snmp_hook.erl
+++ /dev/null
@@ -1,271 +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: mnesia_snmp_hook.erl,v 1.1 2008/12/17 09:53:39 mikpe Exp $
-%%
--module(mnesia_snmp_hook).
-
-%% Hooks (called from mnesia)
--export([check_ustruct/1, create_table/3, delete_table/2,
- key_to_oid/3, update/1, start/2,
- get_row/2, get_next_index/2, get_mnesia_key/2]).
-
-%% sys callback functions
--export([system_continue/3,
- system_terminate/4,
- system_code_change/4
- ]).
-
-%% Internal exports
--export([b_init/2]).
-
-check_ustruct([]) ->
- true; %% default value, not SNMP'ified
-check_ustruct([{key, Types}]) ->
- is_snmp_type(to_list(Types));
-check_ustruct(_) -> false.
-
-to_list(Tuple) when tuple(Tuple) -> tuple_to_list(Tuple);
-to_list(X) -> [X].
-
-is_snmp_type([integer | T]) -> is_snmp_type(T);
-is_snmp_type([string | T]) -> is_snmp_type(T);
-is_snmp_type([fix_string | T]) -> is_snmp_type(T);
-is_snmp_type([]) -> true;
-is_snmp_type(_) -> false.
-
-create_table([], MnesiaTab, _Storage) ->
- mnesia:abort({badarg, MnesiaTab, {snmp, empty_snmpstruct}});
-
-create_table([{key, Us}], MnesiaTab, Storage) ->
- Tree = b_new(MnesiaTab, Us),
- mnesia_lib:db_fixtable(Storage, MnesiaTab, true),
- First = mnesia_lib:db_first(Storage, MnesiaTab),
- build_table(First, MnesiaTab, Tree, Us, Storage),
- mnesia_lib:db_fixtable(Storage, MnesiaTab, false),
- Tree.
-
-build_table(MnesiaKey, MnesiaTab, Tree, Us, Storage)
- when MnesiaKey /= '$end_of_table' ->
-%% SnmpKey = key_to_oid(MnesiaTab, MnesiaKey, Us),
-%% update(write, Tree, MnesiaKey, SnmpKey),
- update(write, Tree, MnesiaKey, MnesiaKey),
- Next = mnesia_lib:db_next_key(Storage, MnesiaTab, MnesiaKey),
- build_table(Next, MnesiaTab, Tree, Us, Storage);
-build_table('$end_of_table', _MnesiaTab, _Tree, _Us, _Storage) ->
- ok.
-
-delete_table(_MnesiaTab, Tree) ->
- exit(Tree, shutdown),
- ok.
-
-%%-----------------------------------------------------------------
-%% update({Op, MnesiaTab, MnesiaKey, SnmpKey})
-%%-----------------------------------------------------------------
-
-update({clear_table, MnesiaTab}) ->
- Tree = mnesia_lib:val({MnesiaTab, {index, snmp}}),
- b_clear(Tree);
-
-update({Op, MnesiaTab, MnesiaKey, SnmpKey}) ->
- Tree = mnesia_lib:val({MnesiaTab, {index, snmp}}),
- update(Op, Tree, MnesiaKey, SnmpKey).
-
-update(Op, Tree, MnesiaKey, _) ->
- case Op of
- write ->
- b_insert(Tree, MnesiaKey, MnesiaKey);
- update_counter ->
- ignore;
- delete ->
- b_delete(Tree, MnesiaKey);
- delete_object ->
- b_delete(Tree, MnesiaKey)
- end,
- ok.
-
-%%-----------------------------------------------------------------
-%% Func: key_to_oid(Tab, Key, Ustruct)
-%% Args: Key ::= key()
-%% key() ::= int() | string() | {int() | string()}
-%% Type ::= {fix_string | term()}
-%% Make an OBJECT IDENTIFIER out of it.
-%% Variable length objects are prepended by their length.
-%% Ex. Key = {"pelle", 42} AND Type = {string, integer} =>
-%% OID [5, $p, $e, $l, $l, $e, 42]
-%% Key = {"pelle", 42} AND Type = {fix_string, integer} =>
-%% OID [$p, $e, $l, $l, $e, 42]
-%%-----------------------------------------------------------------
-key_to_oid(Tab, Key, [{key, Types}]) ->
- MnesiaOid = {Tab, Key},
- if
- tuple(Key), tuple(Types) ->
- case {size(Key), size(Types)} of
- {Size, Size} ->
- keys_to_oid(MnesiaOid, Size, Key, [], Types);
- _ ->
- exit({bad_snmp_key, MnesiaOid})
- end;
- true ->
- key_to_oid_i(MnesiaOid, Key, Types)
- end.
-
-key_to_oid_i(_MnesiaOid, Key, integer) when integer(Key) -> [Key];
-key_to_oid_i(_MnesiaOid, Key, fix_string) when list(Key) -> Key;
-key_to_oid_i(_MnesiaOid, Key, string) when list(Key) -> [length(Key) | Key];
-key_to_oid_i(MnesiaOid, Key, Type) ->
- exit({bad_snmp_key, [MnesiaOid, Key, Type]}).
-
-keys_to_oid(_MnesiaOid, 0, _Key, Oid, _Types) -> Oid;
-keys_to_oid(MnesiaOid, N, Key, Oid, Types) ->
- Type = element(N, Types),
- KeyPart = element(N, Key),
- Oid2 = key_to_oid_i(MnesiaOid, KeyPart, Type) ++ Oid,
- keys_to_oid(MnesiaOid, N-1, Key, Oid2, Types).
-
-%%-----------------------------------------------------------------
-%% Func: get_row/2
-%% Args: Name is the name of the table (atom)
-%% RowIndex is an Oid
-%% Returns: {ok, Row} | undefined
-%% Note that the Row returned might contain columns that
-%% are not visible via SNMP. e.g. the first column may be
-%% ifIndex, and the last MFA ({ifIndex, col1, col2, MFA}).
-%% where ifIndex is used only as index (not as a real col),
-%% and MFA as extra info, used by the application.
-%%-----------------------------------------------------------------
-get_row(Name, RowIndex) ->
- Tree = mnesia_lib:val({Name, {index, snmp}}),
- case b_lookup(Tree, RowIndex) of
- {ok, {_RowIndex, Key}} ->
- [Row] = mnesia:dirty_read({Name, Key}),
- {ok, Row};
- _ ->
- undefined
- end.
-
-%%-----------------------------------------------------------------
-%% Func: get_next_index/2
-%% Args: Name is the name of the table (atom)
-%% RowIndex is an Oid
-%% Returns: {ok, NextIndex} | endOfTable
-%%-----------------------------------------------------------------
-get_next_index(Name, RowIndex) ->
- Tree = mnesia_lib:val({Name, {index, snmp}}),
- case b_lookup_next(Tree, RowIndex) of
- {ok, {NextIndex, _Key}} ->
- {ok, NextIndex};
- _ ->
- endOfTable
- end.
-
-%%-----------------------------------------------------------------
-%% Func: get_mnesia_key/2
-%% Purpose: Get the mnesia key corresponding to the RowIndex.
-%% Args: Name is the name of the table (atom)
-%% RowIndex is an Oid
-%% Returns: {ok, Key} | undefiend
-%%-----------------------------------------------------------------
-get_mnesia_key(Name, RowIndex) ->
- Tree = mnesia_lib:val({Name, {index, snmp}}),
- case b_lookup(Tree, RowIndex) of
- {ok, {_RowIndex, Key}} ->
- {ok, Key};
- _ ->
- undefined
- end.
-
-%%-----------------------------------------------------------------
-%% Encapsulate a bplus_tree in a process.
-%%-----------------------------------------------------------------
-
-b_new(MnesiaTab, Us) ->
- case supervisor:start_child(mnesia_snmp_sup, [MnesiaTab, Us]) of
- {ok, Tree} ->
- Tree;
- {error, Reason} ->
- exit({badsnmp, MnesiaTab, Reason})
- end.
-
-start(MnesiaTab, Us) ->
- Name = {mnesia_snmp, MnesiaTab},
- mnesia_monitor:start_proc(Name, ?MODULE, b_init, [self(), Us]).
-
-b_insert(Tree, Key, Val) -> Tree ! {insert, Key, Val}.
-b_delete(Tree, Key) -> Tree ! {delete, Key}.
-b_lookup(Tree, Key) ->
- Tree ! {lookup, self(), Key},
- receive
- {bplus_res, Res} ->
- Res
- end.
-b_lookup_next(Tree, Key) ->
- Tree ! {lookup_next, self(), Key},
- receive
- {bplus_res, Res} ->
- Res
- end.
-
-b_clear(Tree) ->
- Tree ! clear,
- ok.
-
-b_init(Parent, Us) ->
- %% Do not trap exit
- Tree = snmp_index:new(Us),
- proc_lib:init_ack(Parent, {ok, self()}),
- b_loop(Parent, Tree, Us).
-
-b_loop(Parent, Tree, Us) ->
- receive
- {insert, Key, Val} ->
- NTree = snmp_index:insert(Tree, Key, Val),
- b_loop(Parent, NTree, Us);
- {delete, Key} ->
- NTree = snmp_index:delete(Tree, Key),
- b_loop(Parent, NTree, Us);
- {lookup, From, Key} ->
- Res = snmp_index:get(Tree, Key),
- From ! {bplus_res, Res},
- b_loop(Parent, Tree, Us);
- {lookup_next, From, Key} ->
- Res = snmp_index:get_next(Tree, Key),
- From ! {bplus_res, Res},
- b_loop(Parent, Tree, Us);
- clear ->
- catch snmp_index:delete(Tree), %% Catch because delete/1 is not
- NewTree = snmp_index:new(Us), %% available in old snmp (before R5)
- b_loop(Parent, NewTree, Us);
-
- {'EXIT', Parent, Reason} ->
- exit(Reason);
-
- {system, From, Msg} ->
- mnesia_lib:dbg_out("~p got {system, ~p, ~p}~n", [?MODULE, From, Msg]),
- sys:handle_system_msg(Msg, From, Parent, ?MODULE, [], {Tree, Us})
-
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% System upgrade
-
-system_continue(Parent, _Debug, {Tree, Us}) ->
- b_loop(Parent, Tree, Us).
-
-system_terminate(Reason, _Parent, _Debug, _Tree) ->
- exit(Reason).
-
-system_code_change(State, _Module, _OldVsn, _Extra) ->
- {ok, State}.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_snmp_sup.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_snmp_sup.erl
deleted file mode 100644
index 1cbac23e9d..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_snmp_sup.erl
+++ /dev/null
@@ -1,39 +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: mnesia_snmp_sup.erl,v 1.1 2008/12/17 09:53:39 mikpe Exp $
-%%
--module(mnesia_snmp_sup).
-
--behaviour(supervisor).
-
--export([start/0, init/1]).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% top supervisor callback functions
-
-start() ->
- supervisor:start_link({local, ?MODULE}, ?MODULE, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% sub supervisor callback functions
-
-init([]) ->
- Flags = {simple_one_for_one, 0, timer:hours(24)}, % Trust the top supervisor
- MFA = {mnesia_snmp_hook, start, []},
- Modules = [?MODULE, mnesia_snmp_hook, supervisor],
- KillAfter = mnesia_kernel_sup:supervisor_timeout(timer:seconds(3)),
- Workers = [{?MODULE, MFA, transient, KillAfter, worker, Modules}],
- {ok, {Flags, Workers}}.
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_sp.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_sp.erl
deleted file mode 100644
index ad29d3cc78..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_sp.erl
+++ /dev/null
@@ -1,39 +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: mnesia_sp.erl,v 1.1 2008/12/17 09:53:39 mikpe Exp $
-%%
-
-%% To able to generate nice crash reports we need a catch on the highest level.
-%% This code can't be purged so a code change is not possible.
-%% And hence this a simple module.
-
--module(mnesia_sp).
-
--export([init_proc/4]).
-
-init_proc(Who, Mod, Fun, Args) ->
- mnesia_lib:verbose("~p starting: ~p~n", [Who, self()]),
- case catch apply(Mod, Fun, Args) of
- {'EXIT', Reason} ->
- mnesia_monitor:terminate_proc(Who, Reason, Args),
- exit(Reason);
- Other ->
- Other
- end.
-
-
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_subscr.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_subscr.erl
deleted file mode 100644
index f077291bc6..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_subscr.erl
+++ /dev/null
@@ -1,492 +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: mnesia_subscr.erl,v 1.1 2008/12/17 09:53:39 mikpe Exp $
-%%
--module(mnesia_subscr).
-
--behaviour(gen_server).
-
--export([start/0,
- set_debug_level/1,
- subscribe/2,
- unsubscribe/2,
- unsubscribe_table/1,
- subscribers/0,
- report_table_event/4,
- report_table_event/5,
- report_table_event/6
- ]).
-
-%% gen_server callbacks
--export([init/1,
- handle_call/3,
- handle_cast/2,
- handle_info/2,
- terminate/2,
- code_change/3
- ]).
-
--include("mnesia.hrl").
-
--import(mnesia_lib, [error/2]).
--record(state, {supervisor, pid_tab}).
-
-start() ->
- gen_server:start_link({local, ?MODULE}, ?MODULE, [self()],
- [{timeout, infinity}]).
-
-set_debug_level(Level) ->
- OldEnv = application:get_env(mnesia, debug),
- case mnesia_monitor:patch_env(debug, Level) of
- {error, Reason} ->
- {error, Reason};
- NewLevel ->
- set_debug_level(NewLevel, OldEnv)
- end.
-
-set_debug_level(Level, OldEnv) ->
- case mnesia:system_info(is_running) of
- no when OldEnv == undefined ->
- none;
- no ->
- {ok, E} = OldEnv,
- E;
- _ ->
- Old = mnesia_lib:val(debug),
- Local = mnesia:system_info(local_tables),
- E = whereis(mnesia_event),
- Sub = fun(Tab) -> subscribe(E, {table, Tab}) end,
- UnSub = fun(Tab) -> unsubscribe(E, {table, Tab}) end,
-
- case Level of
- none ->
- lists:foreach(UnSub, Local);
- verbose ->
- lists:foreach(UnSub, Local);
- debug ->
- lists:foreach(UnSub, Local -- [schema]),
- Sub(schema);
- trace ->
- lists:foreach(Sub, Local)
- end,
- mnesia_lib:set(debug, Level),
- Old
- end.
-
-subscribe(ClientPid, system) ->
- change_subscr(activate, ClientPid, system);
-subscribe(ClientPid, {table, Tab}) ->
- change_subscr(activate, ClientPid, {table, Tab, simple});
-subscribe(ClientPid, {table, Tab, simple}) ->
- change_subscr(activate, ClientPid, {table, Tab, simple});
-subscribe(ClientPid, {table, Tab, detailed}) ->
- change_subscr(activate, ClientPid, {table, Tab, detailed});
-subscribe(_ClientPid, What) ->
- {error, {badarg, What}}.
-
-unsubscribe(ClientPid, system) ->
- change_subscr(deactivate, ClientPid, system);
-unsubscribe(ClientPid, {table, Tab}) ->
- change_subscr(deactivate, ClientPid, {table, Tab, simple});
-unsubscribe(ClientPid, {table, Tab, simple}) ->
- change_subscr(deactivate, ClientPid, {table, Tab, simple});
-unsubscribe(ClientPid, {table, Tab, detailed}) ->
- change_subscr(deactivate, ClientPid, {table, Tab, detailed});
-unsubscribe(_ClientPid, What) ->
- {error, {badarg, What}}.
-
-unsubscribe_table(Tab) ->
- call({change, {deactivate_table, Tab}}).
-
-change_subscr(Kind, ClientPid, What) ->
- call({change, {Kind, ClientPid, What}}).
-
-subscribers() ->
- [whereis(mnesia_event) | mnesia_lib:val(subscribers)].
-
-report_table_event(Tab, Tid, Obj, Op) ->
- case ?catch_val({Tab, commit_work}) of
- {'EXIT', _} -> ok;
- Commit ->
- case lists:keysearch(subscribers, 1, Commit) of
- false -> ok;
- {value, Subs} ->
- report_table_event(Subs, Tab, Tid, Obj, Op, undefined)
- end
- end.
-
-%% Backwards compatible for the moment when mnesia_tm get's updated!
-report_table_event(Subscr, Tab, Tid, Obj, Op) ->
- report_table_event(Subscr, Tab, Tid, Obj, Op, undefined).
-
-report_table_event({subscribers, S1, S2}, Tab, Tid, _Obj, clear_table, _Old) ->
- What = {delete, {schema, Tab}, Tid},
- deliver(S1, {mnesia_table_event, What}),
- TabDef = mnesia_schema:cs2list(?catch_val({Tab, cstruct})),
- What2 = {write, {schema, Tab, TabDef}, Tid},
- deliver(S1, {mnesia_table_event, What2}),
- What3 = {delete, schema, {schema, Tab}, [{schema, Tab, TabDef}], Tid},
- deliver(S2, {mnesia_table_event, What3}),
- What4 = {write, schema, {schema, Tab, TabDef}, [], Tid},
- deliver(S2, {mnesia_table_event, What4});
-
-report_table_event({subscribers, Subscr, []}, Tab, Tid, Obj, Op, _Old) ->
- What = {Op, patch_record(Tab, Obj), Tid},
- deliver(Subscr, {mnesia_table_event, What});
-
-report_table_event({subscribers, S1, S2}, Tab, Tid, Obj, Op, Old) ->
- Standard = {Op, patch_record(Tab, Obj), Tid},
- deliver(S1, {mnesia_table_event, Standard}),
- Extended = what(Tab, Tid, Obj, Op, Old),
- deliver(S2, Extended);
-
-%% Backwards compatible for the moment when mnesia_tm get's updated!
-report_table_event({subscribers, Subscr}, Tab, Tid, Obj, Op, Old) ->
- report_table_event({subscribers, Subscr, []}, Tab, Tid, Obj, Op, Old).
-
-
-patch_record(Tab, Obj) ->
- case Tab == element(1, Obj) of
- true ->
- Obj;
- false ->
- setelement(1, Obj, Tab)
- end.
-
-what(Tab, Tid, {RecName, Key}, delete, undefined) ->
- case catch mnesia_lib:db_get(Tab, Key) of
- Old when list(Old) -> %% Op only allowed for set table.
- {mnesia_table_event, {delete, Tab, {RecName, Key}, Old, Tid}};
- _ ->
- %% Record just deleted by a dirty_op or
- %% the whole table has been deleted
- ignore
- end;
-what(Tab, Tid, Obj, delete, Old) ->
- {mnesia_table_event, {delete, Tab, Obj, Old, Tid}};
-what(Tab, Tid, Obj, delete_object, _Old) ->
- {mnesia_table_event, {delete, Tab, Obj, [Obj], Tid}};
-what(Tab, Tid, Obj, write, undefined) ->
- case catch mnesia_lib:db_get(Tab, element(2, Obj)) of
- Old when list(Old) ->
- {mnesia_table_event, {write, Tab, Obj, Old, Tid}};
- {'EXIT', _} ->
- ignore
- end.
-
-deliver(_, ignore) ->
- ok;
-deliver([Pid | Pids], Msg) ->
- Pid ! Msg,
- deliver(Pids, Msg);
-deliver([], _Msg) ->
- ok.
-
-call(Msg) ->
- Pid = whereis(?MODULE),
- case Pid of
- undefined ->
- {error, {node_not_running, node()}};
- Pid ->
- Res = gen_server:call(Pid, Msg, infinity),
- %% We get an exit signal if server dies
- receive
- {'EXIT', _Pid, _Reason} ->
- {error, {node_not_running, node()}}
- after 0 ->
- ignore
- end,
- Res
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%% Callback functions from gen_server
-
-%%----------------------------------------------------------------------
-%% Func: init/1
-%% Returns: {ok, State} |
-%% {ok, State, Timeout} |
-%% {stop, Reason}
-%%----------------------------------------------------------------------
-init([Parent]) ->
- process_flag(trap_exit, true),
- ClientPid = whereis(mnesia_event),
- link(ClientPid),
- mnesia_lib:verbose("~p starting: ~p~n", [?MODULE, self()]),
- Tab = ?ets_new_table(mnesia_subscr, [duplicate_bag, private]),
- ?ets_insert(Tab, {ClientPid, system}),
- {ok, #state{supervisor = Parent, pid_tab = Tab}}.
-
-%%----------------------------------------------------------------------
-%% Func: handle_call/3
-%% Returns: {reply, Reply, State} |
-%% {reply, Reply, State, Timeout} |
-%% {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, Reply, State} | (terminate/2 is called)
-%%----------------------------------------------------------------------
-handle_call({change, How}, _From, State) ->
- Reply = do_change(How, State#state.pid_tab),
- {reply, Reply, State};
-
-handle_call(Msg, _From, State) ->
- error("~p got unexpected call: ~p~n", [?MODULE, Msg]),
- {noreply, State}.
-
-%%----------------------------------------------------------------------
-%% Func: handle_cast/2
-%% Returns: {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State} (terminate/2 is called)
-%%----------------------------------------------------------------------
-handle_cast(Msg, State) ->
- error("~p got unexpected cast: ~p~n", [?MODULE, Msg]),
- {noreply, State}.
-
-%%----------------------------------------------------------------------
-%% Func: handle_info/2
-%% Returns: {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State} (terminate/2 is called)
-%%----------------------------------------------------------------------
-
-handle_info({'EXIT', Pid, _R}, State) when Pid == State#state.supervisor ->
- {stop, shutdown, State};
-
-handle_info({'EXIT', Pid, _Reason}, State) ->
- handle_exit(Pid, State#state.pid_tab),
- {noreply, State};
-
-handle_info(Msg, State) ->
- error("~p got unexpected info: ~p~n", [?MODULE, Msg]),
- {noreply, State}.
-
-%%----------------------------------------------------------------------
-%% Func: terminate/2
-%% Purpose: Shutdown the server
-%% Returns: any (ignored by gen_server)
-%%----------------------------------------------------------------------
-terminate(Reason, State) ->
- prepare_stop(State#state.pid_tab),
- mnesia_monitor:terminate_proc(?MODULE, Reason, State).
-
-%%----------------------------------------------------------------------
-%% Func: code_change/3
-%% Purpose: Upgrade process when its code is to be changed
-%% Returns: {ok, NewState}
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%%----------------------------------------------------------------------
-%%% Internal functions
-%%%----------------------------------------------------------------------
-
-do_change({activate, ClientPid, system}, SubscrTab) when pid(ClientPid) ->
- Var = subscribers,
- activate(ClientPid, system, Var, subscribers(), SubscrTab);
-do_change({activate, ClientPid, {table, Tab, How}}, SubscrTab) when pid(ClientPid) ->
- case ?catch_val({Tab, where_to_read}) of
- Node when Node == node() ->
- Var = {Tab, commit_work},
- activate(ClientPid, {table, Tab, How}, Var, mnesia_lib:val(Var), SubscrTab);
- {'EXIT', _} ->
- {error, {no_exists, Tab}};
- _Node ->
- {error, {not_active_local, Tab}}
- end;
-do_change({deactivate, ClientPid, system}, SubscrTab) ->
- Var = subscribers,
- deactivate(ClientPid, system, Var, SubscrTab);
-do_change({deactivate, ClientPid, {table, Tab, How}}, SubscrTab) ->
- Var = {Tab, commit_work},
- deactivate(ClientPid, {table, Tab, How}, Var, SubscrTab);
-do_change({deactivate_table, Tab}, SubscrTab) ->
- Var = {Tab, commit_work},
- case ?catch_val(Var) of
- {'EXIT', _} ->
- {error, {no_exists, Tab}};
- CommitWork ->
- case lists:keysearch(subscribers, 1, CommitWork) of
- false ->
- ok;
- {value, Subs} ->
- Simple = {table, Tab, simple},
- Detailed = {table, Tab, detailed},
- Fs = fun(C) -> deactivate(C, Simple, Var, SubscrTab) end,
- Fd = fun(C) -> deactivate(C, Detailed, Var, SubscrTab) end,
- case Subs of
- {subscribers, L1, L2} ->
- lists:foreach(Fs, L1),
- lists:foreach(Fd, L2);
- {subscribers, L1} ->
- lists:foreach(Fs, L1)
- end
- end,
- {ok, node()}
- end;
-do_change(_, _) ->
- {error, badarg}.
-
-activate(ClientPid, What, Var, OldSubscribers, SubscrTab) ->
- Old =
- if Var == subscribers ->
- OldSubscribers;
- true ->
- case lists:keysearch(subscribers, 1, OldSubscribers) of
- false -> [];
- {value, Subs} ->
- case Subs of
- {subscribers, L1, L2} ->
- L1 ++ L2;
- {subscribers, L1} ->
- L1
- end
- end
- end,
- case lists:member(ClientPid, Old) of
- false ->
- %% Don't care about checking old links
- case catch link(ClientPid) of
- true ->
- ?ets_insert(SubscrTab, {ClientPid, What}),
- add_subscr(Var, What, ClientPid),
- {ok, node()};
- {'EXIT', _Reason} ->
- {error, {no_exists, ClientPid}}
- end;
- true ->
- {error, {already_exists, What}}
- end.
-
-%%-record(subscribers, {pids = []}). Old subscriber record removed
-%% To solve backward compatibility, this code is a cludge..
-add_subscr(subscribers, _What, Pid) ->
- mnesia_lib:add(subscribers, Pid),
- {ok, node()};
-add_subscr({Tab, commit_work}, What, Pid) ->
- Commit = mnesia_lib:val({Tab, commit_work}),
- case lists:keysearch(subscribers, 1, Commit) of
- false ->
- Subscr =
- case What of
- {table, _, simple} ->
- {subscribers, [Pid], []};
- {table, _, detailed} ->
- {subscribers, [], [Pid]}
- end,
- mnesia_lib:add({Tab, subscribers}, Pid),
- mnesia_lib:set({Tab, commit_work},
- mnesia_lib:sort_commit([Subscr | Commit]));
- {value, Old} ->
- {L1, L2} =
- case Old of
- {subscribers, L} -> %% Old Way
- {L, []};
- {subscribers, SL1, SL2} ->
- {SL1, SL2}
- end,
- Subscr =
- case What of
- {table, _, simple} ->
- {subscribers, [Pid | L1], L2};
- {table, _, detailed} ->
- {subscribers, L1, [Pid | L2]}
- end,
- NewC = lists:keyreplace(subscribers, 1, Commit, Subscr),
- mnesia_lib:set({Tab, commit_work},
- mnesia_lib:sort_commit(NewC)),
- mnesia_lib:add({Tab, subscribers}, Pid)
- end.
-
-deactivate(ClientPid, What, Var, SubscrTab) ->
- ?ets_match_delete(SubscrTab, {ClientPid, What}),
- case catch ?ets_lookup_element(SubscrTab, ClientPid, 1) of
- List when list(List) ->
- ignore;
- {'EXIT', _} ->
- unlink(ClientPid)
- end,
- del_subscr(Var, What, ClientPid),
- {ok, node()}.
-
-del_subscr(subscribers, _What, Pid) ->
- mnesia_lib:del(subscribers, Pid);
-del_subscr({Tab, commit_work}, What, Pid) ->
- Commit = mnesia_lib:val({Tab, commit_work}),
- case lists:keysearch(subscribers, 1, Commit) of
- false ->
- false;
- {value, Old} ->
- {L1, L2} =
- case Old of
- {subscribers, L} -> %% Old Way
- {L, []};
- {subscribers, SL1, SL2} ->
- {SL1, SL2}
- end,
- Subscr =
- case What of %% Ignore user error delete subscr from any list
- {table, _, simple} ->
- NewL1 = lists:delete(Pid, L1),
- NewL2 = lists:delete(Pid, L2),
- {subscribers, NewL1, NewL2};
- {table, _, detailed} ->
- NewL1 = lists:delete(Pid, L1),
- NewL2 = lists:delete(Pid, L2),
- {subscribers, NewL1, NewL2}
- end,
- case Subscr of
- {subscribers, [], []} ->
- NewC = lists:keydelete(subscribers, 1, Commit),
- mnesia_lib:del({Tab, subscribers}, Pid),
- mnesia_lib:set({Tab, commit_work},
- mnesia_lib:sort_commit(NewC));
- _ ->
- NewC = lists:keyreplace(subscribers, 1, Commit, Subscr),
- mnesia_lib:del({Tab, subscribers}, Pid),
- mnesia_lib:set({Tab, commit_work},
- mnesia_lib:sort_commit(NewC))
- end
- end.
-
-handle_exit(ClientPid, SubscrTab) ->
- do_handle_exit(?ets_lookup(SubscrTab, ClientPid)),
- ?ets_delete(SubscrTab, ClientPid).
-
-do_handle_exit([{ClientPid, What} | Tail]) ->
- case What of
- system ->
- del_subscr(subscribers, What, ClientPid);
- {_, Tab, _Level} ->
- del_subscr({Tab, commit_work}, What, ClientPid)
- end,
- do_handle_exit(Tail);
-do_handle_exit([]) ->
- ok.
-
-prepare_stop(SubscrTab) ->
- mnesia_lib:report_system_event({mnesia_down, node()}),
- do_prepare_stop(?ets_first(SubscrTab), SubscrTab).
-
-do_prepare_stop('$end_of_table', _SubscrTab) ->
- ok;
-do_prepare_stop(ClientPid, SubscrTab) ->
- Next = ?ets_next(SubscrTab, ClientPid),
- handle_exit(ClientPid, SubscrTab),
- unlink(ClientPid),
- do_prepare_stop(Next, SubscrTab).
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_sup.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_sup.erl
deleted file mode 100644
index a8a1df885f..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_sup.erl
+++ /dev/null
@@ -1,137 +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: mnesia_sup.erl,v 1.1 2008/12/17 09:53:39 mikpe Exp $
-%%
-%% Supervisor for the entire Mnesia application
-
--module(mnesia_sup).
-
--behaviour(application).
--behaviour(supervisor).
-
--export([start/0, start/2, init/1, stop/1, start_event/0, kill/0]).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% application and suprvisor callback functions
-
-start(normal, Args) ->
- SupName = {local,?MODULE},
- case supervisor:start_link(SupName, ?MODULE, [Args]) of
- {ok, Pid} ->
- {ok, Pid, {normal, Args}};
- Error ->
- Error
- end;
-start(_, _) ->
- {error, badarg}.
-
-start() ->
- SupName = {local,?MODULE},
- supervisor:start_link(SupName, ?MODULE, []).
-
-stop(_StartArgs) ->
- ok.
-
-init([]) -> % Supervisor
- init();
-init([[]]) -> % Application
- init();
-init(BadArg) ->
- {error, {badarg, BadArg}}.
-
-init() ->
- Flags = {one_for_all, 0, 3600}, % Should be rest_for_one policy
-
- Event = event_procs(),
- Kernel = kernel_procs(),
- Mnemosyne = mnemosyne_procs(),
-
- {ok, {Flags, Event ++ Kernel ++ Mnemosyne}}.
-
-event_procs() ->
- KillAfter = timer:seconds(30),
- KA = mnesia_kernel_sup:supervisor_timeout(KillAfter),
- E = mnesia_event,
- [{E, {?MODULE, start_event, []}, permanent, KA, worker, [E, gen_event]}].
-
-kernel_procs() ->
- K = mnesia_kernel_sup,
- KA = infinity,
- [{K, {K, start, []}, permanent, KA, supervisor, [K, supervisor]}].
-
-mnemosyne_procs() ->
- case mnesia_monitor:get_env(embedded_mnemosyne) of
- true ->
- Q = mnemosyne_sup,
- KA = infinity,
- [{Q, {Q, start, []}, permanent, KA, supervisor, [Q, supervisor]}];
- false ->
- []
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% event handler
-
-start_event() ->
- case gen_event:start_link({local, mnesia_event}) of
- {ok, Pid} ->
- case add_event_handler() of
- ok ->
- {ok, Pid};
- Error ->
- Error
- end;
- Error ->
- Error
- end.
-
-add_event_handler() ->
- Handler = mnesia_monitor:get_env(event_module),
- gen_event:add_handler(mnesia_event, Handler, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% debug functions
-
-kill() ->
- Mnesia = [mnesia_fallback | mnesia:ms()],
- Mnemosyne = mnemosyne_ms(),
- Kill = fun(Name) -> catch exit(whereis(Name), kill) end,
- lists:foreach(Kill, Mnemosyne),
- lists:foreach(Kill, Mnesia),
- lists:foreach(fun ensure_dead/1, Mnemosyne),
- lists:foreach(fun ensure_dead/1, Mnesia),
- timer:sleep(10),
- case lists:keymember(mnesia, 1, application:which_applications()) of
- true -> kill();
- false -> ok
- end.
-
-ensure_dead(Name) ->
- case whereis(Name) of
- undefined ->
- ok;
- Pid when pid(Pid) ->
- exit(Pid, kill),
- timer:sleep(10),
- ensure_dead(Name)
- end.
-
-mnemosyne_ms() ->
- case mnesia_monitor:get_env(embedded_mnemosyne) of
- true -> mnemosyne:ms();
- false -> []
- end.
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_text.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_text.erl
deleted file mode 100644
index e6084efbb1..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_text.erl
+++ /dev/null
@@ -1,191 +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: mnesia_text.erl,v 1.2 2010/03/04 13:54:20 maria Exp $
-%%
--module(mnesia_text).
-
--export([parse/1, file/1, load_textfile/1, dump_to_textfile/1]).
-
-load_textfile(File) ->
- ensure_started(),
- case parse(File) of
- {ok, {Tabs, Data}} ->
- Badtabs = make_tabs(lists:map(fun validate_tab/1, Tabs)),
- load_data(del_data(Badtabs, Data, []));
- Other ->
- Other
- end.
-
-dump_to_textfile(File) ->
- dump_to_textfile(mnesia_lib:is_running(), file:open(File, [write])).
-dump_to_textfile(yes, {ok, F}) ->
- Tabs = lists:delete(schema, mnesia_lib:local_active_tables()),
- Defs = lists:map(fun(T) -> {T, [{record_name, mnesia_lib:val({T, record_name})},
- {attributes, mnesia_lib:val({T, attributes})}]}
- end,
- Tabs),
- io:format(F, "~p.~n", [{tables, Defs}]),
- lists:foreach(fun(T) -> dump_tab(F, T) end, Tabs),
- file:close(F);
-dump_to_textfile(_,_) -> error.
-
-
-dump_tab(F, T) ->
- W = mnesia_lib:val({T, wild_pattern}),
- {'atomic',All} = mnesia:transaction(fun() -> mnesia:match_object(T, W, read) end),
- lists:foreach(fun(Term) -> io:format(F,"~p.~n", [setelement(1, Term, T)]) end, All).
-
-
-ensure_started() ->
- case mnesia_lib:is_running() of
- yes ->
- yes;
- no ->
- case mnesia_lib:exists(mnesia_lib:dir("schema.DAT")) of
- true ->
- mnesia:start();
- false ->
- mnesia:create_schema([node()]),
- mnesia:start()
- end
- end.
-
-del_data(Bad, [H|T], Ack) ->
- case lists:member(element(1, H), Bad) of
- true -> del_data(Bad, T, Ack);
- false -> del_data(Bad, T, [H|Ack])
- end;
-del_data(_Bad, [], Ack) ->
- lists:reverse(Ack).
-
-%% Tis the place to call the validate func in mnesia_schema
-validate_tab({Tabname, List}) ->
- {Tabname, List};
-validate_tab({Tabname, RecName, List}) ->
- {Tabname, RecName, List};
-validate_tab(_) -> error(badtab).
-
-make_tabs([{Tab, Def} | Tail]) ->
- case catch mnesia:table_info(Tab, where_to_read) of
- {'EXIT', _} -> %% non-existing table
- case mnesia:create_table(Tab, Def) of
- {aborted, Reason} ->
- io:format("** Failed to create table ~w ~n"
- "** Reason = ~w, Args = ~p~n",
- [Tab, Reason, Def]),
- [Tab | make_tabs(Tail)];
- _ ->
- io:format("New table ~w~n", [Tab]),
- make_tabs(Tail)
- end;
- Node ->
- io:format("** Table ~w already exists on ~p, just entering data~n",
- [Tab, Node]),
- make_tabs(Tail)
- end;
-
-make_tabs([]) ->
- [].
-
-load_data(L) ->
- mnesia:transaction(fun() ->
- F = fun(X) ->
- Tab = element(1, X),
- RN = mnesia:table_info(Tab, record_name),
- Rec = setelement(1, X, RN),
- mnesia:write(Tab, Rec, write) end,
- lists:foreach(F, L)
- end).
-
-parse(File) ->
- case file(File) of
- {ok, Terms} ->
- case catch collect(Terms) of
- {error, X} ->
- {error, X};
- Other ->
- {ok, Other}
- end;
- Other ->
- Other
- end.
-
-collect([{_, {tables, Tabs}}|L]) ->
- {Tabs, collect_data(Tabs, L)};
-
-collect(_) ->
- io:format("No tables found\n", []),
- error(bad_header).
-
-collect_data(Tabs, [{Line, Term} | Tail]) when tuple(Term) ->
- case lists:keysearch(element(1, Term), 1, Tabs) of
- {value, _} ->
- [Term | collect_data(Tabs, Tail)];
- _Other ->
- io:format("Object:~p at line ~w unknown\n", [Term,Line]),
- error(undefined_object)
- end;
-collect_data(_Tabs, []) -> [];
-collect_data(_Tabs, [H|_T]) ->
- io:format("Object:~p unknown\n", [H]),
- error(undefined_object).
-
-error(What) -> throw({error, What}).
-
-file(File) ->
- case file:open(File, [read]) of
- {ok, Stream} ->
- Res = read_terms(Stream, File, 1, []),
- file:close(Stream),
- Res;
- _Other ->
- {error, open}
- end.
-
-read_terms(Stream, File, Line, L) ->
- case read_term_from_stream(Stream, File, Line) of
- {ok, Term, NextLine} ->
- read_terms(Stream, File, NextLine, [Term|L]);
- error ->
- {error, read};
- eof ->
- {ok, lists:reverse(L)}
- end.
-
-read_term_from_stream(Stream, File, Line) ->
- R = io:request(Stream, {get_until,'',erl_scan,tokens,[Line]}),
- case R of
- {ok,Toks,EndLine} ->
- case erl_parse:parse_term(Toks) of
- {ok, Term} ->
- {ok, {Line, Term}, EndLine};
- {error, {NewLine,Mod,What}} ->
- Str = Mod:format_error(What),
- io:format("Error in line:~p of:~p ~s\n",
- [NewLine, File, Str]),
- error;
- T ->
- io:format("Error2 **~p~n",[T]),
- error
- end;
- {eof,_EndLine} ->
- eof;
- Other ->
- io:format("Error1 **~p~n",[Other]),
- error
- end.
-
-
diff --git a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_tm.erl b/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_tm.erl
deleted file mode 100644
index 7bee382a89..0000000000
--- a/lib/dialyzer/test/r9c_tests_SUITE_data/src/mnesia/mnesia_tm.erl
+++ /dev/null
@@ -1,2173 +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: mnesia_tm.erl,v 1.2 2010/03/04 13:54:20 maria Exp $
-%%
--module(mnesia_tm).
-
--export([
- start/0,
- init/1,
- non_transaction/5,
- transaction/6,
- commit_participant/5,
- dirty/2,
- display_info/2,
- do_update_op/3,
- get_info/1,
- get_transactions/0,
- info/1,
- mnesia_down/1,
- prepare_checkpoint/2,
- prepare_checkpoint/1, % Internal
- prepare_snmp/3,
- do_snmp/2,
- put_activity_id/1,
- block_tab/1,
- unblock_tab/1
- ]).
-
-%% sys callback functions
--export([system_continue/3,
- system_terminate/4,
- system_code_change/4
- ]).
-
--include("mnesia.hrl").
--import(mnesia_lib, [set/2]).
--import(mnesia_lib, [fatal/2, verbose/2, dbg_out/2]).
-
--record(state, {coordinators = [], participants = [], supervisor,
- blocked_tabs = [], dirty_queue = []}).
-%% Format on coordinators is [{Tid, EtsTabList} .....
-
--record(prep, {protocol = sym_trans,
- %% async_dirty | sync_dirty | sym_trans | sync_sym_trans | asym_trans
- records = [],
- prev_tab = [], % initiate to a non valid table name
- prev_types,
- prev_snmp,
- types
- }).
-
--record(participant, {tid, pid, commit, disc_nodes = [],
- ram_nodes = [], protocol = sym_trans}).
-
-start() ->
- mnesia_monitor:start_proc(?MODULE, ?MODULE, init, [self()]).
-
-init(Parent) ->
- register(?MODULE, self()),
- process_flag(trap_exit, true),
-
- %% Initialize the schema
- IgnoreFallback = mnesia_monitor:get_env(ignore_fallback_at_startup),
- mnesia_bup:tm_fallback_start(IgnoreFallback),
- mnesia_schema:init(IgnoreFallback),
-
- %% Handshake and initialize transaction recovery
- mnesia_recover:init(),
- Early = mnesia_monitor:init(),
- AllOthers = mnesia_lib:uniq(Early ++ mnesia_lib:all_nodes()) -- [node()],
- set(original_nodes, AllOthers),
- mnesia_recover:connect_nodes(AllOthers),
-
- %% Recover transactions, may wait for decision
- case mnesia_monitor:use_dir() of
- true ->
- P = mnesia_dumper:opt_dump_log(startup), % previous log
- L = mnesia_dumper:opt_dump_log(startup), % latest log
- Msg = "Initial dump of log during startup: ~p~n",
- mnesia_lib:verbose(Msg, [[P, L]]),
- mnesia_log:init();
- false ->
- ignore
- end,
-
- mnesia_schema:purge_tmp_files(),
- mnesia_recover:start_garb(),
-
- ?eval_debug_fun({?MODULE, init}, [{nodes, AllOthers}]),
-
- case val(debug) of
- Debug when Debug /= debug, Debug /= trace ->
- ignore;
- _ ->
- mnesia_subscr:subscribe(whereis(mnesia_event), {table, schema})
- end,
- proc_lib:init_ack(Parent, {ok, self()}),
- doit_loop(#state{supervisor = Parent}).
-
-val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _ReASoN_} -> mnesia_lib:other_val(Var, _ReASoN_);
- _VaLuE_ -> _VaLuE_
- end.
-
-reply({From,Ref}, R) ->
- From ! {?MODULE, Ref, R};
-reply(From, R) ->
- From ! {?MODULE, node(), R}.
-
-reply(From, R, State) ->
- reply(From, R),
- doit_loop(State).
-
-req(R) ->
- case whereis(?MODULE) of
- undefined ->
- {error, {node_not_running, node()}};
- Pid ->
- Ref = make_ref(),
- Pid ! {{self(), Ref}, R},
- rec(Pid, Ref)
- end.
-
-rec() ->
- rec(whereis(?MODULE)).
-
-rec(Pid) when pid(Pid) ->
- receive
- {?MODULE, _, Reply} ->
- Reply;
-
- {'EXIT', Pid, _} ->
- {error, {node_not_running, node()}}
- end;
-rec(undefined) ->
- {error, {node_not_running, node()}}.
-
-rec(Pid, Ref) ->
- receive
- {?MODULE, Ref, Reply} ->
- Reply;
- {'EXIT', Pid, _} ->
- {error, {node_not_running, node()}}
- end.
-
-tmlink({From, Ref}) when reference(Ref) ->
- link(From);
-tmlink(From) ->
- link(From).
-tmpid({Pid, _Ref}) when pid(Pid) ->
- Pid;
-tmpid(Pid) ->
- Pid.
-
-%% Returns a list of participant transaction Tid's
-mnesia_down(Node) ->
- %% Syncronously call needed in order to avoid
- %% race with mnesia_tm's coordinator processes
- %% that may restart and acquire new locks.
- %% mnesia_monitor takes care of the sync
- case whereis(?MODULE) of
- undefined ->
- mnesia_monitor:mnesia_down(?MODULE, {Node, []});
- Pid ->
- Pid ! {mnesia_down, Node}
- end.
-
-prepare_checkpoint(Nodes, Cp) ->
- rpc:multicall(Nodes, ?MODULE, prepare_checkpoint, [Cp]).
-
-prepare_checkpoint(Cp) ->
- req({prepare_checkpoint,Cp}).
-
-block_tab(Tab) ->
- req({block_tab, Tab}).
-
-unblock_tab(Tab) ->
- req({unblock_tab, Tab}).
-
-doit_loop(#state{coordinators = Coordinators, participants = Participants, supervisor = Sup}
- = State) ->
- receive
- {_From, {async_dirty, Tid, Commit, Tab}} ->
- case lists:member(Tab, State#state.blocked_tabs) of
- false ->
- do_async_dirty(Tid, Commit, Tab),
- doit_loop(State);
- true ->
- Item = {async_dirty, Tid, Commit, Tab},
- State2 = State#state{dirty_queue = [Item | State#state.dirty_queue]},
- doit_loop(State2)
- end;
-
- {From, {sync_dirty, Tid, Commit, Tab}} ->
- case lists:member(Tab, State#state.blocked_tabs) of
- false ->
- do_sync_dirty(From, Tid, Commit, Tab),
- doit_loop(State);
- true ->
- Item = {sync_dirty, From, Tid, Commit, Tab},
- State2 = State#state{dirty_queue = [Item | State#state.dirty_queue]},
- doit_loop(State2)
- end;
-
- {From, start_outer} -> %% Create and associate ets_tab with Tid
- case catch ?ets_new_table(mnesia_trans_store, [bag, public]) of
- {'EXIT', Reason} -> %% system limit
- Msg = "Cannot create an ets table for the "
- "local transaction store",
- reply(From, {error, {system_limit, Msg, Reason}}, State);
- Etab ->
- tmlink(From),
- C = mnesia_recover:incr_trans_tid_serial(),
- ?ets_insert(Etab, {nodes, node()}),
- Tid = #tid{pid = tmpid(From), counter = C},
- A2 = [{Tid , [Etab]} | Coordinators],
- S2 = State#state{coordinators = A2},
- reply(From, {new_tid, Tid, Etab}, S2)
- end;
-
- {From, {ask_commit, Protocol, Tid, Commit, DiscNs, RamNs}} ->
- ?eval_debug_fun({?MODULE, doit_ask_commit},
- [{tid, Tid}, {prot, Protocol}]),
- mnesia_checkpoint:tm_enter_pending(Tid, DiscNs, RamNs),
- Pid =
- case Protocol of
- asym_trans when node(Tid#tid.pid) /= node() ->
- Args = [tmpid(From), Tid, Commit, DiscNs, RamNs],
- spawn_link(?MODULE, commit_participant, Args);
- _ when node(Tid#tid.pid) /= node() -> %% *_sym_trans
- reply(From, {vote_yes, Tid}),
- nopid
- end,
- P = #participant{tid = Tid,
- pid = Pid,
- commit = Commit,
- disc_nodes = DiscNs,
- ram_nodes = RamNs,
- protocol = Protocol},
- State2 = State#state{participants = [P | Participants]},
- doit_loop(State2);
-
- {Tid, do_commit} ->
- case mnesia_lib:key_search_delete(Tid, #participant.tid, Participants) of
- {none, _} ->
- verbose("Tried to commit a non participant transaction ~p~n",
- [Tid]),
- doit_loop(State);
- {P, Participants2} ->
- ?eval_debug_fun({?MODULE, do_commit, pre},
- [{tid, Tid}, {participant, P}]),
- case P#participant.pid of
- nopid ->
- Commit = P#participant.commit,
- Member = lists:member(node(), P#participant.disc_nodes),
- if Member == false ->
- ignore;
- P#participant.protocol == sym_trans ->
- mnesia_log:log(Commit);
- P#participant.protocol == sync_sym_trans ->
- mnesia_log:slog(Commit)
- end,
- mnesia_recover:note_decision(Tid, committed),
- do_commit(Tid, Commit),
- if
- P#participant.protocol == sync_sym_trans ->
- Tid#tid.pid ! {?MODULE, node(), {committed, Tid}};
- true ->
- ignore
- end,
- mnesia_locker:release_tid(Tid),
- transaction_terminated(Tid),
- ?eval_debug_fun({?MODULE, do_commit, post}, [{tid, Tid}, {pid, nopid}]),
- doit_loop(State#state{participants = Participants2});
- Pid when pid(Pid) ->
- Pid ! {Tid, committed},
- ?eval_debug_fun({?MODULE, do_commit, post}, [{tid, Tid}, {pid, Pid}]),
- doit_loop(State)
- end
- end;
-
- {Tid, simple_commit} ->
- mnesia_recover:note_decision(Tid, committed),
- mnesia_locker:release_tid(Tid),
- transaction_terminated(Tid),
- doit_loop(State);
-
- {Tid, {do_abort, Reason}} ->
- ?eval_debug_fun({?MODULE, do_abort, pre}, [{tid, Tid}]),
- mnesia_locker:release_tid(Tid),
- case mnesia_lib:key_search_delete(Tid, #participant.tid, Participants) of
- {none, _} ->
- verbose("Tried to abort a non participant transaction ~p: ~p~n",
- [Tid, Reason]),
- doit_loop(State);
- {P, Participants2} ->
- case P#participant.pid of
- nopid ->
- Commit = P#participant.commit,
- mnesia_recover:note_decision(Tid, aborted),
- do_abort(Tid, Commit),
- if
- P#participant.protocol == sync_sym_trans ->
- Tid#tid.pid ! {?MODULE, node(), {aborted, Tid}};
- true ->
- ignore
- end,
- transaction_terminated(Tid),
- ?eval_debug_fun({?MODULE, do_abort, post}, [{tid, Tid}, {pid, nopid}]),
- doit_loop(State#state{participants = Participants2});
- Pid when pid(Pid) ->
- Pid ! {Tid, {do_abort, Reason}},
- ?eval_debug_fun({?MODULE, do_abort, post},
- [{tid, Tid}, {pid, Pid}]),
- doit_loop(State)
- end
- end;
-
- {From, {add_store, Tid}} -> %% new store for nested transaction
- case catch ?ets_new_table(mnesia_trans_store, [bag, public]) of
- {'EXIT', Reason} -> %% system limit
- Msg = "Cannot create an ets table for a nested "
- "local transaction store",
- reply(From, {error, {system_limit, Msg, Reason}}, State);
- Etab ->
- A2 = add_coord_store(Coordinators, Tid, Etab),
- reply(From, {new_store, Etab},
- State#state{coordinators = A2})
- end;
-
- {From, {del_store, Tid, Current, Obsolete, PropagateStore}} ->
- opt_propagate_store(Current, Obsolete, PropagateStore),
- A2 = del_coord_store(Coordinators, Tid, Current, Obsolete),
- reply(From, store_erased, State#state{coordinators = A2});
-
- {'EXIT', Pid, Reason} ->
- handle_exit(Pid, Reason, State);
-
- {From, {restart, Tid, Store}} ->
- A2 = restore_stores(Coordinators, Tid, Store),
- ?ets_match_delete(Store, '_'),
- ?ets_insert(Store, {nodes, node()}),
- reply(From, {restarted, Tid}, State#state{coordinators = A2});
-
- {delete_transaction, Tid} ->
- %% used to clear transactions which are committed
- %% in coordinator or participant processes
- case mnesia_lib:key_search_delete(Tid, #participant.tid, Participants) of
- {none, _} ->
- case mnesia_lib:key_search_delete(Tid, 1, Coordinators) of
- {none, _} ->
- verbose("** ERROR ** Tried to delete a non transaction ~p~n",
- [Tid]),
- doit_loop(State);
- {{_Tid, Etabs}, A2} ->
- erase_ets_tabs(Etabs),
- transaction_terminated(Tid),
- doit_loop(State#state{coordinators = A2})
- end;
- {_P, Participants2} ->
- transaction_terminated(Tid),
- State2 = State#state{participants = Participants2},
- doit_loop(State2)
- end;
-
- {sync_trans_serial, Tid} ->
- %% Do the Lamport thing here
- mnesia_recover:sync_trans_tid_serial(Tid),
- doit_loop(State);
-
- {From, info} ->
- reply(From, {info, Participants, Coordinators}, State);
-
- {mnesia_down, N} ->
- verbose("Got mnesia_down from ~p, reconfiguring...~n", [N]),
- reconfigure_coordinators(N, Coordinators),
-
- Tids = [P#participant.tid || P <- Participants],
- reconfigure_participants(N, Participants),
- mnesia_monitor:mnesia_down(?MODULE, {N, Tids}),
- doit_loop(State);
-
- {From, {unblock_me, Tab}} ->
- case lists:member(Tab, State#state.blocked_tabs) of
- false ->
- verbose("Wrong dirty Op blocked on ~p ~p ~p",
- [node(), Tab, From]),
- reply(From, unblocked),
- doit_loop(State);
- true ->
- Item = {Tab, unblock_me, From},
- State2 = State#state{dirty_queue = [Item | State#state.dirty_queue]},
- doit_loop(State2)
- end;
-
- {From, {block_tab, Tab}} ->
- State2 = State#state{blocked_tabs = [Tab | State#state.blocked_tabs]},
- reply(From, ok, State2);
-
- {From, {unblock_tab, Tab}} ->
- BlockedTabs2 = State#state.blocked_tabs -- [Tab],
- case lists:member(Tab, BlockedTabs2) of
- false ->
- mnesia_controller:unblock_table(Tab),
- Queue = process_dirty_queue(Tab, State#state.dirty_queue),
- State2 = State#state{blocked_tabs = BlockedTabs2,
- dirty_queue = Queue},
- reply(From, ok, State2);
- true ->
- State2 = State#state{blocked_tabs = BlockedTabs2},
- reply(From, ok, State2)
- end;
-
- {From, {prepare_checkpoint, Cp}} ->
- Res = mnesia_checkpoint:tm_prepare(Cp),
- case Res of
- {ok, _Name, IgnoreNew, _Node} ->
- prepare_pending_coordinators(Coordinators, IgnoreNew),
- prepare_pending_participants(Participants, IgnoreNew);
- {error, _Reason} ->
- ignore
- end,
- reply(From, Res, State);
-
- {system, From, Msg} ->
- dbg_out("~p got {system, ~p, ~p}~n", [?MODULE, From, Msg]),
- sys:handle_system_msg(Msg, From, Sup, ?MODULE, [], State);
-
- Msg ->
- verbose("** ERROR ** ~p got unexpected message: ~p~n", [?MODULE, Msg]),
- doit_loop(State)
- end.
-
-do_sync_dirty(From, Tid, Commit, _Tab) ->
- ?eval_debug_fun({?MODULE, sync_dirty, pre}, [{tid, Tid}]),
- Res = (catch do_dirty(Tid, Commit)),
- ?eval_debug_fun({?MODULE, sync_dirty, post}, [{tid, Tid}]),
- From ! {?MODULE, node(), {dirty_res, Res}}.
-
-do_async_dirty(Tid, Commit, _Tab) ->
- ?eval_debug_fun({?MODULE, async_dirty, pre}, [{tid, Tid}]),
- catch do_dirty(Tid, Commit),
- ?eval_debug_fun({?MODULE, async_dirty, post}, [{tid, Tid}]).
-
-%% Process items in fifo order
-process_dirty_queue(Tab, [Item | Queue]) ->
- Queue2 = process_dirty_queue(Tab, Queue),
- case Item of
- {async_dirty, Tid, Commit, Tab} ->
- do_async_dirty(Tid, Commit, Tab),
- Queue2;
- {sync_dirty, From, Tid, Commit, Tab} ->
- do_sync_dirty(From, Tid, Commit, Tab),
- Queue2;
- {Tab, unblock_me, From} ->
- reply(From, unblocked),
- Queue2;
- _ ->
- [Item | Queue2]
- end;
-process_dirty_queue(_Tab, []) ->
- [].
-
-prepare_pending_coordinators([{Tid, [Store | _Etabs]} | Coords], IgnoreNew) ->
- case catch ?ets_lookup(Store, pending) of
- [] ->
- prepare_pending_coordinators(Coords, IgnoreNew);
- [Pending] ->
- case lists:member(Tid, IgnoreNew) of
- false ->
- mnesia_checkpoint:tm_enter_pending(Pending);
- true ->
- ignore
- end,
- prepare_pending_coordinators(Coords, IgnoreNew);
- {'EXIT', _} ->
- prepare_pending_coordinators(Coords, IgnoreNew)
- end;
-prepare_pending_coordinators([], _IgnoreNew) ->
- ok.
-
-prepare_pending_participants([Part | Parts], IgnoreNew) ->
- Tid = Part#participant.tid,
- D = Part#participant.disc_nodes,
- R = Part#participant.ram_nodes,
- case lists:member(Tid, IgnoreNew) of
- false ->
- mnesia_checkpoint:tm_enter_pending(Tid, D, R);
- true ->
- ignore
- end,
- prepare_pending_participants(Parts, IgnoreNew);
-prepare_pending_participants([], _IgnoreNew) ->
- ok.
-
-handle_exit(Pid, Reason, State) when node(Pid) /= node() ->
- %% We got exit from a remote fool
- dbg_out("~p got remote EXIT from unknown ~p~n",
- [?MODULE, {Pid, Reason}]),
- doit_loop(State);
-
-handle_exit(Pid, _Reason, State) when Pid == State#state.supervisor ->
- %% Our supervisor has died, time to stop
- do_stop(State);
-
-handle_exit(Pid, Reason, State) ->
- %% Check if it is a coordinator
- case pid_search_delete(Pid, State#state.coordinators) of
- {none, _} ->
- %% Check if it is a participant
- case mnesia_lib:key_search_delete(Pid, #participant.pid, State#state.participants) of
- {none, _} ->
- %% We got exit from a local fool
- verbose("** ERROR ** ~p got local EXIT from unknown process: ~p~n",
- [?MODULE, {Pid, Reason}]),
- doit_loop(State);
-
- {P, RestP} when record(P, participant) ->
- fatal("Participant ~p in transaction ~p died ~p~n",
- [P#participant.pid, P#participant.tid, Reason]),
- doit_loop(State#state{participants = RestP})
- end;
-
- {{Tid, Etabs}, RestC} ->
- %% A local coordinator has died and
- %% we must determine the outcome of the
- %% transaction and tell mnesia_tm on the
- %% other nodes about it and then recover
- %% locally.
- recover_coordinator(Tid, Etabs),
- doit_loop(State#state{coordinators = RestC})
- end.
-
-recover_coordinator(Tid, Etabs) ->
- verbose("Coordinator ~p in transaction ~p died.~n", [Tid#tid.pid, Tid]),
-
- Store = hd(Etabs),
- CheckNodes = get_nodes(Store),
- TellNodes = CheckNodes -- [node()],
- case catch arrange(Tid, Store, async) of
- {'EXIT', Reason} ->
- dbg_out("Recovery of coordinator ~p failed:~n", [Tid, Reason]),
- Protocol = asym_trans,
- tell_outcome(Tid, Protocol, node(), CheckNodes, TellNodes);
- {_N, Prep} ->
- %% Tell the participants about the outcome
- Protocol = Prep#prep.protocol,
- Outcome = tell_outcome(Tid, Protocol, node(), CheckNodes, TellNodes),
-
- %% Recover locally
- CR = Prep#prep.records,
- {DiscNs, RamNs} = commit_nodes(CR, [], []),
- {value, Local} = lists:keysearch(node(), #commit.node, CR),
-
- ?eval_debug_fun({?MODULE, recover_coordinator, pre},
- [{tid, Tid}, {outcome, Outcome}, {prot, Protocol}]),
- recover_coordinator(Tid, Protocol, Outcome, Local, DiscNs, RamNs),
- ?eval_debug_fun({?MODULE, recover_coordinator, post},
- [{tid, Tid}, {outcome, Outcome}, {prot, Protocol}])
-
- end,
- erase_ets_tabs(Etabs),
- transaction_terminated(Tid),
- mnesia_locker:release_tid(Tid).
-
-recover_coordinator(Tid, sym_trans, committed, Local, _, _) ->
- mnesia_recover:note_decision(Tid, committed),
- do_dirty(Tid, Local);
-recover_coordinator(Tid, sym_trans, aborted, _Local, _, _) ->
- mnesia_recover:note_decision(Tid, aborted);
-recover_coordinator(Tid, sync_sym_trans, committed, Local, _, _) ->
- mnesia_recover:note_decision(Tid, committed),
- do_dirty(Tid, Local);
-recover_coordinator(Tid, sync_sym_trans, aborted, _Local, _, _) ->
- mnesia_recover:note_decision(Tid, aborted);
-
-recover_coordinator(Tid, asym_trans, committed, Local, DiscNs, RamNs) ->
- D = #decision{tid = Tid, outcome = committed,
- disc_nodes = DiscNs, ram_nodes = RamNs},
- mnesia_recover:log_decision(D),
- do_commit(Tid, Local);
-recover_coordinator(Tid, asym_trans, aborted, Local, DiscNs, RamNs) ->
- D = #decision{tid = Tid, outcome = aborted,
- disc_nodes = DiscNs, ram_nodes = RamNs},
- mnesia_recover:log_decision(D),
- do_abort(Tid, Local).
-
-restore_stores([{Tid, Etstabs} | Tail], Tid, Store) ->
- Remaining = lists:delete(Store, Etstabs),
- erase_ets_tabs(Remaining),
- [{Tid, [Store]} | Tail];
-restore_stores([H | T], Tid, Store) ->
- [H | restore_stores(T, Tid, Store)].
-%% No NIL case on purpose
-
-add_coord_store([{Tid, Stores} | Coordinators], Tid, Etab) ->
- [{Tid, [Etab | Stores]} | Coordinators];
-add_coord_store([H | T], Tid, Etab) ->
- [H | add_coord_store(T, Tid, Etab)].
-%% no NIL case on purpose
-
-del_coord_store([{Tid, Stores} | Coordinators], Tid, Current, Obsolete) ->
- Rest =
- case Stores of
- [Obsolete, Current | Tail] -> Tail;
- [Current, Obsolete | Tail] -> Tail
- end,
- ?ets_delete_table(Obsolete),
- [{Tid, [Current | Rest]} | Coordinators];
-del_coord_store([H | T], Tid, Current, Obsolete) ->
- [H | del_coord_store(T, Tid, Current, Obsolete)].
-%% no NIL case on purpose
-
-erase_ets_tabs([H | T]) ->
- ?ets_delete_table(H),
- erase_ets_tabs(T);
-erase_ets_tabs([]) ->
- ok.
-
-%% Deletes a pid from a list of participants
-%% or from a list of coordinators and returns
-%% {none, All} or {Tr, Rest}
-pid_search_delete(Pid, Trs) ->
- pid_search_delete(Pid, Trs, none, []).
-pid_search_delete(Pid, [Tr = {Tid, _Ts} | Trs], _Val, Ack) when Tid#tid.pid == Pid ->
- pid_search_delete(Pid, Trs, Tr, Ack);
-pid_search_delete(Pid, [Tr | Trs], Val, Ack) ->
- pid_search_delete(Pid, Trs, Val, [Tr | Ack]);
-
-pid_search_delete(_Pid, [], Val, Ack) ->
- {Val, Ack}.
-
-%% When TM gets an EXIT sig, we must also check to see
-%% if the crashing transaction is in the Participant list
-%%
-%% search_participant_for_pid([Participant | Tail], Pid) ->
-%% Tid = Participant#participant.tid,
-%% if
-%% Tid#tid.pid == Pid ->
-%% {coordinator, Participant};
-%% Participant#participant.pid == Pid ->
-%% {participant, Participant};
-%% true ->
-%% search_participant_for_pid(Tail, Pid)
-%% end;
-%% search_participant_for_pid([], _) ->
-%% fool.
-
-transaction_terminated(Tid) ->
- mnesia_checkpoint:tm_exit_pending(Tid),
- Pid = Tid#tid.pid,
- if
- node(Pid) == node() ->
- unlink(Pid);
- true -> %% Do the Lamport thing here
- mnesia_recover:sync_trans_tid_serial(Tid)
- end.
-
-non_transaction(OldState, Fun, Args, ActivityKind, Mod) ->
- Id = {ActivityKind, self()},
- NewState = {Mod, Id, non_transaction},
- put(mnesia_activity_state, NewState),
- %% I Want something uniqe here, references are expensive
- Ref = mNeSia_nOn_TrAnSacTioN,
- RefRes = (catch {Ref, apply(Fun, Args)}),
- case OldState of
- undefined -> erase(mnesia_activity_state);
- _ -> put(mnesia_activity_state, OldState)
- end,
- case RefRes of
- {Ref, Res} ->
- case Res of
- {'EXIT', Reason} -> exit(Reason);
- {aborted, Reason} -> mnesia:abort(Reason);
- _ -> Res
- end;
- {'EXIT', Reason} ->
- exit(Reason);
- Throw ->
- throw(Throw)
- end.
-
-transaction(OldTidTs, Fun, Args, Retries, Mod, Type) ->
- Factor = 1,
- case OldTidTs of
- undefined -> % Outer
- execute_outer(Mod, Fun, Args, Factor, Retries, Type);
- {_OldMod, Tid, Ts} -> % Nested
- execute_inner(Mod, Tid, Ts, Fun, Args, Factor, Retries, Type);
- _ -> % Bad nesting
- {aborted, nested_transaction}
- end.
-
-execute_outer(Mod, Fun, Args, Factor, Retries, Type) ->
- case req(start_outer) of
- {error, Reason} ->
- {aborted, Reason};
- {new_tid, Tid, Store} ->
- Ts = #tidstore{store = Store},
- NewTidTs = {Mod, Tid, Ts},
- put(mnesia_activity_state, NewTidTs),
- execute_transaction(Fun, Args, Factor, Retries, Type)
- end.
-
-execute_inner(Mod, Tid, Ts, Fun, Args, Factor, Retries, Type) ->
- case req({add_store, Tid}) of
- {error, Reason} ->
- {aborted, Reason};
- {new_store, Ets} ->
- copy_ets(Ts#tidstore.store, Ets),
- Up = [Ts#tidstore.store | Ts#tidstore.up_stores],
- NewTs = Ts#tidstore{level = 1 + Ts#tidstore.level,
- store = Ets,
- up_stores = Up},
- NewTidTs = {Mod, Tid, NewTs},
- put(mnesia_activity_state, NewTidTs),
- execute_transaction(Fun, Args, Factor, Retries, Type)
- end.
-
-copy_ets(From, To) ->
- do_copy_ets(?ets_first(From), From, To).
-do_copy_ets('$end_of_table', _,_) ->
- ok;
-do_copy_ets(K, From, To) ->
- Objs = ?ets_lookup(From, K),
- insert_objs(Objs, To),
- do_copy_ets(?ets_next(From, K), From, To).
-
-insert_objs([H|T], Tab) ->
- ?ets_insert(Tab, H),
- insert_objs(T, Tab);
-insert_objs([], _Tab) ->
- ok.
-
-execute_transaction(Fun, Args, Factor, Retries, Type) ->
- case catch apply_fun(Fun, Args, Type) of
- {'EXIT', Reason} ->
- check_exit(Fun, Args, Factor, Retries, Reason, Type);
- {'atomic', Value} ->
- mnesia_lib:incr_counter(trans_commits),
- erase(mnesia_activity_state),
- %% no need to clear locks, already done by commit ...
- %% Flush any un processed mnesia_down messages we might have
- flush_downs(),
- {'atomic', Value};
- {nested_atomic, Value} ->
- mnesia_lib:incr_counter(trans_commits),
- {'atomic', Value};
- Value -> %% User called throw
- Reason = {aborted, {throw, Value}},
- return_abort(Fun, Args, Reason)
- end.
-
-apply_fun(Fun, Args, Type) ->
- Result = apply(Fun, Args),
- case t_commit(Type) of
- do_commit ->
- {'atomic', Result};
- do_commit_nested ->
- {nested_atomic, Result};
- {do_abort, {aborted, Reason}} ->
- {'EXIT', {aborted, Reason}};
- {do_abort, Reason} ->
- {'EXIT', {aborted, Reason}}
- end.
-
-check_exit(Fun, Args, Factor, Retries, Reason, Type) ->
- case Reason of
- {aborted, C} when record(C, cyclic) ->
- maybe_restart(Fun, Args, Factor, Retries, Type, C);
- {aborted, {node_not_running, N}} ->
- maybe_restart(Fun, Args, Factor, Retries, Type, {node_not_running, N});
- {aborted, {bad_commit, N}} ->
- maybe_restart(Fun, Args, Factor, Retries, Type, {bad_commit, N});
- _ ->
- return_abort(Fun, Args, Reason)
- end.
-
-maybe_restart(Fun, Args, Factor, Retries, Type, Why) ->
- {Mod, Tid, Ts} = get(mnesia_activity_state),
- case try_again(Retries) of
- yes when Ts#tidstore.level == 1 ->
- restart(Mod, Tid, Ts, Fun, Args, Factor, Retries, Type, Why);
- yes ->
- return_abort(Fun, Args, Why);
- no ->
- return_abort(Fun, Args, {aborted, nomore})
- end.
-
-try_again(infinity) -> yes;
-try_again(X) when number(X) , X > 1 -> yes;
-try_again(_) -> no.
-
-%% We can only restart toplevel transactions.
-%% If a deadlock situation occurs in a nested transaction
-%% The whole thing including all nested transactions need to be
-%% restarted. The stack is thus popped by a consequtive series of
-%% exit({aborted, #cyclic{}}) calls
-
-restart(Mod, Tid, Ts, Fun, Args, Factor0, Retries0, Type, Why) ->
- mnesia_lib:incr_counter(trans_restarts),
- Retries = decr(Retries0),
- case Why of
- {bad_commit, _N} ->
- return_abort(Fun, Args, Why),
- Factor = 1,
- SleepTime = mnesia_lib:random_time(Factor, Tid#tid.counter),
- dbg_out("Restarting transaction ~w: in ~wms ~w~n", [Tid, SleepTime, Why]),
- timer:sleep(SleepTime),
- execute_outer(Mod, Fun, Args, Factor, Retries, Type);
- {node_not_running, _N} -> %% Avoids hanging in receive_release_tid_ack
- return_abort(Fun, Args, Why),
- Factor = 1,
- SleepTime = mnesia_lib:random_time(Factor, Tid#tid.counter),
- dbg_out("Restarting transaction ~w: in ~wms ~w~n", [Tid, SleepTime, Why]),
- timer:sleep(SleepTime),
- execute_outer(Mod, Fun, Args, Factor, Retries, Type);
- _ ->
- SleepTime = mnesia_lib:random_time(Factor0, Tid#tid.counter),
- dbg_out("Restarting transaction ~w: in ~wms ~w~n", [Tid, SleepTime, Why]),
-
- if
- Factor0 /= 10 ->
- ignore;
- true ->
- %% Our serial may be much larger than other nodes ditto
- AllNodes = val({current, db_nodes}),
- verbose("Sync serial ~p~n", [Tid]),
- rpc:abcast(AllNodes, ?MODULE, {sync_trans_serial, Tid})
- end,
- intercept_friends(Tid, Ts),
- Store = Ts#tidstore.store,
- Nodes = get_nodes(Store),
- ?MODULE ! {self(), {restart, Tid, Store}},
- mnesia_locker:send_release_tid(Nodes, Tid),
- timer:sleep(SleepTime),
- mnesia_locker:receive_release_tid_acc(Nodes, Tid),
- case rec() of
- {restarted, Tid} ->
- execute_transaction(Fun, Args, Factor0 + 1,
- Retries, Type);
- {error, Reason} ->
- mnesia:abort(Reason)
- end
- end.
-
-decr(infinity) -> infinity;
-decr(X) when integer(X), X > 1 -> X - 1;
-decr(_X) -> 0.
-
-return_abort(Fun, Args, Reason) ->
- {Mod, Tid, Ts} = get(mnesia_activity_state),
- OldStore = Ts#tidstore.store,
- Nodes = get_nodes(OldStore),
- intercept_friends(Tid, Ts),
- catch mnesia_lib:incr_counter(trans_failures),
- Level = Ts#tidstore.level,
- if
- Level == 1 ->
- mnesia_locker:async_release_tid(Nodes, Tid),
- ?MODULE ! {delete_transaction, Tid},
- erase(mnesia_activity_state),
- dbg_out("Transaction ~p calling ~p with ~p, failed ~p~n",
- [Tid, Fun, Args, Reason]),
- flush_downs(),
- {aborted, mnesia_lib:fix_error(Reason)};
- true ->
- %% Nested transaction
- [NewStore | Tail] = Ts#tidstore.up_stores,
- req({del_store, Tid, NewStore, OldStore, true}),
- Ts2 = Ts#tidstore{store = NewStore,
- up_stores = Tail,
- level = Level - 1},
- NewTidTs = {Mod, Tid, Ts2},
- put(mnesia_activity_state, NewTidTs),
- case Reason of
- #cyclic{} ->
- exit({aborted, Reason});
- {node_not_running, _N} ->
- exit({aborted, Reason});
- {bad_commit, _N}->
- exit({aborted, Reason});
- _ ->
- {aborted, mnesia_lib:fix_error(Reason)}
- end
- end.
-
-flush_downs() ->
- receive
- {?MODULE, _, _} -> flush_downs(); % Votes
- {mnesia_down, _} -> flush_downs()
- after 0 -> flushed
- end.
-
-put_activity_id(undefined) ->
- erase_activity_id();
-put_activity_id({Mod, Tid, Ts}) when record(Tid, tid), record(Ts, tidstore) ->
- flush_downs(),
- Store = Ts#tidstore.store,
- ?ets_insert(Store, {friends, self()}),
- NewTidTs = {Mod, Tid, Ts},
- put(mnesia_activity_state, NewTidTs);
-put_activity_id(SimpleState) ->
- put(mnesia_activity_state, SimpleState).
-
-erase_activity_id() ->
- flush_downs(),
- erase(mnesia_activity_state).
-
-get_nodes(Store) ->
- case catch ?ets_lookup_element(Store, nodes, 2) of
- {'EXIT', _} -> [node()];
- Nodes -> Nodes
- end.
-
-get_friends(Store) ->
- case catch ?ets_lookup_element(Store, friends, 2) of
- {'EXIT', _} -> [];
- Friends -> Friends
- end.
-
-opt_propagate_store(_Current, _Obsolete, false) ->
- ok;
-opt_propagate_store(Current, Obsolete, true) ->
- propagate_store(Current, nodes, get_nodes(Obsolete)),
- propagate_store(Current, friends, get_friends(Obsolete)).
-
-propagate_store(Store, Var, [Val | Vals]) ->
- ?ets_insert(Store, {Var, Val}),
- propagate_store(Store, Var, Vals);
-propagate_store(_Store, _Var, []) ->
- ok.
-
-%% Tell all processes that are cooperating with the current transaction
-intercept_friends(_Tid, Ts) ->
- Friends = get_friends(Ts#tidstore.store),
- Message = {activity_ended, undefined, self()},
- intercept_best_friend(Friends, Message).
-
-intercept_best_friend([], _Message) ->
- ok;
-intercept_best_friend([Pid | _], Message) ->
- Pid ! Message,
- wait_for_best_friend(Pid, 0).
-
-wait_for_best_friend(Pid, Timeout) ->
- receive
- {'EXIT', Pid, _} -> ok;
- {activity_ended, _, Pid} -> ok
- after Timeout ->
- case my_process_is_alive(Pid) of
- true -> wait_for_best_friend(Pid, 1000);
- false -> ok
- end
- end.
-
-my_process_is_alive(Pid) ->
- case catch erlang:is_process_alive(Pid) of % New BIF in R5
- true ->
- true;
- false ->
- false;
- {'EXIT', _} -> % Pre R5 backward compatibility
- case process_info(Pid, message_queue_len) of
- undefined -> false;
- _ -> true
- end
- end.
-
-dirty(Protocol, Item) ->
- {{Tab, Key}, _Val, _Op} = Item,
- Tid = {dirty, self()},
- Prep = prepare_items(Tid, Tab, Key, [Item], #prep{protocol= Protocol}),
- CR = Prep#prep.records,
- case Protocol of
- async_dirty ->
- %% Send commit records to the other involved nodes,
- %% but do only wait for one node to complete.
- %% Preferrably, the local node if possible.
-
- ReadNode = val({Tab, where_to_read}),
- {WaitFor, FirstRes} = async_send_dirty(Tid, CR, Tab, ReadNode),
- rec_dirty(WaitFor, FirstRes);
-
- sync_dirty ->
- %% Send commit records to the other involved nodes,
- %% and wait for all nodes to complete
- {WaitFor, FirstRes} = sync_send_dirty(Tid, CR, Tab, []),
- rec_dirty(WaitFor, FirstRes);
- _ ->
- mnesia:abort({bad_activity, Protocol})
- end.
-
-%% This is the commit function, The first thing it does,
-%% is to find out which nodes that have been participating
-%% in this particular transaction, all of the mnesia_locker:lock*
-%% functions insert the names of the nodes where it aquires locks
-%% into the local shadow Store
-%% This function exacutes in the context of the user process
-t_commit(Type) ->
- {Mod, Tid, Ts} = get(mnesia_activity_state),
- Store = Ts#tidstore.store,
- if
- Ts#tidstore.level == 1 ->
- intercept_friends(Tid, Ts),
- %% N is number of updates
- case arrange(Tid, Store, Type) of
- {N, Prep} when N > 0 ->
- multi_commit(Prep#prep.protocol,
- Tid, Prep#prep.records, Store);
- {0, Prep} ->
- multi_commit(read_only, Tid, Prep#prep.records, Store)
- end;
- true ->
- %% nested commit
- Level = Ts#tidstore.level,
- [Obsolete | Tail] = Ts#tidstore.up_stores,
- req({del_store, Tid, Store, Obsolete, false}),
- NewTs = Ts#tidstore{store = Store,
- up_stores = Tail,
- level = Level - 1},
- NewTidTs = {Mod, Tid, NewTs},
- put(mnesia_activity_state, NewTidTs),
- do_commit_nested
- end.
-
-%% This function arranges for all objects we shall write in S to be
-%% in a list of {Node, CommitRecord}
-%% Important function for the performance of mnesia.
-
-arrange(Tid, Store, Type) ->
- %% The local node is always included
- Nodes = get_nodes(Store),
- Recs = prep_recs(Nodes, []),
- Key = ?ets_first(Store),
- N = 0,
- Prep =
- case Type of
- async -> #prep{protocol = sym_trans, records = Recs};
- sync -> #prep{protocol = sync_sym_trans, records = Recs}
- end,
- case catch do_arrange(Tid, Store, Key, Prep, N) of
- {'EXIT', Reason} ->
- dbg_out("do_arrange failed ~p ~p~n", [Reason, Tid]),
- case Reason of
- {aborted, R} ->
- mnesia:abort(R);
- _ ->
- mnesia:abort(Reason)
- end;
- {New, Prepared} ->
- {New, Prepared#prep{records = reverse(Prepared#prep.records)}}
- end.
-
-reverse([]) ->
- [];
-reverse([H|R]) when record(H, commit) ->
- [
- H#commit{
- ram_copies = lists:reverse(H#commit.ram_copies),
- disc_copies = lists:reverse(H#commit.disc_copies),
- disc_only_copies = lists:reverse(H#commit.disc_only_copies),
- snmp = lists:reverse(H#commit.snmp)
- }
- | reverse(R)].
-
-prep_recs([N | Nodes], Recs) ->
- prep_recs(Nodes, [#commit{decision = presume_commit, node = N} | Recs]);
-prep_recs([], Recs) ->
- Recs.
-
-%% storage_types is a list of {Node, Storage} tuples
-%% where each tuple represents an active replica
-do_arrange(Tid, Store, {Tab, Key}, Prep, N) ->
- Oid = {Tab, Key},
- Items = ?ets_lookup(Store, Oid), %% Store is a bag
- P2 = prepare_items(Tid, Tab, Key, Items, Prep),
- do_arrange(Tid, Store, ?ets_next(Store, Oid), P2, N + 1);
-do_arrange(Tid, Store, SchemaKey, Prep, N) when SchemaKey == op ->
- Items = ?ets_lookup(Store, SchemaKey), %% Store is a bag
- P2 = prepare_schema_items(Tid, Items, Prep),
- do_arrange(Tid, Store, ?ets_next(Store, SchemaKey), P2, N + 1);
-do_arrange(Tid, Store, RestoreKey, Prep, N) when RestoreKey == restore_op ->
- [{restore_op, R}] = ?ets_lookup(Store, RestoreKey),
- Fun = fun({Tab, Key}, CommitRecs, _RecName, Where, Snmp) ->
- Item = [{{Tab, Key}, {Tab, Key}, delete}],
- do_prepare_items(Tid, Tab, Key, Where, Snmp, Item, CommitRecs);
- (BupRec, CommitRecs, RecName, Where, Snmp) ->
- Tab = element(1, BupRec),
- Key = element(2, BupRec),
- Item =
- if
- Tab == RecName ->
- [{{Tab, Key}, BupRec, write}];
- true ->
- BupRec2 = setelement(1, BupRec, RecName),
- [{{Tab, Key}, BupRec2, write}]
- end,
- do_prepare_items(Tid, Tab, Key, Where, Snmp, Item, CommitRecs)
- end,
- Recs2 = mnesia_schema:arrange_restore(R, Fun, Prep#prep.records),
- P2 = Prep#prep{protocol = asym_trans, records = Recs2},
- do_arrange(Tid, Store, ?ets_next(Store, RestoreKey), P2, N + 1);
-do_arrange(_Tid, _Store, '$end_of_table', Prep, N) ->
- {N, Prep};
-do_arrange(Tid, Store, IgnoredKey, Prep, N) -> %% locks, nodes ... local atoms...
- do_arrange(Tid, Store, ?ets_next(Store, IgnoredKey), Prep, N).
-
-%% Returns a prep record with all items in reverse order
-prepare_schema_items(Tid, Items, Prep) ->
- Types = [{N, schema_ops} || N <- val({current, db_nodes})],
- Recs = prepare_nodes(Tid, Types, Items, Prep#prep.records, schema),
- Prep#prep{protocol = asym_trans, records = Recs}.
-
-%% Returns a prep record with all items in reverse order
-prepare_items(Tid, Tab, Key, Items, Prep) when Prep#prep.prev_tab == Tab ->
- Types = Prep#prep.prev_types,
- Snmp = Prep#prep.prev_snmp,
- Recs = Prep#prep.records,
- Recs2 = do_prepare_items(Tid, Tab, Key, Types, Snmp, Items, Recs),
- Prep#prep{records = Recs2};
-
-prepare_items(Tid, Tab, Key, Items, Prep) ->
- Types = val({Tab, where_to_commit}),
- case Types of
- [] -> mnesia:abort({no_exists, Tab});
- {blocked, _} ->
- unblocked = req({unblock_me, Tab}),
- prepare_items(Tid, Tab, Key, Items, Prep);
- _ ->
- Snmp = val({Tab, snmp}),
- Recs2 = do_prepare_items(Tid, Tab, Key, Types,
- Snmp, Items, Prep#prep.records),
- Prep2 = Prep#prep{records = Recs2, prev_tab = Tab,
- prev_types = Types, prev_snmp = Snmp},
- check_prep(Prep2, Types)
- end.
-
-do_prepare_items(Tid, Tab, Key, Types, Snmp, Items, Recs) ->
- Recs2 = prepare_snmp(Tid, Tab, Key, Types, Snmp, Items, Recs), % May exit
- prepare_nodes(Tid, Types, Items, Recs2, normal).
-
-prepare_snmp(Tab, Key, Items) ->
- case val({Tab, snmp}) of
- [] ->
- [];
- Ustruct when Key /= '_' ->
- {_Oid, _Val, Op} = hd(Items),
- %% Still making snmp oid (not used) because we want to catch errors here
- %% And also it keeps backwards comp. with old nodes.
- SnmpOid = mnesia_snmp_hook:key_to_oid(Tab, Key, Ustruct), % May exit
- [{Op, Tab, Key, SnmpOid}];
- _ ->
- [{clear_table, Tab}]
- end.
-
-prepare_snmp(_Tid, _Tab, _Key, _Types, [], _Items, Recs) ->
- Recs;
-
-prepare_snmp(Tid, Tab, Key, Types, Us, Items, Recs) ->
- if Key /= '_' ->
- {_Oid, _Val, Op} = hd(Items),
- SnmpOid = mnesia_snmp_hook:key_to_oid(Tab, Key, Us), % May exit
- prepare_nodes(Tid, Types, [{Op, Tab, Key, SnmpOid}], Recs, snmp);
- Key == '_' ->
- prepare_nodes(Tid, Types, [{clear_table, Tab}], Recs, snmp)
- end.
-
-check_prep(Prep, Types) when Prep#prep.types == Types ->
- Prep;
-check_prep(Prep, Types) when Prep#prep.types == undefined ->
- Prep#prep{types = Types};
-check_prep(Prep, _Types) ->
- Prep#prep{protocol = asym_trans}.
-
-%% Returns a list of commit records
-prepare_nodes(Tid, [{Node, Storage} | Rest], Items, C, Kind) ->
- {Rec, C2} = pick_node(Tid, Node, C, []),
- Rec2 = prepare_node(Node, Storage, Items, Rec, Kind),
- [Rec2 | prepare_nodes(Tid, Rest, Items, C2, Kind)];
-prepare_nodes(_Tid, [], _Items, CommitRecords, _Kind) ->
- CommitRecords.
-
-pick_node(Tid, Node, [Rec | Rest], Done) ->
- if
- Rec#commit.node == Node ->
- {Rec, Done ++ Rest};
- true ->
- pick_node(Tid, Node, Rest, [Rec | Done])
- end;
-pick_node(_Tid, Node, [], Done) ->
- {#commit{decision = presume_commit, node = Node}, Done}.
-
-prepare_node(Node, Storage, [Item | Items], Rec, Kind) when Kind == snmp ->
- Rec2 = Rec#commit{snmp = [Item | Rec#commit.snmp]},
- prepare_node(Node, Storage, Items, Rec2, Kind);
-prepare_node(Node, Storage, [Item | Items], Rec, Kind) when Kind /= schema ->
- Rec2 =
- case Storage of
- ram_copies ->
- Rec#commit{ram_copies = [Item | Rec#commit.ram_copies]};
- disc_copies ->
- Rec#commit{disc_copies = [Item | Rec#commit.disc_copies]};
- disc_only_copies ->
- Rec#commit{disc_only_copies =
- [Item | Rec#commit.disc_only_copies]}
- end,
- prepare_node(Node, Storage, Items, Rec2, Kind);
-prepare_node(_Node, _Storage, Items, Rec, Kind)
- when Kind == schema, Rec#commit.schema_ops == [] ->
- Rec#commit{schema_ops = Items};
-prepare_node(_Node, _Storage, [], Rec, _Kind) ->
- Rec.
-
-%% multi_commit((Protocol, Tid, CommitRecords, Store)
-%% Local work is always performed in users process
-multi_commit(read_only, Tid, CR, _Store) ->
- %% This featherweight commit protocol is used when no
- %% updates has been performed in the transaction.
-
- {DiscNs, RamNs} = commit_nodes(CR, [], []),
- Msg = {Tid, simple_commit},
- rpc:abcast(DiscNs -- [node()], ?MODULE, Msg),
- rpc:abcast(RamNs -- [node()], ?MODULE, Msg),
- mnesia_recover:note_decision(Tid, committed),
- mnesia_locker:release_tid(Tid),
- ?MODULE ! {delete_transaction, Tid},
- do_commit;
-
-multi_commit(sym_trans, Tid, CR, Store) ->
- %% This lightweight commit protocol is used when all
- %% the involved tables are replicated symetrically.
- %% Their storage types must match on each node.
- %%
- %% 1 Ask the other involved nodes if they want to commit
- %% All involved nodes votes yes if they are up
- %% 2a Somebody has voted no
- %% Tell all yes voters to do_abort
- %% 2b Everybody has voted yes
- %% Tell everybody to do_commit. I.e. that they should
- %% prepare the commit, log the commit record and
- %% perform the updates.
- %%
- %% The outcome is kept 3 minutes in the transient decision table.
- %%
- %% Recovery:
- %% If somebody dies before the coordinator has
- %% broadcasted do_commit, the transaction is aborted.
- %%
- %% If a participant dies, the table load algorithm
- %% ensures that the contents of the involved tables
- %% are picked from another node.
- %%
- %% If the coordinator dies, each participants checks
- %% the outcome with all the others. If all are uncertain
- %% about the outcome, the transaction is aborted. If
- %% somebody knows the outcome the others will follow.
-
- {DiscNs, RamNs} = commit_nodes(CR, [], []),
- Pending = mnesia_checkpoint:tm_enter_pending(Tid, DiscNs, RamNs),
- ?ets_insert(Store, Pending),
-
- {WaitFor, Local} = ask_commit(sym_trans, Tid, CR, DiscNs, RamNs),
- {Outcome, []} = rec_all(WaitFor, Tid, do_commit, []),
- ?eval_debug_fun({?MODULE, multi_commit_sym},
- [{tid, Tid}, {outcome, Outcome}]),
- rpc:abcast(DiscNs -- [node()], ?MODULE, {Tid, Outcome}),
- rpc:abcast(RamNs -- [node()], ?MODULE, {Tid, Outcome}),
- case Outcome of
- do_commit ->
- mnesia_recover:note_decision(Tid, committed),
- do_dirty(Tid, Local),
- mnesia_locker:release_tid(Tid),
- ?MODULE ! {delete_transaction, Tid};
- {do_abort, _Reason} ->
- mnesia_recover:note_decision(Tid, aborted)
- end,
- ?eval_debug_fun({?MODULE, multi_commit_sym, post},
- [{tid, Tid}, {outcome, Outcome}]),
- Outcome;
-
-multi_commit(sync_sym_trans, Tid, CR, Store) ->
- %% This protocol is the same as sym_trans except that it
- %% uses syncronized calls to disk_log and syncronized commits
- %% when several nodes are involved.
-
- {DiscNs, RamNs} = commit_nodes(CR, [], []),
- Pending = mnesia_checkpoint:tm_enter_pending(Tid, DiscNs, RamNs),
- ?ets_insert(Store, Pending),
-
- {WaitFor, Local} = ask_commit(sync_sym_trans, Tid, CR, DiscNs, RamNs),
- {Outcome, []} = rec_all(WaitFor, Tid, do_commit, []),
- ?eval_debug_fun({?MODULE, multi_commit_sym_sync},
- [{tid, Tid}, {outcome, Outcome}]),
- rpc:abcast(DiscNs -- [node()], ?MODULE, {Tid, Outcome}),
- rpc:abcast(RamNs -- [node()], ?MODULE, {Tid, Outcome}),
- case Outcome of
- do_commit ->
- mnesia_recover:note_decision(Tid, committed),
- mnesia_log:slog(Local),
- do_commit(Tid, Local),
- %% Just wait for completion result is ignore.
- rec_all(WaitFor, Tid, ignore, []),
- mnesia_locker:release_tid(Tid),
- ?MODULE ! {delete_transaction, Tid};
- {do_abort, _Reason} ->
- mnesia_recover:note_decision(Tid, aborted)
- end,
- ?eval_debug_fun({?MODULE, multi_commit_sym, post},
- [{tid, Tid}, {outcome, Outcome}]),
- Outcome;
-
-multi_commit(asym_trans, Tid, CR, Store) ->
- %% This more expensive commit protocol is used when
- %% table definitions are changed (schema transactions).
- %% It is also used when the involved tables are
- %% replicated asymetrically. If the storage type differs
- %% on at least one node this protocol is used.
- %%
- %% 1 Ask the other involved nodes if they want to commit.
- %% All involved nodes prepares the commit, logs a presume_abort
- %% commit record and votes yes or no depending of the
- %% outcome of the prepare. The preparation is also performed
- %% by the coordinator.
- %%
- %% 2a Somebody has died or voted no
- %% Tell all yes voters to do_abort
- %% 2b Everybody has voted yes
- %% Put a unclear marker in the log.
- %% Tell the others to pre_commit. I.e. that they should
- %% put a unclear marker in the log and reply
- %% acc_pre_commit when they are done.
- %%
- %% 3a Somebody died
- %% Tell the remaining participants to do_abort
- %% 3b Everybody has replied acc_pre_commit
- %% Tell everybody to committed. I.e that they should
- %% put a committed marker in the log, perform the updates
- %% and reply done_commit when they are done. The coordinator
- %% must wait with putting his committed marker inte the log
- %% until the committed has been sent to all the others.
- %% Then he performs local commit before collecting replies.
- %%
- %% 4 Everybody has either died or replied done_commit
- %% Return to the caller.
- %%
- %% Recovery:
- %% If the coordinator dies, the participants (and
- %% the coordinator when he starts again) must do
- %% the following:
- %%
- %% If we have no unclear marker in the log we may
- %% safely abort, since we know that nobody may have
- %% decided to commit yet.
- %%
- %% If we have a committed marker in the log we may
- %% safely commit since we know that everybody else
- %% also will come to this conclusion.
- %%
- %% If we have a unclear marker but no committed
- %% in the log we are uncertain about the real outcome
- %% of the transaction and must ask the others before
- %% we can decide what to do. If someone knows the
- %% outcome we will do the same. If nobody knows, we
- %% will wait for the remaining involved nodes to come
- %% up. When all involved nodes are up and uncertain,
- %% we decide to commit (first put a committed marker
- %% in the log, then do the updates).
-
- D = #decision{tid = Tid, outcome = presume_abort},
- {D2, CR2} = commit_decision(D, CR, [], []),
- DiscNs = D2#decision.disc_nodes,
- RamNs = D2#decision.ram_nodes,
- Pending = mnesia_checkpoint:tm_enter_pending(Tid, DiscNs, RamNs),
- ?ets_insert(Store, Pending),
- {WaitFor, Local} = ask_commit(asym_trans, Tid, CR2, DiscNs, RamNs),
- SchemaPrep = (catch mnesia_schema:prepare_commit(Tid, Local, {coord, WaitFor})),
- {Votes, Pids} = rec_all(WaitFor, Tid, do_commit, []),
-
- ?eval_debug_fun({?MODULE, multi_commit_asym_got_votes},
- [{tid, Tid}, {votes, Votes}]),
- case Votes of
- do_commit ->
- case SchemaPrep of
- {_Modified, C, DumperMode} when record(C, commit) ->
- mnesia_log:log(C), % C is not a binary
- ?eval_debug_fun({?MODULE, multi_commit_asym_log_commit_rec},
- [{tid, Tid}]),
-
- D3 = C#commit.decision,
- D4 = D3#decision{outcome = unclear},
- mnesia_recover:log_decision(D4),
- ?eval_debug_fun({?MODULE, multi_commit_asym_log_commit_dec},
- [{tid, Tid}]),
- tell_participants(Pids, {Tid, pre_commit}),
- %% Now we are uncertain and we do not know
- %% if all participants have logged that
- %% they are uncertain or not
- rec_acc_pre_commit(Pids, Tid, Store, C,
- do_commit, DumperMode, [], []);
- {'EXIT', Reason} ->
- %% The others have logged the commit
- %% record but they are not uncertain
- mnesia_recover:note_decision(Tid, aborted),
- ?eval_debug_fun({?MODULE, multi_commit_asym_prepare_exit},
- [{tid, Tid}]),
- tell_participants(Pids, {Tid, {do_abort, Reason}}),
- do_abort(Tid, Local),
- {do_abort, Reason}
- end;
-
- {do_abort, Reason} ->
- %% The others have logged the commit
- %% record but they are not uncertain
- mnesia_recover:note_decision(Tid, aborted),
- ?eval_debug_fun({?MODULE, multi_commit_asym_do_abort}, [{tid, Tid}]),
- tell_participants(Pids, {Tid, {do_abort, Reason}}),
- do_abort(Tid, Local),
- {do_abort, Reason}
- end.
-
-%% Returns do_commit or {do_abort, Reason}
-rec_acc_pre_commit([Pid | Tail], Tid, Store, Commit, Res, DumperMode,
- GoodPids, SchemaAckPids) ->
- receive
- {?MODULE, _, {acc_pre_commit, Tid, Pid, true}} ->
- rec_acc_pre_commit(Tail, Tid, Store, Commit, Res, DumperMode,
- [Pid | GoodPids], [Pid | SchemaAckPids]);
-
- {?MODULE, _, {acc_pre_commit, Tid, Pid, false}} ->
- rec_acc_pre_commit(Tail, Tid, Store, Commit, Res, DumperMode,
- [Pid | GoodPids], SchemaAckPids);
-
- {?MODULE, _, {acc_pre_commit, Tid, Pid}} ->
- %% Kept for backwards compatibility. Remove after Mnesia 4.x
- rec_acc_pre_commit(Tail, Tid, Store, Commit, Res, DumperMode,
- [Pid | GoodPids], [Pid | SchemaAckPids]);
-
- {mnesia_down, Node} when Node == node(Pid) ->
- AbortRes = {do_abort, {bad_commit, Node}},
- rec_acc_pre_commit(Tail, Tid, Store, Commit, AbortRes, DumperMode,
- GoodPids, SchemaAckPids)
- end;
-rec_acc_pre_commit([], Tid, Store, Commit, Res, DumperMode, GoodPids, SchemaAckPids) ->
- D = Commit#commit.decision,
- case Res of
- do_commit ->
- %% Now everybody knows that the others
- %% has voted yes. We also know that
- %% everybody are uncertain.
- prepare_sync_schema_commit(Store, SchemaAckPids),
- tell_participants(GoodPids, {Tid, committed}),
- D2 = D#decision{outcome = committed},
- mnesia_recover:log_decision(D2),
- ?eval_debug_fun({?MODULE, rec_acc_pre_commit_log_commit},
- [{tid, Tid}]),
-
- %% Now we have safely logged committed
- %% and we can recover without asking others
- do_commit(Tid, Commit, DumperMode),
- ?eval_debug_fun({?MODULE, rec_acc_pre_commit_done_commit},
- [{tid, Tid}]),
- sync_schema_commit(Tid, Store, SchemaAckPids),
- mnesia_locker:release_tid(Tid),
- ?MODULE ! {delete_transaction, Tid};
-
- {do_abort, Reason} ->
- tell_participants(GoodPids, {Tid, {do_abort, Reason}}),
- D2 = D#decision{outcome = aborted},
- mnesia_recover:log_decision(D2),
- ?eval_debug_fun({?MODULE, rec_acc_pre_commit_log_abort},
- [{tid, Tid}]),
- do_abort(Tid, Commit),
- ?eval_debug_fun({?MODULE, rec_acc_pre_commit_done_abort},
- [{tid, Tid}])
- end,
- Res.
-
-%% Note all nodes in case of mnesia_down mgt
-prepare_sync_schema_commit(_Store, []) ->
- ok;
-prepare_sync_schema_commit(Store, [Pid | Pids]) ->
- ?ets_insert(Store, {waiting_for_commit_ack, node(Pid)}),
- prepare_sync_schema_commit(Store, Pids).
-
-sync_schema_commit(_Tid, _Store, []) ->
- ok;
-sync_schema_commit(Tid, Store, [Pid | Tail]) ->
- receive
- {?MODULE, _, {schema_commit, Tid, Pid}} ->
- ?ets_match_delete(Store, {waiting_for_commit_ack, node(Pid)}),
- sync_schema_commit(Tid, Store, Tail);
-
- {mnesia_down, Node} when Node == node(Pid) ->
- ?ets_match_delete(Store, {waiting_for_commit_ack, Node}),
- sync_schema_commit(Tid, Store, Tail)
- end.
-
-tell_participants([Pid | Pids], Msg) ->
- Pid ! Msg,
- tell_participants(Pids, Msg);
-tell_participants([], _Msg) ->
- ok.
-
-%% No need for trapping exits. We are only linked
-%% to mnesia_tm and if it dies we should also die.
-%% The same goes for disk_log and dets.
-commit_participant(Coord, Tid, Bin, DiscNs, RamNs) when binary(Bin) ->
- Commit = binary_to_term(Bin),
- commit_participant(Coord, Tid, Bin, Commit, DiscNs, RamNs);
-commit_participant(Coord, Tid, C, DiscNs, RamNs) when record(C, commit) ->
- commit_participant(Coord, Tid, C, C, DiscNs, RamNs).
-
-commit_participant(Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
- ?eval_debug_fun({?MODULE, commit_participant, pre}, [{tid, Tid}]),
- case catch mnesia_schema:prepare_commit(Tid, C0, {part, Coord}) of
- {Modified, C, DumperMode} when record(C, commit) ->
- %% If we can not find any local unclear decision
- %% we should presume abort at startup recovery
- case lists:member(node(), DiscNs) of
- false ->
- ignore;
- true ->
- case Modified of
- false -> mnesia_log:log(Bin);
- true -> mnesia_log:log(C)
- end
- end,
- ?eval_debug_fun({?MODULE, commit_participant, vote_yes},
- [{tid, Tid}]),
- reply(Coord, {vote_yes, Tid, self()}),
-
- receive
- {Tid, pre_commit} ->
- D = C#commit.decision,
- mnesia_recover:log_decision(D#decision{outcome = unclear}),
- ?eval_debug_fun({?MODULE, commit_participant, pre_commit},
- [{tid, Tid}]),
- Expect_schema_ack = C#commit.schema_ops /= [],
- reply(Coord, {acc_pre_commit, Tid, self(), Expect_schema_ack}),
-
- %% Now we are vulnerable for failures, since
- %% we cannot decide without asking others
- receive
- {Tid, committed} ->
- mnesia_recover:log_decision(D#decision{outcome = committed}),
- ?eval_debug_fun({?MODULE, commit_participant, log_commit},
- [{tid, Tid}]),
- do_commit(Tid, C, DumperMode),
- case Expect_schema_ack of
- false -> ignore;
- true -> reply(Coord, {schema_commit, Tid, self()})
- end,
- ?eval_debug_fun({?MODULE, commit_participant, do_commit},
- [{tid, Tid}]);
-
- {Tid, {do_abort, _Reason}} ->
- mnesia_recover:log_decision(D#decision{outcome = aborted}),
- ?eval_debug_fun({?MODULE, commit_participant, log_abort},
- [{tid, Tid}]),
- mnesia_schema:undo_prepare_commit(Tid, C),
- ?eval_debug_fun({?MODULE, commit_participant, undo_prepare},
- [{tid, Tid}]);
-
- {'EXIT', _, _} ->
- mnesia_recover:log_decision(D#decision{outcome = aborted}),
- ?eval_debug_fun({?MODULE, commit_participant, exit_log_abort},
- [{tid, Tid}]),
- mnesia_schema:undo_prepare_commit(Tid, C),
- ?eval_debug_fun({?MODULE, commit_participant, exit_undo_prepare},
- [{tid, Tid}]);
-
- Msg ->
- verbose("** ERROR ** commit_participant ~p, got unexpected msg: ~p~n",
- [Tid, Msg])
- end;
- {Tid, {do_abort, _Reason}} ->
- mnesia_schema:undo_prepare_commit(Tid, C),
- ?eval_debug_fun({?MODULE, commit_participant, pre_commit_undo_prepare},
- [{tid, Tid}]);
-
- {'EXIT', _, _} ->
- mnesia_schema:undo_prepare_commit(Tid, C),
- ?eval_debug_fun({?MODULE, commit_participant, pre_commit_undo_prepare}, [{tid, Tid}]);
-
- Msg ->
- verbose("** ERROR ** commit_participant ~p, got unexpected msg: ~p~n",
- [Tid, Msg])
- end;
-
- {'EXIT', Reason} ->
- ?eval_debug_fun({?MODULE, commit_participant, vote_no},
- [{tid, Tid}]),
- reply(Coord, {vote_no, Tid, Reason}),
- mnesia_schema:undo_prepare_commit(Tid, C0)
- end,
- mnesia_locker:release_tid(Tid),
- ?MODULE ! {delete_transaction, Tid},
- unlink(whereis(?MODULE)),
- exit(normal).
-
-do_abort(Tid, Bin) when binary(Bin) ->
- %% Possible optimization:
- %% If we want we could pass arround a flag
- %% that tells us whether the binary contains
- %% schema ops or not. Only if the binary
- %% contains schema ops there are meningful
- %% unpack the binary and perform
- %% mnesia_schema:undo_prepare_commit/1.
- do_abort(Tid, binary_to_term(Bin));
-do_abort(Tid, Commit) ->
- mnesia_schema:undo_prepare_commit(Tid, Commit),
- Commit.
-
-do_dirty(Tid, Commit) when Commit#commit.schema_ops == [] ->
- mnesia_log:log(Commit),
- do_commit(Tid, Commit).
-
-%% do_commit(Tid, CommitRecord)
-do_commit(Tid, Bin) when binary(Bin) ->
- do_commit(Tid, binary_to_term(Bin));
-do_commit(Tid, C) ->
- do_commit(Tid, C, optional).
-do_commit(Tid, Bin, DumperMode) when binary(Bin) ->
- do_commit(Tid, binary_to_term(Bin), DumperMode);
-do_commit(Tid, C, DumperMode) ->
- mnesia_dumper:update(Tid, C#commit.schema_ops, DumperMode),
- R = do_snmp(Tid, C#commit.snmp),
- R2 = do_update(Tid, ram_copies, C#commit.ram_copies, R),
- R3 = do_update(Tid, disc_copies, C#commit.disc_copies, R2),
- do_update(Tid, disc_only_copies, C#commit.disc_only_copies, R3).
-
-%% Update the items
-do_update(Tid, Storage, [Op | Ops], OldRes) ->
- case catch do_update_op(Tid, Storage, Op) of
- ok ->
- do_update(Tid, Storage, Ops, OldRes);
- {'EXIT', Reason} ->
- %% This may only happen when we recently have
- %% deleted our local replica, changed storage_type
- %% or transformed table
- %% BUGBUG: Updates may be lost if storage_type is changed.
- %% Determine actual storage type and try again.
- %% BUGBUG: Updates may be lost if table is transformed.
-
- verbose("do_update in ~w failed: ~p -> {'EXIT', ~p}~n",
- [Tid, Op, Reason]),
- do_update(Tid, Storage, Ops, OldRes);
- NewRes ->
- do_update(Tid, Storage, Ops, NewRes)
- end;
-do_update(_Tid, _Storage, [], Res) ->
- Res.
-
-do_update_op(Tid, Storage, {{Tab, K}, Obj, write}) ->
- commit_write(?catch_val({Tab, commit_work}), Tid,
- Tab, K, Obj, undefined),
- mnesia_lib:db_put(Storage, Tab, Obj);
-
-do_update_op(Tid, Storage, {{Tab, K}, Val, delete}) ->
- commit_delete(?catch_val({Tab, commit_work}), Tid, Tab, K, Val, undefined),
- mnesia_lib:db_erase(Storage, Tab, K);
-
-do_update_op(Tid, Storage, {{Tab, K}, {RecName, Incr}, update_counter}) ->
- {NewObj, OldObjs} =
- case catch mnesia_lib:db_update_counter(Storage, Tab, K, Incr) of
- NewVal when integer(NewVal), NewVal >= 0 ->
- {{RecName, K, NewVal}, [{RecName, K, NewVal - Incr}]};
- _ ->
- Zero = {RecName, K, 0},
- mnesia_lib:db_put(Storage, Tab, Zero),
- {Zero, []}
- end,
- commit_update(?catch_val({Tab, commit_work}), Tid, Tab,
- K, NewObj, OldObjs),
- element(3, NewObj);
-
-do_update_op(Tid, Storage, {{Tab, Key}, Obj, delete_object}) ->
- commit_del_object(?catch_val({Tab, commit_work}),
- Tid, Tab, Key, Obj, undefined),
- mnesia_lib:db_match_erase(Storage, Tab, Obj);
-
-do_update_op(Tid, Storage, {{Tab, Key}, Obj, clear_table}) ->
- commit_clear(?catch_val({Tab, commit_work}), Tid, Tab, Key, Obj),
- mnesia_lib:db_match_erase(Storage, Tab, Obj).
-
-commit_write([], _, _, _, _, _) -> ok;
-commit_write([{checkpoints, CpList}|R], Tid, Tab, K, Obj, Old) ->
- mnesia_checkpoint:tm_retain(Tid, Tab, K, write, CpList),
- commit_write(R, Tid, Tab, K, Obj, Old);
-commit_write([H|R], Tid, Tab, K, Obj, Old)
- when element(1, H) == subscribers ->
- mnesia_subscr:report_table_event(H, Tab, Tid, Obj, write, Old),
- commit_write(R, Tid, Tab, K, Obj, Old);
-commit_write([H|R], Tid, Tab, K, Obj, Old)
- when element(1, H) == index ->
- mnesia_index:add_index(H, Tab, K, Obj, Old),
- commit_write(R, Tid, Tab, K, Obj, Old).
-
-commit_update([], _, _, _, _, _) -> ok;
-commit_update([{checkpoints, CpList}|R], Tid, Tab, K, Obj, _) ->
- Old = mnesia_checkpoint:tm_retain(Tid, Tab, K, write, CpList),
- commit_update(R, Tid, Tab, K, Obj, Old);
-commit_update([H|R], Tid, Tab, K, Obj, Old)
- when element(1, H) == subscribers ->
- mnesia_subscr:report_table_event(H, Tab, Tid, Obj, write, Old),
- commit_update(R, Tid, Tab, K, Obj, Old);
-commit_update([H|R], Tid, Tab, K, Obj, Old)
- when element(1, H) == index ->
- mnesia_index:add_index(H, Tab, K, Obj, Old),
- commit_update(R, Tid, Tab, K, Obj, Old).
-
-commit_delete([], _, _, _, _, _) -> ok;
-commit_delete([{checkpoints, CpList}|R], Tid, Tab, K, Obj, _) ->
- Old = mnesia_checkpoint:tm_retain(Tid, Tab, K, delete, CpList),
- commit_delete(R, Tid, Tab, K, Obj, Old);
-commit_delete([H|R], Tid, Tab, K, Obj, Old)
- when element(1, H) == subscribers ->
- mnesia_subscr:report_table_event(H, Tab, Tid, Obj, delete, Old),
- commit_delete(R, Tid, Tab, K, Obj, Old);
-commit_delete([H|R], Tid, Tab, K, Obj, Old)
- when element(1, H) == index ->
- mnesia_index:delete_index(H, Tab, K),
- commit_delete(R, Tid, Tab, K, Obj, Old).
-
-commit_del_object([], _, _, _, _, _) -> ok;
-commit_del_object([{checkpoints, CpList}|R], Tid, Tab, K, Obj, _) ->
- Old = mnesia_checkpoint:tm_retain(Tid, Tab, K, delete_object, CpList),
- commit_del_object(R, Tid, Tab, K, Obj, Old);
-commit_del_object([H|R], Tid, Tab, K, Obj, Old)
- when element(1, H) == subscribers ->
- mnesia_subscr:report_table_event(H, Tab, Tid, Obj, delete_object, Old),
- commit_del_object(R, Tid, Tab, K, Obj, Old);
-commit_del_object([H|R], Tid, Tab, K, Obj, Old)
- when element(1, H) == index ->
- mnesia_index:del_object_index(H, Tab, K, Obj, Old),
- commit_del_object(R, Tid, Tab, K, Obj, Old).
-
-commit_clear([], _, _, _, _) -> ok;
-commit_clear([{checkpoints, CpList}|R], Tid, Tab, K, Obj) ->
- mnesia_checkpoint:tm_retain(Tid, Tab, K, clear_table, CpList),
- commit_clear(R, Tid, Tab, K, Obj);
-commit_clear([H|R], Tid, Tab, K, Obj)
- when element(1, H) == subscribers ->
- mnesia_subscr:report_table_event(H, Tab, Tid, Obj, clear_table, undefined),
- commit_clear(R, Tid, Tab, K, Obj);
-commit_clear([H|R], Tid, Tab, K, Obj)
- when element(1, H) == index ->
- mnesia_index:clear_index(H, Tab, K, Obj),
- commit_clear(R, Tid, Tab, K, Obj).
-
-do_snmp(_, []) -> ok;
-do_snmp(Tid, [Head | Tail]) ->
- case catch mnesia_snmp_hook:update(Head) of
- {'EXIT', Reason} ->
- %% This should only happen when we recently have
- %% deleted our local replica or recently deattached
- %% the snmp table
-
- verbose("do_snmp in ~w failed: ~p -> {'EXIT', ~p}~n",
- [Tid, Head, Reason]);
- ok ->
- ignore
- end,
- do_snmp(Tid, Tail).
-
-commit_nodes([C | Tail], AccD, AccR)
- when C#commit.disc_copies == [],
- C#commit.disc_only_copies == [],
- C#commit.schema_ops == [] ->
- commit_nodes(Tail, AccD, [C#commit.node | AccR]);
-commit_nodes([C | Tail], AccD, AccR) ->
- commit_nodes(Tail, [C#commit.node | AccD], AccR);
-commit_nodes([], AccD, AccR) ->
- {AccD, AccR}.
-
-commit_decision(D, [C | Tail], AccD, AccR) ->
- N = C#commit.node,
- {D2, Tail2} =
- case C#commit.schema_ops of
- [] when C#commit.disc_copies == [],
- C#commit.disc_only_copies == [] ->
- commit_decision(D, Tail, AccD, [N | AccR]);
- [] ->
- commit_decision(D, Tail, [N | AccD], AccR);
- Ops ->
- case ram_only_ops(N, Ops) of
- true ->
- commit_decision(D, Tail, AccD, [N | AccR]);
- false ->
- commit_decision(D, Tail, [N | AccD], AccR)
- end
- end,
- {D2, [C#commit{decision = D2} | Tail2]};
-commit_decision(D, [], AccD, AccR) ->
- {D#decision{disc_nodes = AccD, ram_nodes = AccR}, []}.
-
-ram_only_ops(N, [{op, change_table_copy_type, N, _FromS, _ToS, Cs} | _Ops ]) ->
- case lists:member({name, schema}, Cs) of
- true ->
- %% We always use disk if change type of the schema
- false;
- false ->
- not lists:member(N, val({schema, disc_copies}))
- end;
-
-ram_only_ops(N, _Ops) ->
- not lists:member(N, val({schema, disc_copies})).
-
-%% Returns {WaitFor, Res}
-sync_send_dirty(Tid, [Head | Tail], Tab, WaitFor) ->
- Node = Head#commit.node,
- if
- Node == node() ->
- {WF, _} = sync_send_dirty(Tid, Tail, Tab, WaitFor),
- Res = do_dirty(Tid, Head),
- {WF, Res};
- true ->
- {?MODULE, Node} ! {self(), {sync_dirty, Tid, Head, Tab}},
- sync_send_dirty(Tid, Tail, Tab, [Node | WaitFor])
- end;
-sync_send_dirty(_Tid, [], _Tab, WaitFor) ->
- {WaitFor, {'EXIT', {aborted, {node_not_running, WaitFor}}}}.
-
-%% Returns {WaitFor, Res}
-async_send_dirty(_Tid, _Nodes, Tab, nowhere) ->
- {[], {'EXIT', {aborted, {no_exists, Tab}}}};
-async_send_dirty(Tid, Nodes, Tab, ReadNode) ->
- async_send_dirty(Tid, Nodes, Tab, ReadNode, [], ok).
-
-async_send_dirty(Tid, [Head | Tail], Tab, ReadNode, WaitFor, Res) ->
- Node = Head#commit.node,
- if
- ReadNode == Node, Node == node() ->
- NewRes = do_dirty(Tid, Head),
- async_send_dirty(Tid, Tail, Tab, ReadNode, WaitFor, NewRes);
- ReadNode == Node ->
- {?MODULE, Node} ! {self(), {sync_dirty, Tid, Head, Tab}},
- NewRes = {'EXIT', {aborted, {node_not_running, Node}}},
- async_send_dirty(Tid, Tail, Tab, ReadNode, [Node | WaitFor], NewRes);
- true ->
- {?MODULE, Node} ! {self(), {async_dirty, Tid, Head, Tab}},
- async_send_dirty(Tid, Tail, Tab, ReadNode, WaitFor, Res)
- end;
-async_send_dirty(_Tid, [], _Tab, _ReadNode, WaitFor, Res) ->
- {WaitFor, Res}.
-
-rec_dirty([Node | Tail], Res) when Node /= node() ->
- NewRes = get_dirty_reply(Node, Res),
- rec_dirty(Tail, NewRes);
-rec_dirty([], Res) ->
- Res.
-
-get_dirty_reply(Node, Res) ->
- receive
- {?MODULE, Node, {'EXIT', Reason}} ->
- {'EXIT', {aborted, {badarg, Reason}}};
- {?MODULE, Node, {dirty_res, ok}} ->
- case Res of
- {'EXIT', {aborted, {node_not_running, _Node}}} ->
- ok;
- _ ->
- %% Prioritize bad results, but node_not_running
- Res
- end;
- {?MODULE, Node, {dirty_res, Reply}} ->
- Reply;
- {mnesia_down, Node} ->
- %% It's ok to ignore mnesia_down's
- %% since we will make the replicas
- %% consistent again when Node is started
- Res
- after 1000 ->
- case lists:member(Node, val({current, db_nodes})) of
- true ->
- get_dirty_reply(Node, Res);
- false ->
- Res
- end
- end.
-
-%% Assume that CommitRecord is no binary
-%% Return {Res, Pids}
-ask_commit(Protocol, Tid, CR, DiscNs, RamNs) ->
- ask_commit(Protocol, Tid, CR, DiscNs, RamNs, [], no_local).
-
-ask_commit(Protocol, Tid, [Head | Tail], DiscNs, RamNs, WaitFor, Local) ->
- Node = Head#commit.node,
- if
- Node == node() ->
- ask_commit(Protocol, Tid, Tail, DiscNs, RamNs, WaitFor, Head);
- true ->
- Bin = opt_term_to_binary(Protocol, Head, DiscNs++RamNs),
- Msg = {ask_commit, Protocol, Tid, Bin, DiscNs, RamNs},
- {?MODULE, Node} ! {self(), Msg},
- ask_commit(Protocol, Tid, Tail, DiscNs, RamNs, [Node | WaitFor], Local)
- end;
-ask_commit(_Protocol, _Tid, [], _DiscNs, _RamNs, WaitFor, Local) ->
- {WaitFor, Local}.
-
-opt_term_to_binary(asym_trans, Head, Nodes) ->
- opt_term_to_binary(Nodes, Head);
-opt_term_to_binary(_Protocol, Head, _Nodes) ->
- Head.
-
-opt_term_to_binary([], Head) ->
- term_to_binary(Head);
-opt_term_to_binary([H|R], Head) ->
- case mnesia_monitor:needs_protocol_conversion(H) of
- true -> Head;
- false ->
- opt_term_to_binary(R, Head)
- end.
-
-rec_all([Node | Tail], Tid, Res, Pids) ->
- receive
- {?MODULE, Node, {vote_yes, Tid}} ->
- rec_all(Tail, Tid, Res, Pids);
- {?MODULE, Node, {vote_yes, Tid, Pid}} ->
- rec_all(Tail, Tid, Res, [Pid | Pids]);
- {?MODULE, Node, {vote_no, Tid, Reason}} ->
- rec_all(Tail, Tid, {do_abort, Reason}, Pids);
- {?MODULE, Node, {committed, Tid}} ->
- rec_all(Tail, Tid, Res, Pids);
- {?MODULE, Node, {aborted, Tid}} ->
- rec_all(Tail, Tid, Res, Pids);
-
- {mnesia_down, Node} ->
- rec_all(Tail, Tid, {do_abort, {bad_commit, Node}}, Pids)
- end;
-rec_all([], _Tid, Res, Pids) ->
- {Res, Pids}.
-
-get_transactions() ->
- {info, Participant, Coordinator} = req(info),
- lists:map(fun({Tid, _Tabs}) ->
- Status = tr_status(Tid,Participant),
- {Tid#tid.counter, Tid#tid.pid, Status}
- end,Coordinator).
-
-tr_status(Tid,Participant) ->
- case lists:keymember(Tid, 1, Participant) of
- true -> participant;
- false -> coordinator
- end.
-
-get_info(Timeout) ->
- case whereis(?MODULE) of
- undefined ->
- {timeout, Timeout};
- Pid ->
- Pid ! {self(), info},
- receive
- {?MODULE, _, {info, Part, Coord}} ->
- {info, Part, Coord}
- after Timeout ->
- {timeout, Timeout}
- end
- end.
-
-display_info(Stream, {timeout, T}) ->
- io:format(Stream, "---> No info about coordinator and participant transactions, "
- "timeout ~p <--- ~n", [T]);
-
-display_info(Stream, {info, Part, Coord}) ->
- io:format(Stream, "---> Participant transactions <--- ~n", []),
- lists:foreach(fun(P) -> pr_participant(Stream, P) end, Part),
- io:format(Stream, "---> Coordinator transactions <---~n", []),
- lists:foreach(fun({Tid, _Tabs}) -> pr_tid(Stream, Tid) end, Coord).
-
-pr_participant(Stream, P) ->
- Commit0 = P#participant.commit,
- Commit =
- if
- binary(Commit0) -> binary_to_term(Commit0);
- true -> Commit0
- end,
- pr_tid(Stream, P#participant.tid),
- io:format(Stream, "with participant objects ~p~n", [Commit]).
-
-
-pr_tid(Stream, Tid) ->
- io:format(Stream, "Tid: ~p (owned by ~p) ~n",
- [Tid#tid.counter, Tid#tid.pid]).
-
-info(Serial) ->
- io:format( "Info about transaction with serial == ~p~n", [Serial]),
- {info, Participant, Trs} = req(info),
- search_pr_participant(Serial, Participant),
- search_pr_coordinator(Serial, Trs).
-
-
-search_pr_coordinator(_S, []) -> no;
-search_pr_coordinator(S, [{Tid, _Ts}|Tail]) ->
- case Tid#tid.counter of
- S ->
- io:format( "Tid is coordinator, owner == \n", []),
- display_pid_info(Tid#tid.pid),
- search_pr_coordinator(S, Tail);
- _ ->
- search_pr_coordinator(S, Tail)
- end.
-
-search_pr_participant(_S, []) ->
- false;
-search_pr_participant(S, [ P | Tail]) ->
- Tid = P#participant.tid,
- Commit0 = P#participant.commit,
- if
- Tid#tid.counter == S ->
- io:format( "Tid is participant to commit, owner == \n", []),
- Pid = Tid#tid.pid,
- display_pid_info(Pid),
- io:format( "Tid wants to write objects \n",[]),
- Commit =
- if
- binary(Commit0) -> binary_to_term(Commit0);
- true -> Commit0
- end,
-
- io:format("~p~n", [Commit]),
- search_pr_participant(S,Tail); %% !!!!!
- true ->
- search_pr_participant(S, Tail)
- end.
-
-display_pid_info(Pid) ->
- case rpc:pinfo(Pid) of
- undefined ->
- io:format( "Dead process \n");
- Info ->
- Call = fetch(initial_call, Info),
- Curr = case fetch(current_function, Info) of
- {Mod,F,Args} when list(Args) ->
- {Mod,F,length(Args)};
- Other ->
- Other
- end,
- Reds = fetch(reductions, Info),
- LM = length(fetch(messages, Info)),
- pformat(io_lib:format("~p", [Pid]),
- io_lib:format("~p", [Call]),
- io_lib:format("~p", [Curr]), Reds, LM)
- end.
-
-pformat(A1, A2, A3, A4, A5) ->
- io:format( "~-12s ~-21s ~-21s ~9w ~4w~n", [A1,A2,A3,A4,A5]).
-
-fetch(Key, Info) ->
- case lists:keysearch(Key, 1, Info) of
- {value, {_, Val}} ->
- Val;
- _ ->
- 0
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%
-%%%%%%%%%%%%%%%%%%%%% reconfigure stuff comes here ......
-%%%%%%%%%%%%%%%%%%%%%
-
-reconfigure_coordinators(N, [{Tid, [Store | _]} | Coordinators]) ->
- case mnesia_recover:outcome(Tid, unknown) of
- committed ->
- WaitingNodes = ?ets_lookup(Store, waiting_for_commit_ack),
- case lists:keymember(N, 2, WaitingNodes) of
- false ->
- ignore; % avoid spurious mnesia_down messages
- true ->
- send_mnesia_down(Tid, Store, N)
- end;
- aborted ->
- ignore; % avoid spurious mnesia_down messages
- _ ->
- %% Tell the coordinator about the mnesia_down
- send_mnesia_down(Tid, Store, N)
- end,
- reconfigure_coordinators(N, Coordinators);
-reconfigure_coordinators(_N, []) ->
- ok.
-
-send_mnesia_down(Tid, Store, Node) ->
- Msg = {mnesia_down, Node},
- send_to_pids([Tid#tid.pid | get_friends(Store)], Msg).
-
-send_to_pids([Pid | Pids], Msg) ->
- Pid ! Msg,
- send_to_pids(Pids, Msg);
-send_to_pids([], _Msg) ->
- ok.
-
-reconfigure_participants(N, [P | Tail]) ->
- case lists:member(N, P#participant.disc_nodes) or
- lists:member(N, P#participant.ram_nodes) of
- false ->
- %% Ignore, since we are not a participant
- %% in the transaction.
- reconfigure_participants(N, Tail);
-
- true ->
- %% We are on a participant node, lets
- %% check if the dead one was a
- %% participant or a coordinator.
- Tid = P#participant.tid,
- if
- node(Tid#tid.pid) /= N ->
- %% Another participant node died. Ignore.
- reconfigure_participants(N, Tail);
-
- true ->
- %% The coordinator node has died and
- %% we must determine the outcome of the
- %% transaction and tell mnesia_tm on all
- %% nodes (including the local node) about it
- verbose("Coordinator ~p in transaction ~p died~n",
- [Tid#tid.pid, Tid]),
-
- Nodes = P#participant.disc_nodes ++
- P#participant.ram_nodes,
- AliveNodes = Nodes -- [N],
- Protocol = P#participant.protocol,
- tell_outcome(Tid, Protocol, N, AliveNodes, AliveNodes),
- reconfigure_participants(N, Tail)
- end
- end;
-reconfigure_participants(_, []) ->
- [].
-
-%% We need to determine the outcome of the transaction and
-%% tell mnesia_tm on all involved nodes (including the local node)
-%% about the outcome.
-tell_outcome(Tid, Protocol, Node, CheckNodes, TellNodes) ->
- Outcome = mnesia_recover:what_happened(Tid, Protocol, CheckNodes),
- case Outcome of
- aborted ->
- rpc:abcast(TellNodes, ?MODULE, {Tid,{do_abort, {mnesia_down, Node}}});
- committed ->
- rpc:abcast(TellNodes, ?MODULE, {Tid, do_commit})
- end,
- Outcome.
-
-do_stop(#state{coordinators = Coordinators}) ->
- Msg = {mnesia_down, node()},
- lists:foreach(fun({Tid, _}) -> Tid#tid.pid ! Msg end, Coordinators),
- mnesia_checkpoint:stop(),
- mnesia_log:stop(),
- exit(shutdown).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% System upgrade
-
-system_continue(_Parent, _Debug, State) ->
- doit_loop(State).
-
-system_terminate(_Reason, _Parent, _Debug, State) ->
- do_stop(State).
-
-system_code_change(State, _Module, _OldVsn, _Extra) ->
- {ok, State}.
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/dialyzer_options b/lib/dialyzer/test/race_SUITE_data/dialyzer_options
index 44e1720715..44e1720715 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/dialyzer_options
+++ b/lib/dialyzer/test/race_SUITE_data/dialyzer_options
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args1 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args1
index 3bbe99d4af..3bbe99d4af 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args1
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args1
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args2 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args2
index 34176c66ac..34176c66ac 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args2
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args2
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args3 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args3
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args3
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args3
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args4 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args4
index 8c45de08c2..8c45de08c2 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args4
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args4
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args5 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args5
index a4a0c021c2..a4a0c021c2 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args5
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args5
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args6 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args6
index 10fa4c27e3..10fa4c27e3 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args6
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args6
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args7 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args7
index af43145c17..af43145c17 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args7
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args7
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args8 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args8
index 5a2b41ed8c..5a2b41ed8c 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_args8
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args8
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_control_flow1 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow1
index d7df214939..d7df214939 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_control_flow1
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow1
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_control_flow2 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow2
index cdaeafb0ed..cdaeafb0ed 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_control_flow2
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow2
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_control_flow3 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow3
index d640f564cd..d640f564cd 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_control_flow3
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow3
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_control_flow4 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow4
index 6f34e75902..6f34e75902 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_control_flow4
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow4
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_control_flow5 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow5
index 5af592f43f..5af592f43f 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_control_flow5
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow5
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_diff_atoms_race1 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race1
index 98ccf34e7d..98ccf34e7d 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_diff_atoms_race1
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race1
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_diff_atoms_race2 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race2
index b6af99b4cc..b6af99b4cc 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_diff_atoms_race2
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race2
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_diff_atoms_race3 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race3
index d79182c289..d79182c289 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_diff_atoms_race3
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race3
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_diff_atoms_race4 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race4
index 5bb1b9f781..5bb1b9f781 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_diff_atoms_race4
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race4
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_diff_atoms_race5 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race5
index 7db320e758..7db320e758 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_diff_atoms_race5
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race5
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_diff_atoms_race6 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race6
index c029f79ed5..c029f79ed5 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_diff_atoms_race6
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race6
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_double1 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_double1
index b640b91271..b640b91271 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_double1
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_double1
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_double2 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_double2
index cf61cb5ec3..cf61cb5ec3 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_double2
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_double2
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_funs1 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_funs1
index 540a0cf388..540a0cf388 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_funs1
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_funs1
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_funs2 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_funs2
index 6b618f72b6..6b618f72b6 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_funs2
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_funs2
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_new b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_new
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_new
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_new
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_param b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_param
index 58f934a190..58f934a190 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/ets_insert_param
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_param
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_public b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_public
new file mode 100644
index 0000000000..d091ce3b50
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_public
@@ -0,0 +1,2 @@
+
+ets_insert_public.erl:14: The call ets:insert(Foo::atom(),{'counter',number()}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Foo::atom(),'counter') call in ets_insert_public.erl on line 12
diff --git a/lib/dialyzer/test/race_SUITE_data/results/extract_translations b/lib/dialyzer/test/race_SUITE_data/results/extract_translations
new file mode 100644
index 0000000000..62aa1aa511
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/results/extract_translations
@@ -0,0 +1,5 @@
+
+extract_translations.erl:140: The call ets:insert('files',{atom() | binary() | [atom() | [any()] | char()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('files',File::atom() | binary() | [atom() | [any()] | char()]) call in extract_translations.erl on line 135
+extract_translations.erl:146: The call ets:insert('translations',{_,[]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('translations',Str::any()) call in extract_translations.erl on line 126
+extract_translations.erl:152: The call ets:insert('files',{atom() | binary() | [atom() | [any()] | char()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('files',File::atom() | binary() | [atom() | [any()] | char()]) call in extract_translations.erl on line 148
+extract_translations.erl:154: The call ets:insert('translations',{_,[]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('translations',Str::any()) call in extract_translations.erl on line 126
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_diff_atoms_race1 b/lib/dialyzer/test/race_SUITE_data/results/mnesia_diff_atoms_race1
index f5e544dc2a..f5e544dc2a 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_diff_atoms_race1
+++ b/lib/dialyzer/test/race_SUITE_data/results/mnesia_diff_atoms_race1
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_diff_atoms_race2 b/lib/dialyzer/test/race_SUITE_data/results/mnesia_diff_atoms_race2
index 0ad0bc0afd..0ad0bc0afd 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_diff_atoms_race2
+++ b/lib/dialyzer/test/race_SUITE_data/results/mnesia_diff_atoms_race2
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_one_write_two b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_one_write_two
index a4f3c269f1..a4f3c269f1 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_one_write_two
+++ b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_one_write_two
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_two_write_one b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_two_write_one
index 6e666d755f..6e666d755f 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_two_write_one
+++ b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_two_write_one
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_write_double1 b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double1
index e953c6948b..e953c6948b 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_write_double1
+++ b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double1
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_write_double2 b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double2
index 2a0b4eddd0..2a0b4eddd0 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_write_double2
+++ b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double2
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_write_double3 b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double3
index fe51a5e838..fe51a5e838 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_write_double3
+++ b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double3
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_write_double4 b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double4
index d6a60d847a..d6a60d847a 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_write_double4
+++ b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double4
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_write_one b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_one
index b47f66eb79..b47f66eb79 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_write_one
+++ b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_one
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_write_two b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_two
index 2faf55fe72..2faf55fe72 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/mnesia_dirty_read_write_two
+++ b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_two
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_control_flow1 b/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow1
index 0fcf13c50a..0fcf13c50a 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_control_flow1
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow1
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_control_flow2 b/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow2
index d0c048701d..d0c048701d 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_control_flow2
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow2
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_control_flow3 b/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow3
index 0d93428758..0d93428758 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_control_flow3
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow3
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_control_flow4 b/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow4
index f0ce12d0a4..f0ce12d0a4 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_control_flow4
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow4
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_control_flow5 b/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow5
index fd809139e4..fd809139e4 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_control_flow5
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow5
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_control_flow6 b/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow6
index ba89cc5624..ba89cc5624 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_control_flow6
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow6
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_atoms_no_race b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_atoms_no_race
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_atoms_no_race
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_atoms_no_race
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_atoms_race b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_atoms_race
index 76c746e2f4..76c746e2f4 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_atoms_race
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_atoms_race
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions1 b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1
index 14c157885f..14c157885f 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions1
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions1_nested b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_nested
index c791d4b347..c791d4b347 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions1_nested
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_nested
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions1_pathsens b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_pathsens
index d22e696196..d22e696196 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions1_pathsens
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_pathsens
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions1_twice b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_twice
index 3024c77d91..3024c77d91 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions1_twice
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_twice
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions2 b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2
index 9a22eb7e17..9a22eb7e17 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions2
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions2_nested b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_nested
index 0e757fbccc..0e757fbccc 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions2_nested
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_nested
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions2_pathsens b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_pathsens
index c102b39243..c102b39243 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions2_pathsens
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_pathsens
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions2_twice b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_twice
index b048bc6bed..b048bc6bed 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions2_twice
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_twice
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions3 b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3
index 6d5154b411..6d5154b411 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions3
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions3_nested b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3_nested
index 298c4c7178..298c4c7178 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions3_nested
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3_nested
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions3_pathsens b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3_pathsens
index 5d1ea5bda5..5d1ea5bda5 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions3_pathsens
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3_pathsens
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions4 b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions4
index cb51301f1e..cb51301f1e 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions4
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions4
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions5 b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions5
index 34c477e05a..34c477e05a 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions5
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions5
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions6 b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions6
index 8840ef4ca7..8840ef4ca7 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_functions6
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions6
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules1 b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1
index 8f7d0b7a17..8f7d0b7a17 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules1
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules1_pathsens b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1_pathsens
index 40d36eb7d2..40d36eb7d2 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules1_pathsens
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1_pathsens
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules1_rec b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1_rec
index 278b679aba..278b679aba 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules1_rec
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1_rec
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules2 b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2
index a4e5a000e2..a4e5a000e2 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules2
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules2_pathsens b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2_pathsens
index cc93133019..cc93133019 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules2_pathsens
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2_pathsens
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules2_rec b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2_rec
index 8874ab3553..8874ab3553 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules2_rec
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2_rec
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules3 b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules3
index 8e839a53dc..8e839a53dc 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules3
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules3
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules_nested b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules_nested
index 9192dc0708..9192dc0708 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules_nested
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules_nested
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules_twice b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules_twice
index 3758347255..3758347255 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_modules_twice
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules_twice
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_vars_no_race b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_vars_no_race
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_vars_no_race
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_vars_no_race
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_vars_race b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_vars_race
index e34b4d2138..e34b4d2138 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_diff_vars_race
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_vars_race
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module1 b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module1
index 3ed6f50d8d..3ed6f50d8d 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module1
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module1
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module2 b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module2
index 737054fe67..737054fe67 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module2
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module2
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module3 b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module3
index 4111498efe..4111498efe 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module3
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module3
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module4 b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module4
index 4e70a8efa1..4e70a8efa1 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module4
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module4
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module5 b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module5
index f6a10f52fd..f6a10f52fd 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module5
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module5
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module6 b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module6
index a8623ee985..a8623ee985 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module6
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module6
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module7 b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module7
index e39d630c75..e39d630c75 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module7
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module7
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module8 b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module8
index 58ae498bd4..58ae498bd4 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_intra_inter_module8
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module8
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_param b/lib/dialyzer/test/race_SUITE_data/results/whereis_param
index fb7563b1c7..fb7563b1c7 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_param
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_param
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_param_inter_module b/lib/dialyzer/test/race_SUITE_data/results/whereis_param_inter_module
index fc3e9ca59d..fc3e9ca59d 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_param_inter_module
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_param_inter_module
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function1 b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function1
index 2cf1960d65..2cf1960d65 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function1
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function1
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function2 b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function2
index 4b55bc61ad..4b55bc61ad 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function2
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function2
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function3 b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function3
index 638e9b0f4b..638e9b0f4b 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function3
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function3
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function4 b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function4
index f255cb8170..f255cb8170 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function4
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function4
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function5 b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function5
index 78d81b9a57..78d81b9a57 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function5
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function5
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function6 b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function6
index 6df6de1922..6df6de1922 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function6
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function6
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function7 b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function7
index f3ddb0b537..f3ddb0b537 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function7
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function7
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function8 b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function8
index 9d731ada29..9d731ada29 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_rec_function8
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function8
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_try_catch b/lib/dialyzer/test/race_SUITE_data/results/whereis_try_catch
index fecb0756bd..fecb0756bd 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_try_catch
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_try_catch
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars1 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars1
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars1
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars1
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars10 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars10
index 36a59096e0..36a59096e0 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars10
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars10
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars11 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars11
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars11
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars11
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars12 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars12
index d34e1b1c7e..d34e1b1c7e 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars12
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars12
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars13 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars13
index e6ae40cee0..e6ae40cee0 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars13
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars13
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars14 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars14
index cdd23a7471..cdd23a7471 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars14
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars14
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars15 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars15
index 7f79852978..7f79852978 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars15
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars15
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars16 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars16
index 0f28dff25d..0f28dff25d 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars16
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars16
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars17 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars17
index 3681c1aa9f..3681c1aa9f 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars17
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars17
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars18 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars18
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars18
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars18
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars19 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars19
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars19
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars19
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars2 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars2
index 1636a6e908..1636a6e908 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars2
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars2
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars20 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars20
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars20
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars20
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars21 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars21
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars21
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars21
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars22 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars22
index 0f258cc097..0f258cc097 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars22
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars22
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars3 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars3
index 4f43b9adca..4f43b9adca 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars3
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars3
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars4 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars4
index 9eb833c42a..9eb833c42a 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars4
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars4
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars5 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars5
index b1c269c020..b1c269c020 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars5
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars5
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars6 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars6
index 88c58cfdf2..88c58cfdf2 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars6
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars6
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars7 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars7
index 8924869634..8924869634 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars7
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars7
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars8 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars8
index d9d8f3872f..d9d8f3872f 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars8
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars8
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars9 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars9
index da52ca1f82..da52ca1f82 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/whereis_vars9
+++ b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars9
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args1.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args1.erl
new file mode 100644
index 0000000000..0039195e0a
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args1.erl
@@ -0,0 +1,17 @@
+%% This tests the presence of possible races due to an ets:lookup/ets:insert
+%% combination. It takes into account the argument types of the calls.
+
+-module(ets_insert_args1).
+-export([start/0]).
+
+start() ->
+ F = fun(T) -> [{_, N}] = ets:lookup(T, counter),
+ ets:insert(T, [{counter, N+1}])
+ end,
+ io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
+ ets:insert(foo, {counter, 0}),
+ io:format("Inserted ~w\n", [{counter, 0}]),
+ F(foo),
+ io:format("Update complete\n", []),
+ ObjectList = ets:lookup(foo, counter),
+ io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args2.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args2.erl
new file mode 100644
index 0000000000..c1857eb58b
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args2.erl
@@ -0,0 +1,17 @@
+%% This tests the presence of possible races due to an ets:lookup/ets:insert
+%% combination. It takes into account the argument types of the calls.
+
+-module(ets_insert_args2).
+-export([start/0]).
+
+start() ->
+ F = fun(T)-> [{_, N}] = ets:lookup(T, counter),
+ ets:insert(T, [{counter, N+1}, {maria, N+1}, {kostis, N+1}])
+ end,
+ io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
+ ets:insert(foo, {counter, 0}),
+ io:format("Inserted ~w\n", [{counter, 0}]),
+ F(foo),
+ io:format("Update complete\n", []),
+ ObjectList = ets:lookup(foo, counter),
+ io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args3.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args3.erl
new file mode 100644
index 0000000000..74401b76fd
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args3.erl
@@ -0,0 +1,17 @@
+%% This tests the presence of possible races due to an ets:lookup/ets:insert
+%% combination. It takes into account the argument types of the calls.
+
+-module(ets_insert_args3).
+-export([start/0]).
+
+start() ->
+ F = fun(T)-> [{_, N}] = ets:lookup(T, counter),
+ ets:insert(T, [{maria, N+1}, {kostis, N+1}])
+ end,
+ io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
+ ets:insert(foo, {counter, 0}),
+ io:format("Inserted ~w\n", [{counter, 0}]),
+ F(foo),
+ io:format("Update complete\n", []),
+ ObjectList = ets:lookup(foo, counter),
+ io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args4.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args4.erl
new file mode 100644
index 0000000000..2c892074ec
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args4.erl
@@ -0,0 +1,17 @@
+%% This tests the presence of possible races due to an ets:lookup/ets:insert
+%% combination. It takes into account the argument types of the calls.
+
+-module(ets_insert_args4).
+-export([start/0]).
+
+start() ->
+ F = fun(T)-> [{_, N}] = ets:lookup(T, counter),
+ ets:insert(T, {counter, N+1})
+ end,
+ io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
+ ets:insert(foo, {counter, 0}),
+ io:format("Inserted ~w\n", [{counter, 0}]),
+ F(foo),
+ io:format("Update complete\n", []),
+ ObjectList = ets:lookup(foo, counter),
+ io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args5.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args5.erl
new file mode 100644
index 0000000000..156f555a7c
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args5.erl
@@ -0,0 +1,17 @@
+%% This tests the presence of possible races due to an ets:lookup/ets:insert
+%% combination. It takes into account the argument types of the calls.
+
+-module(ets_insert_args5).
+-export([start/0]).
+
+start() ->
+ F = fun(T)-> [{_, N}] = ets:lookup(T, counter),
+ ets:insert(T, {counter, N+1, N+2})
+ end,
+ io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
+ ets:insert(foo, {counter, 0, 0}),
+ io:format("Inserted ~w\n", [{counter, 0, 0}]),
+ F(foo),
+ io:format("Update complete\n", []),
+ ObjectList = ets:lookup(foo, counter),
+ io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args6.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args6.erl
new file mode 100644
index 0000000000..1e5887f76d
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args6.erl
@@ -0,0 +1,17 @@
+%% This tests the presence of possible races due to an ets:lookup/ets:insert
+%% combination. It takes into account the argument types of the calls.
+
+-module(ets_insert_args6).
+-export([start/0]).
+
+start() ->
+ F = fun(T)-> [{_, N}] = ets:lookup(T, counter),
+ ets:insert(T, [{counter, N+1, N+2}])
+ end,
+ io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
+ ets:insert(foo, {counter, 0, 0}),
+ io:format("Inserted ~w\n", [{counter, 0, 0}]),
+ F(foo),
+ io:format("Update complete\n", []),
+ ObjectList = ets:lookup(foo, counter),
+ io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args7.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args7.erl
new file mode 100644
index 0000000000..912bbf7073
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args7.erl
@@ -0,0 +1,17 @@
+%% This tests the presence of possible races due to an ets:lookup/ets:insert
+%% combination. It takes into account the argument types of the calls.
+
+-module(ets_insert_args7).
+-export([test/0]).
+
+test() ->
+ Foo = foo,
+ ets:new(Foo, [named_table, public]),
+ race(Foo).
+
+race(Tab) ->
+ [{_, N}] = ets:lookup(Tab, counter),
+ aux(Tab, N).
+
+aux(Table, N) ->
+ ets:insert(Table, [{counter, N+1}]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args8.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args8.erl
new file mode 100644
index 0000000000..275cf0291c
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args8.erl
@@ -0,0 +1,16 @@
+%% This tests the presence of possible races due to an ets:lookup/ets:insert
+%% combination. It takes into account the argument types of the calls.
+
+-module(ets_insert_args8).
+-export([test/1]).
+
+test(Foo) ->
+ ets:new(Foo, [named_table, public]),
+ race(Foo).
+
+race(Tab) ->
+ [{_, N}] = ets:lookup(Tab, counter),
+ aux(Tab, N).
+
+aux(Table, N) ->
+ ets:insert(Table, [{counter, N+1}]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow1.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow1.erl
new file mode 100644
index 0000000000..cfe0b2b727
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow1.erl
@@ -0,0 +1,20 @@
+%% This tests the presence of possible races due to an ets:lookup/ets:insert
+%% combination. It takes into account control flow that might exist.
+
+-module(ets_insert_control_flow1).
+-export([start/0]).
+
+start() ->
+ io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
+ ets:insert(foo, {random, random:uniform(maria:get_int())}),
+ io:format("Inserted ~w\n", [{_, N}] = ets:lookup(foo, random)),
+ case (N rem 2 == 0) of
+ true ->
+ io:format("\nInserted an even number\n", []),
+ io:format("\nWill make it odd\n", []),
+ ets:insert(foo, {random, N+1});
+ false -> ok
+ end,
+ io:format("Update complete\n", []),
+ ObjectList = ets:lookup(foo, random),
+ io:format("Random odd integer: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow2.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow2.erl
new file mode 100644
index 0000000000..d160418bdb
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow2.erl
@@ -0,0 +1,26 @@
+%% This tests the presence of possible races due to an ets:lookup/ets:insert
+%% combination. It takes into account control flow that might exist.
+
+-module(ets_insert_control_flow2).
+-export([start/0]).
+
+start() ->
+ io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
+ ets:insert(foo, {random, random:uniform(150)}),
+ io:format("Inserted ~w\n", [{_, N}] = ets:lookup(foo, random)),
+ case (N rem 2 == 0) of
+ true ->
+ io:format("\nInserted an even integer\n", []),
+ io:format("\nWill make it odd and generate password\n", []),
+ ets:insert(foo, [{random, N+1}, {pass, generate_password(N)}]);
+ false ->
+ io:format("\nInserted an odd integer\n", []),
+ io:format("\nWill make it even and generate password\n", []),
+ ets:insert(foo, [{random, N+1}, {pass, generate_password(N)}])
+ end,
+ io:format("Update complete\n", []),
+ ObjectList = ets:lookup(foo, pass),
+ io:format("New password: ~w\n", [ObjectList]).
+
+generate_password(N) ->
+ lists:map(fun (_) -> random:uniform(90)+$\s+1 end, lists:seq(1,N)).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_control_flow3.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow3.erl
index 9c6a22eb05..9c6a22eb05 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_control_flow3.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow3.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_control_flow4.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow4.erl
index caa3804614..caa3804614 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_control_flow4.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow4.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_control_flow5.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow5.erl
index b19fd776ec..b19fd776ec 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_control_flow5.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow5.erl
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race1.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race1.erl
new file mode 100644
index 0000000000..7b2dbb8eff
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race1.erl
@@ -0,0 +1,22 @@
+%% This tests that the race condition detection between ets:lookup/
+%% ets:insert is robust even when the functions are called with
+%% different atoms as arguments.
+
+-module(ets_insert_diff_atoms_race1).
+-export([test/0]).
+
+test() ->
+ ets:new(foo, [named_table, public]),
+ {race(foo), no_race(foo)}.
+
+race(Tab) ->
+ [{_, N}] = ets:lookup(Tab, counter),
+ aux(Tab, N).
+
+no_race(Tab) ->
+ [{_, N}] = ets:lookup(Tab, counter),
+ AnotherTab = bar,
+ aux(AnotherTab, N).
+
+aux(Table, N) ->
+ ets:insert(Table, [{counter, N+1}]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race2.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race2.erl
new file mode 100644
index 0000000000..d7afc79d07
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race2.erl
@@ -0,0 +1,22 @@
+%% This tests that the race condition detection between ets:lookup/
+%% ets:insert is robust even when the functions are called with
+%% different atoms as arguments.
+
+-module(ets_insert_diff_atoms_race2).
+-export([test/0]).
+
+test() ->
+ ets:new(foo, [named_table, public]),
+ {race(foo, counter), no_race(foo, counter)}.
+
+race(Tab, Counter) ->
+ [{_, N}] = ets:lookup(Tab, Counter),
+ aux(Tab, Counter, N).
+
+no_race(Tab, Counter) ->
+ [{_, N}] = ets:lookup(Tab, Counter),
+ AnotherTab = bar,
+ aux(AnotherTab, Counter, N).
+
+aux(Table, Counter, N) ->
+ ets:insert(Table, [{Counter, N+1}]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race3.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race3.erl
new file mode 100644
index 0000000000..e05e9be54b
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race3.erl
@@ -0,0 +1,22 @@
+%% This tests that the race condition detection between ets:lookup/
+%% ets:insert is robust even when the functions are called with
+%% different atoms as arguments.
+
+-module(ets_insert_diff_atoms_race3).
+-export([test/0]).
+
+test() ->
+ ets:new(foo, [named_table, public]),
+ {race(foo), no_race(foo)}.
+
+race(Tab) ->
+ [{_, N}] = ets:lookup(Tab, counter),
+ aux(Tab, N).
+
+no_race(Tab) ->
+ [{_, N}] = ets:lookup(Tab, counter),
+ AnotherTab = bar,
+ aux(AnotherTab, N).
+
+aux(Table, N) ->
+ ets:insert(Table, {counter, N+1}).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race4.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race4.erl
new file mode 100644
index 0000000000..e2a3588f41
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race4.erl
@@ -0,0 +1,22 @@
+%% This tests that the race condition detection between ets:lookup/
+%% ets:insert is robust even when the functions are called with
+%% different atoms as arguments.
+
+-module(ets_insert_diff_atoms_race4).
+-export([test/0]).
+
+test() ->
+ ets:new(foo, [named_table, public]),
+ {race(foo, counter), no_race(foo, counter)}.
+
+race(Tab, Counter) ->
+ [{_, N}] = ets:lookup(Tab, Counter),
+ aux(Tab, Counter, N).
+
+no_race(Tab, Counter) ->
+ [{_, N}] = ets:lookup(Tab, Counter),
+ AnotherTab = bar,
+ aux(AnotherTab, Counter, N).
+
+aux(Table, Counter, N) ->
+ ets:insert(Table, {Counter, N+1}).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race5.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race5.erl
new file mode 100644
index 0000000000..dd53387c11
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race5.erl
@@ -0,0 +1,22 @@
+%% This tests that the race condition detection between ets:lookup/
+%% ets:insert is robust even when the functions are called with
+%% different atoms as arguments.
+
+-module(ets_insert_diff_atoms_race5).
+-export([test/0]).
+
+test() ->
+ ets:new(foo, [named_table, public]),
+ {race(foo, counter), no_race(foo, counter)}.
+
+race(Tab, Counter) ->
+ [{_, N}] = ets:lookup(Tab, Counter),
+ aux(Tab, Counter, N).
+
+no_race(Tab, Counter) ->
+ [{_, N}] = ets:lookup(Tab, Counter),
+ AnotherCounter = index,
+ aux(Tab, AnotherCounter, N).
+
+aux(Table, Counter, N) ->
+ ets:insert(Table, [{Counter, N+1}]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race6.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race6.erl
new file mode 100644
index 0000000000..ec0a0eaadf
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race6.erl
@@ -0,0 +1,22 @@
+%% This tests that the race condition detection between ets:lookup/
+%% ets:insert is robust even when the functions are called with
+%% different atoms as arguments.
+
+-module(ets_insert_diff_atoms_race6).
+-export([test/0]).
+
+test() ->
+ ets:new(foo, [named_table, public]),
+ {race(foo, counter), no_race(foo, counter)}.
+
+race(Tab, Counter) ->
+ [{_, N}] = ets:lookup(Tab, Counter),
+ aux(Tab, Counter, N).
+
+no_race(Tab, Counter) ->
+ [{_, N}] = ets:lookup(Tab, Counter),
+ AnotherCounter = index,
+ aux(Tab, AnotherCounter, N).
+
+aux(Table, Counter, N) ->
+ ets:insert(Table, {Counter, N+1}).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_double1.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_double1.erl
new file mode 100644
index 0000000000..d5b6689eb1
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_double1.erl
@@ -0,0 +1,28 @@
+%% This tests the presence of possible races due to an ets:lookup/ets:insert
+%% combination. It takes into account multiple ets:inserts that might exist.
+
+-module(ets_insert_double1).
+-export([start/0]).
+
+start() ->
+ io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
+ ets:insert(foo, {random, random:uniform(150)}),
+ io:format("Inserted ~w\n", [{_, N}] = ets:lookup(foo, random)),
+ case (N rem 2 == 0) of
+ true ->
+ io:format("\nInserted an even integer\n", []),
+ io:format("\nWill make it odd and generate new password\n", []),
+ ets:insert(foo, [{random, N+1}, {pass, generate_password(N)}]);
+ false ->
+ io:format("\nInserted an odd integer\n", []),
+ io:format("\nWill make it even and generate new password\n", []),
+ ets:insert(foo, [{random, N+1}, {pass, generate_password(N)}])
+ end,
+ io:format("Update complete\n", []),
+ ObjectList = ets:lookup(foo, pass),
+ io:format("New password: ~w\n", [ObjectList]),
+ ets:insert(foo, {pass, 'empty'}).
+
+generate_password(N) ->
+ [{_, P}] = ets:lookup(foo, pass),
+ lists:map(fun (_) -> random:uniform(90)+P+$\s+1 end, lists:seq(1,N)).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_double2.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_double2.erl
new file mode 100644
index 0000000000..fa653e3090
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_double2.erl
@@ -0,0 +1,28 @@
+%% This tests the presence of possible races due to an ets:lookup/ets:insert
+%% combination. It takes into account multiple ets:inserts that might exist.
+
+-module(ets_insert_double2).
+-export([start/2]).
+
+start(Random, Pass) ->
+ io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
+ ets:insert(foo, {Random, random:uniform(150)}),
+ io:format("Inserted ~w\n", [{_, N}] = ets:lookup(foo, Random)),
+ case (N rem 2 == 0) of
+ true ->
+ io:format("\nInserted an even integer\n", []),
+ io:format("\nWill make it odd and generate new password\n", []),
+ ets:insert(foo, [{Random, N+1}, {Pass, generate_password(Pass, N)}]);
+ false ->
+ io:format("\nInserted an odd integer\n", []),
+ io:format("\nWill make it even and generate new password\n", []),
+ ets:insert(foo, [{Random, N+1}, {Pass, generate_password(Pass, N)}])
+ end,
+ io:format("Update complete\n", []),
+ ObjectList = ets:lookup(foo, Pass),
+ io:format("New password: ~w\n", [ObjectList]),
+ ets:insert(foo, {Pass, 'empty'}).
+
+generate_password(Pass, N) ->
+ [{_, P}] = ets:lookup(foo, Pass),
+ lists:map(fun (_) -> random:uniform(90)+P+$\s+1 end, lists:seq(1,N)).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_funs1.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_funs1.erl
new file mode 100644
index 0000000000..b6b258fd21
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_funs1.erl
@@ -0,0 +1,18 @@
+%% This tests the presence of possible races due to an ets:lookup/ets:insert
+%% combination. It takes into account the anonymous functions.
+
+-module(ets_insert_funs1).
+-export([start/0]).
+
+start() ->
+ F = fun(T) ->
+ ets:lookup(T, counter)
+ end,
+ io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
+ ets:insert(foo, {counter, 0}),
+ io:format("Inserted ~w\n", [{counter, 0}]),
+ [{_, N}] = F(foo),
+ ets:insert(foo, [{counter, N+1}]),
+ io:format("Update complete\n", []),
+ ObjectList = ets:lookup(foo, counter),
+ io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_funs2.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_funs2.erl
new file mode 100644
index 0000000000..6b9518f314
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_funs2.erl
@@ -0,0 +1,18 @@
+%% This tests the presence of possible races due to an ets:lookup/ets:insert
+%% combination. It takes into account the anonymous functions.
+
+-module(ets_insert_funs2).
+-export([start/0]).
+
+start() ->
+ F = fun(T, N) ->
+ ets:insert(T, [{counter, N+1}])
+ end,
+ io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
+ ets:insert(foo, {counter, 0}),
+ io:format("Inserted ~w\n", [{counter, 0}]),
+ [{_, N}] = ets:lookup(foo, counter),
+ F(foo, N),
+ io:format("Update complete\n", []),
+ ObjectList = ets:lookup(foo, counter),
+ io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_new.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_new.erl
index 63f3272912..63f3272912 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_new.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_new.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_param.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_param.erl
index a479a31792..a479a31792 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_param.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_param.erl
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_public.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_public.erl
new file mode 100644
index 0000000000..4caa9fe8a0
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_public.erl
@@ -0,0 +1,23 @@
+%% This tests the presence of possible races due to an ets:lookup/ets:insert
+%% combination. It takes into account any public ETS tables that might exist.
+
+-module(ets_insert_public).
+
+-export([main/1]).
+
+%% Main
+main(Foo) ->
+ make_table(Foo),
+ ets:insert(Foo, {counter, 0}),
+ [{_, N}] = ets:lookup(Foo, counter),
+ NewN = N + 1,
+ ets:insert(Foo, {counter, NewN}),
+ NewN.
+
+make_table(Foo) ->
+ init(Foo).
+
+init(Foo) ->
+ ets:new(Foo, [named_table, public]),
+ ets:insert(Foo, {counter, 0}),
+ {ok, feeling_good}.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/extract_translations.erl b/lib/dialyzer/test/race_SUITE_data/src/extract_translations.erl
new file mode 100644
index 0000000000..76ffca4676
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/extract_translations.erl
@@ -0,0 +1,293 @@
+%%%----------------------------------------------------------------------
+%%% File : extract_translations.erl
+%%% Author : Sergei Golovan <[email protected]>
+%%% Purpose : Auxiliary tool for interface/messages translators
+%%% Created : 23 Apr 2005 by Sergei Golovan <[email protected]>
+%%% Id : $Id: extract_translations.erl,v 1.1 2009/08/17 09:18:59 maria Exp $
+%%%----------------------------------------------------------------------
+
+-module(extract_translations).
+-author('[email protected]').
+
+-export([start/0]).
+
+-define(STATUS_SUCCESS, 0).
+-define(STATUS_ERROR, 1).
+-define(STATUS_USAGE, 2).
+
+-include_lib("kernel/include/file.hrl").
+
+
+start() ->
+ ets:new(translations, [named_table, public]),
+ ets:new(translations_obsolete, [named_table, public]),
+ ets:new(files, [named_table, public]),
+ ets:new(vars, [named_table, public]),
+ case init:get_plain_arguments() of
+ ["-srcmsg2po", Dir, File] ->
+ print_po_header(File),
+ Status = process(Dir, File, srcmsg2po),
+ halt(Status);
+ ["-unused", Dir, File] ->
+ Status = process(Dir, File, unused),
+ halt(Status);
+ [Dir, File] ->
+ Status = process(Dir, File, used),
+ halt(Status);
+ _ ->
+ print_usage(),
+ halt(?STATUS_USAGE)
+ end.
+
+
+process(Dir, File, Used) ->
+ case load_file(File) of
+ {error, Reason} ->
+ io:format("~s: ~s~n", [File, file:format_error(Reason)]),
+ ?STATUS_ERROR;
+ _ ->
+ FileList = find_src_files(Dir),
+ lists:foreach(
+ fun(F) ->
+ parse_file(Dir, F, Used)
+ end, FileList),
+ case Used of
+ unused ->
+ ets:foldl(fun({Key, _}, _) ->
+ io:format("~p~n", [Key])
+ end, ok, translations);
+ srcmsg2po ->
+ ets:foldl(fun({Key, Trans}, _) ->
+ print_translation_obsolete(Key, Trans)
+ end, ok, translations_obsolete);
+ _ ->
+ ok
+ end,
+ ?STATUS_SUCCESS
+ end.
+
+parse_file(Dir, File, Used) ->
+ ets:delete_all_objects(vars),
+ case epp:parse_file(File, [Dir, filename:dirname(File) | code:get_path()], []) of
+ {ok, Forms} ->
+ lists:foreach(
+ fun(F) ->
+ parse_form(Dir, File, F, Used)
+ end, Forms);
+ _ ->
+ ok
+ end.
+
+parse_form(Dir, File, Form, Used) ->
+ case Form of
+ %%{undefined, Something} ->
+ %% io:format("Undefined: ~p~n", [Something]);
+ {call,
+ _,
+ {remote, _, {atom, _, translate}, {atom, _, translate}},
+ [_, {string, Line, Str}]
+ } ->
+ process_string(Dir, File, Line, Str, Used);
+ {call,
+ _,
+ {remote, _, {atom, _, translate}, {atom, _, translate}},
+ [_, {var, _, Name}]
+ } ->
+ case ets:lookup(vars, Name) of
+ [{_Name, Value, Line}] ->
+ process_string(Dir, File, Line, Value, Used);
+ _ ->
+ ok
+ end;
+ {match,
+ _,
+ {var, _, Name},
+ {string, Line, Value}
+ } ->
+ ets:insert(vars, {Name, Value, Line});
+ L when is_list(L) ->
+ lists:foreach(
+ fun(F) ->
+ parse_form(Dir, File, F, Used)
+ end, L);
+ T when is_tuple(T) ->
+ lists:foreach(
+ fun(F) ->
+ parse_form(Dir, File, F, Used)
+ end, tuple_to_list(T));
+ _ ->
+ ok
+ end.
+
+process_string(_Dir, _File, _Line, "", _Used) ->
+ ok;
+
+process_string(_Dir, File, Line, Str, Used) ->
+ case {ets:lookup(translations, Str), Used} of
+ {[{_Key, _Trans}], unused} ->
+ ets:delete(translations, Str);
+ {[{_Key, _Trans}], used} ->
+ ok;
+ {[{_Key, Trans}], srcmsg2po} ->
+ ets:delete(translations_obsolete, Str),
+ print_translation(File, Line, Str, Trans);
+ {_, used} ->
+ case ets:lookup(files, File) of
+ [{_}] ->
+ ok;
+ _ ->
+ io:format("~n% ~s~n", [File]),
+ ets:insert(files, {File})
+ end,
+ case Str of
+ [] -> ok;
+ _ -> io:format("{~p, \"\"}.~n", [Str])
+ end,
+ ets:insert(translations, {Str, ""});
+ {_, srcmsg2po} ->
+ case ets:lookup(files, File) of
+ [{_}] ->
+ ok;
+ _ ->
+ ets:insert(files, {File})
+ end,
+ ets:insert(translations, {Str, ""}),
+ print_translation(File, Line, Str, "");
+ _ ->
+ ok
+ end.
+
+load_file(File) ->
+ case file:consult(File) of
+ {ok, Terms} ->
+ lists:foreach(
+ fun({Orig, Trans}) ->
+ case Trans of
+ "" ->
+ ok;
+ _ ->
+ ets:insert(translations, {Orig, Trans}),
+ ets:insert(translations_obsolete, {Orig, Trans})
+ end
+ end, Terms);
+ Err ->
+ Err
+ end.
+
+find_src_files(Dir) ->
+ case file:list_dir(Dir) of
+ {ok, FileList} ->
+ recurse_filelist(
+ lists:map(
+ fun(F) ->
+ filename:join(Dir, F)
+ end, FileList));
+ _ ->
+ []
+ end.
+
+recurse_filelist(FileList) ->
+ recurse_filelist(FileList, []).
+
+recurse_filelist([], Acc) ->
+ lists:reverse(Acc);
+
+recurse_filelist([H | T], Acc) ->
+ case file:read_file_info(H) of
+ {ok, #file_info{type = directory}} ->
+ recurse_filelist(T, lists:reverse(find_src_files(H)) ++ Acc);
+ {ok, #file_info{type = regular}} ->
+ case string:substr(H, string:len(H) - 3) of
+ ".erl" ->
+ recurse_filelist(T, [H | Acc]);
+ ".hrl" ->
+ recurse_filelist(T, [H | Acc]);
+ _ ->
+ recurse_filelist(T, Acc)
+ end;
+ _ ->
+ recurse_filelist(T, Acc)
+ end.
+
+
+print_usage() ->
+ io:format(
+ "Usage: extract_translations [-unused] dir file~n"
+ "~n"
+ "Example:~n"
+ " extract_translations . ./msgs/ru.msg~n"
+ ).
+
+
+%%%
+%%% Gettext
+%%%
+
+print_po_header(File) ->
+ MsgProps = get_msg_header_props(File),
+ {Language, [LastT | AddT]} = prepare_props(MsgProps),
+ application:load(ejabberd),
+ {ok, Version} = application:get_key(ejabberd, vsn),
+ print_po_header(Version, Language, LastT, AddT).
+
+get_msg_header_props(File) ->
+ {ok, F} = file:open(File, [read]),
+ Lines = get_msg_header_props(F, []),
+ file:close(F),
+ Lines.
+
+get_msg_header_props(F, Lines) ->
+ String = io:get_line(F, ""),
+ case io_lib:fread("% ", String) of
+ {ok, [], RemString} ->
+ case io_lib:fread("~s", RemString) of
+ {ok, [Key], Value} when Value /= "\n" ->
+ %% The first character in Value is a blankspace:
+ %% And the last characters are 'slash n'
+ ValueClean = string:substr(Value, 2, string:len(Value)-2),
+ get_msg_header_props(F, Lines ++ [{Key, ValueClean}]);
+ _ ->
+ get_msg_header_props(F, Lines)
+ end;
+ _ ->
+ Lines
+ end.
+
+prepare_props(MsgProps) ->
+ Language = proplists:get_value("Language:", MsgProps),
+ Authors = proplists:get_all_values("Author:", MsgProps),
+ {Language, Authors}.
+
+print_po_header(Version, Language, LastTranslator, AdditionalTranslatorsList) ->
+ AdditionalTranslatorsString = build_additional_translators(AdditionalTranslatorsList),
+ HeaderString =
+ "msgid \"\"\n"
+ "msgstr \"\"\n"
+ "\"Project-Id-Version: " ++ Version ++ "\\n\"\n"
+ ++ "\"X-Language: " ++ Language ++ "\\n\"\n"
+ "\"Last-Translator: " ++ LastTranslator ++ "\\n\"\n"
+ ++ AdditionalTranslatorsString ++
+ "\"MIME-Version: 1.0\\n\"\n"
+ "\"Content-Type: text/plain; charset=UTF-8\\n\"\n"
+ "\"Content-Transfer-Encoding: 8bit\\n\"\n",
+ io:format("~s~n", [HeaderString]).
+
+build_additional_translators(List) ->
+ lists:foldl(
+ fun(T, Str) ->
+ Str ++ "\"X-Additional-Translator: " ++ T ++ "\\n\"\n"
+ end,
+ "",
+ List).
+
+print_translation(File, Line, Str, StrT) ->
+ {ok, StrQ, _} = regexp:gsub(Str, "\"", "\\\""),
+ {ok, StrTQ, _} = regexp:gsub(StrT, "\"", "\\\""),
+ io:format("#: ~s:~p~nmsgid \"~s\"~nmsgstr \"~s\"~n~n", [File, Line, StrQ, StrTQ]).
+
+print_translation_obsolete(Str, StrT) ->
+ File = "unknown.erl",
+ Line = 1,
+ {ok, StrQ, _} = regexp:gsub(Str, "\"", "\\\""),
+ {ok, StrTQ, _} = regexp:gsub(StrT, "\"", "\\\""),
+ io:format("#: ~s:~p~n#~~ msgid \"~s\"~n#~~ msgstr \"~s\"~n~n", [File, Line, StrQ, StrTQ]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/mnesia_diff_atoms_race1.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_diff_atoms_race1.erl
new file mode 100644
index 0000000000..2f499208a2
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/mnesia_diff_atoms_race1.erl
@@ -0,0 +1,33 @@
+%% This tests that the race condition detection between mnesia:dirty_read/
+%% mnesia:dirty_write is robust even when the functions are called with
+%% different atoms as arguments.
+
+-module(mnesia_diff_atoms_race1).
+-export([test/2]).
+
+-record(employee, {emp_no,
+ name,
+ salary,
+ sex,
+ phone,
+ room_no}).
+
+test(Eno, Raise) ->
+ {race(employee, Eno, Raise), no_race(employee, Eno, Raise)}.
+
+race(Tab, Eno, Raise) ->
+ [E] = mnesia:dirty_read(Tab, Eno),
+ Salary = E#employee.salary + Raise,
+ New = E#employee{salary = Salary},
+ aux(Tab, New).
+
+no_race(Tab, Eno, Raise) ->
+ [E] = mnesia:dirty_read(Tab, Eno),
+ Salary = E#employee.salary + Raise,
+ New = E#employee{salary = Salary},
+ AnotherTab = employer,
+ aux(AnotherTab, New).
+
+
+aux(Table, Record) ->
+ mnesia:dirty_write(Table, Record).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/mnesia_diff_atoms_race2.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_diff_atoms_race2.erl
new file mode 100644
index 0000000000..c1dcfbd8f5
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/mnesia_diff_atoms_race2.erl
@@ -0,0 +1,37 @@
+%% This tests that the race condition detection between mnesia:dirty_read/
+%% mnesia:dirty_write is robust even when the functions are called with
+%% different atoms as arguments.
+
+-module(mnesia_diff_atoms_race2).
+-export([test/2]).
+
+-record(employee, {emp_no,
+ name,
+ salary,
+ sex,
+ phone,
+ room_no}).
+
+-record(employer, {emp_no,
+ name,
+ salary,
+ sex,
+ phone,
+ room_no}).
+
+test(Eno, Raise) ->
+ {race(employee, Eno, Raise), no_race(employee, Eno, Raise)}.
+
+race(Tab, Eno, Raise) ->
+ [E] = mnesia:dirty_read(Tab, Eno),
+ Salary = E#employee.salary + Raise,
+ New = E#employee{salary = Salary},
+ aux(New).
+
+no_race(Tab, Eno, Raise) ->
+ [E] = mnesia:dirty_read(Tab, Eno),
+ AnotherRecord = #employer{},
+ aux(AnotherRecord).
+
+aux(Record) ->
+ mnesia:dirty_write(Record).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_one_write_two.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_one_write_two.erl
new file mode 100644
index 0000000000..4ca62deedc
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_one_write_two.erl
@@ -0,0 +1,20 @@
+%% This tests the presence of possible races due to an mnesia:dirty_read/
+%% mnesia:dirty_write combination. It takes into account the argument types
+%% of the calls.
+
+-module(mnesia_dirty_read_one_write_two).
+-export([raise/2]).
+
+-record(employee, {emp_no,
+ name,
+ salary,
+ sex,
+ phone,
+ room_no}).
+
+
+raise(Eno, Raise) ->
+ [E] = mnesia:dirty_read({employee, Eno}),
+ Salary = E#employee.salary + Raise,
+ New = E#employee{salary = Salary},
+ mnesia:dirty_write(employee, New).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_two_write_one.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_two_write_one.erl
new file mode 100644
index 0000000000..e523a03789
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_two_write_one.erl
@@ -0,0 +1,20 @@
+%% This tests the presence of possible races due to an mnesia:dirty_read/
+%% mnesia:dirty_write combination. It takes into account the argument types
+%% of the calls.
+
+-module(mnesia_dirty_read_two_write_one).
+-export([raise/2]).
+
+-record(employee, {emp_no,
+ name,
+ salary,
+ sex,
+ phone,
+ room_no}).
+
+
+raise(Eno, Raise) ->
+ [E] = mnesia:dirty_read(employee, Eno),
+ Salary = E#employee.salary + Raise,
+ New = E#employee{salary = Salary},
+ mnesia:dirty_write(New).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_double1.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double1.erl
index 2bd18e4772..2bd18e4772 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_double1.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double1.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_double2.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double2.erl
index cdbfdc700a..cdbfdc700a 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_double2.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double2.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_double3.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double3.erl
index 051524917e..051524917e 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_double3.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double3.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_double4.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double4.erl
index 96752a6045..96752a6045 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_double4.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double4.erl
diff --git a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_one.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_one.erl
new file mode 100644
index 0000000000..aee6433736
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_one.erl
@@ -0,0 +1,20 @@
+%% This tests the presence of possible races due to an mnesia:dirty_read/
+%% mnesia:dirty_write combination. It takes into account the argument types
+%% of the calls.
+
+-module(mnesia_dirty_read_write_one).
+-export([raise/2]).
+
+-record(employee, {emp_no,
+ name,
+ salary,
+ sex,
+ phone,
+ room_no}).
+
+
+raise(Eno, Raise) ->
+ [E] = mnesia:dirty_read({employee, Eno}),
+ Salary = E#employee.salary + Raise,
+ New = E#employee{salary = Salary},
+ mnesia:dirty_write(New).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_two.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_two.erl
new file mode 100644
index 0000000000..037aeddafd
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_two.erl
@@ -0,0 +1,20 @@
+%% This tests the presence of possible races due to an mnesia:dirty_read/
+%% mnesia:dirty_write combination. It takes into account the argument types
+%% of the calls.
+
+-module(mnesia_dirty_read_write_two).
+-export([raise/2]).
+
+-record(employee, {emp_no,
+ name,
+ salary,
+ sex,
+ phone,
+ room_no}).
+
+
+raise(Eno, Raise) ->
+ [E] = mnesia:dirty_read(employee, Eno),
+ Salary = E#employee.salary + Raise,
+ New = E#employee{salary = Salary},
+ mnesia:dirty_write(employee, New).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow1.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow1.erl
index e65f6c3e23..e65f6c3e23 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow1.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow1.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow2.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow2.erl
index 41039482c9..41039482c9 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow2.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow2.erl
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow3.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow3.erl
new file mode 100644
index 0000000000..94f8445fad
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow3.erl
@@ -0,0 +1,25 @@
+%% This tests the presence of possible races due to a whereis/register
+%% combination. It takes into account control flow that might exist.
+
+-module(whereis_control_flow3).
+-export([start/3]).
+
+start(AnAtom, Fun, FunName) ->
+ Pid =
+ case FunName of
+ master ->
+ case whereis(AnAtom) of
+ undefined ->
+ spawn(Fun);
+ P when is_pid(P) ->
+ P
+ end;
+ slave ->
+ case whereis(AnAtom) of
+ undefined ->
+ spawn(Fun);
+ P when is_pid(P) ->
+ P
+ end
+ end,
+ register(AnAtom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow4.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow4.erl
new file mode 100644
index 0000000000..2a59760789
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow4.erl
@@ -0,0 +1,29 @@
+%% This tests the presence of possible races due to a whereis/register
+%% combination. It takes into account control flow that might exist.
+
+-module(whereis_control_flow4).
+-export([start/1]).
+
+start(Fun) ->
+ case whereis(maria) of
+ undefined ->
+ Pid1 = spawn(Fun),
+ case Pid1 =:= self() of
+ true ->
+ case whereis(kostis) of
+ undefined ->
+ Pid2 = spawn(Fun),
+ case Pid2 =:= self() of
+ true ->
+ register(maria, Pid1),
+ register(kostis, Pid2);
+ false -> ok
+ end;
+ P when is_pid(P) ->
+ ok
+ end;
+ false -> ok
+ end;
+ P when is_pid(P) ->
+ ok
+ end.
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow5.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow5.erl
index 8de9cb2dad..8de9cb2dad 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow5.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow5.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow6.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow6.erl
index 03c5095a50..03c5095a50 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow6.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow6.erl
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_atoms_no_race.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_atoms_no_race.erl
new file mode 100644
index 0000000000..704ee6015d
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_atoms_no_race.erl
@@ -0,0 +1,23 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust even when the functions are called with different atoms
+%% as arguments.
+
+-module(whereis_diff_atoms_no_race).
+-export([test/0]).
+
+test() ->
+ Fun = fun () -> foo end,
+ {no_race(maria, Fun)}.
+
+no_race(AnAtom, Fun) ->
+ case whereis(AnAtom) of
+ undefined ->
+ Pid = spawn(Fun),
+ AnotherAtom = kostis,
+ aux(AnotherAtom, Pid);
+ P when is_pid(P) ->
+ ok
+ end.
+
+aux(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_atoms_race.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_atoms_race.erl
new file mode 100644
index 0000000000..6c834caa0c
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_atoms_race.erl
@@ -0,0 +1,34 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust even when the functions are called with different atoms
+%% as arguments.
+
+-module(whereis_diff_atoms_race).
+-export([test/0]). %, race/1, no_race/1]).
+
+test() ->
+ Fun = fun () -> foo end,
+ {race(maria, Fun), no_race(maria, Fun)}.
+
+race(AnAtom, Fun) ->
+ %AnAtom = maria,
+ case whereis(AnAtom) of
+ undefined ->
+ Pid = spawn(Fun),
+ aux(AnAtom, Pid);
+ P when is_pid(P) ->
+ ok
+ end.
+
+no_race(AnAtom, Fun) ->
+ %AnAtom = maria,
+ case whereis(AnAtom) of
+ undefined ->
+ Pid = spawn(Fun),
+ AnotherAtom = kostis,
+ aux(AnotherAtom, Pid);
+ P when is_pid(P) ->
+ ok
+ end.
+
+aux(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions1.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1.erl
index 6a1c197c06..6a1c197c06 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions1.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1.erl
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_nested.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_nested.erl
new file mode 100644
index 0000000000..4967dec133
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_nested.erl
@@ -0,0 +1,23 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate functions.
+
+-module(whereis_diff_functions1_nested).
+-export([test/2]).
+
+test(AnAtom, Fun) ->
+ start(AnAtom, Fun).
+
+start(AnAtom, Fun) ->
+ case whereis(AnAtom) of
+ undefined ->
+ Pid = spawn(Fun),
+ race1(AnAtom, Pid);
+ P when is_pid(P) ->
+ true
+ end.
+
+race1(Atom, Pid) ->
+ race2(Atom, Pid).
+
+race2(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_pathsens.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_pathsens.erl
new file mode 100644
index 0000000000..ff6506eee8
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_pathsens.erl
@@ -0,0 +1,32 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate functions.
+%% It takes into account control flow that might exist.
+
+-module(whereis_diff_functions1_pathsens).
+-export([test/1]).
+
+test(FunName) ->
+ start(kostis, mod:function(), FunName).
+
+start(AnAtom, Fun, FunName) ->
+ Pid =
+ case FunName of
+ master ->
+ case whereis(AnAtom) of
+ undefined ->
+ spawn(Fun);
+ P when is_pid(P) ->
+ P
+ end;
+ slave ->
+ case whereis(AnAtom) of
+ undefined ->
+ spawn(Fun);
+ P when is_pid(P) ->
+ P
+ end
+ end,
+ race(AnAtom, Pid).
+
+race(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_twice.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_twice.erl
new file mode 100644
index 0000000000..dd395bb6d8
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_twice.erl
@@ -0,0 +1,30 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having multiple calls in separate functions.
+
+-module(whereis_diff_functions1_twice).
+-export([test/2]).
+
+test(AnAtom, Fun) ->
+ start(AnAtom, Fun).
+
+start(AnAtom, Fun) ->
+ case whereis(AnAtom) of
+ undefined ->
+ Pid1 = spawn(Fun),
+ race(AnAtom, Pid1),
+ case whereis(AnAtom) of
+ undefined ->
+ Pid2 = spawn(Fun),
+ race_again(AnAtom, Pid2);
+ P when is_pid(P) ->
+ true
+ end;
+ P when is_pid(P) ->
+ true
+ end.
+
+race(Atom, Pid) ->
+ register(Atom, Pid).
+
+race_again(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2.erl
new file mode 100644
index 0000000000..eaf98291ed
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2.erl
@@ -0,0 +1,25 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate functions.
+
+-module(whereis_diff_functions2).
+-export([test/0]).
+
+test() ->
+ start(kostis, mod:function()).
+
+start(AnAtom, Fun) ->
+ Pid1 = spawn(Fun),
+ no_race(Pid1),
+ case whereis(AnAtom) of
+ undefined ->
+ Pid2 = spawn(Fun),
+ race(AnAtom, Pid2);
+ P when is_pid(P) ->
+ true
+ end.
+
+no_race(Pid) ->
+ register(master, Pid).
+
+race(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_nested.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_nested.erl
new file mode 100644
index 0000000000..5ae8784389
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_nested.erl
@@ -0,0 +1,20 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate functions.
+
+-module(whereis_diff_functions2_nested).
+-export([start/2]).
+
+start(AnAtom, Fun) ->
+ case whereis(AnAtom) of
+ undefined ->
+ Pid = spawn(Fun),
+ race1(AnAtom, Pid);
+ P when is_pid(P) ->
+ true
+ end.
+
+race1(Atom, Pid) ->
+ race2(Atom, Pid).
+
+race2(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_pathsens.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_pathsens.erl
new file mode 100644
index 0000000000..e9ce4bc48e
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_pathsens.erl
@@ -0,0 +1,29 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate functions.
+%% It takes into account control flow that might exist.
+
+-module(whereis_diff_functions2_pathsens).
+-export([race/4]).
+
+start(AnAtom, Fun, FunName) ->
+ Pid =
+ case FunName of
+ master ->
+ case whereis(AnAtom) of
+ undefined ->
+ spawn(Fun);
+ P when is_pid(P) ->
+ P
+ end;
+ slave ->
+ case whereis(AnAtom) of
+ undefined ->
+ spawn(Fun);
+ P when is_pid(P) ->
+ P
+ end
+ end.
+
+race(Atom, Fun, FunName, Pid) ->
+ start(Atom, Fun, FunName),
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_twice.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_twice.erl
new file mode 100644
index 0000000000..d5efe631b8
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_twice.erl
@@ -0,0 +1,27 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having multiple calls in separate functions.
+
+-module(whereis_diff_functions2_twice).
+-export([start/2]).
+
+start(AnAtom, Fun) ->
+ case whereis(AnAtom) of
+ undefined ->
+ Pid1 = spawn(Fun),
+ race(AnAtom, Pid1),
+ case whereis(AnAtom) of
+ undefined ->
+ Pid2 = spawn(Fun),
+ race_again(AnAtom, Pid2);
+ P when is_pid(P) ->
+ true
+ end;
+ P when is_pid(P) ->
+ true
+ end.
+
+race(Atom, Pid) ->
+ register(Atom, Pid).
+
+race_again(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3.erl
new file mode 100644
index 0000000000..093f02a06f
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3.erl
@@ -0,0 +1,11 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate functions.
+
+-module(whereis_diff_functions3).
+-export([start/1]).
+
+start(AnAtom) ->
+ register(AnAtom, race(AnAtom)).
+
+race(Atom) ->
+ whereis(Atom).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3_nested.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3_nested.erl
new file mode 100644
index 0000000000..5c28fc74f6
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3_nested.erl
@@ -0,0 +1,21 @@
+%% This tests that the race condition detection between whereis/unregister
+%% is robust w.r.t. having the calls in separate functions.
+
+-module(whereis_diff_functions3_nested).
+-export([test/1]).
+
+test(AnAtom) ->
+ start(AnAtom).
+
+start(AnAtom) ->
+ case whereis(AnAtom) of
+ undefined -> true;
+ P when is_pid(P) ->
+ race1(AnAtom)
+ end.
+
+race1(Atom) ->
+ race2(Atom).
+
+race2(Atom) ->
+ unregister(Atom).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3_pathsens.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3_pathsens.erl
new file mode 100644
index 0000000000..a3a245b9ea
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3_pathsens.erl
@@ -0,0 +1,29 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate functions.
+%% It takes into account control flow that might exist.
+
+-module(whereis_diff_functions3_pathsens).
+-export([start/3]).
+
+start(AnAtom, Fun, FunName) ->
+ Pid =
+ case FunName of
+ master ->
+ case whereis(AnAtom) of
+ undefined ->
+ spawn(Fun);
+ P when is_pid(P) ->
+ P
+ end;
+ slave ->
+ case whereis(AnAtom) of
+ undefined ->
+ spawn(Fun);
+ P when is_pid(P) ->
+ P
+ end
+ end,
+ race(AnAtom, Pid).
+
+race(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions4.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions4.erl
new file mode 100644
index 0000000000..e40483d487
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions4.erl
@@ -0,0 +1,32 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate functions.
+
+-module(whereis_diff_functions4).
+-export([test/2]).
+
+test(AnAtom, Fun) ->
+ start(AnAtom, Fun).
+
+start(AnAtom, Fun) ->
+ Pid1 = spawn(Fun),
+ no_race(Pid1),
+ case whereis(AnAtom) of
+ undefined ->
+ Pid2 = spawn(Fun),
+ race(AnAtom, Pid2),
+ case whereis(AnAtom) of
+ undefined ->
+ Pid3 = spawn(Fun),
+ race(AnAtom, Pid3);
+ P when is_pid(P) ->
+ true
+ end;
+ P when is_pid(P) ->
+ true
+ end.
+
+no_race(Pid) ->
+ register(master, Pid).
+
+race(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions5.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions5.erl
new file mode 100644
index 0000000000..a2c4352803
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions5.erl
@@ -0,0 +1,22 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate functions.
+
+-module(whereis_diff_functions5).
+-export([start/2]).
+
+start(AnAtom, Fun) ->
+ Pid1 = spawn(Fun),
+ no_race(Pid1),
+ case whereis(AnAtom) of
+ undefined ->
+ Pid2 = spawn(Fun),
+ race(AnAtom, Pid2);
+ P when is_pid(P) ->
+ true
+ end.
+
+no_race(Pid) ->
+ register(master, Pid).
+
+race(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions6.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions6.erl
new file mode 100644
index 0000000000..f016d79533
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions6.erl
@@ -0,0 +1,29 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate functions.
+
+-module(whereis_diff_functions6).
+-export([start/2]).
+
+start(AnAtom, Fun) ->
+ Pid1 = spawn(Fun),
+ no_race(Pid1),
+ case whereis(AnAtom) of
+ undefined ->
+ Pid2 = spawn(Fun),
+ race(AnAtom, Pid2),
+ case whereis(AnAtom) of
+ undefined ->
+ Pid3 = spawn(Fun),
+ race(AnAtom, Pid3);
+ P when is_pid(P) ->
+ true
+ end;
+ P when is_pid(P) ->
+ true
+ end.
+
+no_race(Pid) ->
+ register(master, Pid).
+
+race(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules1.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules1.erl
index 00cb29cec0..00cb29cec0 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules1.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules1.erl
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules2.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules2.erl
new file mode 100644
index 0000000000..e5f6fdeb7b
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules2.erl
@@ -0,0 +1,11 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate modules.
+
+-module(whereis_diff_modules2).
+-export([no_race/1, race/2]).
+
+no_race(Pid) ->
+ register(master, Pid).
+
+race(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules1_pathsens.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules1_pathsens.erl
new file mode 100644
index 0000000000..a5f1d4d3c7
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules1_pathsens.erl
@@ -0,0 +1,26 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate modules (backward analysis).
+%% It takes into account control flow that might exist.
+
+-module(whereis_diff_modules1_pathsens).
+-export([start/3]).
+
+start(AnAtom, Fun, FunName) ->
+ Pid =
+ case FunName of
+ master ->
+ case whereis(AnAtom) of
+ undefined ->
+ spawn(Fun);
+ P when is_pid(P) ->
+ P
+ end;
+ slave ->
+ case whereis(AnAtom) of
+ undefined ->
+ spawn(Fun);
+ P when is_pid(P) ->
+ P
+ end
+ end,
+ whereis_diff_modules2_pathsens:race(AnAtom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules2_pathsens.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules2_pathsens.erl
new file mode 100644
index 0000000000..d24d13976b
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules2_pathsens.erl
@@ -0,0 +1,12 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate modules (backward analysis).
+%% It takes into account control flow that might exist.
+
+-module(whereis_diff_modules2_pathsens).
+-export([no_race/1, race/2]).
+
+no_race(Pid) ->
+ register(master, Pid).
+
+race(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules1_rec.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules1_rec.erl
index a397954eea..a397954eea 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules1_rec.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules1_rec.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules2_rec.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules2_rec.erl
index 4b46b4a8e5..4b46b4a8e5 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules2_rec.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules2_rec.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules3.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules3.erl
index 60b5a1d378..60b5a1d378 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules3.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules3.erl
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules4.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules4.erl
new file mode 100644
index 0000000000..1ab4fbf8d8
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules4.erl
@@ -0,0 +1,11 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate modules.
+
+-module(whereis_diff_modules4).
+-export([no_race/1, race/1]).
+
+no_race(Pid) ->
+ register(master, Pid).
+
+race(Atom) ->
+ whereis(Atom).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules3_pathsens.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules3_pathsens.erl
new file mode 100644
index 0000000000..cb2f85a103
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules3_pathsens.erl
@@ -0,0 +1,25 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate modules (forward analysis).
+%% It takes into account control flow that might exist.
+
+-module(whereis_diff_modules3_pathsens).
+-export([start/3]).
+
+start(AnAtom, Fun, FunName) ->
+ Pid =
+ case FunName of
+ master ->
+ case whereis(AnAtom) of
+ undefined ->
+ spawn(Fun);
+ P when is_pid(P) ->
+ P
+ end;
+ slave ->
+ case whereis(AnAtom) of
+ undefined ->
+ spawn(Fun);
+ P when is_pid(P) ->
+ P
+ end
+ end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules4_pathsens.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules4_pathsens.erl
new file mode 100644
index 0000000000..952f9312f4
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules4_pathsens.erl
@@ -0,0 +1,13 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate modules (forward analysis).
+%% It takes into account control flow that might exist.
+
+-module(whereis_diff_modules4_pathsens).
+-export([no_race/1, race/4]).
+
+no_race(Pid) ->
+ register(master, Pid).
+
+race(Atom, Fun, FunName, Pid) ->
+ whereis_diff_modules3_pathsens:start(Atom, Fun, FunName),
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules3_rec.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules3_rec.erl
index 0320140768..0320140768 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules3_rec.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules3_rec.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules4_rec.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules4_rec.erl
index d49c59ed5c..d49c59ed5c 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules4_rec.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules4_rec.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules5.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules5.erl
index 591732aa31..591732aa31 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules5.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules5.erl
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules6.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules6.erl
new file mode 100644
index 0000000000..159d96cfc5
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules6.erl
@@ -0,0 +1,11 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate modules.
+
+-module(whereis_diff_modules6).
+-export([no_race/1, race/2]).
+
+no_race(Pid) ->
+ register(master, Pid).
+
+race(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules1_nested.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules1_nested.erl
index a25d2f8784..a25d2f8784 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules1_nested.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules1_nested.erl
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules2_nested.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules2_nested.erl
new file mode 100644
index 0000000000..32a55e731a
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules2_nested.erl
@@ -0,0 +1,11 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate modules.
+
+-module(whereis_diff_modules2_nested).
+-export([no_race/1, race/2]).
+
+no_race(Pid) ->
+ register(master, Pid).
+
+race(Atom, Pid) ->
+ whereis_diff_modules3_nested:race(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules3_nested.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules3_nested.erl
new file mode 100644
index 0000000000..414129611f
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules3_nested.erl
@@ -0,0 +1,11 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate modules.
+
+-module(whereis_diff_modules3_nested).
+-export([no_race/1, race/2]).
+
+no_race(Pid) ->
+ register(master, Pid).
+
+race(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules1_twice.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules1_twice.erl
index 92f2cb1fbc..92f2cb1fbc 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules1_twice.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules1_twice.erl
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules2_twice.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules2_twice.erl
new file mode 100644
index 0000000000..390c0dcc94
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules2_twice.erl
@@ -0,0 +1,11 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate modules.
+
+-module(whereis_diff_modules2_twice).
+-export([race/2, race_again/2]).
+
+race(Atom, Pid) ->
+ register(Atom, Pid).
+
+race_again(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_vars_no_race.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_vars_no_race.erl
new file mode 100644
index 0000000000..8466004ce4
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_vars_no_race.erl
@@ -0,0 +1,13 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust even when the functions are called with different variables
+%% as arguments.
+
+-module(whereis_diff_vars_no_race).
+-export([test/3]).
+
+test(AnAtom, AnotherAtom, Pid) ->
+ {aux(AnAtom, Pid), aux(AnotherAtom, Pid)}.
+
+aux(Atom, Pid) ->
+ register(Atom, Pid),
+ whereis(Atom).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_vars_race.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_vars_race.erl
new file mode 100644
index 0000000000..90791de1b2
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_vars_race.erl
@@ -0,0 +1,19 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust even when the functions are called with different variables
+%% as arguments.
+
+-module(whereis_diff_vars_race).
+-export([test/2]).
+
+test(AnAtom, AnotherAtom) ->
+ Fun = fun () -> foo end,
+ {aux(AnAtom, AnotherAtom, Fun), aux(AnotherAtom, AnAtom, Fun)}.
+
+aux(Atom1, Atom2, Fun) ->
+ case whereis(Atom1) of
+ undefined ->
+ Pid = spawn(Fun),
+ register(Atom2, Pid);
+ P when is_pid(P) ->
+ ok
+ end.
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module1.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module1.erl
index 677551c99d..677551c99d 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module1.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module1.erl
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module2.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module2.erl
new file mode 100644
index 0000000000..e7acee0cfd
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module2.erl
@@ -0,0 +1,11 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate functions and modules.
+
+-module(whereis_intra_inter_module2).
+-export([no_race/1, race/2]).
+
+no_race(Pid) ->
+ register(master, Pid).
+
+race(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module3.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module3.erl
index c8103db122..c8103db122 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module3.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module3.erl
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module4.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module4.erl
new file mode 100644
index 0000000000..4094a95223
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module4.erl
@@ -0,0 +1,14 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate functions and modules.
+
+-module(whereis_intra_inter_module4).
+-export([no_race/1, race/2]).
+
+no_race(Pid) ->
+ register(master, Pid).
+
+race(Atom, Pid) ->
+ continue(Atom, Pid).
+
+continue(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module5.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module5.erl
index 2a29779153..2a29779153 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module5.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module5.erl
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module6.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module6.erl
new file mode 100644
index 0000000000..cd05431cd5
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module6.erl
@@ -0,0 +1,14 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate functions and modules.
+
+-module(whereis_intra_inter_module6).
+-export([no_race/1, race/2]).
+
+no_race(Pid) ->
+ register(master, Pid).
+
+race(Atom, Pid) ->
+ continue(Atom, Pid).
+
+continue(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module7.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module7.erl
index 1f702e7af3..1f702e7af3 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module7.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module7.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module8.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module8.erl
index 581817308b..581817308b 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module8.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module8.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module10.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module10.erl
index 7ed50ea742..7ed50ea742 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module10.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module10.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module9.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module9.erl
index 5c5d92b770..5c5d92b770 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module9.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module9.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module11.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module11.erl
index 82abe2f4a8..82abe2f4a8 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module11.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module11.erl
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module12.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module12.erl
new file mode 100644
index 0000000000..c2f5d560a0
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module12.erl
@@ -0,0 +1,14 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate functions and modules.
+
+-module(whereis_intra_inter_module12).
+-export([no_race/1, race/2, continue/2]).
+
+no_race(Pid) ->
+ register(master, Pid).
+
+race(Atom, Pid) ->
+ continue(Atom, Pid).
+
+continue(Atom, Pid) ->
+ register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module13.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module13.erl
index 3cd5cc6fa6..3cd5cc6fa6 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module13.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module13.erl
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module14.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module14.erl
new file mode 100644
index 0000000000..6b6a982055
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module14.erl
@@ -0,0 +1,22 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate functions and modules.
+
+-module(whereis_intra_inter_module14).
+-export([no_race/1, race/2, start/2]).
+
+no_race(Pid) ->
+ register(master, Pid).
+
+race(Atom, Pid) ->
+ register(Atom, Pid).
+
+start(AnAtom, Fun) ->
+ Pid1 = spawn(Fun),
+ no_race(Pid1),
+ case whereis(AnAtom) of
+ undefined ->
+ Pid2 = spawn(Fun),
+ race(AnAtom, Pid2);
+ P when is_pid(P) ->
+ true
+ end.
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module15.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module15.erl
index c60d166fa9..c60d166fa9 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module15.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module15.erl
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module16.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module16.erl
new file mode 100644
index 0000000000..279e633d66
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module16.erl
@@ -0,0 +1,22 @@
+%% This tests that the race condition detection between whereis/register
+%% is robust w.r.t. having the calls in separate functions and modules.
+
+-module(whereis_intra_inter_module16).
+-export([no_race/1, race/2, start/2]).
+
+no_race(Pid) ->
+ register(master, Pid).
+
+race(Atom, Pid) ->
+ register(Atom, Pid).
+
+start(AnAtom, Fun) ->
+ Pid1 = spawn(Fun),
+ no_race(Pid1),
+ case whereis(AnAtom) of
+ undefined ->
+ Pid2 = spawn(Fun),
+ whereis_intra_inter_module15:continue(AnAtom, Pid2);
+ P when is_pid(P) ->
+ true
+ end.
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_param.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_param.erl
index 7bcde321a1..7bcde321a1 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_param.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_param.erl
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module1.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module1.erl
new file mode 100644
index 0000000000..8bac0326a5
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module1.erl
@@ -0,0 +1,8 @@
+%% This tests the presence of possible races due to a whereis/register
+%% combination in higher order functions and inter-module calls.
+
+-module(whereis_param_inter_module1).
+-export([start/2]).
+
+start(AnAtom, Fun) ->
+ register(AnAtom, whereis_param_inter_module2:continue(AnAtom, Fun)).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module2.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module2.erl
index 61252add9a..61252add9a 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module2.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module2.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function1.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function1.erl
index c8095fbf4c..c8095fbf4c 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function1.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function1.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function2.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function2.erl
index 2721c9e19c..2721c9e19c 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function2.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function2.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function3.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function3.erl
index e101f34fba..e101f34fba 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function3.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function3.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function4.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function4.erl
index 4894d3397b..4894d3397b 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function4.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function4.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function5.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function5.erl
index d821f829a2..d821f829a2 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function5.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function5.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function6.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function6.erl
index 4ec4baf0be..4ec4baf0be 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function6.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function6.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function7.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function7.erl
index 7667443117..7667443117 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function7.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function7.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function8.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function8.erl
index a06fb75f64..a06fb75f64 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_rec_function8.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function8.erl
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_try_catch.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_try_catch.erl
new file mode 100644
index 0000000000..39bb440f56
--- /dev/null
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_try_catch.erl
@@ -0,0 +1,25 @@
+% This tests that warnings do appear when a whereis/register combination
+% is handled by try/catch.
+
+-module(whereis_try_catch).
+-export([race/1, no_race/1]).
+
+race(Pid) ->
+ case whereis(master) of
+ undefined ->
+ try
+ io:format("exception", [])
+ catch
+ _ -> register(master, Pid)
+ end
+ end.
+
+no_race(Pid) ->
+ case whereis(master) of
+ undefined ->
+ try
+ register(master, Pid)
+ catch
+ _ -> io:format("exception", [])
+ end
+ end.
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars1.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars1.erl
index 9b249e72be..9b249e72be 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars1.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars1.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars10.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars10.erl
index 5c1896d6b4..5c1896d6b4 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars10.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars10.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars11.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars11.erl
index dc8551b3f2..dc8551b3f2 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars11.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars11.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars12.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars12.erl
index 38b0dc5d04..38b0dc5d04 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars12.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars12.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars13.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars13.erl
index 3a04bba02f..3a04bba02f 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars13.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars13.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars14.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars14.erl
index c688847551..c688847551 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars14.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars14.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars15.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars15.erl
index 4b3a72537e..4b3a72537e 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars15.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars15.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars16.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars16.erl
index 7badb8df22..7badb8df22 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars16.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars16.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars17.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars17.erl
index bc7ef5e980..bc7ef5e980 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars17.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars17.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars18.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars18.erl
index 06416fa987..06416fa987 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars18.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars18.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars19.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars19.erl
index ae5b28e42d..ae5b28e42d 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars19.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars19.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars2.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars2.erl
index bafb5d4644..bafb5d4644 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars2.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars2.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars20.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars20.erl
index 87c6caadf0..87c6caadf0 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars20.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars20.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars21.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars21.erl
index 73d22d3467..73d22d3467 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars21.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars21.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars22.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars22.erl
index dd16928e33..dd16928e33 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars22.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars22.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars3.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars3.erl
index 16c9a6c8bc..16c9a6c8bc 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars3.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars3.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars4.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars4.erl
index da5b329ca9..da5b329ca9 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars4.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars4.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars5.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars5.erl
index dff8646ea8..dff8646ea8 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars5.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars5.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars6.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars6.erl
index cf22ab1883..cf22ab1883 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars6.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars6.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars7.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars7.erl
index 4bce53982a..4bce53982a 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars7.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars7.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars8.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars8.erl
index 937b83cf02..937b83cf02 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars8.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars8.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars9.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars9.erl
index 9beb67ca38..9beb67ca38 100644
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_vars9.erl
+++ b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars9.erl
diff --git a/lib/dialyzer/test/race_tests_SUITE.erl b/lib/dialyzer/test/race_tests_SUITE.erl
deleted file mode 100644
index cfc898d464..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE.erl
+++ /dev/null
@@ -1,799 +0,0 @@
-%% ATTENTION!
-%% This is an automatically generated file. Do not edit.
-%% Use './remake' script to refresh it if needed.
-%% All Dialyzer options should be defined in dialyzer_options
-%% file.
-
--module(race_tests_SUITE).
-
--include("ct.hrl").
--include("dialyzer_test_constants.hrl").
-
--export([suite/0, init_per_suite/0, init_per_suite/1,
- end_per_suite/1, all/0]).
--export([race_tests_SUITE_consistency/1, ets_insert_args1/1,
- ets_insert_args2/1, ets_insert_args3/1, ets_insert_args4/1,
- ets_insert_args5/1, ets_insert_args6/1, ets_insert_args7/1,
- ets_insert_args8/1, ets_insert_control_flow1/1,
- ets_insert_control_flow2/1, ets_insert_control_flow3/1,
- ets_insert_control_flow4/1, ets_insert_control_flow5/1,
- ets_insert_diff_atoms_race1/1, ets_insert_diff_atoms_race2/1,
- ets_insert_diff_atoms_race3/1, ets_insert_diff_atoms_race4/1,
- ets_insert_diff_atoms_race5/1, ets_insert_diff_atoms_race6/1,
- ets_insert_double1/1, ets_insert_double2/1, ets_insert_funs1/1,
- ets_insert_funs2/1, ets_insert_new/1, ets_insert_param/1,
- extract_translations/1, mnesia_diff_atoms_race1/1,
- mnesia_diff_atoms_race2/1, mnesia_dirty_read_one_write_two/1,
- mnesia_dirty_read_two_write_one/1,
- mnesia_dirty_read_write_double1/1,
- mnesia_dirty_read_write_double2/1,
- mnesia_dirty_read_write_double3/1,
- mnesia_dirty_read_write_double4/1, mnesia_dirty_read_write_one/1,
- mnesia_dirty_read_write_two/1, whereis_control_flow1/1,
- whereis_control_flow2/1, whereis_control_flow3/1,
- whereis_control_flow4/1, whereis_control_flow5/1,
- whereis_control_flow6/1, whereis_diff_atoms_no_race/1,
- whereis_diff_atoms_race/1, whereis_diff_functions1/1,
- whereis_diff_functions1_nested/1,
- whereis_diff_functions1_pathsens/1,
- whereis_diff_functions1_twice/1, whereis_diff_functions2/1,
- whereis_diff_functions2_nested/1,
- whereis_diff_functions2_pathsens/1,
- whereis_diff_functions2_twice/1, whereis_diff_functions3/1,
- whereis_diff_functions3_nested/1,
- whereis_diff_functions3_pathsens/1, whereis_diff_functions4/1,
- whereis_diff_functions5/1, whereis_diff_functions6/1,
- whereis_diff_modules1/1, whereis_diff_modules1_pathsens/1,
- whereis_diff_modules1_rec/1, whereis_diff_modules2/1,
- whereis_diff_modules2_pathsens/1, whereis_diff_modules2_rec/1,
- whereis_diff_modules3/1, whereis_diff_modules_nested/1,
- whereis_diff_modules_twice/1, whereis_diff_vars_no_race/1,
- whereis_diff_vars_race/1, whereis_intra_inter_module1/1,
- whereis_intra_inter_module2/1, whereis_intra_inter_module3/1,
- whereis_intra_inter_module4/1, whereis_intra_inter_module5/1,
- whereis_intra_inter_module6/1, whereis_intra_inter_module7/1,
- whereis_intra_inter_module8/1, whereis_param/1,
- whereis_param_inter_module/1, whereis_rec_function1/1,
- whereis_rec_function2/1, whereis_rec_function3/1,
- whereis_rec_function4/1, whereis_rec_function5/1,
- whereis_rec_function6/1, whereis_rec_function7/1,
- whereis_rec_function8/1, whereis_try_catch/1, whereis_vars1/1,
- whereis_vars10/1, whereis_vars11/1, whereis_vars12/1,
- whereis_vars13/1, whereis_vars14/1, whereis_vars15/1,
- whereis_vars16/1, whereis_vars17/1, whereis_vars18/1,
- whereis_vars19/1, whereis_vars2/1, whereis_vars20/1,
- whereis_vars21/1, whereis_vars22/1, whereis_vars3/1,
- whereis_vars4/1, whereis_vars5/1, whereis_vars6/1,
- whereis_vars7/1, whereis_vars8/1, whereis_vars9/1]).
-
-suite() ->
- [{timetrap, {minutes, 1}}].
-
-init_per_suite() ->
- [{timetrap, ?plt_timeout}].
-init_per_suite(Config) ->
- OutDir = ?config(priv_dir, Config),
- case dialyzer_common:check_plt(OutDir) of
- fail -> {skip, "Plt creation/check failed."};
- ok -> [{dialyzer_options, [{warnings,[race_conditions]}]}|Config]
- end.
-
-end_per_suite(_Config) ->
- ok.
-
-all() ->
- [race_tests_SUITE_consistency,ets_insert_args1,ets_insert_args2,
- ets_insert_args3,ets_insert_args4,ets_insert_args5,ets_insert_args6,
- ets_insert_args7,ets_insert_args8,ets_insert_control_flow1,
- ets_insert_control_flow2,ets_insert_control_flow3,ets_insert_control_flow4,
- ets_insert_control_flow5,ets_insert_diff_atoms_race1,
- ets_insert_diff_atoms_race2,ets_insert_diff_atoms_race3,
- ets_insert_diff_atoms_race4,ets_insert_diff_atoms_race5,
- ets_insert_diff_atoms_race6,ets_insert_double1,ets_insert_double2,
- ets_insert_funs1,ets_insert_funs2,ets_insert_new,ets_insert_param,
- extract_translations,mnesia_diff_atoms_race1,mnesia_diff_atoms_race2,
- mnesia_dirty_read_one_write_two,mnesia_dirty_read_two_write_one,
- mnesia_dirty_read_write_double1,mnesia_dirty_read_write_double2,
- mnesia_dirty_read_write_double3,mnesia_dirty_read_write_double4,
- mnesia_dirty_read_write_one,mnesia_dirty_read_write_two,
- whereis_control_flow1,whereis_control_flow2,whereis_control_flow3,
- whereis_control_flow4,whereis_control_flow5,whereis_control_flow6,
- whereis_diff_atoms_no_race,whereis_diff_atoms_race,whereis_diff_functions1,
- whereis_diff_functions1_nested,whereis_diff_functions1_pathsens,
- whereis_diff_functions1_twice,whereis_diff_functions2,
- whereis_diff_functions2_nested,whereis_diff_functions2_pathsens,
- whereis_diff_functions2_twice,whereis_diff_functions3,
- whereis_diff_functions3_nested,whereis_diff_functions3_pathsens,
- whereis_diff_functions4,whereis_diff_functions5,whereis_diff_functions6,
- whereis_diff_modules1,whereis_diff_modules1_pathsens,
- whereis_diff_modules1_rec,whereis_diff_modules2,
- whereis_diff_modules2_pathsens,whereis_diff_modules2_rec,
- whereis_diff_modules3,whereis_diff_modules_nested,
- whereis_diff_modules_twice,whereis_diff_vars_no_race,
- whereis_diff_vars_race,whereis_intra_inter_module1,
- whereis_intra_inter_module2,whereis_intra_inter_module3,
- whereis_intra_inter_module4,whereis_intra_inter_module5,
- whereis_intra_inter_module6,whereis_intra_inter_module7,
- whereis_intra_inter_module8,whereis_param,whereis_param_inter_module,
- whereis_rec_function1,whereis_rec_function2,whereis_rec_function3,
- whereis_rec_function4,whereis_rec_function5,whereis_rec_function6,
- whereis_rec_function7,whereis_rec_function8,whereis_try_catch,
- whereis_vars1,whereis_vars10,whereis_vars11,whereis_vars12,whereis_vars13,
- whereis_vars14,whereis_vars15,whereis_vars16,whereis_vars17,whereis_vars18,
- whereis_vars19,whereis_vars2,whereis_vars20,whereis_vars21,whereis_vars22,
- whereis_vars3,whereis_vars4,whereis_vars5,whereis_vars6,whereis_vars7,
- whereis_vars8,whereis_vars9].
-
-dialyze(Config, TestCase) ->
- Opts = ?config(dialyzer_options, Config),
- Dir = ?config(data_dir, Config),
- OutDir = ?config(priv_dir, Config),
- dialyzer_common:check(TestCase, Opts, Dir, OutDir).
-
-race_tests_SUITE_consistency(Config) ->
- Dir = ?config(data_dir, Config),
- case dialyzer_common:new_tests(Dir, all()) of
- [] -> ok;
- New -> ct:fail({missing_tests,New})
- end.
-
-ets_insert_args1(Config) ->
- case dialyze(Config, ets_insert_args1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_args2(Config) ->
- case dialyze(Config, ets_insert_args2) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_args3(Config) ->
- case dialyze(Config, ets_insert_args3) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_args4(Config) ->
- case dialyze(Config, ets_insert_args4) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_args5(Config) ->
- case dialyze(Config, ets_insert_args5) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_args6(Config) ->
- case dialyze(Config, ets_insert_args6) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_args7(Config) ->
- case dialyze(Config, ets_insert_args7) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_args8(Config) ->
- case dialyze(Config, ets_insert_args8) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_control_flow1(Config) ->
- case dialyze(Config, ets_insert_control_flow1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_control_flow2(Config) ->
- case dialyze(Config, ets_insert_control_flow2) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_control_flow3(Config) ->
- case dialyze(Config, ets_insert_control_flow3) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_control_flow4(Config) ->
- case dialyze(Config, ets_insert_control_flow4) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_control_flow5(Config) ->
- case dialyze(Config, ets_insert_control_flow5) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_diff_atoms_race1(Config) ->
- case dialyze(Config, ets_insert_diff_atoms_race1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_diff_atoms_race2(Config) ->
- case dialyze(Config, ets_insert_diff_atoms_race2) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_diff_atoms_race3(Config) ->
- case dialyze(Config, ets_insert_diff_atoms_race3) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_diff_atoms_race4(Config) ->
- case dialyze(Config, ets_insert_diff_atoms_race4) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_diff_atoms_race5(Config) ->
- case dialyze(Config, ets_insert_diff_atoms_race5) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_diff_atoms_race6(Config) ->
- case dialyze(Config, ets_insert_diff_atoms_race6) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_double1(Config) ->
- case dialyze(Config, ets_insert_double1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_double2(Config) ->
- case dialyze(Config, ets_insert_double2) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_funs1(Config) ->
- case dialyze(Config, ets_insert_funs1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_funs2(Config) ->
- case dialyze(Config, ets_insert_funs2) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_new(Config) ->
- case dialyze(Config, ets_insert_new) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_insert_param(Config) ->
- case dialyze(Config, ets_insert_param) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-extract_translations(Config) ->
- case dialyze(Config, extract_translations) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-mnesia_diff_atoms_race1(Config) ->
- case dialyze(Config, mnesia_diff_atoms_race1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-mnesia_diff_atoms_race2(Config) ->
- case dialyze(Config, mnesia_diff_atoms_race2) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-mnesia_dirty_read_one_write_two(Config) ->
- case dialyze(Config, mnesia_dirty_read_one_write_two) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-mnesia_dirty_read_two_write_one(Config) ->
- case dialyze(Config, mnesia_dirty_read_two_write_one) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-mnesia_dirty_read_write_double1(Config) ->
- case dialyze(Config, mnesia_dirty_read_write_double1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-mnesia_dirty_read_write_double2(Config) ->
- case dialyze(Config, mnesia_dirty_read_write_double2) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-mnesia_dirty_read_write_double3(Config) ->
- case dialyze(Config, mnesia_dirty_read_write_double3) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-mnesia_dirty_read_write_double4(Config) ->
- case dialyze(Config, mnesia_dirty_read_write_double4) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-mnesia_dirty_read_write_one(Config) ->
- case dialyze(Config, mnesia_dirty_read_write_one) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-mnesia_dirty_read_write_two(Config) ->
- case dialyze(Config, mnesia_dirty_read_write_two) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_control_flow1(Config) ->
- case dialyze(Config, whereis_control_flow1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_control_flow2(Config) ->
- case dialyze(Config, whereis_control_flow2) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_control_flow3(Config) ->
- case dialyze(Config, whereis_control_flow3) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_control_flow4(Config) ->
- case dialyze(Config, whereis_control_flow4) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_control_flow5(Config) ->
- case dialyze(Config, whereis_control_flow5) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_control_flow6(Config) ->
- case dialyze(Config, whereis_control_flow6) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_atoms_no_race(Config) ->
- case dialyze(Config, whereis_diff_atoms_no_race) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_atoms_race(Config) ->
- case dialyze(Config, whereis_diff_atoms_race) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_functions1(Config) ->
- case dialyze(Config, whereis_diff_functions1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_functions1_nested(Config) ->
- case dialyze(Config, whereis_diff_functions1_nested) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_functions1_pathsens(Config) ->
- case dialyze(Config, whereis_diff_functions1_pathsens) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_functions1_twice(Config) ->
- case dialyze(Config, whereis_diff_functions1_twice) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_functions2(Config) ->
- case dialyze(Config, whereis_diff_functions2) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_functions2_nested(Config) ->
- case dialyze(Config, whereis_diff_functions2_nested) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_functions2_pathsens(Config) ->
- case dialyze(Config, whereis_diff_functions2_pathsens) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_functions2_twice(Config) ->
- case dialyze(Config, whereis_diff_functions2_twice) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_functions3(Config) ->
- case dialyze(Config, whereis_diff_functions3) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_functions3_nested(Config) ->
- case dialyze(Config, whereis_diff_functions3_nested) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_functions3_pathsens(Config) ->
- case dialyze(Config, whereis_diff_functions3_pathsens) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_functions4(Config) ->
- case dialyze(Config, whereis_diff_functions4) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_functions5(Config) ->
- case dialyze(Config, whereis_diff_functions5) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_functions6(Config) ->
- case dialyze(Config, whereis_diff_functions6) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_modules1(Config) ->
- case dialyze(Config, whereis_diff_modules1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_modules1_pathsens(Config) ->
- case dialyze(Config, whereis_diff_modules1_pathsens) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_modules1_rec(Config) ->
- case dialyze(Config, whereis_diff_modules1_rec) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_modules2(Config) ->
- case dialyze(Config, whereis_diff_modules2) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_modules2_pathsens(Config) ->
- case dialyze(Config, whereis_diff_modules2_pathsens) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_modules2_rec(Config) ->
- case dialyze(Config, whereis_diff_modules2_rec) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_modules3(Config) ->
- case dialyze(Config, whereis_diff_modules3) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_modules_nested(Config) ->
- case dialyze(Config, whereis_diff_modules_nested) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_modules_twice(Config) ->
- case dialyze(Config, whereis_diff_modules_twice) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_vars_no_race(Config) ->
- case dialyze(Config, whereis_diff_vars_no_race) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_diff_vars_race(Config) ->
- case dialyze(Config, whereis_diff_vars_race) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_intra_inter_module1(Config) ->
- case dialyze(Config, whereis_intra_inter_module1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_intra_inter_module2(Config) ->
- case dialyze(Config, whereis_intra_inter_module2) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_intra_inter_module3(Config) ->
- case dialyze(Config, whereis_intra_inter_module3) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_intra_inter_module4(Config) ->
- case dialyze(Config, whereis_intra_inter_module4) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_intra_inter_module5(Config) ->
- case dialyze(Config, whereis_intra_inter_module5) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_intra_inter_module6(Config) ->
- case dialyze(Config, whereis_intra_inter_module6) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_intra_inter_module7(Config) ->
- case dialyze(Config, whereis_intra_inter_module7) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_intra_inter_module8(Config) ->
- case dialyze(Config, whereis_intra_inter_module8) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_param(Config) ->
- case dialyze(Config, whereis_param) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_param_inter_module(Config) ->
- case dialyze(Config, whereis_param_inter_module) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_rec_function1(Config) ->
- case dialyze(Config, whereis_rec_function1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_rec_function2(Config) ->
- case dialyze(Config, whereis_rec_function2) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_rec_function3(Config) ->
- case dialyze(Config, whereis_rec_function3) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_rec_function4(Config) ->
- case dialyze(Config, whereis_rec_function4) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_rec_function5(Config) ->
- case dialyze(Config, whereis_rec_function5) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_rec_function6(Config) ->
- case dialyze(Config, whereis_rec_function6) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_rec_function7(Config) ->
- case dialyze(Config, whereis_rec_function7) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_rec_function8(Config) ->
- case dialyze(Config, whereis_rec_function8) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_try_catch(Config) ->
- case dialyze(Config, whereis_try_catch) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars1(Config) ->
- case dialyze(Config, whereis_vars1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars10(Config) ->
- case dialyze(Config, whereis_vars10) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars11(Config) ->
- case dialyze(Config, whereis_vars11) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars12(Config) ->
- case dialyze(Config, whereis_vars12) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars13(Config) ->
- case dialyze(Config, whereis_vars13) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars14(Config) ->
- case dialyze(Config, whereis_vars14) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars15(Config) ->
- case dialyze(Config, whereis_vars15) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars16(Config) ->
- case dialyze(Config, whereis_vars16) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars17(Config) ->
- case dialyze(Config, whereis_vars17) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars18(Config) ->
- case dialyze(Config, whereis_vars18) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars19(Config) ->
- case dialyze(Config, whereis_vars19) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars2(Config) ->
- case dialyze(Config, whereis_vars2) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars20(Config) ->
- case dialyze(Config, whereis_vars20) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars21(Config) ->
- case dialyze(Config, whereis_vars21) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars22(Config) ->
- case dialyze(Config, whereis_vars22) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars3(Config) ->
- case dialyze(Config, whereis_vars3) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars4(Config) ->
- case dialyze(Config, whereis_vars4) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars5(Config) ->
- case dialyze(Config, whereis_vars5) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars6(Config) ->
- case dialyze(Config, whereis_vars6) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars7(Config) ->
- case dialyze(Config, whereis_vars7) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars8(Config) ->
- case dialyze(Config, whereis_vars8) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-whereis_vars9(Config) ->
- case dialyze(Config, whereis_vars9) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/results/extract_translations b/lib/dialyzer/test/race_tests_SUITE_data/results/extract_translations
deleted file mode 100644
index f7d5abc6f5..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/results/extract_translations
+++ /dev/null
@@ -1,5 +0,0 @@
-
-extract_translations.erl:140: The call ets:insert('files',{atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('files',File::atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]) call in extract_translations.erl on line 135
-extract_translations.erl:146: The call ets:insert('translations',{_,[]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('translations',Str::any()) call in extract_translations.erl on line 126
-extract_translations.erl:152: The call ets:insert('files',{atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('files',File::atom() | binary() | [atom() | binary() | [atom() | binary() | [any()] | char()] | char()]) call in extract_translations.erl on line 148
-extract_translations.erl:154: The call ets:insert('translations',{_,[]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('translations',Str::any()) call in extract_translations.erl on line 126
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args1.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args1.erl
deleted file mode 100644
index 78b586f097..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args1.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the argument types of the calls.
-
--module(ets_insert_args1).
--export([start/0]).
-
-start() ->
- F = fun(T) -> [{_, N}] = ets:lookup(T, counter),
- ets:insert(T, [{counter, N+1}])
- end,
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {counter, 0}),
- io:format("Inserted ~w\n", [{counter, 0}]),
- F(foo),
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, counter),
- io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args2.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args2.erl
deleted file mode 100644
index 7e53b1e8bf..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args2.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the argument types of the calls.
-
--module(ets_insert_args2).
--export([start/0]).
-
-start() ->
- F = fun(T)-> [{_, N}] = ets:lookup(T, counter),
- ets:insert(T, [{counter, N+1}, {maria, N+1}, {kostis, N+1}])
- end,
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {counter, 0}),
- io:format("Inserted ~w\n", [{counter, 0}]),
- F(foo),
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, counter),
- io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args3.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args3.erl
deleted file mode 100644
index b99bde14fa..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args3.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the argument types of the calls.
-
--module(ets_insert_args3).
--export([start/0]).
-
-start() ->
- F = fun(T)-> [{_, N}] = ets:lookup(T, counter),
- ets:insert(T, [{maria, N+1}, {kostis, N+1}])
- end,
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {counter, 0}),
- io:format("Inserted ~w\n", [{counter, 0}]),
- F(foo),
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, counter),
- io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args4.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args4.erl
deleted file mode 100644
index 7bf3599c65..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args4.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the argument types of the calls.
-
--module(ets_insert_args4).
--export([start/0]).
-
-start() ->
- F = fun(T)-> [{_, N}] = ets:lookup(T, counter),
- ets:insert(T, {counter, N+1})
- end,
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {counter, 0}),
- io:format("Inserted ~w\n", [{counter, 0}]),
- F(foo),
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, counter),
- io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args5.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args5.erl
deleted file mode 100644
index 93fef43cf1..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args5.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the argument types of the calls.
-
--module(ets_insert_args5).
--export([start/0]).
-
-start() ->
- F = fun(T)-> [{_, N}] = ets:lookup(T, counter),
- ets:insert(T, {counter, N+1, N+2})
- end,
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {counter, 0, 0}),
- io:format("Inserted ~w\n", [{counter, 0, 0}]),
- F(foo),
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, counter),
- io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args6.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args6.erl
deleted file mode 100644
index 2a803ccaac..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args6.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the argument types of the calls.
-
--module(ets_insert_args6).
--export([start/0]).
-
-start() ->
- F = fun(T)-> [{_, N}] = ets:lookup(T, counter),
- ets:insert(T, [{counter, N+1, N+2}])
- end,
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {counter, 0, 0}),
- io:format("Inserted ~w\n", [{counter, 0, 0}]),
- F(foo),
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, counter),
- io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args7.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args7.erl
deleted file mode 100644
index adc13703a7..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args7.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the argument types of the calls.
-
--module(ets_insert_args7).
--export([test/0]).
-
-test() ->
- Foo = foo,
- ets:new(Foo, [named_table, public]),
- race(Foo).
-
-race(Tab) ->
- [{_, N}] = ets:lookup(Tab, counter),
- aux(Tab, N).
-
-aux(Table, N) ->
- ets:insert(Table, [{counter, N+1}]).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args8.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args8.erl
deleted file mode 100644
index 832fc2eef1..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_args8.erl
+++ /dev/null
@@ -1,16 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the argument types of the calls.
-
--module(ets_insert_args8).
--export([test/1]).
-
-test(Foo) ->
- ets:new(Foo, [named_table, public]),
- race(Foo).
-
-race(Tab) ->
- [{_, N}] = ets:lookup(Tab, counter),
- aux(Tab, N).
-
-aux(Table, N) ->
- ets:insert(Table, [{counter, N+1}]).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_control_flow1.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_control_flow1.erl
deleted file mode 100644
index 7b56495e47..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_control_flow1.erl
+++ /dev/null
@@ -1,20 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account control flow that might exist.
-
--module(ets_insert_control_flow1).
--export([start/0]).
-
-start() ->
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {random, random:uniform(maria:get_int())}),
- io:format("Inserted ~w\n", [{_, N}] = ets:lookup(foo, random)),
- case (N rem 2 == 0) of
- true ->
- io:format("\nInserted an even number\n", []),
- io:format("\nWill make it odd\n", []),
- ets:insert(foo, {random, N+1});
- false -> ok
- end,
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, random),
- io:format("Random odd integer: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_control_flow2.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_control_flow2.erl
deleted file mode 100644
index 434ca113ee..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_control_flow2.erl
+++ /dev/null
@@ -1,26 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account control flow that might exist.
-
--module(ets_insert_control_flow2).
--export([start/0]).
-
-start() ->
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {random, random:uniform(150)}),
- io:format("Inserted ~w\n", [{_, N}] = ets:lookup(foo, random)),
- case (N rem 2 == 0) of
- true ->
- io:format("\nInserted an even integer\n", []),
- io:format("\nWill make it odd and generate password\n", []),
- ets:insert(foo, [{random, N+1}, {pass, generate_password(N)}]);
- false ->
- io:format("\nInserted an odd integer\n", []),
- io:format("\nWill make it even and generate password\n", []),
- ets:insert(foo, [{random, N+1}, {pass, generate_password(N)}])
- end,
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, pass),
- io:format("New password: ~w\n", [ObjectList]).
-
-generate_password(N) ->
- lists:map(fun (_) -> random:uniform(90)+$\s+1 end, lists:seq(1,N)).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race1.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race1.erl
deleted file mode 100644
index 57022c86d4..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race1.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that the race condition detection between ets:lookup/
-%% ets:insert is robust even when the functions are called with
-%% different atoms as arguments.
-
--module(ets_insert_diff_atoms_race1).
--export([test/0]).
-
-test() ->
- ets:new(foo, [named_table, public]),
- {race(foo), no_race(foo)}.
-
-race(Tab) ->
- [{_, N}] = ets:lookup(Tab, counter),
- aux(Tab, N).
-
-no_race(Tab) ->
- [{_, N}] = ets:lookup(Tab, counter),
- AnotherTab = bar,
- aux(AnotherTab, N).
-
-aux(Table, N) ->
- ets:insert(Table, [{counter, N+1}]).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race2.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race2.erl
deleted file mode 100644
index 233a19087e..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race2.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that the race condition detection between ets:lookup/
-%% ets:insert is robust even when the functions are called with
-%% different atoms as arguments.
-
--module(ets_insert_diff_atoms_race2).
--export([test/0]).
-
-test() ->
- ets:new(foo, [named_table, public]),
- {race(foo, counter), no_race(foo, counter)}.
-
-race(Tab, Counter) ->
- [{_, N}] = ets:lookup(Tab, Counter),
- aux(Tab, Counter, N).
-
-no_race(Tab, Counter) ->
- [{_, N}] = ets:lookup(Tab, Counter),
- AnotherTab = bar,
- aux(AnotherTab, Counter, N).
-
-aux(Table, Counter, N) ->
- ets:insert(Table, [{Counter, N+1}]).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race3.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race3.erl
deleted file mode 100644
index a09e4644f8..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race3.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that the race condition detection between ets:lookup/
-%% ets:insert is robust even when the functions are called with
-%% different atoms as arguments.
-
--module(ets_insert_diff_atoms_race3).
--export([test/0]).
-
-test() ->
- ets:new(foo, [named_table, public]),
- {race(foo), no_race(foo)}.
-
-race(Tab) ->
- [{_, N}] = ets:lookup(Tab, counter),
- aux(Tab, N).
-
-no_race(Tab) ->
- [{_, N}] = ets:lookup(Tab, counter),
- AnotherTab = bar,
- aux(AnotherTab, N).
-
-aux(Table, N) ->
- ets:insert(Table, {counter, N+1}).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race4.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race4.erl
deleted file mode 100644
index d0a3f0a1d1..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race4.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that the race condition detection between ets:lookup/
-%% ets:insert is robust even when the functions are called with
-%% different atoms as arguments.
-
--module(ets_insert_diff_atoms_race4).
--export([test/0]).
-
-test() ->
- ets:new(foo, [named_table, public]),
- {race(foo, counter), no_race(foo, counter)}.
-
-race(Tab, Counter) ->
- [{_, N}] = ets:lookup(Tab, Counter),
- aux(Tab, Counter, N).
-
-no_race(Tab, Counter) ->
- [{_, N}] = ets:lookup(Tab, Counter),
- AnotherTab = bar,
- aux(AnotherTab, Counter, N).
-
-aux(Table, Counter, N) ->
- ets:insert(Table, {Counter, N+1}).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race5.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race5.erl
deleted file mode 100644
index bbccaab94d..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race5.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that the race condition detection between ets:lookup/
-%% ets:insert is robust even when the functions are called with
-%% different atoms as arguments.
-
--module(ets_insert_diff_atoms_race5).
--export([test/0]).
-
-test() ->
- ets:new(foo, [named_table, public]),
- {race(foo, counter), no_race(foo, counter)}.
-
-race(Tab, Counter) ->
- [{_, N}] = ets:lookup(Tab, Counter),
- aux(Tab, Counter, N).
-
-no_race(Tab, Counter) ->
- [{_, N}] = ets:lookup(Tab, Counter),
- AnotherCounter = index,
- aux(Tab, AnotherCounter, N).
-
-aux(Table, Counter, N) ->
- ets:insert(Table, [{Counter, N+1}]).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race6.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race6.erl
deleted file mode 100644
index 17457e2b44..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_diff_atoms_race6.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that the race condition detection between ets:lookup/
-%% ets:insert is robust even when the functions are called with
-%% different atoms as arguments.
-
--module(ets_insert_diff_atoms_race6).
--export([test/0]).
-
-test() ->
- ets:new(foo, [named_table, public]),
- {race(foo, counter), no_race(foo, counter)}.
-
-race(Tab, Counter) ->
- [{_, N}] = ets:lookup(Tab, Counter),
- aux(Tab, Counter, N).
-
-no_race(Tab, Counter) ->
- [{_, N}] = ets:lookup(Tab, Counter),
- AnotherCounter = index,
- aux(Tab, AnotherCounter, N).
-
-aux(Table, Counter, N) ->
- ets:insert(Table, {Counter, N+1}).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_double1.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_double1.erl
deleted file mode 100644
index 92fa945b73..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_double1.erl
+++ /dev/null
@@ -1,28 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account multiple ets:inserts that might exist.
-
--module(ets_insert_double1).
--export([start/0]).
-
-start() ->
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {random, random:uniform(150)}),
- io:format("Inserted ~w\n", [{_, N}] = ets:lookup(foo, random)),
- case (N rem 2 == 0) of
- true ->
- io:format("\nInserted an even integer\n", []),
- io:format("\nWill make it odd and generate new password\n", []),
- ets:insert(foo, [{random, N+1}, {pass, generate_password(N)}]);
- false ->
- io:format("\nInserted an odd integer\n", []),
- io:format("\nWill make it even and generate new password\n", []),
- ets:insert(foo, [{random, N+1}, {pass, generate_password(N)}])
- end,
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, pass),
- io:format("New password: ~w\n", [ObjectList]),
- ets:insert(foo, {pass, 'empty'}).
-
-generate_password(N) ->
- [{_, P}] = ets:lookup(foo, pass),
- lists:map(fun (_) -> random:uniform(90)+P+$\s+1 end, lists:seq(1,N)).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_double2.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_double2.erl
deleted file mode 100644
index dc2b14ada0..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_double2.erl
+++ /dev/null
@@ -1,28 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account multiple ets:inserts that might exist.
-
--module(ets_insert_double2).
--export([start/2]).
-
-start(Random, Pass) ->
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {Random, random:uniform(150)}),
- io:format("Inserted ~w\n", [{_, N}] = ets:lookup(foo, Random)),
- case (N rem 2 == 0) of
- true ->
- io:format("\nInserted an even integer\n", []),
- io:format("\nWill make it odd and generate new password\n", []),
- ets:insert(foo, [{Random, N+1}, {Pass, generate_password(Pass, N)}]);
- false ->
- io:format("\nInserted an odd integer\n", []),
- io:format("\nWill make it even and generate new password\n", []),
- ets:insert(foo, [{Random, N+1}, {Pass, generate_password(Pass, N)}])
- end,
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, Pass),
- io:format("New password: ~w\n", [ObjectList]),
- ets:insert(foo, {Pass, 'empty'}).
-
-generate_password(Pass, N) ->
- [{_, P}] = ets:lookup(foo, Pass),
- lists:map(fun (_) -> random:uniform(90)+P+$\s+1 end, lists:seq(1,N)).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_funs1.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_funs1.erl
deleted file mode 100644
index 4a0a012fe3..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_funs1.erl
+++ /dev/null
@@ -1,18 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the anonymous functions.
-
--module(ets_insert_funs1).
--export([start/0]).
-
-start() ->
- F = fun(T) ->
- ets:lookup(T, counter)
- end,
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {counter, 0}),
- io:format("Inserted ~w\n", [{counter, 0}]),
- [{_, N}] = F(foo),
- ets:insert(foo, [{counter, N+1}]),
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, counter),
- io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_funs2.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_funs2.erl
deleted file mode 100644
index 3abb9f2fca..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/ets_insert_funs2.erl
+++ /dev/null
@@ -1,18 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the anonymous functions.
-
--module(ets_insert_funs2).
--export([start/0]).
-
-start() ->
- F = fun(T, N) ->
- ets:insert(T, [{counter, N+1}])
- end,
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {counter, 0}),
- io:format("Inserted ~w\n", [{counter, 0}]),
- [{_, N}] = ets:lookup(foo, counter),
- F(foo, N),
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, counter),
- io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/extract_translations.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/extract_translations.erl
deleted file mode 100644
index 4bf6f1b198..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/extract_translations.erl
+++ /dev/null
@@ -1,294 +0,0 @@
-%%%----------------------------------------------------------------------
-%%% File : extract_translations.erl
-%%% Author : Sergei Golovan <[email protected]>
-%%% Purpose : Auxiliary tool for interface/messages translators
-%%% Created : 23 Apr 2005 by Sergei Golovan <[email protected]>
-%%% Id : $Id: extract_translations.erl,v 1.1 2009/08/17 09:18:59 maria Exp $
-%%%----------------------------------------------------------------------
-
--module(extract_translations).
--author('[email protected]').
-
--export([start/0]).
-
--define(STATUS_SUCCESS, 0).
--define(STATUS_ERROR, 1).
--define(STATUS_USAGE, 2).
-
--include_lib("kernel/include/file.hrl").
-
-
-start() ->
- ets:new(translations, [named_table, public]),
- ets:new(translations_obsolete, [named_table, public]),
- ets:new(files, [named_table, public]),
- ets:new(vars, [named_table, public]),
- case init:get_plain_arguments() of
- ["-srcmsg2po", Dir, File] ->
- print_po_header(File),
- Status = process(Dir, File, srcmsg2po),
- halt(Status);
- ["-unused", Dir, File] ->
- Status = process(Dir, File, unused),
- halt(Status);
- [Dir, File] ->
- Status = process(Dir, File, used),
- halt(Status);
- _ ->
- print_usage(),
- halt(?STATUS_USAGE)
- end.
-
-
-process(Dir, File, Used) ->
- case load_file(File) of
- {error, Reason} ->
- io:format("~s: ~s~n", [File, file:format_error(Reason)]),
- ?STATUS_ERROR;
- _ ->
- FileList = find_src_files(Dir),
- lists:foreach(
- fun(F) ->
- parse_file(Dir, F, Used)
- end, FileList),
- case Used of
- unused ->
- ets:foldl(fun({Key, _}, _) ->
- io:format("~p~n", [Key])
- end, ok, translations);
- srcmsg2po ->
- ets:foldl(fun({Key, Trans}, _) ->
- print_translation_obsolete(Key, Trans)
- end, ok, translations_obsolete);
- _ ->
- ok
- end,
- ?STATUS_SUCCESS
- end.
-
-parse_file(Dir, File, Used) ->
- ets:delete_all_objects(vars),
- case epp:parse_file(File, [Dir, filename:dirname(File) | code:get_path()], []) of
- {ok, Forms} ->
- lists:foreach(
- fun(F) ->
- parse_form(Dir, File, F, Used)
- end, Forms);
- _ ->
- ok
- end.
-
-parse_form(Dir, File, Form, Used) ->
- case Form of
- %%{undefined, Something} ->
- %% io:format("Undefined: ~p~n", [Something]);
- {call,
- _,
- {remote, _, {atom, _, translate}, {atom, _, translate}},
- [_, {string, Line, Str}]
- } ->
- process_string(Dir, File, Line, Str, Used);
- {call,
- _,
- {remote, _, {atom, _, translate}, {atom, _, translate}},
- [_, {var, _, Name}]
- } ->
- case ets:lookup(vars, Name) of
- [{_Name, Value, Line}] ->
- process_string(Dir, File, Line, Value, Used);
- _ ->
- ok
- end;
- {match,
- _,
- {var, _, Name},
- {string, Line, Value}
- } ->
- ets:insert(vars, {Name, Value, Line});
- L when is_list(L) ->
- lists:foreach(
- fun(F) ->
- parse_form(Dir, File, F, Used)
- end, L);
- T when is_tuple(T) ->
- lists:foreach(
- fun(F) ->
- parse_form(Dir, File, F, Used)
- end, tuple_to_list(T));
- _ ->
- ok
- end.
-
-process_string(_Dir, _File, _Line, "", _Used) ->
- ok;
-
-process_string(_Dir, File, Line, Str, Used) ->
- case {ets:lookup(translations, Str), Used} of
- {[{_Key, _Trans}], unused} ->
- ets:delete(translations, Str);
- {[{_Key, _Trans}], used} ->
- ok;
- {[{_Key, Trans}], srcmsg2po} ->
- ets:delete(translations_obsolete, Str),
- print_translation(File, Line, Str, Trans);
- {_, used} ->
- case ets:lookup(files, File) of
- [{_}] ->
- ok;
- _ ->
- io:format("~n% ~s~n", [File]),
- ets:insert(files, {File})
- end,
- case Str of
- [] -> ok;
- _ -> io:format("{~p, \"\"}.~n", [Str])
- end,
- ets:insert(translations, {Str, ""});
- {_, srcmsg2po} ->
- case ets:lookup(files, File) of
- [{_}] ->
- ok;
- _ ->
- ets:insert(files, {File})
- end,
- ets:insert(translations, {Str, ""}),
- print_translation(File, Line, Str, "");
- _ ->
- ok
- end.
-
-load_file(File) ->
- case file:consult(File) of
- {ok, Terms} ->
- lists:foreach(
- fun({Orig, Trans}) ->
- case Trans of
- "" ->
- ok;
- _ ->
- ets:insert(translations, {Orig, Trans}),
- ets:insert(translations_obsolete, {Orig, Trans})
- end
- end, Terms);
- Err ->
- Err
- end.
-
-find_src_files(Dir) ->
- case file:list_dir(Dir) of
- {ok, FileList} ->
- recurse_filelist(
- lists:map(
- fun(F) ->
- filename:join(Dir, F)
- end, FileList));
- _ ->
- []
- end.
-
-recurse_filelist(FileList) ->
- recurse_filelist(FileList, []).
-
-recurse_filelist([], Acc) ->
- lists:reverse(Acc);
-
-recurse_filelist([H | T], Acc) ->
- case file:read_file_info(H) of
- {ok, #file_info{type = directory}} ->
- recurse_filelist(T, lists:reverse(find_src_files(H)) ++ Acc);
- {ok, #file_info{type = regular}} ->
- case string:substr(H, string:len(H) - 3) of
- ".erl" ->
- recurse_filelist(T, [H | Acc]);
- ".hrl" ->
- recurse_filelist(T, [H | Acc]);
- _ ->
- recurse_filelist(T, Acc)
- end;
- _ ->
- recurse_filelist(T, Acc)
- end.
-
-
-print_usage() ->
- io:format(
- "Usage: extract_translations [-unused] dir file~n"
- "~n"
- "Example:~n"
- " extract_translations . ./msgs/ru.msg~n"
- ).
-
-
-%%%
-%%% Gettext
-%%%
-
-print_po_header(File) ->
- MsgProps = get_msg_header_props(File),
- {Language, [LastT | AddT]} = prepare_props(MsgProps),
- application:load(ejabberd),
- {ok, Version} = application:get_key(ejabberd, vsn),
- print_po_header(Version, Language, LastT, AddT).
-
-get_msg_header_props(File) ->
- {ok, F} = file:open(File, [read]),
- Lines = get_msg_header_props(F, []),
- file:close(F),
- Lines.
-
-get_msg_header_props(F, Lines) ->
- String = io:get_line(F, ""),
- case io_lib:fread("% ", String) of
- {ok, [], RemString} ->
- case io_lib:fread("~s", RemString) of
- {ok, [Key], Value} when Value /= "\n" ->
- %% The first character in Value is a blankspace:
- %% And the last characters are 'slash n'
- ValueClean = string:substr(Value, 2, string:len(Value)-2),
- get_msg_header_props(F, Lines ++ [{Key, ValueClean}]);
- _ ->
- get_msg_header_props(F, Lines)
- end;
- _ ->
- Lines
- end.
-
-prepare_props(MsgProps) ->
- Language = proplists:get_value("Language:", MsgProps),
- Authors = proplists:get_all_values("Author:", MsgProps),
- {Language, Authors}.
-
-print_po_header(Version, Language, LastTranslator, AdditionalTranslatorsList) ->
- AdditionalTranslatorsString = build_additional_translators(AdditionalTranslatorsList),
- HeaderString =
- "msgid \"\"\n"
- "msgstr \"\"\n"
- "\"Project-Id-Version: " ++ Version ++ "\\n\"\n"
- ++ "\"X-Language: " ++ Language ++ "\\n\"\n"
- "\"Last-Translator: " ++ LastTranslator ++ "\\n\"\n"
- ++ AdditionalTranslatorsString ++
- "\"MIME-Version: 1.0\\n\"\n"
- "\"Content-Type: text/plain; charset=UTF-8\\n\"\n"
- "\"Content-Transfer-Encoding: 8bit\\n\"\n",
- io:format("~s~n", [HeaderString]).
-
-build_additional_translators(List) ->
- lists:foldl(
- fun(T, Str) ->
- Str ++ "\"X-Additional-Translator: " ++ T ++ "\\n\"\n"
- end,
- "",
- List).
-
-print_translation(File, Line, Str, StrT) ->
- {ok, StrQ, _} = regexp:gsub(Str, "\"", "\\\""),
- {ok, StrTQ, _} = regexp:gsub(StrT, "\"", "\\\""),
- io:format("#: ~s:~p~nmsgid \"~s\"~nmsgstr \"~s\"~n~n", [File, Line, StrQ, StrTQ]).
-
-print_translation_obsolete(Str, StrT) ->
- File = "unknown.erl",
- Line = 1,
- {ok, StrQ, _} = regexp:gsub(Str, "\"", "\\\""),
- {ok, StrTQ, _} = regexp:gsub(StrT, "\"", "\\\""),
- io:format("#: ~s:~p~n#~~ msgid \"~s\"~n#~~ msgstr \"~s\"~n~n", [File, Line, StrQ, StrTQ]).
-
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_diff_atoms_race1.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_diff_atoms_race1.erl
deleted file mode 100644
index 74d17aab0c..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_diff_atoms_race1.erl
+++ /dev/null
@@ -1,33 +0,0 @@
-%% This tests that the race condition detection between mnesia:dirty_read/
-%% mnesia:dirty_write is robust even when the functions are called with
-%% different atoms as arguments.
-
--module(mnesia_diff_atoms_race1).
--export([test/2]).
-
--record(employee, {emp_no,
- name,
- salary,
- sex,
- phone,
- room_no}).
-
-test(Eno, Raise) ->
- {race(employee, Eno, Raise), no_race(employee, Eno, Raise)}.
-
-race(Tab, Eno, Raise) ->
- [E] = mnesia:dirty_read(Tab, Eno),
- Salary = E#employee.salary + Raise,
- New = E#employee{salary = Salary},
- aux(Tab, New).
-
-no_race(Tab, Eno, Raise) ->
- [E] = mnesia:dirty_read(Tab, Eno),
- Salary = E#employee.salary + Raise,
- New = E#employee{salary = Salary},
- AnotherTab = employer,
- aux(AnotherTab, New).
-
-
-aux(Table, Record) ->
- mnesia:dirty_write(Table, Record).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_diff_atoms_race2.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_diff_atoms_race2.erl
deleted file mode 100644
index e92405a673..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_diff_atoms_race2.erl
+++ /dev/null
@@ -1,37 +0,0 @@
-%% This tests that the race condition detection between mnesia:dirty_read/
-%% mnesia:dirty_write is robust even when the functions are called with
-%% different atoms as arguments.
-
--module(mnesia_diff_atoms_race2).
--export([test/2]).
-
--record(employee, {emp_no,
- name,
- salary,
- sex,
- phone,
- room_no}).
-
--record(employer, {emp_no,
- name,
- salary,
- sex,
- phone,
- room_no}).
-
-test(Eno, Raise) ->
- {race(employee, Eno, Raise), no_race(employee, Eno, Raise)}.
-
-race(Tab, Eno, Raise) ->
- [E] = mnesia:dirty_read(Tab, Eno),
- Salary = E#employee.salary + Raise,
- New = E#employee{salary = Salary},
- aux(New).
-
-no_race(Tab, Eno, Raise) ->
- [E] = mnesia:dirty_read(Tab, Eno),
- AnotherRecord = #employer{},
- aux(AnotherRecord).
-
-aux(Record) ->
- mnesia:dirty_write(Record).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_one_write_two.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_one_write_two.erl
deleted file mode 100644
index 81e460be45..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_one_write_two.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests the presence of possible races due to an mnesia:dirty_read/
-%% mnesia:dirty_write combination. It takes into account the argument types
-%% of the calls.
-
--module(mnesia_dirty_read_one_write_two).
--export([raise/2]).
-
--record(employee, {emp_no,
- name,
- salary,
- sex,
- phone,
- room_no}).
-
-
-raise(Eno, Raise) ->
- [E] = mnesia:dirty_read({employee, Eno}),
- Salary = E#employee.salary + Raise,
- New = E#employee{salary = Salary},
- mnesia:dirty_write(employee, New).
-
-
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_two_write_one.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_two_write_one.erl
deleted file mode 100644
index 515e9f11de..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_two_write_one.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests the presence of possible races due to an mnesia:dirty_read/
-%% mnesia:dirty_write combination. It takes into account the argument types
-%% of the calls.
-
--module(mnesia_dirty_read_two_write_one).
--export([raise/2]).
-
--record(employee, {emp_no,
- name,
- salary,
- sex,
- phone,
- room_no}).
-
-
-raise(Eno, Raise) ->
- [E] = mnesia:dirty_read(employee, Eno),
- Salary = E#employee.salary + Raise,
- New = E#employee{salary = Salary},
- mnesia:dirty_write(New).
-
-
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_one.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_one.erl
deleted file mode 100644
index 7ff546a9ea..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_one.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests the presence of possible races due to an mnesia:dirty_read/
-%% mnesia:dirty_write combination. It takes into account the argument types
-%% of the calls.
-
--module(mnesia_dirty_read_write_one).
--export([raise/2]).
-
--record(employee, {emp_no,
- name,
- salary,
- sex,
- phone,
- room_no}).
-
-
-raise(Eno, Raise) ->
- [E] = mnesia:dirty_read({employee, Eno}),
- Salary = E#employee.salary + Raise,
- New = E#employee{salary = Salary},
- mnesia:dirty_write(New).
-
-
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_two.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_two.erl
deleted file mode 100644
index 10952ac86d..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/mnesia_dirty_read_write_two.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests the presence of possible races due to an mnesia:dirty_read/
-%% mnesia:dirty_write combination. It takes into account the argument types
-%% of the calls.
-
--module(mnesia_dirty_read_write_two).
--export([raise/2]).
-
--record(employee, {emp_no,
- name,
- salary,
- sex,
- phone,
- room_no}).
-
-
-raise(Eno, Raise) ->
- [E] = mnesia:dirty_read(employee, Eno),
- Salary = E#employee.salary + Raise,
- New = E#employee{salary = Salary},
- mnesia:dirty_write(employee, New).
-
-
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow3.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow3.erl
deleted file mode 100644
index 87b2976165..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow3.erl
+++ /dev/null
@@ -1,25 +0,0 @@
-%% This tests the presence of possible races due to a whereis/register
-%% combination. It takes into account control flow that might exist.
-
--module(whereis_control_flow3).
--export([start/3]).
-
-start(AnAtom, Fun, FunName) ->
- Pid =
- case FunName of
- master ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end;
- slave ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end
- end,
- register(AnAtom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow4.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow4.erl
deleted file mode 100644
index 9292006fa8..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_control_flow4.erl
+++ /dev/null
@@ -1,29 +0,0 @@
-%% This tests the presence of possible races due to a whereis/register
-%% combination. It takes into account control flow that might exist.
-
--module(whereis_control_flow4).
--export([start/1]).
-
-start(Fun) ->
- case whereis(maria) of
- undefined ->
- Pid1 = spawn(Fun),
- case Pid1 =:= self() of
- true ->
- case whereis(kostis) of
- undefined ->
- Pid2 = spawn(Fun),
- case Pid2 =:= self() of
- true ->
- register(maria, Pid1),
- register(kostis, Pid2);
- false -> ok
- end;
- P when is_pid(P) ->
- ok
- end;
- false -> ok
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_atoms_no_race.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_atoms_no_race.erl
deleted file mode 100644
index dcadcb3683..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_atoms_no_race.erl
+++ /dev/null
@@ -1,24 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust even when the functions are called with different atoms
-%% as arguments.
-
--module(whereis_diff_atoms_no_race).
--export([test/0]).
-
-test() ->
- Fun = fun () -> foo end,
- {no_race(maria, Fun)}.
-
-no_race(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- AnotherAtom = kostis,
- aux(AnotherAtom, Pid);
- P when is_pid(P) ->
- ok
- end.
-
-aux(Atom, Pid) ->
- register(Atom, Pid).
-
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_atoms_race.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_atoms_race.erl
deleted file mode 100644
index 7e302247f8..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_atoms_race.erl
+++ /dev/null
@@ -1,35 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust even when the functions are called with different atoms
-%% as arguments.
-
--module(whereis_diff_atoms_race).
--export([test/0]). %, race/1, no_race/1]).
-
-test() ->
- Fun = fun () -> foo end,
- {race(maria, Fun), no_race(maria, Fun)}.
-
-race(AnAtom, Fun) ->
- %AnAtom = maria,
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- aux(AnAtom, Pid);
- P when is_pid(P) ->
- ok
- end.
-
-no_race(AnAtom, Fun) ->
- %AnAtom = maria,
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- AnotherAtom = kostis,
- aux(AnotherAtom, Pid);
- P when is_pid(P) ->
- ok
- end.
-
-aux(Atom, Pid) ->
- register(Atom, Pid).
-
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions1_nested.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions1_nested.erl
deleted file mode 100644
index 0a77c78ba3..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions1_nested.erl
+++ /dev/null
@@ -1,23 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-
--module(whereis_diff_functions1_nested).
--export([test/2]).
-
-test(AnAtom, Fun) ->
- start(AnAtom, Fun).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- race1(AnAtom, Pid);
- P when is_pid(P) ->
- true
- end.
-
-race1(Atom, Pid) ->
- race2(Atom, Pid).
-
-race2(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions1_pathsens.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions1_pathsens.erl
deleted file mode 100644
index 53955a7fa1..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions1_pathsens.erl
+++ /dev/null
@@ -1,32 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-%% It takes into account control flow that might exist.
-
--module(whereis_diff_functions1_pathsens).
--export([test/1]).
-
-test(FunName) ->
- start(kostis, mod:function(), FunName).
-
-start(AnAtom, Fun, FunName) ->
- Pid =
- case FunName of
- master ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end;
- slave ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end
- end,
- race(AnAtom, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions1_twice.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions1_twice.erl
deleted file mode 100644
index 2e87caff4f..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions1_twice.erl
+++ /dev/null
@@ -1,30 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having multiple calls in separate functions.
-
--module(whereis_diff_functions1_twice).
--export([test/2]).
-
-test(AnAtom, Fun) ->
- start(AnAtom, Fun).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid1 = spawn(Fun),
- race(AnAtom, Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- race_again(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end;
- P when is_pid(P) ->
- true
- end.
-
-race(Atom, Pid) ->
- register(Atom, Pid).
-
-race_again(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions2.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions2.erl
deleted file mode 100644
index 1ec8d194be..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions2.erl
+++ /dev/null
@@ -1,25 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-
--module(whereis_diff_functions2).
--export([test/0]).
-
-test() ->
- start(kostis, mod:function()).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- race(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end.
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions2_nested.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions2_nested.erl
deleted file mode 100644
index 415f73d555..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions2_nested.erl
+++ /dev/null
@@ -1,20 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-
--module(whereis_diff_functions2_nested).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- race1(AnAtom, Pid);
- P when is_pid(P) ->
- true
- end.
-
-race1(Atom, Pid) ->
- race2(Atom, Pid).
-
-race2(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions2_pathsens.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions2_pathsens.erl
deleted file mode 100644
index cbd9a7d016..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions2_pathsens.erl
+++ /dev/null
@@ -1,29 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-%% It takes into account control flow that might exist.
-
--module(whereis_diff_functions2_pathsens).
--export([race/4]).
-
-start(AnAtom, Fun, FunName) ->
- Pid =
- case FunName of
- master ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end;
- slave ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end
- end.
-
-race(Atom, Fun, FunName, Pid) ->
- start(Atom, Fun, FunName),
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions2_twice.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions2_twice.erl
deleted file mode 100644
index d8e4987758..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions2_twice.erl
+++ /dev/null
@@ -1,27 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having multiple calls in separate functions.
-
--module(whereis_diff_functions2_twice).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid1 = spawn(Fun),
- race(AnAtom, Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- race_again(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end;
- P when is_pid(P) ->
- true
- end.
-
-race(Atom, Pid) ->
- register(Atom, Pid).
-
-race_again(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions3.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions3.erl
deleted file mode 100644
index 7d4e0905ef..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions3.erl
+++ /dev/null
@@ -1,11 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-
--module(whereis_diff_functions3).
--export([start/1]).
-
-start(AnAtom) ->
- register(AnAtom, race(AnAtom)).
-
-race(Atom) ->
- whereis(Atom).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions3_nested.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions3_nested.erl
deleted file mode 100644
index b4129dc83b..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions3_nested.erl
+++ /dev/null
@@ -1,21 +0,0 @@
-%% This tests that the race condition detection between whereis/unregister
-%% is robust w.r.t. having the calls in separate functions.
-
--module(whereis_diff_functions3_nested).
--export([test/1]).
-
-test(AnAtom) ->
- start(AnAtom).
-
-start(AnAtom) ->
- case whereis(AnAtom) of
- undefined -> true;
- P when is_pid(P) ->
- race1(AnAtom)
- end.
-
-race1(Atom) ->
- race2(Atom).
-
-race2(Atom) ->
- unregister(Atom).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions3_pathsens.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions3_pathsens.erl
deleted file mode 100644
index f06e43024b..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions3_pathsens.erl
+++ /dev/null
@@ -1,29 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-%% It takes into account control flow that might exist.
-
--module(whereis_diff_functions3_pathsens).
--export([start/3]).
-
-start(AnAtom, Fun, FunName) ->
- Pid =
- case FunName of
- master ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end;
- slave ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end
- end,
- race(AnAtom, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions4.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions4.erl
deleted file mode 100644
index 334485921c..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions4.erl
+++ /dev/null
@@ -1,32 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-
--module(whereis_diff_functions4).
--export([test/2]).
-
-test(AnAtom, Fun) ->
- start(AnAtom, Fun).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- race(AnAtom, Pid2),
- case whereis(AnAtom) of
- undefined ->
- Pid3 = spawn(Fun),
- race(AnAtom, Pid3);
- P when is_pid(P) ->
- true
- end;
- P when is_pid(P) ->
- true
- end.
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions5.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions5.erl
deleted file mode 100644
index b4459273f9..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions5.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-
--module(whereis_diff_functions5).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- race(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end.
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions6.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions6.erl
deleted file mode 100644
index ccf0f5e127..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_functions6.erl
+++ /dev/null
@@ -1,29 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-
--module(whereis_diff_functions6).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- race(AnAtom, Pid2),
- case whereis(AnAtom) of
- undefined ->
- Pid3 = spawn(Fun),
- race(AnAtom, Pid3);
- P when is_pid(P) ->
- true
- end;
- P when is_pid(P) ->
- true
- end.
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules2.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules2.erl
deleted file mode 100644
index dabb7fd2da..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules2.erl
+++ /dev/null
@@ -1,11 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules.
-
--module(whereis_diff_modules2).
--export([no_race/1, race/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules1_pathsens.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules1_pathsens.erl
deleted file mode 100644
index 3dbb645e65..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules1_pathsens.erl
+++ /dev/null
@@ -1,26 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules (backward analysis).
-%% It takes into account control flow that might exist.
-
--module(whereis_diff_modules1_pathsens).
--export([start/3]).
-
-start(AnAtom, Fun, FunName) ->
- Pid =
- case FunName of
- master ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end;
- slave ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end
- end,
- whereis_diff_modules2_pathsens:race(AnAtom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules2_pathsens.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules2_pathsens.erl
deleted file mode 100644
index 99331b81b1..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules2_pathsens.erl
+++ /dev/null
@@ -1,12 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules (backward analysis).
-%% It takes into account control flow that might exist.
-
--module(whereis_diff_modules2_pathsens).
--export([no_race/1, race/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules4.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules4.erl
deleted file mode 100644
index 6ab9a4d824..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules4.erl
+++ /dev/null
@@ -1,11 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules.
-
--module(whereis_diff_modules4).
--export([no_race/1, race/1]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom) ->
- whereis(Atom).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules3_pathsens.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules3_pathsens.erl
deleted file mode 100644
index 1eaa954fa1..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules3_pathsens.erl
+++ /dev/null
@@ -1,25 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules (forward analysis).
-%% It takes into account control flow that might exist.
-
--module(whereis_diff_modules3_pathsens).
--export([start/3]).
-
-start(AnAtom, Fun, FunName) ->
- Pid =
- case FunName of
- master ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end;
- slave ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end
- end.
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules4_pathsens.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules4_pathsens.erl
deleted file mode 100644
index f23a63c8f0..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules4_pathsens.erl
+++ /dev/null
@@ -1,13 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules (forward analysis).
-%% It takes into account control flow that might exist.
-
--module(whereis_diff_modules4_pathsens).
--export([no_race/1, race/4]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Fun, FunName, Pid) ->
- whereis_diff_modules3_pathsens:start(Atom, Fun, FunName),
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules6.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules6.erl
deleted file mode 100644
index ec6c245c9a..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules6.erl
+++ /dev/null
@@ -1,11 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules.
-
--module(whereis_diff_modules6).
--export([no_race/1, race/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules2_nested.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules2_nested.erl
deleted file mode 100644
index 4b4c058884..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules2_nested.erl
+++ /dev/null
@@ -1,11 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules.
-
--module(whereis_diff_modules2_nested).
--export([no_race/1, race/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- whereis_diff_modules3_nested:race(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules3_nested.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules3_nested.erl
deleted file mode 100644
index 5412660b16..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules3_nested.erl
+++ /dev/null
@@ -1,11 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules.
-
--module(whereis_diff_modules3_nested).
--export([no_race/1, race/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules2_twice.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules2_twice.erl
deleted file mode 100644
index afe5214648..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules2_twice.erl
+++ /dev/null
@@ -1,11 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules.
-
--module(whereis_diff_modules2_twice).
--export([race/2, race_again/2]).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
-
-race_again(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_vars_no_race.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_vars_no_race.erl
deleted file mode 100644
index 16f1d91490..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_vars_no_race.erl
+++ /dev/null
@@ -1,13 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust even when the functions are called with different variables
-%% as arguments.
-
--module(whereis_diff_vars_no_race).
--export([test/3]).
-
-test(AnAtom, AnotherAtom, Pid) ->
- {aux(AnAtom, Pid), aux(AnotherAtom, Pid)}.
-
-aux(Atom, Pid) ->
- register(Atom, Pid),
- whereis(Atom).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_vars_race.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_vars_race.erl
deleted file mode 100644
index 7382d184dc..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_diff_vars_race.erl
+++ /dev/null
@@ -1,19 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust even when the functions are called with different variables
-%% as arguments.
-
--module(whereis_diff_vars_race).
--export([test/2]).
-
-test(AnAtom, AnotherAtom) ->
- Fun = fun () -> foo end,
- {aux(AnAtom, AnotherAtom, Fun), aux(AnotherAtom, AnAtom, Fun)}.
-
-aux(Atom1, Atom2, Fun) ->
- case whereis(Atom1) of
- undefined ->
- Pid = spawn(Fun),
- register(Atom2, Pid);
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module2.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module2.erl
deleted file mode 100644
index cc2efbecd0..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module2.erl
+++ /dev/null
@@ -1,11 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module2).
--export([no_race/1, race/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module4.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module4.erl
deleted file mode 100644
index 9769f312a8..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module4.erl
+++ /dev/null
@@ -1,14 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module4).
--export([no_race/1, race/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- continue(Atom, Pid).
-
-continue(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module6.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module6.erl
deleted file mode 100644
index 92a589f97f..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module6.erl
+++ /dev/null
@@ -1,14 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module6).
--export([no_race/1, race/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- continue(Atom, Pid).
-
-continue(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module12.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module12.erl
deleted file mode 100644
index 2160780d8e..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module12.erl
+++ /dev/null
@@ -1,14 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module12).
--export([no_race/1, race/2, continue/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- continue(Atom, Pid).
-
-continue(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module14.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module14.erl
deleted file mode 100644
index 2de6c91985..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module14.erl
+++ /dev/null
@@ -1,23 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module14).
--export([no_race/1, race/2, start/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- race(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end.
-
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module16.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module16.erl
deleted file mode 100644
index 6c170dc851..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module16.erl
+++ /dev/null
@@ -1,23 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module16).
--export([no_race/1, race/2, start/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- whereis_intra_inter_module15:continue(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end.
-
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module1.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module1.erl
deleted file mode 100644
index ab7c9b4cf9..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module1.erl
+++ /dev/null
@@ -1,9 +0,0 @@
-%% This tests the presence of possible races due to a whereis/register
-%% combination in higher order functions and inter-module calls.
-
--module(whereis_param_inter_module1).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- register(AnAtom, whereis_param_inter_module2:continue(AnAtom, Fun)).
-
diff --git a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_try_catch.erl b/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_try_catch.erl
deleted file mode 100644
index 9c8daf8d8c..0000000000
--- a/lib/dialyzer/test/race_tests_SUITE_data/src/whereis_try_catch.erl
+++ /dev/null
@@ -1,25 +0,0 @@
-% This tests that warnings do appear when a whereis/register combination
-% is handled by try/catch.
-
--module(whereis_try_catch).
--export([race/1, no_race/1]).
-
-race(Pid) ->
- case whereis(master) of
- undefined ->
- try
- io:format("exception", [])
- catch
- _ -> register(master, Pid)
- end
- end.
-
-no_race(Pid) ->
- case whereis(master) of
- undefined ->
- try
- register(master, Pid)
- catch
- _ -> io:format("exception", [])
- end
- end.
diff --git a/lib/dialyzer/test/remake b/lib/dialyzer/test/remake
deleted file mode 100755
index 654bdd9e88..0000000000
--- a/lib/dialyzer/test/remake
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-erlc +warn_exported_vars +warn_unused_import +warn_untyped_record +warn_missing_spec dialyzer_common.erl file_utils.erl
-if [ -n "$1" ]; then
- erl -noshell -run dialyzer_common create_suite "$1" -s erlang halt
-else
- erl -noshell -run dialyzer_common create_all_suites -s erlang halt
-fi
-rm dialyzer_common.beam file_utils.beam \ No newline at end of file
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/dialyzer_options b/lib/dialyzer/test/small_SUITE_data/dialyzer_options
index 50991c9bc5..50991c9bc5 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/dialyzer_options
+++ b/lib/dialyzer/test/small_SUITE_data/dialyzer_options
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/andalso_test b/lib/dialyzer/test/small_SUITE_data/results/andalso_test
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/andalso_test
+++ b/lib/dialyzer/test/small_SUITE_data/results/andalso_test
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/app_call b/lib/dialyzer/test/small_SUITE_data/results/app_call
index cc1a63f944..cc1a63f944 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/app_call
+++ b/lib/dialyzer/test/small_SUITE_data/results/app_call
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/appmon_place b/lib/dialyzer/test/small_SUITE_data/results/appmon_place
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/appmon_place
+++ b/lib/dialyzer/test/small_SUITE_data/results/appmon_place
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/areq b/lib/dialyzer/test/small_SUITE_data/results/areq
index dd91f2d2bf..dd91f2d2bf 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/areq
+++ b/lib/dialyzer/test/small_SUITE_data/results/areq
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/atom_call b/lib/dialyzer/test/small_SUITE_data/results/atom_call
index 851bb7ab12..851bb7ab12 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/atom_call
+++ b/lib/dialyzer/test/small_SUITE_data/results/atom_call
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/atom_widen b/lib/dialyzer/test/small_SUITE_data/results/atom_widen
index 6d0a7b2737..6d0a7b2737 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/atom_widen
+++ b/lib/dialyzer/test/small_SUITE_data/results/atom_widen
diff --git a/lib/dialyzer/test/small_SUITE_data/results/blame_contract_range b/lib/dialyzer/test/small_SUITE_data/results/blame_contract_range
new file mode 100644
index 0000000000..0c1c58ac8e
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/blame_contract_range
@@ -0,0 +1,4 @@
+
+blame_contract_range.erl:11: Function foo/0 has no local return
+blame_contract_range.erl:14: The contract blame_contract_range:bar(atom()) -> 'a' cannot be right because the inferred return for bar('b') on line 12 is 'b'
+blame_contract_range.erl:15: The pattern 'a' can never match the type 'b'
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/bs_fail_constr b/lib/dialyzer/test/small_SUITE_data/results/bs_fail_constr
index dbc8241971..dbc8241971 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/bs_fail_constr
+++ b/lib/dialyzer/test/small_SUITE_data/results/bs_fail_constr
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/bs_utf8 b/lib/dialyzer/test/small_SUITE_data/results/bs_utf8
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/bs_utf8
+++ b/lib/dialyzer/test/small_SUITE_data/results/bs_utf8
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/cerl_hipeify b/lib/dialyzer/test/small_SUITE_data/results/cerl_hipeify
index 87bf6f309f..87bf6f309f 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/cerl_hipeify
+++ b/lib/dialyzer/test/small_SUITE_data/results/cerl_hipeify
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/comm_layer b/lib/dialyzer/test/small_SUITE_data/results/comm_layer
index cb4bf14eb4..cb4bf14eb4 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/comm_layer
+++ b/lib/dialyzer/test/small_SUITE_data/results/comm_layer
diff --git a/lib/dialyzer/test/small_SUITE_data/results/common_eunit b/lib/dialyzer/test/small_SUITE_data/results/common_eunit
new file mode 100644
index 0000000000..bb5fd1c9ac
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/common_eunit
@@ -0,0 +1,2 @@
+
+common_eunit.erl:57: The created fun has no local return
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/compare1 b/lib/dialyzer/test/small_SUITE_data/results/compare1
index f0d696ffcb..f0d696ffcb 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/compare1
+++ b/lib/dialyzer/test/small_SUITE_data/results/compare1
diff --git a/lib/dialyzer/test/small_SUITE_data/results/comparisons b/lib/dialyzer/test/small_SUITE_data/results/comparisons
new file mode 100644
index 0000000000..642585d25e
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/comparisons
@@ -0,0 +1,153 @@
+
+comparisons.erl:100: The pattern 'true' can never match the type 'false'
+comparisons.erl:101: The pattern 'true' can never match the type 'false'
+comparisons.erl:102: The pattern 'false' can never match the type 'true'
+comparisons.erl:103: The pattern 'false' can never match the type 'true'
+comparisons.erl:104: The pattern 'true' can never match the type 'false'
+comparisons.erl:105: The pattern 'true' can never match the type 'false'
+comparisons.erl:107: The pattern 'true' can never match the type 'false'
+comparisons.erl:108: The pattern 'true' can never match the type 'false'
+comparisons.erl:109: The pattern 'false' can never match the type 'true'
+comparisons.erl:110: The pattern 'false' can never match the type 'true'
+comparisons.erl:111: The pattern 'true' can never match the type 'false'
+comparisons.erl:112: The pattern 'true' can never match the type 'false'
+comparisons.erl:113: The pattern 'false' can never match the type 'true'
+comparisons.erl:114: The pattern 'false' can never match the type 'true'
+comparisons.erl:115: The pattern 'true' can never match the type 'false'
+comparisons.erl:116: The pattern 'true' can never match the type 'false'
+comparisons.erl:117: The pattern 'false' can never match the type 'true'
+comparisons.erl:118: The pattern 'false' can never match the type 'true'
+comparisons.erl:123: The pattern 'false' can never match the type 'true'
+comparisons.erl:124: The pattern 'false' can never match the type 'true'
+comparisons.erl:125: The pattern 'true' can never match the type 'false'
+comparisons.erl:126: The pattern 'true' can never match the type 'false'
+comparisons.erl:127: The pattern 'false' can never match the type 'true'
+comparisons.erl:128: The pattern 'false' can never match the type 'true'
+comparisons.erl:129: The pattern 'true' can never match the type 'false'
+comparisons.erl:130: The pattern 'true' can never match the type 'false'
+comparisons.erl:132: The pattern 'true' can never match the type 'false'
+comparisons.erl:133: The pattern 'true' can never match the type 'false'
+comparisons.erl:134: The pattern 'false' can never match the type 'true'
+comparisons.erl:135: The pattern 'false' can never match the type 'true'
+comparisons.erl:136: The pattern 'true' can never match the type 'false'
+comparisons.erl:137: The pattern 'true' can never match the type 'false'
+comparisons.erl:138: The pattern 'false' can never match the type 'true'
+comparisons.erl:139: The pattern 'false' can never match the type 'true'
+comparisons.erl:140: The pattern 'true' can never match the type 'false'
+comparisons.erl:141: The pattern 'true' can never match the type 'false'
+comparisons.erl:142: The pattern 'false' can never match the type 'true'
+comparisons.erl:143: The pattern 'false' can never match the type 'true'
+comparisons.erl:144: The pattern 'true' can never match the type 'false'
+comparisons.erl:145: The pattern 'true' can never match the type 'false'
+comparisons.erl:146: The pattern 'false' can never match the type 'true'
+comparisons.erl:147: The pattern 'false' can never match the type 'true'
+comparisons.erl:152: The pattern 'false' can never match the type 'true'
+comparisons.erl:153: The pattern 'false' can never match the type 'true'
+comparisons.erl:154: The pattern 'true' can never match the type 'false'
+comparisons.erl:155: The pattern 'true' can never match the type 'false'
+comparisons.erl:157: The pattern 'true' can never match the type 'false'
+comparisons.erl:158: The pattern 'true' can never match the type 'false'
+comparisons.erl:159: The pattern 'false' can never match the type 'true'
+comparisons.erl:160: The pattern 'false' can never match the type 'true'
+comparisons.erl:161: The pattern 'true' can never match the type 'false'
+comparisons.erl:162: The pattern 'true' can never match the type 'false'
+comparisons.erl:163: The pattern 'false' can never match the type 'true'
+comparisons.erl:164: The pattern 'false' can never match the type 'true'
+comparisons.erl:165: The pattern 'true' can never match the type 'false'
+comparisons.erl:166: The pattern 'true' can never match the type 'false'
+comparisons.erl:167: The pattern 'false' can never match the type 'true'
+comparisons.erl:168: The pattern 'false' can never match the type 'true'
+comparisons.erl:169: The pattern 'true' can never match the type 'false'
+comparisons.erl:170: The pattern 'true' can never match the type 'false'
+comparisons.erl:171: The pattern 'false' can never match the type 'true'
+comparisons.erl:172: The pattern 'false' can never match the type 'true'
+comparisons.erl:173: The pattern 'true' can never match the type 'false'
+comparisons.erl:174: The pattern 'true' can never match the type 'false'
+comparisons.erl:175: The pattern 'false' can never match the type 'true'
+comparisons.erl:176: The pattern 'false' can never match the type 'true'
+comparisons.erl:186: The pattern 'false' can never match the type 'true'
+comparisons.erl:187: The pattern 'false' can never match the type 'true'
+comparisons.erl:188: The pattern 'true' can never match the type 'false'
+comparisons.erl:189: The pattern 'true' can never match the type 'false'
+comparisons.erl:190: The pattern 'false' can never match the type 'true'
+comparisons.erl:191: The pattern 'false' can never match the type 'true'
+comparisons.erl:192: The pattern 'true' can never match the type 'false'
+comparisons.erl:193: The pattern 'true' can never match the type 'false'
+comparisons.erl:203: The pattern 'false' can never match the type 'true'
+comparisons.erl:204: The pattern 'false' can never match the type 'true'
+comparisons.erl:205: The pattern 'true' can never match the type 'false'
+comparisons.erl:206: The pattern 'true' can never match the type 'false'
+comparisons.erl:208: The pattern 'true' can never match the type 'false'
+comparisons.erl:209: The pattern 'true' can never match the type 'false'
+comparisons.erl:210: The pattern 'false' can never match the type 'true'
+comparisons.erl:211: The pattern 'false' can never match the type 'true'
+comparisons.erl:221: The pattern 'true' can never match the type 'false'
+comparisons.erl:222: The pattern 'true' can never match the type 'false'
+comparisons.erl:223: The pattern 'false' can never match the type 'true'
+comparisons.erl:224: The pattern 'false' can never match the type 'true'
+comparisons.erl:225: The pattern 'true' can never match the type 'false'
+comparisons.erl:226: The pattern 'true' can never match the type 'false'
+comparisons.erl:227: The pattern 'false' can never match the type 'true'
+comparisons.erl:228: The pattern 'false' can never match the type 'true'
+comparisons.erl:242: The pattern 'false' can never match the type 'true'
+comparisons.erl:243: The pattern 'false' can never match the type 'true'
+comparisons.erl:244: The pattern 'true' can never match the type 'false'
+comparisons.erl:245: The pattern 'true' can never match the type 'false'
+comparisons.erl:246: The pattern 'false' can never match the type 'true'
+comparisons.erl:247: The pattern 'false' can never match the type 'true'
+comparisons.erl:248: The pattern 'true' can never match the type 'false'
+comparisons.erl:249: The pattern 'true' can never match the type 'false'
+comparisons.erl:251: The pattern 'true' can never match the type 'false'
+comparisons.erl:252: The pattern 'true' can never match the type 'false'
+comparisons.erl:253: The pattern 'false' can never match the type 'true'
+comparisons.erl:254: The pattern 'false' can never match the type 'true'
+comparisons.erl:263: The pattern 'false' can never match the type 'true'
+comparisons.erl:264: The pattern 'false' can never match the type 'true'
+comparisons.erl:265: The pattern 'true' can never match the type 'false'
+comparisons.erl:266: The pattern 'true' can never match the type 'false'
+comparisons.erl:268: The pattern 'true' can never match the type 'false'
+comparisons.erl:269: The pattern 'true' can never match the type 'false'
+comparisons.erl:270: The pattern 'false' can never match the type 'true'
+comparisons.erl:271: The pattern 'false' can never match the type 'true'
+comparisons.erl:272: The pattern 'true' can never match the type 'false'
+comparisons.erl:273: The pattern 'true' can never match the type 'false'
+comparisons.erl:274: The pattern 'false' can never match the type 'true'
+comparisons.erl:275: The pattern 'false' can never match the type 'true'
+comparisons.erl:293: The pattern 'false' can never match the type 'true'
+comparisons.erl:294: The pattern 'false' can never match the type 'true'
+comparisons.erl:295: The pattern 'true' can never match the type 'false'
+comparisons.erl:296: The pattern 'true' can never match the type 'false'
+comparisons.erl:311: The pattern 'true' can never match the type 'false'
+comparisons.erl:312: The pattern 'true' can never match the type 'false'
+comparisons.erl:313: The pattern 'false' can never match the type 'true'
+comparisons.erl:314: The pattern 'false' can never match the type 'true'
+comparisons.erl:44: The pattern 'false' can never match the type 'true'
+comparisons.erl:45: The pattern 'false' can never match the type 'true'
+comparisons.erl:46: The pattern 'true' can never match the type 'false'
+comparisons.erl:47: The pattern 'true' can never match the type 'false'
+comparisons.erl:48: The pattern 'false' can never match the type 'true'
+comparisons.erl:49: The pattern 'false' can never match the type 'true'
+comparisons.erl:50: The pattern 'true' can never match the type 'false'
+comparisons.erl:51: The pattern 'true' can never match the type 'false'
+comparisons.erl:52: The pattern 'false' can never match the type 'true'
+comparisons.erl:53: The pattern 'false' can never match the type 'true'
+comparisons.erl:54: The pattern 'true' can never match the type 'false'
+comparisons.erl:55: The pattern 'true' can never match the type 'false'
+comparisons.erl:69: The pattern 'false' can never match the type 'true'
+comparisons.erl:70: The pattern 'false' can never match the type 'true'
+comparisons.erl:71: The pattern 'true' can never match the type 'false'
+comparisons.erl:72: The pattern 'true' can never match the type 'false'
+comparisons.erl:73: The pattern 'false' can never match the type 'true'
+comparisons.erl:74: The pattern 'false' can never match the type 'true'
+comparisons.erl:75: The pattern 'true' can never match the type 'false'
+comparisons.erl:76: The pattern 'true' can never match the type 'false'
+comparisons.erl:77: The pattern 'false' can never match the type 'true'
+comparisons.erl:78: The pattern 'false' can never match the type 'true'
+comparisons.erl:79: The pattern 'true' can never match the type 'false'
+comparisons.erl:80: The pattern 'true' can never match the type 'false'
+comparisons.erl:94: The pattern 'false' can never match the type 'true'
+comparisons.erl:95: The pattern 'false' can never match the type 'true'
+comparisons.erl:96: The pattern 'true' can never match the type 'false'
+comparisons.erl:97: The pattern 'true' can never match the type 'false'
+comparisons.erl:98: The pattern 'false' can never match the type 'true'
+comparisons.erl:99: The pattern 'false' can never match the type 'true'
diff --git a/lib/dialyzer/test/small_SUITE_data/results/confusing_record_warning b/lib/dialyzer/test/small_SUITE_data/results/confusing_record_warning
new file mode 100644
index 0000000000..ac3d89b02b
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/confusing_record_warning
@@ -0,0 +1,3 @@
+
+confusing_record_warning.erl:18: Function test/1 has no local return
+confusing_record_warning.erl:18: Matching of pattern {'r', [_]} tagged with a record name violates the declared type of #r{field::'binary' | 'undefined'}
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/confusing_warning b/lib/dialyzer/test/small_SUITE_data/results/confusing_warning
index d2d0c91fff..d2d0c91fff 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/confusing_warning
+++ b/lib/dialyzer/test/small_SUITE_data/results/confusing_warning
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/contract1 b/lib/dialyzer/test/small_SUITE_data/results/contract1
index fb8ba5f72b..fb8ba5f72b 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/contract1
+++ b/lib/dialyzer/test/small_SUITE_data/results/contract1
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/contract2 b/lib/dialyzer/test/small_SUITE_data/results/contract2
index 6809e528c4..6809e528c4 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/contract2
+++ b/lib/dialyzer/test/small_SUITE_data/results/contract2
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/contract3 b/lib/dialyzer/test/small_SUITE_data/results/contract3
index 44b49e745a..44b49e745a 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/contract3
+++ b/lib/dialyzer/test/small_SUITE_data/results/contract3
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/contract5 b/lib/dialyzer/test/small_SUITE_data/results/contract5
index 116c4f4d4d..116c4f4d4d 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/contract5
+++ b/lib/dialyzer/test/small_SUITE_data/results/contract5
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/eqeq b/lib/dialyzer/test/small_SUITE_data/results/eqeq
index dabd38ebe3..dabd38ebe3 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/eqeq
+++ b/lib/dialyzer/test/small_SUITE_data/results/eqeq
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/ets_select b/lib/dialyzer/test/small_SUITE_data/results/ets_select
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/ets_select
+++ b/lib/dialyzer/test/small_SUITE_data/results/ets_select
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/exhaust_case b/lib/dialyzer/test/small_SUITE_data/results/exhaust_case
index 45cdd80b64..45cdd80b64 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/exhaust_case
+++ b/lib/dialyzer/test/small_SUITE_data/results/exhaust_case
diff --git a/lib/dialyzer/test/small_SUITE_data/results/failing_funs b/lib/dialyzer/test/small_SUITE_data/results/failing_funs
new file mode 100644
index 0000000000..a1fb22cbc6
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/failing_funs
@@ -0,0 +1,20 @@
+
+failing_funs.erl:101: The created fun has no local return
+failing_funs.erl:104: The created fun has no local return
+failing_funs.erl:127: The created fun has no local return
+failing_funs.erl:135: The created fun has no local return
+failing_funs.erl:138: The created fun has no local return
+failing_funs.erl:13: Function foo3/0 has no local return
+failing_funs.erl:13: The pattern 'b' can never match the type 'a'
+failing_funs.erl:161: The created fun has no local return
+failing_funs.erl:169: The created fun has no local return
+failing_funs.erl:172: The created fun has no local return
+failing_funs.erl:17: The pattern 'b' can never match the type 'a'
+failing_funs.erl:195: The created fun has no local return
+failing_funs.erl:203: The created fun has no local return
+failing_funs.erl:206: The created fun has no local return
+failing_funs.erl:229: The created fun has no local return
+failing_funs.erl:55: The created fun has no local return
+failing_funs.erl:62: The created fun has no local return
+failing_funs.erl:69: The created fun has no local return
+failing_funs.erl:76: The created fun has no local return
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/failing_guard1 b/lib/dialyzer/test/small_SUITE_data/results/failing_guard1
index 5bdd13093a..5bdd13093a 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/failing_guard1
+++ b/lib/dialyzer/test/small_SUITE_data/results/failing_guard1
diff --git a/lib/dialyzer/test/small_SUITE_data/results/flatten b/lib/dialyzer/test/small_SUITE_data/results/flatten
new file mode 100644
index 0000000000..8aa44dd002
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/flatten
@@ -0,0 +1,2 @@
+
+flatten.erl:17: The call lists:flatten(nonempty_improper_list(atom() | [any()] | char(),atom())) will never return since it differs in the 1st argument from the success typing arguments: ([any()])
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/fun_app b/lib/dialyzer/test/small_SUITE_data/results/fun_app
index b28baad43b..b28baad43b 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/fun_app
+++ b/lib/dialyzer/test/small_SUITE_data/results/fun_app
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/fun_ref_match b/lib/dialyzer/test/small_SUITE_data/results/fun_ref_match
index 60b34530b4..60b34530b4 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/fun_ref_match
+++ b/lib/dialyzer/test/small_SUITE_data/results/fun_ref_match
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/gencall b/lib/dialyzer/test/small_SUITE_data/results/gencall
index d0479ed738..d0479ed738 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/gencall
+++ b/lib/dialyzer/test/small_SUITE_data/results/gencall
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/gs_make b/lib/dialyzer/test/small_SUITE_data/results/gs_make
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/gs_make
+++ b/lib/dialyzer/test/small_SUITE_data/results/gs_make
diff --git a/lib/dialyzer/test/small_SUITE_data/results/guard_warnings b/lib/dialyzer/test/small_SUITE_data/results/guard_warnings
new file mode 100644
index 0000000000..0ff998bf50
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/guard_warnings
@@ -0,0 +1,97 @@
+
+guard_warnings.erl:100: Function test45/0 has no local return
+guard_warnings.erl:100: Guard test 'not'('true') can never succeed
+guard_warnings.erl:102: Function test46/1 has no local return
+guard_warnings.erl:102: Guard test X::'true' =:= 'false' can never succeed
+guard_warnings.erl:104: Function test47/1 has no local return
+guard_warnings.erl:104: Guard test X::'true' == 'false' can never succeed
+guard_warnings.erl:106: Function test48/1 has no local return
+guard_warnings.erl:106: Guard test X::'true' =/= 'true' can never succeed
+guard_warnings.erl:114: Function test52_w/1 has no local return
+guard_warnings.erl:118: Function test54_w/1 has no local return
+guard_warnings.erl:12: Function test1/1 has no local return
+guard_warnings.erl:12: Guard test X::'true' =:= 'false' can never succeed
+guard_warnings.erl:14: Function test2/1 has no local return
+guard_warnings.erl:14: Guard test X::'false' =:= 'true' can never succeed
+guard_warnings.erl:16: Function test3/1 has no local return
+guard_warnings.erl:16: Guard test 'not'(X::'true') can never succeed
+guard_warnings.erl:18: Function test4/1 has no local return
+guard_warnings.erl:18: Guard test 'and'('true',X::none()) can never succeed
+guard_warnings.erl:20: Function test5/1 has no local return
+guard_warnings.erl:20: Guard test 'not'(X::'true') can never succeed
+guard_warnings.erl:22: Function test6/1 has no local return
+guard_warnings.erl:22: Guard test 'and'('true',X::none()) can never succeed
+guard_warnings.erl:24: Function test7_w/1 has no local return
+guard_warnings.erl:26: Function test8_w/1 has no local return
+guard_warnings.erl:28: Function test9/1 has no local return
+guard_warnings.erl:28: Guard test not('not'(X::'false')) can never succeed
+guard_warnings.erl:30: Function test10/1 has no local return
+guard_warnings.erl:30: Guard test not('or'('false',X::none())) can never succeed
+guard_warnings.erl:32: Function test11/1 has no local return
+guard_warnings.erl:32: Guard test not('not'(X::'false')) can never succeed
+guard_warnings.erl:34: Function test12/1 has no local return
+guard_warnings.erl:34: Guard test not('or'('false',X::none())) can never succeed
+guard_warnings.erl:36: Function test13/1 has no local return
+guard_warnings.erl:36: Guard test 'and'('true','false') can never succeed
+guard_warnings.erl:38: Function test14/1 has no local return
+guard_warnings.erl:38: Guard test 'and'('false',any()) can never succeed
+guard_warnings.erl:40: Function test15/1 has no local return
+guard_warnings.erl:40: Guard test 'and'(X::'true','false') can never succeed
+guard_warnings.erl:42: Function test16/1 has no local return
+guard_warnings.erl:42: Guard test 'and'('false',X::any()) can never succeed
+guard_warnings.erl:44: Function test17/1 has no local return
+guard_warnings.erl:44: Guard test 'and'(X::'true','false') can never succeed
+guard_warnings.erl:46: Function test18/1 has no local return
+guard_warnings.erl:46: Guard test 'and'('false',X::any()) can never succeed
+guard_warnings.erl:48: Function test19/1 has no local return
+guard_warnings.erl:48: Guard test not('or'('true',any())) can never succeed
+guard_warnings.erl:50: Function test20/1 has no local return
+guard_warnings.erl:50: Guard test not('or'('false','true')) can never succeed
+guard_warnings.erl:52: Function test21/1 has no local return
+guard_warnings.erl:52: Guard test not('or'('true',X::any())) can never succeed
+guard_warnings.erl:54: Function test22/1 has no local return
+guard_warnings.erl:54: Guard test not('or'(X::'false','true')) can never succeed
+guard_warnings.erl:56: Function test23/1 has no local return
+guard_warnings.erl:56: Guard test not('or'('true',X::any())) can never succeed
+guard_warnings.erl:58: Function test24/1 has no local return
+guard_warnings.erl:58: Guard test not('or'(X::'false','true')) can never succeed
+guard_warnings.erl:60: Function test25/1 has no local return
+guard_warnings.erl:60: Guard test 'and'('false',any()) can never succeed
+guard_warnings.erl:62: Function test26/1 has no local return
+guard_warnings.erl:62: Guard test 'and'('true','false') can never succeed
+guard_warnings.erl:64: Function test27/1 has no local return
+guard_warnings.erl:64: Guard test 'and'('false',X::any()) can never succeed
+guard_warnings.erl:66: Function test28/1 has no local return
+guard_warnings.erl:66: Guard test 'and'(X::'true','false') can never succeed
+guard_warnings.erl:68: Function test29/1 has no local return
+guard_warnings.erl:68: Guard test 'and'('false',X::any()) can never succeed
+guard_warnings.erl:70: Function test30/1 has no local return
+guard_warnings.erl:70: Guard test 'and'(X::'true','false') can never succeed
+guard_warnings.erl:72: Function test31/0 has no local return
+guard_warnings.erl:72: Guard test 'and'('false',any()) can never succeed
+guard_warnings.erl:74: Function test32/0 has no local return
+guard_warnings.erl:74: Guard test 'and'('false',any()) can never succeed
+guard_warnings.erl:76: Function test33/0 has no local return
+guard_warnings.erl:76: Guard test not('and'('true','true')) can never succeed
+guard_warnings.erl:78: Function test34/0 has no local return
+guard_warnings.erl:78: Guard test 'and'('false',any()) can never succeed
+guard_warnings.erl:80: Function test35/0 has no local return
+guard_warnings.erl:80: Guard test not('and'('true','true')) can never succeed
+guard_warnings.erl:82: Function test36/0 has no local return
+guard_warnings.erl:82: Guard test 'or'('false','false') can never succeed
+guard_warnings.erl:84: Function test37/0 has no local return
+guard_warnings.erl:84: Guard test 'or'('false','false') can never succeed
+guard_warnings.erl:86: Function test38/0 has no local return
+guard_warnings.erl:86: Guard test 'or'('false','false') can never succeed
+guard_warnings.erl:88: Function test39/0 has no local return
+guard_warnings.erl:88: Guard test 'or'('false','false') can never succeed
+guard_warnings.erl:90: Function test40/0 has no local return
+guard_warnings.erl:90: Guard test 'or'('false','false') can never succeed
+guard_warnings.erl:92: Function test41/0 has no local return
+guard_warnings.erl:92: Guard test 'true' =:= 'false' can never succeed
+guard_warnings.erl:94: Function test42/0 has no local return
+guard_warnings.erl:94: Guard test 'true' == 'false' can never succeed
+guard_warnings.erl:96: Function test43/0 has no local return
+guard_warnings.erl:96: Guard test 'true' =:= 'false' can never succeed
+guard_warnings.erl:98: Function test44/0 has no local return
+guard_warnings.erl:98: Guard test not('true' == 'true') can never succeed
diff --git a/lib/dialyzer/test/small_SUITE_data/results/guards b/lib/dialyzer/test/small_SUITE_data/results/guards
new file mode 100644
index 0000000000..824a7cfa24
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/guards
@@ -0,0 +1,17 @@
+
+guards.erl:100: The variable _ can never match since previous clauses completely covered the type {'true','true'}
+guards.erl:111: The pattern {_, _} can never match since previous clauses completely covered the type {'false',boolean()} | {'true',boolean()}
+guards.erl:122: The pattern {_, _} can never match since previous clauses completely covered the type {'false',boolean()} | {'true',boolean()}
+guards.erl:129: Function t15_a/0 has no local return
+guards.erl:129: The call guards:t15('a') will never return since it differs in the 1st argument from the success typing arguments: ('b')
+guards.erl:129: The call guards:t15('c') will never return since it differs in the 1st argument from the success typing arguments: ('b')
+guards.erl:136: Function t16_a/0 has no local return
+guards.erl:136: The call guards:t16('a') will never return since it differs in the 1st argument from the success typing arguments: ('b')
+guards.erl:136: The call guards:t16('c') will never return since it differs in the 1st argument from the success typing arguments: ('b')
+guards.erl:55: Function t5/1 has no local return
+guards.erl:55: Guard test is_integer(A::atom()) can never succeed
+guards.erl:59: Clause guard cannot succeed. The variable A was matched against the type any()
+guards.erl:59: Function t6/1 has no local return
+guards.erl:67: The call guards:t7({42}) will never return since it differs in the 1st argument from the success typing arguments: (atom() | integer())
+guards.erl:75: The call guards:t8({42}) will never return since it differs in the 1st argument from the success typing arguments: (atom() | integer())
+guards.erl:92: The variable _ can never match since previous clauses completely covered the type {'true','true'}
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/inf_loop2 b/lib/dialyzer/test/small_SUITE_data/results/inf_loop2
index 7e9972ad98..7e9972ad98 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/inf_loop2
+++ b/lib/dialyzer/test/small_SUITE_data/results/inf_loop2
diff --git a/lib/dialyzer/test/small_SUITE_data/results/invalid_specs b/lib/dialyzer/test/small_SUITE_data/results/invalid_specs
new file mode 100644
index 0000000000..c95c0ff1f8
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/invalid_specs
@@ -0,0 +1,3 @@
+
+invalid_spec1.erl:5: Invalid type specification for function invalid_spec1:get_plan_dirty/1. The success typing is ([string()]) -> {maybe_improper_list(),[atom()]}
+invalid_spec2.erl:5: Function foo/0 has no local return
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/letrec1 b/lib/dialyzer/test/small_SUITE_data/results/letrec1
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/letrec1
+++ b/lib/dialyzer/test/small_SUITE_data/results/letrec1
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/list_match b/lib/dialyzer/test/small_SUITE_data/results/list_match
index 95007da604..95007da604 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/list_match
+++ b/lib/dialyzer/test/small_SUITE_data/results/list_match
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/lzip b/lib/dialyzer/test/small_SUITE_data/results/lzip
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/lzip
+++ b/lib/dialyzer/test/small_SUITE_data/results/lzip
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/make_tuple b/lib/dialyzer/test/small_SUITE_data/results/make_tuple
index 4d51586e35..4d51586e35 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/make_tuple
+++ b/lib/dialyzer/test/small_SUITE_data/results/make_tuple
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/minus_minus b/lib/dialyzer/test/small_SUITE_data/results/minus_minus
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/minus_minus
+++ b/lib/dialyzer/test/small_SUITE_data/results/minus_minus
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/mod_info b/lib/dialyzer/test/small_SUITE_data/results/mod_info
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/mod_info
+++ b/lib/dialyzer/test/small_SUITE_data/results/mod_info
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/my_filter b/lib/dialyzer/test/small_SUITE_data/results/my_filter
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/my_filter
+++ b/lib/dialyzer/test/small_SUITE_data/results/my_filter
diff --git a/lib/dialyzer/test/small_SUITE_data/results/my_sofs b/lib/dialyzer/test/small_SUITE_data/results/my_sofs
new file mode 100644
index 0000000000..bc97c08d62
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/my_sofs
@@ -0,0 +1,3 @@
+
+my_sofs.erl:34: The pattern {'Set', _, _} can never match the type #'OrdSet'{}
+my_sofs.erl:54: The pattern {'Set', _, _} can never match the type #'OrdSet'{}
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/no_match b/lib/dialyzer/test/small_SUITE_data/results/no_match
index 9760b980a2..9760b980a2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/no_match
+++ b/lib/dialyzer/test/small_SUITE_data/results/no_match
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/no_unused_fun b/lib/dialyzer/test/small_SUITE_data/results/no_unused_fun
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/no_unused_fun
+++ b/lib/dialyzer/test/small_SUITE_data/results/no_unused_fun
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/no_unused_fun2 b/lib/dialyzer/test/small_SUITE_data/results/no_unused_fun2
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/no_unused_fun2
+++ b/lib/dialyzer/test/small_SUITE_data/results/no_unused_fun2
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/non_existing b/lib/dialyzer/test/small_SUITE_data/results/non_existing
index 58da2bfc8b..58da2bfc8b 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/non_existing
+++ b/lib/dialyzer/test/small_SUITE_data/results/non_existing
diff --git a/lib/dialyzer/test/small_SUITE_data/results/none_scc_inf_loop b/lib/dialyzer/test/small_SUITE_data/results/none_scc_inf_loop
new file mode 100644
index 0000000000..3b1b204708
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/none_scc_inf_loop
@@ -0,0 +1,5 @@
+
+none_scc_inf_loop.erl:10: Function foo/0 has no local return
+none_scc_inf_loop.erl:13: Function foo/1 has no local return
+none_scc_inf_loop.erl:13: The pattern 0 can never match the type 1 | 3
+none_scc_inf_loop.erl:18: Function bar/1 has no local return
diff --git a/lib/dialyzer/test/small_SUITE_data/results/not_bogus_warning b/lib/dialyzer/test/small_SUITE_data/results/not_bogus_warning
new file mode 100644
index 0000000000..e3a7f6b444
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/not_bogus_warning
@@ -0,0 +1,3 @@
+
+not_bogus_warning.erl:11: Guard test not(is_atom(A::'bar' | 'foo')) can never succeed
+not_bogus_warning.erl:24: Guard test not(is_integer(X::42)) can never succeed
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/not_guard_crash b/lib/dialyzer/test/small_SUITE_data/results/not_guard_crash
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/not_guard_crash
+++ b/lib/dialyzer/test/small_SUITE_data/results/not_guard_crash
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/or_bug b/lib/dialyzer/test/small_SUITE_data/results/or_bug
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/or_bug
+++ b/lib/dialyzer/test/small_SUITE_data/results/or_bug
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/orelsebug b/lib/dialyzer/test/small_SUITE_data/results/orelsebug
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/orelsebug
+++ b/lib/dialyzer/test/small_SUITE_data/results/orelsebug
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/orelsebug2 b/lib/dialyzer/test/small_SUITE_data/results/orelsebug2
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/orelsebug2
+++ b/lib/dialyzer/test/small_SUITE_data/results/orelsebug2
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/overloaded1 b/lib/dialyzer/test/small_SUITE_data/results/overloaded1
index ab57ec03ff..ab57ec03ff 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/overloaded1
+++ b/lib/dialyzer/test/small_SUITE_data/results/overloaded1
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/port_info_test b/lib/dialyzer/test/small_SUITE_data/results/port_info_test
index 9ee863f9eb..9ee863f9eb 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/port_info_test
+++ b/lib/dialyzer/test/small_SUITE_data/results/port_info_test
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/process_info_test b/lib/dialyzer/test/small_SUITE_data/results/process_info_test
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/process_info_test
+++ b/lib/dialyzer/test/small_SUITE_data/results/process_info_test
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/pubsub b/lib/dialyzer/test/small_SUITE_data/results/pubsub
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/pubsub
+++ b/lib/dialyzer/test/small_SUITE_data/results/pubsub
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/receive1 b/lib/dialyzer/test/small_SUITE_data/results/receive1
index abf6eec0ca..abf6eec0ca 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/receive1
+++ b/lib/dialyzer/test/small_SUITE_data/results/receive1
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/record_construct b/lib/dialyzer/test/small_SUITE_data/results/record_construct
index c0110b144f..c0110b144f 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/record_construct
+++ b/lib/dialyzer/test/small_SUITE_data/results/record_construct
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/record_pat b/lib/dialyzer/test/small_SUITE_data/results/record_pat
index 9a3f925e42..9a3f925e42 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/record_pat
+++ b/lib/dialyzer/test/small_SUITE_data/results/record_pat
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/record_send_test b/lib/dialyzer/test/small_SUITE_data/results/record_send_test
index 6a08d44179..6a08d44179 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/record_send_test
+++ b/lib/dialyzer/test/small_SUITE_data/results/record_send_test
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/record_test b/lib/dialyzer/test/small_SUITE_data/results/record_test
index 9715f0dcfb..9715f0dcfb 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/record_test
+++ b/lib/dialyzer/test/small_SUITE_data/results/record_test
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types1 b/lib/dialyzer/test/small_SUITE_data/results/recursive_types1
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types1
+++ b/lib/dialyzer/test/small_SUITE_data/results/recursive_types1
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types2 b/lib/dialyzer/test/small_SUITE_data/results/recursive_types2
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types2
+++ b/lib/dialyzer/test/small_SUITE_data/results/recursive_types2
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types3 b/lib/dialyzer/test/small_SUITE_data/results/recursive_types3
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types3
+++ b/lib/dialyzer/test/small_SUITE_data/results/recursive_types3
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types4 b/lib/dialyzer/test/small_SUITE_data/results/recursive_types4
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types4
+++ b/lib/dialyzer/test/small_SUITE_data/results/recursive_types4
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types5 b/lib/dialyzer/test/small_SUITE_data/results/recursive_types5
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types5
+++ b/lib/dialyzer/test/small_SUITE_data/results/recursive_types5
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types6 b/lib/dialyzer/test/small_SUITE_data/results/recursive_types6
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types6
+++ b/lib/dialyzer/test/small_SUITE_data/results/recursive_types6
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types7 b/lib/dialyzer/test/small_SUITE_data/results/recursive_types7
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/recursive_types7
+++ b/lib/dialyzer/test/small_SUITE_data/results/recursive_types7
diff --git a/lib/dialyzer/test/small_SUITE_data/results/refine_failing b/lib/dialyzer/test/small_SUITE_data/results/refine_failing
new file mode 100644
index 0000000000..2bf67c9d81
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/refine_failing
@@ -0,0 +1,2 @@
+
+refine_failing.erl:25: The call refine_failing:update_one(F::any(),Ds::{_,non_neg_integer()},[{_,non_neg_integer()},...]) will never return since it differs in the 2nd argument from the success typing arguments: (any(),[{_,non_neg_integer()}],[{_,non_neg_integer()}])
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/toth b/lib/dialyzer/test/small_SUITE_data/results/toth
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/toth
+++ b/lib/dialyzer/test/small_SUITE_data/results/toth
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/trec b/lib/dialyzer/test/small_SUITE_data/results/trec
index 01ccc63761..01ccc63761 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/trec
+++ b/lib/dialyzer/test/small_SUITE_data/results/trec
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/try1 b/lib/dialyzer/test/small_SUITE_data/results/try1
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/try1
+++ b/lib/dialyzer/test/small_SUITE_data/results/try1
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/tuple1 b/lib/dialyzer/test/small_SUITE_data/results/tuple1
index 1b5ed49b56..1b5ed49b56 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/tuple1
+++ b/lib/dialyzer/test/small_SUITE_data/results/tuple1
diff --git a/lib/dialyzer/test/small_SUITE_data/results/tuple_set_crash b/lib/dialyzer/test/small_SUITE_data/results/tuple_set_crash
new file mode 100644
index 0000000000..191d3d4173
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/tuple_set_crash
@@ -0,0 +1,15 @@
+
+tuple_set_crash.erl:103: Invalid type specification for function tuple_set_crash:parse_device_properties/1. The success typing is (<<_:48>>) -> [{'controller_description',binary()} | {'controller_name',binary()} | {'controller_status',byte()} | {'fw_version',<<_:24>>}]
+tuple_set_crash.erl:123: Invalid type specification for function tuple_set_crash:parse_video_target_info/1. The success typing is (<<_:48>>) -> [{'status',byte()} | {'target_id',non_neg_integer()},...]
+tuple_set_crash.erl:127: Invalid type specification for function tuple_set_crash:parse_audio_target_info/1. The success typing is (<<_:48>>) -> [{'master_volume',char()} | {'status',byte()} | {'target_id',non_neg_integer()},...]
+tuple_set_crash.erl:138: Invalid type specification for function tuple_set_crash:parse_av_device_info/1. The success typing is (<<_:48>>) -> [{'address',byte()} | {'device_id',non_neg_integer()} | {'model',binary()} | {'status',byte()},...]
+tuple_set_crash.erl:143: The pattern <<TargetId:32/integer-little-unit:1,Rest1/binary-unit:8>> can never match the type <<_:8>>
+tuple_set_crash.erl:155: Invalid type specification for function tuple_set_crash:parse_video_output_info/1. The success typing is (<<_:48>>) -> [{'audio_volume',char()} | {'display_type',binary()} | {'output_id',non_neg_integer()},...]
+tuple_set_crash.erl:160: The pattern <<DeviceId:32/integer-little-unit:1,Rest1/binary-unit:8>> can never match the type <<_:8>>
+tuple_set_crash.erl:171: Invalid type specification for function tuple_set_crash:parse_audio_output_info/1. The success typing is (<<_:48>>) -> [{'output_id',non_neg_integer()},...]
+tuple_set_crash.erl:176: The pattern <<DeviceId:32/integer-little-unit:1,Rest1/binary-unit:8>> can never match the type <<_:8>>
+tuple_set_crash.erl:179: The pattern <<AudioVolume:16/integer-little-unit:1,Rest2/binary-unit:8>> can never match the type <<_:8>>
+tuple_set_crash.erl:182: The pattern <<Delay:16/integer-little-unit:1,_Padding/binary-unit:8>> can never match the type <<_:8>>
+tuple_set_crash.erl:62: The pattern {'play_list', _Playlist} can never match the type 'ok' | {'device_properties',[{atom(),_}]} | {'error',[{atom(),_}]}
+tuple_set_crash.erl:64: The pattern {'error', 17} can never match the type 'ok' | {'device_properties',[{atom(),_}]} | {'error',[{atom(),_}]}
+tuple_set_crash.erl:83: The specification for tuple_set_crash:parse_message/1 states that the function might also return {'media_item_url_reply',integer(),binary()} but the inferred return is 'ok' | {'audio_device_info' | 'audio_output_info' | 'audio_target_info' | 'device_properties' | 'error' | 'video_device_info' | 'video_output_info' | 'video_target_info',[{'address' | 'audio_volume' | 'controller_description' | 'controller_name' | 'controller_status' | 'device_id' | 'display_type' | 'fw_version' | 'master_volume' | 'model' | 'output_id' | 'status' | 'target_id',binary() | non_neg_integer()}] | 1..255}
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/unsafe_beamcode_bug b/lib/dialyzer/test/small_SUITE_data/results/unsafe_beamcode_bug
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/unsafe_beamcode_bug
+++ b/lib/dialyzer/test/small_SUITE_data/results/unsafe_beamcode_bug
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/unused_cases b/lib/dialyzer/test/small_SUITE_data/results/unused_cases
index cafe1c042b..cafe1c042b 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/unused_cases
+++ b/lib/dialyzer/test/small_SUITE_data/results/unused_cases
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/unused_clauses b/lib/dialyzer/test/small_SUITE_data/results/unused_clauses
index 4603e888c1..4603e888c1 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/unused_clauses
+++ b/lib/dialyzer/test/small_SUITE_data/results/unused_clauses
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/zero_tuple b/lib/dialyzer/test/small_SUITE_data/results/zero_tuple
index bf5ec5cd6e..bf5ec5cd6e 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/zero_tuple
+++ b/lib/dialyzer/test/small_SUITE_data/results/zero_tuple
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/app_call.erl b/lib/dialyzer/test/small_SUITE_data/src/app_call.erl
index 54d178d29a..54d178d29a 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/app_call.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/app_call.erl
diff --git a/lib/dialyzer/test/small_SUITE_data/src/appmon_place.erl b/lib/dialyzer/test/small_SUITE_data/src/appmon_place.erl
new file mode 100644
index 0000000000..60ffbe818f
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/appmon_place.erl
@@ -0,0 +1,70 @@
+%%---------------------------------------------------------------------
+%% This is added as a test because it was giving a false positive
+%% (function move/4 will nevr be called) due to the strange use of
+%% self-recursive fun construction in placex/3.
+%%
+%% The analysis was getting confused that the foldl call will never
+%% terminate (due to a wrong hard-coded type for foldl) and inferred
+%% that the remaining calls in the body of placex/3 will not be
+%% reached. Fixed 11 March 2005.
+%%---------------------------------------------------------------------
+
+-module(appmon_place).
+-export([place/2]).
+
+place(DG, Root) ->
+ case appmon_dg:get(data, DG, Root) of
+ false -> [0];
+ _Other ->
+ placey(DG, Root, 1),
+ placex(DG, Root, [])
+ end.
+
+placey(DG, V, Y) ->
+ appmon_dg:set(y, DG, V, Y),
+ Y1 = Y+1,
+ lists:foreach(fun(C) -> placey(DG, C, Y1) end, appmon_dg:get(out, DG, V)).
+
+placex(DG, V, LastX) ->
+ Ch = appmon_dg:get(out, DG, V),
+ ChLX = lists:foldl(fun(C, Accu) -> placex(DG, C, Accu) end,
+ tll(LastX),
+ Ch),
+ Width = appmon_dg:get(w, DG, V),
+ MyX = calc_mid(DG, Width, Ch),
+ DeltaX = calc_delta(MyX, hdd(LastX)+20),
+ appmon_dg:set(x, DG, V, MyX),
+ move(DG, V, [MyX+Width | ChLX], DeltaX).
+
+move(_DG, _L, LastX, 0) -> LastX;
+move(DG, V, LastX, DeltaX) -> move2(DG, V, LastX, DeltaX).
+
+move2(DG, V, LastX, DeltaX) ->
+ NewX = appmon_dg:get(x, DG, V)+DeltaX,
+ appmon_dg:set(x, DG, V, NewX),
+ ChLX = lists:foldl(fun(C, LX) -> move2(DG, C, LX, DeltaX) end,
+ tll(LastX),
+ appmon_dg:get(out, DG, V)),
+ [max(NewX+appmon_dg:get(w, DG, V), hdd(LastX)) | ChLX].
+
+max(A, B) when A>B -> A;
+max(_, B) -> B.
+
+calc_mid(_DG, _Width, []) -> 0;
+calc_mid(DG, Width, ChList) ->
+ LeftMostX = appmon_dg:get(x, DG, hd(ChList)),
+ Z2 = lists:last(ChList),
+ RightMostX = appmon_dg:get(x, DG, Z2)+appmon_dg:get(w, DG, Z2),
+ trunc((LeftMostX+RightMostX)/2)-trunc(Width/2).
+
+calc_delta(Mid, Right) ->
+ if Right>Mid -> Right-Mid;
+ true -> 0
+ end.
+
+%% Special head and tail
+%% Handles empty list in a non-standard way
+tll([]) -> [];
+tll([_|T]) -> T.
+hdd([]) -> 0;
+hdd([H|_]) -> H.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/areq.erl b/lib/dialyzer/test/small_SUITE_data/src/areq.erl
new file mode 100644
index 0000000000..66bb30491c
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/areq.erl
@@ -0,0 +1,11 @@
+-module(areq).
+
+-export([t/0]).
+
+t() ->
+ ar_comp(3.0, 3),
+ ex_comp(3.0, 3).
+
+ar_comp(X, Y) -> X == Y.
+
+ex_comp(X, Y) -> X =:= Y.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/atom_call.erl b/lib/dialyzer/test/small_SUITE_data/src/atom_call.erl
new file mode 100644
index 0000000000..2b70503144
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/atom_call.erl
@@ -0,0 +1,14 @@
+%%%-------------------------------------------------------------------
+%%% File : atom_call.erl
+%%% Author : Tobias Lindahl <[email protected]>
+%%% Description :
+%%%
+%%% Created : 10 Dec 2007 by Tobias Lindahl <[email protected]>
+%%%-------------------------------------------------------------------
+-module(atom_call).
+
+-export([f/0,g/0]).
+
+f() -> ok.
+
+g() -> F = f, F().
diff --git a/lib/dialyzer/test/small_SUITE_data/src/atom_guard.erl b/lib/dialyzer/test/small_SUITE_data/src/atom_guard.erl
new file mode 100644
index 0000000000..95581b339a
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/atom_guard.erl
@@ -0,0 +1,8 @@
+-module(atom_guard).
+-export([test/0]).
+
+test() ->
+ foo(42).
+
+foo(X) when is_atom(x) ->
+ X.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/atom_widen.erl b/lib/dialyzer/test/small_SUITE_data/src/atom_widen.erl
index 81bfac9d56..81bfac9d56 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/atom_widen.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/atom_widen.erl
diff --git a/lib/dialyzer/test/small_SUITE_data/src/bin_compr.erl b/lib/dialyzer/test/small_SUITE_data/src/bin_compr.erl
new file mode 100644
index 0000000000..8c2497ed21
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/bin_compr.erl
@@ -0,0 +1,16 @@
+%%% -*- erlang-indent-level: 2 -*-
+%%%------------------------------------------------------------------------
+%%% File : bin_compr.erl
+%%% Purpose : Test case which crashes in dialyzer_dataflow:bind_bin_segs/5.
+%%%------------------------------------------------------------------------
+
+-module(bin_compr).
+
+-export([bc/1]).
+
+%% The binary comprehension below is stupid: it consumes the whole
+%% bitstr in one go and produces a [666] result provided Bits is a
+%% bitstr of at least 8 bits. Still, this is a valid Erlang program
+%% and dialyzer's analysis should not crash on it.
+bc(Bits) ->
+ [666 || <<_:8/integer, _/bits>> <= Bits].
diff --git a/lib/dialyzer/test/small_SUITE_data/src/binary_lc_bug.erl b/lib/dialyzer/test/small_SUITE_data/src/binary_lc_bug.erl
new file mode 100644
index 0000000000..c1e82bfa59
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/binary_lc_bug.erl
@@ -0,0 +1,8 @@
+-module(test).
+
+-export([bin_compr/0]).
+
+bin_compr() ->
+% [ 0 || {N, V} <- [{a, b}] ]. % Works ok
+ << <<>> || {A, B} <- [{a, b}] >>. % Complains
+% << <<>> || X <- [{a, b}] >>. % Works ok
diff --git a/lib/dialyzer/test/small_SUITE_data/src/blame_contract_range.erl b/lib/dialyzer/test/small_SUITE_data/src/blame_contract_range.erl
new file mode 100644
index 0000000000..efd3332b44
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/blame_contract_range.erl
@@ -0,0 +1,16 @@
+%%-----------------------------------------------------------------------
+%% A test where the contract is wrongly specified by the programmer;
+%% however, this is found only by refinement.
+%% Dialyzer in R14B01 and prior gave a confusing (if not bogus) warning
+%% for this case. Corrected in R14B02.
+%%-----------------------------------------------------------------------
+-module(blame_contract_range).
+
+-export([foo/0]).
+
+foo() ->
+ bar(b).
+
+-spec bar(atom()) -> a.
+bar(a) -> a;
+bar(b) -> b.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/bs_fail_constr.erl b/lib/dialyzer/test/small_SUITE_data/src/bs_fail_constr.erl
new file mode 100644
index 0000000000..8c1f8c009a
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/bs_fail_constr.erl
@@ -0,0 +1,15 @@
+-module(bs_fail_constr).
+
+-export([w1/1, w2/1, w3/1, w4/1]).
+
+w1(V) when is_float(V) ->
+ <<V/integer>>.
+
+w2(V) when is_atom(V) ->
+ <<V/binary>>.
+
+w3(S) when is_integer(S), S < 0 ->
+ <<42:S/integer>>.
+
+w4(V) when is_float(V) ->
+ <<V/utf32>>.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/bs_utf8.erl b/lib/dialyzer/test/small_SUITE_data/src/bs_utf8.erl
index 5fe28f1da1..5fe28f1da1 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/bs_utf8.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/bs_utf8.erl
diff --git a/lib/dialyzer/test/small_SUITE_data/src/cerl_hipeify.erl b/lib/dialyzer/test/small_SUITE_data/src/cerl_hipeify.erl
new file mode 100644
index 0000000000..b7883e7b49
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/cerl_hipeify.erl
@@ -0,0 +1,684 @@
+%% =====================================================================
+%% This library is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU Lesser General Public License as
+%% published by the Free Software Foundation; either version 2 of the
+%% License, or (at your option) any later version.
+%%
+%% This library is distributed in the hope that it will be useful, but
+%% WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+%% Lesser General Public License for more details.
+%%
+%% You should have received a copy of the GNU Lesser General Public
+%% License along with this library; if not, write to the Free Software
+%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+%% USA
+%%
+%% $Id: cerl_hipeify.erl,v 1.1 2008/12/17 09:53:49 mikpe Exp $
+%%
+%% @author Richard Carlsson <[email protected]>
+%% @copyright 2000-2004 Richard Carlsson
+%% @doc HiPE-ification of Core Erlang code. Prepares Core Erlang code
+%% for translation to ICode.
+%% @see cerl_to_icode
+
+-module(cerl_hipeify).
+
+-export([transform/2]).
+
+-define(PRIMOP_IDENTITY, identity). % arity 1
+-define(PRIMOP_NOT, 'not'). % arity 1
+-define(PRIMOP_AND, 'and'). % arity 2
+-define(PRIMOP_OR, 'or'). % arity 2
+-define(PRIMOP_XOR, 'xor'). % arity 2
+-define(PRIMOP_ADD, '+'). % arity 2
+-define(PRIMOP_SUB, '-'). % arity 2
+-define(PRIMOP_NEG, neg). % arity 1
+-define(PRIMOP_MUL, '*'). % arity 2
+-define(PRIMOP_DIV, '/'). % arity 2
+-define(PRIMOP_INTDIV, 'div'). % arity 2
+-define(PRIMOP_REM, 'rem'). % arity 2
+-define(PRIMOP_BAND, 'band'). % arity 2
+-define(PRIMOP_BOR, 'bor'). % arity 2
+-define(PRIMOP_BXOR, 'bxor'). % arity 2
+-define(PRIMOP_BNOT, 'bnot'). % arity 1
+-define(PRIMOP_BSL, 'bsl'). % arity 2
+-define(PRIMOP_BSR, 'bsr'). % arity 2
+-define(PRIMOP_EQ, '=='). % arity 2
+-define(PRIMOP_NE, '/='). % arity 2
+-define(PRIMOP_EXACT_EQ, '=:='). % arity 2
+-define(PRIMOP_EXACT_NE, '=/='). % arity 2
+-define(PRIMOP_LT, '<'). % arity 2
+-define(PRIMOP_GT, '>'). % arity 2
+-define(PRIMOP_LE, '=<'). % arity 2
+-define(PRIMOP_GE, '>='). % arity 2
+-define(PRIMOP_IS_ATOM, 'is_atom'). % arity 1
+-define(PRIMOP_IS_BIGNUM, 'is_bignum'). % arity 1
+-define(PRIMOP_IS_BINARY, 'is_binary'). % arity 1
+-define(PRIMOP_IS_CONSTANT, 'is_constant'). % arity 1
+-define(PRIMOP_IS_FIXNUM, 'is_fixnum'). % arity 1
+-define(PRIMOP_IS_FLOAT, 'is_float'). % arity 1
+-define(PRIMOP_IS_FUNCTION, 'is_function'). % arity 1
+-define(PRIMOP_IS_INTEGER, 'is_integer'). % arity 1
+-define(PRIMOP_IS_LIST, 'is_list'). % arity 1
+-define(PRIMOP_IS_NUMBER, 'is_number'). % arity 1
+-define(PRIMOP_IS_PID, 'is_pid'). % arity 1
+-define(PRIMOP_IS_PORT, 'is_port'). % arity 1
+-define(PRIMOP_IS_REFERENCE, 'is_reference'). % arity 1
+-define(PRIMOP_IS_TUPLE, 'is_tuple'). % arity 1
+-define(PRIMOP_IS_RECORD, 'is_record'). % arity 3
+-define(PRIMOP_EXIT, exit). % arity 1
+-define(PRIMOP_THROW, throw). % arity 1
+-define(PRIMOP_ERROR, error). % arity 1,2
+-define(PRIMOP_RETHROW, raise). % arity 2
+-define(PRIMOP_RECEIVE_SELECT, receive_select). % arity 0
+-define(PRIMOP_RECEIVE_NEXT, receive_next). % arity 0
+-define(PRIMOP_ELEMENT, element). % arity 2
+-define(PRIMOP_DSETELEMENT, dsetelement). % arity 3
+-define(PRIMOP_MAKE_FUN, make_fun). % arity 6
+-define(PRIMOP_APPLY_FUN, apply_fun). % arity 2
+-define(PRIMOP_FUN_ELEMENT, closure_element). % arity 2
+-define(PRIMOP_SET_LABEL, set_label). % arity 1
+-define(PRIMOP_GOTO_LABEL, goto_label). % arity 1
+-define(PRIMOP_REDUCTION_TEST, reduction_test). % arity 0
+
+-record(ctxt, {class = expr}).
+
+
+%% @spec transform(Module::cerl(), Options::[term()]) -> cerl()
+%%
+%% cerl() = cerl:cerl()
+%%
+%% @doc Rewrites a Core Erlang module to a form suitable for further
+%% translation to HiPE Icode. See module <code>cerl_to_icode</code> for
+%% details.
+%%
+%% @see cerl_to_icode
+%% @see cerl_cconv
+
+transform(E, Opts) ->
+ %% Start by closure converting the code
+ module(cerl_cconv:transform(E, Opts), Opts).
+
+module(E, Opts) ->
+ {Ds, Env, Ren} = add_defs(cerl:module_defs(E), env__new(),
+ ren__new()),
+ M = cerl:module_name(E),
+ S0 = s__new(cerl:atom_val(M)),
+ S = s__set_pmatch(proplists:get_value(pmatch, Opts), S0),
+ {Ds1, _} = defs(Ds, true, Env, Ren, S),
+ cerl:update_c_module(E, M, cerl:module_exports(E),
+ cerl:module_attrs(E), Ds1).
+
+%% Note that the environment is defined on the renamed variables.
+
+expr(E0, Env, Ren, Ctxt, S0) ->
+ %% Do peephole optimizations as we traverse the code.
+ E = cerl_lib:reduce_expr(E0),
+ case cerl:type(E) of
+ literal ->
+ {E, S0};
+ var ->
+ variable(E, Env, Ren, Ctxt, S0);
+ values ->
+ {Es, S1} = expr_list(cerl:values_es(E), Env, Ren, Ctxt, S0),
+ {cerl:update_c_values(E, Es), S1};
+ cons ->
+ {E1, S1} = expr(cerl:cons_hd(E), Env, Ren, Ctxt, S0),
+ {E2, S2} = expr(cerl:cons_tl(E), Env, Ren, Ctxt, S1),
+ {cerl:update_c_cons(E, E1, E2), S2};
+ tuple ->
+ {Es, S1} = expr_list(cerl:tuple_es(E), Env, Ren, Ctxt, S0),
+ {cerl:update_c_tuple(E, Es), S1};
+ 'let' ->
+ let_expr(E, Env, Ren, Ctxt, S0);
+ seq ->
+ {A, S1} = expr(cerl:seq_arg(E), Env, Ren, Ctxt, S0),
+ {B, S2} = expr(cerl:seq_body(E), Env, Ren, Ctxt, S1),
+ {cerl:update_c_seq(E, A, B), S2};
+ apply ->
+ {Op, S1} = expr(cerl:apply_op(E), Env, Ren, Ctxt, S0),
+ {As, S2} = expr_list(cerl:apply_args(E), Env, Ren, Ctxt, S1),
+ {cerl:update_c_apply(E, Op, As), S2};
+ call ->
+ {M, S1} = expr(cerl:call_module(E), Env, Ren, Ctxt, S0),
+ {N, S2} = expr(cerl:call_name(E), Env, Ren, Ctxt, S1),
+ {As, S3} = expr_list(cerl:call_args(E), Env, Ren, Ctxt, S2),
+ {rewrite_call(E, M, N, As, S3), S3};
+ primop ->
+ {As, S1} = expr_list(cerl:primop_args(E), Env, Ren, Ctxt, S0),
+ N = cerl:primop_name(E),
+ {rewrite_primop(E, N, As, S1), S1};
+ 'case' ->
+ {A, S1} = expr(cerl:case_arg(E), Env, Ren, Ctxt, S0),
+ {E1, Vs, S2} = clauses(cerl:case_clauses(E), Env, Ren, Ctxt, S1),
+ {cerl:c_let(Vs, A, E1), S2};
+ 'fun' ->
+ Vs = cerl:fun_vars(E),
+ {Vs1, Env1, Ren1} = add_vars(Vs, Env, Ren),
+ {B, S1} = expr(cerl:fun_body(E), Env1, Ren1, Ctxt, S0),
+ {cerl:update_c_fun(E, Vs1, B), S1};
+ 'receive' ->
+ receive_expr(E, Env, Ren, Ctxt, S0);
+ 'try' ->
+ {A, S1} = expr(cerl:try_arg(E), Env, Ren, Ctxt, S0),
+ Vs = cerl:try_vars(E),
+ {Vs1, Env1, Ren1} = add_vars(Vs, Env, Ren),
+ {B, S2} = expr(cerl:try_body(E), Env1, Ren1, Ctxt, S1),
+ Evs = cerl:try_evars(E),
+ {Evs1, Env2, Ren2} = add_vars(Evs, Env, Ren),
+ {H, S3} = expr(cerl:try_handler(E), Env2, Ren2, Ctxt, S2),
+ {cerl:update_c_try(E, A, Vs1, B, Evs1, H), S3};
+ 'catch' ->
+ catch_expr(E, Env, Ren, Ctxt, S0);
+ letrec ->
+ {Ds, Env1, Ren1} = add_defs(cerl:letrec_defs(E), Env, Ren),
+ {Ds1, S1} = defs(Ds, false, Env1, Ren1, S0),
+ {B, S2} = expr(cerl:letrec_body(E), Env1, Ren1, Ctxt, S1),
+ {cerl:update_c_letrec(E, Ds1, B), S2};
+ binary ->
+ {Segs, S1}=expr_list(cerl:binary_segments(E), Env, Ren,
+ Ctxt, S0),
+ {cerl:update_c_binary(E, Segs), S1};
+ bitstr ->
+ {E1,S1} = expr(cerl:bitstr_val(E), Env, Ren, Ctxt, S0),
+ {E2,S2} = expr(cerl:bitstr_size(E), Env, Ren, Ctxt, S1),
+ E3 = cerl:bitstr_unit(E),
+ E4 = cerl:bitstr_type(E),
+ E5 = cerl:bitstr_flags(E),
+ {cerl:update_c_bitstr(E, E1, E2, E3, E4, E5), S2}
+ end.
+
+guard_expr(E, Env, Ren, Ctxt, S) ->
+ expr(E, Env, Ren, Ctxt#ctxt{class = guard}, S).
+
+expr_list(Es, Env, Ren, Ctxt, S0) ->
+ list(Es, Env, Ren, Ctxt, S0, fun expr/5).
+
+list([E | Es], Env, Ren, Ctxt, S0, F) ->
+ {E1, S1} = F(E, Env, Ren, Ctxt, S0),
+ {Es1, S2} = list(Es, Env, Ren, Ctxt, S1, F),
+ {[E1 | Es1], S2};
+list([], _, _, _, S, _) ->
+ {[], S}.
+
+pattern(E, Env, Ren) ->
+ case cerl:type(E) of
+ literal ->
+ E;
+ var ->
+ cerl:update_c_var(E, ren__map(cerl:var_name(E), Ren));
+ values ->
+ Es = pattern_list(cerl:values_es(E), Env, Ren),
+ cerl:update_c_values(E, Es);
+ cons ->
+ E1 = pattern(cerl:cons_hd(E), Env, Ren),
+ E2 = pattern(cerl:cons_tl(E), Env, Ren),
+ cerl:update_c_cons(E, E1, E2);
+ tuple ->
+ Es = pattern_list(cerl:tuple_es(E), Env, Ren),
+ cerl:update_c_tuple(E, Es);
+ alias ->
+ V = pattern(cerl:alias_var(E), Env, Ren),
+ P = pattern(cerl:alias_pat(E), Env, Ren),
+ cerl:update_c_alias(E, V, P);
+ binary ->
+ Segs=pattern_list(cerl:binary_segments(E), Env, Ren),
+ cerl:update_c_binary(E, Segs);
+ bitstr ->
+ E1 = pattern(cerl:bitstr_val(E), Env, Ren),
+ E2 = pattern(cerl:bitstr_size(E), Env, Ren),
+ E3 = cerl:bitstr_unit(E),
+ E4 = cerl:bitstr_type(E),
+ E5 = cerl:bitstr_flags(E),
+ cerl:update_c_bitstr(E, E1, E2, E3, E4, E5)
+ end.
+
+
+
+pattern_list([E | Es], Env, Ren) ->
+ [pattern(E, Env, Ren) | pattern_list(Es, Env, Ren)];
+pattern_list([], _, _) ->
+ [].
+
+%% Visit the function body of each definition. We insert an explicit
+%% reduction test at the start of each function.
+
+defs(Ds, Top, Env, Ren, S) ->
+ defs(Ds, [], Top, Env, Ren, S).
+
+defs([{V, F} | Ds], Ds1, Top, Env, Ren, S0) ->
+ S1 = case Top of
+ true -> s__enter_function(cerl:var_name(V), S0);
+ false -> S0
+ end,
+ {B, S2} = expr(cerl:fun_body(F), Env, Ren, #ctxt{}, S1),
+ B1 = cerl:c_seq(cerl:c_primop(cerl:c_atom(?PRIMOP_REDUCTION_TEST),
+ []),
+ B),
+ F1 = cerl:update_c_fun(F, cerl:fun_vars(F), B1),
+ defs(Ds, [{V, F1} | Ds1], Top, Env, Ren, S2);
+defs([], Ds, _Top, _Env, _Ren, S) ->
+ {lists:reverse(Ds), S}.
+
+clauses([C|_]=Cs, Env, Ren, Ctxt, S) ->
+ {Cs1, S1} = clause_list(Cs, Env, Ren, Ctxt, S),
+ %% Perform pattern matching compilation on the clauses.
+ {E, Vs} = case s__get_pmatch(S) of
+ true ->
+ cerl_pmatch:clauses(Cs1, Env);
+ no_duplicates ->
+ put('cerl_pmatch_duplicate_code', never),
+ cerl_pmatch:clauses(Cs1, Env);
+ duplicate_all ->
+ put('cerl_pmatch_duplicate_code', always),
+ cerl_pmatch:clauses(Cs1, Env);
+ Other when Other == false; Other == undefined ->
+ Vs0 = new_vars(cerl:clause_arity(C), Env),
+ {cerl:c_case(cerl:c_values(Vs0), Cs1), Vs0}
+ end,
+ %% We must make sure that we also visit any clause guards generated
+ %% by the pattern matching compilation. We pass an empty renaming,
+ %% so we do not rename any variables twice.
+ {E1, S2} = revisit_expr(E, Env, ren__new(), Ctxt, S1),
+ {E1, Vs, S2}.
+
+clause_list(Cs, Env, Ren, Ctxt, S) ->
+ list(Cs, Env, Ren, Ctxt, S, fun clause/5).
+
+clause(E, Env, Ren, Ctxt, S0) ->
+ Vs = cerl:clause_vars(E),
+ {_, Env1, Ren1} = add_vars(Vs, Env, Ren),
+ %% Visit patterns to rename variables.
+ Ps = pattern_list(cerl:clause_pats(E), Env1, Ren1),
+ {G, S1} = guard_expr(cerl:clause_guard(E), Env1, Ren1, Ctxt, S0),
+ {B, S2} = expr(cerl:clause_body(E), Env1, Ren1, Ctxt, S1),
+ {cerl:update_c_clause(E, Ps, G, B), S2}.
+
+%% This does what 'expr' does, but only recurses into clause guard
+%% expressions, 'case'-expressions, and the bodies of lets and letrecs.
+%% Note that revisiting should not add further renamings, and we simply
+%% ignore making any bindings at all at this level.
+
+revisit_expr(E, Env, Ren, Ctxt, S0) ->
+ %% Also enable peephole optimizations here.
+ revisit_expr_1(cerl_lib:reduce_expr(E), Env, Ren, Ctxt, S0).
+
+revisit_expr_1(E, Env, Ren, Ctxt, S0) ->
+ case cerl:type(E) of
+ 'case' ->
+ {Cs, S1} = revisit_clause_list(cerl:case_clauses(E), Env,
+ Ren, Ctxt, S0),
+ {cerl:update_c_case(E, cerl:case_arg(E), Cs), S1};
+ 'let' ->
+ {B, S1} = revisit_expr(cerl:let_body(E), Env, Ren, Ctxt, S0),
+ {cerl:update_c_let(E, cerl:let_vars(E), cerl:let_arg(E), B),
+ S1};
+ 'letrec' ->
+ {B, S1} = revisit_expr(cerl:letrec_body(E), Env, Ren, Ctxt, S0),
+ {cerl:update_c_letrec(E, cerl:letrec_defs(E), B), S1};
+ _ ->
+ {E, S0}
+ end.
+
+revisit_clause_list(Cs, Env, Ren, Ctxt, S) ->
+ list(Cs, Env, Ren, Ctxt, S, fun revisit_clause/5).
+
+revisit_clause(E, Env, Ren, Ctxt, S0) ->
+ %% Ignore the bindings.
+ {G, S1} = guard_expr(cerl:clause_guard(E), Env, Ren, Ctxt, S0),
+ {B, S2} = revisit_expr(cerl:clause_body(E), Env, Ren, Ctxt, S1),
+ {cerl:update_c_clause(E, cerl:clause_pats(E), G, B), S2}.
+
+%% We use the no-shadowing strategy, renaming variables on the fly and
+%% only when necessary to uphold the invariant.
+
+add_vars(Vs, Env, Ren) ->
+ add_vars(Vs, [], Env, Ren).
+
+add_vars([V | Vs], Vs1, Env, Ren) ->
+ Name = cerl:var_name(V),
+ {Name1, Ren1} = rename(Name, Env, Ren),
+ add_vars(Vs, [cerl:update_c_var(V, Name1) | Vs1],
+ env__bind(Name1, variable, Env), Ren1);
+add_vars([], Vs, Env, Ren) ->
+ {lists:reverse(Vs), Env, Ren}.
+
+rename(Name, Env, Ren) ->
+ case env__is_defined(Name, Env) of
+ false ->
+ {Name, Ren};
+ true ->
+ New = env__new_name(Env),
+ {New, ren__add(Name, New, Ren)}
+ end.
+
+%% Setting up the environment for a list of letrec-bound definitions.
+
+add_defs(Ds, Env, Ren) ->
+ add_defs(Ds, [], Env, Ren).
+
+add_defs([{V, F} | Ds], Ds1, Env, Ren) ->
+ Name = cerl:var_name(V),
+ {Name1, Ren1} =
+ case env__is_defined(Name, Env) of
+ false ->
+ {Name, Ren};
+ true ->
+ {N, A} = Name,
+ S = atom_to_list(N) ++ "_",
+ F = fun (Num) -> %% XXX: BUG: This should be F1
+ {list_to_atom(S ++ integer_to_list(Num)), A}
+ end,
+ New = env__new_function_name(F, Env),
+ {New, ren__add(Name, New, Ren)}
+ end,
+ add_defs(Ds, [{cerl:update_c_var(V, Name1), F} | Ds1],
+ env__bind(Name1, function, Env), Ren1);
+add_defs([], Ds, Env, Ren) ->
+ {lists:reverse(Ds), Env, Ren}.
+
+%% We change remote calls to important built-in functions into primop
+%% calls. In some cases (e.g., for the boolean operators), this is
+%% mainly to allow the cerl_to_icode module to handle them more
+%% straightforwardly. In most cases however, it is simply because they
+%% are supposed to be represented as primop calls on the Icode level.
+
+rewrite_call(E, M, F, As, S) ->
+ case cerl:is_c_atom(M) and cerl:is_c_atom(F) of
+ true ->
+ case call_to_primop(cerl:atom_val(M),
+ cerl:atom_val(F),
+ length(As))
+ of
+ {yes, N} ->
+ %% The primop might need further handling
+ N1 = cerl:c_atom(N),
+ E1 = cerl:update_c_primop(E, N1, As),
+ rewrite_primop(E1, N1, As, S);
+ no ->
+ cerl:update_c_call(E, M, F, As)
+ end;
+ false ->
+ cerl:update_c_call(E, M, F, As)
+ end.
+
+call_to_primop(erlang, 'not', 1) -> {yes, ?PRIMOP_NOT};
+call_to_primop(erlang, 'and', 2) -> {yes, ?PRIMOP_AND};
+call_to_primop(erlang, 'or', 2) -> {yes, ?PRIMOP_OR};
+call_to_primop(erlang, 'xor', 2) -> {yes, ?PRIMOP_XOR};
+call_to_primop(erlang, '+', 2) -> {yes, ?PRIMOP_ADD};
+call_to_primop(erlang, '+', 1) -> {yes, ?PRIMOP_IDENTITY};
+call_to_primop(erlang, '-', 2) -> {yes, ?PRIMOP_SUB};
+call_to_primop(erlang, '-', 1) -> {yes, ?PRIMOP_NEG};
+call_to_primop(erlang, '*', 2) -> {yes, ?PRIMOP_MUL};
+call_to_primop(erlang, '/', 2) -> {yes, ?PRIMOP_DIV};
+call_to_primop(erlang, 'div', 2) -> {yes, ?PRIMOP_INTDIV};
+call_to_primop(erlang, 'rem', 2) -> {yes, ?PRIMOP_REM};
+call_to_primop(erlang, 'band', 2) -> {yes, ?PRIMOP_BAND};
+call_to_primop(erlang, 'bor', 2) -> {yes, ?PRIMOP_BOR};
+call_to_primop(erlang, 'bxor', 2) -> {yes, ?PRIMOP_BXOR};
+call_to_primop(erlang, 'bnot', 1) -> {yes, ?PRIMOP_BNOT};
+call_to_primop(erlang, 'bsl', 2) -> {yes, ?PRIMOP_BSL};
+call_to_primop(erlang, 'bsr', 2) -> {yes, ?PRIMOP_BSR};
+call_to_primop(erlang, '==', 2) -> {yes, ?PRIMOP_EQ};
+call_to_primop(erlang, '/=', 2) -> {yes, ?PRIMOP_NE};
+call_to_primop(erlang, '=:=', 2) -> {yes, ?PRIMOP_EXACT_EQ};
+call_to_primop(erlang, '=/=', 2) -> {yes, ?PRIMOP_EXACT_NE};
+call_to_primop(erlang, '<', 2) -> {yes, ?PRIMOP_LT};
+call_to_primop(erlang, '>', 2) -> {yes, ?PRIMOP_GT};
+call_to_primop(erlang, '=<', 2) -> {yes, ?PRIMOP_LE};
+call_to_primop(erlang, '>=', 2) -> {yes, ?PRIMOP_GE};
+call_to_primop(erlang, is_atom, 1) -> {yes, ?PRIMOP_IS_ATOM};
+call_to_primop(erlang, is_binary, 1) -> {yes, ?PRIMOP_IS_BINARY};
+call_to_primop(erlang, is_constant, 1) -> {yes, ?PRIMOP_IS_CONSTANT};
+call_to_primop(erlang, is_float, 1) -> {yes, ?PRIMOP_IS_FLOAT};
+call_to_primop(erlang, is_function, 1) -> {yes, ?PRIMOP_IS_FUNCTION};
+call_to_primop(erlang, is_integer, 1) -> {yes, ?PRIMOP_IS_INTEGER};
+call_to_primop(erlang, is_list, 1) -> {yes, ?PRIMOP_IS_LIST};
+call_to_primop(erlang, is_number, 1) -> {yes, ?PRIMOP_IS_NUMBER};
+call_to_primop(erlang, is_pid, 1) -> {yes, ?PRIMOP_IS_PID};
+call_to_primop(erlang, is_port, 1) -> {yes, ?PRIMOP_IS_PORT};
+call_to_primop(erlang, is_reference, 1) -> {yes, ?PRIMOP_IS_REFERENCE};
+call_to_primop(erlang, is_tuple, 1) -> {yes, ?PRIMOP_IS_TUPLE};
+call_to_primop(erlang, internal_is_record, 3) -> {yes, ?PRIMOP_IS_RECORD};
+call_to_primop(erlang, element, 2) -> {yes, ?PRIMOP_ELEMENT};
+call_to_primop(erlang, exit, 1) -> {yes, ?PRIMOP_EXIT};
+call_to_primop(erlang, throw, 1) -> {yes, ?PRIMOP_THROW};
+call_to_primop(erlang, error, 1) -> {yes, ?PRIMOP_ERROR};
+call_to_primop(erlang, error, 2) -> {yes, ?PRIMOP_ERROR};
+call_to_primop(erlang, fault, 1) -> {yes, ?PRIMOP_ERROR};
+call_to_primop(erlang, fault, 2) -> {yes, ?PRIMOP_ERROR};
+call_to_primop(_, _, _) -> no.
+
+%% Also, some primops (introduced by Erlang to Core Erlang translation
+%% and possibly other stages) must be recognized and rewritten.
+
+rewrite_primop(E, N, As, S) ->
+ case {cerl:atom_val(N), As} of
+ {match_fail, [R]} ->
+ M = s__get_module_name(S),
+ {F, A} = s__get_function_name(S),
+ Stack = cerl:abstract([{M, F, A}]),
+ case cerl:type(R) of
+ tuple ->
+ %% Function clause failures have a special encoding
+ %% as '{function_clause, Arg1, ..., ArgN}'.
+ case cerl:tuple_es(R) of
+ [X | Xs] ->
+ case cerl:is_c_atom(X) of
+ true ->
+ case cerl:atom_val(X) of
+ function_clause ->
+ FStack = cerl:make_list(
+ [cerl:c_tuple(
+ [cerl:c_atom(M),
+ cerl:c_atom(F),
+ cerl:make_list(Xs)])]),
+ match_fail(E, X, FStack);
+ _ ->
+ match_fail(E, R, Stack)
+ end;
+ false ->
+ match_fail(E, R, Stack)
+ end;
+ _ ->
+ match_fail(E, R, Stack)
+ end;
+ _ ->
+ match_fail(E, R, Stack)
+ end;
+ _ ->
+ cerl:update_c_primop(E, N, As)
+ end.
+
+match_fail(E, R, Stack) ->
+ cerl:update_c_primop(E, cerl:c_atom(?PRIMOP_ERROR), [R, Stack]).
+
+%% Simple let-definitions (of degree 1) in guard context are always
+%% inline expanded. This is allowable, since they cannot have side
+%% effects, and it makes it easy to generate good code for boolean
+%% expressions. It could cause repeated evaluations, but typically,
+%% local definitions within guards are used exactly once.
+
+let_expr(E, Env, Ren, Ctxt, S) ->
+ if Ctxt#ctxt.class == guard ->
+ case cerl:let_vars(E) of
+ [V] ->
+ {Name, Ren1} = rename(cerl:var_name(V), Env, Ren),
+ Env1 = env__bind(Name, {expr, cerl:let_arg(E)}, Env),
+ expr(cerl:let_body(E), Env1, Ren1, Ctxt, S);
+ _ ->
+ let_expr_1(E, Env, Ren, Ctxt, S)
+ end;
+ true ->
+ let_expr_1(E, Env, Ren, Ctxt, S)
+ end.
+
+let_expr_1(E, Env, Ren, Ctxt, S0) ->
+ {A, S1} = expr(cerl:let_arg(E), Env, Ren, Ctxt, S0),
+ Vs = cerl:let_vars(E),
+ {Vs1, Env1, Ren1} = add_vars(Vs, Env, Ren),
+ {B, S2} = expr(cerl:let_body(E), Env1, Ren1, Ctxt, S1),
+ {cerl:update_c_let(E, Vs1, A, B), S2}.
+
+variable(E, Env, Ren, Ctxt, S) ->
+ V = ren__map(cerl:var_name(E), Ren),
+ if Ctxt#ctxt.class == guard ->
+ case env__lookup(V, Env) of
+ {ok, {expr, E1}} ->
+ expr(E1, Env, Ren, Ctxt, S); % inline
+ _ ->
+ %% Since we don't track all bindings when we revisit
+ %% guards, some names will not be in the environment.
+ variable_1(E, V, S)
+ end;
+ true ->
+ variable_1(E, V, S)
+ end.
+
+variable_1(E, V, S) ->
+ {cerl:update_c_var(E, V), S}.
+
+%% A catch-expression 'catch Expr' is rewritten as:
+%%
+%% try Expr
+%% of (V) -> V
+%% catch (T, V, E) ->
+%% letrec 'wrap'/1 = fun (V) -> {'EXIT', V}
+%% in case T of
+%% 'throw' when 'true' -> V
+%% 'exit' when 'true' -> 'wrap'/1(V)
+%% V when 'true' ->
+%% 'wrap'/1({V, erlang:get_stacktrace()})
+%% end
+
+catch_expr(E, Env, Ren, Ctxt, S) ->
+ T = cerl:c_var('T'),
+ V = cerl:c_var('V'),
+ X = cerl:c_var('X'),
+ W = cerl:c_var({wrap,1}),
+ G = cerl:c_call(cerl:c_atom('erlang'),cerl:c_atom('get_stacktrace'),[]),
+ Cs = [cerl:c_clause([cerl:c_atom('throw')], V),
+ cerl:c_clause([cerl:c_atom('exit')], cerl:c_apply(W, [V])),
+ cerl:c_clause([T], cerl:c_apply(W, [cerl:c_tuple([V,G])]))
+ ],
+ C = cerl:c_case(T, Cs),
+ F = cerl:c_fun([V], cerl:c_tuple([cerl:c_atom('EXIT'), V])),
+ H = cerl:c_letrec([{W,F}], C),
+ As = cerl:get_ann(E),
+ {B, S1} = expr(cerl:catch_body(E),Env, Ren, Ctxt, S),
+ {cerl:ann_c_try(As, B, [V], V, [T,V,X], H), S1}.
+
+%% Receive-expressions are rewritten as follows:
+%%
+%% receive
+%% P1 when G1 -> B1
+%% ...
+%% Pn when Gn -> Bn
+%% after T -> A end
+%% becomes:
+%% receive
+%% M when 'true' ->
+%% case M of
+%% P1 when G1 -> do primop RECEIVE_SELECT B1
+%% ...
+%% Pn when Gn -> do primop RECEIVE_SELECT Bn
+%% Pn+1 when 'true' -> primop RECEIVE_NEXT()
+%% end
+%% after T -> A end
+
+receive_expr(E, Env, Ren, Ctxt, S0) ->
+ Cs = cerl:receive_clauses(E),
+ {B, Vs, S1} = clauses(receive_clauses(Cs), Env, Ren, Ctxt, S0),
+ {T, S2} = expr(cerl:receive_timeout(E), Env, Ren, Ctxt, S1),
+ {A, S3} = expr(cerl:receive_action(E), Env, Ren, Ctxt, S2),
+ Cs1 = [cerl:c_clause(Vs, B)],
+ {cerl:update_c_receive(E, Cs1, T, A), S3}.
+
+receive_clauses([C | Cs]) ->
+ Call = cerl:c_primop(cerl:c_atom(?PRIMOP_RECEIVE_SELECT),
+ []),
+ B = cerl:c_seq(Call, cerl:clause_body(C)),
+ C1 = cerl:update_c_clause(C, cerl:clause_pats(C),
+ cerl:clause_guard(C), B),
+ [C1 | receive_clauses(Cs)];
+receive_clauses([]) ->
+ Call = cerl:c_primop(cerl:c_atom(?PRIMOP_RECEIVE_NEXT),
+ []),
+ V = cerl:c_var('X'), % any name is ok
+ [cerl:c_clause([V], Call)].
+
+
+new_vars(N, Env) ->
+ [cerl:c_var(V) || V <- env__new_names(N, Env)].
+
+
+%% ---------------------------------------------------------------------
+%% Environment
+
+env__new() ->
+ rec_env:empty().
+
+env__bind(Key, Value, Env) ->
+ rec_env:bind(Key, Value, Env).
+
+%% env__get(Key, Env) ->
+%% rec_env:get(Key, Env).
+
+env__lookup(Key, Env) ->
+ rec_env:lookup(Key, Env).
+
+env__is_defined(Key, Env) ->
+ rec_env:is_defined(Key, Env).
+
+env__new_name(Env) ->
+ rec_env:new_key(Env).
+
+env__new_names(N, Env) ->
+ rec_env:new_keys(N, Env).
+
+env__new_function_name(F, Env) ->
+ rec_env:new_key(F, Env).
+
+
+%% ---------------------------------------------------------------------
+%% Renaming
+
+ren__new() ->
+ dict:new().
+
+ren__add(Key, Value, Ren) ->
+ dict:store(Key, Value, Ren).
+
+ren__map(Key, Ren) ->
+ case dict:find(Key, Ren) of
+ {ok, Value} ->
+ Value;
+ error ->
+ Key
+ end.
+
+
+%% ---------------------------------------------------------------------
+%% State
+
+-record(state, {module, function, pmatch=true}).
+
+s__new(Module) ->
+ #state{module = Module}.
+
+s__get_module_name(S) ->
+ S#state.module.
+
+s__enter_function(F, S) ->
+ S#state{function = F}.
+
+s__get_function_name(S) ->
+ S#state.function.
+
+s__set_pmatch(V, S) ->
+ S#state{pmatch = V}.
+
+s__get_pmatch(S) ->
+ S#state.pmatch.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/codec_can.erl b/lib/dialyzer/test/small_SUITE_data/src/codec_can.erl
new file mode 100644
index 0000000000..8abf872b37
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/codec_can.erl
@@ -0,0 +1,35 @@
+%%---------------------------------------------------------------------
+%% From: Peer Stritzinger
+%% Date: 1 May 2011
+%% Subject: Dialyzer v2.2.0 crash
+%%
+%% Binaries of the form <<_:N,_:_*M>> in specs resulted in a crash:
+%% dialyzer: Analysis failed with error: {{case_clause,8},
+%% [{erl_types,t_form_to_string,1},
+%% {erl_types,t_form_to_string,1},
+%% {dialyzer_contracts,contract_to_string_1,1},
+%% {dialyzer_contracts,extra_contract_warning,6},
+%% {dialyzer_contracts,picky_contract_check,7},
+%% because function erl_types:t_form_to_string/1 was not the inverse
+%% of erl_types:t_to_string/2.
+%%
+%% Fixed on the same date and send to OTP for inclusion.
+%%---------------------------------------------------------------------
+-module(codec_can).
+
+-export([recv/3, decode/1]).
+
+-record(can_pkt, {id, data :: binary(), timestamp}).
+
+-type can_pkt() :: #can_pkt{}.
+-type channel() :: atom() | pid() | {atom(),_}.
+
+-spec recv(<<_:64,_:_*8>>, fun((can_pkt()) -> R), channel()) -> R.
+recv(Packet, Fun, Chan) ->
+ #can_pkt{id = Can_id, data = Can_data} = P = decode(Packet),
+ Fun(P).
+
+-spec decode(<<_:64,_:_*8>>) -> #can_pkt{id::<<_:11>>,timestamp::char()}.
+decode(<<_:12, Len:4, Timestamp:16, 0:3, Id:11/bitstring, 0:18,
+ Data:Len/binary, _/binary>>) ->
+ #can_pkt{id = Id, data = Data, timestamp = Timestamp}.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_acceptor.erl b/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_acceptor.erl
new file mode 100644
index 0000000000..2ca1468911
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_acceptor.erl
@@ -0,0 +1,119 @@
+% Copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
+%
+% Licensed under the Apache License, Version 2.0 (the "License");
+% you may not use this file except in compliance with the License.
+% You may obtain a copy of the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS,
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+% See the License for the specific language governing permissions and
+% limitations under the License.
+%%%-------------------------------------------------------------------
+%%% File : comm_acceptor.erl
+%%% Author : Thorsten Schuett <[email protected]>
+%%% Description : Acceptor
+%%% This module accepts new connections and starts corresponding
+%%% comm_connection processes.
+%%%
+%%% Created : 18 Apr 2008 by Thorsten Schuett <[email protected]>
+%%%-------------------------------------------------------------------
+%% @author Thorsten Schuett <[email protected]>
+%% @copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
+%% @version $Id $
+-module(comm_layer_dir.comm_acceptor).
+
+-export([start_link/1, init/2]).
+
+-import(config).
+-import(gen_tcp).
+-import(inet).
+-import(log).
+-import(lists).
+-import(process_dictionary).
+
+start_link(InstanceId) ->
+ Pid = spawn_link(comm_layer_dir.comm_acceptor, init, [InstanceId, self()]),
+ receive
+ {started} ->
+ {ok, Pid}
+ end.
+
+init(InstanceId, Supervisor) ->
+ process_dictionary:register_process(InstanceId, acceptor, self()),
+ erlang:register(comm_layer_acceptor, self()),
+ log:log(info,"[ CC ] listening on ~p:~p", [config:listenIP(), config:listenPort()]),
+ LS = case config:listenIP() of
+ undefined ->
+ open_listen_port(config:listenPort(), first_ip());
+ _ ->
+ open_listen_port(config:listenPort(), config:listenIP())
+ end,
+ {ok, {_LocalAddress, LocalPort}} = inet:sockname(LS),
+ comm_port:set_local_address(undefined, LocalPort),
+ %io:format("this() == ~w~n", [{LocalAddress, LocalPort}]),
+ Supervisor ! {started},
+ server(LS).
+
+server(LS) ->
+ case gen_tcp:accept(LS) of
+ {ok, S} ->
+ case comm_port:get_local_address_port() of
+ {undefined, LocalPort} ->
+ {ok, {MyIP, _LocalPort}} = inet:sockname(S),
+ comm_port:set_local_address(MyIP, LocalPort);
+ _ ->
+ ok
+ end,
+ receive
+ {tcp, S, Msg} ->
+ {endpoint, Address, Port} = binary_to_term(Msg),
+ % auto determine remote address, when not sent correctly
+ NewAddress = if Address =:= {0,0,0,0} orelse Address =:= {127,0,0,1} ->
+ case inet:peername(S) of
+ {ok, {PeerAddress, _Port}} ->
+ % io:format("Sent Address ~p\n",[Address]),
+ % io:format("Peername is ~p\n",[PeerAddress]),
+ PeerAddress;
+ {error, _Why} ->
+ % io:format("Peername error ~p\n",[Why]).
+ Address
+ end;
+ true ->
+ % io:format("Address is ~p\n",[Address]),
+ Address
+ end,
+ NewPid = comm_connection:new(NewAddress, Port, S),
+ gen_tcp:controlling_process(S, NewPid),
+ inet:setopts(S, [{active, once}, {send_timeout, config:read(tcp_send_timeout)}]),
+ comm_port:register_connection(NewAddress, Port, NewPid, S)
+ end,
+ server(LS);
+ Other ->
+ log:log(warn,"[ CC ] unknown message ~p", [Other])
+ end.
+
+open_listen_port({From, To}, IP) ->
+ open_listen_port(lists:seq(From, To), IP);
+open_listen_port([Port | Rest], IP) ->
+ case gen_tcp:listen(Port, [binary, {packet, 4}, {reuseaddr, true},
+ {active, once}, {ip, IP}]) of
+ {ok, Socket} ->
+ Socket;
+ {error, Reason} ->
+ log:log(error,"[ CC ] can't listen on ~p: ~p~n", [Port, Reason]),
+ open_listen_port(Rest, IP)
+ end;
+open_listen_port([], _) ->
+ abort;
+open_listen_port(Port, IP) ->
+ open_listen_port([Port], IP).
+
+-include_lib("kernel/include/inet.hrl").
+
+first_ip() ->
+ {ok, Hostname} = inet:gethostname(),
+ {ok, HostEntry} = inet:gethostbyname(Hostname),
+ erlang:hd(HostEntry#hostent.h_addr_list).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_connection.erl b/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_connection.erl
new file mode 100644
index 0000000000..48cc50ae21
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_connection.erl
@@ -0,0 +1,206 @@
+% Copyright 2008 Konrad-Zuse-Zentrum f�r Informationstechnik Berlin
+%
+% Licensed under the Apache License, Version 2.0 (the "License");
+% you may not use this file except in compliance with the License.
+% You may obtain a copy of the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS,
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+% See the License for the specific language governing permissions and
+% limitations under the License.
+%%%-------------------------------------------------------------------
+%%% File : comm_connection.erl
+%%% Author : Thorsten Schuett <[email protected]>
+%%% Description : creates and destroys connections and represents the
+%%% endpoint of a connection where messages are received and
+%% send from/to the network.
+%%%
+%%% Created : 18 Apr 2008 by Thorsten Schuett <[email protected]>
+%%%-------------------------------------------------------------------
+%% @author Thorsten Schuett <[email protected]>
+%% @copyright 2008 Konrad-Zuse-Zentrum f�r Informationstechnik Berlin
+%% @version $Id $
+-module(comm_layer_dir.comm_connection).
+
+-export([send/3, open_new/4, new/3, open_new_async/4]).
+
+-import(config).
+-import(gen_tcp).
+-import(inet).
+-import(io).
+-import(io_lib).
+-import(log).
+-import(timer).
+
+-include("comm_layer.hrl").
+
+%% @doc new accepted connection. called by comm_acceptor
+%% @spec new(inet:ip_address(), int(), socket()) -> pid()
+new(Address, Port, Socket) ->
+ spawn(fun () -> loop(Socket, Address, Port) end).
+
+%% @doc open new connection
+%% @spec open_new(inet:ip_address(), int(), inet:ip_address(), int()) ->
+%% {local_ip, inet:ip_address(), int(), pid(), inet:socket()}
+%% | fail
+%% | {connection, pid(), inet:socket()}
+open_new(Address, Port, undefined, MyPort) ->
+ Myself = self(),
+ LocalPid = spawn(fun () ->
+ case new_connection(Address, Port, MyPort) of
+ fail ->
+ Myself ! {new_connection_failed};
+ Socket ->
+ {ok, {MyIP, _MyPort}} = inet:sockname(Socket),
+ Myself ! {new_connection_started, MyIP, MyPort, Socket},
+ loop(Socket, Address, Port)
+ end
+ end),
+ receive
+ {new_connection_failed} ->
+ fail;
+ {new_connection_started, MyIP, MyPort, S} ->
+ {local_ip, MyIP, MyPort, LocalPid, S}
+ end;
+open_new(Address, Port, _MyAddress, MyPort) ->
+ Owner = self(),
+ LocalPid = spawn(fun () ->
+ case new_connection(Address, Port, MyPort) of
+ fail ->
+ Owner ! {new_connection_failed};
+ Socket ->
+ Owner ! {new_connection_started, Socket},
+ loop(Socket, Address, Port)
+ end
+ end),
+ receive
+ {new_connection_failed} ->
+ fail;
+ {new_connection_started, Socket} ->
+ {connection, LocalPid, Socket}
+ end.
+
+% ===============================================================================
+% @doc open a new connection asynchronously
+% ===============================================================================
+-spec(open_new_async/4 :: (any(), any(), any(), any()) -> pid()).
+open_new_async(Address, Port, _MyAddr, MyPort) ->
+ Pid = spawn(fun () ->
+ case new_connection(Address, Port, MyPort) of
+ fail ->
+ comm_port:unregister_connection(Address, Port),
+ ok;
+ Socket ->
+ loop(Socket, Address, Port)
+ end
+ end),
+ Pid.
+
+
+send({Address, Port, Socket}, Pid, Message) ->
+ BinaryMessage = term_to_binary({deliver, Pid, Message}),
+ SendTimeout = config:read(tcp_send_timeout),
+ {Time, Result} = timer:tc(gen_tcp, send, [Socket, BinaryMessage]),
+ if
+ Time > 1200 * SendTimeout ->
+ log:log(error,"[ CC ] send to ~p took ~p: ~p",
+ [Address, Time, inet:getopts(Socket, [keep_alive, send_timeout])]);
+ true ->
+ ok
+ end,
+ case Result of
+ ok ->
+ ?LOG_MESSAGE(erlang:element(1, Message), byte_size(BinaryMessage)),
+ ok;
+ {error, closed} ->
+ comm_port:unregister_connection(Address, Port),
+ close_connection(Socket);
+ {error, _Reason} ->
+ %log:log(error,"[ CC ] couldn't send to ~p:~p (~p)", [Address, Port, Reason]),
+ comm_port:unregister_connection(Address, Port),
+ close_connection(Socket)
+ end.
+
+loop(fail, Address, Port) ->
+ comm_port:unregister_connection(Address, Port),
+ ok;
+loop(Socket, Address, Port) ->
+ receive
+ {send, Pid, Message} ->
+ case send({Address, Port, Socket}, Pid, Message) of
+ ok -> loop(Socket, Address, Port);
+ _ -> ok
+ end;
+ {tcp_closed, Socket} ->
+ comm_port:unregister_connection(Address, Port),
+ gen_tcp:close(Socket);
+ {tcp, Socket, Data} ->
+ case binary_to_term(Data) of
+ {deliver, Process, Message} ->
+ Process ! Message,
+ inet:setopts(Socket, [{active, once}]),
+ loop(Socket, Address, Port);
+ {user_close} ->
+ comm_port:unregister_connection(Address, Port),
+ gen_tcp:close(Socket);
+ {youare, _Address, _Port} ->
+ %% @TODO what do we get from this information?
+ inet:setopts(Socket, [{active, once}]),
+ loop(Socket, Address, Port);
+ Unknown ->
+ log:log(warn,"[ CC ] unknown message ~p", [Unknown]),
+ inet:setopts(Socket, [{active, once}]),
+ loop(Socket, Address, Port)
+ end;
+
+ {youare, _IP, _Port} ->
+ loop(Socket, Address, Port);
+
+ Unknown ->
+ log:log(warn,"[ CC ] unknown message2 ~p", [Unknown]) ,
+ loop(Socket, Address, Port)
+ end.
+
+% ===============================================================================
+
+-spec(new_connection(inet:ip_address(), integer(), integer()) -> inet:socket() | fail).
+new_connection(Address, Port, MyPort) ->
+ case gen_tcp:connect(Address, Port, [binary, {packet, 4}, {nodelay, true}, {active, once},
+ {send_timeout, config:read(tcp_send_timeout)}],
+ config:read(tcp_connect_timeout)) of
+ {ok, Socket} ->
+ % send end point data
+ case inet:sockname(Socket) of
+ {ok, {MyAddress, _MyPort}} ->
+ Message = term_to_binary({endpoint, MyAddress, MyPort}),
+ gen_tcp:send(Socket, Message),
+ case inet:peername(Socket) of
+ {ok, {RemoteIP, RemotePort}} ->
+ YouAre = term_to_binary({youare, RemoteIP, RemotePort}),
+ gen_tcp:send(Socket, YouAre),
+ Socket;
+ {error, _Reason} ->
+ %log:log(error,"[ CC ] reconnect to ~p because socket is ~p",
+ % [Address, Reason]),
+ close_connection(Socket),
+ new_connection(Address, Port, MyPort)
+ end;
+ {error, _Reason} ->
+ %log:log(error,"[ CC ] reconnect to ~p because socket is ~p",
+ % [Address, Reason]),
+ close_connection(Socket),
+ new_connection(Address, Port, MyPort)
+ end;
+ {error, _Reason} ->
+ %log:log(error,"[ CC ] couldn't connect to ~p:~p (~p)",
+ %[Address, Port, Reason]),
+ fail
+ end.
+
+close_connection(Socket) ->
+ spawn( fun () ->
+ gen_tcp:close(Socket)
+ end ).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_layer.erl b/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_layer.erl
new file mode 100644
index 0000000000..b7fdd183e1
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_layer.erl
@@ -0,0 +1,83 @@
+% Copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
+%
+% Licensed under the Apache License, Version 2.0 (the "License");
+% you may not use this file except in compliance with the License.
+% You may obtain a copy of the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS,
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+% See the License for the specific language governing permissions and
+% limitations under the License.
+%%%-------------------------------------------------------------------
+%%% File : comm_layer.erl
+%%% Author : Thorsten Schuett <[email protected]>
+%%% Description : Public interface to Communication Layer.
+%%% Generic functions to send messages.
+%%% Distinguishes on runtime whether the destination is in the
+%%% same Erlang virtual machine (use ! for sending) or on a remote
+%%% site (use comm_port:send()).
+%%%
+%%% Created : 04 Feb 2008 by Thorsten Schuett <[email protected]>
+%%%-------------------------------------------------------------------
+%% @author Thorsten Schuett <[email protected]>
+%% @copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
+%% @version $Id $
+-module(comm_layer_dir.comm_layer).
+
+-author('[email protected]').
+-vsn('$Id: comm_layer.erl,v 1.1 2009/11/06 12:41:36 maria Exp $ ').
+
+-export([start_link/0, send/2, this/0, here/1]).
+
+-import(io).
+-import(util).
+-import(log).
+
+-include("comm_layer.hrl").
+
+
+% @TODO: should be ip
+-type(process_id() :: {any(), integer(), pid()}).
+%%====================================================================
+%% public functions
+%%====================================================================
+
+%% @doc starts the communication port (for supervisor)
+%% @spec start_link() -> {ok,Pid} | ignore | {error,Error}
+start_link() ->
+ comm_port_sup:start_link().
+
+%% @doc a process descriptor has to specify the erlang vm
+%% + the process inside. {IP address, port, pid}
+%% @type process_id() = {inet:ip_address(), int(), pid()}.
+%% @spec send(process_id(), term()) -> ok
+
+send({{_IP1, _IP2, _IP3, _IP4} = _IP, _Port, _Pid} = Target, Message) ->
+ {MyIP,MyPort} = comm_port:get_local_address_port(),
+ %io:format("send: ~p:~p -> ~p:~p(~p) : ~p\n", [MyIP, MyPort, _IP, _Port, _Pid, Message]),
+ IsLocal = (MyIP == _IP) and (MyPort == _Port),
+ if
+ IsLocal ->
+ ?LOG_MESSAGE(erlang:element(1, Message), byte_size(term_to_binary(Message))),
+ _Pid ! Message;
+ true ->
+ comm_port:send(Target, Message)
+ end;
+
+send(Target, Message) ->
+ log:log(error,"[ CC ] wrong call to cs_send:send: ~w ! ~w", [Target, Message]),
+ log:log(error,"[ CC ] stacktrace: ~w", [util:get_stacktrace()]),
+ ok.
+
+%% @doc returns process descriptor for the calling process
+-spec(this/0 :: () -> atom()).%process_id()).
+this() ->
+ here(self()).
+
+-spec(here/1 :: (pid()) -> process_id()).
+here(Pid) ->
+ {LocalIP, LocalPort} = comm_port:get_local_address_port(),
+ {LocalIP, LocalPort, Pid}.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_layer.hrl b/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_layer.hrl
new file mode 100644
index 0000000000..54f31b7c55
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_layer.hrl
@@ -0,0 +1,29 @@
+% Copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
+%
+% Licensed under the Apache License, Version 2.0 (the "License");
+% you may not use this file except in compliance with the License.
+% You may obtain a copy of the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS,
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+% See the License for the specific language governing permissions and
+% limitations under the License.
+%%%-------------------------------------------------------------------
+%%% File : comm_layer.hrl
+%%% Author : Thorsten Schuett <[email protected]>
+%%% Description :
+%%%
+%%% Created : 31 Jul 2008 by Thorsten Schuett <[email protected]>
+%%%-------------------------------------------------------------------
+%% @author Thorsten Schuett <[email protected]>
+%% @copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
+%% @version $Id: comm_layer.hrl,v 1.1 2009/11/06 12:41:36 maria Exp $
+-author('[email protected]').
+-vsn('$Id: comm_layer.hrl,v 1.1 2009/11/06 12:41:36 maria Exp $ ').
+
+% enable logging of message statistics
+%-define(LOG_MESSAGE(TAG, SIZE), comm_layer.comm_logger:log(TAG, SIZE)).
+-define(LOG_MESSAGE(TAG, SIZE), ok).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_logger.erl b/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_logger.erl
new file mode 100644
index 0000000000..b8882758af
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_logger.erl
@@ -0,0 +1,143 @@
+% Copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
+%
+% Licensed under the Apache License, Version 2.0 (the "License");
+% you may not use this file except in compliance with the License.
+% You may obtain a copy of the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS,
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+% See the License for the specific language governing permissions and
+% limitations under the License.
+%%%-------------------------------------------------------------------
+%%% File : comm_logger.erl
+%%% Author : Thorsten Schuett <[email protected]>
+%%% Description :
+%%%
+%%% Created : 31 Jul 2008 by Thorsten Schuett <[email protected]>
+%%%-------------------------------------------------------------------
+%% @author Thorsten Schuett <[email protected]>
+%% @copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
+%% @version $Id: comm_logger.erl,v 1.1 2009/11/06 12:41:36 maria Exp $
+-module(comm_layer_dir.comm_logger).
+
+-author('[email protected]').
+-vsn('$Id: comm_logger.erl,v 1.1 2009/11/06 12:41:36 maria Exp $ ').
+
+-behaviour(gen_server).
+
+-import(gb_trees).
+-import(gen_server).
+
+%% API
+-export([start_link/0]).
+
+-export([log/2, dump/0]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+-record(state, {start, map}).
+
+%%====================================================================
+%% API
+%%====================================================================
+%%--------------------------------------------------------------------
+%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
+%% Description: Starts the server
+%%--------------------------------------------------------------------
+start_link() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
+%%--------------------------------------------------------------------
+%% Function: log(Tag, Size) -> ok
+%% Description: logs a message type with its size
+%%--------------------------------------------------------------------
+log(Tag, Size) ->
+ gen_server:cast(?MODULE, {log, Tag, Size}).
+
+%%--------------------------------------------------------------------
+%% Function: dump() -> {gb_tree:gb_trees(), {Date, Time}}
+%% Description: gets the logging state
+%%--------------------------------------------------------------------
+dump() ->
+ gen_server:call(?MODULE, {dump}).
+
+%%====================================================================
+%% gen_server callbacks
+%%====================================================================
+
+%%--------------------------------------------------------------------
+%% Function: init(Args) -> {ok, State} |
+%% {ok, State, Timeout} |
+%% ignore |
+%% {stop, Reason}
+%% Description: Initiates the server
+%%--------------------------------------------------------------------
+init([]) ->
+ {ok, #state{start=erlang:now(), map=gb_trees:empty()}}.
+
+%%--------------------------------------------------------------------
+%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
+%% {reply, Reply, State, Timeout} |
+%% {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, Reply, State} |
+%% {stop, Reason, State}
+%% Description: Handling call messages
+%%--------------------------------------------------------------------
+handle_call({dump}, _From, State) ->
+ Reply = {State#state.map, State#state.start},
+ {reply, Reply, State};
+handle_call(_Request, _From, State) ->
+ Reply = ok,
+ {reply, Reply, State}.
+
+%%--------------------------------------------------------------------
+%% Function: handle_cast(Msg, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% Description: Handling cast messages
+%%--------------------------------------------------------------------
+handle_cast({log, Tag, Size}, State) ->
+ case gb_trees:lookup(Tag, State#state.map) of
+ none ->
+ {noreply, State#state{map=gb_trees:insert(Tag, {Size, 1}, State#state.map)}};
+ {value, {OldSize, OldCount}} ->
+ {noreply, State#state{map=gb_trees:update(Tag, {Size + OldSize, OldCount + 1}, State#state.map)}}
+ end;
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% Function: handle_info(Info, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% Description: Handling all non call/cast messages
+%%--------------------------------------------------------------------
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% Function: terminate(Reason, State) -> void()
+%% Description: This function is called by a gen_server when it is about to
+%% terminate. It should be the opposite of Module:init/1 and do any necessary
+%% cleaning up. When it returns, the gen_server terminates with Reason.
+%% The return value is ignored.
+%%--------------------------------------------------------------------
+terminate(_Reason, _State) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% Description: Convert process state when code is changed
+%%--------------------------------------------------------------------
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
diff --git a/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_port.erl b/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_port.erl
new file mode 100644
index 0000000000..e8169b4673
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_port.erl
@@ -0,0 +1,240 @@
+% Copyright 2008 Konrad-Zuse-Zentrum f�r Informationstechnik Berlin
+%
+% Licensed under the Apache License, Version 2.0 (the "License");
+% you may not use this file except in compliance with the License.
+% You may obtain a copy of the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS,
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+% See the License for the specific language governing permissions and
+% limitations under the License.
+%%%-------------------------------------------------------------------
+%%% File : comm_port.erl
+%%% Author : Thorsten Schuett <[email protected]>
+%%% Description : Main CommLayer Interface
+%%% Maps remote addresses to comm_connection PIDs.
+%%%
+%%% Created : 18 Apr 2008 by Thorsten Schuett <[email protected]>
+%%%-------------------------------------------------------------------
+%% @author Thorsten Schuett <[email protected]>
+%% @copyright 2008 Konrad-Zuse-Zentrum f�r Informationstechnik Berlin
+%% @version $Id $
+-module(comm_layer_dir.comm_port).
+
+-author('[email protected]').
+-vsn('$Id: comm_port.erl,v 1.1 2009/11/06 12:41:36 maria Exp $ ').
+
+-behaviour(gen_server).
+
+-import(ets).
+-import(gen_server).
+-import(io).
+-import(log).
+
+-define(ASYNC, true).
+%-define(SYNC, true).
+
+%% API
+-export([start_link/0,
+ send/2,
+ unregister_connection/2, register_connection/4,
+ set_local_address/2, get_local_address_port/0]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+%%====================================================================
+%% API
+%%====================================================================
+
+%% @doc
+%% @spec send({inet:ip_address(), int(), pid()}, term()) -> ok
+-ifdef(ASYNC).
+send({Address, Port, Pid}, Message) ->
+ gen_server:call(?MODULE, {send, Address, Port, Pid, Message}, 20000).
+-endif.
+-ifdef(SYNC).
+send({Address, Port, Pid}, Message) ->
+ case ets:lookup(?MODULE, {Address, Port}) of
+ [{{Address, Port}, {_LPid, Socket}}] ->
+ comm_connection:send({Address, Port, Socket}, Pid, Message),
+ ok;
+ [] ->
+ gen_server:call(?MODULE, {send, Address, Port, Pid, Message}, 20000)
+ end.
+-endif.
+
+
+%% @doc
+%% @spec unregister_connection(inet:ip_address(), int()) -> ok
+unregister_connection(Adress, Port) ->
+ gen_server:call(?MODULE, {unregister_conn, Adress, Port}, 20000).
+
+%% @doc
+%% @spec register_connection(inet:ip_address(), int(), pid(), gen_tcp:socket()) -> ok | duplicate
+register_connection(Adress, Port, Pid, Socket) ->
+ gen_server:call(?MODULE, {register_conn, Adress, Port, Pid, Socket}, 20000).
+
+%% @doc
+%% @spec set_local_address(inet:ip_address(), int()) -> ok
+set_local_address(Address, Port) ->
+ gen_server:call(?MODULE, {set_local_address, Address, Port}, 20000).
+
+
+%% @doc
+%% @spec get_local_address_port() -> {inet:ip_address(),int()}
+get_local_address_port() ->
+ case ets:lookup(?MODULE, local_address_port) of
+ [{local_address_port, Value}] ->
+ Value;
+ [] ->
+ undefined
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
+%% Description: Starts the server
+%%--------------------------------------------------------------------
+start_link() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
+%%====================================================================
+%% gen_server callbacks
+%%====================================================================
+
+%%--------------------------------------------------------------------
+%% Function: init(Args) -> {ok, State} |
+%% {ok, State, Timeout} |
+%% ignore |
+%% {stop, Reason}
+%% Description: Initiates the server
+%%--------------------------------------------------------------------
+init([]) ->
+ ets:new(?MODULE, [set, protected, named_table]),
+ {ok, ok}. % empty state.
+
+%%--------------------------------------------------------------------
+%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
+%% {reply, Reply, State, Timeout} |
+%% {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, Reply, State} |
+%% {stop, Reason, State}
+%% Description: Handling call messages
+%%--------------------------------------------------------------------
+handle_call({send, Address, Port, Pid, Message}, _From, State) ->
+ send(Address, Port, Pid, Message, State);
+
+handle_call({unregister_conn, Address, Port}, _From, State) ->
+ ets:delete(?MODULE, {Address, Port}),
+ {reply, ok, State};
+
+handle_call({register_conn, Address, Port, Pid, Socket}, _From, State) ->
+ case ets:lookup(?MODULE, {Address, Port}) of
+ [{{Address, Port}, _}] ->
+ {reply, duplicate, State};
+ [] ->
+ ets:insert(?MODULE, {{Address, Port}, {Pid, Socket}}),
+ {reply, ok, State}
+ end;
+
+handle_call({set_local_address, Address, Port}, _From, State) ->
+ ets:insert(?MODULE, {local_address_port, {Address,Port}}),
+ {reply, ok, State}.
+
+%%--------------------------------------------------------------------
+%% Function: handle_cast(Msg, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% Description: Handling cast messages
+%%--------------------------------------------------------------------
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% Function: handle_info(Info, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% Description: Handling all non call/cast messages
+%%--------------------------------------------------------------------
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% Function: terminate(Reason, State) -> void()
+%% Description: This function is called by a gen_server when it is about to
+%% terminate. It should be the opposite of Module:init/1 and do any necessary
+%% cleaning up. When it returns, the gen_server terminates with Reason.
+%% The return value is ignored.
+%%--------------------------------------------------------------------
+terminate(_Reason, _State) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% Description: Convert process state when code is changed
+%%--------------------------------------------------------------------
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+
+-ifdef(ASYNC).
+send(Address, Port, Pid, Message, State) ->
+ {DepAddr,DepPort} = get_local_address_port(),
+ if
+ DepAddr == undefined ->
+ open_sync_connection(Address, Port, Pid, Message, State);
+ true ->
+ case ets:lookup(?MODULE, {Address, Port}) of
+ [{{Address, Port}, {ConnPid, _Socket}}] ->
+ ConnPid ! {send, Pid, Message},
+ {reply, ok, State};
+ [] ->
+ ConnPid = comm_connection:open_new_async(Address, Port,
+ DepAddr, DepPort),
+ ets:insert(?MODULE, {{Address, Port}, {ConnPid, undef}}),
+ ConnPid ! {send, Pid, Message},
+ {reply, ok, State}
+ end
+ end.
+-endif.
+
+-ifdef(SYNC).
+send(Address, Port, Pid, Message, State) ->
+ case ets:lookup(?MODULE, {Address, Port}) of
+ [{{Address, Port}, {_LPid, Socket}}] ->
+ comm_connection:send({Address, Port, Socket}, Pid, Message),
+ {reply, ok, State};
+ [] ->
+ open_sync_connection(Address, Port, Pid, Message, State)
+ end.
+-endif.
+
+
+open_sync_connection(Address, Port, Pid, Message, State) ->
+ {DepAddr,DepPort} = get_local_address_port(),
+ case comm_connection:open_new(Address, Port, DepAddr, DepPort) of
+ {local_ip, MyIP, MyPort, MyPid, MySocket} ->
+ comm_connection:send({Address, Port, MySocket}, Pid, Message),
+ log:log(info,"[ CC ] this() == ~w", [{MyIP, MyPort}]),
+ % set_local_address(t, {MyIP,MyPort}}),
+ % register_connection(Address, Port, MyPid, MySocket),
+ ets:insert(?MODULE, {local_address_port, {MyIP,MyPort}}),
+ ets:insert(?MODULE, {{Address, Port}, {MyPid, MySocket}}),
+ {reply, ok, State};
+ fail ->
+ % drop message (remote node not reachable, failure detector will notice)
+ {reply, ok, State};
+ {connection, LocalPid, NewSocket} ->
+ comm_connection:send({Address, Port, NewSocket}, Pid, Message),
+ ets:insert(?MODULE, {{Address, Port}, {LocalPid, NewSocket}}),
+ % register_connection(Address, Port, LPid, NewSocket),
+ {reply, ok, State}
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_port_sup.erl b/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_port_sup.erl
new file mode 100644
index 0000000000..d7a25b14ab
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_port_sup.erl
@@ -0,0 +1,88 @@
+% Copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
+%
+% Licensed under the Apache License, Version 2.0 (the "License");
+% you may not use this file except in compliance with the License.
+% You may obtain a copy of the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS,
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+% See the License for the specific language governing permissions and
+% limitations under the License.
+%%%-------------------------------------------------------------------
+%%% File : comm_port_sup.erl
+%%% Author : Thorsten Schuett <[email protected]>
+%%% Description :
+%%%
+%%% Created : 04 Feb 2008 by Thorsten Schuett <[email protected]>
+%%%-------------------------------------------------------------------
+%% @author Thorsten Schuett <[email protected]>
+%% @copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
+%% @version $Id: comm_port_sup.erl,v 1.1 2009/11/06 12:41:36 maria Exp $
+-module(comm_layer_dir.comm_port_sup).
+
+-author('[email protected]').
+-vsn('$Id: comm_port_sup.erl,v 1.1 2009/11/06 12:41:36 maria Exp $ ').
+
+-behaviour(supervisor).
+
+-import(supervisor).
+-import(randoms).
+-import(string).
+-import(config).
+
+-export([start_link/0, init/1]).
+
+%%====================================================================
+%% API functions
+%%====================================================================
+%%--------------------------------------------------------------------
+%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
+%% Description: Starts the supervisor
+%%--------------------------------------------------------------------
+start_link() ->
+ supervisor:start_link(?MODULE, []).
+
+%%====================================================================
+%% Supervisor callbacks
+%%====================================================================
+%%--------------------------------------------------------------------
+%% Func: init(Args) -> {ok, {SupFlags, [ChildSpec]}} |
+%% ignore |
+%% {error, Reason}
+%% Description: Whenever a supervisor is started using
+%% supervisor:start_link/[2,3], this function is called by the new process
+%% to find out about restart strategy, maximum restart frequency and child
+%% specifications.
+%%--------------------------------------------------------------------
+init([]) ->
+ InstanceId = string:concat("comm_port_", randoms:getRandomId()),
+ CommPort =
+ {comm_port,
+ {comm_layer_dir.comm_port, start_link, []},
+ permanent,
+ brutal_kill,
+ worker,
+ []},
+ CommAcceptor =
+ {comm_acceptor,
+ {comm_layer_dir.comm_acceptor, start_link, [InstanceId]},
+ permanent,
+ brutal_kill,
+ worker,
+ []},
+ CommLogger =
+ {comm_logger,
+ {comm_layer_dir.comm_logger, start_link, []},
+ permanent,
+ brutal_kill,
+ worker,
+ []},
+ {ok, {{one_for_all, 10, 1},
+ [
+ CommPort,
+ CommLogger,
+ CommAcceptor
+ ]}}.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/common_eunit.erl b/lib/dialyzer/test/small_SUITE_data/src/common_eunit.erl
new file mode 100644
index 0000000000..bca390068e
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/common_eunit.erl
@@ -0,0 +1,121 @@
+%%=====================================================================
+%% Program with an erroneous type declaration that caused dialyzer to
+%% go into an infinite loop. There are some comments that explain the
+%% symptoms and the culprit: the return of test_fun() is erroneous and
+%% its type should read
+%% fun((config()) -> test_rep() | [test_rep()])
+%% instead. But this should not throw dialyzer into an infinite loop.
+%% This concerned dialyzer in R14B02 (and probably prior).
+%%=====================================================================
+-module(common_eunit).
+
+-export([expand_cases/2]).
+
+-type test_name() :: atom() | {'group', atom()}.
+
+-type test_rep() :: {{atom(), atom(), arity()}, fun()}
+ | {'setup', fun(), fun()}
+ | {'setup', fun(), fun(), fun()}
+ | {atom(), test_rep()}
+ | {atom(), term(), test_rep()}.
+
+-type config() :: [proplists:property()].
+
+-type control() :: tuple() | atom().
+
+%% The combination of the following type and the (erroneous) spec for
+%% expand_cases/2 is the reason for the infinite loop in dialyzer.
+-type test_fun() :: fun((config()) -> test_rep()).
+
+%% If one comments out this spec the infinite loop disappears.
+-spec expand_cases(atom(), test_name() | [test_name()]) -> test_fun().
+expand_cases(Module, Cases) ->
+ if is_list(Cases) ->
+ TestFuns = [expand_case(Module, Case) || Case <- Cases],
+ fun(Config) -> [F(Config) || F <- TestFuns] end;
+ is_atom(Cases); is_tuple(Cases) ->
+ expand_cases(Module, [Cases])
+ end.
+
+-spec expand_case(atom(), test_name()) -> test_fun().
+expand_case(Module, CaseName) when is_atom(CaseName) ->
+ TestFun = fun(Config) ->
+ {{Module, CaseName, 1},
+ fun() -> apply(Module, CaseName, [Config]) end}
+ end,
+ setup_wrapper(Module, TestFun, {init_per_testcase, [CaseName]},
+ {end_per_testcase, [CaseName]});
+expand_case(Module, {group, GroupName}) ->
+ {Control, Cases} = group_specification(Module, GroupName),
+ TestFun = control_wrapper(Control, expand_cases(Module, Cases)),
+ setup_wrapper(Module, TestFun, {init_per_group, [GroupName]},
+ {end_per_group, [GroupName]}).
+
+-spec control_wrapper([control()], test_fun()) -> test_fun().
+control_wrapper([Control|T], TestFun0) ->
+ TestFun1 = control_wrapper(T, TestFun0),
+ fun(Config) ->
+ case Control of
+ parallel ->
+ {inparallel, TestFun1(Config)};
+ sequence ->
+ {inorder, TestFun1(Config)};
+ {timetrap, Time} ->
+ Seconds = case Time of
+ {hours, Hs} -> Hs * 60 * 60;
+ {minutes, Ms} -> Ms * 60;
+ {seconds, Ss} -> Ss;
+ MSs -> MSs / 1000
+ end,
+ {timeout, Seconds, TestFun1(Config)};
+ C when is_atom(C) ->
+ {C, TestFun1(Config)};
+ {C, Arg} ->
+ {C, Arg, TestFun1(Config)}
+ end
+ end;
+control_wrapper([], TestFun) ->
+ TestFun.
+
+-spec setup_wrapper(atom(), test_fun(), Callback, Callback) -> test_fun()
+ when Callback :: {atom(), list()}.
+setup_wrapper(Module, TestFun, {Setup, SA}, {Cleanup, CA}) ->
+ case erlang:function_exported(Module, Setup, length(SA) + 1) of
+ true ->
+ case erlang:function_exported(Module, Cleanup, length(CA) + 1) of
+ true ->
+ fun(Config0) ->
+ {setup,
+ fun() ->
+ apply(Module, Setup, SA ++ [Config0])
+ end,
+ fun(Config1) ->
+ apply(Module, Cleanup, CA ++ [Config1])
+ end,
+ TestFun}
+ end;
+ false ->
+ fun(Config) ->
+ {setup,
+ fun() ->
+ apply(Module, Setup, SA ++ [Config])
+ end,
+ TestFun}
+ end
+ end;
+ false ->
+ TestFun
+ end.
+
+-spec group_specification(atom(), atom()) -> {[control()], [test_name()]}.
+group_specification(Module, GroupName) ->
+ case lists:keyfind(GroupName, 1, Module:groups()) of
+ {_, Control, Cases} when is_list(Control), is_list(Cases) ->
+ {Control, Cases};
+ {_, Cases} when is_list(Cases) ->
+ {[], Cases};
+ false ->
+ exit({missing_group, GroupName});
+ _ ->
+ exit({bad_group_spec, GroupName})
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/compare1.erl b/lib/dialyzer/test/small_SUITE_data/src/compare1.erl
new file mode 100644
index 0000000000..915ae7621c
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/compare1.erl
@@ -0,0 +1,21 @@
+%%%-------------------------------------------------------------------
+%%% File : compare1.erl
+%%% Author : Tobias Lindahl <[email protected]>
+%%% Description :
+%%%
+%%% Created : 20 Apr 2007 by Tobias Lindahl <[email protected]>
+%%%-------------------------------------------------------------------
+-module(compare1).
+
+-export([t/0]).
+
+t() ->
+ t(42).
+
+t(X) when X > 42 ->
+ error;
+t(X) when X < 42 ->
+ error;
+t(X) when X =/= 42 ->
+ error;
+t(X) -> ok.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/comparisons.erl b/lib/dialyzer/test/small_SUITE_data/src/comparisons.erl
new file mode 100644
index 0000000000..70e3cb6af4
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/comparisons.erl
@@ -0,0 +1,322 @@
+-module(comparisons).
+
+-compile(export_all).
+
+-define(r, get(r)).
+
+integer() -> integer(?r).
+integer(X) when is_integer(X) -> X.
+
+mfloat() -> float(?r).
+mfloat(X) when is_float(X) -> X.
+
+atom() -> atom(?r).
+atom(X) when is_atom(X) -> X.
+
+tuple() -> tuple(?r).
+tuple(X) when is_tuple(X) -> X.
+
+list() -> list(?r).
+list(X) when is_list(X) -> X.
+
+i() -> integer().
+f() -> mfloat().
+n() -> case ?r of 1 -> i(); 2 -> f() end.
+a() -> atom().
+t() -> tuple().
+l() -> list().
+na() -> case ?r of 1 -> n(); 2 -> a() end.
+at() -> case ?r of 1 -> t(); 2 -> a() end.
+tl() -> case ?r of 1 -> t(); 2 -> l() end.
+
+test_i_ll_i() -> case i() < i() of true -> maybe; false -> maybe_too end.
+test_i_le_i() -> case i() =< i() of true -> maybe; false -> maybe_too end.
+test_i_gg_i() -> case i() > i() of true -> maybe; false -> maybe_too end.
+test_i_ge_i() -> case i() >= i() of true -> maybe; false -> maybe_too end.
+test_i_ll_f() -> case i() < f() of true -> maybe; false -> maybe_too end.
+test_i_le_f() -> case i() =< f() of true -> maybe; false -> maybe_too end.
+test_i_gg_f() -> case i() > f() of true -> maybe; false -> maybe_too end.
+test_i_ge_f() -> case i() >= f() of true -> maybe; false -> maybe_too end.
+test_i_ll_n() -> case i() < n() of true -> maybe; false -> maybe_too end.
+test_i_le_n() -> case i() =< n() of true -> maybe; false -> maybe_too end.
+test_i_gg_n() -> case i() > n() of true -> maybe; false -> maybe_too end.
+test_i_ge_n() -> case i() >= n() of true -> maybe; false -> maybe_too end.
+test_i_ll_a() -> case i() < a() of true -> always; false -> never end.
+test_i_le_a() -> case i() =< a() of true -> always; false -> never end.
+test_i_gg_a() -> case i() > a() of true -> never; false -> always end.
+test_i_ge_a() -> case i() >= a() of true -> never; false -> always end.
+test_i_ll_t() -> case i() < t() of true -> always; false -> never end.
+test_i_le_t() -> case i() =< t() of true -> always; false -> never end.
+test_i_gg_t() -> case i() > t() of true -> never; false -> always end.
+test_i_ge_t() -> case i() >= t() of true -> never; false -> always end.
+test_i_ll_l() -> case i() < l() of true -> always; false -> never end.
+test_i_le_l() -> case i() =< l() of true -> always; false -> never end.
+test_i_gg_l() -> case i() > l() of true -> never; false -> always end.
+test_i_ge_l() -> case i() >= l() of true -> never; false -> always end.
+
+test_f_ll_i() -> case f() < i() of true -> maybe; false -> maybe_too end.
+test_f_le_i() -> case f() =< i() of true -> maybe; false -> maybe_too end.
+test_f_gg_i() -> case f() > i() of true -> maybe; false -> maybe_too end.
+test_f_ge_i() -> case f() >= i() of true -> maybe; false -> maybe_too end.
+test_f_ll_f() -> case f() < f() of true -> maybe; false -> maybe_too end.
+test_f_le_f() -> case f() =< f() of true -> maybe; false -> maybe_too end.
+test_f_gg_f() -> case f() > f() of true -> maybe; false -> maybe_too end.
+test_f_ge_f() -> case f() >= f() of true -> maybe; false -> maybe_too end.
+test_f_ll_n() -> case f() < n() of true -> maybe; false -> maybe_too end.
+test_f_le_n() -> case f() =< n() of true -> maybe; false -> maybe_too end.
+test_f_gg_n() -> case f() > n() of true -> maybe; false -> maybe_too end.
+test_f_ge_n() -> case f() >= n() of true -> maybe; false -> maybe_too end.
+test_f_ll_a() -> case f() < a() of true -> always; false -> never end.
+test_f_le_a() -> case f() =< a() of true -> always; false -> never end.
+test_f_gg_a() -> case f() > a() of true -> never; false -> always end.
+test_f_ge_a() -> case f() >= a() of true -> never; false -> always end.
+test_f_ll_t() -> case f() < t() of true -> always; false -> never end.
+test_f_le_t() -> case f() =< t() of true -> always; false -> never end.
+test_f_gg_t() -> case f() > t() of true -> never; false -> always end.
+test_f_ge_t() -> case f() >= t() of true -> never; false -> always end.
+test_f_ll_l() -> case f() < l() of true -> always; false -> never end.
+test_f_le_l() -> case f() =< l() of true -> always; false -> never end.
+test_f_gg_l() -> case f() > l() of true -> never; false -> always end.
+test_f_ge_l() -> case f() >= l() of true -> never; false -> always end.
+
+test_n_ll_i() -> case n() < i() of true -> maybe; false -> maybe_too end.
+test_n_le_i() -> case n() =< i() of true -> maybe; false -> maybe_too end.
+test_n_gg_i() -> case n() > i() of true -> maybe; false -> maybe_too end.
+test_n_ge_i() -> case n() >= i() of true -> maybe; false -> maybe_too end.
+test_n_ll_f() -> case n() < f() of true -> maybe; false -> maybe_too end.
+test_n_le_f() -> case n() =< f() of true -> maybe; false -> maybe_too end.
+test_n_gg_f() -> case n() > f() of true -> maybe; false -> maybe_too end.
+test_n_ge_f() -> case n() >= f() of true -> maybe; false -> maybe_too end.
+test_n_ll_n() -> case n() < n() of true -> maybe; false -> maybe_too end.
+test_n_le_n() -> case n() =< n() of true -> maybe; false -> maybe_too end.
+test_n_gg_n() -> case n() > n() of true -> maybe; false -> maybe_too end.
+test_n_ge_n() -> case n() >= n() of true -> maybe; false -> maybe_too end.
+test_n_ll_a() -> case n() < a() of true -> always; false -> never end.
+test_n_le_a() -> case n() =< a() of true -> always; false -> never end.
+test_n_gg_a() -> case n() > a() of true -> never; false -> always end.
+test_n_ge_a() -> case n() >= a() of true -> never; false -> always end.
+test_n_ll_t() -> case n() < t() of true -> always; false -> never end.
+test_n_le_t() -> case n() =< t() of true -> always; false -> never end.
+test_n_gg_t() -> case n() > t() of true -> never; false -> always end.
+test_n_ge_t() -> case n() >= t() of true -> never; false -> always end.
+test_n_ll_l() -> case n() < l() of true -> always; false -> never end.
+test_n_le_l() -> case n() =< l() of true -> always; false -> never end.
+test_n_gg_l() -> case n() > l() of true -> never; false -> always end.
+test_n_ge_l() -> case n() >= l() of true -> never; false -> always end.
+
+test_a_ll_i() -> case a() < i() of true -> never; false -> always end.
+test_a_le_i() -> case a() =< i() of true -> never; false -> always end.
+test_a_gg_i() -> case a() > i() of true -> always; false -> never end.
+test_a_ge_i() -> case a() >= i() of true -> always; false -> never end.
+test_a_ll_f() -> case a() < f() of true -> never; false -> always end.
+test_a_le_f() -> case a() =< f() of true -> never; false -> always end.
+test_a_gg_f() -> case a() > f() of true -> always; false -> never end.
+test_a_ge_f() -> case a() >= f() of true -> always; false -> never end.
+test_a_ll_n() -> case a() < n() of true -> never; false -> always end.
+test_a_le_n() -> case a() =< n() of true -> never; false -> always end.
+test_a_gg_n() -> case a() > n() of true -> always; false -> never end.
+test_a_ge_n() -> case a() >= n() of true -> always; false -> never end.
+test_a_ll_a() -> case a() < a() of true -> maybe; false -> maybe_too end.
+test_a_le_a() -> case a() =< a() of true -> maybe; false -> maybe_too end.
+test_a_gg_a() -> case a() > a() of true -> maybe; false -> maybe_too end.
+test_a_ge_a() -> case a() >= a() of true -> maybe; false -> maybe_too end.
+test_a_ll_t() -> case a() < t() of true -> always; false -> never end.
+test_a_le_t() -> case a() =< t() of true -> always; false -> never end.
+test_a_gg_t() -> case a() > t() of true -> never; false -> always end.
+test_a_ge_t() -> case a() >= t() of true -> never; false -> always end.
+test_a_ll_l() -> case a() < l() of true -> always; false -> never end.
+test_a_le_l() -> case a() =< l() of true -> always; false -> never end.
+test_a_gg_l() -> case a() > l() of true -> never; false -> always end.
+test_a_ge_l() -> case a() >= l() of true -> never; false -> always end.
+
+test_t_ll_i() -> case t() < i() of true -> never; false -> always end.
+test_t_le_i() -> case t() =< i() of true -> never; false -> always end.
+test_t_gg_i() -> case t() > i() of true -> always; false -> never end.
+test_t_ge_i() -> case t() >= i() of true -> always; false -> never end.
+test_t_ll_f() -> case t() < f() of true -> never; false -> always end.
+test_t_le_f() -> case t() =< f() of true -> never; false -> always end.
+test_t_gg_f() -> case t() > f() of true -> always; false -> never end.
+test_t_ge_f() -> case t() >= f() of true -> always; false -> never end.
+test_t_ll_n() -> case t() < n() of true -> never; false -> always end.
+test_t_le_n() -> case t() =< n() of true -> never; false -> always end.
+test_t_gg_n() -> case t() > n() of true -> always; false -> never end.
+test_t_ge_n() -> case t() >= n() of true -> always; false -> never end.
+test_t_ll_a() -> case t() < a() of true -> never; false -> always end.
+test_t_le_a() -> case t() =< a() of true -> never; false -> always end.
+test_t_gg_a() -> case t() > a() of true -> always; false -> never end.
+test_t_ge_a() -> case t() >= a() of true -> always; false -> never end.
+test_t_ll_t() -> case t() < t() of true -> maybe; false -> maybe_too end.
+test_t_le_t() -> case t() =< t() of true -> maybe; false -> maybe_too end.
+test_t_gg_t() -> case t() > t() of true -> maybe; false -> maybe_too end.
+test_t_ge_t() -> case t() >= t() of true -> maybe; false -> maybe_too end.
+test_t_ll_l() -> case t() < l() of true -> always; false -> never end.
+test_t_le_l() -> case t() =< l() of true -> always; false -> never end.
+test_t_gg_l() -> case t() > l() of true -> never; false -> always end.
+test_t_ge_l() -> case t() >= l() of true -> never; false -> always end.
+
+test_l_ll_i() -> case l() < i() of true -> never; false -> always end.
+test_l_le_i() -> case l() =< i() of true -> never; false -> always end.
+test_l_gg_i() -> case l() > i() of true -> always; false -> never end.
+test_l_ge_i() -> case l() >= i() of true -> always; false -> never end.
+test_l_ll_f() -> case l() < f() of true -> never; false -> always end.
+test_l_le_f() -> case l() =< f() of true -> never; false -> always end.
+test_l_gg_f() -> case l() > f() of true -> always; false -> never end.
+test_l_ge_f() -> case l() >= f() of true -> always; false -> never end.
+test_l_ll_n() -> case l() < n() of true -> never; false -> always end.
+test_l_le_n() -> case l() =< n() of true -> never; false -> always end.
+test_l_gg_n() -> case l() > n() of true -> always; false -> never end.
+test_l_ge_n() -> case l() >= n() of true -> always; false -> never end.
+test_l_ll_a() -> case l() < a() of true -> never; false -> always end.
+test_l_le_a() -> case l() =< a() of true -> never; false -> always end.
+test_l_gg_a() -> case l() > a() of true -> always; false -> never end.
+test_l_ge_a() -> case l() >= a() of true -> always; false -> never end.
+test_l_ll_t() -> case l() < t() of true -> never; false -> always end.
+test_l_le_t() -> case l() =< t() of true -> never; false -> always end.
+test_l_gg_t() -> case l() > t() of true -> always; false -> never end.
+test_l_ge_t() -> case l() >= t() of true -> always; false -> never end.
+test_l_ll_l() -> case l() < l() of true -> maybe; false -> maybe_too end.
+test_l_le_l() -> case l() =< l() of true -> maybe; false -> maybe_too end.
+test_l_gg_l() -> case l() > l() of true -> maybe; false -> maybe_too end.
+test_l_ge_l() -> case l() >= l() of true -> maybe; false -> maybe_too end.
+
+test_n_ll_na() -> case n() < na() of true -> maybe; false -> maybe_too end.
+test_n_le_na() -> case n() =< na() of true -> maybe; false -> maybe_too end.
+test_n_gg_na() -> case n() > na() of true -> maybe; false -> maybe_too end.
+test_n_ge_na() -> case n() >= na() of true -> maybe; false -> maybe_too end.
+test_n_ll_at() -> case n() < at() of true -> always; false -> never end.
+test_n_le_at() -> case n() =< at() of true -> always; false -> never end.
+test_n_gg_at() -> case n() > at() of true -> never; false -> always end.
+test_n_ge_at() -> case n() >= at() of true -> never; false -> always end.
+test_n_ll_tl() -> case n() < tl() of true -> always; false -> never end.
+test_n_le_tl() -> case n() =< tl() of true -> always; false -> never end.
+test_n_gg_tl() -> case n() > tl() of true -> never; false -> always end.
+test_n_ge_tl() -> case n() >= tl() of true -> never; false -> always end.
+
+test_a_ll_na() -> case a() < na() of true -> maybe; false -> maybe_too end.
+test_a_le_na() -> case a() =< na() of true -> maybe; false -> maybe_too end.
+test_a_gg_na() -> case a() > na() of true -> maybe; false -> maybe_too end.
+test_a_ge_na() -> case a() >= na() of true -> maybe; false -> maybe_too end.
+test_a_ll_at() -> case a() < at() of true -> maybe; false -> maybe_too end.
+test_a_le_at() -> case a() =< at() of true -> maybe; false -> maybe_too end.
+test_a_gg_at() -> case a() > at() of true -> maybe; false -> maybe_too end.
+test_a_ge_at() -> case a() >= at() of true -> maybe; false -> maybe_too end.
+test_a_ll_tl() -> case a() < tl() of true -> always; false -> never end.
+test_a_le_tl() -> case a() =< tl() of true -> always; false -> never end.
+test_a_gg_tl() -> case a() > tl() of true -> never; false -> always end.
+test_a_ge_tl() -> case a() >= tl() of true -> never; false -> always end.
+
+test_t_ll_na() -> case t() < na() of true -> never; false -> always end.
+test_t_le_na() -> case t() =< na() of true -> never; false -> always end.
+test_t_gg_na() -> case t() > na() of true -> always; false -> never end.
+test_t_ge_na() -> case t() >= na() of true -> always; false -> never end.
+test_t_ll_at() -> case t() < at() of true -> maybe; false -> maybe_too end.
+test_t_le_at() -> case t() =< at() of true -> maybe; false -> maybe_too end.
+test_t_gg_at() -> case t() > at() of true -> maybe; false -> maybe_too end.
+test_t_ge_at() -> case t() >= at() of true -> maybe; false -> maybe_too end.
+test_t_ll_tl() -> case t() < tl() of true -> maybe; false -> maybe_too end.
+test_t_le_tl() -> case t() =< tl() of true -> maybe; false -> maybe_too end.
+test_t_gg_tl() -> case t() > tl() of true -> maybe; false -> maybe_too end.
+test_t_ge_tl() -> case t() >= tl() of true -> maybe; false -> maybe_too end.
+
+test_l_ll_na() -> case l() < na() of true -> never; false -> always end.
+test_l_le_na() -> case l() =< na() of true -> never; false -> always end.
+test_l_gg_na() -> case l() > na() of true -> always; false -> never end.
+test_l_ge_na() -> case l() >= na() of true -> always; false -> never end.
+test_l_ll_at() -> case l() < at() of true -> never; false -> always end.
+test_l_le_at() -> case l() =< at() of true -> never; false -> always end.
+test_l_gg_at() -> case l() > at() of true -> always; false -> never end.
+test_l_ge_at() -> case l() >= at() of true -> always; false -> never end.
+test_l_ll_tl() -> case l() < tl() of true -> maybe; false -> maybe_too end.
+test_l_le_tl() -> case l() =< tl() of true -> maybe; false -> maybe_too end.
+test_l_gg_tl() -> case l() > tl() of true -> maybe; false -> maybe_too end.
+test_l_ge_tl() -> case l() >= tl() of true -> maybe; false -> maybe_too end.
+
+test_na_ll_n() -> case na() < n() of true -> maybe; false -> maybe_too end.
+test_na_le_n() -> case na() =< n() of true -> maybe; false -> maybe_too end.
+test_na_gg_n() -> case na() > n() of true -> maybe; false -> maybe_too end.
+test_na_ge_n() -> case na() >= n() of true -> maybe; false -> maybe_too end.
+test_na_ll_a() -> case na() < a() of true -> maybe; false -> maybe_too end.
+test_na_le_a() -> case na() =< a() of true -> maybe; false -> maybe_too end.
+test_na_gg_a() -> case na() > a() of true -> maybe; false -> maybe_too end.
+test_na_ge_a() -> case na() >= a() of true -> maybe; false -> maybe_too end.
+test_na_ll_t() -> case na() < t() of true -> always; false -> never end.
+test_na_le_t() -> case na() =< t() of true -> always; false -> never end.
+test_na_gg_t() -> case na() > t() of true -> never; false -> always end.
+test_na_ge_t() -> case na() >= t() of true -> never; false -> always end.
+test_na_ll_l() -> case na() < l() of true -> always; false -> never end.
+test_na_le_l() -> case na() =< l() of true -> always; false -> never end.
+test_na_gg_l() -> case na() > l() of true -> never; false -> always end.
+test_na_ge_l() -> case na() >= l() of true -> never; false -> always end.
+
+test_at_ll_n() -> case at() < n() of true -> never; false -> always end.
+test_at_le_n() -> case at() =< n() of true -> never; false -> always end.
+test_at_gg_n() -> case at() > n() of true -> always; false -> never end.
+test_at_ge_n() -> case at() >= n() of true -> always; false -> never end.
+test_at_ll_a() -> case at() < a() of true -> maybe; false -> maybe_too end.
+test_at_le_a() -> case at() =< a() of true -> maybe; false -> maybe_too end.
+test_at_gg_a() -> case at() > a() of true -> maybe; false -> maybe_too end.
+test_at_ge_a() -> case at() >= a() of true -> maybe; false -> maybe_too end.
+test_at_ll_t() -> case at() < t() of true -> maybe; false -> maybe_too end.
+test_at_le_t() -> case at() =< t() of true -> maybe; false -> maybe_too end.
+test_at_gg_t() -> case at() > t() of true -> maybe; false -> maybe_too end.
+test_at_ge_t() -> case at() >= t() of true -> maybe; false -> maybe_too end.
+test_at_ll_l() -> case at() < l() of true -> always; false -> never end.
+test_at_le_l() -> case at() =< l() of true -> always; false -> never end.
+test_at_gg_l() -> case at() > l() of true -> never; false -> always end.
+test_at_ge_l() -> case at() >= l() of true -> never; false -> always end.
+
+test_tl_ll_n() -> case tl() < n() of true -> never; false -> always end.
+test_tl_le_n() -> case tl() =< n() of true -> never; false -> always end.
+test_tl_gg_n() -> case tl() > n() of true -> always; false -> never end.
+test_tl_ge_n() -> case tl() >= n() of true -> always; false -> never end.
+test_tl_ll_a() -> case tl() < a() of true -> never; false -> always end.
+test_tl_le_a() -> case tl() =< a() of true -> never; false -> always end.
+test_tl_gg_a() -> case tl() > a() of true -> always; false -> never end.
+test_tl_ge_a() -> case tl() >= a() of true -> always; false -> never end.
+test_tl_ll_t() -> case tl() < t() of true -> maybe; false -> maybe_too end.
+test_tl_le_t() -> case tl() =< t() of true -> maybe; false -> maybe_too end.
+test_tl_gg_t() -> case tl() > t() of true -> maybe; false -> maybe_too end.
+test_tl_ge_t() -> case tl() >= t() of true -> maybe; false -> maybe_too end.
+test_tl_ll_l() -> case tl() < l() of true -> maybe; false -> maybe_too end.
+test_tl_le_l() -> case tl() =< l() of true -> maybe; false -> maybe_too end.
+test_tl_gg_l() -> case tl() > l() of true -> maybe; false -> maybe_too end.
+test_tl_ge_l() -> case tl() >= l() of true -> maybe; false -> maybe_too end.
+
+test_na_ll_na() -> case na() < na() of true -> maybe; false -> maybe_too end.
+test_na_le_na() -> case na() =< na() of true -> maybe; false -> maybe_too end.
+test_na_gg_na() -> case na() > na() of true -> maybe; false -> maybe_too end.
+test_na_ge_na() -> case na() >= na() of true -> maybe; false -> maybe_too end.
+test_na_ll_at() -> case na() < at() of true -> maybe; false -> maybe_too end.
+test_na_le_at() -> case na() =< at() of true -> maybe; false -> maybe_too end.
+test_na_gg_at() -> case na() > at() of true -> maybe; false -> maybe_too end.
+test_na_ge_at() -> case na() >= at() of true -> maybe; false -> maybe_too end.
+test_na_ll_tl() -> case na() < tl() of true -> always; false -> never end.
+test_na_le_tl() -> case na() =< tl() of true -> always; false -> never end.
+test_na_gg_tl() -> case na() > tl() of true -> never; false -> always end.
+test_na_ge_tl() -> case na() >= tl() of true -> never; false -> always end.
+
+test_at_ll_na() -> case at() < na() of true -> maybe; false -> maybe_too end.
+test_at_le_na() -> case at() =< na() of true -> maybe; false -> maybe_too end.
+test_at_gg_na() -> case at() > na() of true -> maybe; false -> maybe_too end.
+test_at_ge_na() -> case at() >= na() of true -> maybe; false -> maybe_too end.
+test_at_ll_at() -> case at() < at() of true -> maybe; false -> maybe_too end.
+test_at_le_at() -> case at() =< at() of true -> maybe; false -> maybe_too end.
+test_at_gg_at() -> case at() > at() of true -> maybe; false -> maybe_too end.
+test_at_ge_at() -> case at() >= at() of true -> maybe; false -> maybe_too end.
+test_at_ll_tl() -> case at() < tl() of true -> maybe; false -> maybe_too end.
+test_at_le_tl() -> case at() =< tl() of true -> maybe; false -> maybe_too end.
+test_at_gg_tl() -> case at() > tl() of true -> maybe; false -> maybe_too end.
+test_at_ge_tl() -> case at() >= tl() of true -> maybe; false -> maybe_too end.
+
+test_tl_ll_na() -> case tl() < na() of true -> never; false -> always end.
+test_tl_le_na() -> case tl() =< na() of true -> never; false -> always end.
+test_tl_gg_na() -> case tl() > na() of true -> always; false -> never end.
+test_tl_ge_na() -> case tl() >= na() of true -> always; false -> never end.
+test_tl_ll_at() -> case tl() < at() of true -> maybe; false -> maybe_too end.
+test_tl_le_at() -> case tl() =< at() of true -> maybe; false -> maybe_too end.
+test_tl_gg_at() -> case tl() > at() of true -> maybe; false -> maybe_too end.
+test_tl_ge_at() -> case tl() >= at() of true -> maybe; false -> maybe_too end.
+test_tl_ll_tl() -> case tl() < tl() of true -> maybe; false -> maybe_too end.
+test_tl_le_tl() -> case tl() =< tl() of true -> maybe; false -> maybe_too end.
+test_tl_gg_tl() -> case tl() > tl() of true -> maybe; false -> maybe_too end.
+test_tl_ge_tl() -> case tl() >= tl() of true -> maybe; false -> maybe_too end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/confusing_record_warning.erl b/lib/dialyzer/test/small_SUITE_data/src/confusing_record_warning.erl
new file mode 100644
index 0000000000..8af74e0914
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/confusing_record_warning.erl
@@ -0,0 +1,19 @@
+%%---------------------------------------------------------------------
+%% A user complained that dialyzer produces a weird warning for the
+%% following program. I explained to him that there is an implicit
+%% assumption that when a record is typed one cannot have types of
+%% the same size which are tagged by the record name whose elements
+%% have different types than the ones declared in the record.
+%%
+%% But the warning from dialyzer was weird nonetheless:
+%% The pattern {'r', [_]} can never match the type any()
+%% We should clearly give some less confusing warning in this case.
+%%---------------------------------------------------------------------
+-module(confusing_record_warning).
+
+-export([test/1]).
+
+-record(r, {field :: binary}).
+
+test({r, [_]}) ->
+ #r{field = <<42>>}.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/confusing_warning.erl b/lib/dialyzer/test/small_SUITE_data/src/confusing_warning.erl
index c82df0f056..c82df0f056 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/confusing_warning.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/confusing_warning.erl
diff --git a/lib/dialyzer/test/small_SUITE_data/src/contract2.erl b/lib/dialyzer/test/small_SUITE_data/src/contract2.erl
new file mode 100644
index 0000000000..211de7f009
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/contract2.erl
@@ -0,0 +1,18 @@
+-module(contract2).
+-export([test/2]).
+
+-spec test(list(), list()) -> ok.
+
+test([], []) ->
+ ok;
+test([], L) ->
+ raise(L);
+test([H|T], L) ->
+ case H of
+ true -> test(T, L);
+ false -> test(T, [H|L])
+ end.
+
+-spec raise(_) -> no_return().
+raise(X) ->
+ throw(X).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/contract3.erl b/lib/dialyzer/test/small_SUITE_data/src/contract3.erl
new file mode 100644
index 0000000000..5b0bee9694
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/contract3.erl
@@ -0,0 +1,33 @@
+%%%-------------------------------------------------------------------
+%%% File : contract3.erl
+%%% Author : Tobias Lindahl <[email protected]>
+%%% Description : Check overloaded domains
+%%%
+%%% Created : 2 Nov 2007 by Tobias Lindahl <[email protected]>
+%%%-------------------------------------------------------------------
+-module(contract3).
+
+-export([t/3]).
+
+t(X, Y, Z) ->
+ t1(X),
+ t2(X, Y),
+ t3(X, Y, Z).
+
+-spec t1(atom()|integer()) -> integer();
+ (atom()|list()) -> atom().
+
+t1(X) ->
+ foo:bar(X).
+
+-spec t2(atom(), integer()) -> integer();
+ (atom(), list()) -> atom().
+
+t2(X, Y) ->
+ foo:bar(X, Y).
+
+-spec t3(atom(), integer(), list()) -> integer();
+ (X, integer(), list()) -> X.
+
+t3(X, Y, Z) ->
+ X.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/contract5.erl b/lib/dialyzer/test/small_SUITE_data/src/contract5.erl
new file mode 100644
index 0000000000..c4c9ac9ebf
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/contract5.erl
@@ -0,0 +1,15 @@
+%%%-------------------------------------------------------------------
+%%% File : contract5.erl
+%%% Author : Tobias Lindahl <[email protected]>
+%%% Description : Excercise modified record types.
+%%%
+%%% Created : 15 Apr 2008 by Tobias Lindahl <[email protected]>
+%%%-------------------------------------------------------------------
+-module(contract5).
+-export([t/0]).
+
+-record(bar, {baz}).
+
+-spec t() -> #bar{baz :: boolean()}.
+
+t() -> #bar{baz = not_a_boolean}.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/disj_norm_form.erl b/lib/dialyzer/test/small_SUITE_data/src/disj_norm_form.erl
new file mode 100644
index 0000000000..fedac566ea
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/disj_norm_form.erl
@@ -0,0 +1,23 @@
+%%%-------------------------------------------------------------------
+%%% File : disj_norm_form.erl
+%%% Author : Tobias Lindahl <[email protected]>
+%%% Description : Exposes a bad behavior in expansion to
+%%% disjunctive normal form of guards.
+%%%
+%%% Created : 24 Aug 2007 by Tobias Lindahl <[email protected]>
+%%%-------------------------------------------------------------------
+-module(disj_norm_form).
+
+-export([t/1]).
+
+-record(foo, {bar}).
+
+t(R) ->
+ if R#foo.bar =:= 1;
+ R#foo.bar =:= 2;
+ R#foo.bar =:= 3;
+ R#foo.bar =:= 4;
+ R#foo.bar =:= 5;
+ R#foo.bar =:= 6 -> ok;
+ true -> error
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/eqeq.erl b/lib/dialyzer/test/small_SUITE_data/src/eqeq.erl
new file mode 100644
index 0000000000..f8989185d4
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/eqeq.erl
@@ -0,0 +1,15 @@
+%%%-------------------------------------------------------------------
+%%% File : eqeq.erl
+%%% Author : Tobias Lindahl <[email protected]>
+%%% Description :
+%%%
+%%% Created : 12 Nov 2007 by Tobias Lindahl <[email protected]>
+%%%-------------------------------------------------------------------
+-module(eqeq).
+
+-export([t/0]).
+
+t() ->
+ comp(3.14, foo).
+
+comp(X, Y) -> X =:= Y.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/ets_select.erl b/lib/dialyzer/test/small_SUITE_data/src/ets_select.erl
new file mode 100644
index 0000000000..17bfb5c8bc
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/ets_select.erl
@@ -0,0 +1,11 @@
+-module(ets_select).
+-export([test/0]).
+
+test() ->
+ Table = ets:new(table, [set,{keypos,1}]),
+ ets:insert(Table, {foo, bar, baz}),
+ foo(Table). % ets:select(Table, [{{'_', '$1', '$2'}, [], ['$$']}]).
+
+foo(Table) ->
+ Tuples = ets:select(Table, [{{'_', '$1', '$2'}, [], ['$$']}]),
+ [list_to_tuple(Tuple) || Tuple <- Tuples].
diff --git a/lib/dialyzer/test/small_SUITE_data/src/ets_update_counter.erl b/lib/dialyzer/test/small_SUITE_data/src/ets_update_counter.erl
new file mode 100644
index 0000000000..057748cfb4
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/ets_update_counter.erl
@@ -0,0 +1,25 @@
+-module(ets_update_counter).
+
+-export([ti/2, tl/2, tn/2, tt/2, tu/3, tmix/3]).
+
+ti(T, K) ->
+ ets:update_counter(T, K, 42).
+
+tl(T, K) ->
+ ets:update_counter(T, K, [{2,1}, {3,2}]).
+
+tn(T, K) ->
+ ets:update_counter(T, K, []).
+
+tt(T, K) ->
+ ets:update_counter(T, K, {4,2}).
+
+tu(T, K, Op) ->
+ ets:update_counter(T, K, Op).
+
+tmix(T, K, Choice) ->
+ Op = get_op(Choice),
+ ets:update_counter(T, K, Op).
+
+get_op(i) -> 42;
+get_op(t) -> {4,2}.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/exhaust_case.erl b/lib/dialyzer/test/small_SUITE_data/src/exhaust_case.erl
new file mode 100644
index 0000000000..4b2c16f8a2
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/exhaust_case.erl
@@ -0,0 +1,23 @@
+%%-------------------------------------------------------------------
+%% File : exhaust_case.erl
+%% Author : Kostis Sagonas <[email protected]>
+%% Description : Tests that Dialyzer warns when it finds an unreachable
+%% case clause (independently of whether ground vs. var).
+%%
+%% Created : 15 Dec 2004 by Kostis Sagonas <[email protected]>
+%%-------------------------------------------------------------------
+
+-module(exhaust_case).
+-export([t/1]).
+
+t(X) when is_integer(X) ->
+ case ret(X) of
+ foo -> ok;
+ bar -> ok;
+ 42 -> ok;
+ _other -> error %% unreachable clause (currently no warning)
+ %% other -> error %% but contrast this with this clause... hmm
+ end.
+
+ret(1) -> foo;
+ret(2) -> bar.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/failing_funs.erl b/lib/dialyzer/test/small_SUITE_data/src/failing_funs.erl
new file mode 100644
index 0000000000..1784c4a494
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/failing_funs.erl
@@ -0,0 +1,250 @@
+-module(failing_funs).
+
+-compile(export_all).
+
+% Crashes with system call. No spec.
+foo1() -> halt().
+
+% Crashes with system call. With spec.
+-spec foo2() -> no_return().
+foo2() -> halt().
+
+% Crashes on its own. No spec.
+foo3() -> case a of b -> ok end.
+
+% Crashes on its own. With spec.
+-spec foo4() -> no_return().
+foo4() -> case a of b -> ok end.
+
+% Creates fun that crashes with system call. No spec.
+foo5() -> fun() -> halt() end.
+
+% Creates fun that crashes with system call. With spec.
+-spec foo6() -> fun(() -> no_return()).
+foo6() -> fun() -> halt() end.
+
+% Creates fun from named fun that will crash. Neither have spec.
+foo7() -> fun foo1/0.
+
+% Creates fun from named fun that will crash. Has spec.
+-spec foo8() -> fun(() -> no_return()).
+foo8() -> fun foo1/0.
+
+% Creates fun from named fun that will crash. Named has spec.
+foo9() -> fun foo2/0.
+
+% Creates fun from named fun that will crash. Both have specs.
+-spec foo10() -> fun(() -> no_return()).
+foo10() -> fun foo2/0.
+
+% Creates fun from named fun that will crash. Neither have spec.
+foo11() -> fun foo3/0.
+
+% Creates fun from named fun that will crash. Has spec.
+-spec foo12() -> fun(() -> no_return()).
+foo12() -> fun foo3/0.
+
+% Creates fun from named fun that will crash. Named has spec.
+foo13() -> fun foo4/0.
+
+% Creates fun from named fun that will crash. Both have specs.
+-spec foo14() -> fun(() -> no_return()).
+foo14() -> fun foo4/0.
+
+% Creates fun calling a named fun that will crash. Neither have spec.
+foo15() -> fun() -> foo1() end.
+
+% Creates fun calling a named fun that will crash. Has spec.
+-spec foo16() -> fun(() -> no_return()).
+foo16() -> fun() -> foo1() end.
+
+% Creates fun calling a named fun that will crash. Named has spec.
+foo17() -> fun() -> foo2() end.
+
+% Creates fun calling a named fun that will crash. Both have specs.
+-spec foo18() -> fun(() -> no_return()).
+foo18() -> fun() -> foo2() end.
+
+% Creates fun calling a named fun that will crash. Neither have spec.
+foo19() -> fun() -> foo3() end.
+
+% Creates fun calling a named fun that will crash. Has spec.
+-spec foo20() -> fun(() -> no_return()).
+foo20() -> fun() -> foo3() end.
+
+% Creates fun calling a named fun that will crash. Named has spec.
+foo21() -> fun() -> foo4() end.
+
+% Creates fun calling a named fun that will crash. Both have specs.
+-spec foo22() -> fun(() -> no_return()).
+foo22() -> fun() -> foo4() end.
+
+% Creates two funs with no local return and will return one or die. No spec.
+foo23() ->
+ Bomb = fun() -> halt() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> halt() end
+ end.
+
+% Creates two funs with no local return and will return one or die. With spec.
+-spec foo24() -> fun(() -> no_return()).
+foo24() ->
+ Bomb = fun() -> halt() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> halt() end
+ end.
+
+% Creates two funs with no local return and will return one or die. No spec.
+foo25() ->
+ Bomb = fun() -> foo1() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> foo1() end
+ end.
+
+% Creates two funs with no local return and will return one or die. With spec.
+-spec foo26() -> fun(() -> no_return()).
+foo26() ->
+ Bomb = fun foo1/0,
+ case get(42) of
+ a -> Bomb();
+ b -> fun foo1/0
+ end.
+
+% Creates two funs with no local return and will return one or die. No spec.
+foo27() ->
+ Bomb = fun foo1/0,
+ case get(42) of
+ a -> Bomb();
+ b -> fun foo1/0
+ end.
+
+% Creates two funs with no local return and will return one or die. With spec.
+-spec foo28() -> fun(() -> no_return()).
+foo28() ->
+ Bomb = fun() -> foo1() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> foo1() end
+ end.
+
+% Creates two funs with no local return and will return one or die. No spec.
+foo29() ->
+ Bomb = fun() -> foo2() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> foo2() end
+ end.
+
+% Creates two funs with no local return and will return one or die. With spec.
+-spec foo30() -> fun(() -> no_return()).
+foo30() ->
+ Bomb = fun foo2/0,
+ case get(42) of
+ a -> Bomb();
+ b -> fun foo2/0
+ end.
+
+% Creates two funs with no local return and will return one or die. No spec.
+foo31() ->
+ Bomb = fun foo2/0,
+ case get(42) of
+ a -> Bomb();
+ b -> fun foo2/0
+ end.
+
+% Creates two funs with no local return and will return one or die. With spec.
+-spec foo32() -> fun(() -> no_return()).
+foo32() ->
+ Bomb = fun() -> foo2() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> foo2() end
+ end.
+
+% Creates two funs with no local return and will return one or die. No spec.
+foo33() ->
+ Bomb = fun() -> foo3() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> foo3() end
+ end.
+
+% Creates two funs with no local return and will return one or die. With spec.
+-spec foo34() -> fun(() -> no_return()).
+foo34() ->
+ Bomb = fun foo3/0,
+ case get(42) of
+ a -> Bomb();
+ b -> fun foo3/0
+ end.
+
+% Creates two funs with no local return and will return one or die. No spec.
+foo35() ->
+ Bomb = fun foo3/0,
+ case get(42) of
+ a -> Bomb();
+ b -> fun foo3/0
+ end.
+
+% Creates two funs with no local return and will return one or die. With spec.
+-spec foo36() -> fun(() -> no_return()).
+foo36() ->
+ Bomb = fun() -> foo3() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> foo3() end
+ end.
+
+% Creates two funs with no local return and will return one or die. No spec.
+foo37() ->
+ Bomb = fun() -> foo4() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> foo4() end
+ end.
+
+% Creates two funs with no local return and will return one or die. With spec.
+-spec foo38() -> fun(() -> no_return()).
+foo38() ->
+ Bomb = fun foo4/0,
+ case get(42) of
+ a -> Bomb();
+ b -> fun foo4/0
+ end.
+
+% Creates two funs with no local return and will return one or die. No spec.
+foo39() ->
+ Bomb = fun foo4/0,
+ case get(42) of
+ a -> Bomb();
+ b -> fun foo4/0
+ end.
+
+% Creates two funs with no local return and will return one or die. With spec.
+-spec foo40() -> fun(() -> no_return()).
+foo40() ->
+ Bomb = fun() -> foo4() end,
+ case get(42) of
+ a -> Bomb();
+ b -> fun() -> foo4() end
+ end.
+
+% Obtains two funs with no local return and will return one or die. No spec.
+foo41() ->
+ Bomb = foo5(),
+ case get(42) of
+ a -> Bomb();
+ b -> foo5()
+ end.
+
+% Obtains two funs with no local return and will return one or die. With spec.
+-spec foo42() -> fun(() -> no_return()).
+foo42() ->
+ Bomb = foo5(),
+ case get(42) of
+ a -> Bomb();
+ b -> foo5()
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/failing_guard1.erl b/lib/dialyzer/test/small_SUITE_data/src/failing_guard1.erl
new file mode 100644
index 0000000000..9e39975105
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/failing_guard1.erl
@@ -0,0 +1,15 @@
+%%-----------------------------------------------------------------------
+%% Author: Kostis Sagonas (Wed Aug 23 14:54:25 CEST 2006)
+%%
+%% Program to test failing arithmetic comparisons with a number of the
+%% wrong type. The first case is handled properly; the second one is not.
+%% Why?
+%%-----------------------------------------------------------------------
+
+-module(failing_guard1).
+-export([n/1]).
+
+n(N) when (N / 2) =:= 2 -> multiple_of_four;
+n(N) when (N div 3) =:= 2.0 -> multiple_of_six;
+n(N) when (N rem 3) =:= 2.0 -> multiple_of_six;
+n(N) when is_number(N) -> other_number.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/false_false.erl b/lib/dialyzer/test/small_SUITE_data/src/false_false.erl
new file mode 100644
index 0000000000..e8efc42868
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/false_false.erl
@@ -0,0 +1,32 @@
+%%----------------------------------------------------------------------------
+%% Mail from user (username: sauron!) via Dan Gudmundsson (17 Dec 2010).
+%%
+%% tried this on:
+%% Erlang R14B (erts-5.8.1.2) [smp:2:2] [rq:2] [async-threads:0] ...
+%% and got funny diagnostics from dialyzer
+%%
+%% false_false.erl:20: Function false_or/0 has no local return
+%% false_false.erl:25: The variable _ can never match since previous
+%% clauses completely covered the type 'ok'
+%%
+%% Problem in the handling of 'or' with constant 'false' arguments
+%% fixed by Stavros Aronis and Maria Christakis on the same day.
+%%----------------------------------------------------------------------------
+-module(false_false).
+
+-export([false_or/0, wips/0]).
+
+false_or() ->
+ false or false.
+
+wips() ->
+ case new_execute_cmd(random:uniform(2)) of
+ ok -> mostly_good;
+ _ -> and_here_we_are
+ end.
+
+new_execute_cmd(1) ->
+ ok;
+new_execute_cmd(2) ->
+ io:format("Surprise result is: ~p~n", [false or false]),
+ false.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl b/lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl
new file mode 100644
index 0000000000..086df3464b
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl
@@ -0,0 +1,24 @@
+%%-----------------------------------------------------------------------
+%% Program that gave erroneous warnings due to missing information about
+%% the {encoding, latin1 | unicode | utf8 | ...} option of file:open/3.
+%%-----------------------------------------------------------------------
+-module(file_open_encoding).
+
+-export([parse/1]).
+
+-spec parse(string()) -> proplists:proplist().
+parse(FileName) ->
+ {ok, IoDevice} = file:open(FileName, [read, binary, {encoding, utf8}]),
+ do_parse(IoDevice, []).
+
+do_parse(IoDevice, ResultSoFar) ->
+ case io:get_line(IoDevice, "") of
+ eof ->
+ file:close(IoDevice),
+ ResultSoFar;
+ <<"--"/utf8, _Comment/binary>> ->
+ do_parse(IoDevice, ResultSoFar);
+ Line ->
+ [Key, Value] = binary:split(Line, [<<": ">>, <<"\n">>], [global, trim]),
+ do_parse(IoDevice, [{binary_to_atom(Key, utf8), Value} | ResultSoFar])
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/flatten.erl b/lib/dialyzer/test/small_SUITE_data/src/flatten.erl
new file mode 100644
index 0000000000..e424d5404c
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/flatten.erl
@@ -0,0 +1,18 @@
+%%%-------------------------------------------------------------------
+%%% File : flatten.erl
+%%% Author : Tobias Lindahl <[email protected]>
+%%% Description :
+%%%
+%%% Created : 4 Nov 2007 by Tobias Lindahl <[email protected]>
+%%%-------------------------------------------------------------------
+-module(flatten).
+
+-export([t/1]).
+
+t(Dir) ->
+ case file:list_dir(Dir) of
+ {ok,FileList} ->
+ FileList;
+ {error,Reason} ->
+ {error,lists:flatten("Can't open directory "++Dir++": "++Reason)}
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/fun_app.erl b/lib/dialyzer/test/small_SUITE_data/src/fun_app.erl
new file mode 100644
index 0000000000..20b6138d26
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/fun_app.erl
@@ -0,0 +1,41 @@
+%% This is taken from the code of distel.
+
+-module(fun_app).
+-export([html_index/2]). % , lines/3, curry/2]).
+
+html_index(file,Dir) ->
+ fold_file(curry(fun lines/3,Dir),[],filename:join([Dir,"doc","man_index.html"])).
+
+fold_file(Fun,Acc0,File) ->
+ {ok, FD} = file:open(File, [read]),
+ Acc = fold_file_lines(FD,Fun,Acc0),
+ file:close(FD),
+ Acc.
+
+fold_file_lines(FD,Fun,Acc) ->
+ case io:get_line(FD, "") of
+ eof -> Acc;
+ Line -> fold_file_lines(FD,Fun,Fun(trim_nl(Line),Acc))
+ end.
+
+trim_nl(Str) -> lists:reverse(tl(lists:reverse(Str))).
+
+lines(Line,_,Dir) ->
+ case string:tokens(Line, "<> \"") of
+ ["TD", "A", "HREF=", "../"++Href, M|_] ->
+ case filename:basename(Href, ".html") of
+ "index" -> ok;
+ M -> e_set({file,M}, filename:join([Dir,Href]))
+ end;
+ _ -> ok
+ end.
+
+e_set(Key,Val) -> ets:insert(?MODULE, {Key,Val}).
+
+curry(F, Arg) ->
+ case erlang:fun_info(F,arity) of
+ {_,1} -> fun() -> F(Arg) end;
+ {_,2} -> fun(A) -> F(A,Arg) end;
+ {_,3} -> fun(A,B) -> F(A,B,Arg) end;
+ {_,4} -> fun(A,B,C) -> F(A,B,C,Arg) end
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/fun_ref_match.erl b/lib/dialyzer/test/small_SUITE_data/src/fun_ref_match.erl
new file mode 100644
index 0000000000..31e6bdfb47
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/fun_ref_match.erl
@@ -0,0 +1,21 @@
+%%%-------------------------------------------------------------------
+%%% File : fun_ref_match.erl
+%%% Author : Tobias Lindahl <[email protected]>
+%%% Description : Find that newly created funs and references cannot
+%%% match on earlier bound variables.
+%%%
+%%% Created : 10 Mar 2005 by Tobias Lindahl <[email protected]>
+%%%-------------------------------------------------------------------
+-module(fun_ref_match).
+
+-export([t1/1, t2/1]).
+
+t1(X) ->
+ X = fun(Y) -> Y end,
+ ok.
+
+t2(X) ->
+ case make_ref() of
+ X -> error;
+ _ -> ok
+ end.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/fun_ref_record.erl b/lib/dialyzer/test/small_SUITE_data/src/fun_ref_record.erl
index eace7a4332..eace7a4332 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/fun_ref_record.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/fun_ref_record.erl
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/gencall.erl b/lib/dialyzer/test/small_SUITE_data/src/gencall.erl
index d2875c9df1..d2875c9df1 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/gencall.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/gencall.erl
diff --git a/lib/dialyzer/test/small_SUITE_data/src/gs_make.erl b/lib/dialyzer/test/small_SUITE_data/src/gs_make.erl
new file mode 100644
index 0000000000..2842e773c4
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/gs_make.erl
@@ -0,0 +1,260 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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: gs_make.erl,v 1.1 2008/12/17 09:53:50 mikpe Exp $
+%%
+-module(gs_make).
+
+-export([start/0]).
+
+start() ->
+ Terms = the_config(),
+ DB=fill_ets(Terms),
+ {ok,OutFd} = file:open("gstk_generic.hrl", [write]),
+ put(stdout,OutFd),
+% io:format("terms: ~p ~n ets:~p~n",[Terms,ets:tab2list(DB)]),
+ p("% Don't edit this file. It was generated by gs_make:start/0 "),
+ p("at ~p-~p-~p, ~p:~p:~p.\n\n",
+ lists:append(tuple_to_list(date()),tuple_to_list(time()))),
+ gen_out_opts(DB),
+ gen_read(DB),
+ file:close(OutFd),
+ {ok,"gstk_generic.hrl",DB}.
+
+fill_ets(Terms) ->
+ DB = ets:new(gs_mapping,[bag,public]),
+ fill_ets(DB,Terms).
+
+fill_ets(DB,[]) -> DB;
+fill_ets(DB,[{Objs,Opt,Fun,Access}|Terms]) ->
+ fill_ets(DB,lists:flatten(Objs),Opt,Fun,Access),
+ fill_ets(DB,Terms).
+
+fill_ets(_DB,[],_,_,_) -> done;
+fill_ets(DB,[Obj|Objs],Opt,Fun,rw) ->
+ ets:insert(DB,{Obj,Opt,Fun,read}),
+ ets:insert(DB,{Obj,Opt,Fun,write}),
+ fill_ets(DB,Objs,Opt,Fun,rw);
+fill_ets(DB,[Obj|Objs],Opt,Fun,r) ->
+ ets:insert(DB,{Obj,Opt,Fun,read}),
+ fill_ets(DB,Objs,Opt,Fun,r);
+fill_ets(DB,[Obj|Objs],Opt,Fun,w) ->
+ ets:insert(DB,{Obj,Opt,Fun,write}),
+ fill_ets(DB,Objs,Opt,Fun,w).
+
+
+
+gen_out_opts(DB) ->
+ ObjTypes = lists:flatten(ordsets:from_list(ets:match(DB,{'$1','_','_',write}))),
+ p("out_opts([Option|Options],Gstkid,TkW,DB,ExtraArg,S,P,C) ->\n"),
+ p(" {Opt,Val} =\n"),
+ p(" case Option of \n"),
+ p(" {{default,Cat,Key},V} -> {default,{Cat,{Key,V}}};\n"),
+ p(" {_Key,_V} -> Option;\n"),
+ p(" {default,Cat,Opti} -> {default,{Cat,Opti}};\n"),
+ p(" Atom when atom(Atom) -> {Atom,undefined};\n"),
+ p(" _ -> {error, {invalid_option,Option}}\n"),
+ p(" end,\n"),
+ p(" case Gstkid#gstkid.objtype of\n"),
+ gen_out_type_case_clauses(merge_types(ObjTypes),DB),
+ p(" Q -> exit({internal_error,unknown_objtype,Q})\n"),
+ p(" end;\n"),
+ p("out_opts([],_Gstkid,_TkW,_DB,_ExtraArg,S,P,C) -> \n"),
+ p(" {S,P,C}.\n").
+
+
+gen_out_type_case_clauses([],_DB) -> done;
+gen_out_type_case_clauses([Objtype|Objtypes],DB) ->
+ OptsFuns = lists:map(fun (L) -> list_to_tuple(L) end,
+ ets:match(DB,{Objtype,'$1','$2',write})),
+ p(" ~p -> \ncase Opt of\n",[Objtype]),
+ gen_opt_case_clauses(merge_opts(opt_prio(),OptsFuns)),
+ p(" _ -> \n"),
+ p(" handle_external_opt_call([Option|Options],Gstkid,TkW,DB,ExtraArg,"
+ " gstk_~p:option(Option,Gstkid,TkW,DB,ExtraArg),S,P,C)\n",
+ [Objtype]),
+ p(" end;\n"),
+ gen_out_type_case_clauses(Objtypes,DB).
+
+gen_opt_case_clauses([]) ->
+ done;
+gen_opt_case_clauses([{Opt,Fun}|OptFuncs]) ->
+ p(" ~p ->\n",[Opt]),
+ p(" ~p(Val,Options,Gstkid,TkW,DB,ExtraArg,S,P,C);\n",[Fun]),
+ gen_opt_case_clauses(OptFuncs).
+
+gen_read(DB) ->
+ ObjTypes = lists:flatten(ordsets:from_list(ets:match(DB,{'$1','_','_',read}))),
+ p("read_option(DB,Gstkid,TkW,Option,ExtraArg) ->\n"),
+ p(" Key = case Option of\n"),
+ p(" Atom when atom(Atom) -> Atom;\n"),
+ p(" Opt when tuple(Opt) -> element(1,Opt)\n"),
+ p(" end,\n"),
+ p(" case Gstkid#gstkid.objtype of\n"),
+ gen_read_type_clauses(merge_types(ObjTypes),DB),
+ p(" Q -> exit({internal_error,unknown_objtype,Q})\n"),
+ p(" end.\n").
+
+
+gen_read_type_clauses([],_) -> done;
+gen_read_type_clauses([Objtype|Objtypes],DB) ->
+ OptsFuns = lists:map(fun (L) -> list_to_tuple(L) end,
+ ets:match(DB,{Objtype,'$1','$2',read})),
+ p(" ~p -> \ncase Key of\n",[Objtype]),
+ gen_readopt_case_clauses(merge_opts(opt_prio(),OptsFuns)),
+ p(" _ -> \nhandle_external_read(gstk_~p:read_option(Option,Gstkid,TkW,DB,ExtraArg))\n",[Objtype]),
+ p(" end;\n"),
+ gen_read_type_clauses(Objtypes,DB).
+
+gen_readopt_case_clauses([]) ->
+ done;
+gen_readopt_case_clauses([{Opt,Fun}|OptFuncs]) ->
+ p(" ~p -> \n~p(Option,Gstkid,TkW,DB,ExtraArg);\n",[Opt,Fun]),
+ gen_readopt_case_clauses(OptFuncs).
+
+
+p(Str) ->
+ ok = io:format(get(stdout),Str,[]).
+
+p(Format,Data) ->
+ ok = io:format(get(stdout),Format,Data).
+
+%%----------------------------------------------------------------------
+%% There items should be placed early in a case statement.
+%%----------------------------------------------------------------------
+obj_prio() -> [rectangle,line,gridline,image,button,canvas,checkbutton,radiobutton].
+opt_prio() -> [x,y,width,height,move,coords,data].
+
+merge_types(Types) ->
+ T2 = ordsets:from_list(Types),
+ P2 = ordsets:from_list(obj_prio()),
+ obj_prio() ++ ordsets:subtract(T2, P2).
+
+merge_opts([],L) -> L;
+merge_opts([Opt|Opts],Dict) ->
+ case gs:assq(Opt,Dict) of
+ {value,V} -> [{Opt,V}|merge_opts(Opts,lists:keydelete(Opt,1,Dict))];
+ false -> merge_opts(Opts,Dict)
+ end.
+
+the_config() ->
+ Buttons=[button,checkbutton,radiobutton],
+ AllPureTk = [Buttons,canvas,editor,entry,frame,label,listbox,
+ menubar,menubutton,scale,window],
+ CanvasObj = [arc,image,line,oval,polygon,rectangle,text],
+ All = [AllPureTk,CanvasObj,grid,gridline,menu,menuitem,gs],
+ Containers = [canvas,frame,grid,menu,menubar,menubutton,menuitem,window],
+ Ob1 = [Buttons,canvas,grid,frame,label,entry,editor,listbox,scale],
+ Ob2 = [button,checkbutton,radiobutton,label,menubutton],
+ Ob3 = [Buttons,frame,label,entry,editor,listbox,scale,menubutton,
+ menubar,menu],
+ Ob4 = [canvas,editor,listbox],
+ [{[Buttons,entry,scale,menubutton],enable,gen_enable,rw},
+ {[Buttons,label,entry,scale,menubutton,menu],fg,gen_fg,rw},
+ {[Buttons,label,entry,scale,menubutton,menu],bg,gen_bg,rw},
+ {Ob1,anchor,gen_anchor,rw},
+ {Ob1,height,gen_height,r},
+ {Ob1--[frame],height,gen_height,w},
+ {Ob1,width,gen_width,r},
+ {Ob1--[frame],width,gen_width,w},
+ {Ob1,pack_x,gen_pack_x,rw},
+ {Ob1,pack_y,gen_pack_y,rw},
+ {Ob1,pack_xy,gen_pack_xy,w},
+ {Ob1,x,gen_x,rw},
+ {Ob1,y,gen_y,rw},
+ {Ob1,raise,gen_raise,w},
+ {Ob1,lower,gen_lower,w},
+ {Ob2,align,gen_align,rw},
+ {Ob2,font,gen_font,rw},
+ {Ob2,justify,gen_justify,rw},
+ {Ob2,padx,gen_padx,rw},
+ {Ob2,pady,gen_pady,rw},
+ {Containers,default,gen_default,w},
+ {[AllPureTk,menu],relief,gen_relief,rw},
+ {[AllPureTk,menu],bw,gen_bw,rw},
+ {[Buttons,canvas,frame,label,entry,scale,menubutton,menu,menubar],
+ setfocus,gen_setfocus,rw},
+ {Ob3,buttonpress,gen_buttonpress,rw},
+ {Ob3,buttonrelease,gen_buttonrelease,rw},
+ {Ob3,configure,gen_configure,rw},
+ {[Ob3,window],destroy,gen_destroy,rw},
+ {[Ob3,window],enter,gen_enter,rw},
+ {[Ob3,window],leave,gen_leave,rw},
+ {[Ob3,window],focus,gen_focus_ev,rw},
+ {[Ob3,window],keypress,gen_keypress,rw},
+ {[Ob3,window],keyrelease,gen_keyrelease,rw},
+ {Ob3,motion,gen_motion,rw},
+ %% events containing x,y are special
+ {[window],buttonpress,gen_buttonpress,r},
+ {[window],buttonrelease,gen_buttonrelease,r},
+ {[window],motion,gen_motion,r},
+ {All,font_wh,gen_font_wh,r},
+ {All,choose_font,gen_choose_font,r},
+ {All,data,gen_data,rw},
+ {All,children,gen_children,r},
+ {All,id,gen_id,r},
+ {All,parent,gen_parent,r},
+ {All,type,gen_type,r},
+ {All,beep,gen_beep,w},
+ {All,keep_opt,gen_keep_opt,w},
+ {All,flush,gen_flush,rw},
+ {AllPureTk,highlightbw,gen_highlightbw,rw},
+ {AllPureTk,highlightbg,gen_highlightbg,rw},
+ {AllPureTk,highlightfg,gen_highlightfg,rw},
+ {AllPureTk,cursor,gen_cursor,rw}, % bug
+ {[Buttons,label,menubutton],label,gen_label,rw},
+ {[Buttons,menubutton,menu],activebg,gen_activebg,rw},
+ {[Buttons,menubutton,menu],activefg,gen_activefg,rw},
+ {[entry],selectbg,gen_selectbg,rw},
+ {[entry],selectbw,gen_selectbw,rw},
+ {[entry],selectfg,gen_selectfg,rw},
+ {Ob4,activebg,gen_so_activebg,rw},
+ {Ob4,bc,gen_so_bc,rw},
+ {Ob4,bg,gen_so_bg,rw},
+ {Ob4,hscroll,gen_so_hscroll,r},
+ {Ob4,scrollbg,gen_so_scrollbg,rw},
+ {Ob4,scrollfg,gen_so_scrollfg,rw},
+ {Ob4,scrolls,gen_so_scrolls,w},
+ {Ob4,selectbg,gen_so_selectbg,rw},
+ {Ob4,selectbg,gen_so_selectbg,rw},
+ {Ob4,selectbw,gen_so_selectbw,rw},
+ {Ob4,selectbw,gen_so_selectbw,rw},
+ {Ob4,selectfg,gen_so_selectfg,rw},
+ {Ob4,selectfg,gen_so_selectfg,rw},
+ {Ob4,vscroll,gen_so_vscroll,r},
+ {CanvasObj,coords,gen_citem_coords,rw},
+ {CanvasObj,lower,gen_citem_lower,w},
+ {CanvasObj,raise,gen_citem_raise,w},
+ {CanvasObj,move,gen_citem_move,w},
+ {CanvasObj,setfocus,gen_citem_setfocus,rw},
+ {CanvasObj,buttonpress,gen_citem_buttonpress,w}, % should be rw
+ {CanvasObj,buttonrelease,gen_citem_buttonrelease,w},
+ {CanvasObj,enter,gen_citem_enter,w},
+ {CanvasObj,focus,gen_citem_setfocus,w},
+ {CanvasObj,keypress,gen_citem_keypress,w},
+ {CanvasObj,keyrelease,gen_citem_keyrelease,w},
+ {CanvasObj,leave,gen_citem_leave,w},
+ {CanvasObj,motion,gen_citem_motion,w},
+ {CanvasObj,buttonpress,gen_buttonpress,r},
+ {CanvasObj,buttonrelease,gen_buttonrelease,r},
+ {CanvasObj,configure,gen_configure,r},
+ {CanvasObj,destroy,gen_destroy,r},
+ {CanvasObj,enter,gen_enter,r},
+ {CanvasObj,leave,gen_leave,r},
+ {CanvasObj,focus,gen_focus_ev,r},
+ {CanvasObj,keypress,gen_keypress,r},
+ {CanvasObj,keyrelease,gen_keyrelease,r},
+ {CanvasObj,motion,gen_motion,r},
+ {[arc,oval,polygon,rectangle],fill,gen_citem_fill,rw}].
diff --git a/lib/dialyzer/test/small_SUITE_data/src/guard_warnings.erl b/lib/dialyzer/test/small_SUITE_data/src/guard_warnings.erl
new file mode 100644
index 0000000000..6ab13eef9a
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/guard_warnings.erl
@@ -0,0 +1,118 @@
+%%
+%% A couple of tests for booleans in guards.
+%% Tests with suffix w have incomplete results due to weak dataflow.
+%% Tests with suffix ww have incomplete results due to weak dialyzer.
+%% Tests with suffix x should not give warnings.
+%%
+
+-module(and_bug).
+
+-compile(export_all).
+
+test1(X) when X and not X -> never.
+
+test2(X) when not X and X -> never.
+
+test3(X) when (X and not X) =:= true -> never.
+
+test4(X) when (not X and X) =:= true -> never.
+
+test5(X) when (X and not X) == true -> never.
+
+test6(X) when (not X and X) == true -> never.
+
+test7_w(X) when not (X or not X) -> never.
+
+test8_w(X) when not (not X or X) -> never.
+
+test9(X) when (X or not X) =:= false -> never.
+
+test10(X) when (not X or X) =:= false -> never.
+
+test11(X) when (X or not X) == false -> never.
+
+test12(X) when (not X or X) == false -> never.
+
+test13(X) when X and false -> never.
+
+test14(X) when false and X -> never.
+
+test15(X) when (X and false) =:= true -> never.
+
+test16(X) when (false and X) =:= true -> never.
+
+test17(X) when (X and false) == true -> never.
+
+test18(X) when (false and X) == true -> never.
+
+test19(X) when not (true or X) -> never.
+
+test20(X) when not (X or true) -> never.
+
+test21(X) when (true or X) =:= false -> never.
+
+test22(X) when (X or true) =:= false -> never.
+
+test23(X) when (true or X) == false -> never.
+
+test24(X) when (X or true) == false -> never.
+
+test25(X) when (false and X) -> never.
+
+test26(X) when (X and false) -> never.
+
+test27(X) when (false and X) =:= true -> never.
+
+test28(X) when (X and false) =:= true -> never.
+
+test29(X) when (false and X) == true -> never.
+
+test30(X) when (X and false) == true -> never.
+
+test31() when false and false -> never.
+
+test32() when (false and false) =:= true -> never.
+
+test33() when not (true and true) =:= true -> never.
+
+test34() when (false and false) == true -> never.
+
+test35() when not (true and true) == true -> never.
+
+test36() when false or false -> never.
+
+test37() when (false or false) =:= true -> never.
+
+test38() when not (false or false) =:= false -> never.
+
+test39() when (false or false) == true -> never.
+
+test40() when not (false or false) == false -> never.
+
+test41() when true =:= false -> never.
+
+test42() when true == false -> never.
+
+test43() when not (true =:= true) -> never.
+
+test44() when not (true == true) -> never.
+
+test45() when not (not (not (not (not (not (not true)))))) -> never.
+
+test46(X) when (X =:= true) and (X =:= false) -> never.
+
+test47(X) when (X == true) and (X == false) -> never.
+
+test48(X) when is_boolean(X) and (X =:= true) and (X =/= true) -> never.
+
+test49_x(X) when not (X or X) -> maybe.
+
+test50_x(X) when not (X and X) -> maybe.
+
+test51_x(X) when not (not X) -> maybe.
+
+test52_w(X) when is_boolean(X) and (X =/= true) and (X =:= true) -> never.
+
+test53_ww(X) when is_boolean(X) and (X =/= true) and (X =/= false) -> never.
+
+test54_w(X) when is_boolean(X) and not ((X =:= true) or (X =:= false)) -> never.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/guards.erl b/lib/dialyzer/test/small_SUITE_data/src/guards.erl
new file mode 100644
index 0000000000..34c43d6d12
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/guards.erl
@@ -0,0 +1,136 @@
+-module(guards).
+
+-compile([export_all]).
+
+-record(r, {f}).
+
+%% This is the reduced original test (no warnings)
+
+-define(g1(A), ((A#r.f =:= a) orelse (A#r.f =:= b))).
+
+t1(A) when ?g1(A) -> ok;
+t1(A) when not ?g1(A) -> ko.
+
+%% This should emit a warning
+
+t1_s(A) when ?g1(A) -> ok.
+
+t1_s_a() ->
+ t1_s(#r{f=c}).
+
+%% Same as t1 with 'or' instead of 'orelse' (no warnings)
+
+-define(g2(A), ((A#r.f =:= a) or (A#r.f =:= b))).
+
+t2(A) when ?g2(A) -> ok;
+t2(A) when not ?g2(A) -> ko.
+
+%% This should emit a warning
+
+t2_s(A) when ?g2(A) -> ok.
+
+t2_s_a() ->
+ t2_s(#r{f=c}).
+
+%% This could probably give a warning
+
+-define(g3(A), (A#r.f =:= a orelse is_atom(A))).
+
+t3(A) when ?g3(A) -> ok;
+t3(A) when not ?g3(A) -> ko.
+
+%% This could probably give a warning as well
+
+-define(g4(A), ((A#r.f =:= a) or is_atom(A))).
+
+t4(A) when ?g4(A) -> ok;
+t4(A) when not ?g4(A) -> ko.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Some shots in the dark on guard abuse %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Should give a warning
+
+t5(A) when is_atom(A) and is_integer(A) -> never.
+
+%% Should give the same warning as t5
+
+t6(A) when is_atom(A) andalso is_integer(A) -> never.
+
+%% Should give a warning
+
+t7(A) when is_atom(A) or is_integer(A) -> ok.
+
+at7(42) -> t7(42);
+at7('a') -> t7('a');
+at7({42}) -> t7({42}).
+
+%% Should give a warning
+
+t8(A) when is_atom(A) orelse is_integer(A) -> ok.
+
+at8(42) -> t8(42);
+at8('a') -> t8('a');
+at8({42}) -> t8({42}).
+
+%% Should give a warning
+
+t9(A) when is_atom(A) orelse is_integer(A) -> ok;
+t9(A) when is_atom(A) -> redundant.
+
+%% Should give a warning
+
+t10(A) when is_atom(A) or is_integer(A) -> ok;
+t10(A) when is_atom(A) -> redundant.
+
+%% Should give a warning
+
+t11(A, B) when is_atom(A) and is_atom(B) ->
+ case {is_atom(A), is_atom(B)} of
+ {true, true} -> ok;
+ _ -> redundant
+ end.
+
+%% Should give a warning
+
+t12(A, B) when is_atom(A) andalso is_atom(B) ->
+ case {is_atom(A), is_atom(B)} of
+ {true, true} -> ok;
+ _ -> redundant
+ end.
+
+%% Should give two warnings
+
+t13(A, B) when is_atom(A) or is_atom(B) ->
+ case {is_atom(A), is_atom(B)} of
+ {true , true } -> ok;
+ {true , false} -> ok;
+ {false, true } -> ok;
+ {false, false} -> never;
+ {_ , _ } -> even_more_never
+ end.
+
+%% Should give two warnings
+
+t14(A, B) when is_atom(A) orelse is_atom(B) ->
+ case {is_atom(A), is_atom(B)} of
+ {true , true } -> ok;
+ {true , false} -> ok;
+ {false, true } -> ok;
+ {false, false} -> never;
+ {_ , _ } -> even_more_never
+ end.
+
+%% Should give two warnings
+
+t15(A) when ((A =:= a) or (A =:= b)) and ((A =:= b) or (A =:= c)) -> ok.
+
+t15_a() -> t15(a), t15(b), t15(c).
+
+%% Should give two warnings
+
+t16(A) when ((A =:= a) orelse (A =:= b)) andalso
+ ((A =:= b) orelse (A =:= c)) -> ok.
+
+t16_a() -> t16(a), t16(b), t16(c).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/inf_loop2.erl b/lib/dialyzer/test/small_SUITE_data/src/inf_loop2.erl
new file mode 100644
index 0000000000..6ac29116a5
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/inf_loop2.erl
@@ -0,0 +1,23 @@
+%%---------------------------------------------------------------------
+%% Module that went into an infinite loop when trying to assign types.
+%%
+%% What was happening is that for functions which are in an SCC but all
+%% return none(), a second chance was given to them by the analysis to
+%% see whether they return none() because they are involved in an loop
+%% (presumably server-related) and could be assigned the type unit()
+%% instead. The problem is that when the really return none() for some
+%% other reason (an error such in this case) then we will again find
+%% none() and try again for unit(), thereby entering an infinite loop.
+%% The issue was resolved on May 17th by adding an appropriate boolean
+%% parameter to dialyzer_typesig:solve_scc() function.
+%%---------------------------------------------------------------------
+-module(inf_loop2).
+
+-export([test/0]).
+
+test() ->
+ lists:reverse(gazonk),
+ loop().
+
+loop() ->
+ test().
diff --git a/lib/dialyzer/test/small_SUITE_data/src/invalid_specs/invalid_spec1.erl b/lib/dialyzer/test/small_SUITE_data/src/invalid_specs/invalid_spec1.erl
new file mode 100644
index 0000000000..06ab2f9a22
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/invalid_specs/invalid_spec1.erl
@@ -0,0 +1,28 @@
+-module(invalid_spec1).
+
+-export([get_plan_dirty/1]).
+
+-spec get_plan_dirty([string()]) -> {{atom(), any()}, [atom()]}.
+
+get_plan_dirty(ClassL) ->
+ get_plan_dirty(ClassL, [], []).
+
+get_plan_dirty([], Res, FoundClassList) ->
+ {Res,FoundClassList};
+get_plan_dirty([Class|ClassL], Res, FoundClassList) ->
+ ClassPlan = list_to_atom(Class ++ "_plan"),
+ case catch mnesia:dirty_all_keys(ClassPlan) of
+ {'EXIT',_} ->
+ get_plan_dirty(ClassL, Res, FoundClassList);
+ [] ->
+ get_plan_dirty(ClassL, Res, FoundClassList);
+ KeyL ->
+ ClassAtom = list_to_atom(Class),
+ Res2 =
+ lists:foldl(fun(Key, Acc) ->
+ [{ClassAtom,Key}|Acc]
+ end,
+ Res,
+ KeyL),
+ get_plan_dirty(ClassL, Res2, [ClassAtom|FoundClassList])
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/invalid_specs/invalid_spec2.erl b/lib/dialyzer/test/small_SUITE_data/src/invalid_specs/invalid_spec2.erl
new file mode 100644
index 0000000000..e49f73d014
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/invalid_specs/invalid_spec2.erl
@@ -0,0 +1,11 @@
+-module(invalid_spec2).
+
+-export([foo/0]).
+
+foo() ->
+ case
+ invalid_spec1:get_plan_dirty(mnesia:dirty_all_keys(cmClassInfo))
+ of
+ {[],[]} -> foo;
+ { _, _} -> bar
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/letrec1.erl b/lib/dialyzer/test/small_SUITE_data/src/letrec1.erl
new file mode 100644
index 0000000000..eeea671bcc
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/letrec1.erl
@@ -0,0 +1,13 @@
+%%%-------------------------------------------------------------------
+%%% File : letrec1.erl
+%%% Author : Tobias Lindahl <[email protected]>
+%%% Description :
+%%%
+%%% Created : 9 Mar 2007 by Tobias Lindahl <[email protected]>
+%%%-------------------------------------------------------------------
+-module(letrec1).
+
+-export([t/1]).
+
+t(Opts) ->
+ [Opt || Opt <- Opts, Opt =/= compressed].
diff --git a/lib/dialyzer/test/small_SUITE_data/src/list_match.erl b/lib/dialyzer/test/small_SUITE_data/src/list_match.erl
new file mode 100644
index 0000000000..38ef6ef976
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/list_match.erl
@@ -0,0 +1,20 @@
+%%%-------------------------------------------------------------------
+%%% File : list_match.erl
+%%% Author : Tobias Lindahl <[email protected]>
+%%% Description :
+%%%
+%%% Created : 12 Mar 2007 by Tobias Lindahl <[email protected]>
+%%%-------------------------------------------------------------------
+-module(list_match).
+
+-export([t/0]).
+
+t() ->
+ t([1,2,3,4]).
+
+t([]) ->
+ ok;
+t([H|T]) when is_integer(H) ->
+ t(T);
+t([_|T]) ->
+ t(T).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/list_to_bitstring.erl b/lib/dialyzer/test/small_SUITE_data/src/list_to_bitstring.erl
new file mode 100644
index 0000000000..109aa88f16
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/list_to_bitstring.erl
@@ -0,0 +1,21 @@
+%%=====================================================================
+%% From: Ken Robinson
+%% Date: 28/04/2011, 17:26
+%%
+%% Program that produced bogus "Function has no local return" warnings
+%% due to erlang:list_to_bitstring/1 having erroneous hard coded type
+%% information, namely accepting iolist() instead of bitstrlist().
+%% Fixed 29/04/2011.
+%%=====================================================================
+
+-module(list_to_bitstring).
+
+-export([l2bs/0, l2bs_ok/0]).
+
+%% This function was producing a warning
+l2bs() ->
+ erlang:list_to_bitstring([<<42>>, <<42:13>>]).
+
+%% while this one was ok.
+l2bs_ok() ->
+ erlang:list_to_bitstring([<<42>>, <<42,42>>]).
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/lzip.erl b/lib/dialyzer/test/small_SUITE_data/src/lzip.erl
index 753d2939d8..753d2939d8 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/lzip.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/lzip.erl
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/make_tuple.erl b/lib/dialyzer/test/small_SUITE_data/src/make_tuple.erl
index 0a5edf8c24..0a5edf8c24 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/make_tuple.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/make_tuple.erl
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/minus_minus.erl b/lib/dialyzer/test/small_SUITE_data/src/minus_minus.erl
index f1e9483c40..f1e9483c40 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/minus_minus.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/minus_minus.erl
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/mod_info.erl b/lib/dialyzer/test/small_SUITE_data/src/mod_info.erl
index a24e4276ad..a24e4276ad 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/mod_info.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/mod_info.erl
diff --git a/lib/dialyzer/test/small_SUITE_data/src/my_filter.erl b/lib/dialyzer/test/small_SUITE_data/src/my_filter.erl
new file mode 100644
index 0000000000..ecb2827eb4
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/my_filter.erl
@@ -0,0 +1,17 @@
+-module(my_filter).
+-export([test/0]).
+
+test() ->
+ filter(fun mystery/1, [1,2,3,4]).
+
+filter(Pred, List) when is_function(Pred, 1) ->
+ [ E || E <- List, Pred(E) ].
+
+mystery(X) ->
+ case (X rem 3) of
+ 0 -> true;
+ 1 -> false;
+ 2 -> gazonk
+ end.
+
+%% mystery(_X,_Y) -> true.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/my_sofs.erl b/lib/dialyzer/test/small_SUITE_data/src/my_sofs.erl
new file mode 100644
index 0000000000..e3ae99ebbc
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/my_sofs.erl
@@ -0,0 +1,83 @@
+%% Program showing the problems with record field accesses.
+
+-module(my_sofs).
+-export([ordset_of_sets/3, is_equal/2]).
+
+-define(TAG, 'Set').
+-define(ORDTAG, 'OrdSet').
+
+-record(?TAG, {data = [], type = type}).
+-record(?ORDTAG, {orddata = {}, ordtype = type}).
+
+-define(LIST(S), (S)#?TAG.data).
+-define(TYPE(S), (S)#?TAG.type).
+-define(SET(L, T), #?TAG{data = L, type = T}).
+-define(IS_SET(S), record(S, ?TAG)).
+
+%% Ordered sets and atoms:
+-define(ORDDATA(S), (S)#?ORDTAG.orddata).
+-define(ORDTYPE(S), (S)#?ORDTAG.ordtype).
+-define(ORDSET(L, T), #?ORDTAG{orddata = L, ordtype = T}).
+-define(IS_ORDSET(S), record(S, ?ORDTAG)).
+
+%% When IS_SET is true:
+-define(ANYTYPE, '_').
+-define(REL_TYPE(I, R), element(I, R)).
+-define(SET_OF(X), [X]).
+
+is_equal(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) ->
+ case match_types(?TYPE(S1), ?TYPE(S2)) of
+ true -> ?LIST(S1) == ?LIST(S2);
+ false -> erlang:error(type_mismatch, [S1, S2])
+ end;
+is_equal(S1, S2) when ?IS_ORDSET(S1), ?IS_ORDSET(S2) ->
+ case match_types(?TYPE(S1), ?TYPE(S2)) of
+ true -> ?ORDDATA(S1) == ?ORDDATA(S2);
+ false -> erlang:error(type_mismatch, [S1, S2])
+ end;
+is_equal(S1, S2) when ?IS_SET(S1), ?IS_ORDSET(S2) ->
+ erlang:error(type_mismatch, [S1, S2]);
+is_equal(S1, S2) when ?IS_ORDSET(S1), ?IS_SET(S2) ->
+ erlang:error(type_mismatch, [S1, S2]).
+
+%% Type = OrderedSetType
+%% | SetType
+%% | atom() except '_'
+%% OrderedSetType = {Type, ..., Type}
+%% SetType = [ElementType] % list of exactly one element
+%% ElementType = '_' % any type (implies empty set)
+%% | Type
+
+ordset_of_sets([S | Ss], L, T) when ?IS_SET(S) ->
+ ordset_of_sets(Ss, [?LIST(S) | L], [[?TYPE(S)] | T]);
+ordset_of_sets([S | Ss], L, T) when ?IS_ORDSET(S) ->
+ ordset_of_sets(Ss, [?LIST(S) | L], [?ORDTYPE(S) | T]);
+ordset_of_sets([], L, T) ->
+ ?ORDSET(list_to_tuple(lists:reverse(L)), list_to_tuple(lists:reverse(T)));
+ordset_of_sets(_, _L, _T) ->
+ error.
+
+%% inlined.
+match_types(T, T) -> true;
+match_types(Type1, Type2) -> match_types1(Type1, Type2).
+
+match_types1(Atom, Atom) when is_atom(Atom) ->
+ true;
+match_types1(?ANYTYPE, _) ->
+ true;
+match_types1(_, ?ANYTYPE) ->
+ true;
+match_types1(?SET_OF(Type1), ?SET_OF(Type2)) ->
+ match_types1(Type1, Type2);
+match_types1(T1, T2) when tuple(T1), tuple(T2), size(T1) =:= size(T2) ->
+ match_typesl(size(T1), T1, T2);
+match_types1(_T1, _T2) ->
+ false.
+
+match_typesl(0, _T1, _T2) ->
+ true;
+match_typesl(N, T1, T2) ->
+ case match_types1(?REL_TYPE(N, T1), ?REL_TYPE(N, T2)) of
+ true -> match_typesl(N-1, T1, T2);
+ false -> false
+ end.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/no_match.erl b/lib/dialyzer/test/small_SUITE_data/src/no_match.erl
index e3e7a4b2d1..e3e7a4b2d1 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/no_match.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/no_match.erl
diff --git a/lib/dialyzer/test/small_SUITE_data/src/no_return_bug.erl b/lib/dialyzer/test/small_SUITE_data/src/no_return_bug.erl
new file mode 100644
index 0000000000..5c24902590
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/no_return_bug.erl
@@ -0,0 +1,42 @@
+%% Dialyzer couldn't infer that monitor_diskspace would go in an infinite loop
+%% instead of crashing due to the existence of list comprehensions that have a
+%% normal success typing. These were added to the monitor_diskspace's SCC and
+%% dialyzer_typesig didn't try to assign unit() to monitor_diskspace, as it
+%% required all the members of the SCC to return none().
+%%
+%% Testcase was submitted in erlang-questions mailing list by Prashanth Mundkur
+%% (http://erlang.org/pipermail/erlang-questions/2011-May/058063.html)
+
+-module(no_return_bug).
+-export([diskspace/1, monitor_diskspace/2, refresh_tags/1, monitor_launch/0]).
+
+-type diskinfo() :: {non_neg_integer(), non_neg_integer()}.
+
+-spec diskspace(nonempty_string()) -> {'ok', diskinfo()} | {'error', term()}.
+diskspace(Path) ->
+ case Path of
+ "a" -> {ok, {0,0}};
+ _ -> {error, error}
+ end.
+
+-spec monitor_diskspace(nonempty_string(),
+ [{diskinfo(), nonempty_string()}]) ->
+ no_return().
+monitor_diskspace(Root, Vols) ->
+ Df = fun(VolName) ->
+ diskspace(filename:join([Root, VolName]))
+ end,
+ NewVols = [{Space, VolName}
+ || {VolName, {ok, Space}}
+ <- [{VolName, Df(VolName)}
+ || {_OldSpace, VolName} <- Vols]],
+ monitor_diskspace(Root, NewVols).
+
+-spec refresh_tags(nonempty_string()) -> no_return().
+refresh_tags(Root) ->
+ {ok, _} = diskspace(Root),
+ refresh_tags(Root).
+
+monitor_launch() ->
+ spawn_link(fun() -> refresh_tags("abc") end),
+ spawn_link(fun() -> monitor_diskspace("root", [{{0,0}, "a"}]) end).
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/no_unused_fun.erl b/lib/dialyzer/test/small_SUITE_data/src/no_unused_fun.erl
index 0bd8ba402c..0bd8ba402c 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/no_unused_fun.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/no_unused_fun.erl
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/no_unused_fun2.erl b/lib/dialyzer/test/small_SUITE_data/src/no_unused_fun2.erl
index e287c4de5f..e287c4de5f 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/no_unused_fun2.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/no_unused_fun2.erl
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/non_existing.erl b/lib/dialyzer/test/small_SUITE_data/src/non_existing.erl
index 5701b8a745..5701b8a745 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/non_existing.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/non_existing.erl
diff --git a/lib/dialyzer/test/small_SUITE_data/src/none_scc_inf_loop.erl b/lib/dialyzer/test/small_SUITE_data/src/none_scc_inf_loop.erl
new file mode 100644
index 0000000000..111758965c
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/none_scc_inf_loop.erl
@@ -0,0 +1,21 @@
+%%===========================================================================
+%% Test that made dialyzer go into an infinite loop. The reason was that
+%% t_inf(t_unit(), t_none()) returned t_unit() instead of t_none() as it
+%% should. The issue was identified and fixed by Stavros Aronis on 5/11/2010.
+%%===========================================================================
+-module(none_scc_inf_loop).
+
+-export([foo/0]).
+
+foo() ->
+ foo(3).
+
+foo(0) ->
+ exit(foo);
+foo(N) ->
+ bar(N-1).
+
+bar(0) ->
+ exit(foo);
+bar(N) ->
+ foo(N-1).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/not_bogus_warning.erl b/lib/dialyzer/test/small_SUITE_data/src/not_bogus_warning.erl
new file mode 100644
index 0000000000..53f7e934e4
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/not_bogus_warning.erl
@@ -0,0 +1,25 @@
+%%-----------------------------------------------------------------------------
+%% Test which produces an erroneous warning:
+%% Guard test is_atom(A::'bar' | 'foo') can never succeed
+%% due to the handling of not which of course succeeds when its argument fails
+%%-----------------------------------------------------------------------------
+-module(not_bogus_warning).
+
+-export([t1/0, t2/0, t3/0, t4/0]).
+
+t1() ->
+ [A || A <- [foo, bar], not is_atom(A)].
+
+t2() ->
+ [A || A <- [foo, bar], not is_integer(A)].
+
+t3() ->
+ should_we_warn_here(42).
+
+should_we_warn_here(X) when is_integer(X) -> int.
+
+t4() ->
+ should_we_warn_or_not(42).
+
+should_we_warn_or_not(X) when not is_integer(X) -> not_int;
+should_we_warn_or_not(X) -> int.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/not_guard_crash.erl b/lib/dialyzer/test/small_SUITE_data/src/not_guard_crash.erl
new file mode 100644
index 0000000000..75bcffc2bc
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/not_guard_crash.erl
@@ -0,0 +1,49 @@
+%% From: Matthias Radestock <[email protected]>
+%% Date: 19 August 2007
+%%
+%% when I run dialyzer on my code it throws the following error:
+%%
+%% Analysis failed with error report:
+%% {{case_clause,any},
+%% [{dialyzer_dataflow,bind_guard,5},
+%% {dialyzer_dataflow,bind_guard_case_clauses,6},
+%% {dialyzer_dataflow,bind_guard,5},
+%% {dialyzer_dataflow,bind_guard_case_clauses,6},
+%% {dialyzer_dataflow,bind_guard,5},
+%% {dialyzer_dataflow,bind_eqeq_guard_lit_other,6},
+%% {dialyzer_dataflow,bind_guard,...},
+%% {dialyzer_dataflow,...}]}
+%%
+%% This is happening with the R11B-5 version of dialyzer when
+%% analyzing the attached file.
+%%--------------------------------------------------------------------
+
+-module(not_guard_crash).
+
+-export([match_ticket/2]).
+
+-record(ticket, {passive_flag, active_flag, write_flag, read_flag}).
+
+%%--------------------------------------------------------------------
+
+match_ticket(#ticket{passive_flag = PP,
+ active_flag = PA,
+ write_flag = PW,
+ read_flag = PR},
+ #ticket{passive_flag = TP,
+ active_flag = TA,
+ write_flag = TW,
+ read_flag = TR}) ->
+ if
+ %% Matches if either we're not requesting passive access, or
+ %% passive access is permitted, and ...
+ (not(TP) orelse PP) andalso
+ (not(TA) orelse PA) andalso
+ (not(TW) orelse PW) andalso
+ (not(TR) orelse PR) ->
+ match;
+ true ->
+ no_match
+ end.
+
+%%--------------------------------------------------------------------
diff --git a/lib/dialyzer/test/small_SUITE_data/src/nowarnunused.erl b/lib/dialyzer/test/small_SUITE_data/src/nowarnunused.erl
new file mode 100644
index 0000000000..63daeee9e3
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/nowarnunused.erl
@@ -0,0 +1,7 @@
+-module(nowarnunused).
+
+-compile({nowarn_unused_function, return_error/2}).
+
+-spec return_error(integer(), any()) -> no_return().
+return_error(Line, Message) ->
+ throw({error, {Line, ?MODULE, Message}}).
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/or_bug.erl b/lib/dialyzer/test/small_SUITE_data/src/or_bug.erl
index fb8f6558b8..fb8f6558b8 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/or_bug.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/or_bug.erl
diff --git a/lib/dialyzer/test/small_SUITE_data/src/orelsebug.erl b/lib/dialyzer/test/small_SUITE_data/src/orelsebug.erl
new file mode 100644
index 0000000000..8479fc33cc
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/orelsebug.erl
@@ -0,0 +1,16 @@
+%%%-------------------------------------------------------------------
+%%% File : orelsebug.erl
+%%% Author : Tobias Lindahl <[email protected]>
+%%% Description :
+%%%
+%%% Created : 14 Nov 2006 by Tobias Lindahl <[email protected]>
+%%%-------------------------------------------------------------------
+-module(orelsebug).
+
+-export([t/1, t1/1]).
+
+t(Format) when is_list(Format) ->
+ t1(Format).
+
+t1(Format) when is_list(Format) orelse is_binary(Format) ->
+ Format.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/orelsebug2.erl b/lib/dialyzer/test/small_SUITE_data/src/orelsebug2.erl
new file mode 100644
index 0000000000..60e0c47384
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/orelsebug2.erl
@@ -0,0 +1,23 @@
+%%%-------------------------------------------------------------------
+%%% File : orelsebug2.erl
+%%% Author : Tobias Lindahl <[email protected]>
+%%% Description :
+%%%
+%%% Created : 21 Nov 2006 by Tobias Lindahl <[email protected]>
+%%%-------------------------------------------------------------------
+-module(orelsebug2).
+
+-export([t/1]).
+
+-record(eventdata, {
+ expires
+ }).
+
+t(L) ->
+ L2 = [E1 || E1 <- L, E1#eventdata.expires == x
+ orelse E1#eventdata.expires == y],
+
+ case L2 of
+ [_E] -> x;
+ [] -> y
+ end.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/overloaded1.erl b/lib/dialyzer/test/small_SUITE_data/src/overloaded1.erl
index 0af4f7446f..0af4f7446f 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/overloaded1.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/overloaded1.erl
diff --git a/lib/dialyzer/test/small_SUITE_data/src/param_types_crash.erl b/lib/dialyzer/test/small_SUITE_data/src/param_types_crash.erl
new file mode 100644
index 0000000000..52d52cc9a9
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/param_types_crash.erl
@@ -0,0 +1,77 @@
+%%---------------------------------------------------------------------------
+%% From: Nicolas Tranger <[email protected]>
+%% Date: 10/11/2110
+%%
+%% After adding spec statements to my module, Dialyzer failed on execution
+%% though. I've been trying to create a minimal reproducible case and
+%% reduced the code to something similar of about 80 LOC. As noted in the
+%% comments, commenting out some lines makes Dialyzer parse and analyze
+%% the file correctly. The code executes correctly and as expected.
+%%
+%% I'm not sure what causes the issue. parse_result is polymorphic in its
+%% return type, but statically typed based on the type of the 3th argument
+%% (well, that's how I see things from a Haskell background).
+%%---------------------------------------------------------------------------
+%% This was a bug in erl_types:t_subtract/2 which was not handling the case
+%% of free variables in prameterized types. Fixed 15/10/2010.
+%%---------------------------------------------------------------------------
+-module(param_types_crash).
+
+-export([test/0]).
+
+-type socket_error() :: 'connection_closed' | 'timeout'.
+-type app_error() :: 'no_magic' | 'unknown_failure'.
+
+-type resulthandler_result(T) :: {'ok', T} | socket_error() | app_error().
+-type resulthandler(T) :: fun((binary()) -> resulthandler_result(T)).
+
+test() ->
+ Data = <<0:32/little-unsigned, 1:8/little, 1:8/little-unsigned>>,
+ case parse_result(Data, get_option(fun get_bool/1)) of
+ %% Removing the next 2 lines makes
+ %% dialyzer param_types_crash.erl -Wunmatched_returns -Wunderspecs
+ %% succeed. With these lines, it fails.
+ {ok, none} -> none;
+ {ok, {some, Value}} -> Value;
+ Reply -> {error, Reply}
+ end.
+
+-spec parse_result(binary(), resulthandler(T)) -> resulthandler_result(T).
+parse_result(<<ResultCode:32/little-unsigned, Rest/binary>>, ResultHandler) ->
+ case ResultCode of
+ 0 -> ResultHandler(Rest);
+ 1 -> no_magic;
+ 2 -> unknown_failure
+ end.
+
+-spec get_bool(binary()) -> {'ok', boolean()} | socket_error().
+get_bool(Data) ->
+ case get_data(Data, 1, size(Data)) of
+ {<<Value:8/little-unsigned>>, <<>>} -> {ok, (Value =:= 1)};
+ Other -> Other
+ end.
+
+-spec get_option(resulthandler(T)) -> resulthandler('none' | {'some', T}).
+get_option(Fun) ->
+ fun(Data) ->
+ case get_data(Data, 1, size(Data)) of
+ {<<HasValue:8/little>>, Rest} ->
+ case HasValue of
+ 0 -> {ok, none};
+ 1 -> {ok, Value} = Fun(Rest),
+ {ok, {some, Value}}
+ end;
+ Other -> Other
+ end
+ end.
+
+-spec get_data(binary(), non_neg_integer(), non_neg_integer()) ->
+ {binary(), binary()} | socket_error().
+get_data(Data, Length, Received) when Length > Received ->
+ case Data of
+ <<>> -> connection_closed;
+ _ -> timeout
+ end;
+get_data(Data, Length, _) ->
+ <<Bin:Length/binary, Rest/binary>> = Data,
+ {Bin, Rest}.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/port_info_test.erl b/lib/dialyzer/test/small_SUITE_data/src/port_info_test.erl
new file mode 100644
index 0000000000..2ee9a3a6e2
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/port_info_test.erl
@@ -0,0 +1,33 @@
+%%
+%% Tests hardcoded dependent type info
+%% and the quality of the warnings that Dialyzer spits out
+%%
+-module(port_info_test).
+-export([t1/1, t2/1, t3/1, t4/1, t5/2, buggy/1]).
+
+%% The following errors are correctly caught, but the messages are a bit weird
+t1(X) when is_port(X) ->
+ {connected, 42} = erlang:port_info(X, connected);
+t1(_) -> ok.
+
+t2(X) when is_port(X) ->
+ {registered_name, "42"} = erlang:port_info(X, registered_name);
+t2(_) -> ok.
+
+%% Here only one od the two errors is reported...
+t3(X) when is_atom(X) ->
+ {output, 42} = erlang:port_info(X, connected);
+t3(_) -> ok.
+
+t4(X) when is_atom(X) ->
+ {Atom, _} = erlang:port_info(X, connected),
+ Atom = links;
+t4(_) -> ok.
+
+t5(X, Atom) when is_port(X) ->
+ {gazonk, _} = erlang:port_info(X, Atom);
+t5(_, _) -> ok.
+
+%% The type system is not strong enough to catch the following errors
+buggy(X) when is_atom(X) ->
+ {links, X} = erlang:port_info(foo, X).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/process_info_test.erl b/lib/dialyzer/test/small_SUITE_data/src/process_info_test.erl
new file mode 100644
index 0000000000..2c24ae597f
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/process_info_test.erl
@@ -0,0 +1,20 @@
+%%
+%% Tests hardcoded dependent type info for process_info/1
+%%
+-module(process_info_test).
+-export([pinfo/1]).
+
+pinfo(P) when node(P) == node() -> % On same node
+ case process_info(P) of
+ undefined ->
+ exit(dead);
+ Info -> Info
+ end;
+pinfo(P) -> % On different node
+ case rpc:call(node(P), erlang, process_info, [P]) of
+ {badrpc, _} ->
+ exit(badrpc);
+ undefined -> % This does happen
+ exit(dead);
+ Info -> Info
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/pubsub/pubsub_api.erl b/lib/dialyzer/test/small_SUITE_data/src/pubsub/pubsub_api.erl
new file mode 100644
index 0000000000..85ea292077
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/pubsub/pubsub_api.erl
@@ -0,0 +1,99 @@
+% Copyright 2007-2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
+%
+% Licensed under the Apache License, Version 2.0 (the "License");
+% you may not use this file except in compliance with the License.
+% You may obtain a copy of the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS,
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+% See the License for the specific language governing permissions and
+% limitations under the License.
+%%%-------------------------------------------------------------------
+%%% File : pubsub_api.erl
+%%% Author : Thorsten Schuett <[email protected]>
+%%% Description : Publish API function
+%%%
+%%% Created : 17 Sep 2007 by Thorsten Schuett <[email protected]>
+%%%-------------------------------------------------------------------
+%% @author Thorsten Schuett <[email protected]>
+%% @copyright 2007-2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
+%% @version $Id $
+-module(pubsub_dir.pubsub_api).
+
+-author('[email protected]').
+-vsn('$Id: pubsub_api.erl,v 1.1 2009/11/06 12:39:55 maria Exp $ ').
+
+-export([publish/2, subscribe/2, unsubscribe/2, get_subscribers/1]).
+
+-import(transstore.transaction_api).
+-import(io).
+-import(lists).
+
+%%====================================================================
+%% public functions
+%%====================================================================
+
+%% @doc publishs an event under a given topic.
+%% called e.g. from the java-interface
+%% @spec publish(string(), string()) -> ok
+publish(Topic, Content) ->
+ Subscribers = get_subscribers(Topic),
+ io:format("calling subscribers ~p~n", [Subscribers]),
+ lists:foreach(fun (Subscriber) ->
+ io:format("calling ~p~n", [Subscriber]),
+ pubsub_publish:publish(Subscriber, Topic, Content)
+ end,
+ Subscribers),
+ ok.
+
+%% @doc subscribes a url for a topic.
+%% called e.g. from the java-interface
+%% @spec subscribe(string(), string()) -> ok | {fail, term()}
+subscribe(Topic, URL) ->
+ TFun = fun(TransLog) ->
+ {{Success, _ValueOrReason} = Result, TransLog1} = transaction_api:read(Topic, TransLog),
+ {Result2, TransLog2} = if
+ Success == fail ->
+ transaction_api:write(Topic, [URL], TransLog); %obacht: muss TransLog sein!
+ true ->
+ {value, Subscribers} = Result,
+ transaction_api:write(Topic, [URL | Subscribers], TransLog1)
+ end,
+ if
+ Result2 == ok ->
+ {{ok, ok}, TransLog2};
+ true ->
+ {Result2, TransLog2}
+ end
+ end,
+ transaction_api:do_transaction(TFun, fun (_) -> ok end, fun (X) -> {fail, X} end).
+
+%% @doc unsubscribes a url for a topic.
+-spec(unsubscribe/2 :: (string(), string()) -> ok | {fail, any()}).
+unsubscribe(Topic, URL) ->
+ TFun = fun(TransLog) ->
+ {Subscribers, TransLog1} = transaction_api:read2(TransLog, Topic),
+ case lists:member(URL, Subscribers) of
+ true ->
+ NewSubscribers = lists:delete(URL, Subscribers),
+ TransLog2 = transaction_api:write2(TransLog1, Topic, NewSubscribers),
+ {{ok, ok}, TransLog2};
+ false ->
+ {{fail, not_found}, TransLog}
+ end
+ end,
+ transaction_api:do_transaction(TFun, fun (_) -> ok end, fun (X) -> {fail, X} end).
+
+%% @doc queries the subscribers of a query
+%% @spec get_subscribers(string()) -> [string()]
+get_subscribers(Topic) ->
+ {Fl, _Value} = transaction_api:quorum_read(Topic),
+ if
+ Fl == fail -> %% Fl is either Fail or the Value/Subscribers
+ [];
+ true ->
+ Fl
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/pubsub/pubsub_publish.erl b/lib/dialyzer/test/small_SUITE_data/src/pubsub/pubsub_publish.erl
new file mode 100644
index 0000000000..601dbad74b
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/pubsub/pubsub_publish.erl
@@ -0,0 +1,49 @@
+% Copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
+%
+% Licensed under the Apache License, Version 2.0 (the "License");
+% you may not use this file except in compliance with the License.
+% You may obtain a copy of the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS,
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+% See the License for the specific language governing permissions and
+% limitations under the License.
+%%%-------------------------------------------------------------------
+%%% File : pubsub_publish.erl
+%%% Author : Thorsten Schuett <[email protected]>
+%%% Description : Publish function
+%%%
+%%% Created : 26 Mar 2008 by Thorsten Schuett <[email protected]>
+%%%-------------------------------------------------------------------
+%% @author Thorsten Schuett <[email protected]>
+%% @copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
+%% @version $Id $
+-module(pubsub_dir.pubsub_publish).
+
+-author('[email protected]').
+-vsn('$Id: pubsub_publish.erl,v 1.1 2009/11/06 12:39:55 maria Exp $ ').
+
+-export([publish/3, publish_internal/3]).
+
+-import(json).
+-import(io).
+-import(http).
+-import(jsonrpc).
+
+%%====================================================================
+%% public functions
+%%====================================================================
+
+%% @doc publishs an event to a given url.
+%% @spec publish(string(), string(), string()) -> ok
+%% @todo use pool:pspawn
+publish(URL, Topic, Content) ->
+ spawn(fun () -> pubsub_publish:publish_internal(URL, Topic, Content) end),
+ ok.
+
+publish_internal(URL, Topic, Content) ->
+ Res = jsonrpc:call(URL, [], {call, notify, [Topic, Content]}),
+ io:format("~p ~p~n", [Res, URL]).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/rebar_no_return.erl b/lib/dialyzer/test/small_SUITE_data/src/rebar_no_return.erl
new file mode 100644
index 0000000000..d3b504ae04
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/rebar_no_return.erl
@@ -0,0 +1,19 @@
+-module(rebar_no_return).
+
+-export([t/0]).
+
+-spec t() -> no_return().
+t() ->
+ F = log_and_halt("baz"),
+ F("foo", 123).
+
+-spec log_and_halt(string()) -> fun((string(),integer()) -> no_return()).
+log_and_halt(Msg) ->
+ fun(_, _) ->
+ abort(Msg)
+ end.
+
+-spec abort(string()) -> no_return().
+abort(Msg) ->
+ io:format("~s~n", [Msg]),
+ halt(1).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/receive1.erl b/lib/dialyzer/test/small_SUITE_data/src/receive1.erl
new file mode 100644
index 0000000000..96fdf54e4d
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/receive1.erl
@@ -0,0 +1,16 @@
+%%%-------------------------------------------------------------------
+%%% File : receive1.erl
+%%% Author : Tobias Lindahl <[email protected]>
+%%% Description :
+%%%
+%%% Created : 27 Mar 2007 by Tobias Lindahl <[email protected]>
+%%%-------------------------------------------------------------------
+-module(receive1).
+
+-export([t/1]).
+
+t(X) ->
+ receive
+ after
+ infinity -> X
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/record_construct.erl b/lib/dialyzer/test/small_SUITE_data/src/record_construct.erl
new file mode 100644
index 0000000000..54cc2601bd
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/record_construct.erl
@@ -0,0 +1,21 @@
+-module(record_construct).
+-export([t_loc/0, t_opa/0, t_rem/0]).
+
+-record(r_loc, {a = gazonk :: integer(), b = 42 :: atom()}).
+
+t_loc() ->
+ #r_loc{}.
+
+-record(r_opa, {a :: atom(),
+ b = gb_sets:new() :: gb_set(),
+ c = 42 :: boolean(),
+ d, % untyped on purpose
+ e = false :: boolean()}).
+
+t_opa() ->
+ #r_opa{}.
+
+-record(r_rem, {a = gazonk :: string()}).
+
+t_rem() ->
+ #r_rem{}.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/record_pat.erl b/lib/dialyzer/test/small_SUITE_data/src/record_pat.erl
new file mode 100644
index 0000000000..3308641571
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/record_pat.erl
@@ -0,0 +1,15 @@
+%%%-------------------------------------------------------------------
+%%% File : record_pat.erl
+%%% Author : Tobias Lindahl <>
+%%% Description : Emit warning if a pattern violates the record type
+%%%
+%%% Created : 21 Oct 2008 by Tobias Lindahl <>
+%%%-------------------------------------------------------------------
+-module(record_pat).
+
+-export([t/1]).
+
+-record(foo, {bar :: integer()}).
+
+t(#foo{bar=baz}) -> no_way;
+t(#foo{bar=1}) -> ok.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/record_send_test.erl b/lib/dialyzer/test/small_SUITE_data/src/record_send_test.erl
new file mode 100644
index 0000000000..87cd97bd85
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/record_send_test.erl
@@ -0,0 +1,32 @@
+%%-------------------------------------------------------------------
+%% File : record_send_test.erl
+%% Author : Kostis Sagonas <[email protected]>
+%% Description : A test inspired by a post of Mkcael Remond to the
+%% Erlang mailing list suggesting thst Dialyzer should
+%% be reporting sends to records rather than to pids.
+%% Dialyzer v1.3.0 indeed reports one of the dicrepancies
+%% (the one with the 4-tuple) but not the one where the
+%% message is sent to a pair which is a record.
+%% This should be fixed.
+%%
+%% Created : 10 Apr 2005 by Kostis Sagonas <[email protected]>
+%%-------------------------------------------------------------------
+-module(record_send_test).
+
+-export([t/0]).
+
+-record(rec1, {a=a, b=b, c=c}).
+-record(rec2, {a}).
+
+t() ->
+ t(#rec1{}).
+
+t(Rec1 = #rec1{b=B}) ->
+ Rec2 = some_mod:some_function(),
+ if
+ is_record(Rec2, rec2) ->
+ Rec2 ! hello; %% currently this one is not found
+ true ->
+ Rec1 ! hello_again
+ end,
+ B.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/record_test.erl b/lib/dialyzer/test/small_SUITE_data/src/record_test.erl
new file mode 100644
index 0000000000..48a00b172e
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/record_test.erl
@@ -0,0 +1,22 @@
+%%%-------------------------------------------------------------------
+%%% File : record_test.erl
+%%% Author : Tobias Lindahl <[email protected]>
+%%% Description :
+%%%
+%%% Created : 22 Oct 2004 by Tobias Lindahl <[email protected]>
+%%%-------------------------------------------------------------------
+-module(record_test).
+
+-export([t/0]).
+
+-record(foo, {bar}).
+
+t() ->
+ doit(foo).
+
+doit(X) ->
+ case X of
+ #foo{} -> error1;
+ foo -> ok;
+ _ -> error2
+ end.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types1.erl b/lib/dialyzer/test/small_SUITE_data/src/recursive_types1.erl
index 657d11653b..657d11653b 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types1.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/recursive_types1.erl
diff --git a/lib/dialyzer/test/small_SUITE_data/src/recursive_types2.erl b/lib/dialyzer/test/small_SUITE_data/src/recursive_types2.erl
new file mode 100644
index 0000000000..7985d5fb4b
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/recursive_types2.erl
@@ -0,0 +1,12 @@
+-module(recursive_types2).
+
+-export([test/0]).
+
+-type tree() :: 'nil' | {non_neg_integer(), subtree(), subtree()}.
+
+-type subtree() :: tree().
+
+-spec test() -> {42, tree(), tree()}.
+
+test() ->
+ {42, {42, nil, nil}, {42, {42, nil, nil}, {42, nil, nil}}}.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types3.erl b/lib/dialyzer/test/small_SUITE_data/src/recursive_types3.erl
index 997678ac92..997678ac92 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types3.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/recursive_types3.erl
diff --git a/lib/dialyzer/test/small_SUITE_data/src/recursive_types4.erl b/lib/dialyzer/test/small_SUITE_data/src/recursive_types4.erl
new file mode 100644
index 0000000000..f6b5f87e04
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/recursive_types4.erl
@@ -0,0 +1,13 @@
+-module(recursive_types4).
+
+-export([test/0]).
+
+-record(tree, {node :: atom(),
+ kid = nil :: 'nil' | tree()}).
+
+-type tree() :: #tree{}.
+
+-spec test() -> tree().
+
+test() ->
+ #tree{node = root, kid = #tree{}}.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/recursive_types5.erl b/lib/dialyzer/test/small_SUITE_data/src/recursive_types5.erl
new file mode 100644
index 0000000000..cd1cd5ede9
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/recursive_types5.erl
@@ -0,0 +1,13 @@
+-module(recursive_types5).
+
+-export([test/0]).
+
+-type tree() :: 'nil' | {non_neg_integer(), tree(), tree()}.
+
+-record(tree, {node :: atom(),
+ kid = 'nil' :: tree()}).
+
+-spec test() -> #tree{}.
+
+test() ->
+ #tree{node = root, kid = {42, {42, nil, nil}, {42, nil, nil}}}.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types6.erl b/lib/dialyzer/test/small_SUITE_data/src/recursive_types6.erl
index ff61976736..ff61976736 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types6.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/recursive_types6.erl
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types7.erl b/lib/dialyzer/test/small_SUITE_data/src/recursive_types7.erl
index 92106e9694..92106e9694 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types7.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/recursive_types7.erl
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/refine_bug1.erl b/lib/dialyzer/test/small_SUITE_data/src/refine_bug1.erl
index 1b299e782a..1b299e782a 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/refine_bug1.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/refine_bug1.erl
diff --git a/lib/dialyzer/test/small_SUITE_data/src/refine_failing.erl b/lib/dialyzer/test/small_SUITE_data/src/refine_failing.erl
new file mode 100644
index 0000000000..243f4806e6
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/refine_failing.erl
@@ -0,0 +1,26 @@
+%% This testcase shows why it's a bad idea to block refinement (by forwarding
+%% any() to all arguments) when a failing call is encountered. The initial
+%% success typing for update_one allows anything to be an element of the list in
+%% the second argument. This will be refined during dataflow by the result from
+%% add_counters to just a list of tuples. This will cause the call in the second
+%% clause of update_one to fail correctly and identify the discrepancy. It could
+%% be a better idea to refuse to add the failing calls but this may lead to a
+%% ton of unused functions,
+%%
+%% by Stavros Aronis<[email protected]>
+
+-module(refine_failing).
+
+-export([foo/2]).
+
+foo(A, B) -> update_all(add_counters(A, []), B).
+
+add_counters( [], Acc) -> Acc;
+add_counters([H|T], Acc) -> add_counters(T, [{H, 0}|Acc]).
+
+update_all(Ds, []) -> Ds;
+update_all(Ds, [F|Fs]) -> update_all(update_one(F, Ds, []), Fs).
+
+update_one(_F, [], Acc) -> Acc;
+update_one( F, [{F, Cr},Ds], Acc) -> update_one(F, Ds, [{F,Cr+1}|Acc]);
+update_one( F, [ D|Ds], Acc) -> update_one(F, Ds, [ D|Acc]).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/toth.erl b/lib/dialyzer/test/small_SUITE_data/src/toth.erl
new file mode 100644
index 0000000000..bae22be4f1
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/toth.erl
@@ -0,0 +1,99 @@
+-module(toth).
+-export([sys_table_view/1]).
+
+%%% Constants
+-define(sysTabETS,1).
+-define(sysTabMnesia,2).
+-define(sysTabBoth,3).
+
+sys_table_view([CpId,{match,Pattern},TableType, ViewType]) ->
+ AllTableList =
+ case TableType of
+ ?sysTabMnesia ->
+ lists:sort(mnesia:system_info(tables));
+ ?sysTabBoth ->
+ lists:sort(rpc:call(CpId,ets,all,[]));
+ ?sysTabETS ->
+ lists:sort(rpc:call(CpId,ets,all,[]) --
+ mnesia:system_info(tables));
+ _ -> %%% Happens at registration only
+ [ok]
+ end,
+ %% Filter the matching table names, skip unnamed tables first:
+ NamedTableList = lists:filter(fun (X) -> is_atom(X) end, AllTableList),
+ TablesShown =
+ case Pattern of
+ "" ->
+ NamedTableList;
+ _ ->
+ %% Filter the ones whose name begins with the Pattern:
+ Filter = fun(T) ->
+ lists:prefix(Pattern, atom_to_list(T))
+ end,
+ lists:filter(Filter, NamedTableList)
+ end,
+
+ Fields = [{text, [{value,"CpId: " ++ atom_to_list(CpId)}]},
+ {text, [{value,"TabSpec=" ++ Pattern},
+ {value_format, term}]},
+ {text, [{value,"Table type: " ++ formatTableType(TableType)},
+ {value_format, term}]}],
+
+ Template = [[{type, index},
+ {link, {?MODULE, sys_table_browse,
+ [{"CpId",CpId},{"TableType",TableType},
+ {"View", ViewType},
+ {"FirstKey",1}, {"KeyPattern",""}]}}],
+
+ [{type, data},
+ {title, "Table name"},
+ {display_value, {erlang, atom_to_list}}], %%% else crash
+
+ [{type,data},
+ {title, "No of rows"},
+ {display_value, term}],
+
+ [{type,data},
+ {title, "Memory"},
+ {display_value, term}]
+ ],
+
+ TableAttr = [{rows, [[T,T|tableSize(T,TableType,CpId)] ||
+ T <- TablesShown]},
+ {template,Template}],
+
+ Page = [{header, {"Filter tables", "Selected tables"}},
+ {buttons, [reload, back]},
+ {layout, [{form, Fields},
+ {table, TableAttr}]}
+ ],
+ Page.
+
+%%--------------------------------------------------------------------
+%% tableSize/3
+%% @spec tableSize(T::atom(),TableType::integer(),CpId::atom()) ->
+%% list(integer())
+%% @doc Return the table size and memory size of the table.
+%% @end
+%%---------------------------------------------------------------------
+
+tableSize(T, TableType, CpId) ->
+ case TableType of
+ ?sysTabETS ->
+ [rpc:call(CpId, ets, info, [T, size]),
+ rpc:call(CpId, ets, info, [T, memory])];
+ ?sysTabMnesia ->
+ [mnesia:table_info(T, size),mnesia:table_info(T, memory)];
+ _ -> %%% Registration
+ [0,0]
+ end.
+
+formatTableType(T) ->
+ case T of
+ ?sysTabETS ->
+ "ETS";
+ ?sysTabMnesia ->
+ "mnesia";
+ _ -> %%% Registration !
+ "ETS + mnesia"
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/trec.erl b/lib/dialyzer/test/small_SUITE_data/src/trec.erl
new file mode 100644
index 0000000000..ba50c3b401
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/trec.erl
@@ -0,0 +1,37 @@
+%%
+%% The current treatment of typed records leaves much to be desired.
+%% These are not made up examples; I have cases like that the branch
+%% of the HiPE compiler with types in records. I get very confusing
+%% warnings which require a lot of effort to find their cause and why
+%% a function has no local return.
+%%
+-module(trec).
+-export([test/0, mk_foo_exp/2]).
+
+-record(foo, {a :: integer(), b :: [atom()]}).
+
+%%
+%% For these functions we currently get the following warnings:
+%% 1. Function test/0 has no local return
+%% 2. The call trec:mk_foo_loc(42,any()) will fail since it differs
+%% in argument position 1 from the success typing arguments:
+%% ('undefined',atom())
+%% 3. Function mk_foo_loc/2 has no local return
+%%
+%% Arguably, the second warning is not what most users have in mind
+%% when they wrote the type declarations in the 'foo' record, so no
+%% doubt they'll find it confusing. But note that it is also inconsistent!
+%% How come there is a success typing for a function that has no local return?
+%%
+test() ->
+ mk_foo_loc(42, bar:f()).
+
+mk_foo_loc(A, B) ->
+ #foo{a = A, b = [A,B]}.
+
+%%
+%% For this function we currently get "has no local return" but we get
+%% no reason; I want us to get a reason.
+%%
+mk_foo_exp(A, B) when is_integer(A) ->
+ #foo{a = A, b = [A,B]}.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/try1.erl b/lib/dialyzer/test/small_SUITE_data/src/try1.erl
new file mode 100644
index 0000000000..05963a16af
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/try1.erl
@@ -0,0 +1,26 @@
+%%%-------------------------------------------------------------------
+%%% File : try1.erl
+%%% Author : <[email protected]>
+%%% Description :
+%%%
+%%% Created : 23 Aug 2005 by <[email protected]>
+%%%-------------------------------------------------------------------
+-module(try1).
+
+-export([t/1]).
+
+t(X) ->
+ case wierd_is_bool(X) of
+ true -> ok;
+ false -> ok
+ end.
+
+wierd_is_bool(X) ->
+ try bool(X) of
+ Y -> Y
+ catch
+ _:_ -> false
+ end.
+
+bool(true) -> true;
+bool(false) -> true.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/tuple1.erl b/lib/dialyzer/test/small_SUITE_data/src/tuple1.erl
new file mode 100644
index 0000000000..d608275efe
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/tuple1.erl
@@ -0,0 +1,29 @@
+%%%-------------------------------------------------------------------
+%%% File : tuple1.erl
+%%% Author : Tobias Lindahl <[email protected]>
+%%% Description : Exposed two bugs in the analysis;
+%%% one supressed warning and one crash.
+%%%
+%%% Created : 13 Nov 2006 by Tobias Lindahl <[email protected]>
+%%%-------------------------------------------------------------------
+-module(tuple1).
+
+-export([t1/2, t2/2, t3/2, bar/2]).
+
+t1(List = [_|_], X) ->
+ lists:mapfoldl(fun foo/2, X, List).
+
+t2(List = [_|_], X) ->
+ lists:mapfoldl(fun bar/2, X, List).
+
+t3(List = [_|_], X) ->
+ lists:mapfoldl(fun baz/1, X, List).
+
+
+foo(1, 1) -> a;
+foo(a, 1) -> b.
+
+bar(1, 1) -> {b, b};
+bar(a, 1) -> {a, a}.
+
+baz(1) -> 1.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/tuple_set_crash.erl b/lib/dialyzer/test/small_SUITE_data/src/tuple_set_crash.erl
new file mode 100644
index 0000000000..5503f39412
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/tuple_set_crash.erl
@@ -0,0 +1,207 @@
+%% ====================================================================
+%% Program which resulted in an erl_types crash due to incomplete
+%% handling of tuple_sets in function inf_tuples_in_sets/4.
+%% Reported by Alexey Romanov on 10/10/2010 and fixed 16/10/2010.
+%% Stavros Aronis provided a better fix of the issue on 8/11/2010.
+%% ====================================================================
+
+-module(tuple_set_crash).
+-export([test/5]).
+
+%% ====================================================================
+
+-define(PREPEND_IF_BIT_SET(BitMap, Bit,
+ PatternInBinary, PatternInList,
+ OldRestVar, NewRestVar,
+ OldAccVar, NewAccVar),
+ case byteset:contains(Bit, BitMap) of
+ true ->
+ <<PatternInBinary, NewRestVar/binary>> = OldRestVar,
+ NewAccVar = [PatternInList | OldAccVar];
+ false ->
+ NewRestVar = OldRestVar,
+ NewAccVar = OldAccVar
+ end).
+
+%% ====================================================================
+
+%% Types used in parsing binaries
+-define(BITMAP1, 8/integer-big-unsigned).
+-define(BYTE, 8/integer-little-unsigned).
+-define(WORD, 16/integer-little-unsigned).
+-define(DWORD, 32/integer-little-unsigned).
+-define(DATE, 16/integer-little-signed).
+-define(TIME, 32/float-little-unsigned).
+-define(TINY_STRING_M(Var, Size), Size:?BYTE, Var:Size/binary).
+-define(SMALL_STRING_M(Var, Size), Size:?WORD, Var:Size/binary).
+
+-type config_change() ::
+ {device_properties |
+ video_target |
+ audio_target |
+ video_device |
+ audio_device |
+ video_output |
+ audio_output, [{atom(), any()}]}.
+
+-type message_from_server() ::
+ ok |
+ {error, atom()} |
+ config_change() |
+ {media_item_url_reply, integer(), binary()}.
+
+%% ====================================================================
+
+-spec test(integer(), [integer()], binary(), binary(), binary()) -> {binary(), binary()}.
+test(_TargetId, [], _Key, IVT, IVF) ->
+ {IVT, IVF};
+test(TargetId, [Date | DateTail], Key, IVT, IVF) ->
+ PlayListRequest = play_list_request(TargetId, Date),
+ {ok, Reply, IVT1, IVF1} = culprit(PlayListRequest, Key, IVT, IVF),
+ case Reply of
+ {play_list, _Playlist} ->
+ test(TargetId, DateTail, Key, IVT1, IVF1);
+ {error, 16#11} ->
+ {IVT1, IVF1} %% we can finish early
+ end.
+
+-spec culprit(binary(), binary(), binary(), binary()) ->
+ {ok, message_from_server(), binary(), binary()}.
+culprit(Message, Key, IVecToServer, IVecFromServer) ->
+ {Packet, NewIVecToServer} = message_to_packet(Message, Key, IVecToServer),
+ Message = crypto:aes_cbc_128_decrypt(Key, IVecFromServer, Packet),
+ NewIVecFromServer = crypto:aes_cbc_ivec(Packet),
+ ParsedMessage = parse_message(Message),
+ {ok, ParsedMessage, NewIVecToServer, NewIVecFromServer}.
+
+%% ====================================================================
+
+-spec play_list_request(integer(), integer()) -> binary().
+play_list_request(TargetId, Date) ->
+ <<16#06:?WORD, TargetId:?DWORD, Date:?DATE>>.
+
+-spec parse_message(binary()) -> message_from_server().
+parse_message(<<MessageID:?WORD, Rest/binary>>) ->
+ case MessageID of
+ 16#00 -> parse_error_code(Rest);
+ 16#22 -> {device_properties, parse_device_properties(Rest)};
+ 16#24 -> {video_target_info, parse_video_target_info(Rest)};
+ 16#25 -> {audio_target_info, parse_audio_target_info(Rest)};
+ 16#26 -> {video_device_info, parse_av_device_info(Rest)};
+ 16#27 -> {audio_device_info, parse_av_device_info(Rest)};
+ 16#28 -> {video_output_info, parse_video_output_info(Rest)};
+ 16#29 -> {audio_output_info, parse_audio_output_info(Rest)}
+ end.
+
+-spec parse_error_code(binary()) -> ok | {error, integer()}.
+parse_error_code(<<ErrorCode:?BYTE, _Padding/binary>>) ->
+ case ErrorCode of
+ 0 -> ok;
+ _ -> {error, ErrorCode}
+ end.
+
+-spec parse_device_properties(binary()) -> config_change().
+parse_device_properties(<<BitMap:?BITMAP1, Rest/binary>>) ->
+ Acc0 = [],
+ ?PREPEND_IF_BIT_SET(BitMap, 0,
+ FwVersion:3/binary, {fw_version, FwVersion},
+ Rest, Rest1, Acc0, Acc1),
+ ?PREPEND_IF_BIT_SET(BitMap, 1,
+ ?TINY_STRING_M(ControllerName, _S1),
+ {controller_name, ControllerName},
+ Rest1, Rest2, Acc1, Acc2),
+ ?PREPEND_IF_BIT_SET(BitMap, 2,
+ ?SMALL_STRING_M(ControllerDescription, _S2),
+ {controller_description, ControllerDescription},
+ Rest2, Rest3, Acc2, Acc3),
+ ?PREPEND_IF_BIT_SET(BitMap, 3,
+ ControllerStatus:?BYTE,
+ {controller_status, ControllerStatus},
+ Rest3, _Padding, Acc3, Acc4),
+ Acc4.
+
+-spec parse_video_target_info(binary()) -> config_change().
+parse_video_target_info(<<TargetId:?DWORD, Status:?BYTE, _Padding/binary>>) ->
+ [{target_id, TargetId}, {status, Status}].
+
+-spec parse_audio_target_info(binary()) -> [config_change()].
+parse_audio_target_info(<<TargetId:?DWORD, BitMap:?BITMAP1, Rest/binary>>) ->
+ Acc0 = [{target_id, TargetId}],
+ ?PREPEND_IF_BIT_SET(BitMap, 0,
+ Status:?BYTE, {status, Status},
+ Rest, Rest1, Acc0, Acc1),
+ ?PREPEND_IF_BIT_SET(BitMap, 1,
+ MasterVolume:?WORD, {master_volume, MasterVolume},
+ Rest1, _Padding, Acc1, Acc2),
+ Acc2.
+
+-spec parse_av_device_info(binary()) -> [config_change()].
+parse_av_device_info(<<DeviceId:?DWORD, BitMap:?BITMAP1, Rest/binary>>) ->
+ Acc0 = [{device_id, DeviceId}],
+ ?PREPEND_IF_BIT_SET(BitMap, 0,
+ TargetId:?DWORD, {target_id, TargetId},
+ Rest, Rest1, Acc0, Acc1),
+ ?PREPEND_IF_BIT_SET(BitMap, 1,
+ ?TINY_STRING_M(Model, _S1), {model, Model},
+ Rest1, Rest2, Acc1, Acc2),
+ ?PREPEND_IF_BIT_SET(BitMap, 2,
+ Address:?BYTE, {address, Address},
+ Rest2, Rest3, Acc2, Acc3),
+ ?PREPEND_IF_BIT_SET(BitMap, 3,
+ Status:?BYTE, {status, Status},
+ Rest3, _Padding, Acc3, Acc4),
+ Acc4.
+
+-spec parse_video_output_info(binary()) -> [config_change()].
+parse_video_output_info(<<Output:?DWORD, BitMap:?BITMAP1, Rest/binary>>) ->
+ Acc0 = [{output_id, Output}],
+ ?PREPEND_IF_BIT_SET(BitMap, 0,
+ DeviceId:?DWORD, {device_id, DeviceId},
+ Rest, Rest1, Acc0, Acc1),
+ ?PREPEND_IF_BIT_SET(BitMap, 1,
+ ?TINY_STRING_M(DisplayType, _S1),
+ {display_type, DisplayType},
+ Rest1, Rest2, Acc1, Acc2),
+ ?PREPEND_IF_BIT_SET(BitMap, 2,
+ AudioVolume:?WORD,
+ {audio_volume, AudioVolume},
+ Rest2, _Padding, Acc2, Acc3),
+ Acc3.
+
+-spec parse_audio_output_info(binary()) -> [config_change()].
+parse_audio_output_info(<<Output:?DWORD, BitMap:?BITMAP1, Rest/binary>>) ->
+ Acc0 = [{output_id, Output}],
+ ?PREPEND_IF_BIT_SET(BitMap, 0,
+ DeviceId:?DWORD, {device_id, DeviceId},
+ Rest, Rest1, Acc0, Acc1),
+ ?PREPEND_IF_BIT_SET(BitMap, 1,
+ AudioVolume:?WORD, {audio_volume, AudioVolume},
+ Rest1, Rest2, Acc1, Acc2),
+ ?PREPEND_IF_BIT_SET(BitMap, 2,
+ Delay:?WORD, {delay, Delay},
+ Rest2, _Padding, Acc2, Acc3),
+ Acc3.
+
+-spec message_to_packet(binary(), binary(), binary()) -> {binary(), binary()}.
+message_to_packet(Message, Key, IVec) ->
+ PaddedMessage = pad_pkcs5(Message),
+ Packet = crypto:aes_cbc_128_encrypt(Key, IVec, PaddedMessage),
+ TotalSize = byte_size(Packet),
+ NewIVec = crypto:aes_cbc_ivec(Packet),
+ {<<TotalSize:?WORD, Packet/binary>>, NewIVec}.
+
+-spec pad_pkcs5(binary()) -> binary().
+pad_pkcs5(Message) ->
+ Size = byte_size(Message),
+ PaddingSize = case Size rem 16 of
+ 0 -> 0;
+ Rem -> 16 - Rem
+ end,
+ pad_pkcs5(Message, PaddingSize, PaddingSize).
+
+-spec pad_pkcs5(binary(), integer(), integer()) -> binary().
+pad_pkcs5(Message, _PaddingSize, 0) ->
+ Message;
+pad_pkcs5(Message, PaddingSize, PaddingSizeRemaining) ->
+ pad_pkcs5(<<Message/binary, PaddingSize:?BYTE>>,
+ PaddingSize, PaddingSizeRemaining - 1).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/unsafe_beamcode_bug.erl b/lib/dialyzer/test/small_SUITE_data/src/unsafe_beamcode_bug.erl
new file mode 100644
index 0000000000..071b4a53c1
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/unsafe_beamcode_bug.erl
@@ -0,0 +1,14 @@
+-module(unsafe_beamcode_bug).
+-export([test/1]).
+
+test(N) -> i(r(N)).
+
+%% this function cannot be exported, or the error does not occur
+i({one}) -> ok1;
+i({two, _}) -> ok2;
+i({three, {_,R}, _}) -> R.
+
+r(1) -> {one};
+r(2) -> {two, 2};
+r(42)-> {dummy, 42}; % without this clause, no problem ... hmm
+r(3) -> {three, {rec,ok3}, 2}.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/unused_cases.erl b/lib/dialyzer/test/small_SUITE_data/src/unused_cases.erl
index e6e6693963..e6e6693963 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/unused_cases.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/unused_cases.erl
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/unused_clauses.erl b/lib/dialyzer/test/small_SUITE_data/src/unused_clauses.erl
index a98b227a6b..a98b227a6b 100644
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/unused_clauses.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/unused_clauses.erl
diff --git a/lib/dialyzer/test/small_SUITE_data/src/zero_tuple.erl b/lib/dialyzer/test/small_SUITE_data/src/zero_tuple.erl
new file mode 100644
index 0000000000..7c790e5658
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/zero_tuple.erl
@@ -0,0 +1,12 @@
+-module(zero_tuple).
+-export([t1/0, t2/0]).
+
+t1() ->
+ {} = a(),
+ ok.
+
+t2() ->
+ b = a(),
+ ok.
+
+a() -> a.
diff --git a/lib/dialyzer/test/small_tests_SUITE.erl b/lib/dialyzer/test/small_tests_SUITE.erl
deleted file mode 100644
index 21a2c76160..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE.erl
+++ /dev/null
@@ -1,483 +0,0 @@
-%% ATTENTION!
-%% This is an automatically generated file. Do not edit.
-%% Use './remake' script to refresh it if needed.
-%% All Dialyzer options should be defined in dialyzer_options
-%% file.
-
--module(small_tests_SUITE).
-
--include("ct.hrl").
--include("dialyzer_test_constants.hrl").
-
--export([suite/0, init_per_suite/0, init_per_suite/1,
- end_per_suite/1, all/0]).
--export([small_tests_SUITE_consistency/1, app_call/1, appmon_place/1,
- areq/1, atom_call/1, atom_guard/1, atom_widen/1,
- bs_fail_constr/1, bs_utf8/1, cerl_hipeify/1, comm_layer/1,
- compare1/1, confusing_warning/1, contract2/1, contract3/1,
- contract5/1, disj_norm_form/1, eqeq/1, ets_select/1,
- exhaust_case/1, failing_guard1/1, flatten/1, fun_app/1,
- fun_ref_match/1, fun_ref_record/1, gencall/1, gs_make/1,
- inf_loop2/1, letrec1/1, list_match/1, lzip/1, make_tuple/1,
- minus_minus/1, mod_info/1, my_filter/1, my_sofs/1, no_match/1,
- no_unused_fun/1, no_unused_fun2/1, non_existing/1,
- not_guard_crash/1, or_bug/1, orelsebug/1, orelsebug2/1,
- overloaded1/1, port_info_test/1, process_info_test/1, pubsub/1,
- receive1/1, record_construct/1, record_pat/1,
- record_send_test/1, record_test/1, recursive_types1/1,
- recursive_types2/1, recursive_types3/1, recursive_types4/1,
- recursive_types5/1, recursive_types6/1, recursive_types7/1,
- refine_bug1/1, toth/1, trec/1, try1/1, tuple1/1,
- unsafe_beamcode_bug/1, unused_cases/1, unused_clauses/1,
- zero_tuple/1]).
-
-suite() ->
- [{timetrap, {minutes, 1}}].
-
-init_per_suite() ->
- [{timetrap, ?plt_timeout}].
-init_per_suite(Config) ->
- OutDir = ?config(priv_dir, Config),
- case dialyzer_common:check_plt(OutDir) of
- fail -> {skip, "Plt creation/check failed."};
- ok -> [{dialyzer_options, []}|Config]
- end.
-
-end_per_suite(_Config) ->
- ok.
-
-all() ->
- [small_tests_SUITE_consistency,app_call,appmon_place,areq,atom_call,
- atom_guard,atom_widen,bs_fail_constr,bs_utf8,cerl_hipeify,comm_layer,
- compare1,confusing_warning,contract2,contract3,contract5,disj_norm_form,
- eqeq,ets_select,exhaust_case,failing_guard1,flatten,fun_app,fun_ref_match,
- fun_ref_record,gencall,gs_make,inf_loop2,letrec1,list_match,lzip,
- make_tuple,minus_minus,mod_info,my_filter,my_sofs,no_match,no_unused_fun,
- no_unused_fun2,non_existing,not_guard_crash,or_bug,orelsebug,orelsebug2,
- overloaded1,port_info_test,process_info_test,pubsub,receive1,
- record_construct,record_pat,record_send_test,record_test,recursive_types1,
- recursive_types2,recursive_types3,recursive_types4,recursive_types5,
- recursive_types6,recursive_types7,refine_bug1,toth,trec,try1,tuple1,
- unsafe_beamcode_bug,unused_cases,unused_clauses,zero_tuple].
-
-dialyze(Config, TestCase) ->
- Opts = ?config(dialyzer_options, Config),
- Dir = ?config(data_dir, Config),
- OutDir = ?config(priv_dir, Config),
- dialyzer_common:check(TestCase, Opts, Dir, OutDir).
-
-small_tests_SUITE_consistency(Config) ->
- Dir = ?config(data_dir, Config),
- case dialyzer_common:new_tests(Dir, all()) of
- [] -> ok;
- New -> ct:fail({missing_tests,New})
- end.
-
-app_call(Config) ->
- case dialyze(Config, app_call) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-appmon_place(Config) ->
- case dialyze(Config, appmon_place) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-areq(Config) ->
- case dialyze(Config, areq) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-atom_call(Config) ->
- case dialyze(Config, atom_call) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-atom_guard(Config) ->
- case dialyze(Config, atom_guard) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-atom_widen(Config) ->
- case dialyze(Config, atom_widen) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-bs_fail_constr(Config) ->
- case dialyze(Config, bs_fail_constr) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-bs_utf8(Config) ->
- case dialyze(Config, bs_utf8) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-cerl_hipeify(Config) ->
- case dialyze(Config, cerl_hipeify) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-comm_layer(Config) ->
- case dialyze(Config, comm_layer) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-compare1(Config) ->
- case dialyze(Config, compare1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-confusing_warning(Config) ->
- case dialyze(Config, confusing_warning) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-contract2(Config) ->
- case dialyze(Config, contract2) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-contract3(Config) ->
- case dialyze(Config, contract3) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-contract5(Config) ->
- case dialyze(Config, contract5) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-disj_norm_form(Config) ->
- case dialyze(Config, disj_norm_form) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-eqeq(Config) ->
- case dialyze(Config, eqeq) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-ets_select(Config) ->
- case dialyze(Config, ets_select) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-exhaust_case(Config) ->
- case dialyze(Config, exhaust_case) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-failing_guard1(Config) ->
- case dialyze(Config, failing_guard1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-flatten(Config) ->
- case dialyze(Config, flatten) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-fun_app(Config) ->
- case dialyze(Config, fun_app) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-fun_ref_match(Config) ->
- case dialyze(Config, fun_ref_match) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-fun_ref_record(Config) ->
- case dialyze(Config, fun_ref_record) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-gencall(Config) ->
- case dialyze(Config, gencall) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-gs_make(Config) ->
- case dialyze(Config, gs_make) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-inf_loop2(Config) ->
- case dialyze(Config, inf_loop2) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-letrec1(Config) ->
- case dialyze(Config, letrec1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-list_match(Config) ->
- case dialyze(Config, list_match) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-lzip(Config) ->
- case dialyze(Config, lzip) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-make_tuple(Config) ->
- case dialyze(Config, make_tuple) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-minus_minus(Config) ->
- case dialyze(Config, minus_minus) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-mod_info(Config) ->
- case dialyze(Config, mod_info) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-my_filter(Config) ->
- case dialyze(Config, my_filter) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-my_sofs(Config) ->
- case dialyze(Config, my_sofs) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-no_match(Config) ->
- case dialyze(Config, no_match) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-no_unused_fun(Config) ->
- case dialyze(Config, no_unused_fun) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-no_unused_fun2(Config) ->
- case dialyze(Config, no_unused_fun2) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-non_existing(Config) ->
- case dialyze(Config, non_existing) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-not_guard_crash(Config) ->
- case dialyze(Config, not_guard_crash) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-or_bug(Config) ->
- case dialyze(Config, or_bug) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-orelsebug(Config) ->
- case dialyze(Config, orelsebug) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-orelsebug2(Config) ->
- case dialyze(Config, orelsebug2) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-overloaded1(Config) ->
- case dialyze(Config, overloaded1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-port_info_test(Config) ->
- case dialyze(Config, port_info_test) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-process_info_test(Config) ->
- case dialyze(Config, process_info_test) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-pubsub(Config) ->
- case dialyze(Config, pubsub) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-receive1(Config) ->
- case dialyze(Config, receive1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-record_construct(Config) ->
- case dialyze(Config, record_construct) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-record_pat(Config) ->
- case dialyze(Config, record_pat) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-record_send_test(Config) ->
- case dialyze(Config, record_send_test) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-record_test(Config) ->
- case dialyze(Config, record_test) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-recursive_types1(Config) ->
- case dialyze(Config, recursive_types1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-recursive_types2(Config) ->
- case dialyze(Config, recursive_types2) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-recursive_types3(Config) ->
- case dialyze(Config, recursive_types3) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-recursive_types4(Config) ->
- case dialyze(Config, recursive_types4) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-recursive_types5(Config) ->
- case dialyze(Config, recursive_types5) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-recursive_types6(Config) ->
- case dialyze(Config, recursive_types6) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-recursive_types7(Config) ->
- case dialyze(Config, recursive_types7) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-refine_bug1(Config) ->
- case dialyze(Config, refine_bug1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-toth(Config) ->
- case dialyze(Config, toth) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-trec(Config) ->
- case dialyze(Config, trec) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-try1(Config) ->
- case dialyze(Config, try1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-tuple1(Config) ->
- case dialyze(Config, tuple1) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-unsafe_beamcode_bug(Config) ->
- case dialyze(Config, unsafe_beamcode_bug) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-unused_cases(Config) ->
- case dialyze(Config, unused_cases) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-unused_clauses(Config) ->
- case dialyze(Config, unused_clauses) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-zero_tuple(Config) ->
- case dialyze(Config, zero_tuple) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/flatten b/lib/dialyzer/test/small_tests_SUITE_data/results/flatten
deleted file mode 100644
index 4571214e49..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/flatten
+++ /dev/null
@@ -1,2 +0,0 @@
-
-flatten.erl:17: The call lists:flatten(nonempty_improper_list(atom() | binary() | [any()] | char(),atom())) will never return since it differs in the 1st argument from the success typing arguments: ([any()])
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/results/my_sofs b/lib/dialyzer/test/small_tests_SUITE_data/results/my_sofs
deleted file mode 100644
index bfee0bce0d..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/results/my_sofs
+++ /dev/null
@@ -1,3 +0,0 @@
-
-my_sofs.erl:34: The pattern {'Set', _, _} can never match the type #OrdSet{}
-my_sofs.erl:54: The pattern {'Set', _, _} can never match the type #OrdSet{}
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/appmon_place.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/appmon_place.erl
deleted file mode 100644
index 8371cab233..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/appmon_place.erl
+++ /dev/null
@@ -1,71 +0,0 @@
-%%---------------------------------------------------------------------
-%% This is added as a test because it was giving a false positive
-%% (function move/4 will nevr be called) due to the strange use of
-%% self-recursive fun construction in placex/3.
-%%
-%% The analysis was getting confused that the foldl call will never
-%% terminate (due to a wrong hard-coded type for foldl) and inferred
-%% that the remaining calls in the body of placex/3 will not be
-%% reached. Fixed 11 March 2005.
-%%---------------------------------------------------------------------
-
--module(appmon_place).
--export([place/2]).
-
-place(DG, Root) ->
- case appmon_dg:get(data, DG, Root) of
- false -> [0];
- _Other ->
- placey(DG, Root, 1),
- placex(DG, Root, [])
- end.
-
-placey(DG, V, Y) ->
- appmon_dg:set(y, DG, V, Y),
- Y1 = Y+1,
- lists:foreach(fun(C) -> placey(DG, C, Y1) end, appmon_dg:get(out, DG, V)).
-
-placex(DG, V, LastX) ->
- Ch = appmon_dg:get(out, DG, V),
- ChLX = lists:foldl(fun(C, Accu) -> placex(DG, C, Accu) end,
- tll(LastX),
- Ch),
- Width = appmon_dg:get(w, DG, V),
- MyX = calc_mid(DG, Width, Ch),
- DeltaX = calc_delta(MyX, hdd(LastX)+20),
- appmon_dg:set(x, DG, V, MyX),
- move(DG, V, [MyX+Width | ChLX], DeltaX).
-
-move(_DG, _L, LastX, 0) -> LastX;
-move(DG, V, LastX, DeltaX) -> move2(DG, V, LastX, DeltaX).
-
-move2(DG, V, LastX, DeltaX) ->
- NewX = appmon_dg:get(x, DG, V)+DeltaX,
- appmon_dg:set(x, DG, V, NewX),
- ChLX = lists:foldl(fun(C, LX) -> move2(DG, C, LX, DeltaX) end,
- tll(LastX),
- appmon_dg:get(out, DG, V)),
- [max(NewX+appmon_dg:get(w, DG, V), hdd(LastX)) | ChLX].
-
-max(A, B) when A>B -> A;
-max(_, B) -> B.
-
-calc_mid(_DG, _Width, []) -> 0;
-calc_mid(DG, Width, ChList) ->
- LeftMostX = appmon_dg:get(x, DG, hd(ChList)),
- Z2 = lists:last(ChList),
- RightMostX = appmon_dg:get(x, DG, Z2)+appmon_dg:get(w, DG, Z2),
- trunc((LeftMostX+RightMostX)/2)-trunc(Width/2).
-
-calc_delta(Mid, Right) ->
- if Right>Mid -> Right-Mid;
- true -> 0
- end.
-
-%% Special head and tail
-%% Handles empty list in a non-standard way
-tll([]) -> [];
-tll([_|T]) -> T.
-hdd([]) -> 0;
-hdd([H|_]) -> H.
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/areq.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/areq.erl
deleted file mode 100644
index 1b4eea8511..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/areq.erl
+++ /dev/null
@@ -1,12 +0,0 @@
--module(areq).
-
--export([t/0]).
-
-t() ->
- ar_comp(3.0, 3),
- ex_comp(3.0, 3).
-
-ar_comp(X, Y) -> X == Y.
-
-ex_comp(X, Y) -> X =:= Y.
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/atom_call.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/atom_call.erl
deleted file mode 100644
index bf0646eadc..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/atom_call.erl
+++ /dev/null
@@ -1,14 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : atom_call.erl
-%%% Author : Tobias Lindahl <[email protected]>
-%%% Description :
-%%%
-%%% Created : 10 Dec 2007 by Tobias Lindahl <[email protected]>
-%%%-------------------------------------------------------------------
--module(atom_call).
-
--export([f/0,g/0]).
-
-f() -> ok.
-
-g() -> F = f, F().
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/atom_guard.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/atom_guard.erl
deleted file mode 100644
index 67d97f8e29..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/atom_guard.erl
+++ /dev/null
@@ -1,9 +0,0 @@
--module(atom_guard).
--export([test/0]).
-
-test() ->
- foo(42).
-
-foo(X) when is_atom(x) ->
- X.
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/bs_fail_constr.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/bs_fail_constr.erl
deleted file mode 100644
index 20fd1cbf64..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/bs_fail_constr.erl
+++ /dev/null
@@ -1,16 +0,0 @@
--module(bs_fail_constr).
-
--export([w1/1, w2/1, w3/1, w4/1]).
-
-w1(V) when is_float(V) ->
- <<V/integer>>.
-
-w2(V) when is_atom(V) ->
- <<V/binary>>.
-
-w3(S) when is_integer(S), S < 0 ->
- <<42:S/integer>>.
-
-w4(V) when is_float(V) ->
- <<V/utf32>>.
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/cerl_hipeify.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/cerl_hipeify.erl
deleted file mode 100644
index 3ccadec4d0..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/cerl_hipeify.erl
+++ /dev/null
@@ -1,684 +0,0 @@
-%% =====================================================================
-%% This library is free software; you can redistribute it and/or modify
-%% it under the terms of the GNU Lesser General Public License as
-%% published by the Free Software Foundation; either version 2 of the
-%% License, or (at your option) any later version.
-%%
-%% This library is distributed in the hope that it will be useful, but
-%% WITHOUT ANY WARRANTY; without even the implied warranty of
-%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-%% Lesser General Public License for more details.
-%%
-%% You should have received a copy of the GNU Lesser General Public
-%% License along with this library; if not, write to the Free Software
-%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-%% USA
-%%
-%% $Id: cerl_hipeify.erl,v 1.1 2008/12/17 09:53:49 mikpe Exp $
-%%
-%% @author Richard Carlsson <[email protected]>
-%% @copyright 2000-2004 Richard Carlsson
-%% @doc HiPE-ification of Core Erlang code. Prepares Core Erlang code
-%% for translation to ICode.
-%% @see cerl_to_icode
-
--module(cerl_hipeify).
-
--export([transform/2]).
-
--define(PRIMOP_IDENTITY, identity). % arity 1
--define(PRIMOP_NOT, 'not'). % arity 1
--define(PRIMOP_AND, 'and'). % arity 2
--define(PRIMOP_OR, 'or'). % arity 2
--define(PRIMOP_XOR, 'xor'). % arity 2
--define(PRIMOP_ADD, '+'). % arity 2
--define(PRIMOP_SUB, '-'). % arity 2
--define(PRIMOP_NEG, neg). % arity 1
--define(PRIMOP_MUL, '*'). % arity 2
--define(PRIMOP_DIV, '/'). % arity 2
--define(PRIMOP_INTDIV, 'div'). % arity 2
--define(PRIMOP_REM, 'rem'). % arity 2
--define(PRIMOP_BAND, 'band'). % arity 2
--define(PRIMOP_BOR, 'bor'). % arity 2
--define(PRIMOP_BXOR, 'bxor'). % arity 2
--define(PRIMOP_BNOT, 'bnot'). % arity 1
--define(PRIMOP_BSL, 'bsl'). % arity 2
--define(PRIMOP_BSR, 'bsr'). % arity 2
--define(PRIMOP_EQ, '=='). % arity 2
--define(PRIMOP_NE, '/='). % arity 2
--define(PRIMOP_EXACT_EQ, '=:='). % arity 2
--define(PRIMOP_EXACT_NE, '=/='). % arity 2
--define(PRIMOP_LT, '<'). % arity 2
--define(PRIMOP_GT, '>'). % arity 2
--define(PRIMOP_LE, '=<'). % arity 2
--define(PRIMOP_GE, '>='). % arity 2
--define(PRIMOP_IS_ATOM, 'is_atom'). % arity 1
--define(PRIMOP_IS_BIGNUM, 'is_bignum'). % arity 1
--define(PRIMOP_IS_BINARY, 'is_binary'). % arity 1
--define(PRIMOP_IS_CONSTANT, 'is_constant'). % arity 1
--define(PRIMOP_IS_FIXNUM, 'is_fixnum'). % arity 1
--define(PRIMOP_IS_FLOAT, 'is_float'). % arity 1
--define(PRIMOP_IS_FUNCTION, 'is_function'). % arity 1
--define(PRIMOP_IS_INTEGER, 'is_integer'). % arity 1
--define(PRIMOP_IS_LIST, 'is_list'). % arity 1
--define(PRIMOP_IS_NUMBER, 'is_number'). % arity 1
--define(PRIMOP_IS_PID, 'is_pid'). % arity 1
--define(PRIMOP_IS_PORT, 'is_port'). % arity 1
--define(PRIMOP_IS_REFERENCE, 'is_reference'). % arity 1
--define(PRIMOP_IS_TUPLE, 'is_tuple'). % arity 1
--define(PRIMOP_IS_RECORD, 'is_record'). % arity 3
--define(PRIMOP_EXIT, exit). % arity 1
--define(PRIMOP_THROW, throw). % arity 1
--define(PRIMOP_ERROR, error). % arity 1,2
--define(PRIMOP_RETHROW, raise). % arity 2
--define(PRIMOP_RECEIVE_SELECT, receive_select). % arity 0
--define(PRIMOP_RECEIVE_NEXT, receive_next). % arity 0
--define(PRIMOP_ELEMENT, element). % arity 2
--define(PRIMOP_DSETELEMENT, dsetelement). % arity 3
--define(PRIMOP_MAKE_FUN, make_fun). % arity 6
--define(PRIMOP_APPLY_FUN, apply_fun). % arity 2
--define(PRIMOP_FUN_ELEMENT, closure_element). % arity 2
--define(PRIMOP_SET_LABEL, set_label). % arity 1
--define(PRIMOP_GOTO_LABEL, goto_label). % arity 1
--define(PRIMOP_REDUCTION_TEST, reduction_test). % arity 0
-
--record(ctxt, {class = expr}).
-
-
-%% @spec transform(Module::cerl(), Options::[term()]) -> cerl()
-%%
-%% cerl() = cerl:cerl()
-%%
-%% @doc Rewrites a Core Erlang module to a form suitable for further
-%% translation to HiPE Icode. See module <code>cerl_to_icode</code> for
-%% details.
-%%
-%% @see cerl_to_icode
-%% @see cerl_cconv
-
-transform(E, Opts) ->
- %% Start by closure converting the code
- module(cerl_cconv:transform(E, Opts), Opts).
-
-module(E, Opts) ->
- {Ds, Env, Ren} = add_defs(cerl:module_defs(E), env__new(),
- ren__new()),
- M = cerl:module_name(E),
- S0 = s__new(cerl:atom_val(M)),
- S = s__set_pmatch(proplists:get_value(pmatch, Opts), S0),
- {Ds1, _} = defs(Ds, true, Env, Ren, S),
- cerl:update_c_module(E, M, cerl:module_exports(E),
- cerl:module_attrs(E), Ds1).
-
-%% Note that the environment is defined on the renamed variables.
-
-expr(E0, Env, Ren, Ctxt, S0) ->
- %% Do peephole optimizations as we traverse the code.
- E = cerl_lib:reduce_expr(E0),
- case cerl:type(E) of
- literal ->
- {E, S0};
- var ->
- variable(E, Env, Ren, Ctxt, S0);
- values ->
- {Es, S1} = expr_list(cerl:values_es(E), Env, Ren, Ctxt, S0),
- {cerl:update_c_values(E, Es), S1};
- cons ->
- {E1, S1} = expr(cerl:cons_hd(E), Env, Ren, Ctxt, S0),
- {E2, S2} = expr(cerl:cons_tl(E), Env, Ren, Ctxt, S1),
- {cerl:update_c_cons(E, E1, E2), S2};
- tuple ->
- {Es, S1} = expr_list(cerl:tuple_es(E), Env, Ren, Ctxt, S0),
- {cerl:update_c_tuple(E, Es), S1};
- 'let' ->
- let_expr(E, Env, Ren, Ctxt, S0);
- seq ->
- {A, S1} = expr(cerl:seq_arg(E), Env, Ren, Ctxt, S0),
- {B, S2} = expr(cerl:seq_body(E), Env, Ren, Ctxt, S1),
- {cerl:update_c_seq(E, A, B), S2};
- apply ->
- {Op, S1} = expr(cerl:apply_op(E), Env, Ren, Ctxt, S0),
- {As, S2} = expr_list(cerl:apply_args(E), Env, Ren, Ctxt, S1),
- {cerl:update_c_apply(E, Op, As), S2};
- call ->
- {M, S1} = expr(cerl:call_module(E), Env, Ren, Ctxt, S0),
- {N, S2} = expr(cerl:call_name(E), Env, Ren, Ctxt, S1),
- {As, S3} = expr_list(cerl:call_args(E), Env, Ren, Ctxt, S2),
- {rewrite_call(E, M, N, As, S3), S3};
- primop ->
- {As, S1} = expr_list(cerl:primop_args(E), Env, Ren, Ctxt, S0),
- N = cerl:primop_name(E),
- {rewrite_primop(E, N, As, S1), S1};
- 'case' ->
- {A, S1} = expr(cerl:case_arg(E), Env, Ren, Ctxt, S0),
- {E1, Vs, S2} = clauses(cerl:case_clauses(E), Env, Ren, Ctxt, S1),
- {cerl:c_let(Vs, A, E1), S2};
- 'fun' ->
- Vs = cerl:fun_vars(E),
- {Vs1, Env1, Ren1} = add_vars(Vs, Env, Ren),
- {B, S1} = expr(cerl:fun_body(E), Env1, Ren1, Ctxt, S0),
- {cerl:update_c_fun(E, Vs1, B), S1};
- 'receive' ->
- receive_expr(E, Env, Ren, Ctxt, S0);
- 'try' ->
- {A, S1} = expr(cerl:try_arg(E), Env, Ren, Ctxt, S0),
- Vs = cerl:try_vars(E),
- {Vs1, Env1, Ren1} = add_vars(Vs, Env, Ren),
- {B, S2} = expr(cerl:try_body(E), Env1, Ren1, Ctxt, S1),
- Evs = cerl:try_evars(E),
- {Evs1, Env2, Ren2} = add_vars(Evs, Env, Ren),
- {H, S3} = expr(cerl:try_handler(E), Env2, Ren2, Ctxt, S2),
- {cerl:update_c_try(E, A, Vs1, B, Evs1, H), S3};
- 'catch' ->
- catch_expr(E, Env, Ren, Ctxt, S0);
- letrec ->
- {Ds, Env1, Ren1} = add_defs(cerl:letrec_defs(E), Env, Ren),
- {Ds1, S1} = defs(Ds, false, Env1, Ren1, S0),
- {B, S2} = expr(cerl:letrec_body(E), Env1, Ren1, Ctxt, S1),
- {cerl:update_c_letrec(E, Ds1, B), S2};
- binary ->
- {Segs, S1}=expr_list(cerl:binary_segments(E), Env, Ren,
- Ctxt, S0),
- {cerl:update_c_binary(E, Segs), S1};
- bitstr ->
- {E1,S1} = expr(cerl:bitstr_val(E), Env, Ren, Ctxt, S0),
- {E2,S2} = expr(cerl:bitstr_size(E), Env, Ren, Ctxt, S1),
- E3 = cerl:bitstr_unit(E),
- E4 = cerl:bitstr_type(E),
- E5 = cerl:bitstr_flags(E),
- {cerl:update_c_bitstr(E, E1, E2, E3, E4, E5), S2}
- end.
-
-guard_expr(E, Env, Ren, Ctxt, S) ->
- expr(E, Env, Ren, Ctxt#ctxt{class = guard}, S).
-
-expr_list(Es, Env, Ren, Ctxt, S0) ->
- list(Es, Env, Ren, Ctxt, S0, fun expr/5).
-
-list([E | Es], Env, Ren, Ctxt, S0, F) ->
- {E1, S1} = F(E, Env, Ren, Ctxt, S0),
- {Es1, S2} = list(Es, Env, Ren, Ctxt, S1, F),
- {[E1 | Es1], S2};
-list([], _, _, _, S, _) ->
- {[], S}.
-
-pattern(E, Env, Ren) ->
- case cerl:type(E) of
- literal ->
- E;
- var ->
- cerl:update_c_var(E, ren__map(cerl:var_name(E), Ren));
- values ->
- Es = pattern_list(cerl:values_es(E), Env, Ren),
- cerl:update_c_values(E, Es);
- cons ->
- E1 = pattern(cerl:cons_hd(E), Env, Ren),
- E2 = pattern(cerl:cons_tl(E), Env, Ren),
- cerl:update_c_cons(E, E1, E2);
- tuple ->
- Es = pattern_list(cerl:tuple_es(E), Env, Ren),
- cerl:update_c_tuple(E, Es);
- alias ->
- V = pattern(cerl:alias_var(E), Env, Ren),
- P = pattern(cerl:alias_pat(E), Env, Ren),
- cerl:update_c_alias(E, V, P);
- binary ->
- Segs=pattern_list(cerl:binary_segments(E), Env, Ren),
- cerl:update_c_binary(E, Segs);
- bitstr ->
- E1 = pattern(cerl:bitstr_val(E), Env, Ren),
- E2 = pattern(cerl:bitstr_size(E), Env, Ren),
- E3 = cerl:bitstr_unit(E),
- E4 = cerl:bitstr_type(E),
- E5 = cerl:bitstr_flags(E),
- cerl:update_c_bitstr(E, E1, E2, E3, E4, E5)
- end.
-
-
-
-pattern_list([E | Es], Env, Ren) ->
- [pattern(E, Env, Ren) | pattern_list(Es, Env, Ren)];
-pattern_list([], _, _) ->
- [].
-
-%% Visit the function body of each definition. We insert an explicit
-%% reduction test at the start of each function.
-
-defs(Ds, Top, Env, Ren, S) ->
- defs(Ds, [], Top, Env, Ren, S).
-
-defs([{V, F} | Ds], Ds1, Top, Env, Ren, S0) ->
- S1 = case Top of
- true -> s__enter_function(cerl:var_name(V), S0);
- false -> S0
- end,
- {B, S2} = expr(cerl:fun_body(F), Env, Ren, #ctxt{}, S1),
- B1 = cerl:c_seq(cerl:c_primop(cerl:c_atom(?PRIMOP_REDUCTION_TEST),
- []),
- B),
- F1 = cerl:update_c_fun(F, cerl:fun_vars(F), B1),
- defs(Ds, [{V, F1} | Ds1], Top, Env, Ren, S2);
-defs([], Ds, _Top, _Env, _Ren, S) ->
- {lists:reverse(Ds), S}.
-
-clauses([C|_]=Cs, Env, Ren, Ctxt, S) ->
- {Cs1, S1} = clause_list(Cs, Env, Ren, Ctxt, S),
- %% Perform pattern matching compilation on the clauses.
- {E, Vs} = case s__get_pmatch(S) of
- true ->
- cerl_pmatch:clauses(Cs1, Env);
- no_duplicates ->
- put('cerl_pmatch_duplicate_code', never),
- cerl_pmatch:clauses(Cs1, Env);
- duplicate_all ->
- put('cerl_pmatch_duplicate_code', always),
- cerl_pmatch:clauses(Cs1, Env);
- Other when Other == false; Other == undefined ->
- Vs0 = new_vars(cerl:clause_arity(C), Env),
- {cerl:c_case(cerl:c_values(Vs0), Cs1), Vs0}
- end,
- %% We must make sure that we also visit any clause guards generated
- %% by the pattern matching compilation. We pass an empty renaming,
- %% so we do not rename any variables twice.
- {E1, S2} = revisit_expr(E, Env, ren__new(), Ctxt, S1),
- {E1, Vs, S2}.
-
-clause_list(Cs, Env, Ren, Ctxt, S) ->
- list(Cs, Env, Ren, Ctxt, S, fun clause/5).
-
-clause(E, Env, Ren, Ctxt, S0) ->
- Vs = cerl:clause_vars(E),
- {_, Env1, Ren1} = add_vars(Vs, Env, Ren),
- %% Visit patterns to rename variables.
- Ps = pattern_list(cerl:clause_pats(E), Env1, Ren1),
- {G, S1} = guard_expr(cerl:clause_guard(E), Env1, Ren1, Ctxt, S0),
- {B, S2} = expr(cerl:clause_body(E), Env1, Ren1, Ctxt, S1),
- {cerl:update_c_clause(E, Ps, G, B), S2}.
-
-%% This does what 'expr' does, but only recurses into clause guard
-%% expressions, 'case'-expressions, and the bodies of lets and letrecs.
-%% Note that revisiting should not add further renamings, and we simply
-%% ignore making any bindings at all at this level.
-
-revisit_expr(E, Env, Ren, Ctxt, S0) ->
- %% Also enable peephole optimizations here.
- revisit_expr_1(cerl_lib:reduce_expr(E), Env, Ren, Ctxt, S0).
-
-revisit_expr_1(E, Env, Ren, Ctxt, S0) ->
- case cerl:type(E) of
- 'case' ->
- {Cs, S1} = revisit_clause_list(cerl:case_clauses(E), Env,
- Ren, Ctxt, S0),
- {cerl:update_c_case(E, cerl:case_arg(E), Cs), S1};
- 'let' ->
- {B, S1} = revisit_expr(cerl:let_body(E), Env, Ren, Ctxt, S0),
- {cerl:update_c_let(E, cerl:let_vars(E), cerl:let_arg(E), B),
- S1};
- 'letrec' ->
- {B, S1} = revisit_expr(cerl:letrec_body(E), Env, Ren, Ctxt, S0),
- {cerl:update_c_letrec(E, cerl:letrec_defs(E), B), S1};
- _ ->
- {E, S0}
- end.
-
-revisit_clause_list(Cs, Env, Ren, Ctxt, S) ->
- list(Cs, Env, Ren, Ctxt, S, fun revisit_clause/5).
-
-revisit_clause(E, Env, Ren, Ctxt, S0) ->
- %% Ignore the bindings.
- {G, S1} = guard_expr(cerl:clause_guard(E), Env, Ren, Ctxt, S0),
- {B, S2} = revisit_expr(cerl:clause_body(E), Env, Ren, Ctxt, S1),
- {cerl:update_c_clause(E, cerl:clause_pats(E), G, B), S2}.
-
-%% We use the no-shadowing strategy, renaming variables on the fly and
-%% only when necessary to uphold the invariant.
-
-add_vars(Vs, Env, Ren) ->
- add_vars(Vs, [], Env, Ren).
-
-add_vars([V | Vs], Vs1, Env, Ren) ->
- Name = cerl:var_name(V),
- {Name1, Ren1} = rename(Name, Env, Ren),
- add_vars(Vs, [cerl:update_c_var(V, Name1) | Vs1],
- env__bind(Name1, variable, Env), Ren1);
-add_vars([], Vs, Env, Ren) ->
- {lists:reverse(Vs), Env, Ren}.
-
-rename(Name, Env, Ren) ->
- case env__is_defined(Name, Env) of
- false ->
- {Name, Ren};
- true ->
- New = env__new_name(Env),
- {New, ren__add(Name, New, Ren)}
- end.
-
-%% Setting up the environment for a list of letrec-bound definitions.
-
-add_defs(Ds, Env, Ren) ->
- add_defs(Ds, [], Env, Ren).
-
-add_defs([{V, F} | Ds], Ds1, Env, Ren) ->
- Name = cerl:var_name(V),
- {Name1, Ren1} =
- case env__is_defined(Name, Env) of
- false ->
- {Name, Ren};
- true ->
- {N, A} = Name,
- S = atom_to_list(N) ++ "_",
- F = fun (Num) -> %% XXX: BUG: This should be F1
- {list_to_atom(S ++ integer_to_list(Num)), A}
- end,
- New = env__new_function_name(F, Env),
- {New, ren__add(Name, New, Ren)}
- end,
- add_defs(Ds, [{cerl:update_c_var(V, Name1), F} | Ds1],
- env__bind(Name1, function, Env), Ren1);
-add_defs([], Ds, Env, Ren) ->
- {lists:reverse(Ds), Env, Ren}.
-
-%% We change remote calls to important built-in functions into primop
-%% calls. In some cases (e.g., for the boolean operators), this is
-%% mainly to allow the cerl_to_icode module to handle them more
-%% straightforwardly. In most cases however, it is simply because they
-%% are supposed to be represented as primop calls on the Icode level.
-
-rewrite_call(E, M, F, As, S) ->
- case cerl:is_c_atom(M) and cerl:is_c_atom(F) of
- true ->
- case call_to_primop(cerl:atom_val(M),
- cerl:atom_val(F),
- length(As))
- of
- {yes, N} ->
- %% The primop might need further handling
- N1 = cerl:c_atom(N),
- E1 = cerl:update_c_primop(E, N1, As),
- rewrite_primop(E1, N1, As, S);
- no ->
- cerl:update_c_call(E, M, F, As)
- end;
- false ->
- cerl:update_c_call(E, M, F, As)
- end.
-
-call_to_primop(erlang, 'not', 1) -> {yes, ?PRIMOP_NOT};
-call_to_primop(erlang, 'and', 2) -> {yes, ?PRIMOP_AND};
-call_to_primop(erlang, 'or', 2) -> {yes, ?PRIMOP_OR};
-call_to_primop(erlang, 'xor', 2) -> {yes, ?PRIMOP_XOR};
-call_to_primop(erlang, '+', 2) -> {yes, ?PRIMOP_ADD};
-call_to_primop(erlang, '+', 1) -> {yes, ?PRIMOP_IDENTITY};
-call_to_primop(erlang, '-', 2) -> {yes, ?PRIMOP_SUB};
-call_to_primop(erlang, '-', 1) -> {yes, ?PRIMOP_NEG};
-call_to_primop(erlang, '*', 2) -> {yes, ?PRIMOP_MUL};
-call_to_primop(erlang, '/', 2) -> {yes, ?PRIMOP_DIV};
-call_to_primop(erlang, 'div', 2) -> {yes, ?PRIMOP_INTDIV};
-call_to_primop(erlang, 'rem', 2) -> {yes, ?PRIMOP_REM};
-call_to_primop(erlang, 'band', 2) -> {yes, ?PRIMOP_BAND};
-call_to_primop(erlang, 'bor', 2) -> {yes, ?PRIMOP_BOR};
-call_to_primop(erlang, 'bxor', 2) -> {yes, ?PRIMOP_BXOR};
-call_to_primop(erlang, 'bnot', 1) -> {yes, ?PRIMOP_BNOT};
-call_to_primop(erlang, 'bsl', 2) -> {yes, ?PRIMOP_BSL};
-call_to_primop(erlang, 'bsr', 2) -> {yes, ?PRIMOP_BSR};
-call_to_primop(erlang, '==', 2) -> {yes, ?PRIMOP_EQ};
-call_to_primop(erlang, '/=', 2) -> {yes, ?PRIMOP_NE};
-call_to_primop(erlang, '=:=', 2) -> {yes, ?PRIMOP_EXACT_EQ};
-call_to_primop(erlang, '=/=', 2) -> {yes, ?PRIMOP_EXACT_NE};
-call_to_primop(erlang, '<', 2) -> {yes, ?PRIMOP_LT};
-call_to_primop(erlang, '>', 2) -> {yes, ?PRIMOP_GT};
-call_to_primop(erlang, '=<', 2) -> {yes, ?PRIMOP_LE};
-call_to_primop(erlang, '>=', 2) -> {yes, ?PRIMOP_GE};
-call_to_primop(erlang, is_atom, 1) -> {yes, ?PRIMOP_IS_ATOM};
-call_to_primop(erlang, is_binary, 1) -> {yes, ?PRIMOP_IS_BINARY};
-call_to_primop(erlang, is_constant, 1) -> {yes, ?PRIMOP_IS_CONSTANT};
-call_to_primop(erlang, is_float, 1) -> {yes, ?PRIMOP_IS_FLOAT};
-call_to_primop(erlang, is_function, 1) -> {yes, ?PRIMOP_IS_FUNCTION};
-call_to_primop(erlang, is_integer, 1) -> {yes, ?PRIMOP_IS_INTEGER};
-call_to_primop(erlang, is_list, 1) -> {yes, ?PRIMOP_IS_LIST};
-call_to_primop(erlang, is_number, 1) -> {yes, ?PRIMOP_IS_NUMBER};
-call_to_primop(erlang, is_pid, 1) -> {yes, ?PRIMOP_IS_PID};
-call_to_primop(erlang, is_port, 1) -> {yes, ?PRIMOP_IS_PORT};
-call_to_primop(erlang, is_reference, 1) -> {yes, ?PRIMOP_IS_REFERENCE};
-call_to_primop(erlang, is_tuple, 1) -> {yes, ?PRIMOP_IS_TUPLE};
-call_to_primop(erlang, internal_is_record, 3) -> {yes, ?PRIMOP_IS_RECORD};
-call_to_primop(erlang, element, 2) -> {yes, ?PRIMOP_ELEMENT};
-call_to_primop(erlang, exit, 1) -> {yes, ?PRIMOP_EXIT};
-call_to_primop(erlang, throw, 1) -> {yes, ?PRIMOP_THROW};
-call_to_primop(erlang, error, 1) -> {yes, ?PRIMOP_ERROR};
-call_to_primop(erlang, error, 2) -> {yes, ?PRIMOP_ERROR};
-call_to_primop(erlang, fault, 1) -> {yes, ?PRIMOP_ERROR};
-call_to_primop(erlang, fault, 2) -> {yes, ?PRIMOP_ERROR};
-call_to_primop(_, _, _) -> no.
-
-%% Also, some primops (introduced by Erlang to Core Erlang translation
-%% and possibly other stages) must be recognized and rewritten.
-
-rewrite_primop(E, N, As, S) ->
- case {cerl:atom_val(N), As} of
- {match_fail, [R]} ->
- M = s__get_module_name(S),
- {F, A} = s__get_function_name(S),
- Stack = cerl:abstract([{M, F, A}]),
- case cerl:type(R) of
- tuple ->
- %% Function clause failures have a special encoding
- %% as '{function_clause, Arg1, ..., ArgN}'.
- case cerl:tuple_es(R) of
- [X | Xs] ->
- case cerl:is_c_atom(X) of
- true ->
- case cerl:atom_val(X) of
- function_clause ->
- FStack = cerl:make_list(
- [cerl:c_tuple(
- [cerl:c_atom(M),
- cerl:c_atom(F),
- cerl:make_list(Xs)])]),
- match_fail(E, X, FStack);
- _ ->
- match_fail(E, R, Stack)
- end;
- false ->
- match_fail(E, R, Stack)
- end;
- _ ->
- match_fail(E, R, Stack)
- end;
- _ ->
- match_fail(E, R, Stack)
- end;
- _ ->
- cerl:update_c_primop(E, N, As)
- end.
-
-match_fail(E, R, Stack) ->
- cerl:update_c_primop(E, cerl:c_atom(?PRIMOP_ERROR), [R, Stack]).
-
-%% Simple let-definitions (of degree 1) in guard context are always
-%% inline expanded. This is allowable, since they cannot have side
-%% effects, and it makes it easy to generate good code for boolean
-%% expressions. It could cause repeated evaluations, but typically,
-%% local definitions within guards are used exactly once.
-
-let_expr(E, Env, Ren, Ctxt, S) ->
- if Ctxt#ctxt.class == guard ->
- case cerl:let_vars(E) of
- [V] ->
- {Name, Ren1} = rename(cerl:var_name(V), Env, Ren),
- Env1 = env__bind(Name, {expr, cerl:let_arg(E)}, Env),
- expr(cerl:let_body(E), Env1, Ren1, Ctxt, S);
- _ ->
- let_expr_1(E, Env, Ren, Ctxt, S)
- end;
- true ->
- let_expr_1(E, Env, Ren, Ctxt, S)
- end.
-
-let_expr_1(E, Env, Ren, Ctxt, S0) ->
- {A, S1} = expr(cerl:let_arg(E), Env, Ren, Ctxt, S0),
- Vs = cerl:let_vars(E),
- {Vs1, Env1, Ren1} = add_vars(Vs, Env, Ren),
- {B, S2} = expr(cerl:let_body(E), Env1, Ren1, Ctxt, S1),
- {cerl:update_c_let(E, Vs1, A, B), S2}.
-
-variable(E, Env, Ren, Ctxt, S) ->
- V = ren__map(cerl:var_name(E), Ren),
- if Ctxt#ctxt.class == guard ->
- case env__lookup(V, Env) of
- {ok, {expr, E1}} ->
- expr(E1, Env, Ren, Ctxt, S); % inline
- _ ->
- %% Since we don't track all bindings when we revisit
- %% guards, some names will not be in the environment.
- variable_1(E, V, S)
- end;
- true ->
- variable_1(E, V, S)
- end.
-
-variable_1(E, V, S) ->
- {cerl:update_c_var(E, V), S}.
-
-%% A catch-expression 'catch Expr' is rewritten as:
-%%
-%% try Expr
-%% of (V) -> V
-%% catch (T, V, E) ->
-%% letrec 'wrap'/1 = fun (V) -> {'EXIT', V}
-%% in case T of
-%% 'throw' when 'true' -> V
-%% 'exit' when 'true' -> 'wrap'/1(V)
-%% V when 'true' ->
-%% 'wrap'/1({V, erlang:get_stacktrace()})
-%% end
-
-catch_expr(E, Env, Ren, Ctxt, S) ->
- T = cerl:c_var('T'),
- V = cerl:c_var('V'),
- X = cerl:c_var('X'),
- W = cerl:c_var({wrap,1}),
- G = cerl:c_call(cerl:c_atom('erlang'),cerl:c_atom('get_stacktrace'),[]),
- Cs = [cerl:c_clause([cerl:c_atom('throw')], V),
- cerl:c_clause([cerl:c_atom('exit')], cerl:c_apply(W, [V])),
- cerl:c_clause([T], cerl:c_apply(W, [cerl:c_tuple([V,G])]))
- ],
- C = cerl:c_case(T, Cs),
- F = cerl:c_fun([V], cerl:c_tuple([cerl:c_atom('EXIT'), V])),
- H = cerl:c_letrec([{W,F}], C),
- As = cerl:get_ann(E),
- {B, S1} = expr(cerl:catch_body(E),Env, Ren, Ctxt, S),
- {cerl:ann_c_try(As, B, [V], V, [T,V,X], H), S1}.
-
-%% Receive-expressions are rewritten as follows:
-%%
-%% receive
-%% P1 when G1 -> B1
-%% ...
-%% Pn when Gn -> Bn
-%% after T -> A end
-%% becomes:
-%% receive
-%% M when 'true' ->
-%% case M of
-%% P1 when G1 -> do primop RECEIVE_SELECT B1
-%% ...
-%% Pn when Gn -> do primop RECEIVE_SELECT Bn
-%% Pn+1 when 'true' -> primop RECEIVE_NEXT()
-%% end
-%% after T -> A end
-
-receive_expr(E, Env, Ren, Ctxt, S0) ->
- Cs = cerl:receive_clauses(E),
- {B, Vs, S1} = clauses(receive_clauses(Cs), Env, Ren, Ctxt, S0),
- {T, S2} = expr(cerl:receive_timeout(E), Env, Ren, Ctxt, S1),
- {A, S3} = expr(cerl:receive_action(E), Env, Ren, Ctxt, S2),
- Cs1 = [cerl:c_clause(Vs, B)],
- {cerl:update_c_receive(E, Cs1, T, A), S3}.
-
-receive_clauses([C | Cs]) ->
- Call = cerl:c_primop(cerl:c_atom(?PRIMOP_RECEIVE_SELECT),
- []),
- B = cerl:c_seq(Call, cerl:clause_body(C)),
- C1 = cerl:update_c_clause(C, cerl:clause_pats(C),
- cerl:clause_guard(C), B),
- [C1 | receive_clauses(Cs)];
-receive_clauses([]) ->
- Call = cerl:c_primop(cerl:c_atom(?PRIMOP_RECEIVE_NEXT),
- []),
- V = cerl:c_var('X'), % any name is ok
- [cerl:c_clause([V], Call)].
-
-
-new_vars(N, Env) ->
- [cerl:c_var(V) || V <- env__new_names(N, Env)].
-
-
-%% ---------------------------------------------------------------------
-%% Environment
-
-env__new() ->
- rec_env:empty().
-
-env__bind(Key, Value, Env) ->
- rec_env:bind(Key, Value, Env).
-
-%% env__get(Key, Env) ->
-%% rec_env:get(Key, Env).
-
-env__lookup(Key, Env) ->
- rec_env:lookup(Key, Env).
-
-env__is_defined(Key, Env) ->
- rec_env:is_defined(Key, Env).
-
-env__new_name(Env) ->
- rec_env:new_key(Env).
-
-env__new_names(N, Env) ->
- rec_env:new_keys(N, Env).
-
-env__new_function_name(F, Env) ->
- rec_env:new_key(F, Env).
-
-
-%% ---------------------------------------------------------------------
-%% Renaming
-
-ren__new() ->
- dict:new().
-
-ren__add(Key, Value, Ren) ->
- dict:store(Key, Value, Ren).
-
-ren__map(Key, Ren) ->
- case dict:find(Key, Ren) of
- {ok, Value} ->
- Value;
- error ->
- Key
- end.
-
-
-%% ---------------------------------------------------------------------
-%% State
-
--record(state, {module, function, pmatch=true}).
-
-s__new(Module) ->
- #state{module = Module}.
-
-s__get_module_name(S) ->
- S#state.module.
-
-s__enter_function(F, S) ->
- S#state{function = F}.
-
-s__get_function_name(S) ->
- S#state.function.
-
-s__set_pmatch(V, S) ->
- S#state{pmatch = V}.
-
-s__get_pmatch(S) ->
- S#state.pmatch.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_acceptor.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_acceptor.erl
deleted file mode 100644
index 2aef625dc6..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_acceptor.erl
+++ /dev/null
@@ -1,120 +0,0 @@
-% Copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
-%
-% Licensed under the Apache License, Version 2.0 (the "License");
-% you may not use this file except in compliance with the License.
-% You may obtain a copy of the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS,
-% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-% See the License for the specific language governing permissions and
-% limitations under the License.
-%%%-------------------------------------------------------------------
-%%% File : comm_acceptor.erl
-%%% Author : Thorsten Schuett <[email protected]>
-%%% Description : Acceptor
-%%% This module accepts new connections and starts corresponding
-%%% comm_connection processes.
-%%%
-%%% Created : 18 Apr 2008 by Thorsten Schuett <[email protected]>
-%%%-------------------------------------------------------------------
-%% @author Thorsten Schuett <[email protected]>
-%% @copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
-%% @version $Id $
--module(comm_layer_dir.comm_acceptor).
-
--export([start_link/1, init/2]).
-
--import(config).
--import(gen_tcp).
--import(inet).
--import(log).
--import(lists).
--import(process_dictionary).
-
-start_link(InstanceId) ->
- Pid = spawn_link(comm_layer_dir.comm_acceptor, init, [InstanceId, self()]),
- receive
- {started} ->
- {ok, Pid}
- end.
-
-init(InstanceId, Supervisor) ->
- process_dictionary:register_process(InstanceId, acceptor, self()),
- erlang:register(comm_layer_acceptor, self()),
- log:log(info,"[ CC ] listening on ~p:~p", [config:listenIP(), config:listenPort()]),
- LS = case config:listenIP() of
- undefined ->
- open_listen_port(config:listenPort(), first_ip());
- _ ->
- open_listen_port(config:listenPort(), config:listenIP())
- end,
- {ok, {_LocalAddress, LocalPort}} = inet:sockname(LS),
- comm_port:set_local_address(undefined, LocalPort),
- %io:format("this() == ~w~n", [{LocalAddress, LocalPort}]),
- Supervisor ! {started},
- server(LS).
-
-server(LS) ->
- case gen_tcp:accept(LS) of
- {ok, S} ->
- case comm_port:get_local_address_port() of
- {undefined, LocalPort} ->
- {ok, {MyIP, _LocalPort}} = inet:sockname(S),
- comm_port:set_local_address(MyIP, LocalPort);
- _ ->
- ok
- end,
- receive
- {tcp, S, Msg} ->
- {endpoint, Address, Port} = binary_to_term(Msg),
- % auto determine remote address, when not sent correctly
- NewAddress = if Address =:= {0,0,0,0} orelse Address =:= {127,0,0,1} ->
- case inet:peername(S) of
- {ok, {PeerAddress, _Port}} ->
- % io:format("Sent Address ~p\n",[Address]),
- % io:format("Peername is ~p\n",[PeerAddress]),
- PeerAddress;
- {error, _Why} ->
- % io:format("Peername error ~p\n",[Why]).
- Address
- end;
- true ->
- % io:format("Address is ~p\n",[Address]),
- Address
- end,
- NewPid = comm_connection:new(NewAddress, Port, S),
- gen_tcp:controlling_process(S, NewPid),
- inet:setopts(S, [{active, once}, {send_timeout, config:read(tcp_send_timeout)}]),
- comm_port:register_connection(NewAddress, Port, NewPid, S)
- end,
- server(LS);
- Other ->
- log:log(warn,"[ CC ] unknown message ~p", [Other])
- end.
-
-open_listen_port({From, To}, IP) ->
- open_listen_port(lists:seq(From, To), IP);
-open_listen_port([Port | Rest], IP) ->
- case gen_tcp:listen(Port, [binary, {packet, 4}, {reuseaddr, true},
- {active, once}, {ip, IP}]) of
- {ok, Socket} ->
- Socket;
- {error, Reason} ->
- log:log(error,"[ CC ] can't listen on ~p: ~p~n", [Port, Reason]),
- open_listen_port(Rest, IP)
- end;
-open_listen_port([], _) ->
- abort;
-open_listen_port(Port, IP) ->
- open_listen_port([Port], IP).
-
--include_lib("kernel/include/inet.hrl").
-
-first_ip() ->
- {ok, Hostname} = inet:gethostname(),
- {ok, HostEntry} = inet:gethostbyname(Hostname),
- erlang:hd(HostEntry#hostent.h_addr_list).
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_connection.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_connection.erl
deleted file mode 100644
index 8dca647f6d..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_connection.erl
+++ /dev/null
@@ -1,206 +0,0 @@
-% Copyright 2008 Konrad-Zuse-Zentrum f�r Informationstechnik Berlin
-%
-% Licensed under the Apache License, Version 2.0 (the "License");
-% you may not use this file except in compliance with the License.
-% You may obtain a copy of the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS,
-% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-% See the License for the specific language governing permissions and
-% limitations under the License.
-%%%-------------------------------------------------------------------
-%%% File : comm_connection.erl
-%%% Author : Thorsten Schuett <[email protected]>
-%%% Description : creates and destroys connections and represents the
-%%% endpoint of a connection where messages are received and
-%% send from/to the network.
-%%%
-%%% Created : 18 Apr 2008 by Thorsten Schuett <[email protected]>
-%%%-------------------------------------------------------------------
-%% @author Thorsten Schuett <[email protected]>
-%% @copyright 2008 Konrad-Zuse-Zentrum f�r Informationstechnik Berlin
-%% @version $Id $
--module(comm_layer_dir.comm_connection).
-
--export([send/3, open_new/4, new/3, open_new_async/4]).
-
--import(config).
--import(gen_tcp).
--import(inet).
--import(io).
--import(io_lib).
--import(log).
--import(timer).
-
--include("comm_layer.hrl").
-
-%% @doc new accepted connection. called by comm_acceptor
-%% @spec new(inet:ip_address(), int(), socket()) -> pid()
-new(Address, Port, Socket) ->
- spawn(fun () -> loop(Socket, Address, Port) end).
-
-%% @doc open new connection
-%% @spec open_new(inet:ip_address(), int(), inet:ip_address(), int()) ->
-%% {local_ip, inet:ip_address(), int(), pid(), inet:socket()}
-%% | fail
-%% | {connection, pid(), inet:socket()}
-open_new(Address, Port, undefined, MyPort) ->
- Myself = self(),
- LocalPid = spawn(fun () ->
- case new_connection(Address, Port, MyPort) of
- fail ->
- Myself ! {new_connection_failed};
- Socket ->
- {ok, {MyIP, _MyPort}} = inet:sockname(Socket),
- Myself ! {new_connection_started, MyIP, MyPort, Socket},
- loop(Socket, Address, Port)
- end
- end),
- receive
- {new_connection_failed} ->
- fail;
- {new_connection_started, MyIP, MyPort, S} ->
- {local_ip, MyIP, MyPort, LocalPid, S}
- end;
-open_new(Address, Port, _MyAddress, MyPort) ->
- Owner = self(),
- LocalPid = spawn(fun () ->
- case new_connection(Address, Port, MyPort) of
- fail ->
- Owner ! {new_connection_failed};
- Socket ->
- Owner ! {new_connection_started, Socket},
- loop(Socket, Address, Port)
- end
- end),
- receive
- {new_connection_failed} ->
- fail;
- {new_connection_started, Socket} ->
- {connection, LocalPid, Socket}
- end.
-
-% ===============================================================================
-% @doc open a new connection asynchronously
-% ===============================================================================
--spec(open_new_async/4 :: (any(), any(), any(), any()) -> pid()).
-open_new_async(Address, Port, _MyAddr, MyPort) ->
- Pid = spawn(fun () ->
- case new_connection(Address, Port, MyPort) of
- fail ->
- comm_port:unregister_connection(Address, Port),
- ok;
- Socket ->
- loop(Socket, Address, Port)
- end
- end),
- Pid.
-
-
-send({Address, Port, Socket}, Pid, Message) ->
- BinaryMessage = term_to_binary({deliver, Pid, Message}),
- SendTimeout = config:read(tcp_send_timeout),
- {Time, Result} = timer:tc(gen_tcp, send, [Socket, BinaryMessage]),
- if
- Time > 1200 * SendTimeout ->
- log:log(error,"[ CC ] send to ~p took ~p: ~p",
- [Address, Time, inet:getopts(Socket, [keep_alive, send_timeout])]);
- true ->
- ok
- end,
- case Result of
- ok ->
- ?LOG_MESSAGE(erlang:element(1, Message), byte_size(BinaryMessage)),
- ok;
- {error, closed} ->
- comm_port:unregister_connection(Address, Port),
- close_connection(Socket);
- {error, _Reason} ->
- %log:log(error,"[ CC ] couldn't send to ~p:~p (~p)", [Address, Port, Reason]),
- comm_port:unregister_connection(Address, Port),
- close_connection(Socket)
- end.
-
-loop(fail, Address, Port) ->
- comm_port:unregister_connection(Address, Port),
- ok;
-loop(Socket, Address, Port) ->
- receive
- {send, Pid, Message} ->
- case send({Address, Port, Socket}, Pid, Message) of
- ok -> loop(Socket, Address, Port);
- _ -> ok
- end;
- {tcp_closed, Socket} ->
- comm_port:unregister_connection(Address, Port),
- gen_tcp:close(Socket);
- {tcp, Socket, Data} ->
- case binary_to_term(Data) of
- {deliver, Process, Message} ->
- Process ! Message,
- inet:setopts(Socket, [{active, once}]),
- loop(Socket, Address, Port);
- {user_close} ->
- comm_port:unregister_connection(Address, Port),
- gen_tcp:close(Socket);
- {youare, _Address, _Port} ->
- %% @TODO what do we get from this information?
- inet:setopts(Socket, [{active, once}]),
- loop(Socket, Address, Port);
- Unknown ->
- log:log(warn,"[ CC ] unknown message ~p", [Unknown]),
- inet:setopts(Socket, [{active, once}]),
- loop(Socket, Address, Port)
- end;
-
- {youare, _IP, _Port} ->
- loop(Socket, Address, Port);
-
- Unknown ->
- log:log(warn,"[ CC ] unknown message2 ~p", [Unknown]) ,
- loop(Socket, Address, Port)
- end.
-
-% ===============================================================================
-
--spec(new_connection(inet:ip_address(), integer(), integer()) -> inet:socket() | fail).
-new_connection(Address, Port, MyPort) ->
- case gen_tcp:connect(Address, Port, [binary, {packet, 4}, {nodelay, true}, {active, once},
- {send_timeout, config:read(tcp_send_timeout)}],
- config:read(tcp_connect_timeout)) of
- {ok, Socket} ->
- % send end point data
- case inet:sockname(Socket) of
- {ok, {MyAddress, _MyPort}} ->
- Message = term_to_binary({endpoint, MyAddress, MyPort}),
- gen_tcp:send(Socket, Message),
- case inet:peername(Socket) of
- {ok, {RemoteIP, RemotePort}} ->
- YouAre = term_to_binary({youare, RemoteIP, RemotePort}),
- gen_tcp:send(Socket, YouAre),
- Socket;
- {error, _Reason} ->
- %log:log(error,"[ CC ] reconnect to ~p because socket is ~p",
- % [Address, Reason]),
- close_connection(Socket),
- new_connection(Address, Port, MyPort)
- end;
- {error, _Reason} ->
- %log:log(error,"[ CC ] reconnect to ~p because socket is ~p",
- % [Address, Reason]),
- close_connection(Socket),
- new_connection(Address, Port, MyPort)
- end;
- {error, _Reason} ->
- %log:log(error,"[ CC ] couldn't connect to ~p:~p (~p)",
- %[Address, Port, Reason]),
- fail
- end.
-
-close_connection(Socket) ->
- spawn( fun () ->
- gen_tcp:close(Socket)
- end ).
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_layer.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_layer.erl
deleted file mode 100644
index f48324e49c..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_layer.erl
+++ /dev/null
@@ -1,83 +0,0 @@
-% Copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
-%
-% Licensed under the Apache License, Version 2.0 (the "License");
-% you may not use this file except in compliance with the License.
-% You may obtain a copy of the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS,
-% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-% See the License for the specific language governing permissions and
-% limitations under the License.
-%%%-------------------------------------------------------------------
-%%% File : comm_layer.erl
-%%% Author : Thorsten Schuett <[email protected]>
-%%% Description : Public interface to Communication Layer.
-%%% Generic functions to send messages.
-%%% Distinguishes on runtime whether the destination is in the
-%%% same Erlang virtual machine (use ! for sending) or on a remote
-%%% site (use comm_port:send()).
-%%%
-%%% Created : 04 Feb 2008 by Thorsten Schuett <[email protected]>
-%%%-------------------------------------------------------------------
-%% @author Thorsten Schuett <[email protected]>
-%% @copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
-%% @version $Id $
--module(comm_layer_dir.comm_layer).
-
--author('[email protected]').
--vsn('$Id: comm_layer.erl,v 1.1 2009/11/06 12:41:36 maria Exp $ ').
-
--export([start_link/0, send/2, this/0, here/1]).
-
--import(io).
--import(util).
--import(log).
-
--include("comm_layer.hrl").
-
-
-% @TODO: should be ip
--type(process_id() :: {any(), integer(), pid()}).
-%%====================================================================
-%% public functions
-%%====================================================================
-
-%% @doc starts the communication port (for supervisor)
-%% @spec start_link() -> {ok,Pid} | ignore | {error,Error}
-start_link() ->
- comm_port_sup:start_link().
-
-%% @doc a process descriptor has to specify the erlang vm
-%% + the process inside. {IP address, port, pid}
-%% @type process_id() = {inet:ip_address(), int(), pid()}.
-%% @spec send(process_id(), term()) -> ok
-
-send({{_IP1, _IP2, _IP3, _IP4} = _IP, _Port, _Pid} = Target, Message) ->
- {MyIP,MyPort} = comm_port:get_local_address_port(),
- %io:format("send: ~p:~p -> ~p:~p(~p) : ~p\n", [MyIP, MyPort, _IP, _Port, _Pid, Message]),
- IsLocal = (MyIP == _IP) and (MyPort == _Port),
- if
- IsLocal ->
- ?LOG_MESSAGE(erlang:element(1, Message), byte_size(term_to_binary(Message))),
- _Pid ! Message;
- true ->
- comm_port:send(Target, Message)
- end;
-
-send(Target, Message) ->
- log:log(error,"[ CC ] wrong call to cs_send:send: ~w ! ~w", [Target, Message]),
- log:log(error,"[ CC ] stacktrace: ~w", [util:get_stacktrace()]),
- ok.
-
-%% @doc returns process descriptor for the calling process
--spec(this/0 :: () -> atom()).%process_id()).
-this() ->
- here(self()).
-
--spec(here/1 :: (pid()) -> process_id()).
-here(Pid) ->
- {LocalIP, LocalPort} = comm_port:get_local_address_port(),
- {LocalIP, LocalPort, Pid}.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_layer.hrl b/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_layer.hrl
deleted file mode 100644
index f4e4d560f7..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_layer.hrl
+++ /dev/null
@@ -1,30 +0,0 @@
-% Copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
-%
-% Licensed under the Apache License, Version 2.0 (the "License");
-% you may not use this file except in compliance with the License.
-% You may obtain a copy of the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS,
-% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-% See the License for the specific language governing permissions and
-% limitations under the License.
-%%%-------------------------------------------------------------------
-%%% File : comm_layer.hrl
-%%% Author : Thorsten Schuett <[email protected]>
-%%% Description :
-%%%
-%%% Created : 31 Jul 2008 by Thorsten Schuett <[email protected]>
-%%%-------------------------------------------------------------------
-%% @author Thorsten Schuett <[email protected]>
-%% @copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
-%% @version $Id: comm_layer.hrl,v 1.1 2009/11/06 12:41:36 maria Exp $
--author('[email protected]').
--vsn('$Id: comm_layer.hrl,v 1.1 2009/11/06 12:41:36 maria Exp $ ').
-
-% enable logging of message statistics
-%-define(LOG_MESSAGE(TAG, SIZE), comm_layer.comm_logger:log(TAG, SIZE)).
--define(LOG_MESSAGE(TAG, SIZE), ok).
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_logger.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_logger.erl
deleted file mode 100644
index c70b0d3438..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_logger.erl
+++ /dev/null
@@ -1,143 +0,0 @@
-% Copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
-%
-% Licensed under the Apache License, Version 2.0 (the "License");
-% you may not use this file except in compliance with the License.
-% You may obtain a copy of the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS,
-% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-% See the License for the specific language governing permissions and
-% limitations under the License.
-%%%-------------------------------------------------------------------
-%%% File : comm_logger.erl
-%%% Author : Thorsten Schuett <[email protected]>
-%%% Description :
-%%%
-%%% Created : 31 Jul 2008 by Thorsten Schuett <[email protected]>
-%%%-------------------------------------------------------------------
-%% @author Thorsten Schuett <[email protected]>
-%% @copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
-%% @version $Id: comm_logger.erl,v 1.1 2009/11/06 12:41:36 maria Exp $
--module(comm_layer_dir.comm_logger).
-
--author('[email protected]').
--vsn('$Id: comm_logger.erl,v 1.1 2009/11/06 12:41:36 maria Exp $ ').
-
--behaviour(gen_server).
-
--import(gb_trees).
--import(gen_server).
-
-%% API
--export([start_link/0]).
-
--export([log/2, dump/0]).
-
-%% gen_server callbacks
--export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- terminate/2, code_change/3]).
-
--record(state, {start, map}).
-
-%%====================================================================
-%% API
-%%====================================================================
-%%--------------------------------------------------------------------
-%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
-%% Description: Starts the server
-%%--------------------------------------------------------------------
-start_link() ->
- gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
-
-%%--------------------------------------------------------------------
-%% Function: log(Tag, Size) -> ok
-%% Description: logs a message type with its size
-%%--------------------------------------------------------------------
-log(Tag, Size) ->
- gen_server:cast(?MODULE, {log, Tag, Size}).
-
-%%--------------------------------------------------------------------
-%% Function: dump() -> {gb_tree:gb_trees(), {Date, Time}}
-%% Description: gets the logging state
-%%--------------------------------------------------------------------
-dump() ->
- gen_server:call(?MODULE, {dump}).
-
-%%====================================================================
-%% gen_server callbacks
-%%====================================================================
-
-%%--------------------------------------------------------------------
-%% Function: init(Args) -> {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%--------------------------------------------------------------------
-init([]) ->
- {ok, #state{start=erlang:now(), map=gb_trees:empty()}}.
-
-%%--------------------------------------------------------------------
-%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
-%% {reply, Reply, State, Timeout} |
-%% {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, Reply, State} |
-%% {stop, Reason, State}
-%% Description: Handling call messages
-%%--------------------------------------------------------------------
-handle_call({dump}, _From, State) ->
- Reply = {State#state.map, State#state.start},
- {reply, Reply, State};
-handle_call(_Request, _From, State) ->
- Reply = ok,
- {reply, Reply, State}.
-
-%%--------------------------------------------------------------------
-%% Function: handle_cast(Msg, State) -> {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State}
-%% Description: Handling cast messages
-%%--------------------------------------------------------------------
-handle_cast({log, Tag, Size}, State) ->
- case gb_trees:lookup(Tag, State#state.map) of
- none ->
- {noreply, State#state{map=gb_trees:insert(Tag, {Size, 1}, State#state.map)}};
- {value, {OldSize, OldCount}} ->
- {noreply, State#state{map=gb_trees:update(Tag, {Size + OldSize, OldCount + 1}, State#state.map)}}
- end;
-handle_cast(_Msg, State) ->
- {noreply, State}.
-
-%%--------------------------------------------------------------------
-%% Function: handle_info(Info, State) -> {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State}
-%% Description: Handling all non call/cast messages
-%%--------------------------------------------------------------------
-handle_info(_Info, State) ->
- {noreply, State}.
-
-%%--------------------------------------------------------------------
-%% Function: terminate(Reason, State) -> void()
-%% Description: This function is called by a gen_server when it is about to
-%% terminate. It should be the opposite of Module:init/1 and do any necessary
-%% cleaning up. When it returns, the gen_server terminates with Reason.
-%% The return value is ignored.
-%%--------------------------------------------------------------------
-terminate(_Reason, _State) ->
- ok.
-
-%%--------------------------------------------------------------------
-%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
-%% Description: Convert process state when code is changed
-%%--------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%--------------------------------------------------------------------
-%%% Internal functions
-%%--------------------------------------------------------------------
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_port.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_port.erl
deleted file mode 100644
index 5eded48750..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_port.erl
+++ /dev/null
@@ -1,240 +0,0 @@
-% Copyright 2008 Konrad-Zuse-Zentrum f�r Informationstechnik Berlin
-%
-% Licensed under the Apache License, Version 2.0 (the "License");
-% you may not use this file except in compliance with the License.
-% You may obtain a copy of the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS,
-% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-% See the License for the specific language governing permissions and
-% limitations under the License.
-%%%-------------------------------------------------------------------
-%%% File : comm_port.erl
-%%% Author : Thorsten Schuett <[email protected]>
-%%% Description : Main CommLayer Interface
-%%% Maps remote addresses to comm_connection PIDs.
-%%%
-%%% Created : 18 Apr 2008 by Thorsten Schuett <[email protected]>
-%%%-------------------------------------------------------------------
-%% @author Thorsten Schuett <[email protected]>
-%% @copyright 2008 Konrad-Zuse-Zentrum f�r Informationstechnik Berlin
-%% @version $Id $
--module(comm_layer_dir.comm_port).
-
--author('[email protected]').
--vsn('$Id: comm_port.erl,v 1.1 2009/11/06 12:41:36 maria Exp $ ').
-
--behaviour(gen_server).
-
--import(ets).
--import(gen_server).
--import(io).
--import(log).
-
--define(ASYNC, true).
-%-define(SYNC, true).
-
-%% API
--export([start_link/0,
- send/2,
- unregister_connection/2, register_connection/4,
- set_local_address/2, get_local_address_port/0]).
-
-%% gen_server callbacks
--export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- terminate/2, code_change/3]).
-
-%%====================================================================
-%% API
-%%====================================================================
-
-%% @doc
-%% @spec send({inet:ip_address(), int(), pid()}, term()) -> ok
--ifdef(ASYNC).
-send({Address, Port, Pid}, Message) ->
- gen_server:call(?MODULE, {send, Address, Port, Pid, Message}, 20000).
--endif.
--ifdef(SYNC).
-send({Address, Port, Pid}, Message) ->
- case ets:lookup(?MODULE, {Address, Port}) of
- [{{Address, Port}, {_LPid, Socket}}] ->
- comm_connection:send({Address, Port, Socket}, Pid, Message),
- ok;
- [] ->
- gen_server:call(?MODULE, {send, Address, Port, Pid, Message}, 20000)
- end.
--endif.
-
-
-%% @doc
-%% @spec unregister_connection(inet:ip_address(), int()) -> ok
-unregister_connection(Adress, Port) ->
- gen_server:call(?MODULE, {unregister_conn, Adress, Port}, 20000).
-
-%% @doc
-%% @spec register_connection(inet:ip_address(), int(), pid(), gen_tcp:socket()) -> ok | duplicate
-register_connection(Adress, Port, Pid, Socket) ->
- gen_server:call(?MODULE, {register_conn, Adress, Port, Pid, Socket}, 20000).
-
-%% @doc
-%% @spec set_local_address(inet:ip_address(), int()) -> ok
-set_local_address(Address, Port) ->
- gen_server:call(?MODULE, {set_local_address, Address, Port}, 20000).
-
-
-%% @doc
-%% @spec get_local_address_port() -> {inet:ip_address(),int()}
-get_local_address_port() ->
- case ets:lookup(?MODULE, local_address_port) of
- [{local_address_port, Value}] ->
- Value;
- [] ->
- undefined
- end.
-
-%%--------------------------------------------------------------------
-%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
-%% Description: Starts the server
-%%--------------------------------------------------------------------
-start_link() ->
- gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
-
-%%====================================================================
-%% gen_server callbacks
-%%====================================================================
-
-%%--------------------------------------------------------------------
-%% Function: init(Args) -> {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%--------------------------------------------------------------------
-init([]) ->
- ets:new(?MODULE, [set, protected, named_table]),
- {ok, ok}. % empty state.
-
-%%--------------------------------------------------------------------
-%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
-%% {reply, Reply, State, Timeout} |
-%% {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, Reply, State} |
-%% {stop, Reason, State}
-%% Description: Handling call messages
-%%--------------------------------------------------------------------
-handle_call({send, Address, Port, Pid, Message}, _From, State) ->
- send(Address, Port, Pid, Message, State);
-
-handle_call({unregister_conn, Address, Port}, _From, State) ->
- ets:delete(?MODULE, {Address, Port}),
- {reply, ok, State};
-
-handle_call({register_conn, Address, Port, Pid, Socket}, _From, State) ->
- case ets:lookup(?MODULE, {Address, Port}) of
- [{{Address, Port}, _}] ->
- {reply, duplicate, State};
- [] ->
- ets:insert(?MODULE, {{Address, Port}, {Pid, Socket}}),
- {reply, ok, State}
- end;
-
-handle_call({set_local_address, Address, Port}, _From, State) ->
- ets:insert(?MODULE, {local_address_port, {Address,Port}}),
- {reply, ok, State}.
-
-%%--------------------------------------------------------------------
-%% Function: handle_cast(Msg, State) -> {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State}
-%% Description: Handling cast messages
-%%--------------------------------------------------------------------
-handle_cast(_Msg, State) ->
- {noreply, State}.
-
-%%--------------------------------------------------------------------
-%% Function: handle_info(Info, State) -> {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State}
-%% Description: Handling all non call/cast messages
-%%--------------------------------------------------------------------
-handle_info(_Info, State) ->
- {noreply, State}.
-
-%%--------------------------------------------------------------------
-%% Function: terminate(Reason, State) -> void()
-%% Description: This function is called by a gen_server when it is about to
-%% terminate. It should be the opposite of Module:init/1 and do any necessary
-%% cleaning up. When it returns, the gen_server terminates with Reason.
-%% The return value is ignored.
-%%--------------------------------------------------------------------
-terminate(_Reason, _State) ->
- ok.
-
-%%--------------------------------------------------------------------
-%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
-%% Description: Convert process state when code is changed
-%%--------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%--------------------------------------------------------------------
-%%% Internal functions
-%%--------------------------------------------------------------------
-
--ifdef(ASYNC).
-send(Address, Port, Pid, Message, State) ->
- {DepAddr,DepPort} = get_local_address_port(),
- if
- DepAddr == undefined ->
- open_sync_connection(Address, Port, Pid, Message, State);
- true ->
- case ets:lookup(?MODULE, {Address, Port}) of
- [{{Address, Port}, {ConnPid, _Socket}}] ->
- ConnPid ! {send, Pid, Message},
- {reply, ok, State};
- [] ->
- ConnPid = comm_connection:open_new_async(Address, Port,
- DepAddr, DepPort),
- ets:insert(?MODULE, {{Address, Port}, {ConnPid, undef}}),
- ConnPid ! {send, Pid, Message},
- {reply, ok, State}
- end
- end.
--endif.
-
--ifdef(SYNC).
-send(Address, Port, Pid, Message, State) ->
- case ets:lookup(?MODULE, {Address, Port}) of
- [{{Address, Port}, {_LPid, Socket}}] ->
- comm_connection:send({Address, Port, Socket}, Pid, Message),
- {reply, ok, State};
- [] ->
- open_sync_connection(Address, Port, Pid, Message, State)
- end.
--endif.
-
-
-open_sync_connection(Address, Port, Pid, Message, State) ->
- {DepAddr,DepPort} = get_local_address_port(),
- case comm_connection:open_new(Address, Port, DepAddr, DepPort) of
- {local_ip, MyIP, MyPort, MyPid, MySocket} ->
- comm_connection:send({Address, Port, MySocket}, Pid, Message),
- log:log(info,"[ CC ] this() == ~w", [{MyIP, MyPort}]),
- % set_local_address(t, {MyIP,MyPort}}),
- % register_connection(Address, Port, MyPid, MySocket),
- ets:insert(?MODULE, {local_address_port, {MyIP,MyPort}}),
- ets:insert(?MODULE, {{Address, Port}, {MyPid, MySocket}}),
- {reply, ok, State};
- fail ->
- % drop message (remote node not reachable, failure detector will notice)
- {reply, ok, State};
- {connection, LocalPid, NewSocket} ->
- comm_connection:send({Address, Port, NewSocket}, Pid, Message),
- ets:insert(?MODULE, {{Address, Port}, {LocalPid, NewSocket}}),
- % register_connection(Address, Port, LPid, NewSocket),
- {reply, ok, State}
- end.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_port_sup.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_port_sup.erl
deleted file mode 100644
index 622d0a8c06..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/comm_layer/comm_port_sup.erl
+++ /dev/null
@@ -1,90 +0,0 @@
-% Copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
-%
-% Licensed under the Apache License, Version 2.0 (the "License");
-% you may not use this file except in compliance with the License.
-% You may obtain a copy of the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS,
-% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-% See the License for the specific language governing permissions and
-% limitations under the License.
-%%%-------------------------------------------------------------------
-%%% File : comm_port_sup.erl
-%%% Author : Thorsten Schuett <[email protected]>
-%%% Description :
-%%%
-%%% Created : 04 Feb 2008 by Thorsten Schuett <[email protected]>
-%%%-------------------------------------------------------------------
-%% @author Thorsten Schuett <[email protected]>
-%% @copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
-%% @version $Id: comm_port_sup.erl,v 1.1 2009/11/06 12:41:36 maria Exp $
--module(comm_layer_dir.comm_port_sup).
-
--author('[email protected]').
--vsn('$Id: comm_port_sup.erl,v 1.1 2009/11/06 12:41:36 maria Exp $ ').
-
--behaviour(supervisor).
-
--import(supervisor).
--import(randoms).
--import(string).
--import(config).
-
--export([start_link/0, init/1]).
-
-%%====================================================================
-%% API functions
-%%====================================================================
-%%--------------------------------------------------------------------
-%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
-%% Description: Starts the supervisor
-%%--------------------------------------------------------------------
-start_link() ->
- supervisor:start_link(?MODULE, []).
-
-%%====================================================================
-%% Supervisor callbacks
-%%====================================================================
-%%--------------------------------------------------------------------
-%% Func: init(Args) -> {ok, {SupFlags, [ChildSpec]}} |
-%% ignore |
-%% {error, Reason}
-%% Description: Whenever a supervisor is started using
-%% supervisor:start_link/[2,3], this function is called by the new process
-%% to find out about restart strategy, maximum restart frequency and child
-%% specifications.
-%%--------------------------------------------------------------------
-init([]) ->
- InstanceId = string:concat("comm_port_", randoms:getRandomId()),
- CommPort =
- {comm_port,
- {comm_layer_dir.comm_port, start_link, []},
- permanent,
- brutal_kill,
- worker,
- []},
- CommAcceptor =
- {comm_acceptor,
- {comm_layer_dir.comm_acceptor, start_link, [InstanceId]},
- permanent,
- brutal_kill,
- worker,
- []},
- CommLogger =
- {comm_logger,
- {comm_layer_dir.comm_logger, start_link, []},
- permanent,
- brutal_kill,
- worker,
- []},
- {ok, {{one_for_all, 10, 1},
- [
- CommPort,
- CommLogger,
- CommAcceptor
- ]}}.
-
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/compare1.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/compare1.erl
deleted file mode 100644
index 2626d2ebea..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/compare1.erl
+++ /dev/null
@@ -1,21 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : compare1.erl
-%%% Author : Tobias Lindahl <[email protected]>
-%%% Description :
-%%%
-%%% Created : 20 Apr 2007 by Tobias Lindahl <[email protected]>
-%%%-------------------------------------------------------------------
--module(compare1).
-
--export([t/0]).
-
-t() ->
- t(42).
-
-t(X) when X > 42 ->
- error;
-t(X) when X < 42 ->
- error;
-t(X) when X =/= 42 ->
- error;
-t(X) -> ok.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/contract2.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/contract2.erl
deleted file mode 100644
index 83ee5910f2..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/contract2.erl
+++ /dev/null
@@ -1,18 +0,0 @@
--module(contract2).
--export([test/2]).
-
--spec test(list(), list()) -> ok.
-
-test([], []) ->
- ok;
-test([], L) ->
- raise(L);
-test([H|T], L) ->
- case H of
- true -> test(T, L);
- false -> test(T, [H|L])
- end.
-
--spec raise(_) -> no_return().
-raise(X) ->
- throw(X).
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/contract3.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/contract3.erl
deleted file mode 100644
index c135b72d45..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/contract3.erl
+++ /dev/null
@@ -1,34 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : contract3.erl
-%%% Author : Tobias Lindahl <[email protected]>
-%%% Description : Check overloaded domains
-%%%
-%%% Created : 2 Nov 2007 by Tobias Lindahl <[email protected]>
-%%%-------------------------------------------------------------------
--module(contract3).
-
--export([t/3]).
-
-t(X, Y, Z) ->
- t1(X),
- t2(X, Y),
- t3(X, Y, Z).
-
--spec t1(atom()|integer()) -> integer();
- (atom()|list()) -> atom().
-
-t1(X) ->
- foo:bar(X).
-
--spec t2(atom(), integer()) -> integer();
- (atom(), list()) -> atom().
-
-t2(X, Y) ->
- foo:bar(X, Y).
-
--spec t3(atom(), integer(), list()) -> integer();
- (X, integer(), list()) -> X.
-
-t3(X, Y, Z) ->
- X.
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/contract5.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/contract5.erl
deleted file mode 100644
index 6385473c20..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/contract5.erl
+++ /dev/null
@@ -1,15 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : contract5.erl
-%%% Author : Tobias Lindahl <[email protected]>
-%%% Description : Excercise modified record types.
-%%%
-%%% Created : 15 Apr 2008 by Tobias Lindahl <[email protected]>
-%%%-------------------------------------------------------------------
--module(contract5).
--export([t/0]).
-
--record(bar, {baz}).
-
--spec t() -> #bar{baz :: boolean()}.
-
-t() -> #bar{baz = not_a_boolean}.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/disj_norm_form.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/disj_norm_form.erl
deleted file mode 100644
index 313c2e8b86..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/disj_norm_form.erl
+++ /dev/null
@@ -1,23 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : disj_norm_form.erl
-%%% Author : Tobias Lindahl <[email protected]>
-%%% Description : Exposes a bad behavior in expansion to
-%%% disjunctive normal form of guards.
-%%%
-%%% Created : 24 Aug 2007 by Tobias Lindahl <[email protected]>
-%%%-------------------------------------------------------------------
--module(disj_norm_form).
-
--export([t/1]).
-
--record(foo, {bar}).
-
-t(R) ->
- if R#foo.bar =:= 1;
- R#foo.bar =:= 2;
- R#foo.bar =:= 3;
- R#foo.bar =:= 4;
- R#foo.bar =:= 5;
- R#foo.bar =:= 6 -> ok;
- true -> error
- end.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/eqeq.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/eqeq.erl
deleted file mode 100644
index 6767023e3a..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/eqeq.erl
+++ /dev/null
@@ -1,16 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : eqeq.erl
-%%% Author : Tobias Lindahl <[email protected]>
-%%% Description :
-%%%
-%%% Created : 12 Nov 2007 by Tobias Lindahl <[email protected]>
-%%%-------------------------------------------------------------------
--module(eqeq).
-
--export([t/0]).
-
-t() ->
- comp(3.14, foo).
-
-comp(X, Y) -> X =:= Y.
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/ets_select.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/ets_select.erl
deleted file mode 100644
index 2b3c38cd59..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/ets_select.erl
+++ /dev/null
@@ -1,12 +0,0 @@
--module(ets_select).
--export([test/0]).
-
-test() ->
- Table = ets:new(table, [set,{keypos,1}]),
- ets:insert(Table, {foo, bar, baz}),
- foo(Table). % ets:select(Table, [{{'_', '$1', '$2'}, [], ['$$']}]).
-
-foo(Table) ->
- Tuples = ets:select(Table, [{{'_', '$1', '$2'}, [], ['$$']}]),
- [list_to_tuple(Tuple) || Tuple <- Tuples].
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/exhaust_case.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/exhaust_case.erl
deleted file mode 100644
index 6b20c7c98c..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/exhaust_case.erl
+++ /dev/null
@@ -1,24 +0,0 @@
-%%-------------------------------------------------------------------
-%% File : exhaust_case.erl
-%% Author : Kostis Sagonas <[email protected]>
-%% Description : Tests that Dialyzer warns when it finds an unreachable
-%% case clause (independently of whether ground vs. var).
-%%
-%% Created : 15 Dec 2004 by Kostis Sagonas <[email protected]>
-%%-------------------------------------------------------------------
-
--module(exhaust_case).
--export([t/1]).
-
-t(X) when is_integer(X) ->
- case ret(X) of
- foo -> ok;
- bar -> ok;
- 42 -> ok;
- _other -> error %% unreachable clause (currently no warning)
- %% other -> error %% but contrast this with this clause... hmm
- end.
-
-ret(1) -> foo;
-ret(2) -> bar.
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/failing_guard1.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/failing_guard1.erl
deleted file mode 100644
index 8fa1ce9ce0..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/failing_guard1.erl
+++ /dev/null
@@ -1,16 +0,0 @@
-%%-----------------------------------------------------------------------
-%% Author: Kostis Sagonas (Wed Aug 23 14:54:25 CEST 2006)
-%%
-%% Program to test failing arithmetic comparisons with a number of the
-%% wrong type. The first case is handled properly; the second one is not.
-%% Why?
-%%-----------------------------------------------------------------------
-
--module(failing_guard1).
--export([n/1]).
-
-n(N) when (N / 2) =:= 2 -> multiple_of_four;
-n(N) when (N div 3) =:= 2.0 -> multiple_of_six;
-n(N) when (N rem 3) =:= 2.0 -> multiple_of_six;
-n(N) when is_number(N) -> other_number.
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/flatten.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/flatten.erl
deleted file mode 100644
index ac28fe27c9..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/flatten.erl
+++ /dev/null
@@ -1,18 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : flatten.erl
-%%% Author : Tobias Lindahl <[email protected]>
-%%% Description :
-%%%
-%%% Created : 4 Nov 2007 by Tobias Lindahl <[email protected]>
-%%%-------------------------------------------------------------------
--module(flatten).
-
--export([t/1]).
-
-t(Dir) ->
- case file:list_dir(Dir) of
- {ok,FileList} ->
- FileList;
- {error,Reason} ->
- {error,lists:flatten("Can't open directory "++Dir++": "++Reason)}
- end.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/fun_app.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/fun_app.erl
deleted file mode 100644
index 605b0799d1..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/fun_app.erl
+++ /dev/null
@@ -1,42 +0,0 @@
-%% This is taken from the code of distel.
-
--module(fun_app).
--export([html_index/2]). % , lines/3, curry/2]).
-
-html_index(file,Dir) ->
- fold_file(curry(fun lines/3,Dir),[],filename:join([Dir,"doc","man_index.html"])).
-
-fold_file(Fun,Acc0,File) ->
- {ok, FD} = file:open(File, [read]),
- Acc = fold_file_lines(FD,Fun,Acc0),
- file:close(FD),
- Acc.
-
-fold_file_lines(FD,Fun,Acc) ->
- case io:get_line(FD, "") of
- eof -> Acc;
- Line -> fold_file_lines(FD,Fun,Fun(trim_nl(Line),Acc))
- end.
-
-trim_nl(Str) -> lists:reverse(tl(lists:reverse(Str))).
-
-lines(Line,_,Dir) ->
- case string:tokens(Line, "<> \"") of
- ["TD", "A", "HREF=", "../"++Href, M|_] ->
- case filename:basename(Href, ".html") of
- "index" -> ok;
- M -> e_set({file,M}, filename:join([Dir,Href]))
- end;
- _ -> ok
- end.
-
-e_set(Key,Val) -> ets:insert(?MODULE, {Key,Val}).
-
-curry(F, Arg) ->
- case erlang:fun_info(F,arity) of
- {_,1} -> fun() -> F(Arg) end;
- {_,2} -> fun(A) -> F(A,Arg) end;
- {_,3} -> fun(A,B) -> F(A,B,Arg) end;
- {_,4} -> fun(A,B,C) -> F(A,B,C,Arg) end
- end.
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/fun_ref_match.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/fun_ref_match.erl
deleted file mode 100644
index c15226ba6e..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/fun_ref_match.erl
+++ /dev/null
@@ -1,21 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : fun_ref_match.erl
-%%% Author : Tobias Lindahl <[email protected]>
-%%% Description : Find that newly created funs and references cannot
-%%% match on earlier bound variables.
-%%%
-%%% Created : 10 Mar 2005 by Tobias Lindahl <[email protected]>
-%%%-------------------------------------------------------------------
--module(fun_ref_match).
-
--export([t1/1, t2/1]).
-
-t1(X) ->
- X = fun(Y) -> Y end,
- ok.
-
-t2(X) ->
- case make_ref() of
- X -> error;
- _ -> ok
- end.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/gs_make.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/gs_make.erl
deleted file mode 100644
index cbf3ef5dcb..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/gs_make.erl
+++ /dev/null
@@ -1,261 +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: gs_make.erl,v 1.1 2008/12/17 09:53:50 mikpe Exp $
-%%
--module(gs_make).
-
--export([start/0]).
-
-start() ->
- Terms = the_config(),
- DB=fill_ets(Terms),
- {ok,OutFd} = file:open("gstk_generic.hrl", [write]),
- put(stdout,OutFd),
-% io:format("terms: ~p ~n ets:~p~n",[Terms,ets:tab2list(DB)]),
- p("% Don't edit this file. It was generated by gs_make:start/0 "),
- p("at ~p-~p-~p, ~p:~p:~p.\n\n",
- lists:append(tuple_to_list(date()),tuple_to_list(time()))),
- gen_out_opts(DB),
- gen_read(DB),
- file:close(OutFd),
- {ok,"gstk_generic.hrl",DB}.
-
-fill_ets(Terms) ->
- DB = ets:new(gs_mapping,[bag,public]),
- fill_ets(DB,Terms).
-
-fill_ets(DB,[]) -> DB;
-fill_ets(DB,[{Objs,Opt,Fun,Access}|Terms]) ->
- fill_ets(DB,lists:flatten(Objs),Opt,Fun,Access),
- fill_ets(DB,Terms).
-
-fill_ets(_DB,[],_,_,_) -> done;
-fill_ets(DB,[Obj|Objs],Opt,Fun,rw) ->
- ets:insert(DB,{Obj,Opt,Fun,read}),
- ets:insert(DB,{Obj,Opt,Fun,write}),
- fill_ets(DB,Objs,Opt,Fun,rw);
-fill_ets(DB,[Obj|Objs],Opt,Fun,r) ->
- ets:insert(DB,{Obj,Opt,Fun,read}),
- fill_ets(DB,Objs,Opt,Fun,r);
-fill_ets(DB,[Obj|Objs],Opt,Fun,w) ->
- ets:insert(DB,{Obj,Opt,Fun,write}),
- fill_ets(DB,Objs,Opt,Fun,w).
-
-
-
-gen_out_opts(DB) ->
- ObjTypes = lists:flatten(ordsets:from_list(ets:match(DB,{'$1','_','_',write}))),
- p("out_opts([Option|Options],Gstkid,TkW,DB,ExtraArg,S,P,C) ->\n"),
- p(" {Opt,Val} =\n"),
- p(" case Option of \n"),
- p(" {{default,Cat,Key},V} -> {default,{Cat,{Key,V}}};\n"),
- p(" {_Key,_V} -> Option;\n"),
- p(" {default,Cat,Opti} -> {default,{Cat,Opti}};\n"),
- p(" Atom when atom(Atom) -> {Atom,undefined};\n"),
- p(" _ -> {error, {invalid_option,Option}}\n"),
- p(" end,\n"),
- p(" case Gstkid#gstkid.objtype of\n"),
- gen_out_type_case_clauses(merge_types(ObjTypes),DB),
- p(" Q -> exit({internal_error,unknown_objtype,Q})\n"),
- p(" end;\n"),
- p("out_opts([],_Gstkid,_TkW,_DB,_ExtraArg,S,P,C) -> \n"),
- p(" {S,P,C}.\n").
-
-
-gen_out_type_case_clauses([],_DB) -> done;
-gen_out_type_case_clauses([Objtype|Objtypes],DB) ->
- OptsFuns = lists:map(fun (L) -> list_to_tuple(L) end,
- ets:match(DB,{Objtype,'$1','$2',write})),
- p(" ~p -> \ncase Opt of\n",[Objtype]),
- gen_opt_case_clauses(merge_opts(opt_prio(),OptsFuns)),
- p(" _ -> \n"),
- p(" handle_external_opt_call([Option|Options],Gstkid,TkW,DB,ExtraArg,"
- " gstk_~p:option(Option,Gstkid,TkW,DB,ExtraArg),S,P,C)\n",
- [Objtype]),
- p(" end;\n"),
- gen_out_type_case_clauses(Objtypes,DB).
-
-gen_opt_case_clauses([]) ->
- done;
-gen_opt_case_clauses([{Opt,Fun}|OptFuncs]) ->
- p(" ~p ->\n",[Opt]),
- p(" ~p(Val,Options,Gstkid,TkW,DB,ExtraArg,S,P,C);\n",[Fun]),
- gen_opt_case_clauses(OptFuncs).
-
-gen_read(DB) ->
- ObjTypes = lists:flatten(ordsets:from_list(ets:match(DB,{'$1','_','_',read}))),
- p("read_option(DB,Gstkid,TkW,Option,ExtraArg) ->\n"),
- p(" Key = case Option of\n"),
- p(" Atom when atom(Atom) -> Atom;\n"),
- p(" Opt when tuple(Opt) -> element(1,Opt)\n"),
- p(" end,\n"),
- p(" case Gstkid#gstkid.objtype of\n"),
- gen_read_type_clauses(merge_types(ObjTypes),DB),
- p(" Q -> exit({internal_error,unknown_objtype,Q})\n"),
- p(" end.\n").
-
-
-gen_read_type_clauses([],_) -> done;
-gen_read_type_clauses([Objtype|Objtypes],DB) ->
- OptsFuns = lists:map(fun (L) -> list_to_tuple(L) end,
- ets:match(DB,{Objtype,'$1','$2',read})),
- p(" ~p -> \ncase Key of\n",[Objtype]),
- gen_readopt_case_clauses(merge_opts(opt_prio(),OptsFuns)),
- p(" _ -> \nhandle_external_read(gstk_~p:read_option(Option,Gstkid,TkW,DB,ExtraArg))\n",[Objtype]),
- p(" end;\n"),
- gen_read_type_clauses(Objtypes,DB).
-
-gen_readopt_case_clauses([]) ->
- done;
-gen_readopt_case_clauses([{Opt,Fun}|OptFuncs]) ->
- p(" ~p -> \n~p(Option,Gstkid,TkW,DB,ExtraArg);\n",[Opt,Fun]),
- gen_readopt_case_clauses(OptFuncs).
-
-
-p(Str) ->
- ok = io:format(get(stdout),Str,[]).
-
-p(Format,Data) ->
- ok = io:format(get(stdout),Format,Data).
-
-%%----------------------------------------------------------------------
-%% There items should be placed early in a case statement.
-%%----------------------------------------------------------------------
-obj_prio() -> [rectangle,line,gridline,image,button,canvas,checkbutton,radiobutton].
-opt_prio() -> [x,y,width,height,move,coords,data].
-
-merge_types(Types) ->
- T2 = ordsets:from_list(Types),
- P2 = ordsets:from_list(obj_prio()),
- obj_prio() ++ ordsets:subtract(T2, P2).
-
-merge_opts([],L) -> L;
-merge_opts([Opt|Opts],Dict) ->
- case gs:assq(Opt,Dict) of
- {value,V} -> [{Opt,V}|merge_opts(Opts,lists:keydelete(Opt,1,Dict))];
- false -> merge_opts(Opts,Dict)
- end.
-
-the_config() ->
- Buttons=[button,checkbutton,radiobutton],
- AllPureTk = [Buttons,canvas,editor,entry,frame,label,listbox,
- menubar,menubutton,scale,window],
- CanvasObj = [arc,image,line,oval,polygon,rectangle,text],
- All = [AllPureTk,CanvasObj,grid,gridline,menu,menuitem,gs],
- Containers = [canvas,frame,grid,menu,menubar,menubutton,menuitem,window],
- Ob1 = [Buttons,canvas,grid,frame,label,entry,editor,listbox,scale],
- Ob2 = [button,checkbutton,radiobutton,label,menubutton],
- Ob3 = [Buttons,frame,label,entry,editor,listbox,scale,menubutton,
- menubar,menu],
- Ob4 = [canvas,editor,listbox],
- [{[Buttons,entry,scale,menubutton],enable,gen_enable,rw},
- {[Buttons,label,entry,scale,menubutton,menu],fg,gen_fg,rw},
- {[Buttons,label,entry,scale,menubutton,menu],bg,gen_bg,rw},
- {Ob1,anchor,gen_anchor,rw},
- {Ob1,height,gen_height,r},
- {Ob1--[frame],height,gen_height,w},
- {Ob1,width,gen_width,r},
- {Ob1--[frame],width,gen_width,w},
- {Ob1,pack_x,gen_pack_x,rw},
- {Ob1,pack_y,gen_pack_y,rw},
- {Ob1,pack_xy,gen_pack_xy,w},
- {Ob1,x,gen_x,rw},
- {Ob1,y,gen_y,rw},
- {Ob1,raise,gen_raise,w},
- {Ob1,lower,gen_lower,w},
- {Ob2,align,gen_align,rw},
- {Ob2,font,gen_font,rw},
- {Ob2,justify,gen_justify,rw},
- {Ob2,padx,gen_padx,rw},
- {Ob2,pady,gen_pady,rw},
- {Containers,default,gen_default,w},
- {[AllPureTk,menu],relief,gen_relief,rw},
- {[AllPureTk,menu],bw,gen_bw,rw},
- {[Buttons,canvas,frame,label,entry,scale,menubutton,menu,menubar],
- setfocus,gen_setfocus,rw},
- {Ob3,buttonpress,gen_buttonpress,rw},
- {Ob3,buttonrelease,gen_buttonrelease,rw},
- {Ob3,configure,gen_configure,rw},
- {[Ob3,window],destroy,gen_destroy,rw},
- {[Ob3,window],enter,gen_enter,rw},
- {[Ob3,window],leave,gen_leave,rw},
- {[Ob3,window],focus,gen_focus_ev,rw},
- {[Ob3,window],keypress,gen_keypress,rw},
- {[Ob3,window],keyrelease,gen_keyrelease,rw},
- {Ob3,motion,gen_motion,rw},
- %% events containing x,y are special
- {[window],buttonpress,gen_buttonpress,r},
- {[window],buttonrelease,gen_buttonrelease,r},
- {[window],motion,gen_motion,r},
- {All,font_wh,gen_font_wh,r},
- {All,choose_font,gen_choose_font,r},
- {All,data,gen_data,rw},
- {All,children,gen_children,r},
- {All,id,gen_id,r},
- {All,parent,gen_parent,r},
- {All,type,gen_type,r},
- {All,beep,gen_beep,w},
- {All,keep_opt,gen_keep_opt,w},
- {All,flush,gen_flush,rw},
- {AllPureTk,highlightbw,gen_highlightbw,rw},
- {AllPureTk,highlightbg,gen_highlightbg,rw},
- {AllPureTk,highlightfg,gen_highlightfg,rw},
- {AllPureTk,cursor,gen_cursor,rw}, % bug
- {[Buttons,label,menubutton],label,gen_label,rw},
- {[Buttons,menubutton,menu],activebg,gen_activebg,rw},
- {[Buttons,menubutton,menu],activefg,gen_activefg,rw},
- {[entry],selectbg,gen_selectbg,rw},
- {[entry],selectbw,gen_selectbw,rw},
- {[entry],selectfg,gen_selectfg,rw},
- {Ob4,activebg,gen_so_activebg,rw},
- {Ob4,bc,gen_so_bc,rw},
- {Ob4,bg,gen_so_bg,rw},
- {Ob4,hscroll,gen_so_hscroll,r},
- {Ob4,scrollbg,gen_so_scrollbg,rw},
- {Ob4,scrollfg,gen_so_scrollfg,rw},
- {Ob4,scrolls,gen_so_scrolls,w},
- {Ob4,selectbg,gen_so_selectbg,rw},
- {Ob4,selectbg,gen_so_selectbg,rw},
- {Ob4,selectbw,gen_so_selectbw,rw},
- {Ob4,selectbw,gen_so_selectbw,rw},
- {Ob4,selectfg,gen_so_selectfg,rw},
- {Ob4,selectfg,gen_so_selectfg,rw},
- {Ob4,vscroll,gen_so_vscroll,r},
- {CanvasObj,coords,gen_citem_coords,rw},
- {CanvasObj,lower,gen_citem_lower,w},
- {CanvasObj,raise,gen_citem_raise,w},
- {CanvasObj,move,gen_citem_move,w},
- {CanvasObj,setfocus,gen_citem_setfocus,rw},
- {CanvasObj,buttonpress,gen_citem_buttonpress,w}, % should be rw
- {CanvasObj,buttonrelease,gen_citem_buttonrelease,w},
- {CanvasObj,enter,gen_citem_enter,w},
- {CanvasObj,focus,gen_citem_setfocus,w},
- {CanvasObj,keypress,gen_citem_keypress,w},
- {CanvasObj,keyrelease,gen_citem_keyrelease,w},
- {CanvasObj,leave,gen_citem_leave,w},
- {CanvasObj,motion,gen_citem_motion,w},
- {CanvasObj,buttonpress,gen_buttonpress,r},
- {CanvasObj,buttonrelease,gen_buttonrelease,r},
- {CanvasObj,configure,gen_configure,r},
- {CanvasObj,destroy,gen_destroy,r},
- {CanvasObj,enter,gen_enter,r},
- {CanvasObj,leave,gen_leave,r},
- {CanvasObj,focus,gen_focus_ev,r},
- {CanvasObj,keypress,gen_keypress,r},
- {CanvasObj,keyrelease,gen_keyrelease,r},
- {CanvasObj,motion,gen_motion,r},
- {[arc,oval,polygon,rectangle],fill,gen_citem_fill,rw}].
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/inf_loop2.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/inf_loop2.erl
deleted file mode 100644
index fbbec10a55..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/inf_loop2.erl
+++ /dev/null
@@ -1,23 +0,0 @@
-%%---------------------------------------------------------------------
-%% Module that went into an infinite loop when trying to assign types.
-%%
-%% What was happening is that for functions which are in an SCC but all
-%% return none(), a second chance was given to them by the analysis to
-%% see whether they return none() because they are involved in an loop
-%% (presumably server-related) and could be assigned the type unit()
-%% instead. The problem is that when the really return none() for some
-%% other reason (an error such in this case) then we will again find
-%% none() and try again for unit(), thereby entering an infinite loop.
-%% The issue was resolved on May 17th by adding an appropriate boolean
-%% parameter to dialyzer_typesig:solve_scc() function.
-%%---------------------------------------------------------------------
--module(inf_loop2).
-
--export([test/0]).
-
-test() ->
- lists:reverse(gazonk),
- loop().
-
-loop() ->
- test().
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/letrec1.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/letrec1.erl
deleted file mode 100644
index f5c265cc60..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/letrec1.erl
+++ /dev/null
@@ -1,13 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : letrec1.erl
-%%% Author : Tobias Lindahl <[email protected]>
-%%% Description :
-%%%
-%%% Created : 9 Mar 2007 by Tobias Lindahl <[email protected]>
-%%%-------------------------------------------------------------------
--module(letrec1).
-
--export([t/1]).
-
-t(Opts) ->
- [Opt || Opt <- Opts, Opt =/= compressed].
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/list_match.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/list_match.erl
deleted file mode 100644
index 77de6d7dee..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/list_match.erl
+++ /dev/null
@@ -1,20 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : list_match.erl
-%%% Author : Tobias Lindahl <[email protected]>
-%%% Description :
-%%%
-%%% Created : 12 Mar 2007 by Tobias Lindahl <[email protected]>
-%%%-------------------------------------------------------------------
--module(list_match).
-
--export([t/0]).
-
-t() ->
- t([1,2,3,4]).
-
-t([]) ->
- ok;
-t([H|T]) when is_integer(H) ->
- t(T);
-t([_|T]) ->
- t(T).
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/my_filter.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/my_filter.erl
deleted file mode 100644
index a67c4bd432..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/my_filter.erl
+++ /dev/null
@@ -1,17 +0,0 @@
--module(my_filter).
--export([test/0]).
-
-test() ->
- filter(fun mystery/1, [1,2,3,4]).
-
-filter(Pred, List) when is_function(Pred, 1) ->
- [ E || E <- List, Pred(E) ].
-
-mystery(X) ->
- case (X rem 3) of
- 0 -> true;
- 1 -> false;
- 2 -> gazonk
- end.
-
-%% mystery(_X,_Y) -> true.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/my_sofs.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/my_sofs.erl
deleted file mode 100644
index 32252071d2..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/my_sofs.erl
+++ /dev/null
@@ -1,83 +0,0 @@
-%% Program showing the problems with record field accesses.
-
--module(my_sofs).
--export([ordset_of_sets/3, is_equal/2]).
-
--define(TAG, 'Set').
--define(ORDTAG, 'OrdSet').
-
--record(?TAG, {data = [], type = type}).
--record(?ORDTAG, {orddata = {}, ordtype = type}).
-
--define(LIST(S), (S)#?TAG.data).
--define(TYPE(S), (S)#?TAG.type).
--define(SET(L, T), #?TAG{data = L, type = T}).
--define(IS_SET(S), record(S, ?TAG)).
-
-%% Ordered sets and atoms:
--define(ORDDATA(S), (S)#?ORDTAG.orddata).
--define(ORDTYPE(S), (S)#?ORDTAG.ordtype).
--define(ORDSET(L, T), #?ORDTAG{orddata = L, ordtype = T}).
--define(IS_ORDSET(S), record(S, ?ORDTAG)).
-
-%% When IS_SET is true:
--define(ANYTYPE, '_').
--define(REL_TYPE(I, R), element(I, R)).
--define(SET_OF(X), [X]).
-
-is_equal(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) ->
- case match_types(?TYPE(S1), ?TYPE(S2)) of
- true -> ?LIST(S1) == ?LIST(S2);
- false -> erlang:error(type_mismatch, [S1, S2])
- end;
-is_equal(S1, S2) when ?IS_ORDSET(S1), ?IS_ORDSET(S2) ->
- case match_types(?TYPE(S1), ?TYPE(S2)) of
- true -> ?ORDDATA(S1) == ?ORDDATA(S2);
- false -> erlang:error(type_mismatch, [S1, S2])
- end;
-is_equal(S1, S2) when ?IS_SET(S1), ?IS_ORDSET(S2) ->
- erlang:error(type_mismatch, [S1, S2]);
-is_equal(S1, S2) when ?IS_ORDSET(S1), ?IS_SET(S2) ->
- erlang:error(type_mismatch, [S1, S2]).
-
-%% Type = OrderedSetType
-%% | SetType
-%% | atom() except '_'
-%% OrderedSetType = {Type, ..., Type}
-%% SetType = [ElementType] % list of exactly one element
-%% ElementType = '_' % any type (implies empty set)
-%% | Type
-
-ordset_of_sets([S | Ss], L, T) when ?IS_SET(S) ->
- ordset_of_sets(Ss, [?LIST(S) | L], [[?TYPE(S)] | T]);
-ordset_of_sets([S | Ss], L, T) when ?IS_ORDSET(S) ->
- ordset_of_sets(Ss, [?LIST(S) | L], [?ORDTYPE(S) | T]);
-ordset_of_sets([], L, T) ->
- ?ORDSET(list_to_tuple(lists:reverse(L)), list_to_tuple(lists:reverse(T)));
-ordset_of_sets(_, _L, _T) ->
- error.
-
-%% inlined.
-match_types(T, T) -> true;
-match_types(Type1, Type2) -> match_types1(Type1, Type2).
-
-match_types1(Atom, Atom) when is_atom(Atom) ->
- true;
-match_types1(?ANYTYPE, _) ->
- true;
-match_types1(_, ?ANYTYPE) ->
- true;
-match_types1(?SET_OF(Type1), ?SET_OF(Type2)) ->
- match_types1(Type1, Type2);
-match_types1(T1, T2) when tuple(T1), tuple(T2), size(T1) =:= size(T2) ->
- match_typesl(size(T1), T1, T2);
-match_types1(_T1, _T2) ->
- false.
-
-match_typesl(0, _T1, _T2) ->
- true;
-match_typesl(N, T1, T2) ->
- case match_types1(?REL_TYPE(N, T1), ?REL_TYPE(N, T2)) of
- true -> match_typesl(N-1, T1, T2);
- false -> false
- end.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/not_guard_crash.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/not_guard_crash.erl
deleted file mode 100644
index 0350864dce..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/not_guard_crash.erl
+++ /dev/null
@@ -1,49 +0,0 @@
-%% From: Matthias Radestock <[email protected]>
-%% Date: 19 August 2007
-%%
-%% when I run dialyzer on my code it throws the following error:
-%%
-%% Analysis failed with error report:
-%% {{case_clause,any},
-%% [{dialyzer_dataflow,bind_guard,5},
-%% {dialyzer_dataflow,bind_guard_case_clauses,6},
-%% {dialyzer_dataflow,bind_guard,5},
-%% {dialyzer_dataflow,bind_guard_case_clauses,6},
-%% {dialyzer_dataflow,bind_guard,5},
-%% {dialyzer_dataflow,bind_eqeq_guard_lit_other,6},
-%% {dialyzer_dataflow,bind_guard,...},
-%% {dialyzer_dataflow,...}]}
-%%
-%% This is happening with the R11B-5 version of dialyzer when
-%% analyzing the attached file.
-%%--------------------------------------------------------------------
-
--module(not_guard_crash).
-
--export([match_ticket/2]).
-
--record(ticket, {passive_flag, active_flag, write_flag, read_flag}).
-
-%%--------------------------------------------------------------------
-
-match_ticket(#ticket{passive_flag = PP,
- active_flag = PA,
- write_flag = PW,
- read_flag = PR},
- #ticket{passive_flag = TP,
- active_flag = TA,
- write_flag = TW,
- read_flag = TR}) ->
- if
- %% Matches if either we're not requesting passive access, or
- %% passive access is permitted, and ...
- (not(TP) orelse PP) andalso
- (not(TA) orelse PA) andalso
- (not(TW) orelse PW) andalso
- (not(TR) orelse PR) ->
- match;
- true ->
- no_match
- end.
-
-%%--------------------------------------------------------------------
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/orelsebug.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/orelsebug.erl
deleted file mode 100644
index 626f2b7f03..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/orelsebug.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : orelsebug.erl
-%%% Author : Tobias Lindahl <[email protected]>
-%%% Description :
-%%%
-%%% Created : 14 Nov 2006 by Tobias Lindahl <[email protected]>
-%%%-------------------------------------------------------------------
--module(orelsebug).
-
--export([t/1, t1/1]).
-
-t(Format) when is_list(Format) ->
- t1(Format).
-
-t1(Format) when is_list(Format) orelse is_binary(Format) ->
- Format.
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/orelsebug2.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/orelsebug2.erl
deleted file mode 100644
index 52b1b3b5a9..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/orelsebug2.erl
+++ /dev/null
@@ -1,23 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : orelsebug2.erl
-%%% Author : Tobias Lindahl <[email protected]>
-%%% Description :
-%%%
-%%% Created : 21 Nov 2006 by Tobias Lindahl <[email protected]>
-%%%-------------------------------------------------------------------
--module(orelsebug2).
-
--export([t/1]).
-
--record(eventdata, {
- expires
- }).
-
-t(L) ->
- L2 = [E1 || E1 <- L, E1#eventdata.expires == x
- orelse E1#eventdata.expires == y],
-
- case L2 of
- [_E] -> x;
- [] -> y
- end.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/port_info_test.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/port_info_test.erl
deleted file mode 100644
index d8a5e15caf..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/port_info_test.erl
+++ /dev/null
@@ -1,34 +0,0 @@
-%%
-%% Tests hardcoded dependent type info
-%% and the quality of the warnings that Dialyzer spits out
-%%
--module(port_info_test).
--export([t1/1, t2/1, t3/1, t4/1, t5/2, buggy/1]).
-
-%% The following errors are correctly caught, but the messages are a bit weird
-t1(X) when is_port(X) ->
- {connected, 42} = erlang:port_info(X, connected);
-t1(_) -> ok.
-
-t2(X) when is_port(X) ->
- {registered_name, "42"} = erlang:port_info(X, registered_name);
-t2(_) -> ok.
-
-%% Here only one od the two errors is reported...
-t3(X) when is_atom(X) ->
- {output, 42} = erlang:port_info(X, connected);
-t3(_) -> ok.
-
-t4(X) when is_atom(X) ->
- {Atom, _} = erlang:port_info(X, connected),
- Atom = links;
-t4(_) -> ok.
-
-t5(X, Atom) when is_port(X) ->
- {gazonk, _} = erlang:port_info(X, Atom);
-t5(_, _) -> ok.
-
-%% The type system is not strong enough to catch the following errors
-buggy(X) when is_atom(X) ->
- {links, X} = erlang:port_info(foo, X).
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/process_info_test.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/process_info_test.erl
deleted file mode 100644
index d098884f4d..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/process_info_test.erl
+++ /dev/null
@@ -1,21 +0,0 @@
-%%
-%% Tests hardcoded dependent type info for process_info/1
-%%
--module(process_info_test).
--export([pinfo/1]).
-
-pinfo(P) when node(P) == node() -> % On same node
- case process_info(P) of
- undefined ->
- exit(dead);
- Info -> Info
- end;
-pinfo(P) -> % On different node
- case rpc:call(node(P), erlang, process_info, [P]) of
- {badrpc, _} ->
- exit(badrpc);
- undefined -> % This does happen
- exit(dead);
- Info -> Info
- end.
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/pubsub/pubsub_api.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/pubsub/pubsub_api.erl
deleted file mode 100644
index c30233b8f5..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/pubsub/pubsub_api.erl
+++ /dev/null
@@ -1,99 +0,0 @@
-% Copyright 2007-2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
-%
-% Licensed under the Apache License, Version 2.0 (the "License");
-% you may not use this file except in compliance with the License.
-% You may obtain a copy of the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS,
-% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-% See the License for the specific language governing permissions and
-% limitations under the License.
-%%%-------------------------------------------------------------------
-%%% File : pubsub_api.erl
-%%% Author : Thorsten Schuett <[email protected]>
-%%% Description : Publish API function
-%%%
-%%% Created : 17 Sep 2007 by Thorsten Schuett <[email protected]>
-%%%-------------------------------------------------------------------
-%% @author Thorsten Schuett <[email protected]>
-%% @copyright 2007-2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
-%% @version $Id $
--module(pubsub_dir.pubsub_api).
-
--author('[email protected]').
--vsn('$Id: pubsub_api.erl,v 1.1 2009/11/06 12:39:55 maria Exp $ ').
-
--export([publish/2, subscribe/2, unsubscribe/2, get_subscribers/1]).
-
--import(transstore.transaction_api).
--import(io).
--import(lists).
-
-%%====================================================================
-%% public functions
-%%====================================================================
-
-%% @doc publishs an event under a given topic.
-%% called e.g. from the java-interface
-%% @spec publish(string(), string()) -> ok
-publish(Topic, Content) ->
- Subscribers = get_subscribers(Topic),
- io:format("calling subscribers ~p~n", [Subscribers]),
- lists:foreach(fun (Subscriber) ->
- io:format("calling ~p~n", [Subscriber]),
- pubsub_publish:publish(Subscriber, Topic, Content)
- end,
- Subscribers),
- ok.
-
-%% @doc subscribes a url for a topic.
-%% called e.g. from the java-interface
-%% @spec subscribe(string(), string()) -> ok | {fail, term()}
-subscribe(Topic, URL) ->
- TFun = fun(TransLog) ->
- {{Success, _ValueOrReason} = Result, TransLog1} = transaction_api:read(Topic, TransLog),
- {Result2, TransLog2} = if
- Success == fail ->
- transaction_api:write(Topic, [URL], TransLog); %obacht: muss TransLog sein!
- true ->
- {value, Subscribers} = Result,
- transaction_api:write(Topic, [URL | Subscribers], TransLog1)
- end,
- if
- Result2 == ok ->
- {{ok, ok}, TransLog2};
- true ->
- {Result2, TransLog2}
- end
- end,
- transaction_api:do_transaction(TFun, fun (_) -> ok end, fun (X) -> {fail, X} end).
-
-%% @doc unsubscribes a url for a topic.
--spec(unsubscribe/2 :: (string(), string()) -> ok | {fail, any()}).
-unsubscribe(Topic, URL) ->
- TFun = fun(TransLog) ->
- {Subscribers, TransLog1} = transaction_api:read2(TransLog, Topic),
- case lists:member(URL, Subscribers) of
- true ->
- NewSubscribers = lists:delete(URL, Subscribers),
- TransLog2 = transaction_api:write2(TransLog1, Topic, NewSubscribers),
- {{ok, ok}, TransLog2};
- false ->
- {{fail, not_found}, TransLog}
- end
- end,
- transaction_api:do_transaction(TFun, fun (_) -> ok end, fun (X) -> {fail, X} end).
-
-%% @doc queries the subscribers of a query
-%% @spec get_subscribers(string()) -> [string()]
-get_subscribers(Topic) ->
- {Fl, _Value} = transaction_api:quorum_read(Topic),
- if
- Fl == fail -> %% Fl is either Fail or the Value/Subscribers
- [];
- true ->
- Fl
- end.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/pubsub/pubsub_publish.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/pubsub/pubsub_publish.erl
deleted file mode 100644
index 97c993e576..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/pubsub/pubsub_publish.erl
+++ /dev/null
@@ -1,50 +0,0 @@
-% Copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
-%
-% Licensed under the Apache License, Version 2.0 (the "License");
-% you may not use this file except in compliance with the License.
-% You may obtain a copy of the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS,
-% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-% See the License for the specific language governing permissions and
-% limitations under the License.
-%%%-------------------------------------------------------------------
-%%% File : pubsub_publish.erl
-%%% Author : Thorsten Schuett <[email protected]>
-%%% Description : Publish function
-%%%
-%%% Created : 26 Mar 2008 by Thorsten Schuett <[email protected]>
-%%%-------------------------------------------------------------------
-%% @author Thorsten Schuett <[email protected]>
-%% @copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
-%% @version $Id $
--module(pubsub_dir.pubsub_publish).
-
--author('[email protected]').
--vsn('$Id: pubsub_publish.erl,v 1.1 2009/11/06 12:39:55 maria Exp $ ').
-
--export([publish/3, publish_internal/3]).
-
--import(json).
--import(io).
--import(http).
--import(jsonrpc).
-
-%%====================================================================
-%% public functions
-%%====================================================================
-
-%% @doc publishs an event to a given url.
-%% @spec publish(string(), string(), string()) -> ok
-%% @todo use pool:pspawn
-publish(URL, Topic, Content) ->
- spawn(fun () -> pubsub_publish:publish_internal(URL, Topic, Content) end),
- ok.
-
-publish_internal(URL, Topic, Content) ->
- Res = jsonrpc:call(URL, [], {call, notify, [Topic, Content]}),
- io:format("~p ~p~n", [Res, URL]).
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/receive1.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/receive1.erl
deleted file mode 100644
index 2699a6da51..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/receive1.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : receive1.erl
-%%% Author : Tobias Lindahl <[email protected]>
-%%% Description :
-%%%
-%%% Created : 27 Mar 2007 by Tobias Lindahl <[email protected]>
-%%%-------------------------------------------------------------------
--module(receive1).
-
--export([t/1]).
-
-t(X) ->
- receive
- after
- infinity -> X
- end.
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/record_construct.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/record_construct.erl
deleted file mode 100644
index 627e23956b..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/record_construct.erl
+++ /dev/null
@@ -1,22 +0,0 @@
--module(record_construct).
--export([t_loc/0, t_opa/0, t_rem/0]).
-
--record(r_loc, {a = gazonk :: integer(), b = 42 :: atom()}).
-
-t_loc() ->
- #r_loc{}.
-
--record(r_opa, {a :: atom(),
- b = gb_sets:new() :: gb_set(),
- c = 42 :: boolean(),
- d, % untyped on purpose
- e = false :: boolean()}).
-
-t_opa() ->
- #r_opa{}.
-
--record(r_rem, {a = gazonk :: string()}).
-
-t_rem() ->
- #r_rem{}.
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/record_pat.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/record_pat.erl
deleted file mode 100644
index 89228b8357..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/record_pat.erl
+++ /dev/null
@@ -1,19 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : record_pat.erl
-%%% Author : Tobias Lindahl <>
-%%% Description : Emit warning if a pattern violates the record type
-%%%
-%%% Created : 21 Oct 2008 by Tobias Lindahl <>
-%%%-------------------------------------------------------------------
--module(record_pat).
-
--export([t/1]).
-
--record(foo, {bar :: integer()}).
-
-t(#foo{bar=baz}) -> no_way;
-t(#foo{bar=1}) -> ok.
-
-
-
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/record_send_test.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/record_send_test.erl
deleted file mode 100644
index 742519e54e..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/record_send_test.erl
+++ /dev/null
@@ -1,33 +0,0 @@
-%%-------------------------------------------------------------------
-%% File : record_send_test.erl
-%% Author : Kostis Sagonas <[email protected]>
-%% Description : A test inspired by a post of Mkcael Remond to the
-%% Erlang mailing list suggesting thst Dialyzer should
-%% be reporting sends to records rather than to pids.
-%% Dialyzer v1.3.0 indeed reports one of the dicrepancies
-%% (the one with the 4-tuple) but not the one where the
-%% message is sent to a pair which is a record.
-%% This should be fixed.
-%%
-%% Created : 10 Apr 2005 by Kostis Sagonas <[email protected]>
-%%-------------------------------------------------------------------
--module(record_send_test).
-
--export([t/0]).
-
--record(rec1, {a=a, b=b, c=c}).
--record(rec2, {a}).
-
-t() ->
- t(#rec1{}).
-
-t(Rec1 = #rec1{b=B}) ->
- Rec2 = some_mod:some_function(),
- if
- is_record(Rec2, rec2) ->
- Rec2 ! hello; %% currently this one is not found
- true ->
- Rec1 ! hello_again
- end,
- B.
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/record_test.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/record_test.erl
deleted file mode 100644
index 8151e595a0..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/record_test.erl
+++ /dev/null
@@ -1,24 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : record_test.erl
-%%% Author : Tobias Lindahl <[email protected]>
-%%% Description :
-%%%
-%%% Created : 22 Oct 2004 by Tobias Lindahl <[email protected]>
-%%%-------------------------------------------------------------------
--module(record_test).
-
--export([t/0]).
-
--record(foo, {bar}).
-
-t() ->
- doit(foo).
-
-doit(X) ->
- case X of
- #foo{} -> error1;
- foo -> ok;
- _ -> error2
- end.
-
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types2.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types2.erl
deleted file mode 100644
index 3a22bbf5d2..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types2.erl
+++ /dev/null
@@ -1,12 +0,0 @@
--module(recursive_types2).
-
--export([test/0]).
-
--type tree() :: 'nil' | {non_neg_integer(), child(), child()}.
-
--type child() :: tree().
-
--spec test() -> {42, tree(), tree()}.
-
-test() ->
- {42, {42, nil, nil}, {42, {42, nil, nil}, {42, nil, nil}}}.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types4.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types4.erl
deleted file mode 100644
index 118bab57a1..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types4.erl
+++ /dev/null
@@ -1,13 +0,0 @@
--module(recursive_types4).
-
--export([test/0]).
-
--record(tree, {node :: atom(),
- kid = nil :: 'nil' | tree()}).
-
--type tree() :: #tree{}.
-
--spec test() -> tree().
-
-test() ->
- #tree{node = root, kid = #tree{}}.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types5.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types5.erl
deleted file mode 100644
index a71e613cf0..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/recursive_types5.erl
+++ /dev/null
@@ -1,13 +0,0 @@
--module(recursive_types5).
-
--export([test/0]).
-
--type tree() :: 'nil' | {non_neg_integer(), tree(), tree()}.
-
--record(tree, {node :: atom(),
- kid = 'nil' :: tree()}).
-
--spec test() -> #tree{}.
-
-test() ->
- #tree{node = root, kid = {42, {42, nil, nil}, {42, nil, nil}}}.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/toth.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/toth.erl
deleted file mode 100644
index bd7fa4982e..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/toth.erl
+++ /dev/null
@@ -1,99 +0,0 @@
--module(toth).
--export([sys_table_view/1]).
-
-%%% Constants
--define(sysTabETS,1).
--define(sysTabMnesia,2).
--define(sysTabBoth,3).
-
-sys_table_view([CpId,{match,Pattern},TableType, ViewType]) ->
- AllTableList =
- case TableType of
- ?sysTabMnesia ->
- lists:sort(mnesia:system_info(tables));
- ?sysTabBoth ->
- lists:sort(rpc:call(CpId,ets,all,[]));
- ?sysTabETS ->
- lists:sort(rpc:call(CpId,ets,all,[]) --
- mnesia:system_info(tables));
- _ -> %%% Happens at registration only
- [ok]
- end,
- %% Filter the matching table names, skip unnamed tables first:
- NamedTableList = lists:filter(fun (X) -> is_atom(X) end, AllTableList),
- TablesShown =
- case Pattern of
- "" ->
- NamedTableList;
- _ ->
- %% Filter the ones whose name begins with the Pattern:
- Filter = fun(T) ->
- lists:prefix(Pattern, atom_to_list(T))
- end,
- lists:filter(Filter, NamedTableList)
- end,
-
- Fields = [{text, [{value,"CpId: " ++ atom_to_list(CpId)}]},
- {text, [{value,"TabSpec=" ++ Pattern},
- {value_format, term}]},
- {text, [{value,"Table type: " ++ formatTableType(TableType)},
- {value_format, term}]}],
-
- Template = [[{type, index},
- {link, {?MODULE, sys_table_browse,
- [{"CpId",CpId},{"TableType",TableType},
- {"View", ViewType},
- {"FirstKey",1}, {"KeyPattern",""}]}}],
-
- [{type, data},
- {title, "Table name"},
- {display_value, {erlang, atom_to_list}}], %%% else crash
-
- [{type,data},
- {title, "No of rows"},
- {display_value, term}],
-
- [{type,data},
- {title, "Memory"},
- {display_value, term}]
- ],
-
- TableAttr = [{rows, [[T,T|tableSize(T,TableType,CpId)] ||
- T <- TablesShown]},
- {template,Template}],
-
- Page = [{header, {"Filter tables", "Selected tables"}},
- {buttons, [reload, back]},
- {layout, [{form, Fields},
- {table, TableAttr}]}
- ],
- Page.
-
-%%--------------------------------------------------------------------
-%% tableSize/3
-%% @spec tableSize(T::atom(),TableType::integer(),CpId::atom()) ->
-%% list(integer())
-%% @doc Return the table size and memory size of the table.
-%% @end
-%%---------------------------------------------------------------------
-
-tableSize(T, TableType, CpId) ->
- case TableType of
- ?sysTabETS ->
- [rpc:call(CpId, ets, info, [T, size]),
- rpc:call(CpId, ets, info, [T, memory])];
- ?sysTabMnesia ->
- [mnesia:table_info(T, size),mnesia:table_info(T, memory)];
- _ -> %%% Registration
- [0,0]
- end.
-
-formatTableType(T) ->
- case T of
- ?sysTabETS ->
- "ETS";
- ?sysTabMnesia ->
- "mnesia";
- _ -> %%% Registration !
- "ETS + mnesia"
- end.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/trec.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/trec.erl
deleted file mode 100644
index b36b0cafba..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/trec.erl
+++ /dev/null
@@ -1,37 +0,0 @@
-%%
-%% The current treatment of typed records leaves much to be desired.
-%% These are not made up examples; I have cases like that the branch
-%% of the HiPE compiler with types in records. I get very confusing
-%% warnings which require a lot of effort to find their cause and why
-%% a function has no local return.
-%%
--module(trec).
--export([test/0, mk_foo_exp/2]).
-
--record(foo, {a :: integer(), b :: [atom()]}).
-
-%%
-%% For these functions we currently get the following warnings:
-%% 1. Function test/0 has no local return
-%% 2. The call trec:mk_foo_loc(42,any()) will fail since it differs
-%% in argument position 1 from the success typing arguments:
-%% ('undefined',atom())
-%% 3. Function mk_foo_loc/2 has no local return
-%%
-%% Arguably, the second warning is not what most users have in mind
-%% when they wrote the type declarations in the 'foo' record, so no
-%% doubt they'll find it confusing. But note that it is also inconsistent!
-%% How come there is a success typing for a function that has no local return?
-%%
-test() ->
- mk_foo_loc(42, bar:f()).
-
-mk_foo_loc(A, B) ->
- #foo{a = A, b = [A,B]}.
-
-%%
-%% For this function we currently get "has no local return" but we get
-%% no reason; I want us to get a reason.
-%%
-mk_foo_exp(A, B) when is_integer(A) ->
- #foo{a = A, b = [A,B]}.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/try1.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/try1.erl
deleted file mode 100644
index d07380295b..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/try1.erl
+++ /dev/null
@@ -1,27 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : try1.erl
-%%% Author : <[email protected]>
-%%% Description :
-%%%
-%%% Created : 23 Aug 2005 by <[email protected]>
-%%%-------------------------------------------------------------------
--module(try1).
-
--export([t/1]).
-
-t(X) ->
- case wierd_is_bool(X) of
- true -> ok;
- false -> ok
- end.
-
-wierd_is_bool(X) ->
- try bool(X) of
- Y -> Y
- catch
- _:_ -> false
- end.
-
-bool(true) -> true;
-bool(false) -> true.
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/tuple1.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/tuple1.erl
deleted file mode 100644
index c58aac9646..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/tuple1.erl
+++ /dev/null
@@ -1,29 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : tuple1.erl
-%%% Author : Tobias Lindahl <[email protected]>
-%%% Description : Exposed two bugs in the analysis;
-%%% one supressed warning and one crash.
-%%%
-%%% Created : 13 Nov 2006 by Tobias Lindahl <[email protected]>
-%%%-------------------------------------------------------------------
--module(tuple1).
-
--export([t1/2, t2/2, t3/2, bar/2]).
-
-t1(List = [_|_], X) ->
- lists:mapfoldl(fun foo/2, X, List).
-
-t2(List = [_|_], X) ->
- lists:mapfoldl(fun bar/2, X, List).
-
-t3(List = [_|_], X) ->
- lists:mapfoldl(fun baz/1, X, List).
-
-
-foo(1, 1) -> a;
-foo(a, 1) -> b.
-
-bar(1, 1) -> {b, b};
-bar(a, 1) -> {a, a}.
-
-baz(1) -> 1.
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/unsafe_beamcode_bug.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/unsafe_beamcode_bug.erl
deleted file mode 100644
index 889f94014e..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/unsafe_beamcode_bug.erl
+++ /dev/null
@@ -1,15 +0,0 @@
--module(unsafe_beamcode_bug).
--export([test/1]).
-
-test(N) -> i(r(N)).
-
-%% this function cannot be exported, or the error does not occur
-i({one}) -> ok1;
-i({two, _}) -> ok2;
-i({three, {_,R}, _}) -> R.
-
-r(1) -> {one};
-r(2) -> {two, 2};
-r(42)-> {dummy, 42}; % without this clause, no problem ... hmm
-r(3) -> {three, {rec,ok3}, 2}.
-
diff --git a/lib/dialyzer/test/small_tests_SUITE_data/src/zero_tuple.erl b/lib/dialyzer/test/small_tests_SUITE_data/src/zero_tuple.erl
deleted file mode 100644
index 90dc366fe7..0000000000
--- a/lib/dialyzer/test/small_tests_SUITE_data/src/zero_tuple.erl
+++ /dev/null
@@ -1,13 +0,0 @@
--module(zero_tuple).
--export([t1/0, t2/0]).
-
-t1() ->
- {} = a(),
- ok.
-
-t2() ->
- b = a(),
- ok.
-
-a() -> a.
-
diff --git a/lib/dialyzer/test/user_tests_SUITE_data/dialyzer_options b/lib/dialyzer/test/user_SUITE_data/dialyzer_options
index 513ed7752b..513ed7752b 100644
--- a/lib/dialyzer/test/user_tests_SUITE_data/dialyzer_options
+++ b/lib/dialyzer/test/user_SUITE_data/dialyzer_options
diff --git a/lib/dialyzer/test/user_tests_SUITE_data/results/broken_dialyzer b/lib/dialyzer/test/user_SUITE_data/results/broken_dialyzer
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/user_tests_SUITE_data/results/broken_dialyzer
+++ b/lib/dialyzer/test/user_SUITE_data/results/broken_dialyzer
diff --git a/lib/dialyzer/test/user_tests_SUITE_data/results/gcpFlowControl b/lib/dialyzer/test/user_SUITE_data/results/gcpFlowControl
index 7938c53fc6..7938c53fc6 100644
--- a/lib/dialyzer/test/user_tests_SUITE_data/results/gcpFlowControl
+++ b/lib/dialyzer/test/user_SUITE_data/results/gcpFlowControl
diff --git a/lib/dialyzer/test/user_tests_SUITE_data/results/qlc_error b/lib/dialyzer/test/user_SUITE_data/results/qlc_error
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/user_tests_SUITE_data/results/qlc_error
+++ b/lib/dialyzer/test/user_SUITE_data/results/qlc_error
diff --git a/lib/dialyzer/test/user_tests_SUITE_data/results/spvcOrig b/lib/dialyzer/test/user_SUITE_data/results/spvcOrig
index 8c57358af0..8c57358af0 100644
--- a/lib/dialyzer/test/user_tests_SUITE_data/results/spvcOrig
+++ b/lib/dialyzer/test/user_SUITE_data/results/spvcOrig
diff --git a/lib/dialyzer/test/user_tests_SUITE_data/results/wsp_pdu b/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu
index a47b1f1f2c..a47b1f1f2c 100644
--- a/lib/dialyzer/test/user_tests_SUITE_data/results/wsp_pdu
+++ b/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu
diff --git a/lib/dialyzer/test/user_SUITE_data/src/broken_dialyzer.erl b/lib/dialyzer/test/user_SUITE_data/src/broken_dialyzer.erl
new file mode 100644
index 0000000000..1e0612a345
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/broken_dialyzer.erl
@@ -0,0 +1,130 @@
+-module(broken_dialyzer).
+
+-export([do_move_next/1]).
+
+-define(ap_indices, 512).
+-define(dp_indices, 504).
+
+
+-record(apR,{a,c=[],n=[],nc=0,nn=0,nl=[]}).
+-define(apL(L), [#apR{a=A} || A <- L]).
+
+-define(gr, get(my_return_value)).
+-define(pr(PR), put(my_return_value, PR)).
+-record(bit,{i,c,n,s}). % index, current, next, state
+
+
+do_move_next({BL,AL}) ->
+ Max = max(length(BL), length(AL)),
+ Max2 = max(length(BL)*2, length(AL)),
+ MoveTo = [A || A <- AL, A#apR.nn < Max, A#apR.nn+A#apR.nc < Max2],
+ MoveFrom = [A || A <- AL,
+ (A#apR.nn > Max) orelse (A#apR.nn+A#apR.nc > Max2)],
+ Unchanged = (AL--MoveTo)--MoveFrom,
+ {BL1,{AL1,{AL2,AL3}}} =
+ lists:mapfoldl(
+ fun(B=#bit{i=I,c=C,s=S,n=Next}, {From,{To,FilledUp}})
+ when S==ok;S==lost_replica;S==moved_replica ->
+ case lists:keysearch(Next,#apR.a,From) of
+ {value, F=#apR{n=N1,nn=NN1,nc=NC1}}
+ when (NN1>Max) or (NN1+NC1>Max2) ->
+ case C of
+ [] ->
+ {B, {From,{To,FilledUp}}};
+ ShortList ->
+ T=#apR{a=NewNext,n=N2,nn=NN2} =
+ find_next(Next,ShortList),
+ {value, {C,NL_from}} =
+ lists:keysearch(C,1,F#apR.nl),
+ {value, {C,NL_to}} =
+ lists:keysearch(C,1,T#apR.nl),
+ NewNL_from = lists:keyreplace(
+ C,1,F#apR.nl,{C,NL_from--[I]}),
+ NewNL_to = lists:keyreplace(
+ C,1,T#apR.nl,{C,[I|NL_to]}),
+
+ NewT = T#apR{n=[I|N2],nn=NN2+1,
+ nl=NewNL_to},
+
+ {B#bit{n=NewNext,
+ s = if
+ S == lost_replica ->
+ lost_replica;
+ true ->
+ moved_replica
+ end},
+ {lists:keyreplace(
+ Next,#apR.a,From,
+ F#apR{n=N1--[I],nn=NN1-1,nl=NewNL_from}),
+ if
+ (NewT#apR.nn+NewT#apR.nc >= Max2)
+ or (NewT#apR.nn >= Max) ->
+ {lists:keydelete(NewNext,#apR.a,To),
+ [NewT|FilledUp]};
+ true ->
+ {lists:keyreplace(
+ NewNext,#apR.a,To,NewT),
+ FilledUp}
+ end}}
+ end;
+ _ ->
+ {B, {From,{To,FilledUp}}}
+ end;
+ (B, A) ->
+ {B, A}
+ end, {MoveFrom,{MoveTo,[]}},BL),
+ {BL1,Unchanged++AL1++AL2++AL3}.
+
+%%% -----------------------------------------------------------------
+%%% find_next/2
+%%%
+%%% ------------------------------------------------------------------
+
+find_next(Ap,L) ->
+ hd(catch
+ lists:foreach(
+ fun(SelVal) ->
+ case [ApR ||
+ ApR <- L,
+ begin
+ {value,{Ap,NL}} =
+ lists:keysearch(Ap,1,ApR#apR.nl),
+ length(NL) =< SelVal
+ end] of
+ [] ->
+ ok;
+ ShortList ->
+ throw(ShortList)
+ end
+ end,
+ lists:seq(0,?ap_indices))).
+
+%%% -----------------------------------------------------------------
+%%% max/2
+%%%
+%%% Calculates max number of indices per AP, given number of indices
+%%% and number of APs.
+%%% -----------------------------------------------------------------
+max(F,S) ->
+ (F div S) + if
+ (F rem S) == 0 ->
+ 0;
+ true ->
+ 1
+ end.
+
+%%% ==============================================================
+%%% ADMINISTRATIVE INFORMATION
+%%% ==============================================================
+%%% #Copyright (C) 2005
+%%% by ERICSSON TELECOM AB
+%%% S - 125 26 STOCKHOLM
+%%% SWEDEN, tel int + 46 8 719 0000
+%%%
+%%% The program may be used and/or copied only with the written
+%%% permission from ERICSSON TELECOM AB, or in accordance with
+%%% the terms and conditions stipulated in the agreement/contract
+%%% under which the program has been supplied.
+%%%
+%%% All rights reserved
+%%%
diff --git a/lib/dialyzer/test/user_SUITE_data/src/gcp.hrl b/lib/dialyzer/test/user_SUITE_data/src/gcp.hrl
new file mode 100644
index 0000000000..0b0f1246b5
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/gcp.hrl
@@ -0,0 +1,166 @@
+%%% #0. BASIC INFORMATION
+%%% ----------------------------------------------------------
+%%% %CCaseFile: gcp.hrl %
+%%% Author: EAB/UPD/AV
+%%% Description: Internal include file.
+%%% ----------------------------------------------------------
+-hrl_id('9/190 55-CNA 113 033 Ux').
+-hrl_vsn('/main/R1A/21').
+-hrl_date('2005-05-31').
+-hrl_author('uabasve').
+%%% %CCaseTemplateFile: module.hrl %
+%%% %CCaseTemplateId: 17/002 01-FEA 202 714 Ux, Rev: /main/4 %
+%%%
+%%% Copyright (C) 2000-2005 by Ericsson Telecom AB
+%%% SE-126 25 STOCKHOLM
+%%% SWEDEN, tel int + 46 8 719 0000
+%%%
+%%% The program may be used and/or copied only with the written
+%%% permission from Ericsson Telecom AB, or in accordance with
+%%% the terms and conditions stipulated in the agreement/contract
+%%% under which the program has been supplied.
+%%%
+%%% All rights reserved
+%%%
+%%% ----------------------------------------------------------
+%%% #1. REVISION LOG
+%%% ----------------------------------------------------------
+%%% Rev Date Name What
+%%% ----- ------- -------- ------------------------
+%%% R1A/1 05-02-07 uabasve Copied from EAS R7A/9
+%%% R1A/2 05-02-08 ejojmjn Removed SAAL
+%%% R1A/3- 05-03-18 uabasve Clean.
+%%% ----------------------------------------------------------
+%%%
+%%% #2. CODE
+%%% #---------------------------------------------------------
+%%% #2.1 DEFINITION OF CONSTANTS
+%%% #---------------------------------------------------------
+
+%% Keys into gcpVariables for various options/values.
+-define(TRAFFIC_DESCRIPTOR_KEY, traffic_descriptor).
+
+%% H.248 version at link creation.
+-define(INITIAL_H248_VERSION, 1).
+
+%% Exceptions for use within a module. ?MODULE is just extra protection
+%% against catching something unexpected.
+-define(THROW(Reason), throw({error, ?MODULE, ?LINE, Reason})).
+-define(CATCH(Expr), try Expr
+ catch throw: ?FAILURE(Reason) -> {error, Reason}
+ end).
+-define(FAILURE(T), {error, ?MODULE, _, T}).
+
+%% The SendHandle used by a GCP transport process must be a tuple
+%% of length >= 2 whose first two elements are the pid of the
+%% transport process and index (aka #gcpLinkTable.key) of the link
+%% upon which incoming data has arrived.
+-define(SH_PID(SendHandle), element(1, SendHandle)).
+-define(SH_LINK(SendHandle), element(2, SendHandle)).
+-define(SH_SET_PID(SendHandle, Pid), setelement(1, SendHandle, Pid)).
+
+%% Megaco process that CH and OM servers monitor. This needs to be
+%% replaced by a documented method.
+-define(MEGACO_APP, megaco_config).
+
+%% The message that gcpI:send_reply sends to the process that's waiting
+%% for an action reply.
+-define(ACTION_REPLY_MESSAGE(ActionReplies, Result),
+ {reply, ActionReplies, Result}).
+
+%%% #---------------------------------------------------------
+%%% #2.2 DEFINITION OF RECORDS
+%%% #---------------------------------------------------------
+
+-record(mg, {pref}).
+-record(mgc, {mgid}).
+
+%% User configuration that gets mapped into megaco user info by
+%% gcpLib:make_user_info/1. GCP exposes only a subset of what's
+%% possible to set in megaco.
+-record(user_config,
+ {reply_timer = 30000, %% ms to wait for reply ack
+ %% Incoming transactions:
+ pending_timer = 10000, %% ms until outgoing transaction pending
+ sent_pending_limit = 5, %% nr of outgoing pendings before 506
+ %% Outgoing transactions:
+ recv_pending_limit = infinity,%% nr of incoming pendings before fail
+ request_timer = 3000, %% ms to wait for response before resend
+ request_retries = 5, %% nr unanswered sends before fail
+ long_request_timer = 15000, %% ms to wait for reply after pending
+ long_request_retries = 5}). %% nr of pendings/timeouts before fail
+
+%% Record passed into transport implementations at transport start.
+%% Expected to be passed back to gcpTransportI.
+-record(receive_handle,
+ {megaco_receive_handle, %% passed to megaco:receive_message
+ receive_message}). %% gcpLinkTable.receive_message
+
+%%% ---------------------------------------------------------------------------
+%%% # gcpRegistrationTable
+%%%
+%%% Record containing defined MGC's/MG's (aka megaco users).
+%%% ---------------------------------------------------------------------------
+
+-record(gcpRegistrationTable,
+ {key, %% user reference (aka MG/MGC id)
+ role, %% mg | mgc
+ mid, %% H.248 mid of the MGC/MG
+ version, %% of H.248
+ callback, %% {Module, ExtraArgs}
+ config = #user_config{}}).
+
+%%% ----------------------------------------------------------
+%%% # gcpLinkTable
+%%% ----------------------------------------------------------
+
+-record(gcpLinkTable,
+ {key, %% link reference
+ endpoint, %% #mgc{} | #mg{}
+ user, %% registration table key
+ chid, %% call handler of transport
+ admin_state, %% up | down
+ op_state, %% up | down | pending | disabled
+ restart = auto, %% auto | user
+ encoding_mod, %% module implementing megaco_encoder
+ encoding_config, %% as passed to encoding_mod
+ transport_start, %% {M,F,ExtraArgs} for transport start
+ transport_data, %% arbitrary, passed to transport_mod
+ send_message, %% {default|sysrpc|transport|module, Module}
+ receive_message, %% local | {M,F,ExtraArgs} for decode node
+ tried = false, %% Only for links owned by a MG.
+ %% Used to indicate that a setup attempt
+ %% has been performed on this link.
+ t95_period = 350000}).
+
+%%% ----------------------------------------------------------
+%%% # gcpActiveLinkTable
+%%% ----------------------------------------------------------
+
+-record(gcpActiveLinkTable,
+ {key, %% {mg|mgc, MgId}
+ link, %% link reference
+ chid, %% CH the link is tied to
+ node, %% node the link is on
+ conn_handle, %% record megaco_conn_handle
+ send_handle, %% {TransportPid, LinkIdx, ...}
+ version = ?INITIAL_H248_VERSION}).
+
+%%% ----------------------------------------------------------
+%%% # gcpVariables
+%%% ----------------------------------------------------------
+
+-record(gcpVariables,
+ {key,
+ value}).
+
+%%% ----------------------------------------------------------
+%%% # gcpReplyData
+%%% ----------------------------------------------------------
+
+-record(gcpReplyData,
+ {callback, %% {Module, Args}
+ mgid,
+ user_data, %% As passed by the user on send
+ prio,
+ timestamp}).
diff --git a/lib/dialyzer/test/user_SUITE_data/src/gcpFlowControl.erl b/lib/dialyzer/test/user_SUITE_data/src/gcpFlowControl.erl
new file mode 100644
index 0000000000..8598efb5d1
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/gcpFlowControl.erl
@@ -0,0 +1,397 @@
+%%%-------------------------------------------------------------------
+%%% File : gcpFlowControl.erl
+%%% Author : EAB/UPD/AV
+%%% Description : Implements overload protection.
+%%%-------------------------------------------------------------------
+-module(gcpFlowControl).
+-id('24/190 55-CNA 113 033 Ux').
+-vsn('/main/R1A/14').
+-date('2005-05-04').
+-author('uabasve').
+%%% ----------------------------------------------------------
+%%% %CCaseTemplateFile: module.erl %
+%%% %CCaseTemplateId: 16/002 01-FEA 202 714 Ux, Rev: /main/4 %
+%%%
+%%% Copyright (C) 2001-2005 by Ericsson Telecom AB
+%%% SE-126 25 STOCKHOLM
+%%% SWEDEN, tel int + 46 8 719 0000
+%%%
+%%% The program may be used and/or copied only with the written
+%%% permission from Ericsson Telecom AB, or in accordance with
+%%% the terms and conditions stipulated in the agreement/contract
+%%% under which the program has been supplied.
+%%%
+%%% All rights reserved
+%%%
+%%%
+%%% ----------------------------------------------------------
+%%% #1. REVISION LOG
+%%% ----------------------------------------------------------
+%%% Rev Date Name What
+%%% -------- -------- -------- ------------------------
+%%% R1A/1-2 05-02-07 ejojmjn Copied from EAS R7A/11.
+%%% R1A/3-14 05-03-14 uabasve Clean.
+%%%--------------------------------------------------------------------
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_v1.hrl").
+-include("gcp.hrl").
+
+-export([send_request/4, %% user send from gcpInterface
+ receive_reply/2, %% from callback in gcpTransaction
+ init_ets_tables/1,
+ init_data/2]).
+
+-define(PRIO_INFINITY, 16).
+-define(MIN_WINDOW, 10).
+-define(MAX_WINDOW, 100).
+
+-define(BUCKET_MAX, 100).
+-define(BUCKET_THRESH_HIGH, 80).
+-define(BUCKET_THRESH_LOW, 20).
+
+-define(ALLOW_TIMEOUT, 1000).
+
+%% Holds counters for flow control in GCP
+-record(gcpFlowControlTable,
+ {key,
+ window = 50,
+ available = 50,
+ bucket = 0,
+ q = 0,
+ sent = 0, %% Counts all attempts
+ rejectable = 0, %% Counts rejectable attempts
+ t95,
+ errors = 0,
+ rejects = 0,
+ replies = 0}).
+
+-record(gcpFlowControlBitmap,
+ {key,
+ count = 0}).
+
+%%====================================================================
+%% External functions
+%%====================================================================
+
+%%--------------------------------------------------------------------
+%% Function: send_request/4
+%%
+%% Output: ok | {error, Reason}
+%%--------------------------------------------------------------------
+
+send_request(ActiveLink, TimerOptions, ActionRequests, UserData) ->
+ #gcpActiveLinkTable{key = Key,
+ conn_handle = ConnHandle}
+ = ActiveLink,
+ Prio = prio(ActionRequests),
+ incr(Key, sent),
+ case allow(Key, Prio) of
+ {true, Timestamp} ->
+ grant_request(user_data(ConnHandle),
+ Key,
+ Prio,
+ Timestamp,
+ ConnHandle,
+ TimerOptions,
+ ActionRequests,
+ UserData);
+ false ->
+ {error, rejected}
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: receive_reply/2
+%% Description:
+%%--------------------------------------------------------------------
+
+receive_reply(Key, Timestamp) ->
+ incr(Key, available),
+ incr(Key, replies),
+ release(Key),
+ report_time(Key, Timestamp).
+
+%%--------------------------------------------------------------------
+%% Func: init_ets_tables/1
+%%
+%% Returns: ok
+%%--------------------------------------------------------------------
+
+init_ets_tables(Role) ->
+ create_ets(Role, gcpFlowControlTable, #gcpFlowControlTable.key),
+ create_ets(Role, gcpFlowControlBitmap, #gcpFlowControlBitmap.key),
+ ok.
+
+create_ets(Role, Table, Pos) when integer(Pos) ->
+ create_ets(Role,
+ Table,
+ [named_table, ordered_set, public, {keypos, Pos}]);
+
+create_ets(test, Table, ArgList) ->
+ ets:new(Table, ArgList);
+create_ets(Role, Table, ArgList) ->
+ case ets:info(Table) of
+ undefined ->
+ sysCmd:ets_new(Table, ArgList);
+ _ when Role == ch ->
+ sysCmd:inherit_tables([Table]);
+ _ when Role == om ->
+ ok
+ end.
+
+%%--------------------------------------------------------------------
+%% Func: init_data/2
+%%--------------------------------------------------------------------
+
+init_data(Key, T95) ->
+ ets:insert(gcpFlowControlTable, #gcpFlowControlTable{key = Key,
+ t95 = T95}).
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+
+%%% ----------------------------------------------------------
+%%% incr
+%%% ----------------------------------------------------------
+
+cntr(Key, Field) ->
+ incr(Key, Field, 0).
+
+incr(Key, Field) ->
+ incr(Key, Field, 1).
+
+-define(INCR(Field),
+ incr(Key, Field, X) -> upd_c(Key, {#gcpFlowControlTable.Field, X})).
+
+?INCR(sent);
+?INCR(replies);
+?INCR(q);
+?INCR(t95);
+?INCR(errors);
+?INCR(rejects);
+?INCR(rejectable);
+?INCR(window);
+?INCR(available);
+
+incr(Key, bucket, X)->
+ upd_c(Key, {#gcpFlowControlTable.bucket, X, ?BUCKET_MAX, ?BUCKET_MAX}).
+
+upd_c(Key, N) ->
+ ets:update_counter(gcpFlowControlTable, Key, N).
+
+%%% ----------------------------------------------------------
+%%% decr
+%%%
+%%% Beware that decr is implemented as incr, care has to be taken
+%%% not to bungle things when max/min values are used.
+%%% ----------------------------------------------------------
+
+decr(Key, available, X) ->
+ upd_c(Key, {#gcpFlowControlTable.available, -X});
+decr(Key, window, X) ->
+ upd_c(Key, {#gcpFlowControlTable.window, -X});
+decr(Key, bucket, X) ->
+ upd_c(Key, {#gcpFlowControlTable.bucket, -X, 0, 0}).
+
+decr(Key, Field) ->
+ decr(Key, Field, 1).
+
+%%% ----------------------------------------------------------
+%%% allow
+%%% ----------------------------------------------------------
+
+allow(Key, ?PRIO_INFINITY) ->
+ decr(Key, available),
+ {true, now()};
+
+allow(Key, Prio) ->
+ incr(Key, rejectable),
+ case decr(Key, available) of
+ N when N > 0 ->
+ {true, no_stamp};
+ _ ->
+ %% We did not send it, therefore incr available again
+ incr(Key, available),
+ queue(Key, Prio)
+ end.
+
+%%% ----------------------------------------------------------
+%%% queue
+%%% ----------------------------------------------------------
+
+queue(Key, Prio) ->
+ incr(Key, q),
+ T = {Key, Prio, now(), self()},
+ ets:insert(gcpFlowControlBitmap, #gcpFlowControlBitmap{key = T}),
+ wait(T).
+
+%%% ----------------------------------------------------------
+%%% wait
+%%% ----------------------------------------------------------
+
+wait({Key, _Prio, _When, _Self} = T) ->
+ receive
+ allow ->
+ ets:delete(gcpFlowControlBitmap, T),
+ decr(Key, available),
+ {true, no_stamp}
+ after ?ALLOW_TIMEOUT ->
+ timeout(T),
+ adjust_window(Key),
+ incr(Key, rejects),
+ false
+ end.
+
+timeout(T) ->
+ case ets:update_counter(gcpFlowControlBitmap, T, 1) of
+ 1 ->
+ %% Got the lock: no one has released Key and sent 'allow'.
+ ets:delete(gcpFlowControlBitmap, T),
+ ok;
+ _ ->
+ %% A releasing process got the lock: 'allow' has been
+ %% sent. Try to remove the message before proceeding.
+ %% (This is to keep mdisp from complaining apparently.)
+ ets:delete(gcpFlowControlBitmap, T),
+ receive
+ allow ->
+ ok
+ after ?ALLOW_TIMEOUT ->
+ io:format("~p: errant allow: ~p~n", [?MODULE, T])
+ end
+ end.
+
+%% Now, if we reject and our general response time is low
+%% (i.e. low bucket) then we increase the window size.
+adjust_window(Key) ->
+ adjust_window(Key,
+ cntr(Key, bucket) < ?BUCKET_THRESH_LOW
+ andalso cntr(Key, window) < ?MAX_WINDOW).
+
+adjust_window(Key, true) ->
+ incr(Key, window),
+ incr(Key, available),
+ incr(Key, bucket, 20);
+adjust_window(_, false) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Func: report_time/2
+%%--------------------------------------------------------------------
+
+report_time(_, no_stamp) ->
+ ok;
+report_time(Key, {MS, S, Ms})->
+ {MegaSecs, Secs, MicroSecs} = now(),
+ p(Key,
+ MicroSecs - Ms + 1000000*(Secs - S + 1000000*(MegaSecs - MS)),
+ cntr(Key, t95)).
+
+%%% ----------------------------------------------------------
+%%% p
+%%% ----------------------------------------------------------
+
+p(Key, Time, T95) when Time =< T95 ->
+ decr(Key, bucket);
+p(Key, _Time, _T95) ->
+ %% If we have a long response time, then increase the leaky
+ %% bucket. If the bucket is over the high watermark and the window
+ %% is not already at its minimum size, then decrease the window
+ %% and available.
+ case {cntr(Key, window), incr(Key, bucket, 20)} of
+ {Window, Bucket} when Window > ?MIN_WINDOW,
+ Bucket > ?BUCKET_THRESH_HIGH ->
+ decr(Key, window),
+ decr(Key, available);
+ _ ->
+ ok
+ end.
+
+%%% ----------------------------------------------------------
+%%% release
+%%% ----------------------------------------------------------
+
+release(Key) ->
+ %% The choice of the key below will cause ets:prev/2 to return
+ %% the key with the highest priority which was queued most
+ %% recently. This relies on the fact that integers sort before
+ %% atoms, the atom 'prio' in this case. The atoms 'queued' and
+ %% 'pid' are of no significance.
+ release(Key, {Key, prio, queued, pid}).
+
+%% This isn't a (FIFO) queue within each priority, but a (LIFO) stack.
+
+release(Key, T) ->
+ release(Key, cntr(Key, available), ets:prev(gcpFlowControlBitmap, T)).
+
+%% Note that only keys on the same Key are matched.
+release(Key, N, {Key, _Prio, _When, Pid} = T) when N > 0 ->
+ case catch ets:update_counter(gcpFlowControlBitmap, T, 1) of
+ 1 ->
+ Pid ! allow;
+ _ ->
+ %% Another process has released this key.
+ release(Key, T)
+ end;
+
+release(_, _, _)->
+ ok.
+
+%%% ----------------------------------------------------------
+%%% user_data
+%%% ----------------------------------------------------------
+
+user_data(ConnHandle) ->
+ case catch megaco:conn_info(ConnHandle, reply_data) of
+ {'EXIT', _Reason} ->
+ false;
+ Rec ->
+ {value, Rec}
+ end.
+
+%%% ----------------------------------------------------------
+%%% grant_request
+%%% ----------------------------------------------------------
+
+grant_request({value, Rec},
+ Key, Prio, Time,
+ ConnHandle, Options, ActionRequests, UserData) ->
+ ReplyData = Rec#gcpReplyData{user_data = UserData,
+ prio = Prio,
+ timestamp = Time},
+ cast_rc(megaco:cast(ConnHandle,
+ ActionRequests,
+ [{reply_data, ReplyData} | Options]),
+ Key,
+ ActionRequests);
+
+grant_request(false, Key, _, _, _, _, _, _) ->
+ incr(Key, available),
+ {error, reply_data}.
+
+cast_rc(ok = Ok, _, _) ->
+ Ok;
+cast_rc({error, Reason}, Key, ActionRequests) ->
+ incr(Key, available),
+ gcpLib:error_report(?MODULE, send_request, [ActionRequests],
+ "send failed",
+ Reason),
+ {error, {encode, Reason}}.
+
+%%--------------------------------------------------------------------
+%% Func: prio/1
+%% Returns: The priority of the request
+%%--------------------------------------------------------------------
+
+prio([ActionRequest | _]) ->
+ #'ActionRequest'{contextId = ContextId,
+ contextRequest = ContextRequest}
+ = ActionRequest,
+ prio(ContextId, ContextRequest).
+
+prio(?megaco_choose_context_id, #'ContextRequest'{priority = Prio})
+ when integer(Prio) ->
+ Prio;
+prio(_, _) ->
+ ?PRIO_INFINITY.
diff --git a/lib/dialyzer/test/user_SUITE_data/src/qlc_error.erl b/lib/dialyzer/test/user_SUITE_data/src/qlc_error.erl
new file mode 100644
index 0000000000..04e621dd4b
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/qlc_error.erl
@@ -0,0 +1,15 @@
+%% -*- erlang-indent-level: 2 -*-
+%% $Id: qlc_error.erl,v 1.1 2008/12/17 09:53:52 mikpe Exp $
+
+%% @author Daniel Luna <[email protected]>
+%% @copyright 2006 Daniel Luna
+%%
+%% @doc
+%%
+
+-module(qlc_error).
+-export([fix/0]).
+-include_lib("stdlib/include/qlc.hrl").
+
+fix() ->
+ qlc:eval(qlc:q([I || I <- []])).
diff --git a/lib/dialyzer/test/user_SUITE_data/src/spvcOrig.erl b/lib/dialyzer/test/user_SUITE_data/src/spvcOrig.erl
new file mode 100644
index 0000000000..279caffdde
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/spvcOrig.erl
@@ -0,0 +1,3520 @@
+%%%=======================================================================
+%%%
+%%% Test from Mats Cronqvist <[email protected]>. The
+%%% analysis crasched due to the handling of tuples-as-funs in
+%%% hipe_icode_type.erl, and it also exposed a bug when a control flow
+%%% path is first analyzed and then shown to be infeasible.
+%%%
+
+-file("./spvcOrig.erl", 1).
+
+-module(spvcOrig).
+
+-author(qamarma).
+
+-id('3/190 55-CNA 121 64').
+
+-vsn('/main/Inc4/R2A/R4A/R6A/R7A/R7D/R8B/R10A/R11A/2').
+
+-date('2004-10-26').
+
+-export([gen_set/3,gen_set/4,connect/3,release_comp_nu/3,release_nu/3,timeout/2,restart_spvc/1,restart_multi_spvcs/1,forced_release/1,error_handler/3,get_backoff_table/2,timeout_event/1]).
+
+-export([release_incumbent/2,switch_over/2]).
+
+-export([call_failure/1,get_backoff_table/2]).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/pchTables.hrl", 1).
+
+-hrl_id('2/190 55-CNA 121 08').
+
+-hrl_vsn('/main/Inc3/Inc4/R2A/R3A/R3B/R5A/R6A/R7A/R7D/R8B/13').
+
+-hrl_date('2003-01-24').
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../derived_hrl/mib/AXD301-PCH-MIB.hrl", 1).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/pchTables.hrl", 58).
+
+-record(pchVp, {vplEntry,
+ vplLastChange,
+ vplReceiveTrafficDescrIndex = 0,
+ vplTransmitTrafficDescrIndex = 0,
+ vplCcIdentifier,
+ vplConnId,
+ vplMpId,
+ vplLeafId,
+ vplChargingIndicator = 1,
+ vplRemoteChargingInd = 1,
+ vplChargablePartyIdentifier,
+ vplSegmentEndPoint = 2,
+ vplRowStatus,
+ vplCastType = 1,
+ vplConnKind = 1,
+ vplServiceType = 2,
+ vplEndPointData,
+ vplContinuityCheck = 1,
+ vplUpcNpcMode = 2,
+ vplPreventInbandCc = 1,
+ vplMonAisRdi = 2,
+ vpcAdminStatus = 2,
+ vplSpvcAutoTarget = 2,
+ vplSchedulingFlag = 2,
+ vplApplication,
+ vplRemoteData,
+ vpccAdminStatus = 2,
+ vplContCheckSearch = 1,
+ vplPmSearch = 1,
+ vplLastBuffFlagRead,
+ vplShapingMode = 1,
+ vplGroupShapingId}).
+
+-record(pchVpDb, {vplEntry,
+ vplLastChange,
+ vplReceiveTrafficDescrIndex = 0,
+ vplTransmitTrafficDescrIndex = 0,
+ vplCcIdentifier,
+ vplConnId,
+ vplMpId,
+ vplLeafId,
+ vplAttributes,
+ vplChargablePartyIdentifier,
+ vplRowStatus,
+ vplEndPointData,
+ vplApplication,
+ vplRemoteData,
+ vplLastBuffFlagRead,
+ vplShapingMode,
+ vplGroupShapingId}).
+
+-record(pchVpExt, {vplExtEntry,
+ vplExtReceiveTdIndex,
+ vplExtTransmitTdIndex,
+ vplExtUserName = [],
+ vplExtProviderName = [],
+ vplExtUserOperator}).
+
+-record(pchVc, {vclEntry,
+ vclLastChange,
+ vclReceiveTrafficDescrIndex = 0,
+ vclTransmitTrafficDescrIndex = 0,
+ vclCcIdentifier,
+ vclConnId,
+ vclMpId,
+ vclLeafId,
+ vclChargingIndicator = 1,
+ vclRemoteChargingInd = 1,
+ vclChargablePartyIdentifier,
+ vclPacketDiscard = 2,
+ vclSegmentEndPoint = 2,
+ vclRowStatus,
+ vclCastType = 1,
+ vclConnKind = 1,
+ vclContinuityCheck = 1,
+ vclUpcNpcMode = 2,
+ vclEndPointData,
+ vclPreventInbandCc = 1,
+ vclMonAisRdi = 2,
+ vclSpvcAutoTarget = 2,
+ vclSchedulingFlag = 2,
+ vclApplication,
+ vclRemoteData,
+ vcccAdminStatus = 2,
+ vclContCheckSearch = 1,
+ vclPmSearch = 1,
+ vclLastBuffFlagRead,
+ vclChargingIfChanid,
+ vclShapingMode = 1}).
+
+-record(pchVcDb, {vclEntry,
+ vclLastChange,
+ vclReceiveTrafficDescrIndex = 0,
+ vclTransmitTrafficDescrIndex = 0,
+ vclCcIdentifier,
+ vclConnId,
+ vclMpId,
+ vclLeafId,
+ vclAttributes,
+ vclChargablePartyIdentifier,
+ vclRowStatus,
+ vclEndPointData,
+ vclApplication,
+ vclRemoteData,
+ vclLastBuffFlagRead,
+ vclChargingIfChanid,
+ vclShapingMode}).
+
+-record(pchAtd, {tdIndex,
+ tdType,
+ tdParam1 = 0,
+ tdParam2 = 0,
+ tdParam3 = 0,
+ tdParam4 = 0,
+ tdParam5 = 0,
+ tdTrafficQoSClass = 0,
+ tdRowStatus = 1,
+ tdServiceCategory = 6,
+ tdVcCapability = 1,
+ tdName = [],
+ tdUserCounter = 0,
+ tdUser = []}).
+
+-record(pchAbr, {abrIndex,
+ abrIcr,
+ abrTbe = 16277215,
+ abrFrtt = 0,
+ abrRdf = 11,
+ abrRif = 11,
+ abrNrm = 4,
+ abrTrm = 7,
+ abrCdf = 3,
+ abrAdtf = 50,
+ abrRowStatus = 1}).
+
+-record(pchIndexNext, {key,
+ tdIndexNext,
+ vpccIndexNext,
+ vcccIndexNext,
+ scheduledVpCcIndexNext,
+ scheduledVcCcIndexNext}).
+
+-record(pchSchedVpCc, {schedVpCcIndex,
+ schedVpCcTarget,
+ schedVpCcReceiveTdIndex,
+ schedVpCcTransmitTdIndex,
+ schedVpCcOpTime,
+ schedVpCcOpInd,
+ schedVpCcOpStatus,
+ schedVpCcTimerRef,
+ schedVpCcRowStatus,
+ schedVpCcErrorCode,
+ schedVpCcUserName = [],
+ schedVpCcProviderName = []}).
+
+-record(pchVpCc, {vpccId,
+ vpccUserName = [],
+ vpccAdminStatus,
+ vpccApplication,
+ vpccProviderName = []}).
+
+-record(pchSchedVcCc, {schedVcCcIndex,
+ schedVcCcTarget,
+ schedVcCcReceiveTdIndex,
+ schedVcCcTransmitTdIndex,
+ schedVcCcOpTime,
+ schedVcCcOpInd,
+ schedVcCcOpStatus,
+ schedVcCcTimerRef,
+ schedVcCcRowStatus,
+ schedVcCcErrorCode,
+ schedVcCcUserName = [],
+ schedVcCcProviderName = []}).
+
+-record(pchVcCc, {vcccId,
+ vcccUserName = [],
+ vcccAdminStatus,
+ vcccApplication,
+ vcccProviderName = []}).
+
+-record(pchSigChannels, {et_entry,
+ cp_entry,
+ sb_cp_entry,
+ membership,
+ status,
+ sb_status,
+ application = {0,[]}}).
+
+-record(pchSigChannelExt, {et_entry,
+ user_name,
+ provider_name}).
+
+-record(pchApplication, {key,
+ application,
+ rights}).
+
+-record(pchCurrAlarm, {key,
+ type_of_fault,
+ fault_id}).
+
+-record(pchIfAddress, {ifAddressEntry,
+ ifAddressRowStatus}).
+
+-record(pchAddressToIf, {address,
+ if_index}).
+
+-record(pchPreferences, {key,
+ if_format}).
+
+-record(pchSigChannelCallback, {key,
+ callback,
+ function,
+ args,
+ data}).
+
+-record(pchTermHcId, {hcId,
+ vclEntry}).
+
+-record(pchChg, {chgEntry,
+ chgStatus}).
+
+-record(pchCommState, {key,
+ ccid,
+ request,
+ low_cp_state,
+ high_cp_state,
+ et_side,
+ application,
+ data,
+ timestamp,
+ timer_id,
+ callback}).
+
+-record(pchBufferedCmd, {key,
+ resource,
+ module,
+ function,
+ arguments,
+ data}).
+
+-record(pchAnswerCh, {conn_id,
+ chg_data,
+ call_back_cp,
+ old_rtd,
+ old_ttd,
+ old_EpData,
+ action,
+ resource,
+ data,
+ fail_cause}).
+
+-record(pchAnswerOm, {conn_id}).
+
+-record(ccPch, {rowInd,
+ admState = 2}).
+
+-record(pchIf, {ilmiVpi = 0,
+ ilmiVci = 0,
+ ilmiS = 1,
+ ilmiT = 5,
+ ilmiK = 4,
+ neighborIfName = [],
+ neighborIpAddr = [0,0,0,0],
+ maxVciSvc,
+ overbookingFactor = {0,0},
+ shapingMode = 0,
+ maxVpiSvc,
+ cdvtMultFactor = 100,
+ scBandwidth1 = 0,
+ scBandwidth2 = 0,
+ scBandwidth3 = 0,
+ scBandwidth4 = 0}).
+
+-record(pchMpTemp, {key,
+ data}).
+
+-record(pchLatestErrorCode, {key,
+ errorCode}).
+
+-record(pchRangeTable, {node,
+ tdIndexRange,
+ vpccIndexRange,
+ vcccIndexRange}).
+
+-record(pchIndexBitmaps, {key,
+ available,
+ bitmap}).
+
+-record(pchLinkState, {key,
+ op_state,
+ last_change}).
+
+-record(pchFailedVpl, {vplEntry,
+ vplLastChange}).
+
+-record(pchFailedVcl, {vclEntry,
+ vclLastChange}).
+
+-record(pchStatCounters, {key,
+ ingress,
+ egress}).
+
+-record(pchEtStatTable, {index,
+ value = 0}).
+
+-record(pchAuditResult, {key,
+ passed,
+ not_passed,
+ sizes,
+ obj_keys}).
+
+-record(pch_fault_reqc, {fault_type,
+ fault_location}).
+
+-record(pch_cid, {conn_id,
+ mp_id,
+ leaf_id}).
+
+-file("./spvcOrig.erl", 207).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/pchI.hrl", 1).
+
+-hrl_id('52/190 55-CNA 121 08 Ux').
+
+-hrl_vsn('/main/R6A/R7A/R7D/R8B/3').
+
+-hrl_date('2002-10-14').
+
+-hrl_author(uabdomo).
+
+-record(pch_vc_rec, {ifIndex,
+ vpi,
+ vci,
+ application}).
+
+-record(pch_vp_rec, {ifIndex,
+ vpi}).
+
+-record(pch_td_index, {rtd_index,
+ ttd_index}).
+
+-record(pch_td, {service_cat,
+ pcr,
+ scr,
+ mbs,
+ mcr,
+ cdvt,
+ tagging,
+ clp_significance}).
+
+-record(pch_call_back_req, {module,
+ function,
+ user_data}).
+
+-record(pch_chg_rec, {chg_type,
+ chg_interface,
+ chg_chan_id,
+ chg_party_name}).
+
+-record(pch_polic_rec, {policing,
+ packet_discard}).
+
+-record(pch_user_name_rec, {user_name}).
+
+-record(pch_shaping_rec, {shaping}).
+
+-record(pch_audit_callback, {mod,
+ arg}).
+
+-file("./spvcOrig.erl", 208).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/plc.hrl", 1).
+
+-hrl_id('12/190 55-CNA 121 45 Ux').
+
+-hrl_vsn('/main/R6A/R6B/R7A/R7D/R8B/R9A/R11A/4').
+
+-hrl_date('2004-12-07').
+
+-hrl_author(ethrba).
+
+-record(plcQueues, {name,
+ type,
+ weight,
+ maxlength,
+ owner}).
+
+-record(plcSettings, {flag,
+ value}).
+
+-record(plcAlarm, {flag,
+ value}).
+
+-file("./spvcOrig.erl", 209).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/spvcTables.hrl", 1).
+
+-hrl_id('10/190 55-CNA 121 64').
+
+-hrl_vsn('/main/Inc4/R2A/R3A/R3B/R5A/R6A/R7A/R7D/R8B/4').
+
+-hrl_date('2003-02-12').
+
+-hrl_author(etxovp).
+
+-record(spvcVpc, {spvcVpcEntry,
+ spvcVpcTargetAddress,
+ spvcVpcTargetSelectType,
+ spvcVpcTargetVpi,
+ spvcVpcLastReleaseCause,
+ spvcVpcLastReleaseDiagnostic,
+ spvcVpcRetryInterval = 1000,
+ spvcVpcRetryTimer = 0,
+ spvcVpcRetryThreshold = 1,
+ spvcVpcRetryFailures = 0,
+ spvcVpcRetryLimit = 15,
+ spvcVpcRowStatus,
+ spvcVpcUserName = [],
+ spvcVpcProviderName = [],
+ currentState,
+ crankBackCounter = 0,
+ spvcVpcApplication,
+ spvcRerCap = false,
+ spvcRerStatus = false}).
+
+-record(spvcVpcOpState, {state,
+ timeOfChange}).
+
+-record(spvcVpcPerm, {spvcVpcEntry,
+ spvcVpcTargetAddress,
+ spvcVpcTargetSelectType,
+ spvcVpcTargetVpi,
+ spvcVpcRetryInterval = 1000,
+ spvcVpcRetryThreshold = 1,
+ spvcVpcRetryLimit = 15,
+ spvcVpcRowStatus,
+ spvcVpcUserName,
+ spvcVpcProviderName,
+ spvcVpcApplication}).
+
+-record(spvcVpcDyn, {spvcVpcEntry,
+ spvcVpcLastReleaseCause,
+ spvcVpcLastReleaseDiagnostic,
+ spvcVpcRetryTimer = 0,
+ spvcVpcRetryFailures = 0,
+ currentState,
+ crankBackCounter = 0}).
+
+-record(spvcVcc, {spvcVccEntry,
+ spvcVccTargetAddress,
+ spvcVccTargetSelectType,
+ spvcVccTargetVpi,
+ spvcVccTargetVci,
+ spvcVccLastReleaseCause,
+ spvcVccLastReleaseDiagnostic,
+ spvcVccRetryInterval = 1000,
+ spvcVccRetryTimer = 0,
+ spvcVccRetryThreshold = 1,
+ spvcVccRetryFailures = 0,
+ spvcVccRetryLimit = 15,
+ spvcVccRowStatus,
+ spvcVccUserName = [],
+ spvcVccProviderName = [],
+ currentState,
+ crankBackCounter = 0,
+ spvcVccTargetDlci,
+ spvcVccTargetType,
+ spvcVccApplication,
+ spvcVccFrKey,
+ spvcVccTranslationMode,
+ spvcRerCap = false,
+ spvcRerStatus = false}).
+
+-record(spvcVccOpState, {state,
+ timeOfChange}).
+
+-record(spvcVccPerm, {spvcVccEntry,
+ spvcVccTargetAddress,
+ spvcVccTargetSelectType,
+ spvcVccTargetVpi,
+ spvcVccTargetVci,
+ spvcVccRetryInterval = 1000,
+ spvcVccRetryThreshold = 1,
+ spvcVccRetryLimit = 15,
+ spvcVccRowStatus,
+ spvcVccUserName,
+ spvcVccProviderName,
+ spvcVccTargetDlci,
+ spvcVccTargetType,
+ spvcVccApplication,
+ spvcVccFrKey,
+ spvcVccTranslationMode = 2}).
+
+-record(spvcVccDyn, {spvcVccEntry,
+ spvcVccLastReleaseCause,
+ spvcVccLastReleaseDiagnostic,
+ spvcVccRetryTimer = 0,
+ spvcVccRetryFailures = 0,
+ currentState,
+ crankBackCounter = 0}).
+
+-record(spvcFailures, {dummy_key,
+ spvcCallFailuresTrapEnable = 2,
+ spvcNotificationInterval = 30,
+ backoff_interval = 0.100000,
+ delay_factor = 2,
+ max_delay = 200000}).
+
+-record(spvcCounters, {key,
+ value}).
+
+-record(spvcEventIndicator, {dummy_key,
+ spvcTimerInd = 2,
+ spvcSendEventInd = 2}).
+
+-record(spvcIndexNext, {dummy_key,
+ schedVccIndexNext = 1,
+ schedVpcIndexNext = 1}).
+
+-record(spvcHcIdToTp, {hcId,
+ tpEntry}).
+
+-record(spvcTpToHcId, {tpEntry,
+ hcId,
+ orig_number,
+ orig_vpi,
+ orig_vci,
+ orig_dlci,
+ frKey}).
+
+-record(spvcSchedVpc, {schedVpcIndex,
+ schedVpcSource,
+ schedVpcTargetAddr,
+ schedVpcTargetSelType,
+ schedVpcTargetVpi,
+ schedVpcRetryInt,
+ schedVpcRetryThres,
+ schedVpcRetryLimit,
+ schedVpcOpTime,
+ schedVpcOpInd,
+ schedVpcOpStatus,
+ schedVpcTimerRef,
+ schedVpcRowStatus,
+ schedVpcUserName,
+ schedVpcProviderName,
+ schedVpcFaultCause,
+ schedVpcRerCap = false}).
+
+-record(spvcSchedVcc, {schedVccIndex,
+ schedVccSource,
+ schedVccTargetAddr,
+ schedVccTargetSelType,
+ schedVccTargetVpi,
+ schedVccTargetVci,
+ schedVccRetryInt,
+ schedVccRetryThres,
+ schedVccRetryLimit,
+ schedVccOpTime,
+ schedVccOpInd,
+ schedVccOpStatus,
+ schedVccTimerRef,
+ schedVccRowStatus,
+ schedVccUserName,
+ schedVccProviderName,
+ schedVccFaultCause,
+ schedVccRerCap = false}).
+
+-record(spvcCurrAlarm, {key,
+ fault_id,
+ data}).
+
+-record(spvcChg, {key,
+ data}).
+
+-record(spvcBackoff, {key,
+ delay_time,
+ flag}).
+
+-record(spvcAutoVp, {entry,
+ lastChange,
+ receiveTrafficDescrIndex,
+ transmitTrafficDescrIndex,
+ ccIdentifier,
+ connId,
+ mpId,
+ leafId,
+ chargingIndicator = 1,
+ remoteChargingInd = 1,
+ chargablePartyIdentifier,
+ segmentEndPoint = 2,
+ rowStatus,
+ castType = 1,
+ connKind,
+ serviceType = 2,
+ endPointData,
+ continuityCheck = 1,
+ upcNpcMode = 2,
+ preventInbandCc = 1,
+ monAisRdi = 2,
+ adminStatus,
+ autoTarget = 1,
+ schedulingFlag = 2,
+ application = [],
+ remoteData,
+ vpccAdminStatus = 2,
+ contCheckSearch = 1,
+ pmSearch = 1,
+ lastBuffFlagRead,
+ shapingMode = 1,
+ groupShapingId}).
+
+-record(spvcAutoVc, {entry,
+ lastChange,
+ receiveTrafficDescrIndex,
+ transmitTrafficDescrIndex,
+ ccIdentifier,
+ connId,
+ mpId,
+ leafId,
+ chargingIndicator = 1,
+ remoteChargingInd = 1,
+ chargablePartyIdentifier,
+ packetDiscard = 2,
+ segmentEndPoint = 2,
+ rowStatus,
+ castType = 1,
+ connKind,
+ continuityCheck = 1,
+ upcNpcMode = 2,
+ endPointData,
+ preventInbandCc = 1,
+ monAisRdi = 2,
+ autoTarget = 1,
+ schedulingFlag = 2,
+ application = [],
+ remoteData,
+ vcccAdminStatus = 2,
+ contCheckSearch = 1,
+ pmSearch = 1,
+ lastBuffFlagRead,
+ chargingIfChanid,
+ shapingMode = 1}).
+
+-record(spvcAutoAtd, {index,
+ type,
+ param1 = 0,
+ param2 = 0,
+ param3 = 0,
+ param4 = 0,
+ param5 = 0,
+ trafficQoSClass = 0,
+ rowStatus = 1,
+ serviceCategory = 6,
+ vcCapability = 1,
+ name = [],
+ userCounter = 0}).
+
+-record(spvcAutoAbr, {index,
+ icr,
+ tbe = 16277215,
+ frtt = 0,
+ rdf = 11,
+ rif = 11,
+ nrm = 4,
+ trm = 7,
+ cdf = 3,
+ adtf = 50,
+ rowStatus = 1}).
+
+-record(spvcLatestErrorCode, {key,
+ errorCode}).
+
+-record(spvcVcDyn, {vclEntry,
+ vclCcIdentifier,
+ vclConnId,
+ vclMpId,
+ vclLeafId}).
+
+-record(spvcVpDyn, {vplEntry,
+ vplCcIdentifier,
+ vplConnId,
+ vplMpId,
+ vplLeafId}).
+
+-record(spvcObj, {spvcEntry,
+ spvcTargetAddress,
+ spvcTargetSelectType,
+ spvcTargetVpi,
+ spvcTargetVci,
+ spvcLastReleaseCause,
+ spvcLastReleaseDiagnostic,
+ spvcRetryInterval = 1000,
+ spvcRetryTimer = 0,
+ spvcRetryThreshold = 1,
+ spvcRetryFailures = 0,
+ spvcRetryLimit = 15,
+ spvcRowStatus,
+ spvcUserName,
+ spvcProviderName,
+ currentState,
+ spvcTargetDlci,
+ spvcTargetType,
+ spvcApplication,
+ spvcFrKey,
+ spvcVccTranslationMode = 2,
+ spvcRerCap = false,
+ spvcRerStatus = false}).
+
+-record(spvcTargetVc, {entry,
+ userName = [],
+ providerName = [],
+ opState,
+ rowStatus}).
+
+-record(spvcTargetVp, {entry,
+ userName = [],
+ providerName = [],
+ opState,
+ rowStatus}).
+
+-record(spvcReestablishTimer, {time,
+ timer_id,
+ module,
+ function,
+ args}).
+
+-record(spvcRerVp, {entry,
+ rerCap,
+ rerData}).
+
+-record(spvcRerVc, {entry,
+ rerCap,
+ rerData}).
+
+-record(spvcHcEtStat, {key,
+ counter = 0}).
+
+-record(spvcSaEtStat, {key,
+ counter = 0}).
+
+-file("./spvcOrig.erl", 210).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/spvcDefines.hrl", 1).
+
+-hrl_id('41/190 55-CNA 121 64 Ux').
+
+-hrl_vsn('/main/R6A/R7A/R7D/R8B/3').
+
+-hrl_date('2003-02-21').
+
+-hrl_author(etxhebl).
+
+-file("./spvcOrig.erl", 211).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/spvcFr.hrl", 1).
+
+-hrl_id('48/190 55-CNA 121 64 Ux').
+
+-hrl_vsn('/main/R7A/R7D/2').
+
+-hrl_date('2001-12-06').
+
+-hrl_author(etxhtb).
+
+-record(spvcFr, {spvcFrEntry,
+ spvcFrAtmEntry,
+ spvcFrTargetAddress,
+ spvcFrTargetSelectType,
+ spvcFrTargetIdentifier,
+ spvcFrTargetVpi,
+ spvcFrTargetVci,
+ spvcFrAtmTranslation,
+ spvcFrLastReleaseCause,
+ spvcFrLastReleaseDiagnostic,
+ spvcFrAdminStatus,
+ spvcFrRetryInterval = 1000,
+ spvcFrRetryTimer = 0,
+ spvcFrRetryThreshold = 1,
+ spvcFrRetryFailures = 0,
+ spvcFrRetryLimit = 15,
+ spvcFrRowStatus,
+ spvcFrUserName,
+ spvcFrProviderName,
+ currentState}).
+
+-record(spvcFrPerm, {spvcFrEntry,
+ spvcFrAtmEntry,
+ spvcFrAtmTranslation,
+ spvcFrAdminStatus,
+ spvcFrConnect}).
+
+-record(spvcFrAddress, {addressEntry,
+ addressRowStatus}).
+
+-record(spvcFrAddressToIf, {address,
+ if_index}).
+
+-record(fr_end_point, {ifIndex,
+ dlci}).
+
+-record(fr_atm_translation, {routedIp = off,
+ routedOsi = off,
+ otherRouted = off,
+ arpTranslation = off}).
+
+-record(link_layer_core_parameters, {outgoing_max_ifs,
+ incoming_max_ifs}).
+
+-record(priority_and_service_class, {outgoing_transfer_priority,
+ incoming_transfer_priority,
+ outgoing_discard_priority,
+ incoming_discard_priority}).
+
+-file("./spvcOrig.erl", 212).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../derived_hrl/mib/AXD301-PCH-MIB.hrl", 1).
+
+-file("./spvcOrig.erl", 213).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../derived_hrl/mib/AXD301-SPVC-MIB.hrl", 1).
+
+-file("./spvcOrig.erl", 214).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../derived_hrl/mib/AXD301-FRSPVC-MIB.hrl", 1).
+
+-file("./spvcOrig.erl", 215).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/sysDefines.hrl", 1).
+
+-hrl_id('3/190 55-CNA 121 70').
+
+-hrl_vsn('/main/Inc3/Inc4/Inc5/R3B/R4A/R5B/R6A/R7A/R8B/2').
+
+-hrl_date('2002-06-07').
+
+-hrl_author(etxjotj).
+
+-file("./spvcOrig.erl", 216).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/hciMsg.hrl", 1).
+
+-hrl_id('4/190 55-CNA 121 159 Ux').
+
+-hrl_vsn('/main/R7A/R8B/10').
+
+-hrl_date('2003-02-21').
+
+-hrl_author(etxmexa).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/hciComp.hrl", 1).
+
+-hrl_id('3/190 55-CNA 121 159 Ux').
+
+-hrl_vsn('/main/R7A/1').
+
+-hrl_date('00-03-22').
+
+-hrl_author(etxmexa).
+
+-record(hci_comp_info, {required_FC = 0,
+ desired_FC = 0}).
+
+-record(hci_comp_res, {not_supported_required_FCs,
+ not_supported_desired_FCs,
+ all_supported_FCs}).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/hciMsg.hrl", 14).
+
+-record(hci_add_party, {hci_cpn,
+ hci_aal,
+ hci_bhli,
+ hci_blli,
+ hci_blli_bici,
+ hci_bsco,
+ hci_epr,
+ hci_e2etd,
+ hci_noti,
+ hci_cpsa,
+ hci_clpn,
+ hci_clpsa,
+ hci_cpn_soft,
+ hci_clpn_soft,
+ hci_geidt_list = [],
+ hci_dtl_bin_list = [],
+ hci_pa_list = [],
+ hci_gat_list = [],
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_add_party_ack, {hci_epr,
+ hci_aal,
+ hci_blli,
+ hci_blli_bici,
+ hci_e2etd,
+ hci_noti,
+ hci_cpn_soft,
+ hci_cnosa,
+ hci_cno,
+ hci_geidt_list = [],
+ hci_pa_list = [],
+ hci_gat_list = [],
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_add_party_rej, {hci_cause,
+ hci_epr,
+ hci_geidt_list = [],
+ hci_cb,
+ hci_pa_list = [],
+ hci_internal_rel_info,
+ hci_gat_list = [],
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_alerting, {hci_mci,
+ hci_unrps,
+ hci_cdpi,
+ hci_epr,
+ hci_prog_list = [],
+ hci_nbc,
+ hci_nbhlc,
+ hci_noti,
+ hci_geidt_list = [],
+ hci_pa_list = [],
+ hci_gat_list = [],
+ hci_ssie,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_b_resources, {hci_rem_dataB,
+ hci_vpiB,
+ hci_vciB,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_connect, {hci_mci,
+ hci_unrps,
+ hci_aal,
+ hci_blli,
+ hci_blli_bici,
+ hci_epr,
+ hci_atd,
+ hci_e2etd,
+ hci_noti,
+ hci_abrs,
+ hci_abra,
+ hci_nbc,
+ hci_nbhlc,
+ hci_nbllc,
+ hci_prog_list = [],
+ hci_geidt_list = [],
+ hci_eqos,
+ hci_cpn_soft,
+ hci_cnosa,
+ hci_cno,
+ hci_pa_list = [],
+ hci_gat_list = [],
+ hci_rem_dataB,
+ hci_con_dir = both,
+ hci_ssie,
+ hci_rer_services,
+ hci_rer,
+ hci_opt_traf,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_drop_party, {hci_cause,
+ hci_epr,
+ hci_noti,
+ hci_geidt_list = [],
+ hci_pa_list = [],
+ hci_internal_rel_info,
+ hci_gat_list = [],
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_local_connect, {hci_rem_data,
+ hci_con_dir,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_local_connected, {hci_rem_data,
+ hci_con_dir,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_local_disconnect, {hci_discon_dir,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_local_disconnected, {hci_data,
+ hci_prot_comp}).
+
+-record(hci_notify, {hci_epr,
+ hci_noti,
+ hci_pa_list = [],
+ hci_gat_list = [],
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_party_alerting, {hci_epr,
+ hci_noti,
+ hci_geidt_list = [],
+ hci_pa_list = [],
+ hci_gat_list = [],
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_progress, {hci_mci,
+ hci_unrps,
+ hci_cdpi,
+ hci_prog_list = [],
+ hci_nbc,
+ hci_nbhlc,
+ hci_noti,
+ hci_pa_list = [],
+ hci_gat_list = [],
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_release, {hci_mci,
+ hci_unrps,
+ hci_cause_list = [],
+ hci_noti,
+ hci_prog_list = [],
+ hci_geidt_list = [],
+ hci_cb,
+ hci_pa_list = [],
+ hci_internal_rel_info,
+ hci_gat_list = [],
+ hci_ssie,
+ hci_rer_cause,
+ hci_data,
+ hci_prot_comp,
+ hci_internal_dbg_cc,
+ hci_internal_dbg_l3}).
+
+-record(hci_setup, {hci_mci,
+ hci_unrps,
+ hci_atd,
+ hci_bbc,
+ hci_qos,
+ hci_cpn,
+ hci_aal,
+ hci_bhli,
+ hci_blli_brep,
+ hci_blli_bici,
+ hci_bsco,
+ hci_epr,
+ hci_lpt,
+ hci_e2etd,
+ hci_noti,
+ hci_abrs,
+ hci_abra,
+ hci_prog_list = [],
+ hci_eqos,
+ hci_cpsa_list = [],
+ hci_clpn,
+ hci_bici_clpn,
+ hci_clpsa_list = [],
+ hci_cgpc,
+ hci_nbc_brep,
+ hci_nbhlc_list = [],
+ hci_nbllc_brep,
+ hci_conss,
+ hci_geidt_list = [],
+ hci_cpn_soft,
+ hci_clpn_soft,
+ hci_dtl_bin_list = [],
+ hci_pa_list = [],
+ hci_ncci,
+ hci_routing_address,
+ hci_protocol_internal_info,
+ hci_gat_list = [],
+ hci_con_dir = both,
+ hci_ssie,
+ hci_rer_services,
+ hci_rer,
+ hci_opt_traf,
+ hci_data_setup,
+ hci_prot_comp}).
+
+-record(hci_setup_ack, {hci_assign,
+ hci_rem_dataB,
+ hci_con_dir = both,
+ hci_vpiB,
+ hci_vciB,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_status, {hci_state,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_status_enq, {hci_state,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_remote_data, {hci_prot_type,
+ hci_data,
+ hci_dummy1,
+ hci_dummy2}).
+
+-record(hci_unrec, {hci_mci,
+ hci_head,
+ hci_binary,
+ hci_data,
+ hci_prot_comp}).
+
+-record(hci_atd, {hci_pci,
+ hci_apci,
+ hci_fwd_pcr_clp_0,
+ hci_bwd_pcr_clp_0,
+ hci_fwd_pcr_clp_0_1,
+ hci_bwd_pcr_clp_0_1,
+ hci_fwd_scr_clp_0,
+ hci_bwd_scr_clp_0,
+ hci_fwd_scr_clp_0_1,
+ hci_bwd_scr_clp_0_1,
+ hci_fwd_mbs_clp_0,
+ hci_bwd_mbs_clp_0,
+ hci_fwd_mbs_clp_0_1,
+ hci_bwd_mbs_clp_0_1,
+ hci_best_effort_ind = 0,
+ hci_fwd_frame_discard = 0,
+ hci_bwd_frame_discard = 0,
+ hci_tagging_bwd = 0,
+ hci_tagging_fwd = 0,
+ hci_fwd_abr_mcr,
+ hci_bwd_abr_mcr,
+ hci_binary}).
+
+-record(hci_bbc, {hci_pci,
+ hci_bearer_class,
+ hci_atm_transfer_capability,
+ hci_user_plane_connection_configuration,
+ hci_susceptibility_to_clipping,
+ hci_binary}).
+
+-record(hci_cause, {hci_pci,
+ hci_location,
+ hci_cause_value,
+ hci_diagnostics_list = [],
+ hci_binary}).
+
+-record(hci_cpn, {hci_pci,
+ hci_type_of_number,
+ hci_intern_netw_numb_indic,
+ hci_numbering_plan_indicator,
+ hci_number_digits,
+ hci_orig_native = false}).
+
+-record(hci_clpn, {hci_pci,
+ hci_type_of_number,
+ hci_numbering_plan_indicator,
+ hci_presentation_indicator,
+ hci_screening_indicator,
+ hci_number_digits,
+ hci_incomplete_indicator = 0,
+ hci_binary}).
+
+-record(hci_cno, {hci_type_of_number,
+ hci_numbering_plan_indicator,
+ hci_presentation_indicator,
+ hci_screening_indicator,
+ hci_number_digits,
+ hci_binary}).
+
+-record(hci_cnosa, {hci_binary}).
+
+-record(hci_cpn_soft, {hci_select_type,
+ hci_soft_vpi,
+ hci_soft_vci,
+ hci_soft_dlci,
+ hci_binary}).
+
+-record(hci_clpn_soft, {hci_soft_vpi,
+ hci_soft_vci,
+ hci_soft_dlci,
+ hci_binary}).
+
+-record(hci_rer_services, {hci_inter_req_hard,
+ hci_inter_cap_hard,
+ hci_intra_req_soft,
+ hci_intra_req_hard,
+ hci_intra_cap_asym,
+ hci_intra_cap_sym,
+ hci_intra_cap_hard,
+ hci_binary}).
+
+-record(hci_rer, {hci_func_addr,
+ hci_endpoint_key,
+ hci_switchover,
+ hci_incarnation,
+ hci_pnni_cumul_fw_max_cell_td,
+ hci_cumul_fw_p2p_cdv,
+ hci_cumul_bw_p2p_cdv,
+ hci_binary}).
+
+-record(hci_rer_cause, {hci_rer_rel_cause,
+ hci_binary}).
+
+-record(hci_opt_traf, {hci_origin,
+ hci_cumul_fw_aw,
+ hci_cumul_bw_aw,
+ hci_binary}).
+
+-record(hci_qos, {hci_pci,
+ hci_qos_class_fwd,
+ hci_qos_class_bwd,
+ hci_binary}).
+
+-record(hci_aal, {hci_pci,
+ hci_binary}).
+
+-record(hci_bhli, {hci_pci,
+ hci_binary}).
+
+-record(hci_blli_brep, {hci_brep,
+ hci_blli_list = []}).
+
+-record(hci_blli, {hci_binary}).
+
+-record(hci_blli_bici, {hci_repeated,
+ hci_priority,
+ hci_pci,
+ hci_binary}).
+
+-record(hci_cpsa, {hci_pci,
+ hci_binary}).
+
+-record(hci_clpsa, {hci_pci,
+ hci_binary}).
+
+-record(hci_gat, {hci_binary}).
+
+-record(hci_epr, {hci_epr_type,
+ hci_epr_value,
+ hci_epr_flag,
+ hci_binary}).
+
+-record(hci_eqos, {hci_origin,
+ hci_acc_fwd_p2p_cdv,
+ hci_acc_bwd_p2p_cdv,
+ hci_cum_fwd_p2p_cdv,
+ hci_cum_bwd_p2p_cdv,
+ hci_acc_fwd_clr,
+ hci_acc_bwd_clr,
+ hci_binary}).
+
+-record(hci_brep, {hci_binary}).
+
+-record(hci_bsco, {hci_binary}).
+
+-record(hci_noti, {hci_binary}).
+
+-record(hci_abrs, {hci_fwd_abr_icr,
+ hci_bwd_abr_icr,
+ hci_fwd_abr_tbe,
+ hci_bwd_abr_tbe,
+ hci_cum_rm_fix_round_trip,
+ hci_fwd_rif,
+ hci_bwd_rif,
+ hci_fwd_rdf,
+ hci_bwd_rdf,
+ hci_binary}).
+
+-record(hci_abra, {hci_fwd_nrm,
+ hci_fwd_trm,
+ hci_fwd_cdf,
+ hci_fwd_atdf,
+ hci_bwd_nrm,
+ hci_bwd_trm,
+ hci_bwd_cdf,
+ hci_bwd_atdf,
+ hci_binary}).
+
+-record(hci_prog, {hci_coding_std,
+ hci_location,
+ hci_prog_desc,
+ hci_binary}).
+
+-record(hci_nbc_brep, {hci_brep,
+ hci_nbc_list = []}).
+
+-record(hci_nbc, {hci_binary}).
+
+-record(hci_nbhlc, {hci_binary}).
+
+-record(hci_nbllc_brep, {hci_brep,
+ hci_nbllc_list = []}).
+
+-record(hci_nbllc, {hci_binary}).
+
+-record(hci_geidt, {hci_binary}).
+
+-record(hci_conss, {hci_type_of_conn_scope,
+ hci_conn_scope,
+ hci_binary}).
+
+-record(hci_e2etd, {hci_pci,
+ hci_cumul_td,
+ hci_max_td,
+ hci_pnni_cumul_td,
+ hci_pnni_accept_fwd_max_td,
+ hci_netw_gen}).
+
+-record(hci_cdpi, {hci_pci,
+ hci_cdpci,
+ hci_cdpsi,
+ hci_binary}).
+
+-record(hci_cgpc, {hci_pci,
+ hci_binary}).
+
+-record(hci_lpt, {hci_pci,
+ hci_ptype}).
+
+-record(hci_cb, {hci_cb_level,
+ hci_bl_transit_type,
+ hci_bl_node_id,
+ hci_bl_link_proc_node_id,
+ hci_bl_link_port_id,
+ hci_bl_link_succ_node_id,
+ cause_value,
+ hci_cb_diagnostics,
+ hci_binary}).
+
+-record(hci_pa, {hci_ie_id,
+ hci_coding,
+ hci_action,
+ hci_length,
+ hci_binary,
+ hci_error_type}).
+
+-record(hci_ncci, {hci_pci,
+ hci_ni,
+ hci_point_code,
+ hci_call_id}).
+
+-record(hci_ssie, {hci_ssie_sas = [],
+ hci_binary}).
+
+-record(hci_sas, {hci_sas_vsn,
+ hci_sas_transp_ind,
+ hci_sas_flow_ind,
+ hci_sas_discard,
+ hci_sas_scope,
+ hci_sas_relative_id,
+ hci_binary}).
+
+-record(hci_data, {hci_hcid,
+ hci_sender_ifindex,
+ hci_sender_hcid}).
+
+-record(hci_data_setup, {hci_hcidA,
+ hci_pidA,
+ hci_protA,
+ hci_protB,
+ hci_portB,
+ hci_hcidB,
+ hci_rem_dataA,
+ hci_assign,
+ hci_ifindexB,
+ hci_node_id,
+ hci_succ_node_id,
+ hci_ifindexA,
+ hci_vpiA,
+ hci_vciA,
+ hci_cpA,
+ hci_cpB}).
+
+-record(hci_prot_comp, {hci_requiredFC = 0,
+ hci_desiredFC = 0}).
+
+-file("./spvcOrig.erl", 217).
+
+-file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/ccCd.hrl", 1).
+
+-hrl_id('13/190 55-CNA 121 101 Ux').
+
+-hrl_vsn('/main/R6A/R7A/R8A/R8B/8').
+
+-hrl_date('2003-02-21').
+
+-hrl_author(etxmexa).
+
+-record(ccCdRR, {hcid,
+ vpi,
+ vci,
+ ifindexA,
+ call_type,
+ spvc = false,
+ reserve = yes,
+ etA,
+ destdata,
+ leafdata,
+ loopdata,
+ l3,
+ l3_loop,
+ cc}).
+
+-record(ccCdRD, {destid,
+ loopdata,
+ cc}).
+
+-record(ccCdRL, {leafid,
+ protTypeB,
+ loopdata,
+ l3,
+ l3_loop,
+ cc}).
+
+-record(ccCdDD, {hcid,
+ hcidA,
+ vpi,
+ vci,
+ ifindexB,
+ portB,
+ call_type,
+ spvc = false,
+ reserve = yes,
+ protTypeA,
+ etB,
+ leafdata,
+ loopdata,
+ l3,
+ l3_loop,
+ cc}).
+
+-record(ccCdDL, {leafid,
+ loopdata,
+ l3,
+ l3_loop,
+ cc}).
+
+-record(ccRR, {protTypeA,
+ remote_dataA,
+ remote_dataB,
+ chg_counters,
+ sc,
+ chg_decision = on,
+ cc_loop}).
+
+-record(ccRL, {hcidB,
+ charging,
+ cc_loop}).
+
+-record(ccRD, {portB,
+ ifindexB,
+ cpB,
+ vpiB,
+ vciB,
+ cc_loop}).
+
+-record(ccDD, {protTypeB,
+ remote_dataA,
+ remote_dataB,
+ ifindexA,
+ cpA,
+ vpiA,
+ vciA,
+ chg_counters,
+ sc,
+ chg_decision = on,
+ cc_loop}).
+
+-record(ccDL, {cc_loop}).
+
+-record(loopRR, {vpList,
+ nodeid,
+ succ_nodeid,
+ connection_type,
+ policing,
+ delay_contrib,
+ charging = on,
+ prev_routing_data}).
+
+-record(loopRD, {}).
+
+-record(loopRL, {msg_rec,
+ providerName,
+ userName,
+ partyId,
+ serviceIfA,
+ serviceIdA,
+ serviceIfB,
+ serviceIdB,
+ estAw,
+ dtlLevels}).
+
+-record(loopDD, {nodeid,
+ succ_nodeid,
+ vpList,
+ connection_type,
+ policing,
+ assign,
+ delay_contrib,
+ charging = on}).
+
+-record(loopDL, {msg_rec,
+ providerName,
+ userName,
+ partyId,
+ serviceIfA,
+ serviceIdA,
+ serviceIfB,
+ serviceIdB}).
+
+-record(ccLoopRR, {pidB,
+ qos,
+ atd,
+ bbc,
+ cscope,
+ e2etd,
+ eqos,
+ con_state = none,
+ con_order = both,
+ mr_flag,
+ catch_up_id,
+ cpA}).
+
+-record(ccLoopRD, {}).
+
+-record(ccLoopRL, {route,
+ linklist,
+ routelist,
+ failurelist = [],
+ nodeidlist,
+ cb,
+ cpn,
+ dtl,
+ routing_state,
+ assign,
+ timer_counter = 0,
+ timer_ref,
+ status_enq_ind,
+ link_CB,
+ node_CB,
+ pnnir_rlp,
+ pnni_only}).
+
+-record(ccLoopDD, {pidA,
+ con_state = none,
+ con_order = both,
+ mr_flag,
+ catch_up_id,
+ cpB}).
+
+-record(ccLoopDL, {timer_counter = 0,
+ timer_ref,
+ status_enq_ind}).
+
+-file("./spvcOrig.erl", 218).
+
+-file("/export/localhome/locmacr/built/lib/erlang/lib/snmp-4.1.2/include/STANDARD-MIB.hrl", 1).
+
+-file("./spvcOrig.erl", 219).
+
+error_handler({From,Tag},{M,F,Args},EXITReason) ->
+ spvcLib:do_report(sccm,M,F,Args,"",EXITReason).
+
+connect(HcId,Connect,Key) ->
+ debug_disabled,
+ Obj = spvcDataBase:db_read({spvcObj,Key}),
+ orig_state_machine(Obj#spvcObj.currentState,connect_nu,Obj,[HcId,Connect]).
+
+release_nu(HcId,Release,Key) ->
+ debug_disabled,
+ Obj = spvcDataBase:db_read({spvcObj,Key}),
+ spvcDataBase:db_delete({spvcHcIdToTp,HcId}),
+ orig_state_machine(Obj#spvcObj.currentState,release_nu,Obj,[HcId,Release]).
+
+release_comp_nu(HcId,Release_comp,Key) ->
+ debug_disabled,
+ Obj = spvcDataBase:db_read({spvcObj,Key}),
+ spvcDataBase:db_delete({spvcHcIdToTp,HcId}),
+ orig_state_machine(Obj#spvcObj.currentState,release_comp_nu,Obj,[HcId,Release_comp]).
+
+release_incumbent(HcId,Release) ->
+ debug_disabled,
+ release_incumbent2(spvcDataBase:db_read({spvcHcIdToTp,HcId}),Release).
+
+release_incumbent2(SpvcHcIdToTp,Release) ->
+ release_incumbent3(SpvcHcIdToTp#spvcHcIdToTp.tpEntry,Release).
+
+release_incumbent3({orig,If,Vpi,Vci,Leaf},Release) ->
+ release_incumbent4({If,Vpi,Vci,Leaf},Release);
+release_incumbent3({orig,If,Vpi,Leaf},Release) ->
+ release_incumbent4({If,Vpi,Leaf},Release).
+
+release_incumbent4(TpKey,Release) ->
+ Spvc = spvcDataBase:db_read({spvcObj,TpKey}),
+ active = Spvc#spvcObj.currentState,
+ orig_state_machine(active,release_incumbent,Spvc,[Release]).
+
+switch_over(HcId,{If,Vpi,Vci}) ->
+ Key = case {If,Vpi,Vci} of
+ {If_Value,Vpi_Value,Vci_Value} when integer(Vci_Value) ->
+ {If_Value,Vpi_Value,Vci_Value,1};
+ {If_Value,Vpi_Value,_} ->
+ {If_Value,Vpi_Value,1};
+ {If_Value,Vpi_Value} ->
+ {If_Value,Vpi_Value,1}
+ end,
+ Spvc = spvcDataBase:db_read({spvcObj,Key}),
+ do_switch_over(HcId,Spvc);
+switch_over(HcId,{If,Vpi}) ->
+ Key = case {If,Vpi,no_vc} of
+ {If_Value,Vpi_Value,Vci_Value} when integer(Vci_Value) ->
+ {If_Value,Vpi_Value,Vci_Value,1};
+ {If_Value,Vpi_Value,_} ->
+ {If_Value,Vpi_Value,1};
+ {If_Value,Vpi_Value} ->
+ {If_Value,Vpi_Value,1}
+ end,
+ Spvc = spvcDataBase:db_read({spvcObj,Key}),
+ do_switch_over(HcId,Spvc).
+
+do_switch_over(HcId,Spvc) ->
+ State = Spvc#spvcObj.currentState,
+ orig_state_machine(State,switch_over,Spvc,[HcId]).
+
+gen_set(Type,Row,Cols) ->
+ debug_disabled,
+ gen_set(Type,Row,Cols,undefined).
+
+gen_set(Type,Row,Cols,FrKey) ->
+ debug_disabled,
+ case lists:keysearch(case {case Row of
+ {_,_,_,_} ->
+ spvcVcc;
+ {_,_,_} ->
+ spvcVpc;
+ {_,_} ->
+ spvcFr;
+ [_,_,_,_] ->
+ spvcVcc;
+ [_,_,_] ->
+ spvcVpc;
+ [_,_] ->
+ spvcFr
+ end,rowStatus} of
+ {spvcVcc,targetAddress} ->
+ 2;
+ {spvcVcc,selectType} ->
+ 3;
+ {spvcVcc,targetVpi} ->
+ 18;
+ {spvcVcc,targetVci} ->
+ 5;
+ {spvcVcc,releaseCause} ->
+ 6;
+ {spvcVcc,releaseDiagnostic} ->
+ 7;
+ {spvcVcc,retryInterval} ->
+ 10;
+ {spvcVcc,retryTimer} ->
+ 11;
+ {spvcVcc,retryThreshold} ->
+ 12;
+ {spvcVcc,retryFailures} ->
+ 13;
+ {spvcVcc,retryLimit} ->
+ 14;
+ {spvcVcc,rowStatus} ->
+ 15;
+ {spvcVcc,restart} ->
+ 9;
+ {spvcVcc,targetSelectType_any} ->
+ 2;
+ {spvcVcc,targetSelectType_required} ->
+ 1;
+ {spvcVpc,targetAddress} ->
+ 2;
+ {spvcVpc,selectType} ->
+ 3;
+ {spvcVpc,targetVpi} ->
+ 15;
+ {spvcVpc,releaseCause} ->
+ 5;
+ {spvcVpc,releaseDiagnostic} ->
+ 6;
+ {spvcVpc,retryInterval} ->
+ 9;
+ {spvcVpc,retryTimer} ->
+ 10;
+ {spvcVpc,retryThreshold} ->
+ 11;
+ {spvcVpc,retryFailures} ->
+ 12;
+ {spvcVpc,retryLimit} ->
+ 13;
+ {spvcVpc,rowStatus} ->
+ 14;
+ {spvcVpc,restart} ->
+ 8;
+ {spvcVpc,targetSelectType_any} ->
+ 2;
+ {spvcVpc,targetSelectType_required} ->
+ 1;
+ {spvcFr,targetAddress} ->
+ 3;
+ {spvcFr,selectType} ->
+ 5;
+ {spvcFr,identifier} ->
+ 6;
+ {spvcFr,targetVpi} ->
+ 7;
+ {spvcFr,targetVci} ->
+ 8;
+ {spvcFr,translation} ->
+ 9;
+ {spvcFr,releaseCause} ->
+ 10;
+ {spvcFr,releaseDiagnostic} ->
+ 11;
+ {spvcFr,operStatus} ->
+ 12;
+ {spvcFr,adminStatus} ->
+ 13;
+ {spvcFr,restart} ->
+ 14;
+ {spvcFr,retryInterval} ->
+ 15;
+ {spvcFr,retryTimer} ->
+ 16;
+ {spvcFr,retryThreshold} ->
+ 17;
+ {spvcFr,retryFailures} ->
+ 18;
+ {spvcFr,retryLimit} ->
+ 19;
+ {spvcFr,lastChange} ->
+ 20;
+ {spvcFr,rowStatus} ->
+ 21
+ end,1,Cols) of
+ {value,{_,4}} ->
+ debug_disabled,
+ mnesia:dirty_update_counter(spvcHcEtStat,spvcLib:get_board(hd(Row)),1),
+ case get_link_state(case Row of
+ Row when record(Row,spvcObj) ->
+ case Row#spvcObj.spvcEntry of
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value
+ end;
+ Row when record(Row,spvcVcc) ->
+ {If_Value,_,_,_} = Row#spvcVcc.spvcVccEntry,
+ If_Value;
+ Row when record(Row,spvcVpc) ->
+ {If_Value,_,_} = Row#spvcVpc.spvcVpcEntry,
+ If_Value;
+ Row when record(Row,spvcVpcPerm) ->
+ {If_Value,_,_} = Row#spvcVpcPerm.spvcVpcEntry,
+ If_Value;
+ Row when record(Row,spvcVccPerm) ->
+ {If_Value,_,_,_} = Row#spvcVccPerm.spvcVccEntry,
+ If_Value;
+ Row when record(Row,spvcTargetVc) ->
+ {If_Value,_,_} = Row#spvcTargetVc.entry,
+ If_Value;
+ Row when record(Row,spvcTargetVp) ->
+ {If_Value,_} = Row#spvcTargetVp.entry,
+ If_Value;
+ Row when record(Row,pchVc) ->
+ {If_Value,_,_} = Row#pchVc.vclEntry,
+ If_Value;
+ Row when record(Row,pchVp) ->
+ {If_Value,_} = Row#pchVp.vplEntry,
+ If_Value;
+ Row when record(Row,spvcFr) ->
+ {If_Value,_} = Row#spvcFr.spvcFrEntry,
+ If_Value;
+ Row when record(Row,spvcFrPerm) ->
+ {If_Value,_} = Row#spvcFrPerm.spvcFrEntry,
+ If_Value;
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value;
+ {If_Value,_} ->
+ If_Value;
+ [If_Value|_] ->
+ If_Value;
+ _ ->
+ error
+ end) of
+ disabled ->
+ orig_state_machine(null,createAndGo_disabled,[],[Row,Cols,Type,FrKey]);
+ enabled ->
+ orig_state_machine(null,createAndGo_enabled,[],[Row,Cols,Type,FrKey])
+ end;
+ {value,{_,5}} ->
+ debug_disabled,
+ mnesia:dirty_update_counter(spvcHcEtStat,spvcLib:get_board(hd(Row)),1),
+ orig_state_machine(null,createAndWait,[],[Row,Cols,Type,FrKey]);
+ {value,{_,1}} ->
+ debug_disabled,
+ case spvcDataBase:db_read({spvcObj,list_to_tuple(Row)}) of
+ [] ->
+ ok;
+ Spvc ->
+ case get_link_state(case Row of
+ Row when record(Row,spvcObj) ->
+ case Row#spvcObj.spvcEntry of
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value
+ end;
+ Row when record(Row,spvcVcc) ->
+ {If_Value,_,_,_} = Row#spvcVcc.spvcVccEntry,
+ If_Value;
+ Row when record(Row,spvcVpc) ->
+ {If_Value,_,_} = Row#spvcVpc.spvcVpcEntry,
+ If_Value;
+ Row when record(Row,spvcVpcPerm) ->
+ {If_Value,_,_} = Row#spvcVpcPerm.spvcVpcEntry,
+ If_Value;
+ Row when record(Row,spvcVccPerm) ->
+ {If_Value,_,_,_} = Row#spvcVccPerm.spvcVccEntry,
+ If_Value;
+ Row when record(Row,spvcTargetVc) ->
+ {If_Value,_,_} = Row#spvcTargetVc.entry,
+ If_Value;
+ Row when record(Row,spvcTargetVp) ->
+ {If_Value,_} = Row#spvcTargetVp.entry,
+ If_Value;
+ Row when record(Row,pchVc) ->
+ {If_Value,_,_} = Row#pchVc.vclEntry,
+ If_Value;
+ Row when record(Row,pchVp) ->
+ {If_Value,_} = Row#pchVp.vplEntry,
+ If_Value;
+ Row when record(Row,spvcFr) ->
+ {If_Value,_} = Row#spvcFr.spvcFrEntry,
+ If_Value;
+ Row when record(Row,spvcFrPerm) ->
+ {If_Value,_} = Row#spvcFrPerm.spvcFrEntry,
+ If_Value;
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value;
+ {If_Value,_} ->
+ If_Value;
+ [If_Value|_] ->
+ If_Value;
+ _ ->
+ error
+ end) of
+ disabled ->
+ orig_state_machine(Spvc#spvcObj.currentState,activate_disabled,Spvc,Cols);
+ enabled ->
+ orig_state_machine(Spvc#spvcObj.currentState,activate_enabled,Spvc,Cols)
+ end
+ end;
+ {value,{_,6}} ->
+ debug_disabled,
+ case spvcDataBase:db_read({spvcObj,list_to_tuple(Row)}) of
+ [] ->
+ ok;
+ Spvc ->
+ mnesia:dirty_update_counter(spvcHcEtStat,spvcLib:get_board(hd(Row)),- 1),
+ orig_state_machine(Spvc#spvcObj.currentState,destroy,Spvc,Cols)
+ end;
+ {value,{_,2}} ->
+ debug_disabled,
+ case spvcDataBase:db_read({spvcObj,list_to_tuple(Row)}) of
+ [] ->
+ mnesia:dirty_update_counter(spvcHcEtStat,spvcLib:get_board(hd(Row)),1),
+ ok;
+ Spvc ->
+ orig_state_machine(Spvc#spvcObj.currentState,not_in_service,Spvc,Cols)
+ end;
+ false ->
+ debug_disabled,
+ Spvc = spvcDataBase:db_read({spvcObj,list_to_tuple(Row)}),
+ CurrentState = Spvc#spvcObj.currentState,
+ NewSpvc = set_attrs(Spvc,Cols),
+ Restart = case {case Row of
+ {_,_,_,_} ->
+ spvcVcc;
+ {_,_,_} ->
+ spvcVpc;
+ {_,_} ->
+ spvcFr;
+ [_,_,_,_] ->
+ spvcVcc;
+ [_,_,_] ->
+ spvcVpc;
+ [_,_] ->
+ spvcFr
+ end,restart} of
+ {spvcVcc,targetAddress} ->
+ 2;
+ {spvcVcc,selectType} ->
+ 3;
+ {spvcVcc,targetVpi} ->
+ 18;
+ {spvcVcc,targetVci} ->
+ 5;
+ {spvcVcc,releaseCause} ->
+ 6;
+ {spvcVcc,releaseDiagnostic} ->
+ 7;
+ {spvcVcc,retryInterval} ->
+ 10;
+ {spvcVcc,retryTimer} ->
+ 11;
+ {spvcVcc,retryThreshold} ->
+ 12;
+ {spvcVcc,retryFailures} ->
+ 13;
+ {spvcVcc,retryLimit} ->
+ 14;
+ {spvcVcc,rowStatus} ->
+ 15;
+ {spvcVcc,restart} ->
+ 9;
+ {spvcVcc,targetSelectType_any} ->
+ 2;
+ {spvcVcc,targetSelectType_required} ->
+ 1;
+ {spvcVpc,targetAddress} ->
+ 2;
+ {spvcVpc,selectType} ->
+ 3;
+ {spvcVpc,targetVpi} ->
+ 15;
+ {spvcVpc,releaseCause} ->
+ 5;
+ {spvcVpc,releaseDiagnostic} ->
+ 6;
+ {spvcVpc,retryInterval} ->
+ 9;
+ {spvcVpc,retryTimer} ->
+ 10;
+ {spvcVpc,retryThreshold} ->
+ 11;
+ {spvcVpc,retryFailures} ->
+ 12;
+ {spvcVpc,retryLimit} ->
+ 13;
+ {spvcVpc,rowStatus} ->
+ 14;
+ {spvcVpc,restart} ->
+ 8;
+ {spvcVpc,targetSelectType_any} ->
+ 2;
+ {spvcVpc,targetSelectType_required} ->
+ 1;
+ {spvcFr,targetAddress} ->
+ 3;
+ {spvcFr,selectType} ->
+ 5;
+ {spvcFr,identifier} ->
+ 6;
+ {spvcFr,targetVpi} ->
+ 7;
+ {spvcFr,targetVci} ->
+ 8;
+ {spvcFr,translation} ->
+ 9;
+ {spvcFr,releaseCause} ->
+ 10;
+ {spvcFr,releaseDiagnostic} ->
+ 11;
+ {spvcFr,operStatus} ->
+ 12;
+ {spvcFr,adminStatus} ->
+ 13;
+ {spvcFr,restart} ->
+ 14;
+ {spvcFr,retryInterval} ->
+ 15;
+ {spvcFr,retryTimer} ->
+ 16;
+ {spvcFr,retryThreshold} ->
+ 17;
+ {spvcFr,retryFailures} ->
+ 18;
+ {spvcFr,retryLimit} ->
+ 19;
+ {spvcFr,lastChange} ->
+ 20;
+ {spvcFr,rowStatus} ->
+ 21
+ end,
+ case lists:keysearch(Restart,1,Cols) of
+ {value,{Restart,1}} ->
+ orig_state_machine(CurrentState,restart,NewSpvc,Cols);
+ _ ->
+ spvcDataBase:db_write(NewSpvc),
+ ok
+ end
+ end,
+ {noError,0}.
+
+restart_spvc(Key) ->
+ debug_disabled,
+ Spvc = spvcDataBase:db_read({spvcObj,Key}),
+ handle_restart_spvc(Spvc#spvcObj.currentState,Spvc),
+ ok.
+
+handle_restart_spvc(rest_in_peace,Spvc) ->
+ debug_disabled,
+ rest_in_peace(restart,Spvc,undefined);
+handle_restart_spvc(_,_) ->
+ ok.
+
+restart_multi_spvcs(Key) ->
+ debug_disabled,
+ Spvc = spvcDataBase:db_read({spvcObj,Key}),
+ handle_restart_multi_spvcs(Spvc#spvcObj.currentState,Spvc),
+ ok.
+
+handle_restart_multi_spvcs(rest_in_peace,Spvc) ->
+ debug_disabled,
+ handle_restart_spvc(rest_in_peace,Spvc);
+handle_restart_multi_spvcs(active,Spvc) ->
+ debug_disabled,
+ active(restart,Spvc,undefined);
+handle_restart_multi_spvcs(outgoing_callproceeding,Spvc) ->
+ debug_disabled,
+ outgoing_callproceeding(restart,Spvc,undefined);
+handle_restart_multi_spvcs(release_at_restart,Spvc) ->
+ debug_disabled,
+ release_at_restart(restart,Spvc,undefined);
+handle_restart_multi_spvcs(wait,Spvc) ->
+ debug_disabled,
+ wait(restart,Spvc,undefined);
+handle_restart_multi_spvcs(rest_in_peace,Spvc) ->
+ debug_disabled,
+ rest_in_peace(restart,Spvc,undefined);
+handle_restart_multi_spvcs(_,_) ->
+ ok.
+
+orig_state_machine(null,createAndGo_enabled,Spvc,Attrs) ->
+ null(createAndGo_enabled,Spvc,Attrs);
+orig_state_machine(null,createAndGo_disabled,Spvc,Attrs) ->
+ null(createAndGo_disabled,Spvc,Attrs);
+orig_state_machine(null,createAndWait,Spvc,Attrs) ->
+ null(createAndWait,Spvc,Attrs);
+orig_state_machine(created,activate_disabled,Spvc,Attrs) ->
+ created(activate_disabled,Spvc,Attrs);
+orig_state_machine(created,activate_enabled,Spvc,Attrs) ->
+ created(activate_enabled,Spvc,Attrs);
+orig_state_machine(created,destroy,Spvc,Attrs) ->
+ created(destroy,Spvc,Attrs);
+orig_state_machine(outgoing_callproceeding,connect_nu,Spvc,Attrs) ->
+ outgoing_callproceeding(connect_nu,Spvc,Attrs);
+orig_state_machine(outgoing_callproceeding,destroy,Spvc,Attrs) ->
+ outgoing_callproceeding(destroy,Spvc,Attrs);
+orig_state_machine(outgoing_callproceeding,restart,Spvc,Attrs) ->
+ outgoing_callproceeding(restart,Spvc,Attrs);
+orig_state_machine(outgoing_callproceeding,release_nu,Spvc,Attrs) ->
+ case get_link_state_intf(case Spvc of
+ Spvc when record(Spvc,spvcObj) ->
+ case Spvc#spvcObj.spvcEntry of
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value
+ end;
+ Spvc when record(Spvc,spvcVcc) ->
+ {If_Value,_,_,_} = Spvc#spvcVcc.spvcVccEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVpc) ->
+ {If_Value,_,_} = Spvc#spvcVpc.spvcVpcEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVpcPerm) ->
+ {If_Value,_,_} = Spvc#spvcVpcPerm.spvcVpcEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVccPerm) ->
+ {If_Value,_,_,_} = Spvc#spvcVccPerm.spvcVccEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcTargetVc) ->
+ {If_Value,_,_} = Spvc#spvcTargetVc.entry,
+ If_Value;
+ Spvc when record(Spvc,spvcTargetVp) ->
+ {If_Value,_} = Spvc#spvcTargetVp.entry,
+ If_Value;
+ Spvc when record(Spvc,pchVc) ->
+ {If_Value,_,_} = Spvc#pchVc.vclEntry,
+ If_Value;
+ Spvc when record(Spvc,pchVp) ->
+ {If_Value,_} = Spvc#pchVp.vplEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcFr) ->
+ {If_Value,_} = Spvc#spvcFr.spvcFrEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcFrPerm) ->
+ {If_Value,_} = Spvc#spvcFrPerm.spvcFrEntry,
+ If_Value;
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value;
+ {If_Value,_} ->
+ If_Value;
+ [If_Value|_] ->
+ If_Value;
+ _ ->
+ error
+ end,release_nu) of
+ disabled ->
+ outgoing_callproceeding(release_nu_disabled,Spvc,Attrs);
+ enabled ->
+ outgoing_callproceeding(release_nu_enabled,Spvc,Attrs)
+ end;
+orig_state_machine(outgoing_callproceeding,release_comp_nu,Spvc,Attrs) ->
+ case get_link_state_intf(tuple_to_list(Spvc#spvcObj.spvcEntry),release_comp_nu) of
+ disabled ->
+ outgoing_callproceeding(release_comp_nu_disabled,Spvc,Attrs);
+ enabled ->
+ outgoing_callproceeding(release_comp_nu_enabled,Spvc,Attrs)
+ end;
+orig_state_machine(outgoing_callproceeding,not_in_service,Spvc,Attrs) ->
+ outgoing_callproceeding(not_in_service,Spvc,Attrs);
+orig_state_machine(outgoing_callproceeding,activate_enabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(outgoing_callproceeding,activate_disabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(active,destroy,Spvc,Attrs) ->
+ active(destroy,Spvc,Attrs);
+orig_state_machine(active,restart,Spvc,Attrs) ->
+ active(restart,Spvc,Attrs);
+orig_state_machine(active,release_nu,Spvc,Attrs) ->
+ case cnhChi:get_link_opstate(case Spvc of
+ Spvc when record(Spvc,spvcObj) ->
+ case Spvc#spvcObj.spvcEntry of
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value
+ end;
+ Spvc when record(Spvc,spvcVcc) ->
+ {If_Value,_,_,_} = Spvc#spvcVcc.spvcVccEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVpc) ->
+ {If_Value,_,_} = Spvc#spvcVpc.spvcVpcEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVpcPerm) ->
+ {If_Value,_,_} = Spvc#spvcVpcPerm.spvcVpcEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVccPerm) ->
+ {If_Value,_,_,_} = Spvc#spvcVccPerm.spvcVccEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcTargetVc) ->
+ {If_Value,_,_} = Spvc#spvcTargetVc.entry,
+ If_Value;
+ Spvc when record(Spvc,spvcTargetVp) ->
+ {If_Value,_} = Spvc#spvcTargetVp.entry,
+ If_Value;
+ Spvc when record(Spvc,pchVc) ->
+ {If_Value,_,_} = Spvc#pchVc.vclEntry,
+ If_Value;
+ Spvc when record(Spvc,pchVp) ->
+ {If_Value,_} = Spvc#pchVp.vplEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcFr) ->
+ {If_Value,_} = Spvc#spvcFr.spvcFrEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcFrPerm) ->
+ {If_Value,_} = Spvc#spvcFrPerm.spvcFrEntry,
+ If_Value;
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value;
+ {If_Value,_} ->
+ If_Value;
+ [If_Value|_] ->
+ If_Value;
+ _ ->
+ error
+ end) of
+ disabled ->
+ active(release_nu_disabled,Spvc,Attrs);
+ enabled ->
+ active(release_nu_enabled,Spvc,Attrs)
+ end;
+orig_state_machine(active,release_comp_nu,Spvc,Attrs) ->
+ release_at_restart(release_comp_nu,Spvc,Attrs);
+orig_state_machine(active,not_in_service,Spvc,Attrs) ->
+ active(not_in_service,Spvc,Attrs);
+orig_state_machine(active,activate_enabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(active,activate_disabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(active,release_incumbent,Spvc,Attrs) ->
+ active(release_incumbent,Spvc,Attrs);
+orig_state_machine(wait,destroy,Spvc,Attrs) ->
+ wait(destroy,Spvc,Attrs);
+orig_state_machine(wait,timeout,Spvc,Attrs) ->
+ wait(timeout,Spvc,Attrs);
+orig_state_machine(wait,restart,Spvc,Attrs) ->
+ wait(restart,Spvc,Attrs);
+orig_state_machine(wait,release_nu,Spvc,Attrs) ->
+ ok;
+orig_state_machine(wait,not_in_service,Spvc,Attrs) ->
+ wait(not_in_service,Spvc,Attrs);
+orig_state_machine(wait,activate_enabled,Spvc,Attrs) ->
+ wait(timeout,Spvc,Attrs);
+orig_state_machine(wait,activate_disabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(release_at_restart,release_comp_nu,Spvc,Attrs) ->
+ release_at_restart(release_comp_nu,Spvc,Attrs);
+orig_state_machine(release_at_restart,release_nu,Spvc,Attrs) ->
+ release_at_restart(release_nu,Spvc,Attrs);
+orig_state_machine(release_at_restart,connect_nu,Spvc,Attrs) ->
+ release_at_restart(connect_nu,Spvc,Attrs);
+orig_state_machine(release_at_restart,destroy,Spvc,Attrs) ->
+ release_at_restart(destroy,Spvc,Attrs);
+orig_state_machine(release_at_restart,not_in_service,Spvc,Attrs) ->
+ release_at_restart(not_in_service,Spvc,Attrs);
+orig_state_machine(release_at_restart,activate_enabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(release_at_restart,activate_disabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(release_request,release_comp_nu,Spvc,Attrs) ->
+ release_request(release_comp_nu,Spvc,Attrs);
+orig_state_machine(release_request,release_nu,Spvc,Attrs) ->
+ release_request(release_nu,Spvc,Attrs);
+orig_state_machine(release_request,destroy,Spvc,Attrs) ->
+ release_request(destroy,Spvc,Attrs);
+orig_state_machine(release_request,not_in_service,Spvc,Attrs) ->
+ release_request(not_in_service,Spvc,Attrs);
+orig_state_machine(release_request,activate_enabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(release_request,activate_disabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(rest_in_peace,restart,Spvc,Attrs) ->
+ rest_in_peace(restart,Spvc,Attrs);
+orig_state_machine(rest_in_peace,destroy,Spvc,Attrs) ->
+ rest_in_peace(destroy,Spvc,Attrs);
+orig_state_machine(rest_in_peace,not_in_service,Spvc,Attrs) ->
+ rest_in_peace(not_in_service,Spvc,Attrs);
+orig_state_machine(rest_in_peace,connect_nu,Spvc,Attrs) ->
+ rest_in_peace(connect_nu,Spvc,Attrs);
+orig_state_machine(rest_in_peace,activate_enabled,Spvc,Attrs) ->
+ rest_in_peace(restart,Spvc,Attrs);
+orig_state_machine(rest_in_peace,activate_disabled,Spvc,Attrs) ->
+ ok;
+orig_state_machine(rest_in_peace,release_nu,Spvc,Attrs) ->
+ ok;
+orig_state_machine(rest_in_peace,release_comp_nu,Spvc,Attrs) ->
+ ok;
+orig_state_machine(not_in_service,activate_enabled,Spvc,Attrs) ->
+ not_in_service(activate_enabled,Spvc,Attrs);
+orig_state_machine(not_in_service,activate_disabled,Spvc,Attrs) ->
+ not_in_service(activate_disabled,Spvc,Attrs);
+orig_state_machine(not_in_service,destroy,Spvc,Attrs) ->
+ not_in_service(destroy,Spvc,Attrs);
+orig_state_machine(not_in_service,connect_nu,Spvc,Attrs) ->
+ not_in_service(connect_nu,Spvc,Attrs);
+orig_state_machine(not_in_service,_,Spvc,Attrs) ->
+ ok;
+orig_state_machine(awaiting_switch_over,switch_over,Spvc,[HcId]) ->
+ awaiting_switch_over(switch_over,Spvc,[HcId]);
+orig_state_machine(awaiting_switch_over,activate_disabled,Spvc,Attrs) ->
+ awaiting_switch_over(activate_disabled,Spvc,Attrs);
+orig_state_machine(awaiting_switch_over,destroy,Spvc,Attrs) ->
+ awaiting_switch_over(destroy,Spvc,Attrs);
+orig_state_machine(awaiting_switch_over,restart,Spvc,Attrs) ->
+ awaiting_switch_over(restart,Spvc,Attrs);
+orig_state_machine(awaiting_switch_over,_,Spvc,Attrs) ->
+ ok;
+orig_state_machine(undefined,destroy,Spvc,Attrs) ->
+ rest_in_peace(destroy,Spvc,Attrs).
+
+null(createAndGo_enabled,[],[Row,Cols,Type,FrKey]) ->
+ debug_disabled,
+ Key = list_to_tuple(Row),
+ Spvc = #spvcObj{spvcEntry = Key,
+ spvcApplication = Type,
+ spvcRowStatus = 1,
+ spvcFrKey = FrKey},
+ Spvc1 = set_attrs(Spvc,Cols),
+ {Spvc2,HcId,Setup} = new_state_outgoing_call_proceeding(Spvc1),
+ pchTpUpdate(case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end),
+ spvcDataBase:db_write(Spvc2),
+ setup(HcId,Setup,Spvc2);
+null(createAndGo_disabled,[],[Row,Cols,Type,FrKey]) ->
+ debug_disabled,
+ case get_link_state_intf(Row,null_createAndGo_disabled) of
+ disabled ->
+ Key = list_to_tuple(Row),
+ Spvc = #spvcObj{spvcEntry = Key,
+ spvcRowStatus = 1,
+ currentState = rest_in_peace,
+ spvcApplication = Type,
+ spvcFrKey = FrKey},
+ Spvc1 = set_attrs(Spvc,Cols),
+ pchTpUpdate(case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end),
+ set_call_failure_data_and_send_spvcFailingAlarm(Key),
+ spvcDataBase:db_write(Spvc1);
+ enabled ->
+ null(createAndGo_enabled,[],[Row,Cols,Type,FrKey])
+ end;
+null(createAndWait,[],[Row,Cols,Type,FrKey]) ->
+ debug_disabled,
+ Key = list_to_tuple(Row),
+ Spvc = #spvcObj{spvcEntry = Key,
+ spvcApplication = Type,
+ spvcFrKey = FrKey},
+ Spvc1 = new_state_created(Spvc,Cols),
+ pchTpUpdate(case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end),
+ spvcDataBase:db_write(Spvc1).
+
+pchTpUpdate({If,Vpi,Vci}) ->
+ spvcDataBase:db_write(#spvcVcDyn{vclEntry = {If,Vpi,Vci},
+ vclCcIdentifier = 0});
+pchTpUpdate({If,Vpi}) ->
+ spvcDataBase:db_write(#spvcVpDyn{vplEntry = {If,Vpi},
+ vplCcIdentifier = 0}).
+
+created(activate_enabled,Spvc,Attrs) ->
+ debug_disabled,
+ Spvc1 = set_attrs(Spvc,Attrs),
+ Spvc2 = Spvc1#spvcObj{spvcRowStatus = 1},
+ {Spvc3,HcId,HciMsg} = new_state_outgoing_call_proceeding(Spvc1),
+ spvcDataBase:db_write(Spvc3),
+ setup(HcId,HciMsg,Spvc3);
+created(activate_disabled,Spvc,Attrs) ->
+ debug_disabled,
+ Spvc1 = set_attrs(Spvc,Attrs),
+ Spvc2 = Spvc1#spvcObj{currentState = rest_in_peace,
+ spvcRowStatus = 1},
+ update_state(Spvc,4),
+ spvcDataBase:db_write(Spvc2);
+created(destroy,Spvc,Attrs) ->
+ debug_disabled,
+ clear(Spvc).
+
+outgoing_callproceeding(connect_nu,Spvc,[HcId,Connect]) ->
+ debug_disabled,
+ Spvc1 = new_state_active(Spvc),
+ case Spvc#spvcObj.spvcTargetSelectType of
+ 2 ->
+ Cpn = Connect#hci_connect.hci_cpn_soft,
+ TargetVpi = Cpn#hci_cpn_soft.hci_soft_vpi,
+ TargetVci = Cpn#hci_cpn_soft.hci_soft_vci,
+ TargetDlci = Cpn#hci_cpn_soft.hci_soft_dlci,
+ Spvc2 = Spvc1#spvcObj{spvcTargetSelectType = 1,
+ spvcTargetVpi = TargetVpi,
+ spvcTargetVci = TargetVci,
+ spvcTargetDlci = TargetDlci},
+ spvcDataBase:db_write(Spvc2);
+ 1 ->
+ spvcDataBase:db_write(ets,Spvc1);
+ 2 ->
+ Cpn = Connect#hci_connect.hci_cpn_soft,
+ TargetVpi = Cpn#hci_cpn_soft.hci_soft_vpi,
+ TargetDlci = Cpn#hci_cpn_soft.hci_soft_dlci,
+ Spvc2 = Spvc1#spvcObj{spvcTargetSelectType = 1,
+ spvcTargetVpi = TargetVpi,
+ spvcTargetDlci = TargetDlci},
+ spvcDataBase:db_write(Spvc2);
+ 1 ->
+ spvcDataBase:db_write(ets,Spvc1)
+ end,
+ Key = Spvc#spvcObj.spvcEntry,
+ PchKey = case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end,
+ SpvcDyn = case PchKey of
+ {_,_,_} ->
+ case spvcDataBase:db_read({spvcVcDyn,PchKey}) of
+ [] ->
+ #spvcVcDyn{vclEntry = PchKey,
+ vclCcIdentifier = 0,
+ vclConnId = HcId};
+ SpvcVcDyn ->
+ SpvcVcDyn#spvcVcDyn{vclEntry = PchKey,
+ vclConnId = HcId}
+ end;
+ {_,_} ->
+ case spvcDataBase:db_read({spvcVpDyn,PchKey}) of
+ [] ->
+ #spvcVpDyn{vplEntry = PchKey,
+ vplCcIdentifier = 0,
+ vplConnId = HcId};
+ SpvcVpDyn ->
+ SpvcVpDyn#spvcVpDyn{vplEntry = PchKey,
+ vplConnId = HcId}
+ end
+ end,
+ spvcDataBase:db_write(SpvcDyn),
+ CbCValue = get(no_of_rerouting),
+ CbC = case CbCValue of
+ undefined ->
+ debug_disabled,
+ 0;
+ _ ->
+ CbCValue
+ end,
+ SpvcDyn2 = case Key of
+ {_,_,_,_} ->
+ case spvcDataBase:db_read({spvcVccDyn,Key}) of
+ [] ->
+ #spvcVccDyn{spvcVccEntry = Key,
+ crankBackCounter = CbC};
+ SpvcVccDyn ->
+ SpvcVccDyn#spvcVccDyn{spvcVccEntry = Key,
+ crankBackCounter = CbC}
+ end;
+ {_,_,_} ->
+ case spvcDataBase:db_read({spvcVpcDyn,Key}) of
+ [] ->
+ #spvcVpcDyn{spvcVpcEntry = Key,
+ crankBackCounter = CbC};
+ SpvcVpcDyn ->
+ SpvcVpcDyn#spvcVpcDyn{spvcVpcEntry = Key,
+ crankBackCounter = CbC}
+ end
+ end,
+ spvcDataBase:db_write(SpvcDyn2),
+ NewPch = spvcDataBase:db_read({pch,PchKey}),
+ spvcLib:clear_spvcStillTryingAlarm(Key),
+ case Spvc#spvcObj.spvcFrKey of
+ undefined ->
+ spvcLib:ilmi_change(PchKey,1),
+ ok;
+ FrEndPoint ->
+ SpvcFrObj = spvcDataBase:db_read({spvcFrPerm,FrEndPoint}),
+ NewSpvcFrObj = SpvcFrObj#spvcFrPerm{spvcFrConnect = 3},
+ spvcDataBase:db_write(NewSpvcFrObj),
+ spvcLib:ilmi_change(PchKey,1),
+ set_fr_atm_iw_admin_state(FrEndPoint,up,Spvc)
+ end;
+outgoing_callproceeding(restart,Spvc,_) ->
+ Key = Spvc#spvcObj.spvcEntry,
+ debug_disabled,
+ Spvc1 = new_state_release_at_restart(Spvc),
+ spvcDataBase:db_write(ets,Spvc1),
+ spvcLib:clear_spvcStillTryingAlarm(Key);
+outgoing_callproceeding(release_nu_enabled,Spvc,[HcId,HciMsg]) ->
+ debug_disabled,
+ Spvc1 = new_state_rest_in_peace_or_wait(Spvc,[HcId,HciMsg]),
+ [CcCause|_] = HciMsg#hci_release.hci_cause_list,
+ Spvc2 = Spvc1#spvcObj{spvcLastReleaseCause = CcCause#hci_cause.hci_cause_value,
+ spvcLastReleaseDiagnostic = CcCause#hci_cause.hci_diagnostics_list},
+ spvcDataBase:db_write(ets,Spvc2);
+outgoing_callproceeding(release_nu_disabled,Spvc,[HcId,Release]) ->
+ debug_disabled,
+ Spvc1 = new_state_rest_in_peace(Spvc),
+ [CcCause|_] = Release#hci_release.hci_cause_list,
+ Spvc2 = Spvc1#spvcObj{spvcLastReleaseCause = CcCause#hci_cause.hci_cause_value,
+ spvcLastReleaseDiagnostic = CcCause#hci_cause.hci_diagnostics_list},
+ spvcDataBase:db_write(ets,Spvc2),
+ spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry);
+outgoing_callproceeding(release_comp_nu_enabled,Spvc,[HcId,Release_complete]) ->
+ debug_disabled,
+ Spvc1 = new_state_rest_in_peace_or_wait(Spvc,[HcId,Release_complete]),
+ spvcDataBase:db_write(ets,Spvc1);
+outgoing_callproceeding(release_comp_nu_disabled,Spvc,[HcId,Release_complete]) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = new_state_rest_in_peace(Spvc),
+ spvcDataBase:db_write(ets,Spvc1),
+ spvcLib:clear_spvcStillTryingAlarm(Key);
+outgoing_callproceeding(destroy,Spvc,_) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = new_state_release_request(Spvc),
+ spvcDataBase:db_write(ets,Spvc1),
+ SpvcTpToHcId = read_spvcTpToHcId(Key),
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc1),
+ spvcLib:clear_spvcStillTryingAlarm(Key);
+outgoing_callproceeding(not_in_service,Spvc,_) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = new_state_not_in_service(Spvc),
+ spvcDataBase:db_write(Spvc1),
+ SpvcTpToHcId = read_spvcTpToHcId(Key),
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc1),
+ spvcLib:clear_spvcStillTryingAlarm(Key).
+
+active(restart,Spvc,_) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = new_state_release_at_restart(Spvc),
+ spvcDataBase:db_write(ets,Spvc1),
+ PchKey = case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end,
+ spvcLib:ilmi_change(PchKey,2),
+ case Spvc#spvcObj.spvcFrKey of
+ undefined ->
+ ok;
+ FrEndPoint ->
+ set_fr_atm_iw_admin_state(FrEndPoint,down,Spvc)
+ end;
+active(release_nu_enabled,Spvc,[HcId,Release]) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = new_state_rest_in_peace_or_wait(Spvc,[HcId,Release]),
+ [CcCause|_] = Release#hci_release.hci_cause_list,
+ Spvc2 = Spvc1#spvcObj{spvcLastReleaseCause = CcCause#hci_cause.hci_cause_value,
+ spvcLastReleaseDiagnostic = CcCause#hci_cause.hci_diagnostics_list},
+ spvcDataBase:db_write(ets,Spvc2),
+ PchKey = case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end,
+ spvcLib:ilmi_change(PchKey,2),
+ case Spvc#spvcObj.spvcFrKey of
+ undefined ->
+ ok;
+ FrEndPoint ->
+ set_fr_atm_iw_admin_state(FrEndPoint,down,Spvc)
+ end;
+active(release_nu_disabled,Spvc,[HcId,Release]) ->
+ debug_disabled,
+ case get_link_state_intf(case Spvc of
+ Spvc when record(Spvc,spvcObj) ->
+ case Spvc#spvcObj.spvcEntry of
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value
+ end;
+ Spvc when record(Spvc,spvcVcc) ->
+ {If_Value,_,_,_} = Spvc#spvcVcc.spvcVccEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVpc) ->
+ {If_Value,_,_} = Spvc#spvcVpc.spvcVpcEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVpcPerm) ->
+ {If_Value,_,_} = Spvc#spvcVpcPerm.spvcVpcEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcVccPerm) ->
+ {If_Value,_,_,_} = Spvc#spvcVccPerm.spvcVccEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcTargetVc) ->
+ {If_Value,_,_} = Spvc#spvcTargetVc.entry,
+ If_Value;
+ Spvc when record(Spvc,spvcTargetVp) ->
+ {If_Value,_} = Spvc#spvcTargetVp.entry,
+ If_Value;
+ Spvc when record(Spvc,pchVc) ->
+ {If_Value,_,_} = Spvc#pchVc.vclEntry,
+ If_Value;
+ Spvc when record(Spvc,pchVp) ->
+ {If_Value,_} = Spvc#pchVp.vplEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcFr) ->
+ {If_Value,_} = Spvc#spvcFr.spvcFrEntry,
+ If_Value;
+ Spvc when record(Spvc,spvcFrPerm) ->
+ {If_Value,_} = Spvc#spvcFrPerm.spvcFrEntry,
+ If_Value;
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value;
+ {If_Value,_} ->
+ If_Value;
+ [If_Value|_] ->
+ If_Value;
+ _ ->
+ error
+ end,active_release_nu_disabled) of
+ disabled ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = Spvc#spvcObj{currentState = rest_in_peace},
+ [CcCause|_] = Release#hci_release.hci_cause_list,
+ Spvc2 = Spvc1#spvcObj{spvcLastReleaseCause = CcCause#hci_cause.hci_cause_value,
+ spvcLastReleaseDiagnostic = CcCause#hci_cause.hci_diagnostics_list},
+ PchKey = case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end,
+ spvcLib:ilmi_change(PchKey,2),
+ update_state(Spvc,4),
+ spvcDataBase:db_write(ets,Spvc2),
+ case Spvc#spvcObj.spvcFrKey of
+ undefined ->
+ ok;
+ FrEndPoint ->
+ set_fr_atm_iw_admin_state(FrEndPoint,down,Spvc)
+ end;
+ enabled ->
+ active(release_nu_enabled,Spvc,[HcId,Release])
+ end;
+active(destroy,Spvc,_) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = new_state_release_request(Spvc),
+ spvcDataBase:db_write(ets,Spvc1),
+ PchKey = case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end,
+ spvcLib:ilmi_change(PchKey,2),
+ SpvcTpToHcId = read_spvcTpToHcId(Key),
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc);
+active(not_in_service,Spvc,_) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = new_state_not_in_service(Spvc),
+ spvcDataBase:db_write(Spvc1),
+ PchKey = case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end,
+ spvcLib:ilmi_change(PchKey,2),
+ SpvcTpToHcId = read_spvcTpToHcId(Key),
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc1),
+ case Spvc#spvcObj.spvcFrKey of
+ undefined ->
+ ok;
+ FrEndPoint ->
+ set_fr_atm_iw_admin_state(FrEndPoint,down,Spvc)
+ end;
+active(release_incumbent,Spvc,[Release]) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = new_state_awaiting_switch_over(Spvc),
+ spvcDataBase:db_write(Spvc1),
+ SpvcTpToHcId = read_spvcTpToHcId(Key),
+ spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc1).
+
+read_spvcTpToHcId({If,Vpi,Vci,Leaf}) ->
+ spvcDataBase:db_read({spvcTpToHcId,{orig,If,Vpi,Vci,Leaf}});
+read_spvcTpToHcId({If,Vpi,Leaf}) ->
+ spvcDataBase:db_read({spvcTpToHcId,{orig,If,Vpi,Leaf}}).
+
+release_request(release_nu,Spvc,[HcId,Release]) ->
+ debug_disabled,
+ clear(Spvc);
+release_request(release_comp_nu,Spvc,[HcId,Release_comp]) ->
+ debug_disabled,
+ clear(Spvc);
+release_request(destroy,Spvc,_) ->
+ debug_disabled,
+ case Spvc#spvcObj.spvcEntry of
+ {If,Vpi,Vci,Leaf} ->
+ case spvcDataBase:db_read({spvcTpToHcId,{orig,If,Vpi,Vci,Leaf}}) of
+ SpvcTpToHcId ->
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc),
+ clear(Spvc);
+ _ ->
+ ok
+ end;
+ {If,Vpi,Leaf} ->
+ case spvcDataBase:db_read({spvcTpToHcId,{orig,If,Vpi,Leaf}}) of
+ SpvcTpToHcId ->
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc),
+ clear(Spvc);
+ _ ->
+ ok
+ end
+ end,
+ ok;
+release_request(not_in_service,Spvc,_) ->
+ debug_disabled,
+ ok.
+
+release_at_restart(release_nu,Spvc,[HcId,Release]) ->
+ debug_disabled,
+ {Spvc1,NewHcId,Setup} = new_state_outgoing_call_proceeding(Spvc),
+ [CcCause|_] = Release#hci_release.hci_cause_list,
+ Spvc2 = Spvc1#spvcObj{spvcLastReleaseCause = CcCause#hci_cause.hci_cause_value,
+ spvcLastReleaseDiagnostic = CcCause#hci_cause.hci_diagnostics_list},
+ spvcDataBase:db_write(ets,Spvc2),
+ timer:sleep(500),
+ setup(NewHcId,Setup,Spvc2);
+release_at_restart(release_comp_nu,Spvc,[HcId,Release_complete]) ->
+ debug_disabled,
+ {Spvc1,NewHcId,Setup} = new_state_outgoing_call_proceeding(Spvc),
+ Spvc2 = Spvc1#spvcObj{spvcLastReleaseCause = 31,
+ spvcLastReleaseDiagnostic = []},
+ spvcDataBase:db_write(ets,Spvc2),
+ timer:sleep(500),
+ setup(NewHcId,Setup,Spvc1);
+release_at_restart(connect_nu,Spvc,_) ->
+ debug_disabled,
+ ok;
+release_at_restart(destroy,Spvc,_) ->
+ debug_disabled,
+ Spvc1 = new_state_release_request(Spvc),
+ spvcDataBase:db_write(ets,Spvc1);
+release_at_restart(restart,Spvc,_) ->
+ debug_disabled,
+ Spvc1 = new_state_release_at_restart(Spvc);
+release_at_restart(not_in_service,Spvc,_) ->
+ debug_disabled,
+ Spvc1 = new_state_not_in_service(Spvc),
+ spvcDataBase:db_write(Spvc1).
+
+wait(timeout,Spvc,_) ->
+ debug_disabled,
+ {Spvc1,HcId,Setup} = new_state_outgoing_call_proceeding(Spvc),
+ spvcDataBase:db_write(ets,Spvc1),
+ setup(HcId,Setup,Spvc1);
+wait(destroy,Spvc,_) ->
+ debug_disabled,
+ spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry),
+ clear(Spvc);
+wait(restart,Spvc,_) ->
+ debug_disabled,
+ {Spvc1,HcId,Setup} = new_state_outgoing_call_proceeding(Spvc#spvcObj{spvcRetryFailures = 0}),
+ spvcDataBase:db_write(ets,Spvc1),
+ spvcReestablishTimer:cancel(Spvc#spvcObj.spvcEntry),
+ spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry),
+ setup(HcId,Setup,Spvc1);
+wait(not_in_service,Spvc,_) ->
+ debug_disabled,
+ Spvc1 = new_state_not_in_service(Spvc),
+ spvcDataBase:db_write(Spvc1),
+ spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry).
+
+rest_in_peace(restart,Spvc,_) ->
+ debug_disabled,
+ {Spvc1,HcId,Setup} = new_state_outgoing_call_proceeding(Spvc#spvcObj{spvcRetryFailures = 0}),
+ spvcDataBase:db_write(ets,Spvc1),
+ setup(HcId,Setup,Spvc1),
+ sccmManager:cast_to_sccm(spvcLib:get_cp(om_node),spvcLib,clear_spvcFailingAlarm,[spvcLib:get_membership(node())]);
+rest_in_peace(destroy,Spvc,_) ->
+ debug_disabled,
+ sccmManager:cast_to_sccm(spvcLib:get_cp(om_node),spvcLib,clear_spvcFailingAlarm,[spvcLib:get_membership(node())]),
+ clear(Spvc);
+rest_in_peace(connect_nu,Spvc,_) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ SpvcTpToHcId = read_spvcTpToHcId(Key),
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(b_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc);
+rest_in_peace(not_in_service,Spvc,_) ->
+ debug_disabled,
+ Spvc1 = new_state_not_in_service(Spvc),
+ spvcDataBase:db_write(Spvc1),
+ sccmManager:cast_to_sccm(spvcLib:get_cp(om_node),spvcLib,clear_spvcFailingAlarm,[spvcLib:get_membership(node())]).
+
+not_in_service(activate_enabled,Spvc,_) ->
+ debug_disabled,
+ {Spvc1,HcId,Setup} = new_state_outgoing_call_proceeding(Spvc#spvcObj{spvcRetryFailures = 0}),
+ spvcDataBase:db_write(Spvc1#spvcObj{spvcRowStatus = 1}),
+ setup(HcId,Setup,Spvc1);
+not_in_service(activate_disabled,Spvc,_) ->
+ debug_disabled,
+ Spvc1 = new_state_rest_in_peace(Spvc),
+ spvcDataBase:db_write(Spvc1#spvcObj{spvcRowStatus = 1});
+not_in_service(connect_nu,Spvc,_) ->
+ debug_disabled,
+ Spvc1 = new_state_rest_in_peace(Spvc),
+ spvcDataBase:db_write(Spvc1#spvcObj{spvcRowStatus = 1}),
+ Key = Spvc#spvcObj.spvcEntry,
+ SpvcTpToHcId = read_spvcTpToHcId(Key),
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(b_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc1);
+not_in_service(destroy,Spvc,_) ->
+ debug_disabled,
+ clear(Spvc).
+
+awaiting_switch_over(switch_over,Spvc,[HcId]) ->
+ debug_disabled,
+ Spvc1 = Spvc#spvcObj{currentState = active},
+ Index = Spvc#spvcObj.spvcEntry,
+ TpIndex = create_tp_index(Index),
+ spvcDataBase:db_write(Spvc1),
+ ets:insert(spvcTpToHcId,#spvcTpToHcId{tpEntry = TpIndex,
+ hcId = HcId}),
+ ets:insert(spvcHcIdToTp,#spvcHcIdToTp{tpEntry = TpIndex,
+ hcId = HcId}),
+ update_dyn_table_hcid(Index,HcId),
+ ok;
+awaiting_switch_over(activate_disabled,Spvc,Attrs) ->
+ Spvc1 = new_state_rest_in_peace(Spvc),
+ spvcDataBase:db_write(Spvc1),
+ ok;
+awaiting_switch_over(restart,Spvc,Attrs) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Spvc1 = new_state_release_at_restart(Spvc),
+ spvcDataBase:db_write(ets,Spvc1),
+ PchKey = case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end,
+ spvcLib:ilmi_change(PchKey,2),
+ case Spvc#spvcObj.spvcFrKey of
+ undefined ->
+ ok;
+ FrEndPoint ->
+ set_fr_atm_iw_admin_state(FrEndPoint,down,Spvc)
+ end;
+awaiting_switch_over(destroy,Spvc,Attrs) ->
+ clear(Spvc).
+
+create_tp_index({If,Vpi,Vci,Leaf}) ->
+ list_to_tuple([orig,If,Vpi,Vci,Leaf]);
+create_tp_index({If,Vpi,Leaf}) ->
+ list_to_tuple([orig,If,Vpi,Leaf]).
+
+update_dyn_table_hcid({If,Vpi,Vci,Leaf},HcId) ->
+ [VcDyn] = ets:lookup(spvcVcDyn,{If,Vpi,Vci}),
+ ets:insert(spvcVcDyn,VcDyn#spvcVcDyn{vclConnId = HcId});
+update_dyn_table_hcid({If,Vpi,Leaf},HcId) ->
+ [VpDyn] = ets:lookup(spvcVpDyn,{If,Vpi}),
+ ets:insert(spvcVpDyn,VpDyn#spvcVpDyn{vplConnId = HcId}).
+
+new_state_outgoing_call_proceeding(Spvc) ->
+ debug_disabled,
+ Spvc1 = Spvc#spvcObj{spvcRowStatus = 1,
+ currentState = outgoing_callproceeding},
+ Key = Spvc1#spvcObj.spvcEntry,
+ update_state(Spvc,outgoing_callproceeding),
+ PchKey = case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end,
+ {FwdAtdIndex,BwdAtdIndex} = case PchKey of
+ {_,_,_} ->
+ Vc = spvcDataBase:db_read({pchVc,PchKey}),
+ {Vc#pchVc.vclReceiveTrafficDescrIndex,Vc#pchVc.vclTransmitTrafficDescrIndex};
+ {_,_} ->
+ Vp = spvcDataBase:db_read({pchVp,PchKey}),
+ {Vp#pchVp.vplReceiveTrafficDescrIndex,Vp#pchVp.vplTransmitTrafficDescrIndex}
+ end,
+ FwdPchAtd = spvcDataBase:db_read({pchAtd,FwdAtdIndex}),
+ BwdPchAtd = spvcDataBase:db_read({pchAtd,BwdAtdIndex}),
+ Row = tuple_to_list(Key),
+ HcId = spvcLib:create_hcid(Row,case Row of
+ Row when record(Row,spvcObj) ->
+ case Row#spvcObj.spvcEntry of
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value
+ end;
+ Row when record(Row,spvcVcc) ->
+ {If_Value,_,_,_} = Row#spvcVcc.spvcVccEntry,
+ If_Value;
+ Row when record(Row,spvcVpc) ->
+ {If_Value,_,_} = Row#spvcVpc.spvcVpcEntry,
+ If_Value;
+ Row when record(Row,spvcVpcPerm) ->
+ {If_Value,_,_} = Row#spvcVpcPerm.spvcVpcEntry,
+ If_Value;
+ Row when record(Row,spvcVccPerm) ->
+ {If_Value,_,_,_} = Row#spvcVccPerm.spvcVccEntry,
+ If_Value;
+ Row when record(Row,spvcTargetVc) ->
+ {If_Value,_,_} = Row#spvcTargetVc.entry,
+ If_Value;
+ Row when record(Row,spvcTargetVp) ->
+ {If_Value,_} = Row#spvcTargetVp.entry,
+ If_Value;
+ Row when record(Row,pchVc) ->
+ {If_Value,_,_} = Row#pchVc.vclEntry,
+ If_Value;
+ Row when record(Row,pchVp) ->
+ {If_Value,_} = Row#pchVp.vplEntry,
+ If_Value;
+ Row when record(Row,spvcFr) ->
+ {If_Value,_} = Row#spvcFr.spvcFrEntry,
+ If_Value;
+ Row when record(Row,spvcFrPerm) ->
+ {If_Value,_} = Row#spvcFrPerm.spvcFrEntry,
+ If_Value;
+ {If_Value,_,_,_} ->
+ If_Value;
+ {If_Value,_,_} ->
+ If_Value;
+ {If_Value,_} ->
+ If_Value;
+ [If_Value|_] ->
+ If_Value;
+ _ ->
+ error
+ end),
+ Setup = spvcEncode:encode_cc_setup(Row,Spvc1,FwdPchAtd,BwdPchAtd),
+ debug_disabled,
+ debug_disabled,
+ debug_disabled,
+ {Spvc1,HcId,Setup}.
+
+new_state_release_request(Spvc) ->
+ debug_disabled,
+ update_state(Spvc,release_request),
+ Spvc#spvcObj{currentState = release_request}.
+
+new_state_release_at_restart(Spvc) ->
+ debug_disabled,
+ Spvc1 = Spvc#spvcObj{spvcRetryFailures = 0,
+ currentState = release_at_restart},
+ update_state(Spvc,release_at_restart),
+ HcId = spvcEncode:encode_cc_hcid(Spvc1#spvcObj.spvcEntry),
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(a_side,HcId,Release,Spvc1),
+ Spvc1.
+
+new_state_rest_in_peace_or_wait(Spvc,[HcId,HciMsg]) ->
+ debug_disabled,
+ Spvc1 = Spvc#spvcObj{spvcRetryFailures = Spvc#spvcObj.spvcRetryFailures + 1},
+ case check_limits(Spvc1) of
+ {ok,ok,no_retries} ->
+ send_spvcFailingAlarm(Spvc#spvcObj.spvcEntry),
+ update_state(Spvc,4),
+ spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry),
+ Spvc1#spvcObj{currentState = rest_in_peace};
+ {ok,ok,_} ->
+ Spvc2 = Spvc1#spvcObj{spvcRetryTimer = time(),
+ currentState = wait},
+ update_state(Spvc,wait),
+ start_timer(wait,Spvc2),
+ Spvc2;
+ {retry_threshold,ok,no_retries} ->
+ Spvc2 = Spvc1#spvcObj{currentState = rest_in_peace},
+ update_state(Spvc,4),
+ send_call_failure(Spvc),
+ send_spvcFailingAlarm(Spvc#spvcObj.spvcEntry),
+ spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry),
+ Spvc2;
+ {retry_threshold,ok,_} ->
+ Spvc2 = Spvc1#spvcObj{spvcRetryTimer = time(),
+ currentState = wait},
+ update_state(Spvc,wait),
+ send_call_failure(Spvc2),
+ start_timer(wait,Spvc2),
+ Spvc2;
+ {ok,retry_limit,_} ->
+ send_spvcFailingAlarm(Spvc#spvcObj.spvcEntry),
+ update_state(Spvc,4),
+ spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry),
+ Spvc1#spvcObj{currentState = rest_in_peace};
+ {retry_threshold,retry_limit,_} ->
+ Spvc2 = Spvc1#spvcObj{currentState = rest_in_peace},
+ update_state(Spvc,4),
+ send_call_failure(Spvc2),
+ send_spvcFailingAlarm(Spvc#spvcObj.spvcEntry),
+ spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry),
+ Spvc2
+ end.
+
+send_call_failure(Spvc) ->
+ case Spvc#spvcObj.spvcRetryThreshold of
+ 0 ->
+ ok;
+ _ ->
+ sccmManager:cast_to_sccm(spvcLib:get_cp(om_node),spvcOrig,call_failure,[Spvc])
+ end.
+
+new_state_rest_in_peace(Spvc) ->
+ debug_disabled,
+ update_state(Spvc,4),
+ Spvc1 = Spvc#spvcObj{spvcRetryFailures = Spvc#spvcObj.spvcRetryFailures + 1},
+ send_spvcFailingAlarm(Spvc#spvcObj.spvcEntry),
+ case check_limits(Spvc1) of
+ {ok,_,_} ->
+ Spvc1#spvcObj{currentState = rest_in_peace};
+ {retry_threshold,_,_} ->
+ Spvc2 = Spvc1#spvcObj{currentState = rest_in_peace},
+ case Spvc2#spvcObj.spvcRetryThreshold of
+ 0 ->
+ ok;
+ _ ->
+ sccmManager:cast_to_sccm(spvcLib:get_cp(om_node),spvcOrig,call_failure,[Spvc2])
+ end,
+ Spvc2
+ end.
+
+new_state_active(Spvc) ->
+ debug_disabled,
+ update_state(Spvc,3),
+ Spvc#spvcObj{spvcRetryFailures = 0,
+ currentState = active}.
+
+new_state_created(Spvc,SetCols) ->
+ debug_disabled,
+ update_state(Spvc,created),
+ case spvcSNMP:is_all_values(case Spvc#spvcObj.spvcEntry of
+ {_,_,_,_} ->
+ spvcVcc;
+ {_,_,_} ->
+ spvcVpc;
+ {_,_} ->
+ spvcFr;
+ [_,_,_,_] ->
+ spvcVcc;
+ [_,_,_] ->
+ spvcVpc;
+ [_,_] ->
+ spvcFr
+ end,SetCols) of
+ true ->
+ Spvc1 = Spvc#spvcObj{spvcRowStatus = 2,
+ currentState = created},
+ set_attrs(Spvc1,SetCols);
+ false ->
+ Spvc1 = Spvc#spvcObj{spvcRowStatus = 3,
+ currentState = created},
+ set_attrs(Spvc1,SetCols)
+ end.
+
+new_state_not_in_service(Spvc) ->
+ debug_disabled,
+ update_state(Spvc,not_in_service),
+ Spvc#spvcObj{currentState = not_in_service,
+ spvcRowStatus = 2}.
+
+new_state_awaiting_switch_over(Spvc) ->
+ debug_disabled,
+ Spvc#spvcObj{currentState = awaiting_switch_over}.
+
+update_state(Spvc,NewState) ->
+ State = Spvc#spvcObj.currentState,
+ SpvcEntry = Spvc#spvcObj.spvcEntry,
+ debug_disabled,
+ spvcLib:update_state({State,SpvcEntry},NewState).
+
+send_spvcFailingAlarm(Key) ->
+ debug_disabled,
+ rpc:cast(spvcLib:get_cp(om_node),spvcLib,send_spvcFailingAlarm,[Key]).
+
+set_call_failure_data_and_send_spvcFailingAlarm({If,Vpi,Leaf}) ->
+ debug_disabled,
+ Spvc = spvcDataBase:db_read({spvcObj,{If,Vpi,Leaf}}),
+ if
+ Spvc == [] ->
+ ok;
+ true ->
+ spvcLib:update_state({Spvc#spvcObj.currentState,{If,Vpi,Leaf}},4)
+ end;
+set_call_failure_data_and_send_spvcFailingAlarm({If,Vpi,Vci,Leaf}) ->
+ debug_disabled,
+ Spvc = spvcDataBase:db_read({spvcObj,{If,Vpi,Vci,Leaf}}),
+ if
+ Spvc == [] ->
+ ok;
+ true ->
+ spvcLib:update_state({Spvc#spvcObj.currentState,{If,Vpi,Vci,Leaf}},4)
+ end.
+
+set_attrs(Spvc,SetCols) ->
+ case Spvc#spvcObj.spvcEntry of
+ {_,_,_,_} ->
+ set_attrs_spvcc(Spvc,SetCols);
+ {_,_,_} ->
+ set_attrs_spvpc(Spvc,SetCols)
+ end.
+
+set_attrs_spvcc(Spvc,[{2,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetAddress = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{3,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetSelectType = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{18,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetVpi = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{4,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetVpi = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{5,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetVci = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{6,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcLastReleaseCause = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{7,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcLastReleaseDiagnostic = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{10,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryInterval = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{11,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryTimer = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{12,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryThreshold = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{13,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryFailures = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{14,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryLimit = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{16,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetDlci = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[{17,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetType = Value},
+ set_attrs_spvcc(Spvc1,T);
+set_attrs_spvcc(Spvc,[_|T]) ->
+ set_attrs_spvcc(Spvc,T);
+set_attrs_spvcc(Spvc,[]) ->
+ debug_disabled,
+ Spvc.
+
+set_attrs_spvpc(Spvc,[{2,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetAddress = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{3,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetSelectType = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{15,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetVpi = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{4,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcTargetVpi = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{5,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcLastReleaseCause = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{6,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcLastReleaseDiagnostic = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{9,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryInterval = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{10,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryTimer = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{11,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryThreshold = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{12,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryFailures = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[{13,Value}|T]) ->
+ Spvc1 = Spvc#spvcObj{spvcRetryLimit = Value},
+ set_attrs_spvpc(Spvc1,T);
+set_attrs_spvpc(Spvc,[_|T]) ->
+ set_attrs_spvpc(Spvc,T);
+set_attrs_spvpc(Spvc,[]) ->
+ Spvc.
+
+call_failure(Spvc) ->
+ debug_disabled,
+ Key = case Spvc#spvcObj.spvcFrKey of
+ undefined ->
+ spvcLib:update_counter(callFailures,1,spvcLib:get_membership(node())),
+ atm_spvc;
+ _ ->
+ spvcLib:update_counter(callFrFailures,1,spvcLib:get_membership(node())),
+ fr_spvc
+ end,
+ Obj = spvcDataBase:db_read({spvcFailures,Key}),
+ case Obj#spvcFailures.spvcCallFailuresTrapEnable of
+ 1 ->
+ EventIndObj = spvcDataBase:db_read({spvcEventIndicator,Key}),
+ case EventIndObj#spvcEventIndicator.spvcTimerInd of
+ 1 ->
+ spvcDataBase:db_write(EventIndObj#spvcEventIndicator{spvcSendEventInd = 1}),
+ NI = Obj#spvcFailures.spvcNotificationInterval,
+ sysTimer:apply_after(1000 * NI,spvcOrig,timeout_event,[EventIndObj]);
+ _ ->
+ spvcManager:send_event(Key),
+ NI = Obj#spvcFailures.spvcNotificationInterval,
+ sysTimer:apply_after(1000 * NI,spvcManager,timeout,[Key]),
+ spvcDataBase:db_write(EventIndObj#spvcEventIndicator{spvcTimerInd = 1,
+ spvcSendEventInd = 2})
+ end;
+ _ ->
+ ok
+ end.
+
+timeout_event(EventIndObj) ->
+ spvcDataBase:db_write(EventIndObj#spvcEventIndicator{spvcTimerInd = 2}).
+
+check_limits(Spvc) ->
+ debug_disabled,
+ T = Spvc#spvcObj.spvcRetryThreshold,
+ L = Spvc#spvcObj.spvcRetryLimit,
+ F = Spvc#spvcObj.spvcRetryFailures,
+ I = Spvc#spvcObj.spvcRetryInterval,
+ {check_threshold(F,T),check_limit(F,L),check_interval(I)}.
+
+check_threshold(Failures,Threshold) when Failures == Threshold ->
+ debug_disabled,
+ retry_threshold;
+check_threshold(Failures,Threshold) ->
+ debug_disabled,
+ ok.
+
+check_limit(Failures,0) ->
+ debug_disabled,
+ ok;
+check_limit(Failures,Limit) when Failures < Limit ->
+ debug_disabled,
+ ok;
+check_limit(Failures,Limit) ->
+ debug_disabled,
+ retry_limit.
+
+check_interval(0) ->
+ no_retries;
+check_interval(I) ->
+ I.
+
+start_timer(wait,Spvc) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ Id = spvcReestablishTimer:apply_after(backoff_delay(Key),spvcServer,cast_to_spvc,[node(),spvcOrig,timeout,[wait,Key]]).
+
+timeout(wait,Key) ->
+ debug_disabled,
+ case spvcDataBase:db_read({spvcObj,Key}) of
+ [] ->
+ debug_disabled,
+ ok;
+ Spvc ->
+ case Spvc#spvcObj.currentState of
+ wait ->
+ IfIndex = element(1,Key),
+ case spvcOam:is_reassign_et_in_progress(IfIndex) of
+ true ->
+ ok;
+ _ ->
+ orig_state_machine(wait,timeout,Spvc,[])
+ end;
+ _ ->
+ ok
+ end
+ end;
+timeout(X,Y) ->
+ debug_disabled,
+ ok.
+
+clear(Spvc) ->
+ debug_disabled,
+ Key = Spvc#spvcObj.spvcEntry,
+ PchKey = case Key of
+ {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
+ {IfIndex_Value,Vpi_Value,Vci_Value};
+ {IfIndex_Value,Vpi_Value,_} ->
+ {IfIndex_Value,Vpi_Value};
+ [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
+ [IfIndex_Value,Vpi_Value,Vci_Value];
+ [IfIndex_Value,Vpi_Value,_] ->
+ [IfIndex_Value,Vpi_Value]
+ end,
+ spvcEndPoint:free_tp_spvc(PchKey),
+ spvcDataBase:db_delete({spvcObj,Key}),
+ update_state(Spvc,clear),
+ OrigKey = list_to_tuple([orig] ++ tuple_to_list(Key)),
+ case Spvc#spvcObj.currentState of
+ created ->
+ ok;
+ _ ->
+ case spvcDataBase:db_read({spvcTpToHcId,OrigKey}) of
+ [] ->
+ ok;
+ #spvcTpToHcId{hcId = HcId} ->
+ spvcDataBase:db_delete({spvcHcIdToTp,HcId})
+ end,
+ ets:delete(spvcTpToHcId,OrigKey),
+ spvcReestablishTimer:cancel(Key),
+ ets:delete(spvcBackoff,Spvc#spvcObj.spvcEntry)
+ end,
+ case Spvc#spvcObj.spvcFrKey of
+ undefined ->
+ sccmManager:cast_to_sccm(spvcLib:get_cp(om_node),spvcEndPoint,remove_tp,[tuple_to_list(PchKey)]);
+ FrKey ->
+ spvcFr:clean_up(FrKey)
+ end,
+ case {Spvc#spvcObj.spvcRerCap,Spvc#spvcObj.spvcEntry} of
+ {false,_} ->
+ ok;
+ {true,Entry} when size(Entry) == 3 ->
+ spvcDataBase:db_delete({spvcRerVp,Entry});
+ {true,Entry} when size(Entry) == 4 ->
+ spvcDataBase:db_delete({spvcRerVc,Entry})
+ end.
+
+get_link_state(If) when integer(If) ->
+ debug_disabled,
+ cnhChi:get_link_opstate(If);
+get_link_state(Other) ->
+ debug_disabled,
+ disabled.
+
+get_link_state_intf(If,Msg) when integer(If) ->
+ debug_disabled,
+ case cnhChi:get_link_opstate(If) of
+ enabled ->
+ enabled;
+ _ ->
+ Om_Node = spvcLib:get_cp(om_node),
+ case rpc:call(Om_Node,intfI,get_link_op_state,[If]) of
+ {ok,enabled} ->
+ enabled;
+ Result ->
+ disabled
+ end
+ end;
+get_link_state_intf(Other,Msg) ->
+ debug_disabled,
+ disabled.
+
+setup(HcId,Setup,Spvc) ->
+ case spvcDataBase:db_read({spvcObj,Spvc#spvcObj.spvcEntry}) of
+ [] ->
+ ok;
+ Spvc1 ->
+ case Spvc#spvcObj.currentState == Spvc1#spvcObj.currentState of
+ true ->
+ spvcLib:increase_counter(spvcSaEtStat,Spvc),
+ case Spvc#spvcObj.spvcFrKey of
+ undefined ->
+ do_setup(HcId,Setup,Spvc#spvcObj.spvcRerCap);
+ FrKey ->
+ do_setup(HcId,Setup,FrKey)
+ end;
+ _ ->
+ ok
+ end
+ end.
+
+do_setup(HcId,Setup,Type) when Type == undefined; Type == false ->
+ debug_disabled,
+ ReturnData = {0,HcId},
+ L3Data = {0,[HcId,Setup]},
+ mdisp:msg(node(),{plcOperator,1,infinity},{HcId,{spvcI,ReturnData}},{ccI,l3_msg,[HcId,spvcI,L3Data]});
+do_setup(HcId,Setup,true) ->
+ debug_disabled,
+ ReturnData = {0,HcId},
+ L3Data = {0,[HcId,Setup]},
+ mdisp:msg(node(),{plcOperator,1,infinity},{HcId,{spvcRerI,ReturnData}},{ccI,l3_msg,[HcId,spvcRerI,L3Data]});
+do_setup(HcId,Setup,FrKey) ->
+ debug_disabled,
+ ReturnData = {0,HcId},
+ L3Data = {0,[HcId,Setup]},
+ mdisp:msg(node(),{plcOperator,1,infinity},{HcId,{spvcFrI,ReturnData}},{ccI,l3_msg,[HcId,spvcFrI,L3Data]}).
+
+backoff_delay(Key) ->
+ debug_disabled,
+ Obj = spvcDataBase:db_read({spvcObj,Key}),
+ Var = spvcDataBase:db_read({spvcFailures,atm_spvc}),
+ {Delay,Flag} = case Obj#spvcObj.spvcRetryFailures of
+ 0 ->
+ {100,no_alarm};
+ 1 ->
+ {Obj#spvcObj.spvcRetryInterval,no_alarm};
+ _ ->
+ Table = get_backoff_table(Key,Obj),
+ Max_Delay = Var#spvcFailures.max_delay,
+ case Var#spvcFailures.delay_factor * Table#spvcBackoff.delay_time of
+ DelayValue when DelayValue < Max_Delay ->
+ {DelayValue,no_alarm};
+ _ ->
+ Org_Retry_Interval = Obj#spvcObj.spvcRetryInterval,
+ if
+ Org_Retry_Interval < Max_Delay ->
+ spvcLib:send_spvcStillTryingAlarm(Key,Table#spvcBackoff.flag),
+ {Max_Delay,alarm};
+ true ->
+ spvcLib:send_spvcStillTryingAlarm(Key,Table#spvcBackoff.flag),
+ {Org_Retry_Interval,alarm}
+ end
+ end
+ end,
+ ets:insert(spvcBackoff,#spvcBackoff{key = Key,
+ delay_time = Delay,
+ flag = Flag}),
+ round(Delay).
+
+get_backoff_table(Index,Spvc) ->
+ case ets:lookup(spvcBackoff,Index) of
+ [Obj] ->
+ Obj;
+ _ ->
+ #spvcBackoff{key = Spvc#spvcObj.spvcEntry,
+ delay_time = Spvc#spvcObj.spvcRetryInterval,
+ flag = no_alarm}
+ end.
+
+set_fr_atm_iw_admin_state(FrEndPoint,up,Spvc) ->
+ ok;
+set_fr_atm_iw_admin_state(FrEndPoint,NewStatus,Spvc) ->
+ ok.
+
+forced_release(FrEndPoint) ->
+ FrPerm = spvcDataBase:db_read({spvcFr,FrEndPoint}),
+ case FrPerm of
+ [] ->
+ {error,no_fr_spvc};
+ _ ->
+ Key = FrPerm#spvcFr.spvcFrAtmEntry,
+ Spvc = spvcDataBase:db_read({spvcObj,Key}),
+ SpvcFrObj = spvcDataBase:db_read({spvcFrPerm,FrEndPoint}),
+ case SpvcFrObj#spvcFrPerm.spvcFrConnect of
+ 3 ->
+ SpvcTpToHcId = read_spvcTpToHcId(Key),
+ Release = spvcEncode:encode_cc_release(31),
+ spvcManager:release_un(b_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc);
+ _ ->
+ {error,target_not_owned_by_this_connection}
+ end
+ end.
diff --git a/lib/dialyzer/test/user_SUITE_data/src/wdp.hrl b/lib/dialyzer/test/user_SUITE_data/src/wdp.hrl
new file mode 100644
index 0000000000..767e4d84c3
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/wdp.hrl
@@ -0,0 +1,96 @@
+
+%%
+%% WAP Port Number Definitions (WDP Appendix B.)
+%%
+
+-define(WAP_PORT_WTA_CL_SEC, 2805).
+-define(WAP_PORT_WTA_CO_SEC, 2923).
+-define(WAP_PORT_PUSH_CL, 2948).
+-define(WAP_PORT_PUSH_CL_SEC, 2949).
+
+-define(WAP_PORT_CL, 9200).
+-define(WAP_PORT_CO, 9201).
+-define(WAP_PORT_CL_SEC, 9202).
+-define(WAP_PORT_CO_SEC, 9203).
+-define(WAP_PORT_VCARD, 9204).
+-define(WAP_PORT_VCAL, 9205).
+-define(WAP_PORT_VCARD_SEC, 9206).
+-define(WAP_PORT_VCAL_SEC, 9207).
+
+-define(WAP_PORT_RINGTONE, 5505).
+-define(WAP_PORT_OPER_LOGO, 5506).
+-define(WAP_PORT_CLI_LOGO, 5507).
+
+%%
+%% WDP Bearer Type Assignments (WDP Appendix C.)
+%%
+
+%%
+%% Names after the tag WAP_BEARER_ is [network]_[bearer_type]_[address_type]
+%%
+-define(WAP_BEARER_ANY_ANY_IPV4, 16#00).
+-define(WAP_BEARER_ANY_ANY_IPV6, 16#01).
+-define(WAP_BEARER_GSM_USSD_ANY, 16#02).
+-define(WAP_BEARER_GSM_SMS_GSMMSISDN, 16#03).
+-define(WAP_BEARER_ANSI136_GUTS_ANSI136MSISDN, 16#04).
+-define(WAP_BEARER_IS95CDMA_SMS_IS637MSISDN, 16#05).
+-define(WAP_BEARER_IS95CDMA_CSD_IPV4, 16#06).
+-define(WAP_BEARER_IS95CDMA_PACKETDATA_IPV4, 16#07).
+-define(WAP_BEARER_ANSI136_CSD_IPV4, 16#08).
+-define(WAP_BEARER_ANSI136_PACKETDATA_IPV4, 16#09).
+-define(WAP_BEARER_GSM_CSD_IPV4, 16#0a).
+-define(WAP_BEARER_GSM_GPRS_IPV4, 16#0b).
+-define(WAP_BEARER_GSM_USSD_IPV4, 16#0c).
+-define(WAP_BEARER_AMPS_CDPD_IPV4, 16#0d).
+-define(WAP_BEARER_PDC_CSD_IPV4, 16#0e).
+-define(WAP_BEARER_PDC_PACKETDATA_IPV4, 16#0f).
+-define(WAP_BEARER_IDEN_SMS_IDENMSISDN, 16#10).
+-define(WAP_BEARER_IDEN_CSD_IPV4, 16#11).
+-define(WAP_BEARER_IDEN_PACKETDATA_IPV4, 16#12).
+-define(WAP_BEARER_PAGINGNETWORK_FLEX_FLEXMSISDN, 16#13).
+-define(WAP_BEARER_PHS_SMS_PHSMSISDN, 16#14).
+-define(WAP_BEARER_PHS_CSD_IPV4, 16#15).
+-define(WAP_BEARER_GSM_USSD_GSMSERVICECODE, 16#16).
+-define(WAP_BEARER_TETRA_SDS_TETRAITSI, 16#17).
+-define(WAP_BEARER_TETRA_SDS_TETRAMSISDN, 16#18).
+-define(WAP_BEARER_TETRA_PACKETDATA_IPV4, 16#19).
+-define(WAP_BEARER_PAGINGNETWORK_REFLEX_REFLEXMSISDN, 16#1a).
+-define(WAP_BEARER_GSM_USSD_GSMMSISDN, 16#1b).
+-define(WAP_BEARER_MOBITEX_MPAK_MAN, 16#1c).
+-define(WAP_BEARER_ANSI136_GHOST_GSMMSISDN, 16#1d).
+
+-record(wdp_address,
+ {
+ bearer,
+ address,
+ portnum
+ }).
+
+-record(wdp_sap_info,
+ {
+ mtu, %% max transmission unit (bytes)
+ mru %% max receive unit (bytes)
+ }).
+
+%%
+%% Source and destination address are wdp_addresses
+%%
+-record(wdp_socket_pair,
+ {
+ source,
+ destination
+ }).
+
+-record(wdp_local_port,
+ {
+ port, %% wdp "socket"
+ sap, %% source address
+ user, %% WDP user process
+ monitor %% monitor on WDP user
+ }).
+
+-record(wdp_local_sap,
+ {
+ sap, %% source address
+ port %% wdp "socket"
+ }).
diff --git a/lib/dialyzer/test/user_SUITE_data/src/wsp.hrl b/lib/dialyzer/test/user_SUITE_data/src/wsp.hrl
new file mode 100644
index 0000000000..0adcc13874
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/wsp.hrl
@@ -0,0 +1,239 @@
+
+%% WSP Table 34. PDU Type Assignments
+%%
+
+-define(WSP_Connect, 16#01).
+-define(WSP_ConnectReply, 16#02).
+-define(WSP_Redirect, 16#03).
+-define(WSP_Reply, 16#04).
+-define(WSP_Disconnect, 16#05).
+-define(WSP_Push, 16#06).
+-define(WSP_ConfirmedPush, 16#07).
+-define(WSP_Suspend, 16#08).
+-define(WSP_Resume, 16#09).
+
+-define(WSP_Get, 16#40).
+-define(WSP_Options, 16#41).
+-define(WSP_Head, 16#42).
+-define(WSP_Delete, 16#43).
+-define(WSP_Trace, 16#44).
+
+-define(WSP_Post, 16#60).
+-define(WSP_Put, 16#61).
+
+-define(WSP_DataFragmentPDU, 16#80).
+
+%%
+%% WSP Table 37. Capability Assignments
+%%
+
+-define(WSP_CAP_CLIENT_SDU_SIZE, 16#00).
+-define(WSP_CAP_SERVER_SDU_SIZE, 16#01).
+-define(WSP_CAP_PROTOCOL_OPTIONS, 16#02).
+-define(WSP_CAP_METHOD_MOR, 16#03).
+-define(WSP_CAP_PUSH_MOR, 16#04).
+-define(WSP_CAP_EXTENDED_METHODS, 16#05).
+-define(WSP_CAP_HEADER_CODE_PAGES, 16#06).
+-define(WSP_CAP_ALIASES, 16#07).
+-define(WSP_CAP_CLIENT_MESSAGE_SIZE, 16#08).
+-define(WSP_CAP_SERVER_MESSAGE_SIZE, 16#09).
+
+-define(WSP_CODEPAGE_1, 1).
+-define(WSP_DEFAULT_CODEPAGE, ?WSP_CODEPAGE_1).
+
+-define(ANY_LANGUAGE,128).
+
+-define(WSP_10, {1,0}).
+-define(WSP_11, {1,1}).
+-define(WSP_12, {1,2}).
+-define(WSP_13, {1,3}).
+-define(WSP_14, {1,4}).
+-define(WSP_15, {1,5}).
+
+-define(WSP_COMPLIENT_VERSION, ?WSP_15).
+-define(WSP_DEFAULT_VERSION, ?WSP_12).
+
+-define(WSP_STATUS_CONTINUE, 100).
+-define(WSP_STATUS_SWITCHING_PROTOCOLS, 101).
+-define(WSP_STATUS_OK, 200).
+-define(WSP_STATUS_CREATED, 201).
+-define(WSP_STATUS_ACCEPTED, 202).
+-define(WSP_STATUS_NON_AUTHORITATIVE_INFORMATION, 203).
+-define(WSP_STATUS_NO_CONTENT, 204).
+-define(WSP_STATUS_RESET_CONTENT, 205).
+-define(WSP_STATUS_PARTIAL_CONTENT, 206).
+-define(WSP_STATUS_MULTIPLE_CHOICES, 300).
+-define(WSP_STATUS_MOVED_PERMANENTLY, 301).
+-define(WSP_STATUS_MOVED_TEMPORARILY, 302).
+-define(WSP_STATUS_SEE_OTHER, 303).
+-define(WSP_STATUS_NOT_MODIFIED, 304).
+-define(WSP_STATUS_USE_PROXY, 305).
+-define(WSP_STATUS_RESERVED, 306).
+-define(WSP_STATUS_TEMPORARY_REDIRECT, 307).
+-define(WSP_STATUS_BAD_REQUEST, 400).
+-define(WSP_STATUS_UNAUTHORIZED, 401).
+-define(WSP_STATUS_PAYMENT_REQUIRED, 402).
+-define(WSP_STATUS_FORBIDDEN, 403).
+-define(WSP_STATUS_NOT_FOUND, 404).
+-define(WSP_STATUS_METHOD_NOT_ALLOWED, 405).
+-define(WSP_STATUS_NOT_ACCEPTABLE, 406).
+-define(WSP_STATUS_PROXY_AUTHENTICATION_REQUIRED, 407).
+-define(WSP_STATUS_REQUEST_TIMEOUT, 408).
+-define(WSP_STATUS_CONFLICT, 409).
+-define(WSP_STATUS_GONE, 410).
+-define(WSP_STATUS_LENGTH_REQUIRED, 411).
+-define(WSP_STATUS_PRECONDITION_FAILED, 412).
+-define(WSP_STATUS_REQUEST_ENTITY_TOO_LARGE, 413).
+-define(WSP_STATUS_REQUEST_URI_TOO_LARGE, 414).
+-define(WSP_STATUS_UNSUPPORTED_MEDIA_TYPE, 415).
+-define(WSP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE, 416).
+-define(WSP_STATUS_EXPECTATION_FAILED, 417).
+-define(WSP_STATUS_INTERNAL_SERVER_ERROR, 500).
+-define(WSP_STATUS_NOT_IMPLEMENTED, 501).
+-define(WSP_STATUS_BAD_GATEWAY, 502).
+-define(WSP_STATUS_SERVICE_UNAVAILABLE, 503).
+-define(WSP_STATUS_GATEWAY_TIMEOUT, 504).
+-define(WSP_STATUS_HTTP_VERSION_NOT_SUPPORTED, 505).
+
+-define(ENCODE_SHORT(X), <<1:1, (X):7>>).
+
+-define(ENCODE_LONG(X),
+ if (X) =< 16#ff -> <<1, (X):8>>;
+ (X) =< 16#ffff -> <<2, (X):16>>;
+ (X) =< 16#ffffff -> <<3, (X):24>>;
+ (X) =< 16#ffffffff -> <<4, (X):32>>;
+ true -> encode_long1(X)
+ end).
+
+
+-record(wsp_session,
+ {
+ id, %% uniq session id
+ ref, %% address quadruple (socketpair)
+ state=null, %% connected, suspended
+ version, %% encoding version to use
+ capabilities, %% client capabilities
+ headers %% client hop-by-hop headers!!!
+ }).
+
+-record(wsp_header,
+ {
+ name, %% field name
+ value, %% field value (binary value)
+ params=[] %% field params [{Name,Value} | Value]
+ }).
+
+-record(wsp_multipart_entry,
+ {
+ content_type, %% #wsp_header
+ headers=[],
+ data=(<<>>)
+ }).
+
+-record(wsp_capabilities,
+ {
+ aliases=[], %% [#wdp_address]
+ client_sdu_size=1400,
+ extended_methods=[], %% [{PduType, Name}]
+ header_code_pages=[], %% [{Page,Name}] | [Page]
+ protocol_options=[], %% [push,confirmed_push,resume,
+ %% acknowledgement_headers]
+ method_mor = 10, %% 1?
+ push_mor = 10, %% 1?
+ server_sdu_size=1400,
+ client_message_size,
+ server_message_size,
+ unknown=[]
+ }).
+
+%% WSP PDU records
+
+-record(wsp_connect,
+ {
+ version, %% protocol version, not wsp version?
+ capabilities,
+ headers
+ }).
+
+-record(wsp_connect_reply,
+ {
+ server_session_id,
+ capabilities,
+ headers=[]
+ }).
+
+-define(WSP_PERMANENT_REDIRECT, 16#80).
+-define(WSP_REUSE_SECURITY, 16#40).
+
+-record(wsp_redirect,
+ {
+ flags=[],
+ addresses=[]
+ }).
+
+-record(wsp_disconnect,
+ {
+ server_session_id
+ }).
+
+-record(wsp_get,
+ {
+ type,
+ uri,
+ headers=[]
+ }).
+
+-record(wsp_post,
+ {
+ type,
+ uri,
+ content_type, %% #wsp_header
+ headers=[],
+ data
+ }).
+
+-record(wsp_reply,
+ {
+ status,
+ content_type, %% #wsp_header
+ headers=[],
+ data
+ }).
+
+-record(wsp_data_fragment_pdu,
+ {
+ headers=[],
+ data
+ }).
+
+-record(wsp_push,
+ {
+ type = push,
+ content_type, %% #wsp_header
+ headers=[],
+ data
+ }).
+
+-record(wsp_suspend,
+ {
+ session_id
+ }).
+
+-record(wsp_resume,
+ {
+ session_id,
+ capabilities,
+ headers
+ }).
+
+%% NOTE: not a real pdu
+-record(wsp_acknowledgement_headers,
+ {
+ headers=[]
+ }).
+
+-record(wsp_unknown_pdu,
+ {
+ type, %% integer
+ data %% the payload
+ }).
diff --git a/lib/dialyzer/test/user_SUITE_data/src/wsp_pdu.erl b/lib/dialyzer/test/user_SUITE_data/src/wsp_pdu.erl
new file mode 100644
index 0000000000..e5b387478f
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/wsp_pdu.erl
@@ -0,0 +1,5423 @@
+%%%=======================================================================
+%%% File : wsp_pdu.erl
+%%% Author : Tony Rogvall <[email protected]>
+%%% Description : WSP PDU
+%%% Created : 18 Aug 2003 by <[email protected]>
+%%%=======================================================================
+%%%
+%%% There are a couple of bugs in this file. Some are detected by
+%%% Dialyzer v1.1 starting both from byte code and from source, some
+%%% other ones are detected only starting from sourse, while some
+%%% others go unnoticed (these are identified by "BUG" below). It is
+%%% expected that at least some of them are detected when the new type
+%%% analysis is integrated into Dialyzer. Some other ones, like the
+%%% one with the unused _Acc argument are harder to detect and might
+%%% require different techniques.
+%%%
+%%%=======================================================================
+
+-module(wsp_pdu).
+-export([encode/1, encode/2, decode/1, decode/2]).
+
+%% The following is just to suppress unused function warnings
+-export([decode_address/1, decode_header/2,
+ decode_headers/1, decode_mms_version/1, decode_multipart/1,
+ encode_headers/1, encode_mms_version/1, encode_multipart/1,
+ encode_language/1, encode_short_integer/1,
+ fmt_current_date/0,
+ format_header/1, format_headers/1,
+ parse_header/1, format/1]).
+
+-include("wsp.hrl").
+-include("wdp.hrl").
+
+-ifdef(debug).
+-define(dbg(Fmt,Args), io:format(Fmt, Args)).
+-else.
+-define(dbg(Fmt,Args), ok).
+-endif.
+
+-define(WARN(Cond, Message),
+ if (Cond) ->
+ io:format("Warning: ~s\n", [(Message)]);
+ true ->
+ ok
+ end).
+
+
+format(Pdu) ->
+ if record(Pdu, wsp_connect) ->
+ fmt(Pdu, record_info(fields, wsp_connect));
+ record(Pdu, wsp_connect_reply) ->
+ fmt(Pdu, record_info(fields, wsp_connect_reply));
+ record(Pdu, wsp_redirect) ->
+ fmt(Pdu, record_info(fields, wsp_redirect));
+ record(Pdu, wsp_disconnect) ->
+ fmt(Pdu, record_info(fields, wsp_disconnect));
+ record(Pdu, wsp_get) ->
+ fmt(Pdu, record_info(fields, wsp_get));
+ record(Pdu, wsp_post) ->
+ fmt(Pdu, record_info(fields, wsp_post));
+ record(Pdu,wsp_reply) ->
+ fmt(Pdu, record_info(fields, wsp_reply));
+ record(Pdu,wsp_data_fragment_pdu) ->
+ fmt(Pdu, record_info(fields, wsp_data_fragment_pdu));
+ record(Pdu,wsp_push) ->
+ fmt(Pdu, record_info(fields, wsp_push));
+ record(Pdu, wsp_suspend) ->
+ fmt(Pdu, record_info(fields, wsp_suspend));
+ record(Pdu, wsp_resume) ->
+ fmt(Pdu, record_info(fields, wsp_resume));
+ record(Pdu, wsp_unknown_pdu) ->
+ fmt(Pdu, record_info(fields, wsp_unknown_pdu))
+ end.
+
+fmt(Pdu, Fs) ->
+ [Name | Vs] = tuple_to_list(Pdu),
+ lists:flatten(["\n",atom_to_list(Name)," {\n" , fmt1(Fs, Vs), "\n}"]).
+
+fmt1([F|Fs],[V|Vs]) ->
+ [io_lib:format(" ~s: ~s;\n", [F,fmt_value(V)]) | fmt1(Fs, Vs)];
+fmt1([], []) ->
+ "".
+
+fmt_value(V) when binary(V) -> "#Bin";
+fmt_value(V) -> lists:flatten(io_lib:format("~p",[V])).
+
+
+%%
+%% Wsp pdu encoder
+%%
+encode(Pdu) ->
+ encode(Pdu, ?WSP_DEFAULT_VERSION).
+
+encode(Pdu, Version) ->
+ ?dbg("encode pdu using encoding version ~p\n", [Version]),
+ Enc = encode1(Pdu, Version),
+ ?dbg("pdu: ~p\nreversed pdu: ~p\n",
+ [Pdu, decode(Enc, Version)]),
+ Enc.
+
+
+encode1(Pdu, Version) ->
+ case Pdu of
+ #wsp_connect_reply {server_session_id=ServerSessionId,
+ capabilities=Capabilities,
+ headers=Headers} ->
+ EncServerSessionId = e_uintvar(ServerSessionId),
+ EncCapabilities = encode_capabilities(Capabilities),
+ EncCapabilitiesLength = e_uintvar(size(EncCapabilities)),
+ EncHeaders = encode_headers(Headers,Version),
+ EncHeadersLength = e_uintvar(size(EncHeaders)),
+ <<?WSP_ConnectReply,
+ EncServerSessionId/binary,
+ EncCapabilitiesLength/binary, EncHeadersLength/binary,
+ EncCapabilities/binary, EncHeaders/binary>>;
+
+ #wsp_reply{ status=Status,
+ content_type=ContentType,
+ headers=Headers,
+ data=Data} ->
+ EncStatus = encode_status_code(Status),
+ EncContentType = encode_content_type(ContentType,Version),
+ EncHeaders = encode_headers(Headers,Version),
+ EncHeadersLength = e_uintvar(size(EncContentType)+
+ size(EncHeaders)),
+ <<?WSP_Reply,
+ EncStatus:8,
+ EncHeadersLength/binary,
+ EncContentType/binary,
+ EncHeaders/binary,
+ Data/binary>>;
+
+ #wsp_post{type=Type, uri=URI, content_type=ContentType,
+ headers=Headers, data=Data} ->
+ %% WSP_Post, WSP_Put
+ PDUType = encode_pdu_type(Type),
+ UriLength = e_uintvar(length(URI)),
+ EncContentType = encode_content_type(ContentType,Version),
+ EncHeaders = encode_headers(Headers,Version),
+ EncHeadersLength = e_uintvar(size(EncContentType)+
+ size(EncHeaders)),
+ %% FIXME
+ <<PDUType:8,
+ UriLength/binary,
+ EncHeadersLength/binary,
+ (list_to_binary(URI))/binary,
+ EncContentType/binary,
+ EncHeaders/binary,
+ Data/binary>>;
+
+ #wsp_push{type=Type, content_type=ContentType,
+ headers=Headers, data=Data} ->
+ %% WSP_Push, WSP_ConfirmedPush
+ PDUType = encode_pdu_type(Type),
+ EncContentType = encode_content_type(ContentType,Version),
+ EncHeaders = encode_headers(Headers,Version),
+ ?dbg("Version ~p Headers ~p", [Version, Headers]),
+ ?dbg("EncHeaders ~p", [EncHeaders]),
+ EncHeadersLength = e_uintvar(size(EncContentType)+
+ size(EncHeaders)),
+ ?dbg("EncCT = ~w ~w", [ContentType, EncContentType]),
+ ?dbg("EncHL = ~w", [EncHeadersLength]),
+ <<PDUType:8,
+ EncHeadersLength/binary,
+ EncContentType/binary,
+ EncHeaders/binary,
+ Data/binary>>;
+
+ #wsp_get{type=Type, uri=URI, headers=Headers} ->
+ %% WSP_Get, WSP_Options, WSP_Head, WSP_Delete, WSP_Trace
+ PDUType = encode_pdu_type(Type),
+ UriLength = length(URI),
+ EncHeaders = encode_headers(Headers,Version),
+ <<PDUType:8,
+ (e_uintvar(UriLength))/binary,
+ (list_to_binary(URI))/binary,
+ EncHeaders/binary>>;
+
+ #wsp_redirect { flags = Flags, addresses = Addrs } ->
+ Flg = lists:foldl(fun(permanent,F) ->
+ ?WSP_PERMANENT_REDIRECT bor F;
+ (resue, F) ->
+ ?WSP_REUSE_SECURITY bor F
+ end, 0, Flags),
+ EncAddr = encode_addresses(Addrs),
+ <<?WSP_Redirect, Flg:8, EncAddr/binary >>;
+
+
+ #wsp_data_fragment_pdu { headers=Headers, data=Data } ->
+ EncHeaders = encode_headers(Headers,Version),
+ << ?WSP_DataFragmentPDU, EncHeaders/binary, Data/binary >>
+ end.
+
+decode(Data) ->
+ decode(Data, ?WSP_COMPLIENT_VERSION).
+
+decode(Data0, Version) ->
+ case Data0 of
+ <<?WSP_Connect:8,PduVersion:8,D0/binary>> ->
+ %% 8.2.2.1
+ {CapabilitiesLen,D1} = d_uintvar(D0),
+ {HeadersLen,D2} = d_uintvar(D1),
+ {Capabilities,D3} = split_binary(D2, CapabilitiesLen),
+ Caps = decode_capabilities(Capabilities,#wsp_capabilities{}),
+ {Headers,D4} = split_binary(D3, HeadersLen),
+ DecHeaders = decode_headers(Headers, Version),
+ ?WARN(D4 =/= <<>>, "Connect pdu contains trailing data"),
+ %% FIXME: warn when D4 is not <<>>
+ #wsp_connect{ version = PduVersion,
+ capabilities=Caps,
+ headers = DecHeaders };
+
+ <<?WSP_ConnectReply:8,D0/binary>> ->
+ %% 8.2.2.2
+ {ServerSessionId,D1} = d_uintvar(D0),
+ {CapabilitiesLen,D2} = d_uintvar(D1),
+ {HeadersLen,D3} = d_uintvar(D2),
+ {Capabilities,D4} = split_binary(D3, CapabilitiesLen),
+ Caps = decode_capabilities(Capabilities,#wsp_capabilities{}),
+ {Headers,D5} = split_binary(D4, HeadersLen),
+ DecHeaders = decode_headers(Headers, Version),
+ ?WARN(D5 =/= <<>>, "ConnectReply pdu contains trailing data"),
+ #wsp_connect_reply{server_session_id=ServerSessionId,
+ capabilities=Caps,
+ headers=DecHeaders};
+
+ <<?WSP_Redirect:8,Flg:8,D0/binary>> ->
+ Flags =
+ if Flg band ?WSP_PERMANENT_REDIRECT =/= 0 -> [permanent];
+ true -> []
+ end ++
+ if Flg band ?WSP_REUSE_SECURITY =/= 0 -> [security];
+ true -> []
+ end,
+ Addrs = decode_addresses(D0),
+ %% 8.2.2.3 Redirect
+ #wsp_redirect{flags=Flags,addresses=Addrs};
+
+
+ <<?WSP_Disconnect:8,D0/binary>> ->
+ %% 8.2.2.4 Disconnect
+ {ServerSessionId,_D1} = d_uintvar(D0),
+ #wsp_disconnect{server_session_id=ServerSessionId};
+
+ <<?WSP_Get:8,D0/binary>> ->
+ {URILength, D1} = d_uintvar(D0),
+ <<UriData:URILength/binary,D2/binary>> = D1,
+ Hs = decode_headers(D2, Version),
+ #wsp_get{type='GET',uri=binary_to_list(UriData),headers=Hs };
+
+ <<?WSP_Options:8,D0/binary>> ->
+ {URILength, D1} = d_uintvar(D0),
+ <<UriData:URILength/binary,D2/binary>> = D1,
+ Hs = decode_headers(D2, Version),
+ #wsp_get{type='OPTIONS',uri=binary_to_list(UriData),headers=Hs };
+
+ <<?WSP_Head:8,D0/binary>> ->
+ {URILength, D1} = d_uintvar(D0),
+ <<UriData:URILength/binary,D2/binary>> = D1,
+ Hs = decode_headers(D2, Version),
+ #wsp_get{type='HEAD',uri=binary_to_list(UriData),headers=Hs };
+
+ <<?WSP_Delete:8,D0/binary>> ->
+ {URILength, D1} = d_uintvar(D0),
+ <<UriData:URILength/binary,D2/binary>> = D1,
+ Hs = decode_headers(D2, Version),
+ #wsp_get{type='DELETE',uri=binary_to_list(UriData),headers=Hs };
+
+ <<?WSP_Trace:8,D0/binary>> ->
+ {URILength, D1} = d_uintvar(D0),
+ <<UriData:URILength/binary,D2/binary>> = D1,
+ Hs = decode_headers(D2, Version),
+ #wsp_get{type='TRACE',uri=binary_to_list(UriData),headers=Hs };
+
+ %% 8.2.3.2 Post
+ <<?WSP_Post:8,D0/binary>> ->
+ {URILen, D1} = d_uintvar(D0),
+ {HL0, D2} = d_uintvar(D1),
+ <<UriData:URILen/binary,D3/binary>> = D2,
+ {FieldData,D4} = scan_header_data(D3),
+ HL1 = (HL0-(size(D3)-size(D4))),
+ <<D5:HL1/binary,Data/binary>> = D4,
+ ContentType = decode_content_type(FieldData, Version),
+ Headers = decode_headers(D5, Version),
+ #wsp_post{ type='POST', uri=binary_to_list(UriData),
+ content_type=ContentType, headers=Headers, data=Data};
+
+ <<?WSP_Put:8,D0/binary>> ->
+ {URILen, D1} = d_uintvar(D0),
+ {HL0, D2} = d_uintvar(D1),
+ <<UriData:URILen/binary,D3/binary>> = D2,
+ {FieldData,D4} = scan_header_data(D3),
+ HL1 = (HL0-(size(D3)-size(D4))),
+ <<D5:HL1/binary,Data/binary>> = D4,
+ ContentType = decode_content_type(FieldData, Version),
+ Headers = decode_headers(D5, Version),
+ #wsp_post{ type='PUT', uri=binary_to_list(UriData),
+ content_type=ContentType, headers=Headers, data=Data};
+
+ <<?WSP_Reply:8,StatusCode:8,D0/binary>> ->
+ %% 8.2.3.3 Reply
+ Status = decode_status_code(StatusCode),
+ {HL0, D1} = d_uintvar(D0),
+ {FieldData, D2} = scan_header_data(D1),
+ ContentType = decode_content_type(FieldData, Version),
+ %% Headers are headersLength - binary size of content type
+ HL1 = (HL0-(size(D1)-size(D2))),
+ <<D3:HL1/binary,Data/binary>> = D2,
+ Hs = decode_headers(D3, Version),
+ #wsp_reply{status=Status, content_type=ContentType,
+ headers=Hs, data=Data};
+
+ <<?WSP_DataFragmentPDU:8,D0/binary>> ->
+ %% 8.2.3.4 Data Fragment PDU
+ {HL0, D1} = d_uintvar(D0),
+ <<D2:HL0/binary,Data/binary>> = D1,
+ Hs = decode_headers(D2, Version),
+ #wsp_data_fragment_pdu{headers=Hs, data=Data};
+
+ %% 8.2.4.1 Push or ConfirmedPush
+ <<?WSP_Push:8,D0/binary>> ->
+ {HeadersLength, T200} = d_uintvar(D0),
+ {FieldData, T300} = scan_header_data(T200),
+ ContentType = decode_content_type(FieldData, Version),
+ RealHeadersLength = (HeadersLength-(size(T200)-size(T300))),
+ <<T400:RealHeadersLength/binary,Data/binary>> = T300,
+ Headers = decode_headers(T400, Version),
+ #wsp_push{type=push,content_type=ContentType,
+ headers=Headers,data=Data};
+
+ <<?WSP_ConfirmedPush:8,D0/binary>> ->
+ {HeadersLength, T200} = d_uintvar(D0),
+ {FieldData, T300} = scan_header_data(T200),
+ ContentType = decode_content_type(FieldData, Version),
+ RealHeadersLength = (HeadersLength-(size(T200)-size(T300))),
+ <<T400:RealHeadersLength/binary,Data/binary>> = T300,
+ Headers = decode_headers(T400, Version),
+ #wsp_push{type=confirmed_push,
+ content_type=ContentType,
+ headers=Headers,data=Data};
+
+ <<PDUType:8,T100/binary>> ->
+ #wsp_unknown_pdu { type = PDUType, data = T100 }
+ end.
+
+
+encode_pdu_type(connect) -> ?WSP_Connect;
+encode_pdu_type(connect_reply) -> ?WSP_ConnectReply;
+encode_pdu_type(redirect) -> ?WSP_Redirect;
+encode_pdu_type(reply) -> ?WSP_Reply;
+encode_pdu_type(disconnect) -> ?WSP_Disconnect;
+encode_pdu_type(push) -> ?WSP_Push;
+encode_pdu_type(confirmed_push) -> ?WSP_ConfirmedPush;
+encode_pdu_type(suspend) -> ?WSP_Suspend;
+encode_pdu_type(resume) -> ?WSP_Resume;
+encode_pdu_type(data_fragment_pdu) -> ?WSP_DataFragmentPDU;
+encode_pdu_type('GET') -> ?WSP_Get;
+encode_pdu_type('OPTIONS') -> ?WSP_Options;
+encode_pdu_type('HEAD') -> ?WSP_Head;
+encode_pdu_type('DELETE') -> ?WSP_Delete;
+encode_pdu_type('TRACE') -> ?WSP_Trace;
+encode_pdu_type('POST') -> ?WSP_Post;
+encode_pdu_type('PUT') -> ?WSP_Put;
+encode_pdu_type(Type) when integer(Type) -> Type.
+
+
+decode_pdu_type(?WSP_Connect) -> connect;
+decode_pdu_type(?WSP_ConnectReply) -> connect_reply;
+decode_pdu_type(?WSP_Redirect) -> redirect;
+decode_pdu_type(?WSP_Reply) -> reply;
+decode_pdu_type(?WSP_Disconnect) -> disconnect;
+decode_pdu_type(?WSP_Push) -> push;
+decode_pdu_type(?WSP_ConfirmedPush) -> confirmed_push;
+decode_pdu_type(?WSP_Suspend) -> suspend;
+decode_pdu_type(?WSP_Resume) -> resume;
+decode_pdu_type(?WSP_DataFragmentPDU) -> data_fragment_pdu;
+decode_pdu_type(?WSP_Get) -> 'GET';
+decode_pdu_type(?WSP_Options) -> 'OPTIONS';
+decode_pdu_type(?WSP_Head) -> 'HEAD';
+decode_pdu_type(?WSP_Delete) -> 'DELETE';
+decode_pdu_type(?WSP_Trace) -> 'TRACE';
+decode_pdu_type(?WSP_Post) -> 'POST';
+decode_pdu_type(?WSP_Put) -> 'PUT';
+decode_pdu_type(Type) -> Type. %% allow unknown pdu types.
+
+
+%% Convert various data types to list
+
+to_list(I) when integer(I) ->
+ integer_to_list(I);
+to_list(A) when atom(A) ->
+ atom_to_list(A);
+to_list(Version={X,Y}) when integer(X), integer(Y) ->
+ format_version(Version);
+to_list(DateTime={{_,_,_},{_,_,_}}) ->
+ fmt_date(DateTime);
+to_list(L) when list(L) ->
+ L.
+
+
+
+encode_capabilities(Capa) ->
+ encode_capabilities(Capa,#wsp_capabilities{}).
+
+encode_capabilities(Cap,Def) ->
+ Known =
+ [encode_capability(?WSP_CAP_ALIASES,
+ Cap#wsp_capabilities.aliases,
+ Def#wsp_capabilities.aliases),
+ encode_capability(?WSP_CAP_CLIENT_SDU_SIZE,
+ Cap#wsp_capabilities.client_sdu_size,
+ Def#wsp_capabilities.client_sdu_size),
+ encode_capability(?WSP_CAP_SERVER_SDU_SIZE,
+ Cap#wsp_capabilities.server_sdu_size,
+ Def#wsp_capabilities.server_sdu_size),
+ encode_capability(?WSP_CAP_PROTOCOL_OPTIONS,
+ Cap#wsp_capabilities.protocol_options,
+ Def#wsp_capabilities.protocol_options),
+ encode_capability(?WSP_CAP_METHOD_MOR,
+ Cap#wsp_capabilities.method_mor,
+ Def#wsp_capabilities.method_mor),
+ encode_capability(?WSP_CAP_PUSH_MOR,
+ Cap#wsp_capabilities.push_mor,
+ Def#wsp_capabilities.push_mor),
+ encode_capability(?WSP_CAP_EXTENDED_METHODS,
+ Cap#wsp_capabilities.extended_methods,
+ Def#wsp_capabilities.extended_methods),
+ encode_capability(?WSP_CAP_HEADER_CODE_PAGES,
+ Cap#wsp_capabilities.header_code_pages,
+ Def#wsp_capabilities.header_code_pages),
+ encode_capability(?WSP_CAP_CLIENT_MESSAGE_SIZE,
+ Cap#wsp_capabilities.client_message_size,
+ Def#wsp_capabilities.client_message_size),
+ encode_capability(?WSP_CAP_SERVER_MESSAGE_SIZE,
+ Cap#wsp_capabilities.server_message_size,
+ Def#wsp_capabilities.server_message_size)],
+ Unknown =
+ lists:map(fun({Id, Data}) when integer(Id) ->
+ <<1:1, Id:7, Data/binary>>;
+ ({Id,Data}) ->
+ <<(encode_text_string(Id))/binary, Data/binary>>
+ end, Cap#wsp_capabilities.unknown),
+ list_to_binary(
+ lists:map(fun(<<>>) -> [];
+ (Bin) ->
+ [e_uintvar(size(Bin)), Bin]
+ end, Known ++ Unknown)).
+
+
+
+
+encode_capability(_Capa, Default, Default) ->
+ <<>>;
+encode_capability(Capa, Value, _) ->
+ case Capa of
+ ?WSP_CAP_ALIASES ->
+ <<1:1, ?WSP_CAP_ALIASES:7, (encode_addresses(Value))/binary>>;
+
+ ?WSP_CAP_CLIENT_SDU_SIZE ->
+ <<1:1, ?WSP_CAP_CLIENT_SDU_SIZE:7, (e_uintvar(Value))/binary>>;
+
+ ?WSP_CAP_SERVER_SDU_SIZE ->
+ <<1:1, ?WSP_CAP_SERVER_SDU_SIZE:7, (e_uintvar(Value))/binary>>;
+
+ ?WSP_CAP_PROTOCOL_OPTIONS ->
+ Opts = case lists:member(confirmed_push, Value) of
+ true -> 16#80;
+ false -> 0
+ end bor
+ case lists:member(push, Value) of
+ true -> 16#40;
+ false -> 0
+ end bor
+ case lists:member(resume, Value) of
+ true -> 16#20;
+ false -> 0
+ end bor
+ case lists:member(acknowledgement_headers, Value) of
+ true -> 16#10;
+ false -> 0
+ end,
+ %% FIXME: symbolic encode/decode of options
+ <<1:1, ?WSP_CAP_PROTOCOL_OPTIONS:7, Opts>>;
+
+ ?WSP_CAP_METHOD_MOR ->
+ <<1:1, ?WSP_CAP_METHOD_MOR:7, (e_uintvar(Value))/binary>>;
+
+ ?WSP_CAP_PUSH_MOR ->
+ <<1:1, ?WSP_CAP_PUSH_MOR:7, (e_uintvar(Value))/binary>>;
+
+ ?WSP_CAP_EXTENDED_METHODS ->
+ <<1:1, ?WSP_CAP_EXTENDED_METHODS:7,
+ (encode_extended_methods(Value))/binary>>;
+
+ ?WSP_CAP_HEADER_CODE_PAGES ->
+ Data = list_to_binary(
+ lists:map(fun(Page) when integer(Page) -> Page;
+ ({Page,Name}) ->
+ [Page, encode_text_string(Name)]
+ end, Value)),
+ <<1:1, ?WSP_CAP_HEADER_CODE_PAGES:7, Data/binary>>;
+
+ ?WSP_CAP_CLIENT_MESSAGE_SIZE ->
+ <<1:1, ?WSP_CAP_CLIENT_MESSAGE_SIZE:7,
+ (e_uintvar(Value))/binary>>;
+
+ ?WSP_CAP_SERVER_MESSAGE_SIZE ->
+ <<1:1, ?WSP_CAP_SERVER_MESSAGE_SIZE:7,
+ (e_uintvar(Value))/binary>>;
+ _ when integer(Capa) ->
+ <<1:1, Capa:7, Value/binary>>;
+ _ when list(Capa) ->
+ <<(encode_text_string(Capa))/binary, Value/binary>>
+ end.
+
+
+decode_capabilities(<<>>, WspCaps) ->
+ WspCaps;
+decode_capabilities(D0,WspCaps) ->
+ {Len, D1} = d_uintvar(D0),
+ <<Capa:Len/binary, D2/binary>> = D1,
+ WspCaps1 =
+ case Capa of
+ <<1:1, Id:7, Data/binary>> ->
+ decode_capa(Id, Data, WspCaps);
+ _ ->
+ {Id,Data} = d_text_string(Capa),
+ decode_capa(Id, Data, WspCaps)
+ end,
+ decode_capabilities(D2, WspCaps1).
+
+
+
+decode_capa(Id,Data, WspCaps) ->
+ case Id of
+ ?WSP_CAP_SERVER_SDU_SIZE ->
+ {Val,_} = d_uintvar(Data),
+ WspCaps#wsp_capabilities{server_sdu_size=Val};
+
+ ?WSP_CAP_CLIENT_SDU_SIZE ->
+ {Val,_} = d_uintvar(Data),
+ WspCaps#wsp_capabilities{client_sdu_size=Val};
+
+ ?WSP_CAP_PROTOCOL_OPTIONS ->
+ <<POP,_/binary>> = Data,
+ Opts =
+ if POP band 16#80 == 16#80 -> [confirmed_push];
+ true -> []
+ end ++
+ if POP band 16#40 == 16#40 -> [push];
+ true -> []
+ end ++
+ if POP band 16#20 == 16#20 -> [resume];
+ true -> []
+ end ++
+ if POP band 16#10 == 16#10 -> [acknowledgement_headers];
+ true -> []
+ end,
+ WspCaps#wsp_capabilities{protocol_options=Opts};
+
+ ?WSP_CAP_METHOD_MOR ->
+ {Val,_} = d_uintvar(Data),
+ WspCaps#wsp_capabilities{method_mor=Val};
+
+ ?WSP_CAP_PUSH_MOR ->
+ {Val,_} = d_uintvar(Data),
+ WspCaps#wsp_capabilities{push_mor=Val};
+
+ ?WSP_CAP_EXTENDED_METHODS ->
+ Extended = decode_extended_methods(Data),
+ WspCaps#wsp_capabilities { extended_methods = Extended };
+
+ ?WSP_CAP_HEADER_CODE_PAGES ->
+ %% Client send [Code(uint8) Name(text-string)]*
+ %% Server send [Code(uint8)]*
+ io:format("FIXME: Header Code Pages = ~p\n",[Data]),
+ WspCaps;
+
+ ?WSP_CAP_ALIASES ->
+ Aliases = decode_addresses(Data),
+ WspCaps#wsp_capabilities { aliases = Aliases };
+
+ ?WSP_CAP_CLIENT_MESSAGE_SIZE ->
+ {Val,_} = d_uintvar(Data),
+ WspCaps#wsp_capabilities{client_message_size=Val};
+
+ ?WSP_CAP_SERVER_MESSAGE_SIZE ->
+ {Val,_} = d_uintvar(Data),
+ WspCaps#wsp_capabilities{server_message_size=Val};
+ _ ->
+ Unknown = [{Id, Data} | WspCaps#wsp_capabilities.unknown],
+ io:format("WARNING: ignoring unknown capability ~p\n",
+ [Unknown]),
+ WspCaps#wsp_capabilities{unknown = Unknown}
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Headers = [ Header ]
+%% Header = {FieldName, FieldValue}
+%% FieldName = atom()
+%% FieldValue = {Value, Params}
+%% | Value
+%%
+%% Params = [{Param,Value} | Param]
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-define(WH(Name,Value,Params),
+ #wsp_header { name = (Name), value = (Value), params = Params}).
+
+encode_headers(Headers) ->
+ encode_headers(Headers, ?WSP_DEFAULT_VERSION).
+
+encode_headers(Headers, Version) ->
+ encode_headers(Headers, Version, []).
+
+encode_headers([H|T], Version, Acc) ->
+ encode_headers(T, Version, [encode_header(H, Version)|Acc]);
+encode_headers([], _, Acc) ->
+ list_to_binary(lists:reverse(Acc)).
+
+
+decode_headers(Bin) ->
+ decode_headers(Bin, ?WSP_DEFAULT_VERSION).
+
+decode_headers(<<>>, _Version) ->
+ [];
+decode_headers(Data, Version) ->
+ decode_headers(Data, [], Version, ?WSP_DEFAULT_CODEPAGE).
+
+
+decode_headers(<<1:1,Code:7,Data/binary>>,Acc,Version,CP) ->
+ FieldName = lookup_field_name(Code),
+ {FieldData,Data1} = scan_header_data(Data),
+ H = decode_header(FieldName, FieldData,Version,CP),
+ ?dbg("header: ~p, field data=~p, header=~p\n",
+ [FieldName, FieldData, H]),
+ if H#wsp_header.name == 'Encoding-Version' ->
+ Version1 = H#wsp_header.value,
+ ?dbg("Version switch from ~w to ~w\n", [Version, Version1]),
+ decode_headers(Data1,[H|Acc],Version1, CP);
+ true ->
+ decode_headers(Data1,[H|Acc],Version, CP)
+ end;
+decode_headers(Data = <<Code,_/binary>>,Acc,Version,CP)
+ when Code >= 32, Code < 127->
+ {TmpField,Data1} = d_text_string(Data),
+ FieldName = normalise_field_name(TmpField),
+ {FieldData,Data2} = scan_header_data(Data1),
+ H = decode_header(FieldName,FieldData,Version,CP),
+ ?dbg("header: ~p, field data=~p, header=~p\n",
+ [FieldName, FieldData, H]),
+ if H#wsp_header.name == 'Encoding-Version' ->
+ Version1 = H#wsp_header.value,
+ ?dbg("Version switch from ~w to ~w\n", [Version, Version1]),
+ decode_headers(Data2,[H|Acc],Version1, CP);
+ true ->
+ decode_headers(Data2,[H|Acc],Version, CP)
+ end;
+decode_headers(<<CP1,Data/binary>>,Acc,Version,_CP) when CP1 >= 1, CP1 =< 31 ->
+ ?dbg("decode_headers: codpage changed form ~w -> ~w\n",[_CP,CP1]),
+ decode_headers(Data,Acc,Version,CP1);
+decode_headers(<<16#7f,CP1,Data/binary>>,Acc,Version,_CP) ->
+ ?dbg("decode_headers: codpage changed form ~w -> ~w\n",[_CP,CP1]),
+ decode_headers(Data,Acc,Version,CP1);
+
+decode_headers(<<>>, Acc, _Version, _CP) ->
+ lists:reverse(Acc).
+
+%%
+%% Retrive the header data
+%% (this makes it possible to skip unknown encoding)
+%%
+scan_header_data(Data = <<N,Data0/binary>>) ->
+ if N >= 0, N =< 30 ->
+ <<Value:N/binary, Data1/binary>> = Data0,
+ {{short,Value}, Data1};
+ N == 31 ->
+ {N1, Data1} = d_uintvar(Data0),
+ <<Value:N1/binary, Data2/binary>> = Data1,
+ {{long,Value}, Data2};
+ N >= 32, N =< 127 ->
+ d_text_string(Data);
+ true ->
+ { N band 16#7f, Data0}
+ end.
+
+%%
+%% Decode header: return #wsp_header
+%%
+decode_header(Field, Value) ->
+ decode_header(Field, Value,
+ ?WSP_DEFAULT_VERSION,
+ ?WSP_DEFAULT_CODEPAGE).
+
+decode_header(Field, Value, Version, 1) ->
+ case Field of
+ 'Accept' ->
+ decode_accept(Value, Version);
+
+ 'Accept-Charset' when Version >= ?WSP_13 ->
+ decode_accept_charset(Value, Version);
+ 'Accept-Charset' ->
+ decode_accept_charset(Value, Version);
+
+ 'Accept-Encoding' when Version >= ?WSP_13 ->
+ decode_accept_encoding(Value, Version);
+ 'Accept-Encoding' ->
+ decode_accept_encoding(Value, Version);
+
+ 'Accept-Language' ->
+ decode_accept_language(Value, Version);
+ 'Accept-Ranges' ->
+ decode_accept_ranges(Value, Version);
+ 'Age' ->
+ decode_age(Value,Version);
+ 'Allow' ->
+ decode_allow(Value,Version);
+ 'Authorization' ->
+ decode_authorization(Value,Version);
+
+ 'Cache-Control' when Version >= ?WSP_14 ->
+ decode_cache_control(Value,Version);
+ 'Cache-Control' when Version >= ?WSP_13 ->
+ decode_cache_control(Value,Version);
+ 'Cache-Control' ->
+ decode_cache_control(Value,Version);
+
+ 'Connection' ->
+ decode_connection(Value,Version);
+ 'Content-Base' ->
+ decode_content_base(Value,Version);
+ 'Content-Encoding' ->
+ decode_content_encoding(Value,Version);
+ 'Content-Language' ->
+ decode_content_language(Value,Version);
+ 'Content-Length' ->
+ decode_content_length(Value,Version);
+ 'Content-Location' ->
+ decode_content_location(Value,Version);
+ 'Content-Md5' ->
+ decode_content_md5(Value,Version);
+
+ 'Content-Range' when Version >= ?WSP_13 ->
+ decode_content_range(Value,Version);
+ 'Content-Range' ->
+ decode_content_range(Value,Version);
+
+ 'Content-Type' ->
+ decode_content_type(Value,Version);
+ 'Date' ->
+ decode_date(Value, Version);
+ 'Etag' ->
+ decode_etag(Value,Version);
+ 'Expires' ->
+ decode_expires(Value,Version);
+ 'From' ->
+ decode_from(Value,Version);
+ 'Host' ->
+ decode_host(Value,Version);
+ 'If-Modified-Since' ->
+ decode_if_modified_since(Value,Version);
+ 'If-Match' ->
+ decode_if_match(Value,Version);
+ 'If-None-Match' ->
+ decode_if_none_match(Value,Version);
+ 'If-Range' ->
+ decode_if_range(Value,Version);
+ 'If-Unmodified-Since' ->
+ decode_if_unmodified_since(Value,Version);
+ 'Location' ->
+ decode_location(Value,Version);
+ 'Last-Modified' ->
+ decode_last_modified(Value,Version);
+ 'Max-Forwards' ->
+ decode_max_forwards(Value,Version);
+ 'Pragma' ->
+ decode_pragma(Value,Version);
+ 'Proxy-Authenticate' ->
+ decode_proxy_authenticate(Value,Version);
+ 'Proxy-Authorization' ->
+ decode_proxy_authorization(Value,Version);
+ 'Public' ->
+ decode_public(Value,Version);
+ 'Range' ->
+ decode_range(Value,Version);
+ 'Referer' ->
+ decode_referer(Value,Version);
+ 'Retry-After' ->
+ decode_retry_after(Value,Version);
+ 'Server' ->
+ decode_server(Value,Version);
+ 'Transfer-Encoding' ->
+ decode_transfer_encoding(Value,Version);
+ 'Upgrade' ->
+ decode_upgrade(Value,Version);
+ 'User-Agent' ->
+ decode_user_agent(Value,Version);
+ 'Vary' ->
+ decode_vary(Value,Version);
+ 'Via' ->
+ decode_via(Value,Version);
+ 'Warning' ->
+ decode_warning(Value,Version);
+ 'Www-Authenticate' ->
+ decode_www_authenticate(Value,Version);
+
+ 'Content-Disposition' when Version >= ?WSP_14 ->
+ decode_content_disposition(Value,Version);
+ 'Content-Disposition' ->
+ decode_content_disposition(Value,Version);
+
+ 'X-Wap-Application-Id' when Version >= ?WSP_12 ->
+ decode_x_wap_application_id(Value,Version);
+
+ 'X-Wap-Content-Uri' when Version >= ?WSP_12 ->
+ decode_x_wap_content_uri(Value,Version);
+
+ 'X-Wap-Initiator-Uri' when Version >= ?WSP_12 ->
+ decode_x_wap_initiator_uri(Value,Version);
+
+ 'Accept-Application' when Version >= ?WSP_12 ->
+ decode_accept_application(Value,Version);
+
+ 'Bearer-Indication' when Version >= ?WSP_12 ->
+ decode_bearer_indication(Value,Version);
+
+ 'Push-Flag' when Version >= ?WSP_12 ->
+ decode_push_flag(Value,Version);
+
+ 'Profile' when Version >= ?WSP_12 ->
+ decode_profile(Value,Version);
+
+ 'Profile-Diff' when Version >= ?WSP_12 ->
+ decode_profile_diff(Value,Version);
+
+ 'Profile-Warning' when Version >= ?WSP_12 ->
+ decode_profile_warning(Value,Version);
+
+ 'Expect' when Version >= ?WSP_15 ->
+ decode_expect(Value,Version);
+ 'Expect' when Version >= ?WSP_13 ->
+ decode_expect(Value,Version);
+
+ 'Te' when Version >= ?WSP_13 ->
+ decode_te(Value,Version);
+ 'Trailer' when Version >= ?WSP_13 ->
+ decode_trailer(Value,Version);
+
+ 'X-Wap-Tod' when Version >= ?WSP_13 ->
+ decode_x_wap_tod(Value,Version);
+ 'X-Wap.tod' when Version >= ?WSP_13 ->
+ decode_x_wap_tod(Value,Version);
+
+ 'Content-Id' when Version >= ?WSP_13 ->
+ decode_content_id(Value,Version);
+ 'Set-Cookie' when Version >= ?WSP_13 ->
+ decode_set_cookie(Value,Version);
+ 'Cookie' when Version >= ?WSP_13 ->
+ decode_cookie(Value,Version);
+
+ 'Encoding-Version' when Version >= ?WSP_13 ->
+ decode_encoding_version(Value,Version);
+ 'Profile-Warning' when Version >= ?WSP_14 ->
+ decode_profile_warning(Value,Version);
+
+ 'X-Wap-Security' when Version >= ?WSP_14 ->
+ decode_x_wap_security(Value,Version);
+ 'X-Wap-Loc-Invocation' when Version >= ?WSP_15 ->
+ decode_x_wap_loc_invocation(Value,Version); %% ???
+ 'X-Wap-Loc-Delivery' when Version >= ?WSP_15 ->
+ decode_x_wap_loc_delivery(Value,Version); %% ???
+ _ ->
+ ?dbg("Warning: none standard field ~p in version ~p codepage=1\n",
+ [Field, Version]),
+ ?WH(Field, Value, [])
+ end;
+decode_header(Field, Value, _Version, _CP) ->
+ ?dbg("Warning: none standard field ~p in version ~p codepage=~w\n",
+ [Field, _Version, _CP]),
+ ?WH(Field, Value, []).
+
+%%
+%% Encode field and value according to version
+%% FIXME: spilt multiple header values (i.e Via) into multiple
+%% headers
+%%
+encode_header(H, Version) ->
+ case H#wsp_header.name of
+ 'Accept' ->
+ [16#80, encode_accept(H, Version)];
+ 'Accept-Charset' when Version >= ?WSP_13 ->
+ [16#bb, encode_accept_charset(H, Version)];
+ 'Accept-Charset' ->
+ [16#81, encode_accept_charset(H, Version)];
+ 'Accept-Encoding' when Version >= ?WSP_13 ->
+ [16#bc, encode_accept_encoding(H, Version)];
+ 'Accept-Encoding' ->
+ [16#82, encode_accept_encoding(H, Version)];
+ 'Accept-Language' ->
+ [16#83, encode_accept_language(H, Version)];
+ 'Accept-Ranges' ->
+ [16#84, encode_accept_ranges(H, Version)];
+ 'Accept-Application' when Version >= ?WSP_12 ->
+ [16#b2, encode_accept_application(H,Version)];
+ 'Age' ->
+ [16#85, encode_age(H, Version)];
+ 'Allow' ->
+ [16#86, encode_allow(H, Version)];
+ 'Authorization' ->
+ [16#87, encode_authorization(H, Version)];
+ 'Cache-Control' when Version >= ?WSP_14 ->
+ [16#c7, encode_cache_control(H, Version)];
+ 'Cache-Control' when Version >= ?WSP_13 ->
+ [16#bd, encode_cache_control(H, Version)];
+ 'Cache-Control' ->
+ [16#88, encode_cache_control(H, Version)];
+ 'Connection' ->
+ [16#89, encode_connection(H, Version)];
+ 'Content-Base' ->
+ [16#8a, encode_content_base(H, Version)];
+ 'Content-Encoding' ->
+ [16#8b, encode_content_encoding(H, Version)];
+
+ 'Content-Language' ->
+ [16#8c, encode_content_language(H,Version)];
+ 'Content-Length' ->
+ [16#8d, encode_content_length(H,Version)];
+ 'Content-Location' ->
+ [16#8e, encode_content_location(H,Version)];
+ 'Content-Md5' ->
+ [16#8f, encode_content_md5(H,Version)];
+ 'Content-Range' when Version >= ?WSP_13 ->
+ [16#be, encode_content_range(H,Version)];
+ 'Content-Range' ->
+ [16#90, encode_content_range(H,Version)];
+ 'Content-Type' ->
+ [16#91, encode_content_type(H,Version)];
+ 'Date' ->
+ [16#92, encode_date(H,Version)];
+ 'Etag' ->
+ [16#93, encode_etag(H,Version)];
+ 'Expires' ->
+ [16#94, encode_expires(H,Version)];
+ 'From' ->
+ [16#95, encode_from(H,Version)];
+ 'Host' ->
+ [16#96, encode_host(H,Version)];
+ 'If-Modified-Since' ->
+ [16#97, encode_if_modified_since(H,Version)];
+ 'If-Match' ->
+ [16#98, encode_if_match(H,Version)];
+ 'If-None-Match' ->
+ [16#99, encode_if_none_match(H,Version)];
+ 'If-Range' ->
+ [16#9a, encode_if_range(H,Version)];
+ 'If-Unmodified-Since' ->
+ [16#9b, encode_if_unmodified_since(H,Version)];
+ 'Location' ->
+ [16#9c, encode_location(H,Version)];
+ 'Last-Modified' ->
+ [16#9d, encode_last_modified(H,Version)];
+ 'Max-Forwards' ->
+ [16#9e, encode_max_forwards(H,Version)];
+ 'Pragma' ->
+ [16#9f, encode_pragma(H,Version)];
+ 'Proxy-Authenticate' ->
+ [16#a0, encode_proxy_authenticate(H,Version)];
+ 'Proxy-Authorization' ->
+ [16#a1, encode_proxy_authorization(H,Version)];
+ 'Public' ->
+ [16#a2, encode_public(H,Version)];
+ 'Range' ->
+ [16#a3, encode_range(H,Version)];
+ 'Referer' ->
+ [16#a4, encode_referer(H,Version)];
+ 'Retry-After' ->
+ [16#a5, encode_retry_after(H,Version)];
+ 'Server' ->
+ [16#a6, encode_server(H,Version)];
+ 'Transfer-Encoding' ->
+ [16#a7, encode_transfer_encoding(H,Version)];
+ 'Upgrade' ->
+ [16#a8, encode_upgrade(H,Version)];
+ 'User-Agent' ->
+ [16#a9, encode_user_agent(H,Version)];
+ 'Vary' ->
+ [16#aa, encode_vary(H,Version)];
+ 'Via' ->
+ [16#ab, encode_via(H,Version)];
+ 'Warning' ->
+ [16#ac, encode_warning(H,Version)];
+ 'Www-Authenticate' ->
+ [16#ad, encode_www_authenticate(H,Version)];
+
+ 'Content-Disposition' when Version >= ?WSP_14 ->
+ [16#c5, encode_content_disposition(H,Version)];
+ 'Content-Disposition' ->
+ [16#ae, encode_content_disposition(H,Version)];
+
+
+ 'X-Wap-Application-Id' when Version >= ?WSP_12 ->
+ [16#af, encode_x_wap_application_id(H,Version)];
+ 'X-Wap-Content-Uri' when Version >= ?WSP_12 ->
+ [16#b0, encode_x_wap_content_uri(H,Version)];
+ 'X-Wap-Initiator-Uri' when Version >= ?WSP_12 ->
+ [16#b1, encode_x_wap_initiator_uri(H,Version)];
+
+ 'Bearer-Indication' when Version >= ?WSP_12 ->
+ [16#b3, encode_bearer_indication(H,Version)];
+ 'Push-Flag' when Version >= ?WSP_12 ->
+ [16#b4, encode_push_flag(H,Version)];
+
+ 'Profile' when Version >= ?WSP_12 ->
+ [16#b5, encode_profile(H,Version)];
+ 'Profile-Diff' when Version >= ?WSP_12 ->
+ [16#b6, encode_profile_diff(H,Version)];
+ 'Profile-Warning' when Version >= ?WSP_14 ->
+ [16#c4, encode_profile_warning(H,Version)];
+ 'Profile-Warning' when Version >= ?WSP_12 ->
+ [16#b7, encode_profile_warning(H,Version)];
+
+ 'Expect' when Version >= ?WSP_15 ->
+ [16#c8, encode_expect(H,Version)];
+ 'Expect' when Version >= ?WSP_13 ->
+ [16#b8, encode_expect(H,Version)];
+ 'Te' when Version >= ?WSP_13 ->
+ [16#b9, encode_te(H,Version)];
+ 'Trailer' when Version >= ?WSP_13 ->
+ [16#ba, encode_trailer(H,Version)];
+ 'X-Wap-Tod' when Version >= ?WSP_13 ->
+ [16#bf, encode_x_wap_tod(H,Version)];
+ 'Content-Id' when Version >= ?WSP_13 ->
+ [16#c0, encode_content_id(H,Version)];
+ 'Set-Cookie' when Version >= ?WSP_13 ->
+ [16#c1, encode_set_cookie(H,Version)];
+ 'Cookie' when Version >= ?WSP_13 ->
+ [16#c2, encode_cookie(H,Version)];
+ 'Encoding-Version' when Version >= ?WSP_13 ->
+ [16#c3, encode_encoding_version(H,Version)];
+ 'Encoding-Version' when Version < ?WSP_13 ->
+ [encode_text_string("Encoding-Version"),
+ encode_text_string(lists:flatten(format_version(H#wsp_header.value)))];
+
+ 'X-Wap-Security' when Version >= ?WSP_14 ->
+ [16#c6, encode_x_wap_security(H,Version)];
+ 'X-Wap-Loc-Invocation' when Version >= ?WSP_15 ->
+ [16#c9, encode_x_wap_loc_invocation(H,Version)];
+ 'X-Wap-Loc-Delivery' when Version >= ?WSP_15 ->
+ [16#ca, encode_x_wap_loc_delivery(H,Version)];
+ Field when atom(Field) ->
+ [encode_text_string(atom_to_list(Field)),
+ encode_text_string(H#wsp_header.value)];
+ Field when list(Field) ->
+ [encode_text_string(Field),
+ encode_text_string(H#wsp_header.value)]
+ end.
+
+%%
+%% Convert HTTP headers into WSP headers
+%%
+parse_headers([H | Hs]) ->
+ parse_header(H, Hs);
+parse_headers([]) ->
+ [].
+
+parse_header(H) ->
+ parse_header(H, []).
+
+parse_header({FieldName,FieldValue}, Hs) ->
+ case single_comma_field(FieldName) of
+ true ->
+ io:format("parse: ~s: ~s\n", [FieldName, FieldValue]),
+ H = parse_hdr(FieldName,FieldValue),
+ io:format("header: ~p\n", [H]),
+ [H | parse_headers(Hs)];
+ false ->
+ Values = string:tokens(FieldValue, ","),
+ parse_header(FieldName, Values, Hs)
+ end.
+
+parse_header(FieldName, [Value|Vs], Hs) ->
+ io:format("parse: ~s: ~s\n", [FieldName, Value]),
+ H = parse_hdr(FieldName, Value),
+ io:format("header: ~p\n", [H]),
+ [H | parse_header(FieldName, Vs, Hs)];
+parse_header(_FieldName, [], Hs) ->
+ parse_headers(Hs).
+
+
+single_comma_field(Field) ->
+ case Field of
+ 'Set-Cookie' -> true; %% FIXME (Is multiple!)
+ 'Date' -> true;
+ 'Expires' -> true;
+ 'If-Modified-Since' -> true;
+ 'If-Range' -> true;
+ 'If-Unmodified-Since' -> true;
+ 'Last-Modified' -> true;
+ 'Retry-After' -> true;
+ 'X-Wap-Tod' -> true;
+ _ -> false
+ end.
+
+
+parse_hdr(Field, Value0) ->
+ Value = trim(Value0),
+ case Field of
+ 'Accept' -> parse_accept(Value);
+ 'Accept-Charset' -> parse_accept_charset(Value);
+ 'Accept-Encoding' -> parse_accept_encoding(Value);
+ 'Accept-Language' -> parse_accept_language(Value);
+ 'Accept-Ranges' -> parse_accept_ranges(Value);
+ 'Age' -> parse_age(Value);
+ 'Allow' -> parse_allow(Value);
+ 'Authorization' -> parse_authorization(Value);
+ 'Cache-Control' -> parse_cache_control(Value);
+ 'Connection' -> parse_connection(Value);
+ 'Content-Base' -> parse_content_base(Value);
+ 'Content-Encoding' -> parse_content_encoding(Value);
+ 'Content-Language' -> parse_content_language(Value);
+ 'Content-Length' -> parse_content_length(Value);
+ 'Content-Location' -> parse_content_location(Value);
+ 'Content-Md5' -> parse_content_md5(Value);
+ 'Content-Range' -> parse_content_range(Value);
+ 'Content-Type' -> parse_content_type(Value);
+ 'Date' -> parse_date(Value);
+ 'Etag' -> parse_etag(Value);
+ 'Expires' -> parse_expires(Value);
+ 'From' -> parse_from(Value);
+ 'Host' -> parse_host(Value);
+ 'If-Modified-Since' -> parse_if_modified_since(Value);
+ 'If-Match' -> parse_if_match(Value);
+ 'If-None-Match' -> parse_if_none_match(Value);
+ 'If-Range' -> parse_if_range(Value);
+ 'If-Unmodified-Since' -> parse_if_unmodified_since(Value);
+ 'Location' -> parse_location(Value);
+ 'Last-Modified' -> parse_last_modified(Value);
+ 'Max-Forwards' -> parse_max_forwards(Value);
+ 'Pragma' -> parse_pragma(Value);
+ 'Proxy-Authenticate' -> parse_proxy_authenticate(Value);
+ 'Proxy-Authorization' -> parse_proxy_authorization(Value);
+ 'Public' -> parse_public(Value);
+ 'Range' -> parse_range(Value);
+ 'Referer' -> parse_referer(Value);
+ 'Retry-After' -> parse_retry_after(Value);
+ 'Server' -> parse_server(Value);
+ 'Transfer-Encoding' -> parse_transfer_encoding(Value);
+ 'Upgrade' -> parse_upgrade(Value);
+ 'User-Agent' -> parse_user_agent(Value);
+ 'Vary' -> parse_vary(Value);
+ 'Via' -> parse_via(Value);
+ 'Warning' -> parse_warning(Value);
+ 'Www-Authenticate' -> parse_www_authenticate(Value);
+ 'Content-Disposition' -> parse_content_disposition(Value);
+ 'X-Wap-Application-Id' -> parse_x_wap_application_id(Value);
+ 'X-Wap-Content-Uri' -> parse_x_wap_content_uri(Value);
+ 'X-Wap-Initiator-Uri' -> parse_x_wap_initiator_uri(Value);
+ 'Accept-Application' -> parse_accept_application(Value);
+ 'Bearer-Indication' -> parse_bearer_indication(Value);
+ 'Push-Flag' -> parse_push_flag(Value);
+ 'Profile' -> parse_profile(Value);
+ 'Profile-Diff' -> parse_profile_diff(Value);
+ 'Profile-Warning' -> parse_profile_warning(Value);
+ 'Expect' -> parse_expect(Value);
+ 'Te' -> parse_te(Value);
+ 'Trailer' -> parse_trailer(Value);
+ 'X-Wap-Tod' -> parse_x_wap_tod(Value);
+ 'Content-Id' -> parse_content_id(Value);
+ 'Set-Cookie' -> parse_set_cookie(Value);
+ 'Cookie' -> parse_cookie(Value);
+ 'Encoding-Version' -> parse_encoding_version(Value);
+ 'X-Wap-Security' -> parse_x_wap_security(Value);
+ 'X-Wap-Loc-Invocation' -> parse_x_wap_loc_invocation(Value);
+ 'X-Wap-Loc-Delivery' -> parse_x_wap_loc_delivery(Value);
+ _ ->
+ ?dbg("Warning: header field ~p not recognissed\n",[Field]),
+ #wsp_header { name = Field, value = Value}
+ end.
+
+%%
+%% Format headers, will combine multiple headers into one
+%% FIXME: if length is < MAX_HTTP_HEADER_LENGTH
+%%
+format_headers(Hs) ->
+ format_hdrs(lists:keysort(#wsp_header.name,Hs), []).
+
+format_hdrs([H | Hs], Acc) ->
+ V1 = format_value(H),
+ format_hdrs(Hs, H#wsp_header.name, V1, Acc);
+format_hdrs([], Acc) ->
+ lists:reverse(Acc).
+
+format_hdrs([H|Hs], FieldName, FieldValue, Acc)
+ when FieldName == H#wsp_header.name ->
+ V1 = format_value(H),
+ format_hdrs(Hs, FieldName, [FieldValue,",",V1], Acc);
+format_hdrs(Hs, FieldName, FieldValue, Acc) ->
+ format_hdrs(Hs, [{FieldName, lists:flatten(FieldValue)} | Acc]).
+
+
+%%
+%% Format header: #wsp_header => {FieldName, Value}
+%%
+
+format_header(H) ->
+ {H#wsp_header.name, format_value(H)}.
+
+format_value(H) ->
+ case H#wsp_header.name of
+ 'Accept' -> format_accept(H);
+ 'Accept-Charset' -> format_accept_charset(H);
+ 'Accept-Encoding' -> format_accept_encoding(H);
+ 'Accept-Language' -> format_accept_language(H);
+ 'Accept-Ranges' -> format_accept_ranges(H);
+ 'Age' -> format_age(H);
+ 'Allow' -> format_allow(H);
+ 'Authorization' -> format_authorization(H);
+ 'Cache-Control' -> format_cache_control(H);
+ 'Connection' -> format_connection(H);
+ 'Content-Base' -> format_content_base(H);
+ 'Content-Encoding' -> format_content_encoding(H);
+ 'Content-Language' -> format_content_language(H);
+ 'Content-Length' -> format_content_length(H);
+ 'Content-Location' -> format_content_location(H);
+ 'Content-Md5' -> format_content_md5(H);
+ 'Content-Range' -> format_content_range(H);
+ 'Content-Type' -> format_content_type(H);
+ 'Date' -> format_date(H);
+ 'Etag' -> format_etag(H);
+ 'Expires' -> format_expires(H);
+ 'From' -> format_from(H);
+ 'Host' -> format_host(H);
+ 'If-Modified-Since' -> format_if_modified_since(H);
+ 'If-Match' -> format_if_match(H);
+ 'If-None-Match' -> format_if_none_match(H);
+ 'If-Range' -> format_if_range(H);
+ 'If-Unmodified-Since' -> format_if_unmodified_since(H);
+ 'Location' -> format_location(H);
+ 'Last-Modified' -> format_last_modified(H);
+ 'Max-Forwards' -> format_max_forwards(H);
+ 'Pragma' -> format_pragma(H);
+ 'Proxy-Authenticate' -> format_proxy_authenticate(H);
+ 'Proxy-Authorization' -> format_proxy_authorization(H);
+ 'Public' -> format_public(H);
+ 'Range' -> format_range(H);
+ 'Referer' -> format_referer(H);
+ 'Retry-After' -> format_retry_after(H);
+ 'Server' -> format_server(H);
+ 'Transfer-Encoding' -> format_transfer_encoding(H);
+ 'Upgrade' -> format_upgrade(H);
+ 'User-Agent' -> format_user_agent(H);
+ 'Vary' -> format_vary(H);
+ 'Via' -> format_via(H);
+ 'Warning' -> format_warning(H);
+ 'Www-Authenticate' -> format_www_authenticate(H);
+ 'Content-Disposition' -> format_content_disposition(H);
+ 'X-Wap-Application-Id' -> format_x_wap_application_id(H);
+ 'X-Wap-Content-Uri' -> format_x_wap_content_uri(H);
+ 'X-Wap-Initiator-Uri' -> format_x_wap_initiator_uri(H);
+ 'Accept-Application' -> format_accept_application(H);
+ 'Bearer-Indication' -> format_bearer_indication(H);
+ 'Push-Flag' -> format_push_flag(H);
+ 'Profile' -> format_profile(H);
+ 'Profile-Diff' -> format_profile_diff(H);
+ 'Profile-Warning' -> format_profile_warning(H);
+ 'Expect' -> format_expect(H);
+ 'Te' -> format_te(H);
+ 'Trailer' -> format_trailer(H);
+ 'X-Wap-Tod' -> format_x_wap_tod(H);
+ 'Content-Id' -> format_content_id(H);
+ 'Set-Cookie' -> format_set_cookie(H);
+ 'Cookie' -> format_cookie(H);
+ 'Encoding-Version' -> format_encoding_version(H);
+ 'X-Wap-Security' -> format_x_wap_security(H);
+ 'X-Wap-Loc-Invocation' -> format_x_wap_loc_invocation(H);
+ 'X-Wap-Loc-Delivery' -> format_x_wap_loc_delivery(H);
+ _Field ->
+ ?dbg("Warning: header field ~s not recognissed\n",[_Field]),
+ to_list(H#wsp_header.value)
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Encode of field values
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Accept: <content-type> [q=<q-value>] [params]
+%% Type: Multiple
+%% Ref: 8.4.2.7
+%%
+%% Accept-value = Constrained-media | Accept-general-form
+%%
+%% Accept-general-form = Value-length Media-range [Accept-parameters]
+%% Media-range = (Well-known-media | Extension-media) *(Parameter)
+%% Accept-parameters = Q-token Q-value *(Accept-extension)
+%% Accept-extension = Parameter
+%% Constrain-media = Constrained-encoding
+%% Well-known-media = Integer-value
+%% Constrained-encoding = Short-Integer | Extension-media
+%% Q-token = <Octet 128>
+%%
+parse_accept(String) ->
+ %% FIXME
+ ?WH('Accept',String,[]).
+
+format_accept(H) ->
+ [H#wsp_header.value, format_params(H#wsp_header.params)].
+
+encode_accept(H, Version) ->
+ case encode_params(H#wsp_header.params,Version) of
+ <<>> ->
+ encode_well_known_media(H#wsp_header.value, Version);
+ Params ->
+ Media = encode_well_known_media(H#wsp_header.value, Version),
+ e_value(Media, Params)
+ end.
+
+decode_accept(Value, Version) when integer(Value) ->
+ %% Constrained-encoding: Short-Integer
+ ?WH('Accept',decode_well_known_media(Value, Version),[]);
+decode_accept(Value, Version) when list(Value) ->
+ ?WH('Accept',decode_well_known_media(Value,Version),[]);
+decode_accept({_,Data}, Version) ->
+ %% Accept-general-form
+ {Value,QData} = scan_header_data(Data),
+ Media_Range = decode_well_known_media(Value,Version),
+ Params = decode_params(QData, Version),
+ ?WH('Accept',Media_Range,Params).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Accept-Charset: <charset> | * [q=<q-value>]
+%% Type: Multiple
+%% Ref: 8.4.2.8
+%% Note that the definition of this one is a mess!!!!
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_accept_charset(String) ->
+ %% FIXME
+ ?WH('Accept-Charset',String,[]).
+
+format_accept_charset(H) ->
+ [H#wsp_header.value, format_params(H#wsp_header.params)].
+
+encode_accept_charset(H, _Version) ->
+ %% FIXME
+ encode_text_string(H#wsp_header.value).
+
+decode_accept_charset(0, _Version) ->
+ ?WH('Accept-Charset',"*",[]);
+decode_accept_charset(Value, _Version) when integer(Value) ->
+ ?WH('Accept-Charset', decode_charset(Value),[]);
+decode_accept_charset(Value, _Version) when list(Value) ->
+ ?WH('Accept-Charset',Value,[]);
+decode_accept_charset({short,Data}, _Version) ->
+ %% Me guessing that the short form SHOULD be mulit octet integer!!!
+ Value = d_long(Data),
+ ?WH('Accept-Charset', decode_charset(Value),[]);
+decode_accept_charset({long,Value}, _Version) ->
+ {Data1, QData} = scan_header_data(Value),
+ CharSet = case Data1 of
+ 0 ->
+ "*";
+ Value1 when integer(Value1) ->
+ decode_charset(Value1);
+ Value1 when list(Value1) ->
+ Value1;
+ {short,Value1} ->
+ Value2 = d_long(Value1),
+ decode_charset(Value2)
+ end,
+ Params = if QData == <<>> ->
+ [];
+ true ->
+ {QValue,_} = d_q_value(QData),
+ {CharSet,[{q, QValue}]}
+ end,
+ ?WH('Accept-Charset',CharSet, Params).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Accept-Encoding: gzip | compress | deflate | * [q=<q-value>]
+%% Ref:
+%% Type: Multiple
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_accept_encoding(String) ->
+ ?WH('Accept-Encoding',String,[]).
+
+format_accept_encoding(H) ->
+ [H#wsp_header.value, format_params(H#wsp_header.params)].
+
+encode_accept_encoding(H, _Version) ->
+ %% FIXME general form
+ case H#wsp_header.value of
+ "gzip" -> ?ENCODE_SHORT(0);
+ "compress" -> ?ENCODE_SHORT(1);
+ "deflate" -> ?ENCODE_SHORT(2);
+ Value -> encode_text_string(Value)
+ end.
+
+decode_accept_encoding(0, _Version) ->
+ ?WH('Accept-Encoding',"gzip",[]);
+decode_accept_encoding(1, _Version) ->
+ ?WH('Accept-Encoding',"compress",[]);
+decode_accept_encoding(2, _Version) ->
+ ?WH('Accept-Encoding',"deflate",[]);
+decode_accept_encoding(Value, Version) when list(Version) ->
+ ?WH('Accept-Encoding',Value,[]);
+decode_accept_encoding({_,Data}, _Version) when binary(Data) ->
+ {Enc, Data1} = scan_header_data(Data),
+ Params = if Data1 == <<>> ->
+ [];
+ true ->
+ {QVal,_} = d_q_value(Data1),
+ [{q, QVal}]
+ end,
+ case Enc of
+ 0 -> ?WH('Accept-Encoding',"gzip",Params);
+ 1 -> ?WH('Accept-Encoding',"compress",Params);
+ 2 -> ?WH('Accept-Encoding',"deflate",Params);
+ 3 -> ?WH('Accept-Encoding',"*",Params);
+ _ when list(Enc) ->
+ ?WH('Accept-Encoding',Enc,Params)
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%
+%% Accept-Language: * | <lang> [q=<q-value>]
+%% Type: Multiple
+%% Ref: 8.4.2.10
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_accept_language(Value) ->
+ ?WH('Accept-Language',Value,[]).
+
+format_accept_language(H) ->
+ [H#wsp_header.value, format_params(H#wsp_header.params)].
+
+encode_accept_language(H, _Version) ->
+ case H#wsp_header.value of
+ "*" -> ?ENCODE_SHORT(0);
+ Lang -> case catch encode_lang(Lang) of
+ {'EXIT', _} -> encode_text_string(Lang);
+ Code -> encode_integer(Code)
+ end
+ end.
+
+decode_accept_language(0, _Version) ->
+ ?WH('Accept-Language',"*",[]);
+decode_accept_language(Value, _Version) when integer(Value) ->
+ ?WH('Accept-Language',decode_lang(Value),[]);
+decode_accept_language(Value, _Version) when list(Value) ->
+ ?WH('Accept-Language',Value,[]);
+decode_accept_language({_,Data}, _Version) ->
+ {Data1, QData} = scan_header_data(Data),
+ Charset = case Data1 of
+ 0 ->
+ "*";
+ Value1 when integer(Value1) ->
+ decode_lang(Value1);
+ Value1 when list(Value1) ->
+ Value1;
+ {short,Data2} ->
+ decode_lang(d_long(Data2))
+ end,
+ Params =
+ if QData == <<>> ->
+ [];
+ true ->
+ {QVal,_} = d_q_value(QData),
+ [{q, QVal}]
+ end,
+ ?WH('Accept-Language',Charset,Params).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Accept-Ranges: none | bytes | <extension>
+%% Type: single
+%% Ref:
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_accept_ranges(Value) ->
+ ?WH('Accept-Ranges', Value, []).
+
+format_accept_ranges(H) ->
+ H#wsp_header.value.
+
+encode_accept_ranges(H, _Version) ->
+ case H#wsp_header.value of
+ "none" -> ?ENCODE_SHORT(0);
+ "bytes" -> ?ENCODE_SHORT(1);
+ Value -> encode_text_string(Value)
+ end.
+
+decode_accept_ranges(0, _Version) ->
+ ?WH('Accept-Ranges', "none", []);
+decode_accept_ranges(1, _Version) ->
+ ?WH('Accept-Ranges', "bytes", []);
+decode_accept_ranges(Value, _Version) when list(Value) ->
+ ?WH('Accept-Ranges', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Age: <delta-seconds>
+%% Type: single
+%% Ref:
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_age(Value) ->
+ %% FIXME
+ ?WH('Age', Value, []).
+
+format_age(H) ->
+ integer_to_list(H#wsp_header.value).
+
+encode_age(H, _Version) ->
+ e_delta_seconds(H#wsp_header.value).
+
+decode_age(Value, _Version) when integer(Value) ->
+ ?WH('Age', Value, []);
+decode_age({short,Data}, _Version) ->
+ ?WH('Age', d_long(Data), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Allow: <well-known-method>
+%% Type: multiple
+%% Ref:
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_allow(Value) ->
+ ?WH('Allow', parse_well_known_method(Value), []).
+
+format_allow(H) ->
+ atom_to_list(H#wsp_header.value).
+
+encode_allow(H, Version) ->
+ encode_well_known_method(H#wsp_header.value, Version).
+
+decode_allow(Value, Version) ->
+ ?WH('Allow', decode_well_known_method(Value,Version), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Authorization:
+%% Ref: 8.4.2.14
+%% Type: server-to-client
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_authorization(Value) ->
+ parse_credentials('Authorization', Value).
+
+format_authorization(H) ->
+ format_credentials(H#wsp_header.value, H#wsp_header.params).
+
+encode_authorization(H, Version) ->
+ encode_credentials(H#wsp_header.value, H#wsp_header.params, Version).
+
+decode_authorization({_,Data}, Version) ->
+ decode_credentials('Authorization', Data, Version).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%%
+%% Cache-Control:
+%% 8.4.2.15
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_cache_control(Value) ->
+ case Value of
+ "no-cache" -> ?WH('Cache-Control',Value,[]);
+ "no-store" -> ?WH('Cache-Control',Value,[]);
+ "max-stale" -> ?WH('Cache-Control',Value,[]);
+ "only-if-cached" -> ?WH('Cache-Control',Value,[]);
+ "private" -> ?WH('Cache-Control',Value,[]);
+ "public" -> ?WH('Cache-Control',Value,[]);
+ "no-transform" -> ?WH('Cache-Control',Value,[]);
+ "must-revalidate" -> ?WH('Cache-Control',Value,[]);
+ "proxy-revalidate" -> ?WH('Cache-Control',Value,[]);
+ _ ->
+ Params = parse_params([Value]),
+ ?WH('Cache-Control',"",Params)
+ end.
+
+format_cache_control(H) ->
+ if H#wsp_header.value == "" ->
+ format_params0(H#wsp_header.params);
+ true ->
+ [H#wsp_header.value, format_params(H#wsp_header.params)]
+ end.
+
+
+
+encode_cache_control(H, Version) ->
+ case H#wsp_header.value of
+ "no-cache" -> ?ENCODE_SHORT(0);
+ "no-store" -> ?ENCODE_SHORT(1);
+ "max-stale" -> ?ENCODE_SHORT(3);
+ "only-if-cached" -> ?ENCODE_SHORT(5);
+ "private" -> ?ENCODE_SHORT(7);
+ "public" -> ?ENCODE_SHORT(6);
+ "no-transform" -> ?ENCODE_SHORT(8);
+ "must-revalidate" -> ?ENCODE_SHORT(9);
+ "proxy-revalidate" -> ?ENCODE_SHORT(10);
+ "" ->
+ case H#wsp_header.params of
+ [{'no-cache',Field}] ->
+ e_value(?ENCODE_SHORT(0),
+ e_field_name(Field,Version));
+ [{'max-age',Sec}] ->
+ e_value(?ENCODE_SHORT(2),
+ e_delta_seconds(Sec));
+ [{'max-fresh',Sec}] ->
+ e_value(?ENCODE_SHORT(4),
+ e_delta_seconds(Sec));
+ [{'private',Field}] ->
+ e_value(?ENCODE_SHORT(7),
+ e_field_name(Field,Version));
+ [{'s-maxage',Sec}] ->
+ e_value(?ENCODE_SHORT(11),
+ e_delta_seconds(Sec))
+ end;
+ Ext ->
+ [Param] = H#wsp_header.params,
+ e_value(encode_text_string(Ext),
+ encode_parameter(Param, Version))
+ end.
+
+
+decode_cache_control(Value, _Version) when integer(Value) ->
+ case Value of
+ 0 -> ?WH('Cache-Control',"no-cache",[]);
+ 1 -> ?WH('Cache-Control',"no-store",[]);
+ 3 -> ?WH('Cache-Control',"max-stale",[]);
+ 5 -> ?WH('Cache-Control',"only-if-cached",[]);
+ 7 -> ?WH('Cache-Control',"private",[]);
+ 6 -> ?WH('Cache-Control',"public",[]);
+ 8 -> ?WH('Cache-Control',"no-transform",[]);
+ 9 -> ?WH('Cache-Control',"must-revalidate",[]);
+ 10 -> ?WH('Cache-Control',"proxy-revalidate",[])
+ end;
+decode_cache_control(Value, _Version) when list(Value) ->
+ ?WH('Cache-Control',Value,[]);
+decode_cache_control({_,Data},Version) ->
+ {CacheDir, Data1} = scan_header_data(Data),
+ case CacheDir of
+ 0 ->
+ {Field,_} = d_field_name(Data1),
+ ?WH('Cache-Control',"",[{'no-cache',Field}]);
+ 2 ->
+ {Sec,_} = d_integer_value(Data1),
+ ?WH('Cache-Control',"",[{'max-age',Sec}]);
+ 4 ->
+ {Sec,_} = d_integer_value(Data1),
+ ?WH('Cache-Control',"",[{'max-fresh',Sec}]);
+ 7 ->
+ {Field,_} = d_field_name(Data1),
+ ?WH('Cache-Control',"",[{private,Field}]);
+ 11 ->
+ {Sec,_} = d_integer_value(Data1),
+ ?WH('Cache-Control',"",[{'s-maxage',Sec}]);
+ Ext when list(Ext) ->
+ {Param,_} = decode_parameter(Data1, Version),
+ ?WH('Cache-Control',Ext,[Param])
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Connection: close | Ext
+%% Type: single
+%% Ref: 8.4.2.16
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_connection(Value) ->
+ ?WH('Connection', Value, []).
+
+format_connection(H) ->
+ H#wsp_header.value.
+
+encode_connection(H, _Version) ->
+ case H#wsp_header.value of
+ "close" -> ?ENCODE_SHORT(0);
+ Value -> encode_text_string(Value)
+ end.
+
+decode_connection(0, _Version) ->
+ ?WH('Connection', "close", []);
+decode_connection(Value, _Version) when list(Value) ->
+ ?WH('Connection', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Base: <uri>
+%% Type: single
+%% Ref:
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_content_base(Value) ->
+ ?WH('Content-Base', Value, []).
+
+format_content_base(H) ->
+ H#wsp_header.value.
+
+encode_content_base(H, _Version) ->
+ encode_uri_value(H#wsp_header.value).
+
+decode_content_base(Value, _Version) when list(Value) ->
+ ?WH('Content-Base', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Encoding:
+%% Ref: 8.4.2.18
+%% Type: single
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_content_encoding(Value) ->
+ ?WH('Content-Encoding', tolower(Value), []).
+
+format_content_encoding(H) ->
+ H#wsp_header.value.
+
+encode_content_encoding(H, _Version) ->
+ case H#wsp_header.value of
+ "gzip" -> ?ENCODE_SHORT(0);
+ "compress" -> ?ENCODE_SHORT(1);
+ "deflate" -> ?ENCODE_SHORT(2);
+ Value -> encode_text_string(Value)
+ end.
+
+decode_content_encoding(0, _Version) ->
+ ?WH('Content-Encoding', "gzip", []);
+decode_content_encoding(1, _Version) ->
+ ?WH('Content-Encoding', "compress", []);
+decode_content_encoding(2, _Version) ->
+ ?WH('Content-Encoding',"deflate", []);
+decode_content_encoding(Value, _Version) when list(Value) ->
+ ?WH('Content-Encoding', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Language:
+%% Ref: 8.4.2.19
+%% Type: single
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_content_language(Value) ->
+ ?WH('Content-Language', Value, []).
+
+format_content_language(H) ->
+ H#wsp_header.value.
+
+encode_content_language(H, _Version) ->
+ case H#wsp_header.value of
+ "*" -> ?ENCODE_SHORT(0);
+ Lang -> case catch encode_lang(Lang) of
+ {'EXIT', _} -> encode_text_string(Lang);
+ Code -> encode_integer(Code)
+ end
+ end.
+
+decode_content_language(0, _Version) ->
+ ?WH('Content-Language',"*",[]);
+decode_content_language(Value, _Version) when integer(Value) ->
+ ?WH('Content-Language',decode_lang(Value),[]);
+decode_content_language(Value, _Version) when list(Value) ->
+ ?WH('Content-Language',Value,[]);
+decode_content_language({short,Data}, _Version) ->
+ Value = d_long(Data),
+ ?WH('Content-Language',decode_lang(Value),[]);
+decode_content_language(Value, _Version) when list(Value) ->
+ ?WH('Content-Language',Value,[]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Length: <integer-value>
+%% Ref: 8.4.2.20
+%% Type: single
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_content_length(Value) ->
+ ?WH('Content-Length', list_to_integer(Value), []).
+
+format_content_length(H) ->
+ integer_to_list(H#wsp_header.value).
+
+encode_content_length(H, _Version) ->
+ encode_integer(H#wsp_header.value).
+
+decode_content_length(Value, _Version) when integer(Value) ->
+ ?WH('Content-Length', Value, []);
+decode_content_length({short,Data}, _Version) ->
+ Value = d_long(Data),
+ ?WH('Content-Length', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Location: <uri-value>
+%% Ref: 8.4.2.21
+%% Type: single
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_content_location(Value) ->
+ ?WH('Content-Location', Value, []).
+
+format_content_location(H) ->
+ H#wsp_header.value.
+
+encode_content_location(H, _Version) ->
+ encode_uri_value(H#wsp_header.value).
+
+decode_content_location(Value, _Version) when list(Value) ->
+ ?WH('Content-Location', decode_uri_value(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Md5: <value-length> <digest>
+%% Ref: 8.4.2.22
+%% Type: single, end-to-end
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_content_md5(Value) ->
+ ?WH('Content-Md5', base64:decode(Value), []).
+
+format_content_md5(H) ->
+ base64:encode(H#wsp_header.value).
+
+encode_content_md5(H, _Version) ->
+ e_value(H#wsp_header.value).
+
+decode_content_md5({_,Data}, _Version) ->
+ ?WH('Content-Md5', Data, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Range: <first-byte-pos> <entity-len>
+%% Ref: 8.4.2.23
+%% Type: single
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_content_range(Value) ->
+ %% FIXME:
+ ?WH('Content-Range', Value, []).
+
+format_content_range(H) ->
+ {Pos,Len} = H#wsp_header.value,
+ if Len == "*" ->
+ ["bytes ", integer_to_list(Pos), "-*/*"];
+ true ->
+ ["bytes ", integer_to_list(Pos),"-",integer_to_list(Len-1),
+ "/", integer_to_list(Len)]
+ end.
+
+encode_content_range(H, _Version) ->
+ case H#wsp_header.value of
+ {Pos, "*"} ->
+ e_value(e_uintvar(Pos), <<128>>);
+ {Pos, Len} ->
+ e_value(e_uintvar(Pos), e_uintvar(Len))
+ end.
+
+decode_content_range({_, Data}, _Version) ->
+ {Pos, Data1} = d_uintvar(Data),
+ Len =
+ case Data1 of
+ <<128>> -> "*";
+ _ ->
+ {L, _} = d_uintvar(Data1),
+ L
+ end,
+ ?WH('Content-Range', {Pos,Len}, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Type:
+%% Ref: 8.4.2.24
+%% Type: single, end-to-end
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_content_type(Value) ->
+ case string:tokens(Value, ";") of
+ [Type | Ps] ->
+ Params = parse_params(Ps),
+ ?WH('Content-Type', Type, Params);
+ [] ->
+ ?WH('Content-Type', Value, [])
+ end.
+
+format_content_type(H) ->
+ [H#wsp_header.value, format_params(H#wsp_header.params)].
+
+encode_content_type(H, Version) ->
+ case encode_params(H#wsp_header.params,Version) of
+ <<>> ->
+ encode_well_known_media(H#wsp_header.value, Version);
+ Params ->
+ Media = encode_well_known_media(H#wsp_header.value, Version),
+ e_value(Media, Params)
+ end.
+
+decode_content_type(Value,Version) when integer(Value) ->
+ ?WH('Content-Type', decode_well_known_media(Value,Version), []);
+decode_content_type(Value,Version) when list(Value) ->
+ ?WH('Content-Type', decode_well_known_media(Value,Version), []);
+decode_content_type({_, Data}, Version) ->
+ {Value,Data1} = scan_header_data(Data),
+ ContentType = if integer(Value) ->
+ decode_well_known_media(Value,Version);
+ list(Value) ->
+ decode_well_known_media(Value,Version);
+ true ->
+ {_,Data2} = Value,
+ decode_well_known_media(d_long(Data2),Version)
+ end,
+ Params = decode_params(Data1, Version),
+ ?WH('Content-Type', ContentType, Params).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Date: <http-date>
+%% Ref: 8.2.4.25
+%% Type: single, end-to-end
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_date(String) ->
+ {DateTime, _} = parse_http_date(String),
+ ?WH('Date', DateTime, []).
+
+format_date(H) ->
+ fmt_date(H#wsp_header.value).
+
+encode_date(H, _Version) ->
+ e_date(H#wsp_header.value).
+
+decode_date(Value, _Version) ->
+ ?WH('Date', d_date(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Etag: <text-string>
+%% Ref: 8.2.4.26
+%% Type: single, end-to-end
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_etag(Value) ->
+ ?WH('Etag', Value, []).
+
+format_etag(H) ->
+ H#wsp_header.value.
+
+encode_etag(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_etag(Value, _Version) ->
+ ?WH('Etag', decode_text_string(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Expires: <date-value>
+%% Ref: 8.4.2.27
+%% Type: single, end-to-end, server-to-client
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_expires(String) ->
+ {DateTime, _} = parse_http_date(String),
+ ?WH('Expires', DateTime, []).
+
+format_expires(H) ->
+ fmt_date(H#wsp_header.value).
+
+encode_expires(H, _Version) ->
+ e_date(H#wsp_header.value).
+
+decode_expires(Value, _Version) ->
+ ?WH('Expires', d_date(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% From: <text-string>
+%% Ref: 8.4.2.28
+%% Type: single,
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_from(Value) ->
+ ?WH('From', Value, []).
+
+format_from(H) ->
+ H#wsp_header.value.
+
+encode_from(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_from(Value, _Version) ->
+ ?WH('From', decode_text_string(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Host: <text-string>
+%% Ref: 8.4.2.29
+%% Type: single, end-to-end, client-to-server
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_host(Value) ->
+ ?WH('Host', Value, []).
+
+format_host(H) ->
+ H#wsp_header.value.
+
+encode_host(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_host(Value, _Version) ->
+ ?WH('Host', decode_text_string(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% If-Modified-Since: <date-value>
+%% Ref: 8.4.2.30
+%% Type: single, end-to-end, client-to-server
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_if_modified_since(String) ->
+ {DateTime, _} = parse_http_date(String),
+ ?WH('If-Modified-Since', DateTime, []).
+
+format_if_modified_since(H) ->
+ fmt_date(H#wsp_header.value).
+
+encode_if_modified_since(H, _Version) ->
+ e_date(H#wsp_header.value).
+
+decode_if_modified_since(Value, _Version) ->
+ ?WH('If-Modified-Since', d_date(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% If-Match: <text-string>
+%% Ref: 8.4.2.31
+%% Type: end-to-end, client-to-server
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_if_match(Value) ->
+ ?WH('If-Match', Value, []).
+
+format_if_match(H) ->
+ H#wsp_header.value.
+
+encode_if_match(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_if_match(Value, _Version) ->
+ ?WH('If-Match', decode_text_string(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% If-None-Match: <text-string>
+%% Ref: 8.4.2.32
+%% Type: end-to-end, client-to-server
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_if_none_match(Value) ->
+ ?WH('If-None-Match', Value, []).
+
+format_if_none_match(H) ->
+ H#wsp_header.value.
+
+encode_if_none_match(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_if_none_match(Value, _Version) ->
+ ?WH('If-None-Match', decode_text_string(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% If-Range: Text | Date
+%% Ref: 8.4.2.33
+%% Type: end-to-end, client-to-server
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_if_range(Value) ->
+ case catch parse_http_date(Value) of
+ {'EXIT', _} ->
+ ?WH('If-Range', Value, []);
+ {DateTime,_} ->
+ ?WH('If-Range', DateTime, [])
+ end.
+
+
+format_if_range(H) ->
+ case H#wsp_header.value of
+ Value when list(Value) -> Value;
+ DateTime -> fmt_date(DateTime)
+ end.
+
+encode_if_range(H, _Version) ->
+ case H#wsp_header.value of
+ Value when list(Value) ->
+ encode_text_string(Value);
+ DateTime ->
+ e_date(DateTime)
+ end.
+
+decode_if_range(Value, _Version) when list(Value) ->
+ ?WH('If-Range', decode_text_string(Value), []);
+decode_if_range(Value, _Version) ->
+ ?WH('If-Range', d_date(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% If-Unmodified-Since: <date-value>
+%% Ref: 8.4.2.34
+%% Type: single, end-to-end, client-to-server
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_if_unmodified_since(String) ->
+ {DateTime, _} = parse_http_date(String),
+ ?WH('If-Unmodified-Since', DateTime, []).
+
+format_if_unmodified_since(H) ->
+ fmt_date(H#wsp_header.value).
+
+encode_if_unmodified_since(H, _Version) ->
+ e_date(H#wsp_header.value).
+
+decode_if_unmodified_since(Value, _Version) ->
+ ?WH('If-Unmodified-Since', d_date(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Location: <uri-value>
+%% Ref: 8.4.2.36
+%% Type: single, end-to-end, server-to-client
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_location(Value) ->
+ ?WH('Location', Value, []).
+
+format_location(H) ->
+ H#wsp_header.value.
+
+encode_location(H, _Version) ->
+ encode_uri_value(H#wsp_header.value).
+
+decode_location(Value, _Version) when list(Value) ->
+ ?WH('Location', decode_uri_value(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Last-Modified: <date-value>
+%% Ref: 8.4.2.35
+%% Type: single, end-to-end, server-to-client
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_last_modified(String) ->
+ {DateTime, _} = parse_http_date(String),
+ ?WH('Last-Modified', DateTime, []).
+
+format_last_modified(H) ->
+ fmt_date(H#wsp_header.value).
+
+encode_last_modified(H, _Version) ->
+ e_date(H#wsp_header.value).
+
+decode_last_modified(Value, _Version) ->
+ ?WH('Last-Modified', d_date(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Max-Forwards: <integer-value>
+%% Ref: 8.4.2.37
+%% Type: single, end-to-end, server-to-client
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_max_forwards(String) ->
+ ?WH('Max-Forwards', list_to_integer(String), []).
+
+format_max_forwards(H) ->
+ integer_to_list(H#wsp_header.value).
+
+encode_max_forwards(H, _Version) ->
+ encode_integer(H#wsp_header.value).
+
+decode_max_forwards(Value, _Version) ->
+ decode_integer(Value).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Pragma: No-Cache | value-length Parameter
+%% Ref:
+%% Type:
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_pragma(Value) ->
+ ?WH('Pragma',Value,[]).
+
+format_pragma(H) ->
+ case H#wsp_header.value of
+ "" -> format_params(H#wsp_header.params);
+ Value -> Value
+ end.
+
+encode_pragma(H, Version) ->
+ case H#wsp_header.value of
+ "no-cache" -> ?ENCODE_SHORT(0);
+ "" ->
+ encode_parameter(hd(H#wsp_header.params), Version)
+ end.
+
+decode_pragma(0, _Version) ->
+ ?WH('Pragma',"no-cache",[]);
+decode_pragma({_,Data}, Version) ->
+ {Param,_} = decode_parameter(Data, Version),
+ ?WH('Pragma',"",[Param]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Proxy-Authenticate:
+%% Ref: 8.4.2.39
+%% Type: single?, client-to-proxy
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_proxy_authenticate(Value) ->
+ parse_challenge('Proxy-Authenticate', Value).
+
+format_proxy_authenticate(H) ->
+ format_challenge(H#wsp_header.value, H#wsp_header.params).
+
+encode_proxy_authenticate(H, Version) ->
+ encode_challenge(H#wsp_header.value,
+ H#wsp_header.params, Version).
+
+decode_proxy_authenticate({_, Data}, Version) ->
+ decode_challenge('Proxy-Authenticate', Data, Version).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Proxy-authorization:
+%% Ref: 8.4.2.40
+%% Type: single?, proxy-to-client
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_proxy_authorization(Value) ->
+ parse_credentials('Proxy-Authorization', Value).
+
+format_proxy_authorization(H) ->
+ format_credentials(H#wsp_header.value, H#wsp_header.params).
+
+encode_proxy_authorization(H, Version) ->
+ encode_credentials(H#wsp_header.value, H#wsp_header.params, Version).
+
+decode_proxy_authorization({_,Data}, Version) ->
+ decode_credentials('Proxy-Authorization', Data, Version).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Public: <well-known-method> | Token-Text
+%% Ref: 8.4.2.41
+%% Type:
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_public(Value) ->
+ ?WH('Public', parse_well_known_method(Value), []).
+
+format_public(H) ->
+ if atom(H#wsp_header.value) ->
+ atom_to_list(H#wsp_header.value);
+ list(H#wsp_header.value) ->
+ H#wsp_header.value
+ end.
+
+encode_public(H, Version) ->
+ if atom(H#wsp_header.value) ->
+ encode_well_known_method(H#wsp_header.value,Version);
+ list(H#wsp_header.value) ->
+ encode_text_string(H#wsp_header.value)
+ end.
+
+decode_public(Value, _Version) when list(Value) ->
+ ?WH('Public', Value, []);
+decode_public(Value, Version) ->
+ ?WH('Public', decode_well_known_method(Value,Version), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Range:
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_range(Value) ->
+ %% FIXME:
+ ?WH('Range', Value, []).
+
+format_range(H) ->
+ case H#wsp_header.value of
+ {First,undefined} ->
+ ["bytes=", integer_to_list(First), "-"];
+ {First,Last} ->
+ ["bytes=", integer_to_list(First), "-", integer_to_list(Last)];
+ Len when integer(Len) ->
+ ["bytes=-", integer_to_list(Len)]
+ end.
+
+encode_range(H, _Version) ->
+ case H#wsp_header.value of
+ {First,undefined} ->
+ e_value(?ENCODE_SHORT(0),
+ e_uintvar(First));
+ {First,Last} ->
+ e_value(?ENCODE_SHORT(0),
+ e_uintvar(First),
+ e_uintvar(Last));
+ Len when integer(Len) ->
+ e_value(?ENCODE_SHORT(1),
+ e_uintvar(Len))
+ end.
+
+decode_range({_,Data}, _Version) ->
+ case scan_header_data(Data) of
+ {0, Data1} ->
+ case d_uintvar(Data1) of
+ {First, <<>>} ->
+ ?WH('Range', {First, undefined},[]);
+ {First, Data2} ->
+ {Last, _} = d_uintvar(Data2),
+ ?WH('Range', {First, Last}, [])
+ end;
+ {1, Data1} ->
+ {Len, _} =d_uintvar(Data1),
+ ?WH('Range', Len, [])
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Referer: <uri-value>
+%% Ref: 8.4.2.43
+%% Type: single
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_referer(Value) ->
+ ?WH('Referer', Value, []).
+
+format_referer(H) ->
+ H#wsp_header.value.
+
+encode_referer(H, _Version) ->
+ encode_uri_value(H#wsp_header.value).
+
+decode_referer(Value, _Version) when list(Value) ->
+ ?WH('Referer', decode_uri_value(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Retry-After: Value-length (Retry-date-value | Retry-delta-seconds)
+%% Ref: 8.4.2.44
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_retry_after(Value) ->
+ case catch parse_http_date(Value) of
+ {'EXIT', _} ->
+ ?WH('Retry-After', list_to_integer(Value), []);
+ {DateTime,_} ->
+ ?WH('Retry-After', DateTime, [])
+ end.
+
+format_retry_after(H) ->
+ Value = H#wsp_header.value,
+ if integer(Value) ->
+ integer_to_list(Value);
+ true ->
+ fmt_date(Value)
+ end.
+
+encode_retry_after(H, _Version) ->
+ Value = H#wsp_header.value,
+ if integer(Value) ->
+ e_value(?ENCODE_SHORT(1),
+ e_delta_seconds(Value));
+ true ->
+ e_value(?ENCODE_SHORT(0),
+ e_date(Value))
+ end.
+
+decode_retry_after({_,Data}, _Version) ->
+ case scan_header_data(Data) of
+ {0, Data1} ->
+ ?WH('Retry-After', d_date(Data1), []);
+ {1, Data1} ->
+ case scan_header_data(Data1) of
+ Sec when integer(Sec) ->
+ ?WH('Retry-After', Sec, []);
+ {short,Data2} ->
+ ?WH('Retry-After', d_long(Data2), [])
+ end
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Server: <text-string>
+%% Ref: 8.4.2.45
+%% Type: server-to-client
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_server(Value) ->
+ ?WH('Server', Value, []).
+
+format_server(H) ->
+ H#wsp_header.value.
+
+encode_server(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_server(Value, _Version) ->
+ ?WH('Server', decode_text_string(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Transfer-Encoding:
+%% Ref: 8.4.2.46
+%% Type: hop-by-hop
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_transfer_encoding(Value) ->
+ ?WH('Transfer-Encoding', Value, []).
+
+format_transfer_encoding(H) ->
+ H#wsp_header.value.
+
+encode_transfer_encoding(H, _Version) ->
+ case H#wsp_header.value of
+ "chunked" -> ?ENCODE_SHORT(0);
+ Value -> encode_text_string(Value)
+ end.
+
+decode_transfer_encoding(0, _Version) ->
+ ?WH('Transfer-Encoding', "chunked", []);
+decode_transfer_encoding(Value, _Version) when list(Value)->
+ ?WH('Transfer-Encoding', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Upgrade: Text-String
+%% Ref: 8.4.2.47
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_upgrade(Value) ->
+ ?WH('Upgrade', Value, []).
+
+format_upgrade(H) ->
+ H#wsp_header.value.
+
+encode_upgrade(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_upgrade(Value, _Version) when list(Value) ->
+ ?WH('Upgrade', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% User-Agent:
+%% Ref: 8.4.2.48
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_user_agent(Value) ->
+ ?WH('User-Agent', Value, []).
+
+format_user_agent(H) ->
+ H#wsp_header.value.
+
+encode_user_agent(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_user_agent(Value, _Version) ->
+ ?WH('User-Agent', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Vary: Well-known-header-field | Token-text
+%% Ref: 8.4.2.49
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_vary(Value) ->
+ ?WH('Vary', normalise_field_name(Value), []).
+
+format_vary(H) ->
+ to_list(H#wsp_header.value).
+
+encode_vary(H, Version) ->
+ e_field_name(H#wsp_header.value, Version).
+
+decode_vary(Value, _Version) when integer(Value) ->
+ ?WH('Vary', lookup_field_name(Value), []);
+decode_vary(Value, _Version) when list(Value) ->
+ ?WH('Vary', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Via: <text-string>
+%% Ref: 8.4.2.50
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_via(Value) ->
+ ?WH('Via', Value, []).
+
+format_via(H) ->
+ H#wsp_header.value.
+
+encode_via(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_via(Value, _Version) when list(Value) ->
+ ?WH('Via', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Warning: Warn-Code | Warning-value
+%% Ref: 8.4.2.51
+%% Type: general, multiple
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_warning(Value) ->
+ case string:tokens(Value, " ") of
+ [Code] ->
+ ?WH('Warning', {list_to_integer(Code),"",""}, []);
+ [Code,Agent,Text] ->
+ ?WH('Warning', {list_to_integer(Code), Agent, Text}, [])
+ end.
+
+format_warning(H) ->
+ case H#wsp_header.value of
+ {Code, "", ""} ->
+ integer_to_list(Code);
+ {Code, Agent, Text} ->
+ [integer_to_list(Code), " ", Agent, " ", Text]
+ end.
+
+encode_warning(H, _Version) ->
+ case H#wsp_header.value of
+ {Code,"",""} ->
+ ?ENCODE_SHORT(Code);
+ {Code, Agent, Text} ->
+ e_value(?ENCODE_SHORT(Code),
+ encode_text_string(Agent),
+ encode_text_string(Text))
+ end.
+
+decode_warning(Value, _Version) when integer(Value) ->
+ ?WH('Warning', {Value, "", ""}, []);
+decode_warning({_, Data}, _Version) ->
+ {Code,Data1}= scan_header_data(Data),
+ {Agent,Data2} = d_text_string(Data1),
+ {Text,_Data3} = d_text_string(Data2),
+ ?WH('Warning', {Code,Agent,Text}, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% WWW-Authenticate: challenge
+%% Ref: 8.4.2.52
+%% Type: single? client-to-server
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_www_authenticate(Value) ->
+ parse_challenge('Www-Authenticate', Value).
+
+format_www_authenticate(H) ->
+ format_challenge(H#wsp_header.value, H#wsp_header.params).
+
+encode_www_authenticate(H, Version) ->
+ encode_challenge(H#wsp_header.value,
+ H#wsp_header.params, Version).
+
+decode_www_authenticate({_, Data}, Version) ->
+ decode_challenge('Www-Authenticate', Data, Version).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Disposition: "form-data" | "attachment" [<param>]*
+%% Ref: 8.4.2.53
+%% Type: single
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_content_disposition(Value) ->
+ ?WH('Content-Disposition', Value, []).
+
+format_content_disposition(H) ->
+ [H#wsp_header.value, format_params(H#wsp_header.params)].
+
+encode_content_disposition(H, Version) ->
+ case H#wsp_header.value of
+ "form-data" ->
+ e_value(?ENCODE_SHORT(0),
+ encode_params(H#wsp_header.params, Version));
+ "attachment" ->
+ e_value(?ENCODE_SHORT(1),
+ encode_params(H#wsp_header.params, Version))
+ end.
+
+decode_content_disposition({_,Data}, Version) when binary(Data) ->
+ case scan_header_data(Data) of
+ {0, Data1} ->
+ Params = decode_params(Data1, Version),
+ ?WH('Content-Disposition', "form-data", Params);
+ {1, Data1} ->
+ Params = decode_params(Data1, Version),
+ ?WH('Content-Disposition', "attachment", Params)
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% X-Wap-Application-Id:
+%% Ref: 8.4.2.54
+%% Type:
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_x_wap_application_id(Value) ->
+ ?WH('X-Wap-Application-Id', Value, []).
+
+format_x_wap_application_id(H) ->
+ H#wsp_header.value.
+
+encode_x_wap_application_id(H, _Version) ->
+ encode_push_application(H#wsp_header.value).
+
+decode_x_wap_application_id(Value, _Version) ->
+ ?WH('X-Wap-Application-Id', decode_push_application(Value),[]).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% X-Wap-Content-Uri: <uri-value>
+%% Ref: 8.4.2.55
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_x_wap_content_uri(Value) ->
+ ?WH('X-Wap-Content-Uri', Value, []).
+
+format_x_wap_content_uri(H) ->
+ H#wsp_header.value.
+
+encode_x_wap_content_uri(H, _Version) ->
+ encode_uri_value(H#wsp_header.value).
+
+decode_x_wap_content_uri(Value, _Version) when list(Value) ->
+ ?WH('X-Wap-Content-Uri', decode_uri_value(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% X-Wap-Initiator-Uri: <uri-value>
+%% Ref: 8.4.2.56
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_x_wap_initiator_uri(Value) ->
+ ?WH('X-Wap-Initiator-Uri', Value, []).
+
+format_x_wap_initiator_uri(H) ->
+ H#wsp_header.value.
+
+encode_x_wap_initiator_uri(H, _Version) ->
+ encode_uri_value(H#wsp_header.value).
+
+decode_x_wap_initiator_uri(Value, _Version) when list(Value) ->
+ ?WH('X-Wap-Initiator-Uri', decode_uri_value(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Accept-Application: Any-Application | Appication-Id-Value
+%% Ref: 8.4.2.57
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_accept_application(Value) ->
+ ?WH('Accept-Application', Value, []).
+
+format_accept_application(H) ->
+ H#wsp_header.value.
+
+
+encode_accept_application(H, _Version) ->
+ case H#wsp_header.value of
+ "*" -> ?ENCODE_SHORT(0);
+ Value ->
+ case catch encode_push_application(Value) of
+ {'EXIT',_} ->
+ encode_uri_value(Value);
+ App ->
+ encode_integer(App)
+ end
+ end.
+
+decode_accept_application(0, _Version) ->
+ ?WH('Accept-Application', "*", []);
+decode_accept_application(Value, _Version) when integer(Value) ->
+ ?WH('Accept-Application', decode_push_application(Value), []);
+decode_accept_application({short,Data}, _Version) ->
+ Value = d_long(Data),
+ ?WH('Accept-Application', decode_push_application(Value), []);
+decode_accept_application(Value, _Version) when list(Value) ->
+ ?WH('Accept-Application', decode_uri_value(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Bearer-Indication: <integer-value>
+%% Type: sinlge
+%% Ref: 8.4.2.58
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_bearer_indication(Value) ->
+ ?WH('Bearer-Indication', Value, []).
+
+format_bearer_indication(H) ->
+ integer_to_list(H#wsp_header.value).
+
+encode_bearer_indication(H, _Version) ->
+ encode_integer(H#wsp_header.value).
+
+decode_bearer_indication(Value, _Version) when integer(Value) ->
+ ?WH('Bearer-Indication', Value, []);
+decode_bearer_indication({short,Data}, _Version) ->
+ Value = d_long(Data),
+ ?WH('Bearer-Indication', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Push-Flag: Short-Integer
+%% Type: single
+%% Ref: 8.4.2.59
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_push_flag(Value) ->
+ ?WH('Push-Flag', integer_to_list(Value), []).
+
+format_push_flag(H) ->
+ integer_to_list(H#wsp_header.value).
+
+encode_push_flag(H, _Version) ->
+ ?ENCODE_SHORT(H#wsp_header.value).
+
+decode_push_flag(Value, _Version) when integer(Value) ->
+ ?WH('Push-Flag', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Profile: <uri-value>
+%% Ref: 8.4.2.60
+%% Type: single, hop-by-hop, client-to-proxy
+%%
+%% Note: Normally transfered as 'X-Wap-Profile'
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_profile(Value) ->
+ ?WH('Profile', Value, []).
+
+format_profile(H) ->
+ H#wsp_header.value.
+
+encode_profile(H, _Version) ->
+ encode_uri_value(H#wsp_header.value).
+
+decode_profile(Value, _Version) ->
+ ?WH('Profile', decode_uri_value(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Profile-Diff: Value-Length Octets
+%% Ref: 8.4.2.61
+%% Type: single, hop-by-hop, client-to-proxy
+%%
+%% Value is WBXML encoded profile diff information
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_profile_diff(Value) ->
+ %% FIXME parse XML code?
+ ?WH('Profile-Diff', Value, []).
+
+format_profile_diff(_H) ->
+ %% FIXME emit ???
+ "WBXML".
+
+encode_profile_diff(H, _Version) ->
+ e_value(H#wsp_header.value).
+
+decode_profile_diff({_,Value}, _Version) ->
+ ?WH('Profile-Diff', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Profile-Warning: Code
+%% Ref: 8.4.2.62
+%% Type: single
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_profile_warning(Value) ->
+ ?WH('Profile-Warning', {Value,"",undefined}, []).
+
+format_profile_warning(H) ->
+ {Code,Target,Date} = H#wsp_header.value,
+ CodeData = integer_to_list(Code),
+ if Target == "", Date == undefined ->
+ CodeData;
+ Date == undefined ->
+ [CodeData," ",Target];
+ true ->
+ [CodeData," ",Target," ",format_date(Date)]
+ end.
+
+
+encode_profile_warning(H, _Version) ->
+ {Code,Target,Date} = H#wsp_header.value,
+ CodeData = case Code of
+ 100 -> ?ENCODE_SHORT(16#10);
+ 101 -> ?ENCODE_SHORT(16#11);
+ 102 -> ?ENCODE_SHORT(16#12);
+ 200 -> ?ENCODE_SHORT(16#20);
+ 201 -> ?ENCODE_SHORT(16#21);
+ 202 -> ?ENCODE_SHORT(16#22);
+ 203 -> ?ENCODE_SHORT(16#23)
+ end,
+ if Target == "", Date == undefined ->
+ CodeData;
+ Date == undefined ->
+ e_value(CodeData, encode_text_string(Target));
+ true ->
+ e_value(CodeData, encode_text_string(Target), e_date(Date))
+ end.
+
+
+decode_profile_warning(Value, _Version) when integer(Value) ->
+ Code = case Value of
+ 16#10 -> 100;
+ 16#11 -> 101;
+ 16#12 -> 102;
+ 16#20 -> 200;
+ 16#21 -> 201;
+ 16#22 -> 202;
+ 16#23 -> 203
+ end,
+ ?WH('Profile-Warning', {Code,"",undefined}, []);
+decode_profile_warning({_, <<1:1, Value:7, Data>>}, _Version) ->
+ Code = case Value of
+ 16#10 -> 100;
+ 16#11 -> 101;
+ 16#12 -> 102;
+ 16#20 -> 200;
+ 16#21 -> 201;
+ 16#22 -> 202;
+ 16#23 -> 203
+ end,
+ {Target,Data1} = d_text_string(Data),
+ Date =
+ if Data1 == <<>> ->
+ undefined;
+ true ->
+ {DateValue,_} = scan_header_data(Data1),
+ d_date(DateValue)
+ end,
+ ?WH('Profile-Warning', {Code,Target,Date}, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Expect: 100-contine | Expect-expression
+%% Ref: 8.4.2.63
+%% Type: client-to-server
+%% Note: Bug in the spec value-length is missing !!!
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_expect(Value) ->
+ ?WH('Expect', Value, []).
+
+format_expect(H) ->
+ case H#wsp_header.value of
+ {Var,Val} ->
+ [Var,"=",Val, format_params(H#wsp_header.params)];
+ Val when list(Val) ->
+ Val
+ end.
+
+encode_expect(H, Version) ->
+ case H#wsp_header.value of
+ "100-continue" ->
+ ?ENCODE_SHORT(0);
+ {Var,Val} ->
+ e_value(encode_text_string(Var),
+ encode_text_string(Val),
+ encode_params(H#wsp_header.params,Version))
+ end.
+
+decode_expect(0, _Version) ->
+ ?WH('Expect', "100-continue", []);
+decode_expect({_, Data}, Version) ->
+ {Var, Data1} = d_text_string(Data),
+ {Val, Data2} = d_text_string(Data1),
+ Params = decode_params(Data2, Version),
+ ?WH('Expect', {decode_text_string(Var),
+ decode_text_string(Val)}, Params).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Te: Trailers | TE-General-From
+%% Ref: 8.4.2.64
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_te(Value) ->
+ ?WH('Te', Value, []).
+
+format_te(H) ->
+ [H#wsp_header.value, format_params(H#wsp_header.params)].
+
+encode_te(H, Version) ->
+ case H#wsp_header.value of
+ "trailers" -> ?ENCODE_SHORT(1);
+ "chunked" ->
+ e_value(?ENCODE_SHORT(2),
+ encode_params(H#wsp_header.params,Version));
+ "identity" ->
+ e_value(?ENCODE_SHORT(3),
+ encode_params(H#wsp_header.params,Version));
+ "gzip" ->
+ e_value(?ENCODE_SHORT(4),
+ encode_params(H#wsp_header.params,Version));
+ "compress" ->
+ e_value(?ENCODE_SHORT(5),
+ encode_params(H#wsp_header.params,Version));
+ "deflate" ->
+ e_value(?ENCODE_SHORT(6),
+ encode_params(H#wsp_header.params,Version));
+ Value ->
+ e_value(encode_text_string(Value),
+ encode_params(H#wsp_header.params,Version))
+ end.
+
+decode_te(1, _Version) ->
+ ?WH('Te', "trailers", []);
+decode_te({_, Data}, _Version) ->
+ {Val, Data1} = scan_header_data(Data),
+ Value =
+ case Val of
+ 2 -> "chunked";
+ 3 -> "identity";
+ 4 -> "gzip";
+ 5 -> "compress";
+ 6 -> "deflate";
+ V when list(V) -> V
+ end,
+ Params = case Data1 of
+ <<>> -> [];
+ <<128, QData>> ->
+ {QValue, _} = d_q_value(QData),
+ [{q, QValue}]
+ end,
+ ?WH('Te', Value, Params).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Trailer: Well-known-header-field | Token-text
+%% Ref: 8.4.2.65
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_trailer(Value) ->
+ ?WH('Trailer', normalise_field_name(Value), []).
+
+format_trailer(H) ->
+ to_list(H#wsp_header.value).
+
+encode_trailer(H, Version) ->
+ e_field_name(H#wsp_header.value, Version).
+
+decode_trailer(Value, _Version) when integer(Value) ->
+ ?WH('Trailer', lookup_field_name(Value), []);
+decode_trailer(Value, _Version) when list(Value) ->
+ ?WH('Trailer', Value, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% X-Wap-Tod:
+%% Ref: 8.4.2.66
+%% Type: hop-by-hop
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_x_wap_tod(String) ->
+ {DateTime, _} = parse_http_date(String),
+ ?WH('X-Wap-Tod', DateTime, []).
+
+format_x_wap_tod(H) ->
+ fmt_date(H#wsp_header.value).
+
+encode_x_wap_tod(H, _Version) ->
+ e_date(H#wsp_header.value).
+
+decode_x_wap_tod(Value, _Version) ->
+ ?WH('X-Wap-Tod', d_date(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Content-Id: <quoted-string>
+%% Type:
+%% Ref: 8.4.2.67
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_content_id(Value) ->
+ ?WH('Content-Id', Value, []).
+
+format_content_id(H) ->
+ [$", H#wsp_header.value, $"].
+
+encode_content_id(H, _Version) ->
+ encode_quoted_string(H#wsp_header.value).
+
+decode_content_id(Value, _Version) when list(Value) ->
+ ?WH('Content-Id', decode_quoted_string(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Set-Cookie: <len> <cookie-version> <cookie-name> <cokie-value> <parm>*
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_set_cookie(String) ->
+ %% MEGA FIXME; Cookie-value may be a quoted string and
+ %% contain both ,=; etc Fix several cookies on same line!!
+ case string:tokens(String, ";") of
+ [Cookie | Ps] ->
+ case string:tokens(Cookie, "=") of
+ [Name,Value] ->
+ Params = parse_params(Ps),
+ ?WH('Set-Cookie', {{1,0}, Name, Value}, Params);
+ [Name] ->
+ Params = parse_params(Ps),
+ ?WH('Set-Cookie', {{1,0}, Name, ""}, Params)
+ end;
+ [] ->
+ ?WH('Set-Cookie', {{1,0}, String, ""}, [])
+ end.
+
+format_set_cookie(H) ->
+ case H#wsp_header.value of
+ {{1,0},Name,Value} ->
+ [Name, "=", Value,format_params(H#wsp_header.params)];
+ {Version,Name,Value} ->
+ [format_version(Version)," ",
+ Name, "=", Value,
+ format_params(H#wsp_header.params)]
+ end.
+
+encode_set_cookie(H, Version) ->
+ {CookieVersion,Name,Value} = H#wsp_header.value,
+ e_value(encode_version(CookieVersion),
+ encode_text_string(Name),
+ encode_text_string(Value),
+ encode_params(H#wsp_header.params, Version)).
+
+decode_set_cookie({_, Data}, Version) ->
+ {CookieVersion, Data1} = scan_header_data(Data),
+ {CookieName, Data2} = scan_header_data(Data1),
+ {CookieValue, Data3} = scan_header_data(Data2),
+ Params = decode_params(Data3, Version),
+ ?WH('Set-Cookie', {decode_version(CookieVersion),
+ decode_text_string(CookieName),
+ decode_text_string(CookieValue)}, Params).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Cookie:
+%% Ref: 8.4.2.69
+%% Type: single?, client-to-server
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_cookie(Value) ->
+ %% FIXME parse cookie version etc
+ ?WH('Cookie', {{1,0},Value}, []).
+
+format_cookie(H) ->
+ case H#wsp_header.value of
+ {{1,0}, Cookies} ->
+ lists:map(fun({Name,Value,Ps}) ->
+ [Name,"=",Value, format_params(Ps)]
+ end, Cookies);
+ {Version, Cookies} ->
+ [format_version(Version)," ",
+ lists:map(fun({Name,Value,Ps}) ->
+ [Name,"=",Value, format_params(Ps)]
+ end, Cookies)]
+ end.
+
+encode_cookie(H, Version) ->
+ {Version, Cookies} = H#wsp_header.value,
+ e_value(encode_version(Version),
+ encode_cookies(Cookies, [])).
+
+encode_cookies([{Name,Value,Ps} | Cs], Acc) ->
+ List =
+ [encode_text_string(Name),
+ encode_text_string(Value) |
+ case Ps of
+ [{path,P},{domain,D}] ->
+ [encode_text_string(P), encode_text_string(D)];
+ [{domain,D},{path,P}] ->
+ [encode_text_string(P), encode_text_string(D)];
+ [{path,P}] ->
+ [encode_text_string(P)];
+ [{domain,D}] ->
+ [encode_text_string(""), encode_text_string(D)];
+ [] ->
+ []
+ end],
+ Sz = lists:sum(lists:map(fun(B) -> size(B) end, List)),
+ encode_cookies(Cs, [[e_uintvar(Sz) | List] | Acc]);
+encode_cookies([], Acc) ->
+ list_to_binary(lists:reverse(Acc)).
+
+
+decode_cookie({_, Data}, _Version) ->
+ {CookieVersion, Data1} = scan_header_data(Data),
+ Cookies = decode_cookies(Data1, []),
+ ?WH('Cookie', {decode_version(CookieVersion), Cookies}, []).
+
+decode_cookies(<<>>, Acc) ->
+ lists:reverse(Acc);
+decode_cookies(Data0, _Acc) -> %% IS IGNORING Acc A BUG OR NOT ?
+ {Len, Data1} = d_uintvar(Data0),
+ <<C0:Len/binary, Data2/binary>> = Data1,
+ {Name, C1} = scan_header_data(C0),
+ {Value, C2} = scan_header_data(C1),
+ {Ps1, C3} =
+ case d_text_string(C2) of
+ {"", C21} -> {[], C21};
+ {Path,C21} -> {[{path,Path}], C21}
+ end,
+ {Ps2, _} =
+ case C3 of
+ <<>> -> {[], <<>>};
+ _ ->
+ {Domain,C4} = d_text_string(C3),
+ {[{domain,Domain}], C4}
+ end,
+ decode_cookies(Data2, [{decode_text_string(Name),
+ decode_text_string(Value),
+ Ps1++Ps2}]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Encoding-Version: Version-Value | Value-length Code-Page [Version-Value]
+%% Ref: 8.4.2.70
+%% Type: single, hop-by-hop, client-and-proxys
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_encoding_version(Value) ->
+ ?WH('Encoding-Version', parse_version(Value), []).
+
+format_encoding_version(H) ->
+ format_version(H#wsp_header.value).
+
+encode_encoding_version(H, _Version) ->
+ encode_version(H#wsp_header.value).
+
+decode_encoding_version(Value, _Version) when integer(Value) ->
+ ?WH('Encoding-Version', decode_version(Value), []);
+decode_encoding_version(Value, _Version) when list(Value) ->
+ %% Note: in this case we parse the Value since we
+ %% Must know the Encoding version
+ ?WH('Encoding-Version', parse_version(Value), []);
+decode_encoding_version({_,<<_:1,_CodePage:7>>}, _Version) ->
+ %% ??? FIXME
+ ?WH('Encoding-Version', "", []);
+decode_encoding_version({_,<<_:1,_CodePage:7, Data1/binary>>}, _Version) ->
+ {Value,_Data2} = scan_header_data(Data1),
+ %% FIXME CodePage
+ ?WH('Encoding-Version', decode_version(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% X-Wap-Security:
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_x_wap_security(Value) ->
+ ?WH('X-Wap-Security', Value, []).
+
+format_x_wap_security(H) ->
+ H#wsp_header.value.
+
+encode_x_wap_security(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_x_wap_security(Value, _Version) ->
+ ?WH('X-Wap-Security', decode_text_string(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% X-Wap-Loc-Invocation:
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_x_wap_loc_invocation(Value) ->
+ ?WH('X-Wap-Loc-Invocation', Value, []).
+
+format_x_wap_loc_invocation(H) ->
+ H#wsp_header.value.
+
+encode_x_wap_loc_invocation(H, _Version) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_x_wap_loc_invocation(Value, _Version) ->
+ ?WH('X-Wap-Loc-Invocation', decode_text_string(Value), []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% X-Wap-Loc-Delivery:
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+parse_x_wap_loc_delivery(Value) ->
+ ?WH('X-Wap-Loc-Delivery', Value, []).
+
+format_x_wap_loc_delivery(H) ->
+ H#wsp_header.value.
+
+encode_x_wap_loc_delivery(H, _Value) ->
+ encode_text_string(H#wsp_header.value).
+
+decode_x_wap_loc_delivery(Value, _Version) ->
+ ?WH('X-Wap-Loc-Delivery', decode_text_string(Value), []).
+
+
+%%
+%% Header Field parameters
+%%
+
+parse_params([Param|Ps]) ->
+ case string:tokens(Param, "=") of
+ [Name,Value0] ->
+ Val = trim(Value0),
+ P = case trim(tolower(Name)) of
+ "q" ->{q,Val};
+ "charset" -> {charset,Val};
+ "level" -> {level,Val};
+ "type" -> {type,Val};
+ "name" -> {name,Val};
+ "filename" -> {filename,Val};
+ "differences" -> {differences,Val};
+ "padding" -> {padding,Val};
+ "start" -> {start,Val};
+ "start-info" -> {'start-info',Val};
+ "comment" -> {comment,Val};
+ "domain" -> {domain,Val};
+ "max-age" -> {'max-age',Val};
+ "path" -> {path,Val};
+ "secure" -> {secure,no_value};
+ "sec" -> {sec, Val};
+ "mac" -> {mac, Val};
+ "creation-date" -> {'creation-date', Val};
+ "modification-date" -> {'modification-date', Val};
+ "read-date" -> {'read-date', Val};
+ "size" -> {size, Val};
+ Nm -> {Nm, Val}
+ end,
+ [P | parse_params(Ps)];
+ _ ->
+ parse_params(Ps)
+ end;
+parse_params([]) ->
+ [].
+
+%% format Params without leading ";"
+format_params0([{Param,no_value}|Ps]) ->
+ [to_list(Param) | format_params(Ps)];
+format_params0([{Param,Value}|Ps]) ->
+ [to_list(Param),"=",to_list(Value) | format_params(Ps)].
+
+format_params(Ps) ->
+ lists:map(fun({Param,no_value}) ->
+ ["; ", to_list(Param)];
+ ({Param,Value})->
+ ["; ", to_list(Param),"=",to_list(Value)]
+ end, Ps).
+
+
+encode_params(Params, Version) ->
+ list_to_binary(encode_params1(Params,Version)).
+
+encode_params1([Param|Ps], Version) ->
+ [ encode_parameter(Param, Version) | encode_params1(Ps, Version)];
+encode_params1([], _Version) ->
+ [].
+
+
+decode_params(Data, Version) ->
+ decode_params(Data, [], Version).
+
+decode_params(<<>>, Ps, _Version) ->
+ lists:reverse(Ps);
+decode_params(Data, Ps, Version) ->
+ {ParamVal, Data1} = decode_parameter(Data, Version),
+ decode_params(Data1, [ParamVal | Ps], Version).
+
+
+
+
+encode_parameter({ParamName, ParamValue}, Ver) ->
+ case ParamName of
+ q when Ver >= 16#01 ->
+ <<1:1, 16#00:7,
+ (encode_typed_field(Ver,'Q-value', ParamValue))/binary>>;
+ charset when Ver >= 16#01 ->
+ <<1:1, 16#01:7,
+ (encode_typed_field(Ver,'Well-known-charset',ParamValue))/binary>>;
+ level when Ver >= 16#01 ->
+ <<1:1, 16#02:7,
+ (encode_typed_field(Ver,'Ver-value',ParamValue))/binary>>;
+
+ type when Ver >= ?WSP_12 ->
+ <<1:1, 16#09:7,
+ (encode_typed_field(Ver,'Constrained-encoding',ParamValue))/binary>>;
+ type when Ver >= 16#01 ->
+ <<1:1, 16#03:7,
+ (encode_typed_field(Ver,'Integer-value',ParamValue))/binary>>;
+
+ name when Ver >= ?WSP_14 ->
+ <<1:1, 16#17:7,
+ (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
+ name when Ver >= 16#01 ->
+ <<1:1, 16#05:7,
+ (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
+
+ filename when Ver >= ?WSP_14 ->
+ <<1:1, 16#18:7,
+ (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
+ filename when Ver >= 16#01 ->
+ <<1:1, 16#06:7,
+ (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
+
+ differences when Ver >= 16#01 ->
+ <<1:1, 16#07:7,
+ (encode_typed_field(Ver,'Field-name',ParamValue))/binary>>;
+
+ padding when Ver >= 16#01 ->
+ <<1:1, 16#08:7,
+ (encode_typed_field(Ver,'Short-integer',ParamValue))/binary>>;
+
+
+ start when Ver >= ?WSP_14 ->
+ <<1:1, 16#19:7,
+ (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
+ start when Ver >= ?WSP_12 ->
+ <<1:1, 16#0A:7,
+ (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
+
+
+ 'start-info' when Ver >= ?WSP_14 ->
+ <<1:1, 16#1A:7,
+ (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
+ 'start-info' when Ver >= ?WSP_12 ->
+ <<1:1, 16#0B:7,
+ (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
+
+ comment when Ver >= ?WSP_14 ->
+ <<1:1, 16#1B:7,
+ (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
+ comment when Ver >= ?WSP_13 ->
+ <<1:1, 16#0C:7,
+ (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
+
+ domain when Ver >= ?WSP_14 ->
+ <<1:1, 16#1C:7,
+ (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
+ domain when Ver >= ?WSP_13 ->
+ <<1:1, 16#0D:7,
+ (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
+
+ 'max-age' when Ver >= ?WSP_13 ->
+ <<1:1, 16#0E:7,
+ (encode_typed_field(Ver,'Delta-seconds-value',ParamValue))/binary>>;
+
+ path when Ver >= ?WSP_14 ->
+ <<1:1, 16#1D:7,
+ (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
+ path when Ver >= ?WSP_13 ->
+ <<1:1, 16#0F:7,
+ (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
+
+ secure when Ver >= ?WSP_13 ->
+ <<1:1, 16#10:7,
+ (encode_typed_field(Ver,'No-value',ParamValue))/binary>>;
+ %% NOTE: "sec" and "mac" are really 1.4 features but used by 1.3 client provisioning
+ %"sec" when Ver >= ?WSP_14 ->
+ sec when Ver >= ?WSP_13 ->
+ <<1:1, 16#11:7,
+ (encode_typed_field(Ver,'Short-integer',ParamValue))/binary>>;
+ %"mac" when Ver >= ?WSP_14 ->
+ mac when Ver >= ?WSP_13 ->
+ <<1:1, 16#12:7,
+ (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
+ 'creation-date' when Ver >= ?WSP_14 ->
+ <<1:1, 16#13:7,
+ (encode_typed_field(Ver,'Date-value',ParamValue))/binary>>;
+ 'modification-date' when Ver >= ?WSP_14 ->
+ <<1:1, 16#14:7,
+ (encode_typed_field(Ver,'Date-value',ParamValue))/binary>>;
+ 'read-date' when Ver >= ?WSP_14 ->
+ <<1:1, 16#15:7,
+ (encode_typed_field(Ver,'Date-value',ParamValue))/binary>>;
+ size when Ver >= ?WSP_14 ->
+ <<1:1, 16#16:7,
+ (encode_typed_field(Ver,'Integer-value',ParamValue))/binary>>;
+ _ ->
+ <<(encode_text_string(ParamName))/binary,
+ (encode_text_string(ParamValue))/binary >>
+ end.
+
+%% decode_parameter: return {ParameterName, ParamterValue}
+decode_parameter(<<1:1,Code:7,Data/binary>>, Version) ->
+ case Code of
+ 16#00 ->
+ {Val,Data1} = decode_typed_field('Q-value', Data, Version),
+ {{ q, Val}, Data1};
+
+ 16#01 ->
+ {Val,Data1} = decode_typed_field('Well-known-charset',Data,Version),
+ {{charset, Val}, Data1};
+
+ 16#02 ->
+ {Val,Data1} = decode_typed_field('Version-value',Data,Version),
+ {{level, Val}, Data1};
+
+ 16#03 ->
+ {Val,Data1} = decode_typed_field('Integer-value', Data,Version),
+ {{type, Val}, Data1};
+
+ 16#05 ->
+ {Val,Data1} = decode_typed_field('Text-string', Data,Version),
+ {{name, Val}, Data1};
+
+ 16#06 ->
+ {Val,Data1} = decode_typed_field('Text-string', Data,Version),
+ {{filename, Val}, Data1};
+
+ 16#07 ->
+ {Val,Data1} = decode_typed_field('Field-name', Data,Version),
+ {{differences, Val}, Data1};
+
+ 16#08 ->
+ {Val,Data1} = decode_typed_field('Short-integer', Data,Version),
+ {{padding, Val}, Data1};
+
+ 16#09 ->
+ {Val,Data1} = decode_typed_field('Constrained-encoding', Data,Version),
+ {{type, Val}, Data1};
+
+ 16#0A ->
+ {Val,Data1} = decode_typed_field('Text-string', Data,Version),
+ {{start, Val}, Data1};
+
+ 16#0B ->
+ {Val,Data1} = decode_typed_field('Text-string', Data,Version),
+ {{'start-info', Val}, Data1};
+
+ 16#0C ->
+ {Val,Data1} = decode_typed_field('Text-string', Data,Version),
+ {{comment, Val}, Data1};
+
+ 16#0D ->
+ {Val,Data1} = decode_typed_field('Text-string', Data,Version),
+ {{domain, Val}, Data1};
+
+ 16#0E ->
+ {Val,Data1} = decode_typed_field('Delta-seconds-value', Data,Version),
+ {{'max-age', Val}, Data1};
+
+ 16#0F ->
+ {Val,Data1} = decode_typed_field('Text-string', Data,Version),
+ {{path, Val}, Data1};
+
+ 16#10 ->
+ {Val,Data1} = decode_typed_field('No-value', Data,Version),
+ {{secure, Val}, Data1};
+
+ 16#11 ->
+ {Val,Data1} = decode_typed_field('Short-integer', Data,Version),
+ {{sec, Val}, Data1};
+
+ 16#12 ->
+ {Val,Data1} = decode_typed_field('Text-value', Data,Version),
+ {{mac, Val}, Data1};
+
+ 16#13 ->
+ {Val,Data1} = decode_typed_field('Date-value', Data,Version),
+ {{'creation-date', Val}, Data1};
+
+ 16#14 ->
+ {Val,Data1} = decode_typed_field('Date-value', Data,Version),
+ {{'modification-date', Val}, Data1};
+
+ 16#15 ->
+ {Val,Data1} = decode_typed_field('Date-value', Data,Version),
+ {{'read-date', Val}, Data1};
+
+ 16#16 ->
+ {Val,Data1} = decode_typed_field('Integer-value', Data,Version),
+ {{size, Val}, Data1};
+
+ 16#17 ->
+ {Val,Data1} = decode_typed_field('Text-value', Data,Version),
+ {{name, Val}, Data1};
+
+ 16#18 ->
+ {Val,Data1} = decode_typed_field('Text-value', Data,Version),
+ {{filename, Val}, Data1};
+
+ 16#19 ->
+ {Val,Data1} = decode_typed_field('Text-value', Data,Version),
+ {{start, Val}, Data1};
+
+ 16#1A ->
+ {Val,Data1} = decode_typed_field('Text-value', Data,Version),
+ {{'start-info', Val}, Data1};
+
+ 16#1B ->
+ {Val,Data1} = decode_typed_field('Text-value', Data,Version),
+ {{comment, Val}, Data1};
+
+ 16#1C ->
+ {Val,Data1} = decode_typed_field('Text-value', Data,Version),
+ {{domain, Val}, Data1};
+
+ 16#1D ->
+ {Val,Data1} = decode_typed_field('Text-value', Data,Version),
+ {{path, Val}, Data1};
+ _ ->
+ exit({error, unknown_parameter})
+ end;
+decode_parameter(Data, _Version) ->
+ %% Untyped-parameter: Token-Text Untype-value
+ {ParamName,Data1} = d_text_string(Data),
+ %% Untype-value: Integer-Value | Text-Value!
+ {ParamValue, Data2} = decode_untyped_value(Data1),
+ {{ParamName,ParamValue}, Data2}.
+
+
+encode_typed_field(Ver,Type,Value) ->
+ case Type of
+ 'Well-known-charset' ->
+ MIBenum = encode_charset(Value),
+ encode_integer(MIBenum);
+
+ 'Constrained-encoding' ->
+ encode_constrained_media(Value, Ver);
+
+ 'Text-string' ->
+ encode_text_string(Value);
+
+ 'Text-value' ->
+ encode_text_value(Value);
+
+ 'Short-integer' ->
+ ?ENCODE_SHORT(Value);
+
+ 'Date-value' ->
+ e_date(Value);
+
+ 'Delta-Seconds-value' ->
+ e_delta_seconds(Value);
+
+ 'No-value' ->
+ e_no_value(Value);
+
+ _ ->
+ io:format("FIXME: encode_typed_field unsupported type = ~p\n",
+ [Type]),
+ exit({error,badtype})
+ end.
+
+
+decode_typed_field(Type, Data, Version) ->
+ case Type of
+ 'Q-value' ->
+ d_q_value(Data);
+
+ 'Well-known-charset' ->
+ {MIBenum, T100} = d_integer_value(Data),
+ {decode_charset(MIBenum), T100};
+
+ 'Constrained-encoding' ->
+ {Value, Data1} = scan_header_data(Data),
+ {decode_constrained_media(Value,Version), Data1};
+
+ 'Text-string' ->
+ d_text_string(Data);
+
+ 'Text-value' ->
+ d_text_value(Data);
+
+ 'Short-integer' ->
+ decode_short_integer(Data);
+
+ 'Delta-seconds-value' ->
+ d_integer_value(Data);
+
+ 'Date-value' ->
+ {Val, Data1} = decode_long_integer(Data),
+ {d_date(Val), Data1};
+
+ 'Field-name' ->
+ d_field_name(Data);
+
+ 'No-value' ->
+ d_no_value(Data);
+
+ _ ->
+ io:format("FIXME: unsupported type = ~p\n",[Type]),
+ exit({error,badtype})
+ end.
+
+
+%% Integer-Value | Text-Value
+%% return as {Value, Tail}
+decode_untyped_value(<<1:1, Short:7, Tail/binary>>) ->
+ {Short, Tail};
+decode_untyped_value(<<0:3, Len:5, Data/binary>>) when Len =/= 31 ->
+ Sz = Len*8,
+ <<Long:Sz, Tail/binary>> = Data,
+ {Long, Tail};
+decode_untyped_value(Data) ->
+ d_text_string(Data).
+
+
+e_field_name(Value, Version) ->
+ case normalise_field_name(Value) of
+ 'Accept' -> <<16#80>>;
+ 'Accept-Charset' when Version >= ?WSP_13 -> <<16#bb>>;
+ 'Accept-Charset' -> <<16#81>>;
+ 'Accept-Encoding' when Version >= ?WSP_13 -> <<16#bc>>;
+ 'Accept-Encoding' -> <<16#82>>;
+ 'Accept-Language' -> <<16#83>>;
+ 'Accept-Ranges' -> <<16#84>>;
+ 'Age' -> <<16#85>>;
+ 'Allow' -> <<16#86>>;
+ 'Authorization' -> <<16#87>>;
+ 'Cache-Control' when Version >= ?WSP_14 -> <<16#c7>>;
+ 'Cache-Control' when Version >= ?WSP_13 -> <<16#bd>>;
+ 'Cache-Control' -> <<16#88>>;
+ 'Connection' -> <<16#89>>;
+ 'Content-Base' -> <<16#8a>>;
+ 'Content-Encoding' -> <<16#8b>>;
+ 'Content-Language' -> <<16#8c>>;
+ 'Content-Length' -> <<16#8d>>;
+ 'Content-Location' -> <<16#8e>>;
+ 'Content-Md5' -> <<16#8f>>;
+ 'Content-Range' when Version >= ?WSP_13 -> <<16#be>>;
+ 'Content-Range' -> <<16#90>>;
+ 'Content-Type' -> <<16#91>>;
+ 'Date' -> <<16#92>>;
+ 'Etag' -> <<16#93>>;
+ 'Expires' -> <<16#94>>;
+ 'From' -> <<16#95>>;
+ 'Host' -> <<16#96>>;
+ 'If-Modified-Since' -> <<16#97>>;
+ 'If-Match' -> <<16#98>>;
+ 'If-None-Match' -> <<16#99>>;
+ 'If-Range' -> <<16#9a>>;
+ 'If-Unmodified-Since' -> <<16#9b>>;
+ 'Location' -> <<16#9c>>;
+ 'Last-Modified' -> <<16#9d>>;
+ 'Max-Forwards' -> <<16#9e>>;
+ 'Pragma' -> <<16#9f>>;
+ 'Proxy-Authenticate' -> <<16#a0>>;
+ 'Proxy-Authorization' -> <<16#a1>>;
+ 'Public' -> <<16#a2>>;
+ 'Range' -> <<16#a3>>;
+ 'Referer' -> <<16#a4>>;
+ 'Retry-After' -> <<16#a5>>;
+ 'Server' -> <<16#a6>>;
+ 'Transfer-Encoding' -> <<16#a7>>;
+ 'Upgrade' -> <<16#a8>>;
+ 'User-Agent' -> <<16#a9>>;
+ 'Vary' -> <<16#aa>>;
+ 'Via' -> <<16#ab>>;
+ 'Warning' -> <<16#ac>>;
+ 'Www-Authenticate' -> <<16#ad>>;
+ 'Content-Disposition' when Version >= ?WSP_14 -> <<16#c5>>;
+ 'Content-Disposition' -> <<16#ae>>;
+ %% VERSION > 1.1
+ 'X-Wap-Application-Id' when Version >= ?WSP_12 -> <<16#af>>;
+ 'X-Wap-Content-Uri' when Version >= ?WSP_12 -> <<16#b0>>;
+ 'X-Wap-Initiator-Uri' when Version >= ?WSP_12 -> <<16#b1>>;
+ 'Accept-Application' when Version >= ?WSP_12 -> <<16#b2>>;
+ 'Bearer-Indication' when Version >= ?WSP_12 -> <<16#b3>>;
+ 'Push-Flag' when Version >= ?WSP_12 -> <<16#b4>>;
+ 'Profile' when Version >= ?WSP_12 -> <<16#b5>>;
+ 'Profile-Diff' when Version >= ?WSP_12 -> <<16#b6>>;
+ 'Profile-Warning' when Version >= ?WSP_12 -> <<16#b7>>;
+ 'Expect' when Version >= ?WSP_15 -> <<16#c8>>;
+ 'Expect' when Version >= ?WSP_13 -> <<16#b8>>;
+ 'Te' when Version >= ?WSP_13 -> <<16#b9>>;
+ 'Trailer' when Version >= ?WSP_13 -> <<16#ba>>;
+ 'X-Wap-Tod' when Version >= ?WSP_13 -> <<16#bf>>;
+ 'Content-Id' when Version >= ?WSP_13 -> <<16#c0>>;
+ 'Set-Cookie' when Version >= ?WSP_13 -> <<16#c1>>;
+ 'Cookie' when Version >= ?WSP_13 -> <<16#c2>>;
+ 'Encoding-Version' when Version >= ?WSP_13 -> <<16#c3>>;
+ 'Profile-Warning' when Version >= ?WSP_14 -> <<16#c4>>;
+ 'X-Wap-Security' when Version >= ?WSP_14 -> <<16#c6>>;
+ 'X-Wap-Loc-Invocation' when Version >= ?WSP_15 -> <<16#c9>>;
+ 'X-Wap-Loc-Delivery' when Version >= ?WSP_15 -> <<16#ca>>;
+ Field -> encode_text_string(atom_to_list(Field))
+ end.
+
+
+%%
+%% decode and normalise on form list_to_atom("Ulll-Ulll-Ull")
+%%
+normalise_field_name(Cs) when atom(Cs) ->
+ Cs;
+normalise_field_name(Cs) ->
+ list_to_atom(normalise_fieldU(Cs)).
+
+normalise_fieldU([C|Cs]) when C >= $a, C =< $z ->
+ [(C-$a)+$A | normalise_fieldL(Cs)];
+normalise_fieldU([C|Cs]) -> [ C | normalise_fieldL(Cs)];
+normalise_fieldU([]) -> [].
+
+normalise_fieldL([C|Cs]) when C >= $A, C =< $Z ->
+ [(C-$A)+$a | normalise_fieldL(Cs)];
+normalise_fieldL([$-|Cs]) -> [$- | normalise_fieldU(Cs)];
+normalise_fieldL([C|Cs]) -> [C | normalise_fieldL(Cs)];
+normalise_fieldL([]) -> [].
+
+
+tolower([C|Cs]) when C >= $A, C =< $Z ->
+ [(C-$A)+$a | tolower(Cs)];
+tolower([C|Cs]) -> [C|tolower(Cs)];
+tolower([]) -> [].
+
+trim(Cs) ->
+ lists:reverse(trim1(lists:reverse(trim1(Cs)))).
+
+trim1([$\s|Cs]) -> trim1(Cs);
+trim1([$\t|Cs]) -> trim1(Cs);
+trim1([$\r|Cs]) -> trim1(Cs);
+trim1([$\n|Cs]) -> trim1(Cs);
+trim1(Cs) -> Cs.
+
+
+d_field_name(Data) ->
+ case scan_header_data(Data) of
+ {Code, Data1} when integer(Code) ->
+ {lookup_field_name(Code), Data1};
+ {TmpField,Data1} when list(TmpField) ->
+ {normalise_field_name(TmpField), Data1}
+ end.
+
+d_no_value(<<0, Data/binary>>) ->
+ {no_value, Data}.
+
+e_no_value(_) ->
+ <<0>>.
+
+
+lookup_field_name(Code) ->
+ case Code of
+%%% Version 1.1
+ 16#00 -> 'Accept';
+ 16#01 -> 'Accept-Charset';
+ 16#02 -> 'Accept-Encoding';
+ 16#03 -> 'Accept-Language';
+ 16#04 -> 'Accept-Ranges';
+ 16#05 -> 'Age';
+ 16#06 -> 'Allow';
+ 16#07 -> 'Authorization';
+ 16#08 -> 'Cache-Control';
+ 16#09 -> 'Connection';
+ 16#0a -> 'Content-Base';
+ 16#0b -> 'Content-Encoding';
+ 16#0c -> 'Content-Language';
+ 16#0d -> 'Content-Length';
+ 16#0e -> 'Content-Location';
+ 16#0f -> 'Content-Md5';
+ 16#10 -> 'Content-Range';
+ 16#11 -> 'Content-Type';
+ 16#12 -> 'Date';
+ 16#13 -> 'Etag';
+ 16#14 -> 'Expires';
+ 16#15 -> 'From';
+ 16#16 -> 'Host';
+ 16#17 -> 'If-Modified-Since';
+ 16#18 -> 'If-Match';
+ 16#19 -> 'If-None-Match';
+ 16#1a -> 'If-Range';
+ 16#1b -> 'If-Unmodified-Since';
+ 16#1c -> 'Location';
+ 16#1d -> 'Last-Modified';
+ 16#1e -> 'Max-Forwards';
+ 16#1f -> 'Pragma';
+ 16#20 -> 'Proxy-Authenticate';
+ 16#21 -> 'Proxy-Authorization';
+ 16#22 -> 'Public';
+ 16#23 -> 'Range';
+ 16#24 -> 'Referer';
+ 16#25 -> 'Retry-After';
+ 16#26 -> 'Server';
+ 16#27 -> 'Transfer-Encoding';
+ 16#28 -> 'Upgrade';
+ 16#29 -> 'User-Agent';
+ 16#2a -> 'Vary';
+ 16#2b -> 'Via';
+ 16#2c -> 'Warning';
+ 16#2d -> 'Www-Authenticate';
+ 16#2e -> 'Content-Disposition';
+%%% Version 1.2
+ 16#2f -> 'X-Wap-Application-Id';
+ 16#30 -> 'X-Wap-Content-Uri';
+ 16#31 -> 'X-Wap-Initiator-Uri';
+ 16#32 -> 'Accept-Application';
+ 16#33 -> 'Bearer-Indication';
+ 16#34 -> 'Push-Flag';
+ 16#35 -> 'Profile';
+ 16#36 -> 'Profile-Diff';
+ 16#37 -> 'Profile-Warning';
+%%% Version 1.3
+ 16#38 -> 'Expect';
+ 16#39 -> 'Te';
+ 16#3a -> 'Trailer';
+ 16#3b -> 'Accept-Charset';
+ 16#3c -> 'Accept-Encoding';
+ 16#3d -> 'Cache-Control';
+ 16#3e -> 'Content-Range';
+ 16#3f -> 'X-Wap-Tod';
+ 16#40 -> 'Content-Id';
+ 16#41 -> 'Set-Cookie';
+ 16#42 -> 'Cookie';
+ 16#43 -> 'Encoding-Version';
+%%% Version 1.4
+ 16#44 -> 'Profile-Warning';
+ 16#45 -> 'Content-Disposition';
+ 16#46 -> 'X-Wap-Security';
+ 16#47 -> 'Cache-Control';
+%%% Version 1.5
+ 16#48 -> 'Expect';
+ 16#49 -> 'X-Wap-Loc-Invocation';
+ 16#4a -> 'X-Wap-Loc-Delivery';
+%% Unknown
+ _ ->
+ list_to_atom("X-Unknown-"++erlang:integer_to_list(Code, 16))
+ end.
+
+
+encode_charset(Charset) ->
+ %% FIXME: we should really resolve aliases as well
+ %% charset:from_aliases(Charset)
+ case charset:from_mime_name(Charset) of
+ 0 -> exit({error, unknown_charset});
+ MIBenum -> MIBenum
+ end.
+
+encode_language(Language) ->
+ Code = encode_lang(tolower(Language)),
+ <<Code>>.
+
+
+
+decode_charset(MIBenum) ->
+ case charset:to_mime_name(MIBenum) of
+ undefined ->
+ exit({error, unknown_charset});
+ Preferred ->
+ Preferred
+ end.
+
+%% ISO 639 Language Assignments, Appendix A, Table 41, Page 102-103
+decode_lang(Code) ->
+ case lookup_language(Code) of
+ [L|_] -> atom_to_list(L);
+ [] -> ""
+ end.
+
+
+lookup_language(Code) ->
+ case Code of
+ 16#01 -> ['aa','afar'];
+ 16#02 -> ['ab','abkhazian'];
+ 16#03 -> ['af','afrikans'];
+ 16#04 -> ['am','amharic'];
+ 16#05 -> ['ar','arabic'];
+ 16#06 -> ['as','assamese'];
+ 16#07 -> ['ay','aymara'];
+ 16#08 -> ['az','azerbaijani'];
+ 16#09 -> ['ba','bashkir'];
+ 16#0a -> ['be','byelorussian'];
+ 16#0b -> ['bg','bulgarian'];
+ 16#0c -> ['bh','bihari'];
+ 16#0d -> ['bi','bislama'];
+ 16#0e -> ['bn','bangla','bengali'];
+ 16#0f -> ['bo','tibetan'];
+ 16#10 -> ['br','breton'];
+ 16#11 -> ['ca','catalan'];
+ 16#12 -> ['co','corsican'];
+ 16#13 -> ['cs','czech'];
+ 16#14 -> ['cy','welsh'];
+ 16#15 -> ['da','danish'];
+ 16#16 -> ['de','german'];
+ 16#17 -> ['dz','bhutani'];
+ 16#18 -> ['el','greek'];
+ 16#19 -> ['en','english'];
+ 16#1a -> ['eo','esperanto'];
+ 16#1b -> ['es','spanish'];
+ 16#1c -> ['et','estonian'];
+ 16#1d -> ['eu','basque'];
+ 16#1e -> ['fa','persian'];
+ 16#1f -> ['fi','finnish'];
+ 16#20 -> ['fj','fiji'];
+ 16#82 -> ['fo','faeroese'];
+ 16#22 -> ['fr','french'];
+ 16#83 -> ['fy','frisian'];
+ 16#24 -> ['ga','irish'];
+ 16#25 -> ['gd','scots-gaelic'];
+ 16#26 -> ['gl','galician'];
+ 16#27 -> ['gn','guarani'];
+ 16#28 -> ['gu','gujarati'];
+ 16#29 -> ['ha','hausa'];
+ 16#2a -> ['he','hebrew'];
+ 16#2b -> ['hi','hindi'];
+ 16#2c -> ['hr','croatian'];
+ 16#2d -> ['hu','hungarian'];
+ 16#2e -> ['hy','armenian'];
+ 16#84 -> ['ia','interlingua'];
+ 16#30 -> ['id','indonesian'];
+ 16#86 -> ['ie','interlingue'];
+ 16#87 -> ['ik','inupiak'];
+ 16#33 -> ['is','icelandic'];
+ 16#34 -> ['it','italian'];
+ 16#89 -> ['iu','inuktitut'];
+ 16#36 -> ['ja','japanese'];
+ 16#37 -> ['jw','javanese'];
+ 16#38 -> ['ka','georgian'];
+ 16#39 -> ['kk','kazakh'];
+ 16#8a -> ['kl','greenlandic'];
+ 16#3b -> ['km','cambodian'];
+ 16#3c -> ['kn','kannada'];
+ 16#3d -> ['ko','korean'];
+ 16#3e -> ['ks','kashmiri'];
+ 16#3f -> ['ku','kurdish'];
+ 16#40 -> ['ky','kirghiz'];
+ 16#8b -> ['la','latin'];
+ 16#42 -> ['ln','lingala'];
+ 16#43 -> ['lo','laothian'];
+ 16#44 -> ['lt','lithuanian'];
+ 16#45 -> ['lv','lettish','latvian'];
+ 16#46 -> ['mg','malagese'];
+ 16#47 -> ['mi','maori'];
+ 16#48 -> ['mk','macedonian'];
+ 16#49 -> ['ml','malayalam'];
+ 16#4a -> ['mn','mongolian'];
+ 16#4b -> ['mo','moldavian'];
+ 16#4c -> ['mr','marathi'];
+ 16#4d -> ['ms','malay'];
+ 16#4e -> ['mt','maltese'];
+ 16#4f -> ['my','burmese'];
+ 16#81 -> ['na','nauru'];
+ 16#51 -> ['ne','nepali'];
+ 16#52 -> ['nl','dutch'];
+ 16#53 -> ['no','norwegian'];
+ 16#54 -> ['oc','occitan'];
+ 16#55 -> ['om','oromo'];
+ 16#56 -> ['or','oriya'];
+ 16#57 -> ['pa','punjabi'];
+ 16#58 -> ['po','polish'];
+ 16#59 -> ['ps','pushto','pashto'];
+ 16#5a -> ['pt','portugese'];
+ 16#5b -> ['qu','quechua'];
+ 16#8c -> ['rm','rhaeto-romance'];
+ 16#5d -> ['rn','kirundi'];
+ 16#5e -> ['ro','romanian'];
+ 16#5f -> ['ru','russian'];
+ 16#60 -> ['rw','kinyarwanda'];
+ 16#61 -> ['sa','sanskrit'];
+ 16#62 -> ['sd','sindhi'];
+ 16#63 -> ['sg','sangho'];
+ 16#64 -> ['sh','serbo-croatian'];
+ 16#65 -> ['si','sinhalese'];
+ 16#66 -> ['sk','slovak'];
+ 16#67 -> ['sl','slovenian'];
+ 16#68 -> ['sm','samoan'];
+ 16#69 -> ['sn','shona'];
+ 16#6a -> ['so','somali'];
+ 16#6b -> ['sq','albanian'];
+ 16#6c -> ['sr','serbian'];
+ 16#6d -> ['ss','siswati'];
+ 16#6e -> ['st','seshoto'];
+ 16#6f -> ['su','sundanese'];
+ 16#70 -> ['sv','swedish'];
+ 16#71 -> ['sw','swahili'];
+ 16#72 -> ['ta','tamil'];
+ 16#73 -> ['te','telugu'];
+ 16#74 -> ['tg','tajik'];
+ 16#75 -> ['th','thai'];
+ 16#76 -> ['ti','tigrinya'];
+ 16#77 -> ['tk','turkmen'];
+ 16#78 -> ['tl','tagalog'];
+ 16#79 -> ['tn','setswana'];
+ 16#7a -> ['to','tonga'];
+ 16#7b -> ['tr','turkish'];
+ 16#7c -> ['ts','tsonga'];
+ 16#7d -> ['tt','tatar'];
+ 16#7e -> ['tw','twi'];
+ 16#7f -> ['ug','uighur'];
+ 16#50 -> ['uk','ukrainian'];
+ 16#21 -> ['ur','urdu'];
+ 16#23 -> ['uz','uzbek'];
+ 16#2f -> ['vi','vietnamese'];
+ 16#85 -> ['vo','volapuk'];
+ 16#31 -> ['wo','wolof'];
+ 16#32 -> ['xh','xhosa'];
+ 16#88 -> ['yi','yiddish'];
+ 16#35 -> ['yo','yoruba'];
+ 16#3a -> ['za','zhuang'];
+ 16#41 -> ['zh','chinese'];
+ 16#5c -> ['zu','zulu'];
+ _ -> []
+ end.
+
+encode_lang(Language) ->
+ case tolower(Language) of
+ "aa" -> 16#01;
+ "afar" -> 16#01;
+ "ab" -> 16#02;
+ "abkhazian" -> 16#02;
+ "af" -> 16#03;
+ "afrikans" -> 16#03;
+ "am" -> 16#04;
+ "amharic" -> 16#04;
+ "ar" -> 16#05;
+ "arabic" -> 16#05;
+ "as" -> 16#06;
+ "assamese" -> 16#06;
+ "ay" -> 16#07;
+ "aymara" -> 16#07;
+ "az" -> 16#08;
+ "azerbaijani" -> 16#08;
+ "ba" -> 16#09;
+ "bashkir" -> 16#09;
+ "be" -> 16#0a;
+ "byelorussian" -> 16#0a;
+ "bg" -> 16#0b;
+ "bulgarian" -> 16#0b;
+ "bh" -> 16#0c;
+ "bihari" -> 16#0c;
+ "bi" -> 16#0d;
+ "bislama" -> 16#0d;
+ "bn" -> 16#0e;
+ "bangla" -> 16#0e;
+ "bengali" -> 16#0e;
+ "bo" -> 16#0f;
+ "tibetan" -> 16#0f;
+ "br" -> 16#10;
+ "breton" -> 16#10;
+ "ca" -> 16#11;
+ "catalan" -> 16#11;
+ "co" -> 16#12;
+ "corsican" -> 16#12;
+ "cs" -> 16#13;
+ "czech" -> 16#13;
+ "cy" -> 16#14;
+ "welsh" -> 16#14;
+ "da" -> 16#15;
+ "danish" -> 16#15;
+ "de" -> 16#16;
+ "german" -> 16#16;
+ "dz" -> 16#17;
+ "bhutani" -> 16#17;
+ "el" -> 16#18;
+ "greek" -> 16#18;
+ "en" -> 16#19;
+ "english" -> 16#19;
+ "eo" -> 16#1a;
+ "esperanto" -> 16#1a;
+ "es" -> 16#1b;
+ "spanish" -> 16#1b;
+ "et" -> 16#1c;
+ "estonian" -> 16#1c;
+ "eu" -> 16#1d;
+ "basque" -> 16#1d;
+ "fa" -> 16#1e;
+ "persian" -> 16#1e;
+ "fi" -> 16#1f;
+ "finnish" -> 16#1f;
+ "fj" -> 16#20;
+ "fiji" -> 16#20;
+ "fo" -> 16#82;
+ "faeroese" -> 16#82;
+ "fr" -> 16#22;
+ "french" -> 16#22;
+ "fy" -> 16#83;
+ "frisian" -> 16#83;
+ "ga" -> 16#24;
+ "irish" -> 16#24;
+ "gd" -> 16#25;
+ "scots-gaelic" -> 16#25;
+ "gl" -> 16#26;
+ "galician" -> 16#26;
+ "gn" -> 16#27;
+ "guarani" -> 16#27;
+ "gu" -> 16#28;
+ "gujarati" -> 16#28;
+ "ha" -> 16#29;
+ "hausa" -> 16#29;
+ "he" -> 16#2a;
+ "hebrew" -> 16#2a;
+ "hi" -> 16#2b;
+ "hindi" -> 16#2b;
+ "hr" -> 16#2c;
+ "croatian" -> 16#2c;
+ "hu" -> 16#2d;
+ "hungarian" -> 16#2d;
+ "hy" -> 16#2e;
+ "armenian" -> 16#2e;
+ "ia" -> 16#84;
+ "interlingua" -> 16#84;
+ "id" -> 16#30;
+ "indonesian" -> 16#30;
+ "ie" -> 16#86;
+ "interlingue" -> 16#86;
+ "ik" -> 16#87;
+ "inupiak" -> 16#87;
+ "is" -> 16#33;
+ "icelandic" -> 16#33;
+ "it" -> 16#34;
+ "italian" -> 16#34;
+ "iu" -> 16#89;
+ "inuktitut" -> 16#89;
+ "ja" -> 16#36;
+ "japanese" -> 16#36;
+ "jw" -> 16#37;
+ "javanese" -> 16#37;
+ "ka" -> 16#38;
+ "georgian" -> 16#38;
+ "kk" -> 16#39;
+ "kazakh" -> 16#39;
+ "kl" -> 16#8a;
+ "greenlandic" -> 16#8a;
+ "km" -> 16#3b;
+ "cambodian" -> 16#3b;
+ "kn" -> 16#3c;
+ "kannada" -> 16#3c;
+ "ko" -> 16#3d;
+ "korean" -> 16#3d;
+ "ks" -> 16#3e;
+ "kashmiri" -> 16#3e;
+ "ku" -> 16#3f;
+ "kurdish" -> 16#3f;
+ "ky" -> 16#40;
+ "kirghiz" -> 16#40;
+ "la" -> 16#8b;
+ "latin" -> 16#8b;
+ "ln" -> 16#42;
+ "lingala" -> 16#42;
+ "lo" -> 16#43;
+ "laothian" -> 16#43;
+ "lt" -> 16#44;
+ "lithuanian" -> 16#44;
+ "lv" -> 16#45;
+ "lettish" -> 16#45;
+ "latvian" -> 16#45;
+ "mg" -> 16#46;
+ "malagese" -> 16#46;
+ "mi" -> 16#47;
+ "maori" -> 16#47;
+ "mk" -> 16#48;
+ "macedonian" -> 16#48;
+ "ml" -> 16#49;
+ "malayalam" -> 16#49;
+ "mn" -> 16#4a;
+ "mongolian" -> 16#4a;
+ "mo" -> 16#4b;
+ "moldavian" -> 16#4b;
+ "mr" -> 16#4c;
+ "marathi" -> 16#4c;
+ "ms" -> 16#4d;
+ "malay" -> 16#4d;
+ "mt" -> 16#4e;
+ "maltese" -> 16#4e;
+ "my" -> 16#4f;
+ "burmese" -> 16#4f;
+ "na" -> 16#81;
+ "nauru" -> 16#81;
+ "ne" -> 16#51;
+ "nepali" -> 16#51;
+ "nl" -> 16#52;
+ "dutch" -> 16#52;
+ "no" -> 16#53;
+ "norwegian" -> 16#53;
+ "oc" -> 16#54;
+ "occitan" -> 16#54;
+ "om" -> 16#55;
+ "oromo" -> 16#55;
+ "or" -> 16#56;
+ "oriya" -> 16#56;
+ "pa" -> 16#57;
+ "punjabi" -> 16#57;
+ "po" -> 16#58;
+ "polish" -> 16#58;
+ "ps" -> 16#59;
+ "pushto" -> 16#59;
+ "pt" -> 16#5a;
+ "portugese" -> 16#5a;
+ "qu" -> 16#5b;
+ "quechua" -> 16#5b;
+ "rm" -> 16#8c;
+ "rhaeto-romance" -> 16#8c;
+ "rn" -> 16#5d;
+ "kirundi" -> 16#5d;
+ "ro" -> 16#5e;
+ "romanian" -> 16#5e;
+ "ru" -> 16#5f;
+ "russian" -> 16#5f;
+ "rw" -> 16#60;
+ "kinyarwanda" -> 16#60;
+ "sa" -> 16#61;
+ "sanskrit" -> 16#61;
+ "sd" -> 16#62;
+ "sindhi" -> 16#62;
+ "sg" -> 16#63;
+ "sangho" -> 16#63;
+ "sh" -> 16#64;
+ "serbo-croatian" -> 16#64;
+ "si" -> 16#65;
+ "sinhalese" -> 16#65;
+ "sk" -> 16#66;
+ "slovak" -> 16#66;
+ "sl" -> 16#67;
+ "slovenian" -> 16#67;
+ "sm" -> 16#68;
+ "samoan" -> 16#68;
+ "sn" -> 16#69;
+ "shona" -> 16#69;
+ "so" -> 16#6a;
+ "somali" -> 16#6a;
+ "sq" -> 16#6b;
+ "albanian" -> 16#6b;
+ "sr" -> 16#6c;
+ "serbian" -> 16#6c;
+ "ss" -> 16#6d;
+ "siswati" -> 16#6d;
+ "st" -> 16#6e;
+ "seshoto" -> 16#6e;
+ "su" -> 16#6f;
+ "sundanese" -> 16#6f;
+ "sv" -> 16#70;
+ "swedish" -> 16#70;
+ "sw" -> 16#71;
+ "swahili" -> 16#71;
+ "ta" -> 16#72;
+ "tamil" -> 16#72;
+ "te" -> 16#73;
+ "telugu" -> 16#73;
+ "tg" -> 16#74;
+ "tajik" -> 16#74;
+ "th" -> 16#75;
+ "thai" -> 16#75;
+ "ti" -> 16#76;
+ "tigrinya" -> 16#76;
+ "tk" -> 16#77;
+ "turkmen" -> 16#77;
+ "tl" -> 16#78;
+ "tagalog" -> 16#78;
+ "tn" -> 16#79;
+ "setswana" -> 16#79;
+ "to" -> 16#7a;
+ "tonga" -> 16#7a;
+ "tr" -> 16#7b;
+ "turkish" -> 16#7b;
+ "ts" -> 16#7c;
+ "tsonga" -> 16#7c;
+ "tt" -> 16#7d;
+ "tatar" -> 16#7d;
+ "tw" -> 16#7e;
+ "twi" -> 16#7e;
+ "ug" -> 16#7f;
+ "uighur" -> 16#7f;
+ "uk" -> 16#50;
+ "ukrainian" -> 16#50;
+ "ur" -> 16#21;
+ "urdu" -> 16#21;
+ "uz" -> 16#23;
+ "uzbek" -> 16#23;
+ "vi" -> 16#2f;
+ "vietnamese" -> 16#2f;
+ "vo" -> 16#85;
+ "volapuk" -> 16#85;
+ "wo" -> 16#31;
+ "wolof" -> 16#31;
+ "xh" -> 16#32;
+ "xhosa" -> 16#32;
+ "yi" -> 16#88;
+ "yiddish" -> 16#88;
+ "yo" -> 16#35;
+ "yoruba" -> 16#35;
+ "za" -> 16#3a;
+ "zhuang" -> 16#3a;
+ "zh" -> 16#41;
+ "chinese" -> 16#41;
+ "zu" -> 16#5c;
+ "zulu" -> 16#5c
+ end.
+
+
+%% Push Application ID Assignments
+%%
+%% Assingment are found at http://www.wapforum.org/wina/push-app-id.htm
+%%
+decode_push_application({short,Data}) ->
+ decode_push_application(d_long(Data));
+
+decode_push_application(Code) when integer(Code) ->
+ case Code of
+ 16#00 -> "x-wap-application:*";
+ 16#01 -> "x-wap-application:push.sia";
+ 16#02 -> "x-wap-application:wml.ua";
+ 16#03 -> "x-wap-application:wta.ua";
+ 16#04 -> "x-wap-application:mms.ua";
+ 16#05 -> "x-wap-application:push.syncml";
+ 16#06 -> "x-wap-application:loc.ua";
+ 16#07 -> "x-wap-application:syncml.dm";
+ 16#08 -> "x-wap-application:drm.ua";
+ 16#09 -> "x-wap-application:emn.ua";
+ 16#0A -> "x-wap-application:wv.ua";
+ 16#8000 -> "x-wap-microsoft:localcontent.ua";
+ 16#8001 -> "x-wap-microsoft:IMclient.ua";
+ 16#8002 -> "x-wap-docomo:imode.mail.ua";
+ 16#8003 -> "x-wap-docomo:imode.mr.ua";
+ 16#8004 -> "x-wap-docomo:imode.mf.ua";
+ 16#8005 -> "x-motorola:location.ua";
+ 16#8006 -> "x-motorola:now.ua";
+ 16#8007 -> "x-motorola:otaprov.ua";
+ 16#8008 -> "x-motorola:browser.ua";
+ 16#8009 -> "x-motorola:splash.ua";
+ 16#800B -> "x-wap-nai:mvsw.command";
+ 16#8010 -> "x-wap-openwave:iota.ua"
+ end;
+decode_push_application(App) when list(App) ->
+ App.
+
+
+
+encode_push_application(App) ->
+ case App of
+ "x-wap-application:*" -> ?ENCODE_SHORT(16#00);
+ "x-wap-application:push.sia" -> ?ENCODE_SHORT(16#01);
+ "x-wap-application:wml.ua" -> ?ENCODE_SHORT(16#02);
+ "x-wap-application:wta.ua" -> ?ENCODE_SHORT(16#03);
+ "x-wap-application:mms.ua" -> ?ENCODE_SHORT(16#04);
+ "x-wap-application:push.syncml" -> ?ENCODE_SHORT(16#05);
+ "x-wap-application:loc.ua" -> ?ENCODE_SHORT(16#06);
+ "x-wap-application:syncml.dm" -> ?ENCODE_SHORT(16#07);
+ "x-wap-application:drm.ua" -> ?ENCODE_SHORT(16#08);
+ "x-wap-application:emn.ua" -> ?ENCODE_SHORT(16#09);
+ "x-wap-application:wv.ua" -> ?ENCODE_SHORT(16#0A);
+ "x-wap-microsoft:localcontent.ua" -> encode_integer(16#8000);
+ "x-wap-microsoft:IMclient.ua" -> encode_integer(16#8001);
+ "x-wap-docomo:imode.mail.ua" -> encode_integer(16#8002);
+ "x-wap-docomo:imode.mr.ua" -> encode_integer(16#8003);
+ "x-wap-docomo:imode.mf.ua" -> encode_integer(16#8004);
+ "x-motorola:location.ua" -> encode_integer(16#8005);
+ "x-motorola:now.ua" -> encode_integer(16#8006);
+ "x-motorola:otaprov.ua" -> encode_integer(16#8007);
+ "x-motorola:browser.ua" -> encode_integer(16#8008);
+ "x-motorola:splash.ua" -> encode_integer(16#8009);
+ "x-wap-nai:mvsw.command" -> encode_integer(16#800B);
+ "x-wap-openwave:iota.ua" -> encode_integer(16#8010);
+ _ -> encode_uri_value(App)
+ end.
+
+
+
+
+%% WSP 8.5 Multipart handling
+
+encode_multipart(Entries) ->
+ encode_multipart(Entries, ?WSP_DEFAULT_VERSION).
+
+encode_multipart([], _Version) ->
+ <<>>;
+encode_multipart(Entries, Version) ->
+ EncEntries = encode_multipart_entries(Entries, Version),
+ <<(e_uintvar(length(Entries)))/binary, EncEntries/binary >>.
+
+encode_multipart_entries(Entries, Version) ->
+ encode_multipart_entries(Entries, Version, []).
+
+encode_multipart_entries([], _Version, Acc) ->
+ list_to_binary(lists:reverse(Acc));
+encode_multipart_entries([Entry|T], Version, Acc) ->
+ EncEntry = encode_multipart_entry(Entry, Version),
+ encode_multipart_entries(T, Version, [EncEntry | Acc]).
+
+encode_multipart_entry(Entry, Version) ->
+ #wsp_multipart_entry { content_type = ContentType,
+ headers = Headers,
+ data = Data } = Entry,
+ EncContentType = encode_content_type(ContentType,Version),
+ EncHeaders = encode_headers(Headers, Version),
+ EncHeadersLength = e_uintvar(size(EncContentType)+size(EncHeaders)),
+ DataLen = e_uintvar(size(Data)),
+ <<EncHeadersLength/binary,
+ DataLen/binary,
+ EncContentType/binary,
+ EncHeaders/binary,
+ Data/binary>>.
+
+
+decode_multipart(Data) ->
+ decode_multipart(Data, ?WSP_DEFAULT_VERSION).
+
+decode_multipart(<<>>, _Version) ->
+ {[], <<>>};
+decode_multipart(Data, Version) ->
+ {Entries, Data1} = d_uintvar(Data),
+ decode_multipart_entries(Entries, Data1, Version).
+
+decode_multipart_entries(Entries, Data, Version) ->
+ decode_multipart_entries(Entries, Data, Version, []).
+
+decode_multipart_entries(0, Data, _Version, Acc) ->
+ {lists:reverse(Acc), Data};
+decode_multipart_entries(Entries, Data, Version, Acc) ->
+ {MultiPartEntry, Data1} = decode_multipart_entry(Data,Version),
+ decode_multipart_entries(Entries-1, Data1, Version, [MultiPartEntry|Acc]).
+
+decode_multipart_entry(Data, Version) ->
+ {HeadersLen, Data1} = d_uintvar(Data),
+ {DataLen, Data2} = d_uintvar(Data1),
+ {FieldData,Data3} = scan_header_data(Data2),
+ ContentType = decode_content_type(FieldData, Version),
+ BinHeadersLen = (HeadersLen-(size(Data2)-size(Data3))),
+ <<BinHeaders:BinHeadersLen/binary,Data4/binary>> = Data3,
+ Headers = decode_headers(BinHeaders, Version),
+ <<ValueData:DataLen/binary, Data5/binary>> = Data4,
+ {#wsp_multipart_entry{content_type=ContentType,
+ headers=Headers,
+ data=ValueData},Data5}.
+
+
+parse_credentials(Field, Value) ->
+ %% FIXME
+ ?WH(Field, Value, []).
+
+format_credentials("basic", [User,Password]) ->
+ ["Basic ", base64:encode(User++":"++Password)];
+format_credentials(Scheme, Params) ->
+ [Scheme, format_params(Params)].
+
+encode_credentials("basic", [User,Password], _Version) ->
+ e_value(?ENCODE_SHORT(0),
+ encode_text_string(User),
+ encode_text_string(Password));
+encode_credentials(Scheme, Params, Version) ->
+ e_value(encode_text_string(Scheme), encode_params(Params, Version)).
+
+decode_credentials(Field, Data, Version) ->
+ case scan_header_data(Data) of
+ {0, Data0} ->
+ {User,Data1} = d_text_string(Data0),
+ {Password,_Data2} = d_text_string(Data1),
+ ?WH(Field, "basic", [User,Password]);
+ {Scheme, Data0} when list(Scheme) ->
+ Params = decode_params(Data0, Version),
+ ?WH(Field, Scheme, Params)
+ end.
+
+%%
+%% Challenge: Basic Realm-value | Auth-Scheme Realm *Auth-Params
+%%
+
+parse_challenge(Field, Value) ->
+ %% FIXME
+ ?WH(Field, Value, []).
+
+format_challenge({"basic",Realm}, []) ->
+ ["Basic ", Realm];
+format_challenge({Scheme,Realm}, Params) ->
+ [Scheme," ",Realm, format_params(Params)].
+
+encode_challenge({"basic",Realm}, [], _Version) ->
+ e_value(?ENCODE_SHORT(0),
+ encode_text_string(Realm));
+encode_challenge({Scheme,Realm}, Params, Version) ->
+ e_value(encode_text_string(Scheme),
+ encode_text_string(Realm),
+ encode_params(Params, Version)).
+
+decode_challenge(Field, Data, Version) ->
+ case scan_header_data(Data) of
+ {0, Data0} ->
+ {Realm,_} = d_text_string(Data0),
+ ?WH(Field, {"basic", Realm}, []);
+ {Scheme, Data0} when list(Scheme) ->
+ {Realm,_} = d_text_string(Data0),
+ Params = decode_params(Data0, Version),
+ ?WH(Field, {Scheme,Realm}, Params)
+ end.
+
+
+parse_well_known_method(Value) ->
+ case Value of
+ "GET" -> 'GET';
+ "OPTIONS" -> 'OPTIONS';
+ "HEAD" -> 'HEAD';
+ "DELETE" -> 'DELETE';
+ "TRACE" -> 'TRACE';
+ "POST" -> 'POST';
+ "PUT" -> 'PUT'
+ end.
+
+encode_well_known_method(Value, _Version) ->
+ case Value of
+ 'GET' -> ?ENCODE_SHORT(16#40);
+ 'OPTIONS' -> ?ENCODE_SHORT(16#41);
+ 'HEAD' -> ?ENCODE_SHORT(16#42);
+ 'DELETE' -> ?ENCODE_SHORT(16#43);
+ 'TRACE' -> ?ENCODE_SHORT(16#44);
+ 'POST' -> ?ENCODE_SHORT(16#60);
+ 'PUT' -> ?ENCODE_SHORT(16#61)
+ end.
+
+decode_well_known_method(Value, _Version) ->
+ case Value of
+ 16#40 -> 'GET';
+ 16#41 -> 'OPTIONS';
+ 16#42 -> 'HEAD';
+ 16#43 -> 'DELETE';
+ 16#44 -> 'TRACE';
+ 16#60 -> 'POST';
+ 16#61 -> 'PUT'
+ end.
+
+
+
+%%
+%% WSP Table 36. Status Code Assignments
+%%
+
+encode_status_code(Status) ->
+ case Status of
+ 100 -> 16#10; %% 'Continue'
+ 101 -> 16#11; %% 'Switching Protocols'
+ 200 -> 16#20; %% 'OK, Success'
+ 201 -> 16#21; %% 'Created'
+ 202 -> 16#22; %% 'Accepted'
+ 203 -> 16#23; %% 'Non-Authoritative Information'
+ 204 -> 16#24; %% 'No Content'
+ 205 -> 16#25; %% 'Reset Content'
+ 206 -> 16#26; %% 'Partial Content'
+ 300 -> 16#30; %% 'Multiple Choices'
+ 301 -> 16#31; %% 'Moved Permanently'
+ 302 -> 16#32; %% 'Moved temporarily'
+ 303 -> 16#33; %% 'See Other'
+ 304 -> 16#34; %% 'Not modified'
+ 305 -> 16#35; %% 'Use Proxy'
+ 306 -> 16#36; %% '(reserved)'
+ 307 -> 16#37; %% 'Temporary Redirect'
+ 400 -> 16#40; %% 'Bad Request - server could not understand request'
+ 401 -> 16#41; %% 'Unauthorized'
+ 402 -> 16#42; %% 'Payment required'
+ 403 -> 16#43; %% 'Forbidden operation is understood but refused'
+ 404 -> 16#44; %% 'Not Found'
+ 405 -> 16#45; %% 'Method not allowed'
+ 406 -> 16#46; %% 'Not Acceptable'
+ 407 -> 16#47; %% 'Proxy Authentication required'
+ 408 -> 16#48; %% 'Request Timeout'
+ 409 -> 16#49; %% 'Conflict'
+ 410 -> 16#4A; %% 'Gone'
+ 411 -> 16#4B; %% 'Length Required'
+ 412 -> 16#4C; %% 'Precondition failed'
+ 413 -> 16#4D; %% 'Request entity too large'
+ 414 -> 16#4E; %% 'Request-URI too large'
+ 415 -> 16#4F; %% 'Unsupported media type'
+ 416 -> 16#50; %% 'Requested Range Not Satisfiable'
+ 417 -> 16#51; %% 'Expectation Failed'
+ 500 -> 16#60; %% 'Internal Server Error'
+ 501 -> 16#61; %% 'Not Implemented'
+ 502 -> 16#62; %% 'Bad Gateway'
+ 503 -> 16#63; %% 'Service Unavailable'
+ 504 -> 16#64; %% 'Gateway Timeout'
+ 505 -> 16#65 %% 'HTTP version not supported'
+ end.
+
+
+decode_status_code(StatusCode) ->
+ case StatusCode of
+ 16#10 -> 100; %% 'Continue'
+ 16#11 -> 101; %% 'Switching Protocols'
+ 16#20 -> 200; %% 'OK, Success'
+ 16#21 -> 201; %% 'Created'
+ 16#22 -> 202; %% 'Accepted'
+ 16#23 -> 203; %% 'Non-Authoritative Information'
+ 16#24 -> 204; %% 'No Content'
+ 16#25 -> 205; %% 'Reset Content'
+ 16#26 -> 206; %% 'Partial Content'
+ 16#30 -> 300; %% 'Multiple Choices'
+ 16#31 -> 301; %% 'Moved Permanently'
+ 16#32 -> 302; %% 'Moved temporarily'
+ 16#33 -> 303; %% 'See Other'
+ 16#34 -> 304; %% 'Not modified'
+ 16#35 -> 305; %% 'Use Proxy'
+ 16#36 -> 306; %% '(reserved)'
+ 16#37 -> 307; %% 'Temporary Redirect'
+ 16#40 -> 400; %% 'Bad Request - server could not understand request'
+ 16#41 -> 401; %% 'Unauthorized'
+ 16#42 -> 402; %% 'Payment required'
+ 16#43 -> 403; %% 'Forbidden operation is understood but refused'
+ 16#44 -> 404; %% 'Not Found'
+ 16#45 -> 405; %% 'Method not allowed'
+ 16#46 -> 406; %% 'Not Acceptable'
+ 16#47 -> 407; %% 'Proxy Authentication required'
+ 16#48 -> 408; %% 'Request Timeout'
+ 16#49 -> 409; %% 'Conflict'
+ 16#4A -> 410; %% 'Gone'
+ 16#4B -> 411; %% 'Length Required'
+ 16#4C -> 412; %% 'Precondition failed'
+ 16#4D -> 413; %% 'Request entity too large'
+ 16#4E -> 414; %% 'Request-URI too large'
+ 16#4F -> 415; %% 'Unsupported media type'
+ 16#50 -> 416; %% 'Requested Range Not Satisfiable'
+ 16#51 -> 417; %% 'Expectation Failed'
+ 16#60 -> 500; %% 'Internal Server Error'
+ 16#61 -> 501; %% 'Not Implemented'
+ 16#62 -> 502; %% 'Bad Gateway'
+ 16#63 -> 503; %% 'Service Unavailable'
+ 16#64 -> 504; %% 'Gateway Timeout'
+ 16#65 -> 505 %% 'HTTP version not supported'
+ end.
+
+
+%%
+%% Content Type Assignments
+%%
+%% Assingment are found at http://www.wapforum.org/wina/wsp-content-type.htm
+%%
+%%
+%% string(Version, ContentType) -> Code
+%%
+encode_well_known_media(ContentType, Version) ->
+ case ContentType of
+ %% WSP_REGISTERED_CONTENT_TYPES
+ "application/vnd.uplanet.cacheop-wbxml" ->
+ encode_integer(16#0201);
+ "application/vnd.uplanet.signal" ->
+ encode_integer(16#0202);
+ "application/vnd.uplanet.alert-wbxml" ->
+ encode_integer(16#0203);
+ "application/vnd.uplanet.list-wbxml" ->
+ encode_integer(16#0204);
+ "application/vnd.uplanet.listcmd-wbxml" ->
+ encode_integer(16#0205);
+ "application/vnd.uplanet.channel-wbxml" ->
+ encode_integer(16#0206);
+ "application/vnd.uplanet.provisioning-status-uri" ->
+ encode_integer(16#0207);
+ "x-wap.multipart/vnd.uplanet.header-set" ->
+ encode_integer(16#0208);
+ "application/vnd.uplanet.bearer-choice-wbxml" ->
+ encode_integer(16#0209);
+ "application/vnd.phonecom.mmc-wbxml" ->
+ encode_integer(16#020A);
+ "application/vnd.nokia.syncset+wbxml" ->
+ encode_integer(16#020B);
+ "image/x-up-wpng" ->
+ encode_integer(16#020C);
+ _ ->
+ encode_constrained_media(ContentType, Version)
+ end.
+
+
+encode_constrained_media(ContentType, Version) ->
+ case ContentType of
+ "*/*" -> ?ENCODE_SHORT(16#00);
+ "text/*" -> ?ENCODE_SHORT(16#01);
+ "text/html" -> ?ENCODE_SHORT(16#02);
+ "text/plain" -> ?ENCODE_SHORT(16#03);
+ "text/x-hdml" -> ?ENCODE_SHORT(16#04);
+ "text/x-ttml" -> ?ENCODE_SHORT(16#05);
+ "text/x-vcalendar" -> ?ENCODE_SHORT(16#06);
+ "text/x-vcard" -> ?ENCODE_SHORT(16#07);
+ "text/vnd.wap.wml" -> ?ENCODE_SHORT(16#08);
+ "text/vnd.wap.wmlscript" -> ?ENCODE_SHORT(16#09);
+ "text/vnd.wap.wta-event" -> ?ENCODE_SHORT(16#0A);
+ "multipart/*" -> ?ENCODE_SHORT(16#0B);
+ "multipart/mixed" -> ?ENCODE_SHORT(16#0C);
+ "multipart/form-data" -> ?ENCODE_SHORT(16#0D);
+ "multipart/byterantes" -> ?ENCODE_SHORT(16#0E);
+ "multipart/alternative" -> ?ENCODE_SHORT(16#0F);
+ "application/*" -> ?ENCODE_SHORT(16#10);
+ "application/java-vm" -> ?ENCODE_SHORT(16#11);
+ "application/x-www-form-urlencoded" -> ?ENCODE_SHORT(16#12);
+ "application/x-hdmlc" -> ?ENCODE_SHORT(16#13);
+ "application/vnd.wap.wmlc" -> ?ENCODE_SHORT(16#14);
+ "application/vnd.wap.wmlscriptc" -> ?ENCODE_SHORT(16#15);
+ "application/vnd.wap.wta-eventc" -> ?ENCODE_SHORT(16#16);
+ "application/vnd.wap.uaprof" -> ?ENCODE_SHORT(16#17);
+ "application/vnd.wap.wtls-ca-certificate" -> ?ENCODE_SHORT(16#18);
+ "application/vnd.wap.wtls-user-certificate" -> ?ENCODE_SHORT(16#19);
+ "application/x-x509-ca-cert" -> ?ENCODE_SHORT(16#1A);
+ "application/x-x509-user-cert" -> ?ENCODE_SHORT(16#1B);
+ "image/*" -> ?ENCODE_SHORT(16#1C);
+ "image/gif" -> ?ENCODE_SHORT(16#1D);
+ "image/jpeg" -> ?ENCODE_SHORT(16#1E);
+ "image/tiff" -> ?ENCODE_SHORT(16#1F);
+ "image/png" -> ?ENCODE_SHORT(16#20);
+ "image/vnd.wap.wbmp" -> ?ENCODE_SHORT(16#21);
+ "application/vnd.wap.multipart.*" -> ?ENCODE_SHORT(16#22);
+ "application/vnd.wap.multipart.mixed" -> ?ENCODE_SHORT(16#23);
+ "application/vnd.wap.multipart.form-data" -> ?ENCODE_SHORT(16#24);
+ "application/vnd.wap.multipart.byteranges" -> ?ENCODE_SHORT(16#25);
+ "application/vnd.wap.multipart.alternative" -> ?ENCODE_SHORT(16#26);
+ "application/xml" -> ?ENCODE_SHORT(16#27);
+ "text/xml" -> ?ENCODE_SHORT(16#28);
+ "application/vnd.wap.wbxml" -> ?ENCODE_SHORT(16#29);
+ "application/x-x968-cross-cert" -> ?ENCODE_SHORT(16#2A);
+ "application/x-x968-ca-cert" -> ?ENCODE_SHORT(16#2B);
+ "application/x-x968-user-cert" -> ?ENCODE_SHORT(16#2C);
+
+ %% WAP Version 1.2
+ "text/vnd.wap.si" when Version >= ?WSP_12 ->
+ ?ENCODE_SHORT(16#2D);
+ "application/vnd.wap.sic" when Version >= ?WSP_12 ->
+ ?ENCODE_SHORT(16#2E);
+ "text/vnd.wap.sl" when Version >= ?WSP_12 ->
+ ?ENCODE_SHORT(16#2F);
+ "application/vnd.wap.slc" when Version >= ?WSP_12 ->
+ ?ENCODE_SHORT(16#30);
+ "text/vnd.wap.co" when Version >= ?WSP_12 ->
+ ?ENCODE_SHORT(16#31);
+ "application/vnd.wap.coc" when Version >= ?WSP_12 ->
+ ?ENCODE_SHORT(16#32);
+ "application/vnd.wap.multipart.related" when Version >= ?WSP_12 ->
+ ?ENCODE_SHORT(16#33);
+ "application/vnd.wap.sia" when Version >= ?WSP_12 ->
+ ?ENCODE_SHORT(16#34);
+ %% WAP Version 1.3
+ "text/vnd.wap.connectivity-xml" when Version >= ?WSP_13 ->
+ ?ENCODE_SHORT(16#35);
+ "application/vnd.wap.connectivity-wbxml" when Version >= ?WSP_13 ->
+ ?ENCODE_SHORT(16#36);
+ %% WAP Version 1.4
+ "application/pkcs7-mime" when Version >= ?WSP_14 ->
+ ?ENCODE_SHORT(16#37);
+ "application/vnd.wap.hashed-certificate" when Version >= ?WSP_14 ->
+ ?ENCODE_SHORT(16#38);
+ "application/vnd.wap.signed-certificate" when Version >= ?WSP_14 ->
+ ?ENCODE_SHORT(16#39);
+ "application/vnd.wap.cert-response" when Version >= ?WSP_14 ->
+ ?ENCODE_SHORT(16#3A);
+ "application/xhtml+xml" when Version >= ?WSP_14 ->
+ ?ENCODE_SHORT(16#3B);
+ "application/wml+xml" when Version >= ?WSP_14 ->
+ ?ENCODE_SHORT(16#3C);
+ "text/css" when Version >= ?WSP_14 ->
+ ?ENCODE_SHORT(16#3D);
+ "application/vnd.wap.mms-message" when Version >= ?WSP_14 ->
+ ?ENCODE_SHORT(16#3E);
+ "application/vnd.wap.rollover-certificate" when Version >= ?WSP_14 ->
+ ?ENCODE_SHORT(16#3F);
+ %% WAP Version 1.5
+ "application/vnd.wap.locc+wbxml" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#40);
+ "application/vnd.wap.loc+xml" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#41);
+ "application/vnd.syncml.dm+wbxml" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#42);
+ "application/vnd.syncml.dm+xml" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#43);
+ "application/vnd.syncml.notification" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#44);
+ "application/vnd.wap.xhtml+xml" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#45);
+ "application/vnd.wv.csp.cir" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#46);
+ "application/vnd.oma.dd+xml" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#47);
+ "application/vnd.oma.drm.message" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#48);
+ "application/vnd.oma.drm.content" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#49);
+ "application/vnd.oma.drm.rights+xml" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#4A);
+ "application/vnd.oma.drm.rights+wbxml" when Version >= ?WSP_15 ->
+ ?ENCODE_SHORT(16#4B);
+ _ ->
+ encode_text_string(ContentType)
+ end.
+
+
+decode_well_known_media(Code, Version) when integer(Code) ->
+ case Code of
+ %% WSP_REGISTERED_CONTENT_TYPES
+ 16#0201 -> "application/vnd.uplanet.cacheop-wbxml";
+ 16#0202 -> "application/vnd.uplanet.signal";
+ 16#0203 -> "application/vnd.uplanet.alert-wbxml";
+ 16#0204 -> "application/vnd.uplanet.list-wbxml";
+ 16#0205 -> "application/vnd.uplanet.listcmd-wbxml";
+ 16#0206 -> "application/vnd.uplanet.channel-wbxml";
+ 16#0207 -> "application/vnd.uplanet.provisioning-status-uri";
+ 16#0208 -> "x-wap.multipart/vnd.uplanet.header-set";
+ 16#0209 -> "application/vnd.uplanet.bearer-choice-wbxml";
+ 16#020A -> "application/vnd.phonecom.mmc-wbxml";
+ 16#020B -> "application/vnd.nokia.syncset+wbxml";
+ 16#020C -> "image/x-up-wpng";
+ _ -> decode_constrained_media(Code, Version)
+ end;
+decode_well_known_media(Media, _Version) when list(Media) ->
+ Media;
+decode_well_known_media({short,_Data}, Version) ->
+ decode_well_known_media(d_long(data), Version). %% BUG HERE: Data
+
+
+decode_constrained_media(Code, _Version) when integer(Code) ->
+ case Code of
+ 16#00 -> "*/*";
+ 16#01 -> "text/*";
+ 16#02 -> "text/html";
+ 16#03 -> "text/plain";
+ 16#04 -> "text/x-hdml";
+ 16#05 -> "text/x-ttml";
+ 16#06 -> "text/x-vcalendar";
+ 16#07 -> "text/x-vcard";
+ 16#08 -> "text/vnd.wap.wml";
+ 16#09 -> "text/vnd.wap.wmlscript";
+ 16#0A -> "text/vnd.wap.wta-event";
+ 16#0B -> "multipart/*";
+ 16#0C -> "multipart/mixed";
+ 16#0D -> "multipart/form-data";
+ 16#0E -> "multipart/byterantes";
+ 16#0F -> "multipart/alternative";
+ 16#10 -> "application/*";
+ 16#11 -> "application/java-vm";
+ 16#12 -> "application/x-www-form-urlencoded";
+ 16#13 -> "application/x-hdmlc";
+ 16#14 -> "application/vnd.wap.wmlc";
+ 16#15 -> "application/vnd.wap.wmlscriptc";
+ 16#16 -> "application/vnd.wap.wta-eventc";
+ 16#17 -> "application/vnd.wap.uaprof";
+ 16#18 -> "application/vnd.wap.wtls-ca-certificate";
+ 16#19 -> "application/vnd.wap.wtls-user-certificate";
+ 16#1A -> "application/x-x509-ca-cert";
+ 16#1B -> "application/x-x509-user-cert";
+ 16#1C -> "image/*";
+ 16#1D -> "image/gif";
+ 16#1E -> "image/jpeg";
+ 16#1F -> "image/tiff";
+ 16#20 -> "image/png";
+ 16#21 -> "image/vnd.wap.wbmp";
+ 16#22 -> "application/vnd.wap.multipart.*";
+ 16#23 -> "application/vnd.wap.multipart.mixed";
+ 16#24 -> "application/vnd.wap.multipart.form-data";
+ 16#25 -> "application/vnd.wap.multipart.byteranges";
+ 16#26 -> "application/vnd.wap.multipart.alternative";
+ 16#27 -> "application/xml";
+ 16#28 -> "text/xml";
+ 16#29 -> "application/vnd.wap.wbxml";
+ 16#2A -> "application/x-x968-cross-cert";
+ 16#2B -> "application/x-x968-ca-cert";
+ 16#2C -> "application/x-x968-user-cert";
+ %% WAP Version 1.2
+ 16#2D -> "text/vnd.wap.si";
+ 16#2E -> "application/vnd.wap.sic";
+ 16#2F -> "text/vnd.wap.sl";
+ 16#30 -> "application/vnd.wap.slc";
+ 16#31 -> "text/vnd.wap.co";
+ 16#32 -> "application/vnd.wap.coc";
+ 16#33 -> "application/vnd.wap.multipart.related";
+ 16#34 -> "application/vnd.wap.sia";
+ %% WAP Version 1.3
+ 16#35 -> "text/vnd.wap.connectivity-xml";
+ 16#36 -> "application/vnd.wap.connectivity-wbxml";
+ %% WAP Version 1.4
+ 16#37 -> "application/pkcs7-mime";
+ 16#38 -> "application/vnd.wap.hashed-certificate";
+ 16#39 -> "application/vnd.wap.signed-certificate";
+ 16#3A -> "application/vnd.wap.cert-response";
+ 16#3B -> "application/xhtml+xml";
+ 16#3C -> "application/wml+xml";
+ 16#3D -> "text/css";
+ 16#3E -> "application/vnd.wap.mms-message";
+ 16#3F -> "application/vnd.wap.rollover-certificate";
+ %% WAP Version 1.5
+ 16#40 -> "application/vnd.wap.locc+wbxml";
+ 16#41 -> "application/vnd.wap.loc+xml";
+ 16#42 -> "application/vnd.syncml.dm+wbxml";
+ 16#43 -> "application/vnd.syncml.dm+xml";
+ 16#44 -> "application/vnd.syncml.notification";
+ 16#45 -> "application/vnd.wap.xhtml+xml";
+ 16#46 -> "application/vnd.wv.csp.cir";
+ 16#47 -> "application/vnd.oma.dd+xml";
+ 16#48 -> "application/vnd.oma.drm.message";
+ 16#49 -> "application/vnd.oma.drm.content";
+ 16#4A -> "application/vnd.oma.drm.rights+xml";
+ 16#4B -> "application/vnd.oma.drm.rights+wbxml"
+ end;
+decode_constrained_media(Media, _Version) when list(Media) ->
+ Media.
+
+
+%% Parse <integer> or <integer>.<integer>
+
+parse_version(Value) ->
+ case string:tokens(Value, ".") of
+ [Major,Minor] ->
+ {list_to_integer(Major), list_to_integer(Minor)};
+ [Major] ->
+ case catch list_to_integer(Major) of
+ {'EXIT', _} ->
+ Value;
+ V -> V
+ end
+ end.
+
+format_version({Major,Minor}) ->
+ [integer_to_list(Major),".",integer_to_list(Minor)];
+format_version(Major) when integer(Major) ->
+ integer_to_list(Major);
+format_version(Version) when list(Version) ->
+ Version.
+
+encode_version({Major,Minor}) ->
+ Ver = (((Major-1) band 16#7) bsl 4) bor (Minor band 16#f),
+ ?ENCODE_SHORT(Ver);
+encode_version(Major) when integer(Major) ->
+ Ver = ((Major band 16#7) bsl 4) bor 16#f,
+ ?ENCODE_SHORT(Ver);
+encode_version(Value) when list(Value) ->
+ encode_text_string(Value).
+
+
+decode_version(Value) when integer(Value) ->
+ Major = (Value bsr 4) band 16#7,
+ Minor = Value band 16#f,
+ if Minor == 16#f ->
+ Major;
+ true ->
+ {Major+1,Minor}
+ end;
+decode_version(Value) when list(Value) ->
+ Value.
+
+
+encode_mms_version({Major,Minor}) ->
+ Ver = ((Major band 16#7) bsl 4) bor (Minor band 16#f),
+ ?ENCODE_SHORT(Ver);
+encode_mms_version(Major) when integer(Major) ->
+ Ver = ((Major band 16#7) bsl 4) bor 16#f,
+ ?ENCODE_SHORT(Ver);
+encode_mms_version(Value) when list(Value) ->
+ encode_text_string(Value).
+
+
+decode_mms_version(Value) when integer(Value) ->
+ Major = (Value bsr 4) band 16#7,
+ Minor = Value band 16#f,
+ if Minor == 16#f ->
+ Major;
+ true ->
+ {Major,Minor}
+ end;
+decode_mms_version(Value) when list(Value) ->
+ Value.
+
+
+%%%
+%%% Basic data types
+%%%
+
+e_delta_seconds(Value) ->
+ encode_integer(Value).
+
+
+encode_integer(I) when integer(I), I >= 0 , I < 127 ->
+ ?ENCODE_SHORT(I);
+encode_integer(I) when integer(I) ->
+ encode_long_integer(I);
+encode_integer(List) when list(List) ->
+ encode_integer(list_to_integer(List)).
+
+decode_integer(Value) when integer(Value) ->
+ Value;
+decode_integer({short,Data}) ->
+ Sz = size(Data)*8,
+ <<Value:Sz>> = Data,
+ Value.
+
+encode_short_integer(I) ->
+ ?ENCODE_SHORT(I).
+
+encode_long_integer(I) when I >= 0 ->
+ MOInt = encode_multioctet_integer(I, []),
+ MOIntLen = length(MOInt),
+ list_to_binary([MOIntLen band 16#1f | MOInt]).
+
+encode_multioctet_integer(I,Acc) when I < 256 ->
+ [I | Acc];
+encode_multioctet_integer(I,Acc) ->
+ encode_multioctet_integer(I bsr 8, [(I band 16#ff) | Acc]).
+
+
+%% Integer-Value: Short-Integer | Long-Integer
+%% Short-Integer: <<1:Short:7>>
+%% Long-Integer: <<0-30, X:0-30>>
+%% return {Integer,Tail}
+d_integer_value(<<1:1,Integer:7,Tail/binary>>) ->
+ {Integer, Tail};
+d_integer_value(<<0:3,Len:5,Data/binary>>) when Len =/= 31 ->
+ Sz = Len*8,
+ <<Integer:Sz, Tail/binary>> = Data,
+ {Integer, Tail}.
+
+decode_short_integer(<<1:1,Septet:7,T100/binary>>) ->
+ {Septet, T100}.
+
+decode_long_integer(<<0:3,Len:5,Data/binary>>) when Len =/= 31 ->
+ Sz = Len*8,
+ <<Val:Sz, Tail/binary>> = Data,
+ {Val, Tail}.
+
+d_long(Data) ->
+ Sz = size(Data)*8,
+ <<Value:Sz>> = Data,
+ Value.
+
+
+encode_uri_value(Data) ->
+ encode_text_string(Data).
+
+decode_uri_value(Data) when list(Data) ->
+ Data.
+
+%% parse quoted string
+decode_quoted_string([$" | List]) ->
+ List.
+
+encode_quoted_string([$" | Value]) ->
+ case lists:reverse(Value) of
+ [$" | Value1] ->
+ <<$", (list_to_binary(lists:reverse(Value1)))/binary, 0>>;
+ _ ->
+ <<$", (list_to_binary(Value))/binary, 0>>
+ end;
+encode_quoted_string(Value) ->
+ <<$", (list_to_binary(Value))/binary, 0>>.
+
+
+
+decode_text_string(List) when list(List) ->
+ List;
+decode_text_string(Bin) when binary(Bin) ->
+ binary_to_list(Bin).
+
+
+
+encode_text_string(A) when atom(A) ->
+ encode_text_string(atom_to_list(A));
+encode_text_string([H|T]) when H >= 128 ->
+ <<(list_to_binary([127,H|T]))/binary,0>>;
+encode_text_string(S) ->
+ <<(list_to_binary(S))/binary,0>>.
+
+
+encode_text_value(undefined) ->
+ <<0>>;
+encode_text_value([$"|T]) ->
+ %% remove ending quote ?
+ <<34,(list_to_binary(T))/binary>>;
+encode_text_value(L) ->
+ encode_text_string(L).
+
+
+d_text_value(<<0,T100/binary>>) ->
+ { "", T100};
+d_text_value(<<34,_Tail/binary>>=Data) ->
+ d_text_string(Data);
+d_text_value(Data) ->
+ d_text_string(Data).
+
+
+d_text_string(<<127,Data/binary>>) -> %% Remove quote
+ d_text_string(Data,[]);
+d_text_string(Data) ->
+ d_text_string(Data,[]).
+
+d_text_string(<<0,Tail/binary>>,A) ->
+ {lists:reverse(A), Tail};
+d_text_string(<<C,Tail/binary>>,A) ->
+ d_text_string(Tail,[C|A]);
+d_text_string(<<>>, A) ->
+ {lists:reverse(A), <<>>}.
+
+
+d_q_value(<<0:1,Q:7,Tail/binary>>) ->
+ QVal =
+ if Q >= 1, Q =< 100 ->
+ lists:flatten(io_lib:format("0.~2..0w", [Q-1]));
+ Q >= 101, Q =< 1099 ->
+ lists:flatten(io_lib:format("0.~3..0w", [Q-100]));
+ true ->
+ io:format("Q-value to big ~w\n", [Q]),
+ "***"
+ end,
+ {QVal, Tail};
+d_q_value(<<1:1,Q1:7,0:1,Q0:7,Tail/binary>>) ->
+ Q = (Q1 bsl 7) bor Q0,
+ QVal =
+ if Q >= 1, Q =< 100 ->
+ lists:flatten(io_lib:format("0.~2..0w", [Q-1]));
+ Q >= 101, Q =< 1099 ->
+ lists:flatten(io_lib:format("0.~3..0w", [Q-100]));
+ true ->
+ io:format("Q-value to big ~w\n", [Q]),
+ "***"
+ end,
+ {QVal, Tail}.
+
+
+%%
+%% Decode uintvar
+%%
+d_uintvar(<<0:1,S0:7,T100/binary>>) ->
+ {S0, T100};
+d_uintvar(<<1:1,S1:7,0:1,S0:7,T100/binary>>) ->
+ {(S1 bsl 7) bor S0, T100};
+d_uintvar(<<1:1,S2:7,1:1,S1:7,0:1,S0:7,T100/binary>>) ->
+ {(S2 bsl 14) bor (S1 bsl 7) bor S0, T100};
+d_uintvar(<<1:1,S3:7,1:1,S2:7,1:1,S1:7,0:1,S0:7,T100/binary>>) ->
+ {(S3 bsl 21) bor (S2 bsl 14) bor (S1 bsl 7) bor S0, T100};
+d_uintvar(<<1:1,S4:7,1:1,S3:7,1:1,S2:7,1:1,S1:7,0:1,S0:7,T100/binary>>) ->
+ {(S4 bsl 28) bor (S3 bsl 21) bor (S2 bsl 14) bor (S1 bsl 7) bor S0, T100}.
+
+
+e_uintvar(I) when I < 128 -> <<I>>;
+e_uintvar(I) -> e_uintvar(I,[]).
+
+e_uintvar(0,Acc) ->
+ list_to_binary(Acc);
+e_uintvar(I,[]) ->
+ e_uintvar(I bsr 7, [I band 16#7f]);
+e_uintvar(I,Acc) ->
+ e_uintvar(I bsr 7, [16#80 bor (I band 16#7f) | Acc]).
+
+
+e_value(B) ->
+ Sz = size(B),
+ if Sz =< 30 ->
+ <<Sz:8, B/binary>>;
+ true ->
+ <<31:8, (e_uintvar(Sz))/binary, B/binary >>
+ end.
+
+e_value(B1,B2) ->
+ Sz = size(B1)+size(B2),
+ if Sz =< 30 ->
+ <<Sz:8, B1/binary, B2/binary>>;
+ true ->
+ <<31:8, (e_uintvar(Sz))/binary, B1/binary, B2/binary >>
+ end.
+
+e_value(B1,B2,B3) ->
+ Sz = size(B1)+size(B2)+size(B3),
+ if Sz =< 30 ->
+ <<Sz:8, B1/binary,B2/binary,B3/binary>>;
+ true ->
+ <<31:8,(e_uintvar(Sz))/binary,B1/binary,B2/binary,B3/binary>>
+ end.
+
+e_value(B1,B2,B3,B4) ->
+ Sz = size(B1)+size(B2)+size(B3)+size(B4),
+ if Sz =< 30 ->
+ <<Sz:8, B1/binary,B2/binary,B3/binary,B4/binary>>;
+ true ->
+ <<31:8,(e_uintvar(Sz))/binary,B1/binary,
+ B2/binary,B3/binary,B4/binary>>
+ end.
+
+%%
+%% Extened methods
+%%
+decode_extended_methods(<<PduType:8, Data/binary>>) ->
+ Type = decode_pdu_type(PduType),
+ {Method, Data1} = d_text_string(Data),
+ [{Type,Method} | decode_extended_methods(Data1)];
+decode_extended_methods(<<>>) ->
+ [].
+
+encode_extended_methods(Ms) ->
+ list_to_binary(encode_ext_methods(Ms)).
+
+encode_ext_methods([{Type,Method} | T]) ->
+ [ encode_pdu_type(Type), encode_text_string(Method) |
+ encode_ext_methods(T)];
+encode_ext_methods([]) ->
+ [].
+
+%%
+%% Address lists used by redirect-pdu and aliases-capability
+%%
+decode_address(D0) ->
+ [A] = decode_addresses(D0),
+ A.
+
+decode_addresses(D0) ->
+ case D0 of
+ <<1:1, 1:1,Len:6,B:8,P:16,Addr:Len/binary,D1/binary>> ->
+ [#wdp_address { bearer = B, address = Addr, portnum=P } |
+ decode_addresses(D1)];
+ <<1:1, 0:1,Len:6,B:8,Addr:Len/binary,D1/binary>> ->
+ [#wdp_address { bearer = B, address = Addr } |
+ decode_addresses(D1)];
+ <<0:1, 1:1,Len:6,P:16,Addr:Len/binary,D1/binary>> ->
+ [#wdp_address { portnum=P, address=Addr } |
+ decode_addresses(D1)];
+ <<0:1, 0:1,Len:6,Addr:Len/binary,D1/binary>> ->
+ [#wdp_address { address=Addr } |
+ decode_addresses(D1)];
+ <<>> ->
+ []
+ end.
+
+encode_addresses(As) ->
+ encode_addresses(As, []).
+
+encode_addresses([A|As], Acc) ->
+ encode_addresses(As, [encode_address(A)|Acc]);
+encode_addresses([], Acc) ->
+ list_to_binary(lists:reverse(Acc)).
+
+encode_address(#wdp_address { bearer = B, address = Addr, portnum = P }) ->
+ BAddr = if tuple(Addr) ->
+ list_to_binary(inet:ip_to_bytes(Addr));
+ binary(Addr) ->
+ Addr
+ end,
+ Len = size(BAddr),
+ if B == undefined, P == undefined ->
+ <<0:1, 0:1, Len:6, BAddr/binary>>;
+ B == undefined ->
+ <<0:1, 1:1, Len:6, P:16, BAddr/binary>>;
+ P == undefined ->
+ <<1:1, 0:1, Len:6, B:8, BAddr/binary>>;
+ true ->
+ <<1:1, 1:1, Len:6, B:8, P:16, BAddr/binary>>
+ end.
+
+
+
+
+-define(UNIX_TIME_OFFSET, 62167219200).
+
+d_date(Val) when integer(Val) ->
+ calendar:gregorian_seconds_to_datetime(Val+?UNIX_TIME_OFFSET);
+d_date({short,Data}) ->
+ Sz = size(Data)*8,
+ <<Sec:Sz>> = Data,
+ calendar:gregorian_seconds_to_datetime(Sec+?UNIX_TIME_OFFSET).
+
+e_date(DateTime) ->
+ Sec = calendar:datetime_to_gregorian_seconds(DateTime),
+ encode_long_integer(Sec - ?UNIX_TIME_OFFSET).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% decode http-date (RFC 2068). (MUST be send in RFC1123 date format)
+%% HTTP-date = rfc1123-date | rfc850-date | asctime-date
+%% rfc1123-date = wkday "," SP date1 SP time SP "GMT"
+%% rfc850-date = weekday "," SP date2 SP time SP "GMT"
+%% asctime-date = wkday SP date3 SP time SP 4DIGIT
+%%
+%% date1 = 2DIGIT SP month SP 4DIGIT
+%% ; day month year (e.g., 02 Jun 1982)
+%% date2 = 2DIGIT "-" month "-" 2DIGIT
+%% ; day-month-year (e.g., 02-Jun-82)
+%% date3 = month SP ( 2DIGIT | ( SP 1DIGIT ))
+%% ; month day (e.g., Jun 2)
+%%
+%% time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
+%% ; 00:00:00 - 23:59:59
+%%
+%% wkday = "Mon" | "Tue" | "Wed"
+%% | "Thu" | "Fri" | "Sat" | "Sun"
+%%
+%%
+%% weekday = "Monday" | "Tuesday" | "Wednesday"
+%% | "Thursday" | "Friday" | "Saturday" | "Sunday"
+%%
+%% month = "Jan" | "Feb" | "Mar" | "Apr"
+%% | "May" | "Jun" | "Jul" | "Aug"
+%% | "Sep" | "Oct" | "Nov" | "Dec"
+%%
+%% decode date or crash!
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parse_http_date(Date) ->
+ parse_hdate(tolower(Date)).
+
+parse_hdate([$m,$o,$n,$d,$a,$y,$ | Cs]) -> date2(Cs);
+parse_hdate([$t,$u,$e,$s,$d,$a,$y,$ | Cs]) -> date2(Cs);
+parse_hdate([$w,$e,$d,$n,$s,$d,$a,$y,$ | Cs]) -> date2(Cs);
+parse_hdate([$t,$h,$u,$r,$s,$d,$a,$y,$ | Cs]) -> date2(Cs);
+parse_hdate([$f,$r,$i,$d,$a,$y,$ | Cs]) -> date2(Cs);
+parse_hdate([$s,$a,$t,$u,$r,$d,$a,$y,$ | Cs]) -> date2(Cs);
+parse_hdate([$s,$u,$n,$d,$a,$y,$ | Cs]) -> date2(Cs);
+parse_hdate([$m,$o,$n,X | Cs]) -> date13(X,Cs);
+parse_hdate([$t,$u,$e,X | Cs]) -> date13(X,Cs);
+parse_hdate([$w,$e,$d,X | Cs]) -> date13(X,Cs);
+parse_hdate([$t,$h,$u,X | Cs]) -> date13(X,Cs);
+parse_hdate([$f,$r,$i,X | Cs]) -> date13(X,Cs);
+parse_hdate([$s,$a,$t,X | Cs]) -> date13(X,Cs);
+parse_hdate([$s,$u,$n,X | Cs]) -> date13(X,Cs).
+
+date13($ , Cs) -> date3(Cs);
+date13($,, [$ |Cs]) -> date1(Cs).
+
+%% date1
+date1([D1,D2,$ ,M1,M2,M3,$ ,Y1,Y2,Y3,Y4,$ | Cs]) ->
+ M = parse_month([M1,M2,M3]),
+ D = list_to_integer([D1,D2]),
+ Y = list_to_integer([Y1,Y2,Y3,Y4]),
+ {Time,[$ ,$g,$m,$t|Cs1]} = parse_time(Cs),
+ { {{Y,M,D},Time}, Cs1}.
+
+%% date2
+date2([D1,D2,$-,M1,M2,M3,$-,Y1,Y2 | Cs]) ->
+ M = parse_month([M1,M2,M3]),
+ D = list_to_integer([D1,D2]),
+ Y = 1900 + list_to_integer([Y1,Y2]),
+ {Time, [$ ,$g,$m,$t|Cs1]} = parse_time(Cs),
+ {{{Y,M,D}, Time}, Cs1}.
+
+%% date3
+date3([M1,M2,M3,$ ,D1,D2,$ | Cs]) ->
+ M = parse_month([M1,M2,M3]),
+ D = if D1 == $ -> list_to_integer([D2]);
+ true -> list_to_integer([D1,D2])
+ end,
+ {Time,[$ ,Y1,Y2,Y3,Y4|Cs1]} = parse_time(Cs),
+ Y = list_to_integer([Y1,Y2,Y3,Y4]),
+ { {{Y,M,D}, Time}, Cs1 }.
+
+%% decode lowercase month
+parse_month("jan") -> 1;
+parse_month("feb") -> 2;
+parse_month("mar") -> 3;
+parse_month("apr") -> 4;
+parse_month("may") -> 5;
+parse_month("jun") -> 6;
+parse_month("jul") -> 7;
+parse_month("aug") -> 8;
+parse_month("sep") -> 9;
+parse_month("oct") -> 10;
+parse_month("nov") -> 11;
+parse_month("dec") -> 12.
+
+%% decode time HH:MM:SS
+parse_time([H1,H2,$:,M1,M2,$:,S1,S2|Cs]) ->
+ { {list_to_integer([H1,H2]),
+ list_to_integer([M1,M2]),
+ list_to_integer([S1,S2]) }, Cs}.
+
+%% encode date into rfc1123-date (must be a GMT time!!!)
+fmt_date({{Y,M,D},{TH,TM,TS}}) ->
+ WkDay = case calendar:day_of_the_week({Y,M,D}) of
+ 1 -> "Mon";
+ 2 -> "Tue";
+ 3 -> "Wed";
+ 4 -> "Thu";
+ 5 -> "Fri";
+ 6 -> "Sat";
+ 7 -> "Sun"
+ end,
+ lists:flatten(io_lib:format("~s, ~2..0w ~s ~4..0w "
+ "~2..0w:~2..0w:~2..0w GMT",
+ [WkDay, D, fmt_month(M), Y, TH, TM, TS])).
+
+fmt_current_date() ->
+ fmt_date(calendar:universal_time()).
+
+%% decode lowercase month
+fmt_month(1) -> "Jan";
+fmt_month(2) -> "Feb";
+fmt_month(3) -> "Mar";
+fmt_month(4) -> "Apr";
+fmt_month(5) -> "May";
+fmt_month(6) -> "Jun";
+fmt_month(7) -> "Jul";
+fmt_month(8) -> "Aug";
+fmt_month(9) -> "Sep";
+fmt_month(10) -> "Oct";
+fmt_month(11) -> "Nov";
+fmt_month(12) -> "Dec".
diff --git a/lib/dialyzer/test/user_tests_SUITE.erl b/lib/dialyzer/test/user_tests_SUITE.erl
deleted file mode 100644
index 9654114725..0000000000
--- a/lib/dialyzer/test/user_tests_SUITE.erl
+++ /dev/null
@@ -1,78 +0,0 @@
-%% ATTENTION!
-%% This is an automatically generated file. Do not edit.
-%% Use './remake' script to refresh it if needed.
-%% All Dialyzer options should be defined in dialyzer_options
-%% file.
-
--module(user_tests_SUITE).
-
--include("ct.hrl").
--include("dialyzer_test_constants.hrl").
-
--export([suite/0, init_per_suite/0, init_per_suite/1,
- end_per_suite/1, all/0]).
--export([user_tests_SUITE_consistency/1, broken_dialyzer/1,
- gcpFlowControl/1, qlc_error/1, spvcOrig/1, wsp_pdu/1]).
-
-suite() ->
- [{timetrap, {minutes, 3}}].
-
-init_per_suite() ->
- [{timetrap, ?plt_timeout}].
-init_per_suite(Config) ->
- OutDir = ?config(priv_dir, Config),
- case dialyzer_common:check_plt(OutDir) of
- fail -> {skip, "Plt creation/check failed."};
- ok -> [{dialyzer_options, []}|Config]
- end.
-
-end_per_suite(_Config) ->
- ok.
-
-all() ->
- [user_tests_SUITE_consistency,broken_dialyzer,gcpFlowControl,qlc_error,
- spvcOrig,wsp_pdu].
-
-dialyze(Config, TestCase) ->
- Opts = ?config(dialyzer_options, Config),
- Dir = ?config(data_dir, Config),
- OutDir = ?config(priv_dir, Config),
- dialyzer_common:check(TestCase, Opts, Dir, OutDir).
-
-user_tests_SUITE_consistency(Config) ->
- Dir = ?config(data_dir, Config),
- case dialyzer_common:new_tests(Dir, all()) of
- [] -> ok;
- New -> ct:fail({missing_tests,New})
- end.
-
-broken_dialyzer(Config) ->
- case dialyze(Config, broken_dialyzer) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-gcpFlowControl(Config) ->
- case dialyze(Config, gcpFlowControl) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-qlc_error(Config) ->
- case dialyze(Config, qlc_error) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-spvcOrig(Config) ->
- case dialyze(Config, spvcOrig) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
-wsp_pdu(Config) ->
- case dialyze(Config, wsp_pdu) of
- 'same' -> 'same';
- Error -> ct:fail(Error)
- end.
-
diff --git a/lib/dialyzer/test/user_tests_SUITE_data/src/broken_dialyzer.erl b/lib/dialyzer/test/user_tests_SUITE_data/src/broken_dialyzer.erl
deleted file mode 100644
index fd9a6ada1a..0000000000
--- a/lib/dialyzer/test/user_tests_SUITE_data/src/broken_dialyzer.erl
+++ /dev/null
@@ -1,130 +0,0 @@
--module(broken_dialyzer).
-
--export([do_move_next/1]).
-
--define(ap_indices, 512).
--define(dp_indices, 504).
-
-
--record(apR,{a,c=[],n=[],nc=0,nn=0,nl=[]}).
--define(apL(L), [#apR{a=A} || A <- L]).
-
--define(gr, get(my_return_value)).
--define(pr(PR), put(my_return_value, PR)).
--record(bit,{i,c,n,s}). % index, current, next, state
-
-
-do_move_next({BL,AL}) ->
- Max = max(length(BL), length(AL)),
- Max2 = max(length(BL)*2, length(AL)),
- MoveTo = [A || A <- AL, A#apR.nn < Max, A#apR.nn+A#apR.nc < Max2],
- MoveFrom = [A || A <- AL,
- (A#apR.nn > Max) orelse (A#apR.nn+A#apR.nc > Max2)],
- Unchanged = (AL--MoveTo)--MoveFrom,
- {BL1,{AL1,{AL2,AL3}}} =
- lists:mapfoldl(
- fun(B=#bit{i=I,c=C,s=S,n=Next}, {From,{To,FilledUp}})
- when S==ok;S==lost_replica;S==moved_replica ->
- case lists:keysearch(Next,#apR.a,From) of
- {value, F=#apR{n=N1,nn=NN1,nc=NC1}}
- when (NN1>Max) or (NN1+NC1>Max2) ->
- case C of
- [] ->
- {B, {From,{To,FilledUp}}};
- ShortList ->
- T=#apR{a=NewNext,n=N2,nn=NN2} =
- find_next(Next,ShortList),
- {value, {C,NL_from}} =
- lists:keysearch(C,1,F#apR.nl),
- {value, {C,NL_to}} =
- lists:keysearch(C,1,T#apR.nl),
- NewNL_from = lists:keyreplace(
- C,1,F#apR.nl,{C,NL_from--[I]}),
- NewNL_to = lists:keyreplace(
- C,1,T#apR.nl,{C,[I|NL_to]}),
-
- NewT = T#apR{n=[I|N2],nn=NN2+1,
- nl=NewNL_to},
-
- {B#bit{n=NewNext,
- s = if
- S == lost_replica ->
- lost_replica;
- true ->
- moved_replica
- end},
- {lists:keyreplace(
- Next,#apR.a,From,
- F#apR{n=N1--[I],nn=NN1-1,nl=NewNL_from}),
- if
- (NewT#apR.nn+NewT#apR.nc >= Max2)
- or (NewT#apR.nn >= Max) ->
- {lists:keydelete(NewNext,#apR.a,To),
- [NewT|FilledUp]};
- true ->
- {lists:keyreplace(
- NewNext,#apR.a,To,NewT),
- FilledUp}
- end}}
- end;
- _ ->
- {B, {From,{To,FilledUp}}}
- end;
- (B, A) ->
- {B, A}
- end, {MoveFrom,{MoveTo,[]}},BL),
- {BL1,Unchanged++AL1++AL2++AL3}.
-
-%%% -----------------------------------------------------------------
-%%% find_next/2
-%%%
-%%% ------------------------------------------------------------------
-
-find_next(Ap,L) ->
- hd(catch
- lists:foreach(
- fun(SelVal) ->
- case [ApR ||
- ApR <- L,
- begin
- {value,{Ap,NL}} =
- lists:keysearch(Ap,1,ApR#apR.nl),
- length(NL) =< SelVal
- end] of
- [] ->
- ok;
- ShortList ->
- throw(ShortList)
- end
- end,
- lists:seq(0,?ap_indices))).
-
-%%% -----------------------------------------------------------------
-%%% max/2
-%%%
-%%% Calculates max number of indices per AP, given number of indices
-%%% and number of APs.
-%%% -----------------------------------------------------------------
-max(F,S) ->
- (F div S) + if
- (F rem S) == 0 ->
- 0;
- true ->
- 1
- end.
-
-%%% ==============================================================
-%%% ADMINISTRATIVE INFORMATION
-%%% ==============================================================
-%%% #Copyright (C) 2005
-%%% by ERICSSON TELECOM AB
-%%% S - 125 26 STOCKHOLM
-%%% SWEDEN, tel int + 46 8 719 0000
-%%%
-%%% The program may be used and/or copied only with the written
-%%% permission from ERICSSON TELECOM AB, or in accordance with
-%%% the terms and conditions stipulated in the agreement/contract
-%%% under which the program has been supplied.
-%%%
-%%% All rights reserved
-%%%
diff --git a/lib/dialyzer/test/user_tests_SUITE_data/src/gcp.hrl b/lib/dialyzer/test/user_tests_SUITE_data/src/gcp.hrl
deleted file mode 100644
index aac87d8b6b..0000000000
--- a/lib/dialyzer/test/user_tests_SUITE_data/src/gcp.hrl
+++ /dev/null
@@ -1,166 +0,0 @@
-%%% #0. BASIC INFORMATION
-%%% ----------------------------------------------------------
-%%% %CCaseFile: gcp.hrl %
-%%% Author: EAB/UPD/AV
-%%% Description: Internal include file.
-%%% ----------------------------------------------------------
--hrl_id('9/190 55-CNA 113 033 Ux').
--hrl_vsn('/main/R1A/21').
--hrl_date('2005-05-31').
--hrl_author('uabasve').
-%%% %CCaseTemplateFile: module.hrl %
-%%% %CCaseTemplateId: 17/002 01-FEA 202 714 Ux, Rev: /main/4 %
-%%%
-%%% Copyright (C) 2000-2005 by Ericsson Telecom AB
-%%% SE-126 25 STOCKHOLM
-%%% SWEDEN, tel int + 46 8 719 0000
-%%%
-%%% The program may be used and/or copied only with the written
-%%% permission from Ericsson Telecom AB, or in accordance with
-%%% the terms and conditions stipulated in the agreement/contract
-%%% under which the program has been supplied.
-%%%
-%%% All rights reserved
-%%%
-%%% ----------------------------------------------------------
-%%% #1. REVISION LOG
-%%% ----------------------------------------------------------
-%%% Rev Date Name What
-%%% ----- ------- -------- ------------------------
-%%% R1A/1 05-02-07 uabasve Copied from EAS R7A/9
-%%% R1A/2 05-02-08 ejojmjn Removed SAAL
-%%% R1A/3- 05-03-18 uabasve Clean.
-%%% ----------------------------------------------------------
-%%%
-%%% #2. CODE
-%%% #---------------------------------------------------------
-%%% #2.1 DEFINITION OF CONSTANTS
-%%% #---------------------------------------------------------
-
-%% Keys into gcpVariables for various options/values.
--define(TRAFFIC_DESCRIPTOR_KEY, traffic_descriptor).
-
-%% H.248 version at link creation.
--define(INITIAL_H248_VERSION, 1).
-
-%% Exceptions for use within a module. ?MODULE is just extra protection
-%% against catching something unexpected.
--define(THROW(Reason), throw({error, ?MODULE, ?LINE, Reason})).
--define(CATCH(Expr), try Expr
- catch throw: ?FAILURE(Reason) -> {error, Reason}
- end).
--define(FAILURE(T), {error, ?MODULE, _, T}).
-
-%% The SendHandle used by a GCP transport process must be a tuple
-%% of length >= 2 whose first two elements are the pid of the
-%% transport process and index (aka #gcpLinkTable.key) of the link
-%% upon which incoming data has arrived.
--define(SH_PID(SendHandle), element(1, SendHandle)).
--define(SH_LINK(SendHandle), element(2, SendHandle)).
--define(SH_SET_PID(SendHandle, Pid), setelement(1, SendHandle, Pid)).
-
-%% Megaco process that CH and OM servers monitor. This needs to be
-%% replaced by a documented method.
--define(MEGACO_APP, megaco_config).
-
-%% The message that gcpI:send_reply sends to the process that's waiting
-%% for an action reply.
--define(ACTION_REPLY_MESSAGE(ActionReplies, Result),
- {reply, ActionReplies, Result}).
-
-%%% #---------------------------------------------------------
-%%% #2.2 DEFINITION OF RECORDS
-%%% #---------------------------------------------------------
-
--record(mg, {pref}).
--record(mgc, {mgid}).
-
-%% User configuration that gets mapped into megaco user info by
-%% gcpLib:make_user_info/1. GCP exposes only a subset of what's
-%% possible to set in megaco.
--record(user_config,
- {reply_timer = 30000, %% ms to wait for reply ack
- %% Incoming transactions:
- pending_timer = 10000, %% ms until outgoing transaction pending
- sent_pending_limit = 5, %% nr of outgoing pendings before 506
- %% Outgoing transactions:
- recv_pending_limit = infinity,%% nr of incoming pendings before fail
- request_timer = 3000, %% ms to wait for response before resend
- request_retries = 5, %% nr unanswered sends before fail
- long_request_timer = 15000, %% ms to wait for reply after pending
- long_request_retries = 5}). %% nr of pendings/timeouts before fail
-
-%% Record passed into transport implementations at transport start.
-%% Expected to be passed back to gcpTransportI.
--record(receive_handle,
- {megaco_receive_handle, %% passed to megaco:receive_message
- receive_message}). %% gcpLinkTable.receive_message
-
-%%% ---------------------------------------------------------------------------
-%%% # gcpRegistrationTable
-%%%
-%%% Record containing defined MGC's/MG's (aka megaco users).
-%%% ---------------------------------------------------------------------------
-
--record(gcpRegistrationTable,
- {key, %% user reference (aka MG/MGC id)
- role, %% mg | mgc
- mid, %% H.248 mid of the MGC/MG
- version, %% of H.248
- callback, %% {Module, ExtraArgs}
- config = #user_config{}}).
-
-%%% ----------------------------------------------------------
-%%% # gcpLinkTable
-%%% ----------------------------------------------------------
-
--record(gcpLinkTable,
- {key, %% link reference
- endpoint, %% #mgc{} | #mg{}
- user, %% registration table key
- chid, %% call handler of transport
- admin_state, %% up | down
- op_state, %% up | down | pending | disabled
- restart = auto, %% auto | user
- encoding_mod, %% module implementing megaco_encoder
- encoding_config, %% as passed to encoding_mod
- transport_start, %% {M,F,ExtraArgs} for transport start
- transport_data, %% arbitrary, passed to transport_mod
- send_message, %% {default|sysrpc|transport|module, Module}
- receive_message, %% local | {M,F,ExtraArgs} for decode node
- tried = false, %% Only for links owned by a MG.
- %% Used to indicate that a setup attempt
- %% has been performed on this link.
- t95_period = 350000}).
-
-%%% ----------------------------------------------------------
-%%% # gcpActiveLinkTable
-%%% ----------------------------------------------------------
-
--record(gcpActiveLinkTable,
- {key, %% {mg|mgc, MgId}
- link, %% link reference
- chid, %% CH the link is tied to
- node, %% node the link is on
- conn_handle, %% record megaco_conn_handle
- send_handle, %% {TransportPid, LinkIdx, ...}
- version = ?INITIAL_H248_VERSION}).
-
-%%% ----------------------------------------------------------
-%%% # gcpVariables
-%%% ----------------------------------------------------------
-
--record(gcpVariables,
- {key,
- value}).
-
-%%% ----------------------------------------------------------
-%%% # gcpReplyData
-%%% ----------------------------------------------------------
-
--record(gcpReplyData,
- {callback, %% {Module, Args}
- mgid,
- user_data, %% As passed by the user on send
- prio,
- timestamp}).
diff --git a/lib/dialyzer/test/user_tests_SUITE_data/src/gcpFlowControl.erl b/lib/dialyzer/test/user_tests_SUITE_data/src/gcpFlowControl.erl
deleted file mode 100644
index 1653220352..0000000000
--- a/lib/dialyzer/test/user_tests_SUITE_data/src/gcpFlowControl.erl
+++ /dev/null
@@ -1,397 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File : gcpFlowControl.erl
-%%% Author : EAB/UPD/AV
-%%% Description : Implements overload protection.
-%%%-------------------------------------------------------------------
--module(gcpFlowControl).
--id('24/190 55-CNA 113 033 Ux').
--vsn('/main/R1A/14').
--date('2005-05-04').
--author('uabasve').
-%%% ----------------------------------------------------------
-%%% %CCaseTemplateFile: module.erl %
-%%% %CCaseTemplateId: 16/002 01-FEA 202 714 Ux, Rev: /main/4 %
-%%%
-%%% Copyright (C) 2001-2005 by Ericsson Telecom AB
-%%% SE-126 25 STOCKHOLM
-%%% SWEDEN, tel int + 46 8 719 0000
-%%%
-%%% The program may be used and/or copied only with the written
-%%% permission from Ericsson Telecom AB, or in accordance with
-%%% the terms and conditions stipulated in the agreement/contract
-%%% under which the program has been supplied.
-%%%
-%%% All rights reserved
-%%%
-%%%
-%%% ----------------------------------------------------------
-%%% #1. REVISION LOG
-%%% ----------------------------------------------------------
-%%% Rev Date Name What
-%%% -------- -------- -------- ------------------------
-%%% R1A/1-2 05-02-07 ejojmjn Copied from EAS R7A/11.
-%%% R1A/3-14 05-03-14 uabasve Clean.
-%%%--------------------------------------------------------------------
-
--include_lib("megaco/include/megaco.hrl").
--include_lib("megaco/include/megaco_message_v1.hrl").
--include("gcp.hrl").
-
--export([send_request/4, %% user send from gcpInterface
- receive_reply/2, %% from callback in gcpTransaction
- init_ets_tables/1,
- init_data/2]).
-
--define(PRIO_INFINITY, 16).
--define(MIN_WINDOW, 10).
--define(MAX_WINDOW, 100).
-
--define(BUCKET_MAX, 100).
--define(BUCKET_THRESH_HIGH, 80).
--define(BUCKET_THRESH_LOW, 20).
-
--define(ALLOW_TIMEOUT, 1000).
-
-%% Holds counters for flow control in GCP
--record(gcpFlowControlTable,
- {key,
- window = 50,
- available = 50,
- bucket = 0,
- q = 0,
- sent = 0, %% Counts all attempts
- rejectable = 0, %% Counts rejectable attempts
- t95,
- errors = 0,
- rejects = 0,
- replies = 0}).
-
--record(gcpFlowControlBitmap,
- {key,
- count = 0}).
-
-%%====================================================================
-%% External functions
-%%====================================================================
-
-%%--------------------------------------------------------------------
-%% Function: send_request/4
-%%
-%% Output: ok | {error, Reason}
-%%--------------------------------------------------------------------
-
-send_request(ActiveLink, TimerOptions, ActionRequests, UserData) ->
- #gcpActiveLinkTable{key = Key,
- conn_handle = ConnHandle}
- = ActiveLink,
- Prio = prio(ActionRequests),
- incr(Key, sent),
- case allow(Key, Prio) of
- {true, Timestamp} ->
- grant_request(user_data(ConnHandle),
- Key,
- Prio,
- Timestamp,
- ConnHandle,
- TimerOptions,
- ActionRequests,
- UserData);
- false ->
- {error, rejected}
- end.
-
-%%--------------------------------------------------------------------
-%% Function: receive_reply/2
-%% Description:
-%%--------------------------------------------------------------------
-
-receive_reply(Key, Timestamp) ->
- incr(Key, available),
- incr(Key, replies),
- release(Key),
- report_time(Key, Timestamp).
-
-%%--------------------------------------------------------------------
-%% Func: init_ets_tables/1
-%%
-%% Returns: ok
-%%--------------------------------------------------------------------
-
-init_ets_tables(Role) ->
- create_ets(Role, gcpFlowControlTable, #gcpFlowControlTable.key),
- create_ets(Role, gcpFlowControlBitmap, #gcpFlowControlBitmap.key),
- ok.
-
-create_ets(Role, Table, Pos) when integer(Pos) ->
- create_ets(Role,
- Table,
- [named_table, ordered_set, public, {keypos, Pos}]);
-
-create_ets(test, Table, ArgList) ->
- ets:new(Table, ArgList);
-create_ets(Role, Table, ArgList) ->
- case ets:info(Table) of
- undefined ->
- sysCmd:ets_new(Table, ArgList);
- _ when Role == ch ->
- sysCmd:inherit_tables([Table]);
- _ when Role == om ->
- ok
- end.
-
-%%--------------------------------------------------------------------
-%% Func: init_data/2
-%%--------------------------------------------------------------------
-
-init_data(Key, T95) ->
- ets:insert(gcpFlowControlTable, #gcpFlowControlTable{key = Key,
- t95 = T95}).
-
-%%--------------------------------------------------------------------
-%%% Internal functions
-%%--------------------------------------------------------------------
-
-%%% ----------------------------------------------------------
-%%% incr
-%%% ----------------------------------------------------------
-
-cntr(Key, Field) ->
- incr(Key, Field, 0).
-
-incr(Key, Field) ->
- incr(Key, Field, 1).
-
--define(INCR(Field),
- incr(Key, Field, X) -> upd_c(Key, {#gcpFlowControlTable.Field, X})).
-
-?INCR(sent);
-?INCR(replies);
-?INCR(q);
-?INCR(t95);
-?INCR(errors);
-?INCR(rejects);
-?INCR(rejectable);
-?INCR(window);
-?INCR(available);
-
-incr(Key, bucket, X)->
- upd_c(Key, {#gcpFlowControlTable.bucket, X, ?BUCKET_MAX, ?BUCKET_MAX}).
-
-upd_c(Key, N) ->
- ets:update_counter(gcpFlowControlTable, Key, N).
-
-%%% ----------------------------------------------------------
-%%% decr
-%%%
-%%% Beware that decr is implemented as incr, care has to be taken
-%%% not to bungle things when max/min values are used.
-%%% ----------------------------------------------------------
-
-decr(Key, available, X) ->
- upd_c(Key, {#gcpFlowControlTable.available, -X});
-decr(Key, window, X) ->
- upd_c(Key, {#gcpFlowControlTable.window, -X});
-decr(Key, bucket, X) ->
- upd_c(Key, {#gcpFlowControlTable.bucket, -X, 0, 0}).
-
-decr(Key, Field) ->
- decr(Key, Field, 1).
-
-%%% ----------------------------------------------------------
-%%% allow
-%%% ----------------------------------------------------------
-
-allow(Key, ?PRIO_INFINITY) ->
- decr(Key, available),
- {true, now()};
-
-allow(Key, Prio) ->
- incr(Key, rejectable),
- case decr(Key, available) of
- N when N > 0 ->
- {true, no_stamp};
- _ ->
- %% We did not send it, therefore incr available again
- incr(Key, available),
- queue(Key, Prio)
- end.
-
-%%% ----------------------------------------------------------
-%%% queue
-%%% ----------------------------------------------------------
-
-queue(Key, Prio) ->
- incr(Key, q),
- T = {Key, Prio, now(), self()},
- ets:insert(gcpFlowControlBitmap, #gcpFlowControlBitmap{key = T}),
- wait(T).
-
-%%% ----------------------------------------------------------
-%%% wait
-%%% ----------------------------------------------------------
-
-wait({Key, _Prio, _When, _Self} = T) ->
- receive
- allow ->
- ets:delete(gcpFlowControlBitmap, T),
- decr(Key, available),
- {true, no_stamp}
- after ?ALLOW_TIMEOUT ->
- timeout(T),
- adjust_window(Key),
- incr(Key, rejects),
- false
- end.
-
-timeout(T) ->
- case ets:update_counter(gcpFlowControlBitmap, T, 1) of
- 1 ->
- %% Got the lock: no one has released Key and sent 'allow'.
- ets:delete(gcpFlowControlBitmap, T),
- ok;
- _ ->
- %% A releasing process got the lock: 'allow' has been
- %% sent. Try to remove the message before proceeding.
- %% (This is to keep mdisp from complaining apparently.)
- ets:delete(gcpFlowControlBitmap, T),
- receive
- allow ->
- ok
- after ?ALLOW_TIMEOUT ->
- io:format("~p: errant allow: ~p~n", [?MODULE, T])
- end
- end.
-
-%% Now, if we reject and our general response time is low
-%% (i.e. low bucket) then we increase the window size.
-adjust_window(Key) ->
- adjust_window(Key,
- cntr(Key, bucket) < ?BUCKET_THRESH_LOW
- andalso cntr(Key, window) < ?MAX_WINDOW).
-
-adjust_window(Key, true) ->
- incr(Key, window),
- incr(Key, available),
- incr(Key, bucket, 20);
-adjust_window(_, false) ->
- ok.
-
-%%--------------------------------------------------------------------
-%% Func: report_time/2
-%%--------------------------------------------------------------------
-
-report_time(_, no_stamp) ->
- ok;
-report_time(Key, {MS, S, Ms})->
- {MegaSecs, Secs, MicroSecs} = now(),
- p(Key,
- MicroSecs - Ms + 1000000*(Secs - S + 1000000*(MegaSecs - MS)),
- cntr(Key, t95)).
-
-%%% ----------------------------------------------------------
-%%% p
-%%% ----------------------------------------------------------
-
-p(Key, Time, T95) when Time =< T95 ->
- decr(Key, bucket);
-p(Key, _Time, _T95) ->
- %% If we have a long response time, then increase the leaky
- %% bucket. If the bucket is over the high watermark and the window
- %% is not already at its minimum size, then decrease the window
- %% and available.
- case {cntr(Key, window), incr(Key, bucket, 20)} of
- {Window, Bucket} when Window > ?MIN_WINDOW,
- Bucket > ?BUCKET_THRESH_HIGH ->
- decr(Key, window),
- decr(Key, available);
- _ ->
- ok
- end.
-
-%%% ----------------------------------------------------------
-%%% release
-%%% ----------------------------------------------------------
-
-release(Key) ->
- %% The choice of the key below will cause ets:prev/2 to return
- %% the key with the highest priority which was queued most
- %% recently. This relies on the fact that integers sort before
- %% atoms, the atom 'prio' in this case. The atoms 'queued' and
- %% 'pid' are of no significance.
- release(Key, {Key, prio, queued, pid}).
-
-%% This isn't a (FIFO) queue within each priority, but a (LIFO) stack.
-
-release(Key, T) ->
- release(Key, cntr(Key, available), ets:prev(gcpFlowControlBitmap, T)).
-
-%% Note that only keys on the same Key are matched.
-release(Key, N, {Key, _Prio, _When, Pid} = T) when N > 0 ->
- case catch ets:update_counter(gcpFlowControlBitmap, T, 1) of
- 1 ->
- Pid ! allow;
- _ ->
- %% Another process has released this key.
- release(Key, T)
- end;
-
-release(_, _, _)->
- ok.
-
-%%% ----------------------------------------------------------
-%%% user_data
-%%% ----------------------------------------------------------
-
-user_data(ConnHandle) ->
- case catch megaco:conn_info(ConnHandle, reply_data) of
- {'EXIT', _Reason} ->
- false;
- Rec ->
- {value, Rec}
- end.
-
-%%% ----------------------------------------------------------
-%%% grant_request
-%%% ----------------------------------------------------------
-
-grant_request({value, Rec},
- Key, Prio, Time,
- ConnHandle, Options, ActionRequests, UserData) ->
- ReplyData = Rec#gcpReplyData{user_data = UserData,
- prio = Prio,
- timestamp = Time},
- cast_rc(megaco:cast(ConnHandle,
- ActionRequests,
- [{reply_data, ReplyData} | Options]),
- Key,
- ActionRequests);
-
-grant_request(false, Key, _, _, _, _, _, _) ->
- incr(Key, available),
- {error, reply_data}.
-
-cast_rc(ok = Ok, _, _) ->
- Ok;
-cast_rc({error, Reason}, Key, ActionRequests) ->
- incr(Key, available),
- gcpLib:error_report(?MODULE, send_request, [ActionRequests],
- "send failed",
- Reason),
- {error, {encode, Reason}}.
-
-%%--------------------------------------------------------------------
-%% Func: prio/1
-%% Returns: The priority of the request
-%%--------------------------------------------------------------------
-
-prio([ActionRequest | _]) ->
- #'ActionRequest'{contextId = ContextId,
- contextRequest = ContextRequest}
- = ActionRequest,
- prio(ContextId, ContextRequest).
-
-prio(?megaco_choose_context_id, #'ContextRequest'{priority = Prio})
- when integer(Prio) ->
- Prio;
-prio(_, _) ->
- ?PRIO_INFINITY.
diff --git a/lib/dialyzer/test/user_tests_SUITE_data/src/qlc_error.erl b/lib/dialyzer/test/user_tests_SUITE_data/src/qlc_error.erl
deleted file mode 100644
index a6865c4562..0000000000
--- a/lib/dialyzer/test/user_tests_SUITE_data/src/qlc_error.erl
+++ /dev/null
@@ -1,15 +0,0 @@
-%% -*- erlang-indent-level: 2 -*-
-%% $Id: qlc_error.erl,v 1.1 2008/12/17 09:53:52 mikpe Exp $
-
-%% @author Daniel Luna <[email protected]>
-%% @copyright 2006 Daniel Luna
-%%
-%% @doc
-%%
-
--module(qlc_error).
--export([fix/0]).
--include_lib("stdlib/include/qlc.hrl").
-
-fix() ->
- qlc:eval(qlc:q([I || I <- []])).
diff --git a/lib/dialyzer/test/user_tests_SUITE_data/src/spvcOrig.erl b/lib/dialyzer/test/user_tests_SUITE_data/src/spvcOrig.erl
deleted file mode 100644
index 70a3c4c7e2..0000000000
--- a/lib/dialyzer/test/user_tests_SUITE_data/src/spvcOrig.erl
+++ /dev/null
@@ -1,3523 +0,0 @@
-%%%=======================================================================
-%%%
-%%% Test from Mats Cronqvist <[email protected]>. The
-%%% analysis crasched due to the handling of tuples-as-funs in
-%%% hipe_icode_type.erl, and it also exposed a bug when a control flow
-%%% path is first analyzed and then shown to be infeasible.
-%%%
-
--file("./spvcOrig.erl", 1).
-
--module(spvcOrig).
-
--author(qamarma).
-
--id('3/190 55-CNA 121 64').
-
--vsn('/main/Inc4/R2A/R4A/R6A/R7A/R7D/R8B/R10A/R11A/2').
-
--date('2004-10-26').
-
--export([gen_set/3,gen_set/4,connect/3,release_comp_nu/3,release_nu/3,timeout/2,restart_spvc/1,restart_multi_spvcs/1,forced_release/1,error_handler/3,get_backoff_table/2,timeout_event/1]).
-
--export([release_incumbent/2,switch_over/2]).
-
--export([call_failure/1,get_backoff_table/2]).
-
--file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/pchTables.hrl", 1).
-
--hrl_id('2/190 55-CNA 121 08').
-
--hrl_vsn('/main/Inc3/Inc4/R2A/R3A/R3B/R5A/R6A/R7A/R7D/R8B/13').
-
--hrl_date('2003-01-24').
-
--file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../derived_hrl/mib/AXD301-PCH-MIB.hrl", 1).
-
--file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/pchTables.hrl", 58).
-
--record(pchVp, {vplEntry,
- vplLastChange,
- vplReceiveTrafficDescrIndex = 0,
- vplTransmitTrafficDescrIndex = 0,
- vplCcIdentifier,
- vplConnId,
- vplMpId,
- vplLeafId,
- vplChargingIndicator = 1,
- vplRemoteChargingInd = 1,
- vplChargablePartyIdentifier,
- vplSegmentEndPoint = 2,
- vplRowStatus,
- vplCastType = 1,
- vplConnKind = 1,
- vplServiceType = 2,
- vplEndPointData,
- vplContinuityCheck = 1,
- vplUpcNpcMode = 2,
- vplPreventInbandCc = 1,
- vplMonAisRdi = 2,
- vpcAdminStatus = 2,
- vplSpvcAutoTarget = 2,
- vplSchedulingFlag = 2,
- vplApplication,
- vplRemoteData,
- vpccAdminStatus = 2,
- vplContCheckSearch = 1,
- vplPmSearch = 1,
- vplLastBuffFlagRead,
- vplShapingMode = 1,
- vplGroupShapingId}).
-
--record(pchVpDb, {vplEntry,
- vplLastChange,
- vplReceiveTrafficDescrIndex = 0,
- vplTransmitTrafficDescrIndex = 0,
- vplCcIdentifier,
- vplConnId,
- vplMpId,
- vplLeafId,
- vplAttributes,
- vplChargablePartyIdentifier,
- vplRowStatus,
- vplEndPointData,
- vplApplication,
- vplRemoteData,
- vplLastBuffFlagRead,
- vplShapingMode,
- vplGroupShapingId}).
-
--record(pchVpExt, {vplExtEntry,
- vplExtReceiveTdIndex,
- vplExtTransmitTdIndex,
- vplExtUserName = [],
- vplExtProviderName = [],
- vplExtUserOperator}).
-
--record(pchVc, {vclEntry,
- vclLastChange,
- vclReceiveTrafficDescrIndex = 0,
- vclTransmitTrafficDescrIndex = 0,
- vclCcIdentifier,
- vclConnId,
- vclMpId,
- vclLeafId,
- vclChargingIndicator = 1,
- vclRemoteChargingInd = 1,
- vclChargablePartyIdentifier,
- vclPacketDiscard = 2,
- vclSegmentEndPoint = 2,
- vclRowStatus,
- vclCastType = 1,
- vclConnKind = 1,
- vclContinuityCheck = 1,
- vclUpcNpcMode = 2,
- vclEndPointData,
- vclPreventInbandCc = 1,
- vclMonAisRdi = 2,
- vclSpvcAutoTarget = 2,
- vclSchedulingFlag = 2,
- vclApplication,
- vclRemoteData,
- vcccAdminStatus = 2,
- vclContCheckSearch = 1,
- vclPmSearch = 1,
- vclLastBuffFlagRead,
- vclChargingIfChanid,
- vclShapingMode = 1}).
-
--record(pchVcDb, {vclEntry,
- vclLastChange,
- vclReceiveTrafficDescrIndex = 0,
- vclTransmitTrafficDescrIndex = 0,
- vclCcIdentifier,
- vclConnId,
- vclMpId,
- vclLeafId,
- vclAttributes,
- vclChargablePartyIdentifier,
- vclRowStatus,
- vclEndPointData,
- vclApplication,
- vclRemoteData,
- vclLastBuffFlagRead,
- vclChargingIfChanid,
- vclShapingMode}).
-
--record(pchAtd, {tdIndex,
- tdType,
- tdParam1 = 0,
- tdParam2 = 0,
- tdParam3 = 0,
- tdParam4 = 0,
- tdParam5 = 0,
- tdTrafficQoSClass = 0,
- tdRowStatus = 1,
- tdServiceCategory = 6,
- tdVcCapability = 1,
- tdName = [],
- tdUserCounter = 0,
- tdUser = []}).
-
--record(pchAbr, {abrIndex,
- abrIcr,
- abrTbe = 16277215,
- abrFrtt = 0,
- abrRdf = 11,
- abrRif = 11,
- abrNrm = 4,
- abrTrm = 7,
- abrCdf = 3,
- abrAdtf = 50,
- abrRowStatus = 1}).
-
--record(pchIndexNext, {key,
- tdIndexNext,
- vpccIndexNext,
- vcccIndexNext,
- scheduledVpCcIndexNext,
- scheduledVcCcIndexNext}).
-
--record(pchSchedVpCc, {schedVpCcIndex,
- schedVpCcTarget,
- schedVpCcReceiveTdIndex,
- schedVpCcTransmitTdIndex,
- schedVpCcOpTime,
- schedVpCcOpInd,
- schedVpCcOpStatus,
- schedVpCcTimerRef,
- schedVpCcRowStatus,
- schedVpCcErrorCode,
- schedVpCcUserName = [],
- schedVpCcProviderName = []}).
-
--record(pchVpCc, {vpccId,
- vpccUserName = [],
- vpccAdminStatus,
- vpccApplication,
- vpccProviderName = []}).
-
--record(pchSchedVcCc, {schedVcCcIndex,
- schedVcCcTarget,
- schedVcCcReceiveTdIndex,
- schedVcCcTransmitTdIndex,
- schedVcCcOpTime,
- schedVcCcOpInd,
- schedVcCcOpStatus,
- schedVcCcTimerRef,
- schedVcCcRowStatus,
- schedVcCcErrorCode,
- schedVcCcUserName = [],
- schedVcCcProviderName = []}).
-
--record(pchVcCc, {vcccId,
- vcccUserName = [],
- vcccAdminStatus,
- vcccApplication,
- vcccProviderName = []}).
-
--record(pchSigChannels, {et_entry,
- cp_entry,
- sb_cp_entry,
- membership,
- status,
- sb_status,
- application = {0,[]}}).
-
--record(pchSigChannelExt, {et_entry,
- user_name,
- provider_name}).
-
--record(pchApplication, {key,
- application,
- rights}).
-
--record(pchCurrAlarm, {key,
- type_of_fault,
- fault_id}).
-
--record(pchIfAddress, {ifAddressEntry,
- ifAddressRowStatus}).
-
--record(pchAddressToIf, {address,
- if_index}).
-
--record(pchPreferences, {key,
- if_format}).
-
--record(pchSigChannelCallback, {key,
- callback,
- function,
- args,
- data}).
-
--record(pchTermHcId, {hcId,
- vclEntry}).
-
--record(pchChg, {chgEntry,
- chgStatus}).
-
--record(pchCommState, {key,
- ccid,
- request,
- low_cp_state,
- high_cp_state,
- et_side,
- application,
- data,
- timestamp,
- timer_id,
- callback}).
-
--record(pchBufferedCmd, {key,
- resource,
- module,
- function,
- arguments,
- data}).
-
--record(pchAnswerCh, {conn_id,
- chg_data,
- call_back_cp,
- old_rtd,
- old_ttd,
- old_EpData,
- action,
- resource,
- data,
- fail_cause}).
-
--record(pchAnswerOm, {conn_id}).
-
--record(ccPch, {rowInd,
- admState = 2}).
-
--record(pchIf, {ilmiVpi = 0,
- ilmiVci = 0,
- ilmiS = 1,
- ilmiT = 5,
- ilmiK = 4,
- neighborIfName = [],
- neighborIpAddr = [0,0,0,0],
- maxVciSvc,
- overbookingFactor = {0,0},
- shapingMode = 0,
- maxVpiSvc,
- cdvtMultFactor = 100,
- scBandwidth1 = 0,
- scBandwidth2 = 0,
- scBandwidth3 = 0,
- scBandwidth4 = 0}).
-
--record(pchMpTemp, {key,
- data}).
-
--record(pchLatestErrorCode, {key,
- errorCode}).
-
--record(pchRangeTable, {node,
- tdIndexRange,
- vpccIndexRange,
- vcccIndexRange}).
-
--record(pchIndexBitmaps, {key,
- available,
- bitmap}).
-
--record(pchLinkState, {key,
- op_state,
- last_change}).
-
--record(pchFailedVpl, {vplEntry,
- vplLastChange}).
-
--record(pchFailedVcl, {vclEntry,
- vclLastChange}).
-
--record(pchStatCounters, {key,
- ingress,
- egress}).
-
--record(pchEtStatTable, {index,
- value = 0}).
-
--record(pchAuditResult, {key,
- passed,
- not_passed,
- sizes,
- obj_keys}).
-
--record(pch_fault_reqc, {fault_type,
- fault_location}).
-
--record(pch_cid, {conn_id,
- mp_id,
- leaf_id}).
-
--file("./spvcOrig.erl", 207).
-
--file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/pchI.hrl", 1).
-
--hrl_id('52/190 55-CNA 121 08 Ux').
-
--hrl_vsn('/main/R6A/R7A/R7D/R8B/3').
-
--hrl_date('2002-10-14').
-
--hrl_author(uabdomo).
-
--record(pch_vc_rec, {ifIndex,
- vpi,
- vci,
- application}).
-
--record(pch_vp_rec, {ifIndex,
- vpi}).
-
--record(pch_td_index, {rtd_index,
- ttd_index}).
-
--record(pch_td, {service_cat,
- pcr,
- scr,
- mbs,
- mcr,
- cdvt,
- tagging,
- clp_significance}).
-
--record(pch_call_back_req, {module,
- function,
- user_data}).
-
--record(pch_chg_rec, {chg_type,
- chg_interface,
- chg_chan_id,
- chg_party_name}).
-
--record(pch_polic_rec, {policing,
- packet_discard}).
-
--record(pch_user_name_rec, {user_name}).
-
--record(pch_shaping_rec, {shaping}).
-
--record(pch_audit_callback, {mod,
- arg}).
-
--file("./spvcOrig.erl", 208).
-
--file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/plc.hrl", 1).
-
--hrl_id('12/190 55-CNA 121 45 Ux').
-
--hrl_vsn('/main/R6A/R6B/R7A/R7D/R8B/R9A/R11A/4').
-
--hrl_date('2004-12-07').
-
--hrl_author(ethrba).
-
--record(plcQueues, {name,
- type,
- weight,
- maxlength,
- owner}).
-
--record(plcSettings, {flag,
- value}).
-
--record(plcAlarm, {flag,
- value}).
-
--file("./spvcOrig.erl", 209).
-
--file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/spvcTables.hrl", 1).
-
--hrl_id('10/190 55-CNA 121 64').
-
--hrl_vsn('/main/Inc4/R2A/R3A/R3B/R5A/R6A/R7A/R7D/R8B/4').
-
--hrl_date('2003-02-12').
-
--hrl_author(etxovp).
-
--record(spvcVpc, {spvcVpcEntry,
- spvcVpcTargetAddress,
- spvcVpcTargetSelectType,
- spvcVpcTargetVpi,
- spvcVpcLastReleaseCause,
- spvcVpcLastReleaseDiagnostic,
- spvcVpcRetryInterval = 1000,
- spvcVpcRetryTimer = 0,
- spvcVpcRetryThreshold = 1,
- spvcVpcRetryFailures = 0,
- spvcVpcRetryLimit = 15,
- spvcVpcRowStatus,
- spvcVpcUserName = [],
- spvcVpcProviderName = [],
- currentState,
- crankBackCounter = 0,
- spvcVpcApplication,
- spvcRerCap = false,
- spvcRerStatus = false}).
-
--record(spvcVpcOpState, {state,
- timeOfChange}).
-
--record(spvcVpcPerm, {spvcVpcEntry,
- spvcVpcTargetAddress,
- spvcVpcTargetSelectType,
- spvcVpcTargetVpi,
- spvcVpcRetryInterval = 1000,
- spvcVpcRetryThreshold = 1,
- spvcVpcRetryLimit = 15,
- spvcVpcRowStatus,
- spvcVpcUserName,
- spvcVpcProviderName,
- spvcVpcApplication}).
-
--record(spvcVpcDyn, {spvcVpcEntry,
- spvcVpcLastReleaseCause,
- spvcVpcLastReleaseDiagnostic,
- spvcVpcRetryTimer = 0,
- spvcVpcRetryFailures = 0,
- currentState,
- crankBackCounter = 0}).
-
--record(spvcVcc, {spvcVccEntry,
- spvcVccTargetAddress,
- spvcVccTargetSelectType,
- spvcVccTargetVpi,
- spvcVccTargetVci,
- spvcVccLastReleaseCause,
- spvcVccLastReleaseDiagnostic,
- spvcVccRetryInterval = 1000,
- spvcVccRetryTimer = 0,
- spvcVccRetryThreshold = 1,
- spvcVccRetryFailures = 0,
- spvcVccRetryLimit = 15,
- spvcVccRowStatus,
- spvcVccUserName = [],
- spvcVccProviderName = [],
- currentState,
- crankBackCounter = 0,
- spvcVccTargetDlci,
- spvcVccTargetType,
- spvcVccApplication,
- spvcVccFrKey,
- spvcVccTranslationMode,
- spvcRerCap = false,
- spvcRerStatus = false}).
-
--record(spvcVccOpState, {state,
- timeOfChange}).
-
--record(spvcVccPerm, {spvcVccEntry,
- spvcVccTargetAddress,
- spvcVccTargetSelectType,
- spvcVccTargetVpi,
- spvcVccTargetVci,
- spvcVccRetryInterval = 1000,
- spvcVccRetryThreshold = 1,
- spvcVccRetryLimit = 15,
- spvcVccRowStatus,
- spvcVccUserName,
- spvcVccProviderName,
- spvcVccTargetDlci,
- spvcVccTargetType,
- spvcVccApplication,
- spvcVccFrKey,
- spvcVccTranslationMode = 2}).
-
--record(spvcVccDyn, {spvcVccEntry,
- spvcVccLastReleaseCause,
- spvcVccLastReleaseDiagnostic,
- spvcVccRetryTimer = 0,
- spvcVccRetryFailures = 0,
- currentState,
- crankBackCounter = 0}).
-
--record(spvcFailures, {dummy_key,
- spvcCallFailuresTrapEnable = 2,
- spvcNotificationInterval = 30,
- backoff_interval = 0.100000,
- delay_factor = 2,
- max_delay = 200000}).
-
--record(spvcCounters, {key,
- value}).
-
--record(spvcEventIndicator, {dummy_key,
- spvcTimerInd = 2,
- spvcSendEventInd = 2}).
-
--record(spvcIndexNext, {dummy_key,
- schedVccIndexNext = 1,
- schedVpcIndexNext = 1}).
-
--record(spvcHcIdToTp, {hcId,
- tpEntry}).
-
--record(spvcTpToHcId, {tpEntry,
- hcId,
- orig_number,
- orig_vpi,
- orig_vci,
- orig_dlci,
- frKey}).
-
--record(spvcSchedVpc, {schedVpcIndex,
- schedVpcSource,
- schedVpcTargetAddr,
- schedVpcTargetSelType,
- schedVpcTargetVpi,
- schedVpcRetryInt,
- schedVpcRetryThres,
- schedVpcRetryLimit,
- schedVpcOpTime,
- schedVpcOpInd,
- schedVpcOpStatus,
- schedVpcTimerRef,
- schedVpcRowStatus,
- schedVpcUserName,
- schedVpcProviderName,
- schedVpcFaultCause,
- schedVpcRerCap = false}).
-
--record(spvcSchedVcc, {schedVccIndex,
- schedVccSource,
- schedVccTargetAddr,
- schedVccTargetSelType,
- schedVccTargetVpi,
- schedVccTargetVci,
- schedVccRetryInt,
- schedVccRetryThres,
- schedVccRetryLimit,
- schedVccOpTime,
- schedVccOpInd,
- schedVccOpStatus,
- schedVccTimerRef,
- schedVccRowStatus,
- schedVccUserName,
- schedVccProviderName,
- schedVccFaultCause,
- schedVccRerCap = false}).
-
--record(spvcCurrAlarm, {key,
- fault_id,
- data}).
-
--record(spvcChg, {key,
- data}).
-
--record(spvcBackoff, {key,
- delay_time,
- flag}).
-
--record(spvcAutoVp, {entry,
- lastChange,
- receiveTrafficDescrIndex,
- transmitTrafficDescrIndex,
- ccIdentifier,
- connId,
- mpId,
- leafId,
- chargingIndicator = 1,
- remoteChargingInd = 1,
- chargablePartyIdentifier,
- segmentEndPoint = 2,
- rowStatus,
- castType = 1,
- connKind,
- serviceType = 2,
- endPointData,
- continuityCheck = 1,
- upcNpcMode = 2,
- preventInbandCc = 1,
- monAisRdi = 2,
- adminStatus,
- autoTarget = 1,
- schedulingFlag = 2,
- application = [],
- remoteData,
- vpccAdminStatus = 2,
- contCheckSearch = 1,
- pmSearch = 1,
- lastBuffFlagRead,
- shapingMode = 1,
- groupShapingId}).
-
--record(spvcAutoVc, {entry,
- lastChange,
- receiveTrafficDescrIndex,
- transmitTrafficDescrIndex,
- ccIdentifier,
- connId,
- mpId,
- leafId,
- chargingIndicator = 1,
- remoteChargingInd = 1,
- chargablePartyIdentifier,
- packetDiscard = 2,
- segmentEndPoint = 2,
- rowStatus,
- castType = 1,
- connKind,
- continuityCheck = 1,
- upcNpcMode = 2,
- endPointData,
- preventInbandCc = 1,
- monAisRdi = 2,
- autoTarget = 1,
- schedulingFlag = 2,
- application = [],
- remoteData,
- vcccAdminStatus = 2,
- contCheckSearch = 1,
- pmSearch = 1,
- lastBuffFlagRead,
- chargingIfChanid,
- shapingMode = 1}).
-
--record(spvcAutoAtd, {index,
- type,
- param1 = 0,
- param2 = 0,
- param3 = 0,
- param4 = 0,
- param5 = 0,
- trafficQoSClass = 0,
- rowStatus = 1,
- serviceCategory = 6,
- vcCapability = 1,
- name = [],
- userCounter = 0}).
-
--record(spvcAutoAbr, {index,
- icr,
- tbe = 16277215,
- frtt = 0,
- rdf = 11,
- rif = 11,
- nrm = 4,
- trm = 7,
- cdf = 3,
- adtf = 50,
- rowStatus = 1}).
-
--record(spvcLatestErrorCode, {key,
- errorCode}).
-
--record(spvcVcDyn, {vclEntry,
- vclCcIdentifier,
- vclConnId,
- vclMpId,
- vclLeafId}).
-
--record(spvcVpDyn, {vplEntry,
- vplCcIdentifier,
- vplConnId,
- vplMpId,
- vplLeafId}).
-
--record(spvcObj, {spvcEntry,
- spvcTargetAddress,
- spvcTargetSelectType,
- spvcTargetVpi,
- spvcTargetVci,
- spvcLastReleaseCause,
- spvcLastReleaseDiagnostic,
- spvcRetryInterval = 1000,
- spvcRetryTimer = 0,
- spvcRetryThreshold = 1,
- spvcRetryFailures = 0,
- spvcRetryLimit = 15,
- spvcRowStatus,
- spvcUserName,
- spvcProviderName,
- currentState,
- spvcTargetDlci,
- spvcTargetType,
- spvcApplication,
- spvcFrKey,
- spvcVccTranslationMode = 2,
- spvcRerCap = false,
- spvcRerStatus = false}).
-
--record(spvcTargetVc, {entry,
- userName = [],
- providerName = [],
- opState,
- rowStatus}).
-
--record(spvcTargetVp, {entry,
- userName = [],
- providerName = [],
- opState,
- rowStatus}).
-
--record(spvcReestablishTimer, {time,
- timer_id,
- module,
- function,
- args}).
-
--record(spvcRerVp, {entry,
- rerCap,
- rerData}).
-
--record(spvcRerVc, {entry,
- rerCap,
- rerData}).
-
--record(spvcHcEtStat, {key,
- counter = 0}).
-
--record(spvcSaEtStat, {key,
- counter = 0}).
-
--file("./spvcOrig.erl", 210).
-
--file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/spvcDefines.hrl", 1).
-
--hrl_id('41/190 55-CNA 121 64 Ux').
-
--hrl_vsn('/main/R6A/R7A/R7D/R8B/3').
-
--hrl_date('2003-02-21').
-
--hrl_author(etxhebl).
-
--file("./spvcOrig.erl", 211).
-
--file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/spvcFr.hrl", 1).
-
--hrl_id('48/190 55-CNA 121 64 Ux').
-
--hrl_vsn('/main/R7A/R7D/2').
-
--hrl_date('2001-12-06').
-
--hrl_author(etxhtb).
-
--record(spvcFr, {spvcFrEntry,
- spvcFrAtmEntry,
- spvcFrTargetAddress,
- spvcFrTargetSelectType,
- spvcFrTargetIdentifier,
- spvcFrTargetVpi,
- spvcFrTargetVci,
- spvcFrAtmTranslation,
- spvcFrLastReleaseCause,
- spvcFrLastReleaseDiagnostic,
- spvcFrAdminStatus,
- spvcFrRetryInterval = 1000,
- spvcFrRetryTimer = 0,
- spvcFrRetryThreshold = 1,
- spvcFrRetryFailures = 0,
- spvcFrRetryLimit = 15,
- spvcFrRowStatus,
- spvcFrUserName,
- spvcFrProviderName,
- currentState}).
-
--record(spvcFrPerm, {spvcFrEntry,
- spvcFrAtmEntry,
- spvcFrAtmTranslation,
- spvcFrAdminStatus,
- spvcFrConnect}).
-
--record(spvcFrAddress, {addressEntry,
- addressRowStatus}).
-
--record(spvcFrAddressToIf, {address,
- if_index}).
-
--record(fr_end_point, {ifIndex,
- dlci}).
-
--record(fr_atm_translation, {routedIp = off,
- routedOsi = off,
- otherRouted = off,
- arpTranslation = off}).
-
--record(link_layer_core_parameters, {outgoing_max_ifs,
- incoming_max_ifs}).
-
--record(priority_and_service_class, {outgoing_transfer_priority,
- incoming_transfer_priority,
- outgoing_discard_priority,
- incoming_discard_priority}).
-
--file("./spvcOrig.erl", 212).
-
--file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../derived_hrl/mib/AXD301-PCH-MIB.hrl", 1).
-
--file("./spvcOrig.erl", 213).
-
--file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../derived_hrl/mib/AXD301-SPVC-MIB.hrl", 1).
-
--file("./spvcOrig.erl", 214).
-
--file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../derived_hrl/mib/AXD301-FRSPVC-MIB.hrl", 1).
-
--file("./spvcOrig.erl", 215).
-
--file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/sysDefines.hrl", 1).
-
--hrl_id('3/190 55-CNA 121 70').
-
--hrl_vsn('/main/Inc3/Inc4/Inc5/R3B/R4A/R5B/R6A/R7A/R8B/2').
-
--hrl_date('2002-06-07').
-
--hrl_author(etxjotj).
-
--file("./spvcOrig.erl", 216).
-
--file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/hciMsg.hrl", 1).
-
--hrl_id('4/190 55-CNA 121 159 Ux').
-
--hrl_vsn('/main/R7A/R8B/10').
-
--hrl_date('2003-02-21').
-
--hrl_author(etxmexa).
-
--file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/hciComp.hrl", 1).
-
--hrl_id('3/190 55-CNA 121 159 Ux').
-
--hrl_vsn('/main/R7A/1').
-
--hrl_date('00-03-22').
-
--hrl_author(etxmexa).
-
--record(hci_comp_info, {required_FC = 0,
- desired_FC = 0}).
-
--record(hci_comp_res, {not_supported_required_FCs,
- not_supported_desired_FCs,
- all_supported_FCs}).
-
--file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/hciMsg.hrl", 14).
-
--record(hci_add_party, {hci_cpn,
- hci_aal,
- hci_bhli,
- hci_blli,
- hci_blli_bici,
- hci_bsco,
- hci_epr,
- hci_e2etd,
- hci_noti,
- hci_cpsa,
- hci_clpn,
- hci_clpsa,
- hci_cpn_soft,
- hci_clpn_soft,
- hci_geidt_list = [],
- hci_dtl_bin_list = [],
- hci_pa_list = [],
- hci_gat_list = [],
- hci_data,
- hci_prot_comp}).
-
--record(hci_add_party_ack, {hci_epr,
- hci_aal,
- hci_blli,
- hci_blli_bici,
- hci_e2etd,
- hci_noti,
- hci_cpn_soft,
- hci_cnosa,
- hci_cno,
- hci_geidt_list = [],
- hci_pa_list = [],
- hci_gat_list = [],
- hci_data,
- hci_prot_comp}).
-
--record(hci_add_party_rej, {hci_cause,
- hci_epr,
- hci_geidt_list = [],
- hci_cb,
- hci_pa_list = [],
- hci_internal_rel_info,
- hci_gat_list = [],
- hci_data,
- hci_prot_comp}).
-
--record(hci_alerting, {hci_mci,
- hci_unrps,
- hci_cdpi,
- hci_epr,
- hci_prog_list = [],
- hci_nbc,
- hci_nbhlc,
- hci_noti,
- hci_geidt_list = [],
- hci_pa_list = [],
- hci_gat_list = [],
- hci_ssie,
- hci_data,
- hci_prot_comp}).
-
--record(hci_b_resources, {hci_rem_dataB,
- hci_vpiB,
- hci_vciB,
- hci_data,
- hci_prot_comp}).
-
--record(hci_connect, {hci_mci,
- hci_unrps,
- hci_aal,
- hci_blli,
- hci_blli_bici,
- hci_epr,
- hci_atd,
- hci_e2etd,
- hci_noti,
- hci_abrs,
- hci_abra,
- hci_nbc,
- hci_nbhlc,
- hci_nbllc,
- hci_prog_list = [],
- hci_geidt_list = [],
- hci_eqos,
- hci_cpn_soft,
- hci_cnosa,
- hci_cno,
- hci_pa_list = [],
- hci_gat_list = [],
- hci_rem_dataB,
- hci_con_dir = both,
- hci_ssie,
- hci_rer_services,
- hci_rer,
- hci_opt_traf,
- hci_data,
- hci_prot_comp}).
-
--record(hci_drop_party, {hci_cause,
- hci_epr,
- hci_noti,
- hci_geidt_list = [],
- hci_pa_list = [],
- hci_internal_rel_info,
- hci_gat_list = [],
- hci_data,
- hci_prot_comp}).
-
--record(hci_local_connect, {hci_rem_data,
- hci_con_dir,
- hci_data,
- hci_prot_comp}).
-
--record(hci_local_connected, {hci_rem_data,
- hci_con_dir,
- hci_data,
- hci_prot_comp}).
-
--record(hci_local_disconnect, {hci_discon_dir,
- hci_data,
- hci_prot_comp}).
-
--record(hci_local_disconnected, {hci_data,
- hci_prot_comp}).
-
--record(hci_notify, {hci_epr,
- hci_noti,
- hci_pa_list = [],
- hci_gat_list = [],
- hci_data,
- hci_prot_comp}).
-
--record(hci_party_alerting, {hci_epr,
- hci_noti,
- hci_geidt_list = [],
- hci_pa_list = [],
- hci_gat_list = [],
- hci_data,
- hci_prot_comp}).
-
--record(hci_progress, {hci_mci,
- hci_unrps,
- hci_cdpi,
- hci_prog_list = [],
- hci_nbc,
- hci_nbhlc,
- hci_noti,
- hci_pa_list = [],
- hci_gat_list = [],
- hci_data,
- hci_prot_comp}).
-
--record(hci_release, {hci_mci,
- hci_unrps,
- hci_cause_list = [],
- hci_noti,
- hci_prog_list = [],
- hci_geidt_list = [],
- hci_cb,
- hci_pa_list = [],
- hci_internal_rel_info,
- hci_gat_list = [],
- hci_ssie,
- hci_rer_cause,
- hci_data,
- hci_prot_comp,
- hci_internal_dbg_cc,
- hci_internal_dbg_l3}).
-
--record(hci_setup, {hci_mci,
- hci_unrps,
- hci_atd,
- hci_bbc,
- hci_qos,
- hci_cpn,
- hci_aal,
- hci_bhli,
- hci_blli_brep,
- hci_blli_bici,
- hci_bsco,
- hci_epr,
- hci_lpt,
- hci_e2etd,
- hci_noti,
- hci_abrs,
- hci_abra,
- hci_prog_list = [],
- hci_eqos,
- hci_cpsa_list = [],
- hci_clpn,
- hci_bici_clpn,
- hci_clpsa_list = [],
- hci_cgpc,
- hci_nbc_brep,
- hci_nbhlc_list = [],
- hci_nbllc_brep,
- hci_conss,
- hci_geidt_list = [],
- hci_cpn_soft,
- hci_clpn_soft,
- hci_dtl_bin_list = [],
- hci_pa_list = [],
- hci_ncci,
- hci_routing_address,
- hci_protocol_internal_info,
- hci_gat_list = [],
- hci_con_dir = both,
- hci_ssie,
- hci_rer_services,
- hci_rer,
- hci_opt_traf,
- hci_data_setup,
- hci_prot_comp}).
-
--record(hci_setup_ack, {hci_assign,
- hci_rem_dataB,
- hci_con_dir = both,
- hci_vpiB,
- hci_vciB,
- hci_data,
- hci_prot_comp}).
-
--record(hci_status, {hci_state,
- hci_data,
- hci_prot_comp}).
-
--record(hci_status_enq, {hci_state,
- hci_data,
- hci_prot_comp}).
-
--record(hci_remote_data, {hci_prot_type,
- hci_data,
- hci_dummy1,
- hci_dummy2}).
-
--record(hci_unrec, {hci_mci,
- hci_head,
- hci_binary,
- hci_data,
- hci_prot_comp}).
-
--record(hci_atd, {hci_pci,
- hci_apci,
- hci_fwd_pcr_clp_0,
- hci_bwd_pcr_clp_0,
- hci_fwd_pcr_clp_0_1,
- hci_bwd_pcr_clp_0_1,
- hci_fwd_scr_clp_0,
- hci_bwd_scr_clp_0,
- hci_fwd_scr_clp_0_1,
- hci_bwd_scr_clp_0_1,
- hci_fwd_mbs_clp_0,
- hci_bwd_mbs_clp_0,
- hci_fwd_mbs_clp_0_1,
- hci_bwd_mbs_clp_0_1,
- hci_best_effort_ind = 0,
- hci_fwd_frame_discard = 0,
- hci_bwd_frame_discard = 0,
- hci_tagging_bwd = 0,
- hci_tagging_fwd = 0,
- hci_fwd_abr_mcr,
- hci_bwd_abr_mcr,
- hci_binary}).
-
--record(hci_bbc, {hci_pci,
- hci_bearer_class,
- hci_atm_transfer_capability,
- hci_user_plane_connection_configuration,
- hci_susceptibility_to_clipping,
- hci_binary}).
-
--record(hci_cause, {hci_pci,
- hci_location,
- hci_cause_value,
- hci_diagnostics_list = [],
- hci_binary}).
-
--record(hci_cpn, {hci_pci,
- hci_type_of_number,
- hci_intern_netw_numb_indic,
- hci_numbering_plan_indicator,
- hci_number_digits,
- hci_orig_native = false}).
-
--record(hci_clpn, {hci_pci,
- hci_type_of_number,
- hci_numbering_plan_indicator,
- hci_presentation_indicator,
- hci_screening_indicator,
- hci_number_digits,
- hci_incomplete_indicator = 0,
- hci_binary}).
-
--record(hci_cno, {hci_type_of_number,
- hci_numbering_plan_indicator,
- hci_presentation_indicator,
- hci_screening_indicator,
- hci_number_digits,
- hci_binary}).
-
--record(hci_cnosa, {hci_binary}).
-
--record(hci_cpn_soft, {hci_select_type,
- hci_soft_vpi,
- hci_soft_vci,
- hci_soft_dlci,
- hci_binary}).
-
--record(hci_clpn_soft, {hci_soft_vpi,
- hci_soft_vci,
- hci_soft_dlci,
- hci_binary}).
-
--record(hci_rer_services, {hci_inter_req_hard,
- hci_inter_cap_hard,
- hci_intra_req_soft,
- hci_intra_req_hard,
- hci_intra_cap_asym,
- hci_intra_cap_sym,
- hci_intra_cap_hard,
- hci_binary}).
-
--record(hci_rer, {hci_func_addr,
- hci_endpoint_key,
- hci_switchover,
- hci_incarnation,
- hci_pnni_cumul_fw_max_cell_td,
- hci_cumul_fw_p2p_cdv,
- hci_cumul_bw_p2p_cdv,
- hci_binary}).
-
--record(hci_rer_cause, {hci_rer_rel_cause,
- hci_binary}).
-
--record(hci_opt_traf, {hci_origin,
- hci_cumul_fw_aw,
- hci_cumul_bw_aw,
- hci_binary}).
-
--record(hci_qos, {hci_pci,
- hci_qos_class_fwd,
- hci_qos_class_bwd,
- hci_binary}).
-
--record(hci_aal, {hci_pci,
- hci_binary}).
-
--record(hci_bhli, {hci_pci,
- hci_binary}).
-
--record(hci_blli_brep, {hci_brep,
- hci_blli_list = []}).
-
--record(hci_blli, {hci_binary}).
-
--record(hci_blli_bici, {hci_repeated,
- hci_priority,
- hci_pci,
- hci_binary}).
-
--record(hci_cpsa, {hci_pci,
- hci_binary}).
-
--record(hci_clpsa, {hci_pci,
- hci_binary}).
-
--record(hci_gat, {hci_binary}).
-
--record(hci_epr, {hci_epr_type,
- hci_epr_value,
- hci_epr_flag,
- hci_binary}).
-
--record(hci_eqos, {hci_origin,
- hci_acc_fwd_p2p_cdv,
- hci_acc_bwd_p2p_cdv,
- hci_cum_fwd_p2p_cdv,
- hci_cum_bwd_p2p_cdv,
- hci_acc_fwd_clr,
- hci_acc_bwd_clr,
- hci_binary}).
-
--record(hci_brep, {hci_binary}).
-
--record(hci_bsco, {hci_binary}).
-
--record(hci_noti, {hci_binary}).
-
--record(hci_abrs, {hci_fwd_abr_icr,
- hci_bwd_abr_icr,
- hci_fwd_abr_tbe,
- hci_bwd_abr_tbe,
- hci_cum_rm_fix_round_trip,
- hci_fwd_rif,
- hci_bwd_rif,
- hci_fwd_rdf,
- hci_bwd_rdf,
- hci_binary}).
-
--record(hci_abra, {hci_fwd_nrm,
- hci_fwd_trm,
- hci_fwd_cdf,
- hci_fwd_atdf,
- hci_bwd_nrm,
- hci_bwd_trm,
- hci_bwd_cdf,
- hci_bwd_atdf,
- hci_binary}).
-
--record(hci_prog, {hci_coding_std,
- hci_location,
- hci_prog_desc,
- hci_binary}).
-
--record(hci_nbc_brep, {hci_brep,
- hci_nbc_list = []}).
-
--record(hci_nbc, {hci_binary}).
-
--record(hci_nbhlc, {hci_binary}).
-
--record(hci_nbllc_brep, {hci_brep,
- hci_nbllc_list = []}).
-
--record(hci_nbllc, {hci_binary}).
-
--record(hci_geidt, {hci_binary}).
-
--record(hci_conss, {hci_type_of_conn_scope,
- hci_conn_scope,
- hci_binary}).
-
--record(hci_e2etd, {hci_pci,
- hci_cumul_td,
- hci_max_td,
- hci_pnni_cumul_td,
- hci_pnni_accept_fwd_max_td,
- hci_netw_gen}).
-
--record(hci_cdpi, {hci_pci,
- hci_cdpci,
- hci_cdpsi,
- hci_binary}).
-
--record(hci_cgpc, {hci_pci,
- hci_binary}).
-
--record(hci_lpt, {hci_pci,
- hci_ptype}).
-
--record(hci_cb, {hci_cb_level,
- hci_bl_transit_type,
- hci_bl_node_id,
- hci_bl_link_proc_node_id,
- hci_bl_link_port_id,
- hci_bl_link_succ_node_id,
- cause_value,
- hci_cb_diagnostics,
- hci_binary}).
-
--record(hci_pa, {hci_ie_id,
- hci_coding,
- hci_action,
- hci_length,
- hci_binary,
- hci_error_type}).
-
--record(hci_ncci, {hci_pci,
- hci_ni,
- hci_point_code,
- hci_call_id}).
-
--record(hci_ssie, {hci_ssie_sas = [],
- hci_binary}).
-
--record(hci_sas, {hci_sas_vsn,
- hci_sas_transp_ind,
- hci_sas_flow_ind,
- hci_sas_discard,
- hci_sas_scope,
- hci_sas_relative_id,
- hci_binary}).
-
--record(hci_data, {hci_hcid,
- hci_sender_ifindex,
- hci_sender_hcid}).
-
--record(hci_data_setup, {hci_hcidA,
- hci_pidA,
- hci_protA,
- hci_protB,
- hci_portB,
- hci_hcidB,
- hci_rem_dataA,
- hci_assign,
- hci_ifindexB,
- hci_node_id,
- hci_succ_node_id,
- hci_ifindexA,
- hci_vpiA,
- hci_vciA,
- hci_cpA,
- hci_cpB}).
-
--record(hci_prot_comp, {hci_requiredFC = 0,
- hci_desiredFC = 0}).
-
--file("./spvcOrig.erl", 217).
-
--file("/export/localhome/locmacr/wrk/axd_r11/ATS_CRA12002/SPVC_CNA12164/src/../../../inc/ccCd.hrl", 1).
-
--hrl_id('13/190 55-CNA 121 101 Ux').
-
--hrl_vsn('/main/R6A/R7A/R8A/R8B/8').
-
--hrl_date('2003-02-21').
-
--hrl_author(etxmexa).
-
--record(ccCdRR, {hcid,
- vpi,
- vci,
- ifindexA,
- call_type,
- spvc = false,
- reserve = yes,
- etA,
- destdata,
- leafdata,
- loopdata,
- l3,
- l3_loop,
- cc}).
-
--record(ccCdRD, {destid,
- loopdata,
- cc}).
-
--record(ccCdRL, {leafid,
- protTypeB,
- loopdata,
- l3,
- l3_loop,
- cc}).
-
--record(ccCdDD, {hcid,
- hcidA,
- vpi,
- vci,
- ifindexB,
- portB,
- call_type,
- spvc = false,
- reserve = yes,
- protTypeA,
- etB,
- leafdata,
- loopdata,
- l3,
- l3_loop,
- cc}).
-
--record(ccCdDL, {leafid,
- loopdata,
- l3,
- l3_loop,
- cc}).
-
--record(ccRR, {protTypeA,
- remote_dataA,
- remote_dataB,
- chg_counters,
- sc,
- chg_decision = on,
- cc_loop}).
-
--record(ccRL, {hcidB,
- charging,
- cc_loop}).
-
--record(ccRD, {portB,
- ifindexB,
- cpB,
- vpiB,
- vciB,
- cc_loop}).
-
--record(ccDD, {protTypeB,
- remote_dataA,
- remote_dataB,
- ifindexA,
- cpA,
- vpiA,
- vciA,
- chg_counters,
- sc,
- chg_decision = on,
- cc_loop}).
-
--record(ccDL, {cc_loop}).
-
--record(loopRR, {vpList,
- nodeid,
- succ_nodeid,
- connection_type,
- policing,
- delay_contrib,
- charging = on,
- prev_routing_data}).
-
--record(loopRD, {}).
-
--record(loopRL, {msg_rec,
- providerName,
- userName,
- partyId,
- serviceIfA,
- serviceIdA,
- serviceIfB,
- serviceIdB,
- estAw,
- dtlLevels}).
-
--record(loopDD, {nodeid,
- succ_nodeid,
- vpList,
- connection_type,
- policing,
- assign,
- delay_contrib,
- charging = on}).
-
--record(loopDL, {msg_rec,
- providerName,
- userName,
- partyId,
- serviceIfA,
- serviceIdA,
- serviceIfB,
- serviceIdB}).
-
--record(ccLoopRR, {pidB,
- qos,
- atd,
- bbc,
- cscope,
- e2etd,
- eqos,
- con_state = none,
- con_order = both,
- mr_flag,
- catch_up_id,
- cpA}).
-
--record(ccLoopRD, {}).
-
--record(ccLoopRL, {route,
- linklist,
- routelist,
- failurelist = [],
- nodeidlist,
- cb,
- cpn,
- dtl,
- routing_state,
- assign,
- timer_counter = 0,
- timer_ref,
- status_enq_ind,
- link_CB,
- node_CB,
- pnnir_rlp,
- pnni_only}).
-
--record(ccLoopDD, {pidA,
- con_state = none,
- con_order = both,
- mr_flag,
- catch_up_id,
- cpB}).
-
--record(ccLoopDL, {timer_counter = 0,
- timer_ref,
- status_enq_ind}).
-
--file("./spvcOrig.erl", 218).
-
--file("/export/localhome/locmacr/built/lib/erlang/lib/snmp-4.1.2/include/STANDARD-MIB.hrl", 1).
-
--file("./spvcOrig.erl", 219).
-
-error_handler({From,Tag},{M,F,Args},EXITReason) ->
- spvcLib:do_report(sccm,M,F,Args,"",EXITReason).
-
-connect(HcId,Connect,Key) ->
- debug_disabled,
- Obj = spvcDataBase:db_read({spvcObj,Key}),
- orig_state_machine(Obj#spvcObj.currentState,connect_nu,Obj,[HcId,Connect]).
-
-release_nu(HcId,Release,Key) ->
- debug_disabled,
- Obj = spvcDataBase:db_read({spvcObj,Key}),
- spvcDataBase:db_delete({spvcHcIdToTp,HcId}),
- orig_state_machine(Obj#spvcObj.currentState,release_nu,Obj,[HcId,Release]).
-
-release_comp_nu(HcId,Release_comp,Key) ->
- debug_disabled,
- Obj = spvcDataBase:db_read({spvcObj,Key}),
- spvcDataBase:db_delete({spvcHcIdToTp,HcId}),
- orig_state_machine(Obj#spvcObj.currentState,release_comp_nu,Obj,[HcId,Release_comp]).
-
-release_incumbent(HcId,Release) ->
- debug_disabled,
- release_incumbent2(spvcDataBase:db_read({spvcHcIdToTp,HcId}),Release).
-
-release_incumbent2(SpvcHcIdToTp,Release) ->
- release_incumbent3(SpvcHcIdToTp#spvcHcIdToTp.tpEntry,Release).
-
-release_incumbent3({orig,If,Vpi,Vci,Leaf},Release) ->
- release_incumbent4({If,Vpi,Vci,Leaf},Release);
-release_incumbent3({orig,If,Vpi,Leaf},Release) ->
- release_incumbent4({If,Vpi,Leaf},Release).
-
-release_incumbent4(TpKey,Release) ->
- Spvc = spvcDataBase:db_read({spvcObj,TpKey}),
- active = Spvc#spvcObj.currentState,
- orig_state_machine(active,release_incumbent,Spvc,[Release]).
-
-switch_over(HcId,{If,Vpi,Vci}) ->
- Key = case {If,Vpi,Vci} of
- {If_Value,Vpi_Value,Vci_Value} when integer(Vci_Value) ->
- {If_Value,Vpi_Value,Vci_Value,1};
- {If_Value,Vpi_Value,_} ->
- {If_Value,Vpi_Value,1};
- {If_Value,Vpi_Value} ->
- {If_Value,Vpi_Value,1}
- end,
- Spvc = spvcDataBase:db_read({spvcObj,Key}),
- do_switch_over(HcId,Spvc);
-switch_over(HcId,{If,Vpi}) ->
- Key = case {If,Vpi,no_vc} of
- {If_Value,Vpi_Value,Vci_Value} when integer(Vci_Value) ->
- {If_Value,Vpi_Value,Vci_Value,1};
- {If_Value,Vpi_Value,_} ->
- {If_Value,Vpi_Value,1};
- {If_Value,Vpi_Value} ->
- {If_Value,Vpi_Value,1}
- end,
- Spvc = spvcDataBase:db_read({spvcObj,Key}),
- do_switch_over(HcId,Spvc).
-
-do_switch_over(HcId,Spvc) ->
- State = Spvc#spvcObj.currentState,
- orig_state_machine(State,switch_over,Spvc,[HcId]).
-
-gen_set(Type,Row,Cols) ->
- debug_disabled,
- gen_set(Type,Row,Cols,undefined).
-
-gen_set(Type,Row,Cols,FrKey) ->
- debug_disabled,
- case lists:keysearch(case {case Row of
- {_,_,_,_} ->
- spvcVcc;
- {_,_,_} ->
- spvcVpc;
- {_,_} ->
- spvcFr;
- [_,_,_,_] ->
- spvcVcc;
- [_,_,_] ->
- spvcVpc;
- [_,_] ->
- spvcFr
- end,rowStatus} of
- {spvcVcc,targetAddress} ->
- 2;
- {spvcVcc,selectType} ->
- 3;
- {spvcVcc,targetVpi} ->
- 18;
- {spvcVcc,targetVci} ->
- 5;
- {spvcVcc,releaseCause} ->
- 6;
- {spvcVcc,releaseDiagnostic} ->
- 7;
- {spvcVcc,retryInterval} ->
- 10;
- {spvcVcc,retryTimer} ->
- 11;
- {spvcVcc,retryThreshold} ->
- 12;
- {spvcVcc,retryFailures} ->
- 13;
- {spvcVcc,retryLimit} ->
- 14;
- {spvcVcc,rowStatus} ->
- 15;
- {spvcVcc,restart} ->
- 9;
- {spvcVcc,targetSelectType_any} ->
- 2;
- {spvcVcc,targetSelectType_required} ->
- 1;
- {spvcVpc,targetAddress} ->
- 2;
- {spvcVpc,selectType} ->
- 3;
- {spvcVpc,targetVpi} ->
- 15;
- {spvcVpc,releaseCause} ->
- 5;
- {spvcVpc,releaseDiagnostic} ->
- 6;
- {spvcVpc,retryInterval} ->
- 9;
- {spvcVpc,retryTimer} ->
- 10;
- {spvcVpc,retryThreshold} ->
- 11;
- {spvcVpc,retryFailures} ->
- 12;
- {spvcVpc,retryLimit} ->
- 13;
- {spvcVpc,rowStatus} ->
- 14;
- {spvcVpc,restart} ->
- 8;
- {spvcVpc,targetSelectType_any} ->
- 2;
- {spvcVpc,targetSelectType_required} ->
- 1;
- {spvcFr,targetAddress} ->
- 3;
- {spvcFr,selectType} ->
- 5;
- {spvcFr,identifier} ->
- 6;
- {spvcFr,targetVpi} ->
- 7;
- {spvcFr,targetVci} ->
- 8;
- {spvcFr,translation} ->
- 9;
- {spvcFr,releaseCause} ->
- 10;
- {spvcFr,releaseDiagnostic} ->
- 11;
- {spvcFr,operStatus} ->
- 12;
- {spvcFr,adminStatus} ->
- 13;
- {spvcFr,restart} ->
- 14;
- {spvcFr,retryInterval} ->
- 15;
- {spvcFr,retryTimer} ->
- 16;
- {spvcFr,retryThreshold} ->
- 17;
- {spvcFr,retryFailures} ->
- 18;
- {spvcFr,retryLimit} ->
- 19;
- {spvcFr,lastChange} ->
- 20;
- {spvcFr,rowStatus} ->
- 21
- end,1,Cols) of
- {value,{_,4}} ->
- debug_disabled,
- mnesia:dirty_update_counter(spvcHcEtStat,spvcLib:get_board(hd(Row)),1),
- case get_link_state(case Row of
- Row when record(Row,spvcObj) ->
- case Row#spvcObj.spvcEntry of
- {If_Value,_,_,_} ->
- If_Value;
- {If_Value,_,_} ->
- If_Value
- end;
- Row when record(Row,spvcVcc) ->
- {If_Value,_,_,_} = Row#spvcVcc.spvcVccEntry,
- If_Value;
- Row when record(Row,spvcVpc) ->
- {If_Value,_,_} = Row#spvcVpc.spvcVpcEntry,
- If_Value;
- Row when record(Row,spvcVpcPerm) ->
- {If_Value,_,_} = Row#spvcVpcPerm.spvcVpcEntry,
- If_Value;
- Row when record(Row,spvcVccPerm) ->
- {If_Value,_,_,_} = Row#spvcVccPerm.spvcVccEntry,
- If_Value;
- Row when record(Row,spvcTargetVc) ->
- {If_Value,_,_} = Row#spvcTargetVc.entry,
- If_Value;
- Row when record(Row,spvcTargetVp) ->
- {If_Value,_} = Row#spvcTargetVp.entry,
- If_Value;
- Row when record(Row,pchVc) ->
- {If_Value,_,_} = Row#pchVc.vclEntry,
- If_Value;
- Row when record(Row,pchVp) ->
- {If_Value,_} = Row#pchVp.vplEntry,
- If_Value;
- Row when record(Row,spvcFr) ->
- {If_Value,_} = Row#spvcFr.spvcFrEntry,
- If_Value;
- Row when record(Row,spvcFrPerm) ->
- {If_Value,_} = Row#spvcFrPerm.spvcFrEntry,
- If_Value;
- {If_Value,_,_,_} ->
- If_Value;
- {If_Value,_,_} ->
- If_Value;
- {If_Value,_} ->
- If_Value;
- [If_Value|_] ->
- If_Value;
- _ ->
- error
- end) of
- disabled ->
- orig_state_machine(null,createAndGo_disabled,[],[Row,Cols,Type,FrKey]);
- enabled ->
- orig_state_machine(null,createAndGo_enabled,[],[Row,Cols,Type,FrKey])
- end;
- {value,{_,5}} ->
- debug_disabled,
- mnesia:dirty_update_counter(spvcHcEtStat,spvcLib:get_board(hd(Row)),1),
- orig_state_machine(null,createAndWait,[],[Row,Cols,Type,FrKey]);
- {value,{_,1}} ->
- debug_disabled,
- case spvcDataBase:db_read({spvcObj,list_to_tuple(Row)}) of
- [] ->
- ok;
- Spvc ->
- case get_link_state(case Row of
- Row when record(Row,spvcObj) ->
- case Row#spvcObj.spvcEntry of
- {If_Value,_,_,_} ->
- If_Value;
- {If_Value,_,_} ->
- If_Value
- end;
- Row when record(Row,spvcVcc) ->
- {If_Value,_,_,_} = Row#spvcVcc.spvcVccEntry,
- If_Value;
- Row when record(Row,spvcVpc) ->
- {If_Value,_,_} = Row#spvcVpc.spvcVpcEntry,
- If_Value;
- Row when record(Row,spvcVpcPerm) ->
- {If_Value,_,_} = Row#spvcVpcPerm.spvcVpcEntry,
- If_Value;
- Row when record(Row,spvcVccPerm) ->
- {If_Value,_,_,_} = Row#spvcVccPerm.spvcVccEntry,
- If_Value;
- Row when record(Row,spvcTargetVc) ->
- {If_Value,_,_} = Row#spvcTargetVc.entry,
- If_Value;
- Row when record(Row,spvcTargetVp) ->
- {If_Value,_} = Row#spvcTargetVp.entry,
- If_Value;
- Row when record(Row,pchVc) ->
- {If_Value,_,_} = Row#pchVc.vclEntry,
- If_Value;
- Row when record(Row,pchVp) ->
- {If_Value,_} = Row#pchVp.vplEntry,
- If_Value;
- Row when record(Row,spvcFr) ->
- {If_Value,_} = Row#spvcFr.spvcFrEntry,
- If_Value;
- Row when record(Row,spvcFrPerm) ->
- {If_Value,_} = Row#spvcFrPerm.spvcFrEntry,
- If_Value;
- {If_Value,_,_,_} ->
- If_Value;
- {If_Value,_,_} ->
- If_Value;
- {If_Value,_} ->
- If_Value;
- [If_Value|_] ->
- If_Value;
- _ ->
- error
- end) of
- disabled ->
- orig_state_machine(Spvc#spvcObj.currentState,activate_disabled,Spvc,Cols);
- enabled ->
- orig_state_machine(Spvc#spvcObj.currentState,activate_enabled,Spvc,Cols)
- end
- end;
- {value,{_,6}} ->
- debug_disabled,
- case spvcDataBase:db_read({spvcObj,list_to_tuple(Row)}) of
- [] ->
- ok;
- Spvc ->
- mnesia:dirty_update_counter(spvcHcEtStat,spvcLib:get_board(hd(Row)),- 1),
- orig_state_machine(Spvc#spvcObj.currentState,destroy,Spvc,Cols)
- end;
- {value,{_,2}} ->
- debug_disabled,
- case spvcDataBase:db_read({spvcObj,list_to_tuple(Row)}) of
- [] ->
- mnesia:dirty_update_counter(spvcHcEtStat,spvcLib:get_board(hd(Row)),1),
- ok;
- Spvc ->
- orig_state_machine(Spvc#spvcObj.currentState,not_in_service,Spvc,Cols)
- end;
- false ->
- debug_disabled,
- Spvc = spvcDataBase:db_read({spvcObj,list_to_tuple(Row)}),
- CurrentState = Spvc#spvcObj.currentState,
- NewSpvc = set_attrs(Spvc,Cols),
- Restart = case {case Row of
- {_,_,_,_} ->
- spvcVcc;
- {_,_,_} ->
- spvcVpc;
- {_,_} ->
- spvcFr;
- [_,_,_,_] ->
- spvcVcc;
- [_,_,_] ->
- spvcVpc;
- [_,_] ->
- spvcFr
- end,restart} of
- {spvcVcc,targetAddress} ->
- 2;
- {spvcVcc,selectType} ->
- 3;
- {spvcVcc,targetVpi} ->
- 18;
- {spvcVcc,targetVci} ->
- 5;
- {spvcVcc,releaseCause} ->
- 6;
- {spvcVcc,releaseDiagnostic} ->
- 7;
- {spvcVcc,retryInterval} ->
- 10;
- {spvcVcc,retryTimer} ->
- 11;
- {spvcVcc,retryThreshold} ->
- 12;
- {spvcVcc,retryFailures} ->
- 13;
- {spvcVcc,retryLimit} ->
- 14;
- {spvcVcc,rowStatus} ->
- 15;
- {spvcVcc,restart} ->
- 9;
- {spvcVcc,targetSelectType_any} ->
- 2;
- {spvcVcc,targetSelectType_required} ->
- 1;
- {spvcVpc,targetAddress} ->
- 2;
- {spvcVpc,selectType} ->
- 3;
- {spvcVpc,targetVpi} ->
- 15;
- {spvcVpc,releaseCause} ->
- 5;
- {spvcVpc,releaseDiagnostic} ->
- 6;
- {spvcVpc,retryInterval} ->
- 9;
- {spvcVpc,retryTimer} ->
- 10;
- {spvcVpc,retryThreshold} ->
- 11;
- {spvcVpc,retryFailures} ->
- 12;
- {spvcVpc,retryLimit} ->
- 13;
- {spvcVpc,rowStatus} ->
- 14;
- {spvcVpc,restart} ->
- 8;
- {spvcVpc,targetSelectType_any} ->
- 2;
- {spvcVpc,targetSelectType_required} ->
- 1;
- {spvcFr,targetAddress} ->
- 3;
- {spvcFr,selectType} ->
- 5;
- {spvcFr,identifier} ->
- 6;
- {spvcFr,targetVpi} ->
- 7;
- {spvcFr,targetVci} ->
- 8;
- {spvcFr,translation} ->
- 9;
- {spvcFr,releaseCause} ->
- 10;
- {spvcFr,releaseDiagnostic} ->
- 11;
- {spvcFr,operStatus} ->
- 12;
- {spvcFr,adminStatus} ->
- 13;
- {spvcFr,restart} ->
- 14;
- {spvcFr,retryInterval} ->
- 15;
- {spvcFr,retryTimer} ->
- 16;
- {spvcFr,retryThreshold} ->
- 17;
- {spvcFr,retryFailures} ->
- 18;
- {spvcFr,retryLimit} ->
- 19;
- {spvcFr,lastChange} ->
- 20;
- {spvcFr,rowStatus} ->
- 21
- end,
- case lists:keysearch(Restart,1,Cols) of
- {value,{Restart,1}} ->
- orig_state_machine(CurrentState,restart,NewSpvc,Cols);
- _ ->
- spvcDataBase:db_write(NewSpvc),
- ok
- end
- end,
- {noError,0}.
-
-restart_spvc(Key) ->
- debug_disabled,
- Spvc = spvcDataBase:db_read({spvcObj,Key}),
- handle_restart_spvc(Spvc#spvcObj.currentState,Spvc),
- ok.
-
-handle_restart_spvc(rest_in_peace,Spvc) ->
- debug_disabled,
- rest_in_peace(restart,Spvc,undefined);
-handle_restart_spvc(_,_) ->
- ok.
-
-restart_multi_spvcs(Key) ->
- debug_disabled,
- Spvc = spvcDataBase:db_read({spvcObj,Key}),
- handle_restart_multi_spvcs(Spvc#spvcObj.currentState,Spvc),
- ok.
-
-handle_restart_multi_spvcs(rest_in_peace,Spvc) ->
- debug_disabled,
- handle_restart_spvc(rest_in_peace,Spvc);
-handle_restart_multi_spvcs(active,Spvc) ->
- debug_disabled,
- active(restart,Spvc,undefined);
-handle_restart_multi_spvcs(outgoing_callproceeding,Spvc) ->
- debug_disabled,
- outgoing_callproceeding(restart,Spvc,undefined);
-handle_restart_multi_spvcs(release_at_restart,Spvc) ->
- debug_disabled,
- release_at_restart(restart,Spvc,undefined);
-handle_restart_multi_spvcs(wait,Spvc) ->
- debug_disabled,
- wait(restart,Spvc,undefined);
-handle_restart_multi_spvcs(rest_in_peace,Spvc) ->
- debug_disabled,
- rest_in_peace(restart,Spvc,undefined);
-handle_restart_multi_spvcs(_,_) ->
- ok.
-
-orig_state_machine(null,createAndGo_enabled,Spvc,Attrs) ->
- null(createAndGo_enabled,Spvc,Attrs);
-orig_state_machine(null,createAndGo_disabled,Spvc,Attrs) ->
- null(createAndGo_disabled,Spvc,Attrs);
-orig_state_machine(null,createAndWait,Spvc,Attrs) ->
- null(createAndWait,Spvc,Attrs);
-orig_state_machine(created,activate_disabled,Spvc,Attrs) ->
- created(activate_disabled,Spvc,Attrs);
-orig_state_machine(created,activate_enabled,Spvc,Attrs) ->
- created(activate_enabled,Spvc,Attrs);
-orig_state_machine(created,destroy,Spvc,Attrs) ->
- created(destroy,Spvc,Attrs);
-orig_state_machine(outgoing_callproceeding,connect_nu,Spvc,Attrs) ->
- outgoing_callproceeding(connect_nu,Spvc,Attrs);
-orig_state_machine(outgoing_callproceeding,destroy,Spvc,Attrs) ->
- outgoing_callproceeding(destroy,Spvc,Attrs);
-orig_state_machine(outgoing_callproceeding,restart,Spvc,Attrs) ->
- outgoing_callproceeding(restart,Spvc,Attrs);
-orig_state_machine(outgoing_callproceeding,release_nu,Spvc,Attrs) ->
- case get_link_state_intf(case Spvc of
- Spvc when record(Spvc,spvcObj) ->
- case Spvc#spvcObj.spvcEntry of
- {If_Value,_,_,_} ->
- If_Value;
- {If_Value,_,_} ->
- If_Value
- end;
- Spvc when record(Spvc,spvcVcc) ->
- {If_Value,_,_,_} = Spvc#spvcVcc.spvcVccEntry,
- If_Value;
- Spvc when record(Spvc,spvcVpc) ->
- {If_Value,_,_} = Spvc#spvcVpc.spvcVpcEntry,
- If_Value;
- Spvc when record(Spvc,spvcVpcPerm) ->
- {If_Value,_,_} = Spvc#spvcVpcPerm.spvcVpcEntry,
- If_Value;
- Spvc when record(Spvc,spvcVccPerm) ->
- {If_Value,_,_,_} = Spvc#spvcVccPerm.spvcVccEntry,
- If_Value;
- Spvc when record(Spvc,spvcTargetVc) ->
- {If_Value,_,_} = Spvc#spvcTargetVc.entry,
- If_Value;
- Spvc when record(Spvc,spvcTargetVp) ->
- {If_Value,_} = Spvc#spvcTargetVp.entry,
- If_Value;
- Spvc when record(Spvc,pchVc) ->
- {If_Value,_,_} = Spvc#pchVc.vclEntry,
- If_Value;
- Spvc when record(Spvc,pchVp) ->
- {If_Value,_} = Spvc#pchVp.vplEntry,
- If_Value;
- Spvc when record(Spvc,spvcFr) ->
- {If_Value,_} = Spvc#spvcFr.spvcFrEntry,
- If_Value;
- Spvc when record(Spvc,spvcFrPerm) ->
- {If_Value,_} = Spvc#spvcFrPerm.spvcFrEntry,
- If_Value;
- {If_Value,_,_,_} ->
- If_Value;
- {If_Value,_,_} ->
- If_Value;
- {If_Value,_} ->
- If_Value;
- [If_Value|_] ->
- If_Value;
- _ ->
- error
- end,release_nu) of
- disabled ->
- outgoing_callproceeding(release_nu_disabled,Spvc,Attrs);
- enabled ->
- outgoing_callproceeding(release_nu_enabled,Spvc,Attrs)
- end;
-orig_state_machine(outgoing_callproceeding,release_comp_nu,Spvc,Attrs) ->
- case get_link_state_intf(tuple_to_list(Spvc#spvcObj.spvcEntry),release_comp_nu) of
- disabled ->
- outgoing_callproceeding(release_comp_nu_disabled,Spvc,Attrs);
- enabled ->
- outgoing_callproceeding(release_comp_nu_enabled,Spvc,Attrs)
- end;
-orig_state_machine(outgoing_callproceeding,not_in_service,Spvc,Attrs) ->
- outgoing_callproceeding(not_in_service,Spvc,Attrs);
-orig_state_machine(outgoing_callproceeding,activate_enabled,Spvc,Attrs) ->
- ok;
-orig_state_machine(outgoing_callproceeding,activate_disabled,Spvc,Attrs) ->
- ok;
-orig_state_machine(active,destroy,Spvc,Attrs) ->
- active(destroy,Spvc,Attrs);
-orig_state_machine(active,restart,Spvc,Attrs) ->
- active(restart,Spvc,Attrs);
-orig_state_machine(active,release_nu,Spvc,Attrs) ->
- case cnhChi:get_link_opstate(case Spvc of
- Spvc when record(Spvc,spvcObj) ->
- case Spvc#spvcObj.spvcEntry of
- {If_Value,_,_,_} ->
- If_Value;
- {If_Value,_,_} ->
- If_Value
- end;
- Spvc when record(Spvc,spvcVcc) ->
- {If_Value,_,_,_} = Spvc#spvcVcc.spvcVccEntry,
- If_Value;
- Spvc when record(Spvc,spvcVpc) ->
- {If_Value,_,_} = Spvc#spvcVpc.spvcVpcEntry,
- If_Value;
- Spvc when record(Spvc,spvcVpcPerm) ->
- {If_Value,_,_} = Spvc#spvcVpcPerm.spvcVpcEntry,
- If_Value;
- Spvc when record(Spvc,spvcVccPerm) ->
- {If_Value,_,_,_} = Spvc#spvcVccPerm.spvcVccEntry,
- If_Value;
- Spvc when record(Spvc,spvcTargetVc) ->
- {If_Value,_,_} = Spvc#spvcTargetVc.entry,
- If_Value;
- Spvc when record(Spvc,spvcTargetVp) ->
- {If_Value,_} = Spvc#spvcTargetVp.entry,
- If_Value;
- Spvc when record(Spvc,pchVc) ->
- {If_Value,_,_} = Spvc#pchVc.vclEntry,
- If_Value;
- Spvc when record(Spvc,pchVp) ->
- {If_Value,_} = Spvc#pchVp.vplEntry,
- If_Value;
- Spvc when record(Spvc,spvcFr) ->
- {If_Value,_} = Spvc#spvcFr.spvcFrEntry,
- If_Value;
- Spvc when record(Spvc,spvcFrPerm) ->
- {If_Value,_} = Spvc#spvcFrPerm.spvcFrEntry,
- If_Value;
- {If_Value,_,_,_} ->
- If_Value;
- {If_Value,_,_} ->
- If_Value;
- {If_Value,_} ->
- If_Value;
- [If_Value|_] ->
- If_Value;
- _ ->
- error
- end) of
- disabled ->
- active(release_nu_disabled,Spvc,Attrs);
- enabled ->
- active(release_nu_enabled,Spvc,Attrs)
- end;
-orig_state_machine(active,release_comp_nu,Spvc,Attrs) ->
- release_at_restart(release_comp_nu,Spvc,Attrs);
-orig_state_machine(active,not_in_service,Spvc,Attrs) ->
- active(not_in_service,Spvc,Attrs);
-orig_state_machine(active,activate_enabled,Spvc,Attrs) ->
- ok;
-orig_state_machine(active,activate_disabled,Spvc,Attrs) ->
- ok;
-orig_state_machine(active,release_incumbent,Spvc,Attrs) ->
- active(release_incumbent,Spvc,Attrs);
-orig_state_machine(wait,destroy,Spvc,Attrs) ->
- wait(destroy,Spvc,Attrs);
-orig_state_machine(wait,timeout,Spvc,Attrs) ->
- wait(timeout,Spvc,Attrs);
-orig_state_machine(wait,restart,Spvc,Attrs) ->
- wait(restart,Spvc,Attrs);
-orig_state_machine(wait,release_nu,Spvc,Attrs) ->
- ok;
-orig_state_machine(wait,not_in_service,Spvc,Attrs) ->
- wait(not_in_service,Spvc,Attrs);
-orig_state_machine(wait,activate_enabled,Spvc,Attrs) ->
- wait(timeout,Spvc,Attrs);
-orig_state_machine(wait,activate_disabled,Spvc,Attrs) ->
- ok;
-orig_state_machine(release_at_restart,release_comp_nu,Spvc,Attrs) ->
- release_at_restart(release_comp_nu,Spvc,Attrs);
-orig_state_machine(release_at_restart,release_nu,Spvc,Attrs) ->
- release_at_restart(release_nu,Spvc,Attrs);
-orig_state_machine(release_at_restart,connect_nu,Spvc,Attrs) ->
- release_at_restart(connect_nu,Spvc,Attrs);
-orig_state_machine(release_at_restart,destroy,Spvc,Attrs) ->
- release_at_restart(destroy,Spvc,Attrs);
-orig_state_machine(release_at_restart,not_in_service,Spvc,Attrs) ->
- release_at_restart(not_in_service,Spvc,Attrs);
-orig_state_machine(release_at_restart,activate_enabled,Spvc,Attrs) ->
- ok;
-orig_state_machine(release_at_restart,activate_disabled,Spvc,Attrs) ->
- ok;
-orig_state_machine(release_request,release_comp_nu,Spvc,Attrs) ->
- release_request(release_comp_nu,Spvc,Attrs);
-orig_state_machine(release_request,release_nu,Spvc,Attrs) ->
- release_request(release_nu,Spvc,Attrs);
-orig_state_machine(release_request,destroy,Spvc,Attrs) ->
- release_request(destroy,Spvc,Attrs);
-orig_state_machine(release_request,not_in_service,Spvc,Attrs) ->
- release_request(not_in_service,Spvc,Attrs);
-orig_state_machine(release_request,activate_enabled,Spvc,Attrs) ->
- ok;
-orig_state_machine(release_request,activate_disabled,Spvc,Attrs) ->
- ok;
-orig_state_machine(rest_in_peace,restart,Spvc,Attrs) ->
- rest_in_peace(restart,Spvc,Attrs);
-orig_state_machine(rest_in_peace,destroy,Spvc,Attrs) ->
- rest_in_peace(destroy,Spvc,Attrs);
-orig_state_machine(rest_in_peace,not_in_service,Spvc,Attrs) ->
- rest_in_peace(not_in_service,Spvc,Attrs);
-orig_state_machine(rest_in_peace,connect_nu,Spvc,Attrs) ->
- rest_in_peace(connect_nu,Spvc,Attrs);
-orig_state_machine(rest_in_peace,activate_enabled,Spvc,Attrs) ->
- rest_in_peace(restart,Spvc,Attrs);
-orig_state_machine(rest_in_peace,activate_disabled,Spvc,Attrs) ->
- ok;
-orig_state_machine(rest_in_peace,release_nu,Spvc,Attrs) ->
- ok;
-orig_state_machine(rest_in_peace,release_comp_nu,Spvc,Attrs) ->
- ok;
-orig_state_machine(not_in_service,activate_enabled,Spvc,Attrs) ->
- not_in_service(activate_enabled,Spvc,Attrs);
-orig_state_machine(not_in_service,activate_disabled,Spvc,Attrs) ->
- not_in_service(activate_disabled,Spvc,Attrs);
-orig_state_machine(not_in_service,destroy,Spvc,Attrs) ->
- not_in_service(destroy,Spvc,Attrs);
-orig_state_machine(not_in_service,connect_nu,Spvc,Attrs) ->
- not_in_service(connect_nu,Spvc,Attrs);
-orig_state_machine(not_in_service,_,Spvc,Attrs) ->
- ok;
-orig_state_machine(awaiting_switch_over,switch_over,Spvc,[HcId]) ->
- awaiting_switch_over(switch_over,Spvc,[HcId]);
-orig_state_machine(awaiting_switch_over,activate_disabled,Spvc,Attrs) ->
- awaiting_switch_over(activate_disabled,Spvc,Attrs);
-orig_state_machine(awaiting_switch_over,destroy,Spvc,Attrs) ->
- awaiting_switch_over(destroy,Spvc,Attrs);
-orig_state_machine(awaiting_switch_over,restart,Spvc,Attrs) ->
- awaiting_switch_over(restart,Spvc,Attrs);
-orig_state_machine(awaiting_switch_over,_,Spvc,Attrs) ->
- ok;
-orig_state_machine(undefined,destroy,Spvc,Attrs) ->
- rest_in_peace(destroy,Spvc,Attrs).
-
-null(createAndGo_enabled,[],[Row,Cols,Type,FrKey]) ->
- debug_disabled,
- Key = list_to_tuple(Row),
- Spvc = #spvcObj{spvcEntry = Key,
- spvcApplication = Type,
- spvcRowStatus = 1,
- spvcFrKey = FrKey},
- Spvc1 = set_attrs(Spvc,Cols),
- {Spvc2,HcId,Setup} = new_state_outgoing_call_proceeding(Spvc1),
- pchTpUpdate(case Key of
- {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
- {IfIndex_Value,Vpi_Value,Vci_Value};
- {IfIndex_Value,Vpi_Value,_} ->
- {IfIndex_Value,Vpi_Value};
- [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
- [IfIndex_Value,Vpi_Value,Vci_Value];
- [IfIndex_Value,Vpi_Value,_] ->
- [IfIndex_Value,Vpi_Value]
- end),
- spvcDataBase:db_write(Spvc2),
- setup(HcId,Setup,Spvc2);
-null(createAndGo_disabled,[],[Row,Cols,Type,FrKey]) ->
- debug_disabled,
- case get_link_state_intf(Row,null_createAndGo_disabled) of
- disabled ->
- Key = list_to_tuple(Row),
- Spvc = #spvcObj{spvcEntry = Key,
- spvcRowStatus = 1,
- currentState = rest_in_peace,
- spvcApplication = Type,
- spvcFrKey = FrKey},
- Spvc1 = set_attrs(Spvc,Cols),
- pchTpUpdate(case Key of
- {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
- {IfIndex_Value,Vpi_Value,Vci_Value};
- {IfIndex_Value,Vpi_Value,_} ->
- {IfIndex_Value,Vpi_Value};
- [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
- [IfIndex_Value,Vpi_Value,Vci_Value];
- [IfIndex_Value,Vpi_Value,_] ->
- [IfIndex_Value,Vpi_Value]
- end),
- set_call_failure_data_and_send_spvcFailingAlarm(Key),
- spvcDataBase:db_write(Spvc1);
- enabled ->
- null(createAndGo_enabled,[],[Row,Cols,Type,FrKey])
- end;
-null(createAndWait,[],[Row,Cols,Type,FrKey]) ->
- debug_disabled,
- Key = list_to_tuple(Row),
- Spvc = #spvcObj{spvcEntry = Key,
- spvcApplication = Type,
- spvcFrKey = FrKey},
- Spvc1 = new_state_created(Spvc,Cols),
- pchTpUpdate(case Key of
- {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
- {IfIndex_Value,Vpi_Value,Vci_Value};
- {IfIndex_Value,Vpi_Value,_} ->
- {IfIndex_Value,Vpi_Value};
- [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
- [IfIndex_Value,Vpi_Value,Vci_Value];
- [IfIndex_Value,Vpi_Value,_] ->
- [IfIndex_Value,Vpi_Value]
- end),
- spvcDataBase:db_write(Spvc1).
-
-pchTpUpdate({If,Vpi,Vci}) ->
- spvcDataBase:db_write(#spvcVcDyn{vclEntry = {If,Vpi,Vci},
- vclCcIdentifier = 0});
-pchTpUpdate({If,Vpi}) ->
- spvcDataBase:db_write(#spvcVpDyn{vplEntry = {If,Vpi},
- vplCcIdentifier = 0}).
-
-created(activate_enabled,Spvc,Attrs) ->
- debug_disabled,
- Spvc1 = set_attrs(Spvc,Attrs),
- Spvc2 = Spvc1#spvcObj{spvcRowStatus = 1},
- {Spvc3,HcId,HciMsg} = new_state_outgoing_call_proceeding(Spvc1),
- spvcDataBase:db_write(Spvc3),
- setup(HcId,HciMsg,Spvc3);
-created(activate_disabled,Spvc,Attrs) ->
- debug_disabled,
- Spvc1 = set_attrs(Spvc,Attrs),
- Spvc2 = Spvc1#spvcObj{currentState = rest_in_peace,
- spvcRowStatus = 1},
- update_state(Spvc,4),
- spvcDataBase:db_write(Spvc2);
-created(destroy,Spvc,Attrs) ->
- debug_disabled,
- clear(Spvc).
-
-outgoing_callproceeding(connect_nu,Spvc,[HcId,Connect]) ->
- debug_disabled,
- Spvc1 = new_state_active(Spvc),
- case Spvc#spvcObj.spvcTargetSelectType of
- 2 ->
- Cpn = Connect#hci_connect.hci_cpn_soft,
- TargetVpi = Cpn#hci_cpn_soft.hci_soft_vpi,
- TargetVci = Cpn#hci_cpn_soft.hci_soft_vci,
- TargetDlci = Cpn#hci_cpn_soft.hci_soft_dlci,
- Spvc2 = Spvc1#spvcObj{spvcTargetSelectType = 1,
- spvcTargetVpi = TargetVpi,
- spvcTargetVci = TargetVci,
- spvcTargetDlci = TargetDlci},
- spvcDataBase:db_write(Spvc2);
- 1 ->
- spvcDataBase:db_write(ets,Spvc1);
- 2 ->
- Cpn = Connect#hci_connect.hci_cpn_soft,
- TargetVpi = Cpn#hci_cpn_soft.hci_soft_vpi,
- TargetDlci = Cpn#hci_cpn_soft.hci_soft_dlci,
- Spvc2 = Spvc1#spvcObj{spvcTargetSelectType = 1,
- spvcTargetVpi = TargetVpi,
- spvcTargetDlci = TargetDlci},
- spvcDataBase:db_write(Spvc2);
- 1 ->
- spvcDataBase:db_write(ets,Spvc1)
- end,
- Key = Spvc#spvcObj.spvcEntry,
- PchKey = case Key of
- {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
- {IfIndex_Value,Vpi_Value,Vci_Value};
- {IfIndex_Value,Vpi_Value,_} ->
- {IfIndex_Value,Vpi_Value};
- [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
- [IfIndex_Value,Vpi_Value,Vci_Value];
- [IfIndex_Value,Vpi_Value,_] ->
- [IfIndex_Value,Vpi_Value]
- end,
- SpvcDyn = case PchKey of
- {_,_,_} ->
- case spvcDataBase:db_read({spvcVcDyn,PchKey}) of
- [] ->
- #spvcVcDyn{vclEntry = PchKey,
- vclCcIdentifier = 0,
- vclConnId = HcId};
- SpvcVcDyn ->
- SpvcVcDyn#spvcVcDyn{vclEntry = PchKey,
- vclConnId = HcId}
- end;
- {_,_} ->
- case spvcDataBase:db_read({spvcVpDyn,PchKey}) of
- [] ->
- #spvcVpDyn{vplEntry = PchKey,
- vplCcIdentifier = 0,
- vplConnId = HcId};
- SpvcVpDyn ->
- SpvcVpDyn#spvcVpDyn{vplEntry = PchKey,
- vplConnId = HcId}
- end
- end,
- spvcDataBase:db_write(SpvcDyn),
- CbCValue = get(no_of_rerouting),
- CbC = case CbCValue of
- undefined ->
- debug_disabled,
- 0;
- _ ->
- CbCValue
- end,
- SpvcDyn2 = case Key of
- {_,_,_,_} ->
- case spvcDataBase:db_read({spvcVccDyn,Key}) of
- [] ->
- #spvcVccDyn{spvcVccEntry = Key,
- crankBackCounter = CbC};
- SpvcVccDyn ->
- SpvcVccDyn#spvcVccDyn{spvcVccEntry = Key,
- crankBackCounter = CbC}
- end;
- {_,_,_} ->
- case spvcDataBase:db_read({spvcVpcDyn,Key}) of
- [] ->
- #spvcVpcDyn{spvcVpcEntry = Key,
- crankBackCounter = CbC};
- SpvcVpcDyn ->
- SpvcVpcDyn#spvcVpcDyn{spvcVpcEntry = Key,
- crankBackCounter = CbC}
- end
- end,
- spvcDataBase:db_write(SpvcDyn2),
- NewPch = spvcDataBase:db_read({pch,PchKey}),
- spvcLib:clear_spvcStillTryingAlarm(Key),
- case Spvc#spvcObj.spvcFrKey of
- undefined ->
- spvcLib:ilmi_change(PchKey,1),
- ok;
- FrEndPoint ->
- SpvcFrObj = spvcDataBase:db_read({spvcFrPerm,FrEndPoint}),
- NewSpvcFrObj = SpvcFrObj#spvcFrPerm{spvcFrConnect = 3},
- spvcDataBase:db_write(NewSpvcFrObj),
- spvcLib:ilmi_change(PchKey,1),
- set_fr_atm_iw_admin_state(FrEndPoint,up,Spvc)
- end;
-outgoing_callproceeding(restart,Spvc,_) ->
- Key = Spvc#spvcObj.spvcEntry,
- debug_disabled,
- Spvc1 = new_state_release_at_restart(Spvc),
- spvcDataBase:db_write(ets,Spvc1),
- spvcLib:clear_spvcStillTryingAlarm(Key);
-outgoing_callproceeding(release_nu_enabled,Spvc,[HcId,HciMsg]) ->
- debug_disabled,
- Spvc1 = new_state_rest_in_peace_or_wait(Spvc,[HcId,HciMsg]),
- [CcCause|_] = HciMsg#hci_release.hci_cause_list,
- Spvc2 = Spvc1#spvcObj{spvcLastReleaseCause = CcCause#hci_cause.hci_cause_value,
- spvcLastReleaseDiagnostic = CcCause#hci_cause.hci_diagnostics_list},
- spvcDataBase:db_write(ets,Spvc2);
-outgoing_callproceeding(release_nu_disabled,Spvc,[HcId,Release]) ->
- debug_disabled,
- Spvc1 = new_state_rest_in_peace(Spvc),
- [CcCause|_] = Release#hci_release.hci_cause_list,
- Spvc2 = Spvc1#spvcObj{spvcLastReleaseCause = CcCause#hci_cause.hci_cause_value,
- spvcLastReleaseDiagnostic = CcCause#hci_cause.hci_diagnostics_list},
- spvcDataBase:db_write(ets,Spvc2),
- spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry);
-outgoing_callproceeding(release_comp_nu_enabled,Spvc,[HcId,Release_complete]) ->
- debug_disabled,
- Spvc1 = new_state_rest_in_peace_or_wait(Spvc,[HcId,Release_complete]),
- spvcDataBase:db_write(ets,Spvc1);
-outgoing_callproceeding(release_comp_nu_disabled,Spvc,[HcId,Release_complete]) ->
- debug_disabled,
- Key = Spvc#spvcObj.spvcEntry,
- Spvc1 = new_state_rest_in_peace(Spvc),
- spvcDataBase:db_write(ets,Spvc1),
- spvcLib:clear_spvcStillTryingAlarm(Key);
-outgoing_callproceeding(destroy,Spvc,_) ->
- debug_disabled,
- Key = Spvc#spvcObj.spvcEntry,
- Spvc1 = new_state_release_request(Spvc),
- spvcDataBase:db_write(ets,Spvc1),
- SpvcTpToHcId = read_spvcTpToHcId(Key),
- Release = spvcEncode:encode_cc_release(31),
- spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc1),
- spvcLib:clear_spvcStillTryingAlarm(Key);
-outgoing_callproceeding(not_in_service,Spvc,_) ->
- debug_disabled,
- Key = Spvc#spvcObj.spvcEntry,
- Spvc1 = new_state_not_in_service(Spvc),
- spvcDataBase:db_write(Spvc1),
- SpvcTpToHcId = read_spvcTpToHcId(Key),
- Release = spvcEncode:encode_cc_release(31),
- spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc1),
- spvcLib:clear_spvcStillTryingAlarm(Key).
-
-active(restart,Spvc,_) ->
- debug_disabled,
- Key = Spvc#spvcObj.spvcEntry,
- Spvc1 = new_state_release_at_restart(Spvc),
- spvcDataBase:db_write(ets,Spvc1),
- PchKey = case Key of
- {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
- {IfIndex_Value,Vpi_Value,Vci_Value};
- {IfIndex_Value,Vpi_Value,_} ->
- {IfIndex_Value,Vpi_Value};
- [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
- [IfIndex_Value,Vpi_Value,Vci_Value];
- [IfIndex_Value,Vpi_Value,_] ->
- [IfIndex_Value,Vpi_Value]
- end,
- spvcLib:ilmi_change(PchKey,2),
- case Spvc#spvcObj.spvcFrKey of
- undefined ->
- ok;
- FrEndPoint ->
- set_fr_atm_iw_admin_state(FrEndPoint,down,Spvc)
- end;
-active(release_nu_enabled,Spvc,[HcId,Release]) ->
- debug_disabled,
- Key = Spvc#spvcObj.spvcEntry,
- Spvc1 = new_state_rest_in_peace_or_wait(Spvc,[HcId,Release]),
- [CcCause|_] = Release#hci_release.hci_cause_list,
- Spvc2 = Spvc1#spvcObj{spvcLastReleaseCause = CcCause#hci_cause.hci_cause_value,
- spvcLastReleaseDiagnostic = CcCause#hci_cause.hci_diagnostics_list},
- spvcDataBase:db_write(ets,Spvc2),
- PchKey = case Key of
- {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
- {IfIndex_Value,Vpi_Value,Vci_Value};
- {IfIndex_Value,Vpi_Value,_} ->
- {IfIndex_Value,Vpi_Value};
- [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
- [IfIndex_Value,Vpi_Value,Vci_Value];
- [IfIndex_Value,Vpi_Value,_] ->
- [IfIndex_Value,Vpi_Value]
- end,
- spvcLib:ilmi_change(PchKey,2),
- case Spvc#spvcObj.spvcFrKey of
- undefined ->
- ok;
- FrEndPoint ->
- set_fr_atm_iw_admin_state(FrEndPoint,down,Spvc)
- end;
-active(release_nu_disabled,Spvc,[HcId,Release]) ->
- debug_disabled,
- case get_link_state_intf(case Spvc of
- Spvc when record(Spvc,spvcObj) ->
- case Spvc#spvcObj.spvcEntry of
- {If_Value,_,_,_} ->
- If_Value;
- {If_Value,_,_} ->
- If_Value
- end;
- Spvc when record(Spvc,spvcVcc) ->
- {If_Value,_,_,_} = Spvc#spvcVcc.spvcVccEntry,
- If_Value;
- Spvc when record(Spvc,spvcVpc) ->
- {If_Value,_,_} = Spvc#spvcVpc.spvcVpcEntry,
- If_Value;
- Spvc when record(Spvc,spvcVpcPerm) ->
- {If_Value,_,_} = Spvc#spvcVpcPerm.spvcVpcEntry,
- If_Value;
- Spvc when record(Spvc,spvcVccPerm) ->
- {If_Value,_,_,_} = Spvc#spvcVccPerm.spvcVccEntry,
- If_Value;
- Spvc when record(Spvc,spvcTargetVc) ->
- {If_Value,_,_} = Spvc#spvcTargetVc.entry,
- If_Value;
- Spvc when record(Spvc,spvcTargetVp) ->
- {If_Value,_} = Spvc#spvcTargetVp.entry,
- If_Value;
- Spvc when record(Spvc,pchVc) ->
- {If_Value,_,_} = Spvc#pchVc.vclEntry,
- If_Value;
- Spvc when record(Spvc,pchVp) ->
- {If_Value,_} = Spvc#pchVp.vplEntry,
- If_Value;
- Spvc when record(Spvc,spvcFr) ->
- {If_Value,_} = Spvc#spvcFr.spvcFrEntry,
- If_Value;
- Spvc when record(Spvc,spvcFrPerm) ->
- {If_Value,_} = Spvc#spvcFrPerm.spvcFrEntry,
- If_Value;
- {If_Value,_,_,_} ->
- If_Value;
- {If_Value,_,_} ->
- If_Value;
- {If_Value,_} ->
- If_Value;
- [If_Value|_] ->
- If_Value;
- _ ->
- error
- end,active_release_nu_disabled) of
- disabled ->
- debug_disabled,
- Key = Spvc#spvcObj.spvcEntry,
- Spvc1 = Spvc#spvcObj{currentState = rest_in_peace},
- [CcCause|_] = Release#hci_release.hci_cause_list,
- Spvc2 = Spvc1#spvcObj{spvcLastReleaseCause = CcCause#hci_cause.hci_cause_value,
- spvcLastReleaseDiagnostic = CcCause#hci_cause.hci_diagnostics_list},
- PchKey = case Key of
- {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
- {IfIndex_Value,Vpi_Value,Vci_Value};
- {IfIndex_Value,Vpi_Value,_} ->
- {IfIndex_Value,Vpi_Value};
- [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
- [IfIndex_Value,Vpi_Value,Vci_Value];
- [IfIndex_Value,Vpi_Value,_] ->
- [IfIndex_Value,Vpi_Value]
- end,
- spvcLib:ilmi_change(PchKey,2),
- update_state(Spvc,4),
- spvcDataBase:db_write(ets,Spvc2),
- case Spvc#spvcObj.spvcFrKey of
- undefined ->
- ok;
- FrEndPoint ->
- set_fr_atm_iw_admin_state(FrEndPoint,down,Spvc)
- end;
- enabled ->
- active(release_nu_enabled,Spvc,[HcId,Release])
- end;
-active(destroy,Spvc,_) ->
- debug_disabled,
- Key = Spvc#spvcObj.spvcEntry,
- Spvc1 = new_state_release_request(Spvc),
- spvcDataBase:db_write(ets,Spvc1),
- PchKey = case Key of
- {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
- {IfIndex_Value,Vpi_Value,Vci_Value};
- {IfIndex_Value,Vpi_Value,_} ->
- {IfIndex_Value,Vpi_Value};
- [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
- [IfIndex_Value,Vpi_Value,Vci_Value];
- [IfIndex_Value,Vpi_Value,_] ->
- [IfIndex_Value,Vpi_Value]
- end,
- spvcLib:ilmi_change(PchKey,2),
- SpvcTpToHcId = read_spvcTpToHcId(Key),
- Release = spvcEncode:encode_cc_release(31),
- spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc);
-active(not_in_service,Spvc,_) ->
- debug_disabled,
- Key = Spvc#spvcObj.spvcEntry,
- Spvc1 = new_state_not_in_service(Spvc),
- spvcDataBase:db_write(Spvc1),
- PchKey = case Key of
- {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
- {IfIndex_Value,Vpi_Value,Vci_Value};
- {IfIndex_Value,Vpi_Value,_} ->
- {IfIndex_Value,Vpi_Value};
- [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
- [IfIndex_Value,Vpi_Value,Vci_Value];
- [IfIndex_Value,Vpi_Value,_] ->
- [IfIndex_Value,Vpi_Value]
- end,
- spvcLib:ilmi_change(PchKey,2),
- SpvcTpToHcId = read_spvcTpToHcId(Key),
- Release = spvcEncode:encode_cc_release(31),
- spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc1),
- case Spvc#spvcObj.spvcFrKey of
- undefined ->
- ok;
- FrEndPoint ->
- set_fr_atm_iw_admin_state(FrEndPoint,down,Spvc)
- end;
-active(release_incumbent,Spvc,[Release]) ->
- debug_disabled,
- Key = Spvc#spvcObj.spvcEntry,
- Spvc1 = new_state_awaiting_switch_over(Spvc),
- spvcDataBase:db_write(Spvc1),
- SpvcTpToHcId = read_spvcTpToHcId(Key),
- spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc1).
-
-read_spvcTpToHcId({If,Vpi,Vci,Leaf}) ->
- spvcDataBase:db_read({spvcTpToHcId,{orig,If,Vpi,Vci,Leaf}});
-read_spvcTpToHcId({If,Vpi,Leaf}) ->
- spvcDataBase:db_read({spvcTpToHcId,{orig,If,Vpi,Leaf}}).
-
-release_request(release_nu,Spvc,[HcId,Release]) ->
- debug_disabled,
- clear(Spvc);
-release_request(release_comp_nu,Spvc,[HcId,Release_comp]) ->
- debug_disabled,
- clear(Spvc);
-release_request(destroy,Spvc,_) ->
- debug_disabled,
- case Spvc#spvcObj.spvcEntry of
- {If,Vpi,Vci,Leaf} ->
- case spvcDataBase:db_read({spvcTpToHcId,{orig,If,Vpi,Vci,Leaf}}) of
- SpvcTpToHcId ->
- Release = spvcEncode:encode_cc_release(31),
- spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc),
- clear(Spvc);
- _ ->
- ok
- end;
- {If,Vpi,Leaf} ->
- case spvcDataBase:db_read({spvcTpToHcId,{orig,If,Vpi,Leaf}}) of
- SpvcTpToHcId ->
- Release = spvcEncode:encode_cc_release(31),
- spvcManager:release_un(a_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc),
- clear(Spvc);
- _ ->
- ok
- end
- end,
- ok;
-release_request(not_in_service,Spvc,_) ->
- debug_disabled,
- ok.
-
-release_at_restart(release_nu,Spvc,[HcId,Release]) ->
- debug_disabled,
- {Spvc1,NewHcId,Setup} = new_state_outgoing_call_proceeding(Spvc),
- [CcCause|_] = Release#hci_release.hci_cause_list,
- Spvc2 = Spvc1#spvcObj{spvcLastReleaseCause = CcCause#hci_cause.hci_cause_value,
- spvcLastReleaseDiagnostic = CcCause#hci_cause.hci_diagnostics_list},
- spvcDataBase:db_write(ets,Spvc2),
- timer:sleep(500),
- setup(NewHcId,Setup,Spvc2);
-release_at_restart(release_comp_nu,Spvc,[HcId,Release_complete]) ->
- debug_disabled,
- {Spvc1,NewHcId,Setup} = new_state_outgoing_call_proceeding(Spvc),
- Spvc2 = Spvc1#spvcObj{spvcLastReleaseCause = 31,
- spvcLastReleaseDiagnostic = []},
- spvcDataBase:db_write(ets,Spvc2),
- timer:sleep(500),
- setup(NewHcId,Setup,Spvc1);
-release_at_restart(connect_nu,Spvc,_) ->
- debug_disabled,
- ok;
-release_at_restart(destroy,Spvc,_) ->
- debug_disabled,
- Spvc1 = new_state_release_request(Spvc),
- spvcDataBase:db_write(ets,Spvc1);
-release_at_restart(restart,Spvc,_) ->
- debug_disabled,
- Spvc1 = new_state_release_at_restart(Spvc);
-release_at_restart(not_in_service,Spvc,_) ->
- debug_disabled,
- Spvc1 = new_state_not_in_service(Spvc),
- spvcDataBase:db_write(Spvc1).
-
-wait(timeout,Spvc,_) ->
- debug_disabled,
- {Spvc1,HcId,Setup} = new_state_outgoing_call_proceeding(Spvc),
- spvcDataBase:db_write(ets,Spvc1),
- setup(HcId,Setup,Spvc1);
-wait(destroy,Spvc,_) ->
- debug_disabled,
- spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry),
- clear(Spvc);
-wait(restart,Spvc,_) ->
- debug_disabled,
- {Spvc1,HcId,Setup} = new_state_outgoing_call_proceeding(Spvc#spvcObj{spvcRetryFailures = 0}),
- spvcDataBase:db_write(ets,Spvc1),
- spvcReestablishTimer:cancel(Spvc#spvcObj.spvcEntry),
- spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry),
- setup(HcId,Setup,Spvc1);
-wait(not_in_service,Spvc,_) ->
- debug_disabled,
- Spvc1 = new_state_not_in_service(Spvc),
- spvcDataBase:db_write(Spvc1),
- spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry).
-
-rest_in_peace(restart,Spvc,_) ->
- debug_disabled,
- {Spvc1,HcId,Setup} = new_state_outgoing_call_proceeding(Spvc#spvcObj{spvcRetryFailures = 0}),
- spvcDataBase:db_write(ets,Spvc1),
- setup(HcId,Setup,Spvc1),
- sccmManager:cast_to_sccm(spvcLib:get_cp(om_node),spvcLib,clear_spvcFailingAlarm,[spvcLib:get_membership(node())]);
-rest_in_peace(destroy,Spvc,_) ->
- debug_disabled,
- sccmManager:cast_to_sccm(spvcLib:get_cp(om_node),spvcLib,clear_spvcFailingAlarm,[spvcLib:get_membership(node())]),
- clear(Spvc);
-rest_in_peace(connect_nu,Spvc,_) ->
- debug_disabled,
- Key = Spvc#spvcObj.spvcEntry,
- SpvcTpToHcId = read_spvcTpToHcId(Key),
- Release = spvcEncode:encode_cc_release(31),
- spvcManager:release_un(b_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc);
-rest_in_peace(not_in_service,Spvc,_) ->
- debug_disabled,
- Spvc1 = new_state_not_in_service(Spvc),
- spvcDataBase:db_write(Spvc1),
- sccmManager:cast_to_sccm(spvcLib:get_cp(om_node),spvcLib,clear_spvcFailingAlarm,[spvcLib:get_membership(node())]).
-
-not_in_service(activate_enabled,Spvc,_) ->
- debug_disabled,
- {Spvc1,HcId,Setup} = new_state_outgoing_call_proceeding(Spvc#spvcObj{spvcRetryFailures = 0}),
- spvcDataBase:db_write(Spvc1#spvcObj{spvcRowStatus = 1}),
- setup(HcId,Setup,Spvc1);
-not_in_service(activate_disabled,Spvc,_) ->
- debug_disabled,
- Spvc1 = new_state_rest_in_peace(Spvc),
- spvcDataBase:db_write(Spvc1#spvcObj{spvcRowStatus = 1});
-not_in_service(connect_nu,Spvc,_) ->
- debug_disabled,
- Spvc1 = new_state_rest_in_peace(Spvc),
- spvcDataBase:db_write(Spvc1#spvcObj{spvcRowStatus = 1}),
- Key = Spvc#spvcObj.spvcEntry,
- SpvcTpToHcId = read_spvcTpToHcId(Key),
- Release = spvcEncode:encode_cc_release(31),
- spvcManager:release_un(b_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc1);
-not_in_service(destroy,Spvc,_) ->
- debug_disabled,
- clear(Spvc).
-
-awaiting_switch_over(switch_over,Spvc,[HcId]) ->
- debug_disabled,
- Spvc1 = Spvc#spvcObj{currentState = active},
- Index = Spvc#spvcObj.spvcEntry,
- TpIndex = create_tp_index(Index),
- spvcDataBase:db_write(Spvc1),
- ets:insert(spvcTpToHcId,#spvcTpToHcId{tpEntry = TpIndex,
- hcId = HcId}),
- ets:insert(spvcHcIdToTp,#spvcHcIdToTp{tpEntry = TpIndex,
- hcId = HcId}),
- update_dyn_table_hcid(Index,HcId),
- ok;
-awaiting_switch_over(activate_disabled,Spvc,Attrs) ->
- Spvc1 = new_state_rest_in_peace(Spvc),
- spvcDataBase:db_write(Spvc1),
- ok;
-awaiting_switch_over(restart,Spvc,Attrs) ->
- debug_disabled,
- Key = Spvc#spvcObj.spvcEntry,
- Spvc1 = new_state_release_at_restart(Spvc),
- spvcDataBase:db_write(ets,Spvc1),
- PchKey = case Key of
- {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
- {IfIndex_Value,Vpi_Value,Vci_Value};
- {IfIndex_Value,Vpi_Value,_} ->
- {IfIndex_Value,Vpi_Value};
- [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
- [IfIndex_Value,Vpi_Value,Vci_Value];
- [IfIndex_Value,Vpi_Value,_] ->
- [IfIndex_Value,Vpi_Value]
- end,
- spvcLib:ilmi_change(PchKey,2),
- case Spvc#spvcObj.spvcFrKey of
- undefined ->
- ok;
- FrEndPoint ->
- set_fr_atm_iw_admin_state(FrEndPoint,down,Spvc)
- end;
-awaiting_switch_over(destroy,Spvc,Attrs) ->
- clear(Spvc).
-
-create_tp_index({If,Vpi,Vci,Leaf}) ->
- list_to_tuple([orig,If,Vpi,Vci,Leaf]);
-create_tp_index({If,Vpi,Leaf}) ->
- list_to_tuple([orig,If,Vpi,Leaf]).
-
-update_dyn_table_hcid({If,Vpi,Vci,Leaf},HcId) ->
- [VcDyn] = ets:lookup(spvcVcDyn,{If,Vpi,Vci}),
- ets:insert(spvcVcDyn,VcDyn#spvcVcDyn{vclConnId = HcId});
-update_dyn_table_hcid({If,Vpi,Leaf},HcId) ->
- [VpDyn] = ets:lookup(spvcVpDyn,{If,Vpi}),
- ets:insert(spvcVpDyn,VpDyn#spvcVpDyn{vplConnId = HcId}).
-
-new_state_outgoing_call_proceeding(Spvc) ->
- debug_disabled,
- Spvc1 = Spvc#spvcObj{spvcRowStatus = 1,
- currentState = outgoing_callproceeding},
- Key = Spvc1#spvcObj.spvcEntry,
- update_state(Spvc,outgoing_callproceeding),
- PchKey = case Key of
- {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
- {IfIndex_Value,Vpi_Value,Vci_Value};
- {IfIndex_Value,Vpi_Value,_} ->
- {IfIndex_Value,Vpi_Value};
- [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
- [IfIndex_Value,Vpi_Value,Vci_Value];
- [IfIndex_Value,Vpi_Value,_] ->
- [IfIndex_Value,Vpi_Value]
- end,
- {FwdAtdIndex,BwdAtdIndex} = case PchKey of
- {_,_,_} ->
- Vc = spvcDataBase:db_read({pchVc,PchKey}),
- {Vc#pchVc.vclReceiveTrafficDescrIndex,Vc#pchVc.vclTransmitTrafficDescrIndex};
- {_,_} ->
- Vp = spvcDataBase:db_read({pchVp,PchKey}),
- {Vp#pchVp.vplReceiveTrafficDescrIndex,Vp#pchVp.vplTransmitTrafficDescrIndex}
- end,
- FwdPchAtd = spvcDataBase:db_read({pchAtd,FwdAtdIndex}),
- BwdPchAtd = spvcDataBase:db_read({pchAtd,BwdAtdIndex}),
- Row = tuple_to_list(Key),
- HcId = spvcLib:create_hcid(Row,case Row of
- Row when record(Row,spvcObj) ->
- case Row#spvcObj.spvcEntry of
- {If_Value,_,_,_} ->
- If_Value;
- {If_Value,_,_} ->
- If_Value
- end;
- Row when record(Row,spvcVcc) ->
- {If_Value,_,_,_} = Row#spvcVcc.spvcVccEntry,
- If_Value;
- Row when record(Row,spvcVpc) ->
- {If_Value,_,_} = Row#spvcVpc.spvcVpcEntry,
- If_Value;
- Row when record(Row,spvcVpcPerm) ->
- {If_Value,_,_} = Row#spvcVpcPerm.spvcVpcEntry,
- If_Value;
- Row when record(Row,spvcVccPerm) ->
- {If_Value,_,_,_} = Row#spvcVccPerm.spvcVccEntry,
- If_Value;
- Row when record(Row,spvcTargetVc) ->
- {If_Value,_,_} = Row#spvcTargetVc.entry,
- If_Value;
- Row when record(Row,spvcTargetVp) ->
- {If_Value,_} = Row#spvcTargetVp.entry,
- If_Value;
- Row when record(Row,pchVc) ->
- {If_Value,_,_} = Row#pchVc.vclEntry,
- If_Value;
- Row when record(Row,pchVp) ->
- {If_Value,_} = Row#pchVp.vplEntry,
- If_Value;
- Row when record(Row,spvcFr) ->
- {If_Value,_} = Row#spvcFr.spvcFrEntry,
- If_Value;
- Row when record(Row,spvcFrPerm) ->
- {If_Value,_} = Row#spvcFrPerm.spvcFrEntry,
- If_Value;
- {If_Value,_,_,_} ->
- If_Value;
- {If_Value,_,_} ->
- If_Value;
- {If_Value,_} ->
- If_Value;
- [If_Value|_] ->
- If_Value;
- _ ->
- error
- end),
- Setup = spvcEncode:encode_cc_setup(Row,Spvc1,FwdPchAtd,BwdPchAtd),
- debug_disabled,
- debug_disabled,
- debug_disabled,
- {Spvc1,HcId,Setup}.
-
-new_state_release_request(Spvc) ->
- debug_disabled,
- update_state(Spvc,release_request),
- Spvc#spvcObj{currentState = release_request}.
-
-new_state_release_at_restart(Spvc) ->
- debug_disabled,
- Spvc1 = Spvc#spvcObj{spvcRetryFailures = 0,
- currentState = release_at_restart},
- update_state(Spvc,release_at_restart),
- HcId = spvcEncode:encode_cc_hcid(Spvc1#spvcObj.spvcEntry),
- Release = spvcEncode:encode_cc_release(31),
- spvcManager:release_un(a_side,HcId,Release,Spvc1),
- Spvc1.
-
-new_state_rest_in_peace_or_wait(Spvc,[HcId,HciMsg]) ->
- debug_disabled,
- Spvc1 = Spvc#spvcObj{spvcRetryFailures = Spvc#spvcObj.spvcRetryFailures + 1},
- case check_limits(Spvc1) of
- {ok,ok,no_retries} ->
- send_spvcFailingAlarm(Spvc#spvcObj.spvcEntry),
- update_state(Spvc,4),
- spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry),
- Spvc1#spvcObj{currentState = rest_in_peace};
- {ok,ok,_} ->
- Spvc2 = Spvc1#spvcObj{spvcRetryTimer = time(),
- currentState = wait},
- update_state(Spvc,wait),
- start_timer(wait,Spvc2),
- Spvc2;
- {retry_threshold,ok,no_retries} ->
- Spvc2 = Spvc1#spvcObj{currentState = rest_in_peace},
- update_state(Spvc,4),
- send_call_failure(Spvc),
- send_spvcFailingAlarm(Spvc#spvcObj.spvcEntry),
- spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry),
- Spvc2;
- {retry_threshold,ok,_} ->
- Spvc2 = Spvc1#spvcObj{spvcRetryTimer = time(),
- currentState = wait},
- update_state(Spvc,wait),
- send_call_failure(Spvc2),
- start_timer(wait,Spvc2),
- Spvc2;
- {ok,retry_limit,_} ->
- send_spvcFailingAlarm(Spvc#spvcObj.spvcEntry),
- update_state(Spvc,4),
- spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry),
- Spvc1#spvcObj{currentState = rest_in_peace};
- {retry_threshold,retry_limit,_} ->
- Spvc2 = Spvc1#spvcObj{currentState = rest_in_peace},
- update_state(Spvc,4),
- send_call_failure(Spvc2),
- send_spvcFailingAlarm(Spvc#spvcObj.spvcEntry),
- spvcLib:clear_spvcStillTryingAlarm(Spvc#spvcObj.spvcEntry),
- Spvc2
- end.
-
-send_call_failure(Spvc) ->
- case Spvc#spvcObj.spvcRetryThreshold of
- 0 ->
- ok;
- _ ->
- sccmManager:cast_to_sccm(spvcLib:get_cp(om_node),spvcOrig,call_failure,[Spvc])
- end.
-
-new_state_rest_in_peace(Spvc) ->
- debug_disabled,
- update_state(Spvc,4),
- Spvc1 = Spvc#spvcObj{spvcRetryFailures = Spvc#spvcObj.spvcRetryFailures + 1},
- send_spvcFailingAlarm(Spvc#spvcObj.spvcEntry),
- case check_limits(Spvc1) of
- {ok,_,_} ->
- Spvc1#spvcObj{currentState = rest_in_peace};
- {retry_threshold,_,_} ->
- Spvc2 = Spvc1#spvcObj{currentState = rest_in_peace},
- case Spvc2#spvcObj.spvcRetryThreshold of
- 0 ->
- ok;
- _ ->
- sccmManager:cast_to_sccm(spvcLib:get_cp(om_node),spvcOrig,call_failure,[Spvc2])
- end,
- Spvc2
- end.
-
-new_state_active(Spvc) ->
- debug_disabled,
- update_state(Spvc,3),
- Spvc#spvcObj{spvcRetryFailures = 0,
- currentState = active}.
-
-new_state_created(Spvc,SetCols) ->
- debug_disabled,
- update_state(Spvc,created),
- case spvcSNMP:is_all_values(case Spvc#spvcObj.spvcEntry of
- {_,_,_,_} ->
- spvcVcc;
- {_,_,_} ->
- spvcVpc;
- {_,_} ->
- spvcFr;
- [_,_,_,_] ->
- spvcVcc;
- [_,_,_] ->
- spvcVpc;
- [_,_] ->
- spvcFr
- end,SetCols) of
- true ->
- Spvc1 = Spvc#spvcObj{spvcRowStatus = 2,
- currentState = created},
- set_attrs(Spvc1,SetCols);
- false ->
- Spvc1 = Spvc#spvcObj{spvcRowStatus = 3,
- currentState = created},
- set_attrs(Spvc1,SetCols)
- end.
-
-new_state_not_in_service(Spvc) ->
- debug_disabled,
- update_state(Spvc,not_in_service),
- Spvc#spvcObj{currentState = not_in_service,
- spvcRowStatus = 2}.
-
-new_state_awaiting_switch_over(Spvc) ->
- debug_disabled,
- Spvc#spvcObj{currentState = awaiting_switch_over}.
-
-update_state(Spvc,NewState) ->
- State = Spvc#spvcObj.currentState,
- SpvcEntry = Spvc#spvcObj.spvcEntry,
- debug_disabled,
- spvcLib:update_state({State,SpvcEntry},NewState).
-
-send_spvcFailingAlarm(Key) ->
- debug_disabled,
- rpc:cast(spvcLib:get_cp(om_node),spvcLib,send_spvcFailingAlarm,[Key]).
-
-set_call_failure_data_and_send_spvcFailingAlarm({If,Vpi,Leaf}) ->
- debug_disabled,
- Spvc = spvcDataBase:db_read({spvcObj,{If,Vpi,Leaf}}),
- if
- Spvc == [] ->
- ok;
- true ->
- spvcLib:update_state({Spvc#spvcObj.currentState,{If,Vpi,Leaf}},4)
- end;
-set_call_failure_data_and_send_spvcFailingAlarm({If,Vpi,Vci,Leaf}) ->
- debug_disabled,
- Spvc = spvcDataBase:db_read({spvcObj,{If,Vpi,Vci,Leaf}}),
- if
- Spvc == [] ->
- ok;
- true ->
- spvcLib:update_state({Spvc#spvcObj.currentState,{If,Vpi,Vci,Leaf}},4)
- end.
-
-set_attrs(Spvc,SetCols) ->
- case Spvc#spvcObj.spvcEntry of
- {_,_,_,_} ->
- set_attrs_spvcc(Spvc,SetCols);
- {_,_,_} ->
- set_attrs_spvpc(Spvc,SetCols)
- end.
-
-set_attrs_spvcc(Spvc,[{2,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcTargetAddress = Value},
- set_attrs_spvcc(Spvc1,T);
-set_attrs_spvcc(Spvc,[{3,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcTargetSelectType = Value},
- set_attrs_spvcc(Spvc1,T);
-set_attrs_spvcc(Spvc,[{18,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcTargetVpi = Value},
- set_attrs_spvcc(Spvc1,T);
-set_attrs_spvcc(Spvc,[{4,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcTargetVpi = Value},
- set_attrs_spvcc(Spvc1,T);
-set_attrs_spvcc(Spvc,[{5,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcTargetVci = Value},
- set_attrs_spvcc(Spvc1,T);
-set_attrs_spvcc(Spvc,[{6,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcLastReleaseCause = Value},
- set_attrs_spvcc(Spvc1,T);
-set_attrs_spvcc(Spvc,[{7,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcLastReleaseDiagnostic = Value},
- set_attrs_spvcc(Spvc1,T);
-set_attrs_spvcc(Spvc,[{10,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcRetryInterval = Value},
- set_attrs_spvcc(Spvc1,T);
-set_attrs_spvcc(Spvc,[{11,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcRetryTimer = Value},
- set_attrs_spvcc(Spvc1,T);
-set_attrs_spvcc(Spvc,[{12,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcRetryThreshold = Value},
- set_attrs_spvcc(Spvc1,T);
-set_attrs_spvcc(Spvc,[{13,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcRetryFailures = Value},
- set_attrs_spvcc(Spvc1,T);
-set_attrs_spvcc(Spvc,[{14,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcRetryLimit = Value},
- set_attrs_spvcc(Spvc1,T);
-set_attrs_spvcc(Spvc,[{16,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcTargetDlci = Value},
- set_attrs_spvcc(Spvc1,T);
-set_attrs_spvcc(Spvc,[{17,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcTargetType = Value},
- set_attrs_spvcc(Spvc1,T);
-set_attrs_spvcc(Spvc,[_|T]) ->
- set_attrs_spvcc(Spvc,T);
-set_attrs_spvcc(Spvc,[]) ->
- debug_disabled,
- Spvc.
-
-set_attrs_spvpc(Spvc,[{2,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcTargetAddress = Value},
- set_attrs_spvpc(Spvc1,T);
-set_attrs_spvpc(Spvc,[{3,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcTargetSelectType = Value},
- set_attrs_spvpc(Spvc1,T);
-set_attrs_spvpc(Spvc,[{15,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcTargetVpi = Value},
- set_attrs_spvpc(Spvc1,T);
-set_attrs_spvpc(Spvc,[{4,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcTargetVpi = Value},
- set_attrs_spvpc(Spvc1,T);
-set_attrs_spvpc(Spvc,[{5,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcLastReleaseCause = Value},
- set_attrs_spvpc(Spvc1,T);
-set_attrs_spvpc(Spvc,[{6,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcLastReleaseDiagnostic = Value},
- set_attrs_spvpc(Spvc1,T);
-set_attrs_spvpc(Spvc,[{9,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcRetryInterval = Value},
- set_attrs_spvpc(Spvc1,T);
-set_attrs_spvpc(Spvc,[{10,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcRetryTimer = Value},
- set_attrs_spvpc(Spvc1,T);
-set_attrs_spvpc(Spvc,[{11,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcRetryThreshold = Value},
- set_attrs_spvpc(Spvc1,T);
-set_attrs_spvpc(Spvc,[{12,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcRetryFailures = Value},
- set_attrs_spvpc(Spvc1,T);
-set_attrs_spvpc(Spvc,[{13,Value}|T]) ->
- Spvc1 = Spvc#spvcObj{spvcRetryLimit = Value},
- set_attrs_spvpc(Spvc1,T);
-set_attrs_spvpc(Spvc,[_|T]) ->
- set_attrs_spvpc(Spvc,T);
-set_attrs_spvpc(Spvc,[]) ->
- Spvc.
-
-call_failure(Spvc) ->
- debug_disabled,
- Key = case Spvc#spvcObj.spvcFrKey of
- undefined ->
- spvcLib:update_counter(callFailures,1,spvcLib:get_membership(node())),
- atm_spvc;
- _ ->
- spvcLib:update_counter(callFrFailures,1,spvcLib:get_membership(node())),
- fr_spvc
- end,
- Obj = spvcDataBase:db_read({spvcFailures,Key}),
- case Obj#spvcFailures.spvcCallFailuresTrapEnable of
- 1 ->
- EventIndObj = spvcDataBase:db_read({spvcEventIndicator,Key}),
- case EventIndObj#spvcEventIndicator.spvcTimerInd of
- 1 ->
- spvcDataBase:db_write(EventIndObj#spvcEventIndicator{spvcSendEventInd = 1}),
- NI = Obj#spvcFailures.spvcNotificationInterval,
- sysTimer:apply_after(1000 * NI,spvcOrig,timeout_event,[EventIndObj]);
- _ ->
- spvcManager:send_event(Key),
- NI = Obj#spvcFailures.spvcNotificationInterval,
- sysTimer:apply_after(1000 * NI,spvcManager,timeout,[Key]),
- spvcDataBase:db_write(EventIndObj#spvcEventIndicator{spvcTimerInd = 1,
- spvcSendEventInd = 2})
- end;
- _ ->
- ok
- end.
-
-timeout_event(EventIndObj) ->
- spvcDataBase:db_write(EventIndObj#spvcEventIndicator{spvcTimerInd = 2}).
-
-check_limits(Spvc) ->
- debug_disabled,
- T = Spvc#spvcObj.spvcRetryThreshold,
- L = Spvc#spvcObj.spvcRetryLimit,
- F = Spvc#spvcObj.spvcRetryFailures,
- I = Spvc#spvcObj.spvcRetryInterval,
- {check_threshold(F,T),check_limit(F,L),check_interval(I)}.
-
-check_threshold(Failures,Threshold) when Failures == Threshold ->
- debug_disabled,
- retry_threshold;
-check_threshold(Failures,Threshold) ->
- debug_disabled,
- ok.
-
-check_limit(Failures,0) ->
- debug_disabled,
- ok;
-check_limit(Failures,Limit) when Failures < Limit ->
- debug_disabled,
- ok;
-check_limit(Failures,Limit) ->
- debug_disabled,
- retry_limit.
-
-check_interval(0) ->
- no_retries;
-check_interval(I) ->
- I.
-
-start_timer(wait,Spvc) ->
- debug_disabled,
- Key = Spvc#spvcObj.spvcEntry,
- Id = spvcReestablishTimer:apply_after(backoff_delay(Key),spvcServer,cast_to_spvc,[node(),spvcOrig,timeout,[wait,Key]]).
-
-timeout(wait,Key) ->
- debug_disabled,
- case spvcDataBase:db_read({spvcObj,Key}) of
- [] ->
- debug_disabled,
- ok;
- Spvc ->
- case Spvc#spvcObj.currentState of
- wait ->
- IfIndex = element(1,Key),
- case spvcOam:is_reassign_et_in_progress(IfIndex) of
- true ->
- ok;
- _ ->
- orig_state_machine(wait,timeout,Spvc,[])
- end;
- _ ->
- ok
- end
- end;
-timeout(X,Y) ->
- debug_disabled,
- ok.
-
-clear(Spvc) ->
- debug_disabled,
- Key = Spvc#spvcObj.spvcEntry,
- PchKey = case Key of
- {IfIndex_Value,Vpi_Value,Vci_Value,_} ->
- {IfIndex_Value,Vpi_Value,Vci_Value};
- {IfIndex_Value,Vpi_Value,_} ->
- {IfIndex_Value,Vpi_Value};
- [IfIndex_Value,Vpi_Value,Vci_Value,_] ->
- [IfIndex_Value,Vpi_Value,Vci_Value];
- [IfIndex_Value,Vpi_Value,_] ->
- [IfIndex_Value,Vpi_Value]
- end,
- spvcEndPoint:free_tp_spvc(PchKey),
- spvcDataBase:db_delete({spvcObj,Key}),
- update_state(Spvc,clear),
- OrigKey = list_to_tuple([orig] ++ tuple_to_list(Key)),
- case Spvc#spvcObj.currentState of
- created ->
- ok;
- _ ->
- case spvcDataBase:db_read({spvcTpToHcId,OrigKey}) of
- [] ->
- ok;
- #spvcTpToHcId{hcId = HcId} ->
- spvcDataBase:db_delete({spvcHcIdToTp,HcId})
- end,
- ets:delete(spvcTpToHcId,OrigKey),
- spvcReestablishTimer:cancel(Key),
- ets:delete(spvcBackoff,Spvc#spvcObj.spvcEntry)
- end,
- case Spvc#spvcObj.spvcFrKey of
- undefined ->
- sccmManager:cast_to_sccm(spvcLib:get_cp(om_node),spvcEndPoint,remove_tp,[tuple_to_list(PchKey)]);
- FrKey ->
- spvcFr:clean_up(FrKey)
- end,
- case {Spvc#spvcObj.spvcRerCap,Spvc#spvcObj.spvcEntry} of
- {false,_} ->
- ok;
- {true,Entry} when size(Entry) == 3 ->
- spvcDataBase:db_delete({spvcRerVp,Entry});
- {true,Entry} when size(Entry) == 4 ->
- spvcDataBase:db_delete({spvcRerVc,Entry})
- end.
-
-get_link_state(If) when integer(If) ->
- debug_disabled,
- cnhChi:get_link_opstate(If);
-get_link_state(Other) ->
- debug_disabled,
- disabled.
-
-get_link_state_intf(If,Msg) when integer(If) ->
- debug_disabled,
- case cnhChi:get_link_opstate(If) of
- enabled ->
- enabled;
- _ ->
- Om_Node = spvcLib:get_cp(om_node),
- case rpc:call(Om_Node,intfI,get_link_op_state,[If]) of
- {ok,enabled} ->
- enabled;
- Result ->
- disabled
- end
- end;
-get_link_state_intf(Other,Msg) ->
- debug_disabled,
- disabled.
-
-setup(HcId,Setup,Spvc) ->
- case spvcDataBase:db_read({spvcObj,Spvc#spvcObj.spvcEntry}) of
- [] ->
- ok;
- Spvc1 ->
- case Spvc#spvcObj.currentState == Spvc1#spvcObj.currentState of
- true ->
- spvcLib:increase_counter(spvcSaEtStat,Spvc),
- case Spvc#spvcObj.spvcFrKey of
- undefined ->
- do_setup(HcId,Setup,Spvc#spvcObj.spvcRerCap);
- FrKey ->
- do_setup(HcId,Setup,FrKey)
- end;
- _ ->
- ok
- end
- end.
-
-do_setup(HcId,Setup,Type) when Type == undefined; Type == false ->
- debug_disabled,
- ReturnData = {0,HcId},
- L3Data = {0,[HcId,Setup]},
- mdisp:msg(node(),{plcOperator,1,infinity},{HcId,{spvcI,ReturnData}},{ccI,l3_msg,[HcId,spvcI,L3Data]});
-do_setup(HcId,Setup,true) ->
- debug_disabled,
- ReturnData = {0,HcId},
- L3Data = {0,[HcId,Setup]},
- mdisp:msg(node(),{plcOperator,1,infinity},{HcId,{spvcRerI,ReturnData}},{ccI,l3_msg,[HcId,spvcRerI,L3Data]});
-do_setup(HcId,Setup,FrKey) ->
- debug_disabled,
- ReturnData = {0,HcId},
- L3Data = {0,[HcId,Setup]},
- mdisp:msg(node(),{plcOperator,1,infinity},{HcId,{spvcFrI,ReturnData}},{ccI,l3_msg,[HcId,spvcFrI,L3Data]}).
-
-backoff_delay(Key) ->
- debug_disabled,
- Obj = spvcDataBase:db_read({spvcObj,Key}),
- Var = spvcDataBase:db_read({spvcFailures,atm_spvc}),
- {Delay,Flag} = case Obj#spvcObj.spvcRetryFailures of
- 0 ->
- {100,no_alarm};
- 1 ->
- {Obj#spvcObj.spvcRetryInterval,no_alarm};
- _ ->
- Table = get_backoff_table(Key,Obj),
- Max_Delay = Var#spvcFailures.max_delay,
- case Var#spvcFailures.delay_factor * Table#spvcBackoff.delay_time of
- DelayValue when DelayValue < Max_Delay ->
- {DelayValue,no_alarm};
- _ ->
- Org_Retry_Interval = Obj#spvcObj.spvcRetryInterval,
- if
- Org_Retry_Interval < Max_Delay ->
- spvcLib:send_spvcStillTryingAlarm(Key,Table#spvcBackoff.flag),
- {Max_Delay,alarm};
- true ->
- spvcLib:send_spvcStillTryingAlarm(Key,Table#spvcBackoff.flag),
- {Org_Retry_Interval,alarm}
- end
- end
- end,
- ets:insert(spvcBackoff,#spvcBackoff{key = Key,
- delay_time = Delay,
- flag = Flag}),
- round(Delay).
-
-get_backoff_table(Index,Spvc) ->
- case ets:lookup(spvcBackoff,Index) of
- [Obj] ->
- Obj;
- _ ->
- #spvcBackoff{key = Spvc#spvcObj.spvcEntry,
- delay_time = Spvc#spvcObj.spvcRetryInterval,
- flag = no_alarm}
- end.
-
-set_fr_atm_iw_admin_state(FrEndPoint,up,Spvc) ->
- ok;
-set_fr_atm_iw_admin_state(FrEndPoint,NewStatus,Spvc) ->
- ok.
-
-forced_release(FrEndPoint) ->
- FrPerm = spvcDataBase:db_read({spvcFr,FrEndPoint}),
- case FrPerm of
- [] ->
- {error,no_fr_spvc};
- _ ->
- Key = FrPerm#spvcFr.spvcFrAtmEntry,
- Spvc = spvcDataBase:db_read({spvcObj,Key}),
- SpvcFrObj = spvcDataBase:db_read({spvcFrPerm,FrEndPoint}),
- case SpvcFrObj#spvcFrPerm.spvcFrConnect of
- 3 ->
- SpvcTpToHcId = read_spvcTpToHcId(Key),
- Release = spvcEncode:encode_cc_release(31),
- spvcManager:release_un(b_side,SpvcTpToHcId#spvcTpToHcId.hcId,Release,Spvc);
- _ ->
- {error,target_not_owned_by_this_connection}
- end
- end.
-
-
-
diff --git a/lib/dialyzer/test/user_tests_SUITE_data/src/wdp.hrl b/lib/dialyzer/test/user_tests_SUITE_data/src/wdp.hrl
deleted file mode 100644
index fa0e8af8c7..0000000000
--- a/lib/dialyzer/test/user_tests_SUITE_data/src/wdp.hrl
+++ /dev/null
@@ -1,97 +0,0 @@
-
-%%
-%% WAP Port Number Definitions (WDP Appendix B.)
-%%
-
--define(WAP_PORT_WTA_CL_SEC, 2805).
--define(WAP_PORT_WTA_CO_SEC, 2923).
--define(WAP_PORT_PUSH_CL, 2948).
--define(WAP_PORT_PUSH_CL_SEC, 2949).
-
--define(WAP_PORT_CL, 9200).
--define(WAP_PORT_CO, 9201).
--define(WAP_PORT_CL_SEC, 9202).
--define(WAP_PORT_CO_SEC, 9203).
--define(WAP_PORT_VCARD, 9204).
--define(WAP_PORT_VCAL, 9205).
--define(WAP_PORT_VCARD_SEC, 9206).
--define(WAP_PORT_VCAL_SEC, 9207).
-
--define(WAP_PORT_RINGTONE, 5505).
--define(WAP_PORT_OPER_LOGO, 5506).
--define(WAP_PORT_CLI_LOGO, 5507).
-
-%%
-%% WDP Bearer Type Assignments (WDP Appendix C.)
-%%
-
-%%
-%% Names after the tag WAP_BEARER_ is [network]_[bearer_type]_[address_type]
-%%
--define(WAP_BEARER_ANY_ANY_IPV4, 16#00).
--define(WAP_BEARER_ANY_ANY_IPV6, 16#01).
--define(WAP_BEARER_GSM_USSD_ANY, 16#02).
--define(WAP_BEARER_GSM_SMS_GSMMSISDN, 16#03).
--define(WAP_BEARER_ANSI136_GUTS_ANSI136MSISDN, 16#04).
--define(WAP_BEARER_IS95CDMA_SMS_IS637MSISDN, 16#05).
--define(WAP_BEARER_IS95CDMA_CSD_IPV4, 16#06).
--define(WAP_BEARER_IS95CDMA_PACKETDATA_IPV4, 16#07).
--define(WAP_BEARER_ANSI136_CSD_IPV4, 16#08).
--define(WAP_BEARER_ANSI136_PACKETDATA_IPV4, 16#09).
--define(WAP_BEARER_GSM_CSD_IPV4, 16#0a).
--define(WAP_BEARER_GSM_GPRS_IPV4, 16#0b).
--define(WAP_BEARER_GSM_USSD_IPV4, 16#0c).
--define(WAP_BEARER_AMPS_CDPD_IPV4, 16#0d).
--define(WAP_BEARER_PDC_CSD_IPV4, 16#0e).
--define(WAP_BEARER_PDC_PACKETDATA_IPV4, 16#0f).
--define(WAP_BEARER_IDEN_SMS_IDENMSISDN, 16#10).
--define(WAP_BEARER_IDEN_CSD_IPV4, 16#11).
--define(WAP_BEARER_IDEN_PACKETDATA_IPV4, 16#12).
--define(WAP_BEARER_PAGINGNETWORK_FLEX_FLEXMSISDN, 16#13).
--define(WAP_BEARER_PHS_SMS_PHSMSISDN, 16#14).
--define(WAP_BEARER_PHS_CSD_IPV4, 16#15).
--define(WAP_BEARER_GSM_USSD_GSMSERVICECODE, 16#16).
--define(WAP_BEARER_TETRA_SDS_TETRAITSI, 16#17).
--define(WAP_BEARER_TETRA_SDS_TETRAMSISDN, 16#18).
--define(WAP_BEARER_TETRA_PACKETDATA_IPV4, 16#19).
--define(WAP_BEARER_PAGINGNETWORK_REFLEX_REFLEXMSISDN, 16#1a).
--define(WAP_BEARER_GSM_USSD_GSMMSISDN, 16#1b).
--define(WAP_BEARER_MOBITEX_MPAK_MAN, 16#1c).
--define(WAP_BEARER_ANSI136_GHOST_GSMMSISDN, 16#1d).
-
--record(wdp_address,
- {
- bearer,
- address,
- portnum
- }).
-
--record(wdp_sap_info,
- {
- mtu, %% max transmission unit (bytes)
- mru %% max receive unit (bytes)
- }).
-
-%%
-%% Source and destination address are wdp_addresses
-%%
--record(wdp_socket_pair,
- {
- source,
- destination
- }).
-
--record(wdp_local_port,
- {
- port, %% wdp "socket"
- sap, %% source address
- user, %% WDP user process
- monitor %% monitor on WDP user
- }).
-
--record(wdp_local_sap,
- {
- sap, %% source address
- port %% wdp "socket"
- }).
-
diff --git a/lib/dialyzer/test/user_tests_SUITE_data/src/wsp.hrl b/lib/dialyzer/test/user_tests_SUITE_data/src/wsp.hrl
deleted file mode 100644
index 8190bd6f6f..0000000000
--- a/lib/dialyzer/test/user_tests_SUITE_data/src/wsp.hrl
+++ /dev/null
@@ -1,242 +0,0 @@
-
-%% WSP Table 34. PDU Type Assignments
-%%
-
--define(WSP_Connect, 16#01).
--define(WSP_ConnectReply, 16#02).
--define(WSP_Redirect, 16#03).
--define(WSP_Reply, 16#04).
--define(WSP_Disconnect, 16#05).
--define(WSP_Push, 16#06).
--define(WSP_ConfirmedPush, 16#07).
--define(WSP_Suspend, 16#08).
--define(WSP_Resume, 16#09).
-
--define(WSP_Get, 16#40).
--define(WSP_Options, 16#41).
--define(WSP_Head, 16#42).
--define(WSP_Delete, 16#43).
--define(WSP_Trace, 16#44).
-
--define(WSP_Post, 16#60).
--define(WSP_Put, 16#61).
-
--define(WSP_DataFragmentPDU, 16#80).
-
-%%
-%% WSP Table 37. Capability Assignments
-%%
-
--define(WSP_CAP_CLIENT_SDU_SIZE, 16#00).
--define(WSP_CAP_SERVER_SDU_SIZE, 16#01).
--define(WSP_CAP_PROTOCOL_OPTIONS, 16#02).
--define(WSP_CAP_METHOD_MOR, 16#03).
--define(WSP_CAP_PUSH_MOR, 16#04).
--define(WSP_CAP_EXTENDED_METHODS, 16#05).
--define(WSP_CAP_HEADER_CODE_PAGES, 16#06).
--define(WSP_CAP_ALIASES, 16#07).
--define(WSP_CAP_CLIENT_MESSAGE_SIZE, 16#08).
--define(WSP_CAP_SERVER_MESSAGE_SIZE, 16#09).
-
--define(WSP_CODEPAGE_1, 1).
--define(WSP_DEFAULT_CODEPAGE, ?WSP_CODEPAGE_1).
-
--define(ANY_LANGUAGE,128).
-
--define(WSP_10, {1,0}).
--define(WSP_11, {1,1}).
--define(WSP_12, {1,2}).
--define(WSP_13, {1,3}).
--define(WSP_14, {1,4}).
--define(WSP_15, {1,5}).
-
--define(WSP_COMPLIENT_VERSION, ?WSP_15).
--define(WSP_DEFAULT_VERSION, ?WSP_12).
-
--define(WSP_STATUS_CONTINUE, 100).
--define(WSP_STATUS_SWITCHING_PROTOCOLS, 101).
--define(WSP_STATUS_OK, 200).
--define(WSP_STATUS_CREATED, 201).
--define(WSP_STATUS_ACCEPTED, 202).
--define(WSP_STATUS_NON_AUTHORITATIVE_INFORMATION, 203).
--define(WSP_STATUS_NO_CONTENT, 204).
--define(WSP_STATUS_RESET_CONTENT, 205).
--define(WSP_STATUS_PARTIAL_CONTENT, 206).
--define(WSP_STATUS_MULTIPLE_CHOICES, 300).
--define(WSP_STATUS_MOVED_PERMANENTLY, 301).
--define(WSP_STATUS_MOVED_TEMPORARILY, 302).
--define(WSP_STATUS_SEE_OTHER, 303).
--define(WSP_STATUS_NOT_MODIFIED, 304).
--define(WSP_STATUS_USE_PROXY, 305).
--define(WSP_STATUS_RESERVED, 306).
--define(WSP_STATUS_TEMPORARY_REDIRECT, 307).
--define(WSP_STATUS_BAD_REQUEST, 400).
--define(WSP_STATUS_UNAUTHORIZED, 401).
--define(WSP_STATUS_PAYMENT_REQUIRED, 402).
--define(WSP_STATUS_FORBIDDEN, 403).
--define(WSP_STATUS_NOT_FOUND, 404).
--define(WSP_STATUS_METHOD_NOT_ALLOWED, 405).
--define(WSP_STATUS_NOT_ACCEPTABLE, 406).
--define(WSP_STATUS_PROXY_AUTHENTICATION_REQUIRED, 407).
--define(WSP_STATUS_REQUEST_TIMEOUT, 408).
--define(WSP_STATUS_CONFLICT, 409).
--define(WSP_STATUS_GONE, 410).
--define(WSP_STATUS_LENGTH_REQUIRED, 411).
--define(WSP_STATUS_PRECONDITION_FAILED, 412).
--define(WSP_STATUS_REQUEST_ENTITY_TOO_LARGE, 413).
--define(WSP_STATUS_REQUEST_URI_TOO_LARGE, 414).
--define(WSP_STATUS_UNSUPPORTED_MEDIA_TYPE, 415).
--define(WSP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE, 416).
--define(WSP_STATUS_EXPECTATION_FAILED, 417).
--define(WSP_STATUS_INTERNAL_SERVER_ERROR, 500).
--define(WSP_STATUS_NOT_IMPLEMENTED, 501).
--define(WSP_STATUS_BAD_GATEWAY, 502).
--define(WSP_STATUS_SERVICE_UNAVAILABLE, 503).
--define(WSP_STATUS_GATEWAY_TIMEOUT, 504).
--define(WSP_STATUS_HTTP_VERSION_NOT_SUPPORTED, 505).
-
--define(ENCODE_SHORT(X), <<1:1, (X):7>>).
-
--define(ENCODE_LONG(X),
- if (X) =< 16#ff -> <<1, (X):8>>;
- (X) =< 16#ffff -> <<2, (X):16>>;
- (X) =< 16#ffffff -> <<3, (X):24>>;
- (X) =< 16#ffffffff -> <<4, (X):32>>;
- true -> encode_long1(X)
- end).
-
-
--record(wsp_session,
- {
- id, %% uniq session id
- ref, %% address quadruple (socketpair)
- state=null, %% connected, suspended
- version, %% encoding version to use
- capabilities, %% client capabilities
- headers %% client hop-by-hop headers!!!
- }).
-
--record(wsp_header,
- {
- name, %% field name
- value, %% field value (binary value)
- params=[] %% field params [{Name,Value} | Value]
- }).
-
--record(wsp_multipart_entry,
- {
- content_type, %% #wsp_header
- headers=[],
- data=(<<>>)
- }).
-
--record(wsp_capabilities,
- {
- aliases=[], %% [#wdp_address]
- client_sdu_size=1400,
- extended_methods=[], %% [{PduType, Name}]
- header_code_pages=[], %% [{Page,Name}] | [Page]
- protocol_options=[], %% [push,confirmed_push,resume,
- %% acknowledgement_headers]
- method_mor = 10, %% 1?
- push_mor = 10, %% 1?
- server_sdu_size=1400,
- client_message_size,
- server_message_size,
- unknown=[]
- }).
-
-%% WSP PDU records
-
--record(wsp_connect,
- {
- version, %% protocol version, not wsp version?
- capabilities,
- headers
- }).
-
--record(wsp_connect_reply,
- {
- server_session_id,
- capabilities,
- headers=[]
- }).
-
--define(WSP_PERMANENT_REDIRECT, 16#80).
--define(WSP_REUSE_SECURITY, 16#40).
-
--record(wsp_redirect,
- {
- flags=[],
- addresses=[]
- }).
-
--record(wsp_disconnect,
- {
- server_session_id
- }).
-
--record(wsp_get,
- {
- type,
- uri,
- headers=[]
- }).
-
--record(wsp_post,
- {
- type,
- uri,
- content_type, %% #wsp_header
- headers=[],
- data
- }).
-
--record(wsp_reply,
- {
- status,
- content_type, %% #wsp_header
- headers=[],
- data
- }).
-
--record(wsp_data_fragment_pdu,
- {
- headers=[],
- data
- }).
-
--record(wsp_push,
- {
- type = push,
- content_type, %% #wsp_header
- headers=[],
- data
- }).
-
--record(wsp_suspend,
- {
- session_id
- }).
-
--record(wsp_resume,
- {
- session_id,
- capabilities,
- headers
- }).
-
-%% NOTE: not a real pdu
--record(wsp_acknowledgement_headers,
- {
- headers=[]
- }).
-
--record(wsp_unknown_pdu,
- {
- type, %% integer
- data %% the payload
- }).
-
-
-
diff --git a/lib/dialyzer/test/user_tests_SUITE_data/src/wsp_pdu.erl b/lib/dialyzer/test/user_tests_SUITE_data/src/wsp_pdu.erl
deleted file mode 100644
index 596a2f63ac..0000000000
--- a/lib/dialyzer/test/user_tests_SUITE_data/src/wsp_pdu.erl
+++ /dev/null
@@ -1,5423 +0,0 @@
-%%%=======================================================================
-%%% File : wsp_pdu.erl
-%%% Author : Tony Rogvall <[email protected]>
-%%% Description : WSP PDU
-%%% Created : 18 Aug 2003 by <[email protected]>
-%%%=======================================================================
-%%%
-%%% There are a couple of bugs in this file. Some are detected by
-%%% Dialyzer v1.1 starting both from byte code and from source, some
-%%% other ones are detected only starting from sourse, while some
-%%% others go unnoticed (these are identified by "BUG" below). It is
-%%% expected that at least some of them are detected when the new type
-%%% analysis is integrated into Dialyzer. Some other ones, like the
-%%% one with the unused _Acc argument are harder to detect and might
-%%% require different techniques.
-%%%
-%%%=======================================================================
-
--module(wsp_pdu).
--export([encode/1, encode/2, decode/1, decode/2]).
-
-%% The following is just to suppress unused function warnings
--export([decode_address/1, decode_header/2,
- decode_headers/1, decode_mms_version/1, decode_multipart/1,
- encode_headers/1, encode_mms_version/1, encode_multipart/1,
- encode_language/1, encode_short_integer/1,
- fmt_current_date/0,
- format_header/1, format_headers/1,
- parse_header/1, format/1]).
-
--include("wsp.hrl").
--include("wdp.hrl").
-
--ifdef(debug).
--define(dbg(Fmt,Args), io:format(Fmt, Args)).
--else.
--define(dbg(Fmt,Args), ok).
--endif.
-
--define(WARN(Cond, Message),
- if (Cond) ->
- io:format("Warning: ~s\n", [(Message)]);
- true ->
- ok
- end).
-
-
-format(Pdu) ->
- if record(Pdu, wsp_connect) ->
- fmt(Pdu, record_info(fields, wsp_connect));
- record(Pdu, wsp_connect_reply) ->
- fmt(Pdu, record_info(fields, wsp_connect_reply));
- record(Pdu, wsp_redirect) ->
- fmt(Pdu, record_info(fields, wsp_redirect));
- record(Pdu, wsp_disconnect) ->
- fmt(Pdu, record_info(fields, wsp_disconnect));
- record(Pdu, wsp_get) ->
- fmt(Pdu, record_info(fields, wsp_get));
- record(Pdu, wsp_post) ->
- fmt(Pdu, record_info(fields, wsp_post));
- record(Pdu,wsp_reply) ->
- fmt(Pdu, record_info(fields, wsp_reply));
- record(Pdu,wsp_data_fragment_pdu) ->
- fmt(Pdu, record_info(fields, wsp_data_fragment_pdu));
- record(Pdu,wsp_push) ->
- fmt(Pdu, record_info(fields, wsp_push));
- record(Pdu, wsp_suspend) ->
- fmt(Pdu, record_info(fields, wsp_suspend));
- record(Pdu, wsp_resume) ->
- fmt(Pdu, record_info(fields, wsp_resume));
- record(Pdu, wsp_unknown_pdu) ->
- fmt(Pdu, record_info(fields, wsp_unknown_pdu))
- end.
-
-fmt(Pdu, Fs) ->
- [Name | Vs] = tuple_to_list(Pdu),
- lists:flatten(["\n",atom_to_list(Name)," {\n" , fmt1(Fs, Vs), "\n}"]).
-
-fmt1([F|Fs],[V|Vs]) ->
- [io_lib:format(" ~s: ~s;\n", [F,fmt_value(V)]) | fmt1(Fs, Vs)];
-fmt1([], []) ->
- "".
-
-fmt_value(V) when binary(V) -> "#Bin";
-fmt_value(V) -> lists:flatten(io_lib:format("~p",[V])).
-
-
-%%
-%% Wsp pdu encoder
-%%
-encode(Pdu) ->
- encode(Pdu, ?WSP_DEFAULT_VERSION).
-
-encode(Pdu, Version) ->
- ?dbg("encode pdu using encoding version ~p\n", [Version]),
- Enc = encode1(Pdu, Version),
- ?dbg("pdu: ~p\nreversed pdu: ~p\n",
- [Pdu, decode(Enc, Version)]),
- Enc.
-
-
-encode1(Pdu, Version) ->
- case Pdu of
- #wsp_connect_reply {server_session_id=ServerSessionId,
- capabilities=Capabilities,
- headers=Headers} ->
- EncServerSessionId = e_uintvar(ServerSessionId),
- EncCapabilities = encode_capabilities(Capabilities),
- EncCapabilitiesLength = e_uintvar(size(EncCapabilities)),
- EncHeaders = encode_headers(Headers,Version),
- EncHeadersLength = e_uintvar(size(EncHeaders)),
- <<?WSP_ConnectReply,
- EncServerSessionId/binary,
- EncCapabilitiesLength/binary, EncHeadersLength/binary,
- EncCapabilities/binary, EncHeaders/binary>>;
-
- #wsp_reply{ status=Status,
- content_type=ContentType,
- headers=Headers,
- data=Data} ->
- EncStatus = encode_status_code(Status),
- EncContentType = encode_content_type(ContentType,Version),
- EncHeaders = encode_headers(Headers,Version),
- EncHeadersLength = e_uintvar(size(EncContentType)+
- size(EncHeaders)),
- <<?WSP_Reply,
- EncStatus:8,
- EncHeadersLength/binary,
- EncContentType/binary,
- EncHeaders/binary,
- Data/binary>>;
-
- #wsp_post{type=Type, uri=URI, content_type=ContentType,
- headers=Headers, data=Data} ->
- %% WSP_Post, WSP_Put
- PDUType = encode_pdu_type(Type),
- UriLength = e_uintvar(length(URI)),
- EncContentType = encode_content_type(ContentType,Version),
- EncHeaders = encode_headers(Headers,Version),
- EncHeadersLength = e_uintvar(size(EncContentType)+
- size(EncHeaders)),
- %% FIXME
- <<PDUType:8,
- UriLength/binary,
- EncHeadersLength/binary,
- (list_to_binary(URI))/binary,
- EncContentType/binary,
- EncHeaders/binary,
- Data/binary>>;
-
- #wsp_push{type=Type, content_type=ContentType,
- headers=Headers, data=Data} ->
- %% WSP_Push, WSP_ConfirmedPush
- PDUType = encode_pdu_type(Type),
- EncContentType = encode_content_type(ContentType,Version),
- EncHeaders = encode_headers(Headers,Version),
- ?dbg("Version ~p Headers ~p", [Version, Headers]),
- ?dbg("EncHeaders ~p", [EncHeaders]),
- EncHeadersLength = e_uintvar(size(EncContentType)+
- size(EncHeaders)),
- ?dbg("EncCT = ~w ~w", [ContentType, EncContentType]),
- ?dbg("EncHL = ~w", [EncHeadersLength]),
- <<PDUType:8,
- EncHeadersLength/binary,
- EncContentType/binary,
- EncHeaders/binary,
- Data/binary>>;
-
- #wsp_get{type=Type, uri=URI, headers=Headers} ->
- %% WSP_Get, WSP_Options, WSP_Head, WSP_Delete, WSP_Trace
- PDUType = encode_pdu_type(Type),
- UriLength = length(URI),
- EncHeaders = encode_headers(Headers,Version),
- <<PDUType:8,
- (e_uintvar(UriLength))/binary,
- (list_to_binary(URI))/binary,
- EncHeaders/binary>>;
-
- #wsp_redirect { flags = Flags, addresses = Addrs } ->
- Flg = lists:foldl(fun(permanent,F) ->
- ?WSP_PERMANENT_REDIRECT bor F;
- (resue, F) ->
- ?WSP_REUSE_SECURITY bor F
- end, 0, Flags),
- EncAddr = encode_addresses(Addrs),
- <<?WSP_Redirect, Flg:8, EncAddr/binary >>;
-
-
- #wsp_data_fragment_pdu { headers=Headers, data=Data } ->
- EncHeaders = encode_headers(Headers,Version),
- << ?WSP_DataFragmentPDU, EncHeaders/binary, Data/binary >>
- end.
-
-decode(Data) ->
- decode(Data, ?WSP_COMPLIENT_VERSION).
-
-decode(Data0, Version) ->
- case Data0 of
- <<?WSP_Connect:8,PduVersion:8,D0/binary>> ->
- %% 8.2.2.1
- {CapabilitiesLen,D1} = d_uintvar(D0),
- {HeadersLen,D2} = d_uintvar(D1),
- {Capabilities,D3} = split_binary(D2, CapabilitiesLen),
- Caps = decode_capabilities(Capabilities,#wsp_capabilities{}),
- {Headers,D4} = split_binary(D3, HeadersLen),
- DecHeaders = decode_headers(Headers, Version),
- ?WARN(D4 =/= <<>>, "Connect pdu contains trailing data"),
- %% FIXME: warn when D4 is not <<>>
- #wsp_connect{ version = PduVersion,
- capabilities=Caps,
- headers = DecHeaders };
-
- <<?WSP_ConnectReply:8,D0/binary>> ->
- %% 8.2.2.2
- {ServerSessionId,D1} = d_uintvar(D0),
- {CapabilitiesLen,D2} = d_uintvar(D1),
- {HeadersLen,D3} = d_uintvar(D2),
- {Capabilities,D4} = split_binary(D3, CapabilitiesLen),
- Caps = decode_capabilities(Capabilities,#wsp_capabilities{}),
- {Headers,D5} = split_binary(D4, HeadersLen),
- DecHeaders = decode_headers(Headers, Version),
- ?WARN(D5 =/= <<>>, "ConnectReply pdu contains trailing data"),
- #wsp_connect_reply{server_session_id=ServerSessionId,
- capabilities=Caps,
- headers=DecHeaders};
-
- <<?WSP_Redirect:8,Flg:8,D0/binary>> ->
- Flags =
- if Flg band ?WSP_PERMANENT_REDIRECT =/= 0 -> [permanent];
- true -> []
- end ++
- if Flg band ?WSP_REUSE_SECURITY =/= 0 -> [security];
- true -> []
- end,
- Addrs = decode_addresses(D0),
- %% 8.2.2.3 Redirect
- #wsp_redirect{flags=Flags,addresses=Addrs};
-
-
- <<?WSP_Disconnect:8,D0/binary>> ->
- %% 8.2.2.4 Disconnect
- {ServerSessionId,_D1} = d_uintvar(D0),
- #wsp_disconnect{server_session_id=ServerSessionId};
-
- <<?WSP_Get:8,D0/binary>> ->
- {URILength, D1} = d_uintvar(D0),
- <<UriData:URILength/binary,D2/binary>> = D1,
- Hs = decode_headers(D2, Version),
- #wsp_get{type='GET',uri=binary_to_list(UriData),headers=Hs };
-
- <<?WSP_Options:8,D0/binary>> ->
- {URILength, D1} = d_uintvar(D0),
- <<UriData:URILength/binary,D2/binary>> = D1,
- Hs = decode_headers(D2, Version),
- #wsp_get{type='OPTIONS',uri=binary_to_list(UriData),headers=Hs };
-
- <<?WSP_Head:8,D0/binary>> ->
- {URILength, D1} = d_uintvar(D0),
- <<UriData:URILength/binary,D2/binary>> = D1,
- Hs = decode_headers(D2, Version),
- #wsp_get{type='HEAD',uri=binary_to_list(UriData),headers=Hs };
-
- <<?WSP_Delete:8,D0/binary>> ->
- {URILength, D1} = d_uintvar(D0),
- <<UriData:URILength/binary,D2/binary>> = D1,
- Hs = decode_headers(D2, Version),
- #wsp_get{type='DELETE',uri=binary_to_list(UriData),headers=Hs };
-
- <<?WSP_Trace:8,D0/binary>> ->
- {URILength, D1} = d_uintvar(D0),
- <<UriData:URILength/binary,D2/binary>> = D1,
- Hs = decode_headers(D2, Version),
- #wsp_get{type='TRACE',uri=binary_to_list(UriData),headers=Hs };
-
- %% 8.2.3.2 Post
- <<?WSP_Post:8,D0/binary>> ->
- {URILen, D1} = d_uintvar(D0),
- {HL0, D2} = d_uintvar(D1),
- <<UriData:URILen/binary,D3/binary>> = D2,
- {FieldData,D4} = scan_header_data(D3),
- HL1 = (HL0-(size(D3)-size(D4))),
- <<D5:HL1/binary,Data/binary>> = D4,
- ContentType = decode_content_type(FieldData, Version),
- Headers = decode_headers(D5, Version),
- #wsp_post{ type='POST', uri=binary_to_list(UriData),
- content_type=ContentType, headers=Headers, data=Data};
-
- <<?WSP_Put:8,D0/binary>> ->
- {URILen, D1} = d_uintvar(D0),
- {HL0, D2} = d_uintvar(D1),
- <<UriData:URILen/binary,D3/binary>> = D2,
- {FieldData,D4} = scan_header_data(D3),
- HL1 = (HL0-(size(D3)-size(D4))),
- <<D5:HL1/binary,Data/binary>> = D4,
- ContentType = decode_content_type(FieldData, Version),
- Headers = decode_headers(D5, Version),
- #wsp_post{ type='PUT', uri=binary_to_list(UriData),
- content_type=ContentType, headers=Headers, data=Data};
-
- <<?WSP_Reply:8,StatusCode:8,D0/binary>> ->
- %% 8.2.3.3 Reply
- Status = decode_status_code(StatusCode),
- {HL0, D1} = d_uintvar(D0),
- {FieldData, D2} = scan_header_data(D1),
- ContentType = decode_content_type(FieldData, Version),
- %% Headers are headersLength - binary size of content type
- HL1 = (HL0-(size(D1)-size(D2))),
- <<D3:HL1/binary,Data/binary>> = D2,
- Hs = decode_headers(D3, Version),
- #wsp_reply{status=Status, content_type=ContentType,
- headers=Hs, data=Data};
-
- <<?WSP_DataFragmentPDU:8,D0/binary>> ->
- %% 8.2.3.4 Data Fragment PDU
- {HL0, D1} = d_uintvar(D0),
- <<D2:HL0/binary,Data/binary>> = D1,
- Hs = decode_headers(D2, Version),
- #wsp_data_fragment_pdu{headers=Hs, data=Data};
-
- %% 8.2.4.1 Push or ConfirmedPush
- <<?WSP_Push:8,D0/binary>> ->
- {HeadersLength, T200} = d_uintvar(D0),
- {FieldData, T300} = scan_header_data(T200),
- ContentType = decode_content_type(FieldData, Version),
- RealHeadersLength = (HeadersLength-(size(T200)-size(T300))),
- <<T400:RealHeadersLength/binary,Data/binary>> = T300,
- Headers = decode_headers(T400, Version),
- #wsp_push{type=push,content_type=ContentType,
- headers=Headers,data=Data};
-
- <<?WSP_ConfirmedPush:8,D0/binary>> ->
- {HeadersLength, T200} = d_uintvar(D0),
- {FieldData, T300} = scan_header_data(T200),
- ContentType = decode_content_type(FieldData, Version),
- RealHeadersLength = (HeadersLength-(size(T200)-size(T300))),
- <<T400:RealHeadersLength/binary,Data/binary>> = T300,
- Headers = decode_headers(T400, Version),
- #wsp_push{type=confirmed_push,
- content_type=ContentType,
- headers=Headers,data=Data};
-
- <<PDUType:8,T100/binary>> ->
- #wsp_unknown_pdu { type = PDUType, data = T100 }
- end.
-
-
-encode_pdu_type(connect) -> ?WSP_Connect;
-encode_pdu_type(connect_reply) -> ?WSP_ConnectReply;
-encode_pdu_type(redirect) -> ?WSP_Redirect;
-encode_pdu_type(reply) -> ?WSP_Reply;
-encode_pdu_type(disconnect) -> ?WSP_Disconnect;
-encode_pdu_type(push) -> ?WSP_Push;
-encode_pdu_type(confirmed_push) -> ?WSP_ConfirmedPush;
-encode_pdu_type(suspend) -> ?WSP_Suspend;
-encode_pdu_type(resume) -> ?WSP_Resume;
-encode_pdu_type(data_fragment_pdu) -> ?WSP_DataFragmentPDU;
-encode_pdu_type('GET') -> ?WSP_Get;
-encode_pdu_type('OPTIONS') -> ?WSP_Options;
-encode_pdu_type('HEAD') -> ?WSP_Head;
-encode_pdu_type('DELETE') -> ?WSP_Delete;
-encode_pdu_type('TRACE') -> ?WSP_Trace;
-encode_pdu_type('POST') -> ?WSP_Post;
-encode_pdu_type('PUT') -> ?WSP_Put;
-encode_pdu_type(Type) when integer(Type) -> Type.
-
-
-decode_pdu_type(?WSP_Connect) -> connect;
-decode_pdu_type(?WSP_ConnectReply) -> connect_reply;
-decode_pdu_type(?WSP_Redirect) -> redirect;
-decode_pdu_type(?WSP_Reply) -> reply;
-decode_pdu_type(?WSP_Disconnect) -> disconnect;
-decode_pdu_type(?WSP_Push) -> push;
-decode_pdu_type(?WSP_ConfirmedPush) -> confirmed_push;
-decode_pdu_type(?WSP_Suspend) -> suspend;
-decode_pdu_type(?WSP_Resume) -> resume;
-decode_pdu_type(?WSP_DataFragmentPDU) -> data_fragment_pdu;
-decode_pdu_type(?WSP_Get) -> 'GET';
-decode_pdu_type(?WSP_Options) -> 'OPTIONS';
-decode_pdu_type(?WSP_Head) -> 'HEAD';
-decode_pdu_type(?WSP_Delete) -> 'DELETE';
-decode_pdu_type(?WSP_Trace) -> 'TRACE';
-decode_pdu_type(?WSP_Post) -> 'POST';
-decode_pdu_type(?WSP_Put) -> 'PUT';
-decode_pdu_type(Type) -> Type. %% allow unknown pdu types.
-
-
-%% Convert various data types to list
-
-to_list(I) when integer(I) ->
- integer_to_list(I);
-to_list(A) when atom(A) ->
- atom_to_list(A);
-to_list(Version={X,Y}) when integer(X), integer(Y) ->
- format_version(Version);
-to_list(DateTime={{_,_,_},{_,_,_}}) ->
- fmt_date(DateTime);
-to_list(L) when list(L) ->
- L.
-
-
-
-encode_capabilities(Capa) ->
- encode_capabilities(Capa,#wsp_capabilities{}).
-
-encode_capabilities(Cap,Def) ->
- Known =
- [encode_capability(?WSP_CAP_ALIASES,
- Cap#wsp_capabilities.aliases,
- Def#wsp_capabilities.aliases),
- encode_capability(?WSP_CAP_CLIENT_SDU_SIZE,
- Cap#wsp_capabilities.client_sdu_size,
- Def#wsp_capabilities.client_sdu_size),
- encode_capability(?WSP_CAP_SERVER_SDU_SIZE,
- Cap#wsp_capabilities.server_sdu_size,
- Def#wsp_capabilities.server_sdu_size),
- encode_capability(?WSP_CAP_PROTOCOL_OPTIONS,
- Cap#wsp_capabilities.protocol_options,
- Def#wsp_capabilities.protocol_options),
- encode_capability(?WSP_CAP_METHOD_MOR,
- Cap#wsp_capabilities.method_mor,
- Def#wsp_capabilities.method_mor),
- encode_capability(?WSP_CAP_PUSH_MOR,
- Cap#wsp_capabilities.push_mor,
- Def#wsp_capabilities.push_mor),
- encode_capability(?WSP_CAP_EXTENDED_METHODS,
- Cap#wsp_capabilities.extended_methods,
- Def#wsp_capabilities.extended_methods),
- encode_capability(?WSP_CAP_HEADER_CODE_PAGES,
- Cap#wsp_capabilities.header_code_pages,
- Def#wsp_capabilities.header_code_pages),
- encode_capability(?WSP_CAP_CLIENT_MESSAGE_SIZE,
- Cap#wsp_capabilities.client_message_size,
- Def#wsp_capabilities.client_message_size),
- encode_capability(?WSP_CAP_SERVER_MESSAGE_SIZE,
- Cap#wsp_capabilities.server_message_size,
- Def#wsp_capabilities.server_message_size)],
- Unknown =
- lists:map(fun({Id, Data}) when integer(Id) ->
- <<1:1, Id:7, Data/binary>>;
- ({Id,Data}) ->
- <<(encode_text_string(Id))/binary, Data/binary>>
- end, Cap#wsp_capabilities.unknown),
- list_to_binary(
- lists:map(fun(<<>>) -> [];
- (Bin) ->
- [e_uintvar(size(Bin)), Bin]
- end, Known ++ Unknown)).
-
-
-
-
-encode_capability(_Capa, Default, Default) ->
- <<>>;
-encode_capability(Capa, Value, _) ->
- case Capa of
- ?WSP_CAP_ALIASES ->
- <<1:1, ?WSP_CAP_ALIASES:7, (encode_addresses(Value))/binary>>;
-
- ?WSP_CAP_CLIENT_SDU_SIZE ->
- <<1:1, ?WSP_CAP_CLIENT_SDU_SIZE:7, (e_uintvar(Value))/binary>>;
-
- ?WSP_CAP_SERVER_SDU_SIZE ->
- <<1:1, ?WSP_CAP_SERVER_SDU_SIZE:7, (e_uintvar(Value))/binary>>;
-
- ?WSP_CAP_PROTOCOL_OPTIONS ->
- Opts = case lists:member(confirmed_push, Value) of
- true -> 16#80;
- false -> 0
- end bor
- case lists:member(push, Value) of
- true -> 16#40;
- false -> 0
- end bor
- case lists:member(resume, Value) of
- true -> 16#20;
- false -> 0
- end bor
- case lists:member(acknowledgement_headers, Value) of
- true -> 16#10;
- false -> 0
- end,
- %% FIXME: symbolic encode/decode of options
- <<1:1, ?WSP_CAP_PROTOCOL_OPTIONS:7, Opts>>;
-
- ?WSP_CAP_METHOD_MOR ->
- <<1:1, ?WSP_CAP_METHOD_MOR:7, (e_uintvar(Value))/binary>>;
-
- ?WSP_CAP_PUSH_MOR ->
- <<1:1, ?WSP_CAP_PUSH_MOR:7, (e_uintvar(Value))/binary>>;
-
- ?WSP_CAP_EXTENDED_METHODS ->
- <<1:1, ?WSP_CAP_EXTENDED_METHODS:7,
- (encode_extended_methods(Value))/binary>>;
-
- ?WSP_CAP_HEADER_CODE_PAGES ->
- Data = list_to_binary(
- lists:map(fun(Page) when integer(Page) -> Page;
- ({Page,Name}) ->
- [Page, encode_text_string(Name)]
- end, Value)),
- <<1:1, ?WSP_CAP_HEADER_CODE_PAGES:7, Data/binary>>;
-
- ?WSP_CAP_CLIENT_MESSAGE_SIZE ->
- <<1:1, ?WSP_CAP_CLIENT_MESSAGE_SIZE:7,
- (e_uintvar(Value))/binary>>;
-
- ?WSP_CAP_SERVER_MESSAGE_SIZE ->
- <<1:1, ?WSP_CAP_SERVER_MESSAGE_SIZE:7,
- (e_uintvar(Value))/binary>>;
- _ when integer(Capa) ->
- <<1:1, Capa:7, Value/binary>>;
- _ when list(Capa) ->
- <<(encode_text_string(Capa))/binary, Value/binary>>
- end.
-
-
-decode_capabilities(<<>>, WspCaps) ->
- WspCaps;
-decode_capabilities(D0,WspCaps) ->
- {Len, D1} = d_uintvar(D0),
- <<Capa:Len/binary, D2/binary>> = D1,
- WspCaps1 =
- case Capa of
- <<1:1, Id:7, Data/binary>> ->
- decode_capa(Id, Data, WspCaps);
- _ ->
- {Id,Data} = d_text_string(Capa),
- decode_capa(Id, Data, WspCaps)
- end,
- decode_capabilities(D2, WspCaps1).
-
-
-
-decode_capa(Id,Data, WspCaps) ->
- case Id of
- ?WSP_CAP_SERVER_SDU_SIZE ->
- {Val,_} = d_uintvar(Data),
- WspCaps#wsp_capabilities{server_sdu_size=Val};
-
- ?WSP_CAP_CLIENT_SDU_SIZE ->
- {Val,_} = d_uintvar(Data),
- WspCaps#wsp_capabilities{client_sdu_size=Val};
-
- ?WSP_CAP_PROTOCOL_OPTIONS ->
- <<POP,_/binary>> = Data,
- Opts =
- if POP band 16#80 == 16#80 -> [confirmed_push];
- true -> []
- end ++
- if POP band 16#40 == 16#40 -> [push];
- true -> []
- end ++
- if POP band 16#20 == 16#20 -> [resume];
- true -> []
- end ++
- if POP band 16#10 == 16#10 -> [acknowledgement_headers];
- true -> []
- end,
- WspCaps#wsp_capabilities{protocol_options=Opts};
-
- ?WSP_CAP_METHOD_MOR ->
- {Val,_} = d_uintvar(Data),
- WspCaps#wsp_capabilities{method_mor=Val};
-
- ?WSP_CAP_PUSH_MOR ->
- {Val,_} = d_uintvar(Data),
- WspCaps#wsp_capabilities{push_mor=Val};
-
- ?WSP_CAP_EXTENDED_METHODS ->
- Extended = decode_extended_methods(Data),
- WspCaps#wsp_capabilities { extended_methods = Extended };
-
- ?WSP_CAP_HEADER_CODE_PAGES ->
- %% Client send [Code(uint8) Name(text-string)]*
- %% Server send [Code(uint8)]*
- io:format("FIXME: Header Code Pages = ~p\n",[Data]),
- WspCaps;
-
- ?WSP_CAP_ALIASES ->
- Aliases = decode_addresses(Data),
- WspCaps#wsp_capabilities { aliases = Aliases };
-
- ?WSP_CAP_CLIENT_MESSAGE_SIZE ->
- {Val,_} = d_uintvar(Data),
- WspCaps#wsp_capabilities{client_message_size=Val};
-
- ?WSP_CAP_SERVER_MESSAGE_SIZE ->
- {Val,_} = d_uintvar(Data),
- WspCaps#wsp_capabilities{server_message_size=Val};
- _ ->
- Unknown = [{Id, Data} | WspCaps#wsp_capabilities.unknown],
- io:format("WARNING: ignoring unknown capability ~p\n",
- [Unknown]),
- WspCaps#wsp_capabilities{unknown = Unknown}
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Headers = [ Header ]
-%% Header = {FieldName, FieldValue}
-%% FieldName = atom()
-%% FieldValue = {Value, Params}
-%% | Value
-%%
-%% Params = [{Param,Value} | Param]
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
--define(WH(Name,Value,Params),
- #wsp_header { name = (Name), value = (Value), params = Params}).
-
-encode_headers(Headers) ->
- encode_headers(Headers, ?WSP_DEFAULT_VERSION).
-
-encode_headers(Headers, Version) ->
- encode_headers(Headers, Version, []).
-
-encode_headers([H|T], Version, Acc) ->
- encode_headers(T, Version, [encode_header(H, Version)|Acc]);
-encode_headers([], _, Acc) ->
- list_to_binary(lists:reverse(Acc)).
-
-
-decode_headers(Bin) ->
- decode_headers(Bin, ?WSP_DEFAULT_VERSION).
-
-decode_headers(<<>>, _Version) ->
- [];
-decode_headers(Data, Version) ->
- decode_headers(Data, [], Version, ?WSP_DEFAULT_CODEPAGE).
-
-
-decode_headers(<<1:1,Code:7,Data/binary>>,Acc,Version,CP) ->
- FieldName = lookup_field_name(Code),
- {FieldData,Data1} = scan_header_data(Data),
- H = decode_header(FieldName, FieldData,Version,CP),
- ?dbg("header: ~p, field data=~p, header=~p\n",
- [FieldName, FieldData, H]),
- if H#wsp_header.name == 'Encoding-Version' ->
- Version1 = H#wsp_header.value,
- ?dbg("Version switch from ~w to ~w\n", [Version, Version1]),
- decode_headers(Data1,[H|Acc],Version1, CP);
- true ->
- decode_headers(Data1,[H|Acc],Version, CP)
- end;
-decode_headers(Data = <<Code,_/binary>>,Acc,Version,CP)
- when Code >= 32, Code < 127->
- {TmpField,Data1} = d_text_string(Data),
- FieldName = normalise_field_name(TmpField),
- {FieldData,Data2} = scan_header_data(Data1),
- H = decode_header(FieldName,FieldData,Version,CP),
- ?dbg("header: ~p, field data=~p, header=~p\n",
- [FieldName, FieldData, H]),
- if H#wsp_header.name == 'Encoding-Version' ->
- Version1 = H#wsp_header.value,
- ?dbg("Version switch from ~w to ~w\n", [Version, Version1]),
- decode_headers(Data2,[H|Acc],Version1, CP);
- true ->
- decode_headers(Data2,[H|Acc],Version, CP)
- end;
-decode_headers(<<CP1,Data/binary>>,Acc,Version,_CP) when CP1 >= 1, CP1 =< 31 ->
- ?dbg("decode_headers: codpage changed form ~w -> ~w\n",[_CP,CP1]),
- decode_headers(Data,Acc,Version,CP1);
-decode_headers(<<16#7f,CP1,Data/binary>>,Acc,Version,_CP) ->
- ?dbg("decode_headers: codpage changed form ~w -> ~w\n",[_CP,CP1]),
- decode_headers(Data,Acc,Version,CP1);
-
-decode_headers(<<>>, Acc, _Version, _CP) ->
- lists:reverse(Acc).
-
-%%
-%% Retrive the header data
-%% (this makes it possible to skip unknown encoding)
-%%
-scan_header_data(Data = <<N,Data0/binary>>) ->
- if N >= 0, N =< 30 ->
- <<Value:N/binary, Data1/binary>> = Data0,
- {{short,Value}, Data1};
- N == 31 ->
- {N1, Data1} = d_uintvar(Data0),
- <<Value:N1/binary, Data2/binary>> = Data1,
- {{long,Value}, Data2};
- N >= 32, N =< 127 ->
- d_text_string(Data);
- true ->
- { N band 16#7f, Data0}
- end.
-
-%%
-%% Decode header: return #wsp_header
-%%
-decode_header(Field, Value) ->
- decode_header(Field, Value,
- ?WSP_DEFAULT_VERSION,
- ?WSP_DEFAULT_CODEPAGE).
-
-decode_header(Field, Value, Version, 1) ->
- case Field of
- 'Accept' ->
- decode_accept(Value, Version);
-
- 'Accept-Charset' when Version >= ?WSP_13 ->
- decode_accept_charset(Value, Version);
- 'Accept-Charset' ->
- decode_accept_charset(Value, Version);
-
- 'Accept-Encoding' when Version >= ?WSP_13 ->
- decode_accept_encoding(Value, Version);
- 'Accept-Encoding' ->
- decode_accept_encoding(Value, Version);
-
- 'Accept-Language' ->
- decode_accept_language(Value, Version);
- 'Accept-Ranges' ->
- decode_accept_ranges(Value, Version);
- 'Age' ->
- decode_age(Value,Version);
- 'Allow' ->
- decode_allow(Value,Version);
- 'Authorization' ->
- decode_authorization(Value,Version);
-
- 'Cache-Control' when Version >= ?WSP_14 ->
- decode_cache_control(Value,Version);
- 'Cache-Control' when Version >= ?WSP_13 ->
- decode_cache_control(Value,Version);
- 'Cache-Control' ->
- decode_cache_control(Value,Version);
-
- 'Connection' ->
- decode_connection(Value,Version);
- 'Content-Base' ->
- decode_content_base(Value,Version);
- 'Content-Encoding' ->
- decode_content_encoding(Value,Version);
- 'Content-Language' ->
- decode_content_language(Value,Version);
- 'Content-Length' ->
- decode_content_length(Value,Version);
- 'Content-Location' ->
- decode_content_location(Value,Version);
- 'Content-Md5' ->
- decode_content_md5(Value,Version);
-
- 'Content-Range' when Version >= ?WSP_13 ->
- decode_content_range(Value,Version);
- 'Content-Range' ->
- decode_content_range(Value,Version);
-
- 'Content-Type' ->
- decode_content_type(Value,Version);
- 'Date' ->
- decode_date(Value, Version);
- 'Etag' ->
- decode_etag(Value,Version);
- 'Expires' ->
- decode_expires(Value,Version);
- 'From' ->
- decode_from(Value,Version);
- 'Host' ->
- decode_host(Value,Version);
- 'If-Modified-Since' ->
- decode_if_modified_since(Value,Version);
- 'If-Match' ->
- decode_if_match(Value,Version);
- 'If-None-Match' ->
- decode_if_none_match(Value,Version);
- 'If-Range' ->
- decode_if_range(Value,Version);
- 'If-Unmodified-Since' ->
- decode_if_unmodified_since(Value,Version);
- 'Location' ->
- decode_location(Value,Version);
- 'Last-Modified' ->
- decode_last_modified(Value,Version);
- 'Max-Forwards' ->
- decode_max_forwards(Value,Version);
- 'Pragma' ->
- decode_pragma(Value,Version);
- 'Proxy-Authenticate' ->
- decode_proxy_authenticate(Value,Version);
- 'Proxy-Authorization' ->
- decode_proxy_authorization(Value,Version);
- 'Public' ->
- decode_public(Value,Version);
- 'Range' ->
- decode_range(Value,Version);
- 'Referer' ->
- decode_referer(Value,Version);
- 'Retry-After' ->
- decode_retry_after(Value,Version);
- 'Server' ->
- decode_server(Value,Version);
- 'Transfer-Encoding' ->
- decode_transfer_encoding(Value,Version);
- 'Upgrade' ->
- decode_upgrade(Value,Version);
- 'User-Agent' ->
- decode_user_agent(Value,Version);
- 'Vary' ->
- decode_vary(Value,Version);
- 'Via' ->
- decode_via(Value,Version);
- 'Warning' ->
- decode_warning(Value,Version);
- 'Www-Authenticate' ->
- decode_www_authenticate(Value,Version);
-
- 'Content-Disposition' when Version >= ?WSP_14 ->
- decode_content_disposition(Value,Version);
- 'Content-Disposition' ->
- decode_content_disposition(Value,Version);
-
- 'X-Wap-Application-Id' when Version >= ?WSP_12 ->
- decode_x_wap_application_id(Value,Version);
-
- 'X-Wap-Content-Uri' when Version >= ?WSP_12 ->
- decode_x_wap_content_uri(Value,Version);
-
- 'X-Wap-Initiator-Uri' when Version >= ?WSP_12 ->
- decode_x_wap_initiator_uri(Value,Version);
-
- 'Accept-Application' when Version >= ?WSP_12 ->
- decode_accept_application(Value,Version);
-
- 'Bearer-Indication' when Version >= ?WSP_12 ->
- decode_bearer_indication(Value,Version);
-
- 'Push-Flag' when Version >= ?WSP_12 ->
- decode_push_flag(Value,Version);
-
- 'Profile' when Version >= ?WSP_12 ->
- decode_profile(Value,Version);
-
- 'Profile-Diff' when Version >= ?WSP_12 ->
- decode_profile_diff(Value,Version);
-
- 'Profile-Warning' when Version >= ?WSP_12 ->
- decode_profile_warning(Value,Version);
-
- 'Expect' when Version >= ?WSP_15 ->
- decode_expect(Value,Version);
- 'Expect' when Version >= ?WSP_13 ->
- decode_expect(Value,Version);
-
- 'Te' when Version >= ?WSP_13 ->
- decode_te(Value,Version);
- 'Trailer' when Version >= ?WSP_13 ->
- decode_trailer(Value,Version);
-
- 'X-Wap-Tod' when Version >= ?WSP_13 ->
- decode_x_wap_tod(Value,Version);
- 'X-Wap.tod' when Version >= ?WSP_13 ->
- decode_x_wap_tod(Value,Version);
-
- 'Content-Id' when Version >= ?WSP_13 ->
- decode_content_id(Value,Version);
- 'Set-Cookie' when Version >= ?WSP_13 ->
- decode_set_cookie(Value,Version);
- 'Cookie' when Version >= ?WSP_13 ->
- decode_cookie(Value,Version);
-
- 'Encoding-Version' when Version >= ?WSP_13 ->
- decode_encoding_version(Value,Version);
- 'Profile-Warning' when Version >= ?WSP_14 ->
- decode_profile_warning(Value,Version);
-
- 'X-Wap-Security' when Version >= ?WSP_14 ->
- decode_x_wap_security(Value,Version);
- 'X-Wap-Loc-Invocation' when Version >= ?WSP_15 ->
- decode_x_wap_loc_invocation(Value,Version); %% ???
- 'X-Wap-Loc-Delivery' when Version >= ?WSP_15 ->
- decode_x_wap_loc_delivery(Value,Version); %% ???
- _ ->
- ?dbg("Warning: none standard field ~p in version ~p codepage=1\n",
- [Field, Version]),
- ?WH(Field, Value, [])
- end;
-decode_header(Field, Value, _Version, _CP) ->
- ?dbg("Warning: none standard field ~p in version ~p codepage=~w\n",
- [Field, _Version, _CP]),
- ?WH(Field, Value, []).
-
-%%
-%% Encode field and value according to version
-%% FIXME: spilt multiple header values (i.e Via) into multiple
-%% headers
-%%
-encode_header(H, Version) ->
- case H#wsp_header.name of
- 'Accept' ->
- [16#80, encode_accept(H, Version)];
- 'Accept-Charset' when Version >= ?WSP_13 ->
- [16#bb, encode_accept_charset(H, Version)];
- 'Accept-Charset' ->
- [16#81, encode_accept_charset(H, Version)];
- 'Accept-Encoding' when Version >= ?WSP_13 ->
- [16#bc, encode_accept_encoding(H, Version)];
- 'Accept-Encoding' ->
- [16#82, encode_accept_encoding(H, Version)];
- 'Accept-Language' ->
- [16#83, encode_accept_language(H, Version)];
- 'Accept-Ranges' ->
- [16#84, encode_accept_ranges(H, Version)];
- 'Accept-Application' when Version >= ?WSP_12 ->
- [16#b2, encode_accept_application(H,Version)];
- 'Age' ->
- [16#85, encode_age(H, Version)];
- 'Allow' ->
- [16#86, encode_allow(H, Version)];
- 'Authorization' ->
- [16#87, encode_authorization(H, Version)];
- 'Cache-Control' when Version >= ?WSP_14 ->
- [16#c7, encode_cache_control(H, Version)];
- 'Cache-Control' when Version >= ?WSP_13 ->
- [16#bd, encode_cache_control(H, Version)];
- 'Cache-Control' ->
- [16#88, encode_cache_control(H, Version)];
- 'Connection' ->
- [16#89, encode_connection(H, Version)];
- 'Content-Base' ->
- [16#8a, encode_content_base(H, Version)];
- 'Content-Encoding' ->
- [16#8b, encode_content_encoding(H, Version)];
-
- 'Content-Language' ->
- [16#8c, encode_content_language(H,Version)];
- 'Content-Length' ->
- [16#8d, encode_content_length(H,Version)];
- 'Content-Location' ->
- [16#8e, encode_content_location(H,Version)];
- 'Content-Md5' ->
- [16#8f, encode_content_md5(H,Version)];
- 'Content-Range' when Version >= ?WSP_13 ->
- [16#be, encode_content_range(H,Version)];
- 'Content-Range' ->
- [16#90, encode_content_range(H,Version)];
- 'Content-Type' ->
- [16#91, encode_content_type(H,Version)];
- 'Date' ->
- [16#92, encode_date(H,Version)];
- 'Etag' ->
- [16#93, encode_etag(H,Version)];
- 'Expires' ->
- [16#94, encode_expires(H,Version)];
- 'From' ->
- [16#95, encode_from(H,Version)];
- 'Host' ->
- [16#96, encode_host(H,Version)];
- 'If-Modified-Since' ->
- [16#97, encode_if_modified_since(H,Version)];
- 'If-Match' ->
- [16#98, encode_if_match(H,Version)];
- 'If-None-Match' ->
- [16#99, encode_if_none_match(H,Version)];
- 'If-Range' ->
- [16#9a, encode_if_range(H,Version)];
- 'If-Unmodified-Since' ->
- [16#9b, encode_if_unmodified_since(H,Version)];
- 'Location' ->
- [16#9c, encode_location(H,Version)];
- 'Last-Modified' ->
- [16#9d, encode_last_modified(H,Version)];
- 'Max-Forwards' ->
- [16#9e, encode_max_forwards(H,Version)];
- 'Pragma' ->
- [16#9f, encode_pragma(H,Version)];
- 'Proxy-Authenticate' ->
- [16#a0, encode_proxy_authenticate(H,Version)];
- 'Proxy-Authorization' ->
- [16#a1, encode_proxy_authorization(H,Version)];
- 'Public' ->
- [16#a2, encode_public(H,Version)];
- 'Range' ->
- [16#a3, encode_range(H,Version)];
- 'Referer' ->
- [16#a4, encode_referer(H,Version)];
- 'Retry-After' ->
- [16#a5, encode_retry_after(H,Version)];
- 'Server' ->
- [16#a6, encode_server(H,Version)];
- 'Transfer-Encoding' ->
- [16#a7, encode_transfer_encoding(H,Version)];
- 'Upgrade' ->
- [16#a8, encode_upgrade(H,Version)];
- 'User-Agent' ->
- [16#a9, encode_user_agent(H,Version)];
- 'Vary' ->
- [16#aa, encode_vary(H,Version)];
- 'Via' ->
- [16#ab, encode_via(H,Version)];
- 'Warning' ->
- [16#ac, encode_warning(H,Version)];
- 'Www-Authenticate' ->
- [16#ad, encode_www_authenticate(H,Version)];
-
- 'Content-Disposition' when Version >= ?WSP_14 ->
- [16#c5, encode_content_disposition(H,Version)];
- 'Content-Disposition' ->
- [16#ae, encode_content_disposition(H,Version)];
-
-
- 'X-Wap-Application-Id' when Version >= ?WSP_12 ->
- [16#af, encode_x_wap_application_id(H,Version)];
- 'X-Wap-Content-Uri' when Version >= ?WSP_12 ->
- [16#b0, encode_x_wap_content_uri(H,Version)];
- 'X-Wap-Initiator-Uri' when Version >= ?WSP_12 ->
- [16#b1, encode_x_wap_initiator_uri(H,Version)];
-
- 'Bearer-Indication' when Version >= ?WSP_12 ->
- [16#b3, encode_bearer_indication(H,Version)];
- 'Push-Flag' when Version >= ?WSP_12 ->
- [16#b4, encode_push_flag(H,Version)];
-
- 'Profile' when Version >= ?WSP_12 ->
- [16#b5, encode_profile(H,Version)];
- 'Profile-Diff' when Version >= ?WSP_12 ->
- [16#b6, encode_profile_diff(H,Version)];
- 'Profile-Warning' when Version >= ?WSP_14 ->
- [16#c4, encode_profile_warning(H,Version)];
- 'Profile-Warning' when Version >= ?WSP_12 ->
- [16#b7, encode_profile_warning(H,Version)];
-
- 'Expect' when Version >= ?WSP_15 ->
- [16#c8, encode_expect(H,Version)];
- 'Expect' when Version >= ?WSP_13 ->
- [16#b8, encode_expect(H,Version)];
- 'Te' when Version >= ?WSP_13 ->
- [16#b9, encode_te(H,Version)];
- 'Trailer' when Version >= ?WSP_13 ->
- [16#ba, encode_trailer(H,Version)];
- 'X-Wap-Tod' when Version >= ?WSP_13 ->
- [16#bf, encode_x_wap_tod(H,Version)];
- 'Content-Id' when Version >= ?WSP_13 ->
- [16#c0, encode_content_id(H,Version)];
- 'Set-Cookie' when Version >= ?WSP_13 ->
- [16#c1, encode_set_cookie(H,Version)];
- 'Cookie' when Version >= ?WSP_13 ->
- [16#c2, encode_cookie(H,Version)];
- 'Encoding-Version' when Version >= ?WSP_13 ->
- [16#c3, encode_encoding_version(H,Version)];
- 'Encoding-Version' when Version < ?WSP_13 ->
- [encode_text_string("Encoding-Version"),
- encode_text_string(lists:flatten(format_version(H#wsp_header.value)))];
-
- 'X-Wap-Security' when Version >= ?WSP_14 ->
- [16#c6, encode_x_wap_security(H,Version)];
- 'X-Wap-Loc-Invocation' when Version >= ?WSP_15 ->
- [16#c9, encode_x_wap_loc_invocation(H,Version)];
- 'X-Wap-Loc-Delivery' when Version >= ?WSP_15 ->
- [16#ca, encode_x_wap_loc_delivery(H,Version)];
- Field when atom(Field) ->
- [encode_text_string(atom_to_list(Field)),
- encode_text_string(H#wsp_header.value)];
- Field when list(Field) ->
- [encode_text_string(Field),
- encode_text_string(H#wsp_header.value)]
- end.
-
-%%
-%% Convert HTTP headers into WSP headers
-%%
-parse_headers([H | Hs]) ->
- parse_header(H, Hs);
-parse_headers([]) ->
- [].
-
-parse_header(H) ->
- parse_header(H, []).
-
-parse_header({FieldName,FieldValue}, Hs) ->
- case single_comma_field(FieldName) of
- true ->
- io:format("parse: ~s: ~s\n", [FieldName, FieldValue]),
- H = parse_hdr(FieldName,FieldValue),
- io:format("header: ~p\n", [H]),
- [H | parse_headers(Hs)];
- false ->
- Values = string:tokens(FieldValue, ","),
- parse_header(FieldName, Values, Hs)
- end.
-
-parse_header(FieldName, [Value|Vs], Hs) ->
- io:format("parse: ~s: ~s\n", [FieldName, Value]),
- H = parse_hdr(FieldName, Value),
- io:format("header: ~p\n", [H]),
- [H | parse_header(FieldName, Vs, Hs)];
-parse_header(_FieldName, [], Hs) ->
- parse_headers(Hs).
-
-
-single_comma_field(Field) ->
- case Field of
- 'Set-Cookie' -> true; %% FIXME (Is multiple!)
- 'Date' -> true;
- 'Expires' -> true;
- 'If-Modified-Since' -> true;
- 'If-Range' -> true;
- 'If-Unmodified-Since' -> true;
- 'Last-Modified' -> true;
- 'Retry-After' -> true;
- 'X-Wap-Tod' -> true;
- _ -> false
- end.
-
-
-parse_hdr(Field, Value0) ->
- Value = trim(Value0),
- case Field of
- 'Accept' -> parse_accept(Value);
- 'Accept-Charset' -> parse_accept_charset(Value);
- 'Accept-Encoding' -> parse_accept_encoding(Value);
- 'Accept-Language' -> parse_accept_language(Value);
- 'Accept-Ranges' -> parse_accept_ranges(Value);
- 'Age' -> parse_age(Value);
- 'Allow' -> parse_allow(Value);
- 'Authorization' -> parse_authorization(Value);
- 'Cache-Control' -> parse_cache_control(Value);
- 'Connection' -> parse_connection(Value);
- 'Content-Base' -> parse_content_base(Value);
- 'Content-Encoding' -> parse_content_encoding(Value);
- 'Content-Language' -> parse_content_language(Value);
- 'Content-Length' -> parse_content_length(Value);
- 'Content-Location' -> parse_content_location(Value);
- 'Content-Md5' -> parse_content_md5(Value);
- 'Content-Range' -> parse_content_range(Value);
- 'Content-Type' -> parse_content_type(Value);
- 'Date' -> parse_date(Value);
- 'Etag' -> parse_etag(Value);
- 'Expires' -> parse_expires(Value);
- 'From' -> parse_from(Value);
- 'Host' -> parse_host(Value);
- 'If-Modified-Since' -> parse_if_modified_since(Value);
- 'If-Match' -> parse_if_match(Value);
- 'If-None-Match' -> parse_if_none_match(Value);
- 'If-Range' -> parse_if_range(Value);
- 'If-Unmodified-Since' -> parse_if_unmodified_since(Value);
- 'Location' -> parse_location(Value);
- 'Last-Modified' -> parse_last_modified(Value);
- 'Max-Forwards' -> parse_max_forwards(Value);
- 'Pragma' -> parse_pragma(Value);
- 'Proxy-Authenticate' -> parse_proxy_authenticate(Value);
- 'Proxy-Authorization' -> parse_proxy_authorization(Value);
- 'Public' -> parse_public(Value);
- 'Range' -> parse_range(Value);
- 'Referer' -> parse_referer(Value);
- 'Retry-After' -> parse_retry_after(Value);
- 'Server' -> parse_server(Value);
- 'Transfer-Encoding' -> parse_transfer_encoding(Value);
- 'Upgrade' -> parse_upgrade(Value);
- 'User-Agent' -> parse_user_agent(Value);
- 'Vary' -> parse_vary(Value);
- 'Via' -> parse_via(Value);
- 'Warning' -> parse_warning(Value);
- 'Www-Authenticate' -> parse_www_authenticate(Value);
- 'Content-Disposition' -> parse_content_disposition(Value);
- 'X-Wap-Application-Id' -> parse_x_wap_application_id(Value);
- 'X-Wap-Content-Uri' -> parse_x_wap_content_uri(Value);
- 'X-Wap-Initiator-Uri' -> parse_x_wap_initiator_uri(Value);
- 'Accept-Application' -> parse_accept_application(Value);
- 'Bearer-Indication' -> parse_bearer_indication(Value);
- 'Push-Flag' -> parse_push_flag(Value);
- 'Profile' -> parse_profile(Value);
- 'Profile-Diff' -> parse_profile_diff(Value);
- 'Profile-Warning' -> parse_profile_warning(Value);
- 'Expect' -> parse_expect(Value);
- 'Te' -> parse_te(Value);
- 'Trailer' -> parse_trailer(Value);
- 'X-Wap-Tod' -> parse_x_wap_tod(Value);
- 'Content-Id' -> parse_content_id(Value);
- 'Set-Cookie' -> parse_set_cookie(Value);
- 'Cookie' -> parse_cookie(Value);
- 'Encoding-Version' -> parse_encoding_version(Value);
- 'X-Wap-Security' -> parse_x_wap_security(Value);
- 'X-Wap-Loc-Invocation' -> parse_x_wap_loc_invocation(Value);
- 'X-Wap-Loc-Delivery' -> parse_x_wap_loc_delivery(Value);
- _ ->
- ?dbg("Warning: header field ~p not recognissed\n",[Field]),
- #wsp_header { name = Field, value = Value}
- end.
-
-%%
-%% Format headers, will combine multiple headers into one
-%% FIXME: if length is < MAX_HTTP_HEADER_LENGTH
-%%
-format_headers(Hs) ->
- format_hdrs(lists:keysort(#wsp_header.name,Hs), []).
-
-format_hdrs([H | Hs], Acc) ->
- V1 = format_value(H),
- format_hdrs(Hs, H#wsp_header.name, V1, Acc);
-format_hdrs([], Acc) ->
- lists:reverse(Acc).
-
-format_hdrs([H|Hs], FieldName, FieldValue, Acc)
- when FieldName == H#wsp_header.name ->
- V1 = format_value(H),
- format_hdrs(Hs, FieldName, [FieldValue,",",V1], Acc);
-format_hdrs(Hs, FieldName, FieldValue, Acc) ->
- format_hdrs(Hs, [{FieldName, lists:flatten(FieldValue)} | Acc]).
-
-
-%%
-%% Format header: #wsp_header => {FieldName, Value}
-%%
-
-format_header(H) ->
- {H#wsp_header.name, format_value(H)}.
-
-format_value(H) ->
- case H#wsp_header.name of
- 'Accept' -> format_accept(H);
- 'Accept-Charset' -> format_accept_charset(H);
- 'Accept-Encoding' -> format_accept_encoding(H);
- 'Accept-Language' -> format_accept_language(H);
- 'Accept-Ranges' -> format_accept_ranges(H);
- 'Age' -> format_age(H);
- 'Allow' -> format_allow(H);
- 'Authorization' -> format_authorization(H);
- 'Cache-Control' -> format_cache_control(H);
- 'Connection' -> format_connection(H);
- 'Content-Base' -> format_content_base(H);
- 'Content-Encoding' -> format_content_encoding(H);
- 'Content-Language' -> format_content_language(H);
- 'Content-Length' -> format_content_length(H);
- 'Content-Location' -> format_content_location(H);
- 'Content-Md5' -> format_content_md5(H);
- 'Content-Range' -> format_content_range(H);
- 'Content-Type' -> format_content_type(H);
- 'Date' -> format_date(H);
- 'Etag' -> format_etag(H);
- 'Expires' -> format_expires(H);
- 'From' -> format_from(H);
- 'Host' -> format_host(H);
- 'If-Modified-Since' -> format_if_modified_since(H);
- 'If-Match' -> format_if_match(H);
- 'If-None-Match' -> format_if_none_match(H);
- 'If-Range' -> format_if_range(H);
- 'If-Unmodified-Since' -> format_if_unmodified_since(H);
- 'Location' -> format_location(H);
- 'Last-Modified' -> format_last_modified(H);
- 'Max-Forwards' -> format_max_forwards(H);
- 'Pragma' -> format_pragma(H);
- 'Proxy-Authenticate' -> format_proxy_authenticate(H);
- 'Proxy-Authorization' -> format_proxy_authorization(H);
- 'Public' -> format_public(H);
- 'Range' -> format_range(H);
- 'Referer' -> format_referer(H);
- 'Retry-After' -> format_retry_after(H);
- 'Server' -> format_server(H);
- 'Transfer-Encoding' -> format_transfer_encoding(H);
- 'Upgrade' -> format_upgrade(H);
- 'User-Agent' -> format_user_agent(H);
- 'Vary' -> format_vary(H);
- 'Via' -> format_via(H);
- 'Warning' -> format_warning(H);
- 'Www-Authenticate' -> format_www_authenticate(H);
- 'Content-Disposition' -> format_content_disposition(H);
- 'X-Wap-Application-Id' -> format_x_wap_application_id(H);
- 'X-Wap-Content-Uri' -> format_x_wap_content_uri(H);
- 'X-Wap-Initiator-Uri' -> format_x_wap_initiator_uri(H);
- 'Accept-Application' -> format_accept_application(H);
- 'Bearer-Indication' -> format_bearer_indication(H);
- 'Push-Flag' -> format_push_flag(H);
- 'Profile' -> format_profile(H);
- 'Profile-Diff' -> format_profile_diff(H);
- 'Profile-Warning' -> format_profile_warning(H);
- 'Expect' -> format_expect(H);
- 'Te' -> format_te(H);
- 'Trailer' -> format_trailer(H);
- 'X-Wap-Tod' -> format_x_wap_tod(H);
- 'Content-Id' -> format_content_id(H);
- 'Set-Cookie' -> format_set_cookie(H);
- 'Cookie' -> format_cookie(H);
- 'Encoding-Version' -> format_encoding_version(H);
- 'X-Wap-Security' -> format_x_wap_security(H);
- 'X-Wap-Loc-Invocation' -> format_x_wap_loc_invocation(H);
- 'X-Wap-Loc-Delivery' -> format_x_wap_loc_delivery(H);
- _Field ->
- ?dbg("Warning: header field ~s not recognissed\n",[_Field]),
- to_list(H#wsp_header.value)
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Encode of field values
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Accept: <content-type> [q=<q-value>] [params]
-%% Type: Multiple
-%% Ref: 8.4.2.7
-%%
-%% Accept-value = Constrained-media | Accept-general-form
-%%
-%% Accept-general-form = Value-length Media-range [Accept-parameters]
-%% Media-range = (Well-known-media | Extension-media) *(Parameter)
-%% Accept-parameters = Q-token Q-value *(Accept-extension)
-%% Accept-extension = Parameter
-%% Constrain-media = Constrained-encoding
-%% Well-known-media = Integer-value
-%% Constrained-encoding = Short-Integer | Extension-media
-%% Q-token = <Octet 128>
-%%
-parse_accept(String) ->
- %% FIXME
- ?WH('Accept',String,[]).
-
-format_accept(H) ->
- [H#wsp_header.value, format_params(H#wsp_header.params)].
-
-encode_accept(H, Version) ->
- case encode_params(H#wsp_header.params,Version) of
- <<>> ->
- encode_well_known_media(H#wsp_header.value, Version);
- Params ->
- Media = encode_well_known_media(H#wsp_header.value, Version),
- e_value(Media, Params)
- end.
-
-decode_accept(Value, Version) when integer(Value) ->
- %% Constrained-encoding: Short-Integer
- ?WH('Accept',decode_well_known_media(Value, Version),[]);
-decode_accept(Value, Version) when list(Value) ->
- ?WH('Accept',decode_well_known_media(Value,Version),[]);
-decode_accept({_,Data}, Version) ->
- %% Accept-general-form
- {Value,QData} = scan_header_data(Data),
- Media_Range = decode_well_known_media(Value,Version),
- Params = decode_params(QData, Version),
- ?WH('Accept',Media_Range,Params).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Accept-Charset: <charset> | * [q=<q-value>]
-%% Type: Multiple
-%% Ref: 8.4.2.8
-%% Note that the definition of this one is a mess!!!!
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_accept_charset(String) ->
- %% FIXME
- ?WH('Accept-Charset',String,[]).
-
-format_accept_charset(H) ->
- [H#wsp_header.value, format_params(H#wsp_header.params)].
-
-encode_accept_charset(H, _Version) ->
- %% FIXME
- encode_text_string(H#wsp_header.value).
-
-decode_accept_charset(0, _Version) ->
- ?WH('Accept-Charset',"*",[]);
-decode_accept_charset(Value, _Version) when integer(Value) ->
- ?WH('Accept-Charset', decode_charset(Value),[]);
-decode_accept_charset(Value, _Version) when list(Value) ->
- ?WH('Accept-Charset',Value,[]);
-decode_accept_charset({short,Data}, _Version) ->
- %% Me guessing that the short form SHOULD be mulit octet integer!!!
- Value = d_long(Data),
- ?WH('Accept-Charset', decode_charset(Value),[]);
-decode_accept_charset({long,Value}, _Version) ->
- {Data1, QData} = scan_header_data(Value),
- CharSet = case Data1 of
- 0 ->
- "*";
- Value1 when integer(Value1) ->
- decode_charset(Value1);
- Value1 when list(Value1) ->
- Value1;
- {short,Value1} ->
- Value2 = d_long(Value1),
- decode_charset(Value2)
- end,
- Params = if QData == <<>> ->
- [];
- true ->
- {QValue,_} = d_q_value(QData),
- {CharSet,[{q, QValue}]}
- end,
- ?WH('Accept-Charset',CharSet, Params).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Accept-Encoding: gzip | compress | deflate | * [q=<q-value>]
-%% Ref:
-%% Type: Multiple
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-parse_accept_encoding(String) ->
- ?WH('Accept-Encoding',String,[]).
-
-format_accept_encoding(H) ->
- [H#wsp_header.value, format_params(H#wsp_header.params)].
-
-encode_accept_encoding(H, _Version) ->
- %% FIXME general form
- case H#wsp_header.value of
- "gzip" -> ?ENCODE_SHORT(0);
- "compress" -> ?ENCODE_SHORT(1);
- "deflate" -> ?ENCODE_SHORT(2);
- Value -> encode_text_string(Value)
- end.
-
-decode_accept_encoding(0, _Version) ->
- ?WH('Accept-Encoding',"gzip",[]);
-decode_accept_encoding(1, _Version) ->
- ?WH('Accept-Encoding',"compress",[]);
-decode_accept_encoding(2, _Version) ->
- ?WH('Accept-Encoding',"deflate",[]);
-decode_accept_encoding(Value, Version) when list(Version) ->
- ?WH('Accept-Encoding',Value,[]);
-decode_accept_encoding({_,Data}, _Version) when binary(Data) ->
- {Enc, Data1} = scan_header_data(Data),
- Params = if Data1 == <<>> ->
- [];
- true ->
- {QVal,_} = d_q_value(Data1),
- [{q, QVal}]
- end,
- case Enc of
- 0 -> ?WH('Accept-Encoding',"gzip",Params);
- 1 -> ?WH('Accept-Encoding',"compress",Params);
- 2 -> ?WH('Accept-Encoding',"deflate",Params);
- 3 -> ?WH('Accept-Encoding',"*",Params);
- _ when list(Enc) ->
- ?WH('Accept-Encoding',Enc,Params)
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%
-%% Accept-Language: * | <lang> [q=<q-value>]
-%% Type: Multiple
-%% Ref: 8.4.2.10
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-parse_accept_language(Value) ->
- ?WH('Accept-Language',Value,[]).
-
-format_accept_language(H) ->
- [H#wsp_header.value, format_params(H#wsp_header.params)].
-
-encode_accept_language(H, _Version) ->
- case H#wsp_header.value of
- "*" -> ?ENCODE_SHORT(0);
- Lang -> case catch encode_lang(Lang) of
- {'EXIT', _} -> encode_text_string(Lang);
- Code -> encode_integer(Code)
- end
- end.
-
-decode_accept_language(0, _Version) ->
- ?WH('Accept-Language',"*",[]);
-decode_accept_language(Value, _Version) when integer(Value) ->
- ?WH('Accept-Language',decode_lang(Value),[]);
-decode_accept_language(Value, _Version) when list(Value) ->
- ?WH('Accept-Language',Value,[]);
-decode_accept_language({_,Data}, _Version) ->
- {Data1, QData} = scan_header_data(Data),
- Charset = case Data1 of
- 0 ->
- "*";
- Value1 when integer(Value1) ->
- decode_lang(Value1);
- Value1 when list(Value1) ->
- Value1;
- {short,Data2} ->
- decode_lang(d_long(Data2))
- end,
- Params =
- if QData == <<>> ->
- [];
- true ->
- {QVal,_} = d_q_value(QData),
- [{q, QVal}]
- end,
- ?WH('Accept-Language',Charset,Params).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Accept-Ranges: none | bytes | <extension>
-%% Type: single
-%% Ref:
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-parse_accept_ranges(Value) ->
- ?WH('Accept-Ranges', Value, []).
-
-format_accept_ranges(H) ->
- H#wsp_header.value.
-
-encode_accept_ranges(H, _Version) ->
- case H#wsp_header.value of
- "none" -> ?ENCODE_SHORT(0);
- "bytes" -> ?ENCODE_SHORT(1);
- Value -> encode_text_string(Value)
- end.
-
-decode_accept_ranges(0, _Version) ->
- ?WH('Accept-Ranges', "none", []);
-decode_accept_ranges(1, _Version) ->
- ?WH('Accept-Ranges', "bytes", []);
-decode_accept_ranges(Value, _Version) when list(Value) ->
- ?WH('Accept-Ranges', Value, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Age: <delta-seconds>
-%% Type: single
-%% Ref:
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-parse_age(Value) ->
- %% FIXME
- ?WH('Age', Value, []).
-
-format_age(H) ->
- integer_to_list(H#wsp_header.value).
-
-encode_age(H, _Version) ->
- e_delta_seconds(H#wsp_header.value).
-
-decode_age(Value, _Version) when integer(Value) ->
- ?WH('Age', Value, []);
-decode_age({short,Data}, _Version) ->
- ?WH('Age', d_long(Data), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Allow: <well-known-method>
-%% Type: multiple
-%% Ref:
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_allow(Value) ->
- ?WH('Allow', parse_well_known_method(Value), []).
-
-format_allow(H) ->
- atom_to_list(H#wsp_header.value).
-
-encode_allow(H, Version) ->
- encode_well_known_method(H#wsp_header.value, Version).
-
-decode_allow(Value, Version) ->
- ?WH('Allow', decode_well_known_method(Value,Version), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Authorization:
-%% Ref: 8.4.2.14
-%% Type: server-to-client
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_authorization(Value) ->
- parse_credentials('Authorization', Value).
-
-format_authorization(H) ->
- format_credentials(H#wsp_header.value, H#wsp_header.params).
-
-encode_authorization(H, Version) ->
- encode_credentials(H#wsp_header.value, H#wsp_header.params, Version).
-
-decode_authorization({_,Data}, Version) ->
- decode_credentials('Authorization', Data, Version).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%%
-%% Cache-Control:
-%% 8.4.2.15
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_cache_control(Value) ->
- case Value of
- "no-cache" -> ?WH('Cache-Control',Value,[]);
- "no-store" -> ?WH('Cache-Control',Value,[]);
- "max-stale" -> ?WH('Cache-Control',Value,[]);
- "only-if-cached" -> ?WH('Cache-Control',Value,[]);
- "private" -> ?WH('Cache-Control',Value,[]);
- "public" -> ?WH('Cache-Control',Value,[]);
- "no-transform" -> ?WH('Cache-Control',Value,[]);
- "must-revalidate" -> ?WH('Cache-Control',Value,[]);
- "proxy-revalidate" -> ?WH('Cache-Control',Value,[]);
- _ ->
- Params = parse_params([Value]),
- ?WH('Cache-Control',"",Params)
- end.
-
-format_cache_control(H) ->
- if H#wsp_header.value == "" ->
- format_params0(H#wsp_header.params);
- true ->
- [H#wsp_header.value, format_params(H#wsp_header.params)]
- end.
-
-
-
-encode_cache_control(H, Version) ->
- case H#wsp_header.value of
- "no-cache" -> ?ENCODE_SHORT(0);
- "no-store" -> ?ENCODE_SHORT(1);
- "max-stale" -> ?ENCODE_SHORT(3);
- "only-if-cached" -> ?ENCODE_SHORT(5);
- "private" -> ?ENCODE_SHORT(7);
- "public" -> ?ENCODE_SHORT(6);
- "no-transform" -> ?ENCODE_SHORT(8);
- "must-revalidate" -> ?ENCODE_SHORT(9);
- "proxy-revalidate" -> ?ENCODE_SHORT(10);
- "" ->
- case H#wsp_header.params of
- [{'no-cache',Field}] ->
- e_value(?ENCODE_SHORT(0),
- e_field_name(Field,Version));
- [{'max-age',Sec}] ->
- e_value(?ENCODE_SHORT(2),
- e_delta_seconds(Sec));
- [{'max-fresh',Sec}] ->
- e_value(?ENCODE_SHORT(4),
- e_delta_seconds(Sec));
- [{'private',Field}] ->
- e_value(?ENCODE_SHORT(7),
- e_field_name(Field,Version));
- [{'s-maxage',Sec}] ->
- e_value(?ENCODE_SHORT(11),
- e_delta_seconds(Sec))
- end;
- Ext ->
- [Param] = H#wsp_header.params,
- e_value(encode_text_string(Ext),
- encode_parameter(Param, Version))
- end.
-
-
-decode_cache_control(Value, _Version) when integer(Value) ->
- case Value of
- 0 -> ?WH('Cache-Control',"no-cache",[]);
- 1 -> ?WH('Cache-Control',"no-store",[]);
- 3 -> ?WH('Cache-Control',"max-stale",[]);
- 5 -> ?WH('Cache-Control',"only-if-cached",[]);
- 7 -> ?WH('Cache-Control',"private",[]);
- 6 -> ?WH('Cache-Control',"public",[]);
- 8 -> ?WH('Cache-Control',"no-transform",[]);
- 9 -> ?WH('Cache-Control',"must-revalidate",[]);
- 10 -> ?WH('Cache-Control',"proxy-revalidate",[])
- end;
-decode_cache_control(Value, _Version) when list(Value) ->
- ?WH('Cache-Control',Value,[]);
-decode_cache_control({_,Data},Version) ->
- {CacheDir, Data1} = scan_header_data(Data),
- case CacheDir of
- 0 ->
- {Field,_} = d_field_name(Data1),
- ?WH('Cache-Control',"",[{'no-cache',Field}]);
- 2 ->
- {Sec,_} = d_integer_value(Data1),
- ?WH('Cache-Control',"",[{'max-age',Sec}]);
- 4 ->
- {Sec,_} = d_integer_value(Data1),
- ?WH('Cache-Control',"",[{'max-fresh',Sec}]);
- 7 ->
- {Field,_} = d_field_name(Data1),
- ?WH('Cache-Control',"",[{private,Field}]);
- 11 ->
- {Sec,_} = d_integer_value(Data1),
- ?WH('Cache-Control',"",[{'s-maxage',Sec}]);
- Ext when list(Ext) ->
- {Param,_} = decode_parameter(Data1, Version),
- ?WH('Cache-Control',Ext,[Param])
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Connection: close | Ext
-%% Type: single
-%% Ref: 8.4.2.16
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-parse_connection(Value) ->
- ?WH('Connection', Value, []).
-
-format_connection(H) ->
- H#wsp_header.value.
-
-encode_connection(H, _Version) ->
- case H#wsp_header.value of
- "close" -> ?ENCODE_SHORT(0);
- Value -> encode_text_string(Value)
- end.
-
-decode_connection(0, _Version) ->
- ?WH('Connection', "close", []);
-decode_connection(Value, _Version) when list(Value) ->
- ?WH('Connection', Value, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Content-Base: <uri>
-%% Type: single
-%% Ref:
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-parse_content_base(Value) ->
- ?WH('Content-Base', Value, []).
-
-format_content_base(H) ->
- H#wsp_header.value.
-
-encode_content_base(H, _Version) ->
- encode_uri_value(H#wsp_header.value).
-
-decode_content_base(Value, _Version) when list(Value) ->
- ?WH('Content-Base', Value, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Content-Encoding:
-%% Ref: 8.4.2.18
-%% Type: single
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_content_encoding(Value) ->
- ?WH('Content-Encoding', tolower(Value), []).
-
-format_content_encoding(H) ->
- H#wsp_header.value.
-
-encode_content_encoding(H, _Version) ->
- case H#wsp_header.value of
- "gzip" -> ?ENCODE_SHORT(0);
- "compress" -> ?ENCODE_SHORT(1);
- "deflate" -> ?ENCODE_SHORT(2);
- Value -> encode_text_string(Value)
- end.
-
-decode_content_encoding(0, _Version) ->
- ?WH('Content-Encoding', "gzip", []);
-decode_content_encoding(1, _Version) ->
- ?WH('Content-Encoding', "compress", []);
-decode_content_encoding(2, _Version) ->
- ?WH('Content-Encoding',"deflate", []);
-decode_content_encoding(Value, _Version) when list(Value) ->
- ?WH('Content-Encoding', Value, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Content-Language:
-%% Ref: 8.4.2.19
-%% Type: single
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_content_language(Value) ->
- ?WH('Content-Language', Value, []).
-
-format_content_language(H) ->
- H#wsp_header.value.
-
-encode_content_language(H, _Version) ->
- case H#wsp_header.value of
- "*" -> ?ENCODE_SHORT(0);
- Lang -> case catch encode_lang(Lang) of
- {'EXIT', _} -> encode_text_string(Lang);
- Code -> encode_integer(Code)
- end
- end.
-
-decode_content_language(0, _Version) ->
- ?WH('Content-Language',"*",[]);
-decode_content_language(Value, _Version) when integer(Value) ->
- ?WH('Content-Language',decode_lang(Value),[]);
-decode_content_language(Value, _Version) when list(Value) ->
- ?WH('Content-Language',Value,[]);
-decode_content_language({short,Data}, _Version) ->
- Value = d_long(Data),
- ?WH('Content-Language',decode_lang(Value),[]);
-decode_content_language(Value, _Version) when list(Value) ->
- ?WH('Content-Language',Value,[]).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Content-Length: <integer-value>
-%% Ref: 8.4.2.20
-%% Type: single
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-parse_content_length(Value) ->
- ?WH('Content-Length', list_to_integer(Value), []).
-
-format_content_length(H) ->
- integer_to_list(H#wsp_header.value).
-
-encode_content_length(H, _Version) ->
- encode_integer(H#wsp_header.value).
-
-decode_content_length(Value, _Version) when integer(Value) ->
- ?WH('Content-Length', Value, []);
-decode_content_length({short,Data}, _Version) ->
- Value = d_long(Data),
- ?WH('Content-Length', Value, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Content-Location: <uri-value>
-%% Ref: 8.4.2.21
-%% Type: single
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-parse_content_location(Value) ->
- ?WH('Content-Location', Value, []).
-
-format_content_location(H) ->
- H#wsp_header.value.
-
-encode_content_location(H, _Version) ->
- encode_uri_value(H#wsp_header.value).
-
-decode_content_location(Value, _Version) when list(Value) ->
- ?WH('Content-Location', decode_uri_value(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Content-Md5: <value-length> <digest>
-%% Ref: 8.4.2.22
-%% Type: single, end-to-end
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-parse_content_md5(Value) ->
- ?WH('Content-Md5', base64:decode(Value), []).
-
-format_content_md5(H) ->
- base64:encode(H#wsp_header.value).
-
-encode_content_md5(H, _Version) ->
- e_value(H#wsp_header.value).
-
-decode_content_md5({_,Data}, _Version) ->
- ?WH('Content-Md5', Data, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Content-Range: <first-byte-pos> <entity-len>
-%% Ref: 8.4.2.23
-%% Type: single
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_content_range(Value) ->
- %% FIXME:
- ?WH('Content-Range', Value, []).
-
-format_content_range(H) ->
- {Pos,Len} = H#wsp_header.value,
- if Len == "*" ->
- ["bytes ", integer_to_list(Pos), "-*/*"];
- true ->
- ["bytes ", integer_to_list(Pos),"-",integer_to_list(Len-1),
- "/", integer_to_list(Len)]
- end.
-
-encode_content_range(H, _Version) ->
- case H#wsp_header.value of
- {Pos, "*"} ->
- e_value(e_uintvar(Pos), <<128>>);
- {Pos, Len} ->
- e_value(e_uintvar(Pos), e_uintvar(Len))
- end.
-
-decode_content_range({_, Data}, _Version) ->
- {Pos, Data1} = d_uintvar(Data),
- Len =
- case Data1 of
- <<128>> -> "*";
- _ ->
- {L, _} = d_uintvar(Data1),
- L
- end,
- ?WH('Content-Range', {Pos,Len}, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Content-Type:
-%% Ref: 8.4.2.24
-%% Type: single, end-to-end
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-parse_content_type(Value) ->
- case string:tokens(Value, ";") of
- [Type | Ps] ->
- Params = parse_params(Ps),
- ?WH('Content-Type', Type, Params);
- [] ->
- ?WH('Content-Type', Value, [])
- end.
-
-format_content_type(H) ->
- [H#wsp_header.value, format_params(H#wsp_header.params)].
-
-encode_content_type(H, Version) ->
- case encode_params(H#wsp_header.params,Version) of
- <<>> ->
- encode_well_known_media(H#wsp_header.value, Version);
- Params ->
- Media = encode_well_known_media(H#wsp_header.value, Version),
- e_value(Media, Params)
- end.
-
-decode_content_type(Value,Version) when integer(Value) ->
- ?WH('Content-Type', decode_well_known_media(Value,Version), []);
-decode_content_type(Value,Version) when list(Value) ->
- ?WH('Content-Type', decode_well_known_media(Value,Version), []);
-decode_content_type({_, Data}, Version) ->
- {Value,Data1} = scan_header_data(Data),
- ContentType = if integer(Value) ->
- decode_well_known_media(Value,Version);
- list(Value) ->
- decode_well_known_media(Value,Version);
- true ->
- {_,Data2} = Value,
- decode_well_known_media(d_long(Data2),Version)
- end,
- Params = decode_params(Data1, Version),
- ?WH('Content-Type', ContentType, Params).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Date: <http-date>
-%% Ref: 8.2.4.25
-%% Type: single, end-to-end
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_date(String) ->
- {DateTime, _} = parse_http_date(String),
- ?WH('Date', DateTime, []).
-
-format_date(H) ->
- fmt_date(H#wsp_header.value).
-
-encode_date(H, _Version) ->
- e_date(H#wsp_header.value).
-
-decode_date(Value, _Version) ->
- ?WH('Date', d_date(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Etag: <text-string>
-%% Ref: 8.2.4.26
-%% Type: single, end-to-end
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-parse_etag(Value) ->
- ?WH('Etag', Value, []).
-
-format_etag(H) ->
- H#wsp_header.value.
-
-encode_etag(H, _Version) ->
- encode_text_string(H#wsp_header.value).
-
-decode_etag(Value, _Version) ->
- ?WH('Etag', decode_text_string(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Expires: <date-value>
-%% Ref: 8.4.2.27
-%% Type: single, end-to-end, server-to-client
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_expires(String) ->
- {DateTime, _} = parse_http_date(String),
- ?WH('Expires', DateTime, []).
-
-format_expires(H) ->
- fmt_date(H#wsp_header.value).
-
-encode_expires(H, _Version) ->
- e_date(H#wsp_header.value).
-
-decode_expires(Value, _Version) ->
- ?WH('Expires', d_date(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% From: <text-string>
-%% Ref: 8.4.2.28
-%% Type: single,
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-parse_from(Value) ->
- ?WH('From', Value, []).
-
-format_from(H) ->
- H#wsp_header.value.
-
-encode_from(H, _Version) ->
- encode_text_string(H#wsp_header.value).
-
-decode_from(Value, _Version) ->
- ?WH('From', decode_text_string(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Host: <text-string>
-%% Ref: 8.4.2.29
-%% Type: single, end-to-end, client-to-server
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_host(Value) ->
- ?WH('Host', Value, []).
-
-format_host(H) ->
- H#wsp_header.value.
-
-encode_host(H, _Version) ->
- encode_text_string(H#wsp_header.value).
-
-decode_host(Value, _Version) ->
- ?WH('Host', decode_text_string(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% If-Modified-Since: <date-value>
-%% Ref: 8.4.2.30
-%% Type: single, end-to-end, client-to-server
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_if_modified_since(String) ->
- {DateTime, _} = parse_http_date(String),
- ?WH('If-Modified-Since', DateTime, []).
-
-format_if_modified_since(H) ->
- fmt_date(H#wsp_header.value).
-
-encode_if_modified_since(H, _Version) ->
- e_date(H#wsp_header.value).
-
-decode_if_modified_since(Value, _Version) ->
- ?WH('If-Modified-Since', d_date(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% If-Match: <text-string>
-%% Ref: 8.4.2.31
-%% Type: end-to-end, client-to-server
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_if_match(Value) ->
- ?WH('If-Match', Value, []).
-
-format_if_match(H) ->
- H#wsp_header.value.
-
-encode_if_match(H, _Version) ->
- encode_text_string(H#wsp_header.value).
-
-decode_if_match(Value, _Version) ->
- ?WH('If-Match', decode_text_string(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% If-None-Match: <text-string>
-%% Ref: 8.4.2.32
-%% Type: end-to-end, client-to-server
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_if_none_match(Value) ->
- ?WH('If-None-Match', Value, []).
-
-format_if_none_match(H) ->
- H#wsp_header.value.
-
-encode_if_none_match(H, _Version) ->
- encode_text_string(H#wsp_header.value).
-
-decode_if_none_match(Value, _Version) ->
- ?WH('If-None-Match', decode_text_string(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% If-Range: Text | Date
-%% Ref: 8.4.2.33
-%% Type: end-to-end, client-to-server
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_if_range(Value) ->
- case catch parse_http_date(Value) of
- {'EXIT', _} ->
- ?WH('If-Range', Value, []);
- {DateTime,_} ->
- ?WH('If-Range', DateTime, [])
- end.
-
-
-format_if_range(H) ->
- case H#wsp_header.value of
- Value when list(Value) -> Value;
- DateTime -> fmt_date(DateTime)
- end.
-
-encode_if_range(H, _Version) ->
- case H#wsp_header.value of
- Value when list(Value) ->
- encode_text_string(Value);
- DateTime ->
- e_date(DateTime)
- end.
-
-decode_if_range(Value, _Version) when list(Value) ->
- ?WH('If-Range', decode_text_string(Value), []);
-decode_if_range(Value, _Version) ->
- ?WH('If-Range', d_date(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% If-Unmodified-Since: <date-value>
-%% Ref: 8.4.2.34
-%% Type: single, end-to-end, client-to-server
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_if_unmodified_since(String) ->
- {DateTime, _} = parse_http_date(String),
- ?WH('If-Unmodified-Since', DateTime, []).
-
-format_if_unmodified_since(H) ->
- fmt_date(H#wsp_header.value).
-
-encode_if_unmodified_since(H, _Version) ->
- e_date(H#wsp_header.value).
-
-decode_if_unmodified_since(Value, _Version) ->
- ?WH('If-Unmodified-Since', d_date(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Location: <uri-value>
-%% Ref: 8.4.2.36
-%% Type: single, end-to-end, server-to-client
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_location(Value) ->
- ?WH('Location', Value, []).
-
-format_location(H) ->
- H#wsp_header.value.
-
-encode_location(H, _Version) ->
- encode_uri_value(H#wsp_header.value).
-
-decode_location(Value, _Version) when list(Value) ->
- ?WH('Location', decode_uri_value(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Last-Modified: <date-value>
-%% Ref: 8.4.2.35
-%% Type: single, end-to-end, server-to-client
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_last_modified(String) ->
- {DateTime, _} = parse_http_date(String),
- ?WH('Last-Modified', DateTime, []).
-
-format_last_modified(H) ->
- fmt_date(H#wsp_header.value).
-
-encode_last_modified(H, _Version) ->
- e_date(H#wsp_header.value).
-
-decode_last_modified(Value, _Version) ->
- ?WH('Last-Modified', d_date(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Max-Forwards: <integer-value>
-%% Ref: 8.4.2.37
-%% Type: single, end-to-end, server-to-client
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_max_forwards(String) ->
- ?WH('Max-Forwards', list_to_integer(String), []).
-
-format_max_forwards(H) ->
- integer_to_list(H#wsp_header.value).
-
-encode_max_forwards(H, _Version) ->
- encode_integer(H#wsp_header.value).
-
-decode_max_forwards(Value, _Version) ->
- decode_integer(Value).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Pragma: No-Cache | value-length Parameter
-%% Ref:
-%% Type:
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_pragma(Value) ->
- ?WH('Pragma',Value,[]).
-
-format_pragma(H) ->
- case H#wsp_header.value of
- "" -> format_params(H#wsp_header.params);
- Value -> Value
- end.
-
-encode_pragma(H, Version) ->
- case H#wsp_header.value of
- "no-cache" -> ?ENCODE_SHORT(0);
- "" ->
- encode_parameter(hd(H#wsp_header.params), Version)
- end.
-
-decode_pragma(0, _Version) ->
- ?WH('Pragma',"no-cache",[]);
-decode_pragma({_,Data}, Version) ->
- {Param,_} = decode_parameter(Data, Version),
- ?WH('Pragma',"",[Param]).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Proxy-Authenticate:
-%% Ref: 8.4.2.39
-%% Type: single?, client-to-proxy
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_proxy_authenticate(Value) ->
- parse_challenge('Proxy-Authenticate', Value).
-
-format_proxy_authenticate(H) ->
- format_challenge(H#wsp_header.value, H#wsp_header.params).
-
-encode_proxy_authenticate(H, Version) ->
- encode_challenge(H#wsp_header.value,
- H#wsp_header.params, Version).
-
-decode_proxy_authenticate({_, Data}, Version) ->
- decode_challenge('Proxy-Authenticate', Data, Version).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Proxy-authorization:
-%% Ref: 8.4.2.40
-%% Type: single?, proxy-to-client
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_proxy_authorization(Value) ->
- parse_credentials('Proxy-Authorization', Value).
-
-format_proxy_authorization(H) ->
- format_credentials(H#wsp_header.value, H#wsp_header.params).
-
-encode_proxy_authorization(H, Version) ->
- encode_credentials(H#wsp_header.value, H#wsp_header.params, Version).
-
-decode_proxy_authorization({_,Data}, Version) ->
- decode_credentials('Proxy-Authorization', Data, Version).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Public: <well-known-method> | Token-Text
-%% Ref: 8.4.2.41
-%% Type:
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_public(Value) ->
- ?WH('Public', parse_well_known_method(Value), []).
-
-format_public(H) ->
- if atom(H#wsp_header.value) ->
- atom_to_list(H#wsp_header.value);
- list(H#wsp_header.value) ->
- H#wsp_header.value
- end.
-
-encode_public(H, Version) ->
- if atom(H#wsp_header.value) ->
- encode_well_known_method(H#wsp_header.value,Version);
- list(H#wsp_header.value) ->
- encode_text_string(H#wsp_header.value)
- end.
-
-decode_public(Value, _Version) when list(Value) ->
- ?WH('Public', Value, []);
-decode_public(Value, Version) ->
- ?WH('Public', decode_well_known_method(Value,Version), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Range:
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-parse_range(Value) ->
- %% FIXME:
- ?WH('Range', Value, []).
-
-format_range(H) ->
- case H#wsp_header.value of
- {First,undefined} ->
- ["bytes=", integer_to_list(First), "-"];
- {First,Last} ->
- ["bytes=", integer_to_list(First), "-", integer_to_list(Last)];
- Len when integer(Len) ->
- ["bytes=-", integer_to_list(Len)]
- end.
-
-encode_range(H, _Version) ->
- case H#wsp_header.value of
- {First,undefined} ->
- e_value(?ENCODE_SHORT(0),
- e_uintvar(First));
- {First,Last} ->
- e_value(?ENCODE_SHORT(0),
- e_uintvar(First),
- e_uintvar(Last));
- Len when integer(Len) ->
- e_value(?ENCODE_SHORT(1),
- e_uintvar(Len))
- end.
-
-decode_range({_,Data}, _Version) ->
- case scan_header_data(Data) of
- {0, Data1} ->
- case d_uintvar(Data1) of
- {First, <<>>} ->
- ?WH('Range', {First, undefined},[]);
- {First, Data2} ->
- {Last, _} = d_uintvar(Data2),
- ?WH('Range', {First, Last}, [])
- end;
- {1, Data1} ->
- {Len, _} =d_uintvar(Data1),
- ?WH('Range', Len, [])
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Referer: <uri-value>
-%% Ref: 8.4.2.43
-%% Type: single
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_referer(Value) ->
- ?WH('Referer', Value, []).
-
-format_referer(H) ->
- H#wsp_header.value.
-
-encode_referer(H, _Version) ->
- encode_uri_value(H#wsp_header.value).
-
-decode_referer(Value, _Version) when list(Value) ->
- ?WH('Referer', decode_uri_value(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Retry-After: Value-length (Retry-date-value | Retry-delta-seconds)
-%% Ref: 8.4.2.44
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_retry_after(Value) ->
- case catch parse_http_date(Value) of
- {'EXIT', _} ->
- ?WH('Retry-After', list_to_integer(Value), []);
- {DateTime,_} ->
- ?WH('Retry-After', DateTime, [])
- end.
-
-format_retry_after(H) ->
- Value = H#wsp_header.value,
- if integer(Value) ->
- integer_to_list(Value);
- true ->
- fmt_date(Value)
- end.
-
-encode_retry_after(H, _Version) ->
- Value = H#wsp_header.value,
- if integer(Value) ->
- e_value(?ENCODE_SHORT(1),
- e_delta_seconds(Value));
- true ->
- e_value(?ENCODE_SHORT(0),
- e_date(Value))
- end.
-
-decode_retry_after({_,Data}, _Version) ->
- case scan_header_data(Data) of
- {0, Data1} ->
- ?WH('Retry-After', d_date(Data1), []);
- {1, Data1} ->
- case scan_header_data(Data1) of
- Sec when integer(Sec) ->
- ?WH('Retry-After', Sec, []);
- {short,Data2} ->
- ?WH('Retry-After', d_long(Data2), [])
- end
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Server: <text-string>
-%% Ref: 8.4.2.45
-%% Type: server-to-client
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_server(Value) ->
- ?WH('Server', Value, []).
-
-format_server(H) ->
- H#wsp_header.value.
-
-encode_server(H, _Version) ->
- encode_text_string(H#wsp_header.value).
-
-decode_server(Value, _Version) ->
- ?WH('Server', decode_text_string(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Transfer-Encoding:
-%% Ref: 8.4.2.46
-%% Type: hop-by-hop
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_transfer_encoding(Value) ->
- ?WH('Transfer-Encoding', Value, []).
-
-format_transfer_encoding(H) ->
- H#wsp_header.value.
-
-encode_transfer_encoding(H, _Version) ->
- case H#wsp_header.value of
- "chunked" -> ?ENCODE_SHORT(0);
- Value -> encode_text_string(Value)
- end.
-
-decode_transfer_encoding(0, _Version) ->
- ?WH('Transfer-Encoding', "chunked", []);
-decode_transfer_encoding(Value, _Version) when list(Value)->
- ?WH('Transfer-Encoding', Value, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Upgrade: Text-String
-%% Ref: 8.4.2.47
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_upgrade(Value) ->
- ?WH('Upgrade', Value, []).
-
-format_upgrade(H) ->
- H#wsp_header.value.
-
-encode_upgrade(H, _Version) ->
- encode_text_string(H#wsp_header.value).
-
-decode_upgrade(Value, _Version) when list(Value) ->
- ?WH('Upgrade', Value, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% User-Agent:
-%% Ref: 8.4.2.48
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_user_agent(Value) ->
- ?WH('User-Agent', Value, []).
-
-format_user_agent(H) ->
- H#wsp_header.value.
-
-encode_user_agent(H, _Version) ->
- encode_text_string(H#wsp_header.value).
-
-decode_user_agent(Value, _Version) ->
- ?WH('User-Agent', Value, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Vary: Well-known-header-field | Token-text
-%% Ref: 8.4.2.49
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_vary(Value) ->
- ?WH('Vary', normalise_field_name(Value), []).
-
-format_vary(H) ->
- to_list(H#wsp_header.value).
-
-encode_vary(H, Version) ->
- e_field_name(H#wsp_header.value, Version).
-
-decode_vary(Value, _Version) when integer(Value) ->
- ?WH('Vary', lookup_field_name(Value), []);
-decode_vary(Value, _Version) when list(Value) ->
- ?WH('Vary', Value, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Via: <text-string>
-%% Ref: 8.4.2.50
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_via(Value) ->
- ?WH('Via', Value, []).
-
-format_via(H) ->
- H#wsp_header.value.
-
-encode_via(H, _Version) ->
- encode_text_string(H#wsp_header.value).
-
-decode_via(Value, _Version) when list(Value) ->
- ?WH('Via', Value, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Warning: Warn-Code | Warning-value
-%% Ref: 8.4.2.51
-%% Type: general, multiple
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_warning(Value) ->
- case string:tokens(Value, " ") of
- [Code] ->
- ?WH('Warning', {list_to_integer(Code),"",""}, []);
- [Code,Agent,Text] ->
- ?WH('Warning', {list_to_integer(Code), Agent, Text}, [])
- end.
-
-format_warning(H) ->
- case H#wsp_header.value of
- {Code, "", ""} ->
- integer_to_list(Code);
- {Code, Agent, Text} ->
- [integer_to_list(Code), " ", Agent, " ", Text]
- end.
-
-encode_warning(H, _Version) ->
- case H#wsp_header.value of
- {Code,"",""} ->
- ?ENCODE_SHORT(Code);
- {Code, Agent, Text} ->
- e_value(?ENCODE_SHORT(Code),
- encode_text_string(Agent),
- encode_text_string(Text))
- end.
-
-decode_warning(Value, _Version) when integer(Value) ->
- ?WH('Warning', {Value, "", ""}, []);
-decode_warning({_, Data}, _Version) ->
- {Code,Data1}= scan_header_data(Data),
- {Agent,Data2} = d_text_string(Data1),
- {Text,_Data3} = d_text_string(Data2),
- ?WH('Warning', {Code,Agent,Text}, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% WWW-Authenticate: challenge
-%% Ref: 8.4.2.52
-%% Type: single? client-to-server
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_www_authenticate(Value) ->
- parse_challenge('Www-Authenticate', Value).
-
-format_www_authenticate(H) ->
- format_challenge(H#wsp_header.value, H#wsp_header.params).
-
-encode_www_authenticate(H, Version) ->
- encode_challenge(H#wsp_header.value,
- H#wsp_header.params, Version).
-
-decode_www_authenticate({_, Data}, Version) ->
- decode_challenge('Www-Authenticate', Data, Version).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Content-Disposition: "form-data" | "attachment" [<param>]*
-%% Ref: 8.4.2.53
-%% Type: single
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_content_disposition(Value) ->
- ?WH('Content-Disposition', Value, []).
-
-format_content_disposition(H) ->
- [H#wsp_header.value, format_params(H#wsp_header.params)].
-
-encode_content_disposition(H, Version) ->
- case H#wsp_header.value of
- "form-data" ->
- e_value(?ENCODE_SHORT(0),
- encode_params(H#wsp_header.params, Version));
- "attachment" ->
- e_value(?ENCODE_SHORT(1),
- encode_params(H#wsp_header.params, Version))
- end.
-
-decode_content_disposition({_,Data}, Version) when binary(Data) ->
- case scan_header_data(Data) of
- {0, Data1} ->
- Params = decode_params(Data1, Version),
- ?WH('Content-Disposition', "form-data", Params);
- {1, Data1} ->
- Params = decode_params(Data1, Version),
- ?WH('Content-Disposition', "attachment", Params)
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% X-Wap-Application-Id:
-%% Ref: 8.4.2.54
-%% Type:
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_x_wap_application_id(Value) ->
- ?WH('X-Wap-Application-Id', Value, []).
-
-format_x_wap_application_id(H) ->
- H#wsp_header.value.
-
-encode_x_wap_application_id(H, _Version) ->
- encode_push_application(H#wsp_header.value).
-
-decode_x_wap_application_id(Value, _Version) ->
- ?WH('X-Wap-Application-Id', decode_push_application(Value),[]).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% X-Wap-Content-Uri: <uri-value>
-%% Ref: 8.4.2.55
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_x_wap_content_uri(Value) ->
- ?WH('X-Wap-Content-Uri', Value, []).
-
-format_x_wap_content_uri(H) ->
- H#wsp_header.value.
-
-encode_x_wap_content_uri(H, _Version) ->
- encode_uri_value(H#wsp_header.value).
-
-decode_x_wap_content_uri(Value, _Version) when list(Value) ->
- ?WH('X-Wap-Content-Uri', decode_uri_value(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% X-Wap-Initiator-Uri: <uri-value>
-%% Ref: 8.4.2.56
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_x_wap_initiator_uri(Value) ->
- ?WH('X-Wap-Initiator-Uri', Value, []).
-
-format_x_wap_initiator_uri(H) ->
- H#wsp_header.value.
-
-encode_x_wap_initiator_uri(H, _Version) ->
- encode_uri_value(H#wsp_header.value).
-
-decode_x_wap_initiator_uri(Value, _Version) when list(Value) ->
- ?WH('X-Wap-Initiator-Uri', decode_uri_value(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Accept-Application: Any-Application | Appication-Id-Value
-%% Ref: 8.4.2.57
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_accept_application(Value) ->
- ?WH('Accept-Application', Value, []).
-
-format_accept_application(H) ->
- H#wsp_header.value.
-
-
-encode_accept_application(H, _Version) ->
- case H#wsp_header.value of
- "*" -> ?ENCODE_SHORT(0);
- Value ->
- case catch encode_push_application(Value) of
- {'EXIT',_} ->
- encode_uri_value(Value);
- App ->
- encode_integer(App)
- end
- end.
-
-decode_accept_application(0, _Version) ->
- ?WH('Accept-Application', "*", []);
-decode_accept_application(Value, _Version) when integer(Value) ->
- ?WH('Accept-Application', decode_push_application(Value), []);
-decode_accept_application({short,Data}, _Version) ->
- Value = d_long(Data),
- ?WH('Accept-Application', decode_push_application(Value), []);
-decode_accept_application(Value, _Version) when list(Value) ->
- ?WH('Accept-Application', decode_uri_value(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Bearer-Indication: <integer-value>
-%% Type: sinlge
-%% Ref: 8.4.2.58
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_bearer_indication(Value) ->
- ?WH('Bearer-Indication', Value, []).
-
-format_bearer_indication(H) ->
- integer_to_list(H#wsp_header.value).
-
-encode_bearer_indication(H, _Version) ->
- encode_integer(H#wsp_header.value).
-
-decode_bearer_indication(Value, _Version) when integer(Value) ->
- ?WH('Bearer-Indication', Value, []);
-decode_bearer_indication({short,Data}, _Version) ->
- Value = d_long(Data),
- ?WH('Bearer-Indication', Value, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Push-Flag: Short-Integer
-%% Type: single
-%% Ref: 8.4.2.59
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_push_flag(Value) ->
- ?WH('Push-Flag', integer_to_list(Value), []).
-
-format_push_flag(H) ->
- integer_to_list(H#wsp_header.value).
-
-encode_push_flag(H, _Version) ->
- ?ENCODE_SHORT(H#wsp_header.value).
-
-decode_push_flag(Value, _Version) when integer(Value) ->
- ?WH('Push-Flag', Value, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Profile: <uri-value>
-%% Ref: 8.4.2.60
-%% Type: single, hop-by-hop, client-to-proxy
-%%
-%% Note: Normally transfered as 'X-Wap-Profile'
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_profile(Value) ->
- ?WH('Profile', Value, []).
-
-format_profile(H) ->
- H#wsp_header.value.
-
-encode_profile(H, _Version) ->
- encode_uri_value(H#wsp_header.value).
-
-decode_profile(Value, _Version) ->
- ?WH('Profile', decode_uri_value(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Profile-Diff: Value-Length Octets
-%% Ref: 8.4.2.61
-%% Type: single, hop-by-hop, client-to-proxy
-%%
-%% Value is WBXML encoded profile diff information
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_profile_diff(Value) ->
- %% FIXME parse XML code?
- ?WH('Profile-Diff', Value, []).
-
-format_profile_diff(_H) ->
- %% FIXME emit ???
- "WBXML".
-
-encode_profile_diff(H, _Version) ->
- e_value(H#wsp_header.value).
-
-decode_profile_diff({_,Value}, _Version) ->
- ?WH('Profile-Diff', Value, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Profile-Warning: Code
-%% Ref: 8.4.2.62
-%% Type: single
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_profile_warning(Value) ->
- ?WH('Profile-Warning', {Value,"",undefined}, []).
-
-format_profile_warning(H) ->
- {Code,Target,Date} = H#wsp_header.value,
- CodeData = integer_to_list(Code),
- if Target == "", Date == undefined ->
- CodeData;
- Date == undefined ->
- [CodeData," ",Target];
- true ->
- [CodeData," ",Target," ",format_date(Date)]
- end.
-
-
-encode_profile_warning(H, _Version) ->
- {Code,Target,Date} = H#wsp_header.value,
- CodeData = case Code of
- 100 -> ?ENCODE_SHORT(16#10);
- 101 -> ?ENCODE_SHORT(16#11);
- 102 -> ?ENCODE_SHORT(16#12);
- 200 -> ?ENCODE_SHORT(16#20);
- 201 -> ?ENCODE_SHORT(16#21);
- 202 -> ?ENCODE_SHORT(16#22);
- 203 -> ?ENCODE_SHORT(16#23)
- end,
- if Target == "", Date == undefined ->
- CodeData;
- Date == undefined ->
- e_value(CodeData, encode_text_string(Target));
- true ->
- e_value(CodeData, encode_text_string(Target), e_date(Date))
- end.
-
-
-decode_profile_warning(Value, _Version) when integer(Value) ->
- Code = case Value of
- 16#10 -> 100;
- 16#11 -> 101;
- 16#12 -> 102;
- 16#20 -> 200;
- 16#21 -> 201;
- 16#22 -> 202;
- 16#23 -> 203
- end,
- ?WH('Profile-Warning', {Code,"",undefined}, []);
-decode_profile_warning({_, <<1:1, Value:7, Data>>}, _Version) ->
- Code = case Value of
- 16#10 -> 100;
- 16#11 -> 101;
- 16#12 -> 102;
- 16#20 -> 200;
- 16#21 -> 201;
- 16#22 -> 202;
- 16#23 -> 203
- end,
- {Target,Data1} = d_text_string(Data),
- Date =
- if Data1 == <<>> ->
- undefined;
- true ->
- {DateValue,_} = scan_header_data(Data1),
- d_date(DateValue)
- end,
- ?WH('Profile-Warning', {Code,Target,Date}, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Expect: 100-contine | Expect-expression
-%% Ref: 8.4.2.63
-%% Type: client-to-server
-%% Note: Bug in the spec value-length is missing !!!
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_expect(Value) ->
- ?WH('Expect', Value, []).
-
-format_expect(H) ->
- case H#wsp_header.value of
- {Var,Val} ->
- [Var,"=",Val, format_params(H#wsp_header.params)];
- Val when list(Val) ->
- Val
- end.
-
-encode_expect(H, Version) ->
- case H#wsp_header.value of
- "100-continue" ->
- ?ENCODE_SHORT(0);
- {Var,Val} ->
- e_value(encode_text_string(Var),
- encode_text_string(Val),
- encode_params(H#wsp_header.params,Version))
- end.
-
-decode_expect(0, _Version) ->
- ?WH('Expect', "100-continue", []);
-decode_expect({_, Data}, Version) ->
- {Var, Data1} = d_text_string(Data),
- {Val, Data2} = d_text_string(Data1),
- Params = decode_params(Data2, Version),
- ?WH('Expect', {decode_text_string(Var),
- decode_text_string(Val)}, Params).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Te: Trailers | TE-General-From
-%% Ref: 8.4.2.64
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_te(Value) ->
- ?WH('Te', Value, []).
-
-format_te(H) ->
- [H#wsp_header.value, format_params(H#wsp_header.params)].
-
-encode_te(H, Version) ->
- case H#wsp_header.value of
- "trailers" -> ?ENCODE_SHORT(1);
- "chunked" ->
- e_value(?ENCODE_SHORT(2),
- encode_params(H#wsp_header.params,Version));
- "identity" ->
- e_value(?ENCODE_SHORT(3),
- encode_params(H#wsp_header.params,Version));
- "gzip" ->
- e_value(?ENCODE_SHORT(4),
- encode_params(H#wsp_header.params,Version));
- "compress" ->
- e_value(?ENCODE_SHORT(5),
- encode_params(H#wsp_header.params,Version));
- "deflate" ->
- e_value(?ENCODE_SHORT(6),
- encode_params(H#wsp_header.params,Version));
- Value ->
- e_value(encode_text_string(Value),
- encode_params(H#wsp_header.params,Version))
- end.
-
-decode_te(1, _Version) ->
- ?WH('Te', "trailers", []);
-decode_te({_, Data}, _Version) ->
- {Val, Data1} = scan_header_data(Data),
- Value =
- case Val of
- 2 -> "chunked";
- 3 -> "identity";
- 4 -> "gzip";
- 5 -> "compress";
- 6 -> "deflate";
- V when list(V) -> V
- end,
- Params = case Data1 of
- <<>> -> [];
- <<128, QData>> ->
- {QValue, _} = d_q_value(QData),
- [{q, QValue}]
- end,
- ?WH('Te', Value, Params).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Trailer: Well-known-header-field | Token-text
-%% Ref: 8.4.2.65
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_trailer(Value) ->
- ?WH('Trailer', normalise_field_name(Value), []).
-
-format_trailer(H) ->
- to_list(H#wsp_header.value).
-
-encode_trailer(H, Version) ->
- e_field_name(H#wsp_header.value, Version).
-
-decode_trailer(Value, _Version) when integer(Value) ->
- ?WH('Trailer', lookup_field_name(Value), []);
-decode_trailer(Value, _Version) when list(Value) ->
- ?WH('Trailer', Value, []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% X-Wap-Tod:
-%% Ref: 8.4.2.66
-%% Type: hop-by-hop
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_x_wap_tod(String) ->
- {DateTime, _} = parse_http_date(String),
- ?WH('X-Wap-Tod', DateTime, []).
-
-format_x_wap_tod(H) ->
- fmt_date(H#wsp_header.value).
-
-encode_x_wap_tod(H, _Version) ->
- e_date(H#wsp_header.value).
-
-decode_x_wap_tod(Value, _Version) ->
- ?WH('X-Wap-Tod', d_date(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Content-Id: <quoted-string>
-%% Type:
-%% Ref: 8.4.2.67
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_content_id(Value) ->
- ?WH('Content-Id', Value, []).
-
-format_content_id(H) ->
- [$", H#wsp_header.value, $"].
-
-encode_content_id(H, _Version) ->
- encode_quoted_string(H#wsp_header.value).
-
-decode_content_id(Value, _Version) when list(Value) ->
- ?WH('Content-Id', decode_quoted_string(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Set-Cookie: <len> <cookie-version> <cookie-name> <cokie-value> <parm>*
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_set_cookie(String) ->
- %% MEGA FIXME; Cookie-value may be a quoted string and
- %% contain both ,=; etc Fix several cookies on same line!!
- case string:tokens(String, ";") of
- [Cookie | Ps] ->
- case string:tokens(Cookie, "=") of
- [Name,Value] ->
- Params = parse_params(Ps),
- ?WH('Set-Cookie', {{1,0}, Name, Value}, Params);
- [Name] ->
- Params = parse_params(Ps),
- ?WH('Set-Cookie', {{1,0}, Name, ""}, Params)
- end;
- [] ->
- ?WH('Set-Cookie', {{1,0}, String, ""}, [])
- end.
-
-format_set_cookie(H) ->
- case H#wsp_header.value of
- {{1,0},Name,Value} ->
- [Name, "=", Value,format_params(H#wsp_header.params)];
- {Version,Name,Value} ->
- [format_version(Version)," ",
- Name, "=", Value,
- format_params(H#wsp_header.params)]
- end.
-
-encode_set_cookie(H, Version) ->
- {CookieVersion,Name,Value} = H#wsp_header.value,
- e_value(encode_version(CookieVersion),
- encode_text_string(Name),
- encode_text_string(Value),
- encode_params(H#wsp_header.params, Version)).
-
-decode_set_cookie({_, Data}, Version) ->
- {CookieVersion, Data1} = scan_header_data(Data),
- {CookieName, Data2} = scan_header_data(Data1),
- {CookieValue, Data3} = scan_header_data(Data2),
- Params = decode_params(Data3, Version),
- ?WH('Set-Cookie', {decode_version(CookieVersion),
- decode_text_string(CookieName),
- decode_text_string(CookieValue)}, Params).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Cookie:
-%% Ref: 8.4.2.69
-%% Type: single?, client-to-server
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_cookie(Value) ->
- %% FIXME parse cookie version etc
- ?WH('Cookie', {{1,0},Value}, []).
-
-format_cookie(H) ->
- case H#wsp_header.value of
- {{1,0}, Cookies} ->
- lists:map(fun({Name,Value,Ps}) ->
- [Name,"=",Value, format_params(Ps)]
- end, Cookies);
- {Version, Cookies} ->
- [format_version(Version)," ",
- lists:map(fun({Name,Value,Ps}) ->
- [Name,"=",Value, format_params(Ps)]
- end, Cookies)]
- end.
-
-encode_cookie(H, Version) ->
- {Version, Cookies} = H#wsp_header.value,
- e_value(encode_version(Version),
- encode_cookies(Cookies, [])).
-
-encode_cookies([{Name,Value,Ps} | Cs], Acc) ->
- List =
- [encode_text_string(Name),
- encode_text_string(Value) |
- case Ps of
- [{path,P},{domain,D}] ->
- [encode_text_string(P), encode_text_string(D)];
- [{domain,D},{path,P}] ->
- [encode_text_string(P), encode_text_string(D)];
- [{path,P}] ->
- [encode_text_string(P)];
- [{domain,D}] ->
- [encode_text_string(""), encode_text_string(D)];
- [] ->
- []
- end],
- Sz = lists:sum(lists:map(fun(B) -> size(B) end, List)),
- encode_cookies(Cs, [[e_uintvar(Sz) | List] | Acc]);
-encode_cookies([], Acc) ->
- list_to_binary(lists:reverse(Acc)).
-
-
-decode_cookie({_, Data}, _Version) ->
- {CookieVersion, Data1} = scan_header_data(Data),
- Cookies = decode_cookies(Data1, []),
- ?WH('Cookie', {decode_version(CookieVersion), Cookies}, []).
-
-decode_cookies(<<>>, Acc) ->
- lists:reverse(Acc);
-decode_cookies(Data0, _Acc) -> %% IS IGNORING Acc A BUG OR NOT ?
- {Len, Data1} = d_uintvar(Data0),
- <<C0:Len/binary, Data2/binary>> = Data1,
- {Name, C1} = scan_header_data(C0),
- {Value, C2} = scan_header_data(C1),
- {Ps1, C3} =
- case d_text_string(C2) of
- {"", C21} -> {[], C21};
- {Path,C21} -> {[{path,Path}], C21}
- end,
- {Ps2, _} =
- case C3 of
- <<>> -> {[], <<>>};
- _ ->
- {Domain,C4} = d_text_string(C3),
- {[{domain,Domain}], C4}
- end,
- decode_cookies(Data2, [{decode_text_string(Name),
- decode_text_string(Value),
- Ps1++Ps2}]).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Encoding-Version: Version-Value | Value-length Code-Page [Version-Value]
-%% Ref: 8.4.2.70
-%% Type: single, hop-by-hop, client-and-proxys
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_encoding_version(Value) ->
- ?WH('Encoding-Version', parse_version(Value), []).
-
-format_encoding_version(H) ->
- format_version(H#wsp_header.value).
-
-encode_encoding_version(H, _Version) ->
- encode_version(H#wsp_header.value).
-
-decode_encoding_version(Value, _Version) when integer(Value) ->
- ?WH('Encoding-Version', decode_version(Value), []);
-decode_encoding_version(Value, _Version) when list(Value) ->
- %% Note: in this case we parse the Value since we
- %% Must know the Encoding version
- ?WH('Encoding-Version', parse_version(Value), []);
-decode_encoding_version({_,<<_:1,_CodePage:7>>}, _Version) ->
- %% ??? FIXME
- ?WH('Encoding-Version', "", []);
-decode_encoding_version({_,<<_:1,_CodePage:7, Data1/binary>>}, _Version) ->
- {Value,_Data2} = scan_header_data(Data1),
- %% FIXME CodePage
- ?WH('Encoding-Version', decode_version(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% X-Wap-Security:
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_x_wap_security(Value) ->
- ?WH('X-Wap-Security', Value, []).
-
-format_x_wap_security(H) ->
- H#wsp_header.value.
-
-encode_x_wap_security(H, _Version) ->
- encode_text_string(H#wsp_header.value).
-
-decode_x_wap_security(Value, _Version) ->
- ?WH('X-Wap-Security', decode_text_string(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% X-Wap-Loc-Invocation:
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_x_wap_loc_invocation(Value) ->
- ?WH('X-Wap-Loc-Invocation', Value, []).
-
-format_x_wap_loc_invocation(H) ->
- H#wsp_header.value.
-
-encode_x_wap_loc_invocation(H, _Version) ->
- encode_text_string(H#wsp_header.value).
-
-decode_x_wap_loc_invocation(Value, _Version) ->
- ?WH('X-Wap-Loc-Invocation', decode_text_string(Value), []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% X-Wap-Loc-Delivery:
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-parse_x_wap_loc_delivery(Value) ->
- ?WH('X-Wap-Loc-Delivery', Value, []).
-
-format_x_wap_loc_delivery(H) ->
- H#wsp_header.value.
-
-encode_x_wap_loc_delivery(H, _Value) ->
- encode_text_string(H#wsp_header.value).
-
-decode_x_wap_loc_delivery(Value, _Version) ->
- ?WH('X-Wap-Loc-Delivery', decode_text_string(Value), []).
-
-
-%%
-%% Header Field parameters
-%%
-
-parse_params([Param|Ps]) ->
- case string:tokens(Param, "=") of
- [Name,Value0] ->
- Val = trim(Value0),
- P = case trim(tolower(Name)) of
- "q" ->{q,Val};
- "charset" -> {charset,Val};
- "level" -> {level,Val};
- "type" -> {type,Val};
- "name" -> {name,Val};
- "filename" -> {filename,Val};
- "differences" -> {differences,Val};
- "padding" -> {padding,Val};
- "start" -> {start,Val};
- "start-info" -> {'start-info',Val};
- "comment" -> {comment,Val};
- "domain" -> {domain,Val};
- "max-age" -> {'max-age',Val};
- "path" -> {path,Val};
- "secure" -> {secure,no_value};
- "sec" -> {sec, Val};
- "mac" -> {mac, Val};
- "creation-date" -> {'creation-date', Val};
- "modification-date" -> {'modification-date', Val};
- "read-date" -> {'read-date', Val};
- "size" -> {size, Val};
- Nm -> {Nm, Val}
- end,
- [P | parse_params(Ps)];
- _ ->
- parse_params(Ps)
- end;
-parse_params([]) ->
- [].
-
-%% format Params without leading ";"
-format_params0([{Param,no_value}|Ps]) ->
- [to_list(Param) | format_params(Ps)];
-format_params0([{Param,Value}|Ps]) ->
- [to_list(Param),"=",to_list(Value) | format_params(Ps)].
-
-format_params(Ps) ->
- lists:map(fun({Param,no_value}) ->
- ["; ", to_list(Param)];
- ({Param,Value})->
- ["; ", to_list(Param),"=",to_list(Value)]
- end, Ps).
-
-
-encode_params(Params, Version) ->
- list_to_binary(encode_params1(Params,Version)).
-
-encode_params1([Param|Ps], Version) ->
- [ encode_parameter(Param, Version) | encode_params1(Ps, Version)];
-encode_params1([], _Version) ->
- [].
-
-
-decode_params(Data, Version) ->
- decode_params(Data, [], Version).
-
-decode_params(<<>>, Ps, _Version) ->
- lists:reverse(Ps);
-decode_params(Data, Ps, Version) ->
- {ParamVal, Data1} = decode_parameter(Data, Version),
- decode_params(Data1, [ParamVal | Ps], Version).
-
-
-
-
-encode_parameter({ParamName, ParamValue}, Ver) ->
- case ParamName of
- q when Ver >= 16#01 ->
- <<1:1, 16#00:7,
- (encode_typed_field(Ver,'Q-value', ParamValue))/binary>>;
- charset when Ver >= 16#01 ->
- <<1:1, 16#01:7,
- (encode_typed_field(Ver,'Well-known-charset',ParamValue))/binary>>;
- level when Ver >= 16#01 ->
- <<1:1, 16#02:7,
- (encode_typed_field(Ver,'Ver-value',ParamValue))/binary>>;
-
- type when Ver >= ?WSP_12 ->
- <<1:1, 16#09:7,
- (encode_typed_field(Ver,'Constrained-encoding',ParamValue))/binary>>;
- type when Ver >= 16#01 ->
- <<1:1, 16#03:7,
- (encode_typed_field(Ver,'Integer-value',ParamValue))/binary>>;
-
- name when Ver >= ?WSP_14 ->
- <<1:1, 16#17:7,
- (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
- name when Ver >= 16#01 ->
- <<1:1, 16#05:7,
- (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
-
- filename when Ver >= ?WSP_14 ->
- <<1:1, 16#18:7,
- (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
- filename when Ver >= 16#01 ->
- <<1:1, 16#06:7,
- (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
-
- differences when Ver >= 16#01 ->
- <<1:1, 16#07:7,
- (encode_typed_field(Ver,'Field-name',ParamValue))/binary>>;
-
- padding when Ver >= 16#01 ->
- <<1:1, 16#08:7,
- (encode_typed_field(Ver,'Short-integer',ParamValue))/binary>>;
-
-
- start when Ver >= ?WSP_14 ->
- <<1:1, 16#19:7,
- (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
- start when Ver >= ?WSP_12 ->
- <<1:1, 16#0A:7,
- (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
-
-
- 'start-info' when Ver >= ?WSP_14 ->
- <<1:1, 16#1A:7,
- (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
- 'start-info' when Ver >= ?WSP_12 ->
- <<1:1, 16#0B:7,
- (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
-
- comment when Ver >= ?WSP_14 ->
- <<1:1, 16#1B:7,
- (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
- comment when Ver >= ?WSP_13 ->
- <<1:1, 16#0C:7,
- (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
-
- domain when Ver >= ?WSP_14 ->
- <<1:1, 16#1C:7,
- (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
- domain when Ver >= ?WSP_13 ->
- <<1:1, 16#0D:7,
- (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
-
- 'max-age' when Ver >= ?WSP_13 ->
- <<1:1, 16#0E:7,
- (encode_typed_field(Ver,'Delta-seconds-value',ParamValue))/binary>>;
-
- path when Ver >= ?WSP_14 ->
- <<1:1, 16#1D:7,
- (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
- path when Ver >= ?WSP_13 ->
- <<1:1, 16#0F:7,
- (encode_typed_field(Ver,'Text-string',ParamValue))/binary>>;
-
- secure when Ver >= ?WSP_13 ->
- <<1:1, 16#10:7,
- (encode_typed_field(Ver,'No-value',ParamValue))/binary>>;
- %% NOTE: "sec" and "mac" are really 1.4 features but used by 1.3 client provisioning
- %"sec" when Ver >= ?WSP_14 ->
- sec when Ver >= ?WSP_13 ->
- <<1:1, 16#11:7,
- (encode_typed_field(Ver,'Short-integer',ParamValue))/binary>>;
- %"mac" when Ver >= ?WSP_14 ->
- mac when Ver >= ?WSP_13 ->
- <<1:1, 16#12:7,
- (encode_typed_field(Ver,'Text-value',ParamValue))/binary>>;
- 'creation-date' when Ver >= ?WSP_14 ->
- <<1:1, 16#13:7,
- (encode_typed_field(Ver,'Date-value',ParamValue))/binary>>;
- 'modification-date' when Ver >= ?WSP_14 ->
- <<1:1, 16#14:7,
- (encode_typed_field(Ver,'Date-value',ParamValue))/binary>>;
- 'read-date' when Ver >= ?WSP_14 ->
- <<1:1, 16#15:7,
- (encode_typed_field(Ver,'Date-value',ParamValue))/binary>>;
- size when Ver >= ?WSP_14 ->
- <<1:1, 16#16:7,
- (encode_typed_field(Ver,'Integer-value',ParamValue))/binary>>;
- _ ->
- <<(encode_text_string(ParamName))/binary,
- (encode_text_string(ParamValue))/binary >>
- end.
-
-%% decode_parameter: return {ParameterName, ParamterValue}
-decode_parameter(<<1:1,Code:7,Data/binary>>, Version) ->
- case Code of
- 16#00 ->
- {Val,Data1} = decode_typed_field('Q-value', Data, Version),
- {{ q, Val}, Data1};
-
- 16#01 ->
- {Val,Data1} = decode_typed_field('Well-known-charset',Data,Version),
- {{charset, Val}, Data1};
-
- 16#02 ->
- {Val,Data1} = decode_typed_field('Version-value',Data,Version),
- {{level, Val}, Data1};
-
- 16#03 ->
- {Val,Data1} = decode_typed_field('Integer-value', Data,Version),
- {{type, Val}, Data1};
-
- 16#05 ->
- {Val,Data1} = decode_typed_field('Text-string', Data,Version),
- {{name, Val}, Data1};
-
- 16#06 ->
- {Val,Data1} = decode_typed_field('Text-string', Data,Version),
- {{filename, Val}, Data1};
-
- 16#07 ->
- {Val,Data1} = decode_typed_field('Field-name', Data,Version),
- {{differences, Val}, Data1};
-
- 16#08 ->
- {Val,Data1} = decode_typed_field('Short-integer', Data,Version),
- {{padding, Val}, Data1};
-
- 16#09 ->
- {Val,Data1} = decode_typed_field('Constrained-encoding', Data,Version),
- {{type, Val}, Data1};
-
- 16#0A ->
- {Val,Data1} = decode_typed_field('Text-string', Data,Version),
- {{start, Val}, Data1};
-
- 16#0B ->
- {Val,Data1} = decode_typed_field('Text-string', Data,Version),
- {{'start-info', Val}, Data1};
-
- 16#0C ->
- {Val,Data1} = decode_typed_field('Text-string', Data,Version),
- {{comment, Val}, Data1};
-
- 16#0D ->
- {Val,Data1} = decode_typed_field('Text-string', Data,Version),
- {{domain, Val}, Data1};
-
- 16#0E ->
- {Val,Data1} = decode_typed_field('Delta-seconds-value', Data,Version),
- {{'max-age', Val}, Data1};
-
- 16#0F ->
- {Val,Data1} = decode_typed_field('Text-string', Data,Version),
- {{path, Val}, Data1};
-
- 16#10 ->
- {Val,Data1} = decode_typed_field('No-value', Data,Version),
- {{secure, Val}, Data1};
-
- 16#11 ->
- {Val,Data1} = decode_typed_field('Short-integer', Data,Version),
- {{sec, Val}, Data1};
-
- 16#12 ->
- {Val,Data1} = decode_typed_field('Text-value', Data,Version),
- {{mac, Val}, Data1};
-
- 16#13 ->
- {Val,Data1} = decode_typed_field('Date-value', Data,Version),
- {{'creation-date', Val}, Data1};
-
- 16#14 ->
- {Val,Data1} = decode_typed_field('Date-value', Data,Version),
- {{'modification-date', Val}, Data1};
-
- 16#15 ->
- {Val,Data1} = decode_typed_field('Date-value', Data,Version),
- {{'read-date', Val}, Data1};
-
- 16#16 ->
- {Val,Data1} = decode_typed_field('Integer-value', Data,Version),
- {{size, Val}, Data1};
-
- 16#17 ->
- {Val,Data1} = decode_typed_field('Text-value', Data,Version),
- {{name, Val}, Data1};
-
- 16#18 ->
- {Val,Data1} = decode_typed_field('Text-value', Data,Version),
- {{filename, Val}, Data1};
-
- 16#19 ->
- {Val,Data1} = decode_typed_field('Text-value', Data,Version),
- {{start, Val}, Data1};
-
- 16#1A ->
- {Val,Data1} = decode_typed_field('Text-value', Data,Version),
- {{'start-info', Val}, Data1};
-
- 16#1B ->
- {Val,Data1} = decode_typed_field('Text-value', Data,Version),
- {{comment, Val}, Data1};
-
- 16#1C ->
- {Val,Data1} = decode_typed_field('Text-value', Data,Version),
- {{domain, Val}, Data1};
-
- 16#1D ->
- {Val,Data1} = decode_typed_field('Text-value', Data,Version),
- {{path, Val}, Data1};
- _ ->
- exit({error, unknown_parameter})
- end;
-decode_parameter(Data, _Version) ->
- %% Untyped-parameter: Token-Text Untype-value
- {ParamName,Data1} = d_text_string(Data),
- %% Untype-value: Integer-Value | Text-Value!
- {ParamValue, Data2} = decode_untyped_value(Data1),
- {{ParamName,ParamValue}, Data2}.
-
-
-encode_typed_field(Ver,Type,Value) ->
- case Type of
- 'Well-known-charset' ->
- MIBenum = encode_charset(Value),
- encode_integer(MIBenum);
-
- 'Constrained-encoding' ->
- encode_constrained_media(Value, Ver);
-
- 'Text-string' ->
- encode_text_string(Value);
-
- 'Text-value' ->
- encode_text_value(Value);
-
- 'Short-integer' ->
- ?ENCODE_SHORT(Value);
-
- 'Date-value' ->
- e_date(Value);
-
- 'Delta-Seconds-value' ->
- e_delta_seconds(Value);
-
- 'No-value' ->
- e_no_value(Value);
-
- _ ->
- io:format("FIXME: encode_typed_field unsupported type = ~p\n",
- [Type]),
- exit({error,badtype})
- end.
-
-
-decode_typed_field(Type, Data, Version) ->
- case Type of
- 'Q-value' ->
- d_q_value(Data);
-
- 'Well-known-charset' ->
- {MIBenum, T100} = d_integer_value(Data),
- {decode_charset(MIBenum), T100};
-
- 'Constrained-encoding' ->
- {Value, Data1} = scan_header_data(Data),
- {decode_constrained_media(Value,Version), Data1};
-
- 'Text-string' ->
- d_text_string(Data);
-
- 'Text-value' ->
- d_text_value(Data);
-
- 'Short-integer' ->
- decode_short_integer(Data);
-
- 'Delta-seconds-value' ->
- d_integer_value(Data);
-
- 'Date-value' ->
- {Val, Data1} = decode_long_integer(Data),
- {d_date(Val), Data1};
-
- 'Field-name' ->
- d_field_name(Data);
-
- 'No-value' ->
- d_no_value(Data);
-
- _ ->
- io:format("FIXME: unsupported type = ~p\n",[Type]),
- exit({error,badtype})
- end.
-
-
-%% Integer-Value | Text-Value
-%% return as {Value, Tail}
-decode_untyped_value(<<1:1, Short:7, Tail/binary>>) ->
- {Short, Tail};
-decode_untyped_value(<<0:3, Len:5, Data/binary>>) when Len =/= 31 ->
- Sz = Len*8,
- <<Long:Sz, Tail/binary>> = Data,
- {Long, Tail};
-decode_untyped_value(Data) ->
- d_text_string(Data).
-
-
-e_field_name(Value, Version) ->
- case normalise_field_name(Value) of
- 'Accept' -> <<16#80>>;
- 'Accept-Charset' when Version >= ?WSP_13 -> <<16#bb>>;
- 'Accept-Charset' -> <<16#81>>;
- 'Accept-Encoding' when Version >= ?WSP_13 -> <<16#bc>>;
- 'Accept-Encoding' -> <<16#82>>;
- 'Accept-Language' -> <<16#83>>;
- 'Accept-Ranges' -> <<16#84>>;
- 'Age' -> <<16#85>>;
- 'Allow' -> <<16#86>>;
- 'Authorization' -> <<16#87>>;
- 'Cache-Control' when Version >= ?WSP_14 -> <<16#c7>>;
- 'Cache-Control' when Version >= ?WSP_13 -> <<16#bd>>;
- 'Cache-Control' -> <<16#88>>;
- 'Connection' -> <<16#89>>;
- 'Content-Base' -> <<16#8a>>;
- 'Content-Encoding' -> <<16#8b>>;
- 'Content-Language' -> <<16#8c>>;
- 'Content-Length' -> <<16#8d>>;
- 'Content-Location' -> <<16#8e>>;
- 'Content-Md5' -> <<16#8f>>;
- 'Content-Range' when Version >= ?WSP_13 -> <<16#be>>;
- 'Content-Range' -> <<16#90>>;
- 'Content-Type' -> <<16#91>>;
- 'Date' -> <<16#92>>;
- 'Etag' -> <<16#93>>;
- 'Expires' -> <<16#94>>;
- 'From' -> <<16#95>>;
- 'Host' -> <<16#96>>;
- 'If-Modified-Since' -> <<16#97>>;
- 'If-Match' -> <<16#98>>;
- 'If-None-Match' -> <<16#99>>;
- 'If-Range' -> <<16#9a>>;
- 'If-Unmodified-Since' -> <<16#9b>>;
- 'Location' -> <<16#9c>>;
- 'Last-Modified' -> <<16#9d>>;
- 'Max-Forwards' -> <<16#9e>>;
- 'Pragma' -> <<16#9f>>;
- 'Proxy-Authenticate' -> <<16#a0>>;
- 'Proxy-Authorization' -> <<16#a1>>;
- 'Public' -> <<16#a2>>;
- 'Range' -> <<16#a3>>;
- 'Referer' -> <<16#a4>>;
- 'Retry-After' -> <<16#a5>>;
- 'Server' -> <<16#a6>>;
- 'Transfer-Encoding' -> <<16#a7>>;
- 'Upgrade' -> <<16#a8>>;
- 'User-Agent' -> <<16#a9>>;
- 'Vary' -> <<16#aa>>;
- 'Via' -> <<16#ab>>;
- 'Warning' -> <<16#ac>>;
- 'Www-Authenticate' -> <<16#ad>>;
- 'Content-Disposition' when Version >= ?WSP_14 -> <<16#c5>>;
- 'Content-Disposition' -> <<16#ae>>;
- %% VERSION > 1.1
- 'X-Wap-Application-Id' when Version >= ?WSP_12 -> <<16#af>>;
- 'X-Wap-Content-Uri' when Version >= ?WSP_12 -> <<16#b0>>;
- 'X-Wap-Initiator-Uri' when Version >= ?WSP_12 -> <<16#b1>>;
- 'Accept-Application' when Version >= ?WSP_12 -> <<16#b2>>;
- 'Bearer-Indication' when Version >= ?WSP_12 -> <<16#b3>>;
- 'Push-Flag' when Version >= ?WSP_12 -> <<16#b4>>;
- 'Profile' when Version >= ?WSP_12 -> <<16#b5>>;
- 'Profile-Diff' when Version >= ?WSP_12 -> <<16#b6>>;
- 'Profile-Warning' when Version >= ?WSP_12 -> <<16#b7>>;
- 'Expect' when Version >= ?WSP_15 -> <<16#c8>>;
- 'Expect' when Version >= ?WSP_13 -> <<16#b8>>;
- 'Te' when Version >= ?WSP_13 -> <<16#b9>>;
- 'Trailer' when Version >= ?WSP_13 -> <<16#ba>>;
- 'X-Wap-Tod' when Version >= ?WSP_13 -> <<16#bf>>;
- 'Content-Id' when Version >= ?WSP_13 -> <<16#c0>>;
- 'Set-Cookie' when Version >= ?WSP_13 -> <<16#c1>>;
- 'Cookie' when Version >= ?WSP_13 -> <<16#c2>>;
- 'Encoding-Version' when Version >= ?WSP_13 -> <<16#c3>>;
- 'Profile-Warning' when Version >= ?WSP_14 -> <<16#c4>>;
- 'X-Wap-Security' when Version >= ?WSP_14 -> <<16#c6>>;
- 'X-Wap-Loc-Invocation' when Version >= ?WSP_15 -> <<16#c9>>;
- 'X-Wap-Loc-Delivery' when Version >= ?WSP_15 -> <<16#ca>>;
- Field -> encode_text_string(atom_to_list(Field))
- end.
-
-
-%%
-%% decode and normalise on form list_to_atom("Ulll-Ulll-Ull")
-%%
-normalise_field_name(Cs) when atom(Cs) ->
- Cs;
-normalise_field_name(Cs) ->
- list_to_atom(normalise_fieldU(Cs)).
-
-normalise_fieldU([C|Cs]) when C >= $a, C =< $z ->
- [(C-$a)+$A | normalise_fieldL(Cs)];
-normalise_fieldU([C|Cs]) -> [ C | normalise_fieldL(Cs)];
-normalise_fieldU([]) -> [].
-
-normalise_fieldL([C|Cs]) when C >= $A, C =< $Z ->
- [(C-$A)+$a | normalise_fieldL(Cs)];
-normalise_fieldL([$-|Cs]) -> [$- | normalise_fieldU(Cs)];
-normalise_fieldL([C|Cs]) -> [C | normalise_fieldL(Cs)];
-normalise_fieldL([]) -> [].
-
-
-tolower([C|Cs]) when C >= $A, C =< $Z ->
- [(C-$A)+$a | tolower(Cs)];
-tolower([C|Cs]) -> [C|tolower(Cs)];
-tolower([]) -> [].
-
-trim(Cs) ->
- lists:reverse(trim1(lists:reverse(trim1(Cs)))).
-
-trim1([$\s|Cs]) -> trim1(Cs);
-trim1([$\t|Cs]) -> trim1(Cs);
-trim1([$\r|Cs]) -> trim1(Cs);
-trim1([$\n|Cs]) -> trim1(Cs);
-trim1(Cs) -> Cs.
-
-
-d_field_name(Data) ->
- case scan_header_data(Data) of
- {Code, Data1} when integer(Code) ->
- {lookup_field_name(Code), Data1};
- {TmpField,Data1} when list(TmpField) ->
- {normalise_field_name(TmpField), Data1}
- end.
-
-d_no_value(<<0, Data/binary>>) ->
- {no_value, Data}.
-
-e_no_value(_) ->
- <<0>>.
-
-
-lookup_field_name(Code) ->
- case Code of
-%%% Version 1.1
- 16#00 -> 'Accept';
- 16#01 -> 'Accept-Charset';
- 16#02 -> 'Accept-Encoding';
- 16#03 -> 'Accept-Language';
- 16#04 -> 'Accept-Ranges';
- 16#05 -> 'Age';
- 16#06 -> 'Allow';
- 16#07 -> 'Authorization';
- 16#08 -> 'Cache-Control';
- 16#09 -> 'Connection';
- 16#0a -> 'Content-Base';
- 16#0b -> 'Content-Encoding';
- 16#0c -> 'Content-Language';
- 16#0d -> 'Content-Length';
- 16#0e -> 'Content-Location';
- 16#0f -> 'Content-Md5';
- 16#10 -> 'Content-Range';
- 16#11 -> 'Content-Type';
- 16#12 -> 'Date';
- 16#13 -> 'Etag';
- 16#14 -> 'Expires';
- 16#15 -> 'From';
- 16#16 -> 'Host';
- 16#17 -> 'If-Modified-Since';
- 16#18 -> 'If-Match';
- 16#19 -> 'If-None-Match';
- 16#1a -> 'If-Range';
- 16#1b -> 'If-Unmodified-Since';
- 16#1c -> 'Location';
- 16#1d -> 'Last-Modified';
- 16#1e -> 'Max-Forwards';
- 16#1f -> 'Pragma';
- 16#20 -> 'Proxy-Authenticate';
- 16#21 -> 'Proxy-Authorization';
- 16#22 -> 'Public';
- 16#23 -> 'Range';
- 16#24 -> 'Referer';
- 16#25 -> 'Retry-After';
- 16#26 -> 'Server';
- 16#27 -> 'Transfer-Encoding';
- 16#28 -> 'Upgrade';
- 16#29 -> 'User-Agent';
- 16#2a -> 'Vary';
- 16#2b -> 'Via';
- 16#2c -> 'Warning';
- 16#2d -> 'Www-Authenticate';
- 16#2e -> 'Content-Disposition';
-%%% Version 1.2
- 16#2f -> 'X-Wap-Application-Id';
- 16#30 -> 'X-Wap-Content-Uri';
- 16#31 -> 'X-Wap-Initiator-Uri';
- 16#32 -> 'Accept-Application';
- 16#33 -> 'Bearer-Indication';
- 16#34 -> 'Push-Flag';
- 16#35 -> 'Profile';
- 16#36 -> 'Profile-Diff';
- 16#37 -> 'Profile-Warning';
-%%% Version 1.3
- 16#38 -> 'Expect';
- 16#39 -> 'Te';
- 16#3a -> 'Trailer';
- 16#3b -> 'Accept-Charset';
- 16#3c -> 'Accept-Encoding';
- 16#3d -> 'Cache-Control';
- 16#3e -> 'Content-Range';
- 16#3f -> 'X-Wap-Tod';
- 16#40 -> 'Content-Id';
- 16#41 -> 'Set-Cookie';
- 16#42 -> 'Cookie';
- 16#43 -> 'Encoding-Version';
-%%% Version 1.4
- 16#44 -> 'Profile-Warning';
- 16#45 -> 'Content-Disposition';
- 16#46 -> 'X-Wap-Security';
- 16#47 -> 'Cache-Control';
-%%% Version 1.5
- 16#48 -> 'Expect';
- 16#49 -> 'X-Wap-Loc-Invocation';
- 16#4a -> 'X-Wap-Loc-Delivery';
-%% Unknown
- _ ->
- list_to_atom("X-Unknown-"++erlang:integer_to_list(Code, 16))
- end.
-
-
-encode_charset(Charset) ->
- %% FIXME: we should really resolve aliases as well
- %% charset:from_aliases(Charset)
- case charset:from_mime_name(Charset) of
- 0 -> exit({error, unknown_charset});
- MIBenum -> MIBenum
- end.
-
-encode_language(Language) ->
- Code = encode_lang(tolower(Language)),
- <<Code>>.
-
-
-
-decode_charset(MIBenum) ->
- case charset:to_mime_name(MIBenum) of
- undefined ->
- exit({error, unknown_charset});
- Preferred ->
- Preferred
- end.
-
-%% ISO 639 Language Assignments, Appendix A, Table 41, Page 102-103
-decode_lang(Code) ->
- case lookup_language(Code) of
- [L|_] -> atom_to_list(L);
- [] -> ""
- end.
-
-
-lookup_language(Code) ->
- case Code of
- 16#01 -> ['aa','afar'];
- 16#02 -> ['ab','abkhazian'];
- 16#03 -> ['af','afrikans'];
- 16#04 -> ['am','amharic'];
- 16#05 -> ['ar','arabic'];
- 16#06 -> ['as','assamese'];
- 16#07 -> ['ay','aymara'];
- 16#08 -> ['az','azerbaijani'];
- 16#09 -> ['ba','bashkir'];
- 16#0a -> ['be','byelorussian'];
- 16#0b -> ['bg','bulgarian'];
- 16#0c -> ['bh','bihari'];
- 16#0d -> ['bi','bislama'];
- 16#0e -> ['bn','bangla','bengali'];
- 16#0f -> ['bo','tibetan'];
- 16#10 -> ['br','breton'];
- 16#11 -> ['ca','catalan'];
- 16#12 -> ['co','corsican'];
- 16#13 -> ['cs','czech'];
- 16#14 -> ['cy','welsh'];
- 16#15 -> ['da','danish'];
- 16#16 -> ['de','german'];
- 16#17 -> ['dz','bhutani'];
- 16#18 -> ['el','greek'];
- 16#19 -> ['en','english'];
- 16#1a -> ['eo','esperanto'];
- 16#1b -> ['es','spanish'];
- 16#1c -> ['et','estonian'];
- 16#1d -> ['eu','basque'];
- 16#1e -> ['fa','persian'];
- 16#1f -> ['fi','finnish'];
- 16#20 -> ['fj','fiji'];
- 16#82 -> ['fo','faeroese'];
- 16#22 -> ['fr','french'];
- 16#83 -> ['fy','frisian'];
- 16#24 -> ['ga','irish'];
- 16#25 -> ['gd','scots-gaelic'];
- 16#26 -> ['gl','galician'];
- 16#27 -> ['gn','guarani'];
- 16#28 -> ['gu','gujarati'];
- 16#29 -> ['ha','hausa'];
- 16#2a -> ['he','hebrew'];
- 16#2b -> ['hi','hindi'];
- 16#2c -> ['hr','croatian'];
- 16#2d -> ['hu','hungarian'];
- 16#2e -> ['hy','armenian'];
- 16#84 -> ['ia','interlingua'];
- 16#30 -> ['id','indonesian'];
- 16#86 -> ['ie','interlingue'];
- 16#87 -> ['ik','inupiak'];
- 16#33 -> ['is','icelandic'];
- 16#34 -> ['it','italian'];
- 16#89 -> ['iu','inuktitut'];
- 16#36 -> ['ja','japanese'];
- 16#37 -> ['jw','javanese'];
- 16#38 -> ['ka','georgian'];
- 16#39 -> ['kk','kazakh'];
- 16#8a -> ['kl','greenlandic'];
- 16#3b -> ['km','cambodian'];
- 16#3c -> ['kn','kannada'];
- 16#3d -> ['ko','korean'];
- 16#3e -> ['ks','kashmiri'];
- 16#3f -> ['ku','kurdish'];
- 16#40 -> ['ky','kirghiz'];
- 16#8b -> ['la','latin'];
- 16#42 -> ['ln','lingala'];
- 16#43 -> ['lo','laothian'];
- 16#44 -> ['lt','lithuanian'];
- 16#45 -> ['lv','lettish','latvian'];
- 16#46 -> ['mg','malagese'];
- 16#47 -> ['mi','maori'];
- 16#48 -> ['mk','macedonian'];
- 16#49 -> ['ml','malayalam'];
- 16#4a -> ['mn','mongolian'];
- 16#4b -> ['mo','moldavian'];
- 16#4c -> ['mr','marathi'];
- 16#4d -> ['ms','malay'];
- 16#4e -> ['mt','maltese'];
- 16#4f -> ['my','burmese'];
- 16#81 -> ['na','nauru'];
- 16#51 -> ['ne','nepali'];
- 16#52 -> ['nl','dutch'];
- 16#53 -> ['no','norwegian'];
- 16#54 -> ['oc','occitan'];
- 16#55 -> ['om','oromo'];
- 16#56 -> ['or','oriya'];
- 16#57 -> ['pa','punjabi'];
- 16#58 -> ['po','polish'];
- 16#59 -> ['ps','pushto','pashto'];
- 16#5a -> ['pt','portugese'];
- 16#5b -> ['qu','quechua'];
- 16#8c -> ['rm','rhaeto-romance'];
- 16#5d -> ['rn','kirundi'];
- 16#5e -> ['ro','romanian'];
- 16#5f -> ['ru','russian'];
- 16#60 -> ['rw','kinyarwanda'];
- 16#61 -> ['sa','sanskrit'];
- 16#62 -> ['sd','sindhi'];
- 16#63 -> ['sg','sangho'];
- 16#64 -> ['sh','serbo-croatian'];
- 16#65 -> ['si','sinhalese'];
- 16#66 -> ['sk','slovak'];
- 16#67 -> ['sl','slovenian'];
- 16#68 -> ['sm','samoan'];
- 16#69 -> ['sn','shona'];
- 16#6a -> ['so','somali'];
- 16#6b -> ['sq','albanian'];
- 16#6c -> ['sr','serbian'];
- 16#6d -> ['ss','siswati'];
- 16#6e -> ['st','seshoto'];
- 16#6f -> ['su','sundanese'];
- 16#70 -> ['sv','swedish'];
- 16#71 -> ['sw','swahili'];
- 16#72 -> ['ta','tamil'];
- 16#73 -> ['te','telugu'];
- 16#74 -> ['tg','tajik'];
- 16#75 -> ['th','thai'];
- 16#76 -> ['ti','tigrinya'];
- 16#77 -> ['tk','turkmen'];
- 16#78 -> ['tl','tagalog'];
- 16#79 -> ['tn','setswana'];
- 16#7a -> ['to','tonga'];
- 16#7b -> ['tr','turkish'];
- 16#7c -> ['ts','tsonga'];
- 16#7d -> ['tt','tatar'];
- 16#7e -> ['tw','twi'];
- 16#7f -> ['ug','uighur'];
- 16#50 -> ['uk','ukrainian'];
- 16#21 -> ['ur','urdu'];
- 16#23 -> ['uz','uzbek'];
- 16#2f -> ['vi','vietnamese'];
- 16#85 -> ['vo','volapuk'];
- 16#31 -> ['wo','wolof'];
- 16#32 -> ['xh','xhosa'];
- 16#88 -> ['yi','yiddish'];
- 16#35 -> ['yo','yoruba'];
- 16#3a -> ['za','zhuang'];
- 16#41 -> ['zh','chinese'];
- 16#5c -> ['zu','zulu'];
- _ -> []
- end.
-
-encode_lang(Language) ->
- case tolower(Language) of
- "aa" -> 16#01;
- "afar" -> 16#01;
- "ab" -> 16#02;
- "abkhazian" -> 16#02;
- "af" -> 16#03;
- "afrikans" -> 16#03;
- "am" -> 16#04;
- "amharic" -> 16#04;
- "ar" -> 16#05;
- "arabic" -> 16#05;
- "as" -> 16#06;
- "assamese" -> 16#06;
- "ay" -> 16#07;
- "aymara" -> 16#07;
- "az" -> 16#08;
- "azerbaijani" -> 16#08;
- "ba" -> 16#09;
- "bashkir" -> 16#09;
- "be" -> 16#0a;
- "byelorussian" -> 16#0a;
- "bg" -> 16#0b;
- "bulgarian" -> 16#0b;
- "bh" -> 16#0c;
- "bihari" -> 16#0c;
- "bi" -> 16#0d;
- "bislama" -> 16#0d;
- "bn" -> 16#0e;
- "bangla" -> 16#0e;
- "bengali" -> 16#0e;
- "bo" -> 16#0f;
- "tibetan" -> 16#0f;
- "br" -> 16#10;
- "breton" -> 16#10;
- "ca" -> 16#11;
- "catalan" -> 16#11;
- "co" -> 16#12;
- "corsican" -> 16#12;
- "cs" -> 16#13;
- "czech" -> 16#13;
- "cy" -> 16#14;
- "welsh" -> 16#14;
- "da" -> 16#15;
- "danish" -> 16#15;
- "de" -> 16#16;
- "german" -> 16#16;
- "dz" -> 16#17;
- "bhutani" -> 16#17;
- "el" -> 16#18;
- "greek" -> 16#18;
- "en" -> 16#19;
- "english" -> 16#19;
- "eo" -> 16#1a;
- "esperanto" -> 16#1a;
- "es" -> 16#1b;
- "spanish" -> 16#1b;
- "et" -> 16#1c;
- "estonian" -> 16#1c;
- "eu" -> 16#1d;
- "basque" -> 16#1d;
- "fa" -> 16#1e;
- "persian" -> 16#1e;
- "fi" -> 16#1f;
- "finnish" -> 16#1f;
- "fj" -> 16#20;
- "fiji" -> 16#20;
- "fo" -> 16#82;
- "faeroese" -> 16#82;
- "fr" -> 16#22;
- "french" -> 16#22;
- "fy" -> 16#83;
- "frisian" -> 16#83;
- "ga" -> 16#24;
- "irish" -> 16#24;
- "gd" -> 16#25;
- "scots-gaelic" -> 16#25;
- "gl" -> 16#26;
- "galician" -> 16#26;
- "gn" -> 16#27;
- "guarani" -> 16#27;
- "gu" -> 16#28;
- "gujarati" -> 16#28;
- "ha" -> 16#29;
- "hausa" -> 16#29;
- "he" -> 16#2a;
- "hebrew" -> 16#2a;
- "hi" -> 16#2b;
- "hindi" -> 16#2b;
- "hr" -> 16#2c;
- "croatian" -> 16#2c;
- "hu" -> 16#2d;
- "hungarian" -> 16#2d;
- "hy" -> 16#2e;
- "armenian" -> 16#2e;
- "ia" -> 16#84;
- "interlingua" -> 16#84;
- "id" -> 16#30;
- "indonesian" -> 16#30;
- "ie" -> 16#86;
- "interlingue" -> 16#86;
- "ik" -> 16#87;
- "inupiak" -> 16#87;
- "is" -> 16#33;
- "icelandic" -> 16#33;
- "it" -> 16#34;
- "italian" -> 16#34;
- "iu" -> 16#89;
- "inuktitut" -> 16#89;
- "ja" -> 16#36;
- "japanese" -> 16#36;
- "jw" -> 16#37;
- "javanese" -> 16#37;
- "ka" -> 16#38;
- "georgian" -> 16#38;
- "kk" -> 16#39;
- "kazakh" -> 16#39;
- "kl" -> 16#8a;
- "greenlandic" -> 16#8a;
- "km" -> 16#3b;
- "cambodian" -> 16#3b;
- "kn" -> 16#3c;
- "kannada" -> 16#3c;
- "ko" -> 16#3d;
- "korean" -> 16#3d;
- "ks" -> 16#3e;
- "kashmiri" -> 16#3e;
- "ku" -> 16#3f;
- "kurdish" -> 16#3f;
- "ky" -> 16#40;
- "kirghiz" -> 16#40;
- "la" -> 16#8b;
- "latin" -> 16#8b;
- "ln" -> 16#42;
- "lingala" -> 16#42;
- "lo" -> 16#43;
- "laothian" -> 16#43;
- "lt" -> 16#44;
- "lithuanian" -> 16#44;
- "lv" -> 16#45;
- "lettish" -> 16#45;
- "latvian" -> 16#45;
- "mg" -> 16#46;
- "malagese" -> 16#46;
- "mi" -> 16#47;
- "maori" -> 16#47;
- "mk" -> 16#48;
- "macedonian" -> 16#48;
- "ml" -> 16#49;
- "malayalam" -> 16#49;
- "mn" -> 16#4a;
- "mongolian" -> 16#4a;
- "mo" -> 16#4b;
- "moldavian" -> 16#4b;
- "mr" -> 16#4c;
- "marathi" -> 16#4c;
- "ms" -> 16#4d;
- "malay" -> 16#4d;
- "mt" -> 16#4e;
- "maltese" -> 16#4e;
- "my" -> 16#4f;
- "burmese" -> 16#4f;
- "na" -> 16#81;
- "nauru" -> 16#81;
- "ne" -> 16#51;
- "nepali" -> 16#51;
- "nl" -> 16#52;
- "dutch" -> 16#52;
- "no" -> 16#53;
- "norwegian" -> 16#53;
- "oc" -> 16#54;
- "occitan" -> 16#54;
- "om" -> 16#55;
- "oromo" -> 16#55;
- "or" -> 16#56;
- "oriya" -> 16#56;
- "pa" -> 16#57;
- "punjabi" -> 16#57;
- "po" -> 16#58;
- "polish" -> 16#58;
- "ps" -> 16#59;
- "pushto" -> 16#59;
- "pt" -> 16#5a;
- "portugese" -> 16#5a;
- "qu" -> 16#5b;
- "quechua" -> 16#5b;
- "rm" -> 16#8c;
- "rhaeto-romance" -> 16#8c;
- "rn" -> 16#5d;
- "kirundi" -> 16#5d;
- "ro" -> 16#5e;
- "romanian" -> 16#5e;
- "ru" -> 16#5f;
- "russian" -> 16#5f;
- "rw" -> 16#60;
- "kinyarwanda" -> 16#60;
- "sa" -> 16#61;
- "sanskrit" -> 16#61;
- "sd" -> 16#62;
- "sindhi" -> 16#62;
- "sg" -> 16#63;
- "sangho" -> 16#63;
- "sh" -> 16#64;
- "serbo-croatian" -> 16#64;
- "si" -> 16#65;
- "sinhalese" -> 16#65;
- "sk" -> 16#66;
- "slovak" -> 16#66;
- "sl" -> 16#67;
- "slovenian" -> 16#67;
- "sm" -> 16#68;
- "samoan" -> 16#68;
- "sn" -> 16#69;
- "shona" -> 16#69;
- "so" -> 16#6a;
- "somali" -> 16#6a;
- "sq" -> 16#6b;
- "albanian" -> 16#6b;
- "sr" -> 16#6c;
- "serbian" -> 16#6c;
- "ss" -> 16#6d;
- "siswati" -> 16#6d;
- "st" -> 16#6e;
- "seshoto" -> 16#6e;
- "su" -> 16#6f;
- "sundanese" -> 16#6f;
- "sv" -> 16#70;
- "swedish" -> 16#70;
- "sw" -> 16#71;
- "swahili" -> 16#71;
- "ta" -> 16#72;
- "tamil" -> 16#72;
- "te" -> 16#73;
- "telugu" -> 16#73;
- "tg" -> 16#74;
- "tajik" -> 16#74;
- "th" -> 16#75;
- "thai" -> 16#75;
- "ti" -> 16#76;
- "tigrinya" -> 16#76;
- "tk" -> 16#77;
- "turkmen" -> 16#77;
- "tl" -> 16#78;
- "tagalog" -> 16#78;
- "tn" -> 16#79;
- "setswana" -> 16#79;
- "to" -> 16#7a;
- "tonga" -> 16#7a;
- "tr" -> 16#7b;
- "turkish" -> 16#7b;
- "ts" -> 16#7c;
- "tsonga" -> 16#7c;
- "tt" -> 16#7d;
- "tatar" -> 16#7d;
- "tw" -> 16#7e;
- "twi" -> 16#7e;
- "ug" -> 16#7f;
- "uighur" -> 16#7f;
- "uk" -> 16#50;
- "ukrainian" -> 16#50;
- "ur" -> 16#21;
- "urdu" -> 16#21;
- "uz" -> 16#23;
- "uzbek" -> 16#23;
- "vi" -> 16#2f;
- "vietnamese" -> 16#2f;
- "vo" -> 16#85;
- "volapuk" -> 16#85;
- "wo" -> 16#31;
- "wolof" -> 16#31;
- "xh" -> 16#32;
- "xhosa" -> 16#32;
- "yi" -> 16#88;
- "yiddish" -> 16#88;
- "yo" -> 16#35;
- "yoruba" -> 16#35;
- "za" -> 16#3a;
- "zhuang" -> 16#3a;
- "zh" -> 16#41;
- "chinese" -> 16#41;
- "zu" -> 16#5c;
- "zulu" -> 16#5c
- end.
-
-
-%% Push Application ID Assignments
-%%
-%% Assingment are found at http://www.wapforum.org/wina/push-app-id.htm
-%%
-decode_push_application({short,Data}) ->
- decode_push_application(d_long(Data));
-
-decode_push_application(Code) when integer(Code) ->
- case Code of
- 16#00 -> "x-wap-application:*";
- 16#01 -> "x-wap-application:push.sia";
- 16#02 -> "x-wap-application:wml.ua";
- 16#03 -> "x-wap-application:wta.ua";
- 16#04 -> "x-wap-application:mms.ua";
- 16#05 -> "x-wap-application:push.syncml";
- 16#06 -> "x-wap-application:loc.ua";
- 16#07 -> "x-wap-application:syncml.dm";
- 16#08 -> "x-wap-application:drm.ua";
- 16#09 -> "x-wap-application:emn.ua";
- 16#0A -> "x-wap-application:wv.ua";
- 16#8000 -> "x-wap-microsoft:localcontent.ua";
- 16#8001 -> "x-wap-microsoft:IMclient.ua";
- 16#8002 -> "x-wap-docomo:imode.mail.ua";
- 16#8003 -> "x-wap-docomo:imode.mr.ua";
- 16#8004 -> "x-wap-docomo:imode.mf.ua";
- 16#8005 -> "x-motorola:location.ua";
- 16#8006 -> "x-motorola:now.ua";
- 16#8007 -> "x-motorola:otaprov.ua";
- 16#8008 -> "x-motorola:browser.ua";
- 16#8009 -> "x-motorola:splash.ua";
- 16#800B -> "x-wap-nai:mvsw.command";
- 16#8010 -> "x-wap-openwave:iota.ua"
- end;
-decode_push_application(App) when list(App) ->
- App.
-
-
-
-encode_push_application(App) ->
- case App of
- "x-wap-application:*" -> ?ENCODE_SHORT(16#00);
- "x-wap-application:push.sia" -> ?ENCODE_SHORT(16#01);
- "x-wap-application:wml.ua" -> ?ENCODE_SHORT(16#02);
- "x-wap-application:wta.ua" -> ?ENCODE_SHORT(16#03);
- "x-wap-application:mms.ua" -> ?ENCODE_SHORT(16#04);
- "x-wap-application:push.syncml" -> ?ENCODE_SHORT(16#05);
- "x-wap-application:loc.ua" -> ?ENCODE_SHORT(16#06);
- "x-wap-application:syncml.dm" -> ?ENCODE_SHORT(16#07);
- "x-wap-application:drm.ua" -> ?ENCODE_SHORT(16#08);
- "x-wap-application:emn.ua" -> ?ENCODE_SHORT(16#09);
- "x-wap-application:wv.ua" -> ?ENCODE_SHORT(16#0A);
- "x-wap-microsoft:localcontent.ua" -> encode_integer(16#8000);
- "x-wap-microsoft:IMclient.ua" -> encode_integer(16#8001);
- "x-wap-docomo:imode.mail.ua" -> encode_integer(16#8002);
- "x-wap-docomo:imode.mr.ua" -> encode_integer(16#8003);
- "x-wap-docomo:imode.mf.ua" -> encode_integer(16#8004);
- "x-motorola:location.ua" -> encode_integer(16#8005);
- "x-motorola:now.ua" -> encode_integer(16#8006);
- "x-motorola:otaprov.ua" -> encode_integer(16#8007);
- "x-motorola:browser.ua" -> encode_integer(16#8008);
- "x-motorola:splash.ua" -> encode_integer(16#8009);
- "x-wap-nai:mvsw.command" -> encode_integer(16#800B);
- "x-wap-openwave:iota.ua" -> encode_integer(16#8010);
- _ -> encode_uri_value(App)
- end.
-
-
-
-
-%% WSP 8.5 Multipart handling
-
-encode_multipart(Entries) ->
- encode_multipart(Entries, ?WSP_DEFAULT_VERSION).
-
-encode_multipart([], _Version) ->
- <<>>;
-encode_multipart(Entries, Version) ->
- EncEntries = encode_multipart_entries(Entries, Version),
- <<(e_uintvar(length(Entries)))/binary, EncEntries/binary >>.
-
-encode_multipart_entries(Entries, Version) ->
- encode_multipart_entries(Entries, Version, []).
-
-encode_multipart_entries([], _Version, Acc) ->
- list_to_binary(lists:reverse(Acc));
-encode_multipart_entries([Entry|T], Version, Acc) ->
- EncEntry = encode_multipart_entry(Entry, Version),
- encode_multipart_entries(T, Version, [EncEntry | Acc]).
-
-encode_multipart_entry(Entry, Version) ->
- #wsp_multipart_entry { content_type = ContentType,
- headers = Headers,
- data = Data } = Entry,
- EncContentType = encode_content_type(ContentType,Version),
- EncHeaders = encode_headers(Headers, Version),
- EncHeadersLength = e_uintvar(size(EncContentType)+size(EncHeaders)),
- DataLen = e_uintvar(size(Data)),
- <<EncHeadersLength/binary,
- DataLen/binary,
- EncContentType/binary,
- EncHeaders/binary,
- Data/binary>>.
-
-
-decode_multipart(Data) ->
- decode_multipart(Data, ?WSP_DEFAULT_VERSION).
-
-decode_multipart(<<>>, _Version) ->
- {[], <<>>};
-decode_multipart(Data, Version) ->
- {Entries, Data1} = d_uintvar(Data),
- decode_multipart_entries(Entries, Data1, Version).
-
-decode_multipart_entries(Entries, Data, Version) ->
- decode_multipart_entries(Entries, Data, Version, []).
-
-decode_multipart_entries(0, Data, _Version, Acc) ->
- {lists:reverse(Acc), Data};
-decode_multipart_entries(Entries, Data, Version, Acc) ->
- {MultiPartEntry, Data1} = decode_multipart_entry(Data,Version),
- decode_multipart_entries(Entries-1, Data1, Version, [MultiPartEntry|Acc]).
-
-decode_multipart_entry(Data, Version) ->
- {HeadersLen, Data1} = d_uintvar(Data),
- {DataLen, Data2} = d_uintvar(Data1),
- {FieldData,Data3} = scan_header_data(Data2),
- ContentType = decode_content_type(FieldData, Version),
- BinHeadersLen = (HeadersLen-(size(Data2)-size(Data3))),
- <<BinHeaders:BinHeadersLen/binary,Data4/binary>> = Data3,
- Headers = decode_headers(BinHeaders, Version),
- <<ValueData:DataLen/binary, Data5/binary>> = Data4,
- {#wsp_multipart_entry{content_type=ContentType,
- headers=Headers,
- data=ValueData},Data5}.
-
-
-parse_credentials(Field, Value) ->
- %% FIXME
- ?WH(Field, Value, []).
-
-format_credentials("basic", [User,Password]) ->
- ["Basic ", base64:encode(User++":"++Password)];
-format_credentials(Scheme, Params) ->
- [Scheme, format_params(Params)].
-
-encode_credentials("basic", [User,Password], _Version) ->
- e_value(?ENCODE_SHORT(0),
- encode_text_string(User),
- encode_text_string(Password));
-encode_credentials(Scheme, Params, Version) ->
- e_value(encode_text_string(Scheme), encode_params(Params, Version)).
-
-decode_credentials(Field, Data, Version) ->
- case scan_header_data(Data) of
- {0, Data0} ->
- {User,Data1} = d_text_string(Data0),
- {Password,_Data2} = d_text_string(Data1),
- ?WH(Field, "basic", [User,Password]);
- {Scheme, Data0} when list(Scheme) ->
- Params = decode_params(Data0, Version),
- ?WH(Field, Scheme, Params)
- end.
-
-%%
-%% Challenge: Basic Realm-value | Auth-Scheme Realm *Auth-Params
-%%
-
-parse_challenge(Field, Value) ->
- %% FIXME
- ?WH(Field, Value, []).
-
-format_challenge({"basic",Realm}, []) ->
- ["Basic ", Realm];
-format_challenge({Scheme,Realm}, Params) ->
- [Scheme," ",Realm, format_params(Params)].
-
-encode_challenge({"basic",Realm}, [], _Version) ->
- e_value(?ENCODE_SHORT(0),
- encode_text_string(Realm));
-encode_challenge({Scheme,Realm}, Params, Version) ->
- e_value(encode_text_string(Scheme),
- encode_text_string(Realm),
- encode_params(Params, Version)).
-
-decode_challenge(Field, Data, Version) ->
- case scan_header_data(Data) of
- {0, Data0} ->
- {Realm,_} = d_text_string(Data0),
- ?WH(Field, {"basic", Realm}, []);
- {Scheme, Data0} when list(Scheme) ->
- {Realm,_} = d_text_string(Data0),
- Params = decode_params(Data0, Version),
- ?WH(Field, {Scheme,Realm}, Params)
- end.
-
-
-parse_well_known_method(Value) ->
- case Value of
- "GET" -> 'GET';
- "OPTIONS" -> 'OPTIONS';
- "HEAD" -> 'HEAD';
- "DELETE" -> 'DELETE';
- "TRACE" -> 'TRACE';
- "POST" -> 'POST';
- "PUT" -> 'PUT'
- end.
-
-encode_well_known_method(Value, _Version) ->
- case Value of
- 'GET' -> ?ENCODE_SHORT(16#40);
- 'OPTIONS' -> ?ENCODE_SHORT(16#41);
- 'HEAD' -> ?ENCODE_SHORT(16#42);
- 'DELETE' -> ?ENCODE_SHORT(16#43);
- 'TRACE' -> ?ENCODE_SHORT(16#44);
- 'POST' -> ?ENCODE_SHORT(16#60);
- 'PUT' -> ?ENCODE_SHORT(16#61)
- end.
-
-decode_well_known_method(Value, _Version) ->
- case Value of
- 16#40 -> 'GET';
- 16#41 -> 'OPTIONS';
- 16#42 -> 'HEAD';
- 16#43 -> 'DELETE';
- 16#44 -> 'TRACE';
- 16#60 -> 'POST';
- 16#61 -> 'PUT'
- end.
-
-
-
-%%
-%% WSP Table 36. Status Code Assignments
-%%
-
-encode_status_code(Status) ->
- case Status of
- 100 -> 16#10; %% 'Continue'
- 101 -> 16#11; %% 'Switching Protocols'
- 200 -> 16#20; %% 'OK, Success'
- 201 -> 16#21; %% 'Created'
- 202 -> 16#22; %% 'Accepted'
- 203 -> 16#23; %% 'Non-Authoritative Information'
- 204 -> 16#24; %% 'No Content'
- 205 -> 16#25; %% 'Reset Content'
- 206 -> 16#26; %% 'Partial Content'
- 300 -> 16#30; %% 'Multiple Choices'
- 301 -> 16#31; %% 'Moved Permanently'
- 302 -> 16#32; %% 'Moved temporarily'
- 303 -> 16#33; %% 'See Other'
- 304 -> 16#34; %% 'Not modified'
- 305 -> 16#35; %% 'Use Proxy'
- 306 -> 16#36; %% '(reserved)'
- 307 -> 16#37; %% 'Temporary Redirect'
- 400 -> 16#40; %% 'Bad Request - server could not understand request'
- 401 -> 16#41; %% 'Unauthorized'
- 402 -> 16#42; %% 'Payment required'
- 403 -> 16#43; %% 'Forbidden operation is understood but refused'
- 404 -> 16#44; %% 'Not Found'
- 405 -> 16#45; %% 'Method not allowed'
- 406 -> 16#46; %% 'Not Acceptable'
- 407 -> 16#47; %% 'Proxy Authentication required'
- 408 -> 16#48; %% 'Request Timeout'
- 409 -> 16#49; %% 'Conflict'
- 410 -> 16#4A; %% 'Gone'
- 411 -> 16#4B; %% 'Length Required'
- 412 -> 16#4C; %% 'Precondition failed'
- 413 -> 16#4D; %% 'Request entity too large'
- 414 -> 16#4E; %% 'Request-URI too large'
- 415 -> 16#4F; %% 'Unsupported media type'
- 416 -> 16#50; %% 'Requested Range Not Satisfiable'
- 417 -> 16#51; %% 'Expectation Failed'
- 500 -> 16#60; %% 'Internal Server Error'
- 501 -> 16#61; %% 'Not Implemented'
- 502 -> 16#62; %% 'Bad Gateway'
- 503 -> 16#63; %% 'Service Unavailable'
- 504 -> 16#64; %% 'Gateway Timeout'
- 505 -> 16#65 %% 'HTTP version not supported'
- end.
-
-
-decode_status_code(StatusCode) ->
- case StatusCode of
- 16#10 -> 100; %% 'Continue'
- 16#11 -> 101; %% 'Switching Protocols'
- 16#20 -> 200; %% 'OK, Success'
- 16#21 -> 201; %% 'Created'
- 16#22 -> 202; %% 'Accepted'
- 16#23 -> 203; %% 'Non-Authoritative Information'
- 16#24 -> 204; %% 'No Content'
- 16#25 -> 205; %% 'Reset Content'
- 16#26 -> 206; %% 'Partial Content'
- 16#30 -> 300; %% 'Multiple Choices'
- 16#31 -> 301; %% 'Moved Permanently'
- 16#32 -> 302; %% 'Moved temporarily'
- 16#33 -> 303; %% 'See Other'
- 16#34 -> 304; %% 'Not modified'
- 16#35 -> 305; %% 'Use Proxy'
- 16#36 -> 306; %% '(reserved)'
- 16#37 -> 307; %% 'Temporary Redirect'
- 16#40 -> 400; %% 'Bad Request - server could not understand request'
- 16#41 -> 401; %% 'Unauthorized'
- 16#42 -> 402; %% 'Payment required'
- 16#43 -> 403; %% 'Forbidden operation is understood but refused'
- 16#44 -> 404; %% 'Not Found'
- 16#45 -> 405; %% 'Method not allowed'
- 16#46 -> 406; %% 'Not Acceptable'
- 16#47 -> 407; %% 'Proxy Authentication required'
- 16#48 -> 408; %% 'Request Timeout'
- 16#49 -> 409; %% 'Conflict'
- 16#4A -> 410; %% 'Gone'
- 16#4B -> 411; %% 'Length Required'
- 16#4C -> 412; %% 'Precondition failed'
- 16#4D -> 413; %% 'Request entity too large'
- 16#4E -> 414; %% 'Request-URI too large'
- 16#4F -> 415; %% 'Unsupported media type'
- 16#50 -> 416; %% 'Requested Range Not Satisfiable'
- 16#51 -> 417; %% 'Expectation Failed'
- 16#60 -> 500; %% 'Internal Server Error'
- 16#61 -> 501; %% 'Not Implemented'
- 16#62 -> 502; %% 'Bad Gateway'
- 16#63 -> 503; %% 'Service Unavailable'
- 16#64 -> 504; %% 'Gateway Timeout'
- 16#65 -> 505 %% 'HTTP version not supported'
- end.
-
-
-%%
-%% Content Type Assignments
-%%
-%% Assingment are found at http://www.wapforum.org/wina/wsp-content-type.htm
-%%
-%%
-%% string(Version, ContentType) -> Code
-%%
-encode_well_known_media(ContentType, Version) ->
- case ContentType of
- %% WSP_REGISTERED_CONTENT_TYPES
- "application/vnd.uplanet.cacheop-wbxml" ->
- encode_integer(16#0201);
- "application/vnd.uplanet.signal" ->
- encode_integer(16#0202);
- "application/vnd.uplanet.alert-wbxml" ->
- encode_integer(16#0203);
- "application/vnd.uplanet.list-wbxml" ->
- encode_integer(16#0204);
- "application/vnd.uplanet.listcmd-wbxml" ->
- encode_integer(16#0205);
- "application/vnd.uplanet.channel-wbxml" ->
- encode_integer(16#0206);
- "application/vnd.uplanet.provisioning-status-uri" ->
- encode_integer(16#0207);
- "x-wap.multipart/vnd.uplanet.header-set" ->
- encode_integer(16#0208);
- "application/vnd.uplanet.bearer-choice-wbxml" ->
- encode_integer(16#0209);
- "application/vnd.phonecom.mmc-wbxml" ->
- encode_integer(16#020A);
- "application/vnd.nokia.syncset+wbxml" ->
- encode_integer(16#020B);
- "image/x-up-wpng" ->
- encode_integer(16#020C);
- _ ->
- encode_constrained_media(ContentType, Version)
- end.
-
-
-encode_constrained_media(ContentType, Version) ->
- case ContentType of
- "*/*" -> ?ENCODE_SHORT(16#00);
- "text/*" -> ?ENCODE_SHORT(16#01);
- "text/html" -> ?ENCODE_SHORT(16#02);
- "text/plain" -> ?ENCODE_SHORT(16#03);
- "text/x-hdml" -> ?ENCODE_SHORT(16#04);
- "text/x-ttml" -> ?ENCODE_SHORT(16#05);
- "text/x-vcalendar" -> ?ENCODE_SHORT(16#06);
- "text/x-vcard" -> ?ENCODE_SHORT(16#07);
- "text/vnd.wap.wml" -> ?ENCODE_SHORT(16#08);
- "text/vnd.wap.wmlscript" -> ?ENCODE_SHORT(16#09);
- "text/vnd.wap.wta-event" -> ?ENCODE_SHORT(16#0A);
- "multipart/*" -> ?ENCODE_SHORT(16#0B);
- "multipart/mixed" -> ?ENCODE_SHORT(16#0C);
- "multipart/form-data" -> ?ENCODE_SHORT(16#0D);
- "multipart/byterantes" -> ?ENCODE_SHORT(16#0E);
- "multipart/alternative" -> ?ENCODE_SHORT(16#0F);
- "application/*" -> ?ENCODE_SHORT(16#10);
- "application/java-vm" -> ?ENCODE_SHORT(16#11);
- "application/x-www-form-urlencoded" -> ?ENCODE_SHORT(16#12);
- "application/x-hdmlc" -> ?ENCODE_SHORT(16#13);
- "application/vnd.wap.wmlc" -> ?ENCODE_SHORT(16#14);
- "application/vnd.wap.wmlscriptc" -> ?ENCODE_SHORT(16#15);
- "application/vnd.wap.wta-eventc" -> ?ENCODE_SHORT(16#16);
- "application/vnd.wap.uaprof" -> ?ENCODE_SHORT(16#17);
- "application/vnd.wap.wtls-ca-certificate" -> ?ENCODE_SHORT(16#18);
- "application/vnd.wap.wtls-user-certificate" -> ?ENCODE_SHORT(16#19);
- "application/x-x509-ca-cert" -> ?ENCODE_SHORT(16#1A);
- "application/x-x509-user-cert" -> ?ENCODE_SHORT(16#1B);
- "image/*" -> ?ENCODE_SHORT(16#1C);
- "image/gif" -> ?ENCODE_SHORT(16#1D);
- "image/jpeg" -> ?ENCODE_SHORT(16#1E);
- "image/tiff" -> ?ENCODE_SHORT(16#1F);
- "image/png" -> ?ENCODE_SHORT(16#20);
- "image/vnd.wap.wbmp" -> ?ENCODE_SHORT(16#21);
- "application/vnd.wap.multipart.*" -> ?ENCODE_SHORT(16#22);
- "application/vnd.wap.multipart.mixed" -> ?ENCODE_SHORT(16#23);
- "application/vnd.wap.multipart.form-data" -> ?ENCODE_SHORT(16#24);
- "application/vnd.wap.multipart.byteranges" -> ?ENCODE_SHORT(16#25);
- "application/vnd.wap.multipart.alternative" -> ?ENCODE_SHORT(16#26);
- "application/xml" -> ?ENCODE_SHORT(16#27);
- "text/xml" -> ?ENCODE_SHORT(16#28);
- "application/vnd.wap.wbxml" -> ?ENCODE_SHORT(16#29);
- "application/x-x968-cross-cert" -> ?ENCODE_SHORT(16#2A);
- "application/x-x968-ca-cert" -> ?ENCODE_SHORT(16#2B);
- "application/x-x968-user-cert" -> ?ENCODE_SHORT(16#2C);
-
- %% WAP Version 1.2
- "text/vnd.wap.si" when Version >= ?WSP_12 ->
- ?ENCODE_SHORT(16#2D);
- "application/vnd.wap.sic" when Version >= ?WSP_12 ->
- ?ENCODE_SHORT(16#2E);
- "text/vnd.wap.sl" when Version >= ?WSP_12 ->
- ?ENCODE_SHORT(16#2F);
- "application/vnd.wap.slc" when Version >= ?WSP_12 ->
- ?ENCODE_SHORT(16#30);
- "text/vnd.wap.co" when Version >= ?WSP_12 ->
- ?ENCODE_SHORT(16#31);
- "application/vnd.wap.coc" when Version >= ?WSP_12 ->
- ?ENCODE_SHORT(16#32);
- "application/vnd.wap.multipart.related" when Version >= ?WSP_12 ->
- ?ENCODE_SHORT(16#33);
- "application/vnd.wap.sia" when Version >= ?WSP_12 ->
- ?ENCODE_SHORT(16#34);
- %% WAP Version 1.3
- "text/vnd.wap.connectivity-xml" when Version >= ?WSP_13 ->
- ?ENCODE_SHORT(16#35);
- "application/vnd.wap.connectivity-wbxml" when Version >= ?WSP_13 ->
- ?ENCODE_SHORT(16#36);
- %% WAP Version 1.4
- "application/pkcs7-mime" when Version >= ?WSP_14 ->
- ?ENCODE_SHORT(16#37);
- "application/vnd.wap.hashed-certificate" when Version >= ?WSP_14 ->
- ?ENCODE_SHORT(16#38);
- "application/vnd.wap.signed-certificate" when Version >= ?WSP_14 ->
- ?ENCODE_SHORT(16#39);
- "application/vnd.wap.cert-response" when Version >= ?WSP_14 ->
- ?ENCODE_SHORT(16#3A);
- "application/xhtml+xml" when Version >= ?WSP_14 ->
- ?ENCODE_SHORT(16#3B);
- "application/wml+xml" when Version >= ?WSP_14 ->
- ?ENCODE_SHORT(16#3C);
- "text/css" when Version >= ?WSP_14 ->
- ?ENCODE_SHORT(16#3D);
- "application/vnd.wap.mms-message" when Version >= ?WSP_14 ->
- ?ENCODE_SHORT(16#3E);
- "application/vnd.wap.rollover-certificate" when Version >= ?WSP_14 ->
- ?ENCODE_SHORT(16#3F);
- %% WAP Version 1.5
- "application/vnd.wap.locc+wbxml" when Version >= ?WSP_15 ->
- ?ENCODE_SHORT(16#40);
- "application/vnd.wap.loc+xml" when Version >= ?WSP_15 ->
- ?ENCODE_SHORT(16#41);
- "application/vnd.syncml.dm+wbxml" when Version >= ?WSP_15 ->
- ?ENCODE_SHORT(16#42);
- "application/vnd.syncml.dm+xml" when Version >= ?WSP_15 ->
- ?ENCODE_SHORT(16#43);
- "application/vnd.syncml.notification" when Version >= ?WSP_15 ->
- ?ENCODE_SHORT(16#44);
- "application/vnd.wap.xhtml+xml" when Version >= ?WSP_15 ->
- ?ENCODE_SHORT(16#45);
- "application/vnd.wv.csp.cir" when Version >= ?WSP_15 ->
- ?ENCODE_SHORT(16#46);
- "application/vnd.oma.dd+xml" when Version >= ?WSP_15 ->
- ?ENCODE_SHORT(16#47);
- "application/vnd.oma.drm.message" when Version >= ?WSP_15 ->
- ?ENCODE_SHORT(16#48);
- "application/vnd.oma.drm.content" when Version >= ?WSP_15 ->
- ?ENCODE_SHORT(16#49);
- "application/vnd.oma.drm.rights+xml" when Version >= ?WSP_15 ->
- ?ENCODE_SHORT(16#4A);
- "application/vnd.oma.drm.rights+wbxml" when Version >= ?WSP_15 ->
- ?ENCODE_SHORT(16#4B);
- _ ->
- encode_text_string(ContentType)
- end.
-
-
-decode_well_known_media(Code, Version) when integer(Code) ->
- case Code of
- %% WSP_REGISTERED_CONTENT_TYPES
- 16#0201 -> "application/vnd.uplanet.cacheop-wbxml";
- 16#0202 -> "application/vnd.uplanet.signal";
- 16#0203 -> "application/vnd.uplanet.alert-wbxml";
- 16#0204 -> "application/vnd.uplanet.list-wbxml";
- 16#0205 -> "application/vnd.uplanet.listcmd-wbxml";
- 16#0206 -> "application/vnd.uplanet.channel-wbxml";
- 16#0207 -> "application/vnd.uplanet.provisioning-status-uri";
- 16#0208 -> "x-wap.multipart/vnd.uplanet.header-set";
- 16#0209 -> "application/vnd.uplanet.bearer-choice-wbxml";
- 16#020A -> "application/vnd.phonecom.mmc-wbxml";
- 16#020B -> "application/vnd.nokia.syncset+wbxml";
- 16#020C -> "image/x-up-wpng";
- _ -> decode_constrained_media(Code, Version)
- end;
-decode_well_known_media(Media, _Version) when list(Media) ->
- Media;
-decode_well_known_media({short,_Data}, Version) ->
- decode_well_known_media(d_long(data), Version). %% BUG HERE: Data
-
-
-decode_constrained_media(Code, _Version) when integer(Code) ->
- case Code of
- 16#00 -> "*/*";
- 16#01 -> "text/*";
- 16#02 -> "text/html";
- 16#03 -> "text/plain";
- 16#04 -> "text/x-hdml";
- 16#05 -> "text/x-ttml";
- 16#06 -> "text/x-vcalendar";
- 16#07 -> "text/x-vcard";
- 16#08 -> "text/vnd.wap.wml";
- 16#09 -> "text/vnd.wap.wmlscript";
- 16#0A -> "text/vnd.wap.wta-event";
- 16#0B -> "multipart/*";
- 16#0C -> "multipart/mixed";
- 16#0D -> "multipart/form-data";
- 16#0E -> "multipart/byterantes";
- 16#0F -> "multipart/alternative";
- 16#10 -> "application/*";
- 16#11 -> "application/java-vm";
- 16#12 -> "application/x-www-form-urlencoded";
- 16#13 -> "application/x-hdmlc";
- 16#14 -> "application/vnd.wap.wmlc";
- 16#15 -> "application/vnd.wap.wmlscriptc";
- 16#16 -> "application/vnd.wap.wta-eventc";
- 16#17 -> "application/vnd.wap.uaprof";
- 16#18 -> "application/vnd.wap.wtls-ca-certificate";
- 16#19 -> "application/vnd.wap.wtls-user-certificate";
- 16#1A -> "application/x-x509-ca-cert";
- 16#1B -> "application/x-x509-user-cert";
- 16#1C -> "image/*";
- 16#1D -> "image/gif";
- 16#1E -> "image/jpeg";
- 16#1F -> "image/tiff";
- 16#20 -> "image/png";
- 16#21 -> "image/vnd.wap.wbmp";
- 16#22 -> "application/vnd.wap.multipart.*";
- 16#23 -> "application/vnd.wap.multipart.mixed";
- 16#24 -> "application/vnd.wap.multipart.form-data";
- 16#25 -> "application/vnd.wap.multipart.byteranges";
- 16#26 -> "application/vnd.wap.multipart.alternative";
- 16#27 -> "application/xml";
- 16#28 -> "text/xml";
- 16#29 -> "application/vnd.wap.wbxml";
- 16#2A -> "application/x-x968-cross-cert";
- 16#2B -> "application/x-x968-ca-cert";
- 16#2C -> "application/x-x968-user-cert";
- %% WAP Version 1.2
- 16#2D -> "text/vnd.wap.si";
- 16#2E -> "application/vnd.wap.sic";
- 16#2F -> "text/vnd.wap.sl";
- 16#30 -> "application/vnd.wap.slc";
- 16#31 -> "text/vnd.wap.co";
- 16#32 -> "application/vnd.wap.coc";
- 16#33 -> "application/vnd.wap.multipart.related";
- 16#34 -> "application/vnd.wap.sia";
- %% WAP Version 1.3
- 16#35 -> "text/vnd.wap.connectivity-xml";
- 16#36 -> "application/vnd.wap.connectivity-wbxml";
- %% WAP Version 1.4
- 16#37 -> "application/pkcs7-mime";
- 16#38 -> "application/vnd.wap.hashed-certificate";
- 16#39 -> "application/vnd.wap.signed-certificate";
- 16#3A -> "application/vnd.wap.cert-response";
- 16#3B -> "application/xhtml+xml";
- 16#3C -> "application/wml+xml";
- 16#3D -> "text/css";
- 16#3E -> "application/vnd.wap.mms-message";
- 16#3F -> "application/vnd.wap.rollover-certificate";
- %% WAP Version 1.5
- 16#40 -> "application/vnd.wap.locc+wbxml";
- 16#41 -> "application/vnd.wap.loc+xml";
- 16#42 -> "application/vnd.syncml.dm+wbxml";
- 16#43 -> "application/vnd.syncml.dm+xml";
- 16#44 -> "application/vnd.syncml.notification";
- 16#45 -> "application/vnd.wap.xhtml+xml";
- 16#46 -> "application/vnd.wv.csp.cir";
- 16#47 -> "application/vnd.oma.dd+xml";
- 16#48 -> "application/vnd.oma.drm.message";
- 16#49 -> "application/vnd.oma.drm.content";
- 16#4A -> "application/vnd.oma.drm.rights+xml";
- 16#4B -> "application/vnd.oma.drm.rights+wbxml"
- end;
-decode_constrained_media(Media, _Version) when list(Media) ->
- Media.
-
-
-%% Parse <integer> or <integer>.<integer>
-
-parse_version(Value) ->
- case string:tokens(Value, ".") of
- [Major,Minor] ->
- {list_to_integer(Major), list_to_integer(Minor)};
- [Major] ->
- case catch list_to_integer(Major) of
- {'EXIT', _} ->
- Value;
- V -> V
- end
- end.
-
-format_version({Major,Minor}) ->
- [integer_to_list(Major),".",integer_to_list(Minor)];
-format_version(Major) when integer(Major) ->
- integer_to_list(Major);
-format_version(Version) when list(Version) ->
- Version.
-
-encode_version({Major,Minor}) ->
- Ver = (((Major-1) band 16#7) bsl 4) bor (Minor band 16#f),
- ?ENCODE_SHORT(Ver);
-encode_version(Major) when integer(Major) ->
- Ver = ((Major band 16#7) bsl 4) bor 16#f,
- ?ENCODE_SHORT(Ver);
-encode_version(Value) when list(Value) ->
- encode_text_string(Value).
-
-
-decode_version(Value) when integer(Value) ->
- Major = (Value bsr 4) band 16#7,
- Minor = Value band 16#f,
- if Minor == 16#f ->
- Major;
- true ->
- {Major+1,Minor}
- end;
-decode_version(Value) when list(Value) ->
- Value.
-
-
-encode_mms_version({Major,Minor}) ->
- Ver = ((Major band 16#7) bsl 4) bor (Minor band 16#f),
- ?ENCODE_SHORT(Ver);
-encode_mms_version(Major) when integer(Major) ->
- Ver = ((Major band 16#7) bsl 4) bor 16#f,
- ?ENCODE_SHORT(Ver);
-encode_mms_version(Value) when list(Value) ->
- encode_text_string(Value).
-
-
-decode_mms_version(Value) when integer(Value) ->
- Major = (Value bsr 4) band 16#7,
- Minor = Value band 16#f,
- if Minor == 16#f ->
- Major;
- true ->
- {Major,Minor}
- end;
-decode_mms_version(Value) when list(Value) ->
- Value.
-
-
-%%%
-%%% Basic data types
-%%%
-
-e_delta_seconds(Value) ->
- encode_integer(Value).
-
-
-encode_integer(I) when integer(I), I >= 0 , I < 127 ->
- ?ENCODE_SHORT(I);
-encode_integer(I) when integer(I) ->
- encode_long_integer(I);
-encode_integer(List) when list(List) ->
- encode_integer(list_to_integer(List)).
-
-decode_integer(Value) when integer(Value) ->
- Value;
-decode_integer({short,Data}) ->
- Sz = size(Data)*8,
- <<Value:Sz>> = Data,
- Value.
-
-encode_short_integer(I) ->
- ?ENCODE_SHORT(I).
-
-encode_long_integer(I) when I >= 0 ->
- MOInt = encode_multioctet_integer(I, []),
- MOIntLen = length(MOInt),
- list_to_binary([MOIntLen band 16#1f | MOInt]).
-
-encode_multioctet_integer(I,Acc) when I < 256 ->
- [I | Acc];
-encode_multioctet_integer(I,Acc) ->
- encode_multioctet_integer(I bsr 8, [(I band 16#ff) | Acc]).
-
-
-%% Integer-Value: Short-Integer | Long-Integer
-%% Short-Integer: <<1:Short:7>>
-%% Long-Integer: <<0-30, X:0-30>>
-%% return {Integer,Tail}
-d_integer_value(<<1:1,Integer:7,Tail/binary>>) ->
- {Integer, Tail};
-d_integer_value(<<0:3,Len:5,Data/binary>>) when Len =/= 31 ->
- Sz = Len*8,
- <<Integer:Sz, Tail/binary>> = Data,
- {Integer, Tail}.
-
-decode_short_integer(<<1:1,Septet:7,T100/binary>>) ->
- {Septet, T100}.
-
-decode_long_integer(<<0:3,Len:5,Data/binary>>) when Len =/= 31 ->
- Sz = Len*8,
- <<Val:Sz, Tail/binary>> = Data,
- {Val, Tail}.
-
-d_long(Data) ->
- Sz = size(Data)*8,
- <<Value:Sz>> = Data,
- Value.
-
-
-encode_uri_value(Data) ->
- encode_text_string(Data).
-
-decode_uri_value(Data) when list(Data) ->
- Data.
-
-%% parse quoted string
-decode_quoted_string([$" | List]) ->
- List.
-
-encode_quoted_string([$" | Value]) ->
- case lists:reverse(Value) of
- [$" | Value1] ->
- <<$", (list_to_binary(lists:reverse(Value1)))/binary, 0>>;
- _ ->
- <<$", (list_to_binary(Value))/binary, 0>>
- end;
-encode_quoted_string(Value) ->
- <<$", (list_to_binary(Value))/binary, 0>>.
-
-
-
-decode_text_string(List) when list(List) ->
- List;
-decode_text_string(Bin) when binary(Bin) ->
- binary_to_list(Bin).
-
-
-
-encode_text_string(A) when atom(A) ->
- encode_text_string(atom_to_list(A));
-encode_text_string([H|T]) when H >= 128 ->
- <<(list_to_binary([127,H|T]))/binary,0>>;
-encode_text_string(S) ->
- <<(list_to_binary(S))/binary,0>>.
-
-
-encode_text_value(undefined) ->
- <<0>>;
-encode_text_value([$"|T]) ->
- %% remove ending quote ?
- <<34,(list_to_binary(T))/binary>>;
-encode_text_value(L) ->
- encode_text_string(L).
-
-
-d_text_value(<<0,T100/binary>>) ->
- { "", T100};
-d_text_value(<<34,_Tail/binary>>=Data) ->
- d_text_string(Data);
-d_text_value(Data) ->
- d_text_string(Data).
-
-
-d_text_string(<<127,Data/binary>>) -> %% Remove quote
- d_text_string(Data,[]);
-d_text_string(Data) ->
- d_text_string(Data,[]).
-
-d_text_string(<<0,Tail/binary>>,A) ->
- {lists:reverse(A), Tail};
-d_text_string(<<C,Tail/binary>>,A) ->
- d_text_string(Tail,[C|A]);
-d_text_string(<<>>, A) ->
- {lists:reverse(A), <<>>}.
-
-
-d_q_value(<<0:1,Q:7,Tail/binary>>) ->
- QVal =
- if Q >= 1, Q =< 100 ->
- lists:flatten(io_lib:format("0.~2..0w", [Q-1]));
- Q >= 101, Q =< 1099 ->
- lists:flatten(io_lib:format("0.~3..0w", [Q-100]));
- true ->
- io:format("Q-value to big ~w\n", [Q]),
- "***"
- end,
- {QVal, Tail};
-d_q_value(<<1:1,Q1:7,0:1,Q0:7,Tail/binary>>) ->
- Q = (Q1 bsl 7) bor Q0,
- QVal =
- if Q >= 1, Q =< 100 ->
- lists:flatten(io_lib:format("0.~2..0w", [Q-1]));
- Q >= 101, Q =< 1099 ->
- lists:flatten(io_lib:format("0.~3..0w", [Q-100]));
- true ->
- io:format("Q-value to big ~w\n", [Q]),
- "***"
- end,
- {QVal, Tail}.
-
-
-%%
-%% Decode uintvar
-%%
-d_uintvar(<<0:1,S0:7,T100/binary>>) ->
- {S0, T100};
-d_uintvar(<<1:1,S1:7,0:1,S0:7,T100/binary>>) ->
- {(S1 bsl 7) bor S0, T100};
-d_uintvar(<<1:1,S2:7,1:1,S1:7,0:1,S0:7,T100/binary>>) ->
- {(S2 bsl 14) bor (S1 bsl 7) bor S0, T100};
-d_uintvar(<<1:1,S3:7,1:1,S2:7,1:1,S1:7,0:1,S0:7,T100/binary>>) ->
- {(S3 bsl 21) bor (S2 bsl 14) bor (S1 bsl 7) bor S0, T100};
-d_uintvar(<<1:1,S4:7,1:1,S3:7,1:1,S2:7,1:1,S1:7,0:1,S0:7,T100/binary>>) ->
- {(S4 bsl 28) bor (S3 bsl 21) bor (S2 bsl 14) bor (S1 bsl 7) bor S0, T100}.
-
-
-e_uintvar(I) when I < 128 -> <<I>>;
-e_uintvar(I) -> e_uintvar(I,[]).
-
-e_uintvar(0,Acc) ->
- list_to_binary(Acc);
-e_uintvar(I,[]) ->
- e_uintvar(I bsr 7, [I band 16#7f]);
-e_uintvar(I,Acc) ->
- e_uintvar(I bsr 7, [16#80 bor (I band 16#7f) | Acc]).
-
-
-e_value(B) ->
- Sz = size(B),
- if Sz =< 30 ->
- <<Sz:8, B/binary>>;
- true ->
- <<31:8, (e_uintvar(Sz))/binary, B/binary >>
- end.
-
-e_value(B1,B2) ->
- Sz = size(B1)+size(B2),
- if Sz =< 30 ->
- <<Sz:8, B1/binary, B2/binary>>;
- true ->
- <<31:8, (e_uintvar(Sz))/binary, B1/binary, B2/binary >>
- end.
-
-e_value(B1,B2,B3) ->
- Sz = size(B1)+size(B2)+size(B3),
- if Sz =< 30 ->
- <<Sz:8, B1/binary,B2/binary,B3/binary>>;
- true ->
- <<31:8,(e_uintvar(Sz))/binary,B1/binary,B2/binary,B3/binary>>
- end.
-
-e_value(B1,B2,B3,B4) ->
- Sz = size(B1)+size(B2)+size(B3)+size(B4),
- if Sz =< 30 ->
- <<Sz:8, B1/binary,B2/binary,B3/binary,B4/binary>>;
- true ->
- <<31:8,(e_uintvar(Sz))/binary,B1/binary,
- B2/binary,B3/binary,B4/binary>>
- end.
-
-%%
-%% Extened methods
-%%
-decode_extended_methods(<<PduType:8, Data/binary>>) ->
- Type = decode_pdu_type(PduType),
- {Method, Data1} = d_text_string(Data),
- [{Type,Method} | decode_extended_methods(Data1)];
-decode_extended_methods(<<>>) ->
- [].
-
-encode_extended_methods(Ms) ->
- list_to_binary(encode_ext_methods(Ms)).
-
-encode_ext_methods([{Type,Method} | T]) ->
- [ encode_pdu_type(Type), encode_text_string(Method) |
- encode_ext_methods(T)];
-encode_ext_methods([]) ->
- [].
-
-%%
-%% Address lists used by redirect-pdu and aliases-capability
-%%
-decode_address(D0) ->
- [A] = decode_addresses(D0),
- A.
-
-decode_addresses(D0) ->
- case D0 of
- <<1:1, 1:1,Len:6,B:8,P:16,Addr:Len/binary,D1/binary>> ->
- [#wdp_address { bearer = B, address = Addr, portnum=P } |
- decode_addresses(D1)];
- <<1:1, 0:1,Len:6,B:8,Addr:Len/binary,D1/binary>> ->
- [#wdp_address { bearer = B, address = Addr } |
- decode_addresses(D1)];
- <<0:1, 1:1,Len:6,P:16,Addr:Len/binary,D1/binary>> ->
- [#wdp_address { portnum=P, address=Addr } |
- decode_addresses(D1)];
- <<0:1, 0:1,Len:6,Addr:Len/binary,D1/binary>> ->
- [#wdp_address { address=Addr } |
- decode_addresses(D1)];
- <<>> ->
- []
- end.
-
-encode_addresses(As) ->
- encode_addresses(As, []).
-
-encode_addresses([A|As], Acc) ->
- encode_addresses(As, [encode_address(A)|Acc]);
-encode_addresses([], Acc) ->
- list_to_binary(lists:reverse(Acc)).
-
-encode_address(#wdp_address { bearer = B, address = Addr, portnum = P }) ->
- BAddr = if tuple(Addr) ->
- list_to_binary(inet:ip_to_bytes(Addr));
- binary(Addr) ->
- Addr
- end,
- Len = size(BAddr),
- if B == undefined, P == undefined ->
- <<0:1, 0:1, Len:6, BAddr/binary>>;
- B == undefined ->
- <<0:1, 1:1, Len:6, P:16, BAddr/binary>>;
- P == undefined ->
- <<1:1, 0:1, Len:6, B:8, BAddr/binary>>;
- true ->
- <<1:1, 1:1, Len:6, B:8, P:16, BAddr/binary>>
- end.
-
-
-
-
--define(UNIX_TIME_OFFSET, 62167219200).
-
-d_date(Val) when integer(Val) ->
- calendar:gregorian_seconds_to_datetime(Val+?UNIX_TIME_OFFSET);
-d_date({short,Data}) ->
- Sz = size(Data)*8,
- <<Sec:Sz>> = Data,
- calendar:gregorian_seconds_to_datetime(Sec+?UNIX_TIME_OFFSET).
-
-e_date(DateTime) ->
- Sec = calendar:datetime_to_gregorian_seconds(DateTime),
- encode_long_integer(Sec - ?UNIX_TIME_OFFSET).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% decode http-date (RFC 2068). (MUST be send in RFC1123 date format)
-%% HTTP-date = rfc1123-date | rfc850-date | asctime-date
-%% rfc1123-date = wkday "," SP date1 SP time SP "GMT"
-%% rfc850-date = weekday "," SP date2 SP time SP "GMT"
-%% asctime-date = wkday SP date3 SP time SP 4DIGIT
-%%
-%% date1 = 2DIGIT SP month SP 4DIGIT
-%% ; day month year (e.g., 02 Jun 1982)
-%% date2 = 2DIGIT "-" month "-" 2DIGIT
-%% ; day-month-year (e.g., 02-Jun-82)
-%% date3 = month SP ( 2DIGIT | ( SP 1DIGIT ))
-%% ; month day (e.g., Jun 2)
-%%
-%% time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
-%% ; 00:00:00 - 23:59:59
-%%
-%% wkday = "Mon" | "Tue" | "Wed"
-%% | "Thu" | "Fri" | "Sat" | "Sun"
-%%
-%%
-%% weekday = "Monday" | "Tuesday" | "Wednesday"
-%% | "Thursday" | "Friday" | "Saturday" | "Sunday"
-%%
-%% month = "Jan" | "Feb" | "Mar" | "Apr"
-%% | "May" | "Jun" | "Jul" | "Aug"
-%% | "Sep" | "Oct" | "Nov" | "Dec"
-%%
-%% decode date or crash!
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-parse_http_date(Date) ->
- parse_hdate(tolower(Date)).
-
-parse_hdate([$m,$o,$n,$d,$a,$y,$ | Cs]) -> date2(Cs);
-parse_hdate([$t,$u,$e,$s,$d,$a,$y,$ | Cs]) -> date2(Cs);
-parse_hdate([$w,$e,$d,$n,$s,$d,$a,$y,$ | Cs]) -> date2(Cs);
-parse_hdate([$t,$h,$u,$r,$s,$d,$a,$y,$ | Cs]) -> date2(Cs);
-parse_hdate([$f,$r,$i,$d,$a,$y,$ | Cs]) -> date2(Cs);
-parse_hdate([$s,$a,$t,$u,$r,$d,$a,$y,$ | Cs]) -> date2(Cs);
-parse_hdate([$s,$u,$n,$d,$a,$y,$ | Cs]) -> date2(Cs);
-parse_hdate([$m,$o,$n,X | Cs]) -> date13(X,Cs);
-parse_hdate([$t,$u,$e,X | Cs]) -> date13(X,Cs);
-parse_hdate([$w,$e,$d,X | Cs]) -> date13(X,Cs);
-parse_hdate([$t,$h,$u,X | Cs]) -> date13(X,Cs);
-parse_hdate([$f,$r,$i,X | Cs]) -> date13(X,Cs);
-parse_hdate([$s,$a,$t,X | Cs]) -> date13(X,Cs);
-parse_hdate([$s,$u,$n,X | Cs]) -> date13(X,Cs).
-
-date13($ , Cs) -> date3(Cs);
-date13($,, [$ |Cs]) -> date1(Cs).
-
-%% date1
-date1([D1,D2,$ ,M1,M2,M3,$ ,Y1,Y2,Y3,Y4,$ | Cs]) ->
- M = parse_month([M1,M2,M3]),
- D = list_to_integer([D1,D2]),
- Y = list_to_integer([Y1,Y2,Y3,Y4]),
- {Time,[$ ,$g,$m,$t|Cs1]} = parse_time(Cs),
- { {{Y,M,D},Time}, Cs1}.
-
-%% date2
-date2([D1,D2,$-,M1,M2,M3,$-,Y1,Y2 | Cs]) ->
- M = parse_month([M1,M2,M3]),
- D = list_to_integer([D1,D2]),
- Y = 1900 + list_to_integer([Y1,Y2]),
- {Time, [$ ,$g,$m,$t|Cs1]} = parse_time(Cs),
- {{{Y,M,D}, Time}, Cs1}.
-
-%% date3
-date3([M1,M2,M3,$ ,D1,D2,$ | Cs]) ->
- M = parse_month([M1,M2,M3]),
- D = if D1 == $ -> list_to_integer([D2]);
- true -> list_to_integer([D1,D2])
- end,
- {Time,[$ ,Y1,Y2,Y3,Y4|Cs1]} = parse_time(Cs),
- Y = list_to_integer([Y1,Y2,Y3,Y4]),
- { {{Y,M,D}, Time}, Cs1 }.
-
-%% decode lowercase month
-parse_month("jan") -> 1;
-parse_month("feb") -> 2;
-parse_month("mar") -> 3;
-parse_month("apr") -> 4;
-parse_month("may") -> 5;
-parse_month("jun") -> 6;
-parse_month("jul") -> 7;
-parse_month("aug") -> 8;
-parse_month("sep") -> 9;
-parse_month("oct") -> 10;
-parse_month("nov") -> 11;
-parse_month("dec") -> 12.
-
-%% decode time HH:MM:SS
-parse_time([H1,H2,$:,M1,M2,$:,S1,S2|Cs]) ->
- { {list_to_integer([H1,H2]),
- list_to_integer([M1,M2]),
- list_to_integer([S1,S2]) }, Cs}.
-
-%% encode date into rfc1123-date (must be a GMT time!!!)
-fmt_date({{Y,M,D},{TH,TM,TS}}) ->
- WkDay = case calendar:day_of_the_week({Y,M,D}) of
- 1 -> "Mon";
- 2 -> "Tue";
- 3 -> "Wed";
- 4 -> "Thu";
- 5 -> "Fri";
- 6 -> "Sat";
- 7 -> "Sun"
- end,
- lists:flatten(io_lib:format("~s, ~2..0w ~s ~4..0w "
- "~2..0w:~2..0w:~2..0w GMT",
- [WkDay, D, fmt_month(M), Y, TH, TM, TS])).
-
-fmt_current_date() ->
- fmt_date(calendar:universal_time()).
-
-%% decode lowercase month
-fmt_month(1) -> "Jan";
-fmt_month(2) -> "Feb";
-fmt_month(3) -> "Mar";
-fmt_month(4) -> "Apr";
-fmt_month(5) -> "May";
-fmt_month(6) -> "Jun";
-fmt_month(7) -> "Jul";
-fmt_month(8) -> "Aug";
-fmt_month(9) -> "Sep";
-fmt_month(10) -> "Oct";
-fmt_month(11) -> "Nov";
-fmt_month(12) -> "Dec".
diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk
index 53b6f8c553..a7e82b54ce 100644
--- a/lib/dialyzer/vsn.mk
+++ b/lib/dialyzer/vsn.mk
@@ -1 +1 @@
-DIALYZER_VSN = 2.4.2
+DIALYZER_VSN = 2.4.4
diff --git a/lib/diameter/.gitignore b/lib/diameter/.gitignore
new file mode 100644
index 0000000000..5afcbedc23
--- /dev/null
+++ b/lib/diameter/.gitignore
@@ -0,0 +1,58 @@
+
+# Match at any level.
+*~
+autom4te.cache
+
+# Compiler derivatives
+#
+# Do not use too creative wildcards.
+# Those might ignore files that should not be ignored.
+
+i686-pc-linux-gnu
+x86_64-unknown-linux-gnu
+i386-apple-darwin[0-9]*.[0-9]*.[0-9]*
+sparc-sun-solaris[0-9]*.[0-9]*
+i386-pc-solaris[0-9]*.[0-9]*
+i386-unknown-freebsd[0-9]*.[0-9]*
+tile-tilera-linux-gnu
+powerpc-unknown-linux-gnu
+
+# Mac OS X
+a.out.dSYM/
+
+# Anchored from $DIAMETER_TOP
+/config.log
+/config.status
+
+/Makefile
+/configure
+
+
+# General patterns for applications in lib.
+#
+# Assume that all test/Emakefiles are generated.
+#
+# Any application with a checked-in test/Emakefile should
+# use a negative pattern in its own .gitignore.
+
+#
+# Files generated by configure.
+#
+
+/configure
+/config.log
+/config.status
+
+
+#
+# Generated documentation. (ie. not doc/src)
+#
+
+/doc/[^s]*
+
+
+#
+# Files generated when building/running tests
+#
+
+/test/*.log
diff --git a/lib/diameter/AUTHORS b/lib/diameter/AUTHORS
new file mode 100644
index 0000000000..40bd970276
--- /dev/null
+++ b/lib/diameter/AUTHORS
@@ -0,0 +1,10 @@
+Original Authors:
+
+ Anders Svensson
+ Ulf Wiger
+
+Contributors:
+
+
+
+
diff --git a/lib/diameter/Makefile.in b/lib/diameter/Makefile.in
new file mode 100644
index 0000000000..cf38c26045
--- /dev/null
+++ b/lib/diameter/Makefile.in
@@ -0,0 +1,88 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+ifneq ($(ERL_TOP),)
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+else
+include $(DIAMETER_TOP)/make/target.mk
+include $(DIAMETER_TOP)/make/$(TARGET)/rules.mk
+endif
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include vsn.mk
+VSN=$(DIAMETER_VSN)
+
+DIAMETER_TOP = @DIAMETER_TOP@
+
+
+# ----------------------------------------------------
+# Common Macros
+# ----------------------------------------------------
+
+include subdirs.mk
+
+SUB_DIRECTORIES = $(SUB_DIRS) doc/src
+
+SPECIAL_TARGETS =
+
+ifneq ($(ERL_TOP),)
+ifneq ($(PREFIX),)
+CONFIGURE_OPTS += --prefix=$(PREFIX)
+endif
+endif
+
+
+# ----------------------------------------------------
+# Default Subdir Targets
+# ----------------------------------------------------
+ifneq ($(ERL_TOP),)
+include $(ERL_TOP)/make/otp_subdir.mk
+else
+include $(DIAMETER_TOP)/make/subdir.mk
+endif
+
+.PHONY: reconf conf info version dialyzer
+
+reconf:
+ autoconf
+
+conf: do_configure
+
+do_configure: configure
+ ./configure $(CONFIGURE_OPTS)
+
+configure: configure.in
+ autoconf
+
+info:
+ @echo "APP_VSN: $(APP_VSN)"
+ @echo "DIAMETER_VSN: $(DIAMETER_VSN)"
+
+version:
+ @echo "$(VSN)"
+
+
+dialyzer:
+ (cd ./ebin; \
+ dialyzer --build_plt \
+ --output_plt ../priv/diameter.plt \
+ -r ../../diameter/ebin \
+ --verbose)
diff --git a/lib/diameter/TAR.exclude b/lib/diameter/TAR.exclude
new file mode 100644
index 0000000000..4a2b3192c5
--- /dev/null
+++ b/lib/diameter/TAR.exclude
@@ -0,0 +1,2 @@
+diameter/doc/standard
+
diff --git a/lib/diameter/aclocal.m4 b/lib/diameter/aclocal.m4
new file mode 100644
index 0000000000..2abb47dba2
--- /dev/null
+++ b/lib/diameter/aclocal.m4
@@ -0,0 +1,65 @@
+dnl
+dnl %CopyrightBegin%
+dnl
+dnl Copyright Ericsson AB 1998-2011. All Rights Reserved.
+dnl
+dnl The contents of this file are subject to the Erlang Public License,
+dnl Version 1.1, (the "License"); you may not use this file except in
+dnl compliance with the License. You should have received a copy of the
+dnl Erlang Public License along with this software. If not, it can be
+dnl retrieved online at http://www.erlang.org/.
+dnl
+dnl Software distributed under the License is distributed on an "AS IS"
+dnl basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+dnl the License for the specific language governing rights and limitations
+dnl under the License.
+dnl
+dnl %CopyrightEnd%
+dnl
+
+dnl
+dnl aclocal.m4
+dnl
+dnl Local macros used in configure.in. The Local Macros which
+dnl could/should be part of autoconf are prefixed LM_, macros specific
+dnl to the Erlang system are prefixed ERL_.
+dnl
+
+dnl ----------------------------------------------------------------------
+dnl
+dnl LM_PROG_INSTALL_DIR
+dnl
+dnl Figure out how to create directories with parents.
+dnl (In my opinion INSTALL_DIR is a bad name, MKSUBDIRS or something is better)
+dnl
+dnl We prefer 'install -d', but use 'mkdir -p' if it exists.
+dnl If none of these methods works, we give up.
+dnl
+
+
+AC_DEFUN(LM_PROG_INSTALL_DIR,
+[AC_CACHE_CHECK(how to create a directory including parents,
+ac_cv_prog_mkdir_p,
+[
+temp_name_base=config.$$
+temp_name=$temp_name_base/x/y/z
+$INSTALL -d $temp_name >/dev/null 2>&1
+ac_cv_prog_mkdir_p=none
+if test -d $temp_name; then
+ ac_cv_prog_mkdir_p="$INSTALL -d"
+else
+ mkdir -p $temp_name >/dev/null 2>&1
+ if test -d $temp_name; then
+ ac_cv_prog_mkdir_p="mkdir -p"
+ fi
+fi
+rm -fr $temp_name_base
+])
+
+case "${ac_cv_prog_mkdir_p}" in
+ none) AC_MSG_ERROR(don't know how create directories with parents) ;;
+ *) INSTALL_DIR="$ac_cv_prog_mkdir_p" AC_SUBST(INSTALL_DIR) ;;
+esac
+])
+
+
diff --git a/lib/diameter/autoconf/config.guess b/lib/diameter/autoconf/config.guess
new file mode 100755
index 0000000000..38a833903b
--- /dev/null
+++ b/lib/diameter/autoconf/config.guess
@@ -0,0 +1,1519 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+# Inc.
+
+timestamp='2007-05-17'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <[email protected]>.
+# Please send patches to <[email protected]>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <[email protected]>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# ([email protected] 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ *:SolidBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # [email protected] (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:SunOS:5.*:* | ix86xen:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ case ${UNAME_MACHINE} in
+ pc98)
+ echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ amd64)
+ echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ *)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ esac
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ *:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ *:Interix*:[3456]*)
+ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ EM64T | authenticamd)
+ echo x86_64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ esac ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ avr32*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^CPU/{
+ s: ::g
+ p
+ }'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^CPU/{
+ s: ::g
+ p
+ }'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ or32:Linux:*:*)
+ echo or32-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ tile:Linux:*:*)
+ echo tile-unknown-linux-gnu
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-gnu
+ exit ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit ;;
+ xtensa:Linux:*:*)
+ echo xtensa-unknown-linux-gnu
+ exit ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^LIBC/{
+ s: ::g
+ p
+ }'`"
+ test x"${LIBC}" != x && {
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ exit
+ }
+ test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <[email protected]>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-7:SUPER-UX:*:*)
+ echo sx7-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8:SUPER-UX:*:*)
+ echo sx8-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8R:SUPER-UX:*:*)
+ echo sx8r-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+ i*86:rdos:*:*)
+ echo ${UNAME_MACHINE}-pc-rdos
+ exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <[email protected]> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/lib/diameter/autoconf/config.sub b/lib/diameter/autoconf/config.sub
new file mode 100755
index 0000000000..f43233b104
--- /dev/null
+++ b/lib/diameter/autoconf/config.sub
@@ -0,0 +1,1630 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+# Inc.
+
+timestamp='2007-04-29'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <[email protected]>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <[email protected]>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco6)
+ os=-sco5v6
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fido | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | mcore | mep \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | mt \
+ | msp430 \
+ | nios | nios2 \
+ | ns16k | ns32k \
+ | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nios-* | nios2-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16c)
+ basic_machine=cr16c-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=-mingw32ce
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pc98)
+ basic_machine=i386-pc
+ ;;
+ pc98-*)
+ basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rdos)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sde)
+ basic_machine=mipsisa32-sde
+ os=-elf
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ tile*)
+ basic_machine=tile-tilera
+ os=-linux-gnu
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -openbsd* | -solidbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ score-*)
+ os=-elf
+ ;;
+ spu-*)
+ os=-elf
+ ;;
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mep-*)
+ os=-elf
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/lib/diameter/autoconf/configure.vxworks b/lib/diameter/autoconf/configure.vxworks
new file mode 100755
index 0000000000..33aa497680
--- /dev/null
+++ b/lib/diameter/autoconf/configure.vxworks
@@ -0,0 +1,147 @@
+#!/bin/sh
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1997-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+# Author:
+# Patrik Winroth
+#
+
+
+# vxworks_ppc860 vxworks_ppc603 vxworks_ppc603_longcall vxworks_cpu32 vxworks_sparc
+# vxworks_ppc750 vxworks_simso
+
+case $# in
+1) host=$1 ;;
+*) echo "usage: configure.vxworks host-configuration"; exit 1 ;;
+esac
+
+case $1 in
+vxworks_cpu32) ;;
+vxworks_ppc750) ;;
+vxworks_ppc860) ;;
+vxworks_ppc603) ;;
+vxworks_ppc603_nolongcall) ;;
+vxworks_sparc) ;;
+vxworks_simso) ;;
+vxworks_simlinux) ;;
+vxworks_ppc32) ;;
+*) echo "usage: configure.vxworks TARGET";
+ echo "where TARGET is one of vxworks_cpu32, vxworks_ppc750, vxworks_ppc860, vxworks_ppc603, vxworks_ppc603_nolongcall, vxworks_sparc, vxworks_simso, vxworks_simlinux, vxworks_ppc32"; exit 1;;
+esac
+
+if [ "x$ERL_TOP" = x ]; then
+ echo "You need to set ERL_TOP!"
+ exit 1
+fi
+
+
+target=$host
+
+# Find out the HOST and WIND_BASE environment
+HOST_TYPE=${HOST_TYPE:=sun4-solaris2}
+case $1 in
+vxworks_ppc750) VXTOP=Tornado2.2 ;;
+vxworks_simso) VXTOP=WindRiver ;;
+vxworks_simlinux) VXTOP=WindRiver ;;
+vxworks_ppc32) VXTOP=WindRiver ;;
+*) VXTOP=wind ;;
+esac
+
+WIND_BASE=${WIND_BASE:=`ypmatch tornado passwd | awk -F: '{print $6}'`/$VXTOP}
+
+# These are created by autoconf.
+MKDIRS="${ERL_TOP}/lib/os_mon/priv/bin/$target
+ ${ERL_TOP}/lib/os_mon/priv/obj/$target
+ ${ERL_TOP}/lib/orber/priv/obj/$target
+ ${ERL_TOP}/lib/orber/priv/bin/$target
+ ${ERL_TOP}/lib/ic/priv/lib/$target
+ ${ERL_TOP}/lib/ic/priv/obj/$target
+ ${ERL_TOP}/lib/asn1/priv/lib/$target
+ ${ERL_TOP}/lib/asn1/priv/obj/$target
+ ${ERL_TOP}/lib/erl_interface/obj/$target
+ ${ERL_TOP}/lib/erl_interface/obj.debug/$target
+ ${ERL_TOP}/lib/erl_interface/bin/$target
+ ${ERL_TOP}/lib/runtime_tools/priv/lib/$target
+ ${ERL_TOP}/lib/runtime_tools/priv/obj/$target
+ ${ERL_TOP}/erts/obj/$target
+ ${ERL_TOP}/erts/obj.debug/$target
+ ${ERL_TOP}/bin/$target"
+
+for dir in $MKDIRS; do
+ test ! -d "$dir" && mkdir -p "$dir"
+done
+
+#
+# Create Makefiles for vxWorks.
+#
+my_root=${ERL_TOP}/erts/emulator
+emu_test=$my_root/test
+beam=$my_root/beam
+erts_lib_src=${ERL_TOP}/erts/lib_src
+erts_incl=${ERL_TOP}/erts/include
+erts_incl_intrnl=${ERL_TOP}/erts/include/internal
+etcdir=${ERL_TOP}/erts/etc/common
+erlint_dir=${ERL_TOP}/lib/erl_interface/src
+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
+zlibdir=${ERL_TOP}/erts/emulator/zlib
+runtime_tools_dir=${ERL_TOP}/lib/runtime_tools/c_src
+tools_dir=${ERL_TOP}/lib/tools/c_src
+
+CONFIG_FILES="${ERL_TOP}/erts/emulator/$host/Makefile
+ $erts_lib_src/$host/Makefile
+ $erts_incl/$host/erl_int_sizes_config.h
+ $erts_incl_intrnl/$host/ethread.mk
+ $erts_incl_intrnl/$host/ethread_header_config.h
+ $etcdir/$host/Makefile
+ $erlint_dir/$host/Makefile
+ $erlint_dir/$host/eidefs.mk
+ $epmd_dir/$host/Makefile
+ $internal_tools_dir/make/$host/otp.mk
+ $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"
+
+for file in $CONFIG_FILES; do
+ new_name=`echo $file|sed "s%/$host/%/$target/%"`
+ dir=`echo $new_name|sed 's%/[^/][^/]*$%%'`
+ if test "$dir" != "$new_name" && test "$dir" != .; then
+ test ! -d "$dir" && mkdir "$dir"
+ fi
+
+ sole_name=`echo $file|sed "s%.*$target/%%"`
+ in_file=`echo $dir|sed "s%/[^/][^/]*$%/$sole_name.in%"`
+ echo "creating $new_name"
+ sed -f vxworks/sed.$target -f vxworks/sed.general \
+ -e "s,@HOST_TYPE@,$HOST_TYPE,g" \
+ -e "s,@WIND_BASE@,$WIND_BASE,g" \
+ -e "s,@TARGET@,$target,g" \
+ $in_file > $new_name
+done
+
+
diff --git a/lib/diameter/autoconf/install-sh b/lib/diameter/autoconf/install-sh
new file mode 100755
index 0000000000..a5897de6ea
--- /dev/null
+++ b/lib/diameter/autoconf/install-sh
@@ -0,0 +1,519 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2006-12-25.00
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" "" $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+ doit_exec=exec
+else
+ doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+ test "$posix_glob" != "?" || {
+ if (set -f) 2>/dev/null; then
+ posix_glob=
+ else
+ posix_glob=:
+ fi
+ }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+ --help display this help and exit.
+ --version display version info and exit.
+
+ -c (ignored)
+ -C install only if different (preserve the last data modification time)
+ -d create directories instead of installing files.
+ -g GROUP $chgrpprog installed files to GROUP.
+ -m MODE $chmodprog installed files to MODE.
+ -o USER $chownprog installed files to USER.
+ -s $stripprog installed files.
+ -t DIRECTORY install into DIRECTORY.
+ -T report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+ RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+ case $1 in
+ -c) ;;
+
+ -C) copy_on_change=true;;
+
+ -d) dir_arg=true;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift;;
+
+ --help) echo "$usage"; exit $?;;
+
+ -m) mode=$2
+ case $mode in
+ *' '* | *' '* | *'
+'* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
+
+ -o) chowncmd="$chownprog $2"
+ shift;;
+
+ -s) stripcmd=$stripprog;;
+
+ -t) dst_arg=$2
+ shift;;
+
+ -T) no_target_directory=true;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ --) shift
+ break;;
+
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
+
+ *) break;;
+ esac
+ shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+ # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dst_arg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dst_arg"
+ shift # fnord
+ fi
+ shift # arg
+ dst_arg=$arg
+ done
+fi
+
+if test $# -eq 0; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call `install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+if test -z "$dir_arg"; then
+ trap '(exit $?); exit' 1 2 13 15
+
+ # Set umask so as not to create temps with too-generous modes.
+ # However, 'strip' requires both read and write access to temps.
+ case $mode in
+ # Optimize common cases.
+ *644) cp_umask=133;;
+ *755) cp_umask=22;;
+
+ *[0-7])
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw='% 200'
+ fi
+ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+ *)
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw=,u+rw
+ fi
+ cp_umask=$mode$u_plus_rw;;
+ esac
+fi
+
+for src
+do
+ # Protect names starting with `-'.
+ case $src in
+ -*) src=./$src;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ else
+
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dst_arg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+
+ dst=$dst_arg
+ # Protect names starting with `-'.
+ case $dst in
+ -*) dst=./$dst;;
+ esac
+
+ # If destination is a directory, append the input filename; won't work
+ # if double slashes aren't ignored.
+ if test -d "$dst"; then
+ if test -n "$no_target_directory"; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dst=$dstdir/`basename "$src"`
+ dstdir_status=0
+ else
+ # Prefer dirname, but fall back on a substitute if dirname fails.
+ dstdir=`
+ (dirname "$dst") 2>/dev/null ||
+ expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$dst" : 'X\(//\)[^/]' \| \
+ X"$dst" : 'X\(//\)$' \| \
+ X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+ echo X"$dst" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'
+ `
+
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # Create intermediate dirs using mode 755 as modified by the umask.
+ # This is like FreeBSD 'install' as of 1997-10-28.
+ umask=`umask`
+ case $stripcmd.$umask in
+ # Optimize common cases.
+ *[2367][2367]) mkdir_umask=$umask;;
+ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+ *[0-7])
+ mkdir_umask=`expr $umask + 22 \
+ - $umask % 100 % 40 + $umask % 20 \
+ - $umask % 10 % 4 + $umask % 2
+ `;;
+ *) mkdir_umask=$umask,go-w;;
+ esac
+
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
+
+ posix_mkdir=false
+ case $umask in
+ *[123567][0-7][0-7])
+ # POSIX mkdir -p sets u+wx bits regardless of umask, which
+ # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+ ;;
+ *)
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ if (umask $mkdir_umask &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writeable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ ls_ld_tmpdir=`ls -ld "$tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/d" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+ fi
+ trap '' 0;;
+ esac;;
+ esac
+
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # The umask is ridiculous, or mkdir does not conform to POSIX,
+ # or it failed possibly due to a race condition. Create the
+ # directory the slow way, step by step, checking for races as we go.
+
+ case $dstdir in
+ /*) prefix='/';;
+ -*) prefix='./';;
+ *) prefix='';;
+ esac
+
+ eval "$initialize_posix_glob"
+
+ oIFS=$IFS
+ IFS=/
+ $posix_glob set -f
+ set fnord $dstdir
+ shift
+ $posix_glob set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test -z "$d" && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask=$mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
+ done
+
+ if test -n "$prefixes"; then
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
+ fi
+ fi
+ fi
+
+ if test -n "$dir_arg"; then
+ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+ else
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=$dstdir/_inst.$$_
+ rmtmp=$dstdir/_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+ # Copy the file name to the temp name.
+ (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+ # If -C, don't bother to copy if it wouldn't change the file.
+ if $copy_on_change &&
+ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
+ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+ eval "$initialize_posix_glob" &&
+ $posix_glob set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ $posix_glob set +f &&
+
+ test "$old" = "$new" &&
+ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+ then
+ rm -f "$dsttmp"
+ else
+ # Rename the file to the real destination.
+ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+ {
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ test ! -f "$dst" ||
+ $doit $rmcmd -f "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+ } ||
+ { echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
+ }
+ fi || exit 1
+
+ trap '' 0
+ fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/lib/diameter/autoconf/vxworks/sed.general b/lib/diameter/autoconf/vxworks/sed.general
new file mode 100644
index 0000000000..77b306aa0a
--- /dev/null
+++ b/lib/diameter/autoconf/vxworks/sed.general
@@ -0,0 +1,125 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1997-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+# Author: Patrik Winroth
+#
+# This sed program file is intended to be used when creating Makefiles
+# for vxworks from the generic Makefile.in that is found in a number
+# of directories (see configure.vxworks).
+#
+# This is the general part that is common for all architectures.
+#
+
+# Size of data types.
+s|^#undef SIZEOF_CHAR|#define SIZEOF_CHAR 1|
+s|^#undef SIZEOF_SHORT|#define SIZEOF_SHORT 2|
+s|^#undef SIZEOF_INT|#define SIZEOF_INT 4|
+s|^#undef SIZEOF_LONG_LONG|#define SIZEOF_LONG_LONG 8|
+s|^#undef SIZEOF_LONG$|#define SIZEOF_LONG 4|
+
+# General stuff.
+s|@erts_rootdir@|/clearcase/otp/erts|
+
+s|@LIBOBJS@|$(OBJDIR)/elib_malloc.o|
+s|@DLOAD_LIB@||
+s|@LDFLAGS@||
+# FIXME: A bit strange to clear out remaining DED_*
+s|@DED_LDFLAGS@||
+s|@DED_CFLAGS@||
+s|@STATIC_CFLAGS@||
+s|@GCCLIB@|libgcc.a|
+s|@DEFS@||
+s|@DEXPORT@||
+s|@DCFLAGS@||
+s|@THR_DEFS@||
+s|@THR_LIBS@||
+s|@THR_LIB_NAME@||
+s|@THR_X_LIBS@||
+s|@ETHR_X_LIBS@||
+s|@ETHR_LIBS@||
+s|@ETHR_LIB_NAME@||
+s|@ETHR_DEFS@||
+s|@ETHR_THR_LIB_BASE@||
+s|@EMU_THR_DEFS@||
+s|@EMU_THR_LIBS@||
+s|@EMU_THR_LIB_NAME@|ethread|
+s|@ERTS_ENABLE_KERNEL_POLL@|no|
+s|@cc_root@|/clearcase/otp/|
+# Define VxWorks even though cross-compiling.
+s|@HCFLAGS@|-DVXWORKS|
+s|@HCLIBS@||
+s|@ENABLE_ALLOC_TYPE_VARS@||
+s|@TERMCAP_LIB@||
+s|@ERTS_BUILD_SMP_EMU@|no|
+s|@ERTS_BUILD_HYBRID_EMU@|no|
+s|@HAVE_VALGRIND@|no|
+s|@EXEEXT@||
+s|@WITH_SCTP@||
+
+# HiPE
+s|@HIPE_ENABLED@||
+s|@PERFCTR_PATH@||
+s|@USE_PERFCTR@||
+
+# m4
+s|@OPSYS@|noopsys|
+
+# Conditional inclusion of applications
+s|@HIPE_APP@||
+s|@SSL_APP@|ssl|
+s|@CRYPTO_APP@|crypto|
+s|@SSH_APP@|ssh|
+
+# The target tools prefix, prepended to all cc,ld,as etc commands
+s|@TTPREFIX@|GCC_EXEC_PREFIX=@WIND_BASE@/host/@HOST_TYPE@/lib/gcc-lib/ @WIND_BASE@/host/@HOST_TYPE@/bin/|
+
+# Install programs etc
+s|@PERL@|perl|
+s|@INSTALL@|/usr/ucb/install -c|
+s|@INSTALL_PROGRAM@|${INSTALL}|
+s|@INSTALL_SCRIPT@|${INSTALL}|
+s|@INSTALL_DATA@|${INSTALL} -m 644|
+s|@INSTALL_DIR@|$(INSTALL) -d|
+s|@RM@|/bin/rm|
+s|@MKDIR@|/bin/mkdir|
+s|@ERLANG_OSTYPE@|vxworks|
+s|@vxworks_reclaim@|reclaim.h|
+s|@os_mon_programs@||
+s|@erlexec@|erl.exec|
+s|@EMU_LIBOBJS@||
+
+# General CFLAGS
+s|@GENERAL_CFLAGS@|-DHAVE_LOCALTIME_R -DHAVE_GMTIME_R -DENABLE_ELIB_MALLOC -DELIB_HEAP_USER -DELIB_SORTED_BLOCKS -DWORDS_BIGENDIAN -DELIB_DONT_INITIALIZE -DSIZEOF_CHAR=1 -DSIZEOF_SHORT=2 -DSIZEOF_INT=4 -DSIZEOF_LONG=4 -DSIZEOF_LONG_LONG=8 -DSIZEOF_VOID_P=4 -DERTS_USE_PORT_TASKS=1|g
+s|@WFLAGS@||
+
+# Thread flags for eidefs.mk (erl_interface)
+s|@EI_THREADS@|false|
+
+# Make java code compile although we don't test it on VxWorks (no license)
+s|@JAVAC@|javac|
+
+# What is this anyway?
+# Disable it and see what breaks.
+#s|@ded_soname@||
+
+# Only variable substituted directly
+s|$(LDFLAGS)|-r -d|
+s|@LIBRT@||
+# XXX What is EFFLAGS? Not used in the emulator Makefile.in anyway.
+s|$(EFLAGS)|-DENABLE_ELIB_MALLOC -DELIB_HEAP_USER -DELIB_SORTED_BLOCKS|
+
diff --git a/lib/diameter/autoconf/vxworks/sed.vxworks_cpu32 b/lib/diameter/autoconf/vxworks/sed.vxworks_cpu32
new file mode 100644
index 0000000000..5a1590e786
--- /dev/null
+++ b/lib/diameter/autoconf/vxworks/sed.vxworks_cpu32
@@ -0,0 +1,45 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1997-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+# Author: Patrik Winroth
+#
+# This sed program file is intended to be used when creating Makefiles for vxworks
+# from the generic Makefile.in that is found in a number of directories (see configure.vxworks)
+#
+#
+#
+s|@host@|vxworks_cpu32|
+s|@system_type@|vxworks_cpu32|
+s|@CC@|@TTPREFIX@cc68k|
+s|@HCC@|gcc|
+s|@LD@|@TTPREFIX@ld68k|
+s|@LIBS@||
+s|@DED_LD@|@TTPREFIX@ld68k|
+s|@DED_CFLAGS@|@CFLAGS@|
+s|@DEBUG_FLAGS@|-g|
+s|@GCCLIB_PATH@|@WIND_BASE@/host/@HOST_TYPE@/lib/gcc-lib/m68k-wrs-vxworks/cygnus-2.7.2-960126/m68000/msoft-float/libgcc.a|
+s|@RANLIB@|@TTPREFIX@ranlib68k|
+s|@AR@|@TTPREFIX@ar68k|
+s|@STRIP@|@TTPREFIX@strip68k|
+s|@SYMPREFIX@|_|
+s|@GCCLIBFLAGS@|-L@WIND_BASE@/host/@HOST_TYPE@/lib/gcc-lib/m68k-wrs-vxworks/cygnus-2.7.2-960126/m68000/msoft-float -lgcc|
+
+s|@LIB_CFLAGS@|@CFLAGS@|
+
+s|@CFLAGS@|@GENERAL_CFLAGS@ -DCPU=CPU32 -mnobitfield -DWANT_NONBLOCKING -DHAVE_MEMMOVE -DVXWORKS -I@WIND_BASE@/target/h -fno-builtin -nostdinc -fvolatile -msoft-float|
+#s|@LIB_CFLAGS@|@GENERAL_CFLAGS@ -DCPU=CPU32 -mnobitfield -DWANT_NONBLOCKING -DHAVE_MEMMOVE -DVXWORKS -I@WIND_BASE@/target/h -fno-builtin -nostdinc -fvolatile -msoft-float|
diff --git a/lib/diameter/autoconf/vxworks/sed.vxworks_ppc32 b/lib/diameter/autoconf/vxworks/sed.vxworks_ppc32
new file mode 100644
index 0000000000..9104b24ed3
--- /dev/null
+++ b/lib/diameter/autoconf/vxworks/sed.vxworks_ppc32
@@ -0,0 +1,52 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2006-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+# Author: Peter Andersson
+#
+# This sed program file is intended to be used when creating Makefiles for vxworks
+# from the generic Makefile.in that is found in a number of directories (see configure.vxworks)
+#
+#
+#
+s|@host@|vxworks_ppc32|
+s|@system_type@|vxworks_ppc32|
+s|@ARCH@|ppc32|
+s|@CC@|GCC_EXEC_PREFIX=@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc-lib/ @WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/bin/ccppc -mlongcall|
+s|@HCC@|gcc|
+s|@LD@|GCC_EXEC_PREFIX=@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc-lib/ @WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/bin/ldppc|
+s|@STRIP@|GCC_EXEC_PREFIX=@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc-lib/ @WIND_BASE@/workbench-2.3/@HOST_TYPE@/bin/stripppc|
+s|@SYMPREFIX@||
+s|@LIBS@||
+s|@GCCLIBFLAGS@|-L@WIND_BASE@/vxworks-6.3/target/lib/ppc/PPC32/common -lgcc|
+s|@DED_LD@|GCC_EXEC_PREFIX=@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc-lib/ @WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/bin/ldppc|
+s|@DED_CFLAGS@|@CFLAGS@|
+s|@DEBUG_CFLAGS@|@CFLAGS@|
+# generate dwarf debug code on PPC ..
+s|@DEBUG_FLAGS@|-gdwarf|
+# remove -g option
+s|TYPE_FLAGS = -g |TYPE_FLAGS = |
+s|@GCCLIB_PATH@|@WIND_BASE@/vxworks-6.3/target/lib/ppc/PPC32/common/libgcc.a|
+s|@RANLIB@|GCC_EXEC_PREFIX=@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc-lib/ @WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/bin/ranlibppc|
+s|@AR@|GCC_EXEC_PREFIX=@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc-lib/ @WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/bin/arppc|
+# -Dasm(X)= is for beam
+
+s|@LIB_CFLAGS@|@CFLAGS@|
+
+s|@CFLAGS@|@GENERAL_CFLAGS@ -DCPU=PPC32 -DTOOL_FAMILY=gnu -DTOOL=gnu -DWANT_NONBLOCKING -DHAVE_SENS -DHAVE_MEMMOVE -DVXWORKS -I@WIND_BASE@/vxworks-6.3/target/h -I@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc/powerpc-wrs-vxworks/3.4.4/include -I@WIND_BASE@/vxworks-6.3/target/h/wrn/coreip -mstrict-align -fvolatile -fno-builtin |
+
+#s|@LIB_CFLAGS@|@GENERAL_CFLAGS@ -DCPU=PPC32 -DTOOL_FAMILY=gnu -DTOOL=gnu -DWANT_NONBLOCKING -DHAVE_SENS -DHAVE_MEMMOVE -DVXWORKS -I@WIND_BASE@/vxworks-6.3/target/h/wrn/coreip -I@WIND_BASE@/vxworks-6.3/target/h -mstrict-align -fvolatile -fno-builtin |
diff --git a/lib/diameter/autoconf/vxworks/sed.vxworks_ppc603 b/lib/diameter/autoconf/vxworks/sed.vxworks_ppc603
new file mode 100644
index 0000000000..e1dd7c5afd
--- /dev/null
+++ b/lib/diameter/autoconf/vxworks/sed.vxworks_ppc603
@@ -0,0 +1,51 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2000-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+# Author: Patrik Winroth
+#
+# This sed program file is intended to be used when creating Makefiles for vxworks
+# from the generic Makefile.in that is found in a number of directories (see configure.vxworks)
+#
+#
+#
+s|@host@|vxworks_ppc603|
+s|@system_type@|vxworks_ppc603|
+s|@ARCH@|ppc603|
+s|@CC@|@TTPREFIX@ccppc -mlongcall|
+s|@HCC@|gcc|
+s|@LD@|@TTPREFIX@ldppc|
+s|@STRIP@|@TTPREFIX@stripppc|
+s|@SYMPREFIX@||
+s|@LIBS@||
+s|@GCCLIBFLAGS@|-L@WIND_BASE@/host/@HOST_TYPE@/lib/gcc-lib/powerpc-wrs-vxworks/cygnus-2.7.2-960126 -lgcc|
+s|@DED_LD@|@TTPREFIX@ldppc|
+s|@DED_CFLAGS@|@CFLAGS@|
+s|@DEBUG_CFLAGS@|@CFLAGS@|
+# generate dwarf debug code on PPC ..
+s|@DEBUG_FLAGS@|-gdwarf|
+# remove -g option
+s|TYPE_FLAGS = -g |TYPE_FLAGS = |
+s|@GCCLIB_PATH@|@WIND_BASE@/host/@HOST_TYPE@/lib/gcc-lib/powerpc-wrs-vxworks/cygnus-2.7.2-960126/libgcc.a|
+s|@RANLIB@|@TTPREFIX@ranlibppc|
+s|@AR@|@TTPREFIX@arppc|
+# -Dasm(X)= is for beam
+
+s|@LIB_CFLAGS@|@CFLAGS@|
+
+s|@CFLAGS@|@GENERAL_CFLAGS@ -DCPU=PPC603 -DWANT_NONBLOCKING -DHAVE_MEMMOVE -DVXWORKS -I@WIND_BASE@/target/h -mstrict-align -fvolatile -fno-builtin -fno-for-scope -D_GNU_TOOL|
+#s|@LIB_CFLAGS@|@GENERAL_CFLAGS@ -DCPU=PPC603 -DWANT_NONBLOCKING -DHAVE_MEMMOVE -DVXWORKS -I@WIND_BASE@/target/h -mstrict-align -fvolatile -fno-builtin -fno-for-scope -D_GNU_TOOL|
diff --git a/lib/diameter/autoconf/vxworks/sed.vxworks_ppc603_nolongcall b/lib/diameter/autoconf/vxworks/sed.vxworks_ppc603_nolongcall
new file mode 100644
index 0000000000..5d7673d323
--- /dev/null
+++ b/lib/diameter/autoconf/vxworks/sed.vxworks_ppc603_nolongcall
@@ -0,0 +1,51 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1997-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+# Author: Patrik Winroth
+#
+# This sed program file is intended to be used when creating Makefiles for vxworks
+# from the generic Makefile.in that is found in a number of directories (see configure.vxworks)
+#
+#
+#
+s|@host@|vxworks_ppc603|
+s|@system_type@|vxworks_ppc603|
+s|@ARCH@|ppc603|
+s|@CC@|@TTPREFIX@ccppc|
+s|@HCC@|gcc|
+s|@LD@|@TTPREFIX@ldppc|
+s|@STRIP@|@TTPREFIX@stripppc|
+s|@SYMPREFIX@||
+s|@LIBS@||
+s|@GCCLIBFLAGS@|-L@WIND_BASE@/host/@HOST_TYPE@/lib/gcc-lib/powerpc-wrs-vxworks/cygnus-2.7.2-960126 -lgcc|
+s|@DED_LD@|@TTPREFIX@ldppc|
+s|@DED_CFLAGS@|@CFLAGS@|
+# generate dwarf debug code on PPC ..
+s|@DEBUG_FLAGS@|-gdwarf|
+# remove -g option
+s|TYPE_FLAGS = -g |TYPE_FLAGS = |
+s|@GCCLIB_PATH@|@WIND_BASE@/host/@HOST_TYPE@/lib/gcc-lib/powerpc-wrs-vxworks/cygnus-2.7.2-960126/libgcc.a|
+s|@RANLIB@|@TTPREFIX@ranlibppc|
+s|@AR@|@TTPREFIX@arppc|
+# -Dasm(X)= is for beam
+
+s|@LIB_CFLAGS@|@CFLAGS@|
+
+s|@CFLAGS@|@GENERAL_CFLAGS@ -DCPU=PPC603 -DWANT_NONBLOCKING -DHAVE_MEMMOVE -DVXWORKS -I@WIND_BASE@/target/h -mstrict-align -fvolatile -fno-builtin -fno-for-scope -D_GNU_TOOL|
+#s|@LIB_CFLAGS@|@GENERAL_CFLAGS@ -DCPU=PPC603 -DWANT_NONBLOCKING -DHAVE_MEMMOVE -DVXWORKS -I@WIND_BASE@/target/h -mstrict-align -fvolatile -fno-builtin -fno-for-scope -D_GNU_TOOL|
+
diff --git a/lib/diameter/autoconf/vxworks/sed.vxworks_ppc860 b/lib/diameter/autoconf/vxworks/sed.vxworks_ppc860
new file mode 100644
index 0000000000..7a3c32df5b
--- /dev/null
+++ b/lib/diameter/autoconf/vxworks/sed.vxworks_ppc860
@@ -0,0 +1,50 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1997-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+# Author: Patrik Winroth
+#
+# This sed program file is intended to be used when creating Makefiles for vxworks
+# from the generic Makefile.in that is found in a number of directories (see configure.vxworks)
+#
+#
+#
+s|@host@|vxworks_ppc860|
+s|@system_type@|vxworks_ppc860|
+s|@ARCH@|ppc860|
+s|@CC@|@TTPREFIX@ccppc -mlongcall|
+s|@HCC@|gcc|
+s|@LD@|@TTPREFIX@ldppc|
+s|@STRIP@|@TTPREFIX@stripppc|
+s|@SYMPREFIX@||
+s|@LIBS@||
+s|@GCCLIBFLAGS@|-L@WIND_BASE@/host/@HOST_TYPE@/lib/gcc-lib/powerpc-wrs-vxworks/cygnus-2.7.2-960126/soft-float -lgcc|
+s|@DED_LD@|@TTPREFIX@ldppc|
+s|@DED_CFLAGS@|@CFLAGS@|
+s|@DEBUG_CFLAGS@|@CFLAGS@|
+# generate dwarf debug code on PPC ..
+s|@DEBUG_FLAGS@|-gdwarf|
+# remove -g option (go for dwarf)
+s|TYPE_FLAGS = -g |TYPE_FLAGS = |
+s|@GCCLIB_PATH@|@WIND_BASE@/host/@HOST_TYPE@/lib/gcc-lib/powerpc-wrs-vxworks/cygnus-2.7.2-960126/soft-float/libgcc.a|
+s|@RANLIB@|@TTPREFIX@ranlibppc|
+s|@AR@|@TTPREFIX@arppc|
+
+s|@LIB_CFLAGS@|@CFLAGS@|
+
+s|@CFLAGS@|@GENERAL_CFLAGS@ -DCPU=PPC860 -DWANT_NONBLOCKING -DHAVE_MEMMOVE -DVXWORKS -I@WIND_BASE@/target/h -mcpu=860 -fvolatile -fno-builtin -fno-for-scope -msoft-float -D_GNU_TOOL -nostdinc|
+#s|@LIB_CFLAGS@|@GENERAL_CFLAGS@ -DCPU=PPC860 -DWANT_NONBLOCKING -DHAVE_MEMMOVE -DVXWORKS -I@WIND_BASE@/target/h -mcpu=powerpc -fvolatile -fno-builtin -fno-for-scope -msoft-float -D_GNU_TOOL -nostdinc|
diff --git a/lib/diameter/autoconf/vxworks/sed.vxworks_simlinux b/lib/diameter/autoconf/vxworks/sed.vxworks_simlinux
new file mode 100644
index 0000000000..56eae6507c
--- /dev/null
+++ b/lib/diameter/autoconf/vxworks/sed.vxworks_simlinux
@@ -0,0 +1,59 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2008-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+# Author: Peter Andersson
+#
+# This sed program file is intended to be used when creating Makefiles for vxworks
+# from the generic Makefile.in that is found in a number of directories (see configure.vxworks)
+#
+#
+#
+s|@host@|vxworks_simlinux|
+s|@system_type@|vxworks_simlinux|
+s|@ARCH@|simlinux|
+
+s|@CC@|GCC_EXEC_PREFIX=@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc-lib/ @WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/bin/ccpentium|
+
+s|@HCC@|gcc|
+
+s|@LD@|GCC_EXEC_PREFIX=@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc-lib/ @WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/bin/ldpentium|
+
+#s|@STRIP@|GCC_EXEC_PREFIX=@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc-lib/ @WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/bin/strip|
+s|@STRIP@||
+
+s|@SYMPREFIX@||
+s|@LIBS@||
+s|@GCCLIBFLAGS@|-L@WIND_BASE@/vxworks-6.3/target/lib/simlinux/SIMLINUX/common -lgcc|
+
+s|@DED_LD@|GCC_EXEC_PREFIX=@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc-lib/ @WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/bin/ldpentium|
+
+s|@DED_CFLAGS@|@CFLAGS@|
+s|@DEBUG_CFLAGS@|@CFLAGS@|
+# remove -g option
+s|TYPE_FLAGS = -g |TYPE_FLAGS = |
+s|@GCCLIB_PATH@|@WIND_BASE@/vxworks-6.3/target/lib/simlinux/SIMLINUX/common/libgcc.a|
+
+s|@RANLIB@|GCC_EXEC_PREFIX=@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc-lib/ @WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/bin/ranlibpentium|
+
+s|@AR@|GCC_EXEC_PREFIX=@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc-lib/ @WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/bin/arpentium|
+
+# -Dasm(X)= is for beam
+s|@LIB_CFLAGS@|@CFLAGS@|
+
+s|@CFLAGS@|@GENERAL_CFLAGS@ -DCPU=SIMLINUX -DTOOL_FAMILY=gnu -DTOOL=gnu -DWANT_NONBLOCKING -DHAVE_SENS -DHAVE_MEMMOVE -DVXWORKS -DDEBUG -I@WIND_BASE@/vxworks-6.3/target/h -I@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc/i586-wrs-vxworks/3.4.4/include -I@WIND_BASE@/vxworks-6.3/target/h/wrn/coreip -fvolatile -fno-builtin |
+#s|@LIB_CFLAGS@|@GENERAL_CFLAGS@ -DCPU=SIMLINUX -DTOOL_FAMILY=gnu -DTOOL=gnu -DWANT_NONBLOCKING -DHAVE_SENS -DHAVE_MEMMOVE -DVXWORKS -DDEBUG -I@WIND_BASE@/vxworks-6.3/target/h -I@WIND_BASE@/vxworks-6.3/target/h/wrn/coreip -mstrict-align -fvolatile -fno-builtin |
diff --git a/lib/diameter/autoconf/vxworks/sed.vxworks_simso b/lib/diameter/autoconf/vxworks/sed.vxworks_simso
new file mode 100644
index 0000000000..6b845d31de
--- /dev/null
+++ b/lib/diameter/autoconf/vxworks/sed.vxworks_simso
@@ -0,0 +1,64 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2005-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+# Author: Peter Andersson
+#
+# This sed program file is intended to be used when creating Makefiles for vxworks
+# from the generic Makefile.in that is found in a number of directories (see configure.vxworks)
+#
+#
+#
+s|@host@|vxworks_simso|
+s|@system_type@|vxworks_simso|
+s|@ARCH@|simso|
+
+# Tornado2.2: s|@CC@|@TTPREFIX@ccsimso|
+s|@CC@|GCC_EXEC_PREFIX=@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc-lib/ @WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/bin/ccsparc|
+
+s|@HCC@|gcc|
+
+# Tornado2.2: s|@LD@|@TTPREFIX@ldsimso|
+s|@LD@|GCC_EXEC_PREFIX=@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc-lib/ @WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/bin/ldsparc|
+
+# Tornado2.2: s|@STRIP@|@TTPREFIX@stripsimso|
+s|@STRIP@|GCC_EXEC_PREFIX=@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc-lib/ @WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/bin/stripsparc|
+
+s|@SYMPREFIX@||
+s|@LIBS@||
+s|@GCCLIBFLAGS@|-L@WIND_BASE@/vxworks-6.3/target/lib/simso/SIMSPARCSOLARIS/common -lgcc|
+
+# Tornado2.2: s|@DED_LD@|@TTPREFIX@ldsimso|
+s|@DED_LD@|GCC_EXEC_PREFIX=@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc-lib/ @WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/bin/ldsparc|
+
+s|@DED_CFLAGS@|@CFLAGS@|
+s|@DEBUG_CFLAGS@|@CFLAGS@|
+# remove -g option
+s|TYPE_FLAGS = -g |TYPE_FLAGS = |
+s|@GCCLIB_PATH@|@WIND_BASE@/vxworks-6.3/target/lib/simso/SIMSPARCSOLARIS/common/libgcc.a|
+
+# Tornado2.2: s|@RANLIB@|@TTPREFIX@ranlibsimso|
+s|@RANLIB@|GCC_EXEC_PREFIX=@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc-lib/ @WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/bin/ranlibsparc|
+
+# Tornado2.2: s|@AR@|arsimso|
+s|@AR@|GCC_EXEC_PREFIX=@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc-lib/ @WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/bin/arsparc|
+
+# -Dasm(X)= is for beam
+s|@LIB_CFLAGS@|@CFLAGS@|
+
+s|@CFLAGS@|@GENERAL_CFLAGS@ -DCPU=SIMSPARCSOLARIS -DTOOL_FAMILY=gnu -DTOOL=gnu -DWANT_NONBLOCKING -DHAVE_SENS -DHAVE_MEMMOVE -DVXWORKS -DDEBUG -I@WIND_BASE@/vxworks-6.3/target/h -I@WIND_BASE@/gnu/3.4.4-vxworks-6.3/@HOST_TYPE@/lib/gcc/sparc-wrs-vxworks/3.4.4/include -I@WIND_BASE@/vxworks-6.3/target/h/wrn/coreip -fvolatile -fno-builtin |
+#s|@LIB_CFLAGS@|@GENERAL_CFLAGS@ -DCPU=SIMSPARCSOLARIS -DTOOL_FAMILY=gnu -DTOOL=gnu -DWANT_NONBLOCKING -DHAVE_SENS -DHAVE_MEMMOVE -DVXWORKS -DDEBUG -I@WIND_BASE@/vxworks-6.3/target/h -I@WIND_BASE@/vxworks-6.3/target/h/wrn/coreip -mstrict-align -fvolatile -fno-builtin |
diff --git a/lib/diameter/autoconf/vxworks/sed.vxworks_sparc b/lib/diameter/autoconf/vxworks/sed.vxworks_sparc
new file mode 100644
index 0000000000..6f637d8746
--- /dev/null
+++ b/lib/diameter/autoconf/vxworks/sed.vxworks_sparc
@@ -0,0 +1,38 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1997-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+# Author: Patrik Winroth
+#
+# This sed program file is intended to be used when creating Makefiles for vxworks
+# from the generic Makefile.in that is found in a number of directories (see configure.vxworks)
+#
+
+# ccsparc -O2 doesn't work when compiling "rundir"/gc.c - signal 11 is generated when trying
+# therefore it is compiled with -O1 instead, which works - get a new ccsparc !
+s/\$(COMPILE\.emu) -o \$@ -c gc\.c/$(CC) @CFLAGS@ @DEFS@ -O1 $(BEAM_MODE) -I$(SYSDIR) -I$(EMUDIR) -I. $(CPPFLAGS) -c -o $@ -c gc.c/
+s/@host@/vxworks_sparc/
+s/@system_type@/vxworks_sparc/
+s/@CC@/\/home\/gandalf\/bsproj\/tools\/vw-gnu\/solaris.sparc\/bin\/ccsparc/
+s/@HCC@/gcc/
+s/@LD@/\/home\/gandalf\/bsproj\/tools\/vw-gnu\/solaris.sparc\/bin\/ldsparc/
+s/@DEBUG_FLAGS@/-g/
+s/@GCCLIB_PATH@/\/home\/gandalf\/bsproj\/tools\/vw-gnu\/solaris.sparc\/lib\/gcc-lib\/sparc-wrs-vxworks\/cygnus-2.2.3.1\/libgcc.a/
+s/@RANLIB@/ranlibsparc/
+s/@AR@/arsparc/
+s/@CFLAGS@/-I\/home\/gandalf\/bsproj\/BS.2\/UOS\/vw\/5.2\/h -DWANT_NONBLOCKING -DHAVE_MEMMOVE -DCPU=SPARC -DVXWORKS -fno-builtin -nostdinc/
+
diff --git a/lib/diameter/bin/diameterc b/lib/diameter/bin/diameterc
new file mode 100755
index 0000000000..f5cf3ebc10
--- /dev/null
+++ b/lib/diameter/bin/diameterc
@@ -0,0 +1,155 @@
+#!/usr/bin/env escript
+%% Use -*- erlang -*- mode in Erlang
+
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameterc).
+
+-mode(compile).
+
+-include_lib("kernel/include/file.hrl").
+
+%% The parsed command line.
+-record(argv, {file,
+ options = [{outdir, "."}],
+ output = [erl, hrl]}).
+
+usage() ->
+ io:format(
+ "~w [options] file~n"
+ "~n"
+ " Compile a diameter dictionary file (.dia) to Erlang source (.erl)~n"
+ " and/or header (.hrl) files.~n"
+ "~n"
+ " options:~n"
+ " -h = print this message~n"
+ " -v = verbose output~n"
+ " -o dir = set the output directory (default .)~n"
+ " -i dir = set an include directory for inherited beams~n"
+ " -E = no .erl output~n"
+ " -H = no .hrl output~n"
+ " -d = write intermediate files (.spec and .forms)~n",
+ [?MODULE]).
+
+main(Args) ->
+ %% Add the ebin directory relative to the script path.
+ BinDir = filename:dirname(escript:script_name()),
+ code:add_path(filename:join([BinDir, "..", "ebin"])),
+ halt(gen(Args)).
+
+gen(Args) ->
+ try parse_args(Args) of
+ #argv{} = A ->
+ compile(A)
+ catch
+ throw: usage ->
+ usage(),
+ 0;
+ throw: Reason ->
+ error_msg(norm(Reason)),
+ 1
+ end.
+
+compile(#argv{file = File, options = Opts} = A) ->
+ try
+ Spec = diameter_spec_util:parse(File, Opts),
+ maybe_output(A, Spec, Opts, spec), %% the spec file
+ maybe_output(A, Spec, Opts, erl), %% the erl file
+ maybe_output(A, Spec, Opts, hrl), %% The hrl file
+ 0
+ catch
+ error: Reason ->
+ error_msg({"ERROR: ~p~n ~p", [Reason, erlang:get_stacktrace()]}),
+ 2
+ end.
+
+maybe_output(#argv{file = File, output = Output}, Spec, Opts, Mode) ->
+ lists:member(Mode, Output)
+ andalso diameter_codegen:from_spec(File, Spec, Opts, Mode).
+
+error_msg({Fmt, Args}) ->
+ io:format(standard_error, Fmt ++ "~n", Args).
+
+norm({_,_} = T) ->
+ T;
+norm(Str) ->
+ {Str, []}.
+
+%% parse_args/1
+
+parse_args(Args)
+ when is_list(Args) ->
+ arg(Args, #argv{}).
+
+arg(["-h" | _], _) ->
+ throw(usage);
+
+arg(["-v" | Args], #argv{options = Opts} = A) ->
+ arg(Args, A#argv{options = [verbose | Opts]});
+
+arg(["-o", Dir | Args], #argv{options = Opts} = A) ->
+ true = dir_exists(Dir),
+ arg(Args, A#argv{options = [{outdir, Dir} | Opts]});
+
+arg(["-i", Dir | Args], #argv{options = Opts} = A) ->
+ true = dir_exists(Dir),
+ arg(Args, A#argv{options = Opts ++ [{include, Dir}]});
+
+arg(["-E" | Args], #argv{output = Output} = A) ->
+ arg(Args, A#argv{output = lists:delete(erl, Output)});
+
+arg(["-H" | Args], #argv{output = Output} = A) ->
+ arg(Args, A#argv{output = lists:delete(hrl, Output)});
+
+arg(["-d" | Args], #argv{options = Opts, output = Output} = A) ->
+ arg(Args, A#argv{options = [debug | Opts],
+ output = [spec | Output]});
+
+arg([[$- = M, C, H | T] | Args], A) %% clustered options
+ when C /= $i, C /= $o ->
+ arg([[M,C], [M,H|T] | Args], A);
+
+arg([File], A) ->
+ true = file_exists(File),
+ A#argv{file = File};
+
+arg([], _) ->
+ throw("No input file");
+
+arg([Bad | _], _) ->
+ throw({"Unknown option: ~p", [Bad]}).
+
+%% path_exists/2
+
+path_exists(File, Type) ->
+ case file:read_file_info(File) of
+ {ok, #file_info{type = Type}} ->
+ true;
+ {ok, #file_info{type = WrongType}} ->
+ throw({"Invalid type for file: ~p, ~p", [WrongType, File]});
+ _ ->
+ throw({"No such file: ~p", [File]})
+ end.
+
+file_exists(File) ->
+ path_exists(File, regular).
+
+dir_exists(File) ->
+ path_exists(File, directory).
diff --git a/lib/diameter/configure.in b/lib/diameter/configure.in
new file mode 100644
index 0000000000..9aca3859c5
--- /dev/null
+++ b/lib/diameter/configure.in
@@ -0,0 +1,138 @@
+dnl Process this file with autoconf to produce a configure script.
+
+dnl %CopyrightBegin%
+dnl
+dnl Copyright Ericsson AB 1998-2011. All Rights Reserved.
+dnl
+dnl The contents of this file are subject to the Erlang Public License,
+dnl Version 1.1, (the "License"); you may not use this file except in
+dnl compliance with the License. You should have received a copy of the
+dnl Erlang Public License along with this software. If not, it can be
+dnl retrieved online at http://www.erlang.org/.
+dnl
+dnl Software distributed under the License is distributed on an "AS IS"
+dnl basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+dnl the License for the specific language governing rights and limitations
+dnl under the License.
+dnl
+dnl %CopyrightEnd%
+
+if test "x$no_recursion" != "xyes" -a "x$OVERRIDE_CONFIG_CACHE" = "x"; then
+ # We do not want to use a common cache!
+ cache_file=/dev/null
+fi
+
+AC_INIT(vsn.mk)
+
+dnl <STANDALONE DIAMETER>
+dnl This is needed for diameters own environment to rock,
+dnl but since we are now integrated into OTP, we skip it.
+dnl In order to build stand-alone we need atleast 2.63...
+dnl AC_PREREQ(2.63)
+dnl </STANDALONE DIAMETER>
+
+dnl LM_PRECIOUS_VARS
+
+
+dnl The OTP source tree is the default "top",
+dnl but we can also define our own top: DIAMETER_TOP
+
+if test -n "$ERL_TOP" || test -d $ERL_TOP ; then
+ erl_top=${ERL_TOP}
+ AC_CONFIG_AUX_DIRS($erl_top/erts/autoconf)
+ DIAMETER_TOP=${ERL_TOP}/lib/diameter
+else
+ AC_ARG_VAR(DIAMETER_TOP, [Diameter top source directory])
+ if test -n "$DIAMETER_TOP" || test -d $DIAMETER_TOP ; then
+ AC_CONFIG_AUX_DIRS(autoconf)
+ fi
+
+ dnl <STANDALONE DIAMETER>
+ dnl AC_ERLANG_SUBST_ROOT_DIR
+ dnl AC_ERLANG_SUBST_LIB_DIR
+ dnl AC_ERLANG_CHECK_LIB([erl_docgen],
+ dnl [echo "erl_docgen version \"$ERLANG_LIB_VER_erl_docgen\""
+ dnl echo "is installed in \"$ERLANG_LIB_DIR_erl_docgen\""],
+ dnl [AC_MSG_ERROR([erl_docgen was not found!])])
+ dnl AC_ERLANG_CHECK_LIB([test_server],
+ dnl [echo "test_server version \"$ERLANG_LIB_VER_test_server\""
+ dnl echo "is installed in \"$ERLANG_LIB_DIR_test_server\""],
+ dnl [AC_MSG_ERROR([test_server was not found!])])
+ dnl </STANDALONE DIAMETER>
+
+fi
+
+AC_SUBST(DIAMETER_TOP)
+export DIAMETER_TOP
+
+if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
+ AC_CANONICAL_HOST
+fi
+
+TARGET=$host
+AC_SUBST(TARGET)
+
+if test "x$erl_top" = "x"; then
+ dnl STANDALONE DIAMETER
+ AC_CHECK_PROGS(XSLTPROC, xsltproc)
+ if test -z "$XSLTPROC"; then
+ echo "xsltproc" >> doc/CONF_INFO
+ AC_MSG_WARN([No 'xsltproc' command found: the documentation can not be built])
+ fi
+
+ AC_CHECK_PROGS(FOP, fop)
+ if test -z "$FOP"; then
+ AC_MSG_ERROR([No 'fop' command found: the documentation can not be built])
+ fi
+fi
+
+dnl
+dnl We can live with Solaris /usr/ucb/install
+dnl
+case $host in
+ *-*-solaris*|free_source)
+ if test -x /usr/ucb/install; then
+ INSTALL="/usr/ucb/install -c"
+ fi
+ ;;
+ *)
+ ;;
+esac
+AC_PROG_INSTALL
+LM_PROG_INSTALL_DIR
+
+case $host_os in
+ darwin*)
+ dnl Need to preserve modification time on archives;
+ dnl otherwise, ranlib has to be run on archives
+ dnl again after installation.
+ INSTALL_DATA="$INSTALL_DATA -p";;
+ *)
+ ;;
+esac
+
+dnl
+dnl Fix for Tilera install permissions
+dnl
+
+case $build in
+ *tile*)
+ INSTALL_PROGRAM="$INSTALL_PROGRAM -m755"
+ INSTALL_SCRIPT="$INSTALL_SCRIPT -m755"
+ ;;
+ *)
+ ;;
+esac
+
+
+dnl <STANDALONE DIAMETER>
+dnl AC_ERLANG_NEED_ERL([$PATH])
+dnl AC_ERLANG_NEED_ERLC([$PATH])
+dnl </STANDALONE DIAMETER>
+
+AC_OUTPUT(
+ Makefile:Makefile.in
+ src/app/diameter.mk:src/app/diameter.mk.in
+ make/$host/rules.mk:make/rules.mk.in
+ )
+
diff --git a/lib/diameter/doc/html/.gitignore b/lib/diameter/doc/html/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/diameter/doc/html/.gitignore
diff --git a/lib/diameter/doc/man1/.gitignore b/lib/diameter/doc/man1/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/diameter/doc/man1/.gitignore
diff --git a/lib/diameter/doc/man3/.gitignore b/lib/diameter/doc/man3/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/diameter/doc/man3/.gitignore
diff --git a/lib/diameter/doc/man4/.gitignore b/lib/diameter/doc/man4/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/diameter/doc/man4/.gitignore
diff --git a/lib/diameter/doc/pdf/.gitignore b/lib/diameter/doc/pdf/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/diameter/doc/pdf/.gitignore
diff --git a/lib/diameter/doc/src/.gitignore b/lib/diameter/doc/src/.gitignore
new file mode 100644
index 0000000000..feeb378fd8
--- /dev/null
+++ b/lib/diameter/doc/src/.gitignore
@@ -0,0 +1,2 @@
+
+/depend.mk
diff --git a/lib/diameter/doc/src/Makefile b/lib/diameter/doc/src/Makefile
new file mode 100644
index 0000000000..1453138cb6
--- /dev/null
+++ b/lib/diameter/doc/src/Makefile
@@ -0,0 +1,198 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+ifneq ($(ERL_TOP),)
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+else
+include $(DIAMETER_TOP)/make/target.mk
+include $(DIAMETER_TOP)/make/$(TARGET)/rules.mk
+endif
+
+include ../../vsn.mk
+
+VSN = $(DIAMETER_VSN)
+
+RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+include files.mk
+
+XML_REF_FILES = $(XML_REF1_FILES) $(XML_REF3_FILES) $(XML_REF4_FILES)
+
+XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) \
+ $(XML_REF_FILES) \
+ $(XML_PART_FILES) $(XML_CHAPTER_FILES)
+
+INTERNAL_HTML_FILES = $(TECHNICAL_DESCR_FILES:%.xml=$(HTMLDIR)/%.html)
+
+HTML_APP_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html)
+HTML_EXTRA_FILES = $(XML_EXTRA_FILES:%.xml=$(HTMLDIR)/%.html)
+HTML_PART_FILES = $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
+
+HTML_FILES = $(HTML_APP_FILES) $(HTML_EXTRA_FILES) $(HTML_PART_FILES)
+
+INFO_FILE = ../../info
+
+HTML_REF_FILES = $(XML_REF_FILES:%.xml=$(HTMLDIR)/%.html)
+
+HTML_CHAPTER_FILES = $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html)
+
+EXTRA_FILES = \
+ $(DEFAULT_GIF_FILES) \
+ $(DEFAULT_HTML_FILES) \
+ $(HTML_REF_FILES) \
+ $(HTML_CHAPTER_FILES)
+
+MAN1_FILES = $(XML_REF1_FILES:%.xml=$(MAN1DIR)/%.1)
+MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
+MAN4_FILES = $(XML_REF4_FILES:%.xml=$(MAN4DIR)/%.4)
+
+HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
+
+TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+
+STANDARD_DIR = ../standard
+STANDARDS =
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+
+XML_FLAGS +=
+DVIPS_FLAGS +=
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+$(HTMLDIR)/%.gif: %.gif
+ $(INSTALL_DATA) $< $@
+
+docs: pdf html man
+
+ldocs: local_docs $(INDEX_TARGET)
+
+$(TOP_PDF_FILE): $(XML_FILES)
+
+pdf: $(TOP_PDF_FILE)
+
+html: gifs $(HTML_REF_MAN_FILE)
+
+clean clean_docs: clean_pdf clean_html clean_man
+ rm -f errs core *~
+ rm -f depend.mk
+
+clean_pdf:
+ rm -f $(PDFDIR)/*
+
+clean_man:
+ rm -f $(MAN1DIR)/* $(MAN3DIR)/* $(MAN4DIR)/*
+
+clean_html:
+ rm -rf $(HTMLDIR)/*
+
+gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
+
+man: $(MAN1_FILES) $(MAN3_FILES) $(MAN4_FILES)
+
+$(INDEX_TARGET): $(INDEX_SRC) $(APP_FILE)
+ sed -e 's/%VSN%/$(VSN)/; \
+ s/%ERLANG_SITE%/www\.erlang\.se\//; \
+ s/%UP_ONE_LEVEL%/..\/..\/..\/doc\/index.html/; \
+ s/%OFF_PRINT%/pdf\/diameter-$(VSN).pdf/' $< > $@
+
+depend: depend.mk
+
+debug opt:
+
+info:
+ @echo "->Makefile<-"
+ @echo ""
+ @echo "DOCSUPPORT = $(DOCSUPPORT)"
+ @echo ""
+ @echo "INDEX_FILE = $(INDEX_FILE)"
+ @echo "INDEX_SRC = $(INDEX_SRC)"
+ @echo "INDEX_TARGET = $(INDEX_TARGET)"
+ @echo ""
+ @echo "XML_APPLICATION_FILES = $(XML_APPLICATION_FILES)"
+ @echo "XML_PART_FILES = $(XML_PART_FILES)"
+ @echo "XML_REF1_FILES = $(XML_REF1_FILES)"
+ @echo "XML_REF3_FILES = $(XML_REF3_FILES)"
+ @echo "XML_REF4_FILES = $(XML_REF4_FILES)"
+ @echo "XML_CHAPTER_FILES = $(XML_CHAPTER_FILES)"
+ @echo ""
+ @echo "GIF_FILES = $(GIF_FILES)"
+ @echo ""
+ @echo "TEX_FILES_USERS_GUIDE = $(TEX_FILES_USERS_GUIDE)"
+ @echo "TEX_FILES_REF_MAN = $(TEX_FILES_REF_MAN)"
+ @echo "TEX_FILES_BOOK = $(TEX_FILES_BOOK)"
+ @echo ""
+ @echo "MAN1_FILES = $(MAN1_FILES)"
+ @echo "MAN3_FILES = $(MAN3_FILES)"
+ @echo "MAN4_FILES = $(MAN4_FILES)"
+ @echo ""
+ @echo "HTML_FILES = $(HTML_FILES)"
+ @echo "TOP_HTML_FILES = $(TOP_HTML_FILES)"
+ @echo ""
+ @echo "DEFAULT_HTML_FILES = $(DEFAULT_HTML_FILES)"
+ @echo "DEFAULT_GIF_FILES = $(DEFAULT_GIF_FILES)"
+ @echo ""
+ @echo ""
+
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+ifneq ($(ERL_TOP),)
+include $(ERL_TOP)/make/otp_release_targets.mk
+else
+include $(DIAMETER_TOP)/make/release_targets.mk
+endif
+
+release_docs_spec: $(LOCAL)docs
+ $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
+ $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DIR) $(RELEASE_PATH)/man/man1
+ $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
+ $(INSTALL_DIR) $(RELEASE_PATH)/man/man4
+ $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
+ $(INSTALL_DATA) $(HTMLDIR)/*.* $(RELSYSDIR)/doc/html
+ $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
+ $(INSTALL_DATA) $(MAN1_FILES) $(RELEASE_PATH)/man/man1
+ $(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
+ $(INSTALL_DATA) $(MAN4_FILES) $(RELEASE_PATH)/man/man4
+ [ -z "$(LOCAL)" ] || cp -r $(HTMLDIR)/js $(RELSYSDIR)/doc/html
+ echo $(LOCAL)
+
+release_spec:
+
+depend.mk: depend.sed $(XML_REF_FILES) $(XML_CHAPTER_FILES) Makefile
+ (for f in $(XML_REF_FILES) $(XML_CHAPTER_FILES); do \
+ sed -f $< $$f | sed "s@%FILE%@`basename $$f .xml`@g"; \
+ done) \
+ > $@
+
+-include depend.mk
+
+.PHONY: clean clean_html clean_man clean_pdf \
+ depend debug opt info \
+ docs gifs html ldocs man pdf \
+ release_docs_spec release_spec
diff --git a/lib/diameter/doc/src/book.xml b/lib/diameter/doc/src/book.xml
new file mode 100644
index 0000000000..960296528b
--- /dev/null
+++ b/lib/diameter/doc/src/book.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE book SYSTEM "book.dtd">
+
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
+
+<header titlestyle="normal">
+<copyright>
+<year>2011</year>
+<holder>Ericsson AB. All Rights Reserved.</holder>
+</copyright>
+<legalnotice>
+The contents of this file are subject to the Erlang Public License,
+Version 1.1, (the "License"); you may not use this file except in
+compliance with the License. You should have received a copy of the
+Erlang Public License along with this software. If not, it can be
+retrieved online at http://www.erlang.org/.
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+the License for the specific language governing rights and limitations
+under the License.
+
+</legalnotice>
+
+<title>Diameter</title>
+<prepared></prepared>
+<docno></docno>
+<date></date>
+<rev></rev>
+<file>book.xml</file>
+</header>
+
+<insidecover>
+</insidecover>
+
+<pagetext>Diameter</pagetext>
+
+<preamble>
+<contents level="2"></contents>
+</preamble>
+
+<parts lift="no">
+<xi:include href="user_man.xml"/>
+</parts>
+
+<applications>
+<xi:include href="ref_man.xml"/>
+</applications>
+
+<releasenotes>
+<xi:include href="notes.xml"/>
+</releasenotes>
+
+<index></index>
+
+</book>
diff --git a/lib/diameter/doc/src/depend.sed b/lib/diameter/doc/src/depend.sed
new file mode 100644
index 0000000000..42de597f15
--- /dev/null
+++ b/lib/diameter/doc/src/depend.sed
@@ -0,0 +1,38 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+#
+# Generate dependencies for html output. The output is further
+# massaged in Makefile.
+#
+
+/^<com>/b c
+/^<module>/b c
+
+/^<chapter>/!d
+
+# Chapter: html basename is same as xml.
+s@@$(HTMLDIR)/%FILE%.html: %FILE%.xml@
+q
+
+# Reference: html basename is from contents of com/module element.
+:c
+s@^[^>]*>@@
+s@<.*@@
+s@.*@$(HTMLDIR)/&.html: %FILE%.xml@
+q
diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml
new file mode 100644
index 0000000000..43c497f50a
--- /dev/null
+++ b/lib/diameter/doc/src/diameter.xml
@@ -0,0 +1,1196 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+<header>
+
+<copyright>
+<year>2011</year>
+<holder>Ericsson AB. All Rights Reserved.</holder>
+</copyright>
+<legalnotice>
+The contents of this file are subject to the Erlang Public License,
+Version 1.1, (the "License"); you may not use this file except in
+compliance with the License. You should have received a copy of the
+Erlang Public License along with this software. If not, it can be
+retrieved online at http://www.erlang.org/.
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+the License for the specific language governing rights and limitations
+under the License.
+
+</legalnotice>
+
+<title>diameter(3)</title>
+
+<prepared>Anders Svensson</prepared>
+<responsible></responsible>
+<docno></docno>
+<approved></approved>
+<checked></checked>
+<date></date>
+<rev>%VSN%</rev>
+<file>diameter.xml</file>
+
+</header>
+
+<!-- ===================================================================== -->
+<!-- ===================================================================== -->
+
+<module>diameter</module>
+<modulesummary>Main API of the diameter application.</modulesummary>
+
+<description>
+<p>
+This module provides the interface with which a user
+creates a service that sends and receives messages using the
+Diameter protocol as defined in RFC 3588.</p>
+
+<p>
+Basic usage consists of creating a representation of a
+locally implemented Diameter peer and its capabilities with <seealso
+marker="#start_service">start_service/2</seealso>, adding transport
+capability using <seealso
+marker="#add_transport">add_transport/2</seealso> and sending Diameter
+requests and receiving Diameter answers with <seealso
+marker="#call">call/4</seealso>.
+Incoming Diameter requests are communicated as callbacks to a
+<seealso
+marker="diameter_app">diameter_app(3)</seealso> callback modules as
+specified in the service configuration.</p>
+
+<p>
+Beware the difference between <em>diameter application</em> and
+<em>Diameter application</em>.
+The former refers to the Erlang application named diameter whose main
+api is defined here, the latter to an application of the Diameter
+protocol in the sense of RFC 3588.
+More generally, capitalized Diameter refers to the RFC
+and diameter to this implementation.</p>
+
+<p>
+The diameter application must be started before calling functions in
+this module.</p>
+
+</description>
+
+<!-- ===================================================================== -->
+<!-- ===================================================================== -->
+<section>
+<title>DATA TYPES</title>
+
+<taglist>
+
+<tag><c>Address()</c></tag>
+<tag><c>DiameterIdentity()</c></tag>
+<tag><c>Time()</c></tag>
+<tag><c>Unsigned32()</c></tag>
+<tag><c>UTF8String()</c></tag>
+<item>
+<p>
+Types corresponding to RFC 3588 AVP Data Formats.
+Defined in <seealso marker="diameter_dict">diameter_dict(4)</seealso>.</p>
+
+<marker id="application_alias"/>
+</item>
+
+<tag><c>application_alias() = term()</c></tag>
+<item>
+<p>
+A name identifying a Diameter application in
+service configuration passed to <seealso
+marker="#start_service">start_service/2</seealso> and passed to
+<seealso marker="#call">call/4</seealso> when sending requests
+belonging to the application.</p>
+
+<marker id="application_module"/>
+</item>
+
+<tag><c>application_module() = Mod | [Mod | ExtraArgs]</c></tag>
+<item>
+<code>
+Mod = atom()
+ExtraArgs = list()
+</code>
+
+<p>
+A module implementing the callback interface defined in <seealso
+marker="diameter_app">diameter_app(3)</seealso>, along with any
+extra arguments to be appended to those documented for the interface.
+Any extra arguments are appended to the documented list of arguments for
+each function.
+Note that additional arguments specific to an outgoing request be
+specified to <seealso marker="#call">call/4</seealso>, in which case
+the call-specific arguments are appended to any specified with the
+callback module.</p>
+
+<marker id="application_opt"/>
+</item>
+
+<tag><c>application_opt()</c></tag>
+<item>
+
+<p>
+Options defining a Diameter application as configured in an
+<c>application</c> option passed to
+<seealso marker="#start_service">start_service/2</seealso>.</p>
+
+<taglist>
+
+<tag><c>{alias, application_alias()}</c></tag>
+<item>
+<p>
+An unique identifier for the application in the scope of the
+service.
+Optional, defaults to the value of the <c>dictionary</c> option.</p>
+</item>
+
+<tag><c>{dictionary, atom()}</c></tag>
+<item>
+<p>
+The name of an encode/decode module for the Diameter
+messages defined by the application.
+These modules are generated from a specification file whose format is
+documented in <seealso
+marker="diameter_dict">diameter_dict(4)</seealso>.</p>
+</item>
+
+<tag><c>{module, application_module()}</c></tag>
+<item>
+<p>
+A callback module with which messages of the Diameter application are
+handled.
+See <seealso marker="diameter_app">diameter_app(3)</seealso> for
+information on the required interface and semantics.</p>
+</item>
+
+<tag><c>{state, term()}</c></tag>
+<item>
+<p>
+The initial callback state.
+Defaults to the value of the <c>alias</c> option if unspecified.
+The prevailing state is passed to certain
+<seealso marker="diameter_app">diameter_app(3)</seealso>
+callbacks, which can then return a new state.</p>
+</item>
+
+<tag><c>{call_mutates_state, true|false}</c></tag>
+<item>
+<p>
+Specifies whether or not the <seealso
+marker="diameter_app#pick_peer">pick_peer/4</seealso>
+application callback (following from a call to
+<seealso marker="#call">call/4</seealso>)
+can modifiy state,
+Defaults to <c>false</c> if unspecified.</p>
+
+<p>
+Note that <seealso
+marker="diameter_app#pick_peer">pick_peer</seealso> callbacks are
+serialized when these are allowed to modify state, which is a
+potential performance bottleneck.
+A simple Diameter client may suffer no ill effects from using mutable
+state but a server or agent that responds to incoming request but
+sending its own requests should probably avoid it.</p>
+</item>
+
+<tag><c>{answer_errors, callback|report|discard}</c></tag>
+<item>
+<p>
+Determines the manner in which incoming answer messages containing
+decode errors are handled.
+If <c>callback</c> then errors result in a <seealso
+marker="diameter_app#handle_answer">handle_answer/4</seealso>
+callback in the same fashion as for <seealso
+marker="diameter_app#handle_request">handle_request/3</seealso>, in the
+<c>errors</c> field of the <c>diameter_packet</c> record passed into
+the callback.
+If <c>report</c> then an answer containing errors is discarded
+without a callback and a warning report is written to the log.
+If <c>discard</c> then an answer containing errors is silently
+discarded without a callback.
+In both the <c>report</c> and <c>discard</c> cases the return value
+for the <seealso marker="#call">call/4</seealso> invocation in
+question is as if a callback had taken place and returned
+<c>{error, failure}</c>.</p>
+
+<p>
+Defaults to <c>report</c> if unspecified.</p>
+</item>
+
+</taglist>
+
+<marker id="call_opt"/>
+</item>
+
+<tag><c>call_opt()</c></tag>
+<item>
+
+<p>
+Options available to <seealso marker="#call">call/4</seealso> when
+sending an outgoing Diameter request.</p>
+
+<taglist>
+
+<tag><c>{extra, list()}</c></tag>
+<item>
+<p>
+Extra arguments to append to callbacks to the callback
+module in question.
+These are appended to any extra arguments configured with the callback
+itself.
+Multiple options append to the argument list.</p>
+</item>
+
+<tag><c>{filter, peer_filter()}</c></tag>
+<item>
+<p>
+A filter to apply to the list of available peers before passing them to
+the <seealso marker="diameter_app#pick_peer">pick_peer/4</seealso>
+callback for the application in question.
+Multiple options are equivalent a single <c>all</c> filter on the
+corresponding list of filters.
+Defaults to <c>none</c>.</p>
+</item>
+
+<tag><c>{timeout, Unsigned32()}</c></tag>
+<item>
+<p>
+The number of milliseconds after which the request should
+timeout.
+Defaults to 5000.</p>
+</item>
+
+<tag><c>detach</c></tag>
+<item>
+<p>
+Causes <seealso marker="#call">call/4</seealso> to return <c>ok</c> as
+soon as the request in
+question has been encoded instead of waiting for and returning
+the result from a subsequent
+<seealso marker="diameter_app#handle_answer">handle_answer/4</seealso>
+or <seealso
+marker="diameter_app#handle_error">handle_error/4</seealso>
+callback.</p>
+</item>
+
+</taglist>
+
+<p>
+An invalid option will cause <seealso marker="#call">call/4</seealso>
+to fail.</p>
+
+<marker id="capability"/>
+</item>
+
+<tag><c>capability()</c></tag>
+<item>
+
+<p>
+AVP values used in outgoing CER/CEA messages during capabilities exchange.
+Can be configured both on a service and a transport, the latter taking
+precedence over the former.</p>
+
+<taglist>
+
+<tag><c>{'Origin-Host', DiameterIdentity()}</c></tag>
+<item>
+<p>
+Value of the Origin-Host AVP in outgoing messages.</p>
+</item>
+
+<tag><c>{'Origin-Realm', DiameterIdentity()}</c></tag>
+<item>
+<p>
+Value of the Origin-Realm AVP in outgoing messages.</p>
+</item>
+
+<tag><c>{'Host-IP-Address', [Address()]}</c></tag>
+<item>
+<p>
+Values of Host-IP-Address AVPs.
+Optional.</p>
+
+<p>
+The list of addresses is available to the start function of a
+transport module, which either uses them as is or returns a new list
+(typically as configured as <c>transport_config()</c> on the
+transport module in question) in order for the correct list of
+addresses to be sent in capabilities exchange messages.</p>
+</item>
+
+<tag><c>{'Vendor-Id', Unsigned32()}</c></tag>
+<item>
+<p>
+Value of the Vendor-Id AVP sent in an outgoing capabilities
+exchange message.</p>
+</item>
+
+<tag><c>{'Product-Name', UTF8String()}</c></tag>
+<item>
+<p>
+Value of the Product-Name AVP sent in an outgoing capabilities
+exchange message.</p>
+</item>
+
+<tag><c>{'Origin-State-Id', Unsigned32()}</c></tag>
+<item>
+<p>
+Value of Origin-State-Id to be included in outgoing messages sent by
+diameter itself.
+In particular, the AVP will be included in CER/CEA and DWR/DWA messages.
+Optional.</p>
+
+<p>
+Setting a value of <c>0</c> (zero) is equivalent to not setting a
+value as documented in RFC 3588.
+The function <seealso
+marker="#origin_state_id">origin_state_id/0</seealso>
+can be used as to retrieve a value that is set when the diameter
+application is started.</p>
+</item>
+
+<tag><c>{'Supported-Vendor-Id', [Unsigned32()]}</c></tag>
+<item>
+<p>
+Values of Supported-Vendor-Id AVPs sent in an outgoing
+capabilities exchange message.
+Optional, defaults to the empty list.</p>
+</item>
+
+<tag><c>{'Auth-Application-Id', [Unsigned32()]}</c></tag>
+<item>
+<p>
+Values of Auth-Application-Id AVPs sent in an outgoing
+capabilities exchange message.
+Optional, defaults to the empty list.</p>
+</item>
+
+<tag><c>{'Inband-Security-Id', [Unsigned32()]}</c></tag>
+<item>
+<p>
+Values of Inband-Security-Id AVPs sent in an outgoing
+capabilities exchange message.
+Optional, defaults to the empty list, which is equivalent to a
+list containing only 0 (= NO_INBAND_SECURITY).</p>
+
+<p>
+If 1 (= TLS) is specified then TLS is selected if the CER/CEA received
+from the peer offers it.</p>
+</item>
+
+<tag><c>{'Acct-Application-Id', [Unsigned32()]}</c></tag>
+<item>
+<p>
+Values of Acct-Application-Id AVPs sent in an outgoing
+capabilities exchange message.
+Optional, defaults to the empty list.</p>
+</item>
+
+<tag><c>{'Vendor-Specific-Application-Id', [Grouped()]}</c></tag>
+<item>
+<p>
+Values of Vendor-Specific-Application-Id AVPs sent in
+an outgoing capabilities exchange message.
+Optional, defaults to the empty list.</p>
+</item>
+
+<tag><c>{'Firmware-Revision', Unsigned32()}</c></tag>
+<item>
+<p>
+Value of the Firmware-Revision AVP sent in an outgoing capabilities
+exchange message.
+Optional.</p>
+</item>
+
+</taglist>
+
+<p>
+Note that each tuple communicates one or more AVP values.
+It is an error to specify duplicate tuples.</p>
+
+<marker id="evaluable"/>
+</item>
+
+<tag><c>evaluable() = {M,F,A} | fun() | [evaluable() | A]</c></tag>
+<item>
+<p>
+An expression that can be evaluated as a function in the following
+sense.</p>
+
+<code>
+eval([{M,F,A} | T]) ->
+ apply(M, F, T ++ A);
+eval([[F|A] | T]) ->
+ eval([F | T ++ A]);
+eval([F|A]) ->
+ apply(F, A);
+eval(F) ->
+ eval([F]).
+</code>
+
+<p>
+Evaluating an evaluable() <c>E</c> on an argument list <c>A</c>
+is meant in the sense of <c>eval([E|A])</c>.</p>
+
+<p>
+Beware of using local funs (that is, fun expressions not of the
+form <c>fun Module:Name/Arity</c>) in situations in which the fun is
+not short-lived and code is to be upgraded at runtime since any
+processes retaining such a fun will have a reference to old code.</p>
+
+<marker id="peer_filter"/>
+</item>
+
+<tag><c>peer_filter() = term()</c></tag>
+<item>
+<p>
+A filter passed to <seealso marker="#call">call/4</seealso>
+in order to select candidate peers for a
+<seealso marker="diameter_app#pick_peer">pick_peer/4</seealso>
+callback.
+Has one of the following types.</p>
+
+<taglist>
+
+<tag><c>none</c></tag>
+<item>
+<p>
+Matches any peer.
+This is a convenience that provides a filter equivalent to no
+filter at all.</p>
+</item>
+
+<tag><c>host</c></tag>
+<item>
+<p>
+Matches only those peers whose <c>Origin-Host</c> has the same value
+as <c>Destination-Host</c> in the outgoing request in question,
+or any peer if the request does not contain
+a <c>Destination-Host</c> AVP.</p>
+</item>
+
+<tag><c>realm</c></tag>
+<item>
+<p>
+Matches only those peers whose <c>Origin-Realm</c> has the same value
+as <c>Destination-Realm</c> in the outgoing request in question,
+or any peer if the request does not contain
+a <c>Destination-Realm</c> AVP.</p>
+</item>
+
+<tag><c>{host, any|DiameterIdentity()}</c></tag>
+<item>
+<p>
+Matches only those peers whose <c>Origin-Host</c> has the
+specified value, or all peers if the atom <c>any</c>.</p>
+</item>
+
+<tag><c>{realm, any|DiameterIdentity()</c></tag>
+<item>
+<p>
+Matches only those peers whose <c>Origin-Realm</c> has the
+value, or all peers if the atom <c>any</c>.</p>
+</item>
+
+<tag><c>{eval, evaluable()}</c></tag>
+<item>
+<p>
+Matches only those peers for which the specified evaluable() returns
+<c>true</c> on the connection's <c>diameter_caps</c> record.
+Any other return value or exception is equivalent to <c>false</c>.</p>
+</item>
+
+<tag><c>{neg, peer_filter()}</c></tag>
+<item>
+<p>
+Matches only those peers not matched by the specified filter.</p>
+</item>
+
+<tag><c>{all, [peer_filter()]}</c></tag>
+<item>
+<p>
+Matches only those peers matched by each filter of the specified list.</p>
+</item>
+
+<tag><c>{any, [peer_filter()]}</c></tag>
+<item>
+<p>
+Matches only those peers matched by at least one filter of the
+specified list.</p>
+</item>
+
+</taglist>
+
+<p>
+Note that the <c>host</c> and <c>realm</c> filters examine the
+outgoing request as passed to <seealso marker="#call">call/4</seealso>,
+assuming that this is a record- or list-valued message() as documented
+in <seealso marker="diameter_app">diameter_app(3)</seealso>, and that
+the message contains at most one of each AVP.
+If this is not the case then the <c>{host|realm, DiameterIdentity()}</c>
+filters must be used to achieve the desired result.
+Note also that an empty host/realm (which should not be typical)
+is equivalent to an unspecified one for the purposes of filtering.</p>
+
+<p>
+An invalid filter is equivalent to <c>{any, []}</c>, a filter
+that matches no peer.</p>
+
+<marker id="service_event"/>
+</item>
+
+<tag><c>service_event() = #diameter_event{}</c></tag>
+<item>
+<p>
+Event message sent to processes that have subscribed using <seealso
+marker="#subscribe">subscribe/1</seealso>.</p>
+
+<p>
+The <c>info</c> field of the event record can be one of the
+following.</p>
+
+<taglist>
+
+<tag><c>{up, Ref, Peer, Config, Pkt}</c></tag>
+<tag><c>{up, Ref, Peer, Config}</c></tag>
+<tag><c>{down, Ref, Peer, Config}</c></tag>
+<item>
+<code>
+Ref = transport_ref()
+Peer = diameter_app:peer()
+Config = {connect|listen, [transport_opt()]}
+Pkt = #diameter_packet{}
+</code>
+
+<p>
+Reports that the RFC 3539 watchdog state machine has
+transitioned into (<c>up</c>) or out of (<c>down</c>) the open
+state.
+If a <c>diameter_packet</c> record is present in an <c>up</c> tuple
+then there has been an exchange of capabilities exchange messages and
+the record contains the received CER or CEA, otherwise the
+connection has reestablished without the loss or transport
+connectivity.</p>
+
+<p>
+Note that a single up/down event for a given peer corresponds to
+as many peer_up/down callbacks as there are Diameter
+applications shared by the peer, as determined during capablilities
+exchange.
+That is, the event communicates connectivity with the
+peer as a whole while the callbacks communicate connectivity with
+respect to individual Diameter applications.</p>
+</item>
+
+<tag><c>{reconnect, Ref, Opts}</c></tag>
+<item>
+<code>
+Ref = transport_ref()
+Opts = [transport_opt()]
+</code>
+
+<p>
+A connecting transport is attempting to establish/reestablish a
+transport connection with a peer following <c>reconnect_timer</c> or
+<c>watchdog_timer</c> expiry.</p>
+</item>
+
+</taglist>
+
+<p>
+For forward compatibility, a subscriber should be prepared to receive
+<c>diameter_event.info</c> of forms other than those documented
+above.</p>
+
+<marker id="service_name"/>
+</item>
+
+<tag><c>service_name() = term()</c></tag>
+<item>
+<p>
+The name of a service as passed to <seealso
+marker="#start_service">start_service/2</seealso> and with which the
+service is identified.
+There can be at most one service with a given name on a given node.
+Note that <c>erlang:make_ref/0</c> can be used to generate a service name
+that is somewhat unique.</p>
+
+<marker id="service_opt"/>
+</item>
+
+<tag><c>service_opt()</c></tag>
+<item>
+<p>
+Options accepted by <seealso
+marker="#start_service">start_service/2</seealso>.
+Can be any <c>capability()</c> tuple as
+well as the following.</p>
+
+<taglist>
+
+<tag><c>{application, [application_opt()]}</c></tag>
+<item>
+<p>
+Defines a Diameter application supported by the service.</p>
+
+<p>
+A service must define one application for each Diameter application it
+intends to support.
+For an outgoing Diameter request, the application is specified by
+passing the desired application's <c>application_alias()</c> to
+<seealso marker="#call">call/4</seealso>, while for an
+incoming request the application identifier in the message
+header determines the application (and callback module), the
+application identifier being specified in the <seealso
+marker="diameter_dict">dictionary</seealso> file defining the
+application.</p>
+</item>
+
+</taglist>
+
+<marker id="transport_opt"/>
+</item>
+
+<tag><c>transport_opt()</c></tag>
+<item>
+<p>
+Options accepted by <seealso
+marker="#add_transport">add_transport/2</seealso>.</p>
+
+<taglist>
+<tag><c>{transport_module, atom()}</c></tag>
+<item>
+<p>
+A module implementing a transport process as defined in <seealso
+marker="diameter_transport">diameter_transport(3)</seealso>.
+Defaults to <c>diameter_tcp</c> if unspecified.</p>
+
+<p>
+The interface required of a transport module is documented in <seealso
+marker="diameter_transport">diameter_transport(3)</seealso>.</p>
+</item>
+
+<tag><c>{transport_config, term()}</c></tag>
+<item>
+<p>
+A term passed as the third argument to the <seealso
+marker="diameter_transport#start">start/3</seealso> function of
+the relevant <c>transport_module</c> in order to start a transport process.
+Defaults to the empty list if unspecified.</p>
+</item>
+
+<tag><c>{applications, [application_alias()]}</c></tag>
+<item>
+<p>
+The list of Diameter applications to which usage of the transport
+should be restricted.
+Defaults to all applications configured on the service
+in question.</p>
+</item>
+
+<tag><c>{capabilities, [capability()]}</c></tag>
+<item>
+<p>
+AVP's used to construct outgoing CER/CEA messages.
+Any AVP specified takes precedence over a corresponding value specified
+for the service in question.</p>
+
+<p>
+Specifying a capability as a transport option
+may be particularly appropriate for Inband-Security-Id in case
+TLS is desired over TCP as implemented by
+<seealso marker="diameter_tcp">diameter_tcp(3)</seealso> but
+not over SCTP as implemented by
+<seealso marker="diameter_sctp">diameter_sctp(3)</seealso>.</p>
+</item>
+
+<tag><c>{watchdog_timer, TwInit}</c></tag>
+<item>
+<code>
+TwInit = Unsigned32()
+ | {M,F,A}
+</code>
+
+<p>
+The RFC 3539 watchdog timer.
+An integer value is interpreted as the RFC's TwInit in milliseconds,
+a jitter of &plusmn; 2 seconds being added at each rearming of the
+timer to compute the RFC's Tw.
+An MFA is expected to return the RFC's Tw directly, with jitter
+applied, allowing the jitter calculation to be performed by
+the callback.</p>
+
+<p>
+An integer value must be at least 6000 as required by RFC 3539.
+Defaults to 30000 if unspecified.</p>
+</item>
+
+<tag><c>{reconnect_timer, Tc}</c></tag>
+<item>
+<code>
+Tc = Unsigned32()
+</code>
+
+<p>
+For a connecting transport, the RFC 3588 Tc timer, in milliseconds.
+Note that this timer determines the frequency with which the transport
+will attempt to establish a connection with its peer only <em>before</em>
+an initial connection is established: once there is an initial
+connection it's watchdog_timer that determines the frequency of
+reconnection attempts, as required by RFC 3539.</p>
+
+<p>
+For a listening transport, the timer specifies the time after which a
+previously connected peer will be forgotten: a connection after this time is
+regarded as an initial connection rather than a reestablishment,
+causing the RFC 3539 state machine to pass to state OPEN rather than
+REOPEN.
+Note that these semantics are not goverened by the RFC and
+that a listening transport's reconnect_timer should be greater than its
+peers's Tc plus jitter.</p>
+
+<p>
+Defaults to 30000 for a connecting transport and 60000 for a listening
+transport.</p>
+</item>
+
+</taglist>
+
+<p>
+Unrecognized options are silently ignored but are returned unmodified
+by <seealso
+marker="#service_info">service_info/2</seealso> and can be referred to
+in predicate functions passed to <seealso
+marker="#remove_transport">remove_transport/2</seealso>.</p>
+
+</item>
+
+</taglist>
+
+</section>
+
+<marker id="add_transport"/>
+<funcs>
+
+<!-- ===================================================================== -->
+
+<func>
+<name>add_transport(SvcName, {connect|listen, Options})
+ -> {ok, Ref} | {error, Reason}</name>
+<fsummary>Add transport capability to a service.</fsummary>
+<type>
+<v>SvcName = service_name()</v>
+<v>Options = [transport_opt()]</v>
+<v>Ref = ref()</v>
+<v>Reason = term()</v>
+</type>
+<desc>
+<p>
+Add transport capability to a service.</p>
+
+<p>
+The service will start a transport process(es) in order to establish a
+connection with the peer, either by connecting to the peer
+(<c>connect</c>) or by accepting incoming connection requests
+(<c>listen</c>).
+A connecting transport establishes transport connections with at most
+one peer, an listening transport potentially with many.</p>
+
+<p>
+The diameter application takes responsibility for exchanging
+CER/CEA with the peer.
+Upon successful completion of capabilities exchange the service
+calls each relevant application module's <seealso
+marker="diameter_app#peer_up">peer_up/3</seealso> callback
+after which the caller can exchange Diameter messages with the peer over
+the transport.
+In addition to CER/CEA, the service takes responsibility for the
+handling of DWR/DWA and required by RFC 3539 as well as for DPR/DPA.</p>
+
+<p>
+The returned reference uniquely identifies the transport within the
+scope of the service.
+Note that the function returns before a transport connection has been
+established.
+It is not an error to add a transport to a service that has not yet
+been configured: a service can be started after configuring
+transports.</p>
+
+<marker id="call"/>
+</desc>
+</func>
+
+<!-- ===================================================================== -->
+
+<func>
+<name>call(SvcName, App, Request, Options) -> ok | Answer | {error, Reason}</name>
+<fsummary>Send a Diameter request message.</fsummary>
+<type>
+<v>SvcName = service_name()</v>
+<v>App = application_alias()</v>
+<v>Request = diameter_app:message() | term()</v>
+<v>Answer = term()</v>
+<v>Options = [call_opt()]</v>
+</type>
+<desc>
+<p>
+Send a Diameter request message and possibly return the answer or error.</p>
+
+<p>
+<c>App</c> identifies the Diameter application in which the request is
+defined and callbacks to the corresponding callback module
+will follow as described below and in <seealso
+marker="diameter_app">diameter_app(3)</seealso>.
+Unless the <c>detach</c> option has been specified to cause an earlier
+return, the call returns either when an answer message is received
+from the peer or an error occurs.
+In the case of an answer, the return value is as returned by a
+<seealso
+marker="diameter_app#handle_answer">handle_answer/4</seealso>
+callback.
+In the case of an error, whether or not the error is returned directly
+by diameter or from a <seealso
+marker="diameter_app#handle_error">handle_error/4</seealso>
+callback depends on whether or not the outgoing request is
+successfully encoded for transmission from the peer, the cases being
+documented below.</p>
+
+<p>
+If there are no suitable peers, or if
+<seealso marker="diameter_app#pick_peer">pick_peer/4</seealso>
+rejects them by returning 'false', then <c>{error, no_connection}</c>
+is returned.
+Otherwise <seealso marker="diameter_app#pick_peer">pick_peer/4</seealso>
+is followed by a
+<seealso
+marker="diameter_app#prepare_request">prepare_request/3</seealso>
+callback, the message is encoded and sent.</p>
+
+<p>
+There are several error cases which may prevent an
+answer from being received and passed to a
+<seealso marker="diameter_app#handle_answer">handle_answer/4</seealso>
+callback:</p>
+
+<list>
+
+<item>
+<p>
+If the initial encode of the outgoing request
+fails, then the request process fails and <c>{error, encode}</c>
+is returned.</p>
+</item>
+
+<item>
+<p>
+If the request is successfully encoded and sent but
+the answer times out then a
+<seealso marker="diameter_app#handle_error">handle_error/4</seealso>
+callback takes place with <c>Reason = timeout</c>.</p>
+</item>
+
+<item>
+<p>
+If the request is successfully encoded and sent but the service in
+question is stopped before an answer is received then a
+<seealso marker="diameter_app#handle_error">handle_error/4</seealso>
+callback takes place <c>Reason = cancel</c>.</p>
+</item>
+
+<item>
+<p>
+If the transport connection with the peer goes down after the request
+has been sent but before an answer has been received then an attempt
+is made to resend the request to an alternate peer.
+If no such peer is available, or if the subsequent
+<seealso marker="diameter_app#pick_peer">pick_peer/4</seealso>
+callback rejects the candidates, then a
+<seealso marker="diameter_app#handle_error">handle_error/4</seealso>
+callback takes place with <c>Reason = failover</c>.
+If a peer is selected then a
+<seealso
+marker="diameter_app#prepare_retransmit">prepare_retransmit/3</seealso>
+callback takes place, after which the semantics are the same as
+following an initial
+<seealso marker="diameter_app#prepare_request">
+prepare_request/3</seealso>
+callback.</p>
+</item>
+
+<item>
+<p>
+If an encode error takes place during
+retransmission then the request process fails and
+<c>{error, failure}</c> is returned.</p>
+</item>
+
+<item>
+<p>
+If an application callback made in processing the request fails
+(pick_peer, prepare_request, prepare_retransmit,
+handle_answer or handle_error) then either
+<c>{error, encode}</c> or <c>{error, failure}</c>
+is returned depending on whether or not there has been an
+attempt to send the request over the transport.</p>
+</item>
+
+</list>
+
+<p>
+Note that <c>{error, encode}</c> is the only return value which
+guarantees that the request has <em>not</em> been sent over the
+transport.</p>
+
+<marker id="origin_state_id"/>
+</desc>
+</func>
+
+<!-- ===================================================================== -->
+
+<func>
+<name>origin_state_id() -> Unsigned32()</name>
+<fsummary>Returns a reasonable Origin-State-Id.</fsummary>
+<desc>
+<p>
+Return a reasonable value for use as Origin-State-Id in
+outgoing messages.</p>
+
+<p>
+The value returned is the number of seconds since 19680120T031408Z,
+the first value that can be encoded as a Diameter Time(),
+at the time the diameter application was started.</p>
+
+<marker id="remove_transport"/>
+</desc>
+</func>
+
+<!-- ===================================================================== -->
+
+<func>
+<name>remove_transport(SvcName, Pred) -> ok</name>
+<fsummary>Remove previously added transports.</fsummary>
+<type>
+<v>SvcName = service_name()</v>
+<v>Pred = Fun | MFA | ref() | list() | true | false</v>
+<v></v>
+<v>Fun = fun((reference(), connect|listen, list()) -> boolean())</v>
+<v>&nbsp;&nbsp;&nbsp; | fun((reference(), list()) -> boolean())</v>
+<v>&nbsp;&nbsp;&nbsp; | fun((list()) -> boolean())</v>
+<v>MFA = {atom(), atom(), list()}</v>
+</type>
+<desc>
+<p>
+Remove previously added transports.</p>
+
+<p>
+<c>Pred</c> determines which transports to remove.
+An arity-3-valued <c>Pred</c> removes all transports for which
+<c>Pred(Ref, Type, Opts)</c> returns <c>true</c>, where <c>Type</c> and
+<c>Opts</c> are as passed to <seealso
+marker="#add_transport">add_transport/2</seealso> and <c>Ref</c> is
+as returned by the corresponding call.
+The remaining forms are equivalent to an arity-3 fun as follows.</p>
+
+<code>
+Pred = fun(reference(), list()): fun(Ref, _, Opts) -> Pred(Ref, Opts) end
+Pred = fun(list()): fun(_, _, Opts) -> Pred(Opts) end
+Pred = reference(): fun(Ref, _, _) -> Pred == Ref end
+Pred = list(): fun(_, _, Opts) -> [] == Pred -- Opts end
+Pred = true: fun(_, _, _) -> true end
+Pred = false: fun(_, _, _) -> false end
+Pred = {M,F,A}: fun(Ref, Type, Opts) -> apply(M, F, [Ref, Type, Opts | A]) end
+</code>
+
+<p>
+Removing a transport causes all associated transport connections to
+be broken.
+A base application DPR message with
+Disconnect-Cause <c>DO_NOT_WANT_TO_TALK_TO_YOU</c> will be sent
+to each connected peer before disassociating the transport configuration
+from the service and terminating the transport upon reception of
+DPA or timeout.</p>
+
+<!-- TODO: document the timeout value, possibly make configurable. -->
+
+<marker id="service_info"/>
+</desc>
+</func>
+
+<!-- ===================================================================== -->
+
+<func>
+<name>service_info(SvcName, Item) -> Value</name>
+<fsummary>Return specific information about a started service.</fsummary>
+<type>
+<v>SvcName = service_name()</v>
+<v>Value = term()</v>
+</type>
+<desc>
+<p>
+Return information about a started service.</p>
+
+<marker id="services"/>
+</desc>
+</func>
+
+<!-- ===================================================================== -->
+
+<func>
+<name>services() -> [SvcName]</name>
+<fsummary>Return the list of started services.</fsummary>
+<type>
+<v>SvcName = service_name()</v>
+</type>
+<desc>
+<p>
+Return the list of started services.</p>
+
+<marker id="session_id"/>
+</desc>
+</func>
+
+<!-- ===================================================================== -->
+
+<func>
+<name>session_id(Ident) -> OctetString()</name>
+<fsummary>Return a value for a Session-Id AVP.</fsummary>
+<type>
+<v>Ident = DiameterIdentity()</v>
+</type>
+<desc>
+<p>
+Return a value for a Session-Id AVP.</p>
+
+<p>
+The value has the form required by section 8.8 of RFC 3588.
+Ident should be the Origin-Host of the peer from which
+the message containing the returned value will be sent.</p>
+
+<marker id="start"/>
+</desc>
+</func>
+
+<!-- ===================================================================== -->
+<func>
+<name>start() -> ok | {error, Reason}</name>
+<fsummary>Start the diameter application.</fsummary>
+<desc>
+<p>
+Start the diameter application.</p>
+
+<p>
+The diameter application must be started before starting a service.
+In a production system this will typically be accomplished by a boot
+file, not by calling <c>start/0</c> explicitly.</p>
+
+<marker id="start_service"/>
+</desc>
+</func>
+
+<!-- ===================================================================== -->
+<func>
+<name>start_service(SvcName, Options) -> ok | {error, Reason}</name>
+<fsummary>Start a Diameter service.</fsummary>
+<type>
+<v>SvcName = service_name()</v>
+<v>Options = [service_opt()]</v>
+<v>Reason = term()</v>
+</type>
+<desc>
+<p>
+Start a diameter service.</p>
+
+<p>
+A service defines a locally-implemented Diameter peer, specifying the
+capabilities of the peer to be used during capabilities exchange and
+the Diameter applications that it supports.
+Transports are added to a service using <seealso
+marker="#add_transport">add_transport/2</seealso>.</p>
+
+<marker id="stop_service"/>
+</desc>
+</func>
+
+<!-- ===================================================================== -->
+<func>
+<name>stop() -> ok | {error, Reason}</name>
+<fsummary>Stop the diameter application.</fsummary>
+<desc>
+<p>
+Stop the diameter application.</p>
+
+<p>
+</p>
+
+<marker id="stop_service"/>
+</desc>
+</func>
+
+<!-- ===================================================================== -->
+<func>
+<name>stop_service(SvcName) -> ok | {error, Reason}</name>
+<fsummary>Stop a Diameter service.</fsummary>
+<type>
+<v>SvcName = service_name()</v>
+<v>Reason = term()</v>
+</type>
+<desc>
+<p>
+Stop a diameter service.</p>
+
+<marker id="subscribe"/>
+</desc>
+</func>
+
+<!-- ===================================================================== -->
+
+<func>
+<name>subscribe(SvcName) -> true</name>
+<fsummary>Subscribe to event messages.</fsummary>
+<type>
+<v>SvcName = service_name()</v>
+</type>
+<desc>
+<p>
+Subscribe to <c>service_event()</c> messages from a service.</p>
+
+<p>
+It is not an error to subscribe to events from a service
+that does not yet exist.</p>
+
+<marker id="unsubscribe"/>
+</desc>
+</func>
+
+<!-- ===================================================================== -->
+
+<func>
+<name>unsubscribe(SvcName) -> true</name>
+<fsummary>Unsubscribe to event messages.</fsummary>
+<type>
+<v>SvcName = service_name()</v>
+</type>
+<desc>
+<p>
+Unsubscribe to event messages from a service.</p>
+
+</desc>
+</func>
+
+</funcs>
+
+<!-- ===================================================================== -->
+<!-- ===================================================================== -->
+<section>
+<title>SEE ALSO</title>
+
+<p>
+<seealso marker="diameter_app">diameter_app(3)</seealso>,
+<seealso marker="diameter_transport">diameter_transport(3)</seealso>,
+<seealso marker="diameter_dict">diameter_dict(4)</seealso></p>
+
+</section>
+
+</erlref>
diff --git a/lib/diameter/doc/src/diameter_app.xml b/lib/diameter/doc/src/diameter_app.xml
new file mode 100644
index 0000000000..a9ae0ebbec
--- /dev/null
+++ b/lib/diameter/doc/src/diameter_app.xml
@@ -0,0 +1,615 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+<header>
+
+<copyright>
+<year>2011</year>
+<holder>Ericsson AB. All Rights Reserved.</holder>
+</copyright>
+<legalnotice>
+The contents of this file are subject to the Erlang Public License,
+Version 1.1, (the "License"); you may not use this file except in
+compliance with the License. You should have received a copy of the
+Erlang Public License along with this software. If not, it can be
+retrieved online at http://www.erlang.org/.
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+the License for the specific language governing rights and limitations
+under the License.
+
+</legalnotice>
+
+<title>diameter_app(3)</title>
+<prepared>Anders Svensson</prepared>
+<responsible></responsible>
+<docno></docno>
+<approved></approved>
+<checked></checked>
+<date></date>
+<rev>%REV%</rev>
+<file>diameter_app.xml</file>
+
+</header>
+
+<module>diameter_app</module>
+<modulesummary>
+Callback module of a Diameter application.</modulesummary>
+
+<description>
+
+<p>
+A diameter service as started by <seealso
+marker="diameter#start_service">diameter:start_service/2</seealso>
+configures one of more Diameter applications, each of whose
+configuration specifies a callback that handles messages specific to
+its application.
+The messages and AVPs of the Diameter application are defined in a
+dictionary file whose format is documented in
+<seealso marker="diameter_dict">diameter_dict(4)</seealso>
+while the callback module is documented here.
+The callback module implements the Diameter application-specific
+functionality of a service.</p>
+
+<p>
+A callback module must export all of the functions documented below.
+The functions themselves are of three distinct flavours:</p>
+
+<list>
+<item>
+<p>
+<seealso marker="#peer_up">peer_up/3</seealso> and
+<seealso marker="#peer_down">peer_down/3</seealso> signal the
+attainment or loss of connectivity with a Diameter peer.</p>
+</item>
+
+<item>
+<p>
+<seealso marker="#pick_peer">pick_peer/4</seealso>,
+<seealso marker="#prepare_request">prepare_request/3</seealso>,
+<seealso marker="#prepare_retransmit">prepare_retransmit/3</seealso>,
+<seealso marker="#handle_answer">handle_answer/4</seealso>
+and <seealso marker="#handle_error">handle_error/4</seealso> are (or may
+be) called as a consequence of a call to <seealso
+marker="diameter#call">diameter:call/4</seealso> to send an outgoing
+Diameter request message.</p>
+</item>
+
+<item>
+<p>
+<seealso marker="#handle_request">handle_request/3</seealso>
+is called in response to an incoming Diameter request message.</p>
+</item>
+
+</list>
+
+</description>
+
+<note>
+<p>
+The arities given for the the callback functions here assume no extra
+arguments.
+All functions will also be passed any extra arguments configured with
+the callback module itself when calling <seealso
+marker="diameter#start_service">diameter:start_service/2</seealso>
+and, for the call-specific callbacks, any extra arguments passed to
+<seealso marker="diameter#call">diameter:call/4</seealso>.</p>
+</note>
+
+<!-- ===================================================================== -->
+<!-- ===================================================================== -->
+
+<section>
+<title>DATA TYPES</title>
+
+<taglist>
+
+<tag><c>capabilities() = #diameter_caps{}</c></tag>
+<item>
+<p>
+A record containing the identities of
+the local and remote Diameter peers having an established transport
+connection, as well as the capabilities as
+determined by capabilities exchange.
+Each field of the record is a 2-tuple consisting of
+values for the (local) host and (remote) peer.
+Optional or possibly multiple values are encoded as lists of values,
+mandatory values as the bare value.</p>
+</item>
+
+<tag><c>message() = record() | list()</c></tag>
+<item>
+<p>
+The representation of a Diameter message as passed to
+<seealso marker="diameter#call">diameter:call/4</seealso>.
+The record representation is as outlined in
+<seealso
+marker="diameter_dict#MESSAGE_RECORDS">diameter_dict(4)</seealso>:
+a message as defined in a dictionary file is encoded as a record with
+one field for each component AVP.
+Equivalently, a message can also be encoded as a list whose head is
+the atom-valued message name (the record name minus any
+prefix specified in the relevant dictionary file) and whose tail is a
+list of <c>{FieldName, FieldValue}</c> pairs.</p>
+
+<p>
+A third representation allows a message to be specified as a list
+whose head is a <c>diameter_header</c> record and whose tail is a list
+of <c>diameter_avp</c> records.
+This representation is used by diameter itself when relaying requests
+as directed by the return value of a
+<seealso marker="#handle_request">handle_request/3</seealso>
+callback.
+It differs from the other other two in that it bypasses the checks for
+messages that do not agree with their definitions in the dictionary in
+question (since relays agents must handle arbitrary request): messages
+are sent exactly as specified.</p>
+
+</item>
+
+<tag><c>packet() = #diameter_packet{}</c></tag>
+<item>
+<p>
+A container for incoming and outgoing Diameters message that's passed
+through encode/decode and transport.
+Fields of a packet() record should not be set in return values except
+as documented.</p>
+</item>
+
+<tag><c>peer_ref() = term()</c></tag>
+<item>
+<p>
+A term identifying a transport connection with a Diameter peer.
+Should be treated opaquely.</p>
+</item>
+
+<tag><c>peer() = {peer_ref(), capabilities()}</c></tag>
+<item>
+<p>
+A tuple representing a Diameter peer connection.</p>
+</item>
+
+<tag><c>service_name() = term()</c></tag>
+<item>
+<p>
+The service supporting the Diameter application.
+Specified to <seealso
+marker="diameter#start_service">diameter:start_service/2</seealso>
+when starting the service.</p>
+</item>
+
+<tag><c>state() = term()</c></tag>
+<item>
+<p>
+The state maintained by the application callback functions
+<seealso marker="#peer_up">peer_up/3</seealso>,
+<seealso marker="#peer_down">peer_down/3</seealso> and (optionally)
+<seealso marker="#pick_peer">pick_peer/4</seealso>.
+The initial state is configured in the call to
+<seealso
+marker="diameter#start_service">diameter:start_service/2</seealso>
+that configures the application on a service.
+Callback functions returning a state are evaluated in a common
+service-specific process while
+those not returning state are evaluated in a request-specific
+process.</p>
+</item>
+
+</taglist>
+
+<marker id="peer_up"/>
+</section>
+
+<!-- ===================================================================== -->
+<!-- ===================================================================== -->
+
+<funcs>
+
+<func>
+<name>Mod:peer_up(SvcName, Peer, State) -> NewState</name>
+<fsummary>Invoked when a transport connection has been established</fsummary>
+<type>
+<v>SvcName = service_name()</v>
+<v>Peer = peer()</v>
+<v>State = NewState = state()</v>
+</type>
+<desc>
+<p>
+Invoked when a transport connection has been established
+and a successful capabilities exchange has indicated that the peer
+supports the Diameter application of the application on which
+the callback module in question has been configured.</p>
+
+<marker id="peer_down"/>
+</desc>
+</func>
+
+<func>
+<name>Mod:peer_down(SvcName, Peer, State) -> NewState</name>
+<fsummary>Invoked when a transport connection has been lost.</fsummary>
+<type>
+<v>SvcName = service_name()</v>
+<v>Peer = peer()</v>
+<v>State = NewState = state()</v>
+</type>
+<desc>
+<p>
+Invoked when a transport connection has been lost following a previous
+call to <seealso marker="#peer_up">peer_up/3</seealso>.</p>
+
+<marker id="pick_peer"/>
+</desc>
+</func>
+
+<func>
+<name>Mod:pick_peer(Candidates, Reserved, SvcName, State)
+ -> {ok, Peer} | {Peer, NewState} | false</name>
+<fsummary>Select a target peer for an outgoing request.</fsummary>
+<type>
+<v>Candidates = [peer()]</v>
+<v>Peer = peer() | false</v>
+<v>SvcName = service_name()</v>
+<v>State = NewState = state()</v>
+</type>
+<desc>
+<p>
+Invoked as a consequence of a call to <seealso
+marker="diameter#call">diameter:call/4</seealso> to select a destination
+peer for an outgoing request, the return value indicating the selected peer.
+A new application state can also be returned but only if the Diameter
+application in question was
+configured with the option <c>call_mutates_state</c> set to
+<c>true</c>, as documented for <seealso
+marker="diameter#start_service">diameter:start_service/2</seealso>.</p>
+
+<p>
+The candidate peers list will only include those
+which are selected by any <c>filter</c> option specified in the call to
+<seealso marker="diameter#call">diameter:call/4</seealso>, and only
+those which have indicated support for the Diameter application in
+question.
+The order of the elements is unspecified except that any
+peers whose Origin-Host and Origin-Realm matches that of the
+outgoing request (in the sense of a <c>{filter, {all, [host, realm]}}</c>
+option to <seealso marker="diameter#call">diameter:call/4</seealso>)
+will be placed at the head of the list.</p>
+
+<p>
+The return values <c>false</c> and <c>{false, State}</c> are
+equivalent when callback state is mutable, as are
+<c>{ok, Peer}</c> and <c>{Peer, State}</c>.
+Returning a peer as <c>false</c> causes <c>{error, no_connection}</c>
+to be returned from <seealso marker="diameter#call">diameter:call/4</seealso>.
+Returning a peer() from an initial pick_peer/4 callback will result in a
+<seealso marker="#prepare_request">prepare_request/3</seealso> callback
+followed by either <seealso
+marker="#handle_answer">handle_answer/4</seealso>
+or <seealso marker="#handle_error">handle_error/4</seealso> depending
+on whether or not an answer message is received from the peer.
+If transport with the peer is lost before this then a new <seealso
+marker="#pick_peer">pick_peer/4</seealso> callback takes place to
+select an alternate peer.</p>
+
+<p>
+Note that there is no guarantee that a <seealso
+marker="#pick_peer">pick_peer/4</seealso> callback to select
+an alternate peer will be followed by any additional callbacks, only
+that the initial <seealso
+marker="#pick_peer">pick_peer/4</seealso> will be, since a
+retransmission to an alternate peer is abandoned if an answer is
+received from a previously selected peer.</p>
+
+<marker id="prepare_request"/>
+</desc>
+
+</func>
+
+<func>
+<name>Mod:prepare_request(Packet, SvcName, Peer) -> Action</name>
+<fsummary>Return a request for encoding and transport.</fsummary>
+<type>
+<v>Packet = packet()</v>
+<v>SvcName = service_name()</v>
+<v>Peer = peer()</v>
+<v>Action = {send, packet() | message()} | {discard, Reason} | discard</v>
+</type>
+<desc>
+<p>
+Invoked to return a request for encoding and transport.
+Allows the sender to access the selected peer's capabilities
+in order to set (for example) <c>Destination-Host</c> and/or
+<c>Destination-Realm</c> in the outgoing request, although the
+callback need not be limited to this usage.
+Many implementations may simply want to return <c>{send, Packet}</c></p>
+
+<p>
+A returned packet() should set the request to be encoded in its
+<c>msg</c> field and can set the <c>transport_data</c> field in order
+to pass information to the transport module.
+Extra arguments passed to <seealso
+marker="diameter#call">diameter:call/4</seealso> can be used to
+communicate transport data to the callback.
+A returned packet() can also set the <c>header</c> field to a
+<c>diameter_header</c> record in order to specify values that should
+be preserved in the outgoing request, although this should typically
+not be necessary and allows the callback to set header values
+inappropriately.
+A returned <c>length</c>, <c>cmd_code</c> or <c>application_id</c> is
+ignored.</p>
+
+<p>
+Returning <c>{discard, Reason}</c> causes the request to be aborted
+and the <seealso
+marker="diameter#call">diameter:call/4</seealso> for which the
+callback has taken place to return <c>{error, Reason}</c>.
+Returning <c>discard</c> is equivalent to returning <c>{discard,
+discarded}</c>.</p>
+
+<marker id="prepare_retransmit"/>
+</desc>
+</func>
+
+<func>
+<name>Mod:prepare_retransmit(Packet, SvcName, Peer) -> Result</name>
+<fsummary>Return a request for encoding and retransmission.</fsummary>
+<type>
+<v>Packet = packet()</v>
+<v>SvcName = service_name()</v>
+<v>Peer = peer()</v>
+<v>Result = {send, packet() | message()} | {discard, Reason} | discard</v>
+</type>
+<desc>
+<p>
+Invoked to return a request for encoding and retransmission.
+Has the same role as <seealso
+marker="#prepare_request">prepare_request/3</seealso> in the case that
+a peer connection is lost an an alternate peer selected but the
+argument packet() is as returned by the initial
+<c>prepare_request/3</c>.</p>
+
+<p>
+Returning <c>{discard, Reason}</c> causes the request to be aborted
+and a <seealso
+marker="#handle_error">handle_error/4</seealso> callback to
+take place with <c>Reason</c> as initial argument.
+Returning <c>discard</c> is equivalent to returning <c>{discard,
+discarded}</c>.</p>
+
+<marker id="handle_answer"/>
+</desc>
+</func>
+
+<func>
+<name>Mod:handle_answer(Packet, Request, SvcName, Peer) -> Result</name>
+<fsummary>Receive an answer message from a peer.</fsummary>
+<type>
+<v>Packet = packet()</v>
+<v>Request = message()</v>
+<v>SvcName = service_name()</v>
+<v>Peer = peer()</v>
+<v>Result = term()</v>
+</type>
+<desc>
+<p>
+Invoked when an answer message is received from a peer.
+The return value is returned from the call to <seealso
+marker="diameter#call">diameter:call/4</seealso> for which the
+callback takes place unless the <c>detach</c> option was
+specified.</p>
+
+<p>
+The decoded answer record is in the <c>msg</c> field of the argument
+packet(),
+the undecoded binary in the <c>packet</c> field.
+<c>Request</c> is the outgoing request message as was returned from
+<seealso marker="#prepare_request">prepare_request/3</seealso> or
+<seealso marker="#prepare_retransmit">prepare_retransmit/3</seealso>
+before the request was passed to the transport.</p>
+
+<p>
+For any given call to <seealso
+marker="diameter#call">diameter:call/4</seealso> there is at most one
+call to the handle_answer callback of the application in question: any
+duplicate answer (due to retransmission or otherwise) is discarded.
+Similarly, only one of <c>handle_answer/4</c> or <c>handle_error/4</c> is
+called for any given request.</p>
+
+<p>
+By default, an incoming answer message that cannot be successfully
+decoded causes the request process in question to fail, causing the
+relevant call to <seealso
+marker="diameter#call">diameter:call/4</seealso>
+to return <c>{error, failure} (unless the <c>detach</c> option was
+specified)</c>.
+In particular, there is no <c>handle_error/4</c> callback in this
+case.
+Application configuration may change this behaviour as described for
+<seealso
+marker="diameter#start_service">diameter:start_service/2</seealso>.</p>
+
+<marker id="handle_error"/>
+</desc>
+</func>
+
+<func>
+<name>Mod:handle_error(Reason, Request, SvcName, Peer) -> Result</name>
+<fsummary>Return an error from a outgoing request.</fsummary>
+<type>
+<v>Reason = timeout | failover | term()</v>
+<v>Request = message()</v>
+<v>SvcName = service_name()</v>
+<v>Peer = peer()</v>
+<v>Result = term()</v>
+</type>
+<desc>
+<p>
+Invoked when an error occurs before an answer message is received from
+a peer in response to an outgoing request.
+The return value is returned from the call to <seealso
+marker="diameter#call">diameter:call/4</seealso> for which the
+callback takes place (unless the <c>detach</c> option was
+specified).</p>
+
+<p>
+Reason <c>timeout</c> indicates that an answer message has not been
+received within the required time.
+Reason <c>failover</c> indicates
+that the transport connection to the peer to which the request has
+been sent has been lost but that not alternate node was available,
+possibly because a <seealso marker="#pick_peer">pick_peer/4</seealso>
+callback returned false.</p>
+
+<marker id="handle_request"/>
+</desc>
+</func>
+
+<func>
+<name>Mod:handle_request(Packet, SvcName, Peer) -> Action</name>
+<fsummary>Receive an incoming request.</fsummary>
+<type>
+<v>Packet = packet()</v>
+<v>SvcName = term()</v>
+<v>Peer = peer()</v>
+<v>Action = Reply | {relay, Opts} | discard | {eval, Action, PostF}</v>
+<v>Reply = {reply, message()}
+ | {protocol_error, 3000..3999}</v>
+<v>Opts = diameter:call_opts()</v>
+<v>PostF = diameter:evaluable()</v>
+</type>
+<desc>
+<p>
+Invoked when a request message is received from a peer.
+The application in which the callback takes place (that is, the
+callback module as configured with <seealso
+marker="diameter#start_service">diameter:start_service/2</seealso>)
+is determined by the Application Identifier in the header of the
+incoming request message, the selected module being the one
+whose corresponding <seealso
+marker="diameter_dict#MESSAGE_RECORDS">dictionary</seealso> declares
+itself as defining either the application in question or the Relay
+application.</p>
+
+<p>
+The argument packet() has the following signature.</p>
+
+<code>
+#diameter_packet{header = #diameter_header{},
+ avps = [#diameter_avp{}],
+ msg = record() | undefined,
+ errors = ['Unsigned32'() | {'Unsigned32'(), #diameter_avp{}}],
+ bin = binary(),
+ transport_data = term()}
+</code>
+
+<p>
+The <c>msg</c> field will be <c>undefined</c> only in case the request has
+been received in the relay application.
+Otherwise it contains the record representing the request as outlined
+in <seealso
+marker="diameter_dict#MESSAGE_RECORDS">diameter_dict(4)</seealso>.</p>
+
+<p>
+The <c>errors</c> field specifies any Result-Code's identifying errors
+that were encountered in decoding the request.
+In this case diameter will set both Result-Code and
+Failed-AVP AVP's in a returned
+answer message() before sending it to the peer:
+the returned message() need only set any other required AVP's.
+Note that the errors detected by diameter are all of the 5xxx series
+(Permanent Failures).
+The <c>errors</c> list is empty if the request has been received in
+the relay application.</p>
+
+<p>
+The <c>transport_data</c> field contains an arbitrary term passed into
+diameter from the transport module in question, or the atom
+<c>undefined</c> if the transport specified no data.
+The term is preserved in the packet() containing any answer message
+sent back to the transport process unless another value is explicitly
+specified.</p>
+
+<p>
+The semantics of each of the possible return values are as follows.</p>
+
+<taglist>
+
+<tag><c>{reply, message()}</c></tag>
+<item>
+<p>
+Send the specified answer message to the peer.</p>
+</item>
+
+<tag><c>{protocol_error, 3000..3999}</c></tag>
+<item>
+<p>
+Send an answer message to the peer containing the specified
+protocol error.
+Equivalent to</p>
+<code>
+{reply, ['answer-message' | Avps]
+</code>
+<p>
+where <c>Avps</c> sets the Origin-Host, Origin-Realm, the specified
+Result-Code and (if the request sent one) Session-Id AVP's.</p>
+
+<p>
+Note that RFC 3588 mandates that only answers with a 3xxx series
+Result-Code (protocol errors) may set the E bit.
+Returning a non-3xxx value in a <c>protocol_error</c> tuple
+will cause the request process in question to fail.</p>
+</item>
+
+<tag><c>{relay, Opts}</c></tag>
+<item>
+<p>
+Relay a request to another peer in the role of a Diameter relay agent.
+If a routing loop is detected then the request is answered with
+3005 (DIAMETER_LOOP_DETECTED).
+Otherwise a Route-Record AVP (containing the sending peer's Origin-Host) is
+added to the request and <seealso marker="#pick_peer">pick_peer/4</seealso>
+and subsequent callbacks take place just as if <seealso
+marker="diameter#call">diameter:call/4</seealso> had been called
+explicitly.
+The End-to-End Identifier of the incoming request is preserved in the
+header of the relayed request.</p>
+
+<p>
+The returned <c>Opts</c> should not specify <c>detach</c>.
+A subsequent <seealso marker="#handle_answer">handle_answer/4</seealso>
+callback for the relayed request must return its first
+argument, the <c>diameter_packet</c> record containing the answer
+message.
+Note that the <c>extra</c> option can be specified to supply arguments
+that can distinguish the relay case from others if so desired.
+Any other return value (for example, from a
+<seealso marker="#handle_error">handle_error/4</seealso> callback)
+causes the request to be answered with 3002 (DIAMETER_UNABLE_TO_DELIVER).</p>
+</item>
+
+<tag><c>discard</c></tag>
+<item>
+<p>
+Discard the request.</p>
+</item>
+
+<tag><c>{eval, Action, PostF}</c></tag>
+<item>
+<p>
+Handle the request as if <c>Action</c> has been returned and then
+evaluate <c>PostF</c> in the request process.</p>
+</item>
+
+</taglist>
+
+<p>
+Note that protocol errors detected by diameter will result in an
+answer message without <c>handle_request/3</c> being invoked.</p>
+
+</desc>
+</func>
+
+</funcs>
+
+</erlref>
diff --git a/lib/diameter/doc/src/diameter_compile.xml b/lib/diameter/doc/src/diameter_compile.xml
new file mode 100644
index 0000000000..72bac30709
--- /dev/null
+++ b/lib/diameter/doc/src/diameter_compile.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="iso-8859-1" ?>
+<!DOCTYPE comref SYSTEM "comref.dtd">
+
+<comref>
+<header>
+<copyright>
+<year>2011</year>
+<holder>Ericsson AB. All Rights Reserved.</holder>
+</copyright>
+<legalnotice>
+
+The program may be used and/or copied only with the written permission
+from Ericsson AB, or in accordance with the terms and conditions
+stipulated in the agreement/contract under which the program has been
+supplied.
+
+</legalnotice>
+
+<title>diameterc(1)</title>
+
+<prepared></prepared>
+<docno></docno>
+<date></date>
+<rev></rev>
+<file>diameter_compile.xml</file>
+</header>
+
+<com>diameterc</com>
+<comsummary><![CDATA[diameterc [<options>] <file>]]></comsummary>
+
+<description>
+
+<p>
+The diameterc utility is used to transform diameter
+<seealso marker="diameter_dict">dictionary files</seealso>
+into Erlang source.
+The resulting source implements the interface diameter requires
+to encode and decode the dictionary's messages and AVP's.</p>
+
+</description>
+
+<section>
+<title>USAGE</title>
+
+<taglist>
+
+<tag><![CDATA[diameterc [<options>] <file>]]></tag>
+<item>
+<p>
+Transforms a single dictionary file. Valid options are as follows.</p>
+
+<!-- Leave -h/d/v undocumented, except for the usage message from the
+ utility itself. -->
+
+<taglist>
+<tag><![CDATA[-o <dir>]]></tag>
+<item>
+<p>
+Specifies the directory into which the generated source should be written.
+Defaults to the current working directory.</p>
+</item>
+
+<tag><![CDATA[-i <dir>]]></tag>
+<item>
+<p>
+Specifies a directory to add to the code path.
+Typically used to point at beam files corresponding to dictionaries
+included by the one being compiled (using the <c>@includes</c> directive):
+inclusion is a beam dependency, not an erl/hrl dependency.</p>
+
+<p>
+Multiple <c>-i</c> options can be specified.</p>
+</item>
+
+<tag><![CDATA[-E]]></tag>
+<item>
+<p>
+Supresses erl generation.</p>
+</item>
+
+<tag><![CDATA[-H]]></tag>
+<item>
+<p>
+Supresses hrl generation.</p>
+</item>
+
+</taglist>
+
+</item>
+</taglist>
+
+</section>
+
+<!-- ===================================================================== -->
+
+<section>
+<title>EXIT STATUS</title>
+
+<p>
+Returns 0 on success, non-zero on failure.</p>
+
+</section>
+
+<!-- ===================================================================== -->
+
+<section>
+<title>BUGS</title>
+
+<p>
+The identification of errors in the source file is poor.</p>
+
+</section>
+
+<!-- ===================================================================== -->
+
+<section>
+<title>SEE ALSO</title>
+
+<p>
+<seealso marker="diameter_dict">diameter_dict(4)</seealso></p>
+
+</section>
+
+</comref>
diff --git a/lib/diameter/doc/src/diameter_dict.xml b/lib/diameter/doc/src/diameter_dict.xml
new file mode 100644
index 0000000000..e7c530f1b8
--- /dev/null
+++ b/lib/diameter/doc/src/diameter_dict.xml
@@ -0,0 +1,613 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE erlref SYSTEM "fileref.dtd">
+
+<fileref>
+<header>
+
+<copyright>
+<year>2011</year>
+<holder>Ericsson AB. All Rights Reserved.</holder>
+</copyright>
+<legalnotice>
+The contents of this file are subject to the Erlang Public License,
+Version 1.1, (the "License"); you may not use this file except in
+compliance with the License. You should have received a copy of the
+Erlang Public License along with this software. If not, it can be
+retrieved online at http://www.erlang.org/.
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+the License for the specific language governing rights and limitations
+under the License.
+
+</legalnotice>
+
+<title>diameter_dict(4)</title>
+<prepared>Anders Svensson</prepared>
+<responsible></responsible>
+<docno></docno>
+<approved></approved>
+<checked></checked>
+<date></date>
+<rev>%VSN%</rev>
+<file>diameter_dict.xml</file>
+</header>
+
+<!-- ===================================================================== -->
+
+<file>diameter_dict</file>
+<filesummary>Dictionary inteface of the diameter application.</filesummary>
+
+<description>
+<p>
+A diameter service as configured with <seealso
+marker="diameter#start_service">diameter:start_service/2</seealso>
+specifies one or more supported Diameter applications.
+Each Diameter application specifies a dictionary module that knows how
+to encode and decode its messages and AVP's.
+The dictionary module is in turn generated from a file that defines
+these messages and AVP's.
+The format of such a file is defined in
+<seealso marker="#FILE_FORMAT">FILE FORMAT</seealso> below.
+Users add support for their specific applications by creating
+dictionary files, compiling them to Erlang modules using
+<seealso marker="diameterc">diameterc</seealso> and configuring the
+resulting dictionaries modules on a service.</p>
+
+<p>
+The codec generation also results in a hrl file that defines records
+for the messages and grouped AVP's defined for the application, these
+records being what a user of the diameter application sends and receives.
+(Modulo other available formats as discussed in <seealso
+marker="diameter_app">diameter_app(3)</seealso>.)
+These records and the underlying Erlang data types corresponding to
+Diameter data formats are discussed in <seealso
+marker="#MESSAGE_RECORDS">MESSAGE RECORDS</seealso> and <seealso
+marker="#DATA_TYPES">DATA TYPES</seealso> respectively.
+The generated hrl also contains defines for the possible values of
+AVPs of type Enumerated.</p>
+
+<p>
+The diameter application includes three dictionary modules
+corresponding to applications defined in section 2.4 of RFC 3588:
+<c>diameter_gen_base_rfc3588</c> for the Diameter Common Messages
+application with application identifier 0,
+<c>diameter_gen_accounting</c> for the Diameter Base Accounting
+application with application identifier 3 and
+<c>diameter_gen_relay</c>the Relay application with application
+identifier 0xFFFFFFFF.
+The Common Message and Relay applications are the only applications
+that diameter itself has any specific knowledge of.
+The Common Message application is used for messages that diameter
+itself handles: CER/CEA, DWR/DWA and DPR/DPA.
+The Relay application is given special treatment with regard to
+encode/decode since the messages and AVP's it handles are not specifically
+defined.</p>
+
+<marker id="FILE_FORMAT"/>
+</description>
+
+<!-- ===================================================================== -->
+
+<section>
+<title>FILE FORMAT</title>
+
+<p>
+A dictionary file consists of distinct sections.
+Each section starts with a line consisting of a tag
+followed by zero or more arguments.
+Each section ends at the the start of the next section or end of file.
+Tags consist of an ampersand character followed by a keyword and are
+separated from their arguments by whitespace.
+Whitespace within a section separates individual tokens but its
+quantity is insignificant.</p>
+
+<p>
+The tags, their arguments and the contents of each corresponding
+section are as follows.
+Each section can occur at most once unless otherwise specified.
+The order in which sections are specified is unimportant.</p>
+
+<taglist>
+
+<tag><c>@id Number</c></tag>
+<item>
+<p>
+Defines the integer Number as the Diameter Application Id of the
+application in question.
+Required if the dictionary defines <c>@messages</c>.
+The section has empty content.</p>
+
+<p>
+The Application Id is set in the Diameter Header of outgoing messages
+of the application, and the value in the header of an incoming message
+is used to identify the relevant dictionary module.</p>
+
+<p>
+Example:</p>
+
+<code>
+@id 16777231
+</code>
+
+</item>
+
+<tag><c>@name Mod</c></tag>
+<item>
+<p>
+Defines the name of the generated dictionary module.
+The section has empty content.
+Mod must match the regular expression '^[a-zA-Z0-9][-_a-zA-Z0-9]*$';
+that is, contains only alphanumerics, hyphens and underscores begin with an
+alphanumeric.</p>
+
+<p>
+A name is optional and defaults to the name of the dictionary file
+minus any extension.
+Note that a generated module must have a unique name an not colide
+with another module in the system.</p>
+
+<p>
+Example:</p>
+
+<code>
+@name etsi_e2
+</code>
+
+</item>
+
+<tag><c>@prefix Name</c></tag>
+<item>
+<p>
+Defines Name as the prefix to be added to record and constant names in
+the generated dictionary module and hrl.
+The section has empty content.
+Name must be of the same form as a @name.</p>
+
+<p>
+A prefix is optional but can
+be used to disambiguate record and constant names
+resulting from similarly named messages and AVP's in different
+Diameter applications.</p>
+
+<p>
+Example:</p>
+
+<code>
+@prefix etsi_e2_
+</code>
+
+</item>
+
+<tag><c>@vendor Number Name</c></tag>
+<item>
+<p>
+Defines the integer Number as the the default Vendor-ID of AVP's for
+which the V flag is set.
+Name documents the owner of the application
+but is otherwise unused.
+The section has empty content.</p>
+
+<p>
+Example:</p>
+
+<code>
+@vendor 13019 ETSI
+</code>
+
+</item>
+
+<tag><c>@avp_vendor_id Number</c></tag>
+<item>
+<p>
+Defines the integer Number as the Vendor-ID of the AVP's listed in the
+section content, overriding the <c>@vendor</c> default.
+The section content consists of AVP names.
+Can occur zero or more times (with different values of Number).</p>
+
+<p>
+Example:</p>
+
+<code>
+@avp_vendor_id 2937
+
+WWW-Auth
+Domain-Index
+Region-Set
+</code>
+
+</item>
+
+<tag><c>@inherits Mod</c></tag>
+<item>
+<p>
+Defines the name of a generated dictionary module containing AVP
+definitions referenced by the dictionary but not defined by it.
+The section content is empty.</p>
+
+<p>
+Can occur 0 or more times (with different values of Mod) but all
+dictionaries should typically inherit RFC3588 AVPs from
+<c>diameter_gen_base_rfc3588</c>.</p>
+
+<p>
+Example:</p>
+
+<code>
+@inherits diameter_gen_base_rfc3588
+</code>
+
+</item>
+
+<tag><c>@avp_types</c></tag>
+<item>
+<p>
+Defines the name, code, type and flags of individual AVPs.
+The section consists of definitions of the form</p>
+
+<p><c>Name Code Type Flags</c></p>
+
+<p>
+where Code is the integer AVP code, Flags is a string of V,
+M and P characters indicating the flags to be
+set on an outgoing AVP or a single - (minus) character if none are to
+be set.
+Type identifies either an AVP Data Format as defined in <seealso
+marker="#DATA_TYPES">DATA TYPES</seealso> below or a
+type as defined by a <c>@custom_types</c> tag.</p>
+
+<p>
+Example:</p>
+
+<code>
+@avp_types
+
+Location-Information 350 Grouped VM
+Requested-Information 353 Enumerated V
+</code>
+
+<p>
+Note that the P flag has been deprecated by the Diameter Maintenance
+and Extensions Working Group of the IETF: diameter will set the P flag
+to 0 as mandated by the current draft standard.</p>
+
+</item>
+
+<tag><c>@custom_types Mod</c></tag>
+<item>
+<p>
+Defines AVPs for which module Mod provides encode/decode.
+The section contents consists of type names.
+For each AVP Name defined with custom type Type, Mod should export the
+function Name/3 with arguments encode|decode, Type and Data,
+the latter being the term to be encoded/decoded.
+The function returns the encoded/decoded value.</p>
+
+<p>
+Can occur 0 or more times (with different values of Mod).</p>
+
+<p>
+Example:</p>
+
+<code>
+@custom_types rfc4005_types
+
+Framed-IP-Address
+</code>
+</item>
+
+<tag><c>@messages</c></tag>
+<item>
+<p>
+Defines the messages of the application.
+The section content consists of definitions of the form specified in
+section 3.2 of RFC 3588, "Command Code ABNF specification".</p>
+
+<!-- RFC 4740 RTR/RTA -->
+<code>
+@messages
+
+RTR ::= &lt; Diameter Header: 287, REQ, PXY >
+ &lt; Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Host }
+ { SIP-Deregistration-Reason }
+ [ Destination-Realm ]
+ [ User-Name ]
+ * [ SIP-AOR ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+RTA ::= &lt; Diameter Header: 287, PXY >
+ &lt; Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+</code>
+
+</item>
+
+<tag><c>@grouped</c></tag>
+<item>
+<p>
+Defines the contents of the AVPs of the application having type
+Grouped.
+The section content consists of definitions of the form specified in
+section 4.4 of RFC 3588, "Grouped AVP Values".</p>
+
+<p>
+Example:</p>
+
+<code>
+@grouped
+
+SIP-Deregistration-Reason ::= &lt; AVP Header: 383 >
+ { SIP-Reason-Code }
+ [ SIP-Reason-Info ]
+ * [ AVP ]
+</code>
+</item>
+
+<tag><c>@enum Name</c></tag>
+<item>
+<p>
+Defines values of AVP Name having type Enumerated.
+Section content consists of names and corresponding integer values.
+Integer values can be prefixed with 0x to be interpreted as
+hexidecimal.</p>
+
+<p>
+Can occur 0 or more times (with different values of Name).
+The AVP in question can be defined in an inherited dictionary in order
+to introduce additional values.
+An AVP so extended must be referenced by in a <c>@messages</c> or
+<c>@grouped</c> section.</p>
+
+<p>
+Example:</p>
+
+<code>
+@enum SIP-Reason-Code
+
+PERMANENT_TERMINATION 0
+NEW_SIP_SERVER_ASSIGNED 1
+SIP_SERVER_CHANGE 2
+REMOVE_SIP_SERVER 3
+</code>
+</item>
+
+</taglist>
+
+<p>
+Comments can be included in a dictionary file using semicolon:
+text from a semicolon to end of line is ignored.</p>
+
+<marker id="MESSAGE_RECORDS"/>
+</section>
+
+<!-- ===================================================================== -->
+
+<section>
+<title>MESSAGE RECORDS</title>
+
+<p>
+The hrl generated from a dictionary specification defines records for the
+messages and grouped AVPs defined in <c>@messages</c> and
+<c>@grouped</c> sections.
+For each message or grouped AVP definition, a record is defined whose
+name is the message or AVP name prefixed with any dictionary prefix
+defined with <c>@prefix</c> and whose fields are the names of the AVPs
+contained in the message or grouped AVP in the order specified in the
+definition in question.
+For example, the grouped AVP</p>
+
+<code>
+SIP-Deregistration-Reason ::= &lt; AVP Header: 383 >
+ { SIP-Reason-Code }
+ [ SIP-Reason-Info ]
+ * [ AVP ]
+</code>
+
+<p>
+will result in the following record definition given an empty
+prefix.</p>
+
+<code>
+-record('SIP-Deregistration-Reason' {'SIP-Reason-Code',
+ 'SIP-Reason-Info',
+ 'AVP'}).
+</code>
+
+<p>
+The values encoded in the fields of generated records depends on the
+type and number of times the AVP can occur.
+In particular, an AVP which is specified as occurring exactly once is
+encoded as a value of the AVP's type while an AVP with any other
+specification is encoded as a list of values of the AVP's type.
+The AVP's type is as specified in the AVP definition, the RFC 3588
+types being described below.</p>
+
+<marker id="DATA_TYPES"/>
+</section>
+
+<!-- ===================================================================== -->
+
+<section>
+<title>DATA TYPES</title>
+
+<p>
+The data formats defined in sections 4.2 ("Basic AVP Data
+Formats") and 4.3 ("Derived AVP Data Formats") of RFC 3588 are encoded
+as values of the types defined here.
+Values are passed to <seealso
+marker="diameter#call">diameter:call/4</seealso>
+in a request record when sending a request, returned in a resulting
+answer record and passed to a <seealso
+marker="diameter_app#handle_request">handle_request</seealso>
+callback upon reception of an incoming request.</p>
+
+<p>
+<em>Basic AVP Data Formats</em></p>
+
+<marker id="OctetString"/>
+<marker id="Integer32"/>
+<marker id="Integer64"/>
+<marker id="Unsigned32"/>
+<marker id="Unsigned64"/>
+<marker id="Float32"/>
+<marker id="Float64"/>
+<marker id="Grouped"/>
+
+<code>
+OctetString() = [0..255]
+Integer32() = -2147483647..2147483647
+Integer64() = -9223372036854775807..9223372036854775807
+Unsigned32() = 0..4294967295
+Unsigned64() = 0..18446744073709551615
+Float32() = '-infinity' | float() | infinity
+Float64() = '-infinity' | float() | infinity
+Grouped() = record()
+</code>
+
+<p>
+On encode, an OctetString() can be specified as an iolist(),
+excessively large floats (in absolute value) are equivalent to
+<c>infinity</c> or <c>'-infinity'</c> and excessively large integers
+result in encode failure.
+The records for grouped AVPs are as discussed in the previous
+section.</p>
+
+<p>
+<em>Derived AVP Data Formats</em></p>
+
+<marker id="Address"/>
+<code>
+Address() = OctetString()
+ | tuple()
+</code>
+
+<p>
+On encode, an OctetString() IPv4 address is parsed in the usual
+x.x.x.x format while an IPv6 address is parsed in any of the formats
+specified by section 2.2 of RFC 2373, "Text Representation of
+Addresses".
+An IPv4 tuple() has length 4 and contains values of type 0..255.
+An IPv6 tuple() has length 8 and contains values of type 0..65535.
+The tuple representation is used on decode.</p>
+
+<marker id="Time"/>
+<code>
+Time() = {date(), time()}
+
+where
+
+ date() = {Year, Month, Day}
+ time() = {Hour, Minute, Second}
+
+ Year = integer()
+ Month = 1..12
+ Day = 1..31
+ Hour = 0..23
+ Minute = 0..59
+ Second = 0..59
+</code>
+
+<p>
+Additionally, values that can be encoded are
+limited by way of their encoding as four octets as required by RFC
+3588 with the required extension from RFC 2030.
+In particular, only values between <c>{{1968,1,20},{3,14,8}}</c>
+and <c>{{2104,2,26},{9,42,23}}</c> (both inclusive) can be encoded.</p>
+
+<marker id="UTF8String"/>
+<code>
+UTF8String() = [integer()]
+</code>
+
+<p>
+List elements are the UTF-8 encodings of the individual characters
+in the string.
+Invalid codepoints will result in encode/decode failure.</p>
+
+<marker id="DiameterIdentity"/>
+<code>
+DiameterIdentity() = OctetString()
+</code>
+
+<p>
+A value must have length at least 1.</p>
+
+<marker id="DiameterURI"/>
+<code>
+DiameterURI() = OctetString()
+ | #diameter_URI{type = Type,
+ fqdn = FQDN,
+ port = Port,
+ transport = Transport,
+ protocol = Protocol}
+
+where
+
+ Type = aaa | aaas
+ FQDN = OctetString()
+ Port = integer()
+ Transport = sctp | tcp
+ Protocol = diameter | radius | 'tacacs+'
+</code>
+
+<p>
+On encode, fields port, transport and protocol default to 3868, sctp
+and diameter respectively.
+The grammar of an OctetString-valued DiameterURI() is as specified in
+section 4.3 of RFC 3588.
+The record representation is used on decode.</p>
+
+<marker id="Enumerated"/>
+<code>
+Enumerated() = Integer32()
+</code>
+
+<p>
+On encode, values can be specified using the macros defined in a
+dictionary's hrl file.</p>
+
+<marker id="IPFilterRule"/>
+<marker id="QoSFilterRule"/>
+<code>
+IPFilterRule() = OctetString()
+QoSFilterRule() = OctetString()
+</code>
+
+<p>
+Values of these types are not currently parsed by diameter.</p>
+
+</section>
+
+<!-- ===================================================================== -->
+<!-- ===================================================================== -->
+
+<section>
+<title>SEE ALSO</title>
+
+<p>
+<seealso marker="diameterc">diameterc(1)</seealso>,
+<seealso marker="diameter">diameter(3)</seealso>,
+<seealso marker="diameter_app">diameter_app(3)</seealso></p>
+
+</section>
+
+</fileref>
diff --git a/lib/diameter/doc/src/diameter_examples.xml b/lib/diameter/doc/src/diameter_examples.xml
new file mode 100644
index 0000000000..966d1f1eee
--- /dev/null
+++ b/lib/diameter/doc/src/diameter_examples.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+<header>
+
+<copyright>
+<year>2011</year>
+<holder>Ericsson AB. All Rights Reserved.</holder>
+</copyright>
+
+<legalnotice>
+The contents of this file are subject to the Erlang Public License,
+Version 1.1, (the "License"); you may not use this file except in
+compliance with the License. You should have received a copy of the
+Erlang Public License along with this software. If not, it can be
+retrieved online at http://www.erlang.org/.
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+the License for the specific language governing rights and limitations
+under the License.
+
+</legalnotice>
+
+<title>Examples</title>
+<prepared></prepared>
+<responsible></responsible>
+<docno></docno>
+<approved></approved>
+<checked></checked>
+<date></date>
+<rev></rev>
+<file>diameter_examples.xml</file>
+</header>
+
+<!-- ===================================================================== -->
+
+<p>
+To be written.
+Example code can be found in the diameter application's
+<c>examples</c> subdirectory.</p>
+
+</chapter>
+
diff --git a/lib/diameter/doc/src/diameter_intro.xml b/lib/diameter/doc/src/diameter_intro.xml
new file mode 100644
index 0000000000..ef08002a8b
--- /dev/null
+++ b/lib/diameter/doc/src/diameter_intro.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+<header>
+<copyright>
+<year>2011</year>
+<holder>Ericsson AB. All Rights Reserved.</holder>
+</copyright>
+
+<legalnotice>
+The contents of this file are subject to the Erlang Public License,
+Version 1.1, (the "License"); you may not use this file except in
+compliance with the License. You should have received a copy of the
+Erlang Public License along with this software. If not, it can be
+retrieved online at http://www.erlang.org/.
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+the License for the specific language governing rights and limitations
+under the License.
+
+</legalnotice>
+
+<title>Introduction</title>
+<prepared></prepared>
+<responsible></responsible>
+<docno></docno>
+<approved></approved>
+<checked></checked>
+<date></date>
+<rev></rev>
+<file>diameter_intro.xml</file>
+</header>
+
+<p>
+The diameter application is an implementation of the Diameter protocol
+as defined by RFC 3588.
+It supports arbitrary Diameter applications by way of a
+<em>dictionary</em> interface that allows messages and AVP's to be
+defined and input into diameter as configuration.
+It has support for all roles defined in the RFC: client, server and
+agent.
+This chapter provides a short overview of the application.</p>
+
+<p>
+A Diameter peer is implemented by configuring a <em>service</em> and
+one or more <em>transports</em> using the interface module
+<seealso marker="diameter">diameter</seealso>.
+The service configuration defines the Diameter applications to be
+supported by the peer and, typically, the capabilities that it should
+send to remote peers at capabilities exchange upon the establishment
+of transport connections.
+A transport is configured on a service and provides protocol-specific
+send/receive functionality by way of a transport interface defined by
+diameter and implemented by a transport module.
+The diameter application provides two transport modules: <seealso
+marker="diameter_tcp">diameter_tcp</seealso> and <seealso
+marker="diameter_sctp">diameter_sctp</seealso> for transport over TCP
+(using <c>gen_tcp</c>) and SCTP (using <c>gen_sctp</c>) respectively.
+Other transports can be provided by any module that implements
+diameter's <seealso marker="diameter_transport">transport
+interface</seealso>.</p>
+
+<p>
+While a service typically implements a single Diameter peer (as
+identified by an Origin-Host AVP), transports can themselves be
+associated with capabilities AVP's so that a single service be used to
+implement more than one Diameter peer.</p>
+
+<p>
+Each Diameter application defined on a service is configured with a
+callback module that implements the <seealso
+marker="diameter_app">application interface</seealso> through which
+diameter communicates the connectivity of remote peers, requests peer
+selection for outgoing requests, and communicates the reception of
+incoming Diameter request and answer messages.
+An application using diameter implements these application callback
+modules to provide the functionality of the Diameter peer(s) it
+implements.</p>
+
+<p>
+Each Diameter application is also configured with one or more
+dictionary modules
+that provide encode/decode functionality for outgoing/incoming
+Diameter messages.
+A module is generated from a <seealso
+marker="diameter_dict">specification file</seealso> using the <seealso
+marker="diameterc">diameterc</seealso> utility.
+Dictionaries for the RFC 3588 Diameter Common Messages, Base
+Accounting and Relay applications are provided by the diameter
+application.</p>
+
+</chapter>
+
diff --git a/lib/diameter/doc/src/diameter_sctp.xml b/lib/diameter/doc/src/diameter_sctp.xml
new file mode 100644
index 0000000000..c1e839b8e1
--- /dev/null
+++ b/lib/diameter/doc/src/diameter_sctp.xml
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+<header>
+<copyright>
+<year>2011</year>
+<holder>Ericsson AB. All Rights Reserved.</holder>
+</copyright>
+<legalnotice>
+The contents of this file are subject to the Erlang Public License,
+Version 1.1, (the "License"); you may not use this file except in
+compliance with the License. You should have received a copy of the
+Erlang Public License along with this software. If not, it can be
+retrieved online at http://www.erlang.org/.
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+the License for the specific language governing rights and limitations
+under the License.
+
+</legalnotice>
+
+<title>diameter_sctp(3)</title>
+<prepared>Anders Svensson</prepared>
+<responsible></responsible>
+<docno></docno>
+<approved></approved>
+<checked></checked>
+<date></date>
+<rev></rev>
+<file>diameter_sctp.xml</file>
+</header>
+
+<module>diameter_sctp</module>
+<modulesummary>Diameter transport over SCTP.</modulesummary>
+
+<description>
+
+<p>
+This module implements diameter transport over SCTP using gen_sctp.
+It can be specified as the value of a transport_module option to
+<seealso
+marker="diameter#add_transport">diameter:add_transport/2</seealso>
+and implements the behaviour documented in
+<seealso marker="diameter_transport">diameter_transport(3)</seealso>.</p>
+
+<marker id="start"/>
+</description>
+
+<!-- ===================================================================== -->
+
+<funcs>
+
+<func>
+<name>start({Type, Ref}, Svc, [Opt])
+ -> {ok, Pid, [LAddr]} | {error, Reason}</name>
+<fsummary>Start a transport process.</fsummary>
+<type>
+<v>Type = connect | accept</v>
+<v>Ref = reference()</v>
+<v>Svc = #diameter_service{}</v>
+<v>Opt = {raddr, ip_address()} | {rport, integer()} | term()</v>
+<v>Pid = pid()</v>
+<v>LAddr = ip_address()</v>
+<v>Reason = term()</v>
+</type>
+<desc>
+
+<p>
+The start function required by <seealso
+marker="diameter_transport#start">diameter_transport(3)</seealso>.</p>
+
+<p>
+The only diameter_sctp-specific argument is the options list.
+Options <c>raddr</c> and <c>rport</c> specify the remote address
+and port for a connecting transport and not valid for a listening
+transport.
+The former is required while latter defaults to 3868 if unspecified.
+More than one <c>raddr</c> option can be specified, in which case the
+connecting transport in question attempts each in sequence until
+an association is established.
+Remaining options are any accepted by gen_sctp:open/1, with the exception
+of options <c>mode</c>, <c>binary</c>, <c>list</c>, <c>active</c>
+and <c>sctp_events</c>.
+Note that options <c>ip</c> and <c>port</c> specify the local address
+and port respectively.</p>
+
+<p>
+Multiple <c>ip</c> options can be specified for a multihomed peer.
+If none are specified then the values of Host-IP-Address
+on the service are used. (In particular, one of these must be specified.)
+Option <c>port</c> defaults to 3868 for a listening transport and 0 for a
+connecting transport.</p>
+
+<p>
+diameter_sctp uses the <c>transport_data</c> field of
+the <c>diameter_packet</c> record to communicate the stream on which an
+inbound message has been received, or on which an outbound message
+should be sent: the value will be of the form <c>{stream, Id}</c>
+on an inbound message passed to a <seealso
+marker="diameter_app#handle_request">handle_request</seealso> or <seealso
+marker="diameter_app#handle_answer">handle_answer</seealso> callback.
+For an outbound message, either <c>undefined</c> (explicitly of
+by specifying the outbound message as a <c>binary()</c>) or a tuple
+should be set in the return value of <seealso
+marker="diameter_app#handle_request">handle_request</seealso>
+(typically by retaining the value passed into this function)
+or <seealso
+marker="diameter_app#prepare_request">prepare_request</seealso>.
+The value <c>undefined</c> uses a "next outbound stream" id and then
+increments this modulo the total number outbound streams. That
+is, successive values of <c>undefined</c> cycle through all outbound
+streams.</p>
+
+<!-- TODO: Some way of getting at the number of available outbound -->
+<!-- streams. -->
+
+</desc>
+</func>
+
+</funcs>
+
+<!-- ===================================================================== -->
+<!-- ===================================================================== -->
+
+<section>
+<title>SEE ALSO</title>
+
+<p>
+<seealso marker="diameter_transport">diameter_transport(3)</seealso></p>
+
+</section>
+
+</erlref>
diff --git a/lib/diameter/doc/src/diameter_soc.xml b/lib/diameter/doc/src/diameter_soc.xml
new file mode 100644
index 0000000000..6b9ef9f756
--- /dev/null
+++ b/lib/diameter/doc/src/diameter_soc.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+
+<header>
+<copyright>
+<year>2011</year>
+<holder>Ericsson AB. All Rights Reserved.</holder>
+</copyright>
+
+<legalnotice>
+The contents of this file are subject to the Erlang Public License,
+Version 1.1, (the "License"); you may not use this file except in
+compliance with the License. You should have received a copy of the
+Erlang Public License along with this software. If not, it can be
+retrieved online at http://www.erlang.org/.
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+the License for the specific language governing rights and limitations
+under the License.
+
+</legalnotice>
+
+<title>Standards Compliance</title>
+<prepared></prepared>
+<responsible></responsible>
+<docno></docno>
+<approved></approved>
+<checked></checked>
+<date></date>
+<rev></rev>
+<file>diameter_soc.xml</file>
+
+</header>
+
+<p>
+Known points of questionable or non-compliance.</p>
+
+<!-- ===================================================================== -->
+
+<section>
+<title>RFC 3588</title>
+
+<list>
+
+<item>
+<p>
+The End-to-End Security framework (section 2.9) isn't implemented
+since it is largely unspecified.
+The document that was to describe it
+(reference [AAACMS]) was abandoned in an uncompleted state several
+years ago and the current draft RFC deprecates the framework,
+including the P Flag in the AVP header.</p>
+</item>
+
+<item>
+<p>
+There is no TLS support over SCTP.
+RFC 3588 requires that a Diameter server support TLS but in
+practise this seems to mean TLS over SCTP since there are limitations
+with running over SCTP: see RFC 6083 (DTLS over SCTP), which is a
+response to RFC 3436 (TLS over SCTP).
+The current RFC 3588 draft acknowledges this by equating
+TLS with TLS/TCP and DTLS/SCTP but we do not yet support DTLS.</p>
+</item>
+
+<item>
+<p>
+There is no explicit support for peer discovery (section 5.2).
+It can possibly be implemented on top of diameter as is but this is
+probably something that diameter should do.
+The current draft deprecates portions of the original RFC's mechanisms
+however.</p>
+</item>
+
+<item>
+<p>
+The peer state machine's election process (section 5.6.4) isn't
+implemented as specified since it assumes knowledge of a
+peer's Origin-Host before sending it a CER. (The identity becoming known
+upon reception of CEA.)
+The possibility of configuring
+the peer's Origin-Host could be added, along with handling of the case
+that it sends something else, but for many applications this will
+just be unnecessary configuration of a value that it has no control over.</p>
+</item>
+<!-- Transport protocol plus address/port, which we do know when
+ sending and receiving CER, is enough to definitely identify
+ the peer. However, there's nothing stopping a peer from using
+ different identities on different transport protocols, even
+ if it's maybe a bit far-fetched. -->
+
+</list>
+
+</section>
+
+<!-- ===================================================================== -->
+
+<section>
+<title>RFC 3539</title>
+
+<p>
+RFC 3539 is more difficult to comply to since it discusses
+problems as much as it requires functionality but all the MUST's are
+covered, the watchdog state machine being the primary one.
+Of the optional functionality, load balancing is left to the
+diameter user (since it's the one deciding who to send to) and
+there is no Congestion Manager.</p>
+
+</section>
+
+</chapter>
diff --git a/lib/diameter/doc/src/diameter_tcp.xml b/lib/diameter/doc/src/diameter_tcp.xml
new file mode 100644
index 0000000000..e6b53383c0
--- /dev/null
+++ b/lib/diameter/doc/src/diameter_tcp.xml
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+<header>
+<copyright>
+<year>2011</year>
+<holder>Ericsson AB. All Rights Reserved.</holder>
+</copyright>
+<legalnotice>
+The contents of this file are subject to the Erlang Public License,
+Version 1.1, (the "License"); you may not use this file except in
+compliance with the License. You should have received a copy of the
+Erlang Public License along with this software. If not, it can be
+retrieved online at http://www.erlang.org/.
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+the License for the specific language governing rights and limitations
+under the License.
+
+</legalnotice>
+
+<title>diameter_tcp(3)</title>
+<prepared>Anders Svensson</prepared>
+<responsible></responsible>
+<docno></docno>
+<approved></approved>
+<checked></checked>
+<date></date>
+<rev></rev>
+<file>diameter_tcp.xml</file>
+</header>
+
+<module>diameter_tcp</module>
+<modulesummary>Diameter transport over TCP.</modulesummary>
+
+<description>
+
+<p>
+This module implements diameter transport over TCP using gen_tcp.
+It can be specified as the value of a transport_module option to
+<seealso
+marker="diameter#add_transport">diameter:add_transport/2</seealso>
+and implements the behaviour documented in
+<seealso marker="diameter_transport">diameter_transport(3)</seealso>.
+TLS security is supported, both as an upgrade following
+capabilities exchange as specified by RFC 3588 and
+at connection establishment as in the current draft standard.</p>
+
+<p>
+Note that the ssl application is required for TLS and must be started
+before configuring TLS capability on diameter transports.</p>
+
+<marker id="start"/>
+</description>
+
+<!-- ===================================================================== -->
+
+<funcs>
+
+<func>
+<name>start({Type, Ref}, Svc, [Opt])
+ -> {ok, Pid, [LAddr]} | {error, Reason}</name>
+<fsummary>Start a transport process.</fsummary>
+<type>
+<v>Type = connect | accept</v>
+<v>Ref = reference()</v>
+<v>Svc = #diameter_service{}</v>
+<v>Opt = OwnOpt | SslOpt | OtherOpt</v>
+<v>Pid = pid()</v>
+<v>LAddr = ip_address()</v>
+<v>Reason = term()</v>
+<v>OwnOpt = {raddr, ip_address()}
+ | {rport, integer()}
+ | {port, integer()}</v>
+<v>SslOpt = {ssl_options, true | list()}</v>
+<v>OtherOpt = term()</v>
+</type>
+<desc>
+
+<p>
+The start function required by <seealso
+marker="diameter_transport#start">diameter_transport(3)</seealso>.</p>
+
+<p>
+The only diameter_tcp-specific argument is the options list.
+Options <c>raddr</c> and <c>rport</c> specify the remote address
+and port for a connecting transport and are not valid for a listening
+transport.
+Option <c>ssl_options</c> must be specified for a transport
+that must be able to support TLS: a value of <c>true</c> results in a
+TLS handshake immediately upon connection establishment while
+list() specifies options to be passed to ssl:connect/2 of ssl:ssl_accept/2
+after capabilities exchange if TLS is negotiated.
+Remaining options are any accepted by ssl:connect/3 or gen_tcp:connect/3 for
+a connecting transport, or ssl:listen/3 or gen_tcp:listen/2 for
+a listening transport, depending on whether or not <c>{ssl_options, true}</c>
+has been specified.
+Options <c>binary</c>, <c>packet</c> and <c>active</c> cannot be specified.
+Also, option <c>port</c> can be specified for a listening transport
+to specify the local listening port, the default being the standardized
+3868 if unspecified.
+Note that option <c>ip</c> specifies the local address.</p>
+
+<p>
+An <c>ssl_options</c> list must be specified if and only if
+the transport in question has specified an Inband-Security-Id
+AVP with value TLS on the relevant call to
+<seealso
+marker="diameter#start_service">start_service/2</seealso> or
+<seealso
+marker="diameter#add_transport">add_transport/2</seealso>,
+so that the transport process will receive notification of
+whether or not to commence with a TLS handshake following capabilities
+exchange.
+Failing to specify an options list on a TLS-capable transport
+for which TLS is negotiated will cause TLS handshake to fail.
+Failing to specify TLS capability when <c>ssl_options</c> has been
+specified will cause the transport process to wait for a notification
+that will not be forthcoming, which will eventually cause the RFC 3539
+watchdog to take down the connection.</p>
+
+<p>
+If the service specifies more than one Host-IP-Address and
+option <c>ip</c> is unspecified then then the
+first of the service's addresses is used as the local address.</p>
+
+<p>
+The returned local address list has length one.</p>
+
+</desc>
+</func>
+
+</funcs>
+
+<!-- ===================================================================== -->
+<!-- ===================================================================== -->
+
+<section>
+<title>SEE ALSO</title>
+
+<p>
+<seealso marker="diameter">diameter(3)</seealso>,
+<seealso marker="diameter_transport">diameter_transport(3)</seealso></p>
+
+</section>
+
+</erlref>
diff --git a/lib/diameter/doc/src/diameter_transport.xml b/lib/diameter/doc/src/diameter_transport.xml
new file mode 100644
index 0000000000..087a90b099
--- /dev/null
+++ b/lib/diameter/doc/src/diameter_transport.xml
@@ -0,0 +1,241 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+<header>
+<copyright>
+<year>2011</year>
+<holder>Ericsson AB. All Rights Reserved.</holder>
+</copyright>
+<legalnotice>
+The contents of this file are subject to the Erlang Public License,
+Version 1.1, (the "License"); you may not use this file except in
+compliance with the License. You should have received a copy of the
+Erlang Public License along with this software. If not, it can be
+retrieved online at http://www.erlang.org/.
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+the License for the specific language governing rights and limitations
+under the License.
+
+</legalnotice>
+
+<title>diameter_transport(3)</title>
+<prepared>Anders Svensson</prepared>
+<responsible></responsible>
+<docno></docno>
+<approved></approved>
+<checked></checked>
+<date></date>
+<rev></rev>
+<file>diameter_transport.xml</file>
+</header>
+
+<module>diameter_transport</module>
+<modulesummary>Diameter transport interface.</modulesummary>
+
+<description>
+
+<p>
+A module specified as a <c>transport_module</c> to <seealso
+marker="diameter#add_transport">diameter:add_transport/2</seealso>
+must implement the interface documented here.
+The interface consists of a function with which
+diameter starts a transport process and a message interface with which
+the transport process communicates with the process that starts it (aka its
+parent).</p>
+
+<marker id="start"/>
+</description>
+
+<!-- ===================================================================== -->
+
+<funcs>
+
+<func>
+<name>Mod:start({Type, Ref}, Svc, Opts)
+ -> {ok, Pid} | {ok, Pid, LAddrs} | {error, Reason}</name>
+<fsummary>Start a transport process.</fsummary>
+<type>
+<v>Type = connect | accept</v>
+<v>Ref = reference()</v>
+<v>Svc = #diameter_service{}</v>
+<v>Opts = term()</v>
+<v>Pid = pid()</v>
+<v>LAddrs = [ip_address()]</v>
+<v>Reason = term()</v>
+</type>
+<desc>
+<p>
+Start a transport process.
+Called by diameter as a consequence of a call to <seealso
+marker="diameter#add_transport">diameter:add_transport/2</seealso> in
+order to establish or accept a transport connection respectively.
+A transport process maintains a connection with a single remote peer.</p>
+
+<p>
+The first argument indicates whether the transport process in question
+is being started for a connecting (<c>connect</c>) or listening
+(<c>accept</c>) transport.
+In the latter case, transport processes are started as required to
+accept connections from multiple peers.
+Ref is in each case the same value that was returned from the
+call to <seealso
+marker="diameter#add_transport">diameter:add_transport/2</seealso>
+that has lead to starting of a transport process.</p>
+
+<p>
+A transport process must implement the message interface documented below.
+It should retain the pid of its parent, monitor the parent and terminate if
+it dies.
+It should not link to the parent.
+It should exit if its transport connection with its peer is lost.</p>
+
+<p>
+Transport processes for a given service are started sequentially.</p>
+
+<p>
+The start function should use the 'Host-IP-Address' list on the service,
+namely <c>Svc#diameter_service.host_ip_address</c>, and/or
+<c>Opts</c> to select an appropriate list of local IP addresses,
+and should return this list if different from the service addresses.
+The returned list is used to populate 'Host-IP-Address' AVPs in outgoing
+capabilities exchange messages, the service addresses being used
+otherwise.</p>
+
+<marker id="MESSAGES"/>
+</desc>
+</func>
+
+</funcs>
+
+<!-- ===================================================================== -->
+
+<section>
+<title>MESSAGES</title>
+
+<p>
+All messages sent over the transport interface are of the
+form <c>{diameter, term()}</c>.</p>
+
+<p>
+A transport process can expect the following messages from
+diameter.</p>
+
+<taglist>
+
+<tag><c>{diameter, {send, Packet}}</c></tag>
+<item>
+<p>
+An outbound Diameter message.
+Packet can be either <c>binary()</c> (the message to be sent)
+or a <c>#diameter_packet{}</c> whose <c>transport_data</c> field
+containes a value other than undefined.</p>
+</item>
+
+<tag><c>{diameter, {close, Pid}}</c></tag>
+<item>
+<p>
+A request to close the transport connection.
+The transport process should terminate after closing the
+connection.
+Pid is the pid() of the parent process.</p>
+</item>
+
+<tag><c>{diameter, {tls, Ref, Type, Bool}}</c></tag>
+<item>
+<p>
+Indication of whether or not capabilities exchange has selected
+inband security using TLS.
+Ref is a reference() that must be included in the
+<c>{diameter, {tls, Ref}}</c> reply message to the transport's
+parent process (see below).
+Type is either <c>connect</c> or <c>accept</c> depending on
+whether the process has been started for a connecting or listening
+transport respectively.
+Bool is a boolean() indicating whether or not the transport connection
+should be upgraded to TLS.</p>
+
+<p>
+If TLS is requested (Bool = true) then a connecting process should
+initiate a TLS handshake with the peer and an accepting process should
+prepare to accept a handshake.
+A successful handshake should be followed by a <c>{diameter, {tls, Ref}}</c>
+message to the parent process.
+A failed handshake should cause the process to exit.</p>
+
+<p>
+This message is only sent to a transport process over whose
+<c>Inband-Security-Id</c> configuration has indicated support for
+TLS.</p>
+</item>
+
+</taglist>
+
+<p>
+A transport process should send the following messages
+to its parent.</p>
+
+<taglist>
+
+<tag><c>{diameter, {self(), connected}}</c></tag>
+<item>
+<p>
+Inform the parent that the transport process with Type = accept has
+established a connection with the peer.
+Not sent if the transport process has Type = connect.</p>
+</item>
+
+<tag><c>{diameter, {self(), connected, Remote}}</c></tag>
+<item>
+<p>
+Inform the parent that the transport process with Type = connect
+has established a connection with a peer.
+Not sent if the transport process has Type = accept.
+Remote is an arbitrary term that uniquely identifies the remote
+endpoint to which the transport has connected.</p>
+</item>
+
+<tag><c>{diameter, {recv, Packet}}</c></tag>
+<item>
+<p>
+An inbound Diameter message.
+Packet can be either <c>binary()</c> (the message to be sent)
+or <c>#diameter_packet{}</c>
+whose <c>packet</c> field contains a <c>binary()</c>.
+Any value (other than undefined) set in
+the <c>transport_data</c> field will be passed back with a
+corresponding answer message in the case that the inbound message is a
+request unless the sender sets another value.
+How the <c>transport_data</c> is used/interpreted is up to the
+transport module.</p>
+</item>
+
+<tag><c>{diameter, {tls, Ref}}</c></tag>
+<item>
+<p>
+Acknowledgment of a successful TLS handshake.
+Ref is the reference() received in the
+<c>{diameter, {tls, Ref, Type, Bool}}</c> message in response
+to which the reply is sent.
+A transport must exit if a handshake is not successful.</p>
+</item>
+
+</taglist>
+
+</section>
+
+<!-- ===================================================================== -->
+<!-- ===================================================================== -->
+
+<section>
+<title>SEE ALSO</title>
+
+<p>
+<seealso marker="diameter_tcp">diameter_tcp(3)</seealso>,
+<seealso marker="diameter_sctp">diameter_sctp(3)</seealso></p>
+
+</section>
+
+</erlref>
diff --git a/lib/diameter/doc/src/diameter_using.xml b/lib/diameter/doc/src/diameter_using.xml
new file mode 100644
index 0000000000..809b76bdf3
--- /dev/null
+++ b/lib/diameter/doc/src/diameter_using.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+
+<header>
+<copyright>
+<year>2011</year>
+<holder>Ericsson AB. All Rights Reserved.</holder>
+</copyright>
+
+<legalnotice>
+The contents of this file are subject to the Erlang Public License,
+Version 1.1, (the "License"); you may not use this file except in
+compliance with the License. You should have received a copy of the
+Erlang Public License along with this software. If not, it can be
+retrieved online at http://www.erlang.org/.
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+the License for the specific language governing rights and limitations
+under the License.
+
+</legalnotice>
+
+<title>Using the stack</title>
+<prepared></prepared>
+<responsible></responsible>
+<docno></docno>
+<approved></approved>
+<checked></checked>
+<date></date>
+<rev></rev>
+<file>diameter_using.xml</file>
+
+</header>
+
+<p>
+To be written.</p>
+
+<!-- ===================================================================== -->
+
+</chapter>
diff --git a/lib/diameter/doc/src/files.mk b/lib/diameter/doc/src/files.mk
new file mode 100644
index 0000000000..79d53abceb
--- /dev/null
+++ b/lib/diameter/doc/src/files.mk
@@ -0,0 +1,52 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+XML_APPLICATION_FILES = \
+ ref_man.xml
+
+XML_REF1_FILES = \
+ diameter_compile.xml
+
+XML_REF3_FILES = \
+ diameter.xml \
+ diameter_app.xml \
+ diameter_transport.xml \
+ diameter_tcp.xml \
+ diameter_sctp.xml
+
+XML_REF4_FILES = \
+ diameter_dict.xml
+
+XML_PART_FILES = \
+ user_man.xml
+
+XML_EXTRA_FILES =
+
+XML_CHAPTER_FILES = \
+ diameter_intro.xml \
+ diameter_using.xml \
+ diameter_examples.xml \
+ diameter_soc.xml \
+ notes.xml
+
+BOOK_FILES = \
+ book.xml
+
+GIF_FILES = \
+ notes.gif
diff --git a/lib/diameter/doc/src/notes.gif b/lib/diameter/doc/src/notes.gif
new file mode 100644
index 0000000000..e000cca26a
--- /dev/null
+++ b/lib/diameter/doc/src/notes.gif
Binary files differ
diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml
new file mode 100644
index 0000000000..e2723f3e99
--- /dev/null
+++ b/lib/diameter/doc/src/notes.xml
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+
+<header>
+<copyright>
+<year>2011</year>
+<holder>Ericsson AB. All Rights Reserved.</holder>
+</copyright>
+<legalnotice>
+The contents of this file are subject to the Erlang Public License,
+Version 1.1, (the "License"); you may not use this file except in
+compliance with the License. You should have received a copy of the
+Erlang Public License along with this software. If not, it can be
+retrieved online at http://www.erlang.org/.
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+the License for the specific language governing rights and limitations
+under the License.
+
+</legalnotice>
+
+<title>Release Notes</title>
+<prepared></prepared>
+<docno></docno>
+<date></date>
+<rev></rev>
+<file>notes.xml</file>
+</header>
+
+<p>
+Releases are listed in reverse chronological order, most recent
+first.</p>
+
+<!-- ===================================================================== -->
+
+<section><title>Diameter 0.10</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Handle #sctp_paddr_change and #sctp_pdapi_event from
+ gen_sctp.</p>
+ <p>
+ The events are enabled by default but diameter_sctp
+ neither disabled nor dealt with them. Reception of such
+ an event caused a transport process to crash.</p>
+ <p>
+ Own Id: OTP-9538</p>
+ </item>
+ <item>
+ <p>
+ Fix header folding bug.</p>
+ <p>
+ A prepare_request callback from diameter can return a
+ diameter_header record in order to set values in the
+ header of an outgoing request. A fault in
+ diameter_lib:fold_tuple/3 caused the subsequent encode of
+ the outgoing request to fail.</p>
+ <p>
+ Own Id: OTP-9577</p>
+ </item>
+ <item>
+ <p>
+ Fix bugs in sending of answer-message replies.</p>
+ <p>
+ 3001 (DIAMETER_COMMAND_UNSUPPORTED) was not sent since
+ the decode placed the AVP list in the wrong field of the
+ diameter_packet, causing the subsequent encode to fail.
+ Session-Id was also set improperly, causing encode to
+ fail even in this case.</p>
+ <p>
+ Own Id: OTP-9578</p>
+ </item>
+ <item>
+ <p>
+ Fix improper use of error_logger:info_report/2.</p>
+ <p>
+ Function doesn't take a format string and arguments as it
+ was called. Instead use error_logger:info_report/1 and
+ use the same report format as used for warning and error
+ reports.</p>
+ <p>
+ Own Id: OTP-9579</p>
+ </item>
+ <item>
+ <p>
+ Fix and clarify semantics of peer filters.</p>
+ <p>
+ An eval filter returning a non-true value caused the call
+ process to fail and the doc was vague on how an exception
+ was treated. Clarify that the non-tuple host/realm
+ filters assume messages of a certain form.</p>
+ <p>
+ Own Id: OTP-9580</p>
+ </item>
+ <item>
+ <p>
+ Fix and clarify relay behaviour.</p>
+ <p>
+ Implicit filtering of the sending peer in relaying a
+ request could cause loop detection to be preempted in a
+ manner not specified by RFC3588. Reply with 3002
+ (DIAMETER_UNABLE_TO_DELIVER) on anything but an answer to
+ a relayed request.</p>
+ <p>
+ Own Id: OTP-9583</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ @id required in dictionary files only when @messages is
+ specified.</p>
+ <p>
+ @id defines an application identifier and this is used
+ only when sending or receiving messages. A dictionary can
+ define only AVP's however, to be included by other
+ dictionaries using @inherits, in which case it makes no
+ sense to require @id.</p>
+ <p>
+ Note that message definitions are not inherited with
+ @inherits, only AVP's</p>
+ <p>
+ Own Id: OTP-9467</p>
+ </item>
+ <item>
+ <p>
+ Allow @enum when AVP is defined in an inherited
+ dictionary.</p>
+ <p>
+ 3GPP standards (for one) extend the values allowed for
+ RFC 3588 AVP's of type Enumerated. Previously, extending
+ an AVP was only possible by completely redefining the
+ AVP.</p>
+ <p>
+ Own Id: OTP-9469</p>
+ </item>
+ <item>
+ <p>
+ Migrate testsuites to pure common test and add both
+ suites and testcases.</p>
+ <p>
+ Own Id: OTP-9553</p>
+ </item>
+ <item>
+ <p>
+ Requests of arbitrary form.</p>
+ <p>
+ diameter:call/4 can be passed anything, as long as the
+ subsequent prepare_request callback returns a term that
+ can be encoded.</p>
+ <p>
+ Own Id: OTP-9581</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section>
+<title>diameter 0.9</title>
+
+<p>
+Initial release of the diameter application.</p>
+
+<p>
+Known issues or limitations:</p>
+
+<list>
+
+<item>
+<p>
+Some agent-related functionality is not entirely complete.
+In particular, support for proxy agents, that advertise specific
+Diameter applications but otherwise relay messages in much the same
+way as relay agents (for which a <seealso
+marker="diameter_app#handle_request">handle_request/3</seealso>
+callback can return a <c>relay</c> tuple), will be completed in an
+upcoming release.
+There may also be more explicit support for redirect agents, although
+redirect behaviour can be implemented with the current
+functionality.</p>
+
+</item>
+
+<item>
+<p>
+There is some asymmetry in the treatment of messages sent as
+<c>diameter_header/avp</c> records and those sent in the "normal"
+fashion, and not all of this is documented.
+This is related to the previous point since this form of sending a
+message was introduced specifically to handle relay agent behaviour
+using the same callback interface as for client/server behaviour.</p>
+</item>
+
+<item>
+<p>
+The User's Guide is currently quite thin.
+The introductory chapter followed by the examples (in the application
+<c>examples</c> subdirectory) may be sufficient
+for those having some familiarity with the Diameter protocol but the
+intention is to provide more introductory text.
+The reference documentation is quite complete, although some points
+could likely be expanded upon.</p>
+</item>
+
+<item>
+<p>
+The function <seealso
+marker="diameter#service_info">diameter:service_info/2</seealso>
+can be used to retrieve information about a started service
+(statistics, information about connected peers, etc) but
+this is not yet documented and both the input and output may change
+in the next release.</p>
+</item>
+
+
+</list>
+
+<p>
+See <seealso marker="diameter_soc">Standards Compliance</seealso> for
+standards-related issues.</p>
+</section>
+
+</chapter>
diff --git a/lib/diameter/doc/src/ref_man.xml b/lib/diameter/doc/src/ref_man.xml
new file mode 100644
index 0000000000..137ce79094
--- /dev/null
+++ b/lib/diameter/doc/src/ref_man.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE application SYSTEM "application.dtd">
+
+<application xmlns:xi="http://www.w3.org/2001/XInclude">
+
+<header>
+<copyright>
+<year>2011</year>
+<holder>Ericsson AB. All Rights Reserved.</holder>
+</copyright>
+<legalnotice>
+The contents of this file are subject to the Erlang Public License,
+Version 1.1, (the "License"); you may not use this file except in
+compliance with the License. You should have received a copy of the
+Erlang Public License along with this software. If not, it can be
+retrieved online at http://www.erlang.org/.
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+the License for the specific language governing rights and limitations
+under the License.
+
+</legalnotice>
+
+<title>Diameter Reference Manual</title>
+<prepared></prepared>
+<docno></docno>
+<date></date>
+<rev></rev>
+<file>ref_man.xml</file>
+</header>
+
+<description>
+<p>
+The Diameter application is a framework for building
+applications on top of the Diameter protocol. </p>
+
+</description>
+
+<xi:include href="diameter.xml"/>
+<xi:include href="diameter_compile.xml"/>
+<xi:include href="diameter_app.xml"/>
+<xi:include href="diameter_dict.xml"/>
+<xi:include href="diameter_transport.xml"/>
+<xi:include href="diameter_tcp.xml"/>
+<xi:include href="diameter_sctp.xml"/>
+
+</application>
diff --git a/lib/diameter/doc/src/user_man.xml b/lib/diameter/doc/src/user_man.xml
new file mode 100644
index 0000000000..a6416c7e23
--- /dev/null
+++ b/lib/diameter/doc/src/user_man.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE part SYSTEM "part.dtd">
+
+<part xmlns:xi="http://www.w3.org/2001/XInclude">
+
+<header>
+<copyright>
+<year>2011</year>
+<holder>Ericsson AB. All Rights Reserved.</holder>
+</copyright>
+<legalnotice>
+The contents of this file are subject to the Erlang Public License,
+Version 1.1, (the "License"); you may not use this file except in
+compliance with the License. You should have received a copy of the
+Erlang Public License along with this software. If not, it can be
+retrieved online at http://www.erlang.org/.
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+the License for the specific language governing rights and limitations
+under the License.
+
+</legalnotice>
+
+<title>Diameter Users Guide</title>
+<prepared></prepared>
+<docno></docno>
+<date></date>
+<rev></rev>
+<file>user_man.xml</file>
+</header>
+<description>
+
+<p>
+The diameter application is a framework for building
+applications on top of the Diameter protocol. </p>
+</description>
+
+<xi:include href="diameter_intro.xml"/>
+<xi:include href="diameter_using.xml"/>
+<xi:include href="diameter_examples.xml"/>
+<xi:include href="diameter_soc.xml"/>
+
+</part>
diff --git a/lib/diameter/doc/standard/draft-ietf-dime-capablities-update-07.txt b/lib/diameter/doc/standard/draft-ietf-dime-capablities-update-07.txt
new file mode 100644
index 0000000000..bb7ec2d08c
--- /dev/null
+++ b/lib/diameter/doc/standard/draft-ietf-dime-capablities-update-07.txt
@@ -0,0 +1,392 @@
+
+
+
+Network Working Group K. Jiao
+Internet-Draft Huawei
+Intended status: Standards Track G. Zorn
+Expires: April 27, 2011 Network Zen
+ October 24, 2010
+
+
+ The Diameter Capabilities Update Application
+ draft-ietf-dime-capablities-update-07
+
+Abstract
+
+ This document defines a new Diameter application and associated
+ command codes. The Capabilities Update application is intended to
+ allow the dynamic update of certain Diameter peer capabilities while
+ the peer-to-peer connection is in the open state.
+
+Status of this Memo
+
+ This Internet-Draft is submitted in full conformance with the
+ provisions of BCP 78 and BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF). Note that other groups may also distribute
+ working documents as Internet-Drafts. The list of current Internet-
+ Drafts is at http://datatracker.ietf.org/drafts/current/.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ This Internet-Draft will expire on April 27, 2011.
+
+Copyright Notice
+
+ Copyright (c) 2010 IETF Trust and the persons identified as the
+ document authors. All rights reserved.
+
+ This document is subject to BCP 78 and the IETF Trust's Legal
+ Provisions Relating to IETF Documents
+ (http://trustee.ietf.org/license-info) in effect on the date of
+ publication of this document. Please review these documents
+ carefully, as they describe your rights and restrictions with respect
+ to this document. Code Components extracted from this document must
+ include Simplified BSD License text as described in Section 4.e of
+ the Trust Legal Provisions and are provided without warranty as
+ described in the Simplified BSD License.
+
+
+
+Jiao & Zorn Expires April 27, 2011 [Page 1]
+
+Internet-Draft Diameter Capabilities Update October 2010
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. Specification of Requirements . . . . . . . . . . . . . . . . . 3
+ 3. Diameter Protocol Considerations . . . . . . . . . . . . . . . 3
+ 4. Capabilities Update . . . . . . . . . . . . . . . . . . . . . . 3
+ 4.1. Command-Code Values . . . . . . . . . . . . . . . . . . . . 4
+ 4.1.1. Capabilities-Update-Request . . . . . . . . . . . . . . 5
+ 4.1.2. Capabilities-Update-Answer . . . . . . . . . . . . . . 5
+ 5. Security Considerations . . . . . . . . . . . . . . . . . . . . 6
+ 6. IANA Considerations . . . . . . . . . . . . . . . . . . . . . . 6
+ 6.1. Application Identifier . . . . . . . . . . . . . . . . . . 6
+ 6.2. Command Codes . . . . . . . . . . . . . . . . . . . . . . . 6
+ 7. Contributors . . . . . . . . . . . . . . . . . . . . . . . . . 6
+ 8. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 6
+ 9. References . . . . . . . . . . . . . . . . . . . . . . . . . . 6
+ 9.1. Normative References . . . . . . . . . . . . . . . . . . . 6
+ 9.2. Informative References . . . . . . . . . . . . . . . . . . 7
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 7
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jiao & Zorn Expires April 27, 2011 [Page 2]
+
+Internet-Draft Diameter Capabilities Update October 2010
+
+
+1. Introduction
+
+ Capabilities exchange is an important component of the Diameter Base
+ Protocol [I-D.ietf-dime-rfc3588bis], allowing peers to exchange
+ identities and Diameter capabilities (protocol version number,
+ supported Diameter applications, security mechanisms, etc.). As
+ defined in RFC 3588, however, the capabilities exchange process takes
+ place only once, at the inception of a transport connection between a
+ given pair of peers. Therefore, if a peer's capabilities change (due
+ to software update, for example), the existing connection(s) must be
+ torn down (along with all of the associated user sessions) and
+ restarted before the modified capabilities can be advertised.
+
+ This document defines a new Diameter application intended to allow
+ the dynamic update of a subset of Diameter peer capabilities over an
+ existing connection. Because the Capabilities Update application
+ specified herein operates over an existing transport connection,
+ modification of certain capabilities is prohibited. Specifically,
+ modifying the security mechanism in use is not allowed; if the
+ security method used between a pair of peers is changed the affected
+ connection MUST be restarted.
+
+
+2. Specification of Requirements
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [RFC2119].
+
+
+3. Diameter Protocol Considerations
+
+ This section details the relationship of the Diameter Capabilities
+ Update application to the Diameter Base Protocol.
+
+ This document specifies Diameter Application-ID <TBD1>. Diameter
+ nodes conforming to this specification MUST advertise support by
+ including the value <TBD1> in the Auth-Application-Id of the
+ Capabilities-Exchange-Request (CER) and Capabilities-Exchange-Answer
+ (CEA) commands [I-D.ietf-dime-rfc3588bis].
+
+
+4. Capabilities Update
+
+ When the capabilities of a Diameter node conforming to this
+ specification change, it MUST notify all of the nodes with which it
+ has an open transport connection and which have also advertised
+ support for the Capabilities Update application using the
+
+
+
+Jiao & Zorn Expires April 27, 2011 [Page 3]
+
+Internet-Draft Diameter Capabilities Update October 2010
+
+
+ Capabilities-Update-Request (CUR) message (Section 4.1.1). This
+ message allows the update of a peer's capabilities (supported
+ Diameter applications, etc.).
+
+ A Diameter node only issues a given command to those peers that have
+ advertised support for the Diameter application that defines the
+ command; a Diameter node must cache the supported applications in
+ order to ensure that unrecognized commands and/or Attribute-Value
+ Pairs (AVPs) are not unnecessarily sent to a peer.
+
+ The receiver of the CUR MUST determine common applications by
+ computing the intersection of its own set of supported Application Id
+ against all of the application identifier AVPs (Auth-Application-Id,
+ Acct-Application-Id and Vendor-Specific- Application-Id) present in
+ the CUR. The value of the Vendor-Id AVP in the Vendor-Specific-
+ Application-Id MUST NOT be used during computation.
+
+ If the receiver of a CUR does not have any applications in common
+ with the sender then it MUST return a Capabilities-Update-Answer
+ (CUA) (Section 4.1.2) with the Result-Code AVP set to
+ DIAMETER_NO_COMMON_APPLICATION [I-D.ietf-dime-rfc3588bis], and SHOULD
+ disconnect the transport layer connection; however, if active
+ sessions are using the connection, peers MAY delay disconnection
+ until the sessions can be redirected or gracefully terminated. Note
+ that receiving a CUA from a peer advertising itself as a Relay (see
+ [I-D.ietf-dime-rfc3588bis], Section 2.4) MUST be interpreted as
+ having common applications with the peer.
+
+ As for CER/CEA messages, the CUR and CUA messages MUST NOT be
+ proxied, redirected or relayed.
+
+ Even though the CUR/CUA messages cannot be proxied, it is still
+ possible for an upstream agent to receive a message for which there
+ are no peers available to handle the application that corresponds to
+ the Command-Code. This could happen if, for example, the peers are
+ too busy or down. In such instances, the 'E' bit MUST be set in the
+ answer message with the Result-Code AVP set to
+ DIAMETER_UNABLE_TO_DELIVER to inform the downstream peer to take
+ action (e.g., re-routing requests to an alternate peer).
+
+4.1. Command-Code Values
+
+ This section defines Command-Code [I-D.ietf-dime-rfc3588bis] values
+ that MUST be supported by all Diameter implementations conforming to
+ this specification. The following Command Codes are defined (using
+ modified ABNF [I-D.ietf-dime-rfc3588bis]) in this document:
+ Capabilities-Update-Request (CUR, Section 4.1.1) and Capabilities-
+ Update-Answer (CUA, Section 4.1.2).
+
+
+
+Jiao & Zorn Expires April 27, 2011 [Page 4]
+
+Internet-Draft Diameter Capabilities Update October 2010
+
+
+4.1.1. Capabilities-Update-Request
+
+ The Capabilities-Update-Request (CUR), indicated by the Command-Code
+ set to <CUCC> and the Command Flags' 'R' bit set, is sent to update
+ local capabilities. Upon detection of a transport failure, this
+ message MUST NOT be sent to an alternate peer.
+
+ When Diameter is run over the Stream Control Transmission Protocol
+ [RFC4960], which allows connections to span multiple interfaces and
+ multiple IP addresses, the Capabilities-Update-Request message MUST
+ contain one Host-IP-Address AVP for each potential IP address that
+ may be locally used when transmitting Diameter messages.
+
+ Message Format
+
+ <CUR> ::= < Diameter Header: <CUCC>, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+ 1* { Host-IP-Address }
+ { Vendor-Id }
+ { Product-Name }
+ [ Origin-State-Id ]
+ * [ Supported-Vendor-Id ]
+ * [ Auth-Application-Id ]
+ * [ Acct-Application-Id ]
+ * [ Vendor-Specific-Application-Id ]
+ [ Firmware-Revision ]
+ * [ AVP ]
+
+4.1.2. Capabilities-Update-Answer
+
+ The Capabilities-Update-Answer, indicated by the Command-Code set to
+ <CUCC> and the Command Flags' 'R' bit cleared, is sent in response to
+ a CUR message.
+
+ Message Format
+
+ <CUA> ::= < Diameter Header: <CUCC> >
+ { Origin-Host }
+ { Origin-Realm }
+ { Result-Code }
+ [ Error-Message ]
+ * [ AVP ]
+
+
+
+
+
+
+
+
+Jiao & Zorn Expires April 27, 2011 [Page 5]
+
+Internet-Draft Diameter Capabilities Update October 2010
+
+
+5. Security Considerations
+
+ The security considerations applicable to the Diameter Base Protocol
+ [I-D.ietf-dime-rfc3588bis] are also applicable to this document.
+
+
+6. IANA Considerations
+
+ This section explains the criteria to be used by the IANA for
+ assignment of numbers within namespaces used within this document.
+
+6.1. Application Identifier
+
+ This specification assigns the value <TBD1> from the Application
+ Identifiers namespace [I-D.ietf-dime-rfc3588bis]. See Section 3 for
+ the assignment of the namespace in this specification.
+
+6.2. Command Codes
+
+ This specification assigns the value <CUCC> from the Command Codes
+ namespace [I-D.ietf-dime-rfc3588bis]. See Section 4.1 for the
+ assignment of the namespace in this specification.
+
+
+7. Contributors
+
+ This document is based upon work done by Tina Tsou.
+
+
+8. Acknowledgements
+
+ Thanks to Sebastien Decugis, Niklas Neumann, Subash Comerica, Lionel
+ Morand, Dan Romascanu, Dan Harkins and Ravi for helpful review and
+ discussion.
+
+
+9. References
+
+9.1. Normative References
+
+ [I-D.ietf-dime-rfc3588bis]
+ Fajardo, V., Arkko, J., Loughney, J., and G. Zorn,
+ "Diameter Base Protocol", draft-ietf-dime-rfc3588bis-25
+ (work in progress), September 2010.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+
+
+
+Jiao & Zorn Expires April 27, 2011 [Page 6]
+
+Internet-Draft Diameter Capabilities Update October 2010
+
+
+9.2. Informative References
+
+ [RFC4960] Stewart, R., "Stream Control Transmission Protocol",
+ RFC 4960, September 2007.
+
+
+Authors' Addresses
+
+ Jiao Kang
+ Huawei Technologies
+ Section B1, Huawei Industrial Base
+ Bantian, Longgang District
+ Shenzhen 518129
+ P.R. China
+
+ Phone: +86 755 2878-6690
+
+
+ Glen Zorn
+ Network Zen
+ 227/358 Thanon Sanphawut
+ Bang Na, Bangkok 10260
+ Thailand
+
+ Phone: +66 (0) 87-040-4617
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jiao & Zorn Expires April 27, 2011 [Page 7]
+
diff --git a/lib/diameter/doc/standard/draft-ietf-dime-rfc3588bis-26.txt b/lib/diameter/doc/standard/draft-ietf-dime-rfc3588bis-26.txt
new file mode 100644
index 0000000000..87b9562f93
--- /dev/null
+++ b/lib/diameter/doc/standard/draft-ietf-dime-rfc3588bis-26.txt
@@ -0,0 +1,8681 @@
+
+
+
+DIME V. Fajardo, Ed.
+Internet-Draft Telcordia Technologies
+Obsoletes: 3588 (if approved) J. Arkko
+Intended status: Standards Track Ericsson Research
+Expires: July 24, 2011 J. Loughney
+ Nokia Research Center
+ G. Zorn
+ Network Zen
+ January 20, 2011
+
+
+ Diameter Base Protocol
+ draft-ietf-dime-rfc3588bis-26.txt
+
+Abstract
+
+ The Diameter base protocol is intended to provide an Authentication,
+ Authorization and Accounting (AAA) framework for applications such as
+ network access or IP mobility in both local and roaming situations.
+ This document specifies the message format, transport, error
+ reporting, accounting and security services used by all Diameter
+ applications. The Diameter base protocol as defined in this document
+ must be supported by all Diameter implementations.
+
+Status of this Memo
+
+ This Internet-Draft is submitted in full conformance with the
+ provisions of BCP 78 and BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF). Note that other groups may also distribute
+ working documents as Internet-Drafts. The list of current Internet-
+ Drafts is at http://datatracker.ietf.org/drafts/current/.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ This Internet-Draft will expire on July 24, 2011.
+
+Copyright Notice
+
+ Copyright (c) 2011 IETF Trust and the persons identified as the
+ document authors. All rights reserved.
+
+ This document is subject to BCP 78 and the IETF Trust's Legal
+ Provisions Relating to IETF Documents
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 1]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ (http://trustee.ietf.org/license-info) in effect on the date of
+ publication of this document. Please review these documents
+ carefully, as they describe your rights and restrictions with respect
+ to this document. Code Components extracted from this document must
+ include Simplified BSD License text as described in Section 4.e of
+ the Trust Legal Provisions and are provided without warranty as
+ described in the Simplified BSD License.
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 6
+ 1.1. Diameter Protocol . . . . . . . . . . . . . . . . . . . . 8
+ 1.1.1. Description of the Document Set . . . . . . . . . . . 9
+ 1.1.2. Conventions Used in This Document . . . . . . . . . . 10
+ 1.1.3. Changes from RFC3588 . . . . . . . . . . . . . . . . 10
+ 1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 12
+ 1.3. Approach to Extensibility . . . . . . . . . . . . . . . . 17
+ 1.3.1. Defining New AVP Values . . . . . . . . . . . . . . . 18
+ 1.3.2. Creating New AVPs . . . . . . . . . . . . . . . . . . 18
+ 1.3.3. Creating New Commands . . . . . . . . . . . . . . . . 18
+ 1.3.4. Creating New Diameter Applications . . . . . . . . . 19
+ 2. Protocol Overview . . . . . . . . . . . . . . . . . . . . . . 21
+ 2.1. Transport . . . . . . . . . . . . . . . . . . . . . . . . 22
+ 2.1.1. SCTP Guidelines . . . . . . . . . . . . . . . . . . . 23
+ 2.2. Securing Diameter Messages . . . . . . . . . . . . . . . 24
+ 2.3. Diameter Application Compliance . . . . . . . . . . . . . 24
+ 2.4. Application Identifiers . . . . . . . . . . . . . . . . . 24
+ 2.5. Connections vs. Sessions . . . . . . . . . . . . . . . . 25
+ 2.6. Peer Table . . . . . . . . . . . . . . . . . . . . . . . 26
+ 2.7. Routing Table . . . . . . . . . . . . . . . . . . . . . . 27
+ 2.8. Role of Diameter Agents . . . . . . . . . . . . . . . . . 28
+ 2.8.1. Relay Agents . . . . . . . . . . . . . . . . . . . . 29
+ 2.8.2. Proxy Agents . . . . . . . . . . . . . . . . . . . . 30
+ 2.8.3. Redirect Agents . . . . . . . . . . . . . . . . . . . 31
+ 2.8.4. Translation Agents . . . . . . . . . . . . . . . . . 32
+ 2.9. Diameter Path Authorization . . . . . . . . . . . . . . . 33
+ 3. Diameter Header . . . . . . . . . . . . . . . . . . . . . . . 35
+ 3.1. Command Codes . . . . . . . . . . . . . . . . . . . . . . 38
+ 3.2. Command Code ABNF specification . . . . . . . . . . . . . 38
+ 3.3. Diameter Command Naming Conventions . . . . . . . . . . . 41
+ 4. Diameter AVPs . . . . . . . . . . . . . . . . . . . . . . . . 42
+ 4.1. AVP Header . . . . . . . . . . . . . . . . . . . . . . . 42
+ 4.1.1. Optional Header Elements . . . . . . . . . . . . . . 43
+ 4.2. Basic AVP Data Formats . . . . . . . . . . . . . . . . . 44
+ 4.3. Derived AVP Data Formats . . . . . . . . . . . . . . . . 45
+ 4.3.1. Common Derived AVPs . . . . . . . . . . . . . . . . . 45
+ 4.4. Grouped AVP Values . . . . . . . . . . . . . . . . . . . 52
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 2]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ 4.4.1. Example AVP with a Grouped Data type . . . . . . . . 53
+ 4.5. Diameter Base Protocol AVPs . . . . . . . . . . . . . . . 56
+ 5. Diameter Peers . . . . . . . . . . . . . . . . . . . . . . . 59
+ 5.1. Peer Connections . . . . . . . . . . . . . . . . . . . . 59
+ 5.2. Diameter Peer Discovery . . . . . . . . . . . . . . . . . 60
+ 5.3. Capabilities Exchange . . . . . . . . . . . . . . . . . . 61
+ 5.3.1. Capabilities-Exchange-Request . . . . . . . . . . . . 63
+ 5.3.2. Capabilities-Exchange-Answer . . . . . . . . . . . . 63
+ 5.3.3. Vendor-Id AVP . . . . . . . . . . . . . . . . . . . . 64
+ 5.3.4. Firmware-Revision AVP . . . . . . . . . . . . . . . . 64
+ 5.3.5. Host-IP-Address AVP . . . . . . . . . . . . . . . . . 64
+ 5.3.6. Supported-Vendor-Id AVP . . . . . . . . . . . . . . . 65
+ 5.3.7. Product-Name AVP . . . . . . . . . . . . . . . . . . 65
+ 5.4. Disconnecting Peer connections . . . . . . . . . . . . . 65
+ 5.4.1. Disconnect-Peer-Request . . . . . . . . . . . . . . . 66
+ 5.4.2. Disconnect-Peer-Answer . . . . . . . . . . . . . . . 66
+ 5.4.3. Disconnect-Cause AVP . . . . . . . . . . . . . . . . 66
+ 5.5. Transport Failure Detection . . . . . . . . . . . . . . . 67
+ 5.5.1. Device-Watchdog-Request . . . . . . . . . . . . . . . 67
+ 5.5.2. Device-Watchdog-Answer . . . . . . . . . . . . . . . 67
+ 5.5.3. Transport Failure Algorithm . . . . . . . . . . . . . 68
+ 5.5.4. Failover and Failback Procedures . . . . . . . . . . 68
+ 5.6. Peer State Machine . . . . . . . . . . . . . . . . . . . 69
+ 5.6.1. Incoming connections . . . . . . . . . . . . . . . . 71
+ 5.6.2. Events . . . . . . . . . . . . . . . . . . . . . . . 72
+ 5.6.3. Actions . . . . . . . . . . . . . . . . . . . . . . . 73
+ 5.6.4. The Election Process . . . . . . . . . . . . . . . . 75
+ 6. Diameter message processing . . . . . . . . . . . . . . . . . 76
+ 6.1. Diameter Request Routing Overview . . . . . . . . . . . . 76
+ 6.1.1. Originating a Request . . . . . . . . . . . . . . . . 77
+ 6.1.2. Sending a Request . . . . . . . . . . . . . . . . . . 77
+ 6.1.3. Receiving Requests . . . . . . . . . . . . . . . . . 78
+ 6.1.4. Processing Local Requests . . . . . . . . . . . . . . 78
+ 6.1.5. Request Forwarding . . . . . . . . . . . . . . . . . 78
+ 6.1.6. Request Routing . . . . . . . . . . . . . . . . . . . 78
+ 6.1.7. Predictive Loop Avoidance . . . . . . . . . . . . . . 79
+ 6.1.8. Redirecting Requests . . . . . . . . . . . . . . . . 79
+ 6.1.9. Relaying and Proxying Requests . . . . . . . . . . . 80
+ 6.2. Diameter Answer Processing . . . . . . . . . . . . . . . 82
+ 6.2.1. Processing received Answers . . . . . . . . . . . . . 82
+ 6.2.2. Relaying and Proxying Answers . . . . . . . . . . . . 82
+ 6.3. Origin-Host AVP . . . . . . . . . . . . . . . . . . . . . 83
+ 6.4. Origin-Realm AVP . . . . . . . . . . . . . . . . . . . . 83
+ 6.5. Destination-Host AVP . . . . . . . . . . . . . . . . . . 83
+ 6.6. Destination-Realm AVP . . . . . . . . . . . . . . . . . . 84
+ 6.7. Routing AVPs . . . . . . . . . . . . . . . . . . . . . . 84
+ 6.7.1. Route-Record AVP . . . . . . . . . . . . . . . . . . 84
+ 6.7.2. Proxy-Info AVP . . . . . . . . . . . . . . . . . . . 84
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 3]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ 6.7.3. Proxy-Host AVP . . . . . . . . . . . . . . . . . . . 85
+ 6.7.4. Proxy-State AVP . . . . . . . . . . . . . . . . . . . 85
+ 6.8. Auth-Application-Id AVP . . . . . . . . . . . . . . . . . 85
+ 6.9. Acct-Application-Id AVP . . . . . . . . . . . . . . . . . 85
+ 6.10. Inband-Security-Id AVP . . . . . . . . . . . . . . . . . 85
+ 6.11. Vendor-Specific-Application-Id AVP . . . . . . . . . . . 86
+ 6.12. Redirect-Host AVP . . . . . . . . . . . . . . . . . . . . 87
+ 6.13. Redirect-Host-Usage AVP . . . . . . . . . . . . . . . . . 87
+ 6.14. Redirect-Max-Cache-Time AVP . . . . . . . . . . . . . . . 88
+ 7. Error Handling . . . . . . . . . . . . . . . . . . . . . . . 90
+ 7.1. Result-Code AVP . . . . . . . . . . . . . . . . . . . . . 92
+ 7.1.1. Informational . . . . . . . . . . . . . . . . . . . . 92
+ 7.1.2. Success . . . . . . . . . . . . . . . . . . . . . . . 93
+ 7.1.3. Protocol Errors . . . . . . . . . . . . . . . . . . . 93
+ 7.1.4. Transient Failures . . . . . . . . . . . . . . . . . 94
+ 7.1.5. Permanent Failures . . . . . . . . . . . . . . . . . 95
+ 7.2. Error Bit . . . . . . . . . . . . . . . . . . . . . . . . 98
+ 7.3. Error-Message AVP . . . . . . . . . . . . . . . . . . . . 99
+ 7.4. Error-Reporting-Host AVP . . . . . . . . . . . . . . . . 99
+ 7.5. Failed-AVP AVP . . . . . . . . . . . . . . . . . . . . . 99
+ 7.6. Experimental-Result AVP . . . . . . . . . . . . . . . . . 100
+ 7.7. Experimental-Result-Code AVP . . . . . . . . . . . . . . 100
+ 8. Diameter User Sessions . . . . . . . . . . . . . . . . . . . 101
+ 8.1. Authorization Session State Machine . . . . . . . . . . . 102
+ 8.2. Accounting Session State Machine . . . . . . . . . . . . 107
+ 8.3. Server-Initiated Re-Auth . . . . . . . . . . . . . . . . 112
+ 8.3.1. Re-Auth-Request . . . . . . . . . . . . . . . . . . . 112
+ 8.3.2. Re-Auth-Answer . . . . . . . . . . . . . . . . . . . 113
+ 8.4. Session Termination . . . . . . . . . . . . . . . . . . . 114
+ 8.4.1. Session-Termination-Request . . . . . . . . . . . . . 115
+ 8.4.2. Session-Termination-Answer . . . . . . . . . . . . . 115
+ 8.5. Aborting a Session . . . . . . . . . . . . . . . . . . . 116
+ 8.5.1. Abort-Session-Request . . . . . . . . . . . . . . . . 116
+ 8.5.2. Abort-Session-Answer . . . . . . . . . . . . . . . . 117
+ 8.6. Inferring Session Termination from Origin-State-Id . . . 118
+ 8.7. Auth-Request-Type AVP . . . . . . . . . . . . . . . . . . 118
+ 8.8. Session-Id AVP . . . . . . . . . . . . . . . . . . . . . 119
+ 8.9. Authorization-Lifetime AVP . . . . . . . . . . . . . . . 120
+ 8.10. Auth-Grace-Period AVP . . . . . . . . . . . . . . . . . . 121
+ 8.11. Auth-Session-State AVP . . . . . . . . . . . . . . . . . 121
+ 8.12. Re-Auth-Request-Type AVP . . . . . . . . . . . . . . . . 121
+ 8.13. Session-Timeout AVP . . . . . . . . . . . . . . . . . . . 122
+ 8.14. User-Name AVP . . . . . . . . . . . . . . . . . . . . . . 122
+ 8.15. Termination-Cause AVP . . . . . . . . . . . . . . . . . . 122
+ 8.16. Origin-State-Id AVP . . . . . . . . . . . . . . . . . . . 124
+ 8.17. Session-Binding AVP . . . . . . . . . . . . . . . . . . . 124
+ 8.18. Session-Server-Failover AVP . . . . . . . . . . . . . . . 125
+ 8.19. Multi-Round-Time-Out AVP . . . . . . . . . . . . . . . . 126
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 4]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ 8.20. Class AVP . . . . . . . . . . . . . . . . . . . . . . . . 126
+ 8.21. Event-Timestamp AVP . . . . . . . . . . . . . . . . . . . 126
+ 9. Accounting . . . . . . . . . . . . . . . . . . . . . . . . . 127
+ 9.1. Server Directed Model . . . . . . . . . . . . . . . . . . 127
+ 9.2. Protocol Messages . . . . . . . . . . . . . . . . . . . . 128
+ 9.3. Accounting Application Extension and Requirements . . . . 128
+ 9.4. Fault Resilience . . . . . . . . . . . . . . . . . . . . 129
+ 9.5. Accounting Records . . . . . . . . . . . . . . . . . . . 129
+ 9.6. Correlation of Accounting Records . . . . . . . . . . . . 130
+ 9.7. Accounting Command-Codes . . . . . . . . . . . . . . . . 131
+ 9.7.1. Accounting-Request . . . . . . . . . . . . . . . . . 131
+ 9.7.2. Accounting-Answer . . . . . . . . . . . . . . . . . . 132
+ 9.8. Accounting AVPs . . . . . . . . . . . . . . . . . . . . . 133
+ 9.8.1. Accounting-Record-Type AVP . . . . . . . . . . . . . 133
+ 9.8.2. Acct-Interim-Interval AVP . . . . . . . . . . . . . . 134
+ 9.8.3. Accounting-Record-Number AVP . . . . . . . . . . . . 135
+ 9.8.4. Acct-Session-Id AVP . . . . . . . . . . . . . . . . . 135
+ 9.8.5. Acct-Multi-Session-Id AVP . . . . . . . . . . . . . . 135
+ 9.8.6. Accounting-Sub-Session-Id AVP . . . . . . . . . . . . 135
+ 9.8.7. Accounting-Realtime-Required AVP . . . . . . . . . . 136
+ 10. AVP Occurrence Table . . . . . . . . . . . . . . . . . . . . 137
+ 10.1. Base Protocol Command AVP Table . . . . . . . . . . . . . 137
+ 10.2. Accounting AVP Table . . . . . . . . . . . . . . . . . . 138
+ 11. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 140
+ 11.1. Changes to AVP Header Allocation . . . . . . . . . . . . 140
+ 11.2. Diameter Header . . . . . . . . . . . . . . . . . . . . . 140
+ 11.3. AVP Values . . . . . . . . . . . . . . . . . . . . . . . 140
+ 11.3.1. Experimental-Result-Code AVP . . . . . . . . . . . . 140
+ 11.4. Diameter TCP, SCTP, TLS/TCP and DTLS/SCTP Port Numbers . 141
+ 11.5. S-NAPTR Parameters . . . . . . . . . . . . . . . . . . . 141
+ 12. Diameter protocol related configurable parameters . . . . . . 142
+ 13. Security Considerations . . . . . . . . . . . . . . . . . . . 143
+ 13.1. TLS/TCP and DTLS/SCTP Usage . . . . . . . . . . . . . . . 143
+ 13.2. Peer-to-Peer Considerations . . . . . . . . . . . . . . . 144
+ 14. References . . . . . . . . . . . . . . . . . . . . . . . . . 145
+ 14.1. Normative References . . . . . . . . . . . . . . . . . . 145
+ 14.2. Informational References . . . . . . . . . . . . . . . . 147
+ Appendix A. Acknowledgements . . . . . . . . . . . . . . . . . . 149
+ A.1. RFC3588bis . . . . . . . . . . . . . . . . . . . . . . . 149
+ A.2. RFC3588 . . . . . . . . . . . . . . . . . . . . . . . . . 150
+ Appendix B. S-NAPTR Example . . . . . . . . . . . . . . . . . . 151
+ Appendix C. Duplicate Detection . . . . . . . . . . . . . . . . 152
+ Appendix D. Internationalized Domain Names . . . . . . . . . . . 154
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 155
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 5]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+1. Introduction
+
+ Authentication, Authorization and Accounting (AAA) protocols such as
+ TACACS [RFC1492] and RADIUS [RFC2865] were initially deployed to
+ provide dial-up PPP [RFC1661] and terminal server access. Over time,
+ AAA support was needed on many new access technologies, the scale and
+ complexity of AAA networks grew, and AAA was also used on new
+ applications (such as voice over IP). This lead to new demands on
+ AAA protocols.
+
+ Network access requirements for AAA protocols are summarized in
+ [RFC2989]. These include:
+
+
+ Failover
+
+ [RFC2865] does not define failover mechanisms, and as a result,
+ failover behavior differs between implementations. In order to
+ provide well-defined failover behavior, Diameter supports
+ application-layer acknowledgements, and defines failover
+ algorithms and the associated state machine. This is described in
+ Section 5.5 and [RFC3539].
+
+ Transmission-level security
+
+ [RFC2865] defines an application-layer authentication and
+ integrity scheme that is required only for use with Response
+ packets. While [RFC2869] defines an additional authentication and
+ integrity mechanism, use is only required during Extensible
+ Authentication Protocol (EAP) sessions. While attribute-hiding is
+ supported, [RFC2865] does not provide support for per-packet
+ confidentiality. In accounting, [RFC2866] assumes that replay
+ protection is provided by the backend billing server, rather than
+ within the protocol itself.
+
+ While [RFC3162] defines the use of IPsec with RADIUS, support for
+ IPsec is not required. In order to provide universal support for
+ transmission-level security, and enable both intra- and inter-
+ domain AAA deployments, Diameter provides support for TLS/TCP and
+ DTLS/SCTP. Security is discussed in Section 13.
+
+
+ Reliable transport
+
+
+ RADIUS runs over UDP, and does not define retransmission behavior;
+ as a result, reliability varies between implementations. As
+ described in [RFC2975], this is a major issue in accounting, where
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 6]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ packet loss may translate directly into revenue loss. In order to
+ provide well defined transport behavior, Diameter runs over
+ reliable transport mechanisms (TCP, SCTP) as defined in [RFC3539].
+
+
+ Agent support
+
+ [RFC2865] does not provide for explicit support for agents,
+ including Proxies, Redirects and Relays. Since the expected
+ behavior is not defined, it varies between implementations.
+ Diameter defines agent behavior explicitly; this is described in
+ Section 2.8.
+
+
+ Server-initiated messages
+
+ While RADIUS server-initiated messages are defined in [RFC5176],
+ support is optional. This makes it difficult to implement
+ features such as unsolicited disconnect or re-authentication/
+ re-authorization on demand across a heterogeneous deployment. To
+ tackle this issue, support for server-initiated messages is
+ mandatory in Diameter.
+
+
+ Transition support
+
+ While Diameter does not share a common protocol data unit (PDU)
+ with RADIUS, considerable effort has been expended in enabling
+ backward compatibility with RADIUS, so that the two protocols may
+ be deployed in the same network. Initially, it is expected that
+ Diameter will be deployed within new network devices, as well as
+ within gateways enabling communication between legacy RADIUS
+ devices and Diameter agents. This capability enables Diameter
+ support to be added to legacy networks, by addition of a gateway
+ or server speaking both RADIUS and Diameter.
+
+ In addition to addressing the above requirements, Diameter also
+ provides support for the following:
+
+
+ Capability negotiation
+
+ RADIUS does not support error messages, capability negotiation, or
+ a mandatory/non-mandatory flag for attributes. Since RADIUS
+ clients and servers are not aware of each other's capabilities,
+ they may not be able to successfully negotiate a mutually
+ acceptable service, or in some cases, even be aware of what
+ service has been implemented. Diameter includes support for error
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 7]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ handling (Section 7), capability negotiation (Section 5.3), and
+ mandatory/non-mandatory Attribute-Value Pairs (AVPs) (Section
+ 4.1).
+
+
+ Peer discovery and configuration
+
+ RADIUS implementations typically require that the name or address
+ of servers or clients be manually configured, along with the
+ corresponding shared secrets. This results in a large
+ administrative burden, and creates the temptation to reuse the
+ RADIUS shared secret, which can result in major security
+ vulnerabilities if the Request Authenticator is not globally and
+ temporally unique as required in [RFC2865]. Through DNS, Diameter
+ enables dynamic discovery of peers (see Section 5.2). Derivation
+ of dynamic session keys is enabled via transmission-level
+ security.
+
+
+ Over time, the capabilities of Network Access Server (NAS) devices
+ have increased substantially. As a result, while Diameter is a
+ considerably more sophisticated protocol than RADIUS, it remains
+ feasible to implement it within embedded devices.
+
+1.1. Diameter Protocol
+
+ The Diameter base protocol provides the following facilities:
+
+ o Ability to exchange messages and deliver AVPs
+
+ o Capabilities negotiation
+
+ o Error notification
+
+ o Extensibility, through addition of new applications, commands and
+ AVPs (required in [RFC2989]).
+
+ o Basic services necessary for applications, such as handling of
+ user sessions or accounting
+
+ All data delivered by the protocol is in the form of AVPs. Some of
+ these AVP values are used by the Diameter protocol itself, while
+ others deliver data associated with particular applications that
+ employ Diameter. AVPs may be arbitrarily added to Diameter messages,
+ the only restriction being that the Augmented Backus-Naur Form (ABNF,
+ [RFC5234]) Command Code syntax specification (Section 3.2) is
+ satisfied. AVPs are used by the base Diameter protocol to support
+ the following required features:
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 8]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ o Transporting of user authentication information, for the purposes
+ of enabling the Diameter server to authenticate the user.
+
+ o Transporting of service-specific authorization information,
+ between client and servers, allowing the peers to decide whether a
+ user's access request should be granted.
+
+ o Exchanging resource usage information, which may be used for
+ accounting purposes, capacity planning, etc.
+
+ o Routing, relaying, proxying and redirecting of Diameter messages
+ through a server hierarchy.
+
+ The Diameter base protocol satisfies the minimum requirements for an
+ AAA protocol, as specified by [RFC2989]. The base protocol may be
+ used by itself for accounting purposes only, or it may be used with a
+ Diameter application, such as Mobile IPv4 [RFC4004], or network
+ access [RFC4005]. It is also possible for the base protocol to be
+ extended for use in new applications, via the addition of new
+ commands or AVPs. The initial focus of Diameter was network access
+ and accounting applications. A truly generic AAA protocol used by
+ many applications might provide functionality not provided by
+ Diameter. Therefore, it is imperative that the designers of new
+ applications understand their requirements before using Diameter.
+ See Section 2.4 for more information on Diameter applications.
+
+ Any node can initiate a request. In that sense, Diameter is a peer-
+ to-peer protocol. In this document, a Diameter Client is a device at
+ the edge of the network that performs access control, such as a
+ Network Access Server (NAS) or a Foreign Agent (FA). A Diameter
+ client generates Diameter messages to request authentication,
+ authorization, and accounting services for the user. A Diameter
+ agent is a node that does not provide local user authentication or
+ authorization services; agents include proxies, redirects and relay
+ agents. A Diameter server performs authentication and/or
+ authorization of the user. A Diameter node may act as an agent for
+ certain requests while acting as a server for others.
+
+ The Diameter protocol also supports server-initiated messages, such
+ as a request to abort service to a particular user.
+
+1.1.1. Description of the Document Set
+
+ The Diameter specification consists of an updated version of the base
+ protocol specification (this document) and the Transport Profile
+ [RFC3539]. This document obsoletes RFC 3588. A summary of the base
+ protocol updates included in this document can be found in
+ Section 1.1.3.
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 9]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ This document defines the base protocol specification for AAA, which
+ includes support for accounting. There are also a myriad of
+ applications documents describing applications that use this base
+ specification for Authentication, Authorization and Accounting.
+ These application documents specify how to use the Diameter protocol
+ within the context of their application.
+
+ The Transport Profile document [RFC3539] discusses transport layer
+ issues that arise with AAA protocols and recommendations on how to
+ overcome these issues. This document also defines the Diameter
+ failover algorithm and state machine.
+
+ Clarifications on the Routing of Diameter Request based on Username
+ and the Realm [RFC5729] defines specific behavior on how to route
+ request based on the content of the User-Name AVP (Attribute Value
+ Pair).
+
+1.1.2. Conventions Used in This Document
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC2119].
+
+1.1.3. Changes from RFC3588
+
+ This document obsoletes RFC 3588 but is fully backward compatible
+ with that document. The changes introduced in this document focus on
+ fixing issues that have surfaced during implementation of [RFC3588].
+ An overview of some the major changes are given below.
+
+ o Deprecated the use of Inband-Security AVP for negotiating
+ transport layer security. It has been generally considered that
+ bootstrapping of TLS via Inband-Security AVP creates certain
+ security risk because it does not completely protect the
+ information carried in the CER (Capabilities Exchange Request)/CEA
+ (Capabilities Exchange Answer). This version of Diameter adopted
+ a common approach of defining a well-known secured port that peers
+ should use when communicating via TLS/TCP and DTLS/SCTP. This new
+ approach augments the existing Inband-Security negotiation but
+ does not completely replace it. The old method is kept for
+ backwards compatibility reasons.
+
+ o Deprecated the exchange of CER/CEA messages in the open state.
+ This feature was implied in the peer state machine table of
+ [RFC3588] but it was not clearly defined anywhere else in that
+ document. As work on this document progressed, it became clear
+ that the multiplicity of meaning and use of Application Id AVPs in
+ the CER/CEA messages (and the messages themselves) is seen as an
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 10]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ abuse of the Diameter extensibility rules and thus required
+ simplification. It is assumed that the capabilities exchange in
+ the open state will be re-introduced in a separate specification
+ which clearly defines new commands for this feature.
+
+ o Simplified Security Requirements. The use of a secured transport
+ for exchanging Diameter messages remains mandatory. However, TLS/
+ TCP and DTLS/SCTP has become the primary method of securing
+ Diameter and IPsec is a secondary alternative. See Section 13 for
+ details. The support for the End-to-End security framework
+ (E2ESequence AVP and 'P'-bit in the AVP header) has also been
+ deprecated.
+
+ o Diameter Extensibility Changes. This includes fixes to the
+ Diameter extensibility description (Section 1.3 and others) to
+ better aid Diameter application designers; in addition, the new
+ specification relaxes the policy with respect to the allocation of
+ command codes for vendor-specific uses.
+
+ o Application Id Usage. Clarify the proper use of Application Id
+ information which can be found in multiple places within a
+ Diameter message. This includes correlating Application Ids found
+ in the message headers and AVPs. These changes also clearly
+ specify the proper Application Id value to use for specific base
+ protocol messages (ASR/ASA, STR/STA) as well as clarifying the
+ content and use of Vendor-Specific-Application-Id.
+
+ o Routing Fixes. This document more clearly specifies what
+ information (AVPs and Application Id) can be used for making
+ general routing decisions. A rule for the prioritization of
+ redirect routing criteria when multiple route entries are found
+ via redirects has also been added (See Section 6.13 for details).
+
+ o Simplification of Diameter Peer Discovery. The Diameter discovery
+ process now supports only widely used discovery schemes; the rest
+ have been deprecated (see Section 5.2 for details).
+
+ There are many other many miscellaneous fixes that have been
+ introduced in this document that may not be considered significant
+ but they are important nonetheless. Examples are removal of obsolete
+ types, fixes to command ABNFs, fixes to the state machine,
+ clarification of the election process, message validation, fixes to
+ Failed-AVP and Result-Code AVP values, etc. A comprehensive list of
+ changes is not shown here for practical reasons.
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 11]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+1.2. Terminology
+
+ AAA
+
+ Authentication, Authorization and Accounting.
+
+
+ ABNF
+
+ Augmented Backus-Naur Form [RFC5234]. A metalanguage with its own
+ formal syntax and rules. It is based on the Backus-Naur Form and
+ is used to define message exchanges in a bi-directional
+ communications protocol.
+
+
+ Accounting
+
+ The act of collecting information on resource usage for the
+ purpose of capacity planning, auditing, billing or cost
+ allocation.
+
+
+ Accounting Record
+
+ An accounting record represents a summary of the resource
+ consumption of a user over the entire session. Accounting servers
+ creating the accounting record may do so by processing interim
+ accounting events or accounting events from several devices
+ serving the same user.
+
+
+ Authentication
+
+ The act of verifying the identity of an entity (subject).
+
+
+ Authorization
+
+ The act of determining whether a requesting entity (subject) will
+ be allowed access to a resource (object).
+
+
+ AVP
+
+ The Diameter protocol consists of a header followed by one or more
+ Attribute-Value-Pairs (AVPs). An AVP includes a header and is
+ used to encapsulate protocol-specific data (e.g., routing
+ information) as well as authentication, authorization or
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 12]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ accounting information.
+
+
+ Diameter Agent
+
+ A Diameter Agent is a Diameter Node that provides either relay,
+ proxy, redirect or translation services.
+
+
+ Diameter Client
+
+ A Diameter Client is a Diameter Node that supports Diameter client
+ applications as well as the base protocol. Diameter Clients are
+ often implemented in devices situated at the edge of a network and
+ provide access control services for that network. Typical
+ examples of Diameter Clients include the Network Access Server
+ (NAS) and the Mobile IP Foreign Agent (FA).
+
+
+ Diameter Node
+
+ A Diameter Node is a host process that implements the Diameter
+ protocol, and acts either as a Client, Agent or Server.
+
+
+ Diameter Peer
+
+ If a Diameter Node shares a direct transport connection with
+ another Diameter Node, it is a Diameter Peer to that Diameter
+ Node.
+
+
+ Diameter Server
+
+ A Diameter Server is a Diameter Node that handles authentication,
+ authorization and accounting requests for a particular realm. By
+ its very nature, a Diameter Server must support Diameter server
+ applications in addition to the base protocol.
+
+
+ Downstream
+
+ Downstream is used to identify the direction of a particular
+ Diameter message from the Home Server towards the Diameter Client.
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 13]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Home Realm
+
+ A Home Realm is the administrative domain with which the user
+ maintains an account relationship.
+
+
+ Home Server
+
+ A Diameter Server which serves the Home Realm.
+
+
+ Interim accounting
+
+ An interim accounting message provides a snapshot of usage during
+ a user's session. It is typically implemented in order to provide
+ for partial accounting of a user's session in the case a device
+ reboot or other network problem prevents the delivery of a session
+ summary message or session record.
+
+
+ Local Realm
+
+ A local realm is the administrative domain providing services to a
+ user. An administrative domain may act as a local realm for
+ certain users, while being a home realm for others.
+
+
+ Multi-session
+
+ A multi-session represents a logical linking of several sessions.
+ Multi-sessions are tracked by using the Acct-Multi-Session-Id. An
+ example of a multi-session would be a Multi-link PPP bundle. Each
+ leg of the bundle would be a session while the entire bundle would
+ be a multi-session.
+
+
+ Network Access Identifier
+
+ The Network Access Identifier, or NAI [RFC4282], is used in the
+ Diameter protocol to extract a user's identity and realm. The
+ identity is used to identify the user during authentication and/or
+ authorization, while the realm is used for message routing
+ purposes.
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 14]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Proxy Agent or Proxy
+
+ In addition to forwarding requests and responses, proxies make
+ policy decisions relating to resource usage and provisioning.
+ This is typically accomplished by tracking the state of NAS
+ devices. While proxies typically do not respond to client
+ Requests prior to receiving a Response from the server, they may
+ originate Reject messages in cases where policies are violated.
+ As a result, proxies need to understand the semantics of the
+ messages passing through them, and may not support all Diameter
+ applications.
+
+
+ Realm
+
+ The string in the NAI that immediately follows the '@' character.
+ NAI realm names are required to be unique, and are piggybacked on
+ the administration of the DNS namespace. Diameter makes use of
+ the realm, also loosely referred to as domain, to determine
+ whether messages can be satisfied locally, or whether they must be
+ routed or redirected. In RADIUS, realm names are not necessarily
+ piggybacked on the DNS namespace but may be independent of it.
+
+
+ Real-time Accounting
+
+ Real-time accounting involves the processing of information on
+ resource usage within a defined time window. Time constraints are
+ typically imposed in order to limit financial risk. The Diameter
+ Credit Control Application [RFC4006] is an example of an
+ application that defines real-time accounting functionality.
+
+
+ Relay Agent or Relay
+
+ Relays forward requests and responses based on routing-related
+ AVPs and routing table entries. Since relays do not make policy
+ decisions, they do not examine or alter non-routing AVPs. As a
+ result, relays never originate messages, do not need to understand
+ the semantics of messages or non-routing AVPs, and are capable of
+ handling any Diameter application or message type. Since relays
+ make decisions based on information in routing AVPs and realm
+ forwarding tables they do not keep state on NAS resource usage or
+ sessions in progress.
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 15]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Redirect Agent
+
+ Rather than forwarding requests and responses between clients and
+ servers, redirect agents refer clients to servers and allow them
+ to communicate directly. Since redirect agents do not sit in the
+ forwarding path, they do not alter any AVPs transiting between
+ client and server. Redirect agents do not originate messages and
+ are capable of handling any message type, although they may be
+ configured only to redirect messages of certain types, while
+ acting as relay or proxy agents for other types. As with proxy
+ agents, redirect agents do not keep state with respect to sessions
+ or NAS resources.
+
+
+ Session
+
+ A session is a related progression of events devoted to a
+ particular activity. Diameter application documents provide
+ guidelines as to when a session begins and ends. All Diameter
+ packets with the same Session-Id are considered to be part of the
+ same session.
+
+
+ Stateful Agent
+
+ A stateful agent is one that maintains session state information,
+ by keeping track of all authorized active sessions. Each
+ authorized session is bound to a particular service, and its state
+ is considered active either until it is notified otherwise, or by
+ expiration.
+
+
+ Sub-session
+
+ A sub-session represents a distinct service (e.g., QoS or data
+ characteristics) provided to a given session. These services may
+ happen concurrently (e.g., simultaneous voice and data transfer
+ during the same session) or serially. These changes in sessions
+ are tracked with the Accounting-Sub-Session-Id.
+
+
+ Transaction state
+
+ The Diameter protocol requires that agents maintain transaction
+ state, which is used for failover purposes. Transaction state
+ implies that upon forwarding a request, the Hop-by-Hop identifier
+ is saved; the field is replaced with a locally unique identifier,
+ which is restored to its original value when the corresponding
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 16]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ answer is received. The request's state is released upon receipt
+ of the answer. A stateless agent is one that only maintains
+ transaction state.
+
+
+ Translation Agent
+
+ A translation agent is a stateful Diameter node that performs
+ protocol translation between Diameter and another AAA protocol,
+ such as RADIUS.
+
+
+ Transport Connection
+
+ A transport connection is a TCP or SCTP connection existing
+ directly between two Diameter peers, otherwise known as a Peer-to-
+ Peer Connection.
+
+
+ Upstream
+
+ Upstream is used to identify the direction of a particular
+ Diameter message from the Diameter Client towards the Home Server.
+
+
+ User
+
+ The entity or device requesting or using some resource, in support
+ of which a Diameter client has generated a request.
+
+
+1.3. Approach to Extensibility
+
+ The Diameter protocol is designed to be extensible, using several
+ mechanisms, including:
+
+ o Defining new AVP values
+
+ o Creating new AVPs
+
+ o Creating new commands
+
+ o Creating new applications
+
+ From the point of view of extensibility Diameter authentication,
+ authorization and accounting applications are treated in the same
+ way.
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 17]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Note: Protocol designers should try to re-use existing functionality,
+ namely AVP values, AVPs, commands, and Diameter applications. Reuse
+ simplifies standardization and implementation. To avoid potential
+ interoperability issues it is important to ensure that the semantics
+ of the re-used features are well understood. Given that Diameter can
+ also carry RADIUS attributes as Diameter AVPs, such re-use
+ considerations apply also to existing RADIUS attributes that may be
+ useful in a Diameter application.
+
+1.3.1. Defining New AVP Values
+
+ In order to allocate a new AVP value for AVPs defined in the Diameter
+ Base protocol, the IETF needs to approve a new RFC that describes the
+ AVP value. IANA considerations for these AVP values are discussed in
+ Section 11.4.
+
+ The allocation of AVP values for other AVPs is guided by the IANA
+ considerations of the document that defines those AVPs. Typically,
+ allocation of new values for an AVP defined in an IETF RFC should
+ require IETF Review [RFC5226], whereas values for vendor-specific
+ AVPs can be allocated by the vendor.
+
+1.3.2. Creating New AVPs
+
+ A new AVP being defined MUST use one of the data types listed in
+ Section 4.2 or Section 4.3. If an appropriate derived data type is
+ already defined, it SHOULD be used instead of a base data type to
+ encourage reusability and good design practice.
+
+ In the event that a logical grouping of AVPs is necessary, and
+ multiple "groups" are possible in a given command, it is recommended
+ that a Grouped AVP be used (see Section 4.4).
+
+ The creation of new AVPs can happen in various ways. The recommended
+ approach is to define a new general-purpose AVP in a standards track
+ RFC approved by the IETF. However, as described in Section 11.1.1
+ there are also other mechanisms.
+
+1.3.3. Creating New Commands
+
+ A new Command Code MUST be allocated when required AVPs (those
+ indicated as {AVP} in the ABNF definition) are added to, deleted from
+ or redefined in (for example, by changing a required AVP into an
+ optional one) an existing command.
+
+ Furthermore, if the transport characteristics of a command are
+ changed (for example, with respect to the number of round trips
+ required) a new Command Code MUST be registered.
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 18]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ A change to the ABNF of a command, such as described above, MUST
+ result in the definition of a new Command Code. This subsequently
+ leads to the need to define a new Diameter Application for any
+ application that will use that new Command.
+
+ The IANA considerations for commands are discussed in Section 11.2.1.
+
+1.3.4. Creating New Diameter Applications
+
+ Every Diameter application specification MUST have an IANA assigned
+ Application Id (see Section 2.4 and Section 11.3). The managed
+ Application Id space is flat and there is no relationship between
+ different Diameter applications with respect to their Application
+ Ids. As such, there is no versioning support provided by these
+ application Ids itself; every Diameter application is a standalone
+ application. If the application has a relationship with other
+ Diameter applications, such a relationship is not known to Diameter.
+
+ Before describing the rules for creating new Diameter applications it
+ is important to discuss the semantics of the AVPs occurrences as
+ stated in the ABNF and the M-bit flag (Section 4.1) for an AVP.
+ There is no relationship imposed between the two; they are set
+ independently.
+
+ o The ABNF indicates what AVPs are placed into a Diameter Command by
+ the sender of that Command. Often, since there are multiple modes
+ of protocol interactions many of the AVPs are indicated as
+ optional.
+
+ o The M-bit allows the sender to indicate to the receiver whether or
+ not understanding the semantics of an AVP and its content is
+ mandatory. If the M-bit is set by the sender and the receiver
+ does not understand the AVP or the values carried within that AVP
+ then a failure is generated (see Section 7).
+
+ It is the decision of the protocol designer when to develop a new
+ Diameter application rather than extending Diameter in other ways.
+ However, a new Diameter application MUST be created when one or more
+ of the following criteria are met:
+
+
+ M-bit Setting
+
+ An AVP with the M-bit in the MUST column of the AVP flag table is
+ added to an existing Command/Application.
+
+ An AVP with the M-bit in the MAY column of the AVP flag table is
+ added to an existing Command/Application.
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 19]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Note: The M-bit setting for a given AVP is relevant to an
+ Application and each command within that application which
+ includes the AVP. That is, if an AVP appears in two commands for
+ application Foo and the M-bit settings are different in each
+ command, then there should be two AVP flag tables describing when
+ to set the M-bit.
+
+ Commands
+
+ A new command is used within the existing application either
+ because an additional command is added, an existing command has
+ been modified so that a new Command Code had to be registered, or
+ a command has been deleted.
+
+ If the ABNF definition of a command allows it, an implementation may
+ add arbitrary optional AVPs with the M-bit cleared (including vendor-
+ specific AVPs) to that command without needing to define a new
+ application. Please refer to Section 11.1.1 for details.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 20]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+2. Protocol Overview
+
+ The base Diameter protocol concerns itself with establishing
+ connections to peers, capabilities negotiation, how messages are sent
+ and routed through peers, and how the connections are eventually torn
+ down. The base protocol also defines certain rules that apply to all
+ message exchanges between Diameter nodes.
+
+ Communication between Diameter peers begins with one peer sending a
+ message to another Diameter peer. The set of AVPs included in the
+ message is determined by a particular Diameter application. One AVP
+ that is included to reference a user's session is the Session-Id.
+
+ The initial request for authentication and/or authorization of a user
+ would include the Session-Id AVP. The Session-Id is then used in all
+ subsequent messages to identify the user's session (see Section 8 for
+ more information). The communicating party may accept the request,
+ or reject it by returning an answer message with the Result-Code AVP
+ set to indicate an error occurred. The specific behavior of the
+ Diameter server or client receiving a request depends on the Diameter
+ application employed.
+
+ Session state (associated with a Session-Id) MUST be freed upon
+ receipt of the Session-Termination-Request, Session-Termination-
+ Answer, expiration of authorized service time in the Session-Timeout
+ AVP, and according to rules established in a particular Diameter
+ application.
+
+ The base Diameter protocol may be used by itself for accounting
+ applications. For authentication and authorization, it is always
+ extended for a particular application.
+
+ Diameter Clients MUST support the base protocol, which includes
+ accounting. In addition, they MUST fully support each Diameter
+ application that is needed to implement the client's service, e.g.,
+ NASREQ and/or Mobile IPv4. A Diameter Client MUST be referred to as
+ "Diameter X Client" where X is the application which it supports, and
+ not a "Diameter Client".
+
+ Diameter Servers MUST support the base protocol, which includes
+ accounting. In addition, they MUST fully support each Diameter
+ application that is needed to implement the intended service, e.g.,
+ NASREQ and/or Mobile IPv4. A Diameter Server MUST be referred to as
+ "Diameter X Server" where X is the application which it supports, and
+ not a "Diameter Server".
+
+ Diameter Relays and redirect agents are transparent to the Diameter
+ applications but they MUST support the Diameter base protocol, which
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 21]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ includes accounting, and all Diameter applications.
+
+ Diameter proxies MUST support the base protocol, which includes
+ accounting. In addition, they MUST fully support each Diameter
+ application that is needed to implement proxied services, e.g.,
+ NASREQ and/or Mobile IPv4. A Diameter proxy MUST be referred to as
+ "Diameter X Proxy" where X is the application which it supports, and
+ not a "Diameter Proxy".
+
+2.1. Transport
+
+ The Diameter Transport profile is defined in [RFC3539].
+
+ The base Diameter protocol is run on port 3868 for both TCP [RFC793]
+ and SCTP [RFC4960]. For TLS [RFC5246] and DTLS [RFC4347], a Diameter
+ node that initiate a connection prior to any message exchanges MUST
+ run on port [TBD]. It is assumed that TLS is run on top of TCP when
+ it is used and DTLS is run on top of SCTP when it is used.
+
+ If the Diameter peer does not support receiving TLS/TCP and DTLS/SCTP
+ connections on port [TBD], i.e. the peer complies only with
+ [RFC3588], then the initiator MAY revert to using TCP or SCTP and on
+ port 3868. Note that this scheme is kept for the purpose of
+ backwards compatibility only and that there are inherent security
+ vulnerabilities when the initial CER/CEA messages are sent un-
+ protected (see Section 5.6).
+
+ Diameter clients MUST support either TCP or SCTP, while agents and
+ servers SHOULD support both.
+
+ A Diameter node MAY initiate connections from a source port other
+ than the one that it declares it accepts incoming connections on, and
+ MUST be prepared to receive connections on port 3868 for TCP or SCTP
+ and port [TBD] for TLS/TCP and DTLS/SCTP connections. A given
+ Diameter instance of the peer state machine MUST NOT use more than
+ one transport connection to communicate with a given peer, unless
+ multiple instances exist on the peer in which case a separate
+ connection per process is allowed.
+
+ When no transport connection exists with a peer, an attempt to
+ connect SHOULD be periodically made. This behavior is handled via
+ the Tc timer (see Section 12 for details), whose recommended value is
+ 30 seconds. There are certain exceptions to this rule, such as when
+ a peer has terminated the transport connection stating that it does
+ not wish to communicate.
+
+ When connecting to a peer and either zero or more transports are
+ specified, TLS SHOULD be tried first, followed by DTLS, then by TCP
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 22]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ and finally by SCTP. See Section 5.2 for more information on peer
+ discovery.
+
+ Diameter implementations SHOULD be able to interpret ICMP protocol
+ port unreachable messages as explicit indications that the server is
+ not reachable, subject to security policy on trusting such messages.
+ Further guidance regarding the treatment of ICMP errors can be found
+ in [RFC5927] and [RFC5461]. Diameter implementations SHOULD also be
+ able to interpret a reset from the transport and timed-out connection
+ attempts. If Diameter receives data from the lower layer that cannot
+ be parsed or identified as a Diameter error made by the peer, the
+ stream is compromised and cannot be recovered. The transport
+ connection MUST be closed using a RESET call (send a TCP RST bit) or
+ an SCTP ABORT message (graceful closure is compromised).
+
+2.1.1. SCTP Guidelines
+
+ Diameter messages SHOULD be mapped into SCTP streams in a way that
+ avoids head-of-the-line (HOL) blocking. Among different ways of
+ performing the mapping that fulfill this requirement it is
+ RECOMMENDED that a Diameter node sends every Diameter message
+ (request or response) over the stream zero with the unordered flag
+ set. However, Diameter nodes MAY select and implement other design
+ alternatives for avoiding HOL blocking such as using multiple streams
+ with the unordered flag cleared (as originally instructed in
+ RFC3588). On the receiving side, a Diameter entity MUST be ready to
+ receive Diameter messages over any stream and it is free to return
+ responses over a different stream. This way, both sides manage the
+ available streams in the sending direction, independently of the
+ streams chosen by the other side to send a particular Diameter
+ message. These messages can be out-of-order and belong to different
+ Diameter sessions.
+
+ Out-of-order delivery has special concerns during a connection
+ establishment and termination. When a connection is established, the
+ responder side sends a CEA message and moves to R-Open state as
+ specified in Section 5.6. If an application message is sent shortly
+ after the CEA and delivered out-of-order, the initiator side, still
+ in Wait-I-CEA state, will discard the application message and close
+ the connection. In order to avoid this race condition, the receiver
+ side SHOULD NOT use out-of-order delivery methods until the first
+ message has been received from the initiator, proving that it has
+ moved to I-Open state. To trigger such message, the receiver side
+ could send a DWR immediatly after sending CEA. Upon reception of the
+ corresponding DWA, the receiver side should start using out-of-order
+ delivery methods to counter the HOL blocking.
+
+ Another race condition may occur when DPR and DPA messages are used.
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 23]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Both DPR and DPA are small in size, thus they may be delivered faster
+ to the peer than application messages when out-of-order delivery
+ mechanism is used. Therefore, it is possible that a DPR/DPA exchange
+ completes while application messages are still in transit, resulting
+ to a loss of these messages. An implementation could mitigate this
+ race condition, for example, using timers and wait for a short period
+ of time for pending application level messages to arrive before
+ proceeding to disconnect the transport connection. Eventually, lost
+ messages are handled by the retransmission mechanism described in
+ Section 5.5.4.
+
+2.2. Securing Diameter Messages
+
+ Connections between Diameter peers SHOULD be protected by TLS/TCP and
+ DTLS/SCTP. All Diameter base protocol implementations MUST support
+ the use of TLS/TCP and DTLS/SCTP. If desired, alternative security
+ mechanisms that are independent of Diameter, such as IPsec [RFC4301],
+ can be deployed to secure connections between peers. The Diameter
+ protocol MUST NOT be used without any security mechanism.
+
+2.3. Diameter Application Compliance
+
+ Application Ids are advertised during the capabilities exchange phase
+ (see Section 5.3). Advertising support of an application implies
+ that the sender supports the functionality specified in the
+ respective Diameter application specification.
+
+ Implementations MAY add arbitrary optional AVPs with the M-bit
+ cleared (including vendor-specific AVPs) to a command defined in an
+ application, but only if the command's ABNF syntax specification
+ allows for it. Please refer to Section 11.1.1 for details.
+
+2.4. Application Identifiers
+
+ Each Diameter application MUST have an IANA assigned Application Id
+ (see Section 11.3). The base protocol does not require an
+ Application Id since its support is mandatory. During the
+ capabilities exchange, Diameter nodes inform their peers of locally
+ supported applications. Furthermore, all Diameter messages contain
+ an Application Id, which is used in the message forwarding process.
+
+ The following Application Id values are defined:
+
+ Diameter Common Messages 0
+ Diameter Base Accounting 3
+ Relay 0xffffffff
+
+ Relay and redirect agents MUST advertise the Relay Application
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 24]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Identifier, while all other Diameter nodes MUST advertise locally
+ supported applications. The receiver of a Capabilities Exchange
+ message advertising Relay service MUST assume that the sender
+ supports all current and future applications.
+
+ Diameter relay and proxy agents are responsible for finding an
+ upstream server that supports the application of a particular
+ message. If none can be found, an error message is returned with the
+ Result-Code AVP set to DIAMETER_UNABLE_TO_DELIVER.
+
+2.5. Connections vs. Sessions
+
+ This section attempts to provide the reader with an understanding of
+ the difference between connection and session, which are terms used
+ extensively throughout this document.
+
+ A connection refers to a transport level connection between two peers
+ that is used to send and receive Diameter messages. A session is a
+ logical concept at the application layer existing between the
+ Diameter client and the Diameter server; it is identified via the
+ Session-Id AVP.
+
+
+ +--------+ +-------+ +--------+
+ | Client | | Relay | | Server |
+ +--------+ +-------+ +--------+
+ <----------> <---------->
+ peer connection A peer connection B
+
+ <----------------------------->
+ User session x
+
+ Figure 1: Diameter connections and sessions
+
+ In the example provided in Figure 1, peer connection A is established
+ between the Client and the Relay. Peer connection B is established
+ between the Relay and the Server. User session X spans from the
+ Client via the Relay to the Server. Each "user" of a service causes
+ an auth request to be sent, with a unique session identifier. Once
+ accepted by the server, both the client and the server are aware of
+ the session.
+
+ It is important to note that there is no relationship between a
+ connection and a session, and that Diameter messages for multiple
+ sessions are all multiplexed through a single connection. Also note
+ that Diameter messages pertaining to the session, both application
+ specific and those that are defined in this document such as ASR/ASA,
+ RAR/RAA and STR/STA MUST carry the Application Id of the application.
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 25]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Diameter messages pertaining to peer connection establishment and
+ maintenance such as CER/CEA, DWR/DWA and DPR/DPA MUST carry an
+ Application Id of zero (0).
+
+2.6. Peer Table
+
+ The Diameter Peer Table is used in message forwarding, and referenced
+ by the Routing Table. A Peer Table entry contains the following
+ fields:
+
+ Host identity
+
+ Following the conventions described for the DiameterIdentity
+ derived AVP data format in Section 4.3. This field contains the
+ contents of the Origin-Host (Section 6.3) AVP found in the CER or
+ CEA message.
+
+
+ StatusT
+
+ This is the state of the peer entry, and MUST match one of the
+ values listed in Section 5.6.
+
+
+ Static or Dynamic
+
+ Specifies whether a peer entry was statically configured or
+ dynamically discovered.
+
+
+ Expiration time
+
+ Specifies the time at which dynamically discovered peer table
+ entries are to be either refreshed, or expired.
+
+
+ TLS/TCP and DTLS/SCTP Enabled
+
+ Specifies whether TLS/TCP and DTLS/SCTP is to be used when
+ communicating with the peer.
+
+
+ Additional security information, when needed (e.g., keys,
+ certificates)
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 26]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+2.7. Routing Table
+
+ All Realm-Based routing lookups are performed against what is
+ commonly known as the Routing Table (see Section 12). A Routing
+ Table Entry contains the following fields:
+
+ Realm Name
+
+ This is the field that is MUST be used as a primary key in the
+ routing table lookups. Note that some implementations perform
+ their lookups based on longest-match-from-the-right on the realm
+ rather than requiring an exact match.
+
+
+ Application Identifier
+
+ An application is identified by an Application Id. A route entry
+ can have a different destination based on the Application Id in
+ the message header. This field MUST be used as a secondary key
+ field in routing table lookups.
+
+
+ Local Action
+
+ The Local Action field is used to identify how a message should be
+ treated. The following actions are supported:
+
+
+ 1. LOCAL - Diameter messages that can be satisfied locally, and
+ do not need to be routed to another Diameter entity.
+
+ 2. RELAY - All Diameter messages that fall within this category
+ MUST be routed to a next hop Diameter entity that is indicated
+ by the identifier described below. Routing is done without
+ modifying any non-routing AVPs. See Section 6.1.9 for
+ relaying guidelines
+
+ 3. PROXY - All Diameter messages that fall within this category
+ MUST be routed to a next Diameter entity that is indicated by
+ the identifier described below. The local server MAY apply
+ its local policies to the message by including new AVPs to the
+ message prior to routing. See Section 6.1.9 for proxying
+ guidelines.
+
+ 4. REDIRECT - Diameter messages that fall within this category
+ MUST have the identity of the home Diameter server(s)
+ appended, and returned to the sender of the message. See
+ Section 6.1.8 for redirect guidelines.
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 27]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Server Identifier
+
+ One or more servers to which the message is to be routed. These
+ servers MUST also be present in the Peer table. When the Local
+ Action is set to RELAY or PROXY, this field contains the identity
+ of the server(s) the message MUST be routed to. When the Local
+ Action field is set to REDIRECT, this field contains the identity
+ of one or more servers the message MUST be redirected to.
+
+ Static or Dynamic
+
+ Specifies whether a route entry was statically configured or
+ dynamically discovered.
+
+ Expiration time
+
+ Specifies the time at which a dynamically discovered route table
+ entry expires.
+
+ It is important to note that Diameter agents MUST support at least
+ one of the LOCAL, RELAY, PROXY or REDIRECT modes of operation.
+ Agents do not need to support all modes of operation in order to
+ conform with the protocol specification, but MUST follow the protocol
+ compliance guidelines in Section 2. Relay agents and proxies MUST
+ NOT reorder AVPs.
+
+ The routing table MAY include a default entry that MUST be used for
+ any requests not matching any of the other entries. The routing
+ table MAY consist of only such an entry.
+
+ When a request is routed, the target server MUST have advertised the
+ Application Id (see Section 2.4) for the given message, or have
+ advertised itself as a relay or proxy agent. Otherwise, an error is
+ returned with the Result-Code AVP set to DIAMETER_UNABLE_TO_DELIVER.
+
+2.8. Role of Diameter Agents
+
+ In addition to clients and servers, the Diameter protocol introduces
+ relay, proxy, redirect, and translation agents, each of which is
+ defined in Section 1.3. These Diameter agents are useful for several
+ reasons:
+
+ o They can distribute administration of systems to a configurable
+ grouping, including the maintenance of security associations.
+
+ o They can be used for concentration of requests from an number of
+ co-located or distributed NAS equipment sets to a set of like user
+ groups.
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 28]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ o They can do value-added processing to the requests or responses.
+
+ o They can be used for load balancing.
+
+ o A complex network will have multiple authentication sources, they
+ can sort requests and forward towards the correct target.
+
+ The Diameter protocol requires that agents maintain transaction
+ state, which is used for failover purposes. Transaction state
+ implies that upon forwarding a request, its Hop-by-Hop identifier is
+ saved; the field is replaced with a locally unique identifier, which
+ is restored to its original value when the corresponding answer is
+ received. The request's state is released upon receipt of the
+ answer. A stateless agent is one that only maintains transaction
+ state.
+
+ The Proxy-Info AVP allows stateless agents to add local state to a
+ Diameter request, with the guarantee that the same state will be
+ present in the answer. However, the protocol's failover procedures
+ require that agents maintain a copy of pending requests.
+
+ A stateful agent is one that maintains session state information by
+ keeping track of all authorized active sessions. Each authorized
+ session is bound to a particular service, and its state is considered
+ active either until the agent is notified otherwise, or the session
+ expires. Each authorized session has an expiration, which is
+ communicated by Diameter servers via the Session-Timeout AVP.
+
+ Maintaining session state may be useful in certain applications, such
+ as:
+
+ o Protocol translation (e.g., RADIUS <-> Diameter)
+
+ o Limiting resources authorized to a particular user
+
+ o Per user or transaction auditing
+
+ A Diameter agent MAY act in a stateful manner for some requests and
+ be stateless for others. A Diameter implementation MAY act as one
+ type of agent for some requests, and as another type of agent for
+ others.
+
+2.8.1. Relay Agents
+
+ Relay Agents are Diameter agents that accept requests and route
+ messages to other Diameter nodes based on information found in the
+ messages (e.g., Destination-Realm). This routing decision is
+ performed using a list of supported realms, and known peers. This is
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 29]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ known as the Routing Table, as is defined further in Section 2.7.
+
+ Relays may, for example, be used to aggregate requests from multiple
+ Network Access Servers (NASes) within a common geographical area
+ (POP). The use of Relays is advantageous since it eliminates the
+ need for NASes to be configured with the necessary security
+ information they would otherwise require to communicate with Diameter
+ servers in other realms. Likewise, this reduces the configuration
+ load on Diameter servers that would otherwise be necessary when NASes
+ are added, changed or deleted.
+
+ Relays modify Diameter messages by inserting and removing routing
+ information, but do not modify any other portion of a message.
+ Relays SHOULD NOT maintain session state but MUST maintain
+ transaction state.
+
+ +------+ ---------> +------+ ---------> +------+
+ | | 1. Request | | 2. Request | |
+ | NAS | | DRL | | HMS |
+ | | 4. Answer | | 3. Answer | |
+ +------+ <--------- +------+ <--------- +------+
+ example.net example.net example.com
+
+ Figure 2: Relaying of Diameter messages
+
+ The example provided in Figure 2 depicts a request issued from NAS,
+ which is an access device, for the user [email protected]. Prior to
+ issuing the request, NAS performs a Diameter route lookup, using
+ "example.com" as the key, and determines that the message is to be
+ relayed to DRL, which is a Diameter Relay. DRL performs the same
+ route lookup as NAS, and relays the message to HMS, which is
+ example.com's Home Diameter Server. HMS identifies that the request
+ can be locally supported (via the realm), processes the
+ authentication and/or authorization request, and replies with an
+ answer, which is routed back to NAS using saved transaction state.
+
+ Since Relays do not perform any application level processing, they
+ provide relaying services for all Diameter applications, and
+ therefore MUST advertise the Relay Application Id.
+
+2.8.2. Proxy Agents
+
+ Similarly to relays, proxy agents route Diameter messages using the
+ Diameter Routing Table. However, they differ since they modify
+ messages to implement policy enforcement. This requires that proxies
+ maintain the state of their downstream peers (e.g., access devices)
+ to enforce resource usage, provide admission control, and
+ provisioning.
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 30]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Proxies may, for example, be used in call control centers or access
+ ISPs that provide outsourced connections, they can monitor the number
+ and types of ports in use, and make allocation and admission
+ decisions according to their configuration.
+
+ Since enforcing policies requires an understanding of the service
+ being provided, Proxies MUST only advertise the Diameter applications
+ they support.
+
+2.8.3. Redirect Agents
+
+ Redirect agents are useful in scenarios where the Diameter routing
+ configuration needs to be centralized. An example is a redirect
+ agent that provides services to all members of a consortium, but does
+ not wish to be burdened with relaying all messages between realms.
+ This scenario is advantageous since it does not require that the
+ consortium provide routing updates to its members when changes are
+ made to a member's infrastructure.
+
+ Since redirect agents do not relay messages, and only return an
+ answer with the information necessary for Diameter agents to
+ communicate directly, they do not modify messages. Since redirect
+ agents do not receive answer messages, they cannot maintain session
+ state.
+
+ The example provided in Figure 3 depicts a request issued from the
+ access device, NAS, for the user [email protected]. The message is
+ forwarded by the NAS to its relay, DRL, which does not have a routing
+ entry in its Diameter Routing Table for example.com. DRL has a
+ default route configured to DRD, which is a redirect agent that
+ returns a redirect notification to DRL, as well as HMS' contact
+ information. Upon receipt of the redirect notification, DRL
+ establishes a transport connection with HMS, if one doesn't already
+ exist, and forwards the request to it.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 31]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ +------+
+ | |
+ | DRD |
+ | |
+ +------+
+ ^ |
+ 2. Request | | 3. Redirection
+ | | Notification
+ | v
+ +------+ ---------> +------+ ---------> +------+
+ | | 1. Request | | 4. Request | |
+ | NAS | | DRL | | HMS |
+ | | 6. Answer | | 5. Answer | |
+ +------+ <--------- +------+ <--------- +------+
+ example.net example.net example.com
+
+ Figure 3: Redirecting a Diameter Message
+
+ Since redirect agents do not perform any application level
+ processing, they provide relaying services for all Diameter
+ applications, and therefore MUST advertise the Relay Application
+ Identifier.
+
+2.8.4. Translation Agents
+
+ A translation agent is a device that provides translation between two
+ protocols (e.g., RADIUS<->Diameter, TACACS+<->Diameter). Translation
+ agents are likely to be used as aggregation servers to communicate
+ with a Diameter infrastructure, while allowing for the embedded
+ systems to be migrated at a slower pace.
+
+ Given that the Diameter protocol introduces the concept of long-lived
+ authorized sessions, translation agents MUST be session stateful and
+ MUST maintain transaction state.
+
+ Translation of messages can only occur if the agent recognizes the
+ application of a particular request, and therefore translation agents
+ MUST only advertise their locally supported applications.
+
+ +------+ ---------> +------+ ---------> +------+
+ | | RADIUS Request | | Diameter Request | |
+ | NAS | | TLA | | HMS |
+ | | RADIUS Answer | | Diameter Answer | |
+ +------+ <--------- +------+ <--------- +------+
+ example.net example.net example.com
+
+ Figure 4: Translation of RADIUS to Diameter
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 32]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+2.9. Diameter Path Authorization
+
+ As noted in Section 2.2, Diameter provides transmission level
+ security for each connection using TLS/TCP and DTLS/SCTP. Therefore,
+ each connection can be authenticated, replay and integrity protected.
+
+ In addition to authenticating each connection, each connection as
+ well as the entire session MUST also be authorized. Before
+ initiating a connection, a Diameter Peer MUST check that its peers
+ are authorized to act in their roles. For example, a Diameter peer
+ may be authentic, but that does not mean that it is authorized to act
+ as a Diameter Server advertising a set of Diameter applications.
+
+ Prior to bringing up a connection, authorization checks are performed
+ at each connection along the path. Diameter capabilities negotiation
+ (CER/CEA) also MUST be carried out, in order to determine what
+ Diameter applications are supported by each peer. Diameter sessions
+ MUST be routed only through authorized nodes that have advertised
+ support for the Diameter application required by the session.
+
+ As noted in Section 6.1.9, a relay or proxy agent MUST append a
+ Route-Record AVP to all requests forwarded. The AVP contains the
+ identity of the peer the request was received from.
+
+ The home Diameter server, prior to authorizing a session, MUST check
+ the Route-Record AVPs to make sure that the route traversed by the
+ request is acceptable. For example, administrators within the home
+ realm may not wish to honor requests that have been routed through an
+ untrusted realm. By authorizing a request, the home Diameter server
+ is implicitly indicating its willingness to engage in the business
+ transaction as specified by the contractual relationship between the
+ server and the previous hop. A DIAMETER_AUTHORIZATION_REJECTED error
+ message (see Section 7.1.5) is sent if the route traversed by the
+ request is unacceptable.
+
+ A home realm may also wish to check that each accounting request
+ message corresponds to a Diameter response authorizing the session.
+ Accounting requests without corresponding authorization responses
+ SHOULD be subjected to further scrutiny, as should accounting
+ requests indicating a difference between the requested and provided
+ service.
+
+ Forwarding of an authorization response is considered evidence of a
+ willingness to take on financial risk relative to the session. A
+ local realm may wish to limit this exposure, for example, by
+ establishing credit limits for intermediate realms and refusing to
+ accept responses which would violate those limits. By issuing an
+ accounting request corresponding to the authorization response, the
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 33]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ local realm implicitly indicates its agreement to provide the service
+ indicated in the authorization response. If the service cannot be
+ provided by the local realm, then a DIAMETER_UNABLE_TO_COMPLY error
+ message MUST be sent within the accounting request; a Diameter client
+ receiving an authorization response for a service that it cannot
+ perform MUST NOT substitute an alternate service, and then send
+ accounting requests for the alternate service instead.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 34]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+3. Diameter Header
+
+ A summary of the Diameter header format is shown below. The fields
+ are transmitted in network byte order.
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version | Message Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | command flags | Command-Code |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Application-ID |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Hop-by-Hop Identifier |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | End-to-End Identifier |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | AVPs ...
+ +-+-+-+-+-+-+-+-+-+-+-+-+-
+
+ Version
+
+ This Version field MUST be set to 1 to indicate Diameter Version
+ 1.
+
+ Message Length
+
+ The Message Length field is three octets and indicates the length
+ of the Diameter message including the header fields and the padded
+ AVPs. Thus the message length field is always a multiple of 4.
+
+ Command Flags
+
+ The Command Flags field is eight bits. The following bits are
+ assigned:
+
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+
+ |R P E T r r r r|
+ +-+-+-+-+-+-+-+-+
+
+ R(equest)
+
+ If set, the message is a request. If cleared, the message is
+ an answer.
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 35]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ P(roxiable)
+
+ If set, the message MAY be proxied, relayed or redirected. If
+ cleared, the message MUST be locally processed.
+
+
+ E(rror)
+
+ If set, the message contains a protocol error, and the message
+ will not conform to the ABNF described for this command.
+ Messages with the 'E' bit set are commonly referred to as error
+ messages. This bit MUST NOT be set in request messages. See
+ Section 7.2.
+
+
+ T(Potentially re-transmitted message)
+
+ This flag is set after a link failover procedure, to aid the
+ removal of duplicate requests. It is set when resending
+ requests not yet acknowledged, as an indication of a possible
+ duplicate due to a link failure. This bit MUST be cleared when
+ sending a request for the first time, otherwise the sender MUST
+ set this flag. Diameter agents only need to be concerned about
+ the number of requests they send based on a single received
+ request; retransmissions by other entities need not be tracked.
+ Diameter agents that receive a request with the T flag set,
+ MUST keep the T flag set in the forwarded request. This flag
+ MUST NOT be set if an error answer message (e.g., a protocol
+ error) has been received for the earlier message. It can be
+ set only in cases where no answer has been received from the
+ server for a request and the request is sent again. This flag
+ MUST NOT be set in answer messages.
+
+
+ r(eserved)
+
+ These flag bits are reserved for future use, and MUST be set to
+ zero, and ignored by the receiver.
+
+ Command-Code
+
+ The Command-Code field is three octets, and is used in order to
+ communicate the command associated with the message. The 24-bit
+ address space is managed by IANA (see Section 11.2.1).
+
+ Command-Code values 16,777,214 and 16,777,215 (hexadecimal values
+ FFFFFE -FFFFFF) are reserved for experimental use (See Section
+ 11.3).
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 36]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Application-ID
+
+ Application-ID is four octets and is used to identify to which
+ application the message is applicable for. The application can be
+ an authentication application, an accounting application or a
+ vendor specific application. See Section 11.3 for the possible
+ values that the application-id may use.
+
+ The value of the application-id field in the header MUST be the
+ same as any relevant application-id AVPs contained in the message.
+
+ Hop-by-Hop Identifier
+
+ The Hop-by-Hop Identifier is an unsigned 32-bit integer field (in
+ network byte order) and aids in matching requests and replies.
+ The sender MUST ensure that the Hop-by-Hop identifier in a request
+ is unique on a given connection at any given time, and MAY attempt
+ to ensure that the number is unique across reboots. The sender of
+ an Answer message MUST ensure that the Hop-by-Hop Identifier field
+ contains the same value that was found in the corresponding
+ request. The Hop-by-Hop identifier is normally a monotonically
+ increasing number, whose start value was randomly generated. An
+ answer message that is received with an unknown Hop-by-Hop
+ Identifier MUST be discarded.
+
+
+ End-to-End Identifier
+
+ The End-to-End Identifier is an unsigned 32-bit integer field (in
+ network byte order) and is used to detect duplicate messages.
+ Upon reboot implementations MAY set the high order 12 bits to
+ contain the low order 12 bits of current time, and the low order
+ 20 bits to a random value. Senders of request messages MUST
+ insert a unique identifier on each message. The identifier MUST
+ remain locally unique for a period of at least 4 minutes, even
+ across reboots. The originator of an Answer message MUST ensure
+ that the End-to-End Identifier field contains the same value that
+ was found in the corresponding request. The End-to-End Identifier
+ MUST NOT be modified by Diameter agents of any kind. The
+ combination of the Origin-Host (see Section 6.3) and this field is
+ used to detect duplicates. Duplicate requests SHOULD cause the
+ same answer to be transmitted (modulo the hop-by-hop Identifier
+ field and any routing AVPs that may be present), and MUST NOT
+ affect any state that was set when the original request was
+ processed. Duplicate answer messages that are to be locally
+ consumed (see Section 6.2) SHOULD be silently discarded.
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 37]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ AVPs
+
+ AVPs are a method of encapsulating information relevant to the
+ Diameter message. See Section 4 for more information on AVPs.
+
+3.1. Command Codes
+
+ Each command Request/Answer pair is assigned a command code, and the
+ sub-type (i.e., request or answer) is identified via the 'R' bit in
+ the Command Flags field of the Diameter header.
+
+
+ Every Diameter message MUST contain a command code in its header's
+ Command-Code field, which is used to determine the action that is to
+ be taken for a particular message. The following Command Codes are
+ defined in the Diameter base protocol:
+
+ Command-Name Abbrev. Code Reference
+ --------------------------------------------------------
+ Abort-Session-Request ASR 274 8.5.1
+ Abort-Session-Answer ASA 274 8.5.2
+ Accounting-Request ACR 271 9.7.1
+ Accounting-Answer ACA 271 9.7.2
+ Capabilities-Exchange- CER 257 5.3.1
+ Request
+ Capabilities-Exchange- CEA 257 5.3.2
+ Answer
+ Device-Watchdog-Request DWR 280 5.5.1
+ Device-Watchdog-Answer DWA 280 5.5.2
+ Disconnect-Peer-Request DPR 282 5.4.1
+ Disconnect-Peer-Answer DPA 282 5.4.2
+ Re-Auth-Request RAR 258 8.3.1
+ Re-Auth-Answer RAA 258 8.3.2
+ Session-Termination- STR 275 8.4.1
+ Request
+ Session-Termination- STA 275 8.4.2
+ Answer
+
+3.2. Command Code ABNF specification
+
+ Every Command Code defined MUST include a corresponding ABNF
+ specification, which is used to define the AVPs that MUST or MAY be
+ present when sending the message. The following format is used in
+ the definition:
+
+ command-def = <command-name> "::=" diameter-message
+
+ command-name = diameter-name
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 38]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ diameter-name = ALPHA *(ALPHA / DIGIT / "-")
+
+ diameter-message = header [ *fixed] [ *required] [ *optional]
+
+ header = "<" "Diameter Header:" command-id
+ [r-bit] [p-bit] [e-bit] [application-id] ">"
+
+ application-id = 1*DIGIT
+
+ command-id = 1*DIGIT
+ ; The Command Code assigned to the command
+
+ r-bit = ", REQ"
+ ; If present, the 'R' bit in the Command
+ ; Flags is set, indicating that the message
+ ; is a request, as opposed to an answer.
+
+ p-bit = ", PXY"
+ ; If present, the 'P' bit in the Command
+ ; Flags is set, indicating that the message
+ ; is proxiable.
+
+ e-bit = ", ERR"
+ ; If present, the 'E' bit in the Command
+ ; Flags is set, indicating that the answer
+ ; message contains a Result-Code AVP in
+ ; the "protocol error" class.
+
+ fixed = [qual] "<" avp-spec ">"
+ ; Defines the fixed position of an AVP
+
+ required = [qual] "{" avp-spec "}"
+ ; The AVP MUST be present and can appear
+ ; anywhere in the message.
+
+
+ optional = [qual] "[" avp-name "]"
+ ; The avp-name in the 'optional' rule cannot
+ ; evaluate to any AVP Name which is included
+ ; in a fixed or required rule. The AVP can
+ ; appear anywhere in the message.
+ ;
+ ; NOTE: "[" and "]" have a slightly different
+ ; meaning than in ABNF (RFC 5234]). These braces
+ ; cannot be used to express optional fixed rules
+ ; (such as an optional ICV at the end). To do this,
+ ; the convention is '0*1fixed'.
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 39]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ qual = [min] "*" [max]
+ ; See ABNF conventions, RFC 5234 Section 4.
+ ; The absence of any qualifiers depends on
+ ; whether it precedes a fixed, required, or
+ ; optional rule. If a fixed or required rule has
+ ; no qualifier, then exactly one such AVP MUST
+ ; be present. If an optional rule has no
+ ; qualifier, then 0 or 1 such AVP may be
+ ; present. If an optional rule has a qualifier,
+ ; then the value of min MUST be 0 if present.
+
+ min = 1*DIGIT
+ ; The minimum number of times the element may
+ ; be present. If absent, the default value is zero
+ ; for fixed and optional rules and one for required
+ ; rules. The value MUST be at least one for for
+ ; required rules.
+
+ max = 1*DIGIT
+ ; The maximum number of times the element may
+ ; be present. If absent, the default value is
+ ; infinity. A value of zero implies the AVP MUST
+ ; NOT be present.
+
+ avp-spec = diameter-name
+ ; The avp-spec has to be an AVP Name, defined
+ ; in the base or extended Diameter
+ ; specifications.
+
+ avp-name = avp-spec / "AVP"
+ ; The string "AVP" stands for *any* arbitrary AVP
+ ; Name, not otherwise listed in that command code
+ ; definition. Addition this AVP is recommended for
+ ; all command ABNFs to allow for extensibility.
+
+
+
+ The following is a definition of a fictitious command code:
+
+ Example-Request ::= < Diameter Header: 9999999, REQ, PXY >
+ { User-Name }
+ * { Origin-Host }
+ * [ AVP ]
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 40]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+3.3. Diameter Command Naming Conventions
+
+ Diameter command names typically includes one or more English words
+ followed by the verb Request or Answer. Each English word is
+ delimited by a hyphen. A three-letter acronym for both the request
+ and answer is also normally provided.
+
+ An example is a message set used to terminate a session. The command
+ name is Session-Terminate-Request and Session-Terminate-Answer, while
+ the acronyms are STR and STA, respectively.
+
+ Both the request and the answer for a given command share the same
+ command code. The request is identified by the R(equest) bit in the
+ Diameter header set to one (1), to ask that a particular action be
+ performed, such as authorizing a user or terminating a session. Once
+ the receiver has completed the request it issues the corresponding
+ answer, which includes a result code that communicates one of the
+ following:
+
+ o The request was successful
+
+ o The request failed
+
+ o An additional request has to be sent to provide information the
+ peer requires prior to returning a successful or failed answer.
+
+ o The receiver could not process the request, but provides
+ information about a Diameter peer that is able to satisfy the
+ request, known as redirect.
+
+ Additional information, encoded within AVPs, may also be included in
+ answer messages.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 41]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+4. Diameter AVPs
+
+ Diameter AVPs carry specific authentication, accounting,
+ authorization and routing information as well as configuration
+ details for the request and reply.
+
+ Each AVP of type OctetString MUST be padded to align on a 32-bit
+ boundary, while other AVP types align naturally. A number of zero-
+ valued bytes are added to the end of the AVP Data field till a word
+ boundary is reached. The length of the padding is not reflected in
+ the AVP Length field.
+
+4.1. AVP Header
+
+ The fields in the AVP header MUST be sent in network byte order. The
+ format of the header is:
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | AVP Code |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |V M P r r r r r| AVP Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Vendor-ID (opt) |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Data ...
+ +-+-+-+-+-+-+-+-+
+
+ AVP Code
+
+ The AVP Code, combined with the Vendor-Id field, identifies the
+ attribute uniquely. AVP numbers 1 through 255 are reserved for
+ re-use of RADIUS attributes, without setting the Vendor-Id field.
+ AVP numbers 256 and above are used for Diameter, which are
+ allocated by IANA (see Section 11.1).
+
+
+ AVP Flags
+
+ The AVP Flags field informs the receiver how each attribute must
+ be handled. The 'r' (reserved) bits are unused and SHOULD be set
+ to 0. Note that subsequent Diameter applications MAY define
+ additional bits within the AVP Header, and an unrecognized bit
+ SHOULD be considered an error. The 'P' bit has been reserved for
+ future usage of end-to-end security. At the time of writing there
+ are no end-to-end security mechanisms specified therefore the 'P'
+ bit SHOULD be set to 0.
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 42]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ The 'M' Bit, known as the Mandatory bit, indicates whether the
+ receiver of the AVP MUST parse and understand the semantic of the
+ AVP including its content. The receiving entity MUST return an
+ appropriate error message if it receives an AVP that has the M-bit
+ set but does not understand it. An exception applies when the AVP
+ is embedded within a Grouped AVP. See Section 4.4 for details.
+ Diameter Relay and redirect agents MUST NOT reject messages with
+ unrecognized AVPs.
+
+ The 'M' bit MUST be set according to the rules defined in the
+ application specification which introduces or re-uses this AVP.
+ Within a given application, the M-bit setting for an AVP is either
+ defined for all command types or for each command type.
+
+ AVPs with the 'M' bit cleared are informational only and a
+ receiver that receives a message with such an AVP that is not
+ supported, or whose value is not supported, MAY simply ignore the
+ AVP.
+
+ The 'V' bit, known as the Vendor-Specific bit, indicates whether
+ the optional Vendor-ID field is present in the AVP header. When
+ set the AVP Code belongs to the specific vendor code address
+ space.
+
+ AVP Length
+
+ The AVP Length field is three octets, and indicates the number of
+ octets in this AVP including the AVP Code, AVP Length, AVP Flags,
+ Vendor-ID field (if present) and the AVP data. If a message is
+ received with an invalid attribute length, the message MUST be
+ rejected.
+
+4.1.1. Optional Header Elements
+
+ The AVP Header contains one optional field. This field is only
+ present if the respective bit-flag is enabled.
+
+
+ Vendor-ID
+
+ The Vendor-ID field is present if the 'V' bit is set in the AVP
+ Flags field. The optional four-octet Vendor-ID field contains the
+ IANA assigned "SMI Network Management Private Enterprise Codes"
+ [RFC3232] value, encoded in network byte order. Any vendor or
+ standardization organization that are also treated like vendors in
+ the IANA managed "SMI Network Management Private Enterprise Codes"
+ space wishing to implement a vendor-specific Diameter AVP MUST use
+ their own Vendor-ID along with their privately managed AVP address
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 43]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ space, guaranteeing that they will not collide with any other
+ vendor's vendor-specific AVP(s), nor with future IETF AVPs.
+
+ A vendor ID value of zero (0) corresponds to the IETF adopted AVP
+ values, as managed by the IANA. Since the absence of the vendor
+ ID field implies that the AVP in question is not vendor specific,
+ implementations MUST NOT use the zero (0) vendor ID.
+
+4.2. Basic AVP Data Formats
+
+ The Data field is zero or more octets and contains information
+ specific to the Attribute. The format and length of the Data field
+ is determined by the AVP Code and AVP Length fields. The format of
+ the Data field MUST be one of the following base data types or a data
+ type derived from the base data types. In the event that a new Basic
+ AVP Data Format is needed, a new version of this RFC MUST be created.
+
+
+ OctetString
+
+ The data contains arbitrary data of variable length. Unless
+ otherwise noted, the AVP Length field MUST be set to at least 8
+ (12 if the 'V' bit is enabled). AVP Values of this type that are
+ not a multiple of four-octets in length is followed by the
+ necessary padding so that the next AVP (if any) will start on a
+ 32-bit boundary.
+
+
+ Integer32
+
+ 32 bit signed value, in network byte order. The AVP Length field
+ MUST be set to 12 (16 if the 'V' bit is enabled).
+
+
+ Integer64
+
+ 64 bit signed value, in network byte order. The AVP Length field
+ MUST be set to 16 (20 if the 'V' bit is enabled).
+
+
+ Unsigned32
+
+ 32 bit unsigned value, in network byte order. The AVP Length
+ field MUST be set to 12 (16 if the 'V' bit is enabled).
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 44]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Unsigned64
+
+ 64 bit unsigned value, in network byte order. The AVP Length
+ field MUST be set to 16 (20 if the 'V' bit is enabled).
+
+
+ Float32
+
+ This represents floating point values of single precision as
+ described by [FLOATPOINT]. The 32-bit value is transmitted in
+ network byte order. The AVP Length field MUST be set to 12 (16 if
+ the 'V' bit is enabled).
+
+
+ Float64
+
+ This represents floating point values of double precision as
+ described by [FLOATPOINT]. The 64-bit value is transmitted in
+ network byte order. The AVP Length field MUST be set to 16 (20 if
+ the 'V' bit is enabled).
+
+
+ Grouped
+
+ The Data field is specified as a sequence of AVPs. Each of these
+ AVPs follows - in the order in which they are specified -
+ including their headers and padding. The AVP Length field is set
+ to 8 (12 if the 'V' bit is enabled) plus the total length of all
+ included AVPs, including their headers and padding. Thus the AVP
+ length field of an AVP of type Grouped is always a multiple of 4.
+
+
+4.3. Derived AVP Data Formats
+
+ In addition to using the Basic AVP Data Formats, applications may
+ define data formats derived from the Basic AVP Data Formats. An
+ application that defines new Derived AVP Data Formats MUST include
+ them in a section entitled "Derived AVP Data Formats", using the same
+ format as the definitions below. Each new definition MUST be either
+ defined or listed with a reference to the RFC that defines the
+ format.
+
+4.3.1. Common Derived AVPs
+
+ The following are commonly used Derived AVP Data Formats.
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 45]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Address
+
+ The Address format is derived from the OctetString AVP Base
+ Format. It is a discriminated union, representing, for example a
+ 32-bit (IPv4) [RFC791] or 128-bit (IPv6) [RFC4291] address, most
+ significant octet first. The first two octets of the Address AVP
+ represents the AddressType, which contains an Address Family
+ defined in [IANAADFAM]. The AddressType is used to discriminate
+ the content and format of the remaining octets.
+
+
+ Time
+
+ The Time format is derived from the OctetString AVP Base Format.
+ The string MUST contain four octets, in the same format as the
+ first four bytes are in the NTP timestamp format. The NTP
+ Timestamp format is defined in Chapter 3 of [RFC5905].
+
+ This represents the number of seconds since 0h on 1 January 1900
+ with respect to the Coordinated Universal Time (UTC).
+
+ On 6h 28m 16s UTC, 7 February 2036 the time value will overflow.
+ SNTP [RFC5905] describes a procedure to extend the time to 2104.
+ This procedure MUST be supported by all Diameter nodes.
+
+
+ UTF8String
+
+ The UTF8String format is derived from the OctetString AVP Base
+ Format. This is a human readable string represented using the
+ ISO/IEC IS 10646-1 character set, encoded as an OctetString using
+ the UTF-8 [RFC3629] transformation format described in RFC 3629.
+
+ Since additional code points are added by amendments to the 10646
+ standard from time to time, implementations MUST be prepared to
+ encounter any code point from 0x00000001 to 0x7fffffff. Byte
+ sequences that do not correspond to the valid encoding of a code
+ point into UTF-8 charset or are outside this range are prohibited.
+
+ The use of control codes SHOULD be avoided. When it is necessary
+ to represent a new line, the control code sequence CR LF SHOULD be
+ used.
+
+ The use of leading or trailing white space SHOULD be avoided.
+
+ For code points not directly supported by user interface hardware
+ or software, an alternative means of entry and display, such as
+ hexadecimal, MAY be provided.
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 46]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ For information encoded in 7-bit US-ASCII, the UTF-8 charset is
+ identical to the US-ASCII charset.
+
+ UTF-8 may require multiple bytes to represent a single character /
+ code point; thus the length of an UTF8String in octets may be
+ different from the number of characters encoded.
+
+ Note that the AVP Length field of an UTF8String is measured in
+ octets, not characters.
+
+ DiameterIdentity
+
+ The DiameterIdentity format is derived from the OctetString AVP
+ Base Format.
+
+ DiameterIdentity = FQDN/Realm
+
+
+ DiameterIdentity value is used to uniquely identify either:
+
+ * A Diameter node for purposes of duplicate connection and
+ routing loop detection.
+
+ * A Realm to determine whether messages can be satisfied locally,
+ or whether they must be routed or redirected.
+
+
+ When a DiameterIdentity is used to identify a Diameter node the
+ contents of the string MUST be the FQDN of the Diameter node. If
+ multiple Diameter nodes run on the same host, each Diameter node
+ MUST be assigned a unique DiameterIdentity. If a Diameter node
+ can be identified by several FQDNs, a single FQDN should be picked
+ at startup, and used as the only DiameterIdentity for that node,
+ whatever the connection it is sent on. Note that in this
+ document, DiameterIdentity is in ASCII form in order to be
+ compatible with existing DNS infrastructure. See Appendix D for
+ interactions between the Diameter protocol and Internationalized
+ Domain Name (IDNs).
+
+
+ DiameterURI
+
+ The DiameterURI MUST follow the Uniform Resource Identifiers (URI)
+ syntax [RFC3986] rules specified below:
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 47]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ "aaa://" FQDN [ port ] [ transport ] [ protocol ]
+
+ ; No transport security
+
+ "aaas://" FQDN [ port ] [ transport ] [ protocol ]
+
+ ; Transport security used
+
+ FQDN = Fully Qualified Host Name
+
+ port = ":" 1*DIGIT
+
+ ; One of the ports used to listen for
+ ; incoming connections.
+ ; If absent, the default Diameter port
+ ; (3868) is assumed if no transport
+ ; security is used and port (TBD) when
+ ; transport security (TLS/TCP and DTLS/SCTP) is used.
+
+ transport = ";transport=" transport-protocol
+
+ ; One of the transports used to listen
+ ; for incoming connections. If absent,
+ ; the default protocol is assumed to be TCP.
+ ; UDP MUST NOT be used when the aaa-protocol
+ ; field is set to diameter.
+
+ transport-protocol = ( "tcp" / "sctp" / "udp" )
+
+ protocol = ";protocol=" aaa-protocol
+
+ ; If absent, the default AAA protocol
+ ; is Diameter.
+
+ aaa-protocol = ( "diameter" / "radius" / "tacacs+" )
+
+ The following are examples of valid Diameter host identities:
+
+ aaa://host.example.com;transport=tcp
+ aaa://host.example.com:6666;transport=tcp
+ aaa://host.example.com;protocol=diameter
+ aaa://host.example.com:6666;protocol=diameter
+ aaa://host.example.com:6666;transport=tcp;protocol=diameter
+ aaa://host.example.com:1813;transport=udp;protocol=radius
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 48]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Enumerated
+
+ Enumerated is derived from the Integer32 AVP Base Format. The
+ definition contains a list of valid values and their
+ interpretation and is described in the Diameter application
+ introducing the AVP.
+
+
+ IPFilterRule
+
+ The IPFilterRule format is derived from the OctetString AVP Base
+ Format and uses the ASCII charset. The rule syntax is a modified
+ subset of ipfw(8) from FreeBSD. Packets may be filtered based on
+ the following information that is associated with it:
+
+ Direction (in or out)
+ Source and destination IP address (possibly masked)
+ Protocol
+ Source and destination port (lists or ranges)
+ TCP flags
+ IP fragment flag
+ IP options
+ ICMP types
+
+ Rules for the appropriate direction are evaluated in order, with
+ the first matched rule terminating the evaluation. Each packet is
+ evaluated once. If no rule matches, the packet is dropped if the
+ last rule evaluated was a permit, and passed if the last rule was
+ a deny.
+
+ IPFilterRule filters MUST follow the format:
+
+ action dir proto from src to dst [options]
+
+ action permit - Allow packets that match the rule.
+ deny - Drop packets that match the rule.
+
+ dir "in" is from the terminal, "out" is to the
+ terminal.
+
+ proto An IP protocol specified by number. The "ip"
+ keyword means any protocol will match.
+
+ src and dst <address/mask> [ports]
+
+ The <address/mask> may be specified as:
+ ipno An IPv4 or IPv6 number in dotted-
+ quad or canonical IPv6 form. Only
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 49]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ this exact IP number will match the
+ rule.
+ ipno/bits An IP number as above with a mask
+ width of the form 192.0.2.10/24. In
+ this case, all IP numbers from
+ 192.0.2.0 to 192.0.2.255 will match.
+ The bit width MUST be valid for the
+ IP version and the IP number MUST
+ NOT have bits set beyond the mask.
+ For a match to occur, the same IP
+ version must be present in the
+ packet that was used in describing
+ the IP address. To test for a
+ particular IP version, the bits part
+ can be set to zero. The keyword
+ "any" is 0.0.0.0/0 or the IPv6
+ equivalent. The keyword "assigned"
+ is the address or set of addresses
+ assigned to the terminal. For IPv4,
+ a typical first rule is often "deny
+ in ip! assigned"
+
+ The sense of the match can be inverted by
+ preceding an address with the not modifier (!),
+ causing all other addresses to be matched
+ instead. This does not affect the selection of
+ port numbers.
+
+ With the TCP, UDP and SCTP protocols, optional
+ ports may be specified as:
+
+ {port/port-port}[,ports[,...]]
+
+ The '-' notation specifies a range of ports
+ (including boundaries).
+
+ Fragmented packets that have a non-zero offset
+ (i.e., not the first fragment) will never match
+ a rule that has one or more port
+ specifications. See the frag option for
+ details on matching fragmented packets.
+
+ options:
+ frag Match if the packet is a fragment and this is not
+ the first fragment of the datagram. frag may not
+ be used in conjunction with either tcpflags or
+ TCP/UDP port specifications.
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 50]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ ipoptions spec
+ Match if the IP header contains the comma
+ separated list of options specified in spec. The
+ supported IP options are:
+
+ ssrr (strict source route), lsrr (loose source
+ route), rr (record packet route) and ts
+ (timestamp). The absence of a particular option
+ may be denoted with a '!'.
+
+ tcpoptions spec
+ Match if the TCP header contains the comma
+ separated list of options specified in spec. The
+ supported TCP options are:
+
+ mss (maximum segment size), window (tcp window
+ advertisement), sack (selective ack), ts (rfc1323
+ timestamp) and cc (rfc1644 t/tcp connection
+ count). The absence of a particular option may
+ be denoted with a '!'.
+
+ established
+ TCP packets only. Match packets that have the RST
+ or ACK bits set.
+
+ setup TCP packets only. Match packets that have the SYN
+ bit set but no ACK bit.
+
+
+ tcpflags spec
+ TCP packets only. Match if the TCP header
+ contains the comma separated list of flags
+ specified in spec. The supported TCP flags are:
+
+ fin, syn, rst, psh, ack and urg. The absence of a
+ particular flag may be denoted with a '!'. A rule
+ that contains a tcpflags specification can never
+ match a fragmented packet that has a non-zero
+ offset. See the frag option for details on
+ matching fragmented packets.
+
+ icmptypes types
+ ICMP packets only. Match if the ICMP type is in
+ the list types. The list may be specified as any
+ combination of ranges or individual types
+ separated by commas. Both the numeric values and
+ the symbolic values listed below can be used. The
+ supported ICMP types are:
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 51]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ echo reply (0), destination unreachable (3),
+ source quench (4), redirect (5), echo request
+ (8), router advertisement (9), router
+ solicitation (10), time-to-live exceeded (11), IP
+ header bad (12), timestamp request (13),
+ timestamp reply (14), information request (15),
+ information reply (16), address mask request (17)
+ and address mask reply (18).
+
+ There is one kind of packet that the access device MUST always
+ discard, that is an IP fragment with a fragment offset of one.
+ This is a valid packet, but it only has one use, to try to
+ circumvent firewalls.
+
+ An access device that is unable to interpret or apply a deny rule
+ MUST terminate the session. An access device that is unable to
+ interpret or apply a permit rule MAY apply a more restrictive
+ rule. An access device MAY apply deny rules of its own before the
+ supplied rules, for example to protect the access device owner's
+ infrastructure.
+
+
+4.4. Grouped AVP Values
+
+ The Diameter protocol allows AVP values of type 'Grouped'. This
+ implies that the Data field is actually a sequence of AVPs. It is
+ possible to include an AVP with a Grouped type within a Grouped type,
+ that is, to nest them. AVPs within an AVP of type Grouped have the
+ same padding requirements as non-Grouped AVPs, as defined in Section
+ 4.
+
+ The AVP Code numbering space of all AVPs included in a Grouped AVP is
+ the same as for non-grouped AVPs. Receivers of a Grouped AVP that
+ does not have the 'M' (mandatory) bit set and one or more of the
+ encapsulated AVPs within the group has the 'M' (mandatory) bit set
+ MAY simply be ignored if the Grouped AVP itself is unrecognized. The
+ rule applies even if the encapsulated AVP with its 'M' (mandatory)
+ bit set is further encapsulated within other sub-groups; i.e. other
+ Grouped AVPs embedded within the Grouped AVP.
+
+ Every Grouped AVP defined MUST include a corresponding grammar, using
+ ABNF [RFC5234] (with modifications), as defined below.
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 52]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ grouped-avp-def = <name> "::=" avp
+
+ name-fmt = ALPHA *(ALPHA / DIGIT / "-")
+
+ name = name-fmt
+ ; The name has to be the name of an AVP,
+ ; defined in the base or extended Diameter
+ ; specifications.
+
+ avp = header [ *fixed] [ *required] [ *optional]
+
+ header = "<" "AVP-Header:" avpcode [vendor] ">"
+
+ avpcode = 1*DIGIT
+ ; The AVP Code assigned to the Grouped AVP
+
+ vendor = 1*DIGIT
+ ; The Vendor-ID assigned to the Grouped AVP.
+ ; If absent, the default value of zero is
+ ; used.
+
+4.4.1. Example AVP with a Grouped Data type
+
+ The Example-AVP (AVP Code 999999) is of type Grouped and is used to
+ clarify how Grouped AVP values work. The Grouped Data field has the
+ following ABNF grammar:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 53]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Example-AVP ::= < AVP Header: 999999 >
+ { Origin-Host }
+ 1*{ Session-Id }
+ *[ AVP ]
+
+ An Example-AVP with Grouped Data follows.
+
+ The Origin-Host AVP is required (Section 6.3). In this case:
+
+ Origin-Host = "example.com".
+
+
+ One or more Session-Ids must follow. Here there are two:
+
+ Session-Id =
+ "grump.example.com:33041;23432;893;0AF3B81"
+
+ Session-Id =
+ "grump.example.com:33054;23561;2358;0AF3B82"
+
+ optional AVPs included are
+
+ Recovery-Policy = <binary>
+ 2163bc1d0ad82371f6bc09484133c3f09ad74a0dd5346d54195a7cf0b35
+ 2cabc881839a4fdcfbc1769e2677a4c1fb499284c5f70b48f58503a45c5
+ c2d6943f82d5930f2b7c1da640f476f0e9c9572a50db8ea6e51e1c2c7bd
+ f8bb43dc995144b8dbe297ac739493946803e1cee3e15d9b765008a1b2a
+ cf4ac777c80041d72c01e691cf751dbf86e85f509f3988e5875dc905119
+ 26841f00f0e29a6d1ddc1a842289d440268681e052b30fb638045f7779c
+ 1d873c784f054f688f5001559ecff64865ef975f3e60d2fd7966b8c7f92
+
+ Futuristic-Acct-Record = <binary>
+ fe19da5802acd98b07a5b86cb4d5d03f0314ab9ef1ad0b67111ff3b90a0
+ 57fe29620bf3585fd2dd9fcc38ce62f6cc208c6163c008f4258d1bc88b8
+ 17694a74ccad3ec69269461b14b2e7a4c111fb239e33714da207983f58c
+ 41d018d56fe938f3cbf089aac12a912a2f0d1923a9390e5f789cb2e5067
+ d3427475e49968f841
+
+ The data for the optional AVPs is represented in hex since the format
+ of these AVPs is neither known at the time of definition of the
+ Example-AVP group, nor (likely) at the time when the example instance
+ of this AVP is interpreted - except by Diameter implementations which
+ support the same set of AVPs. The encoding example illustrates how
+ padding is used and how length fields are calculated. Also note that
+ AVPs may be present in the Grouped AVP value which the receiver
+ cannot interpret (here, the Recover-Policy and Futuristic-Acct-Record
+ AVPs). The length of the Example-AVP is the sum of all the length of
+ the member AVPs including their padding plus the Example-AVP header
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 54]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ size.
+
+
+ This AVP would be encoded as follows:
+
+ 0 1 2 3 4 5 6 7
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 0 | Example AVP Header (AVP Code = 999999), Length = 496 |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 8 | Origin-Host AVP Header (AVP Code = 264), Length = 19 |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 16 | 'e' | 'x' | 'a' | 'm' | 'p' | 'l' | 'e' | '.' |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 24 | 'c' | 'o' | 'm' |Padding| Session-Id AVP Header |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 32 | (AVP Code = 263), Length = 49 | 'g' | 'r' | 'u' | 'm' |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ . . .
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 72 | 'F' | '3' | 'B' | '8' | '1' |Padding|Padding|Padding|
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 80 | Session-Id AVP Header (AVP Code = 263), Length = 50 |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 88 | 'g' | 'r' | 'u' | 'm' | 'p' | '.' | 'e' | 'x' |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ . . .
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 120| '5' | '8' | ';' | '0' | 'A' | 'F' | '3' | 'B' |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 128| '8' | '2' |Padding|Padding| Recovery-Policy Header (AVP |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 136| Code = 8341), Length = 223 | 0x21 | 0x63 | 0xbc | 0x1d |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 144| 0x0a | 0xd8 | 0x23 | 0x71 | 0xf6 | 0xbc | 0x09 | 0x48 |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ . . .
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 352| 0x8c | 0x7f | 0x92 |Padding| Futuristic-Acct-Record Header |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 328|(AVP Code = 15930),Length = 137| 0xfe | 0x19 | 0xda | 0x58 |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 336| 0x02 | 0xac | 0xd9 | 0x8b | 0x07 | 0xa5 | 0xb8 | 0xc6 |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ . . .
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 488| 0xe4 | 0x99 | 0x68 | 0xf8 | 0x41 |Padding|Padding|Padding|
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 55]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+4.5. Diameter Base Protocol AVPs
+
+ The following table describes the Diameter AVPs defined in the base
+ protocol, their AVP Code values, types, possible flag values.
+
+ Due to space constraints, the short form DiamIdent is used to
+ represent DiameterIdentity.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 56]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ +----------+
+ | AVP Flag |
+ | rules |
+ |----+-----|
+ AVP Section | |MUST |
+ Attribute Name Code Defined Data Type |MUST| NOT |
+ -----------------------------------------|----+-----|
+ Acct- 85 9.8.2 Unsigned32 | M | V |
+ Interim-Interval | | |
+ Accounting- 483 9.8.7 Enumerated | M | V |
+ Realtime-Required | | |
+ Acct- 50 9.8.5 UTF8String | M | V |
+ Multi-Session-Id | | |
+ Accounting- 485 9.8.3 Unsigned32 | M | V |
+ Record-Number | | |
+ Accounting- 480 9.8.1 Enumerated | M | V |
+ Record-Type | | |
+ Accounting- 44 9.8.4 OctetString| M | V |
+ Session-Id | | |
+ Accounting- 287 9.8.6 Unsigned64 | M | V |
+ Sub-Session-Id | | |
+ Acct- 259 6.9 Unsigned32 | M | V |
+ Application-Id | | |
+ Auth- 258 6.8 Unsigned32 | M | V |
+ Application-Id | | |
+ Auth-Request- 274 8.7 Enumerated | M | V |
+ Type | | |
+ Authorization- 291 8.9 Unsigned32 | M | V |
+ Lifetime | | |
+ Auth-Grace- 276 8.10 Unsigned32 | M | V |
+ Period | | |
+ Auth-Session- 277 8.11 Enumerated | M | V |
+ State | | |
+ Re-Auth-Request- 285 8.12 Enumerated | M | V |
+ Type | | |
+ Class 25 8.20 OctetString| M | V |
+ Destination-Host 293 6.5 DiamIdent | M | V |
+ Destination- 283 6.6 DiamIdent | M | V |
+ Realm | | |
+ Disconnect-Cause 273 5.4.3 Enumerated | M | V |
+ Error-Message 281 7.3 UTF8String | | V,M |
+ Error-Reporting- 294 7.4 DiamIdent | | V,M |
+ Host | | |
+ Event-Timestamp 55 8.21 Time | M | V |
+ Experimental- 297 7.6 Grouped | M | V |
+ Result | | |
+ -----------------------------------------|----+-----|
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 57]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ +----------+
+ | AVP Flag |
+ | rules |
+ |----+-----|
+ AVP Section | |MUST |
+ Attribute Name Code Defined Data Type |MUST| NOT |
+ -----------------------------------------|----+-----|
+ Experimental- 298 7.7 Unsigned32 | M | V |
+ Result-Code | | |
+ Failed-AVP 279 7.5 Grouped | M | V |
+ Firmware- 267 5.3.4 Unsigned32 | | V,M |
+ Revision | | |
+ Host-IP-Address 257 5.3.5 Address | M | V |
+ Inband-Security | M | V |
+ -Id 299 6.10 Unsigned32 | | |
+ Multi-Round- 272 8.19 Unsigned32 | M | V |
+ Time-Out | | |
+ Origin-Host 264 6.3 DiamIdent | M | V |
+ Origin-Realm 296 6.4 DiamIdent | M | V |
+ Origin-State-Id 278 8.16 Unsigned32 | M | V |
+ Product-Name 269 5.3.7 UTF8String | | V,M |
+ Proxy-Host 280 6.7.3 DiamIdent | M | V |
+ Proxy-Info 284 6.7.2 Grouped | M | V |
+ Proxy-State 33 6.7.4 OctetString| M | V |
+ Redirect-Host 292 6.12 DiamURI | M | V |
+ Redirect-Host- 261 6.13 Enumerated | M | V |
+ Usage | | |
+ Redirect-Max- 262 6.14 Unsigned32 | M | V |
+ Cache-Time | | |
+ Result-Code 268 7.1 Unsigned32 | M | V |
+ Route-Record 282 6.7.1 DiamIdent | M | V |
+ Session-Id 263 8.8 UTF8String | M | V |
+ Session-Timeout 27 8.13 Unsigned32 | M | V |
+ Session-Binding 270 8.17 Unsigned32 | M | V |
+ Session-Server- 271 8.18 Enumerated | M | V |
+ Failover | | |
+ Supported- 265 5.3.6 Unsigned32 | M | V |
+ Vendor-Id | | |
+ Termination- 295 8.15 Enumerated | M | V |
+ Cause | | |
+ User-Name 1 8.14 UTF8String | M | V |
+ Vendor-Id 266 5.3.3 Unsigned32 | M | V |
+ Vendor-Specific- 260 6.11 Grouped | M | V |
+ Application-Id | | |
+ -----------------------------------------|----+-----|
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 58]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+5. Diameter Peers
+
+ This section describes how Diameter nodes establish connections and
+ communicate with peers.
+
+5.1. Peer Connections
+
+ Connections between diameter peers are established using their valid
+ DiameterIdentity. A Diameter node initiating a connection to a peer
+ MUST know the peers DiameterIdentity. Methods for discovering a
+ Diameter peer can be found in Section 5.2.
+
+ Although a Diameter node may have many possible peers that it is able
+ to communicate with, it may not be economical to have an established
+ connection to all of them. At a minimum, a Diameter node SHOULD have
+ an established connection with two peers per realm, known as the
+ primary and secondary peers. Of course, a node MAY have additional
+ connections, if it is deemed necessary. Typically, all messages for
+ a realm are sent to the primary peer, but in the event that failover
+ procedures are invoked, any pending requests are sent to the
+ secondary peer. However, implementations are free to load balance
+ requests between a set of peers.
+
+ Note that a given peer MAY act as a primary for a given realm, while
+ acting as a secondary for another realm.
+
+ When a peer is deemed suspect, which could occur for various reasons,
+ including not receiving a DWA within an allotted timeframe, no new
+ requests should be forwarded to the peer, but failover procedures are
+ invoked. When an active peer is moved to this mode, additional
+ connections SHOULD be established to ensure that the necessary number
+ of active connections exists.
+
+ There are two ways that a peer is removed from the suspect peer list:
+
+
+ 1. The peer is no longer reachable, causing the transport connection
+ to be shutdown. The peer is moved to the closed state.
+
+ 2. Three watchdog messages are exchanged with accepted round trip
+ times, and the connection to the peer is considered stabilized.
+
+ In the event the peer being removed is either the primary or
+ secondary, an alternate peer SHOULD replace the deleted peer, and
+ assume the role of either primary or secondary.
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 59]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+5.2. Diameter Peer Discovery
+
+ Allowing for dynamic Diameter agent discovery will make it possible
+ for simpler and more robust deployment of Diameter services. In
+ order to promote interoperable implementations of Diameter peer
+ discovery, the following mechanisms are described. These are based
+ on existing IETF standards. The first option (manual configuration)
+ MUST be supported by all Diameter nodes, while the latter option
+ (DNS) MAY be supported.
+
+ There are two cases where Diameter peer discovery may be performed.
+ The first is when a Diameter client needs to discover a first-hop
+ Diameter agent. The second case is when a Diameter agent needs to
+ discover another agent - for further handling of a Diameter
+ operation. In both cases, the following 'search order' is
+ recommended:
+
+
+ 1. The Diameter implementation consults its list of static
+ (manually) configured Diameter agent locations. These will be
+ used if they exist and respond.
+
+
+ 2. The Diameter implementation performs a NAPTR query for a server
+ in a particular realm. The Diameter implementation has to know
+ in advance which realm to look for a Diameter agent. This could
+ be deduced, for example, from the 'realm' in a NAI that a
+ Diameter implementation needed to perform a Diameter operation
+ on.
+
+ The NAPTR usage in Diameter follows the S-NAPTR DDDS application
+ [RFC3958] in which the SERVICE field includes tags for the
+ desired application and supported application protocol. The
+ application service tag for a Diameter application is 'aaa' and
+ the supported application protocol tags are 'diameter.tcp',
+ 'diameter.sctp', 'diameter.dtls' or 'diameter.tls.tcp'.
+
+ The client can follow the resolution process defined by the
+ S-NAPTR DDDS [RFC3958] application to find a matching SRV, A or
+ AAAA record of a suitable peer. The domain suffixes in the NAPTR
+ replacement field SHOULD match the domain of the original query.
+ An example can be found in Appendix B.
+
+ 3. If no NAPTR records are found, the requester directly queries for
+ SRV records '_diameter._sctp'.realm, '_diameter._dtls'.realm,
+ '_diameter._tcp'.realm and '_diameter._tls'.realm depending on
+ the requesters network protocol capabilities. If SRV records are
+ found then the requester can perform address record query (A RR's
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 60]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ and/or AAAA RR's) for the target hostname specified in the SRV
+ records. If no SRV records are found, the requester gives up.
+
+ If the server is using a site certificate, the domain name in the
+ NAPTR query and the domain name in the replacement field MUST both be
+ valid based on the site certificate handed out by the server in the
+ TLS/TCP and DTLS/SCTP or IKE exchange. Similarly, the domain name in
+ the SRV query and the domain name in the target in the SRV record
+ MUST both be valid based on the same site certificate. Otherwise, an
+ attacker could modify the DNS records to contain replacement values
+ in a different domain, and the client could not validate that this
+ was the desired behavior, or the result of an attack.
+
+ Also, the Diameter Peer MUST check to make sure that the discovered
+ peers are authorized to act in its role. Authentication via IKE or
+ TLS/TCP and DTLS/SCTP, or validation of DNS RRs via DNSSEC is not
+ sufficient to conclude this. For example, a web server may have
+ obtained a valid TLS/TCP and DTLS/SCTP certificate, and secured RRs
+ may be included in the DNS, but this does not imply that it is
+ authorized to act as a Diameter Server.
+
+ Authorization can be achieved for example, by configuration of a
+ Diameter Server CA. Alternatively this can be achieved by definition
+ of OIDs within TLS/TCP and DTLS/SCTP or IKE certificates so as to
+ signify Diameter Server authorization.
+
+ A dynamically discovered peer causes an entry in the Peer Table (see
+ Section 2.6) to be created. Note that entries created via DNS MUST
+ expire (or be refreshed) within the DNS TTL. If a peer is discovered
+ outside of the local realm, a routing table entry (see Section 2.7)
+ for the peer's realm is created. The routing table entry's
+ expiration MUST match the peer's expiration value.
+
+5.3. Capabilities Exchange
+
+ When two Diameter peers establish a transport connection, they MUST
+ exchange the Capabilities Exchange messages, as specified in the peer
+ state machine (see Section 5.6). This message allows the discovery
+ of a peer's identity and its capabilities (protocol version number,
+ supported Diameter applications, security mechanisms, etc.)
+
+ The receiver only issues commands to its peers that have advertised
+ support for the Diameter application that defines the command. A
+ Diameter node MUST cache the supported applications in order to
+ ensure that unrecognized commands and/or AVPs are not unnecessarily
+ sent to a peer.
+
+ A receiver of a Capabilities-Exchange-Req (CER) message that does not
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 61]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ have any applications in common with the sender MUST return a
+ Capabilities-Exchange-Answer (CEA) with the Result-Code AVP set to
+ DIAMETER_NO_COMMON_APPLICATION, and SHOULD disconnect the transport
+ layer connection. Note that receiving a CER or CEA from a peer
+ advertising itself as a Relay (see Section 2.4) MUST be interpreted
+ as having common applications with the peer.
+
+ The receiver of the Capabilities-Exchange-Request (CER) MUST
+ determine common applications by computing the intersection of its
+ own set of supported Application Id against all of the application
+ identifier AVPs (Auth-Application-Id, Acct-Application-Id and Vendor-
+ Specific-Application-Id) present in the CER. The value of the
+ Vendor-Id AVP in the Vendor-Specific-Application-Id MUST NOT be used
+ during computation. The sender of the Capabilities-Exchange-Answer
+ (CEA) SHOULD include all of its supported applications as a hint to
+ the receiver regarding all of its application capabilities.
+
+ Diameter implementations SHOULD first attempt to establish a TLS/TCP
+ and DTLS/SCTP connection prior to the CER/CEA exchange. This
+ protects the capabilities information of both peers. To support
+ older Diameter implementations that do not fully conform to this
+ document, the transport security MAY still be negotiated via Inband-
+ Security AVP. In this case, the receiver of a Capabilities-Exchange-
+ Req (CER) message that does not have any security mechanisms in
+ common with the sender MUST return a Capabilities-Exchange-Answer
+ (CEA) with the Result-Code AVP set to DIAMETER_NO_COMMON_SECURITY,
+ and SHOULD disconnect the transport layer connection.
+
+ CERs received from unknown peers MAY be silently discarded, or a CEA
+ MAY be issued with the Result-Code AVP set to DIAMETER_UNKNOWN_PEER.
+ In both cases, the transport connection is closed. If the local
+ policy permits receiving CERs from unknown hosts, a successful CEA
+ MAY be returned. If a CER from an unknown peer is answered with a
+ successful CEA, the lifetime of the peer entry is equal to the
+ lifetime of the transport connection. In case of a transport
+ failure, all the pending transactions destined to the unknown peer
+ can be discarded.
+
+ The CER and CEA messages MUST NOT be proxied, redirected or relayed.
+
+ Since the CER/CEA messages cannot be proxied, it is still possible
+ that an upstream agent receives a message for which it has no
+ available peers to handle the application that corresponds to the
+ Command-Code. In such instances, the 'E' bit is set in the answer
+ message (see Section 7.) with the Result-Code AVP set to
+ DIAMETER_UNABLE_TO_DELIVER to inform the downstream to take action
+ (e.g., re-routing request to an alternate peer).
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 62]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ With the exception of the Capabilities-Exchange-Request message, a
+ message of type Request that includes the Auth-Application-Id or
+ Acct-Application-Id AVPs, or a message with an application-specific
+ command code, MAY only be forwarded to a host that has explicitly
+ advertised support for the application (or has advertised the Relay
+ Application Id).
+
+5.3.1. Capabilities-Exchange-Request
+
+ The Capabilities-Exchange-Request (CER), indicated by the Command-
+ Code set to 257 and the Command Flags' 'R' bit set, is sent to
+ exchange local capabilities. Upon detection of a transport failure,
+ this message MUST NOT be sent to an alternate peer.
+
+ When Diameter is run over SCTP [RFC4960] or DTLS/SCTP [RFC6083],
+ which allow for connections to span multiple interfaces and multiple
+ IP addresses, the Capabilities-Exchange-Request message MUST contain
+ one Host-IP- Address AVP for each potential IP address that MAY be
+ locally used when transmitting Diameter messages.
+
+ Message Format
+
+ <CER> ::= < Diameter Header: 257, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+ 1* { Host-IP-Address }
+ { Vendor-Id }
+ { Product-Name }
+ [ Origin-State-Id ]
+ * [ Supported-Vendor-Id ]
+ * [ Auth-Application-Id ]
+ * [ Inband-Security-Id ]
+ * [ Acct-Application-Id ]
+ * [ Vendor-Specific-Application-Id ]
+ [ Firmware-Revision ]
+ * [ AVP ]
+
+5.3.2. Capabilities-Exchange-Answer
+
+ The Capabilities-Exchange-Answer (CEA), indicated by the Command-Code
+ set to 257 and the Command Flags' 'R' bit cleared, is sent in
+ response to a CER message.
+
+ When Diameter is run over SCTP [RFC4960] or DTLS/SCTP [RFC6083],
+ which allow connections to span multiple interfaces, hence, multiple
+ IP addresses, the Capabilities-Exchange-Answer message MUST contain
+ one Host-IP-Address AVP for each potential IP address that MAY be
+ locally used when transmitting Diameter messages.
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 63]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Message Format
+
+ <CEA> ::= < Diameter Header: 257 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ 1* { Host-IP-Address }
+ { Vendor-Id }
+ { Product-Name }
+ [ Origin-State-Id ]
+ [ Error-Message ]
+ [ Failed-AVP ]
+ * [ Supported-Vendor-Id ]
+ * [ Auth-Application-Id ]
+ * [ Inband-Security-Id ]
+ * [ Acct-Application-Id ]
+ * [ Vendor-Specific-Application-Id ]
+ [ Firmware-Revision ]
+ * [ AVP ]
+
+5.3.3. Vendor-Id AVP
+
+ The Vendor-Id AVP (AVP Code 266) is of type Unsigned32 and contains
+ the IANA "SMI Network Management Private Enterprise Codes" [RFC3232]
+ value assigned to the vendor of the Diameter device. It is
+ envisioned that the combination of the Vendor-Id, Product-Name
+ (Section 5.3.7) and the Firmware-Revision (Section 5.3.4) AVPs may
+ provide useful debugging information.
+
+ A Vendor-Id value of zero in the CER or CEA messages is reserved and
+ indicates that this field is ignored.
+
+5.3.4. Firmware-Revision AVP
+
+ The Firmware-Revision AVP (AVP Code 267) is of type Unsigned32 and is
+ used to inform a Diameter peer of the firmware revision of the
+ issuing device.
+
+ For devices that do not have a firmware revision (general purpose
+ computers running Diameter software modules, for instance), the
+ revision of the Diameter software module may be reported instead.
+
+5.3.5. Host-IP-Address AVP
+
+ The Host-IP-Address AVP (AVP Code 257) is of type Address and is used
+ to inform a Diameter peer of the sender's IP address. All source
+ addresses that a Diameter node expects to use with SCTP [RFC4960] or
+ DTLS/SCTP [RFC6083] MUST be advertised in the CER and CEA messages by
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 64]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ including a Host-IP-Address AVP for each address.
+
+5.3.6. Supported-Vendor-Id AVP
+
+ The Supported-Vendor-Id AVP (AVP Code 265) is of type Unsigned32 and
+ contains the IANA "SMI Network Management Private Enterprise Codes"
+ [RFC3232] value assigned to a vendor other than the device vendor but
+ including the application vendor. This is used in the CER and CEA
+ messages in order to inform the peer that the sender supports (a
+ subset of) the vendor-specific AVPs defined by the vendor identified
+ in this AVP. The value of this AVP MUST NOT be set to zero.
+ Multiple instances of this AVP containing the same value SHOULD NOT
+ be sent.
+
+5.3.7. Product-Name AVP
+
+ The Product-Name AVP (AVP Code 269) is of type UTF8String, and
+ contains the vendor assigned name for the product. The Product-Name
+ AVP SHOULD remain constant across firmware revisions for the same
+ product.
+
+5.4. Disconnecting Peer connections
+
+ When a Diameter node disconnects one of its transport connections,
+ its peer cannot know the reason for the disconnect, and will most
+ likely assume that a connectivity problem occurred, or that the peer
+ has rebooted. In these cases, the peer may periodically attempt to
+ reconnect, as stated in Section 2.1. In the event that the
+ disconnect was a result of either a shortage of internal resources,
+ or simply that the node in question has no intentions of forwarding
+ any Diameter messages to the peer in the foreseeable future, a
+ periodic connection request would not be welcomed. The
+ Disconnection-Reason AVP contains the reason the Diameter node issued
+ the Disconnect-Peer-Request message.
+
+ The Disconnect-Peer-Request message is used by a Diameter node to
+ inform its peer of its intent to disconnect the transport layer, and
+ that the peer shouldn't reconnect unless it has a valid reason to do
+ so (e.g., message to be forwarded). Upon receipt of the message, the
+ Disconnect-Peer-Answer is returned, which SHOULD contain an error if
+ messages have recently been forwarded, and are likely in flight,
+ which would otherwise cause a race condition.
+
+ The receiver of the Disconnect-Peer-Answer initiates the transport
+ disconnect. The sender of the Disconnect-Peer-Answer should be able
+ to detect the transport closure and cleanup the connection.
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 65]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+5.4.1. Disconnect-Peer-Request
+
+ The Disconnect-Peer-Request (DPR), indicated by the Command-Code set
+ to 282 and the Command Flags' 'R' bit set, is sent to a peer to
+ inform its intentions to shutdown the transport connection. Upon
+ detection of a transport failure, this message MUST NOT be sent to an
+ alternate peer.
+
+ Message Format
+
+ <DPR> ::= < Diameter Header: 282, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+ { Disconnect-Cause }
+ * [ AVP ]
+
+5.4.2. Disconnect-Peer-Answer
+
+ The Disconnect-Peer-Answer (DPA), indicated by the Command-Code set
+ to 282 and the Command Flags' 'R' bit cleared, is sent as a response
+ to the Disconnect-Peer-Request message. Upon receipt of this
+ message, the transport connection is shutdown.
+
+ Message Format
+
+ <DPA> ::= < Diameter Header: 282 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Error-Message ]
+ [ Failed-AVP ]
+ * [ AVP ]
+
+5.4.3. Disconnect-Cause AVP
+
+ The Disconnect-Cause AVP (AVP Code 273) is of type Enumerated. A
+ Diameter node MUST include this AVP in the Disconnect-Peer-Request
+ message to inform the peer of the reason for its intention to
+ shutdown the transport connection. The following values are
+ supported:
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 66]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ REBOOTING 0
+ A scheduled reboot is imminent. Receiver of DPR with above result
+ code MAY attempt reconnection.
+
+ BUSY 1
+ The peer's internal resources are constrained, and it has
+ determined that the transport connection needs to be closed.
+ Receiver of DPR with above result code SHOULD NOT attempt
+ reconnection.
+
+ DO_NOT_WANT_TO_TALK_TO_YOU 2
+ The peer has determined that it does not see a need for the
+ transport connection to exist, since it does not expect any
+ messages to be exchanged in the near future. Receiver of DPR
+ with above result code SHOULD NOT attempt reconnection.
+
+5.5. Transport Failure Detection
+
+ Given the nature of the Diameter protocol, it is recommended that
+ transport failures be detected as soon as possible. Detecting such
+ failures will minimize the occurrence of messages sent to unavailable
+ agents, resulting in unnecessary delays, and will provide better
+ failover performance. The Device-Watchdog-Request and Device-
+ Watchdog-Answer messages, defined in this section, are used to pro-
+ actively detect transport failures.
+
+5.5.1. Device-Watchdog-Request
+
+ The Device-Watchdog-Request (DWR), indicated by the Command-Code set
+ to 280 and the Command Flags' 'R' bit set, is sent to a peer when no
+ traffic has been exchanged between two peers (see Section 5.5.3).
+ Upon detection of a transport failure, this message MUST NOT be sent
+ to an alternate peer.
+
+ Message Format
+
+ <DWR> ::= < Diameter Header: 280, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+ [ Origin-State-Id ]
+ * [ AVP ]
+
+5.5.2. Device-Watchdog-Answer
+
+ The Device-Watchdog-Answer (DWA), indicated by the Command-Code set
+ to 280 and the Command Flags' 'R' bit cleared, is sent as a response
+ to the Device-Watchdog-Request message.
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 67]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Message Format
+
+ <DWA> ::= < Diameter Header: 280 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Error-Message ]
+ [ Failed-AVP ]
+ [ Origin-State-Id ]
+ * [ AVP ]
+
+5.5.3. Transport Failure Algorithm
+
+ The transport failure algorithm is defined in [RFC3539]. All
+ Diameter implementations MUST support the algorithm defined in the
+ specification in order to be compliant to the Diameter base protocol.
+
+5.5.4. Failover and Failback Procedures
+
+ In the event that a transport failure is detected with a peer, it is
+ necessary for all pending request messages to be forwarded to an
+ alternate agent, if possible. This is commonly referred to as
+ failover.
+
+ In order for a Diameter node to perform failover procedures, it is
+ necessary for the node to maintain a pending message queue for a
+ given peer. When an answer message is received, the corresponding
+ request is removed from the queue. The Hop-by-Hop Identifier field
+ is used to match the answer with the queued request.
+
+ When a transport failure is detected, if possible all messages in the
+ queue are sent to an alternate agent with the T flag set. On booting
+ a Diameter client or agent, the T flag is also set on any records
+ still remaining to be transmitted in non-volatile storage. An
+ example of a case where it is not possible to forward the message to
+ an alternate server is when the message has a fixed destination, and
+ the unavailable peer is the message's final destination (see
+ Destination-Host AVP). Such an error requires that the agent return
+ an answer message with the 'E' bit set and the Result-Code AVP set to
+ DIAMETER_UNABLE_TO_DELIVER.
+
+ It is important to note that multiple identical requests or answers
+ MAY be received as a result of a failover. The End-to-End Identifier
+ field in the Diameter header along with the Origin-Host AVP MUST be
+ used to identify duplicate messages.
+
+ As described in Section 2.1, a connection request should be
+ periodically attempted with the failed peer in order to re-establish
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 68]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ the transport connection. Once a connection has been successfully
+ established, messages can once again be forwarded to the peer. This
+ is commonly referred to as failback.
+
+5.6. Peer State Machine
+
+ This section contains a finite state machine that MUST be observed by
+ all Diameter implementations. Each Diameter node MUST follow the
+ state machine described below when communicating with each peer.
+ Multiple actions are separated by commas, and may continue on
+ succeeding lines, as space requires. Similarly, state and next state
+ may also span multiple lines, as space requires.
+
+ This state machine is closely coupled with the state machine
+ described in [RFC3539], which is used to open, close, failover,
+ probe, and reopen transport connections. Note in particular that
+ [RFC3539] requires the use of watchdog messages to probe connections.
+ For Diameter, DWR and DWA messages are to be used.
+
+ I- is used to represent the initiator (connecting) connection, while
+ the R- is used to represent the responder (listening) connection.
+ The lack of a prefix indicates that the event or action is the same
+ regardless of the connection on which the event occurred.
+
+ The stable states that a state machine may be in are Closed, I-Open
+ and R-Open; all other states are intermediate. Note that I-Open and
+ R-Open are equivalent except for whether the initiator or responder
+ transport connection is used for communication.
+
+ A CER message is always sent on the initiating connection immediately
+ after the connection request is successfully completed. In the case
+ of an election, one of the two connections will shut down. The
+ responder connection will survive if the Origin-Host of the local
+ Diameter entity is higher than that of the peer; the initiator
+ connection will survive if the peer's Origin-Host is higher. All
+ subsequent messages are sent on the surviving connection. Note that
+ the results of an election on one peer are guaranteed to be the
+ inverse of the results on the other.
+
+ For TLS/TCP and DTLS/SCTP usage, TLS/TCP and DTLS/SCTP handshake
+ SHOULD begin when both ends are in the closed state prior to any
+ Diameter message exchanges. The TLS/TCP and DTLS/SCTP connection
+ SHOULD be established before sending any CER or CEA message to secure
+ and protect the capabilities information of both peers. The TLS/TCP
+ and DTLS/SCTP connection SHOULD be disconnected when the state
+ machine moves to the closed state. When connecting to responders
+ that do not conform to this document (i.e. older Diameter
+ implementations that are not prepared to received TLS/TCP and DTLS/
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 69]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ SCTP connections in the closed state), the initial TLS/TCP and DTLS/
+ SCTP connection attempt will fail. The initiator MAY then attempt to
+ connect via TCP or SCTP and initiate the TLS/TCP and DTLS/SCTP
+ handshake when both ends are in the open state. If the handshake is
+ successful, all further messages will be sent via TLS/TCP and DTLS/
+ SCTP. If the handshake fails, both ends move to the closed state.
+
+ The state machine constrains only the behavior of a Diameter
+ implementation as seen by Diameter peers through events on the wire.
+
+ Any implementation that produces equivalent results is considered
+ compliant.
+
+ state event action next state
+ -----------------------------------------------------------------
+ Closed Start I-Snd-Conn-Req Wait-Conn-Ack
+ R-Conn-CER R-Accept, R-Open
+ Process-CER,
+ R-Snd-CEA
+
+ Wait-Conn-Ack I-Rcv-Conn-Ack I-Snd-CER Wait-I-CEA
+ I-Rcv-Conn-Nack Cleanup Closed
+ R-Conn-CER R-Accept, Wait-Conn-Ack/
+ Process-CER Elect
+ Timeout Error Closed
+
+ Wait-I-CEA I-Rcv-CEA Process-CEA I-Open
+ R-Conn-CER R-Accept, Wait-Returns
+ Process-CER,
+ Elect
+ I-Peer-Disc I-Disc Closed
+ I-Rcv-Non-CEA Error Closed
+ Timeout Error Closed
+
+ Wait-Conn-Ack/ I-Rcv-Conn-Ack I-Snd-CER,Elect Wait-Returns
+ Elect I-Rcv-Conn-Nack R-Snd-CEA R-Open
+ R-Peer-Disc R-Disc Wait-Conn-Ack
+ R-Conn-CER R-Reject Wait-Conn-Ack/
+ Elect
+ Timeout Error Closed
+
+ Wait-Returns Win-Election I-Disc,R-Snd-CEA R-Open
+ I-Peer-Disc I-Disc, R-Open
+ R-Snd-CEA
+ I-Rcv-CEA R-Disc I-Open
+ R-Peer-Disc R-Disc Wait-I-CEA
+ R-Conn-CER R-Reject Wait-Returns
+ Timeout Error Closed
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 70]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ R-Open Send-Message R-Snd-Message R-Open
+ R-Rcv-Message Process R-Open
+ R-Rcv-DWR Process-DWR, R-Open
+ R-Snd-DWA
+ R-Rcv-DWA Process-DWA R-Open
+ R-Conn-CER R-Reject R-Open
+ Stop R-Snd-DPR Closing
+ R-Rcv-DPR R-Snd-DPA, Closed
+ R-Disc
+ R-Peer-Disc R-Disc Closed
+
+ I-Open Send-Message I-Snd-Message I-Open
+ I-Rcv-Message Process I-Open
+ I-Rcv-DWR Process-DWR, I-Open
+ I-Snd-DWA
+ I-Rcv-DWA Process-DWA I-Open
+ R-Conn-CER R-Reject I-Open
+ Stop I-Snd-DPR Closing
+ I-Rcv-DPR I-Snd-DPA, Closed
+ I-Disc
+ I-Peer-Disc I-Disc Closed
+
+ Closing I-Rcv-DPA I-Disc Closed
+ R-Rcv-DPA R-Disc Closed
+ Timeout Error Closed
+ I-Peer-Disc I-Disc Closed
+ R-Peer-Disc R-Disc Closed
+
+5.6.1. Incoming connections
+
+ When a connection request is received from a Diameter peer, it is
+ not, in the general case, possible to know the identity of that peer
+ until a CER is received from it. This is because host and port
+ determine the identity of a Diameter peer; and the source port of an
+ incoming connection is arbitrary. Upon receipt of CER, the identity
+ of the connecting peer can be uniquely determined from Origin-Host.
+
+ For this reason, a Diameter peer must employ logic separate from the
+ state machine to receive connection requests, accept them, and await
+ CER. Once CER arrives on a new connection, the Origin-Host that
+ identifies the peer is used to locate the state machine associated
+ with that peer, and the new connection and CER are passed to the
+ state machine as an R-Conn-CER event.
+
+ The logic that handles incoming connections SHOULD close and discard
+ the connection if any message other than CER arrives, or if an
+ implementation-defined timeout occurs prior to receipt of CER.
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 71]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Because handling of incoming connections up to and including receipt
+ of CER requires logic, separate from that of any individual state
+ machine associated with a particular peer, it is described separately
+ in this section rather than in the state machine above.
+
+5.6.2. Events
+
+ Transitions and actions in the automaton are caused by events. In
+ this section, we will ignore the -I and -R prefix, since the actual
+ event would be identical, but would occur on one of two possible
+ connections.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 72]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Start The Diameter application has signaled that a
+ connection should be initiated with the peer.
+
+ R-Conn-CER An acknowledgement is received stating that the
+ transport connection has been established, and the
+ associated CER has arrived.
+
+ Rcv-Conn-Ack A positive acknowledgement is received confirming that
+ the transport connection is established.
+
+ Rcv-Conn-Nack A negative acknowledgement was received stating that
+ the transport connection was not established.
+
+ Timeout An application-defined timer has expired while waiting
+ for some event.
+
+ Rcv-CER A CER message from the peer was received.
+
+ Rcv-CEA A CEA message from the peer was received.
+
+ Rcv-Non-CEA A message other than CEA from the peer was received.
+
+ Peer-Disc A disconnection indication from the peer was received.
+
+ Rcv-DPR A DPR message from the peer was received.
+
+ Rcv-DPA A DPA message from the peer was received.
+
+ Win-Election An election was held, and the local node was the
+ winner.
+
+ Send-Message A message is to be sent.
+
+ Rcv-Message A message other than CER, CEA, DPR, DPA, DWR or DWA
+ was received.
+
+ Stop The Diameter application has signaled that a
+ connection should be terminated (e.g., on system
+ shutdown).
+
+5.6.3. Actions
+
+ Actions in the automaton are caused by events and typically indicate
+ the transmission of packets and/or an action to be taken on the
+ connection. In this section we will ignore the I- and R-prefix,
+ since the actual action would be identical, but would occur on one of
+ two possible connections.
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 73]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Snd-Conn-Req A transport connection is initiated with the peer.
+
+ Accept The incoming connection associated with the R-Conn-CER
+ is accepted as the responder connection.
+
+ Reject The incoming connection associated with the R-Conn-CER
+ is disconnected.
+
+ Process-CER The CER associated with the R-Conn-CER is processed.
+ Snd-CER A CER message is sent to the peer.
+
+ Snd-CEA A CEA message is sent to the peer.
+
+ Cleanup If necessary, the connection is shutdown, and any
+ local resources are freed.
+
+ Error The transport layer connection is disconnected,
+ either politely or abortively, in response to
+ an error condition. Local resources are freed.
+
+ Process-CEA A received CEA is processed.
+
+ Snd-DPR A DPR message is sent to the peer.
+
+ Snd-DPA A DPA message is sent to the peer.
+
+ Disc The transport layer connection is disconnected,
+ and local resources are freed.
+
+ Elect An election occurs (see Section 5.6.4 for more
+ information).
+
+ Snd-Message A message is sent.
+
+ Snd-DWR A DWR message is sent.
+
+ Snd-DWA A DWA message is sent.
+
+ Process-DWR The DWR message is serviced.
+
+ Process-DWA The DWA message is serviced.
+
+ Process A message is serviced.
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 74]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+5.6.4. The Election Process
+
+ The election is performed on the responder. The responder compares
+ the Origin-Host received in the CER with its own Origin-Host as two
+ streams of octets. If the local Origin-Host lexicographically
+ succeeds the received Origin-Host a Win-Election event is issued
+ locally. Diameter identities are in ASCII form therefore the lexical
+ comparison is consistent with DNS case insensitivity where octets
+ that fall in the ASCII range 'a' through 'z' MUST compare equally to
+ their upper-case counterparts between 'A' and 'Z'. See Appendix D
+ for interactions between the Diameter protocol and Internationalized
+ Domain Name (IDNs).
+
+ The winner of the election MUST close the connection it initiated.
+ Historically, maintaining the responder side of a connection was more
+ efficient than maintaining the initiator side. However, current
+ practices makes this distinction irrelevant.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 75]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+6. Diameter message processing
+
+ This section describes how Diameter requests and answers are created
+ and processed.
+
+6.1. Diameter Request Routing Overview
+
+ A request is sent towards its final destination using a combination
+ of the Destination-Realm and Destination-Host AVPs, in one of these
+ three combinations:
+
+ o a request that is not able to be proxied (such as CER) MUST NOT
+ contain either Destination-Realm or Destination-Host AVPs.
+
+ o a request that needs to be sent to a home server serving a
+ specific realm, but not to a specific server (such as the first
+ request of a series of round-trips), MUST contain a Destination-
+ Realm AVP, but MUST NOT contain a Destination-Host AVP. For
+ Diameter clients, the value of the Destination-Realm AVP MAY be
+ extracted from the User-Name AVP, or other methods.
+
+ o otherwise, a request that needs to be sent to a specific home
+ server among those serving a given realm, MUST contain both the
+ Destination-Realm and Destination-Host AVPs.
+
+ The Destination-Host AVP is used as described above when the
+ destination of the request is fixed, which includes:
+
+ o Authentication requests that span multiple round trips
+
+ o A Diameter message that uses a security mechanism that makes use
+ of a pre-established session key shared between the source and the
+ final destination of the message.
+
+ o Server initiated messages that MUST be received by a specific
+ Diameter client (e.g., access device), such as the Abort-Session-
+ Request message, which is used to request that a particular user's
+ session be terminated.
+
+ Note that an agent can forward a request to a host described in the
+ Destination-Host AVP only if the host in question is included in its
+ peer table (see Section 2.7). Otherwise, the request is routed based
+ on the Destination-Realm only (see Sections 6.1.6).
+
+ When a message is received, the message is processed in the following
+ order:
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 76]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ o If the message is destined for the local host, the procedures
+ listed in Section 6.1.4 are followed.
+
+ o If the message is intended for a Diameter peer with whom the local
+ host is able to directly communicate, the procedures listed in
+ Section 6.1.5 are followed. This is known as Request Forwarding.
+
+ o The procedures listed in Section 6.1.6 are followed, which is
+ known as Request Routing.
+
+ o If none of the above is successful, an answer is returned with the
+ Result-Code set to DIAMETER_UNABLE_TO_DELIVER, with the E-bit set.
+
+ For routing of Diameter messages to work within an administrative
+ domain, all Diameter nodes within the realm MUST be peers.
+
+ Note the processing rules contained in this section are intended to
+ be used as general guidelines to Diameter developers. Certain
+ implementations MAY use different methods than the ones described
+ here, and still comply with the protocol specification. See Section
+ 7 for more detail on error handling.
+
+6.1.1. Originating a Request
+
+ When creating a request, in addition to any other procedures
+ described in the application definition for that specific request,
+ the following procedures MUST be followed:
+
+ o the Command-Code is set to the appropriate value
+
+ o the 'R' bit is set
+
+ o the End-to-End Identifier is set to a locally unique value
+
+ o the Origin-Host and Origin-Realm AVPs MUST be set to the
+ appropriate values, used to identify the source of the message
+
+ o the Destination-Host and Destination-Realm AVPs MUST be set to the
+ appropriate values as described in Section 6.1.
+
+6.1.2. Sending a Request
+
+ When sending a request, originated either locally, or as the result
+ of a forwarding or routing operation, the following procedures SHOULD
+ be followed:
+
+ o The Hop-by-Hop Identifier SHOULD be set to a locally unique value.
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 77]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ o The message SHOULD be saved in the list of pending requests.
+
+ Other actions to perform on the message based on the particular role
+ the agent is playing are described in the following sections.
+
+6.1.3. Receiving Requests
+
+ A relay or proxy agent MUST check for forwarding loops when receiving
+ requests. A loop is detected if the server finds its own identity in
+ a Route-Record AVP. When such an event occurs, the agent MUST answer
+ with the Result-Code AVP set to DIAMETER_LOOP_DETECTED.
+
+6.1.4. Processing Local Requests
+
+ A request is known to be for local consumption when one of the
+ following conditions occur:
+
+ o The Destination-Host AVP contains the local host's identity,
+
+ o The Destination-Host AVP is not present, the Destination-Realm AVP
+ contains a realm the server is configured to process locally, and
+ the Diameter application is locally supported, or
+
+ o Both the Destination-Host and the Destination-Realm are not
+ present.
+
+ When a request is locally processed, the rules in Section 6.2 should
+ be used to generate the corresponding answer.
+
+6.1.5. Request Forwarding
+
+ Request forwarding is done using the Diameter Peer Table. The
+ Diameter peer table contains all of the peers that the local node is
+ able to directly communicate with.
+
+ When a request is received, and the host encoded in the Destination-
+ Host AVP is one that is present in the peer table, the message SHOULD
+ be forwarded to the peer.
+
+6.1.6. Request Routing
+
+ Diameter request message routing is done via realms and application
+ identifiers. A Diameter message that may be forwarded by Diameter
+ agents (proxies, redirect or relay agents) MUST include the target
+ realm in the Destination-Realm AVP. Request routing SHOULD rely on
+ the Destination-Realm AVP and the Application Id present in the
+ request message header to aid in the routing decision. The realm MAY
+ be retrieved from the User-Name AVP, which is in the form of a
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 78]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Network Access Identifier (NAI). The realm portion of the NAI is
+ inserted in the Destination-Realm AVP.
+
+ Diameter agents MAY have a list of locally supported realms and
+ applications, and MAY have a list of externally supported realms and
+ applications. When a request is received that includes a realm
+ and/or application that is not locally supported, the message is
+ routed to the peer configured in the Routing Table (see Section 2.7).
+
+ Realm names and Application Ids are the minimum supported routing
+ criteria, additional information may be needed to support redirect
+ semantics.
+
+6.1.7. Predictive Loop Avoidance
+
+ Before forwarding or routing a request, Diameter agents, in addition
+ to processing done in Section 6.1.3, SHOULD check for the presence of
+ candidate route's peer identity in any of the Route-Record AVPs. In
+ an event of the agent detecting the presence of a candidate route's
+ peer identity in a Route-Record AVP, the agent MUST ignore such route
+ for the Diameter request message and attempt alternate routes if any.
+ In case all the candidate routes are eliminated by the above
+ criteria, the agent SHOULD return DIAMETER_UNABLE_TO_DELIVER message.
+
+6.1.8. Redirecting Requests
+
+ When a redirect agent receives a request whose routing entry is set
+ to REDIRECT, it MUST reply with an answer message with the 'E' bit
+ set, while maintaining the Hop-by-Hop Identifier in the header, and
+ include the Result-Code AVP to DIAMETER_REDIRECT_INDICATION. Each of
+ the servers associated with the routing entry are added in separate
+ Redirect-Host AVP.
+
+ +------------------+
+ | Diameter |
+ | Redirect Agent |
+ +------------------+
+ ^ | 2. command + 'E' bit
+ 1. Request | | Result-Code =
+ [email protected] | | DIAMETER_REDIRECT_INDICATION +
+ | | Redirect-Host AVP(s)
+ | v
+ +-------------+ 3. Request +-------------+
+ | example.com |------------->| example.net |
+ | Relay | | Diameter |
+ | Agent |<-------------| Server |
+ +-------------+ 4. Answer +-------------+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 79]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Figure 5: Diameter Redirect Agent
+
+ The receiver of the answer message with the 'E' bit set, and the
+ Result-Code AVP set to DIAMETER_REDIRECT_INDICATION uses the hop-by-
+ hop field in the Diameter header to identify the request in the
+ pending message queue (see Section 5.3) that is to be redirected. If
+ no transport connection exists with the new agent, one is created,
+ and the request is sent directly to it.
+
+ Multiple Redirect-Host AVPs are allowed. The receiver of the answer
+ message with the 'E' bit set selects exactly one of these hosts as
+ the destination of the redirected message.
+
+ When the Redirect-Host-Usage AVP included in the answer message has a
+ non-zero value, a route entry for the redirect indications is created
+ and cached by the receiver. The redirect usage for such route entry
+ is set by the value of Redirect-Host-Usage AVP and the lifetime of
+ the cached route entry is set by Redirect-Max-Cache-Time AVP value.
+
+ It is possible that multiple redirect indications can create multiple
+ cached route entries differing only in their redirect usage and the
+ peer to forward messages to. As an example, two(2) route entries
+ that are created by two(2) redirect indications results in two(2)
+ cached routes for the same realm and Application Id. However, one
+ has a redirect usage of ALL_SESSION where matching request will be
+ forwarded to one peer and the other has a redirect usage of ALL_REALM
+ where request are forwarded to another peer. Therefore, an incoming
+ request that matches the realm and Application Id of both routes will
+ need additional resolution. In such a case, a routing precedence
+ rule MUST be used against the redirect usage value to resolve the
+ contention. The precedence rule can be found in Section 6.13.
+
+6.1.9. Relaying and Proxying Requests
+
+ A relay or proxy agent MUST append a Route-Record AVP to all requests
+ forwarded. The AVP contains the identity of the peer the request was
+ received from.
+
+ The Hop-by-Hop identifier in the request is saved, and replaced with
+ a locally unique value. The source of the request is also saved,
+ which includes the IP address, port and protocol.
+
+ A relay or proxy agent MAY include the Proxy-Info AVP in requests if
+ it requires access to any local state information when the
+ corresponding response is received. The Proxy-Info AVP has security
+ implications as state information is distribute to other entities.
+ As such, it is RECOMMMENDED to protect the content of the Proxy-Info
+ AVP with cryptographic mechanisms, for example by using a keyed
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 80]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ message digest. Such a mechanism, however, requires the management
+ of keys, although only locally at the Diameter server. Still, a full
+ description of the management of the keys used to protect the Proxy-
+ Info AVP is beyond the scope of this document. Below is a list of
+ commonly recommended:
+
+ o The keys should be generated securely following the randomness
+ recommendations in [RFC4086].
+
+ o The keys and cryptographic protection algorithms should be at
+ least 128 bits in strength.
+
+ o The keys should not be used for any other purpose than generating
+ and verifying tickets.
+
+ o The keys should be changed regularly.
+
+ o The keys should be changed if the ticket format or cryptographic
+ protection algorithms change.
+
+ The message is then forwarded to the next hop, as identified in the
+ Routing Table.
+
+ Figure 6 provides an example of message routing using the procedures
+ listed in these sections.
+
+ (Origin-Host=nas.example.net) (Origin-Host=nas.example.net)
+ (Origin-Realm=example.net) (Origin-Realm=example.net)
+ (Destination-Realm=example.com) (Destination-
+ Realm=example.com)
+ (Route-Record=nas.example.net)
+ +------+ ------> +------+ ------> +------+
+ | | (Request) | | (Request) | |
+ | NAS +-------------------+ DRL +-------------------+ HMS |
+ | | | | | |
+ +------+ <------ +------+ <------ +------+
+ example.net (Answer) example.net (Answer) example.com
+ (Origin-Host=hms.example.com) (Origin-Host=hms.example.com)
+ (Origin-Realm=example.com) (Origin-Realm=example.com)
+
+ Figure 6: Routing of Diameter messages
+
+ Relay and proxy agents are not required to perform full inspection of
+ incoming messages. At a minimum, validation of the message header
+ and relevant routing AVPs has to be done when relaying messages.
+ Proxy agents may optionally perform more in-depth message validation
+ for applications it is interested in.
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 81]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+6.2. Diameter Answer Processing
+
+ When a request is locally processed, the following procedures MUST be
+ applied to create the associated answer, in addition to any
+ additional procedures that MAY be discussed in the Diameter
+ application defining the command:
+
+ o The same Hop-by-Hop identifier in the request is used in the
+ answer.
+
+ o The local host's identity is encoded in the Origin-Host AVP.
+
+ o The Destination-Host and Destination-Realm AVPs MUST NOT be
+ present in the answer message.
+
+ o The Result-Code AVP is added with its value indicating success or
+ failure.
+
+ o If the Session-Id is present in the request, it MUST be included
+ in the answer.
+
+ o Any Proxy-Info AVPs in the request MUST be added to the answer
+ message, in the same order they were present in the request.
+
+ o The 'P' bit is set to the same value as the one in the request.
+
+ o The same End-to-End identifier in the request is used in the
+ answer.
+
+ Note that the error messages (see Section 7.3) are also subjected to
+ the above processing rules.
+
+6.2.1. Processing received Answers
+
+ A Diameter client or proxy MUST match the Hop-by-Hop Identifier in an
+ answer received against the list of pending requests. The
+ corresponding message should be removed from the list of pending
+ requests. It SHOULD ignore answers received that do not match a
+ known Hop-by-Hop Identifier.
+
+6.2.2. Relaying and Proxying Answers
+
+ If the answer is for a request which was proxied or relayed, the
+ agent MUST restore the original value of the Diameter header's Hop-
+ by-Hop Identifier field.
+
+ If the last Proxy-Info AVP in the message is targeted to the local
+ Diameter server, the AVP MUST be removed before the answer is
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 82]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ forwarded.
+
+ If a relay or proxy agent receives an answer with a Result-Code AVP
+ indicating a failure, it MUST NOT modify the contents of the AVP.
+ Any additional local errors detected SHOULD be logged, but not
+ reflected in the Result-Code AVP. If the agent receives an answer
+ message with a Result-Code AVP indicating success, and it wishes to
+ modify the AVP to indicate an error, it MUST modify the Result-Code
+ AVP to contain the appropriate error in the message destined towards
+ the access device as well as include the Error-Reporting-Host AVP and
+ it MUST issue an STR on behalf of the access device towards the
+ Diameter server.
+
+ The agent MUST then send the answer to the host that it received the
+ original request from.
+
+6.3. Origin-Host AVP
+
+ The Origin-Host AVP (AVP Code 264) is of type DiameterIdentity, and
+ MUST be present in all Diameter messages. This AVP identifies the
+ endpoint that originated the Diameter message. Relay agents MUST NOT
+ modify this AVP.
+
+ The value of the Origin-Host AVP is guaranteed to be unique within a
+ single host.
+
+ Note that the Origin-Host AVP may resolve to more than one address as
+ the Diameter peer may support more than one address.
+
+ This AVP SHOULD be placed as close to the Diameter header as
+ possible.
+
+6.4. Origin-Realm AVP
+
+ The Origin-Realm AVP (AVP Code 296) is of type DiameterIdentity.
+ This AVP contains the Realm of the originator of any Diameter message
+ and MUST be present in all messages.
+
+ This AVP SHOULD be placed as close to the Diameter header as
+ possible.
+
+6.5. Destination-Host AVP
+
+ The Destination-Host AVP (AVP Code 293) is of type DiameterIdentity.
+ This AVP MUST be present in all unsolicited agent initiated messages,
+ MAY be present in request messages, and MUST NOT be present in Answer
+ messages.
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 83]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ The absence of the Destination-Host AVP will cause a message to be
+ sent to any Diameter server supporting the application within the
+ realm specified in Destination-Realm AVP.
+
+ This AVP SHOULD be placed as close to the Diameter header as
+ possible.
+
+6.6. Destination-Realm AVP
+
+ The Destination-Realm AVP (AVP Code 283) is of type DiameterIdentity,
+ and contains the realm the message is to be routed to. The
+ Destination-Realm AVP MUST NOT be present in Answer messages.
+ Diameter Clients insert the realm portion of the User-Name AVP.
+ Diameter servers initiating a request message use the value of the
+ Origin-Realm AVP from a previous message received from the intended
+ target host (unless it is known a priori). When present, the
+ Destination-Realm AVP is used to perform message routing decisions.
+
+ An ABNF for a request message that includes the Destination-Realm AVP
+ SHOULD list the Destination-Realm AVP as a required AVP (an AVP
+ indicated as {AVP}) otherwise the message is inherently a non-
+ routable message.
+
+ This AVP SHOULD be placed as close to the Diameter header as
+ possible.
+
+6.7. Routing AVPs
+
+ The AVPs defined in this section are Diameter AVPs used for routing
+ purposes. These AVPs change as Diameter messages are processed by
+ agents.
+
+6.7.1. Route-Record AVP
+
+ The Route-Record AVP (AVP Code 282) is of type DiameterIdentity. The
+ identity added in this AVP MUST be the same as the one received in
+ the Origin-Host of the Capabilities Exchange message.
+
+6.7.2. Proxy-Info AVP
+
+ The Proxy-Info AVP (AVP Code 284) is of type Grouped. This AVP
+ contains the identity and local state information of the Diameter
+ node that creates and adds it to a message. The Grouped Data field
+ has the following ABNF grammar:
+
+ Proxy-Info ::= < AVP Header: 284 >
+ { Proxy-Host }
+ { Proxy-State }
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 84]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ * [ AVP ]
+
+6.7.3. Proxy-Host AVP
+
+ The Proxy-Host AVP (AVP Code 280) is of type DiameterIdentity. This
+ AVP contains the identity of the host that added the Proxy-Info AVP.
+
+6.7.4. Proxy-State AVP
+
+ The Proxy-State AVP (AVP Code 33) is of type OctetString. It
+ contains state information that would otherwise be stored at the
+ Diameter entity that created it. As such, this AVP MUST be treated
+ as opaque data by other Diameter entities.
+
+6.8. Auth-Application-Id AVP
+
+ The Auth-Application-Id AVP (AVP Code 258) is of type Unsigned32 and
+ is used in order to advertise support of the Authentication and
+ Authorization portion of an application (see Section 2.4). If
+ present in a message other than CER and CEA, the value of the Auth-
+ Application-Id AVP MUST match the Application Id present in the
+ Diameter message header.
+
+6.9. Acct-Application-Id AVP
+
+ The Acct-Application-Id AVP (AVP Code 259) is of type Unsigned32 and
+ is used in order to advertise support of the Accounting portion of an
+ application (see Section 2.4). If present in a message other than
+ CER and CEA, the value of the Acct-Application-Id AVP MUST match the
+ Application Id present in the Diameter message header.
+
+6.10. Inband-Security-Id AVP
+
+ The Inband-Security-Id AVP (AVP Code 299) is of type Unsigned32 and
+ is used in order to advertise support of the security portion of the
+ application. The use of this AVP in CER and CEA messages is no
+ longer recommended. Instead, discovery of a Diameter entities
+ security capabilities can be done either through static configuration
+ or via Diameter Peer Discovery described in Section 5.2.
+
+ The following values are supported:
+
+
+ NO_INBAND_SECURITY 0
+
+ This peer does not support TLS/TCP and DTLS/SCTP. This is the
+ default value, if the AVP is omitted.
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 85]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ TLS 1
+
+ This node supports TLS/TCP and DTLS/SCTP security, as defined by
+ [RFC5246].
+
+6.11. Vendor-Specific-Application-Id AVP
+
+ The Vendor-Specific-Application-Id AVP (AVP Code 260) is of type
+ Grouped and is used to advertise support of a vendor-specific
+ Diameter Application. Exactly one instance of either Auth-
+ Application-Id or Acct-Application-Id AVP MUST be present. The
+ Application Id carried by either Auth-Application-Id or Acct-
+ Application-Id AVP MUST comply with vendor specific Application Id
+ assignment described in Sec 11.3. It MUST also match the Application
+ Id present in the Diameter header except when used in a CER or CEA
+ message.
+
+ The Vendor-Id AVP is an informational AVP pertaining to the vendor
+ who may have authorship of the vendor-specific Diameter application.
+ It MUST NOT be used as a means of defining a completely separate
+ vendor-specific Application Id space.
+
+ The Vendor-Specific-Application-Id AVP SHOULD be placed as close to
+ the Diameter header as possible.
+
+ AVP Format
+
+ <Vendor-Specific-Application-Id> ::= < AVP Header: 260 >
+ { Vendor-Id }
+ [ Auth-Application-Id ]
+ [ Acct-Application-Id ]
+
+ A Vendor-Specific-Application-Id AVP MUST contain exactly one of
+ either Auth-Application-Id or Acct-Application-Id. If a Vendor-
+ Specific-Application-Id is received without any of these two AVPs,
+ then the recipient SHOULD issue an answer with a Result-Code set to
+ DIAMETER_MISSING_AVP. The answer SHOULD also include a Failed-AVP
+ which MUST contain an example of an Auth-Application-Id AVP and an
+ Acct-Application-Id AVP.
+
+ If a Vendor-Specific-Application-Id is received that contains both
+ Auth-Application-Id and Acct-Application-Id, then the recipient MUST
+ issue an answer with Result-Code set to
+ DIAMETER_AVP_OCCURS_TOO_MANY_TIMES. The answer MUST also include a
+ Failed-AVP which MUST contain the received Auth-Application-Id AVP
+ and Acct-Application-Id AVP.
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 86]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+6.12. Redirect-Host AVP
+
+ The Redirect-Host AVP (AVP Code 292) is of type DiameterURI. One or
+ more of instances of this AVP MUST be present if the answer message's
+ 'E' bit is set and the Result-Code AVP is set to
+ DIAMETER_REDIRECT_INDICATION.
+
+ Upon receiving the above, the receiving Diameter node SHOULD forward
+ the request directly to one of the hosts identified in these AVPs.
+ The server contained in the selected Redirect-Host AVP SHOULD be used
+ for all messages matching the criteria set by the Redirect-Host-Usage
+ AVP.
+
+6.13. Redirect-Host-Usage AVP
+
+ The Redirect-Host-Usage AVP (AVP Code 261) is of type Enumerated.
+ This AVP MAY be present in answer messages whose 'E' bit is set and
+ the Result-Code AVP is set to DIAMETER_REDIRECT_INDICATION.
+
+ When present, this AVP provides a hints about how the routing entry
+ resulting from the Redirect-Host is to be used. The following values
+ are supported:
+
+
+ DONT_CACHE 0
+
+ The host specified in the Redirect-Host AVP SHOULD NOT be cached.
+ This is the default value.
+
+
+ ALL_SESSION 1
+
+ All messages within the same session, as defined by the same value
+ of the Session-ID AVP SHOULD be sent to the host specified in the
+ Redirect-Host AVP.
+
+
+ ALL_REALM 2
+
+ All messages destined for the realm requested SHOULD be sent to
+ the host specified in the Redirect-Host AVP.
+
+
+ REALM_AND_APPLICATION 3
+
+ All messages for the application requested to the realm specified
+ SHOULD be sent to the host specified in the Redirect-Host AVP.
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 87]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ ALL_APPLICATION 4
+
+ All messages for the application requested SHOULD be sent to the
+ host specified in the Redirect-Host AVP.
+
+
+ ALL_HOST 5
+
+ All messages that would be sent to the host that generated the
+ Redirect-Host SHOULD be sent to the host specified in the
+ Redirect- Host AVP.
+
+
+ ALL_USER 6
+
+ All messages for the user requested SHOULD be sent to the host
+ specified in the Redirect-Host AVP.
+
+
+
+ When multiple cached routes are created by redirect indications and
+ they differ only in redirect usage and peers to forward requests to
+ (see Section 6.1.8), a precedence rule MUST be applied to the
+ redirect usage values of the cached routes during normal routing to
+ resolve contentions that may occur. The precedence rule is the order
+ that dictate which redirect usage should be considered before any
+ other as they appear. The order is as follows:
+
+
+ 1. ALL_SESSION
+
+ 2. ALL_USER
+
+ 3. REALM_AND_APPLICATION
+
+ 4. ALL_REALM
+
+ 5. ALL_APPLICATION
+
+ 6. ALL_HOST
+
+6.14. Redirect-Max-Cache-Time AVP
+
+ The Redirect-Max-Cache-Time AVP (AVP Code 262) is of type Unsigned32.
+ This AVP MUST be present in answer messages whose 'E' bit is set, the
+ Result-Code AVP is set to DIAMETER_REDIRECT_INDICATION and the
+ Redirect-Host-Usage AVP set to a non-zero value.
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 88]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ This AVP contains the maximum number of seconds the peer and route
+ table entries, created as a result of the Redirect-Host, SHOULD be
+ cached. Note that once a host is no longer reachable, any associated
+ cache, peer and routing table entries MUST be deleted.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 89]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+7. Error Handling
+
+ There are two different types of errors in Diameter; protocol and
+ application errors. A protocol error is one that occurs at the base
+ protocol level, and MAY require per hop attention (e.g., message
+ routing error). Application errors, on the other hand, generally
+ occur due to a problem with a function specified in a Diameter
+ application (e.g., user authentication, missing AVP).
+
+ Result-Code AVP values that are used to report protocol errors MUST
+ only be present in answer messages whose 'E' bit is set. When a
+ request message is received that causes a protocol error, an answer
+ message is returned with the 'E' bit set, and the Result-Code AVP is
+ set to the appropriate protocol error value. As the answer is sent
+ back towards the originator of the request, each proxy or relay agent
+ MAY take action on the message.
+
+ 1. Request +---------+ Link Broken
+ +-------------------------->|Diameter |----///----+
+ | +---------------------| | v
+ +------+--+ | 2. answer + 'E' set | Relay 2 | +--------+
+ |Diameter |<-+ (Unable to Forward) +---------+ |Diameter|
+ | | | Home |
+ | Relay 1 |--+ +---------+ | Server |
+ +---------+ | 3. Request |Diameter | +--------+
+ +-------------------->| | ^
+ | Relay 3 |-----------+
+ +---------+
+
+ Figure 7: Example of Protocol Error causing answer message
+
+ Figure 7 provides an example of a message forwarded upstream by a
+ Diameter relay. When the message is received by Relay 2, and it
+ detects that it cannot forward the request to the home server, an
+ answer message is returned with the 'E' bit set and the Result-Code
+ AVP set to DIAMETER_UNABLE_TO_DELIVER. Given that this error falls
+ within the protocol error category, Relay 1 would take special
+ action, and given the error, attempt to route the message through its
+ alternate Relay 3.
+
+ +---------+ 1. Request +---------+ 2. Request +---------+
+ | Access |------------>|Diameter |------------>|Diameter |
+ | | | | | Home |
+ | Device |<------------| Relay |<------------| Server |
+ +---------+ 4. Answer +---------+ 3. Answer +---------+
+ (Missing AVP) (Missing AVP)
+
+ Figure 8: Example of Application Error Answer message
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 90]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Figure 8 provides an example of a Diameter message that caused an
+ application error. When application errors occur, the Diameter
+ entity reporting the error clears the 'R' bit in the Command Flags,
+ and adds the Result-Code AVP with the proper value. Application
+ errors do not require any proxy or relay agent involvement, and
+ therefore the message would be forwarded back to the originator of
+ the request.
+
+ In the case where the answer message itself contains errors, any
+ related session SHOULD be terminated by sending an STR or ASR
+ message. The Termination-Cause AVP in the STR MAY be filled with the
+ appropriate value to indicate the cause of the error. An application
+ MAY also send an application-specific request instead of STR or ASR
+ to signal the error in the case where no state is maintained or to
+ allow for some form of error recovery with the corresponding Diameter
+ entity.
+
+ There are certain Result-Code AVP application errors that require
+ additional AVPs to be present in the answer. In these cases, the
+ Diameter node that sets the Result-Code AVP to indicate the error
+ MUST add the AVPs. Examples are:
+
+ o A request with an unrecognized AVP is received with the 'M' bit
+ (Mandatory bit) set, causes an answer to be sent with the Result-
+ Code AVP set to DIAMETER_AVP_UNSUPPORTED, and the Failed-AVP AVP
+ containing the offending AVP.
+
+ o A request with an AVP that is received with an unrecognized value
+ causes an answer to be returned with the Result-Code AVP set to
+ DIAMETER_INVALID_AVP_VALUE, with the Failed-AVP AVP containing the
+ AVP causing the error.
+
+ o A received command which is missing AVP(s) that are defined as
+ required in the commands ABNF; examples are AVPs indicated as
+ {AVP}. The receiver issues an answer with the Result-Code set to
+ DIAMETER_MISSING_AVP, and creates an AVP with the AVP Code and
+ other fields set as expected in the missing AVP. The created AVP
+ is then added to the Failed- AVP AVP.
+
+ The Result-Code AVP describes the error that the Diameter node
+ encountered in its processing. In case there are multiple errors,
+ the Diameter node MUST report only the first error it encountered
+ (detected possibly in some implementation dependent order). The
+ specific errors that can be described by this AVP are described in
+ the following section.
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 91]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+7.1. Result-Code AVP
+
+ The Result-Code AVP (AVP Code 268) is of type Unsigned32 and
+ indicates whether a particular request was completed successfully or
+ whether an error occurred. All Diameter answer messages in IETF
+ defined Diameter application specification MUST include one Result-
+ Code AVP. A non-successful Result-Code AVP (one containing a non
+ 2xxx value other than DIAMETER_REDIRECT_INDICATION) MUST include the
+ Error-Reporting-Host AVP if the host setting the Result-Code AVP is
+ different from the identity encoded in the Origin-Host AVP.
+
+
+ The Result-Code data field contains an IANA-managed 32-bit address
+ space representing errors (see Section 11.4). Diameter provides the
+ following classes of errors, all identified by the thousands digit in
+ the decimal notation:
+
+ o 1xxx (Informational)
+
+ o 2xxx (Success)
+
+ o 3xxx (Protocol Errors)
+
+ o 4xxx (Transient Failures)
+
+ o 5xxx (Permanent Failure)
+
+ A non-recognized class (one whose first digit is not defined in this
+ section) MUST be handled as a permanent failure.
+
+7.1.1. Informational
+
+ Errors that fall within this category are used to inform the
+ requester that a request could not be satisfied, and additional
+ action is required on its part before access is granted.
+
+
+ DIAMETER_MULTI_ROUND_AUTH 1001
+
+ This informational error is returned by a Diameter server to
+ inform the access device that the authentication mechanism being
+ used requires multiple round trips, and a subsequent request needs
+ to be issued in order for access to be granted.
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 92]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+7.1.2. Success
+
+ Errors that fall within the Success category are used to inform a
+ peer that a request has been successfully completed.
+
+
+ DIAMETER_SUCCESS 2001
+
+ The request was successfully completed.
+
+ DIAMETER_LIMITED_SUCCESS 2002
+
+ When returned, the request was successfully completed, but
+ additional processing is required by the application in order to
+ provide service to the user.
+
+7.1.3. Protocol Errors
+
+ Errors that fall within the Protocol Error category SHOULD be treated
+ on a per-hop basis, and Diameter proxies MAY attempt to correct the
+ error, if it is possible. Note that these errors MUST only be used
+ in answer messages whose 'E' bit is set. This document omits some
+ error codes defined in [RFC3588]. To provide backward compatibility
+ with [RFC3588] implementations these error code values are not re-
+ used and hence the error codes values enumerated below are non-
+ sequential.
+
+
+ DIAMETER_UNABLE_TO_DELIVER 3002
+
+ This error is given when Diameter can not deliver the message to
+ the destination, either because no host within the realm
+ supporting the required application was available to process the
+ request, or because Destination-Host AVP was given without the
+ associated Destination-Realm AVP.
+
+
+ DIAMETER_REALM_NOT_SERVED 3003
+
+ The intended realm of the request is not recognized.
+
+
+ DIAMETER_TOO_BUSY 3004
+
+ When returned, a Diameter node SHOULD attempt to send the message
+ to an alternate peer. This error MUST only be used when a
+ specific server is requested, and it cannot provide the requested
+ service.
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 93]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ DIAMETER_LOOP_DETECTED 3005
+
+ An agent detected a loop while trying to get the message to the
+ intended recipient. The message MAY be sent to an alternate peer,
+ if one is available, but the peer reporting the error has
+ identified a configuration problem.
+
+
+ DIAMETER_REDIRECT_INDICATION 3006
+
+ A redirect agent has determined that the request could not be
+ satisfied locally and the initiator of the request SHOULD direct
+ the request directly to the server, whose contact information has
+ been added to the response. When set, the Redirect-Host AVP MUST
+ be present.
+
+
+ DIAMETER_APPLICATION_UNSUPPORTED 3007
+
+ A request was sent for an application that is not supported.
+
+
+ DIAMETER_INVALID_BIT_IN_HEADER 3011
+
+ This error is returned when a reserved bit in the Diameter header
+ is set to one (1) or the bits in the Diameter header defined in
+ Section 3 are set incorrectly.
+
+
+ DIAMETER_INVALID_MESSAGE_LENGTH 3012
+
+ This error is returned when a request is received with an invalid
+ message length.
+
+
+7.1.4. Transient Failures
+
+ Errors that fall within the transient failures category are used to
+ inform a peer that the request could not be satisfied at the time it
+ was received, but MAY be able to satisfy the request in the future.
+ Note that these errors MUST be used in answer messages whose 'E' bit
+ is not set.
+
+
+ DIAMETER_AUTHENTICATION_REJECTED 4001
+
+ The authentication process for the user failed, most likely due to
+ an invalid password used by the user. Further attempts MUST only
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 94]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ be tried after prompting the user for a new password.
+
+
+ DIAMETER_OUT_OF_SPACE 4002
+
+ A Diameter node received the accounting request but was unable to
+ commit it to stable storage due to a temporary lack of space.
+
+
+ ELECTION_LOST 4003
+
+ The peer has determined that it has lost the election process and
+ has therefore disconnected the transport connection.
+
+
+7.1.5. Permanent Failures
+
+ Errors that fall within the permanent failures category are used to
+ inform the peer that the request failed, and should not be attempted
+ again. Note that these errors SHOULD be used in answer messages
+ whose 'E' bit is not set. In error conditions where it is not
+ possible or efficient to compose application-specific answer grammar
+ then answer messages with E-bit set and complying to the grammar
+ described in 7.2 MAY also be used for permanent errors.
+
+ To provide backward compatibility with existing implementations that
+ follow [RFC3588], some of the error values that have previously been
+ used in this category by [RFC3588] will not be re-used. Therefore
+ the error values enumerated here may be non-sequential.
+
+
+ DIAMETER_AVP_UNSUPPORTED 5001
+
+ The peer received a message that contained an AVP that is not
+ recognized or supported and was marked with the Mandatory bit. A
+ Diameter message with this error MUST contain one or more Failed-
+ AVP AVP containing the AVPs that caused the failure.
+
+
+ DIAMETER_UNKNOWN_SESSION_ID 5002
+
+ The request contained an unknown Session-Id.
+
+
+ DIAMETER_AUTHORIZATION_REJECTED 5003
+
+ A request was received for which the user could not be authorized.
+ This error could occur if the service requested is not permitted
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 95]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ to the user.
+
+
+ DIAMETER_INVALID_AVP_VALUE 5004
+
+ The request contained an AVP with an invalid value in its data
+ portion. A Diameter message indicating this error MUST include
+ the offending AVPs within a Failed-AVP AVP.
+
+
+ DIAMETER_MISSING_AVP 5005
+
+ The request did not contain an AVP that is required by the Command
+ Code definition. If this value is sent in the Result-Code AVP, a
+ Failed-AVP AVP SHOULD be included in the message. The Failed-AVP
+ AVP MUST contain an example of the missing AVP complete with the
+ Vendor-Id if applicable. The value field of the missing AVP
+ should be of correct minimum length and contain zeroes.
+
+
+ DIAMETER_RESOURCES_EXCEEDED 5006
+
+ A request was received that cannot be authorized because the user
+ has already expended allowed resources. An example of this error
+ condition is a user that is restricted to one dial-up PPP port,
+ attempts to establish a second PPP connection.
+
+
+ DIAMETER_CONTRADICTING_AVPS 5007
+
+ The Home Diameter server has detected AVPs in the request that
+ contradicted each other, and is not willing to provide service to
+ the user. The Failed-AVP AVPs MUST be present which contains the
+ AVPs that contradicted each other.
+
+
+ DIAMETER_AVP_NOT_ALLOWED 5008
+
+ A message was received with an AVP that MUST NOT be present. The
+ Failed-AVP AVP MUST be included and contain a copy of the
+ offending AVP.
+
+
+ DIAMETER_AVP_OCCURS_TOO_MANY_TIMES 5009
+
+ A message was received that included an AVP that appeared more
+ often than permitted in the message definition. The Failed-AVP
+ AVP MUST be included and contain a copy of the first instance of
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 96]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ the offending AVP that exceeded the maximum number of occurrences
+
+
+ DIAMETER_NO_COMMON_APPLICATION 5010
+
+ This error is returned by a Diameter node that receives a CER
+ whereby no applications are common between the CER sending peer
+ and the CER receiving peer.
+
+
+ DIAMETER_UNSUPPORTED_VERSION 5011
+
+ This error is returned when a request was received, whose version
+ number is unsupported.
+
+
+ DIAMETER_UNABLE_TO_COMPLY 5012
+
+ This error is returned when a request is rejected for unspecified
+ reasons.
+
+
+ DIAMETER_INVALID_AVP_LENGTH 5014
+
+ The request contained an AVP with an invalid length. A Diameter
+ message indicating this error MUST include the offending AVPs
+ within a Failed-AVP AVP. In cases where the erroneous AVP length
+ value exceeds the message length or is less than the minimum AVP
+ header length, it is sufficient to include the offending AVP
+ header and a zero filled payload of the minimum required length
+ for the payloads data type. If the AVP is a grouped AVP, the
+ grouped AVP header with an empty payload would be sufficient to
+ indicate the offending AVP. In the case where the offending AVP
+ header cannot be fully decoded when the AVP length is less than
+ the minimum AVP header length, it is sufficient to include an
+ offending AVP header that is formulated by padding the incomplete
+ AVP header with zero up to the minimum AVP header length.
+
+
+ DIAMETER_NO_COMMON_SECURITY 5017
+
+ This error is returned when a CER message is received, and there
+ are no common security mechanisms supported between the peers. A
+ Capabilities-Exchange-Answer (CEA) MUST be returned with the
+ Result-Code AVP set to DIAMETER_NO_COMMON_SECURITY.
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 97]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ DIAMETER_UNKNOWN_PEER 5018
+
+ A CER was received from an unknown peer.
+
+
+ DIAMETER_COMMAND_UNSUPPORTED 5019
+
+ This error code is used when a Diameter entity receives a message
+ with a Command Code that it does not support.
+
+
+ DIAMETER_INVALID_HDR_BITS 5020
+
+ A request was received whose bits in the Diameter header were
+ either set to an invalid combination, or to a value that is
+ inconsistent with the command code's definition.
+
+
+ DIAMETER_INVALID_AVP_BITS 5021
+
+ A request was received that included an AVP whose flag bits are
+ set to an unrecognized value, or that is inconsistent with the
+ AVP's definition.
+
+
+7.2. Error Bit
+
+ The 'E' (Error Bit) in the Diameter header is set when the request
+ caused a protocol-related error (see Section 7.1.3). A message with
+ the 'E' bit MUST NOT be sent as a response to an answer message.
+ Note that a message with the 'E' bit set is still subjected to the
+ processing rules defined in Section 6.2. When set, the answer
+ message will not conform to the ABNF specification for the command,
+ and will instead conform to the following ABNF:
+
+ Message Format
+
+ <answer-message> ::= < Diameter Header: code, ERR [PXY] >
+ 0*1< Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Result-Code }
+ [ Origin-State-Id ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ [ Failed-AVP ]
+ [ Experimental-Result ]
+ * [ Proxy-Info ]
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 98]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ * [ AVP ]
+
+ Note that the code used in the header is the same than the one found
+ in the request message, but with the 'R' bit cleared and the 'E' bit
+ set. The 'P' bit in the header is set to the same value as the one
+ found in the request message.
+
+7.3. Error-Message AVP
+
+ The Error-Message AVP (AVP Code 281) is of type UTF8String. It MAY
+ accompany a Result-Code AVP as a human readable error message. The
+ Error-Message AVP is not intended to be useful in an environment
+ where error messages are processed automatically. It SHOULD NOT be
+ expected that the content of this AVP is parsed by network entities.
+
+7.4. Error-Reporting-Host AVP
+
+ The Error-Reporting-Host AVP (AVP Code 294) is of type
+ DiameterIdentity. This AVP contains the identity of the Diameter
+ host that sent the Result-Code AVP to a value other than 2001
+ (Success), only if the host setting the Result-Code is different from
+ the one encoded in the Origin-Host AVP. This AVP is intended to be
+ used for troubleshooting purposes, and MUST be set when the Result-
+ Code AVP indicates a failure.
+
+7.5. Failed-AVP AVP
+
+ The Failed-AVP AVP (AVP Code 279) is of type Grouped and provides
+ debugging information in cases where a request is rejected or not
+ fully processed due to erroneous information in a specific AVP. The
+ value of the Result-Code AVP will provide information on the reason
+ for the Failed-AVP AVP. A Diameter message SHOULD contain only one
+ Failed-AVP that corresponds to the error indicated by the Result-Code
+ AVP. For practical purposes, this Failed-AVP would typically refer
+ to the first AVP processing error that a Diameter node encounters.
+
+ The possible reasons for this AVP are the presence of an improperly
+ constructed AVP, an unsupported or unrecognized AVP, an invalid AVP
+ value, the omission of a required AVP, the presence of an explicitly
+ excluded AVP (see tables in Section 10), or the presence of two or
+ more occurrences of an AVP which is restricted to 0, 1, or 0-1
+ occurrences.
+
+ A Diameter message SHOULD contain one Failed-AVP AVP, containing the
+ entire AVP that could not be processed successfully. If the failure
+ reason is omission of a required AVP, an AVP with the missing AVP
+ code, the missing vendor id, and a zero filled payload of the minimum
+ required length for the omitted AVP will be added. If the failure
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 99]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ reason is an invalid AVP length where the reported length is less
+ than the minimum AVP header length or greater than the reported
+ message length, a copy of the offending AVP header and a zero filled
+ payload of the minimum required length SHOULD be added.
+
+ In the case where the offending AVP is embedded within a grouped AVP,
+ the Failed-AVP MAY contain the grouped AVP which in turn contains the
+ single offending AVP. The same method MAY be employed if the grouped
+ AVP itself is embedded in yet another grouped AVP and so on. In this
+ case, the Failed-AVP MAY contain the grouped AVP hierarchy up to the
+ single offending AVP. This enables the recipient to detect the
+ location of the offending AVP when embedded in a group.
+
+ AVP Format
+
+ <Failed-AVP> ::= < AVP Header: 279 >
+ 1* {AVP}
+
+7.6. Experimental-Result AVP
+
+ The Experimental-Result AVP (AVP Code 297) is of type Grouped, and
+ indicates whether a particular vendor-specific request was completed
+ successfully or whether an error occurred. This AVP has the
+ following structure:
+
+ AVP Format
+
+ Experimental-Result ::= < AVP Header: 297 >
+ { Vendor-Id }
+ { Experimental-Result-Code }
+
+ The Vendor-Id AVP (see Section 5.3.3) in this grouped AVP identifies
+ the vendor responsible for the assignment of the result code which
+ follows. All Diameter answer messages defined in vendor-specific
+ applications MUST include either one Result-Code AVP or one
+ Experimental-Result AVP.
+
+7.7. Experimental-Result-Code AVP
+
+ The Experimental-Result-Code AVP (AVP Code 298) is of type Unsigned32
+ and contains a vendor-assigned value representing the result of
+ processing the request.
+
+ It is recommended that vendor-specific result codes follow the same
+ conventions given for the Result-Code AVP regarding the different
+ types of result codes and the handling of errors (for non 2xxx
+ values).
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 100]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+8. Diameter User Sessions
+
+ In general, Diameter can provide two different types of services to
+ applications. The first involves authentication and authorization,
+ and can optionally make use of accounting. The second only makes use
+ of accounting.
+
+ When a service makes use of the authentication and/or authorization
+ portion of an application, and a user requests access to the network,
+ the Diameter client issues an auth request to its local server. The
+ auth request is defined in a service-specific Diameter application
+ (e.g., NASREQ). The request contains a Session-Id AVP, which is used
+ in subsequent messages (e.g., subsequent authorization, accounting,
+ etc) relating to the user's session. The Session-Id AVP is a means
+ for the client and servers to correlate a Diameter message with a
+ user session.
+
+ When a Diameter server authorizes a user to use network resources for
+ a finite amount of time, and it is willing to extend the
+ authorization via a future request, it MUST add the Authorization-
+ Lifetime AVP to the answer message. The Authorization-Lifetime AVP
+ defines the maximum number of seconds a user MAY make use of the
+ resources before another authorization request is expected by the
+ server. The Auth-Grace-Period AVP contains the number of seconds
+ following the expiration of the Authorization-Lifetime, after which
+ the server will release all state information related to the user's
+ session. Note that if payment for services is expected by the
+ serving realm from the user's home realm, the Authorization-Lifetime
+ AVP, combined with the Auth-Grace-Period AVP, implies the maximum
+ length of the session the home realm is willing to be fiscally
+ responsible for. Services provided past the expiration of the
+ Authorization-Lifetime and Auth-Grace-Period AVPs are the
+ responsibility of the access device. Of course, the actual cost of
+ services rendered is clearly outside the scope of the protocol.
+
+ An access device that does not expect to send a re-authorization or a
+ session termination request to the server MAY include the Auth-
+ Session-State AVP with the value set to NO_STATE_MAINTAINED as a hint
+ to the server. If the server accepts the hint, it agrees that since
+ no session termination message will be received once service to the
+ user is terminated, it cannot maintain state for the session. If the
+ answer message from the server contains a different value in the
+ Auth-Session-State AVP (or the default value if the AVP is absent),
+ the access device MUST follow the server's directives. Note that the
+ value NO_STATE_MAINTAINED MUST NOT be set in subsequent re-
+ authorization requests and answers.
+
+ The base protocol does not include any authorization request
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 101]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ messages, since these are largely application-specific and are
+ defined in a Diameter application document. However, the base
+ protocol does define a set of messages that are used to terminate
+ user sessions. These are used to allow servers that maintain state
+ information to free resources.
+
+ When a service only makes use of the Accounting portion of the
+ Diameter protocol, even in combination with an application, the
+ Session-Id is still used to identify user sessions. However, the
+ session termination messages are not used, since a session is
+ signaled as being terminated by issuing an accounting stop message.
+
+ Diameter may also be used for services that cannot be easily
+ categorized as authentication, authorization or accounting (e.g.,
+ certain 3GPP IMS interfaces). In such cases, the finite state
+ machine defined in subsequent sections may not be applicable.
+ Therefore, the applications itself MAY need to define its own finite
+ state machine. However, such application-specific state machines
+ SHOULD follow the general state machine framework outlined in this
+ document such as the use of Session-Id AVPs and the use of STR/STA,
+ ASR/ASA messages for stateful sessions.
+
+8.1. Authorization Session State Machine
+
+ This section contains a set of finite state machines, representing
+ the life cycle of Diameter sessions, and which MUST be observed by
+ all Diameter implementations that make use of the authentication
+ and/or authorization portion of a Diameter application. The term
+ Service-Specific below refers to a message defined in a Diameter
+ application (e.g., Mobile IPv4, NASREQ).
+
+ There are four different authorization session state machines
+ supported in the Diameter base protocol. The first two describe a
+ session in which the server is maintaining session state, indicated
+ by the value of the Auth-Session-State AVP (or its absence). One
+ describes the session from a client perspective, the other from a
+ server perspective. The second two state machines are used when the
+ server does not maintain session state. Here again, one describes
+ the session from a client perspective, the other from a server
+ perspective.
+
+ When a session is moved to the Idle state, any resources that were
+ allocated for the particular session must be released. Any event not
+ listed in the state machines MUST be considered as an error
+ condition, and an answer, if applicable, MUST be returned to the
+ originator of the message.
+
+ In the case that an application does not support re-auth, the state
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 102]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ transitions related to server-initiated re-auth when both client and
+ server session maintains state (e.g., Send RAR, Pending, Receive RAA)
+ MAY be ignored.
+
+ In the state table, the event 'Failure to send X' means that the
+ Diameter agent is unable to send command X to the desired
+ destination. This could be due to the peer being down, or due to the
+ peer sending back a transient failure or temporary protocol error
+ notification DIAMETER_TOO_BUSY or DIAMETER_LOOP_DETECTED in the
+ Result-Code AVP of the corresponding Answer command. The event 'X
+ successfully sent' is the complement of 'Failure to send X'.
+
+ The following state machine is observed by a client when state is
+ maintained on the server:
+
+ CLIENT, STATEFUL
+ State Event Action New State
+ ---------------------------------------------------------------
+ Idle Client or Device Requests Send Pending
+ access service
+ specific
+ auth req
+
+ Idle ASR Received Send ASA Idle
+ for unknown session with
+ Result-Code =
+ UNKNOWN_
+ SESSION_ID
+
+ Idle RAR Received Send RAA Idle
+ for unknown session with
+ Result-Code =
+ UNKNOWN_
+ SESSION_ID
+
+ Pending Successful Service-specific Grant Open
+ authorization answer Access
+ received with default
+ Auth-Session-State value
+
+ Pending Successful Service-specific Sent STR Discon
+ authorization answer received
+ but service not provided
+
+ Pending Error processing successful Sent STR Discon
+ Service-specific authorization
+ answer
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 103]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Pending Failed Service-specific Cleanup Idle
+ authorization answer received
+
+ Open User or client device Send Open
+ requests access to service service
+ specific
+ auth req
+
+ Open Successful Service-specific Provide Open
+ authorization answer received Service
+
+ Open Failed Service-specific Discon. Idle
+ authorization answer user/device
+ received.
+
+ Open RAR received and client will Send RAA Open
+ perform subsequent re-auth with
+ Result-Code =
+ SUCCESS
+
+ Open RAR received and client will Send RAA Idle
+ not perform subsequent with
+ re-auth Result-Code !=
+ SUCCESS,
+ Discon.
+ user/device
+
+ Open Session-Timeout Expires on Send STR Discon
+ Access Device
+
+ Open ASR Received, Send ASA Discon
+ client will comply with
+ with request to end the Result-Code =
+ session = SUCCESS,
+ Send STR.
+
+ Open ASR Received, Send ASA Open
+ client will not comply with
+ with request to end the Result-Code !=
+ session != SUCCESS
+
+ Open Authorization-Lifetime + Send STR Discon
+ Auth-Grace-Period expires on
+ access device
+
+ Discon ASR Received Send ASA Discon
+
+ Discon STA Received Discon. Idle
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 104]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ user/device
+
+ The following state machine is observed by a server when it is
+ maintaining state for the session:
+
+ SERVER, STATEFUL
+ State Event Action New State
+ ---------------------------------------------------------------
+ Idle Service-specific authorization Send Open
+ request received, and successful
+ user is authorized serv.
+ specific
+ answer
+
+ Idle Service-specific authorization Send Idle
+ request received, and failed serv.
+ user is not authorized specific
+ answer
+
+ Open Service-specific authorization Send Open
+ request received, and user successful
+ is authorized serv. specific
+ answer
+
+ Open Service-specific authorization Send Idle
+ request received, and user failed serv.
+ is not authorized specific
+ answer,
+ Cleanup
+
+ Open Home server wants to confirm Send RAR Pending
+ authentication and/or
+ authorization of the user
+
+ Pending Received RAA with a failed Cleanup Idle
+ Result-Code
+
+ Pending Received RAA with Result-Code Update Open
+ = SUCCESS session
+
+ Open Home server wants to Send ASR Discon
+ terminate the service
+
+ Open Authorization-Lifetime (and Cleanup Idle
+ Auth-Grace-Period) expires
+ on home server.
+
+ Open Session-Timeout expires on Cleanup Idle
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 105]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ home server
+
+ Discon Failure to send ASR Wait, Discon
+ resend ASR
+
+ Discon ASR successfully sent and Cleanup Idle
+ ASA Received with Result-Code
+
+ Not ASA Received None No Change.
+ Discon
+
+ Any STR Received Send STA, Idle
+ Cleanup.
+
+ The following state machine is observed by a client when state is not
+ maintained on the server:
+
+ CLIENT, STATELESS
+ State Event Action New State
+ ---------------------------------------------------------------
+ Idle Client or Device Requests Send Pending
+ access service
+ specific
+ auth req
+
+ Pending Successful Service-specific Grant Open
+ authorization answer Access
+ received with Auth-Session-
+ State set to
+ NO_STATE_MAINTAINED
+
+ Pending Failed Service-specific Cleanup Idle
+ authorization answer
+ received
+
+ Open Session-Timeout Expires on Discon. Idle
+ Access Device user/device
+
+ Open Service to user is terminated Discon. Idle
+ user/device
+
+ The following state machine is observed by a server when it is not
+ maintaining state for the session:
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 106]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ SERVER, STATELESS
+ State Event Action New State
+ ---------------------------------------------------------------
+ Idle Service-specific authorization Send serv. Idle
+ request received, and specific
+ successfully processed answer
+
+8.2. Accounting Session State Machine
+
+ The following state machines MUST be supported for applications that
+ have an accounting portion or that require only accounting services.
+ The first state machine is to be observed by clients.
+
+ See Section 9.7 for Accounting Command Codes and Section 9.8 for
+ Accounting AVPs.
+
+ The server side in the accounting state machine depends in some cases
+ on the particular application. The Diameter base protocol defines a
+ default state machine that MUST be followed by all applications that
+ have not specified other state machines. This is the second state
+ machine in this section described below.
+
+ The default server side state machine requires the reception of
+ accounting records in any order and at any time, and does not place
+ any standards requirement on the processing of these records.
+ Implementations of Diameter may perform checking, ordering,
+ correlation, fraud detection, and other tasks based on these records.
+ AVPs may need to be inspected as a part of these tasks. The tasks
+ can happen either immediately after record reception or in a post-
+ processing phase. However, as these tasks are typically application
+ or even policy dependent, they are not standardized by the Diameter
+ specifications. Applications MAY define requirements on when to
+ accept accounting records based on the used value of Accounting-
+ Realtime-Required AVP, credit limits checks, and so on.
+
+ However, the Diameter base protocol defines one optional server side
+ state machine that MAY be followed by applications that require
+ keeping track of the session state at the accounting server. Note
+ that such tracking is incompatible with the ability to sustain long
+ duration connectivity problems. Therefore, the use of this state
+ machine is recommended only in applications where the value of the
+ Accounting-Realtime-Required AVP is DELIVER_AND_GRANT, and hence
+ accounting connectivity problems are required to cause the serviced
+ user to be disconnected. Otherwise, records produced by the client
+ may be lost by the server which no longer accepts them after the
+ connectivity is re-established. This state machine is the third
+ state machine in this section. The state machine is supervised by a
+ supervision session timer Ts, which the value should be reasonably
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 107]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ higher than the Acct_Interim_Interval value. Ts MAY be set to two
+ times the value of the Acct_Interim_Interval so as to avoid the
+ accounting session in the Diameter server to change to Idle state in
+ case of short transient network failure.
+
+ Any event not listed in the state machines MUST be considered as an
+ error condition, and a corresponding answer, if applicable, MUST be
+ returned to the originator of the message.
+
+ In the state table, the event 'Failure to send' means that the
+ Diameter client is unable to communicate with the desired
+ destination. This could be due to the peer being down, or due to the
+ peer sending back a transient failure or temporary protocol error
+ notification DIAMETER_OUT_OF_SPACE, DIAMETER_TOO_BUSY, or
+ DIAMETER_LOOP_DETECTED in the Result-Code AVP of the Accounting
+ Answer command.
+
+ The event 'Failed answer' means that the Diameter client received a
+ non-transient failure notification in the Accounting Answer command.
+
+ Note that the action 'Disconnect user/dev' MUST have an effect also
+ to the authorization session state table, e.g., cause the STR message
+ to be sent, if the given application has both authentication/
+ authorization and accounting portions.
+
+ The states PendingS, PendingI, PendingL, PendingE and PendingB stand
+ for pending states to wait for an answer to an accounting request
+ related to a Start, Interim, Stop, Event or buffered record,
+ respectively.
+
+ CLIENT, ACCOUNTING
+ State Event Action New State
+ ---------------------------------------------------------------
+ Idle Client or device requests Send PendingS
+ access accounting
+ start req.
+
+ Idle Client or device requests Send PendingE
+ a one-time service accounting
+ event req
+
+ Idle Records in storage Send PendingB
+ record
+
+ PendingS Successful accounting Open
+ start answer received
+
+ PendingS Failure to send and buffer Store Open
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 108]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ space available and realtime Start
+ not equal to DELIVER_AND_GRANT Record
+
+ PendingS Failure to send and no buffer Open
+ space available and realtime
+ equal to GRANT_AND_LOSE
+
+ PendingS Failure to send and no Disconnect Idle
+ buffer space available and user/dev
+ realtime not equal to
+ GRANT_AND_LOSE
+
+ PendingS Failed accounting start answer Open
+ received and realtime equal
+ to GRANT_AND_LOSE
+
+ PendingS Failed accounting start answer Disconnect Idle
+ received and realtime not user/dev
+ equal to GRANT_AND_LOSE
+
+ PendingS User service terminated Store PendingS
+ stop
+ record
+
+ Open Interim interval elapses Send PendingI
+ accounting
+ interim
+ record
+ Open User service terminated Send PendingL
+ accounting
+ stop req.
+
+ PendingI Successful accounting interim Open
+ answer received
+
+ PendingI Failure to send and (buffer Store Open
+ space available or old interim
+ record can be overwritten) record
+ and realtime not equal to
+ DELIVER_AND_GRANT
+
+ PendingI Failure to send and no buffer Open
+ space available and realtime
+ equal to GRANT_AND_LOSE
+
+
+ PendingI Failure to send and no Disconnect Idle
+ buffer space available and user/dev
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 109]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ realtime not equal to
+ GRANT_AND_LOSE
+
+ PendingI Failed accounting interim Open
+ answer received and realtime
+ equal to GRANT_AND_LOSE
+
+ PendingI Failed accounting interim Disconnect Idle
+ answer received and user/dev
+ realtime not equal to
+ GRANT_AND_LOSE
+
+ PendingI User service terminated Store PendingI
+ stop
+ record
+ PendingE Successful accounting Idle
+ event answer received
+
+ PendingE Failure to send and buffer Store Idle
+ space available event
+ record
+
+ PendingE Failure to send and no buffer Idle
+ space available
+
+ PendingE Failed accounting event answer Idle
+ received
+
+ PendingB Successful accounting answer Delete Idle
+ received record
+
+ PendingB Failure to send Idle
+
+ PendingB Failed accounting answer Delete Idle
+ received record
+
+ PendingL Successful accounting Idle
+ stop answer received
+
+ PendingL Failure to send and buffer Store Idle
+ space available stop
+ record
+
+ PendingL Failure to send and no buffer Idle
+ space available
+
+ PendingL Failed accounting stop answer Idle
+ received
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 110]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ SERVER, STATELESS ACCOUNTING
+ State Event Action New State
+ ---------------------------------------------------------------
+
+ Idle Accounting start request Send Idle
+ received, and successfully accounting
+ processed. start
+ answer
+
+ Idle Accounting event request Send Idle
+ received, and successfully accounting
+ processed. event
+ answer
+
+ Idle Interim record received, Send Idle
+ and successfully processed. accounting
+ interim
+ answer
+
+ Idle Accounting stop request Send Idle
+ received, and successfully accounting
+ processed stop answer
+
+ Idle Accounting request received, Send Idle
+ no space left to store accounting
+ records answer,
+ Result-Code =
+ OUT_OF_
+ SPACE
+
+ SERVER, STATEFUL ACCOUNTING
+ State Event Action New State
+ ---------------------------------------------------------------
+
+ Idle Accounting start request Send Open
+ received, and successfully accounting
+ processed. start
+ answer,
+ Start Ts
+
+ Idle Accounting event request Send Idle
+ received, and successfully accounting
+ processed. event
+ answer
+
+ Idle Accounting request received, Send Idle
+ no space left to store accounting
+ records answer,
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 111]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Result-Code =
+ OUT_OF_
+ SPACE
+
+ Open Interim record received, Send Open
+ and successfully processed. accounting
+ interim
+ answer,
+ Restart Ts
+
+ Open Accounting stop request Send Idle
+ received, and successfully accounting
+ processed stop answer,
+ Stop Ts
+
+ Open Accounting request received, Send Idle
+ no space left to store accounting
+ records answer,
+ Result-Code =
+ OUT_OF_
+ SPACE,
+ Stop Ts
+
+ Open Session supervision timer Ts Stop Ts Idle
+ expired
+
+8.3. Server-Initiated Re-Auth
+
+ A Diameter server may initiate a re-authentication and/or re-
+ authorization service for a particular session by issuing a Re-Auth-
+ Request (RAR).
+
+ For example, for pre-paid services, the Diameter server that
+ originally authorized a session may need some confirmation that the
+ user is still using the services.
+
+ An access device that receives a RAR message with Session-Id equal to
+ a currently active session MUST initiate a re-auth towards the user,
+ if the service supports this particular feature. Each Diameter
+ application MUST state whether server-initiated re-auth is supported,
+ since some applications do not allow access devices to prompt the
+ user for re-auth.
+
+8.3.1. Re-Auth-Request
+
+ The Re-Auth-Request (RAR), indicated by the Command-Code set to 258
+ and the message flags' 'R' bit set, may be sent by any server to the
+ access device that is providing session service, to request that the
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 112]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ user be re-authenticated and/or re-authorized.
+
+
+ Message Format
+
+ <RAR> ::= < Diameter Header: 258, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Destination-Host }
+ { Auth-Application-Id }
+ { Re-Auth-Request-Type }
+ [ User-Name ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+8.3.2. Re-Auth-Answer
+
+ The Re-Auth-Answer (RAA), indicated by the Command-Code set to 258
+ and the message flags' 'R' bit clear, is sent in response to the RAR.
+ The Result-Code AVP MUST be present, and indicates the disposition of
+ the request.
+
+ A successful RAA message MUST be followed by an application-specific
+ authentication and/or authorization message.
+
+
+ Message Format
+
+ <RAA> ::= < Diameter Header: 258, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ [ Origin-State-Id ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ [ Failed-AVP ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 113]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+8.4. Session Termination
+
+ It is necessary for a Diameter server that authorized a session, for
+ which it is maintaining state, to be notified when that session is no
+ longer active, both for tracking purposes as well as to allow
+ stateful agents to release any resources that they may have provided
+ for the user's session. For sessions whose state is not being
+ maintained, this section is not used.
+
+ When a user session that required Diameter authorization terminates,
+ the access device that provided the service MUST issue a Session-
+ Termination-Request (STR) message to the Diameter server that
+ authorized the service, to notify it that the session is no longer
+ active. An STR MUST be issued when a user session terminates for any
+ reason, including user logoff, expiration of Session-Timeout,
+ administrative action, termination upon receipt of an Abort-Session-
+ Request (see below), orderly shutdown of the access device, etc.
+
+ The access device also MUST issue an STR for a session that was
+ authorized but never actually started. This could occur, for
+ example, due to a sudden resource shortage in the access device, or
+ because the access device is unwilling to provide the type of service
+ requested in the authorization, or because the access device does not
+ support a mandatory AVP returned in the authorization, etc.
+
+ It is also possible that a session that was authorized is never
+ actually started due to action of a proxy. For example, a proxy may
+ modify an authorization answer, converting the result from success to
+ failure, prior to forwarding the message to the access device. If
+ the answer did not contain an Auth-Session-State AVP with the value
+ NO_STATE_MAINTAINED, a proxy that causes an authorized session not to
+ be started MUST issue an STR to the Diameter server that authorized
+ the session, since the access device has no way of knowing that the
+ session had been authorized.
+
+ A Diameter server that receives an STR message MUST clean up
+ resources (e.g., session state) associated with the Session-Id
+ specified in the STR, and return a Session-Termination-Answer.
+
+ A Diameter server also MUST clean up resources when the Session-
+ Timeout expires, or when the Authorization-Lifetime and the Auth-
+ Grace-Period AVPs expires without receipt of a re-authorization
+ request, regardless of whether an STR for that session is received.
+ The access device is not expected to provide service beyond the
+ expiration of these timers; thus, expiration of either of these
+ timers implies that the access device may have unexpectedly shut
+ down.
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 114]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+8.4.1. Session-Termination-Request
+
+ The Session-Termination-Request (STR), indicated by the Command-Code
+ set to 275 and the Command Flags' 'R' bit set, is sent by a Diameter
+ client or by a Diameter proxy to inform the Diameter Server that an
+ authenticated and/or authorized session is being terminated.
+
+
+ Message Format
+
+ <STR> ::= < Diameter Header: 275, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Auth-Application-Id }
+ { Termination-Cause }
+ [ User-Name ]
+ [ Destination-Host ]
+ * [ Class ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+8.4.2. Session-Termination-Answer
+
+ The Session-Termination-Answer (STA), indicated by the Command-Code
+ set to 275 and the message flags' 'R' bit clear, is sent by the
+ Diameter Server to acknowledge the notification that the session has
+ been terminated. The Result-Code AVP MUST be present, and MAY
+ contain an indication that an error occurred while servicing the STR.
+
+ Upon sending or receipt of the STA, the Diameter Server MUST release
+ all resources for the session indicated by the Session-Id AVP. Any
+ intermediate server in the Proxy-Chain MAY also release any
+ resources, if necessary.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 115]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Message Format
+
+ <STA> ::= < Diameter Header: 275, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ * [ Class ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ [ Failed-AVP ]
+ [ Origin-State-Id ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+8.5. Aborting a Session
+
+ A Diameter server may request that the access device stop providing
+ service for a particular session by issuing an Abort-Session-Request
+ (ASR).
+
+ For example, the Diameter server that originally authorized the
+ session may be required to cause that session to be stopped for lack
+ of credit or other reasons that were not anticipated when the session
+ was first authorized.
+
+ An access device that receives an ASR with Session-ID equal to a
+ currently active session MAY stop the session. Whether the access
+ device stops the session or not is implementation- and/or
+ configuration-dependent. For example, an access device may honor
+ ASRs from certain agents only. In any case, the access device MUST
+ respond with an Abort-Session-Answer, including a Result-Code AVP to
+ indicate what action it took.
+
+8.5.1. Abort-Session-Request
+
+ The Abort-Session-Request (ASR), indicated by the Command-Code set to
+ 274 and the message flags' 'R' bit set, may be sent by any Diameter
+ server or any Diameter proxy to the access device that is providing
+ session service, to request that the session identified by the
+ Session-Id be stopped.
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 116]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Message Format
+
+ <ASR> ::= < Diameter Header: 274, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Destination-Host }
+ { Auth-Application-Id }
+ [ User-Name ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+8.5.2. Abort-Session-Answer
+
+ The Abort-Session-Answer (ASA), indicated by the Command-Code set to
+ 274 and the message flags' 'R' bit clear, is sent in response to the
+ ASR. The Result-Code AVP MUST be present, and indicates the
+ disposition of the request.
+
+ If the session identified by Session-Id in the ASR was successfully
+ terminated, Result-Code is set to DIAMETER_SUCCESS. If the session
+ is not currently active, Result-Code is set to
+ DIAMETER_UNKNOWN_SESSION_ID. If the access device does not stop the
+ session for any other reason, Result-Code is set to
+ DIAMETER_UNABLE_TO_COMPLY.
+
+
+ Message Format
+
+ <ASA> ::= < Diameter Header: 274, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ [ Origin-State-Id ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ [ Failed-AVP ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 117]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+8.6. Inferring Session Termination from Origin-State-Id
+
+ The Origin-State-Id is used to allow detection of terminated sessions
+ for which no STR would have been issued, due to unanticipated
+ shutdown of an access device.
+
+ A Diameter client or access device increments the value of the
+ Origin-State-Id every time it is started or powered-up. The new
+ Origin-State-Id is then sent in the CER/CEA message immediately upon
+ connection to the server. The Diameter server receiving the new
+ Origin-State-Id can determine whether the sending Diameter client had
+ abruptly shutdown by comparing the old value of the Origin-State-Id
+ it has kept for that specific client is less than the new value and
+ whether it has un-terminated sessions originating from that client.
+
+ An access device can also include the Origin-State-Id in request
+ messages other than CER if there are relays or proxies in between the
+ access device and the server. In this case, however, the server
+ cannot discover that the access device has been restarted unless and
+ until it receives a new request from it. Therefore this mechanism is
+ more opportunistic across proxies and relays.
+
+ The Diameter server may assume that all sessions that were active
+ prior to detection of a client restart have been terminated. The
+ Diameter server MAY clean up all session state associated with such
+ lost sessions, and MAY also issues STRs for all such lost sessions
+ that were authorized on upstream servers, to allow session state to
+ be cleaned up globally.
+
+8.7. Auth-Request-Type AVP
+
+ The Auth-Request-Type AVP (AVP Code 274) is of type Enumerated and is
+ included in application-specific auth requests to inform the peers
+ whether a user is to be authenticated only, authorized only or both.
+ Note any value other than both MAY cause RADIUS interoperability
+ issues. The following values are defined:
+
+
+ AUTHENTICATE_ONLY 1
+
+ The request being sent is for authentication only, and MUST
+ contain the relevant application specific authentication AVPs that
+ are needed by the Diameter server to authenticate the user.
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 118]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ AUTHORIZE_ONLY 2
+
+ The request being sent is for authorization only, and MUST contain
+ the application-specific authorization AVPs that are necessary to
+ identify the service being requested/offered.
+
+
+ AUTHORIZE_AUTHENTICATE 3
+
+ The request contains a request for both authentication and
+ authorization. The request MUST include both the relevant
+ application-specific authentication information, and authorization
+ information necessary to identify the service being requested/
+ offered.
+
+
+8.8. Session-Id AVP
+
+ The Session-Id AVP (AVP Code 263) is of type UTF8String and is used
+ to identify a specific session (see Section 8). All messages
+ pertaining to a specific session MUST include only one Session-Id AVP
+ and the same value MUST be used throughout the life of a session.
+ When present, the Session-Id SHOULD appear immediately following the
+ Diameter Header (see Section 3).
+
+ The Session-Id MUST be globally and eternally unique, as it is meant
+ to uniquely identify a user session without reference to any other
+ information, and may be needed to correlate historical authentication
+ information with accounting information. The Session-Id includes a
+ mandatory portion and an implementation-defined portion; a
+ recommended format for the implementation-defined portion is outlined
+ below.
+
+ The Session-Id MUST begin with the sender's identity encoded in the
+ DiameterIdentity type (see Section 4.4). The remainder of the
+ Session-Id is delimited by a ";" character, and MAY be any sequence
+ that the client can guarantee to be eternally unique; however, the
+ following format is recommended, (square brackets [] indicate an
+ optional element):
+
+ <DiameterIdentity>;<high 32 bits>;<low 32 bits>[;<optional value>]
+
+ <high 32 bits> and <low 32 bits> are decimal representations of the
+ high and low 32 bits of a monotonically increasing 64-bit value. The
+ 64-bit value is rendered in two part to simplify formatting by 32-bit
+ processors. At startup, the high 32 bits of the 64-bit value MAY be
+ initialized to the time in NTP format [RFC5905], and the low 32 bits
+ MAY be initialized to zero. This will for practical purposes
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 119]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ eliminate the possibility of overlapping Session-Ids after a reboot,
+ assuming the reboot process takes longer than a second.
+ Alternatively, an implementation MAY keep track of the increasing
+ value in non-volatile memory.
+
+
+ <optional value> is implementation specific but may include a modem's
+ device Id, a layer 2 address, timestamp, etc.
+
+ Example, in which there is no optional value:
+
+ accesspoint7.example.com;1876543210;523
+
+ Example, in which there is an optional value:
+
+ accesspoint7.example.com;1876543210;523;[email protected]
+
+ The Session-Id is created by the Diameter application initiating the
+ session, which in most cases is done by the client. Note that a
+ Session-Id MAY be used for both the authentication, authorization and
+ accounting commands of a given application.
+
+8.9. Authorization-Lifetime AVP
+
+ The Authorization-Lifetime AVP (AVP Code 291) is of type Unsigned32
+ and contains the maximum number of seconds of service to be provided
+ to the user before the user is to be re-authenticated and/or re-
+ authorized. Care should be taken when the Authorization- Lifetime
+ value is determined, since a low, non-zero, value could create
+ significant Diameter traffic, which could congest both the network
+ and the agents.
+
+ A value of zero (0) means that immediate re-auth is necessary by the
+ access device. The absence of this AVP, or a value of all ones
+ (meaning all bits in the 32 bit field are set to one) means no re-
+ auth is expected.
+
+ If both this AVP and the Session-Timeout AVP are present in a
+ message, the value of the latter MUST NOT be smaller than the
+ Authorization-Lifetime AVP.
+
+ An Authorization-Lifetime AVP MAY be present in re-authorization
+ messages, and contains the number of seconds the user is authorized
+ to receive service from the time the re-auth answer message is
+ received by the access device.
+
+ This AVP MAY be provided by the client as a hint of the maximum
+ lifetime that it is willing to accept. The server MUST return a
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 120]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ value that is equal to, or smaller, than the one provided by the
+ client.
+
+8.10. Auth-Grace-Period AVP
+
+ The Auth-Grace-Period AVP (AVP Code 276) is of type Unsigned32 and
+ contains the number of seconds the Diameter server will wait
+ following the expiration of the Authorization-Lifetime AVP before
+ cleaning up resources for the session.
+
+8.11. Auth-Session-State AVP
+
+ The Auth-Session-State AVP (AVP Code 277) is of type Enumerated and
+ specifies whether state is maintained for a particular session. The
+ client MAY include this AVP in requests as a hint to the server, but
+ the value in the server's answer message is binding. The following
+ values are supported:
+
+
+ STATE_MAINTAINED 0
+
+ This value is used to specify that session state is being
+ maintained, and the access device MUST issue a session termination
+ message when service to the user is terminated. This is the
+ default value.
+
+
+ NO_STATE_MAINTAINED 1
+
+ This value is used to specify that no session termination messages
+ will be sent by the access device upon expiration of the
+ Authorization-Lifetime.
+
+
+8.12. Re-Auth-Request-Type AVP
+
+ The Re-Auth-Request-Type AVP (AVP Code 285) is of type Enumerated and
+ is included in application-specific auth answers to inform the client
+ of the action expected upon expiration of the Authorization-Lifetime.
+ If the answer message contains an Authorization-Lifetime AVP with a
+ positive value, the Re-Auth-Request-Type AVP MUST be present in an
+ answer message. The following values are defined:
+
+
+ AUTHORIZE_ONLY 0
+
+ An authorization only re-auth is expected upon expiration of the
+ Authorization-Lifetime. This is the default value if the AVP is
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 121]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ not present in answer messages that include the Authorization-
+ Lifetime.
+
+
+ AUTHORIZE_AUTHENTICATE 1
+
+ An authentication and authorization re-auth is expected upon
+ expiration of the Authorization-Lifetime.
+
+
+8.13. Session-Timeout AVP
+
+ The Session-Timeout AVP (AVP Code 27) [RFC2865] is of type Unsigned32
+ and contains the maximum number of seconds of service to be provided
+ to the user before termination of the session. When both the
+ Session-Timeout and the Authorization-Lifetime AVPs are present in an
+ answer message, the former MUST be equal to or greater than the value
+ of the latter.
+
+ A session that terminates on an access device due to the expiration
+ of the Session-Timeout MUST cause an STR to be issued, unless both
+ the access device and the home server had previously agreed that no
+ session termination messages would be sent (see Section 8.11).
+
+ A Session-Timeout AVP MAY be present in a re-authorization answer
+ message, and contains the remaining number of seconds from the
+ beginning of the re-auth.
+
+ A value of zero, or the absence of this AVP, means that this session
+ has an unlimited number of seconds before termination.
+
+ This AVP MAY be provided by the client as a hint of the maximum
+ timeout that it is willing to accept. However, the server MAY return
+ a value that is equal to, or smaller, than the one provided by the
+ client.
+
+8.14. User-Name AVP
+
+ The User-Name AVP (AVP Code 1) [RFC2865] is of type UTF8String, which
+ contains the User-Name, in a format consistent with the NAI
+ specification [RFC4282].
+
+8.15. Termination-Cause AVP
+
+ The Termination-Cause AVP (AVP Code 295) is of type Enumerated, and
+ is used to indicate the reason why a session was terminated on the
+ access device. The following values are defined:
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 122]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ DIAMETER_LOGOUT 1
+
+ The user initiated a disconnect
+
+
+ DIAMETER_SERVICE_NOT_PROVIDED 2
+
+ This value is used when the user disconnected prior to the receipt
+ of the authorization answer message.
+
+
+ DIAMETER_BAD_ANSWER 3
+
+ This value indicates that the authorization answer received by the
+ access device was not processed successfully.
+
+
+ DIAMETER_ADMINISTRATIVE 4
+
+ The user was not granted access, or was disconnected, due to
+ administrative reasons, such as the receipt of a Abort-Session-
+ Request message.
+
+
+ DIAMETER_LINK_BROKEN 5
+
+ The communication to the user was abruptly disconnected.
+
+
+ DIAMETER_AUTH_EXPIRED 6
+
+ The user's access was terminated since its authorized session time
+ has expired.
+
+
+ DIAMETER_USER_MOVED 7
+
+ The user is receiving services from another access device.
+
+
+ DIAMETER_SESSION_TIMEOUT 8
+
+ The user's session has timed out, and service has been terminated.
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 123]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+8.16. Origin-State-Id AVP
+
+ The Origin-State-Id AVP (AVP Code 278), of type Unsigned32, is a
+ monotonically increasing value that is advanced whenever a Diameter
+ entity restarts with loss of previous state, for example upon reboot.
+ Origin-State-Id MAY be included in any Diameter message, including
+ CER.
+
+ A Diameter entity issuing this AVP MUST create a higher value for
+ this AVP each time its state is reset. A Diameter entity MAY set
+ Origin-State-Id to the time of startup, or it MAY use an incrementing
+ counter retained in non-volatile memory across restarts.
+
+ The Origin-State-Id, if present, MUST reflect the state of the entity
+ indicated by Origin-Host. If a proxy modifies Origin-Host, it MUST
+ either remove Origin-State-Id or modify it appropriately as well.
+ Typically, Origin-State-Id is used by an access device that always
+ starts up with no active sessions; that is, any session active prior
+ to restart will have been lost. By including Origin-State-Id in a
+ message, it allows other Diameter entities to infer that sessions
+ associated with a lower Origin-State-Id are no longer active. If an
+ access device does not intend for such inferences to be made, it MUST
+ either not include Origin-State-Id in any message, or set its value
+ to 0.
+
+8.17. Session-Binding AVP
+
+ The Session-Binding AVP (AVP Code 270) is of type Unsigned32, and MAY
+ be present in application-specific authorization answer messages. If
+ present, this AVP MAY inform the Diameter client that all future
+ application-specific re-auth and Session-Termination-Request messages
+ for this session MUST be sent to the same authorization server.
+
+ This field is a bit mask, and the following bits have been defined:
+
+
+ RE_AUTH 1
+
+ When set, future re-auth messages for this session MUST NOT
+ include the Destination-Host AVP. When cleared, the default
+ value, the Destination-Host AVP MUST be present in all re-auth
+ messages for this session.
+
+
+ STR 2
+
+ When set, the STR message for this session MUST NOT include the
+ Destination-Host AVP. When cleared, the default value, the
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 124]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Destination-Host AVP MUST be present in the STR message for this
+ session.
+
+
+ ACCOUNTING 4
+
+ When set, all accounting messages for this session MUST NOT
+ include the Destination-Host AVP. When cleared, the default
+ value, the Destination-Host AVP, if known, MUST be present in all
+ accounting messages for this session.
+
+
+8.18. Session-Server-Failover AVP
+
+ The Session-Server-Failover AVP (AVP Code 271) is of type Enumerated,
+ and MAY be present in application-specific authorization answer
+ messages that either do not include the Session-Binding AVP or
+ include the Session-Binding AVP with any of the bits set to a zero
+ value. If present, this AVP MAY inform the Diameter client that if a
+ re-auth or STR message fails due to a delivery problem, the Diameter
+ client SHOULD issue a subsequent message without the Destination-Host
+ AVP. When absent, the default value is REFUSE_SERVICE.
+
+ The following values are supported:
+
+
+ REFUSE_SERVICE 0
+
+ If either the re-auth or the STR message delivery fails, terminate
+ service with the user, and do not attempt any subsequent attempts.
+
+
+ TRY_AGAIN 1
+
+ If either the re-auth or the STR message delivery fails, resend
+ the failed message without the Destination-Host AVP present.
+
+
+ ALLOW_SERVICE 2
+
+ If re-auth message delivery fails, assume that re-authorization
+ succeeded. If STR message delivery fails, terminate the session.
+
+
+ TRY_AGAIN_ALLOW_SERVICE 3
+
+ If either the re-auth or the STR message delivery fails, resend
+ the failed message without the Destination-Host AVP present. If
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 125]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ the second delivery fails for re-auth, assume re-authorization
+ succeeded. If the second delivery fails for STR, terminate the
+ session.
+
+
+8.19. Multi-Round-Time-Out AVP
+
+ The Multi-Round-Time-Out AVP (AVP Code 272) is of type Unsigned32,
+ and SHOULD be present in application-specific authorization answer
+ messages whose Result-Code AVP is set to DIAMETER_MULTI_ROUND_AUTH.
+ This AVP contains the maximum number of seconds that the access
+ device MUST provide the user in responding to an authentication
+ request.
+
+8.20. Class AVP
+
+ The Class AVP (AVP Code 25) is of type OctetString and is used by
+ Diameter servers to return state information to the access device.
+ When one or more Class AVPs are present in application-specific
+ authorization answer messages, they MUST be present in subsequent re-
+ authorization, session termination and accounting messages. Class
+ AVPs found in a re-authorization answer message override the ones
+ found in any previous authorization answer message. Diameter server
+ implementations SHOULD NOT return Class AVPs that require more than
+ 4096 bytes of storage on the Diameter client. A Diameter client that
+ receives Class AVPs whose size exceeds local available storage MUST
+ terminate the session.
+
+8.21. Event-Timestamp AVP
+
+ The Event-Timestamp (AVP Code 55) is of type Time, and MAY be
+ included in an Accounting-Request and Accounting-Answer messages to
+ record the time that the reported event occurred, in seconds since
+ January 1, 1900 00:00 UTC.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 126]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+9. Accounting
+
+ This accounting protocol is based on a server directed model with
+ capabilities for real-time delivery of accounting information.
+ Several fault resilience methods [RFC2975] have been built in to the
+ protocol in order minimize loss of accounting data in various fault
+ situations and under different assumptions about the capabilities of
+ the used devices.
+
+9.1. Server Directed Model
+
+ The server directed model means that the device generating the
+ accounting data gets information from either the authorization server
+ (if contacted) or the accounting server regarding the way accounting
+ data shall be forwarded. This information includes accounting record
+ timeliness requirements.
+
+ As discussed in [RFC2975], real-time transfer of accounting records
+ is a requirement, such as the need to perform credit limit checks and
+ fraud detection. Note that batch accounting is not a requirement,
+ and is therefore not supported by Diameter. Should batched
+ accounting be required in the future, a new Diameter application will
+ need to be created, or it could be handled using another protocol.
+ Note, however, that even if at the Diameter layer accounting requests
+ are processed one by one, transport protocols used under Diameter
+ typically batch several requests in the same packet under heavy
+ traffic conditions. This may be sufficient for many applications.
+
+ The authorization server (chain) directs the selection of proper
+ transfer strategy, based on its knowledge of the user and
+ relationships of roaming partnerships. The server (or agents) uses
+ the Acct-Interim-Interval and Accounting-Realtime-Required AVPs to
+ control the operation of the Diameter peer operating as a client.
+ The Acct-Interim-Interval AVP, when present, instructs the Diameter
+ node acting as a client to produce accounting records continuously
+ even during a session. Accounting-Realtime-Required AVP is used to
+ control the behavior of the client when the transfer of accounting
+ records from the Diameter client is delayed or unsuccessful.
+
+ The Diameter accounting server MAY override the interim interval or
+ the realtime requirements by including the Acct-Interim-Interval or
+ Accounting-Realtime-Required AVP in the Accounting-Answer message.
+ When one of these AVPs is present, the latest value received SHOULD
+ be used in further accounting activities for the same session.
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 127]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+9.2. Protocol Messages
+
+ A Diameter node that receives a successful authentication and/or
+ authorization messages from the Diameter server SHOULD collect
+ accounting information for the session. The Accounting-Request
+ message is used to transmit the accounting information to the
+ Diameter server, which MUST reply with the Accounting-Answer message
+ to confirm reception. The Accounting-Answer message includes the
+ Result-Code AVP, which MAY indicate that an error was present in the
+ accounting message. The value of the Accounting-Realtime-Required
+ AVP received earlier for the session in question may indicate that
+ the user's session has to be terminated when a rejected Accounting-
+ Request message was received.
+
+9.3. Accounting Application Extension and Requirements
+
+ Each Diameter application (e.g., NASREQ, MobileIP), SHOULD define
+ their Service-Specific AVPs that MUST be present in the Accounting-
+ Request message in a section entitled "Accounting AVPs". The
+ application MUST assume that the AVPs described in this document will
+ be present in all Accounting messages, so only their respective
+ service-specific AVPs need to be defined in that section.
+
+ Applications have the option of using one or both of the following
+ accounting application extension models:
+
+ Split Accounting Service
+
+ The accounting message will carry the Application Id of the
+ Diameter base accounting application (see Section 2.4).
+ Accounting messages may be routed to Diameter nodes other than the
+ corresponding Diameter application. These nodes might be
+ centralized accounting servers that provide accounting service for
+ multiple different Diameter applications. These nodes MUST
+ advertise the Diameter base accounting Application Id during
+ capabilities exchange.
+
+
+ Coupled Accounting Service
+
+ The accounting messages will carry the Application Id of the
+ application that is using it. The application itself will process
+ the received accounting records or forward them to an accounting
+ server. There is no accounting application advertisement required
+ during capabilities exchange and the accounting messages will be
+ routed the same as any of the other application messages.
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 128]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ In cases where an application does not define its own accounting
+ service, it is preferred that the split accounting model be used.
+
+9.4. Fault Resilience
+
+ Diameter Base protocol mechanisms are used to overcome small message
+ loss and network faults of temporary nature.
+
+ Diameter peers acting as clients MUST implement the use of failover
+ to guard against server failures and certain network failures.
+ Diameter peers acting as agents or related off-line processing
+ systems MUST detect duplicate accounting records caused by the
+ sending of same record to several servers and duplication of messages
+ in transit. This detection MUST be based on the inspection of the
+ Session-Id and Accounting-Record-Number AVP pairs. Appendix C
+ discusses duplicate detection needs and implementation issues.
+
+ Diameter clients MAY have non-volatile memory for the safe storage of
+ accounting records over reboots or extended network failures, network
+ partitions, and server failures. If such memory is available, the
+ client SHOULD store new accounting records there as soon as the
+ records are created and until a positive acknowledgement of their
+ reception from the Diameter Server has been received. Upon a reboot,
+ the client MUST starting sending the records in the non-volatile
+ memory to the accounting server with appropriate modifications in
+ termination cause, session length, and other relevant information in
+ the records.
+
+ A further application of this protocol may include AVPs to control
+ how many accounting records may at most be stored in the Diameter
+ client without committing them to the non-volatile memory or
+ transferring them to the Diameter server.
+
+ The client SHOULD NOT remove the accounting data from any of its
+ memory areas before the correct Accounting-Answer has been received.
+ The client MAY remove oldest, undelivered or yet unacknowledged
+ accounting data if it runs out of resources such as memory. It is an
+ implementation dependent matter for the client to accept new sessions
+ under this condition.
+
+9.5. Accounting Records
+
+ In all accounting records, the Session-Id AVP MUST be present; the
+ User-Name AVP MUST be present if it is available to the Diameter
+ client.
+
+ Different types of accounting records are sent depending on the
+ actual type of accounted service and the authorization server's
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 129]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ directions for interim accounting. If the accounted service is a
+ one-time event, meaning that the start and stop of the event are
+ simultaneous, then the Accounting-Record-Type AVP MUST be present and
+ set to the value EVENT_RECORD.
+
+ If the accounted service is of a measurable length, then the AVP MUST
+ use the values START_RECORD, STOP_RECORD, and possibly,
+ INTERIM_RECORD. If the authorization server has not directed interim
+ accounting to be enabled for the session, two accounting records MUST
+ be generated for each service of type session. When the initial
+ Accounting-Request for a given session is sent, the Accounting-
+ Record-Type AVP MUST be set to the value START_RECORD. When the last
+ Accounting-Request is sent, the value MUST be STOP_RECORD.
+
+ If the authorization server has directed interim accounting to be
+ enabled, the Diameter client MUST produce additional records between
+ the START_RECORD and STOP_RECORD, marked INTERIM_RECORD. The
+ production of these records is directed by Acct-Interim-Interval as
+ well as any re-authentication or re-authorization of the session.
+ The Diameter client MUST overwrite any previous interim accounting
+ records that are locally stored for delivery, if a new record is
+ being generated for the same session. This ensures that only one
+ pending interim record can exist on an access device for any given
+ session.
+
+ A particular value of Accounting-Sub-Session-Id MUST appear only in
+ one sequence of accounting records from a DIAMETER client, except for
+ the purposes of retransmission. The one sequence that is sent MUST
+ be either one record with Accounting-Record-Type AVP set to the value
+ EVENT_RECORD, or several records starting with one having the value
+ START_RECORD, followed by zero or more INTERIM_RECORD and a single
+ STOP_RECORD. A particular Diameter application specification MUST
+ define the type of sequences that MUST be used.
+
+9.6. Correlation of Accounting Records
+
+ If an application uses accounting messages, it can correlate
+ accounting records with a specific application session by using the
+ Session-Id of the particular application session in the accounting
+ messages. Accounting messages MAY also use a different Session-Id
+ from that of the application sessions in which case other session
+ related information is needed to perform correlation.
+
+ In cases where an application requires multiple accounting sub-
+ session, an Accounting-Sub-Session-Id AVP is used to differentiate
+ each sub-session. The Session-Id would remain constant for all sub-
+ sessions and is be used to correlate all the sub-sessions to a
+ particular application session. Note that receiving a STOP_RECORD
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 130]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ with no Accounting-Sub-Session-Id AVP when sub-sessions were
+ originally used in the START_RECORD messages implies that all sub-
+ sessions are terminated.
+
+ There are also cases where an application needs to correlate multiple
+ application sessions into a single accounting record; the accounting
+ record may span multiple different Diameter applications and sessions
+ used by the same user at a given time. In such cases, the Acct-
+ Multi-Session-Id AVP is used. The Acct-Multi-Session-Id AVP SHOULD
+ be signaled by the server to the access device (typically during
+ authorization) when it determines that a request belongs to an
+ existing session. The access device MUST then include the Acct-
+ Multi-Session-Id AVP in all subsequent accounting messages.
+
+ The Acct-Multi-Session-Id AVP MAY include the value of the original
+ Session-Id. It's contents are implementation specific, but MUST be
+ globally unique across other Acct-Multi-Session-Id, and MUST NOT
+ change during the life of a session.
+
+ A Diameter application document MUST define the exact concept of a
+ session that is being accounted, and MAY define the concept of a
+ multi-session. For instance, the NASREQ DIAMETER application treats
+ a single PPP connection to a Network Access Server as one session,
+ and a set of Multilink PPP sessions as one multi-session.
+
+9.7. Accounting Command-Codes
+
+ This section defines Command-Code values that MUST be supported by
+ all Diameter implementations that provide Accounting services.
+
+9.7.1. Accounting-Request
+
+ The Accounting-Request (ACR) command, indicated by the Command-Code
+ field set to 271 and the Command Flags' 'R' bit set, is sent by a
+ Diameter node, acting as a client, in order to exchange accounting
+ information with a peer.
+
+ The AVP listed below SHOULD include service-specific accounting AVPs,
+ as described in Section 9.3.
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 131]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Message Format
+
+ <ACR> ::= < Diameter Header: 271, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Accounting-Record-Type }
+ { Accounting-Record-Number }
+ [ Acct-Application-Id ]
+ [ Vendor-Specific-Application-Id ]
+ [ User-Name ]
+ [ Destination-Host ]
+ [ Accounting-Sub-Session-Id ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Acct-Interim-Interval ]
+ [ Accounting-Realtime-Required ]
+ [ Origin-State-Id ]
+ [ Event-Timestamp ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+9.7.2. Accounting-Answer
+
+ The Accounting-Answer (ACA) command, indicated by the Command-Code
+ field set to 271 and the Command Flags' 'R' bit cleared, is used to
+ acknowledge an Accounting-Request command. The Accounting-Answer
+ command contains the same Session-Id as the corresponding request.
+
+ Only the target Diameter Server, known as the home Diameter Server,
+ SHOULD respond with the Accounting-Answer command.
+
+ The AVP listed below SHOULD include service-specific accounting AVPs,
+ as described in Section 9.3.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 132]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Message Format
+
+ <ACA> ::= < Diameter Header: 271, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ { Accounting-Record-Type }
+ { Accounting-Record-Number }
+ [ Acct-Application-Id ]
+ [ Vendor-Specific-Application-Id ]
+ [ User-Name ]
+ [ Accounting-Sub-Session-Id ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ [ Failed-AVP ]
+ [ Acct-Interim-Interval ]
+ [ Accounting-Realtime-Required ]
+ [ Origin-State-Id ]
+ [ Event-Timestamp ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+9.8. Accounting AVPs
+
+ This section contains AVPs that describe accounting usage information
+ related to a specific session.
+
+9.8.1. Accounting-Record-Type AVP
+
+ The Accounting-Record-Type AVP (AVP Code 480) is of type Enumerated
+ and contains the type of accounting record being sent. The following
+ values are currently defined for the Accounting-Record-Type AVP:
+
+
+ EVENT_RECORD 1
+
+ An Accounting Event Record is used to indicate that a one-time
+ event has occurred (meaning that the start and end of the event
+ are simultaneous). This record contains all information relevant
+ to the service, and is the only record of the service.
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 133]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ START_RECORD 2
+
+ An Accounting Start, Interim, and Stop Records are used to
+ indicate that a service of a measurable length has been given. An
+ Accounting Start Record is used to initiate an accounting session,
+ and contains accounting information that is relevant to the
+ initiation of the session.
+
+
+ INTERIM_RECORD 3
+
+ An Interim Accounting Record contains cumulative accounting
+ information for an existing accounting session. Interim
+ Accounting Records SHOULD be sent every time a re-authentication
+ or re-authorization occurs. Further, additional interim record
+ triggers MAY be defined by application-specific Diameter
+ applications. The selection of whether to use INTERIM_RECORD
+ records is done by the Acct-Interim-Interval AVP.
+
+
+ STOP_RECORD 4
+
+ An Accounting Stop Record is sent to terminate an accounting
+ session and contains cumulative accounting information relevant to
+ the existing session.
+
+
+9.8.2. Acct-Interim-Interval AVP
+
+ The Acct-Interim-Interval AVP (AVP Code 85) is of type Unsigned32 and
+ is sent from the Diameter home authorization server to the Diameter
+ client. The client uses information in this AVP to decide how and
+ when to produce accounting records. With different values in this
+ AVP, service sessions can result in one, two, or two+N accounting
+ records, based on the needs of the home-organization. The following
+ accounting record production behavior is directed by the inclusion of
+ this AVP:
+
+
+ 1. The omission of the Acct-Interim-Interval AVP or its inclusion
+ with Value field set to 0 means that EVENT_RECORD, START_RECORD,
+ and STOP_RECORD are produced, as appropriate for the service.
+
+
+ 2. The inclusion of the AVP with Value field set to a non-zero value
+ means that INTERIM_RECORD records MUST be produced between the
+ START_RECORD and STOP_RECORD records. The Value field of this
+ AVP is the nominal interval between these records in seconds.
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 134]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ The Diameter node that originates the accounting information,
+ known as the client, MUST produce the first INTERIM_RECORD record
+ roughly at the time when this nominal interval has elapsed from
+ the START_RECORD, the next one again as the interval has elapsed
+ once more, and so on until the session ends and a STOP_RECORD
+ record is produced.
+
+ The client MUST ensure that the interim record production times
+ are randomized so that large accounting message storms are not
+ created either among records or around a common service start
+ time.
+
+9.8.3. Accounting-Record-Number AVP
+
+ The Accounting-Record-Number AVP (AVP Code 485) is of type Unsigned32
+ and identifies this record within one session. As Session-Id AVPs
+ are globally unique, the combination of Session-Id and Accounting-
+ Record-Number AVPs is also globally unique, and can be used in
+ matching accounting records with confirmations. An easy way to
+ produce unique numbers is to set the value to 0 for records of type
+ EVENT_RECORD and START_RECORD, and set the value to 1 for the first
+ INTERIM_RECORD, 2 for the second, and so on until the value for
+ STOP_RECORD is one more than for the last INTERIM_RECORD.
+
+9.8.4. Acct-Session-Id AVP
+
+ The Acct-Session-Id AVP (AVP Code 44) is of type OctetString is only
+ used when RADIUS/Diameter translation occurs. This AVP contains the
+ contents of the RADIUS Acct-Session-Id attribute.
+
+9.8.5. Acct-Multi-Session-Id AVP
+
+ The Acct-Multi-Session-Id AVP (AVP Code 50) is of type UTF8String,
+ following the format specified in Section 8.8. The Acct-Multi-
+ Session-Id AVP is used to link together multiple related accounting
+ sessions, where each session would have a unique Session-Id, but the
+ same Acct-Multi-Session-Id AVP. This AVP MAY be returned by the
+ Diameter server in an authorization answer, and MUST be used in all
+ accounting messages for the given session.
+
+9.8.6. Accounting-Sub-Session-Id AVP
+
+ The Accounting-Sub-Session-Id AVP (AVP Code 287) is of type
+ Unsigned64 and contains the accounting sub-session identifier. The
+ combination of the Session-Id and this AVP MUST be unique per sub-
+ session, and the value of this AVP MUST be monotonically increased by
+ one for all new sub-sessions. The absence of this AVP implies no
+ sub-sessions are in use, with the exception of an Accounting-Request
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 135]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ whose Accounting-Record-Type is set to STOP_RECORD. A STOP_RECORD
+ message with no Accounting-Sub-Session-Id AVP present will signal the
+ termination of all sub-sessions for a given Session-Id.
+
+9.8.7. Accounting-Realtime-Required AVP
+
+ The Accounting-Realtime-Required AVP (AVP Code 483) is of type
+ Enumerated and is sent from the Diameter home authorization server to
+ the Diameter client or in the Accounting-Answer from the accounting
+ server. The client uses information in this AVP to decide what to do
+ if the sending of accounting records to the accounting server has
+ been temporarily prevented due to, for instance, a network problem.
+
+
+ DELIVER_AND_GRANT 1
+
+ The AVP with Value field set to DELIVER_AND_GRANT means that the
+ service MUST only be granted as long as there is a connection to
+ an accounting server. Note that the set of alternative accounting
+ servers are treated as one server in this sense. Having to move
+ the accounting record stream to a backup server is not a reason to
+ discontinue the service to the user.
+
+
+ GRANT_AND_STORE 2
+
+ The AVP with Value field set to GRANT_AND_STORE means that service
+ SHOULD be granted if there is a connection, or as long as records
+ can still be stored as described in Section 9.4.
+
+ This is the default behavior if the AVP isn't included in the
+ reply from the authorization server.
+
+
+ GRANT_AND_LOSE 3
+
+ The AVP with Value field set to GRANT_AND_LOSE means that service
+ SHOULD be granted even if the records cannot be delivered or
+ stored.
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 136]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+10. AVP Occurrence Table
+
+ The following tables presents the AVPs defined in this document, and
+ specifies in which Diameter messages they MAY be present or not.
+ AVPs that occur only inside a Grouped AVP are not shown in this
+ table.
+
+ The table uses the following symbols:
+
+
+ 0 The AVP MUST NOT be present in the message.
+
+ 0+ Zero or more instances of the AVP MAY be present in the
+ message.
+
+ 0-1 Zero or one instance of the AVP MAY be present in the message.
+ It is considered an error if there are more than one instance of
+ the AVP.
+
+ 1 One instance of the AVP MUST be present in the message.
+
+ 1+ At least one instance of the AVP MUST be present in the
+ message.
+
+10.1. Base Protocol Command AVP Table
+
+ The table in this section is limited to the non-accounting Command
+ Codes defined in this specification.
+
+ +-----------------------------------------------+
+ | Command-Code |
+ +---+---+---+---+---+---+---+---+---+---+---+---+
+ Attribute Name |CER|CEA|DPR|DPA|DWR|DWA|RAR|RAA|ASR|ASA|STR|STA|
+ --------------------+---+---+---+---+---+---+---+---+---+---+---+---+
+ Acct-Interim- |0 |0 |0 |0 |0 |0 |0-1|0 |0 |0 |0 |0 |
+ Interval | | | | | | | | | | | | |
+ Accounting-Realtime-|0 |0 |0 |0 |0 |0 |0-1|0 |0 |0 |0 |0 |
+ Required | | | | | | | | | | | | |
+ Acct-Application-Id |0+ |0+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Auth-Application-Id |0+ |0+ |0 |0 |0 |0 |1 |0 |1 |0 |1 |0 |
+ Auth-Grace-Period |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Auth-Request-Type |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Auth-Session-State |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Authorization- |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Lifetime | | | | | | | | | | | | |
+ Class |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0+ |0+ |
+ Destination-Host |0 |0 |0 |0 |0 |0 |1 |0 |1 |0 |0-1|0 |
+ Destination-Realm |0 |0 |0 |0 |0 |0 |1 |0 |1 |0 |1 |0 |
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 137]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Disconnect-Cause |0 |0 |1 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Error-Message |0 |0-1|0 |0-1|0 |0-1|0 |0-1|0 |0-1|0 |0-1|
+ Error-Reporting-Host|0 |0 |0 |0 |0 |0 |0 |0-1|0 |0-1|0 |0-1|
+ Failed-AVP |0 |0+ |0 |0+ |0 |0+ |0 |0+ |0 |0+ |0 |0+ |
+ Firmware-Revision |0-1|0-1|0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Host-IP-Address |1+ |1+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Inband-Security-Id |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Multi-Round-Time-Out|0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Origin-Host |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |
+ Origin-Realm |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |
+ Origin-State-Id |0-1|0-1|0 |0 |0-1|0-1|0-1|0-1|0-1|0-1|0-1|0-1|
+ Product-Name |1 |1 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Proxy-Info |0 |0 |0 |0 |0 |0 |0+ |0+ |0+ |0+ |0+ |0+ |
+ Redirect-Host |0 |0 |0 |0 |0 |0 |0 |0+ |0 |0+ |0 |0+ |
+ Redirect-Host-Usage |0 |0 |0 |0 |0 |0 |0 |0-1|0 |0-1|0 |0-1|
+ Redirect-Max-Cache- |0 |0 |0 |0 |0 |0 |0 |0-1|0 |0-1|0 |0-1|
+ Time | | | | | | | | | | | | |
+ Result-Code |0 |1 |0 |1 |0 |1 |0 |1 |0 |1 |0 |1 |
+ Re-Auth-Request-Type|0 |0 |0 |0 |0 |0 |1 |0 |0 |0 |0 |0 |
+ Route-Record |0 |0 |0 |0 |0 |0 |0+ |0 |0+ |0 |0+ |0 |
+ Session-Binding |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Session-Id |0 |0 |0 |0 |0 |0 |1 |1 |1 |1 |1 |1 |
+ Session-Server- |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Failover | | | | | | | | | | | | |
+ Session-Timeout |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Supported-Vendor-Id |0+ |0+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Termination-Cause |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |1 |0 |
+ User-Name |0 |0 |0 |0 |0 |0 |0-1|0-1|0-1|0-1|0-1|0-1|
+ Vendor-Id |1 |1 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Vendor-Specific- |0+ |0+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Application-Id | | | | | | | | | | | | |
+ --------------------+---+---+---+---+---+---+---+---+---+---+---+---+
+
+10.2. Accounting AVP Table
+
+ The table in this section is used to represent which AVPs defined in
+ this document are to be present in the Accounting messages. These
+ AVP occurrence requirements are guidelines, which may be expanded,
+ and/or overridden by application-specific requirements in the
+ Diameter applications documents.
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 138]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ +-----------+
+ | Command |
+ | Code |
+ +-----+-----+
+ Attribute Name | ACR | ACA |
+ ------------------------------+-----+-----+
+ Acct-Interim-Interval | 0-1 | 0-1 |
+ Acct-Multi-Session-Id | 0-1 | 0-1 |
+ Accounting-Record-Number | 1 | 1 |
+ Accounting-Record-Type | 1 | 1 |
+ Acct-Session-Id | 0-1 | 0-1 |
+ Accounting-Sub-Session-Id | 0-1 | 0-1 |
+ Accounting-Realtime-Required | 0-1 | 0-1 |
+ Acct-Application-Id | 0-1 | 0-1 |
+ Auth-Application-Id | 0 | 0 |
+ Class | 0+ | 0+ |
+ Destination-Host | 0-1 | 0 |
+ Destination-Realm | 1 | 0 |
+ Error-Reporting-Host | 0 | 0+ |
+ Event-Timestamp | 0-1 | 0-1 |
+ Origin-Host | 1 | 1 |
+ Origin-Realm | 1 | 1 |
+ Proxy-Info | 0+ | 0+ |
+ Route-Record | 0+ | 0 |
+ Result-Code | 0 | 1 |
+ Session-Id | 1 | 1 |
+ Termination-Cause | 0 | 0 |
+ User-Name | 0-1 | 0-1 |
+ Vendor-Specific-Application-Id| 0-1 | 0-1 |
+ ------------------------------+-----+-----+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 139]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+11. IANA Considerations
+
+ This section provides guidance to the Internet Assigned Numbers
+ Authority (IANA) regarding registration of values related to the
+ Diameter protocol, in accordance with BCP 26 [RFC5226]. The policies
+ and procedures for the IANA put in place by [RFC3588] applies here.
+ The criteria used by the IANA for assignment of numbers within this
+ namespace remains the same unless otherwise stated in this section.
+ Existing assignments remains the same unless explicitly updated or
+ deprecated in this secion.
+
+11.1. Changes to AVP Header Allocation
+
+ For AVP Headers, the only change is the AVP code block allocations.
+ Block allocation (release of more than 3 at a time for a given
+ purpose) now only require IETF Review as opposed to an IETF
+ Consensus.
+
+11.2. Diameter Header
+
+ For the Diameter Header, the command code namespace allocation has
+ changed. The new allocation rules are as follows:
+
+ The command code values 256 - 8,388,607 (0x100 to 0x7fffff) are
+ for permanent, standard commands, allocated by IETF Review
+ [RFC5226].
+
+ The values 8,388,608 - 16,777,213 (0x800000 - 0xfffffd) are
+ reserved for vendor-specific command codes, to be allocated on a
+ First Come, First Served basis by IANA [RFC5226]. The request to
+ IANA for a Vendor-Specific Command Code SHOULD include a reference
+ to a publicly available specification which documents the command
+ in sufficient detail to aid in interoperability between
+ independent implementations. If the specification cannot be made
+ publicly available, the request for a vendor-specific command code
+ MUST include the contact information of persons and/or entities
+ responsible for authoring and maintaining the command.
+
+11.3. AVP Values
+
+ For AVP values, the Experimental-Result-Code AVP value allocation has
+ been added. The new rule is as follows:
+
+11.3.1. Experimental-Result-Code AVP
+
+ Values for this AVP are purely local to the indicated vendor, and no
+ IANA registry is maintained for them.
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 140]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+11.4. Diameter TCP, SCTP, TLS/TCP and DTLS/SCTP Port Numbers
+
+ Updated port number assignments are described in this section. The
+ IANA has assigned port number 3868 for TCP and SCTP. The port number
+ [TBD] has been assigned for TLS/TCP and DTLS/SCTP.
+
+11.5. S-NAPTR Parameters
+
+ This document registers a new S-NAPTR Application Service Tag value
+ of "aaa".
+
+ This document also registers the following S-NAPTR Application
+ Protocol Tags:
+
+ Tag | Protocol
+ -------------------|---------
+ diameter.tcp | TCP
+ diameter.sctp | SCTP
+ diameter.tls.tcp | TLS/TCP
+ diameter.dtls.sctp | DTLS/SCTP
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 141]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+12. Diameter protocol related configurable parameters
+
+ This section contains the configurable parameters that are found
+ throughout this document:
+
+ Diameter Peer
+
+ A Diameter entity MAY communicate with peers that are statically
+ configured. A statically configured Diameter peer would require
+ that either the IP address or the fully qualified domain name
+ (FQDN) be supplied, which would then be used to resolve through
+ DNS.
+
+ Routing Table
+
+ A Diameter proxy server routes messages based on the realm portion
+ of a Network Access Identifier (NAI). The server MUST have a
+ table of Realm Names, and the address of the peer to which the
+ message must be forwarded to. The routing table MAY also include
+ a "default route", which is typically used for all messages that
+ cannot be locally processed.
+
+ Tc timer
+
+ The Tc timer controls the frequency that transport connection
+ attempts are done to a peer with whom no active transport
+ connection exists. The recommended value is 30 seconds.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 142]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+13. Security Considerations
+
+ The Diameter base protocol messages SHOULD be secured by using TLS
+ [RFC5246] or DTLS/SCTP [RFC6083]. Additional security mechanisms
+ such as IPsec [RFC4301] MAY also be deployed to secure connections
+ between peers. However, all Diameter base protocol implementations
+ MUST support the use of TLS/TCP and DTLS/SCTP and the Diameter
+ protocol MUST NOT be used without any security mechanism.
+
+ If a Diameter connection is to be protected via TLS/TCP and DTLS/SCTP
+ or IPsec, then TLS/TCP and DTLS/SCTP or IPsec/IKE SHOULD begin prior
+ to any Diameter message exchange. All security parameters for TLS/
+ TCP and DTLS/SCTP or IPsec are configured independent of the Diameter
+ protocol. All Diameter message will be sent through the TLS/TCP and
+ DTLS/SCTP or IPsec connection after a successful setup.
+
+ For TLS/TCP and DTLS/SCTP connections to be established in the open
+ state, the CER/CEA exchange MUST include an Inband-Security-ID AVP
+ with a value of TLS/TCP and DTLS/SCTP. The TLS/TCP and DTLS/SCTP
+ handshake will begin when both ends successfully reached the open
+ state, after completion of the CER/CEA exchange. If the TLS/TCP and
+ DTLS/SCTP handshake is successful, all further messages will be sent
+ via TLS/TCP and DTLS/SCTP. If the handshake fails, both ends move to
+ the closed state. See Sections 13.1 for more details.
+
+13.1. TLS/TCP and DTLS/SCTP Usage
+
+ Diameter nodes using TLS/TCP and DTLS/SCTP for security MUST mutually
+ authenticate as part of TLS/TCP and DTLS/SCTP session establishment.
+ In order to ensure mutual authentication, the Diameter node acting as
+ TLS/TCP and DTLS/SCTP server MUST request a certificate from the
+ Diameter node acting as TLS/TCP and DTLS/SCTP client, and the
+ Diameter node acting as TLS/TCP and DTLS/SCTP client MUST be prepared
+ to supply a certificate on request.
+
+ Diameter nodes MUST be able to negotiate the following TLS/TCP and
+ DTLS/SCTP cipher suites:
+
+ TLS_RSA_WITH_RC4_128_MD5
+ TLS_RSA_WITH_RC4_128_SHA
+ TLS_RSA_WITH_3DES_EDE_CBC_SHA
+
+ Diameter nodes SHOULD be able to negotiate the following TLS/TCP and
+ DTLS/SCTP cipher suite:
+
+ TLS_RSA_WITH_AES_128_CBC_SHA
+
+ Diameter nodes MAY negotiate other TLS/TCP and DTLS/SCTP cipher
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 143]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ suites.
+
+13.2. Peer-to-Peer Considerations
+
+ As with any peer-to-peer protocol, proper configuration of the trust
+ model within a Diameter peer is essential to security. When
+ certificates are used, it is necessary to configure the root
+ certificate authorities trusted by the Diameter peer. These root CAs
+ are likely to be unique to Diameter usage and distinct from the root
+ CAs that might be trusted for other purposes such as Web browsing.
+ In general, it is expected that those root CAs will be configured so
+ as to reflect the business relationships between the organization
+ hosting the Diameter peer and other organizations. As a result, a
+ Diameter peer will typically not be configured to allow connectivity
+ with any arbitrary peer. With certificate authentication, Diameter
+ peers may not be known beforehand and therefore peer discovery may be
+ required.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 144]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+14. References
+
+14.1. Normative References
+
+ [FLOATPOINT]
+ Institute of Electrical and Electronics Engineers, "IEEE
+ Standard for Binary Floating-Point Arithmetic, ANSI/IEEE
+ Standard 754-1985", August 1985.
+
+ [IANAADFAM]
+ IANA,, "Address Family Numbers",
+ http://www.iana.org/assignments/address-family-numbers.
+
+ [RADTYPE] IANA,, "RADIUS Types",
+ http://www.iana.org/assignments/radius-types.
+
+ [RFC791] Postel, J., "Internet Protocol", RFC 791, September 1981.
+
+ [RFC793] Postel, J., "Transmission Control Protocol", RFC 793,
+ January 1981.
+
+ [RFC3539] Aboba, B. and J. Wood, "Authentication, Authorization and
+ Accounting (AAA) Transport Profile", RFC 3539, June 2003.
+
+ [RFC4004] Calhoun, P., Johansson, T., Perkins, C., Hiller, T., and
+ P. McCann, "Diameter Mobile IPv4 Application", RFC 4004,
+ August 2005.
+
+ [RFC4005] Calhoun, P., Zorn, G., Spence, D., and D. Mitton,
+ "Diameter Network Access Server Application", RFC 4005,
+ August 2005.
+
+ [RFC4006] Hakala, H., Mattila, L., Koskinen, J-P., Stura, M., and J.
+ Loughney, "Diameter Credit-Control Application", RFC 4006,
+ August 2005.
+
+ [RFC5234] Crocker, D. and P. Overell, "Augmented BNF for Syntax
+ Specifications: ABNF", STD 68, RFC 5234, January 2008.
+
+ [RFC3588] Calhoun, P., Loughney, J., Guttman, E., Zorn, G., and J.
+ Arkko, "Diameter Base Protocol", RFC 3588, September 2003.
+
+ [RFC5226] Narten, T. and H. Alvestrand, "Guidelines for Writing an
+ IANA Considerations Section in RFCs", BCP 26, RFC 5226,
+ May 2008.
+
+ [RFC4291] Hinden, R. and S. Deering, "IP Version 6 Addressing
+ Architecture", RFC 4291, February 2006.
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 145]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC4282] Aboba, B., Beadles, M., Arkko, J., and P. Eronen, "The
+ Network Access Identifier", RFC 4282, December 2005.
+
+ [RFC4086] Eastlake, D., Schiller, J., and S. Crocker, "Randomness
+ Requirements for Security", BCP 106, RFC 4086, June 2005.
+
+ [RFC4960] Stewart, R., "Stream Control Transmission Protocol",
+ RFC 4960, September 2007.
+
+ [RFC3958] Daigle, L. and A. Newton, "Domain-Based Application
+ Service Location Using SRV RRs and the Dynamic Delegation
+ Discovery Service (DDDS)", RFC 3958, January 2005.
+
+ [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security
+ (TLS) Protocol Version 1.2", RFC 5246, August 2008.
+
+ [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
+ Resource Identifier (URI): Generic Syntax", STD 66,
+ RFC 3986, January 2005.
+
+ [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", STD 63, RFC 3629, November 2003.
+
+ [RFC5890] Klensin, J., "Internationalized Domain Names for
+ Applications (IDNA): Definitions and Document Framework",
+ RFC 5890, August 2010.
+
+ [RFC5891] Klensin, J., "Internationalized Domain Names in
+ Applications (IDNA): Protocol", RFC 5891, August 2010.
+
+ [RFC3492] Costello, A., "Punycode: A Bootstring encoding of Unicode
+ for Internationalized Domain Names in Applications
+ (IDNA)", RFC 3492, March 2003.
+
+ [RFC5729] Korhonen, J., Jones, M., Morand, L., and T. Tsou,
+ "Clarifications on the Routing of Diameter Requests Based
+ on the Username and the Realm", RFC 5729, December 2009.
+
+ [RFC4347] Rescorla, E. and N. Modadugu, "Datagram Transport Layer
+ Security", RFC 4347, April 2006.
+
+ [RFC6083] Tuexen, M., Seggelmann, R., and E. Rescorla, "Datagram
+ Transport Layer Security (DTLS) for Stream Control
+ Transmission Protocol (SCTP)", RFC 6083, January 2011.
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 146]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+14.2. Informational References
+
+ [RFC2989] Aboba, B., Calhoun, P., Glass, S., Hiller, T., McCann, P.,
+ Shiino, H., Walsh, P., Zorn, G., Dommety, G., Perkins, C.,
+ Patil, B., Mitton, D., Manning, S., Beadles, M., Chen, X.,
+ Sivalingham, S., Hameed, A., Munson, M., Jacobs, S., Lim,
+ B., Hirschman, B., Hsu, R., Koo, H., Lipford, M.,
+ Campbell, E., Xu, Y., Baba, S., and E. Jaques, "Criteria
+ for Evaluating AAA Protocols for Network Access",
+ RFC 2989, November 2000.
+
+ [RFC2975] Aboba, B., Arkko, J., and D. Harrington, "Introduction to
+ Accounting Management", RFC 2975, October 2000.
+
+ [RFC3232] Reynolds, J., "Assigned Numbers: RFC 1700 is Replaced by
+ an On-line Database", RFC 3232, January 2002.
+
+ [RFC5176] Chiba, M., Dommety, G., Eklund, M., Mitton, D., and B.
+ Aboba, "Dynamic Authorization Extensions to Remote
+ Authentication Dial In User Service (RADIUS)", RFC 5176,
+ January 2008.
+
+ [RFC1661] Simpson, W., "The Point-to-Point Protocol (PPP)", STD 51,
+ RFC 1661, July 1994.
+
+ [RFC2866] Rigney, C., "RADIUS Accounting", RFC 2866, June 2000.
+
+ [RFC2869] Rigney, C., Willats, W., and P. Calhoun, "RADIUS
+ Extensions", RFC 2869, June 2000.
+
+ [RFC2865] Rigney, C., Willens, S., Rubens, A., and W. Simpson,
+ "Remote Authentication Dial In User Service (RADIUS)",
+ RFC 2865, June 2000.
+
+ [RFC3162] Aboba, B., Zorn, G., and D. Mitton, "RADIUS and IPv6",
+ RFC 3162, August 2001.
+
+ [RFC4301] Kent, S. and K. Seo, "Security Architecture for the
+ Internet Protocol", RFC 4301, December 2005.
+
+ [RFC5905] Mills, D., Martin, J., Burbank, J., and W. Kasch, "Network
+ Time Protocol Version 4: Protocol and Algorithms
+ Specification", RFC 5905, June 2010.
+
+ [RFC1492] Finseth, C., "An Access Control Protocol, Sometimes Called
+ TACACS", RFC 1492, July 1993.
+
+ [RFC4690] Klensin, J., Faltstrom, P., Karp, C., and IAB, "Review and
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 147]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ Recommendations for Internationalized Domain Names
+ (IDNs)", RFC 4690, September 2006.
+
+ [RFC5461] Gont, F., "TCP's Reaction to Soft Errors", RFC 5461,
+ February 2009.
+
+ [RFC5927] Gont, F., "ICMP Attacks against TCP", RFC 5927, July 2010.
+
+ [RFC3692] Narten, T., "Assigning Experimental and Testing Numbers
+ Considered Useful", BCP 82, RFC 3692, January 2004.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 148]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+Appendix A. Acknowledgements
+
+A.1. RFC3588bis
+
+ The authors would like to thank the following people that have
+ provided proposals and contributions to this document:
+
+ To Vishnu Ram and Satendra Gera for their contributions on
+ Capabilities Updates, Predictive Loop Avoidance as well as many other
+ technical proposals. To Tolga Asveren for his insights and
+ contributions on almost all of the proposed solutions incorporated
+ into this document. To Timothy Smith for helping on the Capabilities
+ Updates and other topics. To Tony Zhang for providing fixes to loop
+ holes on composing Failed-AVPs as well as many other issues and
+ topics. To Jan Nordqvist for clearly stating the usage of
+ Application Ids. To Anders Kristensen for providing needed technical
+ opinions. To David Frascone for providing invaluable review of the
+ document. To Mark Jones for providing clarifying text on vendor
+ command codes and other vendor specific indicators.
+
+ Special thanks to the Diameter extensibility design team which helped
+ resolve the tricky question of mandatory AVPs and ABNF semantics.
+ The members of this team are as follows:
+
+ Avi Lior, Jari Arkko, Glen Zorn, Lionel Morand, Mark Jones, Tolga
+ Asveren Jouni Korhonen, Glenn McGregor.
+
+ Special thanks also to people who have provided invaluable comments
+ and inputs especially in resolving controversial issues:
+
+ Glen Zorn, Yoshihiro Ohba, Marco Stura, and Pasi Eronen.
+
+ Finally, we would like to thank the original authors of this
+ document:
+
+ Pat Calhoun, John Loughney, Jari Arkko, Erik Guttman and Glen Zorn.
+
+ Their invaluable knowledge and experience has given us a robust and
+ flexible AAA protocol that many people have seen great value in
+ adopting. We greatly appreciate their support and stewardship for
+ the continued improvements of Diameter as a protocol. We would also
+ like to extend our gratitude to folks aside from the authors who have
+ assisted and contributed to the original version of this document.
+ Their efforts significantly contributed to the success of Diameter.
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 149]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+A.2. RFC3588
+
+ The authors would like to thank Nenad Trifunovic, Tony Johansson and
+ Pankaj Patel for their participation in the pre-IETF Document Reading
+ Party. Allison Mankin, Jonathan Wood and Bernard Aboba provided
+ invaluable assistance in working out transport issues, and similarly
+ with Steven Bellovin in the security area.
+
+ Paul Funk and David Mitton were instrumental in getting the Peer
+ State Machine correct, and our deep thanks go to them for their time.
+
+ Text in this document was also provided by Paul Funk, Mark Eklund,
+ Mark Jones and Dave Spence. Jacques Caron provided many great
+ comments as a result of a thorough review of the spec.
+
+ The authors would also like to acknowledge the following people for
+ their contribution in the development of the Diameter protocol:
+
+ Allan C. Rubens, Haseeb Akhtar, William Bulley, Stephen Farrell,
+ David Frascone, Daniel C. Fox, Lol Grant, Ignacio Goyret, Nancy
+ Greene, Peter Heitman, Fredrik Johansson, Mark Jones, Martin Julien,
+ Bob Kopacz, Paul Krumviede, Fergal Ladley, Ryan Moats, Victor Muslin,
+ Kenneth Peirce, John Schnizlein, Sumit Vakil, John R. Vollbrecht and
+ Jeff Weisberg.
+
+ Finally, Pat Calhoun would like to thank Sun Microsystems since most
+ of the effort put into this document was done while he was in their
+ employ.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 150]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+Appendix B. S-NAPTR Example
+
+ As an example, consider a client that wishes to resolve aaa:
+ example1.com. The client performs a NAPTR query for that domain, and
+ the following NAPTR records are returned:
+
+ ;; order pref flags service regexp replacement
+ IN NAPTR 50 50 "s" "aaa:diameter.tls.tcp" ""
+ _diameter._tls.example1.com
+ IN NAPTR 100 50 "s" "aaa:diameter.tcp" ""
+ _aaa._tcp.example1.com
+ IN NAPTR 150 50 "s" "aaa:diameter.sctp" ""
+ _diameter._sctp.example1.com
+
+ This indicates that the server supports TLS, TCP and SCTP in that
+ order. If the client supports TLS, TLS will be used, targeted to a
+ host determined by an SRV lookup of _diameter._tls.example1.com.
+ That lookup would return:
+
+ ;; Priority Weight Port Target
+ IN SRV 0 1 5060 server1.example1.com
+ IN SRV 0 2 5060 server2.example1.com
+
+ As an alternative example, a client that wishes to resolve aaa:
+ example2.com. The client performs a NAPTR query for that domain, and
+ the following NAPTR records are returned:
+
+ ;; order pref flags service regexp replacement
+ IN NAPTR 150 50 "a" "aaa:diameter.tls.tcp" ""
+ server1.example2.com
+ IN NAPTR 150 50 "a" "aaa:diameter.tls.tcp" ""
+ server2.example2.com
+
+ This indicates that the server supports TCP available at the returned
+ host names.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 151]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+Appendix C. Duplicate Detection
+
+ As described in Section 9.4, accounting record duplicate detection is
+ based on session identifiers. Duplicates can appear for various
+ reasons:
+
+ o Failover to an alternate server. Where close to real-time
+ performance is required, failover thresholds need to be kept low
+ and this may lead to an increased likelihood of duplicates.
+ Failover can occur at the client or within Diameter agents.
+
+ o Failure of a client or agent after sending of a record from non-
+ volatile memory, but prior to receipt of an application layer ACK
+ and deletion of the record. record to be sent. This will result
+ in retransmission of the record soon after the client or agent has
+ rebooted.
+
+ o Duplicates received from RADIUS gateways. Since the
+ retransmission behavior of RADIUS is not defined within [RFC2865],
+ the likelihood of duplication will vary according to the
+ implementation.
+
+ o Implementation problems and misconfiguration.
+
+ The T flag is used as an indication of an application layer
+ retransmission event, e.g., due to failover to an alternate server.
+ It is defined only for request messages sent by Diameter clients or
+ agents. For instance, after a reboot, a client may not know whether
+ it has already tried to send the accounting records in its non-
+ volatile memory before the reboot occurred. Diameter servers MAY use
+ the T flag as an aid when processing requests and detecting duplicate
+ messages. However, servers that do this MUST ensure that duplicates
+ are found even when the first transmitted request arrives at the
+ server after the retransmitted request. It can be used only in cases
+ where no answer has been received from the Server for a request and
+ the request is sent again, (e.g., due to a failover to an alternate
+ peer, due to a recovered primary peer or due to a client re-sending a
+ stored record from non-volatile memory such as after reboot of a
+ client or agent).
+
+ In some cases the Diameter accounting server can delay the duplicate
+ detection and accounting record processing until a post-processing
+ phase takes place. At that time records are likely to be sorted
+ according to the included User-Name and duplicate elimination is easy
+ in this case. In other situations it may be necessary to perform
+ real-time duplicate detection, such as when credit limits are imposed
+ or real-time fraud detection is desired.
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 152]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+ In general, only generation of duplicates due to failover or re-
+ sending of records in non-volatile storage can be reliably detected
+ by Diameter clients or agents. In such cases the Diameter client or
+ agents can mark the message as possible duplicate by setting the T
+ flag. Since the Diameter server is responsible for duplicate
+ detection, it can choose to make use of the T flag or not, in order
+ to optimize duplicate detection. Since the T flag does not affect
+ interoperability, and may not be needed by some servers, generation
+ of the T flag is REQUIRED for Diameter clients and agents, but MAY be
+ implemented by Diameter servers.
+
+ As an example, it can be usually be assumed that duplicates appear
+ within a time window of longest recorded network partition or device
+ fault, perhaps a day. So only records within this time window need
+ to be looked at in the backward direction. Secondly, hashing
+ techniques or other schemes, such as the use of the T flag in the
+ received messages, may be used to eliminate the need to do a full
+ search even in this set except for rare cases.
+
+ The following is an example of how the T flag may be used by the
+ server to detect duplicate requests.
+
+
+ A Diameter server MAY check the T flag of the received message to
+ determine if the record is a possible duplicate. If the T flag is
+ set in the request message, the server searches for a duplicate
+ within a configurable duplication time window backward and
+ forward. This limits database searching to those records where
+ the T flag is set. In a well run network, network partitions and
+ device faults will presumably be rare events, so this approach
+ represents a substantial optimization of the duplicate detection
+ process. During failover, it is possible for the original record
+ to be received after the T flag marked record, due to differences
+ in network delays experienced along the path by the original and
+ duplicate transmissions. The likelihood of this occurring
+ increases as the failover interval is decreased. In order to be
+ able to detect out of order duplicates, the Diameter server should
+ use backward and forward time windows when performing duplicate
+ checking for the T flag marked request. For example, in order to
+ allow time for the original record to exit the network and be
+ recorded by the accounting server, the Diameter server can delay
+ processing records with the T flag set until a time period
+ TIME_WAIT + RECORD_PROCESSING_TIME has elapsed after the closing
+ of the original transport connection. After this time period has
+ expired, then it may check the T flag marked records against the
+ database with relative assurance that the original records, if
+ sent, have been received and recorded.
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 153]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+Appendix D. Internationalized Domain Names
+
+ To be compatible with the existing DNS infrastructure and simplify
+ host and domain name comparison, Diameter identities (FQDNs) are
+ represented in ASCII form. This allows the Diameter protocol to fall
+ in-line with the DNS strategy of being transparent from the effects
+ of Internationalized Domain Names (IDNs) by following the
+ recommendations in [RFC4690] and [RFC5890]. Applications that
+ provide support for IDNs outside of the Diameter protocol but
+ interacting with it SHOULD use the representation and conversion
+ framework described in [RFC5890], [RFC5891] and [RFC3492].
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 154]
+
+Internet-Draft Diameter Base Protocol January 2011
+
+
+Authors' Addresses
+
+ Victor Fajardo (editor)
+ Telcordia Technologies
+ One Telcordia Drive, 1S-222
+ Piscataway, NJ 08854
+ USA
+
+ Phone: +1-908-421-1845
+
+
+ Jari Arkko
+ Ericsson Research
+ 02420 Jorvas
+ Finland
+
+ Phone: +358 40 5079256
+
+
+ John Loughney
+ Nokia Research Center
+ 955 Page Mill Road
+ Palo Alto, CA 94304
+ US
+
+ Phone: +1-650-283-8068
+
+
+ Glenn Zorn
+ Network Zen
+ 1310 East Thomas Street
+ Seattle, WA 98102
+ US
+
+ Phone:
+
+
+
+
+
+
+
+
+
+
+
+
+Fajardo, et al. Expires July 24, 2011 [Page 155]
+
+
diff --git a/lib/diameter/doc/standard/rfc3124.txt b/lib/diameter/doc/standard/rfc3124.txt
new file mode 100644
index 0000000000..db57bc370f
--- /dev/null
+++ b/lib/diameter/doc/standard/rfc3124.txt
@@ -0,0 +1,1235 @@
+
+
+
+
+
+
+Network Working Group H. Balakrishnan
+Request for Comments: 3124 MIT LCS
+Category: Standards Track S. Seshan
+ CMU
+ June 2001
+
+
+ The Congestion Manager
+
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+Abstract
+
+ This document describes the Congestion Manager (CM), an end-system
+ module that:
+
+ (i) Enables an ensemble of multiple concurrent streams from a sender
+ destined to the same receiver and sharing the same congestion
+ properties to perform proper congestion avoidance and control, and
+
+ (ii) Allows applications to easily adapt to network congestion.
+
+1. Conventions used in this document:
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC-2119 [Bradner97].
+
+ STREAM
+
+ A group of packets that all share the same source and destination
+ IP address, IP type-of-service, transport protocol, and source and
+ destination transport-layer port numbers.
+
+
+
+
+
+
+
+Balakrishnan, et. al. Standards Track [Page 1]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+ MACROFLOW
+
+ A group of CM-enabled streams that all use the same congestion
+ management and scheduling algorithms, and share congestion state
+ information. Currently, streams destined to different receivers
+ belong to different macroflows. Streams destined to the same
+ receiver MAY belong to different macroflows. When the Congestion
+ Manager is in use, streams that experience identical congestion
+ behavior and use the same congestion control algorithm SHOULD
+ belong to the same macroflow.
+
+ APPLICATION
+
+ Any software module that uses the CM. This includes user-level
+ applications such as Web servers or audio/video servers, as well
+ as in-kernel protocols such as TCP [Postel81] that use the CM for
+ congestion control.
+
+ WELL-BEHAVED APPLICATION
+
+ An application that only transmits when allowed by the CM and
+ accurately accounts for all data that it has sent to the receiver
+ by informing the CM using the CM API.
+
+ PATH MAXIMUM TRANSMISSION UNIT (PMTU)
+
+ The size of the largest packet that the sender can transmit
+ without it being fragmented en route to the receiver. It includes
+ the sizes of all headers and data except the IP header.
+
+ CONGESTION WINDOW (cwnd)
+
+ A CM state variable that modulates the amount of outstanding data
+ between sender and receiver.
+
+ OUTSTANDING WINDOW (ownd)
+
+ The number of bytes that has been transmitted by the source, but
+ not known to have been either received by the destination or lost
+ in the network.
+
+ INITIAL WINDOW (IW)
+
+ The size of the sender's congestion window at the beginning of a
+ macroflow.
+
+
+
+
+
+
+Balakrishnan, et. al. Standards Track [Page 2]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+ DATA TYPE SYNTAX
+
+ We use "u64" for unsigned 64-bit, "u32" for unsigned 32-bit, "u16"
+ for unsigned 16-bit, "u8" for unsigned 8-bit, "i32" for signed
+ 32-bit, "i16" for signed 16-bit quantities, "float" for IEEE
+ floating point values. The type "void" is used to indicate that
+ no return value is expected from a call. Pointers are referred to
+ using "*" syntax, following C language convention.
+
+ We emphasize that all the API functions described in this document
+ are "abstract" calls and that conformant CM implementations may
+ differ in specific implementation details.
+
+2. Introduction
+
+ The framework described in this document integrates congestion
+ management across all applications and transport protocols. The CM
+ maintains congestion parameters (available aggregate and per-stream
+ bandwidth, per-receiver round-trip times, etc.) and exports an API
+ that enables applications to learn about network characteristics,
+ pass information to the CM, share congestion information with each
+ other, and schedule data transmissions. This document focuses on
+ applications and transport protocols with their own independent per-
+ byte or per-packet sequence number information, and does not require
+ modifications to the receiver protocol stack. However, the receiving
+ application must provide feedback to the sending application about
+ received packets and losses, and the latter is expected to use the CM
+ API to update CM state. This document does not address networks with
+ reservations or service differentiation.
+
+ The CM is an end-system module that enables an ensemble of multiple
+ concurrent streams to perform stable congestion avoidance and
+ control, and allows applications to easily adapt their transmissions
+ to prevailing network conditions. It integrates congestion
+ management across all applications and transport protocols. It
+ maintains congestion parameters (available aggregate and per-stream
+ bandwidth, per-receiver round-trip times, etc.) and exports an API
+ that enables applications to learn about network characteristics,
+ pass information to the CM, share congestion information with each
+ other, and schedule data transmissions. When the CM is used, all
+ data transmissions subject to the CM must be done with the explicit
+ consent of the CM via this API to ensure proper congestion behavior.
+
+ Systems MAY choose to use CM, and if so they MUST follow this
+ specification.
+
+ This document focuses on applications and networks where the
+ following conditions hold:
+
+
+
+Balakrishnan, et. al. Standards Track [Page 3]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+ 1. Applications are well-behaved with their own independent
+ per-byte or per-packet sequence number information, and use the
+ CM API to update internal state in the CM.
+
+ 2. Networks are best-effort without service discrimination or
+ reservations. In particular, it does not address situations
+ where different streams between the same pair of hosts traverse
+ paths with differing characteristics.
+
+ The Congestion Manager framework can be extended to support
+ applications that do not provide their own feedback and to
+ differentially-served networks. These extensions will be addressed
+ in later documents.
+
+ The CM is motivated by two main goals:
+
+ (i) Enable efficient multiplexing. Increasingly, the trend on the
+ Internet is for unicast data senders (e.g., Web servers) to transmit
+ heterogeneous types of data to receivers, ranging from unreliable
+ real-time streaming content to reliable Web pages and applets. As a
+ result, many logically different streams share the same path between
+ sender and receiver. For the Internet to remain stable, each of
+ these streams must incorporate control protocols that safely probe
+ for spare bandwidth and react to congestion. Unfortunately, these
+ concurrent streams typically compete with each other for network
+ resources, rather than share them effectively. Furthermore, they do
+ not learn from each other about the state of the network. Even if
+ they each independently implement congestion control (e.g., a group
+ of TCP connections each implementing the algorithms in [Jacobson88,
+ Allman99]), the ensemble of streams tends to be more aggressive in
+ the face of congestion than a single TCP connection implementing
+ standard TCP congestion control and avoidance [Balakrishnan98].
+
+ (ii) Enable application adaptation to congestion. Increasingly,
+ popular real-time streaming applications run over UDP using their own
+ user-level transport protocols for good application performance, but
+ in most cases today do not adapt or react properly to network
+ congestion. By implementing a stable control algorithm and exposing
+ an adaptation API, the CM enables easy application adaptation to
+ congestion. Applications adapt the data they transmit to the current
+ network conditions.
+
+ The CM framework builds on recent work on TCP control block sharing
+ [Touch97], integrated TCP congestion control (TCP-Int)
+ [Balakrishnan98] and TCP sessions [Padmanabhan98]. [Touch97]
+ advocates the sharing of some of the state in the TCP control block
+ to improve transient transport performance and describes sharing
+ across an ensemble of TCP connections. [Balakrishnan98],
+
+
+
+Balakrishnan, et. al. Standards Track [Page 4]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+ [Padmanabhan98], and [Eggert00] describe several experiments that
+ quantify the benefits of sharing congestion state, including improved
+ stability in the face of congestion and better loss recovery.
+ Integrating loss recovery across concurrent connections significantly
+ improves performance because losses on one connection can be detected
+ by noticing that later data sent on another connection has been
+ received and acknowledged. The CM framework extends these ideas in
+ two significant ways: (i) it extends congestion management to non-TCP
+ streams, which are becoming increasingly common and often do not
+ implement proper congestion management, and (ii) it provides an API
+ for applications to adapt their transmissions to current network
+ conditions. For an extended discussion of the motivation for the CM,
+ its architecture, API, and algorithms, see [Balakrishnan99]; for a
+ description of an implementation and performance results, see
+ [Andersen00].
+
+ The resulting end-host protocol architecture at the sender is shown
+ in Figure 1. The CM helps achieve network stability by implementing
+ stable congestion avoidance and control algorithms that are "TCP-
+ friendly" [Mahdavi98] based on algorithms described in [Allman99].
+ However, it does not attempt to enforce proper congestion behavior
+ for all applications (but it does not preclude a policer on the host
+ that performs this task). Note that while the policer at the end-
+ host can use CM, the network has to be protected against compromises
+ to the CM and the policer at the end hosts, a task that requires
+ router machinery [Floyd99a]. We do not address this issue further in
+ this document.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Balakrishnan, et. al. Standards Track [Page 5]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+ |--------| |--------| |--------| |--------| |--------------|
+ | HTTP | | FTP | | RTP 1 | | RTP 2 | | |
+ |--------| |--------| |--------| |--------| | |
+ | | | ^ | ^ | |
+ | | | | | | | Scheduler |
+ | | | | | | |---| | |
+ | | | |-------|--+->| | | |
+ | | | | | |<--| |
+ v v v v | | |--------------|
+ |--------| |--------| |-------------| | | ^
+ | TCP 1 | | TCP 2 | | UDP 1 | | A | |
+ |--------| |--------| |-------------| | | |
+ ^ | ^ | | | | |--------------|
+ | | | | | | P |-->| |
+ | | | | | | | | |
+ |---|------+---|--------------|------->| | | Congestion |
+ | | | | I | | |
+ v v v | | | Controller |
+ |-----------------------------------| | | | |
+ | IP |-->| | | |
+ |-----------------------------------| | | |--------------|
+ |---|
+
+ Figure 1
+
+ The key components of the CM framework are (i) the API, (ii) the
+ congestion controller, and (iii) the scheduler. The API is (in part)
+ motivated by the requirements of application-level framing (ALF)
+ [Clark90], and is described in Section 4. The CM internals (Section
+ 5) include a congestion controller (Section 5.1) and a scheduler to
+ orchestrate data transmissions between concurrent streams in a
+ macroflow (Section 5.2). The congestion controller adjusts the
+ aggregate transmission rate between sender and receiver based on its
+ estimate of congestion in the network. It obtains feedback about its
+ past transmissions from applications themselves via the API. The
+ scheduler apportions available bandwidth amongst the different
+ streams within each macroflow and notifies applications when they are
+ permitted to send data. This document focuses on well-behaved
+ applications; a future one will describe the sender-receiver protocol
+ and header formats that will handle applications that do not
+ incorporate their own feedback to the CM.
+
+3. CM API
+
+ By convention, the IETF does not treat Application Programming
+ Interfaces as standards track. However, it is considered important
+ to have the CM API and CM algorithm requirements in one coherent
+ document. The following section on the CM API uses the terms MUST,
+
+
+
+Balakrishnan, et. al. Standards Track [Page 6]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+ SHOULD, etc., but the terms are meant to apply within the context of
+ an implementation of the CM API. The section does not apply to
+ congestion control implementations in general, only to those
+ implementations offering the CM API.
+
+ Using the CM API, streams can determine their share of the available
+ bandwidth, request and have their data transmissions scheduled,
+ inform the CM about successful transmissions, and be informed when
+ the CM's estimate of path bandwidth changes. Thus, the CM frees
+ applications from having to maintain information about the state of
+ congestion and available bandwidth along any path.
+
+ The function prototypes below follow standard C language convention.
+ We emphasize that these API functions are abstract calls and
+ conformant CM implementations may differ in specific details, as long
+ as equivalent functionality is provided.
+
+ When a new stream is created by an application, it passes some
+ information to the CM via the cm_open(stream_info) API call.
+ Currently, stream_info consists of the following information: (i) the
+ source IP address, (ii) the source port, (iii) the destination IP
+ address, (iv) the destination port, and (v) the IP protocol number.
+
+3.1 State maintenance
+
+ 1. Open: All applications MUST call cm_open(stream_info) before
+ using the CM API. This returns a handle, cm_streamid, for the
+ application to use for all further CM API invocations for that
+ stream. If the returned cm_streamid is -1, then the cm_open()
+ failed and that stream cannot use the CM.
+
+ All other calls to the CM for a stream use the cm_streamid
+ returned from the cm_open() call.
+
+ 2. Close: When a stream terminates, the application SHOULD invoke
+ cm_close(cm_streamid) to inform the CM about the termination
+ of the stream.
+
+ 3. Packet size: cm_mtu(cm_streamid) returns the estimated PMTU of
+ the path between sender and receiver. Internally, this
+ information SHOULD be obtained via path MTU discovery
+ [Mogul90]. It MAY be statically configured in the absence of
+ such a mechanism.
+
+
+
+
+
+
+
+
+Balakrishnan, et. al. Standards Track [Page 7]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+3.2 Data transmission
+
+ The CM accommodates two types of adaptive senders, enabling
+ applications to dynamically adapt their content based on prevailing
+ network conditions, and supporting ALF-based applications.
+
+ 1. Callback-based transmission. The callback-based transmission API
+ puts the stream in firm control of deciding what to transmit at each
+ point in time. To achieve this, the CM does not buffer any data;
+ instead, it allows streams the opportunity to adapt to unexpected
+ network changes at the last possible instant. Thus, this enables
+ streams to "pull out" and repacketize data upon learning about any
+ rate change, which is hard to do once the data has been buffered.
+ The CM must implement a cm_request(i32 cm_streamid) call for streams
+ wishing to send data in this style. After some time, depending on
+ the rate, the CM MUST invoke a callback using cmapp_send(), which is
+ a grant for the stream to send up to PMTU bytes. The callback-style
+ API is the recommended choice for ALF-based streams. Note that
+ cm_request() does not take the number of bytes or MTU-sized units as
+ an argument; each call to cm_request() is an implicit request for
+ sending up to PMTU bytes. The CM MAY provide an alternate interface,
+ cm_request(int k). The cmapp_send callback for this request is
+ granted the right to send up to k PMTU sized segments. Section 4.3
+ discusses the time duration for which the transmission grant is
+ valid, while Section 5.2 describes how these requests are scheduled
+ and callbacks made.
+
+ 2. Synchronous-style. The above callback-based API accommodates a
+ class of ALF streams that are "asynchronous." Asynchronous
+ transmitters do not transmit based on a periodic clock, but do so
+ triggered by asynchronous events like file reads or captured frames.
+ On the other hand, there are many streams that are "synchronous"
+ transmitters, which transmit periodically based on their own internal
+ timers (e.g., an audio senders that sends at a constant sampling
+ rate). While CM callbacks could be configured to periodically
+ interrupt such transmitters, the transmit loop of such applications
+ is less affected if they retain their original timer-based loop. In
+ addition, it complicates the CM API to have a stream express the
+ periodicity and granularity of its callbacks. Thus, the CM MUST
+ export an API that allows such streams to be informed of changes in
+ rates using the cmapp_update(u64 newrate, u32 srtt, u32 rttdev)
+ callback function, where newrate is the new rate in bits per second
+ for this stream, srtt is the current smoothed round trip time
+ estimate in microseconds, and rttdev is the smoothed linear deviation
+ in the round-trip time estimate calculated using the same algorithm
+ as in TCP [Paxson00]. The newrate value reports an instantaneous
+ rate calculated, for example, by taking the ratio of cwnd and srtt,
+ and dividing by the fraction of that ratio allocated to the stream.
+
+
+
+Balakrishnan, et. al. Standards Track [Page 8]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+ In response, the stream MUST adapt its packet size or change its
+ timer interval to conform to (i.e., not exceed) the allowed rate. Of
+ course, it may choose not to use all of this rate. Note that the CM
+ is not on the data path of the actual transmission.
+
+ To avoid unnecessary cmapp_update() callbacks that the application
+ will only ignore, the CM MUST provide a cm_thresh(float
+ rate_downthresh, float rate_upthresh, float rtt_downthresh, float
+ rtt_upthresh) function that a stream can use at any stage in its
+ execution. In response, the CM SHOULD invoke the callback only when
+ the rate decreases to less than (rate_downthresh * lastrate) or
+ increases to more than (rate_upthresh * lastrate), where lastrate is
+ the rate last notified to the stream, or when the round-trip time
+ changes correspondingly by the requisite thresholds. This
+ information is used as a hint by the CM, in the sense the
+ cmapp_update() can be called even if these conditions are not met.
+
+ The CM MUST implement a cm_query(i32 cm_streamid, u64* rate, u32*
+ srtt, u32* rttdev) to allow an application to query the current CM
+ state. This sets the rate variable to the current rate estimate in
+ bits per second, the srtt variable to the current smoothed round-trip
+ time estimate in microseconds, and rttdev to the mean linear
+ deviation. If the CM does not have valid estimates for the
+ macroflow, it fills in negative values for the rate, srtt, and
+ rttdev.
+
+ Note that a stream can use more than one of the above transmission
+ APIs at the same time. In particular, the knowledge of sustainable
+ rate is useful for asynchronous streams as well as synchronous ones;
+ e.g., an asynchronous Web server disseminating images using TCP may
+ use cmapp_send() to schedule its transmissions and cmapp_update() to
+ decide whether to send a low-resolution or high-resolution image. A
+ TCP implementation using the CM is described in Section 6.1.1, where
+ the benefit of the cm_request() callback API for TCP will become
+ apparent.
+
+ The reader will notice that the basic CM API does not provide an
+ interface for buffered congestion-controlled transmissions. This is
+ intentional, since this transmission mode can be implemented using
+ the callback-based primitive. Section 6.1.2 describes how
+ congestion-controlled UDP sockets may be implemented using the CM
+ API.
+
+3.3 Application notification
+
+ When a stream receives feedback from receivers, it MUST use
+ cm_update(i32 cm_streamid, u32 nrecd, u32 nlost, u8 lossmode, i32
+ rtt) to inform the CM about events such as congestion losses,
+
+
+
+Balakrishnan, et. al. Standards Track [Page 9]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+ successful receptions, type of loss (timeout event, Explicit
+ Congestion Notification [Ramakrishnan99], etc.) and round-trip time
+ samples. The nrecd parameter indicates how many bytes were
+ successfully received by the receiver since the last cm_update call,
+ while the nrecd parameter identifies how many bytes were received
+ were lost during the same time period. The rtt value indicates the
+ round-trip time measured during the transmission of these bytes. The
+ rtt value must be set to -1 if no valid round-trip sample was
+ obtained by the application. The lossmode parameter provides an
+ indicator of how a loss was detected. A value of CM_NO_FEEDBACK
+ indicates that the application has received no feedback for all its
+ outstanding data, and is reporting this to the CM. For example, a
+ TCP that has experienced a timeout would use this parameter to inform
+ the CM of this. A value of CM_LOSS_FEEDBACK indicates that the
+ application has experienced some loss, which it believes to be due to
+ congestion, but not all outstanding data has been lost. For example,
+ a TCP segment loss detected using duplicate (selective)
+ acknowledgments or other data-driven techniques fits this category.
+ A value of CM_EXPLICIT_CONGESTION indicates that the receiver echoed
+ an explicit congestion notification message. Finally, a value of
+ CM_NO_CONGESTION indicates that no congestion-related loss has
+ occurred. The lossmode parameter MUST be reported as a bit-vector
+ where the bits correspond to CM_NO_FEEDBACK, CM_LOSS_FEEDBACK,
+ CM_EXPLICIT_CONGESTION, and CM_NO_CONGESTION. Note that over links
+ (paths) that experience losses for reasons other than congestion, an
+ application SHOULD inform the CM of losses, with the CM_NO_CONGESTION
+ field set.
+
+ cm_notify(i32 cm_streamid, u32 nsent) MUST be called when data is
+ transmitted from the host (e.g., in the IP output routine) to inform
+ the CM that nsent bytes were just transmitted on a given stream.
+ This allows the CM to update its estimate of the number of
+ outstanding bytes for the macroflow and for the stream.
+
+ A cmapp_send() grant from the CM to an application is valid only for
+ an expiration time, equal to the larger of the round-trip time and an
+ implementation-dependent threshold communicated as an argument to the
+ cmapp_send() callback function. The application MUST NOT send data
+ based on this callback after this time has expired. Furthermore, if
+ the application decides not to send data after receiving this
+ callback, it SHOULD call cm_notify(stream_info, 0) to allow the CM to
+ permit other streams in the macroflow to transmit data. The CM
+ congestion controller MUST be robust to applications forgetting to
+ invoke cm_notify(stream_info, 0) correctly, or applications that
+ crash or disappear after having made a cm_request() call.
+
+
+
+
+
+
+Balakrishnan, et. al. Standards Track [Page 10]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+3.4 Querying
+
+ If applications wish to learn about per-stream available bandwidth
+ and round-trip time, they can use the CM's cm_query(i32 cm_streamid,
+ i64* rate, i32* srtt, i32* rttdev) call, which fills in the desired
+ quantities. If the CM does not have valid estimates for the
+ macroflow, it fills in negative values for the rate, srtt, and
+ rttdev.
+
+3.5 Sharing granularity
+
+ One of the decisions the CM needs to make is the granularity at which
+ a macroflow is constructed, by deciding which streams belong to the
+ same macroflow and share congestion information. The API provides
+ two functions that allow applications to decide which of their
+ streams ought to belong to the same macroflow.
+
+ cm_getmacroflow(i32 cm_streamid) returns a unique i32 macroflow
+ identifier. cm_setmacroflow(i32 cm_macroflowid, i32 cm_streamid)
+ sets the macroflow of the stream cm_streamid to cm_macroflowid. If
+ the cm_macroflowid that is passed to cm_setmacroflow() is -1, then a
+ new macroflow is constructed and this is returned to the caller.
+ Each call to cm_setmacroflow() overrides the previous macroflow
+ association for the stream, should one exist.
+
+ The default suggested aggregation method is to aggregate by
+ destination IP address; i.e., all streams to the same destination
+ address are aggregated to a single macroflow by default. The
+ cm_getmacroflow() and cm_setmacroflow() calls can then be used to
+ change this as needed. We do note that there are some cases where
+ this may not be optimal, even over best-effort networks. For
+ example, when a group of receivers are behind a NAT device, the
+ sender will see them all as one address. If the hosts behind the NAT
+ are in fact connected over different bottleneck links, some of those
+ hosts could see worse performance than before. It is possible to
+ detect such hosts when using delay and loss estimates, although the
+ specific mechanisms for doing so are beyond the scope of this
+ document.
+
+ The objective of this interface is to set up sharing of groups not
+ sharing policy of relative weights of streams in a macroflow. The
+ latter requires the scheduler to provide an interface to set sharing
+ policy. However, because we want to support many different
+ schedulers (each of which may need different information to set
+ policy), we do not specify a complete API to the scheduler (but see
+
+
+
+
+
+
+Balakrishnan, et. al. Standards Track [Page 11]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+ Section 5.2). A later guideline document is expected to describe a
+ few simple schedulers (e.g., weighted round-robin, hierarchical
+ scheduling) and the API they export to provide relative
+ prioritization.
+
+4. CM internals
+
+ This section describes the internal components of the CM. It
+ includes a Congestion Controller and a Scheduler, with well-defined,
+ abstract interfaces exported by them.
+
+4.1 Congestion controller
+
+ Associated with each macroflow is a congestion control algorithm; the
+ collection of all these algorithms comprises the congestion
+ controller of the CM. The control algorithm decides when and how
+ much data can be transmitted by a macroflow. It uses application
+ notifications (Section 4.3) from concurrent streams on the same
+ macroflow to build up information about the congestion state of the
+ network path used by the macroflow.
+
+ The congestion controller MUST implement a "TCP-friendly" [Mahdavi98]
+ congestion control algorithm. Several macroflows MAY (and indeed,
+ often will) use the same congestion control algorithm but each
+ macroflow maintains state about the network used by its streams.
+
+ The congestion control module MUST implement the following abstract
+ interfaces. We emphasize that these are not directly visible to
+ applications; they are within the context of a macroflow, and are
+ different from the CM API functions of Section 4.
+
+ - void query(u64 *rate, u32 *srtt, u32 *rttdev): This function
+ returns the estimated rate (in bits per second) and smoothed
+ round trip time (in microseconds) for the macroflow.
+
+ - void notify(u32 nsent): This function MUST be used to notify the
+ congestion control module whenever data is sent by an
+ application. The nsent parameter indicates the number of bytes
+ just sent by the application.
+
+ - void update(u32 nsent, u32 nrecd, u32 rtt, u32 lossmode): This
+ function is called whenever any of the CM streams associated with
+ a macroflow identifies that data has reached the receiver or has
+ been lost en route. The nrecd parameter indicates the number of
+ bytes that have just arrived at the receiver. The nsent
+ parameter is the sum of the number of bytes just received and the
+
+
+
+
+
+Balakrishnan, et. al. Standards Track [Page 12]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+ number of bytes identified as lost en route. The rtt parameter is
+ the estimated round trip time in microseconds during the
+ transfer. The lossmode parameter provides an indicator of how a
+ loss was detected (section 4.3).
+
+ Although these interfaces are not visible to applications, the
+ congestion controller MUST implement these abstract interfaces to
+ provide for modular inter-operability with different separately-
+ developed schedulers.
+
+ The congestion control module MUST also call the associated
+ scheduler's schedule function (section 5.2) when it believes that the
+ current congestion state allows an MTU-sized packet to be sent.
+
+4.2 Scheduler
+
+ While it is the responsibility of the congestion control module to
+ determine when and how much data can be transmitted, it is the
+ responsibility of a macroflow's scheduler module to determine which
+ of the streams should get the opportunity to transmit data.
+
+ The Scheduler MUST implement the following interfaces:
+
+ - void schedule(u32 num_bytes): When the congestion control module
+ determines that data can be sent, the schedule() routine MUST be
+ called with no more than the number of bytes that can be sent.
+ In turn, the scheduler MAY call the cmapp_send() function that CM
+ applications must provide.
+
+ - float query_share(i32 cm_streamid): This call returns the
+ described stream's share of the total bandwidth available to the
+ macroflow. This call combined with the query call of the
+ congestion controller provides the information to satisfy an
+ application's cm_query() request.
+
+ - void notify(i32 cm_streamid, u32 nsent): This interface is used
+ to notify the scheduler module whenever data is sent by a CM
+ application. The nsent parameter indicates the number of bytes
+ just sent by the application.
+
+ The Scheduler MAY implement many additional interfaces. As
+ experience with CM schedulers increases, future documents may
+ make additions and/or changes to some parts of the scheduler
+ API.
+
+
+
+
+
+
+
+Balakrishnan, et. al. Standards Track [Page 13]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+5. Examples
+
+5.1 Example applications
+
+ This section describes three possible uses of the CM API by
+ applications. We describe two asynchronous applications---an
+ implementation of a TCP sender and an implementation of congestion-
+ controlled UDP sockets, and a synchronous application---a streaming
+ audio server. More details of these applications and CM
+ implementation optimizations for efficient operation are described in
+ [Andersen00].
+
+ All applications that use the CM MUST incorporate feedback from the
+ receiver. For example, it must periodically (typically once or twice
+ per round trip time) determine how many of its packets arrived at the
+ receiver. When the source gets this feedback, it MUST use
+ cm_update() to inform the CM of this new information. This results
+ in the CM updating ownd and may result in the CM changing its
+ estimates and calling cmapp_update() of the streams of the macroflow.
+
+ The protocols in this section are examples and suggestions for
+ implementation, rather than requirements for any conformant
+ implementation.
+
+5.1.1 TCP
+
+ A TCP implementation that uses CM should use the cmapp_send()
+ callback API. TCP only identifies which data it should send upon the
+ arrival of an acknowledgement or expiration of a timer. As a result,
+ it requires tight control over when and if new data or
+ retransmissions are sent.
+
+ When TCP either connects to or accepts a connection from another
+ host, it performs a cm_open() call to associate the TCP connection
+ with a cm_streamid.
+
+ Once a connection is established, the CM is used to control the
+ transmission of outgoing data. The CM eliminates the need for
+ tracking and reacting to congestion in TCP, because the CM and its
+ transmission API ensure proper congestion behavior. Loss recovery is
+ still performed by TCP based on fast retransmissions and recovery as
+ well as timeouts. In addition, TCP is also modified to have its own
+ outstanding window (tcp_ownd) estimate. Whenever data segments are
+ sent from its cmapp_send() callback, TCP updates its tcp_ownd value.
+ The ownd variable is also updated after each cm_update() call. TCP
+ also maintains a count of the number of outstanding segments
+ (pkt_cnt). At any time, TCP can calculate the average packet size
+ (avg_pkt_size) as tcp_ownd/pkt_cnt. The avg_pkt_size is used by TCP
+
+
+
+Balakrishnan, et. al. Standards Track [Page 14]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+ to help estimate the amount of outstanding data. Note that this is
+ not needed if the SACK option is used on the connection, since this
+ information is explicitly available.
+
+ The TCP output routines are modified as follows:
+
+ 1. All congestion window (cwnd) checks are removed.
+
+ 2. When application data is available. The TCP output routines
+ perform all non-congestion checks (Nagle algorithm, receiver-
+ advertised window check, etc). If these checks pass, the output
+ routine queues the data and calls cm_request() for the stream.
+
+ 3. If incoming data or timers result in a loss being detected, the
+ retransmission is also placed in a queue and cm_request() is
+ called for the stream.
+
+ 4. The cmapp_send() callback for TCP is set to an output routine.
+ If any retransmission is enqueued, the routine outputs the
+ retransmission. Otherwise, the routine outputs as much new data
+ as the TCP connection state allows. However, the cmapp_send()
+ never sends more than a single segment per call. This routine
+ arranges for the other output computations to be done, such as
+ header and options computations.
+
+ The IP output routine on the host calls cm_notify() when the packets
+ are actually sent out. Because it does not know which cm_streamid is
+ responsible for the packet, cm_notify() takes the stream_info as
+ argument (see Section 4 for what the stream_info should contain).
+ Because cm_notify() reports the IP payload size, TCP keeps track of
+ the total header size and incorporates these updates.
+
+ The TCP input routines are modified as follows:
+
+ 1. RTT estimation is done as normal using either timestamps or
+ Karn's algorithm. Any rtt estimate that is generated is passed to
+ CM via the cm_update call.
+
+ 2. All cwnd and slow start threshold (ssthresh) updates are
+ removed.
+
+ 3. Upon the arrival of an ack for new data, TCP computes the value
+ of in_flight (the amount of data in flight) as snd_max-ack-1
+ (i.e., MAX Sequence Sent - Current Ack - 1). TCP then calls
+ cm_update(streamid, tcp_ownd - in_flight, 0, CM_NO_CONGESTION,
+ rtt).
+
+
+
+
+
+Balakrishnan, et. al. Standards Track [Page 15]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+ 4. Upon the arrival of a duplicate acknowledgement, TCP must check
+ its dupack count (dup_acks) to determine its action. If dup_acks
+ < 3, the TCP does nothing. If dup_acks == 3, TCP assumes that a
+ packet was lost and that at least 3 packets arrived to generate
+ these duplicate acks. Therefore, it calls cm_update(streamid, 4 *
+ avg_pkt_size, 3 * avg_pkt_size, CM_LOSS_FEEDBACK, rtt). The
+ average packet size is used since the acknowledgments do not
+ indicate exactly how much data has reached the other end. Most
+ TCP implementations interpret a duplicate ACK as an indication
+ that a full MSS has reached its destination. Once a new ACK is
+ received, these TCP sender implementations may resynchronize with
+ TCP receiver. The CM API does not provide a mechanism for TCP to
+ pass information from this resynchronization. Therefore, TCP can
+ only infer the arrival of an avg_pkt_size amount of data from each
+ duplicate ack. TCP also enqueues a retransmission of the lost
+ segment and calls cm_request(). If dup_acks > 3, TCP assumes that
+ a packet has reached the other end and caused this ack to be sent.
+ As a result, it calls cm_update(streamid, avg_pkt_size,
+ avg_pkt_size, CM_NO_CONGESTION, rtt).
+
+ 5. Upon the arrival of a partial acknowledgment (one that does not
+ exceed the highest segment transmitted at the time the loss
+ occurred, as defined in [Floyd99b]), TCP assumes that a packet was
+ lost and that the retransmitted packet has reached the recipient.
+ Therefore, it calls cm_update(streamid, 2 * avg_pkt_size,
+ avg_pkt_size, CM_NO_CONGESTION, rtt). CM_NO_CONGESTION is used
+ since the loss period has already been reported. TCP also
+ enqueues a retransmission of the lost segment and calls
+ cm_request().
+
+ When the TCP retransmission timer expires, the sender identifies that
+ a segment has been lost and calls cm_update(streamid, avg_pkt_size,
+ 0, CM_NO_FEEDBACK, 0) to signify that no feedback has been received
+ from the receiver and that one segment is sure to have "left the
+ pipe." TCP also enqueues a retransmission of the lost segment and
+ calls cm_request().
+
+5.1.2 Congestion-controlled UDP
+
+ Congestion-controlled UDP is a useful CM application, which we
+ describe in the context of Berkeley sockets [Stevens94]. They
+ provide the same functionality as standard Berkeley UDP sockets, but
+ instead of immediately sending the data from the kernel packet queue
+ to lower layers for transmission, the buffered socket implementation
+ makes calls to the API exported by the CM inside the kernel and gets
+ callbacks from the CM. When a CM UDP socket is created, it is bound
+ to a particular stream. Later, when data is added to the packet
+ queue, cm_request() is called on the stream associated with the
+
+
+
+Balakrishnan, et. al. Standards Track [Page 16]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+ socket. When the CM schedules this stream for transmission, it calls
+ udp_ccappsend() in the UDP module. This function transmits one MTU
+ from the packet queue, and schedules the transmission of any
+ remaining packets. The in-kernel implementation of the CM UDP API
+ should not require any additional data copies and should support all
+ standard UDP options. Modifying existing applications to use
+ congestion-controlled UDP requires the implementation of a new socket
+ option on the socket. To work correctly, the sender must obtain
+ feedback about congestion. This can be done in at least two ways:
+ (i) the UDP receiver application can provide feedback to the sender
+ application, which will inform the CM of network conditions using
+ cm_update(); (ii) the UDP receiver implementation can provide
+ feedback to the sending UDP. Note that this latter alternative
+ requires changes to the receiver's network stack and the sender UDP
+ cannot assume that all receivers support this option without explicit
+ negotiation.
+
+5.1.3 Audio server
+
+ A typical audio application often has access to the sample in a
+ multitude of data rates and qualities. The objective of the
+ application is then to deliver the highest possible quality of audio
+ (typically the highest data rate) its clients. The selection of
+ which version of audio to transmit should be based on the current
+ congestion state of the network. In addition, the source will want
+ audio delivered to its users at a consistent sampling rate. As a
+ result, it must send data a regular rate, minimizing delaying
+ transmissions and reducing buffering before playback. To meet these
+ requirements, this application can use the synchronous sender API
+ (Section 4.2).
+
+ When the source first starts, it uses the cm_query() call to get an
+ initial estimate of network bandwidth and delay. If some other
+ streams on that macroflow have already been active, then it gets an
+ initial estimate that is valid; otherwise, it gets negative values,
+ which it ignores. It then chooses an encoding that does not exceed
+ these estimates (or, in the case of an invalid estimate, uses
+ application-specific initial values) and begins transmitting data.
+ The application also implements the cmapp_update() callback. When
+ the CM determines that network characteristics have changed, it calls
+ the application's cmapp_update() function and passes it a new rate
+ and round-trip time estimate. The application must change its choice
+ of audio encoding to ensure that it does not exceed these new
+ estimates.
+
+
+
+
+
+
+
+Balakrishnan, et. al. Standards Track [Page 17]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+5.2 Example congestion control module
+
+ To illustrate the responsibilities of a congestion control module,
+ the following describes some of the actions of a simple TCP-like
+ congestion control module that implements Additive Increase
+ Multiplicative Decrease congestion control (AIMD_CC):
+
+ - query(): AIMD_CC returns the current congestion window (cwnd)
+ divided by the smoothed rtt (srtt) as its bandwidth estimate. It
+ returns the smoothed rtt estimate as srtt.
+
+ - notify(): AIMD_CC adds the number of bytes sent to its
+ outstanding data window (ownd).
+
+ - update(): AIMD_CC subtracts nsent from ownd. If the value of rtt
+ is non-zero, AIMD_CC updates srtt using the TCP srtt calculation.
+ If the update indicates that data has been lost, AIMD_CC sets
+ cwnd to 1 MTU if the loss_mode is CM_NO_FEEDBACK and to cwnd/2
+ (with a minimum of 1 MTU) if the loss_mode is CM_LOSS_FEEDBACK or
+ CM_EXPLICIT_CONGESTION. AIMD_CC also sets its internal ssthresh
+ variable to cwnd/2. If no loss had occurred, AIMD_CC mimics TCP
+ slow start and linear growth modes. It increments cwnd by nsent
+ when cwnd < ssthresh (bounded by a maximum of ssthresh-cwnd) and
+ by nsent * MTU/cwnd when cwnd > ssthresh.
+
+ - When cwnd or ownd are updated and indicate that at least one MTU
+ may be transmitted, AIMD_CC calls the CM to schedule a
+ transmission.
+
+5.3 Example Scheduler Module
+
+ To clarify the responsibilities of a scheduler module, the following
+ describes some of the actions of a simple round robin scheduler
+ module (RR_sched):
+
+ - schedule(): RR_sched schedules as many streams as possible in round
+ robin fashion.
+
+ - query_share(): RR_sched returns 1/(number of streams in macroflow).
+
+ - notify(): RR_sched does nothing. Round robin scheduling is not
+ affected by the amount of data sent.
+
+6. Security Considerations
+
+ The CM provides many of the same services that the congestion control
+ in TCP provides. As such, it is vulnerable to many of the same
+ security problems. For example, incorrect reports of losses and
+
+
+
+Balakrishnan, et. al. Standards Track [Page 18]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+ transmissions will give the CM an inaccurate picture of the network's
+ congestion state. By giving CM a high estimate of congestion, an
+ attacker can degrade the performance observed by applications. For
+ example, a stream on a host can arbitrarily slow down any other
+ stream on the same macroflow, a form of denial of service.
+
+ The more dangerous form of attack occurs when an application gives
+ the CM a low estimate of congestion. This would cause CM to be
+ overly aggressive and allow data to be sent much more quickly than
+ sound congestion control policies would allow.
+
+ [Touch97] describes a number of the security problems that arise with
+ congestion information sharing. An additional vulnerability (not
+ covered by [Touch97])) occurs because applications have access
+ through the CM API to control shared state that will affect other
+ applications on the same computer. For instance, a poorly designed,
+ possibly a compromised, or intentionally malicious UDP application
+ could misuse cm_update() to cause starvation and/or too-aggressive
+ behavior of others in the macroflow.
+
+7. References
+
+ [Allman99] Allman, M. and Paxson, V., "TCP Congestion
+ Control", RFC 2581, April 1999.
+
+ [Andersen00] Balakrishnan, H., System Support for Bandwidth
+ Management and Content Adaptation in Internet
+ Applications, Proc. 4th Symp. on Operating Systems
+ Design and Implementation, San Diego, CA, October
+ 2000. Available from
+ http://nms.lcs.mit.edu/papers/cm-osdi2000.html
+
+ [Balakrishnan98] Balakrishnan, H., Padmanabhan, V., Seshan, S.,
+ Stemm, M., and Katz, R., "TCP Behavior of a Busy
+ Web Server: Analysis and Improvements," Proc. IEEE
+ INFOCOM, San Francisco, CA, March 1998.
+
+ [Balakrishnan99] Balakrishnan, H., Rahul, H., and Seshan, S., "An
+ Integrated Congestion Management Architecture for
+ Internet Hosts," Proc. ACM SIGCOMM, Cambridge, MA,
+ September 1999.
+
+ [Bradner96] Bradner, S., "The Internet Standards Process ---
+ Revision 3", BCP 9, RFC 2026, October 1996.
+
+ [Bradner97] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+
+
+
+Balakrishnan, et. al. Standards Track [Page 19]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+ [Clark90] Clark, D. and Tennenhouse, D., "Architectural
+ Consideration for a New Generation of Protocols",
+ Proc. ACM SIGCOMM, Philadelphia, PA, September
+ 1990.
+
+ [Eggert00] Eggert, L., Heidemann, J., and Touch, J., "Effects
+ of Ensemble TCP," ACM Computer Comm. Review,
+ January 2000.
+
+ [Floyd99a] Floyd, S. and Fall, K.," Promoting the Use of End-
+ to-End Congestion Control in the Internet,"
+ IEEE/ACM Trans. on Networking, 7(4), August 1999,
+ pp. 458-472.
+
+ [Floyd99b] Floyd, S. and T. Henderson,"The New Reno
+ Modification to TCP's Fast Recovery Algorithm," RFC
+ 2582, April 1999.
+
+ [Jacobson88] Jacobson, V., "Congestion Avoidance and Control,"
+ Proc. ACM SIGCOMM, Stanford, CA, August 1988.
+
+ [Mahdavi98] Mahdavi, J. and Floyd, S., "The TCP Friendly
+ Website,"
+ http://www.psc.edu/networking/tcp_friendly.html
+
+ [Mogul90] Mogul, J. and S. Deering, "Path MTU Discovery," RFC
+ 1191, November 1990.
+
+ [Padmanabhan98] Padmanabhan, V., "Addressing the Challenges of Web
+ Data Transport," PhD thesis, Univ. of California,
+ Berkeley, December 1998.
+
+ [Paxson00] Paxson, V. and M. Allman, "Computing TCP's
+ Retransmission Timer", RFC 2988, November 2000.
+
+ [Postel81] Postel, J., Editor, "Transmission Control
+ Protocol", STD 7, RFC 793, September 1981.
+
+ [Ramakrishnan99] Ramakrishnan, K. and Floyd, S., "A Proposal to Add
+ Explicit Congestion Notification (ECN) to IP," RFC
+ 2481, January 1999.
+
+
+ [Stevens94] Stevens, W., TCP/IP Illustrated, Volume 1.
+ Addison-Wesley, Reading, MA, 1994.
+
+ [Touch97] Touch, J., "TCP Control Block Interdependence", RFC
+ 2140, April 1997.
+
+
+
+Balakrishnan, et. al. Standards Track [Page 20]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+8. Acknowledgments
+
+ We thank David Andersen, Deepak Bansal, and Dorothy Curtis for their
+ work on the CM design and implementation. We thank Vern Paxson for
+ his detailed comments, feedback, and patience, and Sally Floyd, Mark
+ Handley, and Steven McCanne for useful feedback on the CM
+ architecture. Allison Mankin and Joe Touch provided several useful
+ comments on previous drafts of this document.
+
+9. Authors' Addresses
+
+ Hari Balakrishnan
+ Laboratory for Computer Science
+ 200 Technology Square
+ Massachusetts Institute of Technology
+ Cambridge, MA 02139
+
+ Web: http://nms.lcs.mit.edu/~hari/
+
+
+ Srinivasan Seshan
+ School of Computer Science
+ Carnegie Mellon University
+ 5000 Forbes Ave.
+ Pittsburgh, PA 15213
+
+ Web: http://www.cs.cmu.edu/~srini/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Balakrishnan, et. al. Standards Track [Page 21]
+
+RFC 3124 The Congestion Manager June 2001
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Balakrishnan, et. al. Standards Track [Page 22]
+
diff --git a/lib/diameter/doc/standard/rfc3539.txt b/lib/diameter/doc/standard/rfc3539.txt
new file mode 100644
index 0000000000..0b18625cc5
--- /dev/null
+++ b/lib/diameter/doc/standard/rfc3539.txt
@@ -0,0 +1,2299 @@
+
+
+
+
+
+
+Network Working Group B. Aboba
+Request for Comments: 3539 Microsoft
+Category: Standards Track J. Wood
+ Sun Microsystems, Inc.
+ June 2003
+
+
+ Authentication, Authorization and Accounting (AAA) Transport Profile
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+Abstract
+
+ This document discusses transport issues that arise within protocols
+ for Authentication, Authorization and Accounting (AAA). It also
+ provides recommendations on the use of transport by AAA protocols.
+ This includes usage of standards-track RFCs as well as experimental
+ proposals.
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 2
+ 1.1. Requirements Language. . . . . . . . . . . . . . . . . . 2
+ 1.2. Terminology. . . . . . . . . . . . . . . . . . . . . . . 2
+ 2. Issues in Transport Usage. . . . . . . . . . . . . . . . . . . 5
+ 2.1. Application-driven Versus Network-driven . . . . . . . . 5
+ 2.2. Slow Failover. . . . . . . . . . . . . . . . . . . . . . 6
+ 2.3. Use of Nagle Algorithm . . . . . . . . . . . . . . . . . 7
+ 2.4. Multiple Connections . . . . . . . . . . . . . . . . . . 7
+ 2.5. Duplicate Detection. . . . . . . . . . . . . . . . . . . 8
+ 2.6. Invalidation of Transport Parameter Estimates. . . . . . 8
+ 2.7. Inability to use Fast Re-Transmit. . . . . . . . . . . . 9
+ 2.8. Congestion Avoidance . . . . . . . . . . . . . . . . . . 9
+ 2.9. Delayed Acknowledgments. . . . . . . . . . . . . . . . . 11
+ 2.10. Premature Failover . . . . . . . . . . . . . . . . . . . 11
+ 2.11. Head of Line Blocking. . . . . . . . . . . . . . . . . . 11
+ 2.12. Connection Load Balancing. . . . . . . . . . . . . . . . 12
+
+
+
+
+Aboba & Wood Standards Track [Page 1]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ 3. AAA Transport Profile. . . . . . . . . . . . . . . . . . . . . 12
+ 3.1. Transport Mappings . . . . . . . . . . . . . . . . . . . 12
+ 3.2. Use of Nagle Algorithm . . . . . . . . . . . . . . . . . 12
+ 3.3. Multiple Connections . . . . . . . . . . . . . . . . . . 13
+ 3.4. Application Layer Watchdog . . . . . . . . . . . . . . . 13
+ 3.5. Duplicate Detection. . . . . . . . . . . . . . . . . . . 19
+ 3.6. Invalidation of Transport Parameter Estimates. . . . . . 20
+ 3.7. Inability to use Fast Re-Transmit. . . . . . . . . . . . 21
+ 3.8. Head of Line Blocking. . . . . . . . . . . . . . . . . . 22
+ 3.9. Congestion Avoidance . . . . . . . . . . . . . . . . . . 23
+ 3.10. Premature Failover . . . . . . . . . . . . . . . . . . . 24
+ 4. Security Considerations. . . . . . . . . . . . . . . . . . . . 24
+ 5. IANA Considerations. . . . . . . . . . . . . . . . . . . . . . 25
+ 6. References . . . . . . . . . . . . . . . . . . . . . . . . . . 25
+ 6.1. Normative References . . . . . . . . . . . . . . . . . . 25
+ 6.2. Informative References . . . . . . . . . . . . . . . . . 26
+ Appendix A - Detailed Watchdog Algorithm Description . . . . . . . 28
+ Appendix B - AAA Agents. . . . . . . . . . . . . . . . . . . . . . 33
+ B.1. Relays and Proxies . . . . . . . . . . . . . . . . . . . 33
+ B.2. Re-directs . . . . . . . . . . . . . . . . . . . . . . . 35
+ B.3. Store and Forward Proxies. . . . . . . . . . . . . . . . 36
+ B.4. Transport Layer Proxies. . . . . . . . . . . . . . . . . 38
+ Intellectual Property Statement. . . . . . . . . . . . . . . . . . 39
+ Acknowledgments. . . . . . . . . . . . . . . . . . . . . . . . . . 39
+ Author Addresses . . . . . . . . . . . . . . . . . . . . . . . . . 40
+ Full Copyright Statement . . . . . . . . . . . . . . . . . . . . . 41
+
+1. Introduction
+
+ This document discusses transport issues that arise within protocols
+ for Authentication, Authorization and Accounting (AAA). It also
+ provides recommendations on the use of transport by AAA protocols.
+ This includes usage of standards-track RFCs as well as experimental
+ proposals.
+
+1.1. Requirements Language
+
+ In this document, the key words "MAY", "MUST, "MUST NOT", "optional",
+ "recommended", "SHOULD", and "SHOULD NOT", are to be interpreted as
+ described in [RFC2119].
+
+1.2. Terminology
+
+ Accounting
+ The act of collecting information on resource usage for the
+ purpose of trend analysis, auditing, billing, or cost
+ allocation.
+
+
+
+
+Aboba & Wood Standards Track [Page 2]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ Administrative Domain
+ An internet, or a collection of networks, computers, and
+ databases under a common administration.
+
+ Agent A AAA agent is an intermediary that communicates with AAA
+ clients and servers. Several types of AAA agents exist,
+ including Relays, Re-directs, and Proxies.
+
+ Application-driven transport
+ Transport behavior is said to be "application-driven" when
+ the rate at which messages are sent is limited by the rate
+ at which the application generates data, rather than by the
+ size of the congestion window. In the most extreme case,
+ the time between transactions exceeds the round-trip time
+ between sender and receiver, implying that the application
+ operates with an effective congestion window of one. AAA
+ transport is typically application driven.
+
+ Attribute Value Pair (AVP)
+ The variable length concatenation of a unique Attribute
+ (represented by an integer) and a Value containing the
+ actual value identified by the attribute.
+
+ Authentication
+ The act of verifying a claimed identity, in the form of a
+ pre-existing label from a mutually known name space, as the
+ originator of a message (message authentication) or as the
+ end-point of a channel (entity authentication).
+
+ Authorization
+ The act of determining if a particular right, such as
+ access to some resource, can be granted to the presenter of
+ a particular credential.
+
+ Billing The act of preparing an invoice.
+
+ Network Access Identifier
+ The Network Access Identifier (NAI) is the userID submitted
+ by the host during network access authentication. In
+ roaming, the purpose of the NAI is to identify the user as
+ well as to assist in the routing of the authentication
+ request. The NAI may not necessarily be the same as the
+ user's e-mail address or the user-ID submitted in an
+ application layer authentication.
+
+
+
+
+
+
+
+Aboba & Wood Standards Track [Page 3]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ Network Access Server (NAS)
+ A Network Access Server (NAS) is a device that hosts
+ connect to in order to get access to the network.
+
+ Proxy In addition to forwarding requests and responses, proxies
+ enforce policies relating to resource usage and
+ provisioning. This is typically accomplished by tracking
+ the state of NAS devices. While proxies typically do not
+ respond to client Requests prior to receiving a Response
+ from the server, they may originate Reject messages in
+ cases where policies are violated. As a result, proxies
+ need to understand the semantics of the messages passing
+ through them, and may not support all extensions.
+
+ Local Proxy
+ A Local Proxy is a proxy that exists within the same
+ administrative domain as the network device (e.g. NAS) that
+ issued the AAA request. Typically a local proxy is used to
+ multiplex AAA messages to and from a large number of
+ network devices, and may implement policy.
+
+ Store and forward proxy
+ Store and forward proxies distinguish themselves from other
+ proxy species by sending a reply to the NAS prior to
+ proxying the request to the server. As a result, store and
+ forward proxies need to implement AAA client and server
+ functionality for the messages that they handle. Store and
+ Forward proxies also typically keep state on conversations
+ in progress in order to assure delivery of proxied Requests
+ and Responses. While store and forward proxies are most
+ frequently deployed for accounting, they also can be used
+ to implement authentication/authorization policy.
+
+ Network-driven transport
+ Transport behavior is said to be "network driven" when the
+ rate at which messages are sent is limited by the
+ congestion window, not by the rate at which the application
+ can generate data. File transfer is an example of an
+ application where transport is network driven.
+
+ Re-direct Rather than forwarding Requests and Responses between
+ clients and servers, Re-directs refer clients to servers
+ and allow them to communicate directly. Since Re-directs
+ do not sit in the forwarding path, they do not alter any
+ AVPs transitting between client and server. Re-directs do
+ not originate messages and are capable of handling any
+ message type. A Re-direct may be configured only to re-
+ direct messages of certain types, while acting as a Relay
+
+
+
+Aboba & Wood Standards Track [Page 4]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ or Proxy for other types. As with Relays, re-directs do
+ not keep state with respect to conversations or NAS
+ resources.
+
+ Relay Relays forward requests and responses based on routing-
+ related AVPs and domain forwarding table entries. Since
+ relays do not enforce policies, they do not examine or
+ alter non-routing AVPs. As a result, relays never
+ originate messages, do not need to understand the semantics
+ of messages or non-routing AVPs, and are capable of
+ handling any extension or message type. Since relays make
+ decisions based on information in routing AVPs and domain
+ forwarding tables they do not keep state on NAS resource
+ usage or conversations in progress.
+
+2. Issues in AAA Transport Usage
+
+ Issues that arise in AAA transport usage include:
+
+ Application-driven versus network-driven
+ Slow failover
+ Use of Nagle Algorithm
+ Multiple connections
+ Duplicate detection
+ Invalidation of transport parameter estimates
+ Inability to use fast re-transmit
+ Congestion avoidance
+ Delayed acknowledgments
+ Premature Failover
+ Head of line blocking
+ Connection load balancing
+
+ We discuss each of these issues in turn.
+
+2.1. Application-driven versus Network-driven
+
+ AAA transport behavior is typically application rather than network
+ driven. This means that the rate at which messages are sent is
+ typically limited by how quickly they are generated by the
+ application, rather than by the size of the congestion window.
+
+ For example, let us assume a 48-port NAS with an average session time
+ of 20 minutes. This device will, on average, send only 144
+ authentication/authorization requests/hour, and an equivalent number
+ of accounting requests. This represents an average inter-packet
+ spacing of 25 seconds, which is much larger than the Round Trip Time
+ (RTT) in most networks.
+
+
+
+
+Aboba & Wood Standards Track [Page 5]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ Even on much larger NAS devices, the inter-packet spacing is often
+ larger than the RTT. For example, consider a 2048-port NAS with an
+ average session time of 10 minutes. It will on average send 3.4
+ authentication/authorization requests/second, and an equivalent
+ number of accounting requests. This translates to an average inter-
+ packet spacing of 293 ms.
+
+ However, even where transport behavior is largely application-driven,
+ periods of network-driven behavior can occur. For example, after a
+ NAS reboot, previously stored accounting records may be sent to the
+ accounting server in rapid succession. Similarly, after recovery
+ from a power failure, users may respond with a large number of
+ simultaneous logins. In both cases, AAA messages may be generated
+ more quickly than the network will allow them to be sent, and a queue
+ will build up.
+
+ Network congestion can occur when transport behavior is network-
+ driven or application-driven. For example, while a single NAS may
+ not send substantial AAA traffic, many NASes may communicate with a
+ single AAA proxy or server. As a result, routers close to a heavily
+ loaded proxy or server may experience congestion, even though traffic
+ from each individual NAS is light. Such "convergent congestion" can
+ result in dropped packets in routers near the AAA server, or even
+ within the AAA server itself.
+
+ Let us consider what happens when 10,000 48-ports NASes, each with an
+ average session time of 20 minutes, are configured with the same AAA
+ agent or server. The unfortunate proxy or server would receive 400
+ authentication/authorization requests/second and an equivalent number
+ of accounting requests. For 1000 octet requests, this would generate
+ 6.4 Mbps of incoming traffic at the AAA agent or server.
+
+ While this transaction load is within the capabilities of the fastest
+ AAA agents and servers, implementations exist that cannot handle such
+ a high load. Thus high queuing delays and/or dropped packets may be
+ experienced at the agent or server, even if routers on the path are
+ not congested. Thus, a well designed AAA protocol needs to be able
+ to handle congestion occurring at the AAA server, as well as
+ congestion experienced within the network.
+
+2.2. Slow Failover
+
+ Where TCP [RFC793] is used as the transport, AAA implementations will
+ experience very slow fail over times if they wait until a TCP
+ connection times out before resending on another connection. This is
+ not an issue for SCTP [RFC2960], which supports endpoint and path
+ failure detection. As described in section 8 of [RFC2960], when the
+ number of retransmissions exceeds the maximum
+
+
+
+Aboba & Wood Standards Track [Page 6]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ ("Association.Max.Retrans"), the peer endpoint is considered
+ unreachable, the association enters the CLOSED state, and the failure
+ is reported to the application. This enables more rapid failure
+ detection.
+
+2.3. Use of Nagle Algorithm
+
+ AAA protocol messages are often smaller than the maximum segment size
+ (MSS). While exceptions occur when certificate-based authentication
+ messages are issued or where a low path MTU is found, typically AAA
+ protocol messages are less than 1000 octets. Therefore, when using
+ TCP [RFC793], the total packet count and associated network overhead
+ can be reduced by combining multiple AAA messages within a single
+ packet.
+
+ Where AAA runs over TCP and transport behavior is network-driven,
+ such as after a reboot when many users login simultaneously, or many
+ stored accounting records need to be sent, the Nagle algorithm will
+ result in "transport layer batching" of AAA messages. While this
+ does not reduce the work required by the application in parsing
+ packets and responding to the messages, it does reduce the number of
+ packets processed by routers along the path. The Nagle algorithm is
+ not used with SCTP.
+
+ Where AAA transport is application-driven, the NAS will typically
+ receive a reply from the home server prior to having another request
+ to send. This implies, for example, that accounting requests will
+ typically be sent individually rather than being batched by the
+ transport layer. As a result, within the application-driven regime,
+ the Nagle algorithm [RFC896] is ineffective.
+
+2.4. Multiple Connections
+
+ Since the RADIUS [RFC2865] Identifier field is a single octet, a
+ maximum of 256 requests can be in progress between two endpoints
+ described by a 5-tuple: (Client IP address, Client port, UDP, Server
+ IP address, Server port). In order to get around this limitation,
+ RADIUS clients have utilized more than one sending port, sometimes
+ even going to the extreme of using a different UDP source port for
+ each NAS port.
+
+ Were this behavior to be extended to AAA protocols operating over
+ reliable transport, the result would be multiplication of the
+ effective slow-start ramp-up by the number of connections. For
+ example, if a AAA client had ten connections open to a AAA agent, and
+ used a per-connection initial window [RFC3390] of 2, then the
+
+
+
+
+
+Aboba & Wood Standards Track [Page 7]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ effective initial window would be 20. This is inappropriate, since
+ it would permit the AAA client to send a large burst of packets into
+ the network.
+
+2.5. Duplicate Detection
+
+ Where a AAA client maintains connections to multiple AAA agents or
+ servers, and where failover/failback or connection load balancing is
+ supported, it is possible for multiple agents or servers to receive
+ duplicate copies of the same transaction. A transaction may be sent
+ on another connection before expiration of the "time wait" interval
+ necessary to guarantee that all packets sent on the original
+ connection have left the network. Therefore it is conceivable that
+ transactions sent on the alternate connection will arrive before
+ those sent on the failed connection. As a result, AAA agents and
+ servers MUST be prepared to handle duplicates, and MUST assume that
+ duplicates can arrive on any connection.
+
+ For example, in billing, it is necessary to be able to weed out
+ duplicate accounting records, based on the accounting session-id,
+ event-timestamp and NAS identification information. Where
+ authentication requests are always idempotent, the resultant
+ duplicate responses from multiple servers will presumably be
+ identical, so that little harm will result.
+
+ However, there are situations where the response to an authentication
+ request will depend on a previously established state, such as when
+ simultaneous usage restrictions are being enforced. In such cases,
+ authentication requests will not be idempotent. For example, while
+ an initial request might elicit an Accept response, a duplicate
+ request might elicit a Reject response from another server, if the
+ user were already presumed to be logged in, and only one simultaneous
+ session were permitted. In these situations, the AAA client might
+ receive both Accept and Reject responses to the same duplicate
+ request, and the outcome will depend on which response arrives first.
+
+2.6. Invalidation of Transport Parameter Estimates
+
+ Congestion control principles [Congest],[RFC2914] require the ability
+ of a transport protocol to respond effectively to congestion, as
+ sensed via increasing delays, packet loss, or explicit congestion
+ notification.
+
+ With network-driven applications, it is possible to respond to
+ congestion on a timescale comparable to the round-trip time (RTT).
+
+ However, with AAA protocols, the time between sends may be longer
+ than the RTT, so that the network conditions can not be assumed to
+
+
+
+Aboba & Wood Standards Track [Page 8]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ persist between sends. For example, the congestion window may grow
+ during a period in which congestion is being experienced because few
+ packets are sent, limiting the opportunity for feedback. Similarly,
+ after congestion is detected, the congestion window may remain small,
+ even though the network conditions that existed at the time of
+ congestion no longer apply by the time when the next packets are
+ sent. In addition, due to the low sampling interval, estimates of
+ RTT and RTO made via the procedure described in [RFC2988] may become
+ invalid.
+
+2.7. Inability to Use Fast Re-transmit
+
+ When congestion window validation [RFC2861] is implemented, the
+ result is that AAA protocols operate much of the time in slow-start
+ with an initial congestion window set to 1 or 2, depending on the
+ implementation [RFC3390]. This implies that AAA protocols gain
+ little benefit from the windowing features of reliable transport.
+
+ Since the congestion window is so small, it is generally not possible
+ to receive enough duplicate ACKs (3) to trigger fast re-transmit. In
+ addition, since AAA traffic is two-way, ACKs including data will not
+ count as part of the duplicate ACKs necessary to trigger fast re-
+ transmit. As a result, dropped packets will require a retransmission
+ timeout (RTO).
+
+2.8. Congestion Avoidance
+
+ The law of conservation of packets [Congest] suggests that a client
+ should not send another packet into the network until it can be
+ reasonably sure that a packet has exited the network on the same
+ path. In the case of a AAA client, the law suggests that it should
+ not retransmit to the same server or choose another server until it
+ can be reasonably sure that a packet has exited the network on the
+ same path. If the client advances the window as responses arrive,
+ then the client will "self clock", adjusting its transmission rate to
+ the available bandwidth.
+
+ While a AAA client using a reliable transport such as TCP [RFC793] or
+ SCTP [RFC2960] will self-clock when communicating directly with a
+ AAA-server, end-to-end self-clocking is not assured when AAA agents
+ are present.
+
+ As described in the Appendix, AAA agents include Relays, Proxies,
+ Re-directs, Store and Forward proxies, and Transport proxies. Of
+ these agents, only Transport proxies and Re-directs provide a direct
+ transport connection between the AAA client and server, allowing
+ end-to-end self-clocking to occur.
+
+
+
+
+Aboba & Wood Standards Track [Page 9]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ With Relays, Proxies or Store and Forward proxies, two separate and
+ de-coupled transport connections are used. One connection operates
+ between the AAA client and agent, and another between the agent and
+ server. Since the two transport connections are de-coupled,
+ transport layer ACKs do not flow end-to-end, and self-clocking does
+ not occur.
+
+ For example, consider what happens when the bottleneck exists between
+ a AAA Relay and a AAA server. Self-clocking will occur between the
+ AAA client and AAA Relay, causing the AAA client to adjust its
+ sending rate to the rate at which transport ACKs flow back from the
+ AAA Relay. However, since this rate is higher than the bottleneck
+ bandwidth, the overall system will not self-clock.
+
+ Since there is no direct transport connection between the AAA client
+ and AAA server, the AAA client does not have the ability to estimate
+ end-to-end transport parameters and adjust its sending rate to the
+ bottleneck bandwidth between the Relay and server. As a result, the
+ incoming rate at the AAA Relay can be higher than the rate at which
+ packets can be sent to the AAA server.
+
+ In this case, the end-to-end performance will be determined by
+ details of the agent implementation. In general, the end-to-end
+ transport performance in the presence of Relays, Proxies or Store and
+ Forward proxies will always be worse in terms of delay and packet
+ loss than if the AAA client and server were communicating directly.
+
+ For example, if the agent operates with a large receive buffer, it is
+ possible that a large queue will develop on the receiving side, since
+ the AAA client is able to send packets to the AAA agent more rapidly
+ than the agent can send them to the AAA server. Eventually, the
+ buffer will overflow, causing wholesale packet loss as well as high
+ delay.
+
+ Methods to induce fine-grained coupling between the two transport
+ connections are difficult to implement. One possible solution is for
+ the AAA agent to operate with a receive buffer that is no larger than
+ its send buffer. If this is done, "back pressure" (closing of the
+ receive window) will cause the agent to reduce the AAA client sending
+ rate when the agent send buffer fills. However, unless multiple
+ connections exist between the AAA client and AAA agent, closing of
+ the receive window will affect all traffic sent by the AAA client,
+ even traffic destined to AAA servers where no bottleneck exists.
+ Since multiple connections between a AAA client and agent result in
+ multiplication of the effective slow-start ramp rate, this is not
+ recommended. As a result, use of "back pressure" cannot enable
+ individual AAA client-server conversations to self-clock, and this
+ technique appears impractical for use in AAA.
+
+
+
+Aboba & Wood Standards Track [Page 10]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+2.9. Delayed Acknowledgments
+
+ As described in Appendix B, ACKs may comprise as much as half of the
+ traffic generated in a AAA exchange. This occurs because AAA
+ conversations are typically application-driven, and therefore there
+ is frequently not enough traffic to enable ACK piggybacking. As a
+ result, AAA protocols running over TCP or SCTP transport may
+ experience a doubling of traffic as compared with implementations
+ utilizing UDP transport.
+
+ It is typically not possible to address this issue via the sockets
+ API. ACK parameters (such as the value of the delayed ACK timer) are
+ typically fixed by TCP and SCTP implementations and are therefore not
+ tunable by the application.
+
+2.10. Premature Failover
+
+ RADIUS failover implementations are typically based on the concept of
+ primary and secondary servers, in which all traffic flows to the
+ primary server unless it is unavailable. However, the failover
+ algorithm was not specified in [RFC2865] or [RFC2866]. As a result,
+ RADIUS failover implementations vary in quality, with some failing
+ over prematurely, violating the law of "conservation of packets".
+
+ Where a Relay, Proxy or Store and Forward proxy is present, the AAA
+ client has no direct connection to a AAA server, and is unable to
+ estimate the end-to-end transport parameters. As a result, a AAA
+ client awaiting an application-layer response from the server has no
+ transport-based mechanism for determining an appropriate failover
+ timer.
+
+ For example, if the path between the AAA agent and server includes a
+ high delay link, or if the AAA server is very heavily loaded, it is
+ possible that the NAS will failover to another agent while packets
+ are still in flight. This violates the principle of "conservation of
+ packets", since the AAA client will inject additional packets into
+ the network before having evidence that a previously sent packet has
+ left the network. Such behavior can result in a worse situation on
+ an already congested link, resulting in congestive collapse
+ [Congest].
+
+2.11. Head of Line Blocking
+
+ Head of line blocking occurs during periods of packet loss where the
+ time between sends is shorter than the re-transmission timeout value
+ (RTO). In such situations, packets back up in the send queue until
+
+
+
+
+
+Aboba & Wood Standards Track [Page 11]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ the lost packet can be successfully re-transmitted. This can be an
+ issue for SCTP when using ordered delivery over a single stream, and
+ for TCP.
+
+ Head of line blocking is typically an issue only on larger NASes.
+ For example, a 48-port NAS with an average inter-packet spacing of 25
+ seconds is unlikely to have an RTO greater than this, unless severe
+ packet loss has been experienced. However, a 2048-port NAS with an
+ average inter-packet spacing of 293 ms may experience head-of-line
+ blocking since the inter-packet spacing is less than the minimum RTO
+ value of 1 second [RFC2988].
+
+2.12. Connection Load Balancing
+
+ In order to lessen queuing delays and address head of line blocking,
+ a AAA implementation may wish to load balance between connections to
+ multiple destinations. While it is possible to employ dynamic load
+ balancing techniques, this level of sophistication may not be
+ required. In many situations, adequate reliability and load
+ balancing can be achieved via static load balancing, where traffic is
+ distributed between destinations based on static "weights".
+
+3. AAA Transport Profile
+
+ In order to address AAA transport issues, it is recommended that AAA
+ protocols make use of standards track as well as experimental
+ techniques. More details are provided in the sections that follow.
+
+3.1. Transport Mappings
+
+ AAA Servers MUST support TCP and SCTP. AAA clients SHOULD support
+ SCTP, but MUST support TCP if SCTP is not available. As support for
+ SCTP improves, it is possible that SCTP support will be required on
+ clients at some point in the future. AAA agents inherit all the
+ obligations of Servers with respect to transport support.
+
+3.2. Use of Nagle Algorithm
+
+ While AAA protocols typically operate in the application-driven
+ regime, there are circumstances in which they are network driven.
+ For example, where an NAS reboots, or where connectivity is restored
+ between an NAS and a AAA agent, it is possible that multiple packets
+ will be available for sending.
+
+ As a result, there are circumstances where the transport-layer
+ batching provided by the Nagle Algorithm (12) is useful, and as a
+ result, AAA implementations running over TCP MUST enable the Nagle
+ algorithm, [RFC896]. The Nagle algorithm is not used with SCTP.
+
+
+
+Aboba & Wood Standards Track [Page 12]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+3.3. Multiple Connections
+
+ AAA protocols SHOULD use only a single persistent connection between
+ a AAA client and a AAA agent or server. They SHOULD provide for
+ pipelining of requests, so that more than one request can be in
+ progress at a time. In order to minimize use of inactive connections
+ in roaming situations, a AAA client or agent MAY bring down a
+ connection to a AAA agent or server if the connection has been
+ unutilized (discounting the watchdog) for a certain period of time,
+ which MUST NOT be less than BRINGDOWN_INTERVAL (5 minutes).
+
+ While a AAA client/agent SHOULD only use a single persistent
+ connection to a given AAA agent or server, it MAY have connections to
+ multiple AAA agents or servers. A AAA client/agent connected to
+ multiple agents/servers can treat them as primary/secondary or
+ balance load between them.
+
+3.4. Application Layer Watchdog
+
+ In order to enable AAA implementations to more quickly detect
+ transport and application-layer failures, AAA protocols MUST support
+ an application layer watchdog message.
+
+ The application layer watchdog message enables failover from a peer
+ that has failed, either because it is unreachable or because its
+ applications functions have failed. This is distinct from the
+ purpose of the SCTP heartbeat, which is to enable failover between
+ interfaces. The SCTP heartbeat may enable a failover to another path
+ to reach the same server, but does not address the situation where
+ the server system or the application service has failed. Therefore
+ both mechanisms MAY be used together.
+
+ The watchdog is used in order to enable a AAA client or agent to
+ determine when to resend on another connection. It operates on all
+ open connections and is used to suspend and eventually close
+ connections that are experiencing difficulties. The watchdog is also
+ used to re-open and validate connections that have returned to
+ health. The watchdog may be utilized either within primary/secondary
+ or load balancing configurations. However, it is not intended as a
+ cluster heartbeat mechanism.
+
+ The application layer watchdog is designed to detect failures of the
+ immediate peer, and not to be affected by failures of downstream
+ proxies or servers. This prevents instability in downstream AAA
+ components from propagating upstream. While the receipt of any AAA
+ Response from a peer is taken as evidence that the peer is up, lack
+ of a Response is insufficient to conclude that the peer is down.
+ Since the lack of Response may be the result of problems with a
+
+
+
+Aboba & Wood Standards Track [Page 13]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ downstream proxy or server, only after failure to respond to the
+ watchdog message can it be determined that the peer is down.
+
+ Since the watchdog algorithm takes any AAA Response into account in
+ determining peer liveness, decreases in the watchdog timer interval
+ do not significantly increase the level of watchdog traffic on
+ heavily loaded networks. This is because watchdog messages do not
+ need to be sent where other AAA Response traffic serves as a constant
+ reminder of peer liveness. Watchdog traffic only increases when AAA
+ traffic is light, and therefore a AAA Response "signal" is not
+ present. Nevertheless, decreasing the timer interval TWINIT does
+ increase the probability of false failover significantly, and so this
+ decision should be made with care.
+
+3.4.1. Algorithm Overview
+
+ The watchdog behavior is controlled by an algorithm defined in this
+ section. This algorithm is appropriate for use either within
+ primary/secondary or load balancing configurations. Implementations
+ SHOULD implement this algorithm, which operates as follows:
+
+ [1] Watchdog behavior is controlled by a single timer (Tw). The
+ initial value of Tw, prior to jittering is Twinit. The default
+ value of Twinit is 30 seconds. This value was selected because
+ it minimizes the probability that failover will be initiated due
+ to a routing flap, as noted in [Paxson].
+
+ While Twinit MAY be set as low as 6 seconds (not including
+ jitter), it MUST NOT be set lower than this. Note that setting
+ such a low value for Twinit is likely to result in an increased
+ probability of duplicates, as well as an increase in spurious
+ failover and failback attempts.
+
+ In order to avoid synchronization behaviors that can occur with
+ fixed timers among distributed systems, each time the watchdog
+ interval is calculated with a jitter by using the Twinit value
+ and randomly adding a value drawn between -2 and 2 seconds.
+ Alternative calculations to create jitter MAY be used. These
+ MUST be pseudo-random, generated by a PRNG seeded as per
+ [RFC1750].
+
+ [2] When any AAA message is received, Tw is reset. This need not be
+ a response to a watchdog request. Receiving a watchdog response
+ from a peer constitutes activity, and Tw should be reset. If the
+ watchdog timer expires and no watchdog response is pending, then
+ a watchdog message is sent. On sending a watchdog request, Tw is
+ reset.
+
+
+
+
+Aboba & Wood Standards Track [Page 14]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ Watchdog packets are not retransmitted by the AAA protocol, since
+ AAA protocols run over reliable transports that will handle all
+ retransmissions internally. As a result, a watchdog request is
+ only sent when there is no watchdog response pending.
+
+ [3] If the watchdog timer expires and a watchdog response is pending,
+ then failover is initiated. In order for a AAA client or agent
+ to perform failover procedures, it is necessary to maintain a
+ pending message queue for a given peer. When an answer message
+ is received, the corresponding request is removed from the queue.
+ The Hop-by-Hop Identifier field MAY be used to match the answer
+ with the queued request.
+
+ When failover is initiated, all messages in the queue are sent to
+ an alternate agent, if available. Multiple identical requests or
+ answers may be received as a result of a failover. The
+ combination of an end-to-end identifier and the origin host MUST
+ be used to identify duplicate messages.
+
+ Note that where traffic is heavy, the application layer watchdog
+ can take as long as 2Tw to determine that a peer has gone down.
+ For peers receiving a high volume of AAA Requests, AAA Responses
+ will continually reset the timer, so that after a failure it will
+ take Tw for the lack of traffic to be noticed, and for the
+ watchdog message to be sent. Another Tw will elapse before
+ failover is initiated.
+
+ On a lightly loaded network without much AAA Response traffic,
+ the watchdog timer will typically expire without being reset, so
+ that a watchdog response will be outstanding and failover will be
+ initiated after only a single timer interval has expired.
+
+ [4] The client MUST NOT close the primary connection until the
+ primary's watchdog timer has expired at least twice without a
+ response (note that the watchdog is not sent a second time,
+ however). Once this has occurred, the client SHOULD cause a
+ transport reset or close to be done on the connection.
+
+ Once the primary connection has failed, subsequent requests are
+ sent to the alternate server until the watchdog timer on the
+ primary connection is reset.
+
+ Suspension of the primary connection prevents flapping between
+ primary and alternate connections, and ensures that failover
+ behavior remains consistent. The application may not receive a
+ response to the watchdog request message due to a connectivity
+ problem, in which case a transport layer ACK will not have been
+ received, or the lack of response may be due to an application
+
+
+
+Aboba & Wood Standards Track [Page 15]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ problem. Without transport layer visibility, the application is
+ unable to tell the difference, and must behave conservatively.
+
+ In situations where no transport layer ACK is received on the
+ primary connection after multiple re-transmissions, the RTO will
+ be exponentially backed off as described in [RFC2988]. Due to
+ Karn's algorithm as implemented in SCTP and TCP, the RTO
+ estimator will not be reset until another ACK is received in
+ response to a non-re-transmitted request. Thus, in cases where
+ the problem occurs at the transport layer, after the client fails
+ over to the alternate server, the RTO of the primary will remain
+ at a high value unless an ACK is received on the primary
+ connection.
+
+ In the case where the problem occurs at the transport layer,
+ subsequent requests sent on the primary connection will not
+ receive the same service as was originally provided. For
+ example, instead of failover occurring after 3 retransmissions,
+ failover might occur without even a single retransmission if RTO
+ has been sufficiently backed off. Of course, if the lack of a
+ watchdog response was due to an application layer problem, then
+ RTO will not have been backed off. However, without transport
+ layer visibility, there is no way for the application to know
+ this.
+
+ Suspending use of the primary connection until a response to a
+ watchdog message is received guarantees that the RTO timer will
+ have been reset before the primary connection is reused. If no
+ response is received after the second watchdog timer expiration,
+ then the primary connection is closed and the suspension becomes
+ permanent.
+
+ [5] While the connection is in the closed state, the AAA client MUST
+ NOT attempt to send further watchdog messages on the connection.
+ However, after the connection is closed, the AAA client continues
+ to periodically attempt to reopen the connection.
+
+ The AAA client SHOULD wait for the transport layer to report
+ connection failure before attempting again, but MAY choose to
+ bound this wait time by the watchdog interval, Tw. If the
+ connection is successfully opened, then the watchdog message is
+ sent. Once three watchdog messages have been sent and responded
+ to, the connection is returned to service, and transactions are
+ once again sent over it. Connection validation via receipt of
+ multiple watchdogs is not required when a connection is initially
+ brought up -- in this case, the connection can immediately be put
+ into service.
+
+
+
+
+Aboba & Wood Standards Track [Page 16]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ [6] When using SCTP as a transport, it is not necessary to disable
+ SCTP's transport-layer heartbeats. However, if AAA
+ implementations have access to SCTP's heartbeat parameters, they
+ MAY chose to ensure that SCTP's heartbeat interval is longer than
+ the AAA watchdog interval, Tw. This will ensure that alternate
+ paths are still probed by SCTP, while the primary path has a
+ minimum of heartbeat redundancy.
+
+3.4.2. Primary/Secondary Failover Support
+
+ The watchdog timer MAY be integrated with primary/secondary style
+ failover so as to provide improved reliability and basic load
+ balancing. In order to balance load among multiple AAA servers, each
+ AAA server is designated the primary for a portion of the clients,
+ and designated as secondaries of varying priority for the remainder.
+ In this way, load can be balanced among the AAA servers.
+
+ Within primary/secondary configurations, the watchdog timer operates
+ as follows:
+
+ [1] Assume that each client or agent is initially configured with a
+ single primary agent or server, and one or more secondary
+ connections.
+
+ [2] The watchdog mechanism is used to suspend and eventually close
+ primary connections that are experiencing difficulties. It is
+ also used to re-open and validate connections that have returned
+ to health.
+
+ [3] Once a secondary is promoted to primary status, either on a
+ temporary or permanent basis, the next server on the list of
+ secondaries is promoted to fill the open secondary slot.
+
+ [4] The client or agent periodically attempts to re-open closed
+ connections, so that it is possible that a previously closed
+ connection can be returned to service and become eligible for use
+ again. Implementations will typically retain a limit on the
+ number of connections open at a time, so that once a previously
+ closed connection is brought online again, the lowest priority
+ secondary connection will be closed. In order to prevent
+ periodic closing and re-opening of secondary connections, it is
+ recommended that functioning connections remain open for a
+ minimum of 5 minutes.
+
+ [5] In order to enable diagnosis of failover behavior, it is
+ recommended that a table of failover events be kept within the
+ MIB. These failover events SHOULD include appropriate
+ transaction identifiers so that client and server data can be
+
+
+
+Aboba & Wood Standards Track [Page 17]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ compared, providing insight into the cause of the problem
+ (transport or application layer).
+
+3.4.3. Connection Load Balancing
+
+ Primary/secondary failover is capable of providing improved
+ resilience and basic load balancing. However, it does not address
+ TCP head of line blocking, since only a single connection is in use
+ at a time.
+
+ A AAA client or agent maintaining connections to multiple agents or
+ servers MAY load balance between them. Establishing connections to
+ multiple agents or servers reduces, but does not eliminate, head of
+ line blocking issues experienced on TCP connections. This issue does
+ not exist with SCTP connections utilizing multiple streams.
+
+ In connection load balancing configurations, the application watchdog
+ operates as follows:
+
+ [1] Assume that each client or agent is initially configured with
+ connections to multiple AAA agents or servers, with one
+ connection between a given client/agent and an agent/server.
+
+ [2] In static load balancing, transactions are apportioned among the
+ connections based on the total number of connections and a
+ "weight" assigned to each connection. Pearson's hash [RFC3074]
+ applied to the NAI [RFC2486] can be used to determine which
+ connection will handle a given transaction. Hashing on the NAI
+ provides highly granular load balancing, while ensuring that all
+ traffic for a given conversation will be sent to the same agent
+ or server. In dynamic load balancing, the value of the "weight"
+ can vary based on conditions such as AAA server load. Such
+ techniques, while sophisticated, are beyond the scope of this
+ document.
+
+ [3] Transactions are distributed to connections based on the total
+ number of available connections and their weights. A change in
+ the number of available connections forces recomputation of the
+ hash table. In order not to cause conversations in progress to
+ be switched to new destinations, on recomputation, a transitional
+ period is required in which both old and new hash tables are
+ needed in order to permit aging out of conversations in progress.
+ Note that this requires a way to easily determine whether a
+ Request represents a new conversation or the continuation of an
+ existing conversation. As a result, removing and adding of
+ connections is an expensive operation, and it is recommended that
+ the hash table only be recomputed once a connection is closed or
+ returned to service.
+
+
+
+Aboba & Wood Standards Track [Page 18]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ Suspended connections, although they are not used, do not force
+ hash table reconfiguration until they are closed. Similarly,
+ re-opened connections not accumulating sufficient watchdog
+ responses do not force a reconfiguration until they are returned
+ to service.
+
+ While a connection is suspended, transactions that were to have
+ been assigned to it are instead assigned to the next available
+ server. While this results in a momentary imbalance, it is felt
+ that this is a relatively small price to pay in order to reduce
+ hash table thrashing.
+
+ [4] In order to enable diagnosis of load balancing behavior, it is
+ recommended that in addition to a table of failover events, a
+ table of statistics be kept on each client, indexed by a AAA
+ server. That way, the effectiveness of the load balancing
+ algorithm can be evaluated.
+
+3.5. Duplicate Detection
+
+ Multiple facilities are required to enable duplicate detection.
+ These include session identifiers as well as hop-by-hop and end-to-
+ end message identifiers. Hop-by-hop identifiers whose value may
+ change at each hop are not sufficient, since a AAA server may receive
+ the same message from multiple agents. For example, a AAA client can
+ send a request to Agent1, then failover and resend the request to
+ Agent2; both agents forward the request to the home AAA server, with
+ different hop-by-hop identifiers. A Session Identifier is
+ insufficient as it does not distinguish different messages for the
+ the same session.
+
+ Proper treatment of the end-to-end message identifier ensures that
+ AAA operations are idempotent. For example, without an end-to-end
+ identifier, a AAA server keeping track of simultaneous logins might
+ send an Accept in response to an initial Request, and then a Reject
+ in response to a duplicate Request (where the user was allowed only
+ one simultaneous login). Depending on which Response arrived first,
+ the user might be allowed access or not.
+
+ However, if the server were to store the end-to-end message
+ identifier along with the simultaneous login information, then the
+ duplicate Request (which utilizes the same end-to-end message
+ identifier) could be identified and the correct response could be
+ returned.
+
+
+
+
+
+
+
+Aboba & Wood Standards Track [Page 19]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+3.6. Invalidation of Transport Parameter Estimates
+
+ In order to address invalidation of transport parameter estimates,
+ AAA protocol implementations MAY utilize Congestion Window Validation
+ [RFC2861] and RTO validation when using TCP. This specification also
+ recommends a procedure for RTO validation.
+
+ [RFC2581] and [RFC2861] both recommend that a connection go into
+ slow-start after a period where no traffic has been sent within the
+ RTO interval. [RFC2861] recommends only increasing the congestion
+ window if it was full when the ACK arrived. The congestion window is
+ reduced by half once every RTO interval if no traffic is received.
+
+ When Congestion Window Validation is used, the congestion window will
+ not build during application-driven periods, and instead will be
+ decayed. As a result, AAA applications operating within the
+ application-driven regime will typically run with a congestion window
+ equal to the initial window much of the time, operating in "perpetual
+ slowstart".
+
+ During periods in which AAA behavior is application-driven this will
+ have no effect. Since the time between packets will be larger than
+ RTT, AAA will operate with an effective congestion window equal to
+ the initial window. However, during network-driven periods, the
+ effect will be to space out sending of AAA packets. Thus instead of
+ being able to send a large burst of packets into the network, a
+ client will need to wait several RTTs as the congestion window builds
+ during slow-start.
+
+ For example, a client operating over TCP with an initial window of 2,
+ with 35 AAA requests to send would take approximately 6 RTTs to send
+ them, as the congestion window builds during slow start: 2, 3, 3, 6,
+ 9, 12. After the backlog is cleared, the implementation will once
+ again be application-driven and the congestion window size will
+ decay. If the client were using SCTP, the number of RTTs needed to
+ transmit all requests would usually be less, and would depend on the
+ size of the requests, since SCTP tracks the progress for the opening
+ of the congestion window by bytes, not segments.
+
+ Note that [RFC2861] and [RFC2988] do not address the issue of RTO
+ validation. This is also a problem, particularly when the Congestion
+ Manager [RFC3124] is implemented. During periods of high packet
+ loss, the RTO may be repeatedly increased via exponential back-off,
+ and may attain a high value. Due to lack of timely feedback on RTT
+ and RTO during application-driven periods, the high RTO estimate may
+ persist long after the conditions that generated it have dissipated.
+
+
+
+
+
+Aboba & Wood Standards Track [Page 20]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ RTO validation MAY be used to address this issue for TCP, via the
+ following procedure:
+
+ After the congestion window is decayed according to [RFC2861],
+ reset the estimated RTO to 3 seconds. After the next packet comes
+ in, re-calculate RTTavg, RTTdev, and RTO according to the method
+ described in [RFC2581].
+
+ To address this issue for SCTP, AAA implementations SHOULD use SCTP
+ heartbeats. [RFC2960] states that heartbeats should be enabled by
+ default, with an interval of 30 seconds. If this interval proves to
+ be too long to resolve this issue, AAA implementations MAY reduce the
+ heartbeat interval.
+
+3.7. Inability to Use Fast Re-Transmit
+
+ When Congestion Window Validation [RFC2861] is used, AAA
+ implementations will operate with a congestion window equal to the
+ initial window much of the time. As a result, the window size will
+ often not be large enough to enable use of fast re-transmit for TCP.
+ In addition, since AAA traffic is two-way, ACKs carrying data will
+ not count towards triggering fast re-transmit. SCTP is less likely
+ to encounter this issue, so the measures described below apply to
+ TCP.
+
+ To address this issue, AAA implementations SHOULD support selective
+ acknowledgement as described in [RFC2018] and [RFC2883]. AAA
+ implementations SHOULD also implement Limited Transmit for TCP, as
+ described in [RFC3042]. Rather than reducing the number of duplicate
+ ACKs required for triggering fast recovery, which would increase the
+ number of inappropriate re-transmissions, Limited Transmit enables
+ the window size be increased, thus enabling the sending of additional
+ packets which in turn may trigger fast re-transmit without a change
+ to the algorithm.
+
+ However, if congestion window validation [RFC2861] is implemented,
+ this proposal will only have an effect in situations where the time
+ between packets is less than the estimated retransmission timeout
+ (RTO). If the time between packets is greater than RTO, additional
+ packets will typically not be available for sending so as to take
+ advantage of the increased window size. As a result, AAA protocols
+ will typically operate with the lowest possible congestion window
+ size, resulting in a re-transmission timeout for every lost packet.
+
+
+
+
+
+
+
+
+Aboba & Wood Standards Track [Page 21]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+3.8. Head of Line Blocking
+
+ TCP inherently does not provide a solution to the head-of-line
+ blocking problem, although its effects can be lessened by
+ implementation of Limited Transmit [RFC3042], and connection load
+ balancing.
+
+3.8.1. Using SCTP Streams to Prevent Head of Line Blocking
+
+ Each AAA node SHOULD distribute its messages evenly across the range
+ of SCTP streams that it and its peer have agreed upon. (A lost
+ message in one stream will not cause any other streams to block.) A
+ trivial and effective implementation of this simply increments a
+ counter for the stream ID to send on. When the counter reaches the
+ maximum number of streams for the association, it resets to 0.
+
+ AAA peers MUST be able to accept messages on any stream. Note that
+ streams are used *solely* to prevent head-of-the-line blocking. All
+ identifying information is carried within the Diameter payload.
+ Messages distributed across multiple streams may not be received in
+ the order they are sent.
+
+ SCTP peers can allocate up to 65535 streams for an association. The
+ cost for idle streams may or may not be zero, depending on the
+ implementation, and the cost for non-idle streams is always greater
+ than 0. So administrators may wish to limit the number of possible
+ streams on their diameter nodes according to the resources (i.e.
+ memory, CPU power, etc.) of a particular node.
+
+ On a Diameter client, the number of streams may be determined by the
+ maximum number of peak users on the NAS. If a stream is available
+ per user, then this should be sufficient to prevent head-of-line
+ blocking. On a Diameter proxy, the number of streams may be
+ determined by the maximum number of peak sessions in progress from
+ that proxy to each downstream AAA server.
+
+ Stream IDs do not need to be preserved by relay agents. This
+ simplifies implementation, as agents can easily handle forwarding
+ between two associations with different numbers of streams. For
+ example, consider the following case, where a relay server DRL
+ forwards messages between a NAS and a home server, HMS. The NAS and
+ DRL have agreed upon 1000 streams for their association, and DRL and
+ HMS have agreed upon 2000 streams for their association. The
+ following figure shows the message flow from NAS to HMS via DRL, and
+ the stream ID assignments for each message:
+
+
+
+
+
+
+Aboba & Wood Standards Track [Page 22]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ +------+ +------+ +------+
+ | | | | | |
+ | NAS | ---------> | DRL | ---------> | HMS |
+ | | | | | |
+ +------+ 1000 streams +------+ 2000 streams +------+
+
+ msg 1: str id 0 msg 1: str id 0
+ msg 2: str id 1 msg 2: str id 1
+ ...
+ msg 1000: str id 999 msg 1000: str id 999
+ msg 1001: str id 0 msg 1001: str id 1000
+
+ DRL can forward messages 1 through 1000 to HMS using the same stream
+ ID that NAS used to send to DRL. However, since the NAS / DRL
+ association has only 1000 streams, NAS wraps around to stream ID 0
+ when sending message 1001. The DRL / HMS association, on the other
+ hand, has 2000 streams, so DRL can reassign message 1001 to stream ID
+ 1000 when forwarding it on to HMS.
+
+ This distribution scheme acts like a hash table. It is possible, yet
+ unlikely, that two messages will end up in the same stream, and even
+ less likely that there will be message loss resulting in blocking
+ when this happens. If it does turn out to be a problem, local
+ administrators can increase the number of streams on their nodes to
+ improve performance.
+
+3.9. Congestion Avoidance
+
+ In order to improve upon default timer estimates, AAA implementations
+ MAY implement the Congestion Manager (CM) [RFC3124]. CM is an end-
+ system module that:
+
+ (i) Enables an ensemble of multiple concurrent streams from a
+ sender destined to the same receiver and sharing the same
+ congestion properties to perform proper congestion avoidance
+ and control, and
+
+ (ii) Allows applications to easily adapt to network congestion.
+
+ The CM helps integrate congestion management across all applications
+ and transport protocols. The CM maintains congestion parameters
+ (available aggregate and per-stream bandwidth, per-receiver round-
+ trip times, etc.) and exports an API that enables applications to
+ learn about network characteristics, pass information to the CM,
+ share congestion information with each other, and schedule data
+ transmissions.
+
+
+
+
+
+Aboba & Wood Standards Track [Page 23]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ The CM enables the AAA application to access transport parameters
+ (RTTavg, RTTdev) via callbacks. RTO estimates are currently not
+ available via the callback interface, though they probably should be.
+ Where available, transport parameters SHOULD be used to improve upon
+ default timer values.
+
+3.10. Premature Failover
+
+ Premature failover is prevented by the watchdog functionality
+ described above. If the next hop does not return a reply, the AAA
+ client will send a watchdog message to it to verify liveness. If a
+ watchdog reply is received, then the AAA client will know that the
+ next hop server is functioning at the application layer. As a
+ result, it is only necessary to provide terminal error messages, such
+ as the following:
+
+ "Busy": agent/Server too busy to handle additional requests, NAS
+ should failover all requests to another agent/server.
+
+ "Can't Locate": agent can't locate the AAA server for the
+ indicated realm; NAS should failover that request to another
+ proxy.
+
+ "Can't Forward": agent has tried both primary and secondary AAA
+ servers with no response; NAS should failover the request to
+ another agent.
+
+ Note that these messages differ in their scope. The "Busy" message
+ tells the NAS that the agent/server is too busy for ANY request. The
+ "Can't Locate" and "Can't Forward" messages indicate that the
+ ultimate destination cannot be reached or isn't responding, implying
+ per-request failover.
+
+4. Security Considerations
+
+ Since AAA clients, agents and servers serve as network access
+ gatekeepers, they are tempting targets for attackers. General
+ security considerations concerning TCP congestion control are
+ discussed in [RFC2581]. However, there are some additional
+ considerations that apply to this specification.
+
+ By enabling failover between AAA agents, this specification improves
+ the resilience of AAA applications. However, it may also open
+ avenues for denial of service attacks.
+
+ The failover algorithm is driven by lack of response to AAA requests
+ and watchdog packets. On a lightly loaded network where AAA
+ responses would not be received prior to expiration of the watchdog
+
+
+
+Aboba & Wood Standards Track [Page 24]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ timer, an attacker can swamp the network, causing watchdog packets to
+ be dropped. This will cause the AAA client to switch to another AAA
+ agent, where the attack can be repeated. By causing the AAA client
+ to cycle between AAA agents, service can be denied to users desiring
+ network access.
+
+ Where TLS [RFC2246] is being used to provide AAA security, there will
+ be a vulnerability to spoofed reset packets, as well as other
+ transport layer denial of service attacks (e.g. SYN flooding). Since
+ SCTP offers improved denial of service resilience compared with TCP,
+ where AAA applications run over SCTP, this can be mitigated to some
+ extent.
+
+ Where IPsec [RFC2401] is used to provide security, it is important
+ that IPsec policy require IPsec on incoming packets. In order to
+ enable a AAA client to determine what security mechanisms are in use
+ on an agent or server without prior knowledge, it may be tempting to
+ initiate a connection in the clear, and then to have the AAA agent
+ respond with IKE [RFC2409]. While this approach minimizes required
+ client configuration, it increases the vulnerability to denial of
+ service attack, since a connection request can now not only tie up
+ transport resources, but also resources within the IKE
+ implementation.
+
+5. IANA Considerations
+
+ This document does not create any new number spaces for IANA
+ administration.
+
+References
+
+6.1. Normative References
+
+ [RFC793] Postel, J., "Transmission Control Protocol", STD 7, RFC
+ 793, September 1981.
+
+ [RFC896] Nagle, J., "Congestion Control in IP/TCP internetworks",
+ RFC 896, January 1984.
+
+ [RFC1750] Eastlake, D., Crocker, S. and J. Schiller, "Randomness
+ Recommendations for Security", RFC 1750, December 1994.
+
+ [RFC2018] Mathis, M., Mahdavi, J., Floyd, S. and A. Romanow, "TCP
+ Selective Acknowledgment Options", RFC 2018, October 1996.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+
+
+
+Aboba & Wood Standards Track [Page 25]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ [RFC2486] Aboba, B. and M. Beadles, "The Network Access Identifier",
+ RFC 2486, January 1999.
+
+ [RFC2581] Allman, M., Paxson, V. and W. Stevens, "TCP Congestion
+ Control", RFC 2581, April 1999.
+
+ [RFC2883] Floyd, S., Mahdavi, J., Mathis, M., Podolsky, M. and A.
+ Romanow, "An Extension to the Selective Acknowledgment
+ (SACK) Option for TCP", RFC 2883, July 2000.
+
+ [RFC2960] Stewart, R., Xie, Q., Morneault, K., Sharp, C.,
+ Schwarzbauer, H., Taylor, T., Rytina, I., Kalla, M., Zhang,
+ L. and V. Paxson, "Stream Control Transmission Protocol",
+ RFC 2960, October 2000.
+
+ [RFC2988] Paxson, V. and M. Allman, "Computing TCP's Retransmission
+ Timer", RFC 2988, November 2000.
+
+ [RFC3042] Allman, M., Balakrishnan H. and S. Floyd, "Enhancing TCP's
+ Loss Recovery Using Limited Transmit", RFC 3042, January
+ 2001.
+
+ [RFC3074] Volz, B., Gonczi, S., Lemon, T. and R. Stevens, "DHC Load
+ Balancing Algorithm", RFC 3074, February 2001.
+
+ [RFC3124] Balakrishnan, H. and S. Seshan, "The Congestion Manager",
+ RFC 3124, June 2001.
+
+6.2. Informative References
+
+ [RFC2246] Dierks, T. and C. Allen, "The TLS Protocol Version 1.0",
+ RFC 2246, January 1999.
+
+ [RFC2401] Atkinson, R. and S. Kent, "Security Architecture for the
+ Internet Protocol", RFC 2401, November 1998.
+
+ [RFC2409] Harkins, D. and D. Carrel, "The Internet Key Exchange
+ (IKE)", RFC 2409, November 1998.
+
+ [RFC2607] Aboba, B. and J. Vollbrecht, "Proxy Chaining and Policy
+ Implementation in Roaming", RFC 2607, June 1999.
+
+ [RFC2861] Handley, M., Padhye, J. and S. Floyd, "TCP Congestion
+ Window Validation", RFC 2861, June 2000.
+
+ [RFC2865] Rigney, C., Willens, S., Rubens, A. and W. Simpson, "Remote
+ Authentication Dial In User Service (RADIUS)", RFC 2865,
+ June 2000.
+
+
+
+Aboba & Wood Standards Track [Page 26]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ [RFC2866] Rigney, C., "RADIUS Accounting", RFC 2866, June 2000.
+
+ [RFC2914] Floyd, S., "Congestion Control Principles", BCP 41, RFC
+ 2914, September 2000.
+
+ [RFC2975] Aboba, B., Arkko, J. and D. Harrington, "Introduction to
+ Accounting Management", RFC 2975, June 2000.
+
+ [RFC3390] Allman, M., Floyd, S. and C. Partridge, "Increasing TCP's
+ Initial Window", RFC 3390, October 2002.
+
+ [Congest] Jacobson, V., "Congestion Avoidance and Control", Computer
+ Communication Review, vol. 18, no. 4, pp. 314-329, Aug.
+ 1988. ftp://ftp.ee.lbl.gov/papers/congavoid.ps.Z
+
+ [Paxson] Paxson, V., "Measurement and Analysis of End-to-End
+ Internet Dynamics", Ph.D. Thesis, Computer Science
+ Division, University of California, Berkeley, April 1997.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Aboba & Wood Standards Track [Page 27]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+Appendix A - Detailed Watchdog Algorithm
+
+ In this Appendix, the memory control structure that contains all
+ information regarding a specific peer is referred to as a Peer
+ Control Block, or PCB. The PCB contains the following fields:
+
+ Status:
+ OKAY: The connection is up
+ SUSPECT: Failover has been initiated on the connection.
+ DOWN: Connection has been closed.
+ REOPEN: Attempting to reopen a closed connection
+ INITIAL: The initial state of the pcb when it is first created.
+ The pcb has never been opened.
+
+ Variables:
+ Pending: Set to TRUE if there is an outstanding unanswered
+ watchdog request
+ Tw: Watchdog timer value
+ NumDWA: Number of DWAs received during REOPEN
+
+ Tw is the watchdog timer, measured in seconds. Every second, Tw is
+ decremented. When it reaches 0, the OnTimerElapsed event (see below)
+ is invoked. Pseudo-code for the algorithm is included on the
+ following pages.
+
+ SetWatchdog()
+ {
+ /*
+ SetWatchdog() is called whenever it is necessary
+ to reset the watchdog timer Tw. The value of the
+ watchdog timer is calculated based on the default
+ initial value TWINIT and a jitter ranging from
+ -2 to 2 seconds. The default for TWINIT is 30 seconds,
+ and MUST NOT be set lower than 6 seconds.
+ */
+ Tw=TWINIT -2.0 + 4.0 * random() ;
+ SetTimer(Tw) ;
+ return ;
+ }
+
+ /*
+ OnReceive() is called whenever a message
+ is received from the peer. This message MAY
+ be a request or an answer, and can include
+ DWR and DWA messages. Pending is assumed to
+ be a global variable.
+ */
+ OnReceive(pcb, msgType)
+
+
+
+Aboba & Wood Standards Track [Page 28]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ {
+ if (msgType == DWA) {
+ Pending = FALSE;
+ }
+ switch (pcb->Status){
+ case OKAY:
+ SetWatchdog();
+ break;
+ case SUSPECT:
+ pcb->Status = OKAY;
+ Failback(pcb);
+ SetWatchdog();
+ break;
+ case REOPEN:
+ if (msgType == DWA) {
+ NumDWA++;
+ if (NumDWA == 3) {
+ pcb->status = OKAY;
+ Failback();
+ }
+ } else {
+ Throwaway(received packet);
+ }
+ break;
+ case INITIAL:
+ case DOWN:
+ Throwaway(received packet);
+ break;
+ default:
+ Error("Shouldn't be here!");
+ break;
+ }
+ }
+
+ /*
+ OnTimerElapsed() is called whenever Tw reaches zero (0).
+ */
+ OnTimerElapsed(pcb)
+ {
+ switch (pcb->status){
+ case OKAY:
+ if (!Pending) {
+ SendWatchdog(pcb);
+ SetWatchdog();
+ Pending = TRUE;
+ break;
+ }
+ pcb->status = SUSPECT;
+
+
+
+Aboba & Wood Standards Track [Page 29]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ FailOver(pcb);
+ SetWatchdog();
+ break ;
+ case SUSPECT:
+ pcb->status = DOWN;
+ CloseConnection(pcb);
+ SetWatchdog();
+ break;
+ case INITIAL:
+ case DOWN:
+ AttemptOpen(pcb);
+ SetWatchdog();
+ break;
+ case REOPEN:
+ if (!Pending) {
+ SendWatchdog(pbc);
+ SetWatchdog();
+ Pending = TRUE;
+ break;
+ }
+ if (NumDWA < 0) {
+ pcb->status = DOWN;
+ CloseConnection(pcb);
+ } else {
+ NumDWA = -1;
+ }
+ SetWatchdog();
+ break;
+ default:
+ error("Shouldn't be here!);
+ break;
+ }
+ }
+
+ /*
+ OnConnectionUp() is called whenever a connection comes up
+ */
+ OnConnectionUp(pcb)
+ {
+ switch (pcb->status){
+ case INITIAL:
+ pcb->status = OKAY;
+ SetWatchdog();
+ break;
+ case DOWN:
+ pcb->status = REOPEN;
+ NumDWA = 0;
+ SendWatchdog(pcb);
+
+
+
+Aboba & Wood Standards Track [Page 30]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ SetWatchdog();
+ Pending = TRUE;
+ break;
+ default:
+ error("Shouldn't be here!);
+ break;
+ }
+ }
+
+ /*
+ OnConnectionDown() is called whenever a connection goes down
+ */
+ OnConnectionDown(pcb)
+ {
+ pcb->status = DOWN;
+ CloseConnection();
+ switch (pcb->status){
+ case OKAY:
+ Failover(pcb);
+ SetWatchdog();
+ break;
+ case SUSPECT:
+ case REOPEN:
+ SetWatchdog();
+ break;
+ default:
+ error("Shouldn't be here!);
+ break;
+ }
+ }
+
+ /* Here is the state machine equivalent to the above code:
+
+ STATE Event Actions New State
+ ===== ------ ------- ----------
+ OKAY Receive DWA Pending = FALSE
+ SetWatchdog() OKAY
+ OKAY Receive non-DWA SetWatchdog() OKAY
+ SUSPECT Receive DWA Pending = FALSE
+ Failback()
+ SetWatchdog() OKAY
+ SUSPECT Receive non-DWA Failback()
+ SetWatchdog() OKAY
+ REOPEN Receive DWA & Pending = FALSE
+ NumDWA == 2 NumDWA++
+ Failback() OKAY
+ REOPEN Receive DWA & Pending = FALSE
+ NumDWA < 2 NumDWA++ REOPEN
+
+
+
+Aboba & Wood Standards Track [Page 31]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ STATE Event Actions New State
+ ===== ------ ------- ----------
+ REOPEN Receive non-DWA Throwaway() REOPEN
+ INITIAL Receive DWA Pending = FALSE
+ Throwaway() INITIAL
+ INITIAL Receive non-DWA Throwaway() INITIAL
+ DOWN Receive DWA Pending = FALSE
+ Throwaway() DOWN
+ DOWN Receive non-DWA Throwaway() DOWN
+ OKAY Timer expires & SendWatchdog()
+ !Pending SetWatchdog()
+ Pending = TRUE OKAY
+ OKAY Timer expires & Failover()
+ Pending SetWatchdog() SUSPECT
+ SUSPECT Timer expires CloseConnection()
+ SetWatchdog() DOWN
+ INITIAL Timer expires AttemptOpen()
+ SetWatchdog() INITIAL
+ DOWN Timer expires AttemptOpen()
+ SetWatchdog() DOWN
+ REOPEN Timer expires & SendWatchdog()
+ !Pending SetWatchdog()
+ Pending = TRUE REOPEN
+ REOPEN Timer expires & CloseConnection()
+ Pending & SetWatchdog()
+ NumDWA < 0 DOWN
+ REOPEN Timer expires & NumDWA = -1
+ Pending & SetWatchdog()
+ NumDWA >= 0 REOPEN
+ INITIAL Connection up SetWatchdog() OKAY
+ DOWN Connection up NumDWA = 0
+ SendWatchdog()
+ SetWatchdog()
+ Pending = TRUE REOPEN
+ OKAY Connection down CloseConnection()
+ Failover()
+ SetWatchdog() DOWN
+ SUSPECT Connection down CloseConnection()
+ SetWatchdog() DOWN
+ REOPEN Connection down CloseConnection()
+ SetWatchdog() DOWN
+ */
+
+
+
+
+
+
+
+
+
+Aboba & Wood Standards Track [Page 32]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+Appendix B - AAA Agents
+
+ As described in [RFC2865] and [RFC2607], AAA agents have become
+ popular in order to support services such as roaming and shared use
+ networks. Such agents are used both for
+ authentication/authorization, as well as accounting [RFC2975].
+
+ AAA agents include:
+
+ Relays
+ Proxies
+ Re-directs
+ Store and Forward proxies
+ Transport layer proxies
+
+ The transport layer behavior of each of these agents is described
+ below.
+
+B.1 Relays and Proxies
+
+ While the application-layer behavior of relays and proxies are
+ different, at the transport layer the behavior is similar. In both
+ cases, two connections are established: one from the AAA client (NAS)
+ to the relay/proxy, and another from the relay/proxy to the AAA
+ server. The relay/proxy does not respond to a client request until
+ it receives a response from the server. Since the two connections
+ are de-coupled, the end-to-end conversation between the client and
+ server may not self clock.
+
+ Since AAA transport is typically application-driven, there is
+ frequently not enough traffic to enable ACK piggybacking. As a
+ result, the Nagle algorithm is rarely triggered, and delayed ACKs may
+ comprise nearly half the traffic. Thus AAA protocols running over
+ reliable transport will see packet traffic nearly double that
+ experienced with UDP transport. Since ACK parameters (such as the
+ value of the delayed ACK timer) are typically fixed by the TCP
+ implementation and are not tunable by the application, there is
+ little that can be done about this.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Aboba & Wood Standards Track [Page 33]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ A typical trace of a conversation between a NAS, proxy and server is
+ shown below:
+
+ Time NAS Relay/Proxy Server
+ ------ --- ----------- ------
+
+ 0 Request
+ ------->
+ OTTnp + Tpr Request
+ ------->
+
+ OTTnp + TdA Delayed ACK
+ <-------
+
+ OTTnp + OTTps + Reply/ACK
+ Tpr + Tsr <-------
+
+ OTTnp + OTTps +
+ Tpr + Tsr + Reply
+ OTTsp + TpR <-------
+
+ OTTnp + OTTps +
+ Tpr + Tsr + Delayed ACK
+ OTTsp + TdA ------->
+
+ OTTnp + OTTps +
+ OTTsp + OTTpn +
+ Tpr + Tsr + Delayed ACK
+ TpR + TdA ------->
+
+ Key
+ ---
+ OTT = One-way Trip Time
+ OTTnp = One-way trip time (NAS to Relay/Proxy)
+ OTTpn = One-way trip time (Relay/Proxy to NAS)
+ OTTps = One-way trip time (Relay/Proxy to Server)
+ OTTsp = One-way trip time (Server to Relay/Proxy)
+ TdA = Delayed ACK timer
+ Tpr = Relay/Proxy request processing time
+ TpR = Relay/Proxy reply processing time
+ Tsr = Server request processing time
+
+ At time 0, the NAS sends a request to the relay/proxy. Ignoring the
+ serialization time, the request arrives at the relay/proxy at time
+ OTTnp, and the relay/proxy takes an additional Tpr in order to
+ forward the request toward the home server. At time TdA after
+
+
+
+
+
+Aboba & Wood Standards Track [Page 34]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ receiving the request, the relay/proxy sends a delayed ACK. The
+ delayed ACK is sent, rather than being piggybacked on the reply, as
+ long as TdA < OTTps + OTTsp + Tpr + Tsr + TpR.
+
+ Typically Tpr < TdA, so that the delayed ACK is sent after the
+ relay/proxy forwards the request toward the server, but before the
+ relay/proxy receives the reply from the server. However, depending
+ on the TCP implementation on the relay/proxy and when the request is
+ received, it is also possible for the delayed ACK to be sent prior to
+ forwarding the request.
+
+ At time OTTnp + OTTps + Tpr, the server receives the request, and Tsr
+ later, it generates the reply. Where Tsr < TdA, the reply will
+ contain a piggybacked ACK. However, depending on the server
+ responsiveness and TCP implementation, the ACK and reply may be sent
+ separately. This can occur, for example, where a slow database or
+ storage system must be accessed prior to sending the reply.
+
+ At time OTTnp + OTTps + OTTsp + Tpr + Tsr the reply/ACK reaches the
+ relay/proxy, which then takes TpR additional time to forward the
+ reply to the NAS. At TdA after receiving the reply, the relay/proxy
+ generates a delayed ACK. Typically TpR < TdA so that the delayed ACK
+ is sent to the server after the relay/proxy forwards the reply to the
+ NAS. However, depending on the circumstances and the relay/proxy TCP
+ implementation, the delayed ACK may be sent first.
+
+ As with a delayed ACK sent in response to a request, which may be
+ piggybacked if the reply can be received quickly enough, piggybacking
+ of the ACK sent in response to a reply from the server is only
+ possible if additional request traffic is available. However, due to
+ the high inter-packet spacings in typical AAA scenarios, this is
+ unlikely unless the AAA protocol supports a reply ACK.
+
+ At time OTTnp + OTTps + OTTsp + OTTpn + Tpr + Tsr + TpR the NAS
+ receives the reply. TdA later, a delayed ACK is generated.
+
+B.2 Re-directs
+
+ Re-directs operate by referring a NAS to the AAA server, enabling the
+ NAS to talk to the AAA server directly. Since a direct transport
+ connection is established, the end-to-end connection will self-clock.
+
+ With re-directs, delayed ACKs are less frequent than with
+ application-layer proxies since the Re-direct and Server will
+ typically piggyback replies with ACKs.
+
+
+
+
+
+
+Aboba & Wood Standards Track [Page 35]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ The sequence of events is as follows:
+
+ Time NAS Re-direct Server
+ ------ --- --------- ------
+
+ 0 Request
+ ------->
+ OTTnp + Tpr Redirect/ACK
+ <-------
+
+ OTTnp + Tpr + Request
+ OTTpn + Tnr ------->
+
+ OTTnp + OTTpn +
+ Tpr + Tsr + Reply/ACK
+ OTTns <-------
+
+ OTTnp + OTTpn +
+ OTTns + OTTsn +
+ Tpr + Tsr + Delayed ACK
+ TdA ------->
+
+ Key
+ ---
+ OTT = One-way Trip Time
+ OTTnp = One-way trip time (NAS to Re-direct)
+ OTTpn = One-way trip time (Re-direct to NAS)
+ OTTns = One-way trip time (NAS to Server)
+ OTTsn = One-way trip time (Server to NAS)
+ TdA = Delayed ACK timer
+ Tpr = Re-direct processing time
+ Tnr = NAS re-direct processing time
+ Tsr = Server request processing time
+
+B.3 Store and Forward Proxies
+
+ With a store and forward proxy, the proxy may send a reply to the NAS
+ prior to forwarding the request to the server. While store and
+ forward proxies are most frequently deployed for accounting
+ [RFC2975], they also can be used to implement
+ authentication/authorization policy, as described in [RFC2607].
+
+ As noted in [RFC2975], store and forward proxies can have a negative
+ effect on accounting reliability. By sending a reply to the NAS
+ without receiving one from the accounting server, store and forward
+ proxies fool the NAS into thinking that the accounting request had
+ been accepted by the accounting server when this is not the case. As
+ a result, the NAS can delete the accounting packet from non-volatile
+
+
+
+Aboba & Wood Standards Track [Page 36]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ storage before it has been accepted by the accounting server. That
+ leaves the proxy responsible for delivering accounting packets. If
+ the proxy involves moving parts (e.g. a disk drive) while the NAS
+ does not, overall system reliability can be reduced. As a result,
+ store and forward proxies SHOULD NOT be used.
+
+ The sequence of events is as follows:
+
+ Time NAS Proxy Server
+ ------ --- ----- ------
+
+ 0 Request
+ ------->
+ OTTnp + TpR Reply/ACK
+ <-------
+
+ OTTnp + Tpr Request
+ ------->
+
+ OTTnp + OTTph + Reply/ACK
+ Tpr + Tsr <-------
+
+ OTTnp + OTTph +
+ Tpr + Tsr + Reply
+ OTThp + TpR <-------
+
+ OTTnp + OTTph +
+ Tpr + Tsr + Delayed ACK
+ OTThp + TdA ------->
+
+ OTTnp + OTTph +
+ OTThp + OTTpn +
+ Tpr + Tsr + Delayed ACK
+ TpR + TdA ------->
+
+ Key
+ ---
+ OTT = One-way Trip Time
+ OTTnp = One-way trip time (NAS to Proxy)
+ OTTpn = One-way trip time (Proxy to NAS)
+ OTTph = One-way trip time (Proxy to Home server)
+ OTThp = One-way trip time (Home Server to Proxy)
+ TdA = Delayed ACK timer
+ Tpr = Proxy request processing time
+ TpR = Proxy reply processing time
+ Tsr = Server request processing time
+
+
+
+
+
+Aboba & Wood Standards Track [Page 37]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+B.4 Transport Layer Proxies
+
+ In addition to acting as proxies at the application layer, transport
+ layer proxies forward transport ACKs between the AAA client and
+ server. This splices together the client-proxy and proxy-server
+ connections into a single connection that behaves as though it
+ operates end-to-end, exhibiting self-clocking. However, since
+ transport proxies operate at the transport layer, they cannot be
+ implemented purely as applications and they are rarely deployed.
+
+ With a transport proxy, the sequence of events is as follows:
+
+ Time NAS Proxy Home Server
+ ------ --- ----- -----------
+
+ 0 Request
+ ------->
+ OTTnp + Tpr Request
+ ------->
+
+ OTTnp + OTTph + Reply/ACK
+ Tpr + Tsr <-------
+
+ OTTnp + OTTph +
+ Tpr + Tsr + Reply/ACK
+ OTThp + TpR <-------
+
+ OTTnp + OTTph +
+ OTThp + OTTpn +
+ Tpr + Tsr + Delayed ACK
+ TpR + TdA ------->
+
+
+ OTTnp + OTTph +
+ OTThp + OTTpn +
+ Tpr + Tsr + Delayed ACK
+ TpR + TpD ------->
+
+ Key
+ ---
+ OTT = One-way Trip Time
+ OTTnp = One-way trip time (NAS to Proxy)
+ OTTpn = One-way trip time (Proxy to NAS)
+ OTTph = One-way trip time (Proxy to Home server)
+ OTThp = One-way trip time (Home Server to Proxy)
+ TdA = Delayed ACK timer
+ Tpr = Proxy request processing time
+ TpR = Proxy reply processing time
+
+
+
+Aboba & Wood Standards Track [Page 38]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+ Tsr = Server request processing time
+ TpD = Proxy delayed ack processing time
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11. Copies of
+ claims of rights made available for publication and any assurances of
+ licenses to be made available, or the result of an attempt made to
+ obtain a general license or permission for the use of such
+ proprietary rights by implementors or users of this specification can
+ be obtained from the IETF Secretariat.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights which may cover technology that may be required to practice
+ this standard. Please address the information to the IETF Executive
+ Director.
+
+Acknowledgments
+
+ Thanks to Allison Mankin of AT&T, Barney Wolff of Databus, Steve Rich
+ of Cisco, Randy Bush of AT&T, Bo Landarv of IP Unplugged, Jari Arkko
+ of Ericsson, and Pat Calhoun of Blackstorm Networks for fruitful
+ discussions relating to AAA transport.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Aboba & Wood Standards Track [Page 39]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+Authors' Addresses
+
+ Bernard Aboba
+ Microsoft Corporation
+ One Microsoft Way
+ Redmond, WA 98052
+
+ Phone: +1 425 706 6605
+ Fax: +1 425 936 7329
+
+
+ Jonathan Wood
+ Sun Microsystems, Inc.
+ 901 San Antonio Road
+ Palo Alto, CA 94303
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Aboba & Wood Standards Track [Page 40]
+
+RFC 3539 AAA Transport Profile June 2003
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Aboba & Wood Standards Track [Page 41]
+
diff --git a/lib/diameter/doc/standard/rfc3588.txt b/lib/diameter/doc/standard/rfc3588.txt
new file mode 100644
index 0000000000..fe4ff08c81
--- /dev/null
+++ b/lib/diameter/doc/standard/rfc3588.txt
@@ -0,0 +1,8235 @@
+
+
+
+
+
+
+Network Working Group P. Calhoun
+Request for Comments: 3588 Airespace, Inc.
+Category: Standards Track J. Loughney
+ Nokia
+ E. Guttman
+ Sun Microsystems, Inc.
+ G. Zorn
+ Cisco Systems, Inc.
+ J. Arkko
+ Ericsson
+ September 2003
+
+
+ Diameter Base Protocol
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+Abstract
+
+ The Diameter base protocol is intended to provide an Authentication,
+ Authorization and Accounting (AAA) framework for applications such as
+ network access or IP mobility. Diameter is also intended to work in
+ both local Authentication, Authorization & Accounting and roaming
+ situations. This document specifies the message format, transport,
+ error reporting, accounting and security services to be used by all
+ Diameter applications. The Diameter base application needs to be
+ supported by all Diameter implementations.
+
+Conventions Used In This Document
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in BCP 14, RFC 2119
+ [KEYWORD].
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 1]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+Table of Contents
+
+ 1. Introduction................................................. 6
+ 1.1. Diameter Protocol..................................... 9
+ 1.1.1. Description of the Document Set.............. 10
+ 1.2. Approach to Extensibility............................. 11
+ 1.2.1. Defining New AVP Values...................... 11
+ 1.2.2. Creating New AVPs............................ 11
+ 1.2.3. Creating New Authentication Applications..... 11
+ 1.2.4. Creating New Accounting Applications......... 12
+ 1.2.5. Application Authentication Procedures........ 14
+ 1.3. Terminology........................................... 14
+ 2. Protocol Overview............................................ 18
+ 2.1. Transport............................................. 20
+ 2.1.1. SCTP Guidelines.............................. 21
+ 2.2. Securing Diameter Messages............................ 21
+ 2.3. Diameter Application Compliance....................... 21
+ 2.4. Application Identifiers............................... 22
+ 2.5. Connections vs. Sessions.............................. 22
+ 2.6. Peer Table............................................ 23
+ 2.7. Realm-Based Routing Table............................. 24
+ 2.8. Role of Diameter Agents............................... 25
+ 2.8.1. Relay Agents................................. 26
+ 2.8.2. Proxy Agents................................. 27
+ 2.8.3. Redirect Agents.............................. 28
+ 2.8.4. Translation Agents........................... 29
+ 2.9. End-to-End Security Framework......................... 30
+ 2.10. Diameter Path Authorization........................... 30
+ 3. Diameter Header.............................................. 32
+ 3.1. Command Codes......................................... 35
+ 3.2. Command Code ABNF specification....................... 36
+ 3.3. Diameter Command Naming Conventions................... 38
+ 4. Diameter AVPs................................................ 38
+ 4.1. AVP Header............................................ 39
+ 4.1.1. Optional Header Elements..................... 41
+ 4.2. Basic AVP Data Formats................................ 41
+ 4.3. Derived AVP Data Formats.............................. 42
+ 4.4. Grouped AVP Values.................................... 49
+ 4.4.1. Example AVP with a Grouped Data Type......... 50
+ 4.5. Diameter Base Protocol AVPs........................... 53
+ 5. Diameter Peers............................................... 56
+ 5.1. Peer Connections...................................... 56
+ 5.2. Diameter Peer Discovery............................... 56
+ 5.3. Capabilities Exchange................................. 59
+ 5.3.1. Capabilities-Exchange-Request................ 60
+ 5.3.2. Capabilities-Exchange-Answer................. 60
+ 5.3.3. Vendor-Id AVP................................ 61
+ 5.3.4. Firmware-Revision AVP........................ 61
+
+
+
+Calhoun, et al. Standards Track [Page 2]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ 5.3.5. Host-IP-Address AVP.......................... 62
+ 5.3.6. Supported-Vendor-Id AVP...................... 62
+ 5.3.7. Product-Name AVP............................. 62
+ 5.4. Disconnecting Peer Connections........................ 62
+ 5.4.1. Disconnect-Peer-Request...................... 63
+ 5.4.2. Disconnect-Peer-Answer....................... 63
+ 5.4.3. Disconnect-Cause AVP......................... 63
+ 5.5. Transport Failure Detection........................... 64
+ 5.5.1. Device-Watchdog-Request...................... 64
+ 5.5.2. Device-Watchdog-Answer....................... 64
+ 5.5.3. Transport Failure Algorithm.................. 65
+ 5.5.4. Failover and Failback Procedures............. 65
+ 5.6. Peer State Machine.................................... 66
+ 5.6.1. Incoming connections......................... 68
+ 5.6.2. Events....................................... 69
+ 5.6.3. Actions...................................... 70
+ 5.6.4. The Election Process......................... 71
+ 6. Diameter Message Processing.................................. 71
+ 6.1. Diameter Request Routing Overview..................... 71
+ 6.1.1. Originating a Request........................ 73
+ 6.1.2. Sending a Request............................ 73
+ 6.1.3. Receiving Requests........................... 73
+ 6.1.4. Processing Local Requests.................... 73
+ 6.1.5. Request Forwarding........................... 74
+ 6.1.6. Request Routing.............................. 74
+ 6.1.7. Redirecting Requests......................... 74
+ 6.1.8. Relaying and Proxying Requests............... 75
+ 6.2. Diameter Answer Processing............................ 76
+ 6.2.1. Processing Received Answers.................. 77
+ 6.2.2. Relaying and Proxying Answers................ 77
+ 6.3. Origin-Host AVP....................................... 77
+ 6.4. Origin-Realm AVP...................................... 78
+ 6.5. Destination-Host AVP.................................. 78
+ 6.6. Destination-Realm AVP................................. 78
+ 6.7. Routing AVPs.......................................... 78
+ 6.7.1. Route-Record AVP............................. 79
+ 6.7.2. Proxy-Info AVP............................... 79
+ 6.7.3. Proxy-Host AVP............................... 79
+ 6.7.4. Proxy-State AVP.............................. 79
+ 6.8. Auth-Application-Id AVP............................... 79
+ 6.9. Acct-Application-Id AVP............................... 79
+ 6.10. Inband-Security-Id AVP................................ 79
+ 6.11. Vendor-Specific-Application-Id AVP.................... 80
+ 6.12. Redirect-Host AVP..................................... 80
+ 6.13. Redirect-Host-Usage AVP............................... 80
+ 6.14. Redirect-Max-Cache-Time AVP........................... 81
+ 6.15. E2E-Sequence AVP...................................... 82
+
+
+
+
+Calhoun, et al. Standards Track [Page 3]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ 7. Error Handling............................................... 82
+ 7.1. Result-Code AVP....................................... 84
+ 7.1.1. Informational................................ 84
+ 7.1.2. Success...................................... 84
+ 7.1.3. Protocol Errors.............................. 85
+ 7.1.4. Transient Failures........................... 86
+ 7.1.5. Permanent Failures........................... 86
+ 7.2. Error Bit............................................. 88
+ 7.3. Error-Message AVP..................................... 89
+ 7.4. Error-Reporting-Host AVP.............................. 89
+ 7.5. Failed-AVP AVP........................................ 89
+ 7.6. Experimental-Result AVP............................... 90
+ 7.7. Experimental-Result-Code AVP.......................... 90
+ 8. Diameter User Sessions....................................... 90
+ 8.1. Authorization Session State Machine................... 92
+ 8.2. Accounting Session State Machine...................... 96
+ 8.3. Server-Initiated Re-Auth.............................. 101
+ 8.3.1. Re-Auth-Request.............................. 102
+ 8.3.2. Re-Auth-Answer............................... 102
+ 8.4. Session Termination................................... 103
+ 8.4.1. Session-Termination-Request.................. 104
+ 8.4.2. Session-Termination-Answer................... 105
+ 8.5. Aborting a Session.................................... 105
+ 8.5.1. Abort-Session-Request........................ 106
+ 8.5.2. Abort-Session-Answer......................... 106
+ 8.6. Inferring Session Termination from Origin-State-Id.... 107
+ 8.7. Auth-Request-Type AVP................................. 108
+ 8.8. Session-Id AVP........................................ 108
+ 8.9. Authorization-Lifetime AVP............................ 109
+ 8.10. Auth-Grace-Period AVP................................. 110
+ 8.11. Auth-Session-State AVP................................ 110
+ 8.12. Re-Auth-Request-Type AVP.............................. 110
+ 8.13. Session-Timeout AVP................................... 111
+ 8.14. User-Name AVP......................................... 111
+ 8.15. Termination-Cause AVP................................. 111
+ 8.16. Origin-State-Id AVP................................... 112
+ 8.17. Session-Binding AVP................................... 113
+ 8.18. Session-Server-Failover AVP........................... 113
+ 8.19. Multi-Round-Time-Out AVP.............................. 114
+ 8.20. Class AVP............................................. 114
+ 8.21. Event-Timestamp AVP................................... 115
+ 9. Accounting................................................... 115
+ 9.1. Server Directed Model................................. 115
+ 9.2. Protocol Messages..................................... 116
+ 9.3. Application Document Requirements..................... 116
+ 9.4. Fault Resilience...................................... 116
+ 9.5. Accounting Records.................................... 117
+ 9.6. Correlation of Accounting Records..................... 118
+
+
+
+Calhoun, et al. Standards Track [Page 4]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ 9.7. Accounting Command-Codes.............................. 119
+ 9.7.1. Accounting-Request........................... 119
+ 9.7.2. Accounting-Answer............................ 120
+ 9.8. Accounting AVPs....................................... 121
+ 9.8.1. Accounting-Record-Type AVP................... 121
+ 9.8.2. Acct-Interim-Interval AVP.................... 122
+ 9.8.3. Accounting-Record-Number AVP................. 123
+ 9.8.4. Acct-Session-Id AVP.......................... 123
+ 9.8.5. Acct-Multi-Session-Id AVP.................... 123
+ 9.8.6. Accounting-Sub-Session-Id AVP................ 123
+ 9.8.7. Accounting-Realtime-Required AVP............. 123
+ 10. AVP Occurrence Table......................................... 124
+ 10.1. Base Protocol Command AVP Table....................... 124
+ 10.2. Accounting AVP Table.................................. 126
+ 11. IANA Considerations.......................................... 127
+ 11.1. AVP Header............................................ 127
+ 11.1.1. AVP Code..................................... 127
+ 11.1.2. AVP Flags.................................... 128
+ 11.2. Diameter Header....................................... 128
+ 11.2.1. Command Codes................................ 128
+ 11.2.2. Command Flags................................ 129
+ 11.3. Application Identifiers............................... 129
+ 11.4. AVP Values............................................ 129
+ 11.4.1. Result-Code AVP Values....................... 129
+ 11.4.2. Accounting-Record-Type AVP Values............ 130
+ 11.4.3. Termination-Cause AVP Values................. 130
+ 11.4.4. Redirect-Host-Usage AVP Values............... 130
+ 11.4.5. Session-Server-Failover AVP Values........... 130
+ 11.4.6. Session-Binding AVP Values................... 130
+ 11.4.7. Disconnect-Cause AVP Values.................. 130
+ 11.4.8. Auth-Request-Type AVP Values................. 130
+ 11.4.9. Auth-Session-State AVP Values................ 130
+ 11.4.10. Re-Auth-Request-Type AVP Values.............. 131
+ 11.4.11. Accounting-Realtime-Required AVP Values...... 131
+ 11.5. Diameter TCP/SCTP Port Numbers........................ 131
+ 11.6. NAPTR Service Fields.................................. 131
+ 12. Diameter Protocol Related Configurable Parameters............ 131
+ 13. Security Considerations...................................... 132
+ 13.1. IPsec Usage........................................... 133
+ 13.2. TLS Usage............................................. 134
+ 13.3. Peer-to-Peer Considerations........................... 134
+ 14. References................................................... 136
+ 14.1. Normative References.................................. 136
+ 14.2. Informative References................................ 138
+ 15. Acknowledgements............................................. 140
+ Appendix A. Diameter Service Template........................... 141
+ Appendix B. NAPTR Example....................................... 142
+ Appendix C. Duplicate Detection................................. 143
+
+
+
+Calhoun, et al. Standards Track [Page 5]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Appendix D. Intellectual Property Statement..................... 145
+ Authors' Addresses............................................... 146
+ Full Copyright Statement......................................... 147
+
+1. Introduction
+
+ Authentication, Authorization and Accounting (AAA) protocols such as
+ TACACS [TACACS] and RADIUS [RADIUS] were initially deployed to
+ provide dial-up PPP [PPP] and terminal server access. Over time,
+ with the growth of the Internet and the introduction of new access
+ technologies, including wireless, DSL, Mobile IP and Ethernet,
+ routers and network access servers (NAS) have increased in complexity
+ and density, putting new demands on AAA protocols.
+
+ Network access requirements for AAA protocols are summarized in
+ [AAAREQ]. These include:
+
+ Failover
+ [RADIUS] does not define failover mechanisms, and as a result,
+ failover behavior differs between implementations. In order to
+ provide well defined failover behavior, Diameter supports
+ application-layer acknowledgements, and defines failover
+ algorithms and the associated state machine. This is described in
+ Section 5.5 and [AAATRANS].
+
+ Transmission-level security
+ [RADIUS] defines an application-layer authentication and integrity
+ scheme that is required only for use with Response packets. While
+ [RADEXT] defines an additional authentication and integrity
+ mechanism, use is only required during Extensible Authentication
+ Protocol (EAP) sessions. While attribute-hiding is supported,
+ [RADIUS] does not provide support for per-packet confidentiality.
+ In accounting, [RADACCT] assumes that replay protection is
+ provided by the backend billing server, rather than within the
+ protocol itself.
+
+ While [RFC3162] defines the use of IPsec with RADIUS, support for
+ IPsec is not required. Since within [IKE] authentication occurs
+ only within Phase 1 prior to the establishment of IPsec SAs in
+ Phase 2, it is typically not possible to define separate trust or
+ authorization schemes for each application. This limits the
+ usefulness of IPsec in inter-domain AAA applications (such as
+ roaming) where it may be desirable to define a distinct
+ certificate hierarchy for use in a AAA deployment. In order to
+ provide universal support for transmission-level security, and
+ enable both intra- and inter-domain AAA deployments, IPsec support
+ is mandatory in Diameter, and TLS support is optional. Security
+ is discussed in Section 13.
+
+
+
+Calhoun, et al. Standards Track [Page 6]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Reliable transport
+ RADIUS runs over UDP, and does not define retransmission behavior;
+ as a result, reliability varies between implementations. As
+ described in [ACCMGMT], this is a major issue in accounting, where
+ packet loss may translate directly into revenue loss. In order to
+ provide well defined transport behavior, Diameter runs over
+ reliable transport mechanisms (TCP, SCTP) as defined in
+ [AAATRANS].
+
+ Agent support
+ [RADIUS] does not provide for explicit support for agents,
+ including Proxies, Redirects and Relays. Since the expected
+ behavior is not defined, it varies between implementations.
+ Diameter defines agent behavior explicitly; this is described in
+ Section 2.8.
+
+ Server-initiated messages
+ While RADIUS server-initiated messages are defined in [DYNAUTH],
+ support is optional. This makes it difficult to implement
+ features such as unsolicited disconnect or
+ reauthentication/reauthorization on demand across a heterogeneous
+ deployment. Support for server-initiated messages is mandatory in
+ Diameter, and is described in Section 8.
+
+ Auditability
+ RADIUS does not define data-object security mechanisms, and as a
+ result, untrusted proxies may modify attributes or even packet
+ headers without being detected. Combined with lack of support for
+ capabilities negotiation, this makes it very difficult to
+ determine what occurred in the event of a dispute. While
+ implementation of data object security is not mandatory within
+ Diameter, these capabilities are supported, and are described in
+ [AAACMS].
+
+ Transition support
+ While Diameter does not share a common protocol data unit (PDU)
+ with RADIUS, considerable effort has been expended in enabling
+ backward compatibility with RADIUS, so that the two protocols may
+ be deployed in the same network. Initially, it is expected that
+ Diameter will be deployed within new network devices, as well as
+ within gateways enabling communication between legacy RADIUS
+ devices and Diameter agents. This capability, described in
+ [NASREQ], enables Diameter support to be added to legacy networks,
+ by addition of a gateway or server speaking both RADIUS and
+ Diameter.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 7]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ In addition to addressing the above requirements, Diameter also
+ provides support for the following:
+
+ Capability negotiation
+ RADIUS does not support error messages, capability negotiation, or
+ a mandatory/non-mandatory flag for attributes. Since RADIUS
+ clients and servers are not aware of each other's capabilities,
+ they may not be able to successfully negotiate a mutually
+ acceptable service, or in some cases, even be aware of what
+ service has been implemented. Diameter includes support for error
+ handling (Section 7), capability negotiation (Section 5.3), and
+ mandatory/non-mandatory attribute-value pairs (AVPs) (Section
+ 4.1).
+
+ Peer discovery and configuration
+ RADIUS implementations typically require that the name or address
+ of servers or clients be manually configured, along with the
+ corresponding shared secrets. This results in a large
+ administrative burden, and creates the temptation to reuse the
+ RADIUS shared secret, which can result in major security
+ vulnerabilities if the Request Authenticator is not globally and
+ temporally unique as required in [RADIUS]. Through DNS, Diameter
+ enables dynamic discovery of peers. Derivation of dynamic session
+ keys is enabled via transmission-level security.
+
+ Roaming support
+ The ROAMOPS WG provided a survey of roaming implementations
+ [ROAMREV], detailed roaming requirements [ROAMCRIT], defined the
+ Network Access Identifier (NAI) [NAI], and documented existing
+ implementations (and imitations) of RADIUS-based roaming
+ [PROXYCHAIN]. In order to improve scalability, [PROXYCHAIN]
+ introduced the concept of proxy chaining via an intermediate
+ server, facilitating roaming between providers. However, since
+ RADIUS does not provide explicit support for proxies, and lacks
+ auditability and transmission-level security features, RADIUS-
+ based roaming is vulnerable to attack from external parties as
+ well as susceptible to fraud perpetrated by the roaming partners
+ themselves. As a result, it is not suitable for wide-scale
+ deployment on the Internet [PROXYCHAIN]. By providing explicit
+ support for inter-domain roaming and message routing (Sections 2.7
+ and 6), auditability [AAACMS], and transmission-layer security
+ (Section 13) features, Diameter addresses these limitations and
+ provides for secure and scalable roaming.
+
+ In the decade since AAA protocols were first introduced, the
+ capabilities of Network Access Server (NAS) devices have increased
+ substantially. As a result, while Diameter is a considerably more
+ sophisticated protocol than RADIUS, it remains feasible to implement
+
+
+
+Calhoun, et al. Standards Track [Page 8]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ within embedded devices, given improvements in processor speeds and
+ the widespread availability of embedded IPsec and TLS
+ implementations.
+
+1.1. Diameter Protocol
+
+ The Diameter base protocol provides the following facilities:
+
+ - Delivery of AVPs (attribute value pairs)
+ - Capabilities negotiation
+ - Error notification
+ - Extensibility, through addition of new commands and AVPs (required
+ in [AAAREQ]).
+ - Basic services necessary for applications, such as handling of
+ user sessions or accounting
+
+ All data delivered by the protocol is in the form of an AVP. Some of
+ these AVP values are used by the Diameter protocol itself, while
+ others deliver data associated with particular applications that
+ employ Diameter. AVPs may be added arbitrarily to Diameter messages,
+ so long as the required AVPs are included and AVPs that are
+ explicitly excluded are not included. AVPs are used by the base
+ Diameter protocol to support the following required features:
+
+ - Transporting of user authentication information, for the purposes
+ of enabling the Diameter server to authenticate the user.
+
+ - Transporting of service specific authorization information,
+ between client and servers, allowing the peers to decide whether a
+ user's access request should be granted.
+
+ - Exchanging resource usage information, which MAY be used for
+ accounting purposes, capacity planning, etc.
+
+ - Relaying, proxying and redirecting of Diameter messages through a
+ server hierarchy.
+
+ The Diameter base protocol provides the minimum requirements needed
+ for a AAA protocol, as required by [AAAREQ]. The base protocol may
+ be used by itself for accounting purposes only, or it may be used
+ with a Diameter application, such as Mobile IPv4 [DIAMMIP], or
+ network access [NASREQ]. It is also possible for the base protocol
+ to be extended for use in new applications, via the addition of new
+ commands or AVPs. At this time the focus of Diameter is network
+ access and accounting applications. A truly generic AAA protocol
+ used by many applications might provide functionality not provided by
+ Diameter. Therefore, it is imperative that the designers of new
+ applications understand their requirements before using Diameter.
+
+
+
+Calhoun, et al. Standards Track [Page 9]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ See Section 2.4 for more information on Diameter applications.
+
+ Any node can initiate a request. In that sense, Diameter is a peer-
+ to-peer protocol. In this document, a Diameter Client is a device at
+ the edge of the network that performs access control, such as a
+ Network Access Server (NAS) or a Foreign Agent (FA). A Diameter
+ client generates Diameter messages to request authentication,
+ authorization, and accounting services for the user. A Diameter
+ agent is a node that does not authenticate and/or authorize messages
+ locally; agents include proxies, redirects and relay agents. A
+ Diameter server performs authentication and/or authorization of the
+ user. A Diameter node MAY act as an agent for certain requests while
+ acting as a server for others.
+
+ The Diameter protocol also supports server-initiated messages, such
+ as a request to abort service to a particular user.
+
+1.1.1. Description of the Document Set
+
+ Currently, the Diameter specification consists of a base
+ specification (this document), Transport Profile [AAATRANS] and
+ applications: Mobile IPv4 [DIAMMIP], and NASREQ [NASREQ].
+
+ The Transport Profile document [AAATRANS] discusses transport layer
+ issues that arise with AAA protocols and recommendations on how to
+ overcome these issues. This document also defines the Diameter
+ failover algorithm and state machine.
+
+ The Mobile IPv4 [DIAMMIP] application defines a Diameter application
+ that allows a Diameter server to perform AAA functions for Mobile
+ IPv4 services to a mobile node.
+
+ The NASREQ [NASREQ] application defines a Diameter Application that
+ allows a Diameter server to be used in a PPP/SLIP Dial-Up and
+ Terminal Server Access environment. Consideration was given for
+ servers that need to perform protocol conversion between Diameter and
+ RADIUS.
+
+ In summary, this document defines the base protocol specification for
+ AAA, which includes support for accounting. The Mobile IPv4 and the
+ NASREQ documents describe applications that use this base
+ specification for Authentication, Authorization and Accounting.
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 10]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+1.2. Approach to Extensibility
+
+ The Diameter protocol is designed to be extensible, using several
+ mechanisms, including:
+
+ - Defining new AVP values
+ - Creating new AVPs
+ - Creating new authentication/authorization applications
+ - Creating new accounting applications
+ - Application authentication procedures
+
+ Reuse of existing AVP values, AVPs and Diameter applications are
+ strongly recommended. Reuse simplifies standardization and
+ implementation and avoids potential interoperability issues. It is
+ expected that command codes are reused; new command codes can only be
+ created by IETF Consensus (see Section 11.2.1).
+
+1.2.1. Defining New AVP Values
+
+ New applications should attempt to reuse AVPs defined in existing
+ applications when possible, as opposed to creating new AVPs. For
+ AVPs of type Enumerated, an application may require a new value to
+ communicate some service-specific information.
+
+ In order to allocate a new AVP value, a request MUST be sent to IANA
+ [IANA], along with an explanation of the new AVP value. IANA
+ considerations for Diameter are discussed in Section 11.
+
+1.2.2. Creating New AVPs
+
+ When no existing AVP can be used, a new AVP should be created. The
+ new AVP being defined MUST use one of the data types listed in
+ Section 4.2.
+
+ In the event that a logical grouping of AVPs is necessary, and
+ multiple "groups" are possible in a given command, it is recommended
+ that a Grouped AVP be used (see Section 4.4).
+
+ In order to create a new AVP, a request MUST be sent to IANA, with a
+ specification for the AVP. The request MUST include the commands
+ that would make use of the AVP.
+
+1.2.3. Creating New Authentication Applications
+
+ Every Diameter application specification MUST have an IANA assigned
+ Application Identifier (see Section 2.4) or a vendor specific
+ Application Identifier.
+
+
+
+
+Calhoun, et al. Standards Track [Page 11]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Should a new Diameter usage scenario find itself unable to fit within
+ an existing application without requiring major changes to the
+ specification, it may be desirable to create a new Diameter
+ application. Major changes to an application include:
+
+ - Adding new AVPs to the command, which have the "M" bit set.
+
+ - Requiring a command that has a different number of round trips to
+ satisfy a request (e.g., application foo has a command that
+ requires one round trip, but new application bar has a command
+ that requires two round trips to complete).
+
+ - Adding support for an authentication method requiring definition
+ of new AVPs for use with the application. Since a new EAP
+ authentication method can be supported within Diameter without
+ requiring new AVPs, addition of EAP methods does not require the
+ creation of a new authentication application.
+
+ Creation of a new application should be viewed as a last resort. An
+ implementation MAY add arbitrary non-mandatory AVPs to any command
+ defined in an application, including vendor-specific AVPs without
+ needing to define a new application. Please refer to Section 11.1.1
+ for details.
+
+ In order to justify allocation of a new application identifier,
+ Diameter applications MUST define one Command Code, or add new
+ mandatory AVPs to the ABNF.
+
+ The expected AVPs MUST be defined in an ABNF [ABNF] grammar (see
+ Section 3.2). If the Diameter application has accounting
+ requirements, it MUST also specify the AVPs that are to be present in
+ the Diameter Accounting messages (see Section 9.3). However, just
+ because a new authentication application id is required, does not
+ imply that a new accounting application id is required.
+
+ When possible, a new Diameter application SHOULD reuse existing
+ Diameter AVPs, in order to avoid defining multiple AVPs that carry
+ similar information.
+
+1.2.4. Creating New Accounting Applications
+
+ There are services that only require Diameter accounting. Such
+ services need to define the AVPs carried in the Accounting-Request
+ (ACR)/ Accounting-Answer (ACA) messages, but do not need to define
+ new command codes. An implementation MAY add arbitrary non-mandatory
+ AVPs (AVPs with the "M" bit not set) to any command defined in an
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 12]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ application, including vendor-specific AVPs, without needing to
+ define a new accounting application. Please refer to Section 11.1.1
+ for details.
+
+ Application Identifiers are still required for Diameter capability
+ exchange. Every Diameter accounting application specification MUST
+ have an IANA assigned Application Identifier (see Section 2.4) or a
+ vendor specific Application Identifier.
+
+ Every Diameter implementation MUST support accounting. Basic
+ accounting support is sufficient to handle any application that uses
+ the ACR/ACA commands defined in this document, as long as no new
+ mandatory AVPs are added. A mandatory AVP is defined as one which
+ has the "M" bit set when sent within an accounting command,
+ regardless of whether it is required or optional within the ABNF for
+ the accounting application.
+
+ The creation of a new accounting application should be viewed as a
+ last resort and MUST NOT be used unless a new command or additional
+ mechanisms (e.g., application defined state machine) is defined
+ within the application, or new mandatory AVPs are added to the ABNF.
+
+ Within an accounting command, setting the "M" bit implies that a
+ backend server (e.g., billing server) or the accounting server itself
+ MUST understand the AVP in order to compute a correct bill. If the
+ AVP is not relevant to the billing process, when the AVP is included
+ within an accounting command, it MUST NOT have the "M" bit set, even
+ if the "M" bit is set when the same AVP is used within other Diameter
+ commands (i.e., authentication/authorization commands).
+
+ A DIAMETER base accounting implementation MUST be configurable to
+ advertise supported accounting applications in order to prevent the
+ accounting server from accepting accounting requests for unbillable
+ services. The combination of the home domain and the accounting
+ application Id can be used in order to route the request to the
+ appropriate accounting server.
+
+ When possible, a new Diameter accounting application SHOULD attempt
+ to reuse existing AVPs, in order to avoid defining multiple AVPs that
+ carry similar information.
+
+ If the base accounting is used without any mandatory AVPs, new
+ commands or additional mechanisms (e.g., application defined state
+ machine), then the base protocol defined standard accounting
+ application Id (Section 2.4) MUST be used in ACR/ACA commands.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 13]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+1.2.5. Application Authentication Procedures
+
+ When possible, applications SHOULD be designed such that new
+ authentication methods MAY be added without requiring changes to the
+ application. This MAY require that new AVP values be assigned to
+ represent the new authentication transform, or any other scheme that
+ produces similar results. When possible, authentication frameworks,
+ such as Extensible Authentication Protocol [EAP], SHOULD be used.
+
+1.3. Terminology
+
+ AAA
+ Authentication, Authorization and Accounting.
+
+ Accounting
+ The act of collecting information on resource usage for the
+ purpose of capacity planning, auditing, billing or cost
+ allocation.
+
+ Accounting Record
+ An accounting record represents a summary of the resource
+ consumption of a user over the entire session. Accounting servers
+ creating the accounting record may do so by processing interim
+ accounting events or accounting events from several devices
+ serving the same user.
+
+ Authentication
+ The act of verifying the identity of an entity (subject).
+
+ Authorization
+ The act of determining whether a requesting entity (subject) will
+ be allowed access to a resource (object).
+
+ AVP
+ The Diameter protocol consists of a header followed by one or more
+ Attribute-Value-Pairs (AVPs). An AVP includes a header and is
+ used to encapsulate protocol-specific data (e.g., routing
+ information) as well as authentication, authorization or
+ accounting information.
+
+ Broker
+ A broker is a business term commonly used in AAA infrastructures.
+ A broker is either a relay, proxy or redirect agent, and MAY be
+ operated by roaming consortiums. Depending on the business model,
+ a broker may either choose to deploy relay agents or proxy
+ agents.
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 14]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Diameter Agent
+ A Diameter Agent is a Diameter node that provides either relay,
+ proxy, redirect or translation services.
+
+ Diameter Client
+ A Diameter Client is a device at the edge of the network that
+ performs access control. An example of a Diameter client is a
+ Network Access Server (NAS) or a Foreign Agent (FA).
+
+ Diameter Node
+ A Diameter node is a host process that implements the Diameter
+ protocol, and acts either as a Client, Agent or Server.
+
+ Diameter Peer
+ A Diameter Peer is a Diameter Node to which a given Diameter Node
+ has a direct transport connection.
+
+ Diameter Security Exchange
+ A Diameter Security Exchange is a process through which two
+ Diameter nodes establish end-to-end security.
+
+ Diameter Server
+ A Diameter Server is one that handles authentication,
+ authorization and accounting requests for a particular realm. By
+ its very nature, a Diameter Server MUST support Diameter
+ applications in addition to the base protocol.
+
+ Downstream
+ Downstream is used to identify the direction of a particular
+ Diameter message from the home server towards the access device.
+
+ End-to-End Security
+ TLS and IPsec provide hop-by-hop security, or security across a
+ transport connection. When relays or proxy are involved, this
+ hop-by-hop security does not protect the entire Diameter user
+ session. End-to-end security is security between two Diameter
+ nodes, possibly communicating through Diameter Agents. This
+ security protects the entire Diameter communications path from the
+ originating Diameter node to the terminating Diameter node.
+
+ Home Realm
+ A Home Realm is the administrative domain with which the user
+ maintains an account relationship.
+
+ Home Server
+ See Diameter Server.
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 15]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Interim accounting
+ An interim accounting message provides a snapshot of usage during
+ a user's session. It is typically implemented in order to provide
+ for partial accounting of a user's session in the case of a device
+ reboot or other network problem prevents the reception of a
+ session summary message or session record.
+
+ Local Realm
+ A local realm is the administrative domain providing services to a
+ user. An administrative domain MAY act as a local realm for
+ certain users, while being a home realm for others.
+
+ Multi-session
+ A multi-session represents a logical linking of several sessions.
+ Multi-sessions are tracked by using the Acct-Multi-Session-Id. An
+ example of a multi-session would be a Multi-link PPP bundle. Each
+ leg of the bundle would be a session while the entire bundle would
+ be a multi-session.
+
+ Network Access Identifier
+ The Network Access Identifier, or NAI [NAI], is used in the
+ Diameter protocol to extract a user's identity and realm. The
+ identity is used to identify the user during authentication and/or
+ authorization, while the realm is used for message routing
+ purposes.
+
+ Proxy Agent or Proxy
+ In addition to forwarding requests and responses, proxies make
+ policy decisions relating to resource usage and provisioning.
+ This is typically accomplished by tracking the state of NAS
+ devices. While proxies typically do not respond to client
+ Requests prior to receiving a Response from the server, they may
+ originate Reject messages in cases where policies are violated.
+ As a result, proxies need to understand the semantics of the
+ messages passing through them, and may not support all Diameter
+ applications.
+
+ Realm
+ The string in the NAI that immediately follows the '@' character.
+ NAI realm names are required to be unique, and are piggybacked on
+ the administration of the DNS namespace. Diameter makes use of
+ the realm, also loosely referred to as domain, to determine
+ whether messages can be satisfied locally, or whether they must be
+ routed or redirected. In RADIUS, realm names are not necessarily
+ piggybacked on the DNS namespace but may be independent of it.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 16]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Real-time Accounting
+ Real-time accounting involves the processing of information on
+ resource usage within a defined time window. Time constraints are
+ typically imposed in order to limit financial risk.
+
+ Relay Agent or Relay
+ Relays forward requests and responses based on routing-related
+ AVPs and realm routing table entries. Since relays do not make
+ policy decisions, they do not examine or alter non-routing AVPs.
+ As a result, relays never originate messages, do not need to
+ understand the semantics of messages or non-routing AVPs, and are
+ capable of handling any Diameter application or message type.
+ Since relays make decisions based on information in routing AVPs
+ and realm forwarding tables they do not keep state on NAS resource
+ usage or sessions in progress.
+
+ Redirect Agent
+ Rather than forwarding requests and responses between clients and
+ servers, redirect agents refer clients to servers and allow them
+ to communicate directly. Since redirect agents do not sit in the
+ forwarding path, they do not alter any AVPs transiting between
+ client and server. Redirect agents do not originate messages and
+ are capable of handling any message type, although they may be
+ configured only to redirect messages of certain types, while
+ acting as relay or proxy agents for other types. As with proxy
+ agents, redirect agents do not keep state with respect to sessions
+ or NAS resources.
+
+ Roaming Relationships
+ Roaming relationships include relationships between companies and
+ ISPs, relationships among peer ISPs within a roaming consortium,
+ and relationships between an ISP and a roaming consortium.
+
+ Security Association
+ A security association is an association between two endpoints in
+ a Diameter session which allows the endpoints to communicate with
+ integrity and confidentially, even in the presence of relays
+ and/or proxies.
+
+ Session
+ A session is a related progression of events devoted to a
+ particular activity. Each application SHOULD provide guidelines
+ as to when a session begins and ends. All Diameter packets with
+ the same Session-Identifier are considered to be part of the same
+ session.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 17]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Session state
+ A stateful agent is one that maintains session state information,
+ by keeping track of all authorized active sessions. Each
+ authorized session is bound to a particular service, and its state
+ is considered active either until it is notified otherwise, or by
+ expiration.
+
+ Sub-session
+ A sub-session represents a distinct service (e.g., QoS or data
+ characteristics) provided to a given session. These services may
+ happen concurrently (e.g., simultaneous voice and data transfer
+ during the same session) or serially. These changes in sessions
+ are tracked with the Accounting-Sub-Session-Id.
+
+ Transaction state
+ The Diameter protocol requires that agents maintain transaction
+ state, which is used for failover purposes. Transaction state
+ implies that upon forwarding a request, the Hop-by-Hop identifier
+ is saved; the field is replaced with a locally unique identifier,
+ which is restored to its original value when the corresponding
+ answer is received. The request's state is released upon receipt
+ of the answer. A stateless agent is one that only maintains
+ transaction state.
+
+ Translation Agent
+ A translation agent is a stateful Diameter node that performs
+ protocol translation between Diameter and another AAA protocol,
+ such as RADIUS.
+
+ Transport Connection
+ A transport connection is a TCP or SCTP connection existing
+ directly between two Diameter peers, otherwise known as a Peer-
+ to-Peer Connection.
+
+ Upstream
+ Upstream is used to identify the direction of a particular
+ Diameter message from the access device towards the home server.
+
+ User
+ The entity requesting or using some resource, in support of which
+ a Diameter client has generated a request.
+
+2. Protocol Overview
+
+ The base Diameter protocol may be used by itself for accounting
+ applications, but for use in authentication and authorization it is
+ always extended for a particular application. Two Diameter
+ applications are defined by companion documents: NASREQ [NASREQ],
+
+
+
+Calhoun, et al. Standards Track [Page 18]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Mobile IPv4 [DIAMMIP]. These applications are introduced in this
+ document but specified elsewhere. Additional Diameter applications
+ MAY be defined in the future (see Section 11.3).
+
+ Diameter Clients MUST support the base protocol, which includes
+ accounting. In addition, they MUST fully support each Diameter
+ application that is needed to implement the client's service, e.g.,
+ NASREQ and/or Mobile IPv4. A Diameter Client that does not support
+ both NASREQ and Mobile IPv4, MUST be referred to as "Diameter X
+ Client" where X is the application which it supports, and not a
+ "Diameter Client".
+
+ Diameter Servers MUST support the base protocol, which includes
+ accounting. In addition, they MUST fully support each Diameter
+ application that is needed to implement the intended service, e.g.,
+ NASREQ and/or Mobile IPv4. A Diameter Server that does not support
+ both NASREQ and Mobile IPv4, MUST be referred to as "Diameter X
+ Server" where X is the application which it supports, and not a
+ "Diameter Server".
+
+ Diameter Relays and redirect agents are, by definition, protocol
+ transparent, and MUST transparently support the Diameter base
+ protocol, which includes accounting, and all Diameter applications.
+
+ Diameter proxies MUST support the base protocol, which includes
+ accounting. In addition, they MUST fully support each Diameter
+ application that is needed to implement proxied services, e.g.,
+ NASREQ and/or Mobile IPv4. A Diameter proxy which does not support
+ also both NASREQ and Mobile IPv4, MUST be referred to as "Diameter X
+ Proxy" where X is the application which it supports, and not a
+ "Diameter Proxy".
+
+ The base Diameter protocol concerns itself with capabilities
+ negotiation, how messages are sent and how peers may eventually be
+ abandoned. The base protocol also defines certain rules that apply
+ to all exchanges of messages between Diameter nodes.
+
+ Communication between Diameter peers begins with one peer sending a
+ message to another Diameter peer. The set of AVPs included in the
+ message is determined by a particular Diameter application. One AVP
+ that is included to reference a user's session is the Session-Id.
+
+ The initial request for authentication and/or authorization of a user
+ would include the Session-Id. The Session-Id is then used in all
+ subsequent messages to identify the user's session (see Section 8 for
+ more information). The communicating party may accept the request,
+ or reject it by returning an answer message with the Result-Code AVP
+
+
+
+
+Calhoun, et al. Standards Track [Page 19]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ set to indicate an error occurred. The specific behavior of the
+ Diameter server or client receiving a request depends on the Diameter
+ application employed.
+
+ Session state (associated with a Session-Id) MUST be freed upon
+ receipt of the Session-Termination-Request, Session-Termination-
+ Answer, expiration of authorized service time in the Session-Timeout
+ AVP, and according to rules established in a particular Diameter
+ application.
+
+2.1. Transport
+
+ Transport profile is defined in [AAATRANS].
+
+ The base Diameter protocol is run on port 3868 of both TCP [TCP] and
+ SCTP [SCTP] transport protocols.
+
+ Diameter clients MUST support either TCP or SCTP, while agents and
+ servers MUST support both. Future versions of this specification MAY
+ mandate that clients support SCTP.
+
+ A Diameter node MAY initiate connections from a source port other
+ than the one that it declares it accepts incoming connections on, and
+ MUST be prepared to receive connections on port 3868. A given
+ Diameter instance of the peer state machine MUST NOT use more than
+ one transport connection to communicate with a given peer, unless
+ multiple instances exist on the peer in which case a separate
+ connection per process is allowed.
+
+ When no transport connection exists with a peer, an attempt to
+ connect SHOULD be periodically made. This behavior is handled via
+ the Tc timer, whose recommended value is 30 seconds. There are
+ certain exceptions to this rule, such as when a peer has terminated
+ the transport connection stating that it does not wish to
+ communicate.
+
+ When connecting to a peer and either zero or more transports are
+ specified, SCTP SHOULD be tried first, followed by TCP. See Section
+ 5.2 for more information on peer discovery.
+
+ Diameter implementations SHOULD be able to interpret ICMP protocol
+ port unreachable messages as explicit indications that the server is
+ not reachable, subject to security policy on trusting such messages.
+ Diameter implementations SHOULD also be able to interpret a reset
+ from the transport and timed-out connection attempts.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 20]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ If Diameter receives data up from TCP that cannot be parsed or
+ identified as a Diameter error made by the peer, the stream is
+ compromised and cannot be recovered. The transport connection MUST
+ be closed using a RESET call (send a TCP RST bit) or an SCTP ABORT
+ message (graceful closure is compromised).
+
+2.1.1. SCTP Guidelines
+
+ The following are guidelines for Diameter implementations that
+ support SCTP:
+
+ 1. For interoperability: All Diameter nodes MUST be prepared to
+ receive Diameter messages on any SCTP stream in the association.
+
+ 2. To prevent blocking: All Diameter nodes SHOULD utilize all SCTP
+ streams available to the association to prevent head-of-the-line
+ blocking.
+
+2.2. Securing Diameter Messages
+
+ Diameter clients, such as Network Access Servers (NASes) and Mobility
+ Agents MUST support IP Security [SECARCH], and MAY support TLS [TLS].
+ Diameter servers MUST support TLS and IPsec. The Diameter protocol
+ MUST NOT be used without any security mechanism (TLS or IPsec).
+
+ It is suggested that IPsec can be used primarily at the edges and in
+ intra-domain traffic, such as using pre-shared keys between a NAS a
+ local AAA proxy. This also eases the requirements on the NAS to
+ support certificates. It is also suggested that inter-domain traffic
+ would primarily use TLS. See Sections 13.1 and 13.2 for more details
+ on IPsec and TLS usage.
+
+2.3. Diameter Application Compliance
+
+ Application Identifiers are advertised during the capabilities
+ exchange phase (see Section 5.3). For a given application,
+ advertising support of an application implies that the sender
+ supports all command codes, and the AVPs specified in the associated
+ ABNFs, described in the specification.
+
+ An implementation MAY add arbitrary non-mandatory AVPs to any command
+ defined in an application, including vendor-specific AVPs. Please
+ refer to Section 11.1.1 for details.
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 21]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+2.4. Application Identifiers
+
+ Each Diameter application MUST have an IANA assigned Application
+ Identifier (see Section 11.3). The base protocol does not require an
+ Application Identifier since its support is mandatory. During the
+ capabilities exchange, Diameter nodes inform their peers of locally
+ supported applications. Furthermore, all Diameter messages contain
+ an Application Identifier, which is used in the message forwarding
+ process.
+
+ The following Application Identifier values are defined:
+
+ Diameter Common Messages 0
+ NASREQ 1 [NASREQ]
+ Mobile-IP 2 [DIAMMIP]
+ Diameter Base Accounting 3
+ Relay 0xffffffff
+
+ Relay and redirect agents MUST advertise the Relay Application
+ Identifier, while all other Diameter nodes MUST advertise locally
+ supported applications. The receiver of a Capabilities Exchange
+ message advertising Relay service MUST assume that the sender
+ supports all current and future applications.
+
+ Diameter relay and proxy agents are responsible for finding an
+ upstream server that supports the application of a particular
+ message. If none can be found, an error message is returned with the
+ Result-Code AVP set to DIAMETER_UNABLE_TO_DELIVER.
+
+2.5. Connections vs. Sessions
+
+ This section attempts to provide the reader with an understanding of
+ the difference between connection and session, which are terms used
+ extensively throughout this document.
+
+ A connection is a transport level connection between two peers, used
+ to send and receive Diameter messages. A session is a logical
+ concept at the application layer, and is shared between an access
+ device and a server, and is identified via the Session-Id AVP
+
+
+
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 22]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ +--------+ +-------+ +--------+
+ | Client | | Relay | | Server |
+ +--------+ +-------+ +--------+
+ <----------> <---------->
+ peer connection A peer connection B
+
+ <----------------------------->
+ User session x
+
+ Figure 1: Diameter connections and sessions
+
+ In the example provided in Figure 1, peer connection A is established
+ between the Client and its local Relay. Peer connection B is
+ established between the Relay and the Server. User session X spans
+ from the Client via the Relay to the Server. Each "user" of a
+ service causes an auth request to be sent, with a unique session
+ identifier. Once accepted by the server, both the client and the
+ server are aware of the session. It is important to note that there
+ is no relationship between a connection and a session, and that
+ Diameter messages for multiple sessions are all multiplexed through a
+ single connection.
+
+2.6. Peer Table
+
+ The Diameter Peer Table is used in message forwarding, and referenced
+ by the Realm Routing Table. A Peer Table entry contains the
+ following fields:
+
+ Host identity
+ Following the conventions described for the DiameterIdentity
+ derived AVP data format in Section 4.4. This field contains the
+ contents of the Origin-Host (Section 6.3) AVP found in the CER or
+ CEA message.
+
+ StatusT
+ This is the state of the peer entry, and MUST match one of the
+ values listed in Section 5.6.
+
+ Static or Dynamic
+ Specifies whether a peer entry was statically configured, or
+ dynamically discovered.
+
+ Expiration time
+ Specifies the time at which dynamically discovered peer table
+ entries are to be either refreshed, or expired.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 23]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ TLS Enabled
+ Specifies whether TLS is to be used when communicating with the
+ peer.
+
+ Additional security information, when needed (e.g., keys,
+ certificates)
+
+2.7. Realm-Based Routing Table
+
+ All Realm-Based routing lookups are performed against what is
+ commonly known as the Realm Routing Table (see Section 12). A Realm
+ Routing Table Entry contains the following fields:
+
+ Realm Name
+ This is the field that is typically used as a primary key in the
+ routing table lookups. Note that some implementations perform
+ their lookups based on longest-match-from-the-right on the realm
+ rather than requiring an exact match.
+
+ Application Identifier
+ An application is identified by a vendor id and an application id.
+ For all IETF standards track Diameter applications, the vendor id
+ is zero. A route entry can have a different destination based on
+ the application identification AVP of the message. This field
+ MUST be used as a secondary key field in routing table lookups.
+
+ Local Action
+ The Local Action field is used to identify how a message should be
+ treated. The following actions are supported:
+
+ 1. LOCAL - Diameter messages that resolve to a route entry with
+ the Local Action set to Local can be satisfied locally, and do
+ not need to be routed to another server.
+
+ 2. RELAY - All Diameter messages that fall within this category
+ MUST be routed to a next hop server, without modifying any
+ non-routing AVPs. See Section 6.1.8 for relaying guidelines
+
+ 3. PROXY - All Diameter messages that fall within this category
+ MUST be routed to a next hop server. The local server MAY
+ apply its local policies to the message by including new AVPs
+ to the message prior to routing. See Section 6.1.8 for
+ proxying guidelines.
+
+ 4. REDIRECT - Diameter messages that fall within this category
+ MUST have the identity of the home Diameter server(s) appended,
+ and returned to the sender of the message. See Section 6.1.7
+ for redirect guidelines.
+
+
+
+Calhoun, et al. Standards Track [Page 24]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Server Identifier
+ One or more servers the message is to be routed to. These servers
+ MUST also be present in the Peer table. When the Local Action is
+ set to RELAY or PROXY, this field contains the identity of the
+ server(s) the message must be routed to. When the Local Action
+ field is set to REDIRECT, this field contains the identity of one
+ or more servers the message should be redirected to.
+
+ Static or Dynamic
+ Specifies whether a route entry was statically configured, or
+ dynamically discovered.
+
+ Expiration time
+ Specifies the time which a dynamically discovered route table
+ entry expires.
+
+ It is important to note that Diameter agents MUST support at least
+ one of the LOCAL, RELAY, PROXY or REDIRECT modes of operation.
+ Agents do not need to support all modes of operation in order to
+ conform with the protocol specification, but MUST follow the protocol
+ compliance guidelines in Section 2. Relay agents MUST NOT reorder
+ AVPs, and proxies MUST NOT reorder AVPs.
+
+ The routing table MAY include a default entry that MUST be used for
+ any requests not matching any of the other entries. The routing
+ table MAY consist of only such an entry.
+
+ When a request is routed, the target server MUST have advertised the
+ Application Identifier (see Section 2.4) for the given message, or
+ have advertised itself as a relay or proxy agent. Otherwise, an
+ error is returned with the Result-Code AVP set to
+ DIAMETER_UNABLE_TO_DELIVER.
+
+2.8. Role of Diameter Agents
+
+ In addition to client and servers, the Diameter protocol introduces
+ relay, proxy, redirect, and translation agents, each of which is
+ defined in Section 1.3. These Diameter agents are useful for several
+ reasons:
+
+ - They can distribute administration of systems to a configurable
+ grouping, including the maintenance of security associations.
+
+ - They can be used for concentration of requests from an number of
+ co-located or distributed NAS equipment sets to a set of like user
+ groups.
+
+ - They can do value-added processing to the requests or responses.
+
+
+
+Calhoun, et al. Standards Track [Page 25]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ - They can be used for load balancing.
+
+ - A complex network will have multiple authentication sources, they
+ can sort requests and forward towards the correct target.
+
+ The Diameter protocol requires that agents maintain transaction
+ state, which is used for failover purposes. Transaction state
+ implies that upon forwarding a request, its Hop-by-Hop identifier is
+ saved; the field is replaced with a locally unique identifier, which
+ is restored to its original value when the corresponding answer is
+ received. The request's state is released upon receipt of the
+ answer. A stateless agent is one that only maintains transaction
+ state.
+
+ The Proxy-Info AVP allows stateless agents to add local state to a
+ Diameter request, with the guarantee that the same state will be
+ present in the answer. However, the protocol's failover procedures
+ require that agents maintain a copy of pending requests.
+
+ A stateful agent is one that maintains session state information; by
+ keeping track of all authorized active sessions. Each authorized
+ session is bound to a particular service, and its state is considered
+ active either until it is notified otherwise, or by expiration. Each
+ authorized session has an expiration, which is communicated by
+ Diameter servers via the Session-Timeout AVP.
+
+ Maintaining session state MAY be useful in certain applications, such
+ as:
+
+ - Protocol translation (e.g., RADIUS <-> Diameter)
+
+ - Limiting resources authorized to a particular user
+
+ - Per user or transaction auditing
+
+ A Diameter agent MAY act in a stateful manner for some requests and
+ be stateless for others. A Diameter implementation MAY act as one
+ type of agent for some requests, and as another type of agent for
+ others.
+
+2.8.1. Relay Agents
+
+ Relay Agents are Diameter agents that accept requests and route
+ messages to other Diameter nodes based on information found in the
+ messages (e.g., Destination-Realm). This routing decision is
+ performed using a list of supported realms, and known peers. This is
+ known as the Realm Routing Table, as is defined further in Section
+ 2.7.
+
+
+
+Calhoun, et al. Standards Track [Page 26]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Relays MAY be used to aggregate requests from multiple Network Access
+ Servers (NASes) within a common geographical area (POP). The use of
+ Relays is advantageous since it eliminates the need for NASes to be
+ configured with the necessary security information they would
+ otherwise require to communicate with Diameter servers in other
+ realms. Likewise, this reduces the configuration load on Diameter
+ servers that would otherwise be necessary when NASes are added,
+ changed or deleted.
+
+ Relays modify Diameter messages by inserting and removing routing
+ information, but do not modify any other portion of a message.
+ Relays SHOULD NOT maintain session state but MUST maintain
+ transaction state.
+
+ +------+ ---------> +------+ ---------> +------+
+ | | 1. Request | | 2. Request | |
+ | NAS | | DRL | | HMS |
+ | | 4. Answer | | 3. Answer | |
+ +------+ <--------- +------+ <--------- +------+
+ example.net example.net example.com
+
+ Figure 2: Relaying of Diameter messages
+
+ The example provided in Figure 2 depicts a request issued from NAS,
+ which is an access device, for the user [email protected]. Prior to
+ issuing the request, NAS performs a Diameter route lookup, using
+ "example.com" as the key, and determines that the message is to be
+ relayed to DRL, which is a Diameter Relay. DRL performs the same
+ route lookup as NAS, and relays the message to HMS, which is
+ example.com's Home Diameter Server. HMS identifies that the request
+ can be locally supported (via the realm), processes the
+ authentication and/or authorization request, and replies with an
+ answer, which is routed back to NAS using saved transaction state.
+
+ Since Relays do not perform any application level processing, they
+ provide relaying services for all Diameter applications, and
+ therefore MUST advertise the Relay Application Identifier.
+
+2.8.2. Proxy Agents
+
+ Similarly to relays, proxy agents route Diameter messages using the
+ Diameter Routing Table. However, they differ since they modify
+ messages to implement policy enforcement. This requires that proxies
+ maintain the state of their downstream peers (e.g., access devices)
+ to enforce resource usage, provide admission control, and
+ provisioning.
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 27]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ It is important to note that although proxies MAY provide a value-add
+ function for NASes, they do not allow access devices to use end-to-
+ end security, since modifying messages breaks authentication.
+
+ Proxies MAY be used in call control centers or access ISPs that
+ provide outsourced connections, they can monitor the number and types
+ of ports in use, and make allocation and admission decisions
+ according to their configuration.
+
+ Proxies that wish to limit resources MUST maintain session state.
+ All proxies MUST maintain transaction state.
+
+ Since enforcing policies requires an understanding of the service
+ being provided, Proxies MUST only advertise the Diameter applications
+ they support.
+
+2.8.3. Redirect Agents
+
+ Redirect agents are useful in scenarios where the Diameter routing
+ configuration needs to be centralized. An example is a redirect
+ agent that provides services to all members of a consortium, but does
+ not wish to be burdened with relaying all messages between realms.
+ This scenario is advantageous since it does not require that the
+ consortium provide routing updates to its members when changes are
+ made to a member's infrastructure.
+
+ Since redirect agents do not relay messages, and only return an
+ answer with the information necessary for Diameter agents to
+ communicate directly, they do not modify messages. Since redirect
+ agents do not receive answer messages, they cannot maintain session
+ state. Further, since redirect agents never relay requests, they are
+ not required to maintain transaction state.
+
+ The example provided in Figure 3 depicts a request issued from the
+ access device, NAS, for the user [email protected]. The message is
+ forwarded by the NAS to its relay, DRL, which does not have a routing
+ entry in its Diameter Routing Table for example.com. DRL has a
+ default route configured to DRD, which is a redirect agent that
+ returns a redirect notification to DRL, as well as HMS' contact
+ information. Upon receipt of the redirect notification, DRL
+ establishes a transport connection with HMS, if one doesn't already
+ exist, and forwards the request to it.
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 28]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ +------+
+ | |
+ | DRD |
+ | |
+ +------+
+ ^ |
+ 2. Request | | 3. Redirection
+ | | Notification
+ | v
+ +------+ ---------> +------+ ---------> +------+
+ | | 1. Request | | 4. Request | |
+ | NAS | | DRL | | HMS |
+ | | 6. Answer | | 5. Answer | |
+ +------+ <--------- +------+ <--------- +------+
+ example.net example.net example.com
+
+ Figure 3: Redirecting a Diameter Message
+
+ Since redirect agents do not perform any application level
+ processing, they provide relaying services for all Diameter
+ applications, and therefore MUST advertise the Relay Application
+ Identifier.
+
+2.8.4. Translation Agents
+
+ A translation agent is a device that provides translation between two
+ protocols (e.g., RADIUS<->Diameter, TACACS+<->Diameter). Translation
+ agents are likely to be used as aggregation servers to communicate
+ with a Diameter infrastructure, while allowing for the embedded
+ systems to be migrated at a slower pace.
+
+ Given that the Diameter protocol introduces the concept of long-lived
+ authorized sessions, translation agents MUST be session stateful and
+ MUST maintain transaction state.
+
+ Translation of messages can only occur if the agent recognizes the
+ application of a particular request, and therefore translation agents
+ MUST only advertise their locally supported applications.
+
+ +------+ ---------> +------+ ---------> +------+
+ | | RADIUS Request | | Diameter Request | |
+ | NAS | | TLA | | HMS |
+ | | RADIUS Answer | | Diameter Answer | |
+ +------+ <--------- +------+ <--------- +------+
+ example.net example.net example.com
+
+ Figure 4: Translation of RADIUS to Diameter
+
+
+
+
+Calhoun, et al. Standards Track [Page 29]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+2.9. End-to-End Security Framework
+
+ End-to-end security services include confidentiality and message
+ origin authentication. These services are provided by supporting AVP
+ integrity and confidentiality between two peers, communicating
+ through agents.
+
+ End-to-end security is provided via the End-to-End security
+ extension, described in [AAACMS]. The circumstances requiring the
+ use of end-to-end security are determined by policy on each of the
+ peers. Security policies, which are not the subject of
+ standardization, may be applied by next hop Diameter peer or by
+ destination realm. For example, where TLS or IPsec transmission-
+ level security is sufficient, there may be no need for end-to-end
+ security.
+
+ End-to-end security policies include:
+
+ - Never use end-to-end security.
+
+ - Use end-to-end security on messages containing sensitive AVPs.
+ Which AVPs are sensitive is determined by service provider policy.
+ AVPs containing keys and passwords should be considered sensitive.
+ Accounting AVPs may be considered sensitive. Any AVP for which
+ the P bit may be set or which may be encrypted may be considered
+ sensitive.
+
+ - Always use end-to-end security.
+
+ It is strongly RECOMMENDED that all Diameter implementations support
+ end-to-end security.
+
+2.10. Diameter Path Authorization
+
+ As noted in Section 2.2, Diameter requires transmission level
+ security to be used on each connection (TLS or IPsec). Therefore,
+ each connection is authenticated, replay and integrity protected and
+ confidential on a per-packet basis.
+
+ In addition to authenticating each connection, each connection as
+ well as the entire session MUST also be authorized. Before
+ initiating a connection, a Diameter Peer MUST check that its peers
+ are authorized to act in their roles. For example, a Diameter peer
+ may be authentic, but that does not mean that it is authorized to act
+ as a Diameter Server advertising a set of Diameter applications.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 30]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Prior to bringing up a connection, authorization checks are performed
+ at each connection along the path. Diameter capabilities negotiation
+ (CER/CEA) also MUST be carried out, in order to determine what
+ Diameter applications are supported by each peer. Diameter sessions
+ MUST be routed only through authorized nodes that have advertised
+ support for the Diameter application required by the session.
+
+ As noted in Section 6.1.8, a relay or proxy agent MUST append a
+ Route-Record AVP to all requests forwarded. The AVP contains the
+ identity of the peer the request was received from.
+
+ The home Diameter server, prior to authorizing a session, MUST check
+ the Route-Record AVPs to make sure that the route traversed by the
+ request is acceptable. For example, administrators within the home
+ realm may not wish to honor requests that have been routed through an
+ untrusted realm. By authorizing a request, the home Diameter server
+ is implicitly indicating its willingness to engage in the business
+ transaction as specified by the contractual relationship between the
+ server and the previous hop. A DIAMETER_AUTHORIZATION_REJECTED error
+ message (see Section 7.1.5) is sent if the route traversed by the
+ request is unacceptable.
+
+ A home realm may also wish to check that each accounting request
+ message corresponds to a Diameter response authorizing the session.
+ Accounting requests without corresponding authorization responses
+ SHOULD be subjected to further scrutiny, as should accounting
+ requests indicating a difference between the requested and provided
+ service.
+
+ Similarly, the local Diameter agent, on receiving a Diameter response
+ authorizing a session, MUST check the Route-Record AVPs to make sure
+ that the route traversed by the response is acceptable. At each
+ step, forwarding of an authorization response is considered evidence
+ of a willingness to take on financial risk relative to the session.
+ A local realm may wish to limit this exposure, for example, by
+ establishing credit limits for intermediate realms and refusing to
+ accept responses which would violate those limits. By issuing an
+ accounting request corresponding to the authorization response, the
+ local realm implicitly indicates its agreement to provide the service
+ indicated in the authorization response. If the service cannot be
+ provided by the local realm, then a DIAMETER_UNABLE_TO_COMPLY error
+ message MUST be sent within the accounting request; a Diameter client
+ receiving an authorization response for a service that it cannot
+ perform MUST NOT substitute an alternate service, and then send
+ accounting requests for the alternate service instead.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 31]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+3. Diameter Header
+
+ A summary of the Diameter header format is shown below. The fields
+ are transmitted in network byte order.
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version | Message Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | command flags | Command-Code |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Application-ID |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Hop-by-Hop Identifier |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | End-to-End Identifier |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | AVPs ...
+ +-+-+-+-+-+-+-+-+-+-+-+-+-
+
+ Version
+ This Version field MUST be set to 1 to indicate Diameter Version
+ 1.
+
+ Message Length
+ The Message Length field is three octets and indicates the length
+ of the Diameter message including the header fields.
+
+ Command Flags
+ The Command Flags field is eight bits. The following bits are
+ assigned:
+
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+
+ |R P E T r r r r|
+ +-+-+-+-+-+-+-+-+
+
+ R(equest) - If set, the message is a request. If cleared, the
+ message is an answer.
+ P(roxiable) - If set, the message MAY be proxied, relayed or
+ redirected. If cleared, the message MUST be
+ locally processed.
+ E(rror) - If set, the message contains a protocol error,
+ and the message will not conform to the ABNF
+ described for this command. Messages with the 'E'
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 32]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ bit set are commonly referred to as error
+ messages. This bit MUST NOT be set in request
+ messages. See Section 7.2.
+ T(Potentially re-transmitted message)
+ - This flag is set after a link failover procedure,
+ to aid the removal of duplicate requests. It is
+ set when resending requests not yet acknowledged,
+ as an indication of a possible duplicate due to a
+ link failure. This bit MUST be cleared when
+ sending a request for the first time, otherwise
+ the sender MUST set this flag. Diameter agents
+ only need to be concerned about the number of
+ requests they send based on a single received
+ request; retransmissions by other entities need
+ not be tracked. Diameter agents that receive a
+ request with the T flag set, MUST keep the T flag
+ set in the forwarded request. This flag MUST NOT
+ be set if an error answer message (e.g., a
+ protocol error) has been received for the earlier
+ message. It can be set only in cases where no
+ answer has been received from the server for a
+ request and the request is sent again. This flag
+ MUST NOT be set in answer messages.
+
+ r(eserved) - these flag bits are reserved for future use, and
+ MUST be set to zero, and ignored by the receiver.
+
+ Command-Code
+ The Command-Code field is three octets, and is used in order to
+ communicate the command associated with the message. The 24-bit
+ address space is managed by IANA (see Section 11.2.1).
+
+ Command-Code values 16,777,214 and 16,777,215 (hexadecimal values
+ FFFFFE -FFFFFF) are reserved for experimental use (See Section
+ 11.3).
+
+ Application-ID
+ Application-ID is four octets and is used to identify to which
+ application the message is applicable for. The application can be
+ an authentication application, an accounting application or a
+ vendor specific application. See Section 11.3 for the possible
+ values that the application-id may use.
+
+ The application-id in the header MUST be the same as what is
+ contained in any relevant AVPs contained in the message.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 33]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Hop-by-Hop Identifier
+ The Hop-by-Hop Identifier is an unsigned 32-bit integer field (in
+ network byte order) and aids in matching requests and replies.
+ The sender MUST ensure that the Hop-by-Hop identifier in a request
+ is unique on a given connection at any given time, and MAY attempt
+ to ensure that the number is unique across reboots. The sender of
+ an Answer message MUST ensure that the Hop-by-Hop Identifier field
+ contains the same value that was found in the corresponding
+ request. The Hop-by-Hop identifier is normally a monotonically
+ increasing number, whose start value was randomly generated. An
+ answer message that is received with an unknown Hop-by-Hop
+ Identifier MUST be discarded.
+
+ End-to-End Identifier
+ The End-to-End Identifier is an unsigned 32-bit integer field (in
+ network byte order) and is used to detect duplicate messages.
+ Upon reboot implementations MAY set the high order 12 bits to
+ contain the low order 12 bits of current time, and the low order
+ 20 bits to a random value. Senders of request messages MUST
+ insert a unique identifier on each message. The identifier MUST
+ remain locally unique for a period of at least 4 minutes, even
+ across reboots. The originator of an Answer message MUST ensure
+ that the End-to-End Identifier field contains the same value that
+ was found in the corresponding request. The End-to-End Identifier
+ MUST NOT be modified by Diameter agents of any kind. The
+ combination of the Origin-Host (see Section 6.3) and this field is
+ used to detect duplicates. Duplicate requests SHOULD cause the
+ same answer to be transmitted (modulo the hop-by-hop Identifier
+ field and any routing AVPs that may be present), and MUST NOT
+ affect any state that was set when the original request was
+ processed. Duplicate answer messages that are to be locally
+ consumed (see Section 6.2) SHOULD be silently discarded.
+
+ AVPs
+ AVPs are a method of encapsulating information relevant to the
+ Diameter message. See Section 4 for more information on AVPs.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 34]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+3.1. Command Codes
+
+ Each command Request/Answer pair is assigned a command code, and the
+ sub-type (i.e., request or answer) is identified via the 'R' bit in
+ the Command Flags field of the Diameter header.
+
+ Every Diameter message MUST contain a command code in its header's
+ Command-Code field, which is used to determine the action that is to
+ be taken for a particular message. The following Command Codes are
+ defined in the Diameter base protocol:
+
+ Command-Name Abbrev. Code Reference
+ --------------------------------------------------------
+ Abort-Session-Request ASR 274 8.5.1
+ Abort-Session-Answer ASA 274 8.5.2
+ Accounting-Request ACR 271 9.7.1
+ Accounting-Answer ACA 271 9.7.2
+ Capabilities-Exchange- CER 257 5.3.1
+ Request
+ Capabilities-Exchange- CEA 257 5.3.2
+ Answer
+ Device-Watchdog-Request DWR 280 5.5.1
+ Device-Watchdog-Answer DWA 280 5.5.2
+ Disconnect-Peer-Request DPR 282 5.4.1
+ Disconnect-Peer-Answer DPA 282 5.4.2
+ Re-Auth-Request RAR 258 8.3.1
+ Re-Auth-Answer RAA 258 8.3.2
+ Session-Termination- STR 275 8.4.1
+ Request
+ Session-Termination- STA 275 8.4.2
+ Answer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 35]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+3.2. Command Code ABNF specification
+
+ Every Command Code defined MUST include a corresponding ABNF
+ specification, which is used to define the AVPs that MUST or MAY be
+ present. The following format is used in the definition:
+
+ command-def = command-name "::=" diameter-message
+
+ command-name = diameter-name
+
+ diameter-name = ALPHA *(ALPHA / DIGIT / "-")
+
+ diameter-message = header [ *fixed] [ *required] [ *optional]
+ [ *fixed]
+
+ header = "<" Diameter-Header:" command-id
+ [r-bit] [p-bit] [e-bit] [application-id]">"
+
+ application-id = 1*DIGIT
+
+ command-id = 1*DIGIT
+ ; The Command Code assigned to the command
+
+ r-bit = ", REQ"
+ ; If present, the 'R' bit in the Command
+ ; Flags is set, indicating that the message
+ ; is a request, as opposed to an answer.
+
+ p-bit = ", PXY"
+ ; If present, the 'P' bit in the Command
+ ; Flags is set, indicating that the message
+ ; is proxiable.
+
+ e-bit = ", ERR"
+ ; If present, the 'E' bit in the Command
+ ; Flags is set, indicating that the answer
+ ; message contains a Result-Code AVP in
+ ; the "protocol error" class.
+
+ fixed = [qual] "<" avp-spec ">"
+ ; Defines the fixed position of an AVP
+
+ required = [qual] "{" avp-spec "}"
+ ; The AVP MUST be present and can appear
+ ; anywhere in the message.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 36]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ optional = [qual] "[" avp-name "]"
+ ; The avp-name in the 'optional' rule cannot
+ ; evaluate to any AVP Name which is included
+ ; in a fixed or required rule. The AVP can
+ ; appear anywhere in the message.
+
+ qual = [min] "*" [max]
+ ; See ABNF conventions, RFC 2234 Section 6.6.
+ ; The absence of any qualifiers depends on whether
+ ; it precedes a fixed, required, or optional
+ ; rule. If a fixed or required rule has no
+ ; qualifier, then exactly one such AVP MUST
+ ; be present. If an optional rule has no
+ ; qualifier, then 0 or 1 such AVP may be
+ ; present.
+ ;
+ ; NOTE: "[" and "]" have a different meaning
+ ; than in ABNF (see the optional rule, above).
+ ; These braces cannot be used to express
+ ; optional fixed rules (such as an optional
+ ; ICV at the end). To do this, the convention
+ ; is '0*1fixed'.
+
+ min = 1*DIGIT
+ ; The minimum number of times the element may
+ ; be present. The default value is zero.
+
+ max = 1*DIGIT
+ ; The maximum number of times the element may
+ ; be present. The default value is infinity. A
+ ; value of zero implies the AVP MUST NOT be
+ ; present.
+
+ avp-spec = diameter-name
+ ; The avp-spec has to be an AVP Name, defined
+ ; in the base or extended Diameter
+ ; specifications.
+
+ avp-name = avp-spec / "AVP"
+ ; The string "AVP" stands for *any* arbitrary
+ ; AVP Name, which does not conflict with the
+ ; required or fixed position AVPs defined in
+ ; the command code definition.
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 37]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ The following is a definition of a fictitious command code:
+
+ Example-Request ::= < "Diameter-Header: 9999999, REQ, PXY >
+ { User-Name }
+ * { Origin-Host }
+ * [ AVP
+
+3.3. Diameter Command Naming Conventions
+
+ Diameter command names typically includes one or more English words
+ followed by the verb Request or Answer. Each English word is
+ delimited by a hyphen. A three-letter acronym for both the request
+ and answer is also normally provided.
+
+ An example is a message set used to terminate a session. The command
+ name is Session-Terminate-Request and Session-Terminate-Answer, while
+ the acronyms are STR and STA, respectively.
+
+ Both the request and the answer for a given command share the same
+ command code. The request is identified by the R(equest) bit in the
+ Diameter header set to one (1), to ask that a particular action be
+ performed, such as authorizing a user or terminating a session. Once
+ the receiver has completed the request it issues the corresponding
+ answer, which includes a result code that communicates one of the
+ following:
+
+ - The request was successful
+
+ - The request failed
+
+ - An additional request must be sent to provide information the peer
+ requires prior to returning a successful or failed answer.
+
+ - The receiver could not process the request, but provides
+ information about a Diameter peer that is able to satisfy the
+ request, known as redirect.
+
+ Additional information, encoded within AVPs, MAY also be included in
+ answer messages.
+
+4. Diameter AVPs
+
+ Diameter AVPs carry specific authentication, accounting,
+ authorization, routing and security information as well as
+ configuration details for the request and reply.
+
+ Some AVPs MAY be listed more than once. The effect of such an AVP is
+ specific, and is specified in each case by the AVP description.
+
+
+
+Calhoun, et al. Standards Track [Page 38]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Each AVP of type OctetString MUST be padded to align on a 32-bit
+ boundary, while other AVP types align naturally. A number of zero-
+ valued bytes are added to the end of the AVP Data field till a word
+ boundary is reached. The length of the padding is not reflected in
+ the AVP Length field.
+
+4.1. AVP Header
+
+ The fields in the AVP header MUST be sent in network byte order. The
+ format of the header is:
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | AVP Code |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |V M P r r r r r| AVP Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Vendor-ID (opt) |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Data ...
+ +-+-+-+-+-+-+-+-+
+
+ AVP Code
+ The AVP Code, combined with the Vendor-Id field, identifies the
+ attribute uniquely. AVP numbers 1 through 255 are reserved for
+ backward compatibility with RADIUS, without setting the Vendor-Id
+ field. AVP numbers 256 and above are used for Diameter, which are
+ allocated by IANA (see Section 11.1).
+
+ AVP Flags
+ The AVP Flags field informs the receiver how each attribute must
+ be handled. The 'r' (reserved) bits are unused and SHOULD be set
+ to 0. Note that subsequent Diameter applications MAY define
+ additional bits within the AVP Header, and an unrecognized bit
+ SHOULD be considered an error. The 'P' bit indicates the need for
+ encryption for end-to-end security.
+
+ The 'M' Bit, known as the Mandatory bit, indicates whether support
+ of the AVP is required. If an AVP with the 'M' bit set is
+ received by a Diameter client, server, proxy, or translation agent
+ and either the AVP or its value is unrecognized, the message MUST
+ be rejected. Diameter Relay and redirect agents MUST NOT reject
+ messages with unrecognized AVPs.
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 39]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ The 'M' bit MUST be set according to the rules defined for the AVP
+ containing it. In order to preserve interoperability, a Diameter
+ implementation MUST be able to exclude from a Diameter message any
+ Mandatory AVP which is neither defined in the base Diameter
+ protocol nor in any of the Diameter Application specifications
+ governing the message in which it appears. It MAY do this in one
+ of the following ways:
+
+ 1) If a message is rejected because it contains a Mandatory AVP
+ which is neither defined in the base Diameter standard nor in
+ any of the Diameter Application specifications governing the
+ message in which it appears, the implementation may resend the
+ message without the AVP, possibly inserting additional standard
+ AVPs instead.
+
+ 2) A configuration option may be provided on a system wide, per
+ peer, or per realm basis that would allow/prevent particular
+ Mandatory AVPs to be sent. Thus an administrator could change
+ the configuration to avoid interoperability problems.
+
+ Diameter implementations are required to support all Mandatory
+ AVPs which are allowed by the message's formal syntax and defined
+ either in the base Diameter standard or in one of the Diameter
+ Application specifications governing the message.
+
+ AVPs with the 'M' bit cleared are informational only and a
+ receiver that receives a message with such an AVP that is not
+ supported, or whose value is not supported, MAY simply ignore the
+ AVP.
+
+ The 'V' bit, known as the Vendor-Specific bit, indicates whether
+ the optional Vendor-ID field is present in the AVP header. When
+ set the AVP Code belongs to the specific vendor code address
+ space.
+
+ Unless otherwise noted, AVPs will have the following default AVP
+ Flags field settings:
+
+ The 'M' bit MUST be set. The 'V' bit MUST NOT be set.
+
+ AVP Length
+ The AVP Length field is three octets, and indicates the number of
+ octets in this AVP including the AVP Code, AVP Length, AVP Flags,
+ Vendor-ID field (if present) and the AVP data. If a message is
+ received with an invalid attribute length, the message SHOULD be
+ rejected.
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 40]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+4.1.1. Optional Header Elements
+
+ The AVP Header contains one optional field. This field is only
+ present if the respective bit-flag is enabled.
+
+ Vendor-ID
+ The Vendor-ID field is present if the 'V' bit is set in the AVP
+ Flags field. The optional four-octet Vendor-ID field contains the
+ IANA assigned "SMI Network Management Private Enterprise Codes"
+ [ASSIGNNO] value, encoded in network byte order. Any vendor
+ wishing to implement a vendor-specific Diameter AVP MUST use their
+ own Vendor-ID along with their privately managed AVP address
+ space, guaranteeing that they will not collide with any other
+ vendor's vendor-specific AVP(s), nor with future IETF
+ applications.
+
+ A vendor ID value of zero (0) corresponds to the IETF adopted AVP
+ values, as managed by the IANA. Since the absence of the vendor
+ ID field implies that the AVP in question is not vendor specific,
+ implementations MUST NOT use the zero (0) vendor ID.
+
+4.2. Basic AVP Data Formats
+
+ The Data field is zero or more octets and contains information
+ specific to the Attribute. The format and length of the Data field
+ is determined by the AVP Code and AVP Length fields. The format of
+ the Data field MUST be one of the following base data types or a data
+ type derived from the base data types. In the event that a new Basic
+ AVP Data Format is needed, a new version of this RFC must be created.
+
+ OctetString
+ The data contains arbitrary data of variable length. Unless
+ otherwise noted, the AVP Length field MUST be set to at least 8
+ (12 if the 'V' bit is enabled). AVP Values of this type that are
+ not a multiple of four-octets in length is followed by the
+ necessary padding so that the next AVP (if any) will start on a
+ 32-bit boundary.
+
+ Integer32
+ 32 bit signed value, in network byte order. The AVP Length field
+ MUST be set to 12 (16 if the 'V' bit is enabled).
+
+ Integer64
+ 64 bit signed value, in network byte order. The AVP Length field
+ MUST be set to 16 (20 if the 'V' bit is enabled).
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 41]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Unsigned32
+ 32 bit unsigned value, in network byte order. The AVP Length
+ field MUST be set to 12 (16 if the 'V' bit is enabled).
+
+ Unsigned64
+ 64 bit unsigned value, in network byte order. The AVP Length
+ field MUST be set to 16 (20 if the 'V' bit is enabled).
+
+ Float32
+ This represents floating point values of single precision as
+ described by [FLOATPOINT]. The 32-bit value is transmitted in
+ network byte order. The AVP Length field MUST be set to 12 (16 if
+ the 'V' bit is enabled).
+
+ Float64
+ This represents floating point values of double precision as
+ described by [FLOATPOINT]. The 64-bit value is transmitted in
+ network byte order. The AVP Length field MUST be set to 16 (20 if
+ the 'V' bit is enabled).
+
+ Grouped
+ The Data field is specified as a sequence of AVPs. Each of these
+ AVPs follows - in the order in which they are specified -
+ including their headers and padding. The AVP Length field is set
+ to 8 (12 if the 'V' bit is enabled) plus the total length of all
+ included AVPs, including their headers and padding. Thus the AVP
+ length field of an AVP of type Grouped is always a multiple of 4.
+
+4.3. Derived AVP Data Formats
+
+ In addition to using the Basic AVP Data Formats, applications may
+ define data formats derived from the Basic AVP Data Formats. An
+ application that defines new AVP Derived Data Formats MUST include
+ them in a section entitled "AVP Derived Data Formats", using the same
+ format as the definitions below. Each new definition must be either
+ defined or listed with a reference to the RFC that defines the
+ format.
+
+ The below AVP Derived Data Formats are commonly used by applications.
+
+ Address
+ The Address format is derived from the OctetString AVP Base
+ Format. It is a discriminated union, representing, for example a
+ 32-bit (IPv4) [IPV4] or 128-bit (IPv6) [IPV6] address, most
+ significant octet first. The first two octets of the Address
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 42]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ AVP represents the AddressType, which contains an Address Family
+ defined in [IANAADFAM]. The AddressType is used to discriminate
+ the content and format of the remaining octets.
+
+ Time
+ The Time format is derived from the OctetString AVP Base Format.
+ The string MUST contain four octets, in the same format as the
+ first four bytes are in the NTP timestamp format. The NTP
+ Timestamp format is defined in chapter 3 of [SNTP].
+
+ This represents the number of seconds since 0h on 1 January 1900
+ with respect to the Coordinated Universal Time (UTC).
+
+ On 6h 28m 16s UTC, 7 February 2036 the time value will overflow.
+ SNTP [SNTP] describes a procedure to extend the time to 2104.
+ This procedure MUST be supported by all DIAMETER nodes.
+
+ UTF8String
+ The UTF8String format is derived from the OctetString AVP Base
+ Format. This is a human readable string represented using the
+ ISO/IEC IS 10646-1 character set, encoded as an OctetString using
+ the UTF-8 [UFT8] transformation format described in RFC 2279.
+
+ Since additional code points are added by amendments to the 10646
+ standard from time to time, implementations MUST be prepared to
+ encounter any code point from 0x00000001 to 0x7fffffff. Byte
+ sequences that do not correspond to the valid encoding of a code
+ point into UTF-8 charset or are outside this range are prohibited.
+
+ The use of control codes SHOULD be avoided. When it is necessary
+ to represent a new line, the control code sequence CR LF SHOULD be
+ used.
+
+ The use of leading or trailing white space SHOULD be avoided.
+
+ For code points not directly supported by user interface hardware
+ or software, an alternative means of entry and display, such as
+ hexadecimal, MAY be provided.
+
+ For information encoded in 7-bit US-ASCII, the UTF-8 charset is
+ identical to the US-ASCII charset.
+
+ UTF-8 may require multiple bytes to represent a single character /
+ code point; thus the length of an UTF8String in octets may be
+ different from the number of characters encoded.
+
+ Note that the AVP Length field of an UTF8String is measured in
+ octets, not characters.
+
+
+
+Calhoun, et al. Standards Track [Page 43]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ DiameterIdentity
+ The DiameterIdentity format is derived from the OctetString AVP
+ Base Format.
+
+ DiameterIdentity = FQDN
+
+ DiameterIdentity value is used to uniquely identify a Diameter
+ node for purposes of duplicate connection and routing loop
+ detection.
+
+ The contents of the string MUST be the FQDN of the Diameter node.
+ If multiple Diameter nodes run on the same host, each Diameter
+ node MUST be assigned a unique DiameterIdentity. If a Diameter
+ node can be identified by several FQDNs, a single FQDN should be
+ picked at startup, and used as the only DiameterIdentity for that
+ node, whatever the connection it is sent on.
+
+ DiameterURI
+
+ The DiameterURI MUST follow the Uniform Resource Identifiers (URI)
+ syntax [URI] rules specified below:
+
+ "aaa://" FQDN [ port ] [ transport ] [ protocol ]
+
+ ; No transport security
+
+ "aaas://" FQDN [ port ] [ transport ] [ protocol ]
+
+ ; Transport security used
+
+ FQDN = Fully Qualified Host Name
+
+ port = ":" 1*DIGIT
+
+ ; One of the ports used to listen for
+ ; incoming connections.
+ ; If absent,
+ ; the default Diameter port (3868) is
+ ; assumed.
+
+ transport = ";transport=" transport-protocol
+
+ ; One of the transports used to listen
+ ; for incoming connections. If absent,
+ ; the default SCTP [SCTP] protocol is
+ ; assumed. UDP MUST NOT be used when
+ ; the aaa-protocol field is set to
+ ; diameter.
+
+
+
+Calhoun, et al. Standards Track [Page 44]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ transport-protocol = ( "tcp" / "sctp" / "udp" )
+
+ protocol = ";protocol=" aaa-protocol
+
+ ; If absent, the default AAA protocol
+ ; is diameter.
+
+ aaa-protocol = ( "diameter" / "radius" / "tacacs+" )
+
+ The following are examples of valid Diameter host identities:
+
+ aaa://host.example.com;transport=tcp
+ aaa://host.example.com:6666;transport=tcp
+ aaa://host.example.com;protocol=diameter
+ aaa://host.example.com:6666;protocol=diameter
+ aaa://host.example.com:6666;transport=tcp;protocol=diameter
+ aaa://host.example.com:1813;transport=udp;protocol=radius
+
+ Enumerated
+ Enumerated is derived from the Integer32 AVP Base Format. The
+ definition contains a list of valid values and their
+ interpretation and is described in the Diameter application
+ introducing the AVP.
+
+ IPFilterRule
+ The IPFilterRule format is derived from the OctetString AVP Base
+ Format. It uses the ASCII charset. Packets may be filtered based
+ on the following information that is associated with it:
+
+ Direction (in or out)
+ Source and destination IP address (possibly masked)
+ Protocol
+ Source and destination port (lists or ranges)
+ TCP flags
+ IP fragment flag
+ IP options
+ ICMP types
+
+ Rules for the appropriate direction are evaluated in order, with
+ the first matched rule terminating the evaluation. Each packet is
+ evaluated once. If no rule matches, the packet is dropped if the
+ last rule evaluated was a permit, and passed if the last rule was
+ a deny.
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 45]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ IPFilterRule filters MUST follow the format:
+
+ action dir proto from src to dst [options]
+
+ action permit - Allow packets that match the rule.
+ deny - Drop packets that match the rule.
+
+ dir "in" is from the terminal, "out" is to the
+ terminal.
+
+ proto An IP protocol specified by number. The "ip"
+ keyword means any protocol will match.
+
+ src and dst <address/mask> [ports]
+
+ The <address/mask> may be specified as:
+ ipno An IPv4 or IPv6 number in dotted-
+ quad or canonical IPv6 form. Only
+ this exact IP number will match the
+ rule.
+ ipno/bits An IP number as above with a mask
+ width of the form 1.2.3.4/24. In
+ this case, all IP numbers from
+ 1.2.3.0 to 1.2.3.255 will match.
+ The bit width MUST be valid for the
+ IP version and the IP number MUST
+ NOT have bits set beyond the mask.
+ For a match to occur, the same IP
+ version must be present in the
+ packet that was used in describing
+ the IP address. To test for a
+ particular IP version, the bits part
+ can be set to zero. The keyword
+ "any" is 0.0.0.0/0 or the IPv6
+ equivalent. The keyword "assigned"
+ is the address or set of addresses
+ assigned to the terminal. For IPv4,
+ a typical first rule is often "deny
+ in ip! assigned"
+
+ The sense of the match can be inverted by
+ preceding an address with the not modifier (!),
+ causing all other addresses to be matched
+ instead. This does not affect the selection of
+ port numbers.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 46]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ With the TCP, UDP and SCTP protocols, optional
+ ports may be specified as:
+
+ {port/port-port}[,ports[,...]]
+
+ The '-' notation specifies a range of ports
+ (including boundaries).
+
+ Fragmented packets that have a non-zero offset
+ (i.e., not the first fragment) will never match
+ a rule that has one or more port
+ specifications. See the frag option for
+ details on matching fragmented packets.
+
+ options:
+ frag Match if the packet is a fragment and this is not
+ the first fragment of the datagram. frag may not
+ be used in conjunction with either tcpflags or
+ TCP/UDP port specifications.
+
+ ipoptions spec
+ Match if the IP header contains the comma
+ separated list of options specified in spec. The
+ supported IP options are:
+
+ ssrr (strict source route), lsrr (loose source
+ route), rr (record packet route) and ts
+ (timestamp). The absence of a particular option
+ may be denoted with a '!'.
+
+ tcpoptions spec
+ Match if the TCP header contains the comma
+ separated list of options specified in spec. The
+ supported TCP options are:
+
+ mss (maximum segment size), window (tcp window
+ advertisement), sack (selective ack), ts (rfc1323
+ timestamp) and cc (rfc1644 t/tcp connection
+ count). The absence of a particular option may
+ be denoted with a '!'.
+
+ established
+ TCP packets only. Match packets that have the RST
+ or ACK bits set.
+
+ setup TCP packets only. Match packets that have the SYN
+ bit set but no ACK bit.
+
+
+
+
+Calhoun, et al. Standards Track [Page 47]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ tcpflags spec
+ TCP packets only. Match if the TCP header
+ contains the comma separated list of flags
+ specified in spec. The supported TCP flags are:
+
+ fin, syn, rst, psh, ack and urg. The absence of a
+ particular flag may be denoted with a '!'. A rule
+ that contains a tcpflags specification can never
+ match a fragmented packet that has a non-zero
+ offset. See the frag option for details on
+ matching fragmented packets.
+
+ icmptypes types
+ ICMP packets only. Match if the ICMP type is in
+ the list types. The list may be specified as any
+ combination of ranges or individual types
+ separated by commas. Both the numeric values and
+ the symbolic values listed below can be used. The
+ supported ICMP types are:
+
+ echo reply (0), destination unreachable (3),
+ source quench (4), redirect (5), echo request
+ (8), router advertisement (9), router
+ solicitation (10), time-to-live exceeded (11), IP
+ header bad (12), timestamp request (13),
+ timestamp reply (14), information request (15),
+ information reply (16), address mask request (17)
+ and address mask reply (18).
+
+ There is one kind of packet that the access device MUST always
+ discard, that is an IP fragment with a fragment offset of one. This
+ is a valid packet, but it only has one use, to try to circumvent
+ firewalls.
+
+ An access device that is unable to interpret or apply a deny rule
+ MUST terminate the session. An access device that is unable to
+ interpret or apply a permit rule MAY apply a more restrictive
+ rule. An access device MAY apply deny rules of its own before the
+ supplied rules, for example to protect the access device owner's
+ infrastructure.
+
+ The rule syntax is a modified subset of ipfw(8) from FreeBSD, and the
+ ipfw.c code may provide a useful base for implementations.
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 48]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ QoSFilterRule
+ The QosFilterRule format is derived from the OctetString AVP Base
+ Format. It uses the ASCII charset. Packets may be marked or
+ metered based on the following information that is associated with
+ it:
+
+ Direction (in or out)
+ Source and destination IP address (possibly masked)
+ Protocol
+ Source and destination port (lists or ranges)
+ DSCP values (no mask or range)
+
+ Rules for the appropriate direction are evaluated in order, with
+ the first matched rule terminating the evaluation. Each packet is
+ evaluated once. If no rule matches, the packet is treated as best
+ effort. An access device that is unable to interpret or apply a
+ QoS rule SHOULD NOT terminate the session.
+
+ QoSFilterRule filters MUST follow the format:
+
+ action dir proto from src to dst [options]
+
+ tag - Mark packet with a specific DSCP
+ [DIFFSERV]. The DSCP option MUST be
+ included.
+ meter - Meter traffic. The metering options
+ MUST be included.
+
+ dir The format is as described under IPFilterRule.
+
+ proto The format is as described under
+ IPFilterRule.
+
+ src and dst The format is as described under
+ IPFilterRule.
+
+4.4. Grouped AVP Values
+
+ The Diameter protocol allows AVP values of type 'Grouped.' This
+ implies that the Data field is actually a sequence of AVPs. It is
+ possible to include an AVP with a Grouped type within a Grouped type,
+ that is, to nest them. AVPs within an AVP of type Grouped have the
+ same padding requirements as non-Grouped AVPs, as defined in Section
+ 4.
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 49]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ The AVP Code numbering space of all AVPs included in a Grouped AVP is
+ the same as for non-grouped AVPs. Further, if any of the AVPs
+ encapsulated within a Grouped AVP has the 'M' (mandatory) bit set,
+ the Grouped AVP itself MUST also include the 'M' bit set.
+
+ Every Grouped AVP defined MUST include a corresponding grammar, using
+ ABNF [ABNF] (with modifications), as defined below.
+
+ grouped-avp-def = name "::=" avp
+
+ name-fmt = ALPHA *(ALPHA / DIGIT / "-")
+
+ name = name-fmt
+ ; The name has to be the name of an AVP,
+ ; defined in the base or extended Diameter
+ ; specifications.
+
+ avp = header [ *fixed] [ *required] [ *optional]
+ [ *fixed]
+
+ header = "<" "AVP-Header:" avpcode [vendor] ">"
+
+ avpcode = 1*DIGIT
+ ; The AVP Code assigned to the Grouped AVP
+
+ vendor = 1*DIGIT
+ ; The Vendor-ID assigned to the Grouped AVP.
+ ; If absent, the default value of zero is
+ ; used.
+
+4.4.1. Example AVP with a Grouped Data type
+
+ The Example-AVP (AVP Code 999999) is of type Grouped and is used to
+ clarify how Grouped AVP values work. The Grouped Data field has the
+ following ABNF grammar:
+
+ Example-AVP ::= < AVP Header: 999999 >
+ { Origin-Host }
+ 1*{ Session-Id }
+ *[ AVP ]
+
+ An Example-AVP with Grouped Data follows.
+
+ The Origin-Host AVP is required (Section 6.3). In this case:
+
+ Origin-Host = "example.com".
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 50]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ One or more Session-Ids must follow. Here there are two:
+
+ Session-Id =
+ "grump.example.com:33041;23432;893;0AF3B81"
+
+ Session-Id =
+ "grump.example.com:33054;23561;2358;0AF3B82"
+
+ optional AVPs included are
+
+ Recovery-Policy = <binary>
+ 2163bc1d0ad82371f6bc09484133c3f09ad74a0dd5346d54195a7cf0b35
+ 2cabc881839a4fdcfbc1769e2677a4c1fb499284c5f70b48f58503a45c5
+ c2d6943f82d5930f2b7c1da640f476f0e9c9572a50db8ea6e51e1c2c7bd
+ f8bb43dc995144b8dbe297ac739493946803e1cee3e15d9b765008a1b2a
+ cf4ac777c80041d72c01e691cf751dbf86e85f509f3988e5875dc905119
+ 26841f00f0e29a6d1ddc1a842289d440268681e052b30fb638045f7779c
+ 1d873c784f054f688f5001559ecff64865ef975f3e60d2fd7966b8c7f92
+
+ Futuristic-Acct-Record = <binary>
+ fe19da5802acd98b07a5b86cb4d5d03f0314ab9ef1ad0b67111ff3b90a0
+ 57fe29620bf3585fd2dd9fcc38ce62f6cc208c6163c008f4258d1bc88b8
+ 17694a74ccad3ec69269461b14b2e7a4c111fb239e33714da207983f58c
+ 41d018d56fe938f3cbf089aac12a912a2f0d1923a9390e5f789cb2e5067
+ d3427475e49968f841
+
+ The data for the optional AVPs is represented in hex since the format
+ of these AVPs is neither known at the time of definition of the
+ Example-AVP group, nor (likely) at the time when the example instance
+ of this AVP is interpreted - except by Diameter implementations which
+ support the same set of AVPs. The encoding example illustrates how
+ padding is used and how length fields are calculated. Also note that
+ AVPs may be present in the Grouped AVP value which the receiver
+ cannot interpret (here, the Recover-Policy and Futuristic-Acct-Record
+ AVPs).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 51]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ This AVP would be encoded as follows:
+
+ 0 1 2 3 4 5 6 7
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 0 | Example AVP Header (AVP Code = 999999), Length = 468 |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 8 | Origin-Host AVP Header (AVP Code = 264), Length = 19 |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 16 | 'e' | 'x' | 'a' | 'm' | 'p' | 'l' | 'e' | '.' |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 24 | 'c' | 'o' | 'm' |Padding| Session-Id AVP Header |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 32 | (AVP Code = 263), Length = 50 | 'g' | 'r' | 'u' | 'm' |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ . . .
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 64 | 'A' | 'F' | '3' | 'B' | '8' | '1' |Padding|Padding|
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 72 | Session-Id AVP Header (AVP Code = 263), Length = 51 |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 80 | 'g' | 'r' | 'u' | 'm' | 'p' | '.' | 'e' | 'x' |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ . . .
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 104 | '0' | 'A' | 'F' | '3' | 'B' | '8' | '2' |Padding|
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 112 | Recovery-Policy Header (AVP Code = 8341), Length = 223 |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 120 | 0x21 | 0x63 | 0xbc | 0x1d | 0x0a | 0xd8 | 0x23 | 0x71 |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ . . .
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 320 | 0x2f | 0xd7 | 0x96 | 0x6b | 0x8c | 0x7f | 0x92 |Padding|
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 328 | Futuristic-Acct-Record Header (AVP Code = 15930), Length = 137|
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 336 | 0xfe | 0x19 | 0xda | 0x58 | 0x02 | 0xac | 0xd9 | 0x8b |
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ . . .
+ +-------+-------+-------+-------+-------+-------+-------+-------+
+ 464 | 0x41 |Padding|Padding|Padding|
+ +-------+-------+-------+-------+
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 52]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+4.5. Diameter Base Protocol AVPs
+
+ The following table describes the Diameter AVPs defined in the base
+ protocol, their AVP Code values, types, possible flag values and
+ whether the AVP MAY be encrypted. For the originator of a Diameter
+ message, "Encr" (Encryption) means that if a message containing that
+ AVP is to be sent via a Diameter agent (proxy, redirect or relay)
+ then the message MUST NOT be sent unless there is end-to-end security
+ between the originator and the recipient and integrity /
+ confidentiality protection is offered for this AVP OR the originator
+ has locally trusted configuration that indicates that end-to-end
+ security is not needed. Similarly, for the originator of a Diameter
+ message, a "P" in the "MAY" column means that if a message containing
+ that AVP is to be sent via a Diameter agent (proxy, redirect or
+ relay) then the message MUST NOT be sent unless there is end-to-end
+ security between the originator and the recipient or the originator
+ has locally trusted configuration that indicates that end-to-end
+ security is not needed.
+
+ Due to space constraints, the short form DiamIdent is used to
+ represent DiameterIdentity.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 53]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ +---------------------+
+ | AVP Flag rules |
+ |----+-----+----+-----|----+
+ AVP Section | | |SHLD| MUST| |
+ Attribute Name Code Defined Data Type |MUST| MAY | NOT| NOT|Encr|
+ -----------------------------------------|----+-----+----+-----|----|
+ Acct- 85 9.8.2 Unsigned32 | M | P | | V | Y |
+ Interim-Interval | | | | | |
+ Accounting- 483 9.8.7 Enumerated | M | P | | V | Y |
+ Realtime-Required | | | | | |
+ Acct- 50 9.8.5 UTF8String | M | P | | V | Y |
+ Multi-Session-Id | | | | | |
+ Accounting- 485 9.8.3 Unsigned32 | M | P | | V | Y |
+ Record-Number | | | | | |
+ Accounting- 480 9.8.1 Enumerated | M | P | | V | Y |
+ Record-Type | | | | | |
+ Accounting- 44 9.8.4 OctetString| M | P | | V | Y |
+ Session-Id | | | | | |
+ Accounting- 287 9.8.6 Unsigned64 | M | P | | V | Y |
+ Sub-Session-Id | | | | | |
+ Acct- 259 6.9 Unsigned32 | M | P | | V | N |
+ Application-Id | | | | | |
+ Auth- 258 6.8 Unsigned32 | M | P | | V | N |
+ Application-Id | | | | | |
+ Auth-Request- 274 8.7 Enumerated | M | P | | V | N |
+ Type | | | | | |
+ Authorization- 291 8.9 Unsigned32 | M | P | | V | N |
+ Lifetime | | | | | |
+ Auth-Grace- 276 8.10 Unsigned32 | M | P | | V | N |
+ Period | | | | | |
+ Auth-Session- 277 8.11 Enumerated | M | P | | V | N |
+ State | | | | | |
+ Re-Auth-Request- 285 8.12 Enumerated | M | P | | V | N |
+ Type | | | | | |
+ Class 25 8.20 OctetString| M | P | | V | Y |
+ Destination-Host 293 6.5 DiamIdent | M | P | | V | N |
+ Destination- 283 6.6 DiamIdent | M | P | | V | N |
+ Realm | | | | | |
+ Disconnect-Cause 273 5.4.3 Enumerated | M | P | | V | N |
+ E2E-Sequence AVP 300 6.15 Grouped | M | P | | V | Y |
+ Error-Message 281 7.3 UTF8String | | P | | V,M | N |
+ Error-Reporting- 294 7.4 DiamIdent | | P | | V,M | N |
+ Host | | | | | |
+ Event-Timestamp 55 8.21 Time | M | P | | V | N |
+ Experimental- 297 7.6 Grouped | M | P | | V | N |
+ Result | | | | | |
+ -----------------------------------------|----+-----+----+-----|----|
+
+
+
+
+Calhoun, et al. Standards Track [Page 54]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ +---------------------+
+ | AVP Flag rules |
+ |----+-----+----+-----|----+
+ AVP Section | | |SHLD| MUST|MAY |
+ Attribute Name Code Defined Data Type |MUST| MAY | NOT| NOT|Encr|
+ -----------------------------------------|----+-----+----+-----|----|
+ Experimental- 298 7.7 Unsigned32 | M | P | | V | N |
+ Result-Code | | | | | |
+ Failed-AVP 279 7.5 Grouped | M | P | | V | N |
+ Firmware- 267 5.3.4 Unsigned32 | | | |P,V,M| N |
+ Revision | | | | | |
+ Host-IP-Address 257 5.3.5 Address | M | P | | V | N |
+ Inband-Security | M | P | | V | N |
+ -Id 299 6.10 Unsigned32 | | | | | |
+ Multi-Round- 272 8.19 Unsigned32 | M | P | | V | Y |
+ Time-Out | | | | | |
+ Origin-Host 264 6.3 DiamIdent | M | P | | V | N |
+ Origin-Realm 296 6.4 DiamIdent | M | P | | V | N |
+ Origin-State-Id 278 8.16 Unsigned32 | M | P | | V | N |
+ Product-Name 269 5.3.7 UTF8String | | | |P,V,M| N |
+ Proxy-Host 280 6.7.3 DiamIdent | M | | | P,V | N |
+ Proxy-Info 284 6.7.2 Grouped | M | | | P,V | N |
+ Proxy-State 33 6.7.4 OctetString| M | | | P,V | N |
+ Redirect-Host 292 6.12 DiamURI | M | P | | V | N |
+ Redirect-Host- 261 6.13 Enumerated | M | P | | V | N |
+ Usage | | | | | |
+ Redirect-Max- 262 6.14 Unsigned32 | M | P | | V | N |
+ Cache-Time | | | | | |
+ Result-Code 268 7.1 Unsigned32 | M | P | | V | N |
+ Route-Record 282 6.7.1 DiamIdent | M | | | P,V | N |
+ Session-Id 263 8.8 UTF8String | M | P | | V | Y |
+ Session-Timeout 27 8.13 Unsigned32 | M | P | | V | N |
+ Session-Binding 270 8.17 Unsigned32 | M | P | | V | Y |
+ Session-Server- 271 8.18 Enumerated | M | P | | V | Y |
+ Failover | | | | | |
+ Supported- 265 5.3.6 Unsigned32 | M | P | | V | N |
+ Vendor-Id | | | | | |
+ Termination- 295 8.15 Enumerated | M | P | | V | N |
+ Cause | | | | | |
+ User-Name 1 8.14 UTF8String | M | P | | V | Y |
+ Vendor-Id 266 5.3.3 Unsigned32 | M | P | | V | N |
+ Vendor-Specific- 260 6.11 Grouped | M | P | | V | N |
+ Application-Id | | | | | |
+ -----------------------------------------|----+-----+----+-----|----|
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 55]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+5. Diameter Peers
+
+ This section describes how Diameter nodes establish connections and
+ communicate with peers.
+
+5.1. Peer Connections
+
+ Although a Diameter node may have many possible peers that it is able
+ to communicate with, it may not be economical to have an established
+ connection to all of them. At a minimum, a Diameter node SHOULD have
+ an established connection with two peers per realm, known as the
+ primary and secondary peers. Of course, a node MAY have additional
+ connections, if it is deemed necessary. Typically, all messages for
+ a realm are sent to the primary peer, but in the event that failover
+ procedures are invoked, any pending requests are sent to the
+ secondary peer. However, implementations are free to load balance
+ requests between a set of peers.
+
+ Note that a given peer MAY act as a primary for a given realm, while
+ acting as a secondary for another realm.
+
+ When a peer is deemed suspect, which could occur for various reasons,
+ including not receiving a DWA within an allotted timeframe, no new
+ requests should be forwarded to the peer, but failover procedures are
+ invoked. When an active peer is moved to this mode, additional
+ connections SHOULD be established to ensure that the necessary number
+ of active connections exists.
+
+ There are two ways that a peer is removed from the suspect peer list:
+
+ 1. The peer is no longer reachable, causing the transport connection
+ to be shutdown. The peer is moved to the closed state.
+
+ 2. Three watchdog messages are exchanged with accepted round trip
+ times, and the connection to the peer is considered stabilized.
+
+ In the event the peer being removed is either the primary or
+ secondary, an alternate peer SHOULD replace the deleted peer, and
+ assume the role of either primary or secondary.
+
+5.2. Diameter Peer Discovery
+
+ Allowing for dynamic Diameter agent discovery will make it possible
+ for simpler and more robust deployment of Diameter services. In
+ order to promote interoperable implementations of Diameter peer
+ discovery, the following mechanisms are described. These are based
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 56]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ on existing IETF standards. The first option (manual configuration)
+ MUST be supported by all DIAMETER nodes, while the latter two options
+ (SRVLOC and DNS) MAY be supported.
+
+ There are two cases where Diameter peer discovery may be performed.
+ The first is when a Diameter client needs to discover a first-hop
+ Diameter agent. The second case is when a Diameter agent needs to
+ discover another agent - for further handling of a Diameter
+ operation. In both cases, the following 'search order' is
+ recommended:
+
+ 1. The Diameter implementation consults its list of static (manually)
+ configured Diameter agent locations. These will be used if they
+ exist and respond.
+
+ 2. The Diameter implementation uses SLPv2 [SLP] to discover Diameter
+ services. The Diameter service template [TEMPLATE] is included in
+ Appendix A.
+
+ It is recommended that SLPv2 security be deployed (this requires
+ distributing keys to SLPv2 agents). This is discussed further in
+ Appendix A. SLPv2 security SHOULD be used (requiring distribution
+ of keys to SLPv2 agents) in order to ensure that discovered peers
+ are authorized for their roles. SLPv2 is discussed further in
+ Appendix A.
+
+ 3. The Diameter implementation performs a NAPTR query for a server in
+ a particular realm. The Diameter implementation has to know in
+ advance which realm to look for a Diameter agent in. This could
+ be deduced, for example, from the 'realm' in a NAI that a Diameter
+ implementation needed to perform a Diameter operation on.
+
+ 3.1 The services relevant for the task of transport protocol
+ selection are those with NAPTR service fields with values
+ "AAA+D2x", where x is a letter that corresponds to a transport
+ protocol supported by the domain. This specification defines
+ D2T for TCP and D2S for SCTP. We also establish an IANA
+ registry for NAPTR service name to transport protocol
+ mappings.
+
+ These NAPTR records provide a mapping from a domain, to the
+ SRV record for contacting a server with the specific transport
+ protocol in the NAPTR services field. The resource record
+ will contain an empty regular expression and a replacement
+ value, which is the SRV record for that particular transport
+ protocol. If the server supports multiple transport
+ protocols, there will be multiple NAPTR records, each with a
+ different service value. As per RFC 2915 [NAPTR], the client
+
+
+
+Calhoun, et al. Standards Track [Page 57]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ discards any records whose services fields are not applicable.
+ For the purposes of this specification, several rules are
+ defined.
+
+ 3.2 A client MUST discard any service fields that identify a
+ resolution service whose value is not "D2X", for values of X
+ that indicate transport protocols supported by the client.
+ The NAPTR processing as described in RFC 2915 will result in
+ discovery of the most preferred transport protocol of the
+ server that is supported by the client, as well as an SRV
+ record for the server.
+
+ The domain suffixes in the NAPTR replacement field SHOULD
+ match the domain of the original query.
+
+ 4. If no NAPTR records are found, the requester queries for those
+ address records for the destination address,
+ '_diameter._sctp'.realm or '_diameter._tcp'.realm. Address
+ records include A RR's, AAAA RR's or other similar records, chosen
+ according to the requestor's network protocol capabilities. If
+ the DNS server returns no address records, the requestor gives up.
+
+ If the server is using a site certificate, the domain name in the
+ query and the domain name in the replacement field MUST both be
+ valid based on the site certificate handed out by the server in
+ the TLS or IKE exchange. Similarly, the domain name in the SRV
+ query and the domain name in the target in the SRV record MUST
+ both be valid based on the same site certificate. Otherwise, an
+ attacker could modify the DNS records to contain replacement
+ values in a different domain, and the client could not validate
+ that this was the desired behavior, or the result of an attack
+
+ Also, the Diameter Peer MUST check to make sure that the
+ discovered peers are authorized to act in its role.
+ Authentication via IKE or TLS, or validation of DNS RRs via DNSSEC
+ is not sufficient to conclude this. For example, a web server may
+ have obtained a valid TLS certificate, and secured RRs may be
+ included in the DNS, but this does not imply that it is authorized
+ to act as a Diameter Server.
+
+ Authorization can be achieved for example, by configuration of a
+ Diameter Server CA. Alternatively this can be achieved by
+ definition of OIDs within TLS or IKE certificates so as to signify
+ Diameter Server authorization.
+
+ A dynamically discovered peer causes an entry in the Peer Table (see
+ Section 2.6) to be created. Note that entries created via DNS MUST
+ expire (or be refreshed) within the DNS TTL. If a peer is discovered
+
+
+
+Calhoun, et al. Standards Track [Page 58]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ outside of the local realm, a routing table entry (see Section 2.7)
+ for the peer's realm is created. The routing table entry's
+ expiration MUST match the peer's expiration value.
+
+5.3. Capabilities Exchange
+
+ When two Diameter peers establish a transport connection, they MUST
+ exchange the Capabilities Exchange messages, as specified in the peer
+ state machine (see Section 5.6). This message allows the discovery
+ of a peer's identity and its capabilities (protocol version number,
+ supported Diameter applications, security mechanisms, etc.)
+
+ The receiver only issues commands to its peers that have advertised
+ support for the Diameter application that defines the command. A
+ Diameter node MUST cache the supported applications in order to
+ ensure that unrecognized commands and/or AVPs are not unnecessarily
+ sent to a peer.
+
+ A receiver of a Capabilities-Exchange-Req (CER) message that does not
+ have any applications in common with the sender MUST return a
+ Capabilities-Exchange-Answer (CEA) with the Result-Code AVP set to
+ DIAMETER_NO_COMMON_APPLICATION, and SHOULD disconnect the transport
+ layer connection. Note that receiving a CER or CEA from a peer
+ advertising itself as a Relay (see Section 2.4) MUST be interpreted
+ as having common applications with the peer.
+
+ Similarly, a receiver of a Capabilities-Exchange-Req (CER) message
+ that does not have any security mechanisms in common with the sender
+ MUST return a Capabilities-Exchange-Answer (CEA) with the Result-Code
+ AVP set to DIAMETER_NO_COMMON_SECURITY, and SHOULD disconnect the
+ transport layer connection.
+
+ CERs received from unknown peers MAY be silently discarded, or a CEA
+ MAY be issued with the Result-Code AVP set to DIAMETER_UNKNOWN_PEER.
+ In both cases, the transport connection is closed. If the local
+ policy permits receiving CERs from unknown hosts, a successful CEA
+ MAY be returned. If a CER from an unknown peer is answered with a
+ successful CEA, the lifetime of the peer entry is equal to the
+ lifetime of the transport connection. In case of a transport
+ failure, all the pending transactions destined to the unknown peer
+ can be discarded.
+
+ The CER and CEA messages MUST NOT be proxied, redirected or relayed.
+
+ Since the CER/CEA messages cannot be proxied, it is still possible
+ that an upstream agent receives a message for which it has no
+ available peers to handle the application that corresponds to the
+ Command-Code. In such instances, the 'E' bit is set in the answer
+
+
+
+Calhoun, et al. Standards Track [Page 59]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ message (see Section 7.) with the Result-Code AVP set to
+ DIAMETER_UNABLE_TO_DELIVER to inform the downstream to take action
+ (e.g., re-routing request to an alternate peer).
+
+ With the exception of the Capabilities-Exchange-Request message, a
+ message of type Request that includes the Auth-Application-Id or
+ Acct-Application-Id AVPs, or a message with an application-specific
+ command code, MAY only be forwarded to a host that has explicitly
+ advertised support for the application (or has advertised the Relay
+ Application Identifier).
+
+5.3.1. Capabilities-Exchange-Request
+
+ The Capabilities-Exchange-Request (CER), indicated by the Command-
+ Code set to 257 and the Command Flags' 'R' bit set, is sent to
+ exchange local capabilities. Upon detection of a transport failure,
+ this message MUST NOT be sent to an alternate peer.
+
+ When Diameter is run over SCTP [SCTP], which allows for connections
+ to span multiple interfaces and multiple IP addresses, the
+ Capabilities-Exchange-Request message MUST contain one Host-IP-
+ Address AVP for each potential IP address that MAY be locally used
+ when transmitting Diameter messages.
+
+ Message Format
+
+ <CER> ::= < Diameter Header: 257, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+ 1* { Host-IP-Address }
+ { Vendor-Id }
+ { Product-Name }
+ [ Origin-State-Id ]
+ * [ Supported-Vendor-Id ]
+ * [ Auth-Application-Id ]
+ * [ Inband-Security-Id ]
+ * [ Acct-Application-Id ]
+ * [ Vendor-Specific-Application-Id ]
+ [ Firmware-Revision ]
+ * [ AVP ]
+
+5.3.2. Capabilities-Exchange-Answer
+
+ The Capabilities-Exchange-Answer (CEA), indicated by the Command-Code
+ set to 257 and the Command Flags' 'R' bit cleared, is sent in
+ response to a CER message.
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 60]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ When Diameter is run over SCTP [SCTP], which allows connections to
+ span multiple interfaces, hence, multiple IP addresses, the
+ Capabilities-Exchange-Answer message MUST contain one Host-IP-Address
+ AVP for each potential IP address that MAY be locally used when
+ transmitting Diameter messages.
+
+ Message Format
+
+ <CEA> ::= < Diameter Header: 257 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ 1* { Host-IP-Address }
+ { Vendor-Id }
+ { Product-Name }
+ [ Origin-State-Id ]
+ [ Error-Message ]
+ * [ Failed-AVP ]
+ * [ Supported-Vendor-Id ]
+ * [ Auth-Application-Id ]
+ * [ Inband-Security-Id ]
+ * [ Acct-Application-Id ]
+ * [ Vendor-Specific-Application-Id ]
+ [ Firmware-Revision ]
+ * [ AVP ]
+
+5.3.3. Vendor-Id AVP
+
+ The Vendor-Id AVP (AVP Code 266) is of type Unsigned32 and contains
+ the IANA "SMI Network Management Private Enterprise Codes" [ASSIGNNO]
+ value assigned to the vendor of the Diameter application. In
+ combination with the Supported-Vendor-Id AVP (Section 5.3.6), this
+ MAY be used in order to know which vendor specific attributes may be
+ sent to the peer. It is also envisioned that the combination of the
+ Vendor-Id, Product-Name (Section 5.3.7) and the Firmware-Revision
+ (Section 5.3.4) AVPs MAY provide very useful debugging information.
+
+ A Vendor-Id value of zero in the CER or CEA messages is reserved and
+ indicates that this field is ignored.
+
+5.3.4. Firmware-Revision AVP
+
+ The Firmware-Revision AVP (AVP Code 267) is of type Unsigned32 and is
+ used to inform a Diameter peer of the firmware revision of the
+ issuing device.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 61]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ For devices that do not have a firmware revision (general purpose
+ computers running Diameter software modules, for instance), the
+ revision of the Diameter software module may be reported instead.
+
+5.3.5. Host-IP-Address AVP
+
+ The Host-IP-Address AVP (AVP Code 257) is of type Address and is used
+ to inform a Diameter peer of the sender's IP address. All source
+ addresses that a Diameter node expects to use with SCTP [SCTP] MUST
+ be advertised in the CER and CEA messages by including a Host-IP-
+ Address AVP for each address. This AVP MUST ONLY be used in the CER
+ and CEA messages.
+
+5.3.6. Supported-Vendor-Id AVP
+
+ The Supported-Vendor-Id AVP (AVP Code 265) is of type Unsigned32 and
+ contains the IANA "SMI Network Management Private Enterprise Codes"
+ [ASSIGNNO] value assigned to a vendor other than the device vendor.
+ This is used in the CER and CEA messages in order to inform the peer
+ that the sender supports (a subset of) the vendor-specific AVPs
+ defined by the vendor identified in this AVP.
+
+5.3.7. Product-Name AVP
+
+ The Product-Name AVP (AVP Code 269) is of type UTF8String, and
+ contains the vendor assigned name for the product. The Product-Name
+ AVP SHOULD remain constant across firmware revisions for the same
+ product.
+
+5.4. Disconnecting Peer connections
+
+ When a Diameter node disconnects one of its transport connections,
+ its peer cannot know the reason for the disconnect, and will most
+ likely assume that a connectivity problem occurred, or that the peer
+ has rebooted. In these cases, the peer may periodically attempt to
+ reconnect, as stated in Section 2.1. In the event that the
+ disconnect was a result of either a shortage of internal resources,
+ or simply that the node in question has no intentions of forwarding
+ any Diameter messages to the peer in the foreseeable future, a
+ periodic connection request would not be welcomed. The
+ Disconnection-Reason AVP contains the reason the Diameter node issued
+ the Disconnect-Peer-Request message.
+
+ The Disconnect-Peer-Request message is used by a Diameter node to
+ inform its peer of its intent to disconnect the transport layer, and
+ that the peer shouldn't reconnect unless it has a valid reason to do
+ so (e.g., message to be forwarded). Upon receipt of the message, the
+
+
+
+
+Calhoun, et al. Standards Track [Page 62]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Disconnect-Peer-Answer is returned, which SHOULD contain an error if
+ messages have recently been forwarded, and are likely in flight,
+ which would otherwise cause a race condition.
+
+ The receiver of the Disconnect-Peer-Answer initiates the transport
+ disconnect.
+
+5.4.1. Disconnect-Peer-Request
+
+ The Disconnect-Peer-Request (DPR), indicated by the Command-Code set
+ to 282 and the Command Flags' 'R' bit set, is sent to a peer to
+ inform its intentions to shutdown the transport connection. Upon
+ detection of a transport failure, this message MUST NOT be sent to an
+ alternate peer.
+
+ Message Format
+
+ <DPR> ::= < Diameter Header: 282, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+ { Disconnect-Cause }
+
+5.4.2. Disconnect-Peer-Answer
+
+ The Disconnect-Peer-Answer (DPA), indicated by the Command-Code set
+ to 282 and the Command Flags' 'R' bit cleared, is sent as a response
+ to the Disconnect-Peer-Request message. Upon receipt of this
+ message, the transport connection is shutdown.
+
+ Message Format
+
+ <DPA> ::= < Diameter Header: 282 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Error-Message ]
+ * [ Failed-AVP ]
+
+5.4.3. Disconnect-Cause AVP
+
+ The Disconnect-Cause AVP (AVP Code 273) is of type Enumerated. A
+ Diameter node MUST include this AVP in the Disconnect-Peer-Request
+ message to inform the peer of the reason for its intention to
+ shutdown the transport connection. The following values are
+ supported:
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 63]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ REBOOTING 0
+ A scheduled reboot is imminent.
+
+ BUSY 1
+ The peer's internal resources are constrained, and it has
+ determined that the transport connection needs to be closed.
+
+ DO_NOT_WANT_TO_TALK_TO_YOU 2
+ The peer has determined that it does not see a need for the
+ transport connection to exist, since it does not expect any
+ messages to be exchanged in the near future.
+
+5.5. Transport Failure Detection
+
+ Given the nature of the Diameter protocol, it is recommended that
+ transport failures be detected as soon as possible. Detecting such
+ failures will minimize the occurrence of messages sent to unavailable
+ agents, resulting in unnecessary delays, and will provide better
+ failover performance. The Device-Watchdog-Request and Device-
+ Watchdog-Answer messages, defined in this section, are used to pro-
+ actively detect transport failures.
+
+5.5.1. Device-Watchdog-Request
+
+ The Device-Watchdog-Request (DWR), indicated by the Command-Code set
+ to 280 and the Command Flags' 'R' bit set, is sent to a peer when no
+ traffic has been exchanged between two peers (see Section 5.5.3).
+ Upon detection of a transport failure, this message MUST NOT be sent
+ to an alternate peer.
+
+ Message Format
+
+ <DWR> ::= < Diameter Header: 280, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+ [ Origin-State-Id ]
+
+5.5.2. Device-Watchdog-Answer
+
+ The Device-Watchdog-Answer (DWA), indicated by the Command-Code set
+ to 280 and the Command Flags' 'R' bit cleared, is sent as a response
+ to the Device-Watchdog-Request message.
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 64]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Message Format
+
+ <DWA> ::= < Diameter Header: 280 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Error-Message ]
+ * [ Failed-AVP ]
+ [ Original-State-Id ]
+
+5.5.3. Transport Failure Algorithm
+
+ The transport failure algorithm is defined in [AAATRANS]. All
+ Diameter implementations MUST support the algorithm defined in the
+ specification in order to be compliant to the Diameter base protocol.
+
+5.5.4. Failover and Failback Procedures
+
+ In the event that a transport failure is detected with a peer, it is
+ necessary for all pending request messages to be forwarded to an
+ alternate agent, if possible. This is commonly referred to as
+ failover.
+
+ In order for a Diameter node to perform failover procedures, it is
+ necessary for the node to maintain a pending message queue for a
+ given peer. When an answer message is received, the corresponding
+ request is removed from the queue. The Hop-by-Hop Identifier field
+ is used to match the answer with the queued request.
+
+ When a transport failure is detected, if possible all messages in the
+ queue are sent to an alternate agent with the T flag set. On booting
+ a Diameter client or agent, the T flag is also set on any records
+ still remaining to be transmitted in non-volatile storage. An
+ example of a case where it is not possible to forward the message to
+ an alternate server is when the message has a fixed destination, and
+ the unavailable peer is the message's final destination (see
+ Destination-Host AVP). Such an error requires that the agent return
+ an answer message with the 'E' bit set and the Result-Code AVP set to
+ DIAMETER_UNABLE_TO_DELIVER.
+
+ It is important to note that multiple identical requests or answers
+ MAY be received as a result of a failover. The End-to-End Identifier
+ field in the Diameter header along with the Origin-Host AVP MUST be
+ used to identify duplicate messages.
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 65]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ As described in Section 2.1, a connection request should be
+ periodically attempted with the failed peer in order to re-establish
+ the transport connection. Once a connection has been successfully
+ established, messages can once again be forwarded to the peer. This
+ is commonly referred to as failback.
+
+5.6. Peer State Machine
+
+ This section contains a finite state machine that MUST be observed by
+ all Diameter implementations. Each Diameter node MUST follow the
+ state machine described below when communicating with each peer.
+ Multiple actions are separated by commas, and may continue on
+ succeeding lines, as space requires. Similarly, state and next state
+ may also span multiple lines, as space requires.
+
+ This state machine is closely coupled with the state machine
+ described in [AAATRANS], which is used to open, close, failover,
+ probe, and reopen transport connections. Note in particular that
+ [AAATRANS] requires the use of watchdog messages to probe
+ connections. For Diameter, DWR and DWA messages are to be used.
+
+ I- is used to represent the initiator (connecting) connection, while
+ the R- is used to represent the responder (listening) connection.
+ The lack of a prefix indicates that the event or action is the same
+ regardless of the connection on which the event occurred.
+
+ The stable states that a state machine may be in are Closed, I-Open
+ and R-Open; all other states are intermediate. Note that I-Open and
+ R-Open are equivalent except for whether the initiator or responder
+ transport connection is used for communication.
+
+ A CER message is always sent on the initiating connection immediately
+ after the connection request is successfully completed. In the case
+ of an election, one of the two connections will shut down. The
+ responder connection will survive if the Origin-Host of the local
+ Diameter entity is higher than that of the peer; the initiator
+ connection will survive if the peer's Origin-Host is higher. All
+ subsequent messages are sent on the surviving connection. Note that
+ the results of an election on one peer are guaranteed to be the
+ inverse of the results on the other.
+
+ For TLS usage, a TLS handshake will begin when both ends are in the
+ open state. If the TLS handshake is successful, all further messages
+ will be sent via TLS. If the handshake fails, both ends move to the
+ closed state.
+
+ The state machine constrains only the behavior of a Diameter
+ implementation as seen by Diameter peers through events on the wire.
+
+
+
+Calhoun, et al. Standards Track [Page 66]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Any implementation that produces equivalent results is considered
+ compliant.
+
+ state event action next state
+ -----------------------------------------------------------------
+ Closed Start I-Snd-Conn-Req Wait-Conn-Ack
+ R-Conn-CER R-Accept, R-Open
+ Process-CER,
+ R-Snd-CEA
+
+ Wait-Conn-Ack I-Rcv-Conn-Ack I-Snd-CER Wait-I-CEA
+ I-Rcv-Conn-Nack Cleanup Closed
+ R-Conn-CER R-Accept, Wait-Conn-Ack/
+ Process-CER Elect
+ Timeout Error Closed
+
+ Wait-I-CEA I-Rcv-CEA Process-CEA I-Open
+ R-Conn-CER R-Accept, Wait-Returns
+ Process-CER,
+ Elect
+ I-Peer-Disc I-Disc Closed
+ I-Rcv-Non-CEA Error Closed
+ Timeout Error Closed
+
+ Wait-Conn-Ack/ I-Rcv-Conn-Ack I-Snd-CER,Elect Wait-Returns
+ Elect I-Rcv-Conn-Nack R-Snd-CEA R-Open
+ R-Peer-Disc R-Disc Wait-Conn-Ack
+ R-Conn-CER R-Reject Wait-Conn-Ack/
+ Elect
+ Timeout Error Closed
+
+ Wait-Returns Win-Election I-Disc,R-Snd-CEA R-Open
+ I-Peer-Disc I-Disc, R-Open
+ R-Snd-CEA
+ I-Rcv-CEA R-Disc I-Open
+ R-Peer-Disc R-Disc Wait-I-CEA
+ R-Conn-CER R-Reject Wait-Returns
+ Timeout Error Closed
+
+ R-Open Send-Message R-Snd-Message R-Open
+ R-Rcv-Message Process R-Open
+ R-Rcv-DWR Process-DWR, R-Open
+ R-Snd-DWA
+ R-Rcv-DWA Process-DWA R-Open
+ R-Conn-CER R-Reject R-Open
+ Stop R-Snd-DPR Closing
+ R-Rcv-DPR R-Snd-DPA, Closed
+ R-Disc
+
+
+
+Calhoun, et al. Standards Track [Page 67]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ R-Peer-Disc R-Disc Closed
+ R-Rcv-CER R-Snd-CEA R-Open
+ R-Rcv-CEA Process-CEA R-Open
+
+ I-Open Send-Message I-Snd-Message I-Open
+ I-Rcv-Message Process I-Open
+ I-Rcv-DWR Process-DWR, I-Open
+ I-Snd-DWA
+ I-Rcv-DWA Process-DWA I-Open
+ R-Conn-CER R-Reject I-Open
+ Stop I-Snd-DPR Closing
+ I-Rcv-DPR I-Snd-DPA, Closed
+ I-Disc
+ I-Peer-Disc I-Disc Closed
+ I-Rcv-CER I-Snd-CEA I-Open
+ I-Rcv-CEA Process-CEA I-Open
+
+ Closing I-Rcv-DPA I-Disc Closed
+ R-Rcv-DPA R-Disc Closed
+ Timeout Error Closed
+ I-Peer-Disc I-Disc Closed
+ R-Peer-Disc R-Disc Closed
+
+5.6.1. Incoming connections
+
+ When a connection request is received from a Diameter peer, it is
+ not, in the general case, possible to know the identity of that peer
+ until a CER is received from it. This is because host and port
+ determine the identity of a Diameter peer; and the source port of an
+ incoming connection is arbitrary. Upon receipt of CER, the identity
+ of the connecting peer can be uniquely determined from Origin-Host.
+
+ For this reason, a Diameter peer must employ logic separate from the
+ state machine to receive connection requests, accept them, and await
+ CER. Once CER arrives on a new connection, the Origin-Host that
+ identifies the peer is used to locate the state machine associated
+ with that peer, and the new connection and CER are passed to the
+ state machine as an R-Conn-CER event.
+
+ The logic that handles incoming connections SHOULD close and discard
+ the connection if any message other than CER arrives, or if an
+ implementation-defined timeout occurs prior to receipt of CER.
+
+ Because handling of incoming connections up to and including receipt
+ of CER requires logic, separate from that of any individual state
+ machine associated with a particular peer, it is described separately
+ in this section rather than in the state machine above.
+
+
+
+
+Calhoun, et al. Standards Track [Page 68]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+5.6.2. Events
+
+ Transitions and actions in the automaton are caused by events. In
+ this section, we will ignore the -I and -R prefix, since the actual
+ event would be identical, but would occur on one of two possible
+ connections.
+
+ Start The Diameter application has signaled that a
+ connection should be initiated with the peer.
+
+ R-Conn-CER An acknowledgement is received stating that the
+ transport connection has been established, and the
+ associated CER has arrived.
+
+ Rcv-Conn-Ack A positive acknowledgement is received confirming that
+ the transport connection is established.
+
+ Rcv-Conn-Nack A negative acknowledgement was received stating that
+ the transport connection was not established.
+
+ Timeout An application-defined timer has expired while waiting
+ for some event.
+
+ Rcv-CER A CER message from the peer was received.
+
+ Rcv-CEA A CEA message from the peer was received.
+
+ Rcv-Non-CEA A message other than CEA from the peer was received.
+
+ Peer-Disc A disconnection indication from the peer was received.
+
+ Rcv-DPR A DPR message from the peer was received.
+
+ Rcv-DPA A DPA message from the peer was received.
+
+ Win-Election An election was held, and the local node was the
+ winner.
+
+ Send-Message A message is to be sent.
+
+ Rcv-Message A message other than CER, CEA, DPR, DPA, DWR or DWA
+ was received.
+
+ Stop The Diameter application has signaled that a
+ connection should be terminated (e.g., on system
+ shutdown).
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 69]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+5.6.3. Actions
+
+ Actions in the automaton are caused by events and typically indicate
+ the transmission of packets and/or an action to be taken on the
+ connection. In this section we will ignore the I- and R-prefix,
+ since the actual action would be identical, but would occur on one of
+ two possible connections.
+
+ Snd-Conn-Req A transport connection is initiated with the peer.
+
+ Accept The incoming connection associated with the R-Conn-CER
+ is accepted as the responder connection.
+
+ Reject The incoming connection associated with the R-Conn-CER
+ is disconnected.
+
+ Process-CER The CER associated with the R-Conn-CER is processed.
+
+ Snd-CER A CER message is sent to the peer.
+
+ Snd-CEA A CEA message is sent to the peer.
+
+ Cleanup If necessary, the connection is shutdown, and any
+ local resources are freed.
+
+ Error The transport layer connection is disconnected, either
+ politely or abortively, in response to an error
+ condition. Local resources are freed.
+
+ Process-CEA A received CEA is processed.
+
+ Snd-DPR A DPR message is sent to the peer.
+
+ Snd-DPA A DPA message is sent to the peer.
+
+ Disc The transport layer connection is disconnected, and
+ local resources are freed.
+
+ Elect An election occurs (see Section 5.6.4 for more
+ information).
+
+ Snd-Message A message is sent.
+
+ Snd-DWR A DWR message is sent.
+
+ Snd-DWA A DWA message is sent.
+
+ Process-DWR The DWR message is serviced.
+
+
+
+Calhoun, et al. Standards Track [Page 70]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Process-DWA The DWA message is serviced.
+
+ Process A message is serviced.
+
+5.6.4. The Election Process
+
+ The election is performed on the responder. The responder compares
+ the Origin-Host received in the CER sent by its peer with its own
+ Origin-Host. If the local Diameter entity's Origin-Host is higher
+ than the peer's, a Win-Election event is issued locally.
+
+ The comparison proceeds by considering the shorter OctetString to be
+ padded with zeros so that it length is the same as the length of the
+ longer, then performing an octet-by-octet unsigned comparison with
+ the first octet being most significant. Any remaining octets are
+ assumed to have value 0x80.
+
+6. Diameter message processing
+
+ This section describes how Diameter requests and answers are created
+ and processed.
+
+6.1. Diameter Request Routing Overview
+
+ A request is sent towards its final destination using a combination
+ of the Destination-Realm and Destination-Host AVPs, in one of these
+ three combinations:
+
+ - a request that is not able to be proxied (such as CER) MUST NOT
+ contain either Destination-Realm or Destination-Host AVPs.
+
+ - a request that needs to be sent to a home server serving a
+ specific realm, but not to a specific server (such as the first
+ request of a series of round-trips), MUST contain a Destination-
+ Realm AVP, but MUST NOT contain a Destination-Host AVP.
+
+ - otherwise, a request that needs to be sent to a specific home
+ server among those serving a given realm, MUST contain both the
+ Destination-Realm and Destination-Host AVPs.
+
+ The Destination-Host AVP is used as described above when the
+ destination of the request is fixed, which includes:
+
+ - Authentication requests that span multiple round trips
+
+ - A Diameter message that uses a security mechanism that makes use
+ of a pre-established session key shared between the source and the
+ final destination of the message.
+
+
+
+Calhoun, et al. Standards Track [Page 71]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ - Server initiated messages that MUST be received by a specific
+ Diameter client (e.g., access device), such as the Abort-Session-
+ Request message, which is used to request that a particular user's
+ session be terminated.
+
+ Note that an agent can forward a request to a host described in the
+ Destination-Host AVP only if the host in question is included in its
+ peer table (see Section 2.7). Otherwise, the request is routed based
+ on the Destination-Realm only (see Sections 6.1.6).
+
+ The Destination-Realm AVP MUST be present if the message is
+ proxiable. Request messages that may be forwarded by Diameter agents
+ (proxies, redirects or relays) MUST also contain an Acct-
+ Application-Id AVP, an Auth-Application-Id AVP or a Vendor-Specific-
+ Application-Id AVP. A message that MUST NOT be forwarded by Diameter
+ agents (proxies, redirects or relays) MUST not include the
+ Destination-Realm in its ABNF. The value of the Destination-Realm
+ AVP MAY be extracted from the User-Name AVP, or other application-
+ specific methods.
+
+ When a message is received, the message is processed in the following
+ order:
+
+ 1. If the message is destined for the local host, the procedures
+ listed in Section 6.1.4 are followed.
+
+ 2. If the message is intended for a Diameter peer with whom the local
+ host is able to directly communicate, the procedures listed in
+ Section 6.1.5 are followed. This is known as Request Forwarding.
+
+ 3. The procedures listed in Section 6.1.6 are followed, which is
+ known as Request Routing.
+
+ 4. If none of the above is successful, an answer is returned with the
+ Result-Code set to DIAMETER_UNABLE_TO_DELIVER, with the E-bit set.
+
+ For routing of Diameter messages to work within an administrative
+ domain, all Diameter nodes within the realm MUST be peers.
+
+ Note the processing rules contained in this section are intended to
+ be used as general guidelines to Diameter developers. Certain
+ implementations MAY use different methods than the ones described
+ here, and still comply with the protocol specification. See Section
+ 7 for more detail on error handling.
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 72]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+6.1.1. Originating a Request
+
+ When creating a request, in addition to any other procedures
+ described in the application definition for that specific request,
+ the following procedures MUST be followed:
+
+ - the Command-Code is set to the appropriate value
+
+ - the 'R' bit is set
+
+ - the End-to-End Identifier is set to a locally unique value
+
+ - the Origin-Host and Origin-Realm AVPs MUST be set to the
+ appropriate values, used to identify the source of the message
+
+ - the Destination-Host and Destination-Realm AVPs MUST be set to the
+ appropriate values as described in Section 6.1.
+
+ - an Acct-Application-Id AVP, an Auth-Application-Id or a Vendor-
+ Specific-Application-Id AVP must be included if the request is
+ proxiable.
+
+6.1.2. Sending a Request
+
+ When sending a request, originated either locally, or as the result
+ of a forwarding or routing operation, the following procedures MUST
+ be followed:
+
+ - the Hop-by-Hop Identifier should be set to a locally unique value
+
+ - The message should be saved in the list of pending requests.
+
+ Other actions to perform on the message based on the particular role
+ the agent is playing are described in the following sections.
+
+6.1.3. Receiving Requests
+
+ A relay or proxy agent MUST check for forwarding loops when receiving
+ requests. A loop is detected if the server finds its own identity in
+ a Route-Record AVP. When such an event occurs, the agent MUST answer
+ with the Result-Code AVP set to DIAMETER_LOOP_DETECTED.
+
+6.1.4. Processing Local Requests
+
+ A request is known to be for local consumption when one of the
+ following conditions occur:
+
+ - The Destination-Host AVP contains the local host's identity,
+
+
+
+Calhoun, et al. Standards Track [Page 73]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ - The Destination-Host AVP is not present, the Destination-Realm AVP
+ contains a realm the server is configured to process locally, and
+ the Diameter application is locally supported, or
+
+ - Both the Destination-Host and the Destination-Realm are not
+ present.
+
+ When a request is locally processed, the rules in Section 6.2 should
+ be used to generate the corresponding answer.
+
+6.1.5. Request Forwarding
+
+ Request forwarding is done using the Diameter Peer Table. The
+ Diameter peer table contains all of the peers that the local node is
+ able to directly communicate with.
+
+ When a request is received, and the host encoded in the Destination-
+ Host AVP is one that is present in the peer table, the message SHOULD
+ be forwarded to the peer.
+
+6.1.6. Request Routing
+
+ Diameter request message routing is done via realms and applications.
+ A Diameter message that may be forwarded by Diameter agents (proxies,
+ redirects or relays) MUST include the target realm in the
+ Destination-Realm AVP and one of the application identification AVPs
+ Auth-Application-Id, Acct-Application-Id or Vendor-Specific-
+ Application-Id. The realm MAY be retrieved from the User-Name AVP,
+ which is in the form of a Network Access Identifier (NAI). The realm
+ portion of the NAI is inserted in the Destination-Realm AVP.
+
+ Diameter agents MAY have a list of locally supported realms and
+ applications, and MAY have a list of externally supported realms and
+ applications. When a request is received that includes a realm
+ and/or application that is not locally supported, the message is
+ routed to the peer configured in the Realm Routing Table (see Section
+ 2.7).
+
+6.1.7. Redirecting requests
+
+ When a redirect agent receives a request whose routing entry is set
+ to REDIRECT, it MUST reply with an answer message with the 'E' bit
+ set, while maintaining the Hop-by-Hop Identifier in the header, and
+ include the Result-Code AVP to DIAMETER_REDIRECT_INDICATION. Each of
+ the servers associated with the routing entry are added in separate
+ Redirect-Host AVP.
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 74]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ +------------------+
+ | Diameter |
+ | Redirect Agent |
+ +------------------+
+ ^ | 2. command + 'E' bit
+ 1. Request | | Result-Code =
+ [email protected] | | DIAMETER_REDIRECT_INDICATION +
+ | | Redirect-Host AVP(s)
+ | v
+ +-------------+ 3. Request +-------------+
+ | example.com |------------->| example.net |
+ | Relay | | Diameter |
+ | Agent |<-------------| Server |
+ +-------------+ 4. Answer +-------------+
+
+ Figure 5: Diameter Redirect Agent
+
+ The receiver of the answer message with the 'E' bit set, and the
+ Result-Code AVP set to DIAMETER_REDIRECT_INDICATION uses the hop-by-
+ hop field in the Diameter header to identify the request in the
+ pending message queue (see Section 5.3) that is to be redirected. If
+ no transport connection exists with the new agent, one is created,
+ and the request is sent directly to it.
+
+ Multiple Redirect-Host AVPs are allowed. The receiver of the answer
+ message with the 'E' bit set selects exactly one of these hosts as
+ the destination of the redirected message.
+
+6.1.8. Relaying and Proxying Requests
+
+ A relay or proxy agent MUST append a Route-Record AVP to all requests
+ forwarded. The AVP contains the identity of the peer the request was
+ received from.
+
+ The Hop-by-Hop identifier in the request is saved, and replaced with
+ a locally unique value. The source of the request is also saved,
+ which includes the IP address, port and protocol.
+
+ A relay or proxy agent MAY include the Proxy-Info AVP in requests if
+ it requires access to any local state information when the
+ corresponding response is received. Proxy-Info AVP has certain
+ security implications and SHOULD contain an embedded HMAC with a
+ node-local key. Alternatively, it MAY simply use local storage to
+ store state information.
+
+ The message is then forwarded to the next hop, as identified in the
+ Realm Routing Table.
+
+
+
+
+Calhoun, et al. Standards Track [Page 75]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Figure 6 provides an example of message routing using the procedures
+ listed in these sections.
+
+ (Origin-Host=nas.mno.net) (Origin-Host=nas.mno.net)
+ (Origin-Realm=mno.net) (Origin-Realm=mno.net)
+ (Destination-Realm=example.com) (Destination-
+ Realm=example.com)
+ (Route-Record=nas.example.net)
+ +------+ ------> +------+ ------> +------+
+ | | (Request) | | (Request) | |
+ | NAS +-------------------+ DRL +-------------------+ HMS |
+ | | | | | |
+ +------+ <------ +------+ <------ +------+
+ example.net (Answer) example.net (Answer) example.com
+ (Origin-Host=hms.example.com) (Origin-Host=hms.example.com)
+ (Origin-Realm=example.com) (Origin-Realm=example.com)
+
+ Figure 6: Routing of Diameter messages
+
+6.2. Diameter Answer Processing
+
+ When a request is locally processed, the following procedures MUST be
+ applied to create the associated answer, in addition to any
+ additional procedures that MAY be discussed in the Diameter
+ application defining the command:
+
+ - The same Hop-by-Hop identifier in the request is used in the
+ answer.
+
+ - The local host's identity is encoded in the Origin-Host AVP.
+
+ - The Destination-Host and Destination-Realm AVPs MUST NOT be
+ present in the answer message.
+
+ - The Result-Code AVP is added with its value indicating success or
+ failure.
+
+ - If the Session-Id is present in the request, it MUST be included
+ in the answer.
+
+ - Any Proxy-Info AVPs in the request MUST be added to the answer
+ message, in the same order they were present in the request.
+
+ - The 'P' bit is set to the same value as the one in the request.
+
+ - The same End-to-End identifier in the request is used in the
+ answer.
+
+
+
+
+Calhoun, et al. Standards Track [Page 76]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Note that the error messages (see Section 7.3) are also subjected to
+ the above processing rules.
+
+6.2.1. Processing received Answers
+
+ A Diameter client or proxy MUST match the Hop-by-Hop Identifier in an
+ answer received against the list of pending requests. The
+ corresponding message should be removed from the list of pending
+ requests. It SHOULD ignore answers received that do not match a
+ known Hop-by-Hop Identifier.
+
+6.2.2. Relaying and Proxying Answers
+
+ If the answer is for a request which was proxied or relayed, the
+ agent MUST restore the original value of the Diameter header's Hop-
+ by-Hop Identifier field.
+
+ If the last Proxy-Info AVP in the message is targeted to the local
+ Diameter server, the AVP MUST be removed before the answer is
+ forwarded.
+
+ If a relay or proxy agent receives an answer with a Result-Code AVP
+ indicating a failure, it MUST NOT modify the contents of the AVP.
+ Any additional local errors detected SHOULD be logged, but not
+ reflected in the Result-Code AVP. If the agent receives an answer
+ message with a Result-Code AVP indicating success, and it wishes to
+ modify the AVP to indicate an error, it MUST modify the Result-Code
+ AVP to contain the appropriate error in the message destined towards
+ the access device as well as include the Error-Reporting-Host AVP and
+ it MUST issue an STR on behalf of the access device.
+
+ The agent MUST then send the answer to the host that it received the
+ original request from.
+
+6.3. Origin-Host AVP
+
+ The Origin-Host AVP (AVP Code 264) is of type DiameterIdentity, and
+ MUST be present in all Diameter messages. This AVP identifies the
+ endpoint that originated the Diameter message. Relay agents MUST NOT
+ modify this AVP.
+
+ The value of the Origin-Host AVP is guaranteed to be unique within a
+ single host.
+
+ Note that the Origin-Host AVP may resolve to more than one address as
+ the Diameter peer may support more than one address.
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 77]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ This AVP SHOULD be placed as close to the Diameter header as
+ possible. 6.10
+
+6.4. Origin-Realm AVP
+
+ The Origin-Realm AVP (AVP Code 296) is of type DiameterIdentity.
+ This AVP contains the Realm of the originator of any Diameter message
+ and MUST be present in all messages.
+
+ This AVP SHOULD be placed as close to the Diameter header as
+ possible.
+
+6.5. Destination-Host AVP
+
+ The Destination-Host AVP (AVP Code 293) is of type DiameterIdentity.
+ This AVP MUST be present in all unsolicited agent initiated messages,
+ MAY be present in request messages, and MUST NOT be present in Answer
+ messages.
+
+ The absence of the Destination-Host AVP will cause a message to be
+ sent to any Diameter server supporting the application within the
+ realm specified in Destination-Realm AVP.
+
+ This AVP SHOULD be placed as close to the Diameter header as
+ possible.
+
+6.6. Destination-Realm AVP
+
+ The Destination-Realm AVP (AVP Code 283) is of type DiameterIdentity,
+ and contains the realm the message is to be routed to. The
+ Destination-Realm AVP MUST NOT be present in Answer messages.
+ Diameter Clients insert the realm portion of the User-Name AVP.
+ Diameter servers initiating a request message use the value of the
+ Origin-Realm AVP from a previous message received from the intended
+ target host (unless it is known a priori). When present, the
+ Destination-Realm AVP is used to perform message routing decisions.
+
+ Request messages whose ABNF does not list the Destination-Realm AVP
+ as a mandatory AVP are inherently non-routable messages.
+
+ This AVP SHOULD be placed as close to the Diameter header as
+ possible.
+
+6.7. Routing AVPs
+
+ The AVPs defined in this section are Diameter AVPs used for routing
+ purposes. These AVPs change as Diameter messages are processed by
+ agents, and therefore MUST NOT be protected by end-to-end security.
+
+
+
+Calhoun, et al. Standards Track [Page 78]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+6.7.1. Route-Record AVP
+
+ The Route-Record AVP (AVP Code 282) is of type DiameterIdentity. The
+ identity added in this AVP MUST be the same as the one received in
+ the Origin-Host of the Capabilities Exchange message.
+
+6.7.2. Proxy-Info AVP
+
+ The Proxy-Info AVP (AVP Code 284) is of type Grouped. The Grouped
+ Data field has the following ABNF grammar:
+
+ Proxy-Info ::= < AVP Header: 284 >
+ { Proxy-Host }
+ { Proxy-State }
+ * [ AVP ]
+
+6.7.3. Proxy-Host AVP
+
+ The Proxy-Host AVP (AVP Code 280) is of type DiameterIdentity. This
+ AVP contains the identity of the host that added the Proxy-Info AVP.
+
+6.7.4. Proxy-State AVP
+
+ The Proxy-State AVP (AVP Code 33) is of type OctetString, and
+ contains state local information, and MUST be treated as opaque data.
+
+6.8. Auth-Application-Id AVP
+
+ The Auth-Application-Id AVP (AVP Code 258) is of type Unsigned32 and
+ is used in order to advertise support of the Authentication and
+ Authorization portion of an application (see Section 2.4). The
+ Auth-Application-Id MUST also be present in all Authentication and/or
+ Authorization messages that are defined in a separate Diameter
+ specification and have an Application ID assigned.
+
+6.9. Acct-Application-Id AVP
+
+ The Acct-Application-Id AVP (AVP Code 259) is of type Unsigned32 and
+ is used in order to advertise support of the Accounting portion of an
+ application (see Section 2.4). The Acct-Application-Id MUST also be
+ present in all Accounting messages. Exactly one of the Auth-
+ Application-Id and Acct-Application-Id AVPs MAY be present.
+
+6.10. Inband-Security-Id AVP
+
+ The Inband-Security-Id AVP (AVP Code 299) is of type Unsigned32 and
+ is used in order to advertise support of the Security portion of the
+ application.
+
+
+
+Calhoun, et al. Standards Track [Page 79]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Currently, the following values are supported, but there is ample
+ room to add new security Ids.
+
+ NO_INBAND_SECURITY 0
+ This peer does not support TLS. This is the default value, if the
+ AVP is omitted.
+
+ TLS 1
+ This node supports TLS security, as defined by [TLS].
+
+6.11. Vendor-Specific-Application-Id AVP
+
+ The Vendor-Specific-Application-Id AVP (AVP Code 260) is of type
+ Grouped and is used to advertise support of a vendor-specific
+ Diameter Application. Exactly one of the Auth-Application-Id and
+ Acct-Application-Id AVPs MAY be present.
+
+ This AVP MUST also be present as the first AVP in all experimental
+ commands defined in the vendor-specific application.
+
+ This AVP SHOULD be placed as close to the Diameter header as
+ possible.
+
+ AVP Format
+
+ <Vendor-Specific-Application-Id> ::= < AVP Header: 260 >
+ 1* [ Vendor-Id ]
+ 0*1{ Auth-Application-Id }
+ 0*1{ Acct-Application-Id }
+
+6.12. Redirect-Host AVP
+
+ One or more of instances of this AVP MUST be present if the answer
+ message's 'E' bit is set and the Result-Code AVP is set to
+ DIAMETER_REDIRECT_INDICATION.
+
+ Upon receiving the above, the receiving Diameter node SHOULD forward
+ the request directly to one of the hosts identified in these AVPs.
+ The server contained in the selected Redirect-Host AVP SHOULD be used
+ for all messages pertaining to this session.
+
+6.13. Redirect-Host-Usage AVP
+
+ The Redirect-Host-Usage AVP (AVP Code 261) is of type Enumerated.
+ This AVP MAY be present in answer messages whose 'E' bit is set and
+ the Result-Code AVP is set to DIAMETER_REDIRECT_INDICATION.
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 80]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ When present, this AVP dictates how the routing entry resulting from
+ the Redirect-Host is to be used. The following values are supported:
+
+ DONT_CACHE 0
+ The host specified in the Redirect-Host AVP should not be cached.
+ This is the default value.
+
+ ALL_SESSION 1
+ All messages within the same session, as defined by the same value
+ of the Session-ID AVP MAY be sent to the host specified in the
+ Redirect-Host AVP.
+
+ ALL_REALM 2
+ All messages destined for the realm requested MAY be sent to the
+ host specified in the Redirect-Host AVP.
+
+ REALM_AND_APPLICATION 3
+ All messages for the application requested to the realm specified
+ MAY be sent to the host specified in the Redirect-Host AVP.
+
+ ALL_APPLICATION 4
+ All messages for the application requested MAY be sent to the host
+ specified in the Redirect-Host AVP.
+
+ ALL_HOST 5
+ All messages that would be sent to the host that generated the
+ Redirect-Host MAY be sent to the host specified in the Redirect-
+ Host AVP.
+
+ ALL_USER 6
+ All messages for the user requested MAY be sent to the host
+ specified in the Redirect-Host AVP.
+
+6.14. Redirect-Max-Cache-Time AVP
+
+ The Redirect-Max-Cache-Time AVP (AVP Code 262) is of type Unsigned32.
+ This AVP MUST be present in answer messages whose 'E' bit is set, the
+ Result-Code AVP is set to DIAMETER_REDIRECT_INDICATION and the
+ Redirect-Host-Usage AVP set to a non-zero value.
+
+ This AVP contains the maximum number of seconds the peer and route
+ table entries, created as a result of the Redirect-Host, will be
+ cached. Note that once a host created due to a redirect indication
+ is no longer reachable, any associated peer and routing table entries
+ MUST be deleted.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 81]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+6.15. E2E-Sequence AVP
+
+ The E2E-Sequence AVP (AVP Code 300) provides anti-replay protection
+ for end to end messages and is of type grouped. It contains a random
+ value (an OctetString with a nonce) and counter (an Integer). For
+ each end-to-end peer with which a node communicates (or remembers
+ communicating) a different nonce value MUST be used and the counter
+ is initiated at zero and increases by one each time this AVP is
+ emitted to that peer. This AVP MUST be included in all messages
+ which use end-to-end protection (e.g., CMS signing or encryption).
+
+7. Error Handling
+
+ There are two different types of errors in Diameter; protocol and
+ application errors. A protocol error is one that occurs at the base
+ protocol level, and MAY require per hop attention (e.g., message
+ routing error). Application errors, on the other hand, generally
+ occur due to a problem with a function specified in a Diameter
+ application (e.g., user authentication, Missing AVP).
+
+ Result-Code AVP values that are used to report protocol errors MUST
+ only be present in answer messages whose 'E' bit is set. When a
+ request message is received that causes a protocol error, an answer
+ message is returned with the 'E' bit set, and the Result-Code AVP is
+ set to the appropriate protocol error value. As the answer is sent
+ back towards the originator of the request, each proxy or relay agent
+ MAY take action on the message.
+
+ 1. Request +---------+ Link Broken
+ +-------------------------->|Diameter |----///----+
+ | +---------------------| | v
+ +------+--+ | 2. answer + 'E' set | Relay 2 | +--------+
+ |Diameter |<-+ (Unable to Forward) +---------+ |Diameter|
+ | | | Home |
+ | Relay 1 |--+ +---------+ | Server |
+ +---------+ | 3. Request |Diameter | +--------+
+ +-------------------->| | ^
+ | Relay 3 |-----------+
+ +---------+
+
+ Figure 7: Example of Protocol Error causing answer message
+
+ Figure 7 provides an example of a message forwarded upstream by a
+ Diameter relay. When the message is received by Relay 2, and it
+ detects that it cannot forward the request to the home server, an
+ answer message is returned with the 'E' bit set and the Result-Code
+ AVP set to DIAMETER_UNABLE_TO_DELIVER. Given that this error falls
+
+
+
+
+Calhoun, et al. Standards Track [Page 82]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ within the protocol error category, Relay 1 would take special
+ action, and given the error, attempt to route the message through its
+ alternate Relay 3.
+
+ +---------+ 1. Request +---------+ 2. Request +---------+
+ | Access |------------>|Diameter |------------>|Diameter |
+ | | | | | Home |
+ | Device |<------------| Relay |<------------| Server |
+ +---------+ 4. Answer +---------+ 3. Answer +---------+
+ (Missing AVP) (Missing AVP)
+
+ Figure 8: Example of Application Error Answer message
+
+ Figure 8 provides an example of a Diameter message that caused an
+ application error. When application errors occur, the Diameter
+ entity reporting the error clears the 'R' bit in the Command Flags,
+ and adds the Result-Code AVP with the proper value. Application
+ errors do not require any proxy or relay agent involvement, and
+ therefore the message would be forwarded back to the originator of
+ the request.
+
+ There are certain Result-Code AVP application errors that require
+ additional AVPs to be present in the answer. In these cases, the
+ Diameter node that sets the Result-Code AVP to indicate the error
+ MUST add the AVPs. Examples are:
+
+ - An unrecognized AVP is received with the 'M' bit (Mandatory bit)
+ set, causes an answer to be sent with the Result-Code AVP set to
+ DIAMETER_AVP_UNSUPPORTED, and the Failed-AVP AVP containing the
+ offending AVP.
+
+ - An AVP that is received with an unrecognized value causes an
+ answer to be returned with the Result-Code AVP set to
+ DIAMETER_INVALID_AVP_VALUE, with the Failed-AVP AVP containing the
+ AVP causing the error.
+
+ - A command is received with an AVP that is omitted, yet is
+ mandatory according to the command's ABNF. The receiver issues an
+ answer with the Result-Code set to DIAMETER_MISSING_AVP, and
+ creates an AVP with the AVP Code and other fields set as expected
+ in the missing AVP. The created AVP is then added to the Failed-
+ AVP AVP.
+
+ The Result-Code AVP describes the error that the Diameter node
+ encountered in its processing. In case there are multiple errors,
+ the Diameter node MUST report only the first error it encountered
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 83]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ (detected possibly in some implementation dependent order). The
+ specific errors that can be described by this AVP are described in
+ the following section.
+
+7.1. Result-Code AVP
+
+ The Result-Code AVP (AVP Code 268) is of type Unsigned32 and
+ indicates whether a particular request was completed successfully or
+ whether an error occurred. All Diameter answer messages defined in
+ IETF applications MUST include one Result-Code AVP. A non-successful
+ Result-Code AVP (one containing a non 2xxx value other than
+ DIAMETER_REDIRECT_INDICATION) MUST include the Error-Reporting-Host
+ AVP if the host setting the Result-Code AVP is different from the
+ identity encoded in the Origin-Host AVP.
+
+ The Result-Code data field contains an IANA-managed 32-bit address
+ space representing errors (see Section 11.4). Diameter provides the
+ following classes of errors, all identified by the thousands digit in
+ the decimal notation:
+
+ - 1xxx (Informational)
+ - 2xxx (Success)
+ - 3xxx (Protocol Errors)
+ - 4xxx (Transient Failures)
+ - 5xxx (Permanent Failure)
+
+ A non-recognized class (one whose first digit is not defined in this
+ section) MUST be handled as a permanent failure.
+
+7.1.1. Informational
+
+ Errors that fall within this category are used to inform the
+ requester that a request could not be satisfied, and additional
+ action is required on its part before access is granted.
+
+ DIAMETER_MULTI_ROUND_AUTH 1001
+ This informational error is returned by a Diameter server to
+ inform the access device that the authentication mechanism being
+ used requires multiple round trips, and a subsequent request needs
+ to be issued in order for access to be granted.
+
+7.1.2. Success
+
+ Errors that fall within the Success category are used to inform a
+ peer that a request has been successfully completed.
+
+ DIAMETER_SUCCESS 2001
+ The Request was successfully completed.
+
+
+
+Calhoun, et al. Standards Track [Page 84]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ DIAMETER_LIMITED_SUCCESS 2002
+ When returned, the request was successfully completed, but
+ additional processing is required by the application in order to
+ provide service to the user.
+
+7.1.3. Protocol Errors
+
+ Errors that fall within the Protocol Error category SHOULD be treated
+ on a per-hop basis, and Diameter proxies MAY attempt to correct the
+ error, if it is possible. Note that these and only these errors MUST
+ only be used in answer messages whose 'E' bit is set.
+
+ DIAMETER_COMMAND_UNSUPPORTED 3001
+ The Request contained a Command-Code that the receiver did not
+ recognize or support. This MUST be used when a Diameter node
+ receives an experimental command that it does not understand.
+
+ DIAMETER_UNABLE_TO_DELIVER 3002
+ This error is given when Diameter can not deliver the message to
+ the destination, either because no host within the realm
+ supporting the required application was available to process the
+ request, or because Destination-Host AVP was given without the
+ associated Destination-Realm AVP.
+
+ DIAMETER_REALM_NOT_SERVED 3003
+ The intended realm of the request is not recognized.
+
+ DIAMETER_TOO_BUSY 3004
+ When returned, a Diameter node SHOULD attempt to send the message
+ to an alternate peer. This error MUST only be used when a
+ specific server is requested, and it cannot provide the requested
+ service.
+
+ DIAMETER_LOOP_DETECTED 3005
+ An agent detected a loop while trying to get the message to the
+ intended recipient. The message MAY be sent to an alternate peer,
+ if one is available, but the peer reporting the error has
+ identified a configuration problem.
+
+ DIAMETER_REDIRECT_INDICATION 3006
+ A redirect agent has determined that the request could not be
+ satisfied locally and the initiator of the request should direct
+ the request directly to the server, whose contact information has
+ been added to the response. When set, the Redirect-Host AVP MUST
+ be present.
+
+ DIAMETER_APPLICATION_UNSUPPORTED 3007
+ A request was sent for an application that is not supported.
+
+
+
+Calhoun, et al. Standards Track [Page 85]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ DIAMETER_INVALID_HDR_BITS 3008
+ A request was received whose bits in the Diameter header were
+ either set to an invalid combination, or to a value that is
+ inconsistent with the command code's definition.
+
+ DIAMETER_INVALID_AVP_BITS 3009
+ A request was received that included an AVP whose flag bits are
+ set to an unrecognized value, or that is inconsistent with the
+ AVP's definition.
+
+ DIAMETER_UNKNOWN_PEER 3010
+ A CER was received from an unknown peer.
+
+7.1.4. Transient Failures
+
+ Errors that fall within the transient failures category are used
+ to inform a peer that the request could not be satisfied at the
+ time it was received, but MAY be able to satisfy the request in
+ the future.
+
+ DIAMETER_AUTHENTICATION_REJECTED 4001
+ The authentication process for the user failed, most likely due to
+ an invalid password used by the user. Further attempts MUST only
+ be tried after prompting the user for a new password.
+
+ DIAMETER_OUT_OF_SPACE 4002
+ A Diameter node received the accounting request but was unable to
+ commit it to stable storage due to a temporary lack of space.
+
+ ELECTION_LOST 4003
+ The peer has determined that it has lost the election process and
+ has therefore disconnected the transport connection.
+
+7.1.5. Permanent Failures
+
+ Errors that fall within the permanent failures category are used
+ to inform the peer that the request failed, and should not be
+ attempted again.
+
+ DIAMETER_AVP_UNSUPPORTED 5001
+ The peer received a message that contained an AVP that is not
+ recognized or supported and was marked with the Mandatory bit. A
+ Diameter message with this error MUST contain one or more Failed-
+ AVP AVP containing the AVPs that caused the failure.
+
+ DIAMETER_UNKNOWN_SESSION_ID 5002
+ The request contained an unknown Session-Id.
+
+
+
+
+Calhoun, et al. Standards Track [Page 86]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ DIAMETER_AUTHORIZATION_REJECTED 5003
+ A request was received for which the user could not be authorized.
+ This error could occur if the service requested is not permitted
+ to the user.
+
+ DIAMETER_INVALID_AVP_VALUE 5004
+ The request contained an AVP with an invalid value in its data
+ portion. A Diameter message indicating this error MUST include
+ the offending AVPs within a Failed-AVP AVP.
+
+ DIAMETER_MISSING_AVP 5005
+ The request did not contain an AVP that is required by the Command
+ Code definition. If this value is sent in the Result-Code AVP, a
+ Failed-AVP AVP SHOULD be included in the message. The Failed-AVP
+ AVP MUST contain an example of the missing AVP complete with the
+ Vendor-Id if applicable. The value field of the missing AVP
+ should be of correct minimum length and contain zeroes.
+
+ DIAMETER_RESOURCES_EXCEEDED 5006
+ A request was received that cannot be authorized because the user
+ has already expended allowed resources. An example of this error
+ condition is a user that is restricted to one dial-up PPP port,
+ attempts to establish a second PPP connection.
+
+ DIAMETER_CONTRADICTING_AVPS 5007
+ The Home Diameter server has detected AVPs in the request that
+ contradicted each other, and is not willing to provide service to
+ the user. One or more Failed-AVP AVPs MUST be present, containing
+ the AVPs that contradicted each other.
+
+ DIAMETER_AVP_NOT_ALLOWED 5008
+ A message was received with an AVP that MUST NOT be present. The
+ Failed-AVP AVP MUST be included and contain a copy of the
+ offending AVP.
+
+ DIAMETER_AVP_OCCURS_TOO_MANY_TIMES 5009
+ A message was received that included an AVP that appeared more
+ often than permitted in the message definition. The Failed-AVP
+ AVP MUST be included and contain a copy of the first instance of
+ the offending AVP that exceeded the maximum number of occurrences
+
+ DIAMETER_NO_COMMON_APPLICATION 5010
+ This error is returned when a CER message is received, and there
+ are no common applications supported between the peers.
+
+ DIAMETER_UNSUPPORTED_VERSION 5011
+ This error is returned when a request was received, whose version
+ number is unsupported.
+
+
+
+Calhoun, et al. Standards Track [Page 87]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ DIAMETER_UNABLE_TO_COMPLY 5012
+ This error is returned when a request is rejected for unspecified
+ reasons.
+
+ DIAMETER_INVALID_BIT_IN_HEADER 5013
+ This error is returned when an unrecognized bit in the Diameter
+ header is set to one (1).
+
+ DIAMETER_INVALID_AVP_LENGTH 5014
+ The request contained an AVP with an invalid length. A Diameter
+ message indicating this error MUST include the offending AVPs
+ within a Failed-AVP AVP.
+
+ DIAMETER_INVALID_MESSAGE_LENGTH 5015
+ This error is returned when a request is received with an invalid
+ message length.
+
+ DIAMETER_INVALID_AVP_BIT_COMBO 5016
+ The request contained an AVP with which is not allowed to have the
+ given value in the AVP Flags field. A Diameter message indicating
+ this error MUST include the offending AVPs within a Failed-AVP
+ AVP.
+
+ DIAMETER_NO_COMMON_SECURITY 5017
+ This error is returned when a CER message is received, and there
+ are no common security mechanisms supported between the peers. A
+ Capabilities-Exchange-Answer (CEA) MUST be returned with the
+ Result-Code AVP set to DIAMETER_NO_COMMON_SECURITY.
+
+7.2. Error Bit
+
+ The 'E' (Error Bit) in the Diameter header is set when the request
+ caused a protocol-related error (see Section 7.1.3). A message with
+ the 'E' bit MUST NOT be sent as a response to an answer message.
+ Note that a message with the 'E' bit set is still subjected to the
+ processing rules defined in Section 6.2. When set, the answer
+ message will not conform to the ABNF specification for the command,
+ and will instead conform to the following ABNF:
+
+
+
+
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 88]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Message Format
+
+ <answer-message> ::= < Diameter Header: code, ERR [PXY] >
+ 0*1< Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Result-Code }
+ [ Origin-State-Id ]
+ [ Error-Reporting-Host ]
+ [ Proxy-Info ]
+ * [ AVP ]
+
+ Note that the code used in the header is the same than the one found
+ in the request message, but with the 'R' bit cleared and the 'E' bit
+ set. The 'P' bit in the header is set to the same value as the one
+ found in the request message.
+
+7.3. Error-Message AVP
+
+ The Error-Message AVP (AVP Code 281) is of type UTF8String. It MAY
+ accompany a Result-Code AVP as a human readable error message. The
+ Error-Message AVP is not intended to be useful in real-time, and
+ SHOULD NOT be expected to be parsed by network entities.
+
+7.4. Error-Reporting-Host AVP
+
+ The Error-Reporting-Host AVP (AVP Code 294) is of type
+ DiameterIdentity. This AVP contains the identity of the Diameter
+ host that sent the Result-Code AVP to a value other than 2001
+ (Success), only if the host setting the Result-Code is different from
+ the one encoded in the Origin-Host AVP. This AVP is intended to be
+ used for troubleshooting purposes, and MUST be set when the Result-
+ Code AVP indicates a failure.
+
+7.5. Failed-AVP AVP
+
+ The Failed-AVP AVP (AVP Code 279) is of type Grouped and provides
+ debugging information in cases where a request is rejected or not
+ fully processed due to erroneous information in a specific AVP. The
+ value of the Result-Code AVP will provide information on the reason
+ for the Failed-AVP AVP.
+
+ The possible reasons for this AVP are the presence of an improperly
+ constructed AVP, an unsupported or unrecognized AVP, an invalid AVP
+ value, the omission of a required AVP, the presence of an explicitly
+ excluded AVP (see tables in Section 10), or the presence of two or
+ more occurrences of an AVP which is restricted to 0, 1, or 0-1
+ occurrences.
+
+
+
+Calhoun, et al. Standards Track [Page 89]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ A Diameter message MAY contain one Failed-AVP AVP, containing the
+ entire AVP that could not be processed successfully. If the failure
+ reason is omission of a required AVP, an AVP with the missing AVP
+ code, the missing vendor id, and a zero filled payload of the minimum
+ required length for the omitted AVP will be added.
+
+ AVP Format
+
+ <Failed-AVP> ::= < AVP Header: 279 >
+ 1* {AVP}
+
+7.6. Experimental-Result AVP
+
+ The Experimental-Result AVP (AVP Code 297) is of type Grouped, and
+ indicates whether a particular vendor-specific request was completed
+ successfully or whether an error occurred. Its Data field has the
+ following ABNF grammar:
+
+ AVP Format
+
+ Experimental-Result ::= < AVP Header: 297 >
+ { Vendor-Id }
+ { Experimental-Result-Code }
+
+ The Vendor-Id AVP (see Section 5.3.3) in this grouped AVP identifies
+ the vendor responsible for the assignment of the result code which
+ follows. All Diameter answer messages defined in vendor-specific
+ applications MUST include either one Result-Code AVP or one
+ Experimental-Result AVP.
+
+7.7. Experimental-Result-Code AVP
+
+ The Experimental-Result-Code AVP (AVP Code 298) is of type Unsigned32
+ and contains a vendor-assigned value representing the result of
+ processing the request.
+
+ It is recommended that vendor-specific result codes follow the same
+ conventions given for the Result-Code AVP regarding the different
+ types of result codes and the handling of errors (for non 2xxx
+ values).
+
+8. Diameter User Sessions
+
+ Diameter can provide two different types of services to applications.
+ The first involves authentication and authorization, and can
+ optionally make use of accounting. The second only makes use of
+ accounting.
+
+
+
+
+Calhoun, et al. Standards Track [Page 90]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ When a service makes use of the authentication and/or authorization
+ portion of an application, and a user requests access to the network,
+ the Diameter client issues an auth request to its local server. The
+ auth request is defined in a service specific Diameter application
+ (e.g., NASREQ). The request contains a Session-Id AVP, which is used
+ in subsequent messages (e.g., subsequent authorization, accounting,
+ etc) relating to the user's session. The Session-Id AVP is a means
+ for the client and servers to correlate a Diameter message with a
+ user session.
+
+ When a Diameter server authorizes a user to use network resources for
+ a finite amount of time, and it is willing to extend the
+ authorization via a future request, it MUST add the Authorization-
+ Lifetime AVP to the answer message. The Authorization-Lifetime AVP
+ defines the maximum number of seconds a user MAY make use of the
+ resources before another authorization request is expected by the
+ server. The Auth-Grace-Period AVP contains the number of seconds
+ following the expiration of the Authorization-Lifetime, after which
+ the server will release all state information related to the user's
+ session. Note that if payment for services is expected by the
+ serving realm from the user's home realm, the Authorization-Lifetime
+ AVP, combined with the Auth-Grace-Period AVP, implies the maximum
+ length of the session the home realm is willing to be fiscally
+ responsible for. Services provided past the expiration of the
+ Authorization-Lifetime and Auth-Grace-Period AVPs are the
+ responsibility of the access device. Of course, the actual cost of
+ services rendered is clearly outside the scope of the protocol.
+
+ An access device that does not expect to send a re-authorization or a
+ session termination request to the server MAY include the Auth-
+ Session-State AVP with the value set to NO_STATE_MAINTAINED as a hint
+ to the server. If the server accepts the hint, it agrees that since
+ no session termination message will be received once service to the
+ user is terminated, it cannot maintain state for the session. If the
+ answer message from the server contains a different value in the
+ Auth-Session-State AVP (or the default value if the AVP is absent),
+ the access device MUST follow the server's directives. Note that the
+ value NO_STATE_MAINTAINED MUST NOT be set in subsequent re-
+ authorization requests and answers.
+
+ The base protocol does not include any authorization request
+ messages, since these are largely application-specific and are
+ defined in a Diameter application document. However, the base
+ protocol does define a set of messages that is used to terminate user
+ sessions. These are used to allow servers that maintain state
+ information to free resources.
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 91]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ When a service only makes use of the Accounting portion of the
+ Diameter protocol, even in combination with an application, the
+ Session-Id is still used to identify user sessions. However, the
+ session termination messages are not used, since a session is
+ signaled as being terminated by issuing an accounting stop message.
+
+8.1. Authorization Session State Machine
+
+ This section contains a set of finite state machines, representing
+ the life cycle of Diameter sessions, and which MUST be observed by
+ all Diameter implementations that make use of the authentication
+ and/or authorization portion of a Diameter application. The term
+ Service-Specific below refers to a message defined in a Diameter
+ application (e.g., Mobile IPv4, NASREQ).
+
+ There are four different authorization session state machines
+ supported in the Diameter base protocol. The first two describe a
+ session in which the server is maintaining session state, indicated
+ by the value of the Auth-Session-State AVP (or its absence). One
+ describes the session from a client perspective, the other from a
+ server perspective. The second two state machines are used when the
+ server does not maintain session state. Here again, one describes
+ the session from a client perspective, the other from a server
+ perspective.
+
+ When a session is moved to the Idle state, any resources that were
+ allocated for the particular session must be released. Any event not
+ listed in the state machines MUST be considered as an error
+ condition, and an answer, if applicable, MUST be returned to the
+ originator of the message.
+
+ In the state table, the event 'Failure to send X' means that the
+ Diameter agent is unable to send command X to the desired
+ destination. This could be due to the peer being down, or due to the
+ peer sending back a transient failure or temporary protocol error
+ notification DIAMETER_TOO_BUSY or DIAMETER_LOOP_DETECTED in the
+ Result-Code AVP of the corresponding Answer command. The event 'X
+ successfully sent' is the complement of 'Failure to send X'.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 92]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ The following state machine is observed by a client when state is
+ maintained on the server:
+
+ CLIENT, STATEFUL
+ State Event Action New State
+ -------------------------------------------------------------
+ Idle Client or Device Requests Send Pending
+ access service
+ specific
+ auth req
+
+ Idle ASR Received Send ASA Idle
+ for unknown session with
+ Result-Code
+ = UNKNOWN_
+ SESSION_ID
+
+ Pending Successful Service-specific Grant Open
+ authorization answer Access
+ received with default
+ Auth-Session-State value
+
+ Pending Successful Service-specific Sent STR Discon
+ authorization answer received
+ but service not provided
+
+ Pending Error processing successful Sent STR Discon
+ Service-specific authorization
+ answer
+
+ Pending Failed Service-specific Cleanup Idle
+ authorization answer received
+
+ Open User or client device Send Open
+ requests access to service service
+ specific
+ auth req
+
+ Open Successful Service-specific Provide Open
+ authorization answer received Service
+
+ Open Failed Service-specific Discon. Idle
+ authorization answer user/device
+ received.
+
+ Open Session-Timeout Expires on Send STR Discon
+ Access Device
+
+
+
+
+Calhoun, et al. Standards Track [Page 93]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Open ASR Received, Send ASA Discon
+ client will comply with with
+ request to end the session Result-Code
+ = SUCCESS,
+ Send STR.
+
+ Open ASR Received, Send ASA Open
+ client will not comply with with
+ request to end the session Result-Code
+ != SUCCESS
+
+ Open Authorization-Lifetime + Send STR Discon
+ Auth-Grace-Period expires on
+ access device
+
+ Discon ASR Received Send ASA Discon
+
+ Discon STA Received Discon. Idle
+ user/device
+
+ The following state machine is observed by a server when it is
+ maintaining state for the session:
+
+ SERVER, STATEFUL
+ State Event Action New State
+ -------------------------------------------------------------
+ Idle Service-specific authorization Send Open
+ request received, and successful
+ user is authorized serv.
+ specific answer
+
+ Idle Service-specific authorization Send Idle
+ request received, and failed serv.
+ user is not authorized specific answer
+
+ Open Service-specific authorization Send Open
+ request received, and user successful
+ is authorized serv. specific
+ answer
+
+ Open Service-specific authorization Send Idle
+ request received, and user failed serv.
+ is not authorized specific
+ answer,
+ Cleanup
+
+ Open Home server wants to Send ASR Discon
+ terminate the service
+
+
+
+Calhoun, et al. Standards Track [Page 94]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Open Authorization-Lifetime (and Cleanup Idle
+ Auth-Grace-Period) expires
+ on home server.
+
+ Open Session-Timeout expires on Cleanup Idle
+ home server
+
+ Discon Failure to send ASR Wait, Discon
+ resend ASR
+
+ Discon ASR successfully sent and Cleanup Idle
+ ASA Received with Result-Code
+
+ Not ASA Received None No Change.
+ Discon
+
+ Any STR Received Send STA, Idle
+ Cleanup.
+
+ The following state machine is observed by a client when state is not
+ maintained on the server:
+
+ CLIENT, STATELESS
+ State Event Action New State
+ -------------------------------------------------------------
+ Idle Client or Device Requests Send Pending
+ access service
+ specific
+ auth req
+
+ Pending Successful Service-specific Grant Open
+ authorization answer Access
+ received with Auth-Session-
+ State set to
+ NO_STATE_MAINTAINED
+
+ Pending Failed Service-specific Cleanup Idle
+ authorization answer
+ received
+
+ Open Session-Timeout Expires on Discon. Idle
+ Access Device user/device
+
+ Open Service to user is terminated Discon. Idle
+ user/device
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 95]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ The following state machine is observed by a server when it is not
+ maintaining state for the session:
+
+ SERVER, STATELESS
+ State Event Action New State
+ -------------------------------------------------------------
+ Idle Service-specific authorization Send serv. Idle
+ request received, and specific
+ successfully processed answer
+
+8.2. Accounting Session State Machine
+
+ The following state machines MUST be supported for applications that
+ have an accounting portion or that require only accounting services.
+ The first state machine is to be observed by clients.
+
+ See Section 9.7 for Accounting Command Codes and Section 9.8 for
+ Accounting AVPs.
+
+ The server side in the accounting state machine depends in some cases
+ on the particular application. The Diameter base protocol defines a
+ default state machine that MUST be followed by all applications that
+ have not specified other state machines. This is the second state
+ machine in this section described below.
+
+ The default server side state machine requires the reception of
+ accounting records in any order and at any time, and does not place
+ any standards requirement on the processing of these records.
+ Implementations of Diameter MAY perform checking, ordering,
+ correlation, fraud detection, and other tasks based on these records.
+ Both base Diameter AVPs as well as application specific AVPs MAY be
+ inspected as a part of these tasks. The tasks can happen either
+ immediately after record reception or in a post-processing phase.
+ However, as these tasks are typically application or even policy
+ dependent, they are not standardized by the Diameter specifications.
+ Applications MAY define requirements on when to accept accounting
+ records based on the used value of Accounting-Realtime-Required AVP,
+ credit limits checks, and so on.
+
+ However, the Diameter base protocol defines one optional server side
+ state machine that MAY be followed by applications that require
+ keeping track of the session state at the accounting server. Note
+ that such tracking is incompatible with the ability to sustain long
+ duration connectivity problems. Therefore, the use of this state
+ machine is recommended only in applications where the value of the
+ Accounting-Realtime-Required AVP is DELIVER_AND_GRANT, and hence
+ accounting connectivity problems are required to cause the serviced
+ user to be disconnected. Otherwise, records produced by the client
+
+
+
+Calhoun, et al. Standards Track [Page 96]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ may be lost by the server which no longer accepts them after the
+ connectivity is re-established. This state machine is the third
+ state machine in this section. The state machine is supervised by a
+ supervision session timer Ts, which the value should be reasonably
+ higher than the Acct_Interim_Interval value. Ts MAY be set to two
+ times the value of the Acct_Interim_Interval so as to avoid the
+ accounting session in the Diameter server to change to Idle state in
+ case of short transient network failure.
+
+ Any event not listed in the state machines MUST be considered as an
+ error condition, and a corresponding answer, if applicable, MUST be
+ returned to the originator of the message.
+
+ In the state table, the event 'Failure to send' means that the
+ Diameter client is unable to communicate with the desired
+ destination. This could be due to the peer being down, or due to the
+ peer sending back a transient failure or temporary protocol error
+ notification DIAMETER_OUT_OF_SPACE, DIAMETER_TOO_BUSY, or
+ DIAMETER_LOOP_DETECTED in the Result-Code AVP of the Accounting
+ Answer command.
+
+ The event 'Failed answer' means that the Diameter client received a
+ non-transient failure notification in the Accounting Answer command.
+
+ Note that the action 'Disconnect user/dev' MUST have an effect also
+ to the authorization session state table, e.g., cause the STR message
+ to be sent, if the given application has both
+ authentication/authorization and accounting portions.
+
+ The states PendingS, PendingI, PendingL, PendingE and PendingB stand
+ for pending states to wait for an answer to an accounting request
+ related to a Start, Interim, Stop, Event or buffered record,
+ respectively.
+
+ CLIENT, ACCOUNTING
+ State Event Action New State
+ -------------------------------------------------------------
+ Idle Client or device requests Send PendingS
+ access accounting
+ start req.
+
+ Idle Client or device requests Send PendingE
+ a one-time service accounting
+ event req
+
+ Idle Records in storage Send PendingB
+ record
+
+
+
+
+Calhoun, et al. Standards Track [Page 97]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ PendingS Successful accounting Open
+ start answer received
+
+ PendingS Failure to send and buffer Store Open
+ space available and realtime Start
+ not equal to DELIVER_AND_GRANT Record
+
+ PendingS Failure to send and no buffer Open
+ space available and realtime
+ equal to GRANT_AND_LOSE
+
+ PendingS Failure to send and no buffer Disconnect Idle
+ space available and realtime user/dev
+ not equal to
+ GRANT_AND_LOSE
+
+ PendingS Failed accounting start answer Open
+ received and realtime equal
+ to GRANT_AND_LOSE
+
+ PendingS Failed accounting start answer Disconnect Idle
+ received and realtime not user/dev
+ equal to GRANT_AND_LOSE
+
+ PendingS User service terminated Store PendingS
+ stop
+ record
+
+ Open Interim interval elapses Send PendingI
+ accounting
+ interim
+ record
+ Open User service terminated Send PendingL
+ accounting
+ stop req.
+
+ PendingI Successful accounting interim Open
+ answer received
+
+ PendingI Failure to send and (buffer Store Open
+ space available or old record interim
+ can be overwritten) and record
+ realtime not equal to
+ DELIVER_AND_GRANT
+
+ PendingI Failure to send and no buffer Open
+ space available and realtime
+ equal to GRANT_AND_LOSE
+
+
+
+Calhoun, et al. Standards Track [Page 98]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ PendingI Failure to send and no buffer Disconnect Idle
+ space available and realtime user/dev
+ not equal to GRANT_AND_LOSE
+
+ PendingI Failed accounting interim Open
+ answer received and realtime
+ equal to GRANT_AND_LOSE
+
+ PendingI Failed accounting interim Disconnect Idle
+ answer received and realtime user/dev
+ not equal to GRANT_AND_LOSE
+
+ PendingI User service terminated Store PendingI
+ stop
+ record
+ PendingE Successful accounting Idle
+ event answer received
+
+ PendingE Failure to send and buffer Store Idle
+ space available event
+ record
+
+ PendingE Failure to send and no buffer Idle
+ space available
+
+ PendingE Failed accounting event answer Idle
+ received
+
+ PendingB Successful accounting answer Delete Idle
+ received record
+
+ PendingB Failure to send Idle
+
+ PendingB Failed accounting answer Delete Idle
+ received record
+
+ PendingL Successful accounting Idle
+ stop answer received
+
+ PendingL Failure to send and buffer Store Idle
+ space available stop
+ record
+
+ PendingL Failure to send and no buffer Idle
+ space available
+
+ PendingL Failed accounting stop answer Idle
+ received
+
+
+
+Calhoun, et al. Standards Track [Page 99]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ SERVER, STATELESS ACCOUNTING
+ State Event Action New State
+ -------------------------------------------------------------
+
+ Idle Accounting start request Send Idle
+ received, and successfully accounting
+ processed. start
+ answer
+
+ Idle Accounting event request Send Idle
+ received, and successfully accounting
+ processed. event
+ answer
+
+ Idle Interim record received, Send Idle
+ and successfully processed. accounting
+ interim
+ answer
+
+ Idle Accounting stop request Send Idle
+ received, and successfully accounting
+ processed stop answer
+
+ Idle Accounting request received, Send Idle
+ no space left to store accounting
+ records answer,
+ Result-Code
+ = OUT_OF_
+ SPACE
+
+ SERVER, STATEFUL ACCOUNTING
+ State Event Action New State
+ -------------------------------------------------------------
+
+ Idle Accounting start request Send Open
+ received, and successfully accounting
+ processed. start
+ answer,
+ Start Ts
+
+ Idle Accounting event request Send Idle
+ received, and successfully accounting
+ processed. event
+ answer
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 100]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Idle Accounting request received, Send Idle
+ no space left to store accounting
+ records answer,
+ Result-Code
+ = OUT_OF_
+ SPACE
+
+ Open Interim record received, Send Open
+ and successfully processed. accounting
+ interim
+ answer,
+ Restart Ts
+
+ Open Accounting stop request Send Idle
+ received, and successfully accounting
+ processed stop answer,
+ Stop Ts
+
+ Open Accounting request received, Send Idle
+ no space left to store accounting
+ records answer,
+ Result-Code
+ = OUT_OF_
+ SPACE,
+ Stop Ts
+
+ Open Session supervision timer Ts Stop Ts Idle
+ expired
+
+8.3. Server-Initiated Re-Auth
+
+ A Diameter server may initiate a re-authentication and/or re-
+ authorization service for a particular session by issuing a Re-Auth-
+ Request (RAR).
+
+ For example, for pre-paid services, the Diameter server that
+ originally authorized a session may need some confirmation that the
+ user is still using the services.
+
+ An access device that receives a RAR message with Session-Id equal to
+ a currently active session MUST initiate a re-auth towards the user,
+ if the service supports this particular feature. Each Diameter
+ application MUST state whether service-initiated re-auth is
+ supported, since some applications do not allow access devices to
+ prompt the user for re-auth.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 101]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+8.3.1. Re-Auth-Request
+
+ The Re-Auth-Request (RAR), indicated by the Command-Code set to 258
+ and the message flags' 'R' bit set, may be sent by any server to the
+ access device that is providing session service, to request that the
+ user be re-authenticated and/or re-authorized.
+
+ Message Format
+
+ <RAR> ::= < Diameter Header: 258, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Destination-Host }
+ { Auth-Application-Id }
+ { Re-Auth-Request-Type }
+ [ User-Name ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+8.3.2. Re-Auth-Answer
+
+ The Re-Auth-Answer (RAA), indicated by the Command-Code set to 258
+ and the message flags' 'R' bit clear, is sent in response to the RAR.
+ The Result-Code AVP MUST be present, and indicates the disposition of
+ the request.
+
+ A successful RAA message MUST be followed by an application-specific
+ authentication and/or authorization message.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 102]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Message Format
+
+ <RAA> ::= < Diameter Header: 258, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ [ Origin-State-Id ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Host-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+8.4. Session Termination
+
+ It is necessary for a Diameter server that authorized a session, for
+ which it is maintaining state, to be notified when that session is no
+ longer active, both for tracking purposes as well as to allow
+ stateful agents to release any resources that they may have provided
+ for the user's session. For sessions whose state is not being
+ maintained, this section is not used.
+
+ When a user session that required Diameter authorization terminates,
+ the access device that provided the service MUST issue a Session-
+ Termination-Request (STR) message to the Diameter server that
+ authorized the service, to notify it that the session is no longer
+ active. An STR MUST be issued when a user session terminates for any
+ reason, including user logoff, expiration of Session-Timeout,
+ administrative action, termination upon receipt of an Abort-Session-
+ Request (see below), orderly shutdown of the access device, etc.
+
+ The access device also MUST issue an STR for a session that was
+ authorized but never actually started. This could occur, for
+ example, due to a sudden resource shortage in the access device, or
+ because the access device is unwilling to provide the type of service
+ requested in the authorization, or because the access device does not
+ support a mandatory AVP returned in the authorization, etc.
+
+ It is also possible that a session that was authorized is never
+ actually started due to action of a proxy. For example, a proxy may
+ modify an authorization answer, converting the result from success to
+ failure, prior to forwarding the message to the access device. If
+ the answer did not contain an Auth-Session-State AVP with the value
+
+
+
+Calhoun, et al. Standards Track [Page 103]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ NO_STATE_MAINTAINED, a proxy that causes an authorized session not to
+ be started MUST issue an STR to the Diameter server that authorized
+ the session, since the access device has no way of knowing that the
+ session had been authorized.
+
+ A Diameter server that receives an STR message MUST clean up
+ resources (e.g., session state) associated with the Session-Id
+ specified in the STR, and return a Session-Termination-Answer.
+
+ A Diameter server also MUST clean up resources when the Session-
+ Timeout expires, or when the Authorization-Lifetime and the Auth-
+ Grace-Period AVPs expires without receipt of a re-authorization
+ request, regardless of whether an STR for that session is received.
+ The access device is not expected to provide service beyond the
+ expiration of these timers; thus, expiration of either of these
+ timers implies that the access device may have unexpectedly shut
+ down.
+
+8.4.1. Session-Termination-Request
+
+ The Session-Termination-Request (STR), indicated by the Command-Code
+ set to 275 and the Command Flags' 'R' bit set, is sent by the access
+ device to inform the Diameter Server that an authenticated and/or
+ authorized session is being terminated.
+
+ Message Format
+
+ <STR> ::= < Diameter Header: 275, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Auth-Application-Id }
+ { Termination-Cause }
+ [ User-Name ]
+ [ Destination-Host ]
+ * [ Class ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 104]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+8.4.2. Session-Termination-Answer
+
+ The Session-Termination-Answer (STA), indicated by the Command-Code
+ set to 275 and the message flags' 'R' bit clear, is sent by the
+ Diameter Server to acknowledge the notification that the session has
+ been terminated. The Result-Code AVP MUST be present, and MAY
+ contain an indication that an error occurred while servicing the STR.
+
+ Upon sending or receipt of the STA, the Diameter Server MUST release
+ all resources for the session indicated by the Session-Id AVP. Any
+ intermediate server in the Proxy-Chain MAY also release any
+ resources, if necessary.
+
+ Message Format
+
+ <STA> ::= < Diameter Header: 275, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ * [ Class ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ [ Origin-State-Id ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ ^
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+8.5. Aborting a Session
+
+ A Diameter server may request that the access device stop providing
+ service for a particular session by issuing an Abort-Session-Request
+ (ASR).
+
+ For example, the Diameter server that originally authorized the
+ session may be required to cause that session to be stopped for
+ credit or other reasons that were not anticipated when the session
+ was first authorized. On the other hand, an operator may maintain a
+ management server for the purpose of issuing ASRs to administratively
+ remove users from the network.
+
+ An access device that receives an ASR with Session-ID equal to a
+ currently active session MAY stop the session. Whether the access
+
+
+
+Calhoun, et al. Standards Track [Page 105]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ device stops the session or not is implementation- and/or
+ configuration-dependent. For example, an access device may honor
+ ASRs from certain agents only. In any case, the access device MUST
+ respond with an Abort-Session-Answer, including a Result-Code AVP to
+ indicate what action it took.
+
+ Note that if the access device does stop the session upon receipt of
+ an ASR, it issues an STR to the authorizing server (which may or may
+ not be the agent issuing the ASR) just as it would if the session
+ were terminated for any other reason.
+
+8.5.1. Abort-Session-Request
+
+ The Abort-Session-Request (ASR), indicated by the Command-Code set to
+ 274 and the message flags' 'R' bit set, may be sent by any server to
+ the access device that is providing session service, to request that
+ the session identified by the Session-Id be stopped.
+
+ Message Format
+
+ <ASR> ::= < Diameter Header: 274, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Destination-Host }
+ { Auth-Application-Id }
+ [ User-Name ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+8.5.2. Abort-Session-Answer
+
+ The Abort-Session-Answer (ASA), indicated by the Command-Code set to
+ 274 and the message flags' 'R' bit clear, is sent in response to the
+ ASR. The Result-Code AVP MUST be present, and indicates the
+ disposition of the request.
+
+ If the session identified by Session-Id in the ASR was successfully
+ terminated, Result-Code is set to DIAMETER_SUCCESS. If the session
+ is not currently active, Result-Code is set to
+ DIAMETER_UNKNOWN_SESSION_ID. If the access device does not stop the
+ session for any other reason, Result-Code is set to
+ DIAMETER_UNABLE_TO_COMPLY.
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 106]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Message Format
+
+ <ASA> ::= < Diameter Header: 274, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ [ Origin-State-Id ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+8.6. Inferring Session Termination from Origin-State-Id
+
+ Origin-State-Id is used to allow rapid detection of terminated
+ sessions for which no STR would have been issued, due to
+ unanticipated shutdown of an access device.
+
+ By including Origin-State-Id in CER/CEA messages, an access device
+ allows a next-hop server to determine immediately upon connection
+ whether the device has lost its sessions since the last connection.
+
+ By including Origin-State-Id in request messages, an access device
+ also allows a server with which it communicates via proxy to make
+ such a determination. However, a server that is not directly
+ connected with the access device will not discover that the access
+ device has been restarted unless and until it receives a new request
+ from the access device. Thus, use of this mechanism across proxies
+ is opportunistic rather than reliable, but useful nonetheless.
+
+ When a Diameter server receives an Origin-State-Id that is greater
+ than the Origin-State-Id previously received from the same issuer, it
+ may assume that the issuer has lost state since the previous message
+ and that all sessions that were active under the lower Origin-State-
+ Id have been terminated. The Diameter server MAY clean up all
+ session state associated with such lost sessions, and MAY also issues
+ STRs for all such lost sessions that were authorized on upstream
+ servers, to allow session state to be cleaned up globally.
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 107]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+8.7. Auth-Request-Type AVP
+
+ The Auth-Request-Type AVP (AVP Code 274) is of type Enumerated and is
+ included in application-specific auth requests to inform the peers
+ whether a user is to be authenticated only, authorized only or both.
+ Note any value other than both MAY cause RADIUS interoperability
+ issues. The following values are defined:
+
+ AUTHENTICATE_ONLY 1
+ The request being sent is for authentication only, and MUST
+ contain the relevant application specific authentication AVPs that
+ are needed by the Diameter server to authenticate the user.
+
+ AUTHORIZE_ONLY 2
+ The request being sent is for authorization only, and MUST contain
+ the application specific authorization AVPs that are necessary to
+ identify the service being requested/offered.
+
+ AUTHORIZE_AUTHENTICATE 3
+ The request contains a request for both authentication and
+ authorization. The request MUST include both the relevant
+ application specific authentication information, and authorization
+ information necessary to identify the service being
+ requested/offered.
+
+8.8. Session-Id AVP
+
+ The Session-Id AVP (AVP Code 263) is of type UTF8String and is used
+ to identify a specific session (see Section 8). All messages
+ pertaining to a specific session MUST include only one Session-Id AVP
+ and the same value MUST be used throughout the life of a session.
+ When present, the Session-Id SHOULD appear immediately following the
+ Diameter Header (see Section 3).
+
+ The Session-Id MUST be globally and eternally unique, as it is meant
+ to uniquely identify a user session without reference to any other
+ information, and may be needed to correlate historical authentication
+ information with accounting information. The Session-Id includes a
+ mandatory portion and an implementation-defined portion; a
+ recommended format for the implementation-defined portion is outlined
+ below.
+
+ The Session-Id MUST begin with the sender's identity encoded in the
+ DiameterIdentity type (see Section 4.4). The remainder of the
+ Session-Id is delimited by a ";" character, and MAY be any sequence
+ that the client can guarantee to be eternally unique; however, the
+ following format is recommended, (square brackets [] indicate an
+ optional element):
+
+
+
+Calhoun, et al. Standards Track [Page 108]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ <DiameterIdentity>;<high 32 bits>;<low 32 bits>[;<optional value>]
+
+ <high 32 bits> and <low 32 bits> are decimal representations of the
+ high and low 32 bits of a monotonically increasing 64-bit value. The
+ 64-bit value is rendered in two part to simplify formatting by 32-bit
+ processors. At startup, the high 32 bits of the 64-bit value MAY be
+ initialized to the time, and the low 32 bits MAY be initialized to
+ zero. This will for practical purposes eliminate the possibility of
+ overlapping Session-Ids after a reboot, assuming the reboot process
+ takes longer than a second. Alternatively, an implementation MAY
+ keep track of the increasing value in non-volatile memory.
+
+ <optional value> is implementation specific but may include a modem's
+ device Id, a layer 2 address, timestamp, etc.
+
+ Example, in which there is no optional value:
+ accesspoint7.acme.com;1876543210;523
+
+ Example, in which there is an optional value:
+ accesspoint7.acme.com;1876543210;523;[email protected]
+
+ The Session-Id is created by the Diameter application initiating the
+ session, which in most cases is done by the client. Note that a
+ Session-Id MAY be used for both the authorization and accounting
+ commands of a given application.
+
+8.9. Authorization-Lifetime AVP
+
+ The Authorization-Lifetime AVP (AVP Code 291) is of type Unsigned32
+ and contains the maximum number of seconds of service to be provided
+ to the user before the user is to be re-authenticated and/or re-
+ authorized. Great care should be taken when the Authorization-
+ Lifetime value is determined, since a low, non-zero, value could
+ create significant Diameter traffic, which could congest both the
+ network and the agents.
+
+ A value of zero (0) means that immediate re-auth is necessary by the
+ access device. This is typically used in cases where multiple
+ authentication methods are used, and a successful auth response with
+ this AVP set to zero is used to signal that the next authentication
+ method is to be immediately initiated. The absence of this AVP, or a
+ value of all ones (meaning all bits in the 32 bit field are set to
+ one) means no re-auth is expected.
+
+ If both this AVP and the Session-Timeout AVP are present in a
+ message, the value of the latter MUST NOT be smaller than the
+ Authorization-Lifetime AVP.
+
+
+
+
+Calhoun, et al. Standards Track [Page 109]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ An Authorization-Lifetime AVP MAY be present in re-authorization
+ messages, and contains the number of seconds the user is authorized
+ to receive service from the time the re-auth answer message is
+ received by the access device.
+
+ This AVP MAY be provided by the client as a hint of the maximum
+ lifetime that it is willing to accept. However, the server MAY
+ return a value that is equal to, or smaller, than the one provided by
+ the client.
+
+8.10. Auth-Grace-Period AVP
+
+ The Auth-Grace-Period AVP (AVP Code 276) is of type Unsigned32 and
+ contains the number of seconds the Diameter server will wait
+ following the expiration of the Authorization-Lifetime AVP before
+ cleaning up resources for the session.
+
+8.11. Auth-Session-State AVP
+
+ The Auth-Session-State AVP (AVP Code 277) is of type Enumerated and
+ specifies whether state is maintained for a particular session. The
+ client MAY include this AVP in requests as a hint to the server, but
+ the value in the server's answer message is binding. The following
+ values are supported:
+
+ STATE_MAINTAINED 0
+ This value is used to specify that session state is being
+ maintained, and the access device MUST issue a session termination
+ message when service to the user is terminated. This is the
+ default value.
+
+ NO_STATE_MAINTAINED 1
+ This value is used to specify that no session termination messages
+ will be sent by the access device upon expiration of the
+ Authorization-Lifetime.
+
+8.12. Re-Auth-Request-Type AVP
+
+ The Re-Auth-Request-Type AVP (AVP Code 285) is of type Enumerated and
+ is included in application-specific auth answers to inform the client
+ of the action expected upon expiration of the Authorization-Lifetime.
+ If the answer message contains an Authorization-Lifetime AVP with a
+ positive value, the Re-Auth-Request-Type AVP MUST be present in an
+ answer message. The following values are defined:
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 110]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ AUTHORIZE_ONLY 0
+ An authorization only re-auth is expected upon expiration of the
+ Authorization-Lifetime. This is the default value if the AVP is
+ not present in answer messages that include the Authorization-
+ Lifetime.
+
+ AUTHORIZE_AUTHENTICATE 1
+ An authentication and authorization re-auth is expected upon
+ expiration of the Authorization-Lifetime.
+
+8.13. Session-Timeout AVP
+
+ The Session-Timeout AVP (AVP Code 27) [RADIUS] is of type Unsigned32
+ and contains the maximum number of seconds of service to be provided
+ to the user before termination of the session. When both the
+ Session-Timeout and the Authorization-Lifetime AVPs are present in an
+ answer message, the former MUST be equal to or greater than the value
+ of the latter.
+
+ A session that terminates on an access device due to the expiration
+ of the Session-Timeout MUST cause an STR to be issued, unless both
+ the access device and the home server had previously agreed that no
+ session termination messages would be sent (see Section 8.9).
+
+ A Session-Timeout AVP MAY be present in a re-authorization answer
+ message, and contains the remaining number of seconds from the
+ beginning of the re-auth.
+
+ A value of zero, or the absence of this AVP, means that this session
+ has an unlimited number of seconds before termination.
+
+ This AVP MAY be provided by the client as a hint of the maximum
+ timeout that it is willing to accept. However, the server MAY return
+ a value that is equal to, or smaller, than the one provided by the
+ client.
+
+8.14. User-Name AVP
+
+ The User-Name AVP (AVP Code 1) [RADIUS] is of type UTF8String, which
+ contains the User-Name, in a format consistent with the NAI
+ specification [NAI].
+
+8.15. Termination-Cause AVP
+
+ The Termination-Cause AVP (AVP Code 295) is of type Enumerated, and
+ is used to indicate the reason why a session was terminated on the
+ access device. The following values are defined:
+
+
+
+
+Calhoun, et al. Standards Track [Page 111]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ DIAMETER_LOGOUT 1
+ The user initiated a disconnect
+
+ DIAMETER_SERVICE_NOT_PROVIDED 2
+ This value is used when the user disconnected prior to the receipt
+ of the authorization answer message.
+
+ DIAMETER_BAD_ANSWER 3
+ This value indicates that the authorization answer received by the
+ access device was not processed successfully.
+
+ DIAMETER_ADMINISTRATIVE 4
+ The user was not granted access, or was disconnected, due to
+ administrative reasons, such as the receipt of a Abort-Session-
+ Request message.
+
+ DIAMETER_LINK_BROKEN 5
+ The communication to the user was abruptly disconnected.
+
+ DIAMETER_AUTH_EXPIRED 6
+ The user's access was terminated since its authorized session time
+ has expired.
+
+ DIAMETER_USER_MOVED 7
+ The user is receiving services from another access device.
+
+ DIAMETER_SESSION_TIMEOUT 8
+ The user's session has timed out, and service has been terminated.
+
+8.16. Origin-State-Id AVP
+
+ The Origin-State-Id AVP (AVP Code 278), of type Unsigned32, is a
+ monotonically increasing value that is advanced whenever a Diameter
+ entity restarts with loss of previous state, for example upon reboot.
+ Origin-State-Id MAY be included in any Diameter message, including
+ CER.
+
+ A Diameter entity issuing this AVP MUST create a higher value for
+ this AVP each time its state is reset. A Diameter entity MAY set
+ Origin-State-Id to the time of startup, or it MAY use an incrementing
+ counter retained in non-volatile memory across restarts.
+
+ The Origin-State-Id, if present, MUST reflect the state of the entity
+ indicated by Origin-Host. If a proxy modifies Origin-Host, it MUST
+ either remove Origin-State-Id or modify it appropriately as well.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 112]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Typically, Origin-State-Id is used by an access device that always
+ starts up with no active sessions; that is, any session active prior
+ to restart will have been lost. By including Origin-State-Id in a
+ message, it allows other Diameter entities to infer that sessions
+ associated with a lower Origin-State-Id are no longer active. If an
+ access device does not intend for such inferences to be made, it MUST
+ either not include Origin-State-Id in any message, or set its value
+ to 0.
+
+8.17. Session-Binding AVP
+
+ The Session-Binding AVP (AVP Code 270) is of type Unsigned32, and MAY
+ be present in application-specific authorization answer messages. If
+ present, this AVP MAY inform the Diameter client that all future
+ application-specific re-auth messages for this session MUST be sent
+ to the same authorization server. This AVP MAY also specify that a
+ Session-Termination-Request message for this session MUST be sent to
+ the same authorizing server.
+
+ This field is a bit mask, and the following bits have been defined:
+
+ RE_AUTH 1
+ When set, future re-auth messages for this session MUST NOT
+ include the Destination-Host AVP. When cleared, the default
+ value, the Destination-Host AVP MUST be present in all re-auth
+ messages for this session.
+
+ STR 2
+ When set, the STR message for this session MUST NOT include the
+ Destination-Host AVP. When cleared, the default value, the
+ Destination-Host AVP MUST be present in the STR message for this
+ session.
+
+ ACCOUNTING 4
+ When set, all accounting messages for this session MUST NOT
+ include the Destination-Host AVP. When cleared, the default
+ value, the Destination-Host AVP, if known, MUST be present in all
+ accounting messages for this session.
+
+8.18. Session-Server-Failover AVP
+
+ The Session-Server-Failover AVP (AVP Code 271) is of type Enumerated,
+ and MAY be present in application-specific authorization answer
+ messages that either do not include the Session-Binding AVP or
+ include the Session-Binding AVP with any of the bits set to a zero
+ value. If present, this AVP MAY inform the Diameter client that if a
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 113]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ re-auth or STR message fails due to a delivery problem, the Diameter
+ client SHOULD issue a subsequent message without the Destination-Host
+ AVP. When absent, the default value is REFUSE_SERVICE.
+
+ The following values are supported:
+
+ REFUSE_SERVICE 0
+ If either the re-auth or the STR message delivery fails, terminate
+ service with the user, and do not attempt any subsequent attempts.
+
+ TRY_AGAIN 1
+ If either the re-auth or the STR message delivery fails, resend
+ the failed message without the Destination-Host AVP present.
+
+ ALLOW_SERVICE 2
+ If re-auth message delivery fails, assume that re-authorization
+ succeeded. If STR message delivery fails, terminate the session.
+
+ TRY_AGAIN_ALLOW_SERVICE 3
+ If either the re-auth or the STR message delivery fails, resend
+ the failed message without the Destination-Host AVP present. If
+ the second delivery fails for re-auth, assume re-authorization
+ succeeded. If the second delivery fails for STR, terminate the
+ session.
+
+8.19. Multi-Round-Time-Out AVP
+
+ The Multi-Round-Time-Out AVP (AVP Code 272) is of type Unsigned32,
+ and SHOULD be present in application-specific authorization answer
+ messages whose Result-Code AVP is set to DIAMETER_MULTI_ROUND_AUTH.
+ This AVP contains the maximum number of seconds that the access
+ device MUST provide the user in responding to an authentication
+ request.
+
+8.20. Class AVP
+
+ The Class AVP (AVP Code 25) is of type OctetString and is used to by
+ Diameter servers to return state information to the access device.
+ When one or more Class AVPs are present in application-specific
+ authorization answer messages, they MUST be present in subsequent
+ re-authorization, session termination and accounting messages. Class
+ AVPs found in a re-authorization answer message override the ones
+ found in any previous authorization answer message. Diameter server
+ implementations SHOULD NOT return Class AVPs that require more than
+ 4096 bytes of storage on the Diameter client. A Diameter client that
+ receives Class AVPs whose size exceeds local available storage MUST
+ terminate the session.
+
+
+
+
+Calhoun, et al. Standards Track [Page 114]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+8.21. Event-Timestamp AVP
+
+ The Event-Timestamp (AVP Code 55) is of type Time, and MAY be
+ included in an Accounting-Request and Accounting-Answer messages to
+ record the time that the reported event occurred, in seconds since
+ January 1, 1900 00:00 UTC.
+
+9. Accounting
+
+ This accounting protocol is based on a server directed model with
+ capabilities for real-time delivery of accounting information.
+ Several fault resilience methods [ACCMGMT] have been built in to the
+ protocol in order minimize loss of accounting data in various fault
+ situations and under different assumptions about the capabilities of
+ the used devices.
+
+9.1. Server Directed Model
+
+ The server directed model means that the device generating the
+ accounting data gets information from either the authorization server
+ (if contacted) or the accounting server regarding the way accounting
+ data shall be forwarded. This information includes accounting record
+ timeliness requirements.
+
+ As discussed in [ACCMGMT], real-time transfer of accounting records
+ is a requirement, such as the need to perform credit limit checks and
+ fraud detection. Note that batch accounting is not a requirement,
+ and is therefore not supported by Diameter. Should batched
+ accounting be required in the future, a new Diameter application will
+ need to be created, or it could be handled using another protocol.
+ Note, however, that even if at the Diameter layer accounting requests
+ are processed one by one, transport protocols used under Diameter
+ typically batch several requests in the same packet under heavy
+ traffic conditions. This may be sufficient for many applications.
+
+ The authorization server (chain) directs the selection of proper
+ transfer strategy, based on its knowledge of the user and
+ relationships of roaming partnerships. The server (or agents) uses
+ the Acct-Interim-Interval and Accounting-Realtime-Required AVPs to
+ control the operation of the Diameter peer operating as a client.
+ The Acct-Interim-Interval AVP, when present, instructs the Diameter
+ node acting as a client to produce accounting records continuously
+ even during a session. Accounting-Realtime-Required AVP is used to
+ control the behavior of the client when the transfer of accounting
+ records from the Diameter client is delayed or unsuccessful.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 115]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ The Diameter accounting server MAY override the interim interval or
+ the realtime requirements by including the Acct-Interim-Interval or
+ Accounting-Realtime-Required AVP in the Accounting-Answer message.
+ When one of these AVPs is present, the latest value received SHOULD
+ be used in further accounting activities for the same session.
+
+9.2. Protocol Messages
+
+ A Diameter node that receives a successful authentication and/or
+ authorization messages from the Home AAA server MUST collect
+ accounting information for the session. The Accounting-Request
+ message is used to transmit the accounting information to the Home
+ AAA server, which MUST reply with the Accounting-Answer message to
+ confirm reception. The Accounting-Answer message includes the
+ Result-Code AVP, which MAY indicate that an error was present in the
+ accounting message. A rejected Accounting-Request message MAY cause
+ the user's session to be terminated, depending on the value of the
+ Accounting-Realtime-Required AVP received earlier for the session in
+ question.
+
+ Each Diameter Accounting protocol message MAY be compressed, in order
+ to reduce network bandwidth usage. If IPsec and IKE are used to
+ secure the Diameter session, then IP compression [IPComp] MAY be used
+ and IKE [IKE] MAY be used to negotiate the compression parameters.
+ If TLS is used to secure the Diameter session, then TLS compression
+ [TLS] MAY be used.
+
+9.3. Application document requirements
+
+ Each Diameter application (e.g., NASREQ, MobileIP), MUST define their
+ Service-Specific AVPs that MUST be present in the Accounting-Request
+ message in a section entitled "Accounting AVPs". The application
+ MUST assume that the AVPs described in this document will be present
+ in all Accounting messages, so only their respective service-specific
+ AVPs need to be defined in this section.
+
+9.4. Fault Resilience
+
+ Diameter Base protocol mechanisms are used to overcome small message
+ loss and network faults of temporary nature.
+
+ Diameter peers acting as clients MUST implement the use of failover
+ to guard against server failures and certain network failures.
+ Diameter peers acting as agents or related off-line processing
+ systems MUST detect duplicate accounting records caused by the
+ sending of same record to several servers and duplication of messages
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 116]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ in transit. This detection MUST be based on the inspection of the
+ Session-Id and Accounting-Record-Number AVP pairs. Appendix C
+ discusses duplicate detection needs and implementation issues.
+
+ Diameter clients MAY have non-volatile memory for the safe storage of
+ accounting records over reboots or extended network failures, network
+ partitions, and server failures. If such memory is available, the
+ client SHOULD store new accounting records there as soon as the
+ records are created and until a positive acknowledgement of their
+ reception from the Diameter Server has been received. Upon a reboot,
+ the client MUST starting sending the records in the non-volatile
+ memory to the accounting server with appropriate modifications in
+ termination cause, session length, and other relevant information in
+ the records.
+
+ A further application of this protocol may include AVPs to control
+ how many accounting records may at most be stored in the Diameter
+ client without committing them to the non-volatile memory or
+ transferring them to the Diameter server.
+
+ The client SHOULD NOT remove the accounting data from any of its
+ memory areas before the correct Accounting-Answer has been received.
+ The client MAY remove oldest, undelivered or yet unacknowledged
+ accounting data if it runs out of resources such as memory. It is an
+ implementation dependent matter for the client to accept new sessions
+ under this condition.
+
+9.5. Accounting Records
+
+ In all accounting records, the Session-Id AVP MUST be present; the
+ User-Name AVP MUST be present if it is available to the Diameter
+ client. If strong authentication across agents is required, end-to-
+ end security may be used for authentication purposes.
+
+ Different types of accounting records are sent depending on the
+ actual type of accounted service and the authorization server's
+ directions for interim accounting. If the accounted service is a
+ one-time event, meaning that the start and stop of the event are
+ simultaneous, then the Accounting-Record-Type AVP MUST be present and
+ set to the value EVENT_RECORD.
+
+ If the accounted service is of a measurable length, then the AVP MUST
+ use the values START_RECORD, STOP_RECORD, and possibly,
+ INTERIM_RECORD. If the authorization server has not directed interim
+ accounting to be enabled for the session, two accounting records MUST
+ be generated for each service of type session. When the initial
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 117]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Accounting-Request for a given session is sent, the Accounting-
+ Record-Type AVP MUST be set to the value START_RECORD. When the last
+ Accounting-Request is sent, the value MUST be STOP_RECORD.
+
+ If the authorization server has directed interim accounting to be
+ enabled, the Diameter client MUST produce additional records between
+ the START_RECORD and STOP_RECORD, marked INTERIM_RECORD. The
+ production of these records is directed by Acct-Interim-Interval as
+ well as any re-authentication or re-authorization of the session. The
+ Diameter client MUST overwrite any previous interim accounting
+ records that are locally stored for delivery, if a new record is
+ being generated for the same session. This ensures that only one
+ pending interim record can exist on an access device for any given
+ session.
+
+ A particular value of Accounting-Sub-Session-Id MUST appear only in
+ one sequence of accounting records from a DIAMETER client, except for
+ the purposes of retransmission. The one sequence that is sent MUST
+ be either one record with Accounting-Record-Type AVP set to the value
+ EVENT_RECORD, or several records starting with one having the value
+ START_RECORD, followed by zero or more INTERIM_RECORD and a single
+ STOP_RECORD. A particular Diameter application specification MUST
+ define the type of sequences that MUST be used.
+
+9.6. Correlation of Accounting Records
+
+ The Diameter protocol's Session-Id AVP, which is globally unique (see
+ Section 8.8), is used during the authorization phase to identify a
+ particular session. Services that do not require any authorization
+ still use the Session-Id AVP to identify sessions. Accounting
+ messages MAY use a different Session-Id from that sent in
+ authorization messages. Specific applications MAY require different
+ a Session-ID for accounting messages.
+
+ However, there are certain applications that require multiple
+ accounting sub-sessions. Such applications would send messages with
+ a constant Session-Id AVP, but a different Accounting-Sub-Session-Id
+ AVP. In these cases, correlation is performed using the Session-Id.
+ It is important to note that receiving a STOP_RECORD with no
+ Accounting-Sub-Session-Id AVP when sub-sessions were originally used
+ in the START_RECORD messages implies that all sub-sessions are
+ terminated.
+
+ Furthermore, there are certain applications where a user receives
+ service from different access devices (e.g., Mobile IPv4), each with
+ their own unique Session-Id. In such cases, the Acct-Multi-Session-
+ Id AVP is used for correlation. During authorization, a server that
+
+
+
+
+Calhoun, et al. Standards Track [Page 118]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ determines that a request is for an existing session SHOULD include
+ the Acct-Multi-Session-Id AVP, which the access device MUST include
+ in all subsequent accounting messages.
+
+ The Acct-Multi-Session-Id AVP MAY include the value of the original
+ Session-Id. It's contents are implementation specific, but MUST be
+ globally unique across other Acct-Multi-Session-Id, and MUST NOT
+ change during the life of a session.
+
+ A Diameter application document MUST define the exact concept of a
+ session that is being accounted, and MAY define the concept of a
+ multi-session. For instance, the NASREQ DIAMETER application treats
+ a single PPP connection to a Network Access Server as one session,
+ and a set of Multilink PPP sessions as one multi-session.
+
+9.7. Accounting Command-Codes
+
+ This section defines Command-Code values that MUST be supported by
+ all Diameter implementations that provide Accounting services.
+
+9.7.1. Accounting-Request
+
+ The Accounting-Request (ACR) command, indicated by the Command-Code
+ field set to 271 and the Command Flags' 'R' bit set, is sent by a
+ Diameter node, acting as a client, in order to exchange accounting
+ information with a peer.
+
+ One of Acct-Application-Id and Vendor-Specific-Application-Id AVPs
+ MUST be present. If the Vendor-Specific-Application-Id grouped AVP
+ is present, it must have an Acct-Application-Id inside.
+
+ The AVP listed below SHOULD include service specific accounting AVPs,
+ as described in Section 9.3.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 119]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Message Format
+
+ <ACR> ::= < Diameter Header: 271, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Accounting-Record-Type }
+ { Accounting-Record-Number }
+ [ Acct-Application-Id ]
+ [ Vendor-Specific-Application-Id ]
+ [ User-Name ]
+ [ Accounting-Sub-Session-Id ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Acct-Interim-Interval ]
+ [ Accounting-Realtime-Required ]
+ [ Origin-State-Id ]
+ [ Event-Timestamp ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+9.7.2. Accounting-Answer
+
+ The Accounting-Answer (ACA) command, indicated by the Command-Code
+ field set to 271 and the Command Flags' 'R' bit cleared, is used to
+ acknowledge an Accounting-Request command. The Accounting-Answer
+ command contains the same Session-Id and includes the usage AVPs only
+ if CMS is in use when sending this command. Note that the inclusion
+ of the usage AVPs when CMS is not being used leads to unnecessarily
+ large answer messages, and can not be used as a server's proof of the
+ receipt of these AVPs in an end-to-end fashion. If the Accounting-
+ Request was protected by end-to-end security, then the corresponding
+ ACA message MUST be protected by end-to-end security.
+
+ Only the target Diameter Server, known as the home Diameter Server,
+ SHOULD respond with the Accounting-Answer command.
+
+ One of Acct-Application-Id and Vendor-Specific-Application-Id AVPs
+ MUST be present. If the Vendor-Specific-Application-Id grouped AVP
+ is present, it must have an Acct-Application-Id inside.
+
+ The AVP listed below SHOULD include service specific accounting AVPs,
+ as described in Section 9.3.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 120]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Message Format
+
+ <ACA> ::= < Diameter Header: 271, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ { Accounting-Record-Type }
+ { Accounting-Record-Number }
+ [ Acct-Application-Id ]
+ [ Vendor-Specific-Application-Id ]
+ [ User-Name ]
+ [ Accounting-Sub-Session-Id ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Error-Reporting-Host ]
+ [ Acct-Interim-Interval ]
+ [ Accounting-Realtime-Required ]
+ [ Origin-State-Id ]
+ [ Event-Timestamp ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+9.8. Accounting AVPs
+
+ This section contains AVPs that describe accounting usage information
+ related to a specific session.
+
+9.8.1. Accounting-Record-Type AVP
+
+ The Accounting-Record-Type AVP (AVP Code 480) is of type Enumerated
+ and contains the type of accounting record being sent. The following
+ values are currently defined for the Accounting-Record-Type AVP:
+
+ EVENT_RECORD 1
+ An Accounting Event Record is used to indicate that a one-time
+ event has occurred (meaning that the start and end of the event
+ are simultaneous). This record contains all information relevant
+ to the service, and is the only record of the service.
+
+ START_RECORD 2
+ An Accounting Start, Interim, and Stop Records are used to
+ indicate that a service of a measurable length has been given. An
+ Accounting Start Record is used to initiate an accounting session,
+ and contains accounting information that is relevant to the
+ initiation of the session.
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 121]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ INTERIM_RECORD 3
+ An Interim Accounting Record contains cumulative accounting
+ information for an existing accounting session. Interim
+ Accounting Records SHOULD be sent every time a re-authentication
+ or re-authorization occurs. Further, additional interim record
+ triggers MAY be defined by application-specific Diameter
+ applications. The selection of whether to use INTERIM_RECORD
+ records is done by the Acct-Interim-Interval AVP.
+
+ STOP_RECORD 4
+ An Accounting Stop Record is sent to terminate an accounting
+ session and contains cumulative accounting information relevant to
+ the existing session.
+
+9.8.2. Acct-Interim-Interval
+
+ The Acct-Interim-Interval AVP (AVP Code 85) is of type Unsigned32 and
+ is sent from the Diameter home authorization server to the Diameter
+ client. The client uses information in this AVP to decide how and
+ when to produce accounting records. With different values in this
+ AVP, service sessions can result in one, two, or two+N accounting
+ records, based on the needs of the home-organization. The following
+ accounting record production behavior is directed by the inclusion of
+ this AVP:
+
+ 1. The omission of the Acct-Interim-Interval AVP or its inclusion
+ with Value field set to 0 means that EVENT_RECORD, START_RECORD,
+ and STOP_RECORD are produced, as appropriate for the service.
+
+ 2. The inclusion of the AVP with Value field set to a non-zero value
+ means that INTERIM_RECORD records MUST be produced between the
+ START_RECORD and STOP_RECORD records. The Value field of this AVP
+ is the nominal interval between these records in seconds. The
+ Diameter node that originates the accounting information, known as
+ the client, MUST produce the first INTERIM_RECORD record roughly
+ at the time when this nominal interval has elapsed from the
+ START_RECORD, the next one again as the interval has elapsed once
+ more, and so on until the session ends and a STOP_RECORD record is
+ produced.
+
+ The client MUST ensure that the interim record production times
+ are randomized so that large accounting message storms are not
+ created either among records or around a common service start
+ time.
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 122]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+9.8.3. Accounting-Record-Number AVP
+
+ The Accounting-Record-Number AVP (AVP Code 485) is of type Unsigned32
+ and identifies this record within one session. As Session-Id AVPs
+ are globally unique, the combination of Session-Id and Accounting-
+ Record-Number AVPs is also globally unique, and can be used in
+ matching accounting records with confirmations. An easy way to
+ produce unique numbers is to set the value to 0 for records of type
+ EVENT_RECORD and START_RECORD, and set the value to 1 for the first
+ INTERIM_RECORD, 2 for the second, and so on until the value for
+ STOP_RECORD is one more than for the last INTERIM_RECORD.
+
+9.8.4. Acct-Session-Id AVP
+
+ The Acct-Session-Id AVP (AVP Code 44) is of type OctetString is only
+ used when RADIUS/Diameter translation occurs. This AVP contains the
+ contents of the RADIUS Acct-Session-Id attribute.
+
+9.8.5. Acct-Multi-Session-Id AVP
+
+ The Acct-Multi-Session-Id AVP (AVP Code 50) is of type UTF8String,
+ following the format specified in Section 8.8. The Acct-Multi-
+ Session-Id AVP is used to link together multiple related accounting
+ sessions, where each session would have a unique Session-Id, but the
+ same Acct-Multi-Session-Id AVP. This AVP MAY be returned by the
+ Diameter server in an authorization answer, and MUST be used in all
+ accounting messages for the given session.
+
+9.8.6. Accounting-Sub-Session-Id AVP
+
+ The Accounting-Sub-Session-Id AVP (AVP Code 287) is of type
+ Unsigned64 and contains the accounting sub-session identifier. The
+ combination of the Session-Id and this AVP MUST be unique per sub-
+ session, and the value of this AVP MUST be monotonically increased by
+ one for all new sub-sessions. The absence of this AVP implies no
+ sub-sessions are in use, with the exception of an Accounting-Request
+ whose Accounting-Record-Type is set to STOP_RECORD. A STOP_RECORD
+ message with no Accounting-Sub-Session-Id AVP present will signal the
+ termination of all sub-sessions for a given Session-Id.
+
+9.8.7. Accounting-Realtime-Required AVP
+
+ The Accounting-Realtime-Required AVP (AVP Code 483) is of type
+ Enumerated and is sent from the Diameter home authorization server to
+ the Diameter client or in the Accounting-Answer from the accounting
+ server. The client uses information in this AVP to decide what to do
+ if the sending of accounting records to the accounting server has
+ been temporarily prevented due to, for instance, a network problem.
+
+
+
+Calhoun, et al. Standards Track [Page 123]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ DELIVER_AND_GRANT 1
+ The AVP with Value field set to DELIVER_AND_GRANT means that the
+ service MUST only be granted as long as there is a connection to
+ an accounting server. Note that the set of alternative accounting
+ servers are treated as one server in this sense. Having to move
+ the accounting record stream to a backup server is not a reason to
+ discontinue the service to the user.
+
+ GRANT_AND_STORE 2
+ The AVP with Value field set to GRANT_AND_STORE means that service
+ SHOULD be granted if there is a connection, or as long as records
+ can still be stored as described in Section 9.4.
+
+ This is the default behavior if the AVP isn't included in the
+ reply from the authorization server.
+
+ GRANT_AND_LOSE 3
+ The AVP with Value field set to GRANT_AND_LOSE means that service
+ SHOULD be granted even if the records can not be delivered or
+ stored.
+
+10. AVP Occurrence Table
+
+ The following tables presents the AVPs defined in this document, and
+ specifies in which Diameter messages they MAY, or MAY NOT be present.
+ Note that AVPs that can only be present within a Grouped AVP are not
+ represented in this table.
+
+ The table uses the following symbols:
+
+ 0 The AVP MUST NOT be present in the message.
+ 0+ Zero or more instances of the AVP MAY be present in the
+ message.
+ 0-1 Zero or one instance of the AVP MAY be present in the
+ message. It is considered an error if there are more than
+ one instance of the AVP.
+ 1 One instance of the AVP MUST be present in the message.
+ 1+ At least one instance of the AVP MUST be present in the
+ message.
+
+10.1. Base Protocol Command AVP Table
+
+ The table in this section is limited to the non-accounting Command
+ Codes defined in this specification.
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 124]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ +-----------------------------------------------+
+ | Command-Code |
+ +---+---+---+---+---+---+---+---+---+---+---+---+
+ Attribute Name |CER|CEA|DPR|DPA|DWR|DWA|RAR|RAA|ASR|ASA|STR|STA|
+ --------------------+---+---+---+---+---+---+---+---+---+---+---+---+
+ Acct-Interim- |0 |0 |0 |0 |0 |0 |0-1|0 |0 |0 |0 |0 |
+ Interval | | | | | | | | | | | | |
+ Accounting-Realtime-|0 |0 |0 |0 |0 |0 |0-1|0 |0 |0 |0 |0 |
+ Required | | | | | | | | | | | | |
+ Acct-Application-Id |0+ |0+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Auth-Application-Id |0+ |0+ |0 |0 |0 |0 |1 |0 |1 |0 |1 |0 |
+ Auth-Grace-Period |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Auth-Request-Type |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Auth-Session-State |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Authorization- |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Lifetime | | | | | | | | | | | | |
+ Class |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0+ |0+ |
+ Destination-Host |0 |0 |0 |0 |0 |0 |1 |0 |1 |0 |0-1|0 |
+ Destination-Realm |0 |0 |0 |0 |0 |0 |1 |0 |1 |0 |1 |0 |
+ Disconnect-Cause |0 |0 |1 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Error-Message |0 |0-1|0 |0-1|0 |0-1|0 |0-1|0 |0-1|0 |0-1|
+ Error-Reporting-Host|0 |0 |0 |0 |0 |0 |0 |0-1|0 |0-1|0 |0-1|
+ Failed-AVP |0 |0+ |0 |0+ |0 |0+ |0 |0+ |0 |0+ |0 |0+ |
+ Firmware-Revision |0-1|0-1|0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Host-IP-Address |1+ |1+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Inband-Security-Id |0+ |0+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Multi-Round-Time-Out|0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Origin-Host |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |
+ Origin-Realm |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |
+ Origin-State-Id |0-1|0-1|0 |0 |0-1|0-1|0-1|0-1|0-1|0-1|0-1|0-1|
+ Product-Name |1 |1 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Proxy-Info |0 |0 |0 |0 |0 |0 |0+ |0+ |0+ |0+ |0+ |0+ |
+ Redirect-Host |0 |0 |0 |0 |0 |0 |0 |0+ |0 |0+ |0 |0+ |
+ Redirect-Host-Usage |0 |0 |0 |0 |0 |0 |0 |0-1|0 |0-1|0 |0-1|
+ Redirect-Max-Cache- |0 |0 |0 |0 |0 |0 |0 |0-1|0 |0-1|0 |0-1|
+ Time | | | | | | | | | | | | |
+ Result-Code |0 |1 |0 |1 |0 |1 |0 |1 |0 |0 |0 |1 |
+ Re-Auth-Request-Type|0 |0 |0 |0 |0 |0 |1 |0 |0 |0 |0 |0 |
+ Route-Record |0 |0 |0 |0 |0 |0 |0+ |0 |0+ |0 |0+ |0 |
+ Session-Binding |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Session-Id |0 |0 |0 |0 |0 |0 |1 |1 |1 |1 |1 |1 |
+ Session-Server- |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Failover | | | | | | | | | | | | |
+ Session-Timeout |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Supported-Vendor-Id |0+ |0+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Termination-Cause |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |1 |0 |
+ User-Name |0 |0 |0 |0 |0 |0 |0-1|0-1|0-1|0-1|0-1|0-1|
+ Vendor-Id |1 |1 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+
+
+
+Calhoun, et al. Standards Track [Page 125]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Vendor-Specific- |0+ |0+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
+ Application-Id | | | | | | | | | | | | |
+ --------------------+---+---+---+---+---+---+---+---+---+---+---+---+
+
+10.2. Accounting AVP Table
+
+ The table in this section is used to represent which AVPs defined in
+ this document are to be present in the Accounting messages. These
+ AVP occurrence requirements are guidelines, which may be expanded,
+ and/or overridden by application-specific requirements in the
+ Diameter applications documents.
+
+ +-----------+
+ | Command |
+ | Code |
+ +-----+-----+
+ Attribute Name | ACR | ACA |
+ ------------------------------+-----+-----+
+ Acct-Interim-Interval | 0-1 | 0-1 |
+ Acct-Multi-Session-Id | 0-1 | 0-1 |
+ Accounting-Record-Number | 1 | 1 |
+ Accounting-Record-Type | 1 | 1 |
+ Acct-Session-Id | 0-1 | 0-1 |
+ Accounting-Sub-Session-Id | 0-1 | 0-1 |
+ Accounting-Realtime-Required | 0-1 | 0-1 |
+ Acct-Application-Id | 0-1 | 0-1 |
+ Auth-Application-Id | 0 | 0 |
+ Class | 0+ | 0+ |
+ Destination-Host | 0-1 | 0 |
+ Destination-Realm | 1 | 0 |
+ Error-Reporting-Host | 0 | 0+ |
+ Event-Timestamp | 0-1 | 0-1 |
+ Origin-Host | 1 | 1 |
+ Origin-Realm | 1 | 1 |
+ Proxy-Info | 0+ | 0+ |
+ Route-Record | 0+ | 0+ |
+ Result-Code | 0 | 1 |
+ Session-Id | 1 | 1 |
+ Termination-Cause | 0-1 | 0-1 |
+ User-Name | 0-1 | 0-1 |
+ Vendor-Specific-Application-Id| 0-1 | 0-1 |
+ ------------------------------+-----+-----+
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 126]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+11. IANA Considerations
+
+ This section provides guidance to the Internet Assigned Numbers
+ Authority (IANA) regarding registration of values related to the
+ Diameter protocol, in accordance with BCP 26 [IANA]. The following
+ policies are used here with the meanings defined in BCP 26: "Private
+ Use", "First Come First Served", "Expert Review", "Specification
+ Required", "IETF Consensus", "Standards Action".
+
+ This section explains the criteria to be used by the IANA for
+ assignment of numbers within namespaces defined within this document.
+
+ Diameter is not intended as a general purpose protocol, and
+ allocations SHOULD NOT be made for purposes unrelated to
+ authentication, authorization or accounting.
+
+ For registration requests where a Designated Expert should be
+ consulted, the responsible IESG area director should appoint the
+ Designated Expert. For Designated Expert with Specification
+ Required, the request is posted to the AAA WG mailing list (or, if it
+ has been disbanded, a successor designated by the Area Director) for
+ comment and review, and MUST include a pointer to a public
+ specification. Before a period of 30 days has passed, the Designated
+ Expert will either approve or deny the registration request and
+ publish a notice of the decision to the AAA WG mailing list or its
+ successor. A denial notice must be justified by an explanation and,
+ in the cases where it is possible, concrete suggestions on how the
+ request can be modified so as to become acceptable.
+
+11.1. AVP Header
+
+ As defined in Section 4, the AVP header contains three fields that
+ requires IANA namespace management; the AVP Code, Vendor-ID and Flags
+ field.
+
+11.1.1. AVP Codes
+
+ The AVP Code namespace is used to identify attributes. There are
+ multiple namespaces. Vendors can have their own AVP Codes namespace
+ which will be identified by their Vendor-ID (also known as
+ Enterprise-Number) and they control the assignments of their vendor-
+ specific AVP codes within their own namespace. The absence of a
+ Vendor-ID or a Vendor-ID value of zero (0) identifies the IETF IANA
+ controlled AVP Codes namespace. The AVP Codes and sometimes also
+ possible values in an AVP are controlled and maintained by IANA.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 127]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ AVP Code 0 is not used. AVP Codes 1-255 are managed separately as
+ RADIUS Attribute Types [RADTYPE]. This document defines the AVP
+ Codes 257-274, 276-285, 287, 291-300, 480, 483 and 485-486. See
+ Section 4.5 for the assignment of the namespace in this
+ specification.
+
+ AVPs may be allocated following Designated Expert with Specification
+ Required [IANA]. Release of blocks of AVPs (more than 3 at a time
+ for a given purpose) should require IETF Consensus.
+
+ Note that Diameter defines a mechanism for Vendor-Specific AVPs,
+ where the Vendor-Id field in the AVP header is set to a non-zero
+ value. Vendor-Specific AVPs codes are for Private Use and should be
+ encouraged instead of allocation of global attribute types, for
+ functions specific only to one vendor's implementation of Diameter,
+ where no interoperability is deemed useful. Where a Vendor-Specific
+ AVP is implemented by more than one vendor, allocation of global AVPs
+ should be encouraged instead.
+
+11.1.2. AVP Flags
+
+ There are 8 bits in the AVP Flags field of the AVP header, defined in
+ Section 4. This document assigns bit 0 ('V'endor Specific), bit 1
+ ('M'andatory) and bit 2 ('P'rotected). The remaining bits should
+ only be assigned via a Standards Action [IANA].
+
+11.2. Diameter Header
+
+ As defined in Section 3, the Diameter header contains two fields that
+ require IANA namespace management; Command Code and Command Flags.
+
+11.2.1. Command Codes
+
+ The Command Code namespace is used to identify Diameter commands.
+ The values 0-255 are reserved for RADIUS backward compatibility, and
+ are defined as "RADIUS Packet Type Codes" in [RADTYPE]. Values 256-
+ 16,777,213 are for permanent, standard commands, allocated by IETF
+ Consensus [IANA]. This document defines the Command Codes 257, 258,
+ 271, 274-275, 280 and 282. See Section 3.1 for the assignment of the
+ namespace in this specification.
+
+ The values 16,777,214 and 16,777,215 (hexadecimal values 0xfffffe -
+ 0xffffff) are reserved for experimental commands. As these codes are
+ only for experimental and testing purposes, no guarantee is made for
+ interoperability between Diameter peers using experimental commands,
+ as outlined in [IANA-EXP].
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 128]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+11.2.2. Command Flags
+
+ There are eight bits in the Command Flags field of the Diameter
+ header. This document assigns bit 0 ('R'equest), bit 1 ('P'roxy),
+ bit 2 ('E'rror) and bit 3 ('T'). Bits 4 through 7 MUST only be
+ assigned via a Standards Action [IANA].
+
+11.3. Application Identifiers
+
+ As defined in Section 2.4, the Application Identifier is used to
+ identify a specific Diameter Application. There are standards-track
+ application ids and vendor specific application ids.
+
+ IANA [IANA] has assigned the range 0x00000001 to 0x00ffffff for
+ standards-track applications; and 0x01000000 - 0xfffffffe for vendor
+ specific applications, on a first-come, first-served basis. The
+ following values are allocated.
+
+ Diameter Common Messages 0
+ NASREQ 1 [NASREQ]
+ Mobile-IP 2 [DIAMMIP]
+ Diameter Base Accounting 3
+ Relay 0xffffffff
+
+ Assignment of standards-track application IDs are by Designated
+ Expert with Specification Required [IANA].
+
+ Both Application-Id and Acct-Application-Id AVPs use the same
+ Application Identifier space.
+
+ Vendor-Specific Application Identifiers, are for Private Use.
+ Vendor-Specific Application Identifiers are assigned on a First Come,
+ First Served basis by IANA.
+
+11.4. AVP Values
+
+ Certain AVPs in Diameter define a list of values with various
+ meanings. For attributes other than those specified in this section,
+ adding additional values to the list can be done on a First Come,
+ First Served basis by IANA.
+
+11.4.1. Result-Code AVP Values
+
+ As defined in Section 7.1, the Result-Code AVP (AVP Code 268) defines
+ the values 1001, 2001-2002, 3001-3010, 4001-4002 and 5001-5017.
+
+ All remaining values are available for assignment via IETF Consensus
+ [IANA].
+
+
+
+Calhoun, et al. Standards Track [Page 129]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+11.4.2. Accounting-Record-Type AVP Values
+
+ As defined in Section 9.8.1, the Accounting-Record-Type AVP (AVP Code
+ 480) defines the values 1-4. All remaining values are available for
+ assignment via IETF Consensus [IANA].
+
+11.4.3. Termination-Cause AVP Values
+
+ As defined in Section 8.15, the Termination-Cause AVP (AVP Code 295)
+ defines the values 1-8. All remaining values are available for
+ assignment via IETF Consensus [IANA].
+
+11.4.4. Redirect-Host-Usage AVP Values
+
+ As defined in Section 6.13, the Redirect-Host-Usage AVP (AVP Code
+ 261) defines the values 0-5. All remaining values are available for
+ assignment via IETF Consensus [IANA].
+
+11.4.5. Session-Server-Failover AVP Values
+
+ As defined in Section 8.18, the Session-Server-Failover AVP (AVP Code
+ 271) defines the values 0-3. All remaining values are available for
+ assignment via IETF Consensus [IANA].
+
+11.4.6. Session-Binding AVP Values
+
+ As defined in Section 8.17, the Session-Binding AVP (AVP Code 270)
+ defines the bits 1-4. All remaining bits are available for
+ assignment via IETF Consensus [IANA].
+
+11.4.7. Disconnect-Cause AVP Values
+
+ As defined in Section 5.4.3, the Disconnect-Cause AVP (AVP Code 273)
+ defines the values 0-2. All remaining values are available for
+ assignment via IETF Consensus [IANA].
+
+11.4.8. Auth-Request-Type AVP Values
+
+ As defined in Section 8.7, the Auth-Request-Type AVP (AVP Code 274)
+ defines the values 1-3. All remaining values are available for
+ assignment via IETF Consensus [IANA].
+
+11.4.9. Auth-Session-State AVP Values
+
+ As defined in Section 8.11, the Auth-Session-State AVP (AVP Code 277)
+ defines the values 0-1. All remaining values are available for
+ assignment via IETF Consensus [IANA].
+
+
+
+
+Calhoun, et al. Standards Track [Page 130]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+11.4.10. Re-Auth-Request-Type AVP Values
+
+ As defined in Section 8.12, the Re-Auth-Request-Type AVP (AVP Code
+ 285) defines the values 0-1. All remaining values are available for
+ assignment via IETF Consensus [IANA].
+
+11.4.11. Accounting-Realtime-Required AVP Values
+
+ As defined in Section 9.8.7, the Accounting-Realtime-Required AVP
+ (AVP Code 483) defines the values 1-3. All remaining values are
+ available for assignment via IETF Consensus [IANA].
+
+11.4.12. Inband-Security-Id AVP (code 299)
+
+ As defined in Section 6.10, the Inband-Security-Id AVP (AVP Code 299)
+ defines the values 0-1. All remaining values are available for
+ assignment via IETF Consensus [IANA].
+
+11.5. Diameter TCP/SCTP Port Numbers
+
+ The IANA has assigned TCP and SCTP port number 3868 to Diameter.
+
+11.6. NAPTR Service Fields
+
+ The registration in the RFC MUST include the following information:
+
+ Service Field: The service field being registered. An example for a
+ new fictitious transport protocol called NCTP might be "AAA+D2N".
+
+ Protocol: The specific transport protocol associated with that
+ service field. This MUST include the name and acronym for the
+ protocol, along with reference to a document that describes the
+ transport protocol. For example - "New Connectionless Transport
+ Protocol (NCTP), RFC 5766".
+
+ Name and Contact Information: The name, address, email address and
+ telephone number for the person performing the registration.
+
+ The following values have been placed into the registry:
+
+ Services Field Protocol
+ AAA+D2T TCP
+ AAA+D2S SCTP
+
+12. Diameter protocol related configurable parameters
+
+ This section contains the configurable parameters that are found
+ throughout this document:
+
+
+
+Calhoun, et al. Standards Track [Page 131]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ Diameter Peer
+ A Diameter entity MAY communicate with peers that are statically
+ configured. A statically configured Diameter peer would require
+ that either the IP address or the fully qualified domain name
+ (FQDN) be supplied, which would then be used to resolve through
+ DNS.
+
+ Realm Routing Table
+ A Diameter proxy server routes messages based on the realm portion
+ of a Network Access Identifier (NAI). The server MUST have a
+ table of Realm Names, and the address of the peer to which the
+ message must be forwarded to. The routing table MAY also include
+ a "default route", which is typically used for all messages that
+ cannot be locally processed.
+
+ Tc timer
+ The Tc timer controls the frequency that transport connection
+ attempts are done to a peer with whom no active transport
+ connection exists. The recommended value is 30 seconds.
+
+13. Security Considerations
+
+ The Diameter base protocol assumes that messages are secured by using
+ either IPSec or TLS. This security mechanism is acceptable in
+ environments where there is no untrusted third party agent. In other
+ situations, end-to-end security is needed.
+
+ Diameter clients, such as Network Access Servers (NASes) and Mobility
+ Agents MUST support IP Security [SECARCH] and MAY support TLS [TLS].
+ Diameter servers MUST support TLS and IPsec. Diameter
+ implementations MUST use transmission-level security of some kind
+ (IPsec or TLS) on each connection.
+
+ If a Diameter connection is not protected by IPsec, then the CER/CEA
+ exchange MUST include an Inband-Security-ID AVP with a value of TLS.
+ For TLS usage, a TLS handshake will begin when both ends are in the
+ open state, after completion of the CER/CEA exchange. If the TLS
+ handshake is successful, all further messages will be sent via TLS.
+ If the handshake fails, both ends move to the closed state.
+
+ It is suggested that IPsec be used primarily at the edges for intra-
+ domain exchanges. For NAS devices without certificate support, pre-
+ shared keys can be used between the NAS and a local AAA proxy.
+
+ For protection of inter-domain exchanges, TLS is recommended. See
+ Sections 13.1 and 13.2 for more details on IPsec and TLS usage.
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 132]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+13.1. IPsec Usage
+
+ All Diameter implementations MUST support IPsec ESP [IPsec] in
+ transport mode with non-null encryption and authentication algorithms
+ to provide per-packet authentication, integrity protection and
+ confidentiality, and MUST support the replay protection mechanisms of
+ IPsec.
+
+ Diameter implementations MUST support IKE for peer authentication,
+ negotiation of security associations, and key management, using the
+ IPsec DOI [IPSECDOI]. Diameter implementations MUST support peer
+ authentication using a pre-shared key, and MAY support certificate-
+ based peer authentication using digital signatures. Peer
+ authentication using the public key encryption methods outlined in
+ IKE's Sections 5.2 and 5.3 [IKE] SHOULD NOT be used.
+
+ Conformant implementations MUST support both IKE Main Mode and
+ Aggressive Mode. When pre-shared keys are used for authentication,
+ IKE Aggressive Mode SHOULD be used, and IKE Main Mode SHOULD NOT be
+ used. When digital signatures are used for authentication, either
+ IKE Main Mode or IKE Aggressive Mode MAY be used.
+
+ When digital signatures are used to achieve authentication, an IKE
+ negotiator SHOULD use IKE Certificate Request Payload(s) to specify
+ the certificate authority (or authorities) that are trusted in
+ accordance with its local policy. IKE negotiators SHOULD use
+ pertinent certificate revocation checks before accepting a PKI
+ certificate for use in IKE's authentication procedures.
+
+ The Phase 2 Quick Mode exchanges used to negotiate protection for
+ Diameter connections MUST explicitly carry the Identity Payload
+ fields (IDci and IDcr). The DOI provides for several types of
+ identification data. However, when used in conformant
+ implementations, each ID Payload MUST carry a single IP address and a
+ single non-zero port number, and MUST NOT use the IP Subnet or IP
+ Address Range formats. This allows the Phase 2 security association
+ to correspond to specific TCP and SCTP connections.
+
+ Since IPsec acceleration hardware may only be able to handle a
+ limited number of active IKE Phase 2 SAs, Phase 2 delete messages may
+ be sent for idle SAs, as a means of keeping the number of active
+ Phase 2 SAs to a minimum. The receipt of an IKE Phase 2 delete
+ message SHOULD NOT be interpreted as a reason for tearing down a
+ Diameter connection. Rather, it is preferable to leave the
+ connection up, and if additional traffic is sent on it, to bring up
+ another IKE Phase 2 SA to protect it. This avoids the potential for
+ continually bringing connections up and down.
+
+
+
+
+Calhoun, et al. Standards Track [Page 133]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+13.2. TLS Usage
+
+ A Diameter node that initiates a connection to another Diameter node
+ acts as a TLS client according to [TLS], and a Diameter node that
+ accepts a connection acts as a TLS server. Diameter nodes
+ implementing TLS for security MUST mutually authenticate as part of
+ TLS session establishment. In order to ensure mutual authentication,
+ the Diameter node acting as TLS server must request a certificate
+ from the Diameter node acting as TLS client, and the Diameter node
+ acting as TLS client MUST be prepared to supply a certificate on
+ request.
+
+ Diameter nodes MUST be able to negotiate the following TLS cipher
+ suites:
+
+ TLS_RSA_WITH_RC4_128_MD5
+ TLS_RSA_WITH_RC4_128_SHA
+ TLS_RSA_WITH_3DES_EDE_CBC_SHA
+
+ Diameter nodes SHOULD be able to negotiate the following TLS cipher
+ suite:
+
+ TLS_RSA_WITH_AES_128_CBC_SHA
+
+ Diameter nodes MAY negotiate other TLS cipher suites.
+
+13.3. Peer-to-Peer Considerations
+
+ As with any peer-to-peer protocol, proper configuration of the trust
+ model within a Diameter peer is essential to security. When
+ certificates are used, it is necessary to configure the root
+ certificate authorities trusted by the Diameter peer. These root CAs
+ are likely to be unique to Diameter usage and distinct from the root
+ CAs that might be trusted for other purposes such as Web browsing.
+ In general, it is expected that those root CAs will be configured so
+ as to reflect the business relationships between the organization
+ hosting the Diameter peer and other organizations. As a result, a
+ Diameter peer will typically not be configured to allow connectivity
+ with any arbitrary peer. When certificate authentication Diameter
+ peers may not be known beforehand, and therefore peer discovery may
+ be required.
+
+ Note that IPsec is considerably less flexible than TLS when it comes
+ to configuring root CAs. Since use of Port identifiers is prohibited
+ within IKE Phase 1, within IPsec it is not possible to uniquely
+ configure trusted root CAs for each application individually; the
+ same policy must be used for all applications. This implies, for
+ example, that a root CA trusted for use with Diameter must also be
+
+
+
+Calhoun, et al. Standards Track [Page 134]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ trusted to protect SNMP. These restrictions can be awkward at best.
+ Since TLS supports application-level granularity in certificate
+ policy, TLS SHOULD be used to protect Diameter connections between
+ administrative domains. IPsec is most appropriate for intra-domain
+ usage when pre-shared keys are used as a security mechanism.
+
+ When pre-shared key authentication is used with IPsec to protect
+ Diameter, unique pre-shared keys are configured with Diameter peers,
+ who are identified by their IP address (Main Mode), or possibly their
+ FQDN (Aggressive Mode). As a result, it is necessary for the set of
+ Diameter peers to be known beforehand. Therefore, peer discovery is
+ typically not necessary.
+
+ The following is intended to provide some guidance on the issue.
+
+ It is recommended that a Diameter peer implement the same security
+ mechanism (IPsec or TLS) across all its peer-to-peer connections.
+ Inconsistent use of security mechanisms can result in redundant
+ security mechanisms being used (e.g., TLS over IPsec) or worse,
+ potential security vulnerabilities. When IPsec is used with
+ Diameter, a typical security policy for outbound traffic is "Initiate
+ IPsec, from me to any, destination port Diameter"; for inbound
+ traffic, the policy would be "Require IPsec, from any to me,
+ destination port Diameter".
+
+ This policy causes IPsec to be used whenever a Diameter peer
+ initiates a connection to another Diameter peer, and to be required
+ whenever an inbound Diameter connection occurs. This policy is
+ attractive, since it does not require policy to be set for each peer
+ or dynamically modified each time a new Diameter connection is
+ created; an IPsec SA is automatically created based on a simple
+ static policy. Since IPsec extensions are typically not available to
+ the sockets API on most platforms, and IPsec policy functionality is
+ implementation dependent, use of a simple static policy is the often
+ the simplest route to IPsec-enabling a Diameter implementation.
+
+ One implication of the recommended policy is that if a node is using
+ both TLS and IPsec, there is not a convenient way in which to use
+ either TLS or IPsec, but not both, without reserving an additional
+ port for TLS usage. Since Diameter uses the same port for TLS and
+ non-TLS usage, where the recommended IPsec policy is put in place, a
+ TLS-protected connection will match the IPsec policy, and both IPsec
+ and TLS will be used to protect the Diameter connection. To avoid
+ this, it would be necessary to plumb peer-specific policies either
+ statically or dynamically.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 135]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ If IPsec is used to secure Diameter peer-to-peer connections, IPsec
+ policy SHOULD be set so as to require IPsec protection for inbound
+ connections, and to initiate IPsec protection for outbound
+ connections. This can be accomplished via use of inbound and
+ outbound filter policy.
+
+14. References
+
+14.1. Normative References
+
+ [AAATRANS] Aboba, B. and J. Wood, "Authentication, Authorization
+ and Accounting (AAA) Transport Profile", RFC 3539,
+ June 2003.
+
+ [ABNF] Crocker, D. and P. Overell, "Augmented BNF for Syntax
+ Specifications: ABNF", RFC 2234, November 1997.
+
+ [ASSIGNNO] Reynolds, J., "Assigned Numbers: RFC 1700 is Replaced
+ by an On-line Database", RFC 3232, January 2002.
+
+ [DIFFSERV] Nichols, K., Blake, S., Baker, F. and D. Black,
+ "Definition of the Differentiated Services Field (DS
+ Field) in the IPv4 and IPv6 Headers", RFC 2474,
+ December 1998.
+
+ [DIFFSERVAF] Heinanen, J., Baker, F., Weiss, W. and J. Wroclawski,
+ "Assured Forwarding PHB Group", RFC 2597, June 1999.
+
+ [DIFFSERVEF] Davie, B., Charny, A., Bennet, J., Benson, K., Le
+ Boudec, J., Courtney, W., Davari, S., Firoiu, V. and
+ D. Stiliadis, "An Expedited Forwarding PHB", RFC 3246,
+ March 2002.
+
+ [DNSSRV] Gulbrandsen, A., Vixie, P. and L. Esibov, "A DNS RR
+ for specifying the location of services (DNS SRV)",
+ RFC 2782, February 2000.
+
+ [EAP] Blunk, L. and J. Vollbrecht, "PPP Extensible
+ Authentication Protocol (EAP)", RFC 2284, March 1998.
+
+ [FLOATPOINT] Institute of Electrical and Electronics Engineers,
+ "IEEE Standard for Binary Floating-Point Arithmetic",
+ ANSI/IEEE Standard 754-1985, August 1985.
+
+ [IANA] Narten, T. and H. Alvestrand, "Guidelines for Writing
+ an IANA Considerations Section in RFCs", BCP 26, RFC
+ 2434, October 1998.
+
+
+
+
+Calhoun, et al. Standards Track [Page 136]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ [IANAADFAM] IANA; "Address Family Numbers",
+ http://www.iana.org/assignments/address-family-numbers
+
+ [IANAWEB] IANA, "Number assignment", http://www.iana.org
+
+ [IKE] Harkins, D. and D. Carrel, "The Internet Key Exchange
+ (IKE)", RFC 2409, November 1998.
+
+ [IPComp] Shacham, A., Monsour, R., Pereira, R. and M. Thomas,
+ "IP Payload Compression Protocol (IPComp)", RFC 3173,
+ September 2001.
+
+ [IPSECDOI] Piper, D., "The Internet IP Security Domain of
+ Interpretation for ISAKMP", RFC 2407, November 1998.
+
+ [IPV4] Postel, J., "Internet Protocol", STD 5, RFC 791,
+ September 1981.
+
+ [IPV6] Hinden, R. and S. Deering, "IP Version 6 Addressing
+ Architecture", RFC 2373, July 1998.
+
+ [KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [NAI] Aboba, B. and M. Beadles, "The Network Access
+ Identifier", RFC 2486, January 1999.
+
+ [NAPTR] Mealling, M. and R. Daniel, "The naming authority
+ pointer (NAPTR) DNS resource record," RFC 2915,
+ September 2000.
+
+ [RADTYPE] IANA, "RADIUS Types",
+ http://www.iana.org/assignments/radius-types
+
+ [SCTP] Stewart, R., Xie, Q., Morneault, K., Sharp, C.,
+ Schwarzbauer, H., Taylor, T., Rytina, I., Kalla, M.,
+ Zhang, L. and V. Paxson, "Stream Control Transmission
+ Protocol", RFC 2960, October 2000.
+
+ [SLP] Veizades, J., Guttman, E., Perkins, C. and M. Day,
+ "Service Location Protocol, Version 2", RFC 2165, June
+ 1999.
+
+ [SNTP] Mills, D., "Simple Network Time Protocol (SNTP)
+ Version 4 for IPv4, IPv6 and OSI", RFC 2030, October
+ 1996.
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 137]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ [TCP] Postel, J. "Transmission Control Protocol", STD 7, RFC
+ 793, January 1981.
+
+ [TEMPLATE] Guttman, E., Perkins, C. and J. Kempf, "Service
+ Templates and Service: Schemes", RFC 2609, June 1999.
+
+ [TLS] Dierks, T. and C. Allen, "The TLS Protocol Version
+ 1.0", RFC 2246, January 1999.
+
+ [TLSSCTP] Jungmaier, A., Rescorla, E. and M. Tuexen, "Transport
+ Layer Security over Stream Control Transmission
+ Protocol", RFC 3436, December 2002.
+
+ [URI] Berners-Lee, T., Fielding, R. and L. Masinter,
+ "Uniform Resource Identifiers (URI): Generic Syntax",
+ RFC 2396, August 1998.
+
+ [UTF8] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", RFC 2279, January 1998.
+
+14.2. Informative References
+
+ [AAACMS] P. Calhoun, W. Bulley, S. Farrell, "Diameter CMS
+ Security Application", Work in Progress.
+
+ [AAAREQ] Aboba, B., Calhoun, P., Glass, S., Hiller, T., McCann,
+ P., Shiino, H., Zorn, G., Dommety, G., Perkins, C.,
+ Patil, B., Mitton, D., Manning, S., Beadles, M.,
+ Walsh, P., Chen, X., Sivalingham, S., Hameed, A.,
+ Munson, M., Jacobs, S., Lim, B., Hirschman, B., Hsu,
+ R., Xu, Y., Campbell, E., Baba, S. and E. Jaques,
+ "Criteria for Evaluating AAA Protocols for Network
+ Access", RFC 2989, November 2000.
+
+ [ACCMGMT] Aboba, B., Arkko, J. and D. Harrington. "Introduction
+ to Accounting Management", RFC 2975, October 2000.
+
+ [CDMA2000] Hiller, T., Walsh, P., Chen, X., Munson, M., Dommety,
+ G., Sivalingham, S., Lim, B., McCann, P., Shiino, H.,
+ Hirschman, B., Manning, S., Hsu, R., Koo, H., Lipford,
+ M., Calhoun, P., Lo, C., Jaques, E., Campbell, E., Xu,
+ Y., Baba, S., Ayaki, T., Seki, T. and A. Hameed,
+ "CDMA2000 Wireless Data Requirements for AAA", RFC
+ 3141, June 2001.
+
+ [DIAMMIP] P. Calhoun, C. Perkins, "Diameter Mobile IP
+ Application", Work in Progress.
+
+
+
+
+Calhoun, et al. Standards Track [Page 138]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ [DYNAUTH] Chiba, M., Dommety, G., Eklund, M., Mitton, D. and B.
+ Aboba, "Dynamic Authorization Extensions to Remote
+ Authentication Dial In User Service (RADIUS)", RFC
+ 3576, July 2003.
+
+ [IANA-EXP] T. Narten, "Assigning Experimental and Testing Numbers
+ Considered Useful", Work in Progress.
+
+ [MIPV4] Perkins, C., "IP Mobility Support for IPv4", RFC 3344,
+ August 2002.
+
+ [MIPREQ] Glass, S., Hiller, T., Jacobs, S. and C. Perkins,
+ "Mobile IP Authentication, Authorization, and
+ Accounting Requirements", RFC 2977, October 2000.
+
+ [NASNG] Mitton, D. and M. Beadles, "Network Access Server
+ Requirements Next Generation (NASREQNG) NAS Model",
+ RFC 2881, July 2000.
+
+ [NASREQ] P. Calhoun, W. Bulley, A. Rubens, J. Haag, "Diameter
+ NASREQ Application", Work in Progress.
+
+ [NASCRIT] Beadles, M. and D. Mitton, "Criteria for Evaluating
+ Network Access Server Protocols", RFC 3169, September
+ 2001.
+
+ [PPP] Simpson, W., "The Point-to-Point Protocol (PPP)", STD
+ 51, RFC 1661, July 1994.
+
+ [PROXYCHAIN] Aboba, B. and J. Vollbrecht, "Proxy Chaining and
+ Policy Implementation in Roaming", RFC 2607, June
+ 1999.
+
+ [RADACCT] Rigney, C., "RADIUS Accounting", RFC 2866, June 2000.
+
+ [RADEXT] Rigney, C., Willats, W. and P. Calhoun, "RADIUS
+ Extensions", RFC 2869, June 2000.
+
+ [RADIUS] Rigney, C., Willens, S., Rubens, A. and W. Simpson,
+ "Remote Authentication Dial In User Service (RADIUS)",
+ RFC 2865, June 2000.
+
+ [ROAMREV] Aboba, B., Lu, J., Alsop, J., Ding, J. and W. Wang,
+ "Review of Roaming Implementations", RFC 2194,
+ September 1997.
+
+ [ROAMCRIT] Aboba, B. and G. Zorn, "Criteria for Evaluating
+ Roaming Protocols", RFC 2477, January 1999.
+
+
+
+Calhoun, et al. Standards Track [Page 139]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ [SECARCH] Kent, S. and R. Atkinson, "Security Architecture for
+ the Internet Protocol", RFC 2401, November 1998.
+
+ [TACACS] Finseth, C., "An Access Control Protocol, Sometimes
+ Called TACACS", RFC 1492, July 1993.
+
+15. Acknowledgements
+
+ The authors would like to thank Nenad Trifunovic, Tony Johansson and
+ Pankaj Patel for their participation in the pre-IETF Document Reading
+ Party. Allison Mankin, Jonathan Wood and Bernard Aboba provided
+ invaluable assistance in working out transport issues, and similarly
+ with Steven Bellovin in the security area.
+
+ Paul Funk and David Mitton were instrumental in getting the Peer
+ State Machine correct, and our deep thanks go to them for their time.
+
+ Text in this document was also provided by Paul Funk, Mark Eklund,
+ Mark Jones and Dave Spence. Jacques Caron provided many great
+ comments as a result of a thorough review of the spec.
+
+ The authors would also like to acknowledge the following people for
+ their contribution in the development of the Diameter protocol:
+
+ Allan C. Rubens, Haseeb Akhtar, William Bulley, Stephen Farrell,
+ David Frascone, Daniel C. Fox, Lol Grant, Ignacio Goyret, Nancy
+ Greene, Peter Heitman, Fredrik Johansson, Mark Jones, Martin Julien,
+ Bob Kopacz, Paul Krumviede, Fergal Ladley, Ryan Moats, Victor Muslin,
+ Kenneth Peirce, John Schnizlein, Sumit Vakil, John R. Vollbrecht and
+ Jeff Weisberg.
+
+ Finally, Pat Calhoun would like to thank Sun Microsystems since most
+ of the effort put into this document was done while he was in their
+ employ.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 140]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+Appendix A. Diameter Service Template
+
+ The following service template describes the attributes used by
+ Diameter servers to advertise themselves. This simplifies the
+ process of selecting an appropriate server to communicate with. A
+ Diameter client can request specific Diameter servers based on
+ characteristics of the Diameter service desired (for example, an AAA
+ server to use for accounting.)
+
+ Name of submitter: "Erik Guttman" <[email protected]> Language of
+ service template: en
+
+ Security Considerations:
+ Diameter clients and servers use various cryptographic mechanisms
+ to protect communication integrity, confidentiality as well as
+ perform end-point authentication. It would thus be difficult if
+ not impossible for an attacker to advertise itself using SLPv2 and
+ pose as a legitimate Diameter peer without proper preconfigured
+ secrets or cryptographic keys. Still, as Diameter services are
+ vital for network operation it is important to use SLPv2
+ authentication to prevent an attacker from modifying or
+ eliminating service advertisements for legitimate Diameter
+ servers.
+
+ Template text:
+ -------------------------template begins here-----------------------
+ template-type=service:diameter
+
+ template-version=0.0
+
+ template-description=
+ The Diameter protocol is defined by RFC 3588.
+
+ template-url-syntax=
+ url-path= ; The Diameter URL format is described in Section 2.9.
+ ; Example: 'aaa://aaa.example.com:1812;transport=tcp
+ supported-auth-applications= string L M
+ # This attribute lists the Diameter applications supported by the
+ # AAA implementation. The applications currently defined are:
+ # Application Name Defined by
+ # ---------------- -----------------------------------
+ # NASREQ Diameter Network Access Server Application
+ # MobileIP Diameter Mobile IP Application
+ #
+ # Notes:
+ # . Diameter implementations support one or more applications.
+ # . Additional applications may be defined in the future.
+ # An updated service template will be created at that time.
+
+
+
+Calhoun, et al. Standards Track [Page 141]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ #
+ NASREQ,MobileIP
+
+ supported-acct-applications= string L M
+ # This attribute lists the Diameter applications supported by the
+ # AAA implementation. The applications currently defined are:
+ # Application Name Defined by
+ # ---------------- -----------------------------------
+ # NASREQ Diameter Network Access Server Application
+ # MobileIP Diameter Mobile IP Application
+ #
+ # Notes:
+ # . Diameter implementations support one or more applications.
+ # . Additional applications may be defined in the future.
+ # An updated service template will be created at that time.
+ #
+ NASREQ,MobileIP
+
+ supported-transports= string L M
+ SCTP
+ # This attribute lists the supported transports that the Diameter
+ # implementation accepts. Note that a compliant Diameter
+ # implementation MUST support SCTP, though it MAY support other
+ # transports, too.
+ SCTP,TCP
+
+ -------------------------template ends here-----------------------
+
+Appendix B. NAPTR Example
+
+ As an example, consider a client that wishes to resolve aaa:ex.com.
+ The client performs a NAPTR query for that domain, and the following
+ NAPTR records are returned:
+
+ ;; order pref flags service regexp replacement
+ IN NAPTR 50 50 "s" "AAA+D2S" ""
+ _diameter._sctp.example.com IN NAPTR 100 50 "s" "AAA+D2T"
+ "" _aaa._tcp.example.com
+
+ This indicates that the server supports SCTP, and TCP, in that order.
+ If the client supports over SCTP, SCTP will be used, targeted to a
+ host determined by an SRV lookup of _diameter._sctp.ex.com. That
+ lookup would return:
+
+ ;; Priority Weight Port Target
+ IN SRV 0 1 5060 server1.example.com IN SRV 0
+ 2 5060 server2.example.com
+
+
+
+
+Calhoun, et al. Standards Track [Page 142]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+Appendix C. Duplicate Detection
+
+ As described in Section 9.4, accounting record duplicate detection is
+ based on session identifiers. Duplicates can appear for various
+ reasons:
+
+ - Failover to an alternate server. Where close to real-time
+ performance is required, failover thresholds need to be kept low
+ and this may lead to an increased likelihood of duplicates.
+ Failover can occur at the client or within Diameter agents.
+
+ - Failure of a client or agent after sending of a record from non-
+ volatile memory, but prior to receipt of an application layer ACK
+ and deletion of the record. record to be sent. This will result
+ in retransmission of the record soon after the client or agent has
+ rebooted.
+
+ - Duplicates received from RADIUS gateways. Since the
+ retransmission behavior of RADIUS is not defined within [RFC2865],
+ the likelihood of duplication will vary according to the
+ implementation.
+
+ - Implementation problems and misconfiguration.
+
+ The T flag is used as an indication of an application layer
+ retransmission event, e.g., due to failover to an alternate server.
+ It is defined only for request messages sent by Diameter clients or
+ agents. For instance, after a reboot, a client may not know whether
+ it has already tried to send the accounting records in its non-
+ volatile memory before the reboot occurred. Diameter servers MAY use
+ the T flag as an aid when processing requests and detecting duplicate
+ messages. However, servers that do this MUST ensure that duplicates
+ are found even when the first transmitted request arrives at the
+ server after the retransmitted request. It can be used only in cases
+ where no answer has been received from the Server for a request and
+ the request is sent again, (e.g., due to a failover to an alternate
+ peer, due to a recovered primary peer or due to a client re-sending a
+ stored record from non-volatile memory such as after reboot of a
+ client or agent).
+
+ In some cases the Diameter accounting server can delay the duplicate
+ detection and accounting record processing until a post-processing
+ phase takes place. At that time records are likely to be sorted
+ according to the included User-Name and duplicate elimination is easy
+ in this case. In other situations it may be necessary to perform
+ real-time duplicate detection, such as when credit limits are imposed
+ or real-time fraud detection is desired.
+
+
+
+
+Calhoun, et al. Standards Track [Page 143]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+ In general, only generation of duplicates due to failover or re-
+ sending of records in non-volatile storage can be reliably detected
+ by Diameter clients or agents. In such cases the Diameter client or
+ agents can mark the message as possible duplicate by setting the T
+ flag. Since the Diameter server is responsible for duplicate
+ detection, it can choose to make use of the T flag or not, in order
+ to optimize duplicate detection. Since the T flag does not affect
+ interoperability, and may not be needed by some servers, generation
+ of the T flag is REQUIRED for Diameter clients and agents, but MAY be
+ implemented by Diameter servers.
+
+ As an example, it can be usually be assumed that duplicates appear
+ within a time window of longest recorded network partition or device
+ fault, perhaps a day. So only records within this time window need
+ to be looked at in the backward direction. Secondly, hashing
+ techniques or other schemes, such as the use of the T flag in the
+ received messages, may be used to eliminate the need to do a full
+ search even in this set except for rare cases.
+
+ The following is an example of how the T flag may be used by the
+ server to detect duplicate requests.
+
+ A Diameter server MAY check the T flag of the received message to
+ determine if the record is a possible duplicate. If the T flag is
+ set in the request message, the server searches for a duplicate
+ within a configurable duplication time window backward and
+ forward. This limits database searching to those records where
+ the T flag is set. In a well run network, network partitions and
+ device faults will presumably be rare events, so this approach
+ represents a substantial optimization of the duplicate detection
+ process. During failover, it is possible for the original record
+ to be received after the T flag marked record, due to differences
+ in network delays experienced along the path by the original and
+ duplicate transmissions. The likelihood of this occurring
+ increases as the failover interval is decreased. In order to be
+ able to detect out of order duplicates, the Diameter server should
+ use backward and forward time windows when performing duplicate
+ checking for the T flag marked request. For example, in order to
+ allow time for the original record to exit the network and be
+ recorded by the accounting server, the Diameter server can delay
+ processing records with the T flag set until a time period
+ TIME_WAIT + RECORD_PROCESSING_TIME has elapsed after the closing
+ of the original transport connection. After this time period has
+ expired, then it may check the T flag marked records against the
+ database with relative assurance that the original records, if
+ sent, have been received and recorded.
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 144]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+Appendix D. Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11. Copies of
+ claims of rights made available for publication and any assurances of
+ licenses to be made available, or the result of an attempt made to
+ obtain a general license or permission for the use of such
+ proprietary rights by implementers or users of this specification can
+ be obtained from the IETF Secretariat.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights which may cover technology that may be required to practice
+ this standard. Please address the information to the IETF Executive
+ Director.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 145]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+Authors' Addresses
+
+ Pat R. Calhoun
+ Airespace, Inc.
+ 110 Nortech Parkway
+ San Jose, California, 95134
+ USA
+
+ Phone: +1 408-635-2023
+ Fax: +1 408-635-2020
+
+ John Loughney
+ Nokia Research Center
+ Itamerenkatu 11-13
+ 00180 Helsinki
+ Finland
+
+ Phone: +358 50 483 6242
+
+ Jari Arkko
+ Ericsson
+ 02420 Jorvas
+ Finland
+
+ Phone: +358 40 5079256
+
+ Erik Guttman
+ Sun Microsystems, Inc.
+ Eichhoelzelstr. 7
+ 74915 Waibstadt
+ Germany
+
+ Phone: +49 7263 911 701
+
+ Glen Zorn
+ Cisco Systems, Inc.
+ 500 108th Avenue N.E., Suite 500
+ Bellevue, WA 98004
+ USA
+
+ Phone: +1 425 438 8218
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 146]
+
+RFC 3588 Diameter Based Protocol September 2003
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 147]
+
diff --git a/lib/diameter/doc/standard/rfc4005.txt b/lib/diameter/doc/standard/rfc4005.txt
new file mode 100644
index 0000000000..561508b53b
--- /dev/null
+++ b/lib/diameter/doc/standard/rfc4005.txt
@@ -0,0 +1,4763 @@
+
+
+
+
+
+
+Network Working Group P. Calhoun
+Request for Comments: 4005 G. Zorn
+Category: Standards Track Cisco Systems Inc.
+ D. Spence
+ Consultant
+ D. Mitton
+ Circular Networks
+ August 2005
+
+
+ Diameter Network Access Server Application
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ This document describes the Diameter protocol application used for
+ Authentication, Authorization, and Accounting (AAA) services in the
+ Network Access Server (NAS) environment. When combined with the
+ Diameter Base protocol, Transport Profile, and Extensible
+ Authentication Protocol specifications, this application
+ specification satisfies typical network access services requirements.
+
+ Initial deployments of the Diameter protocol are expected to include
+ legacy systems. Therefore, this application has been carefully
+ designed to ease the burden of protocol conversion between RADIUS and
+ Diameter. This is achieved by including the RADIUS attribute space
+ to eliminate the need to perform many attribute translations.
+
+ The interactions between Diameter applications and RADIUS specified
+ in this document are to be applied to all Diameter applications. In
+ this sense, this document extends the Base Diameter protocol.
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 1]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 5
+ 1.1. Terminology . . . . . . . . . . . . . . . . . . . . . . 5
+ 1.2. Requirements Language . . . . . . . . . . . . . . . . . 6
+ 1.3. Advertising Application Support . . . . . . . . . . . . 6
+ 2. NAS Calls, Ports, and Sessions . . . . . . . . . . . . . . . . 6
+ 2.1. Diameter Session Establishment . . . . . . . . . . . . . 7
+ 2.2. Diameter Session Reauthentication or Reauthorization . . 7
+ 2.3. Diameter Session Termination . . . . . . . . . . . . . . 8
+ 3. NAS Messages . . . . . . . . . . . . . . . . . . . . . . . . . 9
+ 3.1. AA-Request (AAR) Command . . . . . . . . . . . . . . . . 9
+ 3.2. AA-Answer (AAA) Command . . . . . . . . . . . . . . . . 11
+ 3.3. Re-Auth-Request (RAR) Command . . . . . . . . . . . . . 13
+ 3.4. Re-Auth-Answer (RAA) Command . . . . . . . . . . . . . . 14
+ 3.5. Session-Termination-Request (STR) Command . . . . . . . 15
+ 3.6. Session-Termination-Answer (STA) Command . . . . . . . . 15
+ 3.7. Abort-Session-Request (ASR) Command . . . . . . . . . . 16
+ 3.8. Abort-Session-Answer (ASA) Command . . . . . . . . . . . 17
+ 3.9. Accounting-Request (ACR) Command . . . . . . . . . . . . 17
+ 3.10. Accounting-Answer (ACA) Command. . . . . . . . . . . . . 19
+ 4. NAS Session AVPs . . . . . . . . . . . . . . . . . . . . . . . 20
+ 4.1. Call and Session Information . . . . . . . . . . . . . . 21
+ 4.2. NAS-Port AVP . . . . . . . . . . . . . . . . . . . . . . 22
+ 4.3. NAS-Port-Id AVP . . . . . . . . . . . . . . . . . . . . 22
+ 4.4. NAS-Port-Type AVP . . . . . . . . . . . . . . . . . . . 22
+ 4.5. Called-Station-Id AVP . . . . . . . . . . . . . . . . . 23
+ 4.6. Calling-Station-Id AVP . . . . . . . . . . . . . . . . . 23
+ 4.7. Connect-Info AVP . . . . . . . . . . . . . . . . . . . . 24
+ 4.8. Originating-Line-Info AVP . . . . . . . . . . . . . . . 24
+ 4.9. Reply-Message AVP . . . . . . . . . . . . . . . . . . . 25
+ 5. NAS Authentication AVPs . . . . . . . . . . . . . . . . . . . 26
+ 5.1. User-Password AVP . . . . . . . . . . . . . . . . . . . 26
+ 5.2. Password-Retry AVP . . . . . . . . . . . . . . . . . . . 27
+ 5.3. Prompt AVP . . . . . . . . . . . . . . . . . . . . . . . 27
+ 5.4. CHAP-Auth AVP . . . . . . . . . . . . . . . . . . . . . 27
+ 5.5. CHAP-Algorithm AVP . . . . . . . . . . . . . . . . . . . 28
+ 5.6. CHAP-Ident AVP . . . . . . . . . . . . . . . . . . . . . 28
+ 5.7. CHAP-Response AVP . . . . . . . . . . . . . . . . . . . 28
+ 5.8. CHAP-Challenge AVP . . . . . . . . . . . . . . . . . . . 28
+ 5.9. ARAP-Password AVP . . . . . . . . . . . . . . . . . . . 28
+ 5.10. ARAP-Challenge-Response AVP. . . . . . . . . . . . . . . 28
+ 5.11. ARAP-Security AVP. . . . . . . . . . . . . . . . . . . . 29
+ 5.12. ARAP-Security-Data AVP . . . . . . . . . . . . . . . . . 29
+ 6. NAS Authorization AVPs . . . . . . . . . . . . . . . . . . . . 29
+ 6.1. Service-Type AVP . . . . . . . . . . . . . . . . . . . . 30
+ 6.2. Callback-Number AVP . . . . . . . . . . . . . . . . . . 32
+ 6.3. Callback-Id AVP . . . . . . . . . . . . . . . . . . . . 32
+
+
+
+Calhoun, et al. Standards Track [Page 2]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ 6.4. Idle-Timeout AVP . . . . . . . . . . . . . . . . . . . . 32
+ 6.5. Port-Limit AVP . . . . . . . . . . . . . . . . . . . . . 32
+ 6.6. NAS-Filter-Rule AVP . . . . . . . . . . . . . . . . . . 32
+ 6.7. Filter-Id AVP . . . . . . . . . . . . . . . . . . . . . 33
+ 6.8. Configuration-Token AVP . . . . . . . . . . . . . . . . 33
+ 6.9. QoS-Filter-Rule AVP . . . . . . . . . . . . . . . . . . 33
+ 6.10. Framed Access Authorization AVPs . . . . . . . . . . . . 35
+ 6.10.1. Framed-Protocol AVP . . . . . . . . . . . . . . 35
+ 6.10.2. Framed-Routing AVP. . . . . . . . . . . . . . . 35
+ 6.10.3. Framed-MTU AVP. . . . . . . . . . . . . . . . . 35
+ 6.10.4. Framed-Compression AVP. . . . . . . . . . . . . 36
+ 6.11. IP Access Authorization AVPs.. . . . . . . . . . . . . . 36
+ 6.11.1. Framed-IP-Address AVP . . . . . . . . . . . . . 36
+ 6.11.2. Framed-IP-Netmask AVP . . . . . . . . . . . . . 36
+ 6.11.3. Framed-Route AVP. . . . . . . . . . . . . . . . 37
+ 6.11.4. Framed-Pool AVP . . . . . . . . . . . . . . . . 37
+ 6.11.5. Framed-Interface-Id AVP . . . . . . . . . . . . 37
+ 6.11.6. Framed-IPv6-Prefix AVP. . . . . . . . . . . . . 38
+ 6.11.7. Framed-IPv6-Route AVP . . . . . . . . . . . . . 38
+ 6.11.8. Framed-IPv6-Pool AVP. . . . . . . . . . . . . . 38
+ 6.12. IPX Access . . . . . . . . . . . . . . . . . . . . . . . 38
+ 6.12.1. Framed-IPX-Network AVP. . . . . . . . . . . . . 39
+ 6.13. AppleTalk Network Access . . . . . . . . . . . . . . . . 39
+ 6.13.1. Framed-AppleTalk-Link AVP . . . . . . . . . . . 39
+ 6.13.2. Framed-AppleTalk-Network AVP . . . . . . . . . 39
+ 6.13.3. Framed-AppleTalk-Zone AVP . . . . . . . . . . . 40
+ 6.14. AppleTalk Remote Access. . . . . . . . . . . . . . . . . 40
+ 6.14.1. ARAP-Features AVP . . . . . . . . . . . . . . . 40
+ 6.14.2. ARAP-Zone-Access AVP. . . . . . . . . . . . . . 40
+ 6.15. Non-Framed Access Authorization AVPs . . . . . . . . . . 40
+ 6.15.1. Login-IP-Host AVP . . . . . . . . . . . . . . . 40
+ 6.15.2. Login-IPv6-Host AVP . . . . . . . . . . . . . . 41
+ 6.15.3. Login-Service AVP . . . . . . . . . . . . . . . 41
+ 6.16. TCP Services . . . . . . . . . . . . . . . . . . . . . . 42
+ 6.16.1. Login-TCP-Port AVP . . . . . . . . . . . . . . 42
+ 6.17. LAT Services . . . . . . . . . . . . . . . . . . . . . . 42
+ 6.17.1. Login-LAT-Service AVP . . . . . . . . . . . . . 42
+ 6.17.2. Login-LAT-Node AVP. . . . . . . . . . . . . . . 43
+ 6.17.3. Login-LAT-Group AVP . . . . . . . . . . . . . . 43
+ 6.17.4. Login-LAT-Port AVP. . . . . . . . . . . . . . . 43
+ 7. NAS Tunneling . . . . . . . . . . . . . . . . . . . . . . . . 44
+ 7.1. Tunneling AVP . . . . . . . . . . . . . . . . . . . . . 44
+ 7.2. Tunnel-Type AVP . . . . . . . . . . . . . . . . . . . . 45
+ 7.3. Tunnel-Medium-Type AVP . . . . . . . . . . . . . . . . . 46
+ 7.4. Tunnel-Client-Endpoint AVP . . . . . . . . . . . . . . . 46
+ 7.5. Tunnel-Server-Endpoint AVP . . . . . . . . . . . . . . . 47
+ 7.6. Tunnel-Password AVP . . . . . . . . . . . . . . . . . . 48
+ 7.7. Tunnel-Private-Group-Id AVP . . . . . . . . . . . . . . 48
+
+
+
+Calhoun, et al. Standards Track [Page 3]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ 7.8. Tunnel-Assignment-Id AVP . . . . . . . . . . . . . . . . 48
+ 7.9. Tunnel-Preference AVP . . . . . . . . . . . . . . . . . 49
+ 7.10. Tunnel-Client-Auth-Id AVP. . . . . . . . . . . . . . . . 50
+ 7.11. Tunnel-Server-Auth-Id AVP. . . . . . . . . . . . . . . . 50
+ 8. NAS Accounting . . . . . . . . . . . . . . . . . . . . . . . . 50
+ 8.1. Accounting-Input-Octets AVP . . . . . . . . . . . . . . 51
+ 8.2. Accounting-Output-Octets AVP . . . . . . . . . . . . . . 52
+ 8.3. Accounting-Input-Packets AVP . . . . . . . . . . . . . . 52
+ 8.4. Accounting-Output-Packets AVP . . . . . . . . . . . . . 52
+ 8.5. Acct-Session-Time AVP . . . . . . . . . . . . . . . . . 52
+ 8.6. Acct-Authentic AVP . . . . . . . . . . . . . . . . . . . 52
+ 8.7. Accounting-Auth-Method AVP . . . . . . . . . . . . . . . 53
+ 8.8. Acct-Delay-Time . . . . . . . . . . . . . . . . . . . . 53
+ 8.9. Acct-Link-Count . . . . . . . . . . . . . . . . . . . . 54
+ 8.10. Acct-Tunnel-Connection AVP . . . . . . . . . . . . . . . 54
+ 8.11. Acct-Tunnel-Packets-Lost AVP . . . . . . . . . . . . . . 55
+ 9. RADIUS/Diameter Protocol Interactions . . . . . . . . . . . . 55
+ 9.1. RADIUS Request Forwarded as Diameter Request . . . . . . 55
+ 9.1.1. RADIUS Dynamic Authorization Considerations . . 59
+ 9.2. Diameter Request Forwarded as RADIUS Request . . . . . . 60
+ 9.2.1. RADIUS Dynamic Authorization Considerations . . 62
+ 9.3. AVPs Used Only for Compatibility . . . . . . . . . . . . 63
+ 9.3.1. NAS-Identifier AVP. . . . . . . . . . . . . . . 63
+ 9.3.2. NAS-IP-Address AVP. . . . . . . . . . . . . . . 64
+ 9.3.3. NAS-IPv6-Address AVP. . . . . . . . . . . . . . 65
+ 9.3.4. State AVP . . . . . . . . . . . . . . . . . . . 65
+ 9.3.5. Termination-Cause AVP Code Values . . . . . . . 66
+ 9.3.6. Origin-AAA-Protocol . . . . . . . . . . . . . . 68
+ 9.4. Prohibited RADIUS Attributes . . . . . . . . . . . . . . 69
+ 9.5. Translatable Diameter AVPs . . . . . . . . . . . . . . . 69
+ 9.6. RADIUS Vendor-Specific Attributes . . . . . . . . . . . 69
+ 9.6.1. Forwarding a Diameter Vendor Specific AVP as a
+ RADIUS VSA . . . . . . . . . . . . . . . . . . . 70
+ 9.6.2. Forwarding a RADIUS VSA as a Diameter Vendor
+ Specific AVP . . . . . . . . . . . . . . . . . . 70
+ 10. AVP Occurrence Tables. . . . . . . . . . . . . . . . . . . . . 71
+ 10.1. AA-Request/Answer AVP Table. . . . . . . . . . . . . . . 71
+ 10.2. Accounting AVP Tables. . . . . . . . . . . . . . . . . . 73
+ 10.2.1. Accounting Framed Access AVP Table. . . . . . . 74
+ 10.2.2. Accounting Non-Framed Access AVP Table. . . . . 76
+ 11. IANA Considerations. . . . . . . . . . . . . . . . . . . . . . 77
+ 11.1. Command Codes. . . . . . . . . . . . . . . . . . . . . . 77
+ 11.2. AVP Codes. . . . . . . . . . . . . . . . . . . . . . . . 78
+ 11.3. Application Identifier . . . . . . . . . . . . . . . . . 78
+ 11.4. CHAP-Algorithm AVP Values. . . . . . . . . . . . . . . . 78
+ 11.5. Accounting-Auth-Method AVP Values. . . . . . . . . . . . 78
+ 11.6. Origin-AAA-Protocol AVP Values . . . . . . . . . . . . . 78
+ 12. Security Considerations. . . . . . . . . . . . . . . . . . . . 78
+
+
+
+Calhoun, et al. Standards Track [Page 4]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ 13. References . . . . . . . . . . . . . . . . . . . . . . . . . . 79
+ 13.1. Normative References . . . . . . . . . . . . . . . . . . 79
+ 13.2. Informative References . . . . . . . . . . . . . . . . . 80
+ 14. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 83
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 84
+ Full Copyright Statement . . . . . . . . . . . . . . . . . . . . . 85
+
+1. Introduction
+
+ This document describes the Diameter protocol application used for
+ AAA in the Network Access Server (NAS) environment. When combined
+ with the Diameter Base protocol [BASE], Transport Profile
+ [DiamTrans], and EAP [DiamEAP] specifications, this Diameter NAS
+ application specification satisfies NAS-related requirements defined
+ in RFC 2989 [AAACriteria] and RFC 3169 [NASCriteria].
+
+ Initial deployments of the Diameter protocol are expected to include
+ legacy systems. Therefore, this application has been carefully
+ designed to ease the burden of protocol conversion between RADIUS and
+ Diameter. This is achieved by including the RADIUS attribute space
+ to eliminate the need to perform many attribute translations.
+
+ The interactions specified in this document between Diameter
+ applications and RADIUS are to be applied to all Diameter
+ applications. In this sense, this document extends the Base Diameter
+ protocol [BASE].
+
+ First, this document describes the operation of a Diameter NAS
+ application. Then it defines the Diameter message Command-Codes.
+ The following sections list the AVPs used in these messages, grouped
+ by common usage. These are session identification, authentication,
+ authorization, tunneling, and accounting. The authorization AVPs are
+ further broken down by service type. Interaction and backward
+ compatibility issues with RADIUS are discussed in later sections.
+
+1.1. Terminology
+
+ The base Diameter [BASE] specification section 1.4 defines most of
+ the terminology used in this document. Additionally, the following
+ terms and acronyms are used in this application:
+
+ NAS (Network Access Server) - A device that provides an access
+ service for a user to a network. The service may be a network
+ connection or a value-added service such as terminal emulation
+ [NASModel].
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 5]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ PPP (Point-to-Point Protocol) - A multiprotocol serial datalink. PPP
+ is the primary IP datalink used for dial-in NAS connection service
+ [PPP].
+
+ CHAP (Challenge Handshake Authentication Protocol) - An
+ authentication process used in PPP [PPPCHAP].
+
+ PAP (Password Authentication Protocol) - A deprecated PPP
+ authentication process, but often used for backward compatibility
+ [PAP].
+
+ SLIP (Serial Line Interface Protocol) - A serial datalink that only
+ supports IP. A design prior to PPP.
+
+ ARAP (Appletalk Remote Access Protocol) - A serial datalink for
+ accessing Appletalk networks [ARAP].
+
+ IPX (Internet Packet Exchange) - The network protocol used by NetWare
+ networks [IPX].
+
+ LAT (Local Area Transport) - A Digital Equipment Corp. LAN protocol
+ for terminal services [LAT].
+
+ VPN (Virtual Private Network) - In this document, this term is used
+ to describe access services that use tunneling methods.
+
+1.2. Requirements Language
+
+ In this document, the key words "MAY", "MUST", "MUST NOT",
+ "OPTIONAL", "RECOMMENDED", "SHOULD", and "SHOULD NOT" are to be
+ interpreted as described in [Keywords].
+
+1.3. Advertising Application Support
+
+ Diameter applications conforming to this specification MUST advertise
+ support by including the value of one (1) in the Auth-Application-Id
+ of Capabilities-Exchange-Request (CER), AA-Request (AAR), and AA-
+ Answer (AAA) messages. All other messages are defined by [BASE] and
+ use the Base application id value.
+
+2. NAS Calls, Ports, and Sessions
+
+ The arrival of a new call or service connection at a port of a
+ Network Access Server (NAS) starts a Diameter NAS message exchange.
+ Information about the call, the identity of the user, and the user's
+ authentication information are packaged into a Diameter AA-Request
+ (AAR) message and sent to a server.
+
+
+
+
+Calhoun, et al. Standards Track [Page 6]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ The server processes the information and responds with a Diameter
+ AA-Answer (AAA) message that contains authorization information for
+ the NAS, or a failure code (Result-Code AVP). A value of
+ DIAMETER_MULTI_ROUND_AUTH indicates an additional authentication
+ exchange, and several AAR and AAA messages may be exchanged until the
+ transaction completes.
+
+ Depending on the Auth-Request-Type AVP, the Diameter protocol allows
+ authorization-only requests that contain no authentication
+ information from the client. This capability goes beyond the Call
+ Check capabilities described in section 5.6 of [RADIUS] in that no
+ access decision is requested. As a result, service cannot be started
+ as a result of a response to an authorization-only request without
+ introducing a significant security vulnerability.
+
+ Since no equivalent capability exists in RADIUS, authorization-only
+ requests from a NAS implementing Diameter may not be easily
+ translated to an equivalent RADIUS message by a Diameter/RADIUS
+ gateway. For example, when a Diameter authorization-only request
+ cannot be translated to a RADIUS Call Check, it would be necessary
+ for the Diameter/RADIUS gateway to add authentication information to
+ the RADIUS Access Request. On receiving the Access-Reply, the
+ Diameter/RADIUS gateway would need to discard the access decision
+ (Accept/Reject). It is not clear whether these translations can be
+ accomplished without adding significant security vulnerabilities.
+
+2.1. Diameter Session Establishment
+
+ When the authentication or authorization exchange completes
+ successfully, the NAS application SHOULD start a session context. If
+ the Result-Code of DIAMETER_MULTI_ROUND_AUTH is returned, the
+ exchange continues until a success or error is returned.
+
+ If accounting is active, the application MUST also send an Accounting
+ message [BASE]. An Accounting-Record-Type of START_RECORD is sent
+ for a new session. If a session fails to start, the EVENT_RECORD
+ message is sent with the reason for the failure described.
+
+ Note that the return of an unsupportable Accounting-Realtime-Required
+ value [BASE] would result in a failure to establish the session.
+
+2.2. Diameter Session Reauthentication or Reauthorization
+
+ The Diameter Base protocol allows users to be periodically
+ reauthenticated and/or reauthorized. In such instances, the
+ Session-Id AVP in the AAR message MUST be the same as the one present
+ in the original authentication/authorization message.
+
+
+
+
+Calhoun, et al. Standards Track [Page 7]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ A Diameter server informs the NAS of the maximum time allowed before
+ reauthentication or reauthorization via the Authorization-Lifetime
+ AVP [BASE]. A NAS MAY reauthenticate and/or reauthorize before the
+ end, but A NAS MUST reauthenticate and/or reauthorize at the end of
+ the period provided by the Authorization-Lifetime AVP. The failure
+ of a reauthentication exchange will terminate the service.
+
+ Furthermore, it is possible for Diameter servers to issue an
+ unsolicited reauthentication and/or reauthorization request (e.g.,
+ Re-Auth-Request (RAR) message [BASE]) to the NAS. Upon receipt of
+ such a message, the NAS MUST respond to the request with a Re-Auth-
+ Answer (RAA) message [BASE].
+
+ If the RAR properly identifies an active session, the NAS will
+ initiate a new local reauthentication or authorization sequence as
+ indicated by the Re-Auth-Request-Type value. This will cause the NAS
+ to send a new AAR message using the existing Session-Id. The server
+ will respond with an AAA message to specify the new service
+ parameters.
+
+ If accounting is active, every change of authentication or
+ authorization SHOULD generate an accounting message. If the NAS
+ service is a continuation of the prior user context, then an
+ Accounting-Record-Type of INTERIM_RECORD indicating the new session
+ attributes and cumulative status would be appropriate. If a new user
+ or a significant change in authorization is detected by the NAS, then
+ the service may send two messages of the types STOP_RECORD and
+ START_RECORD. Accounting may change the subsession identifiers
+ (Acct-Session-ID, or Acct-Sub-Session-Id) to indicate such sub-
+ sessions. A service may also use a different Session-Id value for
+ accounting (see [BASE] section 9.6).
+
+ However, the Diameter Session-ID AVP value used for the initial
+ authorization exchange MUST be used to generate an STR message when
+ the session context is terminated.
+
+2.3. Diameter Session Termination
+
+ When a NAS receives an indication that a user's session is being
+ disconnected by the client (e.g., LCP Terminate is received) or an
+ administrative command, the NAS MUST issue a Session-Termination-
+ Request (STR) [BASE] to its Diameter Server. This will ensure that
+ any resources maintained on the servers are freed appropriately.
+
+ Furthermore, a NAS that receives an Abort-Session-Request (ASR)
+ [BASE] MUST issue an ASA if the session identified is active and
+ disconnect the PPP (or tunneling) session.
+
+
+
+
+Calhoun, et al. Standards Track [Page 8]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ If accounting is active, an Accounting STOP_RECORD message [BASE]
+ MUST be sent upon termination of the session context.
+
+ More information on Diameter Session Termination is included in
+ [BASE] sections 8.4 and 8.5.
+
+3. NAS Messages
+
+ This section defines the Diameter message Command-Code [BASE] values
+ that MUST be supported by all Diameter implementations conforming to
+ this specification. The Command Codes are as follows:
+
+ Command-Name Abbrev. Code Reference
+ -------------------------------------------------------
+ AA-Request AAR 265 3.1
+ AA-Answer AAA 265 3.2
+ Re-Auth-Request RAR 258 3.3
+ Re-Auth-Answer RAA 258 3.4
+ Session-Termination-Request STR 275 3.5
+ Session-Termination-Answer STA 275 3.6
+ Abort-Session-Request ASR 274 3.7
+ Abort-Session-Answer ASA 274 3.8
+ Accounting-Request ACR 271 3.9
+ Accounting-Answer ACA 271 3.10
+
+3.1. AA-Request (AAR) Command
+
+ The AA-Request (AAR), which is indicated by setting the Command-Code
+ field to 265 and the 'R' bit in the Command Flags field, is used to
+ request authentication and/or authorization for a given NAS user.
+ The type of request is identified through the Auth-Request-Type AVP
+ [BASE]. The recommended value for most RADIUS interoperabily
+ situations is AUTHORIZE_AUTHENTICATE.
+
+ If Authentication is requested, the User-Name attribute SHOULD be
+ present, as well as any additional authentication AVPs that would
+ carry the password information. A request for authorization SHOULD
+ only include the information from which the authorization will be
+ performed, such as the User-Name, Called-Station-Id, or Calling-
+ Station-Id AVPs. All requests SHOULD contain AVPs uniquely
+ identifying the source of the call, such as Origin-Host and NAS-Port.
+ Certain networks MAY use different AVPs for authorization purposes.
+ A request for authorization will include some AVPs defined in section
+ 6.
+
+ It is possible for a single session to be authorized first and then
+ for an authentication request to follow.
+
+
+
+
+Calhoun, et al. Standards Track [Page 9]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ This AA-Request message MAY be the result of a multi-round
+ authentication exchange, which occurs when the AA-Answer message is
+ received with the Result-Code AVP set to DIAMETER_MULTI_ROUND_AUTH.
+ A subsequent AAR message SHOULD be sent, with the User-Password AVP
+ that includes the user's response to the prompt, and MUST include any
+ State AVPs that were present in the AAA message.
+
+ Message Format
+ <AA-Request> ::= < Diameter Header: 265, REQ, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Auth-Request-Type }
+ [ Destination-Host ]
+ [ NAS-Identifier ]
+ [ NAS-IP-Address ]
+ [ NAS-IPv6-Address ]
+ [ NAS-Port ]
+ [ NAS-Port-Id ]
+ [ NAS-Port-Type ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ [ Port-Limit ]
+ [ User-Name ]
+ [ User-Password ]
+ [ Service-Type ]
+ [ State ]
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Auth-Session-State ]
+ [ Callback-Number ]
+ [ Called-Station-Id ]
+ [ Calling-Station-Id ]
+ [ Originating-Line-Info ]
+ [ Connect-Info ]
+ [ CHAP-Auth ]
+ [ CHAP-Challenge ]
+ * [ Framed-Compression ]
+ [ Framed-Interface-Id ]
+ [ Framed-IP-Address ]
+ * [ Framed-IPv6-Prefix ]
+ [ Framed-IP-Netmask ]
+ [ Framed-MTU ]
+ [ Framed-Protocol ]
+ [ ARAP-Password ]
+ [ ARAP-Security ]
+
+
+
+Calhoun, et al. Standards Track [Page 10]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ * [ ARAP-Security-Data ]
+ * [ Login-IP-Host ]
+ * [ Login-IPv6-Host ]
+ [ Login-LAT-Group ]
+ [ Login-LAT-Node ]
+ [ Login-LAT-Port ]
+ [ Login-LAT-Service ]
+ * [ Tunneling ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+3.2. AA-Answer (AAA) Command
+
+ The AA-Answer (AAA) message is indicated by setting the Command-Code
+ field to 265 and clearing the 'R' bit in the Command Flags field. It
+ is sent in response to the AA-Request (AAR) message. If
+ authorization was requested, a successful response will include the
+ authorization AVPs appropriate for the service being provided, as
+ defined in section 6.
+
+ For authentication exchanges requiring more than a single round trip,
+ the server MUST set the Result-Code AVP to DIAMETER_MULTI_ROUND_AUTH.
+ An AAA message with this result code MAY include one Reply-Message or
+ more and MAY include zero or one State AVPs.
+
+ If the Reply-Message AVP was present, the network access server
+ SHOULD send the text to the user's client to display to the user,
+ instructing the client to prompt the user for a response. For
+ example, this capability can be achieved in PPP via PAP. If the
+ access client is unable to prompt the user for a new response, it
+ MUST treat the AA-Answer (AAA) with the Reply-Message AVP as an error
+ and deny access.
+
+ Message Format
+
+ <AA-Answer> ::= < Diameter Header: 265, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Request-Type }
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ [ Service-Type ]
+ * [ Class ]
+ * [ Configuration-Token ]
+ [ Acct-Interim-Interval ]
+
+
+
+Calhoun, et al. Standards Track [Page 11]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ [ Idle-Timeout ]
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Auth-Session-State ]
+ [ Re-Auth-Request-Type ]
+ [ Multi-Round-Time-Out ]
+ [ Session-Timeout ]
+ [ State ]
+ * [ Reply-Message ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ * [ Filter-Id ]
+ [ Password-Retry ]
+ [ Port-Limit ]
+ [ Prompt ]
+ [ ARAP-Challenge-Response ]
+ [ ARAP-Features ]
+ [ ARAP-Security ]
+ * [ ARAP-Security-Data ]
+ [ ARAP-Zone-Access ]
+ [ Callback-Id ]
+ [ Callback-Number ]
+ [ Framed-Appletalk-Link ]
+ * [ Framed-Appletalk-Network ]
+ [ Framed-Appletalk-Zone ]
+ * [ Framed-Compression ]
+ [ Framed-Interface-Id ]
+ [ Framed-IP-Address ]
+ * [ Framed-IPv6-Prefix ]
+ [ Framed-IPv6-Pool ]
+ * [ Framed-IPv6-Route ]
+ [ Framed-IP-Netmask ]
+ * [ Framed-Route ]
+ [ Framed-Pool ]
+ [ Framed-IPX-Network ]
+ [ Framed-MTU ]
+ [ Framed-Protocol ]
+ [ Framed-Routing ]
+ * [ Login-IP-Host ]
+ * [ Login-IPv6-Host ]
+ [ Login-LAT-Group ]
+ [ Login-LAT-Node ]
+ [ Login-LAT-Port ]
+ [ Login-LAT-Service ]
+ [ Login-Service ]
+
+
+
+Calhoun, et al. Standards Track [Page 12]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ [ Login-TCP-Port ]
+ * [ NAS-Filter-Rule ]
+ * [ QoS-Filter-Rule ]
+ * [ Tunneling ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+3.3. Re-Auth-Request (RAR) Command
+
+ A Diameter server may initiate a re-authentication and/or re-
+ authorization service for a particular session by issuing a Re-Auth-
+ Request (RAR) message [BASE].
+
+ For example, for pre-paid services, the Diameter server that
+ originally authorized a session may need some confirmation that the
+ user is still using the services.
+
+ If a NAS receives an RAR message with Session-Id equal to a currently
+ active session and a Re-Auth-Type that includes authentication, it
+ MUST initiate a re-authentication toward the user, if the service
+ supports this particular feature.
+
+ Message Format
+
+ <RA-Request> ::= < Diameter Header: 258, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Destination-Host }
+ { Auth-Application-Id }
+ { Re-Auth-Request-Type }
+ [ User-Name ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ [ NAS-Identifier ]
+ [ NAS-IP-Address ]
+ [ NAS-IPv6-Address ]
+ [ NAS-Port ]
+ [ NAS-Port-Id ]
+ [ NAS-Port-Type ]
+ [ Service-Type ]
+ [ Framed-IP-Address ]
+ [ Framed-IPv6-Prefix ]
+ [ Framed-Interface-Id ]
+
+
+
+Calhoun, et al. Standards Track [Page 13]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ [ Called-Station-Id ]
+ [ Calling-Station-Id ]
+ [ Originating-Line-Info ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ State ]
+ * [ Class ]
+ [ Reply-Message ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+3.4. Re-Auth-Answer (RAA) Command
+
+ The Re-Auth-Answer (RAA) message [BASE] is sent in response to the
+ RAR. The Result-Code AVP MUST be present and indicates the
+ disposition of the request.
+
+ A successful RAA transaction MUST be followed by an AAR message.
+
+ Message Format
+
+ <RA-Answer> ::= < Diameter Header: 258, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ * [ Redirected-Host ]
+ [ Redirected-Host-Usage ]
+ [ Redirected-Host-Cache-Time ]
+ [ Service-Type ]
+ * [ Configuration-Token ]
+ [ Idle-Timeout ]
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Re-Auth-Request-Type ]
+ [ State ]
+ * [ Class ]
+ * [ Reply-Message ]
+ [ Prompt ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+
+
+Calhoun, et al. Standards Track [Page 14]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+3.5. Session-Termination-Request (STR) Command
+
+ The Session-Termination-Request (STR) message [BASE] is sent by the
+ NAS to inform the Diameter Server that an authenticated and/or
+ authorized session is being terminated.
+
+ Message Format
+
+ <ST-Request> ::= < Diameter Header: 275, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Auth-Application-Id }
+ { Termination-Cause }
+ [ User-Name ]
+ [ Destination-Host ]
+ * [ Class ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+3.6. Session-Termination-Answer (STA) Command
+
+ The Session-Termination-Answer (STA) message [BASE] is sent by the
+ Diameter Server to acknowledge the notification that the session has
+ been terminated. The Result-Code AVP MUST be present and MAY contain
+ an indication that an error occurred while the STR was being
+ serviced.
+
+ Upon sending or receiving the STA, the Diameter Server MUST release
+ all resources for the session indicated by the Session-Id AVP. Any
+ intermediate server in the Proxy-Chain MAY also release any
+ resources, if necessary.
+
+ Message Format
+
+ <ST-Answer> ::= < Diameter Header: 275, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ * [ Class ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+
+
+
+Calhoun, et al. Standards Track [Page 15]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ * [ Failed-AVP ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usase ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+3.7. Abort-Session-Request (ASR) Command
+
+ The Abort-Session-Request (ASR) message [BASE] may be sent by any
+ server to the NAS providing session service, to request that the
+ session identified by the Session-Id be stopped.
+
+ Message Format
+
+ <AS-Request> ::= < Diameter Header: 274, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Destination-Host }
+ { Auth-Application-Id }
+ [ User-Name ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ [ NAS-Identifier ]
+ [ NAS-IP-Address ]
+ [ NAS-IPv6-Address ]
+ [ NAS-Port ]
+ [ NAS-Port-Id ]
+ [ NAS-Port-Type ]
+ [ Service-Type ]
+ [ Framed-IP-Address ]
+ [ Framed-IPv6-Prefix ]
+ [ Framed-Interface-Id ]
+ [ Called-Station-Id ]
+ [ Calling-Station-Id ]
+ [ Originating-Line-Info ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ State ]
+ * [ Class ]
+ * [ Reply-Message ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+
+
+Calhoun, et al. Standards Track [Page 16]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+3.8. Abort-Session-Answer (ASA) Command
+
+ The ASA message [BASE] is sent in response to the ASR. The Result-
+ Code AVP MUST be present and indicates the disposition of the
+ request.
+
+ If the session identified by Session-Id in the ASR was successfully
+ terminated, Result-Code is set to DIAMETER_SUCCESS. If the session
+ is not currently active, Result-Code is set to
+ DIAMETER_UNKNOWN_SESSION_ID. If the access device does not stop the
+ session for any other reason, Result-Code is set to
+ DIAMETER_UNABLE_TO_COMPLY.
+
+ Message Format
+
+ <AS-Answer> ::= < Diameter Header: 274, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ [ State]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ * [ Redirected-Host ]
+ [ Redirected-Host-Usage ]
+ [ Redirected-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+3.9. Accounting-Request (ACR) Command
+
+ The ACR message [BASE] is sent by the NAS to report its session
+ information to a target server downstream.
+
+ Either of Acct-Application-Id or Vendor-Specific-Application-Id AVPs
+ MUST be present. If the Vendor-Specific-Application-Id grouped AVP
+ is present, it must have an Acct-Application-Id inside.
+
+ The AVPs listed in the Base MUST be assumed to be present, as
+ appropriate. NAS service-specific accounting AVPs SHOULD be present
+ as described in section 8 and the rest of this specification.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 17]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ Message Format
+
+ <AC-Request> ::= < Diameter Header: 271, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Accounting-Record-Type }
+ { Accounting-Record-Number }
+ [ Acct-Application-Id ]
+ [ Vendor-Specific-Application-Id ]
+ [ User-Name ]
+ [ Accounting-Sub-Session-Id ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ [ Destination-Host ]
+ [ Event-Timestamp ]
+ [ Acct-Delay-Time ]
+ [ NAS-Identifier ]
+ [ NAS-IP-Address ]
+ [ NAS-IPv6-Address ]
+ [ NAS-Port ]
+ [ NAS-Port-Id ]
+ [ NAS-Port-Type ]
+ * [ Class ]
+ [ Service-Type ]
+ [ Termination-Cause ]
+ [ Accounting-Input-Octets ]
+ [ Accounting-Input-Packets ]
+ [ Accounting-Output-Octets ]
+ [ Accounting-Output-Packets ]
+ [ Acct-Authentic ]
+ [ Accounting-Auth-Method ]
+ [ Acct-Link-Count ]
+ [ Acct-Session-Time ]
+ [ Acct-Tunnel-Connection ]
+ [ Acct-Tunnel-Packets-Lost ]
+ [ Callback-Id ]
+ [ Callback-Number ]
+ [ Called-Station-Id ]
+ [ Calling-Station-Id ]
+ * [ Connection-Info ]
+ [ Originating-Line-Info ]
+ [ Authorization-Lifetime ]
+ [ Session-Timeout ]
+ [ Idle-Timeout ]
+
+
+
+Calhoun, et al. Standards Track [Page 18]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ [ Port-Limit ]
+ [ Accounting-Realtime-Required ]
+ [ Acct-Interim-Interval ]
+ * [ Filter-Id ]
+ * [ NAS-Filter-Rule ]
+ * [ Qos-Filter-Rule ]
+ [ Framed-AppleTalk-Link ]
+ [ Framed-AppleTalk-Network ]
+ [ Framed-AppleTalk-Zone ]
+ [ Framed-Compression ]
+ [ Framed-Interface-Id ]
+ [ Framed-IP-Address ]
+ [ Framed-IP-Netmask ]
+ * [ Framed-IPv6-Prefix ]
+ [ Framed-IPv6-Pool ]
+ * [ Framed-IPv6-Route ]
+ [ Framed-IPX-Network ]
+ [ Framed-MTU ]
+ [ Framed-Pool ]
+ [ Framed-Protocol ]
+ * [ Framed-Route ]
+ [ Framed-Routing ]
+ * [ Login-IP-Host ]
+ * [ Login-IPv6-Host ]
+ [ Login-LAT-Group ]
+ [ Login-LAT-Node ]
+ [ Login-LAT-Port ]
+ [ Login-LAT-Service ]
+ [ Login-Service ]
+ [ Login-TCP-Port ]
+ * [ Tunneling ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+3.10. Accounting-Answer (ACA) Command
+
+ The ACA message [BASE] is used to acknowledge an Accounting-Request
+ command. The Accounting-Answer command contains the same Session-Id
+ as the Request. If the Accounting-Request was protected by end-to-
+ end security, then the corresponding ACA message MUST be protected as
+ well.
+
+ Only the target Diameter Server or home Diameter Server SHOULD
+ respond with the Accounting-Answer command.
+
+ Either Acct-Application-Id or Vendor-Specific-Application-Id AVPs
+ MUST be present, as it was in the request.
+
+
+
+Calhoun, et al. Standards Track [Page 19]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ The AVPs listed in the Base MUST be assumed to be present, as
+ appropriate. NAS service-specific accounting AVPs SHOULD be present
+ as described in section 8 and the rest of this specification.
+
+ Message Format
+
+ <AC-Answer> ::= < Diameter Header: 271, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ { Accounting-Record-Type }
+ { Accounting-Record-Number }
+ [ Acct-Application-Id ]
+ [ Vendor-Specific-Application-Id ]
+ [ User-Name ]
+ [ Accounting-Sub-Session-Id ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Event-Timestamp ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ [ NAS-Identifier ]
+ [ NAS-IP-Address ]
+ [ NAS-IPv6-Address ]
+ [ NAS-Port ]
+ [ NAS-Port-Id ]
+ [ NAS-Port-Type ]
+ [ Service-Type ]
+ [ Termination-Cause ]
+ [ Accounting-Realtime-Required ]
+ [ Acct-Interim-Interval ]
+ * [ Class ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+4. NAS Session AVPs
+
+ Diameter reserves the AVP Codes 0 - 255 for RADIUS functions that are
+ implemented in Diameter.
+
+ AVPs new to Diameter have code values of 256 and greater. A Diameter
+ message that includes one of these AVPs may represent functions not
+ present in the RADIUS environment and may cause interoperability
+
+
+
+Calhoun, et al. Standards Track [Page 20]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ issues, should the request traverse an AAA system that only supports
+ the RADIUS protocol.
+
+ Some RADIUS attributes are not allowed or supported directly in
+ Diameter. See section 9 for more information.
+
+4.1. Call and Session Information
+
+ This section contains the AVPs specific to NAS Diameter applications
+ that are needed to identify the call and session context and status
+ information. On a request, this information allows the server to
+ qualify the session.
+
+ These AVPs are used in addition to the Base AVPs of:
+
+ Session-Id
+ Auth-Application-Id
+ Origin-Host
+ Origin-Realm
+ Auth-Request-Type
+ Termination-Cause
+
+ The following table describes the session level AVPs; their AVP Code
+ values, types, and possible flag values; and whether the AVP MAY be
+ encrypted.
+
+ +---------------------+
+ | AVP Flag rules |
+ |----+-----+----+-----|----+
+ AVP Section | | |SHLD| MUST| |
+ Attribute Name Code Defined Value Type |MUST| MAY | NOT| NOT|Encr|
+ -----------------------------------------|----+-----+----+-----|----|
+ NAS-Port 5 4.2 Unsigned32 | M | P | | V | Y |
+ NAS-Port-Id 87 4.3 UTF8String | M | P | | V | Y |
+ NAS-Port-Type 61 4.4 Enumerated | M | P | | V | Y |
+ Called-Station-Id 30 4.5 UTF8String | M | P | | V | Y |
+ Calling-Station- 31 4.6 UTF8String | M | P | | V | Y |
+ Id | | | | | |
+ Connect-Info 77 4.7 UTF8String | M | P | | V | Y |
+ Originating-Line- 94 4.8 OctetString| | M,P | | V | Y |
+ Info | | | | | |
+ Reply-Message 18 4.9 UTF8String | M | P | | V | Y |
+ -----------------------------------------|----+-----+----+-----|----|
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 21]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+4.2. NAS-Port AVP
+
+ The NAS-Port AVP (AVP Code 5) is of type Unsigned32 and contains the
+ physical or virtual port number of the NAS which is authenticating
+ the user. Note that "port" is meant in its sense as a service
+ connection on the NAS, not as an IP protocol identifier.
+
+ Either NAS-Port or NAS-Port-Id (AVP Code 87) SHOULD be present in
+ AA-Request (AAR) commands if the NAS differentiates among its ports.
+
+4.3. NAS-Port-Id AVP
+
+ The NAS-Port-Id AVP (AVP Code 87) is of type UTF8String and consists
+ of ASCII text identifying the port of the NAS authenticating the
+ user. Note that "port" is meant in its sense as a service connection
+ on the NAS, not as an IP protocol identifier.
+
+ Either NAS-Port or NAS-Port-Id SHOULD be present in AA-Request (AAR)
+ commands if the NAS differentiates among its ports. NAS-Port-Id is
+ intended for use by NASes that cannot conveniently number their
+ ports.
+
+4.4. NAS-Port-Type AVP
+
+ The NAS-Port-Type AVP (AVP Code 61) is of type Enumerated and
+ contains the type of the port on which the NAS is authenticating the
+ user. This AVP SHOULD be present if the NAS uses the same NAS-Port
+ number ranges for different service types concurrently.
+
+ The supported values are defined in [RADIUSTypes]. The following
+ list is informational and subject to change by the IANA.
+
+ 0 Async
+ 1 Sync
+ 2 ISDN Sync
+ 3 ISDN Async V.120
+ 4 ISDN Async V.110
+ 5 Virtual
+ 6 PIAFS
+ 7 HDLC Clear Channel
+ 8 X.25
+ 9 X.75
+ 10 G.3 Fax
+ 11 SDSL - Symmetric DSL
+ 12 ADSL-CAP - Asymmetric DSL, Carrierless Amplitude Phase
+ Modulation
+ 13 ADSL-DMT - Asymmetric DSL, Discrete Multi-Tone
+ 14 IDSL - ISDN Digital Subscriber Line
+
+
+
+Calhoun, et al. Standards Track [Page 22]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ 15 Ethernet
+ 16 xDSL - Digital Subscriber Line of unknown type
+ 17 Cable
+ 18 Wireless - Other
+ 19 Wireless - IEEE 802.11
+ 20 Token-Ring [RAD802.1X]
+ 21 FDDI [RAD802.1X]
+ 22 Wireless - CDMA2000
+ 23 Wireless - UMTS
+ 24 Wireless - 1X-EV
+ 25 IAPP [IEEE 802.11f]
+
+4.5. Called-Station-Id AVP
+
+ The Called-Station-Id AVP (AVP Code 30) is of type UTF8String and
+ allows the NAS to send the ASCII string describing the layer 2
+ address the user contacted in the request. For dialup access, this
+ can be a phone number obtained by using Dialed Number Identification
+ (DNIS) or a similar technology. Note that this may be different from
+ the phone number the call comes in on. For use with IEEE 802 access,
+ the Called-Station-Id MAY contain a MAC address formatted as
+ described in [RAD802.1X]. It SHOULD only be present in
+ authentication and/or authorization requests.
+
+ If the Auth-Request-Type AVP is set to authorization-only and the
+ User-Name AVP is absent, the Diameter Server MAY perform
+ authorization based on this field. This can be used by a NAS to
+ request whether a call should be answered based on the DNIS.
+
+ The codification of this field's allowed usage range is outside the
+ scope of this specification.
+
+4.6. Calling-Station-Id AVP
+
+ The Calling-Station-Id AVP (AVP Code 31) is of type UTF8String and
+ allows the NAS to send the ASCII string describing the layer 2
+ address from which the user connected in the request. For dialup
+ access, this is the phone number the call came from, using Automatic
+ Number Identification (ANI) or a similar technology. For use with
+ IEEE 802 access, the Calling-Station-Id AVP MAY contain a MAC
+ address, formated as described in [RAD802.1X]. It SHOULD only be
+ present in authentication and/or authorization requests.
+
+ If the Auth-Request-Type AVP is set to authorization-only and the
+ User-Name AVP is absent, the Diameter Server MAY perform
+ authorization based on this field. This can be used by a NAS to
+ request whether a call should be answered based on the layer 2
+ address (ANI, MAC Address, etc.)
+
+
+
+Calhoun, et al. Standards Track [Page 23]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ The codification of this field's allowed usage range is outside the
+ scope of this specification.
+
+4.7. Connect-Info AVP
+
+ The Connect-Info AVP (AVP Code 77) is of type UTF8String and is sent
+ in the AA-Request message or ACR STOP message. When sent in the
+ Access-Request, it indicates the nature of the user's connection.
+ The connection speed SHOULD be included at the beginning of the first
+ Connect-Info AVP in the message. If the transmit and receive
+ connection speeds differ, both may be included in the first AVP with
+ the transmit speed listed first (the speed the NAS modem transmits
+ at), then a slash (/), then the receive speed, and then other
+ optional information.
+
+ For example: "28800 V42BIS/LAPM" or "52000/31200 V90"
+
+ More than one Connect-Info attribute may be present in an
+ Accounting-Request packet to accommodate expected efforts by the ITU
+ to have modems report more connection information in a standard
+ format that might exceed 252 octets.
+
+ If sent in the ACR STOP, this attribute may summarize statistics
+ relating to session quality. For example, in IEEE 802.11, the
+ Connect-Info attribute may contain information on the number of link
+ layer retransmissions. The exact format of this attribute is
+ implementation specific.
+
+4.8. Originating-Line-Info AVP
+
+ The Originating-Line-Info AVP (AVP Code 94) is of type OctetString
+ and is sent by the NAS system to convey information about the origin
+ of the call from an SS7 system.
+
+ The originating line information (OLI) element indicates the nature
+ and/or characteristics of the line from which a call originated
+ (e.g., pay phone, hotel, cellular). Telephone companies are starting
+ to offer OLI to their customers as an option over Primary Rate
+ Interface (PRI). Internet Service Providers (ISPs) can use OLI in
+ addition to Called-Station-Id and Calling-Station-Id attributes to
+ differentiate customer calls and to define different services.
+
+ The Value field contains two octets (00 - 99). ANSI T1.113 and
+ BELLCORE 394 can be used for additional information about these
+ values and their use. For more information on current assignment
+ values, see [ANITypes].
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 24]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ Value Description
+ ------------------------------------------------------------
+ 00 Plain Old Telephone Service (POTS)
+ 01 Multiparty Line (more than 2)
+ 02 ANI Failure
+ 03 ANI Observed
+ 04 ONI Observed
+ 05 ANI Failure Observed
+ 06 Station Level Rating
+ 07 Special Operator Handling Required
+ 08 InterLATA Restricted
+ 10 Test Call
+ 20 Automatic Identified Outward Dialing (AIOD)
+ 23 Coin or Non-Coin
+ 24 Toll Free Service (Non-Pay Origination)
+ 25 Toll Free Service (Pay Origination)
+ 27 Toll Free Service (Coin Control Origination)
+ 29 Prison/Inmate Service
+ 30-32 Intercept
+ 30 Intercept (Blank)
+ 31 Intercept (Trouble)
+ 32 Intercept (Regular)
+ 34 Telco Operator Handled Call
+ 40-49 Unrestricted Use
+ 52 Outward Wide Area Telecommunications Service (OUTWATS)
+ 60 Telecommunications Relay Service (TRS)(Unrestricted)
+ 61 Cellular/Wireless PCS (Type 1)
+ 62 Cellular/Wireless PCS (Type 2)
+ 63 Cellular/Wireless PCS (Roaming)
+ 66 TRS (Hotel)
+ 67 TRS (Restricted)
+ 70 Pay Station, No Coin Control
+ 93 Access for Private Virtual Network Service
+
+4.9. Reply-Message AVP
+
+ The Reply-Message AVP (AVP Code 18) is of type UTF8String and
+ contains text that MAY be displayed to the user. When used in an
+ AA-Answer message with a successful Result-Code AVP, it indicates
+ success. When found in an AAA message with a Result-Code other than
+ DIAMETER_SUCCESS, the AVP contains a failure message.
+
+ The Reply-Message AVP MAY indicate dialog text to prompt the user
+ before another AA-Request attempt. When used in an AA-Answer with a
+ Result-Code of DIAMETER_MULTI_ROUND_AUTH or in an Re-Auth-Request
+ message, it MAY contain a dialog text to prompt the user for a
+ response.
+
+
+
+
+Calhoun, et al. Standards Track [Page 25]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ Multiple Reply-Messages MAY be included, and if any are displayed,
+ they MUST be displayed in the same order as they appear in the
+ Diameter message.
+
+5. NAS Authentication AVPs
+
+ This section defines the AVPs necessary to carry the authentication
+ information in the Diameter protocol. The functionality defined here
+ provides a RADIUS-like AAA service over a more reliable and secure
+ transport, as defined in the base protocol [BASE].
+
+ The following table describes the AVPs; their AVP Code values, types,
+ and possible flag values, and whether the AVP MAY be encrypted.
+
+ +---------------------+
+ | AVP Flag rules |
+ |----+-----+----+-----|----+
+ AVP Section | | |SHLD| MUST| |
+ Attribute Name Code Defined Value Type |MUST| MAY | NOT| NOT|Encr|
+ -----------------------------------------|----+-----+----+-----|----|
+ User-Password 2 5.1 OctetString| M | P | | V | Y |
+ Password-Retry 75 5.2 Unsigned32 | M | P | | V | Y |
+ Prompt 76 5.3 Enumerated | M | P | | V | Y |
+ CHAP-Auth 402 5.4 Grouped | M | P | | V | Y |
+ CHAP-Algorithm 403 5.5 Enumerated | M | P | | V | Y |
+ CHAP-Ident 404 5.6 OctetString| M | P | | V | Y |
+ CHAP-Response 405 5.7 OctetString| M | P | | V | Y |
+ CHAP-Challenge 60 5.8 OctetString| M | P | | V | Y |
+ ARAP-Password 70 5.9 OctetString| M | P | | V | Y |
+ ARAP-Challenge- 84 5.10 OctetString| M | P | | V | Y |
+ Response | | | | | |
+ ARAP-Security 73 5.11 Unsigned32 | M | P | | V | Y |
+ ARAP-Security- 74 5.12 OctetString| M | P | | V | Y |
+ Data | | | | | |
+ -----------------------------------------|----+-----+----+-----|----|
+
+5.1. User-Password AVP
+
+ The User-Password AVP (AVP Code 2) is of type OctetString and
+ contains the password of the user to be authenticated, or the user's
+ input in a multi-round authentication exchange.
+
+ The User-Password AVP contains a user password or one-time password
+ and therefore represents sensitive information. As required in
+ [BASE], Diameter messages are encrypted by using IPsec or TLS.
+ Unless this AVP is used for one-time passwords, the User-Password AVP
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 26]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ SHOULD NOT be used in untrusted proxy environments without encrypting
+ it by using end-to-end security techniques, such as the proposed CMS
+ Security [DiamCMS].
+
+ The clear-text password (prior to encryption) MUST NOT be longer than
+ 128 bytes in length.
+
+5.2. Password-Retry AVP
+
+ The Password-Retry AVP (AVP Code 75) is of type Unsigned32 and MAY be
+ included in the AA-Answer if the Result-Code indicates an
+ authentication failure. The value of this AVP indicates how many
+ authentication attempts a user is permitted before being
+ disconnected. This AVP is primarily intended for use when the
+ Framed-Protocol AVP (see section 6.10.1) is set to ARAP.
+
+5.3. Prompt AVP
+
+ The Prompt AVP (AVP Code 76) is of type Enumerated and MAY be present
+ in the AA-Answer message. When present, it is used by the NAS to
+ determine whether the user's response, when entered, should be
+ echoed.
+
+ The supported values are listed in [RADIUSTypes]. The following list
+ is informational:
+
+ 0 No Echo
+ 1 Echo
+
+5.4. CHAP-Auth AVP
+
+ The CHAP-Auth AVP (AVP Code 402) is of type Grouped and contains the
+ information necessary to authenticate a user using the PPP
+ Challenge-Handshake Authentication Protocol (CHAP) [PPPCHAP]. If the
+ CHAP-Auth AVP is found in a message, the CHAP-Challenge AVP MUST be
+ present as well. The optional AVPs containing the CHAP response
+ depend upon the value of the CHAP-Algorithm AVP. The grouped AVP has
+ the following ABNF grammar:
+
+ CHAP-Auth ::= < AVP Header: 402 >
+ { CHAP-Algorithm }
+ { CHAP-Ident }
+ [ CHAP-Response ]
+ * [ AVP ]
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 27]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+5.5. CHAP-Algorithm AVP
+
+ The CHAP-Algorithm AVP (AVP Code 403) is of type Enumerated and
+ contains the algorithm identifier used in the computation of the CHAP
+ response [PPPCHAP]. The following values are currently supported:
+
+ CHAP with MD5 5
+ The CHAP response is computed by using the procedure described
+ in [PPPCHAP]. This algorithm requires that the CHAP-Response
+ AVP MUST be present in the CHAP-Auth AVP.
+
+5.6. CHAP-Ident AVP
+
+ The CHAP-Ident AVP (AVP Code 404) is of type OctetString and contains
+ the 1 octet CHAP Identifier used in the computation of the CHAP
+ response [PPPCHAP].
+
+5.7. CHAP-Response AVP
+
+ The CHAP-Response AVP (AVP Code 405) is of type OctetString and
+ contains the 16 octet authentication data provided by the user in
+ response to the CHAP challenge [PPPCHAP].
+
+5.8. CHAP-Challenge AVP
+
+ The CHAP-Challenge AVP (AVP Code 60) is of type OctetString and
+ contains the CHAP Challenge sent by the NAS to the CHAP peer
+ [PPPCHAP].
+
+5.9. ARAP-Password AVP
+
+ The ARAP-Password AVP (AVP Code 70) is of type OctetString and is
+ only present when the Framed-Protocol AVP (see section 6.10.1) is
+ included in the message and is set to ARAP. This AVP MUST NOT be
+ present if either the User-Password or the CHAP-Auth AVP is present.
+ See [RADIUSExt] for more information on the contents of this AVP.
+
+5.10. ARAP-Challenge-Response AVP
+
+ The ARAP-Challenge-Response AVP (AVP Code 84) is of type OctetString
+ and is only present when the Framed-Protocol AVP (see section 6.10.1)
+ is included in the message and is set to ARAP. This AVP contains an
+ 8 octet response to the dial-in client's challenge. The RADIUS
+ server calculates this value by taking the dial-in client's challenge
+ from the high-order 8 octets of the ARAP-Password AVP and performing
+ DES encryption on this value with the authenticating user's password
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 28]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ as the key. If the user's password is fewer than 8 octets in length,
+ the password is padded at the end with NULL octets to a length of 8
+ before it is used as a key.
+
+5.11. ARAP-Security AVP
+
+ The ARAP-Security AVP (AVP Code 73) is of type Unsigned32 and MAY be
+ present in the AA-Answer message if the Framed-Protocol AVP (see
+ section 6.10.1) is set to the value of ARAP, and the Result-Code AVP
+ is set to DIAMETER_MULTI_ROUND_AUTH. See [RADIUSExt] for more
+ information on the format of this AVP.
+
+5.12. ARAP-Security-Data AVP
+
+ The ARAP-Security AVP (AVP Code 74) is of type OctetString and MAY be
+ present in the AA-Request or AA-Answer message if the Framed-Protocol
+ AVP is set to the value of ARAP, and the Result-Code AVP is set to
+ DIAMETER_MULTI_ROUND_AUTH. This AVP contains the security module
+ challenge or response associated with the ARAP Security Module
+ specified in ARAP-Security.
+
+6. NAS Authorization AVPs
+
+ This section contains the authorization AVPs supported in the NAS
+ Application. The Service-Type AVP SHOULD be present in all messages,
+ and, based on its value, additional AVPs defined in this section and
+ in section 7 MAY be present.
+
+ Due to space constraints, the short-form IPFltrRule is used to
+ represent IPFilterRule, and QoSFltrRule is used for QoSFilterRule.
+
+ +---------------------+
+ | AVP Flag rules |
+ |----+-----+----+-----|----+
+ AVP Section | | |SHLD| MUST| |
+ Attribute Name Code Defined Value Type |MUST| MAY | NOT| NOT|Encr|
+ -----------------------------------------|----+-----+----+-----|----|
+ Service-Type 6 6.1 Enumerated | M | P | | V | Y |
+ Callback-Number 19 6.2 UTF8String | M | P | | V | Y |
+ Callback-Id 20 6.3 UTF8String | M | P | | V | Y |
+ Idle-Timeout 28 6.4 Unsigned32 | M | P | | V | Y |
+ Port-Limit 62 6.5 Unsigned32 | M | P | | V | Y |
+ NAS-Filter-Rule 400 6.6 IPFltrRule | M | P | | V | Y |
+ Filter-Id 11 6.7 UTF8String | M | P | | V | Y |
+ Configuration- 78 6.8 OctetString| M | | | P,V | |
+ Token | | | | | |
+ QoS-Filter-Rule 407 6.9 QoSFltrRule| | | | | |
+ Framed-Protocol 7 6.10.1 Enumerated | M | P | | V | Y |
+
+
+
+Calhoun, et al. Standards Track [Page 29]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ Framed-Routing 10 6.10.2 Enumerated | M | P | | V | Y |
+ Framed-MTU 12 6.10.3 Unsigned32 | M | P | | V | Y |
+ Framed- 13 6.10.4 Enumerated | M | P | | V | Y |
+ Compression | | | | | |
+ Framed-IP-Address 8 6.11.1 OctetString| M | P | | V | Y |
+ Framed-IP-Netmask 9 6.11.2 OctetString| M | P | | V | Y |
+ Framed-Route 22 6.11.3 UTF8String | M | P | | V | Y |
+ Framed-Pool 88 6.11.4 OctetString| M | P | | V | Y |
+ Framed- 96 6.11.5 Unsigned64 | M | P | | V | Y |
+ Interface-Id | | | | | |
+ Framed-IPv6- 97 6.11.6 OctetString| M | P | | V | Y |
+ Prefix | | | | | |
+ Framed-IPv6- 99 6.11.7 UTF8String | M | P | | V | Y |
+ Route | | | | | |
+ Framed-IPv6-Pool 100 6.11.8 OctetString| M | P | | V | Y |
+ Framed-IPX- 23 6.12.1 UTF8String | M | P | | V | Y |
+ Network | | | | | |
+ Framed-Appletalk- 37 6.13.1 Unsigned32 | M | P | | V | Y |
+ Link | | | | | |
+ Framed-Appletalk- 38 6.13.2 Unsigned32 | M | P | | V | Y |
+ Network | | | | | |
+ Framed-Appletalk- 39 6.13.3 OctetString| M | P | | V | Y |
+ Zone | | | | | |
+ ARAP-Features 71 6.14.1 OctetString| M | P | | V | Y |
+ ARAP-Zone-Access 72 6.14.2 Enumerated | M | P | | V | Y |
+ Login-IP-Host 14 6.15.1 OctetString| M | P | | V | Y |
+ Login-IPv6-Host 98 6.15.2 OctetString| M | P | | V | Y |
+ Login-Service 15 6.15.3 Enumerated | M | P | | V | Y |
+ Login-TCP-Port 16 6.16.1 Unsigned32 | M | P | | V | Y |
+ Login-LAT-Service 34 6.17.1 OctetString| M | P | | V | Y |
+ Login-LAT-Node 35 6.17.2 OctetString| M | P | | V | Y |
+ Login-LAT-Group 36 6.17.3 OctetString| M | P | | V | Y |
+ Login-LAT-Port 63 6.17.4 OctetString| M | P | | V | Y |
+ -----------------------------------------|----+-----+----+-----|----|
+
+6.1. Service-Type AVP
+
+ The Service-Type AVP (AVP Code 6) is of type Enumerated and contains
+ the type of service the user has requested or the type of service to
+ be provided. One such AVP MAY be present in an authentication and/or
+ authorization request or response. A NAS is not required to
+ implement all of these service types. It MUST treat unknown or
+ unsupported Service-Types received in a response as a failure and end
+ the session with a DIAMETER_INVALID_AVP_VALUE Result-Code.
+
+ When used in a request, the Service-Type AVP SHOULD be considered a
+ hint to the server that the NAS believes the user would prefer the
+ kind of service indicated. The server is not required to honor the
+
+
+
+Calhoun, et al. Standards Track [Page 30]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ hint. Furthermore, if the service specified by the server is
+ supported, but not compatible with the current mode of access, the
+ NAS MUST fail to start the session. The NAS MUST also generate the
+ appropriate error message(s).
+
+ The following values have been defined for the Service-Type AVP. The
+ complete list of defined values can be found in [RADIUS] and
+ [RADIUSTypes]. The following list is informational:
+
+ 1 Login
+ 2 Framed
+ 3 Callback Login
+ 4 Callback Framed
+ 5 Outbound
+ 6 Administrative
+ 7 NAS Prompt
+ 8 Authenticate Only
+ 9 Callback NAS Prompt
+ 10 Call Check
+ 11 Callback Administrative
+ 12 Voice
+ 13 Fax
+ 14 Modem Relay
+ 15 IAPP-Register [IEEE 802.11f]
+ 16 IAPP-AP-Check [IEEE 802.11f]
+ 17 Authorize Only [RADDynAuth]
+
+ The following values are further qualified:
+
+ Login 1
+ The user should be connected to a host. The message MAY
+ include additional AVPs defined in sections 6.16 or 6.17.
+
+ Framed 2
+ A Framed Protocol, such as PPP or SLIP, should be started for
+ the User. The message MAY include additional AVPs defined in
+ section 6.10, or section 7 for tunneling services.
+
+ Callback Login 3
+ The user should be disconnected and called back, then connected
+ to a host. The message MAY include additional AVPs defined in
+ this section.
+
+ Callback Framed 4
+ The user should be disconnected and called back, and then a
+ Framed Protocol, such as PPP or SLIP, should be started for the
+ User. The message MAY include additional AVPs defined in
+ section 6.10, or in section 7 for tunneling services.
+
+
+
+Calhoun, et al. Standards Track [Page 31]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+6.2. Callback-Number AVP
+
+ The Callback-Number AVP (AVP Code 19) is of type UTF8String and
+ contains a dialing string to be used for callback. It MAY be used in
+ an authentication and/or authorization request as a hint to the
+ server that a Callback service is desired, but the server is not
+ required to honor the hint in the corresponding response.
+
+ The codification of this field's allowed usage range is outside the
+ scope of this specification.
+
+6.3. Callback-Id AVP
+
+ The Callback-Id AVP (AVP Code 20) is of type UTF8String and contains
+ the name of a place to be called, to be interpreted by the NAS. This
+ AVP MAY be present in an authentication and/or authorization
+ response.
+
+ This AVP is not roaming-friendly as it assumes that the Callback-Id
+ is configured on the NAS. Using the Callback-Number AVP therefore
+ preferable.
+
+6.4. Idle-Timeout AVP
+
+ The Idle-Timeout AVP (AVP Code 28) is of type Unsigned32 and sets the
+ maximum number of consecutive seconds of idle connection allowable to
+ the user before termination of the session or before a prompt is
+ issued. The default is none, or system specific.
+
+6.5. Port-Limit AVP
+
+ The Port-Limit AVP (AVP Code 62) is of type Unsigned32 and sets the
+ maximum number of ports the NAS provides to the user. It MAY be used
+ in an authentication and/or authorization request as a hint to the
+ server that multilink PPP [PPPMP] service is desired, but the server
+ is not required to honor the hint in the corresponding response.
+
+6.6. NAS-Filter-Rule AVP
+
+ The NAS-Filter-Rule AVP (AVP Code 400) is of type IPFilterRule and
+ provides filter rules that need to be configured on the NAS for the
+ user. One or more of these AVPs MAY be present in an authorization
+ response.
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 32]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+6.7. Filter-Id AVP
+
+ The Filter-Id AVP (AVP Code 11) is of type UTF8String and contains
+ the name of the filter list for this user. Zero or more Filter-Id
+ AVPs MAY be sent in an authorization answer.
+
+ Identifying a filter list by name allows the filter to be used on
+ different NASes without regard to filter-list implementation details.
+ However, this AVP is not roaming friendly, as filter naming differs
+ from one service provider to another.
+
+ In non-RADIUS environments, it is RECOMMENDED that the NAS-Filter-
+ Rule AVP be used instead.
+
+6.8. Configuration-Token AVP
+
+ The Configuration-Token AVP (AVP Code 78) is of type OctetString and
+ is sent by a Diameter Server to a Diameter Proxy Agent or Translation
+ Agent in an AA-Answer command to indicate a type of user profile to
+ be used. It should not be sent to a Diameter Client (NAS).
+
+ The format of the Data field of this AVP is site specific.
+
+6.9. QoS-Filter-Rule AVP
+
+ The QoS-Filter-Rule AVP (AVP Code 407) is of type QoSFilterRule and
+ provides QoS filter rules that need to be configured on the NAS for
+ the user. One or more such AVPs MAY be present in an authorization
+ response.
+
+ Note: Due to an editorial mistake in [BASE], only the AVP format is
+ discussed. The complete QoSFilterRule definition was not included.
+ It is reprinted here for clarification.
+
+ QoSFilterRule
+
+ The QosFilterRule format is derived from the OctetString AVP Base
+ Format. It uses the ASCII charset. Packets may be marked or
+ metered based on the following information:
+
+ Direction (in or out)
+ Source and destination IP address (possibly masked)
+ Protocol
+ Source and destination port (lists or ranges)
+ DSCP values (no mask or range)
+
+ Rules for the appropriate direction are evaluated in order; the
+ first matched rule terminates the evaluation. Each packet is
+
+
+
+Calhoun, et al. Standards Track [Page 33]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ evaluated once. If no rule matches, the packet is treated as best
+ effort. An access device unable to interpret or apply a QoS rule
+ SHOULD NOT terminate the session.
+
+ QoSFilterRule filters MUST follow the following format:
+
+ action dir proto from src to dst [options]
+
+ tag - Mark packet with a specific DSCP
+ [DIFFSERV]. The DSCP option MUST be
+ included.
+ meter - Meter traffic. The metering options
+ MUST be included.
+
+ dir The format is as described under IPFilterRule.
+
+ proto The format is as described under IPFilterRule.
+
+ src and dst The format is as described under IPFilterRule.
+
+ options:
+
+ DSCP <color>
+ Color values as defined in [DIFFSERV]. Exact
+ matching of DSCP values is required (no masks or
+ ranges).
+
+ metering <rate> <color_under> <color_over>
+ The metering option provides Assured Forwarding,
+ as defined in [DIFFSERVAF], and MUST be present
+ if the action is set to meter. The rate option is
+ the throughput, in bits per second, used
+ by the access device to mark packets. Traffic
+ over the rate is marked with the color_over
+ codepoint, and traffic under the rate is marked
+ with the color_under codepoint. The color_under
+ and color_over options contain the drop
+ preferences and MUST conform to the recommended
+ codepoint keywords described in [DIFFSERVAF]
+ (e.g., AF13).
+
+ The metering option also supports the strict
+ limit on traffic required by Expedited
+ Forwarding, as defined in [DIFFSERVEF]. The
+ color_over option may contain the keyword "drop"
+ to prevent forwarding of traffic that exceeds the
+ rate parameter.
+
+
+
+
+Calhoun, et al. Standards Track [Page 34]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ The rule syntax is a modified subset of ipfw(8) from FreeBSD,
+ and the ipfw.c code may provide a useful base for
+ implementations.
+
+6.10. Framed Access Authorization AVPs
+
+ This section lists the authorization AVPs necessary to
+ support framed access, such as PPP and SLIP. AVPs defined in this
+ section MAY be present in a message if the Service-Type AVP was set
+ to "Framed" or "Callback Framed".
+
+6.10.1. Framed-Protocol AVP
+
+ The Framed-Protocol AVP (AVP Code 7) is of type Enumerated and
+ contains the framing to be used for framed access. This AVP MAY be
+ present in both requests and responses. The supported values are
+ listed in [RADIUSTypes]. The following list is informational:
+
+ 1 PPP
+ 2 SLIP
+ 3 AppleTalk Remote Access Protocol (ARAP)
+ 4 Gandalf proprietary SingleLink/MultiLink protocol
+ 5 Xylogics proprietary IPX/SLIP
+ 6 X.75 Synchronous
+
+6.10.2. Framed-Routing AVP
+
+ The Framed-Routing AVP (AVP Code 10) is of type Enumerated and
+ contains the routing method for the user when the user is a router to
+ a network. This AVP SHOULD only be present in authorization
+ responses. The supported values are listed in [RADIUSTypes]. The
+ following list is informational:
+
+ 0 None
+ 1 Send routing packets
+ 2 Listen for routing packets
+ 3 Send and Listen
+
+6.10.3. Framed-MTU AVP
+
+ The Framed-MTU AVP (AVP Code 12) is of type Unsigned32 and contains
+ the Maximum Transmission Unit to be configured for the user, when it
+ is not negotiated by some other means (such as PPP). This AVP SHOULD
+ only be present in authorization responses. The MTU value MUST be in
+ the range from 64 to 65535.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 35]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+6.10.4. Framed-Compression AVP
+
+ The Framed-Compression AVP (AVP Code 13) is of type Enumerated and
+ contains the compression protocol to be used for the link. It MAY be
+ used in an authorization request as a hint to the server that a
+ specific compression type is desired, but the server is not required
+ to honor the hint in the corresponding response.
+
+ More than one compression protocol AVP MAY be sent. The NAS is
+ responsible for applying the proper compression protocol to the
+ appropriate link traffic.
+
+ The supported values are listed in [RADIUSTypes]. The following list
+ is informational:
+
+ 0 None
+ 1 VJ TCP/IP header compression
+ 2 IPX header compression
+ 3 Stac-LZS compression
+
+6.11. IP Access Authorization AVPs
+
+ The AVPs defined in this section are used when the user requests, or
+ is being granted, access service to IP.
+
+6.11.1. Framed-IP-Address AVP
+
+ The Framed-IP-Address AVP (AVP Code 8) [RADIUS] is of type
+ OctetString and contains an IPv4 address of the type specified in the
+ attribute value to be configured for the user. It MAY be used in an
+ authorization request as a hint to the server that a specific address
+ is desired, but the server is not required to honor the hint in the
+ corresponding response.
+
+ Two values have special significance: 0xFFFFFFFF and 0xFFFFFFFE. The
+ value 0xFFFFFFFF indicates that the NAS should allow the user to
+ select an address (i.e., negotiated). The value 0xFFFFFFFE indicates
+ that the NAS should select an address for the user (e.g., assigned
+ from a pool of addresses kept by the NAS).
+
+6.11.2. Framed-IP-Netmask AVP
+
+ The Framed-IP-Netmask AVP (AVP Code 9) is of type OctetString and
+ contains the four octets of the IPv4 netmask to be configured for the
+ user when the user is a router to a network. It MAY be used in an
+ authorization request as a hint to the server that a specific netmask
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 36]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ is desired, but the server is not required to honor the hint in the
+ corresponding response. This AVP MUST be present in a response if
+ the request included this AVP with a value of 0xFFFFFFFF.
+
+6.11.3. Framed-Route AVP
+
+ The Framed-Route AVP (AVP Code 22) is of type UTF8String and contains
+ the ASCII routing information to be configured for the user on the
+ NAS. Zero or more of these AVPs MAY be present in an authorization
+ response.
+
+ The string MUST contain a destination prefix in dotted quad form
+ optionally followed by a slash and a decimal length specifier stating
+ how many high-order bits of the prefix should be used. This is
+ followed by a space, a gateway address in dotted quad form, a space,
+ and one or more metrics separated by spaces; for example,
+
+ "192.168.1.0/24 192.168.1.1 1".
+
+ The length specifier may be omitted, in which case it should default
+ to 8 bits for class A prefixes, to 16 bits for class B prefixes, and
+ to 24 bits for class C prefixes; for example,
+
+ "192.168.1.0 192.168.1.1 1".
+
+ Whenever the gateway address is specified as "0.0.0.0" the IP address
+ of the user SHOULD be used as the gateway address.
+
+6.11.4. Framed-Pool AVP
+
+ The Framed-Pool AVP (AVP Code 88) is of type OctetString and contains
+ the name of an assigned address pool that SHOULD be used to assign an
+ address for the user. If a NAS does not support multiple address
+ pools, the NAS SHOULD ignore this AVP. Address pools are usually
+ used for IP addresses but can be used for other protocols if the NAS
+ supports pools for those protocols.
+
+ Although specified as type OctetString for compatibility with RADIUS
+ [RADIUSExt], the encoding of the Data field SHOULD also conform to
+ the rules for the UTF8String Data Format.
+
+6.11.5. Framed-Interface-Id AVP
+
+ The Framed-Interface-Id AVP (AVP Code 96) is of type Unsigned64 and
+ contains the IPv6 interface identifier to be configured for the user.
+ It MAY be used in authorization requests as a hint to the server that
+ a specific interface id is desired, but the server is not required to
+ honor the hint in the corresponding response.
+
+
+
+Calhoun, et al. Standards Track [Page 37]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+6.11.6. Framed-IPv6-Prefix AVP
+
+ The Framed-IPv6-Prefix AVP (AVP Code 97) is of type OctetString and
+ contains the IPv6 prefix to be configured for the user. One or more
+ AVPs MAY be used in authorization requests as a hint to the server
+ that specific IPv6 prefixes are desired, but the server is not
+ required to honor the hint in the corresponding response.
+
+6.11.7. Framed-IPv6-Route AVP
+
+ The Framed-IPv6-Route AVP (AVP Code 99) is of type UTF8String and
+ contains the ASCII routing information to be configured for the user
+ on the NAS. Zero or more of these AVPs MAY be present in an
+ authorization response.
+
+ The string MUST contain an IPv6 address prefix followed by a slash
+ and a decimal length specifier stating how many high order bits of
+ the prefix should be used. This is followed by a space, a gateway
+ address in hexadecimal notation, a space, and one or more metrics
+ separated by spaces; for example,
+
+ "2000:0:0:106::/64 2000::106:a00:20ff:fe99:a998 1".
+
+ Whenever the gateway address is the IPv6 unspecified address, the IP
+ address of the user SHOULD be used as the gateway address, such as
+ in:
+
+ "2000:0:0:106::/64 :: 1".
+
+6.11.8. Framed-IPv6-Pool AVP
+
+ The Framed-IPv6-Pool AVP (AVP Code 100) is of type OctetString and
+ contains the name of an assigned pool that SHOULD be used to assign
+ an IPv6 prefix for the user. If the access device does not support
+ multiple prefix pools, it MUST ignore this AVP.
+
+ Although specified as type OctetString for compatibility with RADIUS
+ [RADIUSIPv6], the encoding of the Data field SHOULD also conform to
+ the rules for the UTF8String Data Format.
+
+6.12. IPX Access
+
+ The AVPs defined in this section are used when the user requests, or
+ is being granted, access to an IPX network service.
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 38]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+6.12.1. Framed-IPX-Network AVP
+
+ The Framed-IPX-Network AVP (AVP Code 23) is of type Unsigned32 and
+ contains the IPX Network number to be configured for the user. It
+ MAY be used in an authorization request as a hint to the server that
+ a specific address is desired, but the server is not required to
+ honor the hint in the corresponding response.
+
+ Two addresses have special significance: 0xFFFFFFFF and 0xFFFFFFFE.
+ The value 0xFFFFFFFF indicates that the NAS should allow the user to
+ select an address (i.e., Negotiated). The value 0xFFFFFFFE indicates
+ that the NAS should select an address for the user (e.g., assign it
+ from a pool of one or more IPX networks kept by the NAS).
+
+6.13. AppleTalk Network Access
+
+ The AVPs defined in this section are used when the user requests, or
+ is being granted, access to an AppleTalk network [AppleTalk].
+
+6.13.1. Framed-AppleTalk-Link AVP
+
+ The Framed-AppleTalk-Link AVP (AVP Code 37) is of type Unsigned32 and
+ contains the AppleTalk network number that should be used for the
+ serial link to the user, which is another AppleTalk router. This AVP
+ MUST only be present in an authorization response and is never used
+ when the user is not another router.
+
+ Despite the size of the field, values range from 0 to 65,535. The
+ special value of 0 indicates an unnumbered serial link. A value of 1
+ to 65,535 means that the serial line between the NAS and the user
+ should be assigned that value as an AppleTalk network number.
+
+6.13.2. Framed-AppleTalk-Network AVP
+
+ The Framed-AppleTalk-Network AVP (AVP Code 38) is of type Unsigned32
+ and contains the AppleTalk Network number that the NAS should probe
+ to allocate an AppleTalk node for the user. This AVP MUST only be
+ present in an authorization response and is never used when the user
+ is not another router. Multiple instances of this AVP indicate that
+ the NAS may probe, using any of the network numbers specified.
+
+ Despite the size of the field, values range from 0 to 65,535. The
+ special value 0 indicates that the NAS should assign a network for
+ the user, using its default cable range. A value between 1 and
+ 65,535 (inclusive) indicates to the AppleTalk Network that the NAS
+ should probe to find an address for the user.
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 39]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+6.13.3. Framed-AppleTalk-Zone AVP
+
+ The Framed-AppleTalk-Zone AVP (AVP Code 39) is of type OctetString
+ and contains the AppleTalk Default Zone to be used for this user.
+ This AVP MUST only be present in an authorization response. Multiple
+ instances of this AVP in the same message are not allowed.
+
+ The codification of this field's allowed range is outside the scope
+ of this specification.
+
+6.14. AppleTalk Remote Access
+
+ The AVPs defined in this section are used when the user requests, or
+ is being granted, access to the AppleTalk network via the AppleTalk
+ Remote Access Protocol [ARAP]. They are only present if the Framed-
+ Protocol AVP (see section 6.10.1) is set to ARAP. Section 2.2 of RFC
+ 2869 [RADIUSExt] describes the operational use of these attributes.
+
+6.14.1. ARAP-Features AVP
+
+ The ARAP-Features AVP (AVP Code 71) is of type OctetString and MAY be
+ present in the AA-Accept message if the Framed-Protocol AVP is set to
+ the value of ARAP. See [RADIUSExt] for more information about the
+ format of this AVP.
+
+6.14.2. ARAP-Zone-Access AVP
+
+ The ARAP-Zone-Access AVP (AVP Code 72) is of type Enumerated and MAY
+ be present in the AA-Accept message if the Framed-Protocol AVP is set
+ to the value of ARAP.
+
+ The supported values are listed in [RADIUSTypes] and defined in
+ [RADIUSExt].
+
+6.15. Non-Framed Access Authorization AVPs
+
+ This section contains the authorization AVPs that are needed to
+ support terminal server functionality. AVPs defined in this section
+ MAY be present in a message if the Service-Type AVP was set to
+ "Login" or "Callback Login".
+
+6.15.1. Login-IP-Host AVP
+
+ The Login-IP-Host AVP (AVP Code 14) [RADIUS] is of type OctetString
+ and contains the IPv4 address of a host with which to connect the
+ user when the Login-Service AVP is included. It MAY be used in an
+ AA-Request command as a hint to the Diameter Server that a specific
+
+
+
+
+Calhoun, et al. Standards Track [Page 40]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ host is desired, but the Diameter Server is not required to honor the
+ hint in the AA-Answer.
+
+ Two addresses have special significance: all ones and 0. The value
+ of all ones indicates that the NAS SHOULD allow the user to select an
+ address. The value 0 indicates that the NAS SHOULD select a host to
+ connect the user to.
+
+6.15.2. Login-IPv6-Host AVP
+
+ The Login-IPv6-Host AVP (AVP Code 98) [RADIUSIPv6] is of type
+ OctetString and contains the IPv6 address of a host with which to
+ connect the user when the Login-Service AVP is included. It MAY be
+ used in an AA-Request command as a hint to the Diameter Server that a
+ specific host is desired, but the Diameter Server is not required to
+ honor the hint in the AA-Answer.
+
+ Two addresses have special significance:
+
+ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF and 0. The value
+ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF indicates that the NAS SHOULD
+ allow the user to select an address. The value 0 indicates that the
+ NAS SHOULD select a host to connect the user to.
+
+6.15.3. Login-Service AVP
+
+ The Login-Service AVP (AVP Code 15) is of type Enumerated and
+ contains the service that should be used to connect the user to the
+ login host. This AVP SHOULD only be present in authorization
+ responses.
+
+ The supported values are listed in [RADIUSTypes]. The following list
+ is informational:
+
+ 0 Telnet
+ 1 Rlogin
+ 2 TCP Clear
+ 3 PortMaster (proprietary)
+ 4 LAT
+ 5 X25-PAD
+ 6 X25-T3POS
+ 8 TCP Clear Quiet (suppresses any NAS-generated connect
+ string)
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 41]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+6.16. TCP Services
+
+ The AVPs described in this section MAY be present if the Login-
+ Service AVP is set to Telnet, Rlogin, TCP Clear, or TCP Clear Quiet.
+
+6.16.1. Login-TCP-Port AVP
+
+ The Login-TCP-Port AVP (AVP Code 16) is of type Unsigned32 and
+ contains the TCP port with which the user is to be connected when the
+ Login-Service AVP is also present. This AVP SHOULD only be present
+ in authorization responses. The value MUST NOT be greater than
+ 65,535.
+
+6.17. LAT Services
+
+ The AVPs described in this section MAY be present if the Login-
+ Service AVP is set to LAT [LAT].
+
+6.17.1. Login-LAT-Service AVP
+
+ The Login-LAT-Service AVP (AVP Code 34) is of type OctetString and
+ contains the system with which the user is to be connected by LAT.
+ It MAY be used in an authorization request as a hint to the server
+ that a specific service is desired, but the server is not required to
+ honor the hint in the corresponding response. This AVP MUST only be
+ present in the response if the Login-Service AVP states that LAT is
+ desired.
+
+ Administrators use this service attribute when dealing with clustered
+ systems, such as a VAX or Alpha cluster. In these environments,
+ several different time-sharing hosts share the same resources (disks,
+ printers, etc.), and administrators often configure each host to
+ offer access (service) to each of the shared resources. In this
+ case, each host in the cluster advertises its services through LAT
+ broadcasts.
+
+ Sophisticated users often know which service providers (machines) are
+ faster and tend to use a node name when initiating a LAT connection.
+ Some administrators want particular users to use certain machines as
+ a primitive form of load balancing (although LAT knows how to do load
+ balancing itself).
+
+ The String field contains the identity of the LAT service to use.
+ The LAT Architecture allows this string to contain $ (dollar), -
+ (hyphen), . (period), _ (underscore), numerics, upper- and lowercase
+ alphabetics, and the ISO Latin-1 character set extension [ISOLatin].
+ All LAT string comparisons are case insensitive.
+
+
+
+
+Calhoun, et al. Standards Track [Page 42]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+6.17.2. Login-LAT-Node AVP
+
+ The Login-LAT-Node AVP (AVP Code 35) is of type OctetString and
+ contains the Node with which the user is to be automatically
+ connected by LAT. It MAY be used in an authorization request as a
+ hint to the server that a specific LAT node is desired, but the
+ server is not required to honor the hint in the corresponding
+ response. This AVP MUST only be present in a response if the Login-
+ Service-Type AVP is set to LAT.
+
+ The String field contains the identity of the LAT service to use.
+ The LAT Architecture allows this string to contain $ (dollar), -
+ (hyphen), . (period), _ (underscore), numerics, upper- and lowercase
+ alphabetics, and the ISO Latin-1 character set extension [ISOLatin].
+ All LAT string comparisons are case insensitive.
+
+6.17.3. Login-LAT-Group AVP
+
+ The Login-LAT-Group AVP (AVP Code 36) is of type OctetString and
+ contains a string identifying the LAT group codes this user is
+ authorized to use. It MAY be used in an authorization request as a
+ hint to the server that a specific group is desired, but the server
+ is not required to honor the hint in the corresponding response.
+ This AVP MUST only be present in a response if the Login-Service-Type
+ AVP is set to LAT.
+
+ LAT supports 256 different group codes, which LAT uses as a form of
+ access rights. LAT encodes the group codes as a 256-bit bitmap.
+
+ Administrators can assign one or more of the group code bits at the
+ LAT service provider; it will only accept LAT connections that have
+ these group codes set in the bitmap. The administrators assign a
+ bitmap of authorized group codes to each user. LAT gets these from
+ the operating system and uses them in its requests to the service
+ providers.
+
+ The codification of the range of allowed usage of this field is
+ outside the scope of this specification.
+
+6.17.4. Login-LAT-Port AVP
+
+ The Login-LAT-Port AVP (AVP Code 63) is of type OctetString and
+ contains the Port with which the user is to be connected by LAT. It
+ MAY be used in an authorization request as a hint to the server that
+ a specific port is desired, but the server is not required to honor
+ the hint in the corresponding response. This AVP MUST only be
+ present in a response if the Login-Service-Type AVP is set to LAT.
+
+
+
+
+Calhoun, et al. Standards Track [Page 43]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ The String field contains the identity of the LAT service to use.
+ The LAT Architecture allows this string to contain $ (dollar), -
+ (hyphen), . (period), _ (underscore), numerics, upper- and lower-case
+ alphabetics, and the ISO Latin-1 character set extension [ISOLatin].
+ All LAT string comparisons are case insensitive.
+
+7. NAS Tunneling
+
+ Some NASes support compulsory tunnel services in which the incoming
+ connection data is conveyed by an encapsulation method to a gateway
+ elsewhere in the network. This is typically transparent to the
+ service user, and the tunnel characteristics may be described by the
+ remote AAA server, based on the user's authorization information.
+ Several tunnel characteristics may be returned, and the NAS
+ implementation may choose one [RADTunnels], [RADTunlAcct].
+
+ +---------------------+
+ | AVP Flag rules |
+ |----+-----+----+-----|----+
+ AVP Section | | |SHLD| MUST| |
+ Attribute Name Code Defined Value Type |MUST| MAY | NOT| NOT |Encr|
+ -----------------------------------------|----+-----+----+-----|----|
+ Tunneling 401 7.1 Grouped | M | P | | V | N |
+ Tunnel-Type 64 7.2 Enumerated | M | P | | V | Y |
+ Tunnel-Medium- 65 7.3 Enumerated | M | P | | V | Y |
+ Type | | | | | |
+ Tunnel-Client- 66 7.4 UTF8String | M | P | | V | Y |
+ Endpoint | | | | | |
+ Tunnel-Server- 67 7.5 UTF8String | M | P | | V | Y |
+ Endpoint | | | | | |
+ Tunnel-Password 69 7.6 OctetString| M | P | | V | Y |
+ Tunnel-Private- 81 7.7 OctetString| M | P | | V | Y |
+ Group-Id | | | | | |
+ Tunnel- 82 7.8 OctetString| M | P | | V | Y |
+ Assignment-Id | | | | | |
+ Tunnel-Preference 83 7.9 Unsigned32 | M | P | | V | Y |
+ Tunnel-Client- 90 7.10 UTF8String | M | P | | V | Y |
+ Auth-Id | | | | | |
+ Tunnel-Server- 91 7.11 UTF8String | M | P | | V | Y |
+ Auth-Id | | | | | |
+ -----------------------------------------|----+-----+----+-----|----|
+
+7.1. Tunneling AVP
+
+ The Tunneling AVP (AVP Code 401) is of type Grouped and contains the
+ following AVPs, used to describe a compulsory tunnel service:
+ [RADTunnels], [RADTunlAcct]. Its data field has the following ABNF
+ grammar:
+
+
+
+Calhoun, et al. Standards Track [Page 44]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ Tunneling ::= < AVP Header: 401 >
+ { Tunnel-Type }
+ { Tunnel-Medium-Type }
+ { Tunnel-Client-Endpoint }
+ { Tunnel-Server-Endpoint }
+ [ Tunnel-Preference ]
+ [ Tunnel-Client-Auth-Id ]
+ [ Tunnel-Server-Auth-Id ]
+ [ Tunnel-Assignment-Id ]
+ [ Tunnel-Password ]
+ [ Tunnel-Private-Group-Id ]
+
+7.2. Tunnel-Type AVP
+
+ The Tunnel-Type AVP (AVP Code 64) is of type Enumerated and contains
+ the tunneling protocol(s) to be used (in the case of a tunnel
+ initiator) or in use (in the case of a tunnel terminator). It MAY be
+ used in an authorization request as a hint to the server that a
+ specific tunnel type is desired, but the server is not required to
+ honor the hint in the corresponding response.
+
+ The Tunnel-Type AVP SHOULD also be included in Accounting-Request
+ messages.
+
+ A tunnel initiator is not required to implement any of these tunnel
+ types. If a tunnel initiator receives a response that contains only
+ unknown or unsupported Tunnel-Types, the tunnel initiator MUST behave
+ as though a response were received with the Result-Code indicating a
+ failure.
+
+ The supported values are listed in [RADIUSTypes]. The following list
+ is informational:
+
+ 1 Point-to-Point Tunneling Protocol (PPTP)
+ 2 Layer Two Forwarding (L2F)
+ 3 Layer Two Tunneling Protocol (L2TP)
+ 4 Ascend Tunnel Management Protocol (ATMP)
+ 5 Virtual Tunneling Protocol (VTP)
+ 6 IP Authentication Header in the Tunnel-mode (AH)
+ 7 IP-in-IP Encapsulation (IP-IP)
+ 8 Minimal IP-in-IP Encapsulation (MIN-IP-IP)
+ 9 IP Encapsulating Security Payload in the Tunnel-mode (ESP)
+ 10 Generic Route Encapsulation (GRE)
+ 11 Bay Dial Virtual Services (DVS)
+ 12 IP-in-IP Tunneling
+ 13 Virtual LANs (VLAN)
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 45]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+7.3. Tunnel-Medium-Type AVP
+
+ The Tunnel-Medium-Type AVP (AVP Code 65) is of type Enumerated and
+ contains the transport medium to use when creating a tunnel for
+ protocols (such as L2TP) that can operate over multiple transports.
+ It MAY be used in an authorization request as a hint to the server
+ that a specific medium is desired, but the server is not required to
+ honor the hint in the corresponding response.
+
+ The supported values are listed in [RADIUSTypes]. The following list
+ is informational:
+
+ 1 IPv4 (IP version 4)
+ 2 IPv6 (IP version 6)
+ 3 NSAP
+ 4 HDLC (8-bit multidrop)
+ 5 BBN 1822
+ 6 802 (includes all 802 media plus Ethernet "canonical
+ format")
+ 7 E.163 (POTS)
+ 8 E.164 (SMDS, Frame Relay, ATM)
+ 9 F.69 (Telex)
+ 10 X.121 (X.25, Frame Relay)
+ 11 IPX
+ 12 Appletalk
+ 13 Decnet IV
+ 14 Banyan Vines
+ 15 E.164 with NSAP format subaddress
+
+7.4. Tunnel-Client-Endpoint AVP
+
+ The Tunnel-Client-Endpoint AVP (AVP Code 66) is of type UTF8String
+ and contains the address of the initiator end of the tunnel. It MAY
+ be used in an authorization request as a hint to the server that a
+ specific endpoint is desired, but the server is not required to honor
+ the hint in the corresponding response.
+
+ This AVP SHOULD be included in the corresponding Accounting-Request
+ messages, in which case it indicates the address from which the
+ tunnel was initiated. This AVP, along with the Tunnel-Server-
+ Endpoint and Session-Id AVP [BASE], MAY be used to provide a globally
+ unique means to identify a tunnel for accounting and auditing
+ purposes.
+
+ If Tunnel-Medium-Type is IPv4 (1), then this string is either the
+ fully qualified domain name (FQDN) of the tunnel client machine, or a
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 46]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ "dotted-decimal" IP address. Implementations MUST support the
+ dotted-decimal format and SHOULD support the FQDN format for IP
+ addresses.
+
+ If Tunnel-Medium-Type is IPv6 (2), then this string is either the
+ FQDN of the tunnel client machine, or a text representation of the
+ address in either the preferred or alternate form [IPv6Addr].
+ Conforming implementations MUST support the preferred form and SHOULD
+ support both the alternate text form and the FQDN format for IPv6
+ addresses.
+
+ If Tunnel-Medium-Type is neither IPv4 nor IPv6, then this string is a
+ tag referring to configuration data local to the Diameter client that
+ describes the interface or medium-specific client address to use.
+
+7.5. Tunnel-Server-Endpoint AVP
+
+ The Tunnel-Server-Endpoint AVP (AVP Code 67) is of type UTF8String
+ and contains the address of the server end of the tunnel. It MAY be
+ used in an authorization request as a hint to the server that a
+ specific endpoint is desired, but the server is not required to honor
+ the hint in the corresponding response.
+
+ This AVP SHOULD be included in the corresponding Accounting-Request
+ messages, in which case it indicates the address from which the
+ tunnel was initiated. This AVP, along with the Tunnel-Client-
+ Endpoint and Session-Id AVP [BASE], MAY be used to provide a globally
+ unique means to identify a tunnel for accounting and auditing
+ purposes.
+
+ If Tunnel-Medium-Type is IPv4 (1), then this string is either the
+ fully qualified domain name (FQDN) of the tunnel server machine, or a
+ "dotted-decimal" IP address. Implementations MUST support the
+ dotted-decimal format and SHOULD support the FQDN format for IP
+ addresses.
+
+ If Tunnel-Medium-Type is IPv6 (2), then this string is either the
+ FQDN of the tunnel server machine, or a text representation of the
+ address in either the preferred or alternate form [IPv6Addr].
+ Implementations MUST support the preferred form and SHOULD support
+ both the alternate text form and the FQDN format for IPv6 addresses.
+
+ If Tunnel-Medium-Type is not IPv4 or IPv6, this string is a tag
+ referring to configuration data local to the Diameter client that
+ describes the interface or medium-specific server address to use.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 47]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+7.6. Tunnel-Password AVP
+
+ The Tunnel-Password AVP (AVP Code 69) is of type OctetString and may
+ contain a password to be used to authenticate to a remote server.
+ The Tunnel-Password AVP contains sensitive information. This value
+ is not protected in the same manner as RADIUS [RADTunnels].
+
+ As required in [BASE], Diameter messages are encrypted by using IPsec
+ or TLS. The Tunnel-Password AVP SHOULD NOT be used in untrusted
+ proxy environments without encrypting it by using end-to-end security
+ techniques, such as CMS Security [DiamCMS].
+
+7.7. Tunnel-Private-Group-Id AVP
+
+ The Tunnel-Private-Group-Id AVP (AVP Code 81) is of type OctetString
+ and contains the group Id for a particular tunneled session. The
+ Tunnel-Private-Group-Id AVP MAY be included in an authorization
+ request if the tunnel initiator can predetermine the group resulting
+ from a particular connection. It SHOULD be included in the
+ authorization response if this tunnel session is to be treated as
+ belonging to a particular private group. Private groups may be used
+ to associate a tunneled session with a particular group of users.
+ For example, it MAY be used to facilitate routing of unregistered IP
+ addresses through a particular interface. This AVP SHOULD be
+ included in the Accounting-Request messages that pertain to the
+ tunneled session.
+
+7.8. Tunnel-Assignment-Id AVP
+
+ The Tunnel-Assignment-Id AVP (AVP Code 82) is of type OctetString and
+ is used to indicate to the tunnel initiator the particular tunnel to
+ which a session is to be assigned. Some tunneling protocols, such as
+ [PPTP] and [L2TP], allow for sessions between the same two tunnel
+ endpoints to be multiplexed over the same tunnel and also for a given
+ session to use its own dedicated tunnel. This attribute provides a
+ mechanism for Diameter to inform the tunnel initiator (e.g., PAC,
+ LAC) whether to assign the session to a multiplexed tunnel or to a
+ separate tunnel. Furthermore, it allows for sessions sharing
+ multiplexed tunnels to be assigned to different multiplexed tunnels.
+
+ A particular tunneling implementation may assign differing
+ characteristics to particular tunnels. For example, different
+ tunnels may be assigned different QoS parameters. Such tunnels may
+ be used to carry either individual or multiple sessions. The
+ Tunnel-Assignment-Id attribute thus allows the Diameter server to
+ indicate that a particular session is to be assigned to a tunnel
+ providing an appropriate level of service. It is expected that any
+ QoS-related Diameter tunneling attributes defined in the future
+
+
+
+Calhoun, et al. Standards Track [Page 48]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ accompanying this one will be associated by the tunnel initiator with
+ the Id given by this attribute. In the meantime, any semantic given
+ to a particular Id string is a matter left to local configuration in
+ the tunnel initiator.
+
+ The Tunnel-Assignment-Id AVP is of significance only to Diameter and
+ the tunnel initiator. The Id it specifies is only intended to be of
+ local use to Diameter and the tunnel initiator. The Id assigned by
+ the tunnel initiator is not conveyed to the tunnel peer.
+
+ This attribute MAY be included in authorization responses. The
+ tunnel initiator receiving this attribute MAY choose to ignore it and
+ to assign the session to an arbitrary multiplexed or non-multiplexed
+ tunnel between the desired endpoints. This AVP SHOULD also be
+ included in the Accounting-Request messages pertaining to the
+ tunneled session.
+
+ If a tunnel initiator supports the Tunnel-Assignment-Id AVP, then it
+ should assign a session to a tunnel in the following manner:
+
+ - If this AVP is present and a tunnel exists between the
+ specified endpoints with the specified Id, then the session
+ should be assigned to that tunnel.
+
+ - If this AVP is present and no tunnel exists between the
+ specified endpoints with the specified Id, then a new tunnel
+ should be established for the session and the specified Id
+ should be associated with the new tunnel.
+
+ - If this AVP is not present, then the session is assigned to an
+ unnamed tunnel. If an unnamed tunnel does not yet exist
+ between the specified endpoints, then it is established and
+ used for this session and for subsequent ones established
+ without the Tunnel-Assignment-Id attribute. A tunnel initiator
+ MUST NOT assign a session for which a Tunnel-Assignment-Id AVP
+ was not specified to a named tunnel (i.e., one that was
+ initiated by a session specifying this AVP).
+
+ Note that the same Id may be used to name different tunnels if these
+ tunnels are between different endpoints.
+
+7.9. Tunnel-Preference AVP
+
+ The Tunnel-Preference AVP (AVP Code 83) is of type Unsigned32 and is
+ used to identify the relative preference assigned to each tunnel when
+ more than one set of tunneling AVPs is returned within separate
+ Grouped-AVP AVPs. It MAY be used in an authorization request as a
+ hint to the server that a specific preference is desired, but the
+
+
+
+Calhoun, et al. Standards Track [Page 49]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ server is not required to honor the hint in the corresponding
+ response.
+
+ For example, suppose that AVPs describing two tunnels are returned by
+ the server, one with a Tunnel-Type of PPTP and the other with a
+ Tunnel-Type of L2TP. If the tunnel initiator supports only one of
+ the Tunnel-Types returned, it will initiate a tunnel of that type.
+ If, however, it supports both tunnel protocols, it SHOULD use the
+ value of the Tunnel-Preference AVP to decide which tunnel should be
+ started. The tunnel with the lowest numerical value in the Value
+ field of this AVP SHOULD be given the highest preference. The values
+ assigned to two or more instances of the Tunnel-Preference AVP within
+ a given authorization response MAY be identical. In this case, the
+ tunnel initiator SHOULD use locally configured metrics to decide
+ which set of AVPs to use.
+
+7.10. Tunnel-Client-Auth-Id AVP
+
+ The Tunnel-Client-Auth-Id AVP (AVP Code 90) is of type UTF8String and
+ specifies the name used by the tunnel initiator during the
+ authentication phase of tunnel establishment. It MAY be used in an
+ authorization request as a hint to the server that a specific
+ preference is desired, but the server is not required to honor the
+ hint in the corresponding response. This AVP MUST be present in the
+ authorization response if an authentication name other than the
+ default is desired. This AVP SHOULD be included in the Accounting-
+ Request messages pertaining to the tunneled session.
+
+7.11. Tunnel-Server-Auth-Id AVP
+
+ The Tunnel-Server-Auth-Id AVP (AVP Code 91) is of type UTF8String and
+ specifies the name used by the tunnel terminator during the
+ authentication phase of tunnel establishment. It MAY be used in an
+ authorization request as a hint to the server that a specific
+ preference is desired, but the server is not required to honor the
+ hint in the corresponding response. This AVP MUST be present in the
+ authorization response if an authentication name other than the
+ default is desired. This AVP SHOULD be included in the Accounting-
+ Request messages pertaining to the tunneled session.
+
+8. NAS Accounting
+
+ Applications implementing this specification use Diameter Accounting,
+ as defined in [BASE], and the AVPs in the following section.
+ Service-specific AVP usage is defined in the tables in section 10.
+
+ If accounting is active, Accounting Request (ACR) messages SHOULD be
+ sent after the completion of any Authentication or Authorization
+
+
+
+Calhoun, et al. Standards Track [Page 50]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ transaction and at the end of a Session. The Accounting-Record-Type
+ value indicates the type of event. All other AVPs identify the
+ session and provide additional information relevant to the event.
+
+ The successful completion of the first Authentication or
+ Authorization transaction SHOULD cause a START_RECORD to be sent. If
+ additional Authentications or Authorizations occur in later
+ transactions, the first exchange should generate a START_RECORD, and
+ the later an INTERIM_RECORD. For a given session, there MUST only be
+ one set of matching START and STOP records, with any number of
+ INTERIM_RECORDS in between, or one EVENT_RECORD indicating the reason
+ a session wasn't started.
+
+ The following table describes the AVPs; their AVP Code values, types,
+ and possible flag values; and whether the AVP MAY be encrypted.
+
+ +---------------------+
+ | AVP Flag rules |
+ |----+-----+----+-----|----+
+ AVP Section | | |SHLD| MUST| |
+ Attribute Name Code Defined Value Type |MUST| MAY | NOT| NOT|Encr|
+ -----------------------------------------|----+-----+----+-----|----|
+ Accounting- 363 8.1 Unsigned64 | M | P | | V | Y |
+ Input-Octets | | | | | |
+ Accounting- 364 8.2 Unsigned64 | M | P | | V | Y |
+ Output-Octets | | | | | |
+ Accounting- 365 8.3 Unsigned64 | M | P | | V | Y |
+ Input-Packets | | | | | |
+ Accounting- 366 8.4 Unsigned64 | M | P | | V | Y |
+ Output-Packets | | | | | |
+ Acct-Session-Time 46 8.5 Unsigned32 | M | P | | V | Y |
+ Acct-Authentic 45 8.6 Enumerated | M | P | | V | Y |
+ Acounting-Auth- 406 8.7 Enumerated | M | P | | V | Y |
+ Method | | | | | |
+ Acct-Delay-Time 41 8.8 Unsigned32 | M | P | | V | Y |
+ Acct-Link-Count 51 8.9 Unsigned32 | M | P | | V | Y |
+ Acct-Tunnel- 68 8.10 OctetString| M | P | | V | Y |
+ Connection | | | | | |
+ Acct-Tunnel- 86 8.11 Unsigned32 | M | P | | V | Y |
+ Packets-Lost | | | | | |
+ -----------------------------------------|----+-----+----+-----|----|
+
+8.1. Accounting-Input-Octets AVP
+
+ The Accounting-Input-Octets AVP (AVP Code 363) is of type Unsigned64
+ and contains the number of octets received from the user.
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 51]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ For NAS usage, this AVP indicates how many octets have been received
+ from the port in the course of this session. It can only be present
+ in ACR messages with an Accounting-Record-Type of INTERIM_RECORD or
+ STOP_RECORD.
+
+8.2. Accounting-Output-Octets AVP
+
+ The Accounting-Output-Octets AVP (AVP Code 364) is of type Unsigned64
+ and contains the number of octets sent to the user.
+
+ For NAS usage, this AVP indicates how many octets have been sent to
+ the port in the course of this session. It can only be present in
+ ACR messages with an Accounting-Record-Type of INTERIM_RECORD or
+ STOP_RECORD.
+
+8.3. Accounting-Input-Packets AVP
+
+ The Accounting-Input-Packets (AVP Code 365) is of type Unsigned64 and
+ contains the number of packets received from the user.
+
+ For NAS usage, this AVP indicates how many packets have been received
+ from the port over the course of a session being provided to a Framed
+ User. It can only be present in ACR messages with an Accounting-
+ Record-Type of INTERIM_RECORD or STOP_RECORD.
+
+8.4. Accounting-Output-Packets AVP
+
+ The Accounting-Output-Packets (AVP Code 366) is of type Unsigned64
+ and contains the number of IP packets sent to the user.
+
+ For NAS usage, this AVP indicates how many packets have been sent to
+ the port over the course of a session being provided to a Framed
+ User. It can only be present in ACR messages with an Accounting-
+ Record-Type of INTERIM_RECORD or STOP_RECORD.
+
+8.5. Acct-Session-Time AVP
+
+ The Acct-Session-Time AVP (AVP Code 46) is of type Unsigned32 and
+ indicates the length of the current session in seconds. It can only
+ be present in ACR messages with an Accounting-Record-Type of
+ INTERIM_RECORD or STOP_RECORD.
+
+8.6. Acct-Authentic AVP
+
+ The Acct-Authentic AVP (AVP Code 45) is of type Enumerated and
+ specifies how the user was authenticated. The supported values are
+ listed in [RADIUSTypes]. The following list is informational:
+
+
+
+
+Calhoun, et al. Standards Track [Page 52]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ 1 RADIUS
+ 2 Local
+ 3 Remote
+ 4 Diameter
+
+8.7. Accounting-Auth-Method AVP
+
+ The Accounting-Auth-Method AVP (AVP Code 406) is of type Enumerated.
+ A NAS MAY include this AVP in an Accounting-Request message to
+ indicate the method used to authenticate the user. (Note that this
+ is equivalent to the RADIUS MS-Acct-Auth-Type VSA attribute).
+
+ The following values are defined:
+
+ 1 PAP
+ 2 CHAP
+ 3 MS-CHAP-1
+ 4 MS-CHAP-2
+ 5 EAP
+ 7 None
+
+8.8. Acct-Delay-Time
+
+ The Acct-Delay-Time AVP (AVP Code 41) is of type Unsigned32 and
+ indicates the number of seconds the Diameter client has been trying
+ to send the Accounting-Request (ACR). The accounting server may
+ subtract this value from the time when the ACR arrives at the server
+ to calculate the approximate time of the event that caused the ACR to
+ be generated.
+
+ This AVP is not used for retransmissions at the transport level (TCP
+ or SCTP). Rather, it may be used when an ACR command cannot be
+ transmitted because there is no appropriate peer to transmit it to or
+ was rejected because it could not be delivered. In these cases, the
+ command MAY be buffered and transmitted later, when an appropriate
+ peer-connection is available or after sufficient time has passed that
+ the destination-host may be reachable and operational. If the ACR is
+ resent in this way, the Acct-Delay-Time AVP SHOULD be included. The
+ value of this AVP indicates the number of seconds that elapsed
+ between the time of the first attempt at transmission and the current
+ attempt.
+
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 53]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+8.9. Acct-Link-Count
+
+ The Acct-Link-Count AVP (AVP Code 51) is of type Unsigned32 and
+ indicates the total number of links that have been active (current or
+ closed) in a given multilink session at the time the accounting
+ record is generated. This AVP MAY be included in Accounting-Requests
+ for any session that may be part of a multilink service.
+
+ The Acct-Link-Count AVP may be used to make it easier for an
+ accounting server to know when it has all the records for a given
+ multilink service. When the number of Accounting-Requests received
+ with Accounting-Record-Type = STOP_RECORD and with the same Acct-
+ Multi-Session-Id and unique Session-Ids equals the largest value of
+ Acct-Link-Count seen in those Accounting-Requests, all STOP_RECORD
+ Accounting-Requests for that multilink service have been received.
+
+ The following example, showing eight Accounting-Requests, illustrates
+ how the Acct-Link-Count AVP is used. In the table below, only the
+ relevant AVPs are shown, although additional AVPs containing
+ accounting information will be present in the Accounting-Requests.
+
+ Acct-Multi- Accounting- Acct-
+ Session-Id Session-Id Record-Type Link-Count
+ --------------------------------------------------------
+ "...10" "...10" START_RECORD 1
+ "...10" "...11" START_RECORD 2
+ "...10" "...11" STOP_RECORD 2
+ "...10" "...12" START_RECORD 3
+ "...10" "...13" START_RECORD 4
+ "...10" "...12" STOP_RECORD 4
+ "...10" "...13" STOP_RECORD 4
+ "...10" "...10" STOP_RECORD 4
+
+8.10. Acct-Tunnel-Connection AVP
+
+ The Acct-Tunnel-Connection AVP (AVP Code 68) is of type OctetString
+ and contains the identifier assigned to the tunnel session. This
+ AVP, along with the Tunnel-Client-Endpoint and Tunnel-Server-Endpoint
+ AVPs, may be used to provide a means to uniquely identify a tunnel
+ session for auditing purposes.
+
+ The format of the identifier in this AVP depends upon the value of
+ the Tunnel-Type AVP. For example, to identify an L2TP tunnel
+ connection fully, the L2TP Tunnel Id and Call Id might be encoded in
+ this field. The exact encoding of this field is implementation
+ dependent.
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 54]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+8.11. Acct-Tunnel-Packets-Lost AVP
+
+ The Acct-Tunnel-Packets-Lost AVP (AVP Code 86) is of type Unsigned32
+ and contains the number of packets lost on a given link.
+
+9. RADIUS/Diameter Protocol Interactions
+
+ This section describes some basic guidelines that servers acting as
+ AAA Translation Agents may use. A complete description of all the
+ differences between RADIUS and Diameter is beyond the scope of this
+ section and document. Note that this document does not restrict
+ implementations from creating additional translation methods, as long
+ as the translation function doesn't violate the RADIUS or the
+ Diameter protocols.
+
+ Although the Diameter protocol is in many ways a superset of RADIUS
+ functions, a number of RADIUS representations are not allowed, so
+ that new capabilities can be used without the old problems.
+
+ There are primarily two different situations that must be handled:
+ one in which a RADIUS request is received that must be forwarded as a
+ Diameter request, and another in which the inverse is true. RADIUS
+ does not support a peer-to-peer architecture, and server-initiated
+ operations are generally not supported. See [RADDynAuth] for an
+ alternative.
+
+ Some RADIUS attributes are encrypted. RADIUS security and encryption
+ techniques are applied on a hop-per-hop basis. A Diameter agent will
+ have to decrypt RADIUS attribute data entering the Diameter system,
+ and if that information is forwarded, the agent MUST secure it by
+ using Diameter specific techniques.
+
+ Note that this section uses the two terms, "AVP" and "attribute", in
+ a concise and specific manner. The former is used to signify a
+ Diameter AVP, and the latter to signify a RADIUS attribute.
+
+9.1. RADIUS Request Forwarded as Diameter Request
+
+ This section describes the actions that should be taken when a
+ Translation Agent receives a RADIUS message to be translated to a
+ Diameter message.
+
+ Note that RADIUS servers are assumed to be stateless. It is also
+ quite possible for the RADIUS messages that comprise the session
+ (i.e., authentication and accounting messages) to be handled by
+ different Translation Agents in the proxy network. Therefore, a
+ RADIUS/Diameter Translation Agent SHOULD NOT be assumed to have an
+ accurate track on session-state information.
+
+
+
+Calhoun, et al. Standards Track [Page 55]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ When a Translation Agent receives a RADIUS message, the following
+ steps should be taken:
+
+ - If a Message-Authenticator attribute is present, the value MUST
+ be checked but not included in the Diameter message. If it is
+ incorrect, the RADIUS message should be silently discarded.
+ The gateway system SHOULD generate and include a Message-
+ Authenticator in returned RADIUS responses.
+
+ - The transport address of the sender MUST be checked against the
+ NAS identifying attributes. See the description of NAS-
+ Identifier and NAS-IP-Address below.
+
+ - The Translation Agent must maintain transaction state
+ information relevant to the RADIUS request, such as the
+ Identifier field in the RADIUS header, any existing RADIUS
+ Proxy-State attribute, and the source IP address and port
+ number of the UDP packet. These may be maintained locally in a
+ state table or saved in a Proxy-Info AVP group. A Diameter
+ Session-Id AVP value must be created using a session state
+ mapping mechanism.
+
+ - If the RADIUS request contained a State attribute and the
+ prefix of the data is "Diameter/", the data following the
+ prefix contains the Diameter Origin-Host/Origin-Realm/Session-
+ Id. If no such attributes are present and the RADIUS command
+ is an Access-Request, a new Session-Id is created. The
+ Session-Id is included in the Session-Id AVP.
+
+ - The Diameter Origin-Host and Origin-Realm AVPs MUST be created
+ and added by using the information from an FQDN corresponding
+ to the NAS-IP-Address attribute (preferred if available),
+ and/or to the NAS-Identifier attribute. (Note that the RADIUS
+ NAS-Identifier is not required to be an FQDN.)
+
+ - The response MUST have an Origin-AAA-Protocol AVP added,
+ indicating the protocol of origin of the message.
+
+ - The Proxy-Info group SHOULD be added, with the local server's
+ identity specified in the Proxy-Host AVP. This should ensure
+ that the response is returned to this system.
+
+ - The Destination-Realm AVP is created from the information found
+ in the RADIUS User-Name attribute.
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 56]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ - If the RADIUS User-Password attribute is present, the password
+ must be unencrypted by using the link's RADIUS shared secret.
+ The unencrypted value must be forwarded in a User-Password AVP
+ using Diameter security.
+
+ - If the RADIUS CHAP-Password attribute is present, the Ident and
+ Data portion of the attribute are used to create the CHAP-Auth
+ grouped AVP.
+
+ - If the RADIUS message contains an address attribute, it MUST be
+ converted to the appropriate Diameter AVP and type.
+
+ - If the RADIUS message contains Tunnel information [RADTunnels],
+ the attributes or tagged groups should each be converted to a
+ Diameter Tunneling Grouped AVP set. If the tunnel information
+ contains a Tunnel-Password attribute, the RADIUS encryption
+ must be resolved, and the password forwarded, by using Diameter
+ security methods.
+
+ - If the RADIUS message received is an Accounting-Request, the
+ Acct-Status-Type attribute value must be converted to a
+ Accounting-Record-Type AVP value. If the Acct-Status-Type
+ attribute value is STOP, the local server MUST issue a
+ Session-Termination-Request message once the Diameter
+ Accounting-Answer message has been received.
+
+ - If the Accounting message contains an Acct-Termination-Cause
+ attribute, it should be translated to the equivalent
+ Termination-Cause AVP value. (see below)
+
+ - If the RADIUS message contains the Accounting-Input-Octets,
+ Accounting-Input-Packets, Accounting-Output-Octets, or
+ Accounting-Output-Packets, these attributes must be converted
+ to the Diameter equivalents. Further, if the Acct-Input-
+ Gigawords or Acct-Output-Gigawords attributes are present,
+ these must be used to properly compute the Diameter accounting
+ AVPs.
+
+ The corresponding Diameter response is always guaranteed to be
+ received by the same Translation Agent that translated the original
+ request, due to the contents of the Proxy-Info AVP group in the
+ Diameter request. The following steps are applied to the response
+ message during the Diameter-to-RADIUS translation:
+
+ - If the Diameter Command-Code is set to AA-Answer and the
+ Result-Code AVP is set to DIAMETER_MULTI_ROUND_AUTH, the
+ gateway must send a RADIUS Access-Challenge. This must have
+ the Origin-Host, Origin-Realm, and Diameter Session-Id AVPs
+
+
+
+Calhoun, et al. Standards Track [Page 57]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ encapsulated in the RADIUS State attribute, with the prefix
+ "Diameter/", concatenated in the above order separated with "/"
+ characters, in UTF-8 [UTF-8]. This is necessary to ensure that
+ the Translation Agent receiving the subsequent RADIUS Access-
+ Request will have access to the Session Identifier and be able
+ to set the Destination-Host to the correct value. If the
+ Multi-Round-Time-Out AVP is present, the value of the AVP MUST
+ be inserted in the RADIUS Session-Timeout AVP.
+
+ - If the Command-Code is set to AA-Answer, the Diameter Session-
+ Id AVP is saved in a new RADIUS Class attribute whose format
+ consists of the string "Diameter/" followed by the Diameter
+ Session Identifier. This will ensure that the subsequent
+ Accounting messages, which could be received by any Translation
+ Agent, would have access to the original Diameter Session
+ Identifier.
+ - If a Proxy-State attribute was present in the RADIUS request,
+ the same attribute is added in the response. This information
+ may be found in the Proxy-Info AVP group, or in a local state
+ table.
+
+ - If state information regarding the RADIUS request was saved in
+ a Proxy-Info AVP or local state table, the RADIUS Identifier
+ and UDP IP Address and port number are extracted and used in
+ issuing the RADIUS reply.
+
+ When translating a Diameter AA-Answer (with successful result code)
+ to RADIUS Access-Accept that contains a Session-Timeout or
+ Authorization-Lifetime AVP, take the following steps:
+
+ - If the Diameter message contains a Session-Timeout AVP but no
+ Authorization-Lifetime AVP, translate it to a Session-Timeout
+ attribute (not a Termination-Action).
+
+ - If the Diameter message contains an Authorization-Lifetime AVP
+ but no Session-Timeout AVP, translate it to a Session-Timeout
+ attribute and a Termination-Action set to AA-REQUEST. (Remove
+ Authorization-Lifetime and Re-Auth-Request-Type.)
+
+ - If the Diameter message has both, the Session-Timeout must be
+ greater than or equal to the Authorization-Lifetime (required
+ by [BASE]). Translate it to a Session-Timeout value (with
+ value from Authorization-Lifetime AVP, the smaller one) and
+ with the Termination-Action set to AA-REQUEST. (Remove the
+ Authorization-Lifetime and Re-Auth-Request-Type.)
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 58]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+9.1.1. RADIUS Dynamic Authorization Considerations
+
+ A Diameter/RADIUS gateway may communicate with a server that
+ implements RADIUS Dynamic Authorization [RADDynAuth]. If the server
+ supports these functions, it MUST be listening on the assigned port
+ and would receive RADIUS CoA-Request and Disconnect-Request messages.
+ These can be mapped into the Diameter Re-Auth-Request (RAR) and
+ Abort-Session-Request (ASR) message exchanges, respectively [BASE].
+
+ If the [RADDynAuth] is not supported, the port would not be active
+ and the RADIUS server would receive an ICMP Port Unreachable
+ indication. Alternatively, if the messages are received but with an
+ inappropriate Service-Type, the gateway can respond with the
+ appropriate NAK message and an Error-Cause attribute with the value
+ of 405, "Unsupported Service".
+
+ The RADIUS CoA-Request and Disconnect-Request messages will not
+ contain a Diameter Session-Id. Diameter requires that this value
+ match an active session context. The gateway MUST have a session Id
+ cache (or other means) to identify the sessions these functions
+ pertain to. If unable to identify the session, the gateway (or NAS)
+ should return an Error-Cause value 503, "Session Context Not Found".
+
+ The RADIUS CoA-Request message only supports a change of
+ authorization attributes, and the received CoA-Request SHOULD include
+ a Service-Type of "Authorize-Only". This indicates an extended
+ exchange request by the rules given in [RADDynAuth] section 3.2, note
+ 6. This is the only type of exchange supported by Diameter [BASE].
+
+ For the CoA-Request, the translated RAR message will have a Re-Auth-
+ Type of AUTHORIZE_ONLY. The returned RAA will be translated into a
+ CoA-NAK with Error-Cause "Request Initiated". The gateway's Diameter
+ client SHOULD also start a reauthorization sequence by sending an AAR
+ message, which will be translated into an Access-Request message.
+ The RADIUS server will use the Access-Accept (or Access-Reject)
+ message to convey the new authorization attributes, which the gateway
+ will pass back in an AAA message.
+
+ Any attributes included in the COA-Request or Access-Accept message
+ are to be considered mandatory in Diameter. If they cannot be
+ supported, they MUST result in an error message return to the RADIUS
+ server, with an Error-Cause of "Unsupported Attribute". The Diameter
+ NAS will attempt to apply all the attributes supplied in the AA
+ message to the session.
+
+ A RADIUS Disconnect-Request message received by the gateway would be
+ translated to a Diameter Abort-Session-Request (ASR) message [BASE].
+ The results will be returned by the Diameter client in an Abort-
+
+
+
+Calhoun, et al. Standards Track [Page 59]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ Session-Answer (ASA) message. A success indication would translate
+ to a RADIUS Disconnect-ACK, and a failure would generate a
+ Disconnect-NAK.
+
+9.2. Diameter Request Forwarded as RADIUS Request
+
+ When a server receives a Diameter request to be forwarded to a RADIUS
+ entity, the following are examples of the steps that may be taken:
+
+ - The Origin-Host AVP's value is inserted into the NAS-Identifier
+ attribute.
+
+ - The following information MUST be present in the corresponding
+ Diameter response and therefore MUST be saved, either in a
+ local state table or encoded in a RADIUS Proxy-State attribute:
+
+ 1. Origin-Host AVP
+ 2. Session-Id AVP
+ 3. Proxy-Info AVP
+ 4. Any other AVP that MUST be present in the response and
+ has no corresponding RADIUS attribute.
+
+ - If the CHAP-Auth AVP is present, the grouped AVPs are used to
+ create the RADIUS CHAP-Password attribute data.
+
+ - If the User-Password AVP is present, the data should be
+ encrypted and forwarded by using RADIUS rules. The same is
+ true for any other RADIUS-encrypted attribute values.
+
+ - AVPs of the type Address must be translated to the
+ corresponding RADIUS attribute.
+
+ - If the Accounting-Input-Octets, Accounting-Input-Packets,
+ Accounting-Output-Octets, or Accounting-Output-Packets AVPs are
+ present, they must be translated to the corresponding RADIUS
+ attributes. If the value of the Diameter AVPs do not fit
+ within a 32-bit RADIUS attribute, the RADIUS Acct-Input-
+ Gigawords and Acct-Output-Gigawords must be used.
+
+ - If the RADIUS link supports the Message-Authenticator attribute
+ [RADIUSExt], it SHOULD be generated and added to the request.
+
+ When the corresponding response is received by the Translation Agent,
+ which is guaranteed in the RADIUS protocol, the following steps may
+ be taken:
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 60]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ - If the RADIUS code is set to Access-Challenge, a Diameter AA-
+ Answer message is created with the Result-Code set to
+ DIAMETER_MULTI_ROUND_AUTH. If the Session-Timeout AVP is
+ present in the RADIUS message, its value is inserted into the
+ Multi-Round-Time-Out AVP.
+
+ - If a Proxy-State attribute is present, extract the encoded
+ information; otherwise, retrieve the original Proxy-Info AVP
+ group information from the local state table.
+
+ - The response's Origin-Host information is created from the FQDN
+ of the RADIUS message's source IP address. The same FQDN is
+ also stored to a Route-Record AVP.
+
+ - The response's Destination-Host AVP is copied from the saved
+ request's Origin-Host information.
+
+ - The Session-Id information can be recovered from local state,
+ or from the constructed State or Proxy-State attribute, as
+ above.
+
+ - If a Proxy-Info AVP was present in the request, the same AVP
+ MUST be added to the response.
+
+ - If the RADIUS State attributes are present, they must be
+ present in the Diameter response, minus those added by the
+ gateway.
+
+ - Any other AVPs that were saved at request time, and that MUST
+ be present in the response, are added to the message.
+
+ When translating a RADIUS Access-Accept to Diameter AA-Answer that
+ contains a Session-Timeout attribute, do the following:
+
+ - If the RADIUS message contains a Session-Timeout attribute and
+ a Termination-Action attribute set to DEFAULT (or no
+ Termination-Action attribute at all), translate it to AA-Answer
+ with a Session-Timeout AVP and remove the Termination-Action
+ attribute.
+
+ - If the RADIUS message contains a Session-Timeout attribute and
+ a Termination-Action attribute set to AA-REQUEST, translate it
+ to AA-Answer with Authorization-Lifetime AVP and with Re-Auth-
+ Request-Type set to AUTHORIZE_AUTHENTICATE and remove the
+ Session-Timeout attribute.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 61]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+9.2.1. RADIUS Dynamic Authorization Considerations
+
+ A RADIUS/Diameter gateway communicating with a RADIUS client that
+ implements RADIUS Dynamic Authorization [RADDynAuth] may translate
+ Diameter Re-Auth-Request (RAR) messages and Abort-Session-Request
+ (ASR) messages [BASE] into RADIUS CoA-Request and Disconnect-Request
+ messages respectively.
+
+ If the RADIUS client does not support the capability, the gateway
+ will receive an ICMP Port Unreachable indication when it transmits
+ the RADIUS message. Even if the NAS supports [RADDynAuth], it may
+ not support the Service-Type in the request message. In this case it
+ will respond with a NAK message and (optionally) an Error-Cause
+ attribute with value 405, "Unsupported Service". If the gateway
+ encounters these error conditions, or if it does not support
+ [RADDynAuth], it sends a Diameter Answer message with an Result-Code
+ AVP of "DIAMETER_COMMAND_UNSUPPORTED" to the AAA server.
+
+ When encoding the RADIUS messages, the gateway MUST include the
+ Diameter Session-ID in the RADIUS State attribute value, as mentioned
+ above. The RADIUS client should return it in the response.
+
+ A Diameter Re-Auth-Request (RAR) message [BASE] received by the
+ gateway will be translated into a RADIUS CoA-Request and sent to the
+ RADIUS client. The RADIUS client should respond with a CoA-ACK or
+ CoA-NAK message, which the gateway should translate into a Re-Auth-
+ Answer (RAA) message.
+
+ If the gateway receives a RADIUS CoA-NAK response containing a
+ Service-Type Attribute with value "Authorize Only" and an Error-Cause
+ Attribute with value "Request Initiated", this indicates an extended
+ exchange request per [RADDynAuth] section 3.2, note 6.
+
+ The response is translated to a Diameter Re-Auth-Answer (RAA) with a
+ Result-Code AVP of "DIAMETER_LIMITED_SUCCESS" sent to the AAA server.
+
+ Subsequently, the gateway should receive a RADIUS Access-Request from
+ the NAS, with a Service-Type of "Authorize Only". This is translated
+ into a Diameter AA-Request with an Auth-Request-Type AVP of
+ AUTHORIZE_ONLY and sent to the AAA server. The AAA server will then
+ reply with a Diameter AA-Answer, which is translated into a RADIUS
+ Access-Accept or Access-Reject, depending on the value of the
+ Result-Code AVP.
+
+ A Diameter Abort-Session-Request (ASR) message [BASE] received by the
+ gateway will be translated into a RADIUS Disconnect-Request and sent
+ to the RADIUS client. The RADIUS client should respond with a
+
+
+
+
+Calhoun, et al. Standards Track [Page 62]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ Disconnect-ACK or Disconnect-NAK message, which the gateway should
+ translate into an Abort-Session-Answer (ASA) message.
+
+ If the gateway receives a RADIUS Disconnect-NAK response containing a
+ Service-Type Attribute with value "Authorize Only" and an Error-Cause
+ Attribute with value "Request Initiated", the Disconnect-NAK response
+ is translated into a Diameter Abort-Session-Answer (ASA) with a
+ Result-Code AVP of "DIAMETER_LIMITED_SUCCESS" sent to the AAA server.
+
+ Subsequently, the gateway should receive a RADIUS Access-Request from
+ the NAS, with a Service-Type of "Authorize Only". This is translated
+ into a Diameter AA-Request with an Auth-Request-Type AVP of
+ AUTHORIZE_ONLY and sent to the AAA server. The AAA server will then
+ reply with a Diameter AA-Answer, which is translated into a RADIUS
+ Access-Accept or Access-Reject, depending on the value of the
+ Result-Code AVP.
+
+9.3. AVPs Used Only for Compatibility
+
+ The AVPs defined in this section SHOULD only be used for backwards
+ compatibility when a Diameter/RADIUS translation function is invoked
+ and are not typically originated by Diameter systems during normal
+ operations.
+
+ +---------------------+
+ | AVP Flag rules |
+ |----+-----+----+-----|----+
+ AVP Section | | |SHLD| MUST| |
+ Attribute Name Code Defined Value Type |MUST| MAY | NOT| NOT|Encr|
+ -----------------------------------------|----+-----+----+-----|----|
+ NAS-Identifier 32 9.3.1 UTF8String | M | P | | V | Y |
+ NAS-IP-Address 4 9.3.2 OctetString| M | P | | V | Y |
+ NAS-IPv6-Address 95 9.3.3 OctetString| M | P | | V | Y |
+ State 24 9.3.4 OctetString| M | P | | V | Y |
+ Termination- 295 9.3.5 Enumerated | M | P | | V | Y |
+ Cause | | | | | |
+ Origin-AAA- 408 9.3.6 Enumerated | M | P | | V | Y |
+ Protocol | | | | | |
+ -----------------------------------------|----+-----+----+-----|----|
+
+9.3.1. NAS-Identifier AVP
+
+ The NAS-Identifier AVP (AVP Code 32) [RADIUS] is of type UTF8String
+ and contains the identity of the NAS providing service to the user.
+ This AVP SHOULD only be added by a RADIUS/Diameter Translation Agent.
+ When this AVP is present, the Origin-Host AVP identifies the NAS
+ providing service to the user.
+
+
+
+
+Calhoun, et al. Standards Track [Page 63]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ In RADIUS it would be possible for a rogue NAS to forge the NAS-
+ Identifier attribute. Diameter/RADIUS translation agents SHOULD
+ attempt to check a received NAS-Identifier attribute against the
+ source address of the RADIUS packet, by doing an A/AAAA RR query. If
+ the NAS-Identifier attribute contains an FQDN, then such a query
+ would resolve to an IP address matching the source address. However,
+ the NAS-Identifier attribute is not required to contain an FQDN, so
+ such a query could fail. If it fails, an error should be logged, but
+ no action should be taken, other than a reverse lookup on the source
+ address and insert the resulting FQDN into the Route-Record AVP.
+
+ Diameter agents and servers SHOULD check whether a NAS-Identifier AVP
+ corresponds to an entry in the Route-Record AVP. If no match is
+ found, then an error is logged, but no other action is taken.
+
+9.3.2. NAS-IP-Address AVP
+
+ The NAS-IP-Address AVP (AVP Code 4) [RADIUS] is of type OctetString
+ and contains the IP Address of the NAS providing service to the user.
+ This AVP SHOULD only be added by a RADIUS/Diameter Translation Agent.
+ When this AVP is present, the Origin-Host AVP identifies the NAS
+ providing service to the user.
+
+ In RADIUS it would be possible for a rogue NAS to forge the NAS-IP-
+ Address attribute value. Diameter/RADIUS translation agents MUST
+ check a received NAS-IP-Address or NAS-IPv6-Address attribute against
+ the source address of the RADIUS packet. If they do not match and
+ the Diameter/RADIUS translation agent does not know whether the
+ packet was sent by a RADIUS proxy or NAS (e.g., no Proxy-State
+ attribute), then by default it is assumed that the source address
+ corresponds to a RADIUS proxy, and that the NAS Address is behind
+ that proxy, potentially with some additional RADIUS proxies in
+ between. The Diameter/RADIUS translation agent MUST insert entries
+ in the Route-Record AVP corresponding to the apparent route. This
+ implies doing a reverse lookup on the source address and NAS-IP-
+ Address or NAS-IPv6-Address attributes to determine the corresponding
+ FQDNs.
+
+ If the source address and the NAS-IP-Address or NAS-IPv6-Address do
+ not match, and the Diameter/RADIUS translation agent knows that it is
+ talking directly to the NAS (e.g., there are no RADIUS proxies
+ between it and the NAS), then the error should be logged, and the
+ packet MUST be discarded.
+
+ Diameter agents and servers MUST check whether the NAS-IP-Address AVP
+ corresponds to an entry in the Route-Record AVP. This is done by
+ doing a reverse lookup (PTR RR) for the NAS-IP-Address to retrieve
+ the corresponding FQDN, and by checking for a match with the Route-
+
+
+
+Calhoun, et al. Standards Track [Page 64]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ Record AVP. If no match is found, then an error is logged, but no
+ other action is taken.
+
+9.3.3. NAS-IPv6-Address AVP
+
+ The NAS-IPv6-Address AVP (AVP Code 95) [RADIUSIPv6] is of type
+ OctetString and contains the IPv6 Address of the NAS providing
+ service to the user. This AVP SHOULD only be added by a
+ RADIUS/Diameter Translation Agent. When this AVP is present, the
+ Origin-Host AVP identifies the NAS providing service to the user.
+
+ In RADIUS it would be possible for a rogue NAS to forge the NAS-
+ IPv6-Address attribute. Diameter/RADIUS translation agents MUST
+ check a received NAS-IPv6-Address attribute against the source
+ address of the RADIUS packet. If they do not match and the
+ Diameter/RADIUS translation agent does not know whether the packet
+ was sent by a RADIUS proxy or NAS (e.g., no Proxy-State attribute),
+ then by default it is assumed that the source address corresponds to
+ a RADIUS proxy, and that the NAS-IPv6-Address is behind that proxy,
+ potentially with some additional RADIUS proxies in between. The
+ Diameter/RADIUS translation agent MUST insert entries in the Route-
+ Record AVP corresponding to the apparent route. This implies doing a
+ reverse lookup on the source address and NAS-IPv6-Address attributes
+ to determine the corresponding FQDNs.
+
+ If the source address and the NAS-IPv6-Address do not match, and the
+ Diameter/RADIUS translation agent knows that it is talking directly
+ to the NAS (e.g., there are no RADIUS proxies between it and the
+ NAS), then the error should be logged, and the packet MUST be
+ discarded.
+
+ Diameter agents and servers MUST check whether the NAS-IPv6-Address
+ AVP corresponds to an entry in the Route-Record AVP. This is done by
+ doing a reverse lookup (PTR RR) for the NAS-IPv6-Address to retrieve
+ the corresponding FQDN, and by checking for a match with the Record-
+ Route AVP. If no match is found, then an error is logged, but no
+ other action is taken.
+
+9.3.4. State AVP
+
+ The State AVP (AVP Code 24) [RADIUS] is of type OctetString and has
+ two uses in the Diameter NAS application.
+
+ The State AVP MAY be sent by a Diameter Server to a NAS in an AA-
+ Response command that contains a Result-Code of
+ DIAMETER_MULTI_ROUND_AUTH. If so, the NAS MUST return it unmodified
+ in the subsequent AA-Request command.
+
+
+
+
+Calhoun, et al. Standards Track [Page 65]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ The State AVP MAY also be sent by a Diameter Server to a NAS in an
+ AA-Response command that also includes a Termination-Action AVP with
+ the value of AA-REQUEST. If the NAS performs the Termination-Action
+ by sending a new AA-Request command upon termination of the current
+ service, it MUST return the State AVP unmodified in the new request
+ command.
+
+ In either usage, the NAS MUST NOT interpret the AVP locally. Usage
+ of the State AVP is implementation dependent.
+
+9.3.5. Termination-Cause AVP Code Values
+
+ This section defines a mapping between Termination-Cause AVP code
+ values and RADIUS Acct-Terminate-Cause attribute code values from RFC
+ 2866 [RADIUSAcct] and [RADIUSTypes], thereby allowing a
+ RADIUS/Diameter Translation Agent to convert between the attribute
+ and AVP values. This section thus extends the definitions in the
+ "Termination-Cause AVP" section of the Base Diameter specification.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 66]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ The table in this section defines the mapping between Termination-
+ Cause AVP and RADIUS Acct-Terminate-Cause causes.
+
+ +-----------------------+
+ | Value |
+ +-----------+-----------+
+ Cause Value Name | RADIUS | Diameter |
+ ------------------------------|-----------+-----------+
+ User Request | 1 | 11 |
+ Lost Carrier | 2 | 12 |
+ Lost Service | 3 | 13 |
+ Idle Timeout | 4 | 14 |
+ Session Timeout | 5 | 15 |
+ Admin Reset | 6 | 16 |
+ Admin Reboot | 7 | 17 |
+ Port Error | 8 | 18 |
+ NAS Error | 9 | 19 |
+ NAS Request | 10 | 20 |
+ NAS Reboot | 11 | 21 |
+ Port Unneeded | 12 | 22 |
+ Port Preempted | 13 | 23 |
+ Port Suspended | 14 | 24 |
+ Service Unavailable | 15 | 25 |
+ Callback | 16 | 26 |
+ User Error | 17 | 27 |
+ Host Request | 18 | 28 |
+ Supplicant Restart | 19 | 29 | [RAD802.1X]
+ Reauthentication Failure | 20 | 30 | [RAD802.1X]
+ Port Reinit | 21 | 31 | [RAD802.1X]
+ Port Disabled | 22 | 32 | [RAD802.1X]
+ ------------------------------|-----------+-----------+
+
+ From RFC 2866, the termination causes are as follows:
+
+ User Request User requested termination of service, for
+ example with LCP Terminate or by logging out.
+
+ Lost Carrier DCD was dropped on the port.
+
+ Lost Service Service can no longer be provided; for
+ example, user's connection to a host was
+ interrupted.
+
+ Idle Timeout Idle timer expired.
+
+ Session Timeout Maximum session length timer expired.
+
+ Admin Reset Administrator reset the port or session.
+
+
+
+Calhoun, et al. Standards Track [Page 67]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ Admin Reboot Administrator is ending service on the NAS,
+ for example, prior to rebooting the NAS.
+
+ Port Error NAS detected an error on the port that
+ required ending the session.
+
+ NAS Error NAS detected an error (other than on the
+ port) that required ending the session.
+
+ NAS Request NAS ended the session for a non-error reason not
+ otherwise listed here.
+
+ NAS Reboot NAS ended the session to reboot
+ non-administratively ("crash").
+
+ Port Unneeded NAS ended the session because resource usage
+ fell below a low-water mark (for example, if
+ a bandwidth-on-demand algorithm decided that
+ the port was no longer needed).
+
+ Port Preempted NAS ended the session to allocate the
+ port to a higher priority use.
+
+ Port Suspended NAS ended the session to suspend a virtual
+ session.
+
+ Service Unavailable NAS was unable to provide requested service.
+
+ Callback NAS is terminating the current session
+ to perform callback for a new session.
+
+ User Error Input from user is in error, causing
+ session termination.
+
+ Host Request Login Host terminated session normally.
+
+9.3.6. Origin-AAA-Protocol
+
+ The Origin-AAA-Protocol AVP (AVP Code 408) is of the type Enumerated
+ and should be inserted in a Diameter message translated by a gateway
+ system from another AAA protocol, such as RADIUS. It identifies the
+ source protocol of the message to the Diameter system receiving the
+ message.
+
+ The supported values are:
+
+ 1 RADIUS
+
+
+
+
+Calhoun, et al. Standards Track [Page 68]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+9.4. Prohibited RADIUS Attributes
+
+ The following RADIUS attributes MUST NOT appear in a Diameter
+ message. Instead, they are translated to other Diameter AVPs or
+ handled in some special manner. The rules for the treatment of the
+ attributes are discussed in sections 9.1, 9.2, and 9.6.
+
+ Attribute Description Defined Nearest Diameter AVP
+ -----------------------------------------------------------------
+ 3 CHAP-Password RFC 2865 CHAP-Auth Group
+ 26 Vendor-Specific RFC 2865 Vendor Specific AVP
+ 29 Termination-Action RFC 2865 Authorization-Lifetime
+ 40 Acct-Status-Type RFC 2866 Accounting-Record-Type
+ 42 Acct-Input-Octets RFC 2866 Accounting-Input-Octets
+ 43 Acct-Output-Octets RFC 2866 Accounting-Output-Octets
+ 47 Acct-Input-Packets RFC 2866 Accounting-Input-Packets
+ 48 Acct-Output-Packets RFC 2866 Accounting-Output-Packets
+ 49 Acct-Terminate-Cause RFC 2866 Termination-Cause
+ 52 Acct-Input-Gigawords RFC 2869 Accounting-Input-Octets
+ 53 Acct-Output-Gigawords RFC 2869 Accounting-Output-Octets
+ 80 Message-Authenticator RFC 2869 none - check and discard
+
+9.5. Translatable Diameter AVPs
+
+ In general, Diameter AVPs that are not RADIUS compatible have code
+ values greater than 255. The table in the section above shows the
+ AVPs that can be converted into RADIUS attributes.
+
+ Another problem may occur with Diameter AVP values that may be more
+ than 253 octets in length. Some RADIUS attributes (including but not
+ limited to (8)Reply-Message, (79)EAP-Message, and (77)Connect-Info)
+ allow concatenation of multiple instances to overcome this
+ limitation. If this is not possible, a Result-Code of
+ DIAMETER_INVALID_AVP_LENGTH should be returned.
+
+9.6. RADIUS Vendor Specific Attributes
+
+ RADIUS supports the inclusion of Vendor Specific Attributes (VSAs)
+ through the use of attribute 26. The recommended format [RADIUS] of
+ the attribute data field includes a 4 octet vendor code followed by a
+ one octet vendor type field and a one octet length field. The last
+ two fields MAY be repeated.
+
+ A system communicating between Diameter and RADIUS MAY have specific
+ knowledge of vendor formats, and MAY be able to translate between the
+ two formats. However, given the deployment of many RADIUS vendor
+ formats that do not follow the example format in RFC 2865 [RADIUS],
+ (e.g., those that use a longer vendor type code) the translations in
+
+
+
+Calhoun, et al. Standards Track [Page 69]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ the next two sections will not work in general for those VSAs. RFC
+ 2865 states that a robust implementation SHOULD support the field as
+ undistinguished octets.
+
+ Systems that don't have vendor format knowledge MAY discard such
+ attributes without knowing a suitable translation. An alternative
+ format is under consideration [VSA], which proposes encodings that
+ would preserve the native information and not require vendor
+ knowledge in the gateway system.
+
+ The following sections are an example for translating RADIUS VSAs
+ that use the example RADIUS format, and Diameter VSAs that have type
+ codes less than 255, and value field lengths less than 252.
+
+9.6.1. Forwarding a Diameter Vendor Specific AVP as a RADIUS VSA
+
+ For Type codes less than 255, the value field length MUST be less
+ than 252 or the AVP will be discarded. The RADIUS VSA attribute
+ should consist of the following fields;
+
+ RADIUS Type = 26, Vendor Specific Attribute
+ RADIUS Length = total length of attribute (header + data)
+ RADIUS Vendor code = Diameter Vendor code
+ RADIUS Vendor type code = low order byte of Diameter AVP code
+ RADIUS Vendor data length = length of Diameter data
+
+ If the Diameter AVP code is greater than 255, then the RADIUS
+ speaking code may use a Vendor specific field coding, if it knows one
+ for that vendor. Otherwise, the AVP will be ignored. If it is
+ flagged as Mandatory, a "DIAMETER_AVP_UNSUPPORTED" Result-Code will
+ be returned, and the RADIUS message will not be sent.
+
+9.6.2. Forwarding a RADIUS VSA as a Diameter Vendor Specific AVP
+
+ The Diameter AVP will consist of the following fields:
+
+ Diameter Flags: V=1, M=0, P=0
+ Diameter Vendor code = RADIUS VSA Vendor code
+ Diameter AVP code = RADIUS VSA Vendor type code
+ Diameter AVP length = length of AVP (header + data)
+ Diameter Data = RADIUS VSA vendor data
+
+ Note that the VSAs are considered optional by RADIUS rules, and this
+ specification does not set the Mandatory flag. If an implementor
+ desires a VSA be made mandatory because it represents a required
+ service policy, the RADIUS gateway should have a process to set the
+ bit on the Diameter side.
+
+
+
+
+Calhoun, et al. Standards Track [Page 70]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ If the RADIUS receiving code knows of vendor specific field
+ interpretations for the specific vendor, it may employ them to parse
+ an extended AVP code or data length. Otherwise the recommended
+ standard fields will be used.
+
+ Nested Multiple vendor data fields MUST be expanded into multiple
+ Diameter AVPs.
+
+10. AVP Occurrence Tables
+
+ The following tables present the AVPs used by NAS applications in NAS
+ messages and specify in which Diameter messages they MAY or MAY NOT
+ be present. [BASE] messages and AVPs are not described in this
+ document. Note that AVPs that can only be present within a Grouped
+ AVP are not represented in this table.
+
+ The table uses the following symbols:
+
+ 0 The AVP MUST NOT be present in the message.
+ 0+ Zero or more instances of the AVP MAY be present in the
+ message.
+ 0-1 Zero or one instance of the AVP MAY be present in the
+ message.
+ 1 One instance of the AVP MUST be present in the message.
+
+10.1. AA-Request/Answer AVP Table
+
+ The table in this section is limited to the Command Codes defined in
+ this specification.
+
+ +-----------+
+ | Command |
+ |-----+-----+
+ Attribute Name | AAR | AAA |
+ ------------------------------|-----+-----+
+ Acct-Interim-Interval | 0 | 0-1 |
+ ARAP-Challenge-Response | 0 | 0-1 |
+ ARAP-Features | 0 | 0-1 |
+ ARAP-Password | 0-1 | 0 |
+ ARAP-Security | 0-1 | 0-1 |
+ ARAP-Security-Data | 0+ | 0+ |
+ ARAP-Zone-Access | 0 | 0-1 |
+ Auth-Application-Id | 1 | 1 |
+ Auth-Grace-Period | 0-1 | 0-1 |
+ Auth-Request-Type | 1 | 1 |
+ Auth-Session-State | 0-1 | 0-1 |
+ Authorization-Lifetime | 0-1 | 0-1 |
+ ------------------------------|-----+-----+
+
+
+
+Calhoun, et al. Standards Track [Page 71]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ +-----------+
+ | Command |
+ |-----+-----+
+ Attribute Name | AAR | AAA |
+ ------------------------------|-----+-----+
+ Callback-Id | 0 | 0-1 |
+ Callback-Number | 0-1 | 0-1 |
+ Called-Station-Id | 0-1 | 0 |
+ Calling-Station-Id | 0-1 | 0 |
+ CHAP-Auth | 0-1 | 0 |
+ CHAP-Challenge | 0-1 | 0 |
+ Class | 0 | 0+ |
+ Configuration-Token | 0 | 0+ |
+ Connect-Info | 0+ | 0 |
+ Destination-Host | 0-1 | 0 |
+ Destination-Realm | 1 | 0 |
+ Error-Message | 0 | 0-1 |
+ Error-Reporting-Host | 0 | 0-1 |
+ Failed-AVP | 0+ | 0+ |
+ Filter-Id | 0 | 0+ |
+ Framed-Appletalk-Link | 0 | 0-1 |
+ Framed-Appletalk-Network | 0 | 0+ |
+ Framed-Appletalk-Zone | 0 | 0-1 |
+ Framed-Compression | 0+ | 0+ |
+ Framed-Interface-Id | 0-1 | 0-1 |
+ Framed-IP-Address | 0-1 | 0-1 |
+ Framed-IP-Netmask | 0-1 | 0-1 |
+ Framed-IPv6-Prefix | 0+ | 0+ |
+ Framed-IPv6-Pool | 0 | 0-1 |
+ Framed-IPv6-Route | 0 | 0+ |
+ Framed-IPX-Network | 0 | 0-1 |
+ Framed-MTU | 0-1 | 0-1 |
+ Framed-Pool | 0 | 0-1 |
+ Framed-Protocol | 0-1 | 0-1 |
+ Framed-Route | 0 | 0+ |
+ Framed-Routing | 0 | 0-1 |
+ Idle-Timeout | 0 | 0-1 |
+ Login-IP-Host | 0+ | 0+ |
+ Login-IPv6-Host | 0+ | 0+ |
+ Login-LAT-Group | 0-1 | 0-1 |
+ Login-LAT-Node | 0-1 | 0-1 |
+ Login-LAT-Port | 0-1 | 0-1 |
+ Login-LAT-Service | 0-1 | 0-1 |
+ Login-Service | 0 | 0-1 |
+ Login-TCP-Port | 0 | 0-1 |
+ Multi-Round-Time-Out | 0 | 0-1 |
+ ------------------------------|-----+-----+
+
+
+
+
+Calhoun, et al. Standards Track [Page 72]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ +-----------+
+ | Command |
+ |-----+-----+
+ Attribute Name | AAR | AAA |
+ ------------------------------|-----+-----+
+ NAS-Filter-Rule | 0 | 0+ |
+ NAS-Identifier | 0-1 | 0 |
+ NAS-IP-Address | 0-1 | 0 |
+ NAS-IPv6-Address | 0-1 | 0 |
+ NAS-Port | 0-1 | 0 |
+ NAS-Port-Id | 0-1 | 0 |
+ NAS-Port-Type | 0-1 | 0 |
+ Origin-AAA-Protocol | 0-1 | 0-1 |
+ Origin-Host | 1 | 1 |
+ Origin-Realm | 1 | 1 |
+ Origin-State-Id | 0-1 | 0-1 |
+ Originating-Line-Info | 0-1 | 0 |
+ Password-Retry | 0 | 0-1 |
+ Port-Limit | 0-1 | 0-1 |
+ Prompt | 0 | 0-1 |
+ Proxy-Info | 0+ | 0+ |
+ QoS-Filter-Rule | 0 | 0+ |
+ Re-Auth-Request-Type | 0 | 0-1 |
+ Redirect-Host | 0 | 0+ |
+ Redirect-Host-Usage | 0 | 0-1 |
+ Redirect-Max-Cache-Time | 0 | 0-1 |
+ Reply-Message | 0 | 0+ |
+ Result-Code | 0 | 1 |
+ Route-Record | 0+ | 0+ |
+ Service-Type | 0-1 | 0-1 |
+ Session-Id | 1 | 1 |
+ Session-Timeout | 0 | 0-1 |
+ State | 0-1 | 0-1 |
+ Tunneling | 0+ | 0+ |
+ User-Name | 0-1 | 0-1 |
+ User-Password | 0-1 | 0 |
+ ------------------------------|-----+-----+
+
+10.2. Accounting AVP Tables
+
+ The tables in this section are used to show which AVPs defined in
+ this document are to be present and used in NAS application
+ Accounting messages. These AVPs are defined in this document, as
+ well as in [BASE] and [RADIUSAcct].
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 73]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+10.2.1. Accounting Framed Access AVP Table
+
+ The table in this section is used when the Service-Type specifies
+ Framed Access.
+
+ +-----------+
+ | Command |
+ |-----+-----+
+ Attribute Name | ACR | ACA |
+ ---------------------------------------|-----+-----+
+ Accounting-Auth-Method | 0-1 | 0 |
+ Accounting-Input-Octets | 1 | 0 |
+ Accounting-Input-Packets | 1 | 0 |
+ Accounting-Output-Octets | 1 | 0 |
+ Accounting-Output-Packets | 1 | 0 |
+ Accounting-Record-Number | 0-1 | 0-1 |
+ Accounting-Record-Type | 1 | 1 |
+ Accounting-Realtime-Required | 0-1 | 0-1 |
+ Accounting-Sub-Session-Id | 0-1 | 0-1 |
+ Acct-Application-Id | 0-1 | 0-1 |
+ Acct-Session-Id | 1 | 0-1 |
+ Acct-Multi-Session-Id | 0-1 | 0-1 |
+ Acct-Authentic | 1 | 0 |
+ Acct-Delay-Time | 0-1 | 0 |
+ Acct-Interim-Interval | 0-1 | 0-1 |
+ Acct-Link-Count | 0-1 | 0 |
+ Acct-Session-Time | 1 | 0 |
+ Acct-Tunnel-Connection | 0-1 | 0 |
+ Acct-Tunnel-Packets-Lost | 0-1 | 0 |
+ Authorization-Lifetime | 0-1 | 0 |
+ Callback-Id | 0-1 | 0 |
+ Callback-Number | 0-1 | 0 |
+ Called-Station-Id | 0-1 | 0 |
+ Calling-Station-Id | 0-1 | 0 |
+ Class | 0+ | 0+ |
+ Connection-Info | 0+ | 0 |
+ Destination-Host | 0-1 | 0 |
+ Destination-Realm | 1 | 0 |
+ Event-Timestamp | 0-1 | 0-1 |
+ Error-Message | 0 | 0-1 |
+ Error-Reporting-Host | 0 | 0-1 |
+ Failed-AVP | 0 | 0+ |
+ ---------------------------------------|-----+-----+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 74]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ +-----------+
+ | Command |
+ |-----+-----+
+ Attribute Name | ACR | ACA |
+ ---------------------------------------|-----+-----+
+ Framed-AppleTalk-Link | 0-1 | 0 |
+ Framed-AppleTalk-Network | 0-1 | 0 |
+ Framed-AppleTalk-Zone | 0-1 | 0 |
+ Framed-Compression | 0-1 | 0 |
+ Framed-IP-Address | 0-1 | 0 |
+ Framed-IP-Netmask | 0-1 | 0 |
+ Framed-IPv6-Prefix | 0+ | 0 |
+ Framed-IPv6-Pool | 0-1 | 0 |
+ Framed-IPX-Network | 0-1 | 0 |
+ Framed-MTU | 0-1 | 0 |
+ Framed-Pool | 0-1 | 0 |
+ Framed-Protocol | 0-1 | 0 |
+ Framed-Route | 0-1 | 0 |
+ Framed-Routing | 0-1 | 0 |
+ NAS-Filter-Rule | 0+ | 0 |
+ NAS-Identifier | 0-1 | 0-1 |
+ NAS-IP-Address | 0-1 | 0-1 |
+ NAS-IPv6-Address | 0-1 | 0-1 |
+ NAS-Port | 0-1 | 0-1 |
+ NAS-Port-Id | 0-1 | 0-1 |
+ NAS-Port-Type | 0-1 | 0-1 |
+ Origin-AAA-Protocol | 0-1 | 0-1 |
+ Origin-Host | 1 | 1 |
+ Origin-Realm | 1 | 1 |
+ Origin-State-Id | 0-1 | 0-1 |
+ Originating-Line-Info | 0-1 | 0 |
+ Proxy-Info | 0+ | 0+ |
+ QoS-Filter-Rule | 0+ | 0 |
+ Route-Record | 0+ | 0+ |
+ Result-Code | 0 | 1 |
+ Service-Type | 0-1 | 0-1 |
+ Session-Id | 1 | 1 |
+ Termination-Cause | 0-1 | 0-1 |
+ Tunnel-Assignment-Id | 0-1 | 0 |
+ Tunnel-Client-Endpoint | 0-1 | 0 |
+ Tunnel-Medium-Type | 0-1 | 0 |
+ Tunnel-Private-Group-Id | 0-1 | 0 |
+ Tunnel-Server-Endpoint | 0-1 | 0 |
+ Tunnel-Type | 0-1 | 0 |
+ User-Name | 0-1 | 0-1 |
+ Vendor-Specific-Application-Id | 0-1 | 0-1 |
+ ---------------------------------------|-----+-----+
+
+
+
+
+Calhoun, et al. Standards Track [Page 75]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+10.2.2. Accounting Non-Framed Access AVP Table
+
+ The table in this section is used when the Service-Type specifies
+ Non-Framed Access.
+
+ +-----------+
+ | Command |
+ |-----+-----+
+ Attribute Name | ACR | ACA |
+ ---------------------------------------|-----+-----+
+ Accounting-Auth-Method | 0-1 | 0 |
+ Accounting-Input-Octets | 1 | 0 |
+ Accounting-Output-Octets | 1 | 0 |
+ Accounting-Record-Type | 1 | 1 |
+ Accounting-Record-Number | 0-1 | 0-1 |
+ Accounting-Realtime-Required | 0-1 | 0-1 |
+ Accounting-Sub-Session-Id | 0-1 | 0-1 |
+ Acct-Application-Id | 0-1 | 0-1 |
+ Acct-Session-Id | 1 | 0-1 |
+ Acct-Multi-Session-Id | 0-1 | 0-1 |
+ Acct-Authentic | 1 | 0 |
+ Acct-Delay-Time | 0-1 | 0 |
+ Acct-Interim-Interval | 0-1 | 0-1 |
+ Acct-Link-Count | 0-1 | 0 |
+ Acct-Session-Time | 1 | 0 |
+ Authorization-Lifetime | 0-1 | 0 |
+ Callback-Id | 0-1 | 0 |
+ Callback-Number | 0-1 | 0 |
+ Called-Station-Id | 0-1 | 0 |
+ Calling-Station-Id | 0-1 | 0 |
+ Class | 0+ | 0+ |
+ Connection-Info | 0+ | 0 |
+ Destination-Host | 0-1 | 0 |
+ Destination-Realm | 1 | 0 |
+ Event-Timestamp | 0-1 | 0-1 |
+ Error-Message | 0 | 0-1 |
+ Error-Reporting-Host | 0 | 0-1 |
+ Failed-AVP | 0 | 0+ |
+ Login-IP-Host | 0+ | 0 |
+ Login-IPv6-Host | 0+ | 0 |
+ Login-LAT-Service | 0-1 | 0 |
+ Login-LAT-Node | 0-1 | 0 |
+ Login-LAT-Group | 0-1 | 0 |
+ Login-LAT-Port | 0-1 | 0 |
+ Login-Service | 0-1 | 0 |
+ Login-TCP-Port | 0-1 | 0 |
+ ---------------------------------------|-----+-----+
+
+
+
+
+Calhoun, et al. Standards Track [Page 76]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ +-----------+
+ | Command |
+ |-----+-----+
+ Attribute Name | ACR | ACA |
+ ---------------------------------------|-----+-----+
+ NAS-Identifier | 0-1 | 0-1 |
+ NAS-IP-Address | 0-1 | 0-1 |
+ NAS-IPv6-Address | 0-1 | 0-1 |
+ NAS-Port | 0-1 | 0-1 |
+ NAS-Port-Id | 0-1 | 0-1 |
+ NAS-Port-Type | 0-1 | 0-1 |
+ Origin-AAA-Protocol | 0-1 | 0-1 |
+ Origin-Host | 1 | 1 |
+ Origin-Realm | 1 | 1 |
+ Origin-State-Id | 0-1 | 0-1 |
+ Originating-Line-Info | 0-1 | 0 |
+ Proxy-Info | 0+ | 0+ |
+ QoS-Filter-Rule | 0+ | 0 |
+ Route-Record | 0+ | 0+ |
+ Result-Code | 0 | 1 |
+ Session-Id | 1 | 1 |
+ Service-Type | 0-1 | 0-1 |
+ Termination-Cause | 0-1 | 0-1 |
+ User-Name | 0-1 | 0-1 |
+ Vendor-Specific-Application-Id | 0-1 | 0-1 |
+ ---------------------------------------|-----+-----+
+
+11. IANA Considerations
+
+ This section provides guidance to the Internet Assigned Numbers
+ Authority (IANA) regarding registration of values related to the
+ Diameter protocol, in accordance with BCP 26 [IANAConsid].
+
+ This document defines values in the namespaces that have been created
+ and defined in the Diameter Base [BASE]. The IANA Considerations
+ section of that document details the assignment criteria. Values
+ assigned in this document, or by future IANA action, must be
+ coordinated within this shared namespace.
+
+11.1. Command Codes
+
+ This specification assigns the value 265 from the Command Code
+ namespace defined in [BASE]. See sections 3.1 and 3.2 for the
+ assignment of the namespace in this specification.
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 77]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+11.2. AVP Codes
+
+ This specification assigns the values 363 - 366 and 400 - 408 from
+ the AVP Code namespace defined in [BASE]. See sections 4 and 5 for
+ the assignment of the namespace in this specification. Note that the
+ values 363 - 366 are jointly, but consistently, assigned in
+ [DiamMIP]. This document also creates one new namespace to be
+ managed by IANA, as described in section 11.5.
+
+ This specification also specifies the use of AVPs in the 0 - 255
+ range, which are defined in [RADIUSTypes]. These values are assigned
+ by the policy in RFC 2865 section 6 [RADIUS] and are amended by RFC
+ 3575 [RADIUSIANA].
+
+11.3. Application Identifier
+
+ This specification uses the value one (1) in the Application
+ Identifier namespace as assigned in [BASE]. See section 1.2 above
+ for more information.
+
+11.4. CHAP-Algorithm AVP Values
+
+ As defined in section 5.5, the CHAP-Algorithm AVP (AVP Code 403) uses
+ the values of the "PPP AUTHENTICATION ALGORITHMS" namespace defined
+ in [PPPCHAP].
+
+11.5. Accounting-Auth-Method AVP Values
+
+ As defined in section 8.6, the Accounting-Auth-Method AVP (AVP Code
+ 406) defines the values 1 - 5. All remaining values are available
+ for assignment via IETF Consensus [IANA].
+
+11.6. Origin-AAA-Protocol AVP Values
+
+ As defined in section 9.3.6, the Origin-AAA-Protocol AVP (AVP Code
+ 408) defines the value 1. All remaining values are available for
+ assignment with a "Specification Required" policy [IANAConsid].
+
+12. Security Considerations
+
+ This document describes the extension of Diameter for the NAS
+ application. The security considerations of the Diameter protocol
+ itself have been discussed in [BASE]. Use of this application of
+ Diameter MUST take into consideration the security issues and
+ requirements of the Base protocol.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 78]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ This document does not contain a security protocol but does discuss
+ how PPP authentication protocols can be carried within the Diameter
+ protocol. The PPP authentication protocols described are PAP and
+ CHAP.
+
+ The use of PAP SHOULD be discouraged, as it exposes users' passwords
+ to possibly non-trusted entities. However, PAP is also frequently
+ used for use with One-Time Passwords, which do not expose a security
+ risk.
+
+ This document also describes how CHAP can be carried within the
+ Diameter protocol, which is required for RADIUS backward
+ compatibility. The CHAP protocol, as used in a RADIUS environment,
+ facilitates authentication replay attacks.
+
+ The use of the EAP authentication protocols described in [DiamEAP]
+ can offer better security, given a method suitable for the
+ circumstances.
+
+13. References
+
+13.1. Normative References
+
+ [BASE] Calhoun, P., Loughney, J., Guttman, E., Zorn, G., and
+ J. Arkko, "Diameter Base Protocol", RFC 3588,
+ September 2003.
+
+ [DiamTrans] Aboba, B. and J. Wood, "Authentication, Authorization
+ and Accounting (AAA) Transport Profile", RFC 3539,
+ June 2003.
+
+ [RADIUS] Rigney, C., Willens, S., Rubens, A., and W. Simpson,
+ "Remote Authentication Dial In User Service (RADIUS)",
+ RFC 2865, June 2000.
+
+ [RADIUSTypes] IANA, "RADIUS Types", URL:
+ <http://www.iana.org/assignments/radius-types>
+
+ [RADIUSIPv6] Aboba, B., Zorn, G., and D. Mitton, "RADIUS and IPv6",
+ RFC 3162, August 2001.
+
+ [IPv6Addr] Nerenberg, L., "IMAP4 Binary Content Extension", RFC
+ 3516, April 2003.
+
+ [PPPCHAP] Simpson, W., "PPP Challenge Handshake Authentication
+ Protocol (CHAP)", RFC 1994, August 1996.
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 79]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ [IANAConsid] Narten, T. and H. Alvestrand, "Guidelines for Writing
+ an IANA Considerations Section in RFCs", BCP 26, RFC
+ 2434, October 1998.
+
+ [IANA] IANA Assigned Numbers Database, URL:
+ <http://www.iana.org/numbers.html>
+
+ [Keywords] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [ANITypes] NANPA Number Resource Info, ANI Assignments, URL:
+ <http://www.nanpa.com/number_resource_info/
+ ani_ii_assignments.html>
+
+13.2. Informative References
+
+ [RADIUSAcct] Rigney, C., "RADIUS Accounting", RFC 2866, June 2000.
+
+ [RADIUSExt] Rigney, C., Willats, W., and P. Calhoun, "RADIUS
+ Extensions", RFC 2869, June 2000.
+
+ [RADTunnels] Zorn, G., Leifer, D., Rubens, A., Shriver, J.,
+ Holdrege, M., and I. Goyret, "RADIUS Attributes for
+ Tunnel Protocol Support", RFC 2868, June 2000.
+
+ [RADTunlAcct] Zorn, G., Aboba, B., and D. Mitton, "RADIUS Accounting
+ Modifications for Tunnel Protocol Support", RFC 2867,
+ June 2000.
+
+ [RADDynAuth] Chiba, M., Dommety, G., Eklund, M., Mitton, D., and B.
+ Aboba, "Dynamic Authorization Extensions to Remote
+ Authentication Dial In User Service (RADIUS)", RFC
+ 3576, July 2003.
+
+ [RADIUSIANA] Aboba, B., "IANA Considerations for RADIUS (Remote
+ Authentication Dial In User Service)", RFC 3575, July
+ 2003.
+
+ [NASModel] Mitton, D. and M. Beadles, "Network Access Server
+ Requirements Next Generation (NASREQNG) NAS Model",
+ RFC 2881, July 2000.
+
+ [NASCriteria] Beadles, M. and D. Mitton, "Criteria for Evaluating
+ Network Access Server Protocols", RFC 3169, September
+ 2001.
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 80]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ [AAACriteria] Aboba, B., Calhoun, P., Glass, S., Hiller, T., McCann,
+ P., Shiino, H., Zorn, G., Dommety, G., Perkins, C.,
+ Patil, B., Mitton, D., Manning, S., Beadles, M.,
+ Walsh, P., Chen, X., Sivalingham, S., Hameed, A.,
+ Munson, M., Jacobs, S., Lim, B., Hirschman, B., Hsu,
+ R., Xu, Y., Campbell, E., Baba, S., and E. Jaques,
+ "Criteria for Evaluating AAA Protocols for Network
+ Access", RFC 2989, November 2000.
+
+ [DiamEAP] Eronen, P., "Diameter EAP Application", Work in
+ Progress, May 2004.
+
+ [DiamCMS] Calhoun, P., Bulley, W., and S. Farrell, "Diameter CMS
+ Security Application", Work in Progress, March 2002.
+
+ [DiamMIP] Calhoun, P., Johansson, T., Perkins, C., Hiller, T.,
+ and P. McCann "Diameter Mobile IPv4 Application", RFC
+ 4004, August 2005.
+
+ [VSA] Mitton, D., "Diameter/RADIUS Vendor Specific AVP
+ Translation", Work in Progress, April 2005.
+
+ [RAD802.1X] Congdon, P., Aboba, B., Smith, A., Zorn, G., and J.
+ Roese, "IEEE 802.1X Remote Authentication Dial In User
+ Service (RADIUS) Usage Guidelines", RFC 3580,
+ September 2003.
+
+ [CDMA2000] 3GPP2 "P.S0001-B", Wireless IP Network Standard,
+ October 2002.
+ http://www.3gpp2.com/Public_html/specs/P.S0001-
+ B_v1.0.pdf
+
+ [AppleTalk] Sidhu, Gursharan; Andrews, Richard F. & Oppenheimer,
+ Alan B. "Inside AppleTalk", Second Edition, Apple
+ Computer., 1990
+
+ [ARAP] Apple Remote Access Protocol (ARAP) Version 2.0
+ External Reference Specification", Apple Computer,
+ September 1994, R0612LL/B
+
+ [IPX] Novell, Inc., "NetWare System Technical Interface
+ Overview", June 1989, # 883-000780-001
+
+ [LAT] Local Area Transport (LAT) Specification V5.0, Digital
+ Equipment Corp., AA-NL26A-TE, June 1989
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 81]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+ [DIFFSERV] Nichols, K., Blake, S., Baker, F., and D. Black,
+ "Definition of the Differentiated Services Field (DS
+ Field) in the IPv4 and IPv6 Headers", RFC 2474,
+ December 1998.
+
+ [DIFFSERVAF] Heinanen, J., Baker, F., Weiss, W., and J. Wroclawski,
+ "Assured Forwarding PHB Group", RFC 2597, June 1999.
+
+ [DIFFSERVEF] Davie, B., Charny, A., Bennet, J.C., Benson, K., Le
+ Boudec, J., Courtney, W., Davari, S., Firoiu, V., and
+ D. Stiliadis, "An Expedited Forwarding PHB (Per-Hop
+ Behavior)", RFC 3246, March 2002.
+
+ [UTF-8] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", STD 63, RFC 3629, November 2003.
+
+ [ISOLatin] ISO 8859. International Standard -- Information
+ Processing -- 8-bit Single-Byte Coded Graphic
+ Character Sets -- Part 1: Latin Alphabet No. 1, ISO
+ 8859-1:1987. URL:
+ <http://www.iso.ch/cate/d16338.html>
+
+ [PPP] Simpson, W., "The Point-to-Point Protocol (PPP)", STD
+ 51, RFC 1661, July 1994.
+
+ [PAP] Lloyd, B. and W. Simpson, "PPP Authentication
+ Protocols", RFC 1334, October 1992.
+
+ [L2TP] Townsley, W., Valencia, A., Rubens, A., Pall, G.,
+ Zorn, G., and B. Palter, "Layer Two Tunneling Protocol
+ "L2TP"", RFC 2661, August 1999.
+
+ [PPPMP] Sklower, K., Lloyd, B., McGregor, G., Carr, D., and T.
+ Coradetti, "The PPP Multilink Protocol (MP)", RFC
+ 1990, August 1996.
+
+ [PPTP] Hamzeh, K., Pall, G., Verthein, W., Taarud, J.,
+ Little, W., and G. Zorn, "Point-to-Point Tunneling
+ Protocol", RFC 2637, July 1999.
+
+ [IEEE 802.11F] IEEE, "Trial-Use Recommended Practice for Multi-Vendor
+ Access Point Interoperability via an Inter-Access
+ Point Protocol Across Distribution Systems Supporting
+ IEEE 802.11 Operation", IEEE 802.11F-2003, June 2003.
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 82]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+14. Acknowledgements
+
+ The authors would like to thank Carl Rigney, Allan C. Rubens, William
+ Allen Simpson, and Steve Willens for their work on the original
+ RADIUS [RADIUS], from which many of the concepts in this
+ specification were derived. Thanks, also, to Carl Rigney for
+ [RADIUSAcct] and [RADIUSExt]; Ward Willats for [RADIUSExt]; Glen
+ Zorn, Bernard Aboba, and Dave Mitton for [RADTunlAcct] and
+ [RADIUSIPv6]; and Dory Leifer, John Shriver, Matt Holdrege, and
+ Ignacio Goyret for their work on [RADTunnels]. This document stole
+ text and concepts from both [RADTunnels] and [RADIUSExt]. Thanks go
+ to Carl Williams for providing IPv6-specific text.
+
+ The authors would also like to acknowledge the following people for
+ their contributions in the development of the Diameter protocol:
+ Bernard Aboba, Jari Arkko, William Bulley, Kuntal Chowdhury, Daniel
+ C. Fox, Lol Grant, Nancy Greene, Jeff Hagg, Peter Heitman, Paul
+ Krumviede, Fergal Ladley, Ryan Moats, Victor Muslin, Kenneth Peirce,
+ Sumit Vakil, John R. Vollbrecht, and Jeff Weisberg.
+
+ Finally, Pat Calhoun would like to thank Sun Microsystems, as most of
+ the effort put into this document was done while he was in their
+ employ.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 83]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+Authors' Addresses
+
+ Pat Calhoun
+ Cisco Systems, Inc.
+ 170 West Tasman Drive
+ San Jose, CA 95134
+ USA
+
+ Phone: +1 408-853-5269
+
+
+ Glen Zorn
+ Cisco Systems, Inc.
+ 500 108th Avenue N.E., Suite 500
+ Bellevue, WA 98004
+ USA
+
+ Phone: 1 425-471-4861
+
+
+ David Spence
+ 3259 Bluett Rd.
+ Ann Arbor, MI 48105
+ USA
+
+ Phone: +1 734 834 6481
+
+
+ David Mitton
+ Circular Networks
+ 733 Turnpike St #154
+ North Andover, MA 01845
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 84]
+
+RFC 4005 Diameter Network Access Server Application August 2005
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2005).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at ietf-
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+Calhoun, et al. Standards Track [Page 85]
+
diff --git a/lib/diameter/doc/standard/rfc4006.txt b/lib/diameter/doc/standard/rfc4006.txt
new file mode 100644
index 0000000000..3f3e5e1d1b
--- /dev/null
+++ b/lib/diameter/doc/standard/rfc4006.txt
@@ -0,0 +1,6387 @@
+
+
+
+
+
+
+Network Working Group H. Hakala
+Request for Comments: 4006 L. Mattila
+Category: Standards Track Ericsson
+ J-P. Koskinen
+ M. Stura
+ J. Loughney
+ Nokia
+ August 2005
+
+
+ Diameter Credit-Control Application
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ This document specifies a Diameter application that can be used to
+ implement real-time credit-control for a variety of end user services
+ such as network access, Session Initiation Protocol (SIP) services,
+ messaging services, and download services.
+
+Table of Contents
+
+ 1. Introduction................................................. 4
+ 1.1. Requirements Language................................. 5
+ 1.2. Terminology........................................... 5
+ 1.3. Advertising Application Support....................... 7
+ 2. Architecture Models.......................................... 7
+ 3. Credit-Control Messages...................................... 9
+ 3.1. Credit-Control-Request (CCR) Command.................. 9
+ 3.2. Credit-Control-Answer (CCA) Command................... 11
+ 4. Credit-Control Application Overview.......................... 11
+ 4.1. Service-Specific Rating Input and Interoperability.... 13
+ 5. Session Based Credit-Control................................. 15
+ 5.1. General Principles.................................... 15
+ 5.2. First Interrogation................................... 21
+ 5.3. Intermediate Interrogation............................ 27
+ 5.4. Final Interrogation................................... 29
+
+
+
+Hakala, et al. Standards Track [Page 1]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ 5.5. Server-Initiated Credit Re-Authorization.............. 30
+ 5.6. Graceful Service Termination.......................... 32
+ 5.7. Failure Procedures.................................... 38
+ 6. One Time Event............................................... 41
+ 6.1. Service Price Enquiry................................. 42
+ 6.2. Balance Check......................................... 42
+ 6.3. Direct Debiting....................................... 43
+ 6.4. Refund................................................ 44
+ 6.5. Failure Procedure..................................... 44
+ 7. Credit-Control Application State Machine..................... 46
+ 8. Credit-Control AVPs.......................................... 55
+ 8.1. CC-Correlation-Id AVP................................. 58
+ 8.2. CC-Request-Number AVP................................. 58
+ 8.3. CC-Request-Type AVP................................... 58
+ 8.4. CC-Session-Failover AVP............................... 59
+ 8.5. CC-Sub-Session-Id AVP................................. 59
+ 8.6. Check-Balance-Result AVP.............................. 60
+ 8.7. Cost-Information AVP.................................. 60
+ 8.8. Unit-Value AVP........................................ 61
+ 8.9. Exponent AVP.......................................... 61
+ 8.10. Value-Digits AVP...................................... 61
+ 8.11. Currency-Code AVP..................................... 62
+ 8.12. Cost-Unit AVP......................................... 62
+ 8.13. Credit-Control AVP.................................... 62
+ 8.14. Credit-Control-Failure-Handling AVP................... 62
+ 8.15. Direct-Debiting-Failure-Handling AVP.................. 63
+ 8.16. Multiple-Services-Credit-Control AVP.................. 64
+ 8.17. Granted-Service-Unit AVP.............................. 65
+ 8.18. Requested-Service-Unit AVP............................ 66
+ 8.19. Used-Service-Unit AVP................................. 66
+ 8.20. Tariff-Time-Change AVP................................ 67
+ 8.21. CC-Time AVP........................................... 67
+ 8.22. CC-Money AVP.......................................... 67
+ 8.23. CC-Total-Octets AVP................................... 68
+ 8.24. CC-Input-Octets AVP................................... 68
+ 8.25. CC-Output-Octets AVP.................................. 68
+ 8.26. CC-Service-Specific-Units AVP......................... 68
+ 8.27. Tariff-Change-Usage AVP............................... 68
+ 8.28. Service-Identifier AVP................................ 69
+ 8.29. Rating-Group AVP...................................... 69
+ 8.30. G-S-U-Pool-Reference AVP.............................. 69
+ 8.31. G-S-U-Pool-Identifier AVP............................. 70
+ 8.32. CC-Unit-Type AVP...................................... 70
+ 8.33. Validity-Time AVP..................................... 70
+ 8.34. Final-Unit-Indication AVP............................. 71
+ 8.35. Final-Unit-Action AVP................................. 72
+ 8.36. Restriction-Filter-Rule AVP........................... 72
+ 8.37. Redirect-Server AVP................................... 73
+
+
+
+Hakala, et al. Standards Track [Page 2]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ 8.38. Redirect-Address-Type AVP............................. 73
+ 8.39. Redirect-Server-Address AVP........................... 74
+ 8.40. Multiple-Services-Indicator AVP....................... 74
+ 8.41. Requested-Action AVP.................................. 74
+ 8.42. Service-Context-Id AVP................................ 75
+ 8.43. Service-Parameter-Info AVP............................ 76
+ 8.44. Service-Parameter-Type AVP............................ 76
+ 8.45. Service-Parameter-Value AVP........................... 77
+ 8.46. Subscription-Id AVP................................... 77
+ 8.47. Subscription-Id-Type AVP.............................. 77
+ 8.48. Subscription-Id-Data AVP.............................. 78
+ 8.49. User-Equipment-Info AVP............................... 78
+ 8.50. User-Equipment-Info-Type AVP.......................... 78
+ 8.50. User-Equipment-Info-Value AVP......................... 79
+ 9. Result Code AVP Values....................................... 79
+ 9.1. Transient Failures.................................... 79
+ 9.2. Permanent Failures.................................... 80
+ 10. AVP Occurrence Table......................................... 80
+ 10.1. Credit-Control AVP Table.............................. 81
+ 10.2. Re-Auth-Request/Answer AVP Table...................... 82
+ 11. RADIUS/Diameter Credit-Control Interworking Model............ 82
+ 12. IANA Considerations.......................................... 85
+ 12.1. Application Identifier................................ 86
+ 12.2. Command Codes......................................... 86
+ 12.3. AVP Codes............................................. 86
+ 12.4. Result-Code AVP Values................................ 86
+ 12.5. CC-Request-Type AVP................................... 86
+ 12.6. CC-Session-Failover AVP............................... 86
+ 12.7. CC-Unit-Type AVP...................................... 87
+ 12.8. Check-Balance-Result AVP.............................. 87
+ 12.9. Credit-Control AVP.................................... 87
+ 12.10. Credit-Control-Failure-Handling AVP................... 87
+ 12.11. Direct-Debiting-Failure-Handling AVP.................. 87
+ 12.12. Final-Unit-Action AVP................................. 87
+ 12.13. Multiple-Services-Indicator AVP....................... 87
+ 12.14. Redirect-Address-Type AVP............................. 88
+ 12.15. Requested-Action AVP.................................. 88
+ 12.16. Subscription-Id-Type AVP.............................. 88
+ 12.17. Tariff-Change-Usage AVP............................... 88
+ 12.18. User-Equipment-Info-Type AVP.......................... 88
+ 13. Credit-Control Application Related Parameters................ 88
+ 14. Security Considerations...................................... 89
+ 14.1. Direct Connection with Redirects...................... 90
+ 15. References................................................... 91
+ 15.1. Normative References.................................. 91
+ 15.2. Informative References................................ 92
+ 16. Acknowledgements............................................. 93
+ Appendix A Credit-Control Sequences.............................. 94
+
+
+
+Hakala, et al. Standards Track [Page 3]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ A.1. Flow I................................................ 94
+ A.2. Flow II............................................... 96
+ A.3. Flow III.............................................. 98
+ A.4. Flow IV............................................... 99
+ A.5. Flow V................................................ 100
+ A.6. Flow VI............................................... 102
+ A.7. Flow VII.............................................. 103
+ A.8. Flow VIII............................................. 105
+ A.9. Flow IX............................................... 107
+ Authors' Addresses............................................... 112
+ Full Copyright Statement......................................... 114
+
+1. Introduction
+
+ This document specifies a Diameter application that can be used to
+ implement real-time credit-control for a variety of end user services
+ such as network access, Session Initiation Protocol (SIP) services,
+ messaging services, and download services. It provides a general
+ solution to real-time cost and credit-control.
+
+ The prepaid model has been shown to be very successful, for instance,
+ in GSM networks, where network operators offering prepaid services
+ have experienced a substantial growth of their customer base and
+ revenues. Prepaid services are now cropping up in many other
+ wireless and wire line based networks.
+
+ In next generation wireless networks, additional functionality is
+ required beyond that specified in the Diameter base protocol. For
+ example, the 3GPP Charging and Billing requirements [3GPPCHARG] state
+ that an application must be able to rate service information in
+ real-time. In addition, it is necessary to check that the end user's
+ account provides coverage for the requested service prior to
+ initiation of that service. When an account is exhausted or expired,
+ the user must be denied the ability to compile additional chargeable
+ events.
+
+ A mechanism has to be provided to allow the user to be informed of
+ the charges to be levied for a requested service. In addition, there
+ are services such as gaming and advertising that may credit as well
+ as debit a user account.
+
+ The other Diameter applications provide service specific
+ authorization, and they do not provide credit authorization for
+ prepaid users. The credit authorization shall be generic and
+ applicable to all the service environments required to support
+ prepaid services.
+
+
+
+
+
+Hakala, et al. Standards Track [Page 4]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ To fulfill these requirements, it is necessary to facilitate credit-
+ control communication between the network element providing the
+ service (e.g., Network Access Server, SIP Proxy, and Application
+ Server) and a credit-control server.
+
+ The scope of this specification is the credit authorization. Service
+ specific authorization and authentication is out of the scope.
+
+1.1. Requirements Language
+
+ In this document, the key words "MAY", "MUST, "MUST NOT", "OPTIONAL",
+ "RECOMMENDED", "SHOULD", and "SHOULD NOT", are to be interpreted as
+ described in [KEYWORDS].
+
+1.2. Terminology
+
+ AAA
+
+ Authentication, Authorization, and Accounting
+
+ AA answer
+
+ AA answer generically refers to a service specific authorization and
+ authentication answer. AA answer commands are defined in service
+ specific authorization applications, e.g., [NASREQ] and [DIAMMIP].
+
+ AA request
+
+ AA request generically refers to a service specific authorization and
+ authentication request. AA request commands are defined in service
+ specific authorization applications e.g., [NASREQ] and [DIAMMIP].
+
+ Credit-control
+
+ Credit-control is a mechanism that directly interacts in real-time
+ with an account and controls or monitors the charges related to the
+ service usage. Credit-control is a process of checking whether
+ credit is available, credit-reservation, deduction of credit from the
+ end user account when service is completed and refunding of reserved
+ credit that is not used.
+
+ Diameter Credit-control Server
+
+ A Diameter credit-control server acts as a prepaid server, performing
+ real-time rating and credit-control. It is located in the home
+ domain and is accessed by service elements or Diameter AAA servers in
+
+
+
+
+
+Hakala, et al. Standards Track [Page 5]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ real-time for purpose of price determination and credit-control
+ before the service event is delivered to the end-user. It may also
+ interact with business support systems.
+
+ Diameter Credit-control Client
+
+ A Diameter credit-control client is an entity that interacts with a
+ credit-control server. It monitors the usage of the granted quota
+ according to instructions returned by credit-control server.
+
+ Interrogation
+
+ The Diameter credit-control client uses interrogation to initiate a
+ session based credit-control process. During the credit-control
+ process, it is used to report the used quota and request a new one.
+ An interrogation maps to a request/answer transaction.
+
+ One-time event
+
+ Basically, a request/answer transaction of type event.
+
+ Rating
+
+ The act of determining the cost of the service event.
+
+ Service
+
+ A type of task performed by a service element for an end user.
+
+ Service Element
+
+ A network element that provides a service to the end users. The
+ Service Element may include the Diameter credit-control client, or
+ another entity (e.g., RADIUS AAA server) that can act as a Credit-
+ control client on behalf of the Service Element. In the latter case,
+ the interface between the Service Element and the Diameter credit-
+ control client is outside the scope of this specification. Examples
+ of the Service Elements include Network Access Server (NAS), SIP
+ Proxy, and Application Servers such as messaging server, content
+ server, and gaming server.
+
+ Service Event
+
+ An event relating to a service provided to the end user.
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 6]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ Session based credit-control
+
+ A credit-control process that makes use of several interrogations:
+ the first, a possible intermediate, and the final. The first
+ interrogation is used to reserve money from the user's account and to
+ initiate the process. The intermediate interrogations may be needed
+ to request new quota while the service is being rendered. The final
+ interrogation is used to exit the process. The credit-control server
+ is required to maintain session state for session-based credit-
+ control.
+
+1.3. Advertising Application Support
+
+ Diameter nodes conforming to this specification MUST advertise
+ support by including the value of 4 in the Auth-Application-Id of the
+ Capabilities-Exchange-Request and Capabilities-Exchange-Answer
+ command [DIAMBASE].
+
+2. Architecture Models
+
+ The current accounting models specified in the Radius Accounting
+ [RFC2866] and Diameter base [DIAMBASE] are not sufficient for real-
+ time credit-control, where credit-worthiness is to be determined
+ prior to service initiation. Also, the existing Diameter
+ authorization applications, [NASREQ] and [DIAMMIP], only provide
+ service authorization, but do not provide credit authorization for
+ prepaid users. In order to support real-time credit-control, a new
+ type of server is needed in the AAA infrastructure: Diameter credit-
+ control server. The Diameter credit-control server is the entity
+ responsible for credit authorization for prepaid subscribers.
+
+ A service element may authenticate and authorize the end user with
+ the AAA server by using AAA protocols; e.g., RADIUS or a Diameter
+ base protocol with a possible Diameter application.
+
+ Accounting protocols such as RADIUS accounting and the Diameter base
+ accounting protocol can be used to provide accounting data to the
+ accounting server after service is initiated, and to provide possible
+ interim reports until service completion. However, for real-time
+ credit-control, these authorization and accounting models are not
+ sufficient.
+
+ When real-time credit-control is required, the credit-control client
+ contacts the credit-control server with information about a possible
+ service event. The credit-control process is performed to determine
+ potential charges and to verify whether the end user's account
+ balance is sufficient to cover the cost of the service being
+ rendered.
+
+
+
+Hakala, et al. Standards Track [Page 7]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ Figure 1 illustrates the typical credit-control architecture, which
+ consists of a Service Element with an embedded Diameter credit-
+ control client, a Diameter credit-control server, and an AAA server.
+ A Business Support System is usually deployed; it includes at least
+ the billing functionality. The credit-control server and AAA server
+ in this architecture model are logical entities. The real
+ configuration can combine them into a single host. The credit-
+ control protocol is the Diameter base protocol with the Diameter
+ credit-control application.
+
+ When an end user requests services such as SIP or messaging, the
+ request is typically forwarded to a service element (e.g., SIP Proxy)
+ in the user's home domain. In some cases it might be possible that
+ the service element in the visited domain can offer services to the
+ end user; however, a commercial agreement must exist between the
+ visited domain and the home domain. Network access is an example of
+ a service offered in the visited domain where the NAS, through an AAA
+ infrastructure, authenticates and authorizes the user with the user's
+ home network.
+
+ Service Element AAA and CC
+ +----------+ +---------+ Protocols+-----------+ +--------+
+ | End |<---->|+-------+|<------------>| AAA | |Business|
+ | User | +->|| CC || | Server |->|Support |
+ | | | || Client||<-----+ | | |System |
+ +----------+ | |+-------+| | +-----------+ | |
+ | +---------+ | ^ +--------+
+ +----------+ | | CC Protocol | ^
+ | End |<--+ | +-----v----+ |
+ | User | +------>|Credit- | |
+ +----------+ Credit-Control |Control |--------+
+ Protocol |Server |
+ +----------+
+
+ Figure 1: Typical credit-control architecture
+
+ There can be multiple credit-control servers in the system for
+ redundancy and load balancing. The system can also contain separate
+ rating server(s), and accounts can be located in a centralized
+ database. To ensure that the end user's account is not debited or
+ credited multiple times for the same service event, only one place in
+ the credit-control system should perform duplicate detection. System
+ internal interfaces can exist to relay messages between servers and
+ an account manager. However, the detailed architecture of the
+ credit-control system and its interfaces are implementation specific
+ and are out of scope of this specification.
+
+
+
+
+
+Hakala, et al. Standards Track [Page 8]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ Protocol transparent Diameter relays can exist between the credit-
+ control client and credit-control server. Also, Diameter Redirect
+ agents that refer credit-control clients to credit-control servers
+ and allow them to communicate directly can exist. These agents
+ transparently support the Diameter credit-control application. The
+ different roles of Diameter Agents are defined in Diameter base
+ [DIAMBASE], section 2.8.
+
+ If Diameter credit-control proxies exist between the credit-control
+ client and the credit-control server, they MUST advertise the
+ Diameter credit-control application support.
+
+3. Credit-Control Messages
+
+ This section defines new Diameter message Command-Code values that
+ MUST be supported by all Diameter implementations that conform to
+ this specification. The Command Codes are as follows:
+
+ Command-Name Abbrev. Code Reference
+ -----------------------------------------------------------
+ Credit-Control-Request CCR 272 3.1
+ Credit-Control-Answer CCA 272 3.2
+
+ Diameter Base [DIAMBASE] defines in the section 3.2 the Command Code
+ ABNF specification. These formats are observed in Credit-Control
+ messages.
+
+3.1. Credit-Control-Request (CCR) Command
+
+ The Credit-Control-Request message (CCR) is indicated by the
+ command-code field being set to 272 and the 'R' bit being set in the
+ Command Flags field. It is used between the Diameter credit-control
+ client and the credit-control server to request credit authorization
+ for a given service.
+
+ The Auth-Application-Id MUST be set to the value 4, indicating the
+ Diameter credit-control application.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 9]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ Message Format
+
+ <Credit-Control-Request> ::= < Diameter Header: 272, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Auth-Application-Id }
+ { Service-Context-Id }
+ { CC-Request-Type }
+ { CC-Request-Number }
+ [ Destination-Host ]
+ [ User-Name ]
+ [ CC-Sub-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Origin-State-Id ]
+ [ Event-Timestamp ]
+ *[ Subscription-Id ]
+ [ Service-Identifier ]
+ [ Termination-Cause ]
+ [ Requested-Service-Unit ]
+ [ Requested-Action ]
+ *[ Used-Service-Unit ]
+ [ Multiple-Services-Indicator ]
+ *[ Multiple-Services-Credit-Control ]
+ *[ Service-Parameter-Info ]
+ [ CC-Correlation-Id ]
+ [ User-Equipment-Info ]
+ *[ Proxy-Info ]
+ *[ Route-Record ]
+ *[ AVP ]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 10]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+3.2. Credit-Control-Answer (CCA) Command
+
+ The Credit-Control-Answer message (CCA) is indicated by the command-
+ code field being set to 272 and the 'R' bit being cleared in the
+ Command Flags field. It is used between the credit-control server
+ and the Diameter credit-control client to acknowledge a Credit-
+ Control-Request command.
+
+ Message Format
+
+ <Credit-Control-Answer> ::= < Diameter Header: 272, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ { Auth-Application-Id }
+ { CC-Request-Type }
+ { CC-Request-Number }
+ [ User-Name ]
+ [ CC-Session-Failover ]
+ [ CC-Sub-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Origin-State-Id ]
+ [ Event-Timestamp ]
+ [ Granted-Service-Unit ]
+ *[ Multiple-Services-Credit-Control ]
+ [ Cost-Information]
+ [ Final-Unit-Indication ]
+ [ Check-Balance-Result ]
+ [ Credit-Control-Failure-Handling ]
+ [ Direct-Debiting-Failure-Handling ]
+ [ Validity-Time]
+ *[ Redirect-Host]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ *[ Proxy-Info ]
+ *[ Route-Record ]
+ *[ Failed-AVP ]
+ *[ AVP ]
+
+4. Credit-Control Application Overview
+
+ The credit authorization process takes place before and during
+ service delivery to the end user and generally requires the user's
+ authentication and authorization before any request is sent to the
+ credit-control server. The credit-control application defined in
+ this specification supports two different credit authorization
+ models: credit authorization with money reservation and credit
+
+
+
+Hakala, et al. Standards Track [Page 11]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ authorization with direct debiting. In both models, the credit-
+ control client requests credit authorization from the credit-control
+ server prior to allowing any service to be delivered to the end user.
+
+ In the first model, the credit-control server rates the request,
+ reserves a suitable amount of money from the user's account, and
+ returns the corresponding amount of credit resources. Note that
+ credit resources may not imply actual monetary credit; credit
+ resources may be granted to the credit control client in the form of
+ units (e.g., data volume or time) to be metered.
+
+ Upon receipt of a successful credit authorization answer with a
+ certain amount of credit resources, the credit-control client allows
+ service delivery to the end user and starts monitoring the usage of
+ the granted resources. When the credit resources granted to the user
+ have been consumed or the service has been successfully delivered or
+ terminated, the credit-control client reports back to the server the
+ used amount. The credit-control server deducts the used amount from
+ the end user's account; it may perform rating and make a new credit
+ reservation if the service delivery is continuing. This process is
+ accomplished with session based credit-control that includes the
+ first interrogation, possible intermediate interrogations, and the
+ final interrogation. For session based credit-control, both the
+ credit control client and the credit-control server are required to
+ maintain credit-control session state. Session based credit-control
+ is described in more detail, with more variations, in section 5.
+
+ In contrast, credit authorization with direct debiting is a single
+ transaction process wherein the credit-control server directly
+ deducts a suitable amount of money from the user's account as soon as
+ the credit authorization request is received. Upon receipt of a
+ successful credit authorization answer, the credit-control client
+ allows service delivery to the end user. This process is
+ accomplished with the one-time event. Session state is not
+ maintained.
+
+ In a multi-service environment, an end user can issue an additional
+ service request (e.g., data service) during an ongoing service (e.g.,
+ voice call) toward the same account. Alternatively, during an active
+ multimedia session, an additional media type is added to the session,
+ causing a new simultaneous request toward same account.
+ Consequently, this needs to be considered when credit resources are
+ granted to the services.
+
+ The credit-control application also supports operations such as
+ service price enquiry, user's balance check, and refund of credit on
+ the user's account. These operations are accomplished with the one-
+ time event. Session state is not maintained.
+
+
+
+Hakala, et al. Standards Track [Page 12]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ A flexible credit-control application specific failure handling is
+ defined in which the home service provider can model the credit-
+ control client behavior according to its own credit risk management
+ policy.
+
+ The Credit-Control-Failure-Handling AVP and the Direct-Debiting-
+ Failure-Handling AVP are defined to determine what is done if the
+ sending of credit-control messages to the credit-control server has
+ been temporarily prevented. The usage of the Credit-Control-
+ Failure-Handling AVP and the Direct-Debiting-Failure-Handling AVP
+ allows flexibility, as failure handling for the credit-control
+ session and one time event direct debiting may be different.
+
+4.1. Service-Specific Rating Input and Interoperability
+
+ The Diameter credit-control application defines the framework for
+ credit-control; it provides generic credit-control mechanisms
+ supporting multiple service applications. The credit-control
+ application, therefore, does not define AVPs that could be used as
+ input in the rating process. Listing the possible services that
+ could use this Diameter application is out of scope for this generic
+ mechanism.
+
+ It is reasonable to expect that a service level agreement will exist
+ between providers of the credit-control client and the credit-control
+ server covering the charging, services offered, roaming agreements,
+ agreed rating input (i.e., AVPs), and so on.
+
+ Therefore, it is assumed that a Diameter credit-control server will
+ provide service only for Diameter credit-control clients that have
+ agreed beforehand as to the content of credit-control messages.
+ Naturally, it is possible that any arbitrary Diameter credit-control
+ client can interchange credit-control messages with any Diameter
+ credit-control server, but with a higher likelihood that unsupported
+ services/AVPs could be present in the credit-control message, causing
+ the server to reject the request with an appropriate result-code.
+
+4.1.1. Specifying Rating Input AVPs
+
+ There are two ways to provide rating input to the credit-control
+ server: either by using AVPs or by including them in the Service-
+ Parameter-Info AVP. The general principles for sending rating
+ parameters are as follows:
+
+ 1a. The service SHOULD re-use existing AVPs if it can use AVPs
+ defined in existing Diameter applications (e.g., NASREQ for network
+ access services). Re-use of existing AVPs is strongly recommended in
+ [DIAMBASE].
+
+
+
+Hakala, et al. Standards Track [Page 13]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ For AVPs of type Enumerated, the service may require a new value to
+ be defined. Allocation of new AVP values is done as specified in
+ [DIAMBASE], section 1.2.
+
+ 1b. New AVPs can be defined if the existing AVPs do not provide
+ sufficient rating information. In this case, the procedures defined
+ in [DIAMBASE] for creating new AVPs MUST be followed.
+
+ 1c. For services specific only to one vendor's implementation, a
+ Vendor-Specific AVP code for Private use can be used. Where a
+ Vendor-Specific AVP is implemented by more than one vendor,
+ allocation of global AVPs is encouraged instead; refer to [DIAMBASE].
+
+ 2. The Service-Parameter-Info AVP MAY be used as a container to pass
+ legacy rating information in its original encoded form (e.g., ASN.1
+ BER). This method can be used to avoid unnecessary conversions from
+ an existing data format to an AVP format. In this case, the rating
+ input is embedded in the Service-Parameter-Info AVP as defined in
+ section 8.43.
+
+ New service applications SHOULD favor the use of explicitly defined
+ AVPs as described in items 1a and 1b, to simplify interoperability.
+
+4.1.2. Service-Specific Documentation
+
+ The service specific rating input AVPs, the contents of the Service-
+ Parameter-Info AVP or Service-Context-Id AVP (defined in section
+ 8.42) are not within the scope of this document. To facilitate
+ interoperability, it is RECOMMENDED that the rating input and the
+ values of the Service-Context-Id be coordinated via an informational
+ RFC or other permanent and readily available reference. The
+ specification of another cooperative standardization body (e.g.,
+ 3GPP, OMA, and 3GPP2) SHOULD be used. However, private services may
+ be deployed that are subject to agreements between providers of the
+ credit-control server and client. In this case, vendor specific AVPs
+ can be used.
+
+ This specification, together with the above service specific
+ documents, governs the credit-control message. Service specific
+ documents define which existing AVPs or new AVPs are used as input to
+ the rating process (i.e., those that do not define new credit-control
+ applications), and thus have to be included in the Credit-Control-
+ Request command by a Diameter credit-control client supporting a
+ given service as *[AVP]. Should Service-Parameter-Info be used, then
+ the service specific document MUST specify the exact content of this
+ grouped AVP.
+
+
+
+
+
+Hakala, et al. Standards Track [Page 14]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ The Service-Context-Id AVP MUST be included at the command level of a
+ Credit-Control Request to identify the service specific document that
+ applies to the request. The specific service or rating group the
+ request relates to is uniquely identified by the combination of
+ Service-Context-Id and Service-Identifier or Rating-Group.
+
+4.1.3. Handling of Unsupported/Incorrect Rating Input
+
+ Diameter credit-control implementations are required to support the
+ Mandatory rating AVPs defined in service specific documentation of
+ the services they support, according to the 'M' bit rules in
+ [DIAMBASE].
+
+ If a rating input required for the rating process is incorrect in the
+ Credit-control request, or if the credit-control server does not
+ support the requested service context (identified by the Service-
+ Context-Id AVP at command level), the Credit-control answer MUST
+ contain the error code DIAMETER_RATING_FAILED. A CCA message with
+ this error MUST contain one or more Failed-AVP AVPs containing the
+ missing and/or unsupported AVPs that caused the failure. A Diameter
+ credit-control client that receives the error code
+ DIAMETER_RATING_FAILED in response to a request MUST NOT send similar
+ requests in the future.
+
+4.1.4. RADIUS Vendor-Specific Rating Attributes
+
+ When service specific documents include RADIUS vendor specific
+ attributes that could be used as input in the rating process, the
+ rules described in [NASREQ] for formatting the Diameter AVP MUST be
+ followed.
+
+ For example, if the AVP code used is the vendor attribute type code,
+ the Vendor-Specific flag MUST be set to 1 and the Vendor-ID MUST be
+ set to the IANA Vendor identification value. The Diameter AVP data
+ field contains only the attribute value of the RADIUS attribute.
+
+5. Session Based Credit-Control
+
+5.1. General Principles
+
+ For a session-based credit-control, several interrogations are
+ needed: the first, intermediate (optional) and the final
+ interrogations. This is illustrated in Figures 2 and 3.
+
+ If the credit-control client performs credit-reservation before
+ granting service to the end user, it MUST use several interrogations
+ toward the credit-control server (i.e., session based credit-
+
+
+
+
+Hakala, et al. Standards Track [Page 15]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ control). In this case, the credit-control server MUST maintain the
+ credit-control session state.
+
+ Each credit-control session MUST have a globally unique Session-Id as
+ defined in [DIAMBASE], which MUST NOT be changed during the lifetime
+ of a credit-control session.
+
+ Certain applications require multiple credit-control sub-sessions.
+ These applications would send messages with a constant Session-Id
+ AVP, but with a different CC-Sub-Session-Id AVP. If several credit
+ sub-sessions will be used, all sub-sessions MUST be closed separately
+ before the main session is closed so that units per sub-session may
+ be reported. The absence of this AVP implies that no sub-sessions
+ are in use.
+
+ Note that the service element might send a service specific re-
+ authorization message to the AAA server due to expiration of the
+ authorization-lifetime during an ongoing credit-control session.
+ However, the service specific re-authorization does not influence the
+ credit authorization that is ongoing between the credit-control
+ client and credit-control server, as credit authorization is
+ controlled by the burning rate of the granted quota.
+
+ If service specific re-authorization fails, the user will be
+ disconnected, and the credit-control client MUST send a final
+ interrogation to the credit-control server.
+
+ The Diameter credit-control server may seek to control the validity
+ time of the granted quota and/or the production of intermediate
+ interrogations. Thus, it MAY include the Validity-Time AVP in the
+ answer message to the credit-control client. Upon expiration of the
+ Validity-Time, the credit-control client MUST generate a credit-
+ control update request and report the used quota to the credit-
+ control server. It is up to the credit-control server to determine
+ the value of the Validity-Time to be used for consumption of the
+ granted service units. If the Validity-Time is used, its value
+ SHOULD be given as input to set the session supervision timer Tcc
+ (the session supervision timer MAY be set to two times the value of
+ the Validity-Time, as defined in section 13). Since credit-control
+ update requests are also produced at the expiry of granted service
+ units and/or for mid-session service events, the omission of
+ Validity-Time does not mean that intermediate interrogation for the
+ purpose of credit-control is not performed.
+
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 16]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+5.1.1. Basic Tariff-Time Change Support
+
+ The Diameter credit-control server and client MAY optionally support
+ a tariff change mechanism. The Diameter credit-control server may
+ include a Tariff-Time-Change AVP in the answer message. Note that
+ the granted units should be allocated based on the worst-case
+ scenario in case of forthcoming tariff change, so that the overall
+ reported used units would never exceed the credit reservation.
+
+ When the Diameter credit-control client reports the used units and a
+ tariff change has occurred during the reporting period, the Diameter
+ credit-control client MUST separately itemize the units used before
+ and after the tariff change. If the client is unable to distinguish
+ whether units straddling the tariff change were used before or after
+ the tariff change, the credit-control client MUST itemize those units
+ in a third category.
+
+ If a client does not support the tariff change mechanism and it
+ receives a CCA message carrying the Tariff-Time-Change AVP, it MUST
+ terminate the credit-control session, giving a reason of
+ DIAMETER_BAD_ANSWER in the Termination-Cause AVP.
+
+ For time based services, the quota is continuously consumed at the
+ regular rate of 60 seconds per minute. At the time when credit
+ resources are allocated, the server already knows how many units will
+ be consumed before the tariff time change and how many units will be
+ consumed afterward. Similarly, the server can determine the units
+ consumed at the before rate and the units consumed at the rate
+ afterward in the event that the end-user closes the session before
+ the consumption of the allotted quota. There is no need for
+ additional traffic between client and server in the case of tariff
+ time changes for continuous time based service. Therefore, the
+ tariff change mechanism is not used for such services. For time-
+ based services in which the quota is NOT continuously consumed at a
+ regular rate, the tariff change mechanism described for volume and
+ event units MAY be used.
+
+5.1.2. Credit-Control for Multiple Services within a (sub-)Session
+
+ When multiple services are used within the same user session and each
+ service or group of services is subject to different cost, it is
+ necessary to perform credit-control for each service independently.
+ Making use of credit-control sub-sessions to achieve independent
+ credit-control will result in increased signaling load and usage of
+ resources in both the credit-control client and the credit-control
+ server. For instance, during one network access session the end user
+ may use several http-services subject to different access cost. The
+ network access specific attributes such as the quality of service
+
+
+
+Hakala, et al. Standards Track [Page 17]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ (QoS) are common to all the services carried within the access
+ bearer, but the cost of the bearer may vary depending on its content.
+
+ To support these scenarios optimally, the credit-control application
+ enables independent credit-control of multiple services in a single
+ credit-control (sub-)session. This is achieved by including the
+ optional Multiple-Services-Credit-Control AVP in Credit-Control-
+ Request/Answer messages. It is possible to request and allocate
+ resources as a credit pool shared between multiple services. The
+ services can be grouped into rating groups in order to achieve even
+ further aggregation of credit allocation. It is also possible to
+ request and allocate quotas on a per service basis. Where quotas are
+ allocated to a pool by means of the Multiple-Services-Credit-Control
+ AVP, the quotas remain independent objects that can be re-authorized
+ independently at any time. Quotas can also be given independent
+ result codes, validity times, and Final-Unit-Indications.
+
+ A Rating-Group gathers a set of services, identified by a Service-
+ Identifier, and subject to the same cost and rating type (e.g.,
+ $0.1/minute). It is assumed that the service element is provided
+ with Rating-Groups, Service-Identifiers, and their associated
+ parameters that define what has to be metered by means outside the
+ scope of this specification. (Examples of parameters associated to
+ Service-Identifiers are IP 5-tuple and HTTP URL.) Service-Identifiers
+ enable authorization on a per-service based credit as well as
+ itemized reporting of service usage. It is up to the credit-control
+ server whether to authorize credit for one or more services or for
+ the whole rating-group. However, the client SHOULD always report
+ used units at the finest supported level of granularity. Where quota
+ is allocated to a rating-group, all the services belonging to that
+ group draw from the allotted quota. The following is a graphical
+ representation of the relationship between service-identifiers,
+ rating-groups, credit pools, and credit-control (sub-)session.
+
+ DCC (Sub-)Session
+ |
+ +------------+-----------+-------------+--------------- +
+ | | | | |
+ Service-Id a Service-Id b Service-Id c Service-Id d.....Service-Id z
+ \ / \ / /
+ \ / \ / /
+ \ / Rating-Group 1.......Rating-Group n
+ \ / | |
+ Quota ---------------Quota Quota
+ | / |
+ | / |
+ Credit-Pool Credit-Pool
+
+
+
+
+Hakala, et al. Standards Track [Page 18]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ If independent credit-control of multiple services is used, the
+ validity-time and final-unit-indication SHOULD be present either in
+ the Multiple-Services-Credit-Control AVP(s) or at command level as
+ single AVPs. However, the Result-Code AVP MAY be present both on the
+ command level and within the Multiple-Services-Credit-Control AVP.
+ If the Result-Code on the command level indicates a value other than
+ SUCCESS, then the Result-Code on command level takes precedence over
+ any included in the Multiple-Services-Credit-Control AVP.
+
+ The credit-control client MUST indicate support for independent
+ credit-control of multiple services within a (sub-)session by
+ including the Multiple-Services-Indicator AVP in the first
+ interrogation. A credit-control server not supporting this feature
+ MUST treat the Multiple-Services-Indicator AVP and any received
+ Multiple-Services-Credit-Control AVPs as invalid AVPs.
+
+ If the client indicated support for independent credit-control of
+ multiple services, a credit-control server that wishes to use the
+ feature MUST return the granted units within the Multiple-Services-
+ Credit-Control AVP associated to the corresponding service-identifier
+ and/or rating-group.
+
+ To avoid a situation where several parallel (and typically also
+ small) credit reservations must be made on the same account (i.e.,
+ credit fragmentation), and also to avoid unnecessary load on the
+ credit-control server, it is possible to provide service units as a
+ pool that applies to multiple services or rating groups. This is
+ achieved by providing the service units in the form of a quota for a
+ particular service or rating group in the Multiple-Services-Credit-
+ Control AVP, and also by including a reference to a credit pool for
+ that unit type.
+
+ The reference includes a multiplier derived from the rating
+ parameter, which translates from service units of a specific type to
+ the abstract service units in the pool. For instance, if the rating
+ parameter for service 1 is $1/MB and the rating parameter for service
+ 2 is $0.5/MB, the multipliers could be 10 and 5 for services 1 and 2,
+ respectively.
+
+ If S is the total service units within the pool, M1, M2, ..., Mn are
+ the multipliers provided for services 1, 2, ..., n, and C1, C2, ...,
+ Cn are the used resources within the session, then the pool credit is
+ exhausted and re-authorization MUST be sought when:
+
+ C1*M1 + C2*M2 + ... + Cn*Mn >= S
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 19]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ The total credit in the pool, S, is calculated from the quotas, which
+ are currently allocated to the pool as follows:
+
+ S = Q1*M1 + Q2*M2 + ... + Qn*Mn
+
+ If services or rating groups are added to or removed from the pool,
+ then the total credit is adjusted appropriately. Note that when the
+ total credit is adjusted because services or rating groups are
+ removed from the pool, the value that need to be removed is the
+ consumed one (i.e., Cx*Mx).
+
+ Re-authorizations for an individual service or rating group may be
+ sought at any time; for example, if a 'non-pooled' quota is used up
+ or the Validity-Time expires.
+
+ Where multiple G-S-U-Pool-Reference AVPs (section 8.30) with the same
+ G-S-U-Pool-Identifier are provided within a Multiple-Services-
+ Credit-Control AVP (section 8.16) along with the Granted-Service-Unit
+ AVP, then these MUST have different CC-Unit-Type values, and they all
+ draw from the credit pool separately. For instance, if one
+ multiplier for time (M1t) and one multiplier for volume (M1v) are
+ given, then the used resources from the pool is the sum C1t*M1t +
+ C1v*M1v, where C1t is the time unit and C1v is the volume unit.
+
+ Where service units are provided within a Multiple-Services-Credit-
+ Control AVP without a corresponding G-S-U-Pool-Reference AVP, then
+ these are handled independently from any credit pool and from any
+ other services or rating groups within the session.
+
+ The credit pool concept is an optimal tool to avoid the over-
+ reservation effect of the basic single quota tariff time change
+ mechanism (the mechanism described in section 5.1.1). Therefore,
+ Diameter credit-control clients and servers implementing the
+ independent credit-control of multiple services SHOULD leverage the
+ credit pool concept when supporting the tariff time change. The
+ Diameter credit-control server SHOULD include both the Tariff-Time-
+ Change and Tariff-Change-Usage AVPs in two quota allocations in the
+ answer message (i.e., two instances of the Multiple-Services-Credit-
+ Control AVP). One of the granted units is allocated to be used
+ before the potential tariff change, while the second granted units
+ are for use after a tariff change. Both granted unit quotas MUST
+ contain the same Service-Identifier and/or Rating-Group. This dual
+ quota mechanism ensures that the overall reported used units would
+ never exceed the credit reservation. The Diameter credit-control
+ client reports both the used units before and after the tariff change
+ in a single instance of the Multiple-Services-Credit-Control AVP.
+
+
+
+
+
+Hakala, et al. Standards Track [Page 20]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ The failure handling for credit-control sessions is defined in
+ section 5.7 and reflected in the basic credit-control state machine
+ in section 7. Credit-control clients and servers implementing the
+ independent credit-control of multiple services in a (sub-)session
+ functionality MUST ensure failure handling and general behavior fully
+ consistent with the above mentioned sections, while maintaining the
+ ability to handle parallel ongoing credit re-authorization within a
+ (sub-)session. Therefore, it is RECOMMENDED that Diameter credit-
+ control clients maintain a PendingU message queue and restart the Tx
+ timer (section 13) every time a CCR message with the value
+ UPDATE_REQUEST is sent while they are in PendingU state. When
+ answers to all pending messages are received, the state machine moves
+ to OPEN state, and Tx is stopped. Naturally, the action performed
+ when a problem for the session is detected according to section 5.7
+ affects all the ongoing services (e.g., failover to a backup server
+ if possible affect all the CCR messages with the value UPDATE_REQUEST
+ in the PendingU queue).
+
+ Since the client may send CCR messages with the value UPDATE_REQUEST
+ while in PendingU (i.e., without waiting for an answer to ongoing
+ credit re-authorization), the time space between these requests may
+ be very short, and the server may not have received the previous
+ request(s) yet. Therefore, in this situation the server may receive
+ out of sequence requests and SHOULD NOT consider this an error
+ condition. A proper answer is to be returned to each of those
+ requests.
+
+5.2. First Interrogation
+
+ When session based credit-control is required (e.g., the
+ authentication server indicated a prepaid user), the first
+ interrogation MUST be sent before the Diameter credit-control client
+ allows any service event to the end user. The CC-Request-Type is set
+ to the value INITIAL_REQUEST in the request message.
+
+ If the Diameter credit-control client knows the cost of the service
+ event (e.g., a content server delivering ringing tones may know their
+ cost) the monetary amount to be charged is included in the
+ Requested-Service-Unit AVP. If the Diameter credit-control client
+ does not know the cost of the service event, the Requested-Service-
+ Unit AVP MAY contain the number of requested service events. Where
+ the Multiple-Services-Credit-Control AVP is used, it MUST contain the
+ Requested-Service-Unit AVP to indicate that the quota for the
+ associated service/rating-group is requested. In the case of
+ multiple services, the Service-Identifier AVP or the Rating-Group AVP
+ within the Multiple-Services-Credit-Control AVP always indicates the
+ service concerned. Additional service event information to be rated
+
+
+
+
+Hakala, et al. Standards Track [Page 21]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ MAY be sent as service specific AVPs or MAY be sent within the
+ Service-Parameter-Info AVP at command level. The Service-Context-Id
+ AVP indicates the service specific document applicable to the
+ request.
+
+ The Event-Timestamp AVP SHOULD be included in the request and
+ contains the time when the service event is requested in the service
+ element. The Subscription-Id AVP SHOULD be included to identify the
+ end user in the credit-control server. The credit-control client MAY
+ include the User-Equipment-Info AVP so that the credit-control server
+ has some indication of the type and capabilities of the end user
+ access device. How the credit-control server uses this information
+ is outside the scope of this document.
+
+ The credit-control server SHOULD rate the service event and make a
+ credit-reservation from the end user's account that covers the cost
+ of the service event. If the type of the Requested-Service-Unit AVP
+ is money, no rating is needed, but the corresponding monetary amount
+ is reserved from the end user's account.
+
+ The credit-control server returns the Granted-Service-Unit AVP in the
+ Answer message to the Diameter credit-control client. The Granted-
+ Service-Unit AVP contains the amount of service units that the
+ Diameter credit-control client can provide to the end user until a
+ new Credit-Control-Request MUST be sent to the credit-control server.
+ If several unit types are sent in the Answer message, the credit-
+ control client MUST handle each unit type separately. The type of
+ the Granted-Service-Unit AVP can be time, volume, service specific,
+ or money, depending on the type of service event. The unit type(s)
+ SHOULD NOT be changed within an ongoing credit-control session.
+
+ There MUST be a maximum of one instance of the same unit type in one
+ Answer message. However, if multiple quotas are conveyed to the
+ credit-control client in the Multiple-Services-Credit-Control AVPs,
+ it is possible to carry two instances of the same unit type
+ associated to a service-identifier/rating-group. This is typically
+ the case when a tariff time change is expected and the credit-control
+ server wants to make a distinction between the granted quota before
+ and after tariff change.
+
+ If the credit-control server determines that no further control is
+ needed for the service, it MAY include the result code indicating
+ that the credit-control is not applicable (e.g., if the service is
+ free of charge). This result code at command level implies that the
+ credit-control session is to be terminated.
+
+ The Credit-Control-Answer message MAY also include the Final-Unit-
+ Indication AVP to indicate that the answer message contains the final
+
+
+
+Hakala, et al. Standards Track [Page 22]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ units for the service. After the end user has consumed these units,
+ the Diameter credit-control-client MUST behave as described in
+ section 5.6.
+
+ This document defines two different approaches to perform the first
+ interrogation to be used in different network architectures. The
+ first approach uses credit-control messages after the user's
+ authorization and authentication takes place. The second approach
+ uses service specific authorization messages to perform the first
+ interrogation during the user's authorization/authentication phase,
+ and credit-control messages for the intermediate and final
+ interrogations. If an implementation of the credit-control client
+ supports both the methods, determining which method to use SHOULD be
+ configurable.
+
+ In service environments such as the Network Access Server (NAS), it
+ is desired to perform the first interrogation as part of the
+ authorization/authentication process for the sake of protocol
+ efficiency. Further credit authorizations after the first
+ interrogation are performed with credit-control commands defined in
+ this specification. Implementations of credit-control clients
+ operating in the mentioned environments SHOULD support this method.
+ If the credit-control server and AAA server are separate physical
+ entities, the service element sends the request messages to the AAA
+ server, which then issues an appropriate request or proxies the
+ received request forward to the credit-control server.
+
+ In other service environments, such as the 3GPP network and some SIP
+ scenarios, there is a substantial decoupling between
+ registration/access to the network and the actual service request
+ (i.e., the authentication/authorization is executed once at
+ registration/access to the network and is not executed for every
+ service event requested by the subscriber). In these environments,
+ it is more appropriate to perform the first interrogation after the
+ user has been authenticated and authorized. The first, the
+ intermediate, and the final interrogations are executed with credit-
+ control commands defined in this specification.
+
+ Other IETF standards or standards developed by other standardization
+ bodies may define the most suitable method in their architectures.
+
+5.2.1. First Interrogation after Authorization and Authentication
+
+ The Diameter credit-control client in the service element may get
+ information from the authorization server as to whether credit-
+ control is required, based on its knowledge of the end user. If
+ credit-control is required the credit-control server needs to be
+ contacted prior to initiating service delivery to the end user. The
+
+
+
+Hakala, et al. Standards Track [Page 23]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ accounting protocol and the credit-control protocol can be used in
+ parallel. The authorization server may also determine whether the
+ parallel accounting stream is required.
+
+ The following diagram illustrates the case where both protocols are
+ used in parallel and the service element sends credit-control
+ messages directly to the credit-control server. More credit-control
+ sequence examples are given in Annex A.
+
+ Diameter
+ End User Service Element AAA Server CC Server
+ (CC Client)
+ | Registration | AA request/answer(accounting,cc or both)|
+ |<----------------->|<------------------>| |
+ | : | | |
+ | : | | |
+ | Service Request | | |
+ |------------------>| | |
+ | | CCR(Initial,Credit-Control AVPs) |
+ | +|---------------------------------------->|
+ | CC stream|| | CCA(Granted-Units)|
+ | +|<----------------------------------------|
+ | Service Delivery | | |
+ |<----------------->| ACR(start,Accounting AVPs) |
+ | : |------------------->|+ |
+ | : | ACA || Accounting stream |
+ | |<-------------------|+ |
+ | : | | |
+ | : | | |
+ | | CCR(Update,Used-Units) |
+ | |---------------------------------------->|
+ | | | CCA(Granted-Units)|
+ | |<----------------------------------------|
+ | : | | |
+ | : | | |
+ | End of Service | | |
+ |------------------>| CCR(Termination, Used-Units) |
+ | |---------------------------------------->|
+ | | | CCA |
+ | |<----------------------------------------|
+ | | ACR(stop) | |
+ | |------------------->| |
+ | | ACA | |
+ | |<-------------------| |
+
+ Figure 2: Protocol example with first interrogation after user's
+ authorization/authentication
+
+
+
+
+Hakala, et al. Standards Track [Page 24]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+5.2.2. Authorization Messages for First Interrogation
+
+ The Diameter credit-control client in the service element MUST
+ actively co-operate with the authorization/authentication client in
+ the construction of the AA request by adding appropriate credit-
+ control AVPs. The credit-control client MUST add the Credit-Control
+ AVP to indicate credit-control capabilities and MAY add other
+ relevant credit-control specific AVPs to the proper
+ authorization/authentication command to perform the first
+ interrogation toward the home Diameter AAA server. The Auth-
+ Application-Id is set to the appropriate value, as defined in the
+ relevant service specific authorization/authentication application
+ document (e.g., [NASREQ], [DIAMMIP]). The home Diameter AAA server
+ authenticates/authorizes the subscriber and determines whether
+ credit-control is required.
+
+ If credit-control is not required for the subscriber, the home
+ Diameter AAA server will respond as usual, with an appropriate AA
+ answer message. If credit-control is required for the subscriber and
+ the Credit-Control AVP with the value set to CREDIT_AUTHORIZATION was
+ present in the authorization request, the home AAA server MUST
+ contact the credit-control server to perform the first interrogation.
+ If credit-control is required for the subscriber and the Credit-
+ Control AVP was not present in the authorization request, the home
+ AAA server MUST send an authorization reject answer message.
+
+ The Diameter AAA server supporting credit-control is required to send
+ the Credit-Control-Request command (CCR) defined in this document to
+ the credit-control server. The Diameter AAA server populates the CCR
+ based on service specific AVPs used for input to the rating process,
+ and possibly on credit-control AVPs received in the AA request. The
+ credit-control server will reserve money from the user's account,
+ will rate the request and will send a Credit-Control-Answer message
+ to the home Diameter AAA server. The answer message includes the
+ Granted-Service-Unit AVP(s) and MAY include other credit-control
+ specific AVPs, as appropriate. Additionally, the credit-control
+ server MAY set the Validity-Time and MAY include the Credit-Control-
+ Failure-Handling AVP and the Direct-Debiting-Failure-Handling AVP to
+ determine what to do if the sending of credit-control messages to the
+ credit-control server has been temporarily prevented.
+
+ Upon receiving the Credit-Control-Answer message from the credit-
+ control server, the home Diameter AAA server will populate the AA
+ answer with the received credit-control AVPs and with the appropriate
+ service attributes according to the authorization/authentication
+ specific application (e.g., [NASREQ], [DIAMMIP]). It will then
+ forward the packet to the credit-control client. If the home
+ Diameter AAA server receives a credit-control reject message, it will
+
+
+
+Hakala, et al. Standards Track [Page 25]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ simply generate an appropriate authorization reject message to the
+ credit-control client, including the credit-control specific error
+ code.
+
+ In this model, the credit-control client sends further credit-control
+ messages to the credit-control server via the home Diameter AAA
+ server. Upon receiving a successful authorization answer message
+ with the Granted-Service-Unit AVP(s), the credit-control client will
+ grant the service to the end user and will generate an intermediate
+ credit-control request, as required by using credit-control commands.
+ The CC-Request-Number of the first UPDATE_REQUEST MUST be set to 1
+ (for how to produce unique value for the CC-Request-Number AVP, see
+ section 8.2).
+
+ If service specific re-authorization is performed (i.e.,
+ authorization-lifetime expires), the credit-control client MUST add
+ to the service specific re-authorization request the Credit-Control
+ AVP with a value set to RE_AUTHORIZATION to indicate that the
+ credit-control server MUST NOT be contacted. When session based
+ credit-control is used for the subscriber, a constant credit-control
+ message stream flows through the home Diameter AAA server. The home
+ Diameter AAA server can make use of this credit-control message flow
+ to deduce that the user's activity is ongoing; therefore, it is
+ recommended to set the authorization-lifetime to a reasonably high
+ value when credit-control is used for the subscriber.
+
+ In this scenario, the home Diameter AAA server MUST advertise support
+ for the credit-control application to its peers during the capability
+ exchange process.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 26]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ The following diagram illustrates the use of
+ authorization/authentication messages to perform the first
+ interrogation. The parallel accounting stream is not shown in the
+ figure.
+
+ Service Element Diameter
+ End User (CC Client) AAA Server CC Server
+ | Service Request | AA Request (CC AVPs) |
+ |------------------>|------------------->| |
+ | | | CCR(Initial, CC AVPs)
+ | | |------------------->|
+ | | | CCA(Granted-Units)
+ | | |<-------------------|
+ | | AA Answer(Granted-Units) |
+ | Service Delivery |<-------------------| |
+ |<----------------->| | |
+ | : | | |
+ | : | | |
+ | : | | |
+ | | | |
+ | | CCR(Update,Used-Units) |
+ | |------------------->| CCR(Update,Used-Units)
+ | | |------------------->|
+ | | | CCA(Granted-Units)|
+ | | CCA(Granted-Units)|<-------------------|
+ | |<-------------------| |
+ | : | | |
+ | : | | |
+ | End of Service | | |
+ |------------------>| CCR(Termination,Used-Units) |
+ | |------------------->| CCR(Term.,Used-Units)
+ | | |------------------->|
+ | | | CCA |
+ | | CCA |<-------------------|
+ | |<-------------------| |
+
+ Figure 3: Protocol example with use of the
+ authorization messages for the first interrogation
+
+5.3. Intermediate Interrogation
+
+ When all the granted service units for one unit type are spent by the
+ end user or the Validity-Time is expired, the Diameter credit-control
+ client MUST send a new Credit-Control-Request to the credit-control
+ server. In the event that credit-control for multiple services is
+ applied in one credit-control session (i.e., units associated to
+ Service-Identifier(s) or Rating-Group are granted), a new Credit-
+ Control-Request MUST be sent to the credit-control server when the
+
+
+
+Hakala, et al. Standards Track [Page 27]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ credit reservation has been wholly consumed, or upon expiration of
+ the Validity-Time. It is always up to the Diameter credit-control
+ client to send a new request well in advance of the expiration of the
+ previous request in order to avoid interruption in the service
+ element. Even if the granted service units reserved by the credit-
+ control server have not been spent upon expiration of the Validity-
+ Time, the Diameter credit-control client MUST send a new Credit-
+ Control-Request to the credit-control server.
+
+ There can also be mid-session service events, which might affect the
+ rating of the current service events. In this case, a spontaneous
+ updating (a new Credit-Control-Request) SHOULD be sent including
+ information related to the service event even if all the granted
+ service units have not been spent or the Validity-Time has not
+ expired.
+
+ When the used units are reported to the credit-control server, the
+ credit-control client will not have any units in its possession
+ before new granted units are received from the credit-control server.
+ When the new granted units are received, these units apply from the
+ point where the measurement of the reported used units stopped.
+ Where independent credit-control of multiple services is supported,
+ this process may be executed for one or more services, a single
+ rating-group, or a pool within the (sub)session.
+
+ The CC-Request-Type AVP is set to the value UPDATE_REQUEST in the
+ intermediate request message. The Subscription-Id AVP SHOULD be
+ included in the intermediate message to identify the end user in the
+ credit-control server. The Service-Context-Id AVP indicates the
+ service specific document applicable to the request.
+
+ The Requested-Service-Unit AVP MAY contain the new amount of
+ requested service units. Where the Multiple-Services-Credit-Control
+ AVP is used, it MUST contain the Requested-Service-Unit AVP if a new
+ quota is requested for the associated service/rating-group. The
+ Used-Service-Unit AVP contains the amount of used service units
+ measured from the point when the service became active or, if interim
+ interrogations are used during the session, from the point when the
+ previous measurement ended. The same unit types used in the previous
+ message SHOULD be used. If several unit types were included in the
+ previous answer message, the used service units for each unit type
+ MUST be reported.
+
+ The Event-Timestamp AVP SHOULD be included in the request and
+ contains the time of the event that triggered the sending of the new
+ Credit-Control-Request.
+
+
+
+
+
+Hakala, et al. Standards Track [Page 28]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ The credit-control server MUST deduct the used amount from the end
+ user's account. It MAY rate the new request and make a new credit-
+ reservation from the end user's account that covers the cost of the
+ requested service event.
+
+ A Credit-Control-Answer message with the CC-Request-Type AVP set to
+ the value UPDATE_REQUEST MAY include the Cost-Information AVP
+ containing the accumulated cost estimation for the session, without
+ taking any credit-reservation into account.
+
+ The Credit-Control-Answer message MAY also include the Final-Unit-
+ Indication AVP to indicate that the answer message contains the final
+ units for the service. After the end user has consumed these units,
+ the Diameter credit-control-client MUST behave as described in
+ section 5.6.
+
+ There can be several intermediate interrogations within a session.
+
+5.4. Final Interrogation
+
+ When the end user terminates the service session, or when the
+ graceful service termination described in section 5.6 takes place,
+ the Diameter credit-control client MUST send a final Credit-Control-
+ Request message to the credit-control server. The CC-Request-Type
+ AVP is set to the value TERMINATION_REQUEST. The Service-Context-Id
+ AVP indicates the service specific document applicable to the
+ request.
+
+ The Event-Timestamp AVP SHOULD be included in the request and
+ contains the time when the session was terminated.
+
+ The Used-Service-Unit AVP contains the amount of used service units
+ measured from the point when the service became active or, if interim
+ interrogations are used during the session, from the point when the
+ previous measurement ended. If several unit types were included in
+ the previous answer message, the used service units for each unit
+ type MUST be reported.
+
+ After final interrogation, the credit-control server MUST refund the
+ reserved credit amount not used to the end user's account and deduct
+ the used monetary amount from the end user's account.
+
+ A Credit-Control-Answer message with the CC-Request-Type set to the
+ value TERMINATION_REQUEST MAY include the Cost-Information AVP
+ containing the estimated total cost for the session in question.
+
+ If the user logs off during an ongoing credit-control session, or if
+ some other reason causes the user to become logged off (e.g., final-
+
+
+
+Hakala, et al. Standards Track [Page 29]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ unit indication causes user logoff according to local policy), the
+ service element, according to application specific policy, may send a
+ Session-Termination-Request (STR) to the home Diameter AAA server as
+ usual [DIAMBASE]. Figure 4 illustrates the case when the final-unit
+ indication causes user logoff upon consumption of the final granted
+ units and the generation of STR.
+
+ Service Element AAA Server CC Server
+ End User (CC Client)
+ | Service Delivery | | |
+ |<----------------->| | |
+ | : | | |
+ | : | | |
+ | : | | |
+ | | | |
+ | | CCR(Update,Used-Units) |
+ | |------------------->| CCR(Update,Used-Units)
+ | | |------------------->|
+ | | CCA(Final-Unit, Terminate)
+ | CCA(Final-Unit, Terminate)|<-------------------|
+ | |<-------------------| |
+ | : | | |
+ | : | | |
+ | Disconnect user | | |
+ |<------------------| CCR(Termination,Used-Units) |
+ | |------------------->| CCR(Term.,Used-Units)
+ | | |------------------->|
+ | | | CCA |
+ | | CCA |<-------------------|
+ | |<-------------------| |
+ | | STR | |
+ | |------------------->| |
+ | | STA | |
+ | |<-------------------| |
+
+ Figure 4: User disconnected due to exhausted account
+
+5.5. Server-Initiated Credit Re-Authorization
+
+ The Diameter credit-control application supports server-initiated
+ re-authorization. The credit-control server MAY optionally initiate
+ the credit re-authorization by issuing a Re-Auth-Request (RAR) as
+ defined in the Diameter base protocol [DIAMBASE]. The Auth-
+ Application-Id in the RAR message is set to 4 to indicate Diameter
+ Credit Control, and the Re-Auth-Request-Type is set to
+ AUTHORIZE_ONLY.
+
+
+
+
+
+Hakala, et al. Standards Track [Page 30]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ Section 5.1.2 defines the feature to enable credit-control for
+ multiple services within a single (sub-)session where the server can
+ authorize credit usage at a different level of granularity. Further,
+ the server may provide credit resources to multiple services or
+ rating groups as a pool (see section 5.1.2 for details and
+ definitions). Therefore, the server, based on its service logic and
+ its knowledge of the ongoing session, can decide to request credit
+ re-authorization for a whole (sub-)session, a single credit pool, a
+ single service, or a single rating-group. To request credit re-
+ authorization for a credit pool, the server includes in the RAR
+ message the G-S-U-Pool-Identifier AVP indicating the affected pool.
+ To request credit re-authorization for a service or a rating-group,
+ the server includes in the RAR message the Service-Identifier AVP or
+ the Rating-Group AVP, respectively. To request credit re-
+ authorization for all the ongoing services within the (sub-)session,
+ the server includes none of the above mentioned AVPs in the RAR
+ message.
+
+ If a credit re-authorization is not already ongoing (i.e., the
+ credit-control session is in Open state), a credit control client
+ that receives an RAR message with Session-Id equal to a currently
+ active credit-control session MUST acknowledge the request by sending
+ the Re-Auth-Answer (RAA) message and MUST initiate the credit re-
+ authorization toward the server by sending a Credit-Control-Request
+ message with the CC-Request-Type AVP set to the value UPDATE_REQUEST.
+ The Result-Code 2002 (DIAMETER_LIMITED_SUCCESS) SHOULD be used in the
+ RAA message to indicate that an additional message (i.e., CCR message
+ with the value UPDATE_REQUEST) is required to complete the procedure.
+ If a quota was allocated to the service, the credit-control client
+ MUST report the used quota in the Credit-Control-Request. Note that
+ the end user does not need to be prompted for the credit re-
+ authorization, since the credit re-authorization is transparent to
+ the user (i.e., it takes place exclusively between the credit-control
+ client and the credit-control server).
+
+ Where multiple services in a user's session are supported, the
+ procedure in the above paragraph will be executed at the granularity
+ requested by the server in the RAR message.
+
+ If credit re-authorization is ongoing at the time when the RAR
+ message is received (i.e., RAR-CCR collision), the credit-control
+ client successfully acknowledges the request but does not initiate a
+ new credit re-authorization. The Result-Code 2001 (DIAMETER_SUCCESS)
+ SHOULD be used in the RAA message to indicate that a credit re-
+ authorization procedure is already ongoing (i.e., the client was in
+ PendingU state when the RAR was received). The credit-control server
+ SHOULD process the Credit-Control-Request as if it was received in
+ answer to the server initiated credit re-authorization, and should
+
+
+
+Hakala, et al. Standards Track [Page 31]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ consider the server initiated credit re-authorization process
+ successful upon reception of the Re-Auth-Answer message.
+
+ When multiple services are supported in a user's session, the server
+ may request credit re-authorization for a credit pool (or for the
+ (sub-)session) while a credit re-authorization is already ongoing for
+ some of the services or rating-groups. In this case, the client
+ acknowledges the server request with an RAA message and MUST send a
+ new Credit-Control-Request message to perform re-authorization for
+ the remaining services/rating-groups. The Result-Code 2002
+ (DIAMETER_LIMITED_SUCCESS) SHOULD be used in the RAA message to
+ indicate that an additional message (i.e., CCR message with value
+ UPDATE_REQUEST) is required to complete the procedure. The server
+ processes the received requests and returns an appropriate answer to
+ both requests.
+
+ The above-defined procedures are enabled for each of the possibly
+ active Diameter credit-control sub-sessions. The server MAY request
+ re-authorization for an active sub-session by including the CC-Sub-
+ Session-Id AVP in the RAR message in addition to the Session-Id AVP.
+
+5.6. Graceful Service Termination
+
+ When the user's account runs out of money, the user may not be
+ allowed to compile additional chargeable events. However, the home
+ service provider may offer some services; for instance, access to a
+ service portal where it is possible to refill the account, for which
+ the user is allowed to benefit for a limited time. The length of
+ this time is usually dependent on the home service provider policy.
+
+ This section defines the optional graceful service termination
+ feature that MAY be supported by the credit-control server. Credit-
+ control client implementations MUST support the Final-Unit-Indication
+ with at least the teardown of the ongoing service session once the
+ subscriber has consumed all the final granted units.
+
+ Where independent credit-control of multiple services in a single
+ credit-control (sub-)session is supported, it is possible to use the
+ graceful service termination for each of the services/rating-groups
+ independently. Naturally, the graceful service termination process
+ defined in the following sub-sections will apply to the specific
+ service/rating-group as requested by the server.
+
+ In some service environments (e.g., NAS), the graceful service
+ termination may be used to redirect the subscriber to a service
+ portal for online balance refill or other services offered by the
+ home service provider. In this case, the graceful termination
+ process installs a set of packet filters to restrict the user's
+
+
+
+Hakala, et al. Standards Track [Page 32]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ access capability only to/from the specified destinations. All the
+ IP packets not matching the filters will be dropped or, possibly,
+ re-directed to the service portal. The user may also be sent an
+ appropriate notification as to why the access has been limited.
+ These actions may be communicated explicitly from the server to the
+ client or may be configured per-service at the client. Explicitly
+ signaled redirect or restrict instructions always take precedence
+ over configured ones.
+
+ It is also possible use the graceful service termination to connect
+ the prepaid user to a top-up server that plays an announcement and
+ prompts the user to replenish the account. In this case, the
+ credit-control server sends only the address of the top-up server
+ where the prepaid user shall be connected after the final granted
+ units have been consumed. An example of this is given in Appendix A
+ (Flow VII).
+
+ The credit-control server MAY initiate the graceful service
+ termination by including the Final-Unit-Indication AVP in the
+ Credit-Control-Answer to indicate that the message contains the final
+ units for the service.
+
+ When the credit-control client receives the Final-Unit-Indication AVP
+ in the answer from the server, its behavior depends on the value
+ indicated in the Final-Unit-Action AVP. The server may request the
+ following actions: TERMINATE, REDIRECT, or RESTRICT_ACCESS.
+
+ A following figure illustrates the graceful service termination
+ procedure described in the following sub-sections.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 33]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ Diameter
+ End User Service Element AAA Server CC Server
+ (CC Client)
+ | Service Delivery | | |
+ |<----------------->| | |
+ | |CCR(Update,Used-Units) |
+ | |------------------->|CCR(Update,Used-Units)
+ | : | |------------------->|
+ | : | |CCA(Final-Unit,Action)
+ | : | |<-------------------|
+ | |CCA(Final-Unit,Action) |
+ | |<-------------------| |
+ | | | |
+ | : | | |
+ | : | | |
+ | : | | |
+ | /////////////// |CCR(Update,Used-Units) |
+ |/Final Units End/->|------------------->|CCR(Update,Used-Units)
+ |/Action and // | |------------------->|
+ |/Restrictions // | | CCA(Validity-Time)|
+ |/Start // | CCA(Validity-Time)|<-------------------|
+ | ///////////// |<-------------------| |
+ | : | | |
+ | : | | |
+ | Replenish Account +-------+ |
+ |<-------------------------------------------->|Account| |
+ | | | +-------+ |
+ | | | RAR |
+ | + | RAR |<===================|
+ | | |<===================| |
+ | | | RAA | |
+ | ///////////// | |===================>| RAA |
+ | /If supported / | | CCR(Update) |===================>|
+ | /by CC Server/ | |===================>| CCR(Update) |
+ | ///////////// | | |===================>|
+ | | | | CCA(Granted-Unit)|
+ | | | CCA(Granted-Unit)|<===================|
+ | Restrictions ->+ |<===================| |
+ | removed | | |
+ | : | | |
+ | OR | CCR(Update) | |
+ | Validity-Time ->|------------------->| CCR(Update) |
+ | expires | |------------------->|
+ | | | CCA(Granted-Unit)|
+ | | CCA(Granted-Unit)|<-------------------|
+ | Restrictions ->|<-------------------| |
+ | removed | | |
+
+
+
+
+Hakala, et al. Standards Track [Page 34]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ Figure 5: Optional graceful service termination procedure
+
+5.6.1. Terminate Action
+
+ The Final-Unit-Indication AVP with Final-Unit-Action TERMINATE does
+ not include any other information. When the subscriber has consumed
+ the final granted units, the service element MUST terminate the
+ service. This is the default handling applicable whenever the
+ credit-control client receives an unsupported Final-Unit-Action value
+ and MUST be supported by all the Diameter credit-control client
+ implementations conforming to this specification. A final Credit-
+ Control-Request message to the credit-control server MUST be sent if
+ the Final-Unit-Indication AVP indicating action TERMINATE was present
+ at command level. The CC-Request-Type AVP in the request is set to
+ the value TERMINATION_REQUEST.
+
+5.6.2. Redirect Action
+
+ The Final-Unit-Indication AVP with Final-Unit-Action REDIRECT
+ indicates to the service element supporting this action that, upon
+ consumption of the final granted units, the user MUST be re-directed
+ to the address specified in the Redirect-Server AVP as follows.
+
+ The credit-control server sends the Redirect-Server AVP in the
+ Credit-Control-Answer message. In such a case, the service element
+ MUST redirect or connect the user to the destination specified in the
+ Redirect-Server AVP, if possible. When the end user is redirected
+ (by using protocols others than Diameter) to the specified server or
+ connected to the top-up server, an additional authorization (and
+ possibly authentication) may be needed before the subscriber can
+ replenish the account; however, this is out of the scope of this
+ specification.
+
+ In addition to the Redirect-Server AVP, the credit-control server MAY
+ include one or more Restriction-Filter-Rule AVPs or one or more
+ Filter-Id AVPs in the Credit-Control-Answer message to enable the
+ user to access other services (for example, zero-rated services). In
+ such a case, the access device MUST drop all the packets not matching
+ the IP filters specified in the Credit-Control-Answer message and, if
+ possible, redirect the user to the destination specified in the
+ Redirect-Server AVP.
+
+ An entity other than the credit-control server may provision the
+ access device with appropriate IP packet filters to be used in
+ conjunction with the Diameter credit-control application. This case
+ is considered in section 5.6.3.
+
+
+
+
+
+Hakala, et al. Standards Track [Page 35]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ When the final granted units have been consumed, the credit-control
+ client MUST perform an intermediate interrogation. The purpose of
+ this interrogation is to indicate to the credit-control server that
+ the specified action started and to report the used units. The
+ credit-control server MUST deduct the used amount from the end user's
+ account but MUST NOT make a new credit reservation. The credit-
+ control client, however, may send intermediate interrogations before
+ all the final granted units have been consumed for which rating and
+ money reservation may be needed; for instance, upon Validity-Time
+ expires or upon mid-session service events that affect the rating of
+ the current service. Therefore, the credit-control client MUST NOT
+ include any rating related AVP in the request sent once all the final
+ granted units have been consumed as an indication to the server that
+ the requested final unit action started, rating and money reservation
+ are not required (when the Multiple-Services-Credit-Control AVP is
+ used, the Service-Identifier or Rating-Group AVPs is included to
+ indicate the concerned services). Naturally, the Credit-Control-
+ Answer message does not contain any granted service unit and MUST
+ include the Validity-Time AVP to indicate to the credit-control
+ client how long the subscriber is allowed to use network resources
+ before a new intermediate interrogation is sent to the server.
+
+ At the expiry of Validity-Time, the credit-control client sends a
+ Credit-Control-Request (UPDATE_REQUEST) as usual. This message does
+ not include the Used-Service-Unit AVP, as there is no allotted quota
+ to report. The credit-control server processes the request and MUST
+ perform the credit reservation. If during this time the subscriber
+ did not replenish his/her account, whether he/she will be
+ disconnected or will be granted access to services not controlled by
+ a credit-control server for an unlimited time is dependent on the
+ home service provider policy (note: the latter option implies that
+ the service element should not remove the restriction filters upon
+ termination of the credit-control). The server will return the
+ appropriate Result-Code (see section 9.1) in the Credit-Control-
+ Answer message in order to implement the policy-defined action.
+ Otherwise, new quota will be returned, the service element MUST
+ remove all the possible restrictions activated by the graceful
+ service termination process and continue the credit-control session
+ and service session as usual.
+
+ The credit-control client may not wait until the expiration of the
+ Validity-Time and may send a spontaneous update (a new Credit-
+ Control-Request) if the service element can determine, for instance,
+ that communication between the end user and the top-up server took
+ place. An example of this is given in Appendix A (Figure A.8).
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 36]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ Note that the credit-control server may already have initiated the
+ above-described process for the first interrogation. However, the
+ user's account might be empty when this first interrogation is
+ performed. In this case, the subscriber can be offered a chance to
+ replenish the account and continue the service. The credit-control
+ client receives a Credit-Control-Answer or service specific
+ authorization answer with the Final-Unit-Indication and Validity-Time
+ AVPs but no Granted-Service-Unit. It immediately starts the graceful
+ service termination without sending any message to the server. An
+ example of this case is illustrated in Appendix A.
+
+5.6.3. Restrict Access Action
+
+ A Final-Unit-Indication AVP with the Final-Unit-Action
+ RESTRICT_ACCESS indicates to the device supporting this action that
+ the user's access MUST be restricted according to the IP packet
+ filters given in the Restriction-Filter-Rule AVP(s) or according to
+ the IP packet filters identified by the Filter-Id AVP(s). The
+ credit-control server SHOULD include either the Restriction-Filter-
+ Rule AVP or the Filter-Id AVP in the Credit-Control-Answer message.
+
+ An entity other than the credit-control server may provision the
+ access device with appropriate IP packet filters to be used in
+ conjunction with the Diameter credit-control application. Such an
+ entity may, for instance, configure the access device with IP flows
+ to be passed when the Diameter credit-control application indicates
+ RESTRICT_ACCESS or REDIRECT. The access device passes IP packets
+ according to the filter rules that may have been received in the
+ Credit-Control-Answer message in addition to those that may have been
+ configured by the other entity. However, when the user's account
+ cannot cover the cost of the requested service, the action taken is
+ the responsibility of the credit-control server that controls the
+ prepaid subscriber.
+
+ If another entity working in conjunction with the Diameter credit-
+ control application already provisions the access device with all the
+ required filter rules for the end user, the credit-control server
+ presumably need not send any additional filter. Therefore, it is
+ RECOMMENDED that credit-control server implementations supporting the
+ graceful service termination be configurable for sending the
+ Restriction-Filter-Rule AVP, the Filter-Id AVP, or none of the above.
+
+ When the final granted units have been consumed, the credit-control
+ client MUST perform an intermediate interrogation. The credit-
+ control client and the credit-control server process this
+ intermediate interrogation and execute subsequent procedures, as
+ specified in the previous section for the REDIRECT action.
+
+
+
+
+Hakala, et al. Standards Track [Page 37]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ The credit-control server may initiate the graceful service
+ termination with action RESTRICT_ACCESS already for the first
+ interrogation, as specified in the previous section for the REDIRECT
+ action.
+
+5.6.4. Usage of the Server-Initiated Credit Re-Authorization
+
+ Once the subscriber replenishes the account, she presumably expects
+ all the restrictions placed by the graceful termination procedure to
+ be removed immediately and unlimited service' access to be resumed.
+ For the best user experience, the credit-control server
+ implementation MAY support the server-initiated credit re-
+ authorization (see section 5.5). In such a case, upon the successful
+ account top-up, the credit-control server sends the Re-Auth-Request
+ (RAR) message to solicit the credit re-authorization. The credit-
+ control client initiates the credit re-authorization by sending the
+ Credit-Control-Request message with the CC-Request-Type AVP set to
+ the value UPDATE_REQUEST. The Used-Service-Unit AVP is not included
+ in the request, as there is no allotted quota to report. The
+ Requested-Service-Unit AVP MAY be included in the request. After the
+ credit-control client successfully receives the Credit-Control-Answer
+ with new Granted-Service-Unit, all the possible restrictions
+ activated for the purpose of the graceful service termination MUST be
+ removed in the service element. The credit-control session and the
+ service session continue as usual.
+
+5.7. Failure Procedures
+
+ The Credit-Control-Failure-Handling AVP (CCFH), as described in this
+ section, determines the behavior of the credit-control client in
+ fault situations. The CCFH may be received from the Diameter home
+ AAA server, from the credit-control server, or may be configured
+ locally. The CCFH value received from the home AAA server overrides
+ the locally configured value. The CCFH value received from the
+ credit-control server in the Credit-Control-Answer message always
+ overrides any existing value.
+
+ The authorization server MAY include the Accounting-Realtime-Required
+ AVP to determine what to do if the sending of accounting records to
+ the accounting server has been temporarily prevented, as defined in
+ [DIAMBASE]. It is RECOMMENDED that the client complement the
+ credit-control failure procedures with backup accounting flow toward
+ an accounting server. By using different combinations of
+ Accounting-Realtime-Required and Credit-Control-Failure-Handling
+ AVPs, different safety levels can be built. For example, by choosing
+ a Credit-Control-Failure-Handling AVP equal to CONTINUE for the
+ credit-control flow and a Accounting-Realtime-Required AVP equal to
+ DELIVER_AND_GRANT for the accounting flow, the service can be granted
+
+
+
+Hakala, et al. Standards Track [Page 38]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ to the end user even if the connection to the credit-control server
+ is down, as long as the accounting server is able to collect the
+ accounting information and information exchange is taking place
+ between the accounting server and credit-control server.
+
+ As the credit-control application is based on real-time bi-
+ directional communication between the credit-control client and the
+ credit-control server, the usage of alternative destinations and the
+ buffering of messages may not be sufficient in the event of
+ communication failures. Because the credit-control server has to
+ maintain session states, moving the credit-control message stream to
+ a backup server requires a complex context transfer solution.
+ Whether the credit-control message stream is moved to a backup
+ credit-control server during an ongoing credit-control session
+ depends on the value of the CC-Session-Failover AVP. However,
+ failover may occur at any point in the path between the credit-
+ control client and the credit-control server if a transport failure
+ is detected with a peer, as described in [DIAMBASE]. As a
+ consequence, the credit-control server might receive duplicate
+ messages. These duplicates or out of sequence messages can be
+ detected in the credit-control server based on the credit-control
+ server session state machine (section 7), Session-Id AVP, and CC-
+ Request-Number AVP.
+
+ If a failure occurs during an ongoing credit-control session, the
+ credit-control client may move the credit-control message stream to
+ an alternative server if the CC-server indicated FAILOVER_SUPPORTED
+ in the CC-Session-Failover AVP. A secondary credit-control server
+ name, either received from the home Diameter AAA server or configured
+ locally, can be used as an address of the backup server. If the CC-
+ Session-Failover AVP is set to FAILOVER_NOT_SUPPORTED, the credit-
+ control message stream MUST NOT be moved to a backup server.
+
+ For new credit-control sessions, failover to an alternative credit-
+ control server SHOULD be performed if possible. For instance, if an
+ implementation of the credit-control client can determine primary
+ credit-control server unavailability, it can establish the new
+ credit-control sessions with a possibly available secondary credit-
+ control server.
+
+ The AAA transport profile [AAATRANS] defines the application layer
+ watchdog algorithm that enables failover from a peer that has failed
+ and is controlled by a watchdog timer (Tw) defined in [AAATRANS].
+ The recommended default initial value for Tw (Twinit) is 30 seconds.
+ Twinit may be set as low as 6 seconds; however, according to
+ [AAATRANS], setting too low a value for Twinit is likely to result in
+ an increased probability of duplicates, as well as an increase in
+ spurious failover and failback attempts. The Diameter base protocol
+
+
+
+Hakala, et al. Standards Track [Page 39]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ is common to several different types of Diameter AAA applications
+ that may be run in the same service element. Therefore, tuning the
+ timer Twinit to a lower value in order to satisfy the requirements of
+ real-time applications, such as the Diameter credit-control
+ application, will certainly cause the above mentioned problems. For
+ prepaid services, however, the end user expects an answer from the
+ network in a reasonable time. Thus, the Diameter credit-control
+ client will react faster than would the underlying base protocol.
+ Therefore this specification defines the timer Tx that is used by the
+ credit-control client (as defined in section 13) to supervise the
+ communication with the credit-control server. When the timer Tx
+ elapses, the credit-control client takes an action to the end user
+ according to the Credit-Control-Failure-Handling AVP.
+
+ When Tx expires, the Diameter credit-control client always terminates
+ the service if the Credit-Control-Failure-Handling (CCFH) AVP is set
+ to the value TERMINATE. The credit-control session may be moved to
+ an alternative server only if a protocol error DIAMETER_TOO_BUSY or
+ DIAMETER_UNABLE_TO_DELIVER is received before Tx expires. Therefore,
+ the value TERMINATE is not appropriate if proper failover behavior is
+ desired.
+
+ If the Credit-Control-Failure-Handling AVP is set to the value
+ CONTINUE or RETRY_AND_TERMINATE, the service will be granted to the
+ end user when the timer Tx expires. An answer message with granted-
+ units may arrive later if the base protocol transport failover
+ occurred in the path to the credit-control server. (The Twinit
+ default value is 3 times more than the Tx recommended value.) The
+ credit-control client SHOULD grant the service to the end user, start
+ monitoring the resource usage, and wait for the possible late answer
+ until the timeout of the request (e.g., 120 seconds). If the request
+ fails and the CC-Session-Failover AVP is set to
+ FAILOVER_NOT_SUPPORTED, the credit-control client terminates or
+ continues the service depending on the value set in the CCFH and MUST
+ free all the reserved resources for the credit-control session. If
+ the protocol error DIAMETER_UNABLE_TO_DELIVER or DIAMETER_TOO_BUSY is
+ received or the request times out and the CC-Session-Failover AVP is
+ set to FAILOVER_SUPPORTED, the credit-control client MAY send the
+ request to a backup server, if possible. If the credit-control
+ client receives a successful answer from the backup server, it
+ continues the credit-control session with such a server. If the re-
+ transmitted request also fails, the credit-control client terminates
+ or continues the service depending on the value set in the CCFH and
+ MUST free all the reserved resources for the credit-control session.
+
+ If a communication failure occurs during the graceful service
+ termination procedure, the service element SHOULD always terminate
+ the ongoing service session.
+
+
+
+Hakala, et al. Standards Track [Page 40]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ If the credit-control server detects a failure during an ongoing
+ credit-control session, it will terminate the credit-control session
+ and return the reserved units back to the end user's account.
+
+ The supervision session timer Tcc (as defined in section 13) is used
+ in the credit-control server to supervise the credit-control session.
+
+ In order to support failover between credit-control servers,
+ information transfer about the credit-control session and account
+ state SHOULD take place between the primary and the secondary
+ credit-control server. Implementations supporting the credit-control
+ session failover MUST also ensure proper detection of duplicate or
+ out of sequence messages. The communication between the servers is
+ regarded as an implementation issue and is outside of the scope of
+ this specification.
+
+6. One Time Event
+
+ The one-time event is used when there is no need to maintain any
+ state in the Diameter credit-control server; for example, enquiring
+ about the price of the service. The use of a one-time event implies
+ that the user has been authenticated and authorized beforehand.
+
+ The one time event can be used when the credit-control client wants
+ to know the cost of the service event or to check the account balance
+ without any credit-reservation. It can also be used for refunding
+ service units on the user's account or for direct debiting without
+ any credit-reservation. The one time event is shown in Figure 6.
+
+ Diameter
+ End User Service Element AAA Server CC Server
+ (CC Client)
+ | Service Request | | |
+ |------------------>| | |
+ | | CCR(Event) | |
+ | |------------------->| CCR(Event) |
+ | | |------------------->|
+ | | | CCA(Granted-Units)|
+ | | CCA(Granted-Units)|<-------------------|
+ | Service Delivery |<-------------------| |
+ |<----------------->| | |
+
+ Figure 6: One time event
+
+ In environments such as the 3GPP architecture, the one time event can
+ be sent from the service element directly to the credit-control
+ server.
+
+
+
+
+Hakala, et al. Standards Track [Page 41]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+6.1. Service Price Enquiry
+
+ The credit-control client may need to know the price of the service
+ event. Services offered by application service providers whose
+ prices are not known in the credit-control client might exist. The
+ end user might also want to get an estimation of the price of a
+ service event before requesting it.
+
+ A Diameter credit-control client requesting the cost information MUST
+ set the CC-Request-Type AVP equal to EVENT_REQUEST, include the
+ Requested-Action AVP set to PRICE_ENQUIRY, and set the requested
+ service event information into the Service-Identifier AVP in the
+ Credit-Control-Request message. Additional service event information
+ may be sent as service specific AVPs or within the Service-
+ Parameter-Info AVP. The Service-Context-Id AVP indicates the service
+ specific document applicable to the request.
+
+ The credit-control server calculates the cost of the requested
+ service event, but it does not perform any account balance check or
+ credit-reservation from the account.
+
+ The estimated cost of the requested service event is returned to the
+ credit-control client in the Cost-Information AVP in the Credit-
+ Control-Answer message.
+
+6.2. Balance Check
+
+ The Diameter credit-control client may only have to verify that the
+ end user's account balance covers the cost of a certain service
+ without reserving any units from the account at the time of the
+ inquiry. This method does not guarantee that credit would be left
+ when the Diameter credit-control client requests the debiting of the
+ account with a separate request.
+
+ A Diameter credit-control client requesting the balance check MUST
+ set the CC-Request-Type AVP equal to EVENT_REQUEST, include a
+ Requested-Action AVP set to CHECK_BALANCE, and include the
+ Subscription-Id AVP in order to identify the end user in the credit-
+ control server. The Service-Context-Id AVP indicates the service
+ specific document applicable to the request.
+
+ The credit-control server makes the balance check, but it does not
+ make any credit-reservation from the account.
+
+ The result of balance check (ENOUGH_CREDIT/NO_CREDIT) is returned to
+ the credit-control client in the Check-Balance-Result AVP in the
+ Credit-Control-Answer message.
+
+
+
+
+Hakala, et al. Standards Track [Page 42]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+6.3. Direct Debiting
+
+ There are certain service events for which service execution is
+ always successful in the service environment. The delay between the
+ service invocation and the actual service delivery to the end user
+ can be sufficiently long that the use of the session-based credit-
+ control would lead to unreasonably long credit-control sessions. In
+ these cases, the Diameter credit-control client can use the one-time
+ event scenario for direct debiting. The Diameter credit-control
+ client SHOULD be sure that the requested service event execution
+ would be successful when this scenario is used.
+
+ In the Credit-Control-Request message, the CC-Request-Type is set to
+ the value EVENT_REQUEST and the Requested-Action AVP is set to
+ DIRECT_DEBITING. The Subscription-Id AVP SHOULD be included to
+ identify the end user in the credit-control server. The Event-
+ Timestamp AVP SHOULD be included in the request and contain the time
+ when the service event is requested in the service element. The
+ Service-Context-Id AVP indicates the service specific document
+ applicable to the request.
+
+ The Diameter credit-control client MAY include the monetary amount to
+ be charged in the Requested-Service-Unit AVP, if it knows the cost of
+ the service event. If the Diameter credit-control client does not
+ know the cost of the service event, the Requested-Service-Unit AVP
+ MAY contain the number of requested service events. The Service-
+ Identifier AVP always indicates the service concerned. Additional
+ service event information to be rated MAY be sent as service specific
+ AVPs or within the Service-Parameter-Info AVP.
+
+ The credit-control server SHOULD rate the service event and deduct
+ the corresponding monetary amount from the end user's account. If
+ the type of the Requested-Service-Unit AVP is money, no rating is
+ needed, but the corresponding monetary amount is deducted from the
+ end user's account.
+
+ The credit-control server returns the Granted-Service-Unit AVP in the
+ Credit-Control-Answer message to the Diameter credit-control client.
+ The Granted-Service-Unit AVP contains the amount of service units
+ that the Diameter credit-control client can provide to the end user.
+ The type of the Granted-Service-Unit can be time, volume, service
+ specific, or money, depending on the type of service event.
+
+ If the credit-control server determines that no credit-control is
+ needed for the service, it can include the result code indicating
+ that the credit-control is not applicable (e.g., service is free of
+ charge).
+
+
+
+
+Hakala, et al. Standards Track [Page 43]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ For informative purposes, the Credit-Control-Answer message MAY also
+ include the Cost-Information AVP containing the estimated total cost
+ of the requested service.
+
+6.4. Refund
+
+ Some services may refund service units to the end user's account; for
+ example, gaming services.
+
+ The credit-control client MUST set CC-Request-Type to the value
+ EVENT_REQUEST and the Requested-Action AVP to REFUND_ACCOUNT in the
+ Credit-Control-Request message. The Subscription-Id AVP SHOULD be
+ included to identify the end user in the credit-control server. The
+ Service-Context-Id AVP indicates the service specific document
+ applicable to the request.
+
+ The Diameter credit-control client MAY include the monetary amount to
+ be refunded in the Requested-Service-Unit AVP. The Service-
+ Identifier AVP always indicates the concerned service. If the
+ Diameter credit-control client does not know the monetary amount to
+ be refunded, in addition to the Service-Identifier AVP it MAY send
+ service specific AVPs or the Service-Parameter-Info AVP containing
+ additional service event information to be rated.
+
+ For informative purposes, the Credit-Control-Answer message MAY also
+ include the Cost-Information AVP containing the estimated monetary
+ amount of refunded unit.
+
+6.5. Failure Procedure
+
+ Failover to an alternative credit-control server is allowed for a one
+ time event, as the server is not maintaining session states. For
+ instance, if the credit-control client receives a protocol error
+ DIAMETER_UNABLE_TO_DELIVER or DIAMETER_TOO_BUSY, it can re-send the
+ request to an alternative server, if possible. There MAY be protocol
+ transparent Diameter relays and redirect agents or Diameter credit-
+ control proxies between the credit-control client and credit-control
+ server. Failover may occur at any point in the path between the
+ credit-control client and the credit-control server if a transport
+ failure is detected with a peer, as described in [DIAMBASE]. Because
+ there can be duplicate requests for various reasons, the credit-
+ control server is responsible for real time duplicate detection.
+ Implementation issues for duplicate detection are discussed in
+ [DIAMBASE], Appendix C.
+
+ When the credit-control client detects a communication failure with
+ the credit-control server, its behavior depends on the requested
+ action. The timer Tx (as defined in section 13) is used in the
+
+
+
+Hakala, et al. Standards Track [Page 44]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ credit-control client to supervise the communication with the
+ credit-control server.
+
+ If the requested action is PRICE_ENQUIRY or CHECK_BALANCE and
+ communication failure is detected, the credit-control client SHOULD
+ forward the request messages to an alternative credit-control server,
+ if possible. The secondary credit-control server name, if received
+ from the home Diameter AAA server, can be used as an address of
+ backup server.
+
+ If the requested action is DIRECT_DEBITING, the Direct-Debiting-
+ Failure-Handling AVP (DDFH) controls the credit-control client's
+ behavior. The DDFH may be received from the home Diameter AAA server
+ or may be locally configured. The credit-control server may also
+ send the DDFH in any CCA message to be used for direct debiting
+ events compiled thereafter. The DDFH value received from the home
+ Diameter AAA server overrides the locally configured value, and the
+ DDFH value received from the credit-control server in a Credit-
+ Control-Answer message always overrides any existing value.
+
+ If the DDFH is set to TERMINATE_OR_BUFFER, the credit-control client
+ SHOULD NOT grant the service if it can determine, eventually after a
+ possible re-transmission attempt to an alternative credit-control
+ server, from the result code or error code in the answer message that
+ units have not been debited. Otherwise, the credit-control client
+ SHOULD grant the service to the end user and store the request in the
+ credit-control application level non-volatile storage. (Note that
+ re-sending the request at a later time is not a guarantee that the
+ service will be debited, as the user's account may be empty when the
+ server successfully processes the request.) The credit-control
+ client MUST mark these request messages as possible duplicates by
+ setting the T-flag in the command header as described in [DIAMBASE],
+ section 3.
+
+ If the Direct-Debiting-Failure-Handling AVP is set to CONTINUE, the
+ service SHOULD be granted, even if credit-control messages cannot be
+ delivered and messages are not buffered.
+
+ If the timer Tx expires, the credit-control client MUST continue the
+ service and wait for a possible late answer. If the request times
+ out, the credit-control client re-transmits the request (marked with
+ T-flag) to a backup credit-control server, if possible. If the re-
+ transmitted request also times out, or if a temporary error is
+ received in answer, the credit-control client buffers the request if
+ the value of the Direct-Debiting-Failure-Handling AVP is set to
+ TERMINATE_OR_BUFFER. If a failed answer is received for the
+
+
+
+
+
+Hakala, et al. Standards Track [Page 45]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ re-transmitted request, the credit-control client frees all the
+ resources reserved for the event message and deletes the request
+ regardless of the value of the DDFH.
+
+ The Credit-Control-Request with the requested action REFUND_ACCOUNT
+ should always be stored in the credit-control application level non-
+ volatile storage in case of temporary failure. The credit-control
+ client MUST mark the re-transmitted request message as a possible
+ duplicate by setting the T-flag in the command header as described in
+ [DIAMBASE], section 3.
+
+ For stored requests, the implementation may choose to limit the
+ number of re-transmission attempts and to define a re-transmission
+ interval.
+
+ Note that only one place in the credit-control system SHOULD be
+ responsible for duplicate detection. If there is only one credit-
+ control server within the given realm, the credit-control server may
+ perform duplicate detection. If there is more than one credit-
+ control server in a given realm, only one entity in the credit-
+ control system should be responsible, to ensure that the end user's
+ account is not debited or credited multiple times for the same
+ service event.
+
+7. Credit-Control Application State Machine
+
+ This section defines the credit-control application state machine.
+
+ The first four state machines are to be observed by credit-control
+ clients. The first one describes the session-based credit-control
+ when the first interrogation is executed as part of the
+ authorization/authentication process. The second describes the
+ session-based credit-control when the first interrogation is executed
+ after the authorization/authentication process. The requirements as
+ to what state machines have to be supported are discussed in section
+ 5.2.
+
+ The third state machine describes the session-based credit-control
+ for the intermediate and final interrogations. The fourth one
+ describes the event-based credit-control. These latter state
+ machines are to be observed by all implementations that conform to
+ this specification.
+
+ The fifth state machine describes the credit-control session from a
+ credit-control server perspective.
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 46]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ Any event not listed in the state machines MUST be considered an
+ error condition, and a corresponding answer, if applicable, MUST be
+ returned to the originator of the message.
+
+ In the state table, the event 'Failure to send' means that the
+ Diameter credit-control client is unable to communicate with the
+ desired destination or, if failover procedure is supported, with a
+ possibly defined alternative destination (e.g., the request times out
+ and the answer message is not received). This could be due to the
+ peer being down, or due to a physical link failure in the path to or
+ from the credit-control server.
+
+ The event 'Temporary error' means that the Diameter credit-control
+ client received a protocol error notification (DIAMETER_TOO_BUSY,
+ DIAMETER_UNABLE_TO_DELIVER, or DIAMETER_LOOP_DETECTED) in the
+ Result-Code AVP of the Credit-Control-Answer command. The above
+ protocol error notification may ultimately be received in answer to
+ the re-transmitted request to a defined alternative destination, if
+ failover is supported.
+
+ The event 'Failed answer' means that the Diameter credit-control
+ client received non-transient failure (permanent failure)
+ notification in the Credit-Control-Answer command. The above
+ permanent failure notification may ultimately be received in answer
+ to the re-transmitted request to a defined alternative destination,
+ if failover is supported.
+
+ The action 'store request' means that a request is stored in the
+ credit-control application level non-volatile storage.
+
+ The event 'Not successfully processed' means that the credit-control
+ server could not process the message; e.g., due to an unknown end
+ user, account being empty, or errors defined in [DIAMBASE].
+
+ The event 'User service terminated' can be triggered by various
+ reasons, e.g., normal user termination, network failure, and ASR
+ (Abort-Session-Request). The Termination-Cause AVP contains
+ information about the termination reason, as specified in [DIAMBASE].
+
+ The Tx timer, which is used to control the waiting time in the
+ credit-control client in the Pending state, is stopped upon exit of
+ the Pending state. The stopping of the Tx timer is omitted in the
+ state machine when the new state is Idle, as moving to Idle state
+ implies the clearing of the session and all the variables associated
+ to it.
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 47]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ The states PendingI, PendingU, PendingT, PendingE, and PendingB stand
+ for pending states to wait for an answer to a credit-control request
+ related to Initial, Update, Termination, Event, or Buffered request,
+ respectively.
+
+ The acronyms CCFH and DDFH stand for Credit-Control-Failure-Handling
+ and Direct-Debiting-Failure-Handling, respectively.
+
+ In the following state machine table, the failover to a secondary
+ server upon 'Temporary error' or 'Failure to send' is not explicitly
+ described. Moving an ongoing credit-control message stream to an
+ alternative server is, however, possible if the CC-Session-Failover
+ AVP is set to FAILOVER_SUPPORTED, as described in section 5.7.
+
+ Re-sending a credit-control event to an alternative server is
+ supported as described in section 6.5.
+
+ CLIENT, SESSION BASED for the first interrogation with AA request
+
+ State Event Action New State
+ ---------------------------------------------------------------
+ Idle Client or device requests Send PendingI
+ access/service AA request
+ with added
+ CC AVPs,
+ start Tx
+
+ PendingI Successful AA req. Grant Open
+ answer received service to
+ end user,
+ stop Tx
+
+ PendingI Tx expired Disconnect Idle
+ user/dev
+
+ PendingI Failed AA answer received Disconnect Idle
+ user/dev
+
+ PendingI AA answer Grant Idle
+ received with result code service
+ equal to CREDIT_CONTROL_ to end user
+ NOT_APPLICABLE
+
+ PendingI User service terminated Queue PendingI
+ termination
+ event
+
+
+
+
+
+Hakala, et al. Standards Track [Page 48]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ PendingI Change in rating condition Queue PendingI
+ changed
+ rating
+ condition
+ event
+
+ CLIENT, SESSION BASED for the first interrogation with CCR
+
+ State Event Action New State
+ ----------------------------------------------------------------
+
+
+ Idle Client or device requests Send PendingI
+ access/service CC initial
+ req.,
+ start Tx
+
+ PendingI Successful CC initial Stop Tx Open
+ answer received
+
+ PendingI Failure to send, or Grant Idle
+ temporary error and service to
+ CCFH equal to CONTINUE end user
+
+ PendingI Failure to send, or Terminate Idle
+ temporary error and end user's
+ CCFH equal to TERMINATE service
+ or to RETRY_AND_TERMINATE
+
+ PendingI Tx expired and CCFH Terminate Idle
+ equal to TERMINATE end user's
+ service
+
+ PendingI Tx expired and CCFH equal Grant PendingI
+ to CONTINUE or to service to
+ RETRY_AND_TERMINATE end user
+
+ PendingI CC initial answer Terminate Idle
+ received with result code end user's
+ END_USER_SERVICE_DENIED or service
+ USER_UNKNOWN
+
+ PendingI CC initial answer Grant Idle
+ received with result code service
+ equal to CREDIT_CONTROL_ to end user
+ NOT_APPLICABLE
+
+
+
+
+
+Hakala, et al. Standards Track [Page 49]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ PendingI Failed CC initial answer Grant Idle
+ received and CCFH equal to service to
+ CONTINUE end user
+
+ PendingI Failed CC initial answer Terminate Idle
+ received and CCFH equal end user's
+ to TERMINATE or to service
+ RETRY_AND_TERMINATE
+
+ PendingI User service terminated Queue PendingI
+ termination
+ event
+
+ PendingI Change in rating condition Queue PendingI
+ changed
+ rating
+ condition
+ event
+
+ CLIENT, SESSION BASED for intermediate and final interrogations
+
+ State Event Action New State
+ ----------------------------------------------------------------
+
+ Open Granted unit elapses Send PendingU
+ and no final unit CC update
+ indication received req.,
+ start Tx
+
+ Open Granted unit elapses Terminate PendingT
+ and final unit action end user's
+ equal to TERMINATE service, send
+ received CC termination
+ req.
+
+ Open Change in rating condition Send PendingU
+ in queue CC update
+ req.,
+ Start Tx
+
+ Open Service terminated in queue Send PendingT
+ CC termination
+ req.
+
+ Open Change in rating condition Send PendingU
+ or Validity-Time elapses CC update
+ req.,
+ Start Tx
+
+
+
+Hakala, et al. Standards Track [Page 50]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ Open User service terminated Send PendingT
+ CC termination
+ req.
+
+ Open RAR received Send RAA PendingU
+ followed by
+ CC update req.,
+ start Tx
+
+ PendingU Successful CC update Stop Tx Open
+ answer received
+
+ PendingU Failure to send, or Grant Idle
+ temporary error and service to
+ CCFH equal to CONTINUE end user
+
+ PendingU Failure to send, or Terminate Idle
+ temporary error and end user's
+ CCFH equal to TERMINATE service
+ or to RETRY_AND_TERMINATE
+
+ PendingU Tx expired and CCFH Terminate Idle
+ equal to TERMINATE end user's
+ service
+
+ PendingU Tx expired and CCFH equal Grant PendingU
+ to CONTINUE or to service to
+ RETRY_AND_TERMINATE end user
+
+ PendingU CC update answer Terminate Idle
+ received with result code end user's
+ END_USER_SERVICE_DENIED service
+
+ PendingU CC update answer Grant Idle
+ received with result code service
+ equal to CREDIT_CONTROL_ to end user
+ NOT_APPLICABLE
+
+ PendingU Failed CC update Grant Idle
+ answer received and service to
+ CCFH equal to CONTINUE end user
+
+ PendingU Failed CC update Terminate Idle
+ answer received and CCFH end user's
+ equal to TERMINATE or service
+ to RETRY_AND_TERMINATE
+
+
+
+
+
+Hakala, et al. Standards Track [Page 51]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ PendingU User service terminated Queue PendingU
+ termination
+ event
+
+ PendingU Change in rating Queue PendingU
+ condition changed
+ rating
+ condition
+ event
+
+ PendingU RAR received Send RAA PendingU
+
+ PendingT Successful CC Idle
+ termination answer received
+
+ PendingT Failure to send, temporary Idle
+ error, or failed answer
+
+ PendingT Change in rating condition PendingT
+
+ CLIENT, EVENT BASED
+
+ State Event Action New State
+ ----------------------------------------------------------------
+ Idle Client or device requests Send PendingE
+ a one-time service CC event
+ req.,
+ Start Tx
+
+ Idle Request in storage Send PendingB
+ stored
+ request
+
+ PendingE Successful CC event Grant Idle
+ answer received service to
+ end user
+
+ PendingE Failure to send, temporary Indicate Idle
+ error, failed CC event service
+ answer received, or error
+ Tx expired; requested
+ action CHECK_BALANCE or
+ PRICE_ENQUIRY
+
+ PendingE CC event answer Terminate Idle
+ received with result code end user's
+ END_USER_SERVICE_DENIED or service
+ USER_UNKNOWN and Tx running
+
+
+
+Hakala, et al. Standards Track [Page 52]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ PendingE CC event answer Grant Idle
+ received with result code service
+ CREDIT_CONTROL_NOT_APPLICABLE; to end
+ requested action user
+ DIRECT_DEBITING
+
+ PendingE Failure to send, temporary Grant Idle
+ error, or failed CC event service
+ answer received; requested to end
+ action DIRECT_DEBITING; user
+ DDFH equal to CONTINUE
+
+ PendingE Failed CC event Terminate Idle
+ answer received or temporary end user's
+ error; requested action service
+ DIRECT_DEBITING;
+ DDFH equal to
+ TERMINATE_OR_BUFFER and
+ Tx running
+
+ PendingE Tx expired; requested Grant PendingE
+ action DIRECT_DEBITING service
+ to end
+ user
+
+ PendingE Failure to send; requested Store Idle
+ action DIRECT_DEBITING; request with
+ DDFH equal to T-flag
+ TERMINATE_OR_BUFFER
+
+ PendingE Temporary error; requested Store Idle
+ action DIRECT_DEBITING; request
+ DDFH equal to
+ TERMINATE_OR_BUFFER;
+ Tx expired
+
+ PendingE Failed answer or answer Idle
+ received with result code
+ END_USER_SERVICE DENIED or
+ USER_UNKNOWN; requested action
+ DIRECT_DEBITING; Tx expired
+
+ PendingE Failed CC event answer Indicate Idle
+ received; requested service
+ action REFUND_ACCOUNT error and
+ delete request
+
+
+
+
+
+Hakala, et al. Standards Track [Page 53]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ PendingE Failure to send or Store Idle
+ Tx expired; requested request
+ action REFUND_ACCOUNT with T-flag
+
+ PendingE Temporary error, Store Idle
+ and requested action request
+ REFUND_ACCOUNT
+
+ PendingB Successful CC answer Delete Idle
+ received request
+
+ PendingB Failed CC answer Delete Idle
+ received request
+
+ PendingB Failure to send or Idle
+ temporary error
+
+ SERVER, SESSION AND EVENT BASED
+
+ State Event Action New State
+ ----------------------------------------------------------------
+
+ Idle CC initial request Send Open
+ received and successfully CC initial
+ processed answer,
+ reserve units,
+ start Tcc
+
+ Idle CC initial request Send Idle
+ received but not CC initial
+ successfully processed answer with
+ Result-Code
+ != SUCCESS
+
+ Idle CC event request Send Idle
+ received and successfully CC event
+ processed answer
+
+ Idle CC event request Send Idle
+ received but not CC event
+ successfully processed answer with
+ Result-Code
+ != SUCCESS
+
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 54]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ Open CC update request Send CC Open
+ received and successfully update answer,
+ processed debit used
+ units,
+ reserve
+ new units,
+ restart Tcc
+
+ Open CC update request Send Idle
+ received but not CC update
+ successfully processed answer with
+ Result-Code
+ != SUCCESS,
+ debit used
+ units
+
+ Open CC termination request Send Idle
+ received and successfully CC termin.
+ processed answer,
+ Stop Tcc,
+ debit used
+ units
+
+ Open CC termination request Send Idle
+ received but not CC termin.
+ successfully processed answer with
+ Result-Code
+ != SUCCESS,
+ debit used
+ units
+
+ Open Session supervision timer Tcc Release Idle
+ expired reserved
+ units
+
+8. Credit-Control AVPs
+
+ This section defines the credit-control AVPs that are specific to
+ Diameter credit-control application and that MAY be included in the
+ Diameter credit-control messages.
+
+ The AVPs defined in this section MAY also be included in
+ authorization commands defined in authorization-specific
+ applications, such as [NASREQ] and [DIAMMIP], if the first
+ interrogation is performed as part of the
+ authorization/authentication process, as described in section 5.2.
+
+
+
+
+
+Hakala, et al. Standards Track [Page 55]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ The Diameter AVP rules are defined in the Diameter Base [DIAMBASE],
+ section 4. These AVP rules are observed in AVPs defined in this
+ section.
+
+ The following table describes the Diameter AVPs defined in the
+ credit-control application, their AVP Code values, types, possible
+ flag values, and whether the AVP MAY be encrypted. The Diameter base
+ [DIAMBASE] specifies the AVP Flag rules for AVPs in section 4.5.
+
+ +--------------------+
+ | AVP Flag rules |
+ |----+-----+----+----|----+
+ AVP Section | | |SHLD|MUST| |
+ Attribute Name Code Defined Data Type |MUST| MAY | NOT|NOT |Encr|
+ -----------------------------------------|----+-----+----+----|----|
+ CC-Correlation-Id 411 8.1 OctetString| | P,M | | V | Y |
+ CC-Input-Octets 412 8.24 Unsigned64 | M | P | | V | Y |
+ CC-Money 413 8.22 Grouped | M | P | | V | Y |
+ CC-Output-Octets 414 8.25 Unsigned64 | M | P | | V | Y |
+ CC-Request-Number 415 8.2 Unsigned32 | M | P | | V | Y |
+ CC-Request-Type 416 8.3 Enumerated | M | P | | V | Y |
+ CC-Service- 417 8.26 Unsigned64 | M | P | | V | Y |
+ Specific-Units | | | | | |
+ CC-Session- 418 8.4 Enumerated | M | P | | V | Y |
+ Failover | | | | | |
+ CC-Sub-Session-Id 419 8.5 Unsigned64 | M | P | | V | Y |
+ CC-Time 420 8.21 Unsigned32 | M | P | | V | Y |
+ CC-Total-Octets 421 8.23 Unsigned64 | M | P | | V | Y |
+ CC-Unit-Type 454 8.32 Enumerated | M | P | | V | Y |
+ Check-Balance- 422 8.6 Enumerated | M | P | | V | Y |
+ Result | | | | | |
+ Cost-Information 423 8.7 Grouped | M | P | | V | Y |
+ Cost-Unit 424 8.12 UTF8String | M | P | | V | Y |
+ Credit-Control 426 8.13 Enumerated | M | P | | V | Y |
+ Credit-Control- 427 8.14 Enumerated | M | P | | V | Y |
+ Failure-Handling | | | | | |
+ Currency-Code 425 8.11 Unsigned32 | M | P | | V | Y |
+ Direct-Debiting- 428 8.15 Enumerated | M | P | | V | Y |
+ Failure-Handling | | | | | |
+ Exponent 429 8.9 Integer32 | M | P | | V | Y |
+ Final-Unit-Action 449 8.35 Enumerated | M | P | | V | Y |
+ Final-Unit- 430 8.34 Grouped | M | P | | V | Y |
+ Indication | | | | | |
+ Granted-Service- 431 8.17 Grouped | M | P | | V | Y |
+ Unit | | | | | |
+ G-S-U-Pool- 453 8.31 Unsigned32 | M | P | | V | Y |
+ Identifier | | | | | |
+
+
+
+
+Hakala, et al. Standards Track [Page 56]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ G-S-U-Pool- 457 8.30 Grouped | M | P | | V | Y |
+ Reference | | | | | |
+ Multiple-Services 456 8.16 Grouped | M | P | | V | Y |
+ -Credit-Control | | | | | |
+ Multiple-Services 455 8.40 Enumerated | M | P | | V | Y |
+ -Indicator | | | | | |
+ Rating-Group 432 8.29 Unsigned32 | M | P | | V | Y |
+ Redirect-Address 433 8.38 Enumerated | M | P | | V | Y |
+ -Type | | | | | |
+ Redirect-Server 434 8.37 Grouped | M | P | | V | Y |
+ Redirect-Server 435 8.39 UTF8String | M | P | | V | Y |
+ -Address | | | | | |
+ Requested-Action 436 8.41 Enumerated | M | P | | V | Y |
+ Requested-Service 437 8.18 Grouped | M | P | | V | Y |
+ -Unit | | | | | |
+ Restriction 438 8.36 IPFiltrRule| M | P | | V | Y |
+ -Filter-Rule | | | | | |
+ Service-Context 461 8.42 UTF8String | M | P | | V | Y |
+ -Id | | | | | |
+ Service- 439 8.28 Unsigned32 | M | P | | V | Y |
+ Identifier | | | | | |
+ Service-Parameter 440 8.43 Grouped | | P,M | | V | Y |
+ -Info | | | | | |
+ Service- 441 8.44 Unsigned32 | | P,M | | V | Y |
+ Parameter-Type | | | | | |
+ Service- 442 8.45 OctetString| | P,M | | V | Y |
+ Parameter-Value | | | | | |
+ Subscription-Id 443 8.46 Grouped | M | P | | V | Y |
+ Subscription-Id 444 8.48 UTF8String | M | P | | V | Y |
+ -Data | | | | | |
+ Subscription-Id 450 8.47 Enumerated | M | P | | V | Y |
+ -Type | | | | | |
+ Tariff-Change 452 8.27 Enumerated | M | P | | V | Y |
+ -Usage | | | | | |
+ Tariff-Time 451 8.20 Time | M | P | | V | Y |
+ -Change | | | | | |
+ Unit-Value 445 8.8 Grouped | M | P | | V | Y |
+ Used-Service-Unit 446 8.19 Grouped | M | P | | V | Y |
+ User-Equipment 458 8.49 Grouped | | P,M | | V | Y |
+ -Info | | | | | |
+ User-Equipment 459 8.50 Enumerated | | P,M | | V | Y |
+ -Info-Type | | | | | |
+ User-Equipment 460 8.51 OctetString| | P,M | | V | Y |
+ -Info-Value | | | | | |
+ Value-Digits 447 8.10 Integer64 | M | P | | V | Y |
+ Validity-Time 448 8.33 Unsigned32 | M | P | | V | Y |
+
+
+
+
+
+Hakala, et al. Standards Track [Page 57]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+8.1. CC-Correlation-Id AVP
+
+ The CC-Correlation-Id AVP (AVP Code 411) is of type OctetString and
+ contains information to correlate credit-control requests generated
+ for different components of the service; e.g., transport and service
+ level. The one who allocates the Service-Context-Id (i.e., unique
+ identifier of a service specific document) is also responsible for
+ defining the content and encoding of the CC-Correlation-Id AVP.
+
+8.2. CC-Request-Number AVP
+
+ The CC-Request-Number AVP (AVP Code 415) is of type Unsigned32 and
+ identifies this request within one session. As Session-Id AVPs are
+ globally unique, the combination of Session-Id and CC-Request-Number
+ AVPs is also globally unique and can be used in matching credit-
+ control messages with confirmations. An easy way to produce unique
+ numbers is to set the value to 0 for a credit-control request of type
+ INITIAL_REQUEST and EVENT_REQUEST and to set the value to 1 for the
+ first UPDATE_REQUEST, to 2 for the second, and so on until the value
+ for TERMINATION_REQUEST is one more than for the last UPDATE_REQUEST.
+
+8.3. CC-Request-Type AVP
+
+ The CC-Request-Type AVP (AVP Code 416) is of type Enumerated and
+ contains the reason for sending the credit-control request message.
+ It MUST be present in all Credit-Control-Request messages. The
+ following values are defined for the CC-Request-Type AVP:
+
+ INITIAL_REQUEST 1
+ An Initial request is used to initiate a credit-control session,
+ and contains credit control information that is relevant to the
+ initiation.
+
+ UPDATE_REQUEST 2
+ An Update request contains credit-control information for an
+ existing credit-control session. Update credit-control requests
+ SHOULD be sent every time a credit-control re-authorization is
+ needed at the expiry of the allocated quota or validity time.
+ Further, additional service-specific events MAY trigger a
+ spontaneous Update request.
+
+ TERMINATION_REQUEST 3
+ A Termination request is sent to terminate a credit-control
+ session and contains credit-control information relevant to the
+ existing session.
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 58]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ EVENT_REQUEST 4
+ An Event request is used when there is no need to maintain any
+ credit-control session state in the credit-control server. This
+ request contains all information relevant to the service, and is
+ the only request of the service. The reason for the Event request
+ is further detailed in the Requested-Action AVP. The Requested-
+ Action AVP MUST be included in the Credit-Control-Request message
+ when CC-Request-Type is set to EVENT_REQUEST.
+
+8.4. CC-Session-Failover AVP
+
+ The CC-Session-Failover AVP (AVP Code 418) is type of Enumerated and
+ contains information as to whether moving the credit-control message
+ stream to a backup server during an ongoing credit-control session is
+ supported. In communication failures, the credit-control message
+ streams can be moved to an alternative destination if the credit-
+ control server supports failover to an alternative server. The
+ secondary credit-control server name, if received from the home
+ Diameter AAA server, can be used as an address of the backup server.
+ An implementation is not required to support moving a credit-control
+ message stream to an alternative server, as this also requires moving
+ information related to the credit-control session to backup server.
+
+ The following values are defined for the CC-Session-Failover AVP:
+
+ FAILOVER_NOT_SUPPORTED 0
+ When the CC-Session-Failover AVP is set to FAILOVER_NOT_SUPPORTED,
+ the credit-control message stream MUST NOT to be moved to an
+ alternative destination in the case of communication failure.
+
+ This is the default behavior if the AVP isn't included in the
+ reply from the authorization or credit-control server.
+
+ FAILOVER_SUPPORTED 1
+ When the CC-Session-Failover AVP is set to FAILOVER_SUPPORTED, the
+ credit-control message stream SHOULD be moved to an alternative
+ destination in the case of communication failure. Moving the
+ credit-control message stream to a backup server MAY require that
+ information related to the credit-control session should also be
+ forwarded to alternative server.
+
+8.5. CC-Sub-Session-Id AVP
+
+ The CC-Sub-Session-Id AVP (AVP Code 419) is of type Unsigned64 and
+ contains the credit-control sub-session identifier. The combination
+ of the Session-Id and this AVP MUST be unique per sub-session, and
+
+
+
+
+
+Hakala, et al. Standards Track [Page 59]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ the value of this AVP MUST be monotonically increased by one for all
+ new sub-sessions. The absence of this AVP implies that no sub-
+ sessions are in use.
+
+8.6. Check-Balance-Result AVP
+
+ The Check Balance Result AVP (AVP Code 422) is of type Enumerated and
+ contains the result of the balance check. This AVP is applicable
+ only when the Requested-Action AVP indicates CHECK_BALANCE in the
+ Credit-Control-Request command.
+
+ The following values are defined for the Check-Balance-Result AVP.
+
+ ENOUGH_CREDIT 0
+ There is enough credit in the account to cover the requested
+ service.
+
+ NO_CREDIT 1
+ There isn't enough credit in the account to cover the requested
+ service.
+
+8.7. Cost-Information AVP
+
+ The Cost-Information AVP (AVP Code 423) is of type Grouped, and it is
+ used to return the cost information of a service, which the credit-
+ control client can transfer transparently to the end user. The
+ included Unit-Value AVP contains the cost estimate (always type of
+ money) of the service, in the case of price enquiry, or the
+ accumulated cost estimation, in the case of credit-control session.
+
+ The Currency-Code specifies in which currency the cost was given.
+ The Cost-Unit specifies the unit when the service cost is a cost per
+ unit (e.g., cost for the service is $1 per minute).
+
+ When the Requested-Action AVP with value PRICE_ENQUIRY is included in
+ the Credit-Control-Request command, the Cost-Information AVP sent in
+ the succeeding Credit-Control-Answer command contains the cost
+ estimation of the requested service, without any reservation being
+ made.
+
+ The Cost-Information AVP included in the Credit-Control-Answer
+ command with the CC-Request-Type set to UPDATE_REQUEST contains the
+ accumulated cost estimation for the session, without taking any
+ credit reservation into account.
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 60]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ The Cost-Information AVP included in the Credit-Control-Answer
+ command with the CC-Request-Type set to EVENT_REQUEST or
+ TERMINATION_REQUEST contains the estimated total cost for the
+ requested service.
+
+ It is defined as follows (per the grouped-avp-def of
+ RFC 3588 [DIAMBASE]):
+
+ Cost-Information ::= < AVP Header: 423 >
+ { Unit-Value }
+ { Currency-Code }
+ [ Cost-Unit ]
+
+8.8. Unit-Value AVP
+
+ Unit-Value AVP is of type Grouped (AVP Code 445) and specifies the
+ units as decimal value. The Unit-Value is a value with an exponent;
+ i.e., Unit-Value = Value-Digits AVP * 10^Exponent. This
+ representation avoids unwanted rounding off. For example, the value
+ of 2,3 is represented as Value-Digits = 23 and Exponent = -1. The
+ absence of the exponent part MUST be interpreted as an exponent equal
+ to zero.
+
+ It is defined as follows (per the grouped-avp-def of
+ RFC 3588 [DIAMBASE]):
+
+ Unit-Value ::= < AVP Header: 445 >
+ { Value-Digits }
+ [ Exponent ]
+
+8.9. Exponent AVP
+
+ Exponent AVP is of type Integer32 (AVP Code 429) and contains the
+ exponent value to be applied for the Value-Digit AVP within the
+ Unit-Value AVP.
+
+8.10. Value-Digits AVP
+
+ The Value-Digits AVP is of type Integer64 (AVP Code 447) and contains
+ the significant digits of the number. If decimal values are needed
+ to present the units, the scaling MUST be indicated with the related
+ Exponent AVP. For example, for the monetary amount $ 0.05 the value
+ of Value-Digits AVP MUST be set to 5, and the scaling MUST be
+ indicated with the Exponent AVP set to -2.
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 61]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+8.11. Currency-Code AVP
+
+ The Currency-Code AVP (AVP Code 425) is of type Unsigned32 and
+ contains a currency code that specifies in which currency the values
+ of AVPs containing monetary units were given. It is specified by
+ using the numeric values defined in the ISO 4217 standard [ISO4217].
+
+8.12. Cost-Unit AVP
+
+ The Cost-Unit AVP (AVP Code 424) is of type UTF8String, and it is
+ used to display a human readable string to the end user. It
+ specifies the applicable unit to the Cost-Information when the
+ service cost is a cost per unit (e.g., cost of the service is $1 per
+ minute). The Cost-Unit can be minutes, hours, days, kilobytes,
+ megabytes, etc.
+
+8.13. Credit-Control AVP
+
+ The Credit-Control AVP (AVP Code 426) is of type Enumerated and MUST
+ be included in AA requests when the service element has credit-
+ control capabilities.
+
+ CREDIT_AUTHORIZATION 0
+ If the home Diameter AAA server determines that the user has
+ prepaid subscription, this value indicates that the credit-control
+ server MUST be contacted to perform the first interrogation. The
+ value of the Credit-Control AVP MUST always be set to 0 in an AA
+ request sent to perform the first interrogation and to initiate a
+ new credit-control session.
+
+ RE_AUTHORIZATION 1
+ This value indicates to the Diameter AAA server that a credit-
+ control session is ongoing for the subscriber and that the
+ credit-control server MUST not be contacted. The Credit-Control
+ AVP set to the value of 1 is to be used only when the first
+ interrogation has been successfully performed and the credit-
+ control session is ongoing (i.e., re-authorization triggered by
+ Authorization-Lifetime). This value MUST NOT be used in an AA
+ request sent to perform the first interrogation.
+
+8.14. Credit-Control-Failure-Handling AVP
+
+ The Credit-Control-Failure-Handling AVP (AVP Code 427) is of type
+ Enumerated. The credit-control client uses information in this AVP
+ to decide what to do if sending credit-control messages to the
+ credit-control server has been, for instance, temporarily prevented
+ due to a network problem. Depending on the service logic, the
+ credit-control server can order the client to terminate the service
+
+
+
+Hakala, et al. Standards Track [Page 62]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ immediately when there is a reason to believe that the service cannot
+ be charged, or to try failover to an alternative server, if possible.
+ Then the server could either terminate or grant the service, should
+ the alternative connection also fail.
+
+ TERMINATE 0
+ When the Credit-Control-Failure-Handling AVP is set to TERMINATE,
+ the service MUST only be granted for as long as there is a
+ connection to the credit-control server. If the credit-control
+ client does not receive any Credit-Control-Answer message within
+ the Tx timer (as defined in section 13), the credit-control
+ request is regarded as failed, and the end user's service session
+ is terminated.
+
+ This is the default behavior if the AVP isn't included in the
+ reply from the authorization or credit-control server.
+
+ CONTINUE 1
+ When the Credit-Control-Failure-Handling AVP is set to CONTINUE,
+ the credit-control client SHOULD re-send the request to an
+ alternative server in the case of transport or temporary failures,
+ provided that a failover procedure is supported in the credit-
+ control server and the credit-control client, and that an
+ alternative server is available. Otherwise, the service SHOULD be
+ granted, even if credit-control messages can't be delivered.
+
+ RETRY_AND_TERMINATE 2
+ When the Credit-Control-Failure-Handling AVP is set to
+ RETRY_AND_TERMINATE, the credit-control client SHOULD re-send the
+ request to an alternative server in the case of transport or
+ temporary failures, provided that a failover procedure is
+ supported in the credit-control server and the credit-control
+ client, and that an alternative server is available. Otherwise,
+ the service SHOULD not be granted when the credit-control messages
+ can't be delivered.
+
+8.15. Direct-Debiting-Failure-Handling AVP
+
+ The Direct-Debiting-Failure-Handling AVP (AVP Code 428) is of type
+ Enumerated. The credit-control client uses information in this AVP
+ to decide what to do if sending credit-control messages (Requested-
+ Action AVP set to DIRECT_DEBITING) to the credit-control server has
+ been, for instance, temporarily prevented due to a network problem.
+
+ TERMINATE_OR_BUFFER 0
+ When the Direct-Debiting-Failure-Handling AVP is set to
+ TERMINATE_OR_BUFFER, the service MUST be granted for as long as
+ there is a connection to the credit-control server. If the
+
+
+
+Hakala, et al. Standards Track [Page 63]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ credit-control client does not receive any Credit-Control-Answer
+ message within the Tx timer (as defined in section 13) the
+ credit-control request is regarded as failed. The client SHOULD
+ terminate the service if it can determine from the failed answer
+ that units have not been debited. Otherwise the credit-control
+ client SHOULD grant the service, store the request in application
+ level non-volatile storage, and try to re-send the request. These
+ requests MUST be marked as possible duplicates by setting the T-
+ flag in the command header as described in [DIAMBASE] section 3.
+
+ This is the default behavior if the AVP isn't included in the
+ reply from the authorization server.
+
+ CONTINUE 1
+ When the Direct-Debiting-Failure-Handling AVP is set to CONTINUE,
+ the service SHOULD be granted, even if credit-control messages
+ can't be delivered, and the request should be deleted.
+
+8.16. Multiple-Services-Credit-Control AVP
+
+ Multiple-Services-Credit-Control AVP (AVP Code 456) is of type
+ Grouped and contains the AVPs related to the independent credit-
+ control of multiple services feature. Note that each instance of
+ this AVP carries units related to one or more services or related to
+ a single rating group.
+
+ The Service-Identifier and the Rating-Group AVPs are used to
+ associate the granted units to a given service or rating group. If
+ both the Service-Identifier and the Rating-Group AVPs are included,
+ the target of the service units is always the service(s) indicated by
+ the value of the Service-Identifier AVP(s). If only the Rating-
+ Group-Id AVP is present, the Multiple-Services-Credit-Control AVP
+ relates to all the services that belong to the specified rating
+ group.
+
+ The G-S-U-Pool-Reference AVP allows the server to specify a G-S-U-
+ Pool-Identifier identifying a credit pool within which the units of
+ the specified type are considered pooled. If a G-S-U-Pool-Reference
+ AVP is present, then actual service units of the specified type MUST
+ also be present. For example, if the G-S-U-Pool-Reference AVP
+ specifies Unit-Type TIME, then the CC-Time AVP MUST be present.
+
+ The Requested-Service-Unit AVP MAY contain the amount of requested
+ service units or the requested monetary value. It MUST be present in
+ the initial interrogation and within the intermediate interrogations
+ in which new quota is requested. If the credit-control client does
+ not include the Requested-Service-Unit AVP in a request command,
+ because for instance, it has determined that the end-user terminated
+
+
+
+Hakala, et al. Standards Track [Page 64]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ the service, the server MUST debit the used amount from the user's
+ account but MUST NOT return a new quota in the corresponding answer.
+ The Validity-Time, Result-Code, and Final-Unit-Indication AVPs MAY be
+ present in an answer command as defined in sections 5.1.2 and 5.6 for
+ the graceful service termination.
+
+ When both the Tariff-Time-Change and Tariff-Change-Usage AVPs are
+ present, the server MUST include two separate instances of the
+ Multiple-Services-Credit-Control AVP with the Granted-Service-Unit
+ AVP associated to the same service-identifier and/or rating-group.
+ Where the two quotas are associated to the same pool or to different
+ pools, the credit pooling mechanism defined in section 5.1.2 applies.
+ The Tariff-Change-Usage AVP MUST NOT be included in request commands
+ to report used units before, and after tariff time change the Used-
+ Service-Unit AVP MUST be used.
+
+ A server not implementing the independent credit-control of multiple
+ services functionality MUST treat the Multiple-Services-Credit-
+ Control AVP as an invalid AVP.
+
+ The Multiple-Services-Control AVP is defined as follows (per the
+ grouped-avp-def of RFC 3588 [DIAMBASE]):
+
+ Multiple-Services-Credit-Control ::= < AVP Header: 456 >
+ [ Granted-Service-Unit ]
+ [ Requested-Service-Unit ]
+ *[ Used-Service-Unit ]
+ [ Tariff-Change-Usage ]
+ *[ Service-Identifier ]
+ [ Rating-Group ]
+ *[ G-S-U-Pool-Reference ]
+ [ Validity-Time ]
+ [ Result-Code ]
+ [ Final-Unit-Indication ]
+ *[ AVP ]
+
+8.17. Granted-Service-Unit AVP
+
+ Granted-Service-Unit AVP (AVP Code 431) is of type Grouped and
+ contains the amount of units that the Diameter credit-control client
+ can provide to the end user until the service must be released or the
+ new Credit-Control-Request must be sent. A client is not required to
+ implement all the unit types, and it must treat unknown or
+ unsupported unit types in the answer message as an incorrect CCA
+ answer. In this case, the client MUST terminate the credit-control
+ session and indicate in the Termination-Cause AVP reason
+ DIAMETER_BAD_ANSWER.
+
+
+
+
+Hakala, et al. Standards Track [Page 65]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ The Granted-Service-Unit AVP is defined as follows (per the grouped-
+ avp-def of RFC 3588 [DIAMBASE]):
+
+ Granted-Service-Unit ::= < AVP Header: 431 >
+ [ Tariff-Time-Change ]
+ [ CC-Time ]
+ [ CC-Money ]
+ [ CC-Total-Octets ]
+ [ CC-Input-Octets ]
+ [ CC-Output-Octets ]
+ [ CC-Service-Specific-Units ]
+ *[ AVP ]
+
+8.18. Requested-Service-Unit AVP
+
+ The Requested-Service-Unit AVP (AVP Code 437) is of type Grouped and
+ contains the amount of requested units specified by the Diameter
+ credit-control client. A server is not required to implement all the
+ unit types, and it must treat unknown or unsupported unit types as
+ invalid AVPs.
+
+ The Requested-Service-Unit AVP is defined as follows (per the
+ grouped-avp-def of RFC 3588 [DIAMBASE]):
+
+ Requested-Service-Unit ::= < AVP Header: 437 >
+ [ CC-Time ]
+ [ CC-Money ]
+ [ CC-Total-Octets ]
+ [ CC-Input-Octets ]
+ [ CC-Output-Octets ]
+ [ CC-Service-Specific-Units ]
+ *[ AVP ]
+
+8.19. Used-Service-Unit AVP
+
+ The Used-Service-Unit AVP is of type Grouped (AVP Code 446) and
+ contains the amount of used units measured from the point when the
+ service became active or, if interim interrogations are used during
+ the session, from the point when the previous measurement ended.
+
+
+
+
+
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 66]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ The Used-Service-Unit AVP is defined as follows (per the grouped-
+ avp-def of RFC 3588 [DIAMBASE]):
+
+ Used-Service-Unit ::= < AVP Header: 446 >
+ [ Tariff-Change-Usage ]
+ [ CC-Time ]
+ [ CC-Money ]
+ [ CC-Total-Octets ]
+ [ CC-Input-Octets ]
+ [ CC-Output-Octets ]
+ [ CC-Service-Specific-Units ]
+ *[ AVP ]
+
+8.20. Tariff-Time-Change AVP
+
+ The Tariff-Time-Change AVP (AVP Code 451) is of type Time. It is
+ sent from the server to the client and includes the time in seconds
+ since January 1, 1900, 00:00 UTC, when the tariff of the service will
+ be changed.
+
+ The tariff change mechanism is optional for the client and server,
+ and it is not used for time-based services defined in section 5. If
+ a client does not support the tariff time change mechanism, it MUST
+ treat Tariff-Time-Change AVP in the answer message as an incorrect
+ CCA answer. In this case, the client terminates the credit-control
+ session and indicates in the Termination-Cause AVP reason
+ DIAMETER_BAD_ANSWER.
+
+ Omission of this AVP means that no tariff change is to be reported.
+
+8.21. CC-Time AVP
+
+ The CC-Time AVP (AVP Code 420) is of type Unsigned32 and indicates
+ the length of the requested, granted, or used time in seconds.
+
+8.22. CC-Money AVP
+
+ The CC-Money AVP (AVP Code 413) is of type Grouped and specifies the
+ monetary amount in the given currency. The Currency-Code AVP SHOULD
+ be included. It is defined as follows (per the grouped-avp-def of
+ RFC 3588 [DIAMBASE]):
+
+ CC-Money ::= < AVP Header: 413 >
+ { Unit-Value }
+ [ Currency-Code ]
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 67]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+8.23. CC-Total-Octets AVP
+
+ The CC-Total-Octets AVP (AVP Code 421) is of type Unsigned64 and
+ contains the total number of requested, granted, or used octets
+ regardless of the direction (sent or received).
+
+8.24. CC-Input-Octets AVP
+
+ The CC-Input-Octets AVP (AVP Code 412) is of type Unsigned64 and
+ contains the number of requested, granted, or used octets that can
+ be/have been received from the end user.
+
+8.25. CC-Output-Octets AVP
+
+ The CC-Output-Octets AVP (AVP Code 414) is of type Unsigned64 and
+ contains the number of requested, granted, or used octets that can
+ be/have been sent to the end user.
+
+8.26. CC-Service-Specific-Units AVP
+
+ The CC-Service-Specific-Units AVP (AVP Code 417) is of type
+ Unsigned64 and specifies the number of service-specific units (e.g.,
+ number of events, points) given in a selected service. The service-
+ specific units always refer to the service identified in the
+ Service-Identifier AVP (or Rating-Group AVP when the Multiple-
+ Services-Credit-Control AVP is used).
+
+8.27. Tariff-Change-Usage AVP
+
+ The Tariff-Change-Usage AVP (AVP Code 452) is of type Enumerated and
+ defines whether units are used before or after a tariff change, or
+ whether the units straddled a tariff change during the reporting
+ period. Omission of this AVP means that no tariff change has
+ occurred.
+
+ In addition, when present in answer messages as part of the
+ Multiple-Services-Credit-Control AVP, this AVP defines whether units
+ are allocated to be used before or after a tariff change event.
+
+ When the Tariff-Time-Change AVP is present, omission of this AVP in
+ answer messages means that the single quota mechanism applies.
+
+ Tariff-Change-Usage can be one of the following:
+
+ UNIT_BEFORE_TARIFF_CHANGE 0
+ When present in the Multiple-Services-Credit-Control AVP, this
+ value indicates the amount of the units allocated for use before a
+ tariff change occurs.
+
+
+
+Hakala, et al. Standards Track [Page 68]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ When present in the Used-Service-Unit AVP, this value indicates
+ the amount of resource units used before a tariff change had
+ occurred.
+
+ UNIT_AFTER_TARIFF_CHANGE 1
+ When present in the Multiple-Services-Credit-Control AVP, this
+ value indicates the amount of the units allocated for use after a
+ tariff change occurs.
+
+ When present in the Used-Service-Unit AVP, this value indicates
+ the amount of resource units used after tariff change had
+ occurred.
+
+ UNIT_INDETERMINATE 2
+ The used unit contains the amount of units that straddle the
+ tariff change (e.g., the metering process reports to the credit-
+ control client in blocks of n octets, and one block straddled the
+ tariff change). This value is to be used only in the Used-
+ Service-Unit AVP.
+
+8.28. Service-Identifier AVP
+
+ The Service-Identifier AVP is of type Unsigned32 (AVP Code 439) and
+ contains the identifier of a service. The specific service the
+ request relates to is uniquely identified by the combination of
+ Service-Context-Id and Service-Identifier AVPs.
+
+ A usage example of this AVP is illustrated in Appendix A (Flow IX).
+
+8.29. Rating-Group AVP
+
+ The Rating-Group AVP is of type Unsigned32 (AVP Code 432) and
+ contains the identifier of a rating group. All the services subject
+ to the same rating type are part of the same rating group. The
+ specific rating group the request relates to is uniquely identified
+ by the combination of Service-Context-Id and Rating-Group AVPs.
+
+ A usage example of this AVP is illustrated in Appendix A (Flow IX).
+
+8.30. G-S-U-Pool-Reference AVP
+
+ The G-S-U-Pool-Reference AVP (AVP Code 457) is of type Grouped. It
+ is used in the Credit-Control-Answer message, and associates the
+ Granted-Service-Unit AVP within which it appears with a credit pool
+ within the session.
+
+ The G-S-U-Pool-Identifier AVP specifies the credit pool from which
+ credit is drawn for this unit type.
+
+
+
+Hakala, et al. Standards Track [Page 69]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ The CC-Unit-Type AVP specifies the type of units for which credit is
+ pooled.
+
+ The Unit-Value AVP specifies the multiplier, which converts between
+ service units of type CC-Unit-Type and abstract service units within
+ the credit pool (and thus to service units of any other service or
+ rating group associated with the same pool).
+
+ The G-S-U-Pool-Reference AVP is defined as follows (per the grouped-
+ avp-def of RFC 3588 [DIAMBASE]):
+
+ G-S-U-Pool-Reference ::= < AVP Header: 457 >
+ { G-S-U-Pool-Identifier }
+ { CC-Unit-Type }
+ { Unit-Value }
+
+8.31. G-S-U-Pool-Identifier AVP
+
+ The G-S-U-Pool-Identifier AVP (AVP Code 453) is of type Unsigned32
+ and identifies a credit pool within the session.
+
+8.32. CC-Unit-Type AVP
+
+ The CC-Unit-Type AVP (AVP Code 454) is of type Enumerated and
+ specifies the type of units considered to be pooled into a credit
+ pool.
+
+ The following values are defined for the CC-Unit-Type AVP:
+
+ TIME 0
+ MONEY 1
+ TOTAL-OCTETS 2
+ INPUT-OCTETS 3
+ OUTPUT-OCTETS 4
+ SERVICE-SPECIFIC-UNITS 5
+
+8.33. Validity-Time AVP
+
+ The Validity-Time AVP is of type Unsigned32 (AVP Code 448). It is
+ sent from the credit-control server to the credit-control client.
+ The AVP contains the validity time of the granted service units. The
+ measurement of the Validity-Time is started upon receipt of the
+ Credit-Control-Answer Message containing this AVP. If the granted
+ service units have not been consumed within the validity time
+ specified in this AVP, the credit-control client MUST send a Credit-
+ Control-Request message to the server, with CC-Request-Type set to
+ UPDATE_REQUEST. The value field of the Validity-Time AVP is given in
+ seconds.
+
+
+
+Hakala, et al. Standards Track [Page 70]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ The Validity-Time AVP is also used for the graceful service
+ termination (see section 5.6) to indicate to the credit-control
+ client how long the subscriber is allowed to use network resources
+ after the specified action (i.e., REDIRECT or RESTRICT_ACCESS)
+ started. When the Validity-Time elapses, a new intermediate
+ interrogation is sent to the server.
+
+8.34. Final-Unit-Indication AVP
+
+ The Final-Unit-Indication AVP (AVP Code 430) is of type Grouped and
+ indicates that the Granted-Service-Unit AVP in the Credit-Control-
+ Answer, or in the AA answer, contains the final units for the
+ service. After these units have expired, the Diameter credit-control
+ client is responsible for executing the action indicated in the
+ Final-Unit-Action AVP (see section 5.6).
+
+ If more than one unit type is received in the Credit-Control-Answer,
+ the unit type that first expired SHOULD cause the credit-control
+ client to execute the specified action.
+
+ In the first interrogation, the Final-Unit-Indication AVP with
+ Final-Unit-Action REDIRECT or RESTRICT_ACCESS can also be present
+ with no Granted-Service-Unit AVP in the Credit-Control-Answer or in
+ the AA answer. This indicates to the Diameter credit-control client
+ to execute the specified action immediately. If the home service
+ provider policy is to terminate the service, naturally, the server
+ SHOULD return the appropriate transient failure (see section 9.1) in
+ order to implement the policy-defined action.
+
+ The Final-Unit-Action AVP defines the behavior of the service element
+ when the user's account cannot cover the cost of the service and MUST
+ always be present if the Final-Unit-Indication AVP is included in a
+ command.
+
+ If the Final-Unit-Action AVP is set to TERMINATE, no other AVPs MUST
+ be present.
+
+ If the Final-Unit-Action AVP is set to REDIRECT at least the
+ Redirect-Server AVP MUST be present. The Restriction-Filter-Rule AVP
+ or the Filter-Id AVP MAY be present in the Credit-Control-Answer
+ message if the user is also allowed to access other services that are
+ not accessible through the address given in the Redirect-Server AVP.
+
+ If the Final-Unit-Action AVP is set to RESTRICT_ACCESS, either the
+ Restriction-Filter-Rule AVP or the Filter-Id AVP SHOULD be present.
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 71]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ The Filter-Id AVP is defined in [NASREQ]. The Filter-Id AVP can be
+ used to reference an IP filter list installed in the access device by
+ means other than the Diameter credit-control application, e.g.,
+ locally configured or configured by another entity.
+
+ The Final-Unit-Indication AVP is defined as follows (per the
+ grouped-avp-def of RFC 3588 [DIAMBASE]):
+
+ Final-Unit-Indication ::= < AVP Header: 430 >
+ { Final-Unit-Action }
+ *[ Restriction-Filter-Rule ]
+ *[ Filter-Id ]
+ [ Redirect-Server ]
+
+8.35. Final-Unit-Action AVP
+
+ The Final-Unit-Action AVP (AVP Code 449) is of type Enumerated and
+ indicates to the credit-control client the action to be taken when
+ the user's account cannot cover the service cost.
+
+ The Final-Unit-Action can be one of the following:
+
+ TERMINATE 0
+ The credit-control client MUST terminate the service session.
+ This is the default handling, applicable whenever the credit-
+ control client receives an unsupported Final-Unit-Action value,
+ and it MUST be supported by all the Diameter credit-control client
+ implementations conforming to this specification.
+
+ REDIRECT 1
+ The service element MUST redirect the user to the address
+ specified in the Redirect-Server-Address AVP. The redirect action
+ is defined in section 5.6.2.
+
+ RESTRICT_ACCESS 2
+ The access device MUST restrict the user access according to the
+ IP packet filters defined in the Restriction-Filter-Rule AVP or
+ according to the IP packet filters identified by the Filter-Id
+ AVP. All the packets not matching the filters MUST be dropped
+ (see section 5.6.3).
+
+8.36. Restriction-Filter-Rule AVP
+
+ The Restriction-Filter-Rule AVP (AVP Code 438) is of type
+ IPFilterRule and provides filter rules corresponding to services that
+ are to remain accessible even if there are no more service units
+ granted. The access device has to configure the specified filter
+
+
+
+
+Hakala, et al. Standards Track [Page 72]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ rules for the subscriber and MUST drop all the packets not matching
+ these filters. Zero, one, or more such AVPs MAY be present in a
+ Credit-Control-Answer message or in an AA answer message.
+
+8.37. Redirect-Server AVP
+
+ The Redirect-Server AVP (AVP Code 434) is of type Grouped and
+ contains the address information of the redirect server (e.g., HTTP
+ redirect server, SIP Server) with which the end user is to be
+ connected when the account cannot cover the service cost. It MUST be
+ present when the Final-Unit-Action AVP is set to REDIRECT.
+
+ It is defined as follows (per the grouped-avp-def of RFC 3588
+ [DIAMBASE]):
+
+ Redirect-Server ::= < AVP Header: 434 >
+ { Redirect-Address-Type }
+ { Redirect-Server-Address }
+
+8.38. Redirect-Address-Type AVP
+
+ The Redirect-Address-Type AVP (AVP Code 433) is of type Enumerated
+ and defines the address type of the address given in the Redirect-
+ Server-Address AVP.
+
+ The address type can be one of the following:
+
+ IPv4 Address 0
+ The address type is in the form of "dotted-decimal" IPv4 address,
+ as defined in [IPv4].
+
+ IPv6 Address 1
+ The address type is in the form of IPv6 address, as defined in
+ [IPv6Addr]. The address is a text representation of the address
+ in either the preferred or alternate text form [IPv6Addr].
+ Conformant implementations MUST support the preferred form and
+ SHOULD support the alternate text form for IPv6 addresses.
+
+ URL 2
+ The address type is in the form of Uniform Resource Locator, as
+ defined in [URL].
+
+ SIP URI 3
+ The address type is in the form of SIP Uniform Resource
+ Identifier, as defined in [SIP].
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 73]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+8.39. Redirect-Server-Address AVP
+
+ The Redirect-Server-Address AVP (AVP Code 435) is of type UTF8String
+ and defines the address of the redirect server (e.g., HTTP redirect
+ server, SIP Server) with which the end user is to be connected when
+ the account cannot cover the service cost.
+
+8.40. Multiple-Services-Indicator AVP
+
+ The Multiple-Services-Indicator AVP (AVP Code 455) is of type
+ Enumerated and indicates whether the Diameter credit-control client
+ is capable of handling multiple services independently within a
+ (sub-) session. The absence of this AVP means that independent
+ credit-control of multiple services is not supported.
+
+ A server not implementing the independent credit-control of multiple
+ services MUST treat the Multiple-Services-Indicator AVP as an invalid
+ AVP.
+
+ The following values are defined for the Multiple-Services-Indicator
+ AVP:
+
+ MULTIPLE_SERVICES_NOT_SUPPORTED 0
+ Client does not support independent credit-control of multiple
+ services within a (sub-)session.
+
+ MULTIPLE_SERVICES_SUPPORTED 1
+ Client supports independent credit-control of multiple services
+ within a (sub-)session.
+
+8.41. Requested-Action AVP
+
+ The Requested-Action AVP (AVP Code 436) is of type Enumerated and
+ contains the requested action being sent by Credit-Control-Request
+ command where the CC-Request-Type is set to EVENT_REQUEST. The
+ following values are defined for the Requested-Action AVP:
+
+ DIRECT_DEBITING 0
+ This indicates a request to decrease the end user's account
+ according to information specified in the Requested-Service-Unit
+ AVP and/or Service-Identifier AVP (additional rating information
+ may be included in service-specific AVPs or in the Service-
+ Parameter-Info AVP). The Granted-Service-Unit AVP in the Credit-
+ Control-Answer command contains the debited units.
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 74]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ REFUND_ACCOUNT 1
+ This indicates a request to increase the end user's account
+ according to information specified in the Requested-Service-Unit
+ AVP and/or Service-Identifier AVP (additional rating information
+ may be included in service-specific AVPs or in the Service-
+ Parameter-Info AVP). The Granted-Service-Unit AVP in the Credit-
+ Control-Answer command contains the refunded units.
+
+ CHECK_BALANCE 2
+ This indicates a balance check request. In this case, the
+ checking of the account balance is done without any credit
+ reservation from the account. The Check-Balance-Result AVP in the
+ Credit-Control-Answer command contains the result of the balance
+ check.
+
+ PRICE_ENQUIRY 3
+ This indicates a price enquiry request. In this case, neither
+ checking of the account balance nor reservation from the account
+ will be done; only the price of the service will be returned in
+ the Cost-Information AVP in the Credit-Control-Answer Command.
+
+8.42. Service-Context-Id AVP
+
+ The Service-Context-Id AVP is of type UTF8String (AVP Code 461) and
+ contains a unique identifier of the Diameter credit-control service
+ specific document that applies to the request (as defined in section
+ 4.1.2). This is an identifier allocated by the service provider, by
+ the service element manufacturer, or by a standardization body, and
+ MUST uniquely identify a given Diameter credit-control service
+ specific document. The format of the Service-Context-Id is:
+
+ "service-context" "@" "domain"
+
+ service-context = Token
+
+ The Token is an arbitrary string of characters and digits.
+
+ 'domain' represents the entity that allocated the Service-Context-Id.
+ It can be ietf.org, 3gpp.org, etc., if the identifier is allocated by
+ a standardization body, or it can be the FQDN of the service provider
+ (e.g., provider.example.com) or of the vendor (e.g.,
+ vendor.example.com) if the identifier is allocated by a private
+ entity.
+
+ This AVP SHOULD be placed as close to the Diameter header as
+ possible.
+
+
+
+
+
+Hakala, et al. Standards Track [Page 75]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ Service-specific documents that are for private use only (i.e., to
+ one provider's own use, where no interoperability is deemed useful)
+ may define private identifiers without need of coordination.
+ However, when interoperability is wanted, coordination of the
+ identifiers via, for example, publication of an informational RFC is
+ RECOMMENDED in order to make Service-Context-Id globally available.
+
+8.43. Service-Parameter-Info AVP
+
+ The Service-Parameter-Info AVP (AVP Code 440) is of type Grouped and
+ contains service-specific information used for price calculation or
+ rating. The Service-Parameter-Type AVP defines the service parameter
+ type, and the Service-Parameter-Value AVP contains the parameter
+ value. The actual contents of these AVPs are not within the scope of
+ this document and SHOULD be defined in another Diameter application,
+ in standards written by other standardization bodies, or in service-
+ specific documentation.
+
+ In the case of an unknown service request (e.g., unknown Service-
+ Parameter-Type), the corresponding answer message MUST contain the
+ error code DIAMETER_RATING_FAILED. A Credit-Control-Answer message
+ with this error MUST contain one or more Failed-AVP AVPs containing
+ the Service-Parameter-Info AVPs that caused the failure.
+
+ It is defined as follows (per the grouped-avp-def of RFC 3588
+ [DIAMBASE]):
+
+ Service-Parameter-Info ::= < AVP Header: 440 >
+ { Service-Parameter-Type }
+ { Service-Parameter-Value }
+
+8.44. Service-Parameter-Type AVP
+
+ The Service-Parameter-Type AVP is of type Unsigned32 (AVP Code 441)
+ and defines the type of the service event specific parameter (e.g.,
+ it can be the end-user location or service name). The different
+ parameters and their types are service specific, and the meanings of
+ these parameters are not defined in this document. Whoever allocates
+ the Service-Context-Id (i.e., unique identifier of a service-specific
+ document) is also responsible for assigning Service-Parameter-Type
+ values for the service and ensuring their uniqueness within the given
+ service. The Service-Parameter-Value AVP contains the value
+ associated with the service parameter type.
+
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 76]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+8.45. Service-Parameter-Value AVP
+
+ The Service-Parameter-Value AVP is of type OctetString (AVP Code 442)
+ and contains the value of the service parameter type.
+
+8.46. Subscription-Id AVP
+
+ The Subscription-Id AVP (AVP Code 443) is used to identify the end
+ user's subscription and is of type Grouped. The Subscription-Id AVP
+ includes a Subscription-Id-Data AVP that holds the identifier and a
+ Subscription-Id-Type AVP that defines the identifier type.
+
+ It is defined as follows (per the grouped-avp-def of RFC 3588
+ [DIAMBASE]):
+
+ Subscription-Id ::= < AVP Header: 443 >
+ { Subscription-Id-Type }
+ { Subscription-Id-Data }
+
+8.47. Subscription-Id-Type AVP
+
+ The Subscription-Id-Type AVP (AVP Code 450) is of type Enumerated,
+ and it is used to determine which type of identifier is carried by
+ the Subscription-Id AVP.
+
+ This specification defines the following subscription identifiers.
+ However, new Subscription-Id-Type values can be assigned by an IANA
+ designated expert, as defined in section 12. A server MUST implement
+ all the Subscription-Id-Types required to perform credit
+ authorization for the services it supports, including possible future
+ values. Unknown or unsupported Subscription-Id-Types MUST be treated
+ according to the 'M' flag rule, as defined in [DIAMBASE].
+
+ END_USER_E164 0
+ The identifier is in international E.164 format (e.g., MSISDN),
+ according to the ITU-T E.164 numbering plan defined in [E164] and
+ [CE164].
+
+ END_USER_IMSI 1
+ The identifier is in international IMSI format, according to the
+ ITU-T E.212 numbering plan as defined in [E212] and [CE212].
+
+ END_USER_SIP_URI 2
+ The identifier is in the form of a SIP URI, as defined in [SIP].
+
+ END_USER_NAI 3
+ The identifier is in the form of a Network Access Identifier, as
+ defined in [NAI].
+
+
+
+Hakala, et al. Standards Track [Page 77]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ END_USER_PRIVATE 4
+ The Identifier is a credit-control server private identifier.
+
+8.48. Subscription-Id-Data AVP
+
+ The Subscription-Id-Data AVP (AVP Code 444) is used to identify the
+ end user and is of type UTF8String. The Subscription-Id-Type AVP
+ defines which type of identifier is used.
+
+8.49. User-Equipment-Info AVP
+
+ The User-Equipment-Info AVP (AVP Code 458) is of type Grouped and
+ allows the credit-control client to indicate the identity and
+ capability of the terminal the subscriber is using for the connection
+ to network.
+
+ It is defined as follows (per the grouped-avp-def of RFC 3588
+ [DIAMBASE]):
+
+ User-Equipment-Info ::= < AVP Header: 458 >
+ { User-Equipment-Info-Type }
+ { User-Equipment-Info-Value }
+
+8.50. User-Equipment-Info-Type AVP
+
+ The User-Equipment-Info-Type AVP is of type Enumerated (AVP Code
+ 459) and defines the type of user equipment information contained in
+ the User-Equipment-Info-Value AVP.
+
+ This specification defines the following user equipment types.
+ However, new User-Equipment-Info-Type values can be assigned by an
+ IANA designated expert, as defined in section 12.
+
+ IMEISV 0
+ The identifier contains the International Mobile Equipment
+ Identifier and Software Version in the international IMEISV format
+ according to 3GPP TS 23.003 [3GPPIMEI].
+
+ MAC 1
+ The 48-bit MAC address is formatted as described in [RAD802.1X].
+
+ EUI64 2
+ The 64-bit identifier used to identify hardware instance of the
+ product, as defined in [EUI64].
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 78]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ MODIFIED_EUI64 3
+ There are a number of types of terminals that have identifiers
+ other than IMEI, IEEE 802 MACs, or EUI-64. These identifiers can
+ be converted to modified EUI-64 format as described in [IPv6Addr]
+ or by using some other methods referred to in the service-specific
+ documentation.
+
+8.51. User-Equipment-Info-Value AVP
+
+ The User-Equipment-Info-Value AVP (AVP Code 460) is of type
+ OctetString. The User-Equipment-Info-Type AVP defines which type of
+ identifier is used.
+
+9. Result Code AVP Values
+
+ This section defines new Result-Code AVP [DIAMBASE] values that must
+ be supported by all Diameter implementations that conform to this
+ specification.
+
+ The Credit-Control-Answer message includes the Result-Code AVP, which
+ may indicate that an error was present in the Credit-Control-Request
+ message. A rejected Credit-Control-Request message SHOULD cause the
+ user's session to be terminated.
+
+9.1. Transient Failures
+
+ Errors that fall within the transient failures category are used to
+ inform a peer that the request could not be satisfied at the time it
+ was received, but that the request MAY be able to be satisfied in the
+ future.
+
+ DIAMETER_END_USER_SERVICE_DENIED 4010
+ The credit-control server denies the service request due to
+ service restrictions. If the CCR contained used-service-units,
+ they are deducted, if possible.
+
+ DIAMETER_CREDIT_CONTROL_NOT_APPLICABLE 4011
+ The credit-control server determines that the service can be
+ granted to the end user but that no further credit-control is
+ needed for the service (e.g., service is free of charge).
+
+ DIAMETER_CREDIT_LIMIT_REACHED 4012
+ The credit-control server denies the service request because the
+ end user's account could not cover the requested service. If the
+ CCR contained used-service-units they are deducted, if possible.
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 79]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+9.2. Permanent Failures
+
+ Errors that fall within the permanent failure category are used to
+ inform the peer that the request failed and should not be attempted
+ again.
+
+ DIAMETER_USER_UNKNOWN 5030
+ The specified end user is unknown in the credit-control server.
+
+ DIAMETER_RATING_FAILED 5031
+ This error code is used to inform the credit-control client that
+ the credit-control server cannot rate the service request due to
+ insufficient rating input, an incorrect AVP combination, or an AVP
+ or an AVP value that is not recognized or supported in the rating.
+ The Failed-AVP AVP MUST be included and contain a copy of the
+ entire AVP(s) that could not be processed successfully or an
+ example of the missing AVP complete with the Vendor-Id if
+ applicable. The value field of the missing AVP should be of
+ correct minimum length and contain zeros.
+
+10. AVP Occurrence Table
+
+ The following table presents the AVPs defined in this document and
+ specifies in which Diameter messages they MAY or MAY NOT be present.
+ Note that AVPs that can only be present within a Grouped AVP are not
+ represented in this table.
+
+ The table uses the following symbols:
+
+ 0 The AVP MUST NOT be present in the message.
+ 0+ Zero or more instances of the AVP MAY be present in the
+ message.
+ 0-1 Zero or one instance of the AVP MAY be present in the
+ message. It is considered an error if there is more
+ than one instance of the AVP.
+ 1 One instance of the AVP MUST be present in the message.
+ 1+ At least one instance of the AVP MUST be present in the
+ message.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 80]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+10.1. Credit-Control AVP Table
+
+ The table in this section is used to represent which credit-control
+ applications specific AVPs defined in this document are to be present
+ in the credit-control messages.
+
+ +-----------+
+ | Command |
+ | Code |
+ |-----+-----+
+ Attribute Name | CCR | CCA |
+ ------------------------------|-----+-----+
+ Acct-Multi-Session-Id | 0-1 | 0-1 |
+ Auth-Application-Id | 1 | 1 |
+ CC-Correlation-Id | 0-1 | 0 |
+ CC-Session-Failover | 0 | 0-1 |
+ CC-Request-Number | 1 | 1 |
+ CC-Request-Type | 1 | 1 |
+ CC-Sub-Session-Id | 0-1 | 0-1 |
+ Check-Balance-Result | 0 | 0-1 |
+ Cost-Information | 0 | 0-1 |
+ Credit-Control-Failure- | 0 | 0-1 |
+ Handling | | |
+ Destination-Host | 0-1 | 0 |
+ Destination-Realm | 1 | 0 |
+ Direct-Debiting-Failure- | 0 | 0-1 |
+ Handling | | |
+ Event-Timestamp | 0-1 | 0-1 |
+ Failed-AVP | 0 | 0+ |
+ Final-Unit-Indication | 0 | 0-1 |
+ Granted-Service-Unit | 0 | 0-1 |
+ Multiple-Services-Credit- | 0+ | 0+ |
+ Control | | |
+ Multiple-Services-Indicator | 0-1 | 0 |
+ Origin-Host | 1 | 1 |
+ Origin-Realm | 1 | 1 |
+ Origin-State-Id | 0-1 | 0-1 |
+ Proxy-Info | 0+ | 0+ |
+ Redirect-Host | 0 | 0+ |
+ Redirect-Host-Usage | 0 | 0-1 |
+ Redirect-Max-Cache-Time | 0 | 0-1 |
+ Requested-Action | 0-1 | 0 |
+ Requested-Service-Unit | 0-1 | 0 |
+ Route-Record | 0+ | 0+ |
+ Result-Code | 0 | 1 |
+ Service-Context-Id | 1 | 0 |
+ Service-Identifier | 0-1 | 0 |
+ Service-Parameter-Info | 0+ | 0 |
+
+
+
+Hakala, et al. Standards Track [Page 81]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ Session-Id | 1 | 1 |
+ Subscription-Id | 0+ | 0 |
+ Termination-Cause | 0-1 | 0 |
+ User-Equipment-Info | 0-1 | 0 |
+ Used-Service-Unit | 0+ | 0 |
+ User-Name | 0-1 | 0-1 |
+ Validity-Time | 0 | 0-1 |
+ ------------------------------|-----+-----+
+
+10.2. Re-Auth-Request/Answer AVP Table
+
+ This section defines AVPs that are specific to the Diameter credit-
+ control application and that MAY be included in the Diameter Re-
+ Auth-Request/Answer (RAR/RAA) message [DIAMBASE].
+
+ Re-Auth-Request/Answer command MAY include the following additional
+ AVPs:
+
+ +---------------+
+ | Command Code |
+ |-------+-------+
+ Attribute Name | RAR | RAA |
+ ------------------------------+-------+-------+
+ CC-Sub-Session-Id | 0-1 | 0-1 |
+ G-S-U-Pool-Identifier | 0-1 | 0-1 |
+ Service-Identifier | 0-1 | 0-1 |
+ Rating-Group | 0-1 | 0-1 |
+ ------------------------------+-------+-------+
+
+11. RADIUS/Diameter Credit-Control Interworking Model
+
+ This section defines the basic principles for the Diameter credit-
+ control/RADIUS prepaid inter-working model; that is, a message
+ translation between a RADIUS based prepaid solution and a Diameter
+ credit-control application. A complete description of the protocol
+ translations between RADIUS and the Diameter credit-control
+ application is beyond the scope of this specification and SHOULD be
+ addressed in another appropriate document, such as the RADIUS prepaid
+ specification.
+
+ The Diameter credit-control architecture may have a Translation Agent
+ capable of translation between RADIUS prepaid and Diameter credit-
+ control protocols. An AAA server (usually the home AAA server) may
+ act as a Translation Agent and as a Diameter credit-control client
+ for service elements that use credit-control mechanisms other than
+ Diameter credit control for instance, RADIUS prepaid. In this case,
+ the home AAA server contacts the Diameter credit-control server as
+ part of the authorization process. The interworking architecture is
+
+
+
+Hakala, et al. Standards Track [Page 82]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ illustrated in Figure 7, and interworking flow in Figure 8. In a
+ roaming situation the service element (e.g., the NAS) may be located
+ in the visited network, and a visited AAA server is usually
+ contacted. The visited AAA server connects then to the home AAA
+ server.
+
+ RADIUS Prepaid
+ +--------+ +---------+ protocol +------------+ +--------+
+ | End |<----->| Service |<---------->| Home AAA | |Business|
+ | User | | Element | | Server | |Support |
+ +--------+ +-->| | |+----------+|->|System |
+ | +---------+ ||CC Client || | |
+ | |+----------+| | |
+ +--------+ | +------^-----+ +----^---+
+ | End |<--+ Credit-Control | |
+ | User | Protocol | |
+ +--------+ +-------V--------+ |
+ |Credit-Control |----+
+ | Server |
+ +----------------+
+
+ Figure 7: Credit-control architecture with service element
+ containing translation agent, translating RADIUS
+ prepaid to Diameter credit-control protocol
+
+ When the AAA server acting as a Translation Agent receives an initial
+ RADIUS Access-Request message from service element (e.g., NAS
+ access), it performs regular authentication and authorization. If
+ the RADIUS Access-Request message indicates that the service element
+ is capable of credit-control, and if the home AAA server finds that
+ the subscriber is a prepaid subscriber, then a Diameter credit-
+ control request SHOULD be sent toward the credit-control server to
+ perform credit authorization and to establish a credit-control
+ session. After the Diameter credit-control server checks the end
+ user's account balance, rates the service, and reserves credit from
+ the end user's account, the reserved quota is returned to the home
+ AAA server in the Diameter Credit-Control-Answer. Then the home AAA
+ server sends the reserved quota to the service element in the RADIUS
+ Access-Accept.
+
+ At the expiry of the allocated quota, the service element sends a new
+ RADIUS Access-Request containing the units used this far to the home
+ AAA server. The home AAA server shall map a RADIUS Access-Request
+ containing the reported units to the Diameter credit-control server
+ in a Diameter Credit-Control-Request (UPDATE_REQUEST). The Diameter
+ credit-control server debits the used units from the end user's
+ account and allocates a new quota that is returned to the home AAA
+ server in the Diameter Credit-Control-Answer. The quota is
+
+
+
+Hakala, et al. Standards Track [Page 83]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ transferred to the service element in the RADIUS Access-Accept. When
+ the end user terminates the service, or when the entire quota has
+ been used, the service element sends a RADIUS Access-Request. To
+ debit the used units from the end user's account and to stop the
+ credit-control session, the home AAA server sends a Diameter Credit-
+ Control-Request (TERMINATION_REQUEST) to the credit-control server.
+ The Diameter credit-control server acknowledges the session
+ termination by sending a Diameter Credit-Control-Answer to the home
+ AAA server. The RADIUS Access-Accept is sent to the NAS.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 84]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ A following diagram illustrates a RADIUS prepaid - Diameter credit-
+ control interworking sequence.
+
+ Service Element Translation Agent
+ (e.g., NAS) (CC Client) CC Server
+ | Access-Request | |
+ |----------------------->| |
+ | | CCR (initial) |
+ | |----------------------->|
+ | | CCA (Granted-Units) |
+ | |<-----------------------|
+ | Access-Accept | |
+ | (Granted-Units) | |
+ |<-----------------------| |
+ : : :
+ | Access-Request | |
+ | (Used-Units) | |
+ |----------------------->| |
+ | | CCR (update, |
+ | | Used-Units) |
+ | |----------------------->|
+ | | CCA (Granted-Units) |
+ | |<-----------------------|
+ | Access-Accept | |
+ | (Granted-Units) | |
+ |<-----------------------| |
+ : : :
+ | Access-Request | |
+ |----------------------->| |
+ | | CCR (terminate, |
+ | | Used-Units) |
+ | |----------------------->|
+ | | CCA |
+ | |<-----------------------|
+ | Access-Accept | |
+ |<-----------------------| |
+ | | |
+
+ Figure 8: Message flow example with RADIUS prepaid -
+ Diameter credit-control interworking
+
+12. IANA Considerations
+
+ This section contains the namespaces that have either been created in
+ this specification, or the values assigned to existing namespaces
+ managed by IANA.
+
+
+
+
+
+Hakala, et al. Standards Track [Page 85]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ In the subsections below, when we speak about review by a Designated
+ Expert, please note that the designated expert will be assigned by
+ the IESG. Initially, such Expert discussions take place on the AAA
+ WG mailing list.
+
+12.1. Application Identifier
+
+ This specification assigns the value 4, 'Diameter Credit Control', to
+ the Application Identifier namespace defined in [DIAMBASE]. See
+ section 1.3 for more information.
+
+12.2. Command Codes
+
+ This specification uses the value 272 from the Command code namespace
+ defined in [DIAMBASE] for the Credit-Control-Request (CCR) and
+ Credit-Control-Answer (CCA) commands.
+
+12.3. AVP Codes
+
+ This specification assigns the values 411 - 461 from the AVP code
+ namespace defined in [DIAMBASE]. See section 8 for the assignment of
+ the namespace in this specification.
+
+12.4. Result-Code AVP Values
+
+ This specification assigns the values 4010, 4011, 4012, 5030, 5031
+ from the Result-Code AVP value namespace defined in [DIAMBASE]. See
+ section 9 for the assignment of the namespace in this specification.
+
+12.5. CC-Request-Type AVP
+
+ As defined in section 8.3, the CC-Request-Type AVP includes
+ Enumerated type values 1 - 4. IANA has created and is maintaining a
+ namespace for this AVP. All remaining values are available for
+ assignment by a Designated Expert [IANA].
+
+12.6. CC-Session-Failover AVP
+
+ As defined in section 8.4, the CC-Failover-Supported AVP includes
+ Enumerated type values 0 - 1. IANA has created and is maintaining a
+ namespace for this AVP. All remaining values are available for
+ assignment by a Designated Expert [IANA].
+
+
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 86]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+12.7. CC-Unit-Type AVP
+
+ As defined in section 8.32, the CC-Unit-Type AVP includes Enumerated
+ type values 0 - 5. IANA has created and is maintaining a namespace
+ for this AVP. All remaining values are available for assignment by a
+ Designated Expert [IANA].
+
+12.8. Check-Balance-Result AVP
+
+ As defined in section 8.6, the Check-Balance-Result AVP includes
+ Enumerated type values 0 - 1. IANA has created and is maintaining a
+ namespace for this AVP. All remaining values are available for
+ assignment by a Designated Expert [IANA].
+
+12.9. Credit-Control AVP
+
+ As defined in section 8.13, the Credit-Control AVP includes
+ Enumerated type values 0 - 1. IANA has created and is maintaining a
+ namespace for this AVP. All remaining values are available for
+ assignment by a Designated Expert [IANA].
+
+12.10. Credit-Control-Failure-Handling AVP
+
+ As defined in section 8.14, the Credit-Control-Failure-Handling AVP
+ includes Enumerated type values 0 - 2. IANA has created and is
+ maintaining a namespace for this AVP. All remaining values are
+ available for assignment by a Designated Expert [IANA].
+
+12.11. Direct-Debiting-Failure-Handling AVP
+
+ As defined in section 8.15, the Direct-Debiting-Failure-Handling AVP
+ includes Enumerated type values 0 - 1. IANA has created and is
+ maintaining a namespace for this AVP. All remaining values are
+ available for assignment by a Designated Expert [IANA].
+
+12.12. Final-Unit-Action AVP
+
+ As defined in section 8.35, the Final-Unit-Action AVP includes
+ Enumerated type values 0 - 2. IANA has created and is maintaining a
+ namespace for this AVP. All remaining values are available for
+ assignment by a Designated Expert [IANA].
+
+12.13. Multiple-Services-Indicator AVP
+
+ As defined in section 8.40, the Multiple-Services-Indicator AVP
+ includes Enumerated type values 0 - 1. IANA has created and is
+ maintaining a namespace for this AVP. All remaining values are
+ available for assignment by a Designated Expert [IANA].
+
+
+
+Hakala, et al. Standards Track [Page 87]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+12.14. Redirect-Address-Type AVP
+
+ As defined in section 8.38, the Redirect-Address-Type AVP includes
+ Enumerated type values 0 - 3. IANA has created and is maintaining a
+ namespace for this AVP. All remaining values are available for
+ assignment by a Designated Expert [IANA].
+
+12.15. Requested-Action AVP
+
+ As defined in section 8.41, the Requested-Action AVP includes
+ Enumerated type values 0 - 3. IANA has created and is maintaining a
+ namespace for this AVP. All remaining values are available for
+ assignment by a Designated Expert [IANA].
+
+12.16. Subscription-Id-Type AVP
+
+ As defined in section 8.47, the Subscription-Id-Type AVP includes
+ Enumerated type values 0 - 4. IANA has created and is maintaining a
+ namespace for this AVP. All remaining values are available for
+ assignment by a Designated Expert [IANA].
+
+12.17. Tariff-Change-Usage AVP
+
+ As defined in section 8.27, the Tariff-Change-Usage AVP includes
+ Enumerated type values 0 - 2. IANA has created and is maintaining a
+ namespace for this AVP. All remaining values are available for
+ assignment by a Designated Expert [IANA].
+
+12.18. User-Equipment-Info-Type AVP
+
+ As defined in section 8.50, the User-Equipment-Info-Type AVP includes
+ Enumerated type values 0 - 3. IANA has created and is maintaining a
+ namespace for this AVP. All remaining values are available for
+ assignment by a Designated Expert [IANA].
+
+13. Credit-Control Application Related Parameters
+
+ Tx timer
+
+ When real-time credit-control is required, the credit-control
+ client contacts the credit-control server before and while the
+ service is provided to an end user. Due to the real-time nature
+ of the application, the communication delays SHOULD be minimized;
+ e.g., to avoid an overly long service setup time experienced by
+ the end user. The Tx timer is introduced to control the waiting
+ time in the client in the Pending state. When the Tx timer
+ elapses, the credit-control client takes an action to the end user
+ according to the value of the Credit-Control-Failure-Handling AVP
+
+
+
+Hakala, et al. Standards Track [Page 88]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ or Direct-Debiting-Failure-Handling AVP. The recommended value is
+ 10 seconds.
+
+ Tcc timer
+
+ The Tcc timer supervises an ongoing credit-control session in the
+ credit-control server. It is RECOMMENDED to use the Validity-Time
+ as input to set the Tcc timer value. In case of transient
+ failures in the network, the Diameter credit-control server might
+ change to Idle state. To avoid this, the Tcc timer MAY be set so
+ that Tcc equals to 2 x Validity-Time.
+
+ Credit-Control-Failure-Handling and Direct-Debiting-Failure-Handling
+
+ Client implementations may offer the possibility of locally
+ configuring these AVPs. In such a case their value and behavior
+ is defined in section 5.7 for the Credit-Control-Failure-Handling
+ and in section 6.5 for the Direct-Debiting-Failure-Handling.
+
+14. Security Considerations
+
+ The Diameter base protocol [DIAMBASE] requires that each Diameter
+ implementation use underlying security; i.e., IPsec or TLS. These
+ mechanisms are believed to provide sufficient protection under the
+ normal Internet threat model; that is, assuming that the authorized
+ nodes engaging in the protocol have not been compromised, but that
+ the attacker has complete control over the communication channels
+ between them. This includes eavesdropping, message modification,
+ insertion, and man-in-the-middle and replay attacks. Note also that
+ this application includes a mechanism for application layer replay
+ protection by means of the Session-Id from [DIAMBASE] and CC-
+ Request-Number, which is specified in this document. The Diameter
+ credit-control application is often used within one domain, and there
+ may be a single hop between the peers. In these environments, the
+ use of TLS or IPsec is sufficient. The details of TLS and IPsec
+ related security considerations are discussed in the [DIAMBASE].
+
+ Because this application handles monetary transactions (directly or
+ indirectly), it increases the interest for various security attacks.
+ Therefore, all parties communicating with each other MUST be
+ authenticated, including, for instance, TLS client-side
+ authentication. In addition, authorization of the client SHOULD be
+ emphasized; i.e., that the client is allowed to perform credit-
+ control for a certain user. The specific means of authorization are
+ outside of the scope of this specification but can be, for instance,
+ manual configuration.
+
+
+
+
+
+Hakala, et al. Standards Track [Page 89]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ Another kind of threat is malicious modification, injection, or
+ deletion of AVPs or complete credit-control messages. The credit-
+ control messages contain sensitive billing related information (such
+ as subscription Id, granted units, used units, cost information)
+ whose malicious modification can have financial consequences.
+ Sometimes simply delaying the credit-control messages can cause
+ disturbances in the credit-control client or server.
+
+ Even without any modification to the messages, an adversary can
+ invite a security threat by eavesdropping, as the transactions
+ contain private information about the user. Also, by monitoring the
+ credit-control messages one can collect information about the
+ credit-control server's billing models and business relationships.
+
+ When third-party relays or proxy are involved, the hop-by-hop
+ security does not necessarily provide sufficient protection for
+ Diameter user session. In some cases, it may be inappropriate to
+ send Diameter messages, such as CCR and CCA, containing sensitive
+ AVPs via untrusted Diameter proxy agents, as there are no assurances
+ that third-party proxies will not modify the credit-control commands
+ or AVP values.
+
+14.1. Direct Connection with Redirects
+
+ A Diameter credit-control agent cannot always know whether agents
+ between it and the end user's Diameter credit-control server are
+ reliable. In this case, the Diameter credit-control agent doesn't
+ have a routing entry in its Diameter Routing Table (defined in
+ [DIAMBASE], section 2.7) for the realm of the credit-control server
+ in the end user's home domain. The Diameter credit-control agent can
+ have a default route configured to a local Redirect agent, and it
+ redirects the CCR message to the redirect agent. The local Redirect
+ agent then returns a redirect notification (Result-code 3006,
+ DIAMETER_REDIRECT_INDICATION) to the credit-control agent, as well as
+ Diameter credit-control server(s) information (Redirect-Host AVP) and
+ information (Redirect-Host-Usage AVP) about how the routing entry
+ resulting from the Redirect-Host is to be used. The Diameter
+ credit-control agent then forwards the CCR message directly to one of
+ the hosts identified by the CCA message from the redirect agent. If
+ the value of the Redirect-Host-Usage AVP is unequal to zero, all
+ following messages are sent to the host specified in the Redirect-
+ Host AVP until the time specified by the Redirect-Max-Cache-Time AVP
+ is expired.
+
+ There are some authorization issues even with redirects. There may
+ be attacks toward nodes that have been properly authorized, but that
+ abuse their authorization or have been compromised. These issues are
+ discussed more widely in [DIAMEAP], section 8.
+
+
+
+Hakala, et al. Standards Track [Page 90]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+15. References
+
+15.1. Normative References
+
+ [DIAMBASE] Calhoun, P., Loughney, J., Guttman, E., Zorn, G., and J.
+ Arkko, "Diameter Base Protocol", RFC 3588, September
+ 2003.
+
+ [3GPPCHARG] 3rd Generation Partnership Project; Technical
+ Specification Group Services and System Aspects, Service
+ aspects; Charging and Billing, (release 5), 3GPP TS
+ 22.115 v. 5.2.1, 2002-03.
+
+ [SIP] Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston,
+ A., Peterson, J., Sparks, R., Handley, M., and E.
+ Schooler, "SIP: Session Initiation Protocol", RFC 3261,
+ June 2002.
+
+ [NAI] Aboba, B. and M. Beadles, "The Network Access
+ Identifier", RFC 2486, January 1999.
+
+ [E164] Recommendation E.164/I.331 (05/97): The International
+ Public Telecommunication Numbering Plan. 1997.
+
+ [CE164] Complement to ITU-T Recommendation E.164 (05/1997):"List
+ of ITU-T Recommendation E.164 assigned country codes",
+ June 2000.
+
+ [E212] Recommendation E.212 (11/98): The international
+ identification plan for mobile terminals and mobile
+ users. 1998.
+
+ [CE212] Complement to ITU-T Recommendation E.212 (11/1997):" List
+ of mobile country or geographical area codes", February
+ 1999.
+
+ [IANA] Narten, T. and H. Alvestrand, "Guidelines for Writing an
+ IANA Considerations Section in RFCs", BCP 26, RFC 2434,
+ October 1998.
+
+ [IPv4] Postel, J., "Internet Protocol", STD 5, RFC 791,
+ September 1981.
+
+ [IPv6Addr] Hinden, R. and S. Deering, "Internet Protocol Version 6
+ (IPv6) Addressing Architecture", RFC 3513, April 2003.
+
+ [KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+
+
+Hakala, et al. Standards Track [Page 91]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ [ISO4217] Codes for the representation of currencies and funds,
+ International Standard ISO 4217,2001
+
+ [NASREQ] Calhoun, P., Zorn, G., Spence, D., and D. Mitton,
+ "Diameter Network Access Server Application", RFC 4005,
+ August 2005.
+
+ [AAATRANS] Aboba, B. and J. Wood, "Authentication, Authorization and
+ Accounting (AAA) Transport Profile", RFC 3539, June 2003.
+
+ [URL] Berners-Lee, T., Masinter, L., and M. McCahill, "Uniform
+ Resource Locators (URL)", RFC 1738, December 1994.
+
+ [RAD802.1X] Congdon, P., Aboba, B., Smith, A., Zorn, G., and J.
+ Roese, "IEEE 802.1X Remote Authentication Dial In User
+ Service (RADIUS) Usage Guidelines", RFC 3580, September
+ 2003.
+
+ [EUI64] IEEE, "Guidelines for 64-bit Global Identifier (EUI-64)
+ Registration Authority",
+ http://standards.ieee.org/regauth/oui/tutorials/
+ EUI64.html March 1997.
+
+ [3GPPIMEI] 3rd Generation Partnership Project; Technical
+ Specification Group Core Network, Numbering, addressing
+ and identification, (release 5), 3GPP TS 23.003 v. 5.8.0,
+ 2003-12
+
+15.2. Informative References
+
+ [RFC2866] Rigney, C., "RADIUS Accounting", RFC 2866, June 2000.
+
+ [DIAMMIP] Calhoun, P., Johansson, T., Perkins, C., Hiller, T., and
+ P. McCann, "Diameter Mobile IPv4 Application", RFC 4004,
+ August 2005.
+
+ [DIAMEAP] Eronen, P., Hiller, T., and G. Zorn, "Diameter Extensible
+ Authentication Protocol (EAP) Application", Work in
+ Progress.
+
+ [RFC3725] Rosenberg, J., Peterson, J., Schulzrinne, H., and G.
+ Camarillo, "Best Current Practices for Third Party Call
+ Control (3pcc) in the Session Initiation Protocol (SIP)",
+ BCP 85, RFC 3725, April 2004.
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 92]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+16. Acknowledgements
+
+ The authors would like to thank Bernard Aboba, Jari Arkko, Robert
+ Ekblad, Pasi Eronen, Benny Gustafsson, Robert Karlsson, Avi Lior,
+ Paco Marin, Jussi Maki, Jeff Meyer, Anne Narhi, John Prudhoe,
+ Christopher Richards, Juha Vallinen, and Mark Watson for their
+ comments and suggestions.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 93]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+Appendix A. Credit-Control Sequences
+
+A.1. Flow I
+
+ NAS
+ End User (CC Client) AAA Server CC Server
+ |(1)User Logon |(2)AA Request (CC AVPs) |
+ |------------------>|------------------->| |
+ | | |(3)CCR(initial, CC AVPs)
+ | | |------------------->|
+ | | | (4)CCA(Granted-Units)
+ | | |<-------------------|
+ | |(5)AA Answer(Granted-Units) |
+ |(6)Access granted |<-------------------| |
+ |<----------------->| | |
+ | | | |
+ : : : :
+ | |(7)CCR(update,Used-Units) |
+ | |------------------->|(8)CCR |
+ | | | (update,Used-Units)
+ | | |------------------->|
+ | | |(9)CCA(Granted-Units)
+ | |(10)CCA(Granted-Units)<------------------|
+ | |<-------------------| |
+ : : : :
+ | (Auth. lifetime expires) | |
+ | |(11) AAR (CC AVP) | |
+ | |------------------->| |
+ | | (12) AAA | |
+ | |<-------------------| |
+ : : : :
+ : : : :
+ |(13) User logoff | | |
+ |------------------>|(14)CCR(term.,Used-Units) |
+ | |------------------->|(15)CCR |
+ | | | (term.,Used-Units)
+ | | |------------------->|
+ | | | (16)CCA |
+ | | (17)CCA |<-------------------|
+ | |<-------------------| |
+ | |(18)STR | |
+ | |------------------->| |
+ | | (19)STA | |
+ | |<-------------------| |
+
+ Figure A.1: Flow I
+
+
+
+
+
+Hakala, et al. Standards Track [Page 94]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ A credit-control flow for Network Access Services prepaid is shown in
+ Figure A.1. The Diameter [NASREQ] is implemented in the Network
+ Access Server (NAS). The focus of this flow is in the credit
+ authorization.
+
+ The user logs on to the network (1). The Diameter NAS sends a
+ Diameter AA-Request (AAR) to the home Diameter AAA server. The
+ credit-control client populates the AAR with the Credit-Control AVP
+ set to CREDIT_AUTHORIZATION, and service-specific AVPs are included,
+ as usual [NASREQ]. The home Diameter AAA server performs service-
+ specific Authentication and Authorization, as usual. The home
+ Diameter AAA server determines that the user is a prepaid user and
+ notices from the Credit-Control AVP that the NAS has credit-control
+ capabilities. It sends a Diameter Credit-Control-Request with CC-
+ Request-Type set to INITIAL_REQUEST to the Diameter credit-control
+ server to perform credit authorization (3) and to establish a
+ credit-control session. (The home Diameter AAA server may forward
+ service-specific AVPs received from the NAS as input for the rating
+ process.) The Diameter credit-control server checks the end user's
+ account balance, rates the service, and reserves credit from the end
+ user's account. The reserved quota is returned to the home Diameter
+ AAA server in the Diameter Credit-Control-Answer (4). The home
+ Diameter AAA server sends the reserved quota to the NAS in the
+ Diameter AA-Answer (AAA). Upon successful AAA, the NAS starts the
+ credit-control session and starts monitoring the granted units (5).
+ The NAS grants access to the end user (6). At the expiry of the
+ allocated quota, the NAS sends a Diameter Credit-Control-Request with
+ CC-Request-Type set to UPDATE_REQUEST to the Home Diameter AAA server
+ (7). This message contains the units used thus far. The home
+ Diameter AAA server forwards the CCR to the Diameter credit-control
+ server (8). The Diameter credit-control server debits the used units
+ from the end user's account and allocates a new quota that is
+ returned to the home Diameter AAA server in the Diameter Credit-
+ Control-Answer (9). The message is forwarded to the NAS (10).
+ During the ongoing credit-control session, the authorization lifetime
+ expires, and the authorization/authentication client in the NAS
+ performs service specific re-authorization to the home Diameter AAA
+ server, as usual. The credit-control client populates the AAR with
+ the Credit-Control AVP set to RE_AUTHORIZATION, indicating that the
+ credit-control server shall not be contacted, as the credit
+ authorization is controlled by the burning rate of the granted units
+ (11). The home Diameter AAA server performs service-specific re-
+ authorization as usual and returns the AA-Answer to the NAS (12).
+ The end user logs off from the network (13). To debit the used units
+ from the end user's account and to stop the credit-control session,
+ the NAS sends a Diameter Credit-Control-Request with CC-Request-Type
+ set to TERMINATION_REQUEST to the home Diameter AAA server (14). The
+ home Diameter AAA server forwards the CCR to the credit-control
+
+
+
+Hakala, et al. Standards Track [Page 95]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ server (15). The Diameter credit-control server acknowledges the
+ session termination by sending a Diameter Credit-Control-Answer to
+ the home Diameter AAA server (16). The home Diameter AAA server
+ forwards the answer to the NAS (17). STR/STA takes place between the
+ NAS and home Diameter AAA server, as usual (18-19).
+
+A.2. Flow II
+
+ SIP Proxy/Registrar AAA
+ A (CC Client) Server B CC Server
+ |(i) REGISTER | | | |
+ |------------->|(ii) | | |
+ | |------------->| | |
+ | |authentication & | |
+ | |authorization | | |
+ | |<-------------| | |
+ |(iii)200 OK | | |
+ |<-------------| | |
+ : : : :
+ |(1) INVITE | :
+ |------------->|
+ | |(2) CCR (Initial, SIP specific AVP) |
+ | |------------------------------------------->|
+ | |(3) CCA (Granted-Units) |
+ | |<-------------------------------------------|
+ | |(4) INVITE | |
+ | |---------------------------->| |
+ : : : :
+ | |(5) CCR (update, Used-Units) |
+ | |------------------------------------------->|
+ | |(6) CCA (Granted-Units) |
+ | |<-------------------------------------------|
+ : : : :
+ |(7) BYE | | |
+ |------------->| | |
+ | |(8) BYE | |
+ | |---------------------------->| |
+ | |(9) CCR (termination, Used-Units) |
+ | |------------------------------------------->|
+ | |(10) CCA () |
+ | |<-------------------------------------------|
+ | | | |
+
+ Figure A.2: Flow II
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 96]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ This is an example of Diameter credit-control for SIP sessions.
+ Although the flow focuses on illustrating the usage of credit-control
+ messages, the SIP signaling is inaccurate, and the diagram is not by
+ any means an attempt to define a service provider's SIP network.
+ However, for the sake of this example, some assumptions are made
+ below.
+
+ Typically, prepaid services based, for example, on time usage for SIP
+ session require an entity in the service provider network to
+ intercept all the requests within the SIP dialog in order to detect
+ events, such as session establishment and session release, that are
+ essential to perform credit-control operations with the credit-
+ control server. Therefore, in this example, it is assumed that the
+ SIP Proxy adds a Record-Route header in the initial SIP INVITE to
+ make sure that all the future requests in the created dialog traverse
+ through it (for the definitions of 'Record-Route' and 'dialog' please
+ refer to [SIP]). Finally, the degree of credit-control measuring of
+ the media by the proxy depends on the business model design used in
+ setting up the end system and proxies in the SIP network.
+
+ The end user (SIP User Agent A) sends REGISTER with credentials (i).
+ The SIP Proxy sends a request to the home AAA server to perform
+ Multimedia authentication and authorization by using, for instance,
+ Diameter Multimedia application (ii). The home AAA server checks
+ that the credentials are correct and checks the user profile.
+ Eventually, 200 OK response (iii) is sent to the UA. Note that the
+ Authentication and Authorization is valid for the registration
+ validity period duration (i.e., until re-registration is performed).
+ Several SIP sessions may be established without re-authorization.
+
+ UA A sends an INVITE (1). The SIP Proxy sends a Diameter Credit-
+ Control-Request (INITIAL_REQUEST) to the Diameter credit-control
+ server (2). The Credit-Control-Request contains information obtained
+ from the SIP signaling describing the requested service (e.g.,
+ calling party, called party, Session Description Protocol
+ attributes). The Diameter credit-control server checks the end
+ user's account balance, rates the service, and reserves credit from
+ the end user's account. The reserved quota is returned to the SIP
+ Proxy in the Diameter Credit-Control-Answer (3). The SIP Proxy
+ forwards the SIP INVITE to UA B (4). B's phone rings, and B answers.
+ The media flows between them, and the SIP Proxy starts measuring the
+ quota. At the expiry of the allocated quota, the SIP Proxy sends a
+ Diameter Credit-Control-Request (UPDATE_REQUEST) to the Diameter
+ credit-control server (5). This message contains the units used thus
+ far. The Diameter credit-control server debits the used units from
+ the end user's account and allocates new credit that is returned to
+ the SIP Proxy in the Diameter Credit-Control-Answer (6). The end
+ user terminates the service by sending a BYE (7). The SIP Proxy
+
+
+
+Hakala, et al. Standards Track [Page 97]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ forwards the BYE message to UA B (8) and sends a Diameter Credit-
+ Control-Request (TERMINATION_REQUEST) to the credit-control server
+ (9). The Diameter credit-control server acknowledges the session
+ termination by sending a Diameter Credit-Control-Answer to the SIP
+ Proxy (10).
+
+A.3. Flow III
+
+ MMS Server
+ A (CC Client) B CC Server
+ |(1) Send MMS | | |
+ |--------------->| | |
+ | |(2) CCR (event, DIRECT_DEBITING,|
+ | | MMS specific AVP) |
+ | |-------------------------------->|
+ | |(3) CCA (Granted-Units) |
+ | |<--------------------------------|
+ |(4) Send MMS Ack| | |
+ |<---------------| | |
+ | |(5) Notify MMS | |
+ | |--------------->| |
+ : : : :
+ | |(6) Retrieve MMS| |
+ | |<---------------| |
+ | |(7) Retrieve MMS| |
+ | | Ack | |
+ | |--------------->| |
+ | | | |
+
+ Figure A.3: Flow III
+
+ A credit-control flow for Multimedia Messaging Services is shown in
+ Figure A.3. The sender is charged as soon as the messaging server
+ successfully stores the message.
+
+ The end user A sends a Multimedia Message (MMS) to the MMS server
+ (1). The MMS server stores the message and sends a Diameter Credit-
+ Control-Request (EVENT_REQUEST with Requested-Action DIRECT_DEBITING)
+ to the Diameter credit-control server (2). The Credit-Control-
+ Request contains information about the MMS message (e.g., size,
+ recipient address, image coding type). The Diameter credit-control
+ server checks the end user's account balance, rates the service, and
+ debits the service from the end user's account. The granted quota is
+ returned to the MMS server in the Diameter Credit-Control-Answer (3).
+ The MMS server acknowledges the successful reception of the MMS
+ message (4). The MMS Server notifies the recipient about the new MMS
+ (5), and end user B retrieves the message from the MMS message store
+ (6),(7).
+
+
+
+Hakala, et al. Standards Track [Page 98]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+A.4. Flow IV
+
+ MMS Server
+ Content Server (CC Client) B CC Server
+ |(1) Send MMS | | |
+ |--------------->| | |
+ | |(2) CCR (event, CHECK_BALANCE, |
+ | | MMS specific AVP) |
+ | |-------------------------------->|
+ | |(3) CCA (ENOUGH_CREDIT) |
+ | |<--------------------------------|
+ |(4) Send MMS Ack| | |
+ |<---------------| | |
+ | |(5) Notify MMS | |
+ | |--------------->| |
+ : : : :
+ | |(6) Retrieve MMS| |
+ | |<---------------| |
+ | |(7) CCR (event, DIRECT_DEBITING,|
+ | | MMS specific AVP) |
+ | |-------------------------------->|
+ | |(8) CCA (Granted-Units) |
+ | |<--------------------------------|
+ | |(9) Retrieve MMS| |
+ | | Ack | |
+ | |--------------->| |
+ | | | |
+
+ Figure A.4: Flow IV
+
+ This is an example of Diameter credit-control for direct debiting
+ using the Multimedia Messaging Service environment. Although the
+ flow focuses on illustrating the usage of credit-control messages,
+ the MMS signaling is inaccurate, and the diagram is not by any means
+ an attempt to define any service provider's MMS configuration or
+ billing model.
+
+ A credit-control flow for Multimedia Messaging Service is shown in
+ Figure A.4. The recipient is charged at the message delivery.
+
+ A content server sends a Multimedia Message (MMS) to the MMS server
+ (1) that stores the message. The message recipient will be charged
+ for the MMS message in this case. As there can be a substantially
+ long time between the receipt of the message at the MMS server and
+ the actual retrieval of the message, the MMS server does not
+ establish any credit-control session to the Diameter credit-control
+ server but performs first only a balance check (without any credit
+ reservation) by sending a Diameter Credit-Control-Request
+
+
+
+Hakala, et al. Standards Track [Page 99]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ (EVENT_REQUEST with Requested-Action CHECK_BALANCE) to verify that
+ end user B can cover the cost for the MMS (2). The Diameter credit-
+ control server checks the end user's account balance and returns the
+ answer to the MMS server in the Diameter Credit-Control-Answer (3).
+ The MMS server acknowledges the successful reception of the MMS
+ message (4). The MMS server notifies the recipient of the new MMS
+ (5), and after some time end user B retrieves the message from the
+ MMS message store (6). The MMS server sends a Diameter Credit-
+ Control-Request (EVENT_REQUEST with Requested-Action:
+ DIRECT_DEBITING) to the Diameter credit-control server (7). The
+ Credit-Control-Request contains information about the MMS message
+ (e.g., size, recipient address, coding type). The Diameter credit-
+ control server checks the end user's account balance, rates the
+ service, and debits the service from the end user's account. The
+ granted quota is returned to the MMS server in the Diameter Credit-
+ Control-Request (8). The MMS is transferred to end user B (9).
+
+ Note that the transfer of the MMS message can take an extended time
+ and can fail, in which case a recovery action is needed. The MMS
+ server should return the already debited units to the user's account
+ by using the REFUND action described in section 6.4.
+
+A.5. Flow V
+
+ SIP Controller
+ A (CC Client) B CC Server
+ |(1)INVITE B(SDP)| | |
+ |--------------->| | |
+ | |(2) CCR (event, PRICE_ENQUIRY, |
+ | | SIP specific AVPs) |
+ | |-------------------------------->|
+ | |(3) CCA (Cost-Information) |
+ | |<--------------------------------|
+ | (4)MESSAGE(URL)| | |
+ |<---------------| | |
+ |(5)HTTP GET | | |
+ |--------------->| | |
+ |(6)HTTP POST | | |
+ |--------------->|(7)INVITE(SDP) | |
+ | |--------------->| |
+ | | (8)200 OK | |
+ | (9)200 OK |<---------------| |
+ |<---------------| | |
+
+ Figure A.5: Flow V
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 100]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ This is an example of Diameter credit-control for SIP sessions.
+ Although the flow focuses on illustrating the usage of credit-control
+ messages, the SIP signaling is inaccurate, and the diagram is not by
+ any means an attempt to define a service provider's SIP network.
+
+ Figure A.5 is an example of Advice of Charge (AoC) service for SIP
+ call. User A can be either a postpaid or prepaid subscriber using
+ the AoC service. It is assumed that the SIP controller also has HTTP
+ capabilities and delivers an interactive AoC web page with, for
+ instance, the cost information, the details of the call derived from
+ the SDP, and a button to accept/not accept the charges. (There may
+ be many other ways to deliver AoC information; however, this flow
+ focuses on the use of the credit-control messages.) The user has
+ been authenticated and authorized prior to initiating the call and
+ subscribed to AoC service.
+
+ UA A sends an INVITE with SDP to B (1). The SIP controller
+ determines that the user is subscribed to AoC service and sends a
+ Diameter Credit-Control-Request (EVENT_REQUEST with Requested-Action:
+ PRICE_ENQUIRY) to the Diameter credit-control server (2). The
+ Credit-Control-Request contains SIP specific AVPs derived from the
+ SIP signaling, describing the requested service (e.g., calling party,
+ called party, Session Description Protocol attributes). The Diameter
+ credit-control server determines the cost of the service and returns
+ the Credit-Control-Answer including the Cost-Information AVP (3).
+ The SIP controller manufactures the AoC web page with information
+ received in SIP signaling and with the cost information received from
+ the credit-control server. Then it sends a SIP MESSAGE that contains
+ a URL pointing to the AoC information web page (4). At the receipt
+ of the SIP MESSAGE, A's UA automatically invokes the web browser that
+ retrieves the AoC information (5). The user clicks on a proper
+ button and accepts the charges (6). The SIP controller continues the
+ session and sends the INVITE to the B party, which accepts the call
+ (7,8,9).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 101]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+A.6. Flow VI
+
+ Gaming Server
+ End User (CC Client) CC Server
+ | (1)Service Delivery | |
+ |<---------------------->| |
+ : : :
+ : : :
+ | |(2)CCR(event,REFUND,Requested-
+ | |Service-Unit,Service-Parameter-Info)
+ | |----------------------->|
+ | | (3)CCA(Cost-Information)
+ | |<-----------------------|
+ | (4)Notification | |
+ |<-----------------------| |
+
+ Figure A.6: Flow VI
+
+ Figure A.6 illustrates a credit-control flow for the REFUND case. It
+ is assumed that there is a trusted relationship and secure connection
+ between the Gaming server and the Diameter credit-control server.
+ The end user may be a prepaid subscriber or a postpaid subscriber.
+
+ While the end user is playing the game (1), she enters a new level
+ that entitles her to a bonus. The Gaming server sends a Diameter
+ Credit-Control-Request (EVENT_REQUEST with Requested-Action:
+ REFUND_ACCOUNT) to the Diameter credit-control server (2). The
+ Credit-Control-Request Request contains the Requested-Service-Unit
+ AVP with the CC-Service-Specific-Units containing the number of
+ points the user just won. The Service-Parameter-Info AVP is also
+ included in the request and specifies the service event to be rated
+ (e.g., Tetris Bonus). From information received, the Diameter
+ credit-control server determines the amount to be credited, refunds
+ the user's account, and returns the Credit-Control-Answer, including
+ the Cost-Information AVP (3). The Cost-Information indicates the
+ credited amount. At the first opportunity, the Gaming server
+ notifies the end user of the credited amount (4).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 102]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+A.7. Flow VII
+
+ SIP Controller Top-Up
+ A (CC Client) Server B CC Server
+ | | | | |
+ | | (1) CCR(Update,Used-Unit) | |
+ | |------------------------------------------>|
+ | | (2) CCA(Final-Unit, Redirect)|
+ | |<------------------------------------------|
+ : : : : :
+ : : : : :
+ | | (3) CCR(Update, Used-Units)| |
+ | |------------------------------------------>|
+ | | (3a)INVITE("hold") | |
+ | |--------------------------->| |
+ | | | (4) CCA(Validity-Time)|
+ | |<------------------------------------------|
+ | (5)INVITE | (6)INVITE | | |
+ |<--------------|------------->| | |
+ | (7)RTP | | |
+ |..............................| | |
+ | | (8)BYE | | |
+ | |<-------------| | |
+ | | (9)CCR(Update) | |
+ | |------------------------------------------>|
+ | | (10)CCA(Granted-Unit) |
+ | |<------------------------------------------|
+ | (12)INVITE | (11)INVITE | |
+ |<--------------|--------------------------->| |
+
+ Figure A.7: Flow VII
+
+ Figure A.7 is an example of the graceful service termination for a
+ SIP call. It is assumed that the call is set up so that the
+ controller is in the call as a B2BUA (Back to Back User Agent)
+ performing third-party call control (3PCC). Note that the SIP
+ signaling is inaccurate, as the focus of this flow is in the graceful
+ service termination and credit-control authorization. The best
+ practice for 3PCC is defined in [RFC3725].
+
+ The call is ongoing between users A and B; user A has a prepaid
+ subscription. At the expiry of the allocated quota, the SIP
+ controller sends a Diameter Credit-Control-Request (UPDATE_REQUEST)
+ to the Diameter credit-control server (1). This message contains the
+ units used thus far. The Diameter credit-control server debits the
+ used units from the end user's account and allocates the final quota
+ returned to the SIP controller in the Diameter Credit-Control-Answer
+ (2). This message contains the Final-Unit-Indication AVP with the
+
+
+
+Hakala, et al. Standards Track [Page 103]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ Final-Unit-Action set to REDIRECT, the Redirect-Address-Type set to
+ SIP URI, and the Redirect-Server-Address set to the Top-up server
+ name (e.g., sip:[email protected]). At the expiry of the
+ final allocated quota, the SIP controller sends a Diameter Credit-
+ Control-Request (UPDATE_REQUEST) to the Diameter credit-control
+ server (3) and places the called party on "hold" by sending an INVITE
+ with the appropriate connection address in the SDP (3a). The
+ Credit-Control-Request message contains the units used thus far. The
+ Diameter credit-control server debits the used units from the end
+ user's account but does not make any credit reservation. The
+ Credit-Control-Answer message, which contains the Validity-Time to
+ supervise the graceful service termination, is returned to the SIP
+ controller (4). The SIP controller establishes a SIP session between
+ the prepaid user and the Top-up server (5, 6). The Top-up server
+ plays an announcement and prompts the user to enter a credit card
+ number and the amount of money to be used to replenish the account
+ (7). The Top-up server validates the credit card number and
+ replenishes the user's account (using some means outside the scope of
+ this specification) and releases the SIP session (8). The SIP
+ controller can now assume that communication between the prepaid user
+ and the Top-up server took place. It sends a spontaneous Credit-
+ Control-Request (UPDATE_REQUEST) to the Diameter credit-control
+ server to check whether the account has been replenished (9). The
+ Diameter credit-control server reserves credit from the end user's
+ account and returns the reserved quota to the SIP controller in the
+ Credit-Control-Answer (10). At this point, the SIP controller re-
+ connects the caller and the called party (11,12).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 104]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+A.8. Flow VIII
+
+ NAS Top-up CC
+ End-User (CC Client) AAA Server Server Server
+ |(1)User Logon |(2)AA Request (CC AVPs) | |
+ |------------------>|------------------->| | |
+ | | |(3)CCR(initial, CC AVPs)
+ | | |------------------->|
+ | | |(4)CCA(Final-Unit, |
+ | | | Validity-Time)|
+ | | |<-------------------|
+ | |(5)AA Answer(Final-Unit,Validity-Time) |
+ |(6)Limited Access |<-------------------| | |
+ | granted | | | |
+ |<----------------->| | | |
+ | | | | |
+ | (7)TCP/HTTP | (8)TCP/HTTP | |
+ |<----------------->|<----------------------------->| |
+ | (9) Replenish account | |
+ |<------------------------------------------------->| |
+ | | | (10)RAR |
+ | |<-------------------|<-------------------|
+ | | (11) RAA | |
+ | |------------------->|------------------->|
+ | |(12)CCR(update) | |
+ | |------------------->|(13)CCR(Update) |
+ | | |------------------->|
+ | | |(14)CCA(Granted-Units)
+ | |(15)CCA(Granted-Units)<------------------|
+ | |<-------------------| |
+
+ Figure A.8: Flow VIII
+
+ Figure A.8 is an example of the graceful service termination
+ initiated when the first interrogation takes place because the user's
+ account is empty. In this example, the credit-control server
+ supports the server-initiated credit re-authorization. The Diameter
+ [NASREQ] is implemented in the Network Access Server (NAS).
+
+ The user logs on to the network (1). The Diameter NAS sends a
+ Diameter AA-Request to the home Diameter AAA server. The credit-
+ control client populates the AAR with the Credit-Control AVP set to
+ CREDIT_AUTHORIZATION, and service specific AVPs are included, as
+ usual [NASREQ]. The home Diameter AAA server performs service
+ specific Authentication and Authorization, as usual. The home
+ Diameter AAA server determines that the user has a prepaid
+ subscription and notices from the Credit-Control AVP that the NAS has
+ credit-control capabilities. It sends a Diameter Credit-Control-
+
+
+
+Hakala, et al. Standards Track [Page 105]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ Request with CC-Request-Type set to INITIAL_REQUEST to the Diameter
+ credit-control server to perform credit authorization (3) and to
+ establish a credit-control session. (The home Diameter AAA server
+ may forward service specific AVPs received from the NAS as input for
+ the rating process.) The Diameter credit-control server checks the
+ end user's account balance, determines that the account cannot cover
+ the cost of the service, and initiates the graceful service
+ termination. The Credit-Control-Answer is returned to the home
+ Diameter AAA server (4). This message contains the Final-Unit-
+ Indication AVP and the Validity-Time AVP set to a reasonable amount
+ of time to give the user a chance to replenish his/her account (e.g.,
+ 10 minutes). The Final-Unit-Indication AVP includes the Final-Unit-
+ Action set to REDIRECT, the Redirect-Address-Type set to URL, and the
+ Redirect-Server-Address set to the HTTP Top-up server name. The home
+ Diameter AAA server sends the received credit-control AVPs to the NAS
+ in the Diameter AA-Answer (5). Upon successful AAA, the NAS starts
+ the credit-control session and immediately starts the graceful
+ service termination, as instructed by the server. The NAS grants
+ limited access to the user (6). The HTTP client software running in
+ the user's device opens the transport connection redirected by the
+ NAS to the Top-up server (7,8). The user is displayed an appropriate
+ web page on which to enter the credit card number, and the amount of
+ money to be used to replenish the account, and with a notification
+ message that she is granted unlimited access if the replenishment
+ operation will be successfully executed within the next, for example,
+ 10 minutes. The Top-up server validates the credit card number and
+ replenishes the user's account (using some means outside the scope of
+ this specification)(9). After successful account top-up, the
+ credit-control server sends a Re-Auth-Request message to the NAS
+ (10). The NAS acknowledges the request by returning the Re-Auth-
+ Answer message (11) and initiates the credit re-authorization by
+ sending a Credit-Control-request (UPDATE_REQUEST) to the Diameter
+ credit-control server (12,13).
+
+ The Diameter credit-control server reserves credit from the end
+ user's account and returns the reserved quota to the NAS via the home
+ Diameter AAA server in the Credit-Control-Answer (14,15). The NAS
+ removes the restriction placed by the graceful service termination
+ and starts monitoring the granted units.
+
+
+
+
+
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 106]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+A.9. Flow IX
+
+ The Diameter credit-control application defines the Multiple-
+ Services-Credit-Control AVP that can be used to support independent
+ credit-control of multiple services in a single credit-control (sub-)
+ session for service elements that have such capabilities. It is
+ possible to request and allocate resources as a credit pool that is
+ shared between services or rating groups.
+
+ The flow example hereafter illustrates a usage scenario where the
+ credit-control client and server support independent credit-control
+ of multiple services, as defined in section 5.1.2. It is assumed
+ that Service-Identifiers, Rating-Groups, and their associated
+ parameters (e.g., IP 5-tuple) are locally configured in the service
+ element or provisioned by an entity other than the credit-control
+ server.
+
+ End User Service Element CC Server
+ (CC client)
+ |(1)User logon | |
+ |------------------>|(2)CCR(initial, Service-Id access, |
+ | | Access specific AVPs, |
+ | | Multiple-Service-Indicator) |
+ | |---------------------------------------->|
+ | |(3)CCA(Multiple-Services-CC ( |
+ | | Granted-Units(Total-Octets), |
+ | | Service-Id access, |
+ | | Validity-time, |
+ | | G-S-U-Pool-Reference(Pool-Id 1, |
+ | | Multiplier 10))) |
+ | |<----------------------------------------|
+ : : :
+ |(4)Service-Request (Service 1) |
+ |------------------>|(5)CCR(update, Multiple-Services-CC( |
+ | | Requested-Units(), Service-Id 1, |
+ | | Rating-Group 1)) |
+ | |---------------------------------------->|
+ | |(6)CCA(Multiple-Services-CC ( |
+ | | Granted-Units(Time), |
+ | | Rating-Group 1, |
+ | | G-S-U-Pool-Reference(Pool-Id 1, |
+ | | Multiplier 1))) |
+ | |<----------------------------------------|
+ : : :
+ |(7)Service-Request (Service 2) |
+ |------------------>| |
+
+
+
+
+
+Hakala, et al. Standards Track [Page 107]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ : : :
+ : : :
+ |(8)Service-Request (Service 3&4) |
+ |------------------>|(9)CCR(update, Multiple-Services-CC ( |
+ | | Requested-Units(), Service-Id 3, |
+ | | Rating-Group 2), |
+ | | Multiple-Services-CC ( |
+ | | Requested-Units(), Service-Id 4, |
+ | | Rating-Group 3)) |
+ | |---------------------------------------->|
+ | |(10)CCA(Multiple-Services-CC ( |
+ | | Granted-Units(Total-Octets), |
+ | | Service-Id 3, Rating-Group 2, |
+ | | Validity-time, |
+ | | G-S-U-Pool-Reference(Pool-Id 2, |
+ | | Multiplier 2)), |
+ | | Multiple-Services-CC ( |
+ | | Granted-Units(Total-Octets), |
+ | | Service-Id 4, Rating-Group 3 |
+ | | Validity-Time, |
+ | | Final-Unit-Ind.(Terminate), |
+ | | G-S-U-Pool-Reference(Pool-Id 2, |
+ | | Multiplier 5))) |
+ | |<----------------------------------------|
+ : : :
+ : : :
+ | +--------------+ | |
+ | |Validity time | |(11)CCR(update, |
+ | |expires for | | Multiple-Services-CC ( |
+ | |Service-Id | | Requested-Unit(), |
+ | | access | | Used-Units(In-Octets,Out-Octets),|
+ | +--------------+ | Service-Id access)) |
+ | |---------------------------------------->|
+ | |(12)CCA(Multiple-Services-CC ( |
+ | | Granted-Units(Total-Octets), |
+ | | Service-Id access, |
+ | | Validity-Time, |
+ | | G-S-U-Pool-Reference(Pool-Id 1, |
+ | | Multiplier 10))) |
+ | |<----------------------------------------|
+ : : :
+ : : :
+
+
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 108]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ | +--------------+ | |
+ | |Total Quota | |(13)CCR(update, |
+ | |elapses for | | Multiple-Services-CC ( |
+ | |pool 2: | | Requested-Unit(), |
+ | |service 4 not | | Used-Units(In-Octets,Out-Octets),|
+ | |allowed, | | Service-Id 3, Rating-group 2), |
+ | |service 3 cont| | Multiple-Services-CC ( |
+ | +--------------+ | Used-Units(In-Octets,Out-Octets),|
+ | | Service-Id 4, Rating-Group 3)) |
+ | |---------------------------------------->|
+ | |(14)CCA(Multiple-Services-CC ( |
+ | | Result-Code 4011, |
+ | | Service-Id 3)) |
+ | |<----------------------------------------|
+ : : :
+ : : :
+ |(15) User logoff | |
+ |------------------>|(16)CCR(term, |
+ | | Multiple-Services-CC ( |
+ | | Used-Units(In-Octets,Out-Octets),|
+ | | Service-Id access), |
+ | | Multiple-Services-CC ( |
+ | | Used-Units(Time), |
+ | | Service-Id 1, Rating-Group 1), |
+ | | Multiple-Services-CC ( |
+ | | Used-Units(Time), |
+ | | Service-Id 2, Rating-Group 1)) |
+ | |---------------------------------------->|
+ | |(17)CCA(term) |
+ | |<----------------------------------------|
+
+ Figure A.9: Flow example independent credit-control of multiple
+ services in a credit-control (sub-)Session
+
+ The user logs on to the network (1). The service element sends a
+ Diameter Credit-Control-Request with CC-Request-Type set to
+ INITIAL_REQUEST to the Diameter credit-control server to perform
+ credit authorization for the bearer service (e.g., Internet access
+ service) and to establish a credit-control session (2). In this
+ message, the credit-control client indicates support for independent
+ credit-control of multiple services within the session by including
+ the Multiple-Service-Indicator AVP. The Diameter credit-control
+ server checks the end user's account balance, with rating information
+ received from the client (i.e., Service-Id and access specific AVPs),
+ rates the request, and reserves credit from the end user's account.
+ Suppose that the server reserves $5 and determines that the cost is
+ $1/MB. It then returns to the service element a Credit-Control-
+ Answer message that includes the Multiple-Services-Credit-Control AVP
+
+
+
+Hakala, et al. Standards Track [Page 109]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ with a quota of 5MB associated to the Service-Id (access), to a
+ multiplier value of 10, and to the Pool-Id 1 (3).
+
+ The user uses Service 1 (4). The service element sends a Diameter
+ Credit-Control-Request with CC-Request-Type set to UPDATE_REQUEST to
+ the credit-control server to perform credit authorization for service
+ 1 (5). This message includes the Multiple-Services-Credit-Control
+ AVP to request service units for Service 1 that belong to Rating-
+ Group 1. The Diameter credit-control server determines that Service
+ 1 draws credit resources from the same account as the access service
+ (i.e., pool 1). It rates the request according to Service-
+ Id/Rating-Group and updates the existing reservation by requesting
+ more credit. Suppose that the server reserves $5 more (now the
+ reservation is $10) and determines that the cost is $0.1/minute. The
+ server authorizes the whole Rating-Group. It then returns to the
+ service element a Credit-Control-Answer message that includes the
+ Multiple-Services-Credit-Control AVP with a quota of 50min.
+ associated to the Rating-Group 1, to a multiplier value of 1, and to
+ the Pool-Id 1 (6). The client adjusts the total amount of resources
+ for pool 1 according the received quota, which gives S for Pool 1 =
+ 100.
+
+ The user uses Service 2, which belongs to the authorized Rating-
+ Group, 1 (7). Resources are then consumed from the pool 1.
+
+ The user now requests Services 3 and 4 as well, which are not
+ authorized (8). The service element sends a Diameter Credit-
+ Control-Request with CC-Request-Type set to UPDATE_REQUEST to the
+ credit-control server in order to perform credit authorization for
+ Services 3 and 4 (9). This message includes two instances of the
+ Multiple-Services-Credit-Control AVP to request service units for
+ Service 3 that belong to Rating-Group 2 and for Service 4 that belong
+ to Rating-Group 3. The Diameter credit-control server determines
+ that Services 3 and 4 draw credit resources from another account
+ (i.e., pool 2). It checks the end user's account balance and,
+ according to Service-Ids/Rating-Groups information, rates the
+ request. Then it reserves credit from pool 2.
+
+ For example, the server reserves $5 and determines that Service 3
+ costs $0.2/MB and Service 4 costs $0.5/MB. The server authorizes
+ only Services 3 and 4. It returns to the service element a Credit-
+ Control-Answer message that includes two instances of the Multiple-
+ Services-Credit-Control AVP (10). One instance grants a quota of
+ 12.5MB associated to the Service-Id 3 to a multiplier value of 2 and
+ to the Pool-Id 2. The other instance grants a quota of 5 MB
+ associated to the Service-Id 4 to a multiplier value of 5 and to the
+ Pool-Id 2.
+
+
+
+
+Hakala, et al. Standards Track [Page 110]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ The server also determines that pool 2 is exhausted and Service 4 is
+ not allowed to continue after these units will be consumed.
+ Therefore the Final-Unit-Indication AVP with action TERMINATE is
+ associated to the Service-Id 4. The client calculates the total
+ amount of resources that can be used for pool 2 according the
+ received quotas and multipliers, which gives S for Pool 2 = 50.
+
+ The Validity-Time for the access service expires. The service
+ element sends a Credit-Control-Request message to the server in order
+ to perform credit re-authorization for Service-Id (access) (11).
+ This message carries one instance of the Multiple-Services-Credit-
+ Control AVP that includes the units used by this service. Suppose
+ that the total amount of used units is 4MB. The client adjusts the
+ total amount of resources for pool 1 accordingly, which gives S for
+ Pool 1 = 60.
+
+ The server deducts $4 from the user's account and updates the
+ reservation by requesting more credit. Suppose that the server
+ reserves $5 more (now the reservation is $11) and already knows the
+ cost of the Service-Id (access), which is $1/MB. It then returns to
+ the service element a Credit-Control-Answer message that includes the
+ Multiple-Services-Credit-Control AVP with a quota of 5 MB associated
+ to the Service-Id (access), to a multiplier value of 10, and to the
+ Pool-Id 1 (12). The client adjusts the total amount of resources for
+ pool 1 according the received quota, which gives S for Pool 1 = 110.
+
+ Services 3 and 4 consume the total amount of pool 2 credit resources
+ (i.e., C1*2 + C2*5 >= S). The service element immediately starts the
+ TERMINATE action concerning Service 4 and sends a Credit-Control-
+ Request message with CC-Request-Type set to UPDATE_REQUEST to the
+ credit-control server in order to perform credit re-authorization for
+ Service 3 (13). This message contains two instances of the
+ Multiple-Services-Credit-Control AVP to report the units used by
+ Services 3 and 4. The server deducts the last $5 from the user's
+ account (pool 2) and returns the answer with Result-Code 4011 in the
+ Multiple-Services-Credit-Control AVP to indicate that Service 3 can
+ continue without credit-control (14).
+
+ The end user logs off from the network (15). To debit the used units
+ from the end user's account and to stop the credit-control session,
+ the service element sends a Diameter Credit-Control-Request with CC-
+ Request-Type set to TERMINATION_REQUEST to the credit-control server
+ (16). This message contains the units consumed by each of the used
+ services in multiple instances of the Multiple-Services-Credit-
+ Control AVP. The used units are associated with the relevant
+ Service-Identifier and Rating-Group. The Diameter credit-control
+
+
+
+
+
+Hakala, et al. Standards Track [Page 111]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ server debits the used units to the user's account (Pool 1) and
+ acknowledges the session termination by sending a Diameter Credit-
+ Control-Answer to the service element (17).
+
+Authors' Addresses
+
+ Harri Hakala
+ Oy L M Ericsson Ab
+ Joukahaisenkatu 1
+ 20520 Turku
+ Finland
+
+ Phone: +358 2 265 3722
+
+
+ Leena Mattila
+ Oy L M Ericsson Ab
+ Joukahaisenkatu 1
+ 20520 Turku
+ Finland
+
+ Phone: +358 2 265 3731
+
+
+ Juha-Pekka Koskinen
+ Nokia Networks
+ Hatanpaanvaltatie 30
+ 33100 Tampere
+ Finland
+
+ Phone: +358 7180 74027
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 112]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+ Marco Stura
+ Nokia Networks
+ Hiomotie 32
+ 00380 Helsinki
+ Finland
+
+ Phone: +358 7180 64308
+
+
+ John Loughney
+ Nokia Research Center
+ Itamerenkatu 11-13
+ 00180 Helsinki
+ Finland
+
+ Phone: +358 50 483 642
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 113]
+
+RFC 4006 Diameter Credit-Control Application August 2005
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2005).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at ietf-
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+Hakala, et al. Standards Track [Page 114]
+
diff --git a/lib/diameter/doc/standard/rfc4072.txt b/lib/diameter/doc/standard/rfc4072.txt
new file mode 100644
index 0000000000..dd0b3a18ac
--- /dev/null
+++ b/lib/diameter/doc/standard/rfc4072.txt
@@ -0,0 +1,1851 @@
+
+
+
+
+
+
+Network Working Group P. Eronen, Ed.
+Request for Comments: 4072 Nokia
+Category: Standards Track T. Hiller
+ Lucent Technologies
+ G. Zorn
+ Cisco Systems
+ August 2005
+
+
+ Diameter Extensible Authentication Protocol (EAP) Application
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ The Extensible Authentication Protocol (EAP) provides a standard
+ mechanism for support of various authentication methods. This
+ document defines the Command-Codes and AVPs necessary to carry EAP
+ packets between a Network Access Server (NAS) and a back-end
+ authentication server.
+
+Table of Contents
+
+ 1. Introduction ...................................................2
+ 1.1. Conventions Used in This Document ........................3
+ 2. Extensible Authentication Protocol Support in Diameter .........3
+ 2.1. Advertising Application Support ..........................3
+ 2.2. Protocol Overview ........................................4
+ 2.3. Sessions and NASREQ Interaction ..........................6
+ 2.3.1. Scenario 1: Direct Connection .....................7
+ 2.3.2. Scenario 2: Direct Connection with Redirects ......8
+ 2.3.3. Scenario 3: Direct EAP, Authorization via Agents ..9
+ 2.3.4. Scenario 4: Proxy Agents .........................10
+ 2.4. Invalid Packets .........................................10
+ 2.5. Retransmission ..........................................11
+ 2.6. Fragmentation ...........................................12
+ 2.7. Accounting ..............................................12
+ 2.8. Usage Guidelines ........................................13
+
+
+
+Eronen, et al. Standards Track [Page 1]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+ 2.8.1. User-Name AVP ....................................13
+ 2.8.2. Conflicting AVPs .................................13
+ 2.8.3. Displayable Messages .............................14
+ 2.8.4. Role Reversal ....................................14
+ 2.8.5. Identifier Space .................................14
+ 3. Command-Codes .................................................14
+ 3.1. Diameter-EAP-Request (DER) Command ......................15
+ 3.2. Diameter-EAP-Answer (DEA) Command .......................16
+ 4. Attribute-Value Pairs .........................................18
+ 4.1. New AVPs ................................................18
+ 4.1.1. EAP-Payload AVP ..................................18
+ 4.1.2. EAP-Reissued-Payload AVP .........................18
+ 4.1.3. EAP-Master-Session-Key AVP .......................19
+ 4.1.4. EAP-Key-Name AVP .................................19
+ 4.1.5. Accounting-EAP-Auth-Method AVP ...................19
+ 5. AVP Occurrence Tables .........................................19
+ 5.1. EAP Command AVP Table ...................................20
+ 5.2. Accounting AVP Table ....................................21
+ 6. RADIUS/Diameter Interactions ..................................22
+ 6.1. RADIUS Request Forwarded as Diameter Request ............22
+ 6.2. Diameter Request Forwarded as RADIUS Request ............23
+ 6.3. Accounting Requests .....................................24
+ 7. IANA Considerations ...........................................24
+ 8. Security Considerations .......................................24
+ 8.1. Overview ................................................24
+ 8.2. AVP Editing .............................................26
+ 8.3. Negotiation Attacks .....................................27
+ 8.4. Session Key Distribution ................................28
+ 8.5. Privacy Issues ..........................................28
+ 8.6. Note about EAP and Impersonation ........................29
+ 9. Acknowledgements ..............................................29
+ 10. References ....................................................30
+ 10.1. Normative References ....................................30
+ 10.2. Informative References ..................................30
+
+1. Introduction
+
+ The Extensible Authentication Protocol (EAP), defined in [EAP], is an
+ authentication framework which supports multiple authentication
+ mechanisms. EAP may be used on dedicated links, switched circuits,
+ and wired as well as wireless links.
+
+ To date, EAP has been implemented with hosts and routers that connect
+ via switched circuits or dial-up lines using PPP [RFC1661], IEEE 802
+ wired switches [IEEE-802.1X], and IEEE 802.11 wireless access points
+ [IEEE-802.11i]. EAP has also been adopted for IPsec remote access in
+ IKEv2 [IKEv2].
+
+
+
+
+Eronen, et al. Standards Track [Page 2]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+ This document specifies the Diameter EAP application that carries EAP
+ packets between a Network Access Server (NAS) working as an EAP
+ Authenticator and a back-end authentication server. The Diameter EAP
+ application is based on the Diameter Network Access Server
+ Application [NASREQ] and is intended for environments similar to
+ NASREQ.
+
+ In the Diameter EAP application, authentication occurs between the
+ EAP client and its home Diameter server. This end-to-end
+ authentication reduces the possibility for fraudulent authentication,
+ such as replay and man-in-the-middle attacks. End-to-end
+ authentication also provides a possibility for mutual authentication,
+ which is not possible with PAP and CHAP in a roaming PPP environment.
+
+ The Diameter EAP application relies heavily on [NASREQ], and in
+ earlier versions was part of the Diameter NASREQ application. It can
+ also be used in conjunction with NASREQ, selecting the application
+ based on the user authentication mechanism (EAP or PAP/CHAP). The
+ Diameter EAP application defines new Command-Codes and Attribute-
+ Value Pairs (AVPs), and can work together with RADIUS EAP support
+ [RFC3579].
+
+1.1. Conventions Used in This Document
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC2119].
+
+2. Extensible Authentication Protocol Support in Diameter
+
+2.1. Advertising Application Support
+
+ Diameter nodes conforming to this specification MUST advertise
+ support by including the Diameter EAP Application ID value of 5 in
+ the Auth-Application-Id AVP of the Capabilities-Exchange-Request and
+ Capabilities-Exchange-Answer command [BASE].
+
+ If the NAS receives a response with the Result-Code set to
+ DIAMETER_APPLICATION_UNSUPPORTED [BASE], it indicates that the
+ Diameter server in the home realm does not support EAP. If possible,
+ the access device MAY attempt to negotiate another authentication
+ protocol, such as PAP or CHAP. An access device SHOULD be cautious
+ when determining whether a less secure authentication protocol will
+ be used, since this could result from a downgrade attack (see
+ Section 8.3).
+
+
+
+
+
+
+Eronen, et al. Standards Track [Page 3]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+2.2. Protocol Overview
+
+ The EAP conversation between the authenticating peer and the access
+ device begins with the initiation of EAP within a link layer, such as
+ PPP [RFC1661] or IEEE 802.11i [IEEE-802.11i]. Once EAP has been
+ initiated, the access device will typically send a Diameter-EAP-
+ Request message with an empty EAP-Payload AVP to the Diameter server,
+ signifying an EAP-Start.
+
+ If the Diameter home server is willing to do EAP authentication, it
+ responds with a Diameter-EAP-Answer message containing an EAP-Payload
+ AVP that includes an encapsulated EAP packet. The Result-Code AVP in
+ the message will be set to DIAMETER_MULTI_ROUND_AUTH, signifying that
+ a subsequent request is expected. The EAP payload is forwarded by
+ the access device to the EAP client. This is illustrated in the
+ diagram below.
+
+ User NAS Server
+ | | |
+ | (initiate EAP) | |
+ |<------------------------------>| |
+ | | Diameter-EAP-Request |
+ | | EAP-Payload(EAP Start) |
+ | |------------------------------->|
+ | | |
+ | | Diameter-EAP-Answer |
+ | Result-Code=DIAMETER_MULTI_ROUND_AUTH |
+ | | EAP-Payload(EAP Request #1) |
+ | |<-------------------------------|
+ | EAP Request #1 | |
+ |<-------------------------------| |
+ : : :
+ : ...continues... :
+
+ The initial Diameter-EAP-Answer in a multi-round exchange normally
+ includes an EAP-Request/Identity, requesting the EAP client to
+ identify itself. Upon receipt of the EAP client's EAP-Response, the
+ access device will then issue a second Diameter-EAP-Request message,
+ with the client's EAP payload encapsulated within the EAP-Payload
+ AVP.
+
+ A preferred approach is for the access device to issue the
+ EAP-Request/Identity message to the EAP client, and forward the
+ EAP-Response/Identity packet, encapsulated within the EAP-Payload
+ AVP, as a Diameter-EAP-Request to the Diameter server (see the
+ diagram below). This alternative reduces the number of Diameter
+ message round trips. When the EAP-Request/Identity message is issued
+ by the access device, it SHOULD interpret the EAP-Response/Identity
+
+
+
+Eronen, et al. Standards Track [Page 4]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+ packet returned by the authenticating peer, and copy its value to a
+ User-Name AVP in Diameter-EAP-Request. This is useful in roaming
+ environments, since the Destination-Realm is needed for routing
+ purposes. Note that this alternative cannot be universally employed,
+ as there are circumstances in which a user's identity is not needed
+ (such as when authorization occurs based on a calling or called phone
+ number).
+
+ User NAS Server
+ | | |
+ | (initiate EAP) | |
+ |<------------------------------>| |
+ | | |
+ | EAP Request(Identity) | |
+ |<-------------------------------| |
+ | | |
+ | EAP Response(Identity) | |
+ |------------------------------->| |
+ | | Diameter-EAP-Request |
+ | | EAP-Payload(EAP Response) |
+ | |------------------------------->|
+ : : :
+ : ...continues... :
+
+ The conversation continues until the Diameter server sends a
+ Diameter-EAP-Answer with a Result-Code AVP indicating success or
+ failure, and an optional EAP-Payload. The Result-Code AVP is used by
+ the access device to determine whether service is to be provided to
+ the EAP client. The access device MUST NOT rely on the contents of
+ the optional EAP-Payload to determine whether service is to be
+ provided.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eronen, et al. Standards Track [Page 5]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+ : ...continued... :
+ : : :
+ | EAP Response #N | |
+ |------------------------------->| |
+ | | Diameter-EAP-Request |
+ | | EAP-Payload(EAP Response #N) |
+ | |------------------------------->|
+ | | |
+ | | Diameter-EAP-Answer |
+ | | Result-Code=DIAMETER_SUCCESS |
+ | | EAP-Payload(EAP Success) |
+ | | [EAP-Master-Session-Key] |
+ | | (authorization AVPs) |
+ | |<-------------------------------|
+ | | |
+ | EAP Success | |
+ |<-------------------------------| |
+
+ If authorization was requested, a Diameter-EAP-Answer with
+ Result-Code set to DIAMETER_SUCCESS SHOULD also include the
+ appropriate authorization AVPs required for the service requested
+ (see Section 5 and [NASREQ]). In some cases, the home server may not
+ be able to provide all necessary authorization AVPs; in this case, a
+ separate authorization step MAY be used as described in
+ Section 2.3.3. Diameter-EAP-Answer messages whose Result-Code AVP is
+ set to DIAMETER_MULTI_ROUND_AUTH MAY include authorization AVPs.
+
+ A Diameter-EAP-Answer with successful Result-Code MAY also include an
+ EAP-Master-Session-Key AVP that contains keying material for
+ protecting the communication between the user and the NAS. Exactly
+ how this keying material is used depends on the link layer in
+ question, and is beyond the scope of this document.
+
+ A home Diameter server MAY request EAP re-authentication by issuing
+ the Re-Auth-Request [BASE] message to the Diameter client.
+
+ Should an EAP authentication session be interrupted due to a home
+ server failure, the session MAY be directed to an alternate server,
+ but the authentication session will have to be restarted from the
+ beginning.
+
+2.3. Sessions and NASREQ Interaction
+
+ The previous section introduced the basic protocol between the NAS
+ and the home server. Since the Diameter-EAP-Answer message may
+ include a Master Session Key (MSK) for protecting the communication
+ between the user and the NAS, one must ensure that this key does not
+ fall into wrong hands.
+
+
+
+Eronen, et al. Standards Track [Page 6]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+ Basic Diameter security mechanisms (IPsec and TLS) protect Diameter
+ messages hop-by-hop. Since there are currently no end-to-end
+ (NAS-to-home server) security mechanisms defined for Diameter, this
+ section describes possible scenarios on how the messages could be
+ transport protected using these hop-by-hop mechanisms.
+
+ This list of scenarios is not intended to be exhaustive, and it is
+ possible to combine them. For instance, the first proxy agent after
+ the NAS could use redirects as in Scenario 2 to bypass any additional
+ proxy agents.
+
+2.3.1. Scenario 1: Direct Connection
+
+ The simplest case is when the NAS contacts the home server directly.
+ All authorization AVPs and EAP keying material are delivered by the
+ home server.
+
+ NAS home server
+ | |
+ | Diameter-EAP-Request |
+ | Auth-Request-Type=AUTHORIZE_AUTHENTICATE |
+ | EAP-Payload(EAP Start) |
+ |---------------------------------------------------------------->|
+ | |
+ | Diameter-EAP-Answer |
+ | Result-Code=DIAMETER_MULTI_ROUND_AUTH |
+ | EAP-Payload(EAP Request) |
+ |<----------------------------------------------------------------|
+ | |
+ : ...more EAP Request/Response pairs... :
+ | |
+ | Diameter-EAP-Request |
+ | EAP-Payload(EAP Response) |
+ |---------------------------------------------------------------->|
+ | |
+ | Diameter-EAP-Answer |
+ | Result-Code=DIAMETER_SUCCESS |
+ | EAP-Payload(EAP Success) |
+ | EAP-Master-Session-Key |
+ | (authorization AVPs) |
+ |<----------------------------------------------------------------|
+
+ This scenario is the most likely to be used in small networks, or in
+ cases where Diameter agents are not needed to provide routing or
+ additional authorization AVPs.
+
+
+
+
+
+
+Eronen, et al. Standards Track [Page 7]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+2.3.2. Scenario 2: Direct Connection with Redirects
+
+ In this scenario the NAS uses a redirect agent to locate the home
+ server. The rest of the session proceeds as before.
+
+ NAS Local redirect agent Home server
+ | | |
+ | Diameter-EAP-Request | |
+ | Auth-Request-Type=AUTHORIZE_AUTHENTICATE |
+ | EAP-Payload(EAP Start) | |
+ |------------------------------->| |
+ | | |
+ | Diameter-EAP-Answer |
+ | Redirect-Host=homeserver.example.com |
+ | Redirect-Host-Usage=REALM_AND_APPLICATION |
+ |<-------------------------------| |
+ | : |
+ | Diameter-EAP-Request : |
+ | Auth-Request-Type=AUTHORIZE_AUTHENTICATE |
+ | EAP-Payload(EAP Start) : |
+ |---------------------------------------------------------------->|
+ | : |
+ : ...rest of the session continues as in first case... :
+ : : :
+
+ The advantage of this scenario is that knowledge of realms and home
+ servers is centralized to a redirect agent, and it is not necessary
+ to modify the NAS configuration when, for example, a new roaming
+ agreement is made.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eronen, et al. Standards Track [Page 8]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+2.3.3. Scenario 3: Direct EAP, Authorization via Agents
+
+ In this scenario the EAP authentication is done directly with the
+ home server (with Auth-Request-Type set to AUTHENTICATE_ONLY), and
+ authorization AVPs are retrieved from local proxy agents. This
+ scenario is intended for environments in which the home server cannot
+ provide all the necessary authorization AVPs to the NAS.
+
+ NAS Local proxy agent Home server
+ | : |
+ | Diameter-EAP-Request : |
+ | Auth-Request-Type=AUTHENTICATE_ONLY |
+ | EAP-Payload(EAP Start) : |
+ |---------------------------------------------------------------->|
+ | : |
+ | : Diameter-EAP-Answer |
+ | Result-Code=DIAMETER_MULTI_ROUND_AUTH |
+ | : EAP-Payload(EAP Request) |
+ |<----------------------------------------------------------------|
+ | : |
+ : ...more EAP Request/Response pairs... :
+ | : |
+ | Diameter-EAP-Request : |
+ | EAP-Payload(EAP Response) : |
+ |---------------------------------------------------------------->|
+ | : |
+ | : Diameter-EAP-Answer |
+ | : Result-Code=DIAMETER_SUCCESS |
+ | : EAP-Payload(EAP Success) |
+ | : EAP-Master-Session-Key |
+ | : (authorization AVPs) |
+ |<----------------------------------------------------------------|
+ | | |
+ | AA-Request | |
+ | Auth-Request-Type=AUTHORIZE_ONLY |
+ | (some AVPs from first session) | |
+ |------------------------------->| |
+ | | |
+ | AA-Answer | |
+ | Result-Code=DIAMETER_SUCCESS | |
+ | (authorization AVPs) | |
+ |<-------------------------------| |
+
+ The NASREQ application is used here for authorization because the
+ realm-specific routing table supports routing based on application,
+ not on Diameter commands.
+
+
+
+
+
+Eronen, et al. Standards Track [Page 9]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+2.3.4. Scenario 4: Proxy Agents
+
+ This scenario is the same as Scenario 1, but the NAS contacts the
+ home server through proxies. Note that the proxies can see the EAP
+ session keys, thus it is not suitable for environments where proxies
+ cannot be trusted.
+
+ NAS Local proxy/relay agent Home server
+ | | |
+ | Diameter-EAP-Request | |
+ | Auth-Request-Type=AUTHORIZE_AUTHENTICATE |
+ | EAP-Payload(EAP Start) | |
+ |------------------------------->|------------------------------->|
+ | | |
+ | | Diameter-EAP-Answer |
+ | Result-Code=DIAMETER_MULTI_ROUND_AUTH |
+ | | EAP-Payload(EAP Request) |
+ |<-------------------------------|<-------------------------------|
+ | : |
+ : ...more EAP Request/Response pairs... :
+ | : |
+ | Diameter-EAP-Request | |
+ | EAP-Payload(EAP Response) | |
+ |------------------------------->|------------------------------->|
+ | | |
+ | | Diameter-EAP-Answer |
+ | | Result-Code=DIAMETER_SUCCESS |
+ | | EAP-Payload(EAP Success) |
+ | | EAP-Master-Session-Key |
+ | | (authorization AVPs) |
+ |<-------------------------------|<-------------------------------|
+
+2.4. Invalid Packets
+
+ While acting as a pass-through, the NAS MUST validate the EAP header
+ fields (Code, Identifier, Length) prior to forwarding an EAP packet
+ to or from the Diameter server. On receiving an EAP packet from the
+ peer, the NAS checks the Code (Code 2=Response) and Length fields,
+ and matches the Identifier value against the current Identifier,
+ supplied by the Diameter server in the most recently validated EAP
+ Request. On receiving an EAP packet from the Diameter server
+ (encapsulated within a Diameter-EAP-Answer), the NAS checks the Code
+ (Code 1=Request) and Length fields, then updates the current
+ Identifier value. Pending EAP Responses that do not match the
+ current Identifier value are silently discarded by the NAS.
+
+
+
+
+
+
+Eronen, et al. Standards Track [Page 10]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+ Since EAP method fields (Type, Type-Data) are typically not validated
+ by a NAS operating as a pass-through, despite these checks it is
+ possible for a NAS to forward an invalid EAP packet to or from the
+ Diameter server.
+
+ A Diameter server receiving an EAP-Payload AVP that it does not
+ understand SHOULD determine whether the error is fatal or non-fatal
+ based on the EAP Type. A Diameter server determining that a fatal
+ error has occurred MUST send a Diameter-EAP-Answer with a failure
+ Result-Code and an EAP-Payload AVP encapsulating an EAP Failure
+ packet. A Diameter server determining that a non-fatal error has
+ occurred MUST send a Diameter-EAP-Answer with
+ DIAMETER_MULTI_ROUND_AUTH Result-Code, but no EAP-Payload AVP. To
+ simplify RADIUS translation, this message MUST also include an
+ EAP-Reissued-Payload AVP encapsulating the previous EAP Request sent
+ by the server.
+
+ When receiving a Diameter-EAP-Answer without an EAP-Payload AVP (and
+ DIAMETER_MULTI_ROUND_AUTH Result-Code), the NAS SHOULD discard the
+ EAP-Response packet most recently transmitted to the Diameter server
+ and check whether additional EAP Response packets that match the
+ current Identifier value have been received. If so, a new EAP
+ Response packet, if available, MUST be sent to the Diameter server
+ within an Diameter-EAP-Request. If no EAP Response packet is
+ available, then the previous EAP Request is resent to the peer, and
+ the retransmission timer is reset.
+
+ In order to provide protection against Denial of Service (DoS)
+ attacks, it is advisable for the NAS to allocate a finite buffer for
+ EAP packets received from the peer, and to discard packets according
+ to an appropriate policy once that buffer has been exceeded. Also,
+ the Diameter server is advised to permit only a modest number of
+ invalid EAP packets within a single session, prior to terminating the
+ session with DIAMETER_AUTHENTICATION_REJECTED Result-Code. By
+ default, a value of 5 invalid EAP packets is recommended.
+
+2.5. Retransmission
+
+ As noted in [EAP], if an EAP packet is lost in transit between the
+ authenticating peer and the NAS (or vice versa), the NAS will
+ retransmit.
+
+ It may be necessary to adjust retransmission strategies and
+ authentication time-outs in certain cases. For example, when a token
+ card is used, additional time may be required to allow the user to
+ find the card and enter the token. Since the NAS will typically not
+ have knowledge of the required parameters, these need to be provided
+ by the Diameter server.
+
+
+
+Eronen, et al. Standards Track [Page 11]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+ If a Multi-Round-Time-Out AVP [BASE] is present in a Diameter-EAP-
+ Answer message that also contains an EAP-Payload AVP, that value is
+ used to set the EAP retransmission timer for that EAP Request and
+ that Request alone.
+
+2.6. Fragmentation
+
+ Using the EAP-Payload AVP, it is possible for the Diameter server to
+ encapsulate an EAP packet that is larger than the MTU on the link
+ between the NAS and the peer. Since it is not possible for the
+ Diameter server to use MTU discovery to ascertain the link MTU, a
+ Framed-MTU AVP may be included in a Diameter-EAP-Request message in
+ order to provide the Diameter server with this information.
+
+ A Diameter server having received a Framed-MTU AVP in a
+ Diameter-EAP-Request message MUST NOT send any subsequent packet in
+ this EAP conversation containing EAP-Payload AVP whose length exceeds
+ that specified by the Framed-MTU value, taking the link type
+ (specified by the NAS-Port-Type AVP) into account. For example, as
+ noted in [RFC3580] Section 3.10, for a NAS-Port-Type value of IEEE
+ 802.11, the RADIUS server may send an EAP packet as large as
+ Framed-MTU minus four (4) octets, taking into account the additional
+ overhead for the IEEE 802.1X Version (1 octet), Type (1 octet) and
+ Body Length (2 octets) fields.
+
+2.7. Accounting
+
+ When a user is authenticated using EAP, the NAS MAY include an
+ Accounting-Auth-Method AVP [NASREQ] with value 5 (EAP) in
+ Accounting-Request messages. This document specifies one additional
+ AVP for accounting messages. One or more Accounting-EAP-Auth-Method
+ AVPs (see Section 4.1.5) MAY be included in Accounting-Request
+ messages to indicate the EAP method(s) used to authenticate the user.
+
+ If the NAS has authenticated the user with a locally implemented EAP
+ method, it knows the method used and SHOULD include it in an
+ Accounting-EAP-Auth-Method AVP.
+
+ If the authentication was done using Diameter-EAP-Request/Answer
+ messages, the Diameter server SHOULD include one or more
+ Accounting-EAP-Auth-Method AVPs in Diameter-EAP-Answer packets with a
+ successful result code. In this case, the NAS SHOULD include these
+ AVPs in Accounting-Request messages.
+
+
+
+
+
+
+
+
+Eronen, et al. Standards Track [Page 12]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+2.8. Usage Guidelines
+
+2.8.1. User-Name AVP
+
+ Unless the access device interprets the EAP-Response/Identity packet
+ returned by the authenticating peer, it will not have access to the
+ user's identity. Furthermore, some EAP methods support identity
+ protection where the user's real identity is not included in
+ EAP-Response/Identity. Therefore, the Diameter Server SHOULD return
+ the user's identity by inserting a User-Name AVP to
+ Diameter-EAP-Answer messages that have a Result-Code of
+ DIAMETER_SUCCESS. A separate billing identifier or pseudonym MAY be
+ used for privacy reasons (see Section 8.5). If the user's identity
+ is not available to the NAS, the Session-Id AVP MAY be used for
+ accounting and billing; however operationally this could be very
+ difficult to manage.
+
+2.8.2. Conflicting AVPs
+
+ A Diameter-EAP-Answer message containing an EAP-Payload of type
+ EAP-Success or EAP-Failure MUST NOT have the Result-Code AVP set to
+ DIAMETER_MULTI_ROUND_AUTH.
+
+ Some lower layers assume that the authorization decision is made by
+ the EAP server, and thus the peer considers EAP Success as an
+ indication that access was granted. In this case, the Result-Code
+ SHOULD match the contained EAP packet: a successful Result-Code for
+ EAP-Success, and a failure Result-Code for EAP-Failure. If the
+ encapsulated EAP packet does not match the result implied by the
+ Result-Code AVP, the combination is likely to cause confusion,
+ because the NAS and peer will conclude the outcome of the
+ authentication differently. For example, if the NAS receives a
+ failure Result-Code with an encapsulated EAP Success, it will not
+ grant access to the peer. However, on receiving the EAP Success, the
+ peer will be led to believe that access was granted.
+
+ This situation can be difficult to avoid when Diameter proxy agents
+ make authorization decisions (that is, proxies can change the
+ Result-Code AVP sent by the home server). Because it is the
+ responsibility of the Diameter server to avoid conflicts, the NAS
+ MUST NOT "manufacture" EAP result packets in order to correct the
+ contradictory messages that it receives. This behavior, originally
+ mandated within [IEEE-802.1X], is now deprecated.
+
+
+
+
+
+
+
+
+Eronen, et al. Standards Track [Page 13]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+2.8.3. Displayable Messages
+
+ The Reply-Message AVP [NASREQ] MUST NOT be included in any Diameter
+ message containing an EAP-Payload AVP.
+
+2.8.4. Role Reversal
+
+ Some environments in which EAP is used, such as PPP, support
+ peer-to-peer operation. Both parties act as authenticators and
+ authenticatees at the same time, in two simultaneous and independent
+ EAP conversations.
+
+ This specification is intended for communication between EAP
+ (passthrough) authenticator and backend authentication server. A
+ Diameter client MUST NOT send a Diameter-EAP-Request encapsulating an
+ EAP Request packet, and a Diameter server receiving such a packet
+ MUST respond with a failure Result-Code.
+
+2.8.5. Identifier Space
+
+ In EAP, each session has its own unique Identifier space. Diameter
+ server implementations MUST be able to distinguish between EAP
+ packets with the same Identifier existing within distinct EAP
+ sessions and originating on the same NAS. This is done by using the
+ Session-Id AVP.
+
+ If a Diameter NAS is in the middle of a multi-round authentication
+ exchange, and it detects that the EAP session between the client and
+ the NAS has been terminated, it MUST select a new Diameter Session-Id
+ for any subsequent EAP sessions. This is necessary in order to
+ distinguish a restarted EAP authentication process from the
+ continuation of an ongoing process (by the same user on the same NAS
+ and port).
+
+ In RADIUS, the same functionality can be achieved through the
+ inclusion or omission of the State attribute. Translation rules in
+ [NASREQ] ensure that an Access-Request without the State attribute
+ maps to a new Diameter Session-Id AVP value. Furthermore, a
+ translation agent will always include a State attribute in
+ Access-Challenge messages, making sure that the State attribute is
+ available for a RADIUS NAS.
+
+3. Command-Codes
+
+ This section defines new Command-Code values that MUST be supported
+ by all Diameter implementations conforming to this specification.
+ The following commands are defined in this section:
+
+
+
+
+Eronen, et al. Standards Track [Page 14]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+ Command-Name Abbrev. Code Reference
+ --------------------------------------------------------
+ Diameter-EAP-Request DER 268 3.1
+ Diameter-EAP-Answer DEA 268 3.2
+
+ When the NASREQ AA-Request (AAR) or AA-Answer (AAA) commands are used
+ for AUTHORIZE_ONLY messages in conjunction with EAP (see
+ Section 2.3.3), an Application Identifier value of 1 (NASREQ) is
+ used, and the commands follow the rules and ABNF defined in [NASREQ].
+
+ When the Re-Auth-Request (RAR), Re-Auth-Answer (RAA),
+ Session-Termination-Request (STR), Session-Termination-Answer (STA),
+ Abort-Session-Request (ASR), Abort-Session-Answer (ASA),
+ Accounting-Request (ACR), and Accounting-Answer (ACA) commands are
+ used together with the Diameter EAP application, they follow the
+ rules in [NASREQ] and [BASE]. The accounting commands use
+ Application Identifier value of 3 (Diameter Base Accounting); the
+ others use 0 (Diameter Common Messages).
+
+3.1. Diameter-EAP-Request (DER) Command
+
+ The Diameter-EAP-Request (DER) command, indicated by the Command-Code
+ field set to 268 and the 'R' bit set in the Command Flags field, is
+ sent by a Diameter client to a Diameter server, and conveys an
+ EAP-Response from the EAP client. The Diameter-EAP-Request MUST
+ contain one EAP-Payload AVP containing the actual EAP payload. An
+ EAP-Payload AVP with no data MAY be sent to the Diameter server to
+ initiate an EAP authentication session.
+
+ The DER message MAY be the result of a multi-round authentication
+ exchange that occurs when the DEA is received with the Result-Code
+ AVP set to DIAMETER_MULTI_ROUND_AUTH [BASE]. A subsequent DER
+ message MUST include any State AVPs [NASREQ] that were present in the
+ DEA. For re-authentication, it is recommended that the Identity
+ request be skipped in order to reduce the number of authentication
+ round trips. This is only possible when the user's identity is
+ already known by the home Diameter server.
+
+ Message format
+
+ <Diameter-EAP-Request> ::= < Diameter Header: 268, REQ, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Auth-Request-Type }
+ [ Destination-Host ]
+
+
+
+Eronen, et al. Standards Track [Page 15]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+ [ NAS-Identifier ]
+ [ NAS-IP-Address ]
+ [ NAS-IPv6-Address ]
+ [ NAS-Port ]
+ [ NAS-Port-Id ]
+ [ NAS-Port-Type ]
+ [ Origin-State-Id ]
+ [ Port-Limit ]
+ [ User-Name ]
+ { EAP-Payload }
+ [ EAP-Key-Name ]
+ [ Service-Type ]
+ [ State ]
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Auth-Session-State ]
+ [ Callback-Number ]
+ [ Called-Station-Id ]
+ [ Calling-Station-Id ]
+ [ Originating-Line-Info ]
+ [ Connect-Info ]
+ * [ Framed-Compression ]
+ [ Framed-Interface-Id ]
+ [ Framed-IP-Address ]
+ * [ Framed-IPv6-Prefix ]
+ [ Framed-IP-Netmask ]
+ [ Framed-MTU ]
+ [ Framed-Protocol ]
+ * [ Tunneling ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+3.2. Diameter-EAP-Answer (DEA) Command
+
+ The Diameter-EAP-Answer (DEA) message, indicated by the Command-Code
+ field set to 268 and the 'R' bit cleared in the Command Flags field,
+ is sent by the Diameter server to the client for one of the following
+ reasons:
+
+ 1. The message is part of a multi-round authentication exchange, and
+ the server is expecting a subsequent Diameter-EAP-Request. This
+ is indicated by setting the Result-Code to
+ DIAMETER_MULTI_ROUND_AUTH, and MAY include zero or more State
+ AVPs.
+
+
+
+
+
+
+Eronen, et al. Standards Track [Page 16]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+ 2. The EAP client has been successfully authenticated and
+ authorized, in which case the message MUST include the
+ Result-Code AVP indicating success, and SHOULD include an
+ EAP-Payload of type EAP-Success. This event MUST cause the
+ access device to provide service to the EAP client.
+
+ 3. The EAP client has not been successfully authenticated and/or
+ authorized, and the Result-Code AVP is set to indicate failure.
+ This message SHOULD include an EAP-Payload, but this AVP is not
+ used to determine whether service is to be provided.
+
+ If the message from the Diameter client included a request for
+ authorization, a successful response MUST include the authorization
+ AVPs that are relevant to the service being provided.
+
+ Message format
+
+ <Diameter-EAP-Answer> ::= < Diameter Header: 268, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Request-Type }
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ [ EAP-Payload ]
+ [ EAP-Reissued-Payload ]
+ [ EAP-Master-Session-Key ]
+ [ EAP-Key-Name ]
+ [ Multi-Round-Time-Out ]
+ [ Accounting-EAP-Auth-Method ]
+ [ Service-Type ]
+ * [ Class ]
+ * [ Configuration-Token ]
+ [ Acct-Interim-Interval ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ [ Idle-Timeout ]
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Auth-Session-State ]
+ [ Re-Auth-Request-Type ]
+ [ Session-Timeout ]
+ [ State ]
+ * [ Reply-Message ]
+ [ Origin-State-Id ]
+ * [ Filter-Id ]
+
+
+
+Eronen, et al. Standards Track [Page 17]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+ [ Port-Limit ]
+ [ Callback-Id ]
+ [ Callback-Number ]
+ [ Framed-Appletalk-Link ]
+ * [ Framed-Appletalk-Network ]
+ [ Framed-Appletalk-Zone ]
+ * [ Framed-Compression ]
+ [ Framed-Interface-Id ]
+ [ Framed-IP-Address ]
+ * [ Framed-IPv6-Prefix ]
+ [ Framed-IPv6-Pool ]
+ * [ Framed-IPv6-Route ]
+ [ Framed-IP-Netmask ]
+ * [ Framed-Route ]
+ [ Framed-Pool ]
+ [ Framed-IPX-Network ]
+ [ Framed-MTU ]
+ [ Framed-Protocol ]
+ [ Framed-Routing ]
+ * [ NAS-Filter-Rule ]
+ * [ QoS-Filter-Rule ]
+ * [ Tunneling ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+4. Attribute-Value Pairs
+
+ This section both defines new AVPs, unique to the EAP Diameter
+ application and describes the usage of AVPs defined elsewhere (if
+ that usage in the EAP application is noteworthy).
+
+4.1. New AVPs
+
+4.1.1. EAP-Payload AVP
+
+ The EAP-Payload AVP (AVP Code 462) is of type OctetString and is used
+ to encapsulate the actual EAP packet that is being exchanged between
+ the EAP client and the home Diameter server.
+
+4.1.2. EAP-Reissued-Payload AVP
+
+ The EAP-Reissued-Payload AVP (AVP Code 463) is of type OctetString.
+ The use of this AVP is described in Section 2.4.
+
+
+
+
+
+Eronen, et al. Standards Track [Page 18]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+4.1.3. EAP-Master-Session-Key AVP
+
+ The EAP-Master-Session-Key AVP (AVP Code 464) is of type OctetString.
+ It contains keying material for protecting the communications between
+ the user and the NAS. Exactly how this keying material is used
+ depends on the link layer in question, and is beyond the scope of
+ this document.
+
+4.1.4. EAP-Key-Name AVP
+
+ The EAP-Key-Name AVP (Radius Attribute Type 102) is of type
+ OctetString. It contains an opaque key identifier (name) generated
+ by the EAP method. Exactly how this name is used depends on the link
+ layer in question, and is beyond the scope of this document (see
+ [EAPKey] for more discussion).
+
+ Note that not all link layers use this name, and currently most EAP
+ methods do not generate it. Since the NAS operates in pass-through
+ mode, it cannot know the Key-Name before receiving it from the AAA
+ server. As a result, a Key-Name AVP sent in a Diameter-EAP-Request
+ MUST NOT contain any data. A home Diameter server receiving a
+ Diameter-EAP-Request with a Key-Name AVP with non-empty data MUST
+ silently discard the AVP. In addition, the home Diameter server
+ SHOULD include this AVP in Diameter-EAP-Response only if an empty
+ EAP-Key-Name AVP was present in Diameter-EAP-Request.
+
+4.1.5. Accounting-EAP-Auth-Method AVP
+
+ The Accounting-EAP-Auth-Method AVP (AVP Code 465) is of type
+ Unsigned64. In case of expanded types [EAP, Section 5.7], this AVP
+ contains the value ((Vendor-Id * 2^32) + Vendor-Type).
+
+ The use of this AVP is described in Section 2.7.
+
+5. AVP Occurrence Tables
+
+ The following tables use these symbols:
+
+ 0 The AVP MUST NOT be present in the message
+ 0+ Zero or more instances of the AVP MAY be present in the message
+ 0-1 Zero or one instance of the AVP MAY be present in the message
+ 1 One instance of the AVP MUST be present in the message
+
+ Note that AVPs that can only be present within a Grouped AVP are not
+ represented in these tables.
+
+
+
+
+
+
+Eronen, et al. Standards Track [Page 19]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+5.1. EAP Command AVP Table
+
+ The following table lists the AVPs that may be present in the DER and
+ DEA Commands, as defined in this document; the AVPs listed are
+ defined both here and in [NASREQ].
+
+ +---------------+
+ | Command-Code |
+ |-------+-------+
+ Attribute Name | DER | DEA |
+ ------------------------------------|-------+-------|
+ Accounting-EAP-Auth-Method | 0 | 0+ |
+ Acct-Interim-Interval [BASE] | 0 | 0-1 |
+ Auth-Application-Id [BASE] | 1 | 1 |
+ Auth-Grace-Period [BASE] | 0-1 | 0-1 |
+ Auth-Request-Type [BASE] | 1 | 1 |
+ Auth-Session-State [BASE] | 0-1 | 0-1 |
+ Authorization-Lifetime [BASE] | 0-1 | 0-1 |
+ Callback-Id [NASREQ] | 0 | 0-1 |
+ Callback-Number [NASREQ] | 0-1 | 0-1 |
+ Called-Station-Id [NASREQ] | 0-1 | 0 |
+ Calling-Station-Id [NASREQ] | 0-1 | 0 |
+ Class [BASE] | 0 | 0+ |
+ Configuration-Token [NASREQ] | 0 | 0+ |
+ Connect-Info [NASREQ] | 0-1 | 0 |
+ Destination-Host [BASE] | 0-1 | 0 |
+ Destination-Realm [BASE] | 1 | 0 |
+ EAP-Master-Session-Key | 0 | 0-1 |
+ EAP-Key-Name | 0-1 | 0-1 |
+ EAP-Payload | 1 | 0-1 |
+ EAP-Reissued-Payload | 0 | 0-1 |
+ Error-Message [BASE] | 0 | 0-1 |
+ Error-Reporting-Host [BASE] | 0 | 0-1 |
+ Failed-AVP [BASE] | 0 | 0+ |
+ Filter-Id [NASREQ] | 0 | 0+ |
+ Framed-Appletalk-Link [NASREQ] | 0 | 0-1 |
+ Framed-Appletalk-Network [NASREQ] | 0 | 0+ |
+ Framed-Appletalk-Zone [NASREQ] | 0 | 0-1 |
+ Framed-Compression [NASREQ] | 0+ | 0+ |
+ Framed-Interface-Id [NASREQ] | 0-1 | 0-1 |
+ Framed-IP-Address [NASREQ] | 0-1 | 0-1 |
+ Framed-IP-Netmask [NASREQ] | 0-1 | 0-1 |
+ Framed-IPv6-Prefix [NASREQ] | 0+ | 0+ |
+ Framed-IPv6-Pool [NASREQ] | 0 | 0-1 |
+ Framed-IPv6-Route [NASREQ] | 0 | 0+ |
+ Framed-IPX-Network [NASREQ] | 0 | 0-1 |
+ Framed-MTU [NASREQ] | 0-1 | 0-1 |
+ Framed-Pool [NASREQ] | 0 | 0-1 |
+
+
+
+Eronen, et al. Standards Track [Page 20]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+ Framed-Protocol [NASREQ] | 0-1 | 0-1 |
+ Framed-Route [NASREQ] | 0 | 0+ |
+ Framed-Routing [NASREQ] | 0 | 0-1 |
+ Idle-Timeout [NASREQ] | 0 | 0-1 |
+ Multi-Round-Time-Out [BASE] | 0 | 0-1 |
+ NAS-Filter-Rule [NASREQ] | 0 | 0+ |
+ NAS-Identifier [NASREQ] | 0-1 | 0 |
+ NAS-IP-Address [NASREQ] | 0-1 | 0 |
+ NAS-IPv6-Address [NASREQ] | 0-1 | 0 |
+ NAS-Port [NASREQ] | 0-1 | 0 |
+ NAS-Port-Id [NASREQ] | 0-1 | 0 |
+ NAS-Port-Type [NASREQ] | 0-1 | 0 |
+ Originating-Line-Info [NASREQ] | 0-1 | 0 |
+ Origin-Host [BASE] | 1 | 1 |
+ Origin-Realm [BASE] | 1 | 1 |
+ Origin-State-Id [BASE] | 0-1 | 0-1 |
+ Port-Limit [NASREQ] | 0-1 | 0-1 |
+ Proxy-Info [BASE] | 0+ | 0+ |
+ QoS-Filter-Rule [NASREQ] | 0 | 0+ |
+ Re-Auth-Request-Type [BASE] | 0 | 0-1 |
+ Redirect-Host [BASE] | 0 | 0+ |
+ Redirect-Host-Usage [BASE] | 0 | 0-1 |
+ Redirect-Max-Cache-Time [BASE] | 0 | 0-1 |
+ Reply-Message [NASREQ] | 0 | 0+ |
+ Result-Code [BASE] | 0 | 1 |
+ Route-Record [BASE] | 0+ | 0+ |
+ Service-Type [NASREQ] | 0-1 | 0-1 |
+ Session-Id [BASE] | 1 | 1 |
+ Session-Timeout [BASE] | 0 | 0-1 |
+ State [NASREQ] | 0-1 | 0-1 |
+ Tunneling [NASREQ] | 0+ | 0+ |
+ User-Name [BASE] | 0-1 | 0-1 |
+
+5.2. Accounting AVP Table
+
+ The table in this section is used to represent which AVPs defined in
+ this document are to be present in the Accounting messages, as
+ defined in [BASE].
+
+ +-----------+
+ | Command |
+ | Code |
+ |-----+-----+
+ Attribute Name | ACR | ACA |
+ ---------------------------------------|-----+-----+
+ Accounting-EAP-Auth-Method | 0+ | 0 |
+
+
+
+
+
+Eronen, et al. Standards Track [Page 21]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+6. RADIUS/Diameter Interactions
+
+ Section 9 of [NASREQ] describes basic guidelines for translation
+ agents that translate between RADIUS and Diameter protocols. These
+ guidelines SHOULD be followed for Diameter EAP application as well,
+ with some additional guidelines given in this section. Note that
+ this document does not restrict implementations from creating
+ additional methods, as long as the translation function does not
+ violate the RADIUS or the Diameter protocols.
+
+6.1. RADIUS Request Forwarded as Diameter Request
+
+ RADIUS Access-Request to Diameter-EAP-Request:
+
+ o RADIUS EAP-Message attribute(s) are translated to a Diameter
+ EAP-Payload AVP. If multiple RADIUS EAP-Message attributes are
+ present, they are concatenated and translated to a single Diameter
+ EAP-Payload AVP.
+
+ o An empty RADIUS EAP-Message attribute (with length 2) signifies
+ EAP-Start, and it is translated to an empty EAP-Payload AVP.
+
+ Diameter-EAP-Answer to RADIUS Access-Accept/Reject/Challenge:
+
+ o Diameter EAP-Payload AVP is translated to RADIUS EAP-Message
+ attribute(s). If necessary, the value is split into multiple
+ RADIUS EAP-Message attributes.
+
+ o Diameter EAP-Reissued-Payload AVP is translated to a message that
+ contains RADIUS EAP-Message attribute(s), and a RADIUS Error-Cause
+ attribute [RFC3576] with value 202 (decimal), "Invalid EAP Packet
+ (Ignored)" [RFC3579].
+
+ o As described in [NASREQ], if the Result-Code AVP set to
+ DIAMETER_MULTI_ROUND_AUTH and the Multi-Round-Time-Out AVP is
+ present, it is translated to the RADIUS Session-Timeout attribute.
+
+ o Diameter EAP-Master-Session-Key AVP can be translated to the
+ vendor-specific RADIUS MS-MPPE-Recv-Key and MS-MPPE-Send-Key
+ attributes [RFC2548]. The first up to 32 octets of the key is
+ stored into MS-MPPE-Recv-Key, and the next up to 32 octets (if
+ present) are stored into MS-MPPE-Send-Key. The encryption of this
+ attribute is described in [RFC2548].
+
+ o Diameter Accounting-EAP-Auth-Method AVPs, if present, are
+ discarded.
+
+
+
+
+
+Eronen, et al. Standards Track [Page 22]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+6.2. Diameter Request Forwarded as RADIUS Request
+
+ Diameter-EAP-Request to RADIUS Access-Request:
+
+ o The Diameter EAP-Payload AVP is translated to RADIUS EAP-Message
+ attribute(s).
+
+ o An empty Diameter EAP-Payload AVP signifies EAP-Start, and is
+ translated to an empty RADIUS EAP-Message attribute.
+
+ o The type (or expanded type) field from the EAP-Payload AVP can be
+ saved either in a local state table, or encoded in a RADIUS
+ Proxy-State attribute. This information is needed to construct an
+ Accounting-EAP-Auth-Method AVP for the answer message (see below).
+
+ RADIUS Access-Accept/Reject/Challenge to Diameter-EAP-Answer:
+
+ o If the RADIUS Access-Challenge message does not contain an
+ Error-Cause attribute [RFC3576] with value 202 (decimal), "Invalid
+ EAP Packet (Ignored)" [RFC3579], any RADIUS EAP-Message attributes
+ are translated to a Diameter EAP-Payload AVP, concatenating them
+ if multiple attributes are present.
+
+ o If the Error-Cause attribute with value 202 is present, any RADIUS
+ EAP-Message attributes are translated to a Diameter
+ EAP-Reissued-Payload AVP, concatenating them if multiple
+ attributes are present.
+
+ o As described in [NASREQ], if the Session-Timeout attribute is
+ present in a RADIUS Access-Challenge message, it is translated to
+ the Diameter Multi-Round-Time-Out AVP.
+
+ o If the vendor-specific RADIUS MS-MPPE-Recv-Key and/or
+ MS-MPPE-Send-Key attributes [RFC2548] are present, they can be
+ translated to a Diameter EAP-Master-Session-Key AVP. The
+ attributes have to be decrypted before conversion, and the Salt,
+ Key-Length and Padding sub-fields are discarded. The Key
+ sub-fields are concatenated (MS-MPPE-Recv-Key first,
+ MS-MPPE-Send-Key next), and the concatenated value is stored into
+ a Diameter EAP-Master-Session-Key AVP.
+
+ o If the Diameter-EAP-Answer will have a successful result code, the
+ saved state (see above) can be used to construct an
+ Accounting-EAP-Auth-Method AVP.
+
+
+
+
+
+
+
+Eronen, et al. Standards Track [Page 23]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+6.3. Accounting Requests
+
+ In Accounting-Requests, the vendor-specific RADIUS MS-Acct-EAP-Type
+ attribute [RFC2548] can be translated to a Diameter
+ Accounting-EAP-Auth-Method AVP, and vice versa.
+
+ When translating from Diameter to RADIUS, note that the
+ MS-Acct-EAP-Type attribute does not support expanded EAP types. Type
+ values greater than 255 should be translated to type 254.
+
+7. IANA Considerations
+
+ This document does not create any new namespaces to be maintained by
+ IANA, but it requires new values in namespaces that have been defined
+ in the Diameter Base protocol and RADIUS specifications.
+
+ o This document defines one new Diameter command (in Section 3)
+ whose Command Code is allocated from the Command Code namespace
+ defined in [BASE]. The Command Code for DER / DEA is 268.
+
+ o This document defines four new AVPs whose AVP Codes are allocated
+ from the AVP Code namespace defined in [BASE] as follows:
+
+ 462 for EAP-Payload (defined in Section 4.1.1),
+ 463 for EAP-Reissued-Payload (defined in Section 4.1.2),
+ 464 for EAP-Master-Session-Key (defined in Section 4.1.3), and
+ 465 for Accounting-EAP-Auth-Method (defined in Section 4.1.5).
+
+ o This document defines one new AVP (attribute) whose AVP Code
+ (Attribute Type) is to be allocated from the Attribute Type
+ namespace defined in [RFC2865] and [RFC3575]. The Radius
+ Attribute Type for EAP-Key-Name (defined in Section 4.1.4) is 102.
+
+ o This document defines one new Diameter application (in
+ Section 2.1) whose Application ID is to be allocated from the
+ Application Identifier namespace defined in [BASE]. The
+ Application ID for Diameter EAP is 5.
+
+8. Security Considerations
+
+8.1. Overview
+
+ Diameter peer-to-peer connections can be protected with IPsec or TLS.
+ These mechanisms are believed to provide sufficient protection under
+ the normal Internet threat model, that is, assuming the authorized
+ nodes engaging in the protocol have not been compromised, but the
+ attacker has complete control over the communication channels between
+ them. This includes eavesdropping, message modification, insertion,
+
+
+
+Eronen, et al. Standards Track [Page 24]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+ man-in-the-middle and replay attacks. The details and related
+ security considerations are discussed in [BASE].
+
+ In addition to authentication provided by IPsec or TLS, authorization
+ is also required. Here, authorization means determining if a
+ Diameter message received from an authenticated Diameter peer should
+ be accepted (and not authorization of users requesting network access
+ from a NAS). In other words, when a Diameter server receives a
+ Diameter-EAP-Request, it has to decide if the client is authorized to
+ act as a NAS for the specific user, service type, and so on.
+ Correspondingly, when a NAS contacts a server to send a
+ Diameter-EAP-Request, it has to determine whether the server is
+ authorized to act as home server for the realm in question.
+
+ Authorization can involve local Access Control Lists (ACLs),
+ information contained in certificates, or some other means. See
+ [BASE] for more discussion and related security considerations. Note
+ that authorization issues are particularly relevant when Diameter
+ redirects are used. While redirection reduces the number of nodes
+ which have access to the contents of Diameter messages, a compromised
+ Diameter agent may not supply the right home server's address. If
+ the Diameter client is unable to tell whether this particular server
+ is authorized to act as the home server for this particular user, the
+ security of the communications rests on the redirect agent.
+
+ The hop-by-hop security mechanisms (IPsec and TLS) combined with
+ proper authorization provide good protection against "outside"
+ attackers, except for denial-of-service attacks. The remaining part
+ of this section deals with attacks by nodes that have been properly
+ authorized (to function as a NAS, Diameter agent, or Diameter
+ server), but abuse their authorization or have been compromised. In
+ general, it is not possible to completely protect against attacks by
+ compromised nodes, but this section offers advice on limiting the
+ extent of the damage.
+
+ Attacks involving eavesdropping or modification of EAP messages are
+ beyond the scope of these document. See [EAP] for discussion of
+ these security considerations (including method negotiation,
+ dictionary attacks, and privacy issues). While these attacks can be
+ carried out by an attacker between the client and the NAS,
+ compromised NASes and Diameter agents are naturally also in a good
+ position to modify and eavesdrop on the EAP messages.
+
+ Similarly, attacks involving the link layer protocol used between the
+ client and the NAS, such as PPP or IEEE 802.11, are beyond the scope
+ of this document.
+
+
+
+
+
+Eronen, et al. Standards Track [Page 25]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+8.2. AVP Editing
+
+ Diameter agents can modify, insert, and delete AVPs. Diameter agents
+ are usually meant to modify AVPs, and the protocol cannot distinguish
+ well-intentioned and malicious modifications (see [RFC2607] for more
+ discussion). Similarly, a compromised NAS or server can naturally
+ include a different set of AVPs than expected.
+
+ Therefore, the question is what an attacker who compromises an
+ authorized NAS, agent, or server can do using Diameter EAP messages.
+ Some of the consequences are rather obvious. For instance, a
+ Diameter agent can give access to unauthorized users by changing the
+ Result-Code to DIAMETER_SUCCESS. Other consequences are less obvious
+ and are discussed below and authentication method negotiation attacks
+ are discussed in the next section.
+
+ By including suitable AVPs in an AA-Answer/Diameter-EAP-Answer
+ messages, an attacker may be able (depending on implementation and
+ configuration details) to:
+
+ o Give unauthorized users access, or deny access to authorized users
+ (Result-Code).
+
+ o Give an attacker a login session to a host otherwise protected by
+ firewalls, or redirect an authorized user's login session to a
+ host controlled by the attacker (Login-Host).
+
+ o Route an authorized user's traffic through a host controlled by
+ the attacker (various tunneling AVPs).
+
+ o Redirect an authorized user's DNS requests to a malicious DNS
+ server (various vendor-specific AVPs).
+
+ o Modify routing tables at the NAS and thus redirect packets
+ destined for someone else (Framed-Route, Framed-Routing).
+
+ o Remove packet filters and other restrictions for user (Filter,
+ Callback, various vendor-specific AVPs).
+
+ o Cause the NAS to call some number, possibly an expensive toll
+ number controlled by the attacker (callback AVPs).
+
+ o Execute Command Line Interface (CLI) commands on the NAS (various
+ vendor-specific attributes).
+
+
+
+
+
+
+
+Eronen, et al. Standards Track [Page 26]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+ By modifying an AA-Request/Diameter-EAP-Request, an attacker may be
+ able to:
+
+ o Change NAS-Identifier/NAS-Port/Origin-Host (or another attribute)
+ so that a valid user appears to be accessing the network from a
+ different NAS than in reality.
+
+ o Modify Calling-Station-ID (either to hide the true value, gain
+ access, or frame someone else).
+
+ o Modify password change messages (some vendor-specific attributes).
+
+ o Modify usage information in accounting messages.
+
+ o Modify contents of Class and State AVPs.
+
+ Some of these attacks can be prevented if the NAS or server is
+ configured to not accept some particular AVPs, or accepts them only
+ from some nodes.
+
+8.3. Negotiation Attacks
+
+ This section deals with attacks where the NAS, any Diameter agents,
+ or Diameter server attempt to cause the authenticating user to choose
+ some authentication method other than EAP, such as PAP or CHAP
+ (negotiation attacks within EAP are discussed in [EAP], Section 7.8).
+
+ The vulnerability can be mitigated via implementation of a per-
+ connection policy by the authenticating peer, and a per-user policy
+ by the Diameter server. For the authenticating peer, the
+ authentication policy should be set on a per-connection basis.
+
+ With a per-connection policy, an authenticating peer will only
+ attempt to negotiate EAP for a session in which EAP support is
+ expected. As a result, it is presumed that an authenticating peer
+ selecting EAP requires that level of security. If it cannot be
+ provided, there is likely a misconfiguration, or the authenticating
+ peer may be contacting the wrong server. In this case, the
+ authenticating peer simply disconnects.
+
+ Similarly, with a per-user policy, the home server will not accept
+ authentication methods other than EAP for users for which EAP support
+ is expected.
+
+ For a NAS, it may not be possible to determine whether a peer is
+ required to authenticate with EAP until the peer's identity is known.
+ For example, for shared-uses NASes one reseller may implement EAP
+ while another does not. Alternatively, some peer might be
+
+
+
+Eronen, et al. Standards Track [Page 27]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+ authenticated locally by the NAS while other peers are authenticated
+ via Diameter. In such cases, if any peers of the NAS MUST do EAP,
+ then the NAS MUST attempt to negotiate EAP for every session. This
+ avoids forcing a peer to support more than one authentication type,
+ which could weaken security.
+
+8.4. Session Key Distribution
+
+ Since there are currently no end-to-end (NAS-to-home server) security
+ mechanisms specified for Diameter, any agents that process
+ Diameter-EAP-Answer messages can see the contents of the
+ EAP-Master-Session-Key AVP. For this reason, this specification
+ strongly recommends avoiding Diameter agents when they cannot be
+ trusted to keep the keys secret.
+
+ In environments where agents are present, several factors should be
+ considered when deciding whether the agents that are authorized (and
+ considered "trustworthy enough") to grant access to users and specify
+ various authorization and tunneling AVPs are also "trustworthy
+ enough" to handle the session keys. These factors include (but are
+ not limited to) the type of access provided (e.g., public Internet or
+ corporate internet), security level of the agents, and the
+ possibilities for attacking user's traffic after it has been
+ decrypted by the NAS.
+
+ Note that the keys communicated in Diameter messages are usually
+ short-term session keys (or short-term master keys that are used to
+ derive session keys). To actually cause any damage, those session
+ keys must end up with some malicious party that must be able to
+ eavesdrop, modify, or insert traffic between the user and the NAS
+ during the lifetime of those keys (for example, in 802.11i the
+ attacker must also eavesdrop the "four-way handshake").
+
+8.5. Privacy Issues
+
+ Diameter messages can contain AVPs that can be used to identify the
+ user (e.g., User-Name) and approximate location of the user (e.g.,
+ Origin-Host for WLAN access points, Calling-Station-Id for fixed
+ phone lines). Thus, any Diameter nodes that process the messages may
+ be able to determine the geographic location of users.
+
+ Note that in many cases, the user identity is also sent in clear
+ inside EAP-Payload AVPs, and it may be possible to eavesdrop this
+ between the user and the NAS.
+
+ This can be mitigated somewhat by using EAP methods that provide
+ identity protection (see [EAP], Section 7.3), and using Session-Id or
+ pseudonyms for accounting.
+
+
+
+Eronen, et al. Standards Track [Page 28]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+8.6. Note about EAP and Impersonation
+
+ If the EAP method used does not provide mutual authentication,
+ obviously anyone can impersonate the network to the user. Even when
+ EAP mutual authentication is used, it occurs between the user and the
+ Diameter home server. See [EAPKey] for an extensive discussion about
+ the details and their implications.
+
+ One issue is worth pointing out here. As described in [EAPKey], the
+ current EAP architecture does not allow the home server to restrict
+ what service parameters or identities (such as SSID or BSSID in
+ 802.11 wireless LANs) are advertised by the NAS to the client. That
+ is, a compromised NAS can change its BSSID or SSID, and thus appear
+ to offer a different service than intended. Even if these parameters
+ are included in Diameter-EAP-Answer messages, the NAS can tell
+ different values to the client.
+
+ Therefore, the NAS's possession of the session keys proves that the
+ user is talking to an authorized NAS, but a compromised NAS can lie
+ about its exact identity. See [EAPKey] for discussion on how
+ individual EAP methods can provide authentication of NAS service
+ parameters and identities.
+
+ Note that the usefulness of this authentication may be rather limited
+ in many environments. For instance, in wireless LANs the user does
+ not usually securely know the identity (such as BSSID) of the "right"
+ access point; it is simply picked from a beacon message that has the
+ correct SSID and good signal strength (something that is easy to
+ spoof). Thus, simply authenticating the identity may not allow the
+ user to distinguish the "right" access point from all others.
+
+9. Acknowledgements
+
+ This Diameter application relies heavily on earlier work on Diameter
+ NASREQ application [NASREQ] and RADIUS EAP support [RFC3579]. Much
+ of the material in this specification has been copied from these
+ documents.
+
+ The authors would also like to acknowledge the following people for
+ their contributions to this document: Bernard Aboba, Jari Arkko,
+ Julien Bournelle, Pat Calhoun, Henry Haverinen, John Loughney,
+ Yoshihiro Ohba, and Joseph Salowey.
+
+
+
+
+
+
+
+
+
+Eronen, et al. Standards Track [Page 29]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+10. References
+
+10.1. Normative References
+
+ [BASE] Calhoun, P., Loughney, J., Guttman, E., Zorn, G., and
+ J. Arkko, "Diameter Base Protocol", RFC 3588,
+ September 2003.
+
+ [EAP] Aboba, B., Blunk, L., Vollbrecht, J., Carlson, J., and
+ H. Levkowetz, "Extensible Authentication Protocol
+ (EAP)", RFC 3748, June 2004.
+
+ [NASREQ] Calhoun, P., Zorn, G., Spence, D., and D. Mitton,
+ "Diameter Network Access Server Application", RFC
+ 4005, August 2005.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+10.2. Informative References
+
+ [EAPKey] Aboba, B., Simon, D., Arkko, J., Eronen, P., and H.
+ Levkowetz, "Extensible Authentication Protocol (EAP)
+ Key Management Framework", Work in Progress, July
+ 2004.
+
+ [IEEE-802.1X] Institute of Electrical and Electronics Engineers,
+ "Local and Metropolitan Area Networks: Port-Based
+ Network Access Control", IEEE Standard 802.1X,
+ September 2001.
+
+ [IEEE-802.11i] Institute of Electrical and Electronics Engineers,
+ "IEEE Standard for Information technology -
+ Telecommunications and information exchange between
+ systems - Local and metropolitan area networks -
+ Specific requirements - Part 11: Wireless Medium
+ Access Control (MAC) and Physical Layer (PHY)
+ Specifications: Amendment 6: Medium Access Control
+ (MAC) Security Enhancements", IEEE Standard
+ 802.11i-2004, July 2004.
+
+ [IKEv2] Kaufman, C., Ed., "Internet Key Exchange (IKEv2)
+ Protocol", Work in Progress, June 2004.
+
+ [RFC1661] Simpson, W., "The Point-to-Point Protocol (PPP)",
+ STD 51, RFC 1661, July 1994.
+
+
+
+
+
+Eronen, et al. Standards Track [Page 30]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+ [RFC2548] Zorn, G., "Microsoft Vendor-specific RADIUS
+ Attributes", RFC 2548, March 1999.
+
+ [RFC2607] Aboba, B. and J. Vollbrecht, "Proxy Chaining and
+ Policy Implementation in Roaming", RFC 2607,
+ June 1999.
+
+ [RFC2865] Rigney, C., Willens, S., Rubens, A., and W. Simpson,
+ "Remote Authentication Dial In User Service (RADIUS)",
+ RFC 2865, June 2000.
+
+ [RFC3575] Aboba, B., "IANA Considerations for RADIUS (Remote
+ Authentication Dial In User Service)", RFC 3575,
+ July 2003.
+
+ [RFC3576] Chiba, M., Dommety, G., Eklund, M., Mitton, D., and B.
+ Aboba, "Dynamic Authorization Extensions to Remote
+ Authentication Dial In User Service (RADIUS)",
+ RFC 3576, July 2003.
+
+ [RFC3579] Aboba, B. and P. Calhoun, "RADIUS (Remote
+ Authentication Dial In User Service) Support For
+ Extensible Authentication Protocol (EAP)", RFC 3579,
+ September 2003.
+
+ [RFC3580] Congdon, P., Aboba, B., Smith, A., Zorn, G., and J.
+ Roese, "IEEE 802.1X Remote Authentication Dial In User
+ Service (RADIUS) Usage Guidelines", RFC 3580,
+ September 2003.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eronen, et al. Standards Track [Page 31]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+Authors' Addresses
+
+ Pasi Eronen (editor)
+ Nokia Research Center
+ P.O. Box 407
+ FIN-00045 Nokia Group
+ Finland
+
+
+
+ Tom Hiller
+ Lucent Technologies
+ 1960 Lucent Lane
+ Naperville, IL 60566
+ USA
+
+ Phone: +1 630 979 7673
+
+
+ Glen Zorn
+ Cisco Systems
+ 500 108th Avenue N.E., Suite 500
+ Bellevue, WA 98004
+ USA
+
+ Phone: +1 425 344 8113
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eronen, et al. Standards Track [Page 32]
+
+RFC 4072 Diameter EAP Application August 2005
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2005).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at ietf-
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+Eronen, et al. Standards Track [Page 33]
+
diff --git a/lib/diameter/doc/standard/rfc4740.txt b/lib/diameter/doc/standard/rfc4740.txt
new file mode 100644
index 0000000000..2154334b66
--- /dev/null
+++ b/lib/diameter/doc/standard/rfc4740.txt
@@ -0,0 +1,4035 @@
+
+
+
+
+
+
+Network Working Group M. Garcia-Martin, Ed.
+Request for Comments: 4740 Nokia
+Category: Standards Track M. Belinchon
+ M. Pallares-Lopez
+ C. Canales-Valenzuela
+ Ericsson
+ K. Tammi
+ Nokia
+ November 2006
+
+
+ Diameter Session Initiation Protocol (SIP) Application
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The IETF Trust (2006).
+
+Abstract
+
+ This document specifies the Diameter Session Initiation Protocol
+ (SIP) application. This is a Diameter application that allows a
+ Diameter client to request authentication and authorization
+ information. This application is designed to be used in conjunction
+ with SIP and provides a Diameter client co-located with a SIP server,
+ with the ability to request the authentication of users and
+ authorization of SIP resources usage from a Diameter server.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 1]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+Table of Contents
+
+ 1. Introduction ....................................................4
+ 2. Terminology .....................................................5
+ 3. Definitions .....................................................5
+ 4. Acronyms ........................................................6
+ 5. Applicability Statement .........................................6
+ 6. Overview of Operation ...........................................7
+ 6.1. General Architecture .......................................7
+ 6.2. Diameter Server Authenticates the User .....................9
+ 6.3. Delegating Final Authentication Check to the SIP Server ...12
+ 6.4. SIP Server Requests Authentication and Authorization ......15
+ 6.5. Locating the Recipient of the SIP Request .................16
+ 6.6. Update of the User Profile ................................17
+ 6.7. SIP Soft State Termination ................................18
+ 6.8. Diameter Server Discovery .................................19
+ 7. Advertising Application Support ................................21
+ 8. Diameter SIP Application Command Codes .........................22
+ 8.1. User-Authorization-Request (UAR) Command ..................22
+ 8.2. User-Authorization-Answer (UAA) Command ...................23
+ 8.3. Server-Assignment-Request (SAR) Command ...................27
+ 8.4. Server-Assignment-Answer (SAA) Command ....................29
+ 8.5. Location-Info-Request (LIR) Command .......................33
+ 8.6. Location-Info-Answer (LIA) Command ........................33
+ 8.7. Multimedia-Auth-Request (MAR) Command .....................35
+ 8.8. Multimedia-Auth-Answer (MAA) Command ......................36
+ 8.9. Registration-Termination-Request (RTR) Command ............39
+ 8.10. Registration-Termination-Answer (RTA) Command ............39
+ 8.11. Push-Profile-Request (PPR) Command .......................41
+ 8.12. Push-Profile-Answer (PPA) Command ........................42
+ 9. Diameter SIP Application AVPs ..................................44
+ 9.1. SIP-Accounting-Information AVP ............................46
+ 9.1.1. SIP-Accounting-Server-URI AVP ......................47
+ 9.1.2. SIP-Credit-Control-Server-URI AVP ..................47
+ 9.2. SIP-Server-URI AVP ........................................47
+ 9.3. SIP-Server-Capabilities AVP ...............................47
+ 9.3.1. SIP-Mandatory-Capability AVP .......................48
+ 9.3.2. SIP-Optional-Capability AVP ........................48
+ 9.4. SIP-Server-Assignment-Type AVP ............................48
+ 9.5. SIP-Auth-Data-Item AVP ....................................50
+ 9.5.1. SIP-Authentication-Scheme AVP ......................50
+ 9.5.2. SIP-Item-Number AVP ................................51
+ 9.5.3. SIP-Authenticate AVP ...............................51
+ 9.5.4. SIP-Authorization AVP ..............................52
+ 9.5.5. SIP-Authentication-Info AVP ........................52
+ 9.5.6. Digest AVPs ........................................53
+ 9.6. SIP-Number-Auth-Items AVP .................................55
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 2]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ 9.7. SIP-Deregistration-Reason AVP .............................55
+ 9.7.1. SIP-Reason-Code AVP ................................55
+ 9.7.2. SIP-Reason-Info AVP ................................56
+ 9.8. SIP-AOR AVP ...............................................56
+ 9.9. SIP-Visited-Network-Id AVP ................................56
+ 9.10. SIP-User-Authorization-Type AVP ..........................56
+ 9.11. SIP-Supported-User-Data-Type AVP .........................57
+ 9.12. SIP-User-Data AVP ........................................57
+ 9.12.1. SIP-User-Data-Type AVP ............................58
+ 9.12.2. SIP-User-Data-Contents AVP ........................58
+ 9.13. SIP-User-Data-Already-Available AVP ......................58
+ 9.14. SIP-Method AVP ...........................................59
+ 10. New Values for Existing AVPs ..................................59
+ 10.1. Extension to the Result-Code AVP Values ..................59
+ 10.1.1. Success Result-Code AVP Values ....................59
+ 10.1.2. Transient Failures Result-Code AVP Values .........60
+ 10.1.3. Permanent Failures Result-Code AVP Values .........60
+ 11. Authentication Details ........................................61
+ 12. Migration from RADIUS .........................................63
+ 12.1. Gateway from RADIUS Client to Diameter Server ............63
+ 12.2. Gateway from Diameter Client to RADIUS Server ............63
+ 12.3. Known Limitations ........................................64
+ 13. IANA Considerations ...........................................64
+ 13.1. Application Identifier ...................................64
+ 13.2. Command Codes ............................................65
+ 13.3. AVP Codes ................................................65
+ 13.4. Additional Values for the Result-Code AVP Value ..........65
+ 13.5. Creation of the SIP-Server-Assignment-Type
+ Section in the AAA .......................................66
+ 13.6. Creation of the SIP-Authentication-Scheme Section
+ in the AAA ...............................................66
+ 13.7. Creation of the SIP-Reason-Code Section in the
+ AAA Registry .............................................66
+ 13.8. Creation of the SIP-User-Authorization-Type
+ Section in the AAA .......................................66
+ 13.9. Creation of the SIP-User-Data-Already-Available
+ Section in the ...........................................66
+ 14. Security Considerations .......................................67
+ 14.1. Final Authentication Check in the Diameter
+ Client/SIP Server ........................................67
+ 15. Contributors ..................................................68
+ 16. Acknowledgements ..............................................68
+ 17. References ....................................................68
+ 17.1. Normative References .....................................68
+ 17.2. Informative References ...................................69
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 3]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+1. Introduction
+
+ This document specifies the Diameter Session Initiation Protocol
+ (SIP) application. This is a Diameter application that allows a
+ Diameter client to request authentication and authorization
+ information to a Diameter server for SIP-based IP multimedia services
+ (see [RFC3261] about SIP). Furthermore, this Diameter SIP
+ application provides the Diameter client with functions that go
+ beyond the typical authorization and authentication, such as the
+ ability to download or receive updated user profiles, or rudimentary
+ routing functions that can assist a SIP server in finding another SIP
+ server allocated to the user.
+
+ We assume that the SIP server (such as SIP proxy server, registrar,
+ redirect server, or alike) and the Diameter client are co-located in
+ the same node, so that the SIP server is able to receive and process
+ SIP requests and responses. In turn, the SIP server relies on the
+ Authentication, Authorization, and Accounting (AAA) infrastructure
+ for authenticating the SIP request and authorizing the usage of
+ particular SIP services.
+
+ This document provides Diameter procedures to implement certain
+ required functionality when SIP is the protocol chosen to initiate
+ and tear down multimedia sessions or when SIP is used for other
+ non-session-related applications. However, this document does not
+ mandate any particular mapping of SIP procedures to Diameter SIP
+ application procedures, nor does it mandate any particular sequence
+ of events between SIP and Diameter. This document provides useful
+ examples to show the interaction between SIP and the Diameter SIP
+ application in order to achieve the desired functionality.
+
+ This application does not require and is not related to other
+ authentication services provided by the Diameter Mobile IPv4
+ [RFC4004] or the Diameter Network Access Server [RFC4005]
+ applications.
+
+ This Diameter SIP application is loosely related to the Diameter
+ credit-control application [RFC4006]. Although both applications are
+ independent, the Diameter SIP application is able to supply the
+ addresses of credit-control servers that will be implementing the
+ Diameter credit-control application [RFC4006].
+
+ Section 5 discusses assumptions and configurations assumed by this
+ document.
+
+ Section 6 provides the reader with informative descriptions of the
+ Diameter SIP application commands and responses and with some
+ guidance about their linkage with SIP procedures.
+
+
+
+Garcia-Martin, et al. Standards Track [Page 4]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ Advertisement of this application is specified in Section 7.
+
+ Section 8 provides a normative description of all the new Diameter
+ commands defined by this specification.
+
+ This application extends the Result-Code Attribute-Value-Pair (AVP)
+ with some new values. Further information is described in
+ Section 10.
+
+ This application defines some new AVPs. All these AVPs are described
+ in Section 9.
+
+ Some extra information about authentication is provided in
+ Section 11.
+
+2. Terminology
+
+ In this document, the key words "MUST", "MUST NOT", "REQUIRED",
+ "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT
+ RECOMMENDED", "MAY", and "OPTIONAL" are to be interpreted as
+ described in BCP 14, RFC 2119 [RFC2119] and indicate requirement
+ levels for compliant implementations.
+
+3. Definitions
+
+ For the purpose of this document, the following terms and definitions
+ apply:
+
+ Node: an addressable device attached to a computer network that
+ implements SIP functionality, Diameter functionality, or a
+ combination of both.
+
+ For the purpose of this document, the following terms and definitions
+ given in RFC 3261 [RFC3261] Section 6, apply:
+
+ o Address-of-Record (AOR)
+ o Outbound proxy
+ o Proxy
+ o Registrar
+ o Server (SIP server)
+ o User Agent (UA)
+ o User Agent Client (UAC)
+ o User Agent Server (UAS)
+
+ For the purpose of this document, the following terms and definitions
+ given in RFC 3588 [RFC3588] Section 1.3, apply:
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 5]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ o Authorization
+ o Authentication
+ o Attribute-Value Pair (AVP)
+ o Diameter Client
+ o Diameter Server
+ o Home Realm
+ o Redirect Agent
+ o User
+
+4. Acronyms
+
+ AKA: Authentication and Key Agreement
+ LIR: Location-Info-Request
+ LIA: Location-Info-Answer
+ MAR: Multimedia-Auth-Request
+ MAA: Multimedia-Auth-Answer
+ PPR: Push-Profile-Request
+ PPA: Push-Profile-Answer
+ RTR: Registration-Termination-Request
+ RTA: Registration-Termination-Answer
+ SAR: Server-Assignment-Request
+ SAA: Server-Assignment-Answer
+ SL: Subscriber Locator
+ UAR: User-Authorization-Request
+ UAA: User-Authorization-Answer
+
+5. Applicability Statement
+
+ This document assumes a general architecture where a Home Realm is
+ composed of one or more nodes implementing Diameter or SIP functions.
+ Users are issuing SIP requests to access SIP resources. For each
+ particular user, the Home Realm needs to authenticate and authorize
+ the usage of those resources and/or the route to the appropriate
+ node. We assume that the database containing the user-related data
+ is located outside the SIP node that requires authorization. Data
+ belonging to different users may be stored in different nodes in the
+ Home Realm, but we assume that all the data related to a particular
+ user is stored in a single node.
+
+ Note: Central to the architecture is the fact that the user data
+ is stored in a single point in the network. This restriction does
+ not mandate a particular implementation, e.g., it is possible to
+ implement clusters of databases operating in mirror mode to
+ provide redundancy. The property required by this specification
+ is that the user data the Diameter server has access to is stored
+ safely in what is seen, from the external point of view, as a
+ single user database.
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 6]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ This document allows several configurations of the Home Realm. In
+ one configuration, a SIP server (proxy, registrar, etc.) is allocated
+ to a user for the purpose of triggering and executing services. The
+ allocation of the SIP server may be done dynamically, e.g., at the
+ time the user registers in the network. This configuration requires
+ a SIP server, typically located at the edge of the network, that is
+ able to allocate another SIP server for the user and that also
+ supports routing of SIP requests and responses towards that allocated
+ SIP server. Both SIP server nodes implement a Diameter client.
+
+ In another configuration, the address of a SIP outbound proxy is
+ configured (by means outside the scope of this specification) into
+ the SIP User Agent. The outbound Diameter client in the SIP outbound
+ proxy node authenticates the user, requests authorization for SIP
+ requests, and performs accounting activities.
+
+6. Overview of Operation
+
+ This section provides an informative description of how the Diameter
+ SIP application can be used together with SIP. This section is not
+ intended to mandate any specific usage of the Diameter SIP
+ application nor does it mandate a specific mapping between SIP and
+ Diameter messages. We provide a collection of examples that show how
+ the required AAA functionality can be achieved in conjunction with
+ SIP.
+
+6.1. General Architecture
+
+ The Diameter SIP application can be used in a SIP environment where
+ an interface to a AAA infrastructure is required to authenticate and
+ authorize the usage of SIP resources. This application provides
+ support for SIP User Agents and proxies that implement and use HTTP
+ Digest authentication [RFC2617], which is the authentication
+ mechanism mandated by SIP [RFC3261]. The application is extensible
+ and, if need arises, it can be extended to provide support for other
+ authentication mechanisms or extensions to HTTP Digest authentication
+ when they occur.
+
+ This application provides limited support for accounting services as
+ follows: the Diameter server is able to provide the addresses of
+ accounting severs to the Diameter client. Figure 1, below, shows a
+ general overview of the integration of the SIP architecture with the
+ AAA architecture.
+
+ According to Figure 1, there are one or more SIP User Agents (UAs)
+ that initiate or terminate SIP traffic through one or more SIP
+ servers. Both SIP servers implement a Diameter client that supports
+ the Diameter application described in this specification.
+
+
+
+Garcia-Martin, et al. Standards Track [Page 7]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ +--------+
+ UAR/UAA +--->|Diameter|<----+ PPR/PPA
+ LIR/LIA | | server | | MAR/MAA
+ | +--------+ | SAR/SAA
+ | | RTR/RTA
+ | |
+ v v
+ +------+ SIP +--------+ SIP +--------+ SIP +------+
+ | SIP |<--------->| SIP |<-------->| SIP |<--------->| SIP |
+ | UA | |server 1| |server 2| | UA |
+ +------+ +--------+ +--------+ +------+
+ ^ ^
+ UAR/UAA | |
+ LIR/LIA | | MAR/MAA
+ | +--------+ | SAR/SAA
+ +--->|Diameter|<----+
+ | SL |
+ +--------+
+
+ Figure 1: Architecture of the Diameter application for SIP
+
+ In Figure 1, it can be seen that SIP server 1 sends different
+ Diameter commands and receives different responses than those sent
+ and received by SIP server 2. This is because SIP server 1 in
+ Figure 1 is located at the edge of a network, and its main task is to
+ locate SIP server 2. SIP server 2 is requesting and receiving
+ authentication and authorization data from the Diameter server and is
+ not located at the edge of the network.
+
+ This Diameter application assumes that all the data pertaining to a
+ given user is stored in a single Diameter server. For redundancy
+ purposes, several Diameter servers can be configured in a redundancy
+ fashion, in which case all of them keep the data synchronized and
+ operate externally as a single Diameter server.
+
+ With respect to SIP server 1 in Figure 1, the Diameter SIP
+ application provides support for the existence of a farm of these
+ servers, typically configured through one or more DNS records that
+ point to several hosts (this is a typical configuration in common SIP
+ deployments). There is no requirement for these types of servers to
+ keep state related to the Diameter SIP application.
+
+ The Diameter SIP application provides support for a feature that
+ allows an administrative domain to provide a collection of SIP
+ servers 2 (as per Figure 1). Once the user registers for the first
+ time, one of these SIP servers is selected and all the SIP requests
+ related to the user are processed by the same SIP server.
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 8]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ The Diameter Subscriber Locator (SL) serves the purpose of locating
+ the Diameter server that contains the user-related data. Its
+ functionality is based on the Diameter redirect mechanism and is
+ further described in Section 6.8.
+
+ It should be noted that this document does not mandate any particular
+ SIP/AAA architecture. However, the Diameter SIP application provides
+ the functionality needed to accommodate all the different
+ architectures where SIP and Diameter are used.
+
+ The following subsections provide an informative overview of the
+ Diameter SIP application, its commands, and a possible interaction
+ with SIP signaling.
+
+6.2. Diameter Server Authenticates the User
+
+ This is the generic mechanism to authenticate users. In this
+ approach, we show an example of an administrative network where the
+ Diameter server is authenticating SIP user requests. This could be
+ the case of a medium-size network where the Diameter server is
+ keeping user records and authenticating SIP requests to perform a
+ certain transaction. We have chosen to show a SIP REGISTER request
+ in the example, but the SIP server could request authentication of
+ any other SIP request.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 9]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ +--------+ +--------+ +--------+
+ | SIP | |Diameter| | SIP |
+ |server 1| | server | |server 2|
+ +--------+ +--------+ +--------+
+ | | |
+ 1. SIP REGISTER | | |
+ -------------------->| 2. UAR | |
+ |------------------>| |
+ | 3. UAA | |
+ |<------------------| |
+ | 4. SIP REGISTER |
+ |-------------------------------------->|
+ | | 5. MAR |
+ | |<------------------|
+ | | 6. MAA |
+ | |------------------>|
+ | 7. SIP 401 (Unauthorized) |
+ 8. SIP 401 (Unauth.) |<--------------------------------------|
+ <--------------------| | |
+ 9. SIP REGISTER | | |
+ -------------------->| 10. UAR | |
+ |------------------>| |
+ | 11. UAA | |
+ |<------------------| |
+ | 12. SIP REGISTER |
+ |-------------------------------------->|
+ | | 13. MAR |
+ | |<------------------|
+ | | 14. MAA |
+ | |------------------>|
+ | 15. SIP 200 (OK) |
+ 16. SIP 200 (OK) |<--------------------------------------|
+ <--------------------| | |
+ | | 17. SAR |
+ | |<------------------|
+ | | 18. SAA |
+ | |------------------>|
+ | | |
+
+ Figure 2: Authentication performed in the Diameter server
+
+ According to Figure 2, a SIP User Agent Client (UAC) sends a SIP
+ REGISTER request (step 1) to SIP server 1, which receives the SIP
+ request. In Figure 2, we assume that this SIP server is located at
+ the edge of the administrative home domain. The Diameter client in
+ SIP server 1 contacts its Diameter server by sending a Diameter
+ User-Authorization-Request (UAR) message (step 2) to determine if
+ this user is allowed to receive service, and if so, request the
+
+
+
+Garcia-Martin, et al. Standards Track [Page 10]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ address of a local SIP server capable of handling this user. The
+ Diameter server answers with a Diameter User-Authorization-Answer
+ (UAA) message (step 3), which indicates a list of capabilities that
+ SIP server 1 may use to select an appropriate SIP server (SIP server
+ 2) and/or a SIP or SIPS URI pointing to SIP server 2.
+
+ SIP server 1 forwards the SIP REGISTER request (step 4) to an
+ appropriate SIP server (SIP server 2). Then the Diameter client in
+ SIP server 2 requests user authentication from the Diameter server by
+ sending a Diameter Multimedia-Auth-Request (MAR) message (step 5).
+ This request also serves to make the Diameter server aware of the SIP
+ or SIPS URI of SIP server 2, so as to return subsequent requests for
+ the same user to the same SIP server 2. The Diameter server responds
+ with a Diameter Multimedia-Auth-Answer (MAA) message (step 6) with
+ Result-Code AVP set to the value DIAMETER_MULTI_ROUND_AUTH. The
+ Diameter server also generates a nonce and includes a challenge in
+ the MAA message. SIP server 2 uses that challenge to map into the
+ WWW-Authenticate header in the SIP 401 (Unauthorized) response (step
+ 7), which is sent back to SIP server 1 and then to the SIP UAC (step
+ 8).
+
+ SIP server 1 receives a next SIP REGISTER request containing the user
+ credentials (step 9). Note that SIP server 1 does not need to keep a
+ state, and even more, there is no guarantee that the SIP request
+ arrives at the same SIP server 1; there could be a farm of SIP
+ servers 1 operating in redundant configuration. The Diameter client
+ in SIP server 1 contacts the Diameter server by sending a Diameter
+ UAR message (step 10) to determine the SIP server allocated to the
+ user. The Diameter server sends the SIP or SIPS URI of SIP server 2
+ in a Diameter UAA message (step 11).
+
+ Then SIP server 1 forwards the SIP REGISTER request to SIP server 2
+ (step 12). SIP server 2 extracts the credentials from the SIP
+ REGISTER request. The Diameter client in SIP server 2 sends those
+ credentials in a Diameter MAR message (step 13) to the Diameter
+ server. At this point, the Diameter server is able to authenticate
+ the user, and upon success, returns a Diameter MAA message (step 14)
+ with the AVP Result-Code set to the value DIAMETER_SUCCESS.
+
+ Then SIP server 2 generates a SIP 200 (OK) response (step 15), which
+ is forwarded to SIP server 1 and eventually to the SIP UAC (step 16).
+
+ If the Diameter client in SIP server 2 is interested in downloading
+ the user profile information or is required to store the address of
+ the SIP server in the Diameter server, then the Diameter client sends
+ a Diameter SAR message (step 17) to the Diameter server. The
+ Diameter server replies with a Diameter SAA message (step 18) that
+ contains the requested user profile information and the
+
+
+
+Garcia-Martin, et al. Standards Track [Page 11]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ acknowledgement of the SIP server address storage. These actions are
+ needed when the SIP server has to retrieve a user profile used to
+ provide services to the served user, or when the SIP server keeps a
+ state for the user, so the Diameter server needs to store the SIP
+ server's address.
+
+6.3. Delegating Final Authentication Check to the SIP Server
+
+ An operator with a large base of installed SIP servers may wish to
+ minimize the number of round-trips between the Diameter client and
+ the Diameter server. We provide support for a mechanism where the
+ Diameter server delegates the final authentication check to the SIP
+ server, thereby saving a round-trip. Section 14.1 discusses the
+ security considerations of this scenario.
+
+ It must noted that this scenario is not applicable when the Diameter
+ server is configured to use a session MD5 (MD5-sess) algorithm,
+ because the Diameter server requires the client nonce to compute the
+ H(A1) before sending it to the Diameter client. However, the client
+ nonce might not be available at that time.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 12]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ +--------+ +--------+ +--------+
+ | SIP | |Diameter| | SIP |
+ |server 1| | server | |server 2|
+ +--------+ +--------+ +--------+
+ | | |
+ 1. SIP REGISTER | | |
+ -------------------->| 2. UAR | |
+ |------------------>| |
+ | 3. UAA | |
+ |<------------------| |
+ | 4. SIP REGISTER |
+ |-------------------------------------->|
+ | | 5. MAR |
+ | |<------------------|
+ | | 6. MAA |
+ | |------------------>|
+ | 7. SIP 401 (Unauthorized) |
+ 8. SIP 401 (Unauth.) |<--------------------------------------|
+ <--------------------| | |
+ 9. SIP REGISTER | | |
+ -------------------->| 10. UAR | |
+ |------------------>| |
+ | 11. UAA | |
+ |<------------------| |
+ | 12. SIP REGISTER |
+ |-------------------------------------->|
+ | | 13. SAR |
+ | |<------------------|
+ | | 14. SAA |
+ | |------------------>|
+ | 15. SIP 200 (OK) |
+ 16. SIP 200 (OK) |<--------------------------------------|
+ <--------------------| | |
+ | | |
+
+ Figure 3: Delegation of authentication to the SIP server
+
+ Figure 3 shows an example where a SIP server is dynamically allocated
+ to serve a SIP User Agent with the support of the Diameter server.
+ This may be the case of certain architectures, such as that of the
+ 3rd Generation Partnership Project (3GPP) IP Multimedia Core Network
+ Subsystem.
+
+ A first SIP server receives a SIP REGISTER request (step 1) whose
+ target is the home network domain. In Figure 3, we assume that this
+ SIP server is located at the edge of the administrative home domain.
+ The Diameter client in this SIP server requests authorization from
+ the Diameter server to proceed with the registration, by sending a
+
+
+
+Garcia-Martin, et al. Standards Track [Page 13]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ Diameter User-Authorization-Request (UAR) message (step 2). The
+ message includes, among other Attribute-Value-Pairs (AVPs), the SIP
+ Address-Of-Record (AOR) that is included in the SIP REGISTER request.
+ The Diameter server verifies the SIP AOR and, if it is a valid
+ defined user in the home network, authorizes the registration to
+ proceed. The Diameter server responds with a Diameter
+ User-Authorization-Answer (UAA) message (step 3), which informs the
+ Diameter client/SIP server about the result of the user
+ authorization. In case of a successful authorization, the Diameter
+ UAA message indicates the address of a local SIP server (SIP server 2
+ in Figure 3) and/or a list of capabilities that SIP server 1 may use
+ to select an appropriate SIP server 2.
+
+ When the authorization is successful, SIP server 1 forwards the SIP
+ REGISTER request (step 4) to the appropriate SIP server (SIP server
+ 2). The Diameter client in SIP server 2 requests authentication
+ parameters by sending a Diameter Multimedia-Auth-Request (MAR)
+ message (step 5) to the Diameter server. This request also makes the
+ Diameter server aware of the SIP or SIPS URI of SIP server 2, so as
+ to return subsequent requests of the same user to the same SIP server
+ 2. The Diameter server responds with a Diameter
+ Multimedia-Auth-Answer (MAA) message (step 6), which includes a nonce
+ and all the rest of the parameters necessary for the designated
+ authentication algorithm associated with the user. Among others, the
+ MAA message includes a Digest-HA1 AVP that contains H(A1) (as defined
+ in RFC 2617 [RFC2617]), and that allows the Diameter client to
+ calculate the expected response. Then the Diameter client can
+ compare this expected response with the response to the challenge
+ sent from the SIP UA. The absence of the Digest-HA1 AVP in MAA
+ indicates that authentication and authorization take place in the
+ Diameter server, as per the scenario described in Section 6.2.
+
+ SIP server 2 creates a SIP 401 (Unauthorized) SIP response (step 7)
+ based on the challenge included in the MAA message, including the
+ authentication material needed by the SIP User Agent Client (UAC) to
+ include the appropriate credentials. SIP server 1 forwards the SIP
+ response to the SIP UAC (step 8).
+
+ The SIP server 1 receives the next SIP REGISTER request containing
+ the user credentials (step 9). Because SIP server 1 does not need to
+ keep a state (and there is no guarantee that the SIP request arrives
+ to the same SIP server 1), the Diameter client in SIP server 1
+ contacts the Diameter server again by sending a Diameter UAR message
+ (step 10) to determine the SIP server allocated to the user. The
+ Diameter server sends the SIP or SIPS URI of SIP server 2 in a
+ Diameter UAA message (step 11).
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 14]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ SIP server 1 forwards the SIP REGISTER request to SIP server 2 (step
+ 12). SIP server 2 validates the credentials by comparing the
+ response supplied by the SIP UA with the expected response calculated
+ by the SIP server 2 (based on the H(A1) received from the Diameter
+ server).
+
+ If the credentials are valid, SIP server 2 sends a Diameter
+ Server-Assignment-Request (SAR) message (step 13) requesting the
+ Diameter server to confirm the completion of the authentication
+ procedure and to confirm the SIP or SIPS URI of the SIP server that
+ is currently serving the user. The Diameter SAR message also serves
+ the purpose of requesting that the Diameter server send the user
+ profile to the SIP server. The Diameter server responds with a
+ Diameter Server-Assignment-Answer (SAA) message (step 14). If the
+ Result-Code AVP value does not inform SIP Server 2 of an error, the
+ SAA message can include zero or more SIP-User-Data AVPs containing
+ the information that SIP server 2 needs in order to provide a service
+ to the user.
+
+ SIP server 2 generates a SIP 200 (OK) response (step 15), which is
+ forwarded to SIP server 1 and eventually to the SIP UAC (step 16).
+
+6.4. SIP Server Requests Authentication and Authorization
+
+ Figure 4 depicts a typical scenario where a stateless SIP proxy
+ requests authentication information and authorization to a Diameter
+ server, for the purpose of providing SIP routing services to a SIP
+ User Agent. The SIP proxy server may be configured as an outbound
+ SIP proxy, so that all the requests initiated by the SIP UA traverse
+ the SIP proxy.
+
+ According to Figure 4, a SIP User Agent sends a SIP request to its
+ outbound SIP proxy server. In this case, the message is a SIP INVITE
+ request (see step 1), but it could be any other SIP request. We
+ assume that this SIP request does not contain any credentials at this
+ time. The outbound SIP proxy server needs to authenticate and
+ authorize the proxy services offered to the user. The Diameter
+ client in the SIP server sends a Multimedia-Auth-Request (MAR)
+ message (step 2). The Diameter server generates a nonce and sends a
+ Multimedia-Auth-Answer (MAA) message (step 3) that includes the nonce
+ and the rest of the data necessary for the SIP server to challenge
+ the user, typically with HTTP Digest Authentication indicated in the
+ MAA message. This data enables the SIP server to create a SIP 407
+ (Proxy Authentication Required) response (step 4) that contains a
+ challenge. The SIP UA creates a new INVITE request (step 5) that
+ contains the credentials. The Diameter client in the SIP server
+ sends the credentials to the Diameter server in a new Diameter MAR
+ message (step 6). The Diameter server validates the credentials and
+
+
+
+Garcia-Martin, et al. Standards Track [Page 15]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ authorize the SIP transaction in a Diameter MAA message (step 7).
+ The SIP server forwards the SIP INVITE request to its destination
+ (step 8) as per regular SIP procedures. Eventually, the session
+ setup is confirmed with a SIP 200 (OK) response (step 9) that is
+ forwarded to the SIP UA (step 10). The session setup is complete.
+
+ +--------+ +--------+
+ |Diameter| | SIP |
+ | server | | server |
+ +--------+ +--------+
+ | |
+ | |
+ 1. SIP INVITE |
+ ----------------------------------->|
+ | 2. MAR |
+ |<------------------|
+ | 3. MAA |
+ |------------------>|
+ | |
+ 4. SIP 407 (Proxy |
+ Authentication Required) |
+ <-----------------------------------|
+ | |
+ 5. SIP INVITE |
+ ----------------------------------->|
+ | 6. MAR |
+ |<------------------|
+ | 7. MAA |
+ |------------------>| 8. SIP INVITE
+ | |---------------->
+ | | 9. SIP 200 (OK)
+ 10. SIP 200 (OK) |<----------------
+ <-----------------------------------|
+ | |
+
+ Figure 4: SIP server requests authorization
+
+6.5. Locating the Recipient of the SIP Request
+
+ Figure 5 shows the scenario where SIP server 1 may be configured as a
+ SIP edge proxy server, processing SIP traffic at the edge of a
+ network. SIP server 1 receives a SIP INVITE request (step 1). SIP
+ server 1 needs to find the address of SIP server 2, which is serving
+ the recipient of the SIP request. The Diameter client in SIP server
+ 1 sends a Diameter Location-Info-Request (LIR) message (step 2) to
+ the Diameter server. The Diameter server responds with a Diameter
+ Location-Info-Answer (LIA) message (step 3) that contains the SIP or
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 16]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ SIPS URI of SIP server 2. SIP server 1 then forwards the SIP INVITE
+ to SIP server 2 (step 4). SIP server 2 eventually forwards the SIP
+ INVITE to the appropriate UAS (step 5).
+
+ +--------+ +--------+ +--------+
+ | SIP | |Diameter| | SIP |
+ |server 1| | server | |server 2|
+ +--------+ +--------+ +--------+
+ | | |
+ 1. SIP INVITE | | |
+ -------------->| 2. LIR | |
+ |---------------->| |
+ | 3. LIA | |
+ |<----------------| |
+ | 4. SIP INVITE |
+ |--------------------------------->|
+ | | | 5. SIP INVITE
+ | | |-------------->
+ | | |
+ | | |
+
+ Figure 5: Locating the SIP server of the recipient
+
+ Although the example shows the connection between a SIP INVITE
+ request and the Diameter LIR message, any SIP request other than
+ REGISTER (such as SUBSCRIBE, OPTIONS, etc.) would trigger the same
+ Diameter message. (A SIP REGISTER request will trigger a Diameter
+ UAR message, as indicated in Figure 2 and Figure 3.)
+
+ The scenario described in this section is also applicable in case an
+ outbound SIP server is not interested in authenticating the user, but
+ is required to locate a further SIP server to route the outbound SIP
+ requests. In this case, the outbound SIP server is mapped to SIP
+ server 1 as shown in Figure 5.
+
+6.6. Update of the User Profile
+
+ The Diameter SIP application provides a mechanism for a Diameter
+ server to asynchronously download a user profile to a SIP server
+ whenever there is an update of such user profile. It must be noted
+ that the Diameter server also attaches the user profile to the
+ Diameter Server-Assignment-Answer (SAA) message. This is valid for
+ most of the daily situations; however, the administrator may decide
+ to update or modify the user profile for a particular user, due to,
+ e.g., new services made available to the user. This may involve
+ mechanisms outside the scope of this specification, such as human
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 17]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ intervention, in the Diameter server. In this situation, the
+ Diameter server is able to push the new user profile into the SIP
+ server allocated to the user.
+
+ The scenario is illustrated in Figure 6. When the user profile
+ changes, the Diameter server sends a Diameter Push-Profile-Request
+ (PPR) message (step 1) to the Diameter client in the SIP server
+ allocated to that user (SIP server 2 in the examples). The Diameter
+ PPR message contains one or more SIP-User-Data AVPs, a User-Name AVP
+ and zero or more SIP-AOR AVPs. The Diameter client in SIP server 2
+ acknowledges the Diameter PPR message by sending a Diameter
+ Push-Profile-Answer (PPA) message (step 2) to the Diameter server.
+
+ +--------+ +--------+
+ |Diameter| | SIP |
+ | server | |server 2|
+ +--------+ +--------+
+ | |
+ | 1. PPR |
+ |------------------>|
+ | |
+ | 2. PPA |
+ |<------------------|
+ | |
+
+ Figure 6: Diameter server pushes an update of the user profile
+
+6.7. SIP Soft State Termination
+
+ SIP can create soft states in SIP nodes based on events such as SIP
+ registrations or SIP event subscriptions. These states are
+ periodically refreshed, and cease to exist if they are not refreshed.
+ Additionally, an administrative action can be taken to terminate a
+ SIP soft state, or the SIP UA can explicitly terminate a SIP soft
+ state.
+
+ The Diameter base protocol offers a mechanism to create and delete
+ states in Diameter nodes. These states are called Diameter user
+ sessions. The Diameter server decides whether to use a Diameter user
+ session as a mechanism to map to a SIP soft state. If the Diameter
+ server decides to use Diameter user sessions, the termination of a
+ Diameter user session implies the termination of the corresponding
+ SIP soft state (e.g., registration, event subscription), and vice
+ versa. If the Diameter server does not use Diameter user sessions,
+ this Diameter SIP application offers specific commands to manage the
+ SIP soft states. Implementations compliant with this specification
+ MUST support both mechanisms of session management.
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 18]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ We provide support for both Diameter client- and Diameter
+ server-initiated session termination. Depending on whether Diameter
+ sessions are used, termination of a SIP soft state can be achieved by
+ one of the following methods:
+
+ o When the Diameter client (SIP proxy) wants to terminate the SIP
+ soft state and Diameter user sessions are not maintained (i.e.,
+ the Auth-Session-State AVP has been previously set to
+ NO_STATE_MAINTAINED), the Diameter client MUST send a
+ Server-Assignment-Request (SAR) message with the
+ SIP-Server-Assignment-Type AVP (Section 9.4) set to any of the
+ deregistration values: TIMEOUT_DEREGISTRATION,
+ USER_DEREGISTRATION, TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME,
+ USER_DEREGISTRATION_STORE_SERVER_NAME,
+ ADMINISTRATIVE_DEREGISTRATION, DEREGISTRATION_TOO_MUCH_DATA.
+
+ o When the Diameter client (SIP proxy) wants to terminate the SIP
+ soft state and Diameter user sessions are maintained (i.e., the
+ Auth-Session-State AVP has been previously set to
+ STATE_MAINTAINED), the Diameter client MUST send a Session-
+ Termination-Request (STR) message as per regular procedures
+ according to RFC 3588 [RFC3588].
+
+ o When the Diameter server wants to terminate the SIP soft state and
+ Diameter user sessions are not maintained (i.e., the
+ Auth-Session-State AVP has been previously set to
+ NO_STATE_MAINTAINED), the Diameter server MUST send a
+ Registration-Termination-Request (RTR) message (see Section 8.9).
+
+ o When the Diameter server wants to terminate the SIP soft state and
+ Diameter user sessions are maintained (i.e., the
+ Auth-Session-State AVP has been previously set to
+ STATE_MAINTAINED), the Diameter server MUST send an
+ Abort-Session-Request (ASR) message as per regular procedures
+ according to RFC 3588 [RFC3588].
+
+6.8. Diameter Server Discovery
+
+ The basic architecture assumption of this document is that all the
+ data related to a user is stored in a unique Diameter server.
+ Contrary to general opinion, this does not create a single point of
+ failure. It is assumed that Diameter servers are configured in a
+ redundant fashion in an attempt to mitigate the
+ single-point-of-failure problem.
+
+ In large networks, where the number of users may be significantly
+ high, there might be a need to scale the number of Diameter servers.
+ All the data associated with a user is still stored in one Diameter
+
+
+
+Garcia-Martin, et al. Standards Track [Page 19]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ server (typically, operating in a redundant configuration), but the
+ data associated with different users may reside in different Diameter
+ servers.
+
+ Although this configuration scales well, it introduces a new problem,
+ namely: given the user's SIP AOR as an input, how to determine which
+ of various Diameter servers is storing the data for that particular
+ SIP AOR. We solve this problem with inspiration from the Diameter
+ redirection mechanism specified in RFC 3588 [RFC3588]. We include in
+ the architecture a new Diameter node that, for the purpose of this
+ document, is known as Diameter Subscriber Locator (SL). The Diameter
+ SL contains a database or routing tables that map SIP AORs to
+ Diameter server URIs. A particular Diameter server URI points to the
+ actual Diameter server that stores all the data related to a
+ particular SIP AOR, and in consequence, to the user who owns the SIP
+ AOR. The Diameter SL acts in a similar way to a Diameter Redirect
+ Agent, dispatching Diameter requests (e.g., providing the redirection
+ URI in the answer). The Diameter SL can redirect all the request
+ pertaining to a user by setting the Redirect-Host-Usage AVP with a
+ value ALL_USER, as specified in RFC 3588 [RFC3588].
+
+ The Diameter SL can be replicated in different nodes along the
+ network, for the purpose of building scalability and redundancy. The
+ database or routing tables have to be consistent across all these
+ different Diameter SLs, so that equal Diameter requests will produce
+ equal Diameter answers, no matter which Diameter SL processes the
+ request.
+
+ +--------+ +--------+ +--------+ +--------+
+ | SIP | |Diameter| |Diameter| | SIP |
+ |server 1| |SL red. | |server 1| |server 2|
+ +--------+ +--------+ +--------+ +--------+
+ | | | |
+ 1. SIP INVITE| | | |
+ ------------>| 2. LIR | | |
+ |---------->| | |
+ | 3. LIA | | |
+ |<----------| | |
+ | 4. LIR | |
+ |---------------------->| |
+ | 5. LIA | |
+ |<----------------------| |
+ | 6. SIP INVITE | |
+ |----------------------------------->| 7. SIP INVITE
+ | | | | ------------->
+ | | | |
+
+ Figure 7: Locating a Diameter server. SL redirecting requests
+
+
+
+Garcia-Martin, et al. Standards Track [Page 20]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ Figure 7 shows an example of operation of a Diameter SL acting in
+ redirect mode. SIP server 1 receives an INVITE request (step 1)
+ addressed (in the SIP Request-URI) to a user for which the Diameter
+ client in SIP server 1 does not possess routing information. In
+ other words, the Diameter client in SIP server 1 does not know the
+ URI of the Diameter server 1. The Diameter client sends a Diameter
+ LIR message (step 2) to any of the Diameter SLs configured in the
+ network. The address of those SLs is assumed to be pre-provisioned
+ in the Diameter client. The Diameter SL, based on the contents of
+ the SIP-AOR AVP and its own routing tables, determines the Diameter
+ server that stores the information allocated to such user. Then it
+ builds a Diameter LIA message (step 3) that includes a Result-Code
+ AVP set to DIAMETER_REDIRECT_INDICATION and one Redirect-Host AVP,
+ whose value is set to the URI of the Diameter server that stores the
+ information related to such user. Then the Diameter client in SIP
+ server 1 builds a new LIR message (step 4) addressed to the Diameter
+ server received in the Redirect-Host AVP. The rest of the procedure
+ is completed as described in previous sections.
+
+7. Advertising Application Support
+
+ Diameter implementations conforming to this specification MUST
+ advertise its support by including an Auth-Application-Id AVP in the
+ Capabilities-Exchange-Request (CER) and Capabilities-Exchange-Answer
+ (CEA) commands, according to the Diameter base protocol, RFC 3588
+ [RFC3588]. This Auth-Application-Id AVP MUST be set to the value of
+ this Diameter SIP application (Section 13.1 indicates the actual
+ value allocated by IANA).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 21]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+8. Diameter SIP Application Command Codes
+
+ All the Diameter implementations conforming to this specification
+ MUST implement and support the list of Diameter commands listed in
+ Table 1.
+
+ +-------------------------------------+-------+------+--------------+
+ | Command Name | Abbr. | Code | Reference |
+ +-------------------------------------+-------+------+--------------+
+ | User-Authorization-Request | UAR | 283 | Section 8.1 |
+ | User-Authorization-Answer | UAA | 283 | Section 8.2 |
+ | Server-Assignment-Request | SAR | 284 | Section 8.3 |
+ | Server-Assignment-Answer | SAA | 284 | Section 8.4 |
+ | Location-Info-Request | LIR | 285 | Section 8.5 |
+ | Location-Info-Answer | LIA | 285 | Section 8.6 |
+ | Multimedia-Auth-Request | MAR | 286 | Section 8.7 |
+ | Multimedia-Auth-Answer | MAA | 286 | Section 8.8 |
+ | Registration-Termination-Request | RTR | 287 | Section 8.9 |
+ | Registration-Termination-Answer | RTA | 287 | Section 8.10 |
+ | Push-Profile-Request | PPR | 288 | Section 8.11 |
+ | Push-Profile-Answer | PPA | 288 | Section 8.12 |
+ +-------------------------------------+-------+------+--------------+
+
+ Table 1: Defined command codes
+
+ Sections defining commands contain the Message Format for that
+ particular command. The Message Formats included in this document
+ are defined as per Section 3.2 of RFC 3588 [RFC3588].
+
+8.1. User-Authorization-Request (UAR) Command
+
+ The User-Authorization-Request (UAR) is indicated by the Command-Code
+ set to 283 and the Command Flags' 'R' bit set. The Diameter client
+ in a SIP server sends this command to the Diameter server to request
+ authorization for the SIP User Agent to route a SIP REGISTER request.
+ Because the SIP REGISTER request implicitly carries a permission to
+ bind an AOR to a contact address, the Diameter client uses the
+ Diameter UAR as a first authorization request towards the Diameter
+ server to authorize the registration. For instance, the Diameter
+ server can verify that the AOR is a legitimate user of the realm.
+
+ The Diameter client in the SIP server requests authorization for one
+ of the possible values defined in the SIP-User-Authorization-Type AVP
+ (Section 9.10).
+
+ The user name used for authentication of the user is conveyed in a
+ User-Name AVP (defined in the Diameter base protocol, RFC 3588
+ [RFC3588]). The location of the authentication user name in the SIP
+
+
+
+Garcia-Martin, et al. Standards Track [Page 22]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ REGISTER request varies depending on the authentication mechanism.
+ When the authentication mechanism is HTTP Digest as defined in RFC
+ 2617 [RFC2617], the authentication user name is found in the
+ "username" directive of the SIP Authorization header field value.
+ This Diameter SIP application only provides support for HTTP Digest
+ authentication in SIP; other authentication mechanisms are not
+ currently supported.
+
+ The SIP or SIPS URI to be registered is conveyed in the SIP-AOR AVP
+ (Section 9.8). Typically this SIP or SIPS URI is found in the To
+ header field value of the SIP REGISTER request that triggered the
+ Diameter UAR message.
+
+ The SIP-Visited-Network-Id AVP indicates the network that is
+ providing SIP services (e.g., SIP proxy functionality or any other
+ kind of services) to the SIP User Agent.
+
+ The Message Format of the UAR command is as follows:
+
+ <UAR> ::= < Diameter Header: 283, REQ, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { SIP-AOR }
+ [ Destination-Host ]
+ [ User-Name ]
+ [ SIP-Visited-Network-Id ]
+ [ SIP-User-Authorization-Type ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+8.2. User-Authorization-Answer (UAA) Command
+
+ The User-Authorization-Answer (UAA) is indicated by the Command-Code
+ set to 283 and the Command Flags' 'R' bit cleared. The Diameter
+ server sends this command in response to a previously received
+ Diameter User-Authorization-Request (UAR) command. The Diameter
+ server indicates the result of the requested registration
+ authorization. Additionally, the Diameter server may indicate a
+ collection of SIP capabilities that assists the Diameter client to
+ select a SIP proxy to the AOR under registration.
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 23]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ In addition to the values already defined in RFC 3588 [RFC3588], the
+ Result-Code AVP may contain one of the values defined in
+ Section 10.1.
+
+ Whenever the Diameter server fails to process the Diameter UAR
+ message, it MUST stop processing and return the relevant error in the
+ Diameter UAA message. When there is success in the process, the
+ Diameter server MUST set the code to DIAMETER_SUCCESS in the Diameter
+ UAA message.
+
+ If the Diameter server requires a User-Name AVP value to process the
+ Diameter UAR request, but the Diameter UAR message did not contain a
+ User-Name AVP value, the Diameter server MUST set the Result-Code AVP
+ value to DIAMETER_USER_NAME_REQUIRED (see Section 10.1.2) and return
+ it in a Diameter UAA message. Upon reception of this Diameter UAA
+ message with the Result-Code AVP value set to
+ DIAMETER_USER_NAME_REQUIRED, the SIP server typically requests
+ authentication by sending a SIP 401 (Unauthorized) or SIP 407 (Proxy
+ Authentication Required) response back to the originator.
+
+ When the authorization procedure succeeds, the Diameter server
+ constructs a User-Authorization-Answer (UAA) message that MUST
+ include (1) the address of the SIP server already assigned to the
+ user name, (2) the capabilities needed by the SIP server (Diameter
+ client) to select another SIP server for the user, or (3) a
+ combination of the previous two options.
+
+ If the Diameter server is already aware of a SIP server allocated to
+ the user, the Diameter UAA message contains the address of that SIP
+ server.
+
+ The Diameter UAA message contains the capabilities required by a SIP
+ server to trigger and execute services. It is required that these
+ capabilities are present in the Diameter UAA message due to the
+ possibility that the Diameter client (in the SIP server) allocates a
+ different SIP server to trigger and execute services for that
+ particular user.
+
+ If a User-Name AVP is present in the Diameter UAR message, then the
+ Diameter server MUST verify the existence of the user in the realm,
+ i.e., the User-Name AVP value is a valid user within that realm. If
+ the Diameter server does not recognize the user name received in the
+ User-Name AVP, the Diameter server MUST build a Diameter User-
+ Authorization-Answer (UAA) message and MUST set the Result-Code AVP
+ to DIAMETER_ERROR_USER_UNKNOWN.
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 24]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ If a User-Name AVP is present in the Diameter UAR message, then the
+ Diameter server MUST authorize that User-Name AVP value is able to
+ register the SIP or SIPS URI included in the SIP-AOR AVP. If this
+ authorization fails, the Diameter server must set the Result-Code AVP
+ to DIAMETER_ERROR_IDENTITIES_DONT_MATCH and send it in a Diameter
+ User-Authorization-Answer (UAA) message.
+
+ Note: Correlation between User-Name and SIP-AOR AVP values is
+ required in order to avoid registration of a SIP-AOR allocated to
+ another user.
+
+ If there is a SIP-Visited-Network-Id AVP in the Diameter UAR message,
+ and the SIP-User-Authorization-Type AVP value received in the
+ Diameter UAR message is set to REGISTRATION or REGISTRATION&
+ CAPABILITIES, then the Diameter server SHOULD verify whether the user
+ is allowed to roam into the network specified in the
+ SIP-Visited-Network-Id AVP in the Diameter UAR message. If the user
+ is not allowed to roam into that network, the Diameter AAA server
+ MUST set the Result-Code AVP value in the Diameter UAA message to
+ DIAMETER_ERROR_ROAMING_NOT_ALLOWED.
+
+ If the SIP-User-Authorization-Type AVP value received in the Diameter
+ UAR message is set to REGISTRATION or REGISTRATION&CAPABILITIES, then
+ the Diameter server SHOULD verify whether the SIP-AOR AVP value is
+ authorized to register in the Home Realm. Where the SIP AOR is not
+ authorized to register in the Home Realm, the Diameter server MUST
+ set the Result-Code AVP to DIAMETER_AUTHORIZATION_REJECTED and send
+ it in a Diameter UAA message.
+
+ When the SIP-User-Authorization-Type AVP is not present in the
+ Diameter UAR message, or when it is present and its value is set to
+ REGISTRATION, then:
+
+ o If the Diameter server is not aware of any previous registration
+ of the user name (including registrations of other SIP AORs
+ allocated to the same user name), then the Diameter server does
+ not know of any SIP server allocated to the user. In this case,
+ the Diameter server MUST set the Result-Code AVP value to
+ DIAMETER_FIRST_REGISTRATION in the Diameter UAA message, and the
+ Diameter server SHOULD include the required SIP server
+ capabilities in the SIP-Server-Capabilities AVP value in the
+ Diameter UAA message. The SIP-Server-Capabilities AVP assists the
+ Diameter client (SIP server) to select an appropriate SIP server
+ for the user, according to the required capabilities.
+
+ o In some cases, the Diameter server is aware of a previously
+ assigned SIP server for the same or different SIP AORs allocated
+ to the same user name. In these cases, re-assignment of a new SIP
+
+
+
+Garcia-Martin, et al. Standards Track [Page 25]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ server may or may not be needed, depending on the capabilities of
+ the SIP server. The Diameter server MUST always include the
+ allocated SIP server URI in the SIP-Server-URI AVP of the UAA
+ message. If the Diameter server does not return the SIP
+ capabilities, the Diameter server MUST set the Result-Code AVP in
+ the Diameter UAA message to DIAMETER_SUBSEQUENT_REGISTRATION.
+ Otherwise (i.e., if the Diameter server includes a
+ SIP-Server-Capabilities AVP), then the Diameter server MUST set
+ the Result-Code AVP in the Diameter UAA message to
+ DIAMETER_SERVER_SELECTION. Then the Diameter client determines,
+ based on the received information, whether it needs to select a
+ new SIP server.
+
+ When the SIP-User-Authorization-Type AVP value received in the
+ Diameter UAR message is set to REGISTRATION&CAPABILITIES, then
+ Diameter Server MUST return the list of capabilities in the
+ SIP-Server-Capabilities AVP value of the Diameter UAA message, it
+ MUST set the Result-Code to DIAMETER_SUCCESS, and it MUST NOT return
+ a SIP-Server-URI AVP. The SIP-Server-Capabilities AVP enables the
+ SIP server (Diameter client) to select another appropriate SIP server
+ for invoking and executing services for the user, depending on the
+ required capabilities. The Diameter server MAY leave the list of
+ capabilities empty to indicate that any SIP server can be selected.
+
+ When the SIP-User-Authorization-Type AVP value received in the
+ Diameter UAR message is set to DEREGISTRATION, then:
+
+ o If the Diameter server is aware of a SIP server assigned to the
+ SIP AOR under deregistration, the Diameter server MUST set the
+ Result-Code AVP to DIAMETER_SUCCESS and MUST set the
+ SIP-Server-URI AVP value to the known SIP server, and return them
+ in the Diameter UAA message.
+
+ o If the Diameter server is not aware of a SIP server assigned to
+ the SIP AOR under deregistration, then the Diameter server MUST
+ set the Result-Code AVP in the Diameter UAA message to
+ DIAMETER_ERROR_IDENTITY_NOT_REGISTERED.
+
+ The Message Format of the UAA command is as follows:
+
+ <UAA> ::= < Diameter Header: 283, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ SIP-Server-URI ]
+
+
+
+Garcia-Martin, et al. Standards Track [Page 26]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ [ SIP-Server-Capabilities ]
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+8.3. Server-Assignment-Request (SAR) Command
+
+ The Server-Assignment-Request (SAR) command is indicated by the
+ Command-Code set to 284 and the Command Flags' 'R' bit set. The
+ Diameter client in a SIP server sends this command to the Diameter
+ server to indicate the completion of the authentication process and
+ to request that the Diameter server store the URI of the SIP server
+ that is currently serving the user. The main functions of the
+ Diameter SAR command are to inform the Diameter server of the URI of
+ the SIP server allocated to the user, and to store or clear it from
+ the Diameter server. Additionally, the Diameter client can request
+ to download the user profile or part of it.
+
+ During the registration procedure, a SIP server becomes assigned to
+ the user. The Diameter client in the assigned SIP server MUST
+ include its own URI in the SIP-Server-URI AVP of the
+ Server-Assignment-Request (SAR) Diameter message and send it to the
+ Diameter server. The Diameter server then becomes aware of the
+ allocation of the SIP server to the user name and the server's URI.
+
+ The Diameter client in the SIP server MAY send a Diameter SAR message
+ because of other reasons. These reasons are identified in the
+ SIP-Server-Assignment-Type AVP (Section 9.4) value. For instance, a
+ Diameter client in a SIP server may contact the Diameter server to
+ request deregistration of a user, to inform the Diameter server of an
+ authentication failure, or just to download the user profile. For a
+ complete description of all the SIP-Server-Assignment-Type AVP
+ values, see Section 9.4.
+
+ Typically the reception of a SIP REGISTER request in a SIP server
+ will trigger the Diameter client in the SIP server to send the
+ Diameter SAR message. However, if a SIP server is receiving other
+ SIP request, such as INVITE, and the SIP server does not have the
+ user profile, the Diameter client in the SIP server may send the
+ Diameter SAR message to the Diameter server in order to download the
+ user profile and make the Diameter server aware of the SIP server
+ assigned to the user.
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 27]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ The user profile is an important piece of information that dictates
+ the behavior of the SIP server when triggering or providing services
+ for the user. Typically the user profile is divided into:
+
+ o Services to be rendered to the user when the user is registered
+ and initiates a SIP request.
+
+ o Services to be rendered to the user when the user is registered
+ and a SIP request destined to that user arrives to the SIP proxy.
+
+ o Services to be rendered to the user when the user is not
+ registered and a SIP request destined to that user arrives to the
+ SIP proxy.
+
+ The SIP-Server-Assignment-Type AVP indicates the reason why the
+ Diameter client (SIP server) contacted the Diameter server. If the
+ Diameter client sets the SIP-Server-Assignment-Type AVP value to
+ REGISTRATION, RE_REGISTRATION, UNREGISTERED_USER, NO_ASSIGNMENT,
+ AUTHENTICATION_FAILURE or AUTHENTICATION_TIMEOUT, the Diameter client
+ MUST include exactly one SIP-AOR AVP in the Diameter SAR message.
+
+ The SAR message MAY contain zero or more SIP-Supported-User-Data-Type
+ AVPs. Each of them contains a type of user data understood by the
+ SIP server. This allows the Diameter client to provide an indication
+ to the Diameter server of the different format of user data
+ understood by the SIP server. The Diameter server uses this
+ information to select one or more SIP-User-Data AVPs that will be
+ included in the SAA message.
+
+ The Message Format of the SAR command is as follows:
+
+ <SAR> ::= < Diameter Header: 284, REQ, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { SIP-Server-Assignment-Type }
+ { SIP-User-Data-Already-Available }
+ [ Destination-Host ]
+ [ User-Name ]
+ [ SIP-Server-URI ]
+ * [ SIP-Supported-User-Data-Type ]
+ * [ SIP-AOR ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+
+
+Garcia-Martin, et al. Standards Track [Page 28]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+8.4. Server-Assignment-Answer (SAA) Command
+
+ The Server-Assignment-Answer (SAA) is indicated by the Command-Code
+ set to 284 and the Command Flags' 'R' bit cleared. The Diameter
+ server sends this command in response to a previously received
+ Diameter Server-Assignment-Request (SAR) command. The response may
+ include the user profile or part of it, if requested.
+
+ In addition to the values already defined in RFC 3588 [RFC3588], the
+ Result-Code AVP may contain one of the values defined in
+ Section 10.1.
+
+ The Result-Code AVP value in the Diameter SAA message may indicate a
+ success or an error in the execution of the Diameter SAR command. If
+ Result-Code AVP value in the Diameter SAA message does not contain an
+ error code, the SAA message MAY include one or more SIP-User-Data
+ AVPs that typically contain the profile of the user, indicating
+ services that the SIP server can provide to that user.
+
+ The Diameter server MAY include one or more
+ SIP-Supported-User-Data-Type AVPs, each one identifying a type of
+ user data format supported in the Diameter server. If there is not a
+ common supported user data type between the Diameter client and the
+ Diameter server, the Diameter server SHOULD declare its list of
+ supported user data types by including one or more
+ SIP-Supported-User-Data-Type AVPs in a Diameter SAA message. This
+ indication is merely for debugging reasons, since there is not a
+ fallback mechanism that allows the Diameter client to retrieve the
+ profile in a supported format.
+
+ If the Diameter server requires a User-Name AVP value to process the
+ Diameter SAR request, but the Diameter SAR message did not contain a
+ User-Name AVP value, the Diameter server MUST set the Result-Code AVP
+ value to DIAMETER_USER_NAME_REQUIRED (see Section 10.1.2) and return
+ it in a Diameter SAA message. Upon reception of this Diameter SAA
+ message with the Result-Code AVP value set to
+ DIAMETER_USER_NAME_REQUIRED, the SIP server typically requests
+ authentication by generating a SIP 401 (Unauthorized) or SIP 407
+ (Proxy Authentication Required) response back to the originator.
+
+ If the User-Name AVP is included in the Diameter SAR message, upon
+ reception of the Diameter SAR message, the Diameter server MUST
+ verify the existence of the user in the realm, i.e., the User-Name
+ AVP value is a valid user within that realm. If the Diameter server
+ does not recognize the user name received in the User-Name AVP, the
+ Diameter server MUST build a Diameter Server-Assignment-Answer (SAA)
+ message and MUST set the Result-Code AVP to
+ DIAMETER_ERROR_USER_UNKNOWN.
+
+
+
+Garcia-Martin, et al. Standards Track [Page 29]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ Then the Diameter server MUST authorize that User-Name AVP value is a
+ valid authentication name for the SIP or SIPS URI included in the
+ SIP-AOR AVP of the Diameter SAR message. If this authorization
+ fails, the Diameter server must set the Result-Code AVP to
+ DIAMETER_ERROR_IDENTITIES_DONT_MATCH and send it in a Diameter
+ Server-Assignment-Answer (SAA) message.
+
+ After successful execution of the Diameter SAR command, the Diameter
+ server MUST clear the "authentication pending" flag and SHOULD move
+ the temporarily stored SIP server URI to permanent storage.
+
+ The actions of the Diameter server upon reception of the Diameter SAR
+ message depend on the value of the SIP-Server-Assignment-Type:
+
+ o If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+ message is set to REGISTRATION or RE_REGISTRATION, the Diameter
+ server SHOULD verify that there is only one SIP-AOR AVP.
+ Otherwise, the Diameter server MUST answer with a Diameter SAA
+ message with the Result-Code AVP value set to
+ DIAMETER_AVP_OCCURS_TOO_MANY_TIMES and MUST NOT include any
+ SIP-User-Data AVP. If there is only one SIP-AOR AVP and if the
+ SIP-User-Data-Already-Available AVP value is set to
+ USER_DATA_NOT_AVAILABLE, then the Diameter server SHOULD include
+ one or more user profile data with the SIP or SIPS URI (SIP-AOR
+ AVP) and all other SIP identities associated with that AVP in the
+ SIP-User-Data AVP value of the Diameter SAA message. On selecting
+ the type of user data, the Diameter server SHOULD take into
+ account the supported formats at the SIP server
+ (SIP-Supported-User-Data-Type AVP in the SAR message) and the
+ local policy. Additionally, the Diameter server MUST set the
+ Result-Code AVP value to DIAMETER_SUCCESS in the Diameter SAA
+ message. The Diameter server considers the SIP AOR authenticated
+ and registered.
+
+ o If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+ message is set to UNREGISTERED_USER, then the Diameter server MUST
+ store the SIP server address included in the SIP-Server-URI AVP
+ value. The Diameter server will return the SIP server address in
+ Diameter Location-Info-Answer (LIA) messages. If the
+ SIP-User-Data-Already-Available AVP value is set to
+ USER_DATA_NOT_AVAILABLE, then the Diameter server SHOULD include
+ one or more user profile data associated with the SIP or SIPS URI
+ (SIP-AOR AVP) and associated identities in the SIP-User-Data AVP
+ value of the Diameter SAA message. On selecting the type of user
+ data, the Diameter server SHOULD take into account the supported
+ formats at the SIP server (SIP-Supported-User-Data-Type AVP in the
+ SAR message) and the local policy. The Diameter server MUST set
+ the Result-Code AVP value to DIAMETER_SUCCESS. The Diameter
+
+
+
+Garcia-Martin, et al. Standards Track [Page 30]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ server considers the SIP AOR UNREGISTERED, but with a SIP server
+ allocated to trigger and provide services for unregistered users.
+ Note that in case of UNREGISTERED_USER (SIP-Server-Assignment-Type
+ AVP), the Diameter server MUST verify that there is only one
+ SIP-AOR AVP. Otherwise, the Diameter server MUST answer the
+ Diameter SAR message with a Diameter SAA message, and it MUST set
+ the Result-Code AVP value to DIAMETER_AVP_OCCURS_TOO_MANY_TIMES
+ and MUST NOT include any SIP-User-Data AVP.
+ If the User-Name AVP was not present in the Diameter SAR message
+ and the SIP-AOR is not known for the Diameter server, the Diameter
+ server MUST NOT include a User-Name AVP in the Diameter SAA
+ message and MUST set the Result-Code AVP value to
+ DIAMETER_ERROR_USER_UNKNOWN.
+
+ o If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+ message is set to TIMEOUT_DEREGISTRATION, USER_DEREGISTRATION,
+ DEREGISTRATION_TOO_MUCH_DATA, or ADMINISTRATIVE_DEREGISTRATION,
+ the Diameter server MUST clear the SIP server address associated
+ with all SIP AORs indicated in each of the SIP-AOR AVP values
+ included in the Diameter SAR message. The Diameter server
+ considers all of these SIP AORs as not registered. The Diameter
+ server MUST set the Result-Code AVP value to DIAMETER_SUCCESS in
+ the Diameter SAA message.
+
+ o If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+ message is set to TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME or
+ USER_DEREGISTRATION_STORE_SERVER_NAME, the Diameter server MAY
+ keep the SIP server address associated with the SIP AORs included
+ in the SIP-AOR AVP values of the Diameter SAR message, even though
+ the SIP AORs become unregistered. This feature allows a SIP
+ server to request that the Diameter server remain an assigned SIP
+ server for those SIP AORs (SIP-AOR AVP values) allocated to the
+ same user name, and avoid SIP server assignment. The Diameter
+ server MUST consider all these SIP AORs as not registered. If the
+ Diameter server honors the request of the Diameter client (SIP
+ server) to remain as an allocated SIP server, then the Diameter
+ server MUST keep the SIP server assigned to those SIP AORs
+ allocated to the username and MUST set the Result-Code AVP value
+ to DIAMETER_SUCCESS in the Diameter SAA message. Otherwise, when
+ the Diameter server does not honor the request of the Diameter
+ client (SIP server) to remain as an allocated SIP server, the
+ Diameter server MUST clear the SIP server name assigned to those
+ SIP AORs and it MUST set the Result-Code AVP value to
+ DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED in the Diameter SAA
+ message.
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 31]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ o If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+ message is set to NO_ASSIGNMENT, the Diameter server SHOULD first
+ verify that the SIP-Server-URI AVP value in the Diameter SAR
+ message is the same URI as the one assigned to the SIP-AOR AVP
+ value. If they differ, then the Diameter server MUST set the
+ Result-Code AVP value to DIAMETER_UNABLE_TO_COMPLY in the Diameter
+ SAA message. Otherwise, if the SIP-User-Data-Already-Available
+ AVP value is set to USER_DATA_NOT_AVAILABLE, then the Diameter
+ server SHOULD include the user profile data with the SIP or SIPS
+ URI (SIP-AOR AVP) and all other SIP identities associated with
+ that AVP in the SIP-User-Data AVP value of the Diameter SAA
+ message. On selecting the type of user data, the Diameter server
+ SHOULD take into account the supported formats at the SIP server
+ (SIP-Supported-User-Data-Type AVP in the SAR message) and the
+ local policy.
+
+ o If the SIP-Server-Assignment-Type AVP value in the Diameter SAR
+ message is set to AUTHENTICATION_FAILURE or
+ AUTHENTICATION_TIMEOUT, the Diameter server MUST verify that there
+ is exactly one SIP-AOR AVP in the Diameter SAR message. If the
+ number of occurrences of the SIP-AOR AVP is not exactly one, the
+ Diameter server MUST set the Result-Code AVP value to
+ DIAMETER_AVP_OCCURS_TOO_MANY_TIMES in the Diameter SAA message,
+ and SHOULD not take further actions. If there is exactly one
+ SIP-AOR AVP in the Diameter SAR message, the Diameter server MUST
+ clear the address of the SIP server assigned to the SIP AOR
+ allocated to the user name, and the Diameter server MUST set the
+ Result-Code AVP value to DIAMETER_SUCCESS in the Diameter SAA
+ message. The Diameter server MUST consider the SIP AOR as not
+ registered.
+
+ The Message Format of the SAA command is as follows:
+
+ <SAA> ::= < Diameter Header: 284, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ * [ SIP-User-Data ]
+ [ SIP-Accounting-Information ]
+ * [ SIP-Supported-User-Data-Type ]
+ [ User-Name ]
+ [ Auth-Grace-Period ]
+ [ Authorization-Lifetime ]
+ [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+
+
+
+Garcia-Martin, et al. Standards Track [Page 32]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+8.5. Location-Info-Request (LIR) Command
+
+ The Location-Info-Request (LIR) is indicated by the Command-Code set
+ to 285 and the Command Flags' 'R' bit set. The Diameter client in a
+ SIP server sends this command to the Diameter server to request
+ routing information, e.g., the URI of the SIP server assigned to the
+ SIP-AOR AVP value allocated to the users.
+
+ The Message Format of the LIR command is as follows:
+
+ <LIR> ::= < Diameter Header: 285, REQ, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { SIP-AOR }
+ [ Destination-Host ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+8.6. Location-Info-Answer (LIA) Command
+
+ The Location-Info-Answer (LIA) is indicated by the Command-Code set
+ to 285 and the Command Flags' 'R' bit cleared. The Diameter server
+ sends this command in response to a previously received Diameter
+ Location-Info-Request (LIR) command.
+
+ In addition to the values already defined in RFC 3588 [RFC3588], the
+ Result-Code AVP may contain one of the values defined in
+ Section 10.1. When the Diameter server finds an error in processing
+ the Diameter LIR message, the Diameter server MUST stop the process
+ of the message and answer with a Diameter LIA message that includes
+ the appropriate error code in the Result-Code AVP value. When there
+ is no error, the Diameter server MUST set the Result-Code AVP value
+ to DIAMETER_SUCCESS in the Diameter LIA message.
+
+ One of the errors that the Diameter server may find is that the
+ SIP-AOR AVP value is not a valid user in the realm. In such cases,
+ the Diameter server MUST set the Result-Code AVP value to
+ DIAMETER_ERROR_USER_UNKNOWN and return it in a Diameter LIA message.
+
+
+
+Garcia-Martin, et al. Standards Track [Page 33]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ If the Diameter server cannot process the Diameter LIR command, e.g.,
+ due to a database error, the Diameter server MUST set the Result-Code
+ AVP value to DIAMETER_UNABLE_TO_COMPLY and return it in a Diameter
+ LIA message. The Diameter server MUST NOT include any SIP-Server-URI
+ or SIP-Server-Capabilities AVP in the Diameter LIA message.
+
+ The Diameter server may or may not be aware of a SIP server assigned
+ to the SIP-AOR AVP value included in the Diameter LIR message. If
+ the Diameter server is aware of a SIP server allocated to that
+ particular user, the Diameter server MUST include the URI of such SIP
+ server in the SIP-Server-URI AVP and return it in a Diameter LIA
+ message. This is typically the situation when the user is either
+ registered, or unregistered but a SIP server is still assigned to the
+ user.
+
+ When the Diameter server is not aware of a SIP server allocated to
+ the user (typically the case when the user unregistered), the
+ Result-Code AVP value in the Diameter LIA message depends on whether
+ the Diameter server is aware that the user has services defined for
+ unregistered users:
+
+ o Those users who have services defined for unregistered users may
+ require the allocation of a SIP server to trigger and perhaps
+ execute those services. Therefore, when the Diameter server is
+ not aware of an assigned SIP server, but the user has services
+ defined for unregistered users, the Diameter server MUST set the
+ Result-Code AVP value to DIAMETER_UNREGISTERED_SERVICE and return
+ it in a Diameter LIA message. The Diameter server MAY also
+ include a SIP-Server-Capabilities AVP to facilitate the SIP server
+ (Diameter client) with the selection of an appropriate SIP server
+ with the required capabilities. Absence of the SIP-Server-
+ Capabilities AVP indicates to the SIP server (Diameter client)
+ that any SIP server is suitable to be allocated for the user.
+
+ o Those users who do not have service defined for unregistered users
+ do not require further processing. The Diameter server MUST set
+ the Result-Code AVP value to
+ DIAMETER_ERROR_IDENTITY_NOT_REGISTERED and return it to the
+ Diameter client in a Diameter LIA message. The SIP server
+ (Diameter client) may return the appropriate SIP response (e.g.,
+ 480 (Temporarily unavailable)) to the original SIP request.
+
+ The Message Format of the LIA command is as follows:
+
+ <LIA> ::= < Diameter Header: 285, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+
+
+
+Garcia-Martin, et al. Standards Track [Page 34]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ [ SIP-Server-URI ]
+ [ SIP-Server-Capabilities ]
+ [ Auth-Grace-Period ]
+ [ Authorization-Lifetime ]
+ [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+8.7. Multimedia-Auth-Request (MAR) Command
+
+ The Multimedia-Auth-Request (MAR) command is indicated by the
+ Command-Code set to 286 and the Command Flags' 'R' bit set. The
+ Diameter client in a SIP server sends this command to the Diameter
+ server to request that the Diameter server authenticate and authorize
+ a user attempt to use some SIP service (in this context, SIP service
+ can be something as simple as a SIP subscription or using the proxy
+ services for a SIP request).
+
+ The MAR command may also register the SIP server's own URI to the
+ Diameter server, so that future LIR/LIA messages can return this URI.
+ If the SIP server is acting as a SIP registrar (see examples in
+ Sections 6.2 and 6.3), its Diameter client MUST include a SIP-
+ Server-URI AVP in the MAR command. In any other cases (see example
+ in Section 6.4), its Diameter client MUST NOT include a SIP-Server-
+ URI AVP in the MAR command.
+
+ The SIP-Method AVP MUST include the SIP method name of the SIP
+ request that triggered this Diameter MAR message. The Diameter
+ server can use this AVP to authorize some SIP requests depending on
+ the method.
+
+ The Diameter MAR message MUST include a SIP-AOR AVP. The SIP-AOR AVP
+ indicates the target of the SIP request. The value of the AVP is
+ extracted from different places in SIP request, depending on the
+ semantics of the SIP request. For SIP REGISTER messages the SIP-AOR
+ AVP value indicates the intended public user identity under
+ registration, and it is the SIP or SIPS URI populated in the To
+ header field value (addr-spec as per RFC 3261 [RFC3261]) of the SIP
+ REGISTER request. For other types of SIP requests, such as INVITE,
+ SUBSCRIBE, MESSAGE, etc., the SIP-AOR AVP value indicates the
+ intended destination of the request. This is typically populated in
+ the Request-URI of the SIP request. Extracting the SIP-AOR AVP value
+
+
+
+Garcia-Martin, et al. Standards Track [Page 35]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ from the proper SIP header field is the Diameter client's
+ responsibility. Extensions to SIP (new SIP methods or new semantics)
+ may require the SIP-AOR to be extracted from other parts of the
+ request.
+
+ If the SIP request includes some sort of authentication information,
+ the Diameter client MUST include the user name, extracted from the
+ authentication information of the SIP request, in the User-Name AVP
+ value.
+
+ The Message Format of the MAR command is as follows:
+
+ <MAR> ::= < Diameter Header: 286, REQ, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { SIP-AOR }
+ { SIP-Method }
+ [ Destination-Host ]
+ [ User-Name ]
+ [ SIP-Server-URI ]
+ [ SIP-Number-Auth-Items ]
+ [ SIP-Auth-Data-Item ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+8.8. Multimedia-Auth-Answer (MAA) Command
+
+ The Multimedia-Auth-Answer (MAA) is indicated by the Command-Code set
+ to 286 and the Command Flags' 'R' bit cleared. The Diameter server
+ sends this command in response to a previously received Diameter
+ Multimedia-Auth-Request (MAR) command.
+
+ In addition to the values already defined in RFC 3588 [RFC3588], the
+ Result-Code AVP may contain one of the values defined in
+ Section 10.1.
+
+ If the Diameter server requires a User-Name AVP value to process the
+ Diameter MAR request, but the Diameter MAR message did not contain a
+ User-Name AVP value, the Diameter server MUST set the Result-Code AVP
+ value to DIAMETER_USER_NAME_REQUIRED (see Section 10.1.2) and return
+ it in a Diameter MAA message. The Diameter server MAY include a
+ SIP-Number-Auth-Items AVP and one or more SIP-Auth-Data-Item AVPs
+ with authentication information (e.g., a challenge). Upon reception
+
+
+
+Garcia-Martin, et al. Standards Track [Page 36]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ of this Diameter MAA message with the Result-Code AVP value set to
+ DIAMETER_USER_NAME_REQUIRED, the SIP server typically requests
+ authentication by generating a SIP 401 (Unauthorized) or SIP 407
+ (Proxy Authentication Required) response back to the originator.
+
+ If the User-Name AVP is present in the Diameter MAR message, the
+ Diameter server MUST verify the existence of the user in the realm,
+ i.e., the User-Name AVP value is a valid user within that realm. If
+ the Diameter server does not recognize the user name received in the
+ User-Name AVP, the Diameter server MUST build a Diameter
+ Multimedia-Auth-Answer (MAA) message and MUST set the Result-Code AVP
+ to DIAMETER_ERROR_USER_UNKNOWN.
+
+ If the SIP-Methods AVP value of the Diameter MAR message is set to
+ REGISTER and a User-Name AVP is present, then the Diameter server
+ MUST authorize that User-Name AVP value is able to use the URI
+ included in the SIP-AOR AVP. If this authorization fails, the
+ Diameter server must set the Result-Code AVP to
+ DIAMETER_ERROR_IDENTITIES_DONT_MATCH and send it in a Diameter
+ Multimedia-Auth-Answer (MAA) message.
+
+ Note: Correlation between User-Name and SIP-AOR AVP values is only
+ required for SIP REGISTER request, to prevent a user from
+ registering a SIP-AOR allocated to another user. In other types
+ of SIP requests (e.g., INVITE), the SIP-AOR indicates the intended
+ destination of the request, rather than the originator of it.
+
+ The Diameter server MUST verify whether the authentication scheme
+ (SIP-Authentication-Scheme AVP value) indicated in the grouped
+ SIP-Auth-Data-Item AVP is supported or not. If that authentication
+ scheme is not supported, then the Diameter server MUST set the
+ Result-Code AVP to DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED and send
+ it in a Diameter Multimedia-Auth-Answer (MAA) message.
+
+ If the SIP-Number-Auth-Items AVP is present in the Diameter MAR
+ message, it indicates the number of authentication data items that
+ the Diameter client is requesting. It is RECOMMENDED that the
+ Diameter server, when building the Diameter MAA message, includes a
+ number of SIP-Auth-Data-Item AVPs that are a subset of the
+ authentication data items requested by the Diameter client in the
+ SIP-Number-Auth-Items AVP value of the Diameter MAR message.
+
+ If the SIP-Server-URI AVP is present in the Diameter MAR message,
+ then the Diameter server MUST compare the stored SIP server (assigned
+ to the user) with the SIP-Server-URI AVP value (received in the
+ Diameter MAR message). If they don't match, the Diameter server MUST
+ temporarily save the newly received SIP server assigned to the user,
+ and MUST set an "authentication pending" flag for the user. If they
+
+
+
+Garcia-Martin, et al. Standards Track [Page 37]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ match, the Diameter server shall clear the "authentication pending"
+ flag for the user.
+
+ In any other situation, if there is a success in processing the
+ Diameter MAR command and the Diameter server stored the
+ SIP-Server-URI, the Diameter server MUST set the Result-Code AVP
+ value to DIAMETER_SUCCESS and return it in a Diameter MAA message.
+
+ If there is a success in processing the Diameter MAR command, but the
+ Diameter server does not store the SIP-Server-URI because the AVP was
+ not present in the Diameter MAR command, then the Diameter server
+ MUST set the Result-Code AVP value to either:
+
+ 1. DIAMETER_SUCCESS_AUTH_SENT_SERVER_NOT_STORED, if the Diameter
+ server is sending authentication credentials to create a
+ challenge.
+
+ 2. DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED, if the Diameter server
+ successfully authenticated the user and authorized the SIP server
+ to proceed with the SIP request.
+
+ Otherwise, the Diameter server MUST set the Result-Code AVP value to
+ DIAMETER_UNABLE_TO_COMPLY, and it MUST NOT include any
+ SIP-Auth-Data-Item AVP.
+
+ The Message Format of the MAA command is as follows:
+
+ <MAA> ::= < Diameter Header: 286, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ [ SIP-AOR ]
+ [ SIP-Number-Auth-Items ]
+ * [ SIP-Auth-Data-Item ]
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 38]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+8.9. Registration-Termination-Request (RTR) Command
+
+ The Registration-Termination-Request (RTR) command is indicated by
+ the Command-Code set to 287 and the Command Flags' 'R' bit set. The
+ Diameter server sends this command to the Diameter client in a SIP
+ server to indicate to the SIP server that one or more SIP AORs have
+ to be deregistered. The command allows an operator to
+ administratively cancel the registration of a user from a centralized
+ Diameter server.
+
+ The Diameter server has the capability to initiate the deregistration
+ of a user and inform the SIP server by means of the Diameter RTR
+ command. The Diameter server can decide whether only one SIP AOR is
+ going to be deregistered, a list of SIP AORs, or all the SIP AORs
+ allocated to the user.
+
+ The absence of a SIP-AOR AVP in the Diameter RTR message indicates
+ that all the SIP AORs allocated to the user identified by the
+ User-Name AVP are being deregistered.
+
+ The Diameter server MUST include a SIP-Deregistration-Reason AVP
+ value to indicate the reason for the deregistration.
+
+ The Message Format of the RTR command is as follows:
+
+ <RTR> ::= < Diameter Header: 287, REQ, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Host }
+ { SIP-Deregistration-Reason }
+ [ Destination-Realm ]
+ [ User-Name ]
+ * [ SIP-AOR ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+8.10. Registration-Termination-Answer (RTA) Command
+
+ The Registration-Termination-Answer (RTA) is indicated by the
+ Command-Code set to 287 and the Command Flags' 'R' bit cleared. The
+ Diameter client sends this command in response to a previously
+ received Diameter Registration-Termination-Request (RTR) command.
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 39]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ In addition to the values already defined in RFC 3588 [RFC3588], the
+ Result-Code AVP may contain one of the values defined in
+ Section 10.1.
+
+ If the SIP server (Diameter client) requires a User-Name AVP value to
+ process the Diameter RTR request, but the Diameter RTR message did
+ not contain a User-Name AVP value, the Diameter client MUST set the
+ Result-Code AVP value to DIAMETER_USER_NAME_REQUIRED (see Section
+ 10.1.2) and return it in a Diameter RTA message.
+
+ The SIP server (Diameter client) applies the administrative
+ deregistration to each of the URIs included in each of the SIP-AOR
+ AVP values, or, if there is no SIP-AOR AVP present in the Diameter
+ RTR request, to all the URIs allocated to the User-Name AVP value.
+
+ The value of the SIP-Deregistration-Reason AVP in the Diameter RTR
+ command has an effect on the actions performed at the SIP server
+ (Diameter client):
+
+ o If the value is set to PERMANENT_TERMINATION, then the user has
+ terminated his/her registration to the realm. If informing the
+ interested parties (e.g., subscribers to the "reg" event
+ [RFC3680]) about the administrative deregistration is supported
+ through SIP procedures, the SIP server (Diameter client) will do
+ so. The Diameter Client in the SIP Server SHOULD NOT request a
+ new user registration. The SIP server clears the registration
+ state of the deregistered AORs.
+
+ o If the value is set to NEW_SIP_SERVER_ASSIGNED, the Diameter
+ server informs the SIP server (Diameter client) that a new SIP
+ server has been allocated to the user, due to some reason. The
+ SIP server, if supported through SIP procedures, will inform the
+ interested parties (e.g., subscribers to the "reg" event
+ [RFC3680]) about the administrative deregistration at this SIP
+ server. The Diameter client in the SIP server SHOULD NOT request
+ a new user registration. The SIP server clears the registration
+ state of the deregistered SIP AORs.
+
+ o If the value is set to SIP_SERVER_CHANGE, the Diameter server
+ informs the SIP server (Diameter client) that a new SIP server has
+ to be allocated to the user, e.g., due to user's capabilities
+ requiring a new SIP server, or not enough resources in the current
+ SIP server. If informing the interested parties about the
+ administrative deregistration is supported through SIP procedures
+ (e.g., subscriptions to the "reg" event [RFC3680]), the SIP server
+ will do so. The Diameter client in the SIP Server SHOULD NOT
+ request a new user registration. The SIP server clears the
+ registration state of the deregistered SIP AORs.
+
+
+
+Garcia-Martin, et al. Standards Track [Page 40]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ o If the value is set to REMOVE_SIP_SERVER, the Diameter server
+ informs the SIP server (Diameter client) that the SIP server will
+ no longer be bound in the Diameter server with that user. The SIP
+ server can delete all data related to the user.
+
+ The Message Format of the RTA command is as follows:
+
+ <RTA> ::= < Diameter Header: 287, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+8.11. Push-Profile-Request (PPR) Command
+
+ The Push-Profile-Request (PPR) command is indicated by the
+ Command-Code set to 288 and the Command Flags' 'R' bit set. The
+ Diameter server sends this command to the Diameter client in a SIP
+ server to update either the user profile of an already registered
+ user in that SIP server or the SIP accounting information. This
+ allows an operator to modify the data of a user profile or the
+ accounting information and push it to the SIP server where the user
+ is registered.
+
+ Each user has a user profile associated with him/her and other
+ accounting information. The profile or the accounting information
+ may change with time, e.g., due to addition of new services to the
+ user. When the user profile or the accounting information changes,
+ the Diameter server sends a Diameter Push-Profile-Request (PPR)
+ command to the Diameter client in a SIP server, in order to start
+ applying those new services.
+
+ A PPR command MAY contain a SIP-Accounting-Information AVP that
+ updates the addresses of the accounting servers. Changes in the
+ addresses of the accounting servers take effect immediately. The
+ Diameter client SHOULD close any existing accounting session with the
+ existing server and start providing accounting information to the
+ newly acquired accounting server.
+
+
+
+Garcia-Martin, et al. Standards Track [Page 41]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ A PPR command MAY contain zero or more SIP-User-Data AVP values
+ containing the new user profile. On selecting the type of user data,
+ the Diameter server SHOULD take into account the supported formats at
+ the SIP server (SIP-Supported-User-Data-Type AVP sent in a previous
+ SAR message) and the local policy.
+
+ The User-Name AVP indicates the user to whom the profile is
+ applicable.
+
+ The Message Format of the PPR command is as follows:
+
+ <PPR> ::= < Diameter Header: 288, REQ, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { User-Name }
+ * [ SIP-User-Data ]
+ [ SIP-Accounting-Information ]
+ [ Destination-Host ]
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+8.12. Push-Profile-Answer (PPA) Command
+
+ The Push-Profile-Answer (PPA) is indicated by the Command-Code set to
+ 288 and the Command Flags' 'R' bit cleared. The Diameter client
+ sends this command in response to a previously received Diameter
+ Push-Profile-Request (PPR) command.
+
+ In addition to the values already defined in RFC 3588 [RFC3588], the
+ Result-Code AVP may contain one of the values defined in
+ Section 10.1.
+
+ If there is no error when processing the received Diameter PPR
+ message, the SIP server (Diameter client) MUST download the received
+ user profile from the SIP-User-Data AVP values in the Diameter PPR
+ message and store it associated with the user specified in the
+ User-Name AVP value.
+
+ If the SIP server does not recognize or does not support some of the
+ data transferred in the SIP-User-Data AVP values, the Diameter client
+ in the SIP server MUST return a Diameter PPA message that includes a
+
+
+
+Garcia-Martin, et al. Standards Track [Page 42]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ Result-Code AVP set to the value
+ DIAMETER_ERROR_NOT_SUPPORTED_USER_DATA.
+
+ If the SIP server (Diameter client) receives a Diameter PPR message
+ with a User-Name AVP that is unknown, the Diameter client MUST set
+ the Result-Code AVP value to DIAMETER_ERROR_USER_UNKNOWN and MUST
+ return it to the Diameter server in a Diameter PPA message.
+
+ If the SIP server (Diameter client) receives in the
+ SIP-User-Data-Content AVP value (of the grouped SIP-User-Data AVP)
+ more data than it can accept, it MUST set the Result-Code AVP value
+ to DIAMETER_ERROR_TOO_MUCH_DATA and MUST return it to the Diameter
+ server in a Diameter PPA message. The SIP server MUST NOT override
+ the existing user profile with the one received in the PPR message.
+
+ If the Diameter server receives the Result-Code AVP value set to
+ DIAMETER_ERROR_TOO_MUCH_DATA in a Diameter PPA message, it SHOULD
+ force a new re-registration of the user by sending to the Diameter
+ client a Diameter Registration-Termination-Request (RTR) with the
+ SIP-Deregistration-Reason AVP value set to SIP_SERVER_CHANGE. This
+ will force a re-registration of the user and will trigger a selection
+ of a new SIP server.
+
+ If the Diameter client is not able to honor the command, for any
+ other reason, it MUST set the Result-Code AVP value to
+ DIAMETER_UNABLE_TO_COMPLY and it MUST return it in a Diameter PPA
+ message.
+
+ The Message Format of the PPA command is as follows:
+
+ <PPA> ::= < Diameter Header: 288, PXY >
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 43]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+9. Diameter SIP Application AVPs
+
+ This section defines new AVPs used in this Diameter SIP application.
+ Applications compliant with this specification MUST implement these
+ AVPs.
+
+ Table 2 lists the new AVPs defined in this Diameter SIP application.
+ The following abbreviations are used in the Data-Type column:
+
+ o DURI: DiameterURI
+ o E: Enumerated
+ o G: Grouped
+ o OS: OctetString
+ o UTF8S: UTF8String
+ o U32: Unsigned32
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 44]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ +-----------------------------------+------+----------------+-------+
+ | Attribute Name | AVP | Reference | Data- |
+ | | Code | | Type |
+ +-----------------------------------+------+----------------+-------+
+ | SIP-Accounting-Information | 368 | Section 9.1 | G |
+ | SIP-Accounting-Server-URI | 369 | Section 9.1.1 | DURI |
+ | SIP-Credit-Control-Server-URI | 370 | Section 9.1.2 | DURI |
+ | SIP-Server-URI | 371 | Section 9.2 | UTF8S |
+ | SIP-Server-Capabilities | 372 | Section 9.3 | G |
+ | SIP-Mandatory-Capability | 373 | Section 9.3.1 | U32 |
+ | SIP-Optional-Capability | 374 | Section 9.3.2 | U32 |
+ | SIP-Server-Assignment-Type | 375 | Section 9.4 | E |
+ | SIP-Auth-Data-Item | 376 | Section 9.5 | G |
+ | SIP-Authentication-Scheme | 377 | Section 9.5.1 | E |
+ | SIP-Item-Number | 378 | Section 9.5.2 | U32 |
+ | SIP-Authenticate | 379 | Section 9.5.3 | G |
+ | SIP-Authorization | 380 | Section 9.5.4 | G |
+ | SIP-Authentication-Info | 381 | Section 9.5.5 | G |
+ | SIP-Number-Auth-Items | 382 | Section 9.6 | U32 |
+ | SIP-Deregistration-Reason | 383 | Section 9.7 | G |
+ | SIP-Reason-Code | 384 | Section 9.7.1 | E |
+ | SIP-Reason-Info | 385 | Section 9.7.2 | UTF8S |
+ | SIP-Visited-Network-Id | 386 | Section 9.9 | UTF8S |
+ | SIP-User-Authorization-Type | 387 | Section 9.10 | E |
+ | SIP-Supported-User-Data-Type | 388 | Section 9.11 | UTF8S |
+ | SIP-User-Data | 389 | Section 9.12 | G |
+ | SIP-User-Data-Type | 390 | Section 9.12.1 | UTF8S |
+ | SIP-User-Data-Contents | 391 | Section 9.12.2 | OS |
+ | SIP-User-Data-Already-Available | 392 | Section 9.13 | E |
+ | SIP-Method | 393 | Section 9.14 | UTF8S |
+ +-----------------------------------+------+----------------+-------+
+
+ Table 2: Defined AVPs
+
+ Table 3 expands the table of AVPs included in Section 4.5 of RFC 3588
+ [RFC3588]. The table indicates the Diameter AVPs defined in this
+ Diameter SIP Application, their possible flag values, and whether the
+ AVP may be encrypted. The acronyms 'M', 'P', and 'V' refer to AVP
+ flags whose semantics are described in RFC 3588 [RFC3588]. The value
+ of the 'Encr' column is also described in RFC 3588 [RFC3588].
+
+
+
+
+
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 45]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ +----------------------------------+------+-----+-----+------+------+
+ | Attribute Name | MUST | MAY | SHD | MUST | Encr |
+ | | | | NOT | NOT | |
+ +----------------------------------+------+-----+-----+------+------+
+ | SIP-Accounting-Information | M | P | | V | N |
+ | SIP-Accounting-Server-URI | M | P | | V | N |
+ | SIP-Credit-Control-Server-URI | M | P | | V | N |
+ | SIP-Server-URI | M | P | | V | N |
+ | SIP-Server-Capabilities | M | P | | V | N |
+ | SIP-Mandatory-Capability | M | P | | V | N |
+ | SIP-Optional-Capability | M | P | | V | N |
+ | SIP-Server-Assignment-Type | M | P | | V | N |
+ | SIP-Auth-Data-Item | M | P | | V | N |
+ | SIP-Authentication-Scheme | M | P | | V | N |
+ | SIP-Item-Number | M | P | | V | N |
+ | SIP-Authenticate | M | P | | V | N |
+ | SIP-Authorization | M | P | | V | N |
+ | SIP-Authentication-Info | M | P | | V | N |
+ | SIP-Number-Auth-Items | M | P | | V | N |
+ | SIP-Deregistration-Reason | M | P | | V | N |
+ | SIP-Reason-Code | M | P | | V | N |
+ | SIP-Reason-Info | M | P | | V | N |
+ | SIP-Visited-Network-Id | M | P | | V | N |
+ | SIP-User-Authorization-Type | M | P | | V | N |
+ | SIP-Supported-User-Data-Type | M | P | | V | N |
+ | SIP-User-Data | M | P | | V | N |
+ | SIP-User-Data-Type | M | P | | V | N |
+ | SIP-User-Data-Contents | M | P | | V | N |
+ | SIP-User-Data-Already-Available | M | P | | V | N |
+ | SIP-Method | M | P | | V | N |
+ +----------------------------------+------+-----+-----+------+------+
+
+ Table 3: Summary of the new AVPs flags
+
+9.1. SIP-Accounting-Information AVP
+
+ The SIP-Accounting-Information (AVP Code 368) is of type Grouped, and
+ contains the Diameter addresses of those nodes that are able to
+ collect accounting information.
+
+ The SIP-Accounting-Information AVP is defined as follows (per the
+ grouped-avp-def of RFC 3588 [RFC3588]):
+
+ SIP-Accounting-Information ::= < AVP Header: 368 >
+ * [ SIP-Accounting-Server-URI ]
+ * [ SIP-Credit-Control-Server-URI ]
+ * [ AVP]
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 46]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+9.1.1. SIP-Accounting-Server-URI AVP
+
+ The SIP-Accounting-Server-URI AVP (AVP Code 369) is of type
+ DiameterURI. This AVP contains the address of a Diameter server that
+ is able to receive SIP-session-related accounting information.
+
+9.1.2. SIP-Credit-Control-Server-URI AVP
+
+ The SIP-Credit-Control-Server-URI AVP (AVP Code 370) is of type
+ DiameterURI. This AVP contains the address of a Diameter server that
+ is able to authorize real-time credit control usage. The Diameter
+ Credit-Control Application [RFC4006] may be used for this purpose.
+
+9.2. SIP-Server-URI AVP
+
+ The SIP-Server-URI AVP (AVP Code 371) is of type UTF8String. This
+ AVP contains a SIP or SIPS URI (as defined in RFC 3261 [RFC3261])
+ that identifies a SIP server.
+
+9.3. SIP-Server-Capabilities AVP
+
+ The SIP-Server-Capabilities AVP (AVP Code 372) is of type Grouped.
+ The Diameter indicates in this AVP the requirements for a particular
+ SIP capability, so that the Diameter client (SIP server) is able to
+ select another appropriate SIP server to serve the user.
+
+ The SIP-Server-Capabilities AVP allows a Diameter client (SIP server)
+ to select another SIP server for triggering or executing services to
+ the user. A user may have enabled some services that require the
+ implementation of certain capabilities in the SIP server that
+ triggers or executes those services. For example, the SIP server
+ that triggers or executes services to this user may need to implement
+ SIP servlets [JSR-000116], Call Processing Language (CPL) [RFC3880],
+ or any other kind of capability. Or perhaps that user belongs to a
+ premium users group that has a certain stringent quality-of-service
+ agreement that requires a fast SIP server. The capabilities required
+ or recommended to a given user are conveyed in the
+ SIP-Server-Capabilities AVP. When it receives them, the Diameter
+ client (SIP server) that does the SIP server selection needs to have
+ the means to find out available SIP servers that meet the required or
+ optional capabilities. Such means are outside the scope of this
+ specification.
+
+ Note that the SIP-Server-Capabilities AVP assists the Diameter client
+ (SIP server) to produce a subset of all the available SIP servers to
+ be allocated to the user in the Home Realm; this is the subset that
+ conforms the requirements of capabilities on a per-user basis.
+ Typically this subset will be formed of more than a single SIP
+
+
+
+Garcia-Martin, et al. Standards Track [Page 47]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ server, so once the subset of those SIP servers is identified, it is
+ possible that several instances of these SIP servers exist, in which
+ case the Diameter client (SIP server) should choose one particular
+ SIP server to execute and trigger services to this user. It is
+ expected that at this point the SIP server (Diameter client) will
+ follow the procedures of RFC 3263 [RFC3263] to allocate one SIP
+ server to the user.
+
+ The SIP-Server-Capabilities AVP is defined as follows (per the
+ grouped-avp-def of RFC 3588 [RFC3588]):
+
+ SIP-Server-Capabilities ::= < AVP Header: 372 >
+ * [ SIP-Mandatory-Capability ]
+ * [ SIP-Optional-Capability ]
+ * [ SIP-Server-URI ]
+ * [ AVP ]
+
+9.3.1. SIP-Mandatory-Capability AVP
+
+ The SIP-Mandatory-Capability AVP (AVP Code 373) is of type
+ Unsigned32. The value represents a certain capability (or set of
+ capabilities) that have to be fulfilled by the SIP server allocated
+ to the user.
+
+ The semantics of the different values are not standardized, as it is
+ a matter of the administrative network to allocate its own semantics
+ within its own network. Each value has to represent a single
+ capability within the administrative network.
+
+9.3.2. SIP-Optional-Capability AVP
+
+ The SIP-Optional-Capability AVP (AVP Code 374) is of type Unsigned32.
+ The value represents a certain capability (or set of capabilities)
+ that, optionally, may be fulfilled by the SIP server allocated to the
+ user.
+
+ The semantics of the different values are not standardized, as it is
+ a matter of the administrative network to allocate its own semantics
+ within its own network. Each value has to represent a single
+ capability within the administrative network.
+
+9.4. SIP-Server-Assignment-Type AVP
+
+ The SIP-Server-Assignment-Type AVP (AVP Code 375) is of type
+ Enumerated and indicates the type of server update being performed in
+ a Diameter Server-Assignment-Request (SAR) operation. The following
+ values are defined:
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 48]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ o NO_ASSIGNMENT (0)
+ The Diameter client uses this value to request the user profile of
+ a SIP AOR, without affecting the registration state of that
+ identity.
+
+ o REGISTRATION (1)
+ First SIP registration of a SIP AOR.
+
+ o RE_REGISTRATION (2)
+ Subsequent SIP registration of a SIP AOR.
+
+ o UNREGISTERED_USER (3)
+ The SIP server has received a SIP request (e.g., SIP INVITE)
+ addressed for a SIP AOR that is not registered.
+
+ o TIMEOUT_DEREGISTRATION (4)
+ The SIP registration timer of an identity has expired.
+
+ o USER_DEREGISTRATION (5)
+ The SIP server has received a request to deregister a SIP AOR.
+
+ o TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME (6)
+ The SIP registration timer of an identity has expired. The SIP
+ server keeps the user data stored and requests the Diameter server
+ to store the SIP server address.
+
+ o USER_DEREGISTRATION_STORE_SERVER_NAME (7)
+ The SIP server has received a user-initiated deregistration
+ request. The SIP server keeps the user data stored and requests
+ the Diameter server to store the SIP server address.
+
+ o ADMINISTRATIVE_DEREGISTRATION (8)
+ The SIP server, due to administrative reasons, has deregistered a
+ SIP AOR.
+
+ o AUTHENTICATION_FAILURE (9)
+ The authentication of a user has failed.
+
+ o AUTHENTICATION_TIMEOUT (10)
+ The authentication timer has expired.
+
+ o DEREGISTRATION_TOO_MUCH_DATA (11)
+ The SIP server has requested user profile information from the
+ Diameter server and has received a volume of data higher than it
+ can accept.
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 49]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+9.5. SIP-Auth-Data-Item AVP
+
+ The SIP-Auth-Data-Item (AVP Code 376) is of type Grouped and contains
+ the authentication and/or authorization information pertaining to a
+ user.
+
+ When the Diameter server uses the grouped SIP-Auth-Data-Item AVP to
+ include a SIP-Authenticate AVP, the Diameter server MUST send a
+ maximum of one authentication data item (e.g., in case the SIP
+ request contained several credentials). Section 11 contains a
+ detailed discussion and normative text of the case when a SIP request
+ contains several credentials.
+
+ The SIP-Auth-Data-Item AVP is defined as follows (per the
+ grouped-avp-def of RFC 3588 [RFC3588]):
+
+ SIP-Auth-Data-Item ::= < AVP Header: 376 >
+ { SIP-Authentication-Scheme }
+ [ SIP-Item-Number ]
+ [ SIP-Authenticate ]
+ [ SIP-Authorization ]
+ [ SIP-Authentication-Info ]
+ * [ AVP ]
+
+9.5.1. SIP-Authentication-Scheme AVP
+
+ The SIP-Authentication-Scheme AVP (AVP Code 377) is of type
+ Enumerated and indicates the authentication scheme used in the
+ authentication of SIP services. RFC 2617 identifies this value as an
+ "auth-scheme" (see Section 1.2 of RFC 2617 [RFC2617]). The only
+ currently defined value is:
+
+ o DIGEST (0) to indicate HTTP Digest authentication as specified in
+ RFC 2617 [RFC2617] Section 3.2.1. Derivative work is also
+ considered Digest authentication scheme, as long as the
+ "auth-scheme" is identified as Digest in the SIP headers carrying
+ the HTTP authentication. This includes, e.g., the HTTP Digest
+ authentication using AKA [RFC3310].
+
+ Each HTTP Digest directive (parameter) is transported in a
+ corresponding AVP, whose name follows the pattern Digest-*. The
+ Digest-* AVPs are RADIUS attributes imported from the RADIUS
+ Extension for Digest Authentication [RFC4590] namespace, allowing a
+ smooth transition between RADIUS and Diameter applications supporting
+ SIP. The Diameter SIP application goes a step further by grouping
+ the Digest-* AVPs into the SIP-Authenticate, SIP-Authorization, and
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 50]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ SIP-Authentication-Info grouped AVPs that correspond to the SIP WWW-
+ Authenticate/Proxy-Authentication, Authorization/Proxy-Authorization,
+ and Authentication-Info headers fields, respectively.
+
+ Note: Due to the fact that HTTP Digest authentication [RFC2617] is
+ the only mandatory authentication mechanism in SIP, this memo only
+ provides support for HTTP Digest authentication and derivative
+ work such as HTTP Digest authentication using AKA [RFC3310].
+ Extensions to this memo can register new values and new AVPs to
+ provide support for other authentication schemes or extensions to
+ HTTP Digest authentication.
+
+ Note: Although RFC 2617 [RFC2617] defines the Basic and Digest
+ schemes for authenticating HTTP requests, RFC 3261 [RFC3261] only
+ imports HTTP Digest as a mechanism to provide authentication in
+ SIP.
+
+ Due to syntactic requirements, HTTP Digest authentication has to
+ escape quote characters in contents of HTTP Digest directives. When
+ translating directives into Digest-* AVPs, the Diameter client or
+ server removes the surrounding quotes where present, as required by
+ the syntax of the Digest-* attributes defined in the "RADIUS
+ Extension for Digest Authentication" [RFC4590].
+
+9.5.2. SIP-Item-Number AVP
+
+ The SIP-Item-Number (AVP Code 378) is of type Unsigned32 and is
+ included in a SIP-Auth-Data-Item grouped AVP in circumstances where
+ there are multiple occurrences of SIP-Auth-Data-Item AVPs and the
+ order of processing is relevant. The AVP indicates the order in
+ which the Grouped SIP-Auth-Data-Item should be processed. Lower
+ values of the SIP-Item-Number AVP indicate that the whole
+ SIP-Auth-Data-Item SHOULD be processed before other
+ SIP-Auth-Data-Item AVPs that contain higher values in the
+ SIP-Item-Number AVP.
+
+9.5.3. SIP-Authenticate AVP
+
+ The SIP-Authenticate AVP (AVP Code 379) is of type Grouped and
+ contains a reconstruction of either the SIP WWW-Authenticate or
+ Proxy-Authentication header fields specified in RFC 2617 [RFC2617]
+ for the HTTP Digest authentication scheme. Additionally, the AVP may
+ include a Digest-HA1 AVP that contains H(A1) (as defined in RFC 2617
+ [RFC2617]). H(A1) allows the Diameter client to create an expected
+ response and compare it with the Digest response received from the
+ SIP UA.
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 51]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ The SIP-Authenticate AVP is defined as follows (per the
+ grouped-avp-def of RFC 3588 [RFC3588]):
+
+ SIP-Authenticate ::= < AVP Header: 379 >
+ { Digest-Realm }
+ { Digest-Nonce }
+ [ Digest-Domain ]
+ [ Digest-Opaque ]
+ [ Digest-Stale ]
+ [ Digest-Algorithm ]
+ [ Digest-QoP ]
+ [ Digest-HA1]
+ * [ Digest-Auth-Param ]
+ * [ AVP ]
+
+9.5.4. SIP-Authorization AVP
+
+ The SIP-Authorization AVP (AVP Code 380) is of type Grouped and
+ contains a reconstruction of either the SIP Authorization or
+ Proxy-Authorization header fields specified in RFC 2617 [RFC2617] for
+ the HTTP Digest authentication scheme.
+
+ The SIP-Authorization AVP is defined as follows (per the
+ grouped-avp-def of RFC 3588 [RFC3588]):
+
+ SIP-Authorization ::= < AVP Header: 380 >
+ { Digest-Username }
+ { Digest-Realm }
+ { Digest-Nonce }
+ { Digest-URI }
+ { Digest-Response }
+ [ Digest-Algorithm ]
+ [ Digest-CNonce ]
+ [ Digest-Opaque ]
+ [ Digest-QoP ]
+ [ Digest-Nonce-Count ]
+ [ Digest-Method]
+ [ Digest-Entity-Body-Hash ]
+ * [ Digest-Auth-Param ]
+ * [ AVP ]
+
+9.5.5. SIP-Authentication-Info AVP
+
+ The SIP-Authentication-Info AVP (AVP Code 381) is of type Grouped and
+ contains a reconstruction of the SIP Authentication-Info header
+ specified in RFC 2617 [RFC2617] for the HTTP Digest authentication
+ scheme.
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 52]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ The SIP-Authentication-Info AVP is defined as follows (per the
+ grouped-avp-def of RFC 3588 [RFC3588]):
+
+ SIP-Authentication-Info ::= < AVP Header: 381 >
+ [ Digest-Nextnonce ]
+ [ Digest-QoP ]
+ [ Digest-Response-Auth ]
+ [ Digest-CNonce ]
+ [ Digest-Nonce-Count ]
+ * [ AVP ]
+
+ Note that, in some cases, the Digest-Response-Auth AVP cannot be
+ calculated at the Diameter server, but has to be calculated at the
+ Diameter client (SIP server). For example, if the value of the
+ quality of protection (qop) parameter in Digest is set to "auth-int",
+ then the response-digest (rspauth parameter value in Digest) is
+ calculated with the hash of the body of the SIP response, which is
+ not available at the Diameter server. In this case, the Diameter
+ client (SIP server) must calculate the response-digest once the body
+ of the SIP response is calculated.
+
+ Therefore, a value of "auth-int" in the Digest-QoP AVP of the
+ SIP-Authentication-Info AVP indicates that the Diameter client (SIP
+ server) MUST compute the Digest "rspauth" parameter value at the
+ Diameter client (SIP server).
+
+9.5.6. Digest AVPs
+
+ The following AVPs are RADIUS attributes defined in the RADIUS
+ Extension for Digest Authentication [RFC4590] and imported by this
+ specification: Digest-AKA-Auts, Digest-Algorithm, Digest-Auth-Param,
+ Digest-CNonce, Digest-Domain, Digest-Entity-Body-Hash, Digest-HA1,
+ Digest-Method, Digest-Nextnonce, Digest-Nonce, Digest-Nonce-Count,
+ Digest-Opaque, Digest-QoP, Digest-Realm, Digest-Response,
+ Digest-Response-Auth, Digest-URI, Digest-Username, and Digest-Stale.
+
+9.5.6.1. Considerations about Digest-HA1 AVP
+
+ The Digest-HA1 AVP contains the value, pre-calculated at the Diameter
+ server, of H(A1) as defined in RFC 2617 [RFC2617]. The Diameter
+ client can use H(A1) to calculate the expected Digest response,
+ according to this challenge. If the SIP UA is in possession of the
+ credentials, the calculated expected response and the response sent
+ from the SIP UA will match. The Diameter server MAY include this AVP
+ to enable and assist the SIP server in authenticating the SIP UA.
+
+ This scenario is not applicable when the Diameter server is
+ configured to use a session MD5 (MD5-sess) algorithm, because the
+
+
+
+Garcia-Martin, et al. Standards Track [Page 53]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ Diameter server requires the client nonce to compute the H(A1) before
+ sending it to the Diameter client, and the client nonce might not be
+ available when the computation of H(A1) is done. Therefore, if the
+ final authentication is delegated to the Diameter client, it is
+ RECOMMENDED to configure the Diameter server to use algorithms
+ different than MD5-sess in HTTP Digest.
+
+ It is up to the Diameter server to include a Digest-HA1 AVP. The
+ Diameter server calculates the Digest H(A1) with the username,
+ password, and realm (and nonce and cnonce, if applicable) as inputs,
+ and places the result in the Digest-HA1 AVP value. For more details
+ of the A1 computation, see RFC 2617 [RFC2617] Section 3.2.2.2. The
+ Diameter client can calculate the Digest expected response with H(A1)
+ as input, as described in RFC 2617 [RFC2617] Section 3.2.2.
+
+ Section 11 provides further normative details about the usage of the
+ Digest-HA1 AVP.
+
+9.5.6.2. Considerations about Digest-Entity-Body-Hash AVP
+
+ The Digest-Entity-Body-Hash AVP contains a hash of the entity body
+ contained in the SIP message. This hash is required by HTTP Digest
+ with quality of protection set to "auth-int". Diameter clients MUST
+ use this AVP to transport the hash of the entity body when HTTP
+ Digest is the authentication mechanism and the Diameter server
+ requires verification of the integrity of the entity body (e.g., qop
+ parameter set to "auth-int").
+
+ The clarifications described in Section 22.4 of RFC 3261 [RFC3261]
+ about the hash of empty entity bodies apply to the
+ Digest-Entity-Body-Hash AVP.
+
+9.5.6.3. Considerations about Digest-Auth-Param AVP
+
+ The Digest-Auth-Param AVP is the mechanism whereby the Diameter
+ client and Diameter server can exchange possible extension parameters
+ contained in Digest headers that are either not understood by the
+ Diameter client or for which there are no corresponding stand-alone
+ AVPs. Unlike the previously listed Digest-* AVPs, the
+ Digest-Auth-Param contains not only the value, but also the parameter
+ name, since it is unknown to the Diameter client. The Diameter node
+ MUST insert one Digest parameter/value combination per AVP value. If
+ the Digest header contains several unknown parameters, then the
+ Diameter implementation MUST repeat this AVP and each instance MUST
+ contain one different unknown Digest parameter/value combination.
+ This AVP corresponds to the "auth-param" parameter defined in Section
+ 3.2.1 of RFC 2617 [RFC2617].
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 54]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ Example: Assume that the Diameter server wants the SIP server to send
+ a "foo" parameter with the value set to "bar", so that the SIP server
+ sends that combination in a SIP WWW-Authenticate header field. The
+ Diameter server builds a grouped SIP-Authenticate AVP that contains a
+ Digest-Auth-Param whose value is set to foo="bar". Then the SIP
+ server creates the WWW-Authenticate header field with all the digest
+ parameters (received in Digest-* AVPs) and adds the foo="bar"
+ parameter to that header field.
+
+9.6. SIP-Number-Auth-Items AVP
+
+ The SIP-Number-Auth-Items AVP (AVP Code 382) is of type Unsigned32
+ and indicates the number of authentication and/or authorization
+ credentials that the Diameter server included in a Diameter message.
+
+ When the AVP is present in a request, it indicates the number of
+ SIP-Auth-Data-Items the Diameter client is requesting. This can be
+ used, for instance, when the SIP server is requesting several
+ pre-calculated authentication credentials. In the answer message,
+ the SIP-Number-Auth-Items AVP indicates the actual number of items
+ that the Diameter server included.
+
+9.7. SIP-Deregistration-Reason AVP
+
+ The SIP-Deregistration-Reason AVP (AVP Code 383) is of type Grouped
+ and indicates the reason for a deregistration operation.
+
+ The SIP-Deregistration-Reason AVP is defined as follows (per the
+ grouped-avp-def of RFC 3588 [RFC3588]):
+
+ SIP-Deregistration-Reason ::= < AVP Header: 383 >
+ { SIP-Reason-Code }
+ [ SIP-Reason-Info ]
+ * [ AVP ]
+
+9.7.1. SIP-Reason-Code AVP
+
+ The SIP-Reason-Code AVP (AVP Code 384) is of type Enumerated and
+ defines the reason for the network initiated deregistration. The
+ following values are defined:
+
+ o PERMANENT_TERMINATION (0)
+ o NEW_SIP_SERVER_ASSIGNED (1)
+ o SIP_SERVER_CHANGE (2)
+ o REMOVE_SIP_SERVER (3)
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 55]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+9.7.2. SIP-Reason-Info AVP
+
+ The SIP-Reason-Info AVP (AVP Code 385) is of type UTF8String and
+ contains textual information that can be rendered to the user, about
+ the reason for a deregistration.
+
+9.8. SIP-AOR AVP
+
+ The SIP-AOR AVP is a RADIUS attribute imported from the RADIUS
+ Extension for Digest Authentication [RFC4590] namespace, allowing a
+ smooth transition between RADIUS and Diameter applications supporting
+ SIP. The SIP-AOR AVP carries the URI of the intended user related to
+ the SIP request (whose location in SIP may vary depending on the
+ actual SIP request and whether the SIP server is acting on Diameter
+ due to a SIP-originated or terminating requests).
+
+ The Diameter client (SIP server) uses the value found in a SIP
+ Request-URI or a header field value of the SIP request to construct
+ the SIP-AOR AVP. The selection of a Request-URI or a particular
+ header field to create the value of the SIP-AOR AVP depends on the
+ semantics of the SIP message and whether the SIP server is acting for
+ originating or terminating requests. For instance, when the SIP
+ server receives an INVITE request addressed to the served user (e.g.,
+ the SIP server is receiving a terminating SIP request), it maps the
+ SIP Request-URI of the SIP request to this AVP. However, when the
+ SIP server receives an INVITE request originated by the served user,
+ it can map either the P-Asserted-Identity or the From header field
+ values to this AVP. If the SIP server is acting as a SIP registrar,
+ then it maps the To header field of the REGISTER request to the
+ SIP-AOR AVP.
+
+9.9. SIP-Visited-Network-Id AVP
+
+ The SIP-Visited-Network-Id AVP (AVP Code 386) is of type UTF8String.
+ This AVP contains an identifier that helps the home network identify
+ the visited network (e.g., the visited network domain name), in order
+ to authorize roaming to that visited network.
+
+9.10. SIP-User-Authorization-Type AVP
+
+ The SIP-User-Authorization-Type AVP (AVP Code 387) is of type
+ Enumerated and indicates the type of user authorization being
+ performed in a User Authorization operation, i.e., the Diameter
+ User-Authorization-Request (UAR) command. The following values are
+ defined:
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 56]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ o REGISTRATION (0)
+ This value is used for initial registration or re-registration.
+ This is the default value.
+
+ o DEREGISTRATION (1)
+ This value is used for deregistration.
+
+ o REGISTRATION_AND_CAPABILITIES (2)
+ This value is used for initial registration or re-registration
+ when the SIP server explicitly requests the Diameter server to get
+ capability information. This capability information helps the SIP
+ server to allocate another SIP server to serve the user.
+
+9.11. SIP-Supported-User-Data-Type AVP
+
+ The SIP-Supported-User-Data-Type AVP (AVP Code 388) is of type
+ UTF8String and contains a string that identifies the type of
+ supported user data (user profile, see SIP-User-Data AVP
+ (Section 9.12)) supported in the node. The AVP can be repeated, if
+ the SIP server supports several user data types. In case of
+ repetition, the Diameter client should order the different instances
+ of this AVP according to its preferences.
+
+ When the Diameter client inserts this AVP in a SAR message, it allows
+ the Diameter client to provide an indication to the Diameter server
+ of the types of user data supported by the SIP server. The Diameter
+ server, upon inspection of these AVPs, will return a suitable
+ SIP-User-Data AVP (Section 9.12) of the type indicated in the
+ SIP-User-Data-Type AVP (Section 9.12.1).
+
+9.12. SIP-User-Data AVP
+
+ The SIP-User-Data AVP (AVP Code 389) is of type Grouped. This AVP
+ allows the Diameter server to transport user-specific data, such as a
+ user profile, to the SIP server (in the Diameter client). The
+ Diameter server selects a type of user data that is understood by the
+ SIP server in the Diameter client, and has been indicated in a
+ SIP-Supported-User-Data-Type AVP. In case the Diameter client
+ indicated support for several types of user data, the Diameter server
+ SHOULD choose the first type supported by the client.
+
+ The SIP-User-Data grouped AVP contains a SIP-User-Data-Type AVP that
+ indicates the type of user data included in the
+ SIP-User-Data-Contents-AVP.
+
+ The SIP-User-Data AVP is defined as follows (per the grouped-avp-def
+ of RFC 3588 [RFC3588]):
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 57]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ SIP-User-Data ::= < AVP Header: 389 >
+ { SIP-User-Data-Type }
+ { SIP-User-Data-Contents }
+ * [ AVP ]
+
+9.12.1. SIP-User-Data-Type AVP
+
+ The SIP-User-Data AVP (AVP Code 390) is of type UTF8String and
+ contains a string that identifies the type of user data included in
+ the SIP-User-Data AVP (Section 9.12).
+
+ This document does not specify a convention to characterize the type
+ of user data contained in the SIP-User-Data AVP (Section 9.12). It
+ is believed that in most cases this feature will be used in
+ environments controlled by a network administrator who can configure
+ both the client and server to assign the same value type at the
+ client and server. It is also RECOMMENDED that organizations
+ developing their own profile of SIP-User-Data AVP (Section 9.12)
+ allocate a type based on their canonical DNS name. For instance,
+ organization "example.com" can define several types of SIP-User-Data
+ and allocate the types "type1.dsa.example.com",
+ "type2.dsa.example.com", and so on. This convention will avoid a
+ clash in the allocation of types of SIP-User-Data AVP (Section 9.12).
+
+9.12.2. SIP-User-Data-Contents AVP
+
+ The SIP-User-Data-Contents AVP (AVP Code 391) is of type OctetString.
+ The Diameter peers do not need to understand the value of this AVP.
+
+ The AVP contains the user profile data required for a SIP server to
+ give service to the user.
+
+9.13. SIP-User-Data-Already-Available AVP
+
+ The SIP-User-Data-Already-Available AVP (AVP Code 392) is of type
+ Enumerated and gives an indication to the Diameter server about
+ whether the Diameter client (SIP server) already received the portion
+ of the user profile needed in order to serve the user. The following
+ values are defined:
+
+ o USER_DATA_NOT_AVAILABLE (0)
+ The Diameter client (SIP server) does not have the data that it
+ needs to serve the user.
+
+ o USER_DATA_ALREADY_AVAILABLE (1)
+ The Diameter client (SIP server) already has received the data
+ that it needs to serve the user.
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 58]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+9.14. SIP-Method AVP
+
+ The SIP-Method-AVP (AVP Code 393) is of type UTF8String and contains
+ the method of the SIP request that triggered the Diameter message.
+ The Diameter server MUST use this AVP solely for authorization of SIP
+ requests, and MUST NOT use it to compute the Digest authentication.
+ To compute the Digest authentication, the Diameter server MUST use
+ the Digest-Method AVP instead.
+
+10. New Values for Existing AVPs
+
+ This section defines new values that the Diameter SIP application
+ extends to already existing AVPs.
+
+10.1. Extension to the Result-Code AVP Values
+
+ The Result-Code AVP is already defined in RFC 3588 [RFC3588]. In
+ addition to the values already defined in RFC 3588 [RFC3588], the
+ Diameter SIP application defines the following new Result-Code AVP
+ values:
+
+10.1.1. Success Result-Code AVP Values
+
+ A Diameter peer uses Result-Code AVP values that fall into the
+ success category to inform the remote peer that a request has been
+ successfully completed.
+
+ o DIAMETER_FIRST_REGISTRATION 2003
+ The user was not previously registered. The Diameter server has
+ now authorized the registration.
+
+ o DIAMETER_SUBSEQUENT_REGISTRATION 2004
+ The user is already registered. The Diameter server has now
+ authorized the re-registration.
+
+ o DIAMETER_UNREGISTERED_SERVICE 2005
+ The user is not currently registered, but the requested service
+ can still be granted to the user.
+
+ o DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED 2006
+ The request operation was successfully processed. The Diameter
+ server does not keep a record of the SIP server address assigned
+ to the user.
+
+ o DIAMETER_SERVER_SELECTION 2007
+ The Diameter server has authorized the registration. The user has
+ already been assigned a SIP server, but it may be necessary to
+ select a new SIP server for the user.
+
+
+
+Garcia-Martin, et al. Standards Track [Page 59]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ o DIAMETER_SUCCESS_AUTH_SENT_SERVER_NOT_STORED 2008
+ The requested operation was successfully executed. The Diameter
+ server is sending a number of authentication credentials in the
+ answer message. The Diameter server does not keep a record of the
+ SIP server.
+
+10.1.2. Transient Failures Result-Code AVP Values
+
+ A Diameter peer uses a Result-Code AVP value that falls in the
+ transient failures category to inform the remote peer that a request
+ could not be satisfied at the time it was received, but it MAY be
+ satisfied by the Diameter peer in the future.
+
+ o DIAMETER_USER_NAME_REQUIRED 4013
+ The Diameter request did not contain a User-Name AVP, which is
+ required to complete the transaction. The Diameter peer MAY
+ include a User-Name AVP and attempt the request again.
+
+10.1.3. Permanent Failures Result-Code AVP Values
+
+ A Diameter peer uses a Result-Code AVP value that falls into the
+ permanent failure category to inform the remote peer that the request
+ failed and should not be attempted again.
+
+ o DIAMETER_ERROR_USER_UNKNOWN 5032
+ The SIP-AOR AVP value does not belong to a known user in this
+ realm.
+
+ o DIAMETER_ERROR_IDENTITIES_DONT_MATCH 5033
+ The value in one of the SIP-AOR AVPs is not allocated to the user
+ specified in the User-Name AVP.
+
+ o DIAMETER_ERROR_IDENTITY_NOT_REGISTERED 5034
+ A query for location information is received for a SIP AOR that
+ has not been registered before. The user to which this identity
+ belongs cannot be given service in this situation.
+
+ o DIAMETER_ERROR_ROAMING_NOT_ALLOWED 5035
+ The user is not allowed to roam to the visited network.
+
+ o DIAMETER_ERROR_IDENTITY_ALREADY_REGISTERED 5036
+ The identity being registered has already been assigned a server
+ and the registration status does not allow that it is overwritten.
+
+ o DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED 5037
+ The authentication scheme indicated in an authentication request
+ is not supported.
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 60]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ o DIAMETER_ERROR_IN_ASSIGNMENT_TYPE 5038
+ The SIP server address sent in the SIP-Server-URI AVP value of the
+ Diameter Server-Assignment-Request (SAR) command is the same SIP
+ server address that is currently assigned to the user name, but
+ the SIP-Server-Assignment-Type AVP is not allowed. For example,
+ the user is registered and the Server-Assignment-Request indicates
+ the assignment for an unregistered user.
+
+ o DIAMETER_ERROR_TOO_MUCH_DATA 5039
+ The Diameter peer in the SIP server receives more data than it can
+ accept. The SIP server cannot overwrite the already stored data.
+
+ o DIAMETER_ERROR_NOT SUPPORTED_USER_DATA 5040
+ The SIP server informs the Diameter server that the received
+ subscription data contained information that was not recognized or
+ supported.
+
+11. Authentication Details
+
+ Authenticating a user can occur through various mechanisms.
+ Currently HTTP Digest authentication is supported. The actual
+ authentication is performed in either the SIP server or the Diameter
+ server.
+
+ If the Diameter server wants to assure that authentication will take
+ place in the Diameter server (as opposed to a delegated
+ authentication taking place in the SIP server), it MUST NOT include a
+ Digest-HA1 AVP (part of the grouped SIP-Authenticate AVP, which in
+ turn is part of the SIP-Auth-Data-Item AVP) in a MAA message. The
+ Diameter server MAY include a pre-calculated Digest-HA1 AVP in the
+ MAA message if it wants to delegate authentication of the user to the
+ SIP server.
+
+ Note that on systems where the SIP User Agent is using HTTP Digest
+ authentication [RFC2617] inside of Transport Layer Security (TLS)
+ [RFC4346], where only the SIP proxy server has a certificate,
+ delegating authentication to the SIP server (by making Digest-HA1
+ available to the SIP server) might reduce the load on the Diameter
+ server.
+
+ When requesting authentication, the Diameter client indicates in the
+ SIP-Number-Auth-Items AVP value of a Diameter MAR message how many
+ authentication credentials are being requested. In the Diameter MAA
+ message, the Diameter server MAY include more than one
+ SIP-Auth-Data-Item AVP, but it is only useful for the Diameter client
+ if the Digest-QoP AVP was set to 'auth-int' (in the MAR message), and
+ if future authentications will have the same realm. When including
+ more than one SIP-Auth-Data-Item AVP, the Diameter server SHOULD
+
+
+
+Garcia-Martin, et al. Standards Track [Page 61]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ indicate how many instances of SIP-Auth-Data-Item AVPs are present
+ with the SIP-Number-Auth-Items AVP. This number may be different
+ from the one requested in the Diameter MAR message. If multiple
+ SIP-Auth-Data-Item AVPs are present, and their ordering is
+ significant, the Diameter server MUST include a SIP-Item-Number AVP
+ in each grouping to indicate the order. The
+ SIP-Authentication-Scheme AVP indicates "Digest" and the
+ SIP-Authenticate AVP contains data (typically a challenge of some
+ kind) that the user can use for her authentication. The grouped
+ SIP-Authorization AVP contains the AVPs that conform to the response
+ expected from the user.
+
+ If the Diameter server performs the authentication of the user, the
+ Diameter MAR message that the Diameter client sends to the Diameter
+ server MUST include all the authentication credentials supplied by
+ the SIP UA (there might be more than one credential, e.g., different
+ realms, authentication of proxies, etc.). Each credential is
+ inserted in a grouped SIP-Authorization AVP (part of the grouped
+ SIP-Auth-Data-Item AVP). The Diameter client MUST insert a
+ SIP-Number-Auth-Items AVP with the value set to the number of
+ credentials enclosed. If necessary, the Digest-Entity-Body-Hash AVP
+ will contain a hash of the body, needed to perform the
+ authentication. If the authentication is successful, the Diameter
+ MAA message will contain a Result-Code AVP indicating success, and if
+ necessary, the Diameter server MAY include one or more
+ SIP-Auth-Data-Item AVPs to provide further authentication credentials
+ to the SIP server. If the authentication is unsuccessful due to
+ missing credentials, the Diameter MAA message will include a
+ SIP-Auth-Data-Item AVP with the SIP-Authentication-Scheme and
+ SIP-Authenticate AVPs containing data (typically a challenge of some
+ kind) that the user can use to authenticate itself.
+
+ There are situations where a SIP request traverses several proxies,
+ and each of the proxies requests to authenticate the SIP UA. In this
+ situation, it is a valid scenario that a SIP request received at a
+ SIP server contains several sets of credentials. The 'realm'
+ directive in HTTP is the key that the Diameter client can use to
+ determine which credential is applicable. Also, none of the realms
+ may be of interest to the Diameter client, in which case the Diameter
+ client MUST consider that no credentials (of interest) were sent. In
+ any case, a Diameter client MUST send zero or exactly one credential
+ to the Diameter server. The Diameter client MUST choose the
+ credential based on the 'realm' directive in the
+ Authorization/Proxy-Authorization header field, and it MUST match the
+ realm of the Diameter client.
+
+ It must be noted that nonces are always generated in the Diameter
+ server.
+
+
+
+Garcia-Martin, et al. Standards Track [Page 62]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+12. Migration from RADIUS
+
+ RADIUS offers support for HTTP Digest authentication in the RADIUS
+ Extension for Digest Authentication [RFC4590]. A number of AVPs (the
+ Digest-* AVPs) of this Diameter SIP application are imported from the
+ RADIUS attributes namespace, thus making the migration from RADIUS to
+ Diameter smooth.
+
+ Note that the RADIUS Extension for Digest Authentication [RFC4590]
+ provides a more limited scope than this Diameter SIP application.
+ Specifically, the RADIUS extension for Digest Authentication merely
+ provides support for HTTP Digest authentication, whereas the Diameter
+ SIP application provides support for user location, profile
+ downloading and update, etc.
+
+ The following sections discuss several configurations in which a
+ gateway translates RADIUS to Diameter and vice versa.
+
+12.1. Gateway from RADIUS Client to Diameter Server
+
+ The gateway maps Access-Request messages to MAR request. If a RADIUS
+ Access-Request message contains at least one Digest-* attribute, the
+ gateway maps all Digest-* attributes to the AVPs of a Diameter
+ SIP-Authorization AVP, constructs a MAR message, and sends it to the
+ Diameter server. If the RADIUS Access-Request message does not
+ contain any Digest-* attribute, then the RADIUS client does not want
+ to apply HTTP Digest authentication, in which case, actions at the
+ gateway are outside the scope of this document.
+
+ The Diameter server responds with a MAA message. If the MAA message
+ contains a Result-Code AVP set to the value DIAMETER_MULTI_ROUND_AUTH
+ and contains challenge parameters in a SIP-Authenticate AVP, then the
+ gateway translates the AVPs of SIP-Authenticate AVP and puts the
+ resulting RADIUS attributes into an Access-Challenge message. It
+ sends the Access-Challenge message to the RADIUS client.
+
+ If the MAA message contains a SIP-Authentication-Info and a
+ Digest-Response AVP, the gateway converts these AVPs to the
+ corresponding RADIUS attributes and constructs a RADIUS message. If
+ the Result-Code AVP is DIAMETER_SUCCESS, an Access-Accept is sent.
+ In all other cases, an Access-Reject is sent.
+
+12.2. Gateway from Diameter Client to RADIUS Server
+
+ The Diameter client sends a Diameter MAR message to the gateway. If
+ the MAR message does not contain SIP-Auth-Data-Item AVPs, the gateway
+ constructs an Access-Request message and maps the SIP-AOR and
+ SIP-Method AVPs to RADIUS attributes. The gateway sends the
+
+
+
+Garcia-Martin, et al. Standards Track [Page 63]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ Access-Request message to the RADIUS server, which will respond with
+ an Access-Challenge. The gateway creates a MAA message with a
+ Result-Code AVP set to DIAMETER_MULTI_ROUND_AUTH and maps the
+ Digest-* attributes to Diameter AVPs in a SIP-Authenticate AVP. The
+ gateway sends the resulting MAA to the Diameter client, which will
+ respond with a new MAR.
+
+ The gateway checks the SIP-Auth-Data-Item AVPs of this MAR for an AVP
+ where the Digest-Realm AVP matches the locally configured realm
+ value. It takes the AVPs from this SIP-Auth-Data-Item AVP, converts
+ them into the corresponding RADIUS attributes and constructs a RADIUS
+ Access-Request message. The gateway sends the Access-Request message
+ to the RADIUS server. If the RADIUS server responds with an
+ Access-Accept message, the gateway converts the RADIUS attributes to
+ Diameter AVPs, constructs a MAA message with a Result-Code AVP set to
+ DIAMETER_SUCCESS and sends this message to the Diameter client. If
+ the RADIUS server responds with an Access-Reject message, the gateway
+ converts the RADIUS attributes to Diameter AVPs, constructs a MAA
+ message with a Result-Code AVP set to
+ DIAMETER_ERROR_IDENTITIES_DONT_MATCH, and sends this message to the
+ Diameter client.
+
+12.3. Known Limitations
+
+ As mentioned earlier, there is not a 100% match between the Diameter
+ SIP application and the RADIUS Extension for Digest Authentication
+ [RFC4590]. In particular, the RADIUS Extension for Digest
+ Authentication [RFC4590] does not offer equivalent functionality to
+ the Diameter UAR/UAA, SAR/SAA, LIR/LIA, RTR/RTA, and PPR/PPA messages
+ defined by this specification.
+
+13. IANA Considerations
+
+ This document serves as IANA registration request for a number of
+ items that should be registered in the AAA parameters registry.
+
+13.1. Application Identifier
+
+ This document defines a standards-track Application-ID that falls
+ into the Application Identifier standards-track address space defined
+ by RFC 3588 [RFC3588] Section 11.3. This Application-ID has been
+ registered in the Application IDs sub-registry of the AAA parameters
+ registry with the following data:
+
+ ID values Name Reference
+ ----------- ------------------------ ---------
+ 6 Diameter Session Initiation RFC 4740
+ Protocol (SIP) Application
+
+
+
+Garcia-Martin, et al. Standards Track [Page 64]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+13.2. Command Codes
+
+ This document defines new standard commands whose Command Codes are
+ to be allocated within the standard permanent Command Codes address
+ space defined in RFC 3588 [RFC3588] Section 11.2.1. These command
+ codes should be registered in the Command Codes sub-registry of the
+ AAA parameters registry.
+
+ Table 1 in Section 8 contains the detailed list of Command Code names
+ and values that are part of this Diameter application.
+
+13.3. AVP Codes
+
+ This document defines new standard AVPs, whose AVP Codes are to be
+ allocated within the AVP Codes address space defined in RFC 3588
+ [RFC3588] Section 11.4. These AVP codes have been registered in the
+ AVP Codes sub-registry of the AAA parameters registry.
+
+ Table 2 in Section 9 contains the detailed list of AVP names and AVP
+ codes that are part of this Diameter application.
+
+13.4. Additional Values for the Result-Code AVP Value
+
+ This document defines new standard Result-Code AVP values to be
+ allocated within the Result-Code AVP address space defined in RFC
+ 3588 [RFC3588] Section 14.4.1. These values are listed in the
+ Result-Code AVP values section of the AVP Specific Values
+ sub-registry of the AAA parameters registry.
+
+ Section 10.1.1 lists the new Result-Code AVP values that fall into
+ the success category, according to RFC 3588 [RFC3588] Section 7.1.2.
+
+ Section 10.1.2 lists the new Result-Code AVP values that fall into
+ the transient failures category, according to RFC 3588 [RFC3588]
+ Section 7.1.4.
+
+ Section 10.1.3 lists the new Result-Code AVP values that fall into
+ the permanent failures category, according to RFC 3588 [RFC3588]
+ Section 7.1.5.
+
+
+
+
+
+
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 65]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+13.5. Creation of the SIP-Server-Assignment-Type Section in the AAA
+ Registry
+
+ This document defines a new SIP-Server-Assignment-Type AVP (see
+ Section 9.4). This AVP is of type Enumerated. We define an initial
+ set of values that should be registered by IANA. IANA should create
+ a new "SIP-Sever-Assignment-Type AVP values" section under the AVP
+ Specific Values sub-registry of the AAA parameters registry. The
+ initial list of values is listed in Section 9.4.
+
+13.6. Creation of the SIP-Authentication-Scheme Section in the AAA
+ Registry
+
+ This document defines a new SIP-Authentication-Scheme AVP (see
+ Section 9.5.1). This AVP is of type Enumerated. We currently define
+ a single value that should be registered by IANA. IANA should create
+ a new "SIP-Authentication-Scheme AVP values" section under the AVP
+ Specific Values sub-registry of the AAA parameters registry. The
+ initial list of values is included in Section 9.5.1.
+
+13.7. Creation of the SIP-Reason-Code Section in the AAA Registry
+
+ This document defines a new SIP-Reason-Code AVP (see Section 9.7.1).
+ This AVP is of type Enumerated. We define an initial set of values
+ that should be registered by IANA. IANA should create a new
+ "SIP-Reason-Code AVP values" section under the AVP Specific Values
+ sub-registry of the AAA parameters registry. The initial list of
+ values is listed in Section 9.7.1.
+
+13.8. Creation of the SIP-User-Authorization-Type Section in the AAA
+ Registry
+
+ This document defines a new SIP-User-Authorization-Type AVP (see
+ Section 9.10). This AVP is of type Enumerated. We define an initial
+ set of values that should be registered by IANA. IANA should create
+ a new "SIP-User-Authorization-Type AVP values" section under the AVP
+ Specific Values sub-registry of the AAA parameters registry. The
+ initial list of values is listed in Section 9.10.
+
+13.9. Creation of the SIP-User-Data-Already-Available Section in the
+ AAA Registry
+
+ This document defines a new SIP-User-Data-Already-Available AVP (see
+ Section 9.13). This AVP is of type Enumerated. We define an initial
+ set of values which should be registered by IANA. IANA should create
+ a new "SIP-User-Data-Already-Available AVP values" section under the
+ AVP Specific Values sub-registry of the AAA parameters registry. The
+ initial list of values is listed in Section 9.13.
+
+
+
+Garcia-Martin, et al. Standards Track [Page 66]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+14. Security Considerations
+
+ This memo does not describe a stand-alone protocol, but a particular
+ application for the Diameter protocol [RFC3588]. Consequently, all
+ the security considerations applicable to Diameter automatically
+ apply to this memo. In particular, Section 13 of RFC 3588 applies to
+ this memo.
+
+ This Diameter SIP application allows a Diameter client to use the
+ properties of HTTP Digest authentication [RFC2617] by evaluating or
+ sending to the Diameter server the credentials supplied by a user.
+ The discussion of HTTP Digest authentication in Section 4 of RFC 2617
+ [RFC2617] is also applicable to this memo.
+
+ This Diameter SIP application also allows a Diameter client to use
+ the properties of HTTP Digest authentication using AKA [RFC3310] by
+ evaluating or sending to the Diameter server the credentials supplied
+ by a user. Section 5 of RFC 3310 [RFC3310] is also applicable to
+ this memo.
+
+14.1. Final Authentication Check in the Diameter Client/SIP Server
+
+ The Diameter SIP application can be configured to operate in a
+ scenario where the final authentication check is performed in the
+ Diameter client (SIP server). There are a number of security
+ considerations associated to it; all of them are consequences of the
+ requirement to transfer H(A1) from the Diameter server to the
+ Diameter client:
+
+ o Both Diameter client and server must trust each other, such as
+ when both client and server belong to the same administrative
+ domain.
+
+ o To avoid eavesdroppers, the transport protocol between the
+ Diameter client and server MUST be secured. RFC 3588 [RFC3588]
+ specifies TLS [RFC4346] and IPsec as possible transport protection
+ mechanisms for Diameter.
+
+ Due to these security considerations, it is RECOMMENDED to configure
+ the Diameter SIP application to operate in the mode where the final
+ authentication check is performed in the Diameter server.
+
+
+
+
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 67]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+15. Contributors
+
+ The authors would like to thank the following contributors who made
+ substantial contributions to this work:
+
+ Pete McCann Lucent
+
+ Jaakko Rajaniemi Nokia
+
+ Wolfgang Beck (Deutsche Telekom AG) provided the text in Section 12,
+ "Migration from RADIUS".
+
+16. Acknowledgements
+
+ The authors would like to thank Tony Johansson and Kevin Purser for
+ their invaluable contribution to the start-up of this application and
+ the continuous progress. The authors would like to thank Daniel
+ Warren, Jayshree Bharatia, Kuntal Chowdhury, Jari Arkko, Avi Lior,
+ Wolfgang Beck, Ulrich Wiehe, Cullen Jennings, Anu Leinonen, Glen
+ Zorn, German Blanco, Mikko Aittola, Bert Wijnen, and Sam Hartman for
+ their reviews and valuable comments.
+
+ The Diameter SIP application is based on the Diameter application for
+ the Cx interface of the 3GPP IP Multimedia Subsystem [3GPP.29.229].
+ The authors would like to thank 3GPP Working Group CN4 for this work.
+
+17. References
+
+17.1. Normative References
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2617] Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence,
+ S., Leach, P., Luotonen, A., and L. Stewart, "HTTP
+ Authentication: Basic and Digest Access
+ Authentication", RFC 2617, June 1999.
+
+ [RFC3261] Rosenberg, J., Schulzrinne, H., Camarillo, G.,
+ Johnston, A., Peterson, J., Sparks, R., Handley, M.,
+ and E. Schooler, "SIP: Session Initiation Protocol",
+ RFC 3261, June 2002.
+
+ [RFC3310] Niemi, A., Arkko, J., and V. Torvinen, "Hypertext
+ Transfer Protocol (HTTP) Digest Authentication Using
+ Authentication and Key Agreement (AKA)", RFC 3310,
+ September 2002.
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 68]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ [RFC3588] Calhoun, P., Loughney, J., Guttman, E., Zorn, G., and
+ J. Arkko, "Diameter Base Protocol", RFC 3588,
+ September 2003.
+
+ [RFC4590] Sterman, B., Sadolevsky, D., Schwartz, D., Williams,
+ D., and W. Beck, "RADIUS Extension for Digest
+ Authentication", RFC 4590, July 2006.
+
+17.2. Informative References
+
+ [RFC4346] Dierks, T. and E. Rescorla, "The Transport Layer
+ Security (TLS) Protocol Version 1.1", RFC 4346, April
+ 2006.
+
+ [RFC3263] Rosenberg, J. and H. Schulzrinne, "Session Initiation
+ Protocol (SIP): Locating SIP Servers", RFC 3263,
+ June 2002.
+
+ [RFC3680] Rosenberg, J., "A Session Initiation Protocol (SIP)
+ Event Package for Registrations", RFC 3680,
+ March 2004.
+
+ [RFC3880] Lennox, J., Wu, X., and H. Schulzrinne, "Call
+ Processing Language (CPL): A Language for User Control
+ of Internet Telephony Services", RFC 3880,
+ October 2004.
+
+ [RFC4004] Calhoun, P., Johansson, T., Perkins, C., Hiller, T.,
+ and P. McCann, "Diameter Mobile IPv4 Application",
+ RFC 4004, August 2005.
+
+ [RFC4005] Calhoun, P., Zorn, G., Spence, D., and D. Mitton,
+ "Diameter Network Access Server Application",
+ RFC 4005, August 2005.
+
+ [RFC4006] Hakala, H., Mattila, L., Koskinen, J-P., Stura, M.,
+ and J. Loughney, "Diameter Credit-Control
+ Application", RFC 4006, August 2005.
+
+ [3GPP.29.229] 3GPP, "Cx and Dx interfaces based on the Diameter
+ protocol; Protocol details", 3GPP TS 29.229 5.12.0,
+ June 2006.
+
+ [JSR-000116] Java Community Process, "SIP Servlet API Specification
+ 1.0 Final Release", JSR 000116, March 2003.
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 69]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+Authors' Addresses
+
+ Miguel A. Garcia-Martin (Editor)
+ Nokia
+ P.O. Box 407
+ NOKIA GROUP, FIN 00045
+ Finland
+
+ Phone: +358 50 480 4586
+
+
+ Maria-Carmen Belinchon
+ Ericsson
+ Via de los Poblados 13
+ Madrid 28033
+ Spain
+
+ Phone: +34 91 339 3535
+
+
+ Miguel A. Pallares-Lopez
+ Ericsson
+ Via de los Poblados 13
+ Madrid 28033
+ Spain
+
+ Phone: +34 91 339 4222
+
+
+ Carolina Canales-Valenzuela
+ Ericsson
+ Via de los Poblados 13
+ Madrid 28033
+ Spain
+
+ Phone: +34 91 339 2680
+
+
+
+
+
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 70]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+ Kalle Tammi
+ Nokia
+ P.O.Box 785
+ Tampere 33101
+ Finland
+
+ Phone: +358 40 505 8670
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 71]
+
+RFC 4740 Diameter SIP Application November 2006
+
+
+Full Copyright Statement
+
+ Copyright (C) The IETF Trust (2006).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST,
+ AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT
+ THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY
+ IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+Garcia-Martin, et al. Standards Track [Page 72]
+
diff --git a/lib/diameter/doc/standard/rfc5447.txt b/lib/diameter/doc/standard/rfc5447.txt
new file mode 100644
index 0000000000..ec556ccc9f
--- /dev/null
+++ b/lib/diameter/doc/standard/rfc5447.txt
@@ -0,0 +1,955 @@
+
+
+
+
+
+
+Network Working Group J. Korhonen, Ed.
+Request for Comments: 5447 Nokia Siemens Networks
+Category: Standards Track J. Bournelle
+ Orange Labs
+ H. Tschofenig
+ Nokia Siemens Networks
+ C. Perkins
+ WiChorus
+ K. Chowdhury
+ Starent Networks
+ February 2009
+
+
+ Diameter Mobile IPv6:
+ Support for Network Access Server to Diameter Server Interaction
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (c) 2009 IETF Trust and the persons identified as the
+ document authors. All rights reserved.
+
+ This document is subject to BCP 78 and the IETF Trust's Legal
+ Provisions Relating to IETF Documents (http://trustee.ietf.org/
+ license-info) in effect on the date of publication of this document.
+ Please review these documents carefully, as they describe your rights
+ and restrictions with respect to this document.
+
+Abstract
+
+ A Mobile IPv6 node requires a home agent address, a home address, and
+ a security association with its home agent before it can start
+ utilizing Mobile IPv6. RFC 3775 requires that some or all of these
+ parameters be statically configured. Mobile IPv6 bootstrapping work
+ aims to make this information dynamically available to the mobile
+ node. An important aspect of the Mobile IPv6 bootstrapping solution
+ is to support interworking with existing Authentication,
+ Authorization, and Accounting (AAA) infrastructures. This document
+ describes MIPv6 bootstrapping using the Diameter Network Access
+ Server to home AAA server interface.
+
+
+
+
+Korhonen, et al. Standards Track [Page 1]
+
+RFC 5447 Diameter MIPv6 NAS-to-HAAA Interaction February 2009
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. Terminology and Abbreviations . . . . . . . . . . . . . . . . 3
+ 3. Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
+ 4. Commands, Attribute-Value Pairs, and Advertising
+ Application Support . . . . . . . . . . . . . . . . . . . . . 6
+ 4.1. Advertising Application Support . . . . . . . . . . . . . 6
+ 4.2. Attribute-Value Pair Definitions . . . . . . . . . . . . . 6
+ 4.2.1. MIP6-Agent-Info AVP . . . . . . . . . . . . . . . . . 6
+ 4.2.2. MIP-Home-Agent-Address AVP . . . . . . . . . . . . . . 7
+ 4.2.3. MIP-Home-Agent-Host AVP . . . . . . . . . . . . . . . 7
+ 4.2.4. MIP6-Home-Link-Prefix AVP . . . . . . . . . . . . . . 8
+ 4.2.5. MIP6-Feature-Vector AVP . . . . . . . . . . . . . . . 8
+ 5. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
+ 5.1. Home Agent Assignment by the NAS . . . . . . . . . . . . . 10
+ 5.2. Home Agent Assignment by the Diameter Server . . . . . . . 11
+ 5.3. Home Agent Assignment by the NAS or Diameter Server . . . 11
+ 6. Attribute-Value Pair Occurrence Tables . . . . . . . . . . . . 12
+ 7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 13
+ 7.1. Registration of New AVPs . . . . . . . . . . . . . . . . . 13
+ 7.2. New Registry: Mobility Capability . . . . . . . . . . . . 13
+ 8. Security Considerations . . . . . . . . . . . . . . . . . . . 14
+ 9. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 14
+ 10. References . . . . . . . . . . . . . . . . . . . . . . . . . . 15
+ 10.1. Normative References . . . . . . . . . . . . . . . . . . . 15
+ 10.2. Informative References . . . . . . . . . . . . . . . . . . 15
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 2]
+
+RFC 5447 Diameter MIPv6 NAS-to-HAAA Interaction February 2009
+
+
+1. Introduction
+
+ The Mobile IPv6 (MIPv6) specification [RFC3775] requires a mobile
+ node (MN) to perform registration with a home agent (HA) with
+ information about its current point of attachment (care-of address).
+ The HA creates and maintains the binding between the MN's home
+ address and the MN's care-of address.
+
+ In order to register with an HA, the MN needs to know some
+ information, such as the home link prefix, the HA address, the home
+ address(es), the home link prefix length, and security-association-
+ related information.
+
+ The aforementioned information may be statically configured.
+ However, static provisioning becomes an administrative burden for an
+ operator. Moreover, it does not address load balancing, failover,
+ opportunistic home link assignment, or assignment of local HAs in
+ close proximity to the MN. Also, the ability to react to sudden
+ environmental or topological changes is minimal. Static provisioning
+ may not be desirable, in light of these limitations.
+
+ Dynamic assignment of MIPv6 home registration information is a
+ desirable feature for ease of deployment and network maintenance.
+ For this purpose, the AAA infrastructure, which is used for access
+ authentication, can be leveraged to assign some or all of the
+ necessary parameters. The Diameter server in the Access Service
+ Provider's (ASP's) or Mobility Service Provider's (MSP's) network may
+ return these parameters to the AAA client. Regarding the
+ bootstrapping procedures, the AAA client might either be the Network
+ Access Server, in case of the integrated scenario, or the HA, in case
+ of the split scenario [RFC5026]. The terms "integrated" and "split"
+ are described in the following terminology section and were
+ introduced in [RFC4640] and [AAA].
+
+2. Terminology and Abbreviations
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [RFC2119].
+
+ General mobility terminology can be found in [RFC3753]. The
+ following additional terms are either borrowed from [RFC4640] or
+ [RFC5026] or are introduced in this document:
+
+ Access Service Authorizer (ASA):
+
+ A network operator that authenticates an MN and establishes the
+ MN's authorization to receive Internet service.
+
+
+
+Korhonen, et al. Standards Track [Page 3]
+
+RFC 5447 Diameter MIPv6 NAS-to-HAAA Interaction February 2009
+
+
+ Access Service Provider (ASP):
+
+ A network operator that provides direct IP packet-forwarding to
+ and from the MN.
+
+ Mobility Service Authorizer (MSA):
+
+ A service provider that authorizes MIPv6 service.
+
+ Mobility Service Provider (MSP):
+
+ A service provider that provides MIPv6 service. In order to
+ obtain such service, the MN must be authenticated and authorized
+ to do so.
+
+ Split Scenario:
+
+ A scenario where the mobility service and the network access
+ service are authorized by different entities.
+
+ Integrated Scenario:
+
+ A scenario where the mobility service and the network access
+ service are authorized by the same entity.
+
+ Network Access Server (NAS):
+
+ A device that provides an access service for a user to a network.
+
+ Home AAA (HAAA):
+
+ An Authentication, Authorization, and Accounting server located in
+ the user's home network, i.e., in the home realm.
+
+ Local AAA (LAAA):
+
+ An Authentication, Authorization, and Accounting proxy located in
+ the local (ASP) network.
+
+ Visited AAA (VAAA):
+
+ An Authentication, Authorization, and Accounting proxy located in
+ a visited network, i.e., in the visited realm. In a roaming case,
+ the local Diameter proxy has the VAAA role (see Figure 1).
+
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 4]
+
+RFC 5447 Diameter MIPv6 NAS-to-HAAA Interaction February 2009
+
+
+3. Overview
+
+ This document addresses the Authentication, Authorization, and
+ Accounting (AAA) functionality required for the MIPv6 bootstrapping
+ solutions outlined in [RFC4640], and focuses on the Diameter-based
+ AAA functionality for the NAS-to-HAAA (home AAA) server
+ communication.
+
+ In the integrated scenario, MIPv6 bootstrapping is provided as part
+ of the network access authentication procedure. Figure 1 shows the
+ participating entities.
+
+ +---------------------------+ +-----------------+
+ |Access Service Provider | |ASA/MSA/(MSP) |
+ |(Mobility Service Provider)| | |
+ | | | |
+ | +--------+ | | +--------+ |
+ | |Local | Diameter | | |Home | |
+ | |Diameter|<---------------------->|Diameter| |
+ | |Proxy | (*) | | |Server | |
+ | +--------+ | | +--------+ |
+ | ^ ^ | | ^ |
+ | | | | | |(+) |
+ | | | | | | |
+ | Diameter | | v |
+ | | |(+) +-------+ | | +-------+ |
+ | | | |Home | | | |Home | |
+ | | +-------->|Agent | | | |Agent | |
+ | (*)| |in ASP | | | |in MSP | |
+ | v +-------+ | | +-------+ |
+ +-------+ IEEE | +-----------+ +-------+ | +-----------------+
+ |Mobile | 802.1X | |NAS/Relay | |DHCPv6 | |
+ |Node |------------|Diameter |---|Server | |
+ | | PANA, | |Client |(+)| | |
+ +-------+ IKEv2, | +-----------+ +-------+ |
+ DHCP,... +---------------------------+
+ (+)
+
+ Legend:
+ (*): Functionality in scope of this specification.
+ (+): Extensions described in other documents.
+
+ Figure 1: Mobile IPv6 Bootstrapping in the Integrated Scenario
+
+ In a typical MIPv6 access scenario, an MN is attached to an ASP's
+ network. During the network attachment procedure, the MN interacts
+ with the NAS/Diameter client. Subsequently, the NAS/Diameter client
+ interacts with the Diameter server over the NAS-to-HAAA interface.
+
+
+
+Korhonen, et al. Standards Track [Page 5]
+
+RFC 5447 Diameter MIPv6 NAS-to-HAAA Interaction February 2009
+
+
+ When the Diameter server performs the authentication and
+ authorization for network access, it also determines whether the user
+ is authorized for the MIPv6 service. Based on the MIPv6 service
+ authorization and the user's policy profile, the Diameter server may
+ return several MIPv6 bootstrapping-related parameters to the NAS.
+ The NAS-to-HAAA interface described in this document is not tied to
+ the Dynamic Host Configuration Protocol for IPv6 (DHCPv6) as the only
+ mechanism to convey MIPv6-related configuration parameters from the
+ NAS/Diameter client to the mobile node.
+
+ While this specification addresses the bootstrapping of MIPv6 HA
+ information and possibly the assignment of the home link prefix, it
+ does not address how the Security Association (SA) between the MN and
+ the HA for MIPv6 purposes is created. The creation or the use of the
+ SA between the MN and the HA takes places after the procedures
+ described in this specification, and therefore are out of scope.
+
+4. Commands, Attribute-Value Pairs, and Advertising Application Support
+
+4.1. Advertising Application Support
+
+ This document does not define a new application. On the other hand,
+ it defines a number of attribute-value pairs (AVPs) used in the
+ interface between NAS to HAAA for the integrated scenario of MIPv6
+ bootstrapping. These AVPs can be used with any present and future
+ Diameter applications, where permitted by the command ABNF. The
+ examples using existing applications and their commands in the
+ following sections are for informational purposes only. The examples
+ in this document reuse the Extensible Authentication Protocol (EAP)
+ [RFC4072] application and its respective commands.
+
+4.2. Attribute-Value Pair Definitions
+
+4.2.1. MIP6-Agent-Info AVP
+
+ The MIP6-Agent-Info AVP (AVP code 486) is of type Grouped and
+ contains necessary information to assign an HA to the MN. When the
+ MIP6-Agent-Info AVP is present in a message, it MUST contain either
+ the MIP-Home-Agent-Address AVP, the MIP-Home-Agent-Host AVP, or both
+ AVPs. The grouped AVP has the following modified ABNF (as defined in
+ [RFC3588]):
+
+ MIP6-Agent-Info ::= < AVP-Header: 486 >
+ *2[ MIP-Home-Agent-Address ]
+ [ MIP-Home-Agent-Host ]
+ [ MIP6-Home-Link-Prefix ]
+ * [ AVP ]
+
+
+
+
+Korhonen, et al. Standards Track [Page 6]
+
+RFC 5447 Diameter MIPv6 NAS-to-HAAA Interaction February 2009
+
+
+ If both the MIP-Home-Agent-Address and MIP-Home-Agent-Host APVs are
+ present in the MIP6-Agent-Info, the MIP-Home-Agent-Address SHOULD
+ have a precedence over the MIP-Home-Agent-Host. The reason for this
+ recommendation is that the MIP-Home-Agent-Address points to a
+ specific home agent, whereas the MIP-Home-Agent-Host may point to a
+ group of HAs located within the same realm. A Diameter client or
+ agent may use the MIP-Home-Agent-Host AVP, for instance, to find out
+ in which realm the HA is located.
+
+ The ABNF allows returning up to two MIPv6 HA addresses. This is a
+ useful feature for deployments where the HA has both IPv6 and IPv4
+ addresses, and particularly addresses Dual Stack Mobile IPv6
+ (DSMIPv6) deployment scenarios [DSMIPv6].
+
+ The MIP6-Agent-Info AVP MAY also be attached by the NAS or by the
+ intermediating Diameter proxies in a request message when sent to the
+ Diameter server as a hint of a locally assigned HA. This AVP MAY
+ also be attached by the intermediating Diameter proxies in a reply
+ message from the Diameter server, if locally assigned HAs are
+ authorized by the Diameter server. There MAY be multiple instances
+ of the MIP6-Agent-Info AVP in Diameter messages, for example, in
+ cases where the NAS receives HA information from an MN's home network
+ and locally allocated HA information from the visited network. See
+ Section 4.2.5 for further discussion on possible scenarios.
+
+4.2.2. MIP-Home-Agent-Address AVP
+
+ The MIP-Home-Agent-Address AVP (AVP Code 334 [RFC4004]) is of type
+ Address and contains the IPv6 or IPv4 address of the MIPv6 HA. The
+ Diameter server MAY decide to assign an HA to the MN that is in close
+ proximity to the point of attachment (e.g., determined by the NAS-
+ Identifier AVP). There may be other reasons for dynamically
+ assigning HAs to the MN, for example, to share the traffic load.
+
+4.2.3. MIP-Home-Agent-Host AVP
+
+ The MIP-Home-Agent-Host AVP (AVP Code 348 [RFC4004]) is of type
+ Grouped and contains the identity of the assigned MIPv6 HA. Both the
+ Destination-Realm and the Destination-Host AVPs of the HA are
+ included in the grouped AVP. The usage of the MIP-Home-Agent-Host
+ AVP is equivalent to the MIP-Home-Agent-Address AVP but offers an
+ additional level of indirection by using the DNS infrastructure. The
+ Destination-Host AVP is used to identify an HA, and the Destination-
+ Realm AVP is used to identify the realm where the HA is located.
+
+ Depending on the actual deployment and DNS configuration, the
+ Destination-Host AVP MAY represent one or more home agents. It is
+ RECOMMENDED that the Destination-Host AVP identifies exactly one HA.
+
+
+
+Korhonen, et al. Standards Track [Page 7]
+
+RFC 5447 Diameter MIPv6 NAS-to-HAAA Interaction February 2009
+
+
+ It is RECOMMENDED that the MIP-Home-Agent-Host AVP is always included
+ in the MIP6-Agent-Info AVP. In this way, the HA can be associated
+ with the corresponding realm of the Diameter entity that added the
+ MIP6-Agent-Info AVP using the Destination-Realm AVP, which is
+ included in the MIP-Home-Agent-Host AVP.
+
+4.2.4. MIP6-Home-Link-Prefix AVP
+
+ The MIP6-Home-Link-Prefix AVP (AVP Code 125) is of type OctetString
+ and contains the Mobile IPv6 home network prefix information in a
+ network byte order. The home network prefix MUST be encoded as the
+ 8-bit prefix length information (one octet) followed by the 128-bit
+ field (16 octets) for the available home network prefix. The
+ trailing bits of the IPv6 prefix after the prefix length bits MUST be
+ set to zero (e.g., if the prefix length is 60, then the remaining 68
+ bits MUST be set to zero).
+
+ The HAAA MAY act as a central entity managing prefixes for MNs. In
+ this case, the HAAA returns to the NAS the prefix allocated to the
+ MN. The NAS/ASP then delivers the home link prefix to the MN using,
+ e.g., mechanisms described in [INTEGRATED]. The NAS/ASP MAY propose
+ to the HAAA a specific prefix to allocate to the MN by including the
+ MIP6-Home-Link-Prefix AVP in the request message. However, the HAAA
+ MAY override the prefix allocation hint proposed by the NAS/ASP and
+ return a different prefix in the response message.
+
+4.2.5. MIP6-Feature-Vector AVP
+
+ The MIP6-Feature-Vector AVP (AVP Code 124) is of type Unsigned64 and
+ contains a 64-bit flags field of supported capabilities of the NAS/
+ ASP. Sending and receiving the MIP6-Feature-Vector AVP with value 0
+ MUST be supported, although that does not provide much guidance about
+ specific needs of bootstrapping.
+
+ The NAS MAY include this AVP to indicate capabilities of the NAS/ASP
+ to the Diameter server. For example, the NAS may indicate that a
+ local HA can be provided. Similarly, the Diameter server MAY include
+ this AVP to inform the NAS/ASP about which of the NAS/ASP indicated
+ capabilities are supported or authorized by the ASA/MSA(/MSP).
+
+ The following capabilities are defined in this document:
+
+
+
+
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 8]
+
+RFC 5447 Diameter MIPv6 NAS-to-HAAA Interaction February 2009
+
+
+ MIP6_INTEGRATED (0x0000000000000001)
+
+ When this flag is set by the NAS, it means that the Mobile IPv6
+ integrated scenario bootstrapping functionality is supported by
+ the NAS. When this flag is set by the Diameter server, then the
+ Mobile IPv6 integrated scenario bootstrapping is supported by the
+ Diameter server.
+
+ LOCAL_HOME_AGENT_ASSIGNMENT (0x0000000000000002)
+
+ When this flag is set in the request message, a local home agent
+ outside the home realm is requested and may be assigned to the MN.
+ When this flag is set by the Diameter server in the answer
+ message, then the assignment of local HAs is authorized by the
+ Diameter server.
+
+ A local HA may be assigned by the NAS, LAAA, or VAAA depending on
+ the network architecture and the deployment.
+
+ The following examples show how the LOCAL_HOME_AGENT_ASSIGNMENT
+ (referred to as LOCAL-bit in the examples) capability and the MIP-
+ Agent-Info AVP (referred to as HA-Info in the examples) are used to
+ assign HAs -- either a local HA (L-HA) or a home network HA (H-HA).
+ Below are examples of request message combinations as seen by the
+ HAAA:
+
+ LOCAL-bit HA-Info Meaning
+
+ 0 - ASP or [LV]AAA is not able to assign an L-HA.
+ 0 L-HA Same as above. HA-Info must be ignored.
+ 1 - ASP or [LV]AAA can/wishes to assign an L-HA.
+ 1 L-HA Same as above but the ASP or [LV]AAA also
+ provides a hint of the assigned L-HA.
+
+ The same as above but for answer message combinations as seen by the
+ NAS:
+
+ LOCAL-bit HA-Info Meaning
+
+ 0 - No HA assignment allowed for HAAA or [LV]AAA.
+ 0 H-HA L-HA is not allowed. HAAA assigns an H-HA.
+ 1 - L-HA is allowed. No HAAA- or [LV]AAA-assigned HA.
+ 1 L-HA L-HA is allowed. [LV]AAA also assigns an L-HA.
+ 1 H-HA L-HA is allowed. HAAA also assigns an HA.
+ 1 H-HA L-HA is allowed. HAAA assigns an H-HA and
+ + L-HA [LV]AAA also assigns an L-HA.
+
+ An NAS should expect to receive multiple MIP6-Agent-Info AVPs.
+
+
+
+Korhonen, et al. Standards Track [Page 9]
+
+RFC 5447 Diameter MIPv6 NAS-to-HAAA Interaction February 2009
+
+
+5. Examples
+
+5.1. Home Agent Assignment by the NAS
+
+ In this scenario, we consider the case where the NAS wishes to
+ allocate a local HA to the MN. The NAS will also inform the Diameter
+ server about the HA address it has assigned to the visiting MN (e.g.,
+ 2001:db8:1:c020::1). The Diameter-EAP-Request message, therefore,
+ has the MIP6-Feature-Vector with the LOCAL_HOME_AGENT_ASSIGNMENT and
+ the MIP6_INTEGRATED set. The MIP6-Agent-Info AVP contains the MIP-
+ Home-Agent-Address AVP with the address of the proposed HA.
+
+ Diameter
+ NAS/VAAA Server
+ | |
+ | Diameter-EAP-Request |
+ | MIP6-Feature-Vector=(LOCAL_HOME_AGENT_ASSIGNMENT |
+ | | MIP6_INTEGRATED) |
+ | MIP6-Agent-Info{ |
+ | MIP-Home-Agent-Address(2001:db8:1:c020::1)} |
+ | } |
+ | Auth-Request-Type=AUTHORIZE_AUTHENTICATE |
+ | EAP-Payload(EAP Start) |
+ |---------------------------------------------------------------->|
+ | |
+ | |
+ : ...more EAP Request/Response pairs... :
+ | |
+ | |
+ | Diameter-EAP-Answer |
+ | MIP6-Feature-Vector=(LOCAL_HOME_AGENT_ASSIGNMENT |
+ | | MIP6_INTEGRATED) |
+ | Result-Code=DIAMETER_SUCCESS |
+ | EAP-Payload(EAP Success) |
+ | EAP-Master-Session-Key |
+ | (authorization AVPs) |
+ | ... |
+ |<----------------------------------------------------------------|
+ | |
+
+ Figure 2: Home Agent Assignment by the NAS
+
+ Depending on the Diameter server's configuration and the user's
+ subscription profile, the Diameter server either accepts or rejects
+ the local HA allocated by the NAS. In our example, the Diameter
+ server accepts the proposal, and the MIP6-Feature-Vector AVP with
+ LOCAL_HOME_AGENT_ASSIGNMENT flag (together with the MIP6_INTEGRATED
+ flag) is set and returned to the NAS.
+
+
+
+Korhonen, et al. Standards Track [Page 10]
+
+RFC 5447 Diameter MIPv6 NAS-to-HAAA Interaction February 2009
+
+
+5.2. Home Agent Assignment by the Diameter Server
+
+ In this scenario, we consider the case where the NAS supports the
+ Diameter MIPv6 integrated scenario as defined in this document, but
+ does not offer local HA assignment. Hence, the MIP6-Feature-Vector
+ AVP only has the MIP6_INTEGRATED flag set. The Diameter server
+ allocates an HA to the mobile node and conveys the address in the
+ MIP-Home-Agent-Address AVP that is encapsulated in the MIP6-Agent-
+ Info AVP. Additionally, the MIP6-Feature-Vector AVP has the
+ MIP6_INTEGRATED flag set.
+
+ Diameter
+ NAS Server
+ | |
+ | Diameter-EAP-Request |
+ | MIP6-Feature-Vector=(MIP6_INTEGRATED) |
+ | Auth-Request-Type=AUTHORIZE_AUTHENTICATE |
+ | EAP-Payload(EAP Start) |
+ |---------------------------------------------------------------->|
+ | |
+ | |
+ : ...more EAP Request/Response pairs... :
+ | |
+ | |
+ | Diameter-EAP-Answer |
+ | MIP6-Agent-Info{ |
+ | MIP-Home-Agent-Address(2001:db8:6000:302::1) |
+ | } |
+ | MIP6-Feature-Vector=(MIP6_INTEGRATED) |
+ | Result-Code=DIAMETER_SUCCESS |
+ | EAP-Payload(EAP Success) |
+ | EAP-Master-Session-Key |
+ | (authorization AVPs) |
+ | ... |
+ |<----------------------------------------------------------------|
+ | |
+
+ Figure 3: Home Agent Assignment by the Diameter Server
+
+5.3. Home Agent Assignment by the NAS or Diameter Server
+
+ This section shows another message flow for the MIPv6 integrated
+ scenario bootstrapping where the NAS informs the Diameter server that
+ it is able to locally assign an HA to the MN. The Diameter server is
+ able to provide an HA to the MN but also authorizes the assignment of
+ the local HA. The Diameter server then replies to the NAS with
+ HA-related bootstrapping information.
+
+
+
+
+Korhonen, et al. Standards Track [Page 11]
+
+RFC 5447 Diameter MIPv6 NAS-to-HAAA Interaction February 2009
+
+
+ Whether the NAS/ASP then offers a locally assigned HA or the
+ Diameter-server-assigned HA to the MN is, in this example, based on
+ the local ASP policy.
+
+ Diameter
+ NAS/VAAA Server
+ | |
+ | Diameter-EAP-Request |
+ | MIP6-Feature-Vector=(LOCAL_HOME_AGENT_ASSIGNMENT |
+ | | MIP6_INTEGRATED) |
+ | MIP6-Agent-Info{ |
+ | MIP-Home-Agent-Address(2001:db8:1:c020::1)} |
+ | } |
+ | Auth-Request-Type=AUTHORIZE_AUTHENTICATE |
+ | EAP-Payload(EAP Start) |
+ |---------------------------------------------------------------->|
+ | |
+ | |
+ : ...more EAP Request/Response pairs... :
+ | |
+ | |
+ | Diameter-EAP-Answer |
+ | MIP6-Agent-Info{ |
+ | MIP-Home-Agent-Address(2001:db8:6000:302::1)} |
+ | MIP6-Feature-Vector=(LOCAL_HOME_AGENT_ASSIGNMENT |
+ | | MIP6_INTEGRATED) |
+ | Result-Code=DIAMETER_SUCCESS |
+ | EAP-Payload(EAP Success) |
+ | EAP-Master-Session-Key |
+ | (authorization AVPs) |
+ | ... |
+ |<----------------------------------------------------------------|
+ | |
+
+ Figure 4: Home Agent Assignment by the NAS or Diameter Server
+
+ If the Diameter server does not allow the MN to use a locally
+ assigned HA, the Diameter server returns to the MN the MIP6-Feature-
+ Vector AVP with the LOCAL_HOME_AGENT_ASSIGNMENT bit unset and the HA
+ address it allocated.
+
+6. Attribute-Value Pair Occurrence Tables
+
+ Figure 5 lists the MIPv6 bootstrapping NAS-to-HAAA interface AVPs
+ along with a specification determining how many of each new AVP may
+ be included in a Diameter command. They may be present in any
+ Diameter application request and answer commands, where permitted by
+ the command ABNF.
+
+
+
+Korhonen, et al. Standards Track [Page 12]
+
+RFC 5447 Diameter MIPv6 NAS-to-HAAA Interaction February 2009
+
+
+ +-----------+
+ | Command |
+ |-----+-----+
+ Attribute Name | Req | Ans |
+ -------------------------------|-----+-----|
+ MIP6-Agent-Info | 0+ | 0+ |
+ MIP6-Feature-Vector | 0-1 | 0-1 |
+ +-----+-----+
+
+ Figure 5: Generic Request and Answer Commands AVP Table
+
+7. IANA Considerations
+
+7.1. Registration of New AVPs
+
+ This specification defines the following AVPs that have been
+ allocated from a normal Diameter AVP Code space (values >= 256):
+
+ MIP6-Agent-Info is set to 486
+
+ The following new AVPs are to be allocated from RADIUS Attribute Type
+ space [RFC2865] so that they are RADIUS backward-compatible (AVP Code
+ values between 0-255):
+
+ MIP6-Feature-Vector is set to 124
+ MIP6-Home-Link-Prefix is set to 125
+
+7.2. New Registry: Mobility Capability
+
+ IANA has created a new registry for the Mobility Capability as
+ described in Section 4.2.5.
+
+ Token | Value | Description
+ ----------------------------------+---------------------+------------
+ MIP6_INTEGRATED | 0x0000000000000001 | [RFC5447]
+ LOCAL_HOME_AGENT_ASSIGNMENT | 0x0000000000000002 | [RFC5447]
+ Available for Assignment via IANA | 2^x |
+
+ Allocation rule: Only numeric values that are 2^x (power of two,
+ where x >= 2) are allowed, based on the allocation policy described
+ below.
+
+ Following the example policies described in [RFC5226], new values for
+ the Mobility Capability Registry will be assigned based on the
+ "Specification Required" policy. No mechanism to mark entries as
+ "deprecated" is envisioned.
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 13]
+
+RFC 5447 Diameter MIPv6 NAS-to-HAAA Interaction February 2009
+
+
+8. Security Considerations
+
+ The security considerations for the Diameter interaction required to
+ accomplish the integrated scenario are described in [INTEGRATED].
+ Additionally, the security considerations for the Diameter base
+ protocol [RFC3588], the Diameter NASREQ application [RFC4005], and
+ the Diameter EAP application (with respect to network access
+ authentication and the transport of keying material) [RFC4072] are
+ applicable to this document. Developers should insure that special
+ attention is paid to configuring the security associations protecting
+ the messages that enable the global positioning and allocation of
+ home agents, for instance, as outlined in Section 5.
+
+ Furthermore, the Diameter messages may be transported between the NAS
+ and the Diameter server via one or more AAA brokers or Diameter
+ agents (such as proxies). In this case, the AAA communication from
+ the NAS to the Diameter server relies on the security properties of
+ the intermediate AAA brokers and Diameter agents.
+
+9. Acknowledgments
+
+ This document is heavily based on the ongoing work for RADIUS MIPv6
+ interaction. Hence, credits go to respective authors for their work
+ with "RADIUS Mobile IPv6 Support" (November 2008). Furthermore, the
+ authors of this document would like to thank the authors of "Diameter
+ Mobile IPv6 Application" (November 2004) -- Franck Le, Basavaraj
+ Patil, Charles E. Perkins, and Stefano Faccin -- for their work in
+ the context of MIPv6 Diameter interworking. Their work influenced
+ this document. Jouni Korhonen would like to thank the Academy of
+ Finland and TEKES MERCoNe Project for providing funding to work on
+ this document while he was with TeliaSonera. Julien Bournelle would
+ like to thank GET/INT since he began to work on this document while
+ he was in their employ. Authors would also like to acknowledge
+ Raymond Hsu for his valuable feedback on local HA assignment and
+ Wolfgang Fritsche for his thorough review. Additionally, we would
+ like to Domagoj Premec for his review comments.
+
+ Finally, we would like to thank Alper Yegin, Robert Marks, and David
+ Frascone for their comments at the second WG Last Call.
+
+
+
+
+
+
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 14]
+
+RFC 5447 Diameter MIPv6 NAS-to-HAAA Interaction February 2009
+
+
+10. References
+
+10.1. Normative References
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2865] Rigney, C., Willens, S., Rubens, A., and W. Simpson,
+ "Remote Authentication Dial In User Service (RADIUS)",
+ RFC 2865, June 2000.
+
+ [RFC3588] Calhoun, P., Loughney, J., Guttman, E., Zorn, G., and
+ J. Arkko, "Diameter Base Protocol", RFC 3588,
+ September 2003.
+
+ [RFC3775] Johnson, D., Perkins, C., and J. Arkko, "Mobility
+ Support in IPv6", RFC 3775, June 2004.
+
+ [RFC4004] Calhoun, P., Johansson, T., Perkins, C., Hiller, T.,
+ and P. McCann, "Diameter Mobile IPv4 Application",
+ RFC 4004, August 2005.
+
+ [RFC4005] Calhoun, P., Zorn, G., Spence, D., and D. Mitton,
+ "Diameter Network Access Server Application", RFC 4005,
+ August 2005.
+
+ [RFC4072] Eronen, P., Hiller, T., and G. Zorn, "Diameter
+ Extensible Authentication Protocol (EAP) Application",
+ RFC 4072, August 2005.
+
+10.2. Informative References
+
+ [AAA] Giaretta, G., Guardini, I., Demaria, E., Bournelle, J.,
+ and R. Lopez, "AAA Goals for Mobile IPv6", Work
+ in Progress, May 2008.
+
+ [DSMIPv6] Solimand, H., "Mobile IPv6 Support for Dual Stack Hosts
+ and Routers (DSMIPv6)", Work in Progress,
+ December 2008.
+
+ [INTEGRATED] Chowdhury, K. and A. Yegin, "MIP6-bootstrapping for the
+ Integrated Scenario", Work in Progress, April 2008.
+
+ [RFC3753] Manner, J. and M. Kojo, "Mobility Related Terminology",
+ RFC 3753, June 2004.
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 15]
+
+RFC 5447 Diameter MIPv6 NAS-to-HAAA Interaction February 2009
+
+
+ [RFC4640] Patel, A. and G. Giaretta, "Problem Statement for
+ bootstrapping Mobile IPv6 (MIPv6)", RFC 4640,
+ September 2006.
+
+ [RFC5026] Giaretta, G., Kempf, J., and V. Devarapalli, "Mobile
+ IPv6 Bootstrapping in Split Scenario", RFC 5026,
+ October 2007.
+
+ [RFC5226] Narten, T. and H. Alvestrand, "Guidelines for Writing
+ an IANA Considerations Section in RFCs", BCP 26,
+ RFC 5226, May 2008.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 16]
+
+RFC 5447 Diameter MIPv6 NAS-to-HAAA Interaction February 2009
+
+
+Authors' Addresses
+
+ Jouni Korhonen (editor)
+ Nokia Siemens Networks
+ Linnoitustie 6
+ Espoo FIN-02600
+ Finland
+
+
+
+ Julien Bournelle
+ Orange Labs
+ 38-4O rue du general Leclerc
+ Issy-Les-Moulineaux 92794
+ France
+
+
+
+ Hannes Tschofenig
+ Nokia Siemens Networks
+ Linnoitustie 6
+ Espoo 02600
+ Finland
+
+ URI: http://www.tschofenig.priv.at
+
+
+ Charles E. Perkins
+ WiChorus Inc.
+ 3590 North First St., Suite 300
+ San Jose, CA 95134
+ US
+
+
+
+ Kuntal Chowdhury
+ Starent Networks
+ 30 International Place
+ Tewksbury, MA 01876
+ US
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 17]
+
diff --git a/lib/diameter/ebin/.gitignore b/lib/diameter/ebin/.gitignore
new file mode 100644
index 0000000000..185bb606e3
--- /dev/null
+++ b/lib/diameter/ebin/.gitignore
@@ -0,0 +1,5 @@
+
+*.app
+*.appup
+*.beam
+
diff --git a/lib/diameter/examples/.gitignore b/lib/diameter/examples/.gitignore
new file mode 100644
index 0000000000..d7995d4e6b
--- /dev/null
+++ b/lib/diameter/examples/.gitignore
@@ -0,0 +1,3 @@
+
+*.beam
+
diff --git a/lib/diameter/examples/GNUmakefile b/lib/diameter/examples/GNUmakefile
new file mode 100644
index 0000000000..4c3f87939b
--- /dev/null
+++ b/lib/diameter/examples/GNUmakefile
@@ -0,0 +1,35 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+
+EXAMPLES = client server relay # redirect proxy
+
+CALLBACKS = $(EXAMPLES:%=%_cb)
+MODULES = peer $(EXAMPLES) $(EXAMPLES:%=%_cb)
+
+BEAM = $(MODULES:%=%.beam)
+
+%.beam: %.erl
+ erlc -W $<
+
+all: $(BEAM)
+
+clean:
+ rm -f $(BEAM)
+
+.PHONY: all clean
diff --git a/lib/diameter/examples/client.erl b/lib/diameter/examples/client.erl
new file mode 100644
index 0000000000..36a77dd524
--- /dev/null
+++ b/lib/diameter/examples/client.erl
@@ -0,0 +1,125 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% An example Diameter client that can sends base protocol RAR
+%% requests to a connected peer.
+%%
+%% The simplest usage is as follows this to connect to a server
+%% listening on the default port on the local host, assuming diameter
+%% is already started (eg. diameter:start()).
+%%
+%% client:start().
+%% client:connect(tcp).
+%% client:call().
+%%
+%% The first call starts the a service with the default name of
+%% ?MODULE, the second defines a connecting transport that results in
+%% a connection to the peer (if it's listening), the third sends it a
+%% RAR and returns the answer.
+%%
+
+-module(client).
+
+-include_lib("diameter/include/diameter.hrl").
+-include_lib("diameter/src/app/diameter_gen_base_rfc3588.hrl").
+
+-export([start/1, %% start a service
+ connect/2, %% add a connecting transport
+ call/1, %% send using the record encoding
+ cast/1, %% send using the list encoding and detached
+ stop/1]). %% stop a service
+%% A real application would typically choose an encoding and whether
+%% they want the call to return the answer or not. Sending with
+%% both the record and list encoding here, one detached and one not,
+%% is just for demonstration purposes.
+
+%% Convenience functions using the default service name, ?SVC_NAME.
+-export([start/0,
+ connect/1,
+ stop/0,
+ call/0,
+ cast/0]).
+
+-define(SVC_NAME, ?MODULE).
+-define(APP_ALIAS, ?MODULE).
+-define(CALLBACK_MOD, client_cb).
+
+-define(L, atom_to_list).
+
+%% The service configuration. As in the server example, a client
+%% supporting multiple Diameter applications may or may not want to
+%% configure a common callback module on all applications.
+-define(SERVICE(Name), [{'Origin-Host', ?L(Name) ++ ".example.com"},
+ {'Origin-Realm', "example.com"},
+ {'Vendor-Id', 0},
+ {'Product-Name', "Client"},
+ {'Auth-Application-Id', [?DIAMETER_APP_ID_COMMON]},
+ {application, [{alias, ?APP_ALIAS},
+ {dictionary, ?DIAMETER_DICT_COMMON},
+ {module, ?CALLBACK_MOD}]}]).
+
+%% start/1
+
+start(Name)
+ when is_atom(Name) ->
+ peer:start(Name, ?SERVICE(Name)).
+
+start() ->
+ start(?SVC_NAME).
+
+%% connect/2
+
+connect(Name, T) ->
+ peer:connect(Name, T).
+
+connect(T) ->
+ connect(?SVC_NAME, T).
+
+%% call/1
+
+call(Name) ->
+ SId = diameter:session_id(?L(Name)),
+ RAR = #diameter_base_RAR{'Session-Id' = SId,
+ 'Auth-Application-Id' = 0,
+ 'Re-Auth-Request-Type' = 0},
+ diameter:call(Name, ?APP_ALIAS, RAR, []).
+
+call() ->
+ call(?SVC_NAME).
+
+%% cast/1
+
+cast(Name) ->
+ SId = diameter:session_id(?L(Name)),
+ RAR = ['RAR', {'Session-Id', SId},
+ {'Auth-Application-Id', 0},
+ {'Re-Auth-Request-Type', 1}],
+ diameter:call(Name, ?APP_ALIAS, RAR, [detach]).
+
+cast() ->
+ cast(?SVC_NAME).
+
+%% stop/1
+
+stop(Name) ->
+ peer:stop(Name).
+
+stop() ->
+ stop(?SVC_NAME).
diff --git a/lib/diameter/examples/client_cb.erl b/lib/diameter/examples/client_cb.erl
new file mode 100644
index 0000000000..524a8f94a1
--- /dev/null
+++ b/lib/diameter/examples/client_cb.erl
@@ -0,0 +1,103 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(client_cb).
+
+-include_lib("diameter/include/diameter.hrl").
+-include_lib("diameter/src/app/diameter_gen_base_rfc3588.hrl").
+
+%% diameter callbacks
+-export([peer_up/3,
+ peer_down/3,
+ pick_peer/4,
+ prepare_request/3,
+ prepare_retransmit/3,
+ handle_answer/4,
+ handle_error/4,
+ handle_request/3]).
+
+%% peer_up/3
+
+peer_up(_SvcName, _Peer, State) ->
+ State.
+
+%% peer_down/3
+
+peer_down(_SvcName, _Peer, State) ->
+ State.
+
+%% pick_peer/4
+
+pick_peer([Peer | _], _, _SvcName, _State) ->
+ {ok, Peer}.
+
+%% prepare_request/3
+
+prepare_request(#diameter_packet{msg = ['RAR' = T | Avps]}, _, {_, Caps}) ->
+ #diameter_caps{origin_host = {OH, DH},
+ origin_realm = {OR, DR}}
+ = Caps,
+
+ {send, [T, {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Destination-Host', DH},
+ {'Destination-Realm', DR}
+ | Avps]};
+
+prepare_request(#diameter_packet{msg = Rec}, _, {_, Caps}) ->
+ #diameter_caps{origin_host = {OH, DH},
+ origin_realm = {OR, DR}}
+ = Caps,
+
+ {send, Rec#diameter_base_RAR{'Origin-Host' = OH,
+ 'Origin-Realm' = OR,
+ 'Destination-Host' = DH,
+ 'Destination-Realm' = DR}}.
+
+%% prepare_retransmit/3
+
+prepare_retransmit(Packet, SvcName, Peer) ->
+ prepare_request(Packet, SvcName, Peer).
+
+%% handle_answer/4
+
+%% Since client.erl has detached the call when using the list
+%% encoding and not otherwise, output to the terminal in the
+%% the former case, return in the latter.
+
+handle_answer(#diameter_packet{msg = Msg}, Request, _SvcName, _Peer)
+ when is_list(Request) ->
+ io:format("answer: ~p~n", [Msg]);
+
+handle_answer(#diameter_packet{msg = Msg}, _Request, _SvcName, _Peer) ->
+ {ok, Msg}.
+
+%% handle_error/4
+
+handle_error(Reason, Request, _SvcName, _Peer)
+ when is_list(Request) ->
+ io:format("error: ~p~n", [Reason]);
+
+handle_error(Reason, _Request, _SvcName, _Peer) ->
+ {error, Reason}.
+
+%% handle_request/3
+
+handle_request(_Packet, _SvcName, _Peer) ->
+ erlang:error({unexpected, ?MODULE, ?LINE}).
diff --git a/lib/diameter/examples/peer.erl b/lib/diameter/examples/peer.erl
new file mode 100644
index 0000000000..89203e15c3
--- /dev/null
+++ b/lib/diameter/examples/peer.erl
@@ -0,0 +1,139 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 library module that factors out commonality in the example
+%% Diameter peers.
+%%
+
+-module(peer).
+
+-include_lib("diameter/include/diameter.hrl").
+-include_lib("diameter/src/app/diameter_gen_base_rfc3588.hrl").
+
+-export([start/2,
+ listen/2,
+ connect/2,
+ stop/1]).
+
+-type service_name()
+ :: term().
+
+-type protocol()
+ :: tcp | sctp.
+
+-type ip_address()
+ :: default
+ | inet:ip_address().
+
+-type server_config()
+ :: protocol()
+ | {protocol(), ip_address(), non_neg_integer()}.
+
+-type client_config()
+ :: protocol()
+ | {protocol(), ip_address(), non_neg_integer()}
+ | {protocol(), ip_address(), ip_address(), non_neg_integer()}.
+
+-define(DEFAULT_ADDR, {127,0,0,1}).
+-define(DEFAULT_PORT, 3868).
+
+%% ---------------------------------------------------------------------------
+%% Interface functions
+%% ---------------------------------------------------------------------------
+
+%% start/2
+
+-spec start(service_name(), list())
+ -> ok
+ | {error, term()}.
+
+start(Name, Opts)
+ when is_atom(Name), is_list(Opts) ->
+ diameter:start_service(Name, Opts).
+
+%% connect/2
+
+-spec connect(service_name(), client_config())
+ -> {ok, reference()}
+ | {error, term()}.
+
+connect(Name, T) ->
+ diameter:add_transport(Name, {connect, [{reconnect_timer, 5000}
+ | client(T)]}).
+
+%% listen/2
+
+-spec listen(service_name(), server_config())
+ -> {ok, reference()}
+ | {error, term()}.
+
+listen(Name, T) ->
+ diameter:add_transport(Name, {listen, server(T)}).
+
+%% stop/1
+
+-spec stop(service_name())
+ -> ok
+ | {error, term()}.
+
+stop(Name) ->
+ diameter:stop_service(Name).
+
+%% ---------------------------------------------------------------------------
+%% Internal functions
+%% ---------------------------------------------------------------------------
+
+%% server/1
+%%
+%% Return config for a listening transport.
+
+server({T, Addr, Port}) ->
+ [{transport_module, tmod(T)},
+ {transport_config, [{reuseaddr, true},
+ {ip, addr(Addr)},
+ {port, Port}]}];
+
+server(T) ->
+ server({T, ?DEFAULT_ADDR, ?DEFAULT_PORT}).
+
+%% client/1
+%%
+%% Return config for a connecting transport.
+
+client({T, LA, RA, RP}) ->
+ [{transport_module, tmod(T)},
+ {transport_config, [{ip, addr(LA)},
+ {raddr, addr(RA)},
+ {rport, RP},
+ {reuseaddr, true}]}];
+
+client({T, LA, RP}) ->
+ client({T, LA, LA, RP});
+
+client(T) ->
+ client({T, ?DEFAULT_ADDR, ?DEFAULT_ADDR, ?DEFAULT_PORT}).
+
+tmod(tcp) -> diameter_tcp;
+tmod(sctp) -> diameter_sctp.
+
+addr(default) ->
+ ?DEFAULT_ADDR;
+addr(A) ->
+ A.
diff --git a/lib/diameter/examples/redirect.erl b/lib/diameter/examples/redirect.erl
new file mode 100644
index 0000000000..b54701243f
--- /dev/null
+++ b/lib/diameter/examples/redirect.erl
@@ -0,0 +1,70 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(redirect).
+
+-include_lib("diameter/include/diameter.hrl").
+-include_lib("diameter/src/app/diameter_gen_base_rfc3588.hrl").
+
+-export([start/1,
+ listen/2,
+ stop/1]).
+
+-export([start/0,
+ listen/1,
+ stop/0]).
+
+-define(APP_ALIAS, ?MODULE).
+-define(SVC_NAME, ?MODULE).
+-define(CALLBACK_MOD, redirect_mod).
+
+%% The service configuration.
+-define(SERVICE(Name), [{'Origin-Host', atom_to_list(Name) ++ ".example.com"},
+ {'Origin-Realm', "example.com"},
+ {'Vendor-Id', 193},
+ {'Product-Name', "RedirectAgent"},
+ {'Auth-Application-Id', [?DIAMETER_APP_ID_RELAY]},
+ {application, [{alias, ?APP_ALIAS},
+ {dictionary, ?DIAMETER_DICT_RELAY},
+ {module, ?CALLBACK_MOD}]}]).
+
+%% start/1
+
+start(Name)
+ when is_atom(Name) ->
+ peer:start(Name, ?SERVICE(Name)).
+
+start() ->
+ start(?SVC_NAME).
+
+%% listen/2
+
+listen(Name, T) ->
+ peer:listen(Name, T).
+
+listen(T) ->
+ listen(?SVC_NAME, T).
+
+%% stop/1
+
+stop(Name) ->
+ peer:stop(Name).
+
+stop() ->
+ stop(?SVC_NAME).
diff --git a/lib/diameter/examples/redirect_cb.erl b/lib/diameter/examples/redirect_cb.erl
new file mode 100644
index 0000000000..ea7ad38749
--- /dev/null
+++ b/lib/diameter/examples/redirect_cb.erl
@@ -0,0 +1,63 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(redirect_cb).
+
+-include_lib("diameter/include/diameter.hrl").
+-include_lib("diameter/src/app/diameter_gen_base_rfc3588.hrl").
+
+%% diameter callbacks
+-export([peer_up/3,
+ peer_down/3,
+ pick_peer/4,
+ prepare_request/3,
+ prepare_retransmit/3,
+ handle_answer/4,
+ handle_error/4,
+ handle_request/3]).
+
+-define(UNEXPECTED, erlang:error({unexpected, ?MODULE, ?LINE})).
+
+peer_up(_SvcName, {PeerRef, _}, State) ->
+ io:format("up: ~p~n", [PeerRef]),
+ State.
+
+peer_down(_SvcName, {PeerRef, _}, State) ->
+ io:format("down: ~p~n", [PeerRef]),
+ State.
+
+pick_peer(_, _, _SvcName, _State) ->
+ ?UNEXPECTED.
+
+prepare_request(_, _SvcName, _Peer) ->
+ ?UNEXPECTED.
+
+prepare_retransmit(_Packet, _SvcName, _Peer) ->
+ ?UNEXPECTED.
+
+handle_answer(_Packet, _Request, _SvcName, _Peer) ->
+ ?UNEXPECTED.
+
+handle_error(_Reason, _Request, _SvcName, _Peer) ->
+ ?UNEXPECTED.
+
+handle_request(#diameter_packet{msg = _, errors = []}, _SvcName, {_, Caps}) ->
+ #diameter_caps{}
+ = Caps,
+ discard. %% TODO
diff --git a/lib/diameter/examples/relay.erl b/lib/diameter/examples/relay.erl
new file mode 100644
index 0000000000..deecb1cfc0
--- /dev/null
+++ b/lib/diameter/examples/relay.erl
@@ -0,0 +1,92 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% An example Diameter relay agent.
+%%
+%% Usage to connect to a server listening on the default port over TCP
+%% and to listen on the default port over SCTP is as follows, assuming
+%% diameter is already started (eg. diameter:start()).
+%%
+%% Eg. relay:start().
+%% relay:connect(tcp).
+%% relay:listen(sctp).
+%%
+
+-module(relay).
+
+-include_lib("diameter/include/diameter.hrl").
+-include_lib("diameter/src/app/diameter_gen_base_rfc3588.hrl").
+
+-export([start/1,
+ listen/2,
+ connect/2,
+ stop/1]).
+
+-export([start/0,
+ listen/1,
+ connect/1,
+ stop/0]).
+
+-define(APP_ALIAS, ?MODULE).
+-define(SVC_NAME, ?MODULE).
+-define(CALLBACK_MOD, relay_cb).
+
+%% The service configuration.
+-define(SERVICE(Name), [{'Origin-Host', atom_to_list(Name) ++ ".example.com"},
+ {'Origin-Realm', "example.com"},
+ {'Vendor-Id', 193},
+ {'Product-Name', "RelayAgent"},
+ {'Auth-Application-Id', [?DIAMETER_APP_ID_RELAY]},
+ {application, [{alias, ?MODULE},
+ {dictionary, ?DIAMETER_DICT_RELAY},
+ {module, ?CALLBACK_MOD}]}]).
+
+%% start/1
+
+start(Name)
+ when is_atom(Name) ->
+ peer:start(Name, ?SERVICE(Name)).
+
+start() ->
+ start(?SVC_NAME).
+
+%% listen/2
+
+listen(Name, T) ->
+ peer:listen(Name, T).
+
+listen(T) ->
+ listen(?SVC_NAME, T).
+
+%% connect/2
+
+connect(Name, T) ->
+ peer:connect(Name, T).
+
+connect(T) ->
+ connect(?SVC_NAME, T).
+
+%% stop/1
+
+stop(Name) ->
+ peer:stop(Name).
+
+stop() ->
+ stop(?SVC_NAME).
diff --git a/lib/diameter/examples/relay_cb.erl b/lib/diameter/examples/relay_cb.erl
new file mode 100644
index 0000000000..9ed6517d5c
--- /dev/null
+++ b/lib/diameter/examples/relay_cb.erl
@@ -0,0 +1,69 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(relay_cb).
+
+-include_lib("diameter/include/diameter.hrl").
+-include_lib("diameter/src/app/diameter_gen_base_rfc3588.hrl").
+
+%% diameter callbacks
+-export([peer_up/3,
+ peer_down/3,
+ pick_peer/5,
+ prepare_request/4,
+ prepare_retransmit/4,
+ handle_answer/5,
+ handle_error/5,
+ handle_request/3]).
+
+peer_up(_SvcName, {PeerRef, _}, State) ->
+ io:format("up: ~p~n", [PeerRef]),
+ State.
+
+peer_down(_SvcName, {PeerRef, _}, State) ->
+ io:format("down: ~p~n", [PeerRef]),
+ State.
+
+%% Returning 'relay' from handle_request causes diameter to resend the
+%% incoming request, which leads to pick_peer and prepare_request
+%% callbacks as if sending explicitly. The 'extra' argument is
+%% appended to the argument list for callbacks following from
+%% resending of the request.
+
+handle_request(_Pkt, _SvcName, _Peer) ->
+ {relay, [{timeout, 1000}, {extra, [relayed]}]}.
+
+%% diameter will filter the sender in the Peers list.
+pick_peer([Peer | _], _, _SvcName, _State, relayed) ->
+ {ok, Peer}.
+
+prepare_request(Pkt, _SvcName, _Peer, relayed) ->
+ {send, Pkt}.
+
+prepare_retransmit(Pkt, _SvcName, _Peer, relayed) ->
+ {send, Pkt}.
+
+%% diameter expects handle_answer to return the diameter_packet record
+%% containing the answer when called for a relayed request.
+
+handle_answer(Pkt, _Request, _SvcName, _Peer, relayed) ->
+ Pkt.
+
+handle_error(Reason, _Request, _SvcName, _Peer, relayed) ->
+ {error, Reason}.
diff --git a/lib/diameter/examples/sctp.erl b/lib/diameter/examples/sctp.erl
new file mode 100644
index 0000000000..2e0e9d8b0b
--- /dev/null
+++ b/lib/diameter/examples/sctp.erl
@@ -0,0 +1,113 @@
+
+-module(sctp).
+
+%%
+%% A small example demonstrating the establishment of an SCTP
+%% association with gen_sctp.
+%%
+
+-export([assoc/0,
+ dbg/0]).
+
+-include_lib("kernel/include/inet_sctp.hrl").
+
+-define(ADDR, {127,0,0,1}).
+-define(SERVER_PORT, 3868).
+-define(CONNECT_TIMEOUT, 2000).
+-define(REQUEST, <<0:64>>).
+-define(REPLY, <<1:64>>).
+
+-record(server, {client,
+ socket,
+ assoc}).
+
+-record(client, {socket,
+ assoc}).
+
+%% assoc/0
+%%
+%% Return on a successfully established association, raise an
+%% exception otherwise.
+
+assoc() ->
+ {_, MRef} = spawn_monitor(fun server/0),
+ receive {'DOWN', MRef, process, _, Info} -> Info end.
+
+%% dbg/0
+
+dbg() ->
+ dbg:tracer(),
+ dbg:p(all,c),
+ dbg:tpl(?MODULE, [{'_',[],[{exception_trace}]}]),
+ dbg:tp(gen_sctp, [{'_',[],[{exception_trace}]}]),
+ ok.
+
+%% server/0
+
+server() ->
+ {ok, Sock} = gen_sctp:open([binary,
+ {reuseaddr, true},
+ {active, true},
+ {ip, ?ADDR},
+ {port, ?SERVER_PORT}]),
+ ok = gen_sctp:listen(Sock, true),
+ {_Pid, MRef} = spawn_monitor(fun client/0),
+ s(#server{client = MRef, socket = Sock}),
+ gen_sctp:close(Sock).
+
+%% s/1
+
+s(#server{} = S) ->
+ s(s(receive T -> T end, S));
+s(T) ->
+ T.
+
+%% s/2
+
+s({sctp, Sock, _RA, _RP, {[], #sctp_assoc_change{state = comm_up,
+ assoc_id = Id}}},
+ #server{socket = Sock, assoc = undefined}
+ = S) ->
+ S#server{assoc = Id};
+
+s({sctp, Sock, _RA, _RP, {[#sctp_sndrcvinfo{assoc_id = AId,
+ stream = SId}],
+ ?REQUEST}},
+ #server{socket = Sock, assoc = AId}
+ = S) ->
+ ok = gen_sctp:send(Sock, AId, SId, ?REPLY),
+ S;
+
+s({'DOWN', MRef, process, _, normal} = T, #server{client = MRef}) ->
+ T.
+
+%% client/0
+
+client() ->
+ {ok, Sock} = gen_sctp:open([binary,
+ {reuseaddr, true},
+ {active, true},
+ {ip, ?ADDR},
+ {port, 0}]),
+ ok = gen_sctp:connect_init(Sock, ?ADDR, ?SERVER_PORT, []),
+ c(#client{socket = Sock}),
+ gen_sctp:close(Sock).
+
+
+%% c/1
+
+c(#client{} = S) ->
+ c(c(receive T -> T end, S));
+c(T) ->
+ T.
+
+c({sctp, Sock, _RA, _RP, {[], #sctp_assoc_change{state = comm_up,
+ assoc_id = Id}}},
+ #client{socket = Sock, assoc = undefined}
+ = S) ->
+ ok = gen_sctp:send(Sock, Id, 0, ?REQUEST),
+ S#client{assoc = Id};
+
+c({sctp, Sock, _RA, _RP, {[#sctp_sndrcvinfo{assoc_id = AId}], ?REPLY}},
+ #client{socket = Sock, assoc = AId}) ->
+ ok.
diff --git a/lib/diameter/examples/server.erl b/lib/diameter/examples/server.erl
new file mode 100644
index 0000000000..ebb408e501
--- /dev/null
+++ b/lib/diameter/examples/server.erl
@@ -0,0 +1,88 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% An example Diameter server that can respond to the base protocol
+%% RAR sent by the client example.
+%%
+%% The simplest example to start a server listening on the loopback
+%% address (which will serve the example usage given in client.erl) is
+%% like this assuming diameter is already started (eg. diameter:start()):
+%%
+%% server:start().
+%% server:listen(tcp).
+%%
+%% The first call starts a service, the second adds a transport listening
+%% on the default port.
+%%
+
+-module(server).
+
+-include_lib("diameter/include/diameter.hrl").
+-include_lib("diameter/src/app/diameter_gen_base_rfc3588.hrl").
+
+-export([start/1, %% start a service
+ listen/2, %% add a listening transport
+ stop/1]). %% stop a service
+
+%% Convenience functions using the default service name, ?SVC_NAME.
+-export([start/0,
+ listen/1,
+ stop/0]).
+
+-define(SVC_NAME, ?MODULE).
+-define(APP_ALIAS, ?MODULE).
+-define(CALLBACK_MOD, server_cb).
+
+%% The service configuration. In a server supporting multiple Diameter
+%% applications each application may have its own, although they could all
+%% be configured with a common callback module.
+-define(SERVICE(Name), [{'Origin-Host', atom_to_list(Name) ++ ".example.com"},
+ {'Origin-Realm', "example.com"},
+ {'Vendor-Id', 193},
+ {'Product-Name', "Server"},
+ {'Auth-Application-Id', [?DIAMETER_APP_ID_COMMON]},
+ {application, [{alias, ?APP_ALIAS},
+ {dictionary, ?DIAMETER_DICT_COMMON},
+ {module, ?CALLBACK_MOD}]}]).
+
+%% start/1
+
+start(Name)
+ when is_atom(Name) ->
+ peer:start(Name, ?SERVICE(Name)).
+
+start() ->
+ start(?SVC_NAME).
+
+%% listen/2
+
+listen(Name, T) ->
+ peer:listen(Name, T).
+
+listen(T) ->
+ listen(?SVC_NAME, T).
+
+%% stop/1
+
+stop(Name) ->
+ peer:stop(Name).
+
+stop() ->
+ stop(?SVC_NAME).
diff --git a/lib/diameter/examples/server_cb.erl b/lib/diameter/examples/server_cb.erl
new file mode 100644
index 0000000000..43b8e24b5c
--- /dev/null
+++ b/lib/diameter/examples/server_cb.erl
@@ -0,0 +1,115 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% The diameter application callback module configured by server.erl.
+%%
+
+-module(server_cb).
+
+-include_lib("diameter/include/diameter.hrl").
+-include_lib("diameter/src/app/diameter_gen_base_rfc3588.hrl").
+
+%% diameter callbacks
+-export([peer_up/3,
+ peer_down/3,
+ pick_peer/4,
+ prepare_request/3,
+ prepare_retransmit/3,
+ handle_answer/4,
+ handle_error/4,
+ handle_request/3]).
+
+-define(UNEXPECTED, erlang:error({unexpected, ?MODULE, ?LINE})).
+
+peer_up(_SvcName, {PeerRef, _}, State) ->
+ io:format("up: ~p~n", [PeerRef]),
+ State.
+
+peer_down(_SvcName, {PeerRef, _}, State) ->
+ io:format("down: ~p~n", [PeerRef]),
+ State.
+
+pick_peer(_, _, _SvcName, _State) ->
+ ?UNEXPECTED.
+
+prepare_request(_, _SvcName, _Peer) ->
+ ?UNEXPECTED.
+
+prepare_retransmit(_Packet, _SvcName, _Peer) ->
+ ?UNEXPECTED.
+
+handle_answer(_Packet, _Request, _SvcName, _Peer) ->
+ ?UNEXPECTED.
+
+handle_error(_Reason, _Request, _SvcName, _Peer) ->
+ ?UNEXPECTED.
+
+%% A request whose decode was successful ...
+handle_request(#diameter_packet{msg = Req, errors = []}, _SvcName, {_, Caps})
+ when is_record(Req, diameter_base_RAR) ->
+ #diameter_caps{origin_host = {OH,_},
+ origin_realm = {OR,_}}
+ = Caps,
+ #diameter_base_RAR{'Session-Id' = Id,
+ 'Re-Auth-Request-Type' = RT}
+ = Req,
+
+ {reply, answer(RT, Id, OH, OR)};
+
+%% ... or one that wasn't. 3xxx errors are answered by diameter itself
+%% but these are 5xxx errors for which we must contruct a reply.
+%% diameter will set Result-Code and Failed-AVP's.
+handle_request(#diameter_packet{msg = Req} = Pkt, _SvcName, {_, Caps})
+ when is_record(Req, diameter_base_RAR) ->
+ #diameter_caps{origin_host = {OH,_},
+ origin_realm = {OR,_}}
+ = Caps,
+ #diameter_base_RAR{'Session-Id' = Id}
+ = Req,
+
+ Ans = #diameter_base_RAA{'Origin-Host' = OH,
+ 'Origin-Realm' = OR,
+ 'Session-Id' = Id},
+
+ {reply, Ans};
+
+%% Should really reply to other base messages that we don't support
+%% but simply discard them instead.
+handle_request(#diameter_packet{}, _SvcName, {_,_}) ->
+ discard.
+
+%% ---------------------------------------------------------------------------
+
+%% Answer using the record or list encoding depending on
+%% Re-Auth-Request-Type. This is just as an example. You would
+%% typically just choose one, and this has nothing to do with the how
+%% client.erl sends.
+
+answer(0, Id, OH, OR) ->
+ #diameter_base_RAA{'Result-Code' = 2001, %% DIAMETER_SUCCESS
+ 'Origin-Host' = OH,
+ 'Origin-Realm' = OR,
+ 'Session-Id' = Id};
+
+answer(_, Id, OH, OR) ->
+ ['RAA', {'Result-Code', 5012}, %% DIAMETER_UNABLE_TO_COMPLY
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Session-Id', Id}].
diff --git a/lib/diameter/include/diameter.hrl b/lib/diameter/include/diameter.hrl
new file mode 100644
index 0000000000..0fa7fd406f
--- /dev/null
+++ b/lib/diameter/include/diameter.hrl
@@ -0,0 +1,130 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_hrl).
+-define(diameter_hrl, true).
+
+%% RFC 3588, 2.4:
+-define(DIAMETER_APP_ID_COMMON, 0).
+-define(DIAMETER_APP_ID_ACCOUNTING, 3).
+-define(DIAMETER_APP_ID_RELAY, 16#FFFFFFFF).
+
+%% Corresponding dictionaries:
+-define(DIAMETER_DICT_COMMON, diameter_gen_base_rfc3588).
+-define(DIAMETER_DICT_ACCOUNTING, diameter_gen_base_accounting).
+-define(DIAMETER_DICT_RELAY, diameter_gen_relay).
+
+%% Events sent to processes that have subscribed with
+%% diameter:subscribe/1.
+%%
+-record(diameter_event,
+ {service, %% name
+ info}). %% tuple()
+
+%% diameter_packet records are passed through the encode/decode
+%% interface supplied by a dictionary module configured on a Diameter
+%% application. For an incoming message the bin field contains the
+%% received binary and the header, avps, msg and errors fields the
+%% result of decoding.
+
+-record(diameter_packet,
+ {header, %% #diameter_header{}
+ avps, %% deep list() of #diameter_avp{}
+ msg, %% fully decoded message
+ bin, %% binary received/sent over the wire
+ errors = [],%% list() of Result-Code | {Result-Code, #diameter_avp{}}
+ transport_data}).
+
+-record(diameter_header,
+ {version, %% 8-bit unsigned
+ length, %% 24-bit unsigned
+ cmd_code, %% 8-bit unsigned
+ application_id, %% 24-bit unsigned
+ hop_by_hop_id, %% 32-bit unsigned
+ end_to_end_id, %% 32-bit unsigned
+ is_request, %% boolean() R flag
+ is_proxiable, %% boolean() P flag
+ is_error, %% boolean() E flag
+ is_retransmitted}). %% boolean() T flag
+
+-record(diameter_avp,
+ {code, %% 32-bit unsigned
+ vendor_id, %% 32-bit unsigned
+ is_mandatory = false, %% boolean() M flag
+ need_encryption = false, %% boolean() P flag
+ data, %% encoded binary()
+ name, %% atom() AVP name
+ value, %% decoded term() decoded | undefined
+ type, %% atom() type name,
+ index}). %% non_neg_integer() | undefined
+
+%% A diameter_caps record corresponds to capabilities configuration on
+%% diameter:start_service/2. In application callbacks is identifies
+%% the peer connection for which the callback is taking place, and in
+%% this case each field is a 2-tuple specifying the host (ie. local)
+%% and peer (ie. remote) values, host values having been configured
+%% and peer values having been received at capabilities exchange.
+
+-record(diameter_caps,
+ {origin_host, %% 'DiameterIdentity'()
+ origin_realm, %% 'DiameterIdentity'()
+ host_ip_address = [], %% ['Address'()]
+ vendor_id, %% 'Unsigned32'()
+ product_name, %% 'OctetString'()
+ origin_state_id = [], %% ['Unsigned32'()]
+ supported_vendor_id = [], %% ['Unsigned32'()]
+ auth_application_id = [], %% ['Unsigned32'()]
+ inband_security_id = [], %% ['Unsigned32'()]
+ acct_application_id = [], %% ['Unsigned32'()]
+ vendor_specific_application_id = [], %% ['Grouped'()]
+ firmware_revision = [], %% ['Unsigned32()]
+ avp = []}).
+
+%% AVP's of type DiameterURI are encoded as a diameter_uri record.
+%% Note that AVP's of type IPFilterRule and QoSFilterRule are currently
+%% encoded simply as OctetString's.
+
+-record(diameter_uri,
+ {type, %% aaa | aaas
+ fqdn, %% string()
+ port = 3868, %% non_neg_integer(),
+ transport = sctp, %% | tcp,
+ protocol = diameter}). %% | radius | 'tacacs+'
+
+%% The diameter service and diameter_apps records are only passed
+%% through the transport interface when starting a transport process,
+%% although typically a transport implementation will (and probably
+%% should) only be interested host_ip_address.
+
+-record(diameter_service,
+ {pid,
+ capabilities, %% #diameter_caps{}
+ applications = []}). %% [#diameter_app{}]
+
+-record(diameter_app,
+ {alias, %% option 'alias'
+ dictionary, %% option 'dictionary', module()
+ module, %% [Mod | Args] callback module() and extra args
+ init_state, %% option 'state', initial callback state
+ id, %% 32-bit unsigned application identifier = Dict:id()
+ mutable = false, %% boolean(), do traffic callbacks modify state?
+ answer_errors = report}). %% | callback | discard
+ %% how to handle containing errors?
+
+-endif. %% -ifdef(diameter_hrl).
diff --git a/lib/diameter/include/diameter_gen.hrl b/lib/diameter/include/diameter_gen.hrl
new file mode 100644
index 0000000000..d037e1044a
--- /dev/null
+++ b/lib/diameter/include/diameter_gen.hrl
@@ -0,0 +1,431 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 contains code that's included by encode/decode modules
+%% generated by diameter_codegen.erl. This code does most of the work, the
+%% generated code being kept simple.
+%%
+
+-define(THROW(T), throw({?MODULE, T})).
+
+%%% ---------------------------------------------------------------------------
+%%% # encode_avps/3
+%%%
+%%% Returns: binary()
+%%% ---------------------------------------------------------------------------
+
+encode_avps(Name, Vals)
+ when is_list(Vals) ->
+ encode_avps(Name, '#set-'(Vals, newrec(Name)));
+
+encode_avps(Name, Rec) ->
+ try
+ list_to_binary(encode(Name, Rec))
+ catch
+ throw: {?MODULE, Reason} ->
+ diameter_dbg:log({encode, error},
+ ?MODULE,
+ ?LINE,
+ {Reason, Name, Rec}),
+ erlang:error(list_to_tuple(Reason ++ [Name]));
+ error: Reason ->
+ Stack = erlang:get_stacktrace(),
+ diameter_dbg:log({encode, failure},
+ ?MODULE,
+ ?LINE,
+ {Reason, Name, Rec, Stack}),
+ erlang:error({encode_failure, Reason, Name, Stack})
+ end.
+
+%% encode/2
+
+encode(Name, Rec) ->
+ lists:flatmap(fun(A) -> encode(Name, A, '#get-'(A, Rec)) end,
+ '#info-'(element(1, Rec), fields)).
+
+%% encode/3
+
+encode(Name, AvpName, Values) ->
+ e(Name, AvpName, avp_arity(Name, AvpName), Values).
+
+%% e/4
+
+e(_, AvpName, 1, undefined) ->
+ ?THROW([mandatory_avp_missing, AvpName]);
+
+e(Name, AvpName, 1, Value) ->
+ e(Name, AvpName, [Value]);
+
+e(_, _, {0,_}, []) ->
+ [];
+
+e(_, AvpName, _, T)
+ when not is_list(T) ->
+ ?THROW([repeated_avp_as_non_list, AvpName, T]);
+
+e(_, AvpName, {Min, _}, L)
+ when length(L) < Min ->
+ ?THROW([repeated_avp_insufficient_arity, AvpName, Min, L]);
+
+e(_, AvpName, {_, Max}, L)
+ when Max < length(L) ->
+ ?THROW([repeated_avp_excessive_arity, AvpName, Max, L]);
+
+e(Name, AvpName, _, Values) ->
+ e(Name, AvpName, Values).
+
+%% e/3
+
+e(Name, 'AVP', Values) ->
+ [pack_AVP(Name, A) || A <- Values];
+
+e(_, AvpName, Values) ->
+ e(AvpName, Values).
+
+%% e/2
+
+e(AvpName, Values) ->
+ H = avp_header(AvpName),
+ [diameter_codec:pack_avp(H, avp(encode, V, AvpName)) || V <- Values].
+
+%% pack_AVP/2
+
+%% No value: assume AVP data is already encoded. The normal case will
+%% be when this is passed back from #diameter_packet.errors as a
+%% consequence of a failed decode. Any AVP can be encoded this way
+%% however, which side-steps any arity checks for known AVP's and
+%% could potentially encode something unfortunate.
+pack_AVP(_, #diameter_avp{value = undefined} = A) ->
+ diameter_codec:pack_avp(A);
+
+%% Missing name for value encode.
+pack_AVP(_, #diameter_avp{name = N, value = V})
+ when N == undefined;
+ N == 'AVP' ->
+ ?THROW([value_with_nameless_avp, N, V]);
+
+%% Or not. Ensure that 'AVP' is the appropriate field. Note that if we
+%% don't know this AVP at all then the encode will fail.
+pack_AVP(Name, #diameter_avp{name = AvpName,
+ value = Data}) ->
+ 0 == avp_arity(Name, AvpName)
+ orelse ?THROW([known_avp_as_AVP, Name, AvpName, Data]),
+ e(AvpName, [Data]).
+
+%%% ---------------------------------------------------------------------------
+%%% # decode_avps/2
+%%%
+%%% Returns: {Rec, Avps, Failed}
+%%%
+%%% Rec = decoded message record
+%%% Avps = list of Avp
+%%% Failed = list of {ResultCode, #diameter_avp{}}
+%%%
+%%% Avp = #diameter_avp{} if type is not Grouped
+%%% | list of Avp where first element has type Grouped
+%%% and following elements are its component
+%%% AVP's.
+%%% ---------------------------------------------------------------------------
+
+decode_avps(Name, Recs) ->
+ d_rc(Name, lists:foldl(fun(T,A) -> decode(Name, T, A) end,
+ {[], {newrec(Name), []}},
+ Recs)).
+
+newrec(Name) ->
+ '#new-'(name2rec(Name)).
+
+%% No errors so far: keep looking.
+d_rc(Name, {Avps, {Rec, [] = Failed}}) ->
+ try
+ true = have_required_avps(Rec, Name),
+ {Rec, Avps, Failed}
+ catch
+ throw: {?MODULE, {AvpName, Reason}} ->
+ diameter_dbg:log({decode, error},
+ ?MODULE,
+ ?LINE,
+ {AvpName, Reason, Rec}),
+ {Rec, Avps, [{5005, empty_avp(AvpName)}]}
+ end;
+%% 3588:
+%%
+%% DIAMETER_MISSING_AVP 5005
+%% The request did not contain an AVP that is required by the Command
+%% Code definition. If this value is sent in the Result-Code AVP, a
+%% Failed-AVP AVP SHOULD be included in the message. The Failed-AVP
+%% AVP MUST contain an example of the missing AVP complete with the
+%% Vendor-Id if applicable. The value field of the missing AVP
+%% should be of correct minimum length and contain zeroes.
+
+%% Or not. Only need to report the first error so look no further.
+d_rc(_, {Avps, {Rec, Failed}}) ->
+ {Rec, Avps, lists:reverse(Failed)}.
+
+%% empty_avp/1
+
+empty_avp(Name) ->
+ {Code, Flags, VId} = avp_header(Name),
+ {Name, Type} = avp_name(Code, VId),
+ #diameter_avp{name = Name,
+ code = Code,
+ vendor_id = VId,
+ is_mandatory = 0 /= (Flags band 2#01000000),
+ need_encryption = 0 /= (Flags band 2#00100000),
+ data = empty_value(Name),
+ type = Type}.
+
+%% have_required_avps/2
+
+have_required_avps(Rec, Name) ->
+ lists:foreach(fun(F) -> hra(Name, F, Rec) end,
+ '#info-'(element(1, Rec), fields)),
+ true.
+
+hra(Name, AvpName, Rec) ->
+ Arity = avp_arity(Name, AvpName),
+ hra(Arity, '#get-'(AvpName, Rec))
+ orelse ?THROW({AvpName, {insufficient_arity, Arity}}).
+
+%% Maximum arities have already been checked in building the record.
+
+hra({Min, _}, L) ->
+ Min =< length(L);
+hra(N, V) ->
+ N /= 1 orelse V /= undefined.
+
+%% 3588, ch 7:
+%%
+%% The Result-Code AVP describes the error that the Diameter node
+%% encountered in its processing. In case there are multiple errors,
+%% the Diameter node MUST report only the first error it encountered
+%% (detected possibly in some implementation dependent order). The
+%% specific errors that can be described by this AVP are described in
+%% the following section.
+
+%% decode/3
+
+decode(Name, #diameter_avp{code = Code, vendor_id = Vid} = Avp, Acc) ->
+ decode(Name, avp_name(Code, Vid), Avp, Acc).
+
+%% decode/4
+
+%% Don't know this AVP: see if it can be packed in an 'AVP' field
+%% undecoded, unless it's mandatory. Need to give Failed-AVP special
+%% treatment since it'll contain any unrecognized mandatory AVP's.
+decode(Name, 'AVP', #diameter_avp{is_mandatory = M} = Avp, {Avps, Acc}) ->
+ {[Avp | Avps], if M, Name /= 'Failed-AVP' ->
+ unknown(Avp, Acc);
+ true ->
+ pack_AVP(Name, Avp, Acc)
+ end};
+%% Note that the type field is 'undefined' in this case.
+
+%% Or try to decode.
+decode(Name, {AvpName, Type}, Avp, Acc) ->
+ d(Name, Avp#diameter_avp{name = AvpName, type = Type}, Acc).
+
+%% d/3
+
+d(Name, Avp, {Avps, Acc}) ->
+ #diameter_avp{name = AvpName,
+ data = Data}
+ = Avp,
+
+ try avp(decode, Data, AvpName) of
+ V ->
+ {H, A} = ungroup(V, Avp),
+ {[H | Avps], pack_avp(Name, A, Acc)}
+ catch
+ error: Reason ->
+ %% Failures here won't be visible since they're a "normal"
+ %% occurrence if the peer sends a faulty AVP that we need to
+ %% respond sensibly to. Log the occurence for traceability,
+ %% but the peer will also receive info in the resulting
+ %% answer-message.
+ diameter_dbg:log({decode, failure},
+ ?MODULE,
+ ?LINE,
+ {Reason, Avp, erlang:get_stacktrace()}),
+ {Rec, Failed} = Acc,
+ {[Avp|Avps], {Rec, [{rc(Reason), Avp} | Failed]}}
+ end.
+
+%% rc/1
+
+%% diameter_types will raise an error of this form to communicate
+%% DIAMETER_INVALID_AVP_LENGTH (5014). A module specified to a
+%% @custom_types tag in a spec file can also raise an error of this
+%% form.
+rc({'DIAMETER', RC, _}) ->
+ RC;
+
+%% 3588:
+%%
+%% DIAMETER_INVALID_AVP_VALUE 5004
+%% The request contained an AVP with an invalid value in its data
+%% portion. A Diameter message indicating this error MUST include
+%% the offending AVPs within a Failed-AVP AVP.
+rc(_) ->
+ 5004.
+
+%% ungroup/2
+%%
+%% Returns: {Avp, Dec}
+%%
+%% Avp = #diameter_avp{} if type is not Grouped
+%% | list of Avp where first element has type Grouped
+%% and following elements are its component
+%% AVP's.
+%% = as for decode_avps/2
+%%
+%% Dec = #diameter_avp{}, either Avp or its head in the list case.
+
+%% The decoded value in the Grouped case is as returned by grouped_avp/3:
+%% a record and a list of component AVP's.
+ungroup(V, #diameter_avp{type = 'Grouped'} = Avp) ->
+ {Rec, As} = V,
+ A = Avp#diameter_avp{value = Rec},
+ {[A|As], A};
+
+%% Otherwise it's just a plain value.
+ungroup(V, #diameter_avp{} = Avp) ->
+ A = Avp#diameter_avp{value = V},
+ {A, A}.
+
+%% pack_avp/3
+
+pack_avp(Name, #diameter_avp{name = AvpName} = Avp, Acc) ->
+ pack_avp(Name, avp_arity(Name, AvpName), Avp, Acc).
+
+%% pack_avp/4
+
+pack_avp(Name, 0, Avp, Acc) ->
+ pack_AVP(Name, Avp, Acc);
+
+pack_avp(_, Arity, Avp, Acc) ->
+ pack(Arity, Avp#diameter_avp.name, Avp, Acc).
+
+%% pack_AVP/3
+
+pack_AVP(Name, Avp, Acc) ->
+ case avp_arity(Name, 'AVP') of
+ 0 ->
+ unknown(Avp, Acc);
+ Arity ->
+ pack(Arity, 'AVP', Avp, Acc)
+ end.
+
+%% 3588:
+%%
+%% DIAMETER_AVP_UNSUPPORTED 5001
+%% The peer received a message that contained an AVP that is not
+%% recognized or supported and was marked with the Mandatory bit. A
+%% Diameter message with this error MUST contain one or more Failed-
+%% AVP AVP containing the AVPs that caused the failure.
+%%
+%% DIAMETER_AVP_NOT_ALLOWED 5008
+%% A message was received with an AVP that MUST NOT be present. The
+%% Failed-AVP AVP MUST be included and contain a copy of the
+%% offending AVP.
+%%
+unknown(#diameter_avp{is_mandatory = B} = Avp, {Rec, Failed}) ->
+ {Rec, [{if B -> 5001; true -> 5008 end, Avp} | Failed]}.
+
+%% pack/4
+
+pack(Arity, FieldName, Avp, {Rec, _} = Acc) ->
+ pack('#get-'(FieldName, Rec), Arity, FieldName, Avp, Acc).
+
+%% pack/5
+
+pack(undefined, 1, FieldName, Avp, Acc) ->
+ p(FieldName, fun(V) -> V end, Avp, Acc);
+
+%% 3588:
+%%
+%% DIAMETER_AVP_OCCURS_TOO_MANY_TIMES 5009
+%% A message was received that included an AVP that appeared more
+%% often than permitted in the message definition. The Failed-AVP
+%% AVP MUST be included and contain a copy of the first instance of
+%% the offending AVP that exceeded the maximum number of occurrences
+%%
+pack(_, 1, _, Avp, {Rec, Failed}) ->
+ {Rec, [{5009, Avp} | Failed]};
+pack(L, {_, Max}, _, Avp, {Rec, Failed})
+ when length(L) == Max ->
+ {Rec, [{5009, Avp} | Failed]};
+
+pack(L, _, FieldName, Avp, Acc) ->
+ p(FieldName, fun(V) -> [V|L] end, Avp, Acc).
+
+%% p/4
+
+p(F, Fun, Avp, {Rec, Failed}) ->
+ {'#set-'({F, Fun(value(F, Avp))}, Rec), Failed}.
+
+value('AVP', Avp) ->
+ Avp;
+value(_, Avp) ->
+ Avp#diameter_avp.value.
+
+%%% ---------------------------------------------------------------------------
+%%% # grouped_avp/3
+%%% ---------------------------------------------------------------------------
+
+grouped_avp(decode, Name, Data) ->
+ {Rec, Avps, []} = decode_avps(Name, diameter_codec:collect_avps(Data)),
+ {Rec, Avps};
+%% Note that a failed match here will result in 5004. Note that this is
+%% the only AVP type that doesn't just return the decoded value, also
+%% returning the list of component #diameter_avp{}'s.
+
+grouped_avp(encode, Name, Data) ->
+ encode_avps(Name, Data).
+
+%%% ---------------------------------------------------------------------------
+%%% # empty_group/1
+%%% ---------------------------------------------------------------------------
+
+empty_group(Name) ->
+ list_to_binary(empty_body(Name)).
+
+empty_body(Name) ->
+ [z(F, avp_arity(Name, F)) || F <- '#info-'(name2rec(Name), fields)].
+
+z(Name, 1) ->
+ z(Name);
+z(_, {0,_}) ->
+ [];
+z(Name, {Min, _}) ->
+ lists:duplicate(Min, z(Name)).
+
+z('AVP') ->
+ <<0:64/integer>>; %% minimal header
+z(Name) ->
+ Bin = diameter_codec:pack_avp(avp_header(Name), empty_value(Name)),
+ << <<0>> || <<_>> <= Bin >>.
+
+%%% ---------------------------------------------------------------------------
+%%% # empty/1
+%%% ---------------------------------------------------------------------------
+
+empty(AvpName) ->
+ avp(encode, zero, AvpName).
diff --git a/lib/diameter/info b/lib/diameter/info
new file mode 100644
index 0000000000..67ef726781
--- /dev/null
+++ b/lib/diameter/info
@@ -0,0 +1,3 @@
+group: comm
+short: Diameter
+
diff --git a/lib/diameter/make/release_targets.mk b/lib/diameter/make/release_targets.mk
new file mode 100644
index 0000000000..5a3b585cbc
--- /dev/null
+++ b/lib/diameter/make/release_targets.mk
@@ -0,0 +1,92 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1997-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+
+ifeq ($(TOPDOC),)
+$(HTMLDIR)/index.html: $(XML_FILES)
+ date=`date +"%B %e %Y"`; \
+ $(XSLTPROC) --noout --stringparam outdir $(HTMLDIR) --stringparam docgen "$(DOCGEN)" --stringparam topdocdir "$(TOPDOCDIR)" \
+ --stringparam pdfdir "$(PDFDIR)" \
+ --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude \
+ -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_html_entities $(DOCGEN)/priv/xsl/db_html.xsl book.xml
+endif
+
+$(HTMLDIR)/users_guide.html: $(XML_FILES)
+ date=`date +"%B %e %Y"`; \
+ $(XSLTPROC) --noout --stringparam outdir $(HTMLDIR) --stringparam docgen "$(DOCGEN)" --stringparam topdocdir "$(TOPDOCDIR)" \
+ --stringparam pdfdir "$(PDFDIR)" \
+ --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude \
+ -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_html_entities $(DOCGEN)/priv/xsl/db_html.xsl book.xml
+
+
+%.fo: $(XML_FILES)
+ date=`date +"%B %e %Y"`; \
+ $(XSLTPROC) --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" \
+ --stringparam appver "$(VSN)" --xinclude \
+ -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_html_entities $(DOCGEN)/priv/xsl/db_pdf.xsl book.xml > $@
+
+
+
+# ------------------------------------------------------------------------
+# The following targets just exist in the documentation directory
+# ------------------------------------------------------------------------
+ifneq ($(XML_FILES),)
+
+# ----------------------------------------------------
+# Generation of application index data
+# ----------------------------------------------------
+$(HTMLDIR)/$(APPLICATION).eix: $(XML_FILES)
+ date=`date +"%B %e %Y"`; \
+ $(XSLTPROC) --stringparam docgen "$(DOCGEN)" \
+ --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude \
+ -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_html_entities $(DOCGEN)/priv/xsl/db_eix.xsl book.xml > $@
+
+docs:
+#docs: $(HTMLDIR)/$(APPLICATION).eix
+
+# ----------------------------------------------------
+# Local documentation target for testing
+# ----------------------------------------------------
+local_docs: TOPDOCDIR=.
+local_docs: local_copy_of_topdefs docs
+
+local_html: TOPDOCDIR=.
+local_html: local_copy_of_topdefs html
+
+local_copy_of_topdefs:
+ $(INSTALL) $(DOCGEN)/priv/css/otp_doc.css $(HTMLDIR)
+ $(INSTALL) $(DOCGEN)/priv/images/erlang-logo.png $(HTMLDIR)
+ $(INSTALL) $(DOCGEN)/priv/images/erlang-logo.gif $(HTMLDIR)
+ $(INSTALL_DIR) $(HTMLDIR)/js/flipmenu
+ $(INSTALL) $(DOCGEN)/priv/js/flipmenu/flip_closed.gif \
+ $(DOCGEN)/priv/js/flipmenu/flip_open.gif \
+ $(DOCGEN)/priv/js/flipmenu/flip_static.gif \
+ $(DOCGEN)/priv/js/flipmenu/flipmenu.js $(HTMLDIR)/js/flipmenu
+
+endif
+
+# ----------------------------------------------------
+# Standard release target
+# ----------------------------------------------------
+
+ifneq ($(PREFIX),)
+
+release release_docs release_tests release_html:
+ $(MAKE) $(MFLAGS) RELEASE_PATH=$(PREFIX) $(TARGET_MAKEFILE) $@_spec
+
+endif
diff --git a/lib/diameter/make/rules.mk.in b/lib/diameter/make/rules.mk.in
new file mode 100644
index 0000000000..6318f2bc9c
--- /dev/null
+++ b/lib/diameter/make/rules.mk.in
@@ -0,0 +1,195 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+# ----------------------------------------------------
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2009-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+.SUFFIXES: .erl .beam .yrl .hrl .xml .xmlsrc .html \
+ .3 .1 .pdf .fo .el .elc
+
+# ----------------------------------------------------
+# Common macros
+# ----------------------------------------------------
+DEFAULT_TARGETS = opt debug release release_docs clean docs
+
+
+# Slash separated list of return values from $(origin VAR)
+# that are untrusted - set default in this file instead.
+# The list is not space separated since some return values
+# contain space, and we want to use $(findstring ...) to
+# search the list.
+DUBIOUS_ORIGINS = /undefined/environment/
+
+
+# # ----------------------------------------------------
+# # TARGET definition
+# # ----------------------------------------------------
+# # TARGET = @TARGET@
+# ifneq ($(OVERRIDE_TARGET),)
+# ifneq ($(TARGET), $(OVERRIDE_TARGET))
+# $(warning overriding $$(TARGET) = \
+# "$(TARGET)" \
+# with \
+# $$(OVERRIDE_TARGET) = \
+# "$(OVERRIDE_TARGET)")
+# override TARGET := $(OVERRIDE_TARGET)
+# endif
+# endif
+#
+
+# ----------------------------------------------------
+# Command macros
+# ----------------------------------------------------
+PREFIX = @prefix@
+INSTALL = @INSTALL@
+INSTALL_DIR = @INSTALL_DIR@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_DATA = @INSTALL_DATA@
+
+
+# ----------------------------------------------------
+# Erlang language section
+# ----------------------------------------------------
+ERL_ROOT_DIR = @ERLANG_ROOT_DIR@
+ERL_LIB_DIR = @ERLANG_LIB_DIR@
+DOCGEN_DIR = @ERLANG_LIB_DIR_erl_docgen@
+TEST_SERVER_DIR = @ERLANG_LIB_VER_test_server@
+EMULATOR = beam
+ERL_COMPILE_FLAGS += +debug_info
+ERLC_WFLAGS = -W
+ERLC = $(ERL_ROOT_DIR)/bin/erlc $(ERLC_WFLAGS) $(ERLC_FLAGS)
+ERL = $(ERL_ROOT_DIR)/bin/erl -boot start_clean
+#ERLC = @ERLC@ $(ERLC_WFLAGS) $(ERLC_FLAGS)
+#ERL = @ERL@ -boot start_clean
+
+ifneq (,$(findstring $(origin EBIN),$(DUBIOUS_ORIGINS)))
+EBIN = ../../ebin
+endif
+
+# Generated (non ebin) files...
+ifneq (,$(findstring $(origin EGEN),$(DUBIOUS_ORIGINS)))
+EGEN = .
+endif
+
+ifneq (,$(findstring $(origin ESRC),$(DUBIOUS_ORIGINS)))
+ESRC = .
+endif
+
+$(EBIN)/%.beam: $(EGEN)/%.erl
+ $(ERLC) $(ERL_COMPILE_FLAGS) -o$(EBIN) $<
+
+$(EBIN)/%.beam: $(ESRC)/%.erl
+ $(ERLC) $(ERL_COMPILE_FLAGS) -o$(EBIN) $<
+
+.erl.beam:
+ $(ERLC) $(ERL_COMPILE_FLAGS) -o$(dir $@) $<
+
+
+#
+# When .erl files are automatically created GNU make removes them if
+# they were the result of a chain of implicit rules. To prevent this
+# we say that all .erl files are "precious".
+#
+.PRECIOUS: %.erl %.fo
+
+
+# ----------------------------------------------------
+# Documentation section
+# ----------------------------------------------------
+# export VSN
+
+# DOCSUPPORT = 1
+
+# TOPDOCDIR=../../../../doc
+
+DOCDIR = ..
+
+PDFDIR=$(DOCDIR)/pdf
+
+HTMLDIR = $(DOCDIR)/html
+
+MAN1DIR = $(DOCDIR)/man1
+MAN2DIR = $(DOCDIR)/man2
+MAN3DIR = $(DOCDIR)/man3
+MAN4DIR = $(DOCDIR)/man4
+MAN6DIR = $(DOCDIR)/man6
+MAN9DIR = $(DOCDIR)/man9
+
+# HTML & GIF files that always are generated and must be delivered
+XML_COLL_FILES = $(XML_APPLICATION_FILES) $(XML_PART_FILES)
+DEFAULT_HTML_FILES = \
+ $(XML_COLL_FILES:%.xml=$(HTMLDIR)/%_frame.html) \
+ $(XML_COLL_FILES:%.xml=$(HTMLDIR)/%_first.html) \
+ $(XML_COLL_FILES:%.xml=$(HTMLDIR)/%_term.html) \
+ $(XML_COLL_FILES:%.xml=$(HTMLDIR)/%_cite.html) \
+ $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%_index.html) \
+ $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.kwc) \
+ $(HTMLDIR)/index.html
+
+DEFAULT_GIF_FILES = $(HTMLDIR)/min_head.gif
+
+#
+# Flags & Commands
+#
+XSLTPROC = @XSLTPROC@
+FOP = @FOP@
+
+DOCGEN=$(DOCGEN_DIR)
+
+$(MAN1DIR)/%.1:: %.xml
+ date=`date +"%B %e %Y"`; \
+ xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
+
+
+$(MAN2DIR)/%.2:: %.xml
+ date=`date +"%B %e %Y"`; \
+ xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
+
+
+$(MAN3DIR)/%.3:: %.xml
+ date=`date +"%B %e %Y"`; \
+ xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
+
+# left for compatibility
+$(MAN4DIR)/%.4:: %.xml
+ date=`date +"%B %e %Y"`; \
+ xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
+
+$(MAN4DIR)/%.5:: %.xml
+ date=`date +"%B %e %Y"`; \
+ xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
+
+# left for compatibility
+$(MAN6DIR)/%.6:: %_app.xml
+ date=`date +"%B %e %Y"`; \
+ xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
+
+$(MAN6DIR)/%.7:: %_app.xml
+ date=`date +"%B %e %Y"`; \
+ xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
+
+$(MAN9DIR)/%.9:: %.xml
+ date=`date +"%B %e %Y"`; \
+ xsltproc --output "$@" --stringparam company "Ericsson AB" --stringparam docgen "$(DOCGEN)" --stringparam gendate "$$date" --stringparam appname "$(APPLICATION)" --stringparam appver "$(VSN)" --xinclude -path $(DOCGEN)/priv/docbuilder_dtd -path $(DOCGEN)/priv/dtd_man_entities $(DOCGEN)/priv/xsl/db_man.xsl $<
+
+
+.xmlsrc.xml:
+ escript $(DOCGEN)/priv/bin/codeline_preprocessing.escript $< $@
+
+.fo.pdf:
+ $(FOP) -fo $< -pdf $@
+
diff --git a/lib/diameter/make/subdir.mk b/lib/diameter/make/subdir.mk
new file mode 100644
index 0000000000..24b08080ae
--- /dev/null
+++ b/lib/diameter/make/subdir.mk
@@ -0,0 +1,53 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1997-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+# Make include file for otp
+
+.PHONY: debug opt release docs release_docs tests release_tests \
+ clean depend valgrind
+
+#
+# Targets that don't affect documentation directories
+#
+opt debug release docs release_docs tests release_tests clean depend valgrind:
+ @set -e ; \
+ app_pwd=`pwd` ; \
+ if test -f vsn.mk; then \
+ echo "=== Entering application" `basename $$app_pwd` ; \
+ fi ; \
+ case "$(MAKE)" in *clearmake*) tflag="-T";; *) tflag="";; esac; \
+ for d in $(SUB_DIRS); do \
+ if test -f $$d/SKIP ; then \
+ echo "=== Skipping subdir $$d, reason:" ; \
+ cat $$d/SKIP ; \
+ echo "===" ; \
+ else \
+ if test ! -d $$d ; then \
+ echo "=== Skipping subdir $$d, it is missing" ; \
+ else \
+ xflag="" ; \
+ if test -f $$d/ignore_config_record.inf; then \
+ xflag=$$tflag ; \
+ fi ; \
+ (cd $$d && $(MAKE) $$xflag $@) || exit $$? ; \
+ fi ; \
+ fi ; \
+ done ; \
+ if test -f vsn.mk; then \
+ echo "=== Leaving application" `basename $$app_pwd` ; \
+ fi
diff --git a/lib/diameter/make/target.mk b/lib/diameter/make/target.mk
new file mode 100644
index 0000000000..4ae470b9e2
--- /dev/null
+++ b/lib/diameter/make/target.mk
@@ -0,0 +1,33 @@
+ifeq ($(OVERRIDE_TARGET),)
+
+ifeq ($(TARGET),)
+
+TARGET := $(shell $(DIAMETER_TOP)/autoconf/config.guess)
+
+else
+
+endif
+
+else
+
+ifneq ($(TARGET),)
+
+ifneq ($(TARGET), $(OVERRIDE_TARGET))
+$(warning overriding $$(TARGET) = \
+ "$(TARGET)" \
+ with \
+ $$(OVERRIDE_TARGET) = \
+ "$(OVERRIDE_TARGET)")
+else
+endif
+
+override TARGET := $(OVERRIDE_TARGET)
+
+else
+
+TARGET := $(OVERRIDE_TARGET)
+
+endif
+
+endif
+
diff --git a/lib/diameter/src/Makefile b/lib/diameter/src/Makefile
new file mode 100644
index 0000000000..6935eb053e
--- /dev/null
+++ b/lib/diameter/src/Makefile
@@ -0,0 +1,43 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+ifneq ($(ERL_TOP),)
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+else
+include $(DIAMETER_TOP)/make/target.mk
+include $(DIAMETER_TOP)/make/$(TARGET)/rules.mk
+endif
+
+# ----------------------------------------------------
+# Common Macros
+# ----------------------------------------------------
+
+include subdirs.mk
+
+SPECIAL_TARGETS =
+
+# ----------------------------------------------------
+# Default Subdir Targets
+# ----------------------------------------------------
+ifneq ($(ERL_TOP),)
+include $(ERL_TOP)/make/otp_subdir.mk
+else
+include $(DIAMETER_TOP)/make/subdir.mk
+endif
+#include ../make/subdir.mk
diff --git a/lib/diameter/src/app/.gitignore b/lib/diameter/src/app/.gitignore
new file mode 100644
index 0000000000..d388e61877
--- /dev/null
+++ b/lib/diameter/src/app/.gitignore
@@ -0,0 +1,6 @@
+
+/diameter_gen_*.erl
+/diameter_gen_*.hrl
+/depend.mk
+/diameter.mk
+
diff --git a/lib/diameter/src/app/Makefile b/lib/diameter/src/app/Makefile
new file mode 100644
index 0000000000..96b7736a90
--- /dev/null
+++ b/lib/diameter/src/app/Makefile
@@ -0,0 +1,218 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+#
+
+ifneq ($(ERL_TOP),)
+include $(ERL_TOP)/make/target.mk
+EBIN = ../../ebin
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+else
+include $(DIAMETER_TOP)/make/target.mk
+EBIN = ../../ebin
+include $(DIAMETER_TOP)/make/$(TARGET)/rules.mk
+endif
+
+
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+
+include ../../vsn.mk
+
+VSN=$(DIAMETER_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+
+RELSYSDIR = $(RELEASE_PATH)/lib/diameter-$(VSN)
+
+INCDIR = ../../include
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+include modules.mk
+
+diameter_gen_base_accounting.erl: \
+ $(EBIN)/diameter_gen_base_rfc3588.beam
+diameter_gen_relay.erl: \
+ $(EBIN)/diameter_gen_base_rfc3588.beam
+
+SPEC_MODULES = \
+ $(SPEC_FILES:%.dia=%)
+
+SPEC_ERL_FILES = \
+ $(SPEC_FILES:%.dia=%.erl)
+
+SPEC_HRL_FILES = \
+ $(SPEC_FILES:%.dia=%.hrl)
+
+MODULES = \
+ $(RUNTIME_MODULES) \
+ $(HELP_MODULES)
+
+APP_MODULES = \
+ $(RUNTIME_MODULES) \
+ $(SPEC_MODULES)
+
+TARGET_MODULES = \
+ $(APP_MODULES) \
+ $(HELP_MODULES)
+
+TARGET_FILES = \
+ $(TARGET_MODULES:%=$(EBIN)/%.$(EMULATOR)) \
+ $(APP_TARGET) \
+ $(APPUP_TARGET)
+
+ESCRIPT_FILES = \
+ ../../bin/diameterc
+
+APP_FILE = diameter.app
+APP_SRC = $(APP_FILE).src
+APP_TARGET = $(EBIN)/$(APP_FILE)
+
+APPUP_FILE = diameter.appup
+APPUP_SRC = $(APPUP_FILE).src
+APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+
+ifeq ($(TYPE),debug)
+ERL_COMPILE_FLAGS += -Ddebug
+endif
+
+include diameter.mk
+
+ERL_COMPILE_FLAGS += \
+ $(DIAMETER_ERL_COMPILE_FLAGS) \
+ -I$(INCDIR)
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+debug:
+ @$(MAKE) TYPE=debug opt
+
+opt: $(TARGET_FILES)
+
+clean:
+ rm -f $(TARGET_FILES) $(SPEC_ERL_FILES) $(SPEC_HRL_FILES)
+ rm -f $(APP_TARGET) $(APPUP_TARGET)
+ rm -f errs core *~ diameter_gen_*.forms diameter_gen_*.spec
+ rm -f depend.mk
+
+docs:
+
+info:
+ @echo ""
+ @echo "SPEC_FILES = $(FILES)"
+ @echo "MODULES = $(MODULES)"
+ @echo ""
+ @echo "EXTERNAL_HRL_FILES = $(EXTERNAL_HRL_FILES)"
+ @echo "INTERNAL_HRL_FILES = $(INTERNAL_HRL_FILES)"
+ @echo ""
+ @echo "EXAMPLE_FILES = $(EXAMPLE_FILES)"
+ @echo ""
+
+# ----------------------------------------------------
+# Special Build Targets
+# ----------------------------------------------------
+
+# Generate the app file and then modules into in. This shouldn't know
+# about ../transport but good enough for now.
+$(APP_TARGET): $(APP_SRC) \
+ ../../vsn.mk \
+ modules.mk \
+ ../transport/modules.mk
+ sed -e 's;%VSN%;$(VSN);' $< > $@
+ M=`echo $(APP_MODULES) | sed -e 's/^ *//' -e 's/ *$$//' -e 'y/ /,/'`; \
+ echo "/%APP_MODULES%/s//$$M/;w;q" | tr ';' '\n' \
+ | ed -s $@
+ $(MAKE) -C ../transport $(APP_TARGET) APP_TARGET=$(APP_TARGET)
+
+$(APPUP_TARGET): $(APPUP_SRC) ../../vsn.mk
+ sed -e 's;%VSN%;$(VSN);' $< > $@
+
+compiler:
+ $(MAKE) -C ../$@
+
+app: $(APP_TARGET) $(APPUP_TARGET)
+
+# erl/hrl from application spec
+diameter_gen_%.erl diameter_gen_%.hrl: diameter_gen_%.dia
+ ../../bin/diameterc -i $(EBIN) -o $(@D) $<
+
+$(SPEC_MODULES:%=$(EBIN)/%.$(EMULATOR)): $(EBIN)/diameter_exprecs.$(EMULATOR)
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+
+ifneq ($(ERL_TOP),)
+include $(ERL_TOP)/make/otp_release_targets.mk
+else
+include $(DIAMETER_TOP)/make/release_targets.mk
+endif
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/bin
+ $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) $(RELSYSDIR)/src/app
+ $(INSTALL_DIR) $(RELSYSDIR)/include
+ $(INSTALL_DIR) $(RELSYSDIR)/examples
+ $(INSTALL_SCRIPT) $(ESCRIPT_FILES) $(RELSYSDIR)/bin
+ $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DATA) $(MODULES:%=%.erl) $(SPEC_ERL_FILES) $(RELSYSDIR)/src/app
+ $(INSTALL_DATA) $(SPEC_FILES) $(RELSYSDIR)/src/app
+ $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src/app
+ $(INSTALL_DATA) $(EXTERNAL_HRL_FILES) $(SPEC_HRL_FILES) $(RELSYSDIR)/include
+ $(INSTALL_DATA) $(EXAMPLE_FILES) $(RELSYSDIR)/examples
+
+release_docs_spec:
+
+# ----------------------------------------------------
+# Dependencies
+# ----------------------------------------------------
+
+$(SPEC_FILES:%.dia=$(EBIN)/%.$(EMULATOR)): \
+ $(DIAMETER_TOP)/include/diameter.hrl \
+ $(DIAMETER_TOP)/include/diameter_gen.hrl
+
+depend: depend.mk
+
+# Generate dependencies makefile. It's assumed that the compile target
+# has already been made since it's currently not smart enough to not
+# force a rebuild of those beams dependent on generated hrls, and this
+# is a no-no at make release.
+depend.mk: depend.sed $(MODULES:%=%.erl) Makefile
+ (for f in $(MODULES); do \
+ sed -f $< $$f.erl | sed "s@/@/$$f@"; \
+ done) \
+ > $@
+
+-include depend.mk
+
+.PRECIOUS: $(SPEC_ERL_FILES) $(SPEC_HRL_FILES)
+.PHONY: app clean debug depend info opt compiler release_spec release_docs_spec
diff --git a/lib/diameter/src/app/depend.sed b/lib/diameter/src/app/depend.sed
new file mode 100644
index 0000000000..9df0133960
--- /dev/null
+++ b/lib/diameter/src/app/depend.sed
@@ -0,0 +1,31 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+
+#
+# Extract include dependencies from .erl files. The output is massaged
+# further in Makefile.
+#
+
+/^-include/!d
+/"diameter/!d
+
+s@^-include_lib("[^/]*@$(DIAMETER_TOP)@
+s@^-include("@@
+s@".*@@
+s@^@$(EBIN)/.$(EMULATOR): @
diff --git a/lib/diameter/src/app/diameter.app.src b/lib/diameter/src/app/diameter.app.src
new file mode 100644
index 0000000000..a806b5c78a
--- /dev/null
+++ b/lib/diameter/src/app/diameter.app.src
@@ -0,0 +1,28 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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, diameter,
+ [{description, "Diameter protocol"},
+ {vsn, "%VSN%"},
+ {modules, [%APP_MODULES%,%TRANSPORT_MODULES%]},
+ {registered, []},
+ {applications, [stdlib, kernel]},
+ {env, []},
+ {mod, {diameter_app, []}}
+ ]}.
diff --git a/lib/diameter/src/app/diameter.appup.src b/lib/diameter/src/app/diameter.appup.src
new file mode 100644
index 0000000000..6d8ceadb92
--- /dev/null
+++ b/lib/diameter/src/app/diameter.appup.src
@@ -0,0 +1,47 @@
+%% This is an -*- erlang -*- file.
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+{"%VSN%",
+ [
+ {"0.9",
+ [
+ {load_module, diameter, soft_purge, soft_purge, []},
+ {load_module, diameter_capx, soft_purge, soft_purge, []},
+ {load_module, diameter_codec, soft_purge, soft_purge, [diameter_lib]},
+ {load_module, diameter_lib, soft_purge, soft_purge, []},
+ {load_module, diameter_types, soft_purge, soft_purge, []},
+ {load_module, diameter_gen_base_accounting, soft_purge, soft_purge, []},
+ {load_module, diameter_gen_base_rfc3588, soft_purge, soft_purge, []},
+ {load_module, diameter_gen_relay, soft_purge, soft_purge, []},
+ {update, diameter_service, soft, soft_purge, soft_purge, [diameter_lib]},
+ {update, diameter_config, soft, soft_purge, soft_purge, []},
+ {update, diameter_peer, soft, soft_purge, soft_purge, []},
+ {update, diameter_peer_fsm, soft, soft_purge, soft_purge, [diameter_lib]},
+ {update, diameter_reg, soft, soft_purge, soft_purge, []},
+ {update, diameter_sctp, soft, soft_purge, soft_purge, []},
+ {update, diameter_stats, soft, soft_purge, soft_purge, []},
+ {update, diameter_sync, soft, soft_purge, soft_purge, []},
+ {update, diameter_watchdog, soft, soft_purge, soft_purge, [diameter_lib]}
+ ]
+ }
+ ],
+ [
+ ]
+}.
diff --git a/lib/diameter/src/app/diameter.erl b/lib/diameter/src/app/diameter.erl
new file mode 100644
index 0000000000..2f721421d8
--- /dev/null
+++ b/lib/diameter/src/app/diameter.erl
@@ -0,0 +1,190 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter).
+
+%% Configuration.
+-export([start_service/2,
+ stop_service/1,
+ add_transport/2,
+ remove_transport/2,
+ subscribe/1,
+ unsubscribe/1]).
+
+%% Traffic.
+-export([session_id/1,
+ origin_state_id/0,
+ call/3,
+ call/4]).
+
+%% Information.
+-export([services/0,
+ service_info/2]).
+
+%% Start/stop the application. In a "real" application this should
+%% typically be a consequence of specifying diameter in a release file
+%% rather than by calling start/stop explicitly.
+-export([start/0,
+ stop/0]).
+
+-include("diameter_internal.hrl").
+-include("diameter_types.hrl").
+
+%%% --------------------------------------------------------------------------
+%%% start/0
+%%% --------------------------------------------------------------------------
+
+-spec start()
+ -> ok
+ | {error, term()}.
+
+start() ->
+ application:start(?APPLICATION).
+
+%%% --------------------------------------------------------------------------
+%%% stop/0
+%%% --------------------------------------------------------------------------
+
+-spec stop()
+ -> ok
+ | {error, term()}.
+
+stop() ->
+ application:stop(?APPLICATION).
+
+%%% --------------------------------------------------------------------------
+%%% start_service/2
+%%% --------------------------------------------------------------------------
+
+-spec start_service(service_name(), [service_opt()])
+ -> ok
+ | {error, term()}.
+
+start_service(SvcName, Opts)
+ when is_list(Opts) ->
+ diameter_config:start_service(SvcName, Opts).
+
+%%% --------------------------------------------------------------------------
+%%% stop_service/1
+%%% --------------------------------------------------------------------------
+
+-spec stop_service(service_name())
+ -> ok
+ | {error, term()}.
+
+stop_service(SvcName) ->
+ diameter_config:stop_service(SvcName).
+
+%%% --------------------------------------------------------------------------
+%%% services/0
+%%% --------------------------------------------------------------------------
+
+-spec services()
+ -> [service_name()].
+
+services() ->
+ [Name || {Name, _} <- diameter_service:services()].
+
+%%% --------------------------------------------------------------------------
+%%% service_info/2
+%%% --------------------------------------------------------------------------
+
+-spec service_info(service_name(), atom() | [atom()])
+ -> any().
+
+service_info(SvcName, Option) ->
+ diameter_service:info(SvcName, Option).
+
+%%% --------------------------------------------------------------------------
+%%% add_transport/3
+%%% --------------------------------------------------------------------------
+
+-spec add_transport(service_name(), {listen|connect, [transport_opt()]})
+ -> {ok, transport_ref()}
+ | {error, term()}.
+
+add_transport(SvcName, {T, Opts} = Cfg)
+ when is_list(Opts), (T == connect orelse T == listen) ->
+ diameter_config:add_transport(SvcName, Cfg).
+
+%%% --------------------------------------------------------------------------
+%%% remove_transport/2
+%%% --------------------------------------------------------------------------
+
+-spec remove_transport(service_name(), transport_pred())
+ -> ok | {error, term()}.
+
+remove_transport(SvcName, Pred) ->
+ diameter_config:remove_transport(SvcName, Pred).
+
+%%% --------------------------------------------------------------------------
+%%% # subscribe(SvcName)
+%%%
+%%% Description: Subscribe to #diameter_event{} messages for the specified
+%%% service.
+%%% --------------------------------------------------------------------------
+
+-spec subscribe(service_name())
+ -> true.
+
+subscribe(SvcName) ->
+ diameter_service:subscribe(SvcName).
+
+%%% --------------------------------------------------------------------------
+%%% # unsubscribe(SvcName)
+%%% --------------------------------------------------------------------------
+
+-spec unsubscribe(service_name())
+ -> true.
+
+unsubscribe(SvcName) ->
+ diameter_service:unsubscribe(SvcName).
+
+%%% ----------------------------------------------------------
+%%% # session_id/1
+%%% ----------------------------------------------------------
+
+-spec session_id('DiameterIdentity'())
+ -> 'OctetString'().
+
+session_id(Ident) ->
+ diameter_session:session_id(Ident).
+
+%%% ----------------------------------------------------------
+%%% # origin_state_id/0
+%%% ----------------------------------------------------------
+
+-spec origin_state_id()
+ -> 'Unsigned32'().
+
+origin_state_id() ->
+ diameter_session:origin_state_id().
+
+%%% --------------------------------------------------------------------------
+%%% # call/[34]
+%%% --------------------------------------------------------------------------
+
+-spec call(service_name(), app_alias(), any(), [call_opt()])
+ -> any().
+
+call(SvcName, App, Message, Options) ->
+ diameter_service:call(SvcName, {alias, App}, Message, Options).
+
+call(SvcName, App, Message) ->
+ call(SvcName, App, Message, []).
diff --git a/lib/diameter/src/app/diameter.mk.in b/lib/diameter/src/app/diameter.mk.in
new file mode 100644
index 0000000000..c161064303
--- /dev/null
+++ b/lib/diameter/src/app/diameter.mk.in
@@ -0,0 +1,47 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+DIAMETER_TOP = @DIAMETER_TOP@
+
+# ifneq ($(PREFIX),)
+# ifeq ($(TESTROOT),)
+# TESTROOT = $(PREFIX)
+# endif
+# endif
+
+ifeq ($(USE_DIAMETER_TEST_CODE), true)
+ERL_COMPILE_FLAGS += -DDIAMETER_TEST_CODE=mona_lisa_spelar_doom
+endif
+
+ifeq ($(USE_DIAMETER_HIPE), true)
+ERL_COMPILE_FLAGS += +native
+endif
+
+ifeq ($(WARN_UNUSED_WARS), true)
+ERL_COMPILE_FLAGS += +warn_unused_vars
+endif
+
+DIAMETER_APP_VSN_COMPILE_FLAGS = \
+ +'{parse_transform,sys_pre_attributes}' \
+ +'{attribute,insert,app_vsn,$(APP_VSN)}'
+
+DIAMETER_ERL_COMPILE_FLAGS += \
+ -pa $(DIAMETER_TOP)/ebin \
+ $(DIAMETER_APP_VSN_COMPILE_FLAGS)
+
diff --git a/lib/diameter/src/app/diameter_app.erl b/lib/diameter/src/app/diameter_app.erl
new file mode 100644
index 0000000000..600f7ff04d
--- /dev/null
+++ b/lib/diameter/src/app/diameter_app.erl
@@ -0,0 +1,36 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_app).
+
+-behaviour(application).
+
+%% application callbacks
+-export([start/2,
+ stop/1]).
+
+%% start/2
+
+start(_Type, _Args) ->
+ diameter_sup:start_link().
+
+%% stop/1
+
+stop(_) ->
+ ok.
diff --git a/lib/diameter/src/app/diameter_callback.erl b/lib/diameter/src/app/diameter_callback.erl
new file mode 100644
index 0000000000..6d5c8cdca1
--- /dev/null
+++ b/lib/diameter/src/app/diameter_callback.erl
@@ -0,0 +1,91 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 minimal application callback module.
+%%
+
+-module(diameter_callback).
+
+-export([peer_up/3,
+ peer_down/3,
+ pick_peer/4,
+ prepare_request/3,
+ prepare_retransmit/3,
+ handle_request/3,
+ handle_answer/4,
+ handle_error/4]).
+
+-include_lib("diameter/include/diameter.hrl").
+
+%%% ----------------------------------------------------------
+%%% # peer_up/3
+%%% ----------------------------------------------------------
+
+peer_up(_Svc, _Peer, State) ->
+ State.
+
+%%% ----------------------------------------------------------
+%%% # peer_down/3
+%%% ----------------------------------------------------------
+
+peer_down(_SvcName, _Peer, State) ->
+ State.
+
+%%% ----------------------------------------------------------
+%%% # pick_peer/4
+%%% ----------------------------------------------------------
+
+pick_peer([Peer|_], _, _SvcName, _State) ->
+ {ok, Peer}.
+
+%%% ----------------------------------------------------------
+%%% # prepare_request/3
+%%% ----------------------------------------------------------
+
+prepare_request(Pkt, _SvcName, _Peer) ->
+ {send, Pkt}.
+
+%%% ----------------------------------------------------------
+%%% # prepare_retransmit/3
+%%% ----------------------------------------------------------
+
+prepare_retransmit(Pkt, _SvcName, _Peer) ->
+ {send, Pkt}.
+
+%%% ----------------------------------------------------------
+%%% # handle_request/3
+%%% ----------------------------------------------------------
+
+handle_request(_Pkt, _SvcName, _Peer) ->
+ {protocol_error, 3001}. %% DIAMETER_COMMAND_UNSUPPORTED
+
+%%% ----------------------------------------------------------
+%%% # handle_answer/4
+%%% ----------------------------------------------------------
+
+handle_answer(#diameter_packet{msg = Ans}, _Req, _SvcName, _Peer) ->
+ Ans.
+
+%%% ---------------------------------------------------------------------------
+%%% # handle_error/4
+%%% ---------------------------------------------------------------------------
+
+handle_error(Reason, _Req, _SvcName, _Peer) ->
+ {error, Reason}.
diff --git a/lib/diameter/src/app/diameter_capx.erl b/lib/diameter/src/app/diameter_capx.erl
new file mode 100644
index 0000000000..138e76411e
--- /dev/null
+++ b/lib/diameter/src/app/diameter_capx.erl
@@ -0,0 +1,405 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 module builds CER and CEA records for use during capabilities
+%% exchange. All of a CER/CEA is built from AVP values configured on
+%% the service in question but values for Supported-Vendor-Id,
+%% Vendor-Specific-Application-Id, Auth-Application-Id and
+%% Acct-Application-id are also obtained using an older method that
+%% remains only for backwards compatibility. With this method, each
+%% dictionary module was required to export a cer/0 that returned a
+%% diameter_base_CER record (or corresponding list, although the list
+%% is also a later addition). Each returned CER contributes its member
+%% values for the aforementioned four AVPs to the resulting CER, with
+%% remaining AVP's either unspecified or identical to those configured
+%% on the service. Auth-Application-Id and Acct-Application-id were
+%% originally treated a little differently, each callback being
+%% required to return either no value of the same value as the other
+%% callbacks, but this coupled the callback modules unnecessarily. (A
+%% union is backwards compatible to boot.)
+%%
+%% Values obtained from the service and callbacks are all included
+%% when building a CER. Older code with only callback can continue to
+%% use them, newer code should probably stick to service configuration
+%% (since this is more explicit) or mix at their own peril.
+%%
+%% The cer/0 callback is now undocumented (despite never being fully
+%% documented to begin with) and should be considered deprecated even
+%% by those poor souls still using it.
+%%
+
+-module(diameter_capx).
+
+-export([build_CER/1,
+ recv_CER/2,
+ recv_CEA/2,
+ make_caps/2]).
+
+-include_lib("diameter/include/diameter.hrl").
+-include("diameter_internal.hrl").
+-include("diameter_types.hrl").
+-include("diameter_gen_base_rfc3588.hrl").
+
+-define(SUCCESS, ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_SUCCESS').
+-define(NOAPP, ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_NO_COMMON_APPLICATION').
+-define(NOSECURITY, ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_NO_COMMON_SECURITY').
+
+-define(NO_INBAND_SECURITY, 0).
+-define(TLS, 1).
+
+%% ===========================================================================
+
+-type tried(T) :: {ok, T} | {error, {term(), list()}}.
+
+-spec build_CER(#diameter_caps{})
+ -> tried(#diameter_base_CER{}).
+
+build_CER(Caps) ->
+ try_it([fun bCER/1, Caps]).
+
+-spec recv_CER(#diameter_base_CER{}, #diameter_service{})
+ -> tried({['Unsigned32'()], #diameter_caps{}, #diameter_base_CEA{}}).
+
+recv_CER(CER, Svc) ->
+ try_it([fun rCER/2, CER, Svc]).
+
+-spec recv_CEA(#diameter_base_CEA{}, #diameter_service{})
+ -> tried({['Unsigned32'()], ['Unsigned32'()], #diameter_caps{}}).
+
+recv_CEA(CEA, Svc) ->
+ try_it([fun rCEA/2, CEA, Svc]).
+
+make_caps(Caps, Opts) ->
+ try_it([fun mk_caps/2, Caps, Opts]).
+
+%% ===========================================================================
+%% ===========================================================================
+
+try_it([Fun | Args]) ->
+ try apply(Fun, Args) of
+ T -> {ok, T}
+ catch
+ throw: ?FAILURE(Reason) -> {error, {Reason, Args}}
+ end.
+
+%% mk_caps/2
+
+mk_caps(Caps0, Opts) ->
+ {Caps, _} = lists:foldl(fun set_cap/2,
+ {Caps0, #diameter_caps{_ = false}},
+ Opts),
+ Caps.
+
+-define(SC(K,F),
+ set_cap({K, Val}, {Caps, #diameter_caps{F = false} = C}) ->
+ {Caps#diameter_caps{F = cap(K, Val)}, C#diameter_caps{F = true}}).
+
+?SC('Origin-Host', origin_host);
+?SC('Origin-Realm', origin_realm);
+?SC('Host-IP-Address', host_ip_address);
+?SC('Vendor-Id', vendor_id);
+?SC('Product-Name', product_name);
+?SC('Origin-State-Id', origin_state_id);
+?SC('Supported-Vendor-Id', supported_vendor_id);
+?SC('Auth-Application-Id', auth_application_id);
+?SC('Inband-Security-Id', inband_security_id);
+?SC('Acct-Application-Id', acct_application_id);
+?SC('Vendor-Specific-Application-Id', vendor_specific_application_id);
+?SC('Firmware-Revision', firmware_revision);
+
+set_cap({Key, _}, _) ->
+ ?THROW({duplicate, Key}).
+
+cap(K, V)
+ when K == 'Origin-Host';
+ K == 'Origin-Realm';
+ K == 'Vendor-Id';
+ K == 'Product-Name' ->
+ V;
+
+cap('Host-IP-Address', Vs)
+ when is_list(Vs) ->
+ lists:map(fun ipaddr/1, Vs);
+
+cap('Firmware-Revision', V) ->
+ [V];
+
+cap(_, Vs)
+ when is_list(Vs) ->
+ Vs;
+
+cap(K, V) ->
+ ?THROW({invalid, K, V}).
+
+ipaddr(A) ->
+ try
+ diameter_lib:ipaddr(A)
+ catch
+ error: {invalid_address, _} = T ->
+ ?THROW(T)
+ end.
+
+%% bCER/1
+%%
+%% Build a CER record to send to a remote peer.
+
+%% Use the fact that diameter_caps has the same field names as CER.
+bCER(#diameter_caps{} = Rec) ->
+ #diameter_base_CER{}
+ = list_to_tuple([diameter_base_CER | tl(tuple_to_list(Rec))]).
+
+%% rCER/2
+%%
+%% Build a CEA record to send to a remote peer in response to an
+%% incoming CER. RFC 3588 gives no guidance on what should be sent
+%% here: should we advertise applications that the peer hasn't sent in
+%% its CER (aside from the relay application) or not? If we send
+%% applications that the peer hasn't advertised then the peer may have
+%% to be aware of the possibility. If we don't then we just look like
+%% a server that supports a subset (possibly) of what the client
+%% advertised, so this feels like the path of least incompatibility.
+%% However, the current draft standard (draft-ietf-dime-rfc3588bis-26,
+%% expires 24 July 2011) says this in section 5.3, Capabilities
+%% Exchange:
+%%
+%% The receiver of the Capabilities-Exchange-Request (CER) MUST
+%% determine common applications by computing the intersection of its
+%% own set of supported Application Id against all of the application
+%% identifier AVPs (Auth-Application-Id, Acct-Application-Id and Vendor-
+%% Specific-Application-Id) present in the CER. The value of the
+%% Vendor-Id AVP in the Vendor-Specific-Application-Id MUST NOT be used
+%% during computation. The sender of the Capabilities-Exchange-Answer
+%% (CEA) SHOULD include all of its supported applications as a hint to
+%% the receiver regarding all of its application capabilities.
+%%
+%% Both RFC and the draft also say this:
+%%
+%% The receiver only issues commands to its peers that have advertised
+%% support for the Diameter application that defines the command. A
+%% Diameter node MUST cache the supported applications in order to
+%% ensure that unrecognized commands and/or AVPs are not unnecessarily
+%% sent to a peer.
+%%
+%% That is, each side sends all of its capabilities and is responsible for
+%% not sending commands that the peer doesn't support.
+
+%% 6.10. Inband-Security-Id AVP
+%%
+%% NO_INBAND_SECURITY 0
+%% This peer does not support TLS. This is the default value, if the
+%% AVP is omitted.
+%%
+%% TLS 1
+%% This node supports TLS security, as defined by [TLS].
+
+rCER(CER, #diameter_service{capabilities = LCaps} = Svc) ->
+ #diameter_base_CEA{}
+ = CEA
+ = cea_from_cer(bCER(LCaps)),
+
+ RCaps = capx_to_caps(CER),
+ SApps = common_applications(LCaps, RCaps, Svc),
+
+ {SApps,
+ RCaps,
+ build_CEA(SApps,
+ LCaps,
+ RCaps,
+ CEA#diameter_base_CEA{'Result-Code' = ?SUCCESS})}.
+
+%% TODO: 5.3 of RFC 3588 says we MUST return DIAMETER_NO_COMMON_APPLICATION
+%% in the CEA and SHOULD disconnect the transport. However, we have
+%% no way to guarantee the send before disconnecting.
+
+build_CEA([], _, _, CEA) ->
+ CEA#diameter_base_CEA{'Result-Code' = ?NOAPP};
+
+build_CEA(_, LCaps, RCaps, CEA) ->
+ case common_security(LCaps, RCaps) of
+ [] ->
+ CEA#diameter_base_CEA{'Result-Code' = ?NOSECURITY};
+ [_] = IS ->
+ CEA#diameter_base_CEA{'Inband-Security-Id' = IS}
+ end.
+
+%% common_security/2
+
+common_security(#diameter_caps{inband_security_id = LS},
+ #diameter_caps{inband_security_id = RS}) ->
+ cs(LS, RS).
+
+%% Unspecified is equivalent to NO_INBAND_SECURITY.
+cs([], RS) ->
+ cs([?NO_INBAND_SECURITY], RS);
+cs(LS, []) ->
+ cs(LS, [?NO_INBAND_SECURITY]);
+
+%% Agree on TLS if both parties support it. When sending CEA, this is
+%% to ensure the peer is clear that we will be expecting a TLS
+%% handshake since there is no ssl:maybe_accept that would allow the
+%% peer to choose between TLS or not upon reception of our CEA. When
+%% receiving CEA it deals with a server that isn't explicit about its choice.
+%% TODO: Make the choice configurable.
+cs(LS, RS) ->
+ Is = ordsets:to_list(ordsets:intersection(ordsets:from_list(LS),
+ ordsets:from_list(RS))),
+ case lists:member(?TLS, Is) of
+ true ->
+ [?TLS];
+ false when [] == Is ->
+ Is;
+ false ->
+ [hd(Is)] %% probably NO_INBAND_SECURITY
+ end.
+%% The only two values defined by RFC 3588 are NO_INBAND_SECURITY and
+%% TLS but don't enforce this. In theory this allows some other
+%% security mechanism we don't have to know about, although in
+%% practice something there may be a need for more synchronization
+%% than notification by way of an event subscription offers.
+
+%% cea_from_cer/1
+
+%% CER is a subset of CEA, the latter adding Result-Code and a few
+%% more AVP's.
+cea_from_cer(#diameter_base_CER{} = CER) ->
+ lists:foldl(fun(F,A) -> to_cea(CER, F, A) end,
+ #diameter_base_CEA{},
+ record_info(fields, diameter_base_CER)).
+
+to_cea(CER, Field, CEA) ->
+ try ?BASE:'#get-'(Field, CER) of
+ V -> ?BASE:'#set-'({Field, V}, CEA)
+ catch
+ error: _ -> CEA
+ end.
+
+%% rCEA/2
+
+rCEA(#diameter_base_CEA{'Result-Code' = RC}
+ = CEA,
+ #diameter_service{capabilities = LCaps}
+ = Svc) ->
+ RC == ?SUCCESS orelse ?THROW({'Result-Code', RC}),
+
+ RCaps = capx_to_caps(CEA),
+ SApps = common_applications(LCaps, RCaps, Svc),
+
+ [] == SApps andalso ?THROW(no_common_applications),
+
+ IS = common_security(LCaps, RCaps),
+
+ [] == IS andalso ?THROW(no_common_security),
+
+ {SApps, IS, RCaps};
+
+rCEA(CEA, _Svc) ->
+ ?THROW({invalid, CEA}).
+
+%% capx_to_caps/1
+
+capx_to_caps(#diameter_base_CEA{'Origin-Host' = OH,
+ 'Origin-Realm' = OR,
+ 'Host-IP-Address' = IP,
+ 'Vendor-Id' = VId,
+ 'Product-Name' = PN,
+ 'Origin-State-Id' = OSI,
+ 'Supported-Vendor-Id' = SV,
+ 'Auth-Application-Id' = Auth,
+ 'Inband-Security-Id' = IS,
+ 'Acct-Application-Id' = Acct,
+ 'Vendor-Specific-Application-Id' = VSA,
+ 'Firmware-Revision' = FR,
+ 'AVP' = X}) ->
+ #diameter_caps{origin_host = OH,
+ origin_realm = OR,
+ vendor_id = VId,
+ product_name = PN,
+ origin_state_id = OSI,
+ host_ip_address = IP,
+ supported_vendor_id = SV,
+ auth_application_id = Auth,
+ inband_security_id = IS,
+ acct_application_id = Acct,
+ vendor_specific_application_id = VSA,
+ firmware_revision = FR,
+ avp = X};
+
+capx_to_caps(#diameter_base_CER{} = CER) ->
+ capx_to_caps(cea_from_cer(CER)).
+
+%% ---------------------------------------------------------------------------
+%% ---------------------------------------------------------------------------
+
+%% common_applications/3
+%%
+%% Identify the (local) applications to be supported on the connection
+%% in question.
+
+common_applications(LCaps, RCaps, #diameter_service{applications = Apps}) ->
+ LA = app_union(LCaps),
+ RA = app_union(RCaps),
+
+ lists:foldl(fun(I,A) -> ca(I, Apps, RA, A) end, [], LA).
+
+ca(Id, Apps, RA, Acc) ->
+ Relay = lists:member(?APP_ID_RELAY, RA),
+ #diameter_app{alias = Alias} = find_app(Id, Apps),
+ tcons(Relay %% peer is a relay
+ orelse ?APP_ID_RELAY == Id %% we're a relay
+ orelse lists:member(Id, RA), %% app is supported by the peer
+ Id,
+ Alias,
+ Acc).
+%% 5.3 of the RFC states that a peer advertising itself as a relay must
+%% be interpreted as having common applications.
+
+%% Extract the list of all application identifiers from Auth-Application-Id,
+%% Acct-Application-Id and Vendor-Specific-Application-Id.
+app_union(#diameter_caps{auth_application_id = U,
+ acct_application_id = C,
+ vendor_specific_application_id = V}) ->
+ set_list(U ++ C ++ lists:flatmap(fun vsa_apps/1, V)).
+
+vsa_apps(#'diameter_base_Vendor-Specific-Application-Id'
+ {'Auth-Application-Id' = U,
+ 'Acct-Application-Id' = C}) ->
+ U ++ C;
+vsa_apps(L) ->
+ Rec = ?BASE:'#new-'('diameter_base_Vendor-Specific-Application-Id', L),
+ vsa_apps(Rec).
+
+%% It's a configuration error for a locally advertised application not
+%% to be represented in Apps. Don't just match on lists:keyfind/3 in
+%% order to generate a more helpful error.
+find_app(Id, Apps) ->
+ case lists:keyfind(Id, #diameter_app.id, Apps) of
+ #diameter_app{} = A ->
+ A;
+ false ->
+ ?THROW({app_not_configured, Id})
+ end.
+
+set_list(L) ->
+ sets:to_list(sets:from_list(L)).
+
+tcons(true, K, V, Acc) ->
+ [{K,V} | Acc];
+tcons(false, _, _, Acc) ->
+ Acc.
diff --git a/lib/diameter/src/app/diameter_codec.erl b/lib/diameter/src/app/diameter_codec.erl
new file mode 100644
index 0000000000..d88f42fb7c
--- /dev/null
+++ b/lib/diameter/src/app/diameter_codec.erl
@@ -0,0 +1,561 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_codec).
+
+-export([encode/2,
+ decode/2,
+ decode/3,
+ collect_avps/1,
+ decode_header/1,
+ sequence_numbers/1,
+ hop_by_hop_id/2,
+ msg_name/1,
+ msg_id/1]).
+
+%% Towards generated encoders (from diameter_gen.hrl).
+-export([pack_avp/1,
+ pack_avp/2]).
+
+-include_lib("diameter/include/diameter.hrl").
+-include("diameter_internal.hrl").
+
+-define(MASK(N,I), ((I) band (1 bsl (N)))).
+
+%% 0 1 2 3
+%% 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+%% +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+%% | Version | Message Length |
+%% +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+%% | command flags | Command-Code |
+%% +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+%% | Application-ID |
+%% +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+%% | Hop-by-Hop Identifier |
+%% +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+%% | End-to-End Identifier |
+%% +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+%% | AVPs ...
+%% +-+-+-+-+-+-+-+-+-+-+-+-+-
+
+%%% ---------------------------------------------------------------------------
+%%% # encode/[2-4]
+%%% ---------------------------------------------------------------------------
+
+encode(Mod, #diameter_packet{} = Pkt) ->
+ try
+ e(Mod, Pkt)
+ catch
+ error: Reason ->
+ %% Be verbose rather than letting the emulator truncate the
+ %% error report.
+ X = {Reason, ?STACK},
+ diameter_lib:error_report(X, {?MODULE, encode, [Mod, Pkt]}),
+ exit(X)
+ end;
+
+encode(Mod, Msg) ->
+ Seq = diameter_session:sequence(),
+ Hdr = #diameter_header{version = ?DIAMETER_VERSION,
+ end_to_end_id = Seq,
+ hop_by_hop_id = Seq},
+ encode(Mod, #diameter_packet{header = Hdr,
+ msg = Msg}).
+
+e(_, #diameter_packet{msg = [#diameter_header{} = Hdr | As]} = Pkt) ->
+ Avps = encode_avps(As),
+ Length = size(Avps) + 20,
+
+ #diameter_header{version = Vsn,
+ cmd_code = Code,
+ application_id = Aid,
+ hop_by_hop_id = Hid,
+ end_to_end_id = Eid}
+ = Hdr,
+
+ Flags = make_flags(0, Hdr),
+
+ Pkt#diameter_packet{bin = <<Vsn:8, Length:24,
+ Flags:8, Code:24,
+ Aid:32,
+ Hid:32,
+ Eid:32,
+ Avps/binary>>};
+
+e(Mod0, #diameter_packet{header = Hdr, msg = Msg} = Pkt) ->
+ #diameter_header{version = Vsn,
+ hop_by_hop_id = Hid,
+ end_to_end_id = Eid}
+ = Hdr,
+
+ {Mod, MsgName} = rec2msg(Mod0, Msg),
+ {Code, Flags0, Aid} = msg_header(Mod, MsgName, Hdr),
+ Flags = make_flags(Flags0, Hdr),
+
+ Avps = encode_avps(Mod, MsgName, values(Msg)),
+ Length = size(Avps) + 20,
+
+ Pkt#diameter_packet{header = Hdr#diameter_header
+ {length = Length,
+ cmd_code = Code,
+ application_id = Aid,
+ is_request = 0 /= ?MASK(7, Flags),
+ is_proxiable = 0 /= ?MASK(6, Flags),
+ is_error = 0 /= ?MASK(5, Flags),
+ is_retransmitted = 0 /= ?MASK(4, Flags)},
+ bin = <<Vsn:8, Length:24,
+ Flags:8, Code:24,
+ Aid:32,
+ Hid:32,
+ Eid:32,
+ Avps/binary>>}.
+
+%% make_flags/2
+
+make_flags(Flags0, #diameter_header{is_request = R,
+ is_proxiable = P,
+ is_error = E,
+ is_retransmitted = T}) ->
+ {Flags, 3} = lists:foldl(fun(B,{F,N}) -> {mf(B,F,N), N-1} end,
+ {Flags0, 7},
+ [R,P,E,T]),
+ Flags.
+
+mf(undefined, F, _) ->
+ F;
+mf(B, F, N) -> %% reset the affected bit
+ (F bxor (F band (1 bsl N))) bor bit(B, N).
+
+bit(true, N) -> 1 bsl N;
+bit(false, _) -> 0.
+
+%% values/1
+
+values([H|T])
+ when is_atom(H) ->
+ T;
+values(Avps) ->
+ Avps.
+
+%% encode_avps/3
+
+%% Specifying values as a #diameter_avp list bypasses arity and other
+%% checks: the values are expected to be already encoded and the AVP's
+%% presented are simply sent. This is needed for relay agents, since
+%% these have to be able to resend whatever comes.
+
+%% Message as a list of #diameter_avp{} ...
+encode_avps(_, _, [#diameter_avp{} | _] = Avps) ->
+ encode_avps(reorder(Avps, [], Avps));
+
+%% ... or as a tuple list or record.
+encode_avps(Mod, MsgName, Values) ->
+ Mod:encode_avps(MsgName, Values).
+
+%% reorder/1
+
+reorder([#diameter_avp{index = 0} | _] = Avps, Acc, _) ->
+ Avps ++ Acc;
+
+reorder([#diameter_avp{index = N} = A | Avps], Acc, _)
+ when is_integer(N) ->
+ lists:reverse(Avps, [A | Acc]);
+
+reorder([H | T], Acc, Avps) ->
+ reorder(T, [H | Acc], Avps);
+
+reorder([], Acc, _) ->
+ Acc.
+
+%% encode_avps/1
+
+encode_avps(Avps) ->
+ list_to_binary(lists:map(fun pack_avp/1, Avps)).
+
+%% msg_header/3
+
+msg_header(Mod, MsgName, Header) ->
+ {Code, Flags, ApplId} = h(Mod, MsgName, Header),
+ {Code, p(Flags, Header), ApplId}.
+
+%% 6.2 of 3588 requires the same 'P' bit on an answer as on the
+%% request.
+
+p(Flags, #diameter_header{is_request = true,
+ is_proxiable = P}) ->
+ Flags band (2#10110000 bor choose(P, 2#01000000, 0));
+p(Flags, _) ->
+ Flags.
+
+h(Mod, 'answer-message' = MsgName, Header) ->
+ ?BASE = Mod,
+ #diameter_header{cmd_code = Code} = Header,
+ {_, Flags, ApplId} = ?BASE:msg_header(MsgName),
+ {Code, Flags, ApplId};
+
+h(Mod, MsgName, _) ->
+ Mod:msg_header(MsgName).
+
+%% rec2msg/2
+
+rec2msg(_, ['answer-message' = M | _]) ->
+ {?BASE, M};
+
+rec2msg(Mod, [MsgName|_])
+ when is_atom(MsgName) ->
+ {Mod, MsgName};
+
+rec2msg(Mod, Rec) ->
+ R = element(1, Rec),
+ A = 'answer-message',
+ case ?BASE:msg2rec(A) of
+ R ->
+ {?BASE, A};
+ _ ->
+ {Mod, Mod:rec2msg(R)}
+ end.
+
+%%% ---------------------------------------------------------------------------
+%%% # decode/2
+%%% ---------------------------------------------------------------------------
+
+%% Unsuccessfully decoded AVPs will be placed in #diameter_packet.errors.
+
+decode(Mod, Pkt) ->
+ decode(Mod:id(), Mod, Pkt).
+
+%% If we're a relay application then just extract the avp's without
+%% any decoding of their data since we don't know the application in
+%% question.
+decode(?APP_ID_RELAY, _, #diameter_packet{} = Pkt) ->
+ case collect_avps(Pkt) of
+ {Bs, As} ->
+ Pkt#diameter_packet{avps = As,
+ errors = [Bs]};
+ As ->
+ Pkt#diameter_packet{avps = As}
+ end;
+
+%% Otherwise decode using the dictionary.
+decode(_, Mod, #diameter_packet{header = Hdr} = Pkt)
+ when is_atom(Mod) ->
+ #diameter_header{cmd_code = CmdCode,
+ is_request = IsRequest,
+ is_error = IsError}
+ = Hdr,
+
+ {M, MsgName} = if IsError andalso not IsRequest ->
+ {?BASE, 'answer-message'};
+ true ->
+ {Mod, Mod:msg_name(CmdCode, IsRequest)}
+ end,
+
+ decode_avps(MsgName, M, Pkt, collect_avps(Pkt));
+
+decode(Id, Mod, Bin)
+ when is_bitstring(Bin) ->
+ decode(Id, Mod, #diameter_packet{header = decode_header(Bin), bin = Bin}).
+
+decode_avps(MsgName, Mod, Pkt, {Bs, Avps}) -> %% invalid avp bits ...
+ ?LOG(invalid, Pkt#diameter_packet.bin),
+ #diameter_packet{errors = Failed}
+ = P
+ = decode_avps(MsgName, Mod, Pkt, Avps),
+ P#diameter_packet{errors = [Bs | Failed]};
+
+decode_avps('', Mod, Pkt, Avps) -> %% unknown message ...
+ ?LOG(unknown, {Mod, Pkt#diameter_packet.header}),
+ Pkt#diameter_packet{avps = lists:reverse(Avps),
+ errors = [3001]}; %% DIAMETER_COMMAND_UNSUPPORTED
+%% msg = undefined identifies this case.
+
+decode_avps(MsgName, Mod, Pkt, Avps) -> %% ... or not
+ {Rec, As, Failed} = Mod:decode_avps(MsgName, Avps),
+ ?LOGC([] /= Failed, failed, {Mod, Failed}),
+ Pkt#diameter_packet{msg = Rec,
+ errors = Failed,
+ avps = As}.
+
+%%% ---------------------------------------------------------------------------
+%%% # decode_header/1
+%%% ---------------------------------------------------------------------------
+
+decode_header(<<Version:8,
+ MsgLength:24,
+ CmdFlags:1/binary,
+ CmdCode:24,
+ ApplicationId:32,
+ HopByHopId:32,
+ EndToEndId:32,
+ _/bitstring>>) ->
+ <<R:1, P:1, E:1, T:1, _:4>>
+ = CmdFlags,
+ %% 3588 (ch 3) says that reserved bits MUST be set to 0 and ignored
+ %% by the receiver.
+
+ %% The RFC is quite unclear about the order of the bits in this
+ %% case. It writes
+ %%
+ %% 0 1 2 3 4 5 6 7
+ %% +-+-+-+-+-+-+-+-+
+ %% |R P E T r r r r|
+ %% +-+-+-+-+-+-+-+-+
+ %%
+ %% in defining these but the scale refers to the (big endian)
+ %% transmission order, first to last, not the bit order. That is,
+ %% R is the high order bit. It's odd that a standard reserves
+ %% low-order bit rather than high-order ones.
+
+ #diameter_header{version = Version,
+ length = MsgLength,
+ cmd_code = CmdCode,
+ application_id = ApplicationId,
+ hop_by_hop_id = HopByHopId,
+ end_to_end_id = EndToEndId,
+ is_request = 1 == R,
+ is_proxiable = 1 == P,
+ is_error = 1 == E,
+ is_retransmitted = 1 == T};
+
+decode_header(_) ->
+ false.
+
+%%% ---------------------------------------------------------------------------
+%%% # sequence_numbers/1
+%%% ---------------------------------------------------------------------------
+
+%% The End-To-End identifier must be unique for at least 4 minutes. We
+%% maintain a 24-bit wraparound counter, and add an 8-bit persistent
+%% wraparound counter. The 8-bit counter is incremented each time the
+%% system is restarted.
+
+sequence_numbers(#diameter_packet{bin = Bin})
+ when is_binary(Bin) ->
+ sequence_numbers(Bin);
+
+sequence_numbers(#diameter_packet{header = #diameter_header{} = H}) ->
+ sequence_numbers(H);
+
+sequence_numbers(#diameter_header{hop_by_hop_id = H,
+ end_to_end_id = E}) ->
+ {H,E};
+
+sequence_numbers(<<_:12/binary, H:32, E:32, _/binary>>) ->
+ {H,E}.
+
+%%% ---------------------------------------------------------------------------
+%%% # hop_by_hop_id/2
+%%% ---------------------------------------------------------------------------
+
+hop_by_hop_id(Id, <<H:12/binary, _:32, T/binary>>) ->
+ <<H/binary, Id:32, T/binary>>.
+
+%%% ---------------------------------------------------------------------------
+%%% # msg_name/1
+%%% ---------------------------------------------------------------------------
+
+msg_name(#diameter_header{application_id = ?APP_ID_COMMON,
+ cmd_code = C,
+ is_request = R}) ->
+ ?BASE:msg_name(C,R);
+
+msg_name(Hdr) ->
+ msg_id(Hdr).
+
+%% Note that messages in different applications could have the same
+%% name.
+
+%%% ---------------------------------------------------------------------------
+%%% # msg_id/1
+%%% ---------------------------------------------------------------------------
+
+msg_id(#diameter_packet{msg = [#diameter_header{} = Hdr | _]}) ->
+ msg_id(Hdr);
+
+msg_id(#diameter_packet{header = #diameter_header{} = Hdr}) ->
+ msg_id(Hdr);
+
+msg_id(#diameter_header{application_id = A,
+ cmd_code = C,
+ is_request = R}) ->
+ {A, C, if R -> 1; true -> 0 end};
+
+msg_id(<<_:32, Rbit:1, _:7, CmdCode:24, ApplId:32, _/bitstring>>) ->
+ {ApplId, CmdCode, Rbit}.
+
+%%% ---------------------------------------------------------------------------
+%%% # collect_avps/1
+%%% ---------------------------------------------------------------------------
+
+%% Note that the returned list of AVP's is reversed relative to their
+%% order in the binary. Note also that grouped avp's aren't unraveled,
+%% only those at the top level.
+
+collect_avps(#diameter_packet{bin = Bin}) ->
+ <<_:20/binary, Avps/bitstring>> = Bin,
+ collect_avps(Avps);
+
+collect_avps(Bin) ->
+ collect_avps(Bin, 0, []).
+
+collect_avps(<<>>, _, Acc) ->
+ Acc;
+collect_avps(Bin, N, Acc) ->
+ try split_avp(Bin) of
+ {Rest, AVP} ->
+ collect_avps(Rest, N+1, [AVP#diameter_avp{index = N} | Acc])
+ catch
+ ?FAILURE(_) ->
+ {Bin, Acc}
+ end.
+
+%% 0 1 2 3
+%% 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+%% +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+%% | AVP Code |
+%% +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+%% |V M P r r r r r| AVP Length |
+%% +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+%% | Vendor-ID (opt) |
+%% +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+%% | Data ...
+%% +-+-+-+-+-+-+-+-+
+
+%% split_avp/1
+
+split_avp(Bin) ->
+ 8 =< size(Bin) orelse ?THROW(truncated_header),
+
+ <<Code:32, Flags:1/binary, Length:24, Rest/bitstring>>
+ = Bin,
+
+ DataSize = Length - 8, % size(Code+Flags+Length) = 8 octets
+ PadSize = (4 - (DataSize rem 4)) rem 4,
+
+ DataSize + PadSize =< size(Rest)
+ orelse ?THROW(truncated_data),
+
+ <<Data:DataSize/binary, _:PadSize/binary, R/bitstring>>
+ = Rest,
+ <<Vbit:1, Mbit:1, Pbit:1, _Reserved:5>>
+ = Flags,
+
+ 0 == Vbit orelse 4 =< size(Data)
+ orelse ?THROW(truncated_vendor_id),
+
+ {Vid, D} = vid(Vbit, Data),
+ {R, #diameter_avp{code = Code,
+ vendor_id = Vid,
+ is_mandatory = 1 == Mbit,
+ need_encryption = 1 == Pbit,
+ data = D}}.
+
+%% The RFC is a little misleading when stating that OctetString is
+%% padded to a 32-bit boundary while other types align naturally. All
+%% other types are already multiples of 32 bits so there's no need to
+%% distinguish between types here. Any invalid lengths will result in
+%% decode error in diameter_types.
+
+vid(1, <<Vid:32, Data/bitstring>>) ->
+ {Vid, Data};
+vid(0, Data) ->
+ {undefined, Data}.
+
+%%% ---------------------------------------------------------------------------
+%%% # pack_avp/1
+%%% ---------------------------------------------------------------------------
+
+%% The normal case here is data as an #diameter_avp{} list or an
+%% iolist, which are the cases that generated codec modules use. The
+%% other case is as a convenience in the relay case in which the
+%% dictionary doesn't know about specific AVP's.
+
+%% Grouped AVP whose components need packing ...
+pack_avp(#diameter_avp{data = [#diameter_avp{} | _] = Avps} = A) ->
+ pack_avp(A#diameter_avp{data = encode_avps(Avps)});
+
+%% ... data as a type/value tuple, possibly with header data, ...
+pack_avp(#diameter_avp{data = {Type, Value}} = A)
+ when is_atom(Type) ->
+ pack_avp(A#diameter_avp{data = diameter_types:Type(encode, Value)});
+pack_avp(#diameter_avp{data = {{_,_,_} = T, {Type, Value}}}) ->
+ pack_avp(T, iolist_to_binary(diameter_types:Type(encode, Value)));
+pack_avp(#diameter_avp{data = {{_,_,_} = T, Bin}})
+ when is_binary(Bin) ->
+ pack_avp(T, Bin);
+pack_avp(#diameter_avp{data = {Dict, Name, Value}} = A) ->
+ {Code, _Flags, Vid} = Hdr = Dict:avp_header(Name),
+ {Name, Type} = Dict:avp_name(Code, Vid),
+ pack_avp(A#diameter_avp{data = {Hdr, {Type, Value}}});
+
+%% ... or as an iolist.
+pack_avp(#diameter_avp{code = Code,
+ vendor_id = V,
+ is_mandatory = M,
+ need_encryption = P,
+ data = Data}) ->
+ Flags = lists:foldl(fun flag_avp/2, 0, [{V /= undefined, 2#10000000},
+ {M, 2#01000000},
+ {P, 2#00100000}]),
+ pack_avp({Code, Flags, V}, iolist_to_binary(Data)).
+
+flag_avp({true, B}, F) ->
+ F bor B;
+flag_avp({false, _}, F) ->
+ F.
+
+%%% ---------------------------------------------------------------------------
+%%% # pack_avp/2
+%%% ---------------------------------------------------------------------------
+
+pack_avp({Code, Flags, VendorId}, Bin)
+ when is_binary(Bin) ->
+ Sz = size(Bin),
+ pack_avp(Code, Flags, VendorId, Sz, pad(Sz rem 4, Bin)).
+
+pad(0, Bin) ->
+ Bin;
+pad(N, Bin) ->
+ P = 8*(4-N),
+ <<Bin/binary, 0:P>>.
+%% Note that padding is not included in the length field as mandated by
+%% the RFC.
+
+%% pack_avp/5
+%%
+%% Prepend the vendor id as required.
+
+pack_avp(Code, Flags, Vid, Sz, Bin)
+ when 0 == Flags band 2#10000000 ->
+ undefined = Vid, %% sanity check
+ pack_avp(Code, Flags, Sz, Bin);
+
+pack_avp(Code, Flags, Vid, Sz, Bin) ->
+ pack_avp(Code, Flags, Sz+4, <<Vid:32, Bin/binary>>).
+
+%% pack_avp/4
+
+pack_avp(Code, Flags, Sz, Bin) ->
+ Length = Sz + 8,
+ <<Code:32, Flags:8, Length:24, Bin/binary>>.
+
+%% ===========================================================================
+
+choose(true, X, _) -> X;
+choose(false, _, X) -> X.
diff --git a/lib/diameter/src/app/diameter_config.erl b/lib/diameter/src/app/diameter_config.erl
new file mode 100644
index 0000000000..a6b48fe65b
--- /dev/null
+++ b/lib/diameter/src/app/diameter_config.erl
@@ -0,0 +1,676 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 module writes service/transport configuration to the table
+%% diameter_config, so that the config will survive service process
+%% death, and then turns it into calls towards diameter_service. It
+%% also restarts services upon their death.
+%%
+%% The table diameter_config is only written here while
+%% diameter_service reads. This is all somewhat after the fact. Once
+%% upon a time the config was only stored in the service process,
+%% causing much grief if these processes died (which they did with
+%% some regularity) and one was forced to reconfigure. This module was
+%% then inserted into the service start in order to keep a more
+%% permanent record of the config. That said, service processes are
+%% now much more robust than they once were and crashing is a thing of
+%% the past.
+%%
+
+-module(diameter_config).
+-compile({no_auto_import, [monitor/2]}).
+
+-behaviour(gen_server).
+
+-export([start_service/2,
+ stop_service/1,
+ add_transport/2,
+ remove_transport/2,
+ have_transport/2,
+ lookup/1]).
+
+%% child server start
+-export([start_link/0]).
+
+%% gen_server callbacks
+-export([init/1,
+ terminate/2,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ code_change/3]).
+
+%% diameter_sync requests.
+-export([sync/1]).
+
+%% debug
+-export([state/0,
+ uptime/0]).
+
+-include_lib("diameter/include/diameter.hrl").
+-include("diameter_internal.hrl").
+
+%% Server state.
+-record(state, {id = now()}).
+
+%% Registered name of the server.
+-define(SERVER, ?MODULE).
+
+%% Table config is written to.
+-define(TABLE, ?MODULE).
+
+%% Workaround for dialyzer's lack of understanding of match specs.
+-type match(T)
+ :: T | '_' | '$1' | '$2' | '$3' | '$4'.
+
+%% Configuration records in ?TABLE.
+
+-record(service,
+ {name,
+ rec :: match(#diameter_service{}),
+ options :: match(list())}).
+
+-record(transport,
+ {service, %% name
+ ref = make_ref() :: match(reference()),
+ type :: match(connect | listen),
+ options :: match(list())}).
+
+%% Monitor entry in ?TABLE.
+-record(monitor, {mref = make_ref() :: reference(),
+ service}). %% name
+
+%% Time to lay low before restarting a dead service.
+-define(RESTART_SLEEP, 2000).
+
+%% A minimal diameter_caps for checking for valid capabilities values.
+-define(EXAMPLE_CAPS,
+ #diameter_caps{origin_host = "TheHost",
+ origin_realm = "TheRealm",
+ host_ip_address = [{127,0,0,1}],
+ vendor_id = 42,
+ product_name = "TheProduct"}).
+
+-define(VALUES(Rec), tl(tuple_to_list(Rec))).
+
+%%% The return values below assume the server diameter_config is started.
+%%% The functions will exit if it isn't.
+
+%% --------------------------------------------------------------------------
+%% # start_service(SvcName, Opts)
+%%
+%% Output: ok | {error, Reason}
+%% --------------------------------------------------------------------------
+
+start_service(SvcName, Opts)
+ when is_list(Opts) ->
+ start_rc(sync(SvcName, {start_service, SvcName, Opts})).
+
+start_rc({ok = T, _Pid}) ->
+ T;
+start_rc({error, _} = No) ->
+ No;
+start_rc(timeout) ->
+ {error, application_not_started}.
+
+%% --------------------------------------------------------------------------
+%% # stop_service(SvcName)
+%%
+%% Output: ok
+%% --------------------------------------------------------------------------
+
+stop_service(SvcName) ->
+ sync(SvcName, {stop_service, SvcName}).
+
+%% --------------------------------------------------------------------------
+%% # add_transport(SvcName, {Type, Opts})
+%%
+%% Input: Type = connect | listen
+%%
+%% Output: {ok, Ref} | {error, Reason}
+%% --------------------------------------------------------------------------
+
+add_transport(SvcName, {T, Opts})
+ when is_list(Opts), (T == connect orelse T == listen) ->
+ sync(SvcName, {add, SvcName, T, Opts}).
+
+%% --------------------------------------------------------------------------
+%% # remove_transport(SvcName, Pred)
+%%
+%% Input: Pred = arity 3 fun on transport ref, connect|listen and Opts,
+%% returning true if the transport is to be removed, false if
+%% not
+%% | arity 2 fun on Ref and Opts only
+%% | arity 1 fun on Opts only
+%% | Opts matching all transports that have all of the specified
+%% options
+%% | Ref matching only the transport with this reference.
+%% | {M,F,A} applied to Ref, connect|listen and Opts
+%% | boolean()
+%%
+%% Output: ok | {error, Reason}
+%% --------------------------------------------------------------------------
+
+remove_transport(SvcName, Pred) ->
+ try
+ sync(SvcName, {remove, SvcName, pred(Pred)})
+ catch
+ ?FAILURE(Reason) ->
+ {error, Reason}
+ end.
+
+pred(Pred)
+ when is_function(Pred, 3) ->
+ Pred;
+pred(Pred)
+ when is_function(Pred, 2) ->
+ fun(R,_,O) -> Pred(R,O) end;
+pred(Pred)
+ when is_function(Pred, 1) ->
+ fun(_,_,O) -> Pred(O) end;
+pred(Opts)
+ when is_list(Opts) ->
+ fun(_,_,O) -> [] == Opts -- O end;
+pred(Ref)
+ when is_reference(Ref) ->
+ fun(R,_,_) -> R == Ref end;
+pred({M,F,A})
+ when is_atom(M), is_atom(F), is_list(A) ->
+ fun(R,T,O) -> apply(M,F,[R,T,O|A]) end;
+pred({Type, Pred}) -> %% backwards compatibility
+ P = pred(Pred),
+ fun(R,T,O) -> T == Type andalso P(R,T,O) end;
+pred(B)
+ when is_boolean(B) ->
+ fun(_,_,_) -> B end;
+pred(_) ->
+ ?THROW(pred).
+
+%% --------------------------------------------------------------------------
+%% # have_transport/2
+%%
+%% Output: true | false
+%% --------------------------------------------------------------------------
+
+have_transport(SvcName, Ref) ->
+ member([{#transport{service = '$1',
+ ref = '$2',
+ _ = '_'},
+ [{'andalso', {'=:=', '$1', {const, SvcName}},
+ {'=:=', '$2', {const, Ref}}}],
+ [true]}]).
+
+%% --------------------------------------------------------------------------
+%% # lookup/1
+%% --------------------------------------------------------------------------
+
+lookup(SvcName) ->
+ select([{#service{name = '$1', rec = '$2', options = '$3'},
+ [{'=:=', '$1', {const, SvcName}}],
+ [{{'$1', '$2', '$3'}}]},
+ {#transport{service = '$1',
+ ref = '$2',
+ type = '$3',
+ options = '$4'},
+ [{'=:=', '$1', {const, SvcName}}],
+ [{{'$2', '$3', '$4'}}]}]).
+
+%% ---------------------------------------------------------
+%% EXPORTED INTERNAL FUNCTIONS
+%% ---------------------------------------------------------
+
+start_link() ->
+ ServerName = {local, ?SERVER},
+ Module = ?MODULE,
+ Args = [],
+ Options = [{spawn_opt, diameter_lib:spawn_opts(server, [])}],
+ gen_server:start_link(ServerName, Module, Args, Options).
+
+state() ->
+ call(state).
+
+uptime() ->
+ call(uptime).
+
+%%% ----------------------------------------------------------
+%%% # init/1
+%%% ----------------------------------------------------------
+
+init([]) ->
+ {ok, #state{}}.
+
+%%% ----------------------------------------------------------
+%%% # handle_call/2
+%%% ----------------------------------------------------------
+
+handle_call(state, _, State) ->
+ {reply, State, State};
+
+handle_call(uptime, _, #state{id = Time} = State) ->
+ {reply, diameter_lib:now_diff(Time), State};
+
+handle_call(Req, From, State) ->
+ ?UNEXPECTED([Req, From]),
+ Reply = {error, {bad_request, Req}},
+ {reply, Reply, State}.
+
+%%% ----------------------------------------------------------
+%%% # handle_cast/2
+%%% ----------------------------------------------------------
+
+handle_cast(Msg, State) ->
+ ?UNEXPECTED([Msg]),
+ {noreply, State}.
+
+%%% ----------------------------------------------------------
+%%% # handle_info/2
+%%% ----------------------------------------------------------
+
+%% A service process has died. This is most likely a consequence of
+%% stop_service, in which case the restart will find no config for the
+%% service and do nothing. The entry keyed on the monitor ref is only
+%% removed as a result of the 'DOWN' notification however.
+handle_info({'DOWN', MRef, process, _, Reason}, State) ->
+ [#monitor{service = SvcName} = T] = select([{#monitor{mref = MRef,
+ _ = '_'},
+ [],
+ ['$_']}]),
+ queue_restart(Reason, SvcName),
+ delete_object(T),
+ {noreply, State};
+
+handle_info({monitor, SvcName, Pid}, State) ->
+ monitor(Pid, SvcName),
+ {noreply, State};
+
+handle_info({restart, SvcName}, State) ->
+ restart(SvcName),
+ {noreply, State};
+
+handle_info(restart, State) ->
+ restart(),
+ {noreply, State};
+
+handle_info(Info, State) ->
+ ?UNEXPECTED([Info]),
+ {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% # terminate/2
+%%--------------------------------------------------------------------
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%% ----------------------------------------------------------
+%%% # code_change/3
+%%% ----------------------------------------------------------
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%% ---------------------------------------------------------
+%% INTERNAL FUNCTIONS
+%% ---------------------------------------------------------
+
+insert(T) ->
+ ets:insert(?TABLE, T).
+
+%% ?TABLE is a bag: check only for a service entry.
+have_service(SvcName) ->
+ member([{#service{name = '$1', _ = '_'},
+ [{'=:=', '$1', {const, SvcName}}],
+ [true]}]).
+
+member(MatchSpec) ->
+ '$end_of_table' =/= ets:select(?TABLE, MatchSpec, 1).
+
+delete_object(T) ->
+ ets:delete_object(?TABLE, T).
+
+delete(Key) ->
+ ets:delete(?TABLE, Key).
+
+select(MatchSpec) ->
+ ets:select(?TABLE, MatchSpec).
+
+select_delete(MatchSpec) ->
+ ets:select_delete(?TABLE, MatchSpec).
+
+%% sync/2
+%%
+%% Interface functions used to be implemented as calls to ?SERVER but
+%% now serialize things per service instead since stopping a service
+%% can take time if the server doesn't answer DPR. A caller who wants
+%% to stop multiple services can then improve performance by spawning
+%% processes to stop them concurrently.
+
+sync(SvcName, T) ->
+ diameter_sync:call({?MODULE, SvcName},
+ {?MODULE, sync, [T]},
+ infinity,
+ infinity).
+
+%% sync/1
+
+sync({restart, SvcName}) ->
+ have_service(SvcName) andalso start(SvcName);
+
+sync({start_service, SvcName, Opts}) ->
+ try
+ start(have_service(SvcName), SvcName, Opts)
+ catch
+ ?FAILURE(Reason) -> {error, Reason}
+ end;
+
+sync({stop_service, SvcName}) ->
+ stop(SvcName);
+
+sync({add, SvcName, Type, Opts}) ->
+ try
+ add(SvcName, Type, Opts)
+ catch
+ ?FAILURE(Reason) -> {error, Reason}
+ end;
+
+sync({remove, SvcName, Pred}) ->
+ remove(select([{#transport{service = '$1', _ = '_'},
+ [{'=:=', '$1', {const, SvcName}}],
+ ['$_']}]),
+ SvcName,
+ Pred).
+
+%% start/3
+
+start(true, _, _) ->
+ {error, already_started};
+start(false, SvcName, Opts) ->
+ insert(make_config(SvcName, Opts)),
+ start(SvcName).
+
+%% start/1
+
+start(SvcName) ->
+ RC = diameter_service:start(SvcName),
+ startmon(SvcName, RC),
+ RC.
+
+startmon(SvcName, {ok, Pid}) ->
+ ?SERVER ! {monitor, SvcName, Pid};
+startmon(_, {error, _}) ->
+ ok.
+
+monitor(Pid, SvcName) ->
+ MRef = erlang:monitor(process, Pid),
+ insert(#monitor{mref = MRef, service = SvcName}).
+
+%% queue_restart/2
+
+%% Service has gone down on monitor death. Note that all service-related
+%% config is deleted.
+queue_restart({shutdown, {monitor, _}}, SvcName) ->
+ delete(SvcName);
+
+%% Application shutdown: ignore.
+queue_restart(shutdown, _) ->
+ ok;
+
+%% Or not.
+queue_restart(_, SvcName) ->
+ erlang:send_after(?RESTART_SLEEP, self(), {restart, SvcName}).
+
+%% restart/1
+
+restart(SvcName) ->
+ sync(SvcName, {restart, SvcName}).
+
+%% restart/0
+%%
+%% Start anything configured as required. Bang 'restart' to the server
+%% to kick things into gear manually. (Not that it should be required
+%% but it's been useful for test.)
+
+restart() ->
+ MatchSpec = [{#service{name = '$1', _ = '_'},
+ [],
+ ['$1']}],
+ lists:foreach(fun restart/1, select(MatchSpec)).
+
+%% stop/1
+
+stop(SvcName) ->
+ %% If the call to the service returns error for any reason other
+ %% than the process not being alive then deleting the config from
+ %% under it will surely bring it down.
+ diameter_service:stop(SvcName),
+ %% Delete only the service entry, not everything keyed on the name,
+ select_delete([{#service{name = '$1', _ = '_'},
+ [{'=:=', '$1', {const, SvcName}}],
+ [true]}]),
+ ok.
+%% Note that a transport has to be removed for its statistics to be
+%% deleted.
+
+%% add/3
+
+add(SvcName, Type, Opts) ->
+ %% Ensure usable capabilities. diameter_service:merge_service/2
+ %% depends on this.
+ lists:foreach(fun(Os) ->
+ is_list(Os) orelse ?THROW({capabilities, Os}),
+ ok = encode_CER(Os)
+ end,
+ [Os || {capabilities, Os} <- Opts, is_list(Os)]),
+
+ Ref = make_ref(),
+ T = {Ref, Type, Opts},
+ %% The call to the service returns error if the service isn't
+ %% started yet, which is harmless. The transport will be started
+ %% when the service is in that case.
+ case start_transport(SvcName, T) of
+ ok ->
+ insert(#transport{service = SvcName,
+ ref = Ref,
+ type = Type,
+ options = Opts}),
+ {ok, Ref};
+ {error, _} = No ->
+ No
+ end.
+
+start_transport(SvcName, T) ->
+ case diameter_service:start_transport(SvcName, T) of
+ {ok, _Pid} ->
+ ok;
+ {error, no_service} ->
+ ok;
+ {error, _} = No ->
+ No
+ end.
+
+%% remove/3
+
+remove(L, SvcName, Pred) ->
+ rm(SvcName, lists:filter(fun(#transport{ref = R, type = T, options = O}) ->
+ Pred(R,T,O)
+ end,
+ L)).
+
+rm(_, []) ->
+ ok;
+rm(SvcName, L) ->
+ Refs = lists:map(fun(#transport{ref = R}) -> R end, L),
+ case stop_transport(SvcName, Refs) of
+ ok ->
+ lists:foreach(fun delete_object/1, L);
+ {error, _} = No ->
+ No
+ end.
+
+stop_transport(SvcName, Refs) ->
+ case diameter_service:stop_transport(SvcName, Refs) of
+ ok ->
+ ok;
+ {error, no_service} ->
+ ok;
+ {error, _} = No ->
+ No
+ end.
+
+%% make_config/2
+
+make_config(SvcName, Opts) ->
+ Apps = init_apps(Opts),
+ [] == Apps andalso ?THROW(no_apps),
+
+ %% Use the fact that diameter_caps has the same field names as CER.
+ Fields = diameter_gen_base_rfc3588:'#info-'(diameter_base_CER) -- ['AVP'],
+
+ COpts = [T || {K,_} = T <- Opts, lists:member(K, Fields)],
+ Caps = make_caps(#diameter_caps{}, COpts),
+
+ ok = encode_CER(COpts),
+
+ Os = split(Opts, [{[fun erlang:is_boolean/1], false, share_peers},
+ {[fun erlang:is_boolean/1], false, use_shared_peers},
+ {[fun erlang:is_pid/1, false], false, monitor}]),
+ %% share_peers and use_shared_peers are currently undocumented.
+
+ #service{name = SvcName,
+ rec = #diameter_service{applications = Apps,
+ capabilities = Caps},
+ options = Os}.
+
+make_caps(Caps, Opts) ->
+ case diameter_capx:make_caps(Caps, Opts) of
+ {ok, T} ->
+ T;
+ {error, {Reason, _}} ->
+ ?THROW(Reason)
+ end.
+
+%% Validate types by encoding a CER.
+encode_CER(Opts) ->
+ {ok, CER} = diameter_capx:build_CER(make_caps(?EXAMPLE_CAPS, Opts)),
+
+ Hdr = #diameter_header{version = ?DIAMETER_VERSION,
+ end_to_end_id = 0,
+ hop_by_hop_id = 0},
+
+ try
+ diameter_codec:encode(?BASE, #diameter_packet{header = Hdr,
+ msg = CER}),
+ ok
+ catch
+ exit: Reason ->
+ ?THROW(Reason)
+ end.
+
+init_apps(Opts) ->
+ lists:foldl(fun app_acc/2, [], lists:reverse(Opts)).
+
+app_acc({application, Opts}, Acc) ->
+ is_list(Opts) orelse ?THROW({application, Opts}),
+
+ [Dict, Mod] = get_opt([dictionary, module], Opts),
+ Alias = get_opt(alias, Opts, Dict),
+ ModS = get_opt(state, Opts, Alias),
+ M = get_opt(call_mutates_state, Opts, false),
+ A = get_opt(answer_errors, Opts, report),
+ [#diameter_app{alias = Alias,
+ dictionary = Dict,
+ id = cb(Dict, id),
+ module = init_mod(Mod),
+ init_state = ModS,
+ mutable = init_mutable(M),
+ answer_errors = init_answers(A)}
+ | Acc];
+app_acc(_, Acc) ->
+ Acc.
+
+init_mod(M)
+ when is_atom(M) ->
+ [M];
+init_mod([M|_] = L)
+ when is_atom(M) ->
+ L;
+init_mod(M) ->
+ ?THROW({module, M}).
+
+init_mutable(M)
+ when M == true;
+ M == false ->
+ M;
+init_mutable(M) ->
+ ?THROW({call_mutates_state, M}).
+
+init_answers(A)
+ when callback == A;
+ report == A;
+ discard == A ->
+ A;
+init_answers(A) ->
+ ?THROW({answer_errors, A}).
+
+%% Get a single value at the specified key.
+get_opt(Keys, List)
+ when is_list(Keys) ->
+ [get_opt(K, List) || K <- Keys];
+get_opt(Key, List) ->
+ case [V || {K,V} <- List, K == Key] of
+ [V] -> V;
+ _ -> ?THROW({arity, Key})
+ end.
+
+%% Get an optional value at the specified key.
+get_opt(Key, List, Def) ->
+ case [V || {K,V} <- List, K == Key] of
+ [] -> Def;
+ [V] -> V;
+ _ -> ?THROW({arity, Key})
+ end.
+
+split(Opts, Defs) ->
+ [{K, value(D, Opts)} || {_,_,K} = D <- Defs].
+
+value({Preds, Def, Key}, Opts) ->
+ V = get_opt(Key, Opts, Def),
+ lists:any(fun(P) -> pred(P,V) end, Preds)
+ orelse ?THROW({value, Key}),
+ V.
+
+pred(F, V)
+ when is_function(F) ->
+ F(V);
+pred(T, V) ->
+ T == V.
+
+cb(M,F) ->
+ try M:F() of
+ V -> V
+ catch
+ E: Reason ->
+ ?THROW({callback, E, Reason, ?STACK})
+ end.
+
+%% call/1
+
+call(Request) ->
+ gen_server:call(?SERVER, Request, infinity).
diff --git a/lib/diameter/src/app/diameter_dbg.erl b/lib/diameter/src/app/diameter_dbg.erl
new file mode 100644
index 0000000000..5b0ac3a3b6
--- /dev/null
+++ b/lib/diameter/src/app/diameter_dbg.erl
@@ -0,0 +1,516 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_dbg).
+
+-export([table/1,
+ tables/0,
+ fields/1,
+ help/0,
+ modules/0,
+ versions/0,
+ version_info/0,
+ compiled/0,
+ procs/0,
+ latest/0,
+ nl/0,
+ log/4]).
+
+-export([diameter_config/0,
+ diameter_peer/0,
+ diameter_reg/0,
+ diameter_request/0,
+ diameter_sequence/0,
+ diameter_service/0,
+ diameter_stats/0]).
+
+-export([pp/1,
+ subscriptions/0,
+ children/0]).
+
+%% Trace help.
+-export([tracer/0, tracer/1,
+ p/0, p/1,
+ stop/0,
+ tpl/1,
+ tp/1]).
+
+-include_lib("diameter/include/diameter.hrl").
+-include("diameter_internal.hrl").
+
+
+-define(INFO, diameter_info).
+-define(SEP(), ?INFO:sep()).
+
+-define(LOCAL, [diameter_config,
+ diameter_peer,
+ diameter_reg,
+ diameter_request,
+ diameter_sequence,
+ diameter_service,
+ diameter_stats]).
+
+-define(VALUES(Rec), tl(tuple_to_list(Rec))).
+
+log(_Slogan, _Mod, _Line, _Details) ->
+ ok.
+
+%%% ----------------------------------------------------------
+%%% # help()
+%%% ----------------------------------------------------------
+
+help() ->
+ not_yet_implemented.
+
+%%% ----------------------------------------------------------
+%%% # table(TableName)
+%%%
+%%% Input: TableName = diameter table containing record entries.
+%%%
+%%% Output: Count | undefined
+%%% ----------------------------------------------------------
+
+table(T)
+ when (T == diameter_peer) orelse (T == diameter_reg) ->
+ ?INFO:format(collect(T), fields(T), fun ?INFO:split/2);
+
+table(Table)
+ when is_atom(Table) ->
+ case fields(Table) of
+ undefined = No ->
+ No;
+ Fields ->
+ ?INFO:format(Table, Fields, fun split/2)
+ end.
+
+split([started, name | Fs], [S, N | Vs]) ->
+ {name, [started | Fs], N, [S | Vs]};
+split([[F|FT]|Fs], [Rec|Vs]) ->
+ [_, V | VT] = tuple_to_list(Rec),
+ {F, FT ++ Fs, V, VT ++ Vs};
+split([F|Fs], [V|Vs]) ->
+ {F, Fs, V, Vs}.
+
+%%% ----------------------------------------------------------
+%%% # TableName()
+%%% ----------------------------------------------------------
+
+-define(TABLE(Name), Name() -> table(Name)).
+
+?TABLE(diameter_config).
+?TABLE(diameter_peer).
+?TABLE(diameter_reg).
+?TABLE(diameter_request).
+?TABLE(diameter_sequence).
+?TABLE(diameter_service).
+?TABLE(diameter_stats).
+
+%%% ----------------------------------------------------------
+%%% # tables()
+%%%
+%%% Output: Number of records output.
+%%%
+%%% Description: Pretty-print records in diameter tables from all nodes.
+%%% ----------------------------------------------------------
+
+tables() ->
+ ?INFO:format(field(?LOCAL), fun split/3, fun collect/1).
+
+field(Tables) ->
+ lists:map(fun(T) -> {T, fields(T)} end, lists:sort(Tables)).
+
+split(_, Fs, Vs) ->
+ split(Fs, Vs).
+
+%%% ----------------------------------------------------------
+%%% # modules()
+%%% ----------------------------------------------------------
+
+modules() ->
+ Path = filename:join([appdir(), atom_to_list(?APPLICATION) ++ ".app"]),
+ {ok, [{application, ?APPLICATION, Attrs}]} = file:consult(Path),
+ {modules, Mods} = lists:keyfind(modules, 1, Attrs),
+ Mods.
+
+appdir() ->
+ [_|_] = code:lib_dir(?APPLICATION, ebin).
+
+%%% ----------------------------------------------------------
+%%% # versions()
+%%% ----------------------------------------------------------
+
+versions() ->
+ ?INFO:versions(modules()).
+
+%%% ----------------------------------------------------------
+%%% # versions()
+%%% ----------------------------------------------------------
+
+version_info() ->
+ ?INFO:version_info(modules()).
+
+%%% ----------------------------------------------------------
+%%% # compiled()
+%%% ----------------------------------------------------------
+
+compiled() ->
+ ?INFO:compiled(modules()).
+
+%%% ----------------------------------------------------------
+%%% procs()
+%%% ----------------------------------------------------------
+
+procs() ->
+ ?INFO:procs(?APPLICATION).
+
+%%% ----------------------------------------------------------
+%%% # latest()
+%%% ----------------------------------------------------------
+
+latest() ->
+ ?INFO:latest(modules()).
+
+%%% ----------------------------------------------------------
+%%% # nl()
+%%% ----------------------------------------------------------
+
+nl() ->
+ lists:foreach(fun(M) -> abcast = c:nl(M) end, modules()).
+
+%%% ----------------------------------------------------------
+%%% # pp(Bin)
+%%%
+%%% Description: Pretty-print a message binary.
+%%% ----------------------------------------------------------
+
+%% Network byte order = big endian.
+
+pp(<<Version:8, MsgLength:24,
+ Rbit:1, Pbit:1, Ebit:1, Tbit:1, Reserved:4, CmdCode:24,
+ ApplId:32,
+ HbHid:32,
+ E2Eid:32,
+ AVPs/binary>>) ->
+ ?SEP(),
+ ppp(["Version",
+ "Message length",
+ "[Actual length]",
+ "R(equest)",
+ "P(roxiable)",
+ "E(rror)",
+ "T(Potential retrans)",
+ "Reserved bits",
+ "Command code",
+ "Application id",
+ "Hop by hop id",
+ "End to end id"],
+ [Version, MsgLength, size(AVPs) + 20,
+ Rbit, Pbit, Ebit, Tbit, Reserved,
+ CmdCode,
+ ApplId,
+ HbHid,
+ E2Eid]),
+ N = avp_loop({AVPs, MsgLength - 20}, 0),
+ ?SEP(),
+ N;
+
+pp(<<_Version:8, MsgLength:24, _/binary>> = Bin) ->
+ {bad_message_length, MsgLength, size(Bin)};
+
+pp(Bin)
+ when is_binary(Bin) ->
+ {truncated_binary, size(Bin)};
+
+pp(_) ->
+ not_binary.
+
+%% avp_loop/2
+
+avp_loop({Bin, Size}, N) ->
+ avp_loop(avp(Bin, Size), N+1);
+avp_loop(ok, N) ->
+ N;
+avp_loop([_E, _Rest] = L, N) ->
+ io:format("! ~s: ~p~n", L),
+ N;
+avp_loop([E, Rest, Fmt | Values], N)
+ when is_binary(Rest) ->
+ io:format("! ~s (" ++ Fmt ++ "): ~p~n", [E|Values] ++ [Rest]),
+ N.
+
+%% avp/2
+
+avp(<<>>, 0) ->
+ ok;
+avp(<<Code:32, Flags:1/binary, Length:24, Rest/binary>>,
+ Size) ->
+ avp(Code, Flags, Length, Rest, Size);
+avp(Bin, _) ->
+ ["truncated AVP header", Bin].
+
+%% avp/5
+
+avp(Code, Flags, Length, Rest, Size) ->
+ <<V:1, M:1, P:1, Res:5>>
+ = Flags,
+ b(),
+ ppp(["AVP Code",
+ "V(endor)",
+ "M(andatory)",
+ "P(Security)",
+ "R(eserved)",
+ "Length"],
+ [Code, V, M, P, Res, Length]),
+ avp(V, Rest, Length - 8, Size - 8).
+
+%% avp/4
+
+avp(1, <<V:32, Data/binary>>, Length, Size) ->
+ ppp({"Vendor-ID", V}),
+ data(Data, Length - 4, Size - 4);
+avp(1, Bin, _, _) ->
+ ["truncated Vendor-ID", Bin];
+avp(0, Data, Length, Size) ->
+ data(Data, Length, Size).
+
+data(Bin, Length, Size)
+ when size(Bin) >= Length ->
+ <<AVP:Length/binary, Rest/binary>> = Bin,
+ ppp({"Data", AVP}),
+ unpad(Rest, Size - Length, Length rem 4);
+
+data(Bin, _, _) ->
+ ["truncated AVP data", Bin].
+
+%% Remove padding bytes up to the next word boundary.
+unpad(Bin, Size, 0) ->
+ {Bin, Size};
+unpad(Bin, Size, N) ->
+ un(Bin, Size, 4 - N).
+
+un(Bin, Size, N)
+ when size(Bin) >= N ->
+ ppp({"Padding bytes", N}),
+ <<Pad:N/binary, Rest/binary>> = Bin,
+ Bits = N*8,
+ case Pad of
+ <<0:Bits>> ->
+ {Rest, Size - N};
+ _ ->
+ ["non-zero padding", Bin, "~p", N]
+ end;
+
+un(Bin, _, _) ->
+ ["truncated padding", Bin].
+
+b() ->
+ io:format("#~n").
+
+ppp(Fields, Values) ->
+ lists:foreach(fun ppp/1, lists:zip(Fields, Values)).
+
+ppp({Field, Value}) ->
+ io:format(": ~-22s : ~p~n", [Field, Value]).
+
+%%% ----------------------------------------------------------
+%%% # subscriptions()
+%%%
+%%% Output: list of {SvcName, Pid}
+%%% ----------------------------------------------------------
+
+subscriptions() ->
+ diameter_service:subscriptions().
+
+%%% ----------------------------------------------------------
+%%% # children()
+%%% ----------------------------------------------------------
+
+children() ->
+ diameter_sup:tree().
+
+%%% ----------------------------------------------------------
+
+%% tracer/[12]
+
+tracer(Port)
+ when is_integer(Port) ->
+ dbg:tracer(port, dbg:trace_port(ip, Port));
+
+tracer(Path)
+ when is_list(Path) ->
+ dbg:tracer(port, dbg:trace_port(file, Path)).
+
+tracer() ->
+ dbg:tracer(process, {fun p/2, ok}).
+
+p(T,_) ->
+ io:format("+ ~p~n", [T]).
+
+%% p/[01]
+
+p() ->
+ p([c,timestamp]).
+
+p(T) ->
+ dbg:p(all,T).
+
+%% stop/0
+
+stop() ->
+ dbg:ctp(),
+ dbg:stop_clear().
+
+%% tpl/1
+%% tp/1
+
+tpl(T) ->
+ dbg(tpl, T).
+
+tp(T) ->
+ dbg(tp, T).
+
+%% dbg/2
+
+dbg(F, L)
+ when is_list(L) ->
+ [dbg(F, X) || X <- L];
+
+dbg(F, M)
+ when is_atom(M) ->
+ apply(dbg, F, [M, x]);
+
+dbg(F, T)
+ when is_tuple(T) ->
+ apply(dbg, F, tuple_to_list(T)).
+
+%% ===========================================================================
+%% ===========================================================================
+
+%% collect/1
+
+collect(diameter_peer) ->
+ lists:flatmap(fun peers/1, diameter:services());
+
+collect(diameter_reg) ->
+ diameter_reg:terms();
+
+collect(Name) ->
+ c(ets:info(Name), Name).
+
+c(undefined, _) ->
+ [];
+c(_, Name) ->
+ ets:tab2list(Name).
+
+%% peers/1
+
+peers(Name) ->
+ peers(Name, diameter:service_info(Name, transport)).
+
+peers(_, undefined) ->
+ [];
+peers(Name, Ts) ->
+ lists:flatmap(fun(T) -> mk_peers(Name, T) end, Ts).
+
+mk_peers(Name, [_, {type, connect} | _] = Ts) ->
+ [[Name | mk_peer(Ts)]];
+mk_peers(Name, [R, {type, listen}, O, {accept = A, As}]) ->
+ [[Name | mk_peer([R, {type, A}, O | Ts])] || Ts <- As].
+%% This is a bit lame: service_info works to build this list and out
+%% of something like what we want here and then we take it apart.
+
+mk_peer(Vs) ->
+ [Type, Ref, State, Opts, WPid, TPid, SApps, Caps]
+ = get_values(Vs, [type,ref,state,options,watchdog,peer,apps,caps]),
+ [Ref, State, [{type, Type} | Opts], s(WPid), s(TPid), SApps, Caps].
+
+get_values(Vs, Ks) ->
+ [proplists:get_value(K, Vs) || K <- Ks].
+
+s(undefined = T) ->
+ T;
+s({Pid, _Started, _State}) ->
+ state(Pid);
+s({Pid, _Started}) ->
+ state(Pid).
+
+%% Collect states from watchdog/transport pids.
+state(Pid) ->
+ MRef = erlang:monitor(process, Pid),
+ Pid ! {state, self()},
+ receive
+ {'DOWN', MRef, process, _, _} ->
+ Pid;
+ {Pid, _} = T ->
+ erlang:demonitor(MRef, [flush]),
+ T
+ end.
+
+%% fields/1
+
+-define(FIELDS(Table), fields(Table) -> record_info(fields, Table)).
+
+fields(diameter_config) ->
+ [];
+
+fields(T)
+ when T == diameter_request;
+ T == diameter_sequence ->
+ fun kv/1;
+
+fields(diameter_stats) ->
+ fun({Ctr, N}) when not is_pid(Ctr) ->
+ {[counter, value], [Ctr, N]};
+ (_) ->
+ []
+ end;
+
+fields(diameter_service) ->
+ [started,
+ name,
+ record_info(fields, diameter_service),
+ peerT,
+ connT,
+ share_peers,
+ use_shared_peers,
+ shared_peers,
+ local_peers,
+ monitor];
+
+?FIELDS(diameter_event);
+?FIELDS(diameter_uri);
+?FIELDS(diameter_avp);
+?FIELDS(diameter_header);
+?FIELDS(diameter_packet);
+?FIELDS(diameter_app);
+?FIELDS(diameter_caps);
+
+fields(diameter_peer) ->
+ [service, ref, state, options, watchdog, peer, applications, capabilities];
+
+fields(diameter_reg) ->
+ [property, pids];
+
+fields(_) ->
+ undefined.
+
+kv({_,_}) ->
+ [key, value];
+kv(_) ->
+ [].
diff --git a/lib/diameter/src/app/diameter_dict.erl b/lib/diameter/src/app/diameter_dict.erl
new file mode 100644
index 0000000000..3b9ba00a3f
--- /dev/null
+++ b/lib/diameter/src/app/diameter_dict.erl
@@ -0,0 +1,153 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 module provide OTP's dict interface built on top of ets.
+%%
+%% Note that while the interface is the same as dict the semantics
+%% aren't quite. A Dict here is just a table identifier (although
+%% this fact can't be used if you want dict/ets-based implementations
+%% to be interchangeable) so changes made to the Dict modify the
+%% underlying table. For merge/3, the first argument table is modified.
+%%
+%% The underlying ets table implementing a dict is deleted when the
+%% process from which new() was invoked exits and the dict is only
+%% writable from this process.
+%%
+%% The reason for this is to be able to swap dict/ets-based
+%% implementations: the former is easier to debug, the latter is
+%% faster for larger tables. It's also just a nice interface even
+%% when there's no need for swapability.
+%%
+
+-module(diameter_dict).
+
+-export([append/3,
+ append_list/3,
+ erase/2,
+ fetch/2,
+ fetch_keys/1,
+ filter/2,
+ find/2,
+ fold/3,
+ from_list/1,
+ is_key/2,
+ map/2,
+ merge/3,
+ new/0,
+ store/3,
+ to_list/1,
+ update/3,
+ update/4,
+ update_counter/3]).
+
+%%% ----------------------------------------------------------
+%%% EXPORTED INTERNAL FUNCTIONS
+%%% ----------------------------------------------------------
+
+append(Key, Value, Dict) ->
+ append_list(Key, [Value], Dict).
+
+append_list(Key, ValueList, Dict)
+ when is_list(ValueList) ->
+ update(Key, fun(V) -> V ++ ValueList end, ValueList, Dict).
+
+erase(Key, Dict) ->
+ ets:delete(Dict, Key),
+ Dict.
+
+fetch(Key, Dict) ->
+ {ok, V} = find(Key, Dict),
+ V.
+
+fetch_keys(Dict) ->
+ ets:foldl(fun({K,_}, Acc) -> [K | Acc] end, [], Dict).
+
+filter(Pred, Dict) ->
+ lists:foreach(fun({K,V}) -> filter(Pred(K,V), K, Dict) end, to_list(Dict)),
+ Dict.
+
+find(Key, Dict) ->
+ case ets:lookup(Dict, Key) of
+ [{Key, V}] ->
+ {ok, V};
+ [] ->
+ error
+ end.
+
+fold(Fun, Acc0, Dict) ->
+ ets:foldl(fun({K,V}, Acc) -> Fun(K, V, Acc) end, Acc0, Dict).
+
+from_list(List) ->
+ lists:foldl(fun store/2, new(), List).
+
+is_key(Key, Dict) ->
+ ets:member(Dict, Key).
+
+map(Fun, Dict) ->
+ lists:foreach(fun({K,V}) -> store(K, Fun(K,V), Dict) end, to_list(Dict)),
+ Dict.
+
+merge(Fun, Dict1, Dict2) ->
+ fold(fun(K2,V2,_) ->
+ update(K2, fun(V1) -> Fun(K2, V1, V2) end, V2, Dict1)
+ end,
+ Dict1,
+ Dict2).
+
+new() ->
+ ets:new(?MODULE, [set]).
+
+store(Key, Value, Dict) ->
+ store({Key, Value}, Dict).
+
+to_list(Dict) ->
+ ets:tab2list(Dict).
+
+update(Key, Fun, Dict) ->
+ store(Key, Fun(fetch(Key, Dict)), Dict).
+
+update(Key, Fun, Initial, Dict) ->
+ store(Key, map(Key, Fun, Dict, Initial), Dict).
+
+update_counter(Key, Increment, Dict)
+ when is_integer(Increment) ->
+ update(Key, fun(V) -> V + Increment end, Increment, Dict).
+
+%%% ---------------------------------------------------------
+%%% INTERNAL FUNCTIONS
+%%% ---------------------------------------------------------
+
+store({_,_} = T, Dict) ->
+ ets:insert(Dict, T),
+ Dict.
+
+filter(true, _, _) ->
+ ok;
+filter(false, K, Dict) ->
+ erase(K, Dict).
+
+map(Key, Fun, Dict, Error) ->
+ case find(Key, Dict) of
+ {ok, V} ->
+ Fun(V);
+ error ->
+ Error
+ end.
+
diff --git a/lib/diameter/src/app/diameter_exprecs.erl b/lib/diameter/src/app/diameter_exprecs.erl
new file mode 100644
index 0000000000..5e120d6f44
--- /dev/null
+++ b/lib/diameter/src/app/diameter_exprecs.erl
@@ -0,0 +1,301 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Parse transform for generating record access functions
+%%
+%% This parse transform can be used to reduce compile-time
+%% dependencies in large systems.
+%%
+%% In the old days, before records, Erlang programmers often wrote
+%% access functions for tuple data. This was tedious and error-prone.
+%% The record syntax made this easier, but since records were implemented
+%% fully in the pre-processor, a nasty compile-time dependency was
+%% introduced.
+%%
+%% This module automates the generation of access functions for
+%% records. While this method cannot fully replace the utility of
+%% pattern matching, it does allow a fair bit of functionality on
+%% records without the need for compile-time dependencies.
+%%
+%% Whenever record definitions need to be exported from a module,
+%% inserting a compiler attribute,
+%%
+%% export_records([RecName, ...])
+%%
+%% causes this transform to lay out access functions for the exported
+%% records:
+%%
+%% -module(foo)
+%% -compile({parse_transform, diameter_exprecs}).
+%%
+%% -record(r, {a, b, c}).
+%% -export_records([a]).
+%%
+%% -export(['#info-'/1, '#info-'/2,
+%% '#new-'/1, '#new-'/2,
+%% '#get-'/2, '#set-'/2,
+%% '#new-a'/0, '#new-a'/1,
+%% '#get-a'/2, '#set-a'/2,
+%% '#info-a'/1]).
+%%
+%% '#info-'(RecName) ->
+%% '#info-'(RecName, fields).
+%%
+%% '#info-'(r, Info) ->
+%% '#info-r'(Info).
+%%
+%% '#new-'(r) -> #r{}.
+%% '#new-'(r, Vals) -> '#new-r'(Vals)
+%%
+%% '#new-r'() -> #r{}.
+%% '#new-r'(Vals) -> '#set-r'(Vals, #r{}).
+%%
+%% '#get-'(Attrs, #r{} = Rec) ->
+%% '#get-r'(Attrs, Rec).
+%%
+%% '#get-r'(Attrs, Rec) when is_list(Attrs) ->
+%% ['#get-r'(A, Rec) || A <- Attrs];
+%% '#get-r'(a, Rec) -> Rec#r.a;
+%% '#get-r'(b, Rec) -> Rec#r.b;
+%% '#get-r'(c, Rec) -> Rec#r.c.
+%%
+%% '#set-'(Vals, #r{} = Rec) ->
+%% '#set-r'(Vals, Rec).
+%%
+%% '#set-r'(Vals, Rec) when is_list(Vals) ->
+%% lists:foldl(fun '#set-r'/2, Rec, Vals);
+%% '#set-r'({a,V}, Rec) -> Rec#r{a = V};
+%% '#set-r'({b,V}, Rec) -> Rec#r{b = V};
+%% '#set-r'({c,V}, Rec) -> Rec#r{c = V}.
+%%
+%% '#info-r'(fields) -> record_info(fields, r);
+%% '#info-r'(size) -> record_info(size, r);
+%% '#info-r'({index, a}) -> 1;
+%% '#info-r'({index, b}) -> 2;
+%% '#info-r'({index, c}) -> 3;
+%%
+
+-module(diameter_exprecs).
+
+-export([parse_transform/2]).
+
+%% Form tag with line number.
+-define(F(T), T, ?LINE).
+%% Yes, that's right. The replacement is to the first unmatched ')'.
+
+-define(attribute, ?F(attribute)).
+-define(clause, ?F(clause)).
+-define(function, ?F(function)).
+-define(call, ?F(call)).
+-define('fun', ?F('fun')).
+-define(generate, ?F(generate)).
+-define(lc, ?F(lc)).
+-define(match, ?F(match)).
+-define(remote, ?F(remote)).
+-define(record, ?F(record)).
+-define(record_field, ?F(record_field)).
+-define(record_index, ?F(record_index)).
+-define(tuple, ?F(tuple)).
+
+-define(ATOM(T), {atom, ?LINE, T}).
+-define(VAR(V), {var, ?LINE, V}).
+
+-define(CALL(F,A), {?call, ?ATOM(F), A}).
+-define(APPLY(M,F,A), {?call, {?remote, ?ATOM(M), ?ATOM(F)}, A}).
+
+%% parse_transform/2
+
+parse_transform(Forms, _Options) ->
+ Rs = [R || {attribute, _, record, R} <- Forms],
+ case lists:append([E || {attribute, _, export_records, E} <- Forms]) of
+ [] ->
+ Forms;
+ Es ->
+ {H,T} = lists:splitwith(fun is_head/1, Forms),
+ H ++ [a_export(Es) | f_accessors(Es, Rs)] ++ T
+ end.
+
+is_head(T) ->
+ not lists:member(element(1,T), [function, eof]).
+
+%% a_export/1
+
+a_export(Exports) ->
+ {?attribute, export, [{fname(info), 1},
+ {fname(info), 2},
+ {fname(new), 1},
+ {fname(new), 2},
+ {fname(get), 2},
+ {fname(set), 2}
+ | lists:flatmap(fun export/1, Exports)]}.
+
+export(Rname) ->
+ New = fname(new, Rname),
+ [{New, 0},
+ {New, 1},
+ {fname(get, Rname), 2},
+ {fname(set, Rname), 2},
+ {fname(info, Rname), 1}].
+
+%% f_accessors/2
+
+f_accessors(Es, Rs) ->
+ ['#info-/1'(),
+ '#info-/2'(Es),
+ '#new-/1'(Es),
+ '#new-/2'(Es),
+ '#get-/2'(Es),
+ '#set-/2'(Es)
+ | lists:flatmap(fun(N) -> accessors(N, fields(N, Rs)) end, Es)].
+
+accessors(Rname, Fields) ->
+ ['#new-X/0'(Rname),
+ '#new-X/1'(Rname),
+ '#get-X/2'(Rname, Fields),
+ '#set-X/2'(Rname, Fields),
+ '#info-X/1'(Rname, Fields)].
+
+fields(Rname, Recs) ->
+ {Rname, Fields} = lists:keyfind(Rname, 1, Recs),
+ lists:map(fun({record_field, _, {atom, _, N}}) -> N;
+ ({record_field, _, {atom, _, N}, _}) -> N
+ end,
+ Fields).
+
+fname_prefix(Op) ->
+ "#" ++ atom_to_list(Op) ++ "-".
+
+fname(Op) ->
+ list_to_atom(fname_prefix(Op)).
+
+fname(Op, Rname) ->
+ Prefix = fname_prefix(Op),
+ list_to_atom(Prefix ++ atom_to_list(Rname)).
+
+%% Generated functions.
+
+'#info-/1'() ->
+ Fname = fname(info),
+ {?function, Fname, 1,
+ [{?clause, [?VAR('RecName')],
+ [],
+ [?CALL(Fname, [?VAR('RecName'), ?ATOM(fields)])]}]}.
+
+'#info-/2'(Exports) ->
+ {?function, fname(info), 2,
+ lists:map(fun 'info-'/1, Exports)}.
+
+'info-'(R) ->
+ {?clause, [?ATOM(R), ?VAR('Info')],
+ [],
+ [?CALL(fname(info, R), [?VAR('Info')])]}.
+
+'#new-/1'(Exports) ->
+ {?function, fname(new), 1,
+ lists:map(fun 'new-'/1, Exports)}.
+
+'new-'(R) ->
+ {?clause, [?ATOM(R)],
+ [],
+ [{?record, R, []}]}.
+
+'#new-/2'(Exports) ->
+ {?function, fname(new), 2,
+ lists:map(fun 'new--'/1, Exports)}.
+
+'new--'(R) ->
+ {?clause, [?ATOM(R), ?VAR('Vals')],
+ [],
+ [?CALL(fname(new, R), [?VAR('Vals')])]}.
+
+'#get-/2'(Exports) ->
+ {?function, fname(get), 2,
+ lists:map(fun 'get-'/1, Exports)}.
+
+'get-'(R) ->
+ {?clause, [?VAR('Attrs'),
+ {?match, {?record, R, []}, ?VAR('Rec')}],
+ [],
+ [?CALL(fname(get, R), [?VAR('Attrs'), ?VAR('Rec')])]}.
+
+'#set-/2'(Exports) ->
+ {?function, fname(set), 2,
+ lists:map(fun 'set-'/1, Exports)}.
+
+'set-'(R) ->
+ {?clause, [?VAR('Vals'), {?match, {?record, R, []}, ?VAR('Rec')}],
+ [],
+ [?CALL(fname(set, R), [?VAR('Vals'), ?VAR('Rec')])]}.
+
+'#new-X/0'(Rname) ->
+ {?function, fname(new, Rname), 0,
+ [{?clause, [],
+ [],
+ [{?record, Rname, []}]}]}.
+
+'#new-X/1'(Rname) ->
+ {?function, fname(new, Rname), 1,
+ [{?clause, [?VAR('Vals')],
+ [],
+ [?CALL(fname(set, Rname), [?VAR('Vals'), {?record, Rname, []}])]}]}.
+
+'#set-X/2'(Rname, Fields) ->
+ {?function, fname(set, Rname), 2,
+ [{?clause, [?VAR('Vals'), ?VAR('Rec')],
+ [[?CALL(is_list, [?VAR('Vals')])]],
+ [?APPLY(lists, foldl, [{?'fun', {function, fname(set, Rname), 2}},
+ ?VAR('Rec'),
+ ?VAR('Vals')])]}
+ | lists:map(fun(A) -> 'set-X'(Rname, A) end, Fields)]}.
+
+'set-X'(Rname, Attr) ->
+ {?clause, [{?tuple, [?ATOM(Attr), ?VAR('V')]}, ?VAR('Rec')],
+ [],
+ [{?record, ?VAR('Rec'), Rname,
+ [{?record_field, ?ATOM(Attr), ?VAR('V')}]}]}.
+
+'#get-X/2'(Rname, Fields) ->
+ FName = fname(get, Rname),
+ {?function, FName, 2,
+ [{?clause, [?VAR('Attrs'), ?VAR('Rec')],
+ [[?CALL(is_list, [?VAR('Attrs')])]],
+ [{?lc, ?CALL(FName, [?VAR('A'), ?VAR('Rec')]),
+ [{?generate, ?VAR('A'), ?VAR('Attrs')}]}]}
+ | lists:map(fun(A) -> 'get-X'(Rname, A) end, Fields)]}.
+
+'get-X'(Rname, Attr) ->
+ {?clause, [?ATOM(Attr), ?VAR('Rec')],
+ [],
+ [{?record_field, ?VAR('Rec'), Rname, ?ATOM(Attr)}]}.
+
+'#info-X/1'(Rname, Fields) ->
+ {?function, fname(info, Rname), 1,
+ [{?clause, [?ATOM(fields)],
+ [],
+ [?CALL(record_info, [?ATOM(fields), ?ATOM(Rname)])]},
+ {?clause, [?ATOM(size)],
+ [],
+ [?CALL(record_info, [?ATOM(size), ?ATOM(Rname)])]}
+ | lists:map(fun(A) -> 'info-X'(Rname, A) end, Fields)]}.
+
+'info-X'(Rname, Attr) ->
+ {?clause, [{?tuple, [?ATOM(index), ?ATOM(Attr)]}],
+ [],
+ [{?record_index, Rname, ?ATOM(Attr)}]}.
diff --git a/lib/diameter/src/app/diameter_gen_base_accounting.dia b/lib/diameter/src/app/diameter_gen_base_accounting.dia
new file mode 100644
index 0000000000..64e95dddb5
--- /dev/null
+++ b/lib/diameter/src/app/diameter_gen_base_accounting.dia
@@ -0,0 +1,68 @@
+;;
+;; %CopyrightBegin%
+;;
+;; Copyright Ericsson AB 2010-2011. All Rights Reserved.
+;;
+;; The contents of this file are subject to the Erlang Public License,
+;; Version 1.1, (the "License"); you may not use this file except in
+;; compliance with the License. You should have received a copy of the
+;; Erlang Public License along with this software. If not, it can be
+;; retrieved online at http://www.erlang.org/.
+;;
+;; Software distributed under the License is distributed on an "AS IS"
+;; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+;; the License for the specific language governing rights and limitations
+;; under the License.
+;;
+;; %CopyrightEnd%
+;;
+
+@id 3
+@prefix diameter_base_accounting
+@vendor 0 IETF
+
+@inherits diameter_gen_base_rfc3588
+
+@messages
+
+ ACR ::= < Diameter Header: 271, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Accounting-Record-Type }
+ { Accounting-Record-Number }
+ [ Acct-Application-Id ]
+ [ Vendor-Specific-Application-Id ]
+ [ User-Name ]
+ [ Accounting-Sub-Session-Id ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Acct-Interim-Interval ]
+ [ Accounting-Realtime-Required ]
+ [ Origin-State-Id ]
+ [ Event-Timestamp ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ACA ::= < Diameter Header: 271, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ { Accounting-Record-Type }
+ { Accounting-Record-Number }
+ [ Acct-Application-Id ]
+ [ Vendor-Specific-Application-Id ]
+ [ User-Name ]
+ [ Accounting-Sub-Session-Id ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Error-Reporting-Host ]
+ [ Acct-Interim-Interval ]
+ [ Accounting-Realtime-Required ]
+ [ Origin-State-Id ]
+ [ Event-Timestamp ]
+ * [ Proxy-Info ]
+ * [ AVP ]
diff --git a/lib/diameter/src/app/diameter_gen_base_rfc3588.dia b/lib/diameter/src/app/diameter_gen_base_rfc3588.dia
new file mode 100644
index 0000000000..4a12e21acd
--- /dev/null
+++ b/lib/diameter/src/app/diameter_gen_base_rfc3588.dia
@@ -0,0 +1,413 @@
+;;
+;; %CopyrightBegin%
+;;
+;; Copyright Ericsson AB 2010-2011. All Rights Reserved.
+;;
+;; The contents of this file are subject to the Erlang Public License,
+;; Version 1.1, (the "License"); you may not use this file except in
+;; compliance with the License. You should have received a copy of the
+;; Erlang Public License along with this software. If not, it can be
+;; retrieved online at http://www.erlang.org/.
+;;
+;; Software distributed under the License is distributed on an "AS IS"
+;; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+;; the License for the specific language governing rights and limitations
+;; under the License.
+;;
+;; %CopyrightEnd%
+;;
+
+@id 0
+@prefix diameter_base
+@vendor 0 IETF
+
+@avp_types
+
+ Acct-Interim-Interval 85 Unsigned32 M
+ Accounting-Realtime-Required 483 Enumerated M
+ Acct-Multi-Session-Id 50 UTF8String M
+ Accounting-Record-Number 485 Unsigned32 M
+ Accounting-Record-Type 480 Enumerated M
+ Acct-Session-Id 44 OctetString M
+ Accounting-Sub-Session-Id 287 Unsigned64 M
+ Acct-Application-Id 259 Unsigned32 M
+ Auth-Application-Id 258 Unsigned32 M
+ Auth-Request-Type 274 Enumerated M
+ Authorization-Lifetime 291 Unsigned32 M
+ Auth-Grace-Period 276 Unsigned32 M
+ Auth-Session-State 277 Enumerated M
+ Re-Auth-Request-Type 285 Enumerated M
+ Class 25 OctetString M
+ Destination-Host 293 DiamIdent M
+ Destination-Realm 283 DiamIdent M
+ Disconnect-Cause 273 Enumerated M
+ E2E-Sequence 300 Grouped M
+ Error-Message 281 UTF8String -
+ Error-Reporting-Host 294 DiamIdent -
+ Event-Timestamp 55 Time M
+ Experimental-Result 297 Grouped M
+ Experimental-Result-Code 298 Unsigned32 M
+ Failed-AVP 279 Grouped M
+ Firmware-Revision 267 Unsigned32 -
+ Host-IP-Address 257 Address M
+ Inband-Security-Id 299 Unsigned32 M
+ Multi-Round-Time-Out 272 Unsigned32 M
+ Origin-Host 264 DiamIdent M
+ Origin-Realm 296 DiamIdent M
+ Origin-State-Id 278 Unsigned32 M
+ Product-Name 269 UTF8String -
+ Proxy-Host 280 DiamIdent M
+ Proxy-Info 284 Grouped M
+ Proxy-State 33 OctetString M
+ Redirect-Host 292 DiamURI M
+ Redirect-Host-Usage 261 Enumerated M
+ Redirect-Max-Cache-Time 262 Unsigned32 M
+ Result-Code 268 Unsigned32 M
+ Route-Record 282 DiamIdent M
+ Session-Id 263 UTF8String M
+ Session-Timeout 27 Unsigned32 M
+ Session-Binding 270 Unsigned32 M
+ Session-Server-Failover 271 Enumerated M
+ Supported-Vendor-Id 265 Unsigned32 M
+ Termination-Cause 295 Enumerated M
+ User-Name 1 UTF8String M
+ Vendor-Id 266 Unsigned32 M
+ Vendor-Specific-Application-Id 260 Grouped M
+
+@messages
+
+ CER ::= < Diameter Header: 257, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+ 1* { Host-IP-Address }
+ { Vendor-Id }
+ { Product-Name }
+ [ Origin-State-Id ]
+ * [ Supported-Vendor-Id ]
+ * [ Auth-Application-Id ]
+ * [ Inband-Security-Id ]
+ * [ Acct-Application-Id ]
+ * [ Vendor-Specific-Application-Id ]
+ [ Firmware-Revision ]
+ * [ AVP ]
+
+ CEA ::= < Diameter Header: 257 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ 1* { Host-IP-Address }
+ { Vendor-Id }
+ { Product-Name }
+ [ Origin-State-Id ]
+ [ Error-Message ]
+ * [ Failed-AVP ]
+ * [ Supported-Vendor-Id ]
+ * [ Auth-Application-Id ]
+ * [ Inband-Security-Id ]
+ * [ Acct-Application-Id ]
+ * [ Vendor-Specific-Application-Id ]
+ [ Firmware-Revision ]
+ * [ AVP ]
+
+ DPR ::= < Diameter Header: 282, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+ { Disconnect-Cause }
+
+ DPA ::= < Diameter Header: 282 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Error-Message ]
+ * [ Failed-AVP ]
+
+ DWR ::= < Diameter Header: 280, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+ [ Origin-State-Id ]
+
+ DWA ::= < Diameter Header: 280 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Error-Message ]
+ * [ Failed-AVP ]
+ [ Origin-State-Id ]
+
+ answer-message ::= < Diameter Header: code, ERR [PXY] >
+ 0*1< Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Result-Code }
+ [ Origin-State-Id ]
+ [ Error-Reporting-Host ]
+ [ Proxy-Info ]
+ * [ AVP ]
+
+ RAR ::= < Diameter Header: 258, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Destination-Host }
+ { Auth-Application-Id }
+ { Re-Auth-Request-Type }
+ [ User-Name ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ RAA ::= < Diameter Header: 258, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ [ Origin-State-Id ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+ STR ::= < Diameter Header: 275, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Auth-Application-Id }
+ { Termination-Cause }
+ [ User-Name ]
+ [ Destination-Host ]
+ * [ Class ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ STA ::= < Diameter Header: 275, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ * [ Class ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ [ Origin-State-Id ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+ ASR ::= < Diameter Header: 274, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Destination-Host }
+ { Auth-Application-Id }
+ [ User-Name ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ASA ::= < Diameter Header: 274, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ [ Origin-State-Id ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+ ACR ::= < Diameter Header: 271, REQ, PXY >
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Accounting-Record-Type }
+ { Accounting-Record-Number }
+ [ Acct-Application-Id ]
+ [ Vendor-Specific-Application-Id ]
+ [ User-Name ]
+ [ Accounting-Sub-Session-Id ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Acct-Interim-Interval ]
+ [ Accounting-Realtime-Required ]
+ [ Origin-State-Id ]
+ [ Event-Timestamp ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ACA ::= < Diameter Header: 271, PXY >
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ { Accounting-Record-Type }
+ { Accounting-Record-Number }
+ [ Acct-Application-Id ]
+ [ Vendor-Specific-Application-Id ]
+ [ User-Name ]
+ [ Accounting-Sub-Session-Id ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Error-Reporting-Host ]
+ [ Acct-Interim-Interval ]
+ [ Accounting-Realtime-Required ]
+ [ Origin-State-Id ]
+ [ Event-Timestamp ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+@enum Disconnect-Cause
+
+ REBOOTING 0
+ BUSY 1
+ DO_NOT_WANT_TO_TALK_TO_YOU 2
+
+@enum Redirect-Host-Usage
+
+ DONT_CACHE 0
+ ALL_SESSION 1
+ ALL_REALM 2
+ REALM_AND_APPLICATION 3
+ ALL_APPLICATION 4
+ ALL_HOST 5
+ ALL_USER 6
+
+@enum Auth-Request-Type
+
+ AUTHENTICATE_ONLY 1
+ AUTHORIZE_ONLY 2
+ AUTHORIZE_AUTHENTICATE 3
+
+@enum Auth-Session-State
+
+ STATE_MAINTAINED 0
+ NO_STATE_MAINTAINED 1
+
+@enum Re-Auth-Request-Type
+
+ AUTHORIZE_ONLY 0
+ AUTHORIZE_AUTHENTICATE 1
+
+@enum Termination-Cause
+
+ DIAMETER_LOGOUT 1
+ DIAMETER_SERVICE_NOT_PROVIDED 2
+ DIAMETER_BAD_ANSWER 3
+ DIAMETER_ADMINISTRATIVE 4
+ DIAMETER_LINK_BROKEN 5
+ DIAMETER_AUTH_EXPIRED 6
+ DIAMETER_USER_MOVED 7
+ DIAMETER_SESSION_TIMEOUT 8
+
+@enum Session-Server-Failover
+
+ REFUSE_SERVICE 0
+ TRY_AGAIN 1
+ ALLOW_SERVICE 2
+ TRY_AGAIN_ALLOW_SERVICE 3
+
+@enum Accounting-Record-Type
+
+ EVENT_RECORD 1
+ START_RECORD 2
+ INTERIM_RECORD 3
+ STOP_RECORD 4
+
+@enum Accounting-Realtime-Required
+
+ DELIVER_AND_GRANT 1
+ GRANT_AND_STORE 2
+ GRANT_AND_LOSE 3
+
+@result_code Result-Code
+
+;; 7.1.1. Informational
+ DIAMETER_MULTI_ROUND_AUTH 1001
+
+;; 7.1.2. Success
+ DIAMETER_SUCCESS 2001
+ DIAMETER_LIMITED_SUCCESS 2002
+
+;; 7.1.3. Protocol Errors
+ DIAMETER_COMMAND_UNSUPPORTED 3001
+ DIAMETER_UNABLE_TO_DELIVER 3002
+ DIAMETER_REALM_NOT_SERVED 3003
+ DIAMETER_TOO_BUSY 3004
+ DIAMETER_LOOP_DETECTED 3005
+ DIAMETER_REDIRECT_INDICATION 3006
+ DIAMETER_APPLICATION_UNSUPPORTED 3007
+ DIAMETER_INVALID_HDR_BITS 3008
+ DIAMETER_INVALID_AVP_BITS 3009
+ DIAMETER_UNKNOWN_PEER 3010
+
+;; 7.1.4. Transient Failures
+ DIAMETER_AUTHENTICATION_REJECTED 4001
+ DIAMETER_OUT_OF_SPACE 4002
+ ELECTION_LOST 4003
+
+;; 7.1.5. Permanent Failures
+ DIAMETER_AVP_UNSUPPORTED 5001
+ DIAMETER_UNKNOWN_SESSION_ID 5002
+ DIAMETER_AUTHORIZATION_REJECTED 5003
+ DIAMETER_INVALID_AVP_VALUE 5004
+ DIAMETER_MISSING_AVP 5005
+ DIAMETER_RESOURCES_EXCEEDED 5006
+ DIAMETER_CONTRADICTING_AVPS 5007
+ DIAMETER_AVP_NOT_ALLOWED 5008
+ DIAMETER_AVP_OCCURS_TOO_MANY_TIMES 5009
+ DIAMETER_NO_COMMON_APPLICATION 5010
+ DIAMETER_UNSUPPORTED_VERSION 5011
+ DIAMETER_UNABLE_TO_COMPLY 5012
+ DIAMETER_INVALID_BIT_IN_HEADER 5013
+ DIAMETER_INVALID_AVP_LENGTH 5014
+ DIAMETER_INVALID_MESSAGE_LENGTH 5015
+ DIAMETER_INVALID_AVP_BIT_COMBO 5016
+ DIAMETER_NO_COMMON_SECURITY 5017
+
+@grouped
+
+ Proxy-Info ::= < AVP Header: 284 >
+ { Proxy-Host }
+ { Proxy-State }
+ * [ AVP ]
+
+ Failed-AVP ::= < AVP Header: 279 >
+ 1* {AVP}
+
+ Experimental-Result ::= < AVP Header: 297 >
+ { Vendor-Id }
+ { Experimental-Result-Code }
+
+ Vendor-Specific-Application-Id ::= < AVP Header: 260 >
+ 1* { Vendor-Id }
+ [ Auth-Application-Id ]
+ [ Acct-Application-Id ]
+
+;; The E2E-Sequence AVP is defined in RFC 3588 as Grouped, but
+;; there is no definition of the group - only an informal text stating
+;; that there should be a nonce (an OctetString) and a counter
+;; (integer)
+;;
+ E2E-Sequence ::= <AVP Header: 300 >
+ 2* { AVP }
diff --git a/lib/diameter/src/app/diameter_gen_relay.dia b/lib/diameter/src/app/diameter_gen_relay.dia
new file mode 100644
index 0000000000..d86446e368
--- /dev/null
+++ b/lib/diameter/src/app/diameter_gen_relay.dia
@@ -0,0 +1,24 @@
+;;
+;; %CopyrightBegin%
+;;
+;; Copyright Ericsson AB 2010-2011. All Rights Reserved.
+;;
+;; The contents of this file are subject to the Erlang Public License,
+;; Version 1.1, (the "License"); you may not use this file except in
+;; compliance with the License. You should have received a copy of the
+;; Erlang Public License along with this software. If not, it can be
+;; retrieved online at http://www.erlang.org/.
+;;
+;; Software distributed under the License is distributed on an "AS IS"
+;; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+;; the License for the specific language governing rights and limitations
+;; under the License.
+;;
+;; %CopyrightEnd%
+;;
+
+@id 0xFFFFFFFF
+@prefix diameter_relay
+@vendor 0 IETF
+
+@inherits diameter_gen_base_rfc3588
diff --git a/lib/diameter/src/app/diameter_info.erl b/lib/diameter/src/app/diameter_info.erl
new file mode 100644
index 0000000000..39d32d07cd
--- /dev/null
+++ b/lib/diameter/src/app/diameter_info.erl
@@ -0,0 +1,869 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_info).
+
+-export([usage/1,
+ format/1,
+ format/2,
+ format/3,
+ format/4,
+ table/2,
+ tables/1,
+ tables/2,
+ split/2,
+ split/3,
+ tab2list/1,
+ modules/1,
+ versions/1,
+ version_info/1,
+ attrs/2,
+ compiled/1,
+ procs/1,
+ latest/1,
+ list/1]).
+
+%% Support for rolling your own.
+-export([sep/0,
+ sep/1,
+ widest/1,
+ p/1,
+ p/3]).
+
+-compile({no_auto_import,[max/2]}).
+
+-export([collect/2]).
+
+-define(LONG_TIMEOUT, 30000).
+-define(VALUES(Rec), tl(tuple_to_list(Rec))).
+
+%%% ----------------------------------------------------------
+%%% # usage(String)
+%%% ----------------------------------------------------------
+
+usage(Usage) ->
+ sep($+),
+ io:format("+ ~p~n", [?MODULE]),
+ io:format("~n~s~n~n", [compact(Usage)]),
+ sep($+).
+
+%%%
+%%% The function format/3, for pretty-printing tables, comes in
+%%% several flavours.
+%%%
+
+%%% ----------------------------------------------------------
+%%% # format(TableName, Fields, SplitFun)
+%%%
+%%% Input: TableName = atom() name of table.
+%%%
+%%% Fields = List of field names for the records maintained
+%%% in the specified table. Can be empty, in which
+%%% case entries are listed unadorned of field names
+%%% and SplitFun is unused.
+%%% | Integer, equivalent to a list with this many '' atoms.
+%%% | Arity 1 fun mapping a table entry to a Fields list
+%%% or a tuple {Fields, Values} of lists of the same
+%%% length.
+%%%
+%%% If Fields is a list then its length must be the same
+%%% as or one less than the size of the tuples contained
+%%% in the table. (The values printed then being those
+%%% in the tuple or record in question.)
+%%%
+%%% SplitFun = Arity 3 fun applied as
+%%%
+%%% SplitFun(TableName, Fields, Values)
+%%%
+%%% in order to obtain a tuple
+%%%
+%%% {Field, RestFields, Value, RestValues}
+%%%
+%%% for which Field/Value will be formatted on
+%%% STDOUT. (This is to allow a value to be
+%%% transformed before being output by returning a
+%%% new value and/or replacing the remainder of
+%%% the list.) The returned lists must have the
+%%% same length and Field here is an atom, '' causing
+%%% a value to be listed unadorned of the field name.
+%%%
+%%% Field can also be list of field names, in
+%%% which case Value must be a record of the
+%%% corresponding type.
+%%%
+%%% | Arity 2 fun applied as SplitFun(Fields, Values).
+%%%
+%%% Output: Count | undefined
+%%%
+%%% Count = Number of entries output.
+%%%
+%%% Description: Pretty-print records in a named table.
+%%% ----------------------------------------------------------
+
+format(Table, Fields, SFun)
+ when is_atom(Table), is_function(SFun, 2) ->
+ ft(ets:info(Table), Table, SFun, Fields);
+
+format(Table, Fields, SFun)
+ when is_atom(Table), is_function(SFun, 3) ->
+ format(Table, Fields, fun(Fs,Vs) -> SFun(Table, Fs, Vs) end);
+
+%%% ----------------------------------------------------------
+%%% # format(Recs, Fields, SplitFun)
+%%%
+%%% Input: Recs = list of records/tuples
+%%% Fields = As for format(Table, Fields, SplitFun), a table
+%%% entry there being a member of Recs.
+%%% SplitFun = Arity 3 fun applied as above but with the TableName
+%%% replaced by the first element of the records in
+%%% question.
+%%% | Arity 2 fun as for format/3.
+%%%
+%%% Output: length(Recs)
+%%%
+%%% Description: Pretty print records/tuples.
+%%% ----------------------------------------------------------
+
+format(Recs, Fields, SFun)
+ when is_list(Recs), is_function(SFun, 3) ->
+ lists:foldl(fun(R,A) -> f(recsplit(SFun, R), 0, Fields, R, A) end,
+ 0,
+ Recs);
+
+format(Recs, Fields, SFun)
+ when is_list(Recs), is_function(SFun, 2) ->
+ lists:foldl(fun(R,A) -> f(SFun, 0, Fields, R, A) end,
+ 0,
+ Recs);
+
+%%% ----------------------------------------------------------
+%%% # format(Tables, SplitFun, CollectFun)
+%%%
+%%% Input: Tables = list of {TableName, Fields}.
+%%% SplitFun = As for format(Table, Fields, SplitFun).
+%%% CollectFun = arity 1 fun mapping a table name to a list
+%%% of elements. A non-list can be returned to indicate
+%%% that the table in question doesn't exist.
+%%%
+%%% Output: Number of entries output.
+%%%
+%%% Description: Pretty-print records in a named tables as collected
+%%% from known nodes. Each table listing is preceeded by
+%%% a banner.
+%%% ----------------------------------------------------------
+
+format(Tables, SFun, CFun)
+ when is_list(Tables), is_function(CFun, 1) ->
+ format_remote(Tables,
+ SFun,
+ rpc:multicall(nodes(known),
+ ?MODULE,
+ collect,
+ [CFun, lists:map(fun({T,_}) -> T end, Tables)],
+ ?LONG_TIMEOUT));
+
+%%% ----------------------------------------------------------
+%%% # format(LocalTables, RemoteTables, SplitFun, CollectFun)
+%%% # format(LocalTables, RemoteTables, SplitFun)
+%%%
+%%% Input: LocalTables = list of {TableName, Fields}.
+%%% | list of {TableName, Recs, Fields}
+%%% RemoteTable = list of {TableName, Fields}.
+%%% SplitFun, CollectFun = As for format(Table, CollectFun, SplitFun).
+%%%
+%%% Output: Number of entries output.
+%%%
+%%% Description: Pretty-print records in a named tables as collected
+%%% from local and remote nodes. Each table listing is
+%%% preceeded by a banner.
+%%% ----------------------------------------------------------
+
+format(Local, Remote, SFun) ->
+ format(Local, Remote, SFun, fun tab2list/1).
+
+format(Local, Remote, SFun, CFun)
+ when is_list(Local), is_list(Remote), is_function(CFun, 1) ->
+ format_local(Local, SFun) + format(Remote, SFun, CFun).
+
+%%% ----------------------------------------------------------
+%%% # format(Tables, SplitFun)
+%%% ----------------------------------------------------------
+
+format(Tables, SFun)
+ when is_list(Tables), (is_function(SFun, 2) or is_function(SFun, 3)) ->
+ format(Tables, SFun, fun tab2list/1);
+
+format(Tables, CFun)
+ when is_list(Tables), is_function(CFun, 1) ->
+ format(Tables, fun split/2, CFun).
+
+%%% ----------------------------------------------------------
+%%% # format(Table|Tables)
+%%% ----------------------------------------------------------
+
+format(Table)
+ when is_atom(Table) ->
+ format(Table, [], fun split/2);
+
+format(Tables)
+ when is_list(Tables) ->
+ format(Tables, fun split/2, fun tab2list/1).
+
+%%% ----------------------------------------------------------
+%%% # split(TableName, Fields, Values)
+%%%
+%%% Description: format/3 SplitFun that does nothing special.
+%%% ----------------------------------------------------------
+
+split([F|FT], [V|VT]) ->
+ {F, FT, V, VT}.
+
+split(_, Fs, Vs) ->
+ split(Fs, Vs).
+
+%%% ----------------------------------------------------------
+%%% # tab2list(TableName)
+%%%
+%%% Description: format/4 CollectFun that extracts records from an
+%%% existing ets table.
+%%% ----------------------------------------------------------
+
+tab2list(Table) ->
+ case ets:info(Table) of
+ undefined = No ->
+ No;
+ _ ->
+ ets:tab2list(Table)
+ end.
+
+list(Table) ->
+ l(tab2list(Table)).
+
+l(undefined = No) ->
+ No;
+l(List)
+ when is_list(List) ->
+ io:format("~p~n", [List]),
+ length(List).
+
+%%% ----------------------------------------------------------
+%%% # table(TableName, Fields)
+%%% ----------------------------------------------------------
+
+table(Table, Fields) ->
+ format(Table, Fields, fun split/2).
+
+%%% ----------------------------------------------------------
+%%% # tables(LocalTables, RemoteTables)
+%%% ----------------------------------------------------------
+
+tables(Local, Remote) ->
+ format(Local, Remote, fun split/2).
+
+%%% ----------------------------------------------------------
+%%% # tables(Tables)
+%%% ----------------------------------------------------------
+
+tables(Tables) ->
+ format(Tables, fun split/2).
+
+%%% ----------------------------------------------------------
+%%% # modules(Prefix|Prefixes)
+%%%
+%%% Input: Prefix = atom()
+%%%
+%%% Description: Return the list of all loaded modules with the
+%%% specified prefix.
+%%% ----------------------------------------------------------
+
+modules(Prefix)
+ when is_atom(Prefix) ->
+ lists:sort(mods(Prefix));
+
+modules(Prefixes)
+ when is_list(Prefixes) ->
+ lists:sort(lists:flatmap(fun modules/1, Prefixes)).
+
+mods(Prefix) ->
+ P = atom_to_list(Prefix),
+ lists:filter(fun(M) ->
+ lists:prefix(P, atom_to_list(M))
+ end,
+ erlang:loaded()).
+
+%%% ----------------------------------------------------------
+%%% # versions(Modules|Prefix)
+%%%
+%%% Output: Number of modules listed.
+%%%
+%%% Description: List the versions of the specified modules.
+%%% ----------------------------------------------------------
+
+versions(Modules) ->
+ {SysInfo, OsInfo, ModInfo} = version_info(Modules),
+ sep(),
+ print_sys_info(SysInfo),
+ sep(),
+ print_os_info(OsInfo),
+ sep(),
+ print_mod_info(ModInfo),
+ sep().
+
+%%% ----------------------------------------------------------
+%%% # attrs(Modules|Prefix, Attr|FormatFun)
+%%%
+%%% Output: Number of modules listed.
+%%%
+%%% Description: List an attribute from module_info.
+%%% ----------------------------------------------------------
+
+attrs(Modules, Attr)
+ when is_atom(Attr) ->
+ attrs(Modules, fun(W,M) -> attr(W, M, Attr, fun attr/1) end);
+
+attrs(Modules, Fun)
+ when is_list(Modules) ->
+ sep(),
+ W = 2 + widest(Modules),
+ N = lists:foldl(fun(M,A) -> Fun(W,M), A+1 end, 0, Modules),
+ sep(),
+ N;
+
+attrs(Prefix, Fun) ->
+ attrs(modules(Prefix), Fun).
+
+%% attr/1
+
+attr(T) when is_atom(T) ->
+ atom_to_list(T);
+attr(N) when is_integer(N) ->
+ integer_to_list(N);
+attr(V) ->
+ case is_list(V) andalso lists:all(fun is_char/1, V) of
+ true -> %% string
+ V;
+ false ->
+ io_lib:format("~p", [V])
+ end.
+
+is_char(C) ->
+ 0 =< C andalso C < 256.
+
+%% attr/4
+
+attr(Width, Mod, Attr, VFun) ->
+ io:format(": ~*s~s~n", [-Width, Mod, attr(Mod, Attr, VFun)]).
+
+attr(Mod, Attr, VFun) ->
+ Key = key(Attr),
+ try
+ VFun(val(Attr, keyfetch(Attr, Mod:module_info(Key))))
+ catch
+ _:_ ->
+ "-"
+ end.
+
+attr(Mod, Attr) ->
+ attr(Mod, Attr, fun attr/1).
+
+key(time) -> compile;
+key(_) -> attributes.
+
+val(time, {_,_,_,_,_,_} = T) ->
+ lists:flatten(io_lib:format("~p-~2..0B-~2..0B ~2..0B:~2..0B:~2..0B",
+ tuple_to_list(T)));
+val(_, [V]) ->
+ V.
+
+%%% ----------------------------------------------------------
+%%% # compiled(Modules|Prefix)
+%%%
+%%% Output: Number of modules listed.
+%%%
+%%% Description: List the compile times of the specified modules.
+%%% ----------------------------------------------------------
+
+compiled(Modules)
+ when is_list(Modules) ->
+ attrs(Modules, fun compiled/2);
+
+compiled(Prefix) ->
+ compiled(modules(Prefix)).
+
+compiled(Width, Mod) ->
+ io:format(": ~*s~19s ~s~n", [-Width,
+ Mod,
+ attr(Mod, time),
+ opt(attr(Mod, date))]).
+
+opt("-") ->
+ "";
+opt(D) ->
+ "(" ++ D ++ ")".
+
+%%% ----------------------------------------------------------
+%%% # procs(Pred|Prefix|Prefixes|Pid|Pids)
+%%%
+%%% Input: Pred = arity 2 fun returning true|false when applied to a
+%%% pid and its process info.
+%%%
+%%% Output: Number of processes listed.
+%%%
+%%% Description: List process info for all local processes that test
+%%% true with the specified predicate. With the prefix
+%%% form, those processes that are either currently
+%%% executing in, started executing in, or have a
+%%% registered name with a specified prefix are listed.
+%%% With the pid forms, only those process that are local
+%%% are listed and those that are dead list only the pid
+%%% itself.
+%%% ----------------------------------------------------------
+
+procs(Pred)
+ when is_function(Pred, 2) ->
+ procs(Pred, erlang:processes());
+
+procs([]) ->
+ 0;
+
+procs(Prefix)
+ when is_atom(Prefix) ->
+ procs(fun(_,I) -> info(fun pre1/2, I, atom_to_list(Prefix)) end);
+
+procs(Prefixes)
+ when is_atom(hd(Prefixes)) ->
+ procs(fun(_,I) -> info(fun pre/2, I, Prefixes) end);
+
+procs(Pid)
+ when is_pid(Pid) ->
+ procs(fun true2/2, [Pid]);
+
+procs(Pids)
+ when is_list(Pids) ->
+ procs(fun true2/2, Pids).
+
+true2(_,_) ->
+ true.
+
+%% procs/2
+
+procs(Pred, Pids) ->
+ Procs = lists:foldl(fun(P,A) ->
+ procs_acc(Pred, P, catch process_info(P), A)
+ end,
+ [],
+ Pids),
+ sep(0 < length(Procs)),
+ lists:foldl(fun(T,N) -> p(T), sep(), N+1 end, 0, Procs).
+
+procs_acc(_, Pid, undefined, Acc) -> %% dead
+ [[{pid, Pid}] | Acc];
+procs_acc(Pred, Pid, Info, Acc)
+ when is_list(Info) ->
+ p_acc(Pred(Pid, Info), Pid, Info, Acc);
+procs_acc(_, _, _, Acc) ->
+ Acc.
+
+p_acc(true, Pid, Info, Acc) ->
+ [[{pid, Pid} | Info] | Acc];
+p_acc(false, _, _, Acc) ->
+ Acc.
+
+%% info/3
+
+info(Pred, Info, T) ->
+ lists:any(fun(I) -> i(Pred, I, T) end, Info).
+
+i(Pred, {K, {M,_,_}}, T)
+ when K == current_function;
+ K == initial_call ->
+ Pred(M,T);
+i(Pred, {registered_name, N}, T) ->
+ Pred(N,T);
+i(_,_,_) ->
+ false.
+
+pre1(A, Pre) ->
+ lists:prefix(Pre, atom_to_list(A)).
+
+pre(A, Prefixes) ->
+ lists:any(fun(P) -> pre1(A, atom_to_list(P)) end, Prefixes).
+
+%%% ----------------------------------------------------------
+%%% # latest(Modules|Prefix)
+%%%
+%%% Output: {Mod, {Y,M,D,HH,MM,SS}, Version}
+%%%
+%%% Description: Return the compile time of the most recently compiled
+%%% module from the specified non-empty list. The modules
+%%% are assumed to exist.
+%%% ----------------------------------------------------------
+
+latest(Prefix)
+ when is_atom(Prefix) ->
+ latest(modules(Prefix));
+
+latest([_|_] = Modules) ->
+ {Mod, T}
+ = hd(lists:sort(fun latest/2, lists:map(fun compile_time/1, Modules))),
+ {Mod, T, app_vsn(Mod)}.
+
+app_vsn(Mod) ->
+ keyfetch(app_vsn, Mod:module_info(attributes)).
+
+compile_time(Mod) ->
+ T = keyfetch(time, Mod:module_info(compile)),
+ {Mod, T}.
+
+latest({_,T1},{_,T2}) ->
+ T1 > T2.
+
+%%% ----------------------------------------------------------
+%%% version_info(Modules|Prefix)
+%%%
+%%% Output: {SysInfo, OSInfo, [ModInfo]}
+%%%
+%%% SysInfo = {Arch, Vers}
+%%% OSInfo = {Vers, {Fam, Name}}
+%%% ModInfo = {Vsn, AppVsn, Time, CompilerVsn}
+%%% ----------------------------------------------------------
+
+version_info(Prefix)
+ when is_atom(Prefix) ->
+ version_info(modules(Prefix));
+
+version_info(Mods)
+ when is_list(Mods) ->
+ {sys_info(), os_info(), [{M, mod_version_info(M)} || M <- Mods]}.
+
+mod_version_info(Mod) ->
+ try
+ Info = Mod:module_info(),
+ [[Vsn], AppVsn] = get_values(attributes, [vsn, app_vsn], Info),
+ [Ver, Time] = get_values(compile, [version, time], Info),
+ [Vsn, AppVsn, Ver, Time]
+ catch
+ _:_ ->
+ []
+ end.
+
+get_values(Attr, Keys, Info) ->
+ As = proplists:get_value(Attr, Info),
+ [proplists:get_value(K, As, "?") || K <- Keys].
+
+sys_info() ->
+ [A,V] = [chomp(erlang:system_info(K)) || K <- [system_architecture,
+ system_version]],
+ {A,V}.
+
+os_info() ->
+ {os:version(), case os:type() of
+ {_Fam, _Name} = T ->
+ T;
+ Fam ->
+ {Fam, ""}
+ end}.
+
+chomp(S) ->
+ string:strip(S, right, $\n).
+
+print_sys_info({Arch, Ver}) ->
+ io:format("System info:~n"
+ " architecture : ~s~n"
+ " version : ~s~n",
+ [Arch, Ver]).
+
+print_os_info({Vsn, {Fam, Name}}) ->
+ io:format("OS info:~n"
+ " family : ~s ~s~n"
+ " version : ~s~n",
+ [str(Fam), bkt(str(Name)), vsn(Vsn)]).
+
+print_mod_info(Mods) ->
+ io:format("Module info:~n", []),
+ lists:foreach(fun print_mod/1, Mods).
+
+print_mod({Mod, []}) ->
+ io:format(" ~w:~n", [Mod]);
+print_mod({Mod, [Vsn, AppVsn, Ver, {Year, Month, Day, Hour, Min, Sec}]}) ->
+ Time = io_lib:format("~w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w",
+ [Year, Month, Day, Hour, Min, Sec]),
+ io:format(" ~w:~n"
+ " vsn : ~s~n"
+ " app_vsn : ~s~n"
+ " compiled : ~s~n"
+ " compiler : ~s~n",
+ [Mod, str(Vsn), str(AppVsn), Time, Ver]).
+
+str(A)
+ when is_atom(A) ->
+ atom_to_list(A);
+str(S)
+ when is_list(S) ->
+ S;
+str(T) ->
+ io_lib:format("~p", [T]).
+
+bkt("" = S) ->
+ S;
+bkt(S) ->
+ [$[, S, $]].
+
+vsn(T) when is_tuple(T) ->
+ case [[$., integer_to_list(N)] || N <- tuple_to_list(T)] of
+ [[$.,S] | Rest] ->
+ [S | Rest];
+ [] = S ->
+ S
+ end;
+vsn(T) ->
+ str(T).
+
+%%% ----------------------------------------------------------
+%%% ----------------------------------------------------------
+
+%% p/1
+
+p(Info) ->
+ W = 2 + widest([K || {K,_} <- Info]),
+ lists:foreach(fun({K,V}) -> p(W,K,V) end, Info).
+
+p(Width, Key, Value) ->
+ io:format(": ~*s: ~p~n", [-Width, Key, Value]).
+
+%% sep/[01]
+
+sep() ->
+ sep($#).
+
+sep(true) ->
+ sep();
+sep(false) ->
+ ok;
+
+sep(Ch) ->
+ io:format("~c~65c~n", [Ch, $-]).
+
+%% widest/1
+
+widest(List) ->
+ lists:foldl(fun widest/2, 0, List).
+
+widest(T, Max)
+ when is_atom(T) ->
+ widest(atom_to_list(T), Max);
+
+widest(T, Max)
+ when is_integer(T) ->
+ widest(integer_to_list(T), Max);
+
+widest(T, Max)
+ when is_list(T) -> %% string
+ max(length(T), Max).
+
+pt(T) ->
+ io:format(": ~p~n", [T]).
+
+recsplit(SFun, Rec) ->
+ fun(Fs,Vs) -> SFun(element(1, Rec), Fs, Vs) end.
+
+max(A, B) ->
+ if A > B -> A; true -> B end.
+
+keyfetch(Key, List) ->
+ {Key,V} = lists:keyfind(Key, 1, List),
+ V.
+
+%% ft/4
+
+ft(undefined = No, _, _, _) ->
+ No;
+
+ft(_, Table, SFun, Fields) ->
+ ets:foldl(fun(R,A) ->
+ f(SFun, 0, Fields, R, A)
+ end,
+ 0,
+ Table).
+
+%% f/5
+
+f(SFun, Width, Fields, Rec, Count) ->
+ ff(SFun, Width, fields(Fields, Rec), Rec, Count).
+
+ff(SFun, Width, Fields, Rec, Count) ->
+ sep(0 == Count),
+ f(SFun, Width, Fields, Rec),
+ sep(),
+ Count+1.
+
+fields(N, _)
+ when is_integer(N), N >= 0 ->
+ lists:duplicate(N, ''); %% list values unadorned
+fields(Fields, R)
+ when is_function(Fields, 1) ->
+ fields(Fields(R), R);
+fields({Fields, Values} = T, _)
+ when length(Fields) == length(Values) ->
+ T;
+fields(Fields, _)
+ when is_list(Fields) ->
+ Fields. %% list field/value pairs, or tuples if []
+
+%% f/4
+
+%% Empty fields list: just print the entry.
+f(_, _, [], Rec)
+ when is_tuple(Rec) ->
+ pt(Rec);
+
+%% Otherwise list field names/values.
+f(SFun, Width, {Fields, Values}, _) ->
+ f(SFun, Width, Fields, Values);
+
+f(SFun, Width, Fields, Rec)
+ when is_tuple(Rec) ->
+ f(SFun, Width, Fields, values(Fields, Rec));
+
+f(_, _, [], []) ->
+ ok;
+
+f(SFun, Width, [HF | _] = Fields, Values) ->
+ {F, FT, V, VT} = SFun(Fields, Values),
+ if is_list(F) -> %% V is a record
+ break($>, HF),
+ f(SFun, Width, F, values(F,V)),
+ break($<, HF),
+ f(SFun, Width, FT, VT);
+ F == '' -> %% no field name: just list value
+ pt(V),
+ f(SFun, Width, FT, VT);
+ true -> %% list field/value.
+ W = max(Width, 1 + widest(Fields)),
+ p(W, F, V),
+ f(SFun, W, FT, VT)
+ end.
+
+values(Fields, Rec)
+ when length(Fields) == size(Rec) - 1 ->
+ ?VALUES(Rec);
+values(Fields, T)
+ when length(Fields) == size(T) ->
+ tuple_to_list(T).
+
+%% format_local/2
+
+format_local(Tables, SFun) ->
+ lists:foldl(fun(T,A) -> fl(SFun, T, A) end, 0, Tables).
+
+fl(SFun, {Table, Recs, Fields}, Count) ->
+ sep(),
+ io:format("# ~p~n", [Table]),
+ N = fmt(Recs, Fields, SFun),
+ sep(0 == N),
+ Count + N;
+
+fl(SFun, {Table, Fields}, Count) ->
+ fl(SFun, {Table, Table, Fields}, Count).
+
+%% fmt/3
+
+fmt(T, Fields, SFun) ->
+ case format(T, Fields, SFun) of
+ undefined ->
+ 0;
+ N ->
+ N
+ end.
+
+%% break/2
+
+break(C, T) ->
+ io:format("~c ~p~n", [C, T]).
+
+%% collect/2
+%%
+%% Output: {[{TableName, Recs}, ...], node()}
+
+collect(CFun, TableNames) ->
+ {lists:foldl(fun(N,A) -> c(CFun, N, A) end, [], TableNames), node()}.
+
+c(CFun, TableName, Acc) ->
+ case CFun(TableName) of
+ Recs when is_list(Recs) ->
+ [{TableName, Recs} | Acc];
+ _ ->
+ Acc
+ end.
+
+%% format_remote/3
+
+format_remote(Tables, SFun, {Replies, BadNodes}) ->
+ N = lists:foldl(fun(T,A) -> fr(Tables, SFun, T, A) end,
+ 0,
+ Replies),
+ sep(0 == N andalso [] /= BadNodes),
+ lists:foreach(fun(Node) -> io:format("# no reply from ~p~n", [Node]) end,
+ BadNodes),
+ sep([] /= BadNodes),
+ N.
+
+fr(Tables, SFun, {List, Node}, Count)
+ when is_list(List) -> %% guard against {badrpc, Reason}
+ lists:foldl(fun({T,Recs}, C) -> fr(Tables, SFun, Node, T, Recs,C) end,
+ Count,
+ List);
+fr(_, _, _, Count) ->
+ Count.
+
+fr(Tables, SFun, Node, Table, Recs, Count) ->
+ Fields = keyfetch(Table, Tables),
+ sep(),
+ io:format("# ~p@~p~n", [Table, Node]),
+ N = format(Recs, Fields, tblsplit(SFun, Table)),
+ sep(0 == N),
+ Count + N.
+
+tblsplit(SFun, Table)
+ when is_function(SFun, 3) ->
+ fun(Fs,Vs) -> SFun(Table, Fs, Vs) end;
+tblsplit(SFun, _)
+ when is_function(SFun, 2) ->
+ SFun.
+
+%% compact/1
+%%
+%% Strip whitespace from both ends of a string.
+
+compact(Str) ->
+ compact(Str, true).
+
+compact([Ch|Rest], B)
+ when Ch == $\n;
+ Ch == $ ;
+ Ch == $\t;
+ Ch == $\v;
+ Ch == $\r ->
+ compact(Rest, B);
+
+compact(Str, false) ->
+ Str;
+
+compact(Str, true) ->
+ lists:reverse(compact(lists:reverse(Str), false)).
diff --git a/lib/diameter/src/app/diameter_internal.hrl b/lib/diameter/src/app/diameter_internal.hrl
new file mode 100644
index 0000000000..63b35550a8
--- /dev/null
+++ b/lib/diameter/src/app/diameter_internal.hrl
@@ -0,0 +1,80 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%% Our Erlang application.
+-define(APPLICATION, diameter).
+
+%% The one and only.
+-define(DIAMETER_VERSION, 1).
+
+%% Exception for use within a module with decent protection against
+%% catching something we haven't thrown. Not foolproof but close
+%% enough. ?MODULE is rudmentary protection against catching across
+%% module boundaries, a root of much evil: always catch ?FAILURE(X),
+%% never X.
+-define(FAILURE(Reason), {{?MODULE}, {Reason}}).
+-define(THROW(Reason), throw(?FAILURE(Reason))).
+
+%% A corresponding error when failure is the best option.
+-define(ERROR(T), erlang:error({T, ?MODULE, ?LINE})).
+
+%% Failure reports always get a stack trace.
+-define(STACK, erlang:get_stacktrace()).
+
+%% Warning report for unexpected messages in various processes.
+-define(UNEXPECTED(F,A),
+ diameter_lib:warning_report(unexpected, {?MODULE, F, A})).
+-define(UNEXPECTED(A), ?UNEXPECTED(?FUNC, A)).
+
+%% Something to trace on.
+-define(LOG(Slogan, Details),
+ diameter_lib:log(Slogan, ?MODULE, ?LINE, Details)).
+-define(LOGC(Bool, Slogan, Details), ((Bool) andalso ?LOG(Slogan, Details))).
+
+%% Compensate for no builtin ?FUNC for use in log reports.
+-define(FUNC, element(2, element(2, process_info(self(), current_function)))).
+
+%% Disjunctive match spec condition. 'false' is to ensure that there's at
+%% least one condition.
+-define(ORCOND(List), list_to_tuple(['orelse', false | List])).
+
+%% 3588, 2.4:
+-define(APP_ID_COMMON, 0).
+-define(APP_ID_RELAY, 16#FFFFFFFF).
+
+-define(BASE, diameter_gen_base_rfc3588).
+
+%%% ---------------------------------------------------------
+
+%%% RFC 3588, ch 2.6 Peer table
+-record(diameter_peer,
+ {host_id,
+ statusT,
+ is_dynamic,
+ expiration,
+ tls_enabled}).
+
+%%% RFC 3588, ch 2.7 Realm-based routing table
+-record(diameter_realm,
+ {name,
+ app_id,
+ local_action, % LOCAL | RELAY | PROXY | REDIRECT
+ server_id,
+ is_dynamic,
+ expiration}).
diff --git a/lib/diameter/src/app/diameter_lib.erl b/lib/diameter/src/app/diameter_lib.erl
new file mode 100644
index 0000000000..362d593b24
--- /dev/null
+++ b/lib/diameter/src/app/diameter_lib.erl
@@ -0,0 +1,272 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_lib).
+
+-export([report/2, info_report/2,
+ error_report/2,
+ warning_report/2,
+ now_diff/1,
+ time/1,
+ eval/1,
+ ip4address/1,
+ ip6address/1,
+ ipaddr/1,
+ spawn_opts/2,
+ wait/1,
+ fold_tuple/3,
+ log/4]).
+
+-include("diameter_internal.hrl").
+
+%% ---------------------------------------------------------------------------
+%% # info_report(Reason, MFA)
+%%
+%% Input: Reason = Arbitrary term indicating the reason for the report.
+%% MFA = {Module, Function, Args} to report.
+%%
+%% Output: true
+%% ---------------------------------------------------------------------------
+
+report(Reason, MFA) ->
+ info_report(Reason, MFA).
+
+info_report(Reason, MFA) ->
+ report(fun error_logger:info_report/1, Reason, MFA),
+ true.
+
+%%% ---------------------------------------------------------------------------
+%%% # error_report(Reason, MFA)
+%%% # warning_report(Reason, MFA)
+%%%
+%%% Output: false
+%%% ---------------------------------------------------------------------------
+
+error_report(Reason, MFA) ->
+ report(fun error_logger:error_report/1, Reason, MFA).
+
+warning_report(Reason, MFA) ->
+ report(fun error_logger:warning_report/1, Reason, MFA).
+
+report(Fun, Reason, MFA) ->
+ Fun([{why, Reason}, {who, self()}, {what, MFA}]),
+ false.
+
+%%% ---------------------------------------------------------------------------
+%%% # now_diff(Time)
+%%%
+%%% Description: Return timer:now_diff(now(), Time) as an {H, M, S, MicroS}
+%%% tuple instead of as integer microseconds.
+%%% ---------------------------------------------------------------------------
+
+now_diff({_,_,_} = Time) ->
+ time(timer:now_diff(erlang:now(), Time)).
+
+%%% ---------------------------------------------------------------------------
+%%% # time(Time)
+%%%
+%%% Input: Time = {MegaSec, Sec, MicroSec}
+%%% | MicroSec
+%%%
+%%% Output: {H, M, S, MicroS}
+%%% ---------------------------------------------------------------------------
+
+time({_,_,_} = Time) -> %% time of day
+ %% 24 hours = 24*60*60*1000000 = 86400000000 microsec
+ time(timer:now_diff(Time, {0,0,0}) rem 86400000000);
+
+time(Micro) -> %% elapsed time
+ Seconds = Micro div 1000000,
+ H = Seconds div 3600,
+ M = (Seconds rem 3600) div 60,
+ S = Seconds rem 60,
+ {H, M, S, Micro rem 1000000}.
+
+%%% ---------------------------------------------------------------------------
+%%% # eval(Func)
+%%% ---------------------------------------------------------------------------
+
+eval({M,F,A}) ->
+ apply(M,F,A);
+
+eval([{M,F,A} | X]) ->
+ apply(M, F, X ++ A);
+
+eval([[F|A] | X]) ->
+ eval([F | X ++ A]);
+
+eval([F|A]) ->
+ apply(F,A);
+
+eval({F}) ->
+ eval(F);
+
+eval(F) ->
+ F().
+
+%%% ---------------------------------------------------------------------------
+%%% # ip4address(Addr)
+%%%
+%%% Input: string() (eg. "10.0.0.1")
+%%% | list of integer()
+%%% | tuple of integer()
+%%%
+%%% Output: {_,_,_,_} of integer
+%%%
+%%% Exceptions: error: {invalid_address, Addr, erlang:get_stacktrace()}
+%%% ---------------------------------------------------------------------------
+
+ip4address([_,_,_,_] = Addr) -> %% Length 4 string can't be an address.
+ ipaddr(list_to_tuple(Addr));
+
+%% Be brutal.
+ip4address(Addr) ->
+ try
+ {_,_,_,_} = ipaddr(Addr)
+ catch
+ error: _ ->
+ erlang:error({invalid_address, Addr, ?STACK})
+ end.
+
+%%% ---------------------------------------------------------------------------
+%%% # ip6address(Addr)
+%%%
+%%% Input: string() (eg. "1080::8:800:200C:417A")
+%%% | list of integer()
+%%% | tuple of integer()
+%%%
+%%% Output: {_,_,_,_,_,_,_,_} of integer
+%%%
+%%% Exceptions: error: {invalid_address, Addr, erlang:get_stacktrace()}
+%%% ---------------------------------------------------------------------------
+
+ip6address([_,_,_,_,_,_,_,_] = Addr) -> %% Length 8 string can't be an address.
+ ipaddr(list_to_tuple(Addr));
+
+%% Be brutal.
+ip6address(Addr) ->
+ try
+ {_,_,_,_,_,_,_,_} = ipaddr(Addr)
+ catch
+ error: _ ->
+ erlang:error({invalid_address, Addr, ?STACK})
+ end.
+
+%%% ---------------------------------------------------------------------------
+%%% # ipaddr(Addr)
+%%%
+%%% Input: string() | tuple of integer()
+%%%
+%%% Output: {_,_,_,_} | {_,_,_,_,_,_,_,_}
+%%%
+%%% Exceptions: error: {invalid_address, erlang:get_stacktrace()}
+%%% ---------------------------------------------------------------------------
+
+-spec ipaddr(string() | tuple())
+ -> inet:ip_address().
+
+%% Don't convert lists of integers since a length 8 list like
+%% [$1,$0,$.,$0,$.,$0,$.,$1] is ambiguous: is it "10.0.0.1" or
+%% "49:48:46:48:46:48:46:49"?
+%%
+%% RFC 2373 defines the format parsed for v6 addresses.
+
+%% Be brutal.
+ipaddr(Addr) ->
+ try
+ ip(Addr)
+ catch
+ error: _ ->
+ erlang:error({invalid_address, ?STACK})
+ end.
+
+%% Already a tuple: ensure non-negative integers of the right size.
+ip(T)
+ when size(T) == 4;
+ size(T) == 8 ->
+ Bs = 2*size(T),
+ [] = lists:filter(fun(N) when 0 =< N -> 0 < N bsr Bs end,
+ tuple_to_list(T)),
+ T;
+
+%% Or not: convert from '.'/':'-separated decimal/hex.
+ip(Addr) ->
+ {ok, A} = inet_parse:address(Addr), %% documented in inet(3)
+ A.
+
+%%% ---------------------------------------------------------------------------
+%%% # spawn_opts(Type, Opts)
+%%% ---------------------------------------------------------------------------
+
+%% TODO: config variables.
+
+spawn_opts(server, Opts) ->
+ opts(75000, Opts);
+spawn_opts(worker, Opts) ->
+ opts(5000, Opts).
+
+opts(HeapSize, Opts) ->
+ [{min_heap_size, HeapSize} | lists:keydelete(min_heap_size, 1, Opts)].
+
+%%% ---------------------------------------------------------------------------
+%%% # wait(MRefs)
+%%% ---------------------------------------------------------------------------
+
+wait(L) ->
+ w([erlang:monitor(process, P) || P <- L]).
+
+w([]) ->
+ ok;
+w(L) ->
+ receive
+ {'DOWN', MRef, process, _, _} ->
+ w(lists:delete(MRef, L))
+ end.
+
+%%% ---------------------------------------------------------------------------
+%%% # fold_tuple(N, T0, T)
+%%% ---------------------------------------------------------------------------
+
+%% Replace fields in T0 by those of T starting at index N, unless the
+%% new value is 'undefined'.
+%%
+%% eg. fold_tuple(2, Hdr, #diameter_header{end_to_end_id = 42})
+
+fold_tuple(_, T, undefined) ->
+ T;
+
+fold_tuple(N, T0, T1) ->
+ {_, T} = lists:foldl(fun(V, {I,_} = IT) -> {I+1, ft(V, IT)} end,
+ {N, T0},
+ lists:nthtail(N-1, tuple_to_list(T1))),
+ T.
+
+ft(undefined, {_, T}) ->
+ T;
+ft(Value, {Idx, T}) ->
+ setelement(Idx, T, Value).
+
+%%% ----------------------------------------------------------
+%%% # log(Slogan, Mod, Line, Details)
+%%%
+%%% Called to have something to trace on for happenings of interest.
+%%% ----------------------------------------------------------
+
+log(_, _, _, _) ->
+ ok.
diff --git a/lib/diameter/src/app/diameter_misc_sup.erl b/lib/diameter/src/app/diameter_misc_sup.erl
new file mode 100644
index 0000000000..4e40476f14
--- /dev/null
+++ b/lib/diameter/src/app/diameter_misc_sup.erl
@@ -0,0 +1,58 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% The supervisor of the static server processes.
+%%
+
+-module(diameter_misc_sup).
+
+-behaviour(supervisor).
+
+-export([start_link/0]). %% supervisor start
+
+%% supervisor callback
+-export([init/1]).
+
+-define(CHILDREN, [diameter_sync, %% serialization
+ diameter_stats, %% statistics counter management
+ diameter_reg, %% service/property publishing
+ diameter_peer, %% remote peer manager
+ diameter_config]). %% configuration/restart
+
+%% start_link/0
+
+start_link() ->
+ SupName = {local, ?MODULE},
+ supervisor:start_link(SupName, ?MODULE, []).
+
+%% init/1
+
+init([]) ->
+ Flags = {one_for_one, 1, 5},
+ Workers = lists:map(fun spec/1, ?CHILDREN),
+ {ok, {Flags, Workers}}.
+
+spec(Mod) ->
+ {Mod,
+ {Mod, start_link, []},
+ permanent,
+ 1000,
+ worker,
+ [Mod]}.
diff --git a/lib/diameter/src/app/diameter_peer.erl b/lib/diameter/src/app/diameter_peer.erl
new file mode 100644
index 0000000000..3e78c4caef
--- /dev/null
+++ b/lib/diameter/src/app/diameter_peer.erl
@@ -0,0 +1,225 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_peer).
+
+-behaviour(gen_server).
+
+%% Interface towards transport modules ...
+-export([recv/2,
+ up/1,
+ up/2]).
+
+%% ... and the stack.
+-export([start/3,
+ send/2,
+ close/1,
+ abort/1,
+ notify/2]).
+
+%% Server start.
+-export([start_link/0]).
+
+%% gen_server callbacks
+-export([init/1,
+ terminate/2,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ code_change/3]).
+
+%% debug
+-export([state/0,
+ uptime/0]).
+
+-include_lib("diameter/include/diameter.hrl").
+-include("diameter_internal.hrl").
+
+%% Registered name of the server.
+-define(SERVER, ?MODULE).
+
+%% Server state.
+-record(state, {id = now()}).
+
+%%% ---------------------------------------------------------------------------
+%%% # notify/2
+%%% ---------------------------------------------------------------------------
+
+notify(SvcName, T) ->
+ rpc:abcast(nodes(), ?SERVER, {notify, SvcName, T}).
+
+%%% ---------------------------------------------------------------------------
+%%% # start/3
+%%% ---------------------------------------------------------------------------
+
+start(T, Opts, #diameter_service{} = Svc) ->
+ {Mod, Cfg} = split_transport(Opts),
+ apply(Mod, start, [T, Svc, Cfg]).
+
+%%% ---------------------------------------------------------------------------
+%%% # up/[12]
+%%% ---------------------------------------------------------------------------
+
+up(Pid) -> %% accepting transport
+ ifc_send(Pid, {self(), connected}).
+
+up(Pid, Remote) -> %% connecting transport
+ ifc_send(Pid, {self(), connected, Remote}).
+
+%%% ---------------------------------------------------------------------------
+%%% # recv/2
+%%% ---------------------------------------------------------------------------
+
+recv(Pid, Pkt) ->
+ ifc_send(Pid, {recv, Pkt}).
+
+%%% ---------------------------------------------------------------------------
+%%% # send/2
+%%% ---------------------------------------------------------------------------
+
+send(Pid, #diameter_packet{transport_data = undefined,
+ bin = Bin}) ->
+ send(Pid, Bin);
+
+send(Pid, Pkt) ->
+ ifc_send(Pid, {send, Pkt}).
+
+%%% ---------------------------------------------------------------------------
+%%% # close/1
+%%% ---------------------------------------------------------------------------
+
+close(Pid) ->
+ ifc_send(Pid, {close, self()}).
+
+%%% ---------------------------------------------------------------------------
+%%% # abort/1
+%%% ---------------------------------------------------------------------------
+
+abort(Pid) ->
+ exit(Pid, shutdown).
+
+%% ---------------------------------------------------------------------------
+%% ---------------------------------------------------------------------------
+
+start_link() ->
+ ServerName = {local, ?SERVER},
+ Module = ?MODULE,
+ Args = [],
+ Options = [{spawn_opt, diameter_lib:spawn_opts(server, [])}],
+ gen_server:start_link(ServerName, Module, Args, Options).
+
+state() ->
+ call(state).
+
+uptime() ->
+ call(uptime).
+
+%%% ----------------------------------------------------------
+%%% # init(Role)
+%%% ----------------------------------------------------------
+
+init([]) ->
+ {ok, #state{}}.
+
+%%% ----------------------------------------------------------
+%%% # handle_call(Request, From, State)
+%%% ----------------------------------------------------------
+
+handle_call(state, _, State) ->
+ {reply, State, State};
+
+handle_call(uptime, _, #state{id = Time} = State) ->
+ {reply, diameter_lib:now_diff(Time), State};
+
+handle_call(Req, From, State) ->
+ ?UNEXPECTED([Req, From]),
+ {reply, nok, State}.
+
+%%% ----------------------------------------------------------
+%%% # handle_cast(Request, State)
+%%% ----------------------------------------------------------
+
+handle_cast(Msg, State) ->
+ ?UNEXPECTED([Msg]),
+ {noreply, State}.
+
+%%% ----------------------------------------------------------
+%%% # handle_info(Request, State)
+%%% ----------------------------------------------------------
+
+%% Remote service is distributing a message.
+handle_info({notify, SvcName, T}, S) ->
+ bang(diameter_service:whois(SvcName), T),
+ {noreply, S};
+
+handle_info(Info, State) ->
+ ?UNEXPECTED([Info]),
+ {noreply, State}.
+
+%% ----------------------------------------------------------
+%% terminate(Reason, State)
+%% ----------------------------------------------------------
+
+terminate(_Reason, _State) ->
+ ok.
+
+%% ----------------------------------------------------------
+%% code_change(OldVsn, State, Extra)
+%% ----------------------------------------------------------
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%% ---------------------------------------------------------
+%% INTERNAL FUNCTIONS
+%% ---------------------------------------------------------
+
+%% ifc_send/2
+%%
+%% Send something over the transport interface.
+
+ifc_send(Pid, T) ->
+ Pid ! {diameter, T}.
+
+%% bang/2
+
+bang(undefined = No, _) ->
+ No;
+bang(Pid, T) ->
+ Pid ! T.
+
+%% split_transport/1
+%%
+%% Split options into transport module, transport config and
+%% remaining options.
+
+split_transport(Opts) ->
+ {[M,C], _} = proplists:split(Opts, [transport_module,
+ transport_config]),
+ {value(M, diameter_tcp), value(C, [])}.
+
+value([{_,V}], _) ->
+ V;
+value([], V) ->
+ V.
+
+%% call/1
+
+call(Request) ->
+ gen_server:call(?SERVER, Request, infinity).
diff --git a/lib/diameter/src/app/diameter_peer_fsm.erl b/lib/diameter/src/app/diameter_peer_fsm.erl
new file mode 100644
index 0000000000..282fa2742f
--- /dev/null
+++ b/lib/diameter/src/app/diameter_peer_fsm.erl
@@ -0,0 +1,777 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 module implements (as a process) the RFC 3588 Peer State
+%% Machine modulo the necessity of adapting the peer election to the
+%% fact that we don't know the identity of a peer until we've
+%% received a CER/CEA from it.
+%%
+
+-module(diameter_peer_fsm).
+-behaviour(gen_server).
+
+%% Interface towards diameter_watchdog.
+-export([start/3]).
+
+%% gen_server callbacks
+-export([init/1,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ terminate/2,
+ code_change/3]).
+
+%% diameter_peer_fsm_sup callback
+-export([start_link/1]).
+
+%% internal callbacks
+-export([match/1]).
+
+-include_lib("diameter/include/diameter.hrl").
+-include("diameter_internal.hrl").
+-include("diameter_types.hrl").
+-include("diameter_gen_base_rfc3588.hrl").
+
+-define(GOAWAY, ?'DIAMETER_BASE_DISCONNECT-CAUSE_DO_NOT_WANT_TO_TALK_TO_YOU').
+-define(REBOOT, ?'DIAMETER_BASE_DISCONNECT-CAUSE_REBOOTING').
+
+-define(NO_INBAND_SECURITY, 0).
+-define(TLS, 1).
+
+-define(LOOP_TIMEOUT, 2000).
+
+%% RFC 3588:
+%%
+%% Timeout An application-defined timer has expired while waiting
+%% for some event.
+%%
+-define(EVENT_TIMEOUT, 10000).
+
+%% How long to wait for a DPA in response to DPR before simply
+%% aborting. Used to distinguish between shutdown and not but there's
+%% not really any need. Stopping a service will require a timeout if
+%% the peer doesn't answer DPR so the value should be short-ish.
+-define(DPA_TIMEOUT, 1000).
+
+-record(state,
+ {state = 'Wait-Conn-Ack' %% state of RFC 3588 Peer State Machine
+ :: 'Wait-Conn-Ack' | recv_CER | 'Wait-CEA' | 'Open',
+ mode :: accept | connect | {connect, reference()},
+ parent :: pid(),
+ transport :: pid(),
+ service :: #diameter_service{},
+ dpr = false :: false | {'Unsigned32'(), 'Unsigned32'()}}).
+ %% | hop by hop and end to end identifiers
+
+%% There are non-3588 states possible as a consequence of 5.6.1 of the
+%% standard and the corresponding problem for incoming CEA's: we don't
+%% know who we're talking to until either a CER or CEA has been
+%% received. The CEA problem in particular makes it impossible to
+%% follow the state machine exactly as documented in 3588: there can
+%% be no election until the CEA arrives and we have an Origin-Host to
+%% elect.
+
+%%
+%% Once upon a time start/2 started a process akin to that started by
+%% start/3 below, which in turn started a watchdog/transport process
+%% with the result that the watchdog could send DWR/DWA regardless of
+%% whether or not the corresponding Peer State Machine was in its open
+%% state; that is, before capabilities exchange had taken place. This
+%% is not what RFC's 3588 and 3539 say (albeit not very clearly).
+%% Watchdog messages are only exchanged on *open* connections, so the
+%% 3539 state machine is more naturally placed on top of the 3588 Peer
+%% State Machine rather than closer to the transport. This is what we
+%% now do below: connect/accept call diameter_watchdog and return the
+%% pid of the watchdog process, and the watchdog in turn calls start/3
+%% below to start the process implementing the Peer State Machine. The
+%% former is a "peer" in diameter_service while the latter is a
+%% "conn". In a sense, diameter_service sees the watchdog as
+%% implementing the Peer State Machine and the process implemented
+%% here as being the transport, not being aware of the watchdog at
+%% all.
+%%
+
+%%% ---------------------------------------------------------------------------
+%%% # start({connect|accept, Ref}, Opts, Service)
+%%%
+%%% Output: Pid
+%%% ---------------------------------------------------------------------------
+
+%% diameter_config requires a non-empty list of applications on the
+%% service but diameter_service then constrains the list to any
+%% specified on the transport in question. Check here that the list is
+%% still non-empty.
+
+start({_, Ref} = Type, Opts, #diameter_service{applications = Apps} = Svc) ->
+ [] /= Apps orelse ?ERROR({no_apps, Type, Opts}),
+ T = {self(), Type, Opts, Svc},
+ {ok, Pid} = diameter_peer_fsm_sup:start_child(T),
+ diameter_stats:reg(Pid, Ref),
+ Pid.
+
+start_link(T) ->
+ {ok, _} = proc_lib:start_link(?MODULE,
+ init,
+ [T],
+ infinity,
+ diameter_lib:spawn_opts(server, [])).
+
+%%% ---------------------------------------------------------------------------
+%%% ---------------------------------------------------------------------------
+
+%% init/1
+
+init(T) ->
+ proc_lib:init_ack({ok, self()}),
+ gen_server:enter_loop(?MODULE, [], i(T)).
+
+i({WPid, {M, _} = T, Opts, #diameter_service{capabilities = Caps} = Svc0}) ->
+ putr(dwa, dwa(Caps)),
+ {ok, TPid, Svc} = start_transport(T, Opts, Svc0),
+ erlang:monitor(process, TPid),
+ erlang:monitor(process, WPid),
+ #state{parent = WPid,
+ transport = TPid,
+ mode = M,
+ service = Svc}.
+%% The transport returns its local ip addresses so that different
+%% transports on the same service can use different local addresses.
+%% The local addresses are put into Host-IP-Address avps here when
+%% sending capabilities exchange messages.
+%%
+%% Invalid transport config may cause us to crash but note that the
+%% watchdog start (start/2) succeeds regardless so as not to crash the
+%% service.
+
+start_transport(T, Opts, Svc) ->
+ case diameter_peer:start(T, Opts, Svc) of
+ {ok, TPid} ->
+ {ok, TPid, Svc};
+ {ok, TPid, [_|_] = Addrs} ->
+ #diameter_service{capabilities = Caps0} = Svc,
+ Caps = Caps0#diameter_caps{host_ip_address = Addrs},
+ {ok, TPid, Svc#diameter_service{capabilities = Caps}};
+ No ->
+ exit({shutdown, No})
+ end.
+
+%% handle_call/3
+
+handle_call(_, _, State) ->
+ {reply, nok, State}.
+
+%% handle_cast/2
+
+handle_cast(_, State) ->
+ {noreply, State}.
+
+%% handle_info/1
+
+handle_info(T, #state{} = State) ->
+ try transition(T, State) of
+ ok ->
+ {noreply, State};
+ #state{state = X} = S ->
+ ?LOGC(X =/= State#state.state, transition, X),
+ {noreply, S};
+ {stop, Reason} ->
+ ?LOG(stop, Reason),
+ x(Reason, State);
+ stop ->
+ ?LOG(stop, T),
+ x(T, State)
+ catch
+ throw: {?MODULE, Tag, Reason} ->
+ ?LOG(Tag, {Reason, T}),
+ {stop, {shutdown, Reason}, State}
+ end.
+
+x(Reason, #state{} = S) ->
+ close_wd(Reason, S),
+ {stop, {shutdown, Reason}, S}.
+
+%% terminate/2
+
+terminate(_, _) ->
+ ok.
+
+%% code_change/3
+
+code_change(_, State, _) ->
+ {ok, State}.
+
+%%% ---------------------------------------------------------------------------
+%%% ---------------------------------------------------------------------------
+
+putr(Key, Val) ->
+ put({?MODULE, Key}, Val).
+
+getr(Key) ->
+ get({?MODULE, Key}).
+
+%% transition/2
+
+%% Connection to peer.
+transition({diameter, {TPid, connected, Remote}},
+ #state{state = PS,
+ mode = M}
+ = S) ->
+ 'Wait-Conn-Ack' = PS, %% assert
+ connect = M, %%
+ send_CER(S#state{mode = {M, Remote},
+ transport = TPid});
+
+%% Connection from peer.
+transition({diameter, {TPid, connected}},
+ #state{state = PS,
+ mode = M,
+ parent = Pid}
+ = S) ->
+ 'Wait-Conn-Ack' = PS, %% assert
+ accept = M, %%
+ Pid ! {accepted, self()},
+ start_timer(S#state{state = recv_CER,
+ transport = TPid});
+
+%% Incoming message from the transport.
+transition({diameter, {recv, Pkt}}, S) ->
+ recv(Pkt, S);
+
+%% Timeout when still in the same state ...
+transition({timeout, PS}, #state{state = PS}) ->
+ stop;
+
+%% ... or not.
+transition({timeout, _}, _) ->
+ ok;
+
+%% Outgoing message.
+transition({send, Msg}, #state{transport = TPid}) ->
+ send(TPid, Msg),
+ ok;
+
+%% Request for graceful shutdown.
+transition({shutdown, Pid}, #state{parent = Pid, dpr = false} = S) ->
+ dpr(?GOAWAY, S);
+transition({shutdown, Pid}, #state{parent = Pid}) ->
+ ok;
+
+%% Application shutdown.
+transition(shutdown, #state{dpr = false} = S) ->
+ dpr(?REBOOT, S);
+transition(shutdown, _) -> %% DPR already send: ensure expected timeout
+ dpa_timer(),
+ ok;
+
+%% Request to close the transport connection.
+transition({close = T, Pid}, #state{parent = Pid,
+ transport = TPid}) ->
+ diameter_peer:close(TPid),
+ {stop, T};
+
+%% DPA reception has timed out.
+transition(dpa_timeout, _) ->
+ stop;
+
+%% Someone wants to know a resolved port: forward to the transport process.
+transition({resolve_port, _Pid} = T, #state{transport = TPid}) ->
+ TPid ! T,
+ ok;
+
+%% Parent or transport has died.
+transition({'DOWN', _, process, P, _},
+ #state{parent = Pid,
+ transport = TPid})
+ when P == Pid;
+ P == TPid ->
+ stop;
+
+%% State query.
+transition({state, Pid}, #state{state = S, transport = TPid}) ->
+ Pid ! {self(), [S, TPid]},
+ ok.
+
+%% Crash on anything unexpected.
+
+%% send_CER/1
+
+send_CER(#state{mode = {connect, Remote},
+ service = #diameter_service{capabilities = Caps},
+ transport = TPid}
+ = S) ->
+ req_send_CER(Caps#diameter_caps.origin_host, Remote)
+ orelse
+ close(connected, S),
+ CER = build_CER(S),
+ ?LOG(send, 'CER'),
+ send(TPid, encode(CER)),
+ start_timer(S#state{state = 'Wait-CEA'}).
+
+%% Register ourselves as connecting to the remote endpoint in
+%% question. This isn't strictly necessary since a peer implementing
+%% the 3588 Peer State Machine should reject duplicate connection's
+%% from the same peer but there's little point in us setting up a
+%% duplicate connection in the first place. This could also include
+%% the transport protocol being used but since we're blind to
+%% transport just avoid duplicate connections to the same host/port.
+req_send_CER(OriginHost, Remote) ->
+ register_everywhere({?MODULE, connection, OriginHost, {remote, Remote}}).
+
+%% start_timer/1
+
+start_timer(#state{state = PS} = S) ->
+ erlang:send_after(?EVENT_TIMEOUT, self(), {timeout, PS}),
+ S.
+
+%% build_CER/1
+
+build_CER(#state{service = #diameter_service{capabilities = Caps}}) ->
+ {ok, CER} = diameter_capx:build_CER(Caps),
+ CER.
+
+%% encode/1
+
+encode(Rec) ->
+ #diameter_packet{bin = Bin} = diameter_codec:encode(?BASE, Rec),
+ Bin.
+
+%% recv/2
+
+%% RFC 3588 has result code 5015 for an invalid length but if a
+%% transport is detecting message boundaries using the length header
+%% then a length error will likely lead to further errors.
+
+recv(#diameter_packet{header = #diameter_header{length = Len}
+ = Hdr,
+ bin = Bin},
+ S)
+ when Len < 20;
+ (0 /= Len rem 4 orelse bit_size(Bin) /= 8*Len) ->
+ discard(invalid_message_length, recv, [size(Bin),
+ bit_size(Bin) rem 8,
+ Hdr,
+ S]);
+
+recv(#diameter_packet{header = #diameter_header{} = Hdr}
+ = Pkt,
+ #state{parent = Pid}
+ = S) ->
+ Name = diameter_codec:msg_name(Hdr),
+ Pid ! {recv, self(), Name, Pkt},
+ diameter_stats:incr({msg_id(Name, Hdr), recv}), %% count received
+ rcv(Name, Pkt, S);
+
+recv(#diameter_packet{header = undefined,
+ bin = Bin}
+ = Pkt,
+ S) ->
+ recv(Pkt#diameter_packet{header = diameter_codec:decode_header(Bin)}, S);
+
+recv(Bin, S)
+ when is_binary(Bin) ->
+ recv(#diameter_packet{bin = Bin}, S);
+
+recv(#diameter_packet{header = false} = Pkt, S) ->
+ discard(truncated_header, recv, [Pkt, S]).
+
+msg_id({_,_,_} = T, _) ->
+ T;
+msg_id(_, Hdr) ->
+ diameter_codec:msg_id(Hdr).
+
+%% Treat invalid length as a transport error and die. Especially in
+%% the TCP case, in which there's no telling where the next message
+%% begins in the incoming byte stream, keeping a crippled connection
+%% alive may just make things worse.
+
+discard(Reason, F, A) ->
+ diameter_stats:incr(Reason),
+ diameter_lib:warning_report(Reason, {?MODULE, F, A}),
+ throw({?MODULE, abort, Reason}).
+
+%% rcv/3
+
+%% Incoming CEA.
+rcv('CEA', Pkt, #state{state = 'Wait-CEA'} = S) ->
+ handle_CEA(Pkt, S);
+
+%% Incoming CER
+rcv('CER' = N, Pkt, #state{state = recv_CER} = S) ->
+ handle_request(N, Pkt, S);
+
+%% Anything but CER/CEA in a non-Open state is an error, as is
+%% CER/CEA in anything but recv_CER/Wait-CEA.
+rcv(Name, _, #state{state = PS})
+ when PS /= 'Open';
+ Name == 'CER';
+ Name == 'CEA' ->
+ {stop, {Name, PS}};
+
+rcv(N, Pkt, S)
+ when N == 'DWR';
+ N == 'DPR' ->
+ handle_request(N, Pkt, S);
+
+%% DPA even though we haven't sent DPR: ignore.
+rcv('DPA', _Pkt, #state{dpr = false}) ->
+ ok;
+
+%% DPA in response to DPR. We could check the sequence numbers but
+%% don't bother, just close.
+rcv('DPA' = N, _Pkt, #state{transport = TPid}) ->
+ diameter_peer:close(TPid),
+ {stop, N};
+
+rcv(_, _, _) ->
+ ok.
+
+%% send/2
+
+%% Msg here could be a #diameter_packet or a binary depending on who's
+%% sending. In particular, the watchdog will send DWR as a binary
+%% while messages coming from clients will be in a #diameter_packet.
+send(Pid, Msg) ->
+ diameter_stats:incr({diameter_codec:msg_id(Msg), send}),
+ diameter_peer:send(Pid, Msg).
+
+%% handle_request/3
+
+handle_request(Type, #diameter_packet{} = Pkt, S) ->
+ ?LOG(recv, Type),
+ send_answer(Type, diameter_codec:decode(?BASE, Pkt), S).
+
+%% send_answer/3
+
+send_answer(Type, ReqPkt, #state{transport = TPid} = S) ->
+ #diameter_packet{header = #diameter_header{version = V,
+ end_to_end_id = Eid,
+ hop_by_hop_id = Hid,
+ is_proxiable = P},
+ transport_data = TD}
+ = ReqPkt,
+
+ {Answer, PostF} = build_answer(Type, V, ReqPkt, S),
+
+ Pkt = #diameter_packet{header = #diameter_header{version = V,
+ end_to_end_id = Eid,
+ hop_by_hop_id = Hid,
+ is_proxiable = P},
+ msg = Answer,
+ transport_data = TD},
+
+ send(TPid, diameter_codec:encode(?BASE, Pkt)),
+ eval(PostF, S).
+
+eval([F|A], S) ->
+ apply(F, A ++ [S]);
+eval(ok, S) ->
+ S.
+
+%% build_answer/4
+
+build_answer('CER',
+ ?DIAMETER_VERSION,
+ #diameter_packet{msg = CER,
+ header = #diameter_header{is_error = false},
+ errors = []}
+ = Pkt,
+ #state{service = Svc}
+ = S) ->
+ #diameter_service{capabilities = #diameter_caps{origin_host = OH}}
+ = Svc,
+
+ {SupportedApps,
+ #diameter_caps{origin_host = DH} = RCaps,
+ #diameter_base_CEA{'Result-Code' = RC}
+ = CEA}
+ = recv_CER(CER, S),
+
+ try
+ 2001 == RC %% DIAMETER_SUCCESS
+ orelse ?THROW({sent_CEA, RC}),
+ register_everywhere({?MODULE, connection, OH, DH})
+ orelse ?THROW({election_lost, 4003}),
+ #diameter_base_CEA{'Inband-Security-Id' = [IS]}
+ = CEA,
+ {CEA, [fun open/5, Pkt, SupportedApps, RCaps, {accept, IS}]}
+ catch
+ ?FAILURE({Reason, RC}) ->
+ {answer('CER', S) ++ [{'Result-Code', RC}],
+ [fun close/2, {'CER', Reason, DH}]}
+ end;
+
+%% The error checks below are similar to those in diameter_service for
+%% other messages. Should factor out the commonality.
+
+build_answer(Type, V, #diameter_packet{header = H, errors = Es} = Pkt, S) ->
+ FailedAvp = failed_avp([A || {_,A} <- Es]),
+ Ans = answer(answer(Type, S), V, H, Es),
+ {set(Ans, FailedAvp), if 'CER' == Type ->
+ [fun close/2, {Type, V, Pkt}];
+ true ->
+ ok
+ end}.
+
+failed_avp([] = No) ->
+ No;
+failed_avp(Avps) ->
+ [{'Failed-AVP', [[{'AVP', Avps}]]}].
+
+set(Ans, []) ->
+ Ans;
+set(['answer-message' | _] = Ans, FailedAvp) ->
+ Ans ++ [{'AVP', [FailedAvp]}];
+set([_|_] = Ans, FailedAvp) ->
+ Ans ++ FailedAvp.
+
+answer([_, OH, OR | _], _, #diameter_header{is_error = true}, _) ->
+ ['answer-message', OH, OR, {'Result-Code', 3008}];
+
+answer([_, OH, OR | _], _, _, [Bs|_])
+ when is_bitstring(Bs) ->
+ ['answer-message', OH, OR, {'Result-Code', 3009}];
+
+answer(Ans, ?DIAMETER_VERSION, _, Es) ->
+ Ans ++ [{'Result-Code', rc(Es)}];
+
+answer(Ans, _, _, _) ->
+ Ans ++ [{'Result-Code', 5011}]. %% DIAMETER_UNSUPPORTED_VERSION
+
+rc([]) ->
+ 2001; %% DIAMETER_SUCCESS
+rc([{RC,_}|_]) ->
+ RC;
+rc([RC|_]) ->
+ RC.
+
+%% DIAMETER_INVALID_HDR_BITS 3008
+%% A request was received whose bits in the Diameter header were
+%% either set to an invalid combination, or to a value that is
+%% inconsistent with the command code's definition.
+
+%% DIAMETER_INVALID_AVP_BITS 3009
+%% A request was received that included an AVP whose flag bits are
+%% set to an unrecognized value, or that is inconsistent with the
+%% AVP's definition.
+
+%% ELECTION_LOST 4003
+%% The peer has determined that it has lost the election process and
+%% has therefore disconnected the transport connection.
+
+%% DIAMETER_NO_COMMON_APPLICATION 5010
+%% This error is returned when a CER message is received, and there
+%% are no common applications supported between the peers.
+
+%% DIAMETER_UNSUPPORTED_VERSION 5011
+%% This error is returned when a request was received, whose version
+%% number is unsupported.
+
+%% answer/2
+
+answer('DWR', _) ->
+ getr(dwa);
+
+answer(Name, #state{service = #diameter_service{capabilities = Caps}}) ->
+ a(Name, Caps).
+
+a('CER', #diameter_caps{vendor_id = Vid,
+ origin_host = Host,
+ origin_realm = Realm,
+ host_ip_address = Addrs,
+ product_name = Name}) ->
+ ['CEA', {'Origin-Host', Host},
+ {'Origin-Realm', Realm},
+ {'Host-IP-Address', Addrs},
+ {'Vendor-Id', Vid},
+ {'Product-Name', Name}];
+
+a('DPR', #diameter_caps{origin_host = Host,
+ origin_realm = Realm}) ->
+ ['DPA', {'Origin-Host', Host},
+ {'Origin-Realm', Realm}].
+
+%% recv_CER/2
+
+recv_CER(CER, #state{service = Svc}) ->
+ {ok, T} = diameter_capx:recv_CER(CER, Svc),
+ T.
+
+%% handle_CEA/1
+
+handle_CEA(#diameter_packet{header = #diameter_header{version = V},
+ bin = Bin}
+ = Pkt,
+ #state{service = #diameter_service{capabilities = LCaps}}
+ = S)
+ when is_binary(Bin) ->
+ ?LOG(recv, 'CEA'),
+
+ ?DIAMETER_VERSION == V orelse close({version, V}, S),
+
+ #diameter_packet{msg = CEA, errors = Errors}
+ = DPkt
+ = diameter_codec:decode(?BASE, Pkt),
+
+ [] == Errors orelse close({errors, Errors}, S),
+
+ {SApps, [IS], #diameter_caps{origin_host = DH} = RCaps}
+ = recv_CEA(CEA, S),
+
+ #diameter_caps{origin_host = OH}
+ = LCaps,
+
+ %% Ensure that we don't already have a connection to the peer in
+ %% question. This isn't the peer election of 3588 except in the
+ %% sense that, since we don't know who we're talking to until we
+ %% receive a CER/CEA, the first that arrives wins the right to a
+ %% connection with the peer.
+
+ register_everywhere({?MODULE, connection, OH, DH})
+ orelse close({'CEA', DH}, S),
+
+ open(DPkt, SApps, RCaps, {connect, IS}, S).
+
+%% recv_CEA/2
+
+recv_CEA(CEA, #state{service = Svc} = S) ->
+ case diameter_capx:recv_CEA(CEA, Svc) of
+ {ok, {_,_}} -> %% return from old code
+ close({'CEA', update}, S);
+ {ok, {[], _, _}} ->
+ close({'CEA', no_common_application}, S);
+ {ok, {_, [], _}} ->
+ close({'CEA', no_common_security}, S);
+ {ok, {_,_,_} = T} ->
+ T;
+ {error, Reason} ->
+ close({'CEA', Reason}, S)
+ end.
+
+%% open/5
+
+open(Pkt, SupportedApps, RCaps, {Type, IS}, #state{parent = Pid,
+ service = Svc}
+ = S) ->
+ #diameter_service{capabilities = #diameter_caps{origin_host = OH,
+ inband_security_id = LS}
+ = LCaps}
+ = Svc,
+ #diameter_caps{origin_host = DH}
+ = RCaps,
+
+ tls_ack(lists:member(?TLS, LS), Type, IS, S),
+ Pid ! {open, self(), {OH,DH}, {capz(LCaps, RCaps), SupportedApps, Pkt}},
+
+ S#state{state = 'Open'}.
+
+%% We've advertised TLS support: tell the transport the result
+%% and expect a reply when the handshake is complete.
+tls_ack(true, Type, IS, #state{transport = TPid} = S) ->
+ Ref = make_ref(),
+ MRef = erlang:monitor(process, TPid),
+ TPid ! {diameter, {tls, Ref, Type, IS == ?TLS}},
+ receive
+ {diameter, {tls, Ref}} ->
+ erlang:demonitor(MRef, [flush]);
+ {'DOWN', MRef, process, _, _} = T ->
+ close({tls_ack, T}, S)
+ end;
+
+%% Or not. Don't send anything to the transport so that transports
+%% not supporting TLS work as before without modification.
+tls_ack(false, _, _, _) ->
+ ok.
+
+capz(#diameter_caps{} = L, #diameter_caps{} = R) ->
+ #diameter_caps{}
+ = list_to_tuple([diameter_caps | lists:zip(tl(tuple_to_list(L)),
+ tl(tuple_to_list(R)))]).
+
+%% close/2
+
+%% Tell the watchdog that our death isn't due to transport failure.
+close(Reason, #state{parent = Pid}) ->
+ close_wd(Reason, Pid),
+ throw({?MODULE, close, Reason}).
+
+%% close_wd/2
+
+%% Ensure the watchdog dies if DPR has been sent ...
+close_wd(_, #state{dpr = false}) ->
+ ok;
+close_wd(Reason, #state{parent = Pid}) ->
+ close_wd(Reason, Pid);
+
+%% ... or otherwise
+close_wd(Reason, Pid) ->
+ Pid ! {close, self(), Reason}.
+
+%% dwa/1
+
+dwa(#diameter_caps{origin_host = OH,
+ origin_realm = OR,
+ origin_state_id = OSI}) ->
+ ['DWA', {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Origin-State-Id', OSI}].
+
+%% dpr/2
+
+dpr(Cause, #state{transport = TPid,
+ service = #diameter_service{capabilities = Caps}}
+ = S) ->
+ #diameter_caps{origin_host = OH,
+ origin_realm = OR}
+ = Caps,
+
+ Bin = encode(['DPR', {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Disconnect-Cause', Cause}]),
+ send(TPid, Bin),
+ dpa_timer(),
+ ?LOG(send, 'DPR'),
+ S#state{dpr = diameter_codec:sequence_numbers(Bin)}.
+
+dpa_timer() ->
+ erlang:send_after(?DPA_TIMEOUT, self(), dpa_timeout).
+
+%% register_everywhere/1
+%%
+%% Register a term and ensure it's not registered elsewhere. Note that
+%% two process that simultaneously register the same term may well
+%% both fail to do so this isn't foolproof.
+
+register_everywhere(T) ->
+ diameter_reg:add_new(T)
+ andalso unregistered(T).
+
+unregistered(T) ->
+ {ResL, _} = rpc:multicall(?MODULE, match, [{node(), T}]),
+ lists:all(fun(L) -> [] == L end, ResL).
+
+match({Node, _})
+ when Node == node() ->
+ [];
+match({_, T}) ->
+ try
+ diameter_reg:match(T)
+ catch
+ _:_ -> []
+ end.
diff --git a/lib/diameter/src/app/diameter_peer_fsm_sup.erl b/lib/diameter/src/app/diameter_peer_fsm_sup.erl
new file mode 100644
index 0000000000..995eaf74d0
--- /dev/null
+++ b/lib/diameter/src/app/diameter_peer_fsm_sup.erl
@@ -0,0 +1,63 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% The supervisor of peer_fsm processes.
+%%
+
+-module(diameter_peer_fsm_sup).
+
+-behaviour(supervisor).
+
+-define(NAME, ?MODULE). %% supervisor name
+
+%%-----------------------------------------------------------------
+%% External exports
+%%-----------------------------------------------------------------
+
+-export([start_link/0, %% supervisor start
+ start_child/1]). %% peer fsm start
+
+-export([init/1]).
+
+%% start_link/0
+
+start_link() ->
+ SupName = {local, ?NAME},
+ supervisor:start_link(SupName, ?MODULE, []).
+
+%% start_child/1
+%%
+%% Start a peer_fsm process.
+
+start_child(T) ->
+ supervisor:start_child(?NAME, [T]).
+
+%% init/1
+
+init([]) ->
+ Mod = diameter_peer_fsm,
+ Flags = {simple_one_for_one, 0, 1},
+ ChildSpec = {Mod,
+ {Mod, start_link, []},
+ temporary,
+ 1000,
+ worker,
+ [Mod]},
+ {ok, {Flags, [ChildSpec]}}.
diff --git a/lib/diameter/src/app/diameter_reg.erl b/lib/diameter/src/app/diameter_reg.erl
new file mode 100644
index 0000000000..882b9da238
--- /dev/null
+++ b/lib/diameter/src/app/diameter_reg.erl
@@ -0,0 +1,327 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% The module implements a simple term -> pid registry.
+%%
+
+-module(diameter_reg).
+-compile({no_auto_import, [monitor/2]}).
+
+-behaviour(gen_server).
+
+-export([add/1,
+ add_new/1,
+ del/1,
+ repl/2,
+ match/1]).
+
+-export([start_link/0]).
+
+%% gen_server callbacks
+-export([init/1,
+ terminate/2,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ code_change/3]).
+
+%% test
+-export([pids/0,
+ terms/0]).
+
+%% debug
+-export([state/0,
+ uptime/0]).
+
+-include("diameter_internal.hrl").
+
+-define(SERVER, ?MODULE).
+-define(TABLE, ?MODULE).
+
+%% Table entry used to keep from starting more than one monitor on the
+%% same process. This isn't a problem but there's no point in starting
+%% multiple monitors if we can avoid it. Note that we can't have a 2-tuple
+%% keyed on Pid since a registered term can be anything. Want the entry
+%% keyed on Pid so that lookup is fast.
+-define(MONITOR(Pid, MRef), {Pid, monitor, MRef}).
+
+%% Table entry containing the Term -> Pid mapping.
+-define(MAPPING(Term, Pid), {Term, Pid}).
+
+-record(state, {id = now()}).
+
+%%% ----------------------------------------------------------
+%%% # add(T)
+%%%
+%%% Input: Term = term()
+%%%
+%%% Output: true
+%%%
+%%% Description: Associate the specified term with self(). The list of pids
+%%% having this or other assocations can be retrieved using
+%%% match/1.
+%%%
+%%% An association is removed when the calling process dies
+%%% or as a result of calling del/1. Adding the same term
+%%% more than once is equivalent to adding it exactly once.
+%%%
+%%% Note that since match/1 takes a pattern as argument,
+%%% specifying a term that contains match variables is
+%%% probably not a good idea
+%%% ----------------------------------------------------------
+
+-spec add(any())
+ -> true.
+
+add(T) ->
+ call({add, fun ets:insert/2, T, self()}).
+
+%%% ----------------------------------------------------------
+%%% # add_new(T)
+%%%
+%%% Input: T = term()
+%%%
+%%% Output: true | false
+%%%
+%%% Description: Like add/1 but only one process is allowed to have the
+%%% the association, false being returned if an association
+%%% already exists.
+%%% ----------------------------------------------------------
+
+-spec add_new(any())
+ -> boolean().
+
+add_new(T) ->
+ call({add, fun insert_new/2, T, self()}).
+
+%%% ----------------------------------------------------------
+%%% # repl(T, NewT)
+%%%
+%%% Input: T, NewT = term()
+%%%
+%%% Output: true | false
+%%%
+%%% Description: Like add/1 but only replace an existing association on T,
+%%% false being returned if it doesn't exist.
+%%% ----------------------------------------------------------
+
+-spec repl(any(), any())
+ -> boolean().
+
+repl(T, U) ->
+ call({repl, T, U, self()}).
+
+%%% ----------------------------------------------------------
+%%% # del(Term)
+%%%
+%%% Input: Term = term()
+%%%
+%%% Output: true
+%%%
+%%% Description: Remove any existing association of Term with self().
+%%% ----------------------------------------------------------
+
+-spec del(any())
+ -> true.
+
+del(T) ->
+ call({del, T, self()}).
+
+%%% ----------------------------------------------------------
+%%% # match(Pat)
+%%%
+%%% Input: Pat = pattern in the sense of ets:match_object/2.
+%%%
+%%% Output: list of {Term, Pid}
+%%%
+%%% Description: Return the list of associations whose Term, as specified
+%%% to add/1 or add_new/1, matches the specified pattern.
+%%%
+%%% Note that there's no guarantee that the returned processes
+%%% are still alive. (Although one that isn't will soon have
+%%% its associations removed.)
+%%% ----------------------------------------------------------
+
+-spec match(tuple())
+ -> [{term(), pid()}].
+
+match(Pat) ->
+ ets:match_object(?TABLE, ?MAPPING(Pat, '_')).
+
+%% ---------------------------------------------------------
+%% EXPORTED INTERNAL FUNCTIONS
+%% ---------------------------------------------------------
+
+start_link() ->
+ ServerName = {local, ?SERVER},
+ Options = [{spawn_opt, diameter_lib:spawn_opts(server, [])}],
+ gen_server:start_link(ServerName, ?MODULE, [], Options).
+
+state() ->
+ call(state).
+
+uptime() ->
+ call(uptime).
+
+%% pids/0
+%%
+%% Output: list of {Pid, [Term, ...]}
+
+pids() ->
+ to_list(fun swap/1).
+
+to_list(Fun) ->
+ ets:foldl(fun(T,A) -> acc(Fun, T, A) end, orddict:new(), ?TABLE).
+
+acc(Fun, ?MAPPING(Term, Pid), Dict) ->
+ append(Fun({Term, Pid}), Dict);
+acc(_, _, Dict) ->
+ Dict.
+
+append({K,V}, Dict) ->
+ orddict:append(K, V, Dict).
+
+id(T) -> T.
+
+%% terms/0
+%%
+%% Output: list of {Term, [Pid, ...]}
+
+terms() ->
+ to_list(fun id/1).
+
+swap({X,Y}) -> {Y,X}.
+
+%%% ----------------------------------------------------------
+%%% # init(Role)
+%%%
+%%% Output: {ok, State}
+%%% ----------------------------------------------------------
+
+init(_) ->
+ ets:new(?TABLE, [bag, named_table]),
+ {ok, #state{}}.
+
+%%% ----------------------------------------------------------
+%%% # handle_call(Request, From, State)
+%%% ----------------------------------------------------------
+
+handle_call({add, Fun, Key, Pid}, _, State) ->
+ B = Fun(?TABLE, {Key, Pid}),
+ monitor(B andalso no_monitor(Pid), Pid),
+ {reply, B, State};
+
+handle_call({del, Key, Pid}, _, State) ->
+ {reply, ets:delete_object(?TABLE, ?MAPPING(Key, Pid)), State};
+
+handle_call({repl, T, U, Pid}, _, State) ->
+ MatchSpec = [{?MAPPING('$1', Pid),
+ [{'=:=', '$1', {const, T}}],
+ ['$_']}],
+ {reply, repl(ets:select(?TABLE, MatchSpec), U, Pid), State};
+
+handle_call(state, _, State) ->
+ {reply, State, State};
+
+handle_call(uptime, _, #state{id = Time} = State) ->
+ {reply, diameter_lib:now_diff(Time), State};
+
+handle_call(Req, From, State) ->
+ ?UNEXPECTED([Req, From]),
+ {reply, nok, State}.
+
+%%% ----------------------------------------------------------
+%%% # handle_cast(Request, State)
+%%% ----------------------------------------------------------
+
+handle_cast(Msg, State)->
+ ?UNEXPECTED([Msg]),
+ {noreply, State}.
+
+%%% ----------------------------------------------------------
+%%% # handle_info(Request, State)
+%%% ----------------------------------------------------------
+
+handle_info({'DOWN', MRef, process, Pid, _}, State) ->
+ ets:delete_object(?TABLE, ?MONITOR(Pid, MRef)),
+ ets:match_delete(?TABLE, ?MAPPING('_', Pid)),
+ {noreply, State};
+
+handle_info(Info, State) ->
+ ?UNEXPECTED([Info]),
+ {noreply, State}.
+
+%%% ----------------------------------------------------------
+%%% # terminate(Reason, State)
+%%% ----------------------------------------------------------
+
+terminate(_Reason, _State)->
+ ok.
+
+%%% ----------------------------------------------------------
+%%% # code_change(OldVsn, State, Extra)
+%%% ----------------------------------------------------------
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%% ---------------------------------------------------------
+%% INTERNAL FUNCTIONS
+%% ---------------------------------------------------------
+
+monitor(true, Pid) ->
+ ets:insert(?TABLE, ?MONITOR(Pid, erlang:monitor(process, Pid)));
+monitor(false, _) ->
+ ok.
+
+%% Do we need a monitor for the specified Pid?
+no_monitor(Pid) ->
+ [] == ets:match_object(?TABLE, ?MONITOR(Pid, '_')).
+
+%% insert_new/2
+
+insert_new(?TABLE, {Key, _} = T) ->
+ flush(ets:lookup(?TABLE, Key)),
+ ets:insert_new(?TABLE, T).
+
+%% Remove any processes that are dead but for which we may not have
+%% received 'DOWN' yet. This is to ensure that add_new can be used
+%% to register a unique name each time a process restarts.
+flush(List) ->
+ lists:foreach(fun({_,P} = T) ->
+ del(erlang:is_process_alive(P), T)
+ end,
+ List).
+
+del(Alive, T) ->
+ Alive orelse ets:delete_object(?TABLE, T).
+
+%% repl/3
+
+repl([?MAPPING(_, Pid) = M], Key, Pid) ->
+ ets:delete_object(?TABLE, M),
+ true = ets:insert(?TABLE, ?MAPPING(Key, Pid));
+repl([], _, _) ->
+ false.
+
+%% call/1
+
+call(Request) ->
+ gen_server:call(?SERVER, Request, infinity).
diff --git a/lib/diameter/src/app/diameter_service.erl b/lib/diameter/src/app/diameter_service.erl
new file mode 100644
index 0000000000..421e36ccf5
--- /dev/null
+++ b/lib/diameter/src/app/diameter_service.erl
@@ -0,0 +1,2903 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Implements the process that represents a service.
+%%
+
+-module(diameter_service).
+-behaviour(gen_server).
+
+-export([start/1,
+ stop/1,
+ start_transport/2,
+ stop_transport/2,
+ info/2,
+ call/4]).
+
+%% towards diameter_watchdog
+-export([receive_message/3]).
+
+%% service supervisor
+-export([start_link/1]).
+
+-export([subscribe/1,
+ unsubscribe/1,
+ subscriptions/1,
+ subscriptions/0,
+ services/0,
+ services/1,
+ whois/1,
+ flush_stats/1]).
+
+%% test/debug
+-export([call_module/3,
+ state/1,
+ uptime/1]).
+
+%%% gen_server callbacks
+-export([init/1,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ terminate/2,
+ code_change/3]).
+
+%% Other callbacks.
+-export([send/1]).
+
+-include_lib("diameter/include/diameter.hrl").
+-include("diameter_internal.hrl").
+-include("diameter_types.hrl").
+
+-define(STATE_UP, up).
+-define(STATE_DOWN, down).
+
+-define(DEFAULT_TC, 30000). %% RFC 3588 ch 2.1
+-define(DEFAULT_TIMEOUT, 5000). %% for outgoing requests
+-define(RESTART_TC, 1000). %% if restart was this recent
+
+%% Used to be able to swap this with anything else dict-like but now
+%% rely on the fact that a service's #state{} record does not change
+%% in storing in it ?STATE table and not always going through the
+%% service process. In particular, rely on the fact that operations on
+%% a ?Dict don't change the handle to it.
+-define(Dict, diameter_dict).
+
+%% Table containing outgoing requests for which a reply has yet to be
+%% received.
+-define(REQUEST_TABLE, diameter_request).
+
+%% Maintains state in a table. In contrast to previously, a service's
+%% stat is not constant and is accessed outside of the service
+%% process.
+-define(STATE_TABLE, ?MODULE).
+
+%% Workaround for dialyzer's lack of understanding of match specs.
+-type match(T)
+ :: T | '_' | '$1' | '$2' | '$3' | '$4'.
+
+%% State of service gen_server.
+-record(state,
+ {id = now(),
+ service_name, %% as passed to start_service/2, key in ?STATE_TABLE
+ service :: #diameter_service{},
+ peerT = ets_new(peers) :: ets:tid(), %% #peer{} at start_fsm
+ connT = ets_new(conns) :: ets:tid(), %% #conn{} at connection_up
+ share_peers = false :: boolean(), %% broadcast peers to remote nodes?
+ use_shared_peers = false :: boolean(), %% use broadcasted peers?
+ shared_peers = ?Dict:new(), %% Alias -> [{TPid, Caps}, ...]
+ local_peers = ?Dict:new(), %% Alias -> [{TPid, Caps}, ...]
+ monitor = false :: false | pid()}). %% process to die with
+%% shared_peers reflects the peers broadcast from remote nodes. Note
+%% that the state term itself doesn't change, which is relevant for
+%% the stateless application callbacks since the state is retrieved
+%% from ?STATE_TABLE from outside the service process. The pid in the
+%% service record is used to determine whether or not we need to call
+%% the process for a pick_peer callback.
+
+%% Record representing a watchdog process.
+-record(peer,
+ {pid :: match(pid()),
+ type :: match(connect | accept),
+ ref :: match(reference()), %% key into diameter_config
+ options :: match([transport_opt()]), %% as passed to start_transport
+ op_state = ?STATE_DOWN :: match(?STATE_DOWN | ?STATE_UP),
+ started = now(), %% at process start
+ conn = false :: match(boolean() | pid())}).
+ %% true at accept, pid() at connection_up (connT key)
+
+%% Record representing a peer_fsm process.
+-record(conn,
+ {pid :: pid(),
+ apps :: [{0..16#FFFFFFFF, app_alias()}], %% {Id, Alias}
+ caps :: #diameter_caps{},
+ started = now(), %% at process start
+ peer :: pid()}). %% key into peerT
+
+%% Record stored in diameter_request for each outgoing request.
+-record(request,
+ {from, %% arg 2 of handle_call/3
+ handler :: match(pid()), %% request process
+ transport :: match(pid()), %% peer process
+ caps :: match(#diameter_caps{}),
+ app :: match(app_alias()), %% #diameter_app.alias
+ dictionary :: match(module()), %% #diameter_app.dictionary
+ module :: match(nonempty_improper_list(module(), list())),
+ %% #diameter_app.module
+ filter :: match(peer_filter()),
+ packet :: match(#diameter_packet{})}).
+
+%% Record call/4 options are parsed into.
+-record(options,
+ {filter = none :: peer_filter(),
+ extra = [] :: list(),
+ timeout = ?DEFAULT_TIMEOUT :: 0..16#FFFFFFFF,
+ detach = false :: boolean()}).
+
+%% Since RFC 3588 requires that a Diameter agent not modify End-to-End
+%% Identifiers, the possibility of explicitly setting an End-to-End
+%% Identifier would be needed to be able to implement an agent in
+%% which one side of the communication is not implemented on top of
+%% diameter. For example, Diameter being sent or received encapsulated
+%% in some other protocol, or even another Diameter stack in a
+%% non-Erlang environment. (Not that this is likely to be a normal
+%% case.)
+%%
+%% The implemented solution is not an option but to respect any header
+%% values set in a diameter_header record returned from a
+%% prepare_request callback. A call to diameter:call/4 can communicate
+%% values to the callback using the 'extra' option if so desired.
+
+%%% ---------------------------------------------------------------------------
+%%% # start(SvcName)
+%%% ---------------------------------------------------------------------------
+
+start(SvcName) ->
+ diameter_service_sup:start_child(SvcName).
+
+start_link(SvcName) ->
+ Options = [{spawn_opt, diameter_lib:spawn_opts(server, [])}],
+ gen_server:start_link(?MODULE, [SvcName], Options).
+%% Put the arbitrary term SvcName in a list in case we ever want to
+%% send more than this and need to distinguish old from new.
+
+%%% ---------------------------------------------------------------------------
+%%% # stop(SvcName)
+%%% ---------------------------------------------------------------------------
+
+stop(SvcName) ->
+ case whois(SvcName) of
+ undefined ->
+ {error, not_started};
+ Pid ->
+ stop(call_service(Pid, stop), Pid)
+ end.
+
+stop(ok, Pid) ->
+ MRef = erlang:monitor(process, Pid),
+ receive {'DOWN', MRef, process, _, _} -> ok end;
+stop(No, _) ->
+ No.
+
+%%% ---------------------------------------------------------------------------
+%%% # start_transport(SvcName, {Ref, Type, Opts})
+%%% ---------------------------------------------------------------------------
+
+start_transport(SvcName, {_,_,_} = T) ->
+ call_service_by_name(SvcName, {start, T}).
+
+%%% ---------------------------------------------------------------------------
+%%% # stop_transport(SvcName, Refs)
+%%% ---------------------------------------------------------------------------
+
+stop_transport(_, []) ->
+ ok;
+stop_transport(SvcName, [_|_] = Refs) ->
+ call_service_by_name(SvcName, {stop, Refs}).
+
+%%% ---------------------------------------------------------------------------
+%%% # info(SvcName, Item)
+%%% ---------------------------------------------------------------------------
+
+info(SvcName, Item) ->
+ info_rc(call_service_by_name(SvcName, {info, Item})).
+
+info_rc({error, _}) ->
+ undefined;
+info_rc(Info) ->
+ Info.
+
+%%% ---------------------------------------------------------------------------
+%%% # receive_message(TPid, Pkt, MessageData)
+%%% ---------------------------------------------------------------------------
+
+%% Handle an incoming message in the watchdog process. This used to
+%% come through the service process but this avoids that becoming a
+%% bottleneck.
+
+receive_message(TPid, Pkt, T)
+ when is_pid(TPid) ->
+ #diameter_packet{header = #diameter_header{is_request = R}} = Pkt,
+ recv(R, (not R) andalso lookup_request(Pkt, TPid), TPid, Pkt, T).
+
+%% Incoming request ...
+recv(true, false, TPid, Pkt, T) ->
+ try
+ spawn(fun() -> recv_request(TPid, Pkt, T) end)
+ catch
+ error: system_limit = E -> %% discard
+ ?LOG({error, E}, now())
+ end;
+
+%% ... answer to known request ...
+recv(false, #request{from = {_, Ref}, handler = Pid} = Req, _, Pkt, _) ->
+ Pid ! {answer, Ref, Req, Pkt};
+%% Note that failover could have happened prior to this message being
+%% received and triggering failback. That is, both a failover message
+%% and answer may be on their way to the handler process. In the worst
+%% case the request process gets notification of the failover and
+%% sends to the alternate peer before an answer arrives, so it's
+%% always the case that we can receive more than one answer after
+%% failover. The first answer received by the request process wins,
+%% any others are discarded.
+
+%% ... or not.
+recv(false, false, _, _, _) ->
+ ok.
+
+%%% ---------------------------------------------------------------------------
+%%% # call(SvcName, App, Msg, Options)
+%%% ---------------------------------------------------------------------------
+
+call(SvcName, App, Msg, Options)
+ when is_list(Options) ->
+ Rec = make_options(Options),
+ Ref = make_ref(),
+ Caller = {self(), Ref},
+ Fun = fun() -> exit({Ref, call(SvcName, App, Msg, Rec, Caller)}) end,
+ try spawn_monitor(Fun) of
+ {_, MRef} ->
+ recv(MRef, Ref, Rec#options.detach, false)
+ catch
+ error: system_limit = E ->
+ {error, E}
+ end.
+
+%% Don't rely on gen_server:call/3 for the timeout handling since it
+%% makes no guarantees about not leaving a reply message in the
+%% mailbox if we catch its exit at timeout. It currently *can* do so,
+%% which is also undocumented.
+
+recv(MRef, _, true, true) ->
+ erlang:demonitor(MRef, [flush]),
+ ok;
+
+recv(MRef, Ref, Detach, Sent) ->
+ receive
+ Ref -> %% send has been attempted
+ recv(MRef, Ref, Detach, true);
+ {'DOWN', MRef, process, _, Reason} ->
+ call_rc(Reason, Ref, Sent)
+ end.
+
+%% call/5 has returned ...
+call_rc({Ref, Ans}, Ref, _) ->
+ Ans;
+
+%% ... or not. In this case failure/encode are documented.
+call_rc(_, _, Sent) ->
+ {error, choose(Sent, failure, encode)}.
+
+%% call/5
+%%
+%% In the process spawned for the outgoing request.
+
+call(SvcName, App, Msg, Opts, Caller) ->
+ c(ets:lookup(?STATE_TABLE, SvcName), App, Msg, Opts, Caller).
+
+c([#state{service_name = SvcName} = S], App, Msg, Opts, Caller) ->
+ case find_transport(App, Msg, Opts, S) of
+ {_,_,_} = T ->
+ send_request(T, Msg, Opts, Caller, SvcName);
+ false ->
+ {error, no_connection};
+ {error, _} = No ->
+ No
+ end;
+
+c([], _, _, _, _) ->
+ {error, no_service}.
+
+%% make_options/1
+
+make_options(Options) ->
+ lists:foldl(fun mo/2, #options{}, Options).
+
+mo({timeout, T}, Rec)
+ when is_integer(T), 0 =< T ->
+ Rec#options{timeout = T};
+
+mo({filter, F}, #options{filter = none} = Rec) ->
+ Rec#options{filter = F};
+mo({filter, F}, #options{filter = {all, Fs}} = Rec) ->
+ Rec#options{filter = {all, [F | Fs]}};
+mo({filter, F}, #options{filter = F0} = Rec) ->
+ Rec#options{filter = {all, [F0, F]}};
+
+mo({extra, L}, #options{extra = X} = Rec)
+ when is_list(L) ->
+ Rec#options{extra = X ++ L};
+
+mo(detach, Rec) ->
+ Rec#options{detach = true};
+
+mo(T, _) ->
+ ?ERROR({invalid_option, T}).
+
+%%% ---------------------------------------------------------------------------
+%%% # subscribe(SvcName)
+%%% # unsubscribe(SvcName)
+%%% ---------------------------------------------------------------------------
+
+subscribe(SvcName) ->
+ diameter_reg:add({?MODULE, subscriber, SvcName}).
+
+unsubscribe(SvcName) ->
+ diameter_reg:del({?MODULE, subscriber, SvcName}).
+
+subscriptions(Pat) ->
+ pmap(diameter_reg:match({?MODULE, subscriber, Pat})).
+
+subscriptions() ->
+ subscriptions('_').
+
+pmap(Props) ->
+ lists:map(fun({{?MODULE, _, Name}, Pid}) -> {Name, Pid} end, Props).
+
+%%% ---------------------------------------------------------------------------
+%%% # services(Pattern)
+%%% ---------------------------------------------------------------------------
+
+services(Pat) ->
+ pmap(diameter_reg:match({?MODULE, service, Pat})).
+
+services() ->
+ services('_').
+
+whois(SvcName) ->
+ case diameter_reg:match({?MODULE, service, SvcName}) of
+ [{_, Pid}] ->
+ Pid;
+ [] ->
+ undefined
+ end.
+
+%%% ---------------------------------------------------------------------------
+%%% # flush_stats/1
+%%%
+%%% Output: list of {{SvcName, Alias, Counter}, Value}
+%%% ---------------------------------------------------------------------------
+
+flush_stats(TPid) ->
+ diameter_stats:flush(TPid).
+
+%% ===========================================================================
+%% ===========================================================================
+
+state(Svc) ->
+ call_service(Svc, state).
+
+uptime(Svc) ->
+ call_service(Svc, uptime).
+
+%% call_module/3
+
+call_module(Service, AppMod, Request) ->
+ call_service(Service, {call_module, AppMod, Request}).
+
+%%% ---------------------------------------------------------------------------
+%%% # init([SvcName])
+%%% ---------------------------------------------------------------------------
+
+init([SvcName]) ->
+ process_flag(trap_exit, true), %% ensure terminate(shutdown, _)
+ i(SvcName, diameter_reg:add_new({?MODULE, service, SvcName})).
+
+i(SvcName, true) ->
+ {ok, i(SvcName)};
+i(_, false) ->
+ {stop, {shutdown, already_started}}.
+
+%%% ---------------------------------------------------------------------------
+%%% # handle_call(Req, From, State)
+%%% ---------------------------------------------------------------------------
+
+handle_call(state, _, S) ->
+ {reply, S, S};
+
+handle_call(uptime, _, #state{id = T} = S) ->
+ {reply, diameter_lib:now_diff(T), S};
+
+%% Start a transport.
+handle_call({start, {Ref, Type, Opts}}, _From, S) ->
+ {reply, start(Ref, {Type, Opts}, S), S};
+
+%% Stop transports.
+handle_call({stop, Refs}, _From, S) ->
+ shutdown(Refs, S),
+ {reply, ok, S};
+
+%% pick_peer with mutable state
+handle_call({pick_peer, Local, Remote, App}, _From, S) ->
+ #diameter_app{mutable = true} = App, %% assert
+ {reply, pick_peer(Local, Remote, self(), S#state.service_name, App), S};
+
+handle_call({call_module, AppMod, Req}, From, S) ->
+ call_module(AppMod, Req, From, S);
+
+handle_call({info, Item}, _From, S) ->
+ {reply, service_info(Item, S), S};
+
+handle_call(stop, _From, S) ->
+ shutdown(S),
+ {stop, normal, ok, S};
+%% The server currently isn't guaranteed to be dead when the caller
+%% gets the reply. We deal with this in the call to the server,
+%% stating a monitor that waits for DOWN before returning.
+
+handle_call(Req, From, S) ->
+ unexpected(handle_call, [Req, From], S),
+ {reply, nok, S}.
+
+%%% ---------------------------------------------------------------------------
+%%% # handle_cast(Req, State)
+%%% ---------------------------------------------------------------------------
+
+handle_cast(Req, S) ->
+ unexpected(handle_cast, [Req], S),
+ {noreply, S}.
+
+%%% ---------------------------------------------------------------------------
+%%% # handle_info(Req, State)
+%%% ---------------------------------------------------------------------------
+
+handle_info(T,S) ->
+ case transition(T,S) of
+ ok ->
+ {noreply, S};
+ #state{} = NS ->
+ {noreply, NS};
+ {stop, Reason} ->
+ {stop, {shutdown, Reason}, S}
+ end.
+
+%% transition/2
+
+%% Peer process is telling us to start a new accept process.
+transition({accepted, Pid, TPid}, S) ->
+ accepted(Pid, TPid, S),
+ ok;
+
+%% Peer process has a new open connection.
+transition({connection_up, Pid, T}, S) ->
+ connection_up(Pid, T, S);
+
+%% Peer process has left state open.
+transition({connection_down, Pid}, S) ->
+ connection_down(Pid, S);
+
+%% Peer process has returned to state open.
+transition({connection_up, Pid}, S) ->
+ connection_up(Pid, S);
+
+%% Accepting transport has lost connectivity.
+transition({close, Pid}, S) ->
+ close(Pid, S),
+ ok;
+
+%% Connecting transport is being restarted by watchdog.
+transition({reconnect, Pid}, S) ->
+ reconnect(Pid, S),
+ ok;
+
+%% Monitor process has died. Just die with a reason that tells
+%% diameter_config about the happening. If a cleaner shutdown is
+%% required then someone should stop us.
+transition({'DOWN', MRef, process, _, Reason}, #state{monitor = MRef}) ->
+ {stop, {monitor, Reason}};
+
+%% Local peer process has died.
+transition({'DOWN', _, process, Pid, Reason}, S)
+ when node(Pid) == node() ->
+ peer_down(Pid, Reason, S);
+
+%% Remote service wants to know about shared transports.
+transition({service, Pid}, S) ->
+ share_peers(Pid, S),
+ ok;
+
+%% Remote service is communicating a shared peer.
+transition({peer, TPid, Aliases, Caps}, S) ->
+ remote_peer_up(TPid, Aliases, Caps, S);
+
+%% Remote peer process has died.
+transition({'DOWN', _, process, TPid, _}, S) ->
+ remote_peer_down(TPid, S);
+
+%% Restart after tc expiry.
+transition({tc_timeout, T}, S) ->
+ tc_timeout(T, S),
+ ok;
+
+%% Request process is telling us it may have missed a failover message
+%% after a transport went down and the service process looked up
+%% outstanding requests.
+transition({failover, TRef, Seqs}, S) ->
+ failover(TRef, Seqs, S),
+ ok;
+
+transition(Req, S) ->
+ unexpected(handle_info, [Req], S),
+ ok.
+
+%%% ---------------------------------------------------------------------------
+%%% # terminate(Reason, State)
+%%% ---------------------------------------------------------------------------
+
+terminate(Reason, #state{service_name = Name} = S) ->
+ ets:delete(?STATE_TABLE, Name),
+ shutdown == Reason %% application shutdown
+ andalso shutdown(S).
+
+%%% ---------------------------------------------------------------------------
+%%% # code_change(FromVsn, State, Extra)
+%%% ---------------------------------------------------------------------------
+
+code_change(FromVsn,
+ #state{service_name = SvcName,
+ service = #diameter_service{applications = Apps}}
+ = S,
+ Extra) ->
+ lists:foreach(fun(A) ->
+ code_change(FromVsn, SvcName, Extra, A)
+ end,
+ Apps),
+ {ok, S}.
+
+code_change(FromVsn, SvcName, Extra, #diameter_app{alias = Alias} = A) ->
+ {ok, S} = cb(A, code_change, [FromVsn,
+ mod_state(Alias),
+ Extra,
+ SvcName]),
+ mod_state(Alias, S).
+
+%% ===========================================================================
+%% ===========================================================================
+
+unexpected(F, A, #state{service_name = Name}) ->
+ ?UNEXPECTED(F, A ++ [Name]).
+
+cb([_|_] = M, F, A) ->
+ eval(M, F, A);
+cb(Rec, F, A) ->
+ {_, M} = app(Rec),
+ eval(M, F, A).
+
+app(#request{app = A, module = M}) ->
+ {A,M};
+app(#diameter_app{alias = A, module = M}) ->
+ {A,M}.
+
+eval([M|X], F, A) ->
+ apply(M, F, A ++ X).
+
+%% Callback with state.
+
+state_cb(#diameter_app{mutable = false, init_state = S}, {ModX, F, A}) ->
+ eval(ModX, F, A ++ [S]);
+
+state_cb(#diameter_app{mutable = true, alias = Alias}, {_,_,_} = MFA) ->
+ state_cb(MFA, Alias);
+
+state_cb({ModX,F,A}, Alias)
+ when is_list(ModX) ->
+ eval(ModX, F, A ++ [mod_state(Alias)]).
+
+choose(true, X, _) -> X;
+choose(false, _, X) -> X.
+
+ets_new(Tbl) ->
+ ets:new(Tbl, [{keypos, 2}]).
+
+insert(Tbl, Rec) ->
+ ets:insert(Tbl, Rec),
+ Rec.
+
+monitor(Pid) ->
+ erlang:monitor(process, Pid),
+ Pid.
+
+%% Using the process dictionary for the callback state was initially
+%% just a way to make what was horrendous trace (big state record and
+%% much else everywhere) somewhat more readable. There's not as much
+%% need for it now but it's no worse (except possibly that we don't
+%% see the table identifier being passed around) than an ets table so
+%% keep it.
+
+mod_state(Alias) ->
+ get({?MODULE, mod_state, Alias}).
+
+mod_state(Alias, ModS) ->
+ put({?MODULE, mod_state, Alias}, ModS).
+
+%% have_transport/2
+
+have_transport(SvcName, Ref) ->
+ [] /= diameter_config:have_transport(SvcName, Ref).
+
+%%% ---------------------------------------------------------------------------
+%%% # shutdown/2
+%%% ---------------------------------------------------------------------------
+
+shutdown(Refs, #state{peerT = PeerT}) ->
+ ets:foldl(fun(P,ok) -> s(P, Refs), ok end, ok, PeerT).
+
+s(#peer{ref = Ref, pid = Pid}, Refs) ->
+ s(lists:member(Ref, Refs), Pid);
+
+s(true, Pid) ->
+ Pid ! {shutdown, self()}; %% 'DOWN' will cleanup as usual
+s(false, _) ->
+ ok.
+
+%%% ---------------------------------------------------------------------------
+%%% # shutdown/1
+%%% ---------------------------------------------------------------------------
+
+shutdown(#state{peerT = PeerT}) ->
+ %% A transport might not be alive to receive the shutdown request
+ %% but give those that are a chance to shutdown gracefully.
+ wait(fun st/2, PeerT),
+ %% Kill the watchdogs explicitly in case there was no transport.
+ wait(fun sw/2, PeerT).
+
+wait(Fun, T) ->
+ diameter_lib:wait(ets:foldl(Fun, [], T)).
+
+st(#peer{conn = B}, Acc)
+ when is_boolean(B) ->
+ Acc;
+st(#peer{conn = Pid}, Acc) ->
+ Pid ! shutdown,
+ [Pid | Acc].
+
+sw(#peer{pid = Pid}, Acc) ->
+ exit(Pid, shutdown),
+ [Pid | Acc].
+
+%%% ---------------------------------------------------------------------------
+%%% # call_service/2
+%%% ---------------------------------------------------------------------------
+
+call_service(Pid, Req)
+ when is_pid(Pid) ->
+ cs(Pid, Req);
+call_service(SvcName, Req) ->
+ call_service_by_name(SvcName, Req).
+
+call_service_by_name(SvcName, Req) ->
+ cs(whois(SvcName), Req).
+
+cs(Pid, Req)
+ when is_pid(Pid) ->
+ try
+ gen_server:call(Pid, Req, infinity)
+ catch
+ E: Reason when E == exit ->
+ {error, {E, Reason}}
+ end;
+
+cs(undefined, _) ->
+ {error, no_service}.
+
+%%% ---------------------------------------------------------------------------
+%%% # i/1
+%%%
+%%% Output: #state{}
+%%% ---------------------------------------------------------------------------
+
+%% Intialize the state of a service gen_server.
+
+i(SvcName) ->
+ %% Split the config into a server state and a list of transports.
+ {#state{} = S, CL} = lists:foldl(fun cfg_acc/2,
+ {false, []},
+ diameter_config:lookup(SvcName)),
+
+ %% Publish the state in order to be able to access it outside of
+ %% the service process. Originally table identifiers were only
+ %% known to the service process but we now want to provide the
+ %% option of application callbacks being 'stateless' in order to
+ %% avoid having to go through a common process. (Eg. An agent that
+ %% sends a request for every incoming request.)
+ true = ets:insert_new(?STATE_TABLE, S),
+
+ %% Start fsms for each transport.
+ lists:foreach(fun(T) -> start_fsm(T,S) end, CL),
+
+ init_shared(S),
+ S.
+
+cfg_acc({SvcName, #diameter_service{applications = Apps} = Rec, Opts},
+ {false, Acc}) ->
+ lists:foreach(fun init_mod/1, Apps),
+ S = #state{service_name = SvcName,
+ service = Rec#diameter_service{pid = self()},
+ share_peers = get_value(share_peers, Opts),
+ use_shared_peers = get_value(use_shared_peers, Opts),
+ monitor = mref(get_value(monitor, Opts))},
+ {S, Acc};
+
+cfg_acc({_Ref, Type, _Opts} = T, {S, Acc})
+ when Type == connect;
+ Type == listen ->
+ {S, [T | Acc]}.
+
+mref(false = No) ->
+ No;
+mref(P) ->
+ erlang:monitor(process, P).
+
+init_shared(#state{use_shared_peers = true,
+ service_name = Svc}) ->
+ diameter_peer:notify(Svc, {service, self()});
+init_shared(#state{use_shared_peers = false}) ->
+ ok.
+
+init_mod(#diameter_app{alias = Alias,
+ init_state = S}) ->
+ mod_state(Alias, S).
+
+start_fsm({Ref, Type, Opts}, S) ->
+ start(Ref, {Type, Opts}, S).
+
+get_value(Key, Vs) ->
+ {_, V} = lists:keyfind(Key, 1, Vs),
+ V.
+
+%%% ---------------------------------------------------------------------------
+%%% # start/3
+%%% ---------------------------------------------------------------------------
+
+%% If the initial start/3 at service/transport start succeeds then
+%% subsequent calls to start/4 on the same service will also succeed
+%% since they involve the same call to merge_service/2. We merge here
+%% rather than earlier since the service may not yet be configured
+%% when the transport is configured.
+
+start(Ref, {T, Opts}, S)
+ when T == connect;
+ T == listen ->
+ try
+ {ok, start(Ref, type(T), Opts, S)}
+ catch
+ ?FAILURE(Reason) ->
+ {error, Reason}
+ end.
+%% TODO: don't actually raise any errors yet
+
+%% There used to be a difference here between the handling of
+%% configured listening and connecting transports but now we simply
+%% tell the transport_module to start an accepting or connecting
+%% process respectively, the transport implementation initiating
+%% listening on a port as required.
+type(listen) -> accept;
+type(accept) -> listen;
+type(connect = T) -> T.
+
+%% start/4
+
+start(Ref, Type, Opts, #state{peerT = PeerT,
+ connT = ConnT,
+ service_name = SvcName,
+ service = Svc})
+ when Type == connect;
+ Type == accept ->
+ Pid = monitor(s(Type, Ref, {ConnT,
+ Opts,
+ SvcName,
+ merge_service(Opts, Svc)})),
+ insert(PeerT, #peer{pid = Pid,
+ type = Type,
+ ref = Ref,
+ options = Opts}),
+ Pid.
+
+%% Note that the service record passed into the watchdog is the merged
+%% record so that each watchdog (and peer_fsm) may get a different
+%% record. This record is what is passed back into application
+%% callbacks.
+
+s(Type, Ref, T) ->
+ diameter_watchdog:start({Type, Ref}, T).
+
+%% merge_service/2
+
+merge_service(Opts, Svc) ->
+ lists:foldl(fun ms/2, Svc, Opts).
+
+%% Limit the applications known to the fsm to those in the 'apps'
+%% option. That this might be empty is checked by the fsm. It's not
+%% checked at config-time since there's no requirement that the
+%% service be configured first. (Which could be considered a bit odd.)
+ms({applications, As}, #diameter_service{applications = Apps} = S)
+ when is_list(As) ->
+ S#diameter_service{applications
+ = [A || A <- Apps,
+ lists:member(A#diameter_app.alias, As)]};
+
+%% The fact that all capabilities can be configured on the transports
+%% means that the service doesn't necessarily represent a single
+%% locally implemented Diameter peer as identified by Origin-Host: a
+%% transport can configure its own Origin-Host. This means that the
+%% service little more than a placeholder for default capabilities
+%% plus a list of applications that individual transports can choose
+%% to support (or not).
+ms({capabilities, Opts}, #diameter_service{capabilities = Caps0} = Svc)
+ when is_list(Opts) ->
+ %% make_caps has already succeeded in diameter_config so it will succeed
+ %% again here.
+ {ok, Caps} = diameter_capx:make_caps(Caps0, Opts),
+ Svc#diameter_service{capabilities = Caps};
+
+ms(_, Svc) ->
+ Svc.
+
+%%% ---------------------------------------------------------------------------
+%%% # accepted/3
+%%% ---------------------------------------------------------------------------
+
+accepted(Pid, _TPid, #state{peerT = PeerT} = S) ->
+ #peer{ref = Ref, type = accept = T, conn = false, options = Opts}
+ = P
+ = fetch(PeerT, Pid),
+ insert(PeerT, P#peer{conn = true}), %% mark replacement transport started
+ start(Ref, T, Opts, S). %% start new peer
+
+fetch(Tid, Key) ->
+ [T] = ets:lookup(Tid, Key),
+ T.
+
+%%% ---------------------------------------------------------------------------
+%%% # connection_up/3
+%%%
+%%% Output: #state{}
+%%% ---------------------------------------------------------------------------
+
+%% Peer process has reached the open state.
+
+connection_up(Pid, {TPid, {Caps, SApps, Pkt}}, #state{peerT = PeerT,
+ connT = ConnT}
+ = S) ->
+ P = fetch(PeerT, Pid),
+ C = #conn{pid = TPid,
+ apps = SApps,
+ caps = Caps,
+ peer = Pid},
+
+ insert(ConnT, C),
+ connection_up([Pkt], P#peer{conn = TPid}, C, S).
+
+%%% ---------------------------------------------------------------------------
+%%% # connection_up/2
+%%%
+%%% Output: #state{}
+%%% ---------------------------------------------------------------------------
+
+%% Peer process has transitioned back into the open state. Note that there
+%% has been no new capabilties exchange in this case.
+
+connection_up(Pid, #state{peerT = PeerT,
+ connT = ConnT}
+ = S) ->
+ #peer{conn = TPid} = P = fetch(PeerT, Pid),
+ C = fetch(ConnT, TPid),
+ connection_up([], P, C, S).
+
+%% connection_up/4
+
+connection_up(T, P, C, #state{peerT = PeerT,
+ local_peers = LDict,
+ service_name = SvcName,
+ service
+ = #diameter_service{applications = Apps}}
+ = S) ->
+ #peer{conn = TPid, op_state = ?STATE_DOWN}
+ = P,
+ #conn{apps = SApps, caps = Caps}
+ = C,
+
+ insert(PeerT, P#peer{op_state = ?STATE_UP}),
+
+ request_peer_up(TPid),
+ report_status(up, P, C, S, T),
+ S#state{local_peers = insert_local_peer(SApps,
+ {{TPid, Caps}, {SvcName, Apps}},
+ LDict)}.
+
+insert_local_peer(SApps, T, LDict) ->
+ lists:foldl(fun(A,D) -> ilp(A, T, D) end, LDict, SApps).
+
+ilp({Id, Alias}, {TC, SA}, LDict) ->
+ init_conn(Id, Alias, TC, SA),
+ ?Dict:append(Alias, TC, LDict).
+
+init_conn(Id, Alias, TC, {SvcName, Apps}) ->
+ #diameter_app{module = ModX,
+ id = Id} %% assert
+ = find_app(Alias, Apps),
+
+ peer_cb({ModX, peer_up, [SvcName, TC]}, Alias).
+
+find_app(Alias, Apps) ->
+ lists:keyfind(Alias, #diameter_app.alias, Apps).
+
+%% A failing peer callback brings down the service. In the case of
+%% peer_up we could just kill the transport and emit an error but for
+%% peer_down we have no way to cleanup any state change that peer_up
+%% may have introduced.
+peer_cb(MFA, Alias) ->
+ try state_cb(MFA, Alias) of
+ ModS ->
+ mod_state(Alias, ModS)
+ catch
+ E: Reason ->
+ ?ERROR({E, Reason, MFA, ?STACK})
+ end.
+
+%%% ---------------------------------------------------------------------------
+%%% # connection_down/2
+%%%
+%%% Output: #state{}
+%%% ---------------------------------------------------------------------------
+
+%% Peer process has transitioned out of the open state.
+
+connection_down(Pid, #state{peerT = PeerT,
+ connT = ConnT}
+ = S) ->
+ #peer{conn = TPid}
+ = P
+ = fetch(PeerT, Pid),
+
+ C = fetch(ConnT, TPid),
+ insert(PeerT, P#peer{op_state = ?STATE_DOWN}),
+ connection_down(P,C,S).
+
+%% connection_down/3
+
+connection_down(#peer{conn = TPid,
+ op_state = ?STATE_UP}
+ = P,
+ #conn{caps = Caps,
+ apps = SApps}
+ = C,
+ #state{service_name = SvcName,
+ service = #diameter_service{applications = Apps},
+ local_peers = LDict}
+ = S) ->
+ report_status(down, P, C, S, []),
+ NewS = S#state{local_peers
+ = remove_local_peer(SApps,
+ {{TPid, Caps}, {SvcName, Apps}},
+ LDict)},
+ request_peer_down(TPid, NewS),
+ NewS.
+
+remove_local_peer(SApps, T, LDict) ->
+ lists:foldl(fun(A,D) -> rlp(A, T, D) end, LDict, SApps).
+
+rlp({Id, Alias}, {TC, SA}, LDict) ->
+ L = ?Dict:fetch(Alias, LDict),
+ down_conn(Id, Alias, TC, SA),
+ ?Dict:store(Alias, lists:delete(TC, L), LDict).
+
+down_conn(Id, Alias, TC, {SvcName, Apps}) ->
+ #diameter_app{module = ModX,
+ id = Id} %% assert
+ = find_app(Alias, Apps),
+
+ peer_cb({ModX, peer_down, [SvcName, TC]}, Alias).
+
+%%% ---------------------------------------------------------------------------
+%%% # peer_down/3
+%%%
+%%% Output: #state{}
+%%% ---------------------------------------------------------------------------
+
+%% Peer process has died.
+
+peer_down(Pid, _Reason, #state{peerT = PeerT} = S) ->
+ P = fetch(PeerT, Pid),
+ ets:delete_object(PeerT, P),
+ restart(P,S),
+ peer_down(P,S).
+
+%% peer_down/2
+
+%% The peer has never come up ...
+peer_down(#peer{conn = B}, S)
+ when is_boolean(B) ->
+ S;
+
+%% ... or it has.
+peer_down(#peer{ref = Ref,
+ conn = TPid,
+ type = Type,
+ options = Opts}
+ = P,
+ #state{service_name = SvcName,
+ connT = ConnT}
+ = S) ->
+ #conn{caps = Caps}
+ = C
+ = fetch(ConnT, TPid),
+ ets:delete_object(ConnT, C),
+ try
+ pd(P,C,S)
+ after
+ send_event(SvcName, {closed, Ref, {TPid, Caps}, {type(Type), Opts}})
+ end.
+
+pd(#peer{op_state = ?STATE_DOWN}, _, S) ->
+ S;
+pd(#peer{op_state = ?STATE_UP} = P, C, S) ->
+ connection_down(P,C,S).
+
+%% restart/2
+
+restart(P,S) ->
+ q_restart(restart(P), S).
+
+%% restart/1
+
+%% Always try to reconnect.
+restart(#peer{ref = Ref,
+ type = connect = T,
+ options = Opts,
+ started = Time}) ->
+ {Time, {Ref, T, Opts}};
+
+%% Transport connection hasn't yet been accepted ...
+restart(#peer{ref = Ref,
+ type = accept = T,
+ options = Opts,
+ conn = false,
+ started = Time}) ->
+ {Time, {Ref, T, Opts}};
+
+%% ... or it has: a replacement transport has already been spawned.
+restart(#peer{type = accept}) ->
+ false.
+
+%% q_restart/2
+
+%% Start the reconnect timer.
+q_restart({Time, {_Ref, Type, Opts} = T}, S) ->
+ start_tc(tc(Time, default_tc(Type, Opts)), T, S);
+q_restart(false, _) ->
+ ok.
+
+%% RFC 3588, 2.1:
+%%
+%% When no transport connection exists with a peer, an attempt to
+%% connect SHOULD be periodically made. This behavior is handled via
+%% the Tc timer, whose recommended value is 30 seconds. There are
+%% certain exceptions to this rule, such as when a peer has terminated
+%% the transport connection stating that it does not wish to
+%% communicate.
+
+default_tc(connect, Opts) ->
+ proplists:get_value(reconnect_timer, Opts, ?DEFAULT_TC);
+default_tc(accept, _) ->
+ 0.
+
+%% Bound tc below if the peer was restarted recently to avoid
+%% continuous in case of faulty config or other problems.
+tc(Time, Tc) ->
+ choose(Tc > ?RESTART_TC
+ orelse timer:now_diff(now(), Time) > 1000*?RESTART_TC,
+ Tc,
+ ?RESTART_TC).
+
+start_tc(0, T, S) ->
+ tc_timeout(T, S);
+start_tc(Tc, T, _) ->
+ erlang:send_after(Tc, self(), {tc_timeout, T}).
+
+%% tc_timeout/2
+
+tc_timeout({Ref, _Type, _Opts} = T, #state{service_name = SvcName} = S) ->
+ tc(have_transport(SvcName, Ref), T, S).
+
+tc(true, {Ref, Type, Opts}, #state{service_name = SvcName}
+ = S) ->
+ send_event(SvcName, {reconnect, Ref, Opts}),
+ start(Ref, Type, Opts, S);
+tc(false = No, _, _) -> %% removed
+ No.
+
+%%% ---------------------------------------------------------------------------
+%%% # close/2
+%%% ---------------------------------------------------------------------------
+
+%% The watchdog doesn't start a new fsm in the accept case, it
+%% simply stays alive until someone tells it to die in order for
+%% another watchdog to be able to detect that it should transition
+%% from initial into reopen rather than okay. That someone is either
+%% the accepting watchdog upon reception of a CER from the previously
+%% connected peer, or us after reconnect_timer timeout.
+
+close(Pid, #state{service_name = SvcName,
+ peerT = PeerT}) ->
+ #peer{pid = Pid,
+ type = accept,
+ ref = Ref,
+ options = Opts}
+ = fetch(PeerT, Pid),
+
+ c(Pid, have_transport(SvcName, Ref), Opts).
+
+%% Tell watchdog to (maybe) die later ...
+c(Pid, true, Opts) ->
+ Tc = proplists:get_value(reconnect_timer, Opts, 2*?DEFAULT_TC),
+ erlang:send_after(Tc, Pid, close);
+
+%% ... or now.
+c(Pid, false, _Opts) ->
+ Pid ! close.
+
+%% The RFC's only document the behaviour of Tc, our reconnect_timer,
+%% for the establishment of connections but we also give
+%% reconnect_timer semantics for a listener, being the time within
+%% which a new connection attempt is expected of a connecting peer.
+%% The value should be greater than the peer's Tc + jitter.
+
+%%% ---------------------------------------------------------------------------
+%%% # reconnect/2
+%%% ---------------------------------------------------------------------------
+
+reconnect(Pid, #state{service_name = SvcName,
+ peerT = PeerT}) ->
+ #peer{ref = Ref,
+ type = connect,
+ options = Opts}
+ = fetch(PeerT, Pid),
+ send_event(SvcName, {reconnect, Ref, Opts}).
+
+%%% ---------------------------------------------------------------------------
+%%% # call_module/4
+%%% ---------------------------------------------------------------------------
+
+%% Backwards compatibility and never documented/advertised. May be
+%% removed.
+
+call_module(Mod, Req, From, #state{service
+ = #diameter_service{applications = Apps},
+ service_name = Svc}
+ = S) ->
+ case cm([A || A <- Apps, Mod == hd(A#diameter_app.module)],
+ Req,
+ From,
+ Svc)
+ of
+ {reply = T, RC} ->
+ {T, RC, S};
+ noreply = T ->
+ {T, S};
+ Reason ->
+ {reply, {error, Reason}, S}
+ end.
+
+cm([#diameter_app{module = ModX, alias = Alias}], Req, From, Svc) ->
+ MFA = {ModX, handle_call, [Req, From, Svc]},
+
+ try state_cb(MFA, Alias) of
+ {noreply = T, ModS} ->
+ mod_state(Alias, ModS),
+ T;
+ {reply = T, RC, ModS} ->
+ mod_state(Alias, ModS),
+ {T, RC};
+ T ->
+ diameter_lib:error_report({invalid, T}, MFA),
+ invalid
+ catch
+ E: Reason ->
+ diameter_lib:error_report({failure, {E, Reason, ?STACK}}, MFA),
+ failure
+ end;
+
+cm([], _, _, _) ->
+ unknown;
+
+cm([_,_|_], _, _, _) ->
+ multiple.
+
+%%% ---------------------------------------------------------------------------
+%%% # send_request/5
+%%% ---------------------------------------------------------------------------
+
+%% Send an outgoing request in its dedicated process.
+%%
+%% Note that both encode of the outgoing request and of the received
+%% answer happens in this process. It's also this process that replies
+%% to the caller. The service process only handles the state-retaining
+%% callbacks.
+%%
+%% The mod field of the #diameter_app{} here includes any extra
+%% arguments passed to diameter:call/2.
+
+send_request({TPid, Caps, App}, Msg, Opts, Caller, SvcName) ->
+ #diameter_app{module = ModX}
+ = App,
+
+ Pkt = make_packet(Msg),
+
+ case cb(ModX, prepare_request, [Pkt, SvcName, {TPid, Caps}]) of
+ {send, P} ->
+ send_request(make_packet(P, Pkt),
+ TPid,
+ Caps,
+ App,
+ Opts,
+ Caller,
+ SvcName);
+ {discard, Reason} ->
+ {error, Reason};
+ discard ->
+ {error, discarded};
+ T ->
+ ?ERROR({invalid_return, prepare_request, App, T})
+ end.
+
+%% make_packet/1
+%%
+%% Turn an outgoing request as passed to call/4 into a diameter_packet
+%% record in preparation for a prepare_request callback.
+
+make_packet(Bin)
+ when is_binary(Bin) ->
+ #diameter_packet{header = diameter_codec:decode_header(Bin),
+ bin = Bin};
+
+make_packet(#diameter_packet{msg = [#diameter_header{} = Hdr | Avps]} = Pkt) ->
+ Pkt#diameter_packet{msg = [make_header(Hdr) | Avps]};
+
+make_packet(#diameter_packet{header = Hdr} = Pkt) ->
+ Pkt#diameter_packet{header = make_header(Hdr)};
+
+make_packet(Msg) ->
+ make_packet(#diameter_packet{msg = Msg}).
+
+%% make_header/1
+
+make_header(undefined) ->
+ Seq = diameter_session:sequence(),
+ make_header(#diameter_header{end_to_end_id = Seq,
+ hop_by_hop_id = Seq});
+
+make_header(#diameter_header{version = undefined} = Hdr) ->
+ make_header(Hdr#diameter_header{version = ?DIAMETER_VERSION});
+
+make_header(#diameter_header{end_to_end_id = undefined} = H) ->
+ Seq = diameter_session:sequence(),
+ make_header(H#diameter_header{end_to_end_id = Seq});
+
+make_header(#diameter_header{hop_by_hop_id = undefined} = H) ->
+ Seq = diameter_session:sequence(),
+ make_header(H#diameter_header{hop_by_hop_id = Seq});
+
+make_header(#diameter_header{} = Hdr) ->
+ Hdr;
+
+make_header(T) ->
+ ?ERROR({invalid_header, T}).
+
+%% make_packet/2
+%%
+%% Reconstruct a diameter_packet from the return value of
+%% prepare_request or prepare_retransmit callback.
+
+make_packet(Bin, _)
+ when is_binary(Bin) ->
+ make_packet(Bin);
+
+make_packet(#diameter_packet{msg = [#diameter_header{} | _]} = Pkt, _) ->
+ Pkt;
+
+%% Returning a diameter_packet with no header from a prepare_request
+%% or prepare_retransmit callback retains the header passed into it.
+%% This is primarily so that the end to end and hop by hop identifiers
+%% are retained.
+make_packet(#diameter_packet{header = Hdr} = Pkt,
+ #diameter_packet{header = Hdr0}) ->
+ Pkt#diameter_packet{header = fold_record(Hdr0, Hdr)};
+
+make_packet(Msg, Pkt) ->
+ Pkt#diameter_packet{msg = Msg}.
+
+%% fold_record/2
+
+fold_record(undefined, R) ->
+ R;
+fold_record(Rec, R) ->
+ diameter_lib:fold_tuple(2, Rec, R).
+
+%% send_request/7
+
+send_request(Pkt, TPid, Caps, App, Opts, Caller, SvcName) ->
+ #diameter_app{alias = Alias,
+ dictionary = Dict,
+ module = ModX,
+ answer_errors = AE}
+ = App,
+
+ EPkt = encode(Dict, Pkt),
+
+ #options{filter = Filter,
+ timeout = Timeout}
+ = Opts,
+
+ Req = #request{packet = Pkt,
+ from = Caller,
+ handler = self(),
+ transport = TPid,
+ caps = Caps,
+ app = Alias,
+ filter = Filter,
+ dictionary = Dict,
+ module = ModX},
+
+ try
+ TRef = send_request(TPid, EPkt, Req, Timeout),
+ ack(Caller),
+ handle_answer(SvcName, AE, recv_answer(Timeout, SvcName, {TRef, Req}))
+ after
+ erase_request(EPkt)
+ end.
+
+%% Tell caller a send has been attempted.
+ack({Pid, Ref}) ->
+ Pid ! Ref.
+
+%% recv_answer/3
+
+recv_answer(Timeout,
+ SvcName,
+ {TRef, #request{from = {_, Ref}, packet = RPkt} = Req}
+ = T) ->
+
+ %% Matching on TRef below ensures we ignore messages that pertain
+ %% to a previous transport prior to failover. The answer message
+ %% includes the #request{} since it's not necessarily Req; that
+ %% is, from the last peer to which we've transmitted.
+
+ receive
+ {answer = A, Ref, Rq, Pkt} -> %% Answer from peer
+ {A, Rq, Pkt};
+ {timeout = Reason, TRef, _} -> %% No timely reply
+ {error, Req, Reason};
+ {failover = Reason, TRef, false} -> %% No alternate peer
+ {error, Req, Reason};
+ {failover, TRef, Transport} -> %% Resend to alternate peer
+ try_retransmit(Timeout, SvcName, Req, Transport);
+ {failover, TRef} -> %% May have missed failover notification
+ Seqs = diameter_codec:sequence_numbers(RPkt),
+ Pid = whois(SvcName),
+ is_pid(Pid) andalso (Pid ! {failover, TRef, Seqs}),
+ recv_answer(Timeout, SvcName, T)
+ end.
+%% Note that failover starts a new timer and that expiry of an old
+%% timer value is ignored. This means that an answer could be accepted
+%% from a peer after timeout in the case of failover.
+
+try_retransmit(Timeout, SvcName, Req, Transport) ->
+ try retransmit(Transport, Req, SvcName, Timeout) of
+ T -> recv_answer(Timeout, SvcName, T)
+ catch
+ ?FAILURE(Reason) -> {error, Req, Reason}
+ end.
+
+%% handle_error/3
+
+handle_error(Req, Reason, SvcName) ->
+ #request{module = ModX,
+ packet = Pkt,
+ transport = TPid,
+ caps = Caps}
+ = Req,
+ cb(ModX, handle_error, [Reason, msg(Pkt), SvcName, {TPid, Caps}]).
+
+msg(#diameter_packet{msg = undefined, bin = Bin}) ->
+ Bin;
+msg(#diameter_packet{msg = Msg}) ->
+ Msg.
+
+%% encode/2
+
+%% Note that prepare_request can return a diameter_packet containing
+%% header or transport_data. Even allow the returned record to contain
+%% an encoded binary. This isn't the usual case but could some in
+%% handy, for test at least. (For example, to send garbage.)
+
+%% The normal case: encode the returned message.
+encode(Dict, #diameter_packet{msg = Msg, bin = undefined} = Pkt) ->
+ D = pick_dictionary([Dict, ?BASE], Msg),
+ diameter_codec:encode(D, Pkt);
+
+%% Callback has returned an encoded binary: just send.
+encode(_, #diameter_packet{} = Pkt) ->
+ Pkt.
+
+%% pick_dictionary/2
+
+%% Pick the first dictionary that declares the application id in the
+%% specified header.
+pick_dictionary(Ds, [#diameter_header{application_id = Id} | _]) ->
+ pd(Ds, fun(D) -> Id = D:id() end);
+
+%% Pick the first dictionary that knows the specified message name.
+pick_dictionary(Ds, [MsgName|_]) ->
+ pd(Ds, fun(D) -> D:msg2rec(MsgName) end);
+
+%% Pick the first dictionary that knows the name of the specified
+%% message record.
+pick_dictionary(Ds, Rec) ->
+ Name = element(1, Rec),
+ pd(Ds, fun(D) -> D:rec2msg(Name) end).
+
+pd([D|Ds], F) ->
+ try
+ F(D),
+ D
+ catch
+ error:_ ->
+ pd(Ds, F)
+ end;
+
+pd([], _) ->
+ ?ERROR(no_dictionary).
+
+%% send_request/4
+
+send_request(TPid, #diameter_packet{bin = Bin} = Pkt, Req, Timeout)
+ when node() == node(TPid) ->
+ %% Store the outgoing request before sending to avoid a race with
+ %% reply reception.
+ TRef = store_request(TPid, Bin, Req, Timeout),
+ send(TPid, Pkt),
+ TRef;
+
+%% Send using a remote transport: spawn a process on the remote node
+%% to relay the answer.
+send_request(TPid, #diameter_packet{} = Pkt, Req, Timeout) ->
+ TRef = erlang:start_timer(Timeout, self(), timeout),
+ T = {TPid, Pkt, Req, Timeout, TRef},
+ spawn(node(TPid), ?MODULE, send, [T]),
+ TRef.
+
+%% send/1
+
+send({TPid, Pkt, #request{handler = Pid} = Req, Timeout, TRef}) ->
+ Ref = send_request(TPid, Pkt, Req#request{handler = self()}, Timeout),
+ Pid ! reref(receive T -> T end, Ref, TRef).
+
+reref({T, Ref, R}, Ref, TRef) ->
+ {T, TRef, R};
+reref(T, _, _) ->
+ T.
+
+%% send/2
+
+send(Pid, Pkt) ->
+ Pid ! {send, Pkt}.
+
+%% retransmit/4
+
+retransmit({TPid, Caps, #diameter_app{alias = Alias} = App},
+ #request{app = Alias,
+ packet = Pkt}
+ = Req,
+ SvcName,
+ Timeout) ->
+ have_request(Pkt, TPid) %% Don't failover to a peer we've
+ andalso ?THROW(timeout), %% already sent to.
+
+ case cb(App, prepare_retransmit, [Pkt, SvcName, {TPid, Caps}]) of
+ {send, P} ->
+ retransmit(make_packet(P, Pkt), TPid, Caps, Req, Timeout);
+ {discard, Reason} ->
+ ?THROW(Reason);
+ discard ->
+ ?THROW(discarded);
+ T ->
+ ?ERROR({invalid_return, prepare_retransmit, App, T})
+ end.
+
+%% retransmit/5
+
+retransmit(Pkt, TPid, Caps, #request{dictionary = Dict} = Req, Timeout) ->
+ EPkt = encode(Dict, Pkt),
+
+ NewReq = Req#request{transport = TPid,
+ packet = Pkt,
+ caps = Caps},
+
+ ?LOG(retransmission, NewReq),
+ TRef = send_request(TPid, EPkt, NewReq, Timeout),
+ {TRef, NewReq}.
+
+%% store_request/4
+
+store_request(TPid, Bin, Req, Timeout) ->
+ Seqs = diameter_codec:sequence_numbers(Bin),
+ TRef = erlang:start_timer(Timeout, self(), timeout),
+ ets:insert(?REQUEST_TABLE, {Seqs, Req, TRef}),
+ ets:member(?REQUEST_TABLE, TPid)
+ orelse (self() ! {failover, TRef}), %% possibly missed failover
+ TRef.
+
+%% lookup_request/2
+
+lookup_request(Msg, TPid)
+ when is_pid(TPid) ->
+ lookup(Msg, TPid, '_');
+
+lookup_request(Msg, TRef)
+ when is_reference(TRef) ->
+ lookup(Msg, '_', TRef).
+
+lookup(Msg, TPid, TRef) ->
+ Seqs = diameter_codec:sequence_numbers(Msg),
+ Spec = [{{Seqs, #request{transport = TPid, _ = '_'}, TRef},
+ [],
+ ['$_']}],
+ case ets:select(?REQUEST_TABLE, Spec) of
+ [{_, Req, _}] ->
+ Req;
+ [] ->
+ false
+ end.
+
+%% erase_request/1
+
+erase_request(Pkt) ->
+ ets:delete(?REQUEST_TABLE, diameter_codec:sequence_numbers(Pkt)).
+
+%% match_requests/1
+
+match_requests(TPid) ->
+ Pat = {'_', #request{transport = TPid, _ = '_'}, '_'},
+ ets:select(?REQUEST_TABLE, [{Pat, [], ['$_']}]).
+
+%% have_request/2
+
+have_request(Pkt, TPid) ->
+ Seqs = diameter_codec:sequence_numbers(Pkt),
+ Pat = {Seqs, #request{transport = TPid, _ = '_'}, '_'},
+ '$end_of_table' /= ets:select(?REQUEST_TABLE, [{Pat, [], ['$_']}], 1).
+
+%% request_peer_up/1
+
+request_peer_up(TPid) ->
+ ets:insert(?REQUEST_TABLE, {TPid}).
+
+%% request_peer_down/2
+
+request_peer_down(TPid, S) ->
+ ets:delete(?REQUEST_TABLE, TPid),
+ lists:foreach(fun(T) -> failover(T,S) end, match_requests(TPid)).
+%% Note that a request process can store its request after failover
+%% notifications are sent here: store_request/4 sends the notification
+%% in that case. Note also that we'll send as many notifications to a
+%% given handler as there are peers its sent to. All but one of these
+%% will be ignored.
+
+%%% ---------------------------------------------------------------------------
+%%% recv_request/3
+%%% ---------------------------------------------------------------------------
+
+recv_request(TPid, Pkt, {ConnT, SvcName, Apps}) ->
+ try ets:lookup(ConnT, TPid) of
+ [C] ->
+ recv_request(C, TPid, Pkt, SvcName, Apps);
+ [] -> %% transport has gone down
+ ok
+ catch
+ error: badarg -> %% service has gone down (and taken table with it)
+ ok
+ end.
+
+%% recv_request/5
+
+recv_request(#conn{apps = SApps, caps = Caps}, TPid, Pkt, SvcName, Apps) ->
+ #diameter_caps{origin_host = {OH,_},
+ origin_realm = {OR,_}}
+ = Caps,
+
+ #diameter_packet{header = #diameter_header{application_id = Id}}
+ = Pkt,
+
+ recv_request(find_recv_app(Id, SApps),
+ {SvcName, OH, OR},
+ TPid,
+ Apps,
+ Caps,
+ Pkt).
+
+%% find_recv_app/2
+
+%% No one should be sending the relay identifier.
+find_recv_app(?APP_ID_RELAY, _) ->
+ false;
+
+%% With any other id we either support it locally or as a relay.
+find_recv_app(Id, SApps) ->
+ keyfind([Id, ?APP_ID_RELAY], 1, SApps).
+
+%% keyfind/3
+
+keyfind([], _, _) ->
+ false;
+keyfind([Key | Rest], Pos, L) ->
+ case lists:keyfind(Key, Pos, L) of
+ false ->
+ keyfind(Rest, Pos, L);
+ T ->
+ T
+ end.
+
+%% recv_request/6
+
+recv_request({Id, Alias}, T, TPid, Apps, Caps, Pkt) ->
+ #diameter_app{dictionary = Dict}
+ = A
+ = find_app(Alias, Apps),
+ recv_request(T, {TPid, Caps}, A, diameter_codec:decode(Id, Dict, Pkt));
+%% Note that the decode is different depending on whether or not Id is
+%% ?APP_ID_RELAY.
+
+%% DIAMETER_APPLICATION_UNSUPPORTED 3007
+%% A request was sent for an application that is not supported.
+
+recv_request(false, T, TPid, _, _, Pkt) ->
+ As = collect_avps(Pkt),
+ protocol_error(3007, T, TPid, Pkt#diameter_packet{avps = As}).
+
+collect_avps(Pkt) ->
+ case diameter_codec:collect_avps(Pkt) of
+ {_Bs, As} ->
+ As;
+ As ->
+ As
+ end.
+
+%% recv_request/4
+
+%% Wrong number of bits somewhere in the message: reply.
+%%
+%% DIAMETER_INVALID_AVP_BITS 3009
+%% A request was received that included an AVP whose flag bits are
+%% set to an unrecognized value, or that is inconsistent with the
+%% AVP's definition.
+%%
+recv_request(T, {TPid, _}, _, #diameter_packet{errors = [Bs | _]} = Pkt)
+ when is_bitstring(Bs) ->
+ protocol_error(3009, T, TPid, Pkt);
+
+%% Either we support this application but don't recognize the command
+%% or we're a relay and the command isn't proxiable.
+%%
+%% DIAMETER_COMMAND_UNSUPPORTED 3001
+%% The Request contained a Command-Code that the receiver did not
+%% recognize or support. This MUST be used when a Diameter node
+%% receives an experimental command that it does not understand.
+%%
+recv_request(T,
+ {TPid, _},
+ #diameter_app{id = Id},
+ #diameter_packet{header = #diameter_header{is_proxiable = P},
+ msg = M}
+ = Pkt)
+ when ?APP_ID_RELAY /= Id, undefined == M;
+ ?APP_ID_RELAY == Id, not P ->
+ protocol_error(3001, T, TPid, Pkt);
+
+%% Error bit was set on a request.
+%%
+%% DIAMETER_INVALID_HDR_BITS 3008
+%% A request was received whose bits in the Diameter header were
+%% either set to an invalid combination, or to a value that is
+%% inconsistent with the command code's definition.
+%%
+recv_request(T,
+ {TPid, _},
+ _,
+ #diameter_packet{header = #diameter_header{is_error = true}}
+ = Pkt) ->
+ protocol_error(3008, T, TPid, Pkt);
+
+%% A message in a locally supported application or a proxiable message
+%% in the relay application. Don't distinguish between the two since
+%% each application has its own callback config. That is, the user can
+%% easily distinguish between the two cases.
+recv_request(T, TC, App, Pkt) ->
+ request_cb(T, TC, App, examine(Pkt)).
+
+%% Note that there may still be errors but these aren't protocol
+%% (3xxx) errors that lead to an answer-message.
+
+request_cb({SvcName, _OH, _OR} = T, TC, App, Pkt) ->
+ request_cb(cb(App, handle_request, [Pkt, SvcName, TC]), App, T, TC, Pkt).
+
+%% examine/1
+%%
+%% Look for errors in a decoded message. Length errors result in
+%% decode failure in diameter_codec.
+
+examine(#diameter_packet{header = #diameter_header{version
+ = ?DIAMETER_VERSION}}
+ = Pkt) ->
+ Pkt;
+
+%% DIAMETER_UNSUPPORTED_VERSION 5011
+%% This error is returned when a request was received, whose version
+%% number is unsupported.
+
+examine(#diameter_packet{errors = Es} = Pkt) ->
+ Pkt#diameter_packet{errors = [5011 | Es]}.
+%% It's odd/unfortunate that this isn't a protocol error.
+
+%% request_cb/5
+
+%% A reply may be an answer-message, constructed either here or by
+%% the handle_request callback. The header from the incoming request
+%% is passed into the encode so that it can retrieve the relevant
+%% command code in this case. It will also then ignore Dict and use
+%% the base encoder.
+request_cb({reply, Ans},
+ #diameter_app{dictionary = Dict},
+ _,
+ {TPid, _},
+ Pkt) ->
+ reply(Ans, Dict, TPid, Pkt);
+
+%% An 3xxx result code, for which the E-bit is set in the header.
+request_cb({protocol_error, RC}, _, T, {TPid, _}, Pkt)
+ when 3000 =< RC, RC < 4000 ->
+ protocol_error(RC, T, TPid, Pkt);
+
+%% RFC 3588 says we must reply 3001 to anything unrecognized or
+%% unsupported. 'noreply' is undocumented (and inappropriately named)
+%% backwards compatibility for this, protocol_error the documented
+%% alternative.
+request_cb(noreply, _, T, {TPid, _}, Pkt) ->
+ protocol_error(3001, T, TPid, Pkt);
+
+%% Relay a request to another peer. This is equivalent to doing an
+%% explicit call/4 with the message in question except that (1) a loop
+%% will be detected by examining Route-Record AVP's, (3) a
+%% Route-Record AVP will be added to the outgoing request and (3) the
+%% End-to-End Identifier will default to that in the
+%% #diameter_header{} without the need for an end_to_end_identifier
+%% option.
+%%
+%% relay and proxy are similar in that they require the same handling
+%% with respect to Route-Record and End-to-End identifier. The
+%% difference is that a proxy advertises specific applications, while
+%% a relay advertises the relay application. If a callback doesn't
+%% want to distinguish between the cases in the callback return value
+%% then 'resend' is a neutral alternative.
+%%
+request_cb({A, Opts},
+ #diameter_app{id = Id}
+ = App,
+ T,
+ TC,
+ Pkt)
+ when A == relay, Id == ?APP_ID_RELAY;
+ A == proxy, Id /= ?APP_ID_RELAY;
+ A == resend ->
+ resend(Opts, App, T, TC, Pkt);
+
+request_cb(discard, _, _, _, _) ->
+ ok;
+
+request_cb({eval, RC, F}, App, T, TC, Pkt) ->
+ request_cb(RC, App, T, TC, Pkt),
+ diameter_lib:eval(F).
+
+%% protocol_error/4
+
+protocol_error(RC, {_, OH, OR}, TPid, #diameter_packet{avps = Avps} = Pkt) ->
+ ?LOG({error, RC}, Pkt),
+ reply(answer_message({OH, OR, RC}, Avps), ?BASE, TPid, Pkt).
+
+%% resend/5
+%%
+%% Resend a message as a relay or proxy agent.
+
+resend(Opts,
+ #diameter_app{} = App,
+ {_SvcName, OH, _OR} = T,
+ {_TPid, _Caps} = TC,
+ #diameter_packet{avps = Avps} = Pkt) ->
+ {Code, _Flags, Vid} = ?BASE:avp_header('Route-Record'),
+ resend(is_loop(Code, Vid, OH, Avps), Opts, App, T, TC, Pkt).
+
+%% DIAMETER_LOOP_DETECTED 3005
+%% An agent detected a loop while trying to get the message to the
+%% intended recipient. The message MAY be sent to an alternate peer,
+%% if one is available, but the peer reporting the error has
+%% identified a configuration problem.
+
+resend(true, _, _, T, {TPid, _}, Pkt) -> %% Route-Record loop
+ protocol_error(3005, T, TPid, Pkt);
+
+%% 6.1.8. Relaying and Proxying Requests
+%%
+%% A relay or proxy agent MUST append a Route-Record AVP to all requests
+%% forwarded. The AVP contains the identity of the peer the request was
+%% received from.
+
+resend(false,
+ Opts,
+ App,
+ {SvcName, _, _} = T,
+ {TPid, #diameter_caps{origin_host = {_, OH}}},
+ #diameter_packet{header = Hdr0,
+ avps = Avps}
+ = Pkt) ->
+ Route = #diameter_avp{data = {?BASE, 'Route-Record', OH}},
+ Seq = diameter_session:sequence(),
+ Hdr = Hdr0#diameter_header{hop_by_hop_id = Seq},
+ Msg = [Hdr, Route | Avps],
+ resend(call(SvcName, App, Msg, Opts), T, TPid, Pkt).
+%% The incoming request is relayed with the addition of a
+%% Route-Record. Note the requirement on the return from call/4 below,
+%% which places a requirement on the value returned by the
+%% handle_answer callback of the application module in question.
+%%
+%% Note that there's nothing stopping the request from being relayed
+%% back to the sender. A pick_peer callback may want to avoid this but
+%% a smart peer might recognize the potential loop and choose another
+%% route. A less smart one will probably just relay the request back
+%% again and force us to detect the loop. A pick_peer that wants to
+%% avoid this can specify filter to avoid the possibility.
+%% Eg. {neg, {host, OH} where #diameter_caps{origin_host = {OH, _}}.
+%%
+%% RFC 6.3 says that a relay agent does not modify Origin-Host but
+%% says nothing about a proxy. Assume it should behave the same way.
+
+%% resend/4
+%%
+%% Relay a reply to a relayed request.
+
+%% Answer from the peer: reset the hop by hop identifier and send.
+resend(#diameter_packet{bin = B}
+ = Pkt,
+ _,
+ TPid,
+ #diameter_packet{header = #diameter_header{hop_by_hop_id = Id},
+ transport_data = TD}) ->
+ send(TPid, Pkt#diameter_packet{bin = diameter_codec:hop_by_hop_id(Id, B),
+ transport_data = TD});
+%% TODO: counters
+
+%% Or not: DIAMETER_UNABLE_TO_DELIVER.
+resend(_, T, TPid, Pkt) ->
+ protocol_error(3002, T, TPid, Pkt).
+
+%% is_loop/4
+%%
+%% Is there a Route-Record AVP with our Origin-Host?
+
+is_loop(Code,
+ Vid,
+ Bin,
+ [#diameter_avp{code = Code, vendor_id = Vid, data = Bin} | _]) ->
+ true;
+
+is_loop(_, _, _, []) ->
+ false;
+
+is_loop(Code, Vid, OH, [_ | Avps])
+ when is_binary(OH) ->
+ is_loop(Code, Vid, OH, Avps);
+
+is_loop(Code, Vid, OH, Avps) ->
+ is_loop(Code, Vid, ?BASE:avp(encode, OH, 'Route-Record'), Avps).
+
+%% reply/4
+%%
+%% Send a locally originating reply.
+
+%% No errors or a diameter_header/avp list.
+reply(Msg, Dict, TPid, #diameter_packet{errors = Es,
+ transport_data = TD}
+ = ReqPkt)
+ when [] == Es;
+ is_record(hd(Msg), diameter_header) ->
+ Pkt = diameter_codec:encode(Dict, make_reply_packet(Msg, ReqPkt)),
+ incr(send, Pkt, Dict, TPid), %% count result codes in sent answers
+ send(TPid, Pkt#diameter_packet{transport_data = TD});
+
+%% Or not: set Result-Code and Failed-AVP AVP's.
+reply(Msg, Dict, TPid, #diameter_packet{errors = [H|_] = Es} = Pkt) ->
+ reply(rc(Msg, rc(H), [A || {_,A} <- Es], Dict),
+ Dict,
+ TPid,
+ Pkt#diameter_packet{errors = []}).
+
+%% make_reply_packet/2
+
+%% Binaries and header/avp lists are sent as-is.
+make_reply_packet(Bin, _)
+ when is_binary(Bin) ->
+ #diameter_packet{bin = Bin};
+make_reply_packet([#diameter_header{} | _] = Msg, _) ->
+ #diameter_packet{msg = Msg};
+
+%% Otherwise a reply message clears the R and T flags and retains the
+%% P flag. The E flag will be set at encode.
+make_reply_packet(Msg, #diameter_packet{header = ReqHdr}) ->
+ Hdr = ReqHdr#diameter_header{version = ?DIAMETER_VERSION,
+ is_request = false,
+ is_error = undefined,
+ is_retransmitted = false},
+ #diameter_packet{header = Hdr,
+ msg = Msg}.
+
+%% rc/1
+
+rc({RC, _}) ->
+ RC;
+rc(RC) ->
+ RC.
+
+%% rc/4
+
+rc(Rec, RC, Failed, Dict)
+ when is_integer(RC) ->
+ set(Rec, [{'Result-Code', RC} | failed_avp(Rec, Failed, Dict)], Dict).
+
+%% Reply as name and tuple list ...
+set([_|_] = Ans, Avps, _) ->
+ Ans ++ Avps; %% Values nearer tail take precedence.
+
+%% ... or record.
+set(Rec, Avps, Dict) ->
+ Dict:'#set-'(Avps, Rec).
+
+%% failed_avp/3
+
+failed_avp(_, [] = No, _) ->
+ No;
+
+failed_avp(Rec, Failed, Dict) ->
+ [fa(Rec, [{'AVP', Failed}], Dict)].
+
+%% Reply as name and tuple list ...
+fa([MsgName | Values], FailedAvp, Dict) ->
+ R = Dict:msg2rec(MsgName),
+ try
+ Dict:'#info-'(R, {index, 'Failed-AVP'}),
+ {'Failed-AVP', [FailedAvp]}
+ catch
+ error: _ ->
+ Avps = proplists:get_value('AVP', Values, []),
+ A = #diameter_avp{name = 'Failed-AVP',
+ value = FailedAvp},
+ {'AVP', [A|Avps]}
+ end;
+
+%% ... or record.
+fa(Rec, FailedAvp, Dict) ->
+ try
+ {'Failed-AVP', [FailedAvp]}
+ catch
+ error: _ ->
+ Avps = Dict:'get-'('AVP', Rec),
+ A = #diameter_avp{name = 'Failed-AVP',
+ value = FailedAvp},
+ {'AVP', [A|Avps]}
+ end.
+
+%% 3. Diameter Header
+%%
+%% E(rror) - If set, the message contains a protocol error,
+%% and the message will not conform to the ABNF
+%% described for this command. Messages with the 'E'
+%% bit set are commonly referred to as error
+%% messages. This bit MUST NOT be set in request
+%% messages. See Section 7.2.
+
+%% 3.2. Command Code ABNF specification
+%%
+%% e-bit = ", ERR"
+%% ; If present, the 'E' bit in the Command
+%% ; Flags is set, indicating that the answer
+%% ; message contains a Result-Code AVP in
+%% ; the "protocol error" class.
+
+%% 7.1.3. Protocol Errors
+%%
+%% Errors that fall within the Protocol Error category SHOULD be treated
+%% on a per-hop basis, and Diameter proxies MAY attempt to correct the
+%% error, if it is possible. Note that these and only these errors MUST
+%% only be used in answer messages whose 'E' bit is set.
+
+%% Thus, only construct answers to protocol errors. Other errors
+%% require an message-specific answer and must be handled by the
+%% application.
+
+%% 6.2. Diameter Answer Processing
+%%
+%% When a request is locally processed, the following procedures MUST be
+%% applied to create the associated answer, in addition to any
+%% additional procedures that MAY be discussed in the Diameter
+%% application defining the command:
+%%
+%% - The same Hop-by-Hop identifier in the request is used in the
+%% answer.
+%%
+%% - The local host's identity is encoded in the Origin-Host AVP.
+%%
+%% - The Destination-Host and Destination-Realm AVPs MUST NOT be
+%% present in the answer message.
+%%
+%% - The Result-Code AVP is added with its value indicating success or
+%% failure.
+%%
+%% - If the Session-Id is present in the request, it MUST be included
+%% in the answer.
+%%
+%% - Any Proxy-Info AVPs in the request MUST be added to the answer
+%% message, in the same order they were present in the request.
+%%
+%% - The 'P' bit is set to the same value as the one in the request.
+%%
+%% - The same End-to-End identifier in the request is used in the
+%% answer.
+%%
+%% Note that the error messages (see Section 7.3) are also subjected to
+%% the above processing rules.
+
+%% 7.3. Error-Message AVP
+%%
+%% The Error-Message AVP (AVP Code 281) is of type UTF8String. It MAY
+%% accompany a Result-Code AVP as a human readable error message. The
+%% Error-Message AVP is not intended to be useful in real-time, and
+%% SHOULD NOT be expected to be parsed by network entities.
+
+%% answer_message/2
+
+answer_message({OH, OR, RC}, Avps) ->
+ {Code, _, Vid} = ?BASE:avp_header('Session-Id'),
+ ['answer-message', {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Result-Code', RC}
+ | session_id(Code, Vid, Avps)].
+
+session_id(Code, Vid, Avps)
+ when is_list(Avps) ->
+ try
+ {value, #diameter_avp{data = D}} = find_avp(Code, Vid, Avps),
+ [{'Session-Id', [?BASE:avp(decode, D, 'Session-Id')]}]
+ catch
+ error: _ ->
+ []
+ end.
+
+%% find_avp/3
+
+find_avp(Code, Vid, Avps)
+ when is_integer(Code), (undefined == Vid orelse is_integer(Vid)) ->
+ find(fun(A) -> is_avp(Code, Vid, A) end, Avps).
+
+%% The final argument here could be a list of AVP's, depending on the case,
+%% but we're only searching at the top level.
+is_avp(Code, Vid, #diameter_avp{code = Code, vendor_id = Vid}) ->
+ true;
+is_avp(_, _, _) ->
+ false.
+
+find(_, []) ->
+ false;
+find(Pred, [H|T]) ->
+ case Pred(H) of
+ true ->
+ {value, H};
+ false ->
+ find(Pred, T)
+ end.
+
+%% 7. Error Handling
+%%
+%% There are certain Result-Code AVP application errors that require
+%% additional AVPs to be present in the answer. In these cases, the
+%% Diameter node that sets the Result-Code AVP to indicate the error
+%% MUST add the AVPs. Examples are:
+%%
+%% - An unrecognized AVP is received with the 'M' bit (Mandatory bit)
+%% set, causes an answer to be sent with the Result-Code AVP set to
+%% DIAMETER_AVP_UNSUPPORTED, and the Failed-AVP AVP containing the
+%% offending AVP.
+%%
+%% - An AVP that is received with an unrecognized value causes an
+%% answer to be returned with the Result-Code AVP set to
+%% DIAMETER_INVALID_AVP_VALUE, with the Failed-AVP AVP containing the
+%% AVP causing the error.
+%%
+%% - A command is received with an AVP that is omitted, yet is
+%% mandatory according to the command's ABNF. The receiver issues an
+%% answer with the Result-Code set to DIAMETER_MISSING_AVP, and
+%% creates an AVP with the AVP Code and other fields set as expected
+%% in the missing AVP. The created AVP is then added to the Failed-
+%% AVP AVP.
+%%
+%% The Result-Code AVP describes the error that the Diameter node
+%% encountered in its processing. In case there are multiple errors,
+%% the Diameter node MUST report only the first error it encountered
+%% (detected possibly in some implementation dependent order). The
+%% specific errors that can be described by this AVP are described in
+%% the following section.
+
+%% 7.5. Failed-AVP AVP
+%%
+%% The Failed-AVP AVP (AVP Code 279) is of type Grouped and provides
+%% debugging information in cases where a request is rejected or not
+%% fully processed due to erroneous information in a specific AVP. The
+%% value of the Result-Code AVP will provide information on the reason
+%% for the Failed-AVP AVP.
+%%
+%% The possible reasons for this AVP are the presence of an improperly
+%% constructed AVP, an unsupported or unrecognized AVP, an invalid AVP
+%% value, the omission of a required AVP, the presence of an explicitly
+%% excluded AVP (see tables in Section 10), or the presence of two or
+%% more occurrences of an AVP which is restricted to 0, 1, or 0-1
+%% occurrences.
+%%
+%% A Diameter message MAY contain one Failed-AVP AVP, containing the
+%% entire AVP that could not be processed successfully. If the failure
+%% reason is omission of a required AVP, an AVP with the missing AVP
+%% code, the missing vendor id, and a zero filled payload of the minimum
+%% required length for the omitted AVP will be added.
+
+%%% ---------------------------------------------------------------------------
+%%% # handle_answer/3
+%%% ---------------------------------------------------------------------------
+
+%% Process an answer message in call-specific process.
+
+handle_answer(SvcName, _, {error, Req, Reason}) ->
+ handle_error(Req, Reason, SvcName);
+
+handle_answer(SvcName,
+ AnswerErrors,
+ {answer, #request{dictionary = Dict} = Req, Pkt}) ->
+ a(examine(diameter_codec:decode(Dict, Pkt)),
+ SvcName,
+ AnswerErrors,
+ Req).
+
+%% We don't really need to do a full decode if we're a relay and will
+%% just resend with a new hop by hop identifier, but might a proxy
+%% want to examine the answer?
+
+a(#diameter_packet{errors = []}
+ = Pkt,
+ SvcName,
+ AE,
+ #request{transport = TPid,
+ dictionary = Dict,
+ caps = Caps,
+ packet = P}
+ = Req) ->
+ try
+ incr(in, Pkt, Dict, TPid)
+ of
+ _ ->
+ cb(Req, handle_answer, [Pkt, msg(P), SvcName, {TPid, Caps}])
+ catch
+ exit: {invalid_error_bit, _} = E ->
+ e(Pkt#diameter_packet{errors = [E]}, SvcName, AE, Req)
+ end;
+
+a(#diameter_packet{} = Pkt, SvcName, AE, Req) ->
+ e(Pkt, SvcName, AE, Req).
+
+e(Pkt, SvcName, callback, #request{transport = TPid,
+ caps = Caps,
+ packet = Pkt}
+ = Req) ->
+ cb(Req, handle_answer, [Pkt, msg(Pkt), SvcName, {TPid, Caps}]);
+e(Pkt, SvcName, report, Req) ->
+ x(errors, handle_answer, [SvcName, Req, Pkt]);
+e(Pkt, SvcName, discard, Req) ->
+ x({errors, handle_answer, [SvcName, Req, Pkt]}).
+
+%% Note that we don't check that the application id in the answer's
+%% header is what we expect. (TODO: Does the rfc says anything about
+%% this?)
+
+%% incr/4
+%%
+%% Increment a stats counter for an incoming or outgoing message.
+
+%% TODO: fix
+incr(_, #diameter_packet{msg = undefined}, _, _) ->
+ ok;
+
+incr(Dir, Pkt, Dict, TPid)
+ when is_pid(TPid) ->
+ #diameter_packet{header = #diameter_header{is_error = E}
+ = Hdr,
+ msg = Rec}
+ = Pkt,
+
+ D = choose(E, ?BASE, Dict),
+ RC = int(get_avp_value(D, 'Result-Code', Rec)),
+ PE = is_protocol_error(RC),
+
+ %% Check that the E bit is set only for 3xxx result codes.
+ (not (E orelse PE))
+ orelse (E andalso PE)
+ orelse x({invalid_error_bit, RC}, answer, [Dir, Pkt]),
+
+ Ctr = rc_counter(D, Rec, RC),
+ is_tuple(Ctr)
+ andalso incr(TPid, {diameter_codec:msg_id(Hdr), Dir, Ctr}).
+
+%% incr/2
+
+incr(TPid, Counter) ->
+ diameter_stats:incr(Counter, TPid, 1).
+
+%% RFC 3588, 7.6:
+%%
+%% All Diameter answer messages defined in vendor-specific
+%% applications MUST include either one Result-Code AVP or one
+%% Experimental-Result AVP.
+%%
+%% Maintain statistics assuming one or the other, not both, which is
+%% surely the intent of the RFC.
+
+rc_counter(_, _, RC)
+ when is_integer(RC) ->
+ {'Result-Code', RC};
+rc_counter(D, Rec, _) ->
+ rcc(get_avp_value(D, 'Experimental-Result', Rec)).
+
+%% Outgoing answers may be in any of the forms messages can be sent
+%% in. Incoming messages will be records. We're assuming here that the
+%% arity of the result code AVP's is 0 or 1.
+
+rcc([{_,_,RC} = T])
+ when is_integer(RC) ->
+ T;
+rcc({_,_,RC} = T)
+ when is_integer(RC) ->
+ T;
+rcc(_) ->
+ undefined.
+
+int([N])
+ when is_integer(N) ->
+ N;
+int(N)
+ when is_integer(N) ->
+ N;
+int(_) ->
+ undefined.
+
+is_protocol_error(RC) ->
+ 3000 =< RC andalso RC < 4000.
+
+-spec x(any(), atom(), list()) -> no_return().
+
+%% Warn and exit request process on errors in an incoming answer.
+x(Reason, F, A) ->
+ diameter_lib:warning_report(Reason, {?MODULE, F, A}),
+ x(Reason).
+
+x(T) ->
+ exit(T).
+
+%%% ---------------------------------------------------------------------------
+%%% # failover/[23]
+%%% ---------------------------------------------------------------------------
+
+%% Failover as a consequence of request_peer_down/2.
+failover({_, #request{handler = Pid} = Req, TRef}, S) ->
+ Pid ! {failover, TRef, rt(Req, S)}.
+
+%% Failover as a consequence of store_request/4.
+failover(TRef, Seqs, S)
+ when is_reference(TRef) ->
+ case lookup_request(Seqs, TRef) of
+ #request{} = Req ->
+ failover({Seqs, Req, TRef}, S);
+ false ->
+ ok
+ end.
+
+%% prepare_request returned a binary ...
+rt(#request{packet = #diameter_packet{msg = undefined}}, _) ->
+ false; %% TODO: Not what we should do.
+
+%% ... or not.
+rt(#request{packet = #diameter_packet{msg = Msg}, dictionary = D} = Req, S) ->
+ find_transport(get_destination(Msg, D), Req, S).
+
+%%% ---------------------------------------------------------------------------
+%%% # report_status/5
+%%% ---------------------------------------------------------------------------
+
+report_status(Status,
+ #peer{ref = Ref,
+ conn = TPid,
+ type = Type,
+ options = Opts},
+ #conn{apps = [_|_] = As,
+ caps = Caps},
+ #state{service_name = SvcName}
+ = S,
+ Extra) ->
+ share_peer(Status, Caps, As, TPid, S),
+ Info = [Status, Ref, {TPid, Caps}, {type(Type), Opts} | Extra],
+ send_event(SvcName, list_to_tuple(Info)).
+
+%% send_event/2
+
+send_event(SvcName, Info) ->
+ send_event(#diameter_event{service = SvcName,
+ info = Info}).
+
+send_event(#diameter_event{service = SvcName} = E) ->
+ lists:foreach(fun({_, Pid}) -> Pid ! E end, subscriptions(SvcName)).
+
+%%% ---------------------------------------------------------------------------
+%%% # share_peer/5
+%%% ---------------------------------------------------------------------------
+
+share_peer(up, Caps, Aliases, TPid, #state{share_peers = true,
+ service_name = Svc}) ->
+ diameter_peer:notify(Svc, {peer, TPid, Aliases, Caps});
+
+share_peer(_, _, _, _, _) ->
+ ok.
+
+%%% ---------------------------------------------------------------------------
+%%% # share_peers/2
+%%% ---------------------------------------------------------------------------
+
+share_peers(Pid, #state{share_peers = true,
+ local_peers = PDict}) ->
+ ?Dict:fold(fun(A,Ps,ok) -> sp(Pid, A, Ps), ok end, ok, PDict);
+
+share_peers(_, #state{share_peers = false}) ->
+ ok.
+
+sp(Pid, Alias, Peers) ->
+ lists:foreach(fun({P,C}) -> Pid ! {peer, P, [Alias], C} end, Peers).
+
+%%% ---------------------------------------------------------------------------
+%%% # remote_peer_up/4
+%%% ---------------------------------------------------------------------------
+
+remote_peer_up(Pid, Aliases, Caps, #state{use_shared_peers = true,
+ service = Svc,
+ shared_peers = PDict}
+ = S) ->
+ #diameter_service{applications = Apps} = Svc,
+ Update = lists:filter(fun(A) ->
+ lists:keymember(A, #diameter_app.alias, Apps)
+ end,
+ Aliases),
+ S#state{shared_peers = rpu(Pid, Caps, PDict, Update)};
+
+remote_peer_up(_, _, _, #state{use_shared_peers = false} = S) ->
+ S.
+
+rpu(_, _, PDict, []) ->
+ PDict;
+rpu(Pid, Caps, PDict, Aliases) ->
+ erlang:monitor(process, Pid),
+ T = {Pid, Caps},
+ lists:foldl(fun(A,D) -> ?Dict:append(A, T, D) end,
+ PDict,
+ Aliases).
+
+%%% ---------------------------------------------------------------------------
+%%% # remote_peer_down/2
+%%% ---------------------------------------------------------------------------
+
+remote_peer_down(Pid, #state{use_shared_peers = true,
+ shared_peers = PDict}
+ = S) ->
+ S#state{shared_peers = lists:foldl(fun(A,D) -> rpd(Pid, A, D) end,
+ PDict,
+ ?Dict:fetch_keys(PDict))}.
+
+rpd(Pid, Alias, PDict) ->
+ ?Dict:update(Alias, fun(Ps) -> lists:keydelete(Pid, 1, Ps) end, PDict).
+
+%%% ---------------------------------------------------------------------------
+%%% find_transport/[34]
+%%%
+%%% Output: {TransportPid, #diameter_caps{}, #diameter_app{}}
+%%% | false
+%%% | {error, Reason}
+%%% ---------------------------------------------------------------------------
+
+%% Initial call, from an arbitrary process.
+find_transport({alias, Alias}, Msg, Opts, #state{service = Svc} = S) ->
+ #diameter_service{applications = Apps} = Svc,
+ ft(find_send_app(Alias, Apps), Msg, Opts, S);
+
+%% Relay or proxy send.
+find_transport(#diameter_app{} = App, Msg, Opts, S) ->
+ ft(App, Msg, Opts, S).
+
+ft(#diameter_app{module = Mod, dictionary = D} = App, Msg, Opts, S) ->
+ #options{filter = Filter,
+ extra = Xtra}
+ = Opts,
+ pick_peer(App#diameter_app{module = Mod ++ Xtra},
+ get_destination(Msg, D),
+ Filter,
+ S);
+ft(false = No, _, _, _) ->
+ No.
+
+%% This can't be used if we're a relay and sending a message
+%% in an application not known locally. (TODO)
+find_send_app(Alias, Apps) ->
+ case lists:keyfind(Alias, #diameter_app.alias, Apps) of
+ #diameter_app{id = ?APP_ID_RELAY} ->
+ false;
+ T ->
+ T
+ end.
+
+%% Retransmission, in the service process.
+find_transport([_,_] = RH,
+ Req,
+ #state{service = #diameter_service{pid = Pid,
+ applications = Apps}}
+ = S)
+ when self() == Pid ->
+ #request{app = Alias,
+ filter = Filter,
+ module = ModX}
+ = Req,
+ #diameter_app{}
+ = App
+ = lists:keyfind(Alias, #diameter_app.alias, Apps),
+
+ pick_peer(App#diameter_app{module = ModX},
+ RH,
+ Filter,
+ S).
+
+%% get_destination/2
+
+get_destination(Msg, Dict) ->
+ [str(get_avp_value(Dict, 'Destination-Realm', Msg)),
+ str(get_avp_value(Dict, 'Destination-Host', Msg))].
+
+%% This is not entirely correct. The avp could have an arity 1, in
+%% which case an empty list is a DiameterIdentity of length 0 rather
+%% than the list of no values we treat it as by mapping to undefined.
+%% This behaviour is documented.
+str([]) ->
+ undefined;
+str(T) ->
+ T.
+
+%% get_avp_value/3
+%%
+%% Find an AVP in a message of one of three forms:
+%%
+%% - a message record (as generated from a .dia spec) or
+%% - a list of an atom message name followed by 2-tuple, avp name/value pairs.
+%% - a list of a #diameter_header{} followed by #diameter_avp{} records,
+%%
+%% In the first two forms a dictionary module is used at encode to
+%% identify the type of the AVP and its arity in the message in
+%% question. The third form allows messages to be sent as is, without
+%% a dictionary, which is needed in the case of relay agents, for one.
+
+get_avp_value(Dict, Name, [#diameter_header{} | Avps]) ->
+ try
+ {Code, _, VId} = Dict:avp_header(Name),
+ [A|_] = lists:dropwhile(fun(#diameter_avp{code = C, vendor_id = V}) ->
+ C /= Code orelse V /= VId
+ end,
+ Avps),
+ avp_decode(Dict, Name, A)
+ catch
+ error: _ ->
+ undefined
+ end;
+
+get_avp_value(_, Name, [_MsgName | Avps]) ->
+ case lists:keyfind(Name, 1, Avps) of
+ {_, V} ->
+ V;
+ _ ->
+ undefined
+ end;
+
+%% Message is typically a record but not necessarily: diameter:call/4
+%% can be passed an arbitrary term.
+get_avp_value(Dict, Name, Rec) ->
+ try
+ Dict:'#get-'(Name, Rec)
+ catch
+ error:_ ->
+ undefined
+ end.
+
+avp_decode(Dict, Name, #diameter_avp{value = undefined,
+ data = Bin}) ->
+ Dict:avp(decode, Bin, Name);
+avp_decode(_, _, #diameter_avp{value = V}) ->
+ V.
+
+%%% ---------------------------------------------------------------------------
+%%% # pick_peer(App, [DestRealm, DestHost], Filter, #state{})
+%%%
+%%% Output: {TransportPid, #diameter_caps{}, App}
+%%% | false
+%%% | {error, Reason}
+%%% ---------------------------------------------------------------------------
+
+%% Find transports to a given realm/host.
+
+pick_peer(#diameter_app{alias = Alias}
+ = App,
+ [_,_] = RH,
+ Filter,
+ #state{local_peers = L,
+ shared_peers = S,
+ service_name = SvcName,
+ service = #diameter_service{pid = Pid}}) ->
+ pick_peer(peers(Alias, RH, Filter, L),
+ peers(Alias, RH, Filter, S),
+ Pid,
+ SvcName,
+ App).
+
+%% pick_peer/5
+
+pick_peer([], [], _, _, _) ->
+ false;
+
+%% App state is mutable but we're not in the service process: go there.
+pick_peer(Local, Remote, Pid, _SvcName, #diameter_app{mutable = true} = App)
+ when self() /= Pid ->
+ call_service(Pid, {pick_peer, Local, Remote, App});
+
+%% App state isn't mutable or it is and we're in the service process:
+%% do the deed.
+pick_peer(Local,
+ Remote,
+ _Pid,
+ SvcName,
+ #diameter_app{module = ModX,
+ alias = Alias,
+ init_state = S,
+ mutable = M}
+ = App) ->
+ MFA = {ModX, pick_peer, [Local, Remote, SvcName]},
+
+ try state_cb(App, MFA) of
+ {ok, {TPid, #diameter_caps{} = Caps}} when is_pid(TPid) ->
+ {TPid, Caps, App};
+ {{TPid, #diameter_caps{} = Caps}, ModS} when is_pid(TPid), M ->
+ mod_state(Alias, ModS),
+ {TPid, Caps, App};
+ {false = No, ModS} when M ->
+ mod_state(Alias, ModS),
+ No;
+ {ok, false = No} ->
+ No;
+ false = No ->
+ No;
+ {{TPid, #diameter_caps{} = Caps}, S} when is_pid(TPid) ->
+ {TPid, Caps, App}; %% Accept returned state in the immutable
+ {false = No, S} -> %% case as long it isn't changed.
+ No;
+ T ->
+ diameter_lib:error_report({invalid, T, App}, MFA)
+ catch
+ E: Reason ->
+ diameter_lib:error_report({failure, {E, Reason, ?STACK}}, MFA)
+ end.
+
+%% peers/4
+
+peers(Alias, RH, Filter, Peers) ->
+ case ?Dict:find(Alias, Peers) of
+ {ok, L} ->
+ ps(L, RH, Filter, {[],[]});
+ error ->
+ []
+ end.
+
+%% Place a peer whose Destination-Host/Realm matches those of the
+%% request at the front of the result list. Could add some sort of
+%% 'sort' option to allow more control.
+
+ps([], _, _, {Ys, Ns}) ->
+ lists:reverse(Ys, Ns);
+ps([{_TPid, #diameter_caps{} = Caps} = TC | Rest], RH, Filter, Acc) ->
+ ps(Rest, RH, Filter, pacc(caps_filter(Caps, RH, Filter),
+ caps_filter(Caps, RH, {all, [host, realm]}),
+ TC,
+ Acc)).
+
+pacc(true, true, Peer, {Ts, Fs}) ->
+ {[Peer|Ts], Fs};
+pacc(true, false, Peer, {Ts, Fs}) ->
+ {Ts, [Peer|Fs]};
+pacc(_, _, _, Acc) ->
+ Acc.
+
+%% caps_filter/3
+
+caps_filter(C, RH, {neg, F}) ->
+ not caps_filter(C, RH, F);
+
+caps_filter(C, RH, {all, L})
+ when is_list(L) ->
+ lists:all(fun(F) -> caps_filter(C, RH, F) end, L);
+
+caps_filter(C, RH, {any, L})
+ when is_list(L) ->
+ lists:any(fun(F) -> caps_filter(C, RH, F) end, L);
+
+caps_filter(#diameter_caps{origin_host = {_,OH}}, [_,DH], host) ->
+ eq(undefined, DH, OH);
+
+caps_filter(#diameter_caps{origin_realm = {_,OR}}, [DR,_], realm) ->
+ eq(undefined, DR, OR);
+
+caps_filter(C, _, Filter) ->
+ caps_filter(C, Filter).
+
+%% caps_filter/2
+
+caps_filter(_, none) ->
+ true;
+
+caps_filter(#diameter_caps{origin_host = {_,OH}}, {host, H}) ->
+ eq(any, H, OH);
+
+caps_filter(#diameter_caps{origin_realm = {_,OR}}, {realm, R}) ->
+ eq(any, R, OR);
+
+%% Anything else is expected to be an eval filter. Filter failure is
+%% documented as being equivalent to a non-matching filter.
+
+caps_filter(C, T) ->
+ try
+ {eval, F} = T,
+ diameter_lib:eval([F,C])
+ catch
+ _:_ -> false
+ end.
+
+eq(Any, Id, PeerId) ->
+ Any == Id orelse try
+ iolist_to_binary(Id) == iolist_to_binary(PeerId)
+ catch
+ _:_ -> false
+ end.
+%% OctetString() can be specified as an iolist() so test for string
+%% rather then term equality.
+
+%% transports/1
+
+transports(#state{peerT = PeerT}) ->
+ ets:select(PeerT, [{#peer{conn = '$1', _ = '_'},
+ [{'is_pid', '$1'}],
+ ['$1']}]).
+
+%%% ---------------------------------------------------------------------------
+%%% # service_info/2
+%%% ---------------------------------------------------------------------------
+
+%% The config passed to diameter:start_service/2.
+-define(CAP_INFO, ['Origin-Host',
+ 'Origin-Realm',
+ 'Vendor-Id',
+ 'Product-Name',
+ 'Origin-State-Id',
+ 'Host-IP-Address',
+ 'Supported-Vendor-Id',
+ 'Auth-Application-Id',
+ 'Inband-Security-Id',
+ 'Acct-Application-Id',
+ 'Vendor-Specific-Application-Id',
+ 'Firmware-Revision']).
+
+-define(ALL_INFO, [capabilities,
+ applications,
+ transport,
+ pending,
+ statistics]).
+
+service_info(Items, S)
+ when is_list(Items) ->
+ [{complete(I), service_info(I,S)} || I <- Items];
+service_info(Item, S)
+ when is_atom(Item) ->
+ service_info(Item, S, true).
+
+service_info(Item, #state{service = Svc} = S, Complete) ->
+ case Item of
+ name ->
+ S#state.service_name;
+ 'Origin-Host' ->
+ (Svc#diameter_service.capabilities)
+ #diameter_caps.origin_host;
+ 'Origin-Realm' ->
+ (Svc#diameter_service.capabilities)
+ #diameter_caps.origin_realm;
+ 'Vendor-Id' ->
+ (Svc#diameter_service.capabilities)
+ #diameter_caps.vendor_id;
+ 'Product-Name' ->
+ (Svc#diameter_service.capabilities)
+ #diameter_caps.product_name;
+ 'Origin-State-Id' ->
+ (Svc#diameter_service.capabilities)
+ #diameter_caps.origin_state_id;
+ 'Host-IP-Address' ->
+ (Svc#diameter_service.capabilities)
+ #diameter_caps.host_ip_address;
+ 'Supported-Vendor-Id' ->
+ (Svc#diameter_service.capabilities)
+ #diameter_caps.supported_vendor_id;
+ 'Auth-Application-Id' ->
+ (Svc#diameter_service.capabilities)
+ #diameter_caps.auth_application_id;
+ 'Inband-Security-Id' ->
+ (Svc#diameter_service.capabilities)
+ #diameter_caps.inband_security_id;
+ 'Acct-Application-Id' ->
+ (Svc#diameter_service.capabilities)
+ #diameter_caps.acct_application_id;
+ 'Vendor-Specific-Application-Id' ->
+ (Svc#diameter_service.capabilities)
+ #diameter_caps.vendor_specific_application_id;
+ 'Firmware-Revision' ->
+ (Svc#diameter_service.capabilities)
+ #diameter_caps.firmware_revision;
+ capabilities -> service_info(?CAP_INFO, S);
+ applications -> info_apps(S);
+ transport -> info_transport(S);
+ pending -> info_pending(S);
+ statistics -> info_stats(S);
+ keys -> ?ALL_INFO ++ ?CAP_INFO; %% mostly for test
+ all -> service_info(?ALL_INFO, S);
+ _ when Complete -> service_info(complete(Item), S, false);
+ _ -> undefined
+ end.
+
+complete(Pre) ->
+ P = atom_to_list(Pre),
+ case [I || I <- [name | ?ALL_INFO] ++ ?CAP_INFO,
+ lists:prefix(P, atom_to_list(I))]
+ of
+ [I] -> I;
+ _ -> Pre
+ end.
+
+info_stats(#state{peerT = PeerT}) ->
+ Peers = ets:select(PeerT, [{#peer{ref = '$1', conn = '$2', _ = '_'},
+ [{'is_pid', '$2'}],
+ [['$1', '$2']]}]),
+ diameter_stats:read(lists:append(Peers)).
+%% TODO: include peer identities in return value
+
+info_transport(#state{peerT = PeerT, connT = ConnT}) ->
+ dict:fold(fun it/3,
+ [],
+ ets:foldl(fun(T,A) -> it_acc(ConnT, A, T) end,
+ dict:new(),
+ PeerT)).
+
+it(Ref, [[{type, connect} | _] = L], Acc) ->
+ [[{ref, Ref} | L] | Acc];
+it(Ref, [[{type, accept}, {options, Opts} | _] | _] = L, Acc) ->
+ [[{ref, Ref},
+ {type, listen},
+ {options, Opts},
+ {accept, [lists:nthtail(2,A) || A <- L]}]
+ | Acc].
+%% Each entry has the same Opts. (TODO)
+
+it_acc(ConnT, Acc, #peer{pid = Pid,
+ type = Type,
+ ref = Ref,
+ options = Opts,
+ op_state = OS,
+ started = T,
+ conn = TPid}) ->
+ dict:append(Ref,
+ [{type, Type},
+ {options, Opts},
+ {watchdog, {Pid, T, OS}}
+ | info_conn(ConnT, TPid)],
+ Acc).
+
+info_conn(ConnT, TPid) ->
+ info_conn(ets:lookup(ConnT, TPid)).
+
+info_conn([#conn{pid = Pid, apps = SApps, caps = Caps, started = T}]) ->
+ [{peer, {Pid, T}},
+ {apps, SApps},
+ {caps, info_caps(Caps)}];
+info_conn([] = No) ->
+ No.
+
+info_caps(#diameter_caps{} = C) ->
+ lists:zip(record_info(fields, diameter_caps), tl(tuple_to_list(C))).
+
+info_apps(#state{service = #diameter_service{applications = Apps}}) ->
+ lists:map(fun mk_app/1, Apps).
+
+mk_app(#diameter_app{alias = Alias,
+ dictionary = Dict,
+ module = ModX,
+ id = Id}) ->
+ [{alias, Alias},
+ {dictionary, Dict},
+ {module, ModX},
+ {id, Id}].
+
+info_pending(#state{} = S) ->
+ MatchSpec = [{{'$1',
+ #request{transport = '$2',
+ from = '$3',
+ app = '$4',
+ _ = '_'},
+ '_'},
+ [?ORCOND([{'==', T, '$2'} || T <- transports(S)])],
+ [{{'$1', [{{app, '$4'}},
+ {{transport, '$2'}},
+ {{from, '$3'}}]}}]}],
+
+ ets:select(?REQUEST_TABLE, MatchSpec).
diff --git a/lib/diameter/src/app/diameter_service_sup.erl b/lib/diameter/src/app/diameter_service_sup.erl
new file mode 100644
index 0000000000..153fff902f
--- /dev/null
+++ b/lib/diameter/src/app/diameter_service_sup.erl
@@ -0,0 +1,64 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% The supervisor of service processes.
+%%
+
+-module(diameter_service_sup).
+
+-behaviour(supervisor).
+
+-export([start_link/0, %% supervisor start
+ start_child/1]). %% service start
+
+%% supervisor callback
+-export([init/1]).
+
+-define(NAME, ?MODULE). %% supervisor name
+
+%% start_link/0
+
+start_link() ->
+ SupName = {local, ?NAME},
+ supervisor:start_link(SupName, ?MODULE, []).
+
+%% start_child/1
+%%
+%% A service and its related processes (transport, peer_fwm and
+%% watchdog) are all temporary since they're all restarted in
+%% application code. A Transport and peer_fsm is restarted by a
+%% watchdog as required by the RFC 3539 state machine, a watchdog is
+%% restarted by service, and services are restarted by diameter_config.
+
+start_child(ServiceName) ->
+ supervisor:start_child(?NAME, [ServiceName]).
+
+%% init/1
+
+init([]) ->
+ Mod = diameter_service,
+ Flags = {simple_one_for_one, 0, 1},
+ ChildSpec = {Mod,
+ {Mod, start_link, []},
+ temporary,
+ 1000,
+ worker,
+ [Mod]},
+ {ok, {Flags, [ChildSpec]}}.
diff --git a/lib/diameter/src/app/diameter_session.erl b/lib/diameter/src/app/diameter_session.erl
new file mode 100644
index 0000000000..bb91e97f39
--- /dev/null
+++ b/lib/diameter/src/app/diameter_session.erl
@@ -0,0 +1,172 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_session).
+
+-export([sequence/0,
+ session_id/1,
+ origin_state_id/0]).
+
+%% towards diameter_sup
+-export([init/0]).
+
+-include("diameter_types.hrl").
+
+-define(INT64, 16#FFFFFFFFFFFFFFFF).
+-define(INT32, 16#FFFFFFFF).
+
+%% ---------------------------------------------------------------------------
+%% # sequence/0
+%%
+%% Output: 32-bit
+%% ---------------------------------------------------------------------------
+
+%% 3588, 3:
+%%
+%% Hop-by-Hop Identifier
+%% The Hop-by-Hop Identifier is an unsigned 32-bit integer field (in
+%% network byte order) and aids in matching requests and replies.
+%% The sender MUST ensure that the Hop-by-Hop identifier in a request
+%% is unique on a given connection at any given time, and MAY attempt
+%% to ensure that the number is unique across reboots. The sender of
+%% an Answer message MUST ensure that the Hop-by-Hop Identifier field
+%% contains the same value that was found in the corresponding
+%% request. The Hop-by-Hop identifier is normally a monotonically
+%% increasing number, whose start value was randomly generated. An
+%% answer message that is received with an unknown Hop-by-Hop
+%% Identifier MUST be discarded.
+%%
+%% End-to-End Identifier
+%% The End-to-End Identifier is an unsigned 32-bit integer field (in
+%% network byte order) and is used to detect duplicate messages.
+%% Upon reboot implementations MAY set the high order 12 bits to
+%% contain the low order 12 bits of current time, and the low order
+%% 20 bits to a random value. Senders of request messages MUST
+%% insert a unique identifier on each message. The identifier MUST
+%% remain locally unique for a period of at least 4 minutes, even
+%% across reboots. The originator of an Answer message MUST ensure
+%% that the End-to-End Identifier field contains the same value that
+%% was found in the corresponding request. The End-to-End Identifier
+%% MUST NOT be modified by Diameter agents of any kind. The
+%% combination of the Origin-Host (see Section 6.3) and this field is
+%% used to detect duplicates. Duplicate requests SHOULD cause the
+%% same answer to be transmitted (modulo the hop-by-hop Identifier
+%% field and any routing AVPs that may be present), and MUST NOT
+%% affect any state that was set when the original request was
+%% processed. Duplicate answer messages that are to be locally
+%% consumed (see Section 6.2) SHOULD be silently discarded.
+
+-spec sequence()
+ -> 'Unsigned32'().
+
+sequence() ->
+ Instr = {_Pos = 2, _Incr = 1, _Threshold = ?INT32, _SetVal = 0},
+ ets:update_counter(diameter_sequence, sequence, Instr).
+
+%% ---------------------------------------------------------------------------
+%% # origin_state_id/0
+%% ---------------------------------------------------------------------------
+
+%% 3588, 8.16:
+%%
+%% The Origin-State-Id AVP (AVP Code 278), of type Unsigned32, is a
+%% monotonically increasing value that is advanced whenever a Diameter
+%% entity restarts with loss of previous state, for example upon reboot.
+%% Origin-State-Id MAY be included in any Diameter message, including
+%% CER.
+%%
+%% A Diameter entity issuing this AVP MUST create a higher value for
+%% this AVP each time its state is reset. A Diameter entity MAY set
+%% Origin-State-Id to the time of startup, or it MAY use an incrementing
+%% counter retained in non-volatile memory across restarts.
+
+-spec origin_state_id()
+ -> 'Unsigned32'().
+
+origin_state_id() ->
+ ets:lookup_element(diameter_sequence, origin_state_id, 2).
+
+%% ---------------------------------------------------------------------------
+%% # session_id/1
+%% ---------------------------------------------------------------------------
+
+%% 3588, 8.8:
+%%
+%% The Session-Id MUST begin with the sender's identity encoded in the
+%% DiameterIdentity type (see Section 4.4). The remainder of the
+%% Session-Id is delimited by a ";" character, and MAY be any sequence
+%% that the client can guarantee to be eternally unique; however, the
+%% following format is recommended, (square brackets [] indicate an
+%% optional element):
+%%
+%% <DiameterIdentity>;<high 32 bits>;<low 32 bits>[;<optional value>]
+%%
+%% <high 32 bits> and <low 32 bits> are decimal representations of the
+%% high and low 32 bits of a monotonically increasing 64-bit value. The
+%% 64-bit value is rendered in two part to simplify formatting by 32-bit
+%% processors. At startup, the high 32 bits of the 64-bit value MAY be
+%% initialized to the time, and the low 32 bits MAY be initialized to
+%% zero. This will for practical purposes eliminate the possibility of
+%% overlapping Session-Ids after a reboot, assuming the reboot process
+%% takes longer than a second. Alternatively, an implementation MAY
+%% keep track of the increasing value in non-volatile memory.
+%%
+%% <optional value> is implementation specific but may include a modem's
+%% device Id, a layer 2 address, timestamp, etc.
+
+-spec session_id('DiameterIdentity'())
+ -> 'OctetString'().
+%% Note that Session-Id has type UTF8String and that any OctetString
+%% is a UTF8String.
+
+session_id(Host) ->
+ Instr = {_Pos = 2, _Incr = 1, _Threshold = ?INT64, _Set = 0},
+ N = ets:update_counter(diameter_sequence, session_base, Instr),
+ Hi = N bsr 32,
+ Lo = N band ?INT32,
+ [Host, ";", integer_to_list(Hi),
+ ";", integer_to_list(Lo),
+ ";", atom_to_list(node())].
+
+%% ---------------------------------------------------------------------------
+%% # init/0
+%% ---------------------------------------------------------------------------
+
+init() ->
+ Now = now(),
+ random:seed(Now),
+ Time = time32(Now),
+ Seq = (?INT32 band (Time bsl 20)) bor (random:uniform(1 bsl 20) - 1),
+ ets:insert(diameter_sequence, [{origin_state_id, Time},
+ {session_base, Time bsl 32},
+ {sequence, Seq}]),
+ Time.
+
+%% ---------------------------------------------------------
+%% INTERNAL FUNCTIONS
+%% ---------------------------------------------------------
+
+%% The minimum value represented by a Time value. (See diameter_types.)
+%% 32 bits extends to 2104.
+-define(TIME0, 62105714048). %% {{1968,1,20},{3,14,8}}
+
+time32(Now) ->
+ Time = calendar:now_to_universal_time(Now),
+ Diff = calendar:datetime_to_gregorian_seconds(Time) - ?TIME0,
+ Diff band ?INT32.
diff --git a/lib/diameter/src/app/diameter_stats.erl b/lib/diameter/src/app/diameter_stats.erl
new file mode 100644
index 0000000000..71479afa95
--- /dev/null
+++ b/lib/diameter/src/app/diameter_stats.erl
@@ -0,0 +1,342 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Statistics collector.
+%%
+
+-module(diameter_stats).
+-compile({no_auto_import, [monitor/2]}).
+
+-behaviour(gen_server).
+
+-export([reg/1, reg/2,
+ incr/1, incr/2, incr/3,
+ read/1,
+ flush/0, flush/1]).
+
+%% supervisor callback
+-export([start_link/0]).
+
+%% gen_server callbacks
+-export([init/1,
+ terminate/2,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ code_change/3]).
+
+%% debug
+-export([state/0,
+ uptime/0]).
+
+-include("diameter_internal.hrl").
+
+%% ets table containing stats. reg(Pid, Ref) inserts a {Pid, Ref},
+%% incr(Counter, X, N) updates the counter keyed at {Counter, X}, and
+%% Pid death causes counters keyed on {Counter, Pid} to be deleted and
+%% added to those keyed on {Counter, Ref}.
+-define(TABLE, ?MODULE).
+
+%% Name of registered server.
+-define(SERVER, ?MODULE).
+
+%% Entries in the table.
+-define(REC(Key, Value), {Key, Value}).
+
+%% Server state.
+-record(state, {id = now()}).
+
+-type counter() :: any().
+-type contrib() :: any().
+
+%%% ---------------------------------------------------------------------------
+%%% # reg(Pid, Contrib)
+%%%
+%%% Description: Register a process as a contributor of statistics
+%%% associated with a specified term. Statistics can be
+%%% contributed by specifying either Pid or Contrib as
+%%% the second argument to incr/3. Statistics contributed
+%%% by Pid are folded into the corresponding entry for
+%%% Contrib when the process dies.
+%%%
+%%% Contrib can be any term but should not be a pid
+%%% passed as the first argument to reg/2. Subsequent
+%%% registrations for the same Pid overwrite the association
+%%% ---------------------------------------------------------------------------
+
+-spec reg(pid(), contrib())
+ -> true.
+
+reg(Pid, Contrib)
+ when is_pid(Pid) ->
+ call({reg, Pid, Contrib}).
+
+-spec reg(contrib())
+ -> true.
+
+reg(Ref) ->
+ reg(self(), Ref).
+
+%%% ---------------------------------------------------------------------------
+%%% # incr(Counter, Contrib, N)
+%%%
+%%% Description: Increment a counter for the specified contributor.
+%%%
+%%% Contrib will typically be an argument passed to reg/2
+%%% but there's nothing that requires this. In particular,
+%%% if Contrib is a pid that hasn't been registered then
+%%% counters are unaffected by the death of the process.
+%%% ---------------------------------------------------------------------------
+
+-spec incr(counter(), contrib(), integer())
+ -> integer().
+
+incr(Ctr, Contrib, N) ->
+ update_counter({Ctr, Contrib}, N).
+
+incr(Ctr, N)
+ when is_integer(N) ->
+ incr(Ctr, self(), N);
+
+incr(Ctr, Contrib) ->
+ incr(Ctr, Contrib, 1).
+
+incr(Ctr) ->
+ incr(Ctr, self(), 1).
+
+%%% ---------------------------------------------------------------------------
+%%% # read(Contribs)
+%%%
+%%% Description: Retrieve counters for the specified contributors.
+%%% ---------------------------------------------------------------------------
+
+-spec read([contrib()])
+ -> [{contrib(), [{counter(), integer()}]}].
+
+read(Contribs) ->
+ lists:foldl(fun(?REC({T,C}, N), D) -> orddict:append(C, {T,N}, D) end,
+ orddict:new(),
+ ets:select(?TABLE, [{?REC({'_', '$1'}, '_'),
+ [?ORCOND([{'=:=', '$1', {const, C}}
+ || C <- Contribs])],
+ ['$_']}])).
+
+%%% ---------------------------------------------------------------------------
+%%% # flush(Contrib)
+%%%
+%%% Description: Retrieve and delete statistics for the specified
+%%% contributor.
+%%%
+%%% If Contrib is a pid registered with reg/2 then statistics
+%%% for both and its associated contributor are retrieved.
+%%% ---------------------------------------------------------------------------
+
+-spec flush(contrib())
+ -> [{counter(), integer()}].
+
+flush(Contrib) ->
+ try
+ call({flush, Contrib})
+ catch
+ exit: _ ->
+ []
+ end.
+
+flush() ->
+ flush(self()).
+
+%%% ---------------------------------------------------------
+%%% EXPORTED INTERNAL FUNCTIONS
+%%% ---------------------------------------------------------
+
+start_link() ->
+ ServerName = {local, ?SERVER},
+ Module = ?MODULE,
+ Args = [],
+ Options = [{spawn_opt, diameter_lib:spawn_opts(server, [])}],
+ gen_server:start_link(ServerName, Module, Args, Options).
+
+state() ->
+ call(state).
+
+uptime() ->
+ call(uptime).
+
+%%% ----------------------------------------------------------
+%%% # init(_)
+%%%
+%%% Output: {ok, State}
+%%% ----------------------------------------------------------
+
+init([]) ->
+ ets:new(?TABLE, [named_table, ordered_set, public]),
+ {ok, #state{}}.
+
+%% ----------------------------------------------------------
+%% handle_call(Request, From, State)
+%% ----------------------------------------------------------
+
+handle_call(state, _, State) ->
+ {reply, State, State};
+
+handle_call(uptime, _, #state{id = Time} = State) ->
+ {reply, diameter_lib:now_diff(Time), State};
+
+handle_call({reg, Pid, Contrib}, _From, State) ->
+ monitor(not ets:member(?TABLE, Pid), Pid),
+ {reply, insert(?REC(Pid, Contrib)), State};
+
+handle_call({flush, Contrib}, _From, State) ->
+ {reply, fetch(Contrib), State};
+
+handle_call(Req, From, State) ->
+ ?UNEXPECTED([Req, From]),
+ {reply, nok, State}.
+
+%% ----------------------------------------------------------
+%% handle_cast(Request, State)
+%% ----------------------------------------------------------
+
+handle_cast({incr, Rec}, State) ->
+ update_counter(Rec),
+ {noreply, State};
+
+handle_cast(Msg, State) ->
+ ?UNEXPECTED([Msg]),
+ {noreply, State}.
+
+%% ----------------------------------------------------------
+%% handle_info(Request, State)
+%% ----------------------------------------------------------
+
+handle_info({'DOWN', _MRef, process, Pid, _}, State) ->
+ down(Pid),
+ {noreply, State};
+
+handle_info(Info, State) ->
+ ?UNEXPECTED([Info]),
+ {noreply, State}.
+
+%% ----------------------------------------------------------
+%% terminate(Reason, State)
+%% ----------------------------------------------------------
+
+terminate(_Reason, _State) ->
+ ok.
+
+%% ----------------------------------------------------------
+%% code_change(OldVsn, State, Extra)
+%% ----------------------------------------------------------
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%% ---------------------------------------------------------
+%%% INTERNAL FUNCTIONS
+%%% ---------------------------------------------------------
+
+%% monitor/2
+
+monitor(true, Pid) ->
+ erlang:monitor(process, Pid);
+monitor(false = No, _) ->
+ No.
+
+%% down/1
+
+down(Pid) ->
+ L = ets:match_object(?TABLE, ?REC({'_', Pid}, '_')),
+ [?REC(_, Ref) = T] = lookup(Pid),
+ fold(Ref, L),
+ delete_object(T),
+ delete(L).
+
+%% Fold Pid-based entries into Ref-based ones.
+fold(Ref, L) ->
+ lists:foreach(fun(?REC({K, _}, V)) -> update_counter({{K, Ref}, V}) end,
+ L).
+
+delete(Objs) ->
+ lists:foreach(fun delete_object/1, Objs).
+
+%% fetch/1
+
+fetch(X) ->
+ MatchSpec = [{?REC({'_', '$1'}, '_'),
+ [?ORCOND([{'==', '$1', {const, T}} || T <- [X | ref(X)]])],
+ ['$_']}],
+ L = ets:select(?TABLE, MatchSpec),
+ delete(L),
+ D = lists:foldl(fun sum/2, dict:new(), L),
+ dict:to_list(D).
+
+sum({{Ctr, _}, N}, Dict) ->
+ dict:update(Ctr, fun(V) -> V+N end, N, Dict).
+
+ref(Pid)
+ when is_pid(Pid) ->
+ ets:select(?TABLE, [{?REC(Pid, '$1'), [], ['$1']}]);
+ref(_) ->
+ [].
+
+%% update_counter/2
+%%
+%% From an arbitrary request process. Cast to the server process to
+%% insert a new element if the counter doesn't exists so that two
+%% processes don't do so simultaneously.
+
+update_counter(Key, N) ->
+ try
+ ets:update_counter(?TABLE, Key, N)
+ catch
+ error: badarg ->
+ cast({incr, ?REC(Key, N)})
+ end.
+
+%% update_counter/1
+%%
+%% From the server process.
+
+update_counter(?REC(Key, N) = T) ->
+ try
+ ets:update_counter(?TABLE, Key, N)
+ catch
+ error: badarg ->
+ insert(T)
+ end.
+
+insert(T) ->
+ ets:insert(?TABLE, T).
+
+lookup(Key) ->
+ ets:lookup(?TABLE, Key).
+
+delete_object(T) ->
+ ets:delete_object(?TABLE, T).
+
+%% cast/1
+
+cast(Msg) ->
+ gen_server:cast(?SERVER, Msg).
+
+%% call/1
+
+call(Request) ->
+ gen_server:call(?SERVER, Request, infinity).
diff --git a/lib/diameter/src/app/diameter_sup.erl b/lib/diameter/src/app/diameter_sup.erl
new file mode 100644
index 0000000000..e5afd23dcd
--- /dev/null
+++ b/lib/diameter/src/app/diameter_sup.erl
@@ -0,0 +1,101 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% The top supervisor for the diameter application.
+%%
+
+-module(diameter_sup).
+
+-behaviour(supervisor).
+
+%% interface
+-export([start_link/0, %% supervisor start
+ tree/0]). %% supervision tree
+
+%% supervisor callback
+-export([init/1]).
+
+-define(CHILDREN, [diameter_misc_sup,
+ diameter_watchdog_sup,
+ diameter_peer_fsm_sup,
+ diameter_transport_sup,
+ diameter_service_sup]).
+
+-define(TABLES, [{diameter_sequence, [set]},
+ {diameter_service, [set, {keypos, 3}]},
+ {diameter_request, [bag]},
+ {diameter_config, [bag, {keypos, 2}]}]).
+
+%% start_link/0
+
+start_link() ->
+ SupName = {local, ?MODULE},
+ supervisor:start_link(SupName, ?MODULE, []).
+
+%% init/1
+
+init([]) ->
+ ets_new(?TABLES),
+ diameter_session:init(),
+ Flags = {one_for_one, 1, 5},
+ ChildSpecs = lists:map(fun spec/1, ?CHILDREN),
+ {ok, {Flags, ChildSpecs}}.
+
+%% spec/1
+
+spec(Mod) ->
+ {Mod,
+ {Mod, start_link, []},
+ permanent,
+ 1000,
+ supervisor,
+ [Mod]}.
+
+%% ets_new/1
+
+ets_new(List)
+ when is_list(List) ->
+ lists:foreach(fun ets_new/1, List);
+
+ets_new({Table, Opts}) ->
+ ets:new(Table, [named_table, public | Opts]).
+
+%% tree/0
+
+tree() ->
+ [{?MODULE, whereis(?MODULE), tree(?MODULE)}].
+
+tree(Sup) ->
+ lists:map(fun t/1, supervisor:which_children(Sup)).
+
+t({Name, Pid, supervisor, _}) ->
+ t(Name, Pid, tree(Pid));
+t({Name, Pid, worker, _}) ->
+ t(Name, Pid).
+
+t(undefined, Pid, Children) ->
+ {Pid, Children};
+t(Name, Pid, Children) ->
+ {Name, Pid, Children}.
+
+t(undefined, Pid) ->
+ Pid;
+t(Name, Pid) ->
+ {Name, Pid}.
diff --git a/lib/diameter/src/app/diameter_sync.erl b/lib/diameter/src/app/diameter_sync.erl
new file mode 100644
index 0000000000..ce2db4b3a2
--- /dev/null
+++ b/lib/diameter/src/app/diameter_sync.erl
@@ -0,0 +1,550 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 module implements a server that serializes requests in named
+%% queues. A request is an MFA or fun and a name can be any term. A
+%% request is applied in a dedicated process that terminates when
+%% the request function returns.
+%%
+
+-module(diameter_sync).
+-behaviour(gen_server).
+
+-export([call/4, call/5,
+ cast/4, cast/5,
+ carp/1, carp/2]).
+
+%% supervisor callback
+-export([start_link/0]).
+
+%% gen_server interface
+-export([init/1,
+ terminate/2,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ code_change/3]).
+
+%% test/debug
+-export([state/0,
+ uptime/0,
+ flush/1,
+ pending/0,
+ pending/1,
+ queues/0,
+ pids/1]).
+
+-include("diameter_internal.hrl").
+
+%% Locally registered server name.
+-define(SERVER, ?MODULE).
+
+%% Message to the server to queue a request ...
+-define(REQUEST(CallOrCast, Name, Req, Max, Timeout),
+ {request, CallOrCast, Name, Req, Max, Timeout}).
+
+%% ... and to retrieve the pid of the prevailing request process.
+-define(CARP(Name),
+ {carp, Name}).
+
+%% Forever ...
+-define(TIMEOUT, 30000).
+
+%% Server state.
+-record(state,
+ {time = now(),
+ pending = 0 :: non_neg_integer(), %% outstanding requests
+ monitor = new() :: ets:tid(), %% MonitorRef -> {Name, From}
+ queue = new() :: ets:tid()}). %% Name -> queue of {Pid, Ref}
+
+%% ----------------------------------------------------------
+%% # call(Node, Name, Req, Max, Timeout)
+%% # call(Name, Req, Max, Timeout)
+%%
+%% Input: Name = term() identifying the queue in which the request is
+%% to be evaluated.
+%% Req = {M,F,A}
+%% | {Fun, Arg}
+%% | [Fun | Args]
+%% | Fun
+%% Max = Upper bound for the number of outstanding requests
+%% in the named queue for Req to be queued.
+%% If more than this number are in the queue then
+%% 'rejected' is returned to the caller. Can be any
+%% term but integer() | infinity is sufficient.
+%% Timeout = 32 bit integer() number of milliseconds after which
+%% request is cancelled (if not already started), causing
+%% 'timeout' to be returned to the caller.
+%% | infinity
+%%
+%% Output: Req() | rejected | timeout
+%%
+%% Description: Serialize a request in a named queue. Note that if
+%% 'timeout' is returned and the request itself does not
+%% return this atom then request has not been evaluated.
+%% ----------------------------------------------------------
+
+call(Name, Req, Max, Timeout) ->
+ call(node(), Name, Req, Max, Timeout).
+
+call(Node, Name, Req, Max, Timeout) ->
+ gen_call({?SERVER, Node}, ?REQUEST(call, Name, Req, Max, Timeout)).
+
+%%% ----------------------------------------------------------
+%%% # cast(Node, Name, Req, Max, Timeout)
+%%% # cast(Name, Req, Max, Timeout)
+%%%
+%%% Output: ok | rejected | timeout
+%%%
+%%% Description: Serialize a request without returning the result to the
+%%% caller. Returns after the task is queued.
+%%% ----------------------------------------------------------
+
+cast(Name, Req, Max, Timeout) ->
+ cast(node(), Name, Req, Max, Timeout).
+
+cast(Node, Name, Req, Max, Timeout) ->
+ gen_call({?SERVER, Node}, ?REQUEST(cast, Name, Req, Max, Timeout)).
+
+%% 'timeout' is only return if the server process that processes
+%% requests isn't alive. Ditto for call/carp.
+
+%%% ----------------------------------------------------------
+%%% # carp(Node, Name)
+%%% # carp(Name)
+%%%
+%%% Output: {value, Pid} | false | timeout
+%%%
+%%% Description: Return the pid of the process processing the task
+%%% at the head of the named queue. Note that the value
+%%% returned by subsequent calls changes as tasks are
+%%% completed, each task executing in a dedicated
+%%% process. The exit value of this process will be
+%%% {value, Req()} if the task returns.
+%%% ----------------------------------------------------------
+
+%% The intention of this is to let a process enqueue a task that waits
+%% for a message before completing, the target pid being retrieved
+%% with carp/[12].
+
+carp(Name) ->
+ carp(node(), Name).
+
+carp(Node, Name) ->
+ gen_call({?SERVER, Node}, ?CARP(Name)).
+
+%%% ---------------------------------------------------------
+%%% EXPORTED INTERNAL FUNCTIONS
+%%% ---------------------------------------------------------
+
+state() ->
+ call(state).
+
+uptime() ->
+ call(uptime).
+
+flush(Name) ->
+ call({flush, Name}).
+
+pending() ->
+ call(pending).
+
+pending(Name) ->
+ call({pending, Name}).
+
+queues() ->
+ call(queues).
+
+pids(Name) ->
+ call({pids, Name}).
+
+%%% ----------------------------------------------------------
+%%% # start_link()
+%%% ----------------------------------------------------------
+
+start_link() ->
+ ServerName = {local, ?SERVER},
+ Module = ?MODULE,
+ Args = [],
+ Options = [{spawn_opt, diameter_lib:spawn_opts(server, [])}],
+ gen_server:start_link(ServerName, Module, Args, Options).
+
+%%% ----------------------------------------------------------
+%%% # init(_)
+%%% ----------------------------------------------------------
+
+init(_) ->
+ {ok, #state{}}.
+
+%%% ----------------------------------------------------------
+%%% # handle_call(Request, From, State)
+%%% ----------------------------------------------------------
+
+%% Enqueue a new request.
+handle_call(?REQUEST(Type, Name, Req, Max, Timeout),
+ From,
+ #state{queue = QD} = State) ->
+ T = find(Name, QD),
+ nq(queued(T) =< Max, T, {Type, From}, Name, Req, Timeout, State);
+
+handle_call(Request, From, State) ->
+ {reply, call(Request, From, State), State}.
+
+%% call/3
+
+call(?CARP(Name), _, #state{queue = QD}) ->
+ pcar(find(Name, QD));
+
+call(state, _, State) ->
+ State;
+
+call(uptime, _, #state{time = T}) ->
+ diameter_lib:now_diff(T);
+
+call({flush, Name}, _, #state{queue = QD}) ->
+ cancel(find(Name, QD));
+
+call(pending, _, #state{pending = N}) ->
+ N;
+
+call({pending, Name}, _, #state{queue = QD}) ->
+ queued(find(Name, QD));
+
+call(queues, _, #state{queue = QD}) ->
+ fetch_keys(QD);
+
+call({pids, Name}, _, #state{queue = QD}) ->
+ plist(find(Name, QD));
+
+call(Req, From, _State) -> %% ignore
+ ?UNEXPECTED(handle_call, [Req, From]),
+ nok.
+
+%%% ----------------------------------------------------------
+%%% handle_cast(Request, State)
+%%% ----------------------------------------------------------
+
+handle_cast(Msg, State) ->
+ ?UNEXPECTED([Msg]),
+ {noreply, State}.
+
+%%% ----------------------------------------------------------
+%%% handle_info(Request, State)
+%%% ----------------------------------------------------------
+
+handle_info(Request, State) ->
+ {noreply, info(Request, State)}.
+
+%% info/2
+
+%% A request has completed execution or timed out.
+info({'DOWN', MRef, process, Pid, Info},
+ #state{pending = N,
+ monitor = MD,
+ queue = QD}
+ = State) ->
+ {Name, From} = fetch(MRef, MD),
+ reply(From, rc(Info)),
+ State#state{pending = N-1,
+ monitor = erase(MRef, MD),
+ queue = dq(fetch(Name, QD), Pid, Info, Name, QD)};
+
+info(Info, State) ->
+ ?UNEXPECTED(handle_info, [Info]),
+ State.
+
+reply({call, From}, T) ->
+ gen_server:reply(From, T);
+reply(cast, _) ->
+ ok.
+
+rc({value, T}) ->
+ T;
+rc(_) ->
+ timeout.
+
+%%% ----------------------------------------------------------
+%%% code_change(OldVsn, State, Extra)
+%%% ----------------------------------------------------------
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%% ----------------------------------------------------------
+%%% terminate(Reason, State)
+%%% ----------------------------------------------------------
+
+terminate(_Reason, _State)->
+ ok.
+
+%%% ---------------------------------------------------------
+%%% INTERNAL FUNCTIONS
+%%% ---------------------------------------------------------
+
+%% queued/1
+
+queued({ok, {N,_}}) ->
+ N;
+queued(error) ->
+ 0.
+
+%% nq/7
+
+%% Maximum number of pending requests exceeded ...
+nq(false, _, _, _Name, _Req, _Timeout, State) ->
+ {reply, rejected, State};
+
+%% ... or not.
+nq(true, T, From, Name, Req, Timeout, #state{pending = N,
+ monitor = MD,
+ queue = QD}
+ = State) ->
+ Ref = make_ref(),
+ Pid = init(Ref, Req, timeout(Timeout, T)),
+ MRef = erlang:monitor(process, Pid),
+ {noreply, State#state{pending = N+1,
+ monitor = store(MRef, {Name, from(From)}, MD),
+ queue = store(Name, nq(T, {Pid, Ref}), QD)}}.
+
+from({call, _} = T) ->
+ T;
+from({cast = T, From}) ->
+ gen_server:reply(From, ok),
+ T.
+
+%% nq/2
+
+%% Other requests in the queue: append.
+nq({ok, {N,Q}}, T) ->
+ {N+1, queue:in(T,Q)};
+
+%% Queue is empty: start execution.
+nq(error, T) ->
+ go(T),
+ {1, queue:from_list([T])}.
+
+%% Don't timeout if the request is evaluated immediately so as to
+%% avoid a race between getting a 'go' and a 'timeout'. Queueing a
+%% request in an empty queue always results in execution.
+timeout(_, error) ->
+ infinity;
+timeout(Timeout, _) ->
+ Timeout.
+
+%% dq/5
+%%
+%% A request process has terminated.
+
+dq({N,Q}, Pid, _Info, Name, QD) ->
+ {{value, T}, TQ} = queue:out(Q),
+ dq(N-1, Pid, T, TQ, Name, QD).
+
+%% dq/6
+
+%% Request was at the head of the queue: start another.
+dq(N, Pid, {Pid, _}, TQ, Name, QD) ->
+ dq(N, TQ, Name, QD);
+
+%% Or not: remove the offender from the queue.
+dq(N, Pid, T, TQ, Name, QD) ->
+ store(Name, {N, req(Pid, queue:from_list([T]), TQ)}, QD).
+
+%% dq/4
+
+%% Queue is empty: erase.
+dq(0, TQ, Name, QD) ->
+ true = queue:is_empty(TQ), %% assert
+ erase(Name, QD);
+
+%% Start the next request.
+dq(N, TQ, Name, QD) ->
+ go(queue:head(TQ)),
+ store(Name, {N, TQ}, QD).
+
+%% req/3
+%%
+%% Find and remove the queue element for the specified pid.
+
+req(Pid, HQ, Q) ->
+ {{value, T}, TQ} = queue:out(Q),
+ req(Pid, T, HQ, TQ).
+
+req(Pid, {Pid, _}, HQ, TQ) ->
+ queue:join(HQ, TQ);
+req(Pid, T, HQ, TQ) ->
+ req(Pid, queue:in(T,HQ), TQ).
+
+%% go/1
+
+go({Pid, Ref}) ->
+ Pid ! {Ref, ok}.
+
+%% init/4
+%%
+%% Start the dedicated process for handling a request. The exit value
+%% is as promised by carp/1.
+
+init(Ref, Req, Timeout) ->
+ spawn(fun() -> exit(i(Ref, Req, Timeout)) end).
+
+i(Ref, Req, Timeout) ->
+ Timer = send_timeout(Ref, Timeout),
+ MRef = erlang:monitor(process, ?SERVER),
+ receive
+ {Ref, ok} -> %% Do the deed.
+ %% Ensure we don't leave messages in the mailbox since the
+ %% request itself might receive. Alternatively, could have
+ %% done the eval in a new process but then we'd have to
+ %% relay messages arriving at this one.
+ cancel_timer(Timer),
+ erlang:demonitor(MRef, [flush]),
+ %% Ref is to ensure that we don't extract any message that
+ %% a client may have sent after retrieving self() with
+ %% carp/1, there being no guarantee that the message
+ %% banged by go/1 is received before the pid becomes
+ %% accessible.
+ {value, eval(Req)};
+ {Ref, timeout = T} ->
+ T;
+ {'DOWN', MRef, process, _Pid, _Info} = D -> %% server death
+ D
+ end.
+
+send_timeout(_Ref, infinity = No) ->
+ No;
+send_timeout(Ref, Ms) ->
+ Msg = {Ref, timeout},
+ TRef = erlang:send_after(Ms, self(), Msg),
+ {TRef, Msg}.
+
+cancel_timer(infinity = No) ->
+ No;
+cancel_timer({TRef, Msg}) ->
+ flush(Msg, erlang:cancel_timer(TRef)).
+
+flush(Msg, false) -> %% Message has already been sent ...
+ %% 'error' should never happen but crash if it does so as not to
+ %% hang the process.
+ ok = receive Msg -> ok after ?TIMEOUT -> error end;
+flush(_, _) -> %% ... or not.
+ ok.
+
+eval({M,F,A}) ->
+ apply(M,F,A);
+eval([Fun | Args]) ->
+ apply(Fun, Args);
+eval({Fun, A}) ->
+ Fun(A);
+eval(Fun) ->
+ Fun().
+
+%% pcar/1
+
+pcar({ok, {_,Q}}) ->
+ {Pid, _Ref} = queue:head(Q),
+ {value, Pid};
+pcar(error) ->
+ false.
+
+%% plist/1
+
+plist({ok, {_,Q}}) ->
+ lists:map(fun({Pid, _Ref}) -> Pid end, queue:to_list(Q));
+plist(error) ->
+ [].
+
+%% cancel/1
+%%
+%% Cancel all but the active request from the named queue. Return the
+%% number of requests cancelled.
+
+%% Just send timeout messages to each request to make them die. Note
+%% that these are guaranteed to arrive before a go message after the
+%% current request completes since both messages are sent from the
+%% server process.
+cancel({ok, {N,Q}}) ->
+ {_,TQ} = queue:split(1,Q),
+ foreach(fun({Pid, Ref}) -> Pid ! {Ref, timeout} end, N-1, TQ),
+ N-1;
+cancel(error) ->
+ 0.
+
+%% foreach/3
+
+foreach(_, 0, _) ->
+ ok;
+foreach(Fun, N, Q) ->
+ Fun(queue:head(Q)),
+ foreach(Fun, N-1, queue:tail(Q)).
+
+%% call/1
+
+%% gen_server:call/3 will exit if the target process dies.
+call(Request) ->
+ try
+ gen_server:call(?SERVER, Request, ?TIMEOUT)
+ catch
+ exit: Reason ->
+ {error, Reason}
+ end.
+
+%% dict-like table manipulation.
+
+erase(Key, Dict) ->
+ ets:delete(Dict, Key),
+ Dict.
+
+fetch(Key, Dict) ->
+ {ok, V} = find(Key, Dict),
+ V.
+
+fetch_keys(Dict) ->
+ ets:foldl(fun({K,_}, Acc) -> [K | Acc] end, [], Dict).
+
+find(Key, Dict) ->
+ case ets:lookup(Dict, Key) of
+ [{Key, V}] ->
+ {ok, V};
+ [] ->
+ error
+ end.
+
+new() ->
+ ets:new(?MODULE, [set]).
+
+store(Key, Value, Dict) ->
+ store({Key, Value}, Dict).
+
+store({_,_} = T, Dict) ->
+ ets:insert(Dict, T),
+ Dict.
+
+%% gen_call/1
+
+gen_call(Server, Req) ->
+ gen_call(Server, Req, infinity).
+
+gen_call(Server, Req, Timeout) ->
+ try
+ gen_server:call(Server, Req, Timeout)
+ catch
+ exit: _ ->
+ timeout
+ end.
diff --git a/lib/diameter/src/app/diameter_types.erl b/lib/diameter/src/app/diameter_types.erl
new file mode 100644
index 0000000000..6b1b1b8d39
--- /dev/null
+++ b/lib/diameter/src/app/diameter_types.erl
@@ -0,0 +1,537 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_types).
+
+%%
+%% Encode/decode of RFC 3588 Data Formats, Basic (section 4.2) and
+%% Derived (section 4.3).
+%%
+
+%% Basic types.
+-export(['OctetString'/2,
+ 'Integer32'/2,
+ 'Integer64'/2,
+ 'Unsigned32'/2,
+ 'Unsigned64'/2,
+ 'Float32'/2,
+ 'Float64'/2]).
+
+%% Derived types.
+-export(['Address'/2,
+ 'Time'/2,
+ 'UTF8String'/2,
+ 'DiameterIdentity'/2,
+ 'DiameterURI'/2,
+ 'IPFilterRule'/2,
+ 'QoSFilterRule'/2]).
+
+-include_lib("diameter/include/diameter.hrl").
+-include("diameter_internal.hrl").
+
+-define(UINT(N,X), ((0 =< X) andalso (X < 1 bsl N))).
+-define(SINT(N,X), ((-1*(1 bsl (N-1)) < X) andalso (X < 1 bsl (N-1)))).
+
+%% The Grouped and Enumerated types are dealt with directly in
+%% generated decode modules by way of diameter_gen.hrl and
+%% diameter_codec.erl. Padding and the setting of Length and other
+%% fields are also dealt with there.
+
+%% 3588:
+%%
+%% DIAMETER_INVALID_AVP_LENGTH 5014
+%% The request contained an AVP with an invalid length. A Diameter
+%% message indicating this error MUST include the offending AVPs
+%% within a Failed-AVP AVP.
+%%
+-define(INVALID_LENGTH(Bin), erlang:error({'DIAMETER', 5014, Bin})).
+
+%% -------------------------------------------------------------------------
+%% 3588, 4.2. Basic AVP Data Formats
+%%
+%% The Data field is zero or more octets and contains information
+%% specific to the Attribute. The format and length of the Data field
+%% is determined by the AVP Code and AVP Length fields. The format of
+%% the Data field MUST be one of the following base data types or a data
+%% type derived from the base data types. In the event that a new Basic
+%% AVP Data Format is needed, a new version of this RFC must be created.
+%% --------------------
+
+'OctetString'(decode, Bin)
+ when is_binary(Bin) ->
+ binary_to_list(Bin);
+
+'OctetString'(encode = M, zero) ->
+ 'OctetString'(M, []);
+
+'OctetString'(encode, Str) ->
+ iolist_to_binary(Str).
+
+%% --------------------
+
+'Integer32'(decode, <<X:32/signed>>) ->
+ X;
+
+'Integer32'(decode, B) ->
+ ?INVALID_LENGTH(B);
+
+'Integer32'(encode = M, zero) ->
+ 'Integer32'(M, 0);
+
+'Integer32'(encode, I)
+ when ?SINT(32,I) ->
+ <<I:32/signed>>.
+
+%% --------------------
+
+'Integer64'(decode, <<X:64/signed>>) ->
+ X;
+
+'Integer64'(decode, B) ->
+ ?INVALID_LENGTH(B);
+
+'Integer64'(encode = M, zero) ->
+ 'Integer64'(M, 0);
+
+'Integer64'(encode, I)
+ when ?SINT(64,I) ->
+ <<I:64/signed>>.
+
+%% --------------------
+
+'Unsigned32'(decode, <<X:32>>) ->
+ X;
+
+'Unsigned32'(decode, B) ->
+ ?INVALID_LENGTH(B);
+
+'Unsigned32'(encode = M, zero) ->
+ 'Unsigned32'(M, 0);
+
+'Unsigned32'(encode, I)
+ when ?UINT(32,I) ->
+ <<I:32>>.
+
+%% --------------------
+
+'Unsigned64'(decode, <<X:64>>) ->
+ X;
+
+'Unsigned64'(decode, B) ->
+ ?INVALID_LENGTH(B);
+
+'Unsigned64'(encode = M, zero) ->
+ 'Unsigned64'(M, 0);
+
+'Unsigned64'(encode, I)
+ when ?UINT(64,I) ->
+ <<I:64>>.
+
+%% --------------------
+
+%% Decent summaries of the IEEE floating point formats can be
+%% found at http://en.wikipedia.org/wiki/IEEE_754-1985 and
+%% http://www.psc.edu/general/software/packages/ieee/ieee.php.
+%%
+%% That the bit syntax uses these formats isn't well documented but
+%% this does indeed appear to be the case. However, the bit syntax
+%% only encodes numeric values, not the standard's (signed) infinity
+%% or NaN. It also encodes any large value as 'infinity', never 'NaN'.
+%% Treat these equivalently on decode for this reason.
+%%
+%% An alternative would be to decode infinity/NaN to the largest
+%% possible float but could likely lead to misleading results if
+%% arithmetic is performed on the decoded value. Better to be explicit
+%% that precision has been lost.
+
+'Float32'(decode, <<S:1, 255:8, _:23>>) ->
+ choose(S, infinity, '-infinity');
+
+'Float32'(decode, <<X:32/float>>) ->
+ X;
+
+'Float32'(decode, B) ->
+ ?INVALID_LENGTH(B);
+
+'Float32'(encode = M, zero) ->
+ 'Float32'(M, 0.0);
+
+'Float32'(encode, infinity) ->
+ <<0:1, 255:8, 0:23>>;
+
+'Float32'(encode, '-infinity') ->
+ <<1:1, 255:8, 0:23>>;
+
+'Float32'(encode, X)
+ when is_float(X) ->
+ <<X:32/float>>.
+%% Note that this could also encode infinity/-infinity for large
+%% (signed) numeric values. Note also that precision is lost just in
+%% using the floating point syntax. For example:
+%%
+%% 1> B = <<3.14159:32/float>>.
+%% <<64,73,15,208>>
+%% 2> <<F:32/float>> = B.
+%% <<64,73,15,208>>
+%% 3> F.
+%% 3.141590118408203
+%%
+%% (The 64 bit type does better.)
+
+%% --------------------
+
+%% The 64 bit format is entirely analogous to the 32 bit format.
+
+'Float64'(decode, <<S:1, 2047:11, _:52>>) ->
+ choose(S, infinity, '-infinity');
+
+'Float64'(decode, <<X:64/float>>) ->
+ X;
+
+'Float64'(decode, B) ->
+ ?INVALID_LENGTH(B);
+
+'Float64'(encode, infinity) ->
+ <<0:1, 2047:11, 0:52>>;
+
+'Float64'(encode, '-infinity') ->
+ <<1:1, 2047:11, 0:52>>;
+
+'Float64'(encode = M, zero) ->
+ 'Float64'(M, 0.0);
+
+'Float64'(encode, X)
+ when is_float(X) ->
+ <<X:64/float>>.
+
+%% -------------------------------------------------------------------------
+%% 3588, 4.3. Derived AVP Data Formats
+%%
+%% In addition to using the Basic AVP Data Formats, applications may
+%% define data formats derived from the Basic AVP Data Formats. An
+%% application that defines new AVP Derived Data Formats MUST include
+%% them in a section entitled "AVP Derived Data Formats", using the same
+%% format as the definitions below. Each new definition must be either
+%% defined or listed with a reference to the RFC that defines the
+%% format.
+%% --------------------
+
+'Address'(encode, zero) ->
+ <<0:48>>;
+
+'Address'(decode, <<1:16, B/binary>>)
+ when size(B) == 4 ->
+ list_to_tuple(binary_to_list(B));
+
+'Address'(decode, <<2:16, B/binary>>)
+ when size(B) == 16 ->
+ list_to_tuple(v6dec(B, []));
+
+'Address'(decode, <<A:16, _/binary>> = B)
+ when 1 == A;
+ 2 == A ->
+ ?INVALID_LENGTH(B);
+
+'Address'(encode, T) ->
+ ipenc(diameter_lib:ipaddr(T)).
+
+ipenc(T)
+ when is_tuple(T), size(T) == 4 ->
+ B = list_to_binary(tuple_to_list(T)),
+ <<1:16, B/binary>>;
+
+ipenc(T)
+ when is_tuple(T), size(T) == 8 ->
+ B = v6enc(lists:reverse(tuple_to_list(T)), <<>>),
+ <<2:16, B/binary>>.
+
+v6dec(<<N:16, B/binary>>, Acc) ->
+ v6dec(B, [N | Acc]);
+
+v6dec(<<>>, Acc) ->
+ lists:reverse(Acc).
+
+v6enc([N | Rest], B)
+ when ?UINT(16,N) ->
+ v6enc(Rest, <<N:16, B/binary>>);
+
+v6enc([], B) ->
+ B.
+
+%% --------------------
+
+%% A DiameterIdentity is a FQDN as definined in RFC 1035, which is at
+%% least one character.
+
+'DiameterIdentity'(encode = M, zero) ->
+ 'OctetString'(M, [0]);
+
+'DiameterIdentity'(encode = M, X) ->
+ <<_,_/binary>> = 'OctetString'(M, X);
+
+'DiameterIdentity'(decode = M, <<_,_/binary>> = X) ->
+ 'OctetString'(M, X).
+
+%% --------------------
+
+'DiameterURI'(decode, Bin)
+ when is_binary(Bin) ->
+ scan_uri(Bin);
+
+%% The minimal DiameterURI is "aaa://x", 7 characters.
+'DiameterURI'(encode = M, zero) ->
+ 'OctetString'(M, lists:duplicate(0,7));
+
+'DiameterURI'(encode, #diameter_uri{type = Type,
+ fqdn = D,
+ port = P,
+ transport = T,
+ protocol = Prot}
+ = U) ->
+ S = lists:append([atom_to_list(Type), "://", D,
+ ":", integer_to_list(P),
+ ";transport=", atom_to_list(T),
+ ";protocol=", atom_to_list(Prot)]),
+ U = scan_uri(S), %% assert
+ list_to_binary(S);
+
+'DiameterURI'(encode, Str) ->
+ Bin = iolist_to_binary(Str),
+ #diameter_uri{} = scan_uri(Bin), %% type check
+ Bin.
+
+%% --------------------
+
+%% This minimal rule is "deny in 0 from 0.0.0.0 to 0.0.0.0", 33 characters.
+'IPFilterRule'(encode = M, zero) ->
+ 'OctetString'(M, lists:duplicate(0,33));
+
+%% TODO: parse grammar.
+'IPFilterRule'(M, X) ->
+ 'OctetString'(M, X).
+
+%% --------------------
+
+%% This minimal rule is the same as for an IPFilterRule.
+'QoSFilterRule'(encode = M, zero = X) ->
+ 'IPFilterRule'(M, X);
+
+%% TODO: parse grammar.
+'QoSFilterRule'(M, X) ->
+ 'OctetString'(M, X).
+
+%% --------------------
+
+'UTF8String'(decode, Bin) ->
+ udec(Bin, []);
+
+'UTF8String'(encode = M, zero) ->
+ 'UTF8String'(M, []);
+
+'UTF8String'(encode, S) ->
+ uenc(S, []).
+
+udec(<<>>, Acc) ->
+ lists:reverse(Acc);
+
+udec(<<C/utf8, Rest/binary>>, Acc) ->
+ udec(Rest, [C | Acc]).
+
+uenc(E, Acc)
+ when E == [];
+ E == <<>> ->
+ list_to_binary(lists:reverse(Acc));
+
+uenc(<<C/utf8, Rest/binary>>, Acc) ->
+ uenc(Rest, [<<C/utf8>> | Acc]);
+
+uenc([[] | Rest], Acc) ->
+ uenc(Rest, Acc);
+
+uenc([[H|T] | Rest], Acc) ->
+ uenc([H, T | Rest], Acc);
+
+uenc([C | Rest], Acc) ->
+ uenc(Rest, [<<C/utf8>> | Acc]).
+
+%% --------------------
+
+%% RFC 3588, 4.3:
+%%
+%% Time
+%% The Time format is derived from the OctetString AVP Base Format.
+%% The string MUST contain four octets, in the same format as the
+%% first four bytes are in the NTP timestamp format. The NTP
+%% Timestamp format is defined in chapter 3 of [SNTP].
+%%
+%% This represents the number of seconds since 0h on 1 January 1900
+%% with respect to the Coordinated Universal Time (UTC).
+%%
+%% On 6h 28m 16s UTC, 7 February 2036 the time value will overflow.
+%% SNTP [SNTP] describes a procedure to extend the time to 2104.
+%% This procedure MUST be supported by all DIAMETER nodes.
+
+%% RFC 2030, 3:
+%%
+%% As the NTP timestamp format has been in use for the last 17 years,
+%% it remains a possibility that it will be in use 40 years from now
+%% when the seconds field overflows. As it is probably inappropriate
+%% to archive NTP timestamps before bit 0 was set in 1968, a
+%% convenient way to extend the useful life of NTP timestamps is the
+%% following convention: If bit 0 is set, the UTC time is in the
+%% range 1968-2036 and UTC time is reckoned from 0h 0m 0s UTC on 1
+%% January 1900. If bit 0 is not set, the time is in the range 2036-
+%% 2104 and UTC time is reckoned from 6h 28m 16s UTC on 7 February
+%% 2036. Note that when calculating the correspondence, 2000 is not a
+%% leap year. Note also that leap seconds are not counted in the
+%% reckoning.
+%%
+%% The statement regarding year 2000 is wrong: errata id 518 at
+%% http://www.rfc-editor.org/errata_search.php?rfc=2030 notes this.
+
+-define(TIME_1900, 59958230400). %% {{1900,1,1},{0,0,0}}
+-define(TIME_2036, 64253197696). %% {{2036,2,7},{6,28,16}}
+%% TIME_2036 = TIME_1900 + (1 bsl 32)
+
+%% Time maps [0, 1 bsl 31) onto [TIME_1900 + 1 bsl 31, TIME_2036 + 1 bsl 31)
+%% by taking integers with the high-order bit set relative to TIME_1900
+%% and those without relative to TIME_2036. This corresponds to the
+%% following dates.
+-define(TIME_MIN, {{1968,1,20},{3,14,8}}). %% TIME_1900 + 1 bsl 31
+-define(TIME_MAX, {{2104,2,26},{9,42,24}}). %% TIME_2036 + 1 bsl 31
+
+'Time'(decode, <<Time:32>>) ->
+ Offset = msb(1 == Time bsr 31),
+ calendar:gregorian_seconds_to_datetime(Time + Offset);
+
+'Time'(decode, B) ->
+ ?INVALID_LENGTH(B);
+
+'Time'(encode, {{_Y,_M,_D},{_HH,_MM,_SS}} = Datetime)
+ when ?TIME_MIN =< Datetime, Datetime < ?TIME_MAX ->
+ S = calendar:datetime_to_gregorian_seconds(Datetime),
+ T = S - msb(S < ?TIME_2036),
+ 0 = T bsr 32, %% sanity check
+ <<T:32>>;
+
+'Time'(encode, zero) ->
+ <<0:32>>.
+
+%% ===========================================================================
+%% ===========================================================================
+
+choose(0, X, _) -> X;
+choose(1, _, X) -> X.
+
+msb(true) -> ?TIME_1900;
+msb(false) -> ?TIME_2036.
+
+%% RFC 3588, 4.3:
+%%
+%% The DiameterURI MUST follow the Uniform Resource Identifiers (URI)
+%% syntax [URI] rules specified below:
+%%
+%% "aaa://" FQDN [ port ] [ transport ] [ protocol ]
+%%
+%% ; No transport security
+%%
+%% "aaas://" FQDN [ port ] [ transport ] [ protocol ]
+%%
+%% ; Transport security used
+%%
+%% FQDN = Fully Qualified Host Name
+%%
+%% port = ":" 1*DIGIT
+%%
+%% ; One of the ports used to listen for
+%% ; incoming connections.
+%% ; If absent,
+%% ; the default Diameter port (3868) is
+%% ; assumed.
+%%
+%% transport = ";transport=" transport-protocol
+%%
+%% ; One of the transports used to listen
+%% ; for incoming connections. If absent,
+%% ; the default SCTP [SCTP] protocol is
+%% ; assumed. UDP MUST NOT be used when
+%% ; the aaa-protocol field is set to
+%% ; diameter.
+%%
+%% transport-protocol = ( "tcp" / "sctp" / "udp" )
+%%
+%% protocol = ";protocol=" aaa-protocol
+%%
+%% ; If absent, the default AAA protocol
+%% ; is diameter.
+%%
+%% aaa-protocol = ( "diameter" / "radius" / "tacacs+" )
+
+scan_uri(Bin)
+ when is_binary(Bin) ->
+ scan_uri(binary_to_list(Bin));
+scan_uri("aaa://" ++ Rest) ->
+ scan_fqdn(Rest, #diameter_uri{type = aaa});
+scan_uri("aaas://" ++ Rest) ->
+ scan_fqdn(Rest, #diameter_uri{type = aaas}).
+
+scan_fqdn(S, U) ->
+ {[_|_] = F, Rest} = lists:splitwith(fun is_fqdn/1, S),
+ scan_opt_port(Rest, U#diameter_uri{fqdn = F}).
+
+scan_opt_port(":" ++ S, U) ->
+ {[_|_] = P, Rest} = lists:splitwith(fun is_digit/1, S),
+ scan_opt_transport(Rest, U#diameter_uri{port = list_to_integer(P)});
+scan_opt_port(S, U) ->
+ scan_opt_transport(S, U).
+
+scan_opt_transport(";transport=" ++ S, U) ->
+ {P, Rest} = transport(S),
+ scan_opt_protocol(Rest, U#diameter_uri{transport = P});
+scan_opt_transport(S, U) ->
+ scan_opt_protocol(S, U).
+
+scan_opt_protocol(";protocol=" ++ S, U) ->
+ {P, ""} = protocol(S),
+ U#diameter_uri{protocol = P};
+scan_opt_protocol("", U) ->
+ U.
+
+transport("tcp" ++ S) ->
+ {tcp, S};
+transport("sctp" ++ S) ->
+ {sctp, S};
+transport("udp" ++ S) ->
+ {udp, S}.
+
+protocol("diameter" ++ S) ->
+ {diameter, S};
+protocol("radius" ++ S) ->
+ {radius, S};
+protocol("tacacs+" ++ S) ->
+ {'tacacs+', S}.
+
+is_fqdn(C) ->
+ is_digit(C) orelse is_alpha(C) orelse C == $. orelse C == $-.
+
+is_alpha(C) ->
+ ($a =< C andalso C =< $z) orelse ($A =< C andalso C =< $Z).
+
+is_digit(C) ->
+ $0 =< C andalso C =< $9.
diff --git a/lib/diameter/src/app/diameter_types.hrl b/lib/diameter/src/app/diameter_types.hrl
new file mode 100644
index 0000000000..02bf8a74dd
--- /dev/null
+++ b/lib/diameter/src/app/diameter_types.hrl
@@ -0,0 +1,139 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Types for function specifications, primarily in diameter.erl. This
+%% has nothing specifically to do with diameter_types.erl.
+%%
+
+-type evaluable()
+ :: {module(), atom(), list()}
+ | fun()
+ | nonempty_improper_list(evaluable(), list()). %% [evaluable() | Args]
+
+-type app_alias()
+ :: any().
+
+-type service_name()
+ :: any().
+
+%% Diameter basic types
+
+-type 'OctetString'() :: iolist().
+-type 'Integer32'() :: -2147483647..2147483647.
+-type 'Integer64'() :: -9223372036854775807..9223372036854775807.
+-type 'Unsigned32'() :: 0..4294967295.
+-type 'Unsigned64'() :: 0..18446744073709551615.
+-type 'Float32'() :: '-infinity' | float() | infinity.
+-type 'Float64'() :: '-infinity' | float() | infinity.
+-type 'Grouped'() :: list() | tuple().
+
+%% Diameter derived types
+
+-type 'Address'()
+ :: inet:ip_address()
+ | string().
+
+-type 'Time'() :: {{integer(), 1..12, 1..31},
+ {0..23, 0..59, 0..59}}.
+-type 'UTF8String'() :: iolist().
+-type 'DiameterIdentity'() :: 'OctetString'().
+-type 'DiameterURI'() :: 'OctetString'().
+-type 'Enumerated'() :: 'Integer32'().
+-type 'IPFilterRule'() :: 'OctetString'().
+-type 'QoSFilterRule'() :: 'OctetString'().
+
+%% Capabilities options/avps on start_service/2 and/or add_transport/2
+
+-type capability()
+ :: {'Origin-Host', 'DiameterIdentity'()}
+ | {'Origin-Realm', 'DiameterIdentity'()}
+ | {'Host-IP-Address', ['Address'()]}
+ | {'Vendor-Id', 'Unsigned32'()}
+ | {'Product-Name', 'UTF8String'()}
+ | {'Supported-Vendor-Id', ['Unsigned32'()]}
+ | {'Auth-Application-Id', ['Unsigned32'()]}
+ | {'Vendor-Specific-Application-Id', ['Grouped'()]}
+ | {'Firmware-Revision', 'Unsigned32'()}.
+
+%% Filters for call/4
+
+-type peer_filter()
+ :: none
+ | host
+ | realm
+ | {host, any|'DiameterIdentity'()}
+ | {realm, any|'DiameterIdentity'()}
+ | {eval, evaluable()}
+ | {neg, peer_filter()}
+ | {all, [peer_filter()]}
+ | {any, [peer_filter()]}.
+
+%% Options passed to start_service/2
+
+-type service_opt()
+ :: capability()
+ | {application, [application_opt()]}.
+
+-type application_opt()
+ :: {alias, app_alias()}
+ | {dictionary, module()}
+ | {module, app_module()}
+ | {state, any()}
+ | {call_mutates_state, boolean()}
+ | {answer_errors, callback|report|discard}.
+
+-type app_module()
+ :: module()
+ | nonempty_improper_list(module(), list()). %% list with module() head
+
+%% Identifier returned by add_transport/2
+
+-type transport_ref()
+ :: reference().
+
+%% Options passed to add_transport/2
+
+-type transport_opt()
+ :: {transport_module, atom()}
+ | {transport_config, any()}
+ | {applications, [app_alias()]}
+ | {capabilities, [capability()]}
+ | {watchdog_timer, 'Unsigned32'() | {module(), atom(), list()}}
+ | {reconnect_timer, 'Unsigned32'()}
+ | {private, any()}.
+
+%% Predicate passed to remove_transport/2
+
+-type transport_pred()
+ :: fun((reference(), connect|listen, list()) -> boolean())
+ | fun((reference(), list()) -> boolean())
+ | fun((list()) -> boolean())
+ | reference()
+ | list()
+ | {connect|listen, transport_pred()}
+ | {atom(), atom(), list()}.
+
+%% Options passed to call/4
+
+-type call_opt()
+ :: {extra, list()}
+ | {filter, peer_filter()}
+ | {timeout, 'Unsigned32'()}
+ | detach.
diff --git a/lib/diameter/src/app/diameter_watchdog.erl b/lib/diameter/src/app/diameter_watchdog.erl
new file mode 100644
index 0000000000..b7c1491f4b
--- /dev/null
+++ b/lib/diameter/src/app/diameter_watchdog.erl
@@ -0,0 +1,571 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 module implements (as a process) the state machine documented
+%% in Appendix A of RFC 3539.
+%%
+
+-module(diameter_watchdog).
+-behaviour(gen_server).
+
+%% towards diameter_service
+-export([start/2]).
+
+%% gen_server callbacks
+-export([init/1,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ terminate/2,
+ code_change/3]).
+
+%% diameter_watchdog_sup callback
+-export([start_link/1]).
+
+-include_lib("diameter/include/diameter.hrl").
+-include("diameter_internal.hrl").
+
+-define(DEFAULT_TW_INIT, 30000). %% RFC 3539 ch 3.4.1
+
+-record(watchdog,
+ {%% PCB - Peer Control Block; see RFC 3539, Appendix A
+ status = initial :: initial | okay | suspect | down | reopen,
+ pending = false :: boolean(),
+ tw :: 6000..16#FFFFFFFF | {module(), atom(), list()},
+ %% {M,F,A} -> integer() >= 0
+ num_dwa = 0 :: -1 | non_neg_integer(),
+ %% number of DWAs received during reopen
+ %% end PCB
+ parent = self() :: pid(),
+ transport :: pid(),
+ tref :: reference(), %% reference for current watchdog timer
+ message_data}). %% term passed into diameter_service with message
+
+%% start/2
+
+start({_,_} = Type, T) ->
+ {ok, Pid} = diameter_watchdog_sup:start_child({Type, self(), T}),
+ Pid.
+
+start_link(T) ->
+ {ok, _} = proc_lib:start_link(?MODULE,
+ init,
+ [T],
+ infinity,
+ diameter_lib:spawn_opts(server, [])).
+
+%% ===========================================================================
+%% ===========================================================================
+
+%% init/1
+
+init(T) ->
+ proc_lib:init_ack({ok, self()}),
+ gen_server:enter_loop(?MODULE, [], i(T)).
+
+i({T, Pid, {ConnT, Opts, SvcName, #diameter_service{applications = Apps,
+ capabilities = Caps}
+ = Svc}}) ->
+ {M,S,U} = now(),
+ random:seed(M,S,U),
+ putr(restart, {T, Opts, Svc}), %% save seeing it in trace
+ putr(dwr, dwr(Caps)), %%
+ #watchdog{parent = monitor(Pid),
+ transport = monitor(diameter_peer_fsm:start(T, Opts, Svc)),
+ tw = proplists:get_value(watchdog_timer,
+ Opts,
+ ?DEFAULT_TW_INIT),
+ message_data = {ConnT, SvcName, Apps}}.
+
+%% handle_call/3
+
+handle_call(_, _, State) ->
+ {reply, nok, State}.
+
+%% handle_cast/2
+
+handle_cast(_, State) ->
+ {noreply, State}.
+
+%% handle_info/2
+
+handle_info(T, State) ->
+ case transition(T, State) of
+ ok ->
+ {noreply, State};
+ #watchdog{status = X} = S ->
+ ?LOGC(X =/= State#watchdog.status, transition, X),
+ {noreply, S};
+ stop ->
+ ?LOG(stop, T),
+ {stop, {shutdown, T}, State}
+ end.
+
+%% terminate/2
+
+terminate(_, _) ->
+ ok.
+
+%% code_change/3
+
+code_change(_, State, _) ->
+ {ok, State}.
+
+%% ===========================================================================
+%% ===========================================================================
+
+%% transition/2
+%%
+%% The state transitions documented here are extracted from RFC 3539,
+%% the commentary is ours.
+
+%% Service or watchdog is telling the watchdog of an accepting
+%% transport to die after reconnect_timer expiry or reestablished
+%% connection (in another transport process) respectively.
+transition(close, #watchdog{status = down}) ->
+ {{accept, _}, _, _} = getr(restart), %% assert
+ stop;
+transition(close, #watchdog{}) ->
+ ok;
+
+%% Service is asking for the peer to be taken down gracefully.
+transition({shutdown, Pid}, #watchdog{parent = Pid,
+ transport = undefined,
+ status = S}) ->
+ down = S, %% sanity check
+ stop;
+transition({shutdown = T, Pid}, #watchdog{parent = Pid,
+ transport = TPid}) ->
+ TPid ! {T, self()},
+ ok;
+
+%% Parent process has died,
+transition({'DOWN', _, process, Pid, _Reason},
+ #watchdog{parent = Pid}) ->
+ stop;
+
+%% Transport has accepted a connection.
+transition({accepted = T, TPid}, #watchdog{transport = TPid,
+ parent = Pid}) ->
+ Pid ! {T, self(), TPid},
+ ok;
+
+%% Transport is telling us that its impending death isn't failure.
+transition({close, TPid, _Reason}, #watchdog{transport = TPid}) ->
+ stop;
+
+%% STATE Event Actions New State
+%% ===== ------ ------- ----------
+%% INITIAL Connection up SetWatchdog() OKAY
+
+%% By construction, the watchdog timer isn't set until we move into
+%% state okay as the result of the Peer State Machine reaching the
+%% Open state.
+%%
+%% If we're an acceptor then we may be resuming a connection that went
+%% down in another acceptor process, in which case this is the
+%% transition below, from down into reopen. That is, it's not until
+%% we know the identity of the peer (ie. now) that we know that we're
+%% in state down rather than initial.
+
+transition({open, TPid, Hosts, T} = Open,
+ #watchdog{transport = TPid,
+ status = initial,
+ parent = Pid}
+ = S) ->
+ case okay(getr(restart), Hosts) of
+ okay ->
+ open(Pid, {TPid, T}),
+ set_watchdog(S#watchdog{status = okay});
+ reopen ->
+ transition(Open, S#watchdog{status = down})
+ end;
+
+%% DOWN Connection up NumDWA = 0
+%% SendWatchdog()
+%% SetWatchdog()
+%% Pending = TRUE REOPEN
+
+transition({open = P, TPid, _Hosts, T},
+ #watchdog{transport = TPid,
+ status = down}
+ = S) ->
+ %% Store the info we need to notify the parent to reopen the
+ %% connection after the requisite DWA's are received, at which
+ %% time we eraser(open).
+ putr(P, {TPid, T}),
+ set_watchdog(send_watchdog(S#watchdog{status = reopen,
+ num_dwa = 0}));
+
+%% OKAY Connection down CloseConnection()
+%% Failover()
+%% SetWatchdog() DOWN
+%% SUSPECT Connection down CloseConnection()
+%% SetWatchdog() DOWN
+%% REOPEN Connection down CloseConnection()
+%% SetWatchdog() DOWN
+
+transition({'DOWN', _, process, TPid, _},
+ #watchdog{transport = TPid,
+ status = initial}) ->
+ stop;
+
+transition({'DOWN', _, process, Pid, _},
+ #watchdog{transport = Pid}
+ = S) ->
+ failover(S),
+ close(S),
+ set_watchdog(S#watchdog{status = down,
+ pending = false,
+ transport = undefined});
+%% Any outstanding pending (or other messages from the transport) will
+%% have arrived before 'DOWN' since the message comes from the same
+%% process. Note that we could also get this message in the initial
+%% state.
+
+%% Incoming message.
+transition({recv, TPid, Name, Pkt}, #watchdog{transport = TPid} = S) ->
+ recv(Name, Pkt, S);
+
+%% Current watchdog has timed out.
+transition({timeout, TRef, tw}, #watchdog{tref = TRef} = S) ->
+ set_watchdog(timeout(S));
+
+%% Timer was canceled after message was already sent.
+transition({timeout, _, tw}, #watchdog{}) ->
+ ok;
+
+%% State query.
+transition({state, Pid}, #watchdog{status = S}) ->
+ Pid ! {self(), S},
+ ok.
+
+%% ===========================================================================
+
+monitor(Pid) ->
+ erlang:monitor(process, Pid),
+ Pid.
+
+putr(Key, Val) ->
+ put({?MODULE, Key}, Val).
+
+getr(Key) ->
+ get({?MODULE, Key}).
+
+eraser(Key) ->
+ erase({?MODULE, Key}).
+
+%% encode/1
+
+encode(Msg) ->
+ #diameter_packet{bin = Bin} = diameter_codec:encode(?BASE, Msg),
+ Bin.
+
+%% okay/2
+
+okay({{accept, Ref}, _, _}, Hosts) ->
+ T = {?MODULE, connection, Ref, Hosts},
+ diameter_reg:add(T),
+ okay(diameter_reg:match(T));
+%% Register before matching so that at least one of two registering
+%% processes will match the other. (Which can't happen as long as
+%% diameter_peer_fsm guarantees at most one open connection to the same
+%% peer.)
+
+okay({{connect, _}, _, _}, _) ->
+ okay.
+
+%% The peer hasn't been connected recently ...
+okay([{_,P}]) ->
+ P = self(), %% assert
+ okay;
+
+%% ... or it has.
+okay(C) ->
+ [_|_] = [P ! close || {_,P} <- C, self() /= P],
+ reopen.
+
+%% set_watchdog/1
+
+set_watchdog(#watchdog{tw = TwInit,
+ tref = TRef}
+ = S) ->
+ cancel(TRef),
+ S#watchdog{tref = erlang:start_timer(tw(TwInit), self(), tw)}.
+
+cancel(undefined) ->
+ ok;
+cancel(TRef) ->
+ erlang:cancel_timer(TRef).
+
+tw(T)
+ when is_integer(T), T >= 6000 ->
+ T - 2000 + (random:uniform(4001) - 1); %% RFC3539 jitter of +/- 2 sec.
+tw({M,F,A}) ->
+ apply(M,F,A).
+
+%% open/2
+
+open(Pid, {_,_} = T) ->
+ Pid ! {connection_up, self(), T}.
+
+%% failover/1
+
+failover(#watchdog{status = okay,
+ parent = Pid}) ->
+ Pid ! {connection_down, self()};
+
+failover(_) ->
+ ok.
+
+%% close/1
+
+close(#watchdog{status = down}) ->
+ ok;
+
+close(#watchdog{parent = Pid}) ->
+ {{T, _}, _, _} = getr(restart),
+ T == accept andalso (Pid ! {close, self()}).
+
+%% send_watchdog/1
+
+send_watchdog(#watchdog{pending = false,
+ transport = TPid}
+ = S) ->
+ TPid ! {send, encode(getr(dwr))},
+ ?LOG(send, 'DWR'),
+ S#watchdog{pending = true}.
+
+%% recv/3
+
+recv(Name, Pkt, S) ->
+ try rcv(Name, S) of
+ #watchdog{} = NS ->
+ rcv(Name, Pkt, S),
+ NS
+ catch
+ throw: {?MODULE, throwaway, #watchdog{} = NS} ->
+ NS
+ end.
+
+%% rcv/3
+
+rcv(N, _, _)
+ when N == 'CER';
+ N == 'CEA';
+ N == 'DWR';
+ N == 'DWA';
+ N == 'DPR';
+ N == 'DPA' ->
+ false;
+
+rcv(_, Pkt, #watchdog{transport = TPid,
+ message_data = T}) ->
+ diameter_service:receive_message(TPid, Pkt, T).
+
+throwaway(S) ->
+ throw({?MODULE, throwaway, S}).
+
+%% rcv/2
+
+%% INITIAL Receive DWA Pending = FALSE
+%% Throwaway() INITIAL
+%% INITIAL Receive non-DWA Throwaway() INITIAL
+
+rcv('DWA', #watchdog{status = initial} = S) ->
+ throwaway(S#watchdog{pending = false});
+
+rcv(_, #watchdog{status = initial} = S) ->
+ throwaway(S);
+
+%% DOWN Receive DWA Pending = FALSE
+%% Throwaway() DOWN
+%% DOWN Receive non-DWA Throwaway() DOWN
+
+rcv('DWA', #watchdog{status = down} = S) ->
+ throwaway(S#watchdog{pending = false});
+
+rcv(_, #watchdog{status = down} = S) ->
+ throwaway(S);
+
+%% OKAY Receive DWA Pending = FALSE
+%% SetWatchdog() OKAY
+%% OKAY Receive non-DWA SetWatchdog() OKAY
+
+rcv('DWA', #watchdog{status = okay} = S) ->
+ set_watchdog(S#watchdog{pending = false});
+
+rcv(_, #watchdog{status = okay} = S) ->
+ set_watchdog(S);
+
+%% SUSPECT Receive DWA Pending = FALSE
+%% Failback()
+%% SetWatchdog() OKAY
+%% SUSPECT Receive non-DWA Failback()
+%% SetWatchdog() OKAY
+
+rcv('DWA', #watchdog{status = suspect} = S) ->
+ failback(S),
+ set_watchdog(S#watchdog{status = okay,
+ pending = false});
+
+rcv(_, #watchdog{status = suspect} = S) ->
+ failback(S),
+ set_watchdog(S#watchdog{status = okay});
+
+%% REOPEN Receive DWA & Pending = FALSE
+%% NumDWA == 2 NumDWA++
+%% Failback() OKAY
+
+rcv('DWA', #watchdog{status = reopen,
+ num_dwa = 2 = N,
+ parent = Pid}
+ = S) ->
+ open(Pid, eraser(open)),
+ S#watchdog{status = okay,
+ num_dwa = N+1,
+ pending = false};
+
+%% REOPEN Receive DWA & Pending = FALSE
+%% NumDWA < 2 NumDWA++ REOPEN
+
+rcv('DWA', #watchdog{status = reopen,
+ num_dwa = N}
+ = S) ->
+ S#watchdog{num_dwa = N+1,
+ pending = false};
+
+%% REOPEN Receive non-DWA Throwaway() REOPEN
+
+rcv(_, #watchdog{status = reopen} = S) ->
+ throwaway(S).
+
+%% failback/1
+
+failback(#watchdog{parent = Pid}) ->
+ Pid ! {connection_up, self()}.
+
+%% timeout/1
+%%
+%% The caller sets the watchdog on the return value.
+
+%% OKAY Timer expires & SendWatchdog()
+%% !Pending SetWatchdog()
+%% Pending = TRUE OKAY
+%% REOPEN Timer expires & SendWatchdog()
+%% !Pending SetWatchdog()
+%% Pending = TRUE REOPEN
+
+timeout(#watchdog{status = T,
+ pending = false}
+ = S)
+ when T == okay;
+ T == reopen ->
+ send_watchdog(S);
+
+%% OKAY Timer expires & Failover()
+%% Pending SetWatchdog() SUSPECT
+
+timeout(#watchdog{status = okay,
+ pending = true}
+ = S) ->
+ failover(S),
+ S#watchdog{status = suspect};
+
+%% SUSPECT Timer expires CloseConnection()
+%% SetWatchdog() DOWN
+%% REOPEN Timer expires & CloseConnection()
+%% Pending & SetWatchdog()
+%% NumDWA < 0 DOWN
+
+timeout(#watchdog{status = T,
+ pending = P,
+ num_dwa = N,
+ transport = TPid}
+ = S)
+ when T == suspect;
+ T == reopen, P, N < 0 ->
+ exit(TPid, shutdown),
+ close(S),
+ S#watchdog{status = down};
+
+%% REOPEN Timer expires & NumDWA = -1
+%% Pending & SetWatchdog()
+%% NumDWA >= 0 REOPEN
+
+timeout(#watchdog{status = reopen,
+ pending = true,
+ num_dwa = N}
+ = S)
+ when 0 =< N ->
+ S#watchdog{num_dwa = -1};
+
+%% DOWN Timer expires AttemptOpen()
+%% SetWatchdog() DOWN
+%% INITIAL Timer expires AttemptOpen()
+%% SetWatchdog() INITIAL
+
+%% RFC 3539, 3.4.1:
+%%
+%% [5] While the connection is in the closed state, the AAA client MUST
+%% NOT attempt to send further watchdog messages on the connection.
+%% However, after the connection is closed, the AAA client continues
+%% to periodically attempt to reopen the connection.
+%%
+%% The AAA client SHOULD wait for the transport layer to report
+%% connection failure before attempting again, but MAY choose to
+%% bound this wait time by the watchdog interval, Tw.
+
+%% Don't bound, restarting the peer process only when the previous
+%% process has died. We only need to handle state down since we start
+%% the first watchdog when transitioning out of initial.
+
+timeout(#watchdog{status = down} = S) ->
+ restart(S).
+
+%% restart/1
+
+restart(#watchdog{transport = undefined} = S) ->
+ restart(getr(restart), S);
+restart(S) ->
+ S.
+
+%% Only restart the transport in the connecting case. For an accepting
+%% transport, we've registered the peer connection when leaving state
+%% initial and this is used by a new accepting process to realize that
+%% it's actually in state down rather then initial when receiving
+%% notification of an open connection.
+
+restart({{connect, _} = T, Opts, Svc}, #watchdog{parent = Pid} = S) ->
+ Pid ! {reconnect, self()},
+ S#watchdog{transport = monitor(diameter_peer_fsm:start(T, Opts, Svc))};
+restart({{accept, _}, _, _}, S) ->
+ S.
+%% Don't currently use Opts/Svc in the accept case but having them in
+%% the process dictionary is helpful if the process dies unexpectedly.
+
+%% dwr/1
+
+dwr(#diameter_caps{origin_host = OH,
+ origin_realm = OR,
+ origin_state_id = OSI}) ->
+ ['DWR', {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Origin-State-Id', OSI}].
diff --git a/lib/diameter/src/app/diameter_watchdog_sup.erl b/lib/diameter/src/app/diameter_watchdog_sup.erl
new file mode 100644
index 0000000000..fc837fe4ef
--- /dev/null
+++ b/lib/diameter/src/app/diameter_watchdog_sup.erl
@@ -0,0 +1,60 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Supervisor for all watchdog processes.
+%%
+
+-module(diameter_watchdog_sup).
+
+-behaviour(supervisor).
+
+%% interface
+-export([start_link/0, %% supervisor start
+ start_child/1]). %% watchdog start
+
+-export([init/1]).
+
+-define(NAME, ?MODULE). %% supervisor name
+
+%% start_link/0
+
+start_link() ->
+ SupName = {local, ?NAME},
+ supervisor:start_link(SupName, ?MODULE, []).
+
+%% start_child/1
+%%
+%% Start a watchdog process.
+
+start_child(T) ->
+ supervisor:start_child(?NAME, [T]).
+
+%% init/1
+
+init([]) ->
+ Mod = diameter_watchdog,
+ Flags = {simple_one_for_one, 0, 1},
+ ChildSpec = {Mod,
+ {Mod, start_link, []},
+ temporary,
+ 1000,
+ worker,
+ [Mod]},
+ {ok, {Flags, [ChildSpec]}}.
diff --git a/lib/diameter/src/app/modules.mk b/lib/diameter/src/app/modules.mk
new file mode 100644
index 0000000000..c133e6f64e
--- /dev/null
+++ b/lib/diameter/src/app/modules.mk
@@ -0,0 +1,70 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+SPEC_FILES = \
+ diameter_gen_base_rfc3588.dia \
+ diameter_gen_base_accounting.dia \
+ diameter_gen_relay.dia
+
+RUNTIME_MODULES = \
+ diameter \
+ diameter_app \
+ diameter_capx \
+ diameter_config \
+ diameter_codec \
+ diameter_dict \
+ diameter_lib \
+ diameter_misc_sup \
+ diameter_peer \
+ diameter_peer_fsm \
+ diameter_peer_fsm_sup \
+ diameter_reg \
+ diameter_service \
+ diameter_service_sup \
+ diameter_session \
+ diameter_stats \
+ diameter_sup \
+ diameter_sync \
+ diameter_types \
+ diameter_watchdog \
+ diameter_watchdog_sup
+
+HELP_MODULES = \
+ diameter_callback \
+ diameter_exprecs \
+ diameter_dbg \
+ diameter_info
+
+INTERNAL_HRL_FILES = \
+ diameter_internal.hrl \
+ diameter_types.hrl
+
+EXTERNAL_HRL_FILES = \
+ ../../include/diameter.hrl \
+ ../../include/diameter_gen.hrl
+
+EXAMPLE_FILES = \
+ ../../examples/GNUmakefile \
+ ../../examples/peer.erl \
+ ../../examples/client.erl \
+ ../../examples/client_cb.erl \
+ ../../examples/server.erl \
+ ../../examples/server_cb.erl \
+ ../../examples/relay.erl \
+ ../../examples/relay_cb.erl
diff --git a/lib/diameter/src/compiler/.gitignore b/lib/diameter/src/compiler/.gitignore
new file mode 100644
index 0000000000..d9f072e262
--- /dev/null
+++ b/lib/diameter/src/compiler/.gitignore
@@ -0,0 +1,3 @@
+
+/depend.mk
+
diff --git a/lib/diameter/src/compiler/Makefile b/lib/diameter/src/compiler/Makefile
new file mode 100644
index 0000000000..779013bfbc
--- /dev/null
+++ b/lib/diameter/src/compiler/Makefile
@@ -0,0 +1,131 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+#
+
+ifneq ($(ERL_TOP),)
+include $(ERL_TOP)/make/target.mk
+EBIN = ../../ebin
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+else
+include $(DIAMETER_TOP)/make/target.mk
+EBIN = ../../ebin
+include $(DIAMETER_TOP)/make/$(TARGET)/rules.mk
+endif
+
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../../vsn.mk
+VSN=$(DIAMETER_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+
+RELSYSDIR = $(RELEASE_PATH)/lib/diameter-$(VSN)
+
+INCDIR = ../../include
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+include modules.mk
+
+ERL_FILES = \
+ $(MODULES:%=%.erl)
+
+TARGET_FILES = \
+ $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+
+ifeq ($(TYPE),debug)
+ERL_COMPILE_FLAGS += -Ddebug
+endif
+
+include ../app/diameter.mk
+
+ERL_COMPILE_FLAGS += \
+ $(DIAMETER_ERL_COMPILE_FLAGS) \
+ -I$(INCDIR)
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+debug:
+ @${MAKE} TYPE=debug opt
+
+opt: $(TARGET_FILES)
+
+clean:
+ rm -f $(TARGET_FILES)
+ rm -f errs core *~
+ rm -f depend.mk
+
+docs:
+
+info:
+ @echo ""
+ @echo "ERL_FILES = $(ERL_FILES)"
+ @echo "HRL_FILES = $(HRL_FILES)"
+ @echo ""
+ @echo "TARGET_FILES = $(TARGET_FILES)"
+ @echo ""
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+ifneq ($(ERL_TOP),)
+include $(ERL_TOP)/make/otp_release_targets.mk
+else
+include $(DIAMETER_TOP)/make/release_targets.mk
+endif
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) $(RELSYSDIR)/src
+ $(INSTALL_DIR) $(RELSYSDIR)/src/compiler
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/src/compiler
+
+release_docs_spec:
+
+force:
+
+# ----------------------------------------------------
+# Dependencies
+# ----------------------------------------------------
+
+depend: depend.mk
+
+# Generate dependencies makefile.
+depend.mk: ../app/depend.sed $(ERL_FILES) Makefile
+ for f in $(MODULES); do \
+ sed -f $< $$f.erl | sed "s@/@/$$f@"; \
+ done \
+ > $@
+
+-include depend.mk
+
+.PHONY: clean debug depend docs force info opt release_docs_spec release_spec
diff --git a/lib/diameter/src/compiler/diameter_codegen.erl b/lib/diameter/src/compiler/diameter_codegen.erl
new file mode 100644
index 0000000000..a33b07a3d3
--- /dev/null
+++ b/lib/diameter/src/compiler/diameter_codegen.erl
@@ -0,0 +1,827 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_codegen).
+
+%%
+%% This module generates .erl and .hrl files for encode/decode
+%% modules from the orddict parsed from a .dia (aka spec) file by
+%% dis_spec_util. The generated code is very simple (one-liners), the
+%% generated functions being called by code included from dis_gen.hrl
+%% in order to encode/decode messages and AVPs. The orddict itself is
+%% returned by dict/0 in the generated module and dis_spec_util calls
+%% this function when importing spec files. (That is, beam has to be
+%% compiled from an imported spec file before it can be imported.)
+%%
+
+-export([from_spec/4]).
+
+%% Internal exports (for test).
+-export([file/1,
+ file/2,
+ file/3]).
+
+-include("diameter_forms.hrl").
+
+%% Generated functions that could have no generated clauses will have
+%% a trailing ?UNEXPECTED clause that should never execute.
+-define(UNEXPECTED(N), {?clause, [?VAR('_') || _ <- lists:seq(1,N)],
+ [],
+ [?APPLY(erlang,
+ error,
+ [?TERM({unexpected, getr(module)})])]}).
+
+
+from_spec(File, Spec, Opts, Mode) ->
+ Outdir = proplists:get_value(outdir, Opts, "."),
+ putr(verbose, lists:member(verbose, Opts)),
+ putr(debug, lists:member(debug, Opts)),
+ codegen(File, Spec, Outdir, Mode).
+
+%% Optional reports when running verbosely.
+report(What, Data) ->
+ report(getr(verbose), What, Data),
+ Data.
+
+report(true, Tag, Data) ->
+ io:format(">>~n>> ~p ~p~n", [Tag, Data]);
+report(false, _, _) ->
+ ok.
+
+putr(Key, Value) ->
+ put({?MODULE, Key}, Value).
+
+getr(Key) ->
+ get({?MODULE, Key}).
+
+%% ===========================================================================
+%% ===========================================================================
+
+%% Generate from parsed spec in a file.
+
+file(F) ->
+ file(F, spec).
+
+file(F, Mode) ->
+ file(F, ".", Mode).
+
+file(F, Outdir, Mode) ->
+ {ok, [Spec]} = file:consult(F),
+ from_spec(F, Spec, Outdir, Mode).
+
+%% ===========================================================================
+%% ===========================================================================
+
+choose(true, X, _) -> X;
+choose(false, _, X) -> X.
+
+get_value(Key, Plist) ->
+ proplists:get_value(Key, Plist, []).
+
+write(Path, [C|_] = Spec)
+ when is_integer(C) ->
+ w(Path, Spec, "~s");
+write(Path, Spec) ->
+ w(Path, Spec, "~p.").
+
+w(Path, Spec, Fmt) ->
+ {ok, Fd} = file:open(Path, [write]),
+ io:fwrite(Fd, Fmt ++ "~n", [Spec]),
+ file:close(Fd).
+
+codegen(File, Spec, Outdir, Mode) ->
+ Mod = mod(File, orddict:find(name, Spec)),
+ Path = filename:join(Outdir, Mod), %% minus extension
+ gen(Mode, Spec, Mod, Path),
+ ok.
+
+mod(File, error) ->
+ filename:rootname(filename:basename(File));
+mod(_, {ok, Mod}) ->
+ atom_to_list(Mod).
+
+gen(spec, Spec, _Mod, Path) ->
+ write(Path ++ ".spec", Spec);
+
+gen(hrl, Spec, Mod, Path) ->
+ gen_hrl(Path ++ ".hrl", Mod, Spec);
+
+gen(erl = Mode, Spec, Mod, Path)
+ when is_list(Mod) ->
+ gen(Mode, Spec, list_to_atom(Mod), Path);
+
+gen(erl, Spec, Mod, Path) ->
+ putr(module, Mod), %% used by ?UNEXPECTED.
+
+ Forms = [{?attribute, module, Mod},
+ {?attribute, compile, [{parse_transform, diameter_exprecs}]},
+ {?attribute, compile, [nowarn_unused_function]},
+ {?attribute, export, [{name, 0},
+ {id, 0},
+ {vendor_id, 0},
+ {vendor_name, 0},
+ {decode_avps, 2}, %% in diameter_gen.hrl
+ {encode_avps, 2}, %%
+ {msg_name, 2},
+ {msg_header, 1},
+ {rec2msg, 1},
+ {msg2rec, 1},
+ {name2rec, 1},
+ {avp_name, 2},
+ {avp_arity, 2},
+ {avp_header, 1},
+ {avp, 3},
+ {grouped_avp, 3},
+ {enumerated_avp, 3},
+ {empty_value, 1},
+ {dict, 0}]},
+ %% diameter.hrl is included for #diameter_avp
+ {?attribute, include_lib, "diameter/include/diameter.hrl"},
+ {?attribute, include_lib, "diameter/include/diameter_gen.hrl"},
+ f_name(Mod),
+ f_id(Spec),
+ f_vendor_id(Spec),
+ f_vendor_name(Spec),
+ f_msg_name(Spec),
+ f_msg_header(Spec),
+ f_rec2msg(Spec),
+ f_msg2rec(Spec),
+ f_name2rec(Spec),
+ f_avp_name(Spec),
+ f_avp_arity(Spec),
+ f_avp_header(Spec),
+ f_avp(Spec),
+ f_enumerated_avp(Spec),
+ f_empty_value(Spec),
+ f_dict(Spec),
+ {eof, ?LINE}],
+
+ gen_erl(Path, insert_hrl_forms(Spec, Forms)).
+
+gen_erl(Path, Forms) ->
+ getr(debug) andalso write(Path ++ ".forms", Forms),
+ write(Path ++ ".erl",
+ header() ++ erl_prettypr:format(erl_syntax:form_list(Forms))).
+
+insert_hrl_forms(Spec, Forms) ->
+ {H,T} = lists:splitwith(fun is_header/1, Forms),
+ H ++ make_hrl_forms(Spec) ++ T.
+
+is_header({attribute, _, export, _}) ->
+ false;
+is_header(_) ->
+ true.
+
+make_hrl_forms(Spec) ->
+ {_Prefix, MsgRecs, GrpRecs, ImportedGrpRecs}
+ = make_record_forms(Spec),
+
+ RecordForms = MsgRecs ++ GrpRecs ++ lists:flatmap(fun({_,Fs}) -> Fs end,
+ ImportedGrpRecs),
+
+ RecNames = lists:map(fun({attribute,_,record,{N,_}}) -> N end,
+ RecordForms),
+
+ %% export_records is used by the diameter_exprecs parse transform.
+ [{?attribute, export_records, RecNames} | RecordForms].
+
+make_record_forms(Spec) ->
+ Prefix = prefix(Spec),
+
+ MsgRecs = a_record(Prefix, fun msg_proj/1, get_value(messages, Spec)),
+ GrpRecs = a_record(Prefix, fun grp_proj/1, get_value(grouped, Spec)),
+
+ ImportedGrpRecs = [{M, a_record(Prefix, fun grp_proj/1, Gs)}
+ || {M,Gs} <- get_value(import_groups, Spec)],
+
+ {Prefix, MsgRecs, GrpRecs, ImportedGrpRecs}.
+
+msg_proj({Name, _, _, _, Avps}) ->
+ {Name, Avps}.
+
+grp_proj({Name, _, _, Avps}) ->
+ {Name, Avps}.
+
+%% a_record/3
+
+a_record(Prefix, ProjF, L) ->
+ lists:map(fun(T) -> a_record(ProjF(T), Prefix) end, L).
+
+a_record({Nm, Avps}, Prefix) ->
+ Name = list_to_atom(Prefix ++ atom_to_list(Nm)),
+ Fields = lists:map(fun field/1, Avps),
+ {?attribute, record, {Name, Fields}}.
+
+field(Avp) ->
+ {Name, Arity} = avp_info(Avp),
+ if 1 == Arity ->
+ {?record_field, ?ATOM(Name)};
+ true ->
+ {?record_field, ?ATOM(Name), ?NIL}
+ end.
+
+%%% ------------------------------------------------------------------------
+%%% # name/0
+%%% ------------------------------------------------------------------------
+
+f_name(Name) ->
+ {?function, name, 0,
+ [{?clause, [], [], [?ATOM(Name)]}]}.
+
+%%% ------------------------------------------------------------------------
+%%% # id/0
+%%% ------------------------------------------------------------------------
+
+f_id(Spec) ->
+ {?function, id, 0,
+ [c_id(orddict:find(id, Spec))]}.
+
+c_id({ok, Id}) ->
+ {?clause, [], [], [?INTEGER(Id)]};
+
+c_id(error) ->
+ ?UNEXPECTED(0).
+
+%%% ------------------------------------------------------------------------
+%%% # vendor_id/0
+%%% ------------------------------------------------------------------------
+
+f_vendor_id(Spec) ->
+ {Id, _} = orddict:fetch(vendor, Spec),
+ {?function, vendor_id, 0,
+ [{?clause, [], [], [?INTEGER(Id)]}]}.
+
+%%% ------------------------------------------------------------------------
+%%% # vendor_name/0
+%%% ------------------------------------------------------------------------
+
+f_vendor_name(Spec) ->
+ {_, Name} = orddict:fetch(vendor, Spec),
+ {?function, vendor_name, 0,
+ [{?clause, [], [], [?ATOM(Name)]}]}.
+
+%%% ------------------------------------------------------------------------
+%%% # msg_name/1
+%%% ------------------------------------------------------------------------
+
+f_msg_name(Spec) ->
+ {?function, msg_name, 2, msg_name(Spec)}.
+
+%% Return the empty name for any unknown command to which
+%% DIAMETER_COMMAND_UNSUPPORTED should be replied.
+
+msg_name(Spec) ->
+ lists:flatmap(fun c_msg_name/1,
+ proplists:get_value(command_codes, Spec, []))
+ ++ [{?clause, [?VAR('_'), ?VAR('_')], [], [?ATOM('')]}].
+
+c_msg_name({Code, Req, Ans}) ->
+ [{?clause, [?INTEGER(Code), ?ATOM(true)],
+ [],
+ [?ATOM(mname(Req))]},
+ {?clause, [?INTEGER(Code), ?ATOM(false)],
+ [],
+ [?ATOM(mname(Ans))]}].
+
+mname({N, _Abbr}) ->
+ N;
+mname(N) ->
+ N.
+
+%%% ------------------------------------------------------------------------
+%%% # msg2rec/1
+%%% ------------------------------------------------------------------------
+
+f_msg2rec(Spec) ->
+ {?function, msg2rec, 1, msg2rec(Spec)}.
+
+msg2rec(Spec) ->
+ Pre = prefix(Spec),
+ Dict = dict:from_list(lists:flatmap(fun msgs/1,
+ get_value(command_codes, Spec))),
+ lists:flatmap(fun(T) -> msg2rec(T, Dict, Pre) end,
+ get_value(messages, Spec))
+ ++ [?UNEXPECTED(1)].
+
+msgs({_Code, Req, Ans}) ->
+ [{mname(Req), Req}, {mname(Ans), Ans}].
+
+msg2rec({N,_,_,_,_}, Dict, Pre) ->
+ c_msg2rec(fetch_names(N, Dict), Pre).
+
+fetch_names(Name, Dict) ->
+ case dict:find(Name, Dict) of
+ {ok, N} ->
+ N;
+ error ->
+ Name
+ end.
+
+c_msg2rec({N,A}, Pre) ->
+ [c_name2rec(N, N, Pre), c_name2rec(A, N, Pre)];
+c_msg2rec(N, Pre) ->
+ [c_name2rec(N, N, Pre)].
+
+%%% ------------------------------------------------------------------------
+%%% # rec2msg/1
+%%% ------------------------------------------------------------------------
+
+f_rec2msg(Spec) ->
+ {?function, rec2msg, 1, rec2msg(Spec)}.
+
+rec2msg(Spec) ->
+ Pre = prefix(Spec),
+ lists:map(fun(T) -> c_rec2msg(T, Pre) end, get_value(messages, Spec))
+ ++ [?UNEXPECTED(1)].
+
+c_rec2msg({N,_,_,_,_}, Pre) ->
+ {?clause, [?ATOM(rec_name(N, Pre))], [], [?ATOM(N)]}.
+
+%%% ------------------------------------------------------------------------
+%%% # name2rec/1
+%%% ------------------------------------------------------------------------
+
+f_name2rec(Spec) ->
+ {?function, name2rec, 1, name2rec(Spec)}.
+
+name2rec(Spec) ->
+ Pre = prefix(Spec),
+ Groups = get_value(grouped, Spec)
+ ++ lists:flatmap(fun avps/1, get_value(import_groups, Spec)),
+ lists:map(fun({N,_,_,_}) -> c_name2rec(N, N, Pre) end, Groups)
+ ++ [{?clause, [?VAR('T')], [], [?CALL(msg2rec, [?VAR('T')])]}].
+
+c_name2rec(Name, Rname, Pre) ->
+ {?clause, [?ATOM(Name)], [], [?ATOM(rec_name(Rname, Pre))]}.
+
+avps({_Mod, Avps}) ->
+ Avps.
+
+%%% ------------------------------------------------------------------------
+%%% # avp_name/1
+%%% ------------------------------------------------------------------------
+
+f_avp_name(Spec) ->
+ {?function, avp_name, 2, avp_name(Spec)}.
+
+%% 3588, 4.1:
+%%
+%% AVP Code
+%% The AVP Code, combined with the Vendor-Id field, identifies the
+%% attribute uniquely. AVP numbers 1 through 255 are reserved for
+%% backward compatibility with RADIUS, without setting the Vendor-Id
+%% field. AVP numbers 256 and above are used for Diameter, which are
+%% allocated by IANA (see Section 11.1).
+
+avp_name(Spec) ->
+ Avps = get_value(avp_types, Spec)
+ ++ lists:flatmap(fun avps/1, get_value(import_avps, Spec)),
+ {Vid, _} = orddict:fetch(vendor, Spec),
+ Vs = lists:flatmap(fun({V,Ns}) -> [{N,V} || N <- Ns] end,
+ get_value(avp_vendor_id, Spec)),
+
+ lists:map(fun(T) -> c_avp_name(T, Vid, Vs) end, Avps)
+ ++ [{?clause, [?VAR('_'), ?VAR('_')], [], [?ATOM('AVP')]}].
+
+c_avp_name({Name, Code, Type, Flags, _Encr}, Vid, Vs) ->
+ c_avp_name({Name, Type},
+ Code,
+ lists:member('V', Flags),
+ Vid,
+ proplists:get_value(Name, Vs)).
+
+c_avp_name(T, Code, false, _, undefined = U) ->
+ {?clause, [?INTEGER(Code), ?ATOM(U)],
+ [],
+ [?TERM(T)]};
+
+c_avp_name(T, Code, true, Vid, V)
+ when is_integer(Vid) ->
+ {?clause, [?INTEGER(Code), ?INTEGER(choose(V == undefined, Vid, V))],
+ [],
+ [?TERM(T)]}.
+
+%%% ------------------------------------------------------------------------
+%%% # avp_arity/2
+%%% ------------------------------------------------------------------------
+
+f_avp_arity(Spec) ->
+ {?function, avp_arity, 2, avp_arity(Spec)}.
+
+avp_arity(Spec) ->
+ Msgs = get_value(messages, Spec),
+ Groups = get_value(grouped, Spec)
+ ++ lists:flatmap(fun avps/1, get_value(import_groups, Spec)),
+ c_avp_arity(Msgs ++ Groups)
+ ++ [{?clause, [?VAR('_'), ?VAR('_')], [], [?INTEGER(0)]}].
+
+c_avp_arity(L)
+ when is_list(L) ->
+ lists:flatmap(fun c_avp_arity/1, L);
+
+c_avp_arity({N,_,_,_,As}) ->
+ c_avp_arity(N,As);
+c_avp_arity({N,_,_,As}) ->
+ c_avp_arity(N,As).
+
+c_avp_arity(Name, Avps) ->
+ lists:map(fun(A) -> c_arity(Name, A) end, Avps).
+
+c_arity(Name, Avp) ->
+ {AvpName, Arity} = avp_info(Avp),
+ {?clause, [?ATOM(Name), ?ATOM(AvpName)], [], [?TERM(Arity)]}.
+
+%%% ------------------------------------------------------------------------
+%%% # avp/3
+%%% ------------------------------------------------------------------------
+
+f_avp(Spec) ->
+ {?function, avp, 3, avp(Spec) ++ [?UNEXPECTED(3)]}.
+
+avp(Spec) ->
+ Native = get_value(avp_types, Spec),
+ Custom = get_value(custom_types, Spec),
+ Imported = get_value(import_avps, Spec),
+ Enums = get_value(enums, Spec),
+ avp([{N,T} || {N,_,T,_,_} <- Native], Imported, Custom, Enums).
+
+avp(Native, Imported, Custom, Enums) ->
+ Dict = orddict:from_list(Native),
+
+ report(native, Dict),
+ report(imported, Imported),
+ report(custom, Custom),
+
+ CustomNames = lists:flatmap(fun({_,Ns}) -> Ns end, Custom),
+
+ lists:map(fun c_base_avp/1,
+ lists:filter(fun({N,_}) ->
+ false == lists:member(N, CustomNames)
+ end,
+ Native))
+ ++ lists:flatmap(fun(I) -> cs_imported_avp(I, Enums) end, Imported)
+ ++ lists:flatmap(fun(C) -> cs_custom_avp(C, Dict) end, Custom).
+
+c_base_avp({AvpName, T}) ->
+ {?clause, [?VAR('T'), ?VAR('Data'), ?ATOM(AvpName)],
+ [],
+ [base_avp(AvpName, T)]}.
+
+base_avp(AvpName, 'Enumerated') ->
+ ?CALL(enumerated_avp, [?VAR('T'), ?ATOM(AvpName), ?VAR('Data')]);
+
+base_avp(AvpName, 'Grouped') ->
+ ?CALL(grouped_avp, [?VAR('T'), ?ATOM(AvpName), ?VAR('Data')]);
+
+base_avp(_, Type) ->
+ ?APPLY(diameter_types, Type, [?VAR('T'), ?VAR('Data')]).
+
+cs_imported_avp({Mod, Avps}, Enums) ->
+ lists:map(fun(A) -> imported_avp(Mod, A, Enums) end, Avps).
+
+imported_avp(_Mod, {AvpName, _, 'Grouped' = T, _, _}, _) ->
+ c_base_avp({AvpName, T});
+
+imported_avp(Mod, {AvpName, _, 'Enumerated' = T, _, _}, Enums) ->
+ case lists:keymember(AvpName, 1, Enums) of
+ true ->
+ c_base_avp({AvpName, T});
+ false ->
+ c_imported_avp(Mod, AvpName)
+ end;
+
+imported_avp(Mod, {AvpName, _, _, _, _}, _) ->
+ c_imported_avp(Mod, AvpName).
+
+c_imported_avp(Mod, AvpName) ->
+ {?clause, [?VAR('T'), ?VAR('Data'), ?ATOM(AvpName)],
+ [],
+ [?APPLY(Mod, avp, [?VAR('T'),
+ ?VAR('Data'),
+ ?ATOM(AvpName)])]}.
+
+cs_custom_avp({Mod, Avps}, Dict) ->
+ lists:map(fun(N) -> c_custom_avp(Mod, N, orddict:fetch(N, Dict)) end,
+ Avps).
+
+c_custom_avp(Mod, AvpName, Type) ->
+ {?clause, [?VAR('T'), ?VAR('Data'), ?ATOM(AvpName)],
+ [],
+ [?APPLY(Mod, AvpName, [?VAR('T'), ?ATOM(Type), ?VAR('Data')])]}.
+
+%%% ------------------------------------------------------------------------
+%%% # enumerated_avp/3
+%%% ------------------------------------------------------------------------
+
+f_enumerated_avp(Spec) ->
+ {?function, enumerated_avp, 3, enumerated_avp(Spec) ++ [?UNEXPECTED(3)]}.
+
+enumerated_avp(Spec) ->
+ Enums = get_value(enums, Spec),
+ lists:flatmap(fun cs_enumerated_avp/1, Enums)
+ ++ lists:flatmap(fun({M,Es}) -> enumerated_avp(M, Es, Enums) end,
+ get_value(import_enums, Spec)).
+
+enumerated_avp(Mod, Es, Enums) ->
+ lists:flatmap(fun({N,_}) ->
+ cs_enumerated_avp(lists:keymember(N, 1, Enums),
+ Mod,
+ N)
+ end,
+ Es).
+
+cs_enumerated_avp(true, Mod, Name) ->
+ [c_imported_avp(Mod, Name)];
+cs_enumerated_avp(false, _, _) ->
+ [].
+
+cs_enumerated_avp({AvpName, Values}) ->
+ lists:flatmap(fun(V) -> c_enumerated_avp(AvpName, V) end, Values).
+
+c_enumerated_avp(AvpName, {I,_}) ->
+ [{?clause, [?ATOM(decode), ?ATOM(AvpName), ?TERM(<<I:32/integer>>)],
+ [],
+ [?TERM(I)]},
+ {?clause, [?ATOM(encode), ?ATOM(AvpName), ?INTEGER(I)],
+ [],
+ [?TERM(<<I:32/integer>>)]}].
+
+%%% ------------------------------------------------------------------------
+%%% msg_header/1
+%%% ------------------------------------------------------------------------
+
+f_msg_header(Spec) ->
+ {?function, msg_header, 1, msg_header(Spec) ++ [?UNEXPECTED(1)]}.
+
+msg_header(Spec) ->
+ msg_header(get_value(messages, Spec), Spec).
+
+msg_header([], _) ->
+ [];
+msg_header(Msgs, Spec) ->
+ ApplId = orddict:fetch(id, Spec),
+
+ lists:map(fun({M,C,F,_,_}) -> c_msg_header(M, C, F, ApplId) end, Msgs).
+
+%% Note that any application id in the message header spec is ignored.
+
+c_msg_header(Name, Code, Flags, ApplId) ->
+ {?clause, [?ATOM(Name)],
+ [],
+ [?TERM({Code, encode_msg_flags(Flags), ApplId})]}.
+
+encode_msg_flags(Flags) ->
+ lists:foldl(fun emf/2, 0, Flags).
+
+emf('REQ', N) -> N bor 2#10000000;
+emf('PXY', N) -> N bor 2#01000000;
+emf('ERR', N) -> N bor 2#00100000.
+
+%%% ------------------------------------------------------------------------
+%%% # avp_header/1
+%%% ------------------------------------------------------------------------
+
+f_avp_header(Spec) ->
+ {?function, avp_header, 1, avp_header(Spec) ++ [?UNEXPECTED(1)]}.
+
+avp_header(Spec) ->
+ Native = get_value(avp_types, Spec),
+ Imported = get_value(import_avps, Spec),
+ {Vid, _} = orddict:fetch(vendor, Spec),
+ Vs = lists:flatmap(fun({V,Ns}) -> [{N,V} || N <- Ns] end,
+ get_value(avp_vendor_id, Spec)),
+
+ lists:flatmap(fun(A) -> c_avp_header({Vid, Vs}, A) end,
+ Native ++ Imported).
+
+c_avp_header({Vid, Vs}, {Name, Code, _Type, Flags, _Encr}) ->
+ [{?clause, [?ATOM(Name)],
+ [],
+ [?TERM({Code, encode_avp_flags(Flags), vid(Name, Flags, Vs, Vid)})]}];
+
+c_avp_header({_, Vs}, {Mod, Avps}) ->
+ lists:map(fun(A) -> c_avp_header(Vs, Mod, A) end, Avps).
+
+c_avp_header(Vs, Mod, {Name, _, _, Flags, _}) ->
+ Apply = ?APPLY(Mod, avp_header, [?ATOM(Name)]),
+ {?clause, [?ATOM(Name)],
+ [],
+ [case proplists:get_value(Name, Vs) of
+ undefined ->
+ Apply;
+ Vid ->
+ true = lists:member('V', Flags), %% sanity check
+ ?CALL(setelement, [?INTEGER(3), Apply, ?INTEGER(Vid)])
+ end]}.
+
+encode_avp_flags(Fs) ->
+ lists:foldl(fun eaf/2, 0, Fs).
+
+eaf('V', F) -> 2#10000000 bor F;
+eaf('M', F) -> 2#01000000 bor F;
+eaf('P', F) -> 2#00100000 bor F.
+
+vid(Name, Flags, Vs, Vid) ->
+ v(lists:member('V', Flags), Name, Vs, Vid).
+
+v(true, Name, Vs, Vid) ->
+ proplists:get_value(Name, Vs, Vid);
+v(false, _, _, _) ->
+ undefined.
+
+%%% ------------------------------------------------------------------------
+%%% # empty_value/0
+%%% ------------------------------------------------------------------------
+
+f_empty_value(Spec) ->
+ {?function, empty_value, 1, empty_value(Spec)}.
+
+empty_value(Spec) ->
+ Imported = lists:flatmap(fun avps/1, get_value(import_enums, Spec)),
+ Groups = get_value(grouped, Spec)
+ ++ lists:flatmap(fun avps/1, get_value(import_groups, Spec)),
+ Enums = [T || {N,_} = T <- get_value(enums, Spec),
+ not lists:keymember(N, 1, Imported)]
+ ++ Imported,
+ lists:map(fun c_empty_value/1, Groups ++ Enums)
+ ++ [{?clause, [?VAR('Name')], [], [?CALL(empty, [?VAR('Name')])]}].
+
+c_empty_value({Name, _, _, _}) ->
+ {?clause, [?ATOM(Name)],
+ [],
+ [?CALL(empty_group, [?ATOM(Name)])]};
+
+c_empty_value({Name, _}) ->
+ {?clause, [?ATOM(Name)],
+ [],
+ [?TERM(<<0:32/integer>>)]}.
+
+%%% ------------------------------------------------------------------------
+%%% # dict/0
+%%% ------------------------------------------------------------------------
+
+f_dict(Spec) ->
+ {?function, dict, 0,
+ [{?clause, [], [], [?TERM(Spec)]}]}.
+
+%%% ------------------------------------------------------------------------
+%%% # gen_hrl/3
+%%% ------------------------------------------------------------------------
+
+gen_hrl(Path, Mod, Spec) ->
+ {ok, Fd} = file:open(Path, [write]),
+
+ {Prefix, MsgRecs, GrpRecs, ImportedGrpRecs}
+ = make_record_forms(Spec),
+
+ file:write(Fd, hrl_header(Mod)),
+
+ forms("Message records", Fd, MsgRecs),
+ forms("Grouped AVP records", Fd, GrpRecs),
+
+ lists:foreach(fun({M,Fs}) ->
+ forms("Grouped AVP records from " ++ atom_to_list(M),
+ Fd,
+ Fs)
+ end,
+ ImportedGrpRecs),
+
+ PREFIX = to_upper(Prefix),
+
+ write("ENUM Macros",
+ Fd,
+ m_enums(PREFIX, false, get_value(enums, Spec))),
+ write("RESULT CODE Macros",
+ Fd,
+ m_enums(PREFIX, false, get_value(result_codes, Spec))),
+
+ lists:foreach(fun({M,Es}) ->
+ write("ENUM Macros from " ++ atom_to_list(M),
+ Fd,
+ m_enums(PREFIX, true, Es))
+ end,
+ get_value(import_enums, Spec)),
+
+ file:close(Fd).
+
+forms(_, _, []) ->
+ ok;
+forms(Banner, Fd, Forms) ->
+ write(Banner, Fd, prettypr(Forms)).
+
+write(_, _, []) ->
+ ok;
+write(Banner, Fd, Str) ->
+ banner(Fd, Banner),
+ io:fwrite(Fd, "~s~n", [Str]).
+
+prettypr(Forms) ->
+ erl_prettypr:format(erl_syntax:form_list(Forms)).
+
+banner(Fd, Heading) ->
+ file:write(Fd, banner(Heading)).
+
+banner(Heading) ->
+ ("\n\n"
+ "%%% -------------------------------------------------------\n"
+ "%%% " ++ Heading ++ ":\n"
+ "%%% -------------------------------------------------------\n\n").
+
+z(S) ->
+ string:join(string:tokens(S, "\s\t"), "\s").
+
+m_enums(Prefix, Wrap, Enums) ->
+ lists:map(fun(T) -> m_enum(Prefix, Wrap, T) end, Enums).
+
+m_enum(Prefix, B, {Name, Values}) ->
+ P = Prefix ++ to_upper(Name) ++ "_",
+ lists:map(fun({I,A}) ->
+ N = ["'", P, to_upper(z(atom_to_list(A))), "'"],
+ wrap(B,
+ N,
+ ["-define(", N, ", ", integer_to_list(I), ").\n"])
+ end,
+ Values).
+
+wrap(true, Name, Def) ->
+ ["-ifndef(", Name, ").\n", Def, "-endif.\n"];
+wrap(false, _, Def) ->
+ Def.
+
+to_upper(A) when is_atom(A) ->
+ to_upper(atom_to_list(A));
+to_upper(S) ->
+ lists:map(fun tu/1, S).
+
+tu(C) when C >= $a, C =< $z ->
+ C + $A - $a;
+tu(C) ->
+ C.
+
+header() ->
+ ("%% -------------------------------------------------------------------\n"
+ "%% This is a generated file.\n"
+ "%% -------------------------------------------------------------------\n"
+ "\n"
+ "%%\n"
+ "%% Copyright (c) Ericsson AB. All rights reserved.\n"
+ "%%\n"
+ "%% The information in this document is the property of Ericsson.\n"
+ "%%\n"
+ "%% Except as specifically authorized in writing by Ericsson, the\n"
+ "%% receiver of this document shall keep the information contained\n"
+ "%% herein confidential and shall protect the same in whole or in\n"
+ "%% part from disclosure and dissemination to third parties.\n"
+ "%%\n"
+ "%% Disclosure and disseminations to the receivers employees shall\n"
+ "%% only be made on a strict need to know basis.\n"
+ "%%\n\n").
+
+hrl_header(Name) ->
+ header() ++ "-hrl_name('" ++ Name ++ ".hrl').\n".
+
+%% avp_info/1
+
+avp_info(Entry) -> %% {Name, Arity}
+ case Entry of
+ {'<',A,'>'} -> {A, 1};
+ {A} -> {A, 1};
+ [A] -> {A, {0,1}};
+ {Q,T} ->
+ {A,_} = avp_info(T),
+ {A, arity(Q)}
+ end.
+
+%% Normalize arity to 1 or {N,X} where N is an integer. A record field
+%% for an AVP is list-valued iff the normalized arity is not 1.
+arity('*' = Inf) -> {0, Inf};
+arity({'*', N}) -> {0, N};
+arity({1,1}) -> 1;
+arity(T) -> T.
+
+prefix(Spec) ->
+ case orddict:find(prefix, Spec) of
+ {ok, P} ->
+ atom_to_list(P) ++ "_";
+ error ->
+ ""
+ end.
+
+rec_name(Name, Prefix) ->
+ list_to_atom(Prefix ++ atom_to_list(Name)).
diff --git a/lib/diameter/src/compiler/diameter_forms.hrl b/lib/diameter/src/compiler/diameter_forms.hrl
new file mode 100644
index 0000000000..d93131df34
--- /dev/null
+++ b/lib/diameter/src/compiler/diameter_forms.hrl
@@ -0,0 +1,52 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Macros used when building abstract code.
+%%
+
+%% Form tag with line number.
+-define(F(T), T, ?LINE).
+%% Yes, that's right. The replacement is to the first unmatched ')'.
+
+-define(attribute, ?F(attribute)).
+-define(clause, ?F(clause)).
+-define(function, ?F(function)).
+-define(call, ?F(call)).
+-define('fun', ?F('fun')).
+-define(generate, ?F(generate)).
+-define(lc, ?F(lc)).
+-define(match, ?F(match)).
+-define(remote, ?F(remote)).
+-define(record, ?F(record)).
+-define(record_field, ?F(record_field)).
+-define(record_index, ?F(record_index)).
+-define(tuple, ?F(tuple)).
+
+-define(ATOM(T), {atom, ?LINE, T}).
+-define(INTEGER(N), {integer, ?LINE, N}).
+-define(VAR(V), {var, ?LINE, V}).
+-define(NIL, {nil, ?LINE}).
+
+-define(CALL(F,A), {?call, ?ATOM(F), A}).
+-define(APPLY(M,F,A), {?call, {?remote, ?ATOM(M), ?ATOM(F)}, A}).
+-define(FIELDS(Fs), [{?record_field, ?ATOM(F), V} || {F,V} <- Fs]).
+
+%% Literal term.
+-define(TERM(T), erl_parse:abstract(T, ?LINE)).
diff --git a/lib/diameter/src/compiler/diameter_make.erl b/lib/diameter/src/compiler/diameter_make.erl
new file mode 100644
index 0000000000..4431b88c4d
--- /dev/null
+++ b/lib/diameter/src/compiler/diameter_make.erl
@@ -0,0 +1,120 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Driver for the encoder generator utility.
+%%
+
+-module(diameter_make).
+
+-export([spec/0,
+ hrl/0,
+ erl/0]).
+
+-spec spec() -> no_return().
+-spec hrl() -> no_return().
+-spec erl() -> no_return().
+
+spec() ->
+ make(spec).
+
+hrl() ->
+ make(hrl).
+
+erl() ->
+ make(erl).
+
+%% make/1
+
+make(Mode) ->
+ Args = init:get_plain_arguments(),
+ Opts = try options(Args) catch throw: help -> help(Mode) end,
+ Files = proplists:get_value(files, Opts, []),
+ lists:foreach(fun(F) -> from_file(F, Mode, Opts) end, Files),
+ halt(0).
+
+%% from_file/3
+
+from_file(F, Mode, Opts) ->
+ try to_spec(F, Mode, Opts) of
+ Spec ->
+ from_spec(F, Spec, Mode, Opts)
+ catch
+ error: Reason ->
+ io:format("==> ~p parse failure:~n~p~n",
+ [F, {Reason, erlang:get_stacktrace()}]),
+ halt(1)
+ end.
+
+%% to_spec/2
+
+%% Try to read the input as an already parsed file or else parse it.
+to_spec(F, spec, Opts) ->
+ diameter_spec_util:parse(F, Opts);
+to_spec(F, _, _) ->
+ {ok, [Spec]} = file:consult(F),
+ Spec.
+
+%% from_spec/4
+
+from_spec(File, Spec, Mode, Opts) ->
+ try
+ diameter_codegen:from_spec(File, Spec, Opts, Mode)
+ catch
+ error: Reason ->
+ io:format("==> ~p codegen failure:~n~p~n~p~n",
+ [Mode, File, {Reason, erlang:get_stacktrace()}]),
+ halt(1)
+ end.
+
+%% options/1
+
+options(["-v" | Rest]) ->
+ [verbose | options(Rest)];
+
+options(["-o", Outdir | Rest]) ->
+ [{outdir, Outdir} | options(Rest)];
+
+options(["-i", Incdir | Rest]) ->
+ [{include, Incdir} | options(Rest)];
+
+options(["-h" | _]) ->
+ throw(help);
+
+options(["--" | Fs]) ->
+ [{files, Fs}];
+
+options(["-" ++ _ = Opt | _]) ->
+ io:fwrite("==> unknown option: ~s~n", [Opt]),
+ throw(help);
+
+options(Fs) -> %% trailing arguments
+ options(["--" | Fs]).
+
+%% help/1
+
+help(M) ->
+ io:fwrite("Usage: ~p ~p [Options] [--] File ...~n"
+ "Options:~n"
+ " -v verbose output~n"
+ " -h shows this help message~n"
+ " -o OutDir where to put the output files~n"
+ " -i IncludeDir where to search for beams to import~n",
+ [?MODULE, M]),
+ halt(1).
diff --git a/lib/diameter/src/compiler/diameter_spec_scan.erl b/lib/diameter/src/compiler/diameter_spec_scan.erl
new file mode 100644
index 0000000000..bc0448882a
--- /dev/null
+++ b/lib/diameter/src/compiler/diameter_spec_scan.erl
@@ -0,0 +1,157 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_spec_scan).
+
+%%
+%% Functions used by the spec file parser in diameter_spec_util.
+%%
+
+-export([split/1,
+ split/2,
+ parse/1]).
+
+%%% -----------------------------------------------------------
+%%% # parse/1
+%%%
+%%% Output: list of Token
+%%%
+%%% Token = '{' | '}' | '<' | '>' | '[' | ']'
+%%% | '*' | '::=' | ':' | ',' | '-'
+%%% | {name, string()}
+%%% | {tag, atom()}
+%%% | {number, integer() >= 0}
+%%%
+%%% Tokenize a string. Fails if the string does not parse.
+%%% -----------------------------------------------------------
+
+parse(S) ->
+ parse(S, []).
+
+%% parse/2
+
+parse(S, Acc) ->
+ acc(split(S), Acc).
+
+acc({T, Rest}, Acc) ->
+ parse(Rest, [T | Acc]);
+acc("", Acc) ->
+ lists:reverse(Acc).
+
+%%% -----------------------------------------------------------
+%%% # split/2
+%%%
+%%% Output: {list() of Token, Rest}
+%%%
+%%% Extract a specified number of tokens from a string. Returns a list
+%%% of length less than the specified number if there are less than
+%%% this number of tokens to be parsed.
+%%% -----------------------------------------------------------
+
+split(Str, N)
+ when N >= 0 ->
+ split(N, Str, []).
+
+split(0, Str, Acc) ->
+ {lists:reverse(Acc), Str};
+
+split(N, Str, Acc) ->
+ case split(Str) of
+ {T, Rest} ->
+ split(N-1, Rest, [T|Acc]);
+ "" = Rest ->
+ {lists:reverse(Acc), Rest}
+ end.
+
+%%% -----------------------------------------------------------
+%%% # split/1
+%%%
+%%% Output: {Token, Rest} | ""
+%%%
+%%% Extract the next token from a string.
+%%% -----------------------------------------------------------
+
+split("" = Rest) ->
+ Rest;
+
+split("::=" ++ T) ->
+ {'::=', T};
+
+split([H|T])
+ when H == ${; H == $};
+ H == $<; H == $>;
+ H == $[; H == $];
+ H == $*; H == $:; H == $,; H == $- ->
+ {list_to_atom([H]), T};
+
+split([H|T]) when $A =< H, H =< $Z;
+ $0 =< H, H =< $9 ->
+ {P, Rest} = splitwith(fun is_name_ch/1, [H], T),
+ Tok = try
+ {number, read_int(P)}
+ catch
+ error:_ ->
+ {name, P}
+ end,
+ {Tok, Rest};
+
+split([H|T]) when $a =< H, H =< $z ->
+ {P, Rest} = splitwith(fun is_name_ch/1, [H], T),
+ {{tag, list_to_atom(P)}, Rest};
+
+split([H|T]) when H == $\t;
+ H == $\s;
+ H == $\n ->
+ split(T).
+
+%% read_int/1
+
+read_int([$0,X|S])
+ when X == $X;
+ X == $x ->
+ {ok, [N], []} = io_lib:fread("~16u", S),
+ N;
+
+read_int(S) ->
+ list_to_integer(S).
+
+%% splitwith/3
+
+splitwith(Fun, Acc, S) ->
+ split([] /= S andalso Fun(hd(S)), Fun, Acc, S).
+
+split(true, Fun, Acc, [H|T]) ->
+ splitwith(Fun, [H|Acc], T);
+split(false, _, Acc, S) ->
+ {lists:reverse(Acc), S}.
+
+is_name_ch(C) ->
+ is_alphanum(C) orelse C == $- orelse C == $_.
+
+is_alphanum(C) ->
+ is_lower(C) orelse is_upper(C) orelse is_digit(C).
+
+is_lower(C) ->
+ $a =< C andalso C =< $z.
+
+is_upper(C) ->
+ $A =< C andalso C =< $Z.
+
+is_digit(C) ->
+ $0 =< C andalso C =< $9.
diff --git a/lib/diameter/src/compiler/diameter_spec_util.erl b/lib/diameter/src/compiler/diameter_spec_util.erl
new file mode 100644
index 0000000000..b60886b678
--- /dev/null
+++ b/lib/diameter/src/compiler/diameter_spec_util.erl
@@ -0,0 +1,1068 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 module turns a .dia (aka spec) file into the orddict that
+%% diameter_codegen.erl in turn morphs into .erl and .hrl files for
+%% encode and decode of Diameter messages and AVPs.
+%%
+
+-module(diameter_spec_util).
+
+-export([parse/2]).
+
+-define(ERROR(T), erlang:error({T, ?MODULE, ?LINE})).
+-define(ATOM, list_to_atom).
+
+%% parse/1
+%%
+%% Output: orddict()
+
+parse(Path, Options) ->
+ put({?MODULE, verbose}, lists:member(verbose, Options)),
+ {ok, B} = file:read_file(Path),
+ Chunks = chunk(B),
+ Spec = make_spec(Chunks),
+ true = groups_defined(Spec), %% sanity checks
+ true = customs_defined(Spec), %%
+ Full = import_enums(import_groups(import_avps(insert_codes(Spec),
+ Options))),
+ true = enums_defined(Full), %% sanity checks
+ true = v_flags_set(Spec),
+ Full.
+
+%% Optional reports when running verbosely.
+report(What, Data) ->
+ report(get({?MODULE, verbose}), What, Data).
+
+report(true, Tag, Data) ->
+ io:format("##~n## ~p ~p~n", [Tag, Data]);
+report(false, _, _) ->
+ ok.
+
+%% chunk/1
+
+chunk(B) ->
+ chunkify(normalize(binary_to_list(B))).
+
+%% normalize/1
+%%
+%% Replace CR NL by NL, multiple NL by one, tab by space, and strip
+%% comments and leading/trailing space from each line. Precludes
+%% semicolons being used for any other purpose than comments.
+
+normalize(Str) ->
+ nh(Str, []).
+
+nh([], Acc) ->
+ lists:reverse(Acc);
+
+%% Trim leading whitespace.
+nh(Str, Acc) ->
+ nb(trim(Str), Acc).
+
+%% tab -> space
+nb([$\t|Rest], Acc) ->
+ nb(Rest, [$\s|Acc]);
+
+%% CR NL -> NL
+nb([$\r,$\n|Rest], Acc) ->
+ nt(Rest, Acc);
+
+%% Gobble multiple newlines before starting over again.
+nb([$\n|Rest], Acc) ->
+ nt(Rest, Acc);
+
+%% Comment.
+nb([$;|Rest], Acc) ->
+ nb(lists:dropwhile(fun(C) -> C /= $\n end, Rest), Acc);
+
+%% Just an ordinary character. Boring ...
+nb([C|Rest], Acc) ->
+ nb(Rest, [C|Acc]);
+
+nb([] = Str, Acc) ->
+ nt(Str, Acc).
+
+%% Discard a subsequent newline.
+nt(T, [$\n|_] = Acc) ->
+ nh(T, trim(Acc));
+
+%% Trim whitespace from the end of the line before continuing.
+nt(T, Acc) ->
+ nh(T, [$\n|trim(Acc)]).
+
+trim(S) ->
+ lists:dropwhile(fun(C) -> lists:member(C, "\s\t") end, S).
+
+%% chunkify/1
+%%
+%% Split the spec file into pieces delimited by lines starting with
+%% @Tag. Returns a list of {Tag, Args, Chunk} where Chunk is the
+%% string extending to the next delimiter. Note that leading
+%% whitespace has already been stripped.
+
+chunkify(Str) ->
+ %% Drop characters to the start of the first chunk.
+ {_, Rest} = split_chunk([$\n|Str]),
+ chunkify(Rest, []).
+
+chunkify([], Acc) ->
+ lists:reverse(Acc);
+
+chunkify(Rest, Acc) ->
+ {H,T} = split_chunk(Rest),
+ chunkify(T, [split_tag(H) | Acc]).
+
+split_chunk(Str) ->
+ split_chunk(Str, []).
+
+split_chunk([] = Rest, Acc) ->
+ {lists:reverse(Acc), Rest};
+split_chunk([$@|Rest], [$\n|_] = Acc) ->
+ {lists:reverse(Acc), Rest};
+split_chunk([C|Rest], Acc) ->
+ split_chunk(Rest, [C|Acc]).
+
+%% Expect a tag and its arguments on a single line.
+split_tag(Str) ->
+ {L, Rest} = get_until($\n, Str),
+ [{tag, Tag} | Toks] = diameter_spec_scan:parse(L),
+ {Tag, Toks, trim(Rest)}.
+
+get_until(EndT, L) ->
+ {H, [EndT | T]} = lists:splitwith(fun(C) -> C =/= EndT end, L),
+ {H,T}.
+
+%% ------------------------------------------------------------------------
+%% make_spec/1
+%%
+%% Turn chunks into spec.
+
+make_spec(Chunks) ->
+ lists:foldl(fun(T,A) -> report(chunk, T), chunk(T,A) end,
+ orddict:new(),
+ Chunks).
+
+chunk({T, [X], []}, Dict)
+ when T == name;
+ T == prefix ->
+ store(T, atomize(X), Dict);
+
+chunk({id = T, [{number, I}], []}, Dict) ->
+ store(T, I, Dict);
+
+chunk({vendor = T, [{number, I}, N], []}, Dict) ->
+ store(T, {I, atomize(N)}, Dict);
+
+%% inherits -> [{Mod, [AvpName, ...]}, ...]
+chunk({inherits = T, [_,_|_] = Args, []}, Acc) ->
+ Mods = [atomize(A) || A <- Args],
+ append_list(T, [{M,[]} || M <- Mods], Acc);
+chunk({inherits = T, [Mod], Body}, Acc) ->
+ append(T, {atomize(Mod), parse_avp_names(Body)}, Acc);
+
+%% avp_types -> [{AvpName, Code, Type, Flags, Encr}, ...]
+chunk({avp_types = T, [], Body}, Acc) ->
+ store(T, parse_avp_types(Body), Acc);
+
+%% custom_types -> [{Mod, [AvpName, ...]}, ...]
+chunk({custom_types = T, [Mod], Body}, Dict) ->
+ [_|_] = Avps = parse_avp_names(Body),
+ append(T, {atomize(Mod), Avps}, Dict);
+
+%% messages -> [{MsgName, Code, Type, Appl, Avps}, ...]
+chunk({messages = T, [], Body}, Acc) ->
+ store(T, parse_messages(Body), Acc);
+
+%% grouped -> [{AvpName, Code, Vendor, Avps}, ...]
+chunk({grouped = T, [], Body}, Acc) ->
+ store(T, parse_groups(Body), Acc);
+
+%% avp_vendor_id -> [{Id, [AvpName, ...]}, ...]
+chunk({avp_vendor_id = T, [{number, I}], Body}, Dict) ->
+ [_|_] = Names = parse_avp_names(Body),
+ append(T, {I, Names}, Dict);
+
+%% enums -> [{AvpName, [{Value, Name}, ...]}, ...]
+chunk({enum, [N], Str}, Dict) ->
+ append(enums, {atomize(N), parse_enums(Str)}, Dict);
+
+%% result_codes -> [{ResultName, [{Value, Name}, ...]}, ...]
+chunk({result_code, [N], Str}, Dict) ->
+ append(result_codes, {atomize(N), parse_enums(Str)}, Dict);
+
+%% commands -> [{Name, Abbrev}, ...]
+chunk({commands = T, [], Body}, Dict) ->
+ store(T, parse_commands(Body), Dict);
+
+chunk(T, _) ->
+ ?ERROR({unknown_tag, T}).
+
+store(Key, Value, Dict) ->
+ error == orddict:find(Key, Dict) orelse ?ERROR({duplicate, Key}),
+ orddict:store(Key, Value, Dict).
+append(Key, Value, Dict) ->
+ orddict:append(Key, Value, Dict).
+append_list(Key, Values, Dict) ->
+ orddict:append_list(Key, Values, Dict).
+
+atomize({tag, T}) ->
+ T;
+atomize({name, T}) ->
+ ?ATOM(T).
+
+get_value(Keys, Spec)
+ when is_list(Keys) ->
+ [get_value(K, Spec) || K <- Keys];
+get_value(Key, Spec) ->
+ proplists:get_value(Key, Spec, []).
+
+%% ------------------------------------------------------------------------
+%% enums_defined/1
+%% groups_defined/1
+%% customs_defined/1
+%%
+%% Ensure that every local enum/grouped/custom is defined as an avp
+%% with an appropriate type.
+
+enums_defined(Spec) ->
+ Avps = get_value(avp_types, Spec),
+ Import = get_value(import_enums, Spec),
+ lists:all(fun({N,_}) ->
+ true = enum_defined(N, Avps, Import)
+ end,
+ get_value(enums, Spec)).
+
+enum_defined(Name, Avps, Import) ->
+ case lists:keyfind(Name, 1, Avps) of
+ {Name, _, 'Enumerated', _, _} ->
+ true;
+ {Name, _, T, _, _} ->
+ ?ERROR({avp_has_wrong_type, Name, 'Enumerated', T});
+ false ->
+ lists:any(fun({_,Is}) -> lists:keymember(Name, 1, Is) end, Import)
+ orelse ?ERROR({avp_not_defined, Name, 'Enumerated'})
+ end.
+%% Note that an AVP is imported only if referenced by a message or
+%% grouped AVP, so the final branch will fail if an enum definition is
+%% extended without this being the case.
+
+groups_defined(Spec) ->
+ Avps = get_value(avp_types, Spec),
+ lists:all(fun({N,_,_,_}) -> true = group_defined(N, Avps) end,
+ get_value(grouped, Spec)).
+
+group_defined(Name, Avps) ->
+ case lists:keyfind(Name, 1, Avps) of
+ {Name, _, 'Grouped', _, _} ->
+ true;
+ {Name, _, T, _, _} ->
+ ?ERROR({avp_has_wrong_type, Name, 'Grouped', T});
+ false ->
+ ?ERROR({avp_not_defined, Name, 'Grouped'})
+ end.
+
+customs_defined(Spec) ->
+ Avps = get_value(avp_types, Spec),
+ lists:all(fun(A) -> true = custom_defined(A, Avps) end,
+ lists:flatmap(fun last/1, get_value(custom_types, Spec))).
+
+custom_defined(Name, Avps) ->
+ case lists:keyfind(Name, 1, Avps) of
+ {Name, _, T, _, _} when T == 'Grouped';
+ T == 'Enumerated' ->
+ ?ERROR({avp_has_invalid_custom_type, Name, T});
+ {Name, _, _, _, _} ->
+ true;
+ false ->
+ ?ERROR({avp_not_defined, Name})
+ end.
+
+last({_,Xs}) -> Xs.
+
+%% ------------------------------------------------------------------------
+%% v_flags_set/1
+
+v_flags_set(Spec) ->
+ Avps = get_value(avp_types, Spec)
+ ++ lists:flatmap(fun last/1, get_value(import_avps, Spec)),
+ Vs = lists:flatmap(fun last/1, get_value(avp_vendor_id, Spec)),
+
+ lists:all(fun(N) -> vset(N, Avps) end, Vs).
+
+vset(Name, Avps) ->
+ A = lists:keyfind(Name, 1, Avps),
+ false == A andalso ?ERROR({avp_not_defined, Name}),
+ {Name, _Code, _Type, Flags, _Encr} = A,
+ lists:member('V', Flags) orelse ?ERROR({v_flag_not_set, A}).
+
+%% ------------------------------------------------------------------------
+%% insert_codes/1
+
+insert_codes(Spec) ->
+ [Msgs, Cmds] = get_value([messages, commands], Spec),
+
+ %% Code -> [{Name, Flags}, ...]
+ Dict = lists:foldl(fun({N,C,Fs,_,_}, D) -> dict:append(C,{N,Fs},D) end,
+ dict:new(),
+ Msgs),
+
+ %% list() of {Code, {ReqName, ReqAbbr}, {AnsName, AnsAbbr}}
+ %% If the name and abbreviation are the same then the 2-tuples
+ %% are replaced by the common atom()-valued name.
+ Codes = dict:fold(fun(C,Ns,A) -> [make_code(C, Ns, Cmds) | A] end,
+ [],
+ dict:erase(-1, Dict)), %% answer-message
+
+ orddict:store(command_codes, Codes, Spec).
+
+make_code(Code, [_,_] = Ns, Cmds) ->
+ {Req, Ans} = make_names(Ns, lists:map(fun({_,Fs}) ->
+ lists:member('REQ', Fs)
+ end,
+ Ns)),
+ {Code, abbrev(Req, Cmds), abbrev(Ans, Cmds)};
+
+make_code(Code, Cs, _) ->
+ ?ERROR({missing_request_or_answer, Code, Cs}).
+
+%% 3.3. Diameter Command Naming Conventions
+%%
+%% Diameter command names typically includes one or more English words
+%% followed by the verb Request or Answer. Each English word is
+%% delimited by a hyphen. A three-letter acronym for both the request
+%% and answer is also normally provided.
+
+make_names([{Rname,_},{Aname,_}], [true, false]) ->
+ {Rname, Aname};
+make_names([{Aname,_},{Rname,_}], [false, true]) ->
+ {Rname, Aname};
+make_names([_,_] = Names, _) ->
+ ?ERROR({inconsistent_command_flags, Names}).
+
+abbrev(Name, Cmds) ->
+ case abbr(Name, get_value(Name, Cmds)) of
+ Name ->
+ Name;
+ Abbr ->
+ {Name, Abbr}
+ end.
+
+%% No explicit abbreviation: construct.
+abbr(Name, []) ->
+ ?ATOM(abbr(string:tokens(atom_to_list(Name), "-")));
+
+%% Abbreviation was specified.
+abbr(_Name, Abbr) ->
+ Abbr.
+
+%% No hyphens: already abbreviated.
+abbr([Abbr]) ->
+ Abbr;
+
+%% XX-Request/Answer ==> XXR/XXA
+abbr([[_,_] = P, T])
+ when T == "Request";
+ T == "Answer" ->
+ P ++ [hd(T)];
+
+%% XXX-...-YYY-Request/Answer ==> X...YR/X...YA
+abbr([_,_|_] = L) ->
+ lists:map(fun erlang:hd/1, L).
+
+%% ------------------------------------------------------------------------
+%% import_avps/2
+
+import_avps(Spec, Options) ->
+ Msgs = get_value(messages, Spec),
+ Groups = get_value(grouped, Spec),
+
+ %% Messages and groups require AVP's referenced by them.
+ NeededAvps
+ = ordsets:from_list(lists:flatmap(fun({_,_,_,_,As}) ->
+ [avp_name(A) || A <- As]
+ end,
+ Msgs)
+ ++ lists:flatmap(fun({_,_,_,As}) ->
+ [avp_name(A) || A <- As]
+ end,
+ Groups)),
+ MissingAvps = missing_avps(NeededAvps, Spec),
+
+ report(needed, NeededAvps),
+ report(missing, MissingAvps),
+
+ Import = inherit(get_value(inherits, Spec), Options),
+
+ report(imported, Import),
+
+ ImportedAvps = lists:map(fun({N,_,_,_,_}) -> N end,
+ lists:flatmap(fun last/1, Import)),
+
+ Unknown = MissingAvps -- ImportedAvps,
+
+ [] == Unknown orelse ?ERROR({undefined_avps, Unknown}),
+
+ orddict:store(import_avps, Import, orddict:erase(inherits, Spec)).
+
+%% missing_avps/2
+%%
+%% Given a list of AVP names and parsed spec, return the list of
+%% AVP's that aren't defined in this spec.
+
+missing_avps(NeededNames, Spec) ->
+ Avps = get_value(avp_types, Spec),
+ Groups = lists:map(fun({N,_,_,As}) ->
+ {N, [avp_name(A) || A <- As]}
+ end,
+ get_value(grouped, Spec)),
+ Names = ordsets:from_list(['AVP' | lists:map(fun({N,_,_,_,_}) -> N end,
+ Avps)]),
+ missing_avps(NeededNames, [], {Names, Groups}).
+
+avp_name({'<',A,'>'}) -> A;
+avp_name({A}) -> A;
+avp_name([A]) -> A;
+avp_name({_, A}) -> avp_name(A).
+
+missing_avps(NeededNames, MissingNames, {Names, _} = T) ->
+ missing(ordsets:filter(fun(N) -> lists:member(N, NeededNames) end, Names),
+ ordsets:union(NeededNames, MissingNames),
+ T).
+
+%% Nothing found locally.
+missing([], MissingNames, _) ->
+ MissingNames;
+
+%% Or not. Keep looking for for the AVP's needed by the found AVP's of
+%% type Grouped.
+missing(FoundNames, MissingNames, {_, Groups} = T) ->
+ NeededNames = lists:flatmap(fun({N,As}) ->
+ choose(lists:member(N, FoundNames), As, [])
+ end,
+ Groups),
+ missing_avps(ordsets:from_list(NeededNames),
+ ordsets:subtract(MissingNames, FoundNames),
+ T).
+
+%% inherit/2
+
+inherit(Inherits, Options) ->
+ Dirs = [D || {include, D} <- Options] ++ ["."],
+ lists:foldl(fun(T,A) -> find_avps(T, A, Dirs) end, [], Inherits).
+
+find_avps({Mod, AvpNames}, Acc, Path) ->
+ report(inherit_from, Mod),
+ Avps = avps_from_beam(find_beam(Mod, Path), Mod), %% could be empty
+ [{Mod, lists:sort(find_avps(AvpNames, Avps))} | Acc].
+
+find_avps([], Avps) ->
+ Avps;
+find_avps(Names, Avps) ->
+ lists:filter(fun({N,_,_,_,_}) -> lists:member(N, Names) end, Avps).
+
+%% find_beam/2
+
+find_beam(Mod, Dirs)
+ when is_atom(Mod) ->
+ find_beam(atom_to_list(Mod), Dirs);
+find_beam(Mod, Dirs) ->
+ Beam = Mod ++ code:objfile_extension(),
+ case try_path(Dirs, Beam) of
+ {value, Path} ->
+ Path;
+ false ->
+ ?ERROR({beam_not_on_path, Beam, Dirs})
+ end.
+
+try_path([D|Ds], Fname) ->
+ Path = filename:join(D, Fname),
+ case file:read_file_info(Path) of
+ {ok, _} ->
+ {value, Path};
+ _ ->
+ try_path(Ds, Fname)
+ end;
+try_path([], _) ->
+ false.
+
+%% avps_from_beam/2
+
+avps_from_beam(Path, Mod) ->
+ report(beam, Path),
+ ok = load_module(code:is_loaded(Mod), Mod, Path),
+ orddict:fetch(avp_types, Mod:dict()).
+
+load_module(false, Mod, Path) ->
+ R = filename:rootname(Path, code:objfile_extension()),
+ {module, Mod} = code:load_abs(R),
+ ok;
+load_module({file, _}, _, _) ->
+ ok.
+
+choose(true, X, _) -> X;
+choose(false, _, X) -> X.
+
+%% ------------------------------------------------------------------------
+%% import_groups/1
+%% import_enums/1
+%%
+%% For each inherited module, store the content of imported AVP's of
+%% type grouped/enumerated in a new key.
+
+import_groups(Spec) ->
+ orddict:store(import_groups, import(grouped, Spec), Spec).
+
+import_enums(Spec) ->
+ orddict:store(import_enums, import(enums, Spec), Spec).
+
+import(Key, Spec) ->
+ lists:flatmap(fun(T) -> import_key(Key, T) end,
+ get_value(import_avps, Spec)).
+
+import_key(Key, {Mod, Avps}) ->
+ Imports = lists:flatmap(fun(T) ->
+ choose(lists:keymember(element(1,T),
+ 1,
+ Avps),
+ [T],
+ [])
+ end,
+ get_value(Key, Mod:dict())),
+ if Imports == [] ->
+ [];
+ true ->
+ [{Mod, Imports}]
+ end.
+
+%% ------------------------------------------------------------------------
+%% parse_enums/1
+%%
+%% Enums are specified either as the integer value followed by the
+%% name or vice-versa. In the former case the name of the enum is
+%% taken to be the string up to the end of line, which may contain
+%% whitespace. In the latter case the integer may be parenthesized,
+%% specified in hex and followed by an inline comment. This is
+%% historical and will likely be changed to require a precise input
+%% format.
+%%
+%% Output: list() of {integer(), atom()}
+
+parse_enums(Str) ->
+ lists:flatmap(fun(L) -> parse_enum(trim(L)) end, string:tokens(Str, "\n")).
+
+parse_enum([]) ->
+ [];
+
+parse_enum(Str) ->
+ REs = [{"^(0[xX][0-9A-Fa-f]+|[0-9]+)\s+(.*?)\s*$", 1, 2},
+ {"^(.+?)\s+(0[xX][0-9A-Fa-f]+|[0-9]+)(\s+.*)?$", 2, 1},
+ {"^(.+?)\s+\\((0[xX][0-9A-Fa-f]+|[0-9]+)\\)(\s+.*)?$", 2, 1}],
+ parse_enum(Str, REs).
+
+parse_enum(Str, REs) ->
+ try lists:foreach(fun(R) -> enum(Str, R) end, REs) of
+ ok ->
+ ?ERROR({bad_enum, Str})
+ catch
+ throw: {enum, T} ->
+ [T]
+ end.
+
+enum(Str, {Re, I, N}) ->
+ case re:run(Str, Re, [{capture, all_but_first, list}]) of
+ {match, Vs} ->
+ T = list_to_tuple(Vs),
+ throw({enum, {to_int(element(I,T)), ?ATOM(element(N,T))}});
+ nomatch ->
+ ok
+ end.
+
+to_int([$0,X|Hex])
+ when X == $x;
+ X == $X ->
+ {ok, [I], _} = io_lib:fread("~#", "16#" ++ Hex),
+ I;
+to_int(I) ->
+ list_to_integer(I).
+
+%% ------------------------------------------------------------------------
+%% parse_messages/1
+%%
+%% Parse according to the ABNF for message specifications in 3.2 of
+%% RFC 3588 (shown below). We require all message and AVP names to
+%% start with a digit or uppercase character, except for the base
+%% answer-message, which is treated as a special case. Allowing names
+%% that start with a digit is more than the RFC specifies but the name
+%% doesn't affect what's sent over the wire. (Certains 3GPP standards
+%% use names starting with a digit. eg 3GPP-Charging-Id in TS32.299.)
+
+%%
+%% Sadly, not even the RFC follows this grammar. In particular, except
+%% in the example in 3.2, it wraps each command-name in angle brackets
+%% ('<' '>') which makes parsing a sequence of specifications require
+%% lookahead: after 'optional' avps have been parsed, it's not clear
+%% whether a '<' is a 'fixed' or whether it's the start of a
+%% subsequent message until we see whether or not '::=' follows the
+%% closing '>'. Require the grammar as specified.
+%%
+%% Output: list of {Name, Code, Flags, ApplId, Avps}
+%%
+%% Name = atom()
+%% Code = integer()
+%% Flags = integer()
+%% ApplId = [] | [integer()]
+%% Avps = see parse_avps/1
+
+parse_messages(Str) ->
+ p_cmd(trim(Str), []).
+
+%% command-def = command-name "::=" diameter-message
+%%
+%% command-name = diameter-name
+%%
+%% diameter-name = ALPHA *(ALPHA / DIGIT / "-")
+%%
+%% diameter-message = header [ *fixed] [ *required] [ *optional]
+%% [ *fixed]
+%%
+%% header = "<" Diameter-Header:" command-id
+%% [r-bit] [p-bit] [e-bit] [application-id]">"
+%%
+%% The header spec (and example that follows it) is slightly mangled
+%% and, given the examples in the RFC should as follows:
+%%
+%% header = "<" "Diameter Header:" command-id
+%% [r-bit] [p-bit] [e-bit] [application-id]">"
+%%
+%% This is what's required/parsed below, modulo whitespace. This is
+%% also what's specified in the current draft standard at
+%% http://ftp.ietf.org/drafts/wg/dime.
+%%
+%% Note that the grammar specifies the order fixed, required,
+%% optional. In practise there seems to be little difference between
+%% the latter two since qualifiers can be used to change the
+%% semantics. For example 1*[XXX] and *1{YYY} specify 1 or more of the
+%% optional avp XXX and 0 or 1 of the required avp YYY, making the
+%% iotional avp required and the required avp optional. The current
+%% draft addresses this somewhat by requiring that min for a qualifier
+%% on an optional avp must be 0 if present. It doesn't say anything
+%% about required avps however, so specifying a min of 0 would still
+%% be possible. The draft also does away with the trailing *fixed.
+%%
+%% What will be parsed here will treat required and optional
+%% interchangeably. That is. only require that required/optional
+%% follow and preceed fixed, not that optional avps must follow
+%% required ones. We already have several specs for which this parsing
+%% is necessary and there seems to be no harm in accepting it.
+
+p_cmd("", Acc) ->
+ lists:reverse(Acc);
+
+p_cmd(Str, Acc) ->
+ {Next, Rest} = split_def(Str),
+ report(command, Next),
+ p_cmd(Rest, [p_cmd(Next) | Acc]).
+
+p_cmd("answer-message" ++ Str) ->
+ p_header([{name, 'answer-message'} | diameter_spec_scan:parse(Str)]);
+
+p_cmd(Str) ->
+ p_header(diameter_spec_scan:parse(Str)).
+
+%% p_header/1
+
+p_header(['<', {name, _} = N, '>' | Toks]) ->
+ p_header([N | Toks]);
+
+p_header([{name, 'answer-message' = N}, '::=',
+ '<', {name, "Diameter"}, {name, "Header"}, ':', {tag, code},
+ ',', {name, "ERR"}, '[', {name, "PXY"}, ']', '>'
+ | Toks]) ->
+ {N, -1, ['ERR', 'PXY'], [], parse_avps(Toks)};
+
+p_header([{name, Name}, '::=',
+ '<', {name, "Diameter"}, {name, "Header"}, ':', {number, Code}
+ | Toks]) ->
+ {Flags, Rest} = p_flags(Toks),
+ {ApplId, [C|_] = R} = p_appl(Rest),
+ '>' == C orelse ?ERROR({invalid_flag, {Name, Code, Flags, ApplId}, R}),
+ {?ATOM(Name), Code, Flags, ApplId, parse_avps(tl(R))};
+
+p_header(Toks) ->
+ ?ERROR({invalid_header, Toks}).
+
+%% application-id = 1*DIGIT
+%%
+%% command-id = 1*DIGIT
+%% ; The Command Code assigned to the command
+%%
+%% r-bit = ", REQ"
+%% ; If present, the 'R' bit in the Command
+%% ; Flags is set, indicating that the message
+%% ; is a request, as opposed to an answer.
+%%
+%% p-bit = ", PXY"
+%% ; If present, the 'P' bit in the Command
+%% ; Flags is set, indicating that the message
+%% ; is proxiable.
+%%
+%% e-bit = ", ERR"
+%% ; If present, the 'E' bit in the Command
+%% ; Flags is set, indicating that the answer
+%% ; message contains a Result-Code AVP in
+%% ; the "protocol error" class.
+
+p_flags(Toks) ->
+ lists:foldl(fun p_flags/2, {[], Toks}, ["REQ", "PXY", "ERR"]).
+
+p_flags(N, {Acc, [',', {name, N} | Toks]}) ->
+ {[?ATOM(N) | Acc], Toks};
+
+p_flags(_, T) ->
+ T.
+
+%% The RFC doesn't specify ',' before application-id but this seems a
+%% bit inconsistent. Accept a comma if it exists.
+p_appl([',', {number, I} | Toks]) ->
+ {[I], Toks};
+p_appl([{number, I} | Toks]) ->
+ {[I], Toks};
+p_appl(Toks) ->
+ {[], Toks}.
+
+%% parse_avps/1
+%%
+%% Output: list() of Avp | {Qual, Avp}
+%%
+%% Qual = '*' | {Min, '*'} | {'*', Max} | {Min, Max}
+%% Avp = {'<', Name, '>'} | {Name} | [Name]
+%%
+%% Min, Max = integer() >= 0
+
+parse_avps(Toks) ->
+ p_avps(Toks, ['<', '|', '<'], []).
+%% The list corresponds to the delimiters expected at the front, middle
+%% and back of the avp specification, '|' representing '{' and '['.
+
+%% fixed = [qual] "<" avp-spec ">"
+%% ; Defines the fixed position of an AVP
+%%
+%% required = [qual] "{" avp-spec "}"
+%% ; The AVP MUST be present and can appear
+%% ; anywhere in the message.
+%%
+%% optional = [qual] "[" avp-name "]"
+%% ; The avp-name in the 'optional' rule cannot
+%% ; evaluate to any AVP Name which is included
+%% ; in a fixed or required rule. The AVP can
+%% ; appear anywhere in the message.
+%%
+%% qual = [min] "*" [max]
+%% ; See ABNF conventions, RFC 2234 Section 6.6.
+%% ; The absence of any qualifiers depends on whether
+%% ; it precedes a fixed, required, or optional
+%% ; rule. If a fixed or required rule has no
+%% ; qualifier, then exactly one such AVP MUST
+%% ; be present. If an optional rule has no
+%% ; qualifier, then 0 or 1 such AVP may be
+%% ; present.
+%% ;
+%% ; NOTE: "[" and "]" have a different meaning
+%% ; than in ABNF (see the optional rule, above).
+%% ; These braces cannot be used to express
+%% ; optional fixed rules (such as an optional
+%% ; ICV at the end). To do this, the convention
+%% ; is '0*1fixed'.
+%%
+%% min = 1*DIGIT
+%% ; The minimum number of times the element may
+%% ; be present. The default value is zero.
+%%
+%% max = 1*DIGIT
+%% ; The maximum number of times the element may
+%% ; be present. The default value is infinity. A
+%% ; value of zero implies the AVP MUST NOT be
+%% ; present.
+%%
+%% avp-spec = diameter-name
+%% ; The avp-spec has to be an AVP Name, defined
+%% ; in the base or extended Diameter
+%% ; specifications.
+%%
+%% avp-name = avp-spec / "AVP"
+%% ; The string "AVP" stands for *any* arbitrary
+%% ; AVP Name, which does not conflict with the
+%% ; required or fixed position AVPs defined in
+%% ; the command code definition.
+%%
+
+p_avps([], _, Acc) ->
+ lists:reverse(Acc);
+
+p_avps(Toks, Delim, Acc) ->
+ {Qual, Rest} = p_qual(Toks),
+ {Avp, R, D} = p_avp(Rest, Delim),
+ T = if Qual == false ->
+ Avp;
+ true ->
+ {Qual, Avp}
+ end,
+ p_avps(R, D, [T | Acc]).
+
+p_qual([{number, Min}, '*', {number, Max} | Toks]) ->
+ {{Min, Max}, Toks};
+p_qual([{number, Min}, '*' = Max | Toks]) ->
+ {{Min, Max}, Toks};
+p_qual(['*' = Min, {number, Max} | Toks]) ->
+ {{Min, Max}, Toks};
+p_qual(['*' = Q | Toks]) ->
+ {Q, Toks};
+p_qual(Toks) ->
+ {false, Toks}.
+
+p_avp([B, {name, Name}, E | Toks], [_|_] = Delim) ->
+ {avp(B, ?ATOM(Name), E),
+ Toks,
+ delim(choose(B == '<', B, '|'), Delim)};
+p_avp(Toks, Delim) ->
+ ?ERROR({invalid_avp, Toks, Delim}).
+
+avp('<' = B, Name, '>' = E) ->
+ {B, Name, E};
+avp('{', Name, '}') ->
+ {Name};
+avp('[', Name, ']') ->
+ [Name];
+avp(B, Name, E) ->
+ ?ERROR({invalid_avp, B, Name, E}).
+
+delim(B, D) ->
+ if B == hd(D) -> D; true -> tl(D) end.
+
+%% split_def/1
+%%
+%% Strip one command definition off head of a string.
+
+split_def(Str) ->
+ sdh(Str, []).
+
+%% Look for the "::=" starting off the definition.
+sdh("", _) ->
+ ?ERROR({missing, '::='});
+sdh("::=" ++ Rest, Acc) ->
+ sdb(Rest, [$=,$:,$:|Acc]);
+sdh([C|Rest], Acc) ->
+ sdh(Rest, [C|Acc]).
+
+%% Look for the "::=" starting off the following definition.
+sdb("::=" ++ _ = Rest, Acc) ->
+ sdt(trim(Acc), Rest);
+sdb("" = Rest, Acc) ->
+ sd(Acc, Rest);
+sdb([C|Rest], Acc) ->
+ sdb(Rest, [C|Acc]).
+
+%% Put name characters of the subsequent specification back into Rest.
+sdt([C|Acc], Rest)
+ when C /= $\n, C /= $\s ->
+ sdt(Acc, [C|Rest]);
+
+sdt(Acc, Rest) ->
+ sd(Acc, Rest).
+
+sd(Acc, Rest) ->
+ {trim(lists:reverse(Acc)), Rest}.
+%% Note that Rest is already trimmed of leading space.
+
+%% ------------------------------------------------------------------------
+%% parse_groups/1
+%%
+%% Parse according to the ABNF for message specifications in 4.4 of
+%% RFC 3588 (shown below). Again, allow names starting with a digit
+%% and also require "AVP Header" without "-" since this is what
+%% the RFC uses in all examples.
+%%
+%% Output: list of {Name, Code, Vendor, Avps}
+%%
+%% Name = atom()
+%% Code = integer()
+%% Vendor = [] | [integer()]
+%% Avps = see parse_avps/1
+
+parse_groups(Str) ->
+ p_group(trim(Str), []).
+
+%% grouped-avp-def = name "::=" avp
+%%
+%% name-fmt = ALPHA *(ALPHA / DIGIT / "-")
+%%
+%% name = name-fmt
+%% ; The name has to be the name of an AVP,
+%% ; defined in the base or extended Diameter
+%% ; specifications.
+%%
+%% avp = header [ *fixed] [ *required] [ *optional]
+%% [ *fixed]
+%%
+%% header = "<" "AVP-Header:" avpcode [vendor] ">"
+%%
+%% avpcode = 1*DIGIT
+%% ; The AVP Code assigned to the Grouped AVP
+%%
+%% vendor = 1*DIGIT
+%% ; The Vendor-ID assigned to the Grouped AVP.
+%% ; If absent, the default value of zero is
+%% ; used.
+
+p_group("", Acc) ->
+ lists:reverse(Acc);
+
+p_group(Str, Acc) ->
+ {Next, Rest} = split_def(Str),
+ report(group, Next),
+ p_group(Rest, [p_group(diameter_spec_scan:parse(Next)) | Acc]).
+
+p_group([{name, Name}, '::=', '<', {name, "AVP"}, {name, "Header"},
+ ':', {number, Code}
+ | Toks]) ->
+ {Id, [C|_] = R} = p_vendor(Toks),
+ C == '>' orelse ?ERROR({invalid_group_header, R}),
+ {?ATOM(Name), Code, Id, parse_avps(tl(R))};
+
+p_group(Toks) ->
+ ?ERROR({invalid_group, Toks}).
+
+p_vendor([{number, I} | Toks]) ->
+ {[I], Toks};
+p_vendor(Toks) ->
+ {[], Toks}.
+
+%% ------------------------------------------------------------------------
+%% parse_avp_names/1
+
+parse_avp_names(Str) ->
+ [p_name(N) || N <- diameter_spec_scan:parse(Str)].
+
+p_name({name, N}) ->
+ ?ATOM(N);
+p_name(T) ->
+ ?ERROR({invalid_avp_name, T}).
+
+%% ------------------------------------------------------------------------
+%% parse_avp_types/1
+%%
+%% Output: list() of {Name, Code, Type, Flags, Encr}
+
+parse_avp_types(Str) ->
+ p_avp_types(Str, []).
+
+p_avp_types(Str, Acc) ->
+ p_type(diameter_spec_scan:split(Str, 3), Acc).
+
+p_type({[],[]}, Acc) ->
+ lists:reverse(Acc);
+
+p_type({[{name, Name}, {number, Code}, {name, Type}], Str}, Acc) ->
+ {Flags, Encr, Rest} = try
+ p_avp_flags(trim(Str), [])
+ catch
+ throw: {?MODULE, Reason} ->
+ ?ERROR({invalid_avp_type, Reason})
+ end,
+ p_avp_types(Rest, [{?ATOM(Name), Code, ?ATOM(type(Type)), Flags, Encr}
+ | Acc]);
+
+p_type(T, _) ->
+ ?ERROR({invalid_avp_type, T}).
+
+p_avp_flags([C|Str], Acc)
+ when C == $M;
+ C == $P;
+ C == $V ->
+ p_avp_flags(Str, [?ATOM([C]) | Acc]);
+%% Could support lowercase here if there's a use for distinguishing
+%% between Must and Should in the future in deciding whether or not
+%% to set a flag.
+
+p_avp_flags([$-|Str], Acc) ->
+ %% Require encr on same line as flags if specified.
+ {H,T} = lists:splitwith(fun(C) -> C /= $\n end, Str),
+
+ {[{name, [$X|X]} | Toks], Rest} = diameter_spec_scan:split([$X|H], 2),
+
+ "" == X orelse throw({?MODULE, {invalid_avp_flag, Str}}),
+
+ Encr = case Toks of
+ [] ->
+ "-";
+ [{_, E}] ->
+ (E == "Y" orelse E == "N")
+ orelse throw({?MODULE, {invalid_encr, E}}),
+ E
+ end,
+
+ Flags = ordsets:from_list(lists:reverse(Acc)),
+
+ {Flags, ?ATOM(Encr), Rest ++ T};
+
+p_avp_flags(Str, Acc) ->
+ p_avp_flags([$-|Str], Acc).
+
+type("DiamIdent") -> "DiameterIdentity"; %% RFC 3588
+type("DiamURI") -> "DiameterURI"; %% RFC 3588
+type("IPFltrRule") -> "IPFilterRule"; %% RFC 4005
+type("QoSFltrRule") -> "QoSFilterRule"; %% RFC 4005
+type(N)
+ when N == "OctetString";
+ N == "Integer32";
+ N == "Integer64";
+ N == "Unsigned32";
+ N == "Unsigned64";
+ N == "Float32";
+ N == "Float64";
+ N == "Grouped";
+ N == "Enumerated";
+ N == "Address";
+ N == "Time";
+ N == "UTF8String";
+ N == "DiameterIdentity";
+ N == "DiameterURI";
+ N == "IPFilterRule";
+ N == "QoSFilterRule" ->
+ N;
+type(N) ->
+ ?ERROR({invalid_avp_type, N}).
+
+%% ------------------------------------------------------------------------
+%% parse_commands/1
+
+parse_commands(Str) ->
+ p_abbr(diameter_spec_scan:parse(Str), []).
+
+ p_abbr([{name, Name}, {name, Abbrev} | Toks], Acc)
+ when length(Abbrev) < length(Name) ->
+ p_abbr(Toks, [{?ATOM(Name), ?ATOM(Abbrev)} | Acc]);
+
+p_abbr([], Acc) ->
+ lists:reverse(Acc);
+
+p_abbr(T, _) ->
+ ?ERROR({invalid_command, T}).
diff --git a/lib/diameter/src/compiler/modules.mk b/lib/diameter/src/compiler/modules.mk
new file mode 100644
index 0000000000..17a311dacf
--- /dev/null
+++ b/lib/diameter/src/compiler/modules.mk
@@ -0,0 +1,27 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+MODULES = \
+ diameter_codegen \
+ diameter_spec_scan \
+ diameter_spec_util
+
+HRL_FILES = \
+ diameter_forms.hrl
+
diff --git a/lib/diameter/src/subdirs.mk b/lib/diameter/src/subdirs.mk
new file mode 100644
index 0000000000..3e12d935bc
--- /dev/null
+++ b/lib/diameter/src/subdirs.mk
@@ -0,0 +1,21 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+SUB_DIRS = compiler app transport
+SUB_DIRECTORIES = $(SUB_DIRS) \ No newline at end of file
diff --git a/lib/diameter/src/transport/.gitignore b/lib/diameter/src/transport/.gitignore
new file mode 100644
index 0000000000..d9f072e262
--- /dev/null
+++ b/lib/diameter/src/transport/.gitignore
@@ -0,0 +1,3 @@
+
+/depend.mk
+
diff --git a/lib/diameter/src/transport/Makefile b/lib/diameter/src/transport/Makefile
new file mode 100644
index 0000000000..4b53100fd2
--- /dev/null
+++ b/lib/diameter/src/transport/Makefile
@@ -0,0 +1,141 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+#
+
+ifneq ($(ERL_TOP),)
+include $(ERL_TOP)/make/target.mk
+EBIN = ../../ebin
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+else
+include $(DIAMETER_TOP)/make/target.mk
+EBIN = ../../ebin
+include $(DIAMETER_TOP)/make/$(TARGET)/rules.mk
+endif
+
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+
+include ../../vsn.mk
+VSN=$(DIAMETER_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+
+RELSYSDIR = $(RELEASE_PATH)/lib/diameter-$(VSN)
+
+INCDIR = ../../include
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+include modules.mk
+
+ERL_FILES = \
+ $(MODULES:%=%.erl)
+
+TARGET_FILES = \
+ $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+
+ifeq ($(TYPE),debug)
+ERL_COMPILE_FLAGS += -Ddebug
+endif
+
+include ../app/diameter.mk
+
+ERL_COMPILE_FLAGS += \
+ $(DIAMETER_ERL_COMPILE_FLAGS) \
+ -I$(INCDIR)
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+debug:
+ @${MAKE} TYPE=debug opt
+
+opt: $(TARGET_FILES)
+
+clean:
+ rm -f $(TARGET_FILES)
+ rm -f errs core *~
+ rm -f depend.mk
+
+docs:
+
+info:
+ @echo ""
+ @echo "ERL_FILES = $(ERL_FILES)"
+ @echo "HRL_FILES = $(HRL_FILES)"
+ @echo ""
+ @echo "TARGET_FILES = $(TARGET_FILES)"
+ @echo ""
+
+# ----------------------------------------------------
+# Special Build Targets
+# ----------------------------------------------------
+
+# Invoked from ../app to add modules to the app file.
+$(APP_TARGET): force
+ M=`echo $(MODULES) | sed -e 's/^ *//' -e 's/ *$$//' -e 'y/ /,/'`; \
+ echo "/%TRANSPORT_MODULES%/s//$$M/;w;q" | tr ';' '\n' \
+ | ed -s $@
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+ifneq ($(ERL_TOP),)
+include $(ERL_TOP)/make/otp_release_targets.mk
+else
+include $(DIAMETER_TOP)/make/release_targets.mk
+endif
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) $(RELSYSDIR)/src/transport
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/src/transport
+
+release_docs_spec:
+
+force:
+
+# ----------------------------------------------------
+# Dependencies
+# ----------------------------------------------------
+
+depend: depend.mk
+
+# Generate dependencies makefile.
+depend.mk: ../app/depend.sed $(ERL_FILES) Makefile
+ for f in $(MODULES); do \
+ sed -f $< $$f.erl | sed "s@/@/$$f@"; \
+ done \
+ > $@
+
+-include depend.mk
+
+.PHONY: clean debug depend docs force info opt release_docs_spec release_spec
diff --git a/lib/diameter/src/transport/diameter_etcp.erl b/lib/diameter/src/transport/diameter_etcp.erl
new file mode 100644
index 0000000000..d925d62545
--- /dev/null
+++ b/lib/diameter/src/transport/diameter_etcp.erl
@@ -0,0 +1,311 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 module implements a transport_module that uses Erlang message
+%% passing for transport.
+%%
+
+-module(diameter_etcp).
+
+-behaviour(gen_server).
+
+%% transport_module interface.
+-export([start/3]).
+
+%% gen_tcp-ish interface used by diameter_tcp.
+-export([listen/2,
+ accept/1,
+ connect/3,
+ send/2,
+ close/1,
+ setopts/2,
+ port/1]).
+
+%% child start
+-export([start_link/1]).
+
+%% gen_server callbacks
+-export([init/1,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ code_change/3,
+ terminate/2]).
+
+%% Server states.
+
+-record(listener,
+ {acceptors = [] :: [pid()]}).
+
+-record(connection,
+ {parent :: pid(),
+ peer :: {connect, reference()} %% {connect, MRef}
+ | accept
+ | pid()}).
+
+%% start/3
+
+%% 'module' option makes diameter_tcp call here instead of gen_tcp/inet.
+start(T, Svc, Opts)
+ when is_list(Opts) ->
+ diameter_etcp_sup:start(),
+ diameter_tcp:start(T, Svc, [{module, ?MODULE} | Opts]).
+
+%% listen/2
+%%
+%% Spawn a process that represents the listening socket. The local
+%% port number can be any term, not just an integer. The listener
+%% process registers its host/port with diameter_reg and this is the
+%% handle with which connect/3 finds the appropriate listening
+%% process.
+
+listen(LPort, Opts) ->
+ Parent = self(),
+ diameter_etcp_sup:start_child({listen, Parent, LPort, Opts}).
+
+%% accept/1
+%%
+%% Output: pid()
+
+accept(LPid) ->
+ start(fun(Ref, Parent) -> acceptor(LPid, Ref, Parent) end).
+
+%% connect/3
+%%
+%% Output: pid()
+
+%% RAddr here can either be a 4/8-tuple address or {Node, Addr}.
+connect(RAddr, RPort, _Opts) ->
+ start(fun(Ref, Parent) -> connector(RAddr, RPort, Ref, Parent) end).
+
+%% send/2
+
+send(Pid, Bin) ->
+ Pid ! {send, Bin},
+ ok.
+
+%% close/1
+
+close(Pid) ->
+ Pid ! close,
+ monitor(Pid),
+ receive {'DOWN', _, process, Pid, _} -> ok end.
+
+%% setopts/2
+
+setopts(_, _) ->
+ ok.
+
+%% port/1
+
+port(_) ->
+ 3868. %% We have no local port: fake it.
+
+%% start_link/1
+
+start_link(T) ->
+ gen_server:start_link(?MODULE, T, []).
+
+%% ---------------------------------------------------------------------------
+%% # init/1
+%% ---------------------------------------------------------------------------
+
+%% Maintain a list of acceptor pids as the process state. Each accept
+%% adds a pid to the list, each connect removes one.
+init({listen, Parent, LPort, Opts}) ->
+ monitor(Parent),
+ {ip, LAddr} = lists:keyfind(ip, 1, Opts),
+ true = diameter_reg:add_new({?MODULE, listener, LAddr, LPort}),
+ {ok, #listener{}};
+
+init({connect, Fun, Ref, Parent}) ->
+ {ok, #connection{parent = Parent,
+ peer = Fun(Ref, Parent)}}.
+
+%% ---------------------------------------------------------------------------
+%% # handle_call/3
+%% ---------------------------------------------------------------------------
+
+handle_call(_, _, State) ->
+ {reply, nok, State}.
+
+%% ---------------------------------------------------------------------------
+%% # handle_cast/2
+%% ---------------------------------------------------------------------------
+
+handle_cast(_, State) ->
+ {noreply, State}.
+
+%% ---------------------------------------------------------------------------
+%% # handle_info/2
+%% ---------------------------------------------------------------------------
+
+handle_info(T, #listener{acceptors = L} = S) ->
+ {noreply, S#listener{acceptors = l(T,L)}};
+
+handle_info(T, State) ->
+ {noreply, transition(T, State)}.
+
+%% ---------------------------------------------------------------------------
+%% # code_change/3
+%% ---------------------------------------------------------------------------
+
+code_change(_, State, _) ->
+ {ok, State}.
+
+%% ---------------------------------------------------------------------------
+%% # terminate/2
+%% ---------------------------------------------------------------------------
+
+terminate(_, _) ->
+ ok.
+
+%% ---------------------------------------------------------------------------
+
+monitor(Pid) ->
+ erlang:monitor(process, Pid).
+
+putr(Key, Val) ->
+ put({?MODULE, Key}, Val).
+
+eraser(Key) ->
+ erase({?MODULE, Key}).
+
+%% l/2
+
+l({'DOWN', _, process, _, _} = T, _) ->
+ x(T);
+
+%% New accepting process.
+l({accept, APid}, As) ->
+ As ++ [APid];
+
+%% Peer wants to connect but we have no acceptor ...
+l({connect, Peer}, [] = As) ->
+ Peer ! {refused, self()},
+ As;
+
+%% ... or we do.
+l({connect, Peer}, [APid | Rest]) ->
+ Peer ! {accepted, APid},
+ Rest.
+
+x(T) ->
+ exit({shutdown, T}).
+
+%% start/1
+
+start(Fun) ->
+ Ref = make_ref(),
+ {ok, Pid}
+ = T
+ = diameter_etcp_sup:start_child({connect, Fun, Ref, self()}),
+ MRef = monitor(Pid),
+ receive
+ {ok, Ref} ->
+ T;
+ {'DOWN', MRef, process, _, Reason} ->
+ {error, Reason}
+ end.
+
+%% acceptor/3
+
+acceptor(LPid, Ref, Parent) ->
+ LPid ! {accept, self()}, %% announce that we're accepting
+ putr(ref, {ok, Ref}),
+ monitor(Parent),
+ monitor(LPid),
+ accept.
+
+%% connector/4
+
+connector(RAddr, RPort, Ref, Parent) ->
+ c(match(RAddr, RPort), Ref, Parent).
+
+c([], _, _) ->
+ x(refused);
+
+c([{_,LPid}], Ref, Parent) ->
+ LPid ! {connect, self()},
+ putr(ref, {ok, Ref}),
+ monitor(Parent),
+ {connect, monitor(LPid)}.
+
+match({Node, RAddr}, RPort) ->
+ rpc:call(Node, diameter_reg, match, [{?MODULE, listener, RAddr, RPort}]);
+
+match(RAddr, RPort) ->
+ match({node(), RAddr}, RPort).
+
+%% transition/2
+
+%% Unexpected parent or peer death.
+transition({'DOWN', _, process, _, _} = T, S) ->
+ element(2,S) ! {tcp_error, self(), T},
+ x(T);
+
+%% Connector is receiving acceptor pid from listener.
+transition({accepted, Peer}, #connection{parent = Parent,
+ peer = {connect, MRef}}) ->
+ monitor(Peer),
+ erlang:demonitor(MRef, [flush]),
+ Peer ! {connect, self()},
+ Parent ! {ok, _} = eraser(ref),
+ #connection{parent = Parent,
+ peer = Peer};
+
+%% Connector is receiving connection refusal from listener.
+transition({refused, _} = T, #connection{peer = {connect, _}}) ->
+ x(T);
+
+%% Acceptor is receiving peer connect.
+transition({connect, Peer}, #connection{parent = Parent,
+ peer = accept}) ->
+ monitor(Peer),
+ Parent ! {ok, _} = eraser(ref),
+ #connection{parent = Parent,
+ peer = Peer};
+
+%% Incoming message.
+transition({recv, Bin}, #connection{parent = Parent} = S) ->
+ Parent ! {tcp, self(), Bin},
+ S;
+
+%% Outgoing message.
+transition({send, Bin}, #connection{peer = Peer} = S) ->
+ Peer ! {recv, Bin},
+ S;
+
+%% diameter_etcp:close/1 call when a peer is connected ...
+transition(close = T, #connection{peer = Peer})
+ when is_pid(Peer) ->
+ Peer ! {close, self()},
+ x(T);
+
+%% ... or not.
+transition(close = T, #connection{}) ->
+ x(T);
+
+%% Peer is closing the connection.
+transition({close, Peer} = T, #connection{parent = Parent,
+ peer = Peer})
+ when is_pid(Peer) ->
+ Parent ! {tcp_closed, self()},
+ x(T).
diff --git a/lib/diameter/src/transport/diameter_etcp_sup.erl b/lib/diameter/src/transport/diameter_etcp_sup.erl
new file mode 100644
index 0000000000..bd089cf041
--- /dev/null
+++ b/lib/diameter/src/transport/diameter_etcp_sup.erl
@@ -0,0 +1,64 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_etcp_sup).
+
+-behaviour(supervisor).
+
+%% interface
+-export([start/0,
+ start_child/1]).
+
+%% internal exports
+-export([start_link/1,
+ init/1]).
+
+%% start/0
+%%
+%% Start the etcp top supervisor.
+
+start() ->
+ diameter_transport_sup:start_child(?MODULE, ?MODULE).
+
+%% start_child/1
+%%
+%% Start a worker under the etcp supervisor.
+
+start_child(T) ->
+ supervisor:start_child(?MODULE, [T]).
+
+%% start_link/1
+%%
+%% Callback from diameter_transport_sup as a result of start/0.
+%% Starts a child supervisor under the transport supervisor.
+
+start_link(?MODULE) ->
+ SupName = {local, ?MODULE},
+ supervisor:start_link(SupName, ?MODULE, []).
+
+init([]) ->
+ Mod = diameter_etcp,
+ Flags = {simple_one_for_one, 0, 1},
+ ChildSpec = {Mod,
+ {Mod, start_link, []},
+ temporary,
+ 1000,
+ worker,
+ [Mod]},
+ {ok, {Flags, [ChildSpec]}}.
diff --git a/lib/diameter/src/transport/diameter_sctp.erl b/lib/diameter/src/transport/diameter_sctp.erl
new file mode 100644
index 0000000000..209f8c01c1
--- /dev/null
+++ b/lib/diameter/src/transport/diameter_sctp.erl
@@ -0,0 +1,696 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_sctp).
+
+-behaviour(gen_server).
+
+%% interface
+-export([start/3]).
+
+%% child start from supervisor
+-export([start_link/1]).
+
+%% child start from here
+-export([init/1]).
+
+%% gen_server callbacks
+-export([handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ code_change/3,
+ terminate/2]).
+
+-export([ports/0,
+ ports/1]).
+
+-include_lib("kernel/include/inet_sctp.hrl").
+-include_lib("diameter/include/diameter.hrl").
+
+-define(ERROR(T), erlang:error({T, ?MODULE, ?LINE})).
+
+%% The default port for a listener.
+-define(DEFAULT_PORT, 3868). %% RFC 3588, ch 2.1
+
+%% How long a listener with no associations lives before offing
+%% itself.
+-define(LISTENER_TIMEOUT, 30000).
+
+%% How long to wait for a transport process to attach after
+%% association establishment.
+-define(ACCEPT_TIMEOUT, 5000).
+
+-type uint() :: non_neg_integer().
+
+%% Accepting/connecting transport process state.
+-record(transport,
+ {parent :: pid(),
+ mode :: {accept, pid()}
+ | {connect, {list(inet:ip_address()), uint(), list()}}
+ %% {RAs, RP, Errors}
+ | connect,
+ socket :: gen_sctp:sctp_socket(),
+ assoc_id :: gen_sctp:assoc_id(), %% association identifier
+ peer :: {[inet:ip_address()], uint()}, %% {RAs, RP}
+ streams :: {uint(), uint()}, %% {InStream, OutStream} counts
+ os = 0 :: uint()}). %% next output stream
+
+%% Listener process state.
+-record(listener,
+ {ref :: reference(),
+ socket :: gen_sctp:sctp_socket(),
+ count = 0 :: uint(),
+ tmap = ets:new(?MODULE, []) :: ets:tid(),
+ %% {MRef, Pid|AssocId}, {AssocId, Pid}
+ pending = {0, ets:new(?MODULE, [ordered_set])},
+ tref :: reference()}).
+%% Field tmap is used to map an incoming message or event to the
+%% relevent transport process. Field pending implements a queue of
+%% transport processes to which an association has been assigned (at
+%% comm_up and written into tmap) but for which diameter hasn't yet
+%% spawned a transport process: a short-lived state of affairs as a
+%% new transport is spawned as a consequence of a peer being taken up,
+%% transport processes being spawned by the listener on demand. In
+%% case diameter starts a transport before comm_up on a new
+%% association, pending is set to an improper list with the spawned
+%% transport as head and the queue as tail.
+
+%% ---------------------------------------------------------------------------
+%% # start/3
+%% ---------------------------------------------------------------------------
+
+start(T, #diameter_service{capabilities = Caps}, Opts)
+ when is_list(Opts) ->
+ diameter_sctp_sup:start(), %% start supervisors on demand
+ Addrs = Caps#diameter_caps.host_ip_address,
+ s(T, Addrs, lists:map(fun ip/1, Opts)).
+
+ip({ifaddr, A}) ->
+ {ip, A};
+ip(T) ->
+ T.
+
+%% A listener spawns transports either as a consequence of this call
+%% when there is not yet an association to associate with it, or at
+%% comm_up on a new association in which case the call retrieves a
+%% transport from the pending queue.
+s({accept, Ref} = A, Addrs, Opts) ->
+ {LPid, LAs} = listener(Ref, {Opts, Addrs}),
+ try gen_server:call(LPid, {A, self()}, infinity) of
+ {ok, TPid} -> {ok, TPid, LAs}
+ catch
+ exit: Reason -> {error, Reason}
+ end;
+%% This implementation is due to there being no accept call in
+%% gen_sctp in order to be able to accept a new association only
+%% *after* an accepting transport has been spawned.
+
+s({connect = C, Ref}, Addrs, Opts) ->
+ diameter_sctp_sup:start_child({C, self(), Opts, Addrs, Ref}).
+
+%% start_link/1
+
+start_link(T) ->
+ proc_lib:start_link(?MODULE,
+ init,
+ [T],
+ infinity,
+ diameter_lib:spawn_opts(server, [])).
+
+%% ---------------------------------------------------------------------------
+%% # init/1
+%% ---------------------------------------------------------------------------
+
+init(T) ->
+ gen_server:enter_loop(?MODULE, [], i(T)).
+
+%% i/1
+
+%% A process owning a listening socket.
+i({listen, Ref, {Opts, Addrs}}) ->
+ {LAs, Sock} = AS = open(Addrs, Opts, ?DEFAULT_PORT),
+ proc_lib:init_ack({ok, self(), LAs}),
+ ok = gen_sctp:listen(Sock, true),
+ true = diameter_reg:add_new({?MODULE, listener, {Ref, AS}}),
+ start_timer(#listener{ref = Ref,
+ socket = Sock});
+
+%% A connecting transport.
+i({connect, Pid, Opts, Addrs, Ref}) ->
+ {[As, Ps], Rest} = proplists:split(Opts, [raddr, rport]),
+ RAs = [diameter_lib:ipaddr(A) || {raddr, A} <- As],
+ [RP] = [P || {rport, P} <- Ps] ++ [P || P <- [?DEFAULT_PORT], [] == Ps],
+ {LAs, Sock} = open(Addrs, Rest, 0),
+ putr(ref, Ref),
+ proc_lib:init_ack({ok, self(), LAs}),
+ erlang:monitor(process, Pid),
+ #transport{parent = Pid,
+ mode = {connect, connect(Sock, RAs, RP, [])},
+ socket = Sock};
+i({connect, _, _, _} = T) -> %% from old code
+ x(T);
+
+%% An accepting transport spawned by diameter.
+i({accept, Pid, LPid, Sock, Ref})
+ when is_pid(Pid) ->
+ putr(ref, Ref),
+ proc_lib:init_ack({ok, self()}),
+ erlang:monitor(process, Pid),
+ erlang:monitor(process, LPid),
+ #transport{parent = Pid,
+ mode = {accept, LPid},
+ socket = Sock};
+i({accept, _, _, _} = T) -> %% from old code
+ x(T);
+
+%% An accepting transport spawned at association establishment.
+i({accept, Ref, LPid, Sock, Id}) ->
+ putr(ref, Ref),
+ proc_lib:init_ack({ok, self()}),
+ MRef = erlang:monitor(process, LPid),
+ %% Wait for a signal that the transport has been started before
+ %% processing other messages.
+ receive
+ {Ref, Pid} -> %% transport started
+ #transport{parent = Pid,
+ mode = {accept, LPid},
+ socket = Sock};
+ {'DOWN', MRef, process, _, _} = T -> %% listener down
+ close(Sock, Id),
+ x(T)
+ after ?ACCEPT_TIMEOUT ->
+ close(Sock, Id),
+ x(timeout)
+ end.
+
+%% close/2
+
+close(Sock, Id) ->
+ gen_sctp:eof(Sock, #sctp_assoc_change{assoc_id = Id}).
+%% Having to pass a record here is hokey.
+
+%% listener/2
+
+listener(LRef, T) ->
+ l(diameter_reg:match({?MODULE, listener, {LRef, '_'}}), LRef, T).
+
+%% Existing process with the listening socket ...
+l([{{?MODULE, listener, {_, AS}}, LPid}], _, _) ->
+ {LAs, _Sock} = AS,
+ {LPid, LAs};
+
+%% ... or not: start one.
+l([], LRef, T) ->
+ {ok, LPid, LAs} = diameter_sctp_sup:start_child({listen, LRef, T}),
+ {LPid, LAs}.
+
+%% open/3
+
+open(Addrs, Opts, PortNr) ->
+ {LAs, Os} = addrs(Addrs, Opts),
+ {LAs, case gen_sctp:open(gen_opts(portnr(Os, PortNr))) of
+ {ok, Sock} ->
+ Sock;
+ {error, Reason} ->
+ x({open, Reason})
+ end}.
+
+addrs(Addrs, Opts) ->
+ case proplists:split(Opts, [ip]) of
+ {[[]], _} ->
+ {Addrs, Opts ++ [{ip, A} || A <- Addrs]};
+ {[As], Os} ->
+ LAs = [diameter_lib:ipaddr(A) || {ip, A} <- As],
+ {LAs, Os ++ [{ip, A} || A <- LAs]}
+ end.
+
+portnr(Opts, PortNr) ->
+ case proplists:get_value(port, Opts) of
+ undefined ->
+ [{port, PortNr} | Opts];
+ _ ->
+ Opts
+ end.
+
+%% x/1
+
+x(Reason) ->
+ exit({shutdown, Reason}).
+
+%% gen_opts/1
+
+gen_opts(Opts) ->
+ {L,_} = proplists:split(Opts, [binary, list, mode, active, sctp_events]),
+ [[],[],[],[],[]] == L orelse ?ERROR({reserved_options, Opts}),
+ [binary, {active, once} | Opts].
+
+%% ---------------------------------------------------------------------------
+%% # ports/0-1
+%% ---------------------------------------------------------------------------
+
+ports() ->
+ Ts = diameter_reg:match({?MODULE, '_', '_'}),
+ [{type(T), N, Pid} || {{?MODULE, T, {_, {_, S}}}, Pid} <- Ts,
+ {ok, N} <- [inet:port(S)]].
+
+ports(Ref) ->
+ Ts = diameter_reg:match({?MODULE, '_', {Ref, '_'}}),
+ [{type(T), N, Pid} || {{?MODULE, T, {R, {_, S}}}, Pid} <- Ts,
+ R == Ref,
+ {ok, N} <- [inet:port(S)]].
+
+type(listener) ->
+ listen;
+type(T) ->
+ T.
+
+%% ---------------------------------------------------------------------------
+%% # handle_call/3
+%% ---------------------------------------------------------------------------
+
+handle_call({{accept, Ref}, Pid}, _, #listener{ref = Ref,
+ count = N}
+ = S) ->
+ {TPid, NewS} = accept(Ref, Pid, S),
+ {reply, {ok, TPid}, NewS#listener{count = N+1}};
+
+handle_call(_, _, State) ->
+ {reply, nok, State}.
+
+%% ---------------------------------------------------------------------------
+%% # handle_cast/2
+%% ---------------------------------------------------------------------------
+
+handle_cast(_, State) ->
+ {noreply, State}.
+
+%% ---------------------------------------------------------------------------
+%% # handle_info/2
+%% ---------------------------------------------------------------------------
+
+handle_info(T, #transport{} = S) ->
+ {noreply, #transport{} = t(T,S)};
+
+handle_info(T, #listener{} = S) ->
+ {noreply, #listener{} = l(T,S)}.
+
+%% ---------------------------------------------------------------------------
+%% # code_change/3
+%% ---------------------------------------------------------------------------
+
+code_change(_, State, _) ->
+ {ok, State}.
+
+%% ---------------------------------------------------------------------------
+%% # terminate/2
+%% ---------------------------------------------------------------------------
+
+terminate(_, #transport{assoc_id = undefined}) ->
+ ok;
+
+terminate(_, #transport{socket = Sock,
+ mode = {accept, _},
+ assoc_id = Id}) ->
+ close(Sock, Id);
+
+terminate(_, #transport{socket = Sock}) ->
+ gen_sctp:close(Sock);
+
+terminate(_, #listener{socket = Sock}) ->
+ gen_sctp:close(Sock).
+
+%% ---------------------------------------------------------------------------
+
+putr(Key, Val) ->
+ put({?MODULE, Key}, Val).
+
+getr(Key) ->
+ get({?MODULE, Key}).
+
+%% start_timer/1
+
+start_timer(#listener{count = 0} = S) ->
+ S#listener{tref = erlang:start_timer(?LISTENER_TIMEOUT, self(), close)};
+start_timer(S) ->
+ S.
+
+%% l/2
+%%
+%% Transition listener state.
+
+%% Incoming message from SCTP.
+l({sctp, Sock, _RA, _RP, Data} = Msg, #listener{socket = Sock} = S) ->
+ setopts(Sock),
+ case find(Data, S) of
+ {TPid, NewS} ->
+ TPid ! Msg,
+ NewS;
+ false ->
+ S
+ end;
+
+%% Transport is asking message to be sent. See send/3 for why the send
+%% isn't directly from the transport.
+l({send, AssocId, StreamId, Bin}, #listener{socket = Sock} = S) ->
+ send(Sock, AssocId, StreamId, Bin),
+ S;
+
+%% Accepting transport has died. One that's awaiting an association ...
+l({'DOWN', MRef, process, TPid, _}, #listener{pending = [TPid | Q],
+ tmap = T,
+ count = N}
+ = S) ->
+ ets:delete(T, MRef),
+ ets:delete(T, TPid),
+ start_timer(S#listener{count = N-1,
+ pending = Q});
+
+%% ... ditto and a new transport has already been started ...
+l({'DOWN', _, process, _, _} = T, #listener{pending = [TPid | Q]}
+ = S) ->
+ #listener{pending = NQ}
+ = NewS
+ = l(T, S#listener{pending = Q}),
+ NewS#listener{pending = [TPid | NQ]};
+
+%% ... or not.
+l({'DOWN', MRef, process, TPid, _}, #listener{socket = Sock,
+ tmap = T,
+ count = N,
+ pending = {P,Q}}
+ = S) ->
+ [{MRef, Id}] = ets:lookup(T, MRef), %% Id = TPid | AssocId
+ ets:delete(T, MRef),
+ ets:delete(T, Id),
+ Id == TPid orelse close(Sock, Id),
+ case ets:lookup(Q, TPid) of
+ [{TPid, _}] -> %% transport in the pending queue ...
+ ets:delete(Q, TPid),
+ S#listener{pending = {P-1, Q}};
+ [] -> %% ... or not
+ start_timer(S#listener{count = N-1})
+ end;
+
+%% Timeout after the last accepting process has died.
+l({timeout, TRef, close = T}, #listener{tref = TRef,
+ count = 0}) ->
+ x(T);
+l({timeout, _, close}, #listener{} = S) ->
+ S.
+
+%% t/2
+%%
+%% Transition transport state.
+
+t(T,S) ->
+ case transition(T,S) of
+ ok ->
+ S;
+ #transport{} = NS ->
+ NS;
+ stop ->
+ x(T)
+ end.
+
+%% transition/2
+
+%% Incoming message.
+transition({sctp, Sock, _RA, _RP, Data}, #transport{socket = Sock,
+ mode = {accept, _}}
+ = S) ->
+ recv(Data, S);
+
+transition({sctp, Sock, _RA, _RP, Data}, #transport{socket = Sock} = S) ->
+ setopts(Sock),
+ recv(Data, S);
+
+%% Outgoing message.
+transition({diameter, {send, Msg}}, S) ->
+ send(Msg, S);
+
+%% Request to close the transport connection.
+transition({diameter, {close, Pid}}, #transport{parent = Pid}) ->
+ stop;
+
+%% TLS over SCTP is described in RFC 3436 but has limitations as
+%% described in RFC 6083. The latter describes DTLS over SCTP, which
+%% addresses these limitations, DTLS itself being described in RFC
+%% 4347. TLS is primarily used over TCP, which the current RFC 3588
+%% draft acknowledges by equating TLS with TLS/TCP and DTLS/SCTP.
+transition({diameter, {tls, _Ref, _Type, _Bool}}, _) ->
+ stop;
+
+%% Listener process has died.
+transition({'DOWN', _, process, Pid, _}, #transport{mode = {accept, Pid}}) ->
+ stop;
+
+%% Parent process has died.
+transition({'DOWN', _, process, Pid, _}, #transport{parent = Pid}) ->
+ stop;
+
+%% Request for the local port number.
+transition({resolve_port, Pid}, #transport{socket = Sock})
+ when is_pid(Pid) ->
+ Pid ! inet:port(Sock),
+ ok.
+
+%% Crash on anything unexpected.
+
+%% accept/3
+%%
+%% Start a new transport process or use one that's already been
+%% started as a consequence of association establishment.
+
+%% No pending associations: spawn a new transport.
+accept(Ref, Pid, #listener{socket = Sock,
+ tmap = T,
+ pending = {0,_} = Q}
+ = S) ->
+ Arg = {accept, Pid, self(), Sock, Ref},
+ {ok, TPid} = diameter_sctp_sup:start_child(Arg),
+ MRef = erlang:monitor(process, TPid),
+ ets:insert(T, [{MRef, TPid}, {TPid, MRef}]),
+ {TPid, S#listener{pending = [TPid | Q]}};
+%% Placing the transport in the pending field makes it available to
+%% the next association. The stack starts a new accepting transport
+%% only after this one brings the connection up (or dies).
+
+%% Accepting transport has died. This can happen if a new transport is
+%% started before the DOWN has arrived.
+accept(Ref, Pid, #listener{pending = [TPid | {0,_} = Q]} = S) ->
+ false = is_process_alive(TPid), %% assert
+ accept(Ref, Pid, S#listener{pending = Q});
+
+%% Pending associations: attach to the first in the queue.
+accept(_, Pid, #listener{ref = Ref, pending = {N,Q}} = S) ->
+ TPid = ets:first(Q),
+ TPid ! {Ref, Pid},
+ ets:delete(Q, TPid),
+ {TPid, S#listener{pending = {N-1, Q}}}.
+
+%% send/2
+
+%% Outbound Diameter message on a specified stream ...
+send(#diameter_packet{bin = Bin, transport_data = {stream, SId}}, S) ->
+ send(SId, Bin, S),
+ S;
+
+%% ... or not: rotate through all steams.
+send(Bin, #transport{streams = {_, OS},
+ os = N}
+ = S)
+ when is_binary(Bin) ->
+ send(N, Bin, S),
+ S#transport{os = (N + 1) rem OS}.
+
+%% send/3
+
+%% Messages have to be sent from the controlling process, which is
+%% probably a bug. Sending from here causes an inet_reply, Sock,
+%% Status} message to be sent to the controlling process while
+%% gen_sctp:send/4 here hangs.
+send(StreamId, Bin, #transport{assoc_id = AId,
+ mode = {accept, LPid}}) ->
+ LPid ! {send, AId, StreamId, Bin};
+
+send(StreamId, Bin, #transport{socket = Sock,
+ assoc_id = AId}) ->
+ send(Sock, AId, StreamId, Bin).
+
+%% send/4
+
+send(Sock, AssocId, Stream, Bin) ->
+ case gen_sctp:send(Sock, AssocId, Stream, Bin) of
+ ok ->
+ ok;
+ {error, Reason} ->
+ x({send, Reason})
+ end.
+
+%% recv/2
+
+%% Association established ...
+recv({[], #sctp_assoc_change{state = comm_up,
+ outbound_streams = OS,
+ inbound_streams = IS,
+ assoc_id = Id}},
+ #transport{assoc_id = undefined,
+ mode = {T, _},
+ socket = Sock}
+ = S) ->
+ Ref = getr(ref),
+ is_reference(Ref) %% started in new code
+ andalso
+ (true = diameter_reg:add_new({?MODULE, T, {Ref, {Id, Sock}}})),
+ up(S#transport{assoc_id = Id,
+ streams = {IS, OS}});
+
+%% ... or not: try the next address.
+recv({[], #sctp_assoc_change{} = E},
+ #transport{assoc_id = undefined,
+ socket = Sock,
+ mode = {connect = C, {[RA|RAs], RP, Es}}}
+ = S) ->
+ S#transport{mode = {C, connect(Sock, RAs, RP, [{RA,E} | Es])}};
+
+%% Lost association after establishment.
+recv({[], #sctp_assoc_change{}}, _) ->
+ stop;
+
+%% Inbound Diameter message.
+recv({[#sctp_sndrcvinfo{stream = Id}], Bin}, #transport{parent = Pid})
+ when is_binary(Bin) ->
+ diameter_peer:recv(Pid, #diameter_packet{transport_data = {stream, Id},
+ bin = Bin}),
+ ok;
+
+recv({[], #sctp_shutdown_event{assoc_id = Id}},
+ #transport{assoc_id = Id}) ->
+ stop;
+
+%% Note that diameter_sctp(3) documents that sctp_events cannot be
+%% specified in the list of options passed to gen_sctp and that
+%% gen_opts/1 guards against this. This is to ensure that we know what
+%% events to expect and also to ensure that we receive
+%% #sctp_sndrcvinfo{} with each incoming message (data_io_event =
+%% true). Adaptation layer events (ie. #sctp_adaptation_event{}) are
+%% disabled by default so don't handle it. We could simply disable
+%% events we don't react to but don't.
+
+recv({[], #sctp_paddr_change{}}, _) ->
+ ok;
+
+recv({[], #sctp_pdapi_event{}}, _) ->
+ ok.
+
+%% up/1
+
+up(#transport{parent = Pid,
+ mode = {connect = C, {[RA | _], RP, _}}}
+ = S) ->
+ diameter_peer:up(Pid, {RA,RP}),
+ S#transport{mode = C};
+
+up(#transport{parent = Pid,
+ mode = {accept, _}}
+ = S) ->
+ diameter_peer:up(Pid),
+ S.
+
+%% find/2
+
+find({[#sctp_sndrcvinfo{assoc_id = Id}], _}
+ = Data,
+ #listener{tmap = T}
+ = S) ->
+ f(ets:lookup(T, Id), Data, S);
+
+find({_, Rec} = Data, #listener{tmap = T} = S) ->
+ f(ets:lookup(T, assoc_id(Rec)), Data, S).
+
+%% New association and a transport waiting for one: use it.
+f([],
+ {_, #sctp_assoc_change{state = comm_up,
+ assoc_id = Id}},
+ #listener{tmap = T,
+ pending = [TPid | {_,_} = Q]}
+ = S) ->
+ [{TPid, MRef}] = ets:lookup(T, TPid),
+ ets:insert(T, [{MRef, Id}, {Id, TPid}]),
+ ets:delete(T, TPid),
+ {TPid, S#listener{pending = Q}};
+
+%% New association and no transport start yet: spawn one and place it
+%% in the queue.
+f([],
+ {_, #sctp_assoc_change{state = comm_up,
+ assoc_id = Id}},
+ #listener{ref = Ref,
+ socket = Sock,
+ tmap = T,
+ pending = {N,Q}}
+ = S) ->
+ Arg = {accept, Ref, self(), Sock, Id},
+ {ok, TPid} = diameter_sctp_sup:start_child(Arg),
+ MRef = erlang:monitor(process, TPid),
+ ets:insert(T, [{MRef, Id}, {Id, TPid}]),
+ ets:insert(Q, {TPid, now()}),
+ {TPid, S#listener{pending = {N+1, Q}}};
+
+%% Known association ...
+f([{_, TPid}], _, S) ->
+ {TPid, S};
+
+%% ... or not: discard.
+f([], _, _) ->
+ false.
+
+%% assoc_id/1
+
+assoc_id(#sctp_shutdown_event{assoc_id = Id}) ->
+ Id;
+assoc_id(#sctp_assoc_change{assoc_id = Id}) ->
+ Id;
+assoc_id(#sctp_sndrcvinfo{assoc_id = Id}) ->
+ Id;
+assoc_id(#sctp_paddr_change{assoc_id = Id}) ->
+ Id;
+assoc_id(#sctp_adaptation_event{assoc_id = Id}) ->
+ Id.
+
+%% connect/4
+
+connect(_, [], _, Reasons) ->
+ x({connect, lists:reverse(Reasons)});
+
+connect(Sock, [Addr | AT] = As, Port, Reasons) ->
+ case gen_sctp:connect_init(Sock, Addr, Port, []) of
+ ok ->
+ {As, Port, Reasons};
+ {error, _} = E ->
+ connect(Sock, AT, Port, [{Addr, E} | Reasons])
+ end.
+
+%% setopts/1
+
+setopts(Sock) ->
+ case inet:setopts(Sock, [{active, once}]) of
+ ok -> ok;
+ X -> x({setopts, Sock, X}) %% possibly on peer disconnect
+ end.
diff --git a/lib/diameter/src/transport/diameter_sctp_sup.erl b/lib/diameter/src/transport/diameter_sctp_sup.erl
new file mode 100644
index 0000000000..3bdae02d68
--- /dev/null
+++ b/lib/diameter/src/transport/diameter_sctp_sup.erl
@@ -0,0 +1,74 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_sctp_sup).
+
+-behaviour(supervisor).
+
+%% interface
+-export([start/0,
+ start_child/1]).
+
+%% internal exports
+-export([start_link/1,
+ init/1]).
+
+%% Start multiple supervisors only because a child can't start another
+%% child before supervisor:start_child/2 has returned.
+-define(TRANSPORT_SUP, diameter_sctp_transport_sup).
+-define(LISTENER_SUP, diameter_sctp_listener_sup).
+
+%% start/0
+%%
+%% Start the TCP-specific supervisors.
+
+start() ->
+ diameter_transport_sup:start_child(?TRANSPORT_SUP, ?MODULE),
+ diameter_transport_sup:start_child(?LISTENER_SUP, ?MODULE).
+
+%% start_child/1
+%%
+%% Start a worker under one of the child supervisors.
+
+start_child(T) ->
+ SupRef = case element(1,T) of
+ connect -> ?TRANSPORT_SUP;
+ accept -> ?TRANSPORT_SUP;
+ listen -> ?LISTENER_SUP
+ end,
+ supervisor:start_child(SupRef, [T]).
+
+%% start_link/1
+%%
+%% Callback from diameter_transport_sup as a result of start/0.
+%% Starts a child supervisor under the transport supervisor.
+
+start_link(Name) ->
+ supervisor:start_link({local, Name}, ?MODULE, []).
+
+init([]) ->
+ Mod = diameter_sctp,
+ Flags = {simple_one_for_one, 0, 1},
+ ChildSpec = {Mod,
+ {Mod, start_link, []},
+ temporary,
+ 1000,
+ worker,
+ [Mod]},
+ {ok, {Flags, [ChildSpec]}}.
diff --git a/lib/diameter/src/transport/diameter_tcp.erl b/lib/diameter/src/transport/diameter_tcp.erl
new file mode 100644
index 0000000000..78dbda6888
--- /dev/null
+++ b/lib/diameter/src/transport/diameter_tcp.erl
@@ -0,0 +1,707 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_tcp).
+
+-behaviour(gen_server).
+
+%% interface
+-export([start/3]).
+
+%% child start from supervisor
+-export([start_link/1]).
+
+%% child start from here
+-export([init/1]).
+
+%% gen_server callbacks
+-export([handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ code_change/3,
+ terminate/2]).
+
+-export([ports/0,
+ ports/1]).
+
+-include_lib("diameter/include/diameter.hrl").
+
+-define(ERROR(T), erlang:error({T, ?MODULE, ?LINE})).
+
+-define(DEFAULT_PORT, 3868). %% RFC 3588, ch 2.1
+-define(LISTENER_TIMEOUT, 30000).
+-define(FRAGMENT_TIMEOUT, 1000).
+
+%% cb_info passed to ssl.
+-define(TCP_CB(Mod), {Mod, tcp, tcp_closed, tcp_error}).
+
+%% The same gen_server implementation supports three different kinds
+%% of processes: an actual transport process, one that will club it to
+%% death should the parent die before a connection is established, and
+%% a process owning the listening port.
+
+%% Listener process state.
+-record(listener, {socket :: inet:socket(),
+ count = 1 :: non_neg_integer(),
+ tref :: reference()}).
+
+%% Monitor process state.
+-record(monitor,
+ {parent :: pid(),
+ transport = self() :: pid()}).
+
+-type tref() :: reference(). %% timer reference
+-type length() :: 0..16#FFFFFF. %% message length from Diameter header
+-type size() :: non_neg_integer(). %% accumulated binary size
+-type frag() :: {length(), size(), binary(), list(binary())}
+ | binary().
+
+%% Accepting/connecting transport process state.
+-record(transport,
+ {socket :: inet:socket(), %% accept or connect socket
+ parent :: pid(), %% of process that started us
+ module :: module(), %% gen_tcp-like module
+ frag = <<>> :: binary() | {tref(), frag()}, %% message fragment
+ ssl :: boolean() | [term()]}). %% ssl options
+%% The usual transport using gen_tcp can be replaced by anything
+%% sufficiently gen_tcp-like by passing a 'module' option as the first
+%% (for simplicity) transport option. The transport_module diameter_etcp
+%% uses this to set itself as the module to call, its start/3 just
+%% calling start/3 here with the option set.
+
+%% ---------------------------------------------------------------------------
+%% # start/3
+%% ---------------------------------------------------------------------------
+
+start({T, Ref}, #diameter_service{capabilities = Caps}, Opts) ->
+ diameter_tcp_sup:start(), %% start tcp supervisors on demand
+ {Mod, Rest} = split(Opts),
+ Addrs = Caps#diameter_caps.host_ip_address,
+ Arg = {T, Ref, Mod, self(), Rest, Addrs},
+ diameter_tcp_sup:start_child(Arg).
+
+split([{module, M} | Opts]) ->
+ {M, Opts};
+split(Opts) ->
+ {gen_tcp, Opts}.
+
+%% start_link/1
+
+start_link(T) ->
+ proc_lib:start_link(?MODULE,
+ init,
+ [T],
+ infinity,
+ diameter_lib:spawn_opts(server, [])).
+
+%% ---------------------------------------------------------------------------
+%% # init/1
+%% ---------------------------------------------------------------------------
+
+init(T) ->
+ gen_server:enter_loop(?MODULE, [], i(T)).
+
+%% i/1
+
+%% A transport process.
+i({T, Ref, Mod, Pid, Opts, Addrs})
+ when T == accept;
+ T == connect ->
+ erlang:monitor(process, Pid),
+ %% Since accept/connect might block indefinitely, spawn a process
+ %% that does nothing but kill us with the parent until call
+ %% returns.
+ {ok, MPid} = diameter_tcp_sup:start_child(#monitor{parent = Pid}),
+ {SslOpts, Rest} = ssl(Opts),
+ Sock = i(T, Ref, Mod, Pid, SslOpts, Rest, Addrs),
+ MPid ! {stop, self()}, %% tell the monitor to die
+ M = if SslOpts -> ssl; true -> Mod end,
+ setopts(M, Sock),
+ putr(ref, Ref),
+ #transport{parent = Pid,
+ module = M,
+ socket = Sock,
+ ssl = SslOpts};
+%% Put the reference in the process dictionary since we now use it
+%% advertise the ssl socket after TLS upgrade.
+
+%% A monitor process to kill the transport if the parent dies.
+i(#monitor{parent = Pid, transport = TPid} = S) ->
+ proc_lib:init_ack({ok, self()}),
+ erlang:monitor(process, Pid),
+ erlang:monitor(process, TPid),
+ S;
+%% In principle a link between the transport and killer processes
+%% could do the same thing: have the accepting/connecting process be
+%% killed when the killer process dies as a consequence of parent
+%% death. However, a link can be unlinked and this is exactly what
+%% gen_tcp seems to so. Links should be left to supervisors.
+
+i({listen, LRef, APid, {Mod, Opts, Addrs}}) ->
+ {[LA, LP], Rest} = proplists:split(Opts, [ip, port]),
+ LAddr = get_addr(LA, Addrs),
+ LPort = get_port(LP),
+ {ok, LSock} = Mod:listen(LPort, gen_opts(LAddr, Rest)),
+ true = diameter_reg:add_new({?MODULE, listener, {LRef, {LAddr, LSock}}}),
+ proc_lib:init_ack({ok, self(), {LAddr, LSock}}),
+ erlang:monitor(process, APid),
+ start_timer(#listener{socket = LSock}).
+
+ssl(Opts) ->
+ {[SslOpts], Rest} = proplists:split(Opts, [ssl_options]),
+ {ssl_opts(SslOpts), Rest}.
+
+ssl_opts([]) ->
+ false;
+ssl_opts([{ssl_options, true}]) ->
+ true;
+ssl_opts([{ssl_options, Opts}])
+ when is_list(Opts) ->
+ Opts;
+ssl_opts(L) ->
+ ?ERROR({ssl_options, L}).
+
+%% i/7
+
+%% Establish a TLS connection before capabilities exchange ...
+i(Type, Ref, Mod, Pid, true, Opts, Addrs) ->
+ i(Type, Ref, ssl, Pid, [{cb_info, ?TCP_CB(Mod)} | Opts], Addrs);
+
+%% ... or not.
+i(Type, Ref, Mod, Pid, _, Opts, Addrs) ->
+ i(Type, Ref, Mod, Pid, Opts, Addrs).
+
+i(accept = T, Ref, Mod, Pid, Opts, Addrs) ->
+ {LAddr, LSock} = listener(Ref, {Mod, Opts, Addrs}),
+ proc_lib:init_ack({ok, self(), [LAddr]}),
+ Sock = ok(accept(Mod, LSock)),
+ true = diameter_reg:add_new({?MODULE, T, {Ref, Sock}}),
+ diameter_peer:up(Pid),
+ Sock;
+
+i(connect = T, Ref, Mod, Pid, Opts, Addrs) ->
+ {[LA, RA, RP], Rest} = proplists:split(Opts, [ip, raddr, rport]),
+ LAddr = get_addr(LA, Addrs),
+ RAddr = get_addr(RA, []),
+ RPort = get_port(RP),
+ proc_lib:init_ack({ok, self(), [LAddr]}),
+ Sock = ok(connect(Mod, RAddr, RPort, gen_opts(LAddr, Rest))),
+ true = diameter_reg:add_new({?MODULE, T, {Ref, Sock}}),
+ diameter_peer:up(Pid, {RAddr, RPort}),
+ Sock.
+
+ok({ok, T}) ->
+ T;
+ok(No) ->
+ x(No).
+
+x(Reason) ->
+ exit({shutdown, Reason}).
+
+%% listener/2
+
+listener(LRef, T) ->
+ l(diameter_reg:match({?MODULE, listener, {LRef, '_'}}), LRef, T).
+
+%% Existing process with the listening socket ...
+l([{{?MODULE, listener, {_, AS}}, LPid}], _, _) ->
+ LPid ! {accept, self()},
+ AS;
+
+%% ... or not: start one.
+l([], LRef, T) ->
+ {ok, _, AS} = diameter_tcp_sup:start_child({listen, LRef, self(), T}),
+ AS.
+
+%% get_addr/2
+
+get_addr(As, Def) ->
+ diameter_lib:ipaddr(addr(As, Def)).
+
+%% Take the first address from the service if several are unspecified.
+addr([], [Addr | _]) ->
+ Addr;
+addr([{_, Addr}], _) ->
+ Addr;
+addr(As, Addrs) ->
+ ?ERROR({invalid_addrs, As, Addrs}).
+
+%% get_port/1
+
+get_port([{_, Port}]) ->
+ Port;
+get_port([]) ->
+ ?DEFAULT_PORT;
+get_port(Ps) ->
+ ?ERROR({invalid_ports, Ps}).
+
+%% gen_opts/2
+
+gen_opts(LAddr, Opts) ->
+ {L,_} = proplists:split(Opts, [binary, packet, active]),
+ [[],[],[]] == L orelse ?ERROR({reserved_options, Opts}),
+ [binary,
+ {packet, 0},
+ {active, once},
+ {ip, LAddr}
+ | Opts].
+
+%% ---------------------------------------------------------------------------
+%% # ports/1
+%% ---------------------------------------------------------------------------
+
+ports() ->
+ Ts = diameter_reg:match({?MODULE, '_', '_'}),
+ [{type(T), resolve(T,S), Pid} || {{?MODULE, T, {_,S}}, Pid} <- Ts].
+
+ports(Ref) ->
+ Ts = diameter_reg:match({?MODULE, '_', {Ref, '_'}}),
+ [{type(T), resolve(T,S), Pid} || {{?MODULE, T, {R,S}}, Pid} <- Ts,
+ R == Ref].
+
+type(listener) ->
+ listen;
+type(T) ->
+ T.
+
+sock(listener, {_LAddr, Sock}) ->
+ Sock;
+sock(_, Sock) ->
+ Sock.
+
+resolve(Type, S) ->
+ Sock = sock(Type, S),
+ try
+ ok(portnr(Sock))
+ catch
+ _:_ -> Sock
+ end.
+
+portnr(Sock)
+ when is_port(Sock) ->
+ portnr(gen_tcp, Sock);
+portnr(Sock) ->
+ portnr(ssl, Sock).
+
+%% ---------------------------------------------------------------------------
+%% # handle_call/3
+%% ---------------------------------------------------------------------------
+
+handle_call(_, _, State) ->
+ {reply, nok, State}.
+
+%% ---------------------------------------------------------------------------
+%% # handle_cast/2
+%% ---------------------------------------------------------------------------
+
+handle_cast(_, State) ->
+ {noreply, State}.
+
+%% ---------------------------------------------------------------------------
+%% # handle_info/2
+%% ---------------------------------------------------------------------------
+
+handle_info(T, #transport{} = S) ->
+ {noreply, #transport{} = t(T,S)};
+
+handle_info(T, #listener{} = S) ->
+ {noreply, #listener{} = l(T,S)};
+
+handle_info(T, #monitor{} = S) ->
+ m(T,S),
+ x(T).
+
+%% ---------------------------------------------------------------------------
+%% # code_change/3
+%% ---------------------------------------------------------------------------
+
+code_change(_, {transport, _, _, _, _} = S, _) ->
+ {ok, #transport{} = list_to_tuple(tuple_to_list(S) ++ [false])};
+code_change(_, State, _) ->
+ {ok, State}.
+
+%% ---------------------------------------------------------------------------
+%% # terminate/2
+%% ---------------------------------------------------------------------------
+
+terminate(_, _) ->
+ ok.
+
+%% ---------------------------------------------------------------------------
+
+putr(Key, Val) ->
+ put({?MODULE, Key}, Val).
+
+getr(Key) ->
+ get({?MODULE, Key}).
+
+%% start_timer/1
+
+start_timer(#listener{count = 0} = S) ->
+ S#listener{tref = erlang:start_timer(?LISTENER_TIMEOUT, self(), close)};
+start_timer(S) ->
+ S.
+
+%% m/2
+%%
+%% Transition monitor state.
+
+%% Transport is telling us to die.
+m({stop, TPid}, #monitor{transport = TPid}) ->
+ ok;
+
+%% Transport has died.
+m({'DOWN', _, process, TPid, _}, #monitor{transport = TPid}) ->
+ ok;
+
+%% Transport parent has died.
+m({'DOWN', _, process, Pid, _}, #monitor{parent = Pid,
+ transport = TPid}) ->
+ exit(TPid, {shutdown, parent}).
+
+%% l/2
+%%
+%% Transition listener state.
+
+%% Another accept transport is attaching.
+l({accept, TPid}, #listener{count = N} = S) ->
+ erlang:monitor(process, TPid),
+ S#listener{count = N+1};
+
+%% Accepting process has died.
+l({'DOWN', _, process, _, _}, #listener{count = N} = S) ->
+ start_timer(S#listener{count = N-1});
+
+%% Timeout after the last accepting process has died.
+l({timeout, TRef, close = T}, #listener{tref = TRef,
+ count = 0}) ->
+ x(T);
+l({timeout, _, close}, #listener{} = S) ->
+ S.
+
+%% t/2
+%%
+%% Transition transport state.
+
+t(T,S) ->
+ case transition(T,S) of
+ ok ->
+ S;
+ #transport{} = NS ->
+ NS;
+ {stop, Reason} ->
+ x(Reason);
+ stop ->
+ x(T)
+ end.
+
+%% transition/2
+
+%% Initial incoming message when we might need to upgrade to TLS:
+%% don't request another message until we know.
+transition({tcp, Sock, Bin}, #transport{socket = Sock,
+ parent = Pid,
+ frag = Head,
+ module = M,
+ ssl = Opts}
+ = S)
+ when is_list(Opts) ->
+ case recv1(Head, Bin) of
+ {Msg, B} when is_binary(Msg) ->
+ diameter_peer:recv(Pid, Msg),
+ S#transport{frag = B};
+ Frag ->
+ setopts(M, Sock),
+ S#transport{frag = Frag}
+ end;
+
+%% Incoming message.
+transition({P, Sock, Bin}, #transport{socket = Sock,
+ module = M,
+ ssl = B}
+ = S)
+ when P == tcp, not B;
+ P == ssl, B ->
+ setopts(M, Sock),
+ recv(Bin, S);
+
+%% Capabilties exchange has decided on whether or not to run over TLS.
+transition({diameter, {tls, Ref, Type, B}}, #transport{parent = Pid}
+ = S) ->
+ #transport{socket = Sock,
+ module = M}
+ = NS
+ = tls_handshake(Type, B, S),
+ Pid ! {diameter, {tls, Ref}},
+ setopts(M, Sock),
+ NS#transport{ssl = B};
+
+transition({C, Sock}, #transport{socket = Sock,
+ ssl = B})
+ when C == tcp_closed, not B;
+ C == ssl_closed, B ->
+ stop;
+
+transition({E, Sock, _Reason} = T, #transport{socket = Sock,
+ ssl = B}
+ = S)
+ when E == tcp_error, not B;
+ E == ssl_error, B ->
+ ?ERROR({T,S});
+
+%% Outgoing message.
+transition({diameter, {send, Bin}}, #transport{socket = Sock,
+ module = M}) ->
+ case send(M, Sock, Bin) of
+ ok ->
+ ok;
+ {error, Reason} ->
+ {stop, {send, Reason}}
+ end;
+
+%% Request to close the transport connection.
+transition({diameter, {close, Pid}}, #transport{parent = Pid,
+ socket = Sock,
+ module = M}) ->
+ M:close(Sock),
+ stop;
+
+%% Timeout for reception of outstanding packets.
+transition({timeout, TRef, flush}, S) ->
+ flush(TRef, S);
+
+%% Request for the local port number.
+transition({resolve_port, Pid}, #transport{socket = Sock,
+ module = M})
+ when is_pid(Pid) ->
+ Pid ! portnr(M, Sock),
+ ok;
+
+%% Parent process has died.
+transition({'DOWN', _, process, Pid, _}, #transport{parent = Pid}) ->
+ stop.
+
+%% Crash on anything unexpected.
+
+%% tls_handshake/3
+%%
+%% In the case that no tls message is received (eg. the service hasn't
+%% been configured to advertise TLS support) we will simply never ask
+%% for another TCP message, which will force the watchdog to
+%% eventually take us down.
+
+%% TLS has already been established with the connection.
+tls_handshake(_, _, #transport{ssl = true} = S) ->
+ S;
+
+%% Capabilities exchange negotiated TLS but transport was not
+%% configured with an options list.
+tls_handshake(_, true, #transport{ssl = false}) ->
+ ?ERROR(no_ssl_options);
+
+%% Capabilities exchange negotiated TLS: upgrade the connection.
+tls_handshake(Type, true, #transport{socket = Sock,
+ module = M,
+ ssl = Opts}
+ = S) ->
+ {ok, SSock} = tls(Type, Sock, [{cb_info, ?TCP_CB(M)} | Opts]),
+ Ref = getr(ref),
+ is_reference(Ref) %% started in new code
+ andalso
+ (true = diameter_reg:add_new({?MODULE, Type, {Ref, SSock}})),
+ S#transport{socket = SSock,
+ module = ssl};
+
+%% Capabilities exchange has not negotiated TLS.
+tls_handshake(_, false, S) ->
+ S.
+
+tls(connect, Sock, Opts) ->
+ ssl:connect(Sock, Opts);
+tls(accept, Sock, Opts) ->
+ ssl:ssl_accept(Sock, Opts).
+
+%% recv/2
+%%
+%% Reassemble fragmented messages and extract multple message sent
+%% using Nagle.
+
+recv(Bin, #transport{parent = Pid, frag = Head} = S) ->
+ case recv1(Head, Bin) of
+ {Msg, B} when is_binary(Msg) ->
+ diameter_peer:recv(Pid, Msg),
+ recv(B, S#transport{frag = <<>>});
+ Frag ->
+ S#transport{frag = Frag}
+ end.
+
+%% recv1/2
+
+%% No previous fragment.
+recv1(<<>>, Bin) ->
+ rcv(Bin);
+
+recv1({TRef, Head}, Bin) ->
+ erlang:cancel_timer(TRef),
+ rcv(Head, Bin).
+
+%% rcv/2
+
+%% Not even the first four bytes of the header.
+rcv(Head, Bin)
+ when is_binary(Head) ->
+ rcv(<<Head/binary, Bin/binary>>);
+
+%% Or enough to know how many bytes to extract.
+rcv({Len, N, Head, Acc}, Bin) ->
+ rcv(Len, N + size(Bin), Head, [Bin | Acc]).
+
+%% rcv/4
+
+%% Extract a message for which we have all bytes.
+rcv(Len, N, Head, Acc)
+ when Len =< N ->
+ rcv1(Len, bin(Head, Acc));
+
+%% Wait for more packets.
+rcv(Len, N, Head, Acc) ->
+ {start_timer(), {Len, N, Head, Acc}}.
+
+%% rcv/2
+
+%% Nothing left.
+rcv(<<>> = Bin) ->
+ Bin;
+
+%% Well, this isn't good. Chances are things will go south from here
+%% but if we're lucky then the bytes we have extend to an intended
+%% message boundary and we can recover by simply discarding them,
+%% which is the result of receiving them.
+rcv(<<_:1/binary, Len:24, _/binary>> = Bin)
+ when Len < 20 ->
+ {Bin, <<>>};
+
+%% Enough bytes to extract a message.
+rcv(<<_:1/binary, Len:24, _/binary>> = Bin)
+ when Len =< size(Bin) ->
+ rcv1(Len, Bin);
+
+%% Or not: wait for more packets.
+rcv(<<_:1/binary, Len:24, _/binary>> = Head) ->
+ {start_timer(), {Len, size(Head), Head, []}};
+
+%% Not even 4 bytes yet.
+rcv(Head) ->
+ {start_timer(), Head}.
+
+%% rcv1/2
+
+rcv1(Len, Bin) ->
+ <<Msg:Len/binary, Rest/binary>> = Bin,
+ {Msg, Rest}.
+
+%% bin/[12]
+
+bin(Head, Acc) ->
+ list_to_binary([Head | lists:reverse(Acc)]).
+
+bin({_, _, Head, Acc}) ->
+ bin(Head, Acc);
+bin(Bin)
+ when is_binary(Bin) ->
+ Bin.
+
+%% start_timer/0
+
+%% An erroneously large message length may leave us with a fragment
+%% that lingers if the peer doesn't have anything more to send. Start
+%% a timer to force reception if an incoming message doesn't arrive
+%% first. This won't stop a peer from sending a large bogus value and
+%% following it up however but such a state of affairs can only go on
+%% for so long since an unanswered DWR will eventually be the result.
+%%
+%% An erroneously small message length causes problems as well but
+%% since all messages with length problems are discarded this should
+%% also eventually lead to watchdog failover.
+
+start_timer() ->
+ erlang:start_timer(?FRAGMENT_TIMEOUT, self(), flush).
+
+flush(TRef, #transport{parent = Pid, frag = {TRef, Head}} = S) ->
+ diameter_peer:recv(Pid, bin(Head)),
+ S#transport{frag = <<>>};
+flush(_, S) ->
+ S.
+
+%% accept/2
+
+accept(ssl, LSock) ->
+ case ssl:transport_accept(LSock) of
+ {ok, Sock} ->
+ {ssl:ssl_accept(Sock), Sock};
+ {error, _} = No ->
+ No
+ end;
+accept(Mod, LSock) ->
+ Mod:accept(LSock).
+
+%% connect/4
+
+connect(Mod, Host, Port, Opts) ->
+ Mod:connect(Host, Port, Opts).
+
+%% send/3
+
+send(gen_tcp, Sock, Bin) ->
+ gen_tcp:send(Sock, Bin);
+send(ssl, Sock, Bin) ->
+ ssl:send(Sock, Bin);
+send(M, Sock, Bin) ->
+ M:send(Sock, Bin).
+
+%% setopts/3
+
+setopts(gen_tcp, Sock, Opts) ->
+ inet:setopts(Sock, Opts);
+setopts(ssl, Sock, Opts) ->
+ ssl:setopts(Sock, Opts);
+setopts(M, Sock, Opts) ->
+ M:setopts(Sock, Opts).
+
+%% setopts/2
+
+setopts(M, Sock) ->
+ case setopts(M, Sock, [{active, once}]) of
+ ok -> ok;
+ X -> x({setopts, M, Sock, X}) %% possibly on peer disconnect
+ end.
+
+%% portnr/2
+
+portnr(gen_tcp, Sock) ->
+ inet:port(Sock);
+portnr(ssl, Sock) ->
+ case ssl:sockname(Sock) of
+ {ok, {_Addr, PortNr}} ->
+ {ok, PortNr};
+ {error, _} = No ->
+ No
+ end;
+portnr(M, Sock) ->
+ M:port(Sock).
diff --git a/lib/diameter/src/transport/diameter_tcp_sup.erl b/lib/diameter/src/transport/diameter_tcp_sup.erl
new file mode 100644
index 0000000000..1016fa2d9b
--- /dev/null
+++ b/lib/diameter/src/transport/diameter_tcp_sup.erl
@@ -0,0 +1,78 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_tcp_sup).
+
+-behaviour(supervisor).
+
+%% interface
+-export([start/0,
+ start_child/1]).
+
+%% internal exports
+-export([start_link/1,
+ init/1]).
+
+%% Start multiple supervisors only because a child can't start another
+%% child before supervisor:start_child/2 has returned, although two is
+%% really sufficient (listeners and monitors can be under the same).
+-define(TRANSPORT_SUP, diameter_tcp_transport_sup).
+-define(LISTENER_SUP, diameter_tcp_listener_sup).
+-define(MONITOR_SUP, diameter_tcp_monitor_sup).
+
+%% start/0
+%%
+%% Start the TCP-specific supervisors.
+
+start() ->
+ diameter_transport_sup:start_child(?TRANSPORT_SUP, ?MODULE),
+ diameter_transport_sup:start_child(?LISTENER_SUP, ?MODULE),
+ diameter_transport_sup:start_child(?MONITOR_SUP, ?MODULE).
+
+%% start_child/1
+%%
+%% Start a worker under one of the child supervisors.
+
+start_child(T) ->
+ SupRef = case element(1,T) of
+ accept -> ?TRANSPORT_SUP;
+ connect -> ?TRANSPORT_SUP;
+ listen -> ?LISTENER_SUP;
+ monitor -> ?MONITOR_SUP
+ end,
+ supervisor:start_child(SupRef, [T]).
+
+%% start_link/1
+%%
+%% Callback from diameter_transport_sup as a result of start/0.
+%% Starts a child supervisor under the transport supervisor.
+
+start_link(Name) ->
+ supervisor:start_link({local, Name}, ?MODULE, []).
+
+init([]) ->
+ Mod = diameter_tcp,
+ Flags = {simple_one_for_one, 0, 1},
+ ChildSpec = {Mod,
+ {Mod, start_link, []},
+ temporary,
+ 1000,
+ worker,
+ [Mod]},
+ {ok, {Flags, [ChildSpec]}}.
diff --git a/lib/diameter/src/transport/diameter_transport_sup.erl b/lib/diameter/src/transport/diameter_transport_sup.erl
new file mode 100644
index 0000000000..6457ab78b0
--- /dev/null
+++ b/lib/diameter/src/transport/diameter_transport_sup.erl
@@ -0,0 +1,68 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Top supervisor for transport processes.
+%%
+
+-module(diameter_transport_sup).
+
+-behaviour(supervisor).
+
+-export([start_link/0, %% supervisor start
+ start_child/2]).
+
+%% supervisor callback
+-export([init/1]).
+
+%% ---------------------------------------------------------------------------
+
+%% start_link/0
+%%
+%% Start the transport top supervisor. This is started as a child at
+%% at application start, from diameter_sup.erl. Protocol-specific
+%% supervisors are started as children of this supervisor dynamically
+%% by calling start_child/2. (Eg. diameter_tcp_sup:start/0, which
+%% is called from diameter_tcp:start/3 to start supervisors the
+%% first time a TCP transport process is started.)
+
+start_link() ->
+ SupName = {local, ?MODULE},
+ supervisor:start_link(SupName, ?MODULE, []).
+
+%% start_child/2
+%%
+%% Start a protocol-specific supervisor under the top supervisor.
+
+start_child(Name, Module) ->
+ Spec = {Name,
+ {Module, start_link, [Name]},
+ permanent,
+ 1000,
+ supervisor,
+ [Module]},
+ supervisor:start_child(?MODULE, Spec).
+
+%% ---------------------------------------------------------------------------
+
+%% Top supervisor callback.
+init([]) ->
+ Flags = {one_for_one, 0, 1},
+ Workers = [], %% Each protocol starts its supervisor on demand.
+ {ok, {Flags, Workers}}.
diff --git a/lib/diameter/src/transport/modules.mk b/lib/diameter/src/transport/modules.mk
new file mode 100644
index 0000000000..a0dc3cf2c0
--- /dev/null
+++ b/lib/diameter/src/transport/modules.mk
@@ -0,0 +1,29 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+MODULES = \
+ diameter_etcp \
+ diameter_etcp_sup \
+ diameter_tcp \
+ diameter_tcp_sup \
+ diameter_sctp \
+ diameter_sctp_sup \
+ diameter_transport_sup
+
+HRL_FILES =
diff --git a/lib/diameter/subdirs.mk b/lib/diameter/subdirs.mk
new file mode 100644
index 0000000000..d80c97d57a
--- /dev/null
+++ b/lib/diameter/subdirs.mk
@@ -0,0 +1,20 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+SUB_DIRS = src doc/src
diff --git a/lib/diameter/test/.gitignore b/lib/diameter/test/.gitignore
new file mode 100644
index 0000000000..df38dfc5e3
--- /dev/null
+++ b/lib/diameter/test/.gitignore
@@ -0,0 +1,3 @@
+
+/log
+/depend.mk
diff --git a/lib/diameter/test/Makefile b/lib/diameter/test/Makefile
new file mode 100644
index 0000000000..04e686c969
--- /dev/null
+++ b/lib/diameter/test/Makefile
@@ -0,0 +1,184 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+ifeq ($(ERL_TOP),)
+TOP = $(DIAMETER_TOP)
+else
+TOP = $(ERL_TOP)
+DIAMETER_TOP = $(TOP)/lib/diameter
+endif
+
+include $(TOP)/make/target.mk
+include $(TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+
+include ../vsn.mk
+
+VSN = $(DIAMETER_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+
+RELSYSDIR = $(RELEASE_PATH)/diameter_test
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+include modules.mk
+
+EBIN = .
+
+HRL_FILES = $(INTERNAL_HRL_FILES)
+ERL_FILES = $(MODULES:%=%.erl)
+
+SOURCE = $(HRL_FILES) $(ERL_FILES)
+TARGET_FILES = $(MODULES:%=%.$(EMULATOR))
+
+SUITE_MODULES = $(filter diameter_%_SUITE, $(MODULES))
+SUITES = $(SUITE_MODULES:diameter_%_SUITE=%)
+
+RELTEST_FILES = $(TEST_SPEC_FILE) $(COVER_SPEC_FILE) $(SOURCE)
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+
+include ../src/app/diameter.mk
+
+# This is only used to compile suite locally when running with a
+# target like 'all' below. Target release_tests only installs source.
+ERL_COMPILE_FLAGS += $(DIAMETER_ERL_COMPILE_FLAGS) \
+ -DDIAMETER_CT=true \
+ -I $(DIAMETER_TOP)/src/app
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+all: $(SUITES)
+
+beam tests debug opt: $(TARGET_FILES)
+
+clean:
+ rm -f $(TARGET_FILES)
+ rm -f depend.mk
+
+realclean: clean
+ rm -rf log
+ rm -f errs core *~
+
+.PHONY: all tests debug opt clean realclean
+
+docs:
+
+info:
+ @echo "TARGET_FILES = $(TARGET_FILES)"
+ @echo
+ @echo "ERL_COMPILE_FLAGS = $(ERL_COMPILE_FLAGS)"
+ @echo "ERL = $(ERL)"
+ @echo "ERLC = $(ERLC)"
+ @echo
+ @echo "HRL_FILES = $(HRL_FILES)"
+ @echo "ERL_FILES = $(ERL_FILES)"
+ @echo "TARGET_FILES = $(TARGET_FILES)"
+ @echo
+ @echo "SUITE_MODULES = $(SUITE_MODULES)"
+ @echo "SUITES = $(SUITES)"
+ @echo
+
+help:
+ @echo
+ @echo "Targets:"
+ @echo
+ @echo " all"
+ @echo " Run all test suites."
+ @echo
+ @echo " $(SUITES)"
+ @echo " Run a specific test suite."
+ @echo
+ @echo " tests"
+ @echo " Compile all test-code."
+ @echo
+ @echo " clean | realclean"
+ @echo " Remove generated files."
+ @echo
+ @echo " info"
+ @echo " Prints various environment variables."
+ @echo " May be useful when debugging this Makefile."
+ @echo
+ @echo " help"
+ @echo " Print this info."
+ @echo
+
+.PHONY: docs info help
+
+# ----------------------------------------------------
+# Special Targets
+# ----------------------------------------------------
+
+# Exit with a non-zero status if the output looks to indicate failure.
+# diameter_ct:run/1 itself can't tell (it seems).
+$(SUITES): log tests
+ $(ERL) -noshell \
+ -pa $(DIAMETER_TOP)/ebin \
+ -sname diameter_test_$@ \
+ -s diameter_ct run diameter_$@_SUITE \
+ -s init stop \
+ | awk '1{rc=0} {print} / FAILED /{rc=1} END{exit rc}'
+# Shorter in sed but requires a GNU extension (ie. Q).
+
+log:
+ mkdir $@
+
+.PHONY: $(SUITES)
+
+# ----------------------------------------------------
+# Release Targets
+# ----------------------------------------------------
+
+include $(TOP)/make/otp_release_targets.mk
+
+release_spec:
+
+release_docs_spec:
+
+release_tests_spec:
+ $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DATA) $(RELTEST_FILES) $(RELSYSDIR)
+
+.PHONY: release_spec release_docs_spec release_test_specs
+
+# ----------------------------------------------------
+
+depend: depend.mk
+
+# Generate dependencies makefile.
+depend.mk: depend.sed $(MODULES:%=%.erl) Makefile
+ (for f in $(MODULES); do \
+ sed -f $< $$f.erl | sed "s@/@/$$f@"; \
+ done) \
+ > $@
+
+-include depend.mk
+
+.PHONY: depend
diff --git a/lib/diameter/test/depend.sed b/lib/diameter/test/depend.sed
new file mode 100644
index 0000000000..a399eb45f0
--- /dev/null
+++ b/lib/diameter/test/depend.sed
@@ -0,0 +1,31 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+
+#
+# Extract local include dependencies from .erl files. The output is massaged
+# further in Makefile.
+#
+
+/^-include/!d
+/^-include_lib/d
+/diameter_gen/d
+
+s@^-include("@@
+s@".*@@
+s@^@$(EBIN)/.$(EMULATOR): @
diff --git a/lib/diameter/test/diameter.cover b/lib/diameter/test/diameter.cover
new file mode 100644
index 0000000000..5fde6c7d01
--- /dev/null
+++ b/lib/diameter/test/diameter.cover
@@ -0,0 +1,6 @@
+%% -*- erlang -*-
+{exclude,
+ [
+ ]
+}.
+
diff --git a/lib/diameter/test/diameter.spec b/lib/diameter/test/diameter.spec
new file mode 100644
index 0000000000..fae7863bec
--- /dev/null
+++ b/lib/diameter/test/diameter.spec
@@ -0,0 +1 @@
+{suites, "../diameter_test", all}.
diff --git a/lib/diameter/test/diameter_app_SUITE.erl b/lib/diameter/test/diameter_app_SUITE.erl
new file mode 100644
index 0000000000..15a98d4441
--- /dev/null
+++ b/lib/diameter/test/diameter_app_SUITE.erl
@@ -0,0 +1,263 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests based on the contents of the diameter app file.
+%%
+
+-module(diameter_app_SUITE).
+
+-export([suite/0,
+ all/0,
+ init_per_suite/1,
+ end_per_suite/1]).
+
+%% testcases
+-export([keys/1,
+ vsn/1,
+ modules/1,
+ exports/1,
+ release/1,
+ xref/1,
+ relup/1]).
+
+-include("diameter_ct.hrl").
+
+-define(A, list_to_atom).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [keys,
+ vsn,
+ modules,
+ exports,
+ release,
+ xref,
+ relup].
+
+init_per_suite(Config) ->
+ [{application, ?APP, App}] = diameter_util:consult(?APP, app),
+ [{app, App} | Config].
+
+end_per_suite(_Config) ->
+ ok.
+
+%% ===========================================================================
+%% # keys/1
+%%
+%% Ensure that the app file contains selected keys. Some of these would
+%% also be caught by other testcases.
+%% ===========================================================================
+
+keys(Config) ->
+ App = fetch(app, Config),
+ [] = lists:filter(fun(K) -> not lists:keymember(K, 1, App) end,
+ [vsn, description, modules, registered, applications]).
+
+%% ===========================================================================
+%% # vsn/1
+%%
+%% Ensure that our app version sticks to convention.
+%% ===========================================================================
+
+vsn(Config) ->
+ true = is_vsn(fetch(vsn, fetch(app, Config))).
+
+%% ===========================================================================
+%% # modules/1
+%%
+%% Ensure that the app file modules and installed modules differ by
+%% compiler/help modules.
+%% ===========================================================================
+
+modules(Config) ->
+ Mods = fetch(modules, fetch(app, Config)),
+ Installed = code_mods(),
+ Help = [diameter_callback,
+ diameter_codegen,
+ diameter_dbg,
+ diameter_exprecs,
+ diameter_info,
+ diameter_spec_scan,
+ diameter_spec_util],
+ {[], Help} = {Mods -- Installed, lists:sort(Installed -- Mods)}.
+
+code_mods() ->
+ Dir = code:lib_dir(?APP, ebin),
+ {ok, Files} = file:list_dir(Dir),
+ [?A(lists:reverse(R)) || N <- Files, "maeb." ++ R <- [lists:reverse(N)]].
+
+%% ===========================================================================
+%% # exports/1
+%%
+%% Ensure that no module does export_all.
+%% ===========================================================================
+
+exports(Config) ->
+ Mods = fetch(modules, fetch(app, Config)),
+ [] = [M || M <- Mods, exports_all(M)].
+
+exports_all(Mod) ->
+ Opts = fetch(options, Mod:module_info(compile)),
+
+ is_list(Opts) andalso lists:member(export_all, Opts).
+
+%% ===========================================================================
+%% # release/1
+%%
+%% Ensure that it's possible to build a minimal release with our app file.
+%% ===========================================================================
+
+release(Config) ->
+ App = fetch(app, Config),
+ Rel = {release,
+ {"diameter test release", fetch(vsn, App)},
+ {erts, erlang:system_info(version)},
+ [{A, appvsn(A)} || A <- fetch(applications, App)]},
+ Dir = fetch(priv_dir, Config),
+ ok = write_file(filename:join([Dir, "diameter_test.rel"]), Rel),
+ {ok, _, []} = systools:make_script("diameter_test", [{path, [Dir]},
+ {outdir, Dir},
+ silent]).
+
+appvsn(Name) ->
+ [{application, Name, App}] = diameter_util:consult(Name, app),
+ fetch(vsn, App).
+
+%% ===========================================================================
+%% # xref/1
+%%
+%% Ensure that no function in our application calls an undefined function
+%% or one in an application we haven't specified as a dependency. (Almost.)
+%% ===========================================================================
+
+xref(Config) ->
+ App = fetch(app, Config),
+ Mods = fetch(modules, App),
+
+ {ok, XRef} = xref:start(make_name(xref_test_name)),
+ ok = xref:set_default(XRef, [{verbose, false}, {warnings, false}]),
+
+ %% Only add our application and those it's dependent on according
+ %% to the app file. Well, almost. erts beams are also required to
+ %% stop xref from complaining about calls to module erlang, which
+ %% was previously in kernel. Erts isn't an application however, in
+ %% the sense that there's no .app file, and isn't listed in
+ %% applications. Seems less than ideal. Also, diameter_tcp does
+ %% call ssl despite ssl not being listed as a dependency in the
+ %% app file since ssl is only required for TLS security: it's up
+ %% to a client who wants TLS it to start ssl.
+ ok = lists:foreach(fun(A) -> add_application(XRef, A) end,
+ [?APP, erts | fetch(applications, App)]),
+
+ {ok, Undefs} = xref:analyze(XRef, undefined_function_calls),
+
+ xref:stop(XRef),
+
+ %% Only care about calls from our own application.
+ [] = lists:filter(fun({{F,_,_},{T,_,_}}) ->
+ lists:member(F, Mods)
+ andalso {F,T} /= {diameter_tcp, ssl}
+ end,
+ Undefs).
+
+add_application(XRef, App) ->
+ add_application(XRef, App, code:lib_dir(App)).
+
+%% erts will not be in the lib directory before installation.
+add_application(XRef, erts, {error, _}) ->
+ Dir = filename:join([code:root_dir(), "erts", "preloaded", "ebin"]),
+ {ok, _} = xref:add_directory(XRef, Dir, []);
+add_application(XRef, App, Dir)
+ when is_list(Dir) ->
+ {ok, App} = xref:add_application(XRef, Dir, []).
+
+make_name(Suf) ->
+ list_to_atom(atom_to_list(?APP) ++ "_" ++ atom_to_list(Suf)).
+
+%% ===========================================================================
+%% # relup/1
+%%
+%% Ensure that we can generate release upgrade files using our appup file.
+%% ===========================================================================
+
+relup(Config) ->
+ [{Vsn, Up, Down}] = diameter_util:consult(?APP, appup),
+ true = is_vsn(Vsn),
+
+ App = fetch(app, Config),
+ Rel = [{erts, erlang:system_info(version)}
+ | [{A, appvsn(A)} || A <- fetch(applications, App)]],
+
+ Dir = fetch(priv_dir, Config),
+
+ Name = write_rel(Dir, Rel, Vsn),
+ UpFrom = acc_rel(Dir, Rel, Up),
+ DownTo = acc_rel(Dir, Rel, Down),
+
+ {[Name], [Name], UpFrom, DownTo} %% no intersections
+ = {[Name] -- UpFrom,
+ [Name] -- DownTo,
+ UpFrom -- DownTo,
+ DownTo -- UpFrom},
+
+ {ok, _, _, []} = systools:make_relup(Name, UpFrom, DownTo, [{path, [Dir]},
+ {outdir, Dir},
+ silent]).
+
+acc_rel(Dir, Rel, List) ->
+ lists:foldl(fun(T,A) -> acc_rel(Dir, Rel, T, A) end,
+ [],
+ List).
+
+acc_rel(Dir, Rel, {Vsn, _}, Acc) ->
+ [write_rel(Dir, Rel, Vsn) | Acc].
+
+%% Write a rel file and return its name.
+write_rel(Dir, [Erts | Apps], Vsn) ->
+ true = is_vsn(Vsn),
+ Name = "diameter_test_" ++ Vsn,
+ ok = write_file(filename:join([Dir, Name ++ ".rel"]),
+ {release,
+ {"diameter " ++ Vsn ++ " test release", Vsn},
+ Erts,
+ Apps}),
+ Name.
+
+%% ===========================================================================
+%% ===========================================================================
+
+fetch(Key, List) ->
+ {Key, {Key, Val}} = {Key, lists:keyfind(Key, 1, List)}, %% useful badmatch
+ Val.
+
+write_file(Path, T) ->
+ file:write_file(Path, io_lib:format("~p.", [T])).
+
+%% Is a version string of the expected form? Return the argument
+%% itself for 'false' for a useful badmatch.
+is_vsn(V) ->
+ is_list(V)
+ andalso length(V) == string:span(V, "0123456789.")
+ andalso V == string:join(string:tokens(V, [$.]), ".") %% no ".."
+ orelse {error, V}.
diff --git a/lib/diameter/test/diameter_codec_SUITE.erl b/lib/diameter/test/diameter_codec_SUITE.erl
new file mode 100644
index 0000000000..30c60be8e9
--- /dev/null
+++ b/lib/diameter/test/diameter_codec_SUITE.erl
@@ -0,0 +1,76 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 encode/decode of dictionary-related modules. Each test case
+%% runs multiple tests in parallel since many of the tests are just
+%% the same code with different in-data: implementing each test as a
+%% single testcase would make for much duplication with ct's current
+%% requirement of one function per testcase.
+%%
+
+-module(diameter_codec_SUITE).
+
+-export([suite/0,
+ all/0,
+ init_per_testcase/2,
+ end_per_testcase/2]).
+
+%% testcases
+-export([base/1,
+ gen/1,
+ lib/1]).
+
+-include("diameter_ct.hrl").
+
+-define(L, atom_to_list).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [base, gen, lib].
+
+init_per_testcase(gen, Config) ->
+ [{application, ?APP, App}] = diameter_util:consult(?APP, app),
+ {modules, Ms} = lists:keyfind(modules, 1, App),
+ [_|_] = Gs = lists:filter(fun(M) ->
+ lists:prefix("diameter_gen_", ?L(M))
+ end,
+ Ms),
+ [{dicts, Gs} | Config];
+
+init_per_testcase(_Name, Config) ->
+ Config.
+
+end_per_testcase(_, _) ->
+ ok.
+
+%% ===========================================================================
+
+base(_Config) ->
+ diameter_codec_test:base().
+
+gen([{dicts, Ms} | _]) ->
+ lists:foreach(fun diameter_codec_test:gen/1, Ms).
+
+lib(_Config) ->
+ diameter_codec_test:lib().
diff --git a/lib/diameter/test/diameter_codec_test.erl b/lib/diameter/test/diameter_codec_test.erl
new file mode 100644
index 0000000000..aab7ab35cc
--- /dev/null
+++ b/lib/diameter/test/diameter_codec_test.erl
@@ -0,0 +1,500 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_codec_test).
+
+-compile(export_all).
+
+%%
+%% Test encode/decode of dictionary-related modules.
+%%
+
+-include_lib("diameter/include/diameter.hrl").
+
+-define(BASE, diameter_gen_base_rfc3588).
+-define(BOOL, [true, false]).
+
+%% ===========================================================================
+%% Interface.
+
+base() ->
+ [] = run([{?MODULE, [base, T]} || T <- [zero, decode]]).
+
+gen(Mod) ->
+ Fs = [{Mod, F, []} || F <- [name, id, vendor_id, vendor_name]],
+ [] = run(Fs ++ [{?MODULE, [gen, Mod, T]} || T <- [messages,
+ command_codes,
+ avp_types,
+ grouped,
+ enums,
+ import_avps,
+ import_groups,
+ import_enums]]).
+
+lib() ->
+ Vs = {_,_} = values('Address'),
+ [] = run([[fun lib/2, N, Vs] || N <- [1,2]]).
+
+%% ===========================================================================
+%% Internal functions.
+
+lib(N, {_,_} = T) ->
+ B = 1 == N rem 2,
+ [] = run([[fun lib/2, A, B] || A <- element(N,T)]);
+
+lib(IP, B) ->
+ LA = tuple_to_list(IP),
+ {SA,Fun} = ip(LA),
+ [] = run([[fun lib/4, IP, B, Fun, A] || A <- [IP, LA, SA]]).
+
+lib(IP, B, Fun, A) ->
+ try Fun(A) of
+ IP when B ->
+ ok
+ catch
+ error:_ when not B ->
+ ok
+ end.
+
+ip([_,_,_,_] = A) ->
+ [$.|S] = lists:append(["." ++ integer_to_list(N) || N <- A]),
+ {S, fun diameter_lib:ip4address/1};
+ip([_,_,_,_,_,_,_,_] = A) ->
+ [$:|S] = lists:flatten([":" ++ io_lib:format("~.16B", [N]) || N <- A]),
+ {S, fun diameter_lib:ip6address/1}.
+
+%% ------------------------------------------------------------------------
+%% base/1
+%%
+%% Test of diameter_types.
+%% ------------------------------------------------------------------------
+
+base(T) ->
+ [] = run([{?MODULE, [base, T, F]} || F <- types()]).
+
+%% Ensure that 'zero' values encode only zeros.
+base(zero = T, F) ->
+ B = diameter_types:F(encode, T),
+ B = z(B);
+
+%% Ensure that we can decode what we encode and vice-versa, and that
+%% we can't decode invalid values.
+base(decode, F) ->
+ {Eq, Vs, Ns} = b(values(F)),
+ [] = run([{?MODULE, [base_decode, F, Eq, V]} || V <- Vs]),
+ [] = run([{?MODULE, [base_invalid, F, Eq, V]} || V <- Ns]).
+
+base_decode(F, Eq, Value) ->
+ d(fun(X,V) -> diameter_types:F(X,V) end, Eq, Value).
+
+base_invalid(F, Eq, Value) ->
+ try
+ base_decode(F, Eq, Value),
+ exit(nok)
+ catch
+ error: _ ->
+ ok
+ end.
+
+b({_,_,_} = T) ->
+ T;
+b({B,Vs})
+ when is_atom(B) ->
+ {B,Vs,[]};
+b({Vs,Ns}) ->
+ {true, Vs, Ns};
+b(Vs) ->
+ {true, Vs, []}.
+
+types() ->
+ [F || {F,2} <- diameter_types:module_info(exports)].
+
+%% ------------------------------------------------------------------------
+%% gen/2
+%%
+%% Test of generated encode/decode module.
+%% ------------------------------------------------------------------------
+
+gen(M, T) ->
+ [] = run(lists:map(fun(X) -> {?MODULE, [gen, M, T, X]} end,
+ fetch(T, M:dict()))).
+
+fetch(T, Spec) ->
+ case orddict:find(T, Spec) of
+ {ok, L} ->
+ L;
+ error ->
+ []
+ end.
+
+gen(M, messages, {Name, Code, Flags, _, _}) ->
+ Rname = M:msg2rec(Name),
+ Name = M:rec2msg(Rname),
+ {Code, F, _} = M:msg_header(Name),
+ 0 = F band 2#00001111,
+ Name = case M:msg_name(Code, lists:member('REQ', Flags)) of
+ N when Name /= 'answer-message' ->
+ N;
+ '' when Name == 'answer-message', M == ?BASE ->
+ Name
+ end,
+ [] = arity(M, Name, Rname);
+
+gen(M, command_codes = T, {Code, {Req, Abbr}, Ans}) ->
+ Rname = M:msg2rec(Req),
+ Rname = M:msg2rec(Abbr),
+ gen(M, T, {Code, Req, Ans});
+
+gen(M, command_codes = T, {Code, Req, {Ans, Abbr}}) ->
+ Rname = M:msg2rec(Ans),
+ Rname = M:msg2rec(Abbr),
+ gen(M, T, {Code, Req, Ans});
+
+gen(M, command_codes, {Code, Req, Ans}) ->
+ Msgs = orddict:fetch(messages, M:dict()),
+ {_, Code, _, _, _} = lists:keyfind(Req, 1, Msgs),
+ {_, Code, _, _, _} = lists:keyfind(Ans, 1, Msgs);
+
+gen(M, avp_types, {Name, Code, Type, _Flags, _Encr}) ->
+ {Code, Flags, VendorId} = M:avp_header(Name),
+ 0 = Flags band 2#00011111,
+ V = undefined /= VendorId,
+ V = 0 /= Flags band 2#10000000,
+ {Name, Type} = M:avp_name(Code, VendorId),
+ B = M:empty_value(Name),
+ B = z(B),
+ [] = avp_decode(M, Type, Name);
+
+gen(M, grouped, {Name, _, _, _}) ->
+ Rname = M:name2rec(Name),
+ [] = arity(M, Name, Rname);
+
+gen(M, enums, {Name, ED}) ->
+ [] = run([{?MODULE, [enum, M, Name, T]} || T <- ED]);
+
+gen(M, Tag, {_Mod, L}) ->
+ T = retag(Tag),
+ [] = run([{?MODULE, [gen, M, T, I]} || I <- L]).
+
+%% avp_decode/3
+
+avp_decode(Mod, Type, Name) ->
+ {Eq, Vs, _} = b(values(Type, Name, Mod)),
+ [] = run([{?MODULE, [avp_decode, Mod, Name, Type, Eq, V]}
+ || V <- v(Vs)]).
+
+avp_decode(Mod, Name, Type, Eq, Value) ->
+ d(fun(X,V) -> avp(Mod, X, V, Name, Type) end, Eq, Value).
+
+avp(Mod, decode = X, V, Name, 'Grouped') ->
+ {Rec, _} = Mod:avp(X, V, Name),
+ Rec;
+avp(Mod, X, V, Name, _) ->
+ Mod:avp(X, V, Name).
+
+%% v/1
+
+%% List of values ...
+v(Vs)
+ when is_list(Vs) ->
+ Vs;
+
+%% .. or enumeration for grouped avps. This could be quite large
+%% (millions of values) but since the avps are also tested
+%% individually don't bother trying everything. Instead, choose a
+%% reasonable number of values at random.
+v(E) ->
+ v(2000, E(0), E).
+
+v(Max, Ord, E)
+ when Ord =< Max ->
+ diameter_enum:to_list(E);
+v(Max, Ord, E) ->
+ {M,S,U} = now(),
+ random:seed(M,S,U),
+ v(Max, Ord, E, []).
+
+v(0, _, _, Acc) ->
+ Acc;
+v(N, Ord, E, Acc) ->
+ v(N-1, Ord, E, [E(random:uniform(Ord)) | Acc]).
+
+%% arity/3
+
+arity(M, Name, Rname) ->
+ Rec = M:'#new-'(Rname),
+ [] = run([{?MODULE, [arity, M, Name, F, Rec]}
+ || F <- M:'#info-'(Rname, fields)]).
+
+arity(M, Name, AvpName, Rec) ->
+ Def = M:'#get-'(AvpName, Rec),
+ Def = case M:avp_arity(Name, AvpName) of
+ 1 ->
+ undefined;
+ A when 0 /= A ->
+ []
+ end.
+
+%% enum/3
+
+enum(M, Name, {E,_}) ->
+ B = <<E:32/integer>>,
+ B = M:avp(encode, E, Name),
+ E = M:avp(decode, B, Name).
+
+retag(import_avps) -> avp_types;
+retag(import_groups) -> grouped;
+retag(import_enums) -> enums;
+
+retag(avp_types) -> import_avps;
+retag(enums) -> import_enums.
+
+%% ===========================================================================
+
+d(F, Eq, V) ->
+ B = F(encode, V),
+ D = F(decode, B),
+ V = if Eq -> %% test for value equality ...
+ D;
+ true -> %% ... or that encode/decode is idempotent
+ D = F(decode, F(encode, D)),
+ V
+ end.
+
+z(B) ->
+ << <<0>> || <<_>> <= B >>.
+
+%% values/1
+%%
+%% Return a list of base type values. Can also be wrapped in a tuple
+%% with 'false' to indicate that encode followed by decode may not be
+%% the identity map. (Although that this composition is idempotent is
+%% tested.)
+
+values('OctetString' = T) ->
+ {["", atom_to_list(T)], [-1, 256]};
+
+values('Integer32') ->
+ Mx = (1 bsl 31) - 1,
+ Mn = -1*Mx,
+ {[Mn, 0, random(Mn,Mx), Mx], [Mn - 1, Mx + 1]};
+
+values('Integer64') ->
+ Mx = (1 bsl 63) - 1,
+ Mn = -1*Mx,
+ {[Mn, 0, random(Mn,Mx), Mx], [Mn - 1, Mx + 1]};
+
+values('Unsigned32') ->
+ M = (1 bsl 32) - 1,
+ {[0, random(M), M], [-1, M + 1]};
+
+values('Unsigned64') ->
+ M = (1 bsl 64) - 1,
+ {[0, random(M), M], [-1, M + 1]};
+
+values('Float32') ->
+ E = (1 bsl 8) - 2,
+ F = (1 bsl 23) - 1,
+ <<Mx:32/float>> = <<0:1/integer, E:8/integer, F:23/integer>>,
+ <<Mn:32/float>> = <<1:1/integer, E:8/integer, F:23/integer>>,
+ {[0.0, infinity, '-infinity', Mx, Mn], [0]};
+
+values('Float64') ->
+ E = (1 bsl 11) - 2,
+ F = (1 bsl 52) - 1,
+ <<Mx:64/float>> = <<0:1/integer, E:11/integer, F:52/integer>>,
+ <<Mn:64/float>> = <<1:1/integer, E:11/integer, F:52/integer>>,
+ {[0.0, infinity, '-infinity', Mx, Mn], [0]};
+
+values('Address') ->
+ {[{255,0,random(16#FF),1}, {65535,0,0,random(16#FFFF),0,0,0,1}],
+ [{256,0,0,1}, {65536,0,0,0,0,0,0,1}]};
+
+values('DiameterIdentity') ->
+ {["x", "diameter.com"], [""]};
+
+values('DiameterURI') ->
+ {false, ["aaa" ++ S ++ "://diameter.se" ++ P ++ Tr ++ Pr
+ || S <- ["", "s"],
+ P <- ["", ":1234"],
+ Tr <- ["" | [";transport=" ++ X
+ || X <- ["tcp", "sctp", "udp"]]],
+ Pr <- ["" | [";protocol=" ++ X
+ || X <- ["diameter","radius","tacacs+"]]]]};
+
+values(T)
+ when T == 'IPFilterRule';
+ T == 'QoSFilterRule' ->
+ ["deny in 0 from 127.0.0.1 to 10.0.0.1"];
+
+%% RFC 3629 defines the UTF-8 encoding of U+0000 through U+10FFFF with the
+%% exception of U+D800 through U+DFFF.
+values('UTF8String') ->
+ {[[],
+ lists:seq(0,16#1FF),
+ [0,16#D7FF,16#E000,16#10FFFF],
+ [random(16#D7FF), random(16#E000,16#10FFFF)]],
+ [[-1],
+ [16#D800],
+ [16#DFFF],
+ [16#110000]]};
+
+values('Time') ->
+ {[{{1968,1,20},{3,14,8}}, %% 19000101T000000 + 1 bsl 31
+ {date(), time()},
+ {{2036,2,7},{6,28,15}},
+ {{2036,2,7},{6,28,16}}, %% 19000101T000000 + 2 bsl 31
+ {{2104,2,26},{9,42,23}}],
+ [{{1968,1,20},{3,14,7}},
+ {{2104,2,26},{9,42,24}}]}. %% 19000101T000000 + 3 bsl 31
+
+%% values/3
+%%
+%% Return list or enumerations of values for a given AVP. Can be
+%% wrapped as for values/1.
+
+values('Enumerated', Name, Mod) ->
+ {_Name, Vals} = lists:keyfind(Name, 1, types(enums, Mod)),
+ lists:map(fun({N,_}) -> N end, Vals);
+
+values('Grouped', Name, Mod) ->
+ Rname = Mod:name2rec(Name),
+ Rec = Mod:'#new-'(Rname),
+ Avps = Mod:'#info-'(Rname, fields),
+ Enum = diameter_enum:combine(lists:map(fun({_,Vs,_}) -> to_enum(Vs) end,
+ [values(F, Mod) || F <- Avps])),
+ {false, diameter_enum:append(group(Mod, Name, Rec, Avps, Enum))};
+
+values(_, 'Framed-IP-Address', _) ->
+ [{127,0,0,1}];
+
+values(Type, _, _) ->
+ values(Type).
+
+to_enum(Vs)
+ when is_list(Vs) ->
+ diameter_enum:new(Vs);
+to_enum(E) ->
+ E.
+
+%% values/2
+
+values('AVP', _) ->
+ {true, [#diameter_avp{code = 0, data = <<0>>}], []};
+
+values(Name, Mod) ->
+ Avps = types(avp_types, Mod),
+ {Name, _Code, Type, _Flags, _Encr} = lists:keyfind(Name, 1, Avps),
+ b(values(Type, Name, Mod)).
+
+%% group/5
+%%
+%% Pack four variants of group values: tagged list containing all
+%% values, the corresponding record, a minimal tagged list and the
+%% coresponding record.
+
+group(Mod, Name, Rec, Avps, Enum) ->
+ lists:map(fun(B) -> group(Mod, Name, Rec, Avps, Enum, B) end,
+ [{A,R} || A <- ?BOOL, R <- ?BOOL]).
+
+group(Mod, Name, Rec, Avps, Enum, B) ->
+ diameter_enum:map(fun(Vs) -> g(Mod, Name, Rec, Avps, Vs, B) end, Enum).
+
+g(Mod, Name, Rec, Avps, Values, {All, AsRec}) ->
+ {Tagged, []}
+ = lists:foldl(fun(N, {A, [V|Vs]}) ->
+ {pack(All, Mod:avp_arity(Name, N), N, V, A), Vs}
+ end,
+ {[], Values},
+ Avps),
+ g(AsRec, Mod, Tagged, Rec).
+
+g(true, Mod, Vals, Rec) ->
+ Mod:'#set-'(Vals, Rec);
+g(false, _, Vals, _) ->
+ Vals.
+
+pack(true, Arity, Avp, Value, Acc) ->
+ [all(Arity, Avp, Value) | Acc];
+pack(false, Arity, Avp, Value, Acc) ->
+ min(Arity, Avp, Value, Acc).
+
+all(Mod, Name, Avp, V) ->
+ all(Mod:avp_arity(Name, Avp), Avp, V).
+
+all(1, Avp, V) ->
+ {Avp, V};
+all({0,'*'}, Avp, V) ->
+ a(1, Avp, V);
+all({N,'*'}, Avp, V) ->
+ a(N, Avp, V);
+all({_,N}, Avp, V) ->
+ a(N, Avp, V).
+
+a(N, Avp, V)
+ when N /= 0 ->
+ {Avp, lists:duplicate(N,V)}.
+
+min(Mod, Name, Avp, V, Acc) ->
+ min(Mod:avp_arity(Name, Avp), Avp, V, Acc).
+
+min(1, Avp, V, Acc) ->
+ [{Avp, V} | Acc];
+min({0,_}, _, _, Acc) ->
+ Acc;
+min({N,_}, Avp, V, Acc) ->
+ [{Avp, lists:duplicate(N,V)} | Acc].
+
+%% types/2
+
+types(T, Mod) ->
+ types(T, retag(T), Mod).
+
+types(T, IT, Mod) ->
+ Dict = Mod:dict(),
+ fetch(T, Dict) ++ lists:flatmap(fun({_,As}) -> As end, fetch(IT, Dict)).
+
+%% random/[12]
+
+random(M) ->
+ random(0,M).
+
+random(Mn,Mx) ->
+ seed(get({?MODULE, seed})),
+ Mn + random:uniform(Mx - Mn + 1) - 1.
+
+seed(undefined) ->
+ put({?MODULE, seed}, true),
+ random:seed(now());
+
+seed(true) ->
+ ok.
+
+%% run/1
+%%
+%% Unravel nested badmatches resulting from [] matches on calls to
+%% run/1 to make for more readable failures.
+
+run(L) ->
+ lists:flatmap(fun flatten/1, diameter_util:run(L)).
+
+flatten({_, {{badmatch, [{_, {{badmatch, _}, _}} | _] = L}, _}}) ->
+ L;
+flatten(T) ->
+ [T].
diff --git a/lib/diameter/test/diameter_ct.erl b/lib/diameter/test/diameter_ct.erl
new file mode 100644
index 0000000000..f8ee3dc1d7
--- /dev/null
+++ b/lib/diameter/test/diameter_ct.erl
@@ -0,0 +1,55 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_ct).
+
+%%
+%% Module used to run suites from Makefile.
+%%
+
+-export([run/1]).
+
+%% ct:run_test/1 is currently documented as returning a list of test
+%% results ... but no. Instead it returns 'ok' regardless of whether
+%% or not the suite in question has failed testcases.
+
+run([Suite]) ->
+ Start = info(),
+ ok = ct:run_test([{suite, Suite},
+ {logdir, "./log"},
+ {auto_compile, false}]),
+ info(Start , info()).
+
+info() ->
+ [{time, now()},
+ {process_count, erlang:system_info(process_count)}
+ | erlang:memory()].
+
+info(L0, L1) ->
+ [T, C | M]
+ = lists:zipwith(fun({T,N0}, {T,N1}) -> {T, N1, diff(T, N0, N1)} end,
+ L0,
+ L1),
+ Diff = [T, C, {memory, M}],
+ ct:pal("INFO: ~p~n", [Diff]).
+
+diff(time, T0, T1) ->
+ timer:now_diff(T1, T0);
+diff(_, N0, N1) ->
+ N1 - N0.
diff --git a/lib/diameter/test/diameter_ct.hrl b/lib/diameter/test/diameter_ct.hrl
new file mode 100644
index 0000000000..b6bd2ca9da
--- /dev/null
+++ b/lib/diameter/test/diameter_ct.hrl
@@ -0,0 +1,21 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(APP, diameter).
+-define(ERROR(T), erlang:error({?MODULE, ?LINE, T})).
diff --git a/lib/diameter/test/diameter_dict_SUITE.erl b/lib/diameter/test/diameter_dict_SUITE.erl
new file mode 100644
index 0000000000..87bb9727fe
--- /dev/null
+++ b/lib/diameter/test/diameter_dict_SUITE.erl
@@ -0,0 +1,151 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of the dict-like diameter_dict.
+%%
+
+-module(diameter_dict_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2]).
+
+%% testcases
+-export([append/1,
+ fetch/1,
+ fetch_keys/1,
+ filter/1,
+ find/1,
+ fold/1,
+ is_key/1,
+ map/1,
+ merge/1,
+ update/1,
+ update_counter/1]).
+
+-include("diameter_ct.hrl").
+
+-define(dict, diameter_dict).
+-define(util, diameter_util).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [{group, all} | tc()].
+
+groups() ->
+ [{all, [parallel], tc()}].
+
+tc() ->
+ [append,
+ fetch,
+ fetch_keys,
+ filter,
+ find,
+ fold,
+ is_key,
+ map,
+ merge,
+ update,
+ update_counter].
+
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(_, _) ->
+ ok.
+
+%% ===========================================================================
+
+-define(KV100, [{N,[N]} || N <- lists:seq(1,100)]).
+
+append(_) ->
+ D = ?dict:append(k, v, ?dict:new()),
+ [{k,[v,v]}] = ?dict:to_list(?dict:append(k, v, D)).
+
+fetch(_) ->
+ D = ?dict:from_list(?KV100),
+ [50] = ?dict:fetch(50, D),
+ Ref = make_ref(),
+ Ref = try ?dict:fetch(Ref, D) catch _:_ -> Ref end.
+
+fetch_keys(_) ->
+ L = ?KV100,
+ D = ?dict:from_list(L),
+ L = [{N,[N]} || N <- lists:sort(?dict:fetch_keys(D))].
+
+filter(_) ->
+ L = ?KV100,
+ F = fun(K,[_]) -> 0 == K rem 2 end,
+ D = ?dict:filter(F, ?dict:from_list(L)),
+ true = [T || {K,V} = T <- L, F(K,V)] == lists:sort(?dict:to_list(D)).
+
+find(_) ->
+ D = ?dict:from_list(?KV100),
+ {ok, [50]} = ?dict:find(50, D),
+ error = ?dict:find(make_ref(), D).
+
+fold(_) ->
+ L = ?KV100,
+ S = lists:sum([N || {N,_} <- L]),
+ S = ?dict:fold(fun(K,[_],A) -> K + A end, 0, ?dict:from_list(L)).
+
+is_key(_) ->
+ L = ?KV100,
+ D = ?dict:from_list(L),
+ true = lists:all(fun({N,_}) -> ?dict:is_key(N,D) end, L),
+ false = ?dict:is_key(make_ref(), D).
+
+map(_) ->
+ L = ?KV100,
+ F = fun(_,V) -> [N] = V, N*2 end,
+ D = ?dict:map(F, ?dict:from_list(L)),
+ M = [{K, F(K,V)} || {K,V} <- L],
+ M = lists:sort(?dict:to_list(D)).
+
+merge(_) ->
+ L = ?KV100,
+ F = fun(_,V1,V2) -> V1 ++ V2 end,
+ D = ?dict:merge(F, ?dict:from_list(L), ?dict:from_list(L)),
+ M = [{K, F(K,V,V)} || {K,V} <- L],
+ M = lists:sort(?dict:to_list(D)).
+
+update(_) ->
+ L = ?KV100,
+ F = fun([V]) -> 2*V end,
+ D = ?dict:update(50, F, ?dict:from_list(L)),
+ 100 = ?dict:fetch(50, D),
+ Ref = make_ref(),
+ Ref = try ?dict:update(Ref, F, D) catch _:_ -> Ref end,
+ [Ref] = ?dict:fetch(Ref, ?dict:update(Ref,
+ fun(_,_) -> ?ERROR(i_think_not) end,
+ [Ref],
+ D)).
+
+update_counter(_) ->
+ L = [{N,2*N} || {N,_} <- ?KV100],
+ D = ?dict:update_counter(50, 20, ?dict:from_list(L)),
+ 120 = ?dict:fetch(50,D),
+ 2 = ?dict:fetch(1,D).
diff --git a/lib/diameter/test/diameter_enum.erl b/lib/diameter/test/diameter_enum.erl
new file mode 100644
index 0000000000..dfb6d04e3c
--- /dev/null
+++ b/lib/diameter/test/diameter_enum.erl
@@ -0,0 +1,406 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_enum).
+
+%%
+%% This module constructs finite enumerations.
+%%
+%% An enumeration is represented as a function on integers, 0 mapping
+%% to the number of values enumerated and successive integers mapping
+%% to enumerated values. The function will fail on anything but 0 and
+%% positive integers less then or equal to the value of the function
+%% at 0.
+%%
+%% The purpose of this is to provide a way of stepping through a large
+%% number of values without explicitly constructing the list of all
+%% possible values. For example, consider the following function that
+%% given a list of lists constructs the list of all possible lists
+%% constructed by choosing one element from each sublist.
+%%
+%% combine([H]) ->
+%% [[X] || X <- H];
+%% combine([H|T]) ->
+%% Ys = combine(T),
+%% [[X|Y] || X <- H, Y <- Ys].
+%%
+%% Eg. [[1,2],[3,4,5]] -> [[1,3],[1,4],[1,5],[2,3],[2,4],[2,5]]
+%%
+%% If L is a list of three 1000 element lists then combine(L) would
+%% construct a list of length 10^9 which will likely exhaust available
+%% memory. (Which is how this module came into being. A tail-recursive
+%% implementation doesn't fare much better.) By contrast,
+%%
+%% F = enum:combine([enum:new(L) || L <- Lists])
+%%
+%% only maps existing lists. It may still be undesirable to step
+%% through a very large number of values but it's possible, and easy
+%% to step through a selection of values as an alternative.
+%%
+
+%% Functions that return enumerations.
+-export([new/1,
+ combine/1,
+ reverse/1,
+ map/2,
+ append/1,
+ duplicate/2,
+ nthtail/2,
+ seq/2,
+ seq/3,
+ zip/1,
+ zip/2,
+ slice/3,
+ split/2]).
+
+%% Functions that operate on existing enumerations.
+-export([foreach/2,
+ foldl/3,
+ foldr/3,
+ all/2,
+ any/2,
+ member/2,
+ last/1,
+ nth/2,
+ to_list/1]).
+
+%% ------------------------------------------------------------------------
+%% new/1
+%%
+%% Turn a list/tuple of values into an enumeration that steps through
+%% each element. Turn anything else into an enumeration of that single
+%% value.
+%% ------------------------------------------------------------------------
+
+new(L)
+ when is_list(L) ->
+ new(list_to_tuple(L));
+
+new(T)
+ when is_tuple(T) ->
+ enum(size(T), fun(N) -> element(N,T) end);
+
+new(T) ->
+ fun(0) -> 1; (1) -> T end.
+
+enum(Ord, F) ->
+ fun(0) -> Ord; (N) when 0 < N, N =< Ord -> F(N) end.
+
+%% ------------------------------------------------------------------------
+%% combine/1
+%%
+%% Map a list/tuple of enumerations to the enumeration of all
+%% lists/tuples constructed by choosing one value from each
+%% enumeration in the list/tuple.
+%% ------------------------------------------------------------------------
+
+combine(T)
+ when is_tuple(T) ->
+ F = combine(tuple_to_list(T)),
+ enum(F(0), fun(N) -> list_to_tuple(F(N)) end);
+
+combine([]) ->
+ fun(0) -> 0 end;
+
+%% Given positive integers n_1,...,n_k, construct a bijection from
+%% {0,...,\prod_{i=1}^k} n_i - 1} to {0,...,n_1} x ... x {0,...,n_k}
+%% that maps N to (N_1,...,N_k) where:
+%%
+%% N_1 = (N div 1) rem n_1
+%% ...
+%% N_k = (N div n_1*...*n_{k-1}) rem n_k
+%%
+%% That is:
+%%
+%% N_i = (N div \prod_{j=1}^{i-1} n_j) rem n_i
+%%
+%% This corresponds to looping through N_1, incrementing N_2 as N_1
+%% loops, and so on up through N_k. The inverse map is as follows.
+%%
+%% (N_1,...,N_k) -> N = N_1 + N_2*n_1 + ... + N_k*n_{k-1}*...*n_1
+%%
+%% = \sum_{i=1}^k N_i*\prod_{j=i}^{i-1} n_j
+%%
+%% [Proof: Induction on k. For k=1 we have the identity map. If
+%% g_k : (N_1,...,N_k) |-> N above is bijective then consider
+%% the bijection
+%%
+%% G : (t,n) |--> t + n*K, K = n_k*...*n_1
+%%
+%% from {0,...,K-1} x {0,...,n_{k+1}-1} onto {0,...,n_{k+1}*K - 1}
+%% with inverse F : n |--> (n rem K, n div K). Since
+%%
+%% g_{k+1}(N_1,...,N_{k+1}) = g_k(N_1,...,N_K) + N_{k+1}*K
+%% = G(g_k(N_1,...,N_K), N_{k+1})
+%%
+%% and G, g_k and ((N-1,...,N_k),N_{k+1}) -> (N_1,...,N_{k+1})
+%% are all bijections, so is g_{k+1}.]
+
+combine([_|_] = L) ->
+ [Ord | Divs] = lists:foldl(fun(F,[D|_] = A) -> [F(0)*D | A] end, [1], L),
+ RL = lists:reverse(L),
+ enum(Ord, fun(N) -> combine(N, Ord, Divs, RL) end).
+
+%% Since we use 0 to return the number of elements enumerated, use
+%% bijections from {1,...,N} rather than {0,...,N-1}.
+
+combine(N, Ord, Divs, L)
+ when 0 < N, N =< Ord ->
+ {Vs, []} = lists:foldl(fun(F, {A, [D|Ds]}) ->
+ {[F(1 + (((N-1) div D) rem F(0))) | A], Ds}
+ end,
+ {[], Divs},
+ L),
+ Vs.
+
+%% ------------------------------------------------------------------------
+%% reverse/1
+%%
+%% Construct the enumeration that reverses the order in which values
+%% are traversed.
+%% ------------------------------------------------------------------------
+
+reverse(E) ->
+ Ord = E(0),
+ enum(Ord, fun(N) -> E(Ord + 1 - N) end).
+
+%% ------------------------------------------------------------------------
+%% map/2
+%%
+%% Construct an enumeration that maps enumerated values.
+%% ------------------------------------------------------------------------
+
+map(Fun, E) ->
+ enum(E(0), fun(N) -> Fun(E(N)) end).
+
+%% ------------------------------------------------------------------------
+%% append/2
+%%
+%% Construct an enumeration that successively steps through each of a
+%% list of enumerations.
+%% ------------------------------------------------------------------------
+
+append(Es) ->
+ [Ord | Os] = lists:foldl(fun(E, [N|_] = A) -> [N+E(0)|A] end, [0], Es),
+ Rev = lists:reverse(Es),
+ enum(Ord, fun(N) -> append(N, Os, Rev) end).
+
+append(N, [Ord | _], [E | _])
+ when N > Ord ->
+ E(N - Ord);
+append(N, [_|Os], [_|Es]) ->
+ append(N, Os, Es).
+
+%% ------------------------------------------------------------------------
+%% duplicate/2
+%%
+%% Construct an enumeration that traverses an enumeration multiple
+%% times. Equivalent to append(lists:duplicate(N, E)).
+%% ------------------------------------------------------------------------
+
+duplicate(N, E) ->
+ Ord = E(0),
+ enum(N*Ord, fun(M) -> E(1 + ((M-1) rem Ord)) end).
+
+%% ------------------------------------------------------------------------
+%% nthtail/2
+%%
+%% Construct an enumeration that omits values at the head of an
+%% existing enumeration.
+%% ------------------------------------------------------------------------
+
+nthtail(N, E)
+ when 0 =< N ->
+ nthtail(E(0) - N, N, E).
+
+nthtail(Ord, N, E)
+ when 0 =< Ord ->
+ enum(Ord, fun(M) -> E(M+N) end).
+
+%% ------------------------------------------------------------------------
+%% seq/[23]
+%%
+%% Construct an enumeration that steps through a sequence of integers.
+%% ------------------------------------------------------------------------
+
+seq(From, To) ->
+ seq(From, To, 1).
+
+seq(From, To, Incr)
+ when From =< To ->
+ enum((To - From + Incr) div Incr, fun(N) -> From + (N-1)*Incr end).
+
+%% ------------------------------------------------------------------------
+%% zip/[12]
+%%
+%% Construct an enumeration whose nth value is the list of nth values
+%% of a list of enumerations.
+%% ------------------------------------------------------------------------
+
+zip(Es) ->
+ zip(fun(T) -> T end, Es).
+
+zip(_, []) ->
+ [];
+zip(Fun, Es) ->
+ enum(lists:min([E(0) || E <- Es]), fun(N) -> Fun([E(N) || E <- Es]) end).
+
+%% ------------------------------------------------------------------------
+%% slice/3
+%%
+%% Construct an enumeration of a given length from a given starting point.
+%% ------------------------------------------------------------------------
+
+slice(N, Len, E)
+ when is_integer(N), N > 0, is_integer(Len), Len >= 0 ->
+ slice(N, Len, E(0) - (N - 1), E).
+
+slice(_, _, Tail, _)
+ when Tail < 1 ->
+ fun(0) -> 0 end;
+
+slice(N, Len, Tail, E) ->
+ enum(lists:min([Len, Tail]), fun(M) -> E(N-1+M) end).
+
+%% ------------------------------------------------------------------------
+%% split/2
+%%
+%% Split an enumeration into a list of enumerations of the specified
+%% length. The last enumeration of the list may have order less than
+%% this length.
+%% ------------------------------------------------------------------------
+
+split(Len, E)
+ when is_integer(Len), Len > 0 ->
+ split(1, E(0), Len, E, []).
+
+split(N, Ord, _, _, Acc)
+ when N > Ord ->
+ lists:reverse(Acc);
+
+split(N, Ord, Len, E, Acc) ->
+ split(N+Len, Ord, Len, E, [slice(N, Len, E) | Acc]).
+
+%% ------------------------------------------------------------------------
+%% foreach/2
+%%
+%% Apply a fun to each value of an enumeration.
+%% ------------------------------------------------------------------------
+
+foreach(Fun, E) ->
+ foldl(fun(N,ok) -> Fun(N), ok end, ok, E).
+
+%% ------------------------------------------------------------------------
+%% foldl/3
+%% foldr/3
+%%
+%% Fold through values in an enumeration.
+%% ------------------------------------------------------------------------
+
+foldl(Fun, Acc, E) ->
+ foldl(E(0), 1, Fun, Acc, E).
+
+foldl(M, N, _, Acc, _)
+ when N == M+1 ->
+ Acc;
+foldl(M, N, Fun, Acc, E) ->
+ foldl(M, N+1, Fun, Fun(E(N), Acc), E).
+
+foldr(Fun, Acc, E) ->
+ foldl(Fun, Acc, reverse(E)).
+
+%% ------------------------------------------------------------------------
+%% all/2
+%%
+%% Do all values of an enumeration satisfy a predicate?
+%% ------------------------------------------------------------------------
+
+all(Pred, E) ->
+ all(E(0), 1, Pred, E).
+
+all(M, N, _, _)
+ when N == M+1 ->
+ true;
+all(M, N, Pred, E) ->
+ Pred(E(N)) andalso all(M, N+1, Pred, E).
+
+%% Note that andalso/orelse are tail-recusive as of R13A.
+
+%% ------------------------------------------------------------------------
+%% any/2
+%%
+%% Does any value of an enumeration satisfy a predicate?
+%% ------------------------------------------------------------------------
+
+any(Pred, E) ->
+ any(E(0), 1, Pred, E).
+
+any(M, N, _, _)
+ when N == M+1 ->
+ false;
+any(M, N, Pred, E) ->
+ Pred(E(N)) orelse any(M, N+1, Pred, E).
+
+%% ------------------------------------------------------------------------
+%% member/2
+%%
+%% Does a value match any in an enumeration?
+%% ------------------------------------------------------------------------
+
+member(X, E) ->
+ member(E(0), 1, X, E).
+
+member(M, N, _, _)
+ when N == M+1 ->
+ false;
+member(M, N, X, E) ->
+ match(E(N), X) orelse member(M, N+1, X, E).
+
+match(X, X) ->
+ true;
+match(_, _) ->
+ false.
+
+%% ------------------------------------------------------------------------
+%% last/1
+%%
+%% Return the last value of an enumeration.
+%% ------------------------------------------------------------------------
+
+last(E) ->
+ E(E(0)).
+
+%% ------------------------------------------------------------------------
+%% nth/2
+%%
+%% Return a selected value of an enumeration.
+%% ------------------------------------------------------------------------
+
+nth(N, E) ->
+ E(N).
+
+%% ------------------------------------------------------------------------
+%% to_list/1
+%%
+%% Turn an enumeration into a list. Not good if the very many values
+%% are enumerated.
+%% ------------------------------------------------------------------------
+
+to_list(E) ->
+ foldr(fun(X,A) -> [X|A] end, [], E).
diff --git a/lib/diameter/test/diameter_failover_SUITE.erl b/lib/diameter/test/diameter_failover_SUITE.erl
new file mode 100644
index 0000000000..c25e9682f0
--- /dev/null
+++ b/lib/diameter/test/diameter_failover_SUITE.erl
@@ -0,0 +1,262 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of traffic between six Diameter nodes in three realms,
+%% connected as follows.
+%%
+%% ----- SERVER1.REALM2
+%% /
+%% / ----- SERVER2.REALM2
+%% | /
+%% CLIENT.REALM1 ------ SERVER3.REALM2
+%% | \
+%% | \
+%% \ ---- SERVER1.REALM3
+%% \
+%% ----- SERVER2.REALM3
+%%
+
+-module(diameter_failover_SUITE).
+
+-export([suite/0,
+ all/0]).
+
+%% testcases
+-export([start/1,
+ start_services/1,
+ connect/1,
+ send_ok/1,
+ send_nok/1,
+ stop_services/1,
+ stop/1]).
+
+%% diameter callbacks
+-export([peer_up/3,
+ peer_down/3,
+ pick_peer/4,
+ prepare_request/3,
+ prepare_retransmit/3,
+ handle_answer/4,
+ handle_error/4,
+ handle_request/3]).
+
+-ifdef(DIAMETER_CT).
+-include("diameter_gen_base_rfc3588.hrl").
+-else.
+-include_lib("diameter/include/diameter_gen_base_rfc3588.hrl").
+-endif.
+
+-include_lib("diameter/include/diameter.hrl").
+-include("diameter_ct.hrl").
+
+%% ===========================================================================
+
+-define(util, diameter_util).
+
+-define(ADDR, {127,0,0,1}).
+
+-define(CLIENT, "CLIENT.REALM1").
+-define(SERVER1, "SERVER1.REALM2").
+-define(SERVER2, "SERVER2.REALM2").
+-define(SERVER3, "SERVER3.REALM2").
+-define(SERVER4, "SERVER1.REALM3").
+-define(SERVER5, "SERVER2.REALM3").
+
+-define(SERVICES, [?CLIENT, ?SERVER1, ?SERVER2, ?SERVER3, ?SERVER4, ?SERVER5]).
+
+-define(DICT_COMMON, ?DIAMETER_DICT_COMMON).
+
+-define(APP_ALIAS, the_app).
+-define(APP_ID, ?DICT_COMMON:id()).
+
+%% Config for diameter:start_service/2.
+-define(SERVICE(Host, Dict),
+ [{'Origin-Host', Host},
+ {'Origin-Realm', realm(Host)},
+ {'Host-IP-Address', [?ADDR]},
+ {'Vendor-Id', 12345},
+ {'Product-Name', "OTP/diameter"},
+ {'Acct-Application-Id', [Dict:id()]},
+ {application, [{alias, ?APP_ALIAS},
+ {dictionary, Dict},
+ {module, ?MODULE},
+ {answer_errors, callback}]}]).
+
+-define(SUCCESS, 2001).
+
+-define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_LOGOUT').
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [start,
+ start_services,
+ connect,
+ send_ok,
+ send_nok,
+ stop_services,
+ stop].
+
+%% ===========================================================================
+%% start/stop testcases
+
+start(_Config) ->
+ ok = diameter:start().
+
+start_services(_Config) ->
+ S = [server(N, ?DICT_COMMON) || N <- tl(?SERVICES)],
+
+ ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT, ?DICT_COMMON)),
+
+ {save_config, [{?CLIENT, S}]}.
+
+connect(Config) ->
+ {_, Conns} = proplists:get_value(saved_config, Config),
+
+ lists:foreach(fun({CN,Ss}) -> connect(CN, Ss) end, Conns).
+
+stop_services(_Config) ->
+ [] = [{H,T} || H <- ?SERVICES,
+ T <- [diameter:stop_service(H)],
+ T /= ok].
+
+stop(_Config) ->
+ ok = diameter:stop().
+
+%% ----------------------------------------
+
+server(Name, Dict) ->
+ ok = diameter:start_service(Name, ?SERVICE(Name, Dict)),
+ {Name, ?util:listen(Name, tcp)}.
+
+connect(Name, Refs) ->
+ [{{Name, ?util:connect(Name, tcp, LRef)}, T} || {_, LRef} = T <- Refs].
+
+%% ===========================================================================
+%% traffic testcases
+
+%% Send an STR and expect success after SERVER3 answers after a couple
+%% of failovers.
+send_ok(_Config) ->
+ Req = ['STR', {'Destination-Realm', realm(?SERVER1)},
+ {'Termination-Cause', ?LOGOUT},
+ {'Auth-Application-Id', ?APP_ID}],
+ #diameter_base_STA{'Result-Code' = ?SUCCESS,
+ 'Origin-Host' = ?SERVER3}
+ = call(Req, [{filter, realm}]).
+
+%% Send an STR and expect failure when both servers fail.
+send_nok(_Config) ->
+ Req = ['STR', {'Destination-Realm', realm(?SERVER4)},
+ {'Termination-Cause', ?LOGOUT},
+ {'Auth-Application-Id', ?APP_ID}],
+ {error, failover} = call(Req, [{filter, realm}]).
+
+%% ===========================================================================
+
+realm(Host) ->
+ tl(lists:dropwhile(fun(C) -> C /= $. end, Host)).
+
+call(Req, Opts) ->
+ diameter:call(?CLIENT, ?APP_ALIAS, Req, Opts).
+
+set([H|T], Vs) ->
+ [H | Vs ++ T].
+
+%% ===========================================================================
+%% diameter callbacks
+
+%% peer_up/3
+
+peer_up(_SvcName, _Peer, State) ->
+ State.
+
+%% peer_down/3
+
+peer_down(_SvcName, _Peer, State) ->
+ State.
+
+%% pick_peer/4
+
+%% Choose a server other than SERVER3 or SERVER5 if possible.
+pick_peer(Peers, _, ?CLIENT, _State) ->
+ case lists:partition(fun({_, #diameter_caps{origin_host = {_, OH}}}) ->
+ OH /= ?SERVER3 andalso OH /= ?SERVER5
+ end,
+ Peers)
+ of
+ {[], [Peer]} ->
+ {ok, Peer};
+ {[Peer | _], _} ->
+ {ok, Peer}
+ end.
+
+%% prepare_request/3
+
+prepare_request(Pkt, ?CLIENT, {_Ref, Caps}) ->
+ {send, prepare(Pkt, Caps)}.
+
+prepare(#diameter_packet{msg = Req}, Caps) ->
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}
+ = Caps,
+ set(Req, [{'Session-Id', diameter:session_id(OH)},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR}]).
+
+%% prepare_retransmit/3
+
+prepare_retransmit(Pkt, ?CLIENT, _Peer) ->
+ {send, Pkt}.
+
+%% handle_answer/4
+
+handle_answer(Pkt, _Req, ?CLIENT, _Peer) ->
+ #diameter_packet{msg = Rec, errors = []} = Pkt,
+ Rec.
+
+%% handle_error/4
+
+handle_error(Reason, _Req, ?CLIENT, _Peer) ->
+ {error, Reason}.
+
+%% handle_request/3
+
+%% Only SERVER3 actually answers.
+handle_request(Pkt, ?SERVER3, {_, Caps}) ->
+ #diameter_packet{msg = #diameter_base_STR{'Session-Id' = SId,
+ 'Origin-Host' = ?CLIENT}}
+ = Pkt,
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}
+ = Caps,
+
+ {reply, #diameter_base_STA{'Result-Code' = ?SUCCESS,
+ 'Session-Id' = SId,
+ 'Origin-Host' = OH,
+ 'Origin-Realm' = OR}};
+
+%% Others kill the transport to force failover.
+handle_request(_, _, {TPid, _}) ->
+ exit(TPid, kill),
+ discard.
diff --git a/lib/diameter/test/diameter_reg_SUITE.erl b/lib/diameter/test/diameter_reg_SUITE.erl
new file mode 100644
index 0000000000..ade824c9dd
--- /dev/null
+++ b/lib/diameter/test/diameter_reg_SUITE.erl
@@ -0,0 +1,119 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of the server implemented by diameter_reg.erl.
+%%
+
+-module(diameter_reg_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2,
+ init_per_suite/1,
+ end_per_suite/1]).
+
+%% testcases
+-export([add/1,
+ add_new/1,
+ del/1,
+ repl/1,
+ terms/1,
+ pids/1]).
+
+-define(reg, diameter_reg).
+-define(util, diameter_util).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [{group, all} | tc()].
+
+groups() ->
+ [{all, [parallel], tc()}].
+
+tc() ->
+ [add,
+ add_new,
+ del,
+ repl,
+ terms,
+ pids].
+
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(_, _) ->
+ ok.
+
+init_per_suite(Config) ->
+ ok = diameter:start(),
+ Config.
+
+end_per_suite(_Config) ->
+ ok = diameter:stop().
+
+%% ===========================================================================
+
+add(_) ->
+ Ref = make_ref(),
+ true = ?reg:add(Ref),
+ true = ?reg:add(Ref),
+ [{Ref, Pid}] = ?reg:match(Ref),
+ Pid = self().
+
+add_new(_) ->
+ Ref = make_ref(),
+ true = ?reg:add_new(Ref),
+ false = ?reg:add_new(Ref).
+
+del(_) ->
+ Ref = make_ref(),
+ true = ?reg:add_new(Ref),
+ true = ?reg:add_new({Ref}),
+ true = ?reg:del({Ref}),
+ [{Ref, Pid}] = ?reg:match(Ref),
+ Pid = self().
+
+repl(_) ->
+ Ref = make_ref(),
+ true = ?reg:add_new({Ref}),
+ true = ?reg:repl({Ref}, Ref),
+ false = ?reg:add_new(Ref),
+ false = ?reg:repl({Ref}, Ref),
+ [{Ref, Pid}] = ?reg:match(Ref),
+ Pid = self().
+
+terms(_) ->
+ Ref = make_ref(),
+ true = ?reg:add_new(Ref),
+ [[Pid]] = [L || {T,L} <- ?reg:terms(), T == Ref],
+ Pid = self().
+
+pids(_) ->
+ Ref = make_ref(),
+ true = ?reg:add_new(Ref),
+ %% Don't match [[Ref]] since this will only necessarily be the
+ %% case when the test is run in its own process.
+ [_|_] = [L || {P,L} <- ?reg:pids(), P == self()].
diff --git a/lib/diameter/test/diameter_relay_SUITE.erl b/lib/diameter/test/diameter_relay_SUITE.erl
new file mode 100644
index 0000000000..03f1115496
--- /dev/null
+++ b/lib/diameter/test/diameter_relay_SUITE.erl
@@ -0,0 +1,368 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of traffic between seven Diameter nodes connected as follows.
+%%
+%% --- SERVER1.REALM2
+%% /
+%% ---- RELAY.REALM2 ---- SERVER2.REALM2
+%% / |
+%% CLIENT.REALM1 |
+%% \ |
+%% ---- RELAY.REALM3 ---- SERVER1.REALM3
+%% \
+%% --- SERVER2.REALM3
+%%
+
+-module(diameter_relay_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2]).
+
+%% testcases
+-export([start/1,
+ start_services/1,
+ connect/1,
+ send1/1,
+ send2/1,
+ send3/1,
+ send4/1,
+ send_loop/1,
+ send_timeout_1/1,
+ send_timeout_2/1,
+ disconnect/1,
+ stop_services/1,
+ stop/1]).
+
+%% diameter callbacks
+-export([peer_up/3,
+ peer_down/3,
+ pick_peer/4,
+ prepare_request/3,
+ prepare_retransmit/3,
+ handle_answer/4,
+ handle_error/4,
+ handle_request/3]).
+
+-ifdef(DIAMETER_CT).
+-include("diameter_gen_base_rfc3588.hrl").
+-else.
+-include_lib("diameter/include/diameter_gen_base_rfc3588.hrl").
+-endif.
+
+-include_lib("diameter/include/diameter.hrl").
+-include("diameter_ct.hrl").
+
+%% ===========================================================================
+
+-define(util, diameter_util).
+
+-define(ADDR, {127,0,0,1}).
+
+-define(CLIENT, "CLIENT.REALM1").
+-define(RELAY1, "RELAY.REALM2").
+-define(SERVER1, "SERVER1.REALM2").
+-define(SERVER2, "SERVER2.REALM2").
+-define(RELAY2, "RELAY.REALM3").
+-define(SERVER3, "SERVER1.REALM3").
+-define(SERVER4, "SERVER2.REALM3").
+
+-define(SERVICES, [?CLIENT,
+ ?RELAY1, ?RELAY2,
+ ?SERVER1, ?SERVER2, ?SERVER3, ?SERVER4]).
+
+-define(DICT_COMMON, ?DIAMETER_DICT_COMMON).
+-define(DICT_RELAY, ?DIAMETER_DICT_RELAY).
+
+-define(APP_ALIAS, the_app).
+-define(APP_ID, ?DICT_COMMON:id()).
+
+%% Config for diameter:start_service/2.
+-define(SERVICE(Host, Dict),
+ [{'Origin-Host', Host},
+ {'Origin-Realm', realm(Host)},
+ {'Host-IP-Address', [?ADDR]},
+ {'Vendor-Id', 12345},
+ {'Product-Name', "OTP/diameter"},
+ {'Acct-Application-Id', [Dict:id()]},
+ {application, [{alias, ?APP_ALIAS},
+ {dictionary, Dict},
+ {module, ?MODULE},
+ {answer_errors, callback}]}]).
+
+-define(SUCCESS, 2001).
+-define(LOOP_DETECTED, 3005).
+-define(UNABLE_TO_DELIVER, 3002).
+
+-define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_LOGOUT').
+-define(AUTHORIZE_ONLY, ?'DIAMETER_BASE_RE-AUTH-REQUEST-TYPE_AUTHORIZE_ONLY').
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [start, start_services, connect]
+ ++ tc()
+ ++ [{group, all},
+ disconnect,
+ stop_services,
+ stop].
+
+groups() ->
+ [{all, [parallel], tc()}].
+
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(_, _) ->
+ ok.
+
+%% Traffic cases run when services are started and connections
+%% established.
+tc() ->
+ [send1,
+ send2,
+ send3,
+ send4,
+ send_loop,
+ send_timeout_1,
+ send_timeout_2].
+
+%% ===========================================================================
+%% start/stop testcases
+
+start(_Config) ->
+ ok = diameter:start().
+
+start_services(_Config) ->
+ [S1,S2,S3,S4] = [server(N, ?DICT_COMMON) || N <- [?SERVER1,
+ ?SERVER2,
+ ?SERVER3,
+ ?SERVER4]],
+ [R1,R2] = [server(N, ?DICT_RELAY) || N <- [?RELAY1, ?RELAY2]],
+
+ ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT, ?DICT_COMMON)),
+
+ {save_config, [{?RELAY1, [S1,S2,R2]},
+ {?RELAY2, [S3,S4]},
+ {?CLIENT, [R1,R2]}]}.
+
+connect(Config) ->
+ {_, Conns} = proplists:get_value(saved_config, Config),
+
+ ?util:write_priv(Config,
+ "cfg",
+ lists:flatmap(fun({CN,Ss}) -> connect(CN, Ss) end,
+ Conns)).
+
+disconnect(Config) ->
+ lists:foreach(fun({{CN,CR},{SN,SR}}) -> ?util:disconnect(CN,CR,SN,SR) end,
+ ?util:read_priv(Config, "cfg")).
+
+stop_services(_Config) ->
+ [] = [{H,T} || H <- ?SERVICES,
+ T <- [diameter:stop_service(H)],
+ T /= ok].
+
+stop(_Config) ->
+ ok = diameter:stop().
+
+%% ----------------------------------------
+
+server(Name, Dict) ->
+ ok = diameter:start_service(Name, ?SERVICE(Name, Dict)),
+ {Name, ?util:listen(Name, tcp)}.
+
+connect(Name, Refs) ->
+ [{{Name, ?util:connect(Name, tcp, LRef)}, T} || {_, LRef} = T <- Refs].
+
+%% ===========================================================================
+%% traffic testcases
+
+%% Send an STR intended for a specific server and expect success.
+send1(_Config) ->
+ call(?SERVER1).
+send2(_Config) ->
+ call(?SERVER2).
+send3(_Config) ->
+ call(?SERVER3).
+send4(_Config) ->
+ call(?SERVER4).
+
+%% Send an ASR that loops between the relays and expect the loop to
+%% be detected.
+send_loop(_Config) ->
+ Req = ['ASR', {'Destination-Realm', realm(?SERVER1)},
+ {'Destination-Host', ?SERVER1},
+ {'Auth-Application-Id', ?APP_ID}],
+ #'diameter_base_answer-message'{'Result-Code' = ?LOOP_DETECTED}
+ = call(Req, [{filter, realm}]).
+
+%% Send a RAR that is incorrectly routed and then discarded and expect
+%% different results depending on whether or not we or the relay
+%% timeout first.
+send_timeout_1(_Config) ->
+ #'diameter_base_answer-message'{'Result-Code' = ?UNABLE_TO_DELIVER}
+ = send_timeout(7000).
+send_timeout_2(_Config) ->
+ {error, timeout} = send_timeout(3000).
+
+send_timeout(Tmo) ->
+ Req = ['RAR', {'Destination-Realm', realm(?SERVER1)},
+ {'Destination-Host', ?SERVER1},
+ {'Auth-Application-Id', ?APP_ID},
+ {'Re-Auth-Request-Type', ?AUTHORIZE_ONLY}],
+ call(Req, [{filter, realm}, {timeout, Tmo}]).
+
+%% ===========================================================================
+
+realm(Host) ->
+ tl(lists:dropwhile(fun(C) -> C /= $. end, Host)).
+
+call(Server) ->
+ Realm = realm(Server),
+ Req = ['STR', {'Destination-Realm', Realm},
+ {'Destination-Host', [Server]},
+ {'Termination-Cause', ?LOGOUT},
+ {'Auth-Application-Id', ?APP_ID}],
+ #diameter_base_STA{'Result-Code' = ?SUCCESS,
+ 'Origin-Host' = Server,
+ 'Origin-Realm' = Realm}
+ = call(Req, [{filter, realm}]).
+
+call(Req, Opts) ->
+ diameter:call(?CLIENT, ?APP_ALIAS, Req, Opts).
+
+set([H|T], Vs) ->
+ [H | Vs ++ T].
+
+%% ===========================================================================
+%% diameter callbacks
+
+%% peer_up/3
+
+peer_up(_SvcName, _Peer, State) ->
+ State.
+
+%% peer_down/3
+
+peer_down(_SvcName, _Peer, State) ->
+ State.
+
+%% pick_peer/4
+
+pick_peer([Peer | _], _, Svc, _State)
+ when Svc == ?RELAY1;
+ Svc == ?RELAY2;
+ Svc == ?CLIENT ->
+ {ok, Peer}.
+
+%% prepare_request/3
+
+prepare_request(Pkt, Svc, _Peer)
+ when Svc == ?RELAY1;
+ Svc == ?RELAY2 ->
+ {send, Pkt};
+
+prepare_request(Pkt, ?CLIENT, {_Ref, Caps}) ->
+ {send, prepare(Pkt, Caps)}.
+
+prepare(#diameter_packet{msg = Req}, Caps) ->
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}
+ = Caps,
+ set(Req, [{'Session-Id', diameter:session_id(OH)},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR}]).
+
+%% prepare_retransmit/3
+
+prepare_retransmit(_Pkt, false, _Peer) ->
+ discard.
+
+%% handle_answer/4
+
+%% A relay must return Pkt.
+handle_answer(Pkt, _Req, Svc, _Peer)
+ when Svc == ?RELAY1;
+ Svc == ?RELAY2 ->
+ Pkt;
+
+handle_answer(Pkt, _Req, ?CLIENT, _Peer) ->
+ #diameter_packet{msg = Rec, errors = []} = Pkt,
+ Rec.
+
+%% handle_error/4
+
+handle_error(Reason, _Req, _Svc, _Peer) ->
+ {error, Reason}.
+
+%% handle_request/3
+
+handle_request(Pkt, OH, {_Ref, #diameter_caps{origin_host = {OH,_}} = Caps})
+ when OH /= ?CLIENT ->
+ request(Pkt, Caps).
+
+%% RELAY1 routes any ASR or RAR to RELAY2 ...
+request(#diameter_packet{header = #diameter_header{cmd_code = C}},
+ #diameter_caps{origin_host = {?RELAY1, _}})
+ when C == 274; %% ASR
+ C == 258 -> %% RAR
+ {relay, [{filter, {realm, realm(?RELAY2)}}]};
+
+%% ... which in turn routes it back. Expect diameter to either answer
+%% either with DIAMETER_LOOP_DETECTED/DIAMETER_UNABLE_TO_COMPLY.
+request(#diameter_packet{header = #diameter_header{cmd_code = 274}},
+ #diameter_caps{origin_host = {?RELAY2, _}}) ->
+ {relay, [{filter, {host, ?RELAY1}}]};
+request(#diameter_packet{header = #diameter_header{cmd_code = 258}},
+ #diameter_caps{origin_host = {?RELAY2, _}}) ->
+ discard;
+
+%% Other request to a relay: send on to one of the servers in the
+%% same realm.
+request(_Pkt, #diameter_caps{origin_host = {OH, _}})
+ when OH == ?RELAY1;
+ OH == ?RELAY2 ->
+ {relay, [{filter, {all, [host, realm]}}]};
+
+%% Request received by a server: answer.
+request(#diameter_packet{msg = #diameter_base_STR{'Session-Id' = SId,
+ 'Origin-Host' = Host,
+ 'Origin-Realm' = Realm,
+ 'Route-Record' = Route}},
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}) ->
+ %% The request should have the Origin-Host/Realm of the original
+ %% sender.
+ R = realm(?CLIENT),
+ {?CLIENT, R} = {Host, Realm},
+ %% A relay appends the identity of the peer that a request was
+ %% received from to the Route-Record avp.
+ [?CLIENT] = Route,
+ {reply, #diameter_base_STA{'Result-Code' = ?SUCCESS,
+ 'Session-Id' = SId,
+ 'Origin-Host' = OH,
+ 'Origin-Realm' = OR}}.
diff --git a/lib/diameter/test/diameter_stats_SUITE.erl b/lib/diameter/test/diameter_stats_SUITE.erl
new file mode 100644
index 0000000000..e50a0050a6
--- /dev/null
+++ b/lib/diameter/test/diameter_stats_SUITE.erl
@@ -0,0 +1,92 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of the server implemented by diameter_stats.erl.
+%%
+
+-module(diameter_stats_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2,
+ init_per_suite/1,
+ end_per_suite/1]).
+
+%% testcases
+-export([an/1,
+ twa/1]).
+
+-define(stat, diameter_stats).
+-define(util, diameter_util).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [{group, all} | tc()].
+
+groups() ->
+ [{all, [parallel], tc()}].
+
+tc() ->
+ [an,
+ twa].
+
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(_, _) ->
+ ok.
+
+init_per_suite(Config) ->
+ ok = diameter:start(),
+ Config.
+
+end_per_suite(_Config) ->
+ ok = diameter:stop().
+
+%% ===========================================================================
+
+an(_) ->
+ Ref = {'_', make_ref()},
+ true = ?stat:reg(Ref),
+ true = ?stat:reg(Ref), %% duplicate
+ ok = ?stat:incr(x),
+ ok = ?stat:incr(x, Ref),
+ ok = ?stat:incr(y, 2),
+ ok = ?stat:incr(y, Ref),
+ %% Flushing a pid flushes even stats on the registered reference.
+ [{x,2},{y,3}] = lists:sort(?stat:flush()),
+ [] = ?stat:flush(Ref),
+ [] = ?stat:flush().
+
+twa(_) ->
+ Ref = make_ref(),
+ ok = ?stat:incr(x, 8),
+ ok = ?stat:incr(x, Ref, 7),
+ %% Flushing a reference doesn't affect registered pids.
+ [{x,7}] = ?stat:flush(Ref),
+ [] = ?stat:flush(Ref),
+ [{x,8}] = ?stat:flush(),
+ [] = ?stat:flush().
diff --git a/lib/diameter/test/diameter_sync_SUITE.erl b/lib/diameter/test/diameter_sync_SUITE.erl
new file mode 100644
index 0000000000..84f77b6066
--- /dev/null
+++ b/lib/diameter/test/diameter_sync_SUITE.erl
@@ -0,0 +1,139 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of the server implemented by diameter_sync.erl.
+%%
+
+-module(diameter_sync_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2,
+ init_per_suite/1,
+ end_per_suite/1]).
+
+%% testcases
+-export([call/1,
+ cast/1,
+ timeout/1,
+ flush/1]).
+
+-define(sync, diameter_sync).
+-define(util, diameter_util).
+
+-define(TIMEOUT, infinity).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [{group, all} | tc()].
+
+groups() ->
+ [{all, [parallel], tc()}].
+
+tc() ->
+ [call,
+ cast,
+ timeout,
+ flush].
+
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(_, _) ->
+ ok.
+
+init_per_suite(Config) ->
+ ok = diameter:start(),
+ Config.
+
+end_per_suite(_Config) ->
+ ok = diameter:stop().
+
+%% ===========================================================================
+
+call(_) ->
+ Ref = make_ref(),
+ Q = {q, Ref},
+ F = fun() -> Ref end,
+ Ref = ?sync:call(Q, F, infinity, ?TIMEOUT),
+ Ref = ?sync:call(Q, F, 0, infinity),
+ Ref = call(Q, F),
+ Ref = call(Q, {fun(_) -> Ref end, x}),
+ timeout = call(Q, fun() -> exit(unexpected) end),
+ {_,_,_} = call(Q, {erlang, now, []}),
+ {_,_,_} = call(Q, [fun erlang:now/0]).
+
+cast(_) ->
+ Ref = make_ref(),
+ Q = {q, Ref},
+ false = ?sync:carp(Q),
+ [] = ?sync:pids(Q),
+ %% Queue a request that blocks until we send it Ref and another
+ %% that exits with Ref.
+ ok = cast(Q, fun() -> receive Ref -> ok end end),
+ ok = cast(Q, fun() -> exit(Ref) end),
+ [_,Pid] = ?sync:pids(Q),
+ %% Ensure some expected truths ...
+ 2 = ?sync:pending(Q),
+ true = 2 =< ?sync:pending(),
+ true = lists:member(Q, ?sync:queues()),
+ %% ... and that the max number of requests is respected.
+ rejected = ?sync:call(Q, {erlang, now, []}, 1, ?TIMEOUT),
+ rejected = ?sync:cast(Q, {erlang, now, []}, 1, ?TIMEOUT),
+ %% Monitor on the identifiable request and see that exits when we
+ %% let the blocking request finish.
+ MRef = erlang:monitor(process, Pid),
+ {value, P} = ?sync:carp(Q),
+ P ! Ref,
+ Ref = receive
+ {'DOWN', MRef, process, _, Reason} ->
+ Reason
+ after ?TIMEOUT ->
+ false
+ end.
+
+timeout(_) ->
+ Q = make_ref(),
+ ok = ?sync:cast(Q, {timer, sleep, [2000]}, infinity, 2000),
+ timeout = ?sync:call(Q, fun() -> ok end, infinity, 1000).
+
+flush(_) ->
+ Q = make_ref(),
+ F = {timer, sleep, [2000]},
+ ok = cast(Q, F),
+ ok = cast(Q, F),
+ 1 = ?sync:flush(Q).
+
+%% ===========================================================================
+
+call(Q, Req) ->
+ sync(call, Q, Req).
+
+cast(Q, Req) ->
+ sync(cast, Q, Req).
+
+sync(F, Q, Req) ->
+ ?sync:F(Q, Req, infinity, infinity).
diff --git a/lib/diameter/test/diameter_tls_SUITE.erl b/lib/diameter/test/diameter_tls_SUITE.erl
new file mode 100644
index 0000000000..99f92ca0e0
--- /dev/null
+++ b/lib/diameter/test/diameter_tls_SUITE.erl
@@ -0,0 +1,411 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of traffic between six Diameter nodes connected as follows.
+%%
+%% ---- SERVER.REALM1 (TLS after capabilities exchange)
+%% /
+%% / ---- SERVER.REALM2 (ditto)
+%% | /
+%% CLIENT.REALM0 ----- SERVER.REALM3 (no security)
+%% | \
+%% \ ---- SERVER.REALM4 (TLS at connection establishment)
+%% \
+%% ---- SERVER.REALM5 (ditto)
+%%
+
+-module(diameter_tls_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2,
+ init_per_suite/1,
+ end_per_suite/1]).
+
+%% testcases
+-export([start_ssl/1,
+ start_diameter/1,
+ make_certs/1, make_certs/0,
+ start_services/1,
+ add_transports/1,
+ send1/1,
+ send2/1,
+ send3/1,
+ send4/1,
+ send5/1,
+ remove_transports/1,
+ stop_services/1,
+ stop_diameter/1,
+ stop_ssl/1]).
+
+%% diameter callbacks
+-export([peer_up/3,
+ peer_down/3,
+ pick_peer/4,
+ prepare_request/3,
+ prepare_retransmit/3,
+ handle_answer/4,
+ handle_error/4,
+ handle_request/3]).
+
+-ifdef(DIAMETER_CT).
+-include("diameter_gen_base_rfc3588.hrl").
+-else.
+-include_lib("diameter/include/diameter_gen_base_rfc3588.hrl").
+-endif.
+
+-include_lib("diameter/include/diameter.hrl").
+-include("diameter_ct.hrl").
+
+%% ===========================================================================
+
+-define(util, diameter_util).
+
+-define(ADDR, {127,0,0,1}).
+
+-define(CLIENT, "CLIENT.REALM0").
+-define(SERVER1, "SERVER.REALM1").
+-define(SERVER2, "SERVER.REALM2").
+-define(SERVER3, "SERVER.REALM3").
+-define(SERVER4, "SERVER.REALM4").
+-define(SERVER5, "SERVER.REALM5").
+
+-define(SERVERS, [?SERVER1, ?SERVER2, ?SERVER3, ?SERVER4, ?SERVER5]).
+
+-define(DICT_COMMON, ?DIAMETER_DICT_COMMON).
+
+-define(APP_ALIAS, the_app).
+-define(APP_ID, ?DICT_COMMON:id()).
+
+-define(NO_INBAND_SECURITY, 0).
+-define(TLS, 1).
+
+%% Config for diameter:start_service/2.
+-define(SERVICE(Host, Dict),
+ [{'Origin-Host', Host},
+ {'Origin-Realm', realm(Host)},
+ {'Host-IP-Address', [?ADDR]},
+ {'Vendor-Id', 12345},
+ {'Product-Name', "OTP/diameter"},
+ {'Inband-Security-Id', [?NO_INBAND_SECURITY]},
+ {'Auth-Application-Id', [Dict:id()]},
+ {application, [{alias, ?APP_ALIAS},
+ {dictionary, Dict},
+ {module, ?MODULE},
+ {answer_errors, callback}]}]).
+
+%% Config for diameter:add_transport/2. In the listening case, listen
+%% on a free port that we then lookup using the implementation detail
+%% that diameter_tcp registers the port with diameter_reg.
+-define(CONNECT(PortNr, Caps, Opts),
+ {connect, [{transport_module, diameter_tcp},
+ {transport_config, [{raddr, ?ADDR},
+ {rport, PortNr},
+ {ip, ?ADDR},
+ {port, 0}
+ | Opts]},
+ {capabilities, Caps}]}).
+-define(LISTEN(Caps, Opts),
+ {listen, [{transport_module, diameter_tcp},
+ {transport_config, [{ip, ?ADDR}, {port, 0} | Opts]},
+ {capabilities, Caps}]}).
+
+-define(SUCCESS, 2001).
+-define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_LOGOUT').
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [start_ssl,
+ start_diameter,
+ make_certs,
+ start_services,
+ add_transports]
+ ++ [{group, N} || {N, _, _} <- groups()]
+ ++ [remove_transports, stop_services, stop_diameter, stop_ssl].
+
+groups() ->
+ Ts = tc(),
+ [{all, [], Ts},
+ {p, [parallel], Ts}].
+
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(_, _) ->
+ ok.
+
+init_per_suite(Config) ->
+ case os:find_executable("openssl") of
+ false ->
+ {skip, no_openssl};
+ _ ->
+ Config
+ end.
+
+end_per_suite(_Config) ->
+ ok.
+
+%% Testcases to run when services are started and connections
+%% established.
+tc() ->
+ [send1,
+ send2,
+ send3,
+ send4,
+ send5].
+
+%% ===========================================================================
+%% testcases
+
+start_ssl(_Config) ->
+ ok = ssl:start().
+
+start_diameter(_Config) ->
+ ok = diameter:start().
+
+make_certs() ->
+ [{timetrap, {seconds, 30}}].
+
+make_certs(Config) ->
+ Dir = proplists:get_value(priv_dir, Config),
+
+ [] = ?util:run([[fun make_cert/2, Dir, B] || B <- ["server1",
+ "server2",
+ "server4",
+ "server5",
+ "client"]]).
+
+start_services(Config) ->
+ Dir = proplists:get_value(priv_dir, Config),
+ Servers = [server(S, sopts(S, Dir)) || S <- ?SERVERS],
+
+ ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT, ?DICT_COMMON)),
+
+ {save_config, [Dir | Servers]}.
+
+add_transports(Config) ->
+ {_, [Dir | Servers]} = proplists:get_value(saved_config, Config),
+
+ true = diameter:subscribe(?CLIENT),
+
+ Opts = ssl_options(Dir, "client"),
+ Connections = [connect(?CLIENT, S, copts(N, Opts))
+ || {S,N} <- lists:zip(Servers, ?SERVERS)],
+
+ ?util:write_priv(Config, "cfg", lists:zip(Servers, Connections)).
+
+
+%% Remove the client transports and expect the corresponding server
+%% transport to go down.
+remove_transports(Config) ->
+ Ts = ?util:read_priv(Config, "cfg"),
+ [] = [T || S <- ?SERVERS, T <- [diameter:subscribe(S)], T /= true],
+ lists:map(fun disconnect/1, Ts).
+
+stop_services(_Config) ->
+ [] = [{H,T} || H <- [?CLIENT | ?SERVERS],
+ T <- [diameter:stop_service(H)],
+ T /= ok].
+
+stop_diameter(_Config) ->
+ ok = diameter:stop().
+
+stop_ssl(_Config) ->
+ ok = ssl:stop().
+
+%% Send an STR intended for a specific server and expect success.
+send1(_Config) ->
+ call(?SERVER1).
+send2(_Config) ->
+ call(?SERVER2).
+send3(_Config) ->
+ call(?SERVER3).
+send4(_Config) ->
+ call(?SERVER4).
+send5(_Config) ->
+ call(?SERVER5).
+
+%% ===========================================================================
+%% diameter callbacks
+
+%% peer_up/3
+
+peer_up(_SvcName, _Peer, State) ->
+ State.
+
+%% peer_down/3
+
+peer_down(_SvcName, _Peer, State) ->
+ State.
+
+%% pick_peer/4
+
+pick_peer([Peer], _, ?CLIENT, _State) ->
+ {ok, Peer}.
+
+%% prepare_request/3
+
+prepare_request(#diameter_packet{msg = Req},
+ ?CLIENT,
+ {_Ref, Caps}) ->
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}
+ = Caps,
+
+ {send, set(Req, [{'Session-Id', diameter:session_id(OH)},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR}])}.
+
+%% prepare_retransmit/3
+
+prepare_retransmit(_Pkt, false, _Peer) ->
+ discard.
+
+%% handle_answer/4
+
+handle_answer(Pkt, _Req, ?CLIENT, _Peer) ->
+ #diameter_packet{msg = Rec, errors = []} = Pkt,
+ Rec.
+
+%% handle_error/4
+
+handle_error(Reason, _Req, ?CLIENT, _Peer) ->
+ {error, Reason}.
+
+%% handle_request/3
+
+handle_request(#diameter_packet{msg = #diameter_base_STR{'Session-Id' = SId}},
+ OH,
+ {_Ref, #diameter_caps{origin_host = {OH,_},
+ origin_realm = {OR, _}}})
+ when OH /= ?CLIENT ->
+ {reply, #diameter_base_STA{'Result-Code' = ?SUCCESS,
+ 'Session-Id' = SId,
+ 'Origin-Host' = OH,
+ 'Origin-Realm' = OR}}.
+
+%% ===========================================================================
+%% support functions
+
+call(Server) ->
+ Realm = realm(Server),
+ Req = ['STR', {'Destination-Realm', Realm},
+ {'Termination-Cause', ?LOGOUT},
+ {'Auth-Application-Id', ?APP_ID}],
+ #diameter_base_STA{'Result-Code' = ?SUCCESS,
+ 'Origin-Host' = Server,
+ 'Origin-Realm' = Realm}
+ = call(Req, [{filter, realm}]).
+
+call(Req, Opts) ->
+ diameter:call(?CLIENT, ?APP_ALIAS, Req, Opts).
+
+set([H|T], Vs) ->
+ [H | Vs ++ T].
+
+disconnect({{LRef, _PortNr}, CRef}) ->
+ ok = diameter:remove_transport(?CLIENT, CRef),
+ ok = receive #diameter_event{info = {down, LRef, _, _}} -> ok
+ after 2000 -> false
+ end.
+
+realm(Host) ->
+ tl(lists:dropwhile(fun(C) -> C /= $. end, Host)).
+
+inband_security(Ids) ->
+ [{'Inband-Security-Id', Ids}].
+
+ssl_options(Dir, Base) ->
+ Root = filename:join([Dir, Base]),
+ [{ssl_options, [{certfile, Root ++ "_ca.pem"},
+ {keyfile, Root ++ "_key.pem"}]}].
+
+make_cert(Dir, Base) ->
+ make_cert(Dir, Base ++ "_key.pem", Base ++ "_ca.pem").
+
+make_cert(Dir, Keyfile, Certfile) ->
+ [K,C] = Paths = [filename:join([Dir, F]) || F <- [Keyfile, Certfile]],
+
+ KCmd = join(["openssl genrsa -out", K, "2048"]),
+ CCmd = join(["openssl req -new -x509 -key", K, "-out", C, "-days 7",
+ "-subj /C=SE/ST=./L=Stockholm/CN=www.erlang.org"]),
+
+ %% Hope for the best and only check that files are written.
+ os:cmd(KCmd),
+ os:cmd(CCmd),
+
+ [_,_] = [T || P <- Paths, {ok, T} <- [file:read_file_info(P)]],
+
+ {K,C}.
+
+join(Strs) ->
+ string:join(Strs, " ").
+
+%% server/2
+
+server(Host, {Caps, Opts}) ->
+ ok = diameter:start_service(Host, ?SERVICE(Host, ?DICT_COMMON)),
+ {ok, LRef} = diameter:add_transport(Host, ?LISTEN(Caps, Opts)),
+ {LRef, hd([_] = ?util:lport(tcp, LRef, 20))}.
+
+sopts(?SERVER1, Dir) ->
+ {inband_security([?TLS]),
+ ssl_options(Dir, "server1")};
+sopts(?SERVER2, Dir) ->
+ {inband_security([?NO_INBAND_SECURITY, ?TLS]),
+ ssl_options(Dir, "server2")};
+sopts(?SERVER3, _) ->
+ {[], []};
+sopts(?SERVER4, Dir) ->
+ {[], ssl(ssl_options(Dir, "server4"))};
+sopts(?SERVER5, Dir) ->
+ {[], ssl(ssl_options(Dir, "server5"))}.
+
+ssl([{ssl_options = T, Opts}]) ->
+ [{T, true} | Opts].
+
+%% connect/3
+
+connect(Host, {_LRef, PortNr}, {Caps, Opts}) ->
+ {ok, Ref} = diameter:add_transport(Host, ?CONNECT(PortNr, Caps, Opts)),
+ ok = receive
+ #diameter_event{service = Host,
+ info = {up, Ref, _, _, #diameter_packet{}}} ->
+ ok
+ after 2000 ->
+ false
+ end,
+ Ref.
+
+copts(S, Opts)
+ when S == ?SERVER1;
+ S == ?SERVER2;
+ S == ?SERVER3 ->
+ {inband_security([?NO_INBAND_SECURITY, ?TLS]), Opts};
+copts(S, Opts)
+ when S == ?SERVER4;
+ S == ?SERVER5 ->
+ {[], ssl(Opts)}.
diff --git a/lib/diameter/test/diameter_tls_SUITE_data/Makefile.ca b/lib/diameter/test/diameter_tls_SUITE_data/Makefile.ca
new file mode 100644
index 0000000000..3f2645add0
--- /dev/null
+++ b/lib/diameter/test/diameter_tls_SUITE_data/Makefile.ca
@@ -0,0 +1,43 @@
+# -*- makefile -*-
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+
+#
+# Certificates are now generated from the suite itself but the
+# makefile itself is still useful.
+#
+
+KEYS = $(HOSTS:%=%_key.pem)
+CERTS = $(HOSTS:%=%_ca.pem)
+
+all: $(CERTS)
+
+%_ca.pem: %_key.pem
+ openssl req -new -x509 -key $< -out $@ -days 1095 \
+ -subj '/C=SE/ST=./L=Stockholm/CN=www.erlang.org'
+
+%_key.pem:
+ openssl genrsa -out $@ 2048
+
+clean:
+ rm -f $(CERTS)
+
+realclean: clean
+ rm -f $(KEYS)
+
+.PRECIOUS: $(KEYS)
+.PHONY: all clean realclean
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
new file mode 100644
index 0000000000..6704f24532
--- /dev/null
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -0,0 +1,754 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of traffic between two Diameter nodes, one client, one server.
+%%
+
+-module(diameter_traffic_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2,
+ init_per_testcase/2,
+ end_per_testcase/2]).
+
+%% testcases
+-export([start/1,
+ start_services/1,
+ add_transports/1,
+ result_codes/1,
+ send_ok/1,
+ send_arbitrary/1,
+ send_unknown/1,
+ send_unknown_mandatory/1,
+ send_noreply/1,
+ send_unsupported/1,
+ send_unsupported_app/1,
+ send_error_bit/1,
+ send_unsupported_version/1,
+ send_long/1,
+ send_nopeer/1,
+ send_noapp/1,
+ send_discard/1,
+ send_any_1/1,
+ send_any_2/1,
+ send_all_1/1,
+ send_all_2/1,
+ send_timeout/1,
+ send_error/1,
+ send_detach/1,
+ send_encode_error/1,
+ send_destination_1/1,
+ send_destination_2/1,
+ send_destination_3/1,
+ send_destination_4/1,
+ send_destination_5/1,
+ send_destination_6/1,
+ send_bad_option_1/1,
+ send_bad_option_2/1,
+ send_bad_filter_1/1,
+ send_bad_filter_2/1,
+ send_bad_filter_3/1,
+ send_bad_filter_4/1,
+ send_multiple_filters_1/1,
+ send_multiple_filters_2/1,
+ send_multiple_filters_3/1,
+ send_anything/1,
+ remove_transports/1,
+ stop_services/1,
+ stop/1]).
+
+%% diameter callbacks
+-export([peer_up/3,
+ peer_down/3,
+ pick_peer/5, pick_peer/6,
+ prepare_request/4, prepare_request/5,
+ prepare_retransmit/4,
+ handle_answer/5, handle_answer/6,
+ handle_error/5,
+ handle_request/3]).
+
+-ifdef(DIAMETER_CT).
+-include("diameter_gen_base_rfc3588.hrl").
+-else.
+-include_lib("diameter/include/diameter_gen_base_rfc3588.hrl").
+-endif.
+
+-include_lib("diameter/include/diameter.hrl").
+-include("diameter_ct.hrl").
+
+%% ===========================================================================
+
+-define(util, diameter_util).
+
+-define(ADDR, {127,0,0,1}).
+
+-define(CLIENT, "CLIENT").
+-define(SERVER, "SERVER").
+-define(REALM, "erlang.org").
+-define(HOST(Host, Realm), Host ++ [$.|Realm]).
+
+-define(APP_ALIAS, base).
+-define(EXTRA, an_extra_argument).
+-define(ENCODINGS, [list, record]).
+
+-define(DICT, ?DIAMETER_DICT_COMMON).
+-define(APP_ID, ?DIAMETER_APP_ID_COMMON).
+
+%% Config for diameter:start_service/2.
+-define(SERVICE(Name),
+ [{'Origin-Host', Name ++ "." ++ ?REALM},
+ {'Origin-Realm', ?REALM},
+ {'Host-IP-Address', [?ADDR]},
+ {'Vendor-Id', 12345},
+ {'Product-Name', "OTP/diameter"},
+ {'Acct-Application-Id', [?DIAMETER_APP_ID_COMMON]},
+ {application, [{alias, ?APP_ALIAS},
+ {dictionary, ?DIAMETER_DICT_COMMON},
+ {module, ?MODULE},
+ {answer_errors, callback}]}]).
+
+-define(SUCCESS,
+ ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_SUCCESS').
+-define(COMMAND_UNSUPPORTED,
+ ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_COMMAND_UNSUPPORTED').
+-define(TOO_BUSY,
+ ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_TOO_BUSY').
+-define(APPLICATION_UNSUPPORTED,
+ ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_APPLICATION_UNSUPPORTED').
+-define(INVALID_HDR_BITS,
+ ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_INVALID_HDR_BITS').
+-define(AVP_UNSUPPORTED,
+ ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_AVP_UNSUPPORTED').
+-define(UNSUPPORTED_VERSION,
+ ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_UNSUPPORTED_VERSION').
+-define(REALM_NOT_SERVED,
+ ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_REALM_NOT_SERVED').
+-define(UNABLE_TO_DELIVER,
+ ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_UNABLE_TO_DELIVER').
+
+-define(EVENT_RECORD,
+ ?'DIAMETER_BASE_ACCOUNTING-RECORD-TYPE_EVENT_RECORD').
+-define(AUTHORIZE_ONLY,
+ ?'DIAMETER_BASE_RE-AUTH-REQUEST-TYPE_AUTHORIZE_ONLY').
+-define(AUTHORIZE_AUTHENTICATE,
+ ?'DIAMETER_BASE_RE-AUTH-REQUEST-TYPE_AUTHORIZE_AUTHENTICATE').
+
+-define(LOGOUT,
+ ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_LOGOUT').
+-define(BAD_ANSWER,
+ ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_BAD_ANSWER').
+
+-define(A, list_to_atom).
+-define(L, atom_to_list).
+-define(P(N), ?A("p_" ++ ?L(N))).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 10}}].
+
+all() ->
+ [start, start_services, add_transports, result_codes
+ | [{group, N} || {N, _, _} <- groups()]]
+ ++ [remove_transports, stop_services, stop].
+
+groups() ->
+ Ts = tc(),
+ [{grp(E,P), P, Ts} || E <- ?ENCODINGS, P <- [[], [parallel]]].
+
+grp(E, []) ->
+ E;
+grp(E, [parallel]) ->
+ ?P(E).
+
+init_per_group(Name, Config) ->
+ E = case ?L(Name) of
+ "p_" ++ Rest ->
+ ?A(Rest);
+ _ ->
+ Name
+ end,
+ [{encode, E} | Config].
+
+end_per_group(_, _) ->
+ ok.
+
+init_per_testcase(Name, Config) ->
+ [{testcase, Name} | Config].
+
+end_per_testcase(_, _) ->
+ ok.
+
+%% Testcases to run when services are started and connections
+%% established.
+tc() ->
+ [send_ok,
+ send_arbitrary,
+ send_unknown,
+ send_unknown_mandatory,
+ send_noreply,
+ send_unsupported,
+ send_unsupported_app,
+ send_error_bit,
+ send_unsupported_version,
+ send_long,
+ send_nopeer,
+ send_noapp,
+ send_discard,
+ send_any_1,
+ send_any_2,
+ send_all_1,
+ send_all_2,
+ send_timeout,
+ send_error,
+ send_detach,
+ send_encode_error,
+ send_destination_1,
+ send_destination_2,
+ send_destination_3,
+ send_destination_4,
+ send_destination_5,
+ send_destination_6,
+ send_bad_option_1,
+ send_bad_option_2,
+ send_bad_filter_1,
+ send_bad_filter_2,
+ send_bad_filter_3,
+ send_bad_filter_4,
+ send_multiple_filters_1,
+ send_multiple_filters_2,
+ send_multiple_filters_3,
+ send_anything].
+
+%% ===========================================================================
+%% start/stop testcases
+
+start(_Config) ->
+ ok = diameter:start().
+
+start_services(_Config) ->
+ ok = diameter:start_service(?SERVER, ?SERVICE(?SERVER)),
+ ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT)).
+
+add_transports(Config) ->
+ LRef = ?util:listen(?SERVER, tcp),
+ CRef = ?util:connect(?CLIENT, tcp, LRef),
+ ?util:write_priv(Config, "transport", {LRef, CRef}).
+
+remove_transports(Config) ->
+ {LRef, CRef} = ?util:read_priv(Config, "transport"),
+ ?util:disconnect(?CLIENT, CRef, ?SERVER, LRef).
+
+stop_services(_Config) ->
+ ok = diameter:stop_service(?CLIENT),
+ ok = diameter:stop_service(?SERVER).
+
+stop(_Config) ->
+ ok = diameter:stop().
+
+%% ===========================================================================
+
+%% Ensure that result codes have the expected values.
+result_codes(_Config) ->
+ {2001, 3001, 3002, 3003, 3004, 3007, 3008, 5001, 5011}
+ = {?SUCCESS,
+ ?COMMAND_UNSUPPORTED,
+ ?UNABLE_TO_DELIVER,
+ ?REALM_NOT_SERVED,
+ ?TOO_BUSY,
+ ?APPLICATION_UNSUPPORTED,
+ ?INVALID_HDR_BITS,
+ ?AVP_UNSUPPORTED,
+ ?UNSUPPORTED_VERSION}.
+
+%% Send an ACR and expect success.
+send_ok(Config) ->
+ Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
+ {'Accounting-Record-Number', 1}],
+ #diameter_base_ACA{'Result-Code' = ?SUCCESS}
+ = call(Config, Req).
+
+%% Send an ASR with an arbitrary AVP and expect success and the same
+%% AVP in the reply.
+send_arbitrary(Config) ->
+ Req = ['ASR', {'AVP', [#diameter_avp{name = 'Class', value = "XXX"}]}],
+ #diameter_base_ASA{'Result-Code' = ?SUCCESS,
+ 'AVP' = Avps}
+ = call(Config, Req),
+ [#diameter_avp{name = 'Class',
+ value = "XXX"}]
+ = Avps.
+
+%% Send an unknown AVP (to some client) and check that it comes back.
+send_unknown(Config) ->
+ Req = ['ASR', {'AVP', [#diameter_avp{code = 999,
+ is_mandatory = false,
+ data = <<17>>}]}],
+ #diameter_base_ASA{'Result-Code' = ?SUCCESS,
+ 'AVP' = Avps}
+ = call(Config, Req),
+ [#diameter_avp{code = 999,
+ is_mandatory = false,
+ data = <<17>>}]
+ = Avps.
+
+%% Ditto but set the M flag.
+send_unknown_mandatory(Config) ->
+ Req = ['ASR', {'AVP', [#diameter_avp{code = 999,
+ is_mandatory = true,
+ data = <<17>>}]}],
+ #diameter_base_ASA{'Result-Code' = ?AVP_UNSUPPORTED,
+ 'Failed-AVP' = Failed}
+ = call(Config, Req),
+ [#'diameter_base_Failed-AVP'{'AVP' = Avps}] = Failed,
+ [#diameter_avp{code = 999,
+ is_mandatory = true,
+ data = <<17>>}]
+ = Avps.
+
+%% Send an STR that the server ignores.
+send_noreply(Config) ->
+ Req = ['STR', {'Termination-Cause', ?BAD_ANSWER}],
+ {error, timeout} = call(Config, Req).
+
+%% Send an unsupported command and expect 3001.
+send_unsupported(Config) ->
+ Req = ['STR', {'Termination-Cause', ?BAD_ANSWER}],
+ #'diameter_base_answer-message'{'Result-Code' = ?COMMAND_UNSUPPORTED}
+ = call(Config, Req).
+
+%% Send an unsupported command and expect 3007.
+send_unsupported_app(Config) ->
+ Req = ['STR', {'Termination-Cause', ?BAD_ANSWER}],
+ #'diameter_base_answer-message'{'Result-Code' = ?APPLICATION_UNSUPPORTED}
+ = call(Config, Req).
+
+%% Send a request with the E bit set and expect 3008.
+send_error_bit(Config) ->
+ Req = ['STR', {'Termination-Cause', ?BAD_ANSWER}],
+ #'diameter_base_answer-message'{'Result-Code' = ?INVALID_HDR_BITS}
+ = call(Config, Req).
+
+%% Send a bad version and check that we get 5011.
+send_unsupported_version(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ #diameter_base_STA{'Result-Code' = ?UNSUPPORTED_VERSION}
+ = call(Config, Req).
+
+%% Send something long that will be fragmented by TCP.
+send_long(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT},
+ {'User-Name', [lists:duplicate(1 bsl 20, $X)]}],
+ #diameter_base_STA{'Result-Code' = ?SUCCESS}
+ = call(Config, Req).
+
+%% Send something for which pick_peer finds no suitable peer.
+send_nopeer(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ {error, no_connection} = call(Config, Req, [{extra, [?EXTRA]}]).
+
+%% Send something on an unconfigured application.
+send_noapp(_Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ {error, no_connection} = diameter:call(?CLIENT, unknown_alias, Req).
+
+%% Send something that's discarded by prepare_request.
+send_discard(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ {error, unprepared} = call(Config, Req).
+
+%% Send with a disjunctive filter.
+send_any_1(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ {error, no_connection} = call(Config, Req, [{filter, {any, []}}]).
+send_any_2(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT},
+ {'Destination-Host', [?HOST(?SERVER, "unknown.org")]}],
+ #'diameter_base_answer-message'{'Result-Code' = ?UNABLE_TO_DELIVER}
+ = call(Config, Req, [{filter, {any, [host, realm]}}]).
+
+%% Send with a conjunctive filter.
+send_all_1(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ Realm = lists:foldr(fun(C,A) -> [C,A] end, [], ?REALM),
+ #diameter_base_STA{'Result-Code' = ?SUCCESS}
+ = call(Config, Req, [{filter, {all, [{host, any},
+ {realm, Realm}]}}]).
+send_all_2(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT},
+ {'Destination-Host', [?HOST(?SERVER, "unknown.org")]}],
+ {error, no_connection}
+ = call(Config, Req, [{filter, {all, [host, realm]}}]).
+
+%% Timeout before the server manages an answer.
+send_timeout(Config) ->
+ Req = ['RAR', {'Re-Auth-Request-Type', ?AUTHORIZE_ONLY}],
+ {error, timeout} = call(Config, Req, [{timeout, 1000}]).
+
+%% Explicitly answer with an answer-message and ensure that we
+%% received the Session-Id.
+send_error(Config) ->
+ Req = ['RAR', {'Re-Auth-Request-Type', ?AUTHORIZE_AUTHENTICATE}],
+ #'diameter_base_answer-message'{'Result-Code' = ?TOO_BUSY,
+ 'Session-Id' = SId}
+ = call(Config, Req),
+ undefined /= SId.
+
+%% Send a request with the detached option and receive it as a message
+%% from handle_answer instead.
+send_detach(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ Ref = make_ref(),
+ ok = call(Config, Req, [{extra, [{self(), Ref}]}, detach]),
+ #diameter_packet{msg = Rec, errors = []}
+ = receive {Ref, T} -> T after 2000 -> false end,
+ #diameter_base_STA{'Result-Code' = ?SUCCESS}
+ = Rec.
+
+%% Send a request which can't be encoded and expect {error, encode}.
+send_encode_error(Config) ->
+ {error, encode} = call(Config, ['STR']). %% No Termination-Cause
+
+%% Send with filtering and expect success.
+send_destination_1(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT},
+ {'Destination-Host', [?HOST(?SERVER, ?REALM)]}],
+ #diameter_base_STA{'Result-Code' = ?SUCCESS}
+ = call(Config, Req, [{filter, {all, [host, realm]}}]).
+send_destination_2(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ #diameter_base_STA{'Result-Code' = ?SUCCESS}
+ = call(Config, Req, [{filter, {all, [host, realm]}}]).
+
+%% Send with filtering on and expect failure when specifying an
+%% unknown host or realm.
+send_destination_3(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT},
+ {'Destination-Realm', "unknown.org"}],
+ {error, no_connection}
+ = call(Config, Req, [{filter, {all, [host, realm]}}]).
+send_destination_4(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT},
+ {'Destination-Host', [?HOST(?SERVER, "unknown.org")]}],
+ {error, no_connection}
+ = call(Config, Req, [{filter, {all, [host, realm]}}]).
+
+%% Send without filtering and expect an error answer when specifying
+%% an unknown host or realm.
+send_destination_5(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT},
+ {'Destination-Realm', "unknown.org"}],
+ #'diameter_base_answer-message'{'Result-Code' = ?REALM_NOT_SERVED}
+ = call(Config, Req).
+send_destination_6(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT},
+ {'Destination-Host', [?HOST(?SERVER, "unknown.org")]}],
+ #'diameter_base_answer-message'{'Result-Code' = ?UNABLE_TO_DELIVER}
+ = call(Config, Req).
+
+%% Specify an invalid option and expect failure.
+send_bad_option_1(Config) ->
+ send_bad_option(Config, x).
+send_bad_option_2(Config) ->
+ send_bad_option(Config, {extra, false}).
+
+send_bad_option(Config, Opt) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ try call(Config, Req, [Opt]) of
+ T -> erlang:error({?MODULE, ?LINE, T})
+ catch
+ error: _ -> ok
+ end.
+
+%% Specify an invalid filter and expect no matching peers.
+send_bad_filter_1(Config) ->
+ send_bad_filter(Config, {all, none}).
+send_bad_filter_2(Config) ->
+ send_bad_filter(Config, {host, x}).
+send_bad_filter_3(Config) ->
+ send_bad_filter(Config, {eval, fun() -> true end}).
+send_bad_filter_4(Config) ->
+ send_bad_filter(Config, {eval, {?MODULE, not_exported, []}}).
+
+send_bad_filter(Config, F) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ {error, no_connection} = call(Config, Req, [{filter, F}]).
+
+%% Specify multiple filter options and expect them be conjunctive.
+send_multiple_filters_1(Config) ->
+ Fun = fun(#diameter_caps{}) -> true end,
+ #diameter_base_STA{'Result-Code' = ?SUCCESS}
+ = send_multiple_filters(Config, [host, {eval, Fun}]).
+send_multiple_filters_2(Config) ->
+ E = {erlang, is_tuple, []},
+ {error, no_connection}
+ = send_multiple_filters(Config, [realm, {neg, {eval, E}}]).
+send_multiple_filters_3(Config) ->
+ E1 = [fun(#diameter_caps{}, ok) -> true end, ok],
+ E2 = {erlang, is_tuple, []},
+ E3 = {erlang, is_record, [diameter_caps]},
+ E4 = [{erlang, is_record, []}, diameter_caps],
+ #diameter_base_STA{'Result-Code' = ?SUCCESS}
+ = send_multiple_filters(Config, [{eval, E} || E <- [E1,E2,E3,E4]]).
+
+send_multiple_filters(Config, Fs) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ call(Config, Req, [{filter, F} || F <- Fs]).
+
+%% Ensure that we can pass a request in any form to diameter:call/4,
+%% only the return value from the prepare_request callback being
+%% significant.
+send_anything(Config) ->
+ #diameter_base_STA{'Result-Code' = ?SUCCESS}
+ = call(Config, anything).
+
+%% ===========================================================================
+
+call(Config, Req) ->
+ call(Config, Req, []).
+
+call(Config, Req, Opts) ->
+ Name = proplists:get_value(testcase, Config),
+ Enc = proplists:get_value(encode, Config),
+ diameter:call(?CLIENT,
+ ?APP_ALIAS,
+ msg(Req, Enc),
+ [{extra, [Name]} | Opts]).
+
+msg([_|_] = L, list) ->
+ L;
+msg([H|T], record) ->
+ ?DICT:'#new-'(?DICT:msg2rec(H), T);
+msg(T, _) ->
+ T.
+
+%% Set only values that aren't already.
+set([H|T], Vs) ->
+ [H | Vs ++ T];
+set(Rec, Vs) ->
+ lists:foldl(fun({F,_} = FV, A) -> set(?DICT:'#get-'(F, A), FV, A) end,
+ Rec,
+ Vs).
+
+set(E, FV, Rec)
+ when E == undefined;
+ E == [] ->
+ ?DICT:'#set-'(FV, Rec);
+set(_, _, Rec) ->
+ Rec.
+
+%% ===========================================================================
+%% diameter callbacks
+
+%% peer_up/3
+
+peer_up(_SvcName, _Peer, State) ->
+ State.
+
+%% peer_down/3
+
+peer_down(_SvcName, _Peer, State) ->
+ State.
+
+%% pick_peer/5/6
+
+pick_peer([Peer], _, ?CLIENT, _State, Name)
+ when Name /= send_detach ->
+ {ok, Peer}.
+
+pick_peer([_Peer], _, ?CLIENT, _State, send_nopeer, ?EXTRA) ->
+ false;
+
+pick_peer([Peer], _, ?CLIENT, _State, send_detach, {_,_}) ->
+ {ok, Peer}.
+
+%% prepare_request/4/5
+
+prepare_request(_Pkt, ?CLIENT, {_Ref, _Caps}, send_discard) ->
+ {discard, unprepared};
+
+prepare_request(Pkt, ?CLIENT, {_Ref, Caps}, Name) ->
+ {send, prepare(Pkt, Caps, Name)}.
+
+prepare_request(Pkt, ?CLIENT, {_Ref, Caps}, send_detach, _) ->
+ {send, prepare(Pkt, Caps)}.
+
+prepare(Pkt, Caps, send_unsupported) ->
+ Req = prepare(Pkt, Caps),
+ #diameter_packet{bin = <<H:5/binary, _CmdCode:3/binary, T/binary>>}
+ = E
+ = diameter_codec:encode(?DICT, Pkt#diameter_packet{msg = Req}),
+ E#diameter_packet{bin = <<H/binary, 42:24/integer, T/binary>>};
+
+prepare(Pkt, Caps, send_unsupported_app) ->
+ Req = prepare(Pkt, Caps),
+ #diameter_packet{bin = <<H:8/binary, _ApplId:4/binary, T/binary>>}
+ = E
+ = diameter_codec:encode(?DICT, Pkt#diameter_packet{msg = Req}),
+ E#diameter_packet{bin = <<H/binary, 42:32/integer, T/binary>>};
+
+prepare(Pkt, Caps, send_error_bit) ->
+ #diameter_packet{header = Hdr} = Pkt,
+ Pkt#diameter_packet{header = Hdr#diameter_header{is_error = true},
+ msg = prepare(Pkt, Caps)};
+
+prepare(Pkt, Caps, send_unsupported_version) ->
+ #diameter_packet{header = Hdr} = Pkt,
+ Pkt#diameter_packet{header = Hdr#diameter_header{version = 42},
+ msg = prepare(Pkt, Caps)};
+
+prepare(Pkt, Caps, send_anything) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+ prepare(Pkt#diameter_packet{msg = Req}, Caps);
+
+prepare(Pkt, Caps, _Name) ->
+ prepare(Pkt, Caps).
+
+prepare(#diameter_packet{msg = Req}, Caps)
+ when is_record(Req, diameter_base_ACR);
+ 'ACR' == hd(Req) ->
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, DR}}
+ = Caps,
+
+ set(Req, [{'Session-Id', diameter:session_id(OH)},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Destination-Realm', DR}]);
+
+prepare(#diameter_packet{msg = Req}, Caps)
+ when is_record(Req, diameter_base_ASR);
+ 'ASR' == hd(Req) ->
+ #diameter_caps{origin_host = {OH, DH},
+ origin_realm = {OR, DR}}
+ = Caps,
+ set(Req, [{'Session-Id', diameter:session_id(OH)},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Destination-Host', DH},
+ {'Destination-Realm', DR},
+ {'Auth-Application-Id', ?APP_ID}]);
+
+prepare(#diameter_packet{msg = Req}, Caps)
+ when is_record(Req, diameter_base_STR);
+ 'STR' == hd(Req) ->
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, DR}}
+ = Caps,
+ set(Req, [{'Session-Id', diameter:session_id(OH)},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Destination-Realm', DR},
+ {'Auth-Application-Id', ?APP_ID}]);
+
+prepare(#diameter_packet{msg = Req}, Caps)
+ when is_record(Req, diameter_base_RAR);
+ 'RAR' == hd(Req) ->
+ #diameter_caps{origin_host = {OH, DH},
+ origin_realm = {OR, DR}}
+ = Caps,
+ set(Req, [{'Session-Id', diameter:session_id(OH)},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Destination-Host', DH},
+ {'Destination-Realm', DR},
+ {'Auth-Application-Id', ?APP_ID}]).
+
+%% prepare_retransmit/4
+
+prepare_retransmit(_Pkt, false, _Peer, _Name) ->
+ discard.
+
+%% handle_answer/5/6
+
+handle_answer(Pkt, Req, ?CLIENT, Peer, Name) ->
+ answer(Pkt, Req, Peer, Name).
+
+handle_answer(Pkt, _Req, ?CLIENT, _Peer, send_detach, {Pid, Ref}) ->
+ Pid ! {Ref, Pkt}.
+
+answer(#diameter_packet{msg = Rec, errors = []}, _Req, _Peer, _) ->
+ Rec.
+
+%% handle_error/5
+
+handle_error(Reason, _Req, ?CLIENT, _Peer, _Name) ->
+ {error, Reason}.
+
+%% handle_request/3
+
+%% Note that diameter will set Result-Code and Failed-AVPs if
+%% #diameter_packet.errors is non-null.
+
+handle_request(Pkt, ?SERVER, {_Ref, Caps}) ->
+ request(Pkt, Caps).
+
+request(#diameter_packet{msg
+ = #diameter_base_ACR{'Session-Id' = SId,
+ 'Accounting-Record-Type' = RT,
+ 'Accounting-Record-Number' = RN}},
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}) ->
+ {reply, ['ACA', {'Result-Code', ?SUCCESS},
+ {'Session-Id', SId},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Accounting-Record-Type', RT},
+ {'Accounting-Record-Number', RN}]};
+
+request(#diameter_packet{msg = #diameter_base_ASR{'Session-Id' = SId,
+ 'AVP' = Avps}},
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}) ->
+ {reply, #diameter_base_ASA{'Result-Code' = ?SUCCESS,
+ 'Session-Id' = SId,
+ 'Origin-Host' = OH,
+ 'Origin-Realm' = OR,
+ 'AVP' = Avps}};
+
+request(#diameter_packet{msg = #diameter_base_STR{'Termination-Cause' = T}},
+ _Caps)
+ when T /= ?LOGOUT ->
+ discard;
+
+request(#diameter_packet{msg = #diameter_base_STR{'Destination-Realm'= R}},
+ #diameter_caps{origin_realm = {OR, _}})
+ when R /= undefined, R /= OR ->
+ {protocol_error, ?REALM_NOT_SERVED};
+
+request(#diameter_packet{msg = #diameter_base_STR{'Destination-Host'= [H]}},
+ #diameter_caps{origin_host = {OH, _}})
+ when H /= OH ->
+ {protocol_error, ?UNABLE_TO_DELIVER};
+
+request(#diameter_packet{msg = #diameter_base_STR{'Session-Id' = SId}},
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}) ->
+ {reply, #diameter_base_STA{'Result-Code' = ?SUCCESS,
+ 'Session-Id' = SId,
+ 'Origin-Host' = OH,
+ 'Origin-Realm' = OR}};
+
+request(#diameter_packet{msg = #diameter_base_RAR{}}, _Caps) ->
+ receive after 2000 -> ok end,
+ {protocol_error, ?TOO_BUSY}.
diff --git a/lib/diameter/test/diameter_transport_SUITE.erl b/lib/diameter/test/diameter_transport_SUITE.erl
new file mode 100644
index 0000000000..a9520ef5bd
--- /dev/null
+++ b/lib/diameter/test/diameter_transport_SUITE.erl
@@ -0,0 +1,436 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of diameter_tcp/sctp as implementations of the diameter
+%% transport interface.
+%%
+
+-module(diameter_transport_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2,
+ init_per_suite/1,
+ end_per_suite/1]).
+
+%% testcases
+-export([start/1,
+ tcp_accept/1,
+ tcp_connect/1,
+ sctp_accept/1,
+ sctp_connect/1,
+ stop/1]).
+
+-export([accept/1,
+ connect/1,
+ init/2]).
+
+-include_lib("kernel/include/inet_sctp.hrl").
+-include_lib("diameter/include/diameter.hrl").
+-include("diameter_ct.hrl").
+
+-define(util, diameter_util).
+
+%% Corresponding to diameter_* transport modules.
+-define(TRANSPORTS, [tcp, sctp]).
+
+%% Receive a message.
+-define(RECV(Pat, Ret), receive Pat -> Ret end).
+-define(RECV(Pat), ?RECV(Pat, now())).
+
+%% Or not.
+-define(WAIT(Ms), receive after Ms -> now() end).
+
+%% Sockets are opened on the loopback address.
+-define(ADDR, {127,0,0,1}).
+
+%% diameter_tcp doesn't use anything but host_ip_address, and that
+%% only is a local address isn't configured as at transport start.
+-define(SVC(Addrs), #diameter_service{capabilities
+ = #diameter_caps{host_ip_address
+ = Addrs}}).
+
+%% The term we register after open a listening port with gen_tcp.
+-define(TEST_LISTENER(Ref, PortNr),
+ {?MODULE, listen, Ref, PortNr}).
+
+%% Message over the transport interface.
+-define(TMSG(T), {diameter, T}).
+
+%% Options for gen_tcp/gen_sctp.
+-define(TCP_OPTS, [binary, {active, true}, {packet, 0}]).
+-define(SCTP_OPTS, [binary, {active, true}, {sctp_initmsg, ?SCTP_INIT}]).
+
+%% Request a specific number of streams just because we can.
+-define(SCTP_INIT, #sctp_initmsg{num_ostreams = 5,
+ max_instreams = 5}).
+
+%% Messages from gen_sctp.
+-define(SCTP(Sock, Data), {sctp, Sock, _, _, Data}).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {minutes, 2}}].
+
+all() ->
+ [start | tc()] ++ [{group, all}, stop].
+
+groups() ->
+ [{all, [parallel], tc()}].
+
+tc() ->
+ [tcp_accept,
+ tcp_connect,
+ sctp_accept,
+ sctp_connect].
+
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(_, _) ->
+ ok.
+
+init_per_suite(Config) ->
+ [{sctp, have_sctp()} | Config].
+
+end_per_suite(_Config) ->
+ ok.
+
+%% ===========================================================================
+
+start(_Config) ->
+ ok = diameter:start().
+
+stop(_Config) ->
+ ok = diameter:stop().
+
+%% ===========================================================================
+%% tcp_accept/1
+%% sctp_accept/1
+%%
+%% diameter transport accepting, test code connecting.
+
+tcp_accept(_) ->
+ accept(tcp).
+
+sctp_accept(Config) ->
+ if_sctp(fun accept/1, Config).
+
+%% Start multiple accepting transport processes that are connected to
+%% with an equal number of connecting processes using gen_tcp/sctp
+%% directly.
+
+-define(PEER_COUNT, 8).
+
+accept(Prot) ->
+ T = {Prot, make_ref()},
+ [] = ?util:run(?util:scramble(acc(2*?PEER_COUNT, T, []))).
+
+acc(0, _, Acc) ->
+ Acc;
+acc(N, T, Acc) ->
+ acc(N-1, T, [{?MODULE, [init,
+ element(1 + N rem 2, {accept, gen_connect}),
+ T]}
+ | Acc]).
+
+%% ===========================================================================
+%% tcp_connect/1
+%% sctp_connect/1
+%%
+%% Test code accepting, diameter transport connecting.
+
+tcp_connect(_) ->
+ connect(tcp).
+
+sctp_connect(Config) ->
+ if_sctp(fun connect/1, Config).
+
+connect(Prot) ->
+ T = {Prot, make_ref()},
+ [] = ?util:run([{?MODULE, [init, X, T]} || X <- [gen_accept, connect]]).
+
+%% ===========================================================================
+%% ===========================================================================
+
+%% have_sctp/0
+
+have_sctp() ->
+ try gen_sctp:open() of
+ {ok, Sock} ->
+ gen_sctp:close(Sock),
+ true;
+ {error, eprotonosupport} -> %% fail on any other reason
+ false
+ catch
+ error: badarg ->
+ false
+ end.
+
+%% if_sctp/2
+
+if_sctp(F, Config) ->
+ case proplists:get_value(sctp, Config) of
+ true ->
+ F(sctp);
+ false ->
+ {skip, no_sctp}
+ end.
+
+%% init/2
+
+init(accept, {Prot, Ref}) ->
+ %% Start an accepting transport and receive notification of a
+ %% connection.
+ TPid = start_accept(Prot, Ref),
+
+ %% Receive a message and send it back.
+ <<_:8, Len:24, _/binary>> = Bin = bin(Prot, ?RECV(?TMSG({recv, P}), P)),
+
+ Len = size(Bin),
+ TPid ! ?TMSG({send, Bin}),
+
+ %% Expect the transport process to die as a result of the peer
+ %% closing the connection.
+ MRef = erlang:monitor(process, TPid),
+ ?RECV({'DOWN', MRef, process, _, _});
+
+init(gen_connect, {Prot, Ref}) ->
+ %% Lookup the peer's listening socket.
+ [PortNr] = ?util:lport(Prot, Ref, 20),
+
+ %% Connect, send a message and receive it back.
+ {ok, Sock} = gen_connect(Prot, PortNr, Ref),
+ Bin = make_msg(),
+ ok = gen_send(Prot, Sock, Bin),
+ Bin = gen_recv(Prot, Sock);
+
+init(gen_accept, {Prot, Ref}) ->
+ %% Open a listening socket and publish the port number.
+ {ok, LSock} = gen_listen(Prot),
+ {ok, PortNr} = inet:port(LSock),
+ true = diameter_reg:add_new(?TEST_LISTENER(Ref, PortNr)),
+
+ %% Accept a connection, receive a message and send it back.
+ {ok, Sock} = gen_accept(Prot, LSock),
+ Bin = gen_recv(Prot, Sock),
+ ok = gen_send(Prot, Sock, Bin);
+
+init(connect, {Prot, Ref}) ->
+ %% Lookup the peer's listening socket.
+ [{?TEST_LISTENER(_, PortNr), _}] = match(?TEST_LISTENER(Ref, '_')),
+
+ %% Start a connecting transport and receive notification of
+ %% the connection.
+ TPid = start_connect(Prot, PortNr, Ref),
+
+ %% Send a message and receive it back.
+ Bin = make_msg(),
+ TPid ! ?TMSG({send, Bin}),
+ Bin = bin(Prot, ?RECV(?TMSG({recv, P}), P)),
+
+ %% Expect the transport process to die as a result of the peer
+ %% closing the connection.
+ MRef = erlang:monitor(process, TPid),
+ ?RECV({'DOWN', MRef, process, _, _}).
+
+match(Pat) ->
+ match(Pat, 20).
+
+match(Pat, T) ->
+ L = diameter_reg:match(Pat),
+ if [] /= L orelse 1 == T ->
+ L;
+ true ->
+ ?WAIT(50),
+ match(Pat, T-1)
+ end.
+
+bin(sctp, #diameter_packet{bin = Bin}) ->
+ Bin;
+bin(tcp, Bin) ->
+ Bin.
+
+%% make_msg/0
+%%
+%% A valid Diameter message in as far as diameter_tcp examines it,
+%% the module examining the length in the Diameter header to locate
+%% message boundaries.
+
+make_msg() ->
+ N = 1024,
+ Bin = rand_bytes(4*N),
+ Len = 4*(N+1),
+ <<1:8, Len:24, Bin/binary>>.
+
+%% crypto:rand_bytes/1 isn't available on all platforms (since openssl
+%% isn't) so roll our own.
+rand_bytes(N) ->
+ random:seed(now()),
+ rand_bytes(N, <<>>).
+
+rand_bytes(0, Bin) ->
+ Bin;
+rand_bytes(N, Bin) ->
+ Oct = random:uniform(256) - 1,
+ rand_bytes(N-1, <<Oct, Bin/binary>>).
+
+%% ===========================================================================
+
+%% start_connect/3
+
+start_connect(Prot, PortNr, Ref) ->
+ {ok, TPid, [?ADDR]} = start_connect(Prot,
+ {connect, Ref},
+ ?SVC([]),
+ [{raddr, ?ADDR},
+ {rport, PortNr},
+ {ip, ?ADDR},
+ {port, 0}]),
+ ?RECV(?TMSG({TPid, connected, _})),
+ TPid.
+
+start_connect(sctp, T, Svc, Opts) ->
+ diameter_sctp:start(T, Svc, [{sctp_initmsg, ?SCTP_INIT} | Opts]);
+start_connect(tcp, T, Svc, Opts) ->
+ diameter_tcp:start(T, Svc, Opts).
+
+%% start_accept/2
+%%
+%% Start transports sequentially by having each wait for a message
+%% from a job in a queue before commencing. Only one transport with
+%% a pending accept is started at a time since diameter_sctp currently
+%% assumes (and diameter currently implements) this.
+
+start_accept(Prot, Ref) ->
+ Pid = sync(accept, Ref),
+
+ %% Configure the same port number for transports on the same
+ %% reference.
+ [PortNr | _] = ?util:lport(Prot, Ref) ++ [0],
+ {Mod, Opts} = tmod(Prot),
+
+ try
+ {ok, TPid, [?ADDR]} = Mod:start({accept, Ref},
+ ?SVC([?ADDR]),
+ [{port, PortNr} | Opts]),
+ ?RECV(?TMSG({TPid, connected})),
+ TPid
+ after
+ Pid ! Ref
+ end.
+
+sync(What, Ref) ->
+ ok = diameter_sync:cast({?MODULE, What, Ref},
+ [fun lock/2, Ref, self()],
+ infinity,
+ infinity),
+ receive {start, Ref, Pid} -> Pid end.
+
+lock(Ref, Pid) ->
+ Pid ! {start, Ref, self()},
+ erlang:monitor(process, Pid),
+ Ref = receive T -> T end.
+
+tmod(sctp) ->
+ {diameter_sctp, [{sctp_initmsg, ?SCTP_INIT}]};
+tmod(tcp) ->
+ {diameter_tcp, []}.
+
+%% ===========================================================================
+
+%% gen_connect/3
+
+gen_connect(Prot, PortNr, Ref) ->
+ Pid = sync(connect, Ref),
+
+ %% Stagger connect attempts to avoid the situation that no
+ %% transport process is accepting yet.
+ receive after 250 -> ok end,
+
+ try
+ gen_connect(Prot, PortNr)
+ after
+ Pid ! Ref
+ end.
+
+gen_connect(sctp = P, PortNr) ->
+ {ok, Sock} = Ok = gen_sctp:open([{ip, ?ADDR}, {port, 0} | ?SCTP_OPTS]),
+ ok = gen_sctp:connect_init(Sock, ?ADDR, PortNr, []),
+ Ok = gen_accept(P, Sock);
+gen_connect(tcp, PortNr) ->
+ gen_tcp:connect(?ADDR, PortNr, ?TCP_OPTS).
+
+%% gen_listen/1
+
+gen_listen(sctp) ->
+ {ok, Sock} = gen_sctp:open([{ip, ?ADDR}, {port, 0} | ?SCTP_OPTS]),
+ {gen_sctp:listen(Sock, true), Sock};
+gen_listen(tcp) ->
+ gen_tcp:listen(0, [{ip, ?ADDR} | ?TCP_OPTS]).
+
+%% gen_accept/2
+
+gen_accept(sctp, Sock) ->
+ Assoc = ?RECV(?SCTP(Sock, {_, #sctp_assoc_change{state = comm_up,
+ outbound_streams = O,
+ inbound_streams = I,
+ assoc_id = A}}),
+ {O, I, A}),
+ putr(assoc, Assoc),
+ {ok, Sock};
+gen_accept(tcp, LSock) ->
+ gen_tcp:accept(LSock).
+
+%% gen_send/3
+
+gen_send(sctp, Sock, Bin) ->
+ {OS, _IS, Id} = getr(assoc),
+ {_, _, Us} = now(),
+ gen_sctp:send(Sock, Id, Us rem OS, Bin);
+gen_send(tcp, Sock, Bin) ->
+ gen_tcp:send(Sock, Bin).
+
+%% gen_recv/2
+
+gen_recv(sctp, Sock) ->
+ {_OS, _IS, Id} = getr(assoc),
+ ?RECV(?SCTP(Sock, {[#sctp_sndrcvinfo{assoc_id = Id}], Bin}), Bin);
+gen_recv(tcp, Sock) ->
+ tcp_recv(Sock, <<>>).
+
+tcp_recv(_, <<_:8, Len:24, _/binary>> = Bin)
+ when Len =< size(Bin) ->
+ Bin;
+tcp_recv(Sock, B) ->
+ receive {tcp, Sock, Bin} -> tcp_recv(Sock, <<B/binary, Bin/binary>>) end.
+
+%% putr/2
+
+putr(Key, Val) ->
+ put({?MODULE, Key}, Val).
+
+%% getr/1
+
+getr(Key) ->
+ get({?MODULE, Key}).
diff --git a/lib/diameter/test/diameter_util.erl b/lib/diameter/test/diameter_util.erl
new file mode 100644
index 0000000000..3fe8ea5363
--- /dev/null
+++ b/lib/diameter/test/diameter_util.erl
@@ -0,0 +1,316 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(diameter_util).
+
+%%
+%% Utility functions.
+%%
+
+%% generic
+-export([consult/2,
+ run/1,
+ fold/3,
+ foldl/3,
+ scramble/1]).
+
+%% diameter-specific
+-export([lport/2,
+ lport/3,
+ listen/2,
+ connect/3,
+ disconnect/4]).
+
+%% common_test-specific
+-export([write_priv/3,
+ read_priv/2,
+ map_priv/3]).
+
+-define(L, atom_to_list).
+
+%% ---------------------------------------------------------------------------
+%% consult/2
+%%
+%% Extract info from the app/appup file (presumably) of the named
+%% application.
+
+consult(Name, Suf)
+ when is_atom(Name), is_atom(Suf) ->
+ case code:lib_dir(Name, ebin) of
+ {error = E, Reason} ->
+ {E, {Name, Reason}};
+ Dir ->
+ consult(filename:join([Dir, ?L(Name) ++ "." ++ ?L(Suf)]))
+ end.
+
+consult(Path) ->
+ case file:consult(Path) of
+ {ok, Terms} ->
+ Terms;
+ {error, Reason} ->
+ {error, {Path, Reason}}
+ end.
+%% Name/Path in the return value distinguish the errors and allow for
+%% a useful badmatch.
+
+%% ---------------------------------------------------------------------------
+%% run/1
+%%
+%% Evaluate functions in parallel and return a list of those that
+%% failed to return. The fun takes a boolean (did the function return
+%% or not), the function that was evaluated, the return value or exit
+%% reason and the prevailing accumulator.
+
+run(L) ->
+ fold(fun cons/4, [], L).
+
+cons(true, _, _, Acc) ->
+ Acc;
+cons(false, F, RC, Acc) ->
+ [{F, RC} | Acc].
+
+%% ---------------------------------------------------------------------------
+%% fold/3
+%%
+%% Parallel fold. Results are folded in the order received.
+
+fold(Fun, Acc0, L)
+ when is_function(Fun, 4) ->
+ Ref = make_ref(),
+ %% Spawn a middleman to collect down messages from processes
+ %% spawned for each function so as not to assume that all DOWN
+ %% messages are ours.
+ MRef = run1([fun fold/4, Ref, Fun, Acc0, L], Ref),
+ {Ref, RC} = down(MRef),
+ RC.
+
+fold(Ref, Fun, Acc0, L) ->
+ recv(run(Ref, L), Ref, Fun, Acc0).
+
+run(Ref, L) ->
+ [{run1(F, Ref), F} || F <- L].
+
+run1(F, Ref) ->
+ {_, MRef} = spawn_monitor(fun() -> exit({Ref, eval(F)}) end),
+ MRef.
+
+recv([], _, _, Acc) ->
+ Acc;
+recv(L, Ref, Fun, Acc) ->
+ {MRef, R} = down(),
+ {MRef, F} = lists:keyfind(MRef, 1, L),
+ recv(lists:keydelete(MRef, 1, L),
+ Ref,
+ Fun,
+ acc(R, Ref, F, Fun, Acc)).
+
+acc({Ref, RC}, Ref, F, Fun, Acc) ->
+ Fun(true, F, RC, Acc);
+acc(Reason, _, F, Fun, Acc) ->
+ Fun(false, F, Reason, Acc).
+
+down(MRef) ->
+ receive {'DOWN', MRef, process, _, Reason} -> Reason end.
+
+down() ->
+ receive {'DOWN', MRef, process, _, Reason} -> {MRef, Reason} end.
+
+%% ---------------------------------------------------------------------------
+%% foldl/3
+%%
+%% Parallel fold. Results are folded in order of the function list.
+
+foldl(Fun, Acc0, L)
+ when is_function(Fun, 4) ->
+ Ref = make_ref(),
+ recvl(run(Ref, L), Ref, Fun, Acc0).
+
+recvl([], _, _, Acc) ->
+ Acc;
+recvl([{MRef, F} | L], Ref, Fun, Acc) ->
+ R = down(MRef),
+ recvl(L, Ref, Fun, acc(R, Ref, F, Fun, Acc)).
+
+%% ---------------------------------------------------------------------------
+%% scramble/1
+%%
+%% Sort a list into random order.
+
+scramble(L) ->
+ foldl(fun(true, _, S, false) -> S end,
+ false,
+ [[fun s/1, L]]).
+
+s(L) ->
+ random:seed(now()),
+ s([], L).
+
+s(Acc, []) ->
+ Acc;
+s(Acc, L) ->
+ {H, [T|Rest]} = lists:split(random:uniform(length(L)) - 1, L),
+ s([T|Acc], H ++ Rest).
+
+%% ---------------------------------------------------------------------------
+%% eval/1
+%%
+%% Evaluate a function in one of a number of forms.
+
+eval({M,[F|A]})
+ when is_atom(F) ->
+ apply(M,F,A);
+
+eval({M,F,A}) ->
+ apply(M,F,A);
+
+eval([F|A])
+ when is_function(F) ->
+ apply(F,A);
+
+eval(L)
+ when is_list(L) ->
+ run(L);
+
+eval(F)
+ when is_function(F,0) ->
+ F().
+
+%% ---------------------------------------------------------------------------
+%% write_priv/3
+%%
+%% Write an arbitrary term to a named file.
+
+write_priv(Config, Name, Term) ->
+ write(path(Config, Name), Term).
+
+write(Path, Term) ->
+ ok = file:write_file(Path, term_to_binary(Term)).
+
+%% read_priv/2
+%%
+%% Read a term from a file.
+
+read_priv(Config, Name) ->
+ read(path(Config, Name)).
+
+read(Path) ->
+ {ok, Bin} = file:read_file(Path),
+ binary_to_term(Bin).
+
+%% map_priv/3
+%%
+%% Modify a term in a file and return both old and new values.
+
+map_priv(Config, Name, Fun1) ->
+ map(path(Config, Name), Fun1).
+
+map(Path, Fun1) ->
+ T0 = read(Path),
+ T1 = Fun1(T0),
+ write(Path, T1),
+ {T0, T1}.
+
+path(Config, Name)
+ when is_atom(Name) ->
+ path(Config, ?L(Name));
+path(Config, Name) ->
+ Dir = proplists:get_value(priv_dir, Config),
+ filename:join([Dir, Name]).
+
+%% ---------------------------------------------------------------------------
+%% lport/2-3
+%%
+%% Lookup the port number of a tcp/sctp listening transport.
+
+lport(M, Ref) ->
+ lport(M, Ref, 1).
+
+lport(M, Ref, Tries) ->
+ lp(tmod(M), Ref, Tries).
+
+lp(M, Ref, T) ->
+ L = [N || {listen, N, _} <- M:ports(Ref)],
+ if [] /= L orelse T =< 1 ->
+ L;
+ true ->
+ receive after 50 -> ok end,
+ lp(M, Ref, T-1)
+ end.
+
+%% ---------------------------------------------------------------------------
+%% listen/2
+%%
+%% Add a listening transport on the loopback address and a free port.
+
+listen(SvcName, Prot) ->
+ add_transport(SvcName, {listen, opts(Prot, listen)}).
+
+%% ---------------------------------------------------------------------------
+%% connect/3
+%%
+%% Add a connecting transport on and connect to a listening transport
+%% with the specified reference.
+
+connect(Client, Prot, LRef) ->
+ [PortNr] = lport(Prot, LRef, 20),
+ Ref = add_transport(Client, {connect, opts(Prot, PortNr)}),
+ true = diameter:subscribe(Client),
+ ok = receive
+ {diameter_event, Client, {up, Ref, _, _, _}} -> ok
+ after 2000 ->
+ {Client, Prot, PortNr, process_info(self(), messages)}
+ end,
+ Ref.
+
+%% ---------------------------------------------------------------------------
+%% disconnect/4
+%%
+%% Remove the client transport and expect the server transport to go
+%% down.
+
+disconnect(Client, Ref, Server, LRef) ->
+ true = diameter:subscribe(Server),
+ ok = diameter:remove_transport(Client, Ref),
+ ok = receive
+ {diameter_event, Server, {down, LRef, _, _}} -> ok
+ after 2000 ->
+ {Client, Ref, Server, LRef, process_info(self(), messages)}
+ end.
+
+%% ---------------------------------------------------------------------------
+
+-define(ADDR, {127,0,0,1}).
+
+add_transport(SvcName, T) ->
+ {ok, Ref} = diameter:add_transport(SvcName, T),
+ Ref.
+
+tmod(tcp) ->
+ diameter_tcp;
+tmod(sctp) ->
+ diameter_sctp.
+
+opts(Prot, T) ->
+ [{transport_module, tmod(Prot)},
+ {transport_config, [{ip, ?ADDR}, {port, 0} | opts(T)]}].
+
+opts(listen) ->
+ [];
+opts(PortNr) ->
+ [{raddr, ?ADDR}, {rport, PortNr}].
diff --git a/lib/diameter/test/diameter_watchdog_SUITE.erl b/lib/diameter/test/diameter_watchdog_SUITE.erl
new file mode 100644
index 0000000000..dec307529a
--- /dev/null
+++ b/lib/diameter/test/diameter_watchdog_SUITE.erl
@@ -0,0 +1,540 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of the RFC3539 watchdog state machine as implemented by
+%% module diameter_watchdog.
+%%
+
+-module(diameter_watchdog_SUITE).
+
+-export([suite/0,
+ all/0,
+ init_per_suite/1,
+ end_per_suite/1]).
+
+%% testcases
+-export([reopen/1, reopen/4]).
+
+-export([start/3, %% diameter_transport callback
+ id/1, %% jitter callback
+ run/1]).
+
+-include_lib("diameter/include/diameter.hrl").
+-include("diameter_ct.hrl").
+
+%% ===========================================================================
+
+-define(util, diameter_util).
+
+-define(BASE, diameter_gen_base_rfc3588).
+-define(APPL_ID, diameter_gen_base_rfc3588:id()).
+-define(SUCCESS, 2001). %% DIAMETER_SUCCESS
+
+%% Addresses for the local and remote diameter nodes. The values don't
+%% matter since we're faking transport.
+-define(LOCALHOST, {127,0,0,1}).
+-define(REMOTEHOST, {10,0,0,1}).
+
+-define(CAPS, #diameter_caps{origin_host = "node.innan.com",
+ origin_realm = "innan.com",
+ host_ip_address = [?LOCALHOST],
+ vendor_id = 1022,
+ product_name = "remote",
+ auth_application_id = [?APPL_ID]}).
+
+-define(APPL, #diameter_app{alias = ?MODULE,
+ dictionary = ?BASE,
+ module = [?MODULE],
+ init_state = now(),
+ id = ?APPL_ID,
+ mutable = false}).
+
+%% Service record maintained by our faked service process.
+-define(SERVICE, #diameter_service{pid = self(),
+ capabilities = ?CAPS,
+ applications = [?APPL]}).
+
+%% Watchdog timer as a callback.
+-define(WD(T), {?MODULE, id, [T]}).
+
+%% Watchdog timers used by the testcases. Note that the short timeout
+%% with random jitter is excluded since the reopen/1 isn't smart
+%% enough to deal with it: see ONE_WD below.
+-define(WD_TIMERS, [?WD(6000)
+ | [F_(T_) || T_ <- [10000, 20000, 30000],
+ F_ <- [fun(T__) -> T__ end,
+ fun(T__) -> ?WD(T__) end]]]).
+
+%% Transport types.
+-define(TRANSPORTS, [connect, accept]).
+
+%% Message over the transport interface.
+-define(TMSG(T), {diameter, T}).
+
+%% Receive a message within a specified time.
+-define(RECV(T, Timeout),
+ receive T -> now()
+ after Timeout -> ?ERROR({timeout, Timeout})
+ end).
+
+%% Receive a message in a given number of watchdogs, plus or minus
+%% half. Note that the call to now_diff assumes left to right
+%% evaluation order.
+-define(RECV(T, N, WdL, WdH),
+ [?ERROR({received, _Elapsed_, _LowerBound_, N, WdL})
+ || _UpperBound_ <- [(N)*(WdH) + (WdH) div 2],
+ _Elapsed_ <- [now_diff(now(), ?RECV(T, _UpperBound_))],
+ _LowerBound_ <- [(N)*(WdL) - (WdL) div 2],
+ _Elapsed_ =< _LowerBound_*1000]).
+
+%% A timeout that ensures one watchdog. The ensure only one watchdog
+%% requires (Wd + 2000) + 1000 < 2*(Wd - 2000) ==> 7000 < Wd for the
+%% case with random jitter.
+-define(ONE_WD(Wd), jitter(Wd,2000) + 1000).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {minutes, 6}}].%% enough for 11 watchdogs @ 30 sec plus jitter
+
+all() ->
+ [reopen].
+
+init_per_suite(Config) ->
+ ok = diameter:start(),
+ Config.
+
+end_per_suite(_Config) ->
+ ok = diameter:stop().
+
+%% ===========================================================================
+%% # reopen/1
+%% ===========================================================================
+
+%% Test the watchdog state machine for the required failover, failback
+%% and reopen behaviour. Do this by having the testcase replace
+%% diameter_service and start watchdogs, and having this module
+%% implement a transport process that plays the role of the peer
+%% Diameter node.
+
+reopen(_) ->
+ [] = ?util:run([{?MODULE, [run, [reopen, Wd, T, N, M]]}
+ || Wd <- ?WD_TIMERS,
+ T <- ?TRANSPORTS,
+ N <- [0,1,2],
+ M <- ['DWR', 'DWA', other]]).
+
+reopen(Wd, Type, N, What) ->
+ Ref = make_ref(),
+
+ %% The maker of transport processes.
+ TPid = start({N, Wd, What, Ref}),
+
+ %% Act like diameter_service and start the watchdog process, which
+ %% in turn starts a peer_fsm process, which in turn starts a
+ %% transport process by way of start/3. Messages received by the
+ %% testcase are those sent by diameter_watchdog to the service
+ %% process (= process starting the watchdog).
+ WPid1 = watchdog(Type, Ref, TPid, Wd),
+
+ %% Low/high watchdog timeouts.
+ WdL = jitter(Wd, -2000),
+ WdH = jitter(Wd, 2000),
+
+ %% Connection should come up immediately as a consequence of
+ %% starting the watchdog process. In the accepting case this
+ %% results in a new watchdog on a transport waiting for a new
+ %% connection.
+ ?RECV({connection_up, WPid1, _}, 1000),
+
+ WPid2 = case Type of
+ connect ->
+ WPid1;
+ accept ->
+ watchdog(Type, Ref, TPid, Wd)
+ end,
+
+ %% OKAY Timer expires & Failover()
+ %% Pending SetWatchdog() SUSPECT
+ %%
+ %% Since our transport is replying to N DWR's before becoming
+ %% silent, we should go down after N+2 watchdog_timer expirations:
+ %% that is, after the first unanswered DWR. Knowing the min/max
+ %% watchdog timeout values gives the time interval in which the
+ %% down message is expected.
+ ?RECV({connection_down, WPid1}, N+2, WdL, WdH),
+
+ %% SUSPECT Receive DWA Pending = FALSE
+ %% Failback()
+ %% SetWatchdog() OKAY
+ %%
+ %% SUSPECT Receive non-DWA Failback()
+ %% SetWatchdog() OKAY
+ %%
+ %% The transport receives a message before the expiry of another
+ %% watchdog to induce failback.
+ ?RECV({connection_up, WPid1}, WdH),
+
+ %% OKAY Timer expires & SendWatchdog()
+ %% !Pending SetWatchdog()
+ %% Pending = TRUE OKAY
+ %%
+ %% OKAY Timer expires & Failover()
+ %% Pending SetWatchdog() SUSPECT
+ %%
+ %% The transport is still not responding to watchdogs so the
+ %% connection should go back down after either one or two watchdog
+ %% expiries, depending on whether or not DWA restored the connection.
+ F = choose(What == 'DWA', 2, 1),
+ ?RECV({connection_down, WPid1}, F, WdL, WdH),
+
+ %% SUSPECT Timer expires CloseConnection()
+ %% SetWatchdog() DOWN
+ %%
+ %% DOWN Timer expires AttemptOpen()
+ %% SetWatchdog() DOWN
+ %%
+ %% Our transport tells us when the fake connection is
+ %% reestablished, which should happen after another couple of
+ %% watchdog expiries, the first bringing the watchdog to state
+ %% DOWN, the second triggering an attempt to reopen the
+ %% connection.
+ ?RECV({reopen, Ref}, 2, WdL, WdH),
+
+ %% DOWN Connection up NumDWA = 0
+ %% SendWatchdog()
+ %% SetWatchdog()
+ %% Pending = TRUE REOPEN
+ %%
+ %% REOPEN Receive DWA & Pending = FALSE
+ %% NumDWA < 2 NumDWA++ REOPEN
+ %%
+ %% REOPEN Receive DWA & Pending = FALSE
+ %% NumDWA == 2 NumDWA++
+ %% Failback() OKAY
+ %%
+ %% Now the watchdog should require three received DWA's before
+ %% taking the connection back up. The first DWR is sent directly
+ %% after capabilities exchange so it should take no more than two
+ %% watchdog expiries.
+ ?RECV({connection_up, WPid2, _}, 2, WdL, WdH).
+
+%% ===========================================================================
+
+%% Start the fake transport process. From diameter's point of view
+%% it's started when diameter calls start/3. We start it before this
+%% happens since we use the same fake transport each time diameter
+%% calls start/3. The process lives and dies with the test case.
+start(Config) ->
+ Pid = self(),
+ spawn(fun() -> loop(init(Pid, Config)) end).
+
+%% Transport start from diameter. This may be called multiple times
+%% depending on the testcase.
+start({Type, _Ref}, #diameter_service{}, Pid) ->
+ Ref = make_ref(),
+ MRef = erlang:monitor(process, Pid),
+ Pid ! {start, self(), Type, Ref},
+ {Ref, TPid} = receive
+ {Ref, _} = T ->
+ T;
+ {'DOWN', MRef, process, _, _} = T ->
+ T
+ end,
+ erlang:demonitor(MRef, [flush]),
+ {ok, TPid}.
+
+%% id/1
+
+id(T) ->
+ T.
+
+%% ===========================================================================
+
+choose(true, X, _) -> X;
+choose(false, _, X) -> X.
+
+%% run/1
+%%
+%% A more useful badmatch in case of failure.
+
+run([F|A]) ->
+ ok = try
+ apply(?MODULE, F, A),
+ ok
+ catch
+ E:R ->
+ {A, E, R, erlang:get_stacktrace()}
+ end.
+
+%% now_diff/2
+
+now_diff(T1, T2) ->
+ timer:now_diff(T2, T1).
+
+%% jitter/2
+
+jitter(?WD(T), _) ->
+ T;
+jitter(T,D) ->
+ T+D.
+
+%% watchdog/4
+%%
+%% Fake the call from diameter_service. The watchdog process will send
+%% messages to the calling "service" process so our tests are that the
+%% watchdog responds as expected.
+
+watchdog(Type, Ref, TPid, Wd) ->
+ Opts = [{transport_module, ?MODULE},
+ {transport_config, TPid},
+ {watchdog_timer, Wd}],
+ monitor(diameter_watchdog:start({Type, Ref},
+ {false, Opts, false, ?SERVICE})).
+
+monitor(Pid) ->
+ erlang:monitor(process, Pid),
+ Pid.
+
+%% ===========================================================================
+
+%% Transport process implmentation. Fakes reception of messages by
+%% sending fakes to the parent (peer fsm) process that called start/3.
+
+-record(transport,
+ {type, %% connect | accept | manager
+ parent, %% pid() of peer_fsm/ervice process
+ open = false, %% done with capabilities exchange?
+ config}).%% testcase-specific config
+
+%% init/2
+
+%% Testcase starting the manager.
+init(SvcPid, {_,_,_,_} = Config) ->
+ putr(peer, [{'Origin-Host', hostname() ++ ".utan.com"},
+ {'Origin-Realm', "utan.com"}]),
+ #transport{type = manager,
+ parent = monitor(SvcPid),
+ config = Config};
+
+%% Manager starting a transport.
+init(_, {Type, ParentPid, SvcPid, TwinPid, Peer, {N,_,_,_} = Config}) ->
+ putr(peer, Peer),
+ putr(service, SvcPid),
+ putr(count, init(Type, ParentPid, TwinPid, N)),%% number of DWR's to answer
+ #transport{type = Type,
+ parent = monitor(ParentPid),
+ config = Config}.
+
+init(Type, ParentPid, undefined, N) ->
+ connected(ParentPid, Type),
+ N;
+init(_, _, TPid, _) ->
+ monitor(TPid),
+ 3.
+
+%% Generate a unique hostname for the faked peer.
+hostname() ->
+ lists:flatten(io_lib:format("~p-~p-~p", tuple_to_list(now()))).
+
+%% loop/1
+
+loop(S) ->
+ loop(msg(receive T -> T end, S)).
+
+msg(T,S) ->
+ case transition(T,S) of
+ ok ->
+ S;
+ #transport{} = NS ->
+ NS;
+ {stop, Reason} ->
+ x(Reason)
+ end.
+
+x(Reason) ->
+ exit(Reason).
+
+%% transition/2
+
+%% Manager is being asked for a new transport process.
+transition({start, Pid, Type, Ref}, #transport{type = manager,
+ parent = SvcPid,
+ config = Config}) ->
+ TPid = start({Type, Pid, SvcPid, getr(transport), getr(peer), Config}),
+ Pid ! {Ref, TPid},
+ putr(transport, TPid),
+ ok;
+
+%% Peer fsm or testcase process has died.
+transition({'DOWN', _, process, Pid, _} = T, #transport{parent = Pid}) ->
+ {stop, T};
+
+%% Twin transport process has gone down. In the connect case, the
+%% transport isn't started until this happens in the first place so
+%% connect immediately. In the accept case, fake the peer reconnecting
+%% only after another watchdog expiry.
+transition({'DOWN', _, process, _, _}, #transport{type = Type,
+ config = {_, Wd, _, _}}) ->
+ Tmo = case Type of
+ connect ->
+ 0;
+ accept ->
+ ?ONE_WD(Wd)
+ end,
+ erlang:send_after(Tmo, self(), reconnect),
+ ok;
+
+transition(reconnect, #transport{type = Type,
+ parent = Pid,
+ config = {_,_,_,Ref}}) ->
+ getr(service) ! {reopen, Ref},
+ connected(Pid, Type),
+ ok;
+
+%% Peer fsm process is sending CER: fake the peer's CEA.
+transition(?TMSG({send, Bin}), #transport{type = connect,
+ open = false,
+ parent = Pid}
+ = S) ->
+ {Code, Flags, _} = ?BASE:msg_header('CER'),
+ <<_:32, Flags:8, Code:24, _:96, _/binary>> = Bin,
+ Hdr = make_header(Bin),
+ recv(Pid, {Hdr, make_cea()}),
+ S#transport{open = true};
+
+%% Peer fsm process is sending CEA.
+transition(?TMSG({send, Bin}), #transport{type = accept,
+ open = false}
+ = S) ->
+ {Code, Flags, _} = ?BASE:msg_header('CEA'),
+ <<_:32, Flags:8, Code:24, _:96, _/binary>> = Bin,
+ S#transport{open = true};
+
+%% Watchdog is sending DWR or DWA.
+transition(?TMSG({send, Bin}), #transport{open = true} = S) ->
+ {Code, _, _} = ?BASE:msg_header('DWR'),
+ {Code, _, _} = ?BASE:msg_header('DWA'),
+ <<_:32, R:1, 0:7, Code:24, _:96, _/binary>> = Bin,
+ Hdr = make_header(Bin),
+ dwa(1 == R, S, Hdr),
+ ok;
+
+%% We're telling ourselves to fake a received message.
+transition({recv, Msg}, #transport{parent = Pid}) ->
+ recv(Pid, Msg),
+ ok;
+
+%% We're telling ourselves to receive a message to induce failback.
+transition(failback = T, #transport{parent = Pid}) ->
+ recv(Pid, eraser(T)),
+ ok.
+
+make_header(Bin) ->
+ #diameter_header{end_to_end_id = E,
+ hop_by_hop_id = H}
+ = diameter_codec:decode_header(Bin),
+ #diameter_header{end_to_end_id = E,
+ hop_by_hop_id = H}.
+
+recv(Pid, Msg) ->
+ Pid ! ?TMSG({recv, encode(Msg)}).
+
+%% Replace the end-to-end/hop-by-hop identifiers with those from an
+%% incoming request to which we're constructing a reply.
+encode({Hdr, [_|_] = Msg}) ->
+ #diameter_header{hop_by_hop_id = HBH,
+ end_to_end_id = E2E}
+ = Hdr,
+ #diameter_packet{bin = Bin} = diameter_codec:encode(?BASE, Msg),
+ <<H:12/binary, _:64, T/binary>> = Bin,
+ <<H/binary, HBH:32, E2E:32, T/binary>>;
+
+encode([_|_] = Msg) ->
+ #diameter_packet{bin = Bin} = diameter_codec:encode(?BASE, Msg),
+ Bin.
+
+connected(Pid, connect) ->
+ Pid ! ?TMSG({self(), connected, make_ref()});
+connected(Pid, accept) ->
+ Pid ! ?TMSG({self(), connected}),
+ recv(Pid, make_cer()).
+
+make_cer() ->
+ ['CER' | getr(peer)] ++ [{'Host-IP-Address', [?REMOTEHOST]},
+ {'Vendor-Id', 1028},
+ {'Product-Name', "Utan"},
+ {'Auth-Application-Id', [?APPL_ID]}].
+
+make_cea() ->
+ ['CER' | Rest] = make_cer(),
+ ['CEA', {'Result-Code', ?SUCCESS} | Rest].
+
+make_dwr() ->
+ ['DWR' | getr(peer)].
+
+make_dwa() ->
+ ['DWR' | Rest] = make_dwr(),
+ ['DWA', {'Result-Code', ?SUCCESS} | Rest].
+
+dwa(false, _, _) -> %% outgoing was DWA ...
+ ok;
+dwa(true, S, Hdr) -> %% ... or DWR
+ dwa(getr(count), Hdr, S);
+
+%% React to the DWR only after another watchdog expiry. We shouldn't
+%% get another DWR while the answer is pending.
+dwa(0, Hdr, #transport{config = {_, Wd, What, _}}) ->
+ erlang:send_after(?ONE_WD(Wd), self(), failback),
+ putr(failback, make_msg(What, Hdr)),
+ eraser(count);
+
+dwa(undefined, _, _) ->
+ undefined = getr(failback), %% ensure this is after failback
+ ok;
+
+%% Reply with DWA.
+dwa(N, Hdr, #transport{parent = Pid}) ->
+ putr(count, N-1),
+ recv(Pid, {Hdr, make_dwa()}).
+
+%% Answer to received DWR.
+make_msg('DWA', Hdr) ->
+ {Hdr, make_dwa()};
+
+%% DWR from peer.
+make_msg('DWR', _) ->
+ make_dwr();
+
+%% An unexpected answer is discarded after passing through the
+%% watchdog state machine.
+make_msg(other, _) ->
+ ['RAA', {'Session-Id', diameter:session_id("abc")},
+ {'Result-Code', 2001}
+ | getr(peer)].
+
+putr(Key, Val) ->
+ put({?MODULE, Key}, Val).
+
+getr(Key) ->
+ get({?MODULE, Key}).
+
+eraser(Key) ->
+ erase({?MODULE, Key}).
diff --git a/lib/diameter/test/modules.mk b/lib/diameter/test/modules.mk
new file mode 100644
index 0000000000..531aca2799
--- /dev/null
+++ b/lib/diameter/test/modules.mk
@@ -0,0 +1,42 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, 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_SPEC_FILE = diameter.spec
+COVER_SPEC_FILE = diameter.cover
+
+MODULES = \
+ diameter_ct \
+ diameter_util \
+ diameter_enum \
+ diameter_codec_SUITE \
+ diameter_codec_test \
+ diameter_app_SUITE \
+ diameter_dict_SUITE \
+ diameter_reg_SUITE \
+ diameter_sync_SUITE \
+ diameter_stats_SUITE \
+ diameter_watchdog_SUITE \
+ diameter_transport_SUITE \
+ diameter_traffic_SUITE \
+ diameter_relay_SUITE \
+ diameter_tls_SUITE \
+ diameter_failover_SUITE
+
+INTERNAL_HRL_FILES = \
+ diameter_ct.hrl
diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk
new file mode 100644
index 0000000000..c783450c9f
--- /dev/null
+++ b/lib/diameter/vsn.mk
@@ -0,0 +1,25 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, 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 = diameter
+DIAMETER_VSN = 0.10
+PRE_VSN =
+APP_VSN = "$(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN)"
+
+TICKETS =
diff --git a/lib/docbuilder/doc/src/character_entities.xml b/lib/docbuilder/doc/src/character_entities.xml
index e78cf0ebec..0a4ae17fb5 100644
--- a/lib/docbuilder/doc/src/character_entities.xml
+++ b/lib/docbuilder/doc/src/character_entities.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -125,7 +125,7 @@
<cell align="left" valign="middle">not sign</cell>
</row>
<row>
- <cell align="left" valign="middle">&shy;</cell>
+ <cell align="left" valign="middle"></cell> <!-- a space is used instead of &shy; due to bug in fop 1.0 -->
<cell align="left" valign="middle">&amp;shy;</cell>
<cell align="left" valign="middle">soft hyphen</cell>
</row>
diff --git a/lib/docbuilder/doc/src/inline_tags.xml b/lib/docbuilder/doc/src/inline_tags.xml
index 10afbf143f..5bcca54c05 100644
--- a/lib/docbuilder/doc/src/inline_tags.xml
+++ b/lib/docbuilder/doc/src/inline_tags.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2010</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -246,7 +246,10 @@
bibliography file. Example:</p>
<pre>
[...,
- {"erlbook","Concurrent Programming in ERLANG","J. Armstrong, R. Virding, C. Wikstr&ouml;m, M. Williams, Concurrent Programming in ERLANG, Prentice Hall, 1996, ISBN 0-13-508301-X","jocke"},
+ {"erlbook",
+ "Concurrent Programming in ERLANG","J. Armstrong, R. Virding, C. Wikstr&ouml;m, "
+ "M. Williams, Concurrent Programming in ERLANG, Prentice Hall, 1996, ISBN 0-13-508301-X",
+ "jocke"},
...].
</pre>
</section>
diff --git a/lib/docbuilder/doc/src/notes.xml b/lib/docbuilder/doc/src/notes.xml
index 4b8c04f323..95f24ea9ca 100644
--- a/lib/docbuilder/doc/src/notes.xml
+++ b/lib/docbuilder/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2007</year><year>2010</year>
+ <year>2007</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,44 @@
<p>This document describes the changes made to the DocBuilder
application.</p>
+<section><title>Docbuilder 0.9.8.11</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The docbuilder application has been deprecated and will
+ be removed in the R15 release.</p>
+ <p>
+ Own Id: OTP-9509</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Docbuilder 0.9.8.10</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> fop 1.0 crashed when building the docbuilder pdf with
+ the following message
+ "java.lang.IllegalArgumentException: factor &lt; 0; was:
+ -1". <br/> This is a known bug in fop 1.0 (fop bug id:
+ Bug 50524) when there is a word that consist of a single
+ soft hyphen (&amp;shy;). this has been fixed in fop
+ source archive but not it's not in a release yet. It's
+ fixed in our documentation by removing the soft hyphens
+ where this is a problem. </p>
+ <p>
+ Own Id: OTP-9143</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Docbuilder 0.9.8.9</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/docbuilder/src/docb_gen.erl b/lib/docbuilder/src/docb_gen.erl
index 0d8d640324..75494314f1 100644
--- a/lib/docbuilder/src/docb_gen.erl
+++ b/lib/docbuilder/src/docb_gen.erl
@@ -18,6 +18,10 @@
-module(docb_gen).
-export([module/1, module/2, users_guide/1, users_guide/2]).
+-deprecated([{module,1,next_major_release},
+ {module,2,next_major_release},
+ {users_guide,1,next_major_release},
+ {users_guide,2,next_major_release}]).
-record(args, {suffix=".xml",
layout=docb_edoc_xml_cb,
diff --git a/lib/docbuilder/src/docb_main.erl b/lib/docbuilder/src/docb_main.erl
index 4f5f035a65..c20cfc8e67 100644
--- a/lib/docbuilder/src/docb_main.erl
+++ b/lib/docbuilder/src/docb_main.erl
@@ -436,11 +436,11 @@ transform(From, To, Opts, File, Tree) ->
case catch Filter:transform(File, Tree, Opts) of
%% R5C
- {'EXIT', {undef, [{Filter, transform, [File, Tree, Opts]}|_]}}->
+ {'EXIT', {undef, [{Filter, transform, [File, Tree, Opts],_}|_]}}->
%% No transformation defined
finish_transform(Tree, File, Opts, Filter);
- {'EXIT', {undef, {Filter, transform, [File, Tree, Opts]}}} ->
+ {'EXIT', {undef, {Filter, transform, [File, Tree, Opts],_}}} ->
%% No transformation defined
finish_transform(Tree, File, Opts, Filter);
@@ -507,16 +507,16 @@ pp({Tag, Optional, Args}, TagPath, Level, Filter, Opts) ->
Rule_3_result =
case catch Filter:rule(TagPath1, {Level,Optional1,Args},Opts) of
%% R5C
- {'EXIT', {undef, [{_, rule, _}|_]}} -> % No rule/3 defined
+ {'EXIT', {undef, [{_, rule, _, _}|_]}} -> % No rule/3 defined
failed;
- {'EXIT', {undef, {_, rule, _}}} -> % No rule/3 defined
+ {'EXIT', {undef, {_, rule, _, _}}} -> % No rule/3 defined
failed;
%% R5C
- {'EXIT', {function_clause, [{_, rule, _}|_]}} -> % No MATCHING rule/3
+ {'EXIT', {function_clause, [{_, rule, _, _}|_]}} -> % No MATCHING rule/3
failed;
- {'EXIT', {function_clause, {_, rule, _}}} -> % No MATCHING rule/3
+ {'EXIT', {function_clause, {_, rule, _, _}}} -> % No MATCHING rule/3
failed;
{'EXIT', What} ->
diff --git a/lib/docbuilder/src/docb_transform.erl b/lib/docbuilder/src/docb_transform.erl
index 9c7561b07b..736ac92274 100644
--- a/lib/docbuilder/src/docb_transform.erl
+++ b/lib/docbuilder/src/docb_transform.erl
@@ -18,6 +18,8 @@
-module(docb_transform).
-export([file/1, file/2]).
+-deprecated([{file,1,next_major_release},
+ {file,2,next_major_release}]).
%% file(File) -> ok | {error, Reason}
%% file(File, Opts) -> ok | {error, Reason}
diff --git a/lib/docbuilder/src/docb_xml_check.erl b/lib/docbuilder/src/docb_xml_check.erl
index 8ae5cd2eac..5912e22e7b 100644
--- a/lib/docbuilder/src/docb_xml_check.erl
+++ b/lib/docbuilder/src/docb_xml_check.erl
@@ -18,6 +18,7 @@
-module(docb_xml_check).
-export([validate/1]).
+-deprecated([{validate,1,next_major_release}]).
%% validate(File) -> ok | error | {error, badfile}
%% File = string(), file name with or without ".xml" extension
diff --git a/lib/docbuilder/test/Makefile b/lib/docbuilder/test/Makefile
index 96b940033e..53dff193dc 100644
--- a/lib/docbuilder/test/Makefile
+++ b/lib/docbuilder/test/Makefile
@@ -72,7 +72,7 @@ release_spec: opt
release_tests_spec: make_emakefile
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(SPEC_FILES) docb.cover $(EMAKEFILE) $(ERL_FILES) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/docbuilder/vsn.mk b/lib/docbuilder/vsn.mk
index 1209b80d94..6df438a537 100644
--- a/lib/docbuilder/vsn.mk
+++ b/lib/docbuilder/vsn.mk
@@ -1 +1 @@
-DOCB_VSN = 0.9.8.9
+DOCB_VSN = 0.9.8.11
diff --git a/lib/edoc/Makefile b/lib/edoc/Makefile
index e512e390e3..1add669398 100644
--- a/lib/edoc/Makefile
+++ b/lib/edoc/Makefile
@@ -13,8 +13,6 @@
# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
# AB. All Rights Reserved.''
#
-# $Id$
-#
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
diff --git a/lib/edoc/doc/Makefile b/lib/edoc/doc/Makefile
index a0f6484382..c5f68b25d0 100644
--- a/lib/edoc/doc/Makefile
+++ b/lib/edoc/doc/Makefile
@@ -13,8 +13,6 @@
# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
# AB. All Rights Reserved.''
#
-# $Id: Makefile,v 1.1.1.1 2004/10/04 13:53:33 richardc Exp $
-#
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
diff --git a/lib/edoc/doc/overview.edoc b/lib/edoc/doc/overview.edoc
index bd603b7a13..2af425272e 100644
--- a/lib/edoc/doc/overview.edoc
+++ b/lib/edoc/doc/overview.edoc
@@ -3,7 +3,7 @@
EDoc overview page
-@author Richard Carlsson <[email protected]>
+@author Richard Carlsson <[email protected]>
@copyright 2003-2006 Richard Carlsson
@version {@version}
@title Welcome to EDoc
@@ -277,12 +277,12 @@ The following tags can be used before a module declaration:
Examples:
```%% @author Richard Carlsson'''
-```%% @author Richard Carlsson <[email protected]>
+```%% @author Richard Carlsson <[email protected]>
%% [http://user.it.uu.se/~richardc/]'''
-```%% @author <[email protected]>'''
+```%% @author <[email protected]>'''
-```%% @author [email protected] [http://user.it.uu.se/~richardc/]'''
+```%% @author [email protected] [http://user.it.uu.se/~richardc/]'''
</dd>
<dt><a name="mtag-copyright">`@copyright'</a></dt>
@@ -1084,10 +1084,11 @@ Details:
the Erlang programming language.</li>
<li>`boolean()' is the subset of `atom()' consisting
of the atoms `true' and `false'.</li>
- <li>`char()' is a subset of
- `integer()' representing character codes.</li>
+ <li>`char()' is the subset of `integer()' representing
+ Unicode character codes: hex 000000-10FFFF.</li>
<li>`tuple()' is the set of all tuples `{...}'.</li>
- <li>`list(T)' is just an alias for `[T]'.</li>
+ <li>`list(T)' is just an alias for `[T]'; list() is an alias
+ for `list(any())', i.e., `[any()]'.</li>
<li>`nil()' is an alias for the empty list `[]'.</li>
<li>`cons(H,T)' is the list constructor. This is usually not
used directly. It is possible to recursively define `list(T)
diff --git a/lib/edoc/doc/src/Makefile b/lib/edoc/doc/src/Makefile
index 5ee0096f0f..b933094464 100644
--- a/lib/edoc/doc/src/Makefile
+++ b/lib/edoc/doc/src/Makefile
@@ -13,8 +13,6 @@
# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
# AB. All Rights Reserved.''
#
-# $Id$
-#
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
diff --git a/lib/edoc/doc/src/notes.xml b/lib/edoc/doc/src/notes.xml
index c18a126264..b220067bbe 100644
--- a/lib/edoc/doc/src/notes.xml
+++ b/lib/edoc/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2007</year><year>2010</year>
+ <year>2007</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,91 @@
<p>This document describes the changes made to the EDoc
application.</p>
+<section><title>Edoc 0.7.9</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p><c>no_return</c> is a new built-in type. </p>
+ <p>
+ Own Id: OTP-9350</p>
+ </item>
+ <item>
+ <p>
+ synchronized with edoc development version</p>
+ <p>
+ forgot to ensure that xmerl is found in path for
+ include_lib to work</p>
+ <p>
+ fix -spec declaration that doesn't work in R13B04</p>
+ <p>
+ eliminate warnings about unused imports</p>
+ <p>
+ removed CVS-keywords from source files (Thanks to Richard
+ Carlsson )</p>
+ <p>
+ Own Id: OTP-9463</p>
+ </item>
+ <item>
+ <p>
+ Add a proplist() type</p>
+ <p>
+ Recently I was adding specs to an API and found that
+ there is no canonical proplist() type defined. (Thanks to
+ Ryan Zezeski)</p>
+ <p>
+ Own Id: OTP-9499</p>
+ </item>
+ <item>
+ <p>
+ Removed some never-matching clauses reported by dialyzer
+ Fix macro expansion in comments following Erlang types
+ URI-escape bytes as two hex digits always (reported by
+ Alfonso De Gregorio) Updated author e-mail Recognize some
+ more URI schemas in wiki text, in particular https
+ (Thanks to Richard Carlsson)</p>
+ <p>
+ Own Id: OTP-9590</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Edoc 0.7.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix infinite loop for malformed edoc input</p>
+ <p>
+ When processing an edoc comment with ``` in it, if the
+ comment ends without a matching ''' then an infinite loop
+ occurs in the function edoc_wiki:strip_empty_lines/2.
+ This change fixes that by adding a clause to return from
+ the function upon the end of the comment input. This
+ allows an error to be thrown to indicate the problem,
+ which is the same behaviour as leaving either `` or `
+ unmatched. (Thanks to Taylor Venable)</p>
+ <p>
+ Own Id: OTP-9165</p>
+ </item>
+ <item>
+ <p> Bugs concerning the option
+ <c>report_missing_types</c> that was added in EDoc-0.7.7
+ have been corrected: the option was misspelled in the
+ source, and local definitions as well as the function
+ tags <c>@private</c> and <c>@hidden</c> were not handled
+ correctly. (Thanks to Manolis Papadakis.) </p>
+ <p>
+ Own Id: OTP-9301</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Edoc 0.7.7</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/edoc/include/Makefile b/lib/edoc/include/Makefile
index 0533c27567..5b2ad38c9d 100644
--- a/lib/edoc/include/Makefile
+++ b/lib/edoc/include/Makefile
@@ -13,8 +13,6 @@
# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
# AB. All Rights Reserved.''
#
-# $Id$
-#
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
diff --git a/lib/edoc/include/edoc_doclet.hrl b/lib/edoc/include/edoc_doclet.hrl
index a99ff1fbab..60ec7f44e4 100644
--- a/lib/edoc/include/edoc_doclet.hrl
+++ b/lib/edoc/include/edoc_doclet.hrl
@@ -18,7 +18,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% Author contact: [email protected]
+%% Author contact: [email protected]
%% =====================================================================
-define(NO_APP, []).
diff --git a/lib/edoc/priv/edoc_generate.src b/lib/edoc/priv/edoc_generate.src
index e87fdbc902..7ec89207b0 100644
--- a/lib/edoc/priv/edoc_generate.src
+++ b/lib/edoc/priv/edoc_generate.src
@@ -14,9 +14,6 @@
# Portions created by Ericsson are Copyright 1999-2000, Ericsson
# Utvecklings AB. All Rights Reserved.''
#
-# $Id$
-#
-#
#EDOC_DIR=/clearcase/otp/internal_tools/edoc
EDOC_DIR=/home/otp/sgml/edoc-%EDOC_VSN%
diff --git a/lib/edoc/src/Makefile b/lib/edoc/src/Makefile
index 9c5a9d30d1..fcb0b61292 100644
--- a/lib/edoc/src/Makefile
+++ b/lib/edoc/src/Makefile
@@ -23,7 +23,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/edoc-$(VSN)
EBIN = ../ebin
XMERL = ../../xmerl
-ERL_COMPILE_FLAGS += -I../include -I$(XMERL)/include +warn_unused_vars +nowarn_shadow_vars +warn_unused_import +warn_deprecated_guard
+ERL_COMPILE_FLAGS += -pa $(XMERL) -I../include -I$(XMERL)/include +warn_unused_vars +nowarn_shadow_vars +warn_unused_import +warn_deprecated_guard
SOURCES= \
edoc.erl edoc_data.erl edoc_doclet.erl edoc_extract.erl \
diff --git a/lib/edoc/src/edoc.erl b/lib/edoc/src/edoc.erl
index 360f2dbc9e..544465b14a 100644
--- a/lib/edoc/src/edoc.erl
+++ b/lib/edoc/src/edoc.erl
@@ -14,10 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @copyright 2001-2007 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @version {@version}
%% @end
%% =====================================================================
@@ -60,8 +58,6 @@
-compile({no_auto_import,[error/1]}).
--import(edoc_report, [report/2, report/3, error/1, error/3]).
-
-include("edoc.hrl").
@@ -179,8 +175,8 @@ application(App, Options) when is_atom(App) ->
Dir when is_list(Dir) ->
application(App, Dir, Options);
_ ->
- report("cannot find application directory for '~s'.",
- [App]),
+ edoc_report:report("cannot find application directory for '~s'.",
+ [App]),
exit(error)
end.
@@ -663,8 +659,8 @@ read_source(Name, Opts0) ->
check_forms(Forms, Name),
Forms;
{error, R} ->
- error({"error reading file '~s'.",
- [edoc_lib:filename(Name)]}),
+ edoc_report:error({"error reading file '~s'.",
+ [edoc_lib:filename(Name)]}),
exit({error, R})
end.
@@ -688,11 +684,10 @@ check_forms(Fs, Name) ->
error_marker ->
case erl_syntax:error_marker_info(F) of
{L, M, D} ->
- error(L, Name, {format_error, M, D});
-
+ edoc_report:error(L, Name, {format_error, M, D});
Other ->
- report(Name, "unknown error in "
- "source code: ~w.", [Other])
+ edoc_report:report(Name, "unknown error in "
+ "source code: ~w.", [Other])
end,
exit(error);
_ ->
diff --git a/lib/edoc/src/edoc.hrl b/lib/edoc/src/edoc.hrl
index 43657b3b8f..98debba4ab 100644
--- a/lib/edoc/src/edoc.hrl
+++ b/lib/edoc/src/edoc.hrl
@@ -18,7 +18,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% Author contact: [email protected]
+%% Author contact: [email protected]
%% =====================================================================
%% Note: Documentation in this file is included by edoc_extract.erl
@@ -37,7 +37,7 @@
-define(SOURCE_DIR, "src").
-define(EBIN_DIR, "ebin").
-define(EDOC_DIR, "doc").
--define(REPORT_MISSING_TYPE, false).
+-define(REPORT_MISSING_TYPES, false).
-include("edoc_doclet.hrl").
diff --git a/lib/edoc/src/edoc_data.erl b/lib/edoc/src/edoc_data.erl
index 27f43dca5a..aad0b14371 100644
--- a/lib/edoc/src/edoc_data.erl
+++ b/lib/edoc/src/edoc_data.erl
@@ -14,11 +14,9 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @private
%% @copyright 2003 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
diff --git a/lib/edoc/src/edoc_doclet.erl b/lib/edoc/src/edoc_doclet.erl
index 30eef3e63a..385d20e9ae 100644
--- a/lib/edoc/src/edoc_doclet.erl
+++ b/lib/edoc/src/edoc_doclet.erl
@@ -14,10 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @copyright 2003-2006 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
@@ -52,7 +50,7 @@
-define(IMAGE, "erlang.png").
-define(NL, "\n").
--include("xmerl.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
%% Sources is the list of inputs in the order they were found. Packages
%% and Modules are sorted lists of atoms without duplicates. (They
diff --git a/lib/edoc/src/edoc_extract.erl b/lib/edoc/src/edoc_extract.erl
index 5e28762c53..5a79e127f6 100644
--- a/lib/edoc/src/edoc_extract.erl
+++ b/lib/edoc/src/edoc_extract.erl
@@ -14,10 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: $
-%%
%% @copyright 2001-2003 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
@@ -77,7 +75,7 @@ source(Forms, Comments, File, Env, Opts) when is_list(Forms) ->
source(Forms1, Comments, File, Env, Opts);
source(Forms, Comments, File, Env, Opts) ->
Tree = erl_recomment:quick_recomment_forms(Forms, Comments),
- TypeDocs = find_type_docs(Forms, Comments),
+ TypeDocs = find_type_docs(Forms, Comments, Env, File),
source1(Tree, File, Env, Opts, TypeDocs).
%% @spec source(Forms, File::filename(), Env::edoc_env(),
@@ -113,7 +111,7 @@ source(Forms, Comments, File, Env, Opts) ->
source(Forms, File, Env, Opts) when is_list(Forms) ->
source(erl_syntax:form_list(Forms), File, Env, Opts);
source(Tree, File0, Env, Opts) ->
- TypeDocs = find_type_docs(Tree, []),
+ TypeDocs = find_type_docs(Tree, [], Env, File0),
source1(Tree, File0, Env, Opts, TypeDocs).
%% Forms0 and Comments is used for extracting Erlang type documentation.
@@ -238,8 +236,8 @@ file(File, Context, Env, Opts) ->
case file:read_file(File) of
{ok, Bin} ->
{ok, text(binary_to_list(Bin), Context, Env, Opts, File)};
- {error, _R} = Error ->
- Error
+ {error, _} = Error ->
+ Error
end.
@@ -298,8 +296,8 @@ get_module_info(Forms, File) ->
{Name, Vars} = case lists:keyfind(module, 1, L) of
{module, N} when is_atom(N) ->
{N, none};
- {module, {N, _Vs} = NVs} when is_atom(N) ->
- NVs;
+ {module, {N, _}=Mod} when is_atom(N) ->
+ Mod;
_ ->
report(File, "module name missing.", []),
exit(error)
@@ -637,14 +635,17 @@ file_macros(_Context, Env) ->
%% The same thing using -type:
%% -type t() :: t1(). % Some docs of t/0;
%% Further docs of t/0.
-find_type_docs(Forms0, Comments) ->
+find_type_docs(Forms0, Comments, Env, File) ->
Tree = erl_recomment:recomment_forms(Forms0, Comments),
Forms = preprocess_forms(Tree),
- edoc_specs:docs(Forms, fun find_fun/2).
+ Env1 = add_macro_defs(edoc_macros:std_macros(Env), [], Env),
+ F = fun(C, Line) -> find_fun(C, Line, Env1, File) end,
+ edoc_specs:docs(Forms, F).
-find_fun(C0, Line) ->
+find_fun(C0, Line, Env, File) ->
C1 = comment_text(C0),
Text = lists:append([C#comment.text || C <- C1]),
Comm = #comment{line = Line, text = Text},
[Tag | _] = scan_tags([Comm]),
- Tag.
+ [Tag1] = edoc_macros:expand_tags([Tag], Env, File),
+ Tag1.
diff --git a/lib/edoc/src/edoc_layout.erl b/lib/edoc/src/edoc_layout.erl
index 3ec87b7060..951cec121c 100644
--- a/lib/edoc/src/edoc_layout.erl
+++ b/lib/edoc/src/edoc_layout.erl
@@ -14,9 +14,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: $
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2001-2006 Richard Carlsson
%% @see edoc
%% @end
@@ -33,7 +31,7 @@
-import(edoc_report, [report/2]).
--include("xmerl.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
-define(HTML_EXPORT, xmerl_html).
-define(DEFAULT_XML_EXPORT, ?HTML_EXPORT).
@@ -959,12 +957,16 @@ local_label(R) ->
xhtml(Title, CSS, Body) ->
[{html, [?NL,
- {head, [?NL,
- {title, Title},
- ?NL] ++ CSS},
- ?NL,
- {body, [{bgcolor, "white"}], Body},
- ?NL]
+ {head, [?NL,
+ {meta, [{'http-equiv',"Content-Type"},
+ {content, "text/html; charset=ISO-8859-1"}],
+ []},
+ ?NL,
+ {title, Title},
+ ?NL] ++ CSS},
+ ?NL,
+ {body, [{bgcolor, "white"}], Body},
+ ?NL]
},
?NL].
diff --git a/lib/edoc/src/edoc_lib.erl b/lib/edoc/src/edoc_lib.erl
index 585e30a2d2..7fd8358add 100644
--- a/lib/edoc/src/edoc_lib.erl
+++ b/lib/edoc/src/edoc_lib.erl
@@ -14,10 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @copyright 2001-2003 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
@@ -40,7 +38,7 @@
-import(edoc_report, [report/2, warning/2]).
-include("edoc.hrl").
--include("xmerl.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
-define(FILE_BASE, "/").
@@ -405,8 +403,13 @@ escape_uri([C | Cs]) ->
escape_uri([]) ->
[].
-escape_byte(C) ->
- "%" ++ hex_octet(C).
+escape_byte(C) when C >= 0, C =< 255 ->
+ [$%, hex_digit(C bsr 4), hex_digit(C band 15)].
+
+hex_digit(N) when N >= 0, N =< 9 ->
+ N + $0;
+hex_digit(N) when N > 9, N =< 15 ->
+ N + $a - 10.
% utf8([C | Cs]) when C > 16#7f ->
% [((C band 16#c0) bsr 6) + 16#c0, C band 16#3f ++ 16#80 | utf8(Cs)];
@@ -415,13 +418,6 @@ escape_byte(C) ->
% utf8([]) ->
% [].
-hex_octet(N) when N =< 9 ->
- [$0 + N];
-hex_octet(N) when N > 15 ->
- hex_octet(N bsr 4) ++ hex_octet(N band 15);
-hex_octet(N) ->
- [N - 10 + $a].
-
%% Please note that URI are *not* file names. Don't use the stdlib
%% 'filename' module for operations on (any parts of) URI.
@@ -494,7 +490,7 @@ uri_get_file(File0) ->
uri_get_http(URI) ->
%% Try using option full_result=false
case catch {ok, httpc:request(get, {URI,[]}, [],
- [{full_result, false}])} of
+ [{full_result, false}])} of
{'EXIT', _} ->
uri_get_http_r10(URI);
Result ->
diff --git a/lib/edoc/src/edoc_macros.erl b/lib/edoc/src/edoc_macros.erl
index 5b512cb53a..70fb38bf0a 100644
--- a/lib/edoc/src/edoc_macros.erl
+++ b/lib/edoc/src/edoc_macros.erl
@@ -16,7 +16,7 @@
%%
%% @private
%% @copyright 2001-2005 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
diff --git a/lib/edoc/src/edoc_parser.yrl b/lib/edoc/src/edoc_parser.yrl
index 6943f1bdb8..4d6428f75b 100644
--- a/lib/edoc/src/edoc_parser.yrl
+++ b/lib/edoc/src/edoc_parser.yrl
@@ -22,10 +22,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% Author contact: [email protected]
-%%
-%% $Id $
-%%
+%% Author contact: [email protected]
%% =====================================================================
Nonterminals
@@ -258,7 +255,7 @@ throws -> etype where_defs:
%% "%% USA"
%% "%%"
%% "%% @private"
-%% "%% @author Richard Carlsson <[email protected]>"
+%% "%% @author Richard Carlsson <[email protected]>"
%% "%% ===================================================================="
%% .
@@ -362,10 +359,10 @@ parse_spec(S, L) ->
{ok, Spec} ->
Spec;
{error, E} ->
- throw_error(E, L)
+ throw_error({parse_spec, E}, L)
end;
{error, E, _} ->
- throw_error(E, L)
+ throw_error({parse_spec, E}, L)
end.
%% ---------------------------------------------------------------------
@@ -458,8 +455,6 @@ parse_throws(S, L) ->
-spec throw_error(term(), erl_scan:line()) -> no_return().
-throw_error({L, M, D}, _L0) ->
- throw({error,L,{format_error,M,D}});
throw_error({parse_spec, E}, L) ->
throw_error({"specification", E}, L);
throw_error({parse_typedef, E}, L) ->
@@ -471,7 +466,4 @@ throw_error({parse_throws, E}, L) ->
throw_error(parse_param, L) ->
throw({error, L, "missing parameter name"});
throw_error({Where, E}, L) when is_list(Where) ->
- throw({error,L,{"unknown error parsing ~s: ~P.",[Where,E,15]}});
-throw_error(E, L) ->
- %% Just in case.
- throw({error,L,{"unknown parse error: ~P.",[E,15]}}).
+ throw({error,L,{"unknown error parsing ~s: ~P.",[Where,E,15]}}).
diff --git a/lib/edoc/src/edoc_refs.erl b/lib/edoc/src/edoc_refs.erl
index b974cf77c1..1f578a3b83 100644
--- a/lib/edoc/src/edoc_refs.erl
+++ b/lib/edoc/src/edoc_refs.erl
@@ -16,7 +16,7 @@
%%
%% @private
%% @copyright 2003 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @see edoc_parse_ref
%% @end
diff --git a/lib/edoc/src/edoc_report.erl b/lib/edoc/src/edoc_report.erl
index ee54c60c90..9bec08ab97 100644
--- a/lib/edoc/src/edoc_report.erl
+++ b/lib/edoc/src/edoc_report.erl
@@ -14,11 +14,9 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @private
%% @copyright 2001-2003 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
diff --git a/lib/edoc/src/edoc_run.erl b/lib/edoc/src/edoc_run.erl
index 96e5ea4631..48b6137ac1 100644
--- a/lib/edoc/src/edoc_run.erl
+++ b/lib/edoc/src/edoc_run.erl
@@ -14,10 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @copyright 2003 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
diff --git a/lib/edoc/src/edoc_scanner.erl b/lib/edoc/src/edoc_scanner.erl
index 9d2e6f3aed..754fcef643 100644
--- a/lib/edoc/src/edoc_scanner.erl
+++ b/lib/edoc/src/edoc_scanner.erl
@@ -13,12 +13,10 @@
%% AB. Portions created by Ericsson are Copyright 1999, Ericsson
%% Utvecklings AB. All Rights Reserved.''
%%
-%% $Id: $
-%%
%% @private
%% @copyright Richard Carlsson 2001-2003. Portions created by Ericsson
%% are Copyright 1999, Ericsson Utvecklings AB. All Rights Reserved.
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
diff --git a/lib/edoc/src/edoc_specs.erl b/lib/edoc/src/edoc_specs.erl
index 45016ef85a..5acf8ac0d5 100644
--- a/lib/edoc/src/edoc_specs.erl
+++ b/lib/edoc/src/edoc_specs.erl
@@ -1,4 +1,4 @@
-%
+%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
@@ -27,7 +27,6 @@
-include("edoc.hrl").
-include("edoc_types.hrl").
--type proplist() :: [proplists:property()].
-type syntaxTree() :: erl_syntax:syntaxTree().
-define(TOP_TYPE, term).
@@ -87,8 +86,9 @@ dummy_spec(Form) ->
#tag{name = spec, line = element(2, hd(TypeSpecs)),
origin = code, data = S}.
--spec docs(Forms::[syntaxTree()], CommentFun) -> dict() when
- CommentFun :: fun(([syntaxTree()], Line :: term()) -> #tag{}).
+-spec docs(Forms::[syntaxTree()],
+ CommentFun :: fun( ([syntaxTree()], Line :: term()) -> #tag{} ))
+ -> dict().
%% @doc Find comments after -type/-opaque declarations.
%% Postcomments "inside" the type are skipped.
@@ -98,7 +98,7 @@ docs(Forms, CommentFun) ->
-type entry() :: #entry{}.
-type module_info() :: #module{}.
-type entries() :: [entry()].
--spec add_data(Entries::entries(), Options::proplist(),
+-spec add_data(Entries::entries(), Options::proplists:proplist(),
File::file:filename(), Module::module_info()) -> entries().
%% @doc Create tags a la EDoc for Erlang specifications and types.
@@ -305,8 +305,6 @@ d2e({ann_type,_,[V, T0]}) ->
%% layout module.
T = d2e(T0),
?add_t_ann(T, element(3, V));
-d2e({type,_,no_return,[]}) ->
- #t_type{name = #t_name{name = none}};
d2e({remote_type,_,[{atom,_,M},{atom,_,F},Ts0]}) ->
Ts = d2e(Ts0),
typevar_anno(#t_type{name = #t_name{module = M, name = F}, args = Ts}, Ts);
@@ -428,8 +426,8 @@ get_typevars(Ts) ->
expand_records(Entries, TypeDefs, DT, Opts, File, Module) ->
TypeList = [{type_name(T), T, not_seen} || T <- TypeDefs],
true = ets:insert(DT, TypeList),
- Warn = proplists:get_value(report_missing_type, Opts,
- ?REPORT_MISSING_TYPE) =:= true,
+ Warn = proplists:get_value(report_missing_types, Opts,
+ ?REPORT_MISSING_TYPES) =:= true,
P = #parms{tab = DT, warn = Warn, file = File, line = 0},
ExportedTypes = [Name ||
{export_type,Ts} <- Module#module.attributes,
diff --git a/lib/edoc/src/edoc_tags.erl b/lib/edoc/src/edoc_tags.erl
index def39ee34c..2d986988c2 100644
--- a/lib/edoc/src/edoc_tags.erl
+++ b/lib/edoc/src/edoc_tags.erl
@@ -14,11 +14,9 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @private
%% @copyright 2001-2003 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
@@ -331,8 +329,8 @@ parse_typedef(Data, Line, _Env, Where) ->
NAs = length(As),
case edoc_types:is_predefined(T, NAs) of
true ->
- case
- edoc_types:is_new_predefined(T, NAs)
+ case
+ edoc_types:is_new_predefined(T, NAs)
orelse edoc_types:is_predefined_otp_type(T, NAs)
of
false ->
@@ -406,17 +404,20 @@ throw_error(L, D) ->
-record(parms, {tab, warn, file, line}).
-check_types(Entries0, Opts, File) ->
- Entries = edoc_data:hidden_filter(Entries0, Opts),
+check_types(Entries, Opts, File) ->
Tags = edoc_data:get_all_tags(Entries),
+ TypeTags = [Tag || #tag{data = {#t_typedef{},_}}=Tag <- Tags],
+ Entries2 = edoc_data:hidden_filter(Entries, Opts),
+ Tags2 = edoc_data:get_all_tags(Entries2),
+ SpecTags = [Tag || #tag{data = #t_spec{}}=Tag <- Tags2],
DT = ets:new(types, [bag]),
_ = [add_type(DT, Name, As, File, Line) ||
#tag{line = Line,
- data = {#t_typedef{name = Name, args = As},_}} <- Tags],
- Warn = proplists:get_value(report_missing_type, Opts,
- ?REPORT_MISSING_TYPE) =:= true,
+ data = {#t_typedef{name = Name, args = As},_}} <- TypeTags],
+ Warn = proplists:get_value(report_missing_types, Opts,
+ ?REPORT_MISSING_TYPES) =:= true,
P = #parms{tab = DT, warn = Warn, file = File, line = 0},
- try check_types(Tags, P)
+ try check_types3(TypeTags++SpecTags, P, [])
after true = ets:delete(DT)
end.
@@ -431,60 +432,64 @@ add_type(DT, Name, Args, File, Line) ->
ets:insert(DT, {Name, NArgs})
end.
-check_types([], _P)->
+check_types3([], _P, _Ls)->
ok;
-check_types([Tag | Tags], P) ->
- check_type(Tag, P, Tags).
+check_types3([Tag | Tags], P, Ls) ->
+ check_type(Tag, P, Ls, Tags).
-check_type(#tag{line = L, data = Data}, P0, Ts) ->
+check_type(#tag{line = L, data = Data}, P0, Ls, Ts) ->
P = P0#parms{line = L},
case Data of
{#t_typedef{type = Type, defs = Defs},_} ->
- check_type(Type, P, Defs++Ts);
+ check_type(Type, P, Ls, Defs++Ts);
#t_spec{type = Type, defs = Defs} ->
- check_type(Type, P, Defs++Ts);
+ LocalTypes =
+ [{N,length(Args)} ||
+ #t_def{name = #t_type{name = N, args = Args}} <- Defs],
+ check_type(Type, P, LocalTypes, Defs),
+ check_types3(Ts, P, Ls);
_->
- check_types(Ts, P0)
+ check_types3(Ts, P0, Ls)
end;
-check_type(#t_def{type = Type}, P, Ts) ->
- check_type(Type, P, Ts);
-check_type(#t_type{name = Name, args = Args}, P, Ts) ->
- check_used_type(Name, Args, P),
- check_types(Args++Ts, P);
-check_type(#t_var{}, P, Ts) ->
- check_types(Ts, P);
-check_type(#t_fun{args = Args, range = Range}, P, Ts) ->
- check_type(Range, P, Args++Ts);
-check_type(#t_tuple{types = Types}, P, Ts) ->
- check_types(Types ++Ts, P);
-check_type(#t_list{type = Type}, P, Ts) ->
- check_type(Type, P, Ts);
-check_type(#t_nil{}, P, Ts) ->
- check_types(Ts, P);
-check_type(#t_paren{type = Type}, P, Ts) ->
- check_type(Type, P, Ts);
-check_type(#t_nonempty_list{type = Type}, P, Ts) ->
- check_type(Type, P, Ts);
-check_type(#t_atom{}, P, Ts) ->
- check_types(Ts, P);
-check_type(#t_integer{}, P, Ts) ->
- check_types(Ts, P);
-check_type(#t_integer_range{}, P, Ts) ->
- check_types(Ts, P);
-check_type(#t_binary{}, P, Ts) ->
- check_types(Ts, P);
-check_type(#t_float{}, P, Ts) ->
- check_types(Ts, P);
-check_type(#t_union{types = Types}, P, Ts) ->
- check_types(Types++Ts, P);
-check_type(#t_record{fields = Fields}, P, Ts) ->
- check_types(Fields++Ts, P);
-check_type(#t_field{type = Type}, P, Ts) ->
- check_type(Type, P, Ts);
-check_type(undefined, P, Ts) ->
- check_types(Ts, P).
-
-check_used_type(#t_name{name = N, module = Mod}=Name, Args, P) ->
+check_type(#t_def{type = Type}, P, Ls, Ts) ->
+ check_type(Type, P, Ls, Ts);
+check_type(#t_type{name = Name, args = Args}, P, Ls, Ts) ->
+ check_used_type(Name, Args, P, Ls),
+ check_types3(Args++Ts, P, Ls);
+check_type(#t_var{}, P, Ls, Ts) ->
+ check_types3(Ts, P, Ls);
+check_type(#t_fun{args = Args, range = Range}, P, Ls, Ts) ->
+ check_type(Range, P, Ls, Args++Ts);
+check_type(#t_tuple{types = Types}, P, Ls, Ts) ->
+ check_types3(Types ++Ts, P, Ls);
+check_type(#t_list{type = Type}, P, Ls, Ts) ->
+ check_type(Type, P, Ls, Ts);
+check_type(#t_nil{}, P, Ls, Ts) ->
+ check_types3(Ts, P, Ls);
+check_type(#t_paren{type = Type}, P, Ls, Ts) ->
+ check_type(Type, P, Ls, Ts);
+check_type(#t_nonempty_list{type = Type}, P, Ls, Ts) ->
+ check_type(Type, P, Ls, Ts);
+check_type(#t_atom{}, P, Ls, Ts) ->
+ check_types3(Ts, P, Ls);
+check_type(#t_integer{}, P, Ls, Ts) ->
+ check_types3(Ts, P, Ls);
+check_type(#t_integer_range{}, P, Ls, Ts) ->
+ check_types3(Ts, P, Ls);
+check_type(#t_binary{}, P, Ls, Ts) ->
+ check_types3(Ts, P, Ls);
+check_type(#t_float{}, P, Ls, Ts) ->
+ check_types3(Ts, P, Ls);
+check_type(#t_union{types = Types}, P, Ls, Ts) ->
+ check_types3(Types++Ts, P, Ls);
+check_type(#t_record{fields = Fields}, P, Ls, Ts) ->
+ check_types3(Fields++Ts, P, Ls);
+check_type(#t_field{type = Type}, P, Ls, Ts) ->
+ check_type(Type, P, Ls, Ts);
+check_type(undefined, P, Ls, Ts) ->
+ check_types3(Ts, P, Ls).
+
+check_used_type(#t_name{name = N, module = Mod}=Name, Args, P, LocalTypes) ->
NArgs = length(Args),
TypeName = {Name, NArgs},
DT = P#parms.tab,
@@ -493,6 +498,7 @@ check_used_type(#t_name{name = N, module = Mod}=Name, Args, P) ->
orelse lists:member(TypeName, ets:lookup(DT, Name))
orelse edoc_types:is_predefined(N, NArgs)
orelse edoc_types:is_predefined_otp_type(N, NArgs)
+ orelse lists:member(TypeName, LocalTypes)
of
true ->
ok;
diff --git a/lib/edoc/src/edoc_types.erl b/lib/edoc/src/edoc_types.erl
index 1ded63dffe..60c6cecb97 100644
--- a/lib/edoc/src/edoc_types.erl
+++ b/lib/edoc/src/edoc_types.erl
@@ -14,11 +14,9 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @private
%% @copyright 2001-2003 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
@@ -34,13 +32,13 @@
%% @headerfile "edoc_types.hrl"
-include("edoc_types.hrl").
--include("xmerl.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
is_predefined(any, 0) -> true;
is_predefined(atom, 0) -> true;
is_predefined(binary, 0) -> true;
-is_predefined(bool, 0) -> true;
+is_predefined(bool, 0) -> true; % kept for backwards compatibility
is_predefined(char, 0) -> true;
is_predefined(cons, 2) -> true;
is_predefined(deep_string, 0) -> true;
@@ -51,6 +49,7 @@ is_predefined(list, 0) -> true;
is_predefined(list, 1) -> true;
is_predefined(nil, 0) -> true;
is_predefined(none, 0) -> true;
+is_predefined(no_return, 0) -> true;
is_predefined(number, 0) -> true;
is_predefined(pid, 0) -> true;
is_predefined(port, 0) -> true;
diff --git a/lib/edoc/src/edoc_types.hrl b/lib/edoc/src/edoc_types.hrl
index 1353bfb93a..05c61d70ff 100644
--- a/lib/edoc/src/edoc_types.hrl
+++ b/lib/edoc/src/edoc_types.hrl
@@ -18,7 +18,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% Author contact: [email protected]
+%% Author contact: [email protected]
%% =====================================================================
%% Type specification data structures
diff --git a/lib/edoc/src/edoc_wiki.erl b/lib/edoc/src/edoc_wiki.erl
index b36aaae6ce..5c71658af5 100644
--- a/lib/edoc/src/edoc_wiki.erl
+++ b/lib/edoc/src/edoc_wiki.erl
@@ -14,11 +14,9 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
%% @private
%% @copyright 2001-2003 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @see edoc
%% @end
%% =====================================================================
@@ -70,7 +68,7 @@
-export([parse_xml/2, expand_text/2]).
-include("edoc.hrl").
--include("xmerl.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
-define(BASE_HEADING, 3).
@@ -82,8 +80,8 @@ parse_xml(Data, Line) ->
parse_xml_1(Text, Line) ->
Text1 = "<doc>" ++ Text ++ "</doc>",
- Options = [{line, Line}, {encoding, "iso-8859-1"}],
- case catch {ok, xmerl_scan:string(Text1, Options)} of
+ Opts = [{line, Line}, {encoding, 'iso-8859-1'}],
+ case catch {ok, xmerl_scan:string(Text1, Opts)} of
{ok, {E, _}} ->
E#xmlElement.content;
{'EXIT', {fatal, {Reason, L, _C}}} ->
@@ -251,10 +249,20 @@ expand_triple([], L, _, L0) ->
expand_uri("http:/" ++ Cs, L, As) ->
expand_uri(Cs, L, "/:ptth", As);
+expand_uri("https:/" ++ Cs, L, As) ->
+ expand_uri(Cs, L, "/:sptth", As);
expand_uri("ftp:/" ++ Cs, L, As) ->
expand_uri(Cs, L, "/:ptf", As);
expand_uri("file:/" ++ Cs, L, As) ->
expand_uri(Cs, L, "/:elif", As);
+expand_uri("mailto:/" ++ Cs, L, As) ->
+ expand_uri(Cs, L, "/:otliam", As);
+expand_uri("nfs:/" ++ Cs, L, As) ->
+ expand_uri(Cs, L, "/:sfn", As);
+expand_uri("shttp:/" ++ Cs, L, As) ->
+ expand_uri(Cs, L, "/:ptths", As);
+expand_uri("xmpp:/" ++ Cs, L, As) ->
+ expand_uri(Cs, L, "/:ppmx", As);
expand_uri(Cs, L, As) ->
expand(Cs, L, [$[ | As]).
@@ -296,6 +304,8 @@ push_uri(Us, Ss, As) ->
strip_empty_lines(Cs) ->
strip_empty_lines(Cs, 0).
+strip_empty_lines([], N) ->
+ {[], N}; % reached the end of input
strip_empty_lines(Cs, N) ->
{Cs1, Cs2} = edoc_lib:split_at(Cs, $\n),
case edoc_lib:is_space(Cs1) of
@@ -358,10 +368,7 @@ par_text(Cs, As, Bs, E, Es) ->
[] -> Bs;
_ -> [#xmlElement{name = p, content = Es1} | Bs]
end,
- Bs1 = case Ss of
- [] -> Bs0;
- _ -> [#xmlText{value = Ss} | Bs0]
- end,
+ Bs1 = [#xmlText{value = Ss} | Bs0],
case Cs2 of
[] ->
par(Es, [], Bs1);
diff --git a/lib/edoc/src/otpsgml_layout.erl b/lib/edoc/src/otpsgml_layout.erl
index 45f74b299e..2c4cd919bb 100644
--- a/lib/edoc/src/otpsgml_layout.erl
+++ b/lib/edoc/src/otpsgml_layout.erl
@@ -14,9 +14,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @author Kenneth Lundin <[email protected]>
%% @copyright 2001-2004 Richard Carlsson
%% @see edoc_layout
@@ -34,7 +32,7 @@
-import(edoc_report, [report/2]).
--include("xmerl.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
-define(SGML_EXPORT, xmerl_otpsgml).
-define(DEFAULT_XML_EXPORT, ?SGML_EXPORT).
diff --git a/lib/edoc/test/Makefile b/lib/edoc/test/Makefile
index f77bbaa09b..2dbdb77eff 100644
--- a/lib/edoc/test/Makefile
+++ b/lib/edoc/test/Makefile
@@ -60,7 +60,7 @@ release_tests_spec: make_emakefile
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(RELSYSDIR)
$(INSTALL_DATA) edoc.spec edoc.cover $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/edoc/test/edoc_SUITE.erl b/lib/edoc/test/edoc_SUITE.erl
index 0d57591e3e..5b95c35756 100644
--- a/lib/edoc/test/edoc_SUITE.erl
+++ b/lib/edoc/test/edoc_SUITE.erl
@@ -13,8 +13,6 @@
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
%% AB. All Rights Reserved.''
%%
-%% $Id$
-%%
-module(edoc_SUITE).
-include_lib("test_server/include/test_server.hrl").
diff --git a/lib/edoc/vsn.mk b/lib/edoc/vsn.mk
index febac9cc42..22f225dd9b 100644
--- a/lib/edoc/vsn.mk
+++ b/lib/edoc/vsn.mk
@@ -1 +1 @@
-EDOC_VSN = 0.7.7
+EDOC_VSN = 0.7.9
diff --git a/lib/erl_docgen/doc/src/notes.xml b/lib/erl_docgen/doc/src/notes.xml
index 7c8a2c8208..6a0eece56d 100644
--- a/lib/erl_docgen/doc/src/notes.xml
+++ b/lib/erl_docgen/doc/src/notes.xml
@@ -30,7 +30,66 @@
</header>
<p>This document describes the changes made to the erl_docgen application.</p>
- <section><title>erl_docgen 0.2.4</title>
+ <section><title>Erl_Docgen 0.2.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Bug fixes. </p>
+ <p>
+ Own Id: OTP-9360</p>
+ </item>
+ <item>
+ <p> The manpage generation has been improved. </p>
+ <p>
+ Own Id: OTP-9541 Aux Id: OTP-9550 </p>
+ </item>
+ <item>
+ <p> Fix eix file generation for new function spec
+ references. </p>
+ <p>
+ Own Id: OTP-9562</p>
+ </item>
+ <item>
+ <p> The function signatures in the pdf files was not in a
+ fixed font. </p>
+ <p>
+ Own Id: OTP-9563</p>
+ </item>
+ <item>
+ <p> The parts level in the system documentation was
+ missing in the bookmarks menu for the pdf and the
+ copyright year generation for PDF was not correct. </p>
+ <p>
+ Own Id: OTP-9576</p>
+ </item>
+ <item>
+ <p> The indentation after <c>Warning:</c> and
+ <c>Note:</c> in manpages has been improved. </p>
+ <p>
+ Own Id: OTP-9588</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Docgen 0.2.5</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> The support for using Erlang specifications and types
+ has been improved. </p>
+ <p>
+ Own Id: OTP-9261</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>erl_docgen 0.2.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/erl_docgen/priv/bin/specs_gen.escript b/lib/erl_docgen/priv/bin/specs_gen.escript
index 840fed6dd5..982afece7f 100644
--- a/lib/erl_docgen/priv/bin/specs_gen.escript
+++ b/lib/erl_docgen/priv/bin/specs_gen.escript
@@ -2,7 +2,7 @@
%% -*- erlang -*-
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2011. All Rights Reserved.
%%
%% The 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 @@
%%% "-I<dir>" Directory to be searched when including a file.
%%% "-module Module"
%%% Module name to use when there is no File argument.
-%%% A temporary file will be created.
+%%% A empty specifications file will be created.
%%% Exactly one of -module Module and File must be given.
%%%
%%% The name of the generated file is "specs_<module>.xml". Its exact
@@ -67,34 +67,73 @@ usage() ->
halt(1).
call_edoc(FileSpec, InclFs, Dir) ->
- Incl = [{includes, InclFs}],
- Pre = [{preprocess, true}],
- Choice = [{dialyzer_specs, all}],
- DirOpt = [{dir, Dir}],
- Pretty = [{pretty_print, erl_pp}],
- Layout = [{layout, otp_specs},
- {file_suffix, ".specs"},
- {stylesheet, ""}],
- Warn = [{report_missing_type, false},
- {report_type_mismatch, false}],
- OptionList = (DirOpt ++ Choice ++ Pre ++ Warn ++ Pretty ++ Layout ++ Incl),
- {File, TmpFile} = case FileSpec of
- {file, File0} ->
- {File0, false};
- {module, Module} ->
- {create_tmp_file(Dir, Module), true}
- end,
- try edoc:files([File], OptionList) of
- ok ->
- clean_up(Dir, File, TmpFile),
- rename(Dir, File)
+ ReadOpts = [{includes, InclFs}, {preprocess, true}],
+ ExtractOpts = [{report_missing_type, false}],
+ LayoutOpts = [{pretty_printer, erl_pp}, {layout, otp_specs}],
+ File = case FileSpec of
+ {file, File0} -> File0;
+ {module, Module0} -> Module0
+ end,
+ try
+ Fs = case FileSpec of
+ {file, _} ->
+ Fs0 = read_file(File, ReadOpts),
+ clauses(Fs0);
+ {module, Module} ->
+ [{attribute,0,module,list_to_atom(Module)}]
+ end,
+ Doc = extract(File, Fs, ExtractOpts),
+ Text = edoc:layout(Doc, LayoutOpts),
+ ok = write_text(Text, File, Dir),
+ rename(Dir, File)
catch
_:_ ->
io:format("EDoc could not process file '~s'\n", [File]),
- clean_up(Dir, File, TmpFile),
+ clean_up(Dir),
halt(3)
end.
+read_file(File, Opts) ->
+ edoc:read_source(File, Opts).
+
+extract(File, Forms, Opts) ->
+ Env = edoc_lib:get_doc_env([], [], [], _Opts=[]),
+ {_Module, Doc} = edoc_extract:source(Forms, File, Env, Opts),
+ Doc.
+
+clauses(Fs) ->
+ clauses(Fs, no).
+
+clauses([], no) ->
+ [];
+clauses([F | Fs], Spec) ->
+ case F of
+ {attribute,_,spec,_} ->
+ clauses(Fs, F);
+ {function,_,_N,_A,_Cls} when Spec =/= no->
+ {attribute,_,spec,{Name,FunTypes}} = Spec,
+ %% [throw({no,Name,{_N,_A}}) || Name =/= {_N,_A}],
+ %% EDoc doesn't care if a function appears more than once;
+ %% this is how overloaded specs are handled:
+ (lists:append([[setelement(4, Spec, {Name,[T]}),F] ||
+ T <- FunTypes])
+ ++ clauses(Fs, no));
+ _ ->
+ [F | clauses(Fs, Spec)]
+ end.
+
+write_text(Text, File, Dir) ->
+ Base = filename:basename(File, ".erl"),
+ OutFile = filename:join(Dir, Base) ++ ".specs",
+ case file:write_file(OutFile, Text) of
+ ok ->
+ ok;
+ {error, R} ->
+ R1 = file:format_error(R),
+ io:format("could not write file '~s': ~s\n", [File, R1]),
+ halt(2)
+ end.
+
rename(Dir, F) ->
Mod = filename:basename(F, ".erl"),
Old = filename:join(Dir, Mod ++ ".specs"),
@@ -108,22 +147,10 @@ rename(Dir, F) ->
halt(2)
end.
-clean_up(Dir, File, TmpFile) ->
- [file:delete(File) || TmpFile],
+clean_up(Dir) ->
_ = [file:delete(filename:join(Dir, F)) ||
F <- ["packages-frame.html",
"overview-summary.html",
"modules-frame.html",
"index.html", "erlang.png", "edoc-info"]],
ok.
-
-create_tmp_file(Dir, Module) ->
- TmpFile = filename:join(Dir, Module++".erl"),
- case file:write_file(TmpFile, "-module(" ++ Module ++ ").\n") of
- ok ->
- TmpFile;
- {error, R} ->
- R1 = file:format_error(R),
- io:format("could not write file '~s': ~s\n", [TmpFile, R1]),
- halt(2)
- end.
diff --git a/lib/erl_docgen/priv/bin/xref_mod_app.escript b/lib/erl_docgen/priv/bin/xref_mod_app.escript
index 13671ef2f8..c2bd62f9e0 100755
--- a/lib/erl_docgen/priv/bin/xref_mod_app.escript
+++ b/lib/erl_docgen/priv/bin/xref_mod_app.escript
@@ -73,7 +73,12 @@ usage() ->
modapp(TopDir) ->
AppDirs = filelib:wildcard(filename:join([TopDir,"lib","*"])),
AM = [appmods(D) || D <- AppDirs],
- lists:keysort(1, [{M,A} || {A,Ms} <- AM, M <- Ms]).
+ ERTS = [preloaded(TopDir) || lists:keyfind("erts", 1, AM) =:= false],
+ lists:keysort(1, [{M,A} || {A,Ms} <- ERTS++AM, M <- Ms]).
+
+preloaded(TopDir) ->
+ {"preloaded",Mods} = appmods(filename:join([TopDir,"erts","preloaded"])),
+ {"erts",Mods}.
%% It's OK if too much data is generated as long as all applications
%% and all modules are mentioned.
diff --git a/lib/erl_docgen/priv/xsl/db_eix.xsl b/lib/erl_docgen/priv/xsl/db_eix.xsl
index 4545322bc2..7a648ddfd7 100644
--- a/lib/erl_docgen/priv/xsl/db_eix.xsl
+++ b/lib/erl_docgen/priv/xsl/db_eix.xsl
@@ -22,10 +22,16 @@
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ extension-element-prefixes="exsl"
xmlns:fn="http://www.w3.org/2005/02/xpath-functions">
<xsl:output method="text" encoding="UTF-8" indent="no"/>
+ <xsl:param name="specs_file" select="''"/>
+ <xsl:variable name="i" select="document($specs_file)"></xsl:variable>
+
+
<!-- Book -->
<xsl:template match="/book">
<xsl:text>%% &#10;%% Search data file for </xsl:text><xsl:value-of select="$appname"/><xsl:text> </xsl:text><xsl:value-of select="$appver"/>
@@ -50,9 +56,7 @@
<xsl:template match="erlref">
<xsl:text>{"</xsl:text><xsl:value-of select="module"/><xsl:text>.html", {function, {"</xsl:text><xsl:value-of select="$appname"/>
<xsl:text>", "</xsl:text><xsl:value-of select="module"/><xsl:text>"}},&#10;[&#10;</xsl:text>
- <xsl:apply-templates select="funcs">
- <xsl:with-param name="mod" select="module"/>
- </xsl:apply-templates>
+ <xsl:apply-templates select="funcs"/>
<xsl:text>]}.&#10;</xsl:text>
<xsl:text>{"</xsl:text><xsl:value-of select="module"/><xsl:text>.html", {module, "</xsl:text>
<xsl:value-of select="$appname"/><xsl:text>"}, ["</xsl:text><xsl:value-of select="module"/><xsl:text>"]}.&#10;</xsl:text>
@@ -62,9 +66,7 @@
<xsl:template match="cref">
<xsl:text>{"</xsl:text><xsl:value-of select="lib"/><xsl:text>.html", {function, {"</xsl:text><xsl:value-of select="$appname"/>
<xsl:text>", "</xsl:text><xsl:value-of select="lib"/><xsl:text>"}}, [&#10;</xsl:text>
- <xsl:apply-templates select="funcs">
- <xsl:with-param name="mod" select="lib"/>
- </xsl:apply-templates>
+ <xsl:apply-templates select="funcs"/>
<xsl:text>]}.&#10;</xsl:text>
<xsl:text>{"</xsl:text><xsl:value-of select="lib"/><xsl:text>.html", {clib, "</xsl:text>
<xsl:value-of select="$appname"/><xsl:text>"}, ["</xsl:text><xsl:value-of select="lib"/><xsl:text>"]}.&#10;</xsl:text>
@@ -91,69 +93,157 @@
<!-- Funcs -->
<xsl:template match="funcs">
- <xsl:param name="mod"/>
<xsl:variable name="lastfuncsblock">
<xsl:value-of select="position() = last()"/>
</xsl:variable>
<xsl:apply-templates select="func/name">
- <xsl:with-param name="mod" select="$mod"/>
<xsl:with-param name="lastfuncsblock" select="$lastfuncsblock"/>
</xsl:apply-templates>
</xsl:template>
+ <xsl:template match="name">
+ <xsl:param name="lastfuncsblock"/>
+ <xsl:choose>
+ <!-- @arity is mandatory when referring to a specification -->
+ <xsl:when test="string-length(@arity) > 0">
+ <xsl:call-template name="spec_name"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="err">
+ <xsl:param name="f"/>
+ <xsl:param name="m"/>
+ <xsl:param name="n"/>
+ <xsl:param name="a"/>
+ <xsl:param name="s"/>
+ <xsl:message terminate="yes">
+ Error <xsl:if test="$f != ''">in <xsl:value-of select ="$f"/>:</xsl:if>
+ <xsl:if test="$m != ''"><xsl:value-of select ="$m"/>:</xsl:if>
+ <xsl:value-of select="$n"/>
+ <xsl:if test="$a != ''">/<xsl:value-of
+ select ="$a"/></xsl:if>: <xsl:value-of select="$s"/>
+ </xsl:message>
+ </xsl:template>
+ <xsl:template name="find_spec">
+ <xsl:variable name="curModule" select="ancestor::erlref/module"/>
+ <xsl:variable name="mod" select="@mod"/>
+ <xsl:variable name="name" select="@name"/>
+ <xsl:variable name="arity" select="@arity"/>
+ <xsl:variable name="clause_i" select="@clause_i"/>
+ <xsl:variable name="spec0" select=
+ "$i/specs/module[@name=$curModule]/spec
+ [name=$name and arity=$arity
+ and (string-length($mod) = 0 or module = $mod)]"/>
+ <xsl:variable name="spec" select="$spec0[string-length($clause_i) = 0
+ or position() = $clause_i]"/>
- <xsl:template match="name">
- <xsl:param name="mod"/>
+ <xsl:if test="count($spec) != 1">
+ <xsl:variable name="why">
+ <xsl:choose>
+ <xsl:when test="count($spec) > 1">ambiguous spec</xsl:when>
+ <xsl:when test="count($spec) = 0">unknown spec</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="err">
+ <xsl:with-param name="f" select="$curModule"/>
+ <xsl:with-param name="m" select="$mod"/>
+ <xsl:with-param name="n" select="$name"/>
+ <xsl:with-param name="a" select="$arity"/>
+ <xsl:with-param name="s" select="$why"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:copy-of select="$spec"/>
+ </xsl:template>
+
+
+ <xsl:template name="spec_name">
+ <xsl:param name="lastfuncsblock"/>
+ <xsl:variable name="fname" select="@name"/>
+ <xsl:variable name="arity" select="@arity"/>
+ <xsl:variable name="spec0">
+ <xsl:call-template name="find_spec"/>
+ </xsl:variable>
+ <xsl:variable name="spec" select="exsl:node-set($spec0)/spec"/>
+
+ <xsl:variable name="tmpstring">
+ <xsl:value-of select="substring-before($spec/contract/clause/head, ' ->')"/>
+ </xsl:variable>
+
+ <xsl:text> {"</xsl:text><xsl:value-of select="$fname"/>
+ <xsl:text>", "</xsl:text><xsl:value-of select="$tmpstring"/>
+ <xsl:text>", "</xsl:text><xsl:value-of select="$fname"/>
+ <xsl:text>-</xsl:text><xsl:value-of select="$arity"/><xsl:text>"}</xsl:text>
+
+ <xsl:choose>
+ <xsl:when test="($lastfuncsblock = 'true') and (position() = last())">
+ <xsl:text>&#10;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>,&#10;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </xsl:template>
+
+
+ <xsl:template name="name">
<xsl:param name="lastfuncsblock"/>
<xsl:variable name="tmpstring">
<xsl:value-of select="substring-before(substring-after(., '('), '->')"/>
- </xsl:variable>
+ </xsl:variable>
+
<xsl:variable name="ustring">
<xsl:choose>
- <xsl:when test="string-length($tmpstring) > 0">
- <xsl:call-template name="remove-paren">
- <xsl:with-param name="string" select="$tmpstring"/>
- </xsl:call-template>
- </xsl:when>
- <xsl:otherwise>
- <xsl:call-template name="remove-paren">
- <xsl:with-param name="string" select="substring-after(., '(')"/>
- </xsl:call-template>
- </xsl:otherwise>
+ <xsl:when test="string-length($tmpstring) > 0">
+ <xsl:call-template name="remove-paren">
+ <xsl:with-param name="string" select="$tmpstring"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="remove-paren">
+ <xsl:with-param name="string" select="substring-after(., '(')"/>
+ </xsl:call-template>
+ </xsl:otherwise>
</xsl:choose>
- </xsl:variable>
+ </xsl:variable>
+
<xsl:variable name="arity">
<xsl:call-template name="calc-arity">
- <xsl:with-param name="string" select="substring-before($ustring, ')')"/>
- <xsl:with-param name="no-of-pars" select="0"/>
+ <xsl:with-param name="string" select="substring-before($ustring, ')')"/>
+ <xsl:with-param name="no-of-pars" select="0"/>
</xsl:call-template>
- </xsl:variable>
+ </xsl:variable>
+
<xsl:variable name="fname">
<xsl:choose>
- <xsl:when test="ancestor::cref">
- <xsl:value-of select="substring-before(nametext, '(')"/>
- </xsl:when>
- <xsl:when test="ancestor::erlref">
- <xsl:variable name="fname1">
- <xsl:value-of select="substring-before(., '(')"/>
- </xsl:variable>
- <xsl:variable name="fname2">
- <xsl:value-of select="substring-after($fname1, 'erlang:')"/>
- </xsl:variable>
- <xsl:choose>
- <xsl:when test="string-length($fname2) > 0">
- <xsl:value-of select="$fname2"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="$fname1"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:when>
+ <xsl:when test="ancestor::cref">
+ <xsl:value-of select="substring-before(nametext, '(')"/>
+ </xsl:when>
+ <xsl:when test="ancestor::erlref">
+ <xsl:variable name="fname1">
+ <xsl:value-of select="substring-before(., '(')"/>
+ </xsl:variable>
+ <xsl:variable name="fname2">
+ <xsl:value-of select="substring-after($fname1, 'erlang:')"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($fname2) > 0">
+ <xsl:value-of select="$fname2"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$fname1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
</xsl:choose>
- </xsl:variable>
+ </xsl:variable>
+
<xsl:text> {"</xsl:text><xsl:value-of select="$fname"/>
<xsl:text>", "</xsl:text><xsl:value-of select="$fname"/>
<xsl:text>(</xsl:text><xsl:value-of select="normalize-space($tmpstring)"/>
diff --git a/lib/erl_docgen/priv/xsl/db_html.xsl b/lib/erl_docgen/priv/xsl/db_html.xsl
index c6375ea621..a9052f29e5 100644
--- a/lib/erl_docgen/priv/xsl/db_html.xsl
+++ b/lib/erl_docgen/priv/xsl/db_html.xsl
@@ -22,12 +22,15 @@
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ extension-element-prefixes="exsl"
xmlns:fn="http://www.w3.org/2005/02/xpath-functions">
<xsl:include href="db_html_params.xsl"/>
<!-- Start of Dialyzer type/spec tags.
- See also the template matching "name" and the template "menu.funcs"
+ See also the templates matching "name" and "seealso" as well as
+ the template "menu.funcs"
-->
<xsl:param name="specs_file" select="''"/>
@@ -38,49 +41,58 @@
<xsl:key name="mod2app" match="module" use="@name"/>
<xsl:template name="err">
+ <xsl:param name="f"/>
<xsl:param name="m"/>
<xsl:param name="n"/>
<xsl:param name="a"/>
<xsl:param name="s"/>
<xsl:message terminate="yes">
- Error <xsl:if test="$m != ''"><xsl:value-of select ="$m"/>:</xsl:if>
- <xsl:value-of
- select="$n"/>/<xsl:value-of
- select="$a"/>: <xsl:value-of select="$s"/>
+ Error <xsl:if test="$f != ''">in <xsl:value-of select ="$f"/>:</xsl:if>
+ <xsl:if test="$m != ''"><xsl:value-of select ="$m"/>:</xsl:if>
+ <xsl:value-of select="$n"/>
+ <xsl:if test="$a != ''">/<xsl:value-of
+ select ="$a"/></xsl:if>: <xsl:value-of select="$s"/>
</xsl:message>
</xsl:template>
- <xsl:template name="spec_name">
+ <xsl:template name="find_spec">
<xsl:variable name="curModule" select="ancestor::erlref/module"/>
<xsl:variable name="mod" select="@mod"/>
<xsl:variable name="name" select="@name"/>
<xsl:variable name="arity" select="@arity"/>
- <xsl:variable name="clause" select="@clause"/>
+ <xsl:variable name="clause_i" select="@clause_i"/>
<xsl:variable name="spec0" select=
"$i/specs/module[@name=$curModule]/spec
[name=$name and arity=$arity
and (string-length($mod) = 0 or module = $mod)]"/>
- <xsl:variable name="spec" select="$spec0[string-length($clause) = 0
- or position() = $clause]"/>
- <xsl:if test="count($spec) = 0">
+ <xsl:variable name="spec" select="$spec0[string-length($clause_i) = 0
+ or position() = $clause_i]"/>
+
+ <xsl:if test="count($spec) != 1">
+ <xsl:variable name="why">
+ <xsl:choose>
+ <xsl:when test="count($spec) > 1">ambiguous spec</xsl:when>
+ <xsl:when test="count($spec) = 0">unknown spec</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
<xsl:call-template name="err">
+ <xsl:with-param name="f" select="$curModule"/>
<xsl:with-param name="m" select="$mod"/>
<xsl:with-param name="n" select="$name"/>
<xsl:with-param name="a" select="$arity"/>
- <xsl:with-param name="s">unknown spec</xsl:with-param>
+ <xsl:with-param name="s" select="$why"/>
</xsl:call-template>
</xsl:if>
+ <xsl:copy-of select="$spec"/>
+ </xsl:template>
- <xsl:variable name="arity_clause">
- <xsl:choose>
- <xsl:when test="string-length(@clause) > 0">
- <xsl:value-of select="@arity"/>/<xsl:value-of select="@clause"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="@arity"/>
- </xsl:otherwise>
- </xsl:choose>
+ <xsl:template name="spec_name">
+ <xsl:variable name="name" select="@name"/>
+ <xsl:variable name="arity" select="@arity"/>
+ <xsl:variable name="spec0">
+ <xsl:call-template name="find_spec"/>
</xsl:variable>
+ <xsl:variable name="spec" select="exsl:node-set($spec0)/spec"/>
<xsl:choose>
<xsl:when test="ancestor::cref">
@@ -89,72 +101,189 @@
</xsl:message>
</xsl:when>
<xsl:when test="ancestor::erlref">
- <a name="{$name}-{$arity_clause}"></a>
- <xsl:choose>
- <xsl:when test="string(@with_guards) = 'no'">
- <xsl:apply-templates select="$spec/contract/clause/head"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:call-template name="contract">
- <xsl:with-param name="contract" select="$spec/contract"/>
- </xsl:call-template>
- </xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="preceding-sibling::name[position() = 1
+ and @name = $name and @arity = $arity]">
+ <!-- Avoid duplicated anchors.-->
+ </xsl:when>
+ <xsl:otherwise>
+ <a name="{$name}-{$arity}"></a>
+ </xsl:otherwise>
</xsl:choose>
+
+ <xsl:variable name="global_types" select="ancestor::erlref/datatypes"/>
+ <xsl:variable name="local_types"
+ select="../type[string-length(@name) > 0]"/>
+ <xsl:apply-templates select="$spec/contract/clause/head">
+ <xsl:with-param name="local_types" select="$local_types"/>
+ <xsl:with-param name="global_types" select="$global_types"/>
+ </xsl:apply-templates>
</xsl:when>
</xsl:choose>
</xsl:template>
- <xsl:template name="contract">
- <xsl:param name="contract"/>
- <xsl:call-template name="clause">
- <xsl:with-param name="clause" select="$contract/clause"/>
- </xsl:call-template>
- </xsl:template>
-
- <xsl:template name="clause">
- <xsl:param name="clause"/>
- <xsl:variable name="type_desc" select="../type_desc"/>
- <xsl:for-each select="$clause">
- <xsl:apply-templates select="head"/>
- <xsl:if test="count(guard) > 0">
- <xsl:call-template name="guard">
- <xsl:with-param name="guard" select="guard"/>
- <xsl:with-param name="type_desc" select="$type_desc"/>
- </xsl:call-template>
- </xsl:if>
- </xsl:for-each>
- </xsl:template>
-
<xsl:template match="head">
+ <xsl:param name="local_types"/>
+ <xsl:param name="global_types"/>
<span class="bold_code">
- <xsl:apply-templates/>
+ <xsl:apply-templates mode="local_type">
+ <xsl:with-param name="local_types" select="$local_types"/>
+ <xsl:with-param name="global_types" select="$global_types"/>
+ </xsl:apply-templates>
</span>
<br/>
</xsl:template>
- <xsl:template name="guard">
- <xsl:param name="guard"/>
+ <!-- The *last* <name name="..." arity=".."/> -->
+ <xsl:template match="name" mode="types">
+ <xsl:variable name="name" select="@name"/>
+ <xsl:variable name="arity" select="@arity"/>
+ <xsl:variable name="spec0">
+ <xsl:call-template name="find_spec"/>
+ </xsl:variable>
+ <xsl:variable name="spec" select="exsl:node-set($spec0)/spec"/>
+ <xsl:variable name="clause" select="$spec/contract/clause"/>
+
+ <xsl:variable name="global_types" select="ancestor::erlref/datatypes"/>
+ <xsl:variable name="type_desc" select="../type_desc"/>
+ <!-- $type is data types to be presented as guards ("local types") -->
+ <xsl:variable name="type"
+ select="../type[string-length(@name) > 0
+ or string-length(@variable) > 0]"/>
+ <xsl:variable name="type_variables"
+ select ="$type[string-length(@variable) > 0]"/>
+ <xsl:variable name="local_types"
+ select ="$type[string-length(@name) > 0]"/>
+ <xsl:variable name="output_subtypes" select="count($type_variables) = 0"/>
+
+ <!-- It is assumed there is no support for overloaded specs
+ (there is no spec with more than one clause) -->
+ <xsl:if test="count($clause/guard) > 0 or count($type) > 0">
+ <div class="REFBODY"><p>Types:</p>
+
+ <xsl:choose>
+ <xsl:when test="$output_subtypes">
+ <xsl:call-template name="subtype">
+ <xsl:with-param name="subtype" select="$clause/guard/subtype"/>
+ <xsl:with-param name="type_desc" select="$type_desc"/>
+ <xsl:with-param name="local_types" select="$local_types"/>
+ <xsl:with-param name="global_types" select="$global_types"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="type_variables">
+ <xsl:with-param name="type_variables" select="$type_variables"/>
+ <xsl:with-param name="type_desc" select="$type_desc"/>
+ <xsl:with-param name="local_types" select="$local_types"/>
+ <xsl:with-param name="global_types" select="$global_types"/>
+ <xsl:with-param name="fname" select="$name"/>
+ <xsl:with-param name="arity" select="$arity"/>
+ </xsl:call-template>
+
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:call-template name="local_type">
+ <xsl:with-param name="type_desc" select="$type_desc"/>
+ <xsl:with-param name="local_types" select="$local_types"/>
+ <xsl:with-param name="global_types" select="$global_types"/>
+ </xsl:call-template>
+ </div>
+
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Handle <type variable="..." name_i="..."/> -->
+ <xsl:template name="type_variables">
+ <xsl:param name="type_variables"/>
<xsl:param name="type_desc"/>
- <div class="REFBODY"><p>Types:</p>
+ <xsl:param name="local_types"/>
+ <xsl:param name="global_types"/>
+ <xsl:param name="fname"/>
+ <xsl:param name="arity"/>
+
+ <xsl:variable name="names" select="../name[string-length(@arity) > 0]"/>
+ <xsl:for-each select="$type_variables">
+ <xsl:variable name="name_i">
+ <xsl:choose>
+ <xsl:when test="string-length(@name_i) > 0">
+ <xsl:value-of select="@name_i"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="count($names)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="spec0">
+ <xsl:for-each select="$names[position() = $name_i]">
+ <xsl:call-template name="find_spec"/>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="spec" select="exsl:node-set($spec0)/spec"/>
+ <xsl:variable name="clause" select="$spec/contract/clause"/>
+ <xsl:variable name="variable" select="@variable"/>
+ <xsl:variable name="subtype"
+ select="$clause/guard/subtype[typename = $variable]"/>
+
+ <xsl:if test="count($subtype) = 0">
+ <xsl:call-template name="err">
+ <xsl:with-param name="f" select="ancestor::erlref/module"/>
+ <xsl:with-param name="n" select="$fname"/>
+ <xsl:with-param name="a" select="$arity"/>
+ <xsl:with-param name="s">unknown type variable <xsl:value-of select="$variable"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+
<xsl:call-template name="subtype">
- <xsl:with-param name="subtype" select="$guard/subtype"/>
- <xsl:with-param name="type_desc" select="$type_desc"/>
+ <xsl:with-param name="subtype" select="$subtype"/>
+ <xsl:with-param name="type_desc" select="$type_desc"/>
+ <xsl:with-param name="local_types" select="$local_types"/>
+ <xsl:with-param name="global_types" select="$global_types"/>
</xsl:call-template>
- </div>
+ </xsl:for-each>
</xsl:template>
<xsl:template name="subtype">
<xsl:param name="subtype"/>
<xsl:param name="type_desc"/>
+ <xsl:param name="local_types"/>
+ <xsl:param name="global_types"/>
+
<xsl:for-each select="$subtype">
<xsl:variable name="tname" select="typename"/>
- <xsl:variable name="tdesc" select="$type_desc[@name = $tname]"/>
<div class="REFTYPES">
<span class="bold_code">
- <xsl:apply-templates select="string"/>
+ <xsl:apply-templates select="string" mode="local_type">
+ <xsl:with-param name="local_types" select="$local_types"/>
+ <xsl:with-param name="global_types" select="$global_types"/>
+ </xsl:apply-templates>
</span>
</div>
- <xsl:apply-templates select="$type_desc[@name = $tname]"/>
+ <xsl:apply-templates select="$type_desc[@variable = $tname]"/>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template name="local_type">
+ <xsl:param name="type_desc"/>
+ <xsl:param name="local_types"/>
+ <xsl:param name="global_types"/>
+
+ <xsl:for-each select="$local_types">
+ <div class="REFTYPES">
+ <xsl:call-template name="type_name">
+ <xsl:with-param name="mode" select="'local_type'"/>
+ <xsl:with-param name="local_types" select="$local_types"/>
+ <xsl:with-param name="global_types" select="$global_types"/>
+ </xsl:call-template>
+ </div>
+ <xsl:variable name="tname" select="@name"/>
+ <xsl:variable name="tnvars" select="@n_vars"/>
+ <xsl:apply-templates select=
+ "$type_desc[@name = $tname
+ and (@n_vars = $tnvars
+ or string-length(@n_vars) = 0 and
+ string-length($tnvars) = 0)]"/>
</xsl:for-each>
</xsl:template>
@@ -193,130 +322,177 @@
<xsl:apply-templates select="desc"/>
</xsl:template>
- <xsl:template match="typehead">
- <span class="bold_code">
- <xsl:apply-templates/>
- </span><br/>
- </xsl:template>
-
- <!-- local_defs -->
- <xsl:template match="local_defs">
- <div class="REFBODY">
- <xsl:apply-templates>
- </xsl:apply-templates>
- </div>
- </xsl:template>
-
- <xsl:template match="local_def">
- <div class="REFTYPES">
- <span class="bold_code">
- <xsl:apply-templates/>
- </span>
- </div>
- </xsl:template>
+ <!-- The "mode" attribute of apply has been used to separate the case
+ when datatypes are copied into specifications' subtypes.
+ A local type has no anchor. There are no links to local types
+ from local types or guards/head of the same specification.
+ -->
<xsl:template name="type_name">
+ <xsl:param name="mode"/> <!-- '' if <datatype> -->
+ <xsl:param name="local_types" select="/.."/>
+ <xsl:param name="global_types" select="/.."/>
<xsl:variable name="curModule" select="ancestor::erlref/module"/>
<xsl:variable name="mod" select="@mod"/>
<xsl:variable name="name" select="@name"/>
- <xsl:variable name="n_vars">
- <xsl:choose>
- <xsl:when test="string-length(@n_vars) > 0">
- <xsl:value-of select="@n_vars"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="0"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
+ <xsl:variable name="n_vars" select="@n_vars"/>
<xsl:choose>
<xsl:when test="string-length($name) > 0">
<xsl:variable name="type" select=
"$i/specs/module[@name=$curModule]/type
- [name=$name and n_vars=$n_vars
+ [name=$name
+ and (string-length($n_vars) = 0 or n_vars = $n_vars)
and (string-length($mod) = 0 or module = $mod)]"/>
<xsl:if test="count($type) != 1">
+ <xsl:variable name="why">
+ <xsl:choose>
+ <xsl:when test="count($type) > 1">ambiguous type</xsl:when>
+ <xsl:when test="count($type) = 0">unknown type</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
<xsl:call-template name="err">
+ <xsl:with-param name="f" select="$curModule"/>
<xsl:with-param name="m" select="$mod"/>
<xsl:with-param name="n" select="$name"/>
<xsl:with-param name="a" select="$n_vars"/>
- <xsl:with-param name="s">unknown type</xsl:with-param>
+ <xsl:with-param name="s" select="$why"/>
</xsl:call-template>
</xsl:if>
- <xsl:apply-templates select="$type/typedecl"/>
+ <xsl:choose>
+ <xsl:when test="$mode = ''">
+ <xsl:apply-templates select="$type/typedecl"/>
+ </xsl:when>
+ <xsl:when test="$mode = 'local_type'">
+ <xsl:apply-templates select="$type/typedecl" mode="local_type">
+ <xsl:with-param name="local_types" select="$local_types"/>
+ <xsl:with-param name="global_types" select="$global_types"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ </xsl:choose>
</xsl:when>
- <xsl:otherwise>
+ <xsl:otherwise> <!-- <datatype> with <name> -->
<span class="bold_code">
- <xsl:value-of select="."/>
+ <xsl:apply-templates/>
</span>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
+ <xsl:template match="typehead">
+ <span class="bold_code">
+ <xsl:apply-templates/>
+ </span><br/>
+ </xsl:template>
+
+ <xsl:template match="typehead" mode="local_type">
+ <xsl:param name="local_types"/>
+ <xsl:param name="global_types"/>
+ <span class="bold_code">
+ <xsl:apply-templates mode="local_type">
+ <xsl:with-param name="local_types" select="$local_types"/>
+ <xsl:with-param name="global_types" select="$global_types"/>
+ </xsl:apply-templates>
+ </span><br/>
+ </xsl:template>
+
+ <!-- Not used right now -->
+ <!-- local_defs -->
+ <xsl:template match="local_defs">
+ <div class="REFBODY">
+ <xsl:apply-templates>
+ </xsl:apply-templates>
+ </div>
+ </xsl:template>
+
+ <!-- Not used right now -->
+ <xsl:template match="local_def">
+ <div class="REFTYPES">
+ <span class="bold_code">
+ <xsl:apply-templates/>
+ </span>
+ </div>
+ </xsl:template>
+
<!-- Used both in <datatype> and in <func>! -->
<xsl:template match="anno">
<xsl:variable name="curModule" select="ancestor::erlref/module"/>
<xsl:variable name="anno" select="normalize-space(text())"/>
<xsl:variable name="namespec"
- select="ancestor::desc/preceding-sibling::name"/>
+ select="ancestor::type_desc/preceding-sibling::name
+ | ancestor::desc/preceding-sibling::name"/>
<xsl:if test="count($namespec) = 0 and string-length($specs_file) > 0">
<xsl:call-template name="err">
- <xsl:with-param name="s">cannot find 'name' (<xsl:value-of select="$anno"/>)
+ <xsl:with-param name="f" select="$curModule"/>
+ <xsl:with-param name="s">cannot find tag 'name' (anno <xsl:value-of select="$anno"/>)
</xsl:with-param>
</xsl:call-template>
</xsl:if>
- <xsl:variable name="mod" select="$namespec/@mod"/>
- <xsl:variable name="name" select="$namespec/@name"/>
- <xsl:variable name="arity" select="$namespec/@arity"/>
- <xsl:variable name="clause" select="$namespec/@clause"/>
- <xsl:variable name="tmp_n_vars" select="$namespec/@n_vars"/>
- <xsl:variable name="n_vars">
- <xsl:choose>
- <xsl:when test="string-length($tmp_n_vars) > 0">
- <xsl:value-of select="$tmp_n_vars"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="0"/>
- </xsl:otherwise>
- </xsl:choose>
+ <!-- Search "local types" as well -->
+ <xsl:variable name="local_types"
+ select="ancestor::desc/preceding-sibling::type
+ [string-length(@name) > 0]
+ | ancestor::type_desc/preceding-sibling::type
+ [string-length(@name) > 0]"/>
+ <xsl:variable name="has_anno_in_local_type">
+ <xsl:for-each select="$local_types">
+ <xsl:call-template name="anno_name">
+ <xsl:with-param name="curModule" select="$curModule"/>
+ <xsl:with-param name="anno" select="$anno"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:variable name="has_anno">
+ <xsl:for-each select="$namespec">
+ <xsl:call-template name="anno_name">
+ <xsl:with-param name="curModule" select="$curModule"/>
+ <xsl:with-param name="anno" select="$anno"/>
+ </xsl:call-template>
+ </xsl:for-each>
</xsl:variable>
+
+ <xsl:if test="$has_anno = '' and $has_anno_in_local_type = ''">
+ <xsl:call-template name="err">
+ <xsl:with-param name="f" select="$curModule"/>
+ <xsl:with-param name="m" select="$namespec/@mod"/>
+ <xsl:with-param name="n" select="$namespec/@name"/>
+ <xsl:with-param name="a" select="'-'"/>
+ <xsl:with-param name="s">unknown annotation <xsl:value-of select="$anno"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:value-of select="$anno"/>
+ </xsl:template>
+
+ <xsl:template name="anno_name">
+ <xsl:param name="curModule"/>
+ <xsl:param name="anno"/>
+ <xsl:variable name="mod" select="@mod"/>
+ <xsl:variable name="name" select="@name"/>
+ <xsl:variable name="arity" select="@arity"/>
+ <xsl:variable name="n_vars" select="@n_vars"/>
+ <xsl:variable name="clause_i" select="@clause_i"/>
+
<xsl:variable name="spec0" select=
"$i/specs/module[@name=$curModule]/spec
[name=$name and arity=$arity
and (string-length($mod) = 0 or module = $mod)]"/>
<xsl:variable name="spec_annos" select=
- "$spec0[string-length($clause) = 0
- or position() = $clause]/anno[.=$anno]"/>
+ "$spec0[string-length($clause_i) = 0
+ or position() = $clause_i]/anno[.=$anno]"/>
<xsl:variable name="type_annos" select=
"$i/specs/module[@name=$curModule]/type
- [name=$name and n_vars=$n_vars
+ [name=$name
+ and (string-length($n_vars) = 0 or n_vars=$n_vars)
and (string-length($mod) = 0 or module = $mod)]/anno[.=$anno]"/>
-
- <xsl:if test="count($spec_annos) = 0
- and count($type_annos) = 0
- and string-length($specs_file) > 0">
- <xsl:variable name="n">
- <xsl:choose>
- <xsl:when test="string-length($arity) = 0">
- <xsl:value-of select="$n_vars"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="$arity"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <xsl:call-template name="err">
- <xsl:with-param name="m" select="$mod"/>
- <xsl:with-param name="n" select="$name"/>
- <xsl:with-param name="a" select="$n"/>
- <xsl:with-param name="s">unknown annotation <xsl:value-of select="$anno"/>
- </xsl:with-param>
- </xsl:call-template>
+ <xsl:if test="count($spec_annos) != 0
+ or count($type_annos) != 0
+ or string-length($specs_file) = 0">
+ <xsl:value-of select="true()"/>
</xsl:if>
- <xsl:value-of select="$anno"/>
</xsl:template>
<!-- Used for indentation of formatted types and specs -->
@@ -324,6 +500,50 @@
<xsl:text>&#160;</xsl:text>
</xsl:template>
+ <xsl:template match="nbsp" mode="local_type">
+ <xsl:apply-templates select="."/>
+ </xsl:template>
+
+ <xsl:template match="br" mode="local_type">
+ <xsl:apply-templates select="."/>
+ </xsl:template>
+
+ <xsl:template match="marker" mode="local_type">
+ <xsl:param name="local_types"/>
+ <xsl:param name="global_types"/>
+ <!-- Craete no anchor -->
+ <!-- It would be possible to create a link to the global type
+ (if there is one), but that would mean even more code...
+ -->
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <!-- Does not look at @n_vars -->
+ <xsl:template match="seealso" mode="local_type">
+ <xsl:param name="local_types"/>
+ <xsl:param name="global_types"/>
+
+ <xsl:variable name="filepart"><xsl:value-of select="substring-before(@marker, '#')"/></xsl:variable>
+ <xsl:variable name="linkpart"><xsl:value-of select="translate(substring-after(@marker, '#'), '/', '-')"/></xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="string-length($filepart) > 0">
+ <xsl:call-template name="seealso"/>
+ </xsl:when>
+ <xsl:when test="count($local_types[concat('type-', @name) = $linkpart]) = 0">
+ <xsl:call-template name="seealso"/>
+ </xsl:when>
+ <xsl:when test="count($global_types/datatype/name[concat('type-', @name) = $linkpart]) > 0">
+ <!-- The type is both local and global; link to the global type -->
+ <xsl:call-template name="seealso"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- No link to local type -->
+ <xsl:apply-templates/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
<!-- End of Dialyzer type/spec tags -->
<!-- Page layout -->
@@ -1178,14 +1398,7 @@
<xsl:choose>
<xsl:when test="string-length(@arity) > 0">
<!-- Dialyzer spec -->
- <xsl:choose>
- <xsl:when test="string-length(@clause) > 0">
- <xsl:value-of select="@arity"/>/<xsl:value-of select="@clause"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="@arity"/>
- </xsl:otherwise>
- </xsl:choose>
+ <xsl:value-of select="@arity"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="calc-arity">
@@ -1221,11 +1434,19 @@
</xsl:choose>
</xsl:variable>
- <li title="{$fname}-{$arity}">
- <a href="{$basename}.html#{$fname}-{$arity}">
- <xsl:value-of select="$fname"/>/<xsl:value-of select="$arity"/>
- </a>
- </li>
+ <xsl:choose>
+ <xsl:when test="preceding-sibling::name[position() = 1
+ and @name = $fname and @arity = $arity]">
+ <!-- Skip. Only works for Dialyzer specs. -->
+ </xsl:when>
+ <xsl:otherwise>
+ <li title="{$fname}-{$arity}">
+ <a href="{$basename}.html#{$fname}-{$arity}">
+ <xsl:value-of select="$fname"/>/<xsl:value-of select="$arity"/>
+ </a>
+ </li>
+ </xsl:otherwise>
+ </xsl:choose>
</xsl:when>
</xsl:choose>
@@ -1470,7 +1691,10 @@
<xsl:template match="func">
<xsl:param name="partnum"/>
- <p><xsl:apply-templates select="name"/></p>
+ <p><xsl:apply-templates select="name"/>
+ <xsl:apply-templates
+ select="name[string-length(@arity) > 0 and position()=last()]"
+ mode="types"/></p>
<xsl:apply-templates select="fsummary|type|desc">
<xsl:with-param name="partnum" select="$partnum"/>
@@ -1478,7 +1702,6 @@
</xsl:template>
-
<xsl:template match="name">
<xsl:choose>
<!-- @arity is mandatory when referring to a specification -->
@@ -1488,6 +1711,11 @@
<xsl:when test="ancestor::datatype">
<xsl:call-template name="type_name"/>
</xsl:when>
+ <xsl:when test="string-length(text()) = 0 and ancestor::erlref">
+ <xsl:message terminate="yes">
+ Error <xsl:value-of select="@name"/>: arity is mandatory when referring to specifications!
+ </xsl:message>
+ </xsl:when>
<xsl:otherwise>
<xsl:call-template name="name"/>
</xsl:otherwise>
@@ -1556,12 +1784,17 @@
<xsl:template match="type">
<xsl:param name="partnum"/>
- <div class="REFBODY"><p>Types:</p>
+ <!-- The case where @name != 0 is taken care of in "type_name" -->
+ <xsl:if test="string-length(@name) = 0 and string-length(@variable) = 0">
- <xsl:apply-templates>
- <xsl:with-param name="partnum" select="$partnum"/>
- </xsl:apply-templates>
- </div>
+ <div class="REFBODY"><p>Types:</p>
+
+ <xsl:apply-templates>
+ <xsl:with-param name="partnum" select="$partnum"/>
+ </xsl:apply-templates>
+ </div>
+
+ </xsl:if>
</xsl:template>
@@ -1612,7 +1845,10 @@
</xsl:template>
<xsl:template match="seealso">
+ <xsl:call-template name="seealso"/>
+ </xsl:template>
+ <xsl:template name="seealso">
<xsl:variable name="filepart"><xsl:value-of select="substring-before(@marker, '#')"/></xsl:variable>
<xsl:variable name="linkpart"><xsl:value-of select="translate(substring-after(@marker, '#'), '/', '-')"/></xsl:variable>
@@ -1633,16 +1869,16 @@
<xsl:variable name="app"
select="$m2a/mod2app/module[@name=$filepart]"/>
-->
- <xsl:variable name="reftext" select="text()"/>
+ <xsl:variable name="this" select="."/>
<xsl:for-each select="$m2a">
<xsl:variable name="app" select="key('mod2app', $filepart)"/>
<xsl:choose>
<xsl:when test="string-length($app) > 0">
- <span class="bold_code"><a href="javascript:erlhref('{$topdocdir}/../','{$app}','{$filepart}.html');"><xsl:value-of select="$reftext"/></a></span>
+ <span class="bold_code"><a href="javascript:erlhref('{$topdocdir}/../','{$app}','{$filepart}.html#{$linkpart}');"><xsl:value-of select="$this"/></a></span>
</xsl:when>
<xsl:otherwise>
<!-- Unknown application; no link -->
- <xsl:value-of select="$reftext"/>
+ <xsl:value-of select="$this"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
diff --git a/lib/erl_docgen/priv/xsl/db_man.xsl b/lib/erl_docgen/priv/xsl/db_man.xsl
index 2a8fb9fe3e..0aca74bc97 100644
--- a/lib/erl_docgen/priv/xsl/db_man.xsl
+++ b/lib/erl_docgen/priv/xsl/db_man.xsl
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
- # Copyright Ericsson AB 2009-2010. All Rights Reserved.
+ # Copyright Ericsson AB 2009-2011. All Rights Reserved.
#
# The 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,13 +21,16 @@
-->
<xsl:stylesheet version="1.0"
- xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ extension-element-prefixes="exsl">
- <xsl:preserve-space elements="code pre"/>
+ <xsl:preserve-space elements="code pre p"/>
<xsl:strip-space elements="*"/>
<xsl:output method="text" encoding="UTF-8" indent="no"/>
- <!-- Start of Dialyzer type/spec tags. See also the template matching "name"
+ <!-- Start of Dialyzer type/spec tags. See also the templates
+ matching "name", "seealso" and "br"
-->
<!-- Note: specs data for *one* module (as opposed to html and pdf) -->
@@ -35,38 +38,58 @@
<xsl:variable name="i" select="document($specs_file)"></xsl:variable>
<xsl:template name="err">
+ <xsl:param name="f"/>
<xsl:param name="m"/>
<xsl:param name="n"/>
<xsl:param name="a"/>
<xsl:param name="s"/>
<xsl:message terminate="yes">
- Error <xsl:if test="$m != ''"><xsl:value-of select ="$m"/>:</xsl:if>
- <xsl:value-of
- select="$n"/>/<xsl:value-of
- select="$a"/>: <xsl:value-of select="$s"/>
+ Error <xsl:if test="$f != ''">in <xsl:value-of select ="$f"/>:</xsl:if>
+ <xsl:if test="$m != ''"><xsl:value-of select ="$m"/>:</xsl:if>
+ <xsl:value-of select="$n"/>
+ <xsl:if test="$a != ''">/<xsl:value-of
+ select ="$a"/></xsl:if>: <xsl:value-of select="$s"/>
</xsl:message>
</xsl:template>
- <xsl:template name="spec_name">
+ <xsl:template name="find_spec">
<xsl:variable name="curModule" select="ancestor::erlref/module"/>
<xsl:variable name="mod" select="@mod"/>
<xsl:variable name="name" select="@name"/>
<xsl:variable name="arity" select="@arity"/>
- <xsl:variable name="clause" select="@clause"/>
+ <xsl:variable name="clause_i" select="@clause_i"/>
<xsl:variable name="spec0" select=
"$i/module[@name=$curModule]/spec
[name=$name and arity=$arity
and (string-length($mod) = 0 or module = $mod)]"/>
- <xsl:variable name="spec" select="$spec0[string-length($clause) = 0
- or position() = $clause]"/>
- <xsl:if test="count($spec) = 0">
+ <xsl:variable name="spec" select="$spec0[string-length($clause_i) = 0
+ or position() = $clause_i]"/>
+
+ <xsl:if test="count($spec) != 1">
+ <xsl:variable name="why">
+ <xsl:choose>
+ <xsl:when test="count($spec) > 1">ambiguous spec</xsl:when>
+ <xsl:when test="count($spec) = 0">unknown spec</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
<xsl:call-template name="err">
+ <xsl:with-param name="f" select="$curModule"/>
<xsl:with-param name="m" select="$mod"/>
<xsl:with-param name="n" select="$name"/>
<xsl:with-param name="a" select="$arity"/>
- <xsl:with-param name="s">unknown spec</xsl:with-param>
+ <xsl:with-param name="s" select="$why"/>
</xsl:call-template>
</xsl:if>
+ <xsl:copy-of select="$spec"/>
+ </xsl:template>
+
+ <xsl:template name="spec_name">
+ <xsl:variable name="name" select="@name"/>
+ <xsl:variable name="arity" select="@arity"/>
+ <xsl:variable name="spec0">
+ <xsl:call-template name="find_spec"/>
+ </xsl:variable>
+ <xsl:variable name="spec" select="exsl:node-set($spec0)/spec"/>
<xsl:choose>
<xsl:when test="ancestor::cref">
@@ -75,42 +98,12 @@
</xsl:message>
</xsl:when>
<xsl:when test="ancestor::erlref">
- <xsl:choose>
- <xsl:when test="string(@with_guards) = 'no'">
- <xsl:apply-templates select="$spec/contract/clause/head"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:call-template name="contract">
- <xsl:with-param name="contract" select="$spec/contract"/>
- </xsl:call-template>
- </xsl:otherwise>
- </xsl:choose>
+ <xsl:apply-templates select="$spec/contract/clause/head"/>
<xsl:text>&#10;.br</xsl:text>
</xsl:when>
</xsl:choose>
</xsl:template>
- <xsl:template name="contract">
- <xsl:param name="contract"/>
- <xsl:call-template name="clause">
- <xsl:with-param name="clause" select="$contract/clause"/>
- </xsl:call-template>
- </xsl:template>
-
- <xsl:template name="clause">
- <xsl:param name="clause"/>
- <xsl:variable name="type_desc" select="../type_desc"/>
- <xsl:for-each select="$clause">
- <xsl:apply-templates select="head"/>
- <xsl:if test="count(guard) > 0">
- <xsl:call-template name="guard">
- <xsl:with-param name="guard" select="guard"/>
- <xsl:with-param name="type_desc" select="$type_desc"/>
- </xsl:call-template>
- </xsl:if>
- </xsl:for-each>
- </xsl:template>
-
<xsl:template match="head">
<xsl:text>&#10;.nf&#10;</xsl:text>
<xsl:text>&#10;.B&#10;</xsl:text>
@@ -119,29 +112,147 @@
<xsl:text>&#10;.fi</xsl:text>
</xsl:template>
- <xsl:template name="guard">
- <xsl:param name="guard"/>
+ <!-- The *last* <name name="..." arity=".."/> -->
+ <xsl:template match="name" mode="types">
+ <xsl:variable name="name" select="@name"/>
+ <xsl:variable name="arity" select="@arity"/>
+ <xsl:variable name="spec0">
+ <xsl:call-template name="find_spec"/>
+ </xsl:variable>
+ <xsl:variable name="spec" select="exsl:node-set($spec0)/spec"/>
+ <xsl:variable name="clause" select="$spec/contract/clause"/>
+
+ <xsl:variable name="type_desc" select="../type_desc"/>
+ <!-- $type is data types to be presented as guards ("local types") -->
+ <xsl:variable name="type"
+ select="../type[string-length(@name) > 0
+ or string-length(@variable) > 0]"/>
+ <xsl:variable name="type_variables"
+ select ="$type[string-length(@variable) > 0]"/>
+ <xsl:variable name="local_types"
+ select ="$type[string-length(@name) > 0]"/>
+ <xsl:variable name="output_subtypes" select="count($type_variables) = 0"/>
+
+ <!-- It is assumed there is no support for overloaded specs
+ (there is no spec with more than one clause) -->
+ <xsl:if test="count($clause/guard) > 0 or count($type) > 0">
+ <xsl:text>&#10;.RS</xsl:text>
+ <xsl:text>&#10;.LP</xsl:text>
+ <xsl:text>&#10;Types:&#10;</xsl:text>
+ <xsl:text>&#10;.RS 3</xsl:text>
+
+ <xsl:choose>
+ <xsl:when test="$output_subtypes">
+ <xsl:call-template name="subtype">
+ <xsl:with-param name="subtype" select="$clause/guard/subtype"/>
+ <xsl:with-param name="type_desc" select="$type_desc"/>
+ <xsl:with-param name="local_types" select="$local_types"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="type_variables">
+ <xsl:with-param name="type_variables" select="$type_variables"/>
+ <xsl:with-param name="type_desc" select="$type_desc"/>
+ <xsl:with-param name="local_types" select="$local_types"/>
+ <xsl:with-param name="fname" select="$name"/>
+ <xsl:with-param name="arity" select="$arity"/>
+ </xsl:call-template>
+
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:call-template name="local_type">
+ <xsl:with-param name="type_desc" select="$type_desc"/>
+ <xsl:with-param name="local_types" select="$local_types"/>
+ </xsl:call-template>
+ <xsl:text>&#10;.RE</xsl:text>
+
+ <xsl:text>&#10;.RE</xsl:text>
+
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Handle <type variable="..." name_i="..."/> -->
+ <xsl:template name="type_variables">
+ <xsl:param name="type_variables"/>
<xsl:param name="type_desc"/>
- <xsl:text>&#10;.RS</xsl:text>
- <xsl:text>&#10;.TP</xsl:text>
- <xsl:text>&#10;Types</xsl:text>
- <xsl:call-template name="subtype">
- <xsl:with-param name="subtype" select="$guard/subtype"/>
- <xsl:with-param name="type_desc" select="$type_desc"/>
- </xsl:call-template>
- <xsl:text>&#10;.RE</xsl:text>
+ <xsl:param name="local_types"/>
+ <xsl:param name="fname"/>
+ <xsl:param name="arity"/>
+
+ <xsl:variable name="names" select="../name[string-length(@arity) > 0]"/>
+ <xsl:for-each select="$type_variables">
+ <xsl:variable name="name_i">
+ <xsl:choose>
+ <xsl:when test="string-length(@name_i) > 0">
+ <xsl:value-of select="@name_i"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="count($names)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="spec0">
+ <xsl:for-each select="$names[position() = $name_i]">
+ <xsl:call-template name="find_spec"/>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="spec" select="exsl:node-set($spec0)/spec"/>
+ <xsl:variable name="clause" select="$spec/contract/clause"/>
+ <xsl:variable name="variable" select="@variable"/>
+ <xsl:variable name="subtype"
+ select="$clause/guard/subtype[typename = $variable]"/>
+
+ <xsl:if test="count($subtype) = 0">
+ <xsl:call-template name="err">
+ <xsl:with-param name="f" select="ancestor::erlref/module"/>
+ <xsl:with-param name="n" select="$fname"/>
+ <xsl:with-param name="a" select="$arity"/>
+ <xsl:with-param name="s">unknown type variable <xsl:value-of select="$variable"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+
+ <xsl:call-template name="subtype">
+ <xsl:with-param name="subtype" select="$subtype"/>
+ <xsl:with-param name="type_desc" select="$type_desc"/>
+ </xsl:call-template>
+ </xsl:for-each>
</xsl:template>
<xsl:template name="subtype">
<xsl:param name="subtype"/>
<xsl:param name="type_desc"/>
+
<xsl:for-each select="$subtype">
<xsl:variable name="tname" select="typename"/>
- <xsl:variable name="tdesc" select="$type_desc[@name = $tname]"/>
- <xsl:text>&#10;</xsl:text>
- <xsl:apply-templates select="string"/>
- <xsl:text>&#10;.br</xsl:text>
- <xsl:apply-templates select="$type_desc[@name = $tname]"/>
+ <xsl:variable name="string" select="string"/>
+ <xsl:if test="string-length($string) > 0">
+ <xsl:text>&#10;</xsl:text>
+ <xsl:apply-templates select="$string"/>
+ <xsl:text>&#10;.br</xsl:text>
+ <xsl:apply-templates select="$type_desc[@variable = $tname]"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template name="local_type">
+ <xsl:param name="type_desc"/>
+ <xsl:param name="local_types"/>
+
+ <xsl:for-each select ="$local_types">
+ <xsl:text>&#10;</xsl:text>
+ <xsl:call-template name="type_name">
+ <xsl:with-param name="mode" select="'local_type'"/>
+ </xsl:call-template>
+ <xsl:text>&#10;.br</xsl:text>
+ <xsl:variable name="tname" select="@name"/>
+ <xsl:variable name="tnvars" select="@n_vars"/>
+ <xsl:apply-templates select=
+ "$type_desc[@name = $tname
+ and (@n_vars = $tnvars
+ or string-length(@n_vars) = 0 and
+ string-length($tnvars) = 0)]"/>
</xsl:for-each>
</xsl:template>
@@ -149,8 +260,8 @@
<!-- Similar to <d> -->
<xsl:template match="type_desc">
- <xsl:text>&#10;</xsl:text><xsl:apply-templates/>
- <xsl:text>&#10;.br</xsl:text>
+ <xsl:text>&#10;.RS 2&#10;</xsl:text><xsl:apply-templates/>
+ <xsl:text>&#10;.RE</xsl:text>
</xsl:template>
<!-- Datatypes -->
@@ -164,59 +275,46 @@
<xsl:apply-templates/>
</xsl:template>
- <xsl:template match="typehead">
- <xsl:text>&#10;.nf&#10;</xsl:text>
- <xsl:text>&#10;.B&#10;</xsl:text>
- <xsl:apply-templates/>
- <xsl:text>&#10;.br</xsl:text>
- <xsl:text>&#10;.fi</xsl:text>
- </xsl:template>
-
- <xsl:template match="local_defs">
- <xsl:text>&#10;.RS</xsl:text>
- <xsl:apply-templates/>
- <xsl:text>&#10;.RE</xsl:text>
- </xsl:template>
-
- <xsl:template match="local_def">
- <xsl:text>&#10;</xsl:text>
- <xsl:apply-templates/>
- <xsl:text>&#10;.br</xsl:text>
- </xsl:template>
-
<xsl:template name="type_name">
+ <xsl:param name="mode"/> <!-- '' if <datatype> -->
<xsl:variable name="curModule" select="ancestor::erlref/module"/>
<xsl:variable name="mod" select="@mod"/>
<xsl:variable name="name" select="@name"/>
- <xsl:variable name="n_vars">
- <xsl:choose>
- <xsl:when test="string-length(@n_vars) > 0">
- <xsl:value-of select="@n_vars"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="0"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
+ <xsl:variable name="n_vars" select="@n_vars"/>
<xsl:choose>
<xsl:when test="string-length($name) > 0">
<xsl:variable name="type" select=
"$i/module[@name=$curModule]/type
- [name=$name and n_vars=$n_vars
+ [name=$name
+ and (string-length($n_vars) = 0 or n_vars = $n_vars)
and (string-length($mod) = 0 or module = $mod)]"/>
<xsl:if test="count($type) != 1">
+ <xsl:variable name="why">
+ <xsl:choose>
+ <xsl:when test="count($type) > 1">ambiguous type</xsl:when>
+ <xsl:when test="count($type) = 0">unknown type</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
<xsl:call-template name="err">
+ <xsl:with-param name="f" select="$curModule"/>
<xsl:with-param name="m" select="$mod"/>
<xsl:with-param name="n" select="$name"/>
<xsl:with-param name="a" select="$n_vars"/>
- <xsl:with-param name="s">unknown type</xsl:with-param>
+ <xsl:with-param name="s" select="$why"/>
</xsl:call-template>
</xsl:if>
- <xsl:apply-templates select="$type/typedecl"/>
+ <xsl:choose>
+ <xsl:when test="$mode = ''">
+ <xsl:apply-templates select="$type/typedecl"/>
+ </xsl:when>
+ <xsl:when test="$mode = 'local_type'">
+ <xsl:apply-templates select="$type/typedecl" mode="local_type"/>
+ </xsl:when>
+ </xsl:choose>
</xsl:when>
- <xsl:otherwise>
+ <xsl:otherwise> <!-- <datatype> with <name> -->
<xsl:text>&#10;.nf&#10;</xsl:text>
<xsl:text>&#10;.B&#10;</xsl:text>
<xsl:apply-templates/>
@@ -226,68 +324,117 @@
</xsl:choose>
</xsl:template>
+ <xsl:template match="typehead">
+ <xsl:text>&#10;.nf&#10;&#10;</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>&#10;.br</xsl:text>
+ <xsl:text>&#10;.fi</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="typehead" mode="local_type">
+ <xsl:text>.nf&#10;</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>&#10;.fi</xsl:text>
+ </xsl:template>
+
+ <!-- Not used right now -->
+ <xsl:template match="local_defs">
+ <xsl:text>&#10;.RS</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>&#10;.RE</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="local_def">
+ <xsl:text>&#10;</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>&#10;.br</xsl:text>
+ </xsl:template>
+
+ <!-- The name of data types -->
+ <xsl:template match="marker">
+ <xsl:if test="string-length(.) != 0">
+ <xsl:text>\fB</xsl:text><xsl:apply-templates/><xsl:text>\fR\&amp;</xsl:text>
+ </xsl:if>
+ </xsl:template>
+
<!-- Used both in <datatype> and in <func>! -->
<xsl:template match="anno">
<xsl:variable name="curModule" select="ancestor::erlref/module"/>
<xsl:variable name="anno" select="normalize-space(text())"/>
<xsl:variable name="namespec"
- select="ancestor::desc/preceding-sibling::name"/>
+ select="ancestor::type_desc/preceding-sibling::name
+ | ancestor::desc/preceding-sibling::name"/>
<xsl:if test="count($namespec) = 0 and string-length($specs_file) > 0">
<xsl:call-template name="err">
- <xsl:with-param name="s">cannot find 'name' (<xsl:value-of select="$anno"/>)
+ <xsl:with-param name="f" select="$curModule"/>
+ <xsl:with-param name="s">cannot find tag 'name' (anno <xsl:value-of select="$anno"/>)
</xsl:with-param>
</xsl:call-template>
</xsl:if>
- <xsl:variable name="mod" select="$namespec/@mod"/>
- <xsl:variable name="name" select="$namespec/@name"/>
- <xsl:variable name="arity" select="$namespec/@arity"/>
- <xsl:variable name="clause" select="$namespec/@clause"/>
- <xsl:variable name="tmp_n_vars" select="$namespec/@n_vars"/>
- <xsl:variable name="n_vars">
- <xsl:choose>
- <xsl:when test="string-length($tmp_n_vars) > 0">
- <xsl:value-of select="$tmp_n_vars"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="0"/>
- </xsl:otherwise>
- </xsl:choose>
+ <!-- Search "local types" as well -->
+ <xsl:variable name="local_types"
+ select="ancestor::desc/preceding-sibling::type
+ [string-length(@name) > 0]
+ | ancestor::type_desc/preceding-sibling::type
+ [string-length(@name) > 0]"/>
+ <xsl:variable name="has_anno_in_local_type">
+ <xsl:for-each select="$local_types">
+ <xsl:call-template name="anno_name">
+ <xsl:with-param name="curModule" select="$curModule"/>
+ <xsl:with-param name="anno" select="$anno"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:variable name="has_anno">
+ <xsl:for-each select="$namespec">
+ <xsl:call-template name="anno_name">
+ <xsl:with-param name="curModule" select="$curModule"/>
+ <xsl:with-param name="anno" select="$anno"/>
+ </xsl:call-template>
+ </xsl:for-each>
</xsl:variable>
+
+ <xsl:if test="$has_anno = '' and $has_anno_in_local_type = ''">
+ <xsl:call-template name="err">
+ <xsl:with-param name="f" select="$curModule"/>
+ <xsl:with-param name="m" select="$namespec/@mod"/>
+ <xsl:with-param name="n" select="$namespec/@name"/>
+ <xsl:with-param name="a" select="'-'"/>
+ <xsl:with-param name="s">unknown annotation <xsl:value-of select="$anno"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:value-of select="$anno"/>
+ </xsl:template>
+
+ <xsl:template name="anno_name">
+ <xsl:param name="curModule"/>
+ <xsl:param name="anno"/>
+ <xsl:variable name="mod" select="@mod"/>
+ <xsl:variable name="name" select="@name"/>
+ <xsl:variable name="arity" select="@arity"/>
+ <xsl:variable name="n_vars" select="@n_vars"/>
+ <xsl:variable name="clause_i" select="@clause_i"/>
+
<xsl:variable name="spec0" select=
"$i/module[@name=$curModule]/spec
[name=$name and arity=$arity
and (string-length($mod) = 0 or module = $mod)]"/>
<xsl:variable name="spec_annos" select=
- "$spec0[string-length($clause) = 0
- or position() = $clause]/anno[.=$anno]"/>
+ "$spec0[string-length($clause_i) = 0
+ or position() = $clause_i]/anno[.=$anno]"/>
<xsl:variable name="type_annos" select=
"$i/module[@name=$curModule]/type
- [name=$name and n_vars=$n_vars
+ [name=$name
+ and (string-length($n_vars) = 0 or n_vars=$n_vars)
and (string-length($mod) = 0 or module = $mod)]/anno[.=$anno]"/>
-
- <xsl:if test="count($spec_annos) = 0
- and count($type_annos) = 0
- and string-length($specs_file) > 0">
- <xsl:variable name="n">
- <xsl:choose>
- <xsl:when test="string-length($arity) = 0">
- <xsl:value-of select="$n_vars"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="$arity"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <xsl:call-template name="err">
- <xsl:with-param name="m" select="$mod"/>
- <xsl:with-param name="n" select="$name"/>
- <xsl:with-param name="a" select="$n"/>
- <xsl:with-param name="s">unknown annotation <xsl:value-of select="$anno"/>
- </xsl:with-param>
- </xsl:call-template>
+ <xsl:if test="count($spec_annos) != 0
+ or count($type_annos) != 0
+ or string-length($specs_file) = 0">
+ <xsl:value-of select="true()"/>
</xsl:if>
- <xsl:value-of select="$anno"/>
</xsl:template>
<!-- Used for indentation of formatted types and specs -->
@@ -330,13 +477,13 @@
<xsl:text>&#10;.TP 2&#10;</xsl:text>
<xsl:text>*&#10;</xsl:text>
<xsl:apply-templates/>
- <xsl:text>&#10;.LP&#10;</xsl:text>
+ <xsl:text>&#10;.LP</xsl:text>
</xsl:template>
<xsl:template match="taglist">
<xsl:text>&#10;.RS 2</xsl:text>
<xsl:apply-templates select="tag|item"/>
- <xsl:text>&#10;.RE&#10;</xsl:text>
+ <xsl:text>&#10;.RE</xsl:text>
</xsl:template>
<xsl:template match="taglist/tag">
@@ -359,7 +506,7 @@
</xsl:when>
<xsl:otherwise>
<xsl:text>&#10;.RS 2</xsl:text>
- <xsl:text>&#10;.LP&#10;&#10;.LP&#10;</xsl:text>
+ <xsl:text>&#10;.LP&#10;</xsl:text>
<xsl:value-of select="$content"/>
<xsl:text>&#10;.RE</xsl:text>
</xsl:otherwise>
@@ -368,18 +515,42 @@
<!-- Note -->
<xsl:template match="note">
- <xsl:text>&#10;.SS Note:</xsl:text>
+ <xsl:text>&#10;.LP&#10;</xsl:text>
+ <xsl:text>&#10;.RS -4</xsl:text>
+ <xsl:text>&#10;.B&#10;</xsl:text>
+ <xsl:text>Note:</xsl:text>
+ <xsl:text>&#10;.RE</xsl:text>
<xsl:apply-templates/>
<xsl:text>&#10;</xsl:text>
</xsl:template>
<!-- Warning -->
<xsl:template match="warning">
- <xsl:text>&#10;.SS Warning:</xsl:text>
+ <xsl:text>&#10;.LP&#10;</xsl:text>
+ <xsl:text>&#10;.RS -4</xsl:text>
+ <xsl:text>&#10;.B&#10;</xsl:text>
+ <xsl:text>Warning:</xsl:text>
+ <xsl:text>&#10;.RE</xsl:text>
<xsl:apply-templates/>
<xsl:text>&#10;</xsl:text>
</xsl:template>
+ <xsl:template match="warning/p | note/p">
+ <xsl:variable name="content">
+ <xsl:text>&#10;</xsl:text>
+ <xsl:apply-templates/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="position() = 1">
+ <xsl:value-of select="$content"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>&#10;.LP</xsl:text>
+ <xsl:value-of select="$content"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
<!-- Paragraph -->
<xsl:template match="p">
<xsl:text>&#10;.LP&#10;</xsl:text>
@@ -394,7 +565,16 @@
</xsl:template>
<xsl:template match="br">
- <xsl:text>&#10;.br&#10;</xsl:text>
+ <xsl:choose>
+ <xsl:when test="ancestor::head">
+ <!-- The header of Dialyzer specs.
+ .B makes next line appear in bold face -->
+ <xsl:text>&#10;.B&#10;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>&#10;.br&#10;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
</xsl:template>
<xsl:template match="c">
@@ -412,17 +592,17 @@
<!-- Code -->
<xsl:template match="code">
<xsl:text>&#10;.LP&#10;</xsl:text>
- <xsl:text>&#10;.nf&#10;</xsl:text>
+ <xsl:text>.nf&#10;</xsl:text>
<xsl:apply-templates/>
- <xsl:text>&#10;.fi&#10;</xsl:text>
+ <xsl:text>&#10;.fi</xsl:text>
</xsl:template>
<!-- Pre -->
<xsl:template match="pre">
<xsl:text>&#10;.LP&#10;</xsl:text>
- <xsl:text>&#10;.nf&#10;</xsl:text>
+ <xsl:text>.nf&#10;</xsl:text>
<xsl:apply-templates/>
- <xsl:text>&#10;.fi&#10;</xsl:text>
+ <xsl:text>&#10;.fi</xsl:text>
</xsl:template>
@@ -542,6 +722,9 @@
<xsl:template match="func">
<xsl:text>&#10;.LP</xsl:text>
<xsl:apply-templates select="name"/>
+ <xsl:apply-templates
+ select="name[string-length(@arity) > 0 and position()=last()]"
+ mode="types"/>
<xsl:apply-templates select="fsummary|type|desc"/>
</xsl:template>
@@ -554,6 +737,11 @@
<xsl:when test="ancestor::datatype">
<xsl:call-template name="type_name"/>
</xsl:when>
+ <xsl:when test="string-length(text()) = 0 and ancestor::erlref">
+ <xsl:message terminate="yes">
+ Error <xsl:value-of select="@name"/>: arity is mandatory when referring to specifications!
+ </xsl:message>
+ </xsl:when>
<xsl:otherwise>
<xsl:call-template name="name"/>
</xsl:otherwise>
@@ -569,24 +757,29 @@
<!-- Type -->
<xsl:template match="type">
- <xsl:text>&#10;.RS</xsl:text>
- <xsl:text>&#10;.TP</xsl:text>
- <xsl:text>&#10;Types</xsl:text>
- <xsl:apply-templates/>
- <xsl:text>&#10;.RE</xsl:text>
+ <!-- The case where @name != 0 is taken care of in "type_name" -->
+ <xsl:if test="string-length(@name) = 0 and string-length(@variable) = 0">
+ <xsl:text>&#10;.RS</xsl:text>
+ <xsl:text>&#10;.LP</xsl:text>
+ <xsl:text>&#10;Types:&#10;</xsl:text>
+ <xsl:text>&#10;.RS 3</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>&#10;.RE</xsl:text>
+ <xsl:text>&#10;.RE</xsl:text>
+ </xsl:if>
</xsl:template>
<!-- V -->
<xsl:template match="v">
- <xsl:text>&#10;</xsl:text><xsl:value-of select="normalize-space(text())"/>
+ <xsl:text>&#10;</xsl:text><xsl:apply-templates/>
<xsl:text>&#10;.br</xsl:text>
</xsl:template>
<!-- D -->
<xsl:template match="d">
- <xsl:text>&#10;</xsl:text><xsl:apply-templates/>
- <xsl:text>&#10;.br</xsl:text>
+ <xsl:text>&#10;.RS 2&#10;</xsl:text><xsl:apply-templates/>
+ <xsl:text>&#10;.RE</xsl:text>
</xsl:template>
<!-- Desc -->
@@ -622,7 +815,7 @@
<xsl:text>&gt;</xsl:text>
</xsl:template>
- <!-- Do not noramlize any text within pre and code tags. -->
+ <!-- Do not normalize any text within pre and code tags. -->
<xsl:template match="pre/text()">
<xsl:call-template name="replace-string">
<xsl:with-param name="text" select="." />
@@ -642,7 +835,36 @@
<!-- Replace ' by \&' ans . by \&. -->
<xsl:template match="text()">
<xsl:variable name="startstring">
- <xsl:value-of select="normalize-space()"/><xsl:text> </xsl:text>
+ <xsl:value-of select="normalize-space()"/>
+ </xsl:variable>
+ <!-- 'C' is just any character but whitespace -->
+ <xsl:variable name="tmp" select="normalize-space(concat('C',.,'C'))"/>
+ <xsl:variable name="space_before">
+ <xsl:choose>
+ <!-- '<p>A<marker id="swamp"/> swamp</p>' does not work; instead:
+ '<p>A <marker id="swamp"/>swamp</p>' -->
+ <xsl:when test="starts-with($tmp, 'C ')
+ and not (string(preceding-sibling::*[position()=1]) = ''
+ and parent::p)">
+ <!-- and not (position() = 1 and parent::p)"> -->
+ <xsl:text> </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="space_after">
+ <xsl:choose>
+ <xsl:when test="substring($tmp, string-length($tmp)-1,1) = ' '
+ and $startstring != ''
+ and not (position() = last() and parent::p)">
+ <xsl:text> </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text/>
+ </xsl:otherwise>
+ </xsl:choose>
</xsl:variable>
<xsl:variable name="rep1">
<xsl:call-template name="replace-string">
@@ -658,11 +880,16 @@
<xsl:with-param name="with" select="&quot;\&amp;&apos;&quot;" />
</xsl:call-template>
</xsl:variable>
- <xsl:call-template name="replace-string">
- <xsl:with-param name="text" select="$rep2" />
- <xsl:with-param name="replace" select="&quot;.&quot;" />
- <xsl:with-param name="with" select="&quot;\&amp;.&quot;" />
- </xsl:call-template>
+ <xsl:variable name="reply">
+ <xsl:call-template name="replace-string">
+ <xsl:with-param name="text" select="$rep2" />
+ <xsl:with-param name="replace" select="&quot;.&quot;" />
+ <xsl:with-param name="with" select="&quot;\&amp;.&quot;" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$space_before"/>
+ <xsl:value-of select="$reply"/>
+ <xsl:value-of select="$space_after"/>
</xsl:template>
<!-- Template replace-string is borrowed at http://www.dpawson.co.uk/xsl/sect2/replace.html -->
diff --git a/lib/erl_docgen/priv/xsl/db_pdf.xsl b/lib/erl_docgen/priv/xsl/db_pdf.xsl
index f500cd3fee..48a7a026c1 100644
--- a/lib/erl_docgen/priv/xsl/db_pdf.xsl
+++ b/lib/erl_docgen/priv/xsl/db_pdf.xsl
@@ -21,6 +21,8 @@
-->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ extension-element-prefixes="exsl"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="xml" indent="yes"/>
@@ -28,45 +30,66 @@
<xsl:include href="db_pdf_params.xsl"/>
<!-- Start of Dialyzer type/spec tags.
- See also the template matching "name" and the template "bookmarks6"
+ See also the templates matching "name" and "seealso" as well as
+ the template "bookmarks6"
-->
<xsl:param name="specs_file" select="''"/>
<xsl:variable name="i" select="document($specs_file)"></xsl:variable>
<xsl:template name="err">
+ <xsl:param name="f"/>
<xsl:param name="m"/>
<xsl:param name="n"/>
<xsl:param name="a"/>
<xsl:param name="s"/>
<xsl:message terminate="yes">
- Error <xsl:if test="$m != ''"><xsl:value-of select ="$m"/>:</xsl:if>
- <xsl:value-of
- select="$n"/>/<xsl:value-of
- select="$a"/>: <xsl:value-of select="$s"/>
+ Error <xsl:if test="$f != ''">in <xsl:value-of select ="$f"/>:</xsl:if>
+ <xsl:if test="$m != ''"><xsl:value-of select ="$m"/>:</xsl:if>
+ <xsl:value-of select="$n"/>
+ <xsl:if test="$a != ''">/<xsl:value-of
+ select ="$a"/></xsl:if>: <xsl:value-of select="$s"/>
</xsl:message>
</xsl:template>
- <xsl:template name="spec_name">
+ <xsl:template name="find_spec">
<xsl:variable name="curModule" select="ancestor::erlref/module"/>
<xsl:variable name="mod" select="@mod"/>
<xsl:variable name="name" select="@name"/>
<xsl:variable name="arity" select="@arity"/>
- <xsl:variable name="clause" select="@clause"/>
+ <xsl:variable name="clause_i" select="@clause_i"/>
<xsl:variable name="spec0" select=
"$i/specs/module[@name=$curModule]/spec
[name=$name and arity=$arity
and (string-length($mod) = 0 or module = $mod)]"/>
- <xsl:variable name="spec" select="$spec0[string-length($clause) = 0
- or position() = $clause]"/>
- <xsl:if test="count($spec) = 0">
+ <xsl:variable name="spec" select="$spec0[string-length($clause_i) = 0
+ or position() = $clause_i]"/>
+
+ <xsl:if test="count($spec) != 1">
+ <xsl:variable name="why">
+ <xsl:choose>
+ <xsl:when test="count($spec) > 1">ambiguous spec</xsl:when>
+ <xsl:when test="count($spec) = 0">unknown spec</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
<xsl:call-template name="err">
+ <xsl:with-param name="f" select="$curModule"/>
<xsl:with-param name="m" select="$mod"/>
<xsl:with-param name="n" select="$name"/>
<xsl:with-param name="a" select="$arity"/>
- <xsl:with-param name="s">unknown spec</xsl:with-param>
+ <xsl:with-param name="s" select="$why"/>
</xsl:call-template>
</xsl:if>
+ <xsl:copy-of select="$spec"/>
+ </xsl:template>
+
+ <xsl:template name="spec_name">
+ <xsl:variable name="name" select="@name"/>
+ <xsl:variable name="arity" select="@arity"/>
+ <xsl:variable name="spec0">
+ <xsl:call-template name="find_spec"/>
+ </xsl:variable>
+ <xsl:variable name="spec" select="exsl:node-set($spec0)/spec"/>
<xsl:choose>
<xsl:when test="ancestor::cref">
@@ -76,78 +99,175 @@
</xsl:when>
<xsl:when test="ancestor::erlref">
<fo:block id="{generate-id()}">
- <xsl:choose>
- <xsl:when test="string(@with_guards) = 'no'">
- <xsl:apply-templates select="$spec/contract/clause/head"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:call-template name="contract">
- <xsl:with-param name="contract" select="$spec/contract"/>
- </xsl:call-template>
- </xsl:otherwise>
- </xsl:choose>
+ <xsl:apply-templates select="$spec/contract/clause/head"/>
</fo:block>
</xsl:when>
</xsl:choose>
</xsl:template>
- <xsl:template name="contract">
- <xsl:param name="contract"/>
- <xsl:call-template name="clause">
- <xsl:with-param name="clause" select="$contract/clause"/>
- </xsl:call-template>
+ <xsl:template match="head">
+ <fo:block xsl:use-attribute-sets="function-name">
+ <xsl:apply-templates/>
+ </fo:block>
</xsl:template>
- <xsl:template name="clause">
- <xsl:param name="clause"/>
+ <!-- The *last* <name name="..." arity=".."/> -->
+ <xsl:template match="name" mode="types">
+ <xsl:variable name="name" select="@name"/>
+ <xsl:variable name="arity" select="@arity"/>
+ <xsl:variable name="spec0">
+ <xsl:call-template name="find_spec"/>
+ </xsl:variable>
+ <xsl:variable name="spec" select="exsl:node-set($spec0)/spec"/>
+ <xsl:variable name="clause" select="$spec/contract/clause"/>
+
<xsl:variable name="type_desc" select="../type_desc"/>
- <xsl:for-each select="$clause">
- <xsl:apply-templates select="head"/>
- <xsl:if test="count(guard) > 0">
- <xsl:call-template name="guard">
- <xsl:with-param name="guard" select="guard"/>
+ <!-- $type is data types to be presented as guards ("local types") -->
+ <xsl:variable name="type"
+ select="../type[string-length(@name) > 0
+ or string-length(@variable) > 0]"/>
+ <xsl:variable name="type_variables"
+ select ="$type[string-length(@variable) > 0]"/>
+ <xsl:variable name="local_types"
+ select ="$type[string-length(@name) > 0]"/>
+ <xsl:variable name="output_subtypes" select="count($type_variables) = 0"/>
+
+ <!-- It is assumed there is no support for overloaded specs
+ (there is no spec with more than one clause) -->
+ <xsl:if test="count($clause/guard) > 0 or count($type) > 0">
+ <fo:block>
+ <xsl:text>Types:</xsl:text>
+ </fo:block>
+ <fo:list-block xsl:use-attribute-sets="type-listblock">
+ <xsl:choose>
+ <xsl:when test="$output_subtypes">
+ <xsl:call-template name="subtype">
+ <xsl:with-param name="subtype" select="$clause/guard/subtype"/>
+ <xsl:with-param name="type_desc" select="$type_desc"/>
+ <xsl:with-param name="local_types" select="$local_types"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="type_variables">
+ <xsl:with-param name="type_variables" select="$type_variables"/>
+ <xsl:with-param name="type_desc" select="$type_desc"/>
+ <xsl:with-param name="local_types" select="$local_types"/>
+ <xsl:with-param name="fname" select="$name"/>
+ <xsl:with-param name="arity" select="$arity"/>
+ </xsl:call-template>
+
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:call-template name="local_type">
<xsl:with-param name="type_desc" select="$type_desc"/>
+ <xsl:with-param name="local_types" select="$local_types"/>
</xsl:call-template>
- </xsl:if>
- </xsl:for-each>
+ </fo:list-block>
+ </xsl:if>
</xsl:template>
- <xsl:template match="head">
- <fo:block xsl:use-attribute-sets="function-name">
- <xsl:apply-templates/>
- </fo:block>
- </xsl:template>
+ <!-- Handle <type variable="..." name_i="..."/> -->
+ <xsl:template name="type_variables">
+ <xsl:param name="type_variables"/>
+ <xsl:param name="type_desc"/>
+ <xsl:param name="local_types"/>
+ <xsl:param name="fname"/>
+ <xsl:param name="arity"/>
+
+ <xsl:variable name="names" select="../name[string-length(@arity) > 0]"/>
+ <xsl:for-each select="$type_variables">
+ <xsl:variable name="name_i">
+ <xsl:choose>
+ <xsl:when test="string-length(@name_i) > 0">
+ <xsl:value-of select="@name_i"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="count($names)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="spec0">
+ <xsl:for-each select="$names[position() = $name_i]">
+ <xsl:call-template name="find_spec"/>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="spec" select="exsl:node-set($spec0)/spec"/>
+ <xsl:variable name="clause" select="$spec/contract/clause"/>
+ <xsl:variable name="variable" select="@variable"/>
+ <xsl:variable name="subtype"
+ select="$clause/guard/subtype[typename = $variable]"/>
+
+ <xsl:if test="count($subtype) = 0">
+ <xsl:call-template name="err">
+ <xsl:with-param name="f" select="ancestor::erlref/module"/>
+ <xsl:with-param name="n" select="$fname"/>
+ <xsl:with-param name="a" select="$arity"/>
+ <xsl:with-param name="s">unknown type variable <xsl:value-of select="$variable"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
- <xsl:template name="guard">
- <fo:block>
- <xsl:text>Types:</xsl:text>
- </fo:block>
- <fo:list-block xsl:use-attribute-sets="type-listblock">
<xsl:call-template name="subtype">
- <xsl:with-param name="subtype" select="$guard/subtype"/>
- <xsl:with-param name="type_desc" select="$type_desc"/>
+ <xsl:with-param name="subtype" select="$subtype"/>
+ <xsl:with-param name="type_desc" select="$type_desc"/>
</xsl:call-template>
- </fo:list-block>
+ </xsl:for-each>
</xsl:template>
+ <!-- Substituted
+ <fo:block xsl:use-attribute-sets="function-name">
+ for
+ <fo:block font-weight="bold">
+ to get proper indentation (a monospace font)
+ -->
<xsl:template name="subtype">
<xsl:param name="subtype"/>
<xsl:param name="type_desc"/>
+
<xsl:for-each select="$subtype">
<xsl:variable name="tname" select="typename"/>
- <xsl:variable name="tdesc" select="$type_desc[@name = $tname]"/>
<fo:list-item xsl:use-attribute-sets="type-listitem">
<fo:list-item-label end-indent="label-end()">
<fo:block>
</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()" format="justify">
- <fo:block font-weight="bold">
- <xsl:apply-templates select="string"/>
+ <fo:block xsl:use-attribute-sets="function-name">
+ <xsl:apply-templates select="string"/>
+ </fo:block>
+ </fo:list-item-body>
+ </fo:list-item>
+ <xsl:apply-templates select="$type_desc[@variable = $tname]"/>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template name="local_type">
+ <xsl:param name="type_desc"/>
+ <xsl:param name="local_types"/>
+
+ <xsl:for-each select="$local_types">
+ <fo:list-item xsl:use-attribute-sets="type-listitem">
+ <fo:list-item-label end-indent="label-end()">
+ <fo:block>
</fo:block>
+ </fo:list-item-label>
+ <fo:list-item-body start-indent="body-start()" format="justify">
+ <!-- <fo:block font-weight="bold">
+ (use function-name in "typehead" instead) -->
+ <xsl:call-template name="type_name">
+ <xsl:with-param name="mode" select="'local_type'"/>
+ </xsl:call-template>
+ <!-- </fo:block> -->
</fo:list-item-body>
</fo:list-item>
- <xsl:apply-templates select="$type_desc[@name = $tname]"/>
+ <xsl:variable name="tname" select="@name"/>
+ <xsl:variable name="tnvars" select="@n_vars"/>
+ <xsl:apply-templates select=
+ "$type_desc[@name = $tname
+ and (@n_vars = $tnvars
+ or string-length(@n_vars) = 0 and
+ string-length($tnvars) = 0)]"/>
</xsl:for-each>
</xsl:template>
@@ -182,6 +302,53 @@
<xsl:apply-templates select="desc"/>
</xsl:template>
+ <xsl:template name="type_name">
+ <xsl:param name="mode"/> <!-- '' if <datatype> -->
+ <xsl:variable name="curModule" select="ancestor::erlref/module"/>
+ <xsl:variable name="mod" select="@mod"/>
+ <xsl:variable name="name" select="@name"/>
+ <xsl:variable name="n_vars" select="@n_vars"/>
+
+ <xsl:choose>
+ <xsl:when test="string-length($name) > 0">
+ <xsl:variable name="type" select=
+ "$i/specs/module[@name=$curModule]/type
+ [name=$name
+ and (string-length($n_vars) = 0 or n_vars = $n_vars)
+ and (string-length($mod) = 0 or module = $mod)]"/>
+
+ <xsl:if test="count($type) != 1">
+ <xsl:variable name="why">
+ <xsl:choose>
+ <xsl:when test="count($type) > 1">ambiguous type</xsl:when>
+ <xsl:when test="count($type) = 0">unknown type</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="err">
+ <xsl:with-param name="f" select="$curModule"/>
+ <xsl:with-param name="m" select="$mod"/>
+ <xsl:with-param name="n" select="$name"/>
+ <xsl:with-param name="a" select="$n_vars"/>
+ <xsl:with-param name="s" select="$why"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="$mode = ''">
+ <xsl:apply-templates select="$type/typedecl"/>
+ </xsl:when>
+ <xsl:when test="$mode = 'local_type'">
+ <xsl:apply-templates select="$type/typedecl" mode="local_type"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <fo:inline font-weight="bold" xsl:use-attribute-sets="type-listitem">
+ <xsl:value-of select="."/>
+ </fo:inline>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
<!-- Like <head>... -->
<xsl:template match="typehead">
<fo:block xsl:use-attribute-sets="function-name">
@@ -189,6 +356,20 @@
</fo:block>
</xsl:template>
+ <!-- Substituted
+ <fo:block xsl:use-attribute-sets="function-name">
+ for
+ <fo:block font-weight="bold">
+ to get proper indentation (a monospace font)
+ -->
+
+ <xsl:template match="typehead" mode="local_type">
+ <fo:block xsl:use-attribute-sets="function-name">
+ <xsl:apply-templates/>
+ </fo:block>
+ </xsl:template>
+
+ <!-- Not used right now -->
<!-- Like <guard>, except "Types:"... -->
<xsl:template match="local_defs">
<fo:list-block xsl:use-attribute-sets="type-listblock">
@@ -211,108 +392,84 @@
</fo:list-item>
</xsl:template>
- <xsl:template name="type_name">
- <xsl:variable name="curModule" select="ancestor::erlref/module"/>
- <xsl:variable name="mod" select="@mod"/>
- <xsl:variable name="name" select="@name"/>
- <xsl:variable name="n_vars">
- <xsl:choose>
- <xsl:when test="string-length(@n_vars) > 0">
- <xsl:value-of select="@n_vars"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="0"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
-
- <xsl:choose>
- <xsl:when test="string-length($name) > 0">
- <xsl:variable name="type" select=
- "$i/specs/module[@name=$curModule]/type
- [name=$name and n_vars=$n_vars
- and (string-length($mod) = 0 or module = $mod)]"/>
-
- <xsl:if test="count($type) != 1">
- <xsl:call-template name="err">
- <xsl:with-param name="m" select="$mod"/>
- <xsl:with-param name="n" select="$name"/>
- <xsl:with-param name="a" select="$n_vars"/>
- <xsl:with-param name="s">unknown type</xsl:with-param>
- </xsl:call-template>
- </xsl:if>
- <xsl:apply-templates select="$type/typedecl"/>
- </xsl:when>
- <xsl:otherwise>
- <fo:inline font-weight="bold" xsl:use-attribute-sets="type-listitem">
- <xsl:value-of select="."/>
- </fo:inline>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:template>
-
<!-- Used both in <datatype> and in <func>! -->
<xsl:template match="anno">
<xsl:variable name="curModule" select="ancestor::erlref/module"/>
<xsl:variable name="anno" select="normalize-space(text())"/>
<xsl:variable name="namespec"
- select="ancestor::desc/preceding-sibling::name"/>
+ select="ancestor::type_desc/preceding-sibling::name
+ | ancestor::desc/preceding-sibling::name"/>
<xsl:if test="count($namespec) = 0 and string-length($specs_file) > 0">
<xsl:call-template name="err">
- <xsl:with-param name="s">cannot find 'name' (<xsl:value-of select="$anno"/>)
+ <xsl:with-param name="f" select="$curModule"/>
+ <xsl:with-param name="s">cannot find tag 'name' (anno <xsl:value-of select="$anno"/>)
</xsl:with-param>
</xsl:call-template>
</xsl:if>
- <xsl:variable name="mod" select="$namespec/@mod"/>
- <xsl:variable name="name" select="$namespec/@name"/>
- <xsl:variable name="arity" select="$namespec/@arity"/>
- <xsl:variable name="clause" select="$namespec/@clause"/>
- <xsl:variable name="tmp_n_vars" select="$namespec/@n_vars"/>
- <xsl:variable name="n_vars">
- <xsl:choose>
- <xsl:when test="string-length($tmp_n_vars) > 0">
- <xsl:value-of select="$tmp_n_vars"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="0"/>
- </xsl:otherwise>
- </xsl:choose>
+ <!-- Search "local types" as well -->
+ <xsl:variable name="local_types"
+ select="ancestor::desc/preceding-sibling::type
+ [string-length(@name) > 0]
+ | ancestor::type_desc/preceding-sibling::type
+ [string-length(@name) > 0]"/>
+ <xsl:variable name="has_anno_in_local_type">
+ <xsl:for-each select="$local_types">
+ <xsl:call-template name="anno_name">
+ <xsl:with-param name="curModule" select="$curModule"/>
+ <xsl:with-param name="anno" select="$anno"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:variable name="has_anno">
+ <xsl:for-each select="$namespec">
+ <xsl:call-template name="anno_name">
+ <xsl:with-param name="curModule" select="$curModule"/>
+ <xsl:with-param name="anno" select="$anno"/>
+ </xsl:call-template>
+ </xsl:for-each>
</xsl:variable>
+
+ <xsl:if test="$has_anno = '' and $has_anno_in_local_type = ''">
+ <xsl:call-template name="err">
+ <xsl:with-param name="f" select="$curModule"/>
+ <xsl:with-param name="m" select="$namespec/@mod"/>
+ <xsl:with-param name="n" select="$namespec/@name"/>
+ <xsl:with-param name="a" select="'-'"/>
+ <xsl:with-param name="s">unknown annotation <xsl:value-of select="$anno"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:value-of select="$anno"/>
+ </xsl:template>
+
+ <xsl:template name="anno_name">
+ <xsl:param name="curModule"/>
+ <xsl:param name="anno"/>
+ <xsl:variable name="mod" select="@mod"/>
+ <xsl:variable name="name" select="@name"/>
+ <xsl:variable name="arity" select="@arity"/>
+ <xsl:variable name="n_vars" select="@n_vars"/>
+ <xsl:variable name="clause_i" select="@clause_i"/>
+
<xsl:variable name="spec0" select=
"$i/specs/module[@name=$curModule]/spec
[name=$name and arity=$arity
and (string-length($mod) = 0 or module = $mod)]"/>
<xsl:variable name="spec_annos" select=
- "$spec0[string-length($clause) = 0
- or position() = $clause]/anno[.=$anno]"/>
+ "$spec0[string-length($clause_i) = 0
+ or position() = $clause_i]/anno[.=$anno]"/>
<xsl:variable name="type_annos" select=
"$i/specs/module[@name=$curModule]/type
- [name=$name and n_vars=$n_vars
+ [name=$name
+ and (string-length($n_vars) = 0 or n_vars=$n_vars)
and (string-length($mod) = 0 or module = $mod)]/anno[.=$anno]"/>
-
- <xsl:if test="count($spec_annos) = 0
- and count($type_annos) = 0
- and string-length($specs_file) > 0">
- <xsl:variable name="n">
- <xsl:choose>
- <xsl:when test="string-length($arity) = 0">
- <xsl:value-of select="$n_vars"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="$arity"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <xsl:call-template name="err">
- <xsl:with-param name="m" select="$mod"/>
- <xsl:with-param name="n" select="$name"/>
- <xsl:with-param name="a" select="$n"/>
- <xsl:with-param name="s">unknown annotation <xsl:value-of select="$anno"/>
- </xsl:with-param>
- </xsl:call-template>
+ <xsl:if test="count($spec_annos) != 0
+ or count($type_annos) != 0
+ or string-length($specs_file) = 0">
+ <xsl:value-of select="true()"/>
</xsl:if>
- <xsl:value-of select="$anno"/>
</xsl:template>
<!-- Used for indentation of formatted types and specs -->
@@ -575,22 +732,23 @@
<xsl:template name="bookmarks1">
<xsl:param name="entries"/>
<xsl:if test="$entries != ''">
+ <xsl:for-each select="$entries">
- <fo:bookmark internal-destination="{generate-id(/book/parts/part)}"
- starting-state="hide">
- <fo:bookmark-title>User's Guide</fo:bookmark-title>
-
- <xsl:for-each select="$entries">
+ <fo:bookmark internal-destination="{generate-id(header/title)}"
+ starting-state="hide">
+ <fo:bookmark-title><xsl:value-of select="header/title"/></fo:bookmark-title>
+
<xsl:call-template name="bookmarks2">
<xsl:with-param name="entries"
select="chapter[header/title]"/>
</xsl:call-template>
- </xsl:for-each>
-
- </fo:bookmark>
+
+ </fo:bookmark>
+ </xsl:for-each>
</xsl:if>
</xsl:template>
+
<xsl:template name="bookmarks2">
<xsl:param name="entries"/>
<xsl:for-each select="$entries">
@@ -777,9 +935,9 @@
<xsl:template match="part">
<xsl:variable name="partnum"><xsl:number level="any" from="book" count="part|application"/></xsl:variable>
- <fo:block xsl:use-attribute-sets="h1" id="{generate-id()}">
+ <fo:block xsl:use-attribute-sets="h1" id="{generate-id(header/title)}">
<xsl:value-of select="$partnum"/>&#160;&#160;&#160;
- <xsl:text>User's Guide</xsl:text>
+ <xsl:value-of select="header/title"/>
</fo:block>
<xsl:apply-templates select="description">
@@ -1225,13 +1383,15 @@
<!-- Func -->
<xsl:template match="func">
<xsl:param name="partnum"/>
-
- <xsl:apply-templates select="name"/>
-
- <xsl:apply-templates select="fsummary|type|desc">
- <xsl:with-param name="partnum" select="$partnum"/>
- </xsl:apply-templates>
-
+ <fo:block space-before="1.5em">
+ <xsl:apply-templates select="name"/>
+ <xsl:apply-templates
+ select="name[string-length(@arity) > 0 and position()=last()]"
+ mode="types"/>
+ <xsl:apply-templates select="fsummary|type|desc">
+ <xsl:with-param name="partnum" select="$partnum"/>
+ </xsl:apply-templates>
+ </fo:block>
</xsl:template>
@@ -1245,6 +1405,11 @@
<xsl:when test="ancestor::datatype">
<xsl:call-template name="type_name"/>
</xsl:when>
+ <xsl:when test="string-length(text()) = 0 and ancestor::erlref">
+ <xsl:message terminate="yes">
+ Error <xsl:value-of select="@name"/>: arity is mandatory when referring to specifications!
+ </xsl:message>
+ </xsl:when>
<xsl:otherwise>
<fo:block xsl:use-attribute-sets="function-name">
<xsl:call-template name="name">
@@ -1259,14 +1424,10 @@
<xsl:param name="partnum"/>
<xsl:choose>
<xsl:when test="ancestor::cref">
- <fo:block id="{generate-id(nametext)}">
- <xsl:value-of select="ret"/><xsl:text> </xsl:text><xsl:value-of select="nametext"/>
- </fo:block>
+ <fo:block id="{generate-id(nametext)}"><xsl:value-of select="ret"/><xsl:text></xsl:text><xsl:value-of select="nametext"/></fo:block>
</xsl:when>
<xsl:otherwise>
- <fo:block id="{generate-id(.)}">
- <xsl:value-of select="."/>
- </fo:block>
+ <fo:block id="{generate-id(.)}"><xsl:value-of select="."/></fo:block>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
@@ -1276,15 +1437,20 @@
<xsl:template match="type">
<xsl:param name="partnum"/>
- <fo:block>
- <xsl:text>Types:</xsl:text>
- </fo:block>
+ <!-- The case where @name != 0 is taken care of in "type_name" -->
+ <xsl:if test="string-length(@name) = 0 and string-length(@variable) = 0">
- <fo:list-block xsl:use-attribute-sets="type-listblock">
- <xsl:apply-templates>
- <xsl:with-param name="partnum" select="$partnum"/>
- </xsl:apply-templates>
- </fo:list-block>
+ <fo:block>
+ <xsl:text>Types:</xsl:text>
+ </fo:block>
+
+ <fo:list-block xsl:use-attribute-sets="type-listblock">
+ <xsl:apply-templates>
+ <xsl:with-param name="partnum" select="$partnum"/>
+ </xsl:apply-templates>
+ </fo:list-block>
+
+ </xsl:if>
</xsl:template>
@@ -1298,7 +1464,7 @@
</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()" format="justify">
- <fo:block font-weight="bold">
+ <fo:block font-weight="bold" font-family="monospace" >
<xsl:apply-templates>
<xsl:with-param name="partnum" select="$partnum"/>
</xsl:apply-templates>
@@ -1431,6 +1597,7 @@
</xsl:template>
+ <!-- Does not look at @n_vars -->
<xsl:template match="seealso">
<fo:inline font-style="italic">
<xsl:apply-templates/>
diff --git a/lib/erl_docgen/priv/xsl/db_pdf_params.xsl b/lib/erl_docgen/priv/xsl/db_pdf_params.xsl
index 7de20f2092..4d9c08d0c3 100644
--- a/lib/erl_docgen/priv/xsl/db_pdf_params.xsl
+++ b/lib/erl_docgen/priv/xsl/db_pdf_params.xsl
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
- # Copyright Ericsson AB 2009-2010. All Rights Reserved.
+ # Copyright Ericsson AB 2009-2011. All Rights Reserved.
#
# The 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 @@
<!-- Fixed strings -->
<xsl:variable name="companyname"><xsl:value-of select="/book/header/copyright/holder"/></xsl:variable>
- <xsl:variable name="copyright">Copyright &#169; <xsl:value-of select="/book/header/copyright/year[1]"/><xsl:text>-</xsl:text><xsl:value-of select="substring-after(substring-after($gendate, ' '), ' ')"/></xsl:variable>
+ <xsl:variable name="copyright">Copyright &#169; <xsl:value-of select="/book/header/copyright/year[1]"/><xsl:text>-</xsl:text><xsl:value-of select="substring-after(normalize-space(substring-after($gendate, ' ')), ' ')"/></xsl:variable>
<!-- FIXME: remove when appendix creation has been fixed -->
<!-- xsl:variable name="appendix_title"-->
@@ -316,8 +316,8 @@
<xsl:attribute name="font-family">monospace</xsl:attribute>
<!-- xsl:attribute name="font-size">0.8em</xsl:attribute -->
<xsl:attribute name="keep-with-next.within-page">always</xsl:attribute>
- <xsl:attribute name="space-after">0.3em</xsl:attribute>
- <xsl:attribute name="space-before">1.5em</xsl:attribute>
+ <xsl:attribute name="space-after">0.25em</xsl:attribute>
+ <!-- xsl:attribute name="space-before">1.5em</xsl:attribute -->
</xsl:attribute-set>
<xsl:attribute-set name="type-listblock">
diff --git a/lib/erl_docgen/src/otp_specs.erl b/lib/erl_docgen/src/otp_specs.erl
index 728ddb2e6e..edb437a942 100644
--- a/lib/erl_docgen/src/otp_specs.erl
+++ b/lib/erl_docgen/src/otp_specs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -380,6 +380,8 @@ t_type([E=#xmlElement{name = float}]) ->
t_float(E);
t_type([#xmlElement{name = nil}]) ->
t_nil();
+t_type([#xmlElement{name = paren, content = Es}]) ->
+ t_paren(Es);
t_type([#xmlElement{name = list, content = Es}]) ->
t_list(Es);
t_type([#xmlElement{name = nonempty_list, content = Es}]) ->
@@ -416,6 +418,9 @@ t_float(E) ->
t_nil() ->
["[]"].
+t_paren(Es) ->
+ ["("] ++ t_utype(get_elem(type, Es)) ++ [")"].
+
t_list(Es) ->
["["] ++ t_utype(get_elem(type, Es)) ++ ["]"].
@@ -532,6 +537,8 @@ ot_type([E=#xmlElement{name = float}]) ->
ot_float(E);
ot_type([#xmlElement{name = nil}]) ->
ot_nil();
+ot_type([#xmlElement{name = paren, content = Es}]) ->
+ ot_paren(Es);
ot_type([#xmlElement{name = list, content = Es}]) ->
ot_list(Es);
ot_type([#xmlElement{name = nonempty_list, content = Es}]) ->
@@ -582,6 +589,9 @@ ot_float(E) ->
ot_nil() ->
{nil,0}.
+ot_paren(Es) ->
+ {paren_type,0,[ot_utype(get_elem(type, Es))]}.
+
ot_list(Es) ->
{type,0,list,[ot_utype(get_elem(type, Es))]}.
@@ -697,5 +707,7 @@ annos_type([#xmlElement{name = union, content = Es}]) ->
lists:flatmap(fun annos_elem/1, Es);
annos_type([E=#xmlElement{name = typevar}]) ->
annos_elem(E);
+annos_type([#xmlElement{name = paren, content = Es}]) ->
+ annos(get_elem(type, Es));
annos_type(_) ->
[].
diff --git a/lib/erl_docgen/vsn.mk b/lib/erl_docgen/vsn.mk
index 29585d8520..79c8c570bf 100644
--- a/lib/erl_docgen/vsn.mk
+++ b/lib/erl_docgen/vsn.mk
@@ -1,2 +1,2 @@
-ERL_DOCGEN_VSN = 0.2.4
+ERL_DOCGEN_VSN = 0.2.6
diff --git a/lib/erl_interface/doc/src/ei.xml b/lib/erl_interface/doc/src/ei.xml
index de4e4b4301..539e16d837 100644
--- a/lib/erl_interface/doc/src/ei.xml
+++ b/lib/erl_interface/doc/src/ei.xml
@@ -4,7 +4,7 @@
<cref>
<header>
<copyright>
- <year>2001</year><year>2010</year>
+ <year>2001</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -581,9 +581,9 @@ ei_x_encode_empty_list(&amp;x);
<c><![CDATA[term]]></c> union, it is decoded, and the appropriate field
in <c><![CDATA[term->value]]></c> is set, and <c><![CDATA[*index]]></c> is
incremented by the term size.</p>
- <p>The function returns 0 on successful decoding, -1 on error,
- and 1 if the term seems alright, but does not fit in the
- <c><![CDATA[term]]></c> structure. If it returns 0, the <c><![CDATA[index]]></c>
+ <p>The function returns 1 on successful decoding, -1 on error,
+ and 0 if the term seems alright, but does not fit in the
+ <c><![CDATA[term]]></c> structure. If it returns 1, the <c><![CDATA[index]]></c>
will be incremented, and the <c><![CDATA[term]]></c> contains the
decoded term.</p>
<p>The <c><![CDATA[term]]></c> structure will contain the arity for a tuple
diff --git a/lib/erl_interface/doc/src/erl_format.xml b/lib/erl_interface/doc/src/erl_format.xml
index 5699485845..f036b12879 100644
--- a/lib/erl_interface/doc/src/erl_format.xml
+++ b/lib/erl_interface/doc/src/erl_format.xml
@@ -4,7 +4,7 @@
<cref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -105,7 +105,7 @@ erl_format("[{name,~a},{age,~i},{data,~w}]",
values in <c><![CDATA[Term]]></c>. </p>
<p>If <c><![CDATA[Term]]></c> and <c><![CDATA[Pattern]]></c> can be matched, the
function returns a non-zero value and binds any unbound
- variables in <c><![CDATA[Pattern]]></c>. If <c><![CDATA[Term]]></c><c><![CDATA[Pattern]]></c> do
+ variables in <c><![CDATA[Pattern]]></c>. If <c><![CDATA[Term]]></c> <c><![CDATA[Pattern]]></c> do
not match, the function returns 0. For example:</p>
<code type="none"><![CDATA[
ETERM *term, *pattern, *pattern2;
diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml
index 784ba78d3e..9a42ebfddf 100644
--- a/lib/erl_interface/doc/src/notes.xml
+++ b/lib/erl_interface/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,6 +30,89 @@
</header>
<p>This document describes the changes made to the Erl_interface application.</p>
+<section><title>Erl_Interface 3.7.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Align ei buffer according to size of pointers</p>
+ <p>
+ Own Id: OTP-9390</p>
+ </item>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ <item>
+ <p>
+ Make comment and documentation reflect code in
+ erl_interface/src/misc/ei_decode_term.c (Thanks to Anneli
+ Cuss)</p>
+ <p>
+ Own Id: OTP-9559</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ ei: integer overflow in string/atom encoding</p>
+ <p>
+ ei_encode_atom() and ei_encode_string() use strlen() to
+ get the length of the buffer. As strlen() returns an
+ unsigned long long and both ei functions take a signed
+ integer, the length fields may overflow.</p>
+ <p>
+ Check so that the results of strlen can be held in a
+ signed integer. (Thanks to Michael Santos)</p>
+ <p>
+ Own Id: OTP-9530</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Interface 3.7.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix using sizeof() for array given as function argument</p>
+ <p>
+ When using the sizeof() operator for an array given as
+ function argument it returns the size of the pointer. In
+ this case, the affected function hex(char digest[16],
+ char buff[33]) will just print 4 or 8 byte instead of the
+ full length of 16 bytes, on 32bit and 64bit systems
+ respectively. (Thanks to Cristian greco)</p>
+ <p>
+ Own Id: OTP-9151</p>
+ </item>
+ <item>
+ <p>
+ Initialize <c>to</c> and <c>to_name</c> in
+ <c>erl_receive_msg</c>. (Thanks to G�ran Larsson)</p>
+ <p>
+ Own Id: OTP-9241</p>
+ </item>
+ <item>
+ <p>
+ erl_interface: fix compile error(Thanks to Michael
+ Santos)</p>
+ <p>
+ Own Id: OTP-9252</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erl_Interface 3.7.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/erl_interface/src/Makefile.in b/lib/erl_interface/src/Makefile.in
index 8ff142a366..0d841cfa48 100644
--- a/lib/erl_interface/src/Makefile.in
+++ b/lib/erl_interface/src/Makefile.in
@@ -143,7 +143,6 @@ BINDIR = $(ERL_TOP)/lib/erl_interface/bin/$(TARGET)
vpath %.c connect:encode:decode:misc:epmd:legacy:registry
-
###########################################################################
# List targets
###########################################################################
@@ -202,11 +201,6 @@ ifeq ($(USING_VC),yes)
# Windows targets
TARGETS = \
- $(BINDIR) \
- $(OBJDIR) \
- $(MT_OBJDIR) \
- $(MD_OBJDIR) \
- $(MDD_OBJDIR) \
$(OBJ_TARGETS) \
$(EXE_TARGETS)
@@ -236,9 +230,6 @@ else
ifeq ($USING_MINGW,yes)
TARGETS = \
- $(BINDIR) \
- $(OBJDIR) \
- $(MD_OBJDIR) \
$(OBJ_TARGETS) \
$(EXE_TARGETS)
@@ -257,10 +248,6 @@ else
ifdef THR_DEFS
TARGETS = \
- $(BINDIR) \
- $(OBJDIR) \
- $(ST_OBJDIR) \
- $(MT_OBJDIR) \
$(OBJ_TARGETS) \
$(EXE_TARGETS)
@@ -283,9 +270,6 @@ FAKE_TARGETS = \
else
TARGETS = \
- $(BINDIR) \
- $(OBJDIR) \
- $(ST_OBJDIR) \
$(OBJ_TARGETS) \
$(EXE_TARGETS)
@@ -601,23 +585,7 @@ $(MDD_OBJDIR)/%.o: %.c
# Create directories
###########################################################################
-$(BINDIR):
- mkdir -p $(BINDIR)
-
-$(OBJDIR):
- mkdir -p $(OBJDIR)
-
-$(ST_OBJDIR):
- mkdir -p $(ST_OBJDIR)
-
-$(MT_OBJDIR):
- mkdir -p $(MT_OBJDIR)
-
-$(MD_OBJDIR):
- mkdir -p $(MD_OBJDIR)
-
-$(MDD_OBJDIR):
- mkdir -p $(MDD_OBJDIR)
+_create_dirs := $(shell mkdir -p $(BINDIR) $(OBJDIR) $(ST_OBJDIR) $(MT_OBJDIR) $(MD_OBJDIR) $(MDD_OBJDIR))
###########################################################################
# Special rules
diff --git a/lib/erl_interface/src/connect/ei_resolve.c b/lib/erl_interface/src/connect/ei_resolve.c
index 50c5a4161d..ba8f8fbce3 100644
--- a/lib/erl_interface/src/connect/ei_resolve.c
+++ b/lib/erl_interface/src/connect/ei_resolve.c
@@ -185,7 +185,12 @@ static int verify_dns_configuration(void)
* align: increment buf until it is dword-aligned, reduce len by same amount.
* advance: increment buf by n bytes, reduce len by same amount .
*/
-#define align_buf(buf,len) for (;(((unsigned)buf)&0x3); (buf)++, len--)
+#if defined SIZEOF_VOID_P
+#define ALIGNBYTES (SIZEOF_VOID_P - 1)
+#else
+#define ALIGNBYTES (sizeof(void*) - 1)
+#endif
+#define align_buf(buf,len) for (;(((unsigned)buf) & ALIGNBYTES); (buf)++, len--)
#define advance_buf(buf,len,n) ((buf)+=(n),(len)-=(n))
/* "and now the tricky part..." */
diff --git a/lib/erl_interface/src/encode/encode_atom.c b/lib/erl_interface/src/encode/encode_atom.c
index 69f2d1451c..6f41f045e0 100644
--- a/lib/erl_interface/src/encode/encode_atom.c
+++ b/lib/erl_interface/src/encode/encode_atom.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2011. All Rights Reserved.
*
* The 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,13 +17,17 @@
* %CopyrightEnd%
*/
#include <string.h>
+#include <limits.h>
#include "eidef.h"
#include "eiext.h"
#include "putget.h"
int ei_encode_atom(char *buf, int *index, const char *p)
{
- return ei_encode_atom_len(buf, index, p, strlen(p));
+ size_t len = strlen(p);
+
+ if (len >= INT_MAX) return -1;
+ return ei_encode_atom_len(buf, index, p, len);
}
int ei_encode_atom_len(char *buf, int *index, const char *p, int len)
diff --git a/lib/erl_interface/src/encode/encode_string.c b/lib/erl_interface/src/encode/encode_string.c
index 1d342cb605..d00d2f3e81 100644
--- a/lib/erl_interface/src/encode/encode_string.c
+++ b/lib/erl_interface/src/encode/encode_string.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2011. All Rights Reserved.
*
* The 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,6 +17,7 @@
* %CopyrightEnd%
*/
#include <string.h>
+#include <limits.h>
#include "eidef.h"
#include "eiext.h"
#include "putget.h"
@@ -24,7 +25,10 @@
int ei_encode_string(char *buf, int *index, const char *p)
{
- return ei_encode_string_len(buf, index, p, strlen(p));
+ size_t len = strlen(p);
+
+ if (len >= INT_MAX) return -1;
+ return ei_encode_string_len(buf, index, p, len);
}
int ei_encode_string_len(char *buf, int *index, const char *p, int len)
diff --git a/lib/erl_interface/src/epmd/epmd_port.c b/lib/erl_interface/src/epmd/epmd_port.c
index 698c75c217..a433815eb7 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-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -228,11 +228,8 @@ int ei_epmd_port (struct in_addr *addr, const char *alive, int *dist)
return ei_epmd_port_tmo (addr, alive, dist, 0);
}
-int ei_epmd_port_tmo (struct in_addr *addr, const char *alive, int *dist,
- unsigned ms)
+int ei_epmd_port_tmo (struct in_addr *addr, const char *alive, int *dist, unsigned ms)
{
- int i;
-
- return ei_epmd_r4_port(addr,alive,dist,ms);
+ return ei_epmd_r4_port(addr,alive,dist,ms);
}
diff --git a/lib/erl_interface/src/legacy/erl_connect.c b/lib/erl_interface/src/legacy/erl_connect.c
index fdf689e191..41d4fa3138 100644
--- a/lib/erl_interface/src/legacy/erl_connect.c
+++ b/lib/erl_interface/src/legacy/erl_connect.c
@@ -293,8 +293,13 @@ static int erl_do_receive_msg(int fd, ei_x_buff* x, ErlMessage* emsg)
emsg->msg = NULL;
if (msg.from.node[0] != '\0')
emsg->from = erl_mk_pid(msg.from.node, msg.from.num, msg.from.serial, msg.from.creation);
+ else
+ emsg->from = NULL;
if (msg.to.node[0] != '\0')
emsg->to = erl_mk_pid(msg.to.node, msg.to.num, msg.to.serial, msg.to.creation);
+ else
+ emsg->to = NULL;
+ memcpy(emsg->to_name, msg.toname, MAXATOMLEN+1);
return r;
}
diff --git a/lib/erl_interface/src/legacy/erl_fix_alloc.c b/lib/erl_interface/src/legacy/erl_fix_alloc.c
index 20f3024e41..2ed0dd1470 100644
--- a/lib/erl_interface/src/legacy/erl_fix_alloc.c
+++ b/lib/erl_interface/src/legacy/erl_fix_alloc.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -109,6 +109,10 @@ void *erl_eterm_alloc (void)
erl_eterm_state->freed--;
} else if ((b = malloc(sizeof(*b))) == NULL) {
erl_errno = ENOMEM;
+#ifdef _REENTRANT
+ ei_mutex_unlock(erl_eterm_state->lock);
+#endif /* _REENTRANT */
+ return NULL;
}
erl_eterm_state->allocated++;
b->free = 0;
diff --git a/lib/erl_interface/src/legacy/erl_timeout.c b/lib/erl_interface/src/legacy/erl_timeout.c
index d9560eebc8..146a106e7c 100644
--- a/lib/erl_interface/src/legacy/erl_timeout.c
+++ b/lib/erl_interface/src/legacy/erl_timeout.c
@@ -43,6 +43,7 @@
# endif
#endif
+#include "erl_interface.h"
#include "erl_timeout.h"
typedef struct jmp_s {
diff --git a/lib/erl_interface/src/misc/ei_decode_term.c b/lib/erl_interface/src/misc/ei_decode_term.c
index bfb4571337..0b82ef0e35 100644
--- a/lib/erl_interface/src/misc/ei_decode_term.c
+++ b/lib/erl_interface/src/misc/ei_decode_term.c
@@ -25,8 +25,8 @@
#include "ei_decode_term.h"
#include "putget.h"
-/* Returns 0 on successful encoding, -1 on error, and 1 if the term seems
- alright, but does not fit in the term structure. If it returns 0, the
+/* Returns 1 on successful encoding, -1 on error, and 0 if the term seems
+ alright, but does not fit in the term structure. If it returns 1, the
index will be incremented, and the term contains the decoded term. */
int ei_decode_ei_term(const char* buf, int* index, ei_term* term)
@@ -111,10 +111,10 @@ int ei_decode_ei_term(const char* buf, int* index, ei_term* term)
break;
case ERL_SMALL_TUPLE_EXT:
term->arity = get8(s);
- break; /*return 0;*/
+ break;
case ERL_LARGE_TUPLE_EXT:
term->arity = get32be(s);
- break; /*return 0;*/
+ break;
case ERL_NIL_EXT:
term->arity = 0;
break;
@@ -123,7 +123,7 @@ int ei_decode_ei_term(const char* buf, int* index, ei_term* term)
return 0;
case ERL_LIST_EXT:
term->arity = get32be(s);
- break; /*return 0;*/
+ break;
case ERL_BINARY_EXT:
term->size = get32be(s);
return 0;
diff --git a/lib/erl_interface/src/registry/reg_dump.c b/lib/erl_interface/src/registry/reg_dump.c
index 1e640fb506..d2854c10b5 100644
--- a/lib/erl_interface/src/registry/reg_dump.c
+++ b/lib/erl_interface/src/registry/reg_dump.c
@@ -215,6 +215,7 @@ static int mn_send_write(int fd, erlang_pid *mnesia, const char *key, ei_reg_obj
else ei_encode_long(msgbuf,&index,(long)(obj->val.p)); /* just the pointer */
break;
default:
+ if (dbuf) free(dbuf);
return -1;
}
diff --git a/lib/erl_interface/src/registry/reg_restore.c b/lib/erl_interface/src/registry/reg_restore.c
index 765c3f4314..7bc1c758af 100644
--- a/lib/erl_interface/src/registry/reg_restore.c
+++ b/lib/erl_interface/src/registry/reg_restore.c
@@ -303,6 +303,9 @@ int ei_reg_restore(int fd, ei_reg *reg, const char *mntab)
if (mn_decode_insert(reg,msgbuf,&index,keybuf)) goto restore_failure;
}
+ if (keybuf) free(keybuf);
+ if (dbuf) free(dbuf);
+
/* wait for unlink */
if (mn_unlink(fd)) return -1;
@@ -310,8 +313,6 @@ int ei_reg_restore(int fd, ei_reg *reg, const char *mntab)
ei_hash_foreach(reg->tab,clean_obj);
/* success */
- if (keybuf) free(keybuf);
- if (dbuf) free(dbuf);
return 0;
restore_failure:
diff --git a/lib/erl_interface/test/Makefile b/lib/erl_interface/test/Makefile
index 8ed6834443..4faf89c0d6 100644
--- a/lib/erl_interface/test/Makefile
+++ b/lib/erl_interface/test/Makefile
@@ -73,7 +73,7 @@ release_spec:
release_tests_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(SPEC_FILES) $(COVER_FILE) $(ERL_FILES) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/erl_interface/test/all_SUITE_data/Makefile.src b/lib/erl_interface/test/all_SUITE_data/Makefile.src
index 9be2360656..42d4c6f27f 100644
--- a/lib/erl_interface/test/all_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/all_SUITE_data/Makefile.src
@@ -30,6 +30,8 @@ CHMOD=chmod
all: $(ALL_OBJS)
+$(EI_COMMON_OBJS): gccifier@exe@
+
@IFEQ@ (@erl_interface_cross_compile@, true)
gccifier@exe@:
$(CP) gccifier.sh gccifier@exe@
diff --git a/lib/erl_interface/test/port_call_SUITE_data/Makefile.src b/lib/erl_interface/test/port_call_SUITE_data/Makefile.src
index dc7385ba32..a512494aa3 100644
--- a/lib/erl_interface/test/port_call_SUITE_data/Makefile.src
+++ b/lib/erl_interface/test/port_call_SUITE_data/Makefile.src
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2009. All Rights Reserved.
+# Copyright Ericsson AB 2001-2011. All Rights Reserved.
#
# The 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,7 +26,7 @@ LIBPATH = @erl_interface_libpath@
LIBERL = $(LIBPATH)/@erl_interface_lib_drv@
LIBEI = $(LIBPATH)/@erl_interface_eilib_drv@
-SHLIB_EXTRA_LDLIBS = $(LIBERL) $(LIBEI)
+SHLIB_EXTRA_LDLIBS = $(LIBERL) $(LIBEI) @erl_interface_threadlib@
SHLIB_EXTRA_CFLAGS = -I@erl_interface_include@ -I../all_SUITE_data
diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk
index 0317462106..601958579c 100644
--- a/lib/erl_interface/vsn.mk
+++ b/lib/erl_interface/vsn.mk
@@ -1 +1 @@
-EI_VSN = 3.7.3
+EI_VSN = 3.7.5
diff --git a/lib/et/doc/src/notes.xml b/lib/et/doc/src/notes.xml
index cd4787c5e7..acc6120fcd 100644
--- a/lib/et/doc/src/notes.xml
+++ b/lib/et/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2002</year><year>2010</year>
+ <year>2002</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -36,6 +36,36 @@
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.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Dialyzer warnings have been fixed. </p>
+ <p>
+ Own Id: OTP-9470</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>ET 1.4.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The popup window 'contents viewer' did not display
+ properly on Windows.</p>
+ <p>
+ Own Id: OTP-9238</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>ET 1.4.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/et/src/et_wx_contents_viewer.erl b/lib/et/src/et_wx_contents_viewer.erl
index aada184a76..86f46f25d0 100644
--- a/lib/et/src/et_wx_contents_viewer.erl
+++ b/lib/et/src/et_wx_contents_viewer.erl
@@ -464,7 +464,8 @@ create_window(S) ->
wxFrame:setMenuBar(Frame,Bar),
create_file_menu(Bar),
Editor = wxTextCtrl:new(Panel, ?wxID_ANY, [{style, 0
- bor ?wxDEFAULT
+ bor ?wxDEFAULT
+ bor ?wxTE_RICH2 %% Needed on Windows
bor ?wxTE_MULTILINE
bor ?wxTE_READONLY
bor ?wxTE_DONTWRAP}]),
@@ -483,6 +484,7 @@ create_window(S) ->
wxFrame:connect(Frame, close_window, [{skip,true}]),
wxFrame:setFocus(Frame),
wxPanel:setSizer(Panel, Sizer),
+ wxSizer:fit(Sizer, Panel),
wxFrame:show(Frame),
S2#state{menu_data = HideData++SearchData++FilterData, editor = Editor, frame = Frame}.
diff --git a/lib/et/src/et_wx_viewer.erl b/lib/et/src/et_wx_viewer.erl
index d42f8c0c86..386f8fc86b 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-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -257,10 +257,10 @@ parse_opt([H | T], S, CollectorOpt) ->
Actors = [create_actor(Name) || Name <- ActorNames2],
parse_opt(T, S#state{actors = Actors}, CollectorOpt);
{include, ActorNames} when is_list(ActorNames) ->
- Actors = [opt_create_actor(Name, include, S#state.actors) || Name <- ActorNames],
+ Actors = [opt_create_actor(Name, include, S) || Name <- ActorNames],
parse_opt(T, S#state{actors = Actors}, CollectorOpt);
{exclude, ActorNames} when is_list(ActorNames) ->
- Actors = [opt_create_actor(Name, exclude, S#state.actors) || Name <- ActorNames],
+ Actors = [opt_create_actor(Name, exclude, S) || Name <- ActorNames],
parse_opt(T, S#state{actors = Actors}, CollectorOpt);
{first_event, _FirstKey} ->
%% NYI
@@ -846,9 +846,6 @@ handle_info(#wx{event = #wxSize{size = {OldW, OldH}}} = Wx, S) ->
refresh_main_window(S4)
end,
noreply(S6);
-handle_info(#wx{event = #wxFocus{}}, S) ->
- wxWindow:setFocus(S#state.canvas), % Get keyboard focus
- noreply(S);
handle_info(#wx{event = #wxMouse{type = enter_window}}, S) ->
wxWindow:setFocus(S#state.canvas), % Get keyboard focus
noreply(S);
@@ -1252,7 +1249,6 @@ create_main_window(S) ->
Self ! Ev
end}]),
wxPanel:connect(Canvas, key_down),
- wxPanel:connect(Canvas, kill_focus),
wxPanel:connect(Canvas, enter_window, [{skip, true}]),
wxFrame:connect(Frame, command_menu_selected),
wxFrame:connect(Frame, close_window),
diff --git a/lib/et/test/Makefile b/lib/et/test/Makefile
index 9a24e3281b..e10a2a1587 100644
--- a/lib/et/test/Makefile
+++ b/lib/et/test/Makefile
@@ -74,7 +74,7 @@ release_tests_spec: opt
$(INSTALL_DATA) et.spec et.cover $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)
$(INSTALL_SCRIPT) ett $(RELSYSDIR)
$(INSTALL_DATA) $(INSTALL_PROGS) $(RELSYSDIR)
-# chmod -f -R u+w $(RELSYSDIR)
+# chmod -R u+w $(RELSYSDIR)
# @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/et/vsn.mk b/lib/et/vsn.mk
index d7cfd7bc84..239a72ad73 100644
--- a/lib/et/vsn.mk
+++ b/lib/et/vsn.mk
@@ -1 +1 @@
-ET_VSN = 1.4.2
+ET_VSN = 1.4.4
diff --git a/lib/eunit/AUTHORS b/lib/eunit/AUTHORS
deleted file mode 100644
index b7c1426aff..0000000000
--- a/lib/eunit/AUTHORS
+++ /dev/null
@@ -1,2 +0,0 @@
-Richard Carlsson <[email protected]>
-Micka�l R�mond <[email protected]>
diff --git a/lib/eunit/Makefile b/lib/eunit/Makefile
index ee69d5e8e0..cd85dff06a 100644
--- a/lib/eunit/Makefile
+++ b/lib/eunit/Makefile
@@ -13,8 +13,6 @@
# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
# AB. All Rights Reserved.''
#
-# $Id$
-#
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
diff --git a/lib/eunit/doc/.gitignore b/lib/eunit/doc/.gitignore
new file mode 100644
index 0000000000..7fcda5db42
--- /dev/null
+++ b/lib/eunit/doc/.gitignore
@@ -0,0 +1,4 @@
+*.html
+stylesheet.css
+erlang.png
+edoc-info
diff --git a/lib/eunit/doc/edoc-info b/lib/eunit/doc/edoc-info
deleted file mode 100644
index 1c04b2ed1a..0000000000
--- a/lib/eunit/doc/edoc-info
+++ /dev/null
@@ -1,3 +0,0 @@
-{application,eunit}.
-{packages,[]}.
-{modules,[eunit,eunit_surefire]}.
diff --git a/lib/eunit/doc/erlang.png b/lib/eunit/doc/erlang.png
deleted file mode 100644
index 987a618e24..0000000000
--- a/lib/eunit/doc/erlang.png
+++ /dev/null
Binary files differ
diff --git a/lib/eunit/doc/eunit.html b/lib/eunit/doc/eunit.html
deleted file mode 100644
index a181d12ce3..0000000000
--- a/lib/eunit/doc/eunit.html
+++ /dev/null
@@ -1,71 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<title>Module eunit</title>
-<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
-</head>
-<body bgcolor="white">
-<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
-<hr>
-
-<h1>Module eunit</h1>
-<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>This module is the main EUnit user interface.
-<p>Copyright � 2004-2009 Micka�l R�mond, Richard Carlsson</p>
-
-<p><b>Version:</b> 2.1.1, Apr 22 2009 22:37:19</p>
-<p><b>Authors:</b> Micka�l R�mond (<a href="mailto:[email protected]"><tt>[email protected]</tt></a>) [<em>web site:</em> <tt><a href="http://www.process-one.net/" target="_top">http://www.process-one.net/</a></tt>], Richard Carlsson (<a href="mailto:[email protected]"><tt>[email protected]</tt></a>) [<em>web site:</em> <tt><a href="http://user.it.uu.se/~richardc/" target="_top">http://user.it.uu.se/~richardc/</a></tt>].</p>
-
-<h2><a name="description">Description</a></h2>This module is the main EUnit user interface.
-<h2><a name="index">Function Index</a></h2>
-<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#start-0">start/0</a></td><td>Starts the EUnit server.</td></tr>
-<tr><td valign="top"><a href="#stop-0">stop/0</a></td><td>Stops the EUnit server.</td></tr>
-<tr><td valign="top"><a href="#test-1">test/1</a></td><td>Equivalent to <a href="#test-2"><tt>test(Tests, [])</tt></a>.
-</td></tr>
-<tr><td valign="top"><a href="#test-2">test/2</a></td><td>Runs a set of tests.</td></tr>
-</table>
-
-<h2><a name="functions">Function Details</a></h2>
-
-<h3 class="function"><a name="start-0">start/0</a></h3>
-<div class="spec">
-<p><tt>start() -&gt; any()</tt></p>
-</div><p>Starts the EUnit server. Normally, you don't need to call this
- function; it is started automatically.</p>
-
-<h3 class="function"><a name="stop-0">stop/0</a></h3>
-<div class="spec">
-<p><tt>stop() -&gt; any()</tt></p>
-</div><p>Stops the EUnit server. Normally, you don't need to call this
- function.</p>
-
-<h3 class="function"><a name="test-1">test/1</a></h3>
-<div class="spec">
-<p><tt>test(Tests) -&gt; any()</tt></p>
-</div><p>Equivalent to <a href="#test-2"><tt>test(Tests, [])</tt></a>.</p>
-
-
-<h3 class="function"><a name="test-2">test/2</a></h3>
-<div class="spec">
-<p><tt>test(Tests::term(), Options::[term()]) -&gt; ok | {error, term()}</tt></p>
-</div><p><p>Runs a set of tests. The format of <code>Tests</code> is described in the
- section <a href="overview-summary.html#EUnit_test_representation">EUnit test
- representation</a> of the overview.</p>
-
- Example: <pre> eunit:test(fred)</pre><p> runs all tests in the module <code>fred</code>
- and also any tests in the module <code>fred_tests</code>, if that module exists.</p>
-
- Options:
- <dl>
- <dt><code>verbose</code></dt>
- <dd>Displays more details about the running tests.</dd>
- </dl>
-
- Options in the environment variable EUNIT are also included last in
- the option list, i.e., have lower precedence than those in <code>Options</code>.</p>
-<p><b>See also:</b> <a href="#test-1">test/1</a>.</p>
-<hr>
-
-<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
-<p><i>Generated by EDoc, Apr 22 2009, 22:37:19.</i></p>
-</body>
-</html>
diff --git a/lib/eunit/doc/eunit_surefire.html b/lib/eunit/doc/eunit_surefire.html
deleted file mode 100644
index f2ecbae572..0000000000
--- a/lib/eunit/doc/eunit_surefire.html
+++ /dev/null
@@ -1,78 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<title>Module eunit_surefire</title>
-<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
-</head>
-<body bgcolor="white">
-<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
-<hr>
-
-<h1>Module eunit_surefire</h1>
-<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>Surefire reports for EUnit (Format used by Maven and Atlassian
-Bamboo for example to integrate test results).
-<p>Copyright � 2009 Micka�l R�mond, Paul Guyot</p>
-
-<p><b>Behaviours:</b> <a href="eunit_listener.html"><tt>eunit_listener</tt></a>.</p>
-<p><b>Authors:</b> Micka�l R�mond (<a href="mailto:[email protected]"><tt>[email protected]</tt></a>).</p>
-<p><b>See also:</b> <a href="eunit.html">eunit</a>.</p>
-
-<h2><a name="description">Description</a></h2><p>Surefire reports for EUnit (Format used by Maven and Atlassian
-Bamboo for example to integrate test results). Based on initial code
-from Paul Guyot.</p>
-
- Example: Generate XML result file in the current directory:
- <pre> eunit:test([fib, eunit_examples],
- [{report,{eunit_surefire,[{dir,"."}]}}]).</pre>
-<h2><a name="index">Function Index</a></h2>
-<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#handle_begin-3">handle_begin/3</a></td><td></td></tr>
-<tr><td valign="top"><a href="#handle_cancel-3">handle_cancel/3</a></td><td></td></tr>
-<tr><td valign="top"><a href="#handle_end-3">handle_end/3</a></td><td></td></tr>
-<tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
-<tr><td valign="top"><a href="#start-0">start/0</a></td><td></td></tr>
-<tr><td valign="top"><a href="#start-1">start/1</a></td><td></td></tr>
-<tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr>
-</table>
-
-<h2><a name="functions">Function Details</a></h2>
-
-<h3 class="function"><a name="handle_begin-3">handle_begin/3</a></h3>
-<div class="spec">
-<p><tt>handle_begin(X1, Data, St) -&gt; any()</tt></p>
-</div>
-
-<h3 class="function"><a name="handle_cancel-3">handle_cancel/3</a></h3>
-<div class="spec">
-<p><tt>handle_cancel(X1, Data, St) -&gt; any()</tt></p>
-</div>
-
-<h3 class="function"><a name="handle_end-3">handle_end/3</a></h3>
-<div class="spec">
-<p><tt>handle_end(X1, Data, St) -&gt; any()</tt></p>
-</div>
-
-<h3 class="function"><a name="init-1">init/1</a></h3>
-<div class="spec">
-<p><tt>init(Options) -&gt; any()</tt></p>
-</div>
-
-<h3 class="function"><a name="start-0">start/0</a></h3>
-<div class="spec">
-<p><tt>start() -&gt; any()</tt></p>
-</div>
-
-<h3 class="function"><a name="start-1">start/1</a></h3>
-<div class="spec">
-<p><tt>start(Options) -&gt; any()</tt></p>
-</div>
-
-<h3 class="function"><a name="terminate-2">terminate/2</a></h3>
-<div class="spec">
-<p><tt>terminate(X1, St) -&gt; any()</tt></p>
-</div>
-<hr>
-
-<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
-<p><i>Generated by EDoc, Apr 22 2009, 22:37:19.</i></p>
-</body>
-</html>
diff --git a/lib/eunit/doc/index.html b/lib/eunit/doc/index.html
deleted file mode 100644
index 9bd8e8cf6b..0000000000
--- a/lib/eunit/doc/index.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<title>The eunit application</title>
-</head>
-<frameset cols="20%,80%">
-<frame src="modules-frame.html" name="modulesFrame" title="">
-
-<frame src="overview-summary.html" name="overviewFrame" title="">
-<noframes>
-<h2>This page uses frames</h2>
-<p>Your browser does not accept frames.
-<br>You should go to the <a href="overview-summary.html">non-frame version</a> instead.
-</p>
-</noframes>
-</frameset>
-</html> \ No newline at end of file
diff --git a/lib/eunit/doc/modules-frame.html b/lib/eunit/doc/modules-frame.html
deleted file mode 100644
index a484e99d4c..0000000000
--- a/lib/eunit/doc/modules-frame.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<title>The eunit application</title>
-<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
-</head>
-<body bgcolor="white">
-<h2 class="indextitle">Modules</h2>
-<table width="100%" border="0" summary="list of modules">
-<tr><td><a href="eunit.html" target="overviewFrame" class="module">eunit</a></td></tr>
-<tr><td><a href="eunit_surefire.html" target="overviewFrame" class="module">eunit_surefire</a></td></tr></table>
-</body>
-</html> \ No newline at end of file
diff --git a/lib/eunit/doc/overview-summary.html b/lib/eunit/doc/overview-summary.html
deleted file mode 100644
index ea7beba8b3..0000000000
--- a/lib/eunit/doc/overview-summary.html
+++ /dev/null
@@ -1,1032 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<title>EUnit - a Lightweight Unit Testing Framework for Erlang
-</title>
-<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
-</head>
-<body bgcolor="white">
-<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
-<h1>EUnit - a Lightweight Unit Testing Framework for Erlang
-</h1>
-<p>Copyright � 2004-2007 Micka�l R�mond, Richard Carlsson</p>
-<p><b>Version:</b> 2.1.1, Apr 22 2009 22:37:19
-</p>
-<p><b>Authors:</b> Richard Carlsson (<a href="mailto:[email protected]"><tt>[email protected]</tt></a>) [<em>web site:</em> <tt><a href="http://user.it.uu.se/~richardc/" target="_top">http://user.it.uu.se/~richardc/</a></tt>], Micka�l R�mond (<a href="mailto:[email protected]"><tt>[email protected]</tt></a>) [<em>web site:</em> <tt><a href="http://www.process-one.net/" target="_top">http://www.process-one.net/</a></tt>].</p>
-<p>EUnit is a unit testing framework for Erlang. It is very powerful
-and flexible, is easy to use, and has small syntactical overhead.</p>
-
-<ul>
-<li><a href="#Unit_testing">Unit testing</a></li>
-<li><a href="#Terminology">Terminology</a></li>
-<li><a href="#Getting_started">Getting started</a></li>
-<li><a href="#EUnit_macros">EUnit macros</a></li>
-<li><a href="#EUnit_test_representation">EUnit test representation</a></li>
-</ul>
-
-<p>EUnit builds on ideas from the family of unit testing frameworks for
-Object Oriented languages that originated with JUnit by Beck and Gamma
-(and Beck's previous framework SUnit for Smalltalk). However, EUnit uses
-techniques more adapted to functional and concurrent programming, and is
-typically less verbose than its relatives.</p>
-
-<p>Although EUnit uses many preprocessor macros, they have been designed to
-be as nonintrusive as possible, and should not cause conflicts with
-existing code. Adding EUnit tests to a module should thus not normally
-require changing existing code. Furthermore, tests that only exercise
-the exported functions of a module can always be placed in a completely
-separate module, avoiding any conflicts entirely.</p>
-
-<h3><a name="Unit_testing">Unit testing</a></h3>
-
-<p>Unit Testing is testing of individual program "units" in relative
-isolation. There is no particular size requirement: a unit can be a
-function, a module, a process, or even a whole application, but the most
-typical testing units are individual functions or modules. In order to
-test a unit, you specify a set of individual tests, set up the smallest
-necessary environment for being able to run those tests (often, you
-don't need to do any setup at all), you run the tests and collect the
-results, and finally you do any necessary cleanup so that the test can
-be run again later. A Unit Testing Framework tries to help you in each
-stage of this process, so that it is easy to write tests, easy to run
-them, and easy to see which tests failed (so you can fix the bugs).</p>
-
-<h4><a name="Advantages_of_unit_testing">Advantages of unit testing</a></h4>
-
-<dl>
- <dt>Reduces the risks of changing the program</dt>
- <dd>Most programs will be modified during their lifetime: bugs will be
- fixed, features will be added, optimizations may become necessary, or
- the code will need to be refactored or cleaned up in other ways to
- make it easier to work with. But every change to a working program is
- a risk of introducing new bugs - or reintroducing bugs that had
- previously been fixed. Having a set of unit tests that you can run
- with very little effort makes it easy to know that the code still
- works as it should (this use is called <em>regression testing</em>;
- see <a href="#Terminology">Terminology</a>). This goes a long way to reduce the
- resistance to changing and refactoring code.</dd>
- <dt>Helps guide and speed up the development process</dt>
- <dd>By focusing on getting the code to pass the tests, the programmer
- can become more productive, not overspecify or get lost in premature
- optimizations, and create code that is correct from the very beginning
- (so-called <em>test-driven development</em>; see <a href="#Terminology">Terminology</a>).</dd>
- <dt>Helps separate interface from implementation</dt>
- <dd>When writing tests, the programmer may discover dependencies
- (in order to get the tests to run) that ought not to be there, and
- which need to be abstracted away to get a cleaner design. This helps
- eliminate bad dependencies before they spread throughout the
- code.</dd>
- <dt>Makes component integration easier</dt>
- <dd>By testing in a bottom-up fashion, beginning with the smallest
- program units and creating a confidence in that they work as they
- should, it becomes easier to test that a higher-level component,
- consisting of several such units, also behaves according to
- specification (known as <em>integration testing</em>; see <a href="#Terminology">Terminology</a>).</dd>
- <dt>Is self-documenting</dt>
- <dd>The tests can be read as documentation, typically showing both
- examples of correct and incorrect usage, along with the expected
- consequences.</dd>
-</dl>
-
-<h3><a name="Terminology">Terminology</a></h3>
-
-<dl>
- <dt>Unit testing</dt>
- <dd>Testing that a program unit behaves as it is supposed to do (in
- itself), according to its specifications. Unit tests have an important
- function as regression tests, when the program later is modified for
- some reason, since they check that the program still behaves according
- to specification.</dd>
- <dt>Regression testing</dt>
- <dd>Running a set of tests after making changes to a program, to check
- that the program behaves as it did before the changes (except, of
- course, for any intentional changes in behaviour). Unit tests are
- important as regression tests, but regression testing can involve more
- than just unit testing, and may also test behaviour that might not be
- part of the normal specification (such as bug-for-bug-compatibility).
- </dd>
- <dt>Integration testing</dt>
- <dd>Testing that a number of individually developed program units
- (assumed to already have been separately unit tested) work together as
- expected. Depending on the system being developed, integration testing
- may be as simple as "just another level of unit testing", but might
- also involve other kinds of tests (compare <em>system testing</em>).
-</dd>
- <dt>System testing</dt>
- <dd>Testing that a complete system behaves according to its
- specification. Specifically, system testing should not require knowing
- any details about the implementation. It typically involves testing
- many different aspects of the system behaviour apart from the basic
- functionality, such as performance, usability, and reliability.</dd>
- <dt>Test-driven development</dt>
- <dd>A program development technique where you continuously write tests
- <em>before</em> you implement the code that is supposed to pass those
- tests. This can help you focus on solving the right problems, and not
- make a more complicated implementation than necessary, by letting the
- unit tests determine when a program is "done": if it fulfils its
- specifications, there is no need to keep adding functionality.</dd>
- <dt>Mock object</dt>
- <dd>Sometimes, testing some unit <code>A</code> (e.g., a function) requires that
- it collaborates somehow with some other unit <code>B</code> (perhaps being passed
- as an argument, or by reference) - but <code>B</code> has not been implemented
- yet. A "mock object" - an object which, for the purposes of testing
- <code>A</code>, looks and behaves like a real <code>B</code> - might then be used instead.
- (This is of course only useful if it would be significantly more work
- to implement a real <code>B</code> than to create a mock object.)</dd>
- <dt>Test case</dt>
- <dd>A single, well-defined test, that somehow can be uniquely
- identified. When executed, the test case either <em>passes</em> or
- <em>fails</em>; the test report should identify exactly which test
- cases failed.</dd>
- <dt>Test suite</dt>
- <dd>A collection of test cases, generally with a specific, common
- target for testing, such as a single function, module, or subsystem. A
- test suite may also be recursively composed by smaller test
- suites.</dd>
-</dl>
-
-<h3><a name="Getting_started">Getting started</a></h3>
-<ul>
- <li><a href="#Including_the_EUnit_header_file">Including the EUnit header file</a></li>
- <li><a href="#Writing_simple_test_functions">Writing simple test functions</a></li>
- <li><a href="#Running_EUnit">Running EUnit</a></li>
- <li><a href="#Writing_test_generating_functions">Writing test generating functions</a></li>
- <li><a href="#An_example">An example</a></li>
- <li><a href="#Disabling_testing">Disabling testing</a></li>
- <li><a href="#Avoiding_compile-time_dependency_on_EUnit">Avoiding compile-time dependency on EUnit</a></li>
-</ul>
-
-<h4><a name="Including_the_EUnit_header_file">Including the EUnit header file</a></h4>
-
-The simplest way to use EUnit in an Erlang module is to add the
-following line at the beginning of the module (after the <code>-module</code>
-declaration, but before any function definitions):
-<pre> -include_lib("eunit/include/eunit.hrl").</pre>
-
-This will have the following effect:
-<ul>
- <li>Creates an exported function <code>test()</code> (unless testing is turned
- off, and the module does not already contain a test() function), that
- can be used to run all the unit tests defined in the module</li>
- <li>Causes all functions whose names match <code>..._test()</code> or <code>..._test_()</code>
- to be automatically exported from the module (unless testing is
- turned off, or the <code>EUNIT_NOAUTO</code> macro is defined)</li>
- <li>Makes all the preprocessor macros of EUnit available, to help
- writing tests</li>
-</ul>
-
-<strong>Note:</strong> For <code>-include_lib(...)</code> to work, the Erlang
-module search path <em>must</em> contain a directory whose name ends in
-<code>eunit/ebin</code> (pointing to the <code>ebin</code> subdirectory of the EUnit
-installation directory). If EUnit is installed as <code>lib/eunit</code> under your
-Erlang/OTP system directory, its <code>ebin</code> subdirectory will be
-automatically added to the search path when Erlang starts. Otherwise,
-you need to add the directory explicitly, by passing a <code>-pa</code> flag to the
-<code>erl</code> or <code>erlc</code> command. For example, a Makefile could contain the
-following action for compiling <code>.erl</code> files:
-<pre> erlc -pa "path/to/eunit/ebin" $(ERL_COMPILE_FLAGS) -o$(EBIN) $&lt;</pre>
-or if you want Eunit to always be available when you run Erlang
-interactively, you can add a line like the following to your
-<code>$HOME/.erlang</code> file:
-<pre> code:add_path("/path/to/eunit/ebin").</pre>
-
-<h4><a name="Writing_simple_test_functions">Writing simple test functions</a></h4>
-
-<p>The EUnit framework makes it extremely easy to write unit tests in
-Erlang. There are a few different ways of writing them, though, so we
-start with the simplest:</p>
-
-<p>A function with a name ending in <code>..._test()</code> is recognized by EUnit as
-a simple test function - it takes no arguments, and its execution either
-succeeds (returning some arbitrary value that EUnit will throw away), or
-fails by throwing an exception of some kind (or by not terminating, in
-which case it will be aborted after a while).</p>
-
-An example of a simple test function could be the following:
-<pre> reverse_test() -&gt; lists:reverse([1,2,3]).</pre><p>
-This just tests that the function <code>lists:reverse(List)</code> does not crash
-when <code>List</code> is <code>[1,2,3]</code>. It is not a great test, but many people write
-simple functions like this one to test the basic functionality of their
-code, and those tests can be used directly by EUnit, without changes,
-as long as their function names match.</p>
-
-<h5><a name="Use_exceptions_to_signal_failure">Use exceptions to signal failure</a></h5>
-
-To write more interesting tests, we need to make them crash (throw an
-exception) when they don't get the result they expect. A simple way of
-doing this is to use pattern matching with <code>=</code>, as in the following
-examples:
-<pre> reverse_nil_test() -&gt; [] = lists:reverse([]).
- reverse_one_test() -&gt; [1] = lists:reverse([1]).
- reverse_two_test() -&gt; [2,1] = lists:reverse([1,2]).</pre><p>
-If there was some bug in <code>lists:reverse/1</code> that made it return something
-other than <code>[2,1]</code> when it got <code>[1,2]</code> as input, then the last test
-above would throw a <code>badmatch</code> error. The first two (we assume they do
-not get a <code>badmatch</code>) would simply return <code>[]</code> and <code>[1]</code>, respectively,
-so both succeed. (Note that EUnit is not psychic: if you write a test
-that returns a value, even if it is the wrong value, EUnit will consider
-it a success. You must make sure that the test is written so that it
-causes a crash if the result is not what it should be.)</p>
-
-<h5><a name="Using_assert_macros">Using assert macros</a></h5>
-
-If you want to use Boolean operators for your tests, the <code>assert</code>
-macro comes in handy (see <a href="#EUnit_macros">EUnit macros</a> for details):
-<pre> length_test() -&gt; ?assert(length([1,2,3]) =:= 3).</pre><p>
-The <code>?assert(Expression)</code> macro will evaluate <code>Expression</code>, and if that
-does not evaluate to <code>true</code>, it will throw an exception; otherwise it
-just returns <code>ok</code>. In the above example, the test will thus fail if the
-call to <code>length</code> does not return 3.</p>
-
-<h4><a name="Running_EUnit">Running EUnit</a></h4>
-
-<p>If you have added the declaration
-<code>-include_lib("eunit/include/eunit.hrl")</code> to your module, as described
-above, you only need to compile the module, and run the automatically
-exported function <code>test()</code>. For example, if your module was named <code>m</code>,
-then calling <code>m:test()</code> will run EUnit on all the tests defined in the
-module. You do not need to write <code>-export</code> declarations for the test
-functions. This is all done by magic.</p>
-
-<p>You can also use the function <a href="eunit.html#test-1"><code>eunit:test/1</code></a> to run arbitrary
-tests, for example to try out some more advanced test descriptors (see
-<a href="#EUnit_test_representation">EUnit test representation</a>). For example, running
-<code>eunit:test(m)</code> does the same thing as the auto-generated function
-<code>m:test()</code>, while <code>eunit:test({inparallel, m})</code> runs the same test
-cases but executes them all in parallel.</p>
-
-<h5><a name="Putting_tests_in_separate_modules">Putting tests in separate modules</a></h5>
-
-<p>If you want to separate your test code from your normal code (at least
-for testing the exported functions), you can simply write the test
-functions in a module named <code>m_tests</code> (note: not <code>m_test</code>), if your
-module is named <code>m</code>. Then, whenever you ask EUnit to test the module
-<code>m</code>, it will also look for the module <code>m_tests</code> and run those tests as
-well. See <code>ModuleName</code> in the section <a href="#Primitives">Primitives</a> for details.</p>
-
-<h5><a name="EUnit_captures_standard_output">EUnit captures standard output</a></h5>
-
-<p>If your test code writes to the standard output, you may be surprised to
-see that the text does not appear on the console when the tests are
-running. This is because EUnit captures all standard output from test
-functions (this also includes setup and cleanup functions, but not
-generator functions), so that it can be included in the test report if
-errors occur. To bypass EUnit and print text directly to the console
-while testing, you can write to the <code>user</code> output stream, as in
-<code>io:format(user, "~w", [Term])</code>. The recommended way of doing this is to
-use the EUnit <a href="#Debugging_macros">Debugging macros</a>, which make it much simpler.</p>
-
-<h4><a name="Writing_test_generating_functions">Writing test generating functions</a></h4>
-
-<p>A drawback of simple test functions is that you must write a separate
-function (with a separate name) for each test case. A more compact way
-of writing tests (and much more flexible, as we shall see), is to write
-functions that <em>return</em> tests, instead of <em>being</em> tests.</p>
-
-<p>A function with a name ending in <code>..._test_()</code> (note the final
-underscore) is recognized by EUnit as a <em>test generator</em>
-function. Test generators return a <em>representation</em> of a <em>set
-of tests</em> to be executed by EUnit.</p>
-
-<h5><a name="Representing_a_test_as_data">Representing a test as data</a></h5>
-
-The most basic representation of a test is a single fun-expression that
-takes no arguments. For example, the following test generator:
-<pre> basic_test_() -&gt;
- fun () -&gt; ?assert(1 + 1 =:= 2) end.</pre>
-will have the same effect as the following simple test:
-<pre> simple_test() -&gt;
- ?assert(1 + 1 =:= 2).</pre><p>
-(in fact, EUnit will handle all simple tests just like it handles
-fun-expressions: it will put them in a list, and run them one by one).</p>
-
-<h5><a name="Using_macros_to_write_tests">Using macros to write tests</a></h5>
-
-To make tests more compact and readable, as well as automatically add
-information about the line number in the source code where a test
-occurred (and reduce the number of characters you have to type), you can
-use the <code>_test</code> macro (note the initial underscore character), like
-this:
-<pre> basic_test_() -&gt;
- ?_test(?assert(1 + 1 =:= 2)).</pre><p>
-The <code>_test</code> macro takes any expression (the "body") as argument, and
-places it within a fun-expression (along with some extra information).
-The body can be any kind of test expression, just like the body of a
-simple test function.</p>
-
-<h5><a name="Underscore-prefixed_macros_create_test_objects">Underscore-prefixed macros create test objects</a></h5>
-
-But this example can be made even shorter! Most test macros, such as the
-family of <code>assert</code> macros, have a corresponding form with an initial
-underscore character, which automatically adds a <code>?_test(...)</code> wrapper.
-The above example can then simply be written:
-<pre> basic_test_() -&gt;
- ?_assert(1 + 1 =:= 2).</pre><p>
-which has exactly the same meaning (note the <code>_assert</code> instead of
-<code>assert</code>). You can think of the initial underscore as signalling
-<em>test object</em>.</p>
-
-<h4><a name="An_example">An example</a></h4>
-
-Sometimes, an example says more than a thousand words. The following
-small Erlang module shows how EUnit can be used in practice.
-<pre> -module(fib).
- -export([fib/1]).
- -include_lib("eunit/include/eunit.hrl").
-
- fib(0) -&gt; 1;
- fib(1) -&gt; 1;
- fib(N) when N &gt; 1 -&gt; fib(N-1) + fib(N-2).
-
- fib_test_() -&gt;
- [?_assert(fib(0) =:= 1),
- ?_assert(fib(1) =:= 1),
- ?_assert(fib(2) =:= 2),
- ?_assert(fib(3) =:= 3),
- ?_assert(fib(4) =:= 5),
- ?_assert(fib(5) =:= 8),
- ?_assertException(error, function_clause, fib(-1)),
- ?_assert(fib(31) =:= 2178309)
- ].</pre>
-
-<p>(Author's note: When I first wrote this example, I happened to write a
-<code>*</code> instead of <code>+</code> in the <code>fib</code> function. Of course, this showed up
-immediately when I ran the tests.)</p>
-
-<p>See <a href="#EUnit_test_representation">EUnit test representation</a> for a full list of all the ways
-you can specify test sets in EUnit.</p>
-
-<h4><a name="Disabling_testing">Disabling testing</a></h4>
-
-Testing can be turned off by defining the <code>NOTEST</code> macro when compiling,
-for example as an option to <code>erlc</code>, as in:
-<pre> erlc -DNOTEST my_module.erl</pre>
-or by adding a macro definition to the code, <em>before the EUnit header
-file is included</em>:
-<pre> -define(NOTEST, 1).</pre><p>
-(the value is not important, but should typically be 1 or <code>true</code>).
-Note that unless the <code>EUNIT_NOAUTO</code> macro is defined, disabling testing
-will also automatically strip all test functions from the code, except
-for any that are explicitly declared as exported.</p>
-
-For instance, to use EUnit in your application, but with testing turned
-off by default, put the following lines in a header file:
-<pre> -define(NOTEST, true).
- -include_lib("eunit/include/eunit.hrl").</pre>
-and then make sure that every module of your application includes that
-header file. This means that you have a only a single place to modify in
-order to change the default setting for testing. To override the <code>NOTEST</code>
-setting without modifying the code, you can define <code>TEST</code> in a compiler
-option, like this:
-<pre> erlc -DTEST my_module.erl</pre>
-
-<p>See <a href="#Compilation_control_macros">Compilation control macros</a> for details about these
-macros.</p>
-
-<h4><a name="Avoiding_compile-time_dependency_on_EUnit">Avoiding compile-time dependency on EUnit</a></h4>
-
-If you are distributing the source code for your application for other
-people to compile and run, you probably want to ensure that the code
-compiles even if EUnit is not available. Like the example in the
-previous section, you can put the following lines in a common header
-file:
-<pre> -ifdef(TEST).
- -include_lib("eunit/include/eunit.hrl").
- -endif.</pre><p>
-and, of course, also make sure that you place all test code that uses
-EUnit macros within <code>-ifdef(TEST)</code> or <code>-ifdef(EUNIT)</code> sections.</p>
-
-
-<h3><a name="EUnit_macros">EUnit macros</a></h3>
-
-<p>Although all the functionality of EUnit is avaliable even without the
-use of preprocessor macros, the EUnit header file defines a number of
-such macros in order to make it as easy as possible to write unit tests
-as compactly as possible and without getting too many details in the
-way.</p>
-
-<p>Except where explicitly stated, using EUnit macros will never introduce
-run-time dependencies on the EUnit library code, regardless of whether
-your code is compiled with testing enabled or disabled.</p>
-
-<ul>
-<li><a href="#Basic_macros">Basic macros</a></li>
-<li><a href="#Compilation_control_macros">Compilation control macros</a></li>
-<li><a href="#Utility_macros">Utility macros</a></li>
-<li><a href="#Assert_macros">Assert macros</a></li>
-<li><a href="#Macros_for_running_external_commands">Macros for running external commands</a></li>
-<li><a href="#Debugging_macros">Debugging macros</a></li>
-</ul>
-
-<h4><a name="Basic_macros">Basic macros</a></h4>
-
-<dl>
-<dt><code>_test(Expr)</code></dt>
-<dd>Turns <code>Expr</code> into a "test object", by wrapping it in a
-fun-expression and a source line number. Technically, this is the same
-as <code>{?LINE, fun () -&gt; (Expr) end}</code>.
-</dd>
-</dl>
-
-<h4><a name="Compilation_control_macros">Compilation control macros</a></h4>
-
-<dl>
-<dt><code>EUNIT</code></dt>
-<dd>This macro is always defined to <code>true</code> whenever EUnit is enabled at
-compile time. This is typically used to place testing code within
-conditional compilation, as in:
-<pre> -ifdef(EUNIT).
- % test code here
- ...
- -endif.</pre>
-e.g., to ensure that the code can be compiled without including the
-EUnit header file, when testing is disabled. See also the macros <code>TEST</code>
-and <code>NOTEST</code>.
-</dd>
-
-<dt><code>EUNIT_NOAUTO</code></dt>
-<dd>If this macro is defined, the automatic exporting or stripping of
-test functions will be disabled.
-</dd>
-
-<dt><code>TEST</code></dt>
-<dd><p>This macro is always defined (to <code>true</code>, unless previously defined
-by the user to have another value) whenever EUnit is enabled at compile
-time. This can be used to place testing code within conditional
-compilation; see also the macros <code>NOTEST</code> and <code>EUNIT</code>.</p>
-
-<p>For testing code that is strictly dependent on EUnit, it may be
-preferable to use the <code>EUNIT</code> macro for this purpose, while for code
-that uses more generic testing conventions, using the <code>TEST</code> macro may
-be preferred.</p>
-
-The <code>TEST</code> macro can also be used to override the <code>NOTEST</code> macro. If
-<code>TEST</code> is defined <em>before</em> the EUnit header file is
-included (even if <code>NOTEST</code> is also defined), then the code will be
-compiled with EUnit enabled.
-</dd>
-
-<dt><code>NOTEST</code></dt>
-<dd><p>This macro is always defined (to <code>true</code>, unless previously defined
-by the user to have another value) whenever EUnit is <em>disabled</em>
-at compile time. (Compare the <code>TEST</code> macro.)</p>
-
-This macro can also be used for conditional compilation, but is more
-typically used to disable testing: If <code>NOTEST</code> is defined
-<em>before</em> the EUnit header file is included, and <code>TEST</code>
-is <em>not</em> defined, then the code will be compiled with EUnit
-disabled. See also <a href="#Disabling_testing">Disabling testing</a>.
-</dd>
-
-<dt><code>NOASSERT</code></dt>
-<dd>If this macro is defined, the assert macros will have no effect,
-when testing is also disabled. See <a href="#Assert_macros">Assert macros</a>. When
-testing is enabled, the assert macros are always enabled automatically
-and cannot be disabled.
-</dd>
-
-<dt><code>ASSERT</code></dt>
-<dd>If this macro is defined, it overrides the NOASSERT macro, forcing
-the assert macros to always be enabled regardless of other settings.
-</dd>
-
-<dt><code>NODEBUG</code></dt>
-<dd>If this macro is defined, the debugging macros will have no effect.
-See <a href="#Debugging_macros">Debugging macros</a>. <code>NODEBUG</code> also implies <code>NOASSERT</code>,
-unless testing is enabled.
-</dd>
-
-<dt><code>DEBUG</code></dt>
-<dd>If this macro is defined, it overrides the NODEBUG macro, forcing
-the debugging macros to be enabled.
-</dd>
-</dl>
-
-<h4><a name="Utility_macros">Utility macros</a></h4>
-
-<p>The following macros can make tests more compact and readable:</p>
-
-<dl>
-<dt><code>LET(Var,Arg,Expr)</code></dt>
-<dd>Creates a local binding <code>Var = Arg</code> in <code>Expr</code>. (This is the same as
-<code>(fun(Var)-&gt;(Expr)end)(Arg)</code>.) Note that the binding is not exported
-outside of <code>Expr</code>, and that within <code>Expr</code>, this binding of <code>Var</code> will
-shadow any binding of <code>Var</code> in the surrounding scope.
-</dd>
-<dt><code>IF(Cond,TrueCase,FalseCase)</code></dt>
-<dd>Evaluates <code>TrueCase</code> if <code>Cond</code> evaluates to <code>true</code>, or otherwise
-evaluates <code>FalseCase</code> if <code>Cond</code> evaluates to <code>false</code>. (This is the same
-as <code>(case (Cond) of true-&gt;(TrueCase); false-&gt;(FalseCase) end)</code>.) Note
-that it is an error if <code>Cond</code> does not yield a boolean value.
-</dd>
-</dl>
-
-<h4><a name="Assert_macros">Assert macros</a></h4>
-
-<p>(Note that these macros also have corresponding forms which start with
-an "<code>_</code>" (underscore) character, as in <code>?_assert(BoolExpr)</code>, that create
-a "test object" instead of performing the test immediately. This is
-equivalent to writing <code>?_test(assert(BoolExpr))</code>, etc.)</p>
-
-<p>If the macro <code>NOASSERT</code> is defined before the EUnit header file is
-included, these macros have no effect when testing is also disabled; see
-<a href="#Compilation_control_macros">Compilation control macros</a> for details.</p>
-
-<dl>
-<dt><code>assert(BoolExpr)</code></dt>
-<dd><p>Evaluates the expression <code>BoolExpr</code>, if testing is enabled. Unless
-the result is <code>true</code>, an informative exception will be generated. If
-there is no exception, the result of the macro expression is the atom
-<code>ok</code>, and the value of <code>BoolExpr</code> is discarded. If testing is disabled,
-the macro will not generate any code except the atom <code>ok</code>, and
-<code>BoolExpr</code> will not be evaluated.</p>
-
-Typical usage:
-<pre> ?assert(f(X, Y) =:= [])</pre>
-
-The <code>assert</code> macro can be used anywhere in a program, not just in unit
-tests, to check pre/postconditions and invariants. For example:
-<pre> some_recursive_function(X, Y, Z) -&gt;
- ?assert(X + Y &gt; Z),
- ...</pre>
-</dd>
-<dt><code>assertNot(BoolExpr)</code></dt>
-<dd>Equivalent to <code>assert(not (BoolExpr))</code>.
-</dd>
-<dt><code>assertMatch(GuardedPattern, Expr)</code></dt>
-<dd><p>Evaluates <code>Expr</code> and matches the result against <code>GuardedPattern</code>, if
-testing is enabled. If the match fails, an informative exception will be
-generated; see the <code>assert</code> macro for further details. <code>GuardedPattern</code>
-can be anything that you can write on the left hand side of the <code>-&gt;</code>
-symbol in a case-clause, except that it cannot contain comma-separated
-guard tests.</p>
-
-<p>The main reason for using <code>assertMatch</code> also for simple matches, instead
-of matching with <code>=</code>, is that it produces more detailed error messages.</p>
-
-Examples:
-<pre> ?assertMatch({found, {fred, _}}, lookup(bloggs, Table))</pre>
-<pre> ?assertMatch([X|_] when X &gt; 0, binary_to_list(B))</pre>
-</dd>
-<dt><code>assertEqual(Expect, Expr)</code></dt>
-<dd><p>Evaluates the expressions <code>Expect</code> and <code>Expr</code> and compares the
-results for equality, if testing is enabled. If the values are not
-equal, an informative exception will be generated; see the <code>assert</code>
-macro for further details.</p>
-
-<p><code>assertEqual</code> is more suitable than than <code>assertMatch</code> when the
-left-hand side is a computed value rather than a simple pattern, and
-gives more details than <code>?assert(Expect =:= Expr)</code>.</p>
-
-Examples:
-<pre> ?assertEqual("b" ++ "a", lists:reverse("ab"))</pre>
-<pre> ?assertEqual(foo(X), bar(Y))</pre>
-</dd>
-<dt><code>assertException(ClassPattern, TermPattern, Expr)</code></dt>
-<dt><code>assertError(TermPattern, Expr)</code></dt>
-<dt><code>assertExit(TermPattern, Expr)</code></dt>
-<dt><code>assertThrow(TermPattern, Expr)</code></dt>
-<dd><p>Evaluates <code>Expr</code>, catching any exception and testing that it matches
-the expected <code>ClassPattern:TermPattern</code>. If the match fails, or if no
-exception is thrown by <code>Expr</code>, an informative exception will be
-generated; see the <code>assert</code> macro for further details. The
-<code>assertError</code>, <code>assertExit</code>, and <code>assertThrow</code> macros, are equivalent to
-using <code>assertException</code> with a <code>ClassPattern</code> of <code>error</code>, <code>exit</code>, or
-<code>throw</code>, respectively.</p>
-
-Examples:
-<pre> ?assertError(badarith, X/0)</pre>
-<pre> ?assertExit(normal, exit(normal))</pre>
-<pre> ?assertException(throw, {not_found,_}, throw({not_found,42}))</pre>
-</dd>
-</dl>
-
-<h4><a name="Macros_for_running_external_commands">Macros for running external commands</a></h4>
-
-<p>Keep in mind that external commands are highly dependent on the
-operating system. You can use the standard library function <code>os:type()</code>
-in test generator functions, to produce different sets of tests
-depending on the current operating system.</p>
-
-<p>Note: these macros introduce a run-time dependency on the EUnit library
-code, if compiled with testing enabled.</p>
-
-<dl>
-<dt><code>assertCmd(CommandString)</code></dt>
-<dd><p>Runs <code>CommandString</code> as an external command, if testing is enabled.
-Unless the returned status value is 0, an informative exception will be
-generated. If there is no exception, the result of the macro expression
-is the atom <code>ok</code>. If testing is disabled, the macro will not generate
-any code except the atom <code>ok</code>, and the command will not be executed.</p>
-
-Typical usage:
-<pre> ?assertCmd("mkdir foo")</pre>
-</dd>
-<dt><code>assertCmdStatus(N, CommandString)</code></dt>
-<dd>Like the <code>assertCmd(CommandString)</code> macro, but generates an
-exception unless the returned status value is <code>N</code>.
-</dd>
-<dt><code>assertCmdOutput(Text, CommandString)</code></dt>
-<dd>Runs <code>CommandString</code> as an external command, if testing is enabled.
-Unless the output produced by the command exactly matches the specified
-string <code>Text</code>, an informative exception will be generated. (Note that
-the output is normalized to use a single LF character as line break on
-all platforms.) If there is no exception, the result of the macro
-expression is the atom <code>ok</code>. If testing is disabled, the macro will not
-generate any code except the atom <code>ok</code>, and the command will not be
-executed.
-</dd>
-<dt><code>cmd(CommandString)</code></dt>
-<dd><p>Runs <code>CommandString</code> as an external command. Unless the returned
-status value is 0 (indicating success), an informative exception will be
-generated; otherwise, the result of the macro expression is the output
-produced by the command, as a flat string. The output is normalized to
-use a single LF character as line break on all platforms.</p>
-
-<p>This macro is useful in the setup and cleanup sections of fixtures,
-e.g., for creating and deleting files or perform similar operating
-system specific tasks, to make sure that the test system is informed of
-any failures.</p>
-
-A Unix-specific example:
-<pre> {setup,
- fun () -&gt; ?cmd("mktemp") end,
- fun (FileName) -&gt; ?cmd("rm " ++ FileName) end,
- ...}</pre>
-</dd>
-</dl>
-
-<h4><a name="Debugging_macros">Debugging macros</a></h4>
-
-<p>To help with debugging, EUnit defines several useful macros for printing
-messages directly to the console (rather than to the standard output).
-Furthermore, these macros all use the same basic format, which includes
-the file and line number where they occur, making it possible in some
-development environments (e.g., when running Erlang in an Emacs buffer)
-to simply click on the message and jump directly to the corresponding
-line in the code.</p>
-
-<p>If the macro <code>NODEBUG</code> is defined before the EUnit header file is
-included, these macros have no effect; see
-<a href="#Compilation_control_macros">Compilation control macros</a> for details.</p>
-
-<dl>
-<dt><code>debugHere</code></dt>
-<dd>Just prints a marker showing the current file and line number. Note
-that this is an argument-less macro. The result is always <code>ok</code>.</dd>
-<dt><code>debugMsg(Text)</code></dt>
-<dd>Outputs the message <code>Text</code> (which can be a plain string, an IO-list,
-or just an atom). The result is always <code>ok</code>.</dd>
-<dt><code>debugFmt(FmtString, Args)</code></dt>
-<dd>This formats the text like <code>io:format(FmtString, Args)</code> and outputs
-it like <code>debugMsg</code>. The result is always <code>ok</code>.</dd>
-<dt><code>debugVal(Expr)</code></dt>
-<dd>Prints both the source code for <code>Expr</code> and its current value. E.g.,
-<code>?debugVal(f(X))</code> might be displayed as "<code>f(X) = 42</code>". (Large terms are
-shown truncated.) The result is always the value of <code>Expr</code>, so this
-macro can be wrapped around any expression to display its value when
-the code is compiled with debugging enabled.</dd>
-<dt><code>debugTime(Text,Expr)</code></dt>
-<dd>Prints <code>Text</code> and the wall clock time for evaluation of <code>Expr</code>. The
-result is always the value of <code>Expr</code>, so this macro can be wrapped
-around any expression to show its run time when the code is compiled
-with debugging enabled. For example, <code>List1 = ?debugTime("sorting",
-lists:sort(List))</code> might show as "<code>sorting: 0.015 s</code>".</dd>
-
-</dl>
-
-
-<h3><a name="EUnit_test_representation">EUnit test representation</a></h3>
-
-<p>The way EUnit represents tests and test sets as data is flexible,
-powerful, and concise. This section describes the representation in
-detail.</p>
-
-<ul>
-<li><a href="#Simple_test_objects">Simple test objects</a></li>
-<li><a href="#Test_sets_and_deep_lists">Test sets and deep lists</a></li>
-<li><a href="#Titles">Titles</a></li>
-<li><a href="#Primitives">Primitives</a></li>
-<li><a href="#Control">Control</a></li>
-<li><a href="#Fixtures">Fixtures</a></li>
-<li><a href="#Lazy_generators">Lazy generators</a></li>
-</ul>
-
-<h4><a name="Simple_test_objects">Simple test objects</a></h4>
-
-A <em>simple test object</em> is one of the following:
-<ul>
- <li>A nullary functional value (i.e., a fun that takes zero
- arguments). Examples:
-<pre> fun () -&gt; ... end</pre>
-<pre> fun some_function/0</pre>
-<pre> fun some_module:some_function/0</pre>
- </li>
- <li>A pair of atoms <code>{ModuleName, FunctionName}</code>, referring to the
- function <code>ModuleName:FunctionName/0</code></li>
- <li>A pair <code>{LineNumber, SimpleTest}</code>, where <code>LineNumber</code> is a
- nonnegative integer and <code>SimpleTest</code> is another simple test
- object. <code>LineNumber</code> should indicate the source line of the test.
- Pairs like this are usually only created via <code>?_test(...)</code> macros;
- see <a href="#Basic_macros">Basic macros</a>.</li>
-</ul><p>
-In brief, a simple test object consists of a single function that takes
-no arguments (possibly annotated with some additional metadata, i.e., a
-line number). Evaluation of the function either <em>succeeds</em>, by
-returning some value (which is ignored), or <em>fails</em>, by throwing
-an exception.</p>
-
-<h4><a name="Test_sets_and_deep_lists">Test sets and deep lists</a></h4>
-
-<p>A test set can be easily created by placing a sequence of test objects
-in a list. If <code>T_1</code>, ..., <code>T_N</code> are individual test objects, then <code>[T_1,
-..., T_N]</code> is a test set consisting of those objects (in that order).</p>
-
-<p>Test sets can be joined in the same way: if <code>S_1</code>, ..., <code>S_K</code> are test
-sets, then <code>[S_1, ..., S_K]</code> is also a test set, where the tests of
-<code>S_i</code> are ordered before those of <code>S_(i+1)</code>, for each subset <code>S_i</code>.</p>
-
-<p>Thus, the main representation of test sets is <em>deep lists</em>, and
-a simple test object can be viewed as a test set containing only a
-single test; there is no difference between <code>T</code> and <code>[T]</code>.</p>
-
-<p>A module can also be used to represent a test set; see <code>ModuleName</code>
-under <a href="#Primitives">Primitives</a> below.</p>
-
-<h4><a name="Titles">Titles</a></h4>
-
-<p>Any test or test set <code>T</code> can be annotated with a title, by wrapping it
-in a pair <code>{Title, T}</code>, where <code>Title</code> is a string. For convenience, any
-test which is normally represented using a tuple can simply be given a
-title string as the first element, i.e., writing <code>{"The Title", ...}</code>
-instead of adding an extra tuple wrapper as in <code>{"The Title", {...}}</code>.</p>
-
-
-<h4><a name="Primitives">Primitives</a></h4>
-
-The following are primitives, which do not contain other test sets as
-arguments:
-<dl>
-<dt><code>ModuleName::atom()</code>
-</dt>
-<dd>A single atom represents a module name, and is equivalent to
-<code>{module, ModuleName}</code>. This is often used as in the call
-<code>eunit:test(some_module)</code>.
-</dd>
-<dt><code>{module, ModuleName::atom()}</code>
-</dt>
-<dd><p>This composes a test set from the exported test functions of the
-named module, i.e., those functions with arity zero whose names end
-with <code>_test</code> or <code>_test_</code>. Basically, the <code>..._test()</code> functions become
-simple tests, while the <code>..._test_()</code> functions become generators.</p>
-
-In addition, EUnit will also look for another module whose name is
-<code>ModuleName</code> plus the suffix <code>_tests</code>, and if it exists, all the tests
-from that module will also be added. (If <code>ModuleName</code> already contains
-the suffix <code>_tests</code>, this is not done.) E.g., the specification
-<code>{module, mymodule}</code> will run all tests in the modules <code>mymodule</code> and
-<code>mymodule_tests</code>. Typically, the <code>_tests</code> module should only contain
-test cases that use the public interface of the main module (and no
-other code).
-</dd>
-<dt><code>{application, AppName::atom(), Info::list()}</code>
-</dt>
-<dd>This is a normal Erlang/OTP application descriptor, as found in an
- <code>.app</code> file. The resulting test set consists of the modules listed in
- the <code>modules</code> entry in <code>Info</code>.
-</dd>
-<dt><code>{application, AppName::atom()}</code>
-</dt>
-<dd>This creates a test set from all the modules belonging to the
-specified application, by consulting the application's <code>.app</code> file
-(see <code>{file, FileName}</code>), or if no such file exists, by testing all
-object files in the application's <tt>ebin</tt>-directory (see <code>{dir,
-Path}</code>); if that does not exist, the <code>code:lib_dir(AppName)</code> directory
-is used.
-</dd>
-<dt><code>Path::string()</code>
-</dt>
-<dd>A single string represents the path of a file or directory, and is
-equivalent to <code>{file, Path}</code>, or <code>{dir, Path}</code>, respectively, depending
-on what <code>Path</code> refers to in the file system.
-</dd>
-<dt><code>{file, FileName::string()}</code>
-</dt>
-<dd><p>If <code>FileName</code> has a suffix that indicates an object file (<code>.beam</code>),
-EUnit will try to reload the module from the specified file and test it.
-Otherwise, the file is assumed to be a text file containing test
-specifications, which will be read using the standard library function
-<code>file:path_consult/2</code>.</p>
-
-Unless the file name is absolute, the file is first searched for
-relative to the current directory, and then using the normal search path
-(<code>code:get_path()</code>). This means that the names of typical "app" files
-can be used directly, without a path, e.g., <code>"mnesia.app"</code>.
-</dd>
-<dt><code>{dir, Path::string()}</code>
-</dt>
-<dd>This tests all object files in the specified directory, as if they
-had been individually specified using <code>{file, FileName}</code>.
-</dd>
-<dt><code>{generator, GenFun::(() -&gt; Tests)}</code>
-</dt>
-<dd>The generator function <code>GenFun</code> is called to produce a test
-set.
-</dd>
-<dt><code>{generator, ModuleName::atom(), FunctionName::atom()}</code>
-</dt>
-<dd>The function <code>ModuleName:FunctionName()</code> is called to produce a test
-set.
-</dd>
-<dt><code>{with, X::any(), [AbstractTestFun::((any()) -&gt; any())]}</code>
-</dt>
-<dd>Distributes the value <code>X</code> over the unary functions in the list,
-turning them into nullary test functions. An <code>AbstractTestFun</code> is like
-an ordinary test fun, but takes one argument instead of zero - it's
-basically missing some information before it can be a proper test. In
-practice, <code>{with, X, [F_1, ..., F_N]}</code> is equivalent to <code>[fun () -&gt;
-F_1(X) end, ..., fun () -&gt; F_N(X) end]</code>. This is particularly useful if
-your abstract test functions are already implemented as proper
-functions: <code>{with, FD, [fun filetest_a/1, fun filetest_b/1, fun
-filetest_c/1]}</code> is equivalent to <code>[fun () -&gt; filetest_a(FD) end, fun ()
--&gt; filetest_b(FD) end, fun () -&gt; filetest_c(FD) end]</code>, but much more
-compact. See also <a href="#Fixtures">Fixtures</a>, below.
-</dd>
-</dl>
-
-<h4><a name="Control">Control</a></h4>
-
-The following representations control how and where tests are executed:
-<dl>
-<dt><code>{spawn, Tests}</code></dt>
-<dd>Runs the specified tests in a separate subprocess, while the current
-test process waits for it to finish. This is useful for tests that need
-a fresh, isolated process state. (Note that EUnit always starts at least
-one such a subprocess automatically; tests are never executed by the
-caller's own process.)</dd>
-<dt><code>{spawn, Node::atom(), Tests}</code></dt>
-<dd>Like <code>{spawn, Tests}</code>, but runs the specified tests on the given
-Erlang node.</dd>
-<dt><code>{timeout, Time::number(), Tests}</code></dt>
-<dd>Runs the specified tests under the given timeout. Time is in
-seconds; e.g., 60 means one minute and 0.1 means 1/10th of a second. If
-the timeout is exceeded, the unfinished tests will be forced to
-terminate. Note that if a timeout is set around a fixture, it includes
-the time for setup and cleanup, and if the timeout is triggered, the
-entire fixture is abruptly terminated (without running the
-cleanup).</dd>
-<dt><code>{inorder, Tests}</code></dt>
-<dd>Runs the specified tests in strict order. Also see <code>{inparallel,
-Tests}</code>. By default, tests are neither marked as <code>inorder</code> or
-<code>inparallel</code>, but may be executed as the test framework chooses.</dd>
-<dt><code>{inparallel, Tests}</code></dt>
-<dd>Runs the specified tests in parallel (if possible). Also see
-<code>{inorder, Tests}</code>.</dd>
-<dt><code>{inparallel, N::integer(), Tests}</code></dt>
-<dd>Like <code>{inparallel, Tests}</code>, but running no more than <code>N</code> subtests
-simultaneously.</dd>
-</dl>
-
-<h4><a name="Fixtures">Fixtures</a></h4>
-
-<p>A "fixture" is some state that is necessary for a particular set of
-tests to run. EUnit's support for fixtures makes it easy to set up such
-state locally for a test set, and automatically tear it down again when
-the test set is finished, regardless of the outcome (success, failures,
-timeouts, etc.).</p>
-
-<p>To make the descriptions simpler, we first list some definitions:
-<center>
-<table border="0" cellspacing="4">
-<tr>
-<td><code>Setup</code></td><td><code>() -&gt; (R::any())</code></td>
-</tr>
-<tr>
-<td><code>SetupX</code></td><td><code>(X::any()) -&gt; (R::any())</code></td>
-</tr>
-<tr>
-<td><code>Cleanup</code></td><td><code>(R::any()) -&gt; any()</code></td>
-</tr>
-<tr>
-<td><code>CleanupX</code></td><td><code>(X::any(), R::any()) -&gt; any()</code></td>
-</tr>
-<tr>
-<td><code>Instantiator</code></td><td><code>((R::any()) -&gt; Tests) | {with, [AbstractTestFun::((any()) -&gt; any())]}</code></td>
-</tr>
-<tr>
-<td><code>Where</code></td><td><code>local | spawn | {spawn, Node::atom()}</code></td>
-</tr>
-</table>
-</center>
-(these are explained in more detail further below.)</p>
-
-The following representations specify fixture handling for test sets:
-<dl>
-<dt><code>{setup, Setup, Tests | Instantiator}</code></dt>
-<dt><code>{setup, Setup, Cleanup, Tests | Instantiator}</code></dt>
-<dt><code>{setup, Where, Setup, Tests | Instantiator}</code></dt>
-<dt><code>{setup, Where, Setup, Cleanup, Tests | Instantiator}</code></dt>
-<dd><code>setup</code> sets up a single fixture for running all of the specified
-tests, with optional teardown afterwards. The arguments are described in
-detail below.
-</dd>
-<dt><code>{node, Node::atom(), Tests | Instantiator}</code></dt>
-<dt><code>{node, Node::atom(), Args::string(), Tests | Instantiator}</code></dt>
-<dd><code>node</code> is like <code>setup</code>, but with a built-in behaviour: it starts a
-slave node for the duration of the tests. The atom <code>Node</code> should have
-the format <code>[email protected]</code>, and <code>Args</code> are the optional
-arguments to the new node; see <code>slave:start_link/3</code> for details.
-</dd>
-<dt><code>{foreach, Where, Setup, Cleanup, [Tests | Instantiator]}</code></dt>
-<dt><code>{foreach, Setup, Cleanup, [Tests | Instantiator]}</code></dt>
-<dt><code>{foreach, Where, Setup, [Tests | Instantiator]}</code></dt>
-<dt><code>{foreach, Setup, [Tests | Instantiator]}</code></dt>
-<dd><code>foreach</code> is used to set up a fixture and optionally tear it down
-afterwards, repeated for each single one of the specified test sets.
-</dd>
-<dt><code>{foreachx, Where, SetupX, CleanupX,
- Pairs::[{X::any(), ((X::any(), R::any()) -&gt; Tests)}]}</code></dt>
-<dt><code>{foreachx, SetupX, CleanupX, Pairs}</code></dt>
-<dt><code>{foreachx, Where, SetupX, Pairs}</code></dt>
-<dt><code>{foreachx, SetupX, Pairs}</code></dt>
-<dd><code>foreachx</code> is like <code>foreach</code>, but uses a list of pairs, each
-containing an extra argument <code>X</code> and an extended instantiator function.
-</dd>
-</dl>
-
-<p>A <code>Setup</code> function is executed just before any of the specified tests
-are run, and a <code>Cleanup</code> function is executed when no more of the
-specified tests will be run, regardless of the reason. A <code>Setup</code>
-function takes no argument, and returns some value which will be passed
-as it is to the <code>Cleanup</code> function. A <code>Cleanup</code> function should do
-whatever necessary and return some arbitrary value, such as the atom
-<code>ok</code>. (<code>SetupX</code> and <code>CleanupX</code> functions are similar, but receive one
-additional argument: some value <code>X</code>, which depends on the context.) When
-no <code>Cleanup</code> function is specified, a dummy function is used which has
-no effect.</p>
-
-<p>An <code>Instantiator</code> function receives the same value as the <code>Cleanup</code>
-function, i.e., the value returned by the <code>Setup</code> function. It should
-then behave much like a generator (see <a href="#Primitives">Primitives</a>), and
-return a test set whose tests have been <em>instantiated</em> with the
-given value. A special case is the syntax <code>{with, [AbstractTestFun]}</code>
-which represents an instantiator function that distributes the value
-over a list of unary functions; see <a href="#Primitives">Primitives</a>: <code>{with, X,
-[...]}</code> for more details.</p>
-
-A <code>Where</code> term controls how the specified tests are executed. The
-default is <code>spawn</code>, which means that the current process handles the
-setup and teardown, while the tests are executed in a subprocess.
-<code>{spawn, Node}</code> is like <code>spawn</code>, but runs the subprocess on the
-specified node. <code>local</code> means that the current process will handle both
-setup/teardown and running the tests - the drawback is that if a test
-times out so that the process is killed, the <em>cleanup will not be
-performed</em>; hence, avoid this for persistent fixtures such as file
-operations. In general, 'local' should only be used when:
-<ul>
- <li>the setup/teardown needs to be executed by the process that will
- run the tests;</li>
- <li>no further teardown needs to be done if the process is killed
- (i.e., no state outside the process was affected by the setup)</li>
-</ul>
-
-<h4><a name="Lazy_generators">Lazy generators</a></h4>
-
-<p>Sometimes, it can be convenient not to produce the whole set of test
-descriptions before the testing begins; for example, if you want to
-generate a huge amount of tests that would take up too much space to
-keep in memory all at once.</p>
-
-<p>It is fairly easy to write a generator which, each time it is called,
-either produces an empty list if it is done, or otherwise produces a
-list containing a single test case plus a new generator which will
-produce the rest of the tests. This demonstrates the basic pattern:</p>
-
-<pre> lazy_test_() -&gt;
- lazy_gen(10000).
-
- lazy_gen(N) -&gt;
- {generator,
- fun () -&gt;
- if N &gt; 0 -&gt;
- [?_test(...)
- | lazy_gen(N-1)];
- true -&gt;
- []
- end
- end}.</pre>
-
-<p>When EUnit traverses the test representation in order to run the tests,
-the new generator will not be called to produce the next test until the
-previous test has been executed.</p>
-
-Note that it is easiest to write this kind of recursive generator using
-a help function, like the <code>lazy_gen/1</code> function above. It can also be
-written using a recursive fun, if you prefer to not clutter your
-function namespace and are comfortable with writing that kind of code.
-
-<hr>
-<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
-<p><i>Generated by EDoc, Apr 22 2009, 22:37:19.</i></p>
-</body>
-</html>
diff --git a/lib/eunit/doc/overview.edoc b/lib/eunit/doc/overview.edoc
index be05a13fba..ad449cb6fc 100644
--- a/lib/eunit/doc/overview.edoc
+++ b/lib/eunit/doc/overview.edoc
@@ -5,8 +5,7 @@
@title EUnit - a Lightweight Unit Testing Framework for Erlang
-@author Richard Carlsson <[email protected]>
- [http://user.it.uu.se/~richardc/]
+@author Richard Carlsson <[email protected]>
@author Micka�l R�mond <[email protected]>
[http://www.process-one.net/]
@copyright 2004-2007 Micka�l R�mond, Richard Carlsson
@@ -913,7 +912,7 @@ To make the descriptions simpler, we first list some definitions:
<td>`CleanupX'</td><td>`(X::any(), R::any()) -> any()'</td>
</tr>
<tr>
-<td>`Instantiator'</td><td>`((R::any()) -> Tests | {with, [AbstractTestFun::((any()) -> any())]}'</td>
+<td>`Instantiator'</td><td>`((R::any()) -> Tests) | {with, [AbstractTestFun::((any()) -> any())]}'</td>
</tr>
<tr>
<td>`Where'</td><td>`local | spawn | {spawn, Node::atom()}'</td>
diff --git a/lib/eunit/doc/packages-frame.html b/lib/eunit/doc/packages-frame.html
deleted file mode 100644
index 52b45534f5..0000000000
--- a/lib/eunit/doc/packages-frame.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<title>The eunit application</title>
-<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
-</head>
-<body bgcolor="white">
-<h2 class="indextitle">Packages</h2>
-<table width="100%" border="0" summary="list of packages"></table>
-</body>
-</html> \ No newline at end of file
diff --git a/lib/eunit/doc/src/notes.xml b/lib/eunit/doc/src/notes.xml
index a9960153e5..e68330482c 100644
--- a/lib/eunit/doc/src/notes.xml
+++ b/lib/eunit/doc/src/notes.xml
@@ -32,6 +32,103 @@
</header>
<p>This document describes the changes made to the EUnit application.</p>
+<section><title>Eunit 2.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Generate separate surefire XMLs for each test suite</p>
+ <p>
+ Previously the test cases of all test suites (=modules)
+ were put in one and the same surefire report XML thereby
+ breaking the principle of least astonishment and making
+ post analysis harder. Assume the following layout:</p>
+ <p>
+ src/x.erl src/y.erl test/x_tests.erl test/y_tests.erl</p>
+ <p>
+ The results for both x_tests and y_tests were written to
+ only one report grouped under either module x or y
+ (seemingly randomly).</p>
+ <p>
+ Now two reports, one for module x and one for y are
+ generated. (Thanks to Klas Johansson)</p>
+ <p>
+ Own Id: OTP-9465</p>
+ </item>
+ <item>
+ <p>
+ Updated to EUnit version 2.2.0</p>
+ <p>
+ New macros assertNotMatch(Guard, Expr),
+ assertNotEqual(Unexpected, Expr), and
+ assertNotException(Class, Term, Expr). </p>
+ <p>
+ The debugMsg macro now also prints the pid of the current
+ process.</p>
+ <p>
+ When testing all modules in a directory, tests in
+ Module_tests.erl are no longer executed twice.</p>
+ <p>
+ The use of regexp internally has been replaced with re.
+ (Thanks to Richard Carlsson)</p>
+ <p>
+ Own Id: OTP-9505</p>
+ </item>
+ <item>
+ <p>
+ Removed some never-matching clauses reported by dialyzer
+ Updated author e-mails and homepages Removed cvs keywords
+ from files Removed files that should not be checked in
+ (Thanks to Richard Carlsson)</p>
+ <p>
+ Own Id: OTP-9591</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Eunit 2.1.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Increase depth of error messages in Eunit Surefire
+ reports</p>
+ <p>
+ Currently, error messages in Eunit Surefire reports are
+ shortened just like when written to a terminal. However,
+ the space limitations that constrain terminal output do
+ not apply here, so it's more useful to include more of
+ the error message. The new depth of 100 should be enough
+ for most cases, while protecting against runaway errors.
+ (Thanks to Magnus Henoch)</p>
+ <p>
+ Own Id: OTP-9220</p>
+ </item>
+ <item>
+ <p>
+ Don't let eunit_surefire report back to eunit when
+ stopping</p>
+ <p>
+ When eunit is terminating, a stop message is sent to all
+ listeners and eunit then waits for *one* result message
+ but previously both eunit_tty and eunit_surefire sent a
+ response on error. Don't send a result message from
+ eunit_surefire; let eunit_tty take care of all result
+ reporting, both positive and negative to avoid race
+ conditions and inconsistencies. (Thanks to Klas
+ Johansson)</p>
+ <p>
+ Own Id: OTP-9269</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Eunit 2.1.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/eunit/doc/stylesheet.css b/lib/eunit/doc/stylesheet.css
deleted file mode 100644
index e426a90483..0000000000
--- a/lib/eunit/doc/stylesheet.css
+++ /dev/null
@@ -1,55 +0,0 @@
-/* standard EDoc style sheet */
-body {
- font-family: Verdana, Arial, Helvetica, sans-serif;
- margin-left: .25in;
- margin-right: .2in;
- margin-top: 0.2in;
- margin-bottom: 0.2in;
- color: #000000;
- background-color: #ffffff;
-}
-h1,h2 {
- margin-left: -0.2in;
-}
-div.navbar {
- background-color: #add8e6;
- padding: 0.2em;
-}
-h2.indextitle {
- padding: 0.4em;
- background-color: #add8e6;
-}
-h3.function,h3.typedecl {
- background-color: #add8e6;
- padding-left: 1em;
-}
-div.spec {
- margin-left: 2em;
- background-color: #eeeeee;
-}
-a.module,a.package {
- text-decoration:none
-}
-a.module:hover,a.package:hover {
- background-color: #eeeeee;
-}
-ul.definitions {
- list-style-type: none;
-}
-ul.index {
- list-style-type: none;
- background-color: #eeeeee;
-}
-
-/*
- * Minor style tweaks
- */
-ul {
- list-style-type: square;
-}
-table {
- border-collapse: collapse;
-}
-td {
- padding: 3
-}
diff --git a/lib/eunit/examples/Makefile b/lib/eunit/examples/Makefile
index d1b5bac224..48ec2ebf2b 100644
--- a/lib/eunit/examples/Makefile
+++ b/lib/eunit/examples/Makefile
@@ -13,8 +13,6 @@
# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
# AB. All Rights Reserved.''
#
-# $Id$
-#
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
diff --git a/lib/eunit/include/eunit.hrl b/lib/eunit/include/eunit.hrl
index 82ba982f03..db68d8ae60 100644
--- a/lib/eunit/include/eunit.hrl
+++ b/lib/eunit/include/eunit.hrl
@@ -13,8 +13,6 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: eunit.hrl 337 2009-03-09 08:38:28Z rcarlsson $
-%%
%% Copyright (C) 2004-2006 Micka�l R�mond, Richard Carlsson
%% Including this file turns on testing and defines TEST, unless NOTEST
@@ -39,6 +37,7 @@
-ifndef(EUNIT_HRL).
-define(EUNIT_HRL, true).
+
%% allow defining TEST to override NOTEST
-ifdef(TEST).
-undef(NOTEST).
@@ -164,7 +163,7 @@
%% This is mostly a convenience which gives more detailed reports.
%% Note: Guard is a guarded pattern, and can not be used for value.
-ifdef(NOASSERT).
--define(assertMatch(Guard,Expr),ok).
+-define(assertMatch(Guard, Expr), ok).
-else.
-define(assertMatch(Guard, Expr),
((fun () ->
@@ -174,17 +173,37 @@
[{module, ?MODULE},
{line, ?LINE},
{expression, (??Expr)},
- {expected, (??Guard)},
+ {pattern, (??Guard)},
{value, __V}]})
end
end)())).
-endif.
-define(_assertMatch(Guard, Expr), ?_test(?assertMatch(Guard, Expr))).
+%% This is the inverse case of assertMatch, for convenience.
+-ifdef(NOASSERT).
+-define(assertNotMatch(Guard, Expr), ok).
+-else.
+-define(assertNotMatch(Guard, Expr),
+ ((fun () ->
+ __V = (Expr),
+ case __V of
+ Guard -> .erlang:error({assertNotMatch_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {pattern, (??Guard)},
+ {value, __V}]});
+ _ -> ok
+ end
+ end)())).
+-endif.
+-define(_assertNotMatch(Guard, Expr), ?_test(?assertNotMatch(Guard, Expr))).
+
%% This is a convenience macro which gives more detailed reports when
%% the expected LHS value is not a pattern, but a computed value
-ifdef(NOASSERT).
--define(assertEqual(Expect,Expr),ok).
+-define(assertEqual(Expect, Expr), ok).
-else.
-define(assertEqual(Expect, Expr),
((fun (__X) ->
@@ -201,9 +220,29 @@
-endif.
-define(_assertEqual(Expect, Expr), ?_test(?assertEqual(Expect, Expr))).
+%% This is the inverse case of assertEqual, for convenience.
+-ifdef(NOASSERT).
+-define(assertNotEqual(Unexpected, Expr), ok).
+-else.
+-define(assertNotEqual(Unexpected, Expr),
+ ((fun (__X) ->
+ case (Expr) of
+ __X -> .erlang:error({assertNotEqual_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {value, __X}]});
+ _ -> ok
+ end
+ end)(Unexpected))).
+-endif.
+-define(_assertNotEqual(Unexpected, Expr),
+ ?_test(?assertNotEqual(Unexpected, Expr))).
+
%% Note: Class and Term are patterns, and can not be used for value.
+%% Term can be a guarded pattern, but Class cannot.
-ifdef(NOASSERT).
--define(assertException(Class, Term, Expr),ok).
+-define(assertException(Class, Term, Expr), ok).
-else.
-define(assertException(Class, Term, Expr),
((fun () ->
@@ -212,7 +251,7 @@
[{module, ?MODULE},
{line, ?LINE},
{expression, (??Expr)},
- {expected,
+ {pattern,
"{ "++(??Class)++" , "++(??Term)
++" , [...] }"},
{unexpected_success, __V}]})
@@ -223,7 +262,7 @@
[{module, ?MODULE},
{line, ?LINE},
{expression, (??Expr)},
- {expected,
+ {pattern,
"{ "++(??Class)++" , "++(??Term)
++" , [...] }"},
{unexpected_exception,
@@ -243,6 +282,43 @@
-define(_assertExit(Term, Expr), ?_assertException(exit, Term, Expr)).
-define(_assertThrow(Term, Expr), ?_assertException(throw, Term, Expr)).
+%% This is the inverse case of assertException, for convenience.
+%% Note: Class and Term are patterns, and can not be used for value.
+%% Both Class and Term can be guarded patterns.
+-ifdef(NOASSERT).
+-define(assertNotException(Class, Term, Expr), ok).
+-else.
+-define(assertNotException(Class, Term, Expr),
+ ((fun () ->
+ try (Expr) of
+ _ -> ok
+ catch
+ __C:__T ->
+ case __C of
+ Class ->
+ case __T of
+ Term ->
+ .erlang:error({assertNotException_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {pattern,
+ "{ "++(??Class)++" , "
+ ++(??Term)++" , [...] }"},
+ {unexpected_exception,
+ {__C, __T,
+ .erlang:get_stacktrace()
+ }}]});
+ _ -> ok
+ end;
+ _ -> ok
+ end
+ end
+ end)())).
+-endif.
+-define(_assertNotException(Class, Term, Expr),
+ ?_test(?assertNotException(Class, Term, Expr))).
+
%% Macros for running operating system commands. (Note that these
%% require EUnit to be present at runtime, or at least eunit_lib.)
@@ -267,7 +343,7 @@
%% these are only used for testing; they always return 'ok' on success,
%% and have no effect if debugging/testing is turned off
-ifdef(NOASSERT).
--define(assertCmdStatus(N, Cmd),ok).
+-define(assertCmdStatus(N, Cmd), ok).
-else.
-define(assertCmdStatus(N, Cmd),
((fun () ->
@@ -285,7 +361,7 @@
-define(assertCmd(Cmd), ?assertCmdStatus(0, Cmd)).
-ifdef(NOASSERT).
--define(assertCmdOutput(T, Cmd),ok).
+-define(assertCmdOutput(T, Cmd), ok).
-else.
-define(assertCmdOutput(T, Cmd),
((fun () ->
@@ -313,11 +389,12 @@
-define(debugHere, ok).
-define(debugFmt(S, As), ok).
-define(debugVal(E), (E)).
--define(debugTime(S,E), (E)).
+-define(debugTime(S, E), (E)).
-else.
-define(debugMsg(S),
(begin
- .io:fwrite(user, <<"~s:~w: ~s\n">>, [?FILE, ?LINE, S]),
+ .io:fwrite(user, <<"~s:~w:~w: ~s\n">>,
+ [?FILE, ?LINE, self(), S]),
ok
end)).
-define(debugHere, (?debugMsg("<-"))).
@@ -327,7 +404,7 @@
?debugFmt(<<"~s = ~P">>, [(??E), __V, 15]),
__V
end)(E))).
--define(debugTime(S,E),
+-define(debugTime(S, E),
((fun () ->
{__T0, _} = statistics(wall_clock),
__V = (E),
@@ -337,4 +414,5 @@
end)())).
-endif.
+
-endif. % EUNIT_HRL
diff --git a/lib/eunit/src/Makefile b/lib/eunit/src/Makefile
index 4897c20ec1..bec2fdbe0b 100644
--- a/lib/eunit/src/Makefile
+++ b/lib/eunit/src/Makefile
@@ -26,8 +26,9 @@ INCLUDE=../include
ERL_COMPILE_FLAGS += -pa $(EBIN) -I$(INCLUDE) +warn_unused_vars +nowarn_shadow_vars +warn_unused_import +warn_obsolete_guard
+PARSE_TRANSFORM = eunit_autoexport.erl
+
SOURCES= \
- eunit_autoexport.erl \
eunit_striptests.erl \
eunit.erl \
eunit_tests.erl \
@@ -43,6 +44,8 @@ SOURCES= \
INCLUDE_FILES = eunit.hrl
+PARSE_TRANSFORM_BIN = $(PARSE_TRANSFORM:%.erl=$(EBIN)/%.$(EMULATOR))
+
OBJECTS=$(SOURCES:%.erl=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
INCLUDE_DELIVERABLES = $(INCLUDE_FILES:%=$(INCLUDE)/%)
@@ -59,7 +62,7 @@ APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
# Targets
# ----------------------------------------------------
-debug opt: $(OBJECTS)
+debug opt: $(PARSE_TRANSFORM_BIN) $(OBJECTS)
docs:
@@ -86,6 +89,8 @@ realclean: clean
$(EBIN)/%.$(EMULATOR):%.erl
erlc -W $(ERL_COMPILE_FLAGS) -o$(EBIN) $<
+$(OBJECTS): $(PARSE_TRANSFORM_BIN)
+
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
@@ -103,9 +108,9 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(OBJECTS) $(RELSYSDIR)/ebin
+ $(INSTALL_DATA) $(PARSE_TRANSFORM_BIN) $(OBJECTS) $(RELSYSDIR)/ebin
$(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(SOURCES) $(RELSYSDIR)/src
+ $(INSTALL_DATA) $(PARSE_TRANSFORM) $(SOURCES) $(RELSYSDIR)/src
$(INSTALL_DIR) $(RELSYSDIR)/include
$(INSTALL_DATA) $(INCLUDE_DELIVERABLES) $(RELSYSDIR)/include
diff --git a/lib/eunit/src/eunit.app.src b/lib/eunit/src/eunit.app.src
index 4fd76588c3..5e16dfa2ce 100644
--- a/lib/eunit/src/eunit.app.src
+++ b/lib/eunit/src/eunit.app.src
@@ -5,17 +5,17 @@
{vsn, "%VSN%"},
{modules, [eunit,
eunit_autoexport,
- eunit_striptests,
- eunit_server,
+ eunit_data,
+ eunit_lib,
+ eunit_listener,
eunit_proc,
eunit_serial,
+ eunit_server,
+ eunit_striptests,
+ eunit_surefire,
eunit_test,
eunit_tests,
- eunit_lib,
- eunit_listener,
- eunit_data,
- eunit_tty,
- eunit_surefire]},
+ eunit_tty]},
{registered,[]},
- {applications, [stdlib]},
+ {applications, [kernel,stdlib]},
{env, []}]}.
diff --git a/lib/eunit/src/eunit.erl b/lib/eunit/src/eunit.erl
index 4a86a108cf..95857e83c8 100644
--- a/lib/eunit/src/eunit.erl
+++ b/lib/eunit/src/eunit.erl
@@ -13,13 +13,10 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: eunit.erl 339 2009-04-05 14:10:47Z rcarlsson $
-%%
%% @copyright 2004-2009 Micka�l R�mond, Richard Carlsson
-%% @author Micka&euml;l R&eacute;mond <[email protected]>
+%% @author Micka�l R�mond <[email protected]>
%% [http://www.process-one.net/]
-%% @author Richard Carlsson <[email protected]>
-%% [http://user.it.uu.se/~richardc/]
+%% @author Richard Carlsson <[email protected]>
%% @version {@version}, {@date} {@time}
%% @doc This module is the main EUnit user interface.
@@ -157,6 +154,7 @@ test_run(Reference, Listeners) ->
receive
{done, Reference} ->
cast(Listeners, {stop, Reference, self()}),
+ wait_until_listeners_have_terminated(Listeners),
receive
{result, Reference, Result} ->
Result
@@ -169,6 +167,15 @@ cast([P | Ps], Msg) ->
cast([], _Msg) ->
ok.
+wait_until_listeners_have_terminated([P | Ps]) ->
+ MRef = erlang:monitor(process, P),
+ receive
+ {'DOWN', MRef, process, P, _} ->
+ wait_until_listeners_have_terminated(Ps)
+ end;
+wait_until_listeners_have_terminated([]) ->
+ ok.
+
%% TODO: functions that run tests on a given node, not a given server
%% TODO: maybe some functions could check for a globally registered server?
%% TODO: some synchronous but completely quiet interface function
diff --git a/lib/eunit/src/eunit_autoexport.erl b/lib/eunit/src/eunit_autoexport.erl
index 7b153c1194..099bcb222e 100644
--- a/lib/eunit/src/eunit_autoexport.erl
+++ b/lib/eunit/src/eunit_autoexport.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: eunit_autoexport.erl 329 2009-03-01 11:23:32Z rcarlsson $
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2006 Richard Carlsson
%% @private
%% @see eunit
diff --git a/lib/eunit/src/eunit_data.erl b/lib/eunit/src/eunit_data.erl
index 0543b6c543..392d378a0e 100644
--- a/lib/eunit/src/eunit_data.erl
+++ b/lib/eunit/src/eunit_data.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2006 Richard Carlsson
%% @private
%% @see eunit
@@ -146,8 +144,10 @@ iter_next(I = #iter{next = [T | Ts]}) ->
iter_prev(#iter{prev = []}) ->
none;
-iter_prev(#iter{prev = [T | Ts], next = Next, pos = Pos} = I) ->
- {T, I#iter{prev = Ts, next = [T | Next], pos = Pos - 1}}.
+iter_prev(#iter{prev = [T | Ts]} = I) ->
+ {T, I#iter{prev = Ts,
+ next = [T | I#iter.next],
+ pos = I#iter.pos - 1}}.
%% ---------------------------------------------------------------------
@@ -363,7 +363,8 @@ parse({file, F} = T) when is_list(F) ->
parse({dir, D}=T) when is_list(D) ->
case eunit_lib:is_string(D) of
true ->
- {data, {"directory \"" ++ D ++ "\"", get_directory_modules(D)}};
+ {data, {"directory \"" ++ D ++ "\"",
+ get_directory_module_tests(D)}};
false ->
bad_test(T)
end;
@@ -385,10 +386,10 @@ parse({S, T1} = T) when is_list(S) ->
end;
parse({S, T1}) when is_binary(S) ->
group(#group{tests = T1, desc = S});
-parse(T) when tuple_size(T) > 2, is_list(element(1, T)) ->
+parse(T) when is_tuple(T), size(T) > 2, is_list(element(1, T)) ->
[S | Es] = tuple_to_list(T),
parse({S, list_to_tuple(Es)});
-parse(T) when tuple_size(T) > 2, is_binary(element(1, T)) ->
+parse(T) when is_tuple(T), size(T) > 2, is_binary(element(1, T)) ->
[S | Es] = tuple_to_list(T),
parse({S, list_to_tuple(Es)});
parse(M) when is_atom(M) ->
@@ -596,7 +597,7 @@ testfuns(Es, M, TestSuffix, GeneratorSuffix) ->
%% ---------------------------------------------------------------------
-%% Getting a test set from a file
+%% Getting a test set from a file (text file or object file)
%% @throws {file_read_error, {Reason::atom(), Message::string(),
%% fileName()}}
@@ -625,17 +626,23 @@ get_file_tests(F) ->
is_module_filename(F) ->
filename:extension(F) =:= code:objfile_extension().
+objfile_test({M, File}) ->
+ {setup,
+ fun () ->
+ %% TODO: better error/stacktrace for this internal fun
+ code:purge(M),
+ {module,M} = code:load_abs(filename:rootname(File)),
+ ok
+ end,
+ {module, M}};
objfile_test(File) ->
+ objfile_test({objfile_module(File), File}).
+
+objfile_module(File) ->
try
- {module, M} = lists:keyfind(module, 1, beam_lib:info(File)),
- {setup,
- fun () ->
- %% TODO: better error/stacktrace for this internal fun
- code:purge(M),
- {module,M} = code:load_abs(filename:rootname(File)),
- ok
- end,
- {module, M}}
+ {value, {module, M}} = lists:keysearch(module, 1,
+ beam_lib:info(File)),
+ M
catch
_:_ ->
throw({file_read_error,
@@ -644,15 +651,34 @@ objfile_test(File) ->
%% ---------------------------------------------------------------------
-%% Getting a list of module names from object files in a directory
-
-%% @throws {file_read_error, {Reason::atom(), Message::string(),
-%% fileName()}}
+%% Getting a set of module tests from the object files in a directory
+
+%% @throws {file_read_error,
+%% {Reason::atom(), Message::string(), fileName()}}
+
+get_directory_module_tests(D) ->
+ Ms = get_directory_modules(D),
+ %% for all 'm' in the set, remove 'm_tests' if present
+ F = fun ({M,_}, S) ->
+ Name = atom_to_list(M),
+ case lists:suffix(?DEFAULT_TESTMODULE_SUFFIX, Name) of
+ false ->
+ Name1 = Name ++ ?DEFAULT_TESTMODULE_SUFFIX,
+ M1 = list_to_atom(Name1),
+ dict:erase(M1, S);
+ true ->
+ S
+ end
+ end,
+ [objfile_test(Obj)
+ || Obj <- dict:to_list(lists:foldl(F, dict:from_list(Ms), Ms))].
%% TODO: handle packages (recursive search for files)
-
get_directory_modules(D) ->
- [objfile_test(filename:join(D, F))
+ [begin
+ F1 = filename:join(D, F),
+ {objfile_module(F1), F1}
+ end
|| F <- eunit_lib:list_dir(D), is_module_filename(F)].
diff --git a/lib/eunit/src/eunit_internal.hrl b/lib/eunit/src/eunit_internal.hrl
index 8d0ac30bd7..92694ec39b 100644
--- a/lib/eunit/src/eunit_internal.hrl
+++ b/lib/eunit/src/eunit_internal.hrl
@@ -1,11 +1,7 @@
%% -------------------------------------------------------------------
%% File: eunit_internal.hrl
%%
-%% $Id: eunit_internal.hrl 329 2009-03-01 11:23:32Z rcarlsson $
-%%
-%% @author Richard Carlsson <[email protected]>
-%% @copyright 2006 Richard Carlsson
-%% @doc
+%% Copyright (C) 2006 Richard Carlsson <[email protected]>
-define(SERVER, eunit_server).
-define(DEFAULT_TEST_SUFFIX, "_test").
diff --git a/lib/eunit/src/eunit_lib.erl b/lib/eunit/src/eunit_lib.erl
index 4751f1094a..1c41e229c5 100644
--- a/lib/eunit/src/eunit_lib.erl
+++ b/lib/eunit/src/eunit_lib.erl
@@ -13,13 +13,10 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: eunit_lib.erl 339 2009-04-05 14:10:47Z rcarlsson $
-%%
%% @copyright 2004-2007 Micka�l R�mond, Richard Carlsson
%% @author Micka�l R�mond <[email protected]>
%% [http://www.process-one.net/]
-%% @author Richard Carlsson <[email protected]>
-%% [http://user.it.uu.se/~richardc/]
+%% @author Richard Carlsson <[email protected]>
%% @private
%% @see eunit
%% @doc Utility functions for eunit
@@ -33,7 +30,7 @@
-export([dlist_next/1, uniq/1, fun_parent/1, is_string/1, command/1,
command/2, command/3, trie_new/0, trie_store/2, trie_match/2,
split_node/1, consult_file/1, list_dir/1, format_exit_term/1,
- format_exception/1, format_error/1]).
+ format_exception/1, format_exception/2, format_error/1]).
%% Type definitions for describing exceptions
@@ -55,21 +52,23 @@
%% ---------------------------------------------------------------------
%% Formatting of error descriptors
+format_exception(Exception) ->
+ format_exception(Exception, 20).
-format_exception({Class,Term,Trace})
+format_exception({Class,Term,Trace}, Depth)
when is_atom(Class), is_list(Trace) ->
case is_stacktrace(Trace) of
true ->
io_lib:format("~w:~P\n~s",
- [Class, Term, 20, format_stacktrace(Trace)]);
+ [Class, Term, Depth, format_stacktrace(Trace)]);
false ->
- format_term(Term)
+ format_term(Term, Depth)
end;
-format_exception(Term) ->
- format_term(Term).
+format_exception(Term, Depth) ->
+ format_term(Term, Depth).
-format_term(Term) ->
- io_lib:format("~P\n", [Term, 15]).
+format_term(Term, Depth) ->
+ io_lib:format("~P\n", [Term, Depth]).
format_exit_term(Term) ->
{Reason, Trace} = analyze_exit_term(Term),
diff --git a/lib/eunit/src/eunit_listener.erl b/lib/eunit/src/eunit_listener.erl
index 20faecbf01..ecaac424a2 100644
--- a/lib/eunit/src/eunit_listener.erl
+++ b/lib/eunit/src/eunit_listener.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2009 Richard Carlsson
%% @private
%% @see eunit
diff --git a/lib/eunit/src/eunit_proc.erl b/lib/eunit/src/eunit_proc.erl
index e2d51d8bd5..ec7d93fd48 100644
--- a/lib/eunit/src/eunit_proc.erl
+++ b/lib/eunit/src/eunit_proc.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2006 Richard Carlsson
%% @private
%% @see eunit
diff --git a/lib/eunit/src/eunit_serial.erl b/lib/eunit/src/eunit_serial.erl
index d9ccae86f9..80e79116e3 100644
--- a/lib/eunit/src/eunit_serial.erl
+++ b/lib/eunit/src/eunit_serial.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id$
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2006 Richard Carlsson
%% @private
%% @see eunit
diff --git a/lib/eunit/src/eunit_server.erl b/lib/eunit/src/eunit_server.erl
index bf1bb9bcef..2002930abb 100644
--- a/lib/eunit/src/eunit_server.erl
+++ b/lib/eunit/src/eunit_server.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: eunit_server.erl 267 2008-10-19 18:48:03Z rcarlsson $
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2006 Richard Carlsson
%% @private
%% @see eunit
@@ -59,8 +57,9 @@ watch(Server, Module, Opts) when is_atom(Module) ->
watch_path(Server, Path, Opts) ->
command(Server, {watch, {path, filename:flatten(Path)}, Opts}).
+%% note that the user must use $ at the end to match whole paths only
watch_regexp(Server, Regex, Opts) ->
- case regexp:parse(Regex) of
+ case re:compile(Regex,[anchored]) of
{ok, R} ->
command(Server, {watch, {regexp, R}, Opts});
{error, _}=Error ->
@@ -278,8 +277,8 @@ is_watched(Path, St) ->
match_any(sets:to_list(St#state.regexps), Path).
match_any([R | Rs], Str) ->
- case regexp:first_match(Str, R) of
- {match, _, _} -> true;
+ case re:run(Str, R, [{capture,none}]) of
+ match -> true;
_ -> match_any(Rs, Str)
end;
match_any([], _Str) -> false.
diff --git a/lib/eunit/src/eunit_striptests.erl b/lib/eunit/src/eunit_striptests.erl
index 606e44b286..c6ade389ba 100644
--- a/lib/eunit/src/eunit_striptests.erl
+++ b/lib/eunit/src/eunit_striptests.erl
@@ -13,10 +13,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: eunit_striptests.erl 329 2009-03-01 11:23:32Z rcarlsson $
-%%
-%% @author Richard Carlsson <[email protected]>
-%% @author Eric Merritt <[email protected]>
+%% @author Richard Carlsson <[email protected]>
+%% @author Eric Merritt <[email protected]>
%% @copyright 2006 Richard Carlsson, Eric Merritt
%% @private
%% @see eunit
diff --git a/lib/eunit/src/eunit_surefire.erl b/lib/eunit/src/eunit_surefire.erl
index eb994a990a..2a6cbca14d 100644
--- a/lib/eunit/src/eunit_surefire.erl
+++ b/lib/eunit/src/eunit_surefire.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: $
-%%
-%% @author Micka&euml;l R&eacute;mond <[email protected]>
+%% @author Micka�l R�mond <[email protected]>
%% @copyright 2009 Micka�l R�mond, Paul Guyot
%% @see eunit
%% @doc Surefire reports for EUnit (Format used by Maven and Atlassian
@@ -58,12 +56,13 @@
{
name :: chars(),
description :: chars(),
- result :: ok | {failed, tuple()} | {aborted, tuple()} | {skipped, tuple()},
+ result :: ok | {failed, tuple()} | {aborted, tuple()} | {skipped, term()},
time :: integer(),
output :: binary()
}).
-record(testsuite,
{
+ id = 0 :: integer(),
name = <<>> :: binary(),
time = 0 :: integer(),
output = <<>> :: binary(),
@@ -76,7 +75,7 @@
-record(state, {verbose = false,
indent = 0,
xmldir = ".",
- testsuite = #testsuite{}
+ testsuites = [] :: [#testsuite{}]
}).
start() ->
@@ -89,61 +88,60 @@ init(Options) ->
XMLDir = proplists:get_value(dir, Options, ?XMLDIR),
St = #state{verbose = proplists:get_bool(verbose, Options),
xmldir = XMLDir,
- testsuite = #testsuite{}},
+ testsuites = []},
receive
{start, _Reference} ->
St
end.
terminate({ok, _Data}, St) ->
- TestSuite = St#state.testsuite,
+ TestSuites = St#state.testsuites,
XmlDir = St#state.xmldir,
- write_report(TestSuite, XmlDir),
+ write_reports(TestSuites, XmlDir),
ok;
-terminate({error, Reason}, _St) ->
- io:fwrite("Internal error: ~P.\n", [Reason, 25]),
- sync_end(error).
-
-sync_end(Result) ->
- receive
- {stop, Reference, ReplyTo} ->
- ReplyTo ! {result, Reference, Result},
- ok
- end.
-
-handle_begin(group, Data, St) ->
+terminate({error, _Reason}, _St) ->
+ %% Don't report any errors here, since eunit_tty takes care of that.
+ %% Just terminate.
+ ok.
+
+handle_begin(Kind, Data, St) when Kind == group; Kind == test ->
+ %% Run this code both for groups and tests; test is a bit
+ %% surprising: This is a workaround for the fact that we don't get
+ %% a group (handle_begin(group, ...) for testsuites (modules)
+ %% which only have one test case. In that case we get a test case
+ %% with an id comprised of just one integer - the group id.
NewId = proplists:get_value(id, Data),
case NewId of
[] ->
St;
- [_GroupId] ->
+ [GroupId] ->
Desc = proplists:get_value(desc, Data),
- TestSuite = St#state.testsuite,
- NewTestSuite = TestSuite#testsuite{name = Desc},
- St#state{testsuite=NewTestSuite};
+ TestSuite = #testsuite{id = GroupId, name = Desc},
+ St#state{testsuites=store_suite(TestSuite, St#state.testsuites)};
%% Surefire format is not hierarchic: Ignore subgroups:
_ ->
St
- end;
-handle_begin(test, _Data, St) ->
- St.
+ end.
handle_end(group, Data, St) ->
%% Retrieve existing test suite:
case proplists:get_value(id, Data) of
[] ->
St;
- [_GroupId|_] ->
- TestSuite = St#state.testsuite,
+ [GroupId|_] ->
+ TestSuites = St#state.testsuites,
+ TestSuite = lookup_suite_by_group_id(GroupId, TestSuites),
%% Update TestSuite data:
Time = proplists:get_value(time, Data),
Output = proplists:get_value(output, Data),
NewTestSuite = TestSuite#testsuite{ time = Time, output = Output },
- St#state{testsuite=NewTestSuite}
+ St#state{testsuites=store_suite(NewTestSuite, TestSuites)}
end;
handle_end(test, Data, St) ->
%% Retrieve existing test suite:
- TestSuite = St#state.testsuite,
+ [GroupId|_] = proplists:get_value(id, Data),
+ TestSuites = St#state.testsuites,
+ TestSuite = lookup_suite_by_group_id(GroupId, TestSuites),
%% Create test case:
Name = format_name(proplists:get_value(source, Data),
@@ -155,7 +153,7 @@ handle_end(test, Data, St) ->
TestCase = #testcase{name = Name, description = Desc,
time = Time,output = Output},
NewTestSuite = add_testcase_to_testsuite(Result, TestCase, TestSuite),
- St#state{testsuite=NewTestSuite}.
+ St#state{testsuites=store_suite(NewTestSuite, TestSuites)}.
%% Cancel group does not give information on the individual cancelled test case
%% We ignore this event
@@ -163,7 +161,9 @@ handle_cancel(group, _Data, St) ->
St;
handle_cancel(test, Data, St) ->
%% Retrieve existing test suite:
- TestSuite = St#state.testsuite,
+ [GroupId|_] = proplists:get_value(id, Data),
+ TestSuites = St#state.testsuites,
+ TestSuite = lookup_suite_by_group_id(GroupId, TestSuites),
%% Create test case:
Name = format_name(proplists:get_value(source, Data),
@@ -177,7 +177,7 @@ handle_cancel(test, Data, St) ->
NewTestSuite = TestSuite#testsuite{
skipped = TestSuite#testsuite.skipped+1,
testcases=[TestCase|TestSuite#testsuite.testcases] },
- St#state{testsuite=NewTestSuite}.
+ St#state{testsuites=store_suite(NewTestSuite, TestSuites)}.
format_name({Module, Function, Arity}, Line) ->
lists:flatten([atom_to_list(Module), ":", atom_to_list(Function), "/",
@@ -189,6 +189,12 @@ format_desc(Desc) when is_binary(Desc) ->
format_desc(Desc) when is_list(Desc) ->
Desc.
+lookup_suite_by_group_id(GroupId, TestSuites) ->
+ #testsuite{} = lists:keyfind(GroupId, #testsuite.id, TestSuites).
+
+store_suite(#testsuite{id=GroupId} = TestSuite, TestSuites) ->
+ lists:keystore(GroupId, #testsuite.id, TestSuites, TestSuite).
+
%% Add testcase to testsuite depending on the result of the test.
add_testcase_to_testsuite(ok, TestCaseTmp, TestSuite) ->
TestCase = TestCaseTmp#testcase{ result = ok },
@@ -220,6 +226,10 @@ add_testcase_to_testsuite({error, Exception}, TestCaseTmp, TestSuite) ->
%% Write a report to the XML directory.
%% This function opens the report file, calls write_report_to/2 and closes the file.
%% ----------------------------------------------------------------------------
+write_reports(TestSuites, XmlDir) ->
+ lists:foreach(fun(TestSuite) -> write_report(TestSuite, XmlDir) end,
+ TestSuites).
+
write_report(#testsuite{name = Name} = TestSuite, XmlDir) ->
Filename = filename:join(XmlDir, lists:flatten(["TEST-", escape_suitename(Name)], ".xml")),
case file:open(Filename, [write, raw]) of
@@ -299,7 +309,6 @@ write_testcase(
output = Output},
FileDescriptor) ->
DescriptionAttr = case Description of
- <<>> -> [];
[] -> [];
_ -> [<<" description=\"">>, escape_attr(Description), <<"\"">>]
end,
@@ -308,7 +317,6 @@ write_testcase(
<<"\" name=\"">>, escape_attr(Name), <<"\"">>,
DescriptionAttr],
ContentAndEndTag = case {Result, Output} of
- {ok, []} -> [<<"/>">>, ?NEWLINE];
{ok, <<>>} -> [<<"/>">>, ?NEWLINE];
_ -> [<<">">>, ?NEWLINE, format_testcase_result(Result), format_testcase_output(Output), ?INDENT, <<"</testcase>">>, ?NEWLINE]
end,
@@ -323,7 +331,7 @@ write_testcase(
format_testcase_result(ok) -> [<<>>];
format_testcase_result({failed, {error, {Type, _}, _} = Exception}) when is_atom(Type) ->
[?INDENT, ?INDENT, <<"<failure type=\"">>, escape_attr(atom_to_list(Type)), <<"\">">>, ?NEWLINE,
- <<"::">>, escape_text(eunit_lib:format_exception(Exception)),
+ <<"::">>, escape_text(eunit_lib:format_exception(Exception, 100)),
?INDENT, ?INDENT, <<"</failure>">>, ?NEWLINE];
format_testcase_result({failed, Term}) ->
[?INDENT, ?INDENT, <<"<failure type=\"unknown\">">>, ?NEWLINE,
@@ -331,7 +339,7 @@ format_testcase_result({failed, Term}) ->
?INDENT, ?INDENT, <<"</failure>">>, ?NEWLINE];
format_testcase_result({aborted, {Class, _Term, _Trace} = Exception}) when is_atom(Class) ->
[?INDENT, ?INDENT, <<"<error type=\"">>, escape_attr(atom_to_list(Class)), <<"\">">>, ?NEWLINE,
- <<"::">>, escape_text(eunit_lib:format_exception(Exception)),
+ <<"::">>, escape_text(eunit_lib:format_exception(Exception, 100)),
?INDENT, ?INDENT, <<"</error>">>, ?NEWLINE];
format_testcase_result({aborted, Term}) ->
[?INDENT, ?INDENT, <<"<error type=\"unknown\">">>, ?NEWLINE,
@@ -357,7 +365,6 @@ format_testcase_result({skipped, Term}) ->
%% Empty output is simply the empty string.
%% Other output is inside a <system-out> xml tag.
%% ----------------------------------------------------------------------------
-format_testcase_output([]) -> [];
format_testcase_output(Output) ->
[?INDENT, ?INDENT, <<"<system-out>">>, escape_text(Output), ?NEWLINE, ?INDENT, ?INDENT, <<"</system-out>">>, ?NEWLINE].
@@ -375,8 +382,6 @@ format_time_s([Digit1, Digit2, Digit3 | Tail]) -> [lists:reverse(Tail), $., Digi
%% Escape a suite's name to generate the filename.
%% Remark: we might overwrite another testsuite's file.
%% ----------------------------------------------------------------------------
-escape_suitename([Head | _T] = List) when is_list(Head) ->
- escape_suitename(lists:flatten(List));
escape_suitename(Binary) when is_binary(Binary) ->
escape_suitename(binary_to_list(Binary));
escape_suitename("module '" ++ String) ->
@@ -384,7 +389,6 @@ escape_suitename("module '" ++ String) ->
escape_suitename(String) ->
escape_suitename(String, []).
-escape_suitename(Binary, Acc) when is_binary(Binary) -> escape_suitename(binary_to_list(Binary), Acc);
escape_suitename([], Acc) -> lists:reverse(Acc);
escape_suitename([$ | Tail], Acc) -> escape_suitename(Tail, [$_ | Acc]);
escape_suitename([$' | Tail], Acc) -> escape_suitename(Tail, Acc);
diff --git a/lib/eunit/src/eunit_test.erl b/lib/eunit/src/eunit_test.erl
index d322c4b420..bca49ae626 100644
--- a/lib/eunit/src/eunit_test.erl
+++ b/lib/eunit/src/eunit_test.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: eunit_test.erl 336 2009-03-06 14:43:21Z rcarlsson $
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2006 Richard Carlsson
%% @private
%% @see eunit
@@ -131,12 +129,27 @@ macro_test_() ->
[{module,_},
{line,_},
{expression,_},
- {expected,"[ _ ]"},
+ {pattern,"[ _ ]"},
{value,[]}]},
_}}
= run_testfun(F)
end),
?_test(begin
+ {?LINE, F} = ?_assertNotMatch(ok, error),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertNotMatch([_], [42]),
+ {error,{error,{assertNotMatch_failed,
+ [{module,_},
+ {line,_},
+ {expression,_},
+ {pattern,"[ _ ]"},
+ {value,[42]}]},
+ _}}
+ = run_testfun(F)
+ end),
+ ?_test(begin
{?LINE, F} = ?_assertEqual(ok, ok),
{ok, ok} = run_testfun(F)
end),
@@ -152,6 +165,20 @@ macro_test_() ->
= run_testfun(F)
end),
?_test(begin
+ {?LINE, F} = ?_assertNotEqual(1, 0),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertNotEqual(2, 1+1),
+ {error,{error,{assertNotEqual_failed,
+ [{module,_},
+ {line,_},
+ {expression,_},
+ {value,2}]},
+ _}}
+ = run_testfun(F)
+ end),
+ ?_test(begin
{?LINE, F} = ?_assertException(error, badarith,
erlang:error(badarith)),
{ok, ok} = run_testfun(F)
@@ -162,7 +189,7 @@ macro_test_() ->
[{module,_},
{line,_},
{expression,_},
- {expected,_},
+ {pattern,_},
{unexpected_success,ok}]},
_}}
= run_testfun(F)
@@ -174,15 +201,48 @@ macro_test_() ->
[{module,_},
{line,_},
{expression,_},
- {expected,_},
+ {pattern,_},
+ {unexpected_exception,
+ {error,badarith,_}}]},
+ _}}
+ = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertError(badarith,
+ erlang:error(badarith)),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertExit(normal, exit(normal)),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertThrow(foo, throw(foo)),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertNotException(error, badarith, 42),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertNotException(error, badarith,
+ erlang:error(badarg)),
+ {ok, ok} = run_testfun(F)
+ end),
+ ?_test(begin
+ {?LINE, F} = ?_assertNotException(error, badarith,
+ erlang:error(badarith)),
+ {error,{error,{assertNotException_failed,
+ [{module,_},
+ {line,_},
+ {expression,_},
+ {pattern,_},
{unexpected_exception,
{error,badarith,_}}]},
_}}
= run_testfun(F)
end)
]}.
-
-under_eunit_test() -> ?assert(?UNDER_EUNIT).
-endif.
diff --git a/lib/eunit/src/eunit_tests.erl b/lib/eunit/src/eunit_tests.erl
index 37c0b4d6ae..47ea0aaf46 100644
--- a/lib/eunit/src/eunit_tests.erl
+++ b/lib/eunit/src/eunit_tests.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: eunit_tests.erl 238 2007-11-15 10:23:54Z mremond $
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2007 Richard Carlsson
%% @private
%% @see eunit
@@ -26,17 +24,17 @@
-include("eunit.hrl").
-ifdef(TEST).
-%% Cause all the other modules to be tested as well as this one.
-full_test_() ->
- %%{application, eunit}. % this currently causes a loop
- %% We use the below until loop detection is implemented
- [eunit_autoexport,
- eunit_striptests,
- eunit_server,
- eunit_proc,
- eunit_serial,
- eunit_test,
- eunit_lib,
- eunit_data,
- eunit_tty].
+id(X) -> X. % for suppressing compiler warnings
-endif.
+
+under_eunit_test() -> ?assert(?UNDER_EUNIT).
+
+let_test() -> ?assertEqual(42, ?LET(X, 17, X+25)).
+
+if_test_() ->
+ [?_assertEqual(17, ?IF(id(1) > 0, 17, 42)),
+ ?_assertEqual(42, ?IF(id(1) < 0, 17, 42))].
+
+matches_test_() ->
+ [?_assert(?MATCHES("hel"++_, "hello")),
+ ?_assertNot(?MATCHES("hal"++_, "hello"))].
diff --git a/lib/eunit/src/eunit_tty.erl b/lib/eunit/src/eunit_tty.erl
index 5fe0140559..e3e7b710b2 100644
--- a/lib/eunit/src/eunit_tty.erl
+++ b/lib/eunit/src/eunit_tty.erl
@@ -13,9 +13,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% $Id: eunit_tty.erl 330 2009-03-01 16:28:02Z rcarlsson $
-%%
-%% @author Richard Carlsson <[email protected]>
+%% @author Richard Carlsson <[email protected]>
%% @copyright 2006-2009 Richard Carlsson
%% @private
%% @see eunit
diff --git a/lib/eunit/vsn.mk b/lib/eunit/vsn.mk
index e1965630e3..b0a77a225b 100644
--- a/lib/eunit/vsn.mk
+++ b/lib/eunit/vsn.mk
@@ -1 +1 @@
-EUNIT_VSN = 2.1.6
+EUNIT_VSN = 2.2.1
diff --git a/lib/gs/contribs/bonk/sounder.erl b/lib/gs/contribs/bonk/sounder.erl
index 11ab03d167..e6f69a1616 100644
--- a/lib/gs/contribs/bonk/sounder.erl
+++ b/lib/gs/contribs/bonk/sounder.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -72,13 +72,13 @@ stop() ->
sounder ! {stop},
ok end.
-new(File) when list(File) -> new(list_to_atom(File));
-new(File) when atom(File) ->
+new(File) when is_list(File) -> new(list_to_atom(File));
+new(File) when is_atom(File) ->
catch begin check(),
sounder ! {new,File,self()},
wait_for_ack(sounder) end.
-play(No) when integer(No) ->
+play(No) when is_integer(No) ->
catch begin check(),
sounder ! {play, No, self()},
wait_for_ack(sounder) end.
@@ -94,14 +94,14 @@ go() ->
loop(Port) ->
receive
- {new, File, From} when atom(File) ->
+ {new, File, From} when is_atom(File) ->
Port ! {self(),{command,lists:append([0],atom_to_list(File))}},
From ! {sounder,wait_for_ack(Port)},
loop(Port);
{play,silent,From} ->
From ! {sounder,false},
loop(Port);
- {play,No,From} when integer(No) ->
+ {play,No,From} when is_integer(No) ->
Port ! {self(),{command,[No]}},
From ! {sounder,wait_for_ack(Port)},
loop(Port);
@@ -118,13 +118,13 @@ loop(Port) ->
nosound() ->
receive
- {new,File,From} when atom(File) ->
+ {new,File,From} when is_atom(File) ->
From ! {sounder,{ok,silent}},
nosound();
{play,silent,From} ->
From ! {sounder,true},
nosound();
- {play,No,From} when integer(No) ->
+ {play,No,From} when is_integer(No) ->
From ! {sounder,{error,no_audio_cap}},
nosound();
{stop} ->
@@ -135,7 +135,7 @@ nosound() ->
wait_for_ack(sounder) ->
receive {sounder,Res} -> Res end;
-wait_for_ack(Port) when port(Port) ->
+wait_for_ack(Port) when is_port(Port) ->
receive
{Port,{data,"ok"}} ->
ok;
@@ -149,7 +149,7 @@ wait_for_ack(Port) when port(Port) ->
check() ->
case whereis(sounder) of
- Pid when pid(Pid) ->
+ Pid when is_pid(Pid) ->
ok;
undefined ->
throw({error,sounder_not_started})
diff --git a/lib/gs/contribs/cols/cols.erl b/lib/gs/contribs/cols/cols.erl
index 67b46d0dfb..111c9a58f1 100644
--- a/lib/gs/contribs/cols/cols.erl
+++ b/lib/gs/contribs/cols/cols.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -278,7 +278,7 @@ fall_column([], _X, _Y, ColumnAcc, ChecksAcc) ->
fall_column([black|Colors], X, Y, ColumnAcc, ChecksAcc) ->
case find_box(Colors) of
false -> {ColumnAcc, ChecksAcc};
- NewColors when list(NewColors) ->
+ NewColors when is_list(NewColors) ->
fall_one_step(NewColors, X, Y, ColumnAcc, ChecksAcc)
end;
fall_column([Color|Colors], X, Y, ColumnAcc, ChecksAcc) ->
@@ -330,7 +330,7 @@ new_column_list([], _, _) -> [].
%%----------------------------------------------------------------------
%% Returns: a reversed list of colors.
%%----------------------------------------------------------------------
-columntuple_to_list(ColumnTuple) when tuple(ColumnTuple) ->
+columntuple_to_list(ColumnTuple) when is_tuple(ColumnTuple) ->
columntuple_to_list(tuple_to_list(ColumnTuple),[]).
columntuple_to_list([],Acc) -> Acc;
diff --git a/lib/gs/contribs/mandel/mandel.erl b/lib/gs/contribs/mandel/mandel.erl
index d4d2452463..0f1df5c665 100644
--- a/lib/gs/contribs/mandel/mandel.erl
+++ b/lib/gs/contribs/mandel/mandel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -119,7 +119,7 @@ start_client(Opts,Nodes) ->
try_random(random,Low,High) ->
random:uniform()*(High-Low)+Low;
-try_random(Float,_Low,_High) when number(Float) -> Float.
+try_random(Float,_Low,_High) when is_number(Float) -> Float.
%%-----------------------------------------------------------------
diff --git a/lib/gs/contribs/othello/othello_board.erl b/lib/gs/contribs/othello/othello_board.erl
index 0206ba2ded..212ba9bfe1 100644
--- a/lib/gs/contribs/othello/othello_board.erl
+++ b/lib/gs/contribs/othello/othello_board.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -147,7 +147,7 @@ but_pressed("Help",_ButtId,_User,GamePid,_Shell,_Wids,_Op) ->
but_pressed("Newgame",_ButtId,_User,GamePid,_Shell,Wids,Options) ->
new_game(GamePid,Wids,Options);
but_pressed([],ButtId,User,GamePid,_Shell,_Wids,_Op)
- when pid(GamePid),User == player ->
+ when is_pid(GamePid),User == player ->
[C,R] = atom_to_list(ButtId),
GamePid ! {self(),position,othello_adt:pos(C-96,translate(R-48))},
GamePid;
@@ -243,7 +243,7 @@ game_msg(Msg,User,GamePid,Shell,Wids,Options) ->
end.
-new_game(GamePid,Wids,Options) when pid(GamePid) ->
+new_game(GamePid,Wids,Options) when is_pid(GamePid) ->
exit(GamePid,kill),
new_game(Wids,Options);
new_game(_,Wids,Options) ->
diff --git a/lib/gs/doc/src/notes.xml b/lib/gs/doc/src/notes.xml
index 744efbd4fc..c32db495a1 100644
--- a/lib/gs/doc/src/notes.xml
+++ b/lib/gs/doc/src/notes.xml
@@ -30,7 +30,21 @@
</header>
<p>This document describes the changes made to the GS application.</p>
- <section><title>GS 1.5.13</title>
+ <section><title>GS 1.5.14</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Remove misc. compiler warnings</p>
+ <p>
+ Own Id: OTP-9542</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>GS 1.5.13</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/gs/examples/calc2.erl b/lib/gs/examples/calc2.erl
index d28780de01..0e841397f6 100644
--- a/lib/gs/examples/calc2.erl
+++ b/lib/gs/examples/calc2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -54,7 +54,7 @@ calc() ->
calc_loop(Lbl,M,V,Op) ->
receive
- {gs,_,click,D,_} when integer(D) ->
+ {gs,_,click,D,_} when is_integer(D) ->
digit_press(Lbl,M,V*10+D,Op);
{gs,_,click,'C',_} ->
c(Lbl,M,V,Op);
diff --git a/lib/gs/src/Makefile b/lib/gs/src/Makefile
index a648d3cf13..964966ba00 100644
--- a/lib/gs/src/Makefile
+++ b/lib/gs/src/Makefile
@@ -90,7 +90,7 @@ clean:
# Special Build Targets
# ----------------------------------------------------
-gstk_generic.hrl: gs_make.erl
+gstk_generic.hrl: gs_make.erl ../ebin/gs_make.$(EMULATOR) ../ebin/gs.$(EMULATOR)
$(ERL) -pa $(EBIN) -s gs_make -s erlang halt -noshell
$(APP_TARGET): $(APP_SRC) ../vsn.mk
@@ -99,6 +99,8 @@ $(APP_TARGET): $(APP_SRC) ../vsn.mk
$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
sed -e 's;%VSN%;$(VSN);' $< > $@
+$(GSTK_GENERIC_TARGET): gstk_generic.hrl
+
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
diff --git a/lib/gs/vsn.mk b/lib/gs/vsn.mk
index 4c91857572..4894c6c13a 100644
--- a/lib/gs/vsn.mk
+++ b/lib/gs/vsn.mk
@@ -1,2 +1,2 @@
-GS_VSN = 1.5.13
+GS_VSN = 1.5.14
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl
index 30b911c41b..1483b2aee1 100644
--- a/lib/hipe/cerl/erl_bif_types.erl
+++ b/lib/hipe/cerl/erl_bif_types.erl
@@ -45,6 +45,7 @@
t_atom_vals/1,
t_binary/0,
t_bitstr/0,
+ t_bitstrlist/0,
t_boolean/0,
t_byte/0,
t_char/0,
@@ -153,7 +154,7 @@ type(binary, bin_to_list, Arity, Xs) when 1 =< Arity, Arity =< 3 ->
fun(_) -> t_list(t_integer()) end);
type(binary, compile_pattern, 1, Xs) ->
strict(arg_types(binary, compile_pattern, 1), Xs,
- fun(_) -> t_tuple([t_atom(bm),t_binary()]) end);
+ fun(_) -> t_binary_compiled_pattern() end);
type(binary, copy, Arity, Xs) when Arity =:= 1; Arity =:= 2 ->
strict(arg_types(binary, copy, Arity), Xs,
fun(_) -> t_binary() end);
@@ -365,7 +366,7 @@ type(erlang, '>', 2, Xs = [Lhs, Rhs]) ->
is_integer(LhsMax), is_integer(RhsMin), RhsMin >= LhsMax -> F;
true -> t_boolean()
end;
- false -> t_boolean()
+ false -> compare('>', Lhs, Rhs)
end,
strict(Xs, Ans);
type(erlang, '>=', 2, Xs = [Lhs, Rhs]) ->
@@ -383,7 +384,7 @@ type(erlang, '>=', 2, Xs = [Lhs, Rhs]) ->
is_integer(LhsMax), is_integer(RhsMin), RhsMin > LhsMax -> F;
true -> t_boolean()
end;
- false -> t_boolean()
+ false -> compare('>=', Lhs, Rhs)
end,
strict(Xs, Ans);
type(erlang, '<', 2, Xs = [Lhs, Rhs]) ->
@@ -401,7 +402,7 @@ type(erlang, '<', 2, Xs = [Lhs, Rhs]) ->
is_integer(LhsMin), is_integer(RhsMax), RhsMax =< LhsMin -> F;
true -> t_boolean()
end;
- false -> t_boolean()
+ false -> compare('<', Lhs, Rhs)
end,
strict(Xs, Ans);
type(erlang, '=<', 2, Xs = [Lhs, Rhs]) ->
@@ -419,7 +420,7 @@ type(erlang, '=<', 2, Xs = [Lhs, Rhs]) ->
is_integer(LhsMin), is_integer(RhsMax), RhsMax < LhsMin -> F;
true -> t_boolean()
end;
- false -> t_boolean()
+ false -> compare('=<', Lhs, Rhs)
end,
strict(Xs, Ans);
type(erlang, '+', 1, Xs) ->
@@ -671,11 +672,12 @@ type(erlang, call_on_load_function, 1, Xs) ->
type(erlang, cancel_timer, 1, Xs) ->
strict(arg_types(erlang, cancel_timer, 1), Xs,
fun (_) -> t_sup(t_integer(), t_atom('false')) end);
+type(erlang, check_old_code, 1, Xs) ->
+ strict(arg_types(erlang, check_old_code, 1), Xs,
+ fun (_) -> t_boolean() end);
type(erlang, check_process_code, 2, Xs) ->
strict(arg_types(erlang, check_process_code, 2), Xs,
fun (_) -> t_boolean() end);
-type(erlang, concat_binary, 1, Xs) ->
- strict(arg_types(erlang, concat_binary, 1), Xs, fun (_) -> t_binary() end);
type(erlang, crc32, 1, Xs) ->
strict(arg_types(erlang, crc32, 1), Xs, fun (_) -> t_crc32() end);
type(erlang, crc32, 2, Xs) ->
@@ -701,7 +703,7 @@ type(erlang, demonitor, 1, Xs) ->
type(erlang, demonitor, 2, Xs) ->
strict(arg_types(erlang, demonitor, 2), Xs, fun (_) -> t_boolean() end);
type(erlang, disconnect_node, 1, Xs) ->
- strict(arg_types(erlang, disconnect_node, 1), Xs, fun (_) -> t_boolean() end);
+ strict(arg_types(erlang, disconnect_node, 1), Xs, fun (_) -> t_sup([t_boolean(), t_atom('ignored')]) end);
type(erlang, display, 1, _) -> t_atom('true');
type(erlang, display_string, 1, Xs) ->
strict(arg_types(erlang, display_string, 1), Xs, fun(_) -> t_atom('true') end);
@@ -735,6 +737,7 @@ type(erlang, element, 2, Xs) ->
type(erlang, erase, 0, _) -> t_any();
type(erlang, erase, 1, _) -> t_any();
type(erlang, external_size, 1, _) -> t_integer();
+type(erlang, external_size, 2, _) -> t_integer();
type(erlang, finish_after_on_load, 2, Xs) ->
%% Internal BIF used by on_load.
strict(arg_types(erlang, finish_after_on_load, 2), Xs,
@@ -796,7 +799,8 @@ type(erlang, get_module_info, 2, Xs) ->
end
end);
type(erlang, get_stacktrace, 0, _) ->
- t_list(t_tuple([t_atom(), t_atom(), t_sup([t_arity(), t_list()])]));
+ t_list(t_tuple([t_atom(), t_atom(), t_sup([t_arity(), t_list()]),
+ t_list()]));
type(erlang, group_leader, 0, _) -> t_pid();
type(erlang, group_leader, 2, Xs) ->
strict(arg_types(erlang, group_leader, 2), Xs,
@@ -1123,7 +1127,7 @@ type(erlang, nodes, 0, _) -> t_list(t_node());
type(erlang, nodes, 1, Xs) ->
strict(arg_types(erlang, nodes, 1), Xs, fun (_) -> t_list(t_node()) end);
type(erlang, now, 0, _) ->
- t_time();
+ t_timestamp();
type(erlang, open_port, 2, Xs) ->
strict(arg_types(erlang, open_port, 2), Xs, fun (_) -> t_port() end);
type(erlang, phash, 2, Xs) ->
@@ -1198,6 +1202,7 @@ type(erlang, process_flag, 2, Xs) ->
case t_atom_vals(Flag) of
['error_handler'] -> t_atom();
['min_heap_size'] -> t_non_neg_integer();
+ ['scheduler'] -> t_non_neg_integer();
['monitor_nodes'] -> t_boolean();
['priority'] -> t_process_priority_level();
['save_calls'] -> t_non_neg_integer();
@@ -1584,8 +1589,7 @@ type(erlang, system_info, 1, Xs) ->
['multi_scheduling_blockers'] ->
t_list(t_pid());
['os_type'] ->
- t_tuple([t_sup([t_atom('ose'), % XXX: undocumented
- t_atom('unix'),
+ t_tuple([t_sup([t_atom('unix'),
t_atom('vxworks'),
t_atom('win32')]),
t_atom()]);
@@ -1899,7 +1903,7 @@ type(prim_file, internal_native2name, 1, Xs) ->
fun (_) -> t_prim_file_name() end);
type(prim_file, internal_normalize_utf8, 1, Xs) ->
strict(arg_types(prim_file, internal_normalize_utf8, 1), Xs,
- fun (_) -> t_binary() end);
+ fun (_) -> t_unicode_string() end);
%%-- gen_tcp ------------------------------------------------------------------
%% NOTE: All type information for this module added to avoid loss of precision
type(gen_tcp, accept, 1, Xs) ->
@@ -2324,10 +2328,7 @@ type(lists, keyfind, 3, Xs) ->
case t_tuple_subtypes(Tuple) of
unknown -> Ret;
List ->
- Keys = [type(erlang, element, 2, [Y, S])
- || S <- List],
- Infs = [t_inf(Key, X) || Key <- Keys],
- case all_is_none(Infs) of
+ case key_comparisons_fail(X, Y, List) of
true -> t_atom('false');
false -> Ret
end
@@ -2357,9 +2358,7 @@ type(lists, keymember, 3, Xs) ->
case t_tuple_subtypes(Tuple) of
unknown -> t_boolean();
List ->
- Keys = [type(erlang, element, 2, [Y,S]) || S <- List],
- Infs = [t_inf(Key, X) || Key <- Keys],
- case all_is_none(Infs) of
+ case key_comparisons_fail(X, Y, List) of
true -> t_atom('false');
false -> t_boolean()
end
@@ -2389,10 +2388,7 @@ type(lists, keysearch, 3, Xs) ->
case t_tuple_subtypes(Tuple) of
unknown -> Ret;
List ->
- Keys = [type(erlang, element, 2, [Y, S])
- || S <- List],
- Infs = [t_inf(Key, X) || Key <- Keys],
- case all_is_none(Infs) of
+ case key_comparisons_fail(X, Y, List) of
true -> t_atom('false');
false -> Ret
end
@@ -2692,7 +2688,7 @@ type(os, getpid, 0, _) -> t_string();
type(os, putenv, 2, Xs) ->
strict(arg_types(os, putenv, 2), Xs, fun (_) -> t_atom('true') end);
type(os, timestamp, 0, _) ->
- t_time();
+ t_timestamp();
%%-- re -----------------------------------------------------------------------
type(re, compile, 1, Xs) ->
strict(arg_types(re, compile, 1), Xs,
@@ -2820,9 +2816,6 @@ list_replace(1, E, [_X | Xs]) ->
any_is_none_or_unit(Ts) ->
lists:any(fun erl_types:t_is_none_or_unit/1, Ts).
-all_is_none(Ts) ->
- lists:all(fun erl_types:t_is_none/1, Ts).
-
check_guard([X], Test, Type) ->
check_guard_single(X, Test, Type).
@@ -3175,6 +3168,59 @@ arith(Op, X1, X2) ->
end.
%%=============================================================================
+%% Comparison of terms
+%%=============================================================================
+
+compare(Op, Lhs, Rhs) ->
+ case t_is_none(t_inf(Lhs, Rhs)) of
+ false -> t_boolean();
+ true ->
+ case Op of
+ '<' -> always_smaller(Lhs, Rhs);
+ '>' -> always_smaller(Rhs, Lhs);
+ '=<' -> always_smaller(Lhs, Rhs);
+ '>=' -> always_smaller(Rhs, Lhs)
+ end
+ end.
+
+always_smaller(Type1, Type2) ->
+ {Min1, Max1} = type_ranks(Type1),
+ {Min2, Max2} = type_ranks(Type2),
+ if Max1 < Min2 -> t_atom('true');
+ Min1 > Max2 -> t_atom('false');
+ true -> t_boolean()
+ end.
+
+type_ranks(Type) ->
+ type_ranks(Type, 1, 0, 0, type_order()).
+
+type_ranks(_Type, _I, Min, Max, []) -> {Min, Max};
+type_ranks(Type, I, Min, Max, [TypeClass|Rest]) ->
+ {NewMin, NewMax} =
+ case t_is_none(t_inf(Type, TypeClass)) of
+ true -> {Min, Max};
+ false -> case Min of
+ 0 -> {I, I};
+ _ -> {Min, I}
+ end
+ end,
+ type_ranks(Type, I+1, NewMin, NewMax, Rest).
+
+type_order() ->
+ [t_number(), t_atom(), t_reference(), t_fun(), t_port(), t_pid(), t_tuple(),
+ t_list(), t_binary()].
+
+key_comparisons_fail(X0, KeyPos, TupleList) ->
+ X = case t_is_number(t_inf(X0, t_number())) of
+ false -> X0;
+ true -> t_number()
+ end,
+ lists:all(fun(Tuple) ->
+ Key = type(erlang, element, 2, [KeyPos, Tuple]),
+ t_is_none(t_inf(Key, X))
+ end, TupleList).
+
+%%=============================================================================
-spec arg_types(atom(), atom(), arity()) -> [erl_types:erl_type()] | 'unknown'.
@@ -3395,10 +3441,10 @@ arg_types(erlang, call_on_load_function, 1) ->
[t_atom()];
arg_types(erlang, cancel_timer, 1) ->
[t_reference()];
+arg_types(erlang, check_old_code, 1) ->
+ [t_atom()];
arg_types(erlang, check_process_code, 2) ->
[t_pid(), t_atom()];
-arg_types(erlang, concat_binary, 1) ->
- [t_list(t_binary())];
arg_types(erlang, crc32, 1) ->
[t_iodata()];
arg_types(erlang, crc32, 2) ->
@@ -3441,6 +3487,8 @@ arg_types(erlang, exit, 2) ->
[t_sup(t_pid(), t_port()), t_any()];
arg_types(erlang, external_size, 1) ->
[t_any()]; % takes any term as input
+arg_types(erlang, external_size, 2) ->
+ [t_any(), t_list()]; % takes any term as input and a list of options
arg_types(erlang, finish_after_on_load, 2) ->
[t_atom(), t_boolean()];
arg_types(erlang, float, 1) ->
@@ -3552,7 +3600,7 @@ arg_types(erlang, list_to_binary, 1) ->
arg_types(erlang, list_to_bitstr, 1) -> % XXX: TAKE OUT
arg_types(erlang, list_to_bitstring, 1);
arg_types(erlang, list_to_bitstring, 1) ->
- [t_iolist()];
+ [t_bitstrlist()];
arg_types(erlang, list_to_existing_atom, 1) ->
[t_string()];
arg_types(erlang, list_to_float, 1) ->
@@ -3695,6 +3743,7 @@ arg_types(erlang, process_display, 2) ->
arg_types(erlang, process_flag, 2) ->
[t_sup([t_atom('trap_exit'), t_atom('error_handler'),
t_atom('min_heap_size'), t_atom('priority'), t_atom('save_calls'),
+ t_atom('scheduler'), % undocumented
t_atom('monitor_nodes'), % undocumented
t_tuple([t_atom('monitor_nodes'), t_list()])]), % undocumented
t_sup([t_boolean(), t_atom(), t_non_neg_integer()])];
@@ -3711,7 +3760,10 @@ arg_types(erlang, purge_module, 1) ->
arg_types(erlang, put, 2) ->
[t_any(), t_any()];
arg_types(erlang, raise, 3) ->
- [t_raise_errorclass(), t_any(), type(erlang, get_stacktrace, 0, [])];
+ OldStyleType = t_list(t_tuple([t_atom(), t_atom(),
+ t_sup([t_arity(), t_list()])])),
+ NewStyleType = type(erlang, get_stacktrace, 0, []),
+ [t_raise_errorclass(), t_any(), t_sup(OldStyleType, NewStyleType)];
arg_types(erlang, read_timer, 1) ->
[t_reference()];
arg_types(erlang, ref_to_list, 1) ->
@@ -3733,7 +3785,7 @@ arg_types(erlang, send, 3) ->
arg_types(erlang, send_after, 3) ->
[t_non_neg_integer(), t_sup(t_pid(), t_atom()), t_any()];
arg_types(erlang, seq_trace, 2) ->
- [t_atom(), t_sup([t_boolean(), t_tuple([t_fixnum(), t_fixnum()]), t_nil()])];
+ [t_atom(), t_sup([t_boolean(), t_tuple([t_fixnum(), t_fixnum()]), t_fixnum(), t_nil()])];
arg_types(erlang, seq_trace_info, 1) ->
[t_seq_trace_info()];
arg_types(erlang, seq_trace_print, 1) ->
@@ -3982,7 +4034,7 @@ arg_types(ets, match_object, 3) ->
arg_types(ets, match_spec_compile, 1) ->
[t_matchspecs()];
arg_types(ets, match_spec_run_r, 3) ->
- [t_matchspecs(), t_any(), t_list()];
+ [t_list(t_tuple()),t_matchspecs(), t_list()];
arg_types(ets, member, 2) ->
[t_tab(), t_any()];
arg_types(ets, new, 2) ->
@@ -4014,8 +4066,12 @@ arg_types(ets, select_reverse, 3) ->
arg_types(ets, slot, 2) ->
[t_tab(), t_non_neg_fixnum()]; % 2nd arg can be 0
arg_types(ets, setopts, 2) ->
- Opt = t_sup(t_tuple([t_atom('heir'), t_pid(), t_any()]),
- t_tuple([t_atom('heir'), t_atom('none')])),
+ Opt = t_sup([t_tuple([t_atom('heir'), t_pid(), t_any()]),
+ t_tuple([t_atom('heir'), t_atom('none')]),
+ t_tuple([t_atom('protection'),
+ t_sup([t_atom('protected'),
+ t_atom('private'),
+ t_atom('public')])])]),
[t_tab(), t_sup(Opt, t_list(Opt))];
arg_types(ets, update_counter, 3) ->
Int = t_integer(),
@@ -4457,6 +4513,9 @@ t_date() ->
t_time() ->
t_tuple([t_non_neg_fixnum(), t_non_neg_fixnum(), t_non_neg_fixnum()]).
+t_timestamp() ->
+ t_tuple([t_non_neg_fixnum(), t_non_neg_fixnum(), t_non_neg_fixnum()]).
+
t_packet() ->
t_sup([t_binary(), t_iolist(), t_httppacket()]).
@@ -4468,27 +4527,6 @@ t_endian() ->
t_sup(t_atom('big'), t_atom('little')).
%% =====================================================================
-%% Types for the binary module
-%% =====================================================================
-
-t_binary_part() ->
- t_tuple([t_non_neg_integer(), t_integer()]).
-
-t_binary_canonical_part() ->
- t_tuple([t_non_neg_integer(), t_non_neg_integer()]).
-
-t_binary_pattern() ->
- t_sup([t_binary(),
- t_list(t_binary()),
- t_binary_compiled_pattern()]).
-
-t_binary_compiled_pattern() ->
- t_tuple([t_atom('cp'), t_binary()]).
-
-t_binary_options() ->
- t_list(t_tuple([t_atom('scope'), t_binary_part()])).
-
-%% =====================================================================
%% HTTP types documented in R12B-4
%% =====================================================================
@@ -4543,7 +4581,28 @@ t_HttpFieldAtom() ->
'Keep-Alive', 'Proxy-Connection']).
t_HttpString() ->
- t_sup(t_string(),t_binary()).
+ t_sup(t_string(), t_binary()).
+
+%% =====================================================================
+%% These are used for the built-in functions of 'binary'
+%% =====================================================================
+
+t_binary_part() ->
+ t_tuple([t_non_neg_integer(), t_integer()]).
+
+t_binary_canonical_part() ->
+ t_tuple([t_non_neg_integer(), t_non_neg_integer()]).
+
+t_binary_pattern() ->
+ t_sup([t_binary(),
+ t_list(t_binary()),
+ t_binary_compiled_pattern()]).
+
+t_binary_compiled_pattern() ->
+ t_tuple([t_sup(t_atom('bm'), t_atom('ac')), t_binary()]).
+
+t_binary_options() ->
+ t_list(t_tuple([t_atom('scope'), t_binary_part()])).
%% =====================================================================
%% These are used for the built-in functions of 'code'
@@ -4564,11 +4623,6 @@ t_code_load_error_rsn() -> % also used in erlang:load_module/2
t_atom('on_load'),
t_atom('sticky_directory')]). % only for the 'code' functions
-t_code_loaded_fname_or_status() ->
- t_sup([t_string(), % filename
- t_atom('preloaded'),
- t_atom('cover_compiled')]).
-
%% =====================================================================
%% These are used for the built-in functions of 'erlang'
%% =====================================================================
@@ -4733,7 +4787,6 @@ t_scheduler_bind_type_results() ->
t_atom('thread_no_node_processor_spread'),
t_atom('unbound')]).
-
t_system_monitor_settings() ->
t_sup([t_atom('undefined'),
t_tuple([t_pid(), t_system_monitor_options()])]).
@@ -4810,16 +4863,12 @@ t_ets_info_items() ->
t_atom('owner'),
t_atom('protection'),
t_atom('size'),
+ t_atom('compressed'),
+ t_atom('heir'),
+ t_atom('stats'),
t_atom('type')]).
%% =====================================================================
-%% These are used for the built-in functions of 'prim_file'
-%% =====================================================================
-
-t_prim_file_name() ->
- t_sup(t_unicode_string(), t_binary()).
-
-%% =====================================================================
%% These are used for the built-in functions of 'gen_tcp'
%% =====================================================================
@@ -5013,6 +5062,13 @@ t_re_CapturedData() ->
t_sup([t_tuple([t_integer(), t_integer()]), t_string(), t_binary()]).
%% =====================================================================
+%% These are used for the built-in functions of 'prim_file'
+%% =====================================================================
+
+t_prim_file_name() ->
+ t_sup(t_unicode_string(), t_binary()).
+
+%% =====================================================================
%% These are used for the built-in functions of 'unicode'
%% =====================================================================
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index 080d6936b2..0ff827ac37 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
%%
%% The 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,6 +59,7 @@
t_bitstr_concat/2,
t_bitstr_match/2,
t_bitstr_unit/1,
+ t_bitstrlist/0,
t_boolean/0,
t_byte/0,
t_char/0,
@@ -210,7 +211,8 @@
record_field_diffs_to_string/2,
subst_all_vars_to_any/1,
lift_list_to_pos_empty/1,
- is_erl_type/1
+ is_erl_type/1,
+ atom_to_string/1
]).
%%-define(DO_ERL_TYPES_TEST, true).
@@ -241,12 +243,11 @@
-define(REC_TYPE_LIMIT, 2).
-define(TUPLE_TAG_LIMIT, 5).
--define(TUPLE_ARITY_LIMIT, 10).
+-define(TUPLE_ARITY_LIMIT, 8).
-define(SET_LIMIT, 13).
-define(MAX_BYTE, 255).
-define(MAX_CHAR, 16#10ffff).
--define(WIDENING_LIMIT, 7).
-define(UNIT_MULTIPLIER, 8).
-define(TAG_IMMED1_SIZE, 4).
@@ -1457,11 +1458,11 @@ t_is_tuple(_) -> false.
%% Non-primitive types, including some handy syntactic sugar types
%%
--spec t_unicode_string() -> erl_type().
+-spec t_bitstrlist() -> erl_type().
+
+t_bitstrlist() ->
+ t_iolist(1, t_bitstr()).
-t_unicode_string() ->
- t_list(t_unicode_char()).
-
-spec t_charlist() -> erl_type().
t_charlist() ->
@@ -1551,15 +1552,16 @@ t_iodata() ->
-spec t_iolist() -> erl_type().
t_iolist() ->
- t_iolist(1).
+ t_iolist(1, t_binary()).
--spec t_iolist(non_neg_integer()) -> erl_type().
+%% Added a second argument which currently is t_binary() | t_bitstr()
+-spec t_iolist(non_neg_integer(), erl_type()) -> erl_type().
-t_iolist(N) when N > 0 ->
- t_maybe_improper_list(t_sup([t_iolist(N-1), t_binary(), t_byte()]),
- t_sup(t_binary(), t_nil()));
-t_iolist(0) ->
- t_maybe_improper_list(t_any(), t_sup(t_binary(), t_nil())).
+t_iolist(N, T) when N > 0 ->
+ t_maybe_improper_list(t_sup([t_iolist(N-1, T), T, t_byte()]),
+ t_sup(T, t_nil()));
+t_iolist(0, T) ->
+ t_maybe_improper_list(t_any(), t_sup(T, t_nil())).
-spec t_parameterized_module() -> erl_type().
@@ -1581,6 +1583,11 @@ t_unicode_binary() ->
t_unicode_char() ->
t_integer(). % representing a valid unicode codepoint
+-spec t_unicode_string() -> erl_type().
+
+t_unicode_string() ->
+ t_list(t_unicode_char()).
+
%%-----------------------------------------------------------------------------
%% Some built-in opaque types
%%
@@ -3220,16 +3227,16 @@ t_to_string(?atom(Set), _RecDict) ->
_ ->
set_to_string(Set)
end;
-t_to_string(?bitstr(8, 0), _RecDict) ->
- "binary()";
t_to_string(?bitstr(0, 0), _RecDict) ->
"<<>>";
+t_to_string(?bitstr(8, 0), _RecDict) ->
+ "binary()";
t_to_string(?bitstr(0, B), _RecDict) ->
- io_lib:format("<<_:~w>>", [B]);
+ lists:flatten(io_lib:format("<<_:~w>>", [B]));
t_to_string(?bitstr(U, 0), _RecDict) ->
- io_lib:format("<<_:_*~w>>", [U]);
+ lists:flatten(io_lib:format("<<_:_*~w>>", [U]));
t_to_string(?bitstr(U, B), _RecDict) ->
- io_lib:format("<<_:~w,_:_*~w>>", [B, U]);
+ lists:flatten(io_lib:format("<<_:~w,_:_*~w>>", [B, U]));
t_to_string(?function(?any, ?any), _RecDict) ->
"fun()";
t_to_string(?function(?any, Range), RecDict) ->
@@ -3238,16 +3245,18 @@ t_to_string(?function(?product(ArgList), Range), RecDict) ->
"fun((" ++ comma_sequence(ArgList, RecDict) ++ ") -> "
++ t_to_string(Range, RecDict) ++ ")";
t_to_string(?identifier(Set), _RecDict) ->
- if Set =:= ?any -> "identifier()";
- true -> sequence([io_lib:format("~w()", [T])
- || T <- set_to_list(Set)], [], " | ")
+ case Set of
+ ?any -> "identifier()";
+ _ ->
+ string:join([io_lib:format("~w()", [T]) || T <- set_to_list(Set)], " | ")
end;
t_to_string(?opaque(Set), _RecDict) ->
- sequence([case is_opaque_builtin(Mod, Name) of
- true -> io_lib:format("~w()", [Name]);
- false -> io_lib:format("~w:~w()", [Mod, Name])
- end
- || #opaque{mod = Mod, name = Name} <- set_to_list(Set)], [], " | ");
+ string:join([case is_opaque_builtin(Mod, Name) of
+ true -> io_lib:format("~w()", [Name]);
+ false -> io_lib:format("~w:~w()", [Mod, Name])
+ end
+ || #opaque{mod = Mod, name = Name} <- set_to_list(Set)],
+ " | ");
t_to_string(?matchstate(Pres, Slots), RecDict) ->
io_lib:format("ms(~s,~s)", [t_to_string(Pres, RecDict),
t_to_string(Slots,RecDict)]);
@@ -3321,14 +3330,15 @@ t_to_string(?number(?any, ?unknown_qual), _RecDict) -> "number()";
t_to_string(?product(List), RecDict) ->
"<" ++ comma_sequence(List, RecDict) ++ ">";
t_to_string(?remote(Set), RecDict) ->
- sequence([case Args =:= [] of
- true -> io_lib:format("~w:~w()", [Mod, Name]);
- false ->
- ArgString = comma_sequence(Args, RecDict),
- io_lib:format("~w:~w(~s)", [Mod, Name, ArgString])
- end
- || #remote{mod = Mod, name = Name, args = Args} <- set_to_list(Set)],
- [], " | ");
+ string:join([case Args =:= [] of
+ true -> io_lib:format("~w:~w()", [Mod, Name]);
+ false ->
+ ArgString = comma_sequence(Args, RecDict),
+ io_lib:format("~w:~w(~s)", [Mod, Name, ArgString])
+ end
+ || #remote{mod = Mod, name = Name, args = Args} <-
+ set_to_list(Set)],
+ " | ");
t_to_string(?tuple(?any, ?any, ?any), _RecDict) -> "tuple()";
t_to_string(?tuple(Elements, _Arity, ?any), RecDict) ->
"{" ++ comma_sequence(Elements, RecDict) ++ "}";
@@ -3350,14 +3360,14 @@ t_to_string(?var(Id), _RecDict) when is_integer(Id) ->
record_to_string(Tag, [_|Fields], FieldNames, RecDict) ->
FieldStrings = record_fields_to_string(Fields, FieldNames, RecDict, []),
- "#" ++ atom_to_list(Tag) ++ "{" ++ sequence(FieldStrings, [], ",") ++ "}".
+ "#" ++ atom_to_string(Tag) ++ "{" ++ string:join(FieldStrings, ",") ++ "}".
record_fields_to_string([F|Fs], [{FName, _DefType}|FDefs], RecDict, Acc) ->
NewAcc =
case t_is_any(F) orelse t_is_atom('undefined', F) of
true -> Acc;
false ->
- StrFV = atom_to_list(FName) ++ "::" ++ t_to_string(F, RecDict),
+ StrFV = atom_to_string(FName) ++ "::" ++ t_to_string(F, RecDict),
%% ActualDefType = t_subtract(DefType, t_atom('undefined')),
%% Str = case t_is_any(ActualDefType) of
%% true -> StrFV;
@@ -3376,14 +3386,14 @@ record_field_diffs_to_string(?tuple([_|Fs], Arity, Tag), RecDict) ->
{ok, FieldNames} = lookup_record(TagAtom, Arity-1, RecDict),
%% io:format("RecCElems = ~p\nRecTypes = ~p\n", [Fs, FieldNames]),
FieldDiffs = field_diffs(Fs, FieldNames, RecDict, []),
- sequence(FieldDiffs, [], " and ").
+ string:join(FieldDiffs, " and ").
field_diffs([F|Fs], [{FName, DefType}|FDefs], RecDict, Acc) ->
NewAcc =
case t_is_subtype(F, DefType) of
true -> Acc;
false ->
- Str = atom_to_list(FName) ++ "::" ++ t_to_string(DefType, RecDict),
+ Str = atom_to_string(FName) ++ "::" ++ t_to_string(DefType, RecDict),
[Str|Acc]
end,
field_diffs(Fs, FDefs, RecDict, NewAcc);
@@ -3395,21 +3405,11 @@ comma_sequence(Types, RecDict) ->
true -> "_";
false -> t_to_string(T, RecDict)
end || T <- Types],
- sequence(List, ",").
+ string:join(List, ",").
union_sequence(Types, RecDict) ->
List = [t_to_string(T, RecDict) || T <- Types],
- sequence(List, " | ").
-
-sequence(List, Delimiter) ->
- sequence(List, [], Delimiter).
-
-sequence([], [], _Delimiter) ->
- [];
-sequence([T], Acc, _Delimiter) ->
- lists:flatten(lists:reverse([T|Acc]));
-sequence([T|Ts], Acc, Delimiter) ->
- sequence(Ts, [T ++ Delimiter|Acc], Delimiter).
+ string:join(List, " | ").
%%=============================================================================
%%
@@ -3490,10 +3490,8 @@ t_from_form({type, _L, binary, []}, _TypeNames, _InOpaque, _RecDict,
t_from_form({type, _L, binary, [Base, Unit]} = Type,
_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), []};
+ {{integer, _, B}, {integer, _, U}} when B >= 0, U >= 0 ->
+ {t_bitstr(U, B), []};
_ -> throw({error, io_lib:format("Unable to evaluate type ~w\n", [Type])})
end;
t_from_form({type, _L, bitstring, []}, _TypeNames, _InOpaque, _RecDict,
@@ -3839,26 +3837,40 @@ t_form_to_string({integer, _L, Int}) -> integer_to_list(Int);
t_form_to_string({op, _L, _Op, _Arg} = Op) ->
case erl_eval:partial_eval(Op) of
{integer, _, _} = Int -> t_form_to_string(Int);
- _ -> io_lib:format("Bad formed type ~w",[Op])
+ _ -> io_lib:format("Badly formed type ~w", [Op])
end;
t_form_to_string({op, _L, _Op, _Arg1, _Arg2} = Op) ->
case erl_eval:partial_eval(Op) of
{integer, _, _} = Int -> t_form_to_string(Int);
- _ -> io_lib:format("Bad formed type ~w",[Op])
+ _ -> io_lib:format("Badly formed type ~w", [Op])
end;
t_form_to_string({ann_type, _L, [Var, Type]}) ->
t_form_to_string(Var) ++ "::" ++ t_form_to_string(Type);
t_form_to_string({paren_type, _L, [Type]}) ->
io_lib:format("(~s)", [t_form_to_string(Type)]);
t_form_to_string({remote_type, _L, [{atom, _, Mod}, {atom, _, Name}, Args]}) ->
- ArgString = "(" ++ sequence(t_form_to_string_list(Args), ",") ++ ")",
+ ArgString = "(" ++ string:join(t_form_to_string_list(Args), ",") ++ ")",
io_lib:format("~w:~w", [Mod, Name]) ++ ArgString;
t_form_to_string({type, _L, arity, []}) -> "arity()";
+t_form_to_string({type, _L, binary, []}) -> "binary()";
+t_form_to_string({type, _L, binary, [Base, Unit]} = Type) ->
+ case {erl_eval:partial_eval(Base), erl_eval:partial_eval(Unit)} of
+ {{integer, _, B}, {integer, _, U}} ->
+ %% the following mirrors the clauses of t_to_string/2
+ case {U, B} of
+ {0, 0} -> "<<>>";
+ {8, 0} -> "binary()";
+ {0, B} -> lists:flatten(io_lib:format("<<_:~w>>", [B]));
+ {U, 0} -> lists:flatten(io_lib:format("<<_:_*~w>>", [U]));
+ {U, B} -> lists:flatten(io_lib:format("<<_:~w,_:_*~w>>", [B, U]))
+ end;
+ _ -> io_lib:format("Badly formed bitstr type ~w", [Type])
+ end;
t_form_to_string({type, _L, 'fun', []}) -> "fun()";
t_form_to_string({type, _L, 'fun', [{type, _, any, []}, Range]}) ->
"fun(...) -> " ++ t_form_to_string(Range);
t_form_to_string({type, _L, 'fun', [{type, _, product, Domain}, Range]}) ->
- "fun((" ++ sequence(t_form_to_string_list(Domain), ",") ++ ") -> "
+ "fun((" ++ string:join(t_form_to_string_list(Domain), ",") ++ ") -> "
++ t_form_to_string(Range) ++ ")";
t_form_to_string({type, _L, iodata, []}) -> "iodata()";
t_form_to_string({type, _L, iolist, []}) -> "iolist()";
@@ -3871,7 +3883,7 @@ t_form_to_string({type, _L, nonempty_list, [Type]}) ->
"[" ++ t_form_to_string(Type) ++ ",...]";
t_form_to_string({type, _L, nonempty_string, []}) -> "nonempty_string()";
t_form_to_string({type, _L, product, Elements}) ->
- "<" ++ sequence(t_form_to_string_list(Elements), ",") ++ ">";
+ "<" ++ string:join(t_form_to_string_list(Elements), ",") ++ ">";
t_form_to_string({type, _L, range, [From, To]} = Type) ->
case {erl_eval:partial_eval(From), erl_eval:partial_eval(To)} of
{{integer, _, FromVal}, {integer, _, ToVal}} ->
@@ -3881,7 +3893,7 @@ t_form_to_string({type, _L, range, [From, To]} = Type) ->
t_form_to_string({type, _L, record, [{atom, _, Name}]}) ->
io_lib:format("#~w{}", [Name]);
t_form_to_string({type, _L, record, [{atom, _, Name}|Fields]}) ->
- FieldString = sequence(t_form_to_string_list(Fields), ","),
+ FieldString = string:join(t_form_to_string_list(Fields), ","),
io_lib:format("#~w{~s}", [Name, FieldString]);
t_form_to_string({type, _L, field_type, [{atom, _, Name}, Type]}) ->
io_lib:format("~w::~s", [Name, t_form_to_string(Type)]);
@@ -3889,27 +3901,16 @@ t_form_to_string({type, _L, term, []}) -> "term()";
t_form_to_string({type, _L, timeout, []}) -> "timeout()";
t_form_to_string({type, _L, tuple, any}) -> "tuple()";
t_form_to_string({type, _L, tuple, Args}) ->
- "{" ++ sequence(t_form_to_string_list(Args), ",") ++ "}";
+ "{" ++ string:join(t_form_to_string_list(Args), ",") ++ "}";
t_form_to_string({type, _L, union, Args}) ->
- sequence(t_form_to_string_list(Args), " | ");
+ string:join(t_form_to_string_list(Args), " | ");
t_form_to_string({type, _L, Name, []} = T) ->
try t_to_string(t_from_form(T))
- catch throw:{error, _} -> atom_to_list(Name) ++ "()"
- end;
-t_form_to_string({type, _L, binary, [X,Y]} = Type) ->
- case {erl_eval:partial_eval(X), erl_eval:partial_eval(Y)} of
- {{integer, _, XVal}, {integer, _, YVal}} ->
- case YVal of
- 0 ->
- case XVal of
- 0 -> "<<>>";
- _ -> io_lib:format("<<_:~w>>", [XVal])
- end
- end;
- _ -> io_lib:format("Bad formed type ~w",[Type])
+ catch throw:{error, _} -> atom_to_string(Name) ++ "()"
end;
t_form_to_string({type, _L, Name, List}) ->
- io_lib:format("~w(~s)", [Name, sequence(t_form_to_string_list(List), ",")]).
+ io_lib:format("~w(~s)",
+ [Name, string:join(t_form_to_string_list(List), ",")]).
t_form_to_string_list(List) ->
t_form_to_string_list(List, []).
@@ -3917,8 +3918,13 @@ t_form_to_string_list(List) ->
t_form_to_string_list([H|T], Acc) ->
t_form_to_string_list(T, [t_form_to_string(H)|Acc]);
t_form_to_string_list([], Acc) ->
- lists:reverse(Acc).
-
+ lists:reverse(Acc).
+
+-spec atom_to_string(atom()) -> string().
+
+atom_to_string(Atom) ->
+ lists:flatten(io_lib:format("~w", [Atom])).
+
%%=============================================================================
%%
%% Utilities
@@ -4057,7 +4063,7 @@ set_to_string(Set) ->
true -> io_lib:write_string(atom_to_list(X), $'); % stupid emacs '
false -> io_lib:format("~w", [X])
end || X <- set_to_list(Set)],
- sequence(L, [], " | ").
+ string:join(L, " | ").
set_min([H|_]) -> H.
diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml
index 434bfac64c..6b601e3039 100644
--- a/lib/hipe/doc/src/notes.xml
+++ b/lib/hipe/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2006</year><year>2010</year>
+ <year>2006</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,6 +30,102 @@
</header>
<p>This document describes the changes made to HiPE.</p>
+<section><title>Hipe 3.8.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Clean up hipe.hrl.src (Thanks to Tuncer Ayaz)</p>
+ <p>
+ Own Id: OTP-9511</p>
+ </item>
+ <item>
+ <p>
+ Fix bug with binary pattern matching of floats of
+ variable size</p>
+ <p>
+ Pattern matching of floats with variable size
+ (&lt;&lt;F:S/float&gt;&gt;) did always fail. Judging from
+ similar code for ints, this bug is simply a typo.(Thanks
+ to Paul Guyot)</p>
+ <p>
+ Own Id: OTP-9556</p>
+ </item>
+ <item>
+ <p>
+ Quote atoms if necessary in types</p>
+ <p>
+ Atoms in some occurrences were not correctly quoted when
+ formatted to strings, for instance by the typer program
+ (Thanks to Tomas Abrahamsson)</p>
+ <p>
+ Update Dialyzer's reference results</p>
+ <p>
+ Own Id: OTP-9560</p>
+ </item>
+ <item>
+ <p>
+ Fix typer's crash for nonexisting files Remove unused
+ macro Fix bug in dataflow Decrease tuple arity limit This
+ fixes a memory related crash.</p>
+ <p>
+ Own Id: OTP-9597</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Types for several BIFs have been extended/corrected. Also
+ the types for types for <c>lists:keyfind/3</c>,
+ <c>lists:keysearch/3</c>, and <c>lists:keyemember/3</c>
+ have been corrected. The incorrect/incomplete types could
+ cause false dialyzer warnings.</p>
+ <p>
+ Own Id: OTP-9496</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Hipe 3.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix hipe bug causing minor heap corruption related to
+ binary matching. The bug has not been confirmed as the
+ cause of any actual fault symptom.</p>
+ <p>
+ Own Id: OTP-9182</p>
+ </item>
+ <item>
+ <p>
+ Enable HiPE by default when compiling for PPC64</p>
+ <p>
+ Own Id: OTP-9198</p>
+ </item>
+ <item>
+ <p>
+ Fix handling of &lt;&lt;_:N,_:_*M&gt;&gt; type
+ expressions Fix the argument of
+ erlang:list_to_bitstring/1 Remove unneeded function
+ 'sequence/2' Same functionality provided by
+ string:join/2.</p>
+ <p>
+ Own Id: OTP-9277</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Hipe 3.7.9</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl
index d7eb035551..45b390acbd 100644
--- a/lib/hipe/icode/hipe_beam_to_icode.erl
+++ b/lib/hipe/icode/hipe_beam_to_icode.erl
@@ -281,10 +281,14 @@ needs_redtest(Leafness) ->
%%-----------------------------------------------------------------------
%%--- label & func_info combo ---
+trans_fun([{label,_}=F,{func_info,_,_,_}=FI|Instructions], Env) ->
+ %% Handle old code without a line instruction.
+ trans_fun([F,{line,[]},FI|Instructions], Env);
trans_fun([{label,B},{label,_},
{func_info,M,F,A},{label,L}|Instructions], Env) ->
trans_fun([{label,B},{func_info,M,F,A},{label,L}|Instructions], Env);
trans_fun([{label,B},
+ {line,_},
{func_info,{atom,_M},{atom,_F},_A},
{label,L}|Instructions], Env) ->
%% Emit code to handle function_clause errors. The BEAM test instructions
@@ -720,7 +724,7 @@ trans_fun([{test,bs_get_float2,{f,Lbl},[Ms,_Live,Size,Unit,{field_flags,Flags0},
?EXIT({bad_bs_size_constant,Size});
BitReg ->
Bits = mk_var(BitReg),
- {{bs_get_float,Unit,Flags}, [Bits,MsVar]}
+ {{bs_get_float,Unit,Flags}, [MsVar,Bits]}
end,
trans_op_call({hipe_bs_primop,Name}, Lbl, Args, [Dst,MsVar], Env, Instructions);
trans_fun([{test,bs_get_integer2,{f,Lbl},[Ms,_Live,Size,Unit,{field_flags,Flags0},X]}|
@@ -1142,6 +1146,11 @@ trans_fun([{trim,N,NY}|Instructions], Env) ->
Moves = trans_trim(N, NY),
Moves ++ trans_fun(Instructions, Env);
%%--------------------------------------------------------------------
+%% New line/1 instruction in R15.
+%%--------------------------------------------------------------------
+trans_fun([{line,_}|Instructions], Env) ->
+ trans_fun(Instructions,Env);
+%%--------------------------------------------------------------------
%%--- ERROR HANDLING ---
%%--------------------------------------------------------------------
trans_fun([X|_], _) ->
@@ -1869,6 +1878,8 @@ patch_make_funs([], FunIndex, Acc) ->
find_mfa([{label,_}|Code]) ->
find_mfa(Code);
+find_mfa([{line,_}|Code]) ->
+ find_mfa(Code);
find_mfa([{func_info,{atom,M},{atom,F},A}|_])
when is_atom(M), is_atom(F), is_integer(A), 0 =< A, A =< 255 ->
{M, F, A}.
diff --git a/lib/hipe/main/hipe.hrl.src b/lib/hipe/main/hipe.hrl.src
index a1fbeda9cf..e74f31b19d 100644
--- a/lib/hipe/main/hipe.hrl.src
+++ b/lib/hipe/main/hipe.hrl.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The 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,9 +50,8 @@
%% Flags:
%% DEBUG - Turns on debugging. (Can be defined to a integer
%% value to determine the level of debugging)
-%% VERBOSE - More info is printed...
%% HIPE_LOGGING - Turn on logging of messages with erl_logger.
-%% DO_ASSERT - Turn on Assertions.
+%% DO_ASSERT - Turn on assertions.
%% TIMING - Turn on timing.
%% HIPE_INSTRUMENT_COMPILER - Turn on instrumentation of the compiler.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -107,13 +106,9 @@
%%
%% Define the exit macro
%%
--ifdef(VERBOSE).
--define(EXIT(Reason), erlang:error({?MODULE,?LINE,Reason})).
--else.
-define(EXIT(Reason),
?msg("EXITED with reason ~w @~w:~w\n", [Reason,?MODULE,?LINE]),
erlang:error({?MODULE,?LINE,Reason})).
--endif.
%%
%% Assertions.
diff --git a/lib/hipe/main/hipe_main.erl b/lib/hipe/main/hipe_main.erl
index e81642fb33..99028cc3c1 100644
--- a/lib/hipe/main/hipe_main.erl
+++ b/lib/hipe/main/hipe_main.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -313,7 +313,7 @@ icode_ssa_struct_reuse(IcodeSSA, Options) ->
icode_ssa_type_info(IcodeSSA, MFA, Options, Servers) ->
?option_time(hipe_icode_type:cfg(IcodeSSA, MFA, Options, Servers),
- "Icode SSA type info", Options).
+ io_lib:format("Icode SSA type info for ~p", [MFA]), Options).
icode_range_analysis(IcodeSSA, MFA, Options, Servers) ->
case proplists:get_bool(icode_range, Options) of
@@ -527,6 +527,8 @@ rtl_to_native(MFA, LinearRTL, Options, DebugState) ->
hipe_sparc_main:rtl_to_sparc(MFA, LinearRTL, Options);
powerpc ->
hipe_ppc_main:rtl_to_ppc(MFA, LinearRTL, Options);
+ ppc64 ->
+ hipe_ppc_main:rtl_to_ppc(MFA, LinearRTL, Options);
arm ->
hipe_arm_main:rtl_to_arm(MFA, LinearRTL, Options);
x86 ->
diff --git a/lib/hipe/ppc/hipe_ppc.erl b/lib/hipe/ppc/hipe_ppc.erl
index 047e86c45b..4014fc1561 100644
--- a/lib/hipe/ppc/hipe_ppc.erl
+++ b/lib/hipe/ppc/hipe_ppc.erl
@@ -1,20 +1,20 @@
%% -*- erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -58,6 +58,10 @@
mk_blr/0,
mk_cmp/3,
+ cmpop_word/0,
+ cmpiop_word/0,
+ cmplop_word/0,
+ cmpliop_word/0,
mk_comment/1,
@@ -73,6 +77,8 @@
mk_loadx/4,
mk_load/6,
ldop_to_ldxop/1,
+ ldop_word/0,
+ ldop_wordx/0,
mk_mfspr/2,
@@ -110,6 +116,8 @@
mk_storex/4,
mk_store/6,
stop_to_stxop/1,
+ stop_word/0,
+ stop_wordx/0,
mk_unary/3,
@@ -189,6 +197,31 @@ mk_blr() -> #blr{}.
mk_cmp(CmpOp, Src1, Src2) -> #cmp{cmpop=CmpOp, src1=Src1, src2=Src2}.
+cmpop_word() ->
+ case get(hipe_target_arch) of
+ powerpc -> 'cmp';
+ ppc64 -> 'cmpd'
+ end.
+
+cmpiop_word() ->
+ case get(hipe_target_arch) of
+ powerpc -> 'cmpi';
+ ppc64 -> 'cmpdi'
+ end.
+
+cmplop_word() ->
+ case get(hipe_target_arch) of
+ powerpc -> 'cmpl';
+ ppc64 -> 'cmpld'
+ end.
+
+cmpliop_word() ->
+ case get(hipe_target_arch) of
+ powerpc -> 'cmpli';
+ ppc64 -> 'cmpldi'
+ end.
+
+
mk_comment(Term) -> #comment{term=Term}.
mk_label(Label) -> #label{label=Label}.
@@ -198,9 +231,50 @@ label_label(#label{label=Label}) -> Label.
%%% Load an integer constant into a register.
mk_li(Dst, Value) -> mk_li(Dst, Value, []).
-mk_li(Dst, Value, Tail) ->
+mk_li(Dst, Value, Tail) -> % Dst can be R0
R0 = mk_temp(0, 'untagged'),
- mk_addi(Dst, R0, Value, Tail).
+ %% Check if immediate can fit in the 32 bits, this is obviously a
+ %% sufficient check for PPC32
+ if Value >= -16#80000000,
+ Value =< 16#7FFFFFFF ->
+ mk_li32(Dst, R0, Value, Tail);
+ true ->
+ Highest = (Value bsr 48), % Value@highest
+ Higher = (Value bsr 32) band 16#FFFF, % Value@higher
+ High = (Value bsr 16) band 16#FFFF, % Value@h
+ Low = Value band 16#FFFF, % Value@l
+ LdLo =
+ case Low of
+ 0 -> Tail;
+ _ -> [mk_alu('ori', Dst, Dst, mk_uimm16(Low)) | Tail]
+ end,
+ Ld32bits =
+ case High of
+ 0 -> LdLo;
+ _ -> [mk_alu('oris', Dst, Dst, mk_uimm16(High)) | LdLo]
+ end,
+ [mk_alu('addis', Dst, R0, mk_simm16(Highest)),
+ mk_alu('ori', Dst, Dst, mk_uimm16(Higher)),
+ mk_alu('sldi', Dst, Dst, mk_uimm16(32)) |
+ Ld32bits]
+ end.
+
+mk_li32(Dst, R0, Value, Tail) ->
+ case at_ha(Value) of
+ 0 ->
+ %% Value[31:16] are the sign-extension of Value[15].
+ %% Use a single addi to load and sign-extend 16 bits.
+ [mk_alu('addi', Dst, R0, mk_simm16(at_l(Value))) | Tail];
+ _ ->
+ %% Use addis to load the high 16 bits, followed by an
+ %% optional ori to load non sign-extended low 16 bits.
+ High = simm16sext((Value bsr 16) band 16#FFFF),
+ [mk_alu('addis', Dst, R0, mk_simm16(High)) |
+ case (Value band 16#FFFF) of
+ 0 -> Tail;
+ Low -> [mk_alu('ori', Dst, Dst, mk_uimm16(Low)) | Tail]
+ end]
+ end.
mk_addi(Dst, R0, Value, Tail) ->
Low = at_l(Value),
@@ -232,27 +306,6 @@ simm16sext(Value) ->
true -> Value
end.
-mk_li_new(Dst, Value, Tail) -> % Dst may be R0
- R0 = mk_temp(0, 'untagged'),
- case at_ha(Value) of
- 0 ->
- %% Value[31:16] are the sign-extension of Value[15].
- %% Use a single addi to load and sign-extend 16 bits.
- [mk_alu('addi', Dst, R0, mk_simm16(at_l(Value))) |
- Tail];
- _ ->
- %% Use addis to load the high 16 bits, followed by an
- %% optional ori to load non sign-extended low 16 bits.
- High = simm16sext((Value bsr 16) band 16#FFFF),
- [mk_alu('addis', Dst, R0, mk_simm16(High)) |
- case (Value band 16#FFFF) of
- 0 -> Tail;
- Low ->
- [mk_alu('ori', Dst, Dst, mk_uimm16(Low)) |
- Tail]
- end]
- end.
-
mk_load(LDop, Dst, Disp, Base) ->
#load{ldop=LDop, dst=Dst, disp=Disp, base=Base}.
@@ -260,8 +313,15 @@ mk_loadx(LdxOp, Dst, Base1, Base2) ->
#loadx{ldxop=LdxOp, dst=Dst, base1=Base1, base2=Base2}.
mk_load(LdOp, Dst, Offset, Base, Scratch, Rest) when is_integer(Offset) ->
- if Offset >= -32768, Offset =< 32767 ->
- [mk_load(LdOp, Dst, Offset, Base) | Rest];
+ RequireAlignment =
+ case LdOp of
+ 'ld' -> true;
+ 'ldx' -> true;
+ _ -> false
+ end,
+ if Offset >= -32768, Offset =< 32767,
+ not RequireAlignment orelse Offset band 3 =:= 0 ->
+ [mk_load(LdOp, Dst, Offset, Base) | Rest];
true ->
LdxOp = ldop_to_ldxop(LdOp),
Index =
@@ -272,8 +332,8 @@ mk_load(LdOp, Dst, Offset, Base, Scratch, Rest) when is_integer(Offset) ->
true -> mk_scratch(Scratch)
end
end,
- mk_li_new(Index, Offset,
- [mk_loadx(LdxOp, Dst, Base, Index) | Rest])
+ mk_li(Index, Offset,
+ [mk_loadx(LdxOp, Dst, Base, Index) | Rest])
end.
ldop_to_ldxop(LdOp) ->
@@ -281,7 +341,21 @@ ldop_to_ldxop(LdOp) ->
'lbz' -> 'lbzx';
'lha' -> 'lhax';
'lhz' -> 'lhzx';
- 'lwz' -> 'lwzx'
+ 'lwa' -> 'lwax';
+ 'lwz' -> 'lwzx';
+ 'ld' -> 'ldx'
+ end.
+
+ldop_word() ->
+ case get(hipe_target_arch) of
+ powerpc -> 'lwz';
+ ppc64 -> 'ld'
+ end.
+
+ldop_wordx() ->
+ case get(hipe_target_arch) of
+ powerpc -> 'lwzx';
+ ppc64 -> 'ldx'
end.
mk_scratch(Scratch) ->
@@ -354,20 +428,40 @@ mk_storex(StxOp, Src, Base1, Base2) ->
#storex{stxop=StxOp, src=Src, base1=Base1, base2=Base2}.
mk_store(StOp, Src, Offset, Base, Scratch, Rest)when is_integer(Offset) ->
- if Offset >= -32768, Offset =< 32767 ->
+ RequireAlignment =
+ case StOp of
+ 'std' -> true;
+ 'stdx' -> true;
+ _ -> false
+ end,
+ if Offset >= -32768, Offset =< 32767,
+ not RequireAlignment orelse Offset band 3 =:= 0 ->
[mk_store(StOp, Src, Offset, Base) | Rest];
true ->
StxOp = stop_to_stxop(StOp),
Index = mk_scratch(Scratch),
- mk_li_new(Index, Offset,
- [mk_storex(StxOp, Src, Base, Index) | Rest])
+ mk_li(Index, Offset,
+ [mk_storex(StxOp, Src, Base, Index) | Rest])
end.
stop_to_stxop(StOp) ->
case StOp of
'stb' -> 'stbx';
'sth' -> 'sthx';
- 'stw' -> 'stwx'
+ 'stw' -> 'stwx';
+ 'std' -> 'stdx'
+ end.
+
+stop_word() ->
+ case get(hipe_target_arch) of
+ powerpc -> 'stw';
+ ppc64 -> 'std'
+ end.
+
+stop_wordx() ->
+ case get(hipe_target_arch) of
+ powerpc -> 'stwx';
+ ppc64 -> 'stdx'
end.
mk_unary(UnOp, Dst, Src) -> #unary{unop=UnOp, dst=Dst, src=Src}.
@@ -379,7 +473,7 @@ mk_fload(Dst, Offset, Base, Scratch) when is_integer(Offset) ->
[mk_lfd(Dst, Offset, Base)];
true ->
Index = mk_scratch(Scratch),
- mk_li_new(Index, Offset, [mk_lfdx(Dst, Base, Index)])
+ mk_li(Index, Offset, [mk_lfdx(Dst, Base, Index)])
end.
mk_stfd(Src, Disp, Base) -> #stfd{src=Src, disp=Disp, base=Base}.
@@ -389,7 +483,7 @@ mk_fstore(Src, Offset, Base, Scratch) when is_integer(Offset) ->
[mk_stfd(Src, Offset, Base)];
true ->
Index = mk_scratch(Scratch),
- mk_li_new(Index, Offset, [mk_stfdx(Src, Base, Index)])
+ mk_li(Index, Offset, [mk_stfdx(Src, Base, Index)])
end.
mk_fp_binary(FpBinOp, Dst, Src1, Src2) ->
diff --git a/lib/hipe/ppc/hipe_ppc_assemble.erl b/lib/hipe/ppc/hipe_ppc_assemble.erl
index 6f06f8b841..b2fd50517b 100644
--- a/lib/hipe/ppc/hipe_ppc_assemble.erl
+++ b/lib/hipe/ppc/hipe_ppc_assemble.erl
@@ -1,20 +1,20 @@
%% -*- erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -39,7 +39,7 @@ assemble(CompiledCode, Closures, Exports, Options) ->
|| {MFA, Defun} <- CompiledCode],
%%
{ConstAlign,ConstSize,ConstMap,RefsFromConsts} =
- hipe_pack_constants:pack_constants(Code, 4),
+ hipe_pack_constants:pack_constants(Code, hipe_rtl_arch:word_size()),
%%
{CodeSize,CodeBinary,AccRefs,LabelMap,ExportMap} =
encode(translate(Code, ConstMap), Options),
@@ -159,6 +159,13 @@ do_alu(I) ->
'srwi.' -> {'rlwinm.', do_srwi_opnds(NewDst, NewSrc1, NewSrc2)};
'srawi' -> {'srawi', {NewDst,NewSrc1,do_srawi_src2(NewSrc2)}};
'srawi.' -> {'srawi.', {NewDst,NewSrc1,do_srawi_src2(NewSrc2)}};
+ %ppc64 extension
+ 'sldi' -> {'rldicr', do_sldi_opnds(NewDst, NewSrc1, NewSrc2)};
+ 'sldi.' -> {'rldicr.', do_sldi_opnds(NewDst, NewSrc1, NewSrc2)};
+ 'srdi' -> {'rldicl', do_srdi_opnds(NewDst, NewSrc1, NewSrc2)};
+ 'srdi.' -> {'rldicl.', do_srdi_opnds(NewDst, NewSrc1, NewSrc2)};
+ 'sradi' -> {'sradi', {NewDst,NewSrc1,do_sradi_src2(NewSrc2)}};
+ 'sradi.' -> {'sradi.', {NewDst,NewSrc1,do_sradi_src2(NewSrc2)}};
_ -> {AluOp, {NewDst,NewSrc1,NewSrc2}}
end,
[{NewI, NewOpnds, I}].
@@ -171,6 +178,15 @@ do_srwi_opnds(Dst, Src1, {uimm,N}) when is_integer(N), 0 =< N, N < 32 ->
do_srawi_src2({uimm,N}) when is_integer(N), 0 =< N, N < 32 -> {sh,N}.
+%% ppc64 extension
+do_sldi_opnds(Dst, Src1, {uimm,N}) when is_integer(N), 0 =< N, N < 64 ->
+ {Dst, Src1, {sh6,N}, {me6,63-N}}.
+
+do_srdi_opnds(Dst, Src1, {uimm,N}) when is_integer(N), 0 =< N, N < 64 ->
+ {Dst, Src1, {sh6,64-N}, {mb6,N}}.
+
+do_sradi_src2({uimm,N}) when is_integer(N), 0 =< N, N < 64 -> {sh6,N}.
+
do_b_fun(I) ->
#b_fun{'fun'=Fun,linkage=Linkage} = I,
[{'.reloc', {b_fun,Fun,Linkage}, #comment{term='fun'}},
@@ -205,7 +221,18 @@ do_cmp(I) ->
#cmp{cmpop=CmpOp,src1=Src1,src2=Src2} = I,
NewSrc1 = do_reg(Src1),
NewSrc2 = do_reg_or_imm(Src2),
- [{CmpOp, {{crf,0},0,NewSrc1,NewSrc2}, I}].
+ {RealOp,L} =
+ case CmpOp of
+ 'cmpd' -> {'cmp',1};
+ 'cmpdi' -> {'cmpi',1};
+ 'cmpld' -> {'cmpl',1};
+ 'cmpldi' -> {'cmpli',1};
+ 'cmp' -> {CmpOp,0};
+ 'cmpi' -> {CmpOp,0};
+ 'cmpl' -> {CmpOp,0};
+ 'cmpli' -> {CmpOp,0}
+ end,
+ [{RealOp, {{crf,0},L,NewSrc1,NewSrc2}, I}].
do_label(I) ->
#label{label=Label} = I,
@@ -214,7 +241,12 @@ do_label(I) ->
do_load(I) ->
#load{ldop=LdOp,dst=Dst,disp=Disp,base=Base} = I,
NewDst = do_reg(Dst),
- NewDisp = do_disp(Disp),
+ NewDisp =
+ case LdOp of
+ 'ld' -> do_disp_ds(Disp);
+ 'ldu' -> do_disp_ds(Disp);
+ _ -> do_disp(Disp)
+ end,
NewBase = do_reg(Base),
[{LdOp, {NewDst,NewDisp,NewBase}, I}].
@@ -265,14 +297,30 @@ do_pseudo_li(I, MFA, ConstMap) ->
end,
NewDst = do_reg(Dst),
Simm0 = {simm,0},
- [{'.reloc', RelocData, #comment{term=reloc}},
- {addi, {NewDst,{r,0},Simm0}, I},
- {addis, {NewDst,NewDst,Simm0}, I}].
+ Uimm0 = {uimm,0},
+ case get(hipe_target_arch) of
+ powerpc ->
+ [{'.reloc', RelocData, #comment{term=reloc}},
+ {addi, {NewDst,{r,0},Simm0}, I},
+ {addis, {NewDst,NewDst,Simm0}, I}];
+ ppc64 ->
+ [{'.reloc', RelocData, #comment{term=reloc}},
+ {addis, {NewDst,{r,0},Simm0}, I}, % @highest
+ {ori, {NewDst,NewDst,Uimm0}, I}, % @higher
+ {rldicr, {NewDst,NewDst,{sh6,32},{me6,31}}, I},
+ {oris, {NewDst,NewDst,Uimm0}, I}, % @h
+ {ori, {NewDst,NewDst,Uimm0}, I}] % @l
+ end.
do_store(I) ->
#store{stop=StOp,src=Src,disp=Disp,base=Base} = I,
NewSrc = do_reg(Src),
- NewDisp = do_disp(Disp),
+ NewDisp =
+ case StOp of
+ 'std' -> do_disp_ds(Disp);
+ 'stdu' -> do_disp_ds(Disp);
+ _ -> do_disp(Disp)
+ end,
NewBase = do_reg(Base),
[{StOp, {NewSrc,NewDisp,NewBase}, I}].
@@ -344,6 +392,10 @@ do_reg_or_imm(Src) ->
do_disp(Disp) when is_integer(Disp), -32768 =< Disp, Disp =< 32767 ->
{d, Disp band 16#ffff}.
+do_disp_ds(Disp) when is_integer(Disp),
+ -32768 =< Disp, Disp =< 32767, Disp band 3 =:= 0 ->
+ {ds, (Disp band 16#ffff) bsr 2}.
+
do_spr(SPR) ->
SPR_NR =
case SPR of
diff --git a/lib/hipe/ppc/hipe_ppc_frame.erl b/lib/hipe/ppc/hipe_ppc_frame.erl
index 158009872f..8a4d1906c0 100644
--- a/lib/hipe/ppc/hipe_ppc_frame.erl
+++ b/lib/hipe/ppc/hipe_ppc_frame.erl
@@ -1,20 +1,20 @@
%% -*- erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -103,12 +103,12 @@ do_pseudo_move(I, Context, FPoff) ->
case temp_is_pseudo(Dst) of
true ->
Offset = pseudo_offset(Dst, FPoff, Context),
- mk_store('stw', Src, Offset, mk_sp(), []);
+ mk_store(hipe_ppc:stop_word(), Src, Offset, mk_sp(), []);
_ ->
case temp_is_pseudo(Src) of
true ->
Offset = pseudo_offset(Src, FPoff, Context),
- mk_load('lwz', Dst, Offset, mk_sp(), []);
+ mk_load(hipe_ppc:ldop_word(), Dst, Offset, mk_sp(), []);
_ ->
[hipe_ppc:mk_alu('or', Dst, Src, Src)]
end
@@ -152,7 +152,7 @@ restore_lr(FPoff, Context, Rest) ->
false -> Rest;
true ->
Temp = mk_temp1(),
- mk_load('lwz', Temp, FPoff - word_size(), mk_sp(),
+ mk_load(hipe_ppc:ldop_word(), Temp, FPoff - word_size(), mk_sp(),
[hipe_ppc:mk_mtspr('lr', Temp) |
Rest])
end.
@@ -324,8 +324,8 @@ simple_moves([{SrcOff,DstOff,Type}|Moves], FPoff, TempReg, Rest) ->
LoadOff = FPoff+SrcOff,
StoreOff = FPoff+DstOff,
simple_moves(Moves, FPoff, TempReg,
- mk_load('lwz', Temp, LoadOff, SP,
- mk_store('stw', Temp, StoreOff, SP,
+ mk_load(hipe_ppc:ldop_word(), Temp, LoadOff, SP,
+ mk_store(hipe_ppc:stop_word(), Temp, StoreOff, SP,
Rest)));
simple_moves([], _, _, Rest) ->
Rest.
@@ -343,7 +343,8 @@ store_moves([{Src,DstOff}|Moves], FPoff, TempReg, Rest) ->
{Temp, hipe_ppc:mk_li(Temp, Src)}
end,
store_moves(Moves, FPoff, TempReg,
- FixSrc ++ mk_store('stw', NewSrc, StoreOff, SP, Rest));
+ FixSrc ++ mk_store(hipe_ppc:stop_word(), NewSrc,
+ StoreOff, SP, Rest));
store_moves([], _, _, Rest) ->
Rest.
@@ -400,7 +401,7 @@ mk_temp_map(Formals, ClobbersLR, Temps) ->
enter_vars([V|Vs], PrevOff, Map) ->
Off =
case hipe_ppc:temp_type(V) of
- 'double' -> PrevOff - 2*word_size();
+ 'double' -> PrevOff - 8;
_ -> PrevOff - word_size()
end,
enter_vars(Vs, Off, tmap_bind(Map, V, Off));
@@ -454,7 +455,8 @@ do_prologue(CFG, Context) ->
AllocFrameCodeTail =
case ClobbersLR of
false -> GotoOldStartCode;
- true -> mk_store('stw', Temp1, FrameSize-word_size(), SP, GotoOldStartCode)
+ true -> mk_store(hipe_ppc:stop_word(), Temp1,
+ FrameSize-word_size(), SP, GotoOldStartCode)
end,
%%
Arity = context_arity(Context),
@@ -484,7 +486,7 @@ do_prologue(CFG, Context) ->
true -> [hipe_ppc:mk_mfspr(Temp1, 'lr') | NewStartCodeTail2]
end,
NewStartCode0 =
- [hipe_ppc:mk_load('lwz', Temp1, ?P_NSP_LIMIT, P) |
+ [hipe_ppc:mk_load(hipe_ppc:ldop_word(), Temp1, ?P_NSP_LIMIT, P) |
hipe_ppc:mk_addi(Temp2, SP, -MaxStack,
[hipe_ppc:mk_cmp('cmpl', Temp2, Temp1) |
NewStartCodeTail1])],
diff --git a/lib/hipe/ppc/hipe_rtl_to_ppc.erl b/lib/hipe/ppc/hipe_rtl_to_ppc.erl
index 458af250de..7dfa56df29 100644
--- a/lib/hipe/ppc/hipe_rtl_to_ppc.erl
+++ b/lib/hipe/ppc/hipe_rtl_to_ppc.erl
@@ -1,20 +1,20 @@
%%% -*- erlang-indent-level: 2 -*-
%%%
%%% %CopyrightBegin%
-%%%
-%%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
-%%%
+%%%
+%%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%%%
%%% The contents of this file are subject to the Erlang Public License,
%%% Version 1.1, (the "License"); you may not use this file except in
%%% compliance with the License. You should have received a copy of the
%%% Erlang Public License along with this software. If not, it can be
%%% retrieved online at http://www.erlang.org/.
-%%%
+%%%
%%% Software distributed under the License is distributed on an "AS IS"
%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%%% the License for the specific language governing rights and limitations
%%% under the License.
-%%%
+%%%
%%% %CopyrightEnd%
%%%
%%% The PowerPC instruction set is quite irregular.
@@ -110,20 +110,27 @@ conv_fconv(I, Map, Data) ->
mk_fconv(Dst, Src) ->
CSP = hipe_ppc:mk_temp(1, 'untagged'),
- R0 = hipe_ppc:mk_temp(0, 'untagged'),
- RTmp1 = hipe_ppc:mk_new_temp('untagged'),
- RTmp2 = hipe_ppc:mk_new_temp('untagged'),
- RTmp3 = hipe_ppc:mk_new_temp('untagged'),
- FTmp1 = hipe_ppc:mk_new_temp('double'),
- FTmp2 = hipe_ppc:mk_new_temp('double'),
- [hipe_ppc:mk_pseudo_li(RTmp1, {fconv_constant,c_const}),
- hipe_ppc:mk_lfd(FTmp1, 0, RTmp1),
- hipe_ppc:mk_alu('xoris', RTmp2, Src, hipe_ppc:mk_uimm16(16#8000)),
- hipe_ppc:mk_store('stw', RTmp2, 28, CSP),
- hipe_ppc:mk_alu('addis', RTmp3, R0, hipe_ppc:mk_simm16(16#4330)),
- hipe_ppc:mk_store('stw', RTmp3, 24, CSP),
- hipe_ppc:mk_lfd(FTmp2, 24, CSP),
- hipe_ppc:mk_fp_binary('fsub', Dst, FTmp2, FTmp1)].
+ case get(hipe_target_arch) of
+ powerpc ->
+ R0 = hipe_ppc:mk_temp(0, 'untagged'),
+ RTmp1 = hipe_ppc:mk_new_temp('untagged'),
+ RTmp2 = hipe_ppc:mk_new_temp('untagged'),
+ RTmp3 = hipe_ppc:mk_new_temp('untagged'),
+ FTmp1 = hipe_ppc:mk_new_temp('double'),
+ FTmp2 = hipe_ppc:mk_new_temp('double'),
+ [hipe_ppc:mk_pseudo_li(RTmp1, {fconv_constant,c_const}),
+ hipe_ppc:mk_lfd(FTmp1, 0, RTmp1),
+ hipe_ppc:mk_alu('xoris', RTmp2, Src, hipe_ppc:mk_uimm16(16#8000)),
+ hipe_ppc:mk_store('stw', RTmp2, 28, CSP),
+ hipe_ppc:mk_alu('addis', RTmp3, R0, hipe_ppc:mk_simm16(16#4330)),
+ hipe_ppc:mk_store('stw', RTmp3, 24, CSP),
+ hipe_ppc:mk_lfd(FTmp2, 24, CSP),
+ hipe_ppc:mk_fp_binary('fsub', Dst, FTmp2, FTmp1)];
+ ppc64 ->
+ [hipe_ppc:mk_store('std', Src, 24, CSP),
+ hipe_ppc:mk_lfd(Dst, 24, CSP),
+ hipe_ppc:mk_fp_unary('fcfid', Dst, Dst)]
+ end.
conv_fmove(I, Map, Data) ->
%% Dst := Src, where both Dst and Src are FP regs
@@ -280,10 +287,14 @@ mk_alu_ri(Dst, Src1, RtlAluOp, Src2) ->
'mul' -> % 'mulli' has a 16-bit simm operand
mk_alu_ri_simm16(Dst, Src1, RtlAluOp, 'mulli', Src2);
'and' -> % 'andi.' has a 16-bit uimm operand
- case rlwinm_mask(Src2) of
- {MB,ME} ->
- [hipe_ppc:mk_unary({'rlwinm',0,MB,ME}, Dst, Src1)];
- _ ->
+ if Src2 band (bnot 16#ffffffff) =:= 0 ->
+ case rlwinm_mask(Src2) of
+ {MB,ME} ->
+ [hipe_ppc:mk_unary({'rlwinm',0,MB,ME}, Dst, Src1)];
+ _ ->
+ mk_alu_ri_bitop(Dst, Src1, RtlAluOp, 'andi.', Src2)
+ end;
+ true ->
mk_alu_ri_bitop(Dst, Src1, RtlAluOp, 'andi.', Src2)
end;
'or' -> % 'ori' has a 16-bit uimm operand
@@ -360,17 +371,33 @@ mk_alu_ri_bitop(Dst, Src1, RtlAluOp, AluOp, Src2) ->
end.
mk_alu_ri_shift(Dst, Src1, RtlAluOp, Src2) ->
- if Src2 < 32, Src2 >= 0 ->
- AluOp =
- case RtlAluOp of
- 'sll' -> 'slwi'; % alias for rlwinm
- 'srl' -> 'srwi'; % alias for rlwinm
- 'sra' -> 'srawi'
- end,
- [hipe_ppc:mk_alu(AluOp, Dst, Src1,
- hipe_ppc:mk_uimm16(Src2))];
- true ->
- mk_alu_ri_rr(Dst, Src1, RtlAluOp, Src2)
+ case get(hipe_target_arch) of
+ ppc64 ->
+ if Src2 < 64, Src2 >= 0 ->
+ AluOp =
+ case RtlAluOp of
+ 'sll' -> 'sldi'; % alias for rldimi %%% buggy
+ 'srl' -> 'srdi'; % alias for rldimi %%% buggy
+ 'sra' -> 'sradi' %%% buggy
+ end,
+ [hipe_ppc:mk_alu(AluOp, Dst, Src1,
+ hipe_ppc:mk_uimm16(Src2))];
+ true ->
+ mk_alu_ri_rr(Dst, Src1, RtlAluOp, Src2)
+ end;
+ powerpc ->
+ if Src2 < 32, Src2 >= 0 ->
+ AluOp =
+ case RtlAluOp of
+ 'sll' -> 'slwi'; % alias for rlwinm
+ 'srl' -> 'srwi'; % alias for rlwinm
+ 'sra' -> 'srawi'
+ end,
+ [hipe_ppc:mk_alu(AluOp, Dst, Src1,
+ hipe_ppc:mk_uimm16(Src2))];
+ true ->
+ mk_alu_ri_rr(Dst, Src1, RtlAluOp, Src2)
+ end
end.
mk_alu_ri_rr(Dst, Src1, RtlAluOp, Src2) ->
@@ -384,15 +411,21 @@ mk_alu_rr(Dst, Src1, RtlAluOp, Src2) ->
[hipe_ppc:mk_alu('subf', Dst, Src2, Src1)];
_ ->
AluOp =
- case RtlAluOp of
- 'add' -> 'add';
- 'mul' -> 'mullw';
- 'or' -> 'or';
- 'and' -> 'and';
- 'xor' -> 'xor';
- 'sll' -> 'slw';
- 'srl' -> 'srw';
- 'sra' -> 'sraw'
+ case {get(hipe_target_arch), RtlAluOp} of
+ {_, 'add'} -> 'add';
+ {_, 'or'} -> 'or';
+ {_, 'and'} -> 'and';
+ {_, 'xor'} -> 'xor';
+
+ {powerpc, 'mul'} -> 'mullw';
+ {powerpc, 'sll'} -> 'slw';
+ {powerpc, 'srl'} -> 'srw';
+ {powerpc, 'sra'} -> 'sraw';
+
+ {ppc64, 'mul'} -> 'mulld';
+ {ppc64, 'sll'} -> 'sld';
+ {ppc64, 'srl'} -> 'srd';
+ {ppc64, 'sra'} -> 'srad'
end,
[hipe_ppc:mk_alu(AluOp, Dst, Src1, Src2)]
end.
@@ -431,16 +464,22 @@ conv_alub(I, Map, Data) ->
{I1 ++ I2, Map2, Data}.
conv_alub_op(RtlAluOp) ->
- case RtlAluOp of
- 'add' -> 'add';
- 'sub' -> 'subf'; % XXX: must swap operands
- 'mul' -> 'mullw';
- 'or' -> 'or';
- 'and' -> 'and';
- 'xor' -> 'xor';
- 'sll' -> 'slw';
- 'srl' -> 'srw';
- 'sra' -> 'sraw'
+ case {get(hipe_target_arch), RtlAluOp} of
+ {_, 'add'} -> 'add';
+ {_, 'sub'} -> 'subf'; % XXX: must swap operands
+ {_, 'or'} -> 'or';
+ {_, 'and'} -> 'and';
+ {_, 'xor'} -> 'xor';
+
+ {powerpc, 'mul'} -> 'mullw';
+ {powerpc, 'sll'} -> 'slw';
+ {powerpc, 'srl'} -> 'srw';
+ {powerpc, 'sra'} -> 'sraw';
+
+ {ppc64, 'mul'} -> 'mulld';
+ {ppc64, 'sll'} -> 'sld';
+ {ppc64, 'srl'} -> 'srd';
+ {ppc64, 'sra'} -> 'srad'
end.
aluop_commutes(AluOp) ->
@@ -454,7 +493,11 @@ aluop_commutes(AluOp) ->
'xor' -> true;
'slw' -> false;
'srw' -> false;
- 'sraw' -> false
+ 'sraw' -> false;
+ 'mulld' -> true; % ppc64
+ 'sld' -> false; % ppc64
+ 'srd' -> false; % ppc64
+ 'srad' -> false % ppc64
end.
conv_alub_cond(Cond) -> % only signed
@@ -528,17 +571,24 @@ mk_alub_ri_Rc(Dst, Src1, AluOp, Src2) ->
mk_alub_ri_Rc_addi(Dst, Src1, Src2, 'addic.', 'add.');
'addc' -> % 'addic' has a 16-bit simm operand
mk_alub_ri_Rc_addi(Dst, Src1, Src2, 'addic', 'addc');
- 'mullw' -> % there is no 'mulli.'
+ 'mullw' -> % there is no 'mulli.'
mk_alub_ri_Rc_rr(Dst, Src1, 'mullw.', Src2);
+ 'mulld' -> % there is no 'mulli.'
+ mk_alub_ri_Rc_rr(Dst, Src1, 'mulld.', Src2);
'or' -> % there is no 'ori.'
mk_alub_ri_Rc_rr(Dst, Src1, 'or.', Src2);
'xor' -> % there is no 'xori.'
mk_alub_ri_Rc_rr(Dst, Src1, 'xor.', Src2);
'and' -> % 'andi.' has a 16-bit uimm operand
- case rlwinm_mask(Src2) of
- {MB,ME} ->
- [hipe_ppc:mk_unary({'rlwinm.',0,MB,ME}, Dst, Src1)];
- _ ->
+ if
+ Src2 band (bnot 16#ffffffff) =:= 0 ->
+ case rlwinm_mask(Src2) of
+ {MB,ME} ->
+ [hipe_ppc:mk_unary({'rlwinm.',0,MB,ME}, Dst, Src1)];
+ _ ->
+ mk_alub_ri_Rc_andi(Dst, Src1, Src2)
+ end;
+ true ->
mk_alub_ri_Rc_andi(Dst, Src1, Src2)
end;
_ -> % shift ops have 5-bit uimm operands
@@ -562,13 +612,16 @@ mk_alub_ri_Rc_andi(Dst, Src1, Src2) ->
end.
mk_alub_ri_Rc_shift(Dst, Src1, AluOp, Src2) ->
- if Src2 < 32, Src2 >= 0 ->
- AluOpIDot =
- case AluOp of
- 'slw' -> 'slwi.'; % alias for rlwinm.
- 'srw' -> 'srwi.'; % alias for rlwinm.
- 'sraw' -> 'srawi.'
- end,
+ {AluOpIDot, MaxIShift} =
+ case AluOp of
+ 'slw' -> {'slwi.', 32}; % alias for rlwinm.
+ 'srw' -> {'srwi.', 32}; % alias for rlwinm.
+ 'sraw' -> {'srawi.', 32};
+ 'sld' -> {'sldi.', 64};
+ 'srd' -> {'srdi.', 64};
+ 'srad' -> {'sradi.', 64}
+ end,
+ if Src2 < MaxIShift, Src2 >= 0 ->
[hipe_ppc:mk_alu(AluOpIDot, Dst, Src1,
hipe_ppc:mk_uimm16(Src2))];
true ->
@@ -576,7 +629,10 @@ mk_alub_ri_Rc_shift(Dst, Src1, AluOp, Src2) ->
case AluOp of
'slw' -> 'slw.';
'srw' -> 'srw.';
- 'sraw' -> 'sraw.'
+ 'sraw' -> 'sraw.';
+ 'sld' -> 'sld.';
+ 'srd' -> 'srd.';
+ 'srad' -> 'srad.'
end,
mk_alub_ri_Rc_rr(Dst, Src1, AluOpDot, Src2)
end.
@@ -598,8 +654,9 @@ mk_alub_rr_OE(Dst, Src1, AluOp, Src2) ->
case AluOp of
'subf' -> 'subfo.';
'add' -> 'addo.';
- 'mullw' -> 'mullwo.'
- %% fail for addc, or, and, xor, slw, srw, sraw
+ 'mullw' -> 'mullwo.';
+ 'mulld' -> 'mulldo.'
+ %% fail for addc, or, and, xor, slw, srw, sraw
end,
[hipe_ppc:mk_alu(AluOpODot, Dst, Src1, Src2)].
@@ -610,12 +667,16 @@ mk_alub_rr_Rc(Dst, Src1, AluOp, Src2) ->
'add' -> 'add.';
'addc' -> 'addc'; % only interested in CA, no Rc needed
'mullw' -> 'mullw.';
+ 'mulld' -> 'mulld.';
'or' -> 'or.';
'and' -> 'and.';
'xor' -> 'xor.';
'slw' -> 'slw.';
+ 'sld' -> 'sld.';
'srw' -> 'srw.';
- 'sraw' -> 'sraw.'
+ 'srd' -> 'srd.';
+ 'sraw' -> 'sraw.';
+ 'srad' -> 'srad.'
end,
[hipe_ppc:mk_alu(AluOpDot, Dst, Src1, Src2)].
@@ -682,17 +743,17 @@ mk_branch_ri(Src1, BCond, Sign, Src2, TrueLab, FalseLab, Pred) ->
case Sign of
'signed' ->
if is_integer(Src2), -32768 =< Src2, Src2 < 32768 ->
- {[], hipe_ppc:mk_simm16(Src2), 'cmpi'};
+ {[], hipe_ppc:mk_simm16(Src2), hipe_ppc:cmpiop_word()};
true ->
Tmp = new_untagged_temp(),
- {mk_li(Tmp, Src2), Tmp, 'cmp'}
+ {mk_li(Tmp, Src2), Tmp, hipe_ppc:cmpop_word()}
end;
'unsigned' ->
if is_integer(Src2), 0 =< Src2, Src2 < 65536 ->
- {[], hipe_ppc:mk_uimm16(Src2), 'cmpli'};
+ {[], hipe_ppc:mk_uimm16(Src2), hipe_ppc:cmpliop_word()};
true ->
Tmp = new_untagged_temp(),
- {mk_li(Tmp, Src2), Tmp, 'cmpl'}
+ {mk_li(Tmp, Src2), Tmp, hipe_ppc:cmplop_word()}
end
end,
FixSrc2 ++
@@ -701,8 +762,8 @@ mk_branch_ri(Src1, BCond, Sign, Src2, TrueLab, FalseLab, Pred) ->
mk_branch_rr(Src1, BCond, Sign, Src2, TrueLab, FalseLab, Pred) ->
CmpOp =
case Sign of
- 'signed' -> 'cmp';
- 'unsigned' -> 'cmpl'
+ 'signed' -> hipe_ppc:cmpop_word();
+ 'unsigned' -> hipe_ppc:cmplop_word()
end,
mk_cmp_bc(CmpOp, Src1, Src2, BCond, TrueLab, FalseLab, Pred).
@@ -841,7 +902,7 @@ mk_store_args([Arg|Args], PrevOffset, Tail) ->
Tmp = new_tagged_temp(),
{Tmp, mk_li(Tmp, Arg)}
end,
- Store = hipe_ppc:mk_store('stw', Src, Offset, mk_sp()),
+ Store = hipe_ppc:mk_store(hipe_ppc:stop_word(), Src, Offset, mk_sp()),
mk_store_args(Args, Offset, FixSrc ++ [Store | Tail]);
mk_store_args([], _, Tail) ->
Tail.
@@ -883,25 +944,19 @@ conv_load(I, Map, Data) ->
{I2, Map2, Data}.
mk_load(Dst, Base1, Base2, LoadSize, LoadSign) ->
- Rest =
- case LoadSize of
- byte ->
- case LoadSign of
- signed -> [hipe_ppc:mk_unary('extsb', Dst, Dst)];
- _ -> []
+ {LdOp, Rest} =
+ case {LoadSize, LoadSign} of
+ {byte, signed} -> {'lbz', [hipe_ppc:mk_unary('extsb', Dst, Dst)]};
+ {byte, unsigned} -> {'lbz', []};
+ {int16, signed} -> {'lha', []};
+ {int16, unsigned} -> {'lhz', []};
+ {int32, signed} ->
+ case get(hipe_target_arch) of
+ powerpc -> {'lwz', []};
+ ppc64 -> {'lwa', []}
end;
- _ -> []
- end,
- LdOp =
- case LoadSize of
- byte -> 'lbz';
- int32 -> 'lwz';
- word -> 'lwz';
- int16 ->
- case LoadSign of
- signed -> 'lha';
- unsigned -> 'lhz'
- end
+ {int32, unsigned} -> {'lwz', []};
+ {word, _} -> {hipe_ppc:ldop_word(), []}
end,
case hipe_ppc:is_temp(Base1) of
true ->
@@ -980,7 +1035,7 @@ mk_store(Src, Base1, Base2, StoreSize) ->
byte -> 'stb';
int16 -> 'sth';
int32 -> 'stw';
- word -> 'stw'
+ word -> hipe_ppc:stop_word()
end,
case hipe_ppc:is_temp(Src) of
true ->
@@ -1022,10 +1077,16 @@ conv_switch(I, Map, Data) ->
JTabR = new_untagged_temp(),
OffsetR = new_untagged_temp(),
DestR = new_untagged_temp(),
+ ShiftInstruction =
+ case get(hipe_target_arch) of
+ powerpc -> 'slwi';
+ ppc64 -> 'sldi'
+ end,
I2 =
[hipe_ppc:mk_pseudo_li(JTabR, {JTabLab,constant}),
- hipe_ppc:mk_alu('slwi', OffsetR, IndexR, hipe_ppc:mk_uimm16(2)),
- hipe_ppc:mk_loadx('lwzx', DestR, JTabR, OffsetR),
+ hipe_ppc:mk_alu(ShiftInstruction, OffsetR, IndexR,
+ hipe_ppc:mk_uimm16(log2_word_size())),
+ hipe_ppc:mk_loadx(hipe_ppc:ldop_wordx(), DestR, JTabR, OffsetR),
hipe_ppc:mk_mtspr('ctr', DestR),
hipe_ppc:mk_bctr(Labels)],
{I2, Map1, NewData}.
@@ -1247,3 +1308,6 @@ vmap_bind(Map, Key, Val) ->
word_size() ->
hipe_rtl_arch:word_size().
+
+log2_word_size() ->
+ hipe_rtl_arch:log2_word_size().
diff --git a/lib/hipe/regalloc/hipe_node_sets.erl b/lib/hipe/regalloc/hipe_node_sets.erl
index b5e2971c4d..be43ff2bfd 100644
--- a/lib/hipe/regalloc/hipe_node_sets.erl
+++ b/lib/hipe/regalloc/hipe_node_sets.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The 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 @@
-record(node_sets,
{spilled, % Nodes marked for spilling
- colored % Nodes succesfully colored
+ colored % Nodes successfully colored
}).
spilled(Node_sets) -> Node_sets#node_sets.spilled.
diff --git a/lib/hipe/rtl/hipe_rtl_arch.erl b/lib/hipe/rtl/hipe_rtl_arch.erl
index 2afdf4eb6b..22cda57a3a 100644
--- a/lib/hipe/rtl/hipe_rtl_arch.erl
+++ b/lib/hipe/rtl/hipe_rtl_arch.erl
@@ -1,20 +1,20 @@
%% -*- erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -86,6 +86,8 @@ first_virtual_reg() ->
hipe_sparc_registers:first_virtual();
powerpc ->
hipe_ppc_registers:first_virtual();
+ ppc64 ->
+ hipe_ppc_registers:first_virtual();
arm ->
hipe_arm_registers:first_virtual();
x86 ->
@@ -100,6 +102,8 @@ heap_pointer() -> % {GetHPInsn, HPReg, PutHPInsn}
heap_pointer_from_reg(hipe_sparc_registers:heap_pointer());
powerpc ->
heap_pointer_from_reg(hipe_ppc_registers:heap_pointer());
+ ppc64 ->
+ heap_pointer_from_reg(hipe_ppc_registers:heap_pointer());
arm ->
heap_pointer_from_reg(hipe_arm_registers:heap_pointer());
x86 ->
@@ -143,6 +147,8 @@ heap_limit() -> % {GetHLIMITInsn, HLIMITReg}
heap_limit_from_pcb();
powerpc ->
heap_limit_from_pcb();
+ ppc64 ->
+ heap_limit_from_pcb();
arm ->
heap_limit_from_pcb();
x86 ->
@@ -165,6 +171,8 @@ fcalls() -> % {GetFCallsInsn, FCallsReg, PutFCallsInsn}
fcalls_from_pcb();
powerpc ->
fcalls_from_pcb();
+ ppc64 ->
+ fcalls_from_pcb();
arm ->
fcalls_from_pcb();
x86 ->
@@ -188,6 +196,8 @@ reg_name(Reg) ->
hipe_sparc_registers:reg_name_gpr(Reg);
powerpc ->
hipe_ppc_registers:reg_name_gpr(Reg);
+ ppc64 ->
+ hipe_ppc_registers:reg_name_gpr(Reg);
arm ->
hipe_arm_registers:reg_name_gpr(Reg);
x86 ->
@@ -215,6 +225,8 @@ is_precolored_regnum(RegNum) ->
hipe_sparc_registers:is_precoloured_gpr(RegNum);
powerpc ->
hipe_ppc_registers:is_precoloured_gpr(RegNum);
+ ppc64 ->
+ hipe_ppc_registers:is_precoloured_gpr(RegNum);
arm ->
hipe_arm_registers:is_precoloured_gpr(RegNum);
x86 ->
@@ -243,6 +255,9 @@ live_at_return() ->
powerpc ->
ordsets:from_list([hipe_rtl:mk_reg(R)
|| {R,_} <- hipe_ppc_registers:live_at_return()]);
+ ppc64 ->
+ ordsets:from_list([hipe_rtl:mk_reg(R)
+ || {R,_} <- hipe_ppc_registers:live_at_return()]);
arm ->
ordsets:from_list([hipe_rtl:mk_reg(R)
|| {R,_} <- hipe_arm_registers:live_at_return()]);
@@ -262,6 +277,7 @@ word_size() ->
case get(hipe_target_arch) of
ultrasparc -> 4;
powerpc -> 4;
+ ppc64 -> 8;
arm -> 4;
x86 -> 4;
amd64 -> 8
@@ -284,6 +300,7 @@ log2_word_size() ->
case get(hipe_target_arch) of
ultrasparc -> 2;
powerpc -> 2;
+ ppc64 -> 3;
arm -> 2;
x86 -> 2;
amd64 -> 3
@@ -297,6 +314,7 @@ endianess() ->
case get(hipe_target_arch) of
ultrasparc -> big;
powerpc -> big;
+ ppc64 -> big;
x86 -> little;
amd64 -> little;
arm -> ?ARM_ENDIANESS
@@ -313,6 +331,8 @@ load_big_2(Dst, Base, Offset, Signedness) ->
case get(hipe_target_arch) of
powerpc ->
load_2_directly(Dst, Base, Offset, Signedness);
+ ppc64 ->
+ load_2_directly(Dst, Base, Offset, Signedness);
%% Note: x86 could use a "load;xchgb" or "load;rol $8,<16-bit reg>"
%% sequence here. This has been implemented, but unfortunately didn't
%% make consistent improvements to our benchmarks.
@@ -333,6 +353,13 @@ load_little_2(Dst, Base, Offset, Signedness) ->
unsigned -> [];
signed -> [hipe_rtl:mk_call([Dst], 'extsh', [Dst], [], [], not_remote)]
end];
+ ppc64 ->
+ [hipe_rtl:mk_call([Dst], 'lhbrx', [Base,Offset], [], [], not_remote),
+ hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(2)) |
+ case Signedness of
+ unsigned -> [];
+ signed -> [hipe_rtl:mk_call([Dst], 'extsh', [Dst], [], [], not_remote)]
+ end];
_ ->
load_little_2_in_pieces(Dst, Base, Offset, Signedness)
end.
@@ -365,6 +392,8 @@ load_big_4(Dst, Base, Offset, Signedness) ->
case get(hipe_target_arch) of
powerpc ->
load_4_directly(Dst, Base, Offset, Signedness);
+ ppc64 ->
+ load_4_directly(Dst, Base, Offset, Signedness);
%% Note: x86 could use a "load;bswap" sequence here.
%% This has been implemented, but unfortunately didn't
%% make any noticeable improvements in our benchmarks.
@@ -386,6 +415,13 @@ load_little_4(Dst, Base, Offset, Signedness) ->
powerpc ->
[hipe_rtl:mk_call([Dst], 'lwbrx', [Base,Offset], [], [], not_remote),
hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(4))];
+ ppc64 ->
+ [hipe_rtl:mk_call([Dst], 'lwbrx', [Base,Offset], [], [], not_remote),
+ hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(4)) |
+ case Signedness of
+ unsigned -> [];
+ signed -> [hipe_rtl:mk_call([Dst], 'extsw', [Dst], [], [], not_remote)]
+ end];
arm ->
%% When loading 4 bytes into a 32-bit register, the
%% signedness of the high-order byte doesn't matter.
@@ -396,7 +432,7 @@ load_little_4(Dst, Base, Offset, Signedness) ->
end.
load_4_directly(Dst, Base, Offset, Signedness) ->
- [hipe_rtl:mk_load(Dst, Base, Offset, word, Signedness),
+ [hipe_rtl:mk_load(Dst, Base, Offset, int32, Signedness),
hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(4))].
load_big_4_in_pieces(Dst, Base, Offset, Signedness) ->
@@ -440,6 +476,8 @@ store_4(Base, Offset, Src) ->
store_4_directly(Base, Offset, Src);
powerpc ->
store_4_directly(Base, Offset, Src);
+ ppc64 ->
+ store_4_directly(Base, Offset, Src);
arm ->
store_big_4_in_pieces(Base, Offset, Src);
ultrasparc ->
@@ -525,6 +563,7 @@ fwait() ->
amd64 -> [hipe_rtl:mk_call([], 'fwait', [], [], [], not_remote)];
arm -> [];
powerpc -> [];
+ ppc64 -> [];
ultrasparc -> []
end.
@@ -549,6 +588,8 @@ handle_fp_exception() ->
[];
powerpc ->
[];
+ ppc64 ->
+ [];
ultrasparc ->
[]
end.
@@ -577,6 +618,8 @@ proc_pointer() -> % must not be exported
hipe_rtl:mk_reg_gcsafe(hipe_sparc_registers:proc_pointer());
powerpc ->
hipe_rtl:mk_reg_gcsafe(hipe_ppc_registers:proc_pointer());
+ ppc64 ->
+ hipe_rtl:mk_reg_gcsafe(hipe_ppc_registers:proc_pointer());
arm ->
hipe_rtl:mk_reg_gcsafe(hipe_arm_registers:proc_pointer());
x86 ->
@@ -601,6 +644,8 @@ nr_of_return_regs() ->
%% hipe_sparc_registers:nr_rets();
powerpc ->
1;
+ ppc64 ->
+ 1;
%% hipe_ppc_registers:nr_rets();
arm ->
1;
diff --git a/lib/hipe/rtl/hipe_rtl_lcm.erl b/lib/hipe/rtl/hipe_rtl_lcm.erl
index 5d65389d48..9224623c8b 100644
--- a/lib/hipe/rtl/hipe_rtl_lcm.erl
+++ b/lib/hipe/rtl/hipe_rtl_lcm.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -269,7 +269,7 @@ insert_expr_last(CFG0, Label, Instr) ->
%% is a branch operation).
insert_expr_last_work(_, Instr, []) ->
%% This case should not happen since this means that block was completely
- %% empty when the function was called. For compability we insert it last.
+ %% empty when the function was called. For compatibility we insert it last.
[Instr];
insert_expr_last_work(_, Instr, [Code1]) ->
%% We insert the code next to last.
diff --git a/lib/hipe/rtl/hipe_tagscheme.erl b/lib/hipe/rtl/hipe_tagscheme.erl
index 5859c345d0..0cc6c2deec 100644
--- a/lib/hipe/rtl/hipe_tagscheme.erl
+++ b/lib/hipe/rtl/hipe_tagscheme.erl
@@ -1045,7 +1045,7 @@ convert_matchstate(Ms) ->
build_sub_binary(Ms, ByteSize, ByteOffset, BitSize, BitOffset,
hipe_rtl:mk_imm(0), Orig),
size_from_header(SizeInWords, Header),
- hipe_rtl:mk_alu(Hole, SizeInWords, sub, hipe_rtl:mk_imm(?SUB_BIN_WORDSIZE-1)),
+ hipe_rtl:mk_alu(Hole, SizeInWords, sub, hipe_rtl:mk_imm(?SUB_BIN_WORDSIZE)),
mk_var_header(BigIntHeader, Hole, ?TAG_HEADER_POS_BIG),
hipe_rtl:mk_store(Ms, hipe_rtl:mk_imm(?SUB_BIN_WORDSIZE*WordSize-?TAG_PRIMARY_BOXED),
BigIntHeader)].
diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk
index 6ba9009a24..65e04ff7fa 100644
--- a/lib/hipe/vsn.mk
+++ b/lib/hipe/vsn.mk
@@ -1 +1 @@
-HIPE_VSN = 3.7.9
+HIPE_VSN = 3.8.1
diff --git a/lib/ic/c_src/Makefile.in b/lib/ic/c_src/Makefile.in
index 6eef7827b9..28040ca42d 100644
--- a/lib/ic/c_src/Makefile.in
+++ b/lib/ic/c_src/Makefile.in
@@ -125,13 +125,9 @@ docs:
# Special Build Targets
# ----------------------------------------------------
-$(OBJDIR):
- -mkdir -p $(OBJDIR)
+_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
-$(LIBDIR):
- -mkdir -p $(LIBDIR)
-
-$(LIBRARY): $(OBJDIR) $(LIBDIR) $(OBJ_FILES)
+$(LIBRARY): $(OBJ_FILES)
-$(AR) $(AR_OUT) $@ $(OBJ_FILES)
-$(RANLIB) $@
diff --git a/lib/ic/doc/src/Makefile b/lib/ic/doc/src/Makefile
index 8eda436a24..acb6848fee 100644
--- a/lib/ic/doc/src/Makefile
+++ b/lib/ic/doc/src/Makefile
@@ -206,6 +206,8 @@ JAVADOCFLAGS = \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
+_create_dirs := $(shell mkdir -p $(JAVA_OUT_DIR))
+
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
@@ -256,10 +258,7 @@ clean clean_docs clean_tex:
endif
-$(JAVA_OUT_DIR):
- mkdir $(JAVA_OUT_DIR)
-
-$(JAVADOC_GENERATED_FILES): $(JAVA_OUT_DIR)
+$(JAVADOC_GENERATED_FILES):
@(cd ../../java_src; $(JAVADOC) $(JAVADOCFLAGS) com.ericsson.otp.ic)
man: $(MAN3_FILES)
diff --git a/lib/ic/doc/src/notes.xml b/lib/ic/doc/src/notes.xml
index 5f6c31069c..de519d5f84 100644
--- a/lib/ic/doc/src/notes.xml
+++ b/lib/ic/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1998</year><year>2010</year>
+ <year>1998</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,22 @@
</header>
<section>
+ <title>IC 4.2.27</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>
+ Reduced compile overhead (Thanks to Haitao Li).</p>
+ <p>
+ Own Id: OTP-9460 </p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
<title>IC 4.2.26</title>
<section>
diff --git a/lib/ic/examples/pre_post_condition/Makefile b/lib/ic/examples/pre_post_condition/Makefile
index 68e2168e1e..85cbbdb9ff 100644
--- a/lib/ic/examples/pre_post_condition/Makefile
+++ b/lib/ic/examples/pre_post_condition/Makefile
@@ -108,9 +108,14 @@ docs:
test: $(TEST_TARGET_FILES)
-$(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES): ex.idl
+IDL-GENERATED: ex.idl
erlc $(ERL_LOCAL_FLAGS) +'{precond,{tracer,pre}}' \
+'{{postcond,"m::i::f"},{tracer,post}}' ex.idl
+ >IDL-GENERATED
+
+$(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Target
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/ignore_config_record.inf b/lib/ic/java_src/com/ericsson/otp/ic/ignore_config_record.inf
deleted file mode 100644
index 34e5586175..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/ignore_config_record.inf
+++ /dev/null
@@ -1 +0,0 @@
-Dummy to speed up compilatio
diff --git a/lib/ic/src/ic.erl b/lib/ic/src/ic.erl
index 3c6ce3d9d6..50fad921c4 100644
--- a/lib/ic/src/ic.erl
+++ b/lib/ic/src/ic.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -320,7 +320,7 @@ pragma(G, File, T) ->
time,
time("pragma registration ", ic_pragma, pragma_reg, [G,T]),
ic_pragma:pragma_reg(G,T)) of
- %% All pragmas were succesfully applied
+ %% All pragmas were successfully applied
{ok,Clean} ->
typing(G, File, Clean);
diff --git a/lib/ic/src/ic_pp.erl b/lib/ic/src/ic_pp.erl
index db06118d32..8b53473caa 100644
--- a/lib/ic/src/ic_pp.erl
+++ b/lib/ic/src/ic_pp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The 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,6 +92,14 @@
%%
%%======================================================================================
+%% Multiple Include Optimization
+%%
+%% Algorithm described at:
+%% http://gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html
+-record(mio, {valid = true, %% multiple include valid
+ cmacro, %% controlling macro of the current conditional directive
+ depth = 0, %% conditional directive depth
+ included = []}).
@@ -130,7 +138,7 @@ run(FileList, FileName, IncDir, Flags) ->
%%----------------------------------------------------------
%% Run the second phase, i.e expand macros
%%----------------------------------------------------------
- {Out, Err, War, _Defs, IfCou} = expand(File, FileName, IncDir, Flags),
+ {Out, Err, War, _Defs, _Mio, IfCou} = expand(File, FileName, IncDir, Flags),
%%----------------------------------------------------------
%% Check if all #if #ifdef #ifndef have a matching #endif
@@ -155,9 +163,9 @@ run(FileList, FileName, IncDir, Flags) ->
%% The entry for all included files
%%
%%
-%% Output {Out, Defs, Err, War}
+%% Output {Out, Err, War, Defs, MultipleIncludeValid}
%%======================================================================================
-run_include(FileName, FileList, _Out, Defs, Err, War, IncLine, IncFile, IncDir) ->
+run_include(FileName, FileList, _Out, Defs, Err, War, IncLine, IncFile, IncDir, Mio) ->
%%----------------------------------------------------------
%% Run the first phase, i.e tokenise the file
@@ -169,18 +177,21 @@ run_include(FileName, FileList, _Out, Defs, Err, War, IncLine, IncFile, IncDir)
%%----------------------------------------------------------
%% Run the second phase, i.e expand macros
%%----------------------------------------------------------
-
- %% Try first pass without file info start/end
- {OutT, ErrT, WarT, DefsT, IfCouT} =
- expand(File, Defs, Err, War, [FileName|IncFile], IncDir),
-
- {Out2, Err2, War2, Defs2, IfCou2} =
- case only_nls(OutT) of
- true -> %% The file is defined before
- {["\n"], ErrT, WarT, DefsT, IfCouT};
- false -> %% The file is not defined before, try second pass
- expand([FileInfoStart|File]++FileInfoEnd, Defs, Err, War, [FileName|IncFile], IncDir)
- end,
+ {Out2, Err2, War2, Defs2, Mio2, IfCou2} =
+ expand([FileInfoStart|File]++FileInfoEnd, Defs, Err, War,
+ [FileName|IncFile], IncDir,
+ #mio{included=Mio#mio.included}),
+
+ MergeIncluded = sets:to_list(sets:from_list(Mio#mio.included ++ Mio2#mio.included)),
+
+ Mio3 =
+ case {Mio2#mio.valid, Mio2#mio.cmacro} of
+ {V, Macro} when V == false;
+ Macro == undefined ->
+ update_mio(Mio#mio{included=MergeIncluded});
+ {true, _} ->
+ update_mio({include, FileName}, Mio#mio{included=MergeIncluded})
+ end,
%%----------------------------------------------------------
%% Check if all #if #ifdef #ifndef have a matching #endif
@@ -192,26 +203,7 @@ run_include(FileName, FileList, _Out, Defs, Err, War, IncLine, IncFile, IncDir)
[]
end,
- {Out2, Defs2, Err2++IfError, War2}.
-
-
-
-%% Return true if there is no data
-%% other than new lines
-only_nls([]) ->
- true;
-only_nls(["\n"|Rem]) ->
- only_nls(Rem);
-only_nls(["\r","\n"|Rem]) ->
- only_nls(Rem);
-only_nls([_|_Rem]) ->
- false.
-
-
-
-
-
-
+ {Out2, Defs2, Err2++IfError, War2, Mio3}.
@@ -647,87 +639,86 @@ expand(List, FileName, IncDir, Flags) ->
%% Get all definitions from preprocessor commnads
%% and merge them on top of the file collected.
CLDefs = get_cmd_line_defs(Flags),
- expand(List, [], [], CLDefs, [FileName], IncDir, check_all, [], [], 1, FileName).
-
-expand(List, Defs, Err, War, [FileName|IncFile], IncDir) ->
- expand(List, [], [], Defs, [FileName|IncFile], IncDir, check_all, Err, War, 1, FileName).
+ expand(List, [], [], CLDefs, [FileName], IncDir, #mio{}, check_all, [], [], 1, FileName).
+expand(List, Defs, Err, War, [FileName|IncFile], IncDir, Mio) ->
+ expand(List, [], [], Defs, [FileName|IncFile], IncDir, Mio, check_all, Err, War, 1, FileName).
%%=======================================================
%% Main loop for the expansion
%%=======================================================
-expand([], Out, _SelfRef, Defs, _IncFile, _IncDir, IfCou, Err, War, _L, _FN) ->
+expand([], Out, _SelfRef, Defs, _IncFile, _IncDir, Mio, IfCou, Err, War, _L, _FN) ->
% io:format("~n ===============~n"),
% io:format(" definitions ~p~n",[lists:reverse(Defs)]),
% io:format(" found warnings ~p~n",[lists:reverse(War)]),
% io:format(" found errors ~p~n",[lists:reverse(Err)]),
% io:format(" ===============~n~n~n"),
- {Out, Err, War, Defs, IfCou};
+ {Out, Err, War, Defs, Mio, IfCou};
-expand([{file_info, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
- expand(Rem, Str++Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+expand([{file_info, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
+ expand(Rem, Str++Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN);
%%---------------------------------------
%% Searching for endif,
%% i.e skip all source lines until matching
%% end if is encountered
%%---------------------------------------
-expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN)
+expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN)
when Command == "ifdef" ->
{_Removed, Rem2, _Nl} = read_to_nl(Rem),
IfCou2 = {endif, Endif+1, IfLine},
- expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, IfCou2, Err, War, L, FN);
+ expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err, War, L, FN);
-expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN)
+expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN)
when Command == "ifndef" ->
{_Removed, Rem2, _Nl} = read_to_nl(Rem),
IfCou2 = {endif, Endif+1, IfLine},
- expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, IfCou2, Err, War, L, FN);
+ expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err, War, L, FN);
-expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN)
+expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN)
when Command == "if" ->
- case pp_command(Command, Rem, Defs, IncDir, Err, War, L, FN) of
+ case pp_command(Command, Rem, Defs, IncDir, Mio, Err, War, L, FN) of
{{'if', true}, Rem2, Err2, War2, Nl} ->
IfCou2 = {endif, Endif+1, IfLine},
- expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, IfCou2, Err2, War2, L+Nl, FN);
+ expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN);
%% {{'if', false}, Rem2, Err2, War2, Nl} -> Not implemented yet
{{'if', error}, Rem2, Err2, War2, Nl} ->
IfCou2 = {endif, Endif, IfLine},
- expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, IfCou2, Err2, War2, L+Nl, FN)
+ expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN)
end;
-expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN)
+expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN)
when Command == "endif" ->
{_Removed, Rem2, Nl} = read_to_nl(Rem),
case Endif of
1 ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, check_all, Err, War, L+Nl, FN);
_ ->
IfCou2 = {endif, Endif-1, IfLine},
- expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, IfCou2, Err, War, L+Nl, FN)
+ expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err, War, L+Nl, FN)
end;
-expand([{command,_Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN) ->
+expand([{command,_Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) ->
{_Removed, Rem2, _Nl} = read_to_nl(Rem),
IfCou2 = {endif, Endif, IfLine},
- expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, IfCou2, Err, War, L, FN);
+ expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err, War, L, FN);
%% Solves a bug when spaces in front of hashmark !
-expand([space | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN) ->
- expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN);
+expand([space | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) ->
+ expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN);
-expand([{nl,_Nl} | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN) ->
- expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN);
+expand([{nl,_Nl} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) ->
+ expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN);
-expand([_X | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN) ->
+expand([_X | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) ->
{_Removed, Rem2, Nl} = read_to_nl(Rem),
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine}, Err, War, L, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN);
@@ -736,121 +727,132 @@ expand([_X | Rem], Out, SelfRef, Defs, IncFile, IncDir, {endif, Endif, IfLine},
%%---------------------------------------
%% Check all tokens
%%---------------------------------------
-expand([{nl, _N} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
- expand(Rem, [$\n | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L+1, FN);
+expand([{nl, _N} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
+ expand(Rem, [$\n | Out], SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L+1, FN);
-expand([space | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
- expand(Rem, [?space | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+expand([space | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
+ expand(Rem, [?space | Out], SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN);
-expand([space_exp | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
- expand(Rem, [?space | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+expand([space_exp | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
+ expand(Rem, [?space | Out], SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN);
-expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L, FN) ->
- case pp_command(Command, Rem, Defs, IncDir, Err, War, L, FN) of
+expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, check_all, Err, War, L, FN) ->
+ case pp_command(Command, Rem, Defs, IncDir, Mio, Err, War, L, FN) of
{define, Rem2, Defs2, Err2, War2, Nl} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs2, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ expand(Rem2, Out2, SelfRef, Defs2, IncFile, IncDir, update_mio(Mio), check_all, Err2, War2, L+Nl, FN);
{undef, Rem2, Defs2, Err2, War2, Nl} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs2, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ expand(Rem2, Out2, SelfRef, Defs2, IncFile, IncDir, update_mio(Mio), check_all, Err2, War2, L+Nl, FN);
{{include, ok}, FileName, FileCont, Rem2, Nl, Err2, War2} ->
- {Out3, Defs3, Err3, War3} =
- run_include(FileName, FileCont, Out, Defs, Err2, War2, L+Nl, IncFile, IncDir),
+ {Out3, Defs3, Err3, War3, Mio2} =
+ run_include(FileName, FileCont, Out, Defs, Err2, War2, L+Nl, IncFile, IncDir, Mio),
Nls = [],
Out4 = Out3++Nls++Out,
- expand(Rem2, Out4, SelfRef, Defs3, IncFile, IncDir, check_all, Err3, War3, L+Nl, FN);
+ expand(Rem2, Out4, SelfRef, Defs3, IncFile, IncDir, Mio2, check_all, Err3, War3, L+Nl, FN);
{{include, error}, Rem2, Nl, Err2, War2} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err2, War2, L+Nl, FN);
+
+ {{include, skip}, Rem2} ->
+ Out2 = [$\n|Out],
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err, War, L+1, FN);
{{ifdef, true}, Rem2, Err2, War2, Nl} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
IfCou2 = {endif, 1, L},
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, IfCou2, Err2, War2, L+Nl, FN);
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN);
{{ifdef, false}, Rem2, Err2, War2, Nl} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ Mio2 = update_mio(ifdef, Mio),
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err2, War2, L+Nl, FN);
{{ifndef, true}, Rem2, Err2, War2, Nl} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
IfCou2 = {endif, 1, L},
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, IfCou2, Err2, War2, L+Nl, FN);
- {{ifndef, false}, Rem2, Err2, War2, Nl} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN);
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN);
+ {{ifndef, false}, Macro, Rem2, Err2, War2, Nl} ->
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ Mio2 = update_mio({ifndef, Macro}, Mio),
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err2, War2, L+Nl, FN);
{endif, Rem2, Err2, War2, Nl} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ Mio2 = update_mio(endif, Mio),
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err2, War2, L+Nl, FN);
{{'if', true}, Rem2, Err2, War2, Nl} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
IfCou2 = {endif, 1, L},
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, IfCou2, Err2, War2, L+Nl, FN);
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN);
%% {{'if', false}, Removed, Rem2, Nl} -> Not implemented at present
{{'if', error}, Rem2, Err2, War2, Nl} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err2, War2, L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ Mio2 = update_mio('if', Mio),
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err2, War2, L+Nl, FN);
{'else', {_Removed, Rem2, Nl}} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
Err2 = {FN, L, "`else' command is not implemented at present"},
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, [Err2|Err], War, L+Nl, FN);
+ Mio2 = update_mio('else', Mio),
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, [Err2|Err], War, L+Nl, FN);
{'elif', {_Removed, Rem2, Nl}} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
Err2 = {FN, L, "`elif' command is not implemented at present"},
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, [Err2|Err], War, L+Nl, FN);
+ Mio2 = update_mio('elif', Mio),
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, [Err2|Err], War, L+Nl, FN);
{warning, {WarningText, Rem2, Nl}} ->
[FileName|_More] = IncFile,
War2 = {FileName, L, "warning: #warning "++detokenise(WarningText)},
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, [War2|War], L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err, [War2|War], L+Nl, FN);
{error, {ErrorText, Rem2, Nl}} ->
[FileName|_More] = IncFile,
Err2 = {FileName, L, detokenise(ErrorText)},
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, [Err2|Err], War, L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, [Err2|Err], War, L+Nl, FN);
{{line, ok}, {_Removed, Rem2, Nl}, L2, FN2, LineText} ->
Out2 = lists:duplicate(Nl,$\n)++LineText++Out,
[_X|IF] = IncFile,
IncFile2 = [FN2|IF],
- expand(Rem2, Out2, SelfRef, Defs, IncFile2, IncDir, check_all, Err, War, L2, FN2);
+ expand(Rem2, Out2, SelfRef, Defs, IncFile2, IncDir, update_mio(Mio), check_all, Err, War, L2, FN2);
{{line, error}, {_Removed, Rem2, Nl}, Err2} ->
- Out2 = [lists:duplicate(Nl,$\n)|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, [Err2|Err], War, L+Nl, FN);
+ Out2 = lists:duplicate(Nl,$\n) ++ Out,
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, [Err2|Err], War, L+Nl, FN);
hash_mark ->
- expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L, FN);
+ expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, Mio, check_all, Err, War, L, FN);
{pragma, Rem2, Nl, Text} ->
Out2 = lists:duplicate(Nl,$\n)++Text++Out,
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L+Nl, FN);
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err, War, L+Nl, FN);
{ident, Rem2, Nl, Text} ->
Out2 = lists:duplicate(Nl,$\n)++Text++Out,
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L+Nl, FN);
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err, War, L+Nl, FN);
{not_recognised, {Removed, Rem2, Nl}} ->
Text = lists:reverse([$#|Command]),
RemovedS = lists:reverse([?space|detokenise(Removed)]),
Out2 = [$\n|RemovedS]++Text++Out,
+ Mio2 = update_mio(Mio),
case Command of
[X|_T] when ?is_upper(X) ->
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L+Nl, FN);
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err, War, L+Nl, FN);
[X|_T] when ?is_lower(X) ->
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L+Nl, FN);
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err, War, L+Nl, FN);
[X|_T] when ?is_underline(X) ->
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, Err, War, L+Nl, FN);
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err, War, L+Nl, FN);
_ ->
Err2 = {FN, L, "invalid preprocessing directive name"},
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, check_all, [Err2|Err], War, L+Nl, FN)
+ expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, [Err2|Err], War, L+Nl, FN)
end;
Else ->
@@ -859,19 +861,19 @@ expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, check_all
end;
-expand([{var, "__LINE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
+expand([{var, "__LINE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
LL = io_lib:format("~p",[L]),
- expand(Rem, [LL | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+ expand(Rem, [LL | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{var, "__FILE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
- expand(Rem, [$",FN,$" | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+expand([{var, "__FILE__"}|Rem], Out, SelfRef, Defs, IncFile, Mio, IncDir, IfCou, Err, War, L, FN) ->
+ expand(Rem, [$",FN,$" | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{var, "__DATE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
+expand([{var, "__DATE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
{{Y,M,D},{_H,_Mi,_S}} = calendar:universal_time(),
Date = io_lib:format("\"~s ~p ~p\"",[month(M),D,Y]),
- expand(Rem, [Date | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+ expand(Rem, [Date | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{var, "__TIME__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
+expand([{var, "__TIME__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
{{_Y,_M,_D},{H,Mi,S}} = calendar:universal_time(),
HS = if H < 10 -> "0"++integer_to_list(H);
true -> integer_to_list(H)
@@ -883,40 +885,40 @@ expand([{var, "__TIME__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err,
true -> integer_to_list(S)
end,
Time = io_lib:format("\"~s:~s:~s\"",[HS,MiS,SS]),
- expand(Rem, [Time | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+ expand(Rem, [Time | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{var, "__INCLUDE_LEVEL__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
+expand([{var, "__INCLUDE_LEVEL__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
IL = io_lib:format("~p",[length(IncFile)-1]),
- expand(Rem, [IL | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+ expand(Rem, [IL | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{var, "__BASE_FILE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
+expand([{var, "__BASE_FILE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
[BF|_T] = lists:reverse(IncFile),
- expand(Rem, [$",BF,$" | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+ expand(Rem, [$",BF,$" | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{var, Var} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
+expand([{var, Var} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
{Out2, Err2, War2, Rem2, SelfRef2} =
source_line(Var, Rem, SelfRef, Defs, Err, War, L, FN),
- expand(Rem2, [Out2 | Out], SelfRef2, Defs, IncFile, IncDir, IfCou, Err2, War2, L, FN);
+ expand(Rem2, [Out2 | Out], SelfRef2, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err2, War2, L, FN);
-expand([{char, Char} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
- expand(Rem, [Char | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+expand([{char, Char} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
+ expand(Rem, [Char | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{number, Number} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
- expand(Rem, [Number | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+expand([{number, Number} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
+ expand(Rem, [Number | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{expanded, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
- expand(Rem, [Str | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+expand([{expanded, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
+ expand(Rem, [Str | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{self_ref, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
+expand([{self_ref, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
SelfRef2 = lists:delete(Str,SelfRef),
- expand(Rem, Out, SelfRef2, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+ expand(Rem, Out, SelfRef2, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{string, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
- expand(Rem, [$", Str, $" | Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN);
+expand([{string, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
+ expand(Rem, [$", Str, $" | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-expand([{string_part, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L, FN) ->
+expand([{string_part, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
{Str2, Rem2, Nl} = expand_string_part([$"|Str], Rem),
- expand(Rem2, [Str2| Out], SelfRef, Defs, IncFile, IncDir, IfCou, Err, War, L+Nl, FN).
+ expand(Rem2, [Str2| Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L+Nl, FN).
@@ -954,13 +956,14 @@ expand_string_part([{string_part, Str_part} | Rem], Str, Nl) ->
get_cmd_line_defs(Flags) ->
Adjusted = parse_cmd_line(Flags,[]),
- {_Out, _Err, _War, Defs, _IfCou} =
+ {_Out, _Err, _War, Defs, _IfCou, _Mio} =
expand(tokenise(Adjusted,""),
[],
[],
[],
[],
[],
+ #mio{},
check_all,
[],
[],
@@ -1030,10 +1033,10 @@ collect_undefine([C|Rest],Found) ->
%%======================================================================================
%%======================================================================================
-pp_command(Command, [space|File], Defs, IncDir, Err, War, L, FN) ->
- pp_command(Command, File, Defs, IncDir, Err, War, L, FN);
+pp_command(Command, [space|File], Defs, IncDir, Mio, Err, War, L, FN) ->
+ pp_command(Command, File, Defs, IncDir, Mio, Err, War, L, FN);
-pp_command(Command, File, Defs, IncDir, Err, War, L, FN) ->
+pp_command(Command, File, Defs, IncDir, Mio, Err, War, L, FN) ->
case Command of
%%----------------------------------------
@@ -1081,14 +1084,16 @@ pp_command(Command, File, Defs, IncDir, Err, War, L, FN) ->
%% #include
%%----------------------------------------
"include" ->
- case include(File, IncDir) of
- {error, Rem, Nl, Err2} ->
- {{include, error}, Rem, Nl, [{FN, L, Err2}|Err], War};
- {error, Rem, Nl, Err2, NameNl} ->
- {{include, error}, Rem, Nl, [{FN, L+ NameNl, Err2}|Err], War};
- {ok, FileName, FileCont, Rem, Nl} ->
- {{include, ok}, FileName, FileCont, Rem, Nl, Err, War}
- end;
+ case include(File, IncDir, Mio) of
+ {error, Rem, Nl, Err2} ->
+ {{include, error}, Rem, Nl, [{FN, L, Err2}|Err], War};
+ {error, Rem, Nl, Err2, NameNl} ->
+ {{include, error}, Rem, Nl, [{FN, L+ NameNl, Err2}|Err], War};
+ {ok, FileNamePath, FileCont, Rem, Nl} ->
+ {{include, ok}, FileNamePath, FileCont, Rem, Nl, Err, War};
+ {skip, Rem} ->
+ {{include, skip}, Rem}
+ end;
%%----------------------------------------
%% #ifdef
@@ -1127,14 +1132,14 @@ pp_command(Command, File, Defs, IncDir, Err, War, L, FN) ->
yes ->
{{ifndef, true}, Rem, Err2, War2, Nl};
no ->
- {{ifndef, false}, Rem, Err2, War2, Nl}
+ {{ifndef, false}, Name, Rem, Err2, War2, Nl}
end;
{ok, Rem, Name, No_of_para, _Parameters, _Macro, Err2, War2, Nl} ->
case is_defined_before(Name, No_of_para, Defs) of
yes ->
{{ifndef, true}, Rem, Err2, War2, Nl};
no ->
- {{ifndef, false}, Rem, Err2, War2, Nl}
+ {{ifndef, false}, Name, Rem, Err2, War2, Nl}
end
end;
@@ -1408,29 +1413,32 @@ undef(_Rem) ->
%%===============================================================
%%===============================================================
-include(File, IncDir) ->
+include(File, IncDir, Mio) ->
case include2(File) of
- {ok, FileName, Rem, Nl, FileType} ->
- %% The error handling is lite strange just to make it compatible to gcc
- case {read_inc_file(FileName, IncDir), Nl, FileType} of
- {{ok, FileList, FileNamePath}, _, _} ->
- {ok, FileNamePath, FileList, Rem, Nl};
- {{error, Text}, _, own_file} ->
- NameNl = count_nl(FileName,0),
- Error = lists:flatten(io_lib:format("~s: ~s",[FileName,Text])),
- {error, Rem, Nl, Error, NameNl};
- {{error, Text}, 1, sys_file} ->
- NameNl = count_nl(FileName,0),
- Error = lists:flatten(io_lib:format("~s: ~s",[FileName,Text])),
- {error, Rem, Nl, Error, NameNl};
- {{error, _Text}, _, sys_file} ->
- {error, Rem, Nl, "`#include' expects \"FILENAME\" or <FILENAME>"}
- end;
-
- {error, {_Removed, Rem, Nl}} ->
- {error, Rem, Nl, "`#include' expects \"FILENAME\" or <FILENAME>"}
+ {ok, FileName, Rem, Nl, FileType} ->
+ Result = read_inc_file(FileName, IncDir, Mio),
+ case {Result, Nl, FileType} of
+ {{ok, FileNamePath, FileCont}, _, _} ->
+ {ok, FileNamePath, FileCont, Rem, Nl};
+ {skip, _, _} ->
+ {skip, Rem};
+ {{error, Text}, _, own_file} ->
+ NameNl = count_nl(FileName,0),
+ Error = lists:flatten(io_lib:format("~s: ~s",[FileName,Text])),
+ {error, Rem, Nl, Error, NameNl};
+ {{error, Text}, 1, sys_file} ->
+ NameNl = count_nl(FileName,0),
+ Error = lists:flatten(io_lib:format("~s: ~s",[FileName,Text])),
+ {error, Rem, Nl, Error, NameNl};
+ {{error, _Text}, _, sys_file} ->
+ {error, Rem, Nl, "`#include' expects \"FILENAME\" or <FILENAME>"}
+ end;
+ {error, {_Removed, Rem, Nl}} ->
+ {error, Rem, Nl, "`#include' expects \#FILENAME\" or <FILENAME>"}
end.
+
+
count_nl([],Nl) ->
Nl;
count_nl([$\n|T],Nl) ->
@@ -1909,18 +1917,37 @@ include_dir(Flags,IncDir) ->
%% Read a included file. Try current dir first then the IncDir list
%%===============================================================
-read_inc_file(FileName, IncDir) ->
- case catch file:read_file(FileName) of
- {ok, Bin} ->
- FileList = binary_to_list(Bin),
- {ok, FileList, FileName};
+read_inc_file(FileName, IncDir, Mio) ->
+ case find_inc_file(FileName, IncDir) of
+ {ok, AbsFile} ->
+ %% is included before?
+ case lists:member(FileName, Mio#mio.included) of
+ false ->
+ case catch file:read_file(AbsFile) of
+ {ok, Bin} ->
+ FileList = binary_to_list(Bin),
+ {ok, AbsFile, FileList};
+ {error, Text} ->
+ {error, Text}
+ end;
+ true ->
+ skip
+ end;
+ {error, Text} ->
+ {error, Text}
+ end.
+
+find_inc_file(FileName, IncDir) ->
+ case catch file:read_file_info(FileName) of
+ {ok, _} ->
+ {ok, FileName};
{error, _} ->
- read_inc_file2(FileName, IncDir)
+ find_inc_file2(FileName, IncDir)
end.
-read_inc_file2(_FileName, []) ->
+find_inc_file2(_FileName, []) ->
{error, "No such file or directory"};
-read_inc_file2(FileName, [D|Rem]) ->
+find_inc_file2(FileName, [D|Rem]) ->
Dir = case lists:last(D) of
$/ ->
D;
@@ -1928,17 +1955,14 @@ read_inc_file2(FileName, [D|Rem]) ->
D++"/"
end,
- case catch file:read_file(Dir++FileName) of
- {ok, Bin} ->
- FileList = binary_to_list(Bin),
- {ok, FileList, Dir++FileName};
+ case catch file:read_file_info(Dir++FileName) of
+ {ok, _} ->
+ {ok, Dir++FileName};
{error, _} ->
- read_inc_file2(FileName, Rem)
+ find_inc_file2(FileName, Rem)
end.
-
-
%%===============================================================
%% Read parameters of a macro or a variable in a source line
%%===============================================================
@@ -2135,5 +2159,73 @@ month(11) -> "Nov";
month(12) -> "Dec".
+%% Multiple Include Optimization
+%%
+%% Algorithm described at:
+%% http://gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html
+update_mio({include, FileName}, #mio{included=Inc}=Mio) ->
+ Mio#mio{valid=false, included=[FileName|Inc]};
+
+%% valid=false & cmacro=undefined indicates it is already decided this file is
+%% not subject to MIO
+update_mio(_, #mio{valid=false, depth=0, cmacro=undefined}=Mio) ->
+ Mio;
+
+%% if valid=true, there is no non-whitespace tokens before this ifndef
+update_mio({'ifndef', Macro}, #mio{valid=true, depth=0, cmacro=undefined}=Mio) ->
+ Mio#mio{valid=false, cmacro=Macro, depth=1};
+
+%% detect any tokens before top level #ifndef
+update_mio(_, #mio{valid=true, depth=0, cmacro=undefined}=Mio) ->
+ Mio#mio{valid=false};
+
+%% If cmacro is alreay set, this is after the top level #endif
+update_mio({'ifndef', _}, #mio{valid=true, depth=0}=Mio) ->
+ Mio#mio{valid=false, cmacro=undefined};
+
+%% non-top level conditional, just update depth
+update_mio({'ifndef', _}, #mio{depth=D}=Mio) when D > 0 ->
+ Mio#mio{depth=D+1};
+update_mio('ifdef', #mio{depth=D}=Mio) ->
+ Mio#mio{depth=D+1};
+update_mio('if', #mio{depth=D}=Mio) ->
+ Mio#mio{depth=D+1};
+
+%% top level #else #elif invalidates multiple include optimization
+update_mio('else', #mio{depth=1}=Mio) ->
+ Mio#mio{valid=false, cmacro=undefined};
+update_mio('else', Mio) ->
+ Mio;
+update_mio('elif', #mio{depth=1}=Mio) ->
+ Mio#mio{valid=false, cmacro=undefined};
+update_mio('elif', Mio) ->
+ Mio;
+
+%% AT exit to top level, if the controlling macro is not set, this could be the
+%% end of a non-ifndef conditional block, or there were tokens before entering
+%% the #ifndef block. In either way, this invalidates the MIO
+%%
+%% It doesn't matter if `valid` is true at the time of exiting, it is set to
+%% true. This will be used to detect if more tokens are following the top
+%% level #endif.
+update_mio('endif', #mio{depth=1, cmacro=undefined}=Mio) ->
+ Mio#mio{valid=false, depth=0};
+update_mio('endif', #mio{depth=1}=Mio) ->
+ Mio#mio{valid=true, depth=0};
+update_mio('endif', #mio{depth=D}=Mio) when D > 1 ->
+ Mio#mio{valid=true, depth=D-1};
+
+%%if more tokens are following the top level #endif.
+update_mio('endif', #mio{depth=1, cmacro=undefined}=Mio) ->
+ Mio#mio{valid=false, depth=0};
+update_mio('endif', #mio{depth=D}=Mio) when D > 0 ->
+ Mio#mio{valid=true, depth=D-1};
+update_mio(_, Mio) ->
+ Mio#mio{valid=false}.
+
+%% clear `valid`, this doesn't matter since #endif will restore it if
+%% appropriate
+update_mio(Mio) ->
+ Mio#mio{valid=false}.
diff --git a/lib/ic/src/ic_pragma.erl b/lib/ic/src/ic_pragma.erl
index 45cb64c9c8..7f2216b9dc 100644
--- a/lib/ic/src/ic_pragma.erl
+++ b/lib/ic/src/ic_pragma.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1600,9 +1600,8 @@ remove_inheriters(S,RS,InheriterList) ->
[_OneOnly] ->
ReducedInhList;
_Other ->
- EtsList = ets:tab2list(S),
CleanList =
- [X || X <- EtsList, element(1,X) == inherits],
+ ets:match(S, {inherits,'_','_'}),
% CodeOptList =
% [X || X <- EtsList, element(1,X) == codeopt],
NoInheriters =remove_inheriters2(S,ReducedInhList,CleanList),
@@ -1648,9 +1647,8 @@ remove_inh([X],[Y],List,EtsList) ->
%%% from others in the list
%%%----------------------------------------------
remove_inherited(S,InheriterList) ->
- EtsList = ets:tab2list(S),
CleanList =
- [X || X <- EtsList, element(1,X) == inherits],
+ ets:match(S, {inherits, '_', '_'}),
remove_inherited(S,InheriterList,CleanList).
@@ -1694,11 +1692,8 @@ remove_inhed([X],[Y],List,EtsList) ->
%% are inherited from scope in the list
%%%----------------------------------------------
get_inherited(S,Scope,OpScopeList) ->
- EtsList = ets:tab2list(S),
- [[element(3,X)] || X <- EtsList,
- element(1,X) == inherits,
- element(2,X) == Scope,
- member([element(3,X)],OpScopeList)].
+ EtsList1 = ets:match(S, {inherits, Scope, '$1'}),
+ [X || X <- EtsList1, member(X, OpScopeList)].
@@ -1771,9 +1766,7 @@ inherits2(_X,Y,Z,EtsList) ->
%% false otherwise
%%
is_inherited_by(Interface1,Interface2,PragmaTab) ->
- FullList = ets:tab2list(PragmaTab),
- InheritsList =
- [X || X <- FullList, element(1,X) == inherits],
+ InheritsList = ets:match(PragmaTab, {inherits, '_', '_'}),
inherits(Interface2,Interface1,InheritsList).
diff --git a/lib/ic/vsn.mk b/lib/ic/vsn.mk
index 6d6c7fa625..6561ccd2a7 100644
--- a/lib/ic/vsn.mk
+++ b/lib/ic/vsn.mk
@@ -1 +1 @@
-IC_VSN = 4.2.26
+IC_VSN = 4.2.27
diff --git a/lib/inets/Makefile b/lib/inets/Makefile
index ec05efa461..4765a2ca3c 100644
--- a/lib/inets/Makefile
+++ b/lib/inets/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2010. All Rights Reserved.
+# Copyright Ericsson AB 1996-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -36,6 +36,8 @@ SPECIAL_TARGETS =
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_subdir.mk
+.PHONY: info gclean
+
info:
@echo "OS: $(OS)"
@echo "DOCB: $(DOCB)"
@@ -44,3 +46,5 @@ info:
@echo "APP_VSN: $(APP_VSN)"
@echo ""
+gclean:
+ git clean -fXd
diff --git a/lib/inets/doc/src/http_server.xml b/lib/inets/doc/src/http_server.xml
index 47ed9cd229..f29b505bc7 100644
--- a/lib/inets/doc/src/http_server.xml
+++ b/lib/inets/doc/src/http_server.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -63,9 +63,9 @@
technologies such as SOAP.</p>
<p>Allmost all server functionality has been implemented using an
- especially crafted server API, it is described in the Erlang Web
- Server API. This API can be used to advantage by all who wants
- to enhance the server core functionality, for example custom
+ especially crafted server API which is described in the Erlang Web
+ Server API. This API can be used to advantage by all who wish
+ to enhance the core server functionality, for example with custom
logging and authentication.</p>
<marker id="config"></marker>
@@ -406,7 +406,7 @@ http://your.server.org/***/Module[:/]Function(?QueryString|/PathInfo)
phase instead of first generating the whole web page and
then sending it to the client. The option to implement a
function with arity two is only kept for
- backwardcompatibilty reasons.
+ backwards compatibility reasons.
See <seealso marker="mod_esi">mod_esi(3)</seealso> for
implementation details of the esi callback function.</p>
</section>
@@ -472,7 +472,7 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[
<tag><em>bytes</em></tag>
<item>The content-length of the document transferred. </item>
</taglist>
- <p>Internal server errors are recorde in the error log file. The
+ <p>Internal server errors are recorded in the error log file. The
format of this file is a more ad hoc format than the logs using
Common Logfile Format, but conforms to the following syntax:
</p>
diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml
index 8f68087871..b1f964ae69 100644
--- a/lib/inets/doc/src/httpc.xml
+++ b/lib/inets/doc/src/httpc.xml
@@ -28,8 +28,10 @@
<date></date>
<rev></rev>
</header>
+
<module>httpc</module>
<modulesummary>An HTTP/1.1 client </modulesummary>
+
<description>
<p>This module provides the API to a HTTP/1.1 compatible client according
to RFC 2616, caching is currently not supported.</p>
@@ -76,38 +78,37 @@ socket_opt() = See the Options used by gen_tcp(3) and
<p>For more information about HTTP see rfc 2616</p>
<code type="none"><![CDATA[
-method() = head | get | put | post | trace | options | delete
-request() = {url(), headers()} |
- {url(), headers(), content_type(), body()}
-url() = string() - Syntax according to the URI definition in rfc 2396, ex: "http://www.erlang.org"
-status_line() = {http_version(), status_code(), reason_phrase()}
-http_version() = string() ex: "HTTP/1.1"
-status_code() = integer()
-reason_phrase() = string()
-content_type() = string()
-headers() = [header()]
-header() = {field(), value()}
-field() = string()
-value() = string()
-body() = string() | binary()
-filename() = string()
+method() = head | get | put | post | trace | options | delete
+request() = {url(), headers()} |
+ {url(), headers(), content_type(), body()}
+url() = string() - Syntax according to the URI definition in rfc 2396, ex: "http://www.erlang.org"
+status_line() = {http_version(), status_code(), reason_phrase()}
+http_version() = string() ex: "HTTP/1.1"
+status_code() = integer()
+reason_phrase() = string()
+content_type() = string()
+headers() = [header()]
+header() = {field(), value()}
+field() = string()
+value() = string()
+body() = string() |
+ binary() |
+ {fun(accumulator()) -> body_processing_result(),
+ accumulator()} |
+ {chunkify,
+ fun(accumulator()) -> body_processing_result(),
+ accumulator()}
+body_processing_result() = eof | {ok, iolist(), accumulator()}
+accumulator() = term()
+filename() = string()
]]></code>
</section>
<section>
<title>SSL DATA TYPES </title>
- <p>Some type definitions relevant when using https,
- for details <seealso marker="ssl:ssl">ssl(3)</seealso>: </p>
- <code type="none"><![CDATA[
-ssl_options() = {verify, code()} |
- {depth, depth()} |
- {certfile, path()} |
- {keyfile, path()} |
- {password, string()} |
- {cacertfile, path()} |
- {ciphers, string()}
- ]]></code>
+ <p>See <seealso marker="ssl:ssl">ssl(3)</seealso> for information
+ about ssl options (<c>ssloptions()</c>). </p>
</section>
<section>
@@ -142,9 +143,10 @@ ssl_options() = {verify, code()} |
<fsummary>Sends a get HTTP-request</fsummary>
<type>
<v>Url = url() </v>
- <v>Result = {status_line(), headers(), body()} |
- {status_code(), body()} | request_id() </v>
- <v>Profile = profile()</v>
+ <v>Result = {status_line(), headers(), Body} |
+ {status_code(), Body} | request_id() </v>
+ <v>Body = string() | binary()</v>
+ <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v>
<v>Reason = term() </v>
</type>
<desc>
@@ -166,9 +168,8 @@ ssl_options() = {verify, code()} |
<v>http_options() = [http_option()]</v>
<v>http_option() = {timeout, timeout()} |
{connect_timeout, timeout()} |
- {ssl, ssl_options()} |
- {ossl, ssl_options()} |
- {essl, ssl_options()} |
+ {ssl, ssloptions()} |
+ {essl, ssloptions()} |
{autoredirect, boolean()} |
{proxy_auth, {userstring(), passwordstring()}} |
{version, http_version()} |
@@ -191,26 +192,28 @@ ssl_options() = {verify, code()} |
<v>Function = atom() </v>
<v>Args = list() </v>
<v>body_format() = string | binary </v>
- <v>Result = {status_line(), headers(), body()} |
- {status_code(), body()} | request_id() </v>
- <v>Profile = profile() </v>
+ <v>Result = {status_line(), headers(), Body} |
+ {status_code(), Body} | request_id() </v>
+ <v>Body = string() | binary()</v>
+ <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v>
<v>Reason = {connect_failed, term()} |
{send_failed, term()} | term() </v>
</type>
<desc>
<p>Sends a HTTP-request. The function can be both synchronous
- and asynchronous. In the later case the function will return
- <c>{ok, RequestId}</c> and later on the information will be delivered
- to the <c>receiver</c> depending on that value. </p>
+ and asynchronous. In the later case the function will return
+ <c>{ok, RequestId}</c> and later on the information will be delivered
+ to the <c>receiver</c> depending on that value. </p>
<p>Http option (<c>http_option()</c>) details: </p>
+ <marker id="request2_http_options"></marker>
<taglist>
<tag><c><![CDATA[timeout]]></c></tag>
<item>
<p>Timeout time for the request. </p>
<p>The clock starts ticking as soon as the request has been
- sent. </p>
+ sent. </p>
<p>Time is in milliseconds. </p>
<p>Defaults to <c>infinity</c>. </p>
</item>
@@ -218,7 +221,7 @@ ssl_options() = {verify, code()} |
<tag><c><![CDATA[connect_timeout]]></c></tag>
<item>
<p>Connection timeout time, used during the initial request,
- when the client is <em>connecting</em> to the server. </p>
+ when the client is <em>connecting</em> to the server. </p>
<p>Time is in milliseconds. </p>
<p>Defaults to the value of the <c>timeout</c> option. </p>
</item>
@@ -226,60 +229,54 @@ ssl_options() = {verify, code()} |
<tag><c><![CDATA[ssl]]></c></tag>
<item>
<p>This is the default ssl config option, currently defaults to
- <c>ossl</c>, see below. </p>
- <p>Defaults to <c>[]</c>. </p>
- </item>
-
- <tag><c><![CDATA[ossl]]></c></tag>
- <item>
- <p>If using the OpenSSL based (old) implementation of SSL,
- these SSL-specific options are used. </p>
+ <c>essl</c>, see below. </p>
<p>Defaults to <c>[]</c>. </p>
</item>
<tag><c><![CDATA[essl]]></c></tag>
<item>
- <p>If using the Erlang based (new) implementation of SSL,
- these SSL-specific options are used. </p>
+ <p>If using the Erlang based implementation of SSL,
+ these SSL-specific options are used. </p>
<p>Defaults to <c>[]</c>. </p>
</item>
<tag><c><![CDATA[autoredirect]]></c></tag>
<item>
- <p>Should the client automatically retrieve the information
- from the new URI and return that as the result instead
- of a 30X-result code. </p>
- <p>Note that for some 30X-result codes automatic redirect
- is not allowed. In these cases the 30X-result will always
- be returned. </p>
- <p>Defaults to <c>true</c>. </p>
+ <p>Should the client automatically retrieve the information
+ from the new URI and return that as the result instead
+ of a 30X-result code. </p>
+ <p>Note that for some 30X-result codes automatic redirect
+ is not allowed. In these cases the 30X-result will always
+ be returned. </p>
+ <p>Defaults to <c>true</c>. </p>
</item>
<tag><c><![CDATA[proxy_auth]]></c></tag>
<item>
<p>A proxy-authorization header using the provided user name and
- password will be added to the request. </p>
+ password will be added to the request. </p>
</item>
<tag><c><![CDATA[version]]></c></tag>
<item>
<p>Can be used to make the client act as an <c>HTTP/1.0</c> or
- <c>HTTP/0.9</c> client. By default this is an <c>HTTP/1.1</c>
- client. When using <c>HTTP/1.0</c> persistent connections will
- not be used. </p>
- <p>Defaults to the string <c>"HTTP/1.1"</c>. </p>
+ <c>HTTP/0.9</c> client. By default this is an <c>HTTP/1.1</c>
+ client. When using <c>HTTP/1.0</c> persistent connections will
+ not be used. </p>
+ <p>Defaults to the string <c>"HTTP/1.1"</c>. </p>
</item>
<tag><c><![CDATA[relaxed]]></c></tag>
<item>
- <p>If set to <c>true</c> workarounds for known server deviations from
- the HTTP-standard are enabled. </p>
+ <p>If set to <c>true</c> workarounds for known server deviations
+ from the HTTP-standard are enabled. </p>
<p>Defaults to <c>false</c>. </p>
</item>
<tag><c><![CDATA[url_encode]]></c></tag>
<item>
- <p>Will apply Percent-encoding, also known as URL encoding on the URL.</p>
+ <p>Will apply Percent-encoding, also known as URL encoding on the
+ URL.</p>
<p>Defaults to <c>false</c>. </p>
</item>
</taglist>
@@ -295,77 +292,77 @@ ssl_options() = {verify, code()} |
<tag><c><![CDATA[stream]]></c></tag>
<item>
<p>Streams the body of a 200 or 206 response to the calling
- process or to a file. When streaming to the calling process
- using the option <c>self</c> the following stream messages
- will be sent to that process: <c>{http, {RequestId,
- stream_start, Headers}, {http, {RequestId, stream,
- BinBodyPart}, {http, {RequestId, stream_end, Headers}</c>. When
- streaming to to the calling processes using the option
- <c>{self, once}</c> the first message will have an additional
- element e.i. <c>{http, {RequestId, stream_start, Headers, Pid}</c>,
- this is the process id that should be used as an argument to
- <c>http:stream_next/1</c> to trigger the next message to be sent to
- the calling process. </p>
+ process or to a file. When streaming to the calling process
+ using the option <c>self</c> the following stream messages
+ will be sent to that process: <c>{http, {RequestId,
+ stream_start, Headers}, {http, {RequestId, stream,
+ BinBodyPart}, {http, {RequestId, stream_end, Headers}</c>. When
+ streaming to to the calling processes using the option
+ <c>{self, once}</c> the first message will have an additional
+ element e.i. <c>{http, {RequestId, stream_start, Headers, Pid}</c>,
+ this is the process id that should be used as an argument to
+ <c>http:stream_next/1</c> to trigger the next message to be sent to
+ the calling process. </p>
<p>Note that it is possible that chunked encoding will add
- headers so that there are more headers in the <c>stream_end</c>
- message than in the <c>stream_start</c>.
- When streaming to a file and the request is asynchronous the
- message <c>{http, {RequestId, saved_to_file}}</c> will be sent. </p>
+ headers so that there are more headers in the <c>stream_end</c>
+ message than in the <c>stream_start</c>.
+ When streaming to a file and the request is asynchronous the
+ message <c>{http, {RequestId, saved_to_file}}</c> will be sent. </p>
<p>Defaults to <c>none</c>. </p>
</item>
<tag><c><![CDATA[body_format]]></c></tag>
<item>
<p>Defines if the body shall be delivered as a string or as a
- binary. This option is only valid for the synchronous
- request. </p>
+ binary. This option is only valid for the synchronous
+ request. </p>
<p>Defaults to <c>string</c>. </p>
</item>
<tag><c><![CDATA[full_result]]></c></tag>
<item>
<p>Should a "full result" be returned to the caller (that is,
- the body, the headers and the entire status-line) or not
- (the body and the status code). </p>
+ the body, the headers and the entire status-line) or not
+ (the body and the status code). </p>
<p>Defaults to <c>true</c>. </p>
</item>
<tag><c><![CDATA[header_as_is]]></c></tag>
<item>
<p>Shall the headers provided by the user be made
- lower case or be regarded as case sensitive. </p>
+ lower case or be regarded as case sensitive. </p>
<p>Note that the http standard requires them to be
- case insenstive. This feature should only be used if there is
- no other way to communicate with the server or for testing
- purpose. Also note that when this option is used no headers
- will be automatically added, all necessary headers have to be
- provided by the user. </p>
- <p>Defaults to <c>false</c>. </p>
+ case insenstive. This feature should only be used if there is
+ no other way to communicate with the server or for testing
+ purpose. Also note that when this option is used no headers
+ will be automatically added, all necessary headers have to be
+ provided by the user. </p>
+ <p>Defaults to <c>false</c>. </p>
</item>
<tag><c><![CDATA[socket_opts]]></c></tag>
<item>
<p>Socket options to be used for this and subsequent
- request(s). </p>
- <p>Overrides any value set by the
- <seealso marker="#set_options">set_options</seealso>
- function. </p>
+ request(s). </p>
+ <p>Overrides any value set by the
+ <seealso marker="#set_options">set_options</seealso>
+ function. </p>
<p>Note that the validity of the options are <em>not</em>
- checked in any way. </p>
+ checked in any way. </p>
<p>Note that this may change the socket behaviour
- (see <seealso marker="kernel:inet#setopts/2">inet:setopts/2</seealso>)
- for an already existing one, and therefore an already connected
- request handler. </p>
+ (see <seealso marker="kernel:inet#setopts/2">inet:setopts/2</seealso>)
+ for an already existing one, and therefore an already connected
+ request handler. </p>
<p>By default the socket options set by the
- <seealso marker="#set_options">set_options/1,2</seealso>
- function are used when establishing a connection. </p>
+ <seealso marker="#set_options">set_options/1,2</seealso>
+ function are used when establishing a connection. </p>
</item>
<tag><c><![CDATA[receiver]]></c></tag>
<item>
<p>Defines how the client will deliver the result of an
- asynchroneous request (<c>sync</c> has the value
- <c>false</c>). </p>
+ asynchroneous request (<c>sync</c> has the value
+ <c>false</c>). </p>
<taglist>
<tag><c><![CDATA[pid()]]></c></tag>
@@ -379,7 +376,7 @@ ssl_options() = {verify, code()} |
<tag><c><![CDATA[function/1]]></c></tag>
<item>
<p>Information will be delivered to the receiver via calls
- to the provided fun: </p>
+ to the provided fun: </p>
<pre>
Receiver(ReplyInfo)
</pre>
@@ -388,7 +385,7 @@ Receiver(ReplyInfo)
<tag><c><![CDATA[{Module, Funcion, Args}]]></c></tag>
<item>
<p>Information will be delivered to the receiver via calls
- to the callback function: </p>
+ to the callback function: </p>
<pre>
apply(Module, Function, [ReplyInfo | Args])
</pre>
@@ -409,7 +406,7 @@ apply(Module, Function, [ReplyInfo | Args])
</pre>
<p>Defaults to the <c>pid()</c> of the process calling the request
- function (<c>self()</c>). </p>
+ function (<c>self()</c>). </p>
</item>
</taglist>
@@ -424,7 +421,7 @@ apply(Module, Function, [ReplyInfo | Args])
<type>
<v>RequestId = request_id() - A unique identifier as returned
by request/4</v>
- <v>Profile = profile()</v>
+ <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v>
</type>
<desc>
<p>Cancels an asynchronous HTTP-request. </p>
@@ -513,11 +510,10 @@ apply(Module, Function, [ReplyInfo | Args])
This option is used to switch on (or off)
different levels of erlang trace on the client.
It is a debug feature.</d>
- <v>Profile = profile()</v>
+ <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v>
</type>
<desc>
- <p>Sets options to be used for subsequent
- requests.</p>
+ <p>Sets options to be used for subsequent requests.</p>
<note>
<p>If possible the client will keep its connections
alive and use persistent connections
@@ -547,7 +543,7 @@ apply(Module, Function, [ReplyInfo | Args])
</type>
<desc>
<p>Triggers the next message to be streamed, e.i.
- same behavior as active once for sockets.</p>
+ same behavior as active once for sockets. </p>
<marker id="verify_cookies"></marker>
<marker id="store_cookies"></marker>
@@ -561,14 +557,14 @@ apply(Module, Function, [ReplyInfo | Args])
<type>
<v>SetCookieHeaders = headers() - where field = "set-cookie"</v>
<v>Url = url()</v>
- <v>Profile = profile()</v>
+ <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v>
</type>
<desc>
<p>Saves the cookies defined in SetCookieHeaders
- in the client profile's cookie database. You need to
- call this function if you have set the option <c>cookies</c> to <c>verify</c>.
- If no profile is specified the default profile will be used.
- </p>
+ in the client profile's cookie database. You need to
+ call this function if you have set the option <c>cookies</c>
+ to <c>verify</c>.
+ If no profile is specified the default profile will be used. </p>
<marker id="cookie_header"></marker>
</desc>
@@ -581,13 +577,12 @@ apply(Module, Function, [ReplyInfo | Args])
making a request to Url using the profile <c>Profile</c>.</fsummary>
<type>
<v>Url = url()</v>
- <v>Profile = profile()</v>
+ <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v>
</type>
<desc>
<p>Returns the cookie header that would be sent
- when making a request to <c>Url</c> using the profile <c>Profile</c>.
- If no profile is specified the default profile will be used.
- </p>
+ when making a request to <c>Url</c> using the profile <c>Profile</c>.
+ If no profile is specified the default profile will be used. </p>
<marker id="reset_cookies"></marker>
</desc>
@@ -599,12 +594,12 @@ apply(Module, Function, [ReplyInfo | Args])
<name>reset_cookies(Profile) -> void()</name>
<fsummary>Reset the cookie database.</fsummary>
<type>
- <v>Profile = profile()</v>
+ <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v>
</type>
<desc>
- <p>Resets (clears) the cookie database for the specified <c>Profile</c>.
- If no profile is specified the default profile will be used.
- </p>
+ <p>Resets (clears) the cookie database for the specified
+ <c>Profile</c>. If no profile is specified the default profile
+ will be used. </p>
</desc>
</func>
@@ -614,17 +609,16 @@ apply(Module, Function, [ReplyInfo | Args])
<name>which_cookies(Profile) -> cookies()</name>
<fsummary>Dumps out the entire cookie database.</fsummary>
<type>
- <v>Profile = profile()</v>
- <v>cookies() = [cooie_stores()]</v>
- <v>cookie_stores() = {cookies, icookies()} | {session_cookies, icookies()}</v>
- <v>icookies() = [icookie()]</v>
+ <v>Profile = profile() | pid() (when started <c>stand_alone</c>)</v>
+ <v>cookies() = [cookie_stores()]</v>
+ <v>cookie_stores() = {cookies, cookies()} | {session_cookies, cookies()}</v>
+ <v>cookies() = [cookie()]</v>
<v>cookie() = term()</v>
</type>
<desc>
<p>This function produces a list of the entire cookie database.
- It is intended for debugging/testing purposes.
- If no profile is specified the default profile will be used.
- </p>
+ It is intended for debugging/testing purposes.
+ If no profile is specified the default profile will be used. </p>
</desc>
</func>
</funcs>
diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml
index 62f4e18f82..f88099a82e 100644
--- a/lib/inets/doc/src/httpd.xml
+++ b/lib/inets/doc/src/httpd.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2010</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -148,13 +148,11 @@
in the apache like configuration file.
</item>
- <tag>{socket_type, ip_comm | ssl | ossl | essl}</tag>
+ <tag>{socket_type, ip_comm | ssl | essl}</tag>
<item>
- <p>When using ssl, there are several alternatives.
- <c>ossl</c> specifically uses the OpenSSL based (old) SSL.
- <c>essl</c> specifically uses the Erlang based (new) SSL.
- When using <c>ssl</c> it <em>currently</em> defaults to
- <c>ossl</c>. </p>
+ <p>When using ssl, there are currently only one alternative.
+ <c>essl</c> specifically uses the Erlang based SSL.
+ <c>ssl</c> defaults to <c>essl</c>. </p>
<p>Defaults to <c>ip_comm</c>. </p>
</item>
@@ -162,7 +160,7 @@
<item>
<p>Defaults to <c>inet6fb4. </c> </p>
<p>Note that this option is only used when the option
- <c>socket_type</c> has the value <c>ip_comm</c>. </p>
+ <c>socket_type</c> has the value <c>ip_comm</c>. </p>
</item>
</taglist>
@@ -525,12 +523,13 @@ bytes
scheme scripts. A matching URL is mapped into a specific module
and function. For example:
- <code>{erl_script_alias, {"/cgi-bin/example" [httpd_example]}
+ <code>{erl_script_alias, {"/cgi-bin/example", [httpd_example]}
</code>
and a request to
http://your.server.org/cgi-bin/example/httpd_example:yahoo
- would refer to httpd_example:yahoo/2 and
+ would refer to httpd_example:yahoo/3 or, if that did not exist,
+ httpd_example:yahoo/2 and
http://your.server.org/cgi-bin/example/other:yahoo would
not be allowed to execute.
</item>
@@ -793,14 +792,14 @@ bytes
<marker id="sdir_prop"></marker>
<p> Here follows the valid properties for security directories</p>
<taglist>
- <tag>{security_data_file, path()}</tag>
+ <tag>{data_file, path()}</tag>
<item>
Name of the security data file. The filename can either
absolute or relative to the server_root. This file is used to
store persistent data for the mod_security module. </item>
- <tag>{security_max_retries, integer()}</tag>
+ <tag>{max_retries, integer()}</tag>
<item> Specifies the maximum number of tries to authenticate a
user has before the user is blocked out. If a user
@@ -810,13 +809,13 @@ bytes
server will return 401 (Unauthorized), for security
reasons. Defaults to 3 may also be set to infinity.</item>
- <tag>{security_block_time, integer()}</tag>
+ <tag>{block_time, integer()}</tag>
<item> Specifies the number of minutes a user is blocked. After
this amount of time, he automatically regains access.
Defaults to 60</item>
- <tag>{security_fail_expire_time, integer()}</tag>
+ <tag>{fail_expire_time, integer()}</tag>
<item>
Specifies the number of minutes a failed user authentication
@@ -824,7 +823,7 @@ bytes
time, his previous failed authentications are
forgotten. Defaults to 30</item>
- <tag>{security_auth_timeout, integer()}</tag>
+ <tag>{auth_timeout, integer()}</tag>
<item>
Specifies the number of seconds a successful user
diff --git a/lib/inets/doc/src/inets.xml b/lib/inets/doc/src/inets.xml
index c367d7fa77..079f60779d 100644
--- a/lib/inets/doc/src/inets.xml
+++ b/lib/inets/doc/src/inets.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
<header>
<copyright>
- <year>2007</year><year>2010</year>
+ <year>2007</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,8 +32,10 @@
<modulesummary>The inets services API</modulesummary>
<description>
<p>This module provides the most basic API to the
- clients and servers, that are part of the Inets application,
- such as start and stop. </p>
+ clients and servers, that are part of the Inets application,
+ such as start and stop. </p>
+
+ <marker id="common_data_types"></marker>
</description>
<section>
@@ -42,7 +44,10 @@
this module: </p>
<p><c> service() = ftpc | tftp | httpc | httpd</c></p>
<p><c> property() = atom() </c></p>
+ <marker id="functions"></marker>
+ <marker id="services"></marker>
</section>
+
<funcs>
<func>
<name>services() -> [{Service, Pid}]</name>
@@ -54,11 +59,13 @@
<desc>
<p>Returns a list of currently running services.</p>
<note>
- <p>Services started as <c>stand_alone</c> will not
- be listed.</p>
+ <p>Services started as <c>stand_alone</c> will not be listed.</p>
</note>
+
+ <marker id="services_info"></marker>
</desc>
</func>
+
<func>
<name>services_info() -> [{Service, Pid, Info}]</name>
<fsummary>Returns a list of currently running services where
@@ -73,11 +80,13 @@
</type>
<desc>
<p>Returns a list of currently running services where each
- service is described by a [{Option, Value}] list. The
- information given in the list is specific for each service
- and it is probable that each service will have its own info
- function that gives you even more details about the
- service.</p>
+ service is described by a [{Option, Value}] list. The
+ information given in the list is specific for each service
+ and it is probable that each service will have its own info
+ function that gives you even more details about the
+ service.</p>
+
+ <marker id="service_names"></marker>
</desc>
</func>
@@ -89,6 +98,8 @@
</type>
<desc>
<p>Returns a list of available service names.</p>
+
+ <marker id="start"></marker>
</desc>
</func>
@@ -101,18 +112,24 @@
</type>
<desc>
<p>Starts the Inets application. Default type
- is temporary. See also
- <seealso marker="kernel:application">application(3)</seealso></p>
+ is temporary. See also
+ <seealso marker="kernel:application">application(3)</seealso>. </p>
+
+ <marker id="stop"></marker>
</desc>
</func>
+
<func>
<name>stop() -> ok </name>
<fsummary>Stops the inets application.</fsummary>
<desc>
<p>Stops the inets application. See also
- <seealso marker="kernel:application">application(3)</seealso></p>
+ <seealso marker="kernel:application">application(3)</seealso>. </p>
+
+ <marker id="start2"></marker>
</desc>
</func>
+
<func>
<name>start(Service, ServiceConfig) -> {ok, Pid} | {error, Reason}</name>
<name>start(Service, ServiceConfig, How) -> {ok, Pid} | {error, Reason}</name>
@@ -144,8 +161,11 @@
some sense the calling process has now become the top
supervisor.</p>
</note>
+
+ <marker id="stop2"></marker>
</desc>
</func>
+
<func>
<name>stop(Service, Reference) -> ok | {error, Reason} </name>
<fsummary>Stops a started service of the inets application or takes
@@ -157,9 +177,11 @@
</type>
<desc>
<p>Stops a started service of the inets application or takes
- down a "stand_alone-service" gracefully. When the
- <c>stand_alone</c> option is used in start,
- only the pid is a valid argument to stop.</p>
+ down a "stand_alone-service" gracefully. When the
+ <c>stand_alone</c> option is used in start,
+ only the pid is a valid argument to stop.</p>
+
+ <marker id="see_also"></marker>
</desc>
</func>
</funcs>
diff --git a/lib/inets/doc/src/mod_auth.xml b/lib/inets/doc/src/mod_auth.xml
index 42c49e9c35..2134ebeeae 100644
--- a/lib/inets/doc/src/mod_auth.xml
+++ b/lib/inets/doc/src/mod_auth.xml
@@ -80,7 +80,7 @@
<marker id="delete_user"></marker>
<p><c>delete_user/2, delete_user/3</c> and <c>delete_user/4</c>
deletes a user
- from the user database. If the operation is succesfull, this
+ from the user database. If the operation is successful, this
function returns <c>true</c>. If an error occurs,
<c>{error,Reason}</c> is returned. When <c>delete_user/2</c> is
called the Port and Dir options are mandatory.</p>
diff --git a/lib/inets/doc/src/mod_esi.xml b/lib/inets/doc/src/mod_esi.xml
index 3c473d3f94..9906ae0895 100644
--- a/lib/inets/doc/src/mod_esi.xml
+++ b/lib/inets/doc/src/mod_esi.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
<header>
<copyright>
- <year>1997</year><year>2010</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,17 +31,20 @@
<module>mod_esi</module>
<modulesummary>Erlang Server Interface </modulesummary>
<description>
- <p>This module defines the API - Erlang Server Interface (ESI).
- Which is a more efficient way of writing erlang scripts
- for your Inets web server than writing them as common CGI scripts.</p>
+ <p>This module defines the Erlang Server Interface (ESI) API.
+ It is a more efficient way of writing erlang scripts
+ for your Inets web server than writing them as common CGI scripts.</p>
+
+ <marker id="deliver"></marker>
</description>
+
<funcs>
<func>
<name>deliver(SessionID, Data) -> ok | {error, Reason}</name>
<fsummary>Sends Data back to client.</fsummary>
<type>
<v>SessionID = term()</v>
- <v>Data = string() | io_list()</v>
+ <v>Data = string() | io_list() | binary()</v>
<v>Reason = term()</v>
</type>
<desc>
@@ -51,13 +54,15 @@
parts of the content to the user.</p>
<p>Sends data from a Erl Scheme script back to the client.</p>
- <note><p>Note
- that if any HTTP-header fields should be added by the
- script they must be in the first call to deliver/2 and the
- data in the call must be a string. Do not
- assume anything about the data type of SessionID, the
- SessionID must be the value given as input to the esi
- call back function that you implemented.</p></note>
+ <note>
+ <p>Note that if any HTTP-header fields should be added by the
+ script they must be in the first call to deliver/2 and the
+ data in the call must be a string. Calls after the headers
+ are complete may contain binary data to reduce copying
+ overhead. Do not assume anything about the data type of
+ SessionID, the SessionID must be the value given as input to
+ the esi call back function that you implemented.</p>
+ </note>
</desc>
</func>
</funcs>
@@ -78,24 +83,24 @@
</type>
<desc>
<p>The <c>Module</c> must be found in the code path and export
- <c>Function</c> with an arity of two. An erlScriptAlias must
+ <c>Function</c> with an arity of three. An erlScriptAlias must
also be set up in the configuration file for the Web server.</p>
- <p>If the HTTP request is a post request and a body is sent
+ <p>If the HTTP request is a 'post' request and a body is sent
then content_length will be the length of the posted
- data. If get is used query_string will be the data after
+ data. If 'get' is used query_string will be the data after
<em>?</em> in the url.</p>
<p>ParsedHeader is the HTTP request as a key value tuple
list. The keys in parsed header will be the in lower case.</p>
<p>SessionID is a identifier
- the server use when <c>deliver/2</c> is called, do not
- assume any-thing about the datatype.</p>
+ the server uses when <c>deliver/2</c> is called; do not
+ assume anything about the datatype.</p>
<p>Use this callback function to dynamically generate dynamic web
- content. when a part of the page is generated send the
+ content. When a part of the page is generated send the
data back to the client through <c>deliver/2</c>. Note
that the first chunk of data sent to the client must at
least contain all HTTP header fields that the response
- will generate. If the first chunk not contains
- <em>End of HTTP header</em> that is <c>"\r\n\r\n"</c>
+ will generate. If the first chunk does not contain the
+ <em>End of HTTP header</em>, that is <c>"\r\n\r\n",</c>
the server will
assume that no HTTP header fields will be generated.</p>
</desc>
@@ -106,14 +111,15 @@
<type>
<v>Env = [EnvironmentDirectives] ++ ParsedHeader</v>
<v>EnvironmentDirectives = {Key,Value}</v>
- <v>Key = query_string | content_length | server_software | gateway_interface | server_protocol | server_port | request_method | remote_addr | script_name. &lt;v>Input = string()</v>
+ <v>Key = query_string | content_length | server_software | gateway_interface | server_protocol | server_port | request_method | remote_addr | script_name.</v>
+ <v>Input = string()</v>
<v>Response = string()</v>
</type>
<desc>
- <p>This callback format consumes quite much memory since the
+ <p>This callback format consumes a lot of memory since the
whole response must be generated before it is sent to the
- user. This functions is deprecated and only keept for backwards
- compatibility.
+ user. This function is deprecated and only kept for backwards
+ compatibility.
For new development Module:Function/3 should be used.</p>
</desc>
</func>
diff --git a/lib/inets/doc/src/mod_security.xml b/lib/inets/doc/src/mod_security.xml
index 2a871d29d8..a3c91dca5b 100644
--- a/lib/inets/doc/src/mod_security.xml
+++ b/lib/inets/doc/src/mod_security.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
<header>
<copyright>
- <year>1998</year><year>2010</year>
+ <year>1998</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index 5da9d98002..87a8c173a5 100644
--- a/lib/inets/doc/src/notes.xml
+++ b/lib/inets/doc/src/notes.xml
@@ -32,6 +32,310 @@
<file>notes.xml</file>
</header>
+ <section><title>Inets 5.8</title>
+
+ <section><title>Improvements and New Features</title>
+ <p>-</p>
+
+<!--
+ <list>
+ <item>
+ <p>[httpc|httpd] Added support for IPv6 with ssl. </p>
+ <p>Own Id: OTP-5566</p>
+ </item>
+
+ </list>
+-->
+
+ </section>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <p>-</p>
+
+<!--
+ <list>
+ <item>
+ <p>[httpc] Remove unnecessary usage of iolist_to_binary when
+ processing body (for PUT and POST). </p>
+ <p>Filipe David Manana</p>
+ <p>Own Id: OTP-9317</p>
+ </item>
+
+ </list>
+-->
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+<!--
+ <p>-</p>
+-->
+
+ <list>
+ <item>
+ <p>[httpc] Deprecated interface module <c>http</c> has been removed.
+ It has (long) been replaced by http client interface module
+ <seealso marker="httpc#">httpc</seealso>. </p>
+ <p>Own Id: OTP-9359</p>
+ </item>
+
+ <item>
+ <p>[httpc|httpd] The old ssl implementation (based on OpenSSL),
+ has been deprecated. The config option that specified usage of
+ this version of the ssl app, <c>ossl</c>, has been removed. </p>
+ <p>Own Id: OTP-9522</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ </section> <!-- 5.8 -->
+
+
+ <section><title>Inets 5.7.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <p>-</p>
+
+<!--
+ <list>
+ <item>
+ <p>[httpc|httpd] Added support for IPv6 with ssl. </p>
+ <p>Own Id: OTP-5566</p>
+ </item>
+
+ </list>
+-->
+
+ </section>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+<!--
+ <p>-</p>
+-->
+
+ <list>
+ <item>
+ <p>[httpc] Parsing of a cookie expire date should be more forgiving.
+ That is, if the parsing fails, the date should be ignored.
+ Also added support for (yet another) date format:
+ "Tue Jan 01 08:00:01 2036 GMT". </p>
+ <p>Own Id: OTP-9433</p>
+ </item>
+
+ <item>
+ <p>[httpc] Rewrote cookie parsing. Among other things solving
+ cookie processing from www.expedia.com. </p>
+ <p>Own Id: OTP-9434</p>
+ </item>
+
+ <item>
+ <p>[httpd] Fix httpd directory traversal on Windows.
+ Directory traversal was possible on Windows where
+ backward slash is used as directory separator. </p>
+ <p>Andr�s Veres-Szentkir�lyi.</p>
+ <p>Own Id: OTP-9561</p>
+ </item>
+
+ </list>
+ </section>
+
+ </section> <!-- 5.7.1 -->
+
+
+ <section><title>Inets 5.7</title>
+
+ <section><title>Improvements and New Features</title>
+<!--
+ <p>-</p>
+-->
+
+ <list>
+ <item>
+ <p>[httpc|httpd] Added support for IPv6 with ssl. </p>
+ <p>Own Id: OTP-5566</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+<!--
+ <p>-</p>
+-->
+
+ <list>
+ <item>
+ <p>[httpc] Remove unnecessary usage of iolist_to_binary when
+ processing body (for PUT and POST). </p>
+ <p>Filipe David Manana</p>
+ <p>Own Id: OTP-9317</p>
+ </item>
+
+ <item>
+ <p>[ftp] FTP client doesn't work with IPv6 host.</p>
+ <p>Attila Rajmund Nohl</p>
+ <p>Own Id: OTP-9342 Aux Id: seq11853</p>
+ </item>
+
+ <item>
+ <p>[httpd] Peer/sockname resolv doesn't work with IPv6 addrs
+ in HTTP. </p>
+ <p>Attila Rajmund Nohl.</p>
+ <p>Own Id: OTP-9343</p>
+ </item>
+
+ <item>
+ <p>[httpc] Clients started stand-alone not properly handled.
+ Also it was not documented how to use them, that is that
+ once started, they are represented by a <c>pid()</c> and not by
+ their <c>profile()</c>. </p>
+ <p>Own Id: OTP-9365</p>
+ </item>
+
+ </list>
+ </section>
+
+ </section> <!-- 5.7 -->
+
+
+ <section><title>Inets 5.6</title>
+
+ <section><title>Improvements and New Features</title>
+<!--
+ <p>-</p>
+-->
+ <list>
+ <item>
+ <p>[httpc] Add support for upload body streaming (PUT and POST).</p>
+ <p>For more info,
+ see the definition of the <c>Body</c> argument of the
+ <seealso marker="httpc#request2">request/4,5</seealso>
+ function. </p>
+ <p>Filipe David Manana</p>
+ <p>Own Id: OTP-9094</p>
+ </item>
+
+ <item>
+ <p>[ftp] Added (type) spec for all exported functions.</p>
+ <p>Own Id: OTP-9114 Aux Id: seq11799</p>
+ </item>
+
+ <item>
+ <p>[httpd]
+ <seealso marker="mod_esi#deliver">mod_esi:deliver/2</seealso>
+ made to accept binary data. </p>
+ <p>Bernard Duggan</p>
+ <p>Own Id: OTP-9123</p>
+ </item>
+
+ <item>
+ <p>[httpd] Prevent XSS in error pages.
+ Prevent user controlled input from being interpreted
+ as HTML in error pages by encoding the reserved HTML
+ characters. </p>
+ <p>Michael Santos</p>
+ <p>Own Id: OTP-9124</p>
+ </item>
+
+ <item>
+ <p>[httpd] Improved error messages. </p>
+ <p>Ricardo Catalinas Jim�nez</p>
+ <p>Own Id: OTP-9157</p>
+ </item>
+
+ <item>
+ <p>[httpd] Extended support for file descriptors.
+ In order to be able to bind to a privileged port
+ without running the erlang VM as root, the support
+ for using file descriptors has been improved.
+ It is now possible to add the file descriptor to the config
+ (option fd) when calling the
+ <seealso marker="inets#start2">inets:start(httpd, ...)</seealso>
+ function. </p>
+ <p>Attila Rajmund Nohl</p>
+ <p>Own Id: OTP-9202</p>
+ <p>Aux Id: seq11819</p>
+ </item>
+
+ <item>
+ <p>The default ssl kind has now been changed to <c>essl</c>. </p>
+ <p><c>ossl</c> will work for as long as the ssl application
+ supports it. </p>
+ <p>See the httpd
+ <seealso marker="httpd#comm_prop">socket_type</seealso>
+ communication property or the httpc
+ <seealso marker="httpc#request2">request/4,5</seealso> function
+ for more info. </p>
+ <p>Own Id: OTP-9230</p>
+ <p>*** POTENTIAL INCOMPATIBILITY ***</p>
+ </item>
+
+ </list>
+ </section>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+<!--
+ <p>-</p>
+-->
+
+ <list>
+ <item>
+ <p>[httpd] Wrong
+ <seealso marker="httpd#sec_prop">security property</seealso>
+ names used in documentation. </p>
+ <p><c>security_data_file</c> used instead of <c>data_file</c>. </p>
+ <p><c>security_max_retries</c> used instead of <c>max_retries</c>. </p>
+ <p><c>security_block_time</c> used instead of <c>block_time</c>. </p>
+ <p><c>security_fail_expire_time</c> used instead of <c>fail_expire_time</c>. </p>
+ <p><c>security_auth_timeout</c> used instead of <c>auth_timeout</c>. </p>
+ <p>Garrett Smith</p>
+ <p>Own Id: OTP-9131</p>
+ </item>
+
+ <item>
+ <p>[httpd] Fix timeout message generated by mod_esi.
+ When a mod_esi request times out, the code to send a
+ timeout response was incorrect and generated an
+ internal server error as well as an invalid response
+ line. </p>
+ <p>Bernard Duggan</p>
+ <p>Own Id: OTP-9158</p>
+ </item>
+
+ <item>
+ <p>[httpc] httpc manager crashes.
+ When a request results in a retry, the request id will be "reused"
+ in the previous implementation a race condition could occur causing
+ the manager to crash. </p>
+ <p>This is now avoided by using proc_lib:init_ack and
+ gen_server:enter_loop to allow mor advanced initialization of
+ httpc_handlers without blocking the httpc_manger and eliminating
+ extra processes that can cause race conditions. </p>
+ <p>Own Id: OTP-9246</p>
+ </item>
+
+ <item>
+ <p>[httpc] Issuing a request (<c>httpc:request</c>) to an
+ host with the ssl option
+ <c>{ip, {127,0,0,1}}</c> results in an handler crash.
+ The reason was that the connect call resulted in an exit with
+ reason <c>badarg</c>
+ (this was the same for both <c>ssl</c> and <c>gen_tcp</c>). </p>
+ <p>Exits was not catched. This has now been improved. </p>
+ <p>Own Id: OTP-9289</p>
+ <p>Aux Id: seq11845</p>
+ </item>
+
+ </list>
+ </section>
+
+ </section> <!-- 5.6 -->
+
+
<section><title>Inets 5.5.2</title>
<section><title>Improvements and New Features</title>
@@ -80,7 +384,8 @@
are URL-encoded. Added support in http-client to use
URL-encoding. Also added the missing include directory
for the inets application.</p>
- <p>Own Id: OTP-8940 Aux Id: seq11735 </p>
+ <p>Own Id: OTP-8940</p>
+ <p>Aux Id: seq11735</p>
</item>
</list>
</section>
@@ -852,570 +1157,11 @@
</section> <!-- 5.1 -->
+ <!--
+ <p>For information about older versions see
+ <url href="part_notes_history_frame.html">release notes history</url>.</p>
+ -->
- <section><title>Inets 5.0.14</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- [tftp] The callback watchdog has been removed, as it
- turned out to be counter productive when the disk was
- overloaded. Earlier a connection was aborted when a
- callback (which performs the file access in the TFTP
- server) took too long time.</p>
- <p>
- [tftp] The error message "Too many connections" has been
- reclassified to be a warning.</p>
- <p>
- Own Id: OTP-7888</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>[httpc] - Incorrect http version option check. </p>
- <p>Mats Cronqvist</p>
- <p>Own Id: OTP-7882</p>
- </item>
-
- <item>
- <p>[httpc] - Unnecessary error report when client
- terminating as a result of the server closed the
- socket unexpectedly. </p>
- <p>Own Id: OTP-7883</p>
- </item>
-
- <item>
- <p>[httpc] - Failed transforming a relative URI to
- an absolute URI. </p>
- <p>Own Id: OTP-7950</p>
- </item>
-
- <item>
- <p>[httpd] - The HTTP server did not handle the config
- option ssl_ca_certificate_file. </p>
- <p>Own Id: OTP-7976</p>
- </item>
-
- </list>
- </section>
-
- </section> <!-- 5.0.14 -->
-
-
- <section><title>Inets 5.0.13</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Ssl did not work correctly with the use of new style
- configuration due to sn old internal format that was not
- changed correctly in all places.</p>
- <p>
- Own Id: OTP-7723 Aux Id: seq11143 </p>
- </item>
- <item>
- <p>
- [httpc] - Now streams 200 and 206 results and not only
- 200 results.</p>
- <p>
- Own Id: OTP-7857</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- [httpc] - The inets http client will now use persistent
- connections without pipelining as default and if a
- pipeline timeout is set it will pipeline the requests on
- the persistent connections.</p>
- <p>
- *** POTENTIAL INCOMPATIBILITY ***</p>
- <p>
- Own Id: OTP-7463</p>
- </item>
- <item>
- <p>
- [httpd] - added option ssl_password_callback_arguments.</p>
- <p>
- Own Id: OTP-7724 Aux Id: seq11151 </p>
- </item>
- <item>
- <p>
- Changed the socket use so that it will become more robust
- to non-functional ipv6 and fallback on ipv4. This changes
- may for very special os-configurations cause a problem
- when used with erts-versions pre R13.</p>
- <p>
- Own Id: OTP-7726</p>
- </item>
- <item>
- <p>
- Removed deprecated function httpd_util:key1search/[2,3]</p>
- <p>
- Own Id: OTP-7815</p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section><title>Inets 5.0.12</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- [httpd] - Updated inets so that it not uses the deprecated
- function ssl:accept/[2,3].</p>
- <p>
- Own Id: OTP-7636 Aux Id: seq11086 </p>
- </item>
- </list>
- </section>
-
- </section>
-
-
- <section><title>Inets 5.0.11</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Transient bug related to hot code swap of the TFTP server is
- now fixed. It could happen that the first TFTP server that was
- started after a code upgrade to Inets-5.0.6 crashed with a
- function clause error in tftp_engine:service_init/2.</p>
- <p> Own Id: OTP-7574 Aux Id: seq11069 </p>
- </item>
- <item>
- <p>
- [httpd] - Validation of ssl_password_callback_module was
- incorrect.</p>
- <p>
- Own Id: OTP-7597 Aux Id: seq11074 </p>
- </item>
- <item>
- <p>
- [httpd] - Misspelling in old apachelike configuration
- directive TransferDiskLogSize has been corrected.</p>
- <p> Own Id: OTP-7598 Aux Id: seq11059 </p>
- </item>
- <item>
- <p>
- Minor problems found by dialyzer has been fixed.</p>
- <p>
- Own Id: OTP-7605</p>
- </item>
- </list>
- </section>
-
- </section>
-
-<section><title>Inets 5.0.10</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Enhanched an info report.</p>
- <p>
- Own Id: OTP-7450</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Changed errro message from
- {wrong_type,{document_root,"/tmp/htdocs"}} to
- {invalid_option,{non_existing,
- document_root,"/tmp/htdocs"}}.</p>
- <p>
- Own Id: OTP-7454</p>
- </item>
- <item>
- <p>
- Relative paths in directory authentication did not work
- as intended, this has now been fixed.</p>
- <p>
- Own Id: OTP-7490</p>
- </item>
- <item>
- <p>
- The query-string passed to the callback function was not
- compliant with the documentation, it is now.</p>
- <p>
- Own Id: OTP-7512</p>
- </item>
- </list>
- </section>
-
-</section>
-
- <section><title>Inets 5.0.9</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Parameters to error_logger:error_report/1 has been
- corrected.</p>
- <p>
- Own Id: OTP-7257 Aux Id: OTP-7294, OTP-7258 </p>
- </item>
- <item>
- <p>
- [httpd] - If a Module/Function request matching an
- erl_script_alias registration does not exist as a function in
- the module registered a 404 error will now be issued instead of a
- 500 error.</p>
- <p>
- Own Id: OTP-7323</p>
- </item>
- <item>
- <p>
- [httpd] -The option auth_type for mod_auth is no longer
- mandatory, for backward-compatibility reasons.</p>
- <p>
- Own Id: OTP-7341</p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section><title>Inets 5.0.8</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- [httpd] - Spelling error caused client connection header
- to be ignored.</p>
- <p>
- Own Id: OTP-7315 Aux Id: seq10951 </p>
- </item>
- <item>
- <p>
- [httpd] - Call to the function
- mod_get:get_modification_date/1 was made too early
- resulting in that httpd did not send the 404 file missing
- response.</p>
- <p>
- Own Id: OTP-7321</p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section><title>Inets 5.0.7</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- [httpc, httpd] - Now follows the recommendation regarding
- line terminators in section 19.3 in RFC 2616 e.i: "The
- line terminator for message-header fields is the sequence
- CRLF. However, we recommend that applications, when
- parsing such headers, recognize a single LF as a line
- terminator and ignore the leading CR".</p>
- <p>
- Own Id: OTP-7304 Aux Id: seq10944 </p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section><title>Inets 5.0.6</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- [tftp] If a callback (which performs the file access in
- the TFTP server) takes too long time (more than the
- double TFTP timeout), the server will abort the
- connection and send an error reply to the client. This
- implies that the server will release resources attached
- to the connection faster than before. The server simply
- assumes that the client has given up.</p>
- <p>
- [tftp] If the TFTP server receives yet another request
- from the same client (same host and port) while it
- already has an active connection to the client, it will
- simply ignore the new request if the request is equal
- with the first one (same filename and options). This
- implies that the (new) client will be served by the
- already ongoing connection on the server side. By not
- setting up yet another connection, in parallel with the
- ongoing one, the server will consumer lesser resources.</p>
- <p>
- [tftp] netascii mode is now supported when the
- client/server has native ascii support (Windows). The new
- optional parameter native_ascii in the tftp_binary and
- tftp_file callback modules can be used to override the
- default behavior.</p>
- <p>
- [tftp] Yet another callback module has been added in
- order to allow customized handling of error, warning and
- info messages. See the new configuration parameter,
- logger.</p>
- <p>
- [tftp] Yet another configuration parameter, max_retries,
- has been added in order to control the number of times a
- packet can be resent. The default is 5.</p>
- <p>
- [tftp] tftp:info/1 and tftp:change_config/2 can now be
- applied to all daemons or all servers in one command
- without bothering about their process identifiers.</p>
- <p>
- External TR HI89527.</p>
- <p>
- Own Id: OTP-7266</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Inets 5.0.5</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- [tftp] Blocks with too low block numbers are silently
- discarded. For example if a server receives block #5 when
- it expects block #7 it will discard the block without
- interrupting the file transfer. Too high block numbers
- does still imply an error. External TR HI96072.</p>
- <p>
- Own Id: OTP-7220</p>
- </item>
- <item>
- <p>
- [tftp] The problem with occasional case_clause errors in
- tftp_engine:common_read/7 has been fixed. External TR
- HI97362.</p>
- <p>
- Own Id: OTP-7221</p>
- </item>
- </list>
- </section>
-
-</section>
-
- <section><title>Inets 5.0.4</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Changed calls to file open to concur with the API and not
- use deprecated syntax.</p>
- <p>
- Own Id: OTP-7172</p>
- </item>
- <item>
- <p>
- [tftp] Server lost the first packet when the client timed
- out</p>
- <p>
- Own Id: OTP-7173</p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section><title>Inets 5.0.3</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Updated copyright headers and fixed backwards
- compatibility for an undocumented feature, for now. This
- feature will later be removed and a new and documented
- option will take its place.</p>
- <p>
- Own Id: OTP-7144</p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section><title>Inets 5.0.2</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- [httpd] - Error logs now has a pretty and a compact
- format and access logs can be written on the common log
- format or the extended common log format.</p>
- <p>
- Own Id: OTP-6661 Aux Id: Seq 7764 </p>
- </item>
- <item>
- <p>
- [httpc] - Added acceptance of missing reason phrase to
- the relaxed mode.</p>
- <p>
- Own Id: OTP-7024</p>
- </item>
- <item>
- <p>
- [httpc] - A new option has been added to enable the
- client to act as lower version clients, by default the
- client is an HTTP/1.1 client.</p>
- <p>
- Own Id: OTP-7043</p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section><title>Inets 5.0.1</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- [httpd] - Deprecated function httpd:start/1 did not
- accept all inputs that it had done previously. This
- should now work again.</p>
- <p>
- Own Id: OTP-7040</p>
- </item>
- </list>
- </section>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- [httpd] - Changed validity check on bind_address so that
- it uses inet:getaddr instead of inet:gethostbyaddr as the
- former puts a too hard restriction on the bind_address.</p>
- <p>
- Own Id: OTP-7041 Aux Id: seq10829 </p>
- </item>
- <item>
- <p>
- [httpc] - Internal process now does try-catch and
- terminates normally in case of HTTP parse errors.
- Semantical the client works just as before returning an
- error message to the client, even if the error massage
- has been enhanced, but there is no supervisor report in
- the shell of a internal process crashing. (Which was the
- expected behavior and not a fault.)</p>
- <p>
- Own Id: OTP-7042</p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section><title>Inets 5.0</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- [httpd, httpc] - Deprecated base64 decode/encode
- functions have been removed. Inets uses base64 in STDLIB
- instead.</p>
- <p>
- *** POTENTIAL INCOMPATIBILITY ***</p>
- <p>
- Own Id: OTP-6485</p>
- </item>
- <item>
- <p>
- [httpd] - It is now possible to restrict the length of
- acceptable URI:s in the HTTP server.</p>
- <p>
- Own Id: OTP-6572</p>
- </item>
- <item>
- <p>
- [httpc] - Profiles are now supported i.e. the options
- available in set_options/1 can be set locally for a
- certain profile and do not have to affect all
- HTTP-requests issued in the Erlang node. Calls to the
- HTTP client API functions not using the profile argument
- will use the default profile.</p>
- <p>
- Own Id: OTP-6690</p>
- </item>
- <item>
- <p>
- A new uniform Inets interface provides a flexible way to
- start/stop Inets services and get information about
- running services. See inets(3). This also means that
- inflexibilities in the HTTP server has been removed and
- more default values has been added.</p>
- <p>
- Own Id: OTP-6705</p>
- </item>
- <item>
- <p>
- [tftp] Logged errors have been changed to be logged
- warnings.</p>
- <p>
- Own Id: OTP-6916 Aux Id: seq10737 </p>
- </item>
- <item>
- <p>
- [httpc] - The client will now return the proper value
- when receiving a HTTP 204 code instead of hanging.</p>
- <p>
- Own Id: OTP-6982</p>
- </item>
- <item>
- <p>
- The Inets application now has to be explicitly started
- and stopped i.e. it will not automatically be started as
- a temporary application as it did before. Although a
- practical feature when testing things in the shell it is
- not desirable that people take advantage of this and not
- start the Inets application in a correct way in their
- products. Added functions to the Inets API that call
- application:start/stop.</p>
- <p>
- *** POTENTIAL INCOMPATIBILITY ***</p>
- <p>
- Own Id: OTP-6993</p>
- </item>
- </list>
- </section>
-
- <!-- p>For information about older versions see
- <url href="part_notes_history_frame.html">release notes history</url>.</p -->
- </section>
</chapter>
diff --git a/lib/inets/doc/src/notes_history.xml b/lib/inets/doc/src/notes_history.xml
index 6480bad758..151bec375e 100644
--- a/lib/inets/doc/src/notes_history.xml
+++ b/lib/inets/doc/src/notes_history.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -123,7 +123,7 @@
re-receive of acknowledgments. If multiple copies of the
same acknowledgments is received the spurious ones are
silently ignored. This fix was intended for inets-4.7.14
- but accidentaly it was not included in that release.</p>
+ but accidentally it was not included in that release.</p>
<p>Own Id: OTP-6706 Aux Id: OTP-6691 </p>
</item>
</list>
diff --git a/lib/inets/src/ftp/ftp.erl b/lib/inets/src/ftp/ftp.erl
index 5ad74851c8..ac72963347 100644
--- a/lib/inets/src/ftp/ftp.erl
+++ b/lib/inets/src/ftp/ftp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The 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,6 +92,12 @@
}).
+-type shortage_reason() :: 'etnospc' | 'epnospc'.
+-type restriction_reason() :: 'epath' | 'efnamena' | 'elogin' | 'enotbinary'.
+-type common_reason() :: 'econn' | 'eclosed' | term().
+-type file_write_error_reason() :: term(). % See file:write for more info
+
+
%%%=========================================================================
%%% API - CLIENT FUNCTIONS
%%%=========================================================================
@@ -106,6 +112,9 @@
%% Description: Start an ftp client and connect to a host.
%%--------------------------------------------------------------------------
+-spec open(Host :: string() | inet:ip_address()) ->
+ {'ok', Pid :: pid()} | {'error', Reason :: 'ehost' | term()}.
+
%% <BACKWARD-COMPATIBILLITY>
open({option_list, Options}) when is_list(Options) ->
try
@@ -126,6 +135,9 @@ open({option_list, Options}) when is_list(Options) ->
open(Host) ->
open(Host, []).
+-spec open(Host :: string() | inet:ip_address(), Opts :: list()) ->
+ {'ok', Pid :: pid()} | {'error', Reason :: 'ehost' | term()}.
+
%% <BACKWARD-COMPATIBILLITY>
open(Host, Port) when is_integer(Port) ->
open(Host, [{port, Port}]);
@@ -161,12 +173,24 @@ open(Host, Opts) when is_list(Opts) ->
%%
%% Description: Login with or without a supplied account name.
%%--------------------------------------------------------------------------
+-spec user(Pid :: pid(),
+ User :: string(),
+ Pass :: string()) ->
+ 'ok' | {'error', Reason :: 'euser' | common_reason()}.
+
user(Pid, User, Pass) ->
call(Pid, {user, User, Pass}, atom).
+-spec user(Pid :: pid(),
+ User :: string(),
+ Pass :: string(),
+ Acc :: string()) ->
+ 'ok' | {'error', Reason :: 'euser' | common_reason()}.
+
user(Pid, User, Pass, Acc) ->
call(Pid, {user, User, Pass, Acc}, atom).
+
%%--------------------------------------------------------------------------
%% account(Pid, Acc) -> ok | {error, eacct}
%% Pid = pid()
@@ -174,9 +198,14 @@ user(Pid, User, Pass, Acc) ->
%%
%% Description: Set a user Account.
%%--------------------------------------------------------------------------
+
+-spec account(Pid :: pid(), Acc :: string()) ->
+ 'ok' | {'error', Reason :: 'eacct' | common_reason()}.
+
account(Pid, Acc) ->
call(Pid, {account, Acc}, atom).
+
%%--------------------------------------------------------------------------
%% pwd(Pid) -> {ok, Dir} | {error, elogin} | {error, econn}
%% Pid = pid()
@@ -184,19 +213,30 @@ account(Pid, Acc) ->
%%
%% Description: Get the current working directory at remote server.
%%--------------------------------------------------------------------------
+
+-spec pwd(Pid :: pid()) ->
+ {'ok', Dir :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
pwd(Pid) ->
call(Pid, pwd, ctrl).
+
%%--------------------------------------------------------------------------
-%% lpwd(Pid) -> {ok, Dir} | {error, elogin}
+%% lpwd(Pid) -> {ok, Dir}
%% Pid = pid()
%% Dir = string()
%%
%% Description: Get the current working directory at local server.
%%--------------------------------------------------------------------------
+
+-spec lpwd(Pid :: pid()) ->
+ {'ok', Dir :: string()}.
+
lpwd(Pid) ->
call(Pid, lpwd, string).
+
%%--------------------------------------------------------------------------
%% cd(Pid, Dir) -> ok | {error, epath} | {error, elogin} | {error, econn}
%% Pid = pid()
@@ -204,9 +244,14 @@ lpwd(Pid) ->
%%
%% Description: Change current working directory at remote server.
%%--------------------------------------------------------------------------
+
+-spec cd(Pid :: pid(), Dir :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
cd(Pid, Dir) ->
call(Pid, {cd, Dir}, atom).
+
%%--------------------------------------------------------------------------
%% lcd(Pid, Dir) -> ok | {error, epath}
%% Pid = pid()
@@ -214,9 +259,14 @@ cd(Pid, Dir) ->
%%
%% Description: Change current working directory for the local client.
%%--------------------------------------------------------------------------
+
+-spec lcd(Pid :: pid(), Dir :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason()}.
+
lcd(Pid, Dir) ->
call(Pid, {lcd, Dir}, string).
+
%%--------------------------------------------------------------------------
%% ls(Pid) -> Result
%% ls(Pid, <Dir>) -> Result
@@ -229,11 +279,22 @@ lcd(Pid, Dir) ->
%%
%% Description: Returns a list of files in long format.
%%--------------------------------------------------------------------------
+
+-spec ls(Pid :: pid()) ->
+ {'ok', Listing :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
ls(Pid) ->
ls(Pid, "").
+
+-spec ls(Pid :: pid(), Dir :: string()) ->
+ {'ok', Listing :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
ls(Pid, Dir) ->
call(Pid, {dir, long, Dir}, string).
+
%%--------------------------------------------------------------------------
%% nlist(Pid) -> Result
%% nlist(Pid, Pathname) -> Result
@@ -246,21 +307,37 @@ ls(Pid, Dir) ->
%%
%% Description: Returns a list of files in short format
%%--------------------------------------------------------------------------
+
+-spec nlist(Pid :: pid()) ->
+ {'ok', Listing :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
nlist(Pid) ->
nlist(Pid, "").
+
+-spec nlist(Pid :: pid(), Pathname :: string()) ->
+ {'ok', Listing :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
nlist(Pid, Dir) ->
call(Pid, {dir, short, Dir}, string).
+
%%--------------------------------------------------------------------------
-%% rename(Pid, CurrFile, NewFile) -> ok | {error, epath} | {error, elogin}
-%% | {error, econn}
+%% rename(Pid, Old, New) -> ok | {error, epath} | {error, elogin}
+%% | {error, econn}
%% Pid = pid()
%% CurrFile = NewFile = string()
%%
%% Description: Rename a file at remote server.
%%--------------------------------------------------------------------------
-rename(Pid, CurrFile, NewFile) ->
- call(Pid, {rename, CurrFile, NewFile}, string).
+
+-spec rename(Pid :: pid(), Old :: string(), New :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
+rename(Pid, Old, New) ->
+ call(Pid, {rename, Old, New}, string).
+
%%--------------------------------------------------------------------------
%% delete(Pid, File) -> ok | {error, epath} | {error, elogin} |
@@ -270,9 +347,14 @@ rename(Pid, CurrFile, NewFile) ->
%%
%% Description: Remove file at remote server.
%%--------------------------------------------------------------------------
+
+-spec delete(Pid :: pid(), File :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
delete(Pid, File) ->
call(Pid, {delete, File}, string).
+
%%--------------------------------------------------------------------------
%% mkdir(Pid, Dir) -> ok | {error, epath} | {error, elogin} | {error, econn}
%% Pid = pid(),
@@ -280,9 +362,14 @@ delete(Pid, File) ->
%%
%% Description: Make directory at remote server.
%%--------------------------------------------------------------------------
+
+-spec mkdir(Pid :: pid(), Dir :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
mkdir(Pid, Dir) ->
call(Pid, {mkdir, Dir}, atom).
+
%%--------------------------------------------------------------------------
%% rmdir(Pid, Dir) -> ok | {error, epath} | {error, elogin} | {error, econn}
%% Pid = pid(),
@@ -290,9 +377,14 @@ mkdir(Pid, Dir) ->
%%
%% Description: Remove directory at remote server.
%%--------------------------------------------------------------------------
+
+-spec rmdir(Pid :: pid(), Dir :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
rmdir(Pid, Dir) ->
call(Pid, {rmdir, Dir}, atom).
+
%%--------------------------------------------------------------------------
%% type(Pid, Type) -> ok | {error, etype} | {error, elogin} | {error, econn}
%% Pid = pid()
@@ -300,23 +392,41 @@ rmdir(Pid, Dir) ->
%%
%% Description: Set transfer type.
%%--------------------------------------------------------------------------
+
+-spec type(Pid :: pid(), Type :: ascii | binary) ->
+ 'ok' |
+ {'error', Reason :: 'etype' | restriction_reason() | common_reason()}.
+
type(Pid, Type) ->
call(Pid, {type, Type}, atom).
+
%%--------------------------------------------------------------------------
-%% recv(Pid, RemoteFileName <LocalFileName>) -> ok | {error, epath} |
+%% recv(Pid, RemoteFileName [, LocalFileName]) -> ok | {error, epath} |
%% {error, elogin} | {error, econn}
%% Pid = pid()
%% RemoteFileName = LocalFileName = string()
%%
%% Description: Transfer file from remote server.
%%--------------------------------------------------------------------------
+
+-spec recv(Pid :: pid(), RemoteFileName :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() |
+ common_reason() |
+ file_write_error_reason()}.
+
recv(Pid, RemotFileName) ->
recv(Pid, RemotFileName, RemotFileName).
+-spec recv(Pid :: pid(),
+ RemoteFileName :: string(),
+ LocalFileName :: string()) ->
+ 'ok' | {'error', Reason :: term()}.
+
recv(Pid, RemotFileName, LocalFileName) ->
call(Pid, {recv, RemotFileName, LocalFileName}, atom).
+
%%--------------------------------------------------------------------------
%% recv_bin(Pid, RemoteFile) -> {ok, Bin} | {error, epath} | {error, elogin}
%% | {error, econn}
@@ -326,9 +436,16 @@ recv(Pid, RemotFileName, LocalFileName) ->
%%
%% Description: Transfer file from remote server into binary.
%%--------------------------------------------------------------------------
+
+-spec recv_bin(Pid :: pid(),
+ RemoteFile :: string()) ->
+ {'ok', Bin :: binary()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
recv_bin(Pid, RemoteFile) ->
call(Pid, {recv_bin, RemoteFile}, bin).
+
%%--------------------------------------------------------------------------
%% recv_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} | {error, epath}
%% | {error, econn}
@@ -337,9 +454,15 @@ recv_bin(Pid, RemoteFile) ->
%%
%% Description: Start receive of chunks of remote file.
%%--------------------------------------------------------------------------
+
+-spec recv_chunk_start(Pid :: pid(),
+ RemoteFile :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
recv_chunk_start(Pid, RemoteFile) ->
call(Pid, {recv_chunk_start, RemoteFile}, atom).
+
%%--------------------------------------------------------------------------
%% recv_chunk(Pid, RemoteFile) -> ok | {ok, Bin} | {error, Reason}
%% Pid = pid()
@@ -347,24 +470,47 @@ recv_chunk_start(Pid, RemoteFile) ->
%%
%% Description: Transfer file from remote server into binary in chunks
%%--------------------------------------------------------------------------
+
+-spec recv_chunk(Pid :: pid()) ->
+ 'ok' |
+ {'ok', Bin :: binary()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
recv_chunk(Pid) ->
call(Pid, recv_chunk, atom).
+
%%--------------------------------------------------------------------------
-%% send(Pid, LocalFileName <RemotFileName>) -> ok | {error, epath}
-%% | {error, elogin}
-%% | {error, econn}
+%% send(Pid, LocalFileName [, RemotFileName]) -> ok | {error, epath}
+%% | {error, elogin}
+%% | {error, econn}
%% Pid = pid()
%% LocalFileName = RemotFileName = string()
%%
%% Description: Transfer file to remote server.
%%--------------------------------------------------------------------------
+
+-spec send(Pid :: pid(), LocalFileName :: string()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
+ shortage_reason()}.
+
send(Pid, LocalFileName) ->
send(Pid, LocalFileName, LocalFileName).
+-spec send(Pid :: pid(),
+ LocalFileName :: string(),
+ RemoteFileName :: string()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
+ shortage_reason()}.
+
send(Pid, LocalFileName, RemotFileName) ->
call(Pid, {send, LocalFileName, RemotFileName}, atom).
+
%%--------------------------------------------------------------------------
%% send_bin(Pid, Bin, RemoteFile) -> ok | {error, epath} | {error, elogin}
%% | {error, enotbinary} | {error, econn}
@@ -374,11 +520,19 @@ send(Pid, LocalFileName, RemotFileName) ->
%%
%% Description: Transfer a binary to a remote file.
%%--------------------------------------------------------------------------
+
+-spec send_bin(Pid :: pid(), Bin :: binary(), RemoteFile :: string()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
+ shortage_reason()}.
+
send_bin(Pid, Bin, RemoteFile) when is_binary(Bin) ->
call(Pid, {send_bin, Bin, RemoteFile}, atom);
send_bin(_Pid, _Bin, _RemoteFile) ->
{error, enotbinary}.
+
%%--------------------------------------------------------------------------
%% send_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} | {error, epath}
%% | {error, econn}
@@ -387,9 +541,14 @@ send_bin(_Pid, _Bin, _RemoteFile) ->
%%
%% Description: Start transfer of chunks to remote file.
%%--------------------------------------------------------------------------
+
+-spec send_chunk_start(Pid :: pid(), RemoteFile :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
send_chunk_start(Pid, RemoteFile) ->
call(Pid, {send_chunk_start, RemoteFile}, atom).
+
%%--------------------------------------------------------------------------
%% append_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} |
%% {error, epath} | {error, econn}
@@ -398,9 +557,14 @@ send_chunk_start(Pid, RemoteFile) ->
%%
%% Description: Start append chunks of data to remote file.
%%--------------------------------------------------------------------------
+
+-spec append_chunk_start(Pid :: pid(), RemoteFile :: string()) ->
+ 'ok' | {'error', Reason :: term()}.
+
append_chunk_start(Pid, RemoteFile) ->
call(Pid, {append_chunk_start, RemoteFile}, atom).
+
%%--------------------------------------------------------------------------
%% send_chunk(Pid, Bin) -> ok | {error, elogin} | {error, enotbinary}
%% | {error, echunk} | {error, econn}
@@ -409,11 +573,19 @@ append_chunk_start(Pid, RemoteFile) ->
%%
%% Purpose: Send chunk to remote file.
%%--------------------------------------------------------------------------
+
+-spec send_chunk(Pid :: pid(), Bin :: binary()) ->
+ 'ok' |
+ {'error', Reason :: 'echunk' |
+ restriction_reason() |
+ common_reason()}.
+
send_chunk(Pid, Bin) when is_binary(Bin) ->
call(Pid, {transfer_chunk, Bin}, atom);
send_chunk(_Pid, _Bin) ->
{error, enotbinary}.
+
%%--------------------------------------------------------------------------
%% append_chunk(Pid, Bin) -> ok | {error, elogin} | {error, enotbinary}
%% | {error, echunk} | {error, econn}
@@ -422,11 +594,19 @@ send_chunk(_Pid, _Bin) ->
%%
%% Description: Append chunk to remote file.
%%--------------------------------------------------------------------------
+
+-spec append_chunk(Pid :: pid(), Bin :: binary()) ->
+ 'ok' |
+ {'error', Reason :: 'echunk' |
+ restriction_reason() |
+ common_reason()}.
+
append_chunk(Pid, Bin) when is_binary(Bin) ->
call(Pid, {transfer_chunk, Bin}, atom);
append_chunk(_Pid, _Bin) ->
{error, enotbinary}.
+
%%--------------------------------------------------------------------------
%% send_chunk_end(Pid) -> ok | {error, elogin} | {error, echunk}
%% | {error, econn}
@@ -434,9 +614,17 @@ append_chunk(_Pid, _Bin) ->
%%
%% Description: End sending of chunks to remote file.
%%--------------------------------------------------------------------------
+
+-spec send_chunk_end(Pid :: pid()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
+ shortage_reason()}.
+
send_chunk_end(Pid) ->
call(Pid, chunk_end, atom).
+
%%--------------------------------------------------------------------------
%% append_chunk_end(Pid) -> ok | {error, elogin} | {error, echunk}
%% | {error, econn}
@@ -444,23 +632,47 @@ send_chunk_end(Pid) ->
%%
%% Description: End appending of chunks to remote file.
%%--------------------------------------------------------------------------
+
+-spec append_chunk_end(Pid :: pid()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
+ shortage_reason()}.
+
append_chunk_end(Pid) ->
call(Pid, chunk_end, atom).
+
%%--------------------------------------------------------------------------
-%% append(Pid, LocalFileName, RemotFileName) -> ok | {error, epath}
-%% | {error, elogin} | {error, econn}
+%% append(Pid, LocalFileName [, RemotFileName]) -> ok | {error, epath}
+%% | {error, elogin}
+%% | {error, econn}
%% Pid = pid()
%% LocalFileName = RemotFileName = string()
%%
%% Description: Append the local file to the remote file
%%--------------------------------------------------------------------------
+
+-spec append(Pid :: pid(), LocalFileName :: string()) ->
+ 'ok' |
+ {'error', Reason :: 'epath' |
+ 'elogin' |
+ 'etnospc' |
+ 'epnospc' |
+ 'efnamena' | common_reason()}.
+
append(Pid, LocalFileName) ->
append(Pid, LocalFileName, LocalFileName).
+-spec append(Pid :: pid(),
+ LocalFileName :: string(),
+ RemoteFileName :: string()) ->
+ 'ok' | {'error', Reason :: term()}.
+
append(Pid, LocalFileName, RemotFileName) ->
call(Pid, {append, LocalFileName, RemotFileName}, atom).
+
%%--------------------------------------------------------------------------
%% append_bin(Pid, Bin, RemoteFile) -> ok | {error, epath} | {error, elogin}
%% | {error, enotbinary} | {error, econn}
@@ -470,27 +682,44 @@ append(Pid, LocalFileName, RemotFileName) ->
%%
%% Purpose: Append a binary to a remote file.
%%--------------------------------------------------------------------------
+
+-spec append_bin(Pid :: pid(),
+ Bin :: binary(),
+ RemoteFile :: string()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
+ shortage_reason()}.
+
append_bin(Pid, Bin, RemoteFile) when is_binary(Bin) ->
call(Pid, {append_bin, Bin, RemoteFile}, atom);
append_bin(_Pid, _Bin, _RemoteFile) ->
{error, enotbinary}.
+
%%--------------------------------------------------------------------------
-%% quote(Pid, Cmd) -> ok
+%% quote(Pid, Cmd) -> list()
%% Pid = pid()
%% Cmd = string()
%%
%% Description: Send arbitrary ftp command.
%%--------------------------------------------------------------------------
+
+-spec quote(Pid :: pid(), Cmd :: string()) -> list().
+
quote(Pid, Cmd) when is_list(Cmd) ->
call(Pid, {quote, Cmd}, atom).
+
%%--------------------------------------------------------------------------
%% close(Pid) -> ok
%% Pid = pid()
%%
%% Description: End the ftp session.
%%--------------------------------------------------------------------------
+
+-spec close(Pid :: pid()) -> 'ok'.
+
close(Pid) ->
cast(Pid, close),
ok.
@@ -502,9 +731,13 @@ close(Pid) ->
%%
%% Description: Return diagnostics.
%%--------------------------------------------------------------------------
+
+-spec formaterror(Tag :: term()) -> string().
+
formaterror(Tag) ->
ftp_response:error_string(Tag).
+
info(Pid) ->
call(Pid, info, list).
@@ -805,10 +1038,12 @@ handle_call({_, {open, ip_comm, Opts}}, From, State) ->
Port = key_search(port, Opts, ?FTP_PORT),
Timeout = key_search(timeout, Opts, ?CONNECTION_TIMEOUT),
Progress = key_search(progress, Opts, ignore),
+ IpFamily = key_search(ipfamily, Opts, inet),
State2 = State#state{client = From,
mode = Mode,
- progress = progress(Progress)},
+ progress = progress(Progress),
+ ipfamily = IpFamily},
?fcrd("handle_call(open) -> setup ctrl connection with",
[{host, Host}, {port, Port}, {timeout, Timeout}]),
diff --git a/lib/inets/src/http_client/Makefile b/lib/inets/src/http_client/Makefile
index 0397b48ab2..3960c36d00 100644
--- a/lib/inets/src/http_client/Makefile
+++ b/lib/inets/src/http_client/Makefile
@@ -41,7 +41,6 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# Target Specs
# ----------------------------------------------------
MODULES = \
- http \
httpc \
httpc_cookie \
httpc_handler \
diff --git a/lib/inets/src/http_client/http.erl b/lib/inets/src/http_client/http.erl
deleted file mode 100644
index bbe2fec267..0000000000
--- a/lib/inets/src/http_client/http.erl
+++ /dev/null
@@ -1,132 +0,0 @@
-%%
-%% %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%
-%%
-%%
-
-%%% Description: OLD API MODULE - USE httpc INSTEAD
-
--module(http).
-
--deprecated({request, 1, next_major_release}).
--deprecated({request, 2, next_major_release}).
--deprecated({request, 4, next_major_release}).
--deprecated({request, 5, next_major_release}).
--deprecated({cancel_request, 1, next_major_release}).
--deprecated({cancel_request, 2, next_major_release}).
--deprecated({set_option, 2, next_major_release}).
--deprecated({set_option, 3, next_major_release}).
--deprecated({set_options, 1, next_major_release}).
--deprecated({set_options, 2, next_major_release}).
--deprecated({verify_cookies, 2, next_major_release}).
--deprecated({verify_cookies, 3, next_major_release}).
--deprecated({cookie_header, 1, next_major_release}).
--deprecated({cookie_header, 2, next_major_release}).
--deprecated({stream_next, 1, next_major_release}).
--deprecated({default_profile, 0, next_major_release}).
-
-%% Deprecated
--export([
- request/1, request/2, request/4, request/5,
- cancel_request/1, cancel_request/2,
- set_option/2, set_option/3,
- set_options/1, set_options/2,
- verify_cookies/2, verify_cookies/3,
- cookie_header/1, cookie_header/2,
- stream_next/1,
- default_profile/0
- ]).
-
-
-%%%=========================================================================
-%%% API
-%%%=========================================================================
-
-%%--------------------------------------------------------------------------
-%% request(Url [, Profile]) ->
-%% request(Method, Request, HTTPOptions, Options [, Profile])
-%%--------------------------------------------------------------------------
-
-request(Url) -> httpc:request(Url).
-request(Url, Profile) -> httpc:request(Url, Profile).
-
-request(Method, Request, HttpOptions, Options) ->
- httpc:request(Method, Request, HttpOptions, Options).
-request(Method, Request, HttpOptions, Options, Profile) ->
- httpc:request(Method, Request, HttpOptions, Options, Profile).
-
-
-%%--------------------------------------------------------------------------
-%% cancel_request(RequestId [, Profile])
-%%-------------------------------------------------------------------------
-
-cancel_request(RequestId) ->
- httpc:cancel_request(RequestId).
-cancel_request(RequestId, Profile) ->
- httpc:cancel_request(RequestId, Profile).
-
-
-%%--------------------------------------------------------------------------
-%% set_options(Options [, Profile])
-%% set_option(Key, Value [, Profile])
-%%-------------------------------------------------------------------------
-
-set_options(Options) ->
- httpc:set_options(Options).
-set_options(Options, Profile) ->
- httpc:set_options(Options, Profile).
-
-set_option(Key, Value) ->
- httpc:set_option(Key, Value).
-set_option(Key, Value, Profile) ->
- httpc:set_option(Key, Value, Profile).
-
-
-%%--------------------------------------------------------------------------
-%% verify_cookies(SetCookieHeaders, Url [, Profile])
-%%-------------------------------------------------------------------------
-
-verify_cookies(SetCookieHeaders, Url) ->
- httpc:store_cookies(SetCookieHeaders, Url).
-verify_cookies(SetCookieHeaders, Url, Profile) ->
- httpc:store_cookies(SetCookieHeaders, Url, Profile).
-
-
-%%--------------------------------------------------------------------------
-%% cookie_header(Url [, Profile])
-%%-------------------------------------------------------------------------
-
-cookie_header(Url) ->
- httpc:cookie_header(Url).
-cookie_header(Url, Profile) ->
- httpc:cookie_header(Url, Profile).
-
-
-%%--------------------------------------------------------------------------
-%% stream_next(Pid)
-%%-------------------------------------------------------------------------
-
-stream_next(Pid) ->
- httpc:stream_next(Pid).
-
-
-%%--------------------------------------------------------------------------
-%% default_profile()
-%%-------------------------------------------------------------------------
-
-default_profile() ->
- httpc:default_profile().
diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl
index 04fae13b20..75c26c63cc 100644
--- a/lib/inets/src/http_client/httpc.erl
+++ b/lib/inets/src/http_client/httpc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -64,17 +64,16 @@ default_profile() ->
profile_name(?DEFAULT_PROFILE) ->
httpc_manager;
+profile_name(Profile) when is_pid(Profile) ->
+ Profile;
profile_name(Profile) ->
- profile_name("httpc_manager_", Profile).
+ Prefix = lists:flatten(io_lib:format("~w_", [?MODULE])),
+ profile_name(Prefix, Profile).
profile_name(Prefix, Profile) when is_atom(Profile) ->
list_to_atom(Prefix ++ atom_to_list(Profile));
-profile_name(Prefix, Profile) when is_pid(Profile) ->
- ProfileStr0 =
- string:strip(string:strip(erlang:pid_to_list(Profile), left, $<), right, $>),
- F = fun($.) -> $_; (X) -> X end,
- ProfileStr = [F(C) || C <- ProfileStr0],
- list_to_atom(Prefix ++ "pid_" ++ ProfileStr).
+profile_name(_Prefix, Profile) when is_pid(Profile) ->
+ Profile.
%%--------------------------------------------------------------------------
@@ -106,7 +105,6 @@ request(Url, Profile) ->
%% {ssl, SSLOptions} | {proxy_auth, {User, Password}}
%% Ssloptions = ssl_options() |
%% {ssl, ssl_options()} |
-%% {ossl, ssl_options()} |
%% {essl, ssl_options()}
%% ssl_options() = [ssl_option()]
%% ssl_option() = {verify, code()} |
@@ -115,9 +113,11 @@ request(Url, Profile) ->
%% {keyfile, path()} | {password, string()} | {cacertfile, path()} |
%% {ciphers, string()}
%% Options - [Option]
-%% Option - {sync, Boolean} | {body_format, BodyFormat} |
-%% {full_result, Boolean} | {stream, To} |
-%% {headers_as_is, Boolean}
+%% Option - {sync, Boolean} |
+%% {body_format, BodyFormat} |
+%% {full_result, Boolean} |
+%% {stream, To} |
+%% {headers_as_is, Boolean}
%% StatusLine = {HTTPVersion, StatusCode, ReasonPhrase}</v>
%% HTTPVersion = string()
%% StatusCode = integer()
@@ -126,7 +126,10 @@ request(Url, Profile) ->
%% Header = {Field, Value}
%% Field = string()
%% Value = string()
-%% Body = string() | binary() - HTLM-code
+%% Body = string() | binary() | {fun(SendAcc) -> SendFunResult, SendAcc} |
+%% {chunkify, fun(SendAcc) -> SendFunResult, SendAcc} - HTLM-code
+%% SendFunResult = eof | {ok, iolist(), NewSendAcc}
+%% SendAcc = NewSendAcc = term()
%%
%% Description: Sends a HTTP-request. The function can be both
%% syncronus and asynchronous in the later case the function will
@@ -426,26 +429,44 @@ service_info(Pid) ->
handle_request(Method, Url,
{Scheme, UserInfo, Host, Port, Path, Query},
- Headers, ContentType, Body,
+ Headers0, ContentType, Body0,
HTTPOptions0, Options0, Profile) ->
- Started = http_util:timestamp(),
- NewHeaders = [{http_util:to_lower(Key), Val} || {Key, Val} <- Headers],
+ Started = http_util:timestamp(),
+ NewHeaders0 = [{http_util:to_lower(Key), Val} || {Key, Val} <- Headers0],
try
begin
+ ?hcrt("begin processing", [{started, Started},
+ {new_headers, NewHeaders0}]),
+
+ {NewHeaders, Body} =
+ case Body0 of
+ {chunkify, ProcessBody, Acc}
+ when is_function(ProcessBody, 1) ->
+ NewHeaders1 = ensure_chunked_encoding(NewHeaders0),
+ Body1 = {mk_chunkify_fun(ProcessBody), Acc},
+ {NewHeaders1, Body1};
+ {ProcessBody, _}
+ when is_function(ProcessBody, 1) ->
+ {NewHeaders0, Body0};
+ _ when is_list(Body0) orelse is_binary(Body0) ->
+ {NewHeaders0, Body0};
+ _ ->
+ throw({error, {bad_body, Body0}})
+ end,
+
HTTPOptions = http_options(HTTPOptions0),
Options = request_options(Options0),
Sync = proplists:get_value(sync, Options),
Stream = proplists:get_value(stream, Options),
Host2 = header_host(Scheme, Host, Port),
HeadersRecord = header_record(NewHeaders, Host2, HTTPOptions),
- Receiver = proplists:get_value(receiver, Options),
- SocketOpts = proplists:get_value(socket_opts, Options),
- UrlEncodeBool = HTTPOptions#http_options.url_encode,
- MaybeEscPath = url_encode(Path, UrlEncodeBool),
- MaybeEscQuery = url_encode(Query, UrlEncodeBool),
- AbsUri = url_encode(Url, UrlEncodeBool),
+ Receiver = proplists:get_value(receiver, Options),
+ SocketOpts = proplists:get_value(socket_opts, Options),
+ MaybeEscPath = maybe_encode_uri(HTTPOptions, Path),
+ MaybeEscQuery = maybe_encode_uri(HTTPOptions, Query),
+ AbsUri = maybe_encode_uri(HTTPOptions, Url),
Request = #request{from = Receiver,
scheme = Scheme,
@@ -458,38 +479,69 @@ handle_request(Method, Url,
settings = HTTPOptions,
abs_uri = AbsUri,
userinfo = UserInfo,
- stream = Stream,
- headers_as_is = headers_as_is(Headers, Options),
+ stream = Stream,
+ headers_as_is = headers_as_is(Headers0, Options),
socket_opts = SocketOpts,
started = Started},
+
case httpc_manager:request(Request, profile_name(Profile)) of
{ok, RequestId} ->
handle_answer(RequestId, Sync, Options);
{error, Reason} ->
+ ?hcrd("request failed", [{reason, Reason}]),
{error, Reason}
end
end
catch
error:{noproc, _} ->
+ ?hcrv("noproc", [{profile, Profile}]),
{error, {not_started, Profile}};
throw:Error ->
+ ?hcrv("throw", [{error, Error}]),
Error
end.
-url_encode(URI, true) ->
+ensure_chunked_encoding(Hdrs) ->
+ Key = "transfer-encoding",
+ lists:keystore(Key, 1, Hdrs, {Key, "chunked"}).
+
+maybe_encode_uri(#http_options{url_encode = true}, URI) ->
http_uri:encode(URI);
-url_encode(URI, false) ->
+maybe_encode_uri(_, URI) ->
URI.
+mk_chunkify_fun(ProcessBody) ->
+ fun(eof_body) ->
+ eof;
+ (Acc) ->
+ case ProcessBody(Acc) of
+ eof ->
+ {ok, <<"0\r\n\r\n">>, eof_body};
+ {ok, Data, NewAcc} ->
+ Chunk = [
+ integer_to_list(iolist_size(Data), 16),
+ "\r\n",
+ Data,
+ "\r\n"],
+ {ok, Chunk, NewAcc}
+ end
+ end.
+
+
handle_answer(RequestId, false, _) ->
{ok, RequestId};
handle_answer(RequestId, true, Options) ->
receive
{http, {RequestId, saved_to_file}} ->
+ ?hcrt("received saved-to-file", [{request_id, RequestId}]),
{ok, saved_to_file};
{http, {RequestId, {_,_,_} = Result}} ->
+ ?hcrt("received answer", [{request_id, RequestId},
+ {result, Result}]),
return_answer(Options, Result);
{http, {RequestId, {error, Reason}}} ->
+ ?hcrt("received error", [{request_id, RequestId},
+ {reason, Reason}]),
{error, Reason}
end.
@@ -498,9 +550,7 @@ return_answer(Options, {{"HTTP/0.9",_,_}, _, BinBody}) ->
{ok, Body};
return_answer(Options, {StatusLine, Headers, BinBody}) ->
-
Body = maybe_format_body(BinBody, Options),
-
case proplists:get_value(full_result, Options, true) of
true ->
{ok, {StatusLine, Headers, Body}};
@@ -593,8 +643,6 @@ http_options_default() ->
{ok, {?HTTP_DEFAULT_SSL_KIND, Value}};
({ssl, SslOptions}) when is_list(SslOptions) ->
{ok, {?HTTP_DEFAULT_SSL_KIND, SslOptions}};
- ({ossl, SslOptions}) when is_list(SslOptions) ->
- {ok, {ossl, SslOptions}};
({essl, SslOptions}) when is_list(SslOptions) ->
{ok, {essl, SslOptions}};
(_) ->
diff --git a/lib/inets/src/http_client/httpc_cookie.erl b/lib/inets/src/http_client/httpc_cookie.erl
index 4d61f82b5a..69900bae65 100644
--- a/lib/inets/src/http_client/httpc_cookie.erl
+++ b/lib/inets/src/http_client/httpc_cookie.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The 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,12 +18,32 @@
%%
%% Description: Cookie handling according to RFC 2109
+%% The syntax for the Set-Cookie response header is
+%%
+%% set-cookie = "Set-Cookie:" cookies
+%% cookies = 1#cookie
+%% cookie = NAME "=" VALUE *(";" cookie-av)
+%% NAME = attr
+%% VALUE = value
+%% cookie-av = "Comment" "=" value
+%% | "Domain" "=" value
+%% | "Max-Age" "=" value
+%% | "Path" "=" value
+%% | "Secure"
+%% | "Version" "=" 1*DIGIT
+
+
+%% application:start(inets).
+%% httpc:set_options([{cookies, enabled}, {proxy, {{"www-proxy.ericsson.se",8080}, ["*.ericsson.se"]}}]).
+%% (catch httpc:request("http://www.expedia.com")).
+
-module(httpc_cookie).
-include("httpc_internal.hrl").
-export([open_db/3, close_db/1, insert/2, header/4, cookies/3]).
-export([reset_db/1, which_cookies/1]).
+-export([image_of/2, print/2]).
-record(cookie_db, {db, session_db}).
@@ -125,7 +145,7 @@ insert(#cookie_db{db = Db} = CookieDb,
name = Name,
path = Path,
max_age = 0}) ->
- ?hcrt("insert", [{domain, Key}, {name, Name}, {path, Path}]),
+ ?hcrt("insert cookie", [{domain, Key}, {name, Name}, {path, Path}]),
Pattern = #http_cookie{domain = Key, name = Name, path = Path, _ = '_'},
case dets:match_object(Db, Pattern) of
[] ->
@@ -136,7 +156,7 @@ insert(#cookie_db{db = Db} = CookieDb,
ok;
insert(#cookie_db{db = Db} = CookieDb,
#http_cookie{domain = Key, name = Name, path = Path} = Cookie) ->
- ?hcrt("insert", [{cookie, Cookie}]),
+ ?hcrt("insert cookie", [{cookie, Cookie}]),
Pattern = #http_cookie{domain = Key,
name = Name,
path = Path,
@@ -163,6 +183,7 @@ header(CookieDb, Scheme, {Host, _}, Path) ->
[] ->
{"cookie", ""};
Cookies ->
+ %% print_cookies("Header Cookies", Cookies),
{"cookie", cookies_to_string(Scheme, Cookies)}
end.
@@ -173,11 +194,20 @@ header(CookieDb, Scheme, {Host, _}, Path) ->
%%--------------------------------------------------------------------
cookies(Headers, RequestPath, RequestHost) ->
+
?hcrt("cookies", [{headers, Headers},
{request_path, RequestPath},
{request_host, RequestHost}]),
+
Cookies = parse_set_cookies(Headers, {RequestPath, RequestHost}),
- accept_cookies(Cookies, RequestPath, RequestHost).
+
+ %% print_cookies("Parsed Cookies", Cookies),
+
+ AcceptedCookies = accept_cookies(Cookies, RequestPath, RequestHost),
+
+ %% print_cookies("Accepted Cookies", AcceptedCookies),
+
+ AcceptedCookies.
%%--------------------------------------------------------------------
@@ -266,7 +296,8 @@ cookies_to_string(_, [], CookieStrs) ->
lists:flatten(lists:reverse(CookieStrs))
end;
-cookies_to_string(https, [#http_cookie{secure = true} = Cookie| Cookies],
+cookies_to_string(https = Scheme,
+ [#http_cookie{secure = true} = Cookie| Cookies],
CookieStrs) ->
Str = case Cookies of
[] ->
@@ -274,7 +305,7 @@ cookies_to_string(https, [#http_cookie{secure = true} = Cookie| Cookies],
_ ->
cookie_to_string(Cookie) ++ "; "
end,
- cookies_to_string(https, Cookies, [Str | CookieStrs]);
+ cookies_to_string(Scheme, Cookies, [Str | CookieStrs]);
cookies_to_string(Scheme, [#http_cookie{secure = true}| Cookies],
CookieStrs) ->
@@ -303,63 +334,54 @@ add_domain(Str, #http_cookie{domain_default = true}) ->
add_domain(Str, #http_cookie{domain = Domain}) ->
Str ++ "; $Domain=" ++ Domain.
-parse_set_cookies(OtherHeaders, DefaultPathDomain) ->
- SetCookieHeaders =
- lists:foldl(fun({"set-cookie", Value}, Acc) ->
- [string:tokens(Value, ",")| Acc];
- (_, Acc) ->
- Acc
- end, [], OtherHeaders),
-
- lists:flatten(
- lists:map(fun(CookieHeader) ->
- NewHeader = fix_netscape_cookie(CookieHeader, []),
- parse_set_cookie(NewHeader, [], DefaultPathDomain)
- end,
- SetCookieHeaders)).
-
-parse_set_cookie([], AccCookies, _) ->
- AccCookies;
-parse_set_cookie([CookieHeader | CookieHeaders], AccCookies,
- Defaults = {DefaultPath, DefaultDomain}) ->
- [CookieStr | Attributes] = case string:tokens(CookieHeader, ";") of
- [CStr] ->
- [CStr, ""];
- [CStr | Attr] ->
- [CStr, Attr]
- end,
- Pos = string:chr(CookieStr, $=),
- Name = string:substr(CookieStr, 1, Pos - 1),
- Value = string:substr(CookieStr, Pos + 1),
- Cookie = #http_cookie{name = string:strip(Name),
- value = string:strip(Value)},
- NewAttributes = parse_set_cookie_attributes(Attributes),
- TmpCookie = cookie_attributes(NewAttributes, Cookie),
+parse_set_cookies(CookieHeaders, DefaultPathDomain) ->
+ SetCookieHeaders = [Value || {"set-cookie", Value} <- CookieHeaders],
+ Cookies = [parse_set_cookie(SetCookieHeader, DefaultPathDomain) ||
+ SetCookieHeader <- SetCookieHeaders],
+ %% print_cookies("Parsed Cookies", Cookies),
+ Cookies.
+
+parse_set_cookie(CookieHeader, {DefaultPath, DefaultDomain}) ->
+ %% io:format("Raw Cookie: ~s~n", [CookieHeader]),
+ Pos = string:chr(CookieHeader, $=),
+ Name = string:substr(CookieHeader, 1, Pos - 1),
+ {Value, Attrs} =
+ case string:substr(CookieHeader, Pos + 1) of
+ [$;|ValueAndAttrs] ->
+ {"", string:tokens(ValueAndAttrs, ";")};
+ ValueAndAttrs ->
+ [V | A] = string:tokens(ValueAndAttrs, ";"),
+ {V, A}
+ end,
+ Cookie = #http_cookie{name = string:strip(Name),
+ value = string:strip(Value)},
+ Attributes = parse_set_cookie_attributes(Attrs),
+ TmpCookie = cookie_attributes(Attributes, Cookie),
%% Add runtime defult values if necessary
- NewCookie = domain_default(path_default(TmpCookie, DefaultPath),
- DefaultDomain),
- parse_set_cookie(CookieHeaders, [NewCookie | AccCookies], Defaults).
-
-parse_set_cookie_attributes([]) ->
- [];
-parse_set_cookie_attributes([Attributes]) ->
- lists:map(fun(Attr) ->
- [AttrName, AttrValue] =
- case string:tokens(Attr, "=") of
- %% All attributes have the form
- %% Name=Value except "secure"!
- [Name] ->
- [Name, ""];
- [Name, Value] ->
- [Name, Value];
- %% Anything not expected will be
- %% disregarded
- _ ->
- ["Dummy",""]
- end,
- {http_util:to_lower(string:strip(AttrName)),
- string:strip(AttrValue)}
- end, Attributes).
+ NewCookie = domain_default(path_default(TmpCookie, DefaultPath),
+ DefaultDomain),
+ NewCookie.
+
+parse_set_cookie_attributes(Attributes) when is_list(Attributes) ->
+ [parse_set_cookie_attribute(A) || A <- Attributes].
+
+parse_set_cookie_attribute(Attribute) ->
+ {AName, AValue} =
+ case string:tokens(Attribute, "=") of
+ %% All attributes have the form
+ %% Name=Value except "secure"!
+ [Name] ->
+ {Name, ""};
+ [Name, Value] ->
+ {Name, Value};
+ %% Anything not expected will be
+ %% disregarded
+ _ ->
+ {"Dummy", ""}
+ end,
+ StrippedName = http_util:to_lower(string:strip(AName)),
+ StrippedValue = string:strip(AValue),
+ {StrippedName, StrippedValue}.
cookie_attributes([], Cookie) ->
Cookie;
@@ -375,10 +397,15 @@ cookie_attributes([{"max-age", Value}| Attributes], Cookie) ->
Cookie#http_cookie{max_age = ExpireTime});
%% Backwards compatibility with netscape cookies
cookie_attributes([{"expires", Value}| Attributes], Cookie) ->
- Time = http_util:convert_netscapecookie_date(Value),
- ExpireTime = calendar:datetime_to_gregorian_seconds(Time),
- cookie_attributes(Attributes,
- Cookie#http_cookie{max_age = ExpireTime});
+ try http_util:convert_netscapecookie_date(Value) of
+ Time ->
+ ExpireTime = calendar:datetime_to_gregorian_seconds(Time),
+ cookie_attributes(Attributes,
+ Cookie#http_cookie{max_age = ExpireTime})
+ catch
+ _:_ ->
+ cookie_attributes(Attributes, Cookie)
+ end;
cookie_attributes([{"path", Value}| Attributes], Cookie) ->
cookie_attributes(Attributes,
Cookie#http_cookie{path = Value});
@@ -404,7 +431,7 @@ path_default(#http_cookie{path = undefined} = Cookie, DefaultPath) ->
path_default(Cookie, _) ->
Cookie.
-%% Note: if the path is only / that / will be keept
+%% Note: if the path is only / that / will be kept
skip_right_most_slash("/") ->
"/";
skip_right_most_slash(Str) ->
@@ -476,20 +503,43 @@ path_sort(Cookies)->
lists:reverse(lists:keysort(#http_cookie.path, Cookies)).
-%% Informally, the Set-Cookie response header comprises the token
-%% Set-Cookie:, followed by a comma-separated list of one or more
-%% cookies. Netscape cookies expires attribute may also have a,
-%% in this case the header list will have been incorrectly split
-%% in parse_set_cookies/2 this functions fix that problem.
-fix_netscape_cookie([Cookie1, Cookie2 | Rest], Acc) ->
- case inets_regexp:match(string:to_lower(Cookie1), "expires=") of
- {_, _, _} ->
- fix_netscape_cookie(Rest, [Cookie1 ++ Cookie2 | Acc]);
- nomatch ->
- fix_netscape_cookie([Cookie2 |Rest], [Cookie1| Acc])
- end;
-fix_netscape_cookie([Cookie | Rest], Acc) ->
- fix_netscape_cookie(Rest, [Cookie | Acc]);
-
-fix_netscape_cookie([], Acc) ->
- Acc.
+%% print_cookies(Header, Cookies) ->
+%% io:format("~s:~n", [Header]),
+%% Prefix = " ",
+%% lists:foreach(fun(Cookie) -> print(Prefix, Cookie) end, Cookies).
+
+image_of(Prefix,
+ #http_cookie{domain = Domain,
+ domain_default = DomainDef,
+ name = Name,
+ value = Value,
+ comment = Comment,
+ max_age = MaxAge,
+ path = Path,
+ path_default = PathDef,
+ secure = Sec,
+ version = Version}) ->
+ lists:flatten(
+ io_lib:format("~sCookie ~s: "
+ "~n~s Value: ~p"
+ "~n~s Domain: ~p"
+ "~n~s DomainDef: ~p"
+ "~n~s Comment: ~p"
+ "~n~s MaxAge: ~p"
+ "~n~s Path: ~p"
+ "~n~s PathDef: ~p"
+ "~n~s Secure: ~p"
+ "~n~s Version: ~p",
+ [Prefix, Name,
+ Prefix, Value,
+ Prefix, Domain,
+ Prefix, DomainDef,
+ Prefix, Comment,
+ Prefix, MaxAge,
+ Prefix, Path,
+ Prefix, PathDef,
+ Prefix, Sec,
+ Prefix, Version])).
+
+print(Prefix, Cookie) when is_record(Cookie, http_cookie) ->
+ io:format("~s~n", [image_of(Prefix, Cookie)]).
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index cb6f3e2841..587e24cc8d 100644
--- a/lib/inets/src/http_client/httpc_handler.erl
+++ b/lib/inets/src/http_client/httpc_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The 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,10 +29,10 @@
%%--------------------------------------------------------------------
%% Internal Application API
-export([
- start_link/2,
- connect_and_send/2,
+ start_link/4,
+ %% connect_and_send/2,
send/2,
- cancel/2,
+ cancel/3,
stream/3,
stream_next/1,
info/1
@@ -51,7 +51,7 @@
-record(state,
{
request, % #request{}
- session, % #tcp_session{}
+ session, % #session{}
status_line, % {Version, StatusCode, ReasonPharse}
headers, % #http_response_h{}
body, % binary()
@@ -94,13 +94,9 @@
%%--------------------------------------------------------------------
%%--------------------------------------------------------------------
-start_link(Options, ProfileName) ->
- Args = [Options, ProfileName],
- gen_server:start_link(?MODULE, Args, []).
-
-connect_and_send(Request, HandlerPid) ->
- call({connect_and_send, Request}, HandlerPid).
-
+start_link(Parent, Request, Options, ProfileName) ->
+ {ok, proc_lib:start_link(?MODULE, init, [[Parent, Request, Options,
+ ProfileName]])}.
%%--------------------------------------------------------------------
%% Function: send(Request, Pid) -> ok
@@ -122,8 +118,8 @@ send(Request, Pid) ->
%% Description: Cancels a request. Intended to be called by the httpc
%% manager process.
%%--------------------------------------------------------------------
-cancel(RequestId, Pid) ->
- cast({cancel, RequestId}, Pid).
+cancel(RequestId, Pid, From) ->
+ cast({cancel, RequestId, From}, Pid).
%%--------------------------------------------------------------------
@@ -229,16 +225,27 @@ stream(BodyPart, Request,_) -> % only 200 and 206 responses can be streamed
%% but we do not want that so errors will be handled by the process
%% sending an init_error message to itself.
%%--------------------------------------------------------------------
-init([Options, ProfileName]) ->
- ?hcrv("init - starting", [{options, Options}, {profile, ProfileName}]),
+init([Parent, Request, Options, ProfileName]) ->
process_flag(trap_exit, true),
- handle_verbose(Options#options.verbose),
- State = #state{status = undefined,
- options = Options,
- profile_name = ProfileName},
- ?hcrd("init - started", []),
- {ok, State}.
+ %% Do not let initial tcp-connection block the manager-process
+ proc_lib:init_ack(Parent, self()),
+ handle_verbose(Options#options.verbose),
+ Address = handle_proxy(Request#request.address, Options#options.proxy),
+ {ok, State} =
+ case {Address /= Request#request.address, Request#request.scheme} of
+ {true, https} ->
+ Error = https_through_proxy_is_not_currently_supported,
+ self() ! {init_error,
+ Error, httpc_response:error(Request, Error)},
+ {ok, #state{request = Request, options = Options,
+ status = ssl_tunnel}};
+ {_, _} ->
+ connect_and_send_first_request(Address, Request,
+ #state{options = Options,
+ profile_name = ProfileName})
+ end,
+ gen_server:enter_loop(?MODULE, [], State).
%%--------------------------------------------------------------------
%% Function: handle_call(Request, From, State) -> {reply, Reply, State} |
@@ -249,41 +256,6 @@ init([Options, ProfileName]) ->
%% {stop, Reason, State} (terminate/2 is called)
%% Description: Handling call messages
%%--------------------------------------------------------------------
-
-
-%% This is the first request, the reason the proc was started
-handle_call({connect_and_send, #request{address = Address0,
- scheme = Scheme} = Request},
- _From,
- #state{options = #options{proxy = Proxy},
- status = undefined,
- session = undefined} = State) ->
- ?hcrv("connect and send", [{address0, Address0}, {proxy, Proxy}]),
- Address = handle_proxy(Address0, Proxy),
- if
- ((Address =/= Address0) andalso (Scheme =:= https)) ->
- %% This is what we should do if and when ssl supports
- %% "socket upgrading"
- %%send_ssl_tunnel_request(Address, Request,
- %% #state{options = Options,
- %% status = ssl_tunnel});
- Reason = {failed_connecting,
- https_through_proxy_is_not_currently_supported},
- %% Send a reply to the original caller
- ErrorResponse = httpc_response:error(Request, Reason),
- httpc_response:send(Request#request.from, ErrorResponse),
- %% Reply to the manager
- ErrorReply = {error, Reason},
- {stop, normal, ErrorReply, State};
- true ->
- case connect_and_send_first_request(Address, Request, State) of
- {ok, NewState} ->
- {reply, ok, NewState};
- {stop, Error, NewState} ->
- {stop, normal, Error, NewState}
- end
- end;
-
handle_call(#request{address = Addr} = Request, _,
#state{status = Status,
session = #session{type = pipeline} = Session,
@@ -445,25 +417,27 @@ handle_call(info, _, State) ->
%% handle_keep_alive_queue/2 on the other hand will just skip the
%% request as if it was never issued as in this case the request will
%% not have been sent.
-handle_cast({cancel, RequestId},
+handle_cast({cancel, RequestId, From},
#state{request = #request{id = RequestId} = Request,
profile_name = ProfileName,
canceled = Canceled} = State) ->
?hcrv("cancel current request", [{request_id, RequestId},
{profile, ProfileName},
{canceled, Canceled}]),
- httpc_manager:request_canceled(RequestId, ProfileName),
+ httpc_manager:request_canceled(RequestId, ProfileName, From),
?hcrv("canceled", []),
{stop, normal,
State#state{canceled = [RequestId | Canceled],
request = Request#request{from = answer_sent}}};
-handle_cast({cancel, RequestId},
+handle_cast({cancel, RequestId, From},
#state{profile_name = ProfileName,
+ request = #request{id = CurrId},
canceled = Canceled} = State) ->
- ?hcrv("cancel", [{request_id, RequestId},
+ ?hcrv("cancel", [{request_id, RequestId},
+ {curr_req_id, CurrId},
{profile, ProfileName},
{canceled, Canceled}]),
- httpc_manager:request_canceled(RequestId, ProfileName),
+ httpc_manager:request_canceled(RequestId, ProfileName, From),
?hcrv("canceled", []),
{noreply, State#state{canceled = [RequestId | Canceled]}};
@@ -541,7 +515,7 @@ handle_info({Proto, _Socket, Data},
{stop, normal, NewState}
end,
- ?hcri("data processed", []),
+ ?hcri("data processed", [{final_result, FinalResult}]),
FinalResult;
@@ -655,8 +629,9 @@ handle_info(timeout_queue, #state{timers = Timers} = State) ->
Timers#timers{queue_timer = undefined}}};
%% Setting up the connection to the server somehow failed.
-handle_info({init_error, _, ClientErrMsg},
+handle_info({init_error, Tag, ClientErrMsg},
State = #state{request = Request}) ->
+ ?hcrv("init error", [{tag, Tag}, {client_error, ClientErrMsg}]),
NewState = answer_request(Request, ClientErrMsg, State),
{stop, normal, NewState};
@@ -733,9 +708,9 @@ terminate(normal,
%% And, just in case, close our side (**really** overkill)
http_transport:close(SocketType, Socket);
-terminate(Reason, #state{session = #session{id = Id,
- socket = Socket,
- socket_type = SocketType},
+terminate(Reason, #state{session = #session{id = Id,
+ socket = Socket,
+ socket_type = SocketType},
request = undefined,
profile_name = ProfileName,
timers = Timers,
@@ -872,62 +847,55 @@ connect(SocketType, ToAddress,
Opts3 = [IpFamily | Opts2],
http_transport:connect(SocketType, ToAddress, Opts3, Timeout)
end.
-
-connect_and_send_first_request(Address,
- #request{settings = Settings,
- headers = Headers,
- address = OrigAddress,
- scheme = Scheme} = Request,
- #state{options = Options} = State) ->
-
- ?hcrd("connect",
- [{address, Address}, {request, Request}, {options, Options}]),
+connect_and_send_first_request(Address, Request, #state{options = Options} = State) ->
SocketType = socket_type(Request),
- ConnTimeout = Settings#http_options.connect_timeout,
+ ConnTimeout = (Request#request.settings)#http_options.connect_timeout,
+ ?hcri("connect",
+ [{address, Address}, {request, Request}, {options, Options}]),
case connect(SocketType, Address, Options, ConnTimeout) of
{ok, Socket} ->
- Session = #session{id = {OrigAddress, self()},
- scheme = Scheme,
- socket = Socket,
- socket_type = SocketType},
- ?hcrd("connected - now send first request", [{socket, Socket}]),
+ ClientClose =
+ httpc_request:is_client_closing(
+ Request#request.headers),
+ SessionType = httpc_manager:session_type(Options),
+ SocketType = socket_type(Request),
+ Session = #session{id = {Request#request.address, self()},
+ scheme = Request#request.scheme,
+ socket = Socket,
+ socket_type = SocketType,
+ client_close = ClientClose,
+ type = SessionType},
+ ?hcri("connected - now send first request", [{socket, Socket}]),
+
case httpc_request:send(Address, Session, Request) of
ok ->
- ?hcrd("first request sent", []),
- ClientClose =
- httpc_request:is_client_closing(Headers),
- SessionType = httpc_manager:session_type(Options),
- Session2 =
- Session#session{client_close = ClientClose,
- type = SessionType},
- TmpState =
- State#state{request = Request,
- session = Session2,
- mfa = init_mfa(Request, State),
- status_line = init_status_line(Request),
- headers = undefined,
- body = undefined,
- status = new},
- ?hcrt("activate socket", []),
- activate_once(Session),
+ ?hcri("first request sent", []),
+ TmpState = State#state{request = Request,
+ session = Session,
+ mfa = init_mfa(Request, State),
+ status_line =
+ init_status_line(Request),
+ headers = undefined,
+ body = undefined,
+ status = new},
+ http_transport:setopts(SocketType,
+ Socket, [{active, once}]),
NewState = activate_request_timeout(TmpState),
{ok, NewState};
-
- {error, Reason} = Error ->
- ?hcrv("failed sending request", [{reason, Reason}]),
- {stop, Error,
- State#state{session = {send_failed, Reason},
- request = Request}}
+ {error, Reason} ->
+ self() ! {init_error, error_sending,
+ httpc_response:error(Request, Reason)},
+ {ok, State#state{request = Request,
+ session =
+ #session{socket = Socket}}}
end;
-
- {error, Reason} = Error ->
- ?hcri("connect failed", [{reason, Reason}]),
- {stop, Error, State#state{session = {connect_failed, Reason},
- request = Request}}
+ {error, Reason} ->
+ self() ! {init_error, error_connecting,
+ httpc_response:error(Request, Reason)},
+ {ok, State#state{request = Request}}
end.
-
handler_info(#state{request = Request,
session = Session,
status_line = _StatusLine,
@@ -1167,12 +1135,12 @@ handle_response(#state{request = Request,
{ok, Msg, Data} ->
?hcrd("handle response - ok", []),
end_stream(StatusLine, Request),
- NewState = answer_request(Request, Msg, State),
+ NewState = maybe_send_answer(Request, Msg, State),
handle_queue(NewState, Data);
{stop, Msg} ->
?hcrd("handle response - stop", [{msg, Msg}]),
end_stream(StatusLine, Request),
- NewState = answer_request(Request, Msg, State),
+ NewState = maybe_send_answer(Request, Msg, State),
{stop, normal, NewState}
end.
@@ -1189,7 +1157,7 @@ handle_cookies(Headers, Request, #options{cookies = enabled}, ProfileName) ->
httpc_manager:store_cookies(Cookies, Request#request.address,
ProfileName).
-%% This request could not be pipelined or used as sequential keept alive
+%% This request could not be pipelined or used as sequential keep alive
%% queue
handle_queue(#state{status = close} = State, _) ->
{stop, normal, State};
@@ -1242,7 +1210,8 @@ handle_pipeline(#state{status = pipeline,
%% See comment for handle_cast({cancel, RequestId})
{stop, normal,
State#state{request =
- NextRequest#request{from = answer_sent}}};
+ NextRequest#request{from = answer_sent},
+ pipeline = Pipeline}};
false ->
?hcrv("next request", [{request, NextRequest}]),
NewSession =
@@ -1435,7 +1404,7 @@ try_to_enable_pipeline_or_keep_alive(
answer_request(#request{id = RequestId, from = From} = Request, Msg,
#state{timers = Timers, profile_name = ProfileName} = State) ->
- ?hcrt("answer request", [{request, Request}]),
+ ?hcrt("answer request", [{request, Request}, {msg, Msg}]),
httpc_response:send(From, Msg),
RequestTimers = Timers#timers.request_timers,
TimerRef =
@@ -1443,6 +1412,7 @@ answer_request(#request{id = RequestId, from = From} = Request, Msg,
Timer = {RequestId, TimerRef},
cancel_timer(TimerRef, {timeout, Request#request.id}),
httpc_manager:request_done(RequestId, ProfileName),
+
State#state{request = Request#request{from = answer_sent},
timers =
Timers#timers{request_timers =
@@ -1662,71 +1632,28 @@ handle_verbose(_) ->
ok.
-%%% Normaly I do not comment out code, I throw it away. But this might
-%%% actually be used one day if ssl is improved.
-%% send_ssl_tunnel_request(Address, Request = #request{address = {Host, Port}},
-%% State) ->
-%% %% A ssl tunnel request is a special http request that looks like
-%% %% CONNECT host:port HTTP/1.1
-%% SslTunnelRequest = #request{method = connect, scheme = http,
-%% headers =
-%% #http_request_h{
-%% host = Host,
-%% address = Address,
-%% path = Host ++ ":",
-%% pquery = integer_to_list(Port),
-%% other = [{ "Proxy-Connection", "keep-alive"}]},
-%% Ipv6 = (State#state.options)#options.ipv6,
-%% SocketType = socket_type(SslTunnelRequest),
-%% case http_transport:connect(SocketType,
-%% SslTunnelRequest#request.address, Ipv6) of
-%% {ok, Socket} ->
-%% case httpc_request:send(Address, SslTunnelRequest, Socket) of
-%% ok ->
-%% Session = #tcp_session{id =
-%% {SslTunnelRequest#request.address,
-%% self()},
-%% scheme =
-%% SslTunnelRequest#request.scheme,
-%% socket = Socket},
-%% NewState = State#state{mfa =
-%% {httpc_response, parse,
-%% [State#state.max_header_size]},
-%% request = Request,
-%% session = Session},
-%% http_transport:setopts(socket_type(
-%% SslTunnelRequest#request.scheme),
-%% Socket,
-%% [{active, once}]),
-%% {ok, NewState};
-%% {error, Reason} ->
-%% self() ! {init_error, error_sending,
-%% httpc_response:error(Request, Reason)},
-%% {ok, State#state{request = Request,
-%% session = #tcp_session{socket =
-%% Socket}}}
-%% end;
-%% {error, Reason} ->
-%% self() ! {init_error, error_connecting,
-%% httpc_response:error(Request, Reason)},
-%% {ok, State#state{request = Request}}
-%% end.
-
-%% d(F) ->
-%% d(F, []).
-
-%% d(F, A) ->
-%% d(get(dbg), F, A).
-
-%% d(true, F, A) ->
-%% io:format(user, "~w:~w:" ++ F ++ "~n", [self(), ?MODULE | A]);
-%% d(_, _, _) ->
-%% ok.
-
+send_raw(#session{socket = Socket, socket_type = SocketType},
+ {ProcessBody, Acc}) when is_function(ProcessBody, 1) ->
+ ?hcrt("send raw", [{acc, Acc}]),
+ send_raw(SocketType, Socket, ProcessBody, Acc);
send_raw(#session{socket = Socket, socket_type = SocketType}, Body) ->
http_transport:send(SocketType, Socket, Body).
+send_raw(SocketType, Socket, ProcessBody, Acc) ->
+ case ProcessBody(Acc) of
+ eof ->
+ ok;
+ {ok, Data, NewAcc} ->
+ DataBin = iolist_to_binary(Data),
+ ?hcrd("send", [{data, DataBin}]),
+ case http_transport:send(SocketType, Socket, DataBin) of
+ ok ->
+ send_raw(SocketType, Socket, ProcessBody, NewAcc);
+ Error ->
+ Error
+ end
+ end.
call(Msg, Pid) ->
@@ -1738,11 +1665,5 @@ call(Msg, Pid, Timeout) ->
cast(Msg, Pid) ->
gen_server:cast(Pid, Msg).
-
-%% to(To, Start) when is_integer(Start) andalso (Start >= 0) ->
-%% http_util:timeout(To, Start);
-%% to(To, _Start) ->
-%% http_util:timeout(To, t()).
-
t() ->
http_util:timestamp().
diff --git a/lib/inets/src/http_client/httpc_handler_sup.erl b/lib/inets/src/http_client/httpc_handler_sup.erl
index 2a69fd15d0..f7a0b014b3 100644
--- a/lib/inets/src/http_client/httpc_handler_sup.erl
+++ b/lib/inets/src/http_client/httpc_handler_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The 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,7 +23,7 @@
%% API
-export([start_link/0]).
--export([start_child/2]).
+-export([start_child/1]).
%% Supervisor callback
-export([init/1]).
@@ -34,11 +34,9 @@
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
-start_child(Options, Profile) ->
- Args = [Options, Profile],
+start_child(Args) ->
supervisor:start_child(?MODULE, Args).
-
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl
index 591cb78c29..9015bf1ce2 100644
--- a/lib/inets/src/http_client/httpc_manager.erl
+++ b/lib/inets/src/http_client/httpc_manager.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The 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 @@
start_link/3,
request/2,
cancel_request/2,
- request_canceled/2,
+ request_canceled/3,
request_done/2,
retry_request/2,
redirect_request/2,
@@ -52,7 +52,7 @@
cancel = [], % [{RequestId, HandlerPid, ClientPid}]
handler_db, % ets() - Entry: #handler_info{}
cookie_db, % cookie_db()
- session_db, % ets() - Entry: #tcp_session{}
+ session_db, % ets() - Entry: #session{}
profile_name, % atom()
options = #options{}
}).
@@ -66,6 +66,7 @@
state % State of the handler: initiating | started | operational | canceled
}).
+-define(DELAY, 500).
%%====================================================================
%% Internal Application API
@@ -158,7 +159,8 @@ cancel_request(RequestId, ProfileName) ->
%% be called by the httpc handler process.
%%--------------------------------------------------------------------
-request_canceled(RequestId, ProfileName) ->
+request_canceled(RequestId, ProfileName, From) ->
+ gen_server:reply(From, ok),
cast(ProfileName, {request_canceled, RequestId}).
@@ -176,7 +178,7 @@ request_done(RequestId, ProfileName) ->
%%--------------------------------------------------------------------
%% Function: insert_session(Session, ProfileName) -> _
-%% Session - #tcp_session{}
+%% Session - #session{}
%% ProfileName - atom()
%%
%% Description: Inserts session information into the httpc manager
@@ -355,44 +357,32 @@ do_init(ProfileName, CookiesDir) ->
%% {stop, Reason, State} (terminate/2 is called)
%% Description: Handling call messages
%%--------------------------------------------------------------------
-handle_call({request, Request}, _From, State) ->
- ?hcrv("request", [{request, Request}]),
+handle_call({request, Request}, _, State) ->
+ ?hcri("request", [{request, Request}]),
case (catch handle_request(Request, State)) of
- {ok, ReqId, NewState} ->
- {reply, {ok, ReqId}, NewState};
-
+ {reply, Msg, NewState} ->
+ {reply, Msg, NewState};
Error ->
- NewError = {error, {failed_process_request, Error}},
- {reply, NewError, State}
+ {stop, Error, httpc_response:error(Request, Error), State}
end;
-
-handle_call({cancel_request, RequestId}, From,
- #state{handler_db = HandlerDb} = State) ->
- ?hcrv("cancel_request", [{request_id, RequestId}]),
+
+handle_call({cancel_request, RequestId}, From, State) ->
+ ?hcri("cancel_request", [{request_id, RequestId}]),
case ets:lookup(State#state.handler_db, RequestId) of
[] ->
- ?hcrd("nothing to cancel", []),
- Reply = ok, %% Nothing to cancel
- {reply, Reply, State};
-
- [#handler_info{handler = Pid}] when is_pid(Pid) ->
- ?hcrd("found operational handler for this request",
- [{handler, Pid}]),
- httpc_handler:cancel(RequestId, Pid),
- {noreply, State#state{cancel =
- [{RequestId, Pid, From} |
- State#state.cancel]}};
-
- [#handler_info{starter = Pid, state = HandlerState}]
- when is_pid(Pid) ->
- ?hcri("found *initiating* handler for this request",
- [{starter, Pid}, {state, HandlerState}]),
- ets:update_element(HandlerDb, RequestId,
- {#handler_info.state, canceled}),
+ %% The request has allready compleated make sure
+ %% it is deliverd to the client process queue so
+ %% it can be thrown away by httpc:cancel_request
+ %% This delay is hopfully a temporary workaround.
+ %% Note that it will not not delay the manager,
+ %% only the client that called httpc:cancel_request
+ timer:apply_after(?DELAY, gen_server, reply, [From, ok]),
+ {noreply, State};
+ [{_, Pid, _}] ->
+ httpc_handler:cancel(RequestId, Pid, From),
{noreply, State#state{cancel =
- [{RequestId, Pid, From} |
+ [{RequestId, Pid, From} |
State#state.cancel]}}
-
end;
handle_call(reset_cookies, _, #state{cookie_db = CookieDb} = State) ->
@@ -437,43 +427,16 @@ handle_call(Req, From, #state{profile_name = ProfileName} = State) ->
%%--------------------------------------------------------------------
handle_cast({retry_or_redirect_request, {Time, Request}},
#state{profile_name = ProfileName} = State) ->
- ?hcrv("retry or redirect request", [{time, Time}, {request, Request}]),
- case timer:apply_after(Time, ?MODULE, retry_request,
- [Request, ProfileName]) of
- {ok, _} ->
- {noreply, State};
- {error, Reason} ->
- error_report(ProfileName,
- "failed scheduling retry/redirect request"
- "~n Time: ~p"
- "~n Request: ~p"
- "~n Reason: ~p", [Time, Request, Reason]),
- {noreply, State}
- end;
+ {ok, _} = timer:apply_after(Time, ?MODULE, retry_request, [Request, ProfileName]),
+ {noreply, State};
-handle_cast({retry_or_redirect_request, Request},
- #state{profile_name = Profile,
- handler_db = HandlerDb} = State) ->
- ?hcrv("retry or redirect request", [{request, Request}]),
+handle_cast({retry_or_redirect_request, Request}, State) ->
case (catch handle_request(Request, State)) of
- {ok, _, NewState} ->
+ {reply, {ok, _}, NewState} ->
{noreply, NewState};
-
Error ->
- ReqId = Request#request.id,
- error_report(Profile,
- "failed to retry or redirect request ~p"
- "~n Error: ~p", [ReqId, Error]),
- case ets:lookup(HandlerDb, ReqId) of
- [#handler_info{from = From}] ->
- Error2 = httpc_response:error(Request, Error),
- httpc_response:send(From, Error2),
- ok;
-
- _ ->
- ok
- end,
- {noreply, State}
+ httpc_response:error(Request, Error),
+ {stop, Error, State}
end;
handle_cast({request_canceled, RequestId}, State) ->
@@ -482,7 +445,6 @@ handle_cast({request_canceled, RequestId}, State) ->
case lists:keysearch(RequestId, 1, State#state.cancel) of
{value, Entry = {RequestId, _, From}} ->
?hcrt("found in cancel", [{from, From}]),
- gen_server:reply(From, ok),
{noreply,
State#state{cancel = lists:delete(Entry, State#state.cancel)}};
Else ->
@@ -539,8 +501,6 @@ handle_cast(Msg, #state{profile_name = ProfileName} = State) ->
"recived unknown message"
"~n Msg: ~p", [Msg]),
{noreply, State}.
-
-
%%--------------------------------------------------------------------
%% Function: handle_info(Info, State) -> {noreply, State} |
@@ -548,39 +508,17 @@ handle_cast(Msg, #state{profile_name = ProfileName} = State) ->
%% {stop, Reason, State} (terminate/2 is called)
%% Description: Handling all non call/cast messages
%%---------------------------------------------------------
-
-handle_info({started, StarterPid, ReqId, HandlerPid}, State) ->
- handle_started(StarterPid, ReqId, HandlerPid, State),
- {noreply, State};
-
-handle_info({connect_and_send, StarterPid, ReqId, HandlerPid, Res}, State) ->
- handle_connect_and_send(StarterPid, ReqId, HandlerPid, Res, State),
- {noreply, State};
-
-handle_info({failed_starting_handler, StarterPid, ReqId, Res}, State) ->
- handle_failed_starting_handler(StarterPid, ReqId, Res, State),
- {noreply, State};
-
-handle_info({'EXIT', Pid, Reason}, #state{handler_db = HandlerDb} = State) ->
- maybe_handle_terminating_starter(Pid, Reason, HandlerDb),
+handle_info({'EXIT', _, _}, State) ->
+ %% Handled in DOWN
{noreply, State};
-
handle_info({'DOWN', _, _, Pid, _}, State) ->
-
- %%
- %% 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, _ = '_'},
- ets:match_delete(State#state.handler_db, Pattern),
+ ets:match_delete(State#state.handler_db, {'_', Pid, '_'}),
%% If there where any canceled request, handled by the
%% the process that now has terminated, the
%% cancelation can be viewed as sucessfull!
- NewCanceledList =
- lists:foldl(fun({_, HandlerPid, From} = Entry, Acc) ->
+ NewCanceldList =
+ lists:foldl(fun(Entry = {_, HandlerPid, From}, Acc) ->
case HandlerPid of
Pid ->
gen_server:reply(From, ok),
@@ -589,15 +527,13 @@ handle_info({'DOWN', _, _, Pid, _}, State) ->
Acc
end
end, State#state.cancel, State#state.cancel),
- {noreply, State#state{cancel = NewCanceledList}};
-
-handle_info(Info, #state{profile_name = ProfileName} = State) ->
- error_report(ProfileName,
- "received unknown info"
- "~n Info: ~p", [Info]),
+ {noreply, State#state{cancel = NewCanceldList}};
+handle_info(Info, State) ->
+ Report = io_lib:format("Unknown message in "
+ "httpc_manager:handle_info ~p~n", [Info]),
+ error_logger:error_report(Report),
{noreply, State}.
-
%%--------------------------------------------------------------------
%% Function: terminate(Reason, State) -> _ (ignored by gen_server)
%% Description: Shutdown the httpc_handler
@@ -655,230 +591,85 @@ get_handler_info(Tab) ->
{Pid, State} <- Handlers2],
Handlers3.
-
-%%
-%% The request handler process is started asynchronously by a
-%% "starter process". When the handler has sucessfully been started,
-%% this message (started) is sent.
-%%
-
-handle_started(StarterPid, ReqId, HandlerPid,
- #state{profile_name = Profile,
- handler_db = HandlerDb}) ->
- 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),
- ok;
-
- [#handler_info{state = State}] ->
- error_report(Profile,
- "unexpected (started) message for handler (~p) in state "
- "~p regarding request ~p - ignoring", [HandlerPid, State, ReqId]),
- ?hcri("received unexpected started message", [{state, State}]),
- ok;
-
- [] ->
- error_report(Profile,
- "unknown handler ~p (~p) started for request ~w - canceling",
- [HandlerPid, StarterPid, ReqId]),
- httpc_handler:cancel(ReqId, HandlerPid)
- end.
-
-
-%%
-%% The request handler process is started asynchronously by a
-%% "starter process". When that process terminates it sends
-%% one of two messages. These ara handled by the two functions
-%% below.
-%%
-
-handle_connect_and_send(_StarterPid, ReqId, HandlerPid, Result,
- #state{profile_name = Profile,
- handler_db = HandlerDb}) ->
- case ets:lookup(HandlerDb, ReqId) of
- [#handler_info{state = started} = HandlerInfo] when Result =:= ok ->
- ?hcri("received connect-and-send ack for started handler", []),
- HandlerInfo2 = HandlerInfo#handler_info{starter = undefined,
- handler = HandlerPid,
- state = operational},
- ets:insert(HandlerDb, HandlerInfo2),
- ok;
-
- [#handler_info{state = canceled} = HandlerInfo] when Result =:= ok ->
- ?hcri("received connect-and-send ack for canceled handler", []),
- httpc_handler:cancel(ReqId, HandlerPid),
- HandlerInfo2 = HandlerInfo#handler_info{starter = undefined,
- handler = HandlerPid},
- ets:insert(HandlerDb, HandlerInfo2),
- ok;
-
- [#handler_info{state = State}] when Result =/= ok ->
- error_report(Profile,
- "handler (~p, ~w) failed to connect and/or "
- "send request ~p"
- "~n Result: ~p",
- [HandlerPid, State, ReqId, Result]),
- ?hcri("received connect-and-send error",
- [{result, Result}, {state, State}]),
- %% We don't need to send a response to the original caller
- %% because the handler already sent one in its terminate
- %% function.
- ets:delete(HandlerDb, ReqId),
- ok;
-
- [] ->
- ?hcri("handler successfully started "
- "for unknown request => canceling",
- [{profile, Profile},
- {handler, HandlerPid},
- {request, ReqId}]),
- httpc_handler:cancel(ReqId, HandlerPid)
- end.
-
-
-handle_failed_starting_handler(_StarterPid, ReqId, Error,
- #state{profile_name = Profile,
- handler_db = HandlerDb}) ->
- case ets:lookup(HandlerDb, ReqId) of
- [#handler_info{state = canceled}] ->
- error_report(Profile,
- "failed starting handler for request ~p"
- "~n Error: ~p", [ReqId, Error]),
- request_canceled(Profile, ReqId), % Fake signal from handler
- ets:delete(HandlerDb, ReqId),
- ok;
-
- [#handler_info{from = From}] ->
- error_report(Profile,
- "failed starting handler for request ~p"
- "~n Error: ~p", [ReqId, Error]),
- Reason2 =
- case Error of
- {error, Reason} ->
- {failed_connecting, Reason};
- _ ->
- {failed_connecting, Error}
- end,
- DummyReq = #request{id = ReqId},
- httpc_response:send(From, httpc_response:error(DummyReq, Reason2)),
- ets:delete(HandlerDb, ReqId),
- ok;
-
- [] ->
- error_report(Profile,
- "failed starting handler for unknown request ~p"
- "~n Error: ~p", [ReqId, Error]),
- ok
- end.
-
-
-maybe_handle_terminating_starter(MeybeStarterPid, Reason, HandlerDb) ->
- Pattern = #handler_info{starter = MeybeStarterPid, _ = '_'},
- case ets:match_object(HandlerDb, Pattern) of
- [#handler_info{id = ReqId, from = From, state = initiating}] ->
- %% The starter process crashed before it could start the
- %% the handler process, therefor we need to answer the
- %% original caller.
- ?hcri("starter process crashed bfore starting handler",
- [{starter, MeybeStarterPid}, {reason, Reason}]),
- Reason2 =
- case Reason of
- {error, Error} ->
- {failed_connecting, Error};
- _ ->
- {failed_connecting, Reason}
- end,
- DummyReq = #request{id = ReqId},
- httpc_response:send(From, httpc_response:error(DummyReq, Reason2)),
- ets:delete(HandlerDb, ReqId),
- ok;
-
- [#handler_info{state = State} = HandlerInfo] ->
- %% The starter process crashed after the handler was started.
- %% The handler will answer to the original caller.
- ?hcri("starter process crashed after starting handler",
- [{starter, MeybeStarterPid}, {reason, Reason}, {state, State}]),
- HandlerInfo2 = HandlerInfo#handler_info{starter = undefined},
- ets:insert(HandlerDb, HandlerInfo2),
- ok;
-
- _ ->
- ok
- end.
-
-
-%% -----
-%% Act as an HTTP/0.9 client that does not know anything
-%% about persistent connections
handle_request(#request{settings =
- #http_options{version = "HTTP/0.9"}} = Request0,
+ #http_options{version = "HTTP/0.9"}} = Request,
State) ->
- Request1 = handle_cookies(generate_request_id(Request0), State),
- Hdrs0 = Request1#request.headers,
- Hdrs1 = Hdrs0#http_request_h{connection = undefined},
- Request2 = Request1#request{headers = Hdrs1},
- create_handler_starter(Request2, State),
- {ok, Request2#request.id, State};
-
-%% -----
-%% Act as an HTTP/1.0 client that does not
-%% use persistent connections
+ %% Act as an HTTP/0.9 client that does not know anything
+ %% about persistent connections
+
+ NewRequest = handle_cookies(generate_request_id(Request), State),
+ NewHeaders =
+ (NewRequest#request.headers)#http_request_h{connection
+ = undefined},
+ start_handler(NewRequest#request{headers = NewHeaders}, State),
+ {reply, {ok, NewRequest#request.id}, State};
+
handle_request(#request{settings =
- #http_options{version = "HTTP/1.0"}} = Request0,
+ #http_options{version = "HTTP/1.0"}} = Request,
State) ->
- Request1 = handle_cookies(generate_request_id(Request0), State),
- Hdrs0 = Request1#request.headers,
- Hdrs1 = Hdrs0#http_request_h{connection = "close"},
- Request2 = Request1#request{headers = Hdrs1},
- create_handler_starter(Request2, State),
- {ok, Request2#request.id, State};
-
-
-%% -----
-handle_request(#request{method = Method,
- address = Address,
- scheme = Scheme} = Request0,
- #state{options = Opts} = State) ->
- Request1 = handle_cookies(generate_request_id(Request0), State),
- SessionType = session_type(Opts),
- case select_session(Method, Address, Scheme, SessionType, State) of
+ %% Act as an HTTP/1.0 client that does not
+ %% use persistent connections
+
+ NewRequest = handle_cookies(generate_request_id(Request), State),
+ NewHeaders =
+ (NewRequest#request.headers)#http_request_h{connection
+ = "close"},
+ start_handler(NewRequest#request{headers = NewHeaders}, State),
+ {reply, {ok, NewRequest#request.id}, State};
+
+handle_request(Request, State = #state{options = Options}) ->
+
+ NewRequest = handle_cookies(generate_request_id(Request), State),
+ SessionType = session_type(Options),
+ case select_session(Request#request.method,
+ Request#request.address,
+ Request#request.scheme, SessionType, State) of
{ok, HandlerPid} ->
- pipeline_or_keep_alive(Request1, HandlerPid, State);
+ pipeline_or_keep_alive(NewRequest, HandlerPid, State);
no_connection ->
- create_handler_starter(Request1, State);
- {no_session, OpenSessions}
- when OpenSessions < Opts#options.max_sessions ->
- create_handler_starter(Request1, State);
+ start_handler(NewRequest, State);
+ {no_session, OpenSessions} when OpenSessions
+ < Options#options.max_sessions ->
+ start_handler(NewRequest, State);
{no_session, _} ->
%% Do not start any more persistent connections
%% towards this server.
- Hdrs0 = Request1#request.headers,
- Hdrs1 = Hdrs0#http_request_h{connection = "close"},
- Request2 = Request1#request{headers = Hdrs1},
- create_handler_starter(Request2, State)
+ NewHeaders =
+ (NewRequest#request.headers)#http_request_h{connection
+ = "close"},
+ start_handler(NewRequest#request{headers = NewHeaders}, State)
end,
- {ok, Request1#request.id, State}.
+ {reply, {ok, NewRequest#request.id}, State}.
+
+
+start_handler(Request, State) ->
+ {ok, Pid} =
+ case is_inets_manager() of
+ true ->
+ httpc_handler_sup:start_child([whereis(httpc_handler_sup),
+ Request, State#state.options,
+ State#state.profile_name]);
+ false ->
+ httpc_handler:start_link(self(), Request, State#state.options,
+ State#state.profile_name)
+ end,
+ ets:insert(State#state.handler_db, {Request#request.id,
+ Pid, Request#request.from}),
+ erlang:monitor(process, Pid).
select_session(Method, HostPort, Scheme, SessionType,
#state{options = #options{max_pipeline_length = MaxPipe,
max_keep_alive_length = MaxKeepAlive},
session_db = SessionDb}) ->
- ?hcrd("select session", [{session_type, SessionType},
- {max_pipeline_length, MaxPipe},
+ ?hcrd("select session", [{session_type, SessionType},
+ {max_pipeline_length, MaxPipe},
{max_keep_alive_length, MaxKeepAlive}]),
case httpc_request:is_idempotent(Method) orelse
(SessionType =:= keep_alive) of
true ->
%% Look for handlers connecting to this host (HostPort)
- %% tcp_session with record name field (tcp_session) and
+ %% session with record name field (session) and
%% socket fields ignored. The fields id (part of: HostPort),
%% client_close, scheme and type specified.
%% The fields id (part of: HandlerPid) and queue_length
@@ -918,92 +709,17 @@ select_session(Candidates, Max) ->
?hcrd("select session - found one", [{handler, HandlerPid}]),
{ok, HandlerPid}
end.
-
-pipeline_or_keep_alive(#request{id = Id} = Request, HandlerPid, State) ->
- ?hcrd("pipeline of keep-alive", [{id, Id}, {handler, HandlerPid}]),
+
+pipeline_or_keep_alive(Request, HandlerPid, State) ->
case (catch httpc_handler:send(Request, HandlerPid)) of
ok ->
- ?hcrd("pipeline or keep-alive - successfully sent", []),
- Entry = #handler_info{id = Id,
- handler = HandlerPid,
- state = operational},
- ets:insert(State#state.handler_db, Entry);
-
- _ -> %% timeout pipelining failed
- ?hcrd("pipeline or keep-alive - failed sending -> "
- "start a new handler", []),
- create_handler_starter(Request, State)
+ ets:insert(State#state.handler_db, {Request#request.id,
+ HandlerPid,
+ Request#request.from});
+ _ -> %timeout pipelining failed
+ start_handler(Request, State)
end.
-
-create_handler_starter(#request{socket_opts = SocketOpts} = Request,
- #state{options = Options} = State)
- when is_list(SocketOpts) ->
- %% The user provided us with (override) socket options
- ?hcrt("create handler starter", [{socket_opts, SocketOpts}, {options, Options}]),
- Options2 = Options#options{socket_opts = SocketOpts},
- create_handler_starter(Request#request{socket_opts = undefined},
- State#state{options = Options2});
-
-create_handler_starter(#request{id = Id,
- from = From} = Request,
- #state{profile_name = ProfileName,
- options = Options,
- handler_db = HandlerDb} = _State) ->
- ?hcrv("create handler starter", [{id, Id}, {profile, ProfileName}]),
- IsInetsManager = is_inets_manager(),
- ManagerPid = self(),
- StarterFun =
- fun() ->
- ?hcrd("handler starter - start",
- [{id, Id},
- {profile, ProfileName},
- {inets_manager, IsInetsManager}]),
- Result1 =
- case IsInetsManager of
- true ->
- httpc_handler_sup:start_child(Options,
- ProfileName);
- false ->
- httpc_handler:start_link(Options,
- ProfileName)
- end,
- ?hcrd("handler starter - maybe connect and send",
- [{id, Id}, {profile, ProfileName}, {result, Result1}]),
- case Result1 of
- {ok, HandlerPid} ->
- StartedMessage =
- {started, self(), Id, HandlerPid},
- ManagerPid ! StartedMessage,
- Result2 = httpc_handler:connect_and_send(Request,
- HandlerPid),
- ?hcrd("handler starter - connected and sent",
- [{id, Id}, {profile, ProfileName},
- {handler, HandlerPid}, {result, Result2}]),
- ConnAndSendMessage =
- {connect_and_send,
- self(), Id, HandlerPid, Result2},
- ManagerPid ! ConnAndSendMessage;
- {error, Reason} ->
- StartFailureMessage =
- {failed_starting_handler, self(), Id, Reason},
- ManagerPid ! StartFailureMessage;
- _ ->
- StartFailureMessage =
- {failed_starting_handler, self(), Id, Result1},
- ManagerPid ! StartFailureMessage
- end
- end,
- Starter = erlang:spawn_link(StarterFun),
- ?hcrd("create handler starter - started", [{id, Id}, {starter, Starter}]),
- Entry = #handler_info{id = Id,
- starter = Starter,
- from = From,
- state = initiating},
- ets:insert(HandlerDb, Entry),
- ok.
-
-
is_inets_manager() ->
case get('$ancestors') of
[httpc_profile_sup | _] ->
@@ -1045,8 +761,6 @@ do_store_cookies([Cookie | Cookies], #state{cookie_db = CookieDb} = State) ->
ok = httpc_cookie:insert(CookieDb, Cookie),
do_store_cookies(Cookies, State).
-
-
session_db_name(ProfileName) ->
make_db_name(ProfileName, "__session_db").
@@ -1074,7 +788,6 @@ cast(ProfileName, Msg) ->
gen_server:cast(ProfileName, Msg).
-
get_proxy(Opts, #options{proxy = Default}) ->
proplists:get_value(proxy, Opts, Default).
@@ -1133,20 +846,6 @@ handle_verbose(trace) ->
handle_verbose(_) ->
ok.
-
error_report(Profile, F, A) ->
Report = io_lib:format("HTTPC-MANAGER<~p> " ++ F ++ "~n", [Profile | A]),
error_logger:error_report(Report).
-
-
-%% d(F) ->
-%% d(F, []).
-
-%% d(F, A) ->
-%% d(get(dbg), F, A).
-
-%% d(true, F, A) ->
-%% io:format(user, "~w:~w:" ++ F ++ "~n", [self(), ?MODULE | A]);
-%% d(_, _, _) ->
-%% ok.
-
diff --git a/lib/inets/src/http_client/httpc_request.erl b/lib/inets/src/http_client/httpc_request.erl
index d4df97ad40..879053f0f2 100644
--- a/lib/inets/src/http_client/httpc_request.erl
+++ b/lib/inets/src/http_client/httpc_request.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -79,36 +79,62 @@ send(SendAddr, Socket, SocketType,
{settings, HttpOptions},
{userinfo, UserInfo}]),
- TmpHeaders = handle_user_info(UserInfo, Headers),
+ TmpHdrs = handle_user_info(UserInfo, Headers),
- {TmpHeaders2, Body} =
- post_data(Method, TmpHeaders, Content, HeadersAsIs),
+ {TmpHdrs2, Body} = post_data(Method, TmpHdrs, Content, HeadersAsIs),
- {NewHeaders, Uri} = case Address of
- SendAddr ->
- {TmpHeaders2, Path ++ Query};
- _Proxy ->
- TmpHeaders3 =
- handle_proxy(HttpOptions, TmpHeaders2),
- {TmpHeaders3, AbsUri}
- end,
-
- FinalHeaders = case NewHeaders of
- HeaderList when is_list(HeaderList) ->
- http_headers(HeaderList, []);
- _ ->
- http_request:http_headers(NewHeaders)
- end,
+ {NewHeaders, Uri} =
+ case Address of
+ SendAddr ->
+ {TmpHdrs2, Path ++ Query};
+ _Proxy ->
+ TmpHdrs3 = handle_proxy(HttpOptions, TmpHdrs2),
+ {TmpHdrs3, AbsUri}
+ end,
+
+ FinalHeaders =
+ case NewHeaders of
+ HeaderList when is_list(HeaderList) ->
+ http_headers(HeaderList, []);
+ _ ->
+ http_request:http_headers(NewHeaders)
+ end,
Version = HttpOptions#http_options.version,
- Message = [method(Method), " ", Uri, " ",
- version(Version), ?CRLF,
- headers(FinalHeaders, Version), ?CRLF, Body],
+ do_send_body(SocketType, Socket, Method, Uri, Version, FinalHeaders, Body).
+
+
+do_send_body(SocketType, Socket, Method, Uri, Version, Headers,
+ {ProcessBody, Acc}) when is_function(ProcessBody, 1) ->
+ ?hcrt("send", [{acc, Acc}]),
+ case do_send_body(SocketType, Socket, Method, Uri, Version, Headers, []) of
+ ok ->
+ do_send_body(SocketType, Socket, ProcessBody, Acc);
+ Error ->
+ Error
+ end;
+do_send_body(SocketType, Socket, Method, Uri, Version, Headers, Body) ->
+ ?hcrt("create message", [{body, Body}]),
+ Message = [method(Method), " ", Uri, " ",
+ version(Version), ?CRLF,
+ headers(Headers, Version), ?CRLF, Body],
?hcrd("send", [{message, Message}]),
-
- http_transport:send(SocketType, Socket, lists:append(Message)).
+ http_transport:send(SocketType, Socket, Message).
+
+do_send_body(SocketType, Socket, ProcessBody, Acc) ->
+ case ProcessBody(Acc) of
+ eof ->
+ ok;
+ {ok, Data, NewAcc} ->
+ case http_transport:send(SocketType, Socket, Data) of
+ ok ->
+ do_send_body(SocketType, Socket, ProcessBody, NewAcc);
+ Error ->
+ Error
+ end
+ end.
%%-------------------------------------------------------------------------
@@ -161,7 +187,6 @@ is_client_closing(Headers) ->
%%%========================================================================
post_data(Method, Headers, {ContentType, Body}, HeadersAsIs)
when (Method =:= post) orelse (Method =:= put) ->
- ContentLength = body_length(Body),
NewBody = case Headers#http_request_h.expect of
"100-continue" ->
"";
@@ -170,14 +195,22 @@ post_data(Method, Headers, {ContentType, Body}, HeadersAsIs)
end,
NewHeaders = case HeadersAsIs of
- [] ->
- Headers#http_request_h{'content-type' =
- ContentType,
- 'content-length' =
- ContentLength};
- _ ->
- HeadersAsIs
- end,
+ [] ->
+ Headers#http_request_h{
+ 'content-type' = ContentType,
+ 'content-length' = case body_length(Body) of
+ undefined ->
+ % on upload streaming the caller must give a
+ % value to the Content-Length header
+ % (or use chunked Transfer-Encoding)
+ Headers#http_request_h.'content-length';
+ Len when is_list(Len) ->
+ Len
+ end
+ };
+ _ ->
+ HeadersAsIs
+ end,
{NewHeaders, NewBody};
@@ -190,7 +223,10 @@ body_length(Body) when is_binary(Body) ->
integer_to_list(size(Body));
body_length(Body) when is_list(Body) ->
- integer_to_list(length(Body)).
+ integer_to_list(length(Body));
+
+body_length({DataFun, _Acc}) when is_function(DataFun, 1) ->
+ undefined.
method(Method) ->
http_util:to_upper(atom_to_list(Method)).
diff --git a/lib/inets/src/http_lib/http_internal.hrl b/lib/inets/src/http_lib/http_internal.hrl
index 5440f214b5..97cf474ab9 100644
--- a/lib/inets/src/http_lib/http_internal.hrl
+++ b/lib/inets/src/http_lib/http_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The 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,8 +28,7 @@
-define(HTTP_MAX_URI_SIZE, nolimit).
-ifndef(HTTP_DEFAULT_SSL_KIND).
--define(HTTP_DEFAULT_SSL_KIND, ossl).
-%% -define(HTTP_DEFAULT_SSL_KIND, essl).
+-define(HTTP_DEFAULT_SSL_KIND, essl).
-endif. % -ifdef(HTTP_DEFAULT_SSL_KIND).
diff --git a/lib/inets/src/http_lib/http_transport.erl b/lib/inets/src/http_lib/http_transport.erl
index 0024d19fc1..5eb827032f 100644
--- a/lib/inets/src/http_lib/http_transport.erl
+++ b/lib/inets/src/http_lib/http_transport.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The 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,7 +23,7 @@
-export([
start/1,
connect/3, connect/4,
- listen/2, listen/3,
+ listen/2, listen/3, listen/4,
accept/2, accept/3,
close/2,
send/3,
@@ -33,8 +33,8 @@
peername/2, sockname/2,
resolve/0
]).
-
-export([negotiate/3]).
+-export([ipv4_name/1, ipv6_name/1]).
-include_lib("inets/src/inets_app/inets_internal.hrl").
-include("http_internal.hrl").
@@ -62,8 +62,6 @@ start(ip_comm) ->
%% This is just for backward compatibillity
start({ssl, _}) ->
do_start_ssl();
-start({ossl, _}) ->
- do_start_ssl();
start({essl, _}) ->
do_start_ssl().
@@ -110,36 +108,45 @@ connect(ip_comm = _SocketType, {Host, Port}, Opts0, Timeout)
Opts = [binary, {packet, 0}, {active, false}, {reuseaddr, true} | Opts0],
?hlrt("connect using gen_tcp",
[{host, Host}, {port, Port}, {opts, Opts}, {timeout, Timeout}]),
- gen_tcp:connect(Host, Port, Opts, Timeout);
+ try gen_tcp:connect(Host, Port, Opts, Timeout) of
+ {ok, _} = OK ->
+ OK;
+ {error, _} = ERROR ->
+ ERROR
+ catch
+ exit:{badarg, _} ->
+ {error, {eoptions, Opts}};
+ exit:badarg ->
+ {error, {eoptions, Opts}}
+ end;
%% Wrapper for backaward compatibillity
connect({ssl, SslConfig}, Address, Opts, Timeout) ->
connect({?HTTP_DEFAULT_SSL_KIND, SslConfig}, Address, Opts, Timeout);
-connect({ossl, SslConfig}, {Host, Port}, _, Timeout) ->
- Opts = [binary, {active, false}, {ssl_imp, old}] ++ SslConfig,
- ?hlrt("connect using ossl",
- [{host, Host},
- {port, Port},
- {ssl_config, SslConfig},
- {timeout, Timeout}]),
- ssl:connect(Host, Port, Opts, Timeout);
-
-connect({essl, SslConfig}, {Host, Port}, _, Timeout) ->
- Opts = [binary, {active, false}, {ssl_imp, new}] ++ SslConfig,
+connect({essl, SslConfig}, {Host, Port}, Opts0, Timeout) ->
+ Opts = [binary, {active, false}, {ssl_imp, new} | Opts0] ++ SslConfig,
?hlrt("connect using essl",
[{host, Host},
{port, Port},
{ssl_config, SslConfig},
{timeout, Timeout}]),
- ssl:connect(Host, Port, Opts, Timeout).
+ case (catch ssl:connect(Host, Port, Opts, Timeout)) of
+ {'EXIT', Reason} ->
+ {error, {eoptions, Reason}};
+ {ok, _} = OK ->
+ OK;
+ {error, _} = ERROR ->
+ ERROR
+ end.
%%-------------------------------------------------------------------------
-%% listen(SocketType, Port) -> {ok, Socket} | {error, Reason}
+%% listen(SocketType, Addr, Port, Fd) -> {ok, Socket} | {error, Reason}
%% SocketType = ip_comm | {ssl, SSLConfig}
%% Port = integer()
-%% Socket = socket()
+%% Socket = socket()
+%% Fd = undefined | fd()
%%
%% Description: Sets up socket to listen on the port Port on the local
%% host using either gen_tcp or ssl. In the gen_tcp case the port
@@ -151,13 +158,8 @@ connect({essl, SslConfig}, {Host, Port}, _, Timeout) ->
listen(SocketType, Port) ->
listen(SocketType, undefined, Port).
-listen(ip_comm, Addr, Port) ->
- case (catch listen_ip_comm(Addr, Port)) of
- {'EXIT', Reason} ->
- {error, {exit, Reason}};
- Else ->
- Else
- end;
+listen(ip_comm = _SocketType, Addr, Port) ->
+ listen_ip_comm(Addr, Port, undefined);
%% Wrapper for backaward compatibillity
listen({ssl, SSLConfig}, Addr, Port) ->
@@ -167,28 +169,27 @@ listen({ssl, SSLConfig}, Addr, Port) ->
{ssl_config, SSLConfig}]),
listen({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Addr, Port);
-listen({ossl, SSLConfig} = Ssl, Addr, Port) ->
- ?hlrt("listen (ossl)",
- [{addr, Addr},
- {port, Port},
- {ssl_config, SSLConfig}]),
- Opt = sock_opt(Ssl, Addr, SSLConfig),
- ?hlrt("listen options", [{opt, Opt}]),
- ssl:listen(Port, [{ssl_imp, old} | Opt]);
-
-listen({essl, SSLConfig} = Ssl, Addr, Port) ->
+listen({essl, SSLConfig}, Addr, Port) ->
?hlrt("listen (essl)",
[{addr, Addr},
{port, Port},
{ssl_config, SSLConfig}]),
- Opt = sock_opt(Ssl, Addr, SSLConfig),
- ?hlrt("listen options", [{opt, Opt}]),
- Opt2 = [{ssl_imp, new}, {reuseaddr, true} | Opt],
- ssl:listen(Port, Opt2).
+ listen_ssl(Addr, Port, [{ssl_imp, new}, {reuseaddr, true} | SSLConfig]).
+
+listen(ip_comm, Addr, Port, Fd) ->
+ listen_ip_comm(Addr, Port, Fd).
-listen_ip_comm(Addr, Port) ->
- {NewPort, Opts, IpFamily} = get_socket_info(Addr, Port),
+listen_ip_comm(Addr, Port, Fd) ->
+ case (catch do_listen_ip_comm(Addr, Port, Fd)) of
+ {'EXIT', Reason} ->
+ {error, {exit, Reason}};
+ Else ->
+ Else
+ end.
+
+do_listen_ip_comm(Addr, Port, Fd) ->
+ {NewPort, Opts, IpFamily} = get_socket_info(Addr, Port, Fd),
case IpFamily of
inet6fb4 ->
Opts2 = [inet6 | Opts],
@@ -220,32 +221,74 @@ listen_ip_comm(Addr, Port) ->
gen_tcp:listen(NewPort, Opts2)
end.
+
+listen_ssl(Addr, Port, Opts0) ->
+ IpFamily = ipfamily_default(Addr, Port),
+ BaseOpts = [{backlog, 128}, {reuseaddr, true} | Opts0],
+ Opts = sock_opts(Addr, BaseOpts),
+ case IpFamily of
+ inet6fb4 ->
+ Opts2 = [inet6 | Opts],
+ ?hlrt("try ipv6 listen", [{opts, Opts2}]),
+ case (catch ssl:listen(Port, Opts2)) of
+ {error, Reason} when ((Reason =:= nxdomain) orelse
+ (Reason =:= eafnosupport)) ->
+ Opts3 = [inet | Opts],
+ ?hlrt("ipv6 listen failed - try ipv4 instead",
+ [{reason, Reason}, {opts, Opts3}]),
+ ssl:listen(Port, Opts3);
+
+ {'EXIT', Reason} ->
+ Opts3 = [inet | Opts],
+ ?hlrt("ipv6 listen exit - try ipv4 instead",
+ [{reason, Reason}, {opts, Opts3}]),
+ ssl:listen(Port, Opts3);
+
+ Other ->
+ ?hlrt("ipv6 listen done", [{other, Other}]),
+ Other
+ end;
+
+ _ ->
+ Opts2 = [IpFamily | Opts],
+ ?hlrt("listen", [{opts, Opts2}]),
+ ssl:listen(Port, Opts2)
+ end.
+
+
ipfamily_default(Addr, Port) ->
httpd_conf:lookup(Addr, Port, ipfamily, inet6fb4).
-get_socket_info(Addr, Port) ->
- Key = list_to_atom("httpd_" ++ integer_to_list(Port)),
- BaseOpts = [{backlog, 128}, {reuseaddr, true}],
+get_socket_info(Addr, Port, Fd0) ->
+ BaseOpts = [{backlog, 128}, {reuseaddr, true}],
IpFamilyDefault = ipfamily_default(Addr, Port),
- case init:get_argument(Key) of
- {ok, [[Value]]} ->
- {Fd, IpFamily} =
- case string:tokens(Value, [$|]) of
- [FdStr, IpFamilyStr] ->
- Fd0 = fd_of(FdStr),
- IpFamily0 = ip_family_of(IpFamilyStr),
- {Fd0, IpFamily0};
- [FdStr] ->
- {fd_of(FdStr), IpFamilyDefault};
- _ ->
- throw({error, {bad_descriptor, Value}})
- end,
- {0, sock_opt(ip_comm, Addr, [{fd, Fd} | BaseOpts]), IpFamily};
- error ->
- {Port, sock_opt(ip_comm, Addr, BaseOpts), IpFamilyDefault}
+ %% The presence of a file descriptor takes precedence
+ case get_fd(Port, Fd0, IpFamilyDefault) of
+ {Fd, IpFamily} ->
+ {0, sock_opts(Addr, [{fd, Fd} | BaseOpts]), IpFamily};
+ undefined ->
+ {Port, sock_opts(Addr, BaseOpts), IpFamilyDefault}
end.
+get_fd(Port, undefined = _Fd, IpFamilyDefault) ->
+ FdKey = list_to_atom("httpd_" ++ integer_to_list(Port)),
+ case init:get_argument(FdKey) of
+ {ok, [[Value]]} ->
+ case string:tokens(Value, [$|]) of
+ [FdStr, IpFamilyStr] ->
+ {fd_of(FdStr), ip_family_of(IpFamilyStr)};
+ [FdStr] ->
+ {fd_of(FdStr), IpFamilyDefault};
+ _ ->
+ throw({error, {bad_descriptor, Value}})
+ end;
+ error ->
+ undefined
+ end;
+get_fd(_Port, Fd, IpFamilyDefault) ->
+ {Fd, IpFamilyDefault}.
+
fd_of(FdStr) ->
case (catch list_to_integer(FdStr)) of
Fd when is_integer(Fd) ->
@@ -285,8 +328,6 @@ accept(ip_comm, ListenSocket, Timeout) ->
accept({ssl, SSLConfig}, ListenSocket, Timeout) ->
accept({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, ListenSocket, Timeout);
-accept({ossl, _SSLConfig}, ListenSocket, Timeout) ->
- ssl:transport_accept(ListenSocket, Timeout);
accept({essl, _SSLConfig}, ListenSocket, Timeout) ->
ssl:transport_accept(ListenSocket, Timeout).
@@ -306,9 +347,6 @@ controlling_process(ip_comm, Socket, NewOwner) ->
controlling_process({ssl, SSLConfig}, Socket, NewOwner) ->
controlling_process({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, NewOwner);
-controlling_process({ossl, _}, Socket, NewOwner) ->
- ssl:controlling_process(Socket, NewOwner);
-
controlling_process({essl, _}, Socket, NewOwner) ->
ssl:controlling_process(Socket, NewOwner).
@@ -329,13 +367,6 @@ setopts(ip_comm, Socket, Options) ->
setopts({ssl, SSLConfig}, Socket, Options) ->
setopts({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Options);
-setopts({ossl, _}, Socket, Options) ->
- ?hlrt("[o]ssl setopts", [{socket, Socket}, {options, Options}]),
- Reason = (catch ssl:setopts(Socket, Options)),
- ?hlrt("[o]ssl setopts result", [{reason, Reason}]),
- Reason;
-
-
setopts({essl, _}, Socket, Options) ->
?hlrt("[e]ssl setopts", [{socket, Socket}, {options, Options}]),
Reason = (catch ssl:setopts(Socket, Options)),
@@ -367,10 +398,6 @@ getopts(ip_comm, Socket, Options) ->
getopts({ssl, SSLConfig}, Socket, Options) ->
getopts({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Options);
-getopts({ossl, _}, Socket, Options) ->
- ?hlrt("ssl getopts", [{socket, Socket}, {options, Options}]),
- getopts_ssl(Socket, Options);
-
getopts({essl, _}, Socket, Options) ->
?hlrt("essl getopts", [{socket, Socket}, {options, Options}]),
getopts_ssl(Socket, Options).
@@ -404,9 +431,6 @@ getstat(ip_comm = _SocketType, Socket) ->
getstat({ssl, SSLConfig}, Socket) ->
getstat({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket);
-getstat({ossl, _} = _SocketType, _Socket) ->
- [];
-
getstat({essl, _} = _SocketType, _Socket) ->
[].
@@ -425,9 +449,6 @@ send(ip_comm, Socket, Message) ->
send({ssl, SSLConfig}, Socket, Message) ->
send({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Message);
-send({ossl, _}, Socket, Message) ->
- ssl:send(Socket, Message);
-
send({essl, _}, Socket, Message) ->
ssl:send(Socket, Message).
@@ -446,9 +467,6 @@ close(ip_comm, Socket) ->
close({ssl, SSLConfig}, Socket) ->
close({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket);
-close({ossl, _}, Socket) ->
- ssl:close(Socket);
-
close({essl, _}, Socket) ->
ssl:close(Socket).
@@ -464,44 +482,25 @@ close({essl, _}, Socket) ->
%% connection, usning either gen_tcp or ssl.
%%-------------------------------------------------------------------------
peername(ip_comm, Socket) ->
- case inet:peername(Socket) of
- {ok,{{A, B, C, D}, Port}} ->
- PeerName = integer_to_list(A)++"."++integer_to_list(B)++"."++
- integer_to_list(C)++"."++integer_to_list(D),
- {Port, PeerName};
- {ok,{{A, B, C, D, E, F, G, H}, Port}} ->
- PeerName = http_util:integer_to_hexlist(A) ++ ":"++
- http_util:integer_to_hexlist(B) ++ ":" ++
- http_util:integer_to_hexlist(C) ++ ":" ++
- http_util:integer_to_hexlist(D) ++ ":" ++
- http_util:integer_to_hexlist(E) ++ ":" ++
- http_util:integer_to_hexlist(F) ++ ":" ++
- http_util:integer_to_hexlist(G) ++":"++
- http_util:integer_to_hexlist(H),
- {Port, PeerName};
- {error, _} ->
- {-1, "unknown"}
- end;
+ do_peername(inet:peername(Socket));
%% Wrapper for backaward compatibillity
peername({ssl, SSLConfig}, Socket) ->
peername({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket);
-peername({ossl, _}, Socket) ->
- peername_ssl(Socket);
-
peername({essl, _}, Socket) ->
- peername_ssl(Socket).
-
-peername_ssl(Socket) ->
- case ssl:peername(Socket) of
- {ok,{{A, B, C, D}, Port}} ->
- PeerName = integer_to_list(A)++"."++integer_to_list(B)++"."++
- integer_to_list(C)++"."++integer_to_list(D),
- {Port, PeerName};
- {error, _} ->
- {-1, "unknown"}
- end.
+ do_peername(ssl:peername(Socket)).
+
+do_peername({ok, {Addr, Port}})
+ when is_tuple(Addr) andalso (size(Addr) =:= 4) ->
+ PeerName = ipv4_name(Addr),
+ {Port, PeerName};
+do_peername({ok, {Addr, Port}})
+ when is_tuple(Addr) andalso (size(Addr) =:= 8) ->
+ PeerName = ipv6_name(Addr),
+ {Port, PeerName};
+do_peername({error, _}) ->
+ {-1, "unknown"}.
%%-------------------------------------------------------------------------
@@ -515,44 +514,25 @@ peername_ssl(Socket) ->
%% other end of connection, using either gen_tcp or ssl.
%%-------------------------------------------------------------------------
sockname(ip_comm, Socket) ->
- case inet:sockname(Socket) of
- {ok,{{A, B, C, D}, Port}} ->
- SockName = integer_to_list(A)++"."++integer_to_list(B)++"."++
- integer_to_list(C)++"."++integer_to_list(D),
- {Port, SockName};
- {ok,{{A, B, C, D, E, F, G, H}, Port}} ->
- SockName = http_util:integer_to_hexlist(A) ++ ":"++
- http_util:integer_to_hexlist(B) ++ ":" ++
- http_util:integer_to_hexlist(C) ++ ":" ++
- http_util:integer_to_hexlist(D) ++ ":" ++
- http_util:integer_to_hexlist(E) ++ ":" ++
- http_util:integer_to_hexlist(F) ++ ":" ++
- http_util:integer_to_hexlist(G) ++":"++
- http_util:integer_to_hexlist(H),
- {Port, SockName};
- {error, _} ->
- {-1, "unknown"}
- end;
+ do_sockname(inet:sockname(Socket));
%% Wrapper for backaward compatibillity
sockname({ssl, SSLConfig}, Socket) ->
sockname({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket);
-sockname({ossl, _}, Socket) ->
- sockname_ssl(Socket);
-
sockname({essl, _}, Socket) ->
- sockname_ssl(Socket).
-
-sockname_ssl(Socket) ->
- case ssl:sockname(Socket) of
- {ok,{{A, B, C, D}, Port}} ->
- SockName = integer_to_list(A)++"."++integer_to_list(B)++"."++
- integer_to_list(C)++"."++integer_to_list(D),
- {Port, SockName};
- {error, _} ->
- {-1, "unknown"}
- end.
+ do_sockname(ssl:sockname(Socket)).
+
+do_sockname({ok, {Addr, Port}})
+ when is_tuple(Addr) andalso (size(Addr) =:= 4) ->
+ SockName = ipv4_name(Addr),
+ {Port, SockName};
+do_sockname({ok, {Addr, Port}})
+ when is_tuple(Addr) andalso (size(Addr) =:= 8) ->
+ SockName = ipv6_name(Addr),
+ {Port, SockName};
+do_sockname({error, _}) ->
+ {-1, "unknown"}.
%%-------------------------------------------------------------------------
@@ -566,38 +546,55 @@ resolve() ->
Name.
+%%-------------------------------------------------------------------------
+%% ipv4_name(Ipv4Addr) -> string()
+%% ipv6_name(Ipv6Addr) -> string()
+%% Ipv4Addr = ip4_address()
+%% Ipv6Addr = ip6_address()
+%%
+%% Description: Returns the local hostname.
+%%-------------------------------------------------------------------------
+ipv4_name({A, B, C, D}) ->
+ integer_to_list(A) ++ "." ++
+ integer_to_list(B) ++ "." ++
+ integer_to_list(C) ++ "." ++
+ integer_to_list(D).
+
+ipv6_name({A, B, C, D, E, F, G, H}) ->
+ http_util:integer_to_hexlist(A) ++ ":"++
+ http_util:integer_to_hexlist(B) ++ ":" ++
+ http_util:integer_to_hexlist(C) ++ ":" ++
+ http_util:integer_to_hexlist(D) ++ ":" ++
+ http_util:integer_to_hexlist(E) ++ ":" ++
+ http_util:integer_to_hexlist(F) ++ ":" ++
+ http_util:integer_to_hexlist(G) ++ ":" ++
+ http_util:integer_to_hexlist(H).
+
+
%%%========================================================================
%%% Internal functions
%%%========================================================================
+%% -- sock_opts --
%% Address any comes from directive: BindAddress "*"
-sock_opt(ip_comm, any = Addr, Opts) ->
- sock_opt2([{ip, Addr} | Opts]);
-sock_opt(ip_comm, undefined, Opts) ->
- sock_opt2(Opts);
-sock_opt(_, any = _Addr, Opts) ->
- sock_opt2(Opts);
-sock_opt(_, undefined = _Addr, Opts) ->
- sock_opt2(Opts);
-sock_opt(_, {_,_,_,_} = Addr, Opts) ->
- sock_opt2([{ip, Addr} | Opts]);
-sock_opt(ip_comm, Addr, Opts) ->
- sock_opt2([{ip, Addr} | Opts]);
-sock_opt(_, Addr, Opts) ->
- sock_opt2([{ip, Addr} | Opts]).
-
-sock_opt2(Opts) ->
+sock_opts(undefined, Opts) ->
+ sock_opts(Opts);
+sock_opts(any = Addr, Opts) ->
+ sock_opts([{ip, Addr} | Opts]);
+sock_opts(Addr, Opts) ->
+ sock_opts([{ip, Addr} | Opts]).
+
+sock_opts(Opts) ->
[{packet, 0}, {active, false} | Opts].
+
+%% -- negotiate --
negotiate(ip_comm,_,_) ->
?hlrt("negotiate(ip_comm)", []),
ok;
negotiate({ssl, SSLConfig}, Socket, Timeout) ->
?hlrt("negotiate(ssl)", []),
negotiate({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Timeout);
-negotiate({ossl, _}, Socket, Timeout) ->
- ?hlrt("negotiate(ossl)", []),
- negotiate_ssl(Socket, Timeout);
negotiate({essl, _}, Socket, Timeout) ->
?hlrt("negotiate(essl)", []),
negotiate_ssl(Socket, Timeout).
diff --git a/lib/inets/src/http_lib/http_util.erl b/lib/inets/src/http_lib/http_util.erl
index 4f1147176c..973600d7be 100644
--- a/lib/inets/src/http_lib/http_util.erl
+++ b/lib/inets/src/http_lib/http_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The 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,7 +25,8 @@
hexlist_to_integer/1, integer_to_hexlist/1,
convert_month/1,
is_hostname/1,
- timestamp/0, timeout/2
+ timestamp/0, timeout/2,
+ html_encode/1
]).
@@ -103,6 +104,22 @@ convert_netscapecookie_date([_D,_A,_Y, $ ,
Sec = list_to_integer([S1,S2]),
{{Year,Month,Day},{Hour,Min,Sec}};
+%% Example: Tue Jan 01 08:00:01 2036 GMT
+convert_netscapecookie_date([_D,_A,_Y, $ ,
+ M,O,N, $ ,
+ D1,D2, $ ,
+ H1,H2, $:,
+ M1,M2, $:,
+ S1,S2, $ ,
+ Y1,Y2,Y3,Y4, $ |_Rest]) ->
+ Year = list_to_integer([Y1,Y2,Y3,Y4]),
+ Day = list_to_integer([D1,D2]),
+ Month = convert_month([M,O,N]),
+ Hour = list_to_integer([H1,H2]),
+ Min = list_to_integer([M1,M2]),
+ Sec = list_to_integer([S1,S2]),
+ {{Year,Month,Day},{Hour,Min,Sec}};
+
%% Sloppy...
convert_netscapecookie_date([_D,_A,_Y, $,, _SP,
D1,D2,_DA,
@@ -187,6 +204,13 @@ timeout(Timeout, Started) ->
end.
+html_encode(Chars) ->
+ Reserved = sets:from_list([$&, $<, $>, $\", $', $/]),
+ lists:append(lists:map(fun(Char) ->
+ char_to_html_entity(Char, Reserved)
+ end, Chars)).
+
+
%%%========================================================================
%%% Internal functions
%%%========================================================================
@@ -235,3 +259,11 @@ convert_to_ascii([Num | Reversed], Number)
convert_to_ascii([Num | Reversed], Number)
when (Num > 9) andalso (Num < 16) ->
convert_to_ascii(Reversed, [Num + 55 | Number]).
+
+char_to_html_entity(Char, Reserved) ->
+ case sets:is_element(Char, Reserved) of
+ true ->
+ "&#" ++ integer_to_list(Char) ++ ";";
+ false ->
+ [Char]
+ end.
diff --git a/lib/inets/src/http_server/httpd_conf.erl b/lib/inets/src/http_server/httpd_conf.erl
index f4d8a6c09f..7646300409 100644
--- a/lib/inets/src/http_server/httpd_conf.erl
+++ b/lib/inets/src/http_server/httpd_conf.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -219,9 +219,8 @@ load("ServerName " ++ ServerName, []) ->
load("SocketType " ++ SocketType, []) ->
%% ssl is the same as HTTP_DEFAULT_SSL_KIND
- %% ossl is ssl based on OpenSSL (the "old" ssl)
%% essl is the pure Erlang-based ssl (the "new" ssl)
- case check_enum(clean(SocketType), ["ssl", "ossl", "essl", "ip_comm"]) of
+ case check_enum(clean(SocketType), ["ssl", "essl", "ip_comm"]) of
{ok, ValidSocketType} ->
{ok, [], {socket_type, ValidSocketType}};
{error,_} ->
@@ -305,7 +304,7 @@ load("MaxKeepAliveRequests " ++ MaxRequests, []) ->
" is an invalid MaxKeepAliveRequests")}
end;
-%% This clause is keept for backwards compability
+%% This clause is kept for backwards compatibility
load("MaxKeepAliveRequest " ++ MaxRequests, []) ->
case make_integer(MaxRequests) of
{ok, Integer} ->
@@ -541,7 +540,6 @@ validate_config_params([{server_name, Value} | _]) ->
validate_config_params([{socket_type, Value} | Rest])
when (Value =:= ip_comm) orelse
(Value =:= ssl) orelse
- (Value =:= ossl) orelse
(Value =:= essl) ->
validate_config_params(Rest);
validate_config_params([{socket_type, Value} | _]) ->
@@ -811,7 +809,7 @@ lookup_socket_type(ConfigDB) ->
case httpd_util:lookup(ConfigDB, socket_type, ip_comm) of
ip_comm ->
ip_comm;
- SSL when (SSL =:= ssl) orelse (SSL =:= ossl) orelse (SSL =:= essl) ->
+ SSL when (SSL =:= ssl) orelse (SSL =:= essl) ->
SSLTag =
if
(SSL =:= ssl) ->
diff --git a/lib/inets/src/http_server/httpd_esi.erl b/lib/inets/src/http_server/httpd_esi.erl
index 026ec9a5fe..000874d0a3 100644
--- a/lib/inets/src/http_server/httpd_esi.erl
+++ b/lib/inets/src/http_server/httpd_esi.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -39,7 +39,7 @@
%% body part. Note that it is presumed that <Data> starts with a
%% string including "\r\n\r\n" if there is any header information
%% present. The returned headers will not contain the HTTP header body
-%% delimiter \r\n. (All header, header delimiters are keept.)
+%% delimiter \r\n. (All header, header delimiters are kept.)
%% Ex: ["Content-Type : text/html\r\n Connection : closing \r\n\r\n" |
%% io_list()] --> {"Content-Type : text/html\r\n Connection : closing \r\n",
%% io_list()}
diff --git a/lib/inets/src/http_server/httpd_file.erl b/lib/inets/src/http_server/httpd_file.erl
index 7e21d9e158..e8a8ab6411 100644
--- a/lib/inets/src/http_server/httpd_file.erl
+++ b/lib/inets/src/http_server/httpd_file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
%%
%% The 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,22 +26,21 @@
handle_error(eacces, Op, ModData, Path) ->
- handle_error(403, Op, ModData, Path,"Forbidden");
+ handle_error(403, Op, ModData, Path, ": Forbidden");
handle_error(enoent, Op, ModData, Path) ->
- handle_error(404, Op, ModData, Path,"File not found");
+ handle_error(404, Op, ModData, Path, ": File not found");
handle_error(enotdir, Op, ModData, Path) ->
handle_error(404, Op, ModData, Path,
- ": A component of the file name is not a directory");
+ ": A component of the file name is not a directory");
handle_error(emfile, Op, _ModData, Path) ->
- handle_error(500, Op, none, Path, ": To many open files");
+ handle_error(500, Op, none, Path, ": Too many open files");
handle_error({enfile,_}, Op, _ModData, Path) ->
handle_error(500, Op, none, Path, ": File table overflow");
handle_error(_Reason, Op, ModData, Path) ->
- handle_error(404, Op, ModData, Path, "File not found").
-
-handle_error(StatusCode, Op, none, Path, Reason) ->
- {StatusCode, none, ?NICE("Can't " ++ Op ++ Path ++ Reason)};
+ handle_error(404, Op, ModData, Path, ": File not found").
+handle_error(StatusCode, Op, none, Path, Reason) ->
+ {StatusCode, none, ?NICE("Can't " ++ Op ++ " " ++ Path ++ Reason)};
handle_error(StatusCode, Op, ModData, Path, Reason) ->
{StatusCode, ModData#mod.request_uri,
- ?NICE("Can't " ++ Op ++ Path ++ Reason)}.
+ ?NICE("Can't " ++ Op ++ " " ++ Path ++ Reason)}.
diff --git a/lib/inets/src/http_server/httpd_log.erl b/lib/inets/src/http_server/httpd_log.erl
index f3ea3aa0e2..db1e2c627a 100644
--- a/lib/inets/src/http_server/httpd_log.erl
+++ b/lib/inets/src/http_server/httpd_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -113,7 +113,7 @@ do_error_entry(ConfigDB, RemoteHost, undefined, Date, Reason) ->
do_error_entry(ConfigDB, RemoteHost, URI, Date, Reason) ->
case httpd_util:lookup(ConfigDB, error_log_format, pretty) of
pretty ->
- io_lib:format("[~s] access to ~s failed for ~s reason: ~n~p~n",
+ io_lib:format("[~s] access to ~s failed for ~s, reason: ~n~p~n",
[Date, URI, RemoteHost, Reason]);
compact ->
io_lib:format( "[~s] access to ~s failed for ~s, reason: ~w~n",
diff --git a/lib/inets/src/http_server/httpd_request.erl b/lib/inets/src/http_server/httpd_request.erl
index 7084d9824a..a04bcc2778 100644
--- a/lib/inets/src/http_server/httpd_request.erl
+++ b/lib/inets/src/http_server/httpd_request.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -312,8 +312,8 @@ validate_uri(RequestURI) ->
{'EXIT',_Reason} ->
{error, {bad_request, {malformed_syntax, RequestURI}}};
_ ->
- Path = format_request_uri(UriNoQueryNoHex),
- Path2=[X||X<-string:tokens(Path, "/"),X=/="."], %% OTP-5938
+ Path = format_request_uri(UriNoQueryNoHex),
+ Path2 = [X||X<-string:tokens(Path, "/\\"),X=/="."],
validate_path( Path2,0, RequestURI)
end.
diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl
index a9db6e2058..c3b47ce390 100644
--- a/lib/inets/src/http_server/httpd_request_handler.erl
+++ b/lib/inets/src/http_server/httpd_request_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The 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,13 +240,13 @@ handle_info({ssl_error, _, _} = Reason, State) ->
%% Timeouts
handle_info(timeout, #state{mod = ModData, mfa = {_, parse, _}} = State) ->
- error_log("No request received on keep-alive connection"
+ error_log("No request received on keep-alive connection "
"before server side timeout", ModData),
%% No response should be sent!
{stop, normal, State#state{response_sent = true}};
handle_info(timeout, #state{mod = ModData} = State) ->
httpd_response:send_status(ModData, 408, "Request timeout"),
- error_log("The client did not send the whole request before the"
+ error_log("The client did not send the whole request before the "
"server side timeout", ModData),
{stop, normal, State#state{response_sent = true}};
diff --git a/lib/inets/src/http_server/httpd_sup.erl b/lib/inets/src/http_server/httpd_sup.erl
index f94e5459c1..264dc9f006 100644
--- a/lib/inets/src/http_server/httpd_sup.erl
+++ b/lib/inets/src/http_server/httpd_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -90,7 +90,7 @@ id(Address, Port) ->
%%% Supervisor callback
%%%=========================================================================
init([HttpdServices]) ->
- ?hdrd("starting", []),
+ ?hdrd("starting", [{httpd_service, HttpdServices}]),
RestartStrategy = one_for_one,
MaxR = 10,
MaxT = 3600,
@@ -182,24 +182,32 @@ httpd_child_spec(ConfigFile, AcceptTimeout, Debug) ->
Error
end.
-httpd_child_spec(Config, AcceptTimeout, Debug, Addr, 0) ->
- case start_listen(Addr, 0, Config) of
- {Pid, {NewPort, NewConfig, ListenSocket}} ->
- Name = {httpd_instance_sup, Addr, NewPort},
- StartFunc = {httpd_instance_sup, start_link,
- [NewConfig, AcceptTimeout,
- {Pid, ListenSocket}, Debug]},
- Restart = permanent,
- Shutdown = infinity,
- Modules = [httpd_instance_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules};
- {Pid, {error, Reason}} ->
- exit(Pid, normal),
- {error, Reason}
- end;
-
httpd_child_spec(Config, AcceptTimeout, Debug, Addr, Port) ->
+ case Port == 0 orelse proplists:is_defined(fd, Config) of
+ true ->
+ httpd_child_spec_listen(Config, AcceptTimeout, Debug, Addr, Port);
+ false ->
+ httpd_child_spec_nolisten(Config, AcceptTimeout, Debug, Addr, Port)
+ end.
+
+httpd_child_spec_listen(Config, AcceptTimeout, Debug, Addr, Port) ->
+ case start_listen(Addr, Port, Config) of
+ {Pid, {NewPort, NewConfig, ListenSocket}} ->
+ Name = {httpd_instance_sup, Addr, NewPort},
+ StartFunc = {httpd_instance_sup, start_link,
+ [NewConfig, AcceptTimeout,
+ {Pid, ListenSocket}, Debug]},
+ Restart = permanent,
+ Shutdown = infinity,
+ Modules = [httpd_instance_sup],
+ Type = supervisor,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules};
+ {Pid, {error, Reason}} ->
+ exit(Pid, normal),
+ {error, Reason}
+ end.
+
+httpd_child_spec_nolisten(Config, AcceptTimeout, Debug, Addr, Port) ->
Name = {httpd_instance_sup, Addr, Port},
StartFunc = {httpd_instance_sup, start_link,
[Config, AcceptTimeout, Debug]},
@@ -224,7 +232,8 @@ listen(Address, Port, Config) ->
SocketType = proplists:get_value(socket_type, Config, ip_comm),
case http_transport:start(SocketType) of
ok ->
- case http_transport:listen(SocketType, Address, Port) of
+ Fd = proplists:get_value(fd, Config),
+ case http_transport:listen(SocketType, Address, Port, Fd) of
{ok, ListenSocket} ->
NewConfig = proplists:delete(port, Config),
{ok, NewPort} = inet:port(ListenSocket),
diff --git a/lib/inets/src/http_server/httpd_util.erl b/lib/inets/src/http_server/httpd_util.erl
index 789f12652b..c051422529 100644
--- a/lib/inets/src/http_server/httpd_util.erl
+++ b/lib/inets/src/http_server/httpd_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -181,7 +181,7 @@ message(304, _URL,_) ->
message(400,none,_) ->
"Your browser sent a query that this server could not understand.";
message(400,Msg,_) ->
- "Your browser sent a query that this server could not understand. "++ maybe_encode(Msg);
+ "Your browser sent a query that this server could not understand. "++ http_util:html_encode(Msg);
message(401,none,_) ->
"This server could not verify that you
are authorized to access the document you
@@ -190,48 +190,48 @@ credentials (e.g., bad password), or your
browser doesn't understand how to supply
the credentials required.";
message(403,RequestURI,_) ->
- "You don't have permission to access "++ maybe_encode(RequestURI) ++" on this server.";
+ "You don't have permission to access "++ http_util:html_encode(RequestURI) ++" on this server.";
message(404,RequestURI,_) ->
- "The requested URL " ++ maybe_encode(RequestURI) ++ " was not found on this server.";
+ "The requested URL " ++ http_util:html_encode(RequestURI) ++ " was not found on this server.";
message(408, Timeout, _) ->
Timeout;
message(412,none,_) ->
- "The requested preconditions where false";
+ "The requested preconditions were false";
message(413, Reason,_) ->
- "Entity: " ++ Reason;
+ "Entity: " ++ http_util:html_encode(Reason);
message(414,ReasonPhrase,_) ->
- "Message "++ ReasonPhrase ++".";
+ "Message "++ http_util:html_encode(ReasonPhrase) ++".";
message(416,ReasonPhrase,_) ->
- ReasonPhrase;
+ http_util:html_encode(ReasonPhrase);
message(500,_,ConfigDB) ->
ServerAdmin=lookup(ConfigDB,server_admin,"unknown@unknown"),
"The server encountered an internal error or "
"misconfiguration and was unable to complete "
"your request.<P>Please contact the server administrator "
- ++ ServerAdmin ++ ", and inform them of the time the error occurred "
+ ++ http_util:html_encode(ServerAdmin) ++ ", and inform them of the time the error occurred "
"and anything you might have done that may have caused the error.";
message(501,{Method, RequestURI, HTTPVersion}, _ConfigDB) ->
if
is_atom(Method) ->
- atom_to_list(Method)++
- " to "++ maybe_encode(RequestURI)++" ("++HTTPVersion++") not supported.";
+ http_util:html_encode(atom_to_list(Method))++
+ " to "++ http_util:html_encode(RequestURI)++" ("++ http_util:html_encode(HTTPVersion)++") not supported.";
is_list(Method) ->
- Method++
- " to "++ maybe_encode(RequestURI)++" ("++HTTPVersion++") not supported."
+ http_util:html_encode(Method)++
+ " to "++ http_util:html_encode(RequestURI)++" ("++ http_util:html_encode(HTTPVersion)++") not supported."
end;
message(503, String, _ConfigDB) ->
- "This service in unavailable due to: "++String.
+ "This service in unavailable due to: "++ http_util:html_encode(String).
maybe_encode(URI) ->
- case lists:member($%, URI) of
- true ->
- URI;
- false ->
- http_uri:encode(URI)
- end.
+ Decoded = try http_uri:decode(URI) of
+ N -> N
+ catch
+ error:_ -> URI
+ end,
+ http_uri:encode(Decoded).
%%convert_rfc_date(Date)->{{YYYY,MM,DD},{HH,MIN,SEC}}
diff --git a/lib/inets/src/http_server/mod_auth_mnesia.erl b/lib/inets/src/http_server/mod_auth_mnesia.erl
index ffe028617b..91beb0e062 100644
--- a/lib/inets/src/http_server/mod_auth_mnesia.erl
+++ b/lib/inets/src/http_server/mod_auth_mnesia.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The 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,7 +55,7 @@ store_directory_data(_Directory, _DirData, _Server_root) ->
%% API
%%
-%% Compability API
+%% Compatibility API
store_user(UserName, Password, Port, Dir, _AccessPassword) ->
%% AccessPassword is ignored - was not used in previous version
diff --git a/lib/inets/src/http_server/mod_esi.erl b/lib/inets/src/http_server/mod_esi.erl
index 929185a67a..e36c33b282 100644
--- a/lib/inets/src/http_server/mod_esi.erl
+++ b/lib/inets/src/http_server/mod_esi.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -415,7 +415,7 @@ deliver_webpage_chunk(#mod{config_db = Db} = ModData, Pid, Timeout) ->
end;
timeout ->
?hdrv("deliver_webpage_chunk - timeout", []),
- send_headers(ModData, {504, "Timeout"},[{"connection", "close"}]),
+ send_headers(ModData, 504, [{"connection", "close"}]),
httpd_socket:close(ModData#mod.socket_type, ModData#mod.socket),
process_flag(trap_exit,false),
{proceed,[{response, {already_sent, 200, 0}} | ModData#mod.data]}
@@ -452,6 +452,10 @@ handle_body(Pid, ModData, Body, Timeout, Size, IsDisableChunkedSend) ->
?hdrt("handle_body - send chunk", [{timeout, Timeout}, {size, Size}]),
httpd_response:send_chunk(ModData, Body, IsDisableChunkedSend),
receive
+ {esi_data, Data} when is_binary(Data) ->
+ ?hdrt("handle_body - received binary data (esi)", []),
+ handle_body(Pid, ModData, Data, Timeout, Size + byte_size(Data),
+ IsDisableChunkedSend);
{esi_data, Data} ->
?hdrt("handle_body - received data (esi)", []),
handle_body(Pid, ModData, Data, Timeout, Size + length(Data),
diff --git a/lib/inets/src/inets_app/inets.app.src b/lib/inets/src/inets_app/inets.app.src
index cb036157a5..4d0defb329 100644
--- a/lib/inets/src/inets_app/inets.app.src
+++ b/lib/inets/src/inets_app/inets.app.src
@@ -34,8 +34,7 @@
ftp_sup,
%% HTTP client:
- http, %% Old client API module
- httpc, %% New client API module
+ httpc,
httpc_handler,
httpc_handler_sup,
httpc_manager,
diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src
index 07da8ca961..e6d315819c 100644
--- a/lib/inets/src/inets_app/inets.appup.src
+++ b/lib/inets/src/inets_app/inets.appup.src
@@ -18,37 +18,37 @@
{"%VSN%",
[
- {"5.5.1",
+ {"5.7.1",
[
- {load_module, http_chunk, soft_purge, soft_purge, []}
+ {restart_application, inets}
]
},
- {"5.5",
+ {"5.7",
[
{restart_application, inets}
]
},
- {"5.4",
+ {"5.6",
[
{restart_application, inets}
]
}
],
- [
- {"5.5.1",
+ [
+ {"5.7.1",
[
- {load_module, http_chunk, soft_purge, soft_purge, []}
+ {restart_application, inets}
]
},
- {"5.5",
+ {"5.7",
[
{restart_application, inets}
]
- },
- {"5.4",
+ },
+ {"5.6",
[
{restart_application, inets}
]
- }
+ }
]
}.
diff --git a/lib/inets/src/inets_app/inets_service.erl b/lib/inets/src/inets_app/inets_service.erl
index e9eb9892f2..f89dac195c 100644
--- a/lib/inets/src/inets_app/inets_service.erl
+++ b/lib/inets/src/inets_app/inets_service.erl
@@ -20,24 +20,20 @@
-module(inets_service).
--export([behaviour_info/1]).
-
-behaviour_info(callbacks) ->
- [{start_standalone, 1},
- {start_service, 1},
- {stop_service, 1},
- {services, 0},
- {service_info, 1}];
-behaviour_info(_) ->
- undefined.
-
%% Starts service stand-alone
%% start_standalone(Config) -> % {ok, Pid} | {error, Reason}
%% <service>:start_link(Config).
+-callback start_standalone(Config :: term()) ->
+ {ok, pid()} | {error, Reason :: term()}.
+
%% Starts service as part of inets
%% start_service(Config) -> % {ok, Pid} | {error, Reason}
%% <service_sup>:start_child(Config).
+
+-callback start_service(Config :: term()) ->
+ {ok, pid()} | {error, Reason :: term()}.
+
%% Stop service
%% stop_service(Pid) -> % ok | {error, Reason}
%% <service_sup>:stop_child(maybe_map_pid_to_other_ref(Pid)).
@@ -51,6 +47,9 @@ behaviour_info(_) ->
%% Error
%% end.
+-callback stop_service(Service :: term()) ->
+ ok | {error, Reason :: term()}.
+
%% Returns list of running services. Services started as stand alone
%% are not listed
%% services() -> % [{Service, Pid}]
@@ -59,7 +58,12 @@ behaviour_info(_) ->
%% [{httpc, Pid} || {_, Pid, _, _} <-
%% supervisor:which_children(httpc_profile_sup)].
+-callback services() ->
+ [{Service :: term(), pid()}].
-%% service_info() -> [{Property, Value}] | {error, Reason}
+%% service_info() -> {ok, [{Property, Value}]} | {error, Reason}
%% ex: httpc:service_info() -> [{profile, ProfileName}]
%% httpd:service_info() -> [{host, Host}, {port, Port}]
+
+-callback service_info(Service :: term()) ->
+ {ok, [{Property :: term(), Value :: term()}]} | {error, Reason :: term()}.
diff --git a/lib/inets/src/tftp/tftp.erl b/lib/inets/src/tftp/tftp.erl
index bfdb4c0030..b33c0a98f4 100644
--- a/lib/inets/src/tftp/tftp.erl
+++ b/lib/inets/src/tftp/tftp.erl
@@ -215,8 +215,6 @@
start/0
]).
--export([behaviour_info/1]).
-
%% Application local functions
-export([
start_standalone/1,
@@ -227,13 +225,50 @@
]).
-behaviour_info(callbacks) ->
- [{prepare, 6}, {open, 6}, {read, 1}, {write, 2}, {abort, 3}];
-behaviour_info(_) ->
- undefined.
+-type peer() :: {PeerType :: inet | inet6,
+ PeerHost :: inet:ip_address(),
+ PeerPort :: port()}.
+
+-type access() :: read | write.
+
+-type options() :: [{Key :: string(), Value :: string()}].
+
+-type error_code() :: undef | enoent | eacces | enospc |
+ badop | eexist | baduser | badopt |
+ integer().
+
+-callback prepare(Peer :: peer(),
+ Access :: access(),
+ Filename :: file:name(),
+ Mode :: string(),
+ SuggestedOptions :: options(),
+ InitialState :: [] | [{root_dir, string()}]) ->
+ {ok, AcceptedOptions :: options(), NewState :: term()} |
+ {error, {Code :: error_code(), string()}}.
+
+-callback open(Peer :: peer(),
+ Access :: access(),
+ Filename :: file:name(),
+ Mode :: string(),
+ SuggestedOptions :: options(),
+ State :: [] | [{root_dir, string()}] | term()) ->
+ {ok, AcceptedOptions :: options(), NewState :: term()} |
+ {error, {Code :: error_code(), string()}}.
+
+-callback read(State :: term()) -> {more, binary(), NewState :: term()} |
+ {last, binary(), integer()} |
+ {error, {Code :: error_code(), string()}}.
+
+-callback write(binary(), State :: term()) ->
+ {more, NewState :: term()} |
+ {last, FileSize :: integer()} |
+ {error, {Code :: error_code(), string()}}.
+
+-callback abort(Code :: error_code(), string(), State :: term()) -> 'ok'.
-include("tftp.hrl").
+
%%-------------------------------------------------------------------
%% read_file(RemoteFilename, LocalFilename, Options) ->
%% {ok, LastCallbackState} | {error, Reason}
diff --git a/lib/inets/test/Makefile b/lib/inets/test/Makefile
index 110ad54c3c..87ca60e4b3 100644
--- a/lib/inets/test/Makefile
+++ b/lib/inets/test/Makefile
@@ -308,11 +308,11 @@ release_spec: opt
release_tests_spec: opt
$(INSTALL_DIR) $(RELTESTSYSDIR)
$(INSTALL_DATA) $(RELTEST_FILES) $(RELTESTSYSDIR)
- chmod -f -R u+w $(RELTESTSYSDIR)
+ chmod -R u+w $(RELTESTSYSDIR)
tar chf - $(DATADIRS) | (cd $(RELTESTSYSDIR); tar xf -)
$(INSTALL_DIR) $(RELTESTSYSALLDATADIR)
$(INSTALL_DIR) $(RELTESTSYSBINDIR)
- chmod -f -R +x $(RELTESTSYSBINDIR)
+ chmod -R +x $(RELTESTSYSBINDIR)
$(INSTALL_DIR) $(RELTESTSYSALLDATADIR)/win32/lib
release_docs_spec:
diff --git a/lib/inets/test/ftp_SUITE.erl b/lib/inets/test/ftp_SUITE.erl
index 4bafdbfef8..17e5f6777e 100644
--- a/lib/inets/test/ftp_SUITE.erl
+++ b/lib/inets/test/ftp_SUITE.erl
@@ -57,35 +57,42 @@
%% Description: Returns documentation/test cases in this test suite
%% or a skip tuple if the platform is not supported.
%%--------------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() -> [{ct_hooks, [ts_install_cth]}].
all() ->
- [{group, solaris8_test}, {group, solaris9_test},
- {group, solaris10_test}, {group, linux_x86_test},
- {group, linux_ppc_test}, {group, macosx_x86_test},
- {group, macosx_ppc_test}, {group, openbsd_test},
- {group, freebsd_test}, {group, netbsd_test},
+ [
+ {group, solaris8_test},
+ {group, solaris9_test},
+ {group, solaris10_test},
+ {group, linux_x86_test},
+ {group, linux_ppc_test},
+ {group, macosx_x86_test},
+ {group, macosx_ppc_test},
+ {group, openbsd_test},
+ {group, freebsd_test},
+ {group, netbsd_test},
{group, windows_xp_test},
{group, windows_2003_server_test},
- {group, ticket_tests}].
+ {group, ticket_tests}
+ ].
groups() ->
- [{solaris8_test, [], [{ftp_solaris8_sparc_test, all}]},
- {solaris9_test, [], [{ftp_solaris9_sparc_test, all}]},
- {solaris10_test, [],
- [{ftp_solaris10_sparc_test, all},
- {ftp_solaris10_x86_test, all}]},
- {linux_x86_test, [], [{ftp_linux_x86_test, all}]},
- {linux_ppc_test, [], [{ftp_linux_ppc_test, all}]},
- {macosx_x86_test, [], [{ftp_macosx_x86_test, all}]},
- {macosx_ppc_test, [], [{ftp_macosx_ppc_test, all}]},
- {openbsd_test, [], [{ftp_openbsd_x86_test, all}]},
- {freebsd_test, [], [{ftp_freebsd_x86_test, all}]},
- {netbsd_test, [], [{ftp_netbsd_x86_test, all}]},
- {windows_xp_test, [], [{ftp_windows_xp_test, all}]},
- {windows_2003_server_test, [],
- [{ftp_windows_2003_server_test, all}]},
- {ticket_tests, [], [{ftp_ticket_test, all}]}].
+ [
+ {solaris8_test, [], [{ftp_solaris8_sparc_test, all}]},
+ {solaris9_test, [], [{ftp_solaris9_sparc_test, all}]},
+ {solaris10_test, [], [{ftp_solaris10_sparc_test, all},
+ {ftp_solaris10_x86_test, all}]},
+ {linux_x86_test, [], [{ftp_linux_x86_test, all}]},
+ {linux_ppc_test, [], [{ftp_linux_ppc_test, all}]},
+ {macosx_x86_test, [], [{ftp_macosx_x86_test, all}]},
+ {macosx_ppc_test, [], [{ftp_macosx_ppc_test, all}]},
+ {openbsd_test, [], [{ftp_openbsd_x86_test, all}]},
+ {freebsd_test, [], [{ftp_freebsd_x86_test, all}]},
+ {netbsd_test, [], [{ftp_netbsd_x86_test, all}]},
+ {windows_xp_test, [], [{ftp_windows_xp_test, all}]},
+ {windows_2003_server_test, [], [{ftp_windows_2003_server_test, all}]},
+ {ticket_tests, [], [{ftp_ticket_test, all}]}
+ ].
init_per_group(_GroupName, Config) ->
Config.
diff --git a/lib/inets/test/ftp_suite_lib.erl b/lib/inets/test/ftp_suite_lib.erl
index d0d07a8358..3ebd02229e 100644
--- a/lib/inets/test/ftp_suite_lib.erl
+++ b/lib/inets/test/ftp_suite_lib.erl
@@ -1129,10 +1129,16 @@ ticket_6035(Config) ->
LogFile = filename:join([PrivDir,"ticket_6035.log"]),
try
begin
+ p("ticket_6035 -> select ftpd host"),
Host = dirty_select_ftpd_host(Config),
+ p("ticket_6035 -> ftpd host selected (~p) => now spawn ftp owner", [Host]),
Pid = spawn(?MODULE, open_wait_6035, [Host, self()]),
+ p("ticket_6035 -> waiter spawned: ~p => now open error logfile (~p)",
+ [Pid, LogFile]),
error_logger:logfile({open, LogFile}),
- ok = kill_ftp_proc_6035(Pid,LogFile),
+ p("ticket_6035 -> error logfile open => now kill waiter process"),
+ true = kill_ftp_proc_6035(Pid, LogFile),
+ p("ticket_6035 -> waiter process killed => now close error logfile"),
error_logger:logfile(close),
p("ticket_6035 -> done", []),
ok
@@ -1146,7 +1152,7 @@ kill_ftp_proc_6035(Pid, LogFile) ->
p("kill_ftp_proc_6035 -> entry"),
receive
open ->
- p("kill_ftp_proc_6035 -> received open: send shutdown"),
+ p("kill_ftp_proc_6035 -> received open => now issue shutdown"),
exit(Pid, shutdown),
kill_ftp_proc_6035(Pid, LogFile);
{open_failed, Reason} ->
@@ -1159,11 +1165,11 @@ kill_ftp_proc_6035(Pid, LogFile) ->
is_error_report_6035(LogFile)
end.
-open_wait_6035(FtpServer, From) ->
- p("open_wait_6035 -> try connect to ~s", [FtpServer]),
+open_wait_6035({Tag, FtpServer}, From) ->
+ p("open_wait_6035 -> try connect to [~p] ~s for ~p", [Tag, FtpServer, From]),
case ftp:open(FtpServer, [{timeout, timer:seconds(15)}]) of
{ok, Pid} ->
- p("open_wait_6035 -> connected, now login"),
+ p("open_wait_6035 -> connected (~p), now login", [Pid]),
LoginResult = ftp:user(Pid,"anonymous","kldjf"),
p("open_wait_6035 -> login result: ~p", [LoginResult]),
From ! open,
@@ -1191,22 +1197,27 @@ is_error_report_6035(LogFile) ->
Res =
case file:read_file(LogFile) of
{ok, Bin} ->
- p("is_error_report_6035 -> logfile read"),
- read_log_6035(binary_to_list(Bin));
+ Txt = binary_to_list(Bin),
+ p("is_error_report_6035 -> logfile read: ~n~p", [Txt]),
+ read_log_6035(Txt);
_ ->
- ok
+ false
end,
p("is_error_report_6035 -> logfile read result: "
"~n ~p", [Res]),
- file:delete(LogFile),
+ %% file:delete(LogFile),
Res.
read_log_6035("=ERROR REPORT===="++_Rest) ->
- error_report;
-read_log_6035([_H|T]) ->
+ p("read_log_6035 -> ERROR REPORT detected"),
+ true;
+read_log_6035([H|T]) ->
+ p("read_log_6035 -> OTHER: "
+ "~p", [H]),
read_log_6035(T);
read_log_6035([]) ->
- ok.
+ p("read_log_6035 -> done"),
+ false.
%%--------------------------------------------------------------------
diff --git a/lib/inets/test/http_format_SUITE.erl b/lib/inets/test/http_format_SUITE.erl
index 931ac6e024..04c7358715 100644
--- a/lib/inets/test/http_format_SUITE.erl
+++ b/lib/inets/test/http_format_SUITE.erl
@@ -584,7 +584,9 @@ convert_netscapecookie_date(Config) when is_list(Config) ->
http_util:convert_netscapecookie_date("Sun, 12-Dec-06 08:59:38 GMT"),
{{2006,12,12},{8,59,38}} =
http_util:convert_netscapecookie_date("Sun 12-Dec-06 08:59:38 GMT"),
- ok.
+ {{2036,1,1},{8,0,1}} =
+ http_util:convert_netscapecookie_date("Tue Jan 01 08:00:01 2036 GMT"),
+ ok.
%%--------------------------------------------------------------------
%%% Internal functions
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index 2c8febf5ed..f95fb93669 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -28,6 +28,7 @@
-include("test_server_line.hrl").
-include_lib("kernel/include/file.hrl").
+-include("inets_test_lib.hrl").
%% Note: This directive should only be used in test suites.
-compile(export_all).
@@ -62,36 +63,88 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [proxy_options, proxy_head, proxy_get, proxy_trace,
- proxy_post, proxy_put, proxy_delete, proxy_auth,
- proxy_headers, proxy_emulate_lower_versions,
- http_options, http_head, http_get, http_post,
- http_dummy_pipe, http_inets_pipe, http_trace,
- http_async, http_save_to_file, http_save_to_file_async,
- http_headers, http_headers_dummy, http_bad_response,
- ssl_head, ossl_head, essl_head, ssl_get, ossl_get,
- essl_get, ssl_trace, ossl_trace, essl_trace,
- http_redirect, http_redirect_loop,
- http_internal_server_error, http_userinfo, http_cookie,
- http_server_does_not_exist, http_invalid_http,
- http_emulate_lower_versions, http_relaxed,
- page_does_not_exist, proxy_page_does_not_exist,
- proxy_https_not_supported, http_stream,
- http_stream_once, proxy_stream, parse_url, options,
- ipv6, headers_as_is, {group, tickets}].
+ [
+ http_options,
+ http_head,
+ http_get,
+ http_post,
+ http_post_streaming,
+ http_dummy_pipe,
+ http_inets_pipe,
+ http_trace,
+ http_async,
+ http_save_to_file,
+ http_save_to_file_async,
+ http_headers,
+ http_headers_dummy,
+ http_bad_response,
+ http_redirect,
+ http_redirect_loop,
+ http_internal_server_error,
+ http_userinfo, http_cookie,
+ http_server_does_not_exist,
+ http_invalid_http,
+ http_emulate_lower_versions,
+ http_relaxed,
+ page_does_not_exist,
+ parse_url,
+ options,
+ headers_as_is,
+ {group, proxy},
+ {group, ssl},
+ {group, stream},
+ {group, ipv6},
+ {group, tickets},
+ initial_server_connect
+ ].
groups() ->
- [{tickets, [],
- [hexed_query_otp_6191, empty_body_otp_6243,
- empty_response_header_otp_6830,
- transfer_encoding_otp_6807, proxy_not_modified_otp_6821,
- no_content_204_otp_6982, missing_CR_otp_7304,
- {group, otp_7883}, {group, otp_8154}, {group, otp_8106},
- otp_8056, otp_8352, otp_8371, otp_8739]},
- {otp_7883, [], [otp_7883_1, otp_7883_2]},
+ [
+ {proxy, [], [proxy_options,
+ proxy_head,
+ proxy_get,
+ proxy_trace,
+ proxy_post,
+ proxy_put,
+ proxy_delete,
+ proxy_auth,
+ proxy_headers,
+ proxy_emulate_lower_versions,
+ proxy_page_does_not_exist,
+ proxy_https_not_supported]},
+ {ssl, [], [ssl_head,
+ essl_head,
+ ssl_get,
+ essl_get,
+ ssl_trace,
+ essl_trace]},
+ {stream, [], [http_stream,
+ http_stream_once,
+ proxy_stream]},
+ {tickets, [], [hexed_query_otp_6191,
+ empty_body_otp_6243,
+ empty_response_header_otp_6830,
+ transfer_encoding_otp_6807,
+ proxy_not_modified_otp_6821,
+ no_content_204_otp_6982,
+ missing_CR_otp_7304,
+ {group, otp_7883},
+ {group, otp_8154},
+ {group, otp_8106},
+ otp_8056,
+ otp_8352,
+ otp_8371,
+ otp_8739]},
+ {otp_7883, [], [otp_7883_1,
+ otp_7883_2]},
{otp_8154, [], [otp_8154_1]},
- {otp_8106, [],
- [otp_8106_pid, otp_8106_fun, otp_8106_mfa]}].
+ {otp_8106, [], [otp_8106_pid,
+ otp_8106_fun,
+ otp_8106_mfa]},
+ {ipv6, [], [ipv6_ipcomm, ipv6_essl]}
+ ].
+
+
init_per_group(_GroupName, Config) ->
Config.
@@ -138,6 +191,7 @@ init_per_suite(Config) ->
{local_port, ?IP_PORT},
{local_ssl_port, ?SSL_PORT} | Config].
+
%%--------------------------------------------------------------------
%% Function: end_per_suite(Config) -> _
%% Config - [tuple()]
@@ -163,25 +217,41 @@ end_per_suite(Config) ->
%% 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_testcase(otp_8154_1 = Case, Config) ->
init_per_testcase(Case, 5, Config);
+
+init_per_testcase(initial_server_connect = Case, Config) ->
+ %% Try to check if crypto actually exist or not,
+ %% this test case does not work unless it does
+ try
+ begin
+ ensure_started(crypto),
+ ensure_started(public_key),
+ ensure_started(ssl),
+ inets:start(),
+ Config
+ end
+ catch
+ throw:{error, {failed_starting, App, ActualError}} ->
+ tsp("init_per_testcase(~w) -> failed starting ~w: "
+ "~n ~p", [Case, App, ActualError]),
+ SkipString =
+ "Could not start " ++ atom_to_list(App),
+ {skip, SkipString};
+ _:X ->
+ SkipString =
+ lists:flatten(
+ io_lib:format("Failed starting apps: ~p", [X])),
+ {skip, SkipString}
+ end;
+
init_per_testcase(Case, Config) ->
init_per_testcase(Case, 2, Config).
-init_per_testcase_ssl(Tag, PrivDir, SslConfFile, Config) ->
- tsp("init_per_testcase_ssl -> stop ssl"),
- application:stop(ssl),
- Config2 = lists:keydelete(local_ssl_server, 1, Config),
- %% Will start inets
- tsp("init_per_testcase_ssl -> try start http server (including inets)"),
- Server = inets_test_lib:start_http_server(
- filename:join(PrivDir, SslConfFile), Tag),
- tsp("init_per_testcase -> Server: ~p", [Server]),
- [{local_ssl_server, Server} | Config2].
-
init_per_testcase(Case, Timeout, Config) ->
- io:format(user, "~n~n*** INIT ~w:[~w][~w] ***~n~n",
- [?MODULE, Timeout, Case]),
+ io:format(user, "~n~n*** INIT ~w:~w[~w] ***~n~n",
+ [?MODULE, Case, Timeout]),
PrivDir = ?config(priv_dir, Config),
tsp("init_per_testcase -> stop inets"),
application:stop(inets),
@@ -197,39 +267,99 @@ init_per_testcase(Case, Timeout, Config) ->
NewConfig =
case atom_to_list(Case) of
[$s, $s, $l | _] ->
- init_per_testcase_ssl(ssl, PrivDir, SslConfFile, [{watchdog, Dog} | TmpConfig]);
-
- [$o, $s, $s, $l | _] ->
- init_per_testcase_ssl(ossl, PrivDir, SslConfFile, [{watchdog, Dog} | TmpConfig]);
+ init_per_testcase_ssl(ssl, PrivDir, SslConfFile,
+ [{watchdog, Dog} | TmpConfig]);
[$e, $s, $s, $l | _] ->
- init_per_testcase_ssl(essl, PrivDir, SslConfFile, [{watchdog, Dog} | TmpConfig]);
+ init_per_testcase_ssl(essl, PrivDir, SslConfFile,
+ [{watchdog, Dog} | TmpConfig]);
- "proxy" ++ Rest ->
+ "proxy_" ++ Rest ->
+ io:format("init_per_testcase -> Rest: ~p~n", [Rest]),
case Rest of
- "_https_not_supported" ->
+ "https_not_supported" ->
tsp("init_per_testcase -> [proxy case] start inets"),
inets:start(),
- tsp("init_per_testcase -> [proxy case] start ssl"),
- application:start(crypto),
- application:start(public_key),
- case (catch application:start(ssl)) of
+ tsp("init_per_testcase -> "
+ "[proxy case] start crypto, public_key and ssl"),
+ try ensure_started([crypto, public_key, ssl]) of
ok ->
- [{watchdog, Dog} | TmpConfig];
- _ ->
- [{skip, "SSL does not seem to be supported"}
- | TmpConfig]
+ [{watchdog, Dog} | TmpConfig]
+ catch
+ throw:{error, {failed_starting, App, _}} ->
+ SkipString =
+ "Could not start " ++ atom_to_list(App),
+ {skip, SkipString};
+ _:X ->
+ SkipString =
+ lists:flatten(
+ io_lib:format("Failed starting apps: ~p", [X])),
+ {skip, SkipString}
end;
+
_ ->
+ %% We use erlang.org for the proxy tests
+ %% and after the switch to erlang-web, many
+ %% of the test cases no longer work (erlang.org
+ %% previously run on Apache).
+ %% Until we have had time to update inets
+ %% (and updated erlang.org to use that inets)
+ %% and the test cases, we simply skip the
+ %% problematic test cases.
+ %% This is not ideal, but I am busy....
case is_proxy_available(?PROXY, ?PROXY_PORT) of
true ->
- inets:start(),
- [{watchdog, Dog} | TmpConfig];
+ BadCases =
+ [
+ "delete",
+ "get",
+ "head",
+ "not_modified_otp_6821",
+ "options",
+ "page_does_not_exist",
+ "post",
+ "put",
+ "stream"
+ ],
+ case lists:member(Rest, BadCases) of
+ true ->
+ [{skip, "TC and server not compatible"}|
+ TmpConfig];
+ false ->
+ inets:start(),
+ [{watchdog, Dog} | TmpConfig]
+ end;
false ->
- [{skip, "Failed to contact proxy"} |
- TmpConfig]
+ [{skip, "proxy not responding"} | TmpConfig]
end
end;
+
+ "ipv6_" ++ _Rest ->
+ %% Ensure needed apps (crypto, public_key and ssl) started
+ try ensure_started([crypto, public_key, ssl]) of
+ ok ->
+ Profile = ipv6,
+ %% A stand-alone profile is represented by a pid()
+ {ok, ProfilePid} =
+ inets:start(httpc,
+ [{profile, Profile},
+ {data_dir, PrivDir}], stand_alone),
+ httpc:set_options([{ipfamily, inet6}], ProfilePid),
+ tsp("httpc profile pid: ~p", [ProfilePid]),
+ [{watchdog, Dog}, {profile, ProfilePid}| TmpConfig]
+ catch
+ throw:{error, {failed_starting, App, ActualError}} ->
+ tsp("init_per_testcase(~w) -> failed starting ~w: "
+ "~n ~p", [Case, App, ActualError]),
+ SkipString =
+ "Could not start " ++ atom_to_list(App),
+ {skip, SkipString};
+ _:X ->
+ SkipString =
+ lists:flatten(
+ io_lib:format("Failed starting apps: ~p", [X])),
+ {skip, SkipString}
+ end;
_ ->
TmpConfig2 = lists:keydelete(local_server, 1, TmpConfig),
Server =
@@ -239,9 +369,7 @@ init_per_testcase(Case, Timeout, Config) ->
[{watchdog, Dog}, {local_server, Server} | TmpConfig2]
end,
- %% httpc:set_options([{proxy, {{?PROXY, ?PROXY_PORT},
- %% ["localhost", ?IPV6_LOCAL_HOST]}}]),
-
+ %% This will fail for the ipv6_ - cases (but that is ok)
httpc:set_options([{proxy, {{?PROXY, ?PROXY_PORT},
["localhost", ?IPV6_LOCAL_HOST]}},
{ipfamily, inet6fb4}]),
@@ -250,6 +378,19 @@ init_per_testcase(Case, Timeout, Config) ->
NewConfig.
+init_per_testcase_ssl(Tag, PrivDir, SslConfFile, Config) ->
+ tsp("init_per_testcase_ssl(~w) -> stop ssl", [Tag]),
+ application:stop(ssl),
+ Config2 = lists:keydelete(local_ssl_server, 1, Config),
+ %% Will start inets
+ tsp("init_per_testcase_ssl(~w) -> try start http server (including inets)",
+ [Tag]),
+ Server = inets_test_lib:start_http_server(
+ filename:join(PrivDir, SslConfFile), Tag),
+ tsp("init_per_testcase(~w) -> Server: ~p", [Tag, Server]),
+ [{local_ssl_server, Server} | Config2].
+
+
%%--------------------------------------------------------------------
%% Function: end_per_testcase(Case, Config) -> _
%% Case - atom()
@@ -258,13 +399,36 @@ init_per_testcase(Case, Timeout, Config) ->
%% A list of key/value pairs, holding the test case configuration.
%% Description: Cleanup after each test case
%%--------------------------------------------------------------------
-end_per_testcase(http_save_to_file, Config) ->
- PrivDir = ?config(priv_dir, Config),
+end_per_testcase(http_save_to_file = Case, Config) ->
+ io:format(user, "~n~n*** END ~w:~w ***~n~n",
+ [?MODULE, Case]),
+ PrivDir = ?config(priv_dir, Config),
FullPath = filename:join(PrivDir, "dummy.html"),
file:delete(FullPath),
finish(Config);
-end_per_testcase(_, Config) ->
+end_per_testcase(Case, Config) ->
+ io:format(user, "~n~n*** END ~w:~w ***~n~n",
+ [?MODULE, Case]),
+ case atom_to_list(Case) of
+ "ipv6_" ++ _Rest ->
+ tsp("end_per_testcase(~w) -> stop ssl", [Case]),
+ application:stop(ssl),
+ tsp("end_per_testcase(~w) -> stop public_key", [Case]),
+ application:stop(public_key),
+ tsp("end_per_testcase(~w) -> stop crypto", [Case]),
+ application:stop(crypto),
+ ProfilePid = ?config(profile, Config),
+ tsp("end_per_testcase(~w) -> stop httpc profile (~p)",
+ [Case, ProfilePid]),
+ unlink(ProfilePid),
+ inets:stop(stand_alone, ProfilePid),
+ tsp("end_per_testcase(~w) -> httpc profile (~p) stopped",
+ [Case, ProfilePid]),
+ ok;
+ _ ->
+ ok
+ end,
finish(Config).
finish(Config) ->
@@ -273,6 +437,7 @@ finish(Config) ->
undefined ->
ok;
_ ->
+ tsp("finish -> stop watchdog (~p)", [Dog]),
test_server:timetrap_cancel(Dog)
end.
@@ -395,6 +560,53 @@ http_post(Config) when is_list(Config) ->
end.
%%-------------------------------------------------------------------------
+http_post_streaming(doc) ->
+ ["Test streaming http post request against local server. "
+ "We only care about the client side of the the post. "
+ "The server script will not actually use the post data."];
+http_post_streaming(suite) ->
+ [];
+http_post_streaming(Config) when is_list(Config) ->
+ case ?config(local_server, Config) of
+ ok ->
+ Port = ?config(local_port, Config),
+ URL = case test_server:os_type() of
+ {win32, _} ->
+ ?URL_START ++ integer_to_list(Port) ++
+ "/cgi-bin/cgi_echo.exe";
+ _ ->
+ ?URL_START ++ integer_to_list(Port) ++
+ "/cgi-bin/cgi_echo"
+ end,
+ %% Cgi-script expects the body length to be 100
+ BodyFun = fun(0) ->
+ io:format("~w:http_post_streaming_fun -> "
+ "zero~n", [?MODULE]),
+ eof;
+ (LenLeft) ->
+ io:format("~w:http_post_streaming_fun -> "
+ "LenLeft: ~p~n", [?MODULE, LenLeft]),
+ {ok, lists:duplicate(10, "1"), LenLeft - 10}
+ end,
+
+ {ok, {{_,200,_}, [_ | _], [_ | _]}} =
+ httpc:request(post, {URL,
+ [{"expect", "100-continue"},
+ {"content-length", "100"}],
+ "text/plain", {BodyFun, 100}}, [], []),
+
+ {ok, {{_,504,_}, [_ | _], []}} =
+ httpc:request(post, {URL,
+ [{"expect", "100-continue"},
+ {"content-length", "10"}],
+ "text/plain", {BodyFun, 10}}, [], []);
+
+ _ ->
+ {skip, "Failed to start local http-server"}
+ end.
+
+
+%%-------------------------------------------------------------------------
http_emulate_lower_versions(doc) ->
["Perform request as 0.9 and 1.0 clients."];
http_emulate_lower_versions(suite) ->
@@ -427,7 +639,7 @@ http_relaxed(suite) ->
http_relaxed(Config) when is_list(Config) ->
ok = httpc:set_options([{ipv6, disabled}]), % also test the old option
%% ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++
"/missing_reason_phrase.html",
@@ -453,7 +665,7 @@ http_dummy_pipe(suite) ->
[];
http_dummy_pipe(Config) when is_list(Config) ->
ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++ "/foobar.html",
@@ -478,34 +690,35 @@ http_inets_pipe(Config) when is_list(Config) ->
{skip, "Failed to start local http-server"}
end.
+
test_pipeline(URL) ->
- p("test_pipeline -> entry with"
- "~n URL: ~p", [URL]),
+ p("test_pipeline -> entry with"
+ "~n URL: ~p", [URL]),
- httpc:set_options([{pipeline_timeout, 50000}]),
-
- p("test_pipeline -> issue (async) request 1"),
- {ok, RequestId1} =
+ httpc:set_options([{pipeline_timeout, 50000}]),
+
+ p("test_pipeline -> issue (async) request 1"),
+ {ok, RequestId1} =
httpc:request(get, {URL, []}, [], [{sync, false}]),
- test_server:format("RequestId1: ~p~n", [RequestId1]),
- p("test_pipeline -> RequestId1: ~p", [RequestId1]),
+ test_server:format("RequestId1: ~p~n", [RequestId1]),
+ p("test_pipeline -> RequestId1: ~p", [RequestId1]),
- %% Make sure pipeline is initiated
- p("test_pipeline -> sleep some", []),
- test_server:sleep(4000),
+ %% Make sure pipeline is initiated
+ p("test_pipeline -> sleep some", []),
+ test_server:sleep(4000),
- p("test_pipeline -> issue (async) request 2"),
- {ok, RequestId2} =
+ p("test_pipeline -> issue (async) request 2"),
+ {ok, RequestId2} =
httpc:request(get, {URL, []}, [], [{sync, false}]),
- tsp("RequestId2: ~p", [RequestId2]),
- p("test_pipeline -> RequestId2: ~p", [RequestId2]),
+ tsp("RequestId2: ~p", [RequestId2]),
+ p("test_pipeline -> RequestId2: ~p", [RequestId2]),
- p("test_pipeline -> issue (sync) request 3"),
- {ok, {{_,200,_}, [_ | _], [_ | _]}} =
+ p("test_pipeline -> issue (sync) request 3"),
+ {ok, {{_,200,_}, [_ | _], [_ | _]}} =
httpc:request(get, {URL, []}, [], []),
p("test_pipeline -> expect reply for (async) request 1 or 2"),
- receive
+ receive
{http, {RequestId1, {{_, 200, _}, _, _}}} ->
p("test_pipeline -> received reply for (async) request 1 - now wait for 2"),
receive
@@ -523,46 +736,46 @@ test_pipeline(URL) ->
ok;
{http, Msg2} ->
test_server:fail(Msg2)
- end;
+ end;
{http, Msg3} ->
test_server:fail(Msg3)
- after 60000 ->
- receive Any1 ->
- tsp("received crap after timeout: ~n ~p", [Any1]),
- test_server:fail({error, {timeout, Any1}})
- end
+ after 60000 ->
+ receive Any1 ->
+ tsp("received crap after timeout: ~n ~p", [Any1]),
+ test_server:fail({error, {timeout, Any1}})
+ end
end,
-
- p("test_pipeline -> sleep some"),
- test_server:sleep(4000),
- p("test_pipeline -> issue (async) request 4"),
- {ok, RequestId3} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
- tsp("RequestId3: ~p", [RequestId3]),
- p("test_pipeline -> RequestId3: ~p", [RequestId3]),
+ p("test_pipeline -> sleep some"),
+ test_server:sleep(4000),
- p("test_pipeline -> issue (async) request 5"),
- {ok, RequestId4} =
+ p("test_pipeline -> issue (async) request 4"),
+ {ok, RequestId3} =
httpc:request(get, {URL, []}, [], [{sync, false}]),
- tsp("RequestId4: ~p~n", [RequestId4]),
- p("test_pipeline -> RequestId4: ~p", [RequestId4]),
-
- p("test_pipeline -> cancel (async) request 4"),
- ok = httpc:cancel_request(RequestId3),
-
- p("test_pipeline -> expect *no* reply for cancelled (async) request 4 (for 3 secs)"),
- receive
- {http, {RequestId3, _}} ->
- test_server:fail(http_cancel_request_failed)
- after 3000 ->
- ok
- end,
+ tsp("RequestId3: ~p", [RequestId3]),
+ p("test_pipeline -> RequestId3: ~p", [RequestId3]),
- p("test_pipeline -> expect reply for (async) request 4"),
- Body =
- receive
- {http, {RequestId4, {{_, 200, _}, _, BinBody4}}} = Res ->
+ p("test_pipeline -> issue (async) request 5"),
+ {ok, RequestId4} =
+ httpc:request(get, {URL, []}, [], [{sync, false}]),
+ tsp("RequestId4: ~p~n", [RequestId4]),
+ p("test_pipeline -> RequestId4: ~p", [RequestId4]),
+
+ p("test_pipeline -> cancel (async) request 4"),
+ ok = httpc:cancel_request(RequestId3),
+
+ p("test_pipeline -> expect *no* reply for cancelled (async) request 4 (for 3 secs)"),
+ receive
+ {http, {RequestId3, _}} ->
+ test_server:fail(http_cancel_request_failed)
+ after 3000 ->
+ ok
+ end,
+
+ p("test_pipeline -> expect reply for (async) request 4"),
+ Body =
+ receive
+ {http, {RequestId4, {{_, 200, _}, _, BinBody4}}} = Res ->
p("test_pipeline -> received reply for (async) request 5"),
tsp("Receive : ~p", [Res]),
BinBody4;
@@ -577,9 +790,9 @@ test_pipeline(URL) ->
p("test_pipeline -> check reply for (async) request 5"),
inets_test_lib:check_body(binary_to_list(Body)),
-
+
p("test_pipeline -> ensure no unexpected incomming"),
- receive
+ receive
{http, Any} ->
test_server:fail({unexpected_message, Any})
after 500 ->
@@ -589,8 +802,6 @@ test_pipeline(URL) ->
p("test_pipeline -> done"),
ok.
-
-
%%-------------------------------------------------------------------------
http_trace(doc) ->
["Perform a TRACE request that goes through a proxy."];
@@ -768,7 +979,7 @@ http_headers_dummy(suite) ->
[];
http_headers_dummy(Config) when is_list(Config) ->
ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy_headers.html",
@@ -833,7 +1044,7 @@ http_bad_response(suite) ->
[];
http_bad_response(Config) when is_list(Config) ->
ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++ "/missing_crlf.html",
@@ -858,13 +1069,6 @@ ssl_head(suite) ->
ssl_head(Config) when is_list(Config) ->
ssl_head(ssl, Config).
-ossl_head(doc) ->
- ["Same as http_head/1 but over ssl sockets."];
-ossl_head(suite) ->
- [];
-ossl_head(Config) when is_list(Config) ->
- ssl_head(ossl, Config).
-
essl_head(doc) ->
["Same as http_head/1 but over ssl sockets."];
essl_head(suite) ->
@@ -887,8 +1091,6 @@ ssl_head(SslTag, Config) ->
case SslTag of
ssl ->
SSLOptions;
- ossl ->
- {ossl, SSLOptions};
essl ->
{essl, SSLOptions}
end,
@@ -913,13 +1115,6 @@ ssl_get(suite) ->
ssl_get(Config) when is_list(Config) ->
ssl_get(ssl, Config).
-ossl_get(doc) ->
- ["Same as http_get/1 but over ssl sockets."];
-ossl_get(suite) ->
- [];
-ossl_get(Config) when is_list(Config) ->
- ssl_get(ossl, Config).
-
essl_get(doc) ->
["Same as http_get/1 but over ssl sockets."];
essl_get(suite) ->
@@ -939,8 +1134,6 @@ ssl_get(SslTag, Config) when is_list(Config) ->
case SslTag of
ssl ->
SSLOptions;
- ossl ->
- {ossl, SSLOptions};
essl ->
{essl, SSLOptions}
end,
@@ -952,9 +1145,9 @@ ssl_get(SslTag, Config) when is_list(Config) ->
httpc:request(get, {URL, []}, [{ssl, SSLConfig}], []),
inets_test_lib:check_body(Body);
{ok, _} ->
- {skip, "Failed to start local http-server"};
+ {skip, "local http-server not started"};
_ ->
- {skip, "Failed to start SSL"}
+ {skip, "SSL not started"}
end.
@@ -966,13 +1159,6 @@ ssl_trace(suite) ->
ssl_trace(Config) when is_list(Config) ->
ssl_trace(ssl, Config).
-ossl_trace(doc) ->
- ["Same as http_trace/1 but over ssl sockets."];
-ossl_trace(suite) ->
- [];
-ossl_trace(Config) when is_list(Config) ->
- ssl_trace(ossl, Config).
-
essl_trace(doc) ->
["Same as http_trace/1 but over ssl sockets."];
essl_trace(suite) ->
@@ -992,8 +1178,6 @@ ssl_trace(SslTag, Config) when is_list(Config) ->
case SslTag of
ssl ->
SSLOptions;
- ossl ->
- {ossl, SSLOptions};
essl ->
{essl, SSLOptions}
end,
@@ -1012,9 +1196,9 @@ ssl_trace(SslTag, Config) when is_list(Config) ->
tsf({failed, Error})
end;
{ok, _} ->
- {skip, "Failed to start local http-server"};
+ {skip, "local http-server not started"};
_ ->
- {skip, "Failed to start SSL"}
+ {skip, "SSL not started"}
end.
@@ -1033,7 +1217,7 @@ http_redirect(Config) when is_list(Config) ->
ok = httpc:set_options([{ipfamily, inet}]),
tsp("http_redirect -> start dummy server inet"),
- {DummyServerPid, Port} = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(ipv4),
tsp("http_redirect -> server port = ~p", [Port]),
URL300 = ?URL_START ++ integer_to_list(Port) ++ "/300.html",
@@ -1145,7 +1329,7 @@ http_redirect_loop(suite) ->
[];
http_redirect_loop(Config) when is_list(Config) ->
ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++ "/redirectloop.html",
@@ -1162,7 +1346,7 @@ http_internal_server_error(suite) ->
[];
http_internal_server_error(Config) when is_list(Config) ->
ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(ipv4),
URL500 = ?URL_START ++ integer_to_list(Port) ++ "/500.html",
@@ -1198,7 +1382,7 @@ http_userinfo(suite) ->
http_userinfo(Config) when is_list(Config) ->
ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(ipv4),
URLAuth = "http://alladin:sesame@localhost:"
++ integer_to_list(Port) ++ "/userinfo.html",
@@ -1224,7 +1408,7 @@ http_cookie(suite) ->
[];
http_cookie(Config) when is_list(Config) ->
ok = httpc:set_options([{cookies, enabled}, {ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(ipv4),
URLStart = ?URL_START
++ integer_to_list(Port),
@@ -1253,6 +1437,9 @@ proxy_options(doc) ->
proxy_options(suite) ->
[];
proxy_options(Config) when is_list(Config) ->
+ %% As of 2011-03-24, erlang.org (which is used as server)
+ %% does no longer run Apache, but instead runs inets, which
+ %% do not implement "options".
case ?config(skip, Config) of
undefined ->
case httpc:request(options, {?PROXY_URL, []}, [], []) of
@@ -1277,6 +1464,8 @@ proxy_head(doc) ->
proxy_head(suite) ->
[];
proxy_head(Config) when is_list(Config) ->
+ %% As of 2011-03-24, erlang.org (which is used as server)
+ %% does no longer run Apache, but instead runs inets.
case ?config(skip, Config) of
undefined ->
case httpc:request(head, {?PROXY_URL, []}, [], []) of
@@ -1372,6 +1561,8 @@ proxy_post(doc) ->
proxy_post(suite) ->
[];
proxy_post(Config) when is_list(Config) ->
+ %% As of 2011-03-24, erlang.org (which is used as server)
+ %% does no longer run Apache, but instead runs inets.
case ?config(skip, Config) of
undefined ->
case httpc:request(post, {?PROXY_URL, [],
@@ -1394,6 +1585,8 @@ proxy_put(doc) ->
proxy_put(suite) ->
[];
proxy_put(Config) when is_list(Config) ->
+ %% As of 2011-03-24, erlang.org (which is used as server)
+ %% does no longer run Apache, but instead runs inets.
case ?config(skip, Config) of
undefined ->
case httpc:request(put, {"http://www.erlang.org/foobar.html", [],
@@ -1418,6 +1611,8 @@ proxy_delete(doc) ->
proxy_delete(suite) ->
[];
proxy_delete(Config) when is_list(Config) ->
+ %% As of 2011-03-24, erlang.org (which is used as server)
+ %% does no longer run Apache, but instead runs inets.
case ?config(skip, Config) of
undefined ->
URL = ?PROXY_URL ++ "/foobar.html",
@@ -1541,25 +1736,11 @@ proxy_https_not_supported(suite) ->
proxy_https_not_supported(Config) when is_list(Config) ->
Result = httpc:request(get, {"https://login.yahoo.com", []}, [], []),
case Result of
- {error, Reason} ->
- %% ok so far
- case Reason of
- {failed_connecting, Why} ->
- %% ok, now check why
- case Why of
- https_through_proxy_is_not_currently_supported ->
- ok;
- _ ->
- tsf({unexpected_why, Why})
- end;
- _ ->
- tsf({unexpected_reason, Reason})
- end;
+ {error, https_through_proxy_is_not_currently_supported} ->
+ ok;
_ ->
- tsf({unexpected_result, Result})
- end,
- ok.
-
+ tsf({unexpected_reason, Result})
+ end.
%%-------------------------------------------------------------------------
@@ -1601,7 +1782,7 @@ http_stream_once(Config) when is_list(Config) ->
p("http_stream_once -> set ipfamily to inet", []),
ok = httpc:set_options([{ipfamily, inet}]),
p("http_stream_once -> start dummy server", []),
- {DummyServerPid, Port} = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(ipv4),
PortStr = integer_to_list(Port),
p("http_stream_once -> once", []),
@@ -1737,28 +1918,79 @@ parse_url(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
-ipv6() ->
- [{require,ipv6_hosts}].
-ipv6(doc) ->
- ["Test ipv6."];
-ipv6(suite) ->
- [];
-ipv6(Config) when is_list(Config) ->
- {ok, Hostname} = inet:gethostname(),
-
- case lists:member(list_to_atom(Hostname),
- ct:get_config(ipv6_hosts)) of
- true ->
- {DummyServerPid, Port} = dummy_server(self(), ipv6),
-
- URL = "http://[" ++ ?IPV6_LOCAL_HOST ++ "]:" ++
+
+ipv6_ipcomm() ->
+ [{require, ipv6_hosts}].
+ipv6_ipcomm(doc) ->
+ ["Test ip_comm ipv6."];
+ipv6_ipcomm(suite) ->
+ [];
+ipv6_ipcomm(Config) when is_list(Config) ->
+ HTTPOptions = [],
+ SocketType = ip_comm,
+ Scheme = "http",
+ Extra = [],
+ ipv6(SocketType, Scheme, HTTPOptions, Extra, Config).
+
+
+%%-------------------------------------------------------------------------
+
+ipv6_essl() ->
+ [{require, ipv6_hosts}].
+ipv6_essl(doc) ->
+ ["Test essl ipv6."];
+ipv6_essl(suite) ->
+ [];
+ipv6_essl(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ CertFile = filename:join(DataDir, "ssl_client_cert.pem"),
+ SSLOptions = [{certfile, CertFile}, {keyfile, CertFile}],
+ SSLConfig = {essl, SSLOptions},
+ tsp("ssl_ipv6 -> make request using: "
+ "~n SSLOptions: ~p", [SSLOptions]),
+ HTTPOptions = [{ssl, SSLConfig}],
+ SocketType = essl,
+ Scheme = "https",
+ Extra = SSLOptions,
+ ipv6(SocketType, Scheme, HTTPOptions, Extra, Config).
+
+
+%%-------------------------------------------------------------------------
+
+ipv6(SocketType, Scheme, HTTPOptions, Extra, Config) ->
+ %% Check if we are a IPv6 host
+ tsp("ipv6 -> verify ipv6 support", []),
+ case inets_test_lib:has_ipv6_support(Config) of
+ {ok, Addr} ->
+ tsp("ipv6 -> ipv6 supported: ~p", [Addr]),
+ {DummyServerPid, Port} = dummy_server(SocketType, ipv6, Extra),
+ Profile = ?config(profile, Config),
+ URL =
+ Scheme ++
+ "://[" ++ http_transport:ipv6_name(Addr) ++ "]:" ++
integer_to_list(Port) ++ "/foobar.html",
- {ok, {{_,200,_}, [_ | _], [_|_]}} =
- httpc:request(get, {URL, []}, [], []),
-
- DummyServerPid ! stop,
+ tsp("ipv6 -> issue request with: "
+ "~n URL: ~p"
+ "~n HTTPOptions: ~p", [URL, HTTPOptions]),
+ case httpc:request(get, {URL, []}, HTTPOptions, [], Profile) of
+ {ok, {{_,200,_}, [_ | _], [_|_]}} ->
+ tsp("ipv6 -> expected result"),
+ DummyServerPid ! stop,
+ ok;
+ {ok, Unexpected} ->
+ tsp("ipv6 -> unexpected result: "
+ "~n ~p", [Unexpected]),
+ DummyServerPid ! stop,
+ tsf({unexpected_result, Unexpected});
+ {error, Reason} ->
+ tsp("ipv6 -> error: "
+ "~n Reason: ~p", [Reason]),
+ DummyServerPid ! stop,
+ tsf(Reason)
+ end,
ok;
- false ->
+ _ ->
+ tsp("ipv6 -> ipv6 not supported", []),
{skip, "Host does not support IPv6"}
end.
@@ -1811,7 +2043,7 @@ http_invalid_http(suite) ->
[];
http_invalid_http(Config) when is_list(Config) ->
ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++ "/invalid_http.html",
@@ -1868,7 +2100,7 @@ transfer_encoding_otp_6807(suite) ->
[];
transfer_encoding_otp_6807(Config) when is_list(Config) ->
ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++
"/capital_transfer_encoding.html",
@@ -1901,7 +2133,7 @@ empty_response_header_otp_6830(suite) ->
[];
empty_response_header_otp_6830(Config) when is_list(Config) ->
ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++ "/no_headers.html",
{ok, {{_,200,_}, [], [_ | _]}} = httpc:request(URL),
@@ -1918,7 +2150,7 @@ no_content_204_otp_6982(suite) ->
[];
no_content_204_otp_6982(Config) when is_list(Config) ->
ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++ "/no_content.html",
{ok, {{_,204,_}, [], []}} = httpc:request(URL),
@@ -1936,7 +2168,7 @@ missing_CR_otp_7304(suite) ->
[];
missing_CR_otp_7304(Config) when is_list(Config) ->
ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++ "/missing_CR.html",
{ok, {{_,200,_}, _, [_ | _]}} = httpc:request(URL),
@@ -1955,7 +2187,7 @@ otp_7883_1(suite) ->
otp_7883_1(Config) when is_list(Config) ->
ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++ "/just_close.html",
{error, socket_closed_remotely} = httpc:request(URL),
@@ -1971,7 +2203,7 @@ otp_7883_2(suite) ->
otp_7883_2(Config) when is_list(Config) ->
ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++ "/just_close.html",
Method = get,
@@ -2312,7 +2544,7 @@ otp_8106_fun(Config) when is_list(Config) ->
ok;
_ ->
{skip, "Failed to start local http-server"}
- end.
+ end.
otp_8106_mfa(doc) ->
@@ -2492,7 +2724,7 @@ otp_8371(suite) ->
[];
otp_8371(Config) when is_list(Config) ->
ok = httpc:set_options([{ipv6, disabled}]), % also test the old option
- {DummyServerPid, Port} = dummy_server(self(), ipv4),
+ {DummyServerPid, Port} = dummy_server(ipv4),
URL = ?URL_START ++ integer_to_list(Port) ++
"/ensure_host_header_with_port.html",
@@ -2538,7 +2770,7 @@ otp_8739(Config) when is_list(Config) ->
Request = {URL, []},
HttpOptions = [{connect_timeout, 500}, {timeout, 1}],
Options = [{sync, true}],
- case http:request(Method, Request, HttpOptions, Options) of
+ case httpc:request(Method, Request, HttpOptions, Options) of
{error, timeout} ->
%% And now we check the size of the handler db
Info = httpc:info(),
@@ -2573,7 +2805,7 @@ otp_8739_dummy_server_init(Parent) ->
Parent ! {port, Port},
otp_8739_dummy_server_main(Parent, ListenSocket).
-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
@@ -2595,7 +2827,31 @@ otp_8739_dummy_server_main(Parent, ListenSocket) ->
exit(Error)
end.
-
+%%-------------------------------------------------------------------------
+
+initial_server_connect(doc) ->
+ ["If this test cases times out the init of httpc_handler process is"
+ "blocking the manager/client process (implementation dependent which) but nither"
+ "should be blocked."];
+initial_server_connect(suite) ->
+ [];
+initial_server_connect(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ ok = httpc:set_options([{ipfamily, inet}]),
+
+ CertFile = filename:join(DataDir, "ssl_server_cert.pem"),
+ SSLOptions = [{certfile, CertFile}, {keyfile, CertFile}],
+
+ {DummyServerPid, Port} = dummy_ssl_server_hang(self(), ipv4, SSLOptions),
+
+ URL = ?SSL_URL_START ++ integer_to_list(Port) ++ "/index.html",
+
+ httpc:request(get, {URL, []}, [{ssl,{essl,[]}}], [{sync, false}]),
+
+ [{session_cookies,[]}] = httpc:which_cookies(),
+
+ DummyServerPid ! stop,
+ ok = httpc:set_options([{ipfamily, inet6fb4}]).
%%--------------------------------------------------------------------
%% Internal functions
@@ -2706,75 +2962,175 @@ receive_streamed_body(RequestId, Body, Pid) ->
test_server:fail(Msg)
end.
+%% Perform a synchronous stop
+dummy_server_stop(Pid) ->
+ Pid ! {stop, self()},
+ receive
+ {stopped, Pid} ->
+ ok
+ end.
+
+dummy_server(IpV) ->
+ dummy_server(self(), ip_comm, IpV, []).
+dummy_server(SocketType, IpV, Extra) ->
+ dummy_server(self(), SocketType, IpV, Extra).
-dummy_server(Caller, IpV) ->
- Pid = spawn(httpc_SUITE, dummy_server_init, [Caller, IpV]),
+dummy_server(Caller, SocketType, IpV, Extra) ->
+ Args = [Caller, SocketType, IpV, Extra],
+ Pid = spawn(httpc_SUITE, dummy_server_init, Args),
receive
{port, Port} ->
{Pid, Port}
end.
-dummy_server_init(Caller, IpV) ->
+dummy_server_init(Caller, ip_comm, IpV, _) ->
+ BaseOpts = [binary, {packet, 0}, {reuseaddr,true}, {active, false}],
{ok, ListenSocket} =
case IpV of
ipv4 ->
- gen_tcp:listen(0, [binary, inet, {packet, 0},
- {reuseaddr,true},
- {active, false}]);
+ tsp("ip_comm ipv4 listen", []),
+ gen_tcp:listen(0, [inet | BaseOpts]);
ipv6 ->
- gen_tcp:listen(0, [binary, inet6, {packet, 0},
- {reuseaddr,true},
- {active, false}])
+ tsp("ip_comm ipv6 listen", []),
+ gen_tcp:listen(0, [inet6 | BaseOpts])
end,
{ok, Port} = inet:port(ListenSocket),
- tsp("dummy_server_init -> Port: ~p", [Port]),
+ tsp("dummy_server_init(ip_comm) -> Port: ~p", [Port]),
Caller ! {port, Port},
- dummy_server_loop({httpd_request, parse, [?HTTP_MAX_HEADER_SIZE]},
- [], ListenSocket).
+ dummy_ipcomm_server_loop({httpd_request, parse, [?HTTP_MAX_HEADER_SIZE]},
+ [], ListenSocket);
+dummy_server_init(Caller, essl, IpV, SSLOptions) ->
+ BaseOpts = [{ssl_imp, new},
+ {backlog, 128}, binary, {reuseaddr,true}, {active, false} |
+ SSLOptions],
+ dummy_ssl_server_init(Caller, BaseOpts, IpV).
+
+dummy_ssl_server_init(Caller, BaseOpts, IpV) ->
+ {ok, ListenSocket} =
+ case IpV of
+ ipv4 ->
+ tsp("dummy_ssl_server_init -> ssl ipv4 listen", []),
+ ssl:listen(0, [inet | BaseOpts]);
+ ipv6 ->
+ tsp("dummy_ssl_server_init -> ssl ipv6 listen", []),
+ ssl:listen(0, [inet6 | BaseOpts])
+ end,
+ tsp("dummy_ssl_server_init -> ListenSocket: ~p", [ListenSocket]),
+ {ok, {_, Port}} = ssl:sockname(ListenSocket),
+ tsp("dummy_ssl_server_init -> Port: ~p", [Port]),
+ Caller ! {port, Port},
+ dummy_ssl_server_loop({httpd_request, parse, [?HTTP_MAX_HEADER_SIZE]},
+ [], ListenSocket).
-dummy_server_loop(MFA, Handlers, ListenSocket) ->
+dummy_ipcomm_server_loop(MFA, Handlers, ListenSocket) ->
receive
stop ->
- lists:foreach(fun(Handler) -> Handler ! stop end, Handlers)
+ tsp("dummy_ipcomm_server_loop -> stop handlers", []),
+ lists:foreach(fun(Handler) -> Handler ! stop end, Handlers);
+ {stop, From} ->
+ tsp("dummy_ipcomm_server_loop -> "
+ "stop command from ~p for handlers (~p)", [From, Handlers]),
+ Stopper = fun(Handler) -> Handler ! stop end,
+ lists:foreach(Stopper, Handlers),
+ From ! {stopped, self()}
after 0 ->
+ tsp("dummy_ipcomm_server_loop -> await accept", []),
{ok, Socket} = gen_tcp:accept(ListenSocket),
+ tsp("dummy_ipcomm_server_loop -> accepted: ~p", [Socket]),
HandlerPid = dummy_request_handler(MFA, Socket),
+ tsp("dummy_icomm_server_loop -> handler created: ~p", [HandlerPid]),
gen_tcp:controlling_process(Socket, HandlerPid),
- HandlerPid ! controller,
- dummy_server_loop(MFA, [HandlerPid | Handlers],
+ tsp("dummy_ipcomm_server_loop -> "
+ "control transfered to handler", []),
+ HandlerPid ! ipcomm_controller,
+ tsp("dummy_ipcomm_server_loop -> "
+ "handler informed about control transfer", []),
+ dummy_ipcomm_server_loop(MFA, [HandlerPid | Handlers],
ListenSocket)
end.
+dummy_ssl_server_loop(MFA, Handlers, ListenSocket) ->
+ receive
+ stop ->
+ tsp("dummy_ssl_server_loop -> stop handlers", []),
+ lists:foreach(fun(Handler) -> Handler ! stop end, Handlers);
+ {stop, From} ->
+ tsp("dummy_ssl_server_loop -> "
+ "stop command from ~p for handlers (~p)", [From, Handlers]),
+ Stopper = fun(Handler) -> Handler ! stop end,
+ lists:foreach(Stopper, Handlers),
+ From ! {stopped, self()}
+ after 0 ->
+ tsp("dummy_ssl_server_loop -> await accept", []),
+ {ok, Socket} = ssl:transport_accept(ListenSocket),
+ tsp("dummy_ssl_server_loop -> accepted: ~p", [Socket]),
+ HandlerPid = dummy_request_handler(MFA, Socket),
+ tsp("dummy_ssl_server_loop -> handler created: ~p", [HandlerPid]),
+ ssl:controlling_process(Socket, HandlerPid),
+ tsp("dummy_ssl_server_loop -> control transfered to handler", []),
+ HandlerPid ! ssl_controller,
+ tsp("dummy_ssl_server_loop -> "
+ "handler informed about control transfer", []),
+ dummy_ssl_server_loop(MFA, [HandlerPid | Handlers],
+ ListenSocket)
+ end.
+
dummy_request_handler(MFA, Socket) ->
+ tsp("spawn request handler", []),
spawn(httpc_SUITE, dummy_request_handler_init, [MFA, Socket]).
dummy_request_handler_init(MFA, Socket) ->
- receive
- controller ->
- inet:setopts(Socket, [{active, true}])
- end,
- dummy_request_handler_loop(MFA, Socket).
+ SockType =
+ receive
+ ipcomm_controller ->
+ tsp("dummy_request_handler_init -> "
+ "received ip_comm controller - activate", []),
+ inet:setopts(Socket, [{active, true}]),
+ ip_comm;
+ ssl_controller ->
+ tsp("dummy_request_handler_init -> "
+ "received ssl controller - activate", []),
+ ssl:setopts(Socket, [{active, true}]),
+ ssl
+ end,
+ dummy_request_handler_loop(MFA, SockType, Socket).
-dummy_request_handler_loop({Module, Function, Args}, Socket) ->
+dummy_request_handler_loop({Module, Function, Args}, SockType, Socket) ->
tsp("dummy_request_handler_loop -> entry with"
"~n Module: ~p"
"~n Function: ~p"
"~n Args: ~p", [Module, Function, Args]),
receive
- {tcp, _, Data} ->
- tsp("dummy_request_handler_loop -> Data ~p", [Data]),
- case handle_request(Module, Function, [Data | Args], Socket) of
- stop ->
+ {Proto, _, Data} when (Proto =:= tcp) orelse (Proto =:= ssl) ->
+ tsp("dummy_request_handler_loop -> [~w] Data ~p", [Proto, Data]),
+ case handle_request(Module, Function, [Data | Args], Socket, Proto) of
+ stop when Proto =:= tcp ->
gen_tcp:close(Socket);
+ stop when Proto =:= ssl ->
+ ssl:close(Socket);
NewMFA ->
- dummy_request_handler_loop(NewMFA, Socket)
+ dummy_request_handler_loop(NewMFA, SockType, Socket)
end;
- stop ->
- gen_tcp:close(Socket)
+ stop when SockType =:= ip_comm ->
+ gen_tcp:close(Socket);
+ stop when SockType =:= ssl ->
+ ssl:close(Socket)
end.
-handle_request(Module, Function, Args, Socket) ->
+
+mk_close(tcp) -> fun(Sock) -> gen_tcp:close(Sock) end;
+mk_close(ssl) -> fun(Sock) -> ssl:close(Sock) end.
+
+mk_send(tcp) -> fun(Sock, Data) -> gen_tcp:send(Sock, Data) end;
+mk_send(ssl) -> fun(Sock, Data) -> ssl:send(Sock, Data) end.
+
+handle_request(Module, Function, Args, Socket, Proto) ->
+ Close = mk_close(Proto),
+ Send = mk_send(Proto),
+ handle_request(Module, Function, Args, Socket, Close, Send).
+
+handle_request(Module, Function, Args, Socket, Close, Send) ->
tsp("handle_request -> entry with"
"~n Module: ~p"
"~n Function: ~p"
@@ -2783,7 +3139,7 @@ handle_request(Module, Function, Args, Socket) ->
{ok, Result} ->
tsp("handle_request -> ok"
"~n Result: ~p", [Result]),
- case (catch handle_http_msg(Result, Socket)) of
+ case (catch handle_http_msg(Result, Socket, Close, Send)) of
stop ->
stop;
<<>> ->
@@ -2791,7 +3147,8 @@ handle_request(Module, Function, Args, Socket) ->
{httpd_request, parse, [[<<>>, ?HTTP_MAX_HEADER_SIZE]]};
Data ->
handle_request(httpd_request, parse,
- [Data |[?HTTP_MAX_HEADER_SIZE]], Socket)
+ [Data |[?HTTP_MAX_HEADER_SIZE]], Socket,
+ Close, Send)
end;
NewMFA ->
tsp("handle_request -> "
@@ -2799,7 +3156,7 @@ handle_request(Module, Function, Args, Socket) ->
NewMFA
end.
-handle_http_msg({_, RelUri, _, {_, Headers}, Body}, Socket) ->
+handle_http_msg({_, RelUri, _, {_, Headers}, Body}, Socket, Close, Send) ->
tsp("handle_http_msg -> entry with: "
"~n RelUri: ~p"
"~n Headers: ~p"
@@ -2956,16 +3313,16 @@ handle_http_msg({_, RelUri, _, {_, Headers}, Body}, Socket) ->
"Expires:Sat, 29 Oct 1994 19:43:31 GMT\r\n" ++
"Proxy-Authenticate:#1Basic" ++
"\r\n\r\n",
- gen_tcp:send(Socket, Head),
- gen_tcp:send(Socket, http_chunk:encode("<HTML><BODY>fo")),
- gen_tcp:send(Socket, http_chunk:encode("obar</BODY></HTML>")),
+ Send(Socket, Head),
+ Send(Socket, http_chunk:encode("<HTML><BODY>fo")),
+ Send(Socket, http_chunk:encode("obar</BODY></HTML>")),
http_chunk:encode_last();
"/capital_transfer_encoding.html" ->
Head = "HTTP/1.1 200 ok\r\n" ++
"Transfer-Encoding:Chunked\r\n\r\n",
- gen_tcp:send(Socket, Head),
- gen_tcp:send(Socket, http_chunk:encode("<HTML><BODY>fo")),
- gen_tcp:send(Socket, http_chunk:encode("obar</BODY></HTML>")),
+ Send(Socket, Head),
+ Send(Socket, http_chunk:encode("<HTML><BODY>fo")),
+ Send(Socket, http_chunk:encode("obar</BODY></HTML>")),
http_chunk:encode_last();
"/cookie.html" ->
"HTTP/1.1 200 ok\r\n" ++
@@ -2984,20 +3341,20 @@ handle_http_msg({_, RelUri, _, {_, Headers}, Body}, Socket) ->
"/once_chunked.html" ->
Head = "HTTP/1.1 200 ok\r\n" ++
"Transfer-Encoding:Chunked\r\n\r\n",
- gen_tcp:send(Socket, Head),
- gen_tcp:send(Socket, http_chunk:encode("<HTML><BODY>fo")),
- gen_tcp:send(Socket,
+ Send(Socket, Head),
+ Send(Socket, http_chunk:encode("<HTML><BODY>fo")),
+ Send(Socket,
http_chunk:encode("obar</BODY></HTML>")),
http_chunk:encode_last();
"/once.html" ->
Head = "HTTP/1.1 200 ok\r\n" ++
"Content-Length:32\r\n\r\n",
- gen_tcp:send(Socket, Head),
- gen_tcp:send(Socket, "<HTML><BODY>fo"),
+ Send(Socket, Head),
+ Send(Socket, "<HTML><BODY>fo"),
test_server:sleep(1000),
- gen_tcp:send(Socket, "ob"),
+ Send(Socket, "ob"),
test_server:sleep(1000),
- gen_tcp:send(Socket, "ar</BODY></HTML>");
+ Send(Socket, "ar</BODY></HTML>");
"/invalid_http.html" ->
"HTTP/1.1 301\r\nDate:Sun, 09 Dec 2007 13:04:18 GMT\r\n" ++
"Transfer-Encoding:chunked\r\n\r\n";
@@ -3020,9 +3377,9 @@ handle_http_msg({_, RelUri, _, {_, Headers}, Body}, Socket) ->
ok;
close ->
%% Nothing to send, just close
- gen_tcp:close(Socket);
+ Close(Socket);
_ when is_list(Msg) orelse is_binary(Msg) ->
- gen_tcp:send(Socket, Msg)
+ Send(Socket, Msg)
end,
tsp("handle_http_msg -> done"),
NextRequest.
@@ -3108,11 +3465,9 @@ pick_header(Headers, Name) ->
Val
end.
-
not_implemented_yet() ->
exit(not_implemented_yet).
-
p(F) ->
p(F, []).
@@ -3126,3 +3481,54 @@ tsp(F, A) ->
tsf(Reason) ->
test_server:fail(Reason).
+
+
+dummy_ssl_server_hang(Caller, IpV, SslOpt) ->
+ Pid = spawn(httpc_SUITE, dummy_ssl_server_hang_init, [Caller, IpV, SslOpt]),
+ receive
+ {port, Port} ->
+ {Pid, Port}
+ end.
+
+dummy_ssl_server_hang_init(Caller, IpV, SslOpt) ->
+ {ok, ListenSocket} =
+ case IpV of
+ ipv4 ->
+ ssl:listen(0, [binary, inet, {packet, 0},
+ {reuseaddr,true},
+ {active, false}] ++ SslOpt);
+ ipv6 ->
+ ssl:listen(0, [binary, inet6, {packet, 0},
+ {reuseaddr,true},
+ {active, false}] ++ SslOpt)
+ end,
+ {ok, {_,Port}} = ssl:sockname(ListenSocket),
+ tsp("dummy_ssl_server_hang_init -> Port: ~p", [Port]),
+ Caller ! {port, Port},
+ {ok, AcceptSocket} = ssl:transport_accept(ListenSocket),
+ dummy_ssl_server_hang_loop(AcceptSocket).
+
+dummy_ssl_server_hang_loop(_) ->
+ %% Do not do ssl:ssl_accept as we
+ %% want to time out the underlying gen_tcp:connect
+ receive
+ stop ->
+ ok
+ end.
+
+
+ensure_started([]) ->
+ ok;
+ensure_started([App|Apps]) ->
+ ensure_started(App),
+ ensure_started(Apps);
+ensure_started(App) when is_atom(App) ->
+ case (catch application:start(App)) of
+ ok ->
+ ok;
+ {error, {already_started, _}} ->
+ ok;
+ Error ->
+ throw({error, {failed_starting, App, Error}})
+ end.
+
diff --git a/lib/inets/test/httpc_cookie_SUITE.erl b/lib/inets/test/httpc_cookie_SUITE.erl
index feef5f1eea..93dbc270c5 100644
--- a/lib/inets/test/httpc_cookie_SUITE.erl
+++ b/lib/inets/test/httpc_cookie_SUITE.erl
@@ -55,7 +55,7 @@ init_per_testcase(session_cookies_only = Case, Config0) ->
"~n Config0: ~p", [Case, Config0]),
Config = init_workdir(Case, Config0),
application:start(inets),
- http:set_options([{cookies, verify}]),
+ httpc:set_options([{cookies, verify}]),
watch_dog(Config);
init_per_testcase(Case, Config0) ->
@@ -66,7 +66,7 @@ init_per_testcase(Case, Config0) ->
application:load(inets),
application:set_env(inets, services, [{httpc, {default, CaseDir}}]),
application:start(inets),
- http:set_options([{cookies, verify}]),
+ httpc:set_options([{cookies, verify}]),
watch_dog(Config).
watch_dog(Config) ->
@@ -119,10 +119,18 @@ end_per_testcase(Case, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [session_cookies_only, netscape_cookies, cookie_cancel,
- cookie_expires, persistent_cookie, domain_cookie,
- secure_cookie, update_cookie, update_cookie_session,
- cookie_attributes].
+ [
+ session_cookies_only,
+ netscape_cookies,
+ cookie_cancel,
+ cookie_expires,
+ persistent_cookie,
+ domain_cookie,
+ secure_cookie,
+ update_cookie,
+ update_cookie_session,
+ cookie_attributes
+ ].
groups() ->
[].
@@ -152,12 +160,12 @@ session_cookies_only(Config) when is_list(Config) ->
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/;"
";max-age=60000"}],
- http:verify_cookies(SetCookieHeaders, ?URL),
- {"cookie","$Version=0; test_cookie=true; $Path=/"}
- = http:cookie_header(?URL),
+ httpc:store_cookies(SetCookieHeaders, ?URL),
+ {"cookie", "$Version=0; test_cookie=true; $Path=/"} =
+ httpc:cookie_header(?URL),
application:stop(inets),
application:start(inets),
- {"cookie",""} = http:cookie_header(?URL),
+ {"cookie", ""} = httpc:cookie_header(?URL),
tsp("session_cookies_only -> Cookies 2: ~p", [httpc:which_cookies()]),
ok.
@@ -172,9 +180,9 @@ netscape_cookies(Config) when is_list(Config) ->
Expires = future_netscape_date(),
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/; "
"expires=" ++ Expires}],
- http:verify_cookies(SetCookieHeaders, ?URL),
- {"cookie","$Version=0; test_cookie=true; $Path=/"} =
- http:cookie_header(?URL),
+ httpc:store_cookies(SetCookieHeaders, ?URL),
+ {"cookie", "$Version=0; test_cookie=true; $Path=/"} =
+ httpc:cookie_header(?URL),
tsp("netscape_cookies -> Cookies 2: ~p", [httpc:which_cookies()]),
ok.
@@ -189,13 +197,13 @@ cookie_cancel(Config) when is_list(Config) ->
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/;"
"max-age=60000"}],
- http:verify_cookies(SetCookieHeaders, ?URL),
- {"cookie","$Version=0; test_cookie=true; $Path=/"}
- = http:cookie_header(?URL),
- NewSetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/;"
- "max-age=0"}],
- http:verify_cookies(NewSetCookieHeaders, ?URL),
- {"cookie", ""} = http:cookie_header(?URL),
+ httpc:store_cookies(SetCookieHeaders, ?URL),
+ {"cookie", "$Version=0; test_cookie=true; $Path=/"} =
+ httpc:cookie_header(?URL),
+ NewSetCookieHeaders =
+ [{"set-cookie", "test_cookie=true; path=/;max-age=0"}],
+ httpc:store_cookies(NewSetCookieHeaders, ?URL),
+ {"cookie", ""} = httpc:cookie_header(?URL),
tsp("cookie_cancel -> Cookies 2: ~p", [httpc:which_cookies()]),
ok.
@@ -209,11 +217,11 @@ cookie_expires(Config) when is_list(Config) ->
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/;"
"max-age=5"}],
- http:verify_cookies(SetCookieHeaders, ?URL),
- {"cookie","$Version=0; test_cookie=true; $Path=/"}
- = http:cookie_header(?URL),
+ httpc:store_cookies(SetCookieHeaders, ?URL),
+ {"cookie", "$Version=0; test_cookie=true; $Path=/"} =
+ httpc:cookie_header(?URL),
test_server:sleep(10000),
- {"cookie", ""} = http:cookie_header(?URL),
+ {"cookie", ""} = httpc:cookie_header(?URL),
tsp("cookie_expires -> Cookies 2: ~p", [httpc:which_cookies()]),
ok.
@@ -227,16 +235,16 @@ persistent_cookie(Config) when is_list(Config)->
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/;"
"max-age=60000"}],
- http:verify_cookies(SetCookieHeaders, ?URL),
- {"cookie","$Version=0; test_cookie=true; $Path=/"} =
- http:cookie_header(?URL),
+ httpc:store_cookies(SetCookieHeaders, ?URL),
+ {"cookie", "$Version=0; test_cookie=true; $Path=/"} =
+ httpc:cookie_header(?URL),
CaseDir = ?config(case_top_dir, Config),
application:stop(inets),
application:load(inets),
application:set_env(inets, services, [{httpc, {default, CaseDir}}]),
application:start(inets),
- http:set_options([{cookies, enabled}]),
- {"cookie","$Version=0; test_cookie=true; $Path=/"} = http:cookie_header(?URL),
+ httpc:set_options([{cookies, enabled}]),
+ {"cookie","$Version=0; test_cookie=true; $Path=/"} = httpc:cookie_header(?URL),
tsp("persistent_cookie -> Cookies 2: ~p", [httpc:which_cookies()]),
ok.
@@ -251,10 +259,10 @@ domain_cookie(Config) when is_list(Config) ->
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/;"
"domain=.cookie.test.org"}],
- http:verify_cookies(SetCookieHeaders, ?URL),
+ httpc:store_cookies(SetCookieHeaders, ?URL),
{"cookie","$Version=0; test_cookie=true; $Path=/; "
"$Domain=.cookie.test.org"} =
- http:cookie_header(?URL_DOMAIN),
+ httpc:cookie_header(?URL_DOMAIN),
tsp("domain_cookie -> Cookies 2: ~p", [httpc:which_cookies()]),
ok.
@@ -275,8 +283,8 @@ secure_cookie(Config) when is_list(Config) ->
tsp("secure_cookie -> Cookies 1: ~p", [httpc:which_cookies()]),
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/; secure"}],
- tsp("secure_cookie -> verify cookies (1)"),
- ok = http:verify_cookies(SetCookieHeaders, ?URL),
+ tsp("secure_cookie -> store cookies (1)"),
+ ok = httpc:store_cookies(SetCookieHeaders, ?URL),
tsp("secure_cookie -> Cookies 2: ~p", [httpc:which_cookies()]),
@@ -286,9 +294,9 @@ secure_cookie(Config) when is_list(Config) ->
tsp("secure_cookie -> check cookie (plain)"),
check_cookie("", ?URL),
- tsp("secure_cookie -> verify cookies (2)"),
+ tsp("secure_cookie -> store cookies (2)"),
SetCookieHeaders1 = [{"set-cookie", "test1_cookie=true; path=/; secure"}],
- ok = http:verify_cookies(SetCookieHeaders1, ?URL),
+ ok = httpc:store_cookies(SetCookieHeaders1, ?URL),
tsp("secure_cookie -> Cookies 3: ~p", [httpc:which_cookies()]),
@@ -297,7 +305,7 @@ secure_cookie(Config) when is_list(Config) ->
"test1_cookie=true; $Path=/",
?URL_SECURE),
%% {"cookie","$Version=0; test_cookie=true; $Path=/; "
-%% "test1_cookie=true; $Path=/"} = http:cookie_header(?URL_SECURE),
+%% "test1_cookie=true; $Path=/"} = httpc:cookie_header(?URL_SECURE),
tsp("secure_cookie -> Cookies 4: ~p", [httpc:which_cookies()]),
@@ -305,38 +313,93 @@ secure_cookie(Config) when is_list(Config) ->
tsp("secure_cookie -> done"),
ok.
+expect_cookie_header(No, ExpectedCookie) ->
+ case httpc:cookie_header(?URL) of
+ {"cookie", ExpectedCookie} ->
+ ok;
+ {"cookie", BadCookie} ->
+ io:format("Bad Cookie ~w: "
+ "~n Expected: ~s"
+ "~n Received: ~s"
+ "~n", [No, ExpectedCookie, BadCookie]),
+ exit({bad_cookie_header, No, ExpectedCookie, BadCookie})
+ end.
+
+print_cookies(Pre) ->
+ io:format("~s: ", [Pre]),
+ print_cookies2(httpc:which_cookies()).
+
+print_cookies2([]) ->
+ ok;
+print_cookies2([{cookies, Cookies}|Rest]) ->
+ print_cookies3("Cookies", Cookies),
+ print_cookies2(Rest);
+print_cookies2([{session_cookies, Cookies}|Rest]) ->
+ print_cookies3("Session Cookies", Cookies),
+ print_cookies2(Rest);
+print_cookies2([_|Rest]) ->
+ print_cookies2(Rest).
+
+print_cookies3(Header, []) ->
+ io:format(" ~s: []", [Header]);
+print_cookies3(Header, Cookies) ->
+ io:format(" ~s: ", [Header]),
+ Prefix = " ",
+ PrintCookie =
+ fun(Cookie) ->
+ io:format("~s", [httpc_cookie:image_of(Prefix, Cookie)])
+ end,
+ lists:foreach(PrintCookie, Cookies).
+
update_cookie(doc)->
- ["Test that a cookie can be updated."];
+ ["Test that a (plain) cookie can be updated."];
update_cookie(suite) ->
[];
-update_cookie(Config) when is_list(Config)->
- SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/;"
- "max-age=6500"},
- {"set-cookie", "test_cookie2=true; path=/;"
- "max-age=6500"}],
- http:verify_cookies(SetCookieHeaders, ?URL),
- {"cookie", "$Version=0; test_cookie2=true; $Path=/; "
- "test_cookie=true; $Path=/"} = http:cookie_header(?URL),
- NewSetCookieHeaders = [{"set-cookie", "test_cookie=false; "
- "path=/;max-age=6500"}],
- http:verify_cookies(NewSetCookieHeaders, ?URL),
- {"cookie", "$Version=0; test_cookie2=true; $Path=/; "
- "test_cookie=false; $Path=/"} = http:cookie_header(?URL).
-
+update_cookie(Config) when is_list(Config) ->
+ print_cookies("Cookies before store"),
+
+ SetCookieHeaders =
+ [{"set-cookie", "test_cookie=true; path=/; max-age=6500"},
+ {"set-cookie", "test_cookie2=true; path=/; max-age=6500"}],
+ httpc:store_cookies(SetCookieHeaders, ?URL),
+ print_cookies("Cookies after first store"),
+ ExpectCookie1 =
+ "$Version=0; "
+ "test_cookie=true; $Path=/; "
+ "test_cookie2=true; $Path=/",
+ expect_cookie_header(1, ExpectCookie1),
+
+ NewSetCookieHeaders =
+ [{"set-cookie", "test_cookie=false; path=/; max-age=6500"}],
+ httpc:store_cookies(NewSetCookieHeaders, ?URL),
+ print_cookies("Cookies after second store"),
+ ExpectCookie2 =
+ "$Version=0; "
+ "test_cookie2=true; $Path=/; "
+ "test_cookie=false; $Path=/",
+ expect_cookie_header(2, ExpectCookie2).
+
update_cookie_session(doc)->
- ["Test that a cookie can be updated."];
+ ["Test that a session cookie can be updated."];
update_cookie_session(suite) ->
[];
update_cookie_session(Config) when is_list(Config)->
+ print_cookies("Cookies before store"),
+
SetCookieHeaders = [{"set-cookie", "test_cookie=true; path=/"},
{"set-cookie", "test_cookie2=true; path=/"}],
- http:verify_cookies(SetCookieHeaders, ?URL),
- {"cookie", "$Version=0; test_cookie2=true; $Path=/; "
- "test_cookie=true; $Path=/"} = http:cookie_header(?URL),
+ httpc:store_cookies(SetCookieHeaders, ?URL),
+ print_cookies("Cookies after first store"),
+ ExpectedCookie1 =
+ "$Version=0; test_cookie=true; $Path=/; test_cookie2=true; $Path=/",
+ expect_cookie_header(1, ExpectedCookie1),
+
NewSetCookieHeaders = [{"set-cookie", "test_cookie=false; path=/"}],
- http:verify_cookies(NewSetCookieHeaders, ?URL),
- {"cookie", "$Version=0; test_cookie2=true; $Path=/; "
- "test_cookie=false; $Path=/"} = http:cookie_header(?URL).
+ httpc:store_cookies(NewSetCookieHeaders, ?URL),
+ print_cookies("Cookies after second store"),
+ ExpectedCookie2 =
+ "$Version=0; test_cookie2=true; $Path=/; test_cookie=false; $Path=/",
+ expect_cookie_header(2, ExpectedCookie2).
cookie_attributes(doc) ->
@@ -348,8 +411,8 @@ cookie_attributes(Config) when is_list(Config) ->
"comment=foobar; "%% Comment
"foo=bar;" %% Nonsense should be ignored
"max-age=60000"}],
- http:verify_cookies(SetCookieHeaders, ?URL),
- {"cookie","$Version=1; test_cookie=true"} = http:cookie_header(?URL),
+ httpc:store_cookies(SetCookieHeaders, ?URL),
+ {"cookie","$Version=1; test_cookie=true"} = httpc:cookie_header(?URL),
ok.
@@ -358,7 +421,7 @@ cookie_attributes(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
check_cookie(Expect, URL) ->
- case http:cookie_header(URL) of
+ case httpc:cookie_header(URL) of
{"cookie", Expect} ->
ok;
{"cookie", Unexpected} ->
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl
index fde5178879..faeed3b5f9 100644
--- a/lib/inets/test/httpd_SUITE.erl
+++ b/lib/inets/test/httpd_SUITE.erl
@@ -68,127 +68,96 @@
-export([
pssl_mod_alias/1,
- ossl_mod_alias/1,
essl_mod_alias/1,
pssl_mod_actions/1,
- ossl_mod_actions/1,
essl_mod_actions/1,
pssl_mod_security/1,
- ossl_mod_security/1,
essl_mod_security/1,
pssl_mod_auth/1,
- ossl_mod_auth/1,
essl_mod_auth/1,
pssl_mod_auth_api/1,
- ossl_mod_auth_api/1,
essl_mod_auth_api/1,
pssl_mod_auth_mnesia_api/1,
- ossl_mod_auth_mnesia_api/1,
essl_mod_auth_mnesia_api/1,
pssl_mod_htaccess/1,
- ossl_mod_htaccess/1,
essl_mod_htaccess/1,
pssl_mod_cgi/1,
- ossl_mod_cgi/1,
essl_mod_cgi/1,
pssl_mod_esi/1,
- ossl_mod_esi/1,
essl_mod_esi/1,
pssl_mod_get/1,
- ossl_mod_get/1,
essl_mod_get/1,
pssl_mod_head/1,
- ossl_mod_head/1,
essl_mod_head/1,
pssl_mod_all/1,
- ossl_mod_all/1,
essl_mod_all/1,
pssl_load_light/1,
- ossl_load_light/1,
essl_load_light/1,
pssl_load_medium/1,
- ossl_load_medium/1,
essl_load_medium/1,
pssl_load_heavy/1,
- ossl_load_heavy/1,
essl_load_heavy/1,
pssl_dos_hostname/1,
- ossl_dos_hostname/1,
essl_dos_hostname/1,
pssl_time_test/1,
- ossl_time_test/1,
essl_time_test/1,
pssl_restart_no_block/1,
- ossl_restart_no_block/1,
essl_restart_no_block/1,
pssl_restart_disturbing_block/1,
- ossl_restart_disturbing_block/1,
essl_restart_disturbing_block/1,
pssl_restart_non_disturbing_block/1,
- ossl_restart_non_disturbing_block/1,
essl_restart_non_disturbing_block/1,
pssl_block_disturbing_idle/1,
- ossl_block_disturbing_idle/1,
essl_block_disturbing_idle/1,
pssl_block_non_disturbing_idle/1,
- ossl_block_non_disturbing_idle/1,
essl_block_non_disturbing_idle/1,
pssl_block_503/1,
- ossl_block_503/1,
essl_block_503/1,
pssl_block_disturbing_active/1,
- ossl_block_disturbing_active/1,
essl_block_disturbing_active/1,
pssl_block_non_disturbing_active/1,
- ossl_block_non_disturbing_active/1,
essl_block_non_disturbing_active/1,
pssl_block_disturbing_active_timeout_not_released/1,
- ossl_block_disturbing_active_timeout_not_released/1,
essl_block_disturbing_active_timeout_not_released/1,
pssl_block_disturbing_active_timeout_released/1,
- ossl_block_disturbing_active_timeout_released/1,
essl_block_disturbing_active_timeout_released/1,
pssl_block_non_disturbing_active_timeout_not_released/1,
- ossl_block_non_disturbing_active_timeout_not_released/1,
essl_block_non_disturbing_active_timeout_not_released/1,
pssl_block_non_disturbing_active_timeout_released/1,
- ossl_block_non_disturbing_active_timeout_released/1,
essl_block_non_disturbing_active_timeout_released/1,
pssl_block_disturbing_blocker_dies/1,
- ossl_block_disturbing_blocker_dies/1,
essl_block_disturbing_blocker_dies/1,
pssl_block_non_disturbing_blocker_dies/1,
- ossl_block_non_disturbing_blocker_dies/1,
essl_block_non_disturbing_blocker_dies/1
]).
@@ -207,8 +176,11 @@
-export([ticket_5775/1,ticket_5865/1,ticket_5913/1,ticket_6003/1,
ticket_7304/1]).
-%%% Misc
--export([ipv6_hostname/1, ipv6_address/1]).
+%%% IPv6 tests
+-export([ipv6_hostname_ipcomm/0, ipv6_hostname_ipcomm/1,
+ ipv6_address_ipcomm/0, ipv6_address_ipcomm/1,
+ ipv6_hostname_essl/0, ipv6_hostname_essl/1,
+ ipv6_address_essl/0, ipv6_address_essl/1]).
%% Help functions
-export([cleanup_mnesia/0, setup_mnesia/0, setup_mnesia/1]).
@@ -241,9 +213,15 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [{group, ip}, {group, ssl}, {group, http_1_1_ip},
- {group, http_1_0_ip}, {group, http_0_9_ip},
- {group, tickets}].
+ [
+ {group, ip},
+ {group, ssl},
+ {group, http_1_1_ip},
+ {group, http_1_0_ip},
+ {group, http_0_9_ip},
+ {group, ipv6},
+ {group, tickets}
+ ].
groups() ->
[{ip, [],
@@ -263,8 +241,7 @@ groups() ->
ip_block_non_disturbing_active_timeout_released,
ip_block_disturbing_blocker_dies,
ip_block_non_disturbing_blocker_dies]},
- {ssl, [],
- [{group, pssl}, {group, ossl}, {group, essl}]},
+ {ssl, [], [{group, pssl}, {group, essl}]},
{pssl, [],
[pssl_mod_alias, pssl_mod_actions, pssl_mod_security,
pssl_mod_auth, pssl_mod_auth_api,
@@ -284,25 +261,6 @@ groups() ->
pssl_block_non_disturbing_active_timeout_released,
pssl_block_disturbing_blocker_dies,
pssl_block_non_disturbing_blocker_dies]},
- {ossl, [],
- [ossl_mod_alias, ossl_mod_actions, ossl_mod_security,
- ossl_mod_auth, ossl_mod_auth_api,
- ossl_mod_auth_mnesia_api, ossl_mod_htaccess,
- ossl_mod_cgi, ossl_mod_esi, ossl_mod_get, ossl_mod_head,
- ossl_mod_all, ossl_load_light, ossl_load_medium,
- ossl_load_heavy, ossl_dos_hostname, ossl_time_test,
- ossl_restart_no_block, ossl_restart_disturbing_block,
- ossl_restart_non_disturbing_block,
- ossl_block_disturbing_idle,
- ossl_block_non_disturbing_idle, ossl_block_503,
- ossl_block_disturbing_active,
- ossl_block_non_disturbing_active,
- ossl_block_disturbing_active_timeout_not_released,
- ossl_block_disturbing_active_timeout_released,
- ossl_block_non_disturbing_active_timeout_not_released,
- ossl_block_non_disturbing_active_timeout_released,
- ossl_block_disturbing_blocker_dies,
- ossl_block_non_disturbing_blocker_dies]},
{essl, [],
[essl_mod_alias, essl_mod_actions, essl_mod_security,
essl_mod_auth, essl_mod_auth_api,
@@ -329,7 +287,8 @@ groups() ->
{http_1_0_ip, [],
[ip_head_1_0, ip_get_1_0, ip_post_1_0]},
{http_0_9_ip, [], [ip_get_0_9]},
- {ipv6, [], [ipv6_hostname, ipv6_address]},
+ {ipv6, [], [ipv6_hostname_ipcomm, ipv6_address_ipcomm,
+ ipv6_hostname_essl, ipv6_address_essl]},
{tickets, [],
[ticket_5775, ticket_5865, ticket_5913, ticket_6003,
ticket_7304]}].
@@ -408,10 +367,10 @@ init_per_testcase2(Case, Config) ->
"~n Config: ~p"
"~n", [?MODULE, Case, Config]),
- IpNormal = integer_to_list(?IP_PORT) ++ ".conf",
- IpHtacess = integer_to_list(?IP_PORT) ++ "htacess.conf",
- SslNormal = integer_to_list(?SSL_PORT) ++ ".conf",
- SslHtacess = integer_to_list(?SSL_PORT) ++ "htacess.conf",
+ IpNormal = integer_to_list(?IP_PORT) ++ ".conf",
+ IpHtaccess = integer_to_list(?IP_PORT) ++ "htaccess.conf",
+ SslNormal = integer_to_list(?SSL_PORT) ++ ".conf",
+ SslHtaccess = integer_to_list(?SSL_PORT) ++ "htaccess.conf",
DataDir = ?config(data_dir, Config),
SuiteTopDir = ?config(suite_top_dir, Config),
@@ -471,9 +430,9 @@ init_per_testcase2(Case, Config) ->
io:format(user, "~w:init_per_testcase2(~w) -> ip testcase setups~n",
[?MODULE, Case]),
create_config([{port, ?IP_PORT}, {sock_type, ip_comm} | NewConfig],
- normal_acess, IpNormal),
+ normal_access, IpNormal),
create_config([{port, ?IP_PORT}, {sock_type, ip_comm} | NewConfig],
- mod_htaccess, IpHtacess),
+ mod_htaccess, IpHtaccess),
%% To be used by SSL test cases
io:format(user, "~w:init_per_testcase2(~w) -> ssl testcase setups~n",
@@ -483,7 +442,6 @@ init_per_testcase2(Case, Config) ->
[X, $s, $s, $l | _] ->
case X of
$p -> ssl;
- $o -> ossl;
$e -> essl
end;
_ ->
@@ -491,9 +449,9 @@ init_per_testcase2(Case, Config) ->
end,
create_config([{port, ?SSL_PORT}, {sock_type, SocketType} | NewConfig],
- normal_acess, SslNormal),
+ normal_access, SslNormal),
create_config([{port, ?SSL_PORT}, {sock_type, SocketType} | NewConfig],
- mod_htaccess, SslHtacess),
+ mod_htaccess, SslHtaccess),
%% To be used by IPv6 test cases. Case-clause is so that
%% you can do ts:run(inets, httpd_SUITE, <test case>)
@@ -501,22 +459,52 @@ init_per_testcase2(Case, Config) ->
%% on 'test_host_ipv6_only' that will only be present
%% when you run the whole test suite due to shortcomings
%% of the test server.
- %% case (catch ?config(test_host_ipv6_only, Config)) of
- %% {_,IPv6Host,IPv6Adress,_,_} ->
- %% create_ipv6_config([{port, ?IP_PORT},
- %% {sock_type, ip_comm} | NewConfig],
- %% "ipv6_hostname.conf", IPv6Host),
- %% create_ipv6_config([{port, ?IP_PORT},
- %% {sock_type, ip_comm} | NewConfig],
- %% "ipv6_address.conf", IPv6Adress);
- %% _ ->
- %% ok
- %% end,
-
+
+ io:format(user, "~w:init_per_testcase2(~w) -> "
+ "maybe generate IPv6 config file(s)", [?MODULE, Case]),
+ NewConfig2 =
+ case atom_to_list(Case) of
+ "ipv6_" ++ _ ->
+ case (catch inets_test_lib:has_ipv6_support(NewConfig)) of
+ {ok, IPv6Address0} ->
+ {ok, Hostname} = inet:gethostname(),
+ IPv6Address = http_transport:ipv6_name(IPv6Address0),
+ create_ipv6_config([{port, ?IP_PORT},
+ {sock_type, ip_comm},
+ {ipv6_host, IPv6Address} |
+ NewConfig],
+ "ipv6_hostname_ipcomm.conf",
+ Hostname),
+ create_ipv6_config([{port, ?IP_PORT},
+ {sock_type, ip_comm},
+ {ipv6_host, IPv6Address} |
+ NewConfig],
+ "ipv6_address_ipcomm.conf",
+ IPv6Address),
+ create_ipv6_config([{port, ?SSL_PORT},
+ {sock_type, essl},
+ {ipv6_host, IPv6Address} |
+ NewConfig],
+ "ipv6_hostname_essl.conf",
+ Hostname),
+ create_ipv6_config([{port, ?SSL_PORT},
+ {sock_type, essl},
+ {ipv6_host, IPv6Address} |
+ NewConfig],
+ "ipv6_address_essl.conf",
+ IPv6Address),
+ [{ipv6_host, IPv6Address} | NewConfig];
+ _ ->
+ NewConfig
+ end;
+ _ ->
+ NewConfig
+ end,
+
io:format(user, "~w:init_per_testcase2(~w) -> done~n",
[?MODULE, Case]),
- NewConfig.
+ NewConfig2.
init_per_testcase3(Case, Config) ->
@@ -547,10 +535,10 @@ init_per_testcase3(Case, Config) ->
[?MODULE, Case]),
inets:disable_trace();
_ ->
- %% TraceLevel = max,
io:format(user, "~w:init_per_testcase3(~w) -> enabling trace",
[?MODULE, Case]),
- TraceLevel = 70,
+ %% TraceLevel = 70,
+ TraceLevel = max,
TraceDest = io,
inets:enable_trace(TraceLevel, TraceDest, httpd)
end,
@@ -569,7 +557,7 @@ init_per_testcase3(Case, Config) ->
inets_test_lib:start_http_server(
filename:join(TcTopDir,
integer_to_list(?IP_PORT) ++
- "htacess.conf")),
+ "htaccess.conf")),
"mod_htaccess";
"ip_" ++ Rest ->
inets_test_lib:start_http_server(
@@ -596,24 +584,22 @@ init_per_testcase3(Case, Config) ->
SslTag =
case X of
$p -> ssl; % plain
- $o -> ossl; % OpenSSL based ssl
$e -> essl % Erlang based ssl
end,
case inets_test_lib:start_http_server_ssl(
filename:join(TcTopDir,
integer_to_list(?SSL_PORT) ++
- "htacess.conf"), SslTag) of
+ "htaccess.conf"), SslTag) of
ok ->
"mod_htaccess";
Other ->
- error_logger:info_report("Other: ~p~n", [Other]),
+ error_logger:info_msg("Other: ~p~n", [Other]),
{skip, "SSL does not seem to be supported"}
end;
[X, $s, $s, $l, $_ | Rest] ->
SslTag =
case X of
$p -> ssl;
- $o -> ossl;
$e -> essl
end,
case inets_test_lib:start_http_server_ssl(
@@ -623,20 +609,17 @@ init_per_testcase3(Case, Config) ->
ok ->
Rest;
Other ->
- error_logger:info_report("Other: ~p~n", [Other]),
+ error_logger:info_msg("Other: ~p~n", [Other]),
{skip, "SSL does not seem to be supported"}
end;
"ipv6_" ++ _ = TestCaseStr ->
- {ok, Hostname} = inet:gethostname(),
-
- case lists:member(list_to_atom(Hostname),
- ?config(ipv6_hosts, Config)) of
- true ->
+ case inets_test_lib:has_ipv6_support() of
+ {ok, _} ->
inets_test_lib:start_http_server(
filename:join(TcTopDir,
TestCaseStr ++ ".conf"));
- false ->
+ _ ->
{skip, "Host does not support IPv6"}
end
end,
@@ -650,8 +633,8 @@ init_per_testcase3(Case, Config) ->
"mod_htaccess" ->
ServerRoot = ?config(server_root, Config),
Path = filename:join([ServerRoot, "htdocs"]),
- catch remove_htacess(Path),
- create_htacess_data(Path, ?config(address, Config)),
+ catch remove_htaccess(Path),
+ create_htaccess_data(Path, ?config(address, Config)),
[{watchdog, Dog} | NewConfig];
"range" ->
ServerRoot = ?config(server_root, Config),
@@ -1121,13 +1104,6 @@ pssl_mod_alias(suite) ->
pssl_mod_alias(Config) when is_list(Config) ->
ssl_mod_alias(ssl, Config).
-ossl_mod_alias(doc) ->
- ["Module test: mod_alias - using new of configure old SSL"];
-ossl_mod_alias(suite) ->
- [];
-ossl_mod_alias(Config) when is_list(Config) ->
- ssl_mod_alias(ossl, Config).
-
essl_mod_alias(doc) ->
["Module test: mod_alias - using new of configure new SSL"];
essl_mod_alias(suite) ->
@@ -1151,13 +1127,6 @@ pssl_mod_actions(suite) ->
pssl_mod_actions(Config) when is_list(Config) ->
ssl_mod_actions(ssl, Config).
-ossl_mod_actions(doc) ->
- ["Module test: mod_actions - using new of configure old SSL"];
-ossl_mod_actions(suite) ->
- [];
-ossl_mod_actions(Config) when is_list(Config) ->
- ssl_mod_actions(ossl, Config).
-
essl_mod_actions(doc) ->
["Module test: mod_actions - using new of configure new SSL"];
essl_mod_actions(suite) ->
@@ -1183,13 +1152,6 @@ pssl_mod_security(suite) ->
pssl_mod_security(Config) when is_list(Config) ->
ssl_mod_security(ssl, Config).
-ossl_mod_security(doc) ->
- ["Module test: mod_security - using new of configure old SSL"];
-ossl_mod_security(suite) ->
- [];
-ossl_mod_security(Config) when is_list(Config) ->
- ssl_mod_security(ossl, Config).
-
essl_mod_security(doc) ->
["Module test: mod_security - using new of configure new SSL"];
essl_mod_security(suite) ->
@@ -1216,13 +1178,6 @@ pssl_mod_auth(suite) ->
pssl_mod_auth(Config) when is_list(Config) ->
ssl_mod_auth(ssl, Config).
-ossl_mod_auth(doc) ->
- ["Module test: mod_auth - using new of configure old SSL"];
-ossl_mod_auth(suite) ->
- [];
-ossl_mod_auth(Config) when is_list(Config) ->
- ssl_mod_auth(ossl, Config).
-
essl_mod_auth(doc) ->
["Module test: mod_auth - using new of configure new SSL"];
essl_mod_auth(suite) ->
@@ -1247,13 +1202,6 @@ pssl_mod_auth_api(suite) ->
pssl_mod_auth_api(Config) when is_list(Config) ->
ssl_mod_auth_api(ssl, Config).
-ossl_mod_auth_api(doc) ->
- ["Module test: mod_auth - using new of configure old SSL"];
-ossl_mod_auth_api(suite) ->
- [];
-ossl_mod_auth_api(Config) when is_list(Config) ->
- ssl_mod_auth_api(ossl, Config).
-
essl_mod_auth_api(doc) ->
["Module test: mod_auth - using new of configure new SSL"];
essl_mod_auth_api(suite) ->
@@ -1280,13 +1228,6 @@ pssl_mod_auth_mnesia_api(suite) ->
pssl_mod_auth_mnesia_api(Config) when is_list(Config) ->
ssl_mod_auth_mnesia_api(ssl, Config).
-ossl_mod_auth_mnesia_api(doc) ->
- ["Module test: mod_auth_mnesia_api - using new of configure old SSL"];
-ossl_mod_auth_mnesia_api(suite) ->
- [];
-ossl_mod_auth_mnesia_api(Config) when is_list(Config) ->
- ssl_mod_auth_mnesia_api(ossl, Config).
-
essl_mod_auth_mnesia_api(doc) ->
["Module test: mod_auth_mnesia_api - using new of configure new SSL"];
essl_mod_auth_mnesia_api(suite) ->
@@ -1311,13 +1252,6 @@ pssl_mod_htaccess(suite) ->
pssl_mod_htaccess(Config) when is_list(Config) ->
ssl_mod_htaccess(ssl, Config).
-ossl_mod_htaccess(doc) ->
- ["Module test: mod_htaccess - using new of configure old SSL"];
-ossl_mod_htaccess(suite) ->
- [];
-ossl_mod_htaccess(Config) when is_list(Config) ->
- ssl_mod_htaccess(ossl, Config).
-
essl_mod_htaccess(doc) ->
["Module test: mod_htaccess - using new of configure new SSL"];
essl_mod_htaccess(suite) ->
@@ -1342,13 +1276,6 @@ pssl_mod_cgi(suite) ->
pssl_mod_cgi(Config) when is_list(Config) ->
ssl_mod_cgi(ssl, Config).
-ossl_mod_cgi(doc) ->
- ["Module test: mod_cgi - using new of configure old SSL"];
-ossl_mod_cgi(suite) ->
- [];
-ossl_mod_cgi(Config) when is_list(Config) ->
- ssl_mod_cgi(ossl, Config).
-
essl_mod_cgi(doc) ->
["Module test: mod_cgi - using new of configure new SSL"];
essl_mod_cgi(suite) ->
@@ -1378,13 +1305,6 @@ pssl_mod_esi(suite) ->
pssl_mod_esi(Config) when is_list(Config) ->
ssl_mod_esi(ssl, Config).
-ossl_mod_esi(doc) ->
- ["Module test: mod_esi - using new of configure old SSL"];
-ossl_mod_esi(suite) ->
- [];
-ossl_mod_esi(Config) when is_list(Config) ->
- ssl_mod_esi(ossl, Config).
-
essl_mod_esi(doc) ->
["Module test: mod_esi - using new of configure new SSL"];
essl_mod_esi(suite) ->
@@ -1409,13 +1329,6 @@ pssl_mod_get(suite) ->
pssl_mod_get(Config) when is_list(Config) ->
ssl_mod_get(ssl, Config).
-ossl_mod_get(doc) ->
- ["Module test: mod_get - using new of configure old SSL"];
-ossl_mod_get(suite) ->
- [];
-ossl_mod_get(Config) when is_list(Config) ->
- ssl_mod_get(ossl, Config).
-
essl_mod_get(doc) ->
["Module test: mod_get - using new of configure new SSL"];
essl_mod_get(suite) ->
@@ -1440,13 +1353,6 @@ pssl_mod_head(suite) ->
pssl_mod_head(Config) when is_list(Config) ->
ssl_mod_head(ssl, Config).
-ossl_mod_head(doc) ->
- ["Module test: mod_head - using new of configure old SSL"];
-ossl_mod_head(suite) ->
- [];
-ossl_mod_head(Config) when is_list(Config) ->
- ssl_mod_head(ossl, Config).
-
essl_mod_head(doc) ->
["Module test: mod_head - using new of configure new SSL"];
essl_mod_head(suite) ->
@@ -1471,13 +1377,6 @@ pssl_mod_all(suite) ->
pssl_mod_all(Config) when is_list(Config) ->
ssl_mod_all(ssl, Config).
-ossl_mod_all(doc) ->
- ["All modules test - using new of configure old SSL"];
-ossl_mod_all(suite) ->
- [];
-ossl_mod_all(Config) when is_list(Config) ->
- ssl_mod_all(ossl, Config).
-
essl_mod_all(doc) ->
["All modules test - using new of configure new SSL"];
essl_mod_all(suite) ->
@@ -1502,13 +1401,6 @@ pssl_load_light(suite) ->
pssl_load_light(Config) when is_list(Config) ->
ssl_load_light(ssl, Config).
-ossl_load_light(doc) ->
- ["Test light load - using new of configure old SSL"];
-ossl_load_light(suite) ->
- [];
-ossl_load_light(Config) when is_list(Config) ->
- ssl_load_light(ossl, Config).
-
essl_load_light(doc) ->
["Test light load - using new of configure new SSL"];
essl_load_light(suite) ->
@@ -1534,13 +1426,6 @@ pssl_load_medium(suite) ->
pssl_load_medium(Config) when is_list(Config) ->
ssl_load_medium(ssl, Config).
-ossl_load_medium(doc) ->
- ["Test medium load - using new of configure old SSL"];
-ossl_load_medium(suite) ->
- [];
-ossl_load_medium(Config) when is_list(Config) ->
- ssl_load_medium(ossl, Config).
-
essl_load_medium(doc) ->
["Test medium load - using new of configure new SSL"];
essl_load_medium(suite) ->
@@ -1572,13 +1457,6 @@ pssl_load_heavy(suite) ->
pssl_load_heavy(Config) when is_list(Config) ->
ssl_load_heavy(ssl, Config).
-ossl_load_heavy(doc) ->
- ["Test heavy load - using new of configure old SSL"];
-ossl_load_heavy(suite) ->
- [];
-ossl_load_heavy(Config) when is_list(Config) ->
- ssl_load_heavy(ossl, Config).
-
essl_load_heavy(doc) ->
["Test heavy load - using new of configure new SSL"];
essl_load_heavy(suite) ->
@@ -1610,13 +1488,6 @@ pssl_dos_hostname(suite) ->
pssl_dos_hostname(Config) when is_list(Config) ->
ssl_dos_hostname(ssl, Config).
-ossl_dos_hostname(doc) ->
- ["Denial Of Service (DOS) attack test case - using new of configure old SSL"];
-ossl_dos_hostname(suite) ->
- [];
-ossl_dos_hostname(Config) when is_list(Config) ->
- ssl_dos_hostname(ossl, Config).
-
essl_dos_hostname(doc) ->
["Denial Of Service (DOS) attack test case - using new of configure new SSL"];
essl_dos_hostname(suite) ->
@@ -1642,13 +1513,6 @@ pssl_time_test(suite) ->
pssl_time_test(Config) when is_list(Config) ->
ssl_time_test(ssl, Config).
-ossl_time_test(doc) ->
- ["using new of configure old SSL"];
-ossl_time_test(suite) ->
- [];
-ossl_time_test(Config) when is_list(Config) ->
- ssl_time_test(ossl, Config).
-
essl_time_test(doc) ->
["using new of configure new SSL"];
essl_time_test(suite) ->
@@ -1688,14 +1552,6 @@ pssl_block_503(suite) ->
pssl_block_503(Config) when is_list(Config) ->
ssl_block_503(ssl, Config).
-ossl_block_503(doc) ->
- ["Check that you will receive status code 503 when the server"
- " is blocked and 200 when its not blocked - using new of configure old SSL."];
-ossl_block_503(suite) ->
- [];
-ossl_block_503(Config) when is_list(Config) ->
- ssl_block_503(ossl, Config).
-
essl_block_503(doc) ->
["Check that you will receive status code 503 when the server"
" is blocked and 200 when its not blocked - using new of configure new SSL."];
@@ -1723,15 +1579,6 @@ pssl_block_disturbing_idle(suite) ->
pssl_block_disturbing_idle(Config) when is_list(Config) ->
ssl_block_disturbing_idle(ssl, Config).
-ossl_block_disturbing_idle(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "distribing does not really make a difference in this case."
- "Using new of configure old SSL"];
-ossl_block_disturbing_idle(suite) ->
- [];
-ossl_block_disturbing_idle(Config) when is_list(Config) ->
- ssl_block_disturbing_idle(ossl, Config).
-
essl_block_disturbing_idle(doc) ->
["Check that you can block/unblock an idle server. The strategy "
"distribing does not really make a difference in this case."
@@ -1760,15 +1607,6 @@ pssl_block_non_disturbing_idle(suite) ->
pssl_block_non_disturbing_idle(Config) when is_list(Config) ->
ssl_block_non_disturbing_idle(ssl, Config).
-ossl_block_non_disturbing_idle(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "non distribing does not really make a difference in this case."
- "Using new of configure old SSL"];
-ossl_block_non_disturbing_idle(suite) ->
- [];
-ossl_block_non_disturbing_idle(Config) when is_list(Config) ->
- ssl_block_non_disturbing_idle(ossl, Config).
-
essl_block_non_disturbing_idle(doc) ->
["Check that you can block/unblock an idle server. The strategy "
"non distribing does not really make a difference in this case."
@@ -1797,15 +1635,6 @@ pssl_block_disturbing_active(suite) ->
pssl_block_disturbing_active(Config) when is_list(Config) ->
ssl_block_disturbing_active(ssl, Config).
-ossl_block_disturbing_active(doc) ->
- ["Check that you can block/unblock an active server. The strategy "
- "distribing means ongoing requests should be terminated."
- "Using new of configure old SSL"];
-ossl_block_disturbing_active(suite) ->
- [];
-ossl_block_disturbing_active(Config) when is_list(Config) ->
- ssl_block_disturbing_active(ossl, Config).
-
essl_block_disturbing_active(doc) ->
["Check that you can block/unblock an active server. The strategy "
"distribing means ongoing requests should be terminated."
@@ -1834,15 +1663,6 @@ pssl_block_non_disturbing_active(suite) ->
pssl_block_non_disturbing_active(Config) when is_list(Config) ->
ssl_block_non_disturbing_active(ssl, Config).
-ossl_block_non_disturbing_active(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "non distribing means the ongoing requests should be compleated."
- "Using new of configure old SSL"];
-ossl_block_non_disturbing_active(suite) ->
- [];
-ossl_block_non_disturbing_active(Config) when is_list(Config) ->
- ssl_block_non_disturbing_active(ossl, Config).
-
essl_block_non_disturbing_active(doc) ->
["Check that you can block/unblock an idle server. The strategy "
"non distribing means the ongoing requests should be compleated."
@@ -1873,17 +1693,6 @@ pssl_block_disturbing_active_timeout_not_released(Config)
when is_list(Config) ->
ssl_block_disturbing_active_timeout_not_released(ssl, Config).
-ossl_block_disturbing_active_timeout_not_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "distribing means ongoing requests should be compleated"
- "if the timeout does not occur."
- "Using new of configure old SSL"];
-ossl_block_disturbing_active_timeout_not_released(suite) ->
- [];
-ossl_block_disturbing_active_timeout_not_released(Config)
- when is_list(Config) ->
- ssl_block_disturbing_active_timeout_not_released(ossl, Config).
-
essl_block_disturbing_active_timeout_not_released(doc) ->
["Check that you can block an active server. The strategy "
"distribing means ongoing requests should be compleated"
@@ -1917,17 +1726,6 @@ pssl_block_disturbing_active_timeout_released(Config)
when is_list(Config) ->
ssl_block_disturbing_active_timeout_released(ssl, Config).
-ossl_block_disturbing_active_timeout_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "distribing means ongoing requests should be terminated when"
- "the timeout occurs."
- "Using new of configure old SSL"];
-ossl_block_disturbing_active_timeout_released(suite) ->
- [];
-ossl_block_disturbing_active_timeout_released(Config)
- when is_list(Config) ->
- ssl_block_disturbing_active_timeout_released(ossl, Config).
-
essl_block_disturbing_active_timeout_released(doc) ->
["Check that you can block an active server. The strategy "
"distribing means ongoing requests should be terminated when"
@@ -1962,16 +1760,6 @@ pssl_block_non_disturbing_active_timeout_not_released(Config)
when is_list(Config) ->
ssl_block_non_disturbing_active_timeout_not_released(ssl, Config).
-ossl_block_non_disturbing_active_timeout_not_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "non non distribing means ongoing requests should be completed."
- "Using new of configure old SSL"];
-ossl_block_non_disturbing_active_timeout_not_released(suite) ->
- [];
-ossl_block_non_disturbing_active_timeout_not_released(Config)
- when is_list(Config) ->
- ssl_block_non_disturbing_active_timeout_not_released(ossl, Config).
-
essl_block_non_disturbing_active_timeout_not_released(doc) ->
["Check that you can block an active server. The strategy "
"non non distribing means ongoing requests should be completed."
@@ -2006,17 +1794,6 @@ pssl_block_non_disturbing_active_timeout_released(Config)
when is_list(Config) ->
ssl_block_non_disturbing_active_timeout_released(ssl, Config).
-ossl_block_non_disturbing_active_timeout_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "non distribing means ongoing requests should be completed. "
- "When the timeout occurs the block operation sohould be canceled."
- "Using new of configure old SSL"];
-ossl_block_non_disturbing_active_timeout_released(suite) ->
- [];
-ossl_block_non_disturbing_active_timeout_released(Config)
- when is_list(Config) ->
- ssl_block_non_disturbing_active_timeout_released(ossl, Config).
-
essl_block_non_disturbing_active_timeout_released(doc) ->
["Check that you can block an active server. The strategy "
"non distribing means ongoing requests should be completed. "
@@ -2050,13 +1827,6 @@ pssl_block_disturbing_blocker_dies(suite) ->
pssl_block_disturbing_blocker_dies(Config) when is_list(Config) ->
ssl_block_disturbing_blocker_dies(ssl, Config).
-ossl_block_disturbing_blocker_dies(doc) ->
- ["using new of configure old SSL"];
-ossl_block_disturbing_blocker_dies(suite) ->
- [];
-ossl_block_disturbing_blocker_dies(Config) when is_list(Config) ->
- ssl_block_disturbing_blocker_dies(ossl, Config).
-
essl_block_disturbing_blocker_dies(doc) ->
["using new of configure new SSL"];
essl_block_disturbing_blocker_dies(suite) ->
@@ -2081,13 +1851,6 @@ pssl_block_non_disturbing_blocker_dies(suite) ->
pssl_block_non_disturbing_blocker_dies(Config) when is_list(Config) ->
ssl_block_non_disturbing_blocker_dies(ssl, Config).
-ossl_block_non_disturbing_blocker_dies(doc) ->
- ["using new of configure old SSL"];
-ossl_block_non_disturbing_blocker_dies(suite) ->
- [];
-ossl_block_non_disturbing_blocker_dies(Config) when is_list(Config) ->
- ssl_block_non_disturbing_blocker_dies(ossl, Config).
-
essl_block_non_disturbing_blocker_dies(doc) ->
["using new of configure new SSL"];
essl_block_non_disturbing_blocker_dies(suite) ->
@@ -2112,13 +1875,6 @@ pssl_restart_no_block(suite) ->
pssl_restart_no_block(Config) when is_list(Config) ->
ssl_restart_no_block(ssl, Config).
-ossl_restart_no_block(doc) ->
- ["using new of configure old SSL"];
-ossl_restart_no_block(suite) ->
- [];
-ossl_restart_no_block(Config) when is_list(Config) ->
- ssl_restart_no_block(ossl, Config).
-
essl_restart_no_block(doc) ->
["using new of configure new SSL"];
essl_restart_no_block(suite) ->
@@ -2143,13 +1899,6 @@ pssl_restart_disturbing_block(suite) ->
pssl_restart_disturbing_block(Config) when is_list(Config) ->
ssl_restart_disturbing_block(ssl, Config).
-ossl_restart_disturbing_block(doc) ->
- ["using new of configure old SSL"];
-ossl_restart_disturbing_block(suite) ->
- [];
-ossl_restart_disturbing_block(Config) when is_list(Config) ->
- ssl_restart_disturbing_block(ossl, Config).
-
essl_restart_disturbing_block(doc) ->
["using new of configure new SSL"];
essl_restart_disturbing_block(suite) ->
@@ -2207,13 +1956,6 @@ pssl_restart_non_disturbing_block(suite) ->
pssl_restart_non_disturbing_block(Config) when is_list(Config) ->
ssl_restart_non_disturbing_block(ssl, Config).
-ossl_restart_non_disturbing_block(doc) ->
- ["using new of configure old SSL"];
-ossl_restart_non_disturbing_block(suite) ->
- [];
-ossl_restart_non_disturbing_block(Config) when is_list(Config) ->
- ssl_restart_non_disturbing_block(ossl, Config).
-
essl_restart_non_disturbing_block(doc) ->
["using new of configure new SSL"];
essl_restart_non_disturbing_block(suite) ->
@@ -2409,30 +2151,76 @@ ip_mod_cgi_chunked_encoding_test(Config) when is_list(Config) ->
ok.
%-------------------------------------------------------------------------
-ipv6_hostname(doc) ->
+
+ipv6_hostname_ipcomm() ->
+ [{require, ipv6_hosts}].
+ipv6_hostname_ipcomm(X) ->
+ SocketType = ip_comm,
+ Port = ?IP_PORT,
+ ipv6_hostname(SocketType, Port, X).
+
+ipv6_hostname_essl() ->
+ [{require, ipv6_hosts}].
+ipv6_hostname_essl(X) ->
+ SocketType = essl,
+ Port = ?SSL_PORT,
+ ipv6_hostname(SocketType, Port, X).
+
+ipv6_hostname(_SocketType, _Port, doc) ->
["Test standard ipv6 address"];
-ipv6_hostname(suite)->
+ipv6_hostname(_SocketType, _Port, suite)->
[];
-ipv6_hostname(Config) when is_list(Config) ->
+ipv6_hostname(SocketType, Port, Config) when is_list(Config) ->
+ tsp("ipv6_hostname -> entry with"
+ "~n SocketType: ~p"
+ "~n Port: ~p"
+ "~n Config: ~p", [SocketType, Port, Config]),
Host = ?config(host, Config),
- httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, node(),
- "GET / HTTP/1.1\r\n\r\n",
- [{statuscode, 200},
- {version, "HTTP/1.1"}]),
+ URI = "GET HTTP://" ++
+ Host ++ ":" ++ integer_to_list(Port) ++ "/ HTTP/1.1\r\n\r\n",
+ tsp("ipv6_hostname -> Host: ~p", [Host]),
+ httpd_test_lib:verify_request(SocketType, Host, Port, [inet6],
+ node(),
+ URI,
+ [{statuscode, 200}, {version, "HTTP/1.1"}]),
ok.
%%-------------------------------------------------------------------------
-ipv6_address(doc) ->
+
+ipv6_address_ipcomm() ->
+ [{require, ipv6_hosts}].
+ipv6_address_ipcomm(X) ->
+ SocketType = ip_comm,
+ Port = ?IP_PORT,
+ ipv6_address(SocketType, Port, X).
+
+ipv6_address_essl() ->
+ [{require, ipv6_hosts}].
+ipv6_address_essl(X) ->
+ SocketType = essl,
+ Port = ?SSL_PORT,
+ ipv6_address(SocketType, Port, X).
+
+ipv6_address(_SocketType, _Port, doc) ->
["Test standard ipv6 address"];
-ipv6_address(suite)->
+ipv6_address(_SocketType, _Port, suite)->
[];
-ipv6_address(Config) when is_list(Config) ->
- httpd_test_lib:verify_request(ip_comm, ?IPV6_LOCAL_HOST, ?IP_PORT,
- node(), "GET / HTTP/1.1\r\n\r\n",
- [{statuscode, 200},
- {version, "HTTP/1.1"}]),
+ipv6_address(SocketType, Port, Config) when is_list(Config) ->
+ tsp("ipv6_address -> entry with"
+ "~n SocketType: ~p"
+ "~n Port: ~p"
+ "~n Config: ~p", [SocketType, Port, Config]),
+ Host = ?config(host, Config),
+ tsp("ipv6_address -> Host: ~p", [Host]),
+ URI = "GET HTTP://" ++
+ Host ++ ":" ++ integer_to_list(Port) ++ "/ HTTP/1.1\r\n\r\n",
+ httpd_test_lib:verify_request(SocketType, Host, Port, [inet6],
+ node(),
+ URI,
+ [{statuscode, 200}, {version, "HTTP/1.1"}]),
ok.
+
%%--------------------------------------------------------------------
ticket_5775(doc) ->
["Tests that content-length is correct"];
@@ -2563,7 +2351,6 @@ create_config(Config, Access, FileName) ->
SSL =
if
(Type =:= ssl) orelse
- (Type =:= ossl) orelse
(Type =:= essl) ->
[cline(["SSLCertificateFile ",
filename:join(ServerRoot, "ssl/ssl_server.pem")]),
@@ -2805,22 +2592,22 @@ cleanup_mnesia() ->
mnesia:delete_schema([node()]),
ok.
-create_htacess_data(Path, IpAddress)->
- create_htacess_dirs(Path),
+create_htaccess_data(Path, IpAddress)->
+ create_htaccess_dirs(Path),
create_html_file(filename:join([Path,"ht/open/dummy.html"])),
create_html_file(filename:join([Path,"ht/blocknet/dummy.html"])),
create_html_file(filename:join([Path,"ht/secret/dummy.html"])),
create_html_file(filename:join([Path,"ht/secret/top_secret/dummy.html"])),
- create_htacess_file(filename:join([Path,"ht/open/.htaccess"]),
+ create_htaccess_file(filename:join([Path,"ht/open/.htaccess"]),
Path, "user one Aladdin"),
- create_htacess_file(filename:join([Path,"ht/secret/.htaccess"]),
+ create_htaccess_file(filename:join([Path,"ht/secret/.htaccess"]),
Path, "group group1 group2"),
- create_htacess_file(filename:join([Path,
+ create_htaccess_file(filename:join([Path,
"ht/secret/top_secret/.htaccess"]),
Path, "user four"),
- create_htacess_file(filename:join([Path,"ht/blocknet/.htaccess"]),
+ create_htaccess_file(filename:join([Path,"ht/blocknet/.htaccess"]),
Path, nouser, IpAddress),
create_user_group_file(filename:join([Path,"ht","users.file"]),
@@ -2835,7 +2622,7 @@ create_html_file(PathAndFileName)->
"<html><head><title>test</title></head>
<body>testar</body></html>")).
-create_htacess_file(PathAndFileName, BaseDir, RequireData)->
+create_htaccess_file(PathAndFileName, BaseDir, RequireData)->
file:write_file(PathAndFileName,
list_to_binary(
"AuthUserFile "++ BaseDir ++
@@ -2844,7 +2631,7 @@ create_htacess_file(PathAndFileName, BaseDir, RequireData)->
" Basic\n<Limit>\nrequire " ++ RequireData ++
"\n</Limit>")).
-create_htacess_file(PathAndFileName, BaseDir, nouser, IpAddress)->
+create_htaccess_file(PathAndFileName, BaseDir, nouser, IpAddress)->
file:write_file(PathAndFileName,list_to_binary(
"AuthUserFile "++ BaseDir ++
"/ht/users.file\nAuthGroupFile " ++
@@ -2858,14 +2645,14 @@ create_htacess_file(PathAndFileName, BaseDir, nouser, IpAddress)->
create_user_group_file(PathAndFileName, Data)->
file:write_file(PathAndFileName, list_to_binary(Data)).
-create_htacess_dirs(Path)->
+create_htaccess_dirs(Path)->
ok = file:make_dir(filename:join([Path,"ht"])),
ok = file:make_dir(filename:join([Path,"ht/open"])),
ok = file:make_dir(filename:join([Path,"ht/blocknet"])),
ok = file:make_dir(filename:join([Path,"ht/secret"])),
ok = file:make_dir(filename:join([Path,"ht/secret/top_secret"])).
-remove_htacess_dirs(Path)->
+remove_htaccess_dirs(Path)->
file:del_dir(filename:join([Path,"ht/secret/top_secret"])),
file:del_dir(filename:join([Path,"ht/secret"])),
file:del_dir(filename:join([Path,"ht/blocknet"])),
@@ -2888,7 +2675,7 @@ format_ip(IpAddress,Pos)when Pos > 0->
format_ip(IpAddress, _Pos)->
"1" ++ IpAddress.
-remove_htacess(Path)->
+remove_htaccess(Path)->
file:delete(filename:join([Path,"ht/open/dummy.html"])),
file:delete(filename:join([Path,"ht/secret/dummy.html"])),
file:delete(filename:join([Path,"ht/secret/top_secret/dummy.html"])),
@@ -2899,7 +2686,7 @@ remove_htacess(Path)->
file:delete(filename:join([Path,"ht/secret/top_secret/.htaccess"])),
file:delete(filename:join([Path,"ht","users.file"])),
file:delete(filename:join([Path,"ht","groups.file"])),
- remove_htacess_dirs(Path).
+ remove_htaccess_dirs(Path).
dos_hostname_poll(Type, Host, Port, Node, Hosts) ->
@@ -2939,35 +2726,65 @@ create_range_data(Path) ->
"12345678901234567890",
"12345678901234567890"])).
-%% create_ipv6_config(Config, FileName, Ipv6Address) ->
-%% ServerRoot = ?config(server_root, Config),
-%% TcTopDir = ?config(tc_top_dir, Config),
-%% Port = ?config(port, Config),
-%% SockType = ?config(sock_type, Config),
-%%
-%% MaxHdrSz = io_lib:format("~p", [256]),
-%% MaxHdrAct = io_lib:format("~p", [close]),
-%%
-%% Mod_order = "Modules mod_alias mod_auth mod_esi mod_actions mod_cgi"
-%% " mod_include mod_dir mod_get mod_head"
-%% " mod_log mod_disk_log mod_trace",
-%%
-%% HttpConfig = [cline(["BindAddress ", "[" ++ Ipv6Address ++"]|inet6"]),
-%% cline(["Port ", integer_to_list(Port)]),
-%% cline(["ServerName ", "httpc_test"]),
-%% cline(["SocketType ", atom_to_list(SockType)]),
-%% cline([Mod_order]),
-%% cline(["ServerRoot ", ServerRoot]),
-%% cline(["DocumentRoot ",
-%% filename:join(ServerRoot, "htdocs")]),
-%% cline(["MaxHeaderSize ",MaxHdrSz]),
-%% cline(["MaxHeaderAction ",MaxHdrAct]),
-%% cline(["DirectoryIndex ", "index.html "]),
-%% cline(["DefaultType ", "text/plain"])],
-%% ConfigFile = filename:join([TcTopDir,FileName]),
-%% {ok, Fd} = file:open(ConfigFile, [write]),
-%% ok = file:write(Fd, lists:flatten(HttpConfig)),
-%% ok = file:close(Fd).
+create_ipv6_config(Config, FileName, Ipv6Address) ->
+ ServerRoot = ?config(server_root, Config),
+ TcTopDir = ?config(tc_top_dir, Config),
+ Port = ?config(port, Config),
+ SockType = ?config(sock_type, Config),
+ Mods = io_lib:format("~p", [httpd_mod]),
+ Funcs = io_lib:format("~p", [ssl_password_cb]),
+ Host = ?config(ipv6_host, Config),
+
+ MaxHdrSz = io_lib:format("~p", [256]),
+ MaxHdrAct = io_lib:format("~p", [close]),
+
+ Mod_order = "Modules mod_alias mod_auth mod_esi mod_actions mod_cgi"
+ " mod_include mod_dir mod_get mod_head"
+ " mod_log mod_disk_log mod_trace",
+
+ SSL =
+ if
+ (SockType =:= ssl) orelse
+ (SockType =:= essl) ->
+ [cline(["SSLCertificateFile ",
+ filename:join(ServerRoot, "ssl/ssl_server.pem")]),
+ cline(["SSLCertificateKeyFile ",
+ filename:join(ServerRoot, "ssl/ssl_server.pem")]),
+ cline(["SSLCACertificateFile ",
+ filename:join(ServerRoot, "ssl/ssl_server.pem")]),
+ cline(["SSLPasswordCallbackModule ", Mods]),
+ cline(["SSLPasswordCallbackFunction ", Funcs]),
+ cline(["SSLVerifyClient 0"]),
+ cline(["SSLVerifyDepth 1"])];
+ true ->
+ []
+ end,
+
+ BindAddress = "[" ++ Ipv6Address ++"]|inet6",
+
+ HttpConfig =
+ [cline(["BindAddress ", BindAddress]),
+ cline(["Port ", integer_to_list(Port)]),
+ cline(["ServerName ", Host]),
+ cline(["SocketType ", atom_to_list(SockType)]),
+ cline([Mod_order]),
+ cline(["ServerRoot ", ServerRoot]),
+ cline(["DocumentRoot ", filename:join(ServerRoot, "htdocs")]),
+ cline(["MaxHeaderSize ",MaxHdrSz]),
+ cline(["MaxHeaderAction ",MaxHdrAct]),
+ cline(["DirectoryIndex ", "index.html "]),
+ cline(["DefaultType ", "text/plain"]),
+ SSL],
+ ConfigFile = filename:join([TcTopDir,FileName]),
+ {ok, Fd} = file:open(ConfigFile, [write]),
+ ok = file:write(Fd, lists:flatten(HttpConfig)),
+ ok = file:close(Fd).
+
+
+%% tsp(F) ->
+%% inets_test_lib:tsp(F).
+tsp(F, A) ->
+ inets_test_lib:tsp(F, A).
tsf(Reason) ->
- test_server:fail(Reason).
+ inets_test_lib:tsf(Reason).
diff --git a/lib/inets/test/httpd_basic_SUITE.erl b/lib/inets/test/httpd_basic_SUITE.erl
index 3e29b68283..f23d0b4765 100644
--- a/lib/inets/test/httpd_basic_SUITE.erl
+++ b/lib/inets/test/httpd_basic_SUITE.erl
@@ -29,7 +29,11 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [uri_too_long_414, header_too_long_413, escaped_url_in_error_body].
+ [
+ uri_too_long_414,
+ header_too_long_413,
+ escaped_url_in_error_body
+ ].
groups() ->
[].
@@ -40,6 +44,7 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
+
%%--------------------------------------------------------------------
%% Function: init_per_suite(Config) -> Config
%% Config - [tuple()]
@@ -50,6 +55,8 @@ end_per_group(_GroupName, Config) ->
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_suite(Config) ->
+ tsp("init_per_suite -> entry with"
+ "~n Config: ~p", [Config]),
ok = inets:start(),
PrivDir = ?config(priv_dir, Config),
HttpdConf = [{port, 0}, {ipfamily, inet},
@@ -64,6 +71,8 @@ init_per_suite(Config) ->
%% Description: Cleanup after the whole suite
%%--------------------------------------------------------------------
end_per_suite(_Config) ->
+ tsp("end_per_suite -> entry with"
+ "~n Config: ~p", [_Config]),
inets:stop(),
ok.
@@ -79,9 +88,12 @@ end_per_suite(_Config) ->
%% 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_testcase(_Case, Config) ->
+init_per_testcase(Case, Config) ->
+ tsp("init_per_testcase(~w) -> entry with"
+ "~n Config: ~p", [Case, Config]),
Config.
+
%%--------------------------------------------------------------------
%% Function: end_per_testcase(Case, Config) -> _
%% Case - atom()
@@ -90,9 +102,12 @@ init_per_testcase(_Case, Config) ->
%% A list of key/value pairs, holding the test case configuration.
%% Description: Cleanup after each test case
%%--------------------------------------------------------------------
-end_per_testcase(_, Config) ->
+end_per_testcase(Case, Config) ->
+ tsp("end_per_testcase(~w) -> entry with"
+ "~n Config: ~p", [Case, Config]),
Config.
+
%%-------------------------------------------------------------------------
%% Test cases starts here.
%%-------------------------------------------------------------------------
@@ -142,22 +157,30 @@ escaped_url_in_error_body(doc) ->
escaped_url_in_error_body(suite) ->
[];
escaped_url_in_error_body(Config) when is_list(Config) ->
- HttpdConf = ?config(httpd_conf, Config),
+ tsp("escaped_url_in_error_body -> entry with"
+ "~n Config: ~p", [Config]),
+ HttpdConf = ?config(httpd_conf, Config),
{ok, Pid} = inets:start(httpd, [{port, 0} | HttpdConf]),
Info = httpd:info(Pid),
Port = proplists:get_value(port, Info),
- Address = proplists:get_value(bind_address, Info),
- Path = "/<b>this_is_bold<b>",
+ _Address = proplists:get_value(bind_address, Info),
+ Path = "/<b>this_is_bold</b>",
URL = ?URL_START ++ integer_to_list(Port) ++ Path,
EscapedPath = http_uri:encode(Path),
- {ok, {404, Body}} = httpc:request(get, {URL, []},
- [{url_encode, true}],
- [{version, "HTTP/1.0"}, {full_result, false}]),
- EscapedPath = find_URL_path(string:tokens(Body, " ")),
- {ok, {404, Body1}} = httpc:request(get, {URL, []}, [],
- [{version, "HTTP/1.0"}, {full_result, false}]),
+ {ok, {404, Body1}} = httpc:request(get, {URL, []},
+ [{url_encode, true},
+ {version, "HTTP/1.0"}],
+ [{full_result, false}]),
EscapedPath = find_URL_path(string:tokens(Body1, " ")),
- inets:stop(httpd, Pid).
+ {ok, {404, Body2}} = httpc:request(get, {URL, []},
+ [{url_encode, false},
+ {version, "HTTP/1.0"}],
+ [{full_result, false}]),
+ HTMLEncodedPath = http_util:html_encode(Path),
+ HTMLEncodedPath = find_URL_path(string:tokens(Body2, " ")),
+ inets:stop(httpd, Pid),
+ tsp("escaped_url_in_error_body -> done"),
+ ok.
find_URL_path([]) ->
"";
@@ -165,3 +188,10 @@ find_URL_path(["URL", URL | _]) ->
URL;
find_URL_path([_ | Rest]) ->
find_URL_path(Rest).
+
+
+tsp(F) ->
+ tsp(F, []).
+tsp(F, A) ->
+ test_server:format("~p ~p:" ++ F ++ "~n", [self(), ?MODULE | A]).
+
diff --git a/lib/inets/test/httpd_mod.erl b/lib/inets/test/httpd_mod.erl
index f2c1fd6a65..1754cec7bc 100644
--- a/lib/inets/test/httpd_mod.erl
+++ b/lib/inets/test/httpd_mod.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The 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,7 +19,6 @@
%%
-module(httpd_mod).
--author('[email protected]').
-include("test_server.hrl").
-include("test_server_line.hrl").
@@ -815,6 +814,8 @@ esi(Type, Port, Host, Node) ->
[{statuscode, 302},
{version, "HTTP/1.0"}]),
ok.
+
+
%%--------------------------------------------------------------------
get(Type, Port, Host, Node) ->
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
diff --git a/lib/inets/test/httpd_test_lib.erl b/lib/inets/test/httpd_test_lib.erl
index 3189a758a5..581461fe03 100644
--- a/lib/inets/test/httpd_test_lib.erl
+++ b/lib/inets/test/httpd_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The 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,7 +22,7 @@
-include("inets_test_lib.hrl").
%% Poll functions
--export([verify_request/6, verify_request/7, is_expect/1]).
+-export([verify_request/6, verify_request/7, verify_request/8, is_expect/1]).
-record(state, {request, % string()
socket, % socket()
@@ -81,33 +81,57 @@
%%------------------------------------------------------------------
verify_request(SocketType, Host, Port, Node, RequestStr, Options) ->
verify_request(SocketType, Host, Port, Node, RequestStr, Options, 30000).
-verify_request(SocketType, Host, Port, Node, RequestStr, Options, TimeOut) ->
- {ok, Socket} = inets_test_lib:connect_bin(SocketType, Host, Port),
+verify_request(SocketType, Host, Port, TranspOpts, Node, RequestStr, Options)
+ when is_list(TranspOpts) ->
+ verify_request(SocketType, Host, Port, TranspOpts, Node, RequestStr, Options, 30000);
+verify_request(SocketType, Host, Port, Node, RequestStr, Options, TimeOut)
+ when (is_integer(TimeOut) orelse (TimeOut =:= infinity)) ->
+ verify_request(SocketType, Host, Port, [], Node, RequestStr, Options, TimeOut).
+verify_request(SocketType, Host, Port, TranspOpts, Node, RequestStr, Options, TimeOut) ->
+ tsp("verify_request -> entry with"
+ "~n SocketType: ~p"
+ "~n Host: ~p"
+ "~n Port: ~p"
+ "~n TranspOpts: ~p"
+ "~n Node: ~p"
+ "~n Options: ~p"
+ "~n TimeOut: ~p",
+ [SocketType, Host, Port, TranspOpts, Node, Options, TimeOut]),
+ case (catch inets_test_lib:connect_bin(SocketType, Host, Port, TranspOpts)) of
+ {ok, Socket} ->
+ tsp("verify_request -> connected - now send message"),
+ SendRes = inets_test_lib:send(SocketType, Socket, RequestStr),
+ tsp("verify_request -> send result: "
+ "~n ~p", [SendRes]),
+ State = case inets_regexp:match(RequestStr, "printenv") of
+ nomatch ->
+ #state{};
+ _ ->
+ #state{print = true}
+ end,
+
+ case request(State#state{request = RequestStr,
+ socket = Socket}, TimeOut) of
+ {error, Reason} ->
+ tsp("request failed: "
+ "~n Reason: ~p", [Reason]),
+ {error, Reason};
+ NewState ->
+ tsp("validate reply: "
+ "~n NewState: ~p", [NewState]),
+ ValidateResult =
+ validate(RequestStr, NewState, Options, Node, Port),
+ tsp("validation result: "
+ "~n ~p", [ValidateResult]),
+ inets_test_lib:close(SocketType, Socket),
+ ValidateResult
+ end;
- _SendRes = inets_test_lib:send(SocketType, Socket, RequestStr),
-
- State = case inets_regexp:match(RequestStr, "printenv") of
- nomatch ->
- #state{};
- _ ->
- #state{print = true}
- end,
-
- case request(State#state{request = RequestStr,
- socket = Socket}, TimeOut) of
- {error, Reason} ->
- tsp("request failed: "
- "~n Reason: ~p", [Reason]),
- {error, Reason};
- NewState ->
- tsp("validate reply: "
- "~n NewState: ~p", [NewState]),
- ValidateResult = validate(RequestStr, NewState, Options,
- Node, Port),
- tsp("validation result: "
- "~n ~p", [ValidateResult]),
- inets_test_lib:close(SocketType, Socket),
- ValidateResult
+ ConnectError ->
+ tsp("verify_request -> connect failed: "
+ "~n ~p"
+ "~n", [ConnectError]),
+ tsf({connect_failure, ConnectError})
end.
request(#state{mfa = {Module, Function, Args},
@@ -214,7 +238,10 @@ validate(RequestStr, #state{status_line = {Version, StatusCode, _},
headers = Headers,
body = Body}, Options, N, P) ->
- %io:format("Status~p: H:~p B:~p~n", [StatusCode, Headers, Body]),
+ %% tsp("validate -> entry with"
+ %% "~n StatusCode: ~p"
+ %% "~n Headers: ~p"
+ %% "~n Body: ~p", [StatusCode, Headers, Body]),
check_version(Version, Options),
case lists:keysearch(statuscode, 1, Options) of
{value, _} ->
@@ -342,8 +369,10 @@ print(_, _, #state{print = false}) ->
ok.
-%% tsp(F) ->
-%% tsp(F, []).
+tsp(F) ->
+ inets_test_lib:tsp(F).
tsp(F, A) ->
- test_server:format("~p ~p:" ++ F ++ "~n", [self(), ?MODULE | A]).
+ inets_test_lib:tsp(F, A).
+tsf(Reason) ->
+ inets_test_lib:tsf(Reason).
diff --git a/lib/inets/test/httpd_time_test.erl b/lib/inets/test/httpd_time_test.erl
index f39f9faff0..c54674be36 100644
--- a/lib/inets/test/httpd_time_test.erl
+++ b/lib/inets/test/httpd_time_test.erl
@@ -19,7 +19,7 @@
%%
-module(httpd_time_test).
--export([t/3, t1/2, t2/2, t3/2, t4/2]).
+-export([t/3, t1/2, t2/2, t4/2]).
-export([do/1, do/2, do/3, do/4, do/5]).
@@ -45,10 +45,6 @@ t2(Host, Port) ->
t(ssl, Host, Port).
-t3(Host, Port) ->
- t(ossl, Host, Port).
-
-
t4(Host, Port) ->
t(essl, Host, Port).
diff --git a/lib/inets/test/inets_app_test.erl b/lib/inets/test/inets_app_test.erl
index 11b507fa26..9d7202e087 100644
--- a/lib/inets/test/inets_app_test.erl
+++ b/lib/inets/test/inets_app_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -241,6 +241,20 @@ undef_funcs(suite) ->
undef_funcs(doc) ->
[];
undef_funcs(Config) when is_list(Config) ->
+ %% We need to check if there is a point to run this test.
+ %% On some platforms, crypto will not build, which in turn
+ %% causes ssl to not to not build (at this time, this will
+ %% change in the future).
+ %% So, we first check if we can start crypto, and if not,
+ %% we skip this test case!
+ case (catch crypto:start()) of
+ ok ->
+ ok;
+ {error, {already_started, crypto}} ->
+ ok;
+ _ ->
+ ?SKIP(crypto_start_check_failed)
+ end,
App = inets,
AppFile = key1search(app_file, Config),
Mods = key1search(modules, AppFile),
diff --git a/lib/inets/test/inets_test_lib.erl b/lib/inets/test/inets_test_lib.erl
index c56a714f5a..ddb1a49394 100644
--- a/lib/inets/test/inets_test_lib.erl
+++ b/lib/inets/test/inets_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The 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,18 +26,64 @@
-export([start_http_server/1, start_http_server/2]).
-export([start_http_server_ssl/1, start_http_server_ssl/2]).
-export([hostname/0]).
--export([connect_bin/3, connect_byte/3, send/3, close/2]).
+-export([connect_bin/3, connect_bin/4,
+ connect_byte/3, connect_byte/4,
+ send/3, close/2]).
-export([copy_file/3, copy_files/2, copy_dirs/2, del_dirs/1]).
-export([info/4, log/4, debug/4, print/4]).
+-export([tsp/1, tsp/2, tsf/1]).
-export([check_body/1]).
-export([millis/0, millis_diff/2, hours/1, minutes/1, seconds/1, sleep/1]).
--export([oscmd/1]).
--export([non_pc_tc_maybe_skip/4, os_based_skip/1]).
+-export([oscmd/1, has_ipv6_support/1]).
+-export([non_pc_tc_maybe_skip/4, os_based_skip/1, skip/3, fail/3]).
-export([flush/0]).
-export([start_node/1, stop_node/1]).
%% -- Misc os command and stuff
+has_ipv6_support(Config) ->
+ case lists:keysearch(ipv6_hosts, 1, Config) of
+ false ->
+ %% Do a basic check to se if
+ %% our own host has a working IPv6 address...
+ tsp("has_ipv6_support -> no ipv6_hosts config"),
+ {ok, Hostname} = inet:gethostname(),
+ case inet:getaddrs(Hostname, inet6) of
+ {ok, [Addr|_]} when is_tuple(Addr) andalso
+ (element(1, Addr) =/= 0) ->
+ %% We actually need to test that the addr can be used,
+ %% this is done by attempting to create a (tcp)
+ %% listen socket
+ tsp("has_ipv6_support -> check Addr: ~p", [Addr]),
+ case (catch gen_tcp:listen(0, [inet6, {ip, Addr}])) of
+ {ok, LSock} ->
+ tsp("has_ipv6_support -> we are ipv6 host"),
+ gen_tcp:close(LSock),
+ {ok, Addr};
+ _ ->
+ undefined
+ end;
+ _ ->
+ undefined
+ end;
+ {value, {_, Hosts}} when is_list(Hosts) ->
+ %% Check if our host is in the list of *known* IPv6 hosts
+ tsp("has_ipv6_support -> Hosts: ~p", [Hosts]),
+ {ok, Hostname} = inet:gethostname(),
+ case lists:member(list_to_atom(Hostname), Hosts) of
+ true ->
+ tsp("has_ipv6_support -> we are known ipv6 host"),
+ {ok, [Addr|_]} = inet:getaddrs(Hostname, inet6),
+ {ok, Addr};
+ false ->
+ undefined
+ end;
+
+ _ ->
+ undefined
+
+ end.
+
oscmd(Cmd) ->
string:strip(os:cmd(Cmd), right, $\n).
@@ -87,31 +133,34 @@ start_http_server(Conf) ->
start_http_server(Conf, ?HTTP_DEFAULT_SSL_KIND).
start_http_server(Conf, essl = _SslTag) ->
+ tsp("start_http_server(essl) -> entry - try start crypto and public_key"),
application:start(crypto),
+ application:start(public_key),
do_start_http_server(Conf);
-start_http_server(Conf, _SslTag) ->
+start_http_server(Conf, SslTag) ->
+ tsp("start_http_server(~w) -> entry", [SslTag]),
do_start_http_server(Conf).
do_start_http_server(Conf) ->
- tsp("start http server with "
+ tsp("do_start_http_server -> entry with"
"~n Conf: ~p"
"~n", [Conf]),
application:load(inets),
case application:set_env(inets, services, [{httpd, Conf}]) of
ok ->
+ tsp("start_http_server -> httpd conf stored in inets app env"),
case application:start(inets) of
ok ->
+ tsp("start_http_server -> inets started"),
ok;
Error1 ->
- test_server:format("<ERROR> Failed starting application: "
- "~n Error: ~p"
- "~n", [Error1]),
+ tsp("<ERROR> Failed starting application: "
+ "~n Error1: ~p", [Error1]),
Error1
end;
Error2 ->
- test_server:format("<ERROR> Failed set application env: "
- "~n Error: ~p"
- "~n", [Error2]),
+ tsp("<ERROR> Failed set application env: "
+ "~n Error: ~p", [Error2]),
Error2
end.
@@ -285,29 +334,39 @@ os_based_skip(_) ->
%% Host -> atom() | string() | {A, B, C, D}
%% Port -> integer()
-connect_bin(ssl, Host, Port) ->
- connect(ssl, Host, Port, [binary, {packet,0}]);
-connect_bin(ossl, Host, Port) ->
- connect(ssl, Host, Port, [{ssl_imp, old}, binary, {packet,0}]);
-connect_bin(essl, Host, Port) ->
- connect(ssl, Host, Port, [{ssl_imp, new}, binary, {packet,0}, {reuseaddr, true}]);
-connect_bin(ip_comm, Host, Port) ->
- Opts = [inet6, binary, {packet,0}],
+connect_bin(SockType, Host, Port) ->
+ connect_bin(SockType, Host, Port, []).
+
+connect_bin(ssl, Host, Port, Opts0) ->
+ Opts = [binary, {packet,0} | Opts0],
+ connect(ssl, Host, Port, Opts);
+connect_bin(essl, Host, Port, Opts0) ->
+ Opts = [{ssl_imp, new}, binary, {packet,0}, {reuseaddr, true} | Opts0],
+ connect(ssl, Host, Port, Opts);
+connect_bin(ip_comm, Host, Port, Opts0) ->
+ Opts = [binary, {packet, 0} | Opts0],
connect(ip_comm, Host, Port, Opts).
+
+connect_byte(SockType, Host, Port) ->
+ connect_byte(SockType, Host, Port, []).
-connect_byte(ssl, Host, Port) ->
- connect(ssl, Host, Port, [{packet,0}]);
-connect_byte(ossl, Host, Port) ->
- connect(ssl, Host, Port, [{ssl_imp, old}, {packet,0}]);
-connect_byte(essl, Host, Port) ->
- connect(ssl, Host, Port, [{ssl_imp, new}, {packet,0}]);
-connect_byte(ip_comm, Host, Port) ->
- Opts = [inet6, {packet,0}],
+connect_byte(ssl, Host, Port, Opts0) ->
+ Opts = [{packet,0} | Opts0],
+ connect(ssl, Host, Port, Opts);
+connect_byte(essl, Host, Port, Opts0) ->
+ Opts = [{ssl_imp, new}, {packet,0} | Opts0],
+ connect(ssl, Host, Port, Opts);
+connect_byte(ip_comm, Host, Port, Opts0) ->
+ Opts = [{packet,0} | Opts0],
connect(ip_comm, Host, Port, Opts).
connect(ssl, Host, Port, Opts) ->
+ tsp("connect(ssl) -> entry with"
+ "~n Host: ~p"
+ "~n Port: ~p"
+ "~n Opts: ~p", [Host, Port, Opts]),
ssl:start(),
%% Does not support ipv6 in old ssl
case ssl:connect(Host, Port, Opts) of
@@ -319,21 +378,28 @@ connect(ssl, Host, Port, Opts) ->
Error
end;
connect(ip_comm, Host, Port, Opts) ->
+ tsp("connect(ip_comm) -> entry with"
+ "~n Host: ~p"
+ "~n Port: ~p"
+ "~n Opts: ~p", [Host, Port, Opts]),
case gen_tcp:connect(Host,Port, Opts) of
{ok, Socket} ->
- %% tsp("connect success"),
+ tsp("connect success"),
{ok, Socket};
{error, nxdomain} ->
- tsp("nxdomain opts: ~p", [Opts]),
+ tsp("connect error nxdomain when opts: ~p", [Opts]),
connect(ip_comm, Host, Port, lists:delete(inet6, Opts));
{error, eafnosupport} ->
- tsp("eafnosupport opts: ~p", [Opts]),
+ tsp("connect error eafnosupport when opts: ~p", [Opts]),
+ connect(ip_comm, Host, Port, lists:delete(inet6, Opts));
+ {error, econnreset} ->
+ tsp("connect error econnreset when opts: ~p", [Opts]),
connect(ip_comm, Host, Port, lists:delete(inet6, Opts));
{error, enetunreach} ->
- tsp("eafnosupport opts: ~p", [Opts]),
+ tsp("connect error eafnosupport when opts: ~p", [Opts]),
connect(ip_comm, Host, Port, lists:delete(inet6, Opts));
{error, {enfile,_}} ->
- tsp("Error enfile"),
+ tsp("connect error enfile when opts: ~p", [Opts]),
{error, enfile};
Error ->
tsp("Unexpected error: "
@@ -349,8 +415,6 @@ connect(ip_comm, Host, Port, Opts) ->
send(ssl, Socket, Data) ->
ssl:send(Socket, Data);
-send(ossl, Socket, Data) ->
- ssl:send(Socket, Data);
send(essl, Socket, Data) ->
ssl:send(Socket, Data);
send(ip_comm,Socket,Data) ->
@@ -359,8 +423,6 @@ send(ip_comm,Socket,Data) ->
close(ssl,Socket) ->
catch ssl:close(Socket);
-close(ossl,Socket) ->
- catch ssl:close(Socket);
close(essl,Socket) ->
catch ssl:close(Socket);
close(ip_comm,Socket) ->
@@ -395,6 +457,13 @@ sleep(MSecs) ->
skip(Reason, File, Line) ->
exit({skipped, {Reason, File, Line}}).
+fail(Reason, File, Line) ->
+ String = lists:flatten(io_lib:format("Failure ~p(~p): ~p~n",
+ [File, Line, Reason])),
+ tsf(String).
+
+
+
flush() ->
receive
Msg ->
@@ -407,7 +476,22 @@ flush() ->
tsp(F) ->
tsp(F, []).
tsp(F, A) ->
- test_server:format("~p ~p:" ++ F ++ "~n", [self(), ?MODULE | A]).
+ Timestamp = formated_timestamp(),
+ test_server:format("*** ~s ~p ~p ~w:" ++ F ++ "~n",
+ [Timestamp, node(), self(), ?MODULE | A]).
tsf(Reason) ->
test_server:fail(Reason).
+
+formated_timestamp() ->
+ format_timestamp( os:timestamp() ).
+
+format_timestamp({_N1, _N2, N3} = Now) ->
+ {Date, Time} = calendar:now_to_datetime(Now),
+ {YYYY,MM,DD} = Date,
+ {Hour,Min,Sec} = Time,
+ FormatDate =
+ io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w",
+ [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
+ lists:flatten(FormatDate).
+
diff --git a/lib/inets/test/inets_test_lib.hrl b/lib/inets/test/inets_test_lib.hrl
index 0cdb04139c..4dd81093a2 100644
--- a/lib/inets/test/inets_test_lib.hrl
+++ b/lib/inets/test/inets_test_lib.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -72,7 +72,7 @@
%% - Test case macros -
--define(SKIP(Reason), inets_test_lib:skip(Reason)).
+-define(SKIP(Reason), inets_test_lib:skip(Reason, ?MODULE, ?LINE)).
-define(FAIL(Reason), inets_test_lib:fail(Reason, ?MODULE, ?LINE)).
diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk
index b1de3fef43..1df4558e45 100644
--- a/lib/inets/vsn.mk
+++ b/lib/inets/vsn.mk
@@ -18,7 +18,7 @@
# %CopyrightEnd%
APPLICATION = inets
-INETS_VSN = 5.5.2
+INETS_VSN = 5.8
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"
diff --git a/lib/inviso/test/Makefile b/lib/inviso/test/Makefile
index cd372624b5..c1df29d631 100644
--- a/lib/inviso/test/Makefile
+++ b/lib/inviso/test/Makefile
@@ -53,7 +53,7 @@ release_spec: opt
release_tests_spec: make_emakefile
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) inviso.spec inviso.cover $(ERL_FILES) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/jinterface/doc/src/notes.xml b/lib/jinterface/doc/src/notes.xml
index 962be63968..11fcc5f387 100644
--- a/lib/jinterface/doc/src/notes.xml
+++ b/lib/jinterface/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2010</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/jinterface/java_src/Makefile b/lib/jinterface/java_src/Makefile
index 755ef46a8b..19f99831eb 100644
--- a/lib/jinterface/java_src/Makefile
+++ b/lib/jinterface/java_src/Makefile
@@ -29,9 +29,7 @@ VSN=$(JINTERFACE_VSN)
# Common Macros
# ----------------------------------------------------
-# call recursive make explicitly below
-# due to separate makefiles for Ronja & OTP
-# SUB_DIRECTORIES = com/ericsson/otp/erlang
+SUB_DIRECTORIES = com/ericsson/otp/erlang
SPECIAL_TARGETS =
@@ -51,15 +49,5 @@ POM_SRC= $(POM_FILE).src
$(POM_TARGET): $(POM_SRC) ../vsn.mk
sed -e 's;%VSN%;$(VSN);' $< > $@
-# ----------------------------------------------------
-# Default Subdir Targets
-# ----------------------------------------------------
-
-.PHONY: debug opt instr release docs release_docs tests release_tests clean depend
-
-debug opt instr release docs release_docs tests release_tests clean depend: $(TARGET_FILES)
- set -e; set -x; \
- case "$(MAKE)" in *clearmake*) tflag="-T";; *) tflag="";; esac; \
- if test -f com/ericsson/otp/erlang/ignore_config_record.inf; then xflag=$$tflag; fi; \
- (cd com/ericsson/otp/erlang && $(MAKE) -f Makefile.otp $$xflag $@)
+include $(ERL_TOP)/make/otp_subdir.mk
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile b/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile
new file mode 100644
index 0000000000..e772a2b0a5
--- /dev/null
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile
@@ -0,0 +1,113 @@
+# -*-Makefile-*-
+
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2000-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+include $(ERL_TOP)/make/target.mk
+
+JAVA_DEST_ROOT = $(ERL_TOP)/lib/jinterface/priv/
+JAVA_SRC_ROOT = $(ERL_TOP)/lib/jinterface/java_src/
+JAVA_CLASS_SUBDIR = com/ericsson/otp/erlang/
+
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include $(ERL_TOP)/lib/jinterface/vsn.mk
+VSN=$(JINTERFACE_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/jinterface-$(VSN)
+
+#
+# JAVA macros
+#
+
+# don't add filenames to the Makefile!
+# all java sourcefiles listed in common include file
+include $(ERL_TOP)/lib/jinterface/java_src/$(JAVA_CLASS_SUBDIR)/java_files
+
+TARGET_FILES= $(JAVA_FILES:%=$(JAVA_DEST_ROOT)$(JAVA_CLASS_SUBDIR)%.class)
+JAVA_SRC= $(JAVA_FILES:%=%.java)
+
+JARFILE= OtpErlang.jar
+
+
+# ----------------------------------------------------
+# Programs and Flags
+# ----------------------------------------------------
+
+JAR= jar
+
+CLASSPATH = $(JAVA_SRC_ROOT)
+
+JAVADOCFLAGS=-d $(DOCDIR)
+JAVAFLAGS=-d $(JAVA_DEST_ROOT)
+JARFLAGS=-cvf
+
+JAVA_OPTIONS =
+
+ifeq ($(TESTROOT),)
+RELEASE_PATH=$(ERL_TOP)/release/$(TARGET)
+else
+RELEASE_PATH=$(TESTROOT)
+endif
+
+
+# ----------------------------------------------------
+# Make Rules
+# ----------------------------------------------------
+
+debug opt: make_dirs $(JAVA_DEST_ROOT)$(JARFILE)
+
+make_dirs:
+ if [ ! -d "$(JAVA_DEST_ROOT)" ];then mkdir "$(JAVA_DEST_ROOT)"; fi
+
+$(JAVA_DEST_ROOT)$(JARFILE): $(TARGET_FILES)
+ @(cd $(JAVA_DEST_ROOT) ; $(JAR) $(JARFLAGS) $(JARFILE) $(JAVA_CLASS_SUBDIR))
+
+clean:
+ rm -f $(TARGET_FILES) *~
+
+docs:
+
+# ----------------------------------------------------
+# Release Targets
+# ----------------------------------------------------
+
+# include $(ERL_TOP)/make/otp_release_targets.mk
+
+release release_docs release_tests release_html:
+ $(MAKE) $(MFLAGS) RELEASE_PATH=$(RELEASE_PATH) $(TARGET_MAKEFILE) $@_spec
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/java_src/com/ericsson/otp/erlang
+ $(INSTALL_DATA) $(JAVA_SRC) $(RELSYSDIR)/java_src/com/ericsson/otp/erlang
+ $(INSTALL_DIR) $(RELSYSDIR)/priv
+ $(INSTALL_DATA) $(JAVA_DEST_ROOT)$(JARFILE) $(RELSYSDIR)/priv
+
+release_docs_spec:
+
+
+
+
+# ----------------------------------------------------
+
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile.otp b/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile.otp
deleted file mode 100644
index d0ff9cda34..0000000000
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile.otp
+++ /dev/null
@@ -1,113 +0,0 @@
-# -*-Makefile-*-
-
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2000-2009. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-include $(ERL_TOP)/make/target.mk
-
-JAVA_DEST_ROOT = $(ERL_TOP)/lib/jinterface/priv/
-JAVA_SRC_ROOT = $(ERL_TOP)/lib/jinterface/java_src/
-JAVA_CLASS_SUBDIR = com/ericsson/otp/erlang/
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include $(ERL_TOP)/lib/jinterface/vsn.mk
-VSN=$(JINTERFACE_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/jinterface-$(VSN)
-
-#
-# JAVA macros
-#
-
-# don't add filenames to the Makefile!
-# all java sourcefiles listed in common include file
-include $(ERL_TOP)/lib/jinterface/java_src/$(JAVA_CLASS_SUBDIR)/java_files
-
-TARGET_FILES= $(JAVA_FILES:%=$(JAVA_DEST_ROOT)$(JAVA_CLASS_SUBDIR)%.class)
-JAVA_SRC= $(JAVA_FILES:%=%.java)
-
-JARFILE= OtpErlang.jar
-
-
-# ----------------------------------------------------
-# Programs and Flags
-# ----------------------------------------------------
-
-JAR= jar
-
-CLASSPATH = $(JAVA_SRC_ROOT)
-
-JAVADOCFLAGS=-d $(DOCDIR)
-JAVAFLAGS=-d $(JAVA_DEST_ROOT)
-JARFLAGS=-cvf
-
-JAVA_OPTIONS =
-
-ifeq ($(TESTROOT),)
-RELEASE_PATH=$(ERL_TOP)/release/$(TARGET)
-else
-RELEASE_PATH=$(TESTROOT)
-endif
-
-
-# ----------------------------------------------------
-# Make Rules
-# ----------------------------------------------------
-
-debug opt: make_dirs $(JAVA_DEST_ROOT)$(JARFILE)
-
-make_dirs:
- if [ ! -d "$(JAVA_DEST_ROOT)" ];then mkdir "$(JAVA_DEST_ROOT)"; fi
-
-$(JAVA_DEST_ROOT)$(JARFILE): $(TARGET_FILES)
- @(cd $(JAVA_DEST_ROOT) ; $(JAR) $(JARFLAGS) $(JARFILE) $(JAVA_CLASS_SUBDIR))
-
-clean:
- rm -f $(TARGET_FILES) *~
-
-docs:
-
-# ----------------------------------------------------
-# Release Targets
-# ----------------------------------------------------
-
-# include $(ERL_TOP)/make/otp_release_targets.mk
-
-release release_docs release_tests release_html:
- $(MAKE) -f Makefile.otp $(MFLAGS) RELEASE_PATH=$(RELEASE_PATH) $(TARGET_MAKEFILE) $@_spec
-
-release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/java_src/com/ericsson/otp/erlang
- $(INSTALL_DATA) $(JAVA_SRC) $(RELSYSDIR)/java_src/com/ericsson/otp/erlang
- $(INSTALL_DIR) $(RELSYSDIR)/priv
- $(INSTALL_DATA) $(JAVA_DEST_ROOT)$(JARFILE) $(RELSYSDIR)/priv
-
-release_docs_spec:
-
-
-
-
-# ----------------------------------------------------
-
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/ignore_config_record.inf b/lib/jinterface/java_src/com/ericsson/otp/erlang/ignore_config_record.inf
deleted file mode 100644
index 0a5053eba3..0000000000
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/ignore_config_record.inf
+++ /dev/null
@@ -1 +0,0 @@
-This file makes clearmake use the -T switch for this subdirectory
diff --git a/lib/kernel/doc/specs/.gitignore b/lib/kernel/doc/specs/.gitignore
new file mode 100644
index 0000000000..322eebcb06
--- /dev/null
+++ b/lib/kernel/doc/specs/.gitignore
@@ -0,0 +1 @@
+specs_*.xml
diff --git a/lib/kernel/doc/src/Makefile b/lib/kernel/doc/src/Makefile
index f8c1cac8b3..214e994889 100644
--- a/lib/kernel/doc/src/Makefile
+++ b/lib/kernel/doc/src/Makefile
@@ -1,19 +1,20 @@
-# ``The contents of this file are subject to the Erlang Public License,
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1997-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
# compliance 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/.
-#
+# retrieved online at http://www.erlang.org/.
+#
# Software distributed under the License is distributed on an "AS IS"
# 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$
+#
+# %CopyrightEnd%
#
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
@@ -94,19 +95,26 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
+
+TOP_SPECS_FILE = specs.xml
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
XML_FLAGS +=
+SPECS_ESRC = ../../src
+
+SPECS_FLAGS = -I../../include
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-docs: pdf html man
+docs: man pdf html
$(TOP_PDF_FILE): $(XML_FILES)
@@ -125,8 +133,22 @@ clean clean_docs:
rm -f $(MAN4DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+ rm -f $(SPECDIR)/*
rm -f errs core *~
+$(SPECDIR)/specs_erl_prim_loader_stub.xml:
+ escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
+ -o$(dir $@) -module erl_prim_loader_stub
+$(SPECDIR)/specs_erlang_stub.xml:
+ escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
+ -o$(dir $@) -module erlang_stub
+$(SPECDIR)/specs_init_stub.xml:
+ escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
+ -o$(dir $@) -module init_stub
+$(SPECDIR)/specs_zlib_stub.xml:
+ escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
+ -o$(dir $@) -module zlib_stub
+
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
diff --git a/lib/kernel/doc/src/app.xml b/lib/kernel/doc/src/app.xml
index ef1f5985f4..ff8a12fe97 100644
--- a/lib/kernel/doc/src/app.xml
+++ b/lib/kernel/doc/src/app.xml
@@ -4,7 +4,7 @@
<fileref>
<header>
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -170,7 +170,6 @@ Phases [{Phase,PhaseArgs}] undefined
start phase defined by the <c>start_phases</c> key, and only
after this extended start procedure will
<c>application:start(Application)</c> return.</p>
- <p></p>
<p>Start phases may be used to synchronize startup of an
application and its included applications. In this case,
the <c>mod</c> key must be specified as:</p>
@@ -182,7 +181,6 @@ Phases [{Phase,PhaseArgs}] undefined
for the primary application) both for the primary application
and for each of its included application, for which the start
phase is defined.</p>
- <p></p>
<p>This implies that for an included application, the set of
start phases must be a subset of the set of phases defined
for the primary application. Refer to <em>OTP Design Principles</em> for more information.</p>
diff --git a/lib/kernel/doc/src/application.xml b/lib/kernel/doc/src/application.xml
index 47d578a339..51a3311ec2 100644
--- a/lib/kernel/doc/src/application.xml
+++ b/lib/kernel/doc/src/application.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2010</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -50,20 +50,27 @@
<p>Refer to <seealso marker="doc/design_principles:des_princ">OTP Design Principles</seealso> for more information about
applications and behaviours.</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="start_type"/>
+ </datatype>
+ <datatype>
+ <name name="restart_type"/>
+ </datatype>
+ <datatype>
+ <!-- Parameterized opaque types are NYI: -->
+ <name><marker id="type-tuple_of">tuple_of(T)</marker></name>
+ <desc><p>A tuple where the elements are of type <c>T</c>.</p></desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>get_all_env() -> Env</name>
- <name>get_all_env(Application) -> Env</name>
+ <name name="get_all_env" arity="0"/>
+ <name name="get_all_env" arity="1"/>
<fsummary>Get the configuration parameters for an application</fsummary>
- <type>
- <v>Application = atom()</v>
- <v>Env = [{Par,Val}]</v>
- <v>&nbsp;Par = atom()</v>
- <v>&nbsp;Val = term()</v>
- </type>
<desc>
<p>Returns the configuration parameters and their values for
- <c>Application</c>. If the argument is omitted, it defaults to
+ <c><anno>Application</anno></c>. If the argument is omitted, it defaults to
the application of the calling process.</p>
<p>If the specified application is not loaded, or if the process
executing the call does not belong to any application,
@@ -71,18 +78,12 @@
</desc>
</func>
<func>
- <name>get_all_key() -> {ok, Keys} | []</name>
- <name>get_all_key(Application) -> {ok, Keys} | undefined </name>
+ <name name="get_all_key" arity="0"/>
+ <name name="get_all_key" arity="1"/>
<fsummary>Get the application specification keys</fsummary>
- <type>
- <v>Application = atom()</v>
- <v>Keys = [{Key,Val}]</v>
- <v>&nbsp;Key = atom()</v>
- <v>&nbsp;Val = term()</v>
- </type>
<desc>
<p>Returns the application specification keys and their values
- for <c>Application</c>. If the argument is omitted, it
+ for <c><anno>Application</anno></c>. If the argument is omitted, it
defaults to the application of the calling process.</p>
<p>If the specified application is not loaded, the function
returns <c>undefined</c>. If the process executing the call
@@ -91,17 +92,12 @@
</desc>
</func>
<func>
- <name>get_application() -> {ok, Application} | undefined</name>
- <name>get_application(Pid | Module) -> {ok, Application} | undefined</name>
+ <name name="get_application" arity="0"/>
+ <name name="get_application" arity="1"/>
<fsummary>Get the name of an application containing a certain process or module</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Module = atom()</v>
- <v>Application = atom()</v>
- </type>
<desc>
<p>Returns the name of the application to which the process
- <c>Pid</c> or the module <c>Module</c> belongs. Providing no
+ <c><anno>Pid</anno></c> or the module <c><anno>Module</anno></c> belongs. Providing no
argument is the same as calling
<c>get_application(self())</c>.</p>
<p>If the specified process does not belong to any application,
@@ -110,17 +106,12 @@
</desc>
</func>
<func>
- <name>get_env(Par) -> {ok, Val} | undefined</name>
- <name>get_env(Application, Par) -> {ok, Val} | undefined</name>
+ <name name="get_env" arity="1"/>
+ <name name="get_env" arity="2"/>
<fsummary>Get the value of a configuration parameter</fsummary>
- <type>
- <v>Application = atom()</v>
- <v>Par = atom()</v>
- <v>Val = term()</v>
- </type>
<desc>
- <p>Returns the value of the configuration parameter <c>Par</c>
- for <c>Application</c>. If the application argument is
+ <p>Returns the value of the configuration parameter <c><anno>Par</anno></c>
+ for <c><anno>Application</anno></c>. If the application argument is
omitted, it defaults to the application of the calling
process.</p>
<p>If the specified application is not loaded, or
@@ -130,17 +121,12 @@
</desc>
</func>
<func>
- <name>get_key(Key) -> {ok, Val} | undefined</name>
- <name>get_key(Application, Key) -> {ok, Val} | undefined</name>
+ <name name="get_key" arity="1"/>
+ <name name="get_key" arity="2"/>
<fsummary>Get the value of an application specification key</fsummary>
- <type>
- <v>Application = atom()</v>
- <v>Key = atom()</v>
- <v>Val = term()</v>
- </type>
<desc>
<p>Returns the value of the application specification key
- <c>Key</c> for <c>Application</c>. If the application
+ <c><anno>Key</anno></c> for <c><anno>Application</anno></c>. If the application
argument is omitted, it defaults to the application of
the calling process.</p>
<p>If the specified application is not loaded, or
@@ -150,45 +136,35 @@
</desc>
</func>
<func>
- <name>load(AppDescr) -> ok | {error, Reason}</name>
- <name>load(AppDescr, Distributed) -> ok | {error, Reason}</name>
+ <name name="load" arity="1"/>
+ <name name="load" arity="2"/>
<fsummary>Load an application</fsummary>
- <type>
- <v>AppDescr = Application | AppSpec</v>
- <v>&nbsp;Application = atom()</v>
- <v>&nbsp;AppSpec = {application,Application,AppSpecKeys}</v>
- <v>&nbsp;&nbsp;AppSpec = [{Key,Val}]</v>
- <v>&nbsp;&nbsp;&nbsp;Key = atom()</v>
- <v>&nbsp;&nbsp;&nbsp;Val = term()</v>
- <v>Distributed = {Application,Nodes} | {Application,Time,Nodes} | default</v>
- <v>&nbsp;Nodes = [node() | {node(),..,node()}]</v>
- <v>&nbsp;Time = integer() > 0</v>
- <v>Reason = term()</v>
- </type>
+ <type name="application_spec"/>
+ <type name="application_opt"/>
<desc>
<p>Loads the application specification for an application into
the application controller. It will also load the application
specifications for any included applications. Note that
the function does not load the actual Erlang object code.</p>
- <p>The application can be given by its name <c>Application</c>.
+ <p>The application can be given by its name <c><anno>Application</anno></c>.
In this case the application controller will search the code
- path for the application resource file <c>Application.app</c>
+ path for the application resource file <c><anno>Application</anno>.app</c>
and load the specification it contains.</p>
<p>The application specification can also be given directly as a
- tuple <c>AppSpec</c>. This tuple should have the format and
+ tuple <c><anno>AppSpec</anno></c>. This tuple should have the format and
contents as described in <c>app(4)</c>.</p>
- <p>If <c>Distributed == {Application,[Time,]Nodes}</c>,
+ <p>If <c><anno>Distributed</anno> == {<anno>Application</anno>,[<anno>Time</anno>,]<anno>Nodes</anno>}</c>,
the application will be distributed. The argument overrides
the value for the application in the Kernel configuration
- parameter <c>distributed</c>. <c>Application</c> must be
+ parameter <c>distributed</c>. <c><anno>Application</anno></c> must be
the name of the application (same as in the first argument).
- If a node crashes and <c>Time</c> has been specified, then
- the application controller will wait for <c>Time</c>
+ If a node crashes and <c><anno>Time</anno></c> has been specified, then
+ the application controller will wait for <c><anno>Time</anno></c>
milliseconds before attempting to restart the application on
- another node. If <c>Time</c> is not specified, it will
+ another node. If <c><anno>Time</anno></c> is not specified, it will
default to 0 and the application will be restarted
immediately.</p>
- <p><c>Nodes</c> is a list of node names where the application
+ <p><c><anno>Nodes</anno></c> is a list of node names where the application
may run, in priority from left to right. Node names can be
grouped using tuples to indicate that they have the same
priority. Example:</p>
@@ -204,32 +180,22 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name>loaded_applications() -> [{Application, Description, Vsn}]</name>
+ <name name="loaded_applications" arity="0"/>
<fsummary>Get the currently loaded applications</fsummary>
- <type>
- <v>Application = atom()</v>
- <v>Description = string()</v>
- <v>Vsn = string()</v>
- </type>
<desc>
<p>Returns a list with information about the applications which
have been loaded using <c>load/1,2</c>, also included
- applications. <c>Application</c> is the application name.
- <c>Description</c> and <c>Vsn</c> are the values of its
+ applications. <c><anno>Application</anno></c> is the application name.
+ <c><anno>Description</anno></c> and <c><anno>Vsn</anno></c> are the values of its
<c>description</c> and <c>vsn</c> application specification
keys, respectively.</p>
</desc>
</func>
<func>
- <name>permit(Application, Bool) -> ok | {error, Reason}</name>
+ <name name="permit" arity="2"/>
<fsummary>Change an application's permission to run on a node.</fsummary>
- <type>
- <v>Application = atom()</v>
- <v>Bool = bool()</v>
- <v>Reason = term()</v>
- </type>
<desc>
- <p>Changes the permission for <c>Application</c> to run at
+ <p>Changes the permission for <c><anno>Application</anno></c> to run at
the current node. The application must have been loaded using
<c>load/1,2</c> for the function to have effect.</p>
<p>If the permission of a loaded, but not started, application
@@ -258,20 +224,14 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name>set_env(Application, Par, Val) -> ok</name>
- <name>set_env(Application, Par, Val, Timeout) -> ok</name>
+ <name name="set_env" arity="3"/>
+ <name name="set_env" arity="4"/>
<fsummary>Set the value of a configuration parameter</fsummary>
- <type>
- <v>Application = atom()</v>
- <v>Par = atom()</v>
- <v>Val = term()</v>
- <v>Timeout = int() | infinity</v>
- </type>
<desc>
- <p>Sets the value of the configuration parameter <c>Par</c> for
- <c>Application</c>.</p>
+ <p>Sets the value of the configuration parameter <c><anno>Par</anno></c> for
+ <c><anno>Application</anno></c>.</p>
<p><c>set_env/3</c> uses the standard <c>gen_server</c> timeout
- value (5000 ms). A <c>Timeout</c> argument can be provided
+ value (5000 ms). A <c><anno>Timeout</anno></c> argument can be provided
if another timeout value is useful, for example, in situations
where the application controller is heavily loaded.</p>
<warning>
@@ -285,20 +245,15 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name>start(Application) -> ok | {error, Reason}</name>
- <name>start(Application, Type) -> ok | {error, Reason}</name>
+ <name name="start" arity="1"/>
+ <name name="start" arity="2"/>
<fsummary>Load and start an application</fsummary>
- <type>
- <v>Application = atom()</v>
- <v>Type = permanent | transient | temporary</v>
- <v>Reason = term()</v>
- </type>
<desc>
- <p>Starts <c>Application</c>. If it is not loaded,
+ <p>Starts <c><anno>Application</anno></c>. If it is not loaded,
the application controller will first load it using
<c>load/1</c>. It will make sure any included applications
are loaded, but will not start them. That is assumed to be
- taken care of in the code for <c>Application</c>.</p>
+ taken care of in the code for <c><anno>Application</anno></c>.</p>
<p>The application controller checks the value of
the application specification key <c>applications</c>, to
ensure that all applications that should be started before
@@ -310,7 +265,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
The application master starts the application by calling
the application callback function <c>Module:start/2</c> as
defined by the application specification key <c>mod</c>.</p>
- <p>The <c>Type</c> argument specifies the type of
+ <p>The <c><anno>Type</anno></c> argument specifies the type of
the application. If omitted, it defaults to <c>temporary</c>.</p>
<list type="bulleted">
<item>If a permanent application terminates, all other
@@ -331,19 +286,15 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name>start_type() -> StartType | local | undefined</name>
+ <name name="start_type" arity="0"/>
<fsummary>Get the start type of an ongoing application startup.</fsummary>
- <type>
- <v>StartType = normal | {takeover,Node} | {failover,Node}</v>
- <v>&nbsp;Node = node()</v>
- </type>
<desc>
<p>This function is intended to be called by a process belonging
to an application, when the application is being started, to
- determine the start type which is either <c>StartType</c> or
+ determine the start type which is either <c><anno>StartType</anno></c> or
<c>local</c>.</p>
- <p>See <c>Module:start/2</c> for a description of
- <c>StartType</c>.</p>
+ <p>See <seealso marker="#start_type"><c>Module:start/2</c></seealso> for a description of
+ <c><anno>StartType</anno></c>.</p>
<p><c>local</c> is returned if only parts of the application is
being restarted (by a supervisor), or if the function is
called outside a startup.</p>
@@ -352,14 +303,10 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name>stop(Application) -> ok | {error, Reason}</name>
+ <name name="stop" arity="1"/>
<fsummary>Stop an application</fsummary>
- <type>
- <v>Application = atom()</v>
- <v>Reason = term()</v>
- </type>
<desc>
- <p>Stops <c>Application</c>. The application master calls
+ <p>Stops <c><anno>Application</anno></c>. The application master calls
<c>Module:prep_stop/1</c>, if such a function is defined, and
then tells the top supervisor of the application to shutdown
(see <c>supervisor(3)</c>). This means that the entire
@@ -384,16 +331,11 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name>takeover(Application, Type) -> ok | {error, Reason}</name>
+ <name name="takeover" arity="2"/>
<fsummary>Take over a distributed application</fsummary>
- <type>
- <v>Application = atom()</v>
- <v>Type = permanent | transient | temporary</v>
- <v>Reason = term()</v>
- </type>
<desc>
<p>Performs a takeover of the distributed application
- <c>Application</c>, which executes at another node
+ <c><anno>Application</anno></c>, which executes at another node
<c>Node</c>. At the current node, the application is
restarted by calling
<c>Module:start({takeover,Node},StartArgs)</c>. <c>Module</c>
@@ -413,14 +355,10 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name>unload(Application) -> ok | {error, Reason}</name>
+ <name name="unload" arity="1"/>
<fsummary>Unload an application</fsummary>
- <type>
- <v>Application = atom()</v>
- <v>Reason = term()</v>
- </type>
<desc>
- <p>Unloads the application specification for <c>Application</c>
+ <p>Unloads the application specification for <c><anno>Application</anno></c>
from the application controller. It will also unload
the application specifications for any included applications.
Note that the function does not purge the actual Erlang
@@ -428,19 +366,14 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name>unset_env(Application, Par) -> ok</name>
- <name>unset_env(Application, Par, Timeout) -> ok</name>
+ <name name="unset_env" arity="2"/>
+ <name name="unset_env" arity="3"/>
<fsummary>Unset the value of a configuration parameter</fsummary>
- <type>
- <v>Application = atom()</v>
- <v>Par = atom()</v>
- <v>Timeout = int() | infinity</v>
- </type>
<desc>
- <p>Removes the configuration parameter <c>Par</c> and its value
- for <c>Application</c>.</p>
+ <p>Removes the configuration parameter <c><anno>Par</anno></c> and its value
+ for <c><anno>Application</anno></c>.</p>
<p><c>unset_env/2</c> uses the standard <c>gen_server</c>
- timeout value (5000 ms). A <c>Timeout</c> argument can be
+ timeout value (5000 ms). A <c><anno>Timeout</anno></c> argument can be
provided if another timeout value is useful, for example, in
situations where the application controller is heavily loaded.</p>
<warning>
@@ -454,23 +387,17 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
</desc>
</func>
<func>
- <name>which_applications() -> [{Application, Description, Vsn}]</name>
- <name>which_applications(Timeout) -> [{Application, Description, Vsn}]</name>
+ <name name="which_applications" arity="0"/>
+ <name name="which_applications" arity="1"/>
<fsummary>Get the currently running applications</fsummary>
- <type>
- <v>Application = atom()</v>
- <v>Description = string()</v>
- <v>Vsn = string()</v>
- <v>Timeout = int() | infinity</v>
- </type>
<desc>
<p>Returns a list with information about the applications which
- are currently running. <c>Application</c> is the application
- name. <c>Description</c> and <c>Vsn</c> are the values of its
+ are currently running. <c><anno>Application</anno></c> is the application
+ name. <c><anno>Description</anno></c> and <c><anno>Vsn</anno></c> are the values of its
<c>description</c> and <c>vsn</c> application specification
keys, respectively.</p>
<p><c>which_applications/0</c> uses the standard
- <c>gen_server</c> timeout value (5000 ms). A <c>Timeout</c>
+ <c>gen_server</c> timeout value (5000 ms). A <c><anno>Timeout</anno></c>
argument can be provided if another timeout value is useful,
for example, in situations where the application controller
is heavily loaded.</p>
@@ -501,7 +428,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
structured according to the OTP design principles as a
supervision tree, this means starting the top supervisor of
the tree.</p>
- <p><c>StartType</c> defines the type of start:</p>
+ <p><marker id="start_type"/><c>StartType</c> defines the type of start:</p>
<list type="bulleted">
<item><c>normal</c> if it's a normal startup.</item>
<item><c>normal</c> also if the application is distributed and
@@ -532,8 +459,7 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
<fsummary>Extended start of an application</fsummary>
<type>
<v>Phase = atom()</v>
- <v>StartType = normal | {takeover,Node} | {failover,Node}</v>
- <v>&nbsp;Node = node()</v>
+ <v>StartType = <seealso marker="#type-start_type">start_type()</seealso></v>
<v>PhaseArgs = term()</v>
<v>Pid = pid()</v>
<v>State = state()</v>
diff --git a/lib/kernel/doc/src/auth.xml b/lib/kernel/doc/src/auth.xml
index f53fc8b29a..15d9ef0fe4 100644
--- a/lib/kernel/doc/src/auth.xml
+++ b/lib/kernel/doc/src/auth.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,29 +34,28 @@
Cookie system, refer to
<seealso marker="doc/reference_manual:distributed">Distributed Erlang</seealso> in the Erlang Reference Manual.</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="cookie"/>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>is_auth(Node) -> yes | no</name>
+ <name name="is_auth" arity="1"/>
<fsummary>Status of communication authorization (deprecated)</fsummary>
- <type>
- <v>Node = node()</v>
- </type>
<desc>
- <p>Returns <c>yes</c> if communication with <c>Node</c> is
- authorized. Note that a connection to <c>Node</c> will
- be established in this case. Returns <c>no</c> if <c>Node</c>
+ <p>Returns <c>yes</c> if communication with <c><anno>Node</anno></c> is
+ authorized. Note that a connection to <c><anno>Node</anno></c> will
+ be established in this case. Returns <c>no</c> if <c><anno>Node</anno></c>
does not exist or communication is not authorized (it has
another cookie than <c>auth</c> thinks it has).</p>
- <p>Use <seealso marker="net_adm#ping/1">net_adm:ping(Node)</seealso>
+ <p>Use <seealso marker="net_adm#ping/1">net_adm:ping(<anno>Node</anno>)</seealso>
instead.</p>
</desc>
</func>
<func>
- <name>cookie() -> Cookie</name>
+ <name name="cookie" arity="0"/>
<fsummary>Magic cookie for local node (deprecated)</fsummary>
- <type>
- <v>Cookie = atom()</v>
- </type>
<desc>
<p>Use
<seealso marker="erts:erlang#erlang:get_cookie/0">erlang:get_cookie()</seealso>
@@ -64,16 +63,14 @@
</desc>
</func>
<func>
- <name>cookie(TheCookie) -> true</name>
+ <name name="cookie" arity="1"/>
<fsummary>Set the magic for the local node (deprecated)</fsummary>
- <type>
- <v>TheCookie = Cookie | [Cookie]</v>
- <d>The cookie may also be given as a list with a single atom element</d>
- <v>&nbsp;Cookie = atom()</v>
- </type>
+ <type_desc variable="TheCookie">
+ The cookie may also be given as a list with a single atom element.
+ </type_desc>
<desc>
<p>Use
- <seealso marker="erts:erlang#erlang:set_cookie/2">erlang:set_cookie(node(), Cookie)</seealso>
+ <seealso marker="erts:erlang#erlang:set_cookie/2">erlang:set_cookie(node(), <anno>Cookie</anno>)</seealso>
instead.</p>
</desc>
</func>
@@ -82,7 +79,7 @@
<fsummary>Set the magic cookie for a node and verify authorization (deprecated)</fsummary>
<type>
<v>Node = node()</v>
- <v>Cookie = atom()</v>
+ <v>Cookie = <seealso marker="#type-cookie">cookie()</seealso></v>
</type>
<desc>
<p>Equivalent to
@@ -90,18 +87,14 @@
</desc>
</func>
<func>
- <name>node_cookie(Node, Cookie) -> yes | no</name>
+ <name name="node_cookie" arity="2"/>
<fsummary>Set the magic cookie for a node and verify authorization (deprecated)</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Cookie = atom()</v>
- </type>
<desc>
- <p>Sets the magic cookie of <c>Node</c> to <c>Cookie</c>, and
+ <p>Sets the magic cookie of <c><anno>Node</anno></c> to <c><anno>Cookie</anno></c>, and
verifies the status of the authorization.
Equivalent to calling
- <seealso marker="erts:erlang#erlang:set_cookie/2">erlang:set_cookie(Node, Cookie)</seealso>, followed by
- <seealso marker="#is_auth/1">auth:is_auth(Node)</seealso>.</p>
+ <seealso marker="erts:erlang#erlang:set_cookie/2">erlang:set_cookie(<anno>Node</anno>, <anno>Cookie</anno>)</seealso>, followed by
+ <seealso marker="#is_auth/1">auth:is_auth(<anno>Node</anno>)</seealso>.</p>
</desc>
</func>
</funcs>
diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml
index 4b8f934df1..6b89711924 100644
--- a/lib/kernel/doc/src/code.xml
+++ b/lib/kernel/doc/src/code.xml
@@ -177,9 +177,9 @@
archives. But the functions in <c>erl_prim_loader</c> may also be
used by other applications to read files from archives. For
example, the call
- <c>erl_prim_loader:list_dir("/otp/root/lib/mnesia-4.4.7.ez/mnesia-4.4.7/examples/bench)"</c>
+ <c>erl_prim_loader:list_dir( "/otp/root/lib/mnesia-4.4.7.ez/mnesia-4.4.7/examples/bench)"</c>
would list the contents of a directory inside an archive.
- See <seealso marker="erts:erl_prim_loader">erl_prim_loader(3)</seealso></p>
+ See <seealso marker="erts:erl_prim_loader">erl_prim_loader(3)</seealso></p>.
<p>An application archive file and a regular application directory
may coexist. This may be useful when there is a need of having
@@ -286,192 +286,158 @@
given to <c>set_path/1</c>.</p>
</section>
+ <datatypes>
+ <datatype>
+ <name name="load_ret"/>
+ </datatype>
+ <datatype>
+ <name name="load_error_rsn"/>
+ </datatype>
+ </datatypes>
+
<funcs>
<func>
- <name>set_path(Path) -> true | {error, What}</name>
+ <name name="set_path" arity="1"/>
<fsummary>Set the code server search path</fsummary>
- <type>
- <v>Path = [Dir]</v>
- <v>Dir = string()</v>
- <v>What = bad_directory | bad_path</v>
- </type>
<desc>
- <p>Sets the code path to the list of directories <c>Path</c>.</p>
+ <p>Sets the code path to the list of directories <c><anno>Path</anno></c>.</p>
<p>Returns <c>true</c> if successful, or
- <c>{error, bad_directory}</c> if any <c>Dir</c> is not
+ <c>{error, bad_directory}</c> if any <c><anno>Dir</anno></c> is not
the name of a directory, or <c>{error, bad_path}</c> if
the argument is invalid.</p>
</desc>
</func>
<func>
- <name>get_path() -> Path</name>
+ <name name="get_path" arity="0"/>
<fsummary>Return the code server search path</fsummary>
- <type>
- <v>Path = [Dir]</v>
- <v>Dir = string()</v>
- </type>
<desc>
<p>Returns the code path</p>
</desc>
</func>
<func>
- <name>add_path(Dir) -> true | {error, What}</name>
- <name>add_pathz(Dir) -> true | {error, What}</name>
+ <name name="add_path" arity="1"/>
+ <name name="add_pathz" arity="1"/>
<fsummary>Add a directory to the end of the code path</fsummary>
- <type>
- <v>Dir = string()</v>
- <v>What = bad_directory</v>
- </type>
+ <type name="add_path_ret"/>
<desc>
- <p>Adds <c>Dir</c> to the code path. The directory is added as
- the last directory in the new path. If <c>Dir</c> already
+ <p>Adds <c><anno>Dir</anno></c> to the code path. The directory is added as
+ the last directory in the new path. If <c><anno>Dir</anno></c> already
exists in the path, it is not added.</p>
<p>Returns <c>true</c> if successful, or
- <c>{error, bad_directory}</c> if <c>Dir</c> is not the name
+ <c>{error, bad_directory}</c> if <c><anno>Dir</anno></c> is not the name
of a directory.</p>
</desc>
</func>
<func>
- <name>add_patha(Dir) -> true | {error, What}</name>
+ <name name="add_patha" arity="1"/>
<fsummary>Add a directory to the beginning of the code path</fsummary>
- <type>
- <v>Dir = string()</v>
- <v>What = bad_directory</v>
- </type>
+ <type name="add_path_ret"/>
<desc>
- <p>Adds <c>Dir</c> to the beginning of the code path. If
- <c>Dir</c> already exists, it is removed from the old
+ <p>Adds <c><anno>Dir</anno></c> to the beginning of the code path. If
+ <c><anno>Dir</anno></c> already exists, it is removed from the old
position in the code path.</p>
<p>Returns <c>true</c> if successful, or
- <c>{error, bad_directory}</c> if <c>Dir</c> is not the name
+ <c>{error, bad_directory}</c> if <c><anno>Dir</anno></c> is not the name
of a directory.</p>
</desc>
</func>
<func>
- <name>add_paths(Dirs) -> ok</name>
- <name>add_pathsz(Dirs) -> ok</name>
+ <name name="add_paths" arity="1"/>
+ <name name="add_pathsz" arity="1"/>
<fsummary>Add directories to the end of the code path</fsummary>
- <type>
- <v>Dirs = [Dir]</v>
- <v>Dir = string()</v>
- </type>
<desc>
- <p>Adds the directories in <c>Dirs</c> to the end of the code
- path. If a <c>Dir</c> already exists, it is not added. This
+ <p>Adds the directories in <c><anno>Dirs</anno></c> to the end of the code
+ path. If a <c><anno>Dir</anno></c> already exists, it is not added. This
function always returns <c>ok</c>, regardless of the validity
- of each individual <c>Dir</c>.</p>
+ of each individual <c><anno>Dir</anno></c>.</p>
</desc>
</func>
<func>
- <name>add_pathsa(Dirs) -> ok</name>
+ <name name="add_pathsa" arity="1"/>
<fsummary>Add directories to the beginning of the code path</fsummary>
- <type>
- <v>Dirs = [Dir]</v>
- <v>Dir = string()</v>
- </type>
<desc>
- <p>Adds the directories in <c>Dirs</c> to the beginning of
- the code path. If a <c>Dir</c> already exists, it is removed
+ <p>Adds the directories in <c><anno>Dirs</anno></c> to the beginning of
+ the code path. If a <c><anno>Dir</anno></c> already exists, it is removed
from the old position in the code path. This function always
returns <c>ok</c>, regardless of the validity of each
- individual <c>Dir</c>.</p>
+ individual <c><anno>Dir</anno></c>.</p>
</desc>
</func>
<func>
- <name>del_path(Name | Dir) -> true | false | {error, What}</name>
+ <name name="del_path" arity="1"/>
<fsummary>Delete a directory from the code path</fsummary>
- <type>
- <v>Name = atom()</v>
- <v>Dir = string()</v>
- <v>What = bad_name</v>
- </type>
<desc>
<p>Deletes a directory from the code path. The argument can be
- an atom <c>Name</c>, in which case the directory with
- the name <c>.../Name[-Vsn][/ebin]</c> is deleted from the code
+ an atom <c><anno>Name</anno></c>, in which case the directory with
+ the name <c>.../<anno>Name</anno>[-Vsn][/ebin]</c> is deleted from the code
path. It is also possible to give the complete directory name
- <c>Dir</c> as argument.</p>
+ <c><anno>Dir</anno></c> as argument.</p>
<p>Returns <c>true</c> if successful, or <c>false</c> if
the directory is not found, or <c>{error, bad_name}</c> if
the argument is invalid.</p>
</desc>
</func>
<func>
- <name>replace_path(Name, Dir) -> true | {error, What}</name>
+ <name name="replace_path" arity="2"/>
<fsummary>Replace a directory with another in the code path</fsummary>
- <type>
- <v>Name = atom()</v>
- <v>Dir = string()</v>
- <v>What = bad_name | bad_directory | {badarg, term()}</v>
- </type>
<desc>
<p>This function replaces an old occurrence of a directory
- named <c>.../Name[-Vsn][/ebin]</c>, in the code path, with
- <c>Dir</c>. If <c>Name</c> does not exist, it adds the new
- directory <c>Dir</c> last in the code path. The new directory
- must also be named <c>.../Name[-Vsn][/ebin]</c>. This function
+ named <c>.../<anno>Name</anno>[-Vsn][/ebin]</c>, in the code path, with
+ <c><anno>Dir</anno></c>. If <c><anno>Name</anno></c> does not exist, it adds the new
+ directory <c><anno>Dir</anno></c> last in the code path. The new directory
+ must also be named <c>.../<anno>Name</anno>[-Vsn][/ebin]</c>. This function
should be used if a new version of the directory (library) is
added to a running system.</p>
<p>Returns <c>true</c> if successful, or
- <c>{error, bad_name}</c> if <c>Name</c> is not found, or
- <c>{error, bad_directory}</c> if <c>Dir</c> does not exist, or
- <c>{error, {badarg, [Name, Dir]}}</c> if <c>Name</c> or
- <c>Dir</c> is invalid.</p>
+ <c>{error, bad_name}</c> if <c><anno>Name</anno></c> is not found, or
+ <c>{error, bad_directory}</c> if <c><anno>Dir</anno></c> does not exist, or
+ <c>{error, {badarg, [<anno>Name</anno>, <anno>Dir</anno>]}}</c> if <c><anno>Name</anno></c> or
+ <c><anno>Dir</anno></c> is invalid.</p>
</desc>
</func>
<func>
- <name>load_file(Module) -> {module, Module} | {error, What}</name>
+ <name name="load_file" arity="1"/>
<fsummary>Load a module</fsummary>
- <type>
- <v>Module = atom()</v>
- <v>What = nofile | sticky_directory | badarg | term()</v>
- </type>
+ <type name="load_ret"/>
<desc>
- <p>Tries to load the Erlang module <c>Module</c>, using
+ <p>Tries to load the Erlang module <c><anno>Module</anno></c>, using
the code path. It looks for the object code file with an
extension that corresponds to the Erlang machine used, for
- example <c>Module.beam</c>. The loading fails if the module
+ example <c><anno>Module</anno>.beam</c>. The loading fails if the module
name found in the object code differs from the name
- <c>Module</c>.
+ <c><anno>Module</anno></c>.
<seealso marker="#load_binary/3">load_binary/3</seealso> must
be used to load object code with a module name that is
different from the file name.</p>
- <p>Returns <c>{module, Module}</c> if successful, or
+ <p>Returns <c>{module, <anno>Module</anno>}</c> if successful, or
<c>{error, nofile}</c> if no object code is found, or
<c>{error, sticky_directory}</c> if the object code resides in
- a sticky directory, or <c>{error, badarg}</c> if the argument
- is invalid. Also if the loading fails, an error tuple is
+ a sticky directory. Also if the loading fails, an error tuple is
returned. See
<seealso marker="erts:erlang#load_module/2">erlang:load_module/2</seealso>
- for possible values of <c>What</c>.</p>
+ for possible values of <c><anno>What</anno></c>.</p>
</desc>
</func>
<func>
- <name>load_abs(Filename) -> {module, Module} | {error, What}</name>
+ <name name="load_abs" arity="1"/>
<fsummary>Load a module, residing in a given file</fsummary>
- <type>
- <v>Filename = string()</v>
- <v>Module = atom()</v>
- <v>What = nofile | sticky_directory | badarg | term()</v>
- </type>
+ <type name="load_ret"/>
+ <type name="loaded_filename"/>
+ <type name="loaded_ret_atoms"/>
<desc>
- <p>Does the same as <c>load_file(Module)</c>, but
- <c>Filename</c> is either an absolute file name, or a
+ <p>Does the same as <c>load_file(<anno>Module</anno>)</c>, but
+ <c><anno>Filename</anno></c> is either an absolute file name, or a
relative file name. The code path is not searched. It returns
a value in the same way as
<seealso marker="#load_file/1">load_file/1</seealso>. Note
- that <c>Filename</c> should not contain the extension (for
+ that <c><anno>Filename</anno></c> should not contain the extension (for
example <c>".beam"</c>); <c>load_abs/1</c> adds the correct
extension itself.</p>
</desc>
</func>
<func>
- <name>ensure_loaded(Module) -> {module, Module} | {error, What}</name>
+ <name name="ensure_loaded" arity="1"/>
<fsummary>Ensure that a module is loaded</fsummary>
- <type>
- <v>Module = atom()</v>
- <v>What = nofile | sticky_directory | embedded | badarg | term()</v>
- </type>
<desc>
<p>Tries to to load a module in the same way as
<seealso marker="#load_file/1">load_file/1</seealso>,
@@ -481,54 +447,45 @@
</desc>
</func>
<func>
- <name>load_binary(Module, Filename, Binary) -> {module, Module} | {error, What}</name>
+ <name name="load_binary" arity="3"/>
<fsummary>Load object code for a module</fsummary>
- <type>
- <v>Module = atom()</v>
- <v>Filename = string()</v>
- <v>What = sticky_directory | badarg | term()</v>
- </type>
+ <type name="loaded_filename"/>
+ <type name="loaded_ret_atoms"/>
<desc>
<p>This function can be used to load object code on remote
- Erlang nodes. The argument <c>Binary</c> must contain
- object code for <c>Module</c>.
- <c>Filename</c> is only used by the code server to keep a
- record of from which file the object code for <c>Module</c>
- comes. Accordingly, <c>Filename</c> is not opened and read by
+ Erlang nodes. The argument <c><anno>Binary</anno></c> must contain
+ object code for <c><anno>Module</anno></c>.
+ <c><anno>Filename</anno></c> is only used by the code server to keep a
+ record of from which file the object code for <c><anno>Module</anno></c>
+ comes. Accordingly, <c><anno>Filename</anno></c> is not opened and read by
the code server.</p>
- <p>Returns <c>{module, Module}</c> if successful, or
+ <p>Returns <c>{module, <anno>Module</anno>}</c> if successful, or
<c>{error, sticky_directory}</c> if the object code resides in
a sticky directory, or <c>{error, badarg}</c> if any argument
is invalid. Also if the loading fails, an error tuple is
returned. See
<seealso marker="erts:erlang#load_module/2">erlang:load_module/2</seealso>
- for possible values of <c>What</c>.</p>
+ for possible values of <c><anno>What</anno></c>.</p>
</desc>
</func>
<func>
- <name>delete(Module) -> true | false</name>
+ <name name="delete" arity="1"/>
<fsummary>Removes current code for a module</fsummary>
- <type>
- <v>Module = atom()</v>
- </type>
<desc>
- <p>Removes the current code for <c>Module</c>, that is,
- the current code for <c>Module</c> is made old. This means
+ <p>Removes the current code for <c><anno>Module</anno></c>, that is,
+ the current code for <c><anno>Module</anno></c> is made old. This means
that processes can continue to execute the code in the module,
but that no external function calls can be made to it.</p>
<p>Returns <c>true</c> if successful, or <c>false</c> if there
- is old code for <c>Module</c> which must be purged first, or
- if <c>Module</c> is not a (loaded) module.</p>
+ is old code for <c><anno>Module</anno></c> which must be purged first, or
+ if <c><anno>Module</anno></c> is not a (loaded) module.</p>
</desc>
</func>
<func>
- <name>purge(Module) -> true | false</name>
+ <name name="purge" arity="1"/>
<fsummary>Removes old code for a module</fsummary>
- <type>
- <v>Module = atom()</v>
- </type>
<desc>
- <p>Purges the code for <c>Module</c>, that is, removes code
+ <p>Purges the code for <c><anno>Module</anno></c>, that is, removes code
marked as old. If some processes still linger in the old code,
these processes are killed before the code is removed.</p>
<p>Returns <c>true</c> if successful and any process needed to
@@ -536,31 +493,26 @@
</desc>
</func>
<func>
- <name>soft_purge(Module) -> true | false</name>
+ <name name="soft_purge" arity="1"/>
<fsummary>Removes old code for a module, unless no process uses it</fsummary>
- <type>
- <v>Module = atom()</v>
- </type>
<desc>
- <p>Purges the code for <c>Module</c>, that is, removes code
+ <p>Purges the code for <c><anno>Module</anno></c>, that is, removes code
marked as old, but only if no processes linger in it.</p>
<p>Returns <c>false</c> if the module could not be purged due
to processes lingering in old code, otherwise <c>true</c>.</p>
</desc>
</func>
<func>
- <name>is_loaded(Module) -> {file, Loaded} | false</name>
+ <name name="is_loaded" arity="1"/>
<fsummary>Check if a module is loaded</fsummary>
- <type>
- <v>Module = atom()</v>
- <v>Loaded = Absname | preloaded | cover_compiled</v>
- <v>Absname = string()</v>
- </type>
- <desc>
- <p>Checks if <c>Module</c> is loaded. If it is,
- <c>{file, Loaded}</c> is returned, otherwise <c>false</c>.</p>
- <p>Normally, <c>Loaded</c> is the absolute file name
- <c>Absname</c> from which the code was obtained. If the module
+ <type name="loaded_filename"/>
+ <type name="loaded_ret_atoms"/>
+ <type_desc name="loaded_filename"><c><anno>Filename</anno></c> is an absolute filename</type_desc>
+ <desc>
+ <p>Checks if <c><anno>Module</anno></c> is loaded. If it is,
+ <c>{file, <anno>Loaded</anno>}</c> is returned, otherwise <c>false</c>.</p>
+ <p>Normally, <c><anno>Loaded</anno></c> is the absolute file name
+ <c>Filename</c> from which the code was obtained. If the module
is preloaded (see
<seealso marker="sasl:script">script(4)</seealso>),
<c>Loaded==preloaded</c>. If the module is Cover compiled (see
@@ -569,32 +521,26 @@
</desc>
</func>
<func>
- <name>all_loaded() -> [{Module, Loaded}]</name>
+ <name name="all_loaded" arity="0"/>
<fsummary>Get all loaded modules</fsummary>
- <type>
- <v>Module = atom()</v>
- <v>Loaded = Absname | preloaded | cover_compiled</v>
- <v>Absname = string()</v>
- </type>
+ <type name="loaded_filename"/>
+ <type name="loaded_ret_atoms"/>
+ <type_desc name="loaded_filename"><c><anno>Filename</anno></c> is an absolute filename</type_desc>
<desc>
- <p>Returns a list of tuples <c>{Module, Loaded}</c> for all
- loaded modules. <c>Loaded</c> is normally the absolute file
+ <p>Returns a list of tuples <c>{<anno>Module</anno>, <anno>Loaded</anno>}</c> for all
+ loaded modules. <c><anno>Loaded</anno></c> is normally the absolute file
name, as described for
<seealso marker="#is_loaded/1">is_loaded/1</seealso>.</p>
</desc>
</func>
<func>
- <name>which(Module) -> Which</name>
+ <name name="which" arity="1"/>
<fsummary>The object code file of a module</fsummary>
- <type>
- <v>Module = atom()</v>
- <v>Which = Filename | non_existing | preloaded | cover_compiled</v>
- <v>Filename = string()</v>
- </type>
+ <type name="loaded_ret_atoms"/>
<desc>
<p>If the module is not loaded, this function searches the code
path for the first file which contains object code for
- <c>Module</c> and returns the absolute file name. If
+ <c><anno>Module</anno></c> and returns the absolute file name. If
the module is loaded, it returns the name of the file which
contained the loaded object code. If the module is pre-loaded,
<c>preloaded</c> is returned. If the module is Cover compiled,
@@ -603,21 +549,16 @@
</desc>
</func>
<func>
- <name>get_object_code(Module) -> {Module, Binary, Filename} | error</name>
+ <name name="get_object_code" arity="1"/>
<fsummary>Get the object code for a module</fsummary>
- <type>
- <v>Module = atom()</v>
- <v>Binary = binary()</v>
- <v>Filename = string()</v>
- </type>
<desc>
<p>Searches the code path for the object code of the module
- <c>Module</c>. It returns <c>{Module, Binary, Filename}</c>
- if successful, and <c>error</c> if not. <c>Binary</c> is a
+ <c><anno>Module</anno></c>. It returns <c>{<anno>Module</anno>, <anno>Binary</anno>, <anno>Filename</anno>}</c>
+ if successful, and <c>error</c> if not. <c><anno>Binary</anno></c> is a
binary data object which contains the object code for
the module. This can be useful if code is to be loaded on a
remote node in a distributed system. For example, loading
- module <c>Module</c> on a node <c>Node</c> is done as
+ module <c><anno>Module</anno></c> on a node <c>Node</c> is done as
follows:</p>
<code type="none">
...
@@ -627,7 +568,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name>root_dir() -> string()</name>
+ <name name="root_dir" arity="0"/>
<fsummary>Root directory of Erlang/OTP</fsummary>
<desc>
<p>Returns the root directory of Erlang/OTP, which is
@@ -638,7 +579,7 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name>lib_dir() -> string()</name>
+ <name name="lib_dir" arity="0"/>
<fsummary>Library directory of Erlang/OTP</fsummary>
<desc>
<p>Returns the library directory, <c>$OTPROOT/lib</c>, where
@@ -649,19 +590,16 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name>lib_dir(Name) -> string() | {error, bad_name}</name>
+ <name name="lib_dir" arity="1"/>
<fsummary>Library directory for an application</fsummary>
- <type>
- <v>Name = atom()</v>
- </type>
<desc>
<p>This function is mainly intended for finding out the path
for the "library directory", the top directory, for an
- application <c>Name</c> located under <c>$OTPROOT/lib</c> or
+ application <c><anno>Name</anno></c> located under <c>$OTPROOT/lib</c> or
on a directory referred to via the <c>ERL_LIBS</c>
environment variable.</p>
- <p>If there is a regular directory called <c>Name</c> or
- <c>Name-Vsn</c> in the code path with an <c>ebin</c>
+ <p>If there is a regular directory called <c><anno>Name</anno></c> or
+ <c><anno>Name</anno>-Vsn</c> in the code path with an <c>ebin</c>
subdirectory, the path to this directory is returned (not
the <c>ebin</c> directory). If the directory refers to a
directory in an archive, the archive name is stripped away
@@ -675,23 +613,19 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
<pre>
> <input>code:lib_dir(mnesia).</input>
"/usr/local/otp/lib/mnesia-4.2.2"</pre>
- <p>Returns <c>{error, bad_name}</c> if <c>Name</c>
+ <p>Returns <c>{error, bad_name}</c> if <c><anno>Name</anno></c>
is not the name of an application under <c>$OTPROOT/lib</c> or
on a directory referred to via the <c>ERL_LIBS</c>
environment variable. Fails with an exception if <c>Name</c>
has the wrong type.</p>
- <warning><p>For backward compatibility, <c>Name</c> is also allowed to
+ <warning><p>For backward compatibility, <c><anno>Name</anno></c> is also allowed to
be a string. That will probably change in a future release.</p></warning>
</desc>
</func>
<func>
- <name>lib_dir(Name, SubDir) -> string() | {error, bad_name}</name>
+ <name name="lib_dir" arity="2"/>
<fsummary>subdirectory for an application</fsummary>
- <type>
- <v>Name = atom()</v>
- <v>SubDir = atom()</v>
- </type>
<desc>
<p>Returns the path to a subdirectory directly under the top
directory of an application. Normally the subdirectories
@@ -705,12 +639,12 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
> <input>code:lib_dir(megaco, priv).</input>
"/usr/local/otp/lib/megaco-3.9.1.1/priv"</pre>
- <p>Fails with an exception if <c>Name</c> or <c>SubDir</c> has
+ <p>Fails with an exception if <c><anno>Name</anno></c> or <c><anno>SubDir</anno></c> has
the wrong type.</p>
</desc>
</func>
<func>
- <name>compiler_dir() -> string()</name>
+ <name name="compiler_dir" arity="0"/>
<fsummary>Library directory for the compiler</fsummary>
<desc>
<p>Returns the compiler library directory. Equivalent to
@@ -718,21 +652,18 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name>priv_dir(Name) -> string() | {error, bad_name}</name>
+ <name name="priv_dir" arity="1"/>
<fsummary>Priv directory for an application</fsummary>
- <type>
- <v>Name = atom()</v>
- </type>
<desc>
<p>Returns the path to the <c>priv</c> directory in an
- application. Equivalent to <c>code:lib_dir(Name,priv).</c>.</p>
+ application. Equivalent to <c>code:lib_dir(<anno>Name</anno>, priv).</c>.</p>
- <warning><p>For backward compatibility, <c>Name</c> is also allowed to
+ <warning><p>For backward compatibility, <c><anno>Name</anno></c> is also allowed to
be a string. That will probably change in a future release.</p></warning>
</desc>
</func>
<func>
- <name>objfile_extension() -> ".beam"</name>
+ <name name="objfile_extension" arity="0"/>
<fsummary>Object code file extension</fsummary>
<desc>
<p>Returns the object code file extension that corresponds to
@@ -740,24 +671,16 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name>stick_dir(Dir) -> ok | error</name>
+ <name name="stick_dir" arity="1"/>
<fsummary>Mark a directory as sticky</fsummary>
- <type>
- <v>Dir = string()</v>
- <v>What = term()</v>
- </type>
<desc>
- <p>This function marks <c>Dir</c> as sticky.</p>
+ <p>This function marks <c><anno>Dir</anno></c> as sticky.</p>
<p>Returns <c>ok</c> if successful or <c>error</c> if not.</p>
</desc>
</func>
<func>
- <name>unstick_dir(Dir) -> ok | error</name>
+ <name name="unstick_dir" arity="1"/>
<fsummary>Remove a sticky directory mark</fsummary>
- <type>
- <v>Dir = string()</v>
- <v>What = term()</v>
- </type>
<desc>
<p>This function unsticks a directory which has been marked as
sticky.</p>
@@ -765,45 +688,39 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name>is_sticky(Module) -> true | false</name>
+ <name name="is_sticky" arity="1"/>
<fsummary>Test whether a module is sticky</fsummary>
- <type>
- <v>Module = atom()</v>
- </type>
<desc>
- <p>This function returns <c>true</c> if <c>Module</c> is the
+ <p>This function returns <c>true</c> if <c><anno>Module</anno></c> is the
name of a module that has been loaded from a sticky directory
(or in other words: an attempt to reload the module will fail),
- or <c>false</c> if <c>Module</c> is not a loaded module or is
+ or <c>false</c> if <c><anno>Module</anno></c> is not a loaded module or is
not sticky.</p>
</desc>
</func>
<func>
- <name>rehash() -> ok</name>
+ <name name="rehash" arity="0"/>
<fsummary>Rehash or create code path cache</fsummary>
<desc>
<p>This function creates or rehashes the code path cache.</p>
</desc>
</func>
<func>
- <name>where_is_file(Filename) -> Absname | non_existing</name>
+ <name name="where_is_file" arity="1"/>
<fsummary>Full name of a file located in the code path</fsummary>
- <type>
- <v>Filename = Absname = string()</v>
- </type>
<desc>
- <p>Searches the code path for <c>Filename</c>, a file of
+ <p>Searches the code path for <c><anno>Filename</anno></c>, a file of
arbitrary type. If found, the full name is returned.
<c>non_existing</c> is returned if the file cannot be found.
The function can be useful, for example, to locate
application resource files. If the code path cache is used,
the code server will efficiently read the full name from
- the cache, provided that <c>Filename</c> is an object code
+ the cache, provided that <c><anno>Filename</anno></c> is an object code
file or an <c>.app</c> file.</p>
</desc>
</func>
<func>
- <name>clash() -> ok</name>
+ <name name="clash" arity="0"/>
<fsummary>Search for modules with identical names.</fsummary>
<desc>
<p>Searches the entire code space for module names with
@@ -811,10 +728,10 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
</desc>
</func>
<func>
- <name>is_module_native(Module) -> true | false | undefined</name>
+ <name>is_module_native(Module) -> boolean() | undefined</name>
<fsummary>Test whether a module has native code</fsummary>
<type>
- <v>Module = atom()</v>
+ <v>Module = module()</v>
</type>
<desc>
<p>This function returns <c>true</c> if <c>Module</c> is
diff --git a/lib/kernel/doc/src/disk_log.xml b/lib/kernel/doc/src/disk_log.xml
index 324d4264cf..d278d54d93 100644
--- a/lib/kernel/doc/src/disk_log.xml
+++ b/lib/kernel/doc/src/disk_log.xml
@@ -179,13 +179,48 @@
reopen the log simultaneously.</p>
</note>
</description>
+ <datatypes>
+ <datatype>
+ <name name="log"/>
+ </datatype>
+ <datatype>
+ <name name="dlog_size"/>
+ </datatype>
+ <datatype>
+ <name name="dlog_format"/>
+ </datatype>
+ <datatype>
+ <name name="dlog_head_opt"/>
+ </datatype>
+ <datatype>
+ <name name="dlog_byte"/>
+ </datatype>
+ <datatype>
+ <name name="dlog_mode"/>
+ </datatype>
+ <datatype>
+ <name name="dlog_type"/>
+ </datatype>
+ <datatype>
+ <name name="continuation"/>
+ <desc><p>Chunk continuation returned by
+ <c>chunk/2,3</c>, <c>bchunk/2,3</c>, or <c>chunk_step/3</c>.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="bytes"/>
+ </datatype>
+ <datatype>
+ <name name="invalid_header"/>
+ </datatype>
+ <datatype>
+ <name name="file_error"/>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>accessible_logs() -> {[LocalLog], [DistributedLog]}</name>
+ <name name="accessible_logs" arity="0"/>
<fsummary>Return the accessible disk logs on the current node.</fsummary>
- <type>
- <v>LocalLog = DistributedLog = term()</v>
- </type>
<desc>
<p>The <c>accessible_logs/0</c> function returns
the names of the disk logs accessible on the current node.
@@ -195,16 +230,13 @@
</desc>
</func>
<func>
- <name>alog(Log, Term)</name>
- <name>balog(Log, Bytes) -> ok | {error, Reason}</name>
+ <name name="alog" arity="2"/>
+ <name name="balog" arity="2"/>
+ <type variable="Log"/>
+ <type variable="Term" name_i="1"/>
+ <type variable="Bytes"/>
+ <type name="notify_ret"/>
<fsummary>Asynchronously log an item onto a disk log.</fsummary>
- <type>
- <v>Log = term()</v>
- <v>Term = term()</v>
- <v>Bytes = binary() | [Byte]</v>
- <v>Byte = [Byte] | 0 =&lt; integer() =&lt; 255</v>
- <v>Reason = no_such_log</v>
- </type>
<desc>
<p>The <c>alog/2</c> and <c>balog/2</c> functions asynchronously
append an item to a disk log. The function <c>alog/2</c> is
@@ -225,17 +257,13 @@
</desc>
</func>
<func>
- <name>alog_terms(Log, TermList)</name>
- <name>balog_terms(Log, BytesList) -> ok | {error, Reason}</name>
+ <name name="alog_terms" arity="2"/>
+ <name name="balog_terms" arity="2"/>
<fsummary>Asynchronously log several items onto a disk log.</fsummary>
- <type>
- <v>Log = term()</v>
- <v>TermList = [term()]</v>
- <v>BytesList = [Bytes]</v>
- <v>Bytes = binary() | [Byte]</v>
- <v>Byte = [Byte] | 0 =&lt; integer() =&lt; 255</v>
- <v>Reason = no_such_log</v>
- </type>
+ <type variable="Log"/>
+ <type variable="TermList" name_i="1"/>
+ <type variable="ByteList"/>
+ <type name="notify_ret"/>
<desc>
<p>The <c>alog_terms/2</c> and <c>balog_terms/2</c> functions
asynchronously append a list of items to a disk log.
@@ -257,14 +285,10 @@
</desc>
</func>
<func>
- <name>block(Log)</name>
- <name>block(Log, QueueLogRecords) -> ok | {error, Reason}</name>
+ <name name="block" arity="1"/>
+ <name name="block" arity="2"/>
+ <type name="block_error_rsn"/>
<fsummary>Block a disk log.</fsummary>
- <type>
- <v>Log = term()</v>
- <v>QueueLogRecords = bool()</v>
- <v>Reason = no_such_log | nonode | {blocked_log, Log}</v>
- </type>
<desc>
<p>With a call to <c>block/1,2</c> a process can block a log.
If the blocking process is not an owner of the log, a temporary
@@ -280,52 +304,32 @@
affected by the block. Any other attempt than those hitherto
mentioned to update or read a blocked log suspends the
calling process until the log is unblocked or returns an
- error message <c>{blocked_log, Log}</c>, depending on
- whether the value of <c>QueueLogRecords</c> is <c>true</c>
- or <c>false</c>. The default value of <c>QueueLogRecords</c>
+ error message <c>{blocked_log, <anno>Log</anno>}</c>, depending on
+ whether the value of <c><anno>QueueLogRecords</anno></c> is <c>true</c>
+ or <c>false</c>. The default value of <c><anno>QueueLogRecords</anno></c>
is <c>true</c>, which is used by <c>block/1</c>.
</p>
</desc>
</func>
<func>
- <name>change_header(Log, Header) -> ok | {error, Reason}</name>
+ <name name="change_header" arity="2"/>
<fsummary>Change the head or head_func option for an owner of a disk log.</fsummary>
- <type>
- <v>Log = term()</v>
- <v>Header = {head, Head} | {head_func, {M,F,A}}</v>
- <v>Head = none | term() | binary() | [Byte]</v>
- <v>Byte = [Byte] | 0 =&lt; integer() =&lt; 255</v>
- <v>Reason = no_such_log | nonode | {read_only_mode, Log} | {blocked_log, Log} | {badarg, head}</v>
- </type>
<desc>
<p>The <c>change_header/2</c> function changes the value of
the <c>head</c> or <c>head_func</c> option of a disk log.</p>
</desc>
</func>
<func>
- <name>change_notify(Log, Owner, Notify) -> ok | {error, Reason}</name>
+ <name name="change_notify" arity="3"/>
<fsummary>Change the notify option for an owner of a disk log.</fsummary>
- <type>
- <v>Log = term()</v>
- <v>Owner = pid()</v>
- <v>Notify = bool()</v>
- <v>Reason = no_such_log | nonode | {blocked_log, Log} | {badarg, notify} | {not_owner, Owner}</v>
- </type>
<desc>
<p>The <c>change_notify/3</c> function changes the value of the
<c>notify</c> option for an owner of a disk log. </p>
</desc>
</func>
<func>
- <name>change_size(Log, Size) -> ok | {error, Reason}</name>
+ <name name="change_size" arity="2"/>
<fsummary>Change the size of an open disk log.</fsummary>
- <type>
- <v>Log = term()</v>
- <v>Size = integer() > 0 | infinity | {MaxNoBytes, MaxNoFiles}</v>
- <v>MaxNoBytes = integer() > 0</v>
- <v>MaxNoFiles = integer() > 0</v>
- <v>Reason = no_such_log | nonode | {read_only_mode, Log} | {blocked_log, Log} | {new_size_too_small, CurrentSize} | {badarg, size} | {file_error, FileName, FileError}</v>
- </type>
<desc>
<p>The <c>change_size/2</c> function changes the size of an open log.
For a halt log it is always possible to increase the size,
@@ -363,21 +367,17 @@
</desc>
</func>
<func>
- <name>chunk(Log, Continuation)</name>
- <name>chunk(Log, Continuation, N) -> {Continuation2, Terms} | {Continuation2, Terms, Badbytes} | eof | {error, Reason}</name>
- <name>bchunk(Log, Continuation)</name>
- <name>bchunk(Log, Continuation, N) -> {Continuation2, Binaries} | {Continuation2, Binaries, Badbytes} | eof | {error, Reason}</name>
+ <name name="chunk" arity="2"/>
+ <name name="chunk" arity="3"/>
+ <name name="bchunk" arity="2"/>
+ <name name="bchunk" arity="3"/>
<fsummary>Read a chunk of items written to a disk log.</fsummary>
- <type>
- <v>Log = term()</v>
- <v>Continuation = start | cont()</v>
- <v>N = integer() > 0 | infinity</v>
- <v>Continuation2 = cont()</v>
- <v>Terms = [term()]</v>
- <v>Badbytes = integer()</v>
- <v>Reason = no_such_log | {format_external, Log} | {blocked_log, Log} | {badarg, continuation} | {not_internal_wrap, Log} | {corrupt_log_file, FileName} | {file_error, FileName, FileError}</v>
- <v>Binaries = [binary()]</v>
- </type>
+ <type variable="Log"/>
+ <type variable="Continuation"/>
+ <type variable="N"/>
+ <type name="chunk_ret"/>
+ <type name="bchunk_ret"/>
+ <type name="chunk_error_rsn"/>
<desc>
<p>The <c>chunk/2,3</c> and <c>bchunk/2,3</c> functions make
it possible to efficiently read the terms which have been
@@ -394,31 +394,31 @@
individual distributed log on some other node is chosen, if
such a log exists.
</p>
- <p>When <c>chunk/3</c> is called, <c>N</c> controls the
+ <p>When <c>chunk/3</c> is called, <c><anno>N</anno></c> controls the
maximum number of terms that are read from the log in each
chunk. Default is <c>infinity</c>, which means that all the
terms contained in the 64 kilobyte chunk are read. If less than
- <c>N</c> terms are returned, this does not necessarily mean
+ <c><anno>N</anno></c> terms are returned, this does not necessarily mean
that the end of the file has been reached.
</p>
<p>The <c>chunk</c> function returns a tuple
- <c>{Continuation2, Terms}</c>, where <c>Terms</c> is a list
- of terms found in the log. <c>Continuation2</c> is yet
+ <c>{<anno>Continuation2</anno>, <anno>Terms</anno>}</c>, where <c><anno>Terms</anno></c> is a list
+ of terms found in the log. <c><anno>Continuation2</anno></c> is yet
another continuation which must be passed on to any
subsequent calls to <c>chunk</c>. With a series of calls to
<c>chunk</c> it is possible to extract all terms from a log.
</p>
<p>The <c>chunk</c> function returns a tuple
- <c>{Continuation2, Terms, Badbytes}</c> if the log is opened
- in read-only mode and the read chunk is corrupt. <c>Badbytes</c>
+ <c>{<anno>Continuation2</anno>, <anno>Terms</anno>, <anno>Badbytes</anno>}</c> if the log is opened
+ in read-only mode and the read chunk is corrupt. <c><anno>Badbytes</anno></c>
is the number of bytes in the file which were found not to be
Erlang terms in the chunk. Note also that the log is not repaired.
When trying to read chunks from a log opened in read-write mode,
- the tuple <c>{corrupt_log_file, FileName}</c> is returned if the
+ the tuple <c>{corrupt_log_file, <anno>FileName</anno>}</c> is returned if the
read chunk is corrupt.
</p>
<p><c>chunk</c> returns <c>eof</c> when the end of the log is
- reached, or <c>{error, Reason}</c> if an error occurs. Should
+ reached, or <c>{error, <anno>Reason</anno>}</c> if an error occurs. Should
a wrap log file be missing, a message is output on the error log.
</p>
<p>When <c>chunk/2,3</c> is used with wrap logs, the returned
@@ -431,12 +431,8 @@
</desc>
</func>
<func>
- <name>chunk_info(Continuation) -> InfoList | {error, Reason}</name>
+ <name name="chunk_info" arity="1"/>
<fsummary>Return information about a chunk continuation of a disk log.</fsummary>
- <type>
- <v>Continuation = cont()</v>
- <v>Reason = {no_continuation, Continuation}</v>
- </type>
<desc>
<p>The <c>chunk_info/1</c> function returns the following pair
describing the chunk continuation returned by
@@ -444,29 +440,22 @@
</p>
<list type="bulleted">
<item>
- <p><c>{node, Node}</c>. Terms are read from
- the disk log running on <c>Node</c>.</p>
+ <p><c>{node, <anno>Node</anno>}</c>. Terms are read from
+ the disk log running on <c><anno>Node</anno></c>.</p>
</item>
</list>
</desc>
</func>
<func>
- <name>chunk_step(Log, Continuation, Step) -> {ok, Continuation2} | {error, Reason}</name>
+ <name name="chunk_step" arity="3"/>
<fsummary>Step forward or backward among the wrap log files of a disk log.</fsummary>
- <type>
- <v>Log = term()</v>
- <v>Continuation = start | cont()</v>
- <v>Step = integer()</v>
- <v>Continuation2 = cont()</v>
- <v>Reason = no_such_log | end_of_log | {format_external, Log} | {blocked_log, Log} | {badarg, continuation} | {file_error, FileName, FileError}</v>
- </type>
<desc>
<p>The function <c>chunk_step</c> can be used in conjunction
with <c>chunk/2,3</c> and <c>bchunk/2,3</c> to search
through an internally formatted wrap log. It takes as
argument a continuation as returned by <c>chunk/2,3</c>,
<c>bchunk/2,3</c>, or <c>chunk_step/3</c>, and steps forward
- (or backward) <c>Step</c> files in the wrap log. The
+ (or backward) <c><anno>Step</anno></c> files in the wrap log. The
continuation returned points to the first log item in the
new current file.
</p>
@@ -482,14 +471,11 @@
</desc>
</func>
<func>
- <name>close(Log) -> ok | {error, Reason}</name>
+ <name name="close" arity="1"/>
<fsummary>Close a disk log.</fsummary>
- <type>
- <v>Reason = no_such_log | nonode | {file_error, FileName, FileError}</v>
- </type>
+ <type name="close_error_rsn"/>
<desc>
- <p> <marker id="close_1"></marker>
-The function <c>close/1</c> closes a
+ <p><marker id="close_1"></marker>The function <c>close/1</c> closes a
local or distributed disk log properly. An internally
formatted log must be closed before the Erlang system is
stopped, otherwise the log is regarded as unclosed and the
@@ -511,11 +497,8 @@ The function <c>close/1</c> closes a
</desc>
</func>
<func>
- <name>format_error(Error) -> Chars</name>
+ <name name="format_error" arity="1"/>
<fsummary>Return an English description of a disk log error reply.</fsummary>
- <type>
- <v>Chars = [char() | Chars]</v>
- </type>
<desc>
<p>Given the error returned by any function in this module,
the function <c>format_error</c> returns a descriptive string
@@ -524,11 +507,10 @@ The function <c>close/1</c> closes a
</desc>
</func>
<func>
- <name>inc_wrap_file(Log) -> ok | {error, Reason}</name>
+ <name name="inc_wrap_file" arity="1"/>
<fsummary>Change to the next wrap log file of a disk log.</fsummary>
- <type>
- <v>Reason = no_such_log | nonode | {read_only_mode, Log} | {blocked_log, Log} | {halt_log, Log} | {invalid_header, InvalidHeader} | {file_error, FileName, FileError}</v>
- </type>
+ <type name="inc_wrap_error_rsn"/>
+ <type name="invalid_header"/>
<desc>
<p>The <c>inc_wrap_file/1</c> function forces the internally formatted
disk log to start logging to the
@@ -543,8 +525,9 @@ The function <c>close/1</c> closes a
</desc>
</func>
<func>
- <name>info(Log) -> InfoList | {error, no_such_log}</name>
+ <name name="info" arity="1"/>
<fsummary>Return information about a disk log.</fsummary>
+ <type name="dlog_info"/>
<desc>
<p>The <c>info/1</c> function returns a list of <c>{Tag, Value}</c>
pairs describing the log. If there is a disk log process running
@@ -556,55 +539,55 @@ The function <c>close/1</c> closes a
</p>
<list type="bulleted">
<item>
- <p><c>{name, Log}</c>, where <c>Log</c> is the name of
+ <p><c>{name, <anno>Log</anno>}</c>, where <c><anno>Log</anno></c> is the name of
the log as given by the <c>open/1</c> option <c>name</c>.</p>
</item>
<item>
- <p><c>{file, File}</c>. For halt logs <c>File</c> is the
- filename, and for wrap logs <c>File</c> is the base name.</p>
+ <p><c>{file, <anno>File</anno>}</c>. For halt logs <c><anno>File</anno></c> is the
+ filename, and for wrap logs <c><anno>File</anno></c> is the base name.</p>
</item>
<item>
- <p><c>{type, Type}</c>, where <c>Type</c> is the type of
+ <p><c>{type, <anno>Type</anno>}</c>, where <c><anno>Type</anno></c> is the type of
the log as given by the <c>open/1</c> option <c>type</c>.</p>
</item>
<item>
- <p><c>{format, Format}</c>, where <c>Format</c> is the format
+ <p><c>{format, <anno>Format</anno>}</c>, where <c><anno>Format</anno></c> is the format
of the log as given by the <c>open/1</c> option <c>format</c>.</p>
</item>
<item>
- <p><c>{size, Size}</c>, where <c>Size</c> is the size
+ <p><c>{size, <anno>Size</anno>}</c>, where <c><anno>Size</anno></c> is the size
of the log as given by the <c>open/1</c> option <c>size</c>,
or the size set by <c>change_size/2</c>. The value set by
<c>change_size/2</c> is reflected immediately.</p>
</item>
<item>
- <p><c>{mode, Mode}</c>, where <c>Mode</c> is the mode
+ <p><c>{mode, <anno>Mode</anno>}</c>, where <c><anno>Mode</anno></c> is the mode
of the log as given by the <c>open/1</c> option <c>mode</c>.</p>
</item>
<item>
- <p><c>{owners, [{pid(), Notify}]}</c> where <c>Notify</c>
+ <p><c>{owners, [{pid(), <anno>Notify</anno>}]}</c> where <c><anno>Notify</anno></c>
is the value set by the <c>open/1</c> option <c>notify</c>
or the function <c>change_notify/3</c> for the owners of
the log.</p>
</item>
<item>
- <p><c>{users, Users}</c> where <c>Users</c> is the number
+ <p><c>{users, <anno>Users</anno>}</c> where <c><anno>Users</anno></c> is the number
of anonymous users of the log, see the <c>open/1</c> option
<seealso marker="#linkto">linkto</seealso>.</p>
</item>
<item>
- <p><c>{status, Status}</c>, where <c>Status</c> is <c>ok</c>
- or <c>{blocked, QueueLogRecords}</c> as set by the functions
+ <p><c>{status, <anno>Status</anno>}</c>, where <c><anno>Status</anno></c> is <c>ok</c>
+ or <c>{blocked, <anno>QueueLogRecords</anno>}</c> as set by the functions
<c>block/1,2</c> and <c>unblock/1</c>.</p>
</item>
<item>
- <p><c>{node, Node}</c>. The information returned by the
+ <p><c>{node, <anno>Node</anno>}</c>. The information returned by the
current invocation of the <c>info/1</c> function has been
- gathered from the disk log process running on <c>Node</c>.</p>
+ gathered from the disk log process running on <c><anno>Node</anno></c>.</p>
</item>
<item>
- <p><c>{distributed, Dist}</c>. If the log is local on
- the current node, then <c>Dist</c> has the value <c>local</c>,
+ <p><c>{distributed, <anno>Dist</anno>}</c>. If the log is local on
+ the current node, then <c><anno>Dist</anno></c> has the value <c>local</c>,
otherwise all nodes where the log is distributed
are returned as a list.</p>
</item>
@@ -614,16 +597,16 @@ The function <c>close/1</c> closes a
</p>
<list type="bulleted">
<item>
- <p><c>{head, Head}</c>. Depending of the value of
+ <p><c>{head, <anno>Head</anno>}</c>. Depending of the value of
the <c>open/1</c> options <c>head</c> and <c>head_func</c>
or set by the function <c>change_header/2</c>, the value
- of <c>Head</c> is <c>none</c> (default),
+ of <c><anno>Head</anno></c> is <c>none</c> (default),
<c>{head, H}</c> (<c>head</c> option) or <c>{M,F,A}</c>
(<c>head_func</c> option).</p>
</item>
<item>
- <p><c>{no_written_items, NoWrittenItems}</c>, where
- <c>NoWrittenItems</c> is the number of items
+ <p><c>{no_written_items, <anno>NoWrittenItems</anno>}</c>, where
+ <c><anno>NoWrittenItems</anno></c> is the number of items
written to the log since the disk log process was created.</p>
</item>
</list>
@@ -632,7 +615,7 @@ The function <c>close/1</c> closes a
</p>
<list type="bulleted">
<item>
- <p><c>{full, Full}</c>, where <c>Full</c> is <c>true</c> or
+ <p><c>{full, <anno>Full</anno>}</c>, where <c><anno>Full</anno></c> is <c>true</c> or
<c>false</c> depending on whether the halt log is full or not.</p>
</item>
</list>
@@ -660,8 +643,8 @@ The function <c>close/1</c> closes a
<c>size</c> or set by <c>change_size/2</c>.</p>
</item>
<item>
- <p><c>{no_overflows, {SinceLogWasOpened, SinceLastInfo}}</c>,
- where <c>SinceLogWasOpened</c> (<c>SinceLastInfo</c>) is
+ <p><c>{no_overflows, {<anno>SinceLogWasOpened</anno>, <anno>SinceLastInfo</anno>}}</c>,
+ where <c><anno>SinceLogWasOpened</anno></c> (<c><anno>SinceLastInfo</anno></c>) is
the number of times a wrap log file has been filled up and a
new one opened or <c>inc_wrap_file/1</c> has been called since
the disk log was last opened (<c>info/1</c>
@@ -677,21 +660,18 @@ The function <c>close/1</c> closes a
</desc>
</func>
<func>
- <name>lclose(Log)</name>
- <name>lclose(Log, Node) -> ok | {error, Reason}</name>
+ <name name="lclose" arity="1"/>
+ <name name="lclose" arity="2"/>
+ <type name="lclose_error_rsn"/>
<fsummary>Close a disk log on one node.</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Reason = no_such_log | {file_error, FileName, FileError}</v>
- </type>
<desc>
<p>The function <c>lclose/1</c> closes a local log or an
individual distributed log on the current node.
The function <c>lclose/2</c> closes an individual
distributed log on the specified node if the node
is not the current one.
- <c>lclose(Log)</c> is equivalent to
- <c>lclose(Log,&nbsp;node())</c>.
+ <c>lclose(<anno>Log</anno>)</c> is equivalent to
+ <c>lclose(<anno>Log</anno>,&nbsp;node())</c>.
See also <seealso marker="#close_1">close/1</seealso>.
</p>
<p>If there is no log with the given name
@@ -700,20 +680,17 @@ The function <c>close/1</c> closes a
</desc>
</func>
<func>
- <name>log(Log, Term)</name>
- <name>blog(Log, Bytes) -> ok | {error, Reason}</name>
+ <name name="log" arity="2"/>
+ <name name="blog" arity="2"/>
<fsummary>Log an item onto a disk log.</fsummary>
- <type>
- <v>Log = term()</v>
- <v>Term = term()</v>
- <v>Bytes = binary() | [Byte]</v>
- <v>Byte = [Byte] | 0 =&lt; integer() =&lt; 255</v>
- <v>Reason = no_such_log | nonode | {read_only_mode, Log} | {format_external, Log} | {blocked_log, Log} | {full, Log} | {invalid_header, InvalidHeader} | {file_error, FileName, FileError}</v>
- </type>
+ <type variable="Log"/>
+ <type variable="Term" name_i="1"/>
+ <type variable="Bytes"/>
+ <type name="log_error_rsn"/>
<desc>
<p>The <c>log/2</c> and <c>blog/2</c> functions synchronously
append a term to a disk log. They return <c>ok</c> or
- <c>{error, Reason}</c> when the term has been written to
+ <c>{error, <anno>Reason</anno>}</c> when the term has been written to
disk. If the log is distributed, <c>ok</c> is always
returned, unless all nodes are down. Terms are written by
means of the ordinary <c>write()</c> function of the
@@ -736,17 +713,13 @@ The function <c>close/1</c> closes a
</desc>
</func>
<func>
- <name>log_terms(Log, TermList)</name>
- <name>blog_terms(Log, BytesList) -> ok | {error, Reason}</name>
+ <name name="log_terms" arity="2"/>
+ <name name="blog_terms" arity="2"/>
<fsummary>Log several items onto a disk log.</fsummary>
- <type>
- <v>Log = term()</v>
- <v>TermList = [term()]</v>
- <v>BytesList = [Bytes]</v>
- <v>Bytes = binary() | [Byte]</v>
- <v>Byte = [Byte] | 0 =&lt; integer() =&lt; 255</v>
- <v>Reason = no_such_log | nonode | {read_only_mode, Log} | {format_external, Log} | {blocked_log, Log} | {full, Log} | {invalid_header, InvalidHeader} | {file_error, FileName, FileError}</v>
- </type>
+ <type variable="Log"/>
+ <type variable="TermList" name_i="1"/>
+ <type variable="BytesList"/>
+ <type name="log_error_rsn"/>
<desc>
<p>The <c>log_terms/2</c> and <c>blog_terms/2</c> functions
synchronously append a list of items to the log. The benefit
@@ -769,47 +742,33 @@ The function <c>close/1</c> closes a
</desc>
</func>
<func>
- <name>open(ArgL) -> OpenRet | DistOpenRet</name>
+ <name name="open" arity="1"/>
+ <type name="dlog_options"/>
+ <type name="dlog_option"/>
+ <type name="open_ret"/>
+ <type name="ret"/>
+ <type name="dist_open_ret"/>
+ <type name="dist_error_rsn"/>
+ <type name="open_error_rsn"/>
+ <type name="dlog_optattr"/>
+ <type name="dlog_size"/>
<fsummary>Open a disk log file.</fsummary>
- <type>
- <v>ArgL = [Opt]</v>
- <v>Opt = {name, term()} | {file, FileName}, {linkto, LinkTo} | {repair, Repair} | {type, Type} | {format, Format} | {size, Size} | {distributed, [Node]} | {notify, bool()} | {head, Head} | {head_func, {M,F,A}} | {mode, Mode}</v>
- <v>FileName = string() | atom()</v>
- <v>LinkTo = pid() | none</v>
- <v>Repair = true | false | truncate</v>
- <v>Type = halt | wrap</v>
- <v>Format = internal | external</v>
- <v>Size = integer() > 0 | infinity | {MaxNoBytes, MaxNoFiles}</v>
- <v>MaxNoBytes = integer() > 0</v>
- <v>MaxNoFiles = 0 &lt; integer() &lt; 65000</v>
- <v>Rec = integer()</v>
- <v>Bad = integer()</v>
- <v>Head = none | term() | binary() | [Byte]</v>
- <v>Byte = [Byte] | 0 =&lt; integer() =&lt; 255</v>
- <v>Mode = read_write | read_only</v>
- <v>OpenRet = Ret | {error, Reason}</v>
- <v>DistOpenRet = {[{Node, Ret}], [{BadNode, {error, DistReason}}]}</v>
- <v>Node = BadNode = atom()</v>
- <v>Ret = {ok, Log} | {repaired, Log, {recovered, Rec}, {badbytes, Bad}}</v>
- <v>DistReason = nodedown | Reason</v>
- <v>Reason = no_such_log | {badarg, Arg} | {size_mismatch, CurrentSize, NewSize} | {arg_mismatch, OptionName, CurrentValue, Value} | {name_already_open, Log} | {open_read_write, Log} | {open_read_only, Log} | {need_repair, Log} | {not_a_log_file, FileName} | {invalid_index_file, FileName} | {invalid_header, InvalidHeader} | {file_error, FileName, FileError} | {node_already_open, Log}</v>
- </type>
<desc>
- <p>The <c>ArgL</c> parameter is a list of options which have
+ <p>The <c><anno>ArgL</anno></c> parameter is a list of options which have
the following meanings:</p>
<list type="bulleted">
<item>
- <p><c>{name, Log}</c> specifies the name of the log.
+ <p><c>{name, <anno>Log</anno>}</c> specifies the name of the log.
This is the name which must be passed on as a parameter in
all subsequent logging operations. A name must always
be supplied.
</p>
</item>
<item>
- <p><c>{file, FileName}</c> specifies the name of the
+ <p><c>{file, <anno>FileName</anno>}</c> specifies the name of the
file which will be used for logged terms. If this value is
omitted and the name of the log is either an atom or a string,
- the file name will default to <c>lists:concat([Log, ".LOG"])</c> for halt logs. For wrap logs, this will be
+ the file name will default to <c>lists:concat([<anno>Log</anno>, ".LOG"])</c> for halt logs. For wrap logs, this will be
the base name of the files. Each file in a wrap log
will be called <c><![CDATA[<base_name>.N]]></c>, where <c>N</c> is an
integer. Each wrap log will also have two files called
@@ -817,22 +776,22 @@ The function <c>close/1</c> closes a
</p>
</item>
<item>
- <p><c>{linkto, LinkTo}</c>. <marker id="linkto"></marker>
+ <p><c>{linkto, <anno>LinkTo</anno>}</c>. <marker id="linkto"></marker>
If
- <c>LinkTo</c> is a pid, that pid becomes an owner of the
- log. If <c>LinkTo</c> is <c>none</c> the log records
+ <c><anno>LinkTo</anno></c> is a pid, that pid becomes an owner of the
+ log. If <c><anno>LinkTo</anno></c> is <c>none</c> the log records
that it is used anonymously by some process by
incrementing the <c>users</c> counter. By default, the
process which calls <c>open/1</c> owns the log.
</p>
</item>
<item>
- <p><c>{repair, Repair}</c>. If <c>Repair</c> is <c>true</c>,
+ <p><c>{repair, <anno>Repair</anno>}</c>. If <c><anno>Repair</anno></c> is <c>true</c>,
the current log file will be repaired, if needed. As the
restoration is initiated, a message is output on the error log.
If <c>false</c> is given,
no automatic repair will be attempted. Instead, the
- tuple <c>{error, {need_repair, Log}}</c> is returned if an
+ tuple <c>{error, {need_repair, <anno>Log</anno>}}</c> is returned if an
attempt is made to open a corrupt log file.
If <c>truncate</c> is given, the log file will
be truncated, creating an empty log. Default is
@@ -841,41 +800,41 @@ If
</p>
</item>
<item>
- <p><c>{type, Type}</c> is the type of the log. Default
+ <p><c>{type, <anno>Type</anno>}</c> is the type of the log. Default
is <c>halt</c>.
</p>
</item>
<item>
- <p><c>{format, Format}</c> specifies the format of the
+ <p><c>{format, <anno>Format</anno>}</c> specifies the format of the
disk log. Default is <c>internal</c>.
</p>
</item>
<item>
- <p><c>{size, Size}</c> specifies the size of the log.
+ <p><c>{size, <anno>Size</anno>}</c> specifies the size of the log.
When a halt log has reached its maximum size, all attempts to
log more items are rejected. The default size is
<c>infinity</c>, which for halt implies that there is no
- maximum size. For wrap logs, the <c>Size</c> parameter
+ maximum size. For wrap logs, the <c><anno>Size</anno></c> parameter
may be either a pair
- <c>{MaxNoBytes, MaxNoFiles}</c> or <c>infinity</c>. In the
+ <c>{<anno>MaxNoBytes</anno>, <anno>MaxNoFiles</anno>}</c> or <c>infinity</c>. In the
latter case, if the files of an already existing wrap log
with the same name can be found, the size is read
from the existing wrap log, otherwise an error is returned.
- Wrap logs write at most <c>MaxNoBytes</c> bytes on each file
- and use <c>MaxNoFiles</c> files before starting all over with
- the first wrap log file. Regardless of <c>MaxNoBytes</c>,
+ Wrap logs write at most <c><anno>MaxNoBytes</anno></c> bytes on each file
+ and use <c><anno>MaxNoFiles</anno></c> files before starting all over with
+ the first wrap log file. Regardless of <c><anno>MaxNoBytes</anno></c>,
at least the header (if there is one) and one
item is written on each wrap log file before
wrapping to the next file.
When opening an existing wrap log, it is not
necessary to supply a value for the option <c>Size</c>, but any
supplied value must equal the current size of the log, otherwise
- the tuple <c>{error, {size_mismatch, CurrentSize, NewSize}}</c>
+ the tuple <c>{error, {size_mismatch, <anno>CurrentSize</anno>, <anno>NewSize</anno>}}</c>
is returned.
</p>
</item>
<item>
- <p><c>{distributed, Nodes}</c>. This option can be used for
+ <p><c>{distributed, <anno>Nodes</anno>}</c>. This option can be used for
adding members to a distributed disk log. The
default value is <c>[]</c>, which means that
the log is local on the current node.
@@ -946,10 +905,10 @@ If
</list>
</item>
<item>
- <p><c>{head, Head}</c> specifies a header to be
+ <p><c>{head, <anno>Head</anno>}</c> specifies a header to be
written first on the log file. If the log is a wrap
- log, the item <c>Head</c> is written first in each new file.
- <c>Head</c> should be a term if the format is
+ log, the item <c><anno>Head</anno></c> is written first in each new file.
+ <c><anno>Head</anno></c> should be a term if the format is
<c>internal</c>, and a deep list of bytes (or a binary)
otherwise. Default is <c>none</c>, which means that
no header is written first on the file.
@@ -966,17 +925,17 @@ If
</p>
</item>
<item>
- <p><c>{mode, Mode}</c> specifies if the log is to be
+ <p><c>{mode, <anno>Mode</anno>}</c> specifies if the log is to be
opened in read-only or read-write mode. It defaults to
<c>read_write</c>.
</p>
</item>
</list>
- <p>The <c>open/1</c> function returns <c>{ok, Log}</c> if the
+ <p>The <c>open/1</c> function returns <c>{ok, <anno>Log</anno>}</c> if the
log file was successfully opened. If the file was
- successfully repaired, the tuple <c>{repaired, Log, {recovered, Rec}, {badbytes, Bad}}</c> is returned, where
- <c>Rec</c> is the number of whole Erlang terms found in the
- file and <c>Bad</c> is the number of bytes in the file which
+ successfully repaired, the tuple <c>{repaired, <anno>Log</anno>, {recovered, <anno>Rec</anno>}, {badbytes, <anno>Bad</anno>}}</c> is returned, where
+ <c><anno>Rec</anno></c> is the number of whole Erlang terms found in the
+ file and <c><anno>Bad</anno></c> is the number of bytes in the file which
were non-Erlang terms. If the <c>distributed</c> parameter
was given, <c>open/1</c> returns a list of
successful replies and a list of erroneous replies. Each
@@ -988,7 +947,7 @@ If
position after the last logged item, and the logging of items
will commence from there. If the format is <c>internal</c>
and the existing file is not recognized as an internally
- formatted log, a tuple <c>{error, {not_a_log_file, FileName}}</c>
+ formatted log, a tuple <c>{error, {not_a_log_file, <anno>FileName</anno>}}</c>
is returned.
</p>
<p>The <c>open/1</c> function cannot be used for changing the
@@ -1000,15 +959,15 @@ If
or <c>change_size/2</c>. As a consequence,
none of the options except <c>name</c> is mandatory. If some
given value differs from the current value, a tuple
- <c>{error, {arg_mismatch, OptionName, CurrentValue, Value}}</c>
+ <c>{error, {arg_mismatch, <anno>OptionName</anno>, <anno>CurrentValue</anno>, <anno>Value</anno>}}</c>
is returned. Caution: an owner's attempt to open a log
as owner once again is acknowledged with the return value
- <c>{ok, Log}</c>, but the state of the disk log is not
+ <c>{ok, <anno>Log</anno>}</c>, but the state of the disk log is not
affected in any way.
</p>
<p>If a log with a given name is local on some node,
and one tries to open the log distributed on the same node,
- then the tuple <c>{error, {node_already_open, Name}}</c> is
+ then the tuple <c>{error, {node_already_open, <anno>Log</anno>}}</c> is
returned. The same tuple is returned if the log is distributed on
some node, and one tries to open the log locally on the same node.
Opening individual distributed disk logs for the first time
@@ -1036,12 +995,8 @@ If
</desc>
</func>
<func>
- <name>pid2name(Pid) -> {ok, Log} | undefined</name>
+ <name name="pid2name" arity="1"/>
<fsummary>Return the name of the disk log handled by a pid.</fsummary>
- <type>
- <v>Log = term()</v>
- <v>Pid = pid()</v>
- </type>
<desc>
<p>The <c>pid2name/1</c> function returns the name of the log
given the pid of a disk log process on the current node, or
@@ -1052,26 +1007,23 @@ If
</desc>
</func>
<func>
- <name>reopen(Log, File)</name>
- <name>reopen(Log, File, Head)</name>
- <name>breopen(Log, File, BHead) -> ok | {error, Reason}</name>
+ <name name="reopen" arity="2"/>
+ <name name="reopen" arity="3"/>
+ <name name="breopen" arity="3"/>
<fsummary>Reopen a disk log and save the old log.</fsummary>
- <type>
- <v>Log = term()</v>
- <v>File = string()</v>
- <v>Head = term()</v>
- <v>BHead = binary() | [Byte]</v>
- <v>Byte = [Byte] | 0 =&lt; integer() =&lt; 255</v>
- <v>Reason = no_such_log | nonode | {read_only_mode, Log} | {blocked_log, Log} | {same_file_name, Log} | {invalid_index_file, FileName} | {invalid_header, InvalidHeader} | {file_error, FileName, FileError}</v>
- </type>
+ <type variable="Log"/>
+ <type variable="File" name_i="1"/>
+ <type variable="Head" name_i="2"/>
+ <type variable="BHead"/>
+ <type name="reopen_error_rsn"/>
<desc>
<p>The <c>reopen</c> functions first rename the log file
- to <c>File</c> and then re-create a new log file.
- In case of a wrap log, <c>File</c> is used as the base name
+ to <c><anno>File</anno></c> and then re-create a new log file.
+ In case of a wrap log, <c><anno>File</anno></c> is used as the base name
of the renamed files.
By default the header given to <c>open/1</c> is written first in
- the newly opened log file, but if the <c>Head</c> or the
- <c>BHead</c> argument is given, this item is used instead.
+ the newly opened log file, but if the <c><anno>Head</anno></c> or the
+ <c><anno>BHead</anno></c> argument is given, this item is used instead.
The header argument is used once only; next time a wrap log file
is opened, the header given to <c>open/1</c> is used.
</p>
@@ -1089,12 +1041,9 @@ If
</desc>
</func>
<func>
- <name>sync(Log) -> ok | {error, Reason}</name>
+ <name name="sync" arity="1"/>
+ <type name="sync_error_rsn"/>
<fsummary>Flush the contents of a disk log to the disk.</fsummary>
- <type>
- <v>Log = term()</v>
- <v>Reason = no_such_log | nonode | {read_only_mode, Log} | {blocked_log, Log} | {file_error, FileName, FileError}</v>
- </type>
<desc>
<p>The <c>sync/1</c> function ensures that the contents of the
log are actually written to the disk.
@@ -1103,20 +1052,17 @@ If
</desc>
</func>
<func>
- <name>truncate(Log)</name>
- <name>truncate(Log, Head)</name>
- <name>btruncate(Log, BHead) -> ok | {error, Reason}</name>
+ <name name="truncate" arity="1"/>
+ <name name="truncate" arity="2"/>
+ <name name="btruncate" arity="2"/>
<fsummary>Truncate a disk log.</fsummary>
- <type>
- <v>Log = term()</v>
- <v>Head = term()</v>
- <v>BHead = binary() | [Byte]</v>
- <v>Byte = [Byte] | 0 =&lt; integer() =&lt; 255</v>
- <v>Reason = no_such_log | nonode | {read_only_mode, Log} | {blocked_log, Log} | {invalid_header, InvalidHeader} | {file_error, FileName, FileError}</v>
- </type>
+ <type variable="Log"/>
+ <type variable="Head" name_i="2"/>
+ <type variable="BHead"/>
+ <type name="trunc_error_rsn"/>
<desc>
<p>The <c>truncate</c> functions remove all items from a disk log.
- If the <c>Head</c> or the <c>BHead</c> argument is
+ If the <c><anno>Head</anno></c> or the <c><anno>BHead</anno></c> argument is
given, this item is written first in the newly truncated
log, otherwise the header given to <c>open/1</c> is used.
The header argument is only used once; next time a wrap log file
@@ -1138,12 +1084,9 @@ If
</desc>
</func>
<func>
- <name>unblock(Log) -> ok | {error, Reason}</name>
+ <name name="unblock" arity="1"/>
+ <type name="unblock_error_rsn"/>
<fsummary>Unblock a disk log.</fsummary>
- <type>
- <v>Log = term()</v>
- <v>Reason = no_such_log | nonode | {not_blocked, Log} | {not_blocked_by_pid, Log}</v>
- </type>
<desc>
<p>The <c>unblock/1</c> function unblocks a log.
A log can only be unblocked by the blocking process.
@@ -1159,4 +1102,3 @@ If
<seealso marker="wrap_log_reader">wrap_log_reader(3)</seealso></p>
</section>
</erlref>
-
diff --git a/lib/kernel/doc/src/erl_boot_server.xml b/lib/kernel/doc/src/erl_boot_server.xml
index 4e7533810e..472671a80e 100644
--- a/lib/kernel/doc/src/erl_boot_server.xml
+++ b/lib/kernel/doc/src/erl_boot_server.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -49,29 +49,17 @@
</description>
<funcs>
<func>
- <name>start(Slaves) -> {ok, Pid} | {error, What}</name>
+ <name name="start" arity="1"/>
<fsummary>Start the boot server</fsummary>
- <type>
- <v>Slaves = [Host]</v>
- <v>Host = atom()</v>
- <v>Pid = pid()</v>
- <v>What = term()</v>
- </type>
<desc>
- <p>Starts the boot server. <c>Slaves</c> is a list of IP
+ <p>Starts the boot server. <c><anno>Slaves</anno></c> is a list of IP
addresses for hosts which are allowed to use this server as a
boot server.</p>
</desc>
</func>
<func>
- <name>start_link(Slaves) -> {ok, Pid} | {error, What}</name>
+ <name name="start_link" arity="1"/>
<fsummary>Start the boot server and links the caller</fsummary>
- <type>
- <v>Slaves = [Host]</v>
- <v>Host = atom()</v>
- <v>Pid = pid()</v>
- <v>What = term()()</v>
- </type>
<desc>
<p>Starts the boot server and links to the caller. This function
is used to start the server if it is included in a supervision
@@ -79,37 +67,23 @@
</desc>
</func>
<func>
- <name>add_slave(Slave) -> ok | {error, What}</name>
+ <name name="add_slave" arity="1"/>
<fsummary>Add a slave to the list of allowed slaves</fsummary>
- <type>
- <v>Slave = Host</v>
- <v>Host = atom()</v>
- <v>What = term()</v>
- </type>
<desc>
- <p>Adds a <c>Slave</c> node to the list of allowed slave hosts.</p>
+ <p>Adds a <c><anno>Slave</anno></c> node to the list of allowed slave hosts.</p>
</desc>
</func>
<func>
- <name>delete_slave(Slave) -> ok | {error, What}</name>
+ <name name="delete_slave" arity="1"/>
<fsummary>Delete a slave from the list of allowed slaves</fsummary>
- <type>
- <v>Slave = Host</v>
- <v>Host = atom()</v>
- <v>What = void()</v>
- </type>
<desc>
- <p>Deletes a <c>Slave</c> node from the list of allowed slave
+ <p>Deletes a <c><anno>Slave</anno></c> node from the list of allowed slave
hosts.</p>
</desc>
</func>
<func>
- <name>which_slaves() -> Slaves</name>
+ <name name="which_slaves" arity="0"/>
<fsummary>Return the current list of allowed slave hosts</fsummary>
- <type>
- <v>Slaves = [Host]</v>
- <v>Host = atom()</v>
- </type>
<desc>
<p>Returns the current list of allowed slave hosts.</p>
</desc>
diff --git a/lib/kernel/doc/src/erl_ddll.xml b/lib/kernel/doc/src/erl_ddll.xml
index 9a62b45d63..1911fb628e 100644
--- a/lib/kernel/doc/src/erl_ddll.xml
+++ b/lib/kernel/doc/src/erl_ddll.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2010</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -172,6 +172,14 @@
</item>
</taglist>
</description>
+ <datatypes>
+ <datatype>
+ <name name="driver"/>
+ </datatype>
+ <datatype>
+ <name name="path"/>
+ </datatype>
+ </datatypes>
<funcs>
<func>
<name>demonitor(MonitorRef) -> ok</name>
@@ -189,37 +197,21 @@
</desc>
</func>
<func>
- <name>info() -> AllInfoList</name>
+ <name name="info" arity="0"/>
<fsummary>Retrieve information about all drivers</fsummary>
- <type>
- <v>AllInfoList = [ DriverInfo ]</v>
- <v>DriverInfo = {DriverName, InfoList}</v>
- <v>DriverName = string()</v>
- <v>InfoList = [ InfoItem ]</v>
- <v>InfoItem = {Tag, Value}</v>
- <v>Tag = atom()</v>
- <v>Value = term()</v>
- </type>
<desc>
- <p>Returns a list of tuples <c>{DriverName, InfoList}</c>, where
- <c>InfoList</c> is the result of calling <seealso marker="#info/1">info/1</seealso> for that
- <c>DriverName</c>. Only dynamically linked in drivers are
+ <p>Returns a list of tuples <c>{<anno>DriverName</anno>, <anno>InfoList</anno>}</c>, where
+ <c><anno>InfoList</anno></c> is the result of calling <seealso marker="#info/1">info/1</seealso> for that
+ <c><anno>DriverName</anno></c>. Only dynamically linked in drivers are
included in the list.</p>
</desc>
</func>
<func>
- <name>info(Name) -> InfoList</name>
+ <name name="info" arity="1"/>
<fsummary>Retrieve information about one driver</fsummary>
- <type>
- <v>Name = string() | atom()</v>
- <v>InfoList = [ InfoItem ]</v>
- <v>InfoItem = {Tag, Value}</v>
- <v>Tag = atom()</v>
- <v>Value = term()</v>
- </type>
<desc>
- <p>Returns a list of tuples <c>{Tag, Value}</c>, where
- <c>Tag</c> is the information item and <c>Value</c> is the result
+ <p>Returns a list of tuples <c>{<anno>Tag</anno>, <anno>Value</anno>}</c>, where
+ <c><anno>Tag</anno></c> is the information item and <c><anno>Value</anno></c> is the result
of calling <seealso marker="#info/2">info/2</seealso> with this driver name and
this tag. The result being a tuple list containing all
information available about a driver. </p>
@@ -305,22 +297,18 @@
</desc>
</func>
<func>
- <name>load(Path, Name) -> ok | {error, ErrorDesc}</name>
+ <name name="load" arity="2"/>
<fsummary>Load a driver</fsummary>
- <type>
- <v>Path = Name = string() | atom()</v>
- <v>ErrorDesc = term()</v>
- </type>
<desc>
- <p>Loads and links the dynamic driver <c>Name</c>. <c>Path</c>
+ <p>Loads and links the dynamic driver <c><anno>Name</anno></c>. <c><anno>Path</anno></c>
is a file path to the directory containing the driver.
- <c>Name</c> must be a sharable object/dynamic library. Two
- drivers with different <c>Path</c> parameters cannot be
- loaded under the same name. The <c>Name</c> is a string or
+ <c><anno>Name</anno></c> must be a sharable object/dynamic library. Two
+ drivers with different <c><anno>Path</anno></c> parameters cannot be
+ loaded under the same name. The <c><anno>Name</anno></c> is a string or
atom containing at least one character.</p>
- <p>The <c>Name</c> given should correspond to the filename
+ <p>The <c><anno>Name</anno></c> given should correspond to the filename
of the actual dynamically loadable object file residing in
- the directory given as <c>Path</c>, but <em>without</em> the
+ the directory given as <c><anno>Path</anno></c>, but <em>without</em> the
extension (i.e. <c>.so</c>). The driver name provided in
the driver initialization routine must correspond with the
filename, in much the same way as erlang module names
@@ -328,14 +316,14 @@
<p>If the driver has been previously unloaded, but is still
present due to open ports against it, a call to
<c>load/2</c> will stop the unloading and keep the driver
- (as long as the <c>Path</c> is the same) and <c>ok</c> is
+ (as long as the <c><anno>Path</anno></c> is the same) and <c>ok</c> is
returned. If one actually wants the object code to be
reloaded, one uses <seealso marker="#reload/2">reload/2</seealso> or the low-level
interface <seealso marker="#try_load/3">try_load/3</seealso>
instead. Please refer to the description of <seealso marker="#scenarios">different scenarios</seealso> for
loading/unloading in the introduction.</p>
<p>If more than one process tries to load an already loaded
- driver withe the same <c>Path</c>, or if the same process
+ driver withe the same <c><anno>Path</anno></c>, or if the same process
tries to load it several times, the function will return
<c>ok</c>. The emulator will keep track of the
<c>load/2</c> calls, so that a corresponding number of
@@ -349,16 +337,16 @@
several drivers with the same name but with different
<c>Path</c> parameters.</p>
<note>
- <p>Note especially that the <c>Path</c> is interpreted
+ <p>Note especially that the <c><anno>Path</anno></c> is interpreted
literally, so that all loaders of the same driver needs to
- give the same <em>literal</em><c>Path</c> string, even
+ give the same <em>literal</em><c><anno>Path</anno></c> string, even
though different paths might point out the same directory
in the filesystem (due to use of relative paths and
links).</p>
</note>
<p>On success, the function returns <c>ok</c>. On
- failure, the return value is <c>{error,ErrorDesc}</c>,
- where <c>ErrorDesc</c> is an opaque term to be
+ failure, the return value is <c>{error,<anno>ErrorDesc</anno>}</c>,
+ where <c><anno>ErrorDesc</anno></c> is an opaque term to be
translated into human readable form by the <seealso marker="#format_error/1">format_error/1</seealso>
function.</p>
<p>For more control over the error handling, again use the
@@ -369,20 +357,16 @@
</desc>
</func>
<func>
- <name>load_driver(Path, Name) -> ok | {error, ErrorDesc}</name>
+ <name name="load_driver" arity="2"/>
<fsummary>Load a driver</fsummary>
- <type>
- <v>Path = Name = string() | atom()</v>
- <v>ErrorDesc = term()</v>
- </type>
<desc>
<p>Works essentially as <c>load/2</c>, but will load the driver
- with options other options. All ports that are using the
+ with other options. All ports that are using the
driver will get killed with the reason
<c>driver_unloaded</c> when the driver is to be unloaded.</p>
<p>The number of loads and unloads by different <seealso marker="#users">users</seealso> influence the actual loading
and unloading of a driver file. The port killing will
- therefore only happen when the <em>last</em><seealso marker="#users">user</seealso> unloads the driver, or the
+ therefore only happen when the <em>last</em> <seealso marker="#users">user</seealso> unloads the driver, or the
last process having loaded the driver exits.</p>
<p>This interface (or at least the name of the functions) is
kept for backward compatibility. Using <seealso marker="#try_load/3">try_load/3</seealso> with
@@ -551,16 +535,11 @@
</desc>
</func>
<func>
- <name>reload(Path, Name) -> ok | {error, ErrorDesc}</name>
+ <name name="reload" arity="2"/>
<fsummary>Replace a driver</fsummary>
- <type>
- <v>Path = Name = string() | atom()</v>
- <v>ErrorDesc = pending_process | OpaqueError</v>
- <v>OpaqueError = term()</v>
- </type>
<desc>
- <p>Reloads the driver named <c>Name</c> from a possibly
- different <c>Path</c> than was previously used. This
+ <p>Reloads the driver named <c><anno>Name</anno></c> from a possibly
+ different <c><anno>Path</anno></c> than was previously used. This
function is used in the code change <seealso marker="#scenarios">scenario</seealso> described in the
introduction.</p>
<p>If there are other <seealso marker="#users">users</seealso>
@@ -574,7 +553,7 @@
<p>If one wants to avoid hanging on open ports, one should use
the <seealso marker="#try_load/3">try_load/3</seealso>
function instead.</p>
- <p>The <c>Name</c> and <c>Path</c> parameters have exactly the
+ <p>The <c><anno>Name</anno></c> and <c><anno>Path</anno></c> parameters have exactly the
same meaning as when calling the plain <seealso marker="#load/2">load/2</seealso> function.</p>
<note>
<p>Avoid mixing
@@ -594,13 +573,8 @@
</desc>
</func>
<func>
- <name>reload_driver(Path, Name) -> ok | {error, ErrorDesc}</name>
+ <name name="reload_driver" arity="2"/>
<fsummary>Replace a driver</fsummary>
- <type>
- <v>Path = Name = string() | atom()</v>
- <v>ErrorDesc = pending_process | OpaqueError</v>
- <v>OpaqueError = term()</v>
- </type>
<desc>
<p>Works exactly as <seealso marker="#reload/2">reload/2</seealso>, but for drivers
loaded with the <seealso marker="#load_driver/2">load_driver/2</seealso> interface. </p>
@@ -1015,7 +989,7 @@
<c>{ok, pending_driver}</c> or <c>{ok, pending_process}</c>.</p>
</item>
</taglist>
- <p>The <c>pending_driver</c><c>MonitorOption</c> is by far
+ <p>The <c>pending_driver</c> <c>MonitorOption</c> is by far
the most useful and it has to be used to ensure that the
driver has really been unloaded and the ports closed
whenever the <c>kill_ports</c> option is used or the
@@ -1066,15 +1040,11 @@
</desc>
</func>
<func>
- <name>unload(Name) -> ok | {error, ErrorDesc}</name>
+ <name name="unload" arity="1"/>
<fsummary>Unload a driver</fsummary>
- <type>
- <v>Name = string() | atom()</v>
- <v>ErrorDesc = term()</v>
- </type>
<desc>
<p>Unloads, or at least dereferences the driver named
- <c>Name</c>. If the caller is the last <seealso marker="#users">user</seealso> of the driver, and there
+ <c><anno>Name</anno></c>. If the caller is the last <seealso marker="#users">user</seealso> of the driver, and there
are no more open ports using the driver, the driver will
actually get unloaded. In all other cases, actual unloading
will be delayed until all ports are closed and there are no
@@ -1084,7 +1054,7 @@
is no longer considered a user of the driver. For usage
scenarios, see the <seealso marker="#scenarios">description</seealso> in the beginning
of this document. </p>
- <p>The <c>ErrorDesc</c> returned is an opaque value to be
+ <p>The <c><anno>ErrorDesc</anno></c> returned is an opaque value to be
passed further on to the <seealso marker="#format_error/1">format_error/1</seealso>
function. For more control over the operation, use the
<seealso marker="#try_unload/2">try_unload/2</seealso>
@@ -1094,15 +1064,11 @@
</desc>
</func>
<func>
- <name>unload_driver(Name) -> ok | {error, ErrorDesc}</name>
+ <name name="unload_driver" arity="1"/>
<fsummary>Unload a driver</fsummary>
- <type>
- <v>Name = string() | atom()</v>
- <v>ErrorDesc = term()</v>
- </type>
<desc>
<p>Unloads, or at least dereferences the driver named
- <c>Name</c>. If the caller is the last <seealso marker="#users">user</seealso> of the driver, all
+ <c><anno>Name</anno></c>. If the caller is the last <seealso marker="#users">user</seealso> of the driver, all
remaining open ports using the driver will get killed with
the reason <c>driver_unloaded</c> and the driver will
eventually get unloaded.</p>
@@ -1112,7 +1078,7 @@
<seealso marker="#users">user</seealso>. For
usage scenarios, see the <seealso marker="#scenarios">description</seealso> in the beginning
of this document.</p>
- <p>The <c>ErrorDesc</c> returned is an opaque value to be
+ <p>The <c><anno>ErrorDesc</anno></c> returned is an opaque value to be
passed further on to the <seealso marker="#format_error/1">format_error/1</seealso>
function. For more control over the operation, use the
<seealso marker="#try_unload/2">try_unload/2</seealso>
@@ -1125,7 +1091,7 @@
<name>loaded_drivers() -> {ok, Drivers}</name>
<fsummary>List loaded drivers</fsummary>
<type>
- <v>Drivers = [Driver()]</v>
+ <v>Drivers = [Driver]</v>
<v>Driver = string()</v>
</type>
<desc>
@@ -1138,13 +1104,10 @@
</desc>
</func>
<func>
- <name>format_error(ErrorDesc) -> string()</name>
+ <name name="format_error" arity="1"/>
<fsummary>Format an error descriptor</fsummary>
- <type>
- <v>ErrorDesc -- see below</v>
- </type>
<desc>
- <p>Takes an <c>ErrorDesc</c> returned by load, unload or
+ <p>Takes an <c><anno>ErrorDesc</anno></c> returned by load, unload or
reload functions and returns a string which
describes the error or warning.</p>
<note>
diff --git a/lib/kernel/doc/src/error_handler.xml b/lib/kernel/doc/src/error_handler.xml
index 7f78322472..acbf9a2c6e 100644
--- a/lib/kernel/doc/src/error_handler.xml
+++ b/lib/kernel/doc/src/error_handler.xml
@@ -37,48 +37,44 @@
</description>
<funcs>
<func>
- <name>undefined_function(Module, Function, Args) -> term()</name>
+ <name name="undefined_function" arity="3"/>
<fsummary>Called when an undefined function is encountered</fsummary>
- <type>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- <d>A (possibly empty) list of arguments <c>Arg1,..,ArgN</c></d>
- </type>
+ <type_desc variable="Args">
+ A (possibly empty) list of arguments <c>Arg1,..,ArgN</c>
+ </type_desc>
<desc>
<p>This function is evaluated if a call is made to
- <c>Module:Function(Arg1,.., ArgN)</c> and
- <c>Module:Function/N</c> is undefined. Note that
+ <c><anno>Module</anno>:<anno>Function</anno>(Arg1,.., ArgN)</c> and
+ <c><anno>Module</anno>:<anno>Function</anno>/N</c> is undefined. Note that
<c>undefined_function/3</c> is evaluated inside the process
making the original call.</p>
- <p>If <c>Module</c> is interpreted, the interpreter is invoked
+ <p>If <c><anno>Module</anno></c> is interpreted, the interpreter is invoked
and the return value of the interpreted
- <c>Function(Arg1,.., ArgN)</c> call is returned.</p>
+ <c><anno>Function</anno>(Arg1,.., ArgN)</c> call is returned.</p>
<p>Otherwise, it returns, if possible, the value of
- <c>apply(Module, Function, Args)</c> after an attempt has been
- made to autoload <c>Module</c>. If this is not possible, the
- call to <c>Module:Function(Arg1,.., ArgN)</c> fails with
+ <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c> after an attempt has been
+ made to autoload <c><anno>Module</anno></c>. If this is not possible, the
+ call to <c><anno>Module</anno>:<anno>Function</anno>(Arg1,.., ArgN)</c> fails with
exit reason <c>undef</c>.</p>
</desc>
</func>
<func>
- <name>undefined_lambda(Module, Fun, Args) -> term()</name>
+ <name name="undefined_lambda" arity="3"/>
<fsummary>Called when an undefined lambda (fun) is encountered</fsummary>
- <type>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- <d>A (possibly empty) list of arguments <c>Arg1,..,ArgN</c></d>
- </type>
+ <type_desc variable="Args">
+ A (possibly empty) list of arguments <c>Arg1,..,ArgN</c>
+ </type_desc>
<desc>
<p>This function is evaluated if a call is made to
- <c>Fun(Arg1,.., ArgN)</c> when the module defining the fun is
+ <c><anno>Fun</anno>(Arg1,.., ArgN)</c> when the module defining the fun is
not loaded. The function is evaluated inside the process
making the original call.</p>
- <p>If <c>Module</c> is interpreted, the interpreter is invoked
+ <p>If <c><anno>Module</anno></c> is interpreted, the interpreter is invoked
and the return value of the interpreted
- <c>Fun(Arg1,.., ArgN)</c> call is returned.</p>
+ <c><anno>Fun</anno>(Arg1,.., ArgN)</c> call is returned.</p>
<p>Otherwise, it returns, if possible, the value of
- <c>apply(Fun, Args)</c> after an attempt has been made to
- autoload <c>Module</c>. If this is not possible, the call
+ <c>apply(<anno>Fun</anno>, <anno>Args</anno>)</c> after an attempt has been made to
+ autoload <c><anno>Module</anno></c>. If this is not possible, the call
fails with exit reason <c>undef</c>.</p>
</desc>
</func>
diff --git a/lib/kernel/doc/src/error_logger.xml b/lib/kernel/doc/src/error_logger.xml
index e107d9b746..2d95f96ac7 100644
--- a/lib/kernel/doc/src/error_logger.xml
+++ b/lib/kernel/doc/src/error_logger.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -65,19 +65,20 @@
be tagged as warnings or info. Tagging them as warnings may
require rewriting existing user defined event handlers.</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="report"/>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>error_msg(Format) -> ok</name>
- <name>error_msg(Format, Data) -> ok</name>
- <name>format(Format, Data) -> ok</name>
+ <name name="error_msg" arity="1"/>
+ <name name="error_msg" arity="2"/>
+ <name name="format" arity="2"/>
<fsummary>Send an standard error event to the error logger</fsummary>
- <type>
- <v>Format = string()</v>
- <v>Data = [term()]</v>
- </type>
<desc>
<p>Sends a standard error event to the error logger.
- The <c>Format</c> and <c>Data</c> arguments are the same as
+ The <c><anno>Format</anno></c> and <c><anno>Data</anno></c> arguments are the same as
the arguments of <c>io:format/2</c>. The event is handled by
the standard event handler.</p>
<pre>
@@ -94,12 +95,8 @@ ok</pre>
</desc>
</func>
<func>
- <name>error_report(Report) -> ok</name>
+ <name name="error_report" arity="1"/>
<fsummary>Send a standard error report event to the error logger</fsummary>
- <type>
- <v>Report = [{Tag, Data} | term()] | string() | term()</v>
- <v>&nbsp;Tag = Data = term()</v>
- </type>
<desc>
<p>Sends a standard error report event to the error logger.
The event is handled by the standard event handler.</p>
@@ -119,18 +116,13 @@ ok</pre>
</desc>
</func>
<func>
- <name>error_report(Type, Report) -> ok</name>
+ <name name="error_report" arity="2"/>
<fsummary>Send a user defined error report event to the error logger</fsummary>
- <type>
- <v>Type = term()</v>
- <v>Report = [{Tag, Data} | term()] | string() | term()</v>
- <v>&nbsp;Tag = Data = term()</v>
- </type>
<desc>
<p>Sends a user defined error report event to the error logger.
An event handler to handle the event is supposed to have been
added. The event is ignored by the standard event handler.</p>
- <p>It is recommended that <c>Report</c> follows the same
+ <p>It is recommended that <c><anno>Report</anno></c> follows the same
structure as for <c>error_report/1</c>.</p>
</desc>
</func>
@@ -174,16 +166,12 @@ ok</pre>
</desc>
</func>
<func>
- <name>warning_msg(Format) -> ok</name>
- <name>warning_msg(Format, Data) -> ok</name>
+ <name name="warning_msg" arity="1"/>
+ <name name="warning_msg" arity="2"/>
<fsummary>Send a standard warning event to the error logger</fsummary>
- <type>
- <v>Format = string()</v>
- <v>Data = [term()]</v>
- </type>
<desc>
<p>Sends a standard warning event to the error logger.
- The <c>Format</c> and <c>Data</c> arguments are the same as
+ The <c><anno>Format</anno></c> and <c><anno>Data</anno></c> arguments are the same as
the arguments of <c>io:format/2</c>. The event is handled by
the standard event handler. It is tagged either as an error,
warning or info, see
@@ -196,12 +184,8 @@ ok</pre>
</desc>
</func>
<func>
- <name>warning_report(Report) -> ok</name>
+ <name name="warning_report" arity="1"/>
<fsummary>Send a standard warning report event to the error logger</fsummary>
- <type>
- <v>Report = [{Tag, Data} | term()] | string() | term()</v>
- <v>&nbsp;Tag = Data = term()</v>
- </type>
<desc>
<p>Sends a standard warning report event to the error logger.
The event is handled by the standard event handler. It is
@@ -210,13 +194,8 @@ ok</pre>
</desc>
</func>
<func>
- <name>warning_report(Type, Report) -> ok</name>
+ <name name="warning_report" arity="2"/>
<fsummary>Send a user defined warning report event to the error logger</fsummary>
- <type>
- <v>Type = term()</v>
- <v>Report = [{Tag, Data} | term()] | string() | term()</v>
- <v>&nbsp;Tag = Data = term()</v>
- </type>
<desc>
<p>Sends a user defined warning report event to the error
logger. An event handler to handle the event is supposed to
@@ -227,16 +206,12 @@ ok</pre>
</desc>
</func>
<func>
- <name>info_msg(Format) -> ok</name>
- <name>info_msg(Format, Data) -> ok</name>
+ <name name="info_msg" arity="1"/>
+ <name name="info_msg" arity="2"/>
<fsummary>Send a standard information event to the error logger</fsummary>
- <type>
- <v>Format = string()</v>
- <v>Data = [term()]</v>
- </type>
<desc>
<p>Sends a standard information event to the error logger.
- The <c>Format</c> and <c>Data</c> arguments are the same as
+ The <c><anno>Format</anno></c> and <c><anno>Data</anno></c> arguments are the same as
the arguments of <c>io:format/2</c>. The event is handled by
the standard event handler.</p>
<pre>
@@ -253,12 +228,8 @@ ok</pre>
</desc>
</func>
<func>
- <name>info_report(Report) -> ok</name>
+ <name name="info_report" arity="1"/>
<fsummary>Send a standard information report event to the error logger</fsummary>
- <type>
- <v>Report = [{Tag, Data} | term()] | string() | term()</v>
- <v>&nbsp;Tag = Data = term()</v>
- </type>
<desc>
<p>Sends a standard information report event to the error
logger. The event is handled by the standard event handler.</p>
@@ -278,63 +249,49 @@ ok</pre>
</desc>
</func>
<func>
- <name>info_report(Type, Report) -> ok</name>
+ <name name="info_report" arity="2"/>
<fsummary>Send a user defined information report event to the error logger</fsummary>
- <type>
- <v>Type = term()</v>
- <v>Report = [{Tag, Data} | term()] | string() | term()</v>
- <v>&nbsp;Tag = Data = term()</v>
- </type>
<desc>
<p>Sends a user defined information report event to the error
logger. An event handler to handle the event is supposed to
have been added. The event is ignored by the standard event
handler.</p>
- <p>It is recommended that <c>Report</c> follows the same
+ <p>It is recommended that <c><anno>Report</anno></c> follows the same
structure as for <c>info_report/1</c>.</p>
</desc>
</func>
<func>
- <name>add_report_handler(Handler) -> Result</name>
- <name>add_report_handler(Handler, Args) -> Result</name>
+ <name name="add_report_handler" arity="1"/>
+ <name name="add_report_handler" arity="2"/>
<fsummary>Add an event handler to the error logger</fsummary>
- <type>
- <v>Handler, Args, Result -- see gen_event:add_handler/3</v>
- </type>
<desc>
<p>Adds a new event handler to the error logger. The event
handler must be implemented as a <c>gen_event</c> callback
module, see
<seealso marker="stdlib:gen_event">gen_event(3)</seealso>.</p>
- <p><c>Handler</c> is typically the name of the callback module
- and <c>Args</c> is an optional term (defaults to []) passed
- to the initialization callback function <c>Module:init/1</c>.
+ <p><c><anno>Handler</anno></c> is typically the name of the callback module
+ and <c><anno>Args</anno></c> is an optional term (defaults to []) passed
+ to the initialization callback function <c><anno>Handler</anno>:init/1</c>.
The function returns <c>ok</c> if successful.</p>
<p>The event handler must be able to handle the
<seealso marker="#events">events</seealso> described below.</p>
</desc>
</func>
<func>
- <name>delete_report_handler(Handler) -> Result</name>
+ <name name="delete_report_handler" arity="1"/>
<fsummary>Delete an event handler from the error logger</fsummary>
- <type>
- <v>Handler, Result -- see gen_event:delete_handler/3</v>
- </type>
<desc>
<p>Deletes an event handler from the error logger by calling
- <c>gen_event:delete_handler(error_logger, Handler, [])</c>,
+ <c>gen_event:delete_handler(error_logger, <anno>Handler</anno>, [])</c>,
see <seealso marker="stdlib:gen_event">gen_event(3)</seealso>.</p>
</desc>
</func>
<func>
- <name>tty(Flag) -> ok</name>
+ <name name="tty" arity="1"/>
<fsummary>Enable or disable printouts to the tty</fsummary>
- <type>
- <v>Flag = bool()</v>
- </type>
<desc>
- <p>Enables (<c>Flag == true</c>) or disables
- (<c>Flag == false</c>) printout of standard events to the tty.</p>
+ <p>Enables (<c><anno>Flag</anno> == true</c>) or disables
+ (<c><anno>Flag</anno> == false</c>) printout of standard events to the tty.</p>
<p>This is done by adding or deleting the standard event handler
for output to tty, thus calling this function overrides
the value of the Kernel <c>error_logger</c> configuration
@@ -342,13 +299,15 @@ ok</pre>
</desc>
</func>
<func>
- <name>logfile(Request) -> ok | Filename | {error, What}</name>
+ <name name="logfile" arity="1" clause_i="1"/>
+ <name name="logfile" arity="1" clause_i="2"/>
+ <name name="logfile" arity="1" clause_i="3"/>
+ <type variable="Filename"/>
+ <type variable="OpenReason" name_i="1"/>
+ <type variable="CloseReason" name_i="2"/>
+ <type variable="FilenameReason" name_i="3"/>
+ <type name="open_error"/>
<fsummary>Enable or disable error printouts to a file</fsummary>
- <type>
- <v>Request = {open, Filename} | close | filename</v>
- <v>&nbsp;Filename = atom() | string()</v>
- <v>What = allready_have_logfile | no_log_file | term()</v>
- </type>
<desc>
<p>Enables or disables printout of standard events to a file.</p>
<p>This is done by adding or deleting the standard event handler
@@ -361,22 +320,22 @@ ok</pre>
There can only be one active log file at a time.</p>
<p><c>Request</c> is one of:</p>
<taglist>
- <tag><c>{open, Filename}</c></tag>
+ <tag><c>{open, <anno>Filename</anno>}</c></tag>
<item>
- <p>Opens the log file <c>Filename</c>. Returns <c>ok</c> if
+ <p>Opens the log file <c><anno>Filename</anno></c>. Returns <c>ok</c> if
successful, or <c>{error, allready_have_logfile}</c> if
logging to file is already enabled, or an error tuple if
- another error occurred. For example, if <c>Filename</c>
+ another error occurred. For example, if <c><anno>Filename</anno></c>
could not be opened.</p>
</item>
<tag><c>close</c></tag>
<item>
<p>Closes the current log file. Returns <c>ok</c>, or
- <c>{error, What}</c>.</p>
+ <c>{error, module_not_found}</c>.</p>
</item>
<tag><c>filename</c></tag>
<item>
- <p>Returns the name of the log file <c>Filename</c>, or
+ <p>Returns the name of the log file <c><anno>Filename</anno></c>, or
<c>{error, no_log_file}</c> if logging to file is not
enabled.</p>
</item>
diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml
index 36fce464c5..7db20e6343 100644
--- a/lib/kernel/doc/src/file.xml
+++ b/lib/kernel/doc/src/file.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2010</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -60,11 +60,13 @@
converted, why the Unicode mode for file names is not default on
systems having completely transparent file naming.</p>
- <note>As of R14B01, the most basic file handling modules
- (<c>file</c>, <c>prim_file</c>, <c>filelib</c> and
- <c>filename</c>) accept raw file names, but the rest of OTP is not
- guaranteed to handle them, why Unicode file naming on systems
- where it is not default is still considered experimental.</note>
+ <note>
+ <p>As of R14B01, the most basic file handling modules
+ (<c>file</c>, <c>prim_file</c>, <c>filelib</c> and
+ <c>filename</c>) accept raw file names, but the rest of OTP is not
+ guaranteed to handle them, why Unicode file naming on systems
+ where it is not default is still considered experimental.</p>
+ </note>
<p>Raw file names is a new feature in OTP R14B01, which allows the
user to supply completely uninterpreted file names to the
@@ -93,47 +95,67 @@
is UTF-8...</p>
</description>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-iodata() = iolist() | binary()
- iolist() = [char() | binary() | iolist()]
-
-io_device()
- as returned by file:open/2, a process handling IO protocols
-
-name() = string() | atom() | DeepList | RawFilename
- DeepList = [char() | atom() | DeepList]
- RawFilename = binary()
- If VM is in unicode filename mode, string() and char() are allowed to be > 255.
- RawFilename is a filename not subject to Unicode translation, meaning that it
- can contain characters not conforming to the Unicode encoding expected from the
- filesystem (i.e. non-UTF-8 characters although the VM is started in Unicode
- filename mode).
-
-posix()
- an atom which is named from the POSIX error codes used in
- Unix, and in the runtime libraries of most C compilers
-
-ext_posix() = posix() | badarg
+ <datatypes>
+ <datatype>
+ <name name="deep_list"/>
+ </datatype>
+ <datatype>
+ <name name="fd"/>
+ </datatype>
+ <datatype>
+ <name name="filename"/>
+ </datatype>
+ <datatype>
+ <name name="io_device"/>
+ <desc>
+ <p>As returned by
+ <seealso marker="#open/2">file:open/2</seealso>,
+ a process handling IO protocols.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="name"/>
+ <desc>
+ <p>If VM is in Unicode filename mode, <c>string()</c> and <c>char()</c>
+ are allowed to be > 255.
+ <c><anno>RawFilename</anno></c> is a filename not subject to
+ Unicode translation,
+ meaning that it can contain characters not conforming to
+ the Unicode encoding expected from the filesystem
+ (i.e. non-UTF-8 characters although the VM is started
+ in Unicode filename mode).
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="posix"/>
+ <desc>
+ <p>An atom which is named from the POSIX error codes used in
+ Unix, and in the runtime libraries of most C compilers.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="date_time"/>
+ <desc>
+ <p>Must denote a valid date and time.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="file_info"/>
+ </datatype>
+ <datatype>
+ <name name="location"/>
+ </datatype>
+ <datatype>
+ <name name="mode"/>
+ </datatype>
+ </datatypes>
-time() = {{Year, Month, Day}, {Hour, Minute, Second}}
- Year = Month = Day = Hour = Minute = Second = int()
- Must denote a valid date and time</code>
- </section>
<funcs>
<func>
- <name>advise(IoDevice, Offset, Length, Advise) -> ok | {error, Reason}</name>
+ <name name="advise" arity="4"/>
<fsummary>Predeclare an access pattern for file data</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Offset = int()</v>
- <v>Length = int()</v>
- <v>Advise = posix_file_advise()</v>
- <v>posix_file_advise() = normal | sequential | random | no_reuse
- | will_need | dont_need</v>
- <v>Reason = ext_posix()</v>
- </type>
+ <type name="posix_file_advise"/>
<desc>
<p><c>advise/4</c> can be used to announce an intention to access file
data in a specific pattern in the future, thus allowing the
@@ -142,93 +164,58 @@ time() = {{Year, Month, Day}, {Hour, Minute, Second}}
</desc>
</func>
<func>
- <name>change_group(Filename, Gid) -> ok | {error, Reason}</name>
+ <name name="change_group" arity="2"/>
<fsummary>Change group of a file</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>Gid = int()</v>
- <v>Reason = ext_posix()</v>
- </type>
<desc>
<p>Changes group of a file. See
<seealso marker="#write_file_info/2">write_file_info/2</seealso>.</p>
</desc>
</func>
<func>
- <name>change_mode(Filename, Mode) -> ok | {error, Reason}</name>
+ <name name="change_mode" arity="2"/>
<fsummary>Change permissions of a file</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>Mode = int()</v>
- <v>Reason = ext_posix()</v>
- </type>
<desc>
<p>Changes permissions of a file. See
<seealso marker="#write_file_info/2">write_file_info/2</seealso>.</p>
</desc>
</func>
<func>
- <name>change_owner(Filename, Uid) -> ok | {error, Reason}</name>
+ <name name="change_owner" arity="2"/>
<fsummary>Change owner of a file</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>Uid = int()</v>
- <v>Reason = ext_posix()</v>
- </type>
<desc>
<p>Changes owner of a file. See
<seealso marker="#write_file_info/2">write_file_info/2</seealso>.</p>
</desc>
</func>
<func>
- <name>change_owner(Filename, Uid, Gid) -> ok | {error, Reason}</name>
+ <name name="change_owner" arity="3"/>
<fsummary>Change owner and group of a file</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>Uid = int()</v>
- <v>Gid = int()</v>
- <v>Reason = ext_posix()</v>
- </type>
<desc>
<p>Changes owner and group of a file. See
<seealso marker="#write_file_info/2">write_file_info/2</seealso>.</p>
</desc>
</func>
<func>
- <name>change_time(Filename, Mtime) -> ok | {error, Reason}</name>
+ <name name="change_time" arity="2"/>
<fsummary>Change the modification time of a file</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>Mtime = time()</v>
- <v>Reason = ext_posix()</v>
- </type>
<desc>
<p>Changes the modification and access times of a file. See
<seealso marker="#write_file_info/2">write_file_info/2</seealso>.</p>
</desc>
</func>
<func>
- <name>change_time(Filename, Mtime, Atime) -> ok | {error, Reason}</name>
+ <name name="change_time" arity="3"/>
<fsummary>Change the modification and last access time of a file</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>Mtime = Atime = time()</v>
- <v>Reason = ext_posix()</v>
- </type>
<desc>
<p>Changes the modification and last access times of a file. See
<seealso marker="#write_file_info/2">write_file_info/2</seealso>.</p>
</desc>
</func>
<func>
- <name>close(IoDevice) -> ok | {error, Reason}</name>
+ <name name="close" arity="1"/>
<fsummary>Close a file</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Reason = ext_posix() | terminated</v>
- </type>
<desc>
- <p>Closes the file referenced by <c>IoDevice</c>. It mostly
+ <p>Closes the file referenced by <c><anno>IoDevice</anno></c>. It mostly
returns <c>ok</c>, expect for some severe errors such as out
of memory.</p>
<p>Note that if the option <c>delayed_write</c> was
@@ -238,20 +225,13 @@ time() = {{Year, Month, Day}, {Hour, Minute, Second}}
</desc>
</func>
<func>
- <name>consult(Filename) -> {ok, Terms} | {error, Reason}</name>
+ <name name="consult" arity="1"/>
<fsummary>Read Erlang terms from a file</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>Terms = [term()]</v>
- <v>Reason = ext_posix() | terminated | system_limit
- | {Line, Mod, Term}</v>
- <v>&nbsp;Line, Mod, Term -- see below</v>
- </type>
<desc>
- <p>Reads Erlang terms, separated by '.', from <c>Filename</c>.
- Returns one of the following:</p>
+ <p>Reads Erlang terms, separated by '.', from
+ <c><anno>Filename</anno></c>. Returns one of the following:</p>
<taglist>
- <tag><c>{ok, Terms}</c></tag>
+ <tag><c>{ok, <anno>Terms</anno>}</c></tag>
<item>
<p>The file was successfully read.</p>
</item>
@@ -261,7 +241,8 @@ time() = {{Year, Month, Day}, {Hour, Minute, Second}}
See <seealso marker="#open/2">open/2</seealso> for a list
of typical error codes.</p>
</item>
- <tag><c>{error, {Line, Mod, Term}}</c></tag>
+ <tag><c>{error, {<anno>Line</anno>, <anno>Mod</anno>,
+ <anno>Term</anno>}}</c></tag>
<item>
<p>An error occurred when interpreting the Erlang terms in
the file. Use <c>format_error/1</c> to convert
@@ -270,62 +251,53 @@ time() = {{Year, Month, Day}, {Hour, Minute, Second}}
</item>
</taglist>
<p>Example:</p>
- <code type="none">
-f.txt: {person, "kalle", 25}.
+<code type="none">f.txt: {person, "kalle", 25}.
{person, "pelle", 30}.</code>
- <pre>
-1> <input>file:consult("f.txt").</input>
+<pre>1> <input>file:consult("f.txt").</input>
{ok,[{person,"kalle",25},{person,"pelle",30}]}</pre>
</desc>
</func>
<func>
- <name>copy(Source, Destination) -></name>
- <name>copy(Source, Destination, ByteCount) -> {ok, BytesCopied} | {error, Reason}</name>
+ <name name="copy" arity="2"/>
+ <name name="copy" arity="3"/>
<fsummary>Copy file contents</fsummary>
- <type>
- <v>Source = Destination = io_device() | Filename | {Filename, Modes}</v>
- <v>&nbsp;Filename = name()</v>
- <v>&nbsp;Modes = [Mode] -- see open/2</v>
- <v>ByteCount = int() >= 0 | infinity</v>
- <v>BytesCopied = int()</v>
- </type>
<desc>
- <p>Copies <c>ByteCount</c> bytes from <c>Source</c> to
- <c>Destination</c>. <c>Source</c> and <c>Destination</c> refer
+ <p>Copies <c><anno>ByteCount</anno></c> bytes from
+ <c><anno>Source</anno></c> to <c><anno>Destination</anno></c>.
+ <c><anno>Source</anno></c> and <c><anno>Destination</anno></c> refer
to either filenames or IO devices from e.g. <c>open/2</c>.
- <c>ByteCount</c> defaults <c>infinity</c>, denoting an
+ <c><anno>ByteCount</anno></c> defaults to <c>infinity</c>, denoting an
infinite number of bytes.</p>
- <p>The argument <c>Modes</c> is a list of possible modes, see
- <seealso marker="#open/2">open/2</seealso>, and defaults to
+ <p>The argument <c><anno>Modes</anno></c> is a list of possible modes,
+ see <seealso marker="#open/2">open/2</seealso>, and defaults to
[].</p>
- <p>If both <c>Source</c> and <c>Destination</c> refer to
+ <p>If both <c><anno>Source</anno></c> and
+ <c><anno>Destination</anno></c> refer to
filenames, the files are opened with <c>[read, binary]</c>
and <c>[write, binary]</c> prepended to their mode lists,
respectively, to optimize the copy.</p>
- <p>If <c>Source</c> refers to a filename, it is opened with
+ <p>If <c><anno>Source</anno></c> refers to a filename, it is opened with
<c>read</c> mode prepended to the mode list before the copy,
and closed when done.</p>
- <p>If <c>Destination</c> refers to a filename, it is opened
+ <p>If <c><anno>Destination</anno></c> refers to a filename, it is opened
with <c>write</c> mode prepended to the mode list before
the copy, and closed when done.</p>
- <p>Returns <c>{ok, BytesCopied}</c> where <c>BytesCopied</c> is
+ <p>Returns <c>{ok, <anno>BytesCopied</anno>}</c> where
+ <c><anno>BytesCopied</anno></c> is
the number of bytes that actually was copied, which may be
- less than <c>ByteCount</c> if end of file was encountered on
- the source. If the operation fails, <c>{error, Reason}</c> is
- returned.</p>
+ less than <c><anno>ByteCount</anno></c> if end of file was
+ encountered on the source. If the operation fails,
+ <c>{error, <anno>Reason</anno>}</c> is returned.</p>
<p>Typical error reasons: As for <c>open/2</c> if a file had to
be opened, and as for <c>read/2</c> and <c>write/2</c>.</p>
</desc>
</func>
<func>
- <name>del_dir(Dir) -> ok | {error, Reason}</name>
+ <name name="del_dir" arity="1"/>
<fsummary>Delete a directory</fsummary>
- <type>
- <v>Dir = name()</v>
- <v>Reason = ext_posix()</v>
- </type>
<desc>
- <p>Tries to delete the directory <c>Dir</c>. The directory must
+ <p>Tries to delete the directory <c><anno>Dir</anno></c>.
+ The directory must
be empty before it can be deleted. Returns <c>ok</c> if
successful.</p>
<p>Typical error reasons are:</p>
@@ -333,7 +305,7 @@ f.txt: {person, "kalle", 25}.
<tag><c>eacces</c></tag>
<item>
<p>Missing search or write permissions for the parent
- directories of <c>Dir</c>.</p>
+ directories of <c><anno>Dir</anno></c>.</p>
</item>
<tag><c>eexist</c></tag>
<item>
@@ -345,8 +317,8 @@ f.txt: {person, "kalle", 25}.
</item>
<tag><c>enotdir</c></tag>
<item>
- <p>A component of <c>Dir</c> is not a directory. On some
- platforms, <c>enoent</c> is returned instead.</p>
+ <p>A component of <c><anno>Dir</anno></c> is not a directory.
+ On some platforms, <c>enoent</c> is returned instead.</p>
</item>
<tag><c>einval</c></tag>
<item>
@@ -357,15 +329,11 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>delete(Filename) -> ok | {error, Reason}</name>
+ <name name="delete" arity="1"/>
<fsummary>Delete a file</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>Reason = ext_posix()</v>
- </type>
<desc>
- <p>Tries to delete the file <c>Filename</c>. Returns <c>ok</c>
- if successful.</p>
+ <p>Tries to delete the file <c><anno>Filename</anno></c>.
+ Returns <c>ok</c> if successful.</p>
<p>Typical error reasons are:</p>
<taglist>
<tag><c>enoent</c></tag>
@@ -387,30 +355,24 @@ f.txt: {person, "kalle", 25}.
</item>
<tag><c>einval</c></tag>
<item>
- <p><c>Filename</c> had an improper type, such as tuple.</p>
+ <p><c><anno>Filename</anno></c> had an improper type, such as tuple.</p>
</item>
</taglist>
<warning>
- <p>In a future release, a bad type for the <c>Filename</c>
- argument will probably generate an exception.</p>
- <p></p>
+ <p>In a future release, a bad type for the
+ <c><anno>Filename</anno></c> argument will probably generate
+ an exception.</p>
</warning>
</desc>
</func>
<func>
- <name>eval(Filename) -> ok | {error, Reason}</name>
+ <name name="eval" arity="1"/>
<fsummary>Evaluate Erlang expressions in a file</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>Reason = ext_posix() | terminated | system_limit
- | {Line, Mod, Term}</v>
- <v>&nbsp;Line, Mod, Term -- see below</v>
- </type>
<desc>
<p>Reads and evaluates Erlang expressions, separated by '.' (or
',', a sequence of expressions is also an expression), from
- <c>Filename</c>. The actual result of the evaluation is not
- returned; any expression sequence in the file must be there
+ <c><anno>Filename</anno></c>. The actual result of the evaluation
+ is not returned; any expression sequence in the file must be there
for its side effect. Returns one of the following:</p>
<taglist>
<tag><c>ok</c></tag>
@@ -422,7 +384,8 @@ f.txt: {person, "kalle", 25}.
<p>An error occurred when opening the file or reading it.
See <c>open/2</c> for a list of typical error codes.</p>
</item>
- <tag><c>{error, {Line, Mod, Term}}</c></tag>
+ <tag><c>{error, {<anno>Line</anno>, <anno>Mod</anno>,
+ <anno>Term</anno>}}</c></tag>
<item>
<p>An error occurred when interpreting the Erlang
expressions in the file. Use <c>format_error/1</c> to
@@ -433,18 +396,11 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>eval(Filename, Bindings) -> ok | {error, Reason}</name>
+ <name name="eval" arity="2"/>
<fsummary>Evaluate Erlang expressions in a file</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>Bindings -- see erl_eval(3)</v>
- <v>Reason = ext_posix() | terminated | system_limit
- | {Line, Mod, Term}</v>
- <v>&nbsp;Line, Mod, Term -- see eval/1</v>
- </type>
<desc>
<p>The same as <c>eval/1</c> but the variable bindings
- <c>Bindings</c> are used in the evaluation. See
+ <c><anno>Bindings</anno></c> are used in the evaluation. See
<seealso marker="stdlib:erl_eval">erl_eval(3)</seealso> about
variable bindings.</p>
</desc>
@@ -458,27 +414,19 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>format_error(Reason) -> Chars</name>
+ <name name="format_error" arity="1"/>
<fsummary>Return a descriptive string for an error reason</fsummary>
- <type>
- <v>Reason = atom() | {Line, Mod, Term}</v>
- <v>&nbsp;Line, Mod, Term -- see eval/1</v>
- <v>Chars = [char() | Chars]</v>
- </type>
<desc>
<p>Given the error reason returned by any function in this
module, returns a descriptive string of the error in English.</p>
</desc>
</func>
<func>
- <name>get_cwd() -> {ok, Dir} | {error, Reason}</name>
+ <name name="get_cwd" arity="0"/>
<fsummary>Get the current working directory</fsummary>
- <type>
- <v>Dir = string()</v>
- <v>Reason = posix()</v>
- </type>
<desc>
- <p>Returns <c>{ok, Dir}</c>, where <c>Dir</c> is the current
+ <p>Returns <c>{ok, <anno>Dir</anno>}</c>, where <c><anno>Dir</anno></c>
+ is the current
working directory of the file server.</p>
<note>
<p>In rare circumstances, this function can fail on Unix.
@@ -496,17 +444,14 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>get_cwd(Drive) -> {ok, Dir} | {error, Reason}</name>
+ <name name="get_cwd" arity="1"/>
<fsummary>Get the current working directory for the drive specified</fsummary>
- <type>
- <v>Drive = string() -- see below</v>
- <v>Dir = string()</v>
- <v>Reason = ext_posix()</v>
- </type>
<desc>
- <p><c>Drive</c> should be of the form "<c>Letter</c><c>:</c>",
- for example "c:". Returns <c>{ok, Dir}</c> or
- <c>{error, Reason}</c>, where <c>Dir</c> is the current
+ <p><c><anno>Drive</anno></c> should be of the form
+ "<c>Letter</c><c>:</c>",
+ for example "c:". Returns <c>{ok, <anno>Dir</anno>}</c> or
+ <c>{error, <anno>Reason</anno>}</c>, where <c><anno>Dir</anno></c>
+ is the current
working directory of the drive specified.</p>
<p>This function returns <c>{error, enotsup}</c> on platforms
which have no concept of current drive (Unix, for example).</p>
@@ -514,7 +459,7 @@ f.txt: {person, "kalle", 25}.
<taglist>
<tag><c>enotsup</c></tag>
<item>
- <p>The operating system have no concept of drives.</p>
+ <p>The operating system has no concept of drives.</p>
</item>
<tag><c>eacces</c></tag>
<item>
@@ -522,32 +467,27 @@ f.txt: {person, "kalle", 25}.
</item>
<tag><c>einval</c></tag>
<item>
- <p>The format of <c>Drive</c> is invalid.</p>
+ <p>The format of <c><anno>Drive</anno></c> is invalid.</p>
</item>
</taglist>
</desc>
</func>
<func>
- <name>list_dir(Dir) -> {ok, Filenames} | {error, Reason}</name>
+ <name name="list_dir" arity="1"/>
<fsummary>List files in a directory</fsummary>
- <type>
- <v>Dir = name()</v>
- <v>Filenames = [Filename]</v>
- <v>&nbsp;Filename = string()</v>
- <v>Reason = ext_posix()</v>
- </type>
<desc>
<p>Lists all the files in a directory. Returns
- <c>{ok, Filenames}</c> if successful. Otherwise, it returns
- <c>{error, Reason}</c>. <c>Filenames</c> is a list of
+ <c>{ok, <anno>Filenames</anno>}</c> if successful.
+ Otherwise, it returns <c>{error, <anno>Reason</anno>}</c>.
+ <c><anno>Filenames</anno></c> is a list of
the names of all the files in the directory. The names are
not sorted.</p>
<p>Typical error reasons are:</p>
<taglist>
<tag><c>eacces</c></tag>
<item>
- <p>Missing search or write permissions for <c>Dir</c> or
- one of its parent directories.</p>
+ <p>Missing search or write permissions for <c><anno>Dir</anno></c>
+ or one of its parent directories.</p>
</item>
<tag><c>enoent</c></tag>
<item>
@@ -557,14 +497,10 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>make_dir(Dir) -> ok | {error, Reason}</name>
+ <name name="make_dir" arity="1"/>
<fsummary>Make a directory</fsummary>
- <type>
- <v>Dir = name()</v>
- <v>Reason = ext_posix()</v>
- </type>
<desc>
- <p>Tries to create the directory <c>Dir</c>. Missing parent
+ <p>Tries to create the directory <c><anno>Dir</anno></c>. Missing parent
directories are <em>not</em> created. Returns <c>ok</c> if
successful.</p>
<p>Typical error reasons are:</p>
@@ -572,15 +508,15 @@ f.txt: {person, "kalle", 25}.
<tag><c>eacces</c></tag>
<item>
<p>Missing search or write permissions for the parent
- directories of <c>Dir</c>.</p>
+ directories of <c><anno>Dir</anno></c>.</p>
</item>
<tag><c>eexist</c></tag>
<item>
- <p>There is already a file or directory named <c>Dir</c>.</p>
+ <p>There is already a file or directory named <c><anno>Dir</anno></c>.</p>
</item>
<tag><c>enoent</c></tag>
<item>
- <p>A component of <c>Dir</c> does not exist.</p>
+ <p>A component of <c><anno>Dir</anno></c> does not exist.</p>
</item>
<tag><c>enospc</c></tag>
<item>
@@ -588,35 +524,33 @@ f.txt: {person, "kalle", 25}.
</item>
<tag><c>enotdir</c></tag>
<item>
- <p>A component of <c>Dir</c> is not a directory. On some
- platforms, <c>enoent</c> is returned instead.</p>
+ <p>A component of <c><anno>Dir</anno></c> is not a directory.
+ On some platforms, <c>enoent</c> is returned instead.</p>
</item>
</taglist>
</desc>
</func>
<func>
- <name>make_link(Existing, New) -> ok | {error, Reason}</name>
+ <name name="make_link" arity="2"/>
<fsummary>Make a hard link to a file</fsummary>
- <type>
- <v>Existing = New = name()</v>
- <v>Reason = ext_posix()</v>
- </type>
<desc>
- <p>Makes a hard link from <c>Existing</c> to <c>New</c>, on
+ <p>Makes a hard link from <c><anno>Existing</anno></c> to
+ <c><anno>New</anno></c>, on
platforms that support links (Unix). This function returns
<c>ok</c> if the link was successfully created, or
- <c>{error, Reason}</c>. On platforms that do not support
+ <c>{error, <anno>Reason</anno>}</c>. On platforms that do not support
links, <c>{error,enotsup}</c> is returned.</p>
<p>Typical error reasons:</p>
<taglist>
<tag><c>eacces</c></tag>
<item>
<p>Missing read or write permissions for the parent
- directories of <c>Existing</c> or <c>New</c>.</p>
+ directories of <c><anno>Existing</anno></c> or
+ <c><anno>New</anno></c>.</p>
</item>
<tag><c>eexist</c></tag>
<item>
- <p><c>New</c> already exists.</p>
+ <p><c><anno>New</anno></c> already exists.</p>
</item>
<tag><c>enotsup</c></tag>
<item>
@@ -626,30 +560,28 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>make_symlink(Name1, Name2) -> ok | {error, Reason}</name>
+ <name name="make_symlink" arity="2"/>
<fsummary>Make a symbolic link to a file or directory</fsummary>
- <type>
- <v>Name1 = Name2 = name()</v>
- <v>Reason = ext_posix()</v>
- </type>
<desc>
- <p>This function creates a symbolic link <c>Name2</c> to
- the file or directory <c>Name1</c>, on platforms that support
- symbolic links (most Unix systems). <c>Name1</c> need not
+ <p>This function creates a symbolic link <c><anno>Name2</anno></c> to
+ the file or directory <c><anno>Name1</anno></c>, on platforms that
+ support
+ symbolic links (most Unix systems). <c><anno>Name1</anno></c> need not
exist. This function returns <c>ok</c> if the link was
- successfully created, or <c>{error, Reason}</c>. On platforms
+ successfully created, or <c>{error, <anno>Reason</anno>}</c>.
+ On platforms
that do not support symbolic links, <c>{error, enotsup}</c>
is returned.</p>
<p>Typical error reasons:</p>
<taglist>
<tag><c>eacces</c></tag>
<item>
- <p>Missing read or write permissions for the parent
- directories of <c>Name1</c> or <c>Name2</c>.</p>
+ <p>Missing read or write permissions for the parent directories
+ of <c><anno>Name1</anno></c> or <c><anno>Name2</anno></c>.</p>
</item>
<tag><c>eexist</c></tag>
<item>
- <p><c>Name2</c> already exists.</p>
+ <p><c><anno>Name2</anno></c> already exists.</p>
</item>
<tag><c>enotsup</c></tag>
<item>
@@ -668,22 +600,12 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>open(Filename, Modes) -> {ok, IoDevice} | {error, Reason}</name>
+ <name name="open" arity="2"/>
<fsummary>Open a file</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>Modes = [Mode]</v>
- <v>&nbsp;Mode = read | write | append | exclusive | raw | binary | {delayed_write, Size, Delay} | delayed_write | {read_ahead, Size} | read_ahead | compressed | {encoding, Encoding}</v>
- <v>&nbsp;&nbsp;Size = Delay = int()</v>
- <v>&nbsp;&nbsp;Encoding = latin1 | unicode | utf8 | utf16 | {utf16, Endian} | utf32 | {utf32, Endian}</v>
- <v>&nbsp;&nbsp;&nbsp;&nbsp;Endian = big | little</v>
- <v>IoDevice = io_device()</v>
- <v>Reason = ext_posix() | system_limit</v>
- </type>
<desc>
- <p>Opens the file <c>Filename</c> in the mode determined by
- <c>Modes</c>, which may contain one or more of the following
- items:</p>
+ <p>Opens the file <c><anno>Filename</anno></c> in the mode determined
+ by <c><anno>Modes</anno></c>, which may contain one or more of the
+ following items:</p>
<taglist>
<tag><c>read</c></tag>
<item>
@@ -841,23 +763,23 @@ f.txt: {person, "kalle", 25}.
</taglist>
<p>Returns:</p>
<taglist>
- <tag><c>{ok, IoDevice}</c></tag>
+ <tag><c>{ok, <anno>IoDevice</anno>}</c></tag>
<item>
<p>The file has been opened in the requested mode.
- <c>IoDevice</c> is a reference to the file.</p>
+ <c><anno>IoDevice</anno></c> is a reference to the file.</p>
</item>
- <tag><c>{error, Reason}</c></tag>
+ <tag><c>{error, <anno>Reason</anno>}</c></tag>
<item>
<p>The file could not be opened.</p>
</item>
</taglist>
- <p><c>IoDevice</c> is really the pid of the process which
+ <p><c><anno>IoDevice</anno></c> is really the pid of the process which
handles the file. This process is linked to the process
which originally opened the file. If any process to which
- the <c>IoDevice</c> is linked terminates, the file will be
- closed and the process itself will be terminated.
- An <c>IoDevice</c> returned from this call can be used as an
- argument to the IO functions (see
+ the <c><anno>IoDevice</anno></c> is linked terminates, the file will
+ be closed and the process itself will be terminated.
+ An <c><anno>IoDevice</anno></c> returned from this call can be used
+ as an argument to the IO functions (see
<seealso marker="stdlib:io">io(3)</seealso>).</p>
<note>
<p>In previous versions of <c>file</c>, modes were given
@@ -897,34 +819,25 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>path_consult(Path, Filename) -> {ok, Terms, FullName} | {error, Reason}</name>
+ <name name="path_consult" arity="2"/>
<fsummary>Read Erlang terms from a file</fsummary>
- <type>
- <v>Path = [Dir]</v>
- <v>&nbsp;Dir = name()</v>
- <v>Filename = name()</v>
- <v>Terms = [term()]</v>
- <v>FullName = string()</v>
- <v>Reason = ext_posix() | terminated | system_limit
- | {Line, Mod, Term}</v>
- <v>&nbsp;Line, Mod, Term -- see below</v>
- </type>
<desc>
- <p>Searches the path <c>Path</c> (a list of directory names)
- until the file <c>Filename</c> is found. If <c>Filename</c>
- is an absolute filename, <c>Path</c> is ignored.
+ <p>Searches the path <c><anno>Path</anno></c> (a list of directory
+ names) until the file <c><anno>Filename</anno></c> is found.
+ If <c><anno>Filename</anno></c>
+ is an absolute filename, <c><anno>Path</anno></c> is ignored.
Then reads Erlang terms, separated by '.', from the file.
Returns one of the following:</p>
<taglist>
- <tag><c>{ok, Terms, FullName}</c></tag>
+ <tag><c>{ok, <anno>Terms</anno>, <anno>FullName</anno>}</c></tag>
<item>
- <p>The file was successfully read. <c>FullName</c> is
+ <p>The file was successfully read. <c><anno>FullName</anno></c> is
the full name of the file.</p>
</item>
<tag><c>{error, enoent}</c></tag>
<item>
<p>The file could not be found in any of the directories in
- <c>Path</c>.</p>
+ <c><anno>Path</anno></c>.</p>
</item>
<tag><c>{error, atom()}</c></tag>
<item>
@@ -932,7 +845,8 @@ f.txt: {person, "kalle", 25}.
See <seealso marker="#open/2">open/2</seealso> for a list
of typical error codes.</p>
</item>
- <tag><c>{error, {Line, Mod, Term}}</c></tag>
+ <tag><c>{error, {<anno>Line</anno>, <anno>Mod</anno>,
+ <anno>Term</anno>}}</c></tag>
<item>
<p>An error occurred when interpreting the Erlang terms in
the file. Use <c>format_error/1</c> to convert
@@ -943,36 +857,28 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>path_eval(Path, Filename) -> {ok, FullName} | {error, Reason}</name>
+ <name name="path_eval" arity="2"/>
<fsummary>Evaluate Erlang expressions in a file</fsummary>
- <type>
- <v>Path = [Dir]</v>
- <v>&nbsp;Dir = name()</v>
- <v>Filename = name()</v>
- <v>FullName = string()</v>
- <v>Reason = ext_posix() | terminated | system_limit
- | {Line, Mod, Term}</v>
- <v>&nbsp;Line, Mod, Term -- see below</v>
- </type>
<desc>
- <p>Searches the path <c>Path</c> (a list of directory names)
- until the file <c>Filename</c> is found. If <c>Filename</c>
- is an absolute file name, <c>Path</c> is ignored. Then reads
+ <p>Searches the path <c><anno>Path</anno></c> (a list of directory
+ names) until the file <c><anno>Filename</anno></c> is found.
+ If <c><anno>Filename</anno></c> is an absolute file name,
+ <c><anno>Path</anno></c> is ignored. Then reads
and evaluates Erlang expressions, separated by '.' (or ',', a
sequence of expressions is also an expression), from the file.
The actual result of evaluation is not returned; any
expression sequence in the file must be there for its side
effect. Returns one of the following:</p>
<taglist>
- <tag><c>{ok, FullName}</c></tag>
+ <tag><c>{ok, <anno>FullName</anno>}</c></tag>
<item>
- <p>The file was read and evaluated. <c>FullName</c> is
+ <p>The file was read and evaluated. <c><anno>FullName</anno></c> is
the full name of the file.</p>
</item>
<tag><c>{error, enoent}</c></tag>
<item>
<p>The file could not be found in any of the directories in
- <c>Path</c>.</p>
+ <c><anno>Path</anno></c>.</p>
</item>
<tag><c>{error, atom()}</c></tag>
<item>
@@ -980,7 +886,8 @@ f.txt: {person, "kalle", 25}.
See <seealso marker="#open/2">open/2</seealso> for a list
of typical error codes.</p>
</item>
- <tag><c>{error, {Line, Mod, Term}}</c></tag>
+ <tag><c>{error, {<anno>Line</anno>, <anno>Mod</anno>,
+ <anno>Term</anno>}}</c></tag>
<item>
<p>An error occurred when interpreting the Erlang
expressions in the file. Use <c>format_error/1</c> to
@@ -991,34 +898,26 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>path_open(Path, Filename, Modes) -> {ok, IoDevice, FullName} | {error, Reason}</name>
+ <name name="path_open" arity="3"/>
<fsummary>Open a file</fsummary>
- <type>
- <v>Path = [Dir]</v>
- <v>&nbsp;Dir = name()</v>
- <v>Filename = name()</v>
- <v>Modes = [Mode] -- see open/2</v>
- <v>IoDevice = io_device()</v>
- <v>FullName = string()</v>
- <v>Reason = ext_posix() | system_limit</v>
- </type>
<desc>
- <p>Searches the path <c>Path</c> (a list of directory names)
- until the file <c>Filename</c> is found. If <c>Filename</c>
- is an absolute file name, <c>Path</c> is ignored.
- Then opens the file in the mode determined by <c>Modes</c>.
+ <p>Searches the path <c><anno>Path</anno></c> (a list of directory
+ names) until the file <c><anno>Filename</anno></c> is found.
+ If <c><anno>Filename</anno></c>
+ is an absolute file name, <c><anno>Path</anno></c> is ignored.
+ Then opens the file in the mode determined by <c><anno>Modes</anno></c>.
Returns one of the following:</p>
<taglist>
- <tag><c>{ok, IoDevice, FullName}</c></tag>
+ <tag><c>{ok, <anno>IoDevice</anno>, <anno>FullName</anno>}</c></tag>
<item>
<p>The file has been opened in the requested mode.
- <c>IoDevice</c> is a reference to the file and
- <c>FullName</c> is the full name of the file.</p>
+ <c><anno>IoDevice</anno></c> is a reference to the file and
+ <c><anno>FullName</anno></c> is the full name of the file.</p>
</item>
<tag><c>{error, enoent}</c></tag>
<item>
<p>The file could not be found in any of the directories in
- <c>Path</c>.</p>
+ <c><anno>Path</anno></c>.</p>
</item>
<tag><c>{error, atom()}</c></tag>
<item>
@@ -1028,36 +927,27 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>path_script(Path, Filename) -> {ok, Value, FullName} | {error, Reason}</name>
+ <name name="path_script" arity="2"/>
<fsummary>Evaluate and return the value of Erlang expressions in a file</fsummary>
- <type>
- <v>Path = [Dir]</v>
- <v>&nbsp;Dir = name()</v>
- <v>Filename = name()</v>
- <v>Value = term()</v>
- <v>FullName = string()</v>
- <v>Reason = ext_posix() | terminated | system_limit
- | {Line, Mod, Term}</v>
- <v>&nbsp;Line, Mod, Term -- see below</v>
- </type>
<desc>
- <p>Searches the path <c>Path</c> (a list of directory names)
- until the file <c>Filename</c> is found. If <c>Filename</c>
- is an absolute file name, <c>Path</c> is ignored. Then reads
+ <p>Searches the path <c><anno>Path</anno></c> (a list of directory
+ names) until the file <c><anno>Filename</anno></c> is found.
+ If <c><anno>Filename</anno></c> is an absolute file name,
+ <c><anno>Path</anno></c> is ignored. Then reads
and evaluates Erlang expressions, separated by '.' (or ',', a
sequence of expressions is also an expression), from the file.
Returns one of the following:</p>
<taglist>
- <tag><c>{ok, Value, FullName}</c></tag>
+ <tag><c>{ok, <anno>Value</anno>, <anno>FullName</anno>}</c></tag>
<item>
- <p>The file was read and evaluated. <c>FullName</c> is
- the full name of the file and <c>Value</c> the value of
+ <p>The file was read and evaluated. <c><anno>FullName</anno></c> is
+ the full name of the file and <c><anno>Value</anno></c> the value of
the last expression.</p>
</item>
<tag><c>{error, enoent}</c></tag>
<item>
<p>The file could not be found in any of the directories in
- <c>Path</c>.</p>
+ <c><anno>Path</anno></c>.</p>
</item>
<tag><c>{error, atom()}</c></tag>
<item>
@@ -1065,7 +955,8 @@ f.txt: {person, "kalle", 25}.
See <seealso marker="#open/2">open/2</seealso> for a list
of typical error codes.</p>
</item>
- <tag><c>{error, {Line, Mod, Term}}</c></tag>
+ <tag><c>{error, {<anno>Line</anno>, <anno>Mod</anno>,
+ <anno>Term</anno>}}</c></tag>
<item>
<p>An error occurred when interpreting the Erlang
expressions in the file. Use <c>format_error/1</c> to
@@ -1076,42 +967,28 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>path_script(Path, Filename, Bindings) -> {ok, Value, FullName} | {error, Reason}</name>
+ <name name="path_script" arity="3"/>
<fsummary>Evaluate and return the value of Erlang expressions in a file</fsummary>
- <type>
- <v>Path = [Dir]</v>
- <v>&nbsp;Dir = name()</v>
- <v>Filename = name()</v>
- <v>Bindings -- see erl_eval(3)</v>
- <v>Value = term()</v>
- <v>FullName = string()</v>
- <v>Reason = posix() | terminated | system_limit
- | {Line, Mod, Term}</v>
- <v>&nbsp;Line, Mod, Term -- see path_script/2</v>
- </type>
<desc>
<p>The same as <c>path_script/2</c> but the variable bindings
- <c>Bindings</c> are used in the evaluation. See
+ <c><anno>Bindings</anno></c> are used in the evaluation. See
<seealso marker="stdlib:erl_eval">erl_eval(3)</seealso> about
variable bindings.</p>
</desc>
</func>
<func>
- <name>pid2name(Pid) -> string() | undefined</name>
+ <name name="pid2name" arity="1"/>
<fsummary>Return the name of the file handled by a pid</fsummary>
- <type>
- <v>Pid = pid()</v>
- </type>
<desc>
- <p>If <c>Pid</c> is an IO device, that is, a pid returned from
+ <p>If <c><anno>Pid</anno></c> is an IO device, that is, a pid returned from
<c>open/2</c>, this function returns the filename, or rather:</p>
<taglist>
- <tag><c>{ok, Filename}</c></tag>
+ <tag><c>{ok, <anno>Filename</anno>}</c></tag>
<item>
<p>If this node's file server is not a slave, the file was
opened by this node's file server, (this implies that
- <c>Pid</c> must be a local pid) and the file is not
- closed. <c>Filename</c> is the filename in flat string
+ <c><anno>Pid</anno></c> must be a local pid) and the file is not
+ closed. <c><anno>Filename</anno></c> is the filename in flat string
format.</p>
</item>
<tag><c>undefined</c></tag>
@@ -1125,21 +1002,15 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>position(IoDevice, Location) -> {ok, NewPosition} | {error, Reason}</name>
+ <name name="position" arity="2"/>
<fsummary>Set position in a file</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Location = Offset | {bof, Offset} | {cur, Offset} | {eof, Offset} | bof | cur | eof</v>
- <v>&nbsp;Offset = int()</v>
- <v>NewPosition = int()</v>
- <v>Reason = ext_posix() | terminated</v>
- </type>
<desc>
- <p>Sets the position of the file referenced by <c>IoDevice</c>
- to <c>Location</c>. Returns <c>{ok, NewPosition}</c> (as
+ <p>Sets the position of the file referenced by <c><anno>IoDevice</anno></c>
+ to <c><anno>Location</anno></c>. Returns
+ <c>{ok, <anno>NewPosition</anno>}</c> (as
absolute offset) if successful, otherwise
- <c>{error, Reason}</c>. <c>Location</c> is one of
- the following:</p>
+ <c>{error, <anno>Reason</anno>}</c>. <c><anno>Location</anno></c> is
+ one of the following:</p>
<taglist>
<tag><c>Offset</c></tag>
<item>
@@ -1167,7 +1038,8 @@ f.txt: {person, "kalle", 25}.
<taglist>
<tag><c>einval</c></tag>
<item>
- <p>Either <c>Location</c> was illegal, or it evaluated to a
+ <p>Either <c><anno>Location</anno></c> was illegal, or it
+ evaluated to a
negative offset in the file. Note that if the resulting
position is a negative value, the result is an error, and
after the call the file position is undefined.</p>
@@ -1176,22 +1048,14 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>pread(IoDevice, LocNums) -> {ok, DataL} | eof | {error, Reason}</name>
+ <name name="pread" arity="2"/>
<fsummary>Read from a file at certain positions</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>LocNums = [{Location, Number}]</v>
- <v>&nbsp;Location -- see position/2</v>
- <v>&nbsp;Number = int()</v>
- <v>DataL = [Data]</v>
- <v>&nbsp;Data = [char()] | binary()</v>
- <v>Reason = ext_posix() | terminated</v>
- </type>
<desc>
<p>Performs a sequence of <c>pread/3</c> in one operation,
which is more efficient than calling them one at a time.
- Returns <c>{ok, [Data, ...]}</c> or <c>{error, Reason}</c>,
- where each <c>Data</c>, the result of the corresponding
+ Returns <c>{ok, [<anno>Data</anno>, ...]}</c> or
+ <c>{error, <anno>Reason</anno>}</c>,
+ where each <c><anno>Data</anno></c>, the result of the corresponding
<c>pread</c>, is either a list or a binary depending on
the mode of the file, or <c>eof</c> if the requested position
was beyond end of file.</p>
@@ -1199,76 +1063,53 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>pread(IoDevice, Location, Number) -> {ok, Data} | eof | {error, Reason}</name>
+ <name name="pread" arity="3"/>
<fsummary>Read from a file at a certain position</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Location -- see position/2</v>
- <v>Number = int()</v>
- <v>Data = [char()] | binary()</v>
- <v>Reason = ext_posix() | terminated</v>
- </type>
<desc>
<p>Combines <c>position/2</c> and <c>read/2</c> in one
operation, which is more efficient than calling them one at a
- time. If <c>IoDevice</c> has been opened in raw mode, some
- restrictions apply: <c>Location</c> is only allowed to be an
+ time. If <c><anno>IoDevice</anno></c> has been opened in raw mode,
+ some restrictions apply: <c><anno>Location</anno></c> is only allowed
+ to be an
integer; and the current position of the file is undefined
after the operation.</p>
<p>As the position is given as a byte-offset, special caution has to be taken when working with files where <c>encoding</c> is set to something else than <c>latin1</c>, as not every byte position will be a valid character boundary on such a file.</p>
</desc>
</func>
<func>
- <name>pwrite(IoDevice, LocBytes) -> ok | {error, {N, Reason}}</name>
+ <name name="pwrite" arity="2"/>
<fsummary>Write to a file at certain positions</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>LocBytes = [{Location, Bytes}]</v>
- <v>&nbsp;Location -- see position/2</v>
- <v>&nbsp;Bytes = iodata()</v>
- <v>N = int()</v>
- <v>Reason = ext_posix() | terminated</v>
- </type>
<desc>
<p>Performs a sequence of <c>pwrite/3</c> in one operation,
which is more efficient than calling them one at a time.
- Returns <c>ok</c> or <c>{error, {N, Reason}}</c>, where
- <c>N</c> is the number of successful writes that was done
+ Returns <c>ok</c> or <c>{error, {<anno>N</anno>,
+ <anno>Reason</anno>}}</c>, where
+ <c><anno>N</anno></c> is the number of successful writes that was done
before the failure.</p>
<p>When positioning in a file with other <c>encoding</c> than <c>latin1</c>, caution must be taken to set the position on a correct character boundary, see <seealso marker="#position/2">position/2</seealso> for details.</p>
</desc>
</func>
<func>
- <name>pwrite(IoDevice, Location, Bytes) -> ok | {error, Reason}</name>
+ <name name="pwrite" arity="3"/>
<fsummary>Write to a file at a certain position</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Location -- see position/2</v>
- <v>Bytes = iodata()</v>
- <v>Reason = ext_posix() | terminated</v>
- </type>
<desc>
<p>Combines <c>position/2</c> and <c>write/2</c> in one
operation, which is more efficient than calling them one at a
- time. If <c>IoDevice</c> has been opened in raw mode, some
- restrictions apply: <c>Location</c> is only allowed to be an
+ time. If <c><anno>IoDevice</anno></c> has been opened in raw mode,
+ some restrictions apply: <c><anno>Location</anno></c> is only allowed
+ to be an
integer; and the current position of the file is undefined
after the operation.</p>
<p>When positioning in a file with other <c>encoding</c> than <c>latin1</c>, caution must be taken to set the position on a correct character boundary, see <seealso marker="#position/2">position/2</seealso> for details.</p>
</desc>
</func>
<func>
- <name>read(IoDevice, Number) -> {ok, Data} | eof | {error, Reason}</name>
+ <name name="read" arity="2"/>
<fsummary>Read from a file</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Number = int()</v>
- <v>Data = [char()] | binary()</v>
- <v>Reason = ext_posix() | terminated</v>
- </type>
<desc>
- <p>Reads <c>Number</c> bytes/characters from the file referenced by
- <c>IoDevice</c>. The functions <c>read/2</c>, <c>pread/3</c>
+ <p>Reads <c><anno>Number</anno></c> bytes/characters from the file
+ referenced by <c><anno>IoDevice</anno></c>. The functions
+ <c>read/2</c>, <c>pread/3</c>
and <c>read_line/1</c> are the only ways to read from a file
opened in raw mode (although they work for normally opened
files, too).</p>
@@ -1276,7 +1117,7 @@ f.txt: {person, "kalle", 25}.
<p>Also if <c>encoding</c> is set to something else than <c>latin1</c>, the <c>read/3</c> call will fail if the data contains characters larger than 255, why the <seealso marker="stdlib:io">io(3)</seealso> module is to be preferred when reading such a file.</p>
<p>The function returns:</p>
<taglist>
- <tag><c>{ok, Data}</c></tag>
+ <tag><c>{ok, <anno>Data</anno>}</c></tag>
<item>
<p>If the file was opened in binary mode, the read bytes are
returned in a binary, otherwise in a list. The list or
@@ -1285,10 +1126,10 @@ f.txt: {person, "kalle", 25}.
</item>
<tag><c>eof</c></tag>
<item>
- <p>Returned if <c>Number>0</c> and end of file was reached
- before anything at all could be read.</p>
+ <p>Returned if <c><anno>Number</anno>>0</c> and end of file was
+ reached before anything at all could be read.</p>
</item>
- <tag><c>{error, Reason}</c></tag>
+ <tag><c>{error, <anno>Reason</anno>}</c></tag>
<item>
<p>An error occurred.</p>
</item>
@@ -1307,17 +1148,14 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>read_file(Filename) -> {ok, Binary} | {error, Reason}</name>
+ <name name="read_file" arity="1"/>
<fsummary>Read a file</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>Binary = binary()</v>
- <v>Reason = ext_posix() | terminated | system_limit</v>
- </type>
<desc>
- <p>Returns <c>{ok, Binary}</c>, where <c>Binary</c> is a binary
- data object that contains the contents of <c>Filename</c>, or
- <c>{error, Reason}</c> if an error occurs.</p>
+ <p>Returns <c>{ok, <anno>Binary</anno>}</c>, where
+ <c><anno>Binary</anno></c> is a binary
+ data object that contains the contents of
+ <c><anno>Filename</anno></c>, or
+ <c>{error, <anno>Reason</anno>}</c> if an error occurs.</p>
<p>Typical error reasons:</p>
<taglist>
<tag><c>enoent</c></tag>
@@ -1346,17 +1184,13 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>read_file_info(Filename) -> {ok, FileInfo} | {error, Reason}</name>
+ <name name="read_file_info" arity="1"/>
<fsummary>Get information about a file</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>FileInfo = #file_info{}</v>
- <v>Reason = ext_posix()</v>
- </type>
<desc>
<p>Retrieves information about a file. Returns
- <c>{ok, FileInfo}</c> if successful, otherwise
- <c>{error, Reason}</c>. <c>FileInfo</c> is a record
+ <c>{ok, <anno>FileInfo</anno>}</c> if successful, otherwise
+ <c>{error, <anno>Reason</anno>}</c>. <c><anno>FileInfo</anno></c>
+ is a record
<c>file_info</c>, defined in the Kernel include file
<c>file.hrl</c>. Include the following directive in the module
from which the function is called:</p>
@@ -1364,7 +1198,7 @@ f.txt: {person, "kalle", 25}.
-include_lib("kernel/include/file.hrl").</code>
<p>The record <c>file_info</c> contains the following fields.</p>
<taglist>
- <tag><c>size = int()</c></tag>
+ <tag><c>size = integer()</c></tag>
<item>
<p>Size of file in bytes.</p>
</item>
@@ -1376,22 +1210,22 @@ f.txt: {person, "kalle", 25}.
<item>
<p>The current system access to the file.</p>
</item>
- <tag><c>atime = time()</c></tag>
+ <tag><c>atime = <seealso marker="#type-date_time">date_time()</seealso></c></tag>
<item>
<p>The last (local) time the file was read.</p>
</item>
- <tag><c>mtime = time()</c></tag>
+ <tag><c>mtime = <seealso marker="#type-date_time">date_time()</seealso></c></tag>
<item>
<p>The last (local) time the file was written.</p>
</item>
- <tag><c>ctime = time()</c></tag>
+ <tag><c>ctime = <seealso marker="#type-date_time">date_time()</seealso></c></tag>
<item>
<p>The interpretation of this time field depends on
the operating system. On Unix, it is the last time
the file or the inode was changed. In Windows, it is
the create time.</p>
</item>
- <tag><c>mode = int()</c></tag>
+ <tag><c>mode = integer()</c></tag>
<item>
<p>The file permissions as the sum of the following bit
values:</p>
@@ -1422,33 +1256,33 @@ f.txt: {person, "kalle", 25}.
<p>On Unix platforms, other bits than those listed above
may be set.</p>
</item>
- <tag><c>links = int()</c></tag>
+ <tag><c>links = integer()</c></tag>
<item>
<p>Number of links to the file (this will always be 1 for
file systems which have no concept of links).</p>
</item>
- <tag><c>major_device = int()</c></tag>
+ <tag><c>major_device = integer()</c></tag>
<item>
<p>Identifies the file system where the file is located.
In Windows, the number indicates a drive as follows:
0 means A:, 1 means B:, and so on.</p>
</item>
- <tag><c>minor_device = int()</c></tag>
+ <tag><c>minor_device = integer()</c></tag>
<item>
<p>Only valid for character devices on Unix. In all other
cases, this field is zero.</p>
</item>
- <tag><c>inode = int()</c></tag>
+ <tag><c>inode = integer()</c></tag>
<item>
<p>Gives the <c>inode</c> number. On non-Unix file systems,
this field will be zero.</p>
</item>
- <tag><c>uid = int()</c></tag>
+ <tag><c>uid = integer()</c></tag>
<item>
<p>Indicates the owner of the file. Will be zero for
non-Unix file systems.</p>
</item>
- <tag><c>gid = int()</c></tag>
+ <tag><c>gid = integer()</c></tag>
<item>
<p>Gives the group that the owner of the file belongs to.
Will be zero for non-Unix file systems.</p>
@@ -1474,21 +1308,16 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>read_line(IoDevice) -> {ok, Data} | eof | {error, Reason}</name>
+ <name name="read_line" arity="1"/>
<fsummary>Read a line from a file</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Data = [char()] | binary()</v>
- <v>Reason = ext_posix() | terminated</v>
- </type>
<desc>
<p>Reads a line of bytes/characters from the file referenced by
- <c>IoDevice</c>. Lines are defined to be delimited by the linefeed (LF, <c>\n</c>) character, but any carriage return (CR, <c>\r</c>) followed by a newline is also treated as a single LF character (the carriage return is silently ignored). The line is returned <em>including</em> the LF, but excluding any CR immediately followed by a LF. This behaviour is consistent with the behaviour of <seealso marker="stdlib:io#get_line/2">io:get_line/2</seealso>. If end of file is reached without any LF ending the last line, a line with no trailing LF is returned.</p>
+ <c><anno>IoDevice</anno></c>. Lines are defined to be delimited by the linefeed (LF, <c>\n</c>) character, but any carriage return (CR, <c>\r</c>) followed by a newline is also treated as a single LF character (the carriage return is silently ignored). The line is returned <em>including</em> the LF, but excluding any CR immediately followed by a LF. This behaviour is consistent with the behaviour of <seealso marker="stdlib:io#get_line/2">io:get_line/2</seealso>. If end of file is reached without any LF ending the last line, a line with no trailing LF is returned.</p>
<p>The function can be used on files opened in <c>raw</c> mode. It is however inefficient to use it on <c>raw</c> files if the file is not opened with the option <c>{read_ahead, Size}</c> specified, why combining <c>raw</c> and <c>{read_ahead, Size}</c> is highly recommended when opening a text file for raw line oriented reading.</p>
<p>If <c>encoding</c> is set to something else than <c>latin1</c>, the <c>read_line/1</c> call will fail if the data contains characters larger than 255, why the <seealso marker="stdlib:io">io(3)</seealso> module is to be preferred when reading such a file.</p>
<p>The function returns:</p>
<taglist>
- <tag><c>{ok, Data}</c></tag>
+ <tag><c>{ok, <anno>Data</anno>}</c></tag>
<item>
<p>One line from the file is returned, including the trailing LF, but with CRLF sequences replaced by a single LF (see above).</p>
<p>If the file was opened in binary mode, the read bytes are
@@ -1499,7 +1328,7 @@ f.txt: {person, "kalle", 25}.
<p>Returned if end of file was reached
before anything at all could be read.</p>
</item>
- <tag><c>{error, Reason}</c></tag>
+ <tag><c>{error, <anno>Reason</anno>}</c></tag>
<item>
<p>An error occurred.</p>
</item>
@@ -1518,23 +1347,19 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>read_link(Name) -> {ok, Filename} | {error, Reason}</name>
+ <name name="read_link" arity="1"/>
<fsummary>See what a link is pointing to</fsummary>
- <type>
- <v>Name = name()</v>
- <v>Filename = string()</v>
- <v>Reason = ext_posix()</v>
- </type>
<desc>
- <p>This function returns <c>{ok, Filename}</c> if <c>Name</c>
- refers to a symbolic link or <c>{error, Reason}</c> otherwise.
+ <p>This function returns <c>{ok, <anno>Filename</anno>}</c> if
+ <c><anno>Name</anno></c> refers to a symbolic link or
+ <c>{error, <anno>Reason</anno>}</c> otherwise.
On platforms that do not support symbolic links, the return
value will be <c>{error,enotsup}</c>.</p>
<p>Typical error reasons:</p>
<taglist>
<tag><c>einval</c></tag>
<item>
- <p><c>Linkname</c> does not refer to a symbolic link.</p>
+ <p><c><anno>Name</anno></c> does not refer to a symbolic link.</p>
</item>
<tag><c>enoent</c></tag>
<item>
@@ -1548,34 +1373,26 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>read_link_info(Name) -> {ok, FileInfo} | {error, Reason}</name>
+ <name name="read_link_info" arity="1"/>
<fsummary>Get information about a link or file</fsummary>
- <type>
- <v>Name = name()</v>
- <v>FileInfo = #file_info{}, see read_file_info/1</v>
- <v>Reason = ext_posix()</v>
- </type>
<desc>
<p>This function works like <c>read_file_info/1</c>, except that
- if <c>Name</c> is a symbolic link, information about the link
- will be returned in the <c>file_info</c> record and
+ if <c><anno>Name</anno></c> is a symbolic link, information about
+ the link will be returned in the <c>file_info</c> record and
the <c>type</c> field of the record will be set to
<c>symlink</c>.</p>
- <p>If <c>Name</c> is not a symbolic link, this function returns
+ <p>If <c><anno>Name</anno></c> is not a symbolic link, this function returns
exactly the same result as <c>read_file_info/1</c>.
On platforms that do not support symbolic links, this function
is always equivalent to <c>read_file_info/1</c>.</p>
</desc>
</func>
<func>
- <name>rename(Source, Destination) -> ok | {error, Reason}</name>
+ <name name="rename" arity="2"/>
<fsummary>Rename a file</fsummary>
- <type>
- <v>Source = Destination = name()</v>
- <v>Reason = ext_posix()</v>
- </type>
<desc>
- <p>Tries to rename the file <c>Source</c> to <c>Destination</c>.
+ <p>Tries to rename the file <c><anno>Source</anno></c> to
+ <c><anno>Destination</anno></c>.
It can be used to move files (and directories) between
directories, but it is not sufficient to specify
the destination only. The destination file name must also be
@@ -1593,25 +1410,28 @@ f.txt: {person, "kalle", 25}.
<tag><c>eacces</c></tag>
<item>
<p>Missing read or write permissions for the parent
- directories of <c>Source</c> or <c>Destination</c>. On
+ directories of <c><anno>Source</anno></c> or
+ <c><anno>Destination</anno></c>. On
some platforms, this error is given if either
- <c>Source</c> or <c>Destination</c> is open.</p>
+ <c><anno>Source</anno></c> or <c><anno>Destination</anno></c>
+ is open.</p>
</item>
<tag><c>eexist</c></tag>
<item>
- <p><c>Destination</c> is not an empty directory. On some
- platforms, also given when <c>Source</c> and
- <c>Destination</c> are not of the same type.</p>
+ <p><c><anno>Destination</anno></c> is not an empty directory.
+ On some platforms, also given when <c><anno>Source</anno></c> and
+ <c><anno>Destination</anno></c> are not of the same type.</p>
</item>
<tag><c>einval</c></tag>
<item>
- <p><c>Source</c> is a root directory, or <c>Destination</c>
- is a sub-directory of <c>Source</c>.</p>
+ <p><c><anno>Source</anno></c> is a root directory, or
+ <c><anno>Destination</anno></c>
+ is a sub-directory of <c><anno>Source</anno></c>.</p>
</item>
<tag><c>eisdir</c></tag>
<item>
- <p><c>Destination</c> is a directory, but <c>Source</c> is
- not.</p>
+ <p><c><anno>Destination</anno></c> is a directory, but
+ <c><anno>Source</anno></c> is not.</p>
</item>
<tag><c>enoent</c></tag>
<item>
@@ -1619,35 +1439,28 @@ f.txt: {person, "kalle", 25}.
</item>
<tag><c>enotdir</c></tag>
<item>
- <p><c>Source</c> is a directory, but <c>Destination</c> is
- not.</p>
+ <p><c><anno>Source</anno></c> is a directory, but
+ <c><anno>Destination</anno></c> is not.</p>
</item>
<tag><c>exdev</c></tag>
<item>
- <p><c>Source</c> and <c>Destination</c> are on different
- file systems.</p>
+ <p><c><anno>Source</anno></c> and <c><anno>Destination</anno></c>
+ are on different file systems.</p>
</item>
</taglist>
</desc>
</func>
<func>
- <name>script(Filename) -> {ok, Value} | {error, Reason}</name>
+ <name name="script" arity="1"/>
<fsummary>Evaluate and return the value of Erlang expressions in a file</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>Value = term()</v>
- <v>Reason = ext_posix() | terminated | system_limit
- | {Line, Mod, Term}</v>
- <v>&nbsp;Line, Mod, Term -- see below</v>
- </type>
<desc>
<p>Reads and evaluates Erlang expressions, separated by '.' (or
',', a sequence of expressions is also an expression), from
the file. Returns one of the following:</p>
<taglist>
- <tag><c>{ok, Value}</c></tag>
+ <tag><c>{ok, <anno>Value</anno>}</c></tag>
<item>
- <p>The file was read and evaluated. <c>Value</c> is
+ <p>The file was read and evaluated. <c><anno>Value</anno></c> is
the value of the last expression.</p>
</item>
<tag><c>{error, atom()}</c></tag>
@@ -1656,7 +1469,8 @@ f.txt: {person, "kalle", 25}.
See <seealso marker="#open/2">open/2</seealso> for a list
of typical error codes.</p>
</item>
- <tag><c>{error, {Line, Mod, Term}}</c></tag>
+ <tag><c>{error, {<anno>Line</anno>, <anno>Mod</anno>,
+ <anno>Term</anno>}}</c></tag>
<item>
<p>An error occurred when interpreting the Erlang
expressions in the file. Use <c>format_error/1</c> to
@@ -1667,33 +1481,21 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>script(Filename, Bindings) -> {ok, Value} | {error, Reason}</name>
+ <name name="script" arity="2"/>
<fsummary>Evaluate and return the value of Erlang expressions in a file</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>Bindings -- see erl_eval(3)</v>
- <v>Value = term()</v>
- <v>Reason = ext_posix() | terminated | system_limit
- | {Line, Mod, Term}</v>
- <v>&nbsp;Line, Mod, Term -- see below</v>
- </type>
<desc>
<p>The same as <c>script/1</c> but the variable bindings
- <c>Bindings</c> are used in the evaluation. See
+ <c><anno>Bindings</anno></c> are used in the evaluation. See
<seealso marker="stdlib:erl_eval">erl_eval(3)</seealso> about
variable bindings.</p>
</desc>
</func>
<func>
- <name>set_cwd(Dir) -> ok | {error,Reason}</name>
+ <name name="set_cwd" arity="1"/>
<fsummary>Set the current working directory</fsummary>
- <type>
- <v>Dir = name()</v>
- <v>Reason = ext_posix()</v>
- </type>
<desc>
<p>Sets the current working directory of the file server to
- <c>Dir</c>. Returns <c>ok</c> if successful.</p>
+ <c><anno>Dir</anno></c>. Returns <c>ok</c> if successful.</p>
<p>Typical error reasons are:</p>
<taglist>
<tag><c>enoent</c></tag>
@@ -1702,8 +1504,8 @@ f.txt: {person, "kalle", 25}.
</item>
<tag><c>enotdir</c></tag>
<item>
- <p>A component of <c>Dir</c> is not a directory. On some
- platforms, <c>enoent</c> is returned.</p>
+ <p>A component of <c><anno>Dir</anno></c> is not a directory.
+ On some platforms, <c>enoent</c> is returned.</p>
</item>
<tag><c>eacces</c></tag>
<item>
@@ -1712,23 +1514,20 @@ f.txt: {person, "kalle", 25}.
</item>
<tag><c>badarg</c></tag>
<item>
- <p><c>Filename</c> had an improper type, such as tuple.</p>
+ <p><c><anno>Dir</anno></c> had an improper type,
+ such as tuple.</p>
</item>
</taglist>
<warning>
- <p>In a future release, a bad type for the <c>Filename</c>
+ <p>In a future release, a bad type for the
+ <c><anno>Dir</anno></c>
argument will probably generate an exception.</p>
- <p></p>
</warning>
</desc>
</func>
<func>
- <name>sync(IoDevice) -> ok | {error, Reason}</name>
+ <name name="sync" arity="1"/>
<fsummary>Synchronizes the in-memory state of a file with that on the physical medium</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Reason = ext_posix() | terminated</v>
- </type>
<desc>
<p>Makes sure that any buffers kept by the operating system
(not by the Erlang runtime system) are written to disk. On
@@ -1743,12 +1542,8 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>datasync(IoDevice) -> ok | {error, Reason}</name>
+ <name name="datasync" arity="1"/>
<fsummary>Synchronizes the in-memory data of a file, ignoring most of its metadata, with that on the physical medium</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Reason = ext_posix() | terminated</v>
- </type>
<desc>
<p>Makes sure that any buffers kept by the operating system
(not by the Erlang runtime system) are written to disk. In
@@ -1770,32 +1565,23 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>truncate(IoDevice) -> ok | {error, Reason}</name>
+ <name name="truncate" arity="1"/>
<fsummary>Truncate a file</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Reason = ext_posix() | terminated</v>
- </type>
<desc>
- <p>Truncates the file referenced by <c>IoDevice</c> at
+ <p>Truncates the file referenced by <c><anno>IoDevice</anno></c> at
the current position. Returns <c>ok</c> if successful,
- otherwise <c>{error, Reason}</c>.</p>
+ otherwise <c>{error, <anno>Reason</anno>}</c>.</p>
</desc>
</func>
<func>
- <name>write(IoDevice, Bytes) -> ok | {error, Reason}</name>
+ <name name="write" arity="2"/>
<fsummary>Write to a file</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Bytes = iodata()</v>
- <v>Reason = ext_posix() | terminated</v>
- </type>
<desc>
- <p>Writes <c>Bytes</c> to the file referenced by
- <c>IoDevice</c>. This function is the only way to write to a
+ <p>Writes <c><anno>Bytes</anno></c> to the file referenced by
+ <c><anno>IoDevice</anno></c>. This function is the only way to write to a
file opened in raw mode (although it works for normally
opened files, too). Returns <c>ok</c> if successful, and
- <c>{error, Reason}</c> otherwise.</p>
+ <c>{error, <anno>Reason</anno>}</c> otherwise.</p>
<p>If the file is opened with <c>encoding</c> set to something else than <c>latin1</c>, each byte written might result in several bytes actually being written to the file, as the byte range 0..255 might represent anything between one and four bytes depending on value and UTF encoding type.</p>
<p>Typical error reasons are:</p>
<taglist>
@@ -1811,18 +1597,14 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>write_file(Filename, Bytes) -> ok | {error, Reason}</name>
+ <name name="write_file" arity="2"/>
<fsummary>Write a file</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>Bytes = iodata()</v>
- <v>Reason = ext_posix() | terminated | system_limit</v>
- </type>
<desc>
- <p>Writes the contents of the iodata term <c>Bytes</c> to the
- file <c>Filename</c>. The file is created if it does not
+ <p>Writes the contents of the iodata term <c><anno>Bytes</anno></c>
+ to the file <c><anno>Filename</anno></c>.
+ The file is created if it does not
exist. If it exists, the previous contents are
- overwritten. Returns <c>ok</c>, or <c>{error, Reason}</c>.</p>
+ overwritten. Returns <c>ok</c>, or <c>{error, <anno>Reason</anno>}</c>.</p>
<p>Typical error reasons are:</p>
<taglist>
<tag><c>enoent</c></tag>
@@ -1851,33 +1633,23 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
- <name>write_file(Filename, Bytes, Modes) -> ok | {error, Reason}</name>
+ <name name="write_file" arity="3"/>
<fsummary>Write a file</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>Bytes = iodata()</v>
- <v>Modes = [Mode] -- see open/2</v>
- <v>Reason = ext_posix() | terminated | system_limit</v>
- </type>
<desc>
<p>Same as <c>write_file/2</c>, but takes a third argument
- <c>Modes</c>, a list of possible modes, see
+ <c><anno>Modes</anno></c>, a list of possible modes, see
<seealso marker="#open/2">open/2</seealso>. The mode flags
<c>binary</c> and <c>write</c> are implicit, so they should
not be used.</p>
</desc>
</func>
<func>
- <name>write_file_info(Filename, FileInfo) -> ok | {error, Reason}</name>
+ <name name="write_file_info" arity="2"/>
<fsummary>Change information about a file</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>FileInfo = #file_info{} -- see also read_file_info/1</v>
- <v>Reason = ext_posix()</v>
- </type>
<desc>
<p>Change file information. Returns <c>ok</c> if successful,
- otherwise <c>{error, Reason}</c>. <c>FileInfo</c> is a record
+ otherwise <c>{error, <anno>Reason</anno>}</c>.
+ <c><anno>FileInfo</anno></c> is a record
<c>file_info</c>, defined in the Kernel include file
<c>file.hrl</c>. Include the following directive in the module
from which the function is called:</p>
@@ -1886,22 +1658,22 @@ f.txt: {person, "kalle", 25}.
<p>The following fields are used from the record, if they are
given.</p>
<taglist>
- <tag><c>atime = time()</c></tag>
+ <tag><c>atime = <seealso marker="#type-date_time">date_time()</seealso></c></tag>
<item>
<p>The last (local) time the file was read.</p>
</item>
- <tag><c>mtime = time()</c></tag>
+ <tag><c>mtime = <seealso marker="#type-date_time">date_time()</seealso></c></tag>
<item>
<p>The last (local) time the file was written.</p>
</item>
- <tag><c>ctime = time()</c></tag>
+ <tag><c>ctime = <seealso marker="#type-date_time">date_time()</seealso></c></tag>
<item>
<p>On Unix, any value give for this field will be ignored
(the "ctime" for the file will be set to the current
time). On Windows, this field is the new creation time to
set for the file.</p>
</item>
- <tag><c>mode = int()</c></tag>
+ <tag><c>mode = integer()</c></tag>
<item>
<p>The file permissions as the sum of the following bit
values:</p>
@@ -1932,12 +1704,12 @@ f.txt: {person, "kalle", 25}.
<p>On Unix platforms, other bits than those listed above
may be set.</p>
</item>
- <tag><c>uid = int()</c></tag>
+ <tag><c>uid = integer()</c></tag>
<item>
<p>Indicates the owner of the file. Ignored for non-Unix
file systems.</p>
</item>
- <tag><c>gid = int()</c></tag>
+ <tag><c>gid = integer()</c></tag>
<item>
<p>Gives the group that the owner of the file belongs to.
Ignored non-Unix file systems.</p>
diff --git a/lib/kernel/doc/src/gen_sctp.xml b/lib/kernel/doc/src/gen_sctp.xml
index fb09092f1c..688cd0f78f 100644
--- a/lib/kernel/doc/src/gen_sctp.xml
+++ b/lib/kernel/doc/src/gen_sctp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2007</year><year>2010</year>
+ <year>2007</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -47,8 +47,7 @@
SUSE Linux Enterprise Server 10 Service Pack 1 (x86_64)
kernel 2.6.16.54-0.2.3-smp with lksctp-tools-1.0.7.</p>
<p>Record definitions for the <c>gen_sctp</c> module can be found using:</p>
- <pre>
- -include_lib("kernel/include/inet_sctp.hrl"). </pre>
+<pre> -include_lib("kernel/include/inet_sctp.hrl"). </pre>
<p>These record definitions use the "new" spelling 'adaptation',
not the deprecated 'adaption', regardless of which
spelling the underlying C API uses.</p>
@@ -63,79 +62,54 @@
<item><seealso marker="#options">SCTP SOCKET OPTIONS</seealso></item>
<item><seealso marker="#examples">SCTP EXAMPLES</seealso></item>
<item><seealso marker="#seealso">SEE ALSO</seealso></item>
- <item><seealso marker="#authors">AUTHORS</seealso></item>
</list>
+ <marker id="types"></marker>
</section>
- <section>
- <marker id="types"></marker>
- <title>DATA TYPES</title>
- <marker id="type-assoc_id"></marker>
- <taglist>
- <tag><c>assoc_id()</c></tag>
- <item>
+ <datatypes>
+ <datatype>
+ <name><marker id="type-assoc_id">assoc_id()</marker></name>
+ <desc>
<p>An opaque term returned in for example #sctp_paddr_change{}
that identifies an association for an SCTP socket. The term
is opaque except for the special value <c>0</c> that has a
- meaning such as "the whole endpoint" or "all future associations".</p>
- <marker id="type-charlist"></marker>
- </item>
- <tag><c>charlist() = [char()]</c></tag>
- <item> <marker id="type-iolist"></marker>
-</item>
- <tag><c>iolist() = [char() | binary()]</c></tag>
- <item> <marker id="type-ip_address"></marker>
-</item>
- <tag><c>ip_address()</c></tag>
- <item>
- <p>Represents an address of an SCTP socket.
- It is a tuple as explained in
- <seealso marker="inet">inet(3)</seealso>.</p>
- <marker id="type-port_number"></marker>
- </item>
- <tag><c>port_number() = 0 .. 65535</c></tag>
- <item> <marker id="type-posix"></marker>
-</item>
- <tag><c>posix()</c></tag>
- <item>
- <p>See
- <seealso marker="inet#error_codes">inet(3); POSIX Error Codes.</seealso></p>
- <marker id="type-sctp_option"></marker>
- </item>
- <tag><c>sctp_option()</c></tag>
- <item>
+ meaning such as "the whole endpoint" or "all future associations".
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="option"/>
+ <desc>
<p>One of the
<seealso marker="#options">SCTP Socket Options.</seealso></p>
- <marker id="type-sctp_socket"></marker>
- </item>
- <tag><c>sctp_socket()</c></tag>
- <item>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="option_name"/>
+ <desc><marker id="type-sctp_socket"></marker></desc>
+ </datatype>
+ <datatype>
+ <name><marker id="type-sctp_socket">sctp_socket()</marker></name>
+ <desc>
<p>Socket identifier returned from <c>open/*</c>.</p>
- <marker id="type-timeout"></marker>
- </item>
- <tag><c>timeout() = int() | infinity</c></tag>
- <item>
- <p>Timeout used in SCTP connect and receive calls.</p>
- </item>
- </taglist>
- <marker id="exports"></marker>
- </section>
+ <marker id="exports"></marker>
+ </desc>
+ </datatype>
+ </datatypes>
+
<funcs>
<func>
- <name>abort(sctp_socket(), Assoc) -&gt; ok | {error, posix()}</name>
+ <name name="abort" arity="2"/>
<fsummary>Abnormally terminate the association given by Assoc, without flushing of unsent data</fsummary>
- <type>
- <v>Assoc = #sctp_assoc_change{}</v>
- </type>
<desc>
- <p>Abnormally terminates the association given by <c>Assoc</c>, without
+ <p>Abnormally terminates the association given by <c><anno>Assoc</anno></c>, without
flushing of unsent data. The socket itself remains open. Other
associations opened on this socket are still valid, and it can be
used in new associations.</p>
</desc>
</func>
<func>
- <name>close(sctp_socket()) -&gt; ok | {error, posix()}</name>
+ <name name="close" arity="1"/>
<fsummary>Completely close the socket and all associations on it</fsummary>
<desc>
<p>Completely closes the socket and all associations on it. The unsent
@@ -148,35 +122,26 @@
</desc>
</func>
<func>
- <name>connect(Socket, Addr, Port, Opts) -&gt; {ok,Assoc} | {error, posix()}</name>
+ <name name="connect" arity="4"/>
<fsummary>Same as <c>connect(Socket, Addr, Port, Opts, infinity)</c>.</fsummary>
<desc>
- <p>Same as <c>connect(Socket, Addr, Port, Opts, infinity)</c>.</p>
+ <p>Same as <c>connect(<anno>Socket</anno>, <anno>Addr</anno>, <anno>Port</anno>, <anno>Opts</anno>, infinity)</c>.</p>
</desc>
</func>
<func>
- <name>connect(Socket, Addr, Port, [Opt], Timeout) -&gt; {ok, Assoc} | {error, posix()}</name>
+ <name name="connect" arity="5"/>
<fsummary>Establish a new association for the socket <c>Socket</c>, with a peer (SCTP server socket)</fsummary>
- <type>
- <v>Socket = sctp_socket()</v>
- <v>Addr = ip_address() | Host</v>
- <v>Port = port_number()</v>
- <v>Opt = sctp_option()</v>
- <v>Timeout = timeout()</v>
- <v>Host = atom() | string()</v>
- <v>Assoc = #sctp_assoc_change{}</v>
- </type>
<desc>
- <p>Establishes a new association for the socket <c>Socket</c>,
+ <p>Establishes a new association for the socket <c><anno>Socket</anno></c>,
with the peer (SCTP server socket) given by
- <c>Addr</c> and <c>Port</c>. The <c>Timeout</c>,
+ <c><anno>Addr</anno></c> and <c><anno>Port</anno></c>. The <c><anno>Timeout</anno></c>,
is expressed in milliseconds. A socket can be associated with multiple peers.</p>
- <p><b>WARNING:</b>Using a value of <c>Timeout</c> less than
+ <p><b>WARNING:</b>Using a value of <c><anno>Timeout</anno></c> less than
the maximum time taken by the OS to establish an association (around 4.5 minutes
if the default values from RFC 4960 are used) can result in
inconsistent or incorrect return values. This is especially
- relevant for associations sharing the same <c>Socket</c>
+ relevant for associations sharing the same <c><anno>Socket</anno></c>
(i.e. source address and port) since the controlling process
blocks until <c>connect/*</c> returns.
<seealso marker="#connect_init/4">connect_init/*</seealso>
@@ -185,26 +150,24 @@
<p><marker id="record-sctp_assoc_change"></marker>
The result of <c>connect/*</c> is an <c>#sctp_assoc_change{}</c>
event which contains, in particular, the new
- <seealso marker="#type-assoc_id">Association ID:</seealso></p>
- <pre>
- #sctp_assoc_change{
+ <seealso marker="#type-assoc_id">Association ID</seealso>.</p>
+<pre> #sctp_assoc_change{
state = atom(),
error = atom(),
- outbound_streams = int(),
- inbound_streams = int(),
+ outbound_streams = integer(),
+ inbound_streams = integer(),
assoc_id = assoc_id()
} </pre>
<p>The number of outbound and inbound streams can be set by
giving an <c>sctp_initmsg</c> option to <c>connect</c>
as in:</p>
- <pre>
- connect(Socket, Ip, Port,
+<pre> connect(<anno>Socket</anno>, Ip, <anno>Port</anno>,
[{sctp_initmsg,#sctp_initmsg{num_ostreams=OutStreams,
max_instreams=MaxInStreams}}]) </pre>
- <p>All options <c>Opt</c> are set on the socket before the
+ <p>All options <c><anno>Opt</anno></c> are set on the socket before the
association is attempted. If an option record has got undefined
field values, the options record is first read from the socket
- for those values. In effect, <c>Opt</c> option records only
+ for those values. In effect, <c><anno>Opt</anno></c> option records only
define field values to change before connecting.</p>
<p>The returned <c>outbound_streams</c> and <c>inbound_streams</c>
are the actual stream numbers on the socket, which may be different
@@ -242,27 +205,19 @@
</desc>
</func>
<func>
- <name>connect_init(Socket, Addr, Port, Opts) -&gt; ok | {error, posix()}</name>
+ <name name="connect_init" arity="4"/>
<fsummary>Same as <c>connect_init(Socket, Addr, Port, Opts, infinity)</c>.</fsummary>
<desc>
- <p>Same as <c>connect_init(Socket, Addr, Port, Opts, infinity)</c>.</p>
+ <p>Same as <c>connect_init(<anno>Socket</anno>, <anno>Addr</anno>, <anno>Port</anno>, <anno>Opts</anno>, infinity)</c>.</p>
</desc>
</func>
<func>
- <name>connect_init(Socket, Addr, Port, [Opt], Timeout) -&gt; ok | {error, posix()}</name>
+ <name name="connect_init" arity="5"/>
<fsummary>Initiate a new association for the socket <c>Socket</c>, with a peer (SCTP server socket)</fsummary>
- <type>
- <v>Socket = sctp_socket()</v>
- <v>Addr = ip_address() | Host</v>
- <v>Port = port_number()</v>
- <v>Opt = sctp_option()</v>
- <v>Timeout = timeout()</v>
- <v>Host = atom() | string()</v>
- </type>
<desc>
- <p>Initiates a new association for the socket <c>Socket</c>,
+ <p>Initiates a new association for the socket <c><anno>Socket</anno></c>,
with the peer (SCTP server socket) given by
- <c>Addr</c> and <c>Port</c>.</p>
+ <c><anno>Addr</anno></c> and <c><anno>Port</anno></c>.</p>
<p>The fundamental difference between this API
and <c>connect/*</c> is that the return value is that of the
underlying OS connect(2) system call. If <c>ok</c> is returned
@@ -275,66 +230,67 @@
active option.</p>
<p>The parameters are as described
in <seealso marker="#connect/5">connect/*</seealso>, with the
- exception of the <c>Timeout</c> value.</p>
- <p>The timer associated with <c>Timeout</c> only supervises
- IP resolution of <c>Addr</c></p>
+ exception of the <c><anno>Timeout</anno></c> value.</p>
+ <p>The timer associated with <c><anno>Timeout</anno></c> only supervises
+ IP resolution of <c><anno>Addr</anno></c></p>
</desc>
</func>
<func>
- <name>controlling_process(sctp_socket(), pid()) -&gt; ok</name>
+ <name name="controlling_process" arity="2"/>
<fsummary>Assign a new controlling process pid to the socket</fsummary>
<desc>
- <p>Assigns a new controlling process Pid to Socket. Same implementation
+ <p>Assigns a new controlling process <c><anno>Pid</anno></c> to <c><anno>Socket</anno></c>. Same implementation
as <c>gen_udp:controlling_process/2</c>.</p>
</desc>
</func>
<func>
- <name>eof(Socket, Assoc) -&gt; ok | {error, Reason}</name>
+ <name name="eof" arity="2"/>
<fsummary>Gracefully terminate the association given by Assoc, with flushing of all unsent data</fsummary>
- <type>
- <v>Socket = sctp_socket()</v>
- <v>Assoc = #sctp_assoc_change{}</v>
- </type>
<desc>
- <p>Gracefully terminates the association given by <c>Assoc</c>, with
+ <p>Gracefully terminates the association given by <c><anno>Assoc</anno></c>, with
flushing of all unsent data. The socket itself remains open. Other
associations opened on this socket are still valid, and it can be
used in new associations.</p>
</desc>
</func>
<func>
- <name>listen(Socket, IsServer) -&gt; ok | {error, Reason}</name>
+ <name name="listen" arity="2"/>
<fsummary>Set up a socket to listen.</fsummary>
- <type>
- <v>Socket = sctp_socket()</v>
- <v>IsServer = bool()</v>
- </type>
<desc>
<p>Sets up a socket to listen on the IP address and port number
- it is bound to. IsServer must be 'true' or 'false'.
+ it is bound to. <c><anno>IsServer</anno></c> must be <c>true</c>
+ or <c>false</c>.
In the contrast to TCP, in SCTP there is no listening queue length.
- If IsServer is 'true' the socket accepts new associations, i.e.
+ If <c><anno>IsServer</anno></c> is <c>true</c> the socket accepts new associations, i.e.
it will become an SCTP server socket.</p>
</desc>
</func>
<func>
- <name>open() -&gt; {ok, Socket} | {error, posix()}</name>
- <name>open(Port) -&gt; {ok, Socket} | {error, posix()}</name>
- <name>open([Opt]) -&gt; {ok, Socket} | {error, posix()}</name>
- <name>open(Port, [Opt]) -&gt; {ok, Socket} | {error, posix()}</name>
+ <name name="open" arity="0"/>
+ <name name="open" arity="1" clause_i="1"/>
+ <name name="open" arity="1" clause_i="2"/>
+ <name name="open" arity="2"/>
<fsummary>Create an SCTP socket and bind it to local addresses</fsummary>
- <type>
- <v>Opt = {ip,IP} | {ifaddr,IP} | {port,Port} | sctp_option()</v>
- <v>IP = ip_address() | any | loopback</v>
- <v>Port = port_number()</v>
- </type>
<desc>
<p>Creates an SCTP socket and binds it to the local addresses
- specified by all <c>{ip,IP}</c> (or synonymously <c>{ifaddr,IP}</c>)
+ specified by all <c>{ip,<anno>IP</anno>}</c> (or synonymously <c>{ifaddr,<anno>IP</anno>}</c>)
options (this feature is called SCTP multi-homing).
- The default <c>IP</c> and <c>Port</c> are <c>any</c>
+ The default <c><anno>IP</anno></c> and <c><anno>Port</anno></c> are <c>any</c>
and <c>0</c>, meaning bind to all local addresses on any
one free port.</p>
+
+ <p>Other options are:</p>
+ <taglist>
+ <tag><c>inet6</c></tag>
+ <item>
+ <p>Set up the socket for IPv6.</p>
+ </item>
+ <tag><c>inet</c></tag>
+ <item>
+ <p>Set up the socket for IPv4. This is the default.</p>
+ </item>
+ </taglist>
+
<p>A default set of socket <seealso marker="#options">options</seealso>
is used. In particular, the socket is opened in
<seealso marker="#option-binary">binary</seealso> and
@@ -345,27 +301,16 @@
</desc>
</func>
<func>
- <name>recv(sctp_socket()) -&gt; {ok, {FromIP, FromPort, AncData, BinMsg}} | {error, Reason}</name>
- <name>recv(sctp_socket(), timeout()) -&gt; {ok, {FromIP, FromPort, AncData, Data}} | {error, Reason}</name>
+ <name name="recv" arity="1"/>
+ <name name="recv" arity="2"/>
<fsummary>Receive a message from a socket</fsummary>
- <type>
- <v>FromIP = ip_address()</v>
- <v>FromPort = port_number()</v>
- <v>AncData = [#sctp_sndrcvinfo{}]</v>
- <v>Data = binary() | charlist() | #sctp_sndrcvinfo{} |
- #sctp_assoc_change{} | #sctp_paddr_change{} |
- #sctp_adaptation_event{} </v>
- <v>Reason = posix() | #sctp_send_failed{} | #scpt_paddr_change{} |
- #sctp_pdapi_event{} | #sctp_remote_error{} |
- #sctp_shutdown_event{}</v>
- </type>
<desc>
- <p>Receives the <c>Data</c> message from any association of the socket.
+ <p>Receives the <c><anno>Data</anno></c> message from any association of the socket.
If the receive times out <c>{error,timeout</c> is returned.
The default timeout is <c>infinity</c>.
- <c>FromIP</c> and <c>FromPort</c> indicate the sender's address.</p>
- <p><c>AncData</c> is a list of Ancillary Data items which
- may be received along with the main <c>Data</c>.
+ <c><anno>FromIP</anno></c> and <c><anno>FromPort</anno></c> indicate the sender's address.</p>
+ <p><c><anno>AncData</anno></c> is a list of Ancillary Data items which
+ may be received along with the main <c><anno>Data</anno></c>.
This list can be empty, or contain a single
<seealso marker="#record-sctp_sndrcvinfo">#sctp_sndrcvinfo{}</seealso>
record, if receiving of such ancillary data is enabled
@@ -375,10 +320,10 @@
provide an easy way of determining the association and stream
over which the message has been received.
(An alternative way would be to get the Association ID from the
- <c>FromIP</c> and <c>FromPort</c> using the
+ <c><anno>FromIP</anno></c> and <c><anno>FromPort</anno></c> using the
<seealso marker="#option-sctp_get_peer_addr_info">sctp_get_peer_addr_info</seealso> socket option,
but this would still not produce the Stream number).</p>
- <p>The actual <c>Data</c> received may be a <c>binary()</c>,
+ <p>The actual <c><anno>Data</anno></c> received may be a <c>binary()</c>,
or <c>list()</c> of bytes (integers in the range 0 through 255)
depending on the socket mode, or an SCTP Event.
<marker id="sctp_events"></marker>
@@ -392,11 +337,10 @@
<p><seealso marker="#record-sctp_assoc_change">#sctp_assoc_change{}</seealso>;</p>
</item>
<item>
- <pre>
- #sctp_paddr_change{
+<pre> #sctp_paddr_change{
addr = {ip_address(),port()},
state = atom(),
- error = int(),
+ error = integer(),
assoc_id = assoc_id()
} </pre>
<p>Indicates change of the status of the peer's IP address given by
@@ -430,10 +374,9 @@
converted into a string using <c>error_string/1</c>.</p>
</item>
<item>
- <pre>
- #sctp_send_failed{
+<pre> #sctp_send_failed{
flags = true | false,
- error = int(),
+ error = integer(),
info = #sctp_sndrcvinfo{},
assoc_id = assoc_id()
data = binary()
@@ -451,9 +394,8 @@
returned by <c>recv/*</c>.</p>
</item>
<item>
- <pre>
- #sctp_adaptation_event{
- adaptation_ind = int(),
+<pre> #sctp_adaptation_event{
+ adaptation_ind = integer(),
assoc_id = assoc_id()
} </pre>
<p>Delivered when a peer sends an Adaptation Layer Indication
@@ -463,8 +405,7 @@
the Erlang/SCTP binding, this event is disabled by default.</p>
</item>
<item>
- <pre>
- #sctp_pdapi_event{
+<pre> #sctp_pdapi_event{
indication = sctp_partial_delivery_aborted,
assoc_id = assoc_id()
} </pre>
@@ -476,15 +417,10 @@
</desc>
</func>
<func>
- <name>send(Socket, SndRcvInfo, Data) -&gt; ok | {error, Reason}</name>
+ <name name="send" arity="3"/>
<fsummary>Send a message using an <c>#sctp_sndrcvinfo{}</c>record</fsummary>
- <type>
- <v>Socket = sctp_socket()</v>
- <v>SndRcvInfo = #sctp_sndrcvinfo{}</v>
- <v>Data = binary() | iolist()</v>
- </type>
<desc>
- <p>Sends the <c>Data</c> message with all sending parameters from a
+ <p>Sends the <c><anno>Data</anno></c> message with all sending parameters from a
<seealso marker="#record-sctp_sndrcvinfo">#sctp_sndrcvinfo{}</seealso> record.
This way, the user can specify the PPID (passed to the remote end)
and Context (passed to the local SCTP layer) which can be used
@@ -494,21 +430,15 @@
</desc>
</func>
<func>
- <name>send(Socket, Assoc, Stream, Data) -&gt; ok | {error, Reason}</name>
+ <name name="send" arity="4"/>
<fsummary>Send a message over an existing association and given stream</fsummary>
- <type>
- <v>Socket = sctp_socket()</v>
- <v>Assoc = #sctp_assoc_change{} | assoc_id()</v>
- <v>Stream = integer()</v>
- <v>Data = binary() | iolist()</v>
- </type>
<desc>
- <p>Sends <c>Data</c> message over an existing association and given
+ <p>Sends <c><anno>Data</anno></c> message over an existing association and given
stream.</p>
</desc>
</func>
<func>
- <name>error_string(integer()) -> ok | string() | undefined</name>
+ <name name="error_string" arity="1"/>
<fsummary>Translate an SCTP error number into a string</fsummary>
<desc>
<p>Translates an SCTP error number from for example
@@ -532,7 +462,7 @@
<marker id="option-binary"></marker>
<marker id="option-list"></marker>
<taglist>
- <tag><c>{mode, list|binary}</c>or just <c>list</c> or <c>binary</c>.</tag>
+ <tag><c>{mode, list|binary}</c> or just <c>list</c> or <c>binary</c></tag>
<item>
<p>Determines the type of data returned from <c>gen_sctp:recv/1,2</c>.</p>
<marker id="option-active"></marker>
@@ -562,7 +492,7 @@
</list>
<marker id="option-buffer"></marker>
</item>
- <tag><c>{buffer, int()}</c></tag>
+ <tag><c>{buffer, integer()}</c></tag>
<item>
<p>Determines the size of the user-level software buffer used by
the SCTP driver. Not to be confused with <c>sndbuf</c>
@@ -572,7 +502,7 @@
In fact, the <c>val(buffer)</c> is automatically set to
the above maximum when <c>sndbuf</c> or <c>recbuf</c> values are set.</p>
</item>
- <tag><c>{tos, int()}</c></tag>
+ <tag><c>{tos, integer()}</c></tag>
<item>
<p>Sets the Type-Of-Service field on the IP datagrams being sent,
to the given value, which effectively determines a prioritization
@@ -580,7 +510,7 @@
are system-dependent. TODO: we do not provide
symbolic names for these values yet.</p>
</item>
- <tag><c>{priority, int()}</c></tag>
+ <tag><c>{priority, integer()}</c></tag>
<item>
<p>A protocol-independent equivalent of <c>tos</c> above. Setting
priority implies setting tos as well.</p>
@@ -599,7 +529,7 @@
required for high-throughput servers).</p>
<marker id="option-linger"></marker>
</item>
- <tag><c>{linger, {true|false, int()}</c></tag>
+ <tag><c>{linger, {true|false, integer()}</c></tag>
<item>
<p>Determines the timeout in seconds for flushing unsent data in the
<c>gen_sctp:close/1</c> socket call. If the 1st component of the value
@@ -609,14 +539,14 @@
the flushing time-out in seconds.</p>
<marker id="option-sndbuf"></marker>
</item>
- <tag><c>{sndbuf, int()}</c></tag>
+ <tag><c>{sndbuf, integer()}</c></tag>
<item>
<p>The size, in bytes, of the *kernel* send buffer for this socket.
Sending errors would occur for datagrams larger than
<c>val(sndbuf)</c>. Setting this option also adjusts
the size of the driver buffer (see <c>buffer</c> above).</p>
</item>
- <tag><c>{recbuf, int()}</c></tag>
+ <tag><c>{recbuf, integer()}</c></tag>
<item>
<p>The size, in bytes, of the *kernel* recv buffer for this socket.
Sending errors would occur for datagrams larger than
@@ -625,12 +555,11 @@
</item>
<tag><c>{sctp_rtoinfo, #sctp_rtoinfo{}}</c></tag>
<item>
- <pre>
- #sctp_rtoinfo{
+<pre> #sctp_rtoinfo{
assoc_id = assoc_id(),
- initial = int(),
- max = int(),
- min = int()
+ initial = integer(),
+ max = integer(),
+ min = integer()
} </pre>
<p>Determines re-transmission time-out parameters, in milliseconds,
for the association(s) given by <c>assoc_id</c>.
@@ -640,14 +569,13 @@
</item>
<tag><c>{sctp_associnfo, #sctp_assocparams{}}</c></tag>
<item>
- <pre>
- #sctp_assocparams{
+<pre> #sctp_assocparams{
assoc_id = assoc_id(),
- asocmaxrxt = int(),
- number_peer_destinations = int(),
- peer_rwnd = int(),
- local_rwnd = int(),
- cookie_life = int()
+ asocmaxrxt = integer(),
+ number_peer_destinations = integer(),
+ peer_rwnd = integer(),
+ local_rwnd = integer(),
+ cookie_life = integer()
} </pre>
<p>Determines association parameters for the association(s) given by
<c>assoc_id</c>. <c>assoc_id = 0</c> (default) indicates
@@ -656,12 +584,11 @@
</item>
<tag><c>{sctp_initmsg, #sctp_initmsg{}}</c></tag>
<item>
- <pre>
- #sctp_initmsg{
- num_ostreams = int(),
- max_instreams = int(),
- max_attempts = int(),
- max_init_timeo = int()
+<pre> #sctp_initmsg{
+ num_ostreams = integer(),
+ max_instreams = integer(),
+ max_attempts = integer(),
+ max_init_timeo = integer()
} </pre>
<p>Determines the default parameters which this socket attempts
to negotiate with its peer while establishing an association with it.
@@ -685,12 +612,12 @@
for establishing an association.</p>
</item>
</list>
- <p></p>
</item>
- <tag><c>{sctp_autoclose, int()|infinity}</c></tag>
+ <tag><c>{sctp_autoclose, integer() >= 0}</c></tag>
<item>
<p>Determines the time (in seconds) after which an idle association is
- automatically closed.</p>
+ automatically closed. <c>0</c> means that the association is
+ never automatically closed.</p>
</item>
<tag><c>{sctp_nodelay, true|false}</c></tag>
<item>
@@ -712,15 +639,14 @@
<p>Turns on|off automatic mapping of IPv4 addresses into IPv6 ones
(if the socket address family is AF_INET6).</p>
</item>
- <tag><c>{sctp_maxseg, int()}</c></tag>
+ <tag><c>{sctp_maxseg, integer()}</c></tag>
<item>
<p>Determines the maximum chunk size if message fragmentation is used.
If <c>0</c>, the chunk size is limited by the Path MTU only.</p>
</item>
<tag><c>{sctp_primary_addr, #sctp_prim{}}</c></tag>
<item>
- <pre>
- #sctp_prim{
+<pre> #sctp_prim{
assoc_id = assoc_id(),
addr = {IP, Port}
}
@@ -733,8 +659,7 @@
</item>
<tag><c>{sctp_set_peer_primary_addr, #sctp_setpeerprim{}}</c></tag>
<item>
- <pre>
- #sctp_setpeerprim{
+<pre> #sctp_setpeerprim{
assoc_id = assoc_id(),
addr = {IP, Port}
}
@@ -748,9 +673,8 @@
<tag><c>{sctp_adaptation_layer, #sctp_setadaptation{}}</c></tag>
<item>
<marker id="record-sctp_setadaptation"></marker>
- <pre>
- #sctp_setadaptation{
- adaptation_ind = int()
+<pre> #sctp_setadaptation{
+ adaptation_ind = integer()
} </pre>
<p>When set, requests that the local endpoint uses the value given by
<c>adaptation_ind</c> as the Adaptation Indication parameter for
@@ -760,14 +684,13 @@
</item>
<tag><c>{sctp_peer_addr_params, #sctp_paddrparams{}}</c></tag>
<item>
- <pre>
- #sctp_paddrparams{
+<pre> #sctp_paddrparams{
assoc_id = assoc_id(),
address = {IP, Port},
- hbinterval = int(),
- pathmaxrxt = int(),
- pathmtu = int(),
- sackdelay = int(),
+ hbinterval = integer(),
+ pathmaxrxt = integer(),
+ pathmtu = integer(),
+ sackdelay = integer(),
flags = list()
}
IP = ip_address()
@@ -818,24 +741,21 @@
<p><c>sackdelay_disable</c>: disable SAC delay.</p>
</item>
</list>
- <p></p>
</item>
</list>
- <p></p>
</item>
<tag><c>{sctp_default_send_param, #sctp_sndrcvinfo{}}</c></tag>
<item>
<marker id="record-sctp_sndrcvinfo"></marker>
- <pre>
- #sctp_sndrcvinfo{
- stream = int(),
- ssn = int(),
+<pre> #sctp_sndrcvinfo{
+ stream = integer(),
+ ssn = integer(),
flags = list(),
- ppid = int(),
- context = int(),
- timetolive = int(),
- tsn = int(),
- cumtsn = int(),
+ ppid = integer(),
+ context = integer(),
+ timetolive = integer(),
+ tsn = integer(),
+ cumtsn = integer(),
assoc_id = assoc_id()
} </pre>
<p><c>#sctp_sndrcvinfo{}</c> is used both in this socket option, and as
@@ -869,20 +789,17 @@
association, with flushing of unsent data.</p>
</item>
</list>
- <p></p>
<p>Other fields are rarely used. See
<url href="http://www.rfc-archive.org/getrfc.php?rfc=2960">RFC2960</url> and
<url href="http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13">Sockets API Extensions for SCTP</url> for full information.</p>
</item>
</list>
- <p></p>
<marker id="option-sctp_events"></marker>
</item>
<tag><c>{sctp_events, #sctp_event_subscribe{}}</c></tag>
<item>
<marker id="record-sctp_event_subscribe"></marker>
- <pre>
- #sctp_event_subscribe{
+<pre> #sctp_event_subscribe{
data_io_event = true | false,
association_event = true | false,
address_event = true | false,
@@ -907,10 +824,9 @@
</item>
<tag><c>{sctp_delayed_ack_time, #sctp_assoc_value{}}</c></tag>
<item>
- <pre>
- #sctp_assoc_value{
+<pre> #sctp_assoc_value{
assoc_id = assoc_id(),
- assoc_value = int()
+ assoc_value = integer()
} </pre>
<p>Rarely used. Determines the ACK time
(given by <c>assoc_value</c> in milliseconds) for
@@ -919,16 +835,15 @@
</item>
<tag><c>{sctp_status, #sctp_status{}}</c></tag>
<item>
- <pre>
- #sctp_status{
+<pre> #sctp_status{
assoc_id = assoc_id(),
state = atom(),
- rwnd = int(),
- unackdata = int(),
- penddata = int(),
- instrms = int(),
- outstrms = int(),
- fragmentation_point = int(),
+ rwnd = integer(),
+ unackdata = integer(),
+ penddata = integer(),
+ instrms = integer(),
+ outstrms = integer(),
+ fragmentation_point = integer(),
primary = #sctp_paddrinfo{}
} </pre>
<p>This option is read-only. It determines the status of
@@ -992,21 +907,19 @@
address (see below for the format of <c>#sctp_paddrinfo{}</c>).</p>
</item>
</list>
- <p></p>
<marker id="option-sctp_get_peer_addr_info"></marker>
</item>
<tag><c>{sctp_get_peer_addr_info, #sctp_paddrinfo{}}</c></tag>
<item>
<marker id="record-sctp_paddrinfo"></marker>
- <pre>
- #sctp_paddrinfo{
+<pre> #sctp_paddrinfo{
assoc_id = assoc_id(),
address = {IP, Port},
state = inactive | active,
- cwnd = int(),
- srtt = int(),
- rto = int(),
- mtu = int()
+ cwnd = integer(),
+ srtt = integer(),
+ rto = integer(),
+ mtu = integer()
}
IP = ip_address()
Port = port_number() </pre>
@@ -1030,8 +943,7 @@
<item>
<p>Example of an Erlang SCTP Server which receives SCTP messages and
prints them on the standard output:</p>
- <pre>
- -module(sctp_server).
+<pre> -module(sctp_server).
-export([server/0,server/1,server/2]).
-include_lib("kernel/include/inet.hrl").
@@ -1047,7 +959,7 @@
server(IP, Port) when is_tuple(IP) orelse IP == any orelse IP == loopback,
is_integer(Port) -&gt;
- {ok,S} = gen_sctp:open([{ip,IP},{port,Port}],[{recbuf,65536}]),
+ {ok,S} = gen_sctp:open(Port, [{recbuf,65536}, {ip,IP}]),
io:format("Listening on ~w:~w. ~w~n", [IP,Port,S]),
ok = gen_sctp:listen(S, true),
server_loop(S).
@@ -1060,7 +972,6 @@
io:format("Received: ~p~n", [Data])
end,
server_loop(S). </pre>
- <p></p>
</item>
<item>
<p>Example of an Erlang SCTP Client which interacts with the above Server.
@@ -1070,8 +981,7 @@
over Stream 5 fails. The client then <c>abort</c>s the association,
which results in the corresponding Event being received on
the Server side.</p>
- <pre>
- -module(sctp_client).
+<pre> -module(sctp_client).
-export([client/0, client/1, client/2]).
-include_lib("kernel/include/inet.hrl").
@@ -1104,13 +1014,11 @@
timer:sleep(1000),
gen_sctp:close(S). </pre>
- <p></p>
</item>
<item>
<p>A very simple Erlang SCTP Client which uses the
connect_init API.</p>
- <pre>
--module(ex3).
+<pre>-module(ex3).
-export([client/4]).
-include_lib("kernel/include/inet.hrl").
@@ -1163,7 +1071,6 @@ client_loop(S, Peer1, Port1, AssocId1, Peer2, Port2, AssocId2) -&gt;
ok
end.
</pre>
- <p></p>
</item>
</list>
</section>
@@ -1176,7 +1083,6 @@ client_loop(S, Peer1, Port1, AssocId1, Peer2, Port2, AssocId2) -&gt;
<seealso marker="gen_udp">gen_udp(3)</seealso>,
<url href="http://www.rfc-archive.org/getrfc.php?rfc=2960">RFC2960</url> (Stream Control Transmission Protocol),
<url href="http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13">Sockets API Extensions for SCTP.</url></p>
- <marker id="authors"></marker>
</section>
</erlref>
diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml
index aa171c77c2..8a5d40bb16 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>2010</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -37,7 +37,7 @@
binary and closing the connection:</p>
<code type="none">
client() ->
- SomeHostInNet = "localhost" % to make it runnable on one machine
+ SomeHostInNet = "localhost", % to make it runnable on one machine
{ok, Sock} = gen_tcp:connect(SomeHostInNet, 5678,
[binary, {packet, 0}]),
ok = gen_tcp:send(Sock, "Some Data"),
@@ -63,36 +63,36 @@ do_recv(Sock, Bs) ->
<p>For more examples, see the <seealso marker="#examples">examples</seealso> section.</p>
</description>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-ip_address()
- see inet(3)
-
-posix()
- see inet(3)
+ <datatypes>
+ <datatype>
+ <name name="option"/>
+ </datatype>
+ <datatype>
+ <name name="option_name"/>
+ </datatype>
+ <datatype>
+ <name name="connect_option"/>
+ </datatype>
+ <datatype>
+ <name name="listen_option"/>
+ </datatype>
+ <datatype>
+ <name><marker id="type-socket">socket()</marker></name>
+ <desc>
+ <p>As returned by accept/1,2 and connect/3,4.</p>
+ <marker id="connect"></marker>
+ </desc>
+ </datatype>
+ </datatypes>
-socket()
- as returned by accept/1,2 and connect/3,4</code>
- <marker id="connect"></marker>
- </section>
<funcs>
<func>
- <name>connect(Address, Port, Options) -> {ok, Socket} | {error, Reason}</name>
- <name>connect(Address, Port, Options, Timeout) -> {ok, Socket} | {error, Reason}</name>
+ <name name="connect" arity="3"/>
+ <name name="connect" arity="4"/>
<fsummary>Connect to a TCP port</fsummary>
- <type>
- <v>Address = string() | atom() | ip_address()</v>
- <v>Port = 0..65535</v>
- <v>Options = [Opt]</v>
- <v>&nbsp;Opt -- see below</v>
- <v>Timeout = int() | infinity</v>
- <v>Socket = socket()</v>
- <v>Reason = posix()</v>
- </type>
<desc>
- <p>Connects to a server on TCP port <c>Port</c> on the host
- with IP address <c>Address</c>. The <c>Address</c> argument
+ <p>Connects to a server on TCP port <c><anno>Port</anno></c> on the host
+ with IP address <c><anno>Address</anno></c>. The <c><anno>Address</anno></c> argument
can be either a hostname, or an IP address.</p>
<p>The available options are:</p>
<taglist>
@@ -113,7 +113,7 @@ socket()
<item>
<p>Specify which local port number to use.</p>
</item>
- <tag><c>{fd, int()}</c></tag>
+ <tag><c>{fd, integer() >= 0}</c></tag>
<item>
<p>If a socket has somehow been connected without using
<c>gen_tcp</c>, use this option to pass the file
@@ -127,13 +127,13 @@ socket()
<item>
<p>Set up the socket for IPv4.</p>
</item>
- <tag>Opt</tag>
+ <tag><c>Opt</c></tag>
<item>
<p>See
<seealso marker="inet#setopts/2">inet:setopts/2</seealso>.</p>
</item>
</taglist>
- <p>Packets can be sent to the returned socket <c>Socket</c>
+ <p>Packets can be sent to the returned socket <c><anno>Socket</anno></c>
using <c>send/2</c>. Packets sent from the peer are delivered
as messages:</p>
<code type="none">
@@ -148,7 +148,7 @@ socket()
<p>unless <c>{active, false}</c> is specified in the option list
for the socket, in which case packets are retrieved by
calling <c>recv/2</c>.</p>
- <p>The optional <c>Timeout</c> parameter specifies a timeout in
+ <p>The optional <c><anno>Timeout</anno></c> parameter specifies a timeout in
milliseconds. The default value is <c>infinity</c>.</p>
<note>
<p>The default values for options given to <c>connect</c> can
@@ -159,19 +159,12 @@ socket()
</desc>
</func>
<func>
- <name>listen(Port, Options) -> {ok, ListenSocket} | {error, Reason}</name>
+ <name name="listen" arity="2"/>
<fsummary>Set up a socket to listen on a port</fsummary>
- <type>
- <v>Port = 0..65535</v>
- <v>Options = [Opt]</v>
- <v>&nbsp;Opt -- see below</v>
- <v>ListenSocket -- see below</v>
- <v>Reason = posix()</v>
- </type>
<desc>
- <p>Sets up a socket to listen on the port <c>Port</c> on
+ <p>Sets up a socket to listen on the port <c><anno>Port</anno></c> on
the local host.</p>
- <p>If <c>Port == 0</c>, the underlying OS assigns an available
+ <p>If <c><anno>Port</anno> == 0</c>, the underlying OS assigns an available
port number, use <c>inet:port/1</c> to retrieve it.</p>
<p>The available options are:</p>
<taglist>
@@ -194,6 +187,10 @@ socket()
<p>If the host has several network interfaces, this option
specifies which one to listen on.</p>
</item>
+ <tag><c>{port, Port}</c></tag>
+ <item>
+ <p>Specify which local port number to use.</p>
+ </item>
<tag><c>{fd, Fd}</c></tag>
<item>
<p>If a socket has somehow been connected without using
@@ -214,7 +211,7 @@ socket()
<seealso marker="inet#setopts/2">inet:setopts/2</seealso>.</p>
</item>
</taglist>
- <p>The returned socket <c>ListenSocket</c> can only be used in
+ <p>The returned socket <c><anno>ListenSocket</anno></c> can only be used in
calls to <c>accept/1,2</c>.</p>
<note>
<p>The default values for options given to <c>listen</c> can
@@ -225,27 +222,23 @@ socket()
</desc>
</func>
<func>
- <name>accept(ListenSocket) -> {ok, Socket} | {error, Reason}</name>
- <name>accept(ListenSocket, Timeout) -> {ok, Socket} | {error, Reason}</name>
+ <name name="accept" arity="1"/>
+ <name name="accept" arity="2"/>
<fsummary>Accept an incoming connection request on a listen socket</fsummary>
- <type>
- <v>ListenSocket -- see listen/2</v>
- <v>Timeout = int() | infinity</v>
- <v>Socket = socket()</v>
- <v>Reason = closed | timeout | posix()</v>
- </type>
+ <type_desc variable="ListenSocket">Returned by <c>listen/2</c>.
+ </type_desc>
<desc>
<p>Accepts an incoming connection request on a listen socket.
- <c>Socket</c> must be a socket returned from <c>listen/2</c>.
- <c>Timeout</c> specifies a timeout value in ms, defaults to
+ <c><anno>Socket</anno></c> must be a socket returned from <c>listen/2</c>.
+ <c><anno>Timeout</anno></c> specifies a timeout value in ms, defaults to
<c>infinity</c>.</p>
- <p>Returns <c>{ok, Socket}</c> if a connection is established,
- or <c>{error, closed}</c> if <c>ListenSocket</c> is closed,
+ <p>Returns <c>{ok, <anno>Socket</anno>}</c> if a connection is established,
+ or <c>{error, closed}</c> if <c><anno>ListenSocket</anno></c> is closed,
or <c>{error, timeout}</c> if no connection is established
within the specified time. May also return a POSIX error
value if something else goes wrong, see inet(3) for possible
error values.</p>
- <p>Packets can be sent to the returned socket <c>Socket</c>
+ <p>Packets can be sent to the returned socket <c><anno>Socket</anno></c>
using <c>send/2</c>. Packets sent from the peer are delivered
as messages:</p>
<code type="none">
@@ -264,13 +257,8 @@ socket()
</desc>
</func>
<func>
- <name>send(Socket, Packet) -> ok | {error, Reason}</name>
+ <name name="send" arity="2"/>
<fsummary>Send a packet</fsummary>
- <type>
- <v>Socket = socket()</v>
- <v>Packet = [char()] | binary()</v>
- <v>Reason = posix()</v>
- </type>
<desc>
<p>Sends a packet on a socket. </p>
<p>There is no <c>send</c> call with timeout option, you use the
@@ -279,70 +267,52 @@ socket()
</desc>
</func>
<func>
- <name>recv(Socket, Length) -> {ok, Packet} | {error, Reason}</name>
- <name>recv(Socket, Length, Timeout) -> {ok, Packet} | {error, Reason}</name>
+ <name name="recv" arity="2"/>
+ <name name="recv" arity="3"/>
<fsummary>Receive a packet from a passive socket</fsummary>
- <type>
- <v>Socket = socket()</v>
- <v>Length = int()</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>
+ <type_desc variable="HttpPacket">See the description of
+ <c>HttpPacket</c> in <seealso marker="erts:erlang#decode_packet/3">
+ erlang:decode_packet/3</seealso>.
+ </type_desc>
<desc>
<p>This function receives a packet from a socket in passive
mode. A closed socket is indicated by a return value
<c>{error, closed}</c>.</p>
- <p>The <c>Length</c> argument is only meaningful when
+ <p>The <c><anno>Length</anno></c> argument is only meaningful when
the socket is in <c>raw</c> mode and denotes the number of
- bytes to read. If <c>Length</c> = 0, all available bytes are
- returned. If <c>Length</c> &gt; 0, exactly <c>Length</c>
+ bytes to read. If <c><anno>Length</anno></c> = 0, all available bytes are
+ returned. If <c><anno>Length</anno></c> &gt; 0, exactly <c><anno>Length</anno></c>
bytes are returned, or an error; possibly discarding less
- than <c>Length</c> bytes of data when the socket gets closed
+ than <c><anno>Length</anno></c> bytes of data when the socket gets closed
from the other side.</p>
- <p>The optional <c>Timeout</c> parameter specifies a timeout in
+ <p>The optional <c><anno>Timeout</anno></c> parameter specifies a timeout in
milliseconds. The default value is <c>infinity</c>.</p>
</desc>
</func>
<func>
- <name>controlling_process(Socket, Pid) -> ok | {error, Reason}</name>
+ <name name="controlling_process" arity="2"/>
<fsummary>Change controlling process of a socket</fsummary>
- <type>
- <v>Socket = socket()</v>
- <v>Pid = pid()</v>
- <v>Reason = closed | not_owner | posix()</v>
- </type>
<desc>
- <p>Assigns a new controlling process <c>Pid</c> to
- <c>Socket</c>. The controlling process is the process which
+ <p>Assigns a new controlling process <c><anno>Pid</anno></c> to
+ <c><anno>Socket</anno></c>. The controlling process is the process which
receives messages from the socket. If called by any other
process than the current controlling process,
<c>{error, eperm}</c> is returned.</p>
</desc>
</func>
<func>
- <name>close(Socket) -> ok | {error, Reason}</name>
+ <name name="close" arity="1"/>
<fsummary>Close a TCP socket</fsummary>
- <type>
- <v>Socket = socket()</v>
- <v>Reason = posix()</v>
- </type>
<desc>
<p>Closes a TCP socket.</p>
</desc>
</func>
<func>
- <name>shutdown(Socket, How) -> ok | {error, Reason}</name>
+ <name name="shutdown" arity="2"/>
<fsummary>Immediately close a socket</fsummary>
- <type>
- <v>Socket = socket()</v>
- <v>How = read | write | read_write</v>
- <v>Reason = posix()</v>
- </type>
<desc>
<p>Immediately close a socket in one or two directions.</p>
- <p><c>How == write</c> means closing the socket for writing,
+ <p><c><anno>How</anno> == write</c> means closing the socket for writing,
reading from it is still possible.</p>
<p>To be able to handle that the peer has done a shutdown on
the write side, the <c>{exit_on_close, false}</c> option
diff --git a/lib/kernel/doc/src/gen_udp.xml b/lib/kernel/doc/src/gen_udp.xml
index 71f2e9bd83..daa9b7d887 100644
--- a/lib/kernel/doc/src/gen_udp.xml
+++ b/lib/kernel/doc/src/gen_udp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,32 +34,28 @@
with sockets using the UDP protocol.</p>
</description>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-ip_address()
- see inet(3)
-
-posix()
- see inet(3)
+ <datatypes>
+ <datatype>
+ <name name="option"/>
+ </datatype>
+ <datatype>
+ <name name="option_name"/>
+ </datatype>
+ <datatype>
+ <name><marker id="type-socket">socket()</marker></name>
+ <desc>
+ <p>As returned by open/1,2.</p>
+ </desc>
+ </datatype>
+ </datatypes>
-socket()
- as returned by open/1,2</code>
- </section>
<funcs>
<func>
- <name>open(Port) -> {ok, Socket} | {error, Reason}</name>
- <name>open(Port, Options) -> {ok, Socket} | {error, Reason}</name>
+ <name name="open" arity="1"/>
+ <name name="open" arity="2"/>
<fsummary>Associate a UDP port number with the process calling it</fsummary>
- <type>
- <v>Port = 0..65535</v>
- <v>Options = [Opt]</v>
- <v>&nbsp;Opt -- see below</v>
- <v>Socket = socket()</v>
- <v>Reason = posix()</v>
- </type>
<desc>
- <p>Associates a UDP port number (<c>Port</c>) with the calling
+ <p>Associates a UDP port number (<c><anno>Port</anno></c>) with the calling
process.</p>
<p>The available options are:</p>
<taglist>
@@ -76,7 +72,7 @@ socket()
<p>If the host has several network interfaces, this option
specifies which one to use.</p>
</item>
- <tag><c>{fd, int()}</c></tag>
+ <tag><c>{fd, integer() >= 0}</c></tag>
<item>
<p>If a socket has somehow been opened without using
<c>gen_udp</c>, use this option to pass the file
@@ -96,7 +92,7 @@ socket()
<seealso marker="inet#setopts/2">inet:setopts/2</seealso>.</p>
</item>
</taglist>
- <p>The returned socket <c>Socket</c> is used to send packets
+ <p>The returned socket <c><anno>Socket</anno></c> is used to send packets
from this port with <c>send/4</c>. When UDP packets arrive at
the opened port, they are delivered as messages:</p>
<code type="none">
@@ -110,66 +106,42 @@ socket()
binary if the option <c>binary</c> was specified.</p>
<p>Default value for the receive buffer option is
<c>{recbuf, 8192}</c>.</p>
- <p>If <c>Port == 0</c>, the underlying OS assigns a free UDP
+ <p>If <c><anno>Port</anno> == 0</c>, the underlying OS assigns a free UDP
port, use <c>inet:port/1</c> to retrieve it.</p>
</desc>
</func>
<func>
- <name>send(Socket, Address, Port, Packet) -> ok | {error, Reason}</name>
+ <name name="send" arity="4"/>
<fsummary>Send a packet</fsummary>
- <type>
- <v>Socket = socket()</v>
- <v>Address = string() | atom() | ip_address()</v>
- <v>Port = 0..65535</v>
- <v>Packet = [char()] | binary()</v>
- <v>Reason = not_owner | posix()</v>
- </type>
<desc>
<p>Sends a packet to the specified address and port.
- The <c>Address</c> argument can be either a hostname, or an
+ The <c><anno>Address</anno></c> argument can be either a hostname, or an
IP address.</p>
</desc>
</func>
<func>
- <name>recv(Socket, Length) -> {ok, {Address, Port, Packet}} | {error, Reason}</name>
- <name>recv(Socket, Length, Timeout) -> {ok, {Address, Port, Packet}} | {error, Reason}</name>
+ <name name="recv" arity="2"/>
+ <name name="recv" arity="3"/>
<fsummary>Receive a packet from a passive socket</fsummary>
- <type>
- <v>Socket = socket()</v>
- <v>Length = int()</v>
- <v>Address = ip_address()</v>
- <v>Port = 0..65535</v>
- <v>Packet = [char()] | binary()</v>
- <v>Timeout = int() | infinity</v>
- <v>Reason = not_owner | posix()</v>
- </type>
<desc>
<p>This function receives a packet from a socket in passive
mode.</p>
- <p>The optional <c>Timeout</c> parameter specifies a timeout in
+ <p>The optional <c><anno>Timeout</anno></c> parameter specifies a timeout in
milliseconds. The default value is <c>infinity</c>.</p>
</desc>
</func>
<func>
- <name>controlling_process(Socket, Pid) -> ok</name>
+ <name name="controlling_process" arity="2"/>
<fsummary>Change controlling process of a socket</fsummary>
- <type>
- <v>Socket = socket()</v>
- <v>Pid = pid()</v>
- </type>
<desc>
- <p>Assigns a new controlling process <c>Pid</c> to
- <c>Socket</c>. The controlling process is the process which
+ <p>Assigns a new controlling process <c><anno>Pid</anno></c> to
+ <c><anno>Socket</anno></c>. The controlling process is the process which
receives messages from the socket.</p>
</desc>
</func>
<func>
- <name>close(Socket) -> ok | {error, Reason}</name>
+ <name name="close" arity="1"/>
<fsummary>Close a UDP socket</fsummary>
- <type>
- <v>Socket = socket()</v>
- <v>Reason = not_owner | posix()</v>
- </type>
<desc>
<p>Closes a UDP socket.</p>
</desc>
diff --git a/lib/kernel/doc/src/global.xml b/lib/kernel/doc/src/global.xml
index 077109d6c9..304a9b1d88 100644
--- a/lib/kernel/doc/src/global.xml
+++ b/lib/kernel/doc/src/global.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -106,45 +106,37 @@
</description>
+ <datatypes>
+ <datatype>
+ <name name="id"/>
+ </datatype>
+ </datatypes>
+
<funcs>
<func>
- <name>del_lock(Id)</name>
- <name>del_lock(Id, Nodes) -> void()</name>
+ <name name="del_lock" arity="1"/>
+ <name name="del_lock" arity="2"/>
<fsummary>Delete a lock</fsummary>
- <type>
- <v>Id = {ResourceId, LockRequesterId}</v>
- <v>&nbsp;ResourceId = term()</v>
- <v>&nbsp;LockRequesterId = term()</v>
- <v>Nodes = [node()]</v>
- </type>
<desc>
- <p>Deletes the lock <c>Id</c> synchronously.</p>
+ <p>Deletes the lock <c><anno>Id</anno></c> synchronously.</p>
</desc>
</func>
<func>
- <name>notify_all_name(Name, Pid1, Pid2) -> none</name>
+ <name name="notify_all_name" arity="3"/>
<fsummary>Name resolving function that notifies both pids</fsummary>
- <type>
- <v>Name = term()</v>
- <v>Pid1 = Pid2 = pid()</v>
- </type>
<desc>
<p>This function can be used as a name resolving function for
<c>register_name/3</c> and <c>re_register_name/3</c>. It
unregisters both pids, and sends the message
- <c>{global_name_conflict, Name, OtherPid}</c> to both
+ <c>{global_name_conflict, <anno>Name</anno>, OtherPid}</c> to both
processes.</p>
</desc>
</func>
<func>
- <name>random_exit_name(Name, Pid1, Pid2) -> Pid1 | Pid2</name>
+ <name name="random_exit_name" arity="3"/>
<fsummary>Name resolving function that kills one pid</fsummary>
- <type>
- <v>Name = term()</v>
- <v>Pid1 = Pid2 = pid()</v>
- </type>
<desc>
<p>This function can be used as a name resolving function for
<c>register_name/3</c> and <c>re_register_name/3</c>. It
@@ -154,33 +146,27 @@
</func>
<func>
- <name>random_notify_name(Name, Pid1, Pid2) -> Pid1 | Pid2</name>
+ <name name="random_notify_name" arity="3"/>
<fsummary>Name resolving function that notifies one pid</fsummary>
- <type>
- <v>Name = term()</v>
- <v>Pid1 = Pid2 = pid()</v>
- </type>
<desc>
<p>This function can be used as a name resolving function for
<c>register_name/3</c> and <c>re_register_name/3</c>. It
randomly chooses one of the pids for registration, and sends
- the message <c>{global_name_conflict, Name}</c> to the other
+ the message <c>{global_name_conflict, <anno>Name</anno>}</c> to the other
pid.</p>
</desc>
</func>
<func>
- <name>register_name(Name, Pid)</name>
- <name>register_name(Name, Pid, Resolve) -> yes | no</name>
+ <name name="register_name" arity="2"/>
+ <name name="register_name" arity="3"/>
<fsummary>Globally register a name for a pid</fsummary>
- <type>
- <v>Name = term()</v>
- <v>Pid = pid()</v>
- <v>Resolve = fun() or {Module, Function} where</v>
- <v>&nbsp;&nbsp;Resolve(Name, Pid, Pid2) -> Pid | Pid2 | none</v>
- </type>
+ <type name="method"/>
+ <type_desc name="method">{<c>Module</c>, <c>Function</c>}
+ is also allowed
+ </type_desc>
<desc>
- <p>Globally associates the name <c>Name</c> with a pid, that is,
+ <p>Globally associates the name <c><anno>Name</anno></c> with a pid, that is,
Globally notifies all nodes of a new global name in a network
of Erlang nodes.</p>
@@ -188,7 +174,7 @@
of the globally registered names that already exist.
The network is also informed of any global names in newly
connected nodes. If any name clashes are discovered,
- the <c>Resolve</c> function is called. Its purpose is to
+ the <c><anno>Resolve</anno></c> function is called. Its purpose is to
decide which pid is correct. If the function crashes, or
returns anything other than one of the pids, the name is
unregistered. This function is called once for each name
@@ -196,7 +182,7 @@
<p>There are three pre-defined resolve functions:
<c>random_exit_name/3</c>, <c>random_notify_name/3</c>, and
- <c>notify_all_name/3</c>. If no <c>Resolve</c> function is
+ <c>notify_all_name/3</c>. If no <c><anno>Resolve</anno></c> function is
defined, <c>random_exit_name</c> is used. This means that one
of the two registered processes will be selected as correct
while the other is killed.</p>
@@ -225,78 +211,63 @@
</func>
<func>
- <name>registered_names() -> [Name]</name>
+ <name name="registered_names" arity="0"/>
<fsummary>All globally registered names</fsummary>
- <type>
- <v>Name = term()</v>
- </type>
<desc>
<p>Returns a lists of all globally registered names.</p>
</desc>
</func>
<func>
- <name>re_register_name(Name, Pid)</name>
- <name>re_register_name(Name, Pid, Resolve) -> void()</name>
+ <name name="re_register_name" arity="2"/>
+ <name name="re_register_name" arity="3"/>
<fsummary>Atomically re-register a name</fsummary>
- <type>
- <v>Name = term()</v>
- <v>Pid = pid()</v>
- <v>Resolve = fun() or {Module, Function} where</v>
- <v>&nbsp;&nbsp;Resolve(Name, Pid, Pid2) -> Pid | Pid2 | none</v>
- </type>
+ <type name="method"/>
+ <type_desc name="method">{<c>Module</c>, <c>Function</c>}
+ is also allowed
+ </type_desc>
<desc>
- <p>Atomically changes the registered name <c>Name</c> on all
- nodes to refer to <c>Pid</c>.</p>
+ <p>Atomically changes the registered name <c><anno>Name</anno></c> on all
+ nodes to refer to <c><anno>Pid</anno></c>.</p>
- <p>The <c>Resolve</c> function has the same behavior as in
+ <p>The <c><anno>Resolve</anno></c> function has the same behavior as in
<c>register_name/2,3</c>.</p>
</desc>
</func>
<func>
- <name>send(Name, Msg) -> Pid</name>
+ <name name="send" arity="2"/>
<fsummary>Send a message to a globally registered pid</fsummary>
- <type>
- <v>Name = term()</v>
- <v>Msg = term()</v>
- <v>Pid = pid()</v>
- </type>
<desc>
- <p>Sends the message <c>Msg</c> to the pid globally registered
- as <c>Name</c>.</p>
+ <p>Sends the message <c><anno>Msg</anno></c> to the pid globally registered
+ as <c><anno>Name</anno></c>.</p>
- <p>Failure: If <c>Name</c> is not a globally registered
+ <p>Failure: If <c><anno>Name</anno></c> is not a globally registered
name, the calling function will exit with reason
- <c>{badarg, {Name, Msg}}</c>.</p>
+ <c>{badarg, {<anno>Name</anno>, <anno>Msg</anno>}}</c>.</p>
</desc>
</func>
<func>
- <name>set_lock(Id)</name>
- <name>set_lock(Id, Nodes)</name>
- <name>set_lock(Id, Nodes, Retries) -> boolean()</name>
+ <name name="set_lock" arity="1"/>
+ <name name="set_lock" arity="2"/>
+ <name name="set_lock" arity="3"/>
<fsummary>Set a lock on the specified nodes</fsummary>
- <type>
- <v>Id = {ResourceId, LockRequesterId}</v>
- <v>&nbsp;ResourceId = term()</v>
- <v>&nbsp;LockRequesterId = term()</v>
- <v>Nodes = [node()]</v>
- <v>Retries = int() >= 0 | infinity</v>
- </type>
+ <type name="id"/>
+ <type name="retries"/>
<desc>
<p>Sets a lock on the specified nodes (or on all nodes if none
- are specified) on <c>ResourceId</c> for
- <c>LockRequesterId</c>. If a lock already exists on
- <c>ResourceId</c> for another requester than
- <c>LockRequesterId</c>, and <c>Retries</c> is not equal to 0,
+ are specified) on <c><anno>ResourceId</anno></c> for
+ <c><anno>LockRequesterId</anno></c>. If a lock already exists on
+ <c><anno>ResourceId</anno></c> for another requester than
+ <c><anno>LockRequesterId</anno></c>, and <c><anno>Retries</anno></c> is not equal to 0,
the process sleeps for a while and will try to execute
- the action later. When <c>Retries</c> attempts have been made,
+ the action later. When <c><anno>Retries</anno></c> attempts have been made,
<c>false</c> is returned, otherwise <c>true</c>. If
- <c>Retries</c> is <c>infinity</c>, <c>true</c> is eventually
+ <c><anno>Retries</anno></c> is <c>infinity</c>, <c>true</c> is eventually
returned (unless the lock is never released).</p>
- <p>If no value for <c>Retries</c> is given, <c>infinity</c> is
+ <p>If no value for <c><anno>Retries</anno></c> is given, <c>infinity</c> is
used.</p>
<p>This function is completely synchronous.</p>
@@ -315,7 +286,7 @@
application to detect and rectify a deadlock.</p>
<note>
- <p>Some values of <c>ResourceId</c> should be avoided or
+ <p>Some values of <c><anno>ResourceId</anno></c> should be avoided or
Erlang/OTP will not work properly. A list of resources to
avoid: <c>global</c>, <c>dist_ac</c>,
<c>mnesia_table_lock</c>, <c>mnesia_adjust_log_writes</c>,
@@ -326,7 +297,7 @@
</func>
<func>
- <name>sync() -> void()</name>
+ <name name="sync" arity="0"/>
<fsummary>Synchronize the global name server</fsummary>
<desc>
<p>Synchronizes the global name server with all nodes known to
@@ -335,56 +306,45 @@
the global name server will receive global information from
all nodes. This function can be called when new nodes are
added to the network.</p>
+ <p>The only possible error reason <c>Reason</c> is
+ <c>{"global_groups definition error", Error}</c>.</p>
</desc>
</func>
<func>
- <name>trans(Id, Fun)</name>
- <name>trans(Id, Fun, Nodes)</name>
- <name>trans(Id, Fun, Nodes, Retries) -> Res | aborted</name>
+ <name name="trans" arity="2"/>
+ <name name="trans" arity="3"/>
+ <name name="trans" arity="4"/>
<fsummary>Micro transaction facility</fsummary>
- <type>
- <v>Id = {ResourceId, LockRequesterId}</v>
- <v>&nbsp;ResourceId = term()</v>
- <v>&nbsp;LockRequesterId = term()</v>
- <v>Fun = fun() | {M, F}</v>
- <v>Nodes = [node()]</v>
- <v>Retries = int() >= 0 | infinity</v>
- <v>Res = term()</v>
- </type>
+ <type name="retries"/>
+ <type name="trans_fun"/>
<desc>
- <p>Sets a lock on <c>Id</c> (using <c>set_lock/3</c>). If this
- succeeds, <c>Fun()</c> is evaluated and the result <c>Res</c>
+ <p>Sets a lock on <c><anno>Id</anno></c> (using <c>set_lock/3</c>). If this
+ succeeds, <c><anno>Fun</anno>()</c> is evaluated and the result <c><anno>Res</anno></c>
is returned. Returns <c>aborted</c> if the lock attempt
- failed. If <c>Retries</c> is set to <c>infinity</c>,
+ failed. If <c><anno>Retries</anno></c> is set to <c>infinity</c>,
the transaction will not abort.</p>
<p><c>infinity</c> is the default setting and will be used if
- no value is given for <c>Retries</c>.</p>
+ no value is given for <c><anno>Retries</anno></c>.</p>
</desc>
</func>
<func>
- <name>unregister_name(Name) -> void()</name>
+ <name name="unregister_name" arity="1"/>
<fsummary>Remove a globally registered name for a pid</fsummary>
- <type>
- <v>Name = term()</v>
- </type>
<desc>
- <p>Removes the globally registered name <c>Name</c> from
+ <p>Removes the globally registered name <c><anno>Name</anno></c> from
the network of Erlang nodes.</p>
</desc>
</func>
<func>
- <name>whereis_name(Name) -> pid() | undefined</name>
+ <name name="whereis_name" arity="1"/>
<fsummary>Get the pid with a given globally registered name</fsummary>
- <type>
- <v>Name = term()</v>
- </type>
<desc>
<p>Returns the pid with the globally registered name
- <c>Name</c>. Returns <c>undefined</c> if the name is not
+ <c><anno>Name</anno></c>. Returns <c>undefined</c> if the name is not
globally registered.</p>
</desc>
</func>
diff --git a/lib/kernel/doc/src/global_group.xml b/lib/kernel/doc/src/global_group.xml
index 4facf4a4aa..abf6178fc4 100644
--- a/lib/kernel/doc/src/global_group.xml
+++ b/lib/kernel/doc/src/global_group.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1998</year><year>2009</year>
+ <year>1998</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -42,26 +42,7 @@
<seealso marker="kernel_app">kernel(6)</seealso>,
<seealso marker="config">config(4)</seealso>:</p>
<code type="none">
-{global_groups, [GroupTuple]}</code>
- <p>Types:</p>
- <list type="bulleted">
- <item><c>GroupTuple = {GroupName, [Node]} | {GroupName, PublishType, [Node]}</c></item>
- <item><c>GroupName = atom()</c> (naming a global group)</item>
- <item><c>PublishType = normal | hidden</c></item>
- <item><c>Node = atom()</c> (naming a node)</item>
- </list>
- <p>A <c>GroupTuple</c> without <c>PublishType</c> is the same as a
- <c>GroupTuple</c> with <c>PublishType == normal</c>.</p>
- <p>A node started with the command line flag <c>-hidden</c>, see
- <seealso marker="erts:erl">erl(1)</seealso>, is said to be a
- <em>hidden</em> node. A hidden node will establish hidden
- connections to nodes not part of the same global group, but
- normal (visible) connections to nodes part of the same global
- group.</p>
- <p>A global group defined with <c>PublishType == hidden</c>, is
- said to be a hidden global group. All nodes in a hidden global
- group are hidden nodes, regardless if they are started with
- the <c>-hidden</c> command line flag or not.</p>
+{global_groups, [GroupTuple :: group_tuple()]}</code>
<p>For the processes and nodes to run smoothly using the global
group functionality, the following criteria must be met:</p>
<list type="bulleted">
@@ -82,14 +63,44 @@
<p>In the following description, a <em>group node</em> is a node
belonging to the same global group as the local node.</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="group_tuple"/>
+ <desc>
+ <p>A <c>GroupTuple</c> without <c>PublishType</c> is the same as a
+ <c>GroupTuple</c> with <c>PublishType == normal</c>.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="group_name"/>
+ </datatype>
+ <datatype>
+ <name name="publish_type"/>
+ <desc>
+ <p>A node started with the command line flag <c>-hidden</c>, see
+ <seealso marker="erts:erl">erl(1)</seealso>, is said to be a
+ <em>hidden</em> node. A hidden node will establish hidden
+ connections to nodes not part of the same global group, but
+ normal (visible) connections to nodes part of the same global
+ group.</p>
+ <p>A global group defined with <c>PublishType == hidden</c>, is
+ said to be a hidden global group. All nodes in a hidden global
+ group are hidden nodes, regardless if they are started with
+ the <c>-hidden</c> command line flag or not.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="name"/>
+ <desc><p>A registered name.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="where"/>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>global_groups() -> {GroupName, GroupNames} | undefined</name>
+ <name name="global_groups" arity="0"/>
<fsummary>Return the global group names</fsummary>
- <type>
- <v>GroupName = atom()</v>
- <v>GroupNames = [GroupName]</v>
- </type>
<desc>
<p>Returns a tuple containing the name of the global group
the local node belongs to, and the list of all other known
@@ -98,53 +109,52 @@
</desc>
</func>
<func>
- <name>info() -> [{Item, Info}]</name>
+ <name name="info" arity="0"/>
<fsummary>Information about global groups</fsummary>
- <type>
- <v>Item, Info -- see below</v>
- </type>
+ <type name="info_item"/>
+ <type name="sync_state"/>
<desc>
<p>Returns a list containing information about the global
groups. Each element of the list is a tuple. The order of
the tuples is not defined.</p>
<taglist>
- <tag><c>{state, State}</c></tag>
+ <tag><c>{state, <anno>State</anno>}</c></tag>
<item>
<p>If the local node is part of a global group,
- <c>State == synced</c>. If no global groups are defined,
- <c>State == no_conf</c>.</p>
+ <c><anno>State</anno> == synced</c>. If no global groups are defined,
+ <c><anno>State</anno> == no_conf</c>.</p>
</item>
- <tag><c>{own_group_name, GroupName}</c></tag>
+ <tag><c>{own_group_name, <anno>GroupName</anno>}</c></tag>
<item>
<p>The name (atom) of the group that the local node belongs
to.</p>
</item>
- <tag><c>{own_group_nodes, Nodes}</c></tag>
+ <tag><c>{own_group_nodes, <anno>Nodes</anno>}</c></tag>
<item>
<p>A list of node names (atoms), the group nodes.</p>
</item>
- <tag><c>{synced_nodes, Nodes}</c></tag>
+ <tag><c>{synced_nodes, <anno>Nodes</anno>}</c></tag>
<item>
<p>A list of node names, the group nodes currently
synchronized with the local node.</p>
</item>
- <tag><c>{sync_error, Nodes}</c></tag>
+ <tag><c>{sync_error, <anno>Nodes</anno>}</c></tag>
<item>
<p>A list of node names, the group nodes with which
the local node has failed to synchronize.</p>
</item>
- <tag><c>{no_contact, Nodes}</c></tag>
+ <tag><c>{no_contact, <anno>Nodes</anno>}</c></tag>
<item>
<p>A list of node names, the group nodes to which there are
currently no connections.</p>
</item>
- <tag><c>{other_groups, Groups}</c></tag>
+ <tag><c>{other_groups, <anno>Groups</anno>}</c></tag>
<item>
- <p><c>Groups</c> is a list of tuples
- <c>{GroupName, Nodes}</c>, specifying the name and nodes
+ <p><c><anno>Groups</anno></c> is a list of tuples
+ <c>{<anno>GroupName</anno>, <anno>Nodes</anno>}</c>, specifying the name and nodes
of the other global groups.</p>
</item>
- <tag><c>{monitoring, Pids}</c></tag>
+ <tag><c>{monitoring, <anno>Pids</anno>}</c></tag>
<item>
<p>A list of pids, specifying the processes which have
subscribed to <c>nodeup</c> and <c>nodedown</c> messages.</p>
@@ -153,73 +163,52 @@
</desc>
</func>
<func>
- <name>monitor_nodes(Flag) -> ok </name>
+ <name name="monitor_nodes" arity="1"/>
<fsummary>Subscribe to node status changes</fsummary>
- <type>
- <v>Flag = bool()</v>
- </type>
<desc>
- <p>Depending on <c>Flag</c>, the calling process starts
- subscribing (<c>Flag == true</c>) or stops subscribing
- (<c>Flag == false</c>) to node status change messages.</p>
+ <p>Depending on <c><anno>Flag</anno></c>, the calling process starts
+ subscribing (<c><anno>Flag</anno> == true</c>) or stops subscribing
+ (<c><anno>Flag</anno> == false</c>) to node status change messages.</p>
<p>A process which has subscribed will receive the messages
<c>{nodeup, Node}</c> and <c>{nodedown, Node}</c> when a
group node connects or disconnects, respectively.</p>
</desc>
</func>
<func>
- <name>own_nodes() -> Nodes</name>
+ <name name="own_nodes" arity="0"/>
<fsummary>Return the group nodes</fsummary>
- <type>
- <v>Nodes = [Node]</v>
- <v>&nbsp;Node = node()</v>
- </type>
<desc>
<p>Returns the names of all group nodes, regardless of their
current status.</p>
</desc>
</func>
<func>
- <name>registered_names(Where) -> Names</name>
+ <name name="registered_names" arity="1"/>
<fsummary>Return globally registered names</fsummary>
- <type>
- <v>Where = {node, Node} | {group, GroupName}</v>
- <v>&nbsp;Node = node()</v>
- <v>&nbsp;GroupName = atom()</v>
- <v>Names = [Name]</v>
- <v>&nbsp;Name = atom()</v>
- </type>
<desc>
<p>Returns a list of all names which are globally registered
on the specified node or in the specified global group.</p>
</desc>
</func>
<func>
- <name>send(Name, Msg) -> pid() | {badarg, {Name, Msg}}</name>
- <name>send(Where, Name, Msg) -> pid() | {badarg, {Name, Msg}}</name>
+ <name name="send" arity="2"/>
+ <name name="send" arity="3"/>
<fsummary>Send a message to a globally registered pid</fsummary>
- <type>
- <v>Where = {node, Node} | {group, GroupName}</v>
- <v>&nbsp;Node = node()</v>
- <v>&nbsp;GroupName = atom()</v>
- <v>Name = atom()</v>
- <v>Msg = term()</v>
- </type>
<desc>
- <p>Searches for <c>Name</c>, globally registered on
+ <p>Searches for <c><anno>Name</anno></c>, globally registered on
the specified node or in the specified global group, or --
- if the <c>Where</c> argument is not provided -- in any global
+ if the <c><anno>Where</anno></c> argument is not provided -- in any global
group. The global groups are searched in the order in which
they appear in the value of the <c>global_groups</c>
configuration parameter.</p>
- <p>If <c>Name</c> is found, the message <c>Msg</c> is sent to
+ <p>If <c><anno>Name</anno></c> is found, the message <c><anno>Msg</anno></c> is sent to
the corresponding pid. The pid is also the return value of
the function. If the name is not found, the function returns
- <c>{badarg, {Name, Msg}}</c>.</p>
+ <c>{badarg, {<anno>Name</anno>, <anno>Msg</anno>}}</c>.</p>
</desc>
</func>
<func>
- <name>sync() -> ok</name>
+ <name name="sync" arity="0"/>
<fsummary>Synchronize the group nodes</fsummary>
<desc>
<p>Synchronizes the group nodes, that is, the global name
@@ -235,23 +224,17 @@
</desc>
</func>
<func>
- <name>whereis_name(Name) -> pid() | undefined</name>
- <name>whereis_name(Where, Name) -> pid() | undefined</name>
+ <name name="whereis_name" arity="1"/>
+ <name name="whereis_name" arity="2"/>
<fsummary>Get the pid with a given globally registered name</fsummary>
- <type>
- <v>Where = {node, Node} | {group, GroupName}</v>
- <v>&nbsp;Node = node()</v>
- <v>&nbsp;GroupName = atom()</v>
- <v>Name = atom()</v>
- </type>
<desc>
- <p>Searches for <c>Name</c>, globally registered on
+ <p>Searches for <c><anno>Name</anno></c>, globally registered on
the specified node or in the specified global group, or -- if
- the <c>Where</c> argument is not provided -- in any global
+ the <c><anno>Where</anno></c> argument is not provided -- in any global
group. The global groups are searched in the order in which
they appear in the value of the <c>global_groups</c>
configuration parameter.</p>
- <p>If <c>Name</c> is found, the corresponding pid is returned.
+ <p>If <c><anno>Name</anno></c> is found, the corresponding pid is returned.
If the name is not found, the function returns
<c>undefined</c>.</p>
</desc>
diff --git a/lib/kernel/doc/src/heart.xml b/lib/kernel/doc/src/heart.xml
index 0df699572d..e2dbcbe63d 100644
--- a/lib/kernel/doc/src/heart.xml
+++ b/lib/kernel/doc/src/heart.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -76,11 +76,8 @@
</description>
<funcs>
<func>
- <name>set_cmd(Cmd) -> ok | {error, {bad_cmd, Cmd}}</name>
+ <name name="set_cmd" arity="1"/>
<fsummary>Set a temporary reboot command</fsummary>
- <type>
- <v>Cmd = string()</v>
- </type>
<desc>
<p>Sets a temporary reboot command. This command is used if
a <c>HEART_COMMAND</c> other than the one specified with
@@ -88,12 +85,12 @@
the system. The new Erlang runtime system will (if it
misbehaves) use the environment variable
<c>HEART_COMMAND</c> to reboot.</p>
- <p>Limitations: The length of the <c>Cmd</c> command string
+ <p>Limitations: The length of the <c><anno>Cmd</anno></c> command string
must be less than 2047 characters.</p>
</desc>
</func>
<func>
- <name>clear_cmd() -> ok</name>
+ <name name="clear_cmd" arity="0"/>
<fsummary>Clear the temporary boot command</fsummary>
<desc>
<p>Clears the temporary boot command. If the system terminates,
@@ -101,11 +98,8 @@
</desc>
</func>
<func>
- <name>get_cmd() -> {ok, Cmd}</name>
+ <name name="get_cmd" arity="0"/>
<fsummary>Get the temporary reboot command</fsummary>
- <type>
- <v>Cmd = string()</v>
- </type>
<desc>
<p>Get the temporary reboot command. If the command is cleared,
the empty string will be returned.</p>
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml
index f05a224f33..fad5af85bb 100644
--- a/lib/kernel/doc/src/inet.xml
+++ b/lib/kernel/doc/src/inet.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2010</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -54,33 +54,6 @@ $ <input>erl -sname test -kernel \</input>
<input>inet_default_listen_options '[{delay_send,true}]'</input></pre>
<p>Note that the default option <c>{active, true}</c> currently
cannot be changed, for internal reasons.</p>
- </description>
-
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-#hostent{h_addr_list = [ip_address()] % list of addresses for this host
- h_addrtype = inet | inet6
- h_aliases = [hostname()] % list of aliases
- h_length = int() % length of address in bytes
- h_name = hostname() % official name for host
- The record is defined in the Kernel include file "inet.hrl"
- Add the following directive to the module:
- -include_lib("kernel/include/inet.hrl").
-
-hostname() = atom() | string()
-
-ip_address() = {N1,N2,N3,N4} % IPv4
- | {K1,K2,K3,K4,K5,K6,K7,K8} % IPv6
- Ni = 0..255
- Ki = 0..65535
-
-posix()
- an atom which is named from the Posix error codes used in
- Unix, and in the runtime libraries of most C compilers
-
-socket()
- see gen_tcp(3), gen_udp(3)</code>
<p>Addresses as inputs to functions can be either a string or a
tuple. For instance, the IP address 150.236.20.73 can be passed to
<c>gethostbyaddr/1</c> either as the string "150.236.20.73"
@@ -109,24 +82,61 @@ fe80::204:acff:fe17:bf38
{ok,{192,168,42,2}}
2> <input>inet_parse:address("FFFF::192.168.42.2").</input>
{ok,{65535,0,0,0,0,0,49320,10754}}</pre>
- </section>
+ </description>
+
+ <datatypes>
+ <datatype>
+ <name name="hostent"/>
+ <desc>
+ <p>The record is defined in the Kernel include file "inet.hrl".
+ Add the following directive to the module:</p>
+<code>-include_lib("kernel/include/inet.hrl").</code></desc>
+ </datatype>
+ <datatype>
+ <name name="hostname"/>
+ </datatype>
+ <datatype>
+ <name name="ip_address"/>
+ </datatype>
+ <datatype>
+ <name name="ip4_address"/>
+ </datatype>
+ <datatype>
+ <name name="ip6_address"/>
+ </datatype>
+ <datatype>
+ <name name="port_number"/>
+ </datatype>
+ <datatype>
+ <name name="posix"/>
+ <desc><p>An atom which is named from the Posix error codes
+ used in Unix, and in the runtime libraries of most
+ C compilers. See
+ <seealso marker="#error_codes">POSIX Error Codes</seealso>.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name><marker id="type-socket">socket()</marker></name>
+ <desc><p>See <seealso marker="gen_tcp#type-socket">gen_tcp(3)</seealso>
+ and <seealso marker="gen_udp#type-socket">gen_udp(3)</seealso>.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="address_family"/>
+ </datatype>
+ </datatypes>
+
<funcs>
<func>
- <name>close(Socket) -> ok</name>
+ <name name="close" arity="1"/>
<fsummary>Close a socket of any type</fsummary>
- <type>
- <v>Socket = socket()</v>
- </type>
<desc>
<p>Closes a socket of any type.</p>
</desc>
</func>
<func>
- <name>get_rc() -> [{Par, Val}]</name>
+ <name name="get_rc" arity="0"/>
<fsummary>Return a list of IP configuration parameters</fsummary>
- <type>
- <v>Par, Val -- see below</v>
- </type>
<desc>
<p>Returns the state of the Inet configuration database in
form of a list of recorded configuration parameters. (See the
@@ -135,116 +145,74 @@ fe80::204:acff:fe17:bf38
</desc>
</func>
<func>
- <name>format_error(Posix) -> string()</name>
+ <name name="format_error" arity="1"/>
<fsummary>Return a descriptive string for an error reason</fsummary>
- <type>
- <v>Posix = posix()</v>
- </type>
<desc>
<p>Returns a diagnostic error string. See the section below
- for possible <c>Posix</c> values and the corresponding
+ for possible <c><anno>Posix</anno></c> values and the corresponding
strings.</p>
</desc>
</func>
<func>
- <name>getaddr(Host, Family) -> {ok, Address} | {error, posix()}</name>
+ <name name="getaddr" arity="2"/>
<fsummary>Return the IP-address for a host</fsummary>
- <type>
- <v>Host = ip_address() | string() | atom()</v>
- <v>Family = inet | inet6</v>
- <v>Address = ip_address()</v>
- <v>posix() = term()</v>
- </type>
<desc>
- <p>Returns the IP-address for <c>Host</c> as a tuple of
- integers. <c>Host</c> can be an IP-address, a single hostname
+ <p>Returns the IP-address for <c><anno>Host</anno></c> as a tuple of
+ integers. <c><anno>Host</anno></c> can be an IP-address, a single hostname
or a fully qualified hostname.</p>
</desc>
</func>
<func>
- <name>getaddrs(Host, Family) -> {ok, Addresses} | {error, posix()}</name>
+ <name name="getaddrs" arity="2"/>
<fsummary>Return the IP-addresses for a host</fsummary>
- <type>
- <v>Host = ip_address() | string() | atom()</v>
- <v>Addresses = [ip_address()]</v>
- <v>Family = inet | inet6</v>
- </type>
<desc>
- <p>Returns a list of all IP-addresses for <c>Host</c>.
- <c>Host</c> can be an IP-address, a single hostname or a fully
+ <p>Returns a list of all IP-addresses for <c><anno>Host</anno></c>.
+ <c><anno>Host</anno></c> can be an IP-address, a single hostname or a fully
qualified hostname.</p>
</desc>
</func>
<func>
- <name>gethostbyaddr(Address) -> {ok, Hostent} | {error, posix()}</name>
+ <name name="gethostbyaddr" arity="1"/>
<fsummary>Return a hostent record for the host with the given address</fsummary>
- <type>
- <v>Address = string() | ip_address()</v>
- <v>Hostent = #hostent{}</v>
- </type>
<desc>
<p>Returns a <c>hostent</c> record given an address.</p>
</desc>
</func>
<func>
- <name>gethostbyname(Name) -> {ok, Hostent} | {error, posix()}</name>
+ <name name="gethostbyname" arity="1"/>
<fsummary>Return a hostent record for the host with the given name</fsummary>
- <type>
- <v>Hostname = hostname()</v>
- <v>Hostent = #hostent{}</v>
- </type>
<desc>
<p>Returns a <c>hostent</c> record given a hostname.</p>
</desc>
</func>
<func>
- <name>gethostbyname(Name, Family) -> {ok, Hostent} | {error, posix()}</name>
+ <name name="gethostbyname" arity="2"/>
<fsummary>Return a hostent record for the host with the given name</fsummary>
- <type>
- <v>Hostname = hostname()</v>
- <v>Family = inet | inet6</v>
- <v>Hostent = #hostent{}</v>
- </type>
<desc>
<p>Returns a <c>hostent</c> record given a hostname, restricted
to the given address family.</p>
</desc>
</func>
<func>
- <name>gethostname() -> {ok, Hostname}</name>
+ <name name="gethostname" arity="0"/>
<fsummary>Return the local hostname</fsummary>
- <type>
- <v>Hostname = string()</v>
- </type>
<desc>
<p>Returns the local hostname. Will never fail.</p>
</desc>
</func>
<func>
- <name>getifaddrs() -> {ok,Iflist} | {error,posix}</name>
+ <name name="getifaddrs" arity="0"/>
<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
+ interface's addresses. <c><anno>Ifname</anno></c> is a Unicode string.
+ <c><anno>Hwaddr</anno></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>
+ The <c>{addr,<anno>Addr</anno>}</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
@@ -252,8 +220,8 @@ fe80::204:acff:fe17:bf38
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:
+ Do not rely too much on the order of <c><anno>Flag</anno></c> atoms or
+ <c><anno>Ifopt</anno></c> tuples. There are some rules, though:
<list>
<item>
Immediately after <c>{addr,_}</c> follows <c>{netmask,_}</c>
@@ -261,7 +229,7 @@ fe80::204:acff:fe17:bf38
<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.
+ <c>pointtopoint</c> flag <em>is</em> set.
</item>
<item>
Any <c>{netmask,_}</c>, <c>{broadaddr,_}</c> or
@@ -277,32 +245,23 @@ fe80::204:acff:fe17:bf38
</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.
+ functions, so the <c><anno>Netmask</anno></c> and <c><anno>Broadaddr</anno></c>
+ values may be calculated, just as some <c><anno>Flag</anno></c> values.
You have been warned. Report flagrant bugs.
</p>
</desc>
+ </func>
<func>
- <name>getopts(Socket, Options) -> {ok, OptionValues} | {error, posix()}</name>
+ <name name="getopts" arity="2"/>
<fsummary>Get one or more options for a socket</fsummary>
- <type>
- <v>Socket = term()</v>
- <v>Options = [Opt | RawOptReq]</v>
- <v>Opt = atom()</v>
- <v>RawOptReq = {raw, Protocol, OptionNum, ValueSpec}</v>
- <v>Protocol = int()</v>
- <v>OptionNum = int()</v>
- <v>ValueSpec = ValueSize | ValueBin</v>
- <v>ValueSize = int()</v>
- <v>ValueBin = binary()</v>
- <v>OptionValues = [{Opt, Val} | {raw, Protocol, OptionNum, ValueBin}]</v>
- </type>
+ <type name="socket_getopt"/>
+ <type name="socket_setopt"/>
<desc>
<p>Gets one or more options for a socket.
See <seealso marker="#setopts/2">setopts/2</seealso>
for a list of available options.</p>
- <p>The number of elements in the returned <c>OptionValues</c>
+ <p>The number of elements in the returned <c><anno>OptionValues</anno></c>
list does not necessarily correspond to the number of options
asked for. If the operating system fails to support an option,
it is simply left out in the returned list. An error tuple is only
@@ -310,12 +269,12 @@ fe80::204:acff:fe17:bf38
(i.e. the socket is closed or the buffer size in a raw request
is too large). This behavior is kept for backward
compatibility reasons.</p>
- <p>A <c>RawOptReq</c> can be used to get information about
+ <p>A raw option request <c>RawOptReq = {raw, Protocol, OptionNum, ValueSpec}</c> can be used to get information about
socket options not (explicitly) supported by the emulator. The
use of raw socket options makes the code non portable, but
allows the Erlang programmer to take advantage of unusual features
present on the current platform.</p>
- <p>The <c>RawOptReq</c> consists of the tag <c>raw</c> followed
+ <p>The <c>RawOptReq</c> consists of the tag <c>raw</c> followed
by the protocol level, the option number and either a binary
or the size, in bytes, of the
buffer in which the option value is to be stored. A binary
@@ -358,19 +317,14 @@ fe80::204:acff:fe17:bf38
</func>
<func>
- <name>getstat(Socket)</name>
- <name>getstat(Socket, Options) -> {ok, OptionValues} | {error, posix()}</name>
+ <name name="getstat" arity="1"/>
+ <name name="getstat" arity="2"/>
<fsummary>Get one or more statistic options for a socket</fsummary>
- <type>
- <v>Socket = term()</v>
- <v>Options = [Opt]</v>
- <v>OptionValues = [{Opt, Val}]</v>
- <v>&nbsp;Opt, Val -- see below</v>
- </type>
+ <type name="stat_option"/>
<desc>
<p>Gets one or more statistic options for a socket.</p>
- <p><c>getstat(Socket)</c> is equivalent to
- <c>getstat(Socket,&nbsp;[recv_avg,&nbsp;recv_cnt,&nbsp;recv_dvi,&nbsp;recv_max,&nbsp;recv_oct,&nbsp;send_avg,&nbsp;send_cnt,&nbsp;send_dvi,&nbsp;send_max,&nbsp;send_oct])</c></p>
+ <p><c>getstat(<anno>Socket</anno>)</c> is equivalent to
+ <c>getstat(<anno>Socket</anno>,&nbsp;[recv_avg,&nbsp;recv_cnt,&nbsp;recv_dvi,&nbsp;recv_max,&nbsp;recv_oct,&nbsp;send_avg,&nbsp;send_cnt,&nbsp;send_dvi,&nbsp;send_max,&nbsp;send_oct])</c></p>
<p>The following options are available:</p>
<taglist>
<tag><c>recv_avg</c></tag>
@@ -419,52 +373,31 @@ fe80::204:acff:fe17:bf38
</func>
<func>
- <name>peername(Socket) -> {ok, {Address, Port}} | {error, posix()}</name>
+ <name name="peername" arity="1"/>
<fsummary>Return the address and port for the other end of a connection</fsummary>
- <type>
- <v>Socket = socket()</v>
- <v>Address = ip_address()</v>
- <v>Port = int()</v>
- </type>
<desc>
<p>Returns the address and port for the other end of a
connection.</p>
</desc>
</func>
<func>
- <name>port(Socket) -> {ok, Port} | {error, any()}</name>
+ <name name="port" arity="1"/>
<fsummary>Return the local port number for a socket</fsummary>
- <type>
- <v>Socket = socket()</v>
- <v>Port = int()</v>
- </type>
<desc>
<p>Returns the local port number for a socket.</p>
</desc>
</func>
<func>
- <name>sockname(Socket) -> {ok, {Address, Port}} | {error, posix()}</name>
+ <name name="sockname" arity="1"/>
<fsummary>Return the local address and port number for a socket</fsummary>
- <type>
- <v>Socket = socket()</v>
- <v>Address = ip_address()</v>
- <v>Port = int()</v>
- </type>
<desc>
<p>Returns the local address and port number for a socket.</p>
</desc>
</func>
<func>
- <name>setopts(Socket, Options) -> ok | {error, posix()}</name>
+ <name name="setopts" arity="2"/>
<fsummary>Set one or more options for a socket</fsummary>
- <type>
- <v>Socket = term()</v>
- <v>Options = [{Opt, Val} | {raw, Protocol, Option, ValueBin}]</v>
- <v>Protocol = int()</v>
- <v>OptionNum = int()</v>
- <v>ValueBin = binary()</v>
- <v>&nbsp;Opt, Val -- see below</v>
- </type>
+ <type name="socket_setopt"/>
<desc>
<p>Sets one or more options for a socket. The following options
are available:</p>
@@ -622,8 +555,14 @@ fe80::204:acff:fe17:bf38
mode will return <c>{ok, HttpPacket}</c> from <c>gen_tcp:recv</c>
while an active socket will send messages like <c>{http,
Socket, HttpPacket}</c>.</p>
- <p>Note that the packet type <c>httph</c> is not
- needed when reading from a socket.</p>
+ </item>
+ <tag><c>httph | httph_bin</c></tag>
+ <item>
+ <p>These two types are often not needed as the socket will
+ automatically switch from <c>http</c>/<c>http_bin</c> to
+ <c>httph</c>/<c>httph_bin</c> internally after the first line
+ has been read. There might be occasions however when they are
+ useful, such as parsing trailers from chunked encoding.</p>
</item>
</taglist>
</item>
diff --git a/lib/kernel/doc/src/inet_res.xml b/lib/kernel/doc/src/inet_res.xml
index d8fe23544b..bf73ccf13d 100644
--- a/lib/kernel/doc/src/inet_res.xml
+++ b/lib/kernel/doc/src/inet_res.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2009</year><year>2009</year>
+ <year>2009</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -76,64 +76,38 @@
query is tried for the <c>alt_nameservers</c>.</p>
</section>
-
-
-
- <section>
- <title>DATA TYPES</title>
- <p>As defined in the module
- <seealso marker="kernel:inet">inet</seealso>:</p>
- <code type="none">
-hostent() = #hostent{}
-posix() = some atom()s
-ip_address() = tuple of integers of arity 4 or 8</code>
-
+ <datatypes>
<p>Resolver types:</p>
- <code type="none">These correspond to resolver options:
-
-res_option() =
- [ {alt_nameservers, [ nameserver() ]}
- | {edns, 0 | false} % Use EDNS
- | {inet6, bool()} % Return IPv6 addresses
- | {nameservers, [ nameserver() ]} % List of nameservers
- | {recurse, bool()} % Request server recursion
- | {retry, integer()} % UDP retries
- | {timeout, integer()} % UDP query timeout
- | {udp_payload_size, integer()} % EDNS payload size
- | {usevc, bool()} ] % Use TCP (Virtual Circuit)
-
-nameserver() = {ip_address(),Port}
- Port = integer(1..65535)
-
-res_error() =
- formerr |
- qfmterror |
- servfail |
- nxdomain |
- notimp |
- refused |
- badvers |
- timeout
-</code>
-
- <p>DNS types:</p>
- <marker id="dns_types"/>
- <code type="none">dns_name() = string() with no adjacent dots
-
-rr_type() = a | aaaa | cname | gid | hinfo | ns | mb | md | mg | mf
- | minfo | mx | naptr | null | ptr | soa | spf | srv | txt
- | uid | uinfo | unspec | wks
-
-query_type() = axfr | mailb | maila | any | rr_type()
-
-dns_class() = in | chaos | hs | any
-
+ <datatype>
+ <name name="res_option"/>
+ </datatype>
+ <datatype>
+ <name name="nameserver"/>
+ </datatype>
+ <datatype>
+ <name name="res_error"/>
+ </datatype>
+
+ <p><marker id="dns_types"/>DNS types:</p>
+ <datatype>
+ <name name="dns_name"/>
+ <desc><p>A string with no adjacent dots.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="rr_type"/>
+ </datatype>
+ <datatype>
+ <name name="dns_class"/>
+ </datatype>
+ <datatype>
+ <name name="dns_msg"/>
+ <desc>
+ <p>This is the start of a hiearchy of opaque data structures
+ that can be examined with access functions in inet_dns that
+ return lists of {Field,Value} tuples. The arity 2 functions
+ just return the value for a given field.
+<pre>
dns_msg() = DnsMsg
- This is the start of a hiearchy of opaque data structures
- that can be examined with access functions in inet_dns
- that return lists of {Field,Value} tuples. The arity 2
- functions just return the value for a given field.
-
inet_dns:msg(DnsMsg) ->
[ {header, dns_header()}
| {qdlist, dns_query()}
@@ -143,19 +117,21 @@ dns_msg() = DnsMsg
inet_dns:msg(DnsMsg, header) -> dns_header() % for example
inet_dns:msg(DnsMsg, Field) -> Value
-dhs_header() = DnsHeader
+dns_header() = DnsHeader
inet_dns:header(DnsHeader) ->
[ {id, integer()}
- | {qr, bool()}
+ | {qr, boolean()}
| {opcode, 'query' | iquery | status | integer()}
- | {aa, bool()}
- | {tc, bool()}
- | {rd, bool()}
- | {ra, bool()}
- | {pr, bool()}
+ | {aa, boolean()}
+ | {tc, boolean()}
+ | {rd, boolean()}
+ | {ra, boolean()}
+ | {pr, boolean()}
| {rcode, integer(0..16)} ]
inet_dns:header(DnsHeader, Field) -> Value
+query_type() = axfr | mailb | maila | any | rr_type()
+
dns_query() = DnsQuery
inet_dns:dns_query(DnsQuery) ->
[ {domain, dns_name()}
@@ -179,32 +155,6 @@ dns_rr() = DnsRr
| {data, dns_data()} ]
inet_dns:rr(DnsRr, Field) -> Value
-dns_data() = % for dns_type()
- [ dns_name() % ns, md, mf, cname, mb, mg, mr, ptr
- | ip_address(v4) % a
- | ip_address(v6) % aaaa
- | {MName,RName,Serial,Refresh,Retry,Expiry,Minimum} % soa
- | {ip_address(v4),Proto,BitMap} % wks
- | {CpuString,OsString} % hinfo
- | {RM,EM} % minfo
- | {Prio,dns_name()} % mx
- | {Prio,Weight,Port,dns_name()} % srv
- | {Order,Preference,Flags,Services,Regexp,dns_name()} % naptr
- | [ string() ] % txt, spf
- | binary() ] % null, integer()
-MName, RName = dns_name()
-Serial, Refresh, Retry, Expiry, Minimum = integer(),
-Proto = integer()
-BitMap = binary()
-CpuString, OsString = string()
-RM = EM = dns_name()
-Prio, Weight, Port = integer()
-Order, Preference = integer()
-Flags, Services = string(),
-Regexp = string(utf8)
-
-
-
There is an info function for the types above:
inet_dns:record_type(dns_msg()) -> msg;
@@ -214,26 +164,25 @@ inet_dns:record_type(dns_rr()) -> rr;
inet_dns:record_type(_) -> undefined.
So; inet_dns:(inet_dns:record_type(X))(X) will convert
-any of these data structures into a {Field,Value} list.</code>
- </section>
-
+any of these data structures into a {Field,Value} list.</pre></p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="dns_data"/>
+ <desc><p><c><anno>Regexp</anno></c> is a string with characters encoded in the
+ UTF-8 coding standard.</p>
+ </desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>getbyname(Name, Type) -> {ok,hostent()} | {error,Reason}</name>
- <name>getbyname(Name, Type, Timeout) ->
- {ok,hostent()} | {error,Reason}
- </name>
+ <name name="getbyname" arity="2"/>
+ <name name="getbyname" arity="3"/>
<fsummary>Resolve a DNS record of the given type for the given host
</fsummary>
- <type>
- <v>Name = dns_name()</v>
- <v>Type = rr_type()</v>
- <v>Timeout = integer() >= 0 | infinity</v>
- <v>Reason = posix() | res_error()</v>
- </type>
<desc>
<p>Resolve a DNS record of the given type for the given host,
of class <c>in</c>. On success returns a <c>hostent()</c> record with
@@ -252,17 +201,10 @@ any of these data structures into a {Field,Value} list.</code>
</func>
<func>
- <name>gethostbyaddr(Address) -> {ok,hostent()} | {error,Reason}</name>
- <name>gethostbyaddr(Address, Timeout) ->
- {ok,hostent()} | {error,Reason}
- </name>
+ <name name="gethostbyaddr" arity="1"/>
+ <name name="gethostbyaddr" arity="2"/>
<fsummary>Return a hostent record for the host with the given address
</fsummary>
- <type>
- <v>Address = ip_address()</v>
- <v>Timeout = integer() >= 0 | infinity</v>
- <v>Reason = posix() | res_error()</v>
- </type>
<desc>
<p>Backend functions used by
<seealso marker="kernel:inet#gethostbyaddr/1">
@@ -273,20 +215,11 @@ any of these data structures into a {Field,Value} list.</code>
</func>
<func>
- <name>gethostbyname(Name) -> {ok,hostent()} | Reason}</name>
- <name>gethostbyname(Name, Family) ->
- {ok,hostent()} | {error,Reason}}
- </name>
- <name>gethostbyname(Name, Family, Timeout) ->
- {ok,hostent()} | {error,Reason}
- </name>
+ <name name="gethostbyname" arity="1"/>
+ <name name="gethostbyname" arity="2"/>
+ <name name="gethostbyname" arity="3"/>
<fsummary>Return a hostent record for the host with the given name
</fsummary>
- <type>
- <v>Name = dns_name()</v>
- <v>Timeout = integer() >= 0 | infinity</v>
- <v>Reason = posix() | res_error()</v>
- </type>
<desc>
<p>Backend functions used by
<seealso marker="kernel:inet#gethostbyname/1">
@@ -305,26 +238,16 @@ any of these data structures into a {Field,Value} list.</code>
</func>
<func>
- <name>lookup(Name, Class, Type) -> [ dns_data() ]
- </name>
- <name>lookup(Name, Class, Type, Opts) -> [ dns_data() ]
- </name>
- <name>lookup(Name, Class, Type, Opts, Timeout) -> [ dns_data() ]
- </name>
+ <name name="lookup" arity="3"/>
+ <name name="lookup" arity="4"/>
+ <name name="lookup" arity="5"/>
<fsummary>Resolve the DNS data for the record of the given type and class
for the given name
</fsummary>
- <type>
- <v>Name = dns_name() | ip_address()</v>
- <v>Type = rr_type()</v>
- <v>Opts = res_option() | verbose</v>
- <v>Timeout = integer() >= 0 | infinity</v>
- <v>Reason = posix() | res_error()</v>
- </type>
<desc>
<p>Resolve the DNS data for the record of the given type and class
for the given name. On success filters out the answer records
- with the correct <c>Class</c> and <c>Type</c> and returns
+ with the correct <c><anno>Class</anno></c> and <c><anno>Type</anno></c> and returns
a list of their data fields. So a lookup for type <c>any</c>
will give an empty answer since the answer records have
specific types that are not <c>any</c>. An empty answer
@@ -332,44 +255,33 @@ any of these data structures into a {Field,Value} list.</code>
</p><p>
Calls <seealso marker="#resolve/3">resolve/2..4</seealso>
with the same arguments and filters the result, so
- <c>Opts</c> is explained there.
+ <c><anno>Opts</anno></c> is explained there.
</p>
</desc>
</func>
<func>
- <name>resolve(Name, Class, Type) -> {ok,dns_msg()} | Error
- </name>
- <name>resolve(Name, Class, Type, Opts) -> {ok,dns_msg()} | Error
- </name>
- <name>resolve(Name, Class, Type, Opts, Timeout) -> {ok,dns_msg()} | Error
- </name>
+ <name name="resolve" arity="3"/>
+ <name name="resolve" arity="4"/>
+ <name name="resolve" arity="5"/>
<fsummary>Resolve a DNS record of the given type and class
for the given name
</fsummary>
- <type>
- <v>Name = dns_name() | ip_address()</v>
- <v>Type = rr_type()</v>
- <v>Opts = res_option() | verbose | atom()</v>
- <v>Timeout = integer() >= 0 | infinity</v>
- <v>Error = {error,Reason} | {error,{Reason,dns_msg()}}</v>
- <v>Reason = posix() | res_error()</v>
- </type>
<desc>
<p>Resolve a DNS record of the given type and class for the given name.
The returned <c>dns_msg()</c> can be examined using
access functions in <c>inet_db</c> as described
in <seealso marker="#dns_types">DNS types</seealso>.
</p><p>
- If <c>Name</c> is an <c>ip_address()</c>, the domain name
+ If <c><anno>Name</anno></c> is an <c>ip_address()</c>, the domain name
to query for is generated as the standard reverse
".IN-ADDR.ARPA." name for an IPv4 address, or the
".IP6.ARPA." name for an IPv6 address.
In this case you most probably want to use
- <c>Class = in</c> and <c>Type = ptr</c> but it
+ <c><anno>Class</anno> = in</c> and <c><anno>Type</anno> = ptr</c> but it
is not done automatically.
</p><p>
- <c>Opts</c> override the corresponding resolver options.
+ <c><anno>Opts</anno></c> override the corresponding resolver options.
If the option <c>nameservers</c> is given, it is
also assumed that it is the complete list of nameserves,
so the resolver option <c>alt_nameserves</c> is ignored.
@@ -382,14 +294,14 @@ any of these data structures into a {Field,Value} list.</code>
of queries, replies retransmissions, etc, similar
to from utilities like <c>dig</c>, <c>nslookup</c> et.al.
</p><p>
- If <c>Opt</c> is an arbitrary atom it is interpreted
- as <c>{Opt,true}</c> unless the atom string starts with
- <c>"no"</c> making the interpretation <c>{Opt,false}</c>.
+ If <c><anno>Opt</anno></c> is an arbitrary atom it is interpreted
+ as <c>{<anno>Opt</anno>,true}</c> unless the atom string starts with
+ <c>"no"</c> making the interpretation <c>{<anno>Opt</anno>,false}</c>.
For example: <c>usevc</c> is an alias for <c>{usevc,true}</c>,
and <c>nousevc</c> an alias for <c>{usevc,false}</c>.
</p><p>
The <c>inet6</c> option currently has no effect on this function.
- You probably want to use <c>Type = a | aaaa</c> instead.
+ You probably want to use <c><anno>Type</anno> = a | aaaa</c> instead.
</p>
</desc>
</func>
@@ -430,24 +342,18 @@ any of these data structures into a {Field,Value} list.</code>
<funcs>
<func>
- <name>nslookup(Name, Class, Type) -> {ok,dns_msg()} | {error,Reason}
- </name>
- <name>nslookup(Name, Class, Type, Timeout) ->
- {ok,dns_msg()} | {error,Reason}
- </name>
- <name>nslookup(Name, Class, Type, Nameservers) ->
- {ok,dns_msg()} | {error,Reason}
- </name>
+ <name name="nslookup" arity="3"/>
+ <name name="nslookup" arity="4" clause_i="1"/>
+ <name name="nslookup" arity="4" clause_i="2"/>
<fsummary>Resolve a DNS record of the given type and class
for the given name
</fsummary>
- <type>
- <v>Name = dns_name() | ip_address()</v>
- <v>Type = rr_type()</v>
- <v>Nameservers = [ nameserver() ]</v>
- <v>Timeout = integer() >= 0 | infinity</v>
- <v>Reason = posix() | res_error()</v>
- </type>
+ <type variable="Name"/>
+ <type variable="Class"/>
+ <type variable="Type"/>
+ <type variable="Timeout" name_i="2"/>
+ <type variable="Nameservers"/>
+ <type variable="Reason"/>
<desc>
<p>Resolve a DNS record of the given type and class for the given name.
</p>
@@ -455,22 +361,11 @@ any of these data structures into a {Field,Value} list.</code>
</func>
<func>
- <name>nnslookup(Name, Class, Type, Nameservers) ->
- {ok,dns_msg()} | {error,posix()}
- </name>
- <name>nnslookup(Name, Class, Type, Nameservers, Timeout) ->
- {ok,dns_msg()} | {error,posix()}
- </name>
+ <name name="nnslookup" arity="4"/>
+ <name name="nnslookup" arity="5"/>
<fsummary>Resolve a DNS record of the given type and class
for the given name
</fsummary>
- <type>
- <v>Name = dns_name() | ip_address()</v>
- <v>Type = rr_type()</v>
- <v>Nameservers = [ nameserver() ]</v>
- <v>Timeout = integer() >= 0 | infinity</v>
- <v>Reason = posix() | res_error()</v>
- </type>
<desc>
<p>Resolve a DNS record of the given type and class for the given name.
</p>
diff --git a/lib/kernel/doc/src/net_adm.xml b/lib/kernel/doc/src/net_adm.xml
index 7ec4f7f0e7..f2aac9282c 100644
--- a/lib/kernel/doc/src/net_adm.xml
+++ b/lib/kernel/doc/src/net_adm.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,94 +34,70 @@
</description>
<funcs>
<func>
- <name>dns_hostname(Host) -> {ok, Name} | {error, Host}</name>
+ <name name="dns_hostname" arity="1"/>
<fsummary>Official name of a host</fsummary>
- <type>
- <v>Host = atom() | string()</v>
- <v>Name = string()</v>
- </type>
<desc>
- <p>Returns the official name of <c>Host</c>, or
- <c>{error, Host}</c> if no such name is found. See also
+ <p>Returns the official name of <c><anno>Host</anno></c>, or
+ <c>{error, <anno>Host</anno>}</c> if no such name is found. See also
<c>inet(3)</c>.</p>
</desc>
</func>
<func>
- <name>host_file() -> Hosts | {error, Reason}</name>
+ <name name="host_file" arity="0"/>
<fsummary>Read the <c>.hosts.erlang</c>file</fsummary>
- <type>
- <v>Hosts = [Host]</v>
- <v>&nbsp;Host = atom()</v>
- <v>Reason = term()</v>
- </type>
<desc>
<p>Reads the <c>.hosts.erlang</c> file, see the section
<em>Files</em> below. Returns the hosts in this file as a
- list, or returns <c>{error, Reason}</c> if the file could not
- be read. See <c>file(3)</c> for possible values of
- <c>Reason</c>.</p>
+ list, or returns <c>{error, <anno>Reason</anno>}</c> if the file could not
+ be read or the Erlang terms on the file could not be interpreted.</p>
</desc>
</func>
<func>
- <name>localhost() -> Name</name>
+ <name name="localhost" arity="0"/>
<fsummary>Name of the local host</fsummary>
- <type>
- <v>Name = string()</v>
- </type>
<desc>
<p>Returns the name of the local host. If Erlang was started
- with the <c>-name</c> command line flag, <c>Name</c> is
+ with the <c>-name</c> command line flag, <c><anno>Name</anno></c> is
the fully qualified name.</p>
</desc>
</func>
<func>
- <name>names() -> {ok, [{Name, Port}]} | {error, Reason}</name>
- <name>names(Host) -> {ok, [{Name, Port}]} | {error, Reason}</name>
+ <name name="names" arity="0"/>
+ <name name="names" arity="1"/>
<fsummary>Names of Erlang nodes at a host</fsummary>
- <type>
- <v>Name = string()</v>
- <v>Port = int()</v>
- <v>Reason = address | term()</v>
- </type>
<desc>
<p>Similar to <c>epmd -names</c>, see <c>epmd(1)</c>.
- <c>Host</c> defaults to the local host. Returns the names and
+ <c><anno>Host</anno></c> defaults to the local host. Returns the names and
associated port numbers of the Erlang nodes that <c>epmd</c>
at the specified host has registered.</p>
<p>Returns <c>{error, address}</c> if <c>epmd</c> is not
- running. See <c>inet(3)</c> for other possible values of
- <c>Reason</c>.</p>
+ running.</p>
<pre>
(arne@dunn)1> <input>net_adm:names().</input>
{ok,[{"arne",40262}]}</pre>
</desc>
</func>
<func>
- <name>ping(Node) -> pong | pang</name>
+ <name name="ping" arity="1"/>
<fsummary>Set up a connection to a node</fsummary>
- <type>
- <v>Node = node()</v>
- </type>
<desc>
- <p>Tries to set up a connection to <c>Node</c>. Returns
+ <p>Tries to set up a connection to <c><anno>Node</anno></c>. Returns
<c>pang</c> if it fails, or <c>pong</c> if it is successful.</p>
</desc>
</func>
<func>
- <name>world() -> [node()]</name>
- <name>world(Arg) -> [node()]</name>
+ <name name="world" arity="0"/>
+ <name name="world" arity="1"/>
+ <type name="verbosity"/>
<fsummary>Lookup and connect to all nodes at all hosts in <c>.hosts.erlang</c></fsummary>
- <type>
- <v>Arg = silent | verbose</v>
- </type>
<desc>
<p>This function calls <c>names(Host)</c> for all hosts which
are specified in the Erlang host file <c>.hosts.erlang</c>,
collects the replies and then evaluates <c>ping(Node)</c> on
all those nodes. Returns the list of all nodes that were,
successfully pinged.</p>
- <p><c>Arg</c> defaults to <c>silent</c>.
- If <c>Arg == verbose</c>, the function writes information about which
+ <p><c><anno>Arg</anno></c> defaults to <c>silent</c>.
+ If <c><anno>Arg</anno> == verbose</c>, the function writes information about which
nodes it is pinging to stdout.</p>
<p>This function can be useful when a node is started, and
the names of the other nodes in the network are not initially
@@ -131,14 +107,10 @@
</desc>
</func>
<func>
- <name>world_list(Hosts) -> [node()]</name>
- <name>world_list(Hosts, Arg) -> [node()]</name>
+ <name name="world_list" arity="1"/>
+ <name name="world_list" arity="2"/>
+ <type name="verbosity"/>
<fsummary>Lookup and connect to all nodes at specified hosts</fsummary>
- <type>
- <v>Hosts = [Host]</v>
- <v>&nbsp;Host = atom()</v>
- <v>Arg = silent | verbose</v>
- </type>
<desc>
<p>As <c>world/0,1</c>, but the hosts are given as argument
instead of being read from <c>.hosts.erlang</c>.</p>
diff --git a/lib/kernel/doc/src/net_kernel.xml b/lib/kernel/doc/src/net_kernel.xml
index a18226e779..3b7a710664 100644
--- a/lib/kernel/doc/src/net_kernel.xml
+++ b/lib/kernel/doc/src/net_kernel.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -37,13 +37,10 @@
monitoring of the network.</p>
<p>An Erlang node is started using the command line flag
<c>-name</c> or <c>-sname</c>:</p>
- <pre>
-$ <input>erl -sname foobar</input></pre>
+<pre>$ <input>erl -sname foobar</input></pre>
<p>It is also possible to call <c>net_kernel:start([foobar])</c>
directly from the normal Erlang shell prompt:</p>
- <p></p>
- <pre>
-1> <input>net_kernel:start([foobar, shortnames]).</input>
+<pre>1> <input>net_kernel:start([foobar, shortnames]).</input>
{ok,&lt;0.64.0>}
(foobar@gringotts)2></pre>
<p>If the node is started with the command line flag <c>-sname</c>,
@@ -64,50 +61,38 @@ $ <input>erl -sname foobar</input></pre>
</description>
<funcs>
<func>
- <name>allow(Nodes) -> ok | error</name>
+ <name name="allow" arity="1"/>
<fsummary>Limit access to a specified set of nodes</fsummary>
- <type>
- <v>Nodes = [node()]</v>
- </type>
<desc>
<p>Limits access to the specified set of nodes. Any access
- attempts made from (or to) nodes not in <c>Nodes</c> will be
+ attempts made from (or to) nodes not in <c><anno>Nodes</anno></c> will be
rejected.</p>
- <p>Returns <c>error</c> if any element in <c>Nodes</c> is not
+ <p>Returns <c>error</c> if any element in <c><anno>Nodes</anno></c> is not
an atom.</p>
</desc>
</func>
<func>
- <name>connect_node(Node) -> true | false | ignored</name>
+ <name name="connect_node" arity="1"/>
<fsummary>Establish a connection to a node</fsummary>
- <type>
- <v>Node = node()</v>
- </type>
<desc>
- <p>Establishes a connection to <c>Node</c>. Returns <c>true</c>
+ <p>Establishes a connection to <c><anno>Node</anno></c>. Returns <c>true</c>
if successful, <c>false</c> if not, and <c>ignored</c> if
the local node is not alive.</p>
</desc>
</func>
<func>
- <name>monitor_nodes(Flag) -> ok | Error</name>
- <name>monitor_nodes(Flag, Options) -> ok | Error</name>
+ <name name="monitor_nodes" arity="1"/>
+ <name name="monitor_nodes" arity="2"/>
<fsummary>Subscribe to node status change messages</fsummary>
- <type>
- <v>Flag = true | false</v>
- <v>Options = [Option]</v>
- <v>&nbsp;Option -- see below</v>
- <v>Error = error | {error, term()}</v>
- </type>
<desc>
<p>The calling process subscribes or unsubscribes to node
status change messages. A <c>nodeup</c> message is delivered
to all subscribing process when a new node is connected, and
a <c>nodedown</c> message is delivered when a node is
disconnected.</p>
- <p>If <c>Flag</c> is <c>true</c>, a new subscription is started.
- If <c>Flag</c> is <c>false</c>, all previous subscriptions --
- started with the same <c>Options</c> -- are stopped. Two
+ <p>If <c><anno>Flag</anno></c> is <c>true</c>, a new subscription is started.
+ If <c><anno>Flag</anno></c> is <c>false</c>, all previous subscriptions --
+ started with the same <c><anno>Options</anno></c> -- are stopped. Two
option lists are considered the same if they contain the same
set of options.</p>
<p>As of <c>kernel</c> version 2.11.4, and <c>erts</c> version
@@ -139,23 +124,23 @@ $ <input>erl -sname foobar</input></pre>
<p>Note, that this is <em>not</em> guaranteed for <c>kernel</c>
versions before 2.13.</p>
<p>The format of the node status change messages depends on
- <c>Options</c>. If <c>Options</c> is [], which is the default,
+ <c><anno>Options</anno></c>. If <c><anno>Options</anno></c> is [], which is the default,
the format is:</p>
<code type="none">
{nodeup, Node} | {nodedown, Node}
Node = node()</code>
- <p>If <c>Options /= []</c>, the format is:</p>
+ <p>If <c><anno>Options</anno> /= []</c>, the format is:</p>
<code type="none">
{nodeup, Node, InfoList} | {nodedown, Node, InfoList}
Node = node()
InfoList = [{Tag, Val}]</code>
<p><c>InfoList</c> is a list of tuples. Its contents depends on
- <c>Options</c>, see below.</p>
+ <c><anno>Options</anno></c>, see below.</p>
<p>Also, when <c>OptionList == []</c> only visible nodes, that
is, nodes that appear in the result of
<seealso marker="erts:erlang#nodes/0">nodes/0</seealso>, are
monitored.</p>
- <p><c>Option</c> can be any of the following:</p>
+ <p><c><anno>Option</anno></c> can be any of the following:</p>
<taglist>
<tag><c>{node_type, NodeType}</c></tag>
<item>
@@ -209,61 +194,50 @@ $ <input>erl -sname foobar</input></pre>
</desc>
</func>
<func>
- <name>get_net_ticktime() -> Res</name>
+ <name name="get_net_ticktime" arity="0"/>
<fsummary>Get <c>net_ticktime</c></fsummary>
- <type>
- <v>Res = NetTicktime | {ongoing_change_to, NetTicktime}</v>
- <v>&nbsp;NetTicktime = int()</v>
- </type>
<desc>
<p>Gets <c>net_ticktime</c> (see
<seealso marker="kernel_app">kernel(6)</seealso>).</p>
- <p>Currently defined return values (<c>Res</c>):</p>
+ <p>Currently defined return values (<c><anno>Res</anno></c>):</p>
<taglist>
- <tag><c>NetTicktime</c></tag>
+ <tag><c><anno>NetTicktime</anno></c></tag>
<item>
- <p><c>net_ticktime</c> is <c>NetTicktime</c> seconds.</p>
+ <p><c>net_ticktime</c> is <c><anno>NetTicktime</anno></c> seconds.</p>
</item>
- <tag><c>{ongoing_change_to, NetTicktime}</c></tag>
+ <tag><c>{ongoing_change_to, <anno>NetTicktime</anno>}</c></tag>
<item>
<p><c>net_kernel</c> is currently changing
- <c>net_ticktime</c> to <c>NetTicktime</c> seconds.</p>
+ <c>net_ticktime</c> to <c><anno>NetTicktime</anno></c> seconds.</p>
</item>
</taglist>
</desc>
</func>
<func>
- <name>set_net_ticktime(NetTicktime) -> Res</name>
- <name>set_net_ticktime(NetTicktime, TransitionPeriod) -> Res</name>
+ <name name="set_net_ticktime" arity="1"/>
+ <name name="set_net_ticktime" arity="2"/>
<fsummary>Set <c>net_ticktime</c></fsummary>
- <type>
- <v>NetTicktime = int() > 0</v>
- <v>TransitionPeriod = int() >= 0</v>
- <v>Res = unchanged | change_initiated | {ongoing_change_to, NewNetTicktime}</v>
- <v>&nbsp;NewNetTicktime = int() > 0</v>
- </type>
<desc>
<p>Sets <c>net_ticktime</c> (see
<seealso marker="kernel_app">kernel(6)</seealso>) to
- <c>NetTicktime</c> seconds. <c>TransitionPeriod</c> defaults
+ <c><anno>NetTicktime</anno></c> seconds. <c><anno>TransitionPeriod</anno></c> defaults
to 60.</p>
<p>Some definitions:</p>
- <p></p>
<taglist>
<tag>The minimum transition traffic interval (<c>MTTI</c>)</tag>
<item>
- <p><c>minimum(NetTicktime, PreviousNetTicktime)*1000 div 4</c> milliseconds.</p>
+ <p><c>minimum(<anno>NetTicktime</anno>, PreviousNetTicktime)*1000 div 4</c> milliseconds.</p>
</item>
<tag>The transition period</tag>
<item>
<p>The time of the least number of consecutive <c>MTTI</c>s
- to cover <c>TransitionPeriod</c> seconds following
+ to cover <c><anno>TransitionPeriod</anno></c> seconds following
the call to <c>set_net_ticktime/2</c> (i.e.
- ((<c>TransitionPeriod*1000 - 1) div MTTI + 1)*MTTI</c>
+ ((<c><anno>TransitionPeriod</anno>*1000 - 1) div MTTI + 1)*MTTI</c>
milliseconds).</p>
</item>
</taglist>
- <p>If <c><![CDATA[NetTicktime < PreviousNetTicktime]]></c>, the actual
+ <p>If <c><![CDATA[<anno>NetTicktime</anno> < PreviousNetTicktime]]></c>, the actual
<c>net_ticktime</c> change will be done at the end of
the transition period; otherwise, at the beginning. During
the transition period, <c>net_kernel</c> will ensure that
@@ -271,7 +245,7 @@ $ <input>erl -sname foobar</input></pre>
every <c>MTTI</c> millisecond.</p>
<note>
<p>The <c>net_ticktime</c> changes have to be initiated on all
- nodes in the network (with the same <c>NetTicktime</c>)
+ nodes in the network (with the same <c><anno>NetTicktime</anno></c>)
before the end of any transition period on any node;
otherwise, connections may erroneously be disconnected.</p>
</note>
@@ -280,18 +254,18 @@ $ <input>erl -sname foobar</input></pre>
<tag><c>unchanged</c></tag>
<item>
<p><c>net_ticktime</c> already had the value of
- <c>NetTicktime</c> and was left unchanged.</p>
+ <c><anno>NetTicktime</anno></c> and was left unchanged.</p>
</item>
<tag><c>change_initiated</c></tag>
<item>
<p><c>net_kernel</c> has initiated the change of
- <c>net_ticktime</c> to <c>NetTicktime</c> seconds.</p>
+ <c>net_ticktime</c> to <c><anno>NetTicktime</anno></c> seconds.</p>
</item>
- <tag><c>{ongoing_change_to, NewNetTicktime}</c></tag>
+ <tag><c>{ongoing_change_to, <anno>NewNetTicktime</anno>}</c></tag>
<item>
<p>The request was <em>ignored</em>; because,
<c>net_kernel</c> was busy changing <c>net_ticktime</c> to
- <c>NewTicktime</c> seconds.</p>
+ <c><anno>NewNetTicktime</anno></c> seconds.</p>
</item>
</taglist>
</desc>
@@ -315,7 +289,7 @@ $ <input>erl -sname foobar</input></pre>
</desc>
</func>
<func>
- <name>stop() -> ok | {error, not_allowed | not_found}</name>
+ <name name="stop" arity="0"/>
<fsummary>Turn a node into a non-distributed Erlang runtime system</fsummary>
<desc>
<p>Turns a distributed node into a non-distributed node. For
diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml
index 065b24c53d..ec57b03bd9 100644
--- a/lib/kernel/doc/src/notes.xml
+++ b/lib/kernel/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,6 +30,127 @@
</header>
<p>This document describes the changes made to the Kernel application.</p>
+<section><title>Kernel 2.14.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix type of Packet arg of gen_tcp:send/2 and
+ gen_udp:send/4</p>
+ <p>
+ The type is marked as a binary() or a string() but in
+ practice it can be an iodata(). The test suite was
+ updated to confirm the gen_tcp/2 and gen_udp:send/4
+ functions accept iodata() (iolists) packets. (Thanks to
+ Filipe David Manana)</p>
+ <p>
+ Own Id: OTP-9514</p>
+ </item>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> The types and specifications of the inet modules have
+ been improved. </p>
+ <p>
+ Own Id: OTP-9260</p>
+ </item>
+ <item>
+ <p> Types and specifications have been added. </p>
+ <p>
+ Own Id: OTP-9356</p>
+ </item>
+ <item>
+ <p> Contracts in STDLIB and Kernel have been improved and
+ type errors have been corrected. </p>
+ <p>
+ Own Id: OTP-9485</p>
+ </item>
+ <item>
+ <p> Update documentation and specifications of some of
+ the zlib functions. </p>
+ <p>
+ Own Id: OTP-9506</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 2.14.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The send_timeout option in gen_tcp did not work properly
+ in active mode or with {active,once} options. This is now
+ corrected.</p>
+ <p>
+ Own Id: OTP-9145</p>
+ </item>
+ <item>
+ <p>
+ Fixed various typos across the documentation (Thanks to
+ Tuncer Ayaz)</p>
+ <p>
+ Own Id: OTP-9154</p>
+ </item>
+ <item>
+ <p>
+ Fix typo in doc of rpc:pmap/3 (Thanks to Ricardo
+ Catalinas Jim�nez)</p>
+ <p>
+ Own Id: OTP-9168</p>
+ </item>
+ <item>
+ <p>
+ A bug in inet_res, the specialized DNS resolver, has been
+ corrected. A late answer with unfortunate timing could
+ cause a runtime exception. Some code cleanup and
+ improvements also tagged along. Thanks to Evegeniy
+ Khramtsov for a pinpointing bug report and bug fix
+ testing.</p>
+ <p>
+ Own Id: OTP-9221 Aux Id: OTP-8712 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Types and specifications have been added. </p>
+ <p>
+ Own Id: OTP-9268</p>
+ </item>
+ <item>
+ <p> Erlang types and specifications are used for
+ documentation. </p>
+ <p>
+ Own Id: OTP-9272</p>
+ </item>
+ <item>
+ <p> Two opaque types that could cause warnings when
+ running Dialyzer have been modified. </p>
+ <p>
+ Own Id: OTP-9337</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Kernel 2.14.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -2470,7 +2591,7 @@
<c>badarg</c> if a process is already registered. As it
turns out there is no check in <c>global</c> if a process is
registered under more than one name. If some process is
- accidentaly or by design given several names, it is
+ accidentally or by design given several names, it is
possible that the name registry becomes inconsistent due
to the way the resolve function is called when name
clashes are discovered (see <c>register_name/3</c> in
diff --git a/lib/kernel/doc/src/os.xml b/lib/kernel/doc/src/os.xml
index 2c9cc33eb7..e94119845a 100644
--- a/lib/kernel/doc/src/os.xml
+++ b/lib/kernel/doc/src/os.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -38,13 +38,10 @@
</description>
<funcs>
<func>
- <name>cmd(Command) -> string()</name>
+ <name name="cmd" arity="1"/>
<fsummary>Execute a command in a shell of the target OS</fsummary>
- <type>
- <v>Command = string() | atom()</v>
- </type>
<desc>
- <p>Executes <c>Command</c> in a command shell of the target OS,
+ <p>Executes <c><anno>Command</anno></c> in a command shell of the target OS,
captures the standard output of the command and returns this
result as a string. This function is a replacement of
the previous <c>unix:cmd/1</c>; on a Unix platform they are
@@ -60,23 +57,18 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
</desc>
</func>
<func>
- <name>find_executable(Name) -> Filename | false</name>
- <name>find_executable(Name, Path) -> Filename | false</name>
+ <name name="find_executable" arity="1"/>
+ <name name="find_executable" arity="2"/>
<fsummary>Absolute filename of a program</fsummary>
- <type>
- <v>Name = string()</v>
- <v>Path = string()</v>
- <v>Filename = string()</v>
- </type>
<desc>
<p>These two functions look up an executable program given its
name and a search path, in the same way as the underlying
operating system. <c>find_executable/1</c> uses the current
execution path (that is, the environment variable PATH on
Unix and Windows).</p>
- <p><c>Path</c>, if given, should conform to the syntax of
+ <p><c><anno>Path</anno></c>, if given, should conform to the syntax of
execution paths on the operating system. The absolute
- filename of the executable program <c>Name</c> is returned,
+ filename of the executable program <c><anno>Name</anno></c> is returned,
or <c>false</c> if the program was not found.</p>
</desc>
</func>
@@ -134,10 +126,11 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
</desc>
</func>
<func>
- <name>timestamp() -> {MegaSecs, Secs, MicroSecs}</name>
+ <name>timestamp() -> Timestamp</name>
<fsummary>Returna a timestamp from the OS in the erlang:now/0 format</fsummary>
<type>
- <v>MegaSecs = Secs = MicroSecs = int()</v>
+ <v>Timestamp = {MegaSecs, Secs, MicroSecs} = <seealso marker="erts:erlang#type-timestamp">erlang:timestamp()</seealso></v>
+ <v>MegaSecs = Secs = MicroSecs = integer() >= 0</v>
</type>
<desc>
<p>Returns a tuple in the same format as <seealso marker="erts:erlang#now/0">erlang:now/0</seealso>. The difference is that this function returns what the operating system thinks (a.k.a. the wall clock time) without any attempts at time correction. The result of two different calls to this function is <em>not</em> guaranteed to be different.</p>
@@ -165,19 +158,15 @@ format_utc_timestamp() ->
</desc>
</func>
<func>
- <name>type() -> {Osfamily, Osname} | Osfamily</name>
+ <name name="type" arity="0"/>
<fsummary>Return the OS family and, in some cases, OS name of the current operating system</fsummary>
- <type>
- <v>Osfamily = win32 | unix | vxworks</v>
- <v>Osname = atom()</v>
- </type>
<desc>
- <p>Returns the <c>Osfamily</c> and, in some cases, <c>Osname</c>
+ <p>Returns the <c><anno>Osfamily</anno></c> and, in some cases, <c><anno>Osname</anno></c>
of the current operating system.</p>
- <p>On Unix, <c>Osname</c> will have same value as
+ <p>On Unix, <c><anno>Osname</anno></c> will have same value as
<c>uname -s</c> returns, but in lower case. For example, on
Solaris 1 and 2, it will be <c>sunos</c>.</p>
- <p>In Windows, <c>Osname</c> will be either <c>nt</c> (on
+ <p>In Windows, <c><anno>Osname</anno></c> will be either <c>nt</c> (on
Windows NT), or <c>windows</c> (on Windows 95).</p>
<p>On VxWorks the OS family alone is returned, that is
<c>vxworks</c>.</p>
@@ -185,17 +174,13 @@ format_utc_timestamp() ->
<p>Think twice before using this function. Use the
<c>filename</c> module if you want to inspect or build
file names in a portable way.
- Avoid matching on the <c>Osname</c> atom.</p>
+ Avoid matching on the <c><anno>Osname</anno></c> atom.</p>
</note>
</desc>
</func>
<func>
- <name>version() -> {Major, Minor, Release} | VersionString</name>
+ <name name="version" arity="0"/>
<fsummary>Return the Operating System version</fsummary>
- <type>
- <v>Major = Minor = Release = integer()</v>
- <v>VersionString = string()</v>
- </type>
<desc>
<p>Returns the operating system version.
On most systems, this function returns a tuple, but a string
diff --git a/lib/kernel/doc/src/pg2.xml b/lib/kernel/doc/src/pg2.xml
index 7463fd10f5..d26ff0fc6b 100644
--- a/lib/kernel/doc/src/pg2.xml
+++ b/lib/kernel/doc/src/pg2.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -60,13 +60,16 @@
to avoid name clashes.</p>
</warning>
</description>
+ <datatypes>
+ <datatype>
+ <name name="name"/>
+ <desc><p>The name of a process group.</p></desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>create(Name) -> void()</name>
+ <name name="create" arity="1"/>
<fsummary>Create a new, empty process group</fsummary>
- <type>
- <v>Name = term()</v>
- </type>
<desc>
<p>Creates a new, empty process group. The group is globally
visible on all nodes. If the group exists, nothing happens.
@@ -74,24 +77,16 @@
</desc>
</func>
<func>
- <name>delete(Name) -> void()</name>
+ <name name="delete" arity="1"/>
<fsummary>Delete a process group</fsummary>
- <type>
- <v>Name = term()</v>
- </type>
<desc>
<p>Deletes a process group.
</p>
</desc>
</func>
<func>
- <name>get_closest_pid(Name) -> Pid | {error, Reason}</name>
+ <name name="get_closest_pid" arity="1"/>
<fsummary>Common dispatch function</fsummary>
- <type>
- <v>Name = term()</v>
- <v>Pid = pid()</v>
- <v>Reason = {no_process, Name} | {no_such_group, Name}</v>
- </type>
<desc>
<p>This is a useful dispatch function which can be used from
client functions. It returns a process on the local node, if
@@ -100,13 +95,8 @@
</desc>
</func>
<func>
- <name>get_members(Name) -> [Pid] | {error, Reason}</name>
+ <name name="get_members" arity="1"/>
<fsummary>Return all processes in a group</fsummary>
- <type>
- <v>Name = term()</v>
- <v>Pid = pid()</v>
- <v>Reason = {no_such_group, Name}</v>
- </type>
<desc>
<p>Returns all processes in the group <c>Name</c>. This
function should be used from within a client function that
@@ -115,13 +105,8 @@
</desc>
</func>
<func>
- <name>get_local_members(Name) -> [Pid] | {error, Reason}</name>
+ <name name="get_local_members" arity="1"/>
<fsummary>Return all local processes in a group</fsummary>
- <type>
- <v>Name = term()</v>
- <v>Pid = pid()</v>
- <v>Reason = {no_such_group, Name}</v>
- </type>
<desc>
<p>Returns all processes running on the local node in the
group <c>Name</c>. This function should to be used from
@@ -131,13 +116,8 @@
</desc>
</func>
<func>
- <name>join(Name, Pid) -> ok | {error, Reason}</name>
+ <name name="join" arity="2"/>
<fsummary>Join a process to a group</fsummary>
- <type>
- <v>Name = term()</v>
- <v>Pid = pid()</v>
- <v>Reason = {no_such_group, Name}</v>
- </type>
<desc>
<p>Joins the process <c>Pid</c> to the group <c>Name</c>.
A process can join a group several times; it must then
@@ -146,13 +126,8 @@
</desc>
</func>
<func>
- <name>leave(Name, Pid) -> ok | {error, Reason}</name>
+ <name name="leave" arity="2"/>
<fsummary>Make a process leave a group</fsummary>
- <type>
- <v>Name = term()</v>
- <v>Pid = pid()</v>
- <v>Reason = {no_such_group, Name}</v>
- </type>
<desc>
<p>Makes the process <c>Pid</c> leave the group <c>Name</c>.
If the process is not a member of the group, <c>ok</c> is
@@ -161,24 +136,17 @@
</desc>
</func>
<func>
- <name>which_groups() -> [Name]</name>
+ <name name="which_groups" arity="0"/>
<fsummary>Return a list of all known groups</fsummary>
- <type>
- <v>Name = term()</v>
- </type>
<desc>
<p>Returns a list of all known groups.
</p>
</desc>
</func>
<func>
- <name>start()</name>
- <name>start_link() -> {ok, Pid} | {error, Reason}</name>
+ <name name="start" arity="0"/>
+ <name name="start_link" arity="0"/>
<fsummary>Start the pg2 server</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Reason = term()</v>
- </type>
<desc>
<p>Starts the pg2 server. Normally, the server does not need
to be started explicitly, as it is started dynamically if it
diff --git a/lib/kernel/doc/src/rpc.xml b/lib/kernel/doc/src/rpc.xml
index 86c6ea9178..b01ff16c85 100644
--- a/lib/kernel/doc/src/rpc.xml
+++ b/lib/kernel/doc/src/rpc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -37,40 +37,34 @@
for collecting information on a remote node, or for running a
function with some specific side effects on the remote node.</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="key"/>
+ <desc>
+ <p>As returned by <seealso marker="#async_call/4">
+ <c>async_call/4</c>.</seealso></p>
+ </desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>call(Node, Module, Function, Args) -> Res | {badrpc, Reason}</name>
+ <name name="call" arity="4"/>
<fsummary>Evaluate a function call on a node</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- <v>Res = term()</v>
- <v>Reason = term()</v>
- </type>
<desc>
- <p>Evaluates <c>apply(Module, Function, Args)</c> on the node
- <c>Node</c> and returns the corresponding value <c>Res</c>, or
- <c>{badrpc, Reason}</c> if the call fails.</p>
+ <p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c> on the node
+ <c><anno>Node</anno></c> and returns the corresponding value <c><anno>Res</anno></c>, or
+ <c>{badrpc, <anno>Reason</anno>}</c> if the call fails.</p>
</desc>
</func>
<func>
- <name>call(Node, Module, Function, Args, Timeout) -> Res | {badrpc, Reason}</name>
+ <name name="call" arity="5"/>
<fsummary>Evaluate a function call on a node</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- <v>Res = term()</v>
- <v>Reason = timeout | term()</v>
- <v>Timeout = int() | infinity</v>
- </type>
<desc>
- <p>Evaluates <c>apply(Module, Function, Args)</c> on the node
- <c>Node</c> and returns the corresponding value <c>Res</c>, or
- <c>{badrpc, Reason}</c> if the call fails. <c>Timeout</c> is
+ <p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c> on the node
+ <c><anno>Node</anno></c> and returns the corresponding value <c><anno>Res</anno></c>, or
+ <c>{badrpc, <anno>Reason</anno>}</c> if the call fails. <c><anno>Timeout</anno></c> is
a timeout value in milliseconds. If the call times out,
- <c>Reason</c> is <c>timeout</c>.</p>
+ <c><anno>Reason</anno></c> is <c>timeout</c>.</p>
<p>If the reply arrives after the call times out, no message
will contaminate the caller's message queue, since this
function spawns off a middleman process to act as (a void)
@@ -80,17 +74,10 @@
</desc>
</func>
<func>
- <name>block_call(Node, Module, Function, Args) -> Res | {badrpc, Reason}</name>
+ <name name="block_call" arity="4"/>
<fsummary>Evaluate a function call on a node in the RPC server's context</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- <v>Res = term()</v>
- <v>Reason = term()</v>
- </type>
<desc>
- <p>Like <c>call/4</c>, but the RPC server at <c>Node</c> does
+ <p>Like <c>call/4</c>, but the RPC server at <c><anno>Node</anno></c> does
not create a separate process to handle the call. Thus,
this function can be used if the intention of the call is to
block the RPC server from any other incoming requests until
@@ -101,50 +88,31 @@
</desc>
</func>
<func>
- <name>block_call(Node, Module, Function, Args, Timeout) -> Res | {badrpc, Reason}</name>
+ <name name="block_call" arity="5"/>
<fsummary>Evaluate a function call on a node in the RPC server's context</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- <v>Timeout = int() | infinity</v>
- <v>Res = term()</v>
- <v>Reason = term()</v>
- </type>
<desc>
<p>Like <c>block_call/4</c>, but with a timeout value in
the same manner as <c>call/5</c>.</p>
</desc>
</func>
<func>
- <name>async_call(Node, Module, Function, Args) -> Key</name>
+ <name name="async_call" arity="4"/>
<fsummary>Evaluate a function call on a node, asynchronous version</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- <v>Key -- see below</v>
- </type>
<desc>
<p>Implements <em>call streams with promises</em>, a type of
RPC which does not suspend the caller until the result is
finished. Instead, a key is returned which can be used at a
later stage to collect the value. The key can be viewed as a
promise to deliver the answer.</p>
- <p>In this case, the key <c>Key</c> is returned, which can be
+ <p>In this case, the key <c><anno>Key</anno></c> is returned, which can be
used in a subsequent call to <c>yield/1</c> or
<c>nb_yield/1,2</c> to retrieve the value of evaluating
- <c>apply(Module, Function, Args)</c> on the node <c>Node</c>.</p>
+ <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c> on the node <c><anno>Node</anno></c>.</p>
</desc>
</func>
<func>
- <name>yield(Key) -> Res | {badrpc, Reason}</name>
+ <name name="yield" arity="1"/>
<fsummary>Deliver the result of evaluating a function call on a node (blocking)</fsummary>
- <type>
- <v>Key -- see async_call/4</v>
- <v>Res = term()</v>
- <v>Reason = term()</v>
- </type>
<desc>
<p>Returns the promised answer from a previous
<c>async_call/4</c>. If the answer is available, it is
@@ -153,87 +121,46 @@
</desc>
</func>
<func>
- <name>nb_yield(Key) -> {value, Val} | timeout</name>
+ <name name="nb_yield" arity="1"/>
<fsummary>Deliver the result of evaluating a function call on a node (non-blocking)</fsummary>
- <type>
- <v>Key -- see async_call/4</v>
- <v>Val = Res | {badrpc, Reason}</v>
- <v>&nbsp;Res = term()</v>
- <v>&nbsp;Reason = term()</v>
- </type>
<desc>
- <p>Equivalent to <c>nb_yield(Key, 0)</c>.</p>
+ <p>Equivalent to <c>nb_yield(<anno>Key</anno>, 0)</c>.</p>
</desc>
</func>
<func>
- <name>nb_yield(Key, Timeout) -> {value, Val} | timeout</name>
+ <name name="nb_yield" arity="2"/>
<fsummary>Deliver the result of evaluating a function call on a node (non-blocking)</fsummary>
- <type>
- <v>Key -- see async_call/4</v>
- <v>Timeout = int() | infinity</v>
- <v>Val = Res | {badrpc, Reason}</v>
- <v>&nbsp;Res = term()</v>
- <v>&nbsp;Reason = term()</v>
- </type>
<desc>
<p>This is a non-blocking version of <c>yield/1</c>. It returns
- the tuple <c>{value, Val}</c> when the computation has
- finished, or <c>timeout</c> when <c>Timeout</c> milliseconds
+ the tuple <c>{value, <anno>Val</anno>}</c> when the computation has
+ finished, or <c>timeout</c> when <c><anno>Timeout</anno></c> milliseconds
has elapsed.</p>
</desc>
</func>
<func>
- <name>multicall(Module, Function, Args) -> {ResL, BadNodes}</name>
+ <name name="multicall" arity="3"/>
<fsummary>Evaluate a function call on a number of nodes</fsummary>
- <type>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- <v>ResL = [term()]</v>
- <v>BadNodes = [node()]</v>
- </type>
<desc>
- <p>Equivalent to <c>multicall([node()|nodes()], Module, Function, Args, infinity)</c>.</p>
+ <p>Equivalent to <c>multicall([node()|nodes()], <anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>, infinity)</c>.</p>
</desc>
</func>
<func>
- <name>multicall(Nodes, Module, Function, Args) -> {ResL, BadNodes}</name>
+ <name name="multicall" arity="4" clause_i="1"/>
<fsummary>Evaluate a function call on a number of nodes</fsummary>
- <type>
- <v>Nodes = [node()]</v>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- <v>ResL = [term()]</v>
- <v>BadNodes = [node()]</v>
- </type>
<desc>
- <p>Equivalent to <c>multicall(Nodes, Module, Function, Args, infinity)</c>.</p>
+ <p>Equivalent to <c>multicall(<anno>Nodes</anno>, <anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>, infinity)</c>.</p>
</desc>
</func>
<func>
- <name>multicall(Module, Function, Args, Timeout) -> {ResL, BadNodes}</name>
+ <name name="multicall" arity="4" clause_i="2"/>
<fsummary>Evaluate a function call on a number of nodes</fsummary>
- <type>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- <v>Timeout = int() | infinity</v>
- <v>ResL = [term()]</v>
- <v>BadNodes = [node()]</v>
- </type>
<desc>
- <p>Equivalent to <c>multicall([node()|nodes()], Module, Function, Args, Timeout)</c>.</p>
+ <p>Equivalent to <c>multicall([node()|nodes()], <anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>, <anno>Timeout</anno>)</c>.</p>
</desc>
</func>
<func>
- <name>multicall(Nodes, Module, Function, Args, Timeout) -> {ResL, BadNodes}</name>
+ <name name="multicall" arity="5"/>
<fsummary>Evaluate a function call on a number of nodes</fsummary>
- <type>
- <v>Nodes = [node()]</v>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- <v>Timeout = int() | infinity</v>
- <v>ResL = [term()]</v>
- <v>BadNodes = [node()]</v>
- </type>
<desc>
<p>In contrast to an RPC, a multicall is an RPC which is sent
concurrently from one client to multiple servers. This is
@@ -243,12 +170,12 @@
making a series of RPCs on all the nodes, but the multicall
is faster as all the requests are sent at the same time
and are collected one by one as they come back.</p>
- <p>The function evaluates <c>apply(Module, Function, Args)</c>
+ <p>The function evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c>
on the specified nodes and collects the answers. It returns
- <c>{ResL, Badnodes}</c>, where <c>Badnodes</c> is a list
+ <c>{<anno>ResL</anno>, <anno>BadNodes</anno>}</c>, where <c><anno>BadNodes</anno></c> is a list
of the nodes that terminated or timed out during computation,
- and <c>ResL</c> is a list of the return values.
- <c>Timeout</c> is a time (integer) in milliseconds, or
+ and <c><anno>ResL</anno></c> is a list of the return values.
+ <c><anno>Timeout</anno></c> is a time (integer) in milliseconds, or
<c>infinity</c>.</p>
<p>The following example is useful when new object code is to
be loaded on all nodes in the network, and also indicates
@@ -264,93 +191,60 @@
</desc>
</func>
<func>
- <name>cast(Node, Module, Function, Args) -> void()</name>
+ <name name="cast" arity="4"/>
<fsummary>Run a function on a node ignoring the result</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- </type>
<desc>
- <p>Evaluates <c>apply(Module, Function, Args)</c> on the node
- <c>Node</c>. No response is delivered and the calling
+ <p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c> on the node
+ <c><anno>Node</anno></c>. No response is delivered and the calling
process is not suspended until the evaluation is complete, as
is the case with <c>call/4,5</c>.</p>
</desc>
</func>
<func>
- <name>eval_everywhere(Module, Funtion, Args) -> void()</name>
+ <name name="eval_everywhere" arity="3"/>
<fsummary>Run a function on all nodes, ignoring the result</fsummary>
- <type>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- </type>
<desc>
- <p>Equivalent to <c>eval_everywhere([node()|nodes()], Module, Function, Args)</c>.</p>
+ <p>Equivalent to <c>eval_everywhere([node()|nodes()], <anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c>.</p>
</desc>
</func>
<func>
- <name>eval_everywhere(Nodes, Module, Function, Args) -> void()</name>
+ <name name="eval_everywhere" arity="4"/>
<fsummary>Run a function on specific nodes, ignoring the result</fsummary>
- <type>
- <v>Nodes = [node()]</v>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- </type>
<desc>
- <p>Evaluates <c>apply(Module, Function, Args)</c> on
+ <p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c> on
the specified nodes. No answers are collected.</p>
</desc>
</func>
<func>
- <name>abcast(Name, Msg) -> void()</name>
+ <name name="abcast" arity="2"/>
<fsummary>Broadcast a message asynchronously to a registered process on all nodes</fsummary>
- <type>
- <v>Name = atom()</v>
- <v>Msg = term()</v>
- </type>
<desc>
- <p>Equivalent to <c>abcast([node()|nodes()], Name, Msg)</c>.</p>
+ <p>Equivalent to <c>abcast([node()|nodes()], <anno>Name</anno>, <anno>Msg</anno>)</c>.</p>
</desc>
</func>
<func>
- <name>abcast(Nodes, Name, Msg) -> void()</name>
+ <name name="abcast" arity="3"/>
<fsummary>Broadcast a message asynchronously to a registered process on specific nodes</fsummary>
- <type>
- <v>Nodes = [node()]</v>
- <v>Name = atom()</v>
- <v>Msg = term()</v>
- </type>
<desc>
- <p>Broadcasts the message <c>Msg</c> asynchronously to
- the registered process <c>Name</c> on the specified nodes.</p>
+ <p>Broadcasts the message <c><anno>Msg</anno></c> asynchronously to
+ the registered process <c><anno>Name</anno></c> on the specified nodes.</p>
</desc>
</func>
<func>
- <name>sbcast(Name, Msg) -> {GoodNodes, BadNodes}</name>
+ <name name="sbcast" arity="2"/>
<fsummary>Broadcast a message synchronously to a registered process on all nodes</fsummary>
- <type>
- <v>Name = atom()</v>
- <v>Msg = term()</v>
- <v>GoodNodes = BadNodes = [node()]</v>
- </type>
<desc>
- <p>Equivalent to <c>sbcast([node()|nodes()], Name, Msg)</c>.</p>
+ <p>Equivalent to <c>sbcast([node()|nodes()], <anno>Name</anno>, <anno>Msg</anno>)</c>.</p>
</desc>
</func>
<func>
- <name>sbcast(Nodes, Name, Msg) -> {GoodNodes, BadNodes}</name>
+ <name name="sbcast" arity="3"/>
<fsummary>Broadcast a message synchronously to a registered process on specific nodes</fsummary>
- <type>
- <v>Name = atom()</v>
- <v>Msg = term()</v>
- <v>Nodes = GoodNodes = BadNodes = [node()]</v>
- </type>
<desc>
- <p>Broadcasts the message <c>Msg</c> synchronously to
- the registered process <c>Name</c> on the specified nodes.</p>
- <p>Returns <c>{GoodNodes, BadNodes}</c>, where <c>GoodNodes</c>
- is the list of nodes which have <c>Name</c> as a registered
+ <p>Broadcasts the message <c><anno>Msg</anno></c> synchronously to
+ the registered process <c><anno>Name</anno></c> on the specified nodes.</p>
+ <p>Returns <c>{<anno>GoodNodes</anno>, <anno>BadNodes</anno>}</c>, where <c><anno>GoodNodes</anno></c>
+ is the list of nodes which have <c><anno>Name</anno></c> as a registered
process.</p>
<p>The function is synchronous in the sense that it is known
that all servers have received the message when the call
@@ -362,67 +256,46 @@
</desc>
</func>
<func>
- <name>server_call(Node, Name, ReplyWrapper, Msg) -> Reply | {error, Reason}</name>
+ <name name="server_call" arity="4"/>
<fsummary>Interact with a server on a node</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Name = atom()</v>
- <v>ReplyWrapper = Msg = Reply = term()</v>
- <v>Reason = term()</v>
- </type>
<desc>
<p>This function can be used when interacting with a server
- called <c>Name</c> at node <c>Node</c>. It is assumed that
+ called <c><anno>Name</anno></c> at node <c><anno>Node</anno></c>. It is assumed that
the server receives messages in the format
- <c>{From, Msg}</c> and replies using <c>From ! {ReplyWrapper, Node, Reply}</c>. This function makes such
+ <c>{From, <anno>Msg</anno>}</c> and replies using <c>From ! {<anno>ReplyWrapper</anno>, <anno>Node</anno>, <anno>Reply</anno>}</c>. This function makes such
a server call and ensures that the entire call is packed into
an atomic transaction which either succeeds or fails. It
never hangs, unless the server itself hangs.</p>
- <p>The function returns the answer <c>Reply</c> as produced by
- the server <c>Name</c>, or <c>{error, Reason}</c>.</p>
+ <p>The function returns the answer <c><anno>Reply</anno></c> as produced by
+ the server <c><anno>Name</anno></c>, or <c>{error, <anno>Reason</anno>}</c>.</p>
</desc>
</func>
<func>
- <name>multi_server_call(Name, Msg) -> {Replies, BadNodes}</name>
+ <name name="multi_server_call" arity="2"/>
<fsummary>Interact with the servers on a number of nodes</fsummary>
- <type>
- <v>Name = atom()</v>
- <v>Msg = term()</v>
- <v>Replies = [Reply]</v>
- <v>&nbsp;Reply = term()</v>
- <v>BadNodes = [node()]</v>
- </type>
<desc>
- <p>Equivalent to <c>multi_server_call([node()|nodes()], Name, Msg)</c>.</p>
+ <p>Equivalent to <c>multi_server_call([node()|nodes()], <anno>Name</anno>, <anno>Msg</anno>)</c>.</p>
</desc>
</func>
<func>
- <name>multi_server_call(Nodes, Name, Msg) -> {Replies, BadNodes}</name>
+ <name name="multi_server_call" arity="3"/>
<fsummary>Interact with the servers on a number of nodes</fsummary>
- <type>
- <v>Nodes = [node()]</v>
- <v>Name = atom()</v>
- <v>Msg = term()</v>
- <v>Replies = [Reply]</v>
- <v>&nbsp;Reply = term()</v>
- <v>BadNodes = [node()]</v>
- </type>
<desc>
<p>This function can be used when interacting with servers
- called <c>Name</c> on the specified nodes. It is assumed that
- the servers receive messages in the format <c>{From, Msg}</c>
- and reply using <c>From ! {Name, Node, Reply}</c>, where
+ called <c><anno>Name</anno></c> on the specified nodes. It is assumed that
+ the servers receive messages in the format <c>{From, <anno>Msg</anno>}</c>
+ and reply using <c>From ! {<anno>Name</anno>, Node, <anno>Reply</anno>}</c>, where
<c>Node</c> is the name of the node where the server is
- located. The function returns <c>{Replies, Badnodes}</c>,
- where <c>Replies</c> is a list of all <c>Reply</c> values and
- <c>BadNodes</c> is a list of the nodes which did not exist, or
+ located. The function returns <c>{<anno>Replies</anno>, <anno>BadNodes</anno>}</c>,
+ where <c><anno>Replies</anno></c> is a list of all <c><anno>Reply</anno></c> values and
+ <c><anno>BadNodes</anno></c> is a list of the nodes which did not exist, or
where the server did not exist, or where the server terminated
before sending any reply.</p>
</desc>
</func>
<func>
- <name>safe_multi_server_call(Name, Msg) -> {Replies, BadNodes}</name>
- <name>safe_multi_server_call(Nodes, Name, Msg) -> {Replies, BadNodes}</name>
+ <name name="safe_multi_server_call" arity="2"/>
+ <name name="safe_multi_server_call" arity="3"/>
<fsummary>Interact with the servers on a number of nodes (deprecated)</fsummary>
<desc>
<warning>
@@ -432,66 +305,47 @@
<p>In Erlang/OTP R6B and earlier releases,
<c>multi_server_call/2,3</c> could not handle the case
where the remote node exists, but there is no server called
- <c>Name</c>. Instead this function had to be used. In
+ <c><anno>Name</anno></c>. Instead this function had to be used. In
Erlang/OTP R7B and later releases, however, the functions are
equivalent, except for this function being slightly slower.</p>
</desc>
</func>
<func>
- <name>parallel_eval(FuncCalls) -> ResL</name>
+ <name name="parallel_eval" arity="1"/>
<fsummary>Evaluate several function calls on all nodes in parallel</fsummary>
- <type>
- <v>FuncCalls = [{Module, Function, Args}]</v>
- <v>&nbsp;Module = Function = atom()</v>
- <v>&nbsp;Args = [term()]</v>
- <v>ResL = [term()]</v>
- </type>
<desc>
- <p>For every tuple in <c>FuncCalls</c>, evaluates
- <c>apply(Module, Function, Args)</c> on some node in
+ <p>For every tuple in <c><anno>FuncCalls</anno></c>, evaluates
+ <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c> on some node in
the network. Returns the list of return values, in the same
- order as in <c>FuncCalls</c>.</p>
+ order as in <c><anno>FuncCalls</anno></c>.</p>
</desc>
</func>
<func>
- <name>pmap({Module, Function}, ExtraArgs, List2) -> List1</name>
+ <name name="pmap" arity="3"/>
<fsummary>Parallell evaluation of mapping a function over a list </fsummary>
- <type>
- <v>Module = Function = atom()</v>
- <v>ExtraArgs = [term()]</v>
- <v>List1 = [Elem]</v>
- <v>&nbsp;Elem = term()</v>
- <v>List2 = [term()]</v>
- </type>
<desc>
- <p>Evaluates <c>apply(Module, Function, [Elem|ExtraArgs])</c>,
- for every element <c>Elem</c> in <c>List1</c>, in parallel.
+ <p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>, [<anno>Elem</anno>|<anno>ExtraArgs</anno>])</c>,
+ for every element <c><anno>Elem</anno></c> in <c><anno>List1</anno></c>, in parallel.
Returns the list of return values, in the same order as in
- <c>List1</c>.</p>
+ <c><anno>List1</anno></c>.</p>
</desc>
</func>
<func>
- <name>pinfo(Pid) -> [{Item, Info}] | undefined</name>
+ <name name="pinfo" arity="1"/>
<fsummary>Information about a process</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Item, Info -- see erlang:process_info/1</v>
- </type>
<desc>
<p>Location transparent version of the BIF
- <c>process_info/1</c>.</p>
+ <seealso marker="erts:erlang#process_info/1">
+ <c>process_info/1</c></seealso>.</p>
</desc>
</func>
<func>
- <name>pinfo(Pid, Item) -> {Item, Info} | undefined | []</name>
+ <name name="pinfo" arity="2"/>
<fsummary>Information about a process</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Item, Info -- see erlang:process_info/1</v>
- </type>
<desc>
<p>Location transparent version of the BIF
- <c>process_info/2</c>.</p>
+ <seealso marker="erts:erlang#process_info/2">
+ <c>process_info/2</c></seealso>.</p>
</desc>
</func>
</funcs>
diff --git a/lib/kernel/doc/src/seq_trace.xml b/lib/kernel/doc/src/seq_trace.xml
index 6c043dd767..1ab955bd8a 100644
--- a/lib/kernel/doc/src/seq_trace.xml
+++ b/lib/kernel/doc/src/seq_trace.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1998</year><year>2009</year>
+ <year>1998</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -47,17 +47,22 @@
from users.</p>
</note>
</description>
+ <datatypes>
+ <datatype>
+ <name name="token"/>
+ <desc>
+ <p>An opaque term (a tuple) representing a trace token.</p>
+ </desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>set_token(Token) -> PreviousToken</name>
+ <name name="set_token" arity="1"/>
<fsummary>Set the trace token</fsummary>
- <type>
- <v>Token = PreviousToken = term() | []</v>
- </type>
<desc>
- <p>Sets the trace token for the calling process to <c>Token</c>.
- If <c>Token == []</c> then tracing is disabled, otherwise
- <c>Token</c> should be an Erlang term returned from
+ <p>Sets the trace token for the calling process to <c><anno>Token</anno></c>.
+ If <c><anno>Token</anno> == []</c> then tracing is disabled, otherwise
+ <c><anno>Token</anno></c> should be an Erlang term returned from
<c>get_token/0</c> or <c>set_token/1</c>. <c>set_token/1</c>
can be used to temporarily exclude message passing from
the trace by setting the trace token to empty like this:</p>
@@ -72,18 +77,16 @@ seq_trace:set_token(OldToken), % activate the trace token again
</desc>
</func>
<func>
- <name>set_token(Component, Val) -> {Component, OldVal}</name>
+ <name name="set_token" arity="2"/>
<fsummary>Set a component of the trace token</fsummary>
- <type>
- <v>Component = label | serial | Flag</v>
- <v>&nbsp;Flag = send | 'receive' | print | timestamp </v>
- <v>Val = OldVal -- see below</v>
- </type>
+ <type name="component"/>
+ <type name="flag"/>
+ <type name="value"/>
<desc>
- <p>Sets the individual <c>Component</c> of the trace token to
- <c>Val</c>. Returns the previous value of the component.</p>
+ <p>Sets the individual <c><anno>Component</anno></c> of the trace token to
+ <c><anno>Val</anno></c>. Returns the previous value of the component.</p>
<taglist>
- <tag><c>set_token(label, Int)</c></tag>
+ <tag><c>set_token(label, <anno>Integer</anno>)</c></tag>
<item>
<p>The <c>label</c> component is an integer which
identifies all events belonging to the same sequential
@@ -93,31 +96,31 @@ seq_trace:set_token(OldToken), % activate the trace token again
</item>
<tag><c>set_token(serial, SerialValue)</c></tag>
<item>
- <p><c>SerialValue = {Previous, Current}</c>.
+ <p><c>SerialValue = {<anno>Previous</anno>, <anno>Current</anno>}</c>.
The <c>serial</c> component contains counters which
enables the traced messages to be sorted, should never be
set explicitly by the user as these counters are updated
automatically. Default is <c>{0, 0}</c>.</p>
</item>
- <tag><c>set_token(send, Bool)</c></tag>
+ <tag><c>set_token(send, <anno>Bool</anno>)</c></tag>
<item>
<p>A trace token flag (<c>true | false</c>) which
enables/disables tracing on message sending. Default is
<c>false</c>.</p>
</item>
- <tag><c>set_token('receive', Bool)</c></tag>
+ <tag><c>set_token('receive', <anno>Bool</anno>)</c></tag>
<item>
<p>A trace token flag (<c>true | false</c>) which
enables/disables tracing on message reception. Default is
<c>false</c>.</p>
</item>
- <tag><c>set_token(print, Bool)</c></tag>
+ <tag><c>set_token(print, <anno>Bool</anno>)</c></tag>
<item>
<p>A trace token flag (<c>true | false</c>) which
enables/disables tracing on explicit calls to
<c>seq_trace:print/1</c>. Default is <c>false</c>.</p>
</item>
- <tag><c>set_token(timestamp, Bool)</c></tag>
+ <tag><c>set_token(timestamp, <anno>Bool</anno>)</c></tag>
<item>
<p>A trace token flag (<c>true | false</c>) which
enables/disables a timestamp to be generated for each
@@ -127,11 +130,8 @@ seq_trace:set_token(OldToken), % activate the trace token again
</desc>
</func>
<func>
- <name>get_token() -> TraceToken</name>
+ <name name="get_token" arity="0"/>
<fsummary>Return the value of the trace token</fsummary>
- <type>
- <v>TraceToken = term() | []</v>
- </type>
<desc>
<p>Returns the value of the trace token for the calling process.
If <c>[]</c> is returned, it means that tracing is not active.
@@ -141,13 +141,11 @@ seq_trace:set_token(OldToken), % activate the trace token again
</desc>
</func>
<func>
- <name>get_token(Component) -> {Component, Val}</name>
+ <name name="get_token" arity="1"/>
<fsummary>Return the value of a trace token component</fsummary>
- <type>
- <v>Component = label | serial | Flag</v>
- <v>&nbsp;Flag = send | 'receive' | print | timestamp </v>
- <v>Val -- see set_token/2</v>
- </type>
+ <type name="component"/>
+ <type name="flag"/>
+ <type name="value"/>
<desc>
<p>Returns the value of the trace token component
<c>Component</c>. See
@@ -156,33 +154,26 @@ seq_trace:set_token(OldToken), % activate the trace token again
</desc>
</func>
<func>
- <name>print(TraceInfo) -> void()</name>
+ <name name="print" arity="1"/>
<fsummary>Put the Erlang term <c>TraceInfo</c>into the sequential trace output</fsummary>
- <type>
- <v>TraceInfo = term()</v>
- </type>
<desc>
- <p>Puts the Erlang term <c>TraceInfo</c> into the sequential
+ <p>Puts the Erlang term <c><anno>TraceInfo</anno></c> into the sequential
trace output if the calling process currently is executing
within a sequential trace and the <c>print</c> flag of
the trace token is set.</p>
</desc>
</func>
<func>
- <name>print(Label, TraceInfo) -> void()</name>
+ <name name="print" arity="2"/>
<fsummary>Put the Erlang term <c>TraceInfo</c>into the sequential trace output</fsummary>
- <type>
- <v>Label = int()</v>
- <v>TraceInfo = term()</v>
- </type>
<desc>
<p>Same as <c>print/1</c> with the additional condition that
- <c>TraceInfo</c> is output only if <c>Label</c> is equal to
+ <c><anno>TraceInfo</anno></c> is output only if <c>Label</c> is equal to
the label component of the trace token.</p>
</desc>
</func>
<func>
- <name>reset_trace() -> void()</name>
+ <name name="reset_trace" arity="0"/>
<fsummary>Stop all sequential tracing on the local node</fsummary>
<desc>
<p>Sets the trace token to empty for all processes on the
@@ -194,26 +185,22 @@ seq_trace:set_token(OldToken), % activate the trace token again
</desc>
</func>
<func>
- <name>set_system_tracer(Tracer) -> OldTracer</name>
+ <name name="set_system_tracer" arity="1"/>
<fsummary>Set the system tracer</fsummary>
- <type>
- <v>Tracer = OldTracer = pid() | port() | false</v>
- </type>
+ <type name="tracer"/>
<desc>
<p>Sets the system tracer. The system tracer can be either a
- process or port denoted by <c>Tracer</c>. Returns the previous
+ process or port denoted by <c><anno>Tracer</anno></c>. Returns the previous
value (which can be <c>false</c> if no system tracer is
active).</p>
- <p>Failure: <c>{badarg, Info}}</c> if <c>Pid</c> is not an
+ <p>Failure: <c>{badarg, Info}}</c> if <c><anno>Pid</anno></c> is not an
existing local pid.</p>
</desc>
</func>
<func>
- <name>get_system_tracer() -> Tracer</name>
+ <name name="get_system_tracer" arity="0"/>
<fsummary>Return the pid() or port() of the current system tracer.</fsummary>
- <type>
- <v>Tracer = pid() | port() | false</v>
- </type>
+ <type name="tracer"/>
<desc>
<p>Returns the pid or port identifier of the current system
tracer or <c>false</c> if no system tracer is activated.</p>
diff --git a/lib/kernel/doc/src/specs.xml b/lib/kernel/doc/src/specs.xml
new file mode 100644
index 0000000000..b41addaa0c
--- /dev/null
+++ b/lib/kernel/doc/src/specs.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="latin1" ?>
+<specs xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="../specs/specs_application.xml"/>
+ <xi:include href="../specs/specs_auth.xml"/>
+ <xi:include href="../specs/specs_code.xml"/>
+ <xi:include href="../specs/specs_disk_log.xml"/>
+ <xi:include href="../specs/specs_erl_boot_server.xml"/>
+ <xi:include href="../specs/specs_erl_ddll.xml"/>
+ <xi:include href="../specs/specs_erl_prim_loader_stub.xml"/>
+ <xi:include href="../specs/specs_erlang_stub.xml"/>
+ <xi:include href="../specs/specs_error_handler.xml"/>
+ <xi:include href="../specs/specs_error_logger.xml"/>
+ <xi:include href="../specs/specs_file.xml"/>
+ <xi:include href="../specs/specs_gen_tcp.xml"/>
+ <xi:include href="../specs/specs_gen_udp.xml"/>
+ <xi:include href="../specs/specs_gen_sctp.xml"/>
+ <xi:include href="../specs/specs_global.xml"/>
+ <xi:include href="../specs/specs_global_group.xml"/>
+ <xi:include href="../specs/specs_heart.xml"/>
+ <xi:include href="../specs/specs_inet.xml"/>
+ <xi:include href="../specs/specs_inet_res.xml"/>
+ <xi:include href="../specs/specs_init_stub.xml"/>
+ <xi:include href="../specs/specs_net_adm.xml"/>
+ <xi:include href="../specs/specs_net_kernel.xml"/>
+ <xi:include href="../specs/specs_os.xml"/>
+ <xi:include href="../specs/specs_pg2.xml"/>
+ <xi:include href="../specs/specs_rpc.xml"/>
+ <xi:include href="../specs/specs_seq_trace.xml"/>
+ <xi:include href="../specs/specs_user.xml"/>
+ <xi:include href="../specs/specs_wrap_log_reader.xml"/>
+ <xi:include href="../specs/specs_zlib_stub.xml"/>
+ <xi:include href="../specs/specs_packages.xml"/>
+</specs>
diff --git a/lib/kernel/doc/src/wrap_log_reader.xml b/lib/kernel/doc/src/wrap_log_reader.xml
index 18664a029f..6cf480b532 100644
--- a/lib/kernel/doc/src/wrap_log_reader.xml
+++ b/lib/kernel/doc/src/wrap_log_reader.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1998</year><year>2009</year>
+ <year>1998</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -50,18 +50,20 @@
the called node, it is entirely up to the user to be sure that all items are read.
</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="continuation"/>
+ <desc><p>Continuation returned by
+ <c>open/1,2</c> or <c>chunk/1,2</c>.</p>
+ </desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>chunk(Continuation)</name>
- <name>chunk(Continuation, N) -> {Continuation2, Terms} | {Continuation2, Terms, Badbytes} | {Continuation2, eof} | {error, Reason}</name>
+ <name name="chunk" arity="1"/>
+ <name name="chunk" arity="2"/>
<fsummary>Read a chunk of objects written to a wrap log.</fsummary>
- <type>
- <v>Continuation = continuation()</v>
- <v>N = int() > 0 | infinity</v>
- <v>Continuation2 = continuation()</v>
- <v>Terms= [term()]</v>
- <v>Badbytes = integer()</v>
- </type>
+ <type name="chunk_ret"/>
<desc>
<p>This function makes it possible to efficiently read the
terms which have been appended to a log. It minimises disk
@@ -70,29 +72,29 @@
<p>The first time <c>chunk</c> is called an initial
continuation returned from the <c>open/1</c>, <c>open/2</c> must be provided.
</p>
- <p>When <c>chunk/3</c> is called, <c>N</c> controls the
+ <p>When <c>chunk/3</c> is called, <c><anno>N</anno></c> controls the
maximum number of terms that are read from the log in each
chunk. Default is <c>infinity</c>, which means that all the
terms contained in the 8K chunk are read. If less than
- <c>N</c> terms are returned, this does not necessarily mean
+ <c><anno>N</anno></c> terms are returned, this does not necessarily mean
that end of file is reached.
</p>
<p>The <c>chunk</c> function returns a tuple
- <c>{Continuation2, Terms}</c>, where <c>Terms</c> is a list
- of terms found in the log. <c>Continuation2</c> is yet
+ <c>{<anno>Continuation2</anno>, <anno>Terms</anno>}</c>, where <c><anno>Terms</anno></c> is a list
+ of terms found in the log. <c><anno>Continuation2</anno></c> is yet
another continuation which must be passed on into any
subsequent calls to <c>chunk</c>. With a series of calls to
<c>chunk</c> it is then possible to extract all terms from a
log.
</p>
<p>The <c>chunk</c> function returns a tuple
- <c>{Continuation2, Terms, Badbytes}</c> if the log is opened
- in read only mode and the read chunk is corrupt. <c>Badbytes</c>
+ <c>{<anno>Continuation2</anno>, <anno>Terms</anno>, <anno>Badbytes</anno>}</c> if the log is opened
+ in read only mode and the read chunk is corrupt. <c><anno>Badbytes</anno></c>
indicates the number of non-Erlang terms found in the chunk.
Note also that the log is not repaired.
</p>
- <p><c>chunk</c> returns <c>{Continuation2, eof}</c> when the end of the log is
- reached, and <c>{error, Reason}</c> if an error occurs.
+ <p><c>chunk</c> returns <c>{<anno>Continuation2</anno>, eof}</c> when the end of the log is
+ reached, and <c>{error, <anno>Reason</anno>}</c> if an error occurs.
</p>
<p>The returned continuation may or may not be valid in the next call to
<c>chunk</c>. This is because the log may wrap and delete
@@ -103,37 +105,29 @@
</desc>
</func>
<func>
- <name>close(Continuation) -> ok </name>
+ <name name="close" arity="1"/>
<fsummary>Close a log</fsummary>
- <type>
- <v>Continuation = continuation()</v>
- </type>
<desc>
<p>This function closes a log file properly.
</p>
</desc>
</func>
<func>
- <name>open(Filename) -> OpenRet</name>
- <name>open(Filename, N) -> OpenRet</name>
+ <name name="open" arity="1"/>
+ <name name="open" arity="2"/>
<fsummary>Open a log file</fsummary>
- <type>
- <v>File = string() | atom()</v>
- <v>N = integer()</v>
- <v>OpenRet = {ok, Continuation} | {error, Reason} </v>
- <v>Continuation = continuation()</v>
- </type>
+ <type name="open_ret"/>
<desc>
- <p><c>Filename</c> specifies the name of the file which is to be read. </p>
- <p><c>N</c> specifies the index of the file which is to be read.
- If <c>N</c> is omitted the whole wrap log file will be read; if it
+ <p><c><anno>Filename</anno></c> specifies the name of the file which is to be read. </p>
+ <p><c><anno>N</anno></c> specifies the index of the file which is to be read.
+ If <c><anno>N</anno></c> is omitted the whole wrap log file will be read; if it
is specified only the specified index file will be read.
</p>
- <p>The <c>open</c> function returns <c>{ok, Continuation}</c> if the
- log/index file was successfully opened. The <c>Continuation</c>
+ <p>The <c>open</c> function returns <c>{ok, <anno>Continuation</anno>}</c> if the
+ log/index file was successfully opened. The <c><anno>Continuation</anno></c>
is to be used when chunking or closing the file.
</p>
- <p>The function returns <c>{error, Reason}</c> for all errors.
+ <p>The function returns <c>{error, <anno>Reason</anno>}</c> for all errors.
</p>
</desc>
</func>
diff --git a/lib/kernel/examples/uds_dist/c_src/uds_drv.c b/lib/kernel/examples/uds_dist/c_src/uds_drv.c
index fb10a375f4..9327ab19dc 100644
--- a/lib/kernel/examples/uds_dist/c_src/uds_drv.c
+++ b/lib/kernel/examples/uds_dist/c_src/uds_drv.c
@@ -111,7 +111,7 @@ do { \
typedef enum {
portTypeUnknown, /* An uninitialized port */
portTypeListener, /* A listening port/socket */
- portTypeAcceptor, /* An intermidiate stage when accepting
+ portTypeAcceptor, /* An intermediate stage when accepting
on a listen port */
portTypeConnector, /* An intermediate stage when connecting */
portTypeCommand, /* A connected open port in command mode */
@@ -401,7 +401,7 @@ static void uds_finish(void)
/*
** Protocol to control:
** 'C': Set port in command mode.
-** 'I': Set port in intermidiate mode
+** 'I': Set port in intermediate mode
** 'D': Set port in data mode
** 'N': Get identification number for listen port
** 'S': Get statistics
@@ -1000,7 +1000,7 @@ static int ensure_dir(char *path)
/*
** Try to open a lock file and lock the first byte write-only (advisory)
-** return the file descriptor if succesful, otherwise -1 (<0).
+** return the file descriptor if successful, otherwise -1 (<0).
*/
static int try_lock(char *sockname, Byte *p_creation)
{
diff --git a/lib/kernel/src/dist.hrl b/lib/kernel/include/dist.hrl
index aea1ab81ba..aea1ab81ba 100644
--- a/lib/kernel/src/dist.hrl
+++ b/lib/kernel/include/dist.hrl
diff --git a/lib/kernel/src/dist_util.hrl b/lib/kernel/include/dist_util.hrl
index f2b0598532..f2b0598532 100644
--- a/lib/kernel/src/dist_util.hrl
+++ b/lib/kernel/include/dist_util.hrl
diff --git a/lib/kernel/include/inet.hrl b/lib/kernel/include/inet.hrl
index 929b2ee294..3e64d4bb79 100644
--- a/lib/kernel/include/inet.hrl
+++ b/lib/kernel/include/inet.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The 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,18 +19,11 @@
%% This record is returned by inet:gethostbyaddr/2 and inet:gethostbyname/2.
--type hostname() :: atom() | string().
--type ip4_address() :: {0..255,0..255,0..255,0..255}.
--type ip6_address() :: {0..65535,0..65535,0..65535,0..65535,
- 0..65535,0..65535,0..65535,0..65535}.
--type ip_address() :: ip4_address() | ip6_address().
--type ip_port() :: 0..65535.
-
-record(hostent,
{
- h_name :: hostname(), %% offical name of host
- h_aliases = [] :: [hostname()], %% alias list
+ h_name :: inet:hostname(), %% offical name of host
+ h_aliases = [] :: [inet:hostname()], %% alias list
h_addrtype :: 'inet' | 'inet6', %% host address type
h_length :: non_neg_integer(), %% length of address
- h_addr_list = [] :: [ip_address()] %% list of addresses from name server
+ h_addr_list = [] :: [inet:ip_address()]%% list of addresses from name server
}).
diff --git a/lib/kernel/src/net_address.hrl b/lib/kernel/include/net_address.hrl
index 5342076507..5342076507 100644
--- a/lib/kernel/src/net_address.hrl
+++ b/lib/kernel/include/net_address.hrl
diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile
index 9db6014a7d..02be6b5036 100644
--- a/lib/kernel/src/Makefile
+++ b/lib/kernel/src/Makefile
@@ -118,11 +118,14 @@ MODULES = \
user_sup \
wrap_log_reader
-HRL_FILES= ../include/file.hrl ../include/inet.hrl ../include/inet_sctp.hrl
+HRL_FILES= ../include/file.hrl ../include/inet.hrl ../include/inet_sctp.hrl \
+ ../include/dist.hrl ../include/dist_util.hrl \
+ ../include/net_address.hrl
+
INTERNAL_HRL_FILES= application_master.hrl disk_log.hrl \
- net_address.hrl inet_dns.hrl inet_res.hrl \
+ inet_dns.hrl inet_res.hrl \
inet_boot.hrl inet_config.hrl inet_int.hrl \
- dist.hrl dist_util.hrl inet_dns_record_adts.hrl
+ inet_dns_record_adts.hrl
ERL_FILES= $(MODULES:%=%.erl)
@@ -215,7 +218,7 @@ $(EBIN)/code_server.beam: ../include/file.hrl
$(EBIN)/disk_log.beam: disk_log.hrl
$(EBIN)/disk_log_1.beam: disk_log.hrl ../include/file.hrl
$(EBIN)/disk_log_server.beam: disk_log.hrl
-$(EBIN)/dist_util.beam: dist_util.hrl dist.hrl
+$(EBIN)/dist_util.beam: ../include/dist_util.hrl ../include/dist.hrl
$(EBIN)/erl_boot_server.beam: inet_boot.hrl
$(EBIN)/erl_epmd.beam: inet_int.hrl erl_epmd.hrl
$(EBIN)/file.beam: ../include/file.hrl
@@ -226,7 +229,7 @@ $(EBIN)/global.beam: ../../stdlib/include/ms_transform.hrl
$(EBIN)/hipe_unified_loader.beam: ../../hipe/main/hipe.hrl hipe_ext_format.hrl
$(EBIN)/inet.beam: ../include/inet.hrl inet_int.hrl ../include/inet_sctp.hrl
$(EBIN)/inet6_tcp.beam: inet_int.hrl
-$(EBIN)/inet6_tcp_dist.beam: net_address.hrl dist.hrl dist_util.hrl
+$(EBIN)/inet6_tcp_dist.beam: ../include/net_address.hrl ../include/dist.hrl ../include/dist_util.hrl
$(EBIN)/inet6_udp.beam: inet_int.hrl
$(EBIN)/inet6_sctp.beam: inet_int.hrl
$(EBIN)/inet_config.beam: inet_config.hrl ../include/inet.hrl
@@ -237,10 +240,10 @@ $(EBIN)/inet_hosts.beam: ../include/inet.hrl
$(EBIN)/inet_parse.beam: ../include/file.hrl
$(EBIN)/inet_res.beam: ../include/inet.hrl inet_res.hrl inet_dns.hrl inet_int.hrl
$(EBIN)/inet_tcp.beam: inet_int.hrl
-$(EBIN)/inet_udp_dist.beam: net_address.hrl dist.hrl dist_util.hrl
+$(EBIN)/inet_udp_dist.beam: ../include/net_address.hrl ../include/dist.hrl ../include/dist_util.hrl
$(EBIN)/inet_udp.beam: inet_int.hrl
$(EBIN)/inet_sctp.beam: inet_int.hrl ../include/inet_sctp.hrl
-$(EBIN)/net_kernel.beam: net_address.hrl
+$(EBIN)/net_kernel.beam: ../include/net_address.hrl
$(EBIN)/os.beam: ../include/file.hrl
$(EBIN)/ram_file.beam: ../include/file.hrl
$(EBIN)/wrap_log_reader.beam: disk_log.hrl ../include/file.hrl
diff --git a/lib/kernel/src/application.erl b/lib/kernel/src/application.erl
index 2a193affd4..caac4d926c 100644
--- a/lib/kernel/src/application.erl
+++ b/lib/kernel/src/application.erl
@@ -28,49 +28,70 @@
-export([get_application/0, get_application/1, info/0]).
-export([start_type/0]).
--export([behaviour_info/1]).
-
%%%-----------------------------------------------------------------
+-type start_type() :: 'normal'
+ | {'takeover', Node :: node()}
+ | {'failover', Node :: node()}.
-type restart_type() :: 'permanent' | 'transient' | 'temporary'.
--type application_opt() :: {'description', string()}
- | {'vsn', string()}
- | {'id', string()}
- | {'modules', [atom() | {atom(), any()}]}
- | {'registered', [atom()]}
- | {'applications', [atom()]}
- | {'included_applications', [atom()]}
- | {'env', [{atom(), any()}]}
- | {'start_phases', [{atom(), any()}] | 'undefined'}
- | {'maxT', timeout()} % max timeout
- | {'maxP', integer() | 'infinity'} % max processes
- | {'mod', {atom(), any()}}.
--type application_spec() :: {'application', atom(), [application_opt()]}.
+-type application_opt() :: {'description', Description :: string()}
+ | {'vsn', Vsn :: string()}
+ | {'id', Id :: string()}
+ | {'modules', [(Module :: module()) |
+ {Module :: module(), Version :: term()}]}
+ | {'registered', Names :: [Name :: atom()]}
+ | {'applications', [Application :: atom()]}
+ | {'included_applications', [Application :: atom()]}
+ | {'env', [{Par :: atom(), Val :: term()}]}
+ | {'start_phases',
+ [{Phase :: atom(), PhaseArgs :: term()}] | 'undefined'}
+ | {'maxT', MaxT :: timeout()} % max timeout
+ | {'maxP',
+ MaxP :: pos_integer() | 'infinity'} % max processes
+ | {'mod', Start :: {Module :: module(), StartArgs :: term()}}.
+-type application_spec() :: {'application',
+ Application :: atom(),
+ AppSpecKeys :: [application_opt()]}.
+
+-type(tuple_of(_T) :: tuple()).
%%------------------------------------------------------------------
--spec behaviour_info(atom()) -> 'undefined' | [{atom(), byte()}].
+-callback start(StartType :: normal | {takeover, node()} | {failover, node()},
+ StartArgs :: term()) ->
+ {ok, pid()} | {ok, pid(), State :: term()} | {error, Reason :: term}.
-behaviour_info(callbacks) ->
- [{start,2},{stop,1}];
-behaviour_info(_Other) ->
- undefined.
+-callback stop(State :: term()) ->
+ term().
%%%-----------------------------------------------------------------
%%% This module is API towards application_controller and
%%% application_master.
%%%-----------------------------------------------------------------
--spec load(Application :: atom() | application_spec()) ->
- 'ok' | {'error', term()}.
+-spec load(AppDescr) -> 'ok' | {'error', Reason} when
+ AppDescr :: Application | (AppSpec :: application_spec()),
+ Application :: atom(),
+ Reason :: term().
load(Application) ->
- load(Application, []).
-
--spec load(Application :: atom() | application_spec(),
- Distributed :: any()) -> 'ok' | {'error', term()}.
+ load1(Application, []).
+
+-spec load(AppDescr, Distributed) -> 'ok' | {'error', Reason} when
+ AppDescr :: Application | (AppSpec :: application_spec()),
+ Application :: atom(),
+ Distributed :: {Application,Nodes}
+ | {Application,Time,Nodes}
+ | 'default',
+ Nodes :: [node() | tuple_of(node())],
+ Time :: pos_integer(),
+ Reason :: term().
load(Application, DistNodes) ->
+ load1(Application, DistNodes).
+
+%% Workaround due to specs.
+load1(Application, DistNodes) ->
case application_controller:load_application(Application) of
ok when DistNodes =/= [] ->
AppName = get_appl_name(Application),
@@ -85,18 +106,24 @@ load(Application, DistNodes) ->
Else
end.
--spec unload(Application :: atom()) -> 'ok' | {'error', term()}.
+-spec unload(Application) -> 'ok' | {'error', Reason} when
+ Application :: atom(),
+ Reason :: term().
unload(Application) ->
application_controller:unload_application(Application).
--spec start(Application :: atom()) -> 'ok' | {'error', term()}.
+-spec start(Application) -> 'ok' | {'error', Reason} when
+ Application :: atom(),
+ Reason :: term().
start(Application) ->
start(Application, temporary).
--spec start(Application :: atom() | application_spec(),
- RestartType :: restart_type()) -> any().
+-spec start(Application, Type) -> 'ok' | {'error', Reason} when
+ Application :: atom(),
+ Type :: restart_type(),
+ Reason :: term().
start(Application, RestartType) ->
case load(Application) of
@@ -120,12 +147,18 @@ start_boot(Application) ->
start_boot(Application, RestartType) ->
application_controller:start_boot_application(Application, RestartType).
--spec takeover(Application :: atom(), RestartType :: restart_type()) -> any().
+-spec takeover(Application, Type) -> 'ok' | {'error', Reason} when
+ Application :: atom(),
+ Type :: restart_type(),
+ Reason :: term().
takeover(Application, RestartType) ->
dist_ac:takeover_application(Application, RestartType).
--spec permit(Application :: atom(), Bool :: boolean()) -> 'ok' | {'error', term()}.
+-spec permit(Application, Permission) -> 'ok' | {'error', Reason} when
+ Application :: atom(),
+ Permission :: boolean(),
+ Reason :: term().
permit(Application, Bool) ->
case Bool of
@@ -142,105 +175,146 @@ permit(Application, Bool) ->
LocalResult
end.
--spec stop(Application :: atom()) -> 'ok' | {'error', term()}.
+-spec stop(Application) -> 'ok' | {'error', Reason} when
+ Application :: atom(),
+ Reason :: term().
stop(Application) ->
application_controller:stop_application(Application).
--spec which_applications() -> [{atom(), string(), string()}].
+-spec which_applications() -> [{Application, Description, Vsn}] when
+ Application :: atom(),
+ Description :: string(),
+ Vsn :: string().
which_applications() ->
application_controller:which_applications().
--spec which_applications(timeout()) -> [{atom(), string(), string()}].
+-spec which_applications(Timeout) -> [{Application, Description, Vsn}] when
+ Timeout :: timeout(),
+ Application :: atom(),
+ Description :: string(),
+ Vsn :: string().
which_applications(infinity) ->
application_controller:which_applications(infinity);
which_applications(Timeout) when is_integer(Timeout), Timeout>=0 ->
application_controller:which_applications(Timeout).
--spec loaded_applications() -> [{atom(), string(), string()}].
+-spec loaded_applications() -> [{Application, Description, Vsn}] when
+ Application :: atom(),
+ Description :: string(),
+ Vsn :: string().
loaded_applications() ->
application_controller:loaded_applications().
--spec info() -> any().
+-spec info() -> term().
info() ->
application_controller:info().
--spec set_env(Application :: atom(), Key :: atom(), Value :: any()) -> 'ok'.
+-spec set_env(Application, Par, Val) -> 'ok' when
+ Application :: atom(),
+ Par :: atom(),
+ Val :: term().
set_env(Application, Key, Val) ->
application_controller:set_env(Application, Key, Val).
--spec set_env(Application :: atom(), Key :: atom(),
- Value :: any(), Timeout :: timeout()) -> 'ok'.
+-spec set_env(Application, Par, Val, Timeout) -> 'ok' when
+ Application :: atom(),
+ Par :: atom(),
+ Val :: term(),
+ Timeout :: timeout().
set_env(Application, Key, Val, infinity) ->
application_controller:set_env(Application, Key, Val, infinity);
set_env(Application, Key, Val, Timeout) when is_integer(Timeout), Timeout>=0 ->
application_controller:set_env(Application, Key, Val, Timeout).
--spec unset_env(atom(), atom()) -> 'ok'.
+-spec unset_env(Application, Par) -> 'ok' when
+ Application :: atom(),
+ Par :: atom().
unset_env(Application, Key) ->
application_controller:unset_env(Application, Key).
--spec unset_env(atom(), atom(), timeout()) -> 'ok'.
+-spec unset_env(Application, Par, Timeout) -> 'ok' when
+ Application :: atom(),
+ Par :: atom(),
+ Timeout :: timeout().
unset_env(Application, Key, infinity) ->
application_controller:unset_env(Application, Key, infinity);
unset_env(Application, Key, Timeout) when is_integer(Timeout), Timeout>=0 ->
application_controller:unset_env(Application, Key, Timeout).
--spec get_env(atom()) -> 'undefined' | {'ok', term()}.
+-spec get_env(Par) -> 'undefined' | {'ok', Val} when
+ Par :: atom(),
+ Val :: term().
get_env(Key) ->
application_controller:get_pid_env(group_leader(), Key).
--spec get_env(atom(), atom()) -> 'undefined' | {'ok', term()}.
+-spec get_env(Application, Par) -> 'undefined' | {'ok', Val} when
+ Application :: atom(),
+ Par :: atom(),
+ Val :: term().
get_env(Application, Key) ->
application_controller:get_env(Application, Key).
--spec get_all_env() -> [{atom(), any()}].
+-spec get_all_env() -> Env when
+ Env :: [{Par :: atom(), Val :: term()}].
get_all_env() ->
application_controller:get_pid_all_env(group_leader()).
--spec get_all_env(atom()) -> [{atom(), any()}].
+-spec get_all_env(Application) -> Env when
+ Application :: atom(),
+ Env :: [{Par :: atom(), Val :: term()}].
get_all_env(Application) ->
application_controller:get_all_env(Application).
--spec get_key(atom()) -> 'undefined' | {'ok', term()}.
+-spec get_key(Key) -> 'undefined' | {'ok', Val} when
+ Key :: atom(),
+ Val :: term().
get_key(Key) ->
application_controller:get_pid_key(group_leader(), Key).
--spec get_key(atom(), atom()) -> 'undefined' | {'ok', term()}.
+-spec get_key(Application, Key) -> 'undefined' | {'ok', Val} when
+ Application :: atom(),
+ Key :: atom(),
+ Val :: term().
get_key(Application, Key) ->
application_controller:get_key(Application, Key).
--spec get_all_key() -> 'undefined' | [] | {'ok', [{atom(),any()},...]}.
+-spec get_all_key() -> [] | {'ok', Keys} when
+ Keys :: [{Key :: atom(),Val :: term()},...].
get_all_key() ->
application_controller:get_pid_all_key(group_leader()).
--spec get_all_key(atom()) -> 'undefined' | {'ok', [{atom(),any()},...]}.
+-spec get_all_key(Application) -> 'undefined' | Keys when
+ Application :: atom(),
+ Keys :: {'ok', [{Key :: atom(),Val :: term()},...]}.
get_all_key(Application) ->
application_controller:get_all_key(Application).
--spec get_application() -> 'undefined' | {'ok', atom()}.
+-spec get_application() -> 'undefined' | {'ok', Application} when
+ Application :: atom().
get_application() ->
application_controller:get_application(group_leader()).
--spec get_application(Pid :: pid()) -> 'undefined' | {'ok', atom()}
- ; (Module :: atom()) -> 'undefined' | {'ok', atom()}.
+-spec get_application(PidOrModule) -> 'undefined' | {'ok', Application} when
+ PidOrModule :: (Pid :: pid()) | (Module :: module()),
+ Application :: atom().
get_application(Pid) when is_pid(Pid) ->
case process_info(Pid, group_leader) of
@@ -252,8 +326,8 @@ get_application(Pid) when is_pid(Pid) ->
get_application(Module) when is_atom(Module) ->
application_controller:get_application_module(Module).
--spec start_type() -> 'undefined' | 'local' | 'normal'
- | {'takeover', node()} | {'failover', node()}.
+-spec start_type() -> StartType | 'undefined' | 'local' when
+ StartType :: start_type().
start_type() ->
application_controller:start_type(group_leader()).
diff --git a/lib/kernel/src/auth.erl b/lib/kernel/src/auth.erl
index 5c7fe2421d..c329a5652a 100644
--- a/lib/kernel/src/auth.erl
+++ b/lib/kernel/src/auth.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -57,7 +57,8 @@ start_link() ->
%%--Deprecated interface------------------------------------------------
--spec is_auth(Node :: node()) -> 'yes' | 'no'.
+-spec is_auth(Node) -> 'yes' | 'no' when
+ Node :: node().
is_auth(Node) ->
case net_adm:ping(Node) of
@@ -65,12 +66,15 @@ is_auth(Node) ->
pang -> no
end.
--spec cookie() -> cookie().
+-spec cookie() -> Cookie when
+ Cookie :: cookie().
cookie() ->
get_cookie().
--spec cookie(Cookies :: [cookie(),...] | cookie()) -> 'true'.
+-spec cookie(TheCookie) -> 'true' when
+ TheCookie :: Cookie | [Cookie],
+ Cookie :: cookie().
cookie([Cookie]) ->
set_cookie(Cookie);
@@ -82,7 +86,9 @@ cookie(Cookie) ->
node_cookie([Node, Cookie]) ->
node_cookie(Node, Cookie).
--spec node_cookie(Node :: node(), Cookie :: cookie()) -> 'yes' | 'no'.
+-spec node_cookie(Node, Cookie) -> 'yes' | 'no' when
+ Node :: node(),
+ Cookie :: cookie().
node_cookie(Node, Cookie) ->
set_cookie(Node, Cookie),
@@ -206,7 +212,7 @@ handle_info({From,badcookie,net_kernel,{From,spawn_link,_M,_F,_A,_Gleader}}, O)
{noreply, O};
handle_info({_From,badcookie,ddd_server,_Mess}, O) ->
%% Ignore bad messages to the ddd server, they will be resent
- %% If the authentication is succesful
+ %% If the authentication is successful
{noreply, O};
handle_info({From,badcookie,rex,_Msg}, O) ->
auth:print(getnode(From),
diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl
index b0f99305f2..882e9625fe 100644
--- a/lib/kernel/src/code.erl
+++ b/lib/kernel/src/code.erl
@@ -82,7 +82,8 @@
%% add_pathsa([Dir]) -> ok
%% add_pathsz([Dir]) -> ok
%% del_path(Dir) -> boolean() | {error, bad_name}
-%% replace_path(Name, Dir) -> true | replace_path_error()
+%% replace_path(Name, Dir) -> true | {error, bad_directory | bad_name
+%% | {badarg,_}}
%% load_file(Module) -> {module, Module} | {error, What :: atom()}
%% load_abs(File) -> {module, Module} | {error, What :: atom()}
%% load_abs(File, Module) -> {module, Module} | {error, What :: atom()}
@@ -113,11 +114,16 @@
%% Some types for basic exported functions of this module
%%----------------------------------------------------------------------------
--type load_error_rsn() :: 'badfile' | 'native_code' | 'nofile' | 'not_purged'
- | 'sticky_directory'. % for some functions only
--type load_ret() :: {'error', load_error_rsn()} | {'module', atom()}.
+-type load_error_rsn() :: 'badfile'
+ | 'native_code'
+ | 'nofile'
+ | 'not_purged'
+ | 'on_load'
+ | 'sticky_directory'.
+-type load_ret() :: {'error', What :: load_error_rsn()}
+ | {'module', Module :: module()}.
-type loaded_ret_atoms() :: 'cover_compiled' | 'preloaded'.
--type loaded_filename() :: file:filename() | loaded_ret_atoms().
+-type loaded_filename() :: (Filename :: file:filename()) | loaded_ret_atoms().
%%----------------------------------------------------------------------------
%% User interface
@@ -127,55 +133,74 @@
objfile_extension() ->
init:objfile_extension().
--spec load_file(Module :: atom()) -> load_ret().
+-spec load_file(Module) -> load_ret() when
+ Module :: module().
load_file(Mod) when is_atom(Mod) ->
call({load_file,Mod}).
--spec ensure_loaded(Module :: atom()) -> load_ret().
+-spec ensure_loaded(Module) -> {module, Module} | {error, What} when
+ Module :: module(),
+ What :: embedded | badfile | native_code | nofile | on_load.
ensure_loaded(Mod) when is_atom(Mod) ->
call({ensure_loaded,Mod}).
%% XXX File as an atom is allowed only for backwards compatibility.
--spec load_abs(Filename :: file:filename()) -> load_ret().
+-spec load_abs(Filename) -> load_ret() when
+ Filename :: file:filename().
load_abs(File) when is_list(File); is_atom(File) -> call({load_abs,File,[]}).
%% XXX Filename is also an atom(), e.g. 'cover_compiled'
--spec load_abs(Filename :: loaded_filename(), Module :: atom()) -> load_ret().
+-spec load_abs(Filename :: loaded_filename(), Module :: module()) -> load_ret().
load_abs(File, M) when (is_list(File) orelse is_atom(File)), is_atom(M) ->
call({load_abs,File,M}).
%% XXX Filename is also an atom(), e.g. 'cover_compiled'
--spec load_binary(Module :: atom(), Filename :: loaded_filename(), Binary :: binary()) -> load_ret().
+-spec load_binary(Module, Filename, Binary) ->
+ {module, Module} | {error, What} when
+ Module :: module(),
+ Filename :: loaded_filename(),
+ Binary :: binary(),
+ What :: badarg | load_error_rsn().
load_binary(Mod, File, Bin)
when is_atom(Mod), (is_list(File) orelse is_atom(File)), is_binary(Bin) ->
call({load_binary,Mod,File,Bin}).
--spec load_native_partial(Module :: atom(), Binary :: binary()) -> load_ret().
+-spec load_native_partial(Module :: module(), Binary :: binary()) -> load_ret().
load_native_partial(Mod, Bin) when is_atom(Mod), is_binary(Bin) ->
call({load_native_partial,Mod,Bin}).
--spec load_native_sticky(Module :: atom(), Binary :: binary(), WholeModule :: 'false' | binary()) -> load_ret().
+-spec load_native_sticky(Module :: module(), Binary :: binary(), WholeModule :: 'false' | binary()) -> load_ret().
load_native_sticky(Mod, Bin, WholeModule)
when is_atom(Mod), is_binary(Bin),
(is_binary(WholeModule) orelse WholeModule =:= false) ->
call({load_native_sticky,Mod,Bin,WholeModule}).
--spec delete(Module :: atom()) -> boolean().
+-spec delete(Module) -> boolean() when
+ Module :: module().
delete(Mod) when is_atom(Mod) -> call({delete,Mod}).
--spec purge(Module :: atom()) -> boolean().
+-spec purge(Module) -> boolean() when
+ Module :: module().
purge(Mod) when is_atom(Mod) -> call({purge,Mod}).
--spec soft_purge(Module :: atom()) -> boolean().
+-spec soft_purge(Module) -> boolean() when
+ Module :: module().
soft_purge(Mod) when is_atom(Mod) -> call({soft_purge,Mod}).
--spec is_loaded(Module :: atom()) -> {'file', loaded_filename()} | 'false'.
+-spec is_loaded(Module) -> {'file', Loaded} | false when
+ Module :: module(),
+ Loaded :: loaded_filename().
is_loaded(Mod) when is_atom(Mod) -> call({is_loaded,Mod}).
--spec get_object_code(Module :: atom()) -> {atom(), binary(), file:filename()} | 'error'.
+-spec get_object_code(Module) -> {Module, Binary, Filename} | error when
+ Module :: module(),
+ Binary :: binary(),
+ Filename :: file:filename().
get_object_code(Mod) when is_atom(Mod) -> call({get_object_code, Mod}).
--spec all_loaded() -> [{atom(), loaded_filename()}].
+-spec all_loaded() -> [{Module, Loaded}] when
+ Module :: module(),
+ Loaded :: loaded_filename().
all_loaded() -> call(all_loaded).
-spec stop() -> no_return().
@@ -188,65 +213,86 @@ root_dir() -> call({dir,root_dir}).
lib_dir() -> call({dir,lib_dir}).
%% XXX is_list() is for backwards compatibility -- take out in future version
--spec lib_dir(App :: atom()) -> file:filename() | {'error', 'bad_name'}.
+-spec lib_dir(Name) -> file:filename() | {'error', 'bad_name'} when
+ Name :: atom().
lib_dir(App) when is_atom(App) ; is_list(App) -> call({dir,{lib_dir,App}}).
--spec lib_dir(App :: atom(), SubDir :: atom()) -> file:filename() | {'error', 'bad_name'}.
+-spec lib_dir(Name, SubDir) -> file:filename() | {'error', 'bad_name'} when
+ Name :: atom(),
+ SubDir :: atom().
lib_dir(App, SubDir) when is_atom(App), is_atom(SubDir) -> call({dir,{lib_dir,App,SubDir}}).
-spec compiler_dir() -> file:filename().
compiler_dir() -> call({dir,compiler_dir}).
%% XXX is_list() is for backwards compatibility -- take out in future version
--spec priv_dir(App :: atom()) -> file:filename() | {'error', 'bad_name'}.
+-spec priv_dir(Name) -> file:filename() | {'error', 'bad_name'} when
+ Name :: atom().
priv_dir(App) when is_atom(App) ; is_list(App) -> call({dir,{priv_dir,App}}).
--spec stick_dir(Directory :: file:filename()) -> 'ok' | 'error'.
+-spec stick_dir(Dir) -> 'ok' | 'error' when
+ Dir :: file:filename().
stick_dir(Dir) when is_list(Dir) -> call({stick_dir,Dir}).
--spec unstick_dir(Directory :: file:filename()) -> 'ok' | 'error'.
+-spec unstick_dir(Dir) -> 'ok' | 'error' when
+ Dir :: file:filename().
unstick_dir(Dir) when is_list(Dir) -> call({unstick_dir,Dir}).
--spec stick_mod(Module :: atom()) -> 'true'.
+-spec stick_mod(Module :: module()) -> 'true'.
stick_mod(Mod) when is_atom(Mod) -> call({stick_mod,Mod}).
--spec unstick_mod(Module :: atom()) -> 'true'.
+-spec unstick_mod(Module :: module()) -> 'true'.
unstick_mod(Mod) when is_atom(Mod) -> call({unstick_mod,Mod}).
--spec is_sticky(Module :: atom()) -> boolean().
+-spec is_sticky(Module) -> boolean() when
+ Module :: module().
is_sticky(Mod) when is_atom(Mod) -> call({is_sticky,Mod}).
--spec set_path(Directories :: [file:filename()]) ->
- 'true' | {'error', 'bad_directory' | 'bad_path'}.
+-spec set_path(Path) -> 'true' | {'error', What} when
+ Path :: [Dir :: file:filename()],
+ What :: 'bad_directory' | 'bad_path'.
set_path(PathList) when is_list(PathList) -> call({set_path,PathList}).
--spec get_path() -> [file:filename()].
+-spec get_path() -> Path when
+ Path :: [Dir :: file:filename()].
get_path() -> call(get_path).
-type add_path_ret() :: 'true' | {'error', 'bad_directory'}.
--spec add_path(Directory :: file:filename()) -> add_path_ret().
+-spec add_path(Dir) -> add_path_ret() when
+ Dir :: file:filename().
add_path(Dir) when is_list(Dir) -> call({add_path,last,Dir}).
--spec add_pathz(Directory :: file:filename()) -> add_path_ret().
+-spec add_pathz(Dir) -> add_path_ret() when
+ Dir :: file:filename().
add_pathz(Dir) when is_list(Dir) -> call({add_path,last,Dir}).
--spec add_patha(Directory :: file:filename()) -> add_path_ret().
+-spec add_patha(Dir) -> add_path_ret() when
+ Dir :: file:filename().
add_patha(Dir) when is_list(Dir) -> call({add_path,first,Dir}).
--spec add_paths(Directories :: [file:filename()]) -> 'ok'.
+-spec add_paths(Dirs) -> 'ok' when
+ Dirs :: [Dir :: file:filename()].
add_paths(Dirs) when is_list(Dirs) -> call({add_paths,last,Dirs}).
--spec add_pathsz(Directories :: [file:filename()]) -> 'ok'.
+-spec add_pathsz(Dirs) -> 'ok' when
+ Dirs :: [Dir :: file:filename()].
add_pathsz(Dirs) when is_list(Dirs) -> call({add_paths,last,Dirs}).
--spec add_pathsa(Directories :: [file:filename()]) -> 'ok'.
+-spec add_pathsa(Dirs) -> 'ok' when
+ Dirs :: [Dir :: file:filename()].
add_pathsa(Dirs) when is_list(Dirs) -> call({add_paths,first,Dirs}).
--spec del_path(Name :: file:filename() | atom()) -> boolean() | {'error', 'bad_name'}.
+-spec del_path(NameOrDir) -> boolean() | {'error', What} when
+ NameOrDir :: Name | Dir,
+ Name :: atom(),
+ Dir :: file:filename(),
+ What :: 'bad_name'.
del_path(Name) when is_list(Name) ; is_atom(Name) -> call({del_path,Name}).
--type replace_path_error() :: {'error', 'bad_directory' | 'bad_name' | {'badarg',_}}.
--spec replace_path(Name:: atom(), Dir :: file:filename()) -> 'true' | replace_path_error().
+-spec replace_path(Name, Dir) -> 'true' | {'error', What} when
+ Name:: atom(),
+ Dir :: file:filename(),
+ What :: 'bad_directory' | 'bad_name' | {'badarg',_}.
replace_path(Name, Dir) when (is_atom(Name) orelse is_list(Name)),
(is_atom(Dir) orelse is_list(Dir)) ->
call({replace_path,Name,Dir}).
@@ -351,10 +397,9 @@ get_mode(Flags) ->
%% In that case return the name of the file which contains
%% the loaded object code
--type which_ret_atoms() :: loaded_ret_atoms() | 'non_existing'.
-
--spec which(Module :: atom()) -> file:filename() | which_ret_atoms().
-
+-spec which(Module) -> Which when
+ Module :: module(),
+ Which :: file:filename() | loaded_ret_atoms() | non_existing.
which(Module) when is_atom(Module) ->
case is_loaded(Module) of
false ->
@@ -394,9 +439,9 @@ which(File, Base, [Directory|Tail]) ->
%% Search the code path for a specific file. Try to locate
%% it in the code path cache if possible.
--spec where_is_file(Filename :: file:filename()) ->
- 'non_existing' | file:filename().
-
+-spec where_is_file(Filename) -> non_existing | Absname when
+ Filename :: file:filename(),
+ Absname :: file:filename().
where_is_file(File) when is_list(File) ->
case call({is_cached,File}) of
no ->
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index 4a1fc7df34..e3d22e7999 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1379,8 +1379,12 @@ absname_vr([[X, $:]|Name], _, _AbsBase) ->
%% Kill all processes running code from *old* Module, and then purge the
%% module. Return true if any processes killed, else false.
-do_purge(Mod) ->
- do_purge(processes(), to_atom(Mod), false).
+do_purge(Mod0) ->
+ Mod = to_atom(Mod0),
+ case erlang:check_old_code(Mod) of
+ false -> false;
+ true -> do_purge(processes(), Mod, false)
+ end.
do_purge([P|Ps], Mod, Purged) ->
case erlang:check_process_code(P, Mod) of
@@ -1399,16 +1403,19 @@ do_purge([], Mod, Purged) ->
Purged.
%% do_soft_purge(Module)
-%% Purge old code only if no procs remain that run old code
+%% Purge old code only if no procs remain that run old code.
%% Return true in that case, false if procs remain (in this
%% case old code is not purged)
do_soft_purge(Mod) ->
- catch do_soft_purge(processes(), Mod).
+ case erlang:check_old_code(Mod) of
+ false -> true;
+ true -> do_soft_purge(processes(), Mod)
+ end.
do_soft_purge([P|Ps], Mod) ->
case erlang:check_process_code(P, Mod) of
- true -> throw(false);
+ true -> false;
false -> do_soft_purge(Ps, Mod)
end;
do_soft_purge([], Mod) ->
diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl
index 7f1b5f9ec6..d6bc23be6d 100644
--- a/lib/kernel/src/disk_log.erl
+++ b/lib/kernel/src/disk_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -70,9 +70,10 @@
%%% Contract type specifications
%%%----------------------------------------------------------------------
+-opaque continuation() :: #continuation{}.
+
-type bytes() :: binary() | [byte()].
--type log() :: term(). % XXX: refine
-type file_error() :: term(). % XXX: refine
-type invalid_header() :: term(). % XXX: refine
@@ -87,27 +88,30 @@
-type open_error_rsn() :: 'no_such_log'
| {'badarg', term()}
- | {'size_mismatch', dlog_size(), dlog_size()}
- | {'arg_mismatch', dlog_optattr(), term(), term()}
- | {'name_already_open', log()}
- | {'open_read_write', log()}
- | {'open_read_only', log()}
- | {'need_repair', log()}
- | {'not_a_log_file', string()}
- | {'invalid_index_file', string()}
+ | {'size_mismatch', CurrentSize :: dlog_size(),
+ NewSize :: dlog_size()}
+ | {'arg_mismatch', OptionName :: dlog_optattr(),
+ CurrentValue :: term(), Value :: term()}
+ | {'name_already_open', Log :: log()}
+ | {'open_read_write', Log :: log()}
+ | {'open_read_only', Log :: log()}
+ | {'need_repair', Log :: log()}
+ | {'not_a_log_file', FileName :: file:filename()}
+ | {'invalid_index_file', FileName :: file:filename()}
| {'invalid_header', invalid_header()}
| {'file_error', file:filename(), file_error()}
- | {'node_already_open', log()}.
+ | {'node_already_open', Log :: log()}.
-type dist_error_rsn() :: 'nodedown' | open_error_rsn().
--type ret() :: {'ok', log()}
- | {'repaired', log(), {'recovered', non_neg_integer()},
- {'badbytes', non_neg_integer()}}.
+-type ret() :: {'ok', Log :: log()}
+ | {'repaired', Log :: log(),
+ {'recovered', Rec :: non_neg_integer()},
+ {'badbytes', Bad :: non_neg_integer()}}.
-type open_ret() :: ret() | {'error', open_error_rsn()}.
-type dist_open_ret() :: {[{node(), ret()}],
[{node(), {'error', dist_error_rsn()}}]}.
--type all_open_ret() :: open_ret() | dist_open_ret().
--spec open(Args :: dlog_options()) -> all_open_ret().
+-spec open(ArgL) -> open_ret() | dist_open_ret() when
+ ArgL :: dlog_options().
open(A) ->
disk_log_server:open(check_arg(A, #arg{options = A})).
@@ -116,40 +120,57 @@ open(A) ->
| {'full', log()} | {'invalid_header', invalid_header()}
| {'file_error', file:filename(), file_error()}.
--spec log(Log :: log(), Term :: term()) -> 'ok' | {'error', log_error_rsn()}.
+-spec log(Log, Term) -> ok | {error, Reason :: log_error_rsn()} when
+ Log :: log(),
+ Term :: term().
log(Log, Term) ->
req(Log, {log, term_to_binary(Term)}).
--spec blog(Log :: log(), Bytes :: bytes()) -> 'ok' | {'error', log_error_rsn()}.
+-spec blog(Log, Bytes) -> ok | {error, Reason :: log_error_rsn()} when
+ Log :: log(),
+ Bytes :: bytes().
blog(Log, Bytes) ->
req(Log, {blog, check_bytes(Bytes)}).
--spec log_terms(Log :: log(), Terms :: [term()]) -> 'ok' | {'error', term()}.
+-spec log_terms(Log, TermList) -> ok | {error, Resaon :: log_error_rsn()} when
+ Log :: log(),
+ TermList :: [term()].
log_terms(Log, Terms) ->
Bs = terms2bins(Terms),
req(Log, {log, Bs}).
--spec blog_terms(Log :: log(), Bytes :: [bytes()]) -> 'ok' | {'error', term()}.
+-spec blog_terms(Log, BytesList) ->
+ ok | {error, Reason :: log_error_rsn()} when
+ Log :: log(),
+ BytesList :: [bytes()].
blog_terms(Log, Bytess) ->
Bs = check_bytes_list(Bytess, Bytess),
req(Log, {blog, Bs}).
-type notify_ret() :: 'ok' | {'error', 'no_such_log'}.
--spec alog(Log :: log(), Term :: term()) -> notify_ret().
+-spec alog(Log, Term) -> notify_ret() when
+ Log :: log(),
+ Term :: term().
alog(Log, Term) ->
notify(Log, {alog, term_to_binary(Term)}).
--spec alog_terms(Log :: log(), Terms :: [term()]) -> notify_ret().
+-spec alog_terms(Log, TermList) -> notify_ret() when
+ Log :: log(),
+ TermList :: [term()].
alog_terms(Log, Terms) ->
Bs = terms2bins(Terms),
notify(Log, {alog, Bs}).
--spec balog(Log :: log(), Bytes :: bytes()) -> notify_ret().
+-spec balog(Log, Bytes) -> notify_ret() when
+ Log :: log(),
+ Bytes :: bytes().
balog(Log, Bytes) ->
notify(Log, {balog, check_bytes(Bytes)}).
--spec balog_terms(Log :: log(), Bytes :: [bytes()]) -> notify_ret().
+-spec balog_terms(Log, ByteList) -> notify_ret() when
+ Log :: log(),
+ ByteList :: [bytes()].
balog_terms(Log, Bytess) ->
Bs = check_bytes_list(Bytess, Bytess),
notify(Log, {balog, Bs}).
@@ -157,18 +178,22 @@ balog_terms(Log, Bytess) ->
-type close_error_rsn() ::'no_such_log' | 'nonode'
| {'file_error', file:filename(), file_error()}.
--spec close(Log :: log()) -> 'ok' | {'error', close_error_rsn()}.
+-spec close(Log) -> 'ok' | {'error', close_error_rsn()} when
+ Log :: log().
close(Log) ->
req(Log, close).
-type lclose_error_rsn() :: 'no_such_log'
| {'file_error', file:filename(), file_error()}.
--spec lclose(Log :: log()) -> 'ok' | {'error', lclose_error_rsn()}.
+-spec lclose(Log) -> 'ok' | {'error', lclose_error_rsn()} when
+ Log :: log().
lclose(Log) ->
lclose(Log, node()).
--spec lclose(Log :: log(), Node :: node()) -> 'ok' | {'error', lclose_error_rsn()}.
+-spec lclose(Log, Node) -> 'ok' | {'error', lclose_error_rsn()} when
+ Log :: log(),
+ Node :: node().
lclose(Log, Node) ->
lreq(Log, close, Node).
@@ -178,29 +203,49 @@ lclose(Log, Node) ->
| {'invalid_header', invalid_header()}
| {'file_error', file:filename(), file_error()}.
--spec truncate(Log :: log()) -> 'ok' | {'error', trunc_error_rsn()}.
+-spec truncate(Log) -> 'ok' | {'error', trunc_error_rsn()} when
+ Log :: log().
truncate(Log) ->
req(Log, {truncate, none, truncate, 1}).
--spec truncate(Log :: log(), Head :: term()) -> 'ok' | {'error', trunc_error_rsn()}.
+-spec truncate(Log, Head) -> 'ok' | {'error', trunc_error_rsn()} when
+ Log :: log(),
+ Head :: term().
truncate(Log, Head) ->
req(Log, {truncate, {ok, term_to_binary(Head)}, truncate, 2}).
--spec btruncate(Log :: log(), Head :: bytes()) -> 'ok' | {'error', trunc_error_rsn()}.
+-spec btruncate(Log, BHead) -> 'ok' | {'error', trunc_error_rsn()} when
+ Log :: log(),
+ BHead :: bytes().
btruncate(Log, Head) ->
req(Log, {truncate, {ok, check_bytes(Head)}, btruncate, 2}).
--spec reopen(Log :: log(), Filename :: file:filename()) -> 'ok' | {'error', term()}.
+-type reopen_error_rsn() :: no_such_log
+ | nonode
+ | {read_only_mode, log()}
+ | {blocked_log, log()}
+ | {same_file_name, log()} |
+ {invalid_index_file, file:filename()}
+ | {invalid_header, invalid_header()}
+ | {'file_error', file:filename(), file_error()}.
+
+-spec reopen(Log, File) -> 'ok' | {'error', reopen_error_rsn()} when
+ Log :: log(),
+ File :: file:filename().
reopen(Log, NewFile) ->
req(Log, {reopen, NewFile, none, reopen, 2}).
--spec reopen(Log :: log(), Filename :: file:filename(), Head :: term()) ->
- 'ok' | {'error', term()}.
+-spec reopen(Log, File, Head) -> 'ok' | {'error', reopen_error_rsn()} when
+ Log :: log(),
+ File :: file:filename(),
+ Head :: term().
reopen(Log, NewFile, NewHead) ->
req(Log, {reopen, NewFile, {ok, term_to_binary(NewHead)}, reopen, 3}).
--spec breopen(Log :: log(), Filename :: file:filename(), Head :: bytes()) ->
- 'ok' | {'error', term()}.
+-spec breopen(Log, File, BHead) -> 'ok' | {'error', reopen_error_rsn()} when
+ Log :: log(),
+ File :: file:filename(),
+ BHead :: bytes().
breopen(Log, NewFile, NewHead) ->
req(Log, {reopen, NewFile, {ok, check_bytes(NewHead)}, breopen, 3}).
@@ -210,21 +255,36 @@ breopen(Log, NewFile, NewHead) ->
| {'invalid_header', invalid_header()}
| {'file_error', file:filename(), file_error()}.
--spec inc_wrap_file(Log :: log()) -> 'ok' | {'error', inc_wrap_error_rsn()}.
+-spec inc_wrap_file(Log) -> 'ok' | {'error', inc_wrap_error_rsn()} when
+ Log :: log().
inc_wrap_file(Log) ->
req(Log, inc_wrap_file).
--spec change_size(Log :: log(), Size :: dlog_size()) -> 'ok' | {'error', term()}.
+-spec change_size(Log, Size) -> 'ok' | {'error', Reason} when
+ Log :: log(),
+ Size :: dlog_size(),
+ Reason :: no_such_log | nonode | {read_only_mode, Log}
+ | {blocked_log, Log}
+ | {new_size_too_small, CurrentSize :: pos_integer()}
+ | {badarg, size}
+ | {file_error, file:filename(), file_error()}.
change_size(Log, NewSize) ->
req(Log, {change_size, NewSize}).
--spec change_notify(Log :: log(), Pid :: pid(), Notify :: boolean()) ->
- 'ok' | {'error', term()}.
+-spec change_notify(Log, Owner, Notify) -> 'ok' | {'error', Reason} when
+ Log :: log(),
+ Owner :: pid(),
+ Notify :: boolean(),
+ Reason :: no_such_log | nonode | {blocked_log, Log}
+ | {badarg, notify} | {not_owner, Owner}.
change_notify(Log, Pid, NewNotify) ->
req(Log, {change_notify, Pid, NewNotify}).
--spec change_header(Log :: log(), Head :: {atom(), term()}) ->
- 'ok' | {'error', term()}.
+-spec change_header(Log, Header) -> 'ok' | {'error', Reason} when
+ Log :: log(),
+ Header :: {head, dlog_head_opt()} | {head_func, mfa()},
+ Reason :: no_such_log | nonode | {read_only_mode, Log}
+ | {blocked_log, Log} | {badarg, head}.
change_header(Log, NewHead) ->
req(Log, {change_header, NewHead}).
@@ -232,17 +292,21 @@ change_header(Log, NewHead) ->
| {'blocked_log', log()}
| {'file_error', file:filename(), file_error()}.
--spec sync(Log :: log()) -> 'ok' | {'error', sync_error_rsn()}.
+-spec sync(Log) -> 'ok' | {'error', sync_error_rsn()} when
+ Log :: log().
sync(Log) ->
req(Log, sync).
-type block_error_rsn() :: 'no_such_log' | 'nonode' | {'blocked_log', log()}.
--spec block(Log :: log()) -> 'ok' | {'error', block_error_rsn()}.
+-spec block(Log) -> 'ok' | {'error', block_error_rsn()} when
+ Log :: log().
block(Log) ->
block(Log, true).
--spec block(Log :: log(), QueueLogRecords :: boolean()) -> 'ok' | {'error', term()}.
+-spec block(Log, QueueLogRecords) -> 'ok' | {'error', block_error_rsn()} when
+ Log :: log(),
+ QueueLogRecords :: boolean().
block(Log, QueueLogRecords) ->
req(Log, {block, QueueLogRecords}).
@@ -250,19 +314,46 @@ block(Log, QueueLogRecords) ->
| {'not_blocked', log()}
| {'not_blocked_by_pid', log()}.
--spec unblock(Log :: log()) -> 'ok' | {'error', unblock_error_rsn()}.
+-spec unblock(Log) -> 'ok' | {'error', unblock_error_rsn()} when
+ Log :: log().
unblock(Log) ->
req(Log, unblock).
--spec format_error(Error :: term()) -> string().
+-spec format_error(Error) -> io_lib:chars() when
+ Error :: term().
format_error(Error) ->
do_format_error(Error).
--spec info(Log :: log()) -> [{atom(), any()}] | {'error', term()}.
+-type dlog_info() :: {name, Log :: log()}
+ | {file, File :: file:filename()}
+ | {type, Type :: dlog_type()}
+ | {format, Format :: dlog_format()}
+ | {size, Size :: dlog_size()}
+ | {mode, Mode :: dlog_mode()}
+ | {owners, [{pid(), Notify :: boolean()}]}
+ | {users, Users :: non_neg_integer()}
+ | {status, Status ::
+ ok | {blocked, QueueLogRecords :: boolean()}}
+ | {node, Node :: node()}
+ | {distributed, Dist :: local | [node()]}
+ | {head, Head :: none | {head, term()} | mfa()}
+ | {no_written_items, NoWrittenItems ::non_neg_integer()}
+ | {full, Full :: boolean}
+ | {no_current_bytes, non_neg_integer()}
+ | {no_current_items, non_neg_integer()}
+ | {no_items, non_neg_integer()}
+ | {current_file, pos_integer()}
+ | {no_overflows, {SinceLogWasOpened :: non_neg_integer(),
+ SinceLastInfo :: non_neg_integer()}}.
+-spec info(Log) -> InfoList | {'error', no_such_log} when
+ Log :: log(),
+ InfoList :: [dlog_info()].
info(Log) ->
sreq(Log, info).
--spec pid2name(Pid :: pid()) -> {'ok', log()} | 'undefined'.
+-spec pid2name(Pid) -> {'ok', Log} | 'undefined' when
+ Pid :: pid(),
+ Log :: log().
pid2name(Pid) ->
disk_log_server:start(),
case ets:lookup(?DISK_LOG_PID_TABLE, Pid) of
@@ -274,13 +365,31 @@ pid2name(Pid) ->
%% It retuns a {Cont2, ObjList} | eof | {error, Reason}
%% The initial continuation is the atom 'start'
--spec chunk(Log :: log(), Cont :: any()) ->
- {'error', term()} | 'eof' | {any(), [any()]} | {any(), [any()], integer()}.
+-type chunk_error_rsn() :: no_such_log
+ | {format_external, log()}
+ | {blocked_log, log()}
+ | {badarg, continuation}
+ | {not_internal_wrap, log()}
+ | {corrupt_log_file, FileName :: file:filename()}
+ | {file_error, file:filename(), file_error()}.
+
+-type chunk_ret() :: {Continuation2 :: continuation(), Terms :: [term()]}
+ | {Continuation2 :: continuation(),
+ Terms :: [term()],
+ Badbytes :: non_neg_integer()}
+ | eof
+ | {error, Reason :: chunk_error_rsn()}.
+
+-spec chunk(Log, Continuation) -> chunk_ret() when
+ Log :: log(),
+ Continuation :: start | continuation().
chunk(Log, Cont) ->
chunk(Log, Cont, infinity).
--spec chunk(Log :: log(), Cont :: any(), N :: pos_integer() | 'infinity') ->
- {'error', term()} | 'eof' | {any(), [any()]} | {any(), [any()], integer()}.
+-spec chunk(Log, Continuation, N) -> chunk_ret() when
+ Log :: log(),
+ Continuation :: start | continuation(),
+ N :: pos_integer() | infinity.
chunk(Log, Cont, infinity) ->
%% There cannot be more than ?MAX_CHUNK_SIZE terms in a chunk.
ichunk(Log, Cont, ?MAX_CHUNK_SIZE);
@@ -346,13 +455,24 @@ ichunk_bad_end([B | Bs], Mode, Log, C, Bad, A) ->
ichunk_bad_end(Bs, Mode, Log, C, Bad, [T | A])
end.
--spec bchunk(Log :: log(), Cont :: any()) ->
- {'error', any()} | 'eof' | {any(), [binary()]} | {any(), [binary()], integer()}.
+-type bchunk_ret() :: {Continuation2 :: continuation(),
+ Binaries :: [binary()]}
+ | {Continuation2 :: continuation(),
+ Binaries :: [binary()],
+ Badbytes :: non_neg_integer()}
+ | eof
+ | {error, Reason :: chunk_error_rsn()}.
+
+-spec bchunk(Log, Continuation) -> bchunk_ret() when
+ Log :: log(),
+ Continuation :: start | continuation().
bchunk(Log, Cont) ->
bchunk(Log, Cont, infinity).
--spec bchunk(Log :: log(), Cont :: any(), N :: 'infinity' | pos_integer()) ->
- {'error', any()} | 'eof' | {any(), [binary()]} | {any(), [binary()], integer()}.
+-spec bchunk(Log, Continuation, N) -> bchunk_ret() when
+ Log :: log(),
+ Continuation :: start | continuation(),
+ N :: pos_integer() | infinity.
bchunk(Log, Cont, infinity) ->
%% There cannot be more than ?MAX_CHUNK_SIZE terms in a chunk.
bichunk(Log, Cont, ?MAX_CHUNK_SIZE);
@@ -375,8 +495,14 @@ bichunk_end({C = #continuation{}, R, Bad}) ->
bichunk_end(R) ->
R.
--spec chunk_step(Log :: log(), Cont :: any(), N :: integer()) ->
- {'ok', any()} | {'error', term()}.
+-spec chunk_step(Log, Continuation, Step) ->
+ {'ok', any()} | {'error', Reason} when
+ Log :: log(),
+ Continuation :: start | continuation(),
+ Step :: integer(),
+ Reason :: no_such_log | end_of_log | {format_external, Log}
+ | {blocked_log, Log} | {badarg, continuation}
+ | {file_error, file:filename(), file_error()}.
chunk_step(Log, Cont, N) when is_integer(N) ->
ichunk_step(Log, Cont, N).
@@ -387,14 +513,18 @@ ichunk_step(_Log, More, N) when is_record(More, continuation) ->
ichunk_step(_Log, _, _) ->
{error, {badarg, continuation}}.
--spec chunk_info(More :: any()) ->
- [{'node', node()},...] | {'error', {'no_continuation', any()}}.
+-spec chunk_info(Continuation) -> InfoList | {error, Reason} when
+ Continuation :: continuation(),
+ InfoList :: [{node, Node :: node()}, ...],
+ Reason :: {no_continuation, Continuation}.
chunk_info(More = #continuation{}) ->
[{node, node(More#continuation.pid)}];
chunk_info(BadCont) ->
{error, {no_continuation, BadCont}}.
--spec accessible_logs() -> {[_], [_]}.
+-spec accessible_logs() -> {[LocalLog], [DistributedLog]} when
+ LocalLog :: log(),
+ DistributedLog :: log().
accessible_logs() ->
disk_log_server:accessible_logs().
@@ -1110,20 +1240,29 @@ is_owner(Pid, L) ->
%% ok | throw(Error)
rename_file(File, NewFile, halt) ->
- file:rename(File, NewFile);
+ case file:rename(File, NewFile) of
+ ok ->
+ ok;
+ Else ->
+ file_error(NewFile, Else)
+ end;
rename_file(File, NewFile, wrap) ->
rename_file(wrap_file_extensions(File), File, NewFile, ok).
-rename_file([Ext|Exts], File, NewFile, Res) ->
- NRes = case file:rename(add_ext(File, Ext), add_ext(NewFile, Ext)) of
+rename_file([Ext|Exts], File, NewFile0, Res) ->
+ NewFile = add_ext(NewFile0, Ext),
+ NRes = case file:rename(add_ext(File, Ext), NewFile) of
ok ->
Res;
Else ->
- Else
+ file_error(NewFile, Else)
end,
- rename_file(Exts, File, NewFile, NRes);
+ rename_file(Exts, File, NewFile0, NRes);
rename_file([], _File, _NewFiles, Res) -> Res.
+file_error(FileName, {error, Error}) ->
+ {error, {file_error, FileName, Error}}.
+
%% "Old" error messages have been kept, arg_mismatch has been added.
%%-spec compare_arg(dlog_options(), #arg{},
compare_arg([], _A, none, _OrigHead) ->
@@ -1817,7 +1956,8 @@ monitor_request(Pid, Req) ->
receive
{'DOWN', Ref, process, Pid, _Info} ->
{error, no_such_log};
- {disk_log, Pid, Reply} ->
+ {disk_log, Pid, Reply} when not is_tuple(Reply) orelse
+ element(2, Reply) =/= disk_log_stopped ->
erlang:demonitor(Ref),
receive
{'DOWN', Ref, process, Pid, _Reason} ->
diff --git a/lib/kernel/src/disk_log.hrl b/lib/kernel/src/disk_log.hrl
index 9a94d4d3b9..259967650f 100644
--- a/lib/kernel/src/disk_log.hrl
+++ b/lib/kernel/src/disk_log.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The 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,18 +53,34 @@
%% Types -- alphabetically
%%------------------------------------------------------------------------
+-type dlog_byte() :: [dlog_byte()] | byte().
-type dlog_format() :: 'external' | 'internal'.
-type dlog_format_type() :: 'halt_ext' | 'halt_int' | 'wrap_ext' | 'wrap_int'.
-type dlog_head() :: 'none' | {'ok', binary()} | mfa().
+-type dlog_head_opt() :: none | term() | binary() | [dlog_byte()].
+-type log() :: term(). % XXX: refine
-type dlog_mode() :: 'read_only' | 'read_write'.
-type dlog_name() :: atom() | string().
-type dlog_optattr() :: 'name' | 'file' | 'linkto' | 'repair' | 'type'
| 'format' | 'size' | 'distributed' | 'notify'
| 'head' | 'head_func' | 'mode'.
--type dlog_options() :: [{dlog_optattr(), any()}].
+-type dlog_option() :: {name, Log :: log()}
+ | {file, FileName :: file:filename()}
+ | {linkto, LinkTo :: none | pid()}
+ | {repair, Repair :: true | false | truncate}
+ | {type, Type :: dlog_type}
+ | {format, Format :: dlog_format()}
+ | {size, Size :: dlog_size()}
+ | {distributed, Nodes :: [node()]}
+ | {notify, boolean()}
+ | {head, Head :: dlog_head_opt()}
+ | {head_func, mfa()}
+ | {mode, Mode :: dlog_mode()}.
+-type dlog_options() :: [dlog_option()].
-type dlog_repair() :: 'truncate' | boolean().
-type dlog_size() :: 'infinity' | pos_integer()
- | {pos_integer(), pos_integer()}.
+ | {MaxNoBytes :: pos_integer(),
+ MaxNoFiles :: pos_integer()}.
-type dlog_status() :: 'ok' | {'blocked', 'false' | [_]}. %QueueLogRecords
-type dlog_type() :: 'halt' | 'wrap'.
@@ -75,7 +91,7 @@
%% record of args for open
-record(arg, {name = 0,
version = undefined,
- file = none :: 'none' | string(),
+ file = none :: 'none' | file:filename(),
repair = true :: dlog_repair(),
size = infinity :: dlog_size(),
type = halt :: dlog_type(),
diff --git a/lib/kernel/src/erl_boot_server.erl b/lib/kernel/src/erl_boot_server.erl
index b4c5f5e27c..0d68d3e198 100644
--- a/lib/kernel/src/erl_boot_server.erl
+++ b/lib/kernel/src/erl_boot_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,7 +59,11 @@
-type ip4_address() :: {0..255,0..255,0..255,0..255}.
--spec start(Slaves :: [atom()]) -> {'ok', pid()} | {'error', any()}.
+-spec start(Slaves) -> {'ok', Pid} | {'error', What} when
+ Slaves :: [Host],
+ Host :: atom(),
+ Pid :: pid(),
+ What :: any().
start(Slaves) ->
case check_arg(Slaves) of
@@ -69,7 +73,11 @@ start(Slaves) ->
{error, {badarg, Slaves}}
end.
--spec start_link(Slaves :: [atom()]) -> {'ok', pid()} | {'error', any()}.
+-spec start_link(Slaves) -> {'ok', Pid} | {'error', What} when
+ Slaves :: [Host],
+ Host :: atom(),
+ Pid :: pid(),
+ What :: any().
start_link(Slaves) ->
case check_arg(Slaves) of
@@ -95,7 +103,10 @@ check_arg([], Result) ->
check_arg(_, _Result) ->
error.
--spec add_slave(Slave :: atom()) -> 'ok' | {'error', any()}.
+-spec add_slave(Slave) -> 'ok' | {'error', What} when
+ Slave :: Host,
+ Host :: atom(),
+ What :: any().
add_slave(Slave) ->
case inet:getaddr(Slave, inet) of
@@ -105,7 +116,10 @@ add_slave(Slave) ->
{error, {badarg, Slave}}
end.
--spec delete_slave(Slave :: atom()) -> 'ok' | {'error', any()}.
+-spec delete_slave(Slave) -> 'ok' | {'error', What} when
+ Slave :: Host,
+ Host :: atom(),
+ What :: any().
delete_slave(Slave) ->
case inet:getaddr(Slave, inet) of
@@ -131,7 +145,9 @@ add_subnet(Mask, Addr) when is_tuple(Mask), is_tuple(Addr) ->
delete_subnet(Mask, Addr) when is_tuple(Mask), is_tuple(Addr) ->
gen_server:call(boot_server, {delete, {Mask, Addr}}).
--spec which_slaves() -> [atom()].
+-spec which_slaves() -> Slaves when
+ Slaves :: [Host],
+ Host :: atom().
which_slaves() ->
gen_server:call(boot_server, which).
diff --git a/lib/kernel/src/erl_ddll.erl b/lib/kernel/src/erl_ddll.erl
index ce64589a29..646cac99c5 100644
--- a/lib/kernel/src/erl_ddll.erl
+++ b/lib/kernel/src/erl_ddll.erl
@@ -44,14 +44,18 @@ start() ->
stop() ->
ok.
--spec load_driver(Path :: path(), Driver :: driver()) ->
- 'ok' | {'error', any()}.
+-spec load_driver(Path, Name) -> 'ok' | {'error', ErrorDesc} when
+ Path :: path(),
+ Name :: driver(),
+ ErrorDesc :: term().
load_driver(Path, Driver) ->
do_load_driver(Path, Driver, [{driver_options,[kill_ports]}]).
--spec load(Path :: path(), Driver :: driver()) ->
- 'ok' | {'error', any()}.
+-spec load(Path, Name) -> 'ok' | {'error', ErrorDesc} when
+ Path :: path(),
+ Name :: driver(),
+ ErrorDesc ::term().
load(Path, Driver) ->
do_load_driver(Path, Driver, []).
@@ -100,30 +104,41 @@ do_unload_driver(Driver,Flags) ->
end
end.
--spec unload_driver(Driver :: driver()) -> 'ok' | {'error', any()}.
+-spec unload_driver(Name) -> 'ok' | {'error', ErrorDesc} when
+ Name :: driver(),
+ ErrorDesc :: term().
unload_driver(Driver) ->
do_unload_driver(Driver,[{monitor,pending_driver},kill_ports]).
--spec unload(Driver :: driver()) -> 'ok' | {'error', any()}.
+-spec unload(Name) -> 'ok' | {'error', ErrorDesc} when
+ Name :: driver(),
+ ErrorDesc :: term().
unload(Driver) ->
do_unload_driver(Driver,[]).
--spec reload(Path :: path(), Driver :: driver()) ->
- 'ok' | {'error', any()}.
+-spec reload(Path, Name) -> 'ok' | {'error', ErrorDesc} when
+ Path :: path(),
+ Name :: driver(),
+ ErrorDesc :: pending_process | OpaqueError,
+ OpaqueError :: term().
reload(Path,Driver) ->
do_load_driver(Path, Driver, [{reload,pending_driver}]).
--spec reload_driver(Path :: path(), Driver :: driver()) ->
- 'ok' | {'error', any()}.
+-spec reload_driver(Path, Name) -> 'ok' | {'error', ErrorDesc} when
+ Path :: path(),
+ Name :: driver(),
+ ErrorDesc :: pending_process | OpaqueError,
+ OpaqueError :: term().
reload_driver(Path,Driver) ->
do_load_driver(Path, Driver, [{reload,pending_driver},
{driver_options,[kill_ports]}]).
--spec format_error(Code :: atom()) -> string().
+-spec format_error(ErrorDesc) -> string() when
+ ErrorDesc :: term().
format_error(Code) ->
case Code of
@@ -135,7 +150,10 @@ format_error(Code) ->
erl_ddll:format_error_int(Code)
end.
--spec info(Driver :: driver()) -> [{atom(), any()}, ...].
+-spec info(Name) -> InfoList when
+ Name :: driver(),
+ InfoList :: [InfoItem, ...],
+ InfoItem :: {Tag :: atom(), Value :: term()}.
info(Driver) ->
[{processes, erl_ddll:info(Driver,processes)},
@@ -146,7 +164,12 @@ info(Driver) ->
{awaiting_load, erl_ddll:info(Driver,awaiting_load)},
{awaiting_unload, erl_ddll:info(Driver,awaiting_unload)}].
--spec info() -> [{string(), [{atom(), any()}]}].
+-spec info() -> AllInfoList when
+ AllInfoList :: [DriverInfo],
+ DriverInfo :: {DriverName, InfoList},
+ DriverName :: string(),
+ InfoList :: [InfoItem],
+ InfoItem :: {Tag :: atom(), Value :: term()}.
info() ->
{ok,DriverList} = erl_ddll:loaded_drivers(),
diff --git a/lib/kernel/src/error_handler.erl b/lib/kernel/src/error_handler.erl
index 6f69f4ccb9..a67b11a888 100644
--- a/lib/kernel/src/error_handler.erl
+++ b/lib/kernel/src/error_handler.erl
@@ -28,8 +28,11 @@
-export([undefined_function/3, undefined_lambda/3, stub_function/3,
breakpoint/3]).
--spec undefined_function(Module :: atom(), Function :: atom(), Args :: [_]) ->
- any().
+-spec undefined_function(Module, Function, Args) ->
+ any() when
+ Module :: atom(),
+ Function :: atom(),
+ Args :: list().
undefined_function(Module, Func, Args) ->
case ensure_loaded(Module) of
@@ -51,8 +54,10 @@ undefined_function(Module, Func, Args) ->
crash(Module, Func, Args)
end.
--spec undefined_lambda(Module :: atom(), Function :: fun(), Args :: [_]) ->
- any().
+-spec undefined_lambda(Module, Fun, Args) -> term() when
+ Module :: atom(),
+ Fun :: fun(),
+ Args :: list().
undefined_lambda(Module, Fun, Args) ->
case ensure_loaded(Module) of
@@ -83,12 +88,12 @@ int() -> int.
-spec crash(atom(), [term()]) -> no_return().
crash(Fun, Args) ->
- crash({Fun,Args}).
+ crash({Fun,Args,[]}).
-spec crash(atom(), atom(), arity()) -> no_return().
crash(M, F, A) ->
- crash({M,F,A}).
+ crash({M,F,A,[]}).
-spec crash(tuple()) -> no_return().
@@ -96,7 +101,8 @@ crash(Tuple) ->
try erlang:error(undef)
catch
error:undef ->
- erlang:raise(error, undef, [Tuple|tl(erlang:get_stacktrace())])
+ Stk = [Tuple|tl(erlang:get_stacktrace())],
+ erlang:raise(error, undef, Stk)
end.
%% If the code_server has not been started yet dynamic code loading
@@ -122,7 +128,7 @@ ensure_loaded(Module) ->
-spec stub_function(atom(), atom(), [_]) -> no_return().
stub_function(Mod, Func, Args) ->
- exit({undef,[{Mod,Func,Args}]}).
+ exit({undef,[{Mod,Func,Args,[]}]}).
check_inheritance(Module, Args) ->
Attrs = erlang:get_module_info(Module, attributes),
diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl
index cafdc52e84..f94cca000f 100644
--- a/lib/kernel/src/error_logger.erl
+++ b/lib/kernel/src/error_logger.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -69,17 +69,22 @@ start_link() ->
%% Used for simple messages; error or information.
%%-----------------------------------------------------------------
--spec error_msg(Format :: string()) -> 'ok'.
+-spec error_msg(Format) -> 'ok' when
+ Format :: string().
error_msg(Format) ->
error_msg(Format,[]).
--spec error_msg(Format :: string(), Args :: list()) -> 'ok'.
+-spec error_msg(Format, Data) -> 'ok' when
+ Format :: string(),
+ Data :: list().
error_msg(Format, Args) ->
notify({error, group_leader(), {self(), Format, Args}}).
--spec format(Format :: string(), Args :: list()) -> 'ok'.
+-spec format(Format, Data) -> 'ok' when
+ Format :: string(),
+ Data :: list().
format(Format, Args) ->
notify({error, group_leader(), {self(), Format, Args}}).
@@ -90,12 +95,18 @@ format(Format, Args) ->
%% The 'std_error' error_report type can always be used.
%%-----------------------------------------------------------------
--spec error_report(Report :: any()) -> 'ok'.
+-type report() ::
+ [{Tag :: term(), Data :: term()} | term()] | string() | term().
+
+-spec error_report(Report) -> 'ok' when
+ Report :: report().
error_report(Report) ->
error_report(std_error, Report).
--spec error_report(Type :: any(), Report :: any()) -> 'ok'.
+-spec error_report(Type, Report) -> 'ok' when
+ Type :: term(),
+ Report :: report().
error_report(Type, Report) ->
notify({error_report, group_leader(), {self(), Type, Report}}).
@@ -109,12 +120,15 @@ error_report(Type, Report) ->
%% mapped to std_info or std_error accordingly.
%%-----------------------------------------------------------------
--spec warning_report(Report :: any()) -> 'ok'.
+-spec warning_report(Report) -> 'ok' when
+ Report :: report().
warning_report(Report) ->
warning_report(std_warning, Report).
--spec warning_report(Type :: any(), Report :: any()) -> 'ok'.
+-spec warning_report(Type, Report) -> 'ok' when
+ Type :: any(),
+ Report :: report().
warning_report(Type, Report) ->
{Tag, NType} = case error_logger:warning_map() of
@@ -143,12 +157,15 @@ warning_report(Type, Report) ->
%% other types of reports.
%%-----------------------------------------------------------------
--spec warning_msg(Format :: string()) -> 'ok'.
+-spec warning_msg(Format) -> 'ok' when
+ Format :: string().
warning_msg(Format) ->
warning_msg(Format,[]).
--spec warning_msg(Format :: string(), Args :: list()) -> 'ok'.
+-spec warning_msg(Format, Data) -> 'ok' when
+ Format :: string(),
+ Data :: list().
warning_msg(Format, Args) ->
Tag = case error_logger:warning_map() of
@@ -167,12 +184,15 @@ warning_msg(Format, Args) ->
%% The 'std_info' info_report type can always be used.
%%-----------------------------------------------------------------
--spec info_report(Report :: any()) -> 'ok'.
+-spec info_report(Report) -> 'ok' when
+ Report :: report().
info_report(Report) ->
info_report(std_info, Report).
--spec info_report(Type :: any(), Report :: any()) -> 'ok'.
+-spec info_report(Type, Report) -> 'ok' when
+ Type :: any(),
+ Report :: report().
info_report(Type, Report) ->
notify({info_report, group_leader(), {self(), Type, Report}}).
@@ -182,12 +202,15 @@ info_report(Type, Report) ->
%% information messages.
%%-----------------------------------------------------------------
--spec info_msg(Format :: string()) -> 'ok'.
+-spec info_msg(Format) -> 'ok' when
+ Format :: string().
info_msg(Format) ->
info_msg(Format,[]).
--spec info_msg(Format :: string(), Args :: list()) -> 'ok'.
+-spec info_msg(Format, Data) -> 'ok' when
+ Format :: string(),
+ Data :: list().
info_msg(Format, Args) ->
notify({info_msg, group_leader(), {self(), Format, Args}}).
@@ -223,17 +246,23 @@ swap_handler(silent) ->
swap_handler(false) ->
ok. % keep primitive event handler as-is
--spec add_report_handler(Module :: atom()) -> any().
+-spec add_report_handler(Handler) -> any() when
+ Handler :: module().
add_report_handler(Module) when is_atom(Module) ->
gen_event:add_handler(error_logger, Module, []).
--spec add_report_handler(atom(), any()) -> any().
+-spec add_report_handler(Handler, Args) -> Result when
+ Handler :: module(),
+ Args :: gen_event:handler_args(),
+ Result :: gen_event:add_handler_ret().
add_report_handler(Module, Args) when is_atom(Module) ->
gen_event:add_handler(error_logger, Module, Args).
--spec delete_report_handler(Module :: atom()) -> any().
+-spec delete_report_handler(Handler) -> Result when
+ Handler :: module(),
+ Result :: gen_event:del_handler_ret().
delete_report_handler(Module) when is_atom(Module) ->
gen_event:delete_handler(error_logger, Module, []).
@@ -250,9 +279,16 @@ simple_logger() ->
%% Log all errors to File for all eternity
--spec logfile(Request :: {'open', string()}) -> 'ok' | {'error',any()}
- ; (Request :: 'close') -> 'ok' | {'error', any()}
- ; (Request :: 'filename') -> atom() | string() | {'error', any()}.
+-type open_error() :: file:posix() | badarg | system_limit.
+
+-spec logfile(Request :: {open, Filename}) -> ok | {error, OpenReason} when
+ Filename ::file:name(),
+ OpenReason :: allready_have_logfile | open_error()
+ ; (Request :: close) -> ok | {error, CloseReason} when
+ CloseReason :: module_not_found
+ ; (Request :: filename) -> Filename | {error, FilenameReason} when
+ Filename :: file:name(),
+ FilenameReason :: no_log_file.
logfile({open, File}) ->
case lists:member(error_logger_file_h,
@@ -280,7 +316,8 @@ logfile(filename) ->
%% Possibly turn off all tty printouts, maybe we only want the errors
%% to go to a file
--spec tty(Flag :: boolean()) -> 'ok'.
+-spec tty(Flag) -> 'ok' when
+ Flag :: boolean().
tty(true) ->
Hs = gen_event:which_handlers(error_logger),
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index 88bcf9a9cc..706c60caaf 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -79,15 +79,19 @@
-type file_info() :: #file_info{}.
-type fd() :: #file_descriptor{}.
-type io_device() :: pid() | fd().
--type location() :: integer() | {'bof', integer()} | {'cur', integer()}
- | {'eof', integer()} | 'bof' | 'cur' | 'eof'.
+-type location() :: integer() | {'bof', Offset :: integer()}
+ | {'cur', Offset :: integer()}
+ | {'eof', Offset :: integer()} | 'bof' | 'cur' | 'eof'.
-type mode() :: 'read' | 'write' | 'append'
| 'exclusive' | 'raw' | 'binary'
- | {'delayed_write', non_neg_integer(), non_neg_integer()}
- | 'delayed_write' | {'read_ahead', pos_integer()}
+ | {'delayed_write',
+ Size :: non_neg_integer(),
+ Delay :: non_neg_integer()}
+ | 'delayed_write' | {'read_ahead', Size :: pos_integer()}
| 'read_ahead' | 'compressed'
| {'encoding', unicode:encoding()}.
--type name() :: string() | atom() | [name()] | binary().
+-type deep_list() :: [char() | atom() | deep_list()].
+-type name() :: string() | atom() | deep_list() | (RawFilename :: binary()).
-type posix() :: 'eacces' | 'eagain' | 'ebadf' | 'ebusy' | 'edquot'
| 'eexist' | 'efault' | 'efbig' | 'eintr' | 'einval'
| 'eio' | 'eisdir' | 'eloop' | 'emfile' | 'emlink'
@@ -96,19 +100,17 @@
| 'enotblk' | 'enotdir' | 'enotsup' | 'enxio' | 'eperm'
| 'epipe' | 'erofs' | 'espipe' | 'esrch' | 'estale'
| 'exdev'.
--type bindings() :: any().
-
--type date() :: {pos_integer(), pos_integer(), pos_integer()}.
--type time() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}.
--type date_time() :: {date(), time()}.
+-type date_time() :: calendar:datetime().
-type posix_file_advise() :: 'normal' | 'sequential' | 'random'
| 'no_reuse' | 'will_need' | 'dont_need'.
%%%-----------------------------------------------------------------
%%% General functions
--spec format_error(Reason :: posix() | {integer(), atom(), any()}) ->
- string().
+-spec format_error(Reason) -> Chars when
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()},
+ Chars :: string().
format_error({_Line, ?MODULE, undefined_script}) ->
"no value returned from script";
@@ -129,7 +131,9 @@ format_error(terminated) ->
format_error(ErrorId) ->
erl_posix_msg:message(ErrorId).
--spec pid2name(Pid :: pid()) -> {'ok', filename()} | 'undefined'.
+-spec pid2name(Pid) -> {ok, Filename} | undefined when
+ Filename :: filename(),
+ Pid :: pid().
pid2name(Pid) when is_pid(Pid) ->
case whereis(?FILE_SERVER) of
@@ -148,42 +152,61 @@ pid2name(Pid) when is_pid(Pid) ->
%%% File server functions.
%%% Functions that do not operate on a single open file.
%%% Stateless.
--spec get_cwd() -> {'ok', filename()} | {'error', posix()}.
+-spec get_cwd() -> {ok, Dir} | {error, Reason} when
+ Dir :: filename(),
+ Reason :: posix().
get_cwd() ->
call(get_cwd, []).
--spec get_cwd(Drive :: string()) -> {'ok', filename()} | {'error', posix()}.
+-spec get_cwd(Drive) -> {ok, Dir} | {error, Reason} when
+ Drive :: string(),
+ Dir :: filename(),
+ Reason :: posix() | badarg.
get_cwd(Drive) ->
check_and_call(get_cwd, [file_name(Drive)]).
--spec set_cwd(Dirname :: name()) -> 'ok' | {'error', posix()}.
+-spec set_cwd(Dir) -> ok | {error, Reason} when
+ Dir :: name(),
+ Reason :: posix() | badarg.
set_cwd(Dirname) ->
check_and_call(set_cwd, [file_name(Dirname)]).
--spec delete(Name :: name()) -> 'ok' | {'error', posix()}.
+-spec delete(Filename) -> ok | {error, Reason} when
+ Filename :: name(),
+ Reason :: posix() | badarg.
delete(Name) ->
check_and_call(delete, [file_name(Name)]).
--spec rename(From :: name(), To :: name()) -> 'ok' | {'error', posix()}.
+-spec rename(Source, Destination) -> ok | {error, Reason} when
+ Source :: name(),
+ Destination :: name(),
+ Reason :: posix() | badarg.
rename(From, To) ->
check_and_call(rename, [file_name(From), file_name(To)]).
--spec make_dir(Name :: name()) -> 'ok' | {'error', posix()}.
+-spec make_dir(Dir) -> ok | {error, Reason} when
+ Dir :: name(),
+ Reason :: posix() | badarg.
make_dir(Name) ->
check_and_call(make_dir, [file_name(Name)]).
--spec del_dir(Name :: name()) -> 'ok' | {'error', posix()}.
+-spec del_dir(Dir) -> ok | {error, Reason} when
+ Dir :: name(),
+ Reason :: posix() | badarg.
del_dir(Name) ->
check_and_call(del_dir, [file_name(Name)]).
--spec read_file_info(Name :: name()) -> {'ok', file_info()} | {'error', posix()}.
+-spec read_file_info(Filename) -> {ok, FileInfo} | {error, Reason} when
+ Filename :: name(),
+ FileInfo :: file_info(),
+ Reason :: posix() | badarg.
read_file_info(Name) ->
check_and_call(read_file_info, [file_name(Name)]).
@@ -193,45 +216,66 @@ read_file_info(Name) ->
altname(Name) ->
check_and_call(altname, [file_name(Name)]).
--spec read_link_info(Name :: name()) -> {'ok', file_info()} | {'error', posix()}.
+-spec read_link_info(Name) -> {ok, FileInfo} | {error, Reason} when
+ Name :: name(),
+ FileInfo :: file_info(),
+ Reason :: posix() | badarg.
read_link_info(Name) ->
check_and_call(read_link_info, [file_name(Name)]).
--spec read_link(Name :: name()) -> {'ok', filename()} | {'error', posix()}.
+-spec read_link(Name) -> {ok, Filename} | {error, Reason} when
+ Name :: name(),
+ Filename :: filename(),
+ Reason :: posix() | badarg.
read_link(Name) ->
check_and_call(read_link, [file_name(Name)]).
--spec write_file_info(Name :: name(), Info :: file_info()) ->
- 'ok' | {'error', posix()}.
+-spec write_file_info(Filename, FileInfo) -> ok | {error, Reason} when
+ Filename :: name(),
+ FileInfo :: file_info(),
+ Reason :: posix() | badarg.
write_file_info(Name, Info = #file_info{}) ->
check_and_call(write_file_info, [file_name(Name), Info]).
--spec list_dir(Name :: name()) -> {'ok', [filename()]} | {'error', posix()}.
+-spec list_dir(Dir) -> {ok, Filenames} | {error, Reason} when
+ Dir :: name(),
+ Filenames :: [filename()],
+ Reason :: posix() | badarg.
list_dir(Name) ->
check_and_call(list_dir, [file_name(Name)]).
--spec read_file(Name :: name()) ->
- {'ok', binary()} | {'error', posix() | 'terminated' | 'system_limit'}.
+-spec read_file(Filename) -> {ok, Binary} | {error, Reason} when
+ Filename :: name(),
+ Binary :: binary(),
+ Reason :: posix() | badarg | terminated | system_limit.
read_file(Name) ->
check_and_call(read_file, [file_name(Name)]).
--spec make_link(Old :: name(), New :: name()) -> 'ok' | {'error', posix()}.
+-spec make_link(Existing, New) -> ok | {error, Reason} when
+ Existing :: name(),
+ New :: name(),
+ Reason :: posix() | badarg.
make_link(Old, New) ->
check_and_call(make_link, [file_name(Old), file_name(New)]).
--spec make_symlink(Old :: name(), New :: name()) -> 'ok' | {'error', posix()}.
+-spec make_symlink(Name1, Name2) -> ok | {error, Reason} when
+ Name1 :: name(),
+ Name2 :: name(),
+ Reason :: posix() | badarg.
make_symlink(Old, New) ->
check_and_call(make_symlink, [file_name(Old), file_name(New)]).
--spec write_file(Name :: name(), Bin :: iodata()) ->
- 'ok' | {'error', posix() | 'terminated' | 'system_limit'}.
+-spec write_file(Filename, Bytes) -> ok | {error, Reason} when
+ Filename :: name(),
+ Bytes :: iodata(),
+ Reason :: posix() | badarg | terminated | system_limit.
write_file(Name, Bin) ->
check_and_call(write_file, [file_name(Name), make_binary(Bin)]).
@@ -240,8 +284,11 @@ write_file(Name, Bin) ->
%% when it is time to change file server protocol again.
%% Meanwhile, it is implemented here, slightly less efficient.
--spec write_file(Name :: name(), Bin :: iodata(), Modes :: [mode()]) ->
- 'ok' | {'error', posix()}.
+-spec write_file(Filename, Bytes, Modes) -> ok | {error, Reason} when
+ Filename :: name(),
+ Bytes :: iodata(),
+ Modes :: [mode()],
+ Reason :: posix() | badarg | terminated | system_limit.
write_file(Name, Bin, ModeList) when is_list(ModeList) ->
case make_binary(Bin) of
@@ -295,8 +342,11 @@ raw_write_file_info(Name, #file_info{} = Info) ->
%% Contemporary mode specification - list of options
--spec open(Name :: name(), Modes :: [mode()]) ->
- {'ok', io_device()} | {'error', posix() | 'system_limit'}.
+-spec open(Filename, Modes) -> {ok, IoDevice} | {error, Reason} when
+ Filename :: name(),
+ Modes :: [mode()],
+ IoDevice :: io_device(),
+ Reason :: posix() | badarg | system_limit.
open(Item, ModeList) when is_list(ModeList) ->
case lists:member(raw, ModeList) of
@@ -349,7 +399,9 @@ open(Item, Mode) ->
%%% The File argument must be either a Pid or a handle
%%% returned from ?PRIM_FILE:open.
--spec close(File :: io_device()) -> 'ok' | {'error', posix() | 'terminated'}.
+-spec close(IoDevice) -> ok | {error, Reason} when
+ IoDevice :: io_device(),
+ Reason :: posix() | badarg | terminated.
close(File) when is_pid(File) ->
R = file_request(File, close),
@@ -367,9 +419,12 @@ close(#file_descriptor{module = Module} = Handle) ->
close(_) ->
{error, badarg}.
--spec advise(File :: io_device(), Offset :: integer(),
- Length :: integer(), Advise :: posix_file_advise()) ->
- 'ok' | {'error', posix()}.
+-spec advise(IoDevice, Offset, Length, Advise) -> ok | {error, Reason} when
+ IoDevice :: io_device(),
+ Offset :: integer(),
+ Length :: integer(),
+ Advise :: posix_file_advise(),
+ Reason :: posix() | badarg.
advise(File, Offset, Length, Advise) when is_pid(File) ->
R = file_request(File, {advise, Offset, Length, Advise}),
@@ -379,8 +434,11 @@ advise(#file_descriptor{module = Module} = Handle, Offset, Length, Advise) ->
advise(_, _, _, _) ->
{error, badarg}.
--spec read(File :: io_device() | atom(), Size :: non_neg_integer()) ->
- 'eof' | {'ok', [char()] | binary()} | {'error', posix()}.
+-spec read(IoDevice, Number) -> {ok, Data} | eof | {error, Reason} when
+ IoDevice :: io_device() | atom(),
+ Number :: non_neg_integer(),
+ Data :: string() | binary(),
+ Reason :: posix() | badarg | terminated.
read(File, Sz) when (is_pid(File) orelse is_atom(File)), is_integer(Sz), Sz >= 0 ->
case io:request(File, {get_chars, '', Sz}) of
@@ -395,8 +453,10 @@ read(#file_descriptor{module = Module} = Handle, Sz)
read(_, _) ->
{error, badarg}.
--spec read_line(File :: io_device() | atom()) ->
- 'eof' | {'ok', [char()] | binary()} | {'error', posix()}.
+-spec read_line(IoDevice) -> {ok, Data} | eof | {error, Reason} when
+ IoDevice :: io_device() | atom(),
+ Data :: string() | binary(),
+ Reason :: posix() | badarg | terminated.
read_line(File) when (is_pid(File) orelse is_atom(File)) ->
case io:request(File, {get_line, ''}) of
@@ -410,9 +470,12 @@ read_line(#file_descriptor{module = Module} = Handle) ->
read_line(_) ->
{error, badarg}.
--spec pread(File :: io_device(),
- LocationNumbers :: [{location(), non_neg_integer()}]) ->
- {'ok', [string() | binary() | 'eof']} | {'error', posix()}.
+-spec pread(IoDevice, LocNums) -> {ok, DataL} | eof | {error, Reason} when
+ IoDevice :: io_device(),
+ LocNums :: [{Location :: location(), Number :: non_neg_integer()}],
+ DataL :: [Data],
+ Data :: string() | binary() | eof,
+ Reason :: posix() | badarg | terminated.
pread(File, L) when is_pid(File), is_list(L) ->
pread_int(File, L, []);
@@ -435,10 +498,13 @@ pread_int(File, [{At, Sz} | T], R) when is_integer(Sz), Sz >= 0 ->
pread_int(_, _, _) ->
{error, badarg}.
--spec pread(File :: io_device(),
- Location :: location(),
- Size :: non_neg_integer()) ->
- 'eof' | {'ok', string() | binary()} | {'error', posix()}.
+-spec pread(IoDevice, Location, Number) ->
+ {ok, Data} | eof | {error, Reason} when
+ IoDevice :: io_device(),
+ Location :: location(),
+ Number :: non_neg_integer(),
+ Data :: string() | binary(),
+ Reason :: posix() | badarg | terminated.
pread(File, At, Sz) when is_pid(File), is_integer(Sz), Sz >= 0 ->
R = file_request(File, {pread, At, Sz}),
@@ -449,8 +515,10 @@ pread(#file_descriptor{module = Module} = Handle, Offs, Sz)
pread(_, _, _) ->
{error, badarg}.
--spec write(File :: io_device() | atom(), Byte :: iodata()) ->
- 'ok' | {'error', posix() | 'terminated'}.
+-spec write(IoDevice, Bytes) -> ok | {error, Reason} when
+ IoDevice :: io_device() | atom(),
+ Bytes :: iodata(),
+ Reason :: posix() | badarg | terminated.
write(File, Bytes) when (is_pid(File) orelse is_atom(File)) ->
case make_binary(Bytes) of
@@ -464,8 +532,11 @@ write(#file_descriptor{module = Module} = Handle, Bytes) ->
write(_, _) ->
{error, badarg}.
--spec pwrite(File :: io_device(), L :: [{location(), iodata()}]) ->
- 'ok' | {'error', {non_neg_integer(), posix()}}.
+-spec pwrite(IoDevice, LocBytes) -> ok | {error, {N, Reason}} when
+ IoDevice :: io_device(),
+ LocBytes :: [{Location :: location(), Bytes :: iodata()}],
+ N :: non_neg_integer(),
+ Reason :: posix() | badarg | terminated.
pwrite(File, L) when is_pid(File), is_list(L) ->
pwrite_int(File, L, 0);
@@ -486,10 +557,11 @@ pwrite_int(File, [{At, Bytes} | T], R) ->
pwrite_int(_, _, _) ->
{error, badarg}.
--spec pwrite(File :: io_device(),
- Location :: location(),
- Bytes :: iodata()) ->
- 'ok' | {'error', posix()}.
+-spec pwrite(IoDevice, Location, Bytes) -> ok | {error, Reason} when
+ IoDevice :: io_device(),
+ Location :: location(),
+ Bytes :: iodata(),
+ Reason :: posix() | badarg | terminated.
pwrite(File, At, Bytes) when is_pid(File) ->
R = file_request(File, {pwrite, At, Bytes}),
@@ -499,7 +571,9 @@ pwrite(#file_descriptor{module = Module} = Handle, Offs, Bytes) ->
pwrite(_, _, _) ->
{error, badarg}.
--spec datasync(File :: io_device()) -> 'ok' | {'error', posix()}.
+-spec datasync(IoDevice) -> ok | {error, Reason} when
+ IoDevice :: io_device(),
+ Reason :: posix() | badarg | terminated.
datasync(File) when is_pid(File) ->
R = file_request(File, datasync),
@@ -509,7 +583,9 @@ datasync(#file_descriptor{module = Module} = Handle) ->
datasync(_) ->
{error, badarg}.
--spec sync(File :: io_device()) -> 'ok' | {'error', posix()}.
+-spec sync(IoDevice) -> ok | {error, Reason} when
+ IoDevice :: io_device(),
+ Reason :: posix() | badarg | terminated.
sync(File) when is_pid(File) ->
R = file_request(File, sync),
@@ -519,8 +595,11 @@ sync(#file_descriptor{module = Module} = Handle) ->
sync(_) ->
{error, badarg}.
--spec position(File :: io_device(), Location :: location()) ->
- {'ok',integer()} | {'error', posix()}.
+-spec position(IoDevice, Location) -> {ok, NewPosition} | {error, Reason} when
+ IoDevice :: io_device(),
+ Location :: location(),
+ NewPosition :: integer(),
+ Reason :: posix() | badarg | terminated.
position(File, At) when is_pid(File) ->
R = file_request(File, {position,At}),
@@ -530,7 +609,9 @@ position(#file_descriptor{module = Module} = Handle, At) ->
position(_, _) ->
{error, badarg}.
--spec truncate(File :: io_device()) -> 'ok' | {'error', posix()}.
+-spec truncate(IoDevice) -> ok | {error, Reason} when
+ IoDevice :: io_device(),
+ Reason :: posix() | badarg | terminated.
truncate(File) when is_pid(File) ->
R = file_request(File, truncate),
@@ -540,17 +621,26 @@ truncate(#file_descriptor{module = Module} = Handle) ->
truncate(_) ->
{error, badarg}.
--spec copy(Source :: io_device() | name() | {name(), [mode()]},
- Destination :: io_device() | name() | {name(), [mode()]}) ->
- {'ok', non_neg_integer()} | {'error', posix()}.
+-spec copy(Source, Destination) -> {ok, BytesCopied} | {error, Reason} when
+ Source :: io_device() | Filename | {Filename, Modes},
+ Destination :: io_device() | Filename | {Filename, Modes},
+ Filename :: name(),
+ Modes :: [mode()],
+ BytesCopied :: non_neg_integer(),
+ Reason :: posix() | badarg | terminated.
copy(Source, Dest) ->
copy_int(Source, Dest, infinity).
--spec copy(Source :: io_device() | name() | {name(), [mode()]},
- Destination :: io_device() | name() | {name(), [mode()]},
- Length :: non_neg_integer() | 'infinity') ->
- {'ok', non_neg_integer()} | {'error', posix()}.
+-spec copy(Source, Destination, ByteCount) ->
+ {ok, BytesCopied} | {error, Reason} when
+ Source :: io_device() | Filename | {Filename, Modes},
+ Destination :: io_device() | Filename | {Filename, Modes},
+ Filename :: name(),
+ Modes :: [mode()],
+ ByteCount :: non_neg_integer() | infinity,
+ BytesCopied :: non_neg_integer(),
+ Reason :: posix() | badarg | terminated.
copy(Source, Dest, Length)
when is_integer(Length), Length >= 0;
@@ -772,8 +862,11 @@ ipread_s32bu_p32bu_2(File,
%%% The following functions, built upon the other interface functions,
%%% provide a higher-lever interface to files.
--spec consult(File :: name()) ->
- {'ok', list()} | {'error', posix() | {integer(), atom(), any()}}.
+-spec consult(Filename) -> {ok, Terms} | {error, Reason} when
+ Filename :: name(),
+ Terms :: [term()],
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
consult(File) ->
case open(File, [read]) of
@@ -785,8 +878,14 @@ consult(File) ->
Error
end.
--spec path_consult(Paths :: [name()], File :: name()) ->
- {'ok', list(), filename()} | {'error', posix() | {integer(), atom(), any()}}.
+-spec path_consult(Path, Filename) -> {ok, Terms, FullName} | {error, Reason} when
+ Path :: [Dir],
+ Dir :: name(),
+ Filename :: name(),
+ Terms :: [term()],
+ FullName :: filename(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
path_consult(Path, File) ->
case path_open(Path, File, [read]) of
@@ -803,13 +902,19 @@ path_consult(Path, File) ->
E2
end.
--spec eval(File :: name()) -> 'ok' | {'error', posix()}.
+-spec eval(Filename) -> ok | {error, Reason} when
+ Filename :: name(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
eval(File) ->
eval(File, erl_eval:new_bindings()).
--spec eval(File :: name(), Bindings :: bindings()) ->
- 'ok' | {'error', posix()}.
+-spec eval(Filename, Bindings) -> ok | {error, Reason} when
+ Filename :: name(),
+ Bindings :: erl_eval:binding_struct(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
eval(File, Bs) ->
case open(File, [read]) of
@@ -821,14 +926,24 @@ eval(File, Bs) ->
Error
end.
--spec path_eval(Paths :: [name()], File :: name()) ->
- {'ok', filename()} | {'error', posix() | {integer(), atom(), any()}}.
+-spec path_eval(Path, Filename) -> {ok, FullName} | {error, Reason} when
+ Path :: [Dir :: name()],
+ Filename :: name(),
+ FullName :: filename(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
path_eval(Path, File) ->
path_eval(Path, File, erl_eval:new_bindings()).
--spec path_eval(Paths :: [name()], File :: name(), Bindings :: bindings()) ->
- {'ok', filename()} | {'error', posix() | {integer(), atom(), any()}}.
+-spec path_eval(Path, Filename, Bindings) ->
+ {ok, FullName} | {error, Reason} when
+ Path :: [Dir :: name()],
+ Filename :: name(),
+ Bindings :: erl_eval:binding_struct(),
+ FullName :: filename(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
path_eval(Path, File, Bs) ->
case path_open(Path, File, [read]) of
@@ -845,14 +960,21 @@ path_eval(Path, File, Bs) ->
E2
end.
--spec script(File :: name()) ->
- {'ok', any()} | {'error', posix() | {integer(), atom(), any()}}.
+-spec script(Filename) -> {ok, Value} | {error, Reason} when
+ Filename :: name(),
+ Value :: term(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
script(File) ->
script(File, erl_eval:new_bindings()).
--spec script(File :: name(), Bindings :: bindings()) ->
- {'ok', any()} | {'error', posix() | {integer(), atom(), any()}}.
+-spec script(Filename, Bindings) -> {ok, Value} | {error, Reason} when
+ Filename :: name(),
+ Bindings :: erl_eval:binding_struct(),
+ Value :: term(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
script(File, Bs) ->
case open(File, [read]) of
@@ -864,16 +986,27 @@ script(File, Bs) ->
Error
end.
--spec path_script/2 :: (Paths :: [name()], File :: name()) ->
- {'ok', term(), filename()} | {'error', posix() | {integer(), atom(), _}}.
+-spec path_script(Path, Filename) ->
+ {ok, Value, FullName} | {error, Reason} when
+ Path :: [Dir :: name()],
+ Filename :: name(),
+ Value :: term(),
+ FullName :: filename(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
path_script(Path, File) ->
path_script(Path, File, erl_eval:new_bindings()).
--spec path_script(Paths :: [name()],
- File :: name(),
- Bindings :: bindings()) ->
- {'ok', term(), filename()} | {'error', posix() | {integer(), atom(), _}}.
+-spec path_script(Path, Filename, Bindings) ->
+ {ok, Value, FullName} | {error, Reason} when
+ Path :: [Dir :: name()],
+ Filename :: name(),
+ Bindings :: erl_eval:binding_struct(),
+ Value :: term(),
+ FullName :: filename(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
path_script(Path, File, Bs) ->
case path_open(Path, File, [read]) of
@@ -898,8 +1031,14 @@ path_script(Path, File, Bs) ->
%% Searches the Paths for file Filename which can be opened with Mode.
%% The path list is ignored if Filename contains an absolute path.
--spec path_open(Paths :: [name()], Name :: name(), Modes :: [mode()]) ->
- {'ok', io_device(), filename()} | {'error', posix()}.
+-spec path_open(Path, Filename, Modes) ->
+ {ok, IoDevice, FullName} | {error, Reason} when
+ Path :: [Dir :: name()],
+ Filename :: name(),
+ Modes :: [mode()],
+ IoDevice :: io_device(),
+ FullName :: filename(),
+ Reason :: posix() | badarg | system_limit.
path_open(PathList, Name, Mode) ->
case file_name(Name) of
@@ -919,47 +1058,57 @@ path_open(PathList, Name, Mode) ->
end
end.
--spec change_mode(Name :: name(), Mode :: integer()) ->
- 'ok' | {'error', posix()}.
+-spec change_mode(Filename, Mode) -> ok | {error, Reason} when
+ Filename :: name(),
+ Mode :: integer(),
+ Reason :: posix() | badarg.
change_mode(Name, Mode)
when is_integer(Mode) ->
write_file_info(Name, #file_info{mode=Mode}).
--spec change_owner(Name :: name(), OwnerId :: integer()) ->
- 'ok' | {'error', posix()}.
+-spec change_owner(Filename, Uid) -> ok | {error, Reason} when
+ Filename :: name(),
+ Uid :: integer(),
+ Reason :: posix() | badarg.
change_owner(Name, OwnerId)
when is_integer(OwnerId) ->
write_file_info(Name, #file_info{uid=OwnerId}).
--spec change_owner(Name :: name(),
- OwnerId :: integer(),
- GroupId :: integer()) ->
- 'ok' | {'error', posix()}.
+-spec change_owner(Filename, Uid, Gid) -> ok | {error, Reason} when
+ Filename :: name(),
+ Uid :: integer(),
+ Gid :: integer(),
+ Reason :: posix() | badarg.
change_owner(Name, OwnerId, GroupId)
when is_integer(OwnerId), is_integer(GroupId) ->
write_file_info(Name, #file_info{uid=OwnerId, gid=GroupId}).
--spec change_group(Name :: name(), GroupId :: integer()) ->
- 'ok' | {'error', posix()}.
+-spec change_group(Filename, Gid) -> ok | {error, Reason} when
+ Filename :: name(),
+ Gid :: integer(),
+ Reason :: posix() | badarg.
change_group(Name, GroupId)
when is_integer(GroupId) ->
write_file_info(Name, #file_info{gid=GroupId}).
--spec change_time(Name :: name(), Time :: date_time()) ->
- 'ok' | {'error', posix()}.
+-spec change_time(Filename, Mtime) -> ok | {error, Reason} when
+ Filename :: name(),
+ Mtime :: date_time(),
+ Reason :: posix() | badarg.
change_time(Name, Time)
when is_tuple(Time) ->
write_file_info(Name, #file_info{mtime=Time}).
--spec change_time(Name :: name(),
- ATime :: date_time(),
- MTime :: date_time()) ->
- 'ok' | {'error', posix()}.
+-spec change_time(Filename, Atime, Mtime) -> ok | {error, Reason} when
+ Filename :: name(),
+ Atime :: date_time(),
+ Mtime :: date_time(),
+ Reason :: posix() | badarg.
change_time(Name, Atime, Mtime)
when is_tuple(Atime), is_tuple(Mtime) ->
@@ -1014,7 +1163,7 @@ path_open_first([Path|Rest], Name, Mode, LastError) ->
{error, _} = Error ->
Error;
FilePath ->
- FileName = filename:join(FilePath, Name),
+ FileName = fname_join(FilePath, Name),
case open(FileName, Mode) of
{ok, Fd} ->
{ok, Fd, FileName};
@@ -1027,6 +1176,11 @@ path_open_first([Path|Rest], Name, Mode, LastError) ->
path_open_first([], _Name, _Mode, LastError) ->
{error, LastError}.
+fname_join(".", Name) ->
+ Name;
+fname_join(Dir, Name) ->
+ filename:join(Dir, Name).
+
%%%-----------------------------------------------------------------
%%% Utility functions.
diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl
index cccfa75005..6cebb7ab97 100644
--- a/lib/kernel/src/gen_sctp.erl
+++ b/lib/kernel/src/gen_sctp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The 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,11 +33,87 @@
-export([error_string/1]).
-export([controlling_process/2]).
-
+-type assoc_id() :: term().
+-type option() ::
+ {active, true | false | once} |
+ {buffer, non_neg_integer()} |
+ {dontroute, boolean()} |
+ {linger, {boolean(), non_neg_integer()}} |
+ {mode, list | binary} | list | binary |
+ {priority, non_neg_integer()} |
+ {recbuf, non_neg_integer()} |
+ {reuseaddr, boolean()} |
+ {sctp_adaptation_layer, #sctp_setadaptation{}} |
+ {sctp_associnfo, #sctp_assocparams{}} |
+ {sctp_autoclose, non_neg_integer()} |
+ {sctp_default_send_param, #sctp_sndrcvinfo{}} |
+ {sctp_delayed_ack_time, #sctp_assoc_value{}} |
+ {sctp_disable_fragments, boolean()} |
+ {sctp_events, #sctp_event_subscribe{}} |
+ {sctp_get_peer_addr_info, #sctp_paddrinfo{}} |
+ {sctp_i_want_mapped_v4_addr, boolean()} |
+ {sctp_initmsg, #sctp_initmsg{}} |
+ {sctp_maxseg, non_neg_integer()} |
+ {sctp_nodelay, boolean()} |
+ {sctp_peer_addr_params, #sctp_paddrparams{}} |
+ {sctp_primary_addr, #sctp_prim{}} |
+ {sctp_rtoinfo, #sctp_rtoinfo{}} |
+ {sctp_set_peer_primary_addr, #sctp_setpeerprim{}} |
+ {sctp_status, #sctp_status{}} |
+ {sndbuf, non_neg_integer()} |
+ {tos, non_neg_integer()}.
+-type option_name() ::
+ active |
+ buffer |
+ dontroute |
+ linger |
+ mode |
+ priority |
+ recbuf |
+ reuseaddr |
+ sctp_adaptation_layer |
+ sctp_associnfo |
+ sctp_autoclose |
+ sctp_default_send_param |
+ sctp_delayed_ack_time |
+ sctp_disable_fragments |
+ sctp_events |
+ sctp_get_peer_addr_info |
+ sctp_i_want_mapped_v4_addr |
+ sctp_initmsg |
+ sctp_maxseg |
+ sctp_nodelay |
+ sctp_peer_addr_params |
+ sctp_primary_addr |
+ sctp_rtoinfo |
+ sctp_set_peer_primary_addr |
+ sctp_status |
+ sndbuf |
+ tos.
+-type sctp_socket() :: port().
+
+-export_type([assoc_id/0, option/0, option_name/0, sctp_socket/0]).
+
+-spec open() -> {ok, Socket} | {error, inet:posix()} when
+ Socket :: sctp_socket().
open() ->
open([]).
+-spec open(Port) -> {ok, Socket} | {error, inet:posix()} when
+ Port :: inet:port_number(),
+ Socket :: sctp_socket();
+ (Opts) -> {ok, Socket} | {error, inet:posix()} when
+ Opts :: [Opt],
+ Opt :: {ip,IP}
+ | {ifaddr,IP}
+ | inet:address_family()
+ | {port,Port}
+ | option(),
+ IP :: inet:ip_address() | any | loopback,
+ Port :: inet:port_number(),
+ Socket :: sctp_socket().
+
open(Opts) when is_list(Opts) ->
Mod = mod(Opts, undefined),
case Mod:open(Opts) of
@@ -52,11 +128,25 @@ open(Port) when is_integer(Port) ->
open(X) ->
erlang:error(badarg, [X]).
+-spec open(Port, Opts) -> {ok, Socket} | {error, inet:posix()} when
+ Opts :: [Opt],
+ Opt :: {ip,IP}
+ | {ifaddr,IP}
+ | inet:address_family()
+ | {port,Port}
+ | option(),
+ IP :: inet:ip_address() | any | loopback,
+ Port :: inet:port_number(),
+ Socket :: sctp_socket().
+
open(Port, Opts) when is_integer(Port), is_list(Opts) ->
open([{port,Port}|Opts]);
open(Port, Opts) ->
erlang:error(badarg, [Port,Opts]).
+-spec close(Socket) -> ok | {error, inet:posix()} when
+ Socket :: sctp_socket().
+
close(S) when is_port(S) ->
case inet_db:lookup_socket(S) of
{ok,Mod} ->
@@ -68,6 +158,11 @@ close(S) ->
+-spec listen(Socket, IsServer) -> ok | {error, Reason} when
+ Socket :: sctp_socket(),
+ IsServer :: boolean(),
+ Reason :: term().
+
listen(S, Flag) when is_port(S), is_boolean(Flag) ->
case inet_db:lookup_socket(S) of
{ok,Mod} ->
@@ -77,9 +172,25 @@ listen(S, Flag) when is_port(S), is_boolean(Flag) ->
listen(S, Flag) ->
erlang:error(badarg, [S,Flag]).
+-spec connect(Socket, Addr, Port, Opts) -> {ok, Assoc} | {error, inet:posix()} when
+ Socket :: sctp_socket(),
+ Addr :: inet:ip_address() | inet:hostname(),
+ Port :: inet:port_number(),
+ Opts :: [Opt :: option()],
+ Assoc :: #sctp_assoc_change{}.
+
connect(S, Addr, Port, Opts) ->
connect(S, Addr, Port, Opts, infinity).
+-spec connect(Socket, Addr, Port, Opts, Timeout) ->
+ {ok, Assoc} | {error, inet:posix()} when
+ Socket :: sctp_socket(),
+ Addr :: inet:ip_address() | inet:hostname(),
+ Port :: inet:port_number(),
+ Opts :: [Opt :: option()],
+ Timeout :: timeout(),
+ Assoc :: #sctp_assoc_change{}.
+
connect(S, Addr, Port, Opts, Timeout) ->
case do_connect(S, Addr, Port, Opts, Timeout, true) of
badarg ->
@@ -88,9 +199,24 @@ connect(S, Addr, Port, Opts, Timeout) ->
Result
end.
+-spec connect_init(Socket, Addr, Port, Opts) ->
+ ok | {error, inet:posix()} when
+ Socket :: sctp_socket(),
+ Addr :: inet:ip_address() | inet:hostname(),
+ Port :: inet:port_number(),
+ Opts :: [option()].
+
connect_init(S, Addr, Port, Opts) ->
connect_init(S, Addr, Port, Opts, infinity).
+-spec connect_init(Socket, Addr, Port, Opts, Timeout) ->
+ ok | {error, inet:posix()} when
+ Socket :: sctp_socket(),
+ Addr :: inet:ip_address() | inet:hostname(),
+ Port :: inet:port_number(),
+ Opts :: [option()],
+ Timeout :: timeout().
+
connect_init(S, Addr, Port, Opts, Timeout) ->
case do_connect(S, Addr, Port, Opts, Timeout, false) of
badarg ->
@@ -130,12 +256,20 @@ do_connect(_S, _Addr, _Port, _Opts, _Timeout, _ConnWait) ->
badarg.
+-spec eof(Socket, Assoc) -> ok | {error, Reason} when
+ Socket :: sctp_socket(),
+ Assoc :: #sctp_assoc_change{},
+ Reason :: term().
eof(S, #sctp_assoc_change{assoc_id=AssocId}) when is_port(S) ->
eof_or_abort(S, AssocId, eof);
eof(S, Assoc) ->
erlang:error(badarg, [S,Assoc]).
+-spec abort(Socket, Assoc) -> ok | {error, inet:posix()} when
+ Socket :: sctp_socket(),
+ Assoc :: #sctp_assoc_change{}.
+
abort(S, #sctp_assoc_change{assoc_id=AssocId}) when is_port(S) ->
eof_or_abort(S, AssocId, abort);
abort(S, Assoc) ->
@@ -151,6 +285,11 @@ eof_or_abort(S, AssocId, Action) ->
end.
+-spec send(Socket, SndRcvInfo, Data) -> ok | {error, Reason} when
+ Socket :: sctp_socket(),
+ SndRcvInfo :: #sctp_sndrcvinfo{},
+ Data :: binary | iolist(),
+ Reason :: term().
%% Full-featured send. Rarely needed.
send(S, #sctp_sndrcvinfo{}=SRI, Data) when is_port(S) ->
@@ -162,6 +301,13 @@ send(S, #sctp_sndrcvinfo{}=SRI, Data) when is_port(S) ->
send(S, SRI, Data) ->
erlang:error(badarg, [S,SRI,Data]).
+-spec send(Socket, Assoc, Stream, Data) -> ok | {error, Reason} when
+ Socket :: sctp_socket(),
+ Assoc :: #sctp_assoc_change{} | assoc_id(),
+ Stream :: integer(),
+ Data :: binary | iolist(),
+ Reason :: term().
+
send(S, #sctp_assoc_change{assoc_id=AssocId}, Stream, Data)
when is_port(S), is_integer(Stream) ->
case inet_db:lookup_socket(S) of
@@ -179,9 +325,36 @@ send(S, AssocId, Stream, Data)
send(S, AssocChange, Stream, Data) ->
erlang:error(badarg, [S,AssocChange,Stream,Data]).
+-spec recv(Socket) -> {ok, {FromIP, FromPort, AncData, Data}}
+ | {error, Reason} when
+ Socket :: sctp_socket(),
+ FromIP :: inet:ip_address(),
+ FromPort :: inet:port_number(),
+ AncData :: [#sctp_sndrcvinfo{}],
+ Data :: binary() | string() | #sctp_sndrcvinfo{}
+ | #sctp_assoc_change{} | #sctp_paddr_change{}
+ | #sctp_adaptation_event{},
+ Reason :: inet:posix() | #sctp_send_failed{} | #sctp_paddr_change{}
+ | #sctp_pdapi_event{} | #sctp_remote_error{}
+ | #sctp_shutdown_event{}.
+
recv(S) ->
recv(S, infinity).
+-spec recv(Socket, Timeout) -> {ok, {FromIP, FromPort, AncData, Data}}
+ | {error, Reason} when
+ Socket :: sctp_socket(),
+ Timeout :: timeout(),
+ FromIP :: inet:ip_address(),
+ FromPort :: inet:port_number(),
+ AncData :: [#sctp_sndrcvinfo{}],
+ Data :: binary() | string() | #sctp_sndrcvinfo{}
+ | #sctp_assoc_change{} | #sctp_paddr_change{}
+ | #sctp_adaptation_event{},
+ Reason :: inet:posix() | #sctp_send_failed{} | #sctp_paddr_change{}
+ | #sctp_pdapi_event{} | #sctp_remote_error{}
+ | #sctp_shutdown_event{}.
+
recv(S, Timeout) when is_port(S) ->
case inet_db:lookup_socket(S) of
{ok,Mod} ->
@@ -192,6 +365,8 @@ recv(S, Timeout) ->
erlang:error(badarg, [S,Timeout]).
+-spec error_string(ErrorNumber) -> ok | string() | unknown_error when
+ ErrorNumber :: integer().
error_string(0) ->
ok;
@@ -224,6 +399,9 @@ error_string(X) ->
erlang:error(badarg, [X]).
+-spec controlling_process(Socket, Pid) -> ok when
+ Socket :: sctp_socket(),
+ Pid :: pid().
controlling_process(S, Pid) when is_port(S), is_pid(Pid) ->
inet:udp_controlling_process(S, Pid);
diff --git a/lib/kernel/src/gen_tcp.erl b/lib/kernel/src/gen_tcp.erl
index 16a87d71b6..8ab18c01b4 100644
--- a/lib/kernel/src/gen_tcp.erl
+++ b/lib/kernel/src/gen_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The 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,12 +28,109 @@
-include("inet_int.hrl").
+-type option() ::
+ {active, true | false | once} |
+ {bit8, clear | set | on | off} |
+ {buffer, non_neg_integer()} |
+ {delay_send, boolean()} |
+ {deliver, port | term} |
+ {dontroute, boolean()} |
+ {exit_on_close, boolean()} |
+ {header, non_neg_integer()} |
+ {high_watermark, non_neg_integer()} |
+ {keepalive, boolean()} |
+ {linger, {boolean(), non_neg_integer()}} |
+ {low_watermark, non_neg_integer()} |
+ {mode, list | binary} | list | binary |
+ {nodelay, boolean()} |
+ {packet,
+ 0 | 1 | 2 | 4 | raw | sunrm | asn1 |
+ cdr | fcgi | line | tpkt | http | httph | http_bin | httph_bin } |
+ {packet_size, non_neg_integer()} |
+ {priority, non_neg_integer()} |
+ {raw,
+ Protocol :: non_neg_integer(),
+ OptionNum :: non_neg_integer(),
+ ValueBin :: binary()} |
+ {recbuf, non_neg_integer()} |
+ {reuseaddr, boolean()} |
+ {send_timeout, non_neg_integer() | infinity} |
+ {send_timeout_close, boolean()} |
+ {sndbuf, non_neg_integer()} |
+ {tos, non_neg_integer()}.
+-type option_name() ::
+ active |
+ bit8 |
+ buffer |
+ delay_send |
+ deliver |
+ dontroute |
+ exit_on_close |
+ header |
+ high_watermark |
+ keepalive |
+ linger |
+ low_watermark |
+ mode |
+ nodelay |
+ packet |
+ packet_size |
+ priority |
+ {raw,
+ Protocol :: non_neg_integer(),
+ OptionNum :: non_neg_integer(),
+ ValueSpec :: (ValueSize :: non_neg_integer()) |
+ (ValueBin :: binary())} |
+ recbuf |
+ reuseaddr |
+ send_timeout |
+ send_timeout_close |
+ sndbuf |
+ tos.
+-type connect_option() ::
+ {ip, inet:ip_address()} |
+ {fd, Fd :: non_neg_integer()} |
+ {ifaddr, inet:ip_address()} |
+ inet:address_family() |
+ {port, inet:port_number()} |
+ {tcp_module, module()} |
+ option().
+-type listen_option() ::
+ {ip, inet:ip_address()} |
+ {fd, Fd :: non_neg_integer()} |
+ {ifaddr, inet:ip_address()} |
+ inet:address_family() |
+ {port, inet:port_number()} |
+ {backlog, B :: non_neg_integer()} |
+ {tcp_module, module()} |
+ option().
+-type socket() :: port().
+
+-export_type([option/0, option_name/0, connect_option/0, listen_option/0]).
+
%%
%% Connect a socket
%%
+
+-spec connect(Address, Port, Options) -> {ok, Socket} | {error, Reason} when
+ Address :: inet:ip_address() | inet:hostname(),
+ Port :: inet:port_number(),
+ Options :: [connect_option()],
+ Socket :: socket(),
+ Reason :: inet:posix().
+
connect(Address, Port, Opts) ->
connect(Address,Port,Opts,infinity).
+-spec connect(Address, Port, Options, Timeout) ->
+ {ok, Socket} | {error, Reason} when
+ Address :: inet:ip_address() | inet:hostname(),
+ Port :: inet:port_number(),
+ Options :: [connect_option()],
+ Timeout :: timeout(),
+ Socket :: socket(),
+ Reason :: inet:posix().
+
connect(Address, Port, Opts, Time) ->
Timer = inet:start_timer(Time),
Res = (catch connect1(Address,Port,Opts,Timer)),
@@ -72,6 +169,13 @@ try_connect([], _Port, _Opts, _Timer, _Mod, Err) ->
%%
%% Listen on a tcp port
%%
+
+-spec listen(Port, Options) -> {ok, ListenSocket} | {error, Reason} when
+ Port :: inet:port_number(),
+ Options :: [listen_option()],
+ ListenSocket :: socket(),
+ Reason :: inet:posix().
+
listen(Port, Opts) ->
Mod = mod(Opts, undefined),
case Mod:getserv(Port) of
@@ -85,6 +189,12 @@ listen(Port, Opts) ->
%%
%% Generic tcp accept
%%
+
+-spec accept(ListenSocket) -> {ok, Socket} | {error, Reason} when
+ ListenSocket :: socket(),
+ Socket :: socket(),
+ Reason :: closed | timeout | inet:posix().
+
accept(S) ->
case inet_db:lookup_socket(S) of
{ok, Mod} ->
@@ -93,6 +203,12 @@ accept(S) ->
Error
end.
+-spec accept(ListenSocket, Timeout) -> {ok, Socket} | {error, Reason} when
+ ListenSocket :: socket(),
+ Timeout :: timeout(),
+ Socket :: socket(),
+ Reason :: closed | timeout | inet:posix().
+
accept(S, Time) when is_port(S) ->
case inet_db:lookup_socket(S) of
{ok, Mod} ->
@@ -104,6 +220,12 @@ accept(S, Time) when is_port(S) ->
%%
%% Generic tcp shutdown
%%
+
+-spec shutdown(Socket, How) -> ok | {error, Reason} when
+ Socket :: socket(),
+ How :: read | write | read_write,
+ Reason :: inet:posix().
+
shutdown(S, How) when is_port(S) ->
case inet_db:lookup_socket(S) of
{ok, Mod} ->
@@ -115,12 +237,22 @@ shutdown(S, How) when is_port(S) ->
%%
%% Close
%%
+
+-spec close(Socket) -> ok when
+ Socket :: socket().
+
close(S) ->
inet:tcp_close(S).
%%
%% Send
%%
+
+-spec send(Socket, Packet) -> ok | {error, Reason} when
+ Socket :: socket(),
+ Packet :: iodata(),
+ Reason :: inet:posix().
+
send(S, Packet) when is_port(S) ->
case inet_db:lookup_socket(S) of
{ok, Mod} ->
@@ -132,6 +264,14 @@ send(S, Packet) when is_port(S) ->
%%
%% Receive data from a socket (passive mode)
%%
+
+-spec recv(Socket, Length) -> {ok, Packet} | {error, Reason} when
+ Socket :: socket(),
+ Length :: non_neg_integer(),
+ Packet :: string() | binary() | HttpPacket,
+ Reason :: closed | inet:posix(),
+ HttpPacket :: term().
+
recv(S, Length) when is_port(S) ->
case inet_db:lookup_socket(S) of
{ok, Mod} ->
@@ -140,6 +280,14 @@ recv(S, Length) when is_port(S) ->
Error
end.
+-spec recv(Socket, Length, Timeout) -> {ok, Packet} | {error, Reason} when
+ Socket :: socket(),
+ Length :: non_neg_integer(),
+ Timeout :: timeout(),
+ Packet :: string() | binary() | HttpPacket,
+ Reason :: closed | inet:posix(),
+ HttpPacket :: term().
+
recv(S, Length, Time) when is_port(S) ->
case inet_db:lookup_socket(S) of
{ok, Mod} ->
@@ -159,6 +307,12 @@ unrecv(S, Data) when is_port(S) ->
%%
%% Set controlling process
%%
+
+-spec controlling_process(Socket, Pid) -> ok | {error, Reason} when
+ Socket :: socket(),
+ Pid :: pid(),
+ Reason :: closed | not_owner | inet:posix().
+
controlling_process(S, NewOwner) ->
case inet_db:lookup_socket(S) of
{ok, _Mod} -> % Just check that this is an open socket
diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl
index 99020c7b6c..8688799ae9 100644
--- a/lib/kernel/src/gen_udp.erl
+++ b/lib/kernel/src/gen_udp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The 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,17 +25,93 @@
-include("inet_int.hrl").
+-type option() ::
+ {active, true | false | once} |
+ {add_membership, {inet:ip_address(), inet:ip_address()}} |
+ {broadcast, boolean()} |
+ {buffer, non_neg_integer()} |
+ {deliver, port | term} |
+ {dontroute, boolean()} |
+ {drop_membership, {inet:ip_address(), inet:ip_address()}} |
+ {header, non_neg_integer()} |
+ {mode, list | binary} | list | binary |
+ {multicast_if, inet:ip_address()} |
+ {multicast_loop, boolean()} |
+ {multicast_ttl, non_neg_integer()} |
+ {priority, non_neg_integer()} |
+ {raw,
+ Protocol :: non_neg_integer(),
+ OptionNum :: non_neg_integer(),
+ ValueBin :: binary()} |
+ {read_packets, non_neg_integer()} |
+ {recbuf, non_neg_integer()} |
+ {reuseaddr, boolean()} |
+ {sndbuf, non_neg_integer()} |
+ {tos, non_neg_integer()}.
+-type option_name() ::
+ active |
+ broadcast |
+ buffer |
+ deliver |
+ dontroute |
+ header |
+ mode |
+ multicast_if |
+ multicast_loop |
+ multicast_ttl |
+ priority |
+ {raw,
+ Protocol :: non_neg_integer(),
+ OptionNum :: non_neg_integer(),
+ ValueSpec :: (ValueSize :: non_neg_integer()) |
+ (ValueBin :: binary())} |
+ read_packets |
+ recbuf |
+ reuseaddr |
+ sndbuf |
+ tos.
+-type socket() :: port().
+
+-export_type([option/0, option_name/0]).
+
+-spec open(Port) -> {ok, Socket} | {error, Reason} when
+ Port :: inet:port_number(),
+ Socket :: socket(),
+ Reason :: inet:posix().
+
open(Port) ->
open(Port, []).
+-spec open(Port, Opts) -> {ok, Socket} | {error, Reason} when
+ Port :: inet:port_number(),
+ Opts :: [Option],
+ Option :: {ip, inet:ip_address()}
+ | {fd, non_neg_integer()}
+ | {ifaddr, inet:ip_address()}
+ | inet:address_family()
+ | {port, inet:port_number()}
+ | option(),
+ Socket :: socket(),
+ Reason :: inet:posix().
+
open(Port, Opts) ->
Mod = mod(Opts, undefined),
{ok,UP} = Mod:getserv(Port),
Mod:open(UP, Opts).
+-spec close(Socket) -> ok when
+ Socket :: socket().
+
close(S) ->
inet:udp_close(S).
+-spec send(Socket, Address, Port, Packet) -> ok | {error, Reason} when
+ Socket :: socket(),
+ Address :: inet:ip_address() | inet:hostname(),
+ Port :: inet:port_number(),
+ Packet :: iodata(),
+ Reason :: not_owner | inet:posix().
+
send(S, Address, Port, Packet) when is_port(S) ->
case inet_db:lookup_socket(S) of
{ok, Mod} ->
@@ -61,6 +137,15 @@ send(S, Packet) when is_port(S) ->
Error
end.
+-spec recv(Socket, Length) ->
+ {ok, {Address, Port, Packet}} | {error, Reason} when
+ Socket :: socket(),
+ Length :: non_neg_integer(),
+ Address :: inet:ip_address(),
+ Port :: inet:port_number(),
+ Packet :: string() | binary(),
+ Reason :: not_owner | inet:posix().
+
recv(S,Len) when is_port(S), is_integer(Len) ->
case inet_db:lookup_socket(S) of
{ok, Mod} ->
@@ -69,6 +154,16 @@ recv(S,Len) when is_port(S), is_integer(Len) ->
Error
end.
+-spec recv(Socket, Length, Timeout) ->
+ {ok, {Address, Port, Packet}} | {error, Reason} when
+ Socket :: socket(),
+ Length :: non_neg_integer(),
+ Timeout :: timeout(),
+ Address :: inet:ip_address(),
+ Port :: inet:port_number(),
+ Packet :: string() | binary(),
+ Reason :: not_owner | inet:posix().
+
recv(S,Len,Time) when is_port(S) ->
case inet_db:lookup_socket(S) of
{ok, Mod} ->
@@ -90,6 +185,10 @@ connect(S, Address, Port) when is_port(S) ->
Error
end.
+-spec controlling_process(Socket, Pid) -> ok when
+ Socket :: socket(),
+ Pid :: pid().
+
controlling_process(S, NewOwner) ->
inet:udp_controlling_process(S, NewOwner).
diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl
index 6343acd000..7d15f8bf83 100644
--- a/lib/kernel/src/global.erl
+++ b/lib/kernel/src/global.erl
@@ -166,7 +166,7 @@ start_link() ->
stop() ->
gen_server:call(global_name_server, stop, infinity).
--spec sync() -> 'ok' | {'error', term()}.
+-spec sync() -> 'ok' | {'error', Reason :: term()}.
sync() ->
case check_sync_nodes() of
{error, _} = Error ->
@@ -175,7 +175,7 @@ sync() ->
gen_server:call(global_name_server, {sync, SyncNodes}, infinity)
end.
--spec sync([node()]) -> 'ok' | {'error', term()}.
+-spec sync([node()]) -> 'ok' | {'error', Reason :: term()}.
sync(Nodes) ->
case check_sync_nodes(Nodes) of
{error, _} = Error ->
@@ -184,7 +184,10 @@ sync(Nodes) ->
gen_server:call(global_name_server, {sync, SyncNodes}, infinity)
end.
--spec send(term(), term()) -> pid().
+-spec send(Name, Msg) -> Pid when
+ Name :: term(),
+ Msg :: term(),
+ Pid :: pid().
send(Name, Msg) ->
case whereis_name(Name) of
Pid when is_pid(Pid) ->
@@ -195,7 +198,8 @@ send(Name, Msg) ->
end.
%% See OTP-3737.
--spec whereis_name(term()) -> pid() | 'undefined'.
+-spec whereis_name(Name) -> pid() | 'undefined' when
+ Name :: term().
whereis_name(Name) ->
where(Name).
@@ -219,13 +223,19 @@ node_disconnected(Node) ->
%% undefined which one of them is used.
%% Method blocks the name registration, but does not affect global locking.
%%-----------------------------------------------------------------
--spec register_name(term(), pid()) -> 'yes' | 'no'.
+-spec register_name(Name, Pid) -> 'yes' | 'no' when
+ Name :: term(),
+ Pid :: pid().
register_name(Name, Pid) when is_pid(Pid) ->
register_name(Name, Pid, fun random_exit_name/3).
--type method() :: fun((term(), pid(), pid()) -> pid() | 'none').
+-type method() :: fun((Name :: term(), Pid :: pid(), Pid2 :: pid()) ->
+ pid() | 'none').
--spec register_name(term(), pid(), method()) -> 'yes' | 'no'.
+-spec register_name(Name, Pid, Resolve) -> 'yes' | 'no' when
+ Name :: term(),
+ Pid :: pid(),
+ Resolve :: method().
register_name(Name, Pid, Method) when is_pid(Pid) ->
Fun = fun(Nodes) ->
case (where(Name) =:= undefined) andalso check_dupname(Name, Pid) of
@@ -257,7 +267,8 @@ check_dupname(Name, Pid) ->
end
end.
--spec unregister_name(term()) -> _.
+-spec unregister_name(Name) -> _ when
+ Name :: term().
unregister_name(Name) ->
case where(Name) of
undefined ->
@@ -273,11 +284,16 @@ unregister_name(Name) ->
gen_server:call(global_name_server, {registrar, Fun}, infinity)
end.
--spec re_register_name(term(), pid()) -> _.
+-spec re_register_name(Name, Pid) -> _ when
+ Name :: term(),
+ Pid :: pid().
re_register_name(Name, Pid) when is_pid(Pid) ->
re_register_name(Name, Pid, fun random_exit_name/3).
--spec re_register_name(term(), pid(), method()) -> _.
+-spec re_register_name(Name, Pid, Resolve) -> _ when
+ Name :: term(),
+ Pid :: pid(),
+ Resolve :: method().
re_register_name(Name, Pid, Method) when is_pid(Pid) ->
Fun = fun(Nodes) ->
gen_server:multi_call(Nodes,
@@ -288,7 +304,8 @@ re_register_name(Name, Pid, Method) when is_pid(Pid) ->
?trace({re_register_name, self(), Name, Pid, Method}),
gen_server:call(global_name_server, {registrar, Fun}, infinity).
--spec registered_names() -> [term()].
+-spec registered_names() -> [Name] when
+ Name :: term().
registered_names() ->
MS = ets:fun2ms(fun({Name,_Pid,_M,_RP,_R}) -> Name end),
ets:select(global_names, MS).
@@ -329,19 +346,25 @@ register_name_external(Name, Pid, Method) when is_pid(Pid) ->
unregister_name_external(Name) ->
unregister_name(Name).
--type id() :: {term(), term()}.
+-type id() :: {ResourceId :: term(), LockRequesterId :: term()}.
--spec set_lock(id()) -> boolean().
+-spec set_lock(Id) -> boolean() when
+ Id :: id().
set_lock(Id) ->
set_lock(Id, [node() | nodes()], infinity, 1).
-type retries() :: non_neg_integer() | 'infinity'.
--spec set_lock(id(), [node()]) -> boolean().
+-spec set_lock(Id, Nodes) -> boolean() when
+ Id :: id(),
+ Nodes :: [node()].
set_lock(Id, Nodes) ->
set_lock(Id, Nodes, infinity, 1).
--spec set_lock(id(), [node()], retries()) -> boolean().
+-spec set_lock(Id, Nodes, Retries) -> boolean() when
+ Id :: id(),
+ Nodes :: [node()],
+ Retries :: retries().
set_lock(Id, Nodes, Retries) when is_integer(Retries), Retries >= 0 ->
set_lock(Id, Nodes, Retries, 1);
set_lock(Id, Nodes, infinity) ->
@@ -363,11 +386,14 @@ set_lock({_ResourceId, _LockRequesterId} = Id, Nodes, Retries, Times) ->
set_lock(Id, Nodes, dec(Retries), Times+1)
end.
--spec del_lock(id()) -> 'true'.
+-spec del_lock(Id) -> 'true' when
+ Id :: id().
del_lock(Id) ->
del_lock(Id, [node() | nodes()]).
--spec del_lock(id(), [node()]) -> 'true'.
+-spec del_lock(Id, Nodes) -> 'true' when
+ Id :: id(),
+ Nodes :: [node()].
del_lock({_ResourceId, _LockRequesterId} = Id, Nodes) ->
?trace({del_lock, {me,self()}, Id, {nodes,Nodes}}),
gen_server:multi_call(Nodes, global_name_server, {del_lock, Id}),
@@ -375,13 +401,25 @@ del_lock({_ResourceId, _LockRequesterId} = Id, Nodes) ->
-type trans_fun() :: function() | {module(), atom()}.
--spec trans(id(), trans_fun()) -> term().
+-spec trans(Id, Fun) -> Res | aborted when
+ Id :: id(),
+ Fun :: trans_fun(),
+ Res :: term().
trans(Id, Fun) -> trans(Id, Fun, [node() | nodes()], infinity).
--spec trans(id(), trans_fun(), [node()]) -> term().
+-spec trans(Id, Fun, Nodes) -> Res | aborted when
+ Id :: id(),
+ Fun :: trans_fun(),
+ Nodes :: [node()],
+ Res :: term().
trans(Id, Fun, Nodes) -> trans(Id, Fun, Nodes, infinity).
--spec trans(id(), trans_fun(), [node()], retries()) -> term().
+-spec trans(Id, Fun, Nodes, Retries) -> Res | aborted when
+ Id :: id(),
+ Fun :: trans_fun(),
+ Nodes :: [node()],
+ Retries :: retries(),
+ Res :: term().
trans(Id, Fun, Nodes, Retries) ->
case set_lock(Id, Nodes, Retries) of
true ->
@@ -1928,7 +1966,10 @@ resolve_it(Method, Name, Pid1, Pid2) ->
minmax(P1,P2) ->
if node(P1) < node(P2) -> {P1, P2}; true -> {P2, P1} end.
--spec random_exit_name(term(), pid(), pid()) -> pid().
+-spec random_exit_name(Name, Pid1, Pid2) -> 'none' when
+ Name :: term(),
+ Pid1 :: pid(),
+ Pid2 :: pid().
random_exit_name(Name, Pid, Pid2) ->
{Min, Max} = minmax(Pid, Pid2),
error_logger:info_msg("global: Name conflict terminating ~w\n",
@@ -1936,12 +1977,19 @@ random_exit_name(Name, Pid, Pid2) ->
exit(Max, kill),
Min.
+-spec random_notify_name(Name, Pid1, Pid2) -> 'none' when
+ Name :: term(),
+ Pid1 :: pid(),
+ Pid2 :: pid().
random_notify_name(Name, Pid, Pid2) ->
{Min, Max} = minmax(Pid, Pid2),
Max ! {global_name_conflict, Name},
Min.
--spec notify_all_name(term(), pid(), pid()) -> 'none'.
+-spec notify_all_name(Name, Pid1, Pid2) -> 'none' when
+ Name :: term(),
+ Pid1 :: pid(),
+ Pid2 :: pid().
notify_all_name(Name, Pid, Pid2) ->
Pid ! {global_name_conflict, Name, Pid2},
Pid2 ! {global_name_conflict, Name, Pid},
diff --git a/lib/kernel/src/global_group.erl b/lib/kernel/src/global_group.erl
index 7e141ac5c7..025a9b8a5b 100644
--- a/lib/kernel/src/global_group.erl
+++ b/lib/kernel/src/global_group.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -62,9 +62,10 @@
-type sync_state() :: 'no_conf' | 'synced'.
-type group_name() :: atom().
--type group_tuple() :: {group_name(), [node()]}
- | {group_name(), publish_type(), [node()]}.
-
+-type group_tuple() :: {GroupName :: group_name(), [node()]}
+ | {GroupName :: group_name(),
+ PublishType :: publish_type(),
+ [node()]}.
%%%====================================================================================
%%% The state of the global_group process
@@ -97,11 +98,14 @@
%%% External exported
%%%====================================================================================
--spec global_groups() -> {group_name(), [group_name()]} | 'undefined'.
+-spec global_groups() -> {GroupName, GroupNames} | undefined when
+ GroupName :: group_name(),
+ GroupNames :: [GroupName].
global_groups() ->
request(global_groups).
--spec monitor_nodes(boolean()) -> 'ok'.
+-spec monitor_nodes(Flag) -> 'ok' when
+ Flag :: boolean().
monitor_nodes(Flag) ->
case Flag of
true -> request({monitor_nodes, Flag});
@@ -109,30 +113,41 @@ monitor_nodes(Flag) ->
_ -> {error, not_boolean}
end.
--spec own_nodes() -> [node()].
+-spec own_nodes() -> Nodes when
+ Nodes :: [Node :: node()].
own_nodes() ->
request(own_nodes).
-type name() :: atom().
-type where() :: {'node', node()} | {'group', group_name()}.
--spec registered_names(where()) -> [name()].
+-spec registered_names(Where) -> Names when
+ Where :: where(),
+ Names :: [Name :: name()].
registered_names(Arg) ->
request({registered_names, Arg}).
--spec send(name(), term()) -> pid() | {'badarg', {name(), term()}}.
+-spec send(Name, Msg) -> pid() | {'badarg', {Name, Msg}} when
+ Name :: name(),
+ Msg :: term().
send(Name, Msg) ->
request({send, Name, Msg}).
--spec send(where(), name(), term()) -> pid() | {'badarg', {name(), term()}}.
+-spec send(Where, Name, Msg) -> pid() | {'badarg', {Name, Msg}} when
+ Where :: where(),
+ Name :: name(),
+ Msg :: term().
send(Group, Name, Msg) ->
request({send, Group, Name, Msg}).
--spec whereis_name(name()) -> pid() | 'undefined'.
+-spec whereis_name(Name) -> pid() | 'undefined' when
+ Name :: name().
whereis_name(Name) ->
request({whereis_name, Name}).
--spec whereis_name(where(), name()) -> pid() | 'undefined'.
+-spec whereis_name(Where, Name) -> pid() | 'undefined' when
+ Where :: where(),
+ Name :: name().
whereis_name(Group, Name) ->
request({whereis_name, Group, Name}).
@@ -155,14 +170,14 @@ ng_add_check(Node, OthersNG) ->
ng_add_check(Node, PubType, OthersNG) ->
request({ng_add_check, Node, PubType, OthersNG}).
--type info_item() :: {'state', sync_state()}
- | {'own_group_name', group_name()}
- | {'own_group_nodes', [node()]}
- | {'synched_nodes', [node()]}
- | {'sync_error', [node()]}
- | {'no_contact', [node()]}
- | {'other_groups', [group_tuple()]}
- | {'monitoring', [pid()]}.
+-type info_item() :: {'state', State :: sync_state()}
+ | {'own_group_name', GroupName :: group_name()}
+ | {'own_group_nodes', Nodes :: [node()]}
+ | {'synched_nodes', Nodes :: [node()]}
+ | {'sync_error', Nodes :: [node()]}
+ | {'no_contact', Nodes :: [node()]}
+ | {'other_groups', Groups :: [group_tuple()]}
+ | {'monitoring', Pids :: [pid()]}.
-spec info() -> [info_item()].
info() ->
@@ -1012,6 +1027,7 @@ grp_tuple({Name, normal, Nodes}) ->
%%% The special process which checks that all nodes in the own global group
%%% agrees on the configuration.
%%%====================================================================================
+-spec sync_init(_, _, _, _) -> no_return().
sync_init(Type, Cname, PubType, Nodes) ->
{Up, Down} = sync_check_node(lists:delete(node(), Nodes), [], []),
sync_check_init(Type, Up, Cname, Nodes, Down, PubType).
@@ -1032,9 +1048,11 @@ sync_check_node([Node|Nodes], Up, Down) ->
%%% Check that all nodes are in agreement of the global
%%% group configuration.
%%%-------------------------------------------------------------
+-spec sync_check_init(_, _, _, _, _, _) -> no_return().
sync_check_init(Type, Up, Cname, Nodes, Down, PubType) ->
sync_check_init(Type, Up, Cname, Nodes, 3, [], Down, PubType).
+-spec sync_check_init(_, _, _, _, _, _, _, _) -> no_return().
sync_check_init(_Type, NoContact, _Cname, _Nodes, 0, ErrorNodes, Down, _PubType) ->
case ErrorNodes of
[] ->
diff --git a/lib/kernel/src/global_search.erl b/lib/kernel/src/global_search.erl
index b723e18a1b..0bf53e29b8 100644
--- a/lib/kernel/src/global_search.erl
+++ b/lib/kernel/src/global_search.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -69,6 +69,7 @@ start(Flag, Arg) ->
%%%====================================================================================
%%%====================================================================================
+-spec init_send(_) -> no_return().
init_send({any, NodesList, Name, Msg, From}) ->
case whereis_any_loop(NodesList, Name) of
undefined ->
@@ -115,6 +116,7 @@ init_send({node, Node, Name, Msg, From}) ->
%%%====================================================================================
%%%====================================================================================
+-spec init_whereis(_) -> no_return().
init_whereis({any, NodesList, Name, From}) ->
R = whereis_any_loop(NodesList, Name),
gen_server:cast(global_group, {find_name_res, R, self(), From}),
@@ -146,6 +148,7 @@ init_whereis({node, Node, Name, From}) ->
%%%====================================================================================
%%%====================================================================================
%%%====================================================================================
+-spec init_names(_) -> no_return().
init_names({group, Nodes, From}) ->
case names_group_loop(Nodes) of
group_down ->
diff --git a/lib/kernel/src/heart.erl b/lib/kernel/src/heart.erl
index e78acfc7a6..255ae4e51b 100644
--- a/lib/kernel/src/heart.erl
+++ b/lib/kernel/src/heart.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -85,19 +85,21 @@ init(Starter, Parent) ->
Starter ! {start_error, self()}
end.
--spec set_cmd(string()) -> 'ok' | {'error', {'bad_cmd', string()}}.
+-spec set_cmd(Cmd) -> 'ok' | {'error', {'bad_cmd', Cmd}} when
+ Cmd :: string().
set_cmd(Cmd) ->
heart ! {self(), set_cmd, Cmd},
wait().
--spec get_cmd() -> 'ok'.
+-spec get_cmd() -> {ok, Cmd} when
+ Cmd :: string().
get_cmd() ->
heart ! {self(), get_cmd},
wait().
--spec clear_cmd() -> {'ok', string()}.
+-spec clear_cmd() -> ok.
clear_cmd() ->
heart ! {self(), clear_cmd},
diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl
index f289b8110d..1d3eb926ca 100644
--- a/lib/kernel/src/hipe_unified_loader.erl
+++ b/lib/kernel/src/hipe_unified_loader.erl
@@ -258,7 +258,7 @@ find_callee_mfas(Patches) when is_list(Patches) ->
amd64 -> [];
arm -> find_callee_mfas(Patches, gb_sets:empty(), false);
powerpc -> find_callee_mfas(Patches, gb_sets:empty(), true);
- %% ppc64 -> find_callee_mfas(Patches, gb_sets:empty(), true);
+ ppc64 -> find_callee_mfas(Patches, gb_sets:empty(), true);
ultrasparc -> [];
x86 -> []
end.
@@ -301,6 +301,7 @@ mk_trampoline_map(CalleeMFAs, Trampolines) ->
SizeofLong =
case erlang:system_info(hipe_architecture) of
amd64 -> 8;
+ ppc64 -> 8;
_ -> 4
end,
mk_trampoline_map(tuple_size(CalleeMFAs), CalleeMFAs,
@@ -625,15 +626,15 @@ patch_instr(Address, Value, Type) ->
%%
%% XXX: It appears this is used for inserting both code addresses
%% and other data. In HiPE, code addresses are still 32-bit on
-%% 64-bit machines.
+%% some 64-bit machines.
write_word(DataAddress, DataWord) ->
case erlang:system_info(hipe_architecture) of
amd64 ->
hipe_bifs:write_u64(DataAddress, DataWord),
DataAddress+8;
- %% ppc64 ->
- %% hipe_bifs:write_u64(DataAddress, DataWord),
- %% DataAddress+8;
+ ppc64 ->
+ hipe_bifs:write_u64(DataAddress, DataWord),
+ DataAddress+8;
_ ->
hipe_bifs:write_u32(DataAddress, DataWord),
DataAddress+4
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index 327e0f93f1..48a6f3db65 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -63,7 +63,9 @@
%% timer interface
-export([start_timer/1, timeout/1, timeout/2, stop_timer/1]).
--export_type([ip_address/0, socket/0]).
+-export_type([address_family/0, hostent/0, hostname/0, ip4_address/0,
+ ip6_address/0, ip_address/0, posix/0, socket/0,
+ port_number/0]).
%% imports
-import(lists, [append/1, duplicate/2, filter/2, foldl/3]).
@@ -79,97 +81,22 @@
%%% ---------------------------------
%%% Contract type definitions
+
+-type hostent() :: #hostent{}.
+-type hostname() :: atom() | string().
+-type ip4_address() :: {0..255,0..255,0..255,0..255}.
+-type ip6_address() :: {0..65535,0..65535,0..65535,0..65535,
+ 0..65535,0..65535,0..65535,0..65535}.
+-type ip_address() :: ip4_address() | ip6_address().
+-type port_number() :: 0..65535.
+-type posix() :: exbadport | exbadseq | file:posix().
-type socket() :: port().
--type posix() :: atom().
-type socket_setopt() ::
- {'raw', non_neg_integer(), non_neg_integer(), binary()} |
- %% TCP/UDP options
- {'reuseaddr', boolean()} |
- {'keepalive', boolean()} |
- {'dontroute', boolean()} |
- {'linger', {boolean(), non_neg_integer()}} |
- {'broadcast', boolean()} |
- {'sndbuf', non_neg_integer()} |
- {'recbuf', non_neg_integer()} |
- {'priority', non_neg_integer()} |
- {'tos', non_neg_integer()} |
- {'nodelay', boolean()} |
- {'multicast_ttl', non_neg_integer()} |
- {'multicast_loop', boolean()} |
- {'multicast_if', ip_address()} |
- {'add_membership', {ip_address(), ip_address()}} |
- {'drop_membership', {ip_address(), ip_address()}} |
- {'header', non_neg_integer()} |
- {'buffer', non_neg_integer()} |
- {'active', boolean() | 'once'} |
- {'packet',
- 0 | 1 | 2 | 4 | 'raw' | 'sunrm' | 'asn1' |
- 'cdr' | 'fcgi' | 'line' | 'tpkt' | 'http' | 'httph' | 'http_bin' | 'httph_bin' } |
- {'mode', list() | binary()} |
- {'port', 'port', 'term'} |
- {'exit_on_close', boolean()} |
- {'low_watermark', non_neg_integer()} |
- {'high_watermark', non_neg_integer()} |
- {'bit8', 'clear' | 'set' | 'on' | 'off'} |
- {'send_timeout', non_neg_integer() | 'infinity'} |
- {'send_timeout_close', boolean()} |
- {'delay_send', boolean()} |
- {'packet_size', non_neg_integer()} |
- {'read_packets', non_neg_integer()} |
- %% SCTP options
- {'sctp_rtoinfo', #sctp_rtoinfo{}} |
- {'sctp_associnfo', #sctp_assocparams{}} |
- {'sctp_initmsg', #sctp_initmsg{}} |
- {'sctp_nodelay', boolean()} |
- {'sctp_autoclose', non_neg_integer()} |
- {'sctp_disable_fragments', boolean()} |
- {'sctp_i_want_mapped_v4_addr', boolean()} |
- {'sctp_maxseg', non_neg_integer()} |
- {'sctp_primary_addr', #sctp_prim{}} |
- {'sctp_set_peer_primary_addr', #sctp_setpeerprim{}} |
- {'sctp_adaptation_layer', #sctp_setadaptation{}} |
- {'sctp_peer_addr_params', #sctp_paddrparams{}} |
- {'sctp_default_send_param', #sctp_sndrcvinfo{}} |
- {'sctp_events', #sctp_event_subscribe{}} |
- {'sctp_delayed_ack_time', #sctp_assoc_value{}}.
+ gen_sctp:option() | gen_tcp:option() | gen_udp:option().
-type socket_getopt() ::
- {'raw',
- non_neg_integer(), non_neg_integer(), binary()|non_neg_integer()} |
- %% TCP/UDP options
- 'reuseaddr' | 'keepalive' | 'dontroute' | 'linger' |
- 'broadcast' | 'sndbuf' | 'recbuf' | 'priority' | 'tos' | 'nodelay' |
- 'multicast_ttl' | 'multicast_loop' | 'multicast_if' |
- 'add_membership' | 'drop_membership' |
- 'header' | 'buffer' | 'active' | 'packet' | 'mode' | 'port' |
- 'exit_on_close' | 'low_watermark' | 'high_watermark' | 'bit8' |
- 'send_timeout' | 'send_timeout_close' |
- 'delay_send' | 'packet_size' | 'read_packets' |
- %% SCTP options
- {'sctp_status', #sctp_status{}} |
- 'sctp_get_peer_addr_info' |
- {'sctp_get_peer_addr_info', #sctp_status{}} |
- 'sctp_rtoinfo' |
- {'sctp_rtoinfo', #sctp_rtoinfo{}} |
- 'sctp_associnfo' |
- {'sctp_associnfo', #sctp_assocparams{}} |
- 'sctp_initmsg' |
- {'sctp_initmsg', #sctp_initmsg{}} |
- 'sctp_nodelay' | 'sctp_autoclose' | 'sctp_disable_fragments' |
- 'sctp_i_want_mapped_v4_addr' | 'sctp_maxseg' |
- {'sctp_primary_addr', #sctp_prim{}} |
- {'sctp_set_peer_primary_addr', #sctp_setpeerprim{}} |
- 'sctp_adaptation_layer' |
- {'sctp_adaptation_layer', #sctp_setadaptation{}} |
- {'sctp_peer_addr_params', #sctp_paddrparams{}} |
- 'sctp_default_send_param' |
- {'sctp_default_send_param', #sctp_sndrcvinfo{}} |
- 'sctp_events' |
- {'sctp_events', #sctp_event_subscribe{}} |
- 'sctp_delayed_ack_time' |
- {'sctp_delayed_ack_time', #sctp_assoc_value{}}.
-
+ gen_sctp:option_name() | gen_tcp:option_name() | gen_udp:option_name().
-type ether_address() :: [0..255].
-type if_setopt() ::
@@ -187,7 +114,7 @@
'addr' | 'broadaddr' | 'dstaddr' |
'mtu' | 'netmask' | 'flags' |'hwaddr'.
--type family_option() :: 'inet' | 'inet6'.
+-type address_family() :: 'inet' | 'inet6'.
-type protocol_option() :: 'tcp' | 'udp' | 'sctp'.
-type stat_option() ::
'recv_cnt' | 'recv_max' | 'recv_avg' | 'recv_oct' | 'recv_dvi' |
@@ -195,12 +122,13 @@
%%% ---------------------------------
--spec get_rc() -> [{any(),any()}].
+-spec get_rc() -> [{Par :: any(), Val :: any()}].
get_rc() ->
inet_db:get_rc().
--spec close(Socket :: socket()) -> 'ok'.
+-spec close(Socket) -> 'ok' when
+ Socket :: socket().
close(Socket) ->
prim_inet:close(Socket),
@@ -211,13 +139,15 @@ close(Socket) ->
ok
end.
--spec peername(Socket :: socket()) ->
- {'ok', {ip_address(), non_neg_integer()}} | {'error', posix()}.
+-spec peername(Socket) -> {ok, {Address, Port}} | {error, posix()} when
+ Socket :: socket(),
+ Address :: ip_address(),
+ Port :: non_neg_integer().
peername(Socket) ->
prim_inet:peername(Socket).
--spec setpeername(Socket :: socket(), Address :: {ip_address(), ip_port()}) ->
+-spec setpeername(Socket :: socket(), Address :: {ip_address(), port_number()}) ->
'ok' | {'error', any()}.
setpeername(Socket, {IP,Port}) ->
@@ -226,13 +156,15 @@ setpeername(Socket, undefined) ->
prim_inet:setpeername(Socket, undefined).
--spec sockname(Socket :: socket()) ->
- {'ok', {ip_address(), non_neg_integer()}} | {'error', posix()}.
+-spec sockname(Socket) -> {ok, {Address, Port}} | {error, posix()} when
+ Socket :: socket(),
+ Address :: ip_address(),
+ Port :: non_neg_integer().
sockname(Socket) ->
prim_inet:sockname(Socket).
--spec setsockname(Socket :: socket(), Address :: {ip_address(), ip_port()}) ->
+-spec setsockname(Socket :: socket(), Address :: {ip_address(), port_number()}) ->
'ok' | {'error', any()}.
setsockname(Socket, {IP,Port}) ->
@@ -240,7 +172,9 @@ setsockname(Socket, {IP,Port}) ->
setsockname(Socket, undefined) ->
prim_inet:setsockname(Socket, undefined).
--spec port(Socket :: socket()) -> {'ok', ip_port()} | {'error', any()}.
+-spec port(Socket) -> {'ok', Port} | {'error', any()} when
+ Socket :: socket(),
+ Port :: port_number().
port(Socket) ->
case prim_inet:sockname(Socket) of
@@ -254,14 +188,18 @@ port(Socket) ->
send(Socket, Packet) ->
prim_inet:send(Socket, Packet).
--spec setopts(Socket :: socket(), Opts :: [socket_setopt()]) ->
- 'ok' | {'error', posix()}.
+-spec setopts(Socket, Options) -> ok | {error, posix()} when
+ Socket :: socket(),
+ Options :: [socket_setopt()].
setopts(Socket, Opts) ->
prim_inet:setopts(Socket, Opts).
--spec getopts(Socket :: socket(), Opts :: [socket_getopt()]) ->
- {'ok', [socket_setopt()]} | {'error', posix()}.
+-spec getopts(Socket, Options) ->
+ {'ok', OptionValues} | {'error', posix()} when
+ Socket :: socket(),
+ Options :: [socket_getopt()],
+ OptionValues :: [socket_setopt()].
getopts(Socket, Opts) ->
prim_inet:getopts(Socket, Opts).
@@ -272,7 +210,19 @@ getopts(Socket, Opts) ->
getifaddrs(Socket) ->
prim_inet:getifaddrs(Socket).
--spec getifaddrs() -> {'ok', [string()]} | {'error', posix()}.
+-spec getifaddrs() -> {ok, Iflist} | {error, posix()} when
+ Iflist :: [{Ifname,[Ifopt]}],
+ Ifname :: string(),
+ Ifopt :: {flag,[Flag]} | {addr,Addr} | {netmask,Netmask}
+ | {broadaddr,Broadaddr} | {dstaddr,Dstaddr}
+ | {hwaddr,Hwaddr},
+ Flag :: up | broadcast | loopback | pointtopoint
+ | running | multicast,
+ Addr :: ip_address(),
+ Netmask :: ip_address(),
+ Broadaddr :: ip_address(),
+ Dstaddr :: ip_address(),
+ Hwaddr :: [byte()].
getifaddrs() ->
withsocket(fun(S) -> prim_inet:getifaddrs(S) end).
@@ -371,7 +321,8 @@ popf(_Socket) ->
% use of the DHCP-protocol
% should never fail
--spec gethostname() -> {'ok', string()}.
+-spec gethostname() -> {'ok', Hostname} when
+ Hostname :: string().
gethostname() ->
case inet_udp:open(0,[]) of
@@ -390,32 +341,41 @@ gethostname() ->
gethostname(Socket) ->
prim_inet:gethostname(Socket).
--spec getstat(Socket :: socket()) ->
- {'ok', [{stat_option(), integer()}]} | {'error', posix()}.
+-spec getstat(Socket) ->
+ {ok, OptionValues} | {error, posix()} when
+ Socket :: socket(),
+ OptionValues :: [{stat_option(), integer()}].
getstat(Socket) ->
prim_inet:getstat(Socket, stats()).
--spec getstat(Socket :: socket(), Statoptions :: [stat_option()]) ->
- {'ok', [{stat_option(), integer()}]} | {'error', posix()}.
+-spec getstat(Socket, Options) ->
+ {ok, OptionValues} | {error, posix()} when
+ Socket :: socket(),
+ Options :: [stat_option()],
+ OptionValues :: [{stat_option(), integer()}].
getstat(Socket,What) ->
prim_inet:getstat(Socket, What).
--spec gethostbyname(Name :: string() | atom()) ->
- {'ok', #hostent{}} | {'error', posix()}.
+-spec gethostbyname(Hostname) -> {ok, Hostent} | {error, posix()} when
+ Hostname :: hostname(),
+ Hostent :: hostent().
gethostbyname(Name) ->
gethostbyname_tm(Name, inet, false).
--spec gethostbyname(Name :: string() | atom(), Family :: family_option()) ->
- {'ok', #hostent{}} | {'error', posix()}.
+-spec gethostbyname(Hostname, Family) ->
+ {ok, Hostent} | {error, posix()} when
+ Hostname :: hostname(),
+ Family :: address_family(),
+ Hostent :: hostent().
gethostbyname(Name,Family) ->
gethostbyname_tm(Name, Family, false).
--spec gethostbyname(Name :: string() | atom(),
- Family :: family_option(),
+-spec gethostbyname(Name :: hostname(),
+ Family :: address_family(),
Timeout :: non_neg_integer() | 'infinity') ->
{'ok', #hostent{}} | {'error', posix()}.
@@ -439,8 +399,9 @@ gethostbyname_tm(Name,Family,Timer) ->
gethostbyname_tm(Name, Family, Timer, Opts).
--spec gethostbyaddr(Address :: string() | ip_address()) ->
- {'ok', #hostent{}} | {'error', posix()}.
+-spec gethostbyaddr(Address) -> {ok, Hostent} | {error, posix()} when
+ Address :: string() | ip_address(),
+ Hostent :: hostent().
gethostbyaddr(Address) ->
gethostbyaddr_tm(Address, false).
@@ -491,15 +452,16 @@ getfd(Socket) ->
%% Lookup an ip address
%%
--spec getaddr(Host :: ip_address() | string() | atom(),
- Family :: family_option()) ->
- {'ok', ip_address()} | {'error', posix()}.
+-spec getaddr(Host, Family) -> {ok, Address} | {error, posix()} when
+ Host :: ip_address() | hostname(),
+ Family :: address_family(),
+ Address :: ip_address().
getaddr(Address, Family) ->
getaddr(Address, Family, infinity).
--spec getaddr(Host :: ip_address() | string() | atom(),
- Family :: family_option(),
+-spec getaddr(Host :: ip_address() | hostname(),
+ Family :: address_family(),
Timeout :: non_neg_integer() | 'infinity') ->
{'ok', ip_address()} | {'error', posix()}.
@@ -515,15 +477,17 @@ getaddr_tm(Address, Family, Timer) ->
Error -> Error
end.
--spec getaddrs(Host :: ip_address() | string() | atom(),
- Family :: family_option()) ->
- {'ok', [ip_address()]} | {'error', posix()}.
+-spec getaddrs(Host, Family) ->
+ {ok, Addresses} | {error, posix()} when
+ Host :: ip_address() | hostname(),
+ Family :: address_family(),
+ Addresses :: [ip_address()].
getaddrs(Address, Family) ->
getaddrs(Address, Family, infinity).
-spec getaddrs(Host :: ip_address() | string() | atom(),
- Family :: family_option(),
+ Family :: address_family(),
Timeout :: non_neg_integer() | 'infinity') ->
{'ok', [ip_address()]} | {'error', posix()}.
@@ -533,7 +497,7 @@ getaddrs(Address, Family, Timeout) ->
stop_timer(Timer),
Res.
--spec getservbyport(Port :: ip_port(), Protocol :: atom() | string()) ->
+-spec getservbyport(Port :: port_number(), Protocol :: atom() | string()) ->
{'ok', string()} | {'error', posix()}.
getservbyport(Port, Proto) ->
@@ -547,7 +511,7 @@ getservbyport(Port, Proto) ->
-spec getservbyname(Name :: atom() | string(),
Protocol :: atom() | string()) ->
- {'ok', ip_port()} | {'error', posix()}.
+ {'ok', port_number()} | {'error', posix()}.
getservbyname(Name, Protocol) when is_atom(Name) ->
case inet_udp:open(0, []) of
@@ -1030,7 +994,7 @@ gethostbyaddr_tm_native(Addr, Timer, Opts) ->
-spec open(Fd :: integer(),
Addr :: ip_address(),
- Port :: ip_port(),
+ Port :: port_number(),
Opts :: [socket_setopt()],
Protocol :: protocol_option(),
Family :: 'inet' | 'inet6',
@@ -1071,7 +1035,7 @@ open(Fd, _Addr, _Port, Opts, Protocol, Family, Module) ->
-spec fdopen(Fd :: non_neg_integer(),
Opts :: [socket_setopt()],
Protocol :: protocol_option(),
- Family :: family_option(),
+ Family :: address_family(),
Module :: atom()) ->
{'ok', socket()} | {'error', posix()}.
@@ -1237,7 +1201,8 @@ port_list(Name) ->
%% utils
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec format_error(posix()) -> string().
+-spec format_error(Posix) -> string() when
+ Posix :: posix().
format_error(exbadport) -> "invalid port state";
format_error(exbadseq) -> "bad command sequence";
diff --git a/lib/kernel/src/inet_config.erl b/lib/kernel/src/inet_config.erl
index 2458876326..1ddbdcec25 100644
--- a/lib/kernel/src/inet_config.erl
+++ b/lib/kernel/src/inet_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -44,26 +44,6 @@
%%
-spec init() -> 'ok'.
init() ->
- OsType = os:type(),
- case OsType of
- {ose,_} ->
- case init:get_argument(loader) of
- {ok,[["ose_inet"]]} ->
- %% port already started by prim_loader
- ok;
- _Other ->
- %% Setup reserved port for ose_inet driver (only OSE)
- case catch erlang:open_port({spawn,"ose_inet"}, [binary]) of
- {'EXIT',Why} ->
- error("can't open port for ose_inet: ~p", [Why]);
- OseInetPort ->
- erlang:display({ose_inet_port,OseInetPort})
- end
- end;
- _ ->
- ok
- end,
-
set_hostname(),
%% Note: In shortnames (or non-distributed) mode we don't need to know
@@ -71,6 +51,7 @@ init() ->
%% the user to provide it (by means of inetrc), so we need to look
%% for it ourselves.
+ OsType = os:type(),
do_load_resolv(OsType, erl_dist_mode()),
case OsType of
@@ -226,35 +207,6 @@ do_load_resolv(vxworks, _) ->
load_resolv(Resolv, resolv)
end;
-do_load_resolv({ose,_Type}, _) ->
- inet_db:set_lookup([file, dns]),
- case os:getenv("NAMESERVER") of
- false ->
- case os:getenv("RESOLVFILE") of
- false ->
- erlang:display('Warning: No NAMESERVER or RESOLVFILE specified!'),
- no_resolv;
- Resolv ->
- load_resolv(Resolv, resolv)
- end;
- Ns ->
- {ok,IP} = inet_parse:address(Ns),
- inet_db:add_rc_list([{nameserver,IP}])
- end,
- case os:getenv("DOMAIN") of
- false ->
- no_domain;
- D ->
- ok = inet_db:add_rc_list([{domain,D}])
- end,
- case os:getenv("HOSTSFILE") of
- false ->
- erlang:display('Warning: No HOSTSFILE specified!'),
- no_hosts_file;
- File ->
- load_hosts(File, ose)
- end;
-
do_load_resolv(_, _) ->
inet_db:set_lookup([native]).
diff --git a/lib/kernel/src/inet_dns_record_adts.pl b/lib/kernel/src/inet_dns_record_adts.pl
index b1d8fab939..da50c7114f 100644
--- a/lib/kernel/src/inet_dns_record_adts.pl
+++ b/lib/kernel/src/inet_dns_record_adts.pl
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009. All Rights Reserved.
+# Copyright Ericsson AB 2009-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -73,6 +73,10 @@ while( my ($Name, $r) = each(%Names)) {
# "@Values" = "V1,V2"...",VN"
my @D = @DATA;
foreach my $line (@D) {
+ # Ignore !name lines
+ if ($line =~ s/^\!(\S+)\s+//) {
+ next if $1 eq $Name;
+ }
my $m = 1;
# For leading * iterate $n times, otherwise once
$line =~ s/^\s*[*]// and $m = $n;
@@ -155,9 +159,9 @@ make_Name() -> \
make_Name(L) when is_list(L) -> \
make_Name(#Record{}, L).
-%% Generate #Record{} with one updated field
-%%
-*make_Name(Field, Value) -> \
+!dns_rr_opt %% Generate #Record{} with one updated field
+!dns_rr_opt %%
+!dns_rr_opt *make_Name(Field, Value) -> \
#Record{Field=Value};
%%
%% Update #Record{} from property list
diff --git a/lib/kernel/src/inet_res.erl b/lib/kernel/src/inet_res.erl
index de0f23bf24..59ba408d7a 100644
--- a/lib/kernel/src/inet_res.erl
+++ b/lib/kernel/src/inet_res.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -47,18 +47,93 @@
false -> ok
end).
+-type res_option() ::
+ {alt_nameservers, [nameserver()]}
+ | {edns, 0 | false}
+ | {inet6, boolean()}
+ | {nameservers, [nameserver()]}
+ | {recurse, boolean()}
+ | {retry, integer()}
+ | {timeout, integer()}
+ | {udp_payload_size, integer()}
+ | {usevc, boolean()}.
+
+-type nameserver() :: {inet:ip_address(), Port :: 1..65535}.
+
+-type res_error() :: formerr | qfmterror | servfail | nxdomain |
+ notimp | refused | badvers | timeout.
+
+-type dns_name() :: string().
+
+-type rr_type() :: a | aaaa | cname | gid | hinfo | ns | mb | md | mg | mf
+ | minfo | mx | naptr | null | ptr | soa | spf | srv | txt
+ | uid | uinfo | unspec | wks.
+
+-type dns_class() :: in | chaos | hs | any.
+
+-type dns_msg() :: term().
+
+-type dns_data() ::
+ dns_name()
+ | inet:ip4_address()
+ | inet:ip6_address()
+ | {MName :: dns_name(),
+ RName :: dns_name(),
+ Serial :: integer(),
+ Refresh :: integer(),
+ Retry :: integer(),
+ Expiry :: integer(),
+ Minimum :: integer()}
+ | {inet:ip4_address(), Proto :: integer(), BitMap :: binary()}
+ | {CpuString :: string(), OsString :: string()}
+ | {RM :: dns_name(), EM :: dns_name()}
+ | {Prio :: integer(), dns_name()}
+ | {Prio :: integer(),Weight :: integer(),Port :: integer(),dns_name()}
+ | {Order :: integer(),Preference :: integer(),Flags :: string(),
+ Services :: string(),Regexp :: string(), dns_name()}
+ | [string()]
+ | binary().
+
%% --------------------------------------------------------------------------
%% resolve:
%%
%% Nameserver query
%%
+-spec resolve(Name, Class, Type) -> {ok, dns_msg()} | Error when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Error :: {error, Reason} | {error,{Reason,dns_msg()}},
+ Reason :: inet:posix() | res_error().
+
resolve(Name, Class, Type) ->
resolve(Name, Class, Type, [], infinity).
+-spec resolve(Name, Class, Type, Opts) ->
+ {ok, dns_msg()} | Error when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Opts :: [Opt],
+ Opt :: res_option() | verbose | atom(),
+ Error :: {error, Reason} | {error,{Reason,dns_msg()}},
+ Reason :: inet:posix() | res_error().
+
resolve(Name, Class, Type, Opts) ->
resolve(Name, Class, Type, Opts, infinity).
+-spec resolve(Name, Class, Type, Opts, Timeout) ->
+ {ok, dns_msg()} | Error when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Opts :: [Opt],
+ Opt :: res_option() | verbose | atom(),
+ Timeout :: timeout(),
+ Error :: {error, Reason} | {error,{Reason,dns_msg()}},
+ Reason :: inet:posix() | res_error().
+
resolve(Name, Class, Type, Opts, Timeout) ->
case nsdname(Name) of
{ok, Nm} ->
@@ -76,12 +151,30 @@ resolve(Name, Class, Type, Opts, Timeout) ->
%% Convenience wrapper to resolve/3,4,5 that filters out all answer data
%% fields of the class and type asked for.
+-spec lookup(Name, Class, Type) -> [dns_data()] when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type().
+
lookup(Name, Class, Type) ->
lookup(Name, Class, Type, []).
+-spec lookup(Name, Class, Type, Opts) -> [dns_data()] when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Opts :: [res_option() | verbose].
+
lookup(Name, Class, Type, Opts) ->
lookup(Name, Class, Type, Opts, infinity).
+-spec lookup(Name, Class, Type, Opts, Timeout) -> [dns_data()] when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Opts :: [res_option() | verbose],
+ Timeout :: timeout().
+
lookup(Name, Class, Type, Opts, Timeout) ->
lookup_filter(resolve(Name, Class, Type, Opts, Timeout),
Class, Type).
@@ -101,17 +194,55 @@ lookup_filter({error,_}, _, _) -> [].
%%
%% To be deprecated
+-spec nslookup(Name, Class, Type) -> {ok, dns_msg()} | {error, Reason} when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Reason :: inet:posix() | res_error().
+
nslookup(Name, Class, Type) ->
do_nslookup(Name, Class, Type, [], infinity).
+-spec nslookup(Name, Class, Type, Timeout) ->
+ {ok, dns_msg()} | {error, Reason} when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Timeout :: timeout(),
+ Reason :: inet:posix() | res_error();
+ (Name, Class, Type, Nameservers) ->
+ {ok, dns_msg()} | {error, Reason} when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Nameservers :: [nameserver()],
+ Reason :: inet:posix() | res_error().
+
nslookup(Name, Class, Type, Timeout) when is_integer(Timeout), Timeout >= 0 ->
do_nslookup(Name, Class, Type, [], Timeout);
nslookup(Name, Class, Type, NSs) -> % For backwards compatibility
nnslookup(Name, Class, Type, NSs). % with OTP R6B only
+-spec nnslookup(Name, Class, Type, Nameservers) ->
+ {ok, dns_msg()} | {error, Reason} when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Nameservers :: [nameserver()],
+ Reason :: inet:posix().
+
nnslookup(Name, Class, Type, NSs) ->
nnslookup(Name, Class, Type, NSs, infinity).
+-spec nnslookup(Name, Class, Type, Nameservers, Timeout) ->
+ {ok, dns_msg()} | {error, Reason} when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Timeout :: timeout(),
+ Nameservers :: [nameserver()],
+ Reason :: inet:posix().
+
nnslookup(Name, Class, Type, NSs, Timeout) ->
do_nslookup(Name, Class, Type, [{nameservers,NSs}], Timeout).
@@ -192,8 +323,19 @@ make_options(Opts, [Name|Names]) ->
%%
%% --------------------------------------------------------------------------
+-spec gethostbyaddr(Address) -> {ok, Hostent} | {error, Reason} when
+ Address :: inet:ip_address(),
+ Hostent :: inet:hostent(),
+ Reason :: inet:posix() | res_error().
+
gethostbyaddr(IP) -> gethostbyaddr_tm(IP,false).
+-spec gethostbyaddr(Address, Timeout) -> {ok, Hostent} | {error, Reason} when
+ Address :: inet:ip_address(),
+ Timeout :: timeout(),
+ Hostent :: inet:hostent(),
+ Reason :: inet:posix() | res_error().
+
gethostbyaddr(IP,Timeout) ->
Timer = inet:start_timer(Timeout),
Res = gethostbyaddr_tm(IP,Timer),
@@ -249,6 +391,11 @@ res_gethostbyaddr(Addr, IP, Timer) ->
%% Caches the answer.
%% --------------------------------------------------------------------------
+-spec gethostbyname(Name) -> {ok, Hostent} | {error, Reason} when
+ Name :: dns_name(),
+ Hostent :: inet:hostent(),
+ Reason :: inet:posix() | res_error().
+
gethostbyname(Name) ->
case inet_db:res_option(inet6) of
true ->
@@ -257,9 +404,23 @@ gethostbyname(Name) ->
gethostbyname_tm(Name, inet, false)
end.
+-spec gethostbyname(Name, Family) -> {ok, Hostent} | {error, Reason} when
+ Name :: dns_name(),
+ Hostent :: inet:hostent(),
+ Family :: inet:address_family(),
+ Reason :: inet:posix() | res_error().
+
gethostbyname(Name,Family) ->
gethostbyname_tm(Name,Family,false).
+-spec gethostbyname(Name, Family, Timeout) ->
+ {ok, Hostent} | {error, Reason} when
+ Name :: dns_name(),
+ Hostent :: inet:hostent(),
+ Timeout :: timeout(),
+ Family :: inet:address_family(),
+ Reason :: inet:posix() | res_error().
+
gethostbyname(Name,Family,Timeout) ->
Timer = inet:start_timer(Timeout),
Res = gethostbyname_tm(Name,Family,Timer),
@@ -298,14 +459,27 @@ gethostbyname_tm(_Name, _Family, _Timer) ->
%%
%% getbyname(domain_name(), Type) => {ok, hostent()} | {error, Reason}
%%
-%% where domain_name() is domain string or atom and Type is ?S_A, ?S_MX ...
+%% where domain_name() is domain string and Type is ?S_A, ?S_MX ...
%%
%% Caches the answer.
%% --------------------------------------------------------------------------
+-spec getbyname(Name, Type) -> {ok, Hostent} | {error, Reason} when
+ Name :: dns_name(),
+ Type :: rr_type(),
+ Hostent :: inet:hostent(),
+ Reason :: inet:posix() | res_error().
+
getbyname(Name, Type) ->
getbyname_tm(Name,Type,false).
+-spec getbyname(Name, Type, Timeout) -> {ok, Hostent} | {error, Reason} when
+ Name :: dns_name(),
+ Type :: rr_type(),
+ Timeout :: timeout(),
+ Hostent :: inet:hostent(),
+ Reason :: inet:posix() | res_error().
+
getbyname(Name, Type, Timeout) ->
Timer = inet:start_timer(Timeout),
Res = getbyname_tm(Name, Type, Timer),
@@ -539,27 +713,41 @@ udp_send(#sock{inet=I}, {A,B,C,D}=IP, Port, Buffer)
when ?ip(A,B,C,D), ?port(Port) ->
gen_udp:send(I, IP, Port, Buffer).
-udp_recv(#sock{inet6=I}, {A,B,C,D,E,F,G,H}=IP, Port, Timeout)
+udp_recv(#sock{inet6=I}, {A,B,C,D,E,F,G,H}=IP, Port, Timeout, Decode)
when ?ip6(A,B,C,D,E,F,G,H), ?port(Port) ->
- do_udp_recv(fun(T) -> gen_udp:recv(I, 0, T) end, IP, Port, Timeout);
-udp_recv(#sock{inet=I}, {A,B,C,D}=IP, Port, Timeout)
+ do_udp_recv(I, IP, Port, Timeout, Decode, erlang:now(), Timeout);
+udp_recv(#sock{inet=I}, {A,B,C,D}=IP, Port, Timeout, Decode)
when ?ip(A,B,C,D), ?port(Port) ->
- do_udp_recv(fun(T) -> gen_udp:recv(I, 0, T) end, IP, Port, Timeout).
-
-do_udp_recv(Recv, IP, Port, Timeout) ->
- do_udp_recv(Recv, IP, Port, Timeout,
- if Timeout =/= 0 -> erlang:now(); true -> undefined end).
-
-do_udp_recv(Recv, IP, Port, Timeout, Then) ->
- case Recv(Timeout) of
- {ok,{IP,Port,Answer}} ->
- {ok,Answer,erlang:max(0, Timeout - now_ms(erlang:now(), Then))};
- {ok,_} when Timeout =:= 0 ->
- {error,timeout};
- {ok,_} ->
- Now = erlang:now(),
- T = erlang:max(0, Timeout - now_ms(Now, Then)),
- do_udp_recv(Recv, IP, Port, T, Now);
+ do_udp_recv(I, IP, Port, Timeout, Decode, erlang:now(), Timeout).
+
+do_udp_recv(_I, _IP, _Port, 0, _Decode, _Start, _T) ->
+ timeout;
+do_udp_recv(I, IP, Port, Timeout, Decode, Start, T) ->
+ case gen_udp:recv(I, 0, T) of
+ {ok,Reply} ->
+ case Decode(Reply) of
+ false when T =:= 0 ->
+ %% This is a compromize between the hard way i.e
+ %% in the clause below if NewT becomes 0 bailout
+ %% immediately and risk that the right reply lies
+ %% ahead after some bad id replies, and the
+ %% forgiving way i.e go on with Timeout 0 until
+ %% the right reply comes or no reply (timeout)
+ %% which opens for a DOS attack by a malicious
+ %% DNS server flooding with bad id replies causing
+ %% an infinite loop here.
+ %%
+ %% Timeout is used as a sanity limit counter
+ %% just to put an end to the loop.
+ NewTimeout = erlang:max(0, Timeout - 50),
+ do_udp_recv(I, IP, Port, NewTimeout, Decode, Start, T);
+ false ->
+ Now = erlang:now(),
+ NewT = erlang:max(0, Timeout - now_ms(Now, Start)),
+ do_udp_recv(I, IP, Port, Timeout, Decode, Start, NewT);
+ Result ->
+ Result
+ end;
Error -> Error
end.
@@ -580,6 +768,17 @@ udp_close(#sock{inet=I,inet6=I6}) ->
%% end
%% end
%%
+%% But that man page also says dig always use num_servers = 1.
+%%
+%% Our man page says: timeout/retry, then double for next retry, i.e
+%% for i = 0 to retry - 1
+%% foreach nameserver
+%% send query
+%% wait((time * (2**i)) / retry)
+%% end
+%% end
+%%
+%% And that is what the code seems to do, now fixed, hopefully...
do_query(_Q, [], _Timer) ->
{error,nxdomain};
@@ -589,19 +788,16 @@ do_query(#q{options=#options{retry=Retry}}=Q, NSs, Timer) ->
query_retries(_Q, _NSs, _Timer, Retry, Retry, S) ->
udp_close(S),
{error,timeout};
+query_retries(_Q, [], _Timer, _Retry, _I, S) ->
+ udp_close(S),
+ {error,timeout};
query_retries(Q, NSs, Timer, Retry, I, S0) ->
- Num = length(NSs),
- if Num =:= 0 ->
- udp_close(S0),
- {error,timeout};
- true ->
- case query_nss(Q, NSs, Timer, Retry, I, S0, []) of
- {S,{noanswer,ErrNSs}} -> %% remove unreachable nameservers
- query_retries(Q, NSs--ErrNSs, Timer, Retry, I+1, S);
- {S,Result} ->
- udp_close(S),
- Result
- end
+ case query_nss(Q, NSs, Timer, Retry, I, S0, []) of
+ {S,{noanswer,ErrNSs}} -> %% remove unreachable nameservers
+ query_retries(Q, NSs--ErrNSs, Timer, Retry, I+1, S);
+ {S,Result} ->
+ udp_close(S),
+ Result
end.
query_nss(_Q, [], _Timer, _Retry, _I, S, ErrNSs) ->
@@ -611,13 +807,13 @@ query_nss(#q{edns=undefined}=Q, NSs, Timer, Retry, I, S, ErrNSs) ->
query_nss(Q, NSs, Timer, Retry, I, S, ErrNSs) ->
query_nss_edns(Q, NSs, Timer, Retry, I, S, ErrNSs).
-query_nss_edns(#q{options=#options{udp_payload_size=PSz}=Options,
- edns={Id,Buffer}}=Q,
- [{IP,Port}=NS|NSs]=NSs0, Timer, Retry, I, S0, ErrNSs) ->
- {S,Res}=Reply = query_ns(S0, Id, Buffer, IP, Port, Timer,
- Retry, I, Options, PSz),
+query_nss_edns(
+ #q{options=#options{udp_payload_size=PSz}=Options,edns={Id,Buffer}}=Q,
+ [{IP,Port}=NS|NSs]=NSs0, Timer, Retry, I, S0, ErrNSs) ->
+ {S,Res}=Reply =
+ query_ns(S0, Id, Buffer, IP, Port, Timer, Retry, I, Options, PSz),
case Res of
- timeout -> {S,{error,timeout}};
+ timeout -> {S,{error,timeout}}; % Bailout timeout
{ok,_} -> Reply;
{error,{nxdomain,_}} -> Reply;
{error,{E,_}} when E =:= qfmterror; E =:= notimp; E =:= servfail;
@@ -629,17 +825,19 @@ query_nss_edns(#q{options=#options{udp_payload_size=PSz}=Options,
query_nss(Q, NSs, Timer, Retry, I, S, ErrNSs)
end.
-query_nss_dns(#q{dns=Qdns}=Q0, [{IP,Port}=NS|NSs],
- Timer, Retry, I, S0, ErrNSs) ->
+query_nss_dns(
+ #q{dns=Qdns}=Q0,
+ [{IP,Port}=NS|NSs], Timer, Retry, I, S0, ErrNSs) ->
#q{options=Options,dns={Id,Buffer}}=Q =
if
is_function(Qdns, 0) -> Q0#q{dns=Qdns()};
true -> Q0
end,
- {S,Res}=Reply = query_ns(S0, Id, Buffer, IP, Port, Timer,
- Retry, I, Options, ?PACKETSZ),
+ {S,Res}=Reply =
+ query_ns(
+ S0, Id, Buffer, IP, Port, Timer, Retry, I, Options, ?PACKETSZ),
case Res of
- timeout -> {S,{error,timeout}};
+ timeout -> {S,{error,timeout}}; % Bailout timeout
{ok,_} -> Reply;
{error,{E,_}} when E =:= nxdomain; E =:= qfmterror -> Reply;
{error,E} when E =:= fmt; E =:= enetunreach; E =:= econnrefused ->
@@ -653,48 +851,66 @@ query_ns(S0, Id, Buffer, IP, Port, Timer, Retry, I,
PSz) ->
case UseVC orelse iolist_size(Buffer) > PSz of
true ->
- {S0,query_tcp(Tm, Id, Buffer, IP, Port, Timer, Verbose)};
+ TcpTimeout = inet:timeout(Tm*5, Timer),
+ {S0,query_tcp(TcpTimeout, Id, Buffer, IP, Port, Verbose)};
false ->
case udp_open(S0, IP) of
{ok,S} ->
- {S,case query_udp(S, Id, Buffer, IP, Port, Timer,
- Retry, I, Tm, Verbose) of
- {ok,#dns_rec{header=H}} when H#dns_header.tc ->
- query_tcp(Tm, Id, Buffer,
- IP, Port, Timer, Verbose);
- Reply -> Reply
- end};
+ Timeout =
+ inet:timeout( (Tm * (1 bsl I)) div Retry, Timer),
+ {S,
+ case query_udp(
+ S, Id, Buffer, IP, Port, Timeout, Verbose) of
+ {ok,#dns_rec{header=H}} when H#dns_header.tc ->
+ TcpTimeout = inet:timeout(Tm*5, Timer),
+ query_tcp(
+ TcpTimeout, Id, Buffer, IP, Port, Verbose);
+ Reply -> Reply
+ end};
Error ->
{S0,Error}
end
end.
-query_udp(S, Id, Buffer, IP, Port, Timer, Retry, I, Tm, Verbose) ->
- Timeout = inet:timeout( (Tm * (1 bsl I)) div Retry, Timer),
+query_udp(_S, _Id, _Buffer, _IP, _Port, 0, _Verbose) ->
+ timeout;
+query_udp(S, Id, Buffer, IP, Port, Timeout, Verbose) ->
?verbose(Verbose, "Try UDP server : ~p:~p (timeout=~w)\n",
- [IP, Port, Timeout]),
- udp_connect(S, IP, Port),
- udp_send(S, IP, Port, Buffer),
- query_udp_recv(S, IP, Port, Id, Timeout, Verbose).
-
-query_udp_recv(S, IP, Port, Id, Timeout, Verbose) ->
- case udp_recv(S, IP, Port, Timeout) of
- {ok,Answer,T} ->
- case decode_answer(Answer, Id, Verbose) of
- {error, badid} ->
- query_udp_recv(S, IP, Port, Id, T, Verbose);
- Reply -> Reply
+ [IP,Port,Timeout]),
+ case
+ case udp_connect(S, IP, Port) of
+ ok ->
+ udp_send(S, IP, Port, Buffer);
+ E1 ->
+ E1 end of
+ ok ->
+ Decode =
+ fun ({RecIP,RecPort,Answer})
+ when RecIP =:= IP, RecPort =:= Port ->
+ case decode_answer(Answer, Id, Verbose) of
+ {error,badid} ->
+ false;
+ Reply ->
+ Reply
+ end;
+ ({_,_,_}) ->
+ false
+ end,
+ case udp_recv(S, IP, Port, Timeout, Decode) of
+ {ok,_}=Result ->
+ Result;
+ E2 ->
+ ?verbose(Verbose, "UDP server error: ~p\n", [E2]),
+ E2
end;
- {error, timeout} when Timeout =:= 0 ->
- ?verbose(Verbose, "UDP server timeout\n", []),
- timeout;
- Error ->
- ?verbose(Verbose, "UDP server error: ~p\n", [Error]),
- Error
+ E3 ->
+ ?verbose(Verbose, "UDP send failed: ~p\n", [E3]),
+ {error,econnrefused}
end.
-query_tcp(Tm, Id, Buffer, IP, Port, Timer, Verbose) ->
- Timeout = inet:timeout(Tm*5, Timer),
+query_tcp(0, _Id, _Buffer, _IP, _Port, _Verbose) ->
+ timeout;
+query_tcp(Timeout, Id, Buffer, IP, Port, Verbose) ->
?verbose(Verbose, "Try TCP server : ~p:~p (timeout=~w)\n",
[IP, Port, Timeout]),
Family = case IP of
@@ -716,19 +932,10 @@ query_tcp(Tm, Id, Buffer, IP, Port, Timer, Verbose) ->
end;
Error ->
gen_tcp:close(S),
- case Error of
- {error, timeout} when Timeout =:= 0 ->
- ?verbose(Verbose, "TCP server recv timeout\n", []),
- timeout;
- _ ->
- ?verbose(Verbose, "TCP server recv error: ~p\n",
- [Error]),
- Error
- end
+ ?verbose(Verbose, "TCP server recv error: ~p\n",
+ [Error]),
+ Error
end;
- {error, timeout} when Timeout =:= 0 ->
- ?verbose(Verbose, "TCP server connect timeout\n", []),
- timeout;
Error ->
?verbose(Verbose, "TCP server error: ~p\n", [Error]),
Error
diff --git a/lib/kernel/src/inet_udp.erl b/lib/kernel/src/inet_udp.erl
index 9a4089ab19..60bd96f332 100644
--- a/lib/kernel/src/inet_udp.erl
+++ b/lib/kernel/src/inet_udp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -39,8 +39,10 @@ getserv(Name) when is_atom(Name) -> inet:getservbyname(Name,udp).
getaddr(Address) -> inet:getaddr(Address, inet).
getaddr(Address,Timer) -> inet:getaddr_tm(Address, inet, Timer).
+-spec open(_) -> {ok, inet:socket()} | {error, atom()}.
open(Port) -> open(Port, []).
+-spec open(_, _) -> {ok, inet:socket()} | {error, atom()}.
open(Port, Opts) ->
case inet:udp_options(
[{port,Port}, {recbuf, ?RECBUF} | Opts],
@@ -69,6 +71,8 @@ recv(S,Len) ->
recv(S,Len,Time) ->
prim_inet:recvfrom(S, Len, Time).
+-spec close(inet:socket()) -> ok.
+
close(S) ->
inet:udp_close(S).
diff --git a/lib/kernel/src/net_adm.erl b/lib/kernel/src/net_adm.erl
index 737b1ecee9..9b2dac9544 100644
--- a/lib/kernel/src/net_adm.erl
+++ b/lib/kernel/src/net_adm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,11 @@
%% Try to read .hosts.erlang file in
%% 1. cwd , 2. $HOME 3. init:root_dir()
--spec host_file() -> [atom()] | {'error',atom() | {integer(),atom(),_}}.
+-spec host_file() -> Hosts | {error, Reason} when
+ Hosts :: [Host :: atom()],
+ %% Copied from file:path_consult/2:
+ Reason :: file:posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
host_file() ->
Home = case init:get_argument(home) of
@@ -50,7 +54,8 @@ host_file() ->
%% Check whether a node is up or down
%% side effect: set up a connection to Node if there not yet is one.
--spec ping(atom()) -> 'pang' | 'pong'.
+-spec ping(Node) -> pong | pang when
+ Node :: atom().
ping(Node) when is_atom(Node) ->
case catch gen:call({net_kernel, Node},
@@ -63,7 +68,8 @@ ping(Node) when is_atom(Node) ->
pang
end.
--spec localhost() -> string().
+-spec localhost() -> Name when
+ Name :: string().
localhost() ->
{ok, Host} = inet:gethostname(),
@@ -73,12 +79,20 @@ localhost() ->
end.
--spec names() -> {'ok', [{string(), integer()}]} | {'error', _}.
+-spec names() -> {ok, [{Name, Port}]} | {error, Reason} when
+ Name :: string(),
+ Port :: non_neg_integer(),
+ Reason :: address | file:posix().
names() ->
names(localhost()).
--spec names(atom() | string()) -> {'ok', [{string(), integer()}]} | {'error', _}.
+
+-spec names(Host) -> {ok, [{Name, Port}]} | {error, Reason} when
+ Host :: atom() | string(),
+ Name :: string(),
+ Port :: non_neg_integer(),
+ Reason :: address | file:posix().
names(Hostname) ->
case inet:gethostbyname(Hostname) of
@@ -88,8 +102,9 @@ names(Hostname) ->
Else
end.
--spec dns_hostname(atom() | string()) ->
- {'ok', string()} | {'error', atom() | string()}.
+-spec dns_hostname(Host) -> {ok, Name} | {error, Host} when
+ Host :: atom() | string(),
+ Name :: string().
dns_hostname(Hostname) ->
case inet:gethostbyname(Hostname) of
@@ -164,7 +179,8 @@ collect_new(Sofar, Nodelist) ->
world() ->
world(silent).
--spec world(verbosity()) -> [node()].
+-spec world(Arg) -> [node()] when
+ Arg :: verbosity().
world(Verbose) ->
case net_adm:host_file() of
@@ -172,12 +188,15 @@ world(Verbose) ->
Hosts -> expand_hosts(Hosts, Verbose)
end.
--spec world_list([atom()]) -> [node()].
+-spec world_list(Hosts) -> [node()] when
+ Hosts :: [atom()].
world_list(Hosts) when is_list(Hosts) ->
expand_hosts(Hosts, silent).
--spec world_list([atom()], verbosity()) -> [node()].
+-spec world_list(Hosts, Arg) -> [node()] when
+ Hosts :: [atom()],
+ Arg :: verbosity().
world_list(Hosts, Verbose) when is_list(Hosts) ->
expand_hosts(Hosts, Verbose).
diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl
index 49a02359b0..9e3d730cee 100644
--- a/lib/kernel/src/net_kernel.erl
+++ b/lib/kernel/src/net_kernel.erl
@@ -145,8 +145,15 @@
%% Interface functions
kernel_apply(M,F,A) -> request({apply,M,F,A}).
+
+-spec allow(Nodes) -> ok | error when
+ Nodes :: [node()].
allow(Nodes) -> request({allow, Nodes}).
+
longnames() -> request(longnames).
+
+-spec stop() -> ok | {error, Reason} when
+ Reason :: not_allowed | not_found.
stop() -> erl_distribution:stop().
node_info(Node) -> get_node_info(Node).
@@ -158,10 +165,28 @@ i(Node) -> print_info(Node).
verbose(Level) when is_integer(Level) ->
request({verbose, Level}).
+-spec set_net_ticktime(NetTicktime, TransitionPeriod) -> Res when
+ NetTicktime :: pos_integer(),
+ TransitionPeriod :: non_neg_integer(),
+ Res :: unchanged
+ | change_initiated
+ | {ongoing_change_to, NewNetTicktime},
+ NewNetTicktime :: pos_integer().
set_net_ticktime(T, TP) when is_integer(T), T > 0, is_integer(TP), TP >= 0 ->
ticktime_res(request({new_ticktime, T*250, TP*1000})).
+
+-spec set_net_ticktime(NetTicktime) -> Res when
+ NetTicktime :: pos_integer(),
+ Res :: unchanged
+ | change_initiated
+ | {ongoing_change_to, NewNetTicktime},
+ NewNetTicktime :: pos_integer().
set_net_ticktime(T) when is_integer(T) ->
set_net_ticktime(T, ?DEFAULT_TRANSITION_PERIOD).
+
+-spec get_net_ticktime() -> Res when
+ Res :: NetTicktime | {ongoing_change_to, NetTicktime} | ignored,
+ NetTicktime :: pos_integer().
get_net_ticktime() ->
ticktime_res(request(ticktime)).
@@ -171,6 +196,9 @@ get_net_ticktime() ->
%% flags (we may want to move it elsewhere later). In order to easily
%% be backward compatible, errors are created here when process_flag()
%% fails.
+-spec monitor_nodes(Flag) -> ok | Error when
+ Flag :: boolean(),
+ Error :: error | {error, term()}.
monitor_nodes(Flag) ->
case catch process_flag(monitor_nodes, Flag) of
true -> ok;
@@ -178,6 +206,13 @@ monitor_nodes(Flag) ->
_ -> mk_monitor_nodes_error(Flag, [])
end.
+-spec monitor_nodes(Flag, Options) -> ok | Error when
+ Flag :: boolean(),
+ Options :: [Option],
+ Option :: {node_type, NodeType}
+ | nodedown_reason,
+ NodeType :: visible | hidden | all,
+ Error :: error | {error, term()}.
monitor_nodes(Flag, Opts) ->
case catch process_flag({monitor_nodes, Opts}, Flag) of
true -> ok;
@@ -209,6 +244,8 @@ publish_on_node(Node) when is_atom(Node) ->
update_publish_nodes(Ns) ->
request({update_publish_nodes, Ns}).
+-spec connect_node(Node) -> boolean() | ignored when
+ Node :: node().
%% explicit connects
connect_node(Node) when is_atom(Node) ->
request({connect, normal, Node}).
@@ -1249,7 +1286,7 @@ protocol_childspecs([H|T]) ->
epmd_module() ->
case init:get_argument(epmd_module) of
{ok,[[Module]]} ->
- Module;
+ list_to_atom(Module);
_ ->
erl_epmd
end.
diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl
index d1feae771d..f6769df585 100644
--- a/lib/kernel/src/os.erl
+++ b/lib/kernel/src/os.erl
@@ -24,7 +24,10 @@
-include("file.hrl").
--spec type() -> 'vxworks' | {'unix',atom()} | {'win32',atom()} | {'ose',atom()}.
+-spec type() -> vxworks | {Osfamily, Osname} when
+ Osfamily :: unix | win32,
+ Osname :: atom().
+
type() ->
case erlang:system_info(os_type) of
{vxworks, _} ->
@@ -32,18 +35,27 @@ type() ->
Else -> Else
end.
--spec version() -> string() | {non_neg_integer(),non_neg_integer(),non_neg_integer()}.
+-spec version() -> VersionString | {Major, Minor, Release} when
+ VersionString :: string(),
+ Major :: non_neg_integer(),
+ Minor :: non_neg_integer(),
+ Release :: non_neg_integer().
version() ->
erlang:system_info(os_version).
--spec find_executable(string()) -> string() | 'false'.
+-spec find_executable(Name) -> Filename | 'false' when
+ Name :: string(),
+ Filename :: string().
find_executable(Name) ->
case os:getenv("PATH") of
false -> find_executable(Name, []);
Path -> find_executable(Name, Path)
end.
--spec find_executable(string(), string()) -> string() | 'false'.
+-spec find_executable(Name, Path) -> Filename | 'false' when
+ Name :: string(),
+ Path :: string(),
+ Filename :: string().
find_executable(Name, Path) ->
Extensions = extensions(),
case filename:pathtype(Name) of
@@ -147,7 +159,8 @@ extensions() ->
end.
%% Executes the given command in the default shell for the operating system.
--spec cmd(atom() | string() | [string()]) -> string().
+-spec cmd(Command) -> string() when
+ Command :: atom() | io_lib:chars().
cmd(Cmd) ->
validate(Cmd),
case type() of
diff --git a/lib/kernel/src/pg2.erl b/lib/kernel/src/pg2.erl
index 956a900adc..0d5838716e 100644
--- a/lib/kernel/src/pg2.erl
+++ b/lib/kernel/src/pg2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The 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,17 +30,19 @@
%%% Exported functions
%%%
--spec start_link() -> {'ok', pid()} | {'error', term()}.
+-spec start_link() -> {'ok', pid()} | {'error', any()}.
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
--spec start() -> {'ok', pid()} | {'error', term()}.
+-spec start() -> {'ok', pid()} | {'error', any()}.
start() ->
ensure_started().
--spec create(term()) -> 'ok'.
+-type name() :: any().
+
+-spec create(Name :: name()) -> 'ok'.
create(Name) ->
ensure_started(),
@@ -55,9 +57,7 @@ create(Name) ->
ok
end.
--type name() :: term().
-
--spec delete(name()) -> 'ok'.
+-spec delete(Name :: name()) -> 'ok'.
delete(Name) ->
ensure_started(),
@@ -67,7 +67,8 @@ delete(Name) ->
end),
ok.
--spec join(name(), pid()) -> 'ok' | {'error', {'no_such_group', term()}}.
+-spec join(Name, Pid :: pid()) -> 'ok' | {'error', {'no_such_group', Name}}
+ when Name :: name().
join(Name, Pid) when is_pid(Pid) ->
ensure_started(),
@@ -83,7 +84,8 @@ join(Name, Pid) when is_pid(Pid) ->
ok
end.
--spec leave(name(), pid()) -> 'ok' | {'error', {'no_such_group', name()}}.
+-spec leave(Name, Pid :: pid()) -> 'ok' | {'error', {'no_such_group', Name}}
+ when Name :: name().
leave(Name, Pid) when is_pid(Pid) ->
ensure_started(),
@@ -99,10 +101,9 @@ leave(Name, Pid) when is_pid(Pid) ->
ok
end.
--type get_members_ret() :: [pid()] | {'error', {'no_such_group', name()}}.
+-spec get_members(Name) -> [pid()] | {'error', {'no_such_group', Name}}
+ when Name :: name().
--spec get_members(name()) -> get_members_ret().
-
get_members(Name) ->
ensure_started(),
case ets:member(pg2_table, {group, Name}) of
@@ -112,7 +113,8 @@ get_members(Name) ->
{error, {no_such_group, Name}}
end.
--spec get_local_members(name()) -> get_members_ret().
+-spec get_local_members(Name) -> [pid()] | {'error', {'no_such_group', Name}}
+ when Name :: name().
get_local_members(Name) ->
ensure_started(),
@@ -123,15 +125,15 @@ get_local_members(Name) ->
{error, {no_such_group, Name}}
end.
--spec which_groups() -> [name()].
+-spec which_groups() -> [Name :: name()].
which_groups() ->
ensure_started(),
all_groups().
--type gcp_error_reason() :: {'no_process', term()} | {'no_such_group', term()}.
-
--spec get_closest_pid(term()) -> pid() | {'error', gcp_error_reason()}.
+-spec get_closest_pid(Name) -> pid() | {'error', Reason} when
+ Name :: name(),
+ Reason :: {'no_process', Name} | {'no_such_group', Name}.
get_closest_pid(Name) ->
case get_local_members(Name) of
@@ -157,7 +159,9 @@ get_closest_pid(Name) ->
-record(state, {}).
--spec init([]) -> {'ok', #state{}}.
+-opaque state() :: #state{}.
+
+-spec init(Arg :: []) -> {'ok', state()}.
init([]) ->
Ns = nodes(),
@@ -169,13 +173,13 @@ init([]) ->
pg2_table = ets:new(pg2_table, [ordered_set, protected, named_table]),
{ok, #state{}}.
--type call() :: {'create', name()}
- | {'delete', name()}
- | {'join', name(), pid()}
- | {'leave', name(), pid()}.
-
--spec handle_call(call(), _, #state{}) ->
- {'reply', 'ok', #state{}}.
+-spec handle_call(Call :: {'create', Name}
+ | {'delete', Name}
+ | {'join', Name, Pid :: pid()}
+ | {'leave', Name, Pid :: pid()},
+ From :: {pid(),Tag :: any()},
+ State :: state()) -> {'reply', 'ok', state()}
+ when Name :: name().
handle_call({create, Name}, _From, S) ->
assure_group(Name),
@@ -195,11 +199,10 @@ handle_call(Request, From, S) ->
[Request, From]),
{noreply, S}.
--type all_members() :: [[name(),...]].
--type cast() :: {'exchange', node(), all_members()}
- | {'del_member', name(), pid()}.
-
--spec handle_cast(cast(), #state{}) -> {'noreply', #state{}}.
+-spec handle_cast(Cast :: {'exchange', node(), Names :: [[Name,...]]}
+ | {'del_member', Name, Pid :: pid()},
+ State :: state()) -> {'noreply', state()}
+ when Name :: name().
handle_cast({exchange, _Node, List}, S) ->
store(List),
@@ -208,7 +211,8 @@ handle_cast(_, S) ->
%% Ignore {del_member, Name, Pid}.
{noreply, S}.
--spec handle_info(tuple(), #state{}) -> {'noreply', #state{}}.
+-spec handle_info(Tuple :: tuple(), State :: state()) ->
+ {'noreply', state()}.
handle_info({'DOWN', MonitorRef, process, _Pid, _Info}, S) ->
member_died(MonitorRef),
@@ -222,7 +226,7 @@ handle_info({new_pg2, Node}, S) ->
handle_info(_, S) ->
{noreply, S}.
--spec terminate(term(), #state{}) -> 'ok'.
+-spec terminate(Reason :: any(), State :: state()) -> 'ok'.
terminate(_Reason, _S) ->
true = ets:delete(pg2_table),
diff --git a/lib/kernel/src/rpc.erl b/lib/kernel/src/rpc.erl
index e09acb5024..e214ffa404 100644
--- a/lib/kernel/src/rpc.erl
+++ b/lib/kernel/src/rpc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -263,14 +263,28 @@ proxy_user_flush() ->
%% THE rpc client interface
--spec call(node(), atom(), atom(), [term()]) -> term().
+-spec call(Node, Module, Function, Args) -> Res | {badrpc, Reason} when
+ Node :: node(),
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Res :: term(),
+ Reason :: term().
call(N,M,F,A) when node() =:= N -> %% Optimize local call
local_call(M, F, A);
call(N,M,F,A) ->
do_call(N, {call,M,F,A,group_leader()}, infinity).
--spec call(node(), atom(), atom(), [term()], timeout()) -> term().
+-spec call(Node, Module, Function, Args, Timeout) ->
+ Res | {badrpc, Reason} when
+ Node :: node(),
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Res :: term(),
+ Reason :: term(),
+ Timeout :: timeout().
call(N,M,F,A,_Timeout) when node() =:= N -> %% Optimize local call
local_call(M,F,A);
@@ -279,14 +293,28 @@ call(N,M,F,A,infinity) ->
call(N,M,F,A,Timeout) when is_integer(Timeout), Timeout >= 0 ->
do_call(N, {call,M,F,A,group_leader()}, Timeout).
--spec block_call(node(), atom(), atom(), [term()]) -> term().
+-spec block_call(Node, Module, Function, Args) -> Res | {badrpc, Reason} when
+ Node :: node(),
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Res :: term(),
+ Reason :: term().
block_call(N,M,F,A) when node() =:= N -> %% Optimize local call
local_call(M,F,A);
block_call(N,M,F,A) ->
do_call(N, {block_call,M,F,A,group_leader()}, infinity).
--spec block_call(node(), atom(), atom(), [term()], timeout()) -> term().
+-spec block_call(Node, Module, Function, Args, Timeout) ->
+ Res | {badrpc, Reason} when
+ Node :: node(),
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Res :: term(),
+ Reason :: term(),
+ Timeout :: timeout().
block_call(N,M,F,A,_Timeout) when node() =:= N -> %% Optimize local call
local_call(M, F, A);
@@ -339,7 +367,13 @@ rpc_check(X) -> X.
%% The entire call is packed into an atomic transaction which
%% either succeeds or fails, i.e. never hangs (unless the server itself hangs).
--spec server_call(node(), atom(), term(), term()) -> term() | {'error', 'nodedown'}.
+-spec server_call(Node, Name, ReplyWrapper, Msg) -> Reply | {error, Reason} when
+ Node :: node(),
+ Name :: atom(),
+ ReplyWrapper :: term(),
+ Msg :: term(),
+ Reply :: term(),
+ Reason :: nodedown.
server_call(Node, Name, ReplyWrapper, Msg)
when is_atom(Node), is_atom(Name) ->
@@ -362,7 +396,11 @@ server_call(Node, Name, ReplyWrapper, Msg)
end
end.
--spec cast(node(), atom(), atom(), [term()]) -> 'true'.
+-spec cast(Node, Module, Function, Args) -> true when
+ Node :: node(),
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()].
cast(Node, Mod, Fun, Args) when Node =:= node() ->
catch spawn(Mod, Fun, Args),
@@ -373,12 +411,17 @@ cast(Node, Mod, Fun, Args) ->
%% Asynchronous broadcast, returns nothing, it's just send'n prey
--spec abcast(atom(), term()) -> 'abcast'.
+-spec abcast(Name, Msg) -> abcast when
+ Name :: atom(),
+ Msg :: term().
abcast(Name, Mess) ->
abcast([node() | nodes()], Name, Mess).
--spec abcast([node()], atom(), term()) -> 'abcast'.
+-spec abcast(Nodes, Name, Msg) -> abcast when
+ Nodes :: [node()],
+ Name :: atom(),
+ Msg :: term().
abcast([Node|Tail], Name, Mess) ->
Dest = {Name,Node},
@@ -396,23 +439,39 @@ abcast([], _,_) -> abcast.
%% message when we return from the call, we can't know that they have
%% processed the message though.
--spec sbcast(atom(), term()) -> {[node()], [node()]}.
+-spec sbcast(Name, Msg) -> {GoodNodes, BadNodes} when
+ Name :: atom(),
+ Msg :: term(),
+ GoodNodes :: [node()],
+ BadNodes :: [node()].
sbcast(Name, Mess) ->
sbcast([node() | nodes()], Name, Mess).
--spec sbcast([node()], atom(), term()) -> {[node()], [node()]}.
+-spec sbcast(Nodes, Name, Msg) -> {GoodNodes, BadNodes} when
+ Name :: atom(),
+ Msg :: term(),
+ Nodes :: [node()],
+ GoodNodes :: [node()],
+ BadNodes :: [node()].
sbcast(Nodes, Name, Mess) ->
Monitors = send_nodes(Nodes, ?NAME, {sbcast, Name, Mess}, []),
rec_nodes(?NAME, Monitors).
--spec eval_everywhere(atom(), atom(), [term()]) -> 'abcast'.
+-spec eval_everywhere(Module, Function, Args) -> abcast when
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()].
eval_everywhere(Mod, Fun, Args) ->
eval_everywhere([node() | nodes()] , Mod, Fun, Args).
--spec eval_everywhere([node()], atom(), atom(), [term()]) -> 'abcast'.
+-spec eval_everywhere(Nodes, Module, Function, Args) -> abcast when
+ Nodes :: [node()],
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()].
eval_everywhere(Nodes, Mod, Fun, Args) ->
gen_server:abcast(Nodes, ?NAME, {cast,Mod,Fun,Args,group_leader()}).
@@ -453,20 +512,45 @@ unmonitor(Ref) when is_reference(Ref) ->
%% Call apply(M,F,A) on all nodes in parallel
--spec multicall(atom(), atom(), [term()]) -> {[_], [node()]}.
+-spec multicall(Module, Function, Args) -> {ResL, BadNodes} when
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ ResL :: [term()],
+ BadNodes :: [node()].
multicall(M, F, A) ->
multicall(M, F, A, infinity).
--spec multicall([node()], atom(), atom(), [term()]) -> {[_], [node()]}
- ; (atom(), atom(), [term()], timeout()) -> {[_], [node()]}.
+-spec multicall(Nodes, Module, Function, Args) -> {ResL, BadNodes} when
+ Nodes :: [node()],
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ ResL :: [term()],
+ BadNodes :: [node()];
+ (Module, Function, Args, Timeout) -> {ResL, BadNodes} when
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Timeout :: timeout(),
+ ResL :: [term()],
+ BadNodes :: [node()].
multicall(Nodes, M, F, A) when is_list(Nodes) ->
multicall(Nodes, M, F, A, infinity);
multicall(M, F, A, Timeout) ->
multicall([node() | nodes()], M, F, A, Timeout).
--spec multicall([node()], atom(), atom(), [term()], timeout()) -> {[_], [node()]}.
+-spec multicall(Nodes, Module, Function, Args, Timeout) ->
+ {ResL, BadNodes} when
+ Nodes :: [node()],
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Timeout :: timeout(),
+ ResL :: [term()],
+ BadNodes :: [node()].
multicall(Nodes, M, F, A, infinity)
when is_list(Nodes), is_atom(M), is_atom(F), is_list(A) ->
@@ -495,12 +579,21 @@ do_multicall(Nodes, M, F, A, Timeout) ->
%%
%% There is no apparent order among the replies.
--spec multi_server_call(atom(), term()) -> {[_], [node()]}.
+-spec multi_server_call(Name, Msg) -> {Replies, BadNodes} when
+ Name :: atom(),
+ Msg :: term(),
+ Replies :: [Reply :: term()],
+ BadNodes :: [node()].
multi_server_call(Name, Msg) ->
multi_server_call([node() | nodes()], Name, Msg).
--spec multi_server_call([node()], atom(), term()) -> {[_], [node()]}.
+-spec multi_server_call(Nodes, Name, Msg) -> {Replies, BadNodes} when
+ Nodes :: [node()],
+ Name :: atom(),
+ Msg :: term(),
+ Replies :: [Reply :: term()],
+ BadNodes :: [node()].
multi_server_call(Nodes, Name, Msg)
when is_list(Nodes), is_atom(Name) ->
@@ -509,9 +602,22 @@ multi_server_call(Nodes, Name, Msg)
%% Deprecated functions. Were only needed when communicating with R6 nodes.
+-spec safe_multi_server_call(Name, Msg) -> {Replies, BadNodes} when
+ Name :: atom(),
+ Msg :: term(),
+ Replies :: [Reply :: term()],
+ BadNodes :: [node()].
+
safe_multi_server_call(Name, Msg) ->
multi_server_call(Name, Msg).
+-spec safe_multi_server_call(Nodes, Name, Msg) -> {Replies, BadNodes} when
+ Nodes :: [node()],
+ Name :: atom(),
+ Msg :: term(),
+ Replies :: [Reply :: term()],
+ BadNodes :: [node()].
+
safe_multi_server_call(Nodes, Name, Msg) ->
multi_server_call(Nodes, Name, Msg).
@@ -539,7 +645,14 @@ rec_nodes(Name, [{N,R} | Tail], Badnodes, Replies) ->
%% rpc's towards the same node. I.e. it returns immediately and
%% it returns a Key that can be used in a subsequent yield(Key).
--spec async_call(node(), atom(), atom(), [term()]) -> pid().
+-opaque key() :: pid().
+
+-spec async_call(Node, Module, Function, Args) -> Key when
+ Node :: node(),
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Key :: key().
async_call(Node, Mod, Fun, Args) ->
ReplyTo = self(),
@@ -549,20 +662,28 @@ async_call(Node, Mod, Fun, Args) ->
ReplyTo ! {self(), {promise_reply, R}} %% self() is key
end).
--spec yield(pid()) -> term().
+-spec yield(Key) -> Res | {badrpc, Reason} when
+ Key :: key(),
+ Res :: term(),
+ Reason :: term().
yield(Key) when is_pid(Key) ->
{value,R} = do_yield(Key, infinity),
R.
--spec nb_yield(pid(), timeout()) -> {'value', _} | 'timeout'.
+-spec nb_yield(Key, Timeout) -> {value, Val} | timeout when
+ Key :: key(),
+ Timeout :: timeout(),
+ Val :: (Res :: term()) | {badrpc, Reason :: term()}.
nb_yield(Key, infinity=Inf) when is_pid(Key) ->
do_yield(Key, Inf);
nb_yield(Key, Timeout) when is_pid(Key), is_integer(Timeout), Timeout >= 0 ->
do_yield(Key, Timeout).
--spec nb_yield(pid()) -> {'value', _} | 'timeout'.
+-spec nb_yield(Key) -> {value, Val} | timeout when
+ Key :: key(),
+ Val :: (Res :: term()) | {badrpc, Reason :: term()}.
nb_yield(Key) when is_pid(Key) ->
do_yield(Key, 0).
@@ -582,7 +703,12 @@ do_yield(Key, Timeout) ->
%% ArgL === [{M,F,Args},........]
%% Returns a lists of the evaluations in the same order as
%% given to ArgL
--spec parallel_eval([{atom(), atom(), [_]}]) -> [_].
+-spec parallel_eval(FuncCalls) -> ResL when
+ FuncCalls :: [{Module, Function, Args}],
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ ResL :: [term()].
parallel_eval(ArgL) ->
Nodes = [node() | nodes()],
@@ -599,7 +725,13 @@ map_nodes([{M,F,A}|Tail],[Node|MoreNodes], Original) ->
%% Parallel version of lists:map/3 with exactly the same
%% arguments and return value as lists:map/3,
%% except that it calls exit/1 if a network error occurs.
--spec pmap({atom(),atom()}, [term()], [term()]) -> [term()].
+-spec pmap(FuncSpec, ExtraArgs, List1) -> List2 when
+ FuncSpec :: {Module,Function},
+ Module :: module(),
+ Function :: atom(),
+ ExtraArgs :: [term()],
+ List1 :: [Elem :: term()],
+ List2 :: [term()].
pmap({M,F}, As, List) ->
check(parallel_eval(build_args(M,F,As, List, [])), []).
@@ -616,15 +748,20 @@ check([], Ack) -> Ack.
%% location transparent version of process_info
--spec pinfo(pid()) -> [{atom(), _}] | 'undefined'.
+-spec pinfo(Pid) -> [{Item, Info}] | undefined when
+ Pid :: pid(),
+ Item :: atom(),
+ Info :: term().
pinfo(Pid) when node(Pid) =:= node() ->
process_info(Pid);
pinfo(Pid) ->
call(node(Pid), erlang, process_info, [Pid]).
--spec pinfo(pid(), Item) -> {Item, _} | 'undefined' | []
- when is_subtype(Item, atom()).
+-spec pinfo(Pid, Item) -> {Item, Info} | undefined | [] when
+ Pid :: pid(),
+ Item :: atom(),
+ Info :: term().
pinfo(Pid, Item) when node(Pid) =:= node() ->
process_info(Pid, Item);
diff --git a/lib/kernel/src/seq_trace.erl b/lib/kernel/src/seq_trace.erl
index 78c3040f21..a90b7b07c8 100644
--- a/lib/kernel/src/seq_trace.erl
+++ b/lib/kernel/src/seq_trace.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The 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,15 +38,17 @@
-type flag() :: 'send' | 'receive' | 'print' | 'timestamp'.
-type component() :: 'label' | 'serial' | flag().
--type value() :: non_neg_integer()
- | {non_neg_integer(), non_neg_integer()}
- | boolean().
--type token_pair() :: {component(), value()}.
+-type value() :: (Integer :: non_neg_integer())
+ | {Previous :: non_neg_integer(),
+ Current :: non_neg_integer()}
+ | (Bool :: boolean()).
%%---------------------------------------------------------------------------
--type token() :: [] | {integer(), boolean(), _, _, _}.
--spec set_token(token()) -> token() | 'ok'.
+-type token() :: {integer(), boolean(), _, _, _}.
+-spec set_token(Token) -> PreviousToken | 'ok' when
+ Token :: [] | token(),
+ PreviousToken :: [] | token().
set_token([]) ->
erlang:seq_trace(sequential_trace_token,[]);
@@ -58,28 +60,35 @@ set_token({Flags,Label,Serial,_From,Lastcnt}) ->
%% expects that, the BIF can however "unofficially" handle atoms as well, and
%% atoms can be used if only Erlang nodes are involved
--spec set_token(component(), value()) -> token_pair().
+-spec set_token(Component, Val) -> {Component, OldVal} when
+ Component :: component(),
+ Val :: value(),
+ OldVal :: value().
set_token(Type, Val) ->
erlang:seq_trace(Type, Val).
--spec get_token() -> term().
+-spec get_token() -> [] | token().
get_token() ->
element(2,process_info(self(),sequential_trace_token)).
--spec get_token(component()) -> token_pair().
-
+-spec get_token(Component) -> {Component, Val} when
+ Component :: component(),
+ Val :: value().
get_token(Type) ->
erlang:seq_trace_info(Type).
--spec print(term()) -> 'ok'.
+-spec print(TraceInfo) -> 'ok' when
+ TraceInfo :: term().
print(Term) ->
erlang:seq_trace_print(Term),
ok.
--spec print(integer(), term()) -> 'ok'.
+-spec print(Label, TraceInfo) -> 'ok' when
+ Label :: integer(),
+ TraceInfo :: term().
print(Label, Term) when is_atom(Label) ->
erlang:error(badarg, [Label, Term]);
@@ -94,14 +103,17 @@ reset_trace() ->
%% reset_trace(Pid) -> % this might be a useful function too
--type tracer() :: pid() | port() | 'false'.
+-type tracer() :: (Pid :: pid()) | port() | 'false'.
--spec set_system_tracer(tracer()) -> tracer().
+-spec set_system_tracer(Tracer) -> OldTracer when
+ Tracer :: tracer(),
+ OldTracer :: tracer().
set_system_tracer(Pid) ->
erlang:system_flag(sequential_tracer, Pid).
--spec get_system_tracer() -> tracer().
+-spec get_system_tracer() -> Tracer when
+ Tracer :: tracer().
get_system_tracer() ->
element(2, erlang:system_info(sequential_tracer)).
diff --git a/lib/kernel/src/wrap_log_reader.erl b/lib/kernel/src/wrap_log_reader.erl
index fabaa07752..c41e0091e4 100644
--- a/lib/kernel/src/wrap_log_reader.erl
+++ b/lib/kernel/src/wrap_log_reader.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -41,6 +41,8 @@
first_no :: non_neg_integer() | 'one' % first read file number
}).
+-opaque continuation() :: #wrap_reader{}.
+
%%
%% Exported functions
%%
@@ -50,9 +52,11 @@
%% is not yet reached, we are on the first 'round' of filling the wrap
%% files.
--type open_ret() :: {'ok', #wrap_reader{}} | {'error', tuple()}.
+-type open_ret() :: {'ok', Continuation :: continuation()}
+ | {'error', Reason :: tuple()}.
--spec open(atom() | string()) -> open_ret().
+-spec open(Filename) -> open_ret() when
+ Filename :: string() | atom().
open(File) when is_atom(File) ->
open(atom_to_list(File));
@@ -77,7 +81,9 @@ open(File) when is_list(File) ->
Error
end.
--spec open(atom() | string(), integer()) -> open_ret().
+-spec open(Filename, N) -> open_ret() when
+ Filename :: string() | atom(),
+ N :: integer().
open(File, FileNo) when is_atom(File), is_integer(FileNo) ->
open(atom_to_list(File), FileNo);
@@ -100,22 +106,29 @@ open(File, FileNo) when is_list(File), is_integer(FileNo) ->
Error
end.
--spec close(#wrap_reader{}) -> 'ok' | {'error', atom()}.
+-spec close(Continuation) -> 'ok' | {'error', Reason} when
+ Continuation :: continuation(),
+ Reason :: file:posix().
close(#wrap_reader{fd = FD}) ->
file:close(FD).
--type chunk_ret() :: {#wrap_reader{}, [term()]}
- | {#wrap_reader{}, [term()], non_neg_integer()}
- | {#wrap_reader{}, 'eof'}
- | {'error', term()}.
+-type chunk_ret() :: {Continuation2, Terms :: [term()]}
+ | {Continuation2,
+ Terms :: [term()],
+ Badbytes :: non_neg_integer()}
+ | {Continuation2, 'eof'}
+ | {'error', Reason :: term()}.
--spec chunk(#wrap_reader{}) -> chunk_ret().
+-spec chunk(Continuation) -> chunk_ret() when
+ Continuation :: continuation().
chunk(WR = #wrap_reader{}) ->
chunk(WR, ?MAX_CHUNK_SIZE, 0).
--spec chunk(#wrap_reader{}, 'infinity' | pos_integer()) -> chunk_ret().
+-spec chunk(Continuation, N) -> chunk_ret() when
+ Continuation :: continuation(),
+ N :: infinity | pos_integer().
chunk(WR = #wrap_reader{}, infinity) ->
chunk(WR, ?MAX_CHUNK_SIZE, 0);
diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile
index 5f8f3a6bf6..82bc3fc6d1 100644
--- a/lib/kernel/test/Makefile
+++ b/lib/kernel/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2010. All Rights Reserved.
+# Copyright Ericsson AB 1997-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -144,7 +144,7 @@ release_tests_spec: make_emakefile
$(INSTALL_DATA) $(APP_FILES) $(RELSYSDIR)
$(INSTALL_DATA) kernel.spec $(EMAKEFILE)\
$(COVERFILE) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/kernel/test/application_SUITE.erl b/lib/kernel/test/application_SUITE.erl
index 4ae4151004..2c5b8ccb66 100644
--- a/lib/kernel/test/application_SUITE.erl
+++ b/lib/kernel/test/application_SUITE.erl
@@ -967,7 +967,7 @@ otp_1586(doc) ->
["Test recursive load of applications."];
otp_1586(Conf) when is_list(Conf) ->
Dir = ?config(priv_dir,Conf),
- {ok, Fd} = file:open(filename:join(Dir, "app5.app"), write),
+ {ok, Fd} = file:open(filename:join(Dir, "app5.app"), [write]),
w_app5(Fd),
file:close(Fd),
?line code:add_patha(Dir),
@@ -1021,10 +1021,10 @@ otp_2012(Conf) when is_list(Conf) ->
?line yes = global:register_name(conf_change, CcPid),
% Write a .app file
- {ok, Fd} = file:open("app1.app", write),
+ {ok, Fd} = file:open("app1.app", [write]),
w_app1(Fd),
file:close(Fd),
- {ok, Fd2} = file:open("app2.app", write),
+ {ok, Fd2} = file:open("app2.app", [write]),
w_app1(Fd2),
file:close(Fd2),
@@ -1096,7 +1096,7 @@ otp_2973(doc) ->
["Test of two processes simultanously starting the same application."];
otp_2973(Conf) when is_list(Conf) ->
% Write a .app file
- {ok, Fd} = file:open("app0.app", write),
+ {ok, Fd} = file:open("app0.app", [write]),
w_app(Fd, app0()),
file:close(Fd),
@@ -1138,7 +1138,7 @@ otp_2973(Conf) when is_list(Conf) ->
% Write a .app file
- ?line {ok, Fda} = file:open("app_start_error.app", write),
+ ?line {ok, Fda} = file:open("app_start_error.app", [write]),
?line w_app_start_error(Fda),
?line file:close(Fda),
@@ -1273,12 +1273,12 @@ otp_4066(Conf) when is_list(Conf) ->
App1Nodes = {app1, AllNodes},
Dir = ?config(priv_dir,Conf),
- ?line {ok, FdC} = file:open(filename:join(Dir, "otp_4066.config"), write),
+ ?line {ok, FdC} = file:open(filename:join(Dir, "otp_4066.config"), [write]),
?line write_config(FdC, config_4066(AllNodes, 5000, [App1Nodes])),
?line file:close(FdC),
% Write the app1.app file
- ?line {ok, FdA12} = file:open(filename:join(Dir, "app1.app"), write),
+ ?line {ok, FdA12} = file:open(filename:join(Dir, "app1.app"), [write]),
?line w_app1(FdA12),
?line file:close(FdA12),
@@ -1441,7 +1441,7 @@ otp_5606(Conf) when is_list(Conf) ->
%% Write a config file
Dir = ?config(priv_dir, Conf),
- {ok, Fd} = file:open(filename:join(Dir, "sys.config"), write),
+ {ok, Fd} = file:open(filename:join(Dir, "sys.config"), [write]),
NodeNames = [Ncp1, Ncp2] = node_names([cp1, cp2], Conf),
(config4(NodeNames))(Fd, 10000),
file:close(Fd),
@@ -2436,7 +2436,7 @@ start_node_config_sf(Name, SysConfigFun, Conf) ->
write_config_file(SysConfigFun, Conf) ->
Dir = ?config(priv_dir, Conf),
- {ok, Fd} = file:open(filename:join(Dir, "sys.config"), write),
+ {ok, Fd} = file:open(filename:join(Dir, "sys.config"), [write]),
SysConfigFun(Fd),
file:close(Fd),
filename:join(Dir,"sys").
@@ -2571,15 +2571,15 @@ cc(List) ->
create_app() ->
?line Dir = "./",
?line App1 = Dir ++ "app1",
- ?line {ok, Fd1} = file:open(App1++".app",write),
+ ?line {ok, Fd1} = file:open(App1++".app",[write]),
?line io:format(Fd1, "~p. \n", [app1()]),
?line file:close(Fd1),
?line App2 = Dir ++ "app2",
- ?line {ok, Fd2} = file:open(App2++".app",write),
+ ?line {ok, Fd2} = file:open(App2++".app",[write]),
?line io:format(Fd2, "~p. \n", [app2()]),
?line file:close(Fd2),
?line App3 = Dir ++ "app_sp",
- ?line {ok, Fd3} = file:open(App3++".app",write),
+ ?line {ok, Fd3} = file:open(App3++".app",[write]),
?line io:format(Fd3, "~p. \n", [app_sp()]),
?line file:close(Fd3),
ok.
@@ -2591,7 +2591,7 @@ create_script(ScriptName) ->
?line Apps = which_applications(),
?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
- ?line {ok,Fd} = file:open(Name++".rel",write),
+ ?line {ok,Fd} = file:open(Name++".rel",[write]),
?line io:format(Fd,
"{release, {\"Test release 3\", \"LATEST\"}, \n"
" {erts, \"4.4\"}, \n"
@@ -2610,7 +2610,7 @@ create_script_dc(ScriptName) ->
?line Apps = which_applications(),
?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
- ?line {ok,Fd} = file:open(Name++".rel",write),
+ ?line {ok,Fd} = file:open(Name++".rel",[write]),
?line io:format(Fd,
"{release, {\"Test release 3\", \"LATEST\"}, \n"
" {erts, \"4.4\"}, \n"
@@ -2630,7 +2630,7 @@ create_script_3002(ScriptName) ->
?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
?line {value,{_,_,SaslVer}} = lists:keysearch(sasl,1,Apps),
- ?line {ok,Fd} = file:open(Name++".rel",write),
+ ?line {ok,Fd} = file:open(Name++".rel",[write]),
?line io:format(Fd,
"{release, {\"Test release 3\", \"LATEST\"}, \n"
" {erts, \"4.4\"}, \n"
@@ -2646,22 +2646,22 @@ create_script_3002(ScriptName) ->
distr_changed_prep(Conf) when is_list(Conf) ->
% Write .app files
- ?line {ok, Fd1} = file:open("app1.app", write),
+ ?line {ok, Fd1} = file:open("app1.app", [write]),
?line w_app1(Fd1),
?line file:close(Fd1),
- ?line {ok, Fd2} = file:open("app2.app", write),
+ ?line {ok, Fd2} = file:open("app2.app", [write]),
?line w_app2(Fd2),
?line file:close(Fd2),
- ?line {ok, Fd3} = file:open("app3.app", write),
+ ?line {ok, Fd3} = file:open("app3.app", [write]),
?line w_app3(Fd3),
?line file:close(Fd3),
- ?line {ok, Fd4} = file:open("app6.app", write),
+ ?line {ok, Fd4} = file:open("app6.app", [write]),
?line w_app6(Fd4),
?line file:close(Fd4),
- ?line {ok, Fd5} = file:open("app7.app", write),
+ ?line {ok, Fd5} = file:open("app7.app", [write]),
?line w_app7(Fd5),
?line file:close(Fd5),
- ?line {ok, Fd6} = file:open("app8.app", write),
+ ?line {ok, Fd6} = file:open("app8.app", [write]),
?line w_app8(Fd6),
?line file:close(Fd6),
@@ -2683,7 +2683,7 @@ distr_changed_prep(Conf) when is_list(Conf) ->
WithSyncTime = config_fun(config_dc(NodeNames)),
?line Dir = ?config(priv_dir,Conf),
- ?line {ok, Fd_dc2} = file:open(filename:join(Dir, "sys2.config"), write),
+ ?line {ok, Fd_dc2} = file:open(filename:join(Dir, "sys2.config"), [write]),
?line (config_dc2(NodeNames))(Fd_dc2),
?line file:close(Fd_dc2),
?line Config2 = filename:join(Dir, "sys2"),
diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl
index 3ad49254f1..10ab3e4370 100644
--- a/lib/kernel/test/code_SUITE.erl
+++ b/lib/kernel/test/code_SUITE.erl
@@ -81,6 +81,13 @@ init_per_suite(Config) ->
end_per_suite(Config) ->
Config.
+init_per_testcase(big_boot_embedded, Config) ->
+ case catch crypto:start() of
+ ok ->
+ init_per_testcase(do_big_boot_embedded, Config);
+ _Else ->
+ {skip, "Needs crypto!"}
+ end;
init_per_testcase(_Func, Config) ->
Dog=?t:timetrap(?t:minutes(5)),
P=code:get_path(),
@@ -258,8 +265,8 @@ replace_path(Config) when is_list(Config) ->
%% Add a completly new application.
- NewAppName = "blurf_blarfer",
- ?line NewAppDir = filename:join(Cwd, NewAppName ++ "-6.33.1"),
+ NewAppName = 'blurf_blarfer',
+ ?line NewAppDir = filename:join(Cwd, atom_to_list(NewAppName) ++ "-6.33.1"),
?line ok = file:make_dir(NewAppDir),
?line true = code:replace_path(NewAppName, NewAppDir),
?line NewAppDir = code:lib_dir(NewAppName),
@@ -410,8 +417,10 @@ all_loaded_1() ->
?line Loaded2 = match_and_remove(Preloaded, Loaded1),
ObjExt = code:objfile_extension(),
- ?line [] = lists:filter(fun({Mod,AbsName}) when is_atom(Mod), is_list(AbsName) ->
- Mod =:= filename:basename(AbsName, ObjExt);
+ ?line [] = lists:filter(fun({Mod,AbsName}) when is_atom(Mod),
+ is_list(AbsName) ->
+ Mod =/= list_to_atom(filename:basename(AbsName,
+ ObjExt));
(_) -> true
end,
Loaded2),
@@ -571,11 +580,13 @@ add_del_path(Config) when is_list(Config) ->
clash(Config) when is_list(Config) ->
DDir = ?config(data_dir,Config)++"clash/",
P = code:get_path(),
+ [TestServerPath|_] = [Path || Path <- code:get_path(),
+ re:run(Path,"test_server/?$",[]) /= nomatch],
%% test non-clashing entries
- %% remove "." to prevent clash with test-server path
- ?line true = code:del_path("."),
+ %% remove TestServerPath to prevent clash with test-server path
+ ?line true = code:del_path(TestServerPath),
?line true = code:add_path(DDir++"foobar-0.1/ebin"),
?line true = code:add_path(DDir++"zork-0.8/ebin"),
test_server:capture_start(),
@@ -587,8 +598,8 @@ clash(Config) when is_list(Config) ->
%% test clashing entries
- %% remove "." to prevent clash with test-server path
- ?line true = code:del_path("."),
+ %% remove TestServerPath to prevent clash with test-server path
+ ?line true = code:del_path(TestServerPath),
?line true = code:add_path(DDir++"foobar-0.1/ebin"),
?line true = code:add_path(DDir++"foobar-0.1.ez/foobar-0.1/ebin"),
test_server:capture_start(),
@@ -601,9 +612,9 @@ clash(Config) when is_list(Config) ->
%% test "Bad path can't read"
- %% remove "." to prevent clash with test-server path
+ %% remove TestServerPath to prevent clash with test-server path
Priv = ?config(priv_dir, Config),
- ?line true = code:del_path("."),
+ ?line true = code:del_path(TestServerPath),
TmpEzFile = Priv++"foobar-0.tmp.ez",
?line {ok, _} = file:copy(DDir++"foobar-0.1.ez", TmpEzFile),
?line true = code:add_path(TmpEzFile++"/foobar-0.1/ebin"),
@@ -984,9 +995,9 @@ purge_stacktrace(Config) when is_list(Config) ->
error:function_clause ->
?line code:load_file(code_b_test),
?line case erlang:get_stacktrace() of
- [{?MODULE,_,[a]},
- {code_b_test,call,2},
- {?MODULE,purge_stacktrace,1}|_] ->
+ [{?MODULE,_,[a],_},
+ {code_b_test,call,2,_},
+ {?MODULE,purge_stacktrace,1,_}|_] ->
?line false = code:purge(code_b_test),
?line [] = erlang:get_stacktrace()
end
@@ -996,8 +1007,8 @@ purge_stacktrace(Config) when is_list(Config) ->
error:function_clause ->
?line code:load_file(code_b_test),
?line case erlang:get_stacktrace() of
- [{code_b_test,call,[nofun,2]},
- {?MODULE,purge_stacktrace,1}|_] ->
+ [{code_b_test,call,[nofun,2],_},
+ {?MODULE,purge_stacktrace,1,_}|_] ->
?line false = code:purge(code_b_test),
?line [] = erlang:get_stacktrace()
end
@@ -1008,8 +1019,8 @@ purge_stacktrace(Config) when is_list(Config) ->
error:badarg ->
?line code:load_file(code_b_test),
?line case erlang:get_stacktrace() of
- [{code_b_test,call,Args},
- {?MODULE,purge_stacktrace,1}|_] ->
+ [{code_b_test,call,Args,_},
+ {?MODULE,purge_stacktrace,1,_}|_] ->
?line false = code:purge(code_b_test),
?line [] = erlang:get_stacktrace()
end
@@ -1023,8 +1034,8 @@ mult_lib_roots(Config) when is_list(Config) ->
"my_dummy_app-c/ebin/code_SUITE_mult_root_module"),
%% Set up ERL_LIBS and start a slave node.
- ErlLibs = filename:join(DataDir, first_root) ++ mult_lib_sep() ++
- filename:join(DataDir, second_root),
+ ErlLibs = filename:join(DataDir, "first_root") ++ mult_lib_sep() ++
+ filename:join(DataDir, "second_root"),
?line {ok,Node} =
?t:start_node(mult_lib_roots, slave,
@@ -1344,7 +1355,7 @@ create_script(Config) ->
?line Apps = application_controller:which_applications(),
?line {value,{_,_,KernelVer}} = lists:keysearch(kernel, 1, Apps),
?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib, 1, Apps),
- ?line {ok,Fd} = file:open(Name ++ ".rel", write),
+ ?line {ok,Fd} = file:open(Name ++ ".rel", [write]),
?line io:format(Fd,
"{release, {\"Test release 3\", \"P2A\"}, \n"
" {erts, \"9.42\"}, \n"
@@ -1409,7 +1420,7 @@ create_big_script(Config,Local) ->
%% Now we should have only "real" applications...
?line [application:load(list_to_atom(Y)) || {match,[Y]} <- [ re:run(X,code:lib_dir()++"/"++"([^/-]*).*/ebin",[{capture,[1],list}]) || X <- code:get_path()],filter_app(Y,Local)],
?line Apps = [ {N,V} || {N,_,V} <- application:loaded_applications()],
- ?line {ok,Fd} = file:open(Name ++ ".rel", write),
+ ?line {ok,Fd} = file:open(Name ++ ".rel", [write]),
?line io:format(Fd,
"{release, {\"Test release 3\", \"P2A\"}, \n"
" {erts, \"9.42\"}, \n"
@@ -1470,7 +1481,7 @@ do_on_load_error(ReturnValue) ->
?line ErrorPid ! ReturnValue,
receive
{'DOWN',Ref,process,_,Exit} ->
- ?line {undef,[{on_load_error,main,[]}|_]} = Exit
+ ?line {undef,[{on_load_error,main,[],_}|_]} = Exit
end.
native_early_modules(suite) -> [];
diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl
index 4ae47b4762..ad987fe7a7 100644
--- a/lib/kernel/test/disk_log_SUITE.erl
+++ b/lib/kernel/test/disk_log_SUITE.erl
@@ -1831,11 +1831,16 @@ block_queue2(Conf) when is_list(Conf) ->
%% Asynchronous stuff is ignored.
?line ok = disk_log:balog_terms(n, [<<"foo">>,<<"bar">>]),
?line ok = disk_log:balog_terms(n, [<<"more">>,<<"terms">>]),
+ Parent = self(),
?line Fun =
- fun() -> {error,disk_log_stopped} = disk_log:sync(n)
+ fun() ->
+ {error,no_such_log} = disk_log:sync(n),
+ receive {disk_log, _, {error, disk_log_stopped}} -> ok end,
+ Parent ! disk_log_stopped_ok
end,
?line spawn(Fun),
?line ok = sync_do(Pid, close),
+ ?line receive disk_log_stopped_ok -> ok end,
?line sync_do(Pid, terminate),
?line {ok,<<>>} = file:read_file(File ++ ".1"),
?line del(File, No),
@@ -2708,7 +2713,7 @@ error_log(Conf) when is_list(Conf) ->
% reopen (rename) fails, the log is terminated, ./File.2/ exists
?line {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
{format, external},{size, 100000}]),
- ?line {error, eisdir} = disk_log:reopen(n, LDir),
+ ?line {error, {file_error, _, eisdir}} = disk_log:reopen(n, LDir),
?line true = (P0 == pps()),
?line file:delete(File),
@@ -2719,7 +2724,7 @@ error_log(Conf) when is_list(Conf) ->
?line {ok, n} = disk_log:open([{name, n}, {file, File2}, {type, wrap},
{format, external},{size, {100, No}}]),
?line ok = disk_log:blog_terms(n, [B,B,B]),
- ?line {error, eisdir} = disk_log:reopen(n, File),
+ ?line {error, {file_error, _, eisdir}} = disk_log:reopen(n, File),
?line {error, no_such_log} = disk_log:close(n),
?line del(File2, No),
?line del(File, No),
@@ -4917,7 +4922,7 @@ mark(FileName, What) ->
ok = file:close(Fd).
crash(File, Where) ->
- {ok, Fd} = file:open(File, read_write),
+ {ok, Fd} = file:open(File, [read,write]),
file:position(Fd, Where),
ok = file:write(Fd, [10]),
ok = file:close(Fd).
@@ -4933,7 +4938,7 @@ writable(Fname) ->
file:write_file_info(Fname, Info#file_info{mode = Mode}).
truncate(File, Where) ->
- {ok, Fd} = file:open(File, read_write),
+ {ok, Fd} = file:open(File, [read,write]),
file:position(Fd, Where),
ok = file:truncate(Fd),
ok = file:close(Fd).
diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl
index f47c4603cf..7599a89779 100644
--- a/lib/kernel/test/erl_prim_loader_SUITE.erl
+++ b/lib/kernel/test/erl_prim_loader_SUITE.erl
@@ -547,8 +547,6 @@ host() ->
stop_node(Node) ->
test_server:stop_node(Node).
-get_loader_flag({ose,_}) ->
- " -loader ose_inet ";
get_loader_flag(_) ->
" -loader inet ".
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index 8078c7d021..77fc7e73f9 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -360,41 +360,50 @@ make_del_dir(Config) when is_list(Config) ->
?line {error, eexist} = ?FILE_MODULE:make_dir(NewDir),
?line ok = ?FILE_MODULE:del_dir(NewDir),
?line {error, enoent} = ?FILE_MODULE:del_dir(NewDir),
-
- %% Check that we get an error when trying to create...
- %% a deep directory
- ?line NewDir2 = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_mk-dir/foo"),
- ?line {error, enoent} = ?FILE_MODULE:make_dir(NewDir2),
- %% a nameless directory
- ?line {error, enoent} = ?FILE_MODULE:make_dir(""),
- %% a directory with illegal name
- ?line {error, badarg} = ?FILE_MODULE:make_dir({1,2,3}),
-
- %% a directory with illegal name, even if it's a (bad) list
- ?line {error, badarg} = ?FILE_MODULE:make_dir([1,2,3,{}]),
-
- %% Maybe this isn't an error, exactly, but worth mentioning anyway:
- %% ok = ?FILE_MODULE:make_dir([$f,$o,$o,0,$b,$a,$r])),
- %% The above line works, and created a directory "./foo"
- %% More elegant would maybe have been to fail, or to really create
- %% a directory, but with a name that incorporates the "bar" part of
- %% the list, so that [$f,$o,$o,0,$f,$o,$o] wouldn't refer to the same
- %% dir. But this would slow it down.
-
- %% Try deleting some bad directories
- %% Deleting the parent directory to the current, sounds dangerous, huh?
- %% Don't worry ;-) the parent directory should never be empty, right?
- case ?FILE_MODULE:del_dir('..') of
- {error, eexist} -> ok;
- {error, einval} -> ok %FreeBSD
+ % Make sure we are not in a directory directly under test_server
+ % as that would result in eacess errors when trying to delere '..',
+ % because there are processes having that directory as current.
+ ?line ok = ?FILE_MODULE:make_dir(NewDir),
+ ?line {ok,CurrentDir} = file:get_cwd(),
+ ?line ok = ?FILE_MODULE:set_cwd(NewDir),
+ try
+ %% Check that we get an error when trying to create...
+ %% a deep directory
+ ?line NewDir2 = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_mk-dir-noexist/foo"),
+ ?line {error, enoent} = ?FILE_MODULE:make_dir(NewDir2),
+ %% a nameless directory
+ ?line {error, enoent} = ?FILE_MODULE:make_dir(""),
+ %% a directory with illegal name
+ ?line {error, badarg} = ?FILE_MODULE:make_dir({1,2,3}),
+
+ %% a directory with illegal name, even if it's a (bad) list
+ ?line {error, badarg} = ?FILE_MODULE:make_dir([1,2,3,{}]),
+
+ %% Maybe this isn't an error, exactly, but worth mentioning anyway:
+ %% ok = ?FILE_MODULE:make_dir([$f,$o,$o,0,$b,$a,$r])),
+ %% The above line works, and created a directory "./foo"
+ %% More elegant would maybe have been to fail, or to really create
+ %% a directory, but with a name that incorporates the "bar" part of
+ %% the list, so that [$f,$o,$o,0,$f,$o,$o] wouldn't refer to the same
+ %% dir. But this would slow it down.
+
+ %% Try deleting some bad directories
+ %% Deleting the parent directory to the current, sounds dangerous, huh?
+ %% Don't worry ;-) the parent directory should never be empty, right?
+ ?line case ?FILE_MODULE:del_dir('..') of
+ {error, eexist} -> ok;
+ {error, einval} -> ok %FreeBSD
+ end,
+ ?line {error, enoent} = ?FILE_MODULE:del_dir(""),
+ ?line {error, badarg} = ?FILE_MODULE:del_dir([3,2,1,{}]),
+
+ ?line [] = flush(),
+ ?line test_server:timetrap_cancel(Dog)
+ after
+ ?FILE_MODULE:set_cwd(CurrentDir)
end,
- ?line {error, enoent} = ?FILE_MODULE:del_dir(""),
- ?line {error, badarg} = ?FILE_MODULE:del_dir([3,2,1,{}]),
-
- ?line [] = flush(),
- ?line test_server:timetrap_cancel(Dog),
ok.
cur_dir_0(suite) -> [];
@@ -2055,6 +2064,10 @@ try_read_file_list(Fd) ->
?line Title = "Real Programmers Don't Use PASCAL</TITLE>\n",
?line Title = io:get_line(Fd, ''),
+ %% Seek past the end of the file.
+
+ ?line {ok, _} = ?FILE_MODULE:position(Fd, 25000),
+
%% Done.
?line ?FILE_MODULE:close(Fd),
@@ -2152,7 +2165,7 @@ write_compressed(Config) when is_list(Config) ->
?line Second = io:get_line(Fd1, ''),
?line ok = ?FILE_MODULE:close(Fd1),
- %% Verify succesful compression by uncompressing the file
+ %% Verify successful compression by uncompressing the file
%% using zlib:gunzip/1.
?line {ok,Contents} = file:read_file(MyFile),
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index 03e734445c..1b534a5fc4 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -212,7 +212,9 @@ xfer_active(Config) when is_list(Config) ->
?line test_server:fail({unexpected,flush()})
end,
?line io:format("SbAssocId=~p~n", [SbAssocId]),
- ?line ok = gen_sctp:send(Sa, SaAssocId, 0, Data),
+ ?line ok =
+ do_from_other_process(
+ fun () -> gen_sctp:send(Sa, SaAssocId, 0, Data) end),
?line receive
{sctp,Sb,Loopback,Pa,
{[#sctp_sndrcvinfo{stream=Stream,
@@ -378,11 +380,14 @@ def_sndrcvinfo(Config) when is_list(Config) ->
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
+ do_from_other_process(
+ fun () ->
+ gen_sctp:send(
+ S2,
+ #sctp_sndrcvinfo{stream=0, ppid=20, assoc_id=S2AssocId},
+ <<"4: ",Data/binary>>)
+ end),
+ ?line case ok(do_from_other_process(fun() -> gen_sctp:recv(S1) end)) of
{Loopback,P2,
[#sctp_sndrcvinfo{
stream=0, ppid=20, context=0, assoc_id=S1AssocId}],
@@ -575,6 +580,8 @@ api_opts(doc) ->
api_opts(suite) ->
[];
api_opts(Config) when is_list(Config) ->
+ ?line Sndbuf = 32768,
+ ?line Recbuf = 65536,
?line {ok,S} = gen_sctp:open(0),
?line OSType = os:type(),
?line case {inet:setopts(S, [{linger,{true,2}}]),OSType} of
@@ -582,7 +589,15 @@ api_opts(Config) when is_list(Config) ->
ok;
{{error,einval},{unix,sunos}} ->
ok
- end.
+ end,
+ ?line ok = inet:setopts(S, [{sndbuf,Sndbuf}]),
+ ?line ok = inet:setopts(S, [{recbuf,Recbuf}]),
+ ?line case inet:getopts(S, [sndbuf]) of
+ {ok,[{sndbuf,SB}]} when SB >= Sndbuf -> ok
+ end,
+ ?line case inet:getopts(S, [recbuf]) of
+ {ok,[{recbuf,RB}]} when RB >= Recbuf -> ok
+ end.
implicit_inet6(Config) when is_list(Config) ->
?line Hostname = ok(inet:gethostname()),
@@ -638,3 +653,31 @@ implicit_inet6(S1, Addr) ->
{{0,0,0,0,0,0,0,0},P2} -> ok
end,
?line ok = gen_sctp:close(S2).
+
+
+
+do_from_other_process(Fun) ->
+ Parent = self(),
+ Ref = make_ref(),
+ Child =
+ spawn(fun () ->
+ try Fun() of
+ Result ->
+ Parent ! {Ref,Result}
+ catch
+ Class:Reason ->
+ Stacktrace = erlang:get_stacktrace(),
+ Parent ! {Ref,Class,Reason,Stacktrace}
+ end
+ end),
+ Mref = erlang:monitor(process, Child),
+ receive
+ {Ref,Result} ->
+ receive {'DOWN',Mref,_,_,_} -> Result end;
+ {Ref,Class,Reason,Stacktrace} ->
+ receive {'DOWN',Mref,_,_,_} ->
+ erlang:raise(Class, Reason, Stacktrace)
+ end;
+ {'DOWN',Mref,_,_,Reason} ->
+ erlang:exit(Reason)
+ end.
diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl
index fd4685cdad..cbaec2d6dd 100644
--- a/lib/kernel/test/gen_tcp_api_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_api_SUITE.erl
@@ -158,6 +158,10 @@ t_shutdown_error(Config) when is_list(Config) ->
t_fdopen(Config) when is_list(Config) ->
?line Question = "Aaaa... Long time ago in a small town in Germany,",
+ ?line Question1 = list_to_binary(Question),
+ ?line Question2 = [<<"Aaaa">>, "... ", $L, <<>>, $o, "ng time ago ",
+ ["in ", [], <<"a small town">>, [" in Germany,", <<>>]]],
+ ?line Question1 = iolist_to_binary(Question2),
?line Answer = "there was a shoemaker, Schumacher was his name.",
?line {ok, L} = gen_tcp:listen(0, [{active, false}]),
?line {ok, Port} = inet:port(L),
@@ -167,6 +171,10 @@ t_fdopen(Config) when is_list(Config) ->
?line {ok, Server} = gen_tcp:fdopen(FD, []),
?line ok = gen_tcp:send(Client, Question),
?line {ok, Question} = gen_tcp:recv(Server, length(Question), 2000),
+ ?line ok = gen_tcp:send(Client, Question1),
+ ?line {ok, Question} = gen_tcp:recv(Server, length(Question), 2000),
+ ?line ok = gen_tcp:send(Client, Question2),
+ ?line {ok, Question} = gen_tcp:recv(Server, length(Question), 2000),
?line ok = gen_tcp:send(Server, Answer),
?line {ok, Answer} = gen_tcp:recv(Client, length(Answer), 2000),
?line ok = gen_tcp:close(Client),
diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl
index d8a5519195..514deaf065 100644
--- a/lib/kernel/test/gen_udp_SUITE.erl
+++ b/lib/kernel/test/gen_udp_SUITE.erl
@@ -201,13 +201,21 @@ binary_passive_recv(suite) ->
binary_passive_recv(doc) ->
["OTP-3823 gen_udp:recv does not return address in binary mode"];
binary_passive_recv(Config) when is_list(Config) ->
- ?line D = "The quick brown fox jumps over a lazy dog",
- ?line B = list_to_binary(D),
+ ?line D1 = "The quick brown fox jumps over a lazy dog",
+ ?line D2 = list_to_binary(D1),
+ ?line D3 = ["The quick", <<" brown ">>, "fox jumps ", <<"over ">>,
+ <<>>, $a, [[], " lazy ", <<"dog">>]],
+ ?line D2 = iolist_to_binary(D3),
+ ?line B = D2,
?line {ok, R} = gen_udp:open(0, [binary, {active, false}]),
?line {ok, RP} = inet:port(R),
?line {ok, S} = gen_udp:open(0),
?line {ok, SP} = inet:port(S),
- ?line ok = gen_udp:send(S, localhost, RP, D),
+ ?line ok = gen_udp:send(S, localhost, RP, D1),
+ ?line {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1),
+ ?line ok = gen_udp:send(S, localhost, RP, D2),
+ ?line {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1),
+ ?line ok = gen_udp:send(S, localhost, RP, D3),
?line {ok, {{127, 0, 0, 1}, SP, B}} = gen_udp:recv(R, byte_size(B)+1),
?line ok = gen_udp:close(S),
?line ok = gen_udp:close(R),
@@ -400,6 +408,7 @@ open_fd(Config) when is_list(Config) ->
{ok,S1} = gen_udp:open(0),
{ok,P2} = inet:port(S1),
{ok,FD} = prim_inet:getfd(S1),
+ {error,einval} = gen_udp:open(P2, [inet6, {fd,FD}]),
{ok,S2} = gen_udp:open(P2, [{fd,FD}]),
{ok,S3} = gen_udp:open(0),
{ok,P3} = inet:port(S3),
diff --git a/lib/kernel/test/global_group_SUITE.erl b/lib/kernel/test/global_group_SUITE.erl
index 13b2fd07b5..799b0d9d05 100644
--- a/lib/kernel/test/global_group_SUITE.erl
+++ b/lib/kernel/test/global_group_SUITE.erl
@@ -100,7 +100,7 @@ start_gg_proc(Config) when is_list(Config) ->
?line Dir = ?config(priv_dir, Config),
?line File = filename:join(Dir, "global_group.config"),
- ?line {ok, Fd}=file:open(File, write),
+ ?line {ok, Fd}=file:open(File, [write]),
[Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config),
?line config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"),
@@ -135,7 +135,7 @@ no_gg_proc(Config) when is_list(Config) ->
?line Dir = ?config(priv_dir, Config),
?line File = filename:join(Dir, "no_global_group.config"),
- ?line {ok, Fd} = file:open(File, write),
+ ?line {ok, Fd} = file:open(File, [write]),
?line config_no(Fd),
?line NN = node_name(atom_to_list(node())),
@@ -308,7 +308,7 @@ no_gg_proc_sync(Config) when is_list(Config) ->
?line Dir = ?config(priv_dir, Config),
?line File = filename:join(Dir, "no_global_group_sync.config"),
- ?line {ok, Fd} = file:open(File, write),
+ ?line {ok, Fd} = file:open(File, [write]),
[Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz] =
node_names([cp1,cp2,cp3,cpx,cpy,cpz], Config),
@@ -482,7 +482,7 @@ compatible(Config) when is_list(Config) ->
?line Dir = ?config(priv_dir, Config),
?line File = filename:join(Dir, "global_group_comp.config"),
- ?line {ok, Fd} = file:open(File, write),
+ ?line {ok, Fd} = file:open(File, [write]),
[Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz] =
node_names([cp1,cp2,cp3,cpx,cpy,cpz], Config),
@@ -655,7 +655,7 @@ one_grp(Config) when is_list(Config) ->
?line Dir = ?config(priv_dir, Config),
?line File = filename:join(Dir, "global_group.config"),
- ?line {ok, Fd} = file:open(File, write),
+ ?line {ok, Fd} = file:open(File, [write]),
[Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config),
?line config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"),
@@ -742,7 +742,7 @@ one_grp_x(Config) when is_list(Config) ->
?line Dir = ?config(priv_dir, Config),
?line File = filename:join(Dir, "global_group.config"),
- ?line {ok, Fd} = file:open(File, write),
+ ?line {ok, Fd} = file:open(File, [write]),
[Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config),
?line config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"),
@@ -804,7 +804,7 @@ two_grp(Config) when is_list(Config) ->
?line Dir = ?config(priv_dir, Config),
?line File = filename:join(Dir, "global_group.config"),
- ?line {ok, Fd} = file:open(File, write),
+ ?line {ok, Fd} = file:open(File, [write]),
[Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz,Ncpq] =
node_names([cp1,cp2,cp3,cpx,cpy,cpz,cpq], Config),
@@ -1104,7 +1104,7 @@ hidden_groups(Config) when is_list(Config) ->
?line Dir = ?config(priv_dir, Config),
?line File = filename:join(Dir, "global_group.config"),
- ?line {ok, Fd} = file:open(File, write),
+ ?line {ok, Fd} = file:open(File, [write]),
[Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz,Ncpq] =
node_names([cp1,cp2,cp3,cpx,cpy,cpz,cpq], Config),
diff --git a/lib/kernel/test/heart_SUITE.erl b/lib/kernel/test/heart_SUITE.erl
index 043c753cf8..233e438dc9 100644
--- a/lib/kernel/test/heart_SUITE.erl
+++ b/lib/kernel/test/heart_SUITE.erl
@@ -22,7 +22,7 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2, start/1, restart/1,
- reboot/1, set_cmd/1, clear_cmd/1,
+ reboot/1, set_cmd/1, clear_cmd/1, get_cmd/1,
dont_drop/1, kill_pid/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
@@ -58,7 +58,7 @@ end_per_testcase(_Func, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [start, restart, reboot, set_cmd, clear_cmd, kill_pid].
+ [start, restart, reboot, set_cmd, clear_cmd, get_cmd, kill_pid].
groups() ->
[].
@@ -246,6 +246,15 @@ clear_cmd(Config) when is_list(Config) ->
end,
ok.
+get_cmd(suite) -> [];
+get_cmd(Config) when is_list(Config) ->
+ ?line {ok, Node} = start_check(slave, heart_test),
+ Cmd = "test",
+ ?line ok = rpc:call(Node, heart, set_cmd, [Cmd]),
+ ?line {ok, Cmd} = rpc:call(Node, heart, get_cmd, []),
+ stop_node(Node),
+ ok.
+
dont_drop(suite) ->
%%% Removed as it may crash epmd/distribution in colourful
%%% ways. While we ARE finding out WHY, it would
diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl
index 1bb173a3ac..aaa20b7398 100644
--- a/lib/kernel/test/inet_SUITE.erl
+++ b/lib/kernel/test/inet_SUITE.erl
@@ -294,7 +294,7 @@ t_getaddr_v6(Config) when is_list(Config) ->
?line {Name,FullName,IPStr,_IP,_,IP_46_Str,IP46} =
ct:get_config(test_host_ipv4_only),
case {inet:getaddr(IP_46_Str, inet6),inet:getaddr(Name, inet6)} of
- {{ok,IP46},{ok,_}} ->
+ {{ok,IP46},{ok,V4Addr}} when V4Addr /= {0,0,0,0,0,0,0,1} ->
%% Since we suceeded in parsing an IPv6 address string and
%% look up the name, this computer fully supports IPv6.
?line {ok,IP46} = inet:getaddr(IP46, inet6),
diff --git a/lib/kernel/test/inet_res_SUITE.erl b/lib/kernel/test/inet_res_SUITE.erl
index 5fc8df475d..8a3d220e46 100644
--- a/lib/kernel/test/inet_res_SUITE.erl
+++ b/lib/kernel/test/inet_res_SUITE.erl
@@ -27,7 +27,8 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
init_per_testcase/2, end_per_testcase/2]).
--export([basic/1, resolve/1, edns0/1, txt_record/1, files_monitor/1]).
+-export([basic/1, resolve/1, edns0/1, txt_record/1, files_monitor/1,
+ last_ms_answer/1]).
-export([
gethostbyaddr/0, gethostbyaddr/1,
gethostbyaddr_v6/0, gethostbyaddr_v6/1,
@@ -45,6 +46,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[basic, resolve, edns0, txt_record, files_monitor,
+ last_ms_answer,
gethostbyaddr, gethostbyaddr_v6, gethostbyname,
gethostbyname_v6, getaddr, getaddr_v6, ipv4_to_ipv6,
host_and_addr].
@@ -64,16 +66,15 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-zone_dir(basic) ->
- otptest;
-zone_dir(resolve) ->
- otptest;
-zone_dir(edns0) ->
- otptest;
-zone_dir(files_monitor) ->
- otptest;
-zone_dir(_) ->
- undefined.
+zone_dir(TC) ->
+ case TC of
+ basic -> otptest;
+ resolve -> otptest;
+ edns0 -> otptest;
+ files_monitor -> otptest;
+ last_ms_answer -> otptest;
+ _ -> undefined
+ end.
init_per_testcase(Func, Config) ->
PrivDir = ?config(priv_dir, Config),
@@ -116,9 +117,15 @@ ns_init(ZoneDir, PrivDir, DataDir) ->
case os:type() of
{unix,_} when ZoneDir =:= undefined -> undefined;
{unix,_} ->
- {ok,S} = gen_udp:open(0, [{reuseaddr,true}]),
- {ok,PortNum} = inet:port(S),
- gen_udp:close(S),
+ PortNum = case {os:type(),os:version()} of
+ {{unix,solaris},{M,V,_}} when M =< 5, V < 10 ->
+ 11895 + random:uniform(100);
+ _ ->
+ {ok,S} = gen_udp:open(0, [{reuseaddr,true}]),
+ {ok,PNum} = inet:port(S),
+ gen_udp:close(S),
+ PNum
+ end,
RunNamed = filename:join(DataDir, ?RUN_NAMED),
NS = {{127,0,0,1},PortNum},
P = erlang:open_port({spawn_executable,RunNamed},
@@ -184,6 +191,88 @@ ns_printlog(Fname) ->
ok
end.
+%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Behaviour modifying nameserver proxy
+
+proxy_start(TC, {NS,P}) ->
+ Tag = make_ref(),
+ Parent = self(),
+ Pid =
+ spawn_link(
+ fun () ->
+ try proxy_start(TC, NS, P, Parent, Tag)
+ catch C:X ->
+ io:format(
+ "~w: ~w:~p ~p~n",
+ [self(),C,X,erlang:get_stacktrace()])
+ end
+ end),
+ receive {started,Tag,Port} ->
+ ProxyNS = {{127,0,0,1},Port},
+ {proxy,Pid,Tag,ProxyNS}
+ end.
+
+proxy_start(TC, NS, P, Parent, Tag) ->
+ {ok,Outbound} = gen_udp:open(0, [binary]),
+ ok = gen_udp:connect(Outbound, NS, P),
+ {ok,Inbound} = gen_udp:open(0, [binary]),
+ {ok,Port} = inet:port(Inbound),
+ Parent ! {started,Tag,Port},
+ proxy(TC, Outbound, NS, P, Inbound).
+
+
+%% To provoke the last_ms_answer bug (OTP-9221) the proxy
+%% * Relays the query to the right nameserver
+%% * Intercepts the reply but holds it until the timer that
+%% was started when receiving the query fires.
+%% * Repeats the reply with incorrect query ID a number of
+%% times with a short interval.
+%% * Sends the correct reply, to give a correct test result
+%% after bug correction.
+%%
+%% The repetition of an incorrect answer with tight interval will keep
+%% inet_res in an inner loop in the code that decrements the remaining
+%% time until it hits 0 which triggers a crash, if the outer timeout
+%% parameter to inet_res:resolve is so short that it runs out during
+%% these repetitions.
+proxy(last_ms_answer, Outbound, NS, P, Inbound) ->
+ receive
+ {udp,Inbound,SrcIP,SrcPort,Data} ->
+ Time =
+ inet_db:res_option(timeout) div inet_db:res_option(retry),
+ Tag = erlang:make_ref(),
+ erlang:send_after(Time - 10, self(), {time,Tag}),
+ ok = gen_udp:send(Outbound, NS, P, Data),
+ receive
+ {udp,Outbound,NS,P,Reply} ->
+ {ok,Msg} = inet_dns:decode(Reply),
+ Hdr = inet_dns:msg(Msg, header),
+ Id = inet_dns:header(Hdr, id),
+ BadHdr =
+ inet_dns:make_header(Hdr, id, (Id+1) band 16#ffff),
+ BadMsg = inet_dns:make_msg(Msg, header, BadHdr),
+ BadReply = inet_dns:encode(BadMsg),
+ receive
+ {time,Tag} ->
+ proxy__last_ms_answer(
+ Inbound, SrcIP, SrcPort, BadReply, Reply, 30)
+ end
+ end
+ end.
+
+proxy__last_ms_answer(Socket, IP, Port, _, Reply, 0) ->
+ ok = gen_udp:send(Socket, IP, Port, Reply);
+proxy__last_ms_answer(Socket, IP, Port, BadReply, Reply, N) ->
+ ok = gen_udp:send(Socket, IP, Port, BadReply),
+ receive after 1 -> ok end,
+ proxy__last_ms_answer(Socket, IP, Port, BadReply, Reply, N-1).
+
+proxy_wait({proxy,Pid,_,_}) ->
+ Mref = erlang:monitor(process, Pid),
+ receive {'DOWN',Mref,_,_,_} -> ok end.
+
+proxy_ns({proxy,_,_,ProxyNS}) -> ProxyNS.
+
%%
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -204,7 +293,7 @@ basic(Config) when is_list(Config) ->
{ok,Msg1} = inet_dns:decode(Bin1),
%%
%% resolve
- {ok,Msg2} = inet_res:resolve(Name, in, a, [{nameservers,[NS]}]),
+ {ok,Msg2} = inet_res:resolve(Name, in, a, [{nameservers,[NS]},verbose]),
io:format("~p~n", [Msg2]),
[RR2] = inet_dns:msg(Msg2, anlist),
IP = inet_dns:rr(RR2, data),
@@ -474,6 +563,26 @@ do_files_monitor(Config) ->
ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+last_ms_answer(doc) ->
+ ["Answer just when timeout is triggered (OTP-9221)"];
+last_ms_answer(Config) when is_list(Config) ->
+ NS = ns(Config),
+ Name = "ns.otptest",
+ %%IP = {127,0,0,254},
+ Time = inet_db:res_option(timeout) div inet_db:res_option(retry),
+ PSpec = proxy_start(last_ms_answer, NS),
+ ProxyNS = proxy_ns(PSpec),
+ %%
+ %% resolve; whith short timeout to trigger Timeout =:= 0 in inet_res
+ {error,timeout} =
+ inet_res:resolve(
+ Name, in, a, [{nameservers,[ProxyNS]},verbose], Time + 10),
+ %%
+ proxy_wait(PSpec),
+ ok.
+
+%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Compatibility tests. Call the inet_SUITE tests, but with
%% lookup = [file,dns] instead of [native]
diff --git a/lib/kernel/test/inet_res_SUITE_data/run-named b/lib/kernel/test/inet_res_SUITE_data/run-named
index b418607d48..7caa3756ef 100755
--- a/lib/kernel/test/inet_res_SUITE_data/run-named
+++ b/lib/kernel/test/inet_res_SUITE_data/run-named
@@ -2,7 +2,7 @@
##
## %CopyrightBegin%
##
-## Copyright Ericsson AB 2009. All Rights Reserved.
+## Copyright Ericsson AB 2009-2011. All Rights Reserved.
##
## The contents of this file are subject to the Erlang Public License,
## Version 1.1, (the "License"); you may not use this file except in
@@ -155,7 +155,7 @@ $NAMED $NAMED_FG -c "$CONF_FILE" >"$LOG_FILE" 2>&1 </dev/null &
NAMED=$!
trap "kill -TERM $NAMED >/dev/null 2>&1; wait $NAMED >/dev/null 2>&1" \
0 1 2 3 15
-sleep 1 # Give name server time to load its zone files
+sleep 2 # Give name server time to load its zone files
echo "Running: Enter \`\`quit'' to terminate nameserver[$NAMED]..."
while read LINE; do
test :"$LINE" = :'quit' && break
diff --git a/lib/kernel/test/init_SUITE.erl b/lib/kernel/test/init_SUITE.erl
index 2db0f7dcb8..b39fadd65f 100644
--- a/lib/kernel/test/init_SUITE.erl
+++ b/lib/kernel/test/init_SUITE.erl
@@ -656,7 +656,7 @@ create_script(Config) ->
?line Apps = application_controller:which_applications(),
?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
- ?line {ok,Fd} = file:open(Name ++ ".rel", write),
+ ?line {ok,Fd} = file:open(Name ++ ".rel", [write]),
?line io:format(Fd,
"{release, {\"Test release 3\", \"P2A\"}, \n"
" {erts, \"4.4\"}, \n"
diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl
index a04ea3cdcd..00eda6292f 100644
--- a/lib/kernel/test/prim_file_SUITE.erl
+++ b/lib/kernel/test/prim_file_SUITE.erl
@@ -250,39 +250,49 @@ make_del_dir(Config, Handle, Suffix) ->
?line ok = ?PRIM_FILE_call(del_dir, Handle, [NewDir]),
?line {error, enoent} = ?PRIM_FILE_call(del_dir, Handle, [NewDir]),
- %% Check that we get an error when trying to create...
- %% a deep directory
- ?line NewDir2 = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_mk-dir/foo"),
- ?line {error, enoent} = ?PRIM_FILE_call(make_dir, Handle, [NewDir2]),
- %% a nameless directory
- ?line {error, enoent} = ?PRIM_FILE_call(make_dir, Handle, [""]),
- %% a directory with illegal name
- ?line {error, badarg} = ?PRIM_FILE_call(make_dir, Handle, ['mk-dir']),
-
- %% a directory with illegal name, even if it's a (bad) list
- ?line {error, badarg} = ?PRIM_FILE_call(make_dir, Handle, [[1,2,3,{}]]),
-
- %% Maybe this isn't an error, exactly, but worth mentioning anyway:
- %% ok = ?PRIM_FILE:make_dir([$f,$o,$o,0,$b,$a,$r])),
- %% The above line works, and created a directory "./foo"
- %% More elegant would maybe have been to fail, or to really create
- %% a directory, but with a name that incorporates the "bar" part of
- %% the list, so that [$f,$o,$o,0,$f,$o,$o] wouldn't refer to the same
- %% dir. But this would slow it down.
-
- %% Try deleting some bad directories
- %% Deleting the parent directory to the current, sounds dangerous, huh?
- %% Don't worry ;-) the parent directory should never be empty, right?
- case ?PRIM_FILE_call(del_dir, Handle, [".."]) of
- {error, eexist} -> ok;
- {error, einval} -> ok %FreeBSD
+ % Make sure we are not in a directory directly under test_server
+ % as that would result in eacess errors when trying to delere '..',
+ % because there are processes having that directory as current.
+ ?line ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]),
+ ?line {ok, CurrentDir} = ?PRIM_FILE_call(get_cwd, Handle, []),
+ ?line ok = ?PRIM_FILE_call(set_cwd, Handle, [NewDir]),
+ try
+ %% Check that we get an error when trying to create...
+ %% a deep directory
+ ?line NewDir2 = filename:join(RootDir,
+ atom_to_list(?MODULE)
+ ++"_mk-dir-noexist/foo"),
+ ?line {error, enoent} = ?PRIM_FILE_call(make_dir, Handle, [NewDir2]),
+ %% a nameless directory
+ ?line {error, enoent} = ?PRIM_FILE_call(make_dir, Handle, [""]),
+ %% a directory with illegal name
+ ?line {error, badarg} = ?PRIM_FILE_call(make_dir, Handle, ['mk-dir']),
+
+ %% a directory with illegal name, even if it's a (bad) list
+ ?line {error, badarg} = ?PRIM_FILE_call(make_dir, Handle, [[1,2,3,{}]]),
+
+ %% Maybe this isn't an error, exactly, but worth mentioning anyway:
+ %% ok = ?PRIM_FILE:make_dir([$f,$o,$o,0,$b,$a,$r])),
+ %% The above line works, and created a directory "./foo"
+ %% More elegant would maybe have been to fail, or to really create
+ %% a directory, but with a name that incorporates the "bar" part of
+ %% the list, so that [$f,$o,$o,0,$f,$o,$o] wouldn't refer to the same
+ %% dir. But this would slow it down.
+
+ %% Try deleting some bad directories
+ %% Deleting the parent directory to the current, sounds dangerous, huh?
+ %% Don't worry ;-) the parent directory should never be empty, right?
+ ?line case ?PRIM_FILE_call(del_dir, Handle, [".."]) of
+ {error, eexist} -> ok;
+ {error, einval} -> ok %FreeBSD
+ end,
+ ?line {error, enoent} = ?PRIM_FILE_call(del_dir, Handle, [""]),
+ ?line {error, badarg} = ?PRIM_FILE_call(del_dir, Handle, [[3,2,1,{}]]),
+
+ ?line test_server:timetrap_cancel(Dog)
+ after
+ ?line ok = ?PRIM_FILE_call(set_cwd, Handle, [CurrentDir])
end,
- ?line {error, enoent} = ?PRIM_FILE_call(del_dir, Handle, [""]),
- ?line {error, badarg} = ?PRIM_FILE_call(del_dir, Handle, [[3,2,1,{}]]),
-
- ?line test_server:timetrap_cancel(Dog),
ok.
cur_dir_0a(suite) -> [];
diff --git a/lib/kernel/test/ram_file_SUITE.erl b/lib/kernel/test/ram_file_SUITE.erl
index 9b3fbb91fc..ab95a3ff5f 100644
--- a/lib/kernel/test/ram_file_SUITE.erl
+++ b/lib/kernel/test/ram_file_SUITE.erl
@@ -552,7 +552,7 @@ large_file_light(Config) when is_list(Config) ->
?line PrivDir = ?config(priv_dir, Config),
%% Marker for next test case that is to heavy to run in a suite.
?line ok = ?FILE_MODULE:write_file(
- filename:join(PrivDir, large_file_light),
+ filename:join(PrivDir, "large_file_light"),
<<"TAG">>),
%%
?line Data = "abcdefghijklmnopqrstuvwzyz",
@@ -582,7 +582,7 @@ large_file_heavy(Config) when is_list(Config) ->
?line PrivDir = ?config(priv_dir, Config),
%% Check previous test case marker.
case ?FILE_MODULE:read_file_info(
- filename:join(PrivDir, large_file_light)) of
+ filename:join(PrivDir, "large_file_light")) of
{ok,_} ->
{skipped,"Too heavy for casual testing!"};
_ ->
diff --git a/lib/kernel/test/zlib_SUITE.erl b/lib/kernel/test/zlib_SUITE.erl
index 9eb84c9167..74bafe8935 100644
--- a/lib/kernel/test/zlib_SUITE.erl
+++ b/lib/kernel/test/zlib_SUITE.erl
@@ -42,8 +42,8 @@
end
end()).
--define(BARG, {'EXIT',{badarg,[{zlib,_,_}|_]}}).
--define(DATA_ERROR, {'EXIT',{data_error,[{zlib,_,_}|_]}}).
+-define(BARG, {'EXIT',{badarg,[{zlib,_,_,_}|_]}}).
+-define(DATA_ERROR, {'EXIT',{data_error,[{zlib,_,_,_}|_]}}).
init_per_testcase(_Func, Config) ->
Dog = test_server:timetrap(test_server:seconds(60)),
@@ -412,6 +412,7 @@ api_crc32(Config) when is_list(Config) ->
Compressed = list_to_binary(Compressed1 ++ Compressed2),
CRC1 = ?m( CRC1 when is_integer(CRC1), zlib:crc32(Z1)),
?m(CRC1 when is_integer(CRC1), zlib:crc32(Z1,Bin)),
+ ?m(CRC1 when is_integer(CRC1), zlib:crc32(Z1,binary_to_list(Bin))),
?m(CRC2 when is_integer(CRC2), zlib:crc32(Z1,Compressed)),
CRC2 = ?m(CRC2 when is_integer(CRC2), zlib:crc32(Z1,0,Compressed)),
?m(CRC3 when CRC2 /= CRC3, zlib:crc32(Z1,234,Compressed)),
@@ -437,6 +438,7 @@ api_adler32(Config) when is_list(Config) ->
Compressed2 = ?m(_, zlib:deflate(Z1, <<>>, finish)),
Compressed = list_to_binary(Compressed1 ++ Compressed2),
?m(ADLER1 when is_integer(ADLER1), zlib:adler32(Z1,Bin)),
+ ?m(ADLER1 when is_integer(ADLER1), zlib:adler32(Z1,binary_to_list(Bin))),
ADLER2 = ?m(ADLER2 when is_integer(ADLER2), zlib:adler32(Z1,Compressed)),
?m(ADLER2 when is_integer(ADLER2), zlib:adler32(Z1,1,Compressed)),
?m(ADLER3 when ADLER2 /= ADLER3, zlib:adler32(Z1,234,Compressed)),
@@ -464,6 +466,7 @@ api_un_compress(Config) when is_list(Config) ->
?m({'EXIT',{data_error,_}}, zlib:uncompress(<<120,156,3>>)),
?m({'EXIT',{data_error,_}}, zlib:uncompress(<<120,156,3,0>>)),
?m({'EXIT',{data_error,_}}, zlib:uncompress(<<0,156,3,0,0,0,0,1>>)),
+ ?m(Bin, zlib:uncompress(binary_to_list(Comp))),
?m(Bin, zlib:uncompress(Comp)).
api_un_zip(doc) -> "Test zip";
@@ -472,10 +475,12 @@ api_un_zip(Config) when is_list(Config) ->
?m(?BARG,zlib:zip(not_a_binary)),
Bin = <<1,11,1,23,45>>,
?line Comp = zlib:zip(Bin),
+ ?m(Comp, zlib:zip(binary_to_list(Bin))),
?m(?BARG,zlib:unzip(not_a_binary)),
?m({'EXIT',{data_error,_}}, zlib:unzip(<<171,171,171,171,171>>)),
?m({'EXIT',{data_error,_}}, zlib:unzip(<<>>)),
?m(Bin, zlib:unzip(Comp)),
+ ?m(Bin, zlib:unzip(binary_to_list(Comp))),
%% OTP-6396
B = <<131,104,19,100,0,13,99,95,99,105,100,95,99,115,103,115,110,95,50,97,1,107,0,4,208,161,246,29,107,0,3,237,166,224,107,0,6,66,240,153,0,2,10,1,0,8,97,116,116,97,99,104,101,100,104,2,100,0,22,117,112,100,97,116,101,95,112,100,112,95,99,111,110,116,101,120,116,95,114,101,113,107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104,12,3,197,31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64,104,116,73,64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,5,0,33,4,4,10,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,1,114,45,97,112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99,50,52,48,4,103,112,114,115,8,0,104,2,104,2,100,0,8,97,99,116,105,118,97,116,101,104,23,100,0,11,112,100,112,95,99,111,110,116,1,120,116,100,0,7,112,114,105,109,97,114,121,97,1,100,0,9,117,110,100,101,102,105,110,101,100,97,1,97,4,97,4,97,7,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,10100,100,0,9,117,110,100,101,102,105,110,101,100,100,0,5,102,97,108,115,101,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,1,101,100,97,0,100,0,9,117,110,100,101,102,105,110,101,100,107,0,4,16,0,1,144,107,0,4,61,139,186,181,107,0,4,10,8,201,49,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,0,101,100,100,0,9,117,110,100,101,102,105,110,101,100,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,21,106,108,0,0,0,3,104,2,97,1,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,167,20,104,2,97,4,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,21,104,2,97,10,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,26,106,100,0,5,118,101,114,57,57,100,0,9,117,110,0,101,102,105,110,101,100,107,0,2,0,244,107,0,4,10,6,102,195,107,0,4,10,6,102,195,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,107,0,125,248,143,0,203,25115,157,116,65,185,65,172,55,87,164,88,225,50,203,251,115,157,116,65,185,65,172,55,87,164,88,225,50,0,0,82,153,50,0,200,98,87,148,237,193,185,65,149,167,69,144,14,16,153,50,3,81,70,94,13,109,193,1,120,5,181,113,198,118,50,3,81,70,94,13,109,193,185,120,5,181,113,198,118,153,3,81,70,94,13,109,193,185,120,5,181,113,198,118,153,50,16,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,113,92,2,119,128,0,0,108,0,0,1,107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104,12,3,11,97,31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64,104,116,73,64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,0,33,4,4,10,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,101,114,45,97,112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99,50,52,48,4,103,112,114,115,8,0,106>>,
@@ -504,10 +509,12 @@ api_g_un_zip(Config) when is_list(Config) ->
?m(?BARG,zlib:gzip(not_a_binary)),
Bin = <<1,11,1,23,45>>,
?line Comp = zlib:gzip(Bin),
+ ?m(Comp, zlib:gzip(binary_to_list(Bin))),
?m(?BARG, zlib:gunzip(not_a_binary)),
?m(?DATA_ERROR, zlib:gunzip(<<171,171,171,171,171>>)),
?m(?DATA_ERROR, zlib:gunzip(<<>>)),
?m(Bin, zlib:gunzip(Comp)),
+ ?m(Bin, zlib:gunzip(binary_to_list(Comp))),
%% Bad CRC; bad length.
BadCrc = bad_crc_data(),
@@ -844,6 +851,7 @@ dictionary_usage({run}) ->
?m(ok, zlib:inflateInit(Z2)),
?line {'EXIT',{{need_dictionary,DictID},_}} = (catch zlib:inflate(Z2, Compressed)),
?m(ok, zlib:inflateSetDictionary(Z2, Dict)),
+ ?m(ok, zlib:inflateSetDictionary(Z2, binary_to_list(Dict))),
?line Uncompressed = ?m(B when is_list(B), zlib:inflate(Z2, [])),
?m(ok, zlib:inflateEnd(Z2)),
?m(ok, zlib:close(Z2)),
diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk
index e7b71cc168..76c62ece67 100644
--- a/lib/kernel/vsn.mk
+++ b/lib/kernel/vsn.mk
@@ -1 +1 @@
-KERNEL_VSN = 2.14.4
+KERNEL_VSN = 2.15
diff --git a/lib/megaco/doc/src/megaco.xml b/lib/megaco/doc/src/megaco.xml
index b9bf414299..5dd622368c 100644
--- a/lib/megaco/doc/src/megaco.xml
+++ b/lib/megaco/doc/src/megaco.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2010</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -646,7 +646,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
segments has not yet been received.</p>
<p>When the timer finally expires, a "megaco segments not
received" (459) error message is sent to the other side
- and the user is notified with a <c><![CDATA[segment timeout]]></c><c><![CDATA[UserReply]]></c> in either the
+ and the user is notified with a <c><![CDATA[segment timeout]]></c> <c><![CDATA[UserReply]]></c> in either the
<seealso marker="megaco_user#trans_reply">handle_trans_reply</seealso> callback function or
the return value of the
<seealso marker="megaco#call">call</seealso> function. </p>
@@ -1165,7 +1165,7 @@ megaco_incr_timer() = #megaco_incr_timer{}
<p>When the timer finally expires, a "megaco segments not
received" (459) error message is sent to the other side
and the user is notified with a
- <c><![CDATA[segment timeout]]></c><c><![CDATA[UserReply]]></c> in either the
+ <c><![CDATA[segment timeout]]></c> <c><![CDATA[UserReply]]></c> in either the
<seealso marker="megaco_user#trans_reply">handle_trans_reply</seealso>
callback function or
the return value of the
diff --git a/lib/megaco/doc/src/notes.xml b/lib/megaco/doc/src/notes.xml
index 4f678a2a1b..2aba8db71b 100644
--- a/lib/megaco/doc/src/notes.xml
+++ b/lib/megaco/doc/src/notes.xml
@@ -36,6 +36,48 @@
section is the version number of Megaco.</p>
+ <section><title>Megaco 3.15.1.1</title>
+
+ <p>Version 3.15.1.1 supports code replacement in runtime from/to
+ version 3.15.1 and 3.15.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+
+<!--
+ <p>-</p>
+-->
+
+ <list type="bulleted">
+ <item>
+ <p>Correct various XML errors. </p>
+ <p>Own Id: OTP-9550</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Fixed bugs and malfunctions</title>
+
+ <p>-</p>
+
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>Fixing miscellaneous things detected by dialyzer. </p>
+ <p>Own Id: OTP-9075</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ </section> <!-- 3.15.1.1 -->
+
+
<section><title>Megaco 3.15.1</title>
<p>Version 3.15.1 supports code replacement in runtime from/to
diff --git a/lib/megaco/src/app/megaco.appup.src b/lib/megaco/src/app/megaco.appup.src
index 01b070d79f..7107178d1a 100644
--- a/lib/megaco/src/app/megaco.appup.src
+++ b/lib/megaco/src/app/megaco.appup.src
@@ -136,10 +136,17 @@
%% |
%% v
%% 3.15.1
+%% |
+%% v
+%% 3.15.1.1
%%
%%
{"%VSN%",
[
+ {"3.15.1",
+ [
+ ]
+ },
{"3.15",
[
{load_module, megaco_flex_scanner, soft_purge, soft_purge, []},
@@ -153,6 +160,10 @@
}
],
[
+ {"3.15.1",
+ [
+ ]
+ },
{"3.15",
[
{load_module, megaco_flex_scanner, soft_purge, soft_purge, []},
diff --git a/lib/megaco/src/binary/depend.mk b/lib/megaco/src/binary/depend.mk
index 5ec4977175..d12bd8bad0 100644
--- a/lib/megaco/src/binary/depend.mk
+++ b/lib/megaco/src/binary/depend.mk
@@ -83,17 +83,16 @@ PER_BIN_DRV_V3_FLAGS = $(ASN1_CT_OPTS) +optimize
# --- Version 1 ---
-$(BER_ASN1_V1_SPEC).erl $(BER_ASN1_V1_SPEC).hrl: \
+$(BER_ASN1_V1_SPEC).erl: \
$(BER_ASN1_V1_SPEC).set.asn \
$(ASN1_V1_SPEC).asn
@echo "$(BER_ASN1_V1_SPEC):"
$(ERLC) -bber $(BER_V1_FLAGS) $(BER_ASN1_V1_SPEC).set.asn
$(EBIN)/$(BER_ASN1_V1_SPEC).$(EMULATOR): \
- $(BER_ASN1_V1_SPEC).erl \
- $(BER_ASN1_V1_SPEC).hrl
+ $(BER_ASN1_V1_SPEC).erl
-$(BER_BIN_ASN1_V1_SPEC).erl $(BER_BIN_ASN1_V1_SPEC).hrl: \
+$(BER_BIN_ASN1_V1_SPEC).erl: \
$(BER_BIN_ASN1_V1_SPEC).set.asn \
$(BER_BIN_ASN1_V1_SPEC).asn1config \
$(ASN1_V1_SPEC).asn
@@ -101,10 +100,9 @@ $(BER_BIN_ASN1_V1_SPEC).erl $(BER_BIN_ASN1_V1_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_V1_FLAGS) $(BER_BIN_ASN1_V1_SPEC).set.asn
$(EBIN)/$(BER_BIN_ASN1_V1_SPEC).$(EMULATOR): \
- $(BER_BIN_ASN1_V1_SPEC).erl \
- $(BER_BIN_ASN1_V1_SPEC).hrl
+ $(BER_BIN_ASN1_V1_SPEC).erl
-$(BER_BIN_DRV_ASN1_V1_SPEC).erl $(BER_BIN_DRV_ASN1_V1_SPEC).hrl: \
+$(BER_BIN_DRV_ASN1_V1_SPEC).erl: \
$(BER_BIN_DRV_ASN1_V1_SPEC).set.asn \
$(BER_BIN_DRV_ASN1_V1_SPEC).asn1config \
$(ASN1_V1_SPEC).asn
@@ -112,53 +110,48 @@ $(BER_BIN_DRV_ASN1_V1_SPEC).erl $(BER_BIN_DRV_ASN1_V1_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_DRV_V1_FLAGS) $(BER_BIN_DRV_ASN1_V1_SPEC).set.asn
$(EBIN)/$(BER_BIN_DRV_ASN1_V1_SPEC).$(EMULATOR): \
- $(BER_BIN_DRV_ASN1_V1_SPEC).erl \
- $(BER_BIN_DRV_ASN1_V1_SPEC).hrl
+ $(BER_BIN_DRV_ASN1_V1_SPEC).erl
-$(PER_ASN1_V1_SPEC).erl $(PER_ASN1_V1_SPEC).hrl: \
+$(PER_ASN1_V1_SPEC).erl: \
$(PER_ASN1_V1_SPEC).set.asn \
$(ASN1_V1_SPEC).asn
@echo "$(PER_ASN1_V1_SPEC):"
$(ERLC) -bper $(PER_V1_FLAGS) $(PER_ASN1_V1_SPEC).set.asn
$(EBIN)/$(PER_ASN1_V1_SPEC).$(EMULATOR): \
- $(PER_ASN1_V1_SPEC).erl \
- $(PER_ASN1_V1_SPEC).hrl
+ $(PER_ASN1_V1_SPEC).erl
-$(PER_BIN_ASN1_V1_SPEC).erl $(PER_BIN_ASN1_V1_SPEC).hrl: \
+$(PER_BIN_ASN1_V1_SPEC).erl: \
$(PER_BIN_ASN1_V1_SPEC).set.asn \
$(ASN1_V1_SPEC).asn
@echo "$(PER_BIN_ASN1_V1_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_V1_FLAGS) $(PER_BIN_ASN1_V1_SPEC).set.asn
$(EBIN)/$(PER_BIN_ASN1_V1_SPEC).$(EMULATOR): \
- $(PER_BIN_ASN1_V1_SPEC).erl \
- $(PER_BIN_ASN1_V1_SPEC).hrl
+ $(PER_BIN_ASN1_V1_SPEC).erl
-$(PER_BIN_DRV_ASN1_V1_SPEC).erl $(PER_BIN_DRV_ASN1_V1_SPEC).hrl: \
+$(PER_BIN_DRV_ASN1_V1_SPEC).erl: \
$(PER_BIN_DRV_ASN1_V1_SPEC).set.asn \
$(ASN1_V1_SPEC).asn
@echo "$(PER_BIN_DRV_ASN1_V1_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_DRV_V1_FLAGS) $(PER_BIN_DRV_ASN1_V1_SPEC).set.asn
$(EBIN)/$(PER_BIN_DRV_ASN1_V1_SPEC).$(EMULATOR): \
- $(PER_BIN_DRV_ASN1_V1_SPEC).erl \
- $(PER_BIN_DRV_ASN1_V1_SPEC).hrl
+ $(PER_BIN_DRV_ASN1_V1_SPEC).erl
# --- Version 2 ---
-$(BER_ASN1_V2_SPEC).erl $(BER_ASN1_V2_SPEC).hrl: \
+$(BER_ASN1_V2_SPEC).erl: \
$(BER_ASN1_V2_SPEC).set.asn \
$(ASN1_V2_SPEC).asn
@echo "$(BER_ASN1_V2_SPEC):"
$(ERLC) -bber $(BER_V2_FLAGS) $(BER_ASN1_V2_SPEC).set.asn
$(EBIN)/$(BER_ASN1_V2_SPEC).$(EMULATOR): \
- $(BER_ASN1_V2_SPEC).erl \
- $(BER_ASN1_V2_SPEC).hrl
+ $(BER_ASN1_V2_SPEC).erl
-$(BER_BIN_ASN1_V2_SPEC).erl $(BER_BIN_ASN1_V2_SPEC).hrl: \
+$(BER_BIN_ASN1_V2_SPEC).erl: \
$(BER_BIN_ASN1_V2_SPEC).set.asn \
$(BER_BIN_ASN1_V2_SPEC).asn1config \
$(ASN1_V2_SPEC).asn
@@ -166,10 +159,9 @@ $(BER_BIN_ASN1_V2_SPEC).erl $(BER_BIN_ASN1_V2_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_V2_FLAGS) $(BER_BIN_ASN1_V2_SPEC).set.asn
$(EBIN)/$(BER_BIN_ASN1_V2_SPEC).$(EMULATOR): \
- $(BER_BIN_ASN1_V2_SPEC).erl \
- $(BER_BIN_ASN1_V2_SPEC).hrl
+ $(BER_BIN_ASN1_V2_SPEC).erl
-$(BER_BIN_DRV_ASN1_V2_SPEC).erl $(BER_BIN_DRV_ASN1_V2_SPEC).hrl: \
+$(BER_BIN_DRV_ASN1_V2_SPEC).erl: \
$(BER_BIN_DRV_ASN1_V2_SPEC).set.asn \
$(BER_BIN_DRV_ASN1_V2_SPEC).asn1config \
$(ASN1_V2_SPEC).asn
@@ -177,55 +169,50 @@ $(BER_BIN_DRV_ASN1_V2_SPEC).erl $(BER_BIN_DRV_ASN1_V2_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_DRV_V2_FLAGS) $(BER_BIN_DRV_ASN1_V2_SPEC).set.asn
$(EBIN)/$(BER_BIN_DRV_ASN1_V2_SPEC).$(EMULATOR): \
- $(BER_BIN_DRV_ASN1_V2_SPEC).erl \
- $(BER_BIN_DRV_ASN1_V2_SPEC).hrl
+ $(BER_BIN_DRV_ASN1_V2_SPEC).erl
-$(PER_ASN1_V2_SPEC).erl $(PER_ASN1_V2_SPEC).hrl: \
+$(PER_ASN1_V2_SPEC).erl: \
$(PER_ASN1_V2_SPEC).set.asn \
$(ASN1_V2_SPEC).asn
@echo "$(PER_ASN1_V2_SPEC):"
$(ERLC) -bper $(PER_V2_FLAGS) $(PER_ASN1_V2_SPEC).set.asn
$(EBIN)/$(PER_ASN1_V2_SPEC).$(EMULATOR): \
- $(PER_ASN1_V2_SPEC).erl \
- $(PER_ASN1_V2_SPEC).hrl
+ $(PER_ASN1_V2_SPEC).erl
-$(PER_BIN_ASN1_V2_SPEC).erl $(PER_BIN_ASN1_V2_SPEC).hrl: \
+$(PER_BIN_ASN1_V2_SPEC).erl: \
$(PER_BIN_ASN1_V2_SPEC).set.asn \
$(ASN1_V2_SPEC).asn
@echo "$(PER_BIN_ASN1_V2_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_V2_FLAGS) $(PER_BIN_ASN1_V2_SPEC).set.asn
$(EBIN)/$(PER_BIN_ASN1_V2_SPEC).$(EMULATOR): \
- $(PER_BIN_ASN1_V2_SPEC).erl \
- $(PER_BIN_ASN1_V2_SPEC).hrl
+ $(PER_BIN_ASN1_V2_SPEC).erl
-$(PER_BIN_DRV_ASN1_V2_SPEC).erl $(PER_BIN_DRV_ASN1_V2_SPEC).hrl: \
+$(PER_BIN_DRV_ASN1_V2_SPEC).erl: \
$(PER_BIN_DRV_ASN1_V2_SPEC).set.asn \
$(ASN1_V2_SPEC).asn
@echo "$(PER_BIN_DRV_ASN1_V2_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_DRV_V2_FLAGS) $(PER_BIN_DRV_ASN1_V2_SPEC).set.asn
$(EBIN)/$(PER_BIN_DRV_ASN1_V2_SPEC).$(EMULATOR): \
- $(PER_BIN_DRV_ASN1_V2_SPEC).erl \
- $(PER_BIN_DRV_ASN1_V2_SPEC).hrl
+ $(PER_BIN_DRV_ASN1_V2_SPEC).erl
# --- Version 3 ---
# -- (prev3a) --
-$(BER_ASN1_PREV3A_SPEC).erl $(BER_ASN1_PREV3A_SPEC).hrl: \
+$(BER_ASN1_PREV3A_SPEC).erl: \
$(BER_ASN1_PREV3A_SPEC).set.asn \
$(ASN1_PREV3A_SPEC).asn
@echo "$(BER_ASN1_PREV3A_SPEC):"
$(ERLC) -bber $(BER_PREV3A_FLAGS) $(BER_ASN1_PREV3A_SPEC).set.asn
$(EBIN)/$(BER_ASN1_PREV3A_SPEC).$(EMULATOR): \
- $(BER_ASN1_PREV3A_SPEC).erl \
- $(BER_ASN1_PREV3A_SPEC).hrl
+ $(BER_ASN1_PREV3A_SPEC).erl
-$(BER_BIN_ASN1_PREV3A_SPEC).erl $(BER_BIN_ASN1_PREV3A_SPEC).hrl: \
+$(BER_BIN_ASN1_PREV3A_SPEC).erl: \
$(BER_BIN_ASN1_PREV3A_SPEC).set.asn \
$(BER_BIN_ASN1_PREV3A_SPEC).asn1config \
$(ASN1_PREV3A_SPEC).asn
@@ -233,10 +220,9 @@ $(BER_BIN_ASN1_PREV3A_SPEC).erl $(BER_BIN_ASN1_PREV3A_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_PREV3A_FLAGS) $(BER_BIN_ASN1_PREV3A_SPEC).set.asn
$(EBIN)/$(BER_BIN_ASN1_PREV3A_SPEC).$(EMULATOR): \
- $(BER_BIN_ASN1_PREV3A_SPEC).erl \
- $(BER_BIN_ASN1_PREV3A_SPEC).hrl
+ $(BER_BIN_ASN1_PREV3A_SPEC).erl
-$(BER_BIN_DRV_ASN1_PREV3A_SPEC).erl $(BER_BIN_DRV_ASN1_PREV3A_SPEC).hrl: \
+$(BER_BIN_DRV_ASN1_PREV3A_SPEC).erl: \
$(BER_BIN_DRV_ASN1_PREV3A_SPEC).set.asn \
$(BER_BIN_DRV_ASN1_PREV3A_SPEC).asn1config \
$(ASN1_PREV3A_SPEC).asn
@@ -244,52 +230,47 @@ $(BER_BIN_DRV_ASN1_PREV3A_SPEC).erl $(BER_BIN_DRV_ASN1_PREV3A_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_DRV_PREV3A_FLAGS) $(BER_BIN_DRV_ASN1_PREV3A_SPEC).set.asn
$(EBIN)/$(BER_BIN_DRV_ASN1_PREV3A_SPEC).$(EMULATOR): \
- $(BER_BIN_DRV_ASN1_PREV3A_SPEC).erl \
- $(BER_BIN_DRV_ASN1_PREV3A_SPEC).hrl
+ $(BER_BIN_DRV_ASN1_PREV3A_SPEC).erl
-$(PER_ASN1_PREV3A_SPEC).erl $(PER_ASN1_PREV3A_SPEC).hrl: \
+$(PER_ASN1_PREV3A_SPEC).erl: \
$(PER_ASN1_PREV3A_SPEC).set.asn \
$(ASN1_PREV3A_SPEC).asn
@echo "$(PER_ASN1_PREV3A_SPEC):"
$(ERLC) -bper $(PER_PREV3A_FLAGS) $(PER_ASN1_PREV3A_SPEC).set.asn
$(EBIN)/$(PER_ASN1_PREV3A_SPEC).$(EMULATOR): \
- $(PER_ASN1_PREV3A_SPEC).erl \
- $(PER_ASN1_PREV3A_SPEC).hrl
+ $(PER_ASN1_PREV3A_SPEC).erl
-$(PER_BIN_ASN1_PREV3A_SPEC).erl $(PER_BIN_ASN1_PREV3A_SPEC).hrl: \
+$(PER_BIN_ASN1_PREV3A_SPEC).erl: \
$(PER_BIN_ASN1_PREV3A_SPEC).set.asn \
$(ASN1_PREV3A_SPEC).asn
@echo "$(PER_BIN_ASN1_PREV3A_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_PREV3A_FLAGS) $(PER_BIN_ASN1_PREV3A_SPEC).set.asn
$(EBIN)/$(PER_BIN_ASN1_PREV3A_SPEC).$(EMULATOR): \
- $(PER_BIN_ASN1_PREV3A_SPEC).erl \
- $(PER_BIN_ASN1_PREV3A_SPEC).hrl
+ $(PER_BIN_ASN1_PREV3A_SPEC).erl
-$(PER_BIN_DRV_ASN1_PREV3A_SPEC).erl $(PER_BIN_DRV_ASN1_PREV3A_SPEC).hrl: \
+$(PER_BIN_DRV_ASN1_PREV3A_SPEC).erl: \
$(PER_BIN_DRV_ASN1_PREV3A_SPEC).set.asn \
$(ASN1_PREV3A_SPEC).asn
@echo "$(PER_BIN_DRV_ASN1_PREV3A_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_DRV_PREV3A_FLAGS) $(PER_BIN_DRV_ASN1_PREV3A_SPEC).set.asn
$(EBIN)/$(PER_BIN_DRV_ASN1_PREV3A_SPEC).$(EMULATOR): \
- $(PER_BIN_DRV_ASN1_PREV3A_SPEC).erl \
- $(PER_BIN_DRV_ASN1_PREV3A_SPEC).hrl
+ $(PER_BIN_DRV_ASN1_PREV3A_SPEC).erl
# -- (prev3b) --
-$(BER_ASN1_PREV3B_SPEC).erl $(BER_ASN1_PREV3B_SPEC).hrl: \
+$(BER_ASN1_PREV3B_SPEC).erl: \
$(BER_ASN1_PREV3B_SPEC).set.asn \
$(ASN1_PREV3B_SPEC).asn
@echo "$(BER_ASN1_PREV3B_SPEC):"
$(ERLC) -bber $(BER_PREV3B_FLAGS) $(BER_ASN1_PREV3B_SPEC).set.asn
$(EBIN)/$(BER_ASN1_PREV3B_SPEC).$(EMULATOR): \
- $(BER_ASN1_PREV3B_SPEC).erl \
- $(BER_ASN1_PREV3B_SPEC).hrl
+ $(BER_ASN1_PREV3B_SPEC).erl
-$(BER_BIN_ASN1_PREV3B_SPEC).erl $(BER_BIN_ASN1_PREV3B_SPEC).hrl: \
+$(BER_BIN_ASN1_PREV3B_SPEC).erl: \
$(BER_BIN_ASN1_PREV3B_SPEC).set.asn \
$(BER_BIN_ASN1_PREV3B_SPEC).asn1config \
$(ASN1_PREV3B_SPEC).asn
@@ -297,10 +278,9 @@ $(BER_BIN_ASN1_PREV3B_SPEC).erl $(BER_BIN_ASN1_PREV3B_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_PREV3B_FLAGS) $(BER_BIN_ASN1_PREV3B_SPEC).set.asn
$(EBIN)/$(BER_BIN_ASN1_PREV3B_SPEC).$(EMULATOR): \
- $(BER_BIN_ASN1_PREV3B_SPEC).erl \
- $(BER_BIN_ASN1_PREV3B_SPEC).hrl
+ $(BER_BIN_ASN1_PREV3B_SPEC).erl
-$(BER_BIN_DRV_ASN1_PREV3B_SPEC).erl $(BER_BIN_DRV_ASN1_PREV3B_SPEC).hrl: \
+$(BER_BIN_DRV_ASN1_PREV3B_SPEC).erl: \
$(BER_BIN_DRV_ASN1_PREV3B_SPEC).set.asn \
$(BER_BIN_DRV_ASN1_PREV3B_SPEC).asn1config \
$(ASN1_PREV3B_SPEC).asn
@@ -308,53 +288,48 @@ $(BER_BIN_DRV_ASN1_PREV3B_SPEC).erl $(BER_BIN_DRV_ASN1_PREV3B_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_DRV_PREV3B_FLAGS) $(BER_BIN_DRV_ASN1_PREV3B_SPEC).set.asn
$(EBIN)/$(BER_BIN_DRV_ASN1_PREV3B_SPEC).$(EMULATOR): \
- $(BER_BIN_DRV_ASN1_PREV3B_SPEC).erl \
- $(BER_BIN_DRV_ASN1_PREV3B_SPEC).hrl
+ $(BER_BIN_DRV_ASN1_PREV3B_SPEC).erl
-$(PER_ASN1_PREV3B_SPEC).erl $(PER_ASN1_PREV3B_SPEC).hrl: \
+$(PER_ASN1_PREV3B_SPEC).erl: \
$(PER_ASN1_PREV3B_SPEC).set.asn \
$(ASN1_PREV3B_SPEC).asn
@echo "$(PER_ASN1_PREV3B_SPEC):"
$(ERLC) -bper $(PER_PREV3B_FLAGS) $(PER_ASN1_PREV3B_SPEC).set.asn
$(EBIN)/$(PER_ASN1_PREV3B_SPEC).$(EMULATOR): \
- $(PER_ASN1_PREV3B_SPEC).erl \
- $(PER_ASN1_PREV3B_SPEC).hrl
+ $(PER_ASN1_PREV3B_SPEC).erl
-$(PER_BIN_ASN1_PREV3B_SPEC).erl $(PER_BIN_ASN1_PREV3B_SPEC).hrl: \
+$(PER_BIN_ASN1_PREV3B_SPEC).erl: \
$(PER_BIN_ASN1_PREV3B_SPEC).set.asn \
$(ASN1_PREV3B_SPEC).asn
@echo "$(PER_BIN_ASN1_PREV3B_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_PREV3B_FLAGS) $(PER_BIN_ASN1_PREV3B_SPEC).set.asn
$(EBIN)/$(PER_BIN_ASN1_PREV3B_SPEC).$(EMULATOR): \
- $(PER_BIN_ASN1_PREV3B_SPEC).erl \
- $(PER_BIN_ASN1_PREV3B_SPEC).hrl
+ $(PER_BIN_ASN1_PREV3B_SPEC).erl
-$(PER_BIN_DRV_ASN1_PREV3B_SPEC).erl $(PER_BIN_DRV_ASN1_PREV3B_SPEC).hrl: \
+$(PER_BIN_DRV_ASN1_PREV3B_SPEC).erl: \
$(PER_BIN_DRV_ASN1_PREV3B_SPEC).set.asn \
$(ASN1_PREV3B_SPEC).asn
@echo "$(PER_BIN_DRV_ASN1_PREV3B_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_DRV_PREV3B_FLAGS) $(PER_BIN_DRV_ASN1_PREV3B_SPEC).set.asn
$(EBIN)/$(PER_BIN_DRV_ASN1_PREV3B_SPEC).$(EMULATOR): \
- $(PER_BIN_DRV_ASN1_PREV3B_SPEC).erl \
- $(PER_BIN_DRV_ASN1_PREV3B_SPEC).hrl
+ $(PER_BIN_DRV_ASN1_PREV3B_SPEC).erl
# -- (prev3c) --
-$(BER_ASN1_PREV3C_SPEC).erl $(BER_ASN1_PREV3C_SPEC).hrl: \
+$(BER_ASN1_PREV3C_SPEC).erl: \
$(BER_ASN1_PREV3C_SPEC).set.asn \
$(ASN1_PREV3C_SPEC).asn
@echo "$(BER_ASN1_PREV3C_SPEC):"
$(ERLC) -bber $(BER_PREV3C_FLAGS) $(BER_ASN1_PREV3C_SPEC).set.asn
$(EBIN)/$(BER_ASN1_PREV3C_SPEC).$(EMULATOR): \
- $(BER_ASN1_PREV3C_SPEC).erl \
- $(BER_ASN1_PREV3C_SPEC).hrl
+ $(BER_ASN1_PREV3C_SPEC).erl
-$(BER_BIN_ASN1_PREV3C_SPEC).erl $(BER_BIN_ASN1_PREV3C_SPEC).hrl: \
+$(BER_BIN_ASN1_PREV3C_SPEC).erl: \
$(BER_BIN_ASN1_PREV3C_SPEC).set.asn \
$(BER_BIN_ASN1_PREV3C_SPEC).asn1config \
$(ASN1_PREV3C_SPEC).asn
@@ -362,10 +337,9 @@ $(BER_BIN_ASN1_PREV3C_SPEC).erl $(BER_BIN_ASN1_PREV3C_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_PREV3C_FLAGS) $(BER_BIN_ASN1_PREV3C_SPEC).set.asn
$(EBIN)/$(BER_BIN_ASN1_PREV3C_SPEC).$(EMULATOR): \
- $(BER_BIN_ASN1_PREV3C_SPEC).erl \
- $(BER_BIN_ASN1_PREV3C_SPEC).hrl
+ $(BER_BIN_ASN1_PREV3C_SPEC).erl
-$(BER_BIN_DRV_ASN1_PREV3C_SPEC).erl $(BER_BIN_DRV_ASN1_PREV3C_SPEC).hrl: \
+$(BER_BIN_DRV_ASN1_PREV3C_SPEC).erl: \
$(BER_BIN_DRV_ASN1_PREV3C_SPEC).set.asn \
$(BER_BIN_DRV_ASN1_PREV3C_SPEC).asn1config \
$(ASN1_PREV3C_SPEC).asn
@@ -373,53 +347,48 @@ $(BER_BIN_DRV_ASN1_PREV3C_SPEC).erl $(BER_BIN_DRV_ASN1_PREV3C_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_DRV_PREV3C_FLAGS) $(BER_BIN_DRV_ASN1_PREV3C_SPEC).set.asn
$(EBIN)/$(BER_BIN_DRV_ASN1_PREV3C_SPEC).$(EMULATOR): \
- $(BER_BIN_DRV_ASN1_PREV3C_SPEC).erl \
- $(BER_BIN_DRV_ASN1_PREV3C_SPEC).hrl
+ $(BER_BIN_DRV_ASN1_PREV3C_SPEC).erl
-$(PER_ASN1_PREV3C_SPEC).erl $(PER_ASN1_PREV3C_SPEC).hrl: \
+$(PER_ASN1_PREV3C_SPEC).erl: \
$(PER_ASN1_PREV3C_SPEC).set.asn \
$(ASN1_PREV3C_SPEC).asn
@echo "$(PER_ASN1_PREV3C_SPEC):"
$(ERLC) -bper $(PER_PREV3C_FLAGS) $(PER_ASN1_PREV3C_SPEC).set.asn
$(EBIN)/$(PER_ASN1_PREV3C_SPEC).$(EMULATOR): \
- $(PER_ASN1_PREV3C_SPEC).erl \
- $(PER_ASN1_PREV3C_SPEC).hrl
+ $(PER_ASN1_PREV3C_SPEC).erl
-$(PER_BIN_ASN1_PREV3C_SPEC).erl $(PER_BIN_ASN1_PREV3C_SPEC).hrl: \
+$(PER_BIN_ASN1_PREV3C_SPEC).erl: \
$(PER_BIN_ASN1_PREV3C_SPEC).set.asn \
$(ASN1_PREV3C_SPEC).asn
@echo "$(PER_BIN_ASN1_PREV3C_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_PREV3C_FLAGS) $(PER_BIN_ASN1_PREV3C_SPEC).set.asn
$(EBIN)/$(PER_BIN_ASN1_PREV3C_SPEC).$(EMULATOR): \
- $(PER_BIN_ASN1_PREV3C_SPEC).erl \
- $(PER_BIN_ASN1_PREV3C_SPEC).hrl
+ $(PER_BIN_ASN1_PREV3C_SPEC).erl
-$(PER_BIN_DRV_ASN1_PREV3C_SPEC).erl $(PER_BIN_DRV_ASN1_PREV3C_SPEC).hrl: \
+$(PER_BIN_DRV_ASN1_PREV3C_SPEC).erl: \
$(PER_BIN_DRV_ASN1_PREV3C_SPEC).set.asn \
$(ASN1_PREV3C_SPEC).asn
@echo "$(PER_BIN_DRV_ASN1_PREV3C_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_DRV_PREV3C_FLAGS) $(PER_BIN_DRV_ASN1_PREV3C_SPEC).set.asn
$(EBIN)/$(PER_BIN_DRV_ASN1_PREV3C_SPEC).$(EMULATOR): \
- $(PER_BIN_DRV_ASN1_PREV3C_SPEC).erl \
- $(PER_BIN_DRV_ASN1_PREV3C_SPEC).hrl
+ $(PER_BIN_DRV_ASN1_PREV3C_SPEC).erl
# -- (v3) --
-$(BER_ASN1_V3_SPEC).erl $(BER_ASN1_V3_SPEC).hrl: \
+$(BER_ASN1_V3_SPEC).erl: \
$(BER_ASN1_V3_SPEC).set.asn \
$(ASN1_V3_SPEC).asn
@echo "$(BER_ASN1_V3_SPEC):"
$(ERLC) -bber $(BER_V3_FLAGS) $(BER_ASN1_V3_SPEC).set.asn
$(EBIN)/$(BER_ASN1_V3_SPEC).$(EMULATOR): \
- $(BER_ASN1_V3_SPEC).erl \
- $(BER_ASN1_V3_SPEC).hrl
+ $(BER_ASN1_V3_SPEC).erl
-$(BER_BIN_ASN1_V3_SPEC).erl $(BER_BIN_ASN1_V3_SPEC).hrl: \
+$(BER_BIN_ASN1_V3_SPEC).erl: \
$(BER_BIN_ASN1_V3_SPEC).set.asn \
$(BER_BIN_ASN1_V3_SPEC).asn1config \
$(ASN1_V3_SPEC).asn
@@ -427,10 +396,9 @@ $(BER_BIN_ASN1_V3_SPEC).erl $(BER_BIN_ASN1_V3_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_V3_FLAGS) $(BER_BIN_ASN1_V3_SPEC).set.asn
$(EBIN)/$(BER_BIN_ASN1_V3_SPEC).$(EMULATOR): \
- $(BER_BIN_ASN1_V3_SPEC).erl \
- $(BER_BIN_ASN1_V3_SPEC).hrl
+ $(BER_BIN_ASN1_V3_SPEC).erl
-$(BER_BIN_DRV_ASN1_V3_SPEC).erl $(BER_BIN_DRV_ASN1_V3_SPEC).hrl: \
+$(BER_BIN_DRV_ASN1_V3_SPEC).erl: \
$(BER_BIN_DRV_ASN1_V3_SPEC).set.asn \
$(BER_BIN_DRV_ASN1_V3_SPEC).asn1config \
$(ASN1_V3_SPEC).asn
@@ -438,38 +406,34 @@ $(BER_BIN_DRV_ASN1_V3_SPEC).erl $(BER_BIN_DRV_ASN1_V3_SPEC).hrl: \
$(ERLC) -bber_bin $(BER_BIN_DRV_V3_FLAGS) $(BER_BIN_DRV_ASN1_V3_SPEC).set.asn
$(EBIN)/$(BER_BIN_DRV_ASN1_V3_SPEC).$(EMULATOR): \
- $(BER_BIN_DRV_ASN1_V3_SPEC).erl \
- $(BER_BIN_DRV_ASN1_V3_SPEC).hrl
+ $(BER_BIN_DRV_ASN1_V3_SPEC).erl
-$(PER_ASN1_V3_SPEC).erl $(PER_ASN1_V3_SPEC).hrl: \
+$(PER_ASN1_V3_SPEC).erl: \
$(PER_ASN1_V3_SPEC).set.asn \
$(ASN1_V3_SPEC).asn
@echo "$(PER_ASN1_V3_SPEC):"
$(ERLC) -bper $(PER_V3_FLAGS) $(PER_ASN1_V3_SPEC).set.asn
$(EBIN)/$(PER_ASN1_V3_SPEC).$(EMULATOR): \
- $(PER_ASN1_V3_SPEC).erl \
- $(PER_ASN1_V3_SPEC).hrl
+ $(PER_ASN1_V3_SPEC).erl
-$(PER_BIN_ASN1_V3_SPEC).erl $(PER_BIN_ASN1_V3_SPEC).hrl: \
+$(PER_BIN_ASN1_V3_SPEC).erl: \
$(PER_BIN_ASN1_V3_SPEC).set.asn \
$(ASN1_V3_SPEC).asn
@echo "$(PER_BIN_ASN1_V3_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_V3_FLAGS) $(PER_BIN_ASN1_V3_SPEC).set.asn
$(EBIN)/$(PER_BIN_ASN1_V3_SPEC).$(EMULATOR): \
- $(PER_BIN_ASN1_V3_SPEC).erl \
- $(PER_BIN_ASN1_V3_SPEC).hrl
+ $(PER_BIN_ASN1_V3_SPEC).erl
-$(PER_BIN_DRV_ASN1_V3_SPEC).erl $(PER_BIN_DRV_ASN1_V3_SPEC).hrl: \
+$(PER_BIN_DRV_ASN1_V3_SPEC).erl: \
$(PER_BIN_DRV_ASN1_V3_SPEC).set.asn \
$(ASN1_V3_SPEC).asn
@echo "$(PER_BIN_DRV_ASN1_V3_SPEC):"
$(ERLC) -bper_bin $(PER_BIN_DRV_V3_FLAGS) $(PER_BIN_DRV_ASN1_V3_SPEC).set.asn
$(EBIN)/$(PER_BIN_DRV_ASN1_V3_SPEC).$(EMULATOR): \
- $(PER_BIN_DRV_ASN1_V3_SPEC).erl \
- $(PER_BIN_DRV_ASN1_V3_SPEC).hrl
+ $(PER_BIN_DRV_ASN1_V3_SPEC).erl
# -------------
diff --git a/lib/megaco/src/flex/Makefile.in b/lib/megaco/src/flex/Makefile.in
index 5af651d89b..2c46a673e4 100644
--- a/lib/megaco/src/flex/Makefile.in
+++ b/lib/megaco/src/flex/Makefile.in
@@ -391,7 +391,9 @@ $(STD_DRV).c: $(STD_DRV).flex
$(MT_DRV).c: $(MT_DRV).flex
$(LEX) $(MT_LEX_FLAGS) -P$* -o$@ $<
-solibs: $(LIBDIR) $(OBJDIR) $(SOLIBS)
+_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
+
+solibs: $(SOLIBS)
$(OBJDIR)/$(STD_DRV).o: $(STD_DRV).c
@echo "compiling std driver:"
@@ -411,10 +413,3 @@ $(LIBDIR)/$(STD_DRV).$(DED_EXT): $(OBJDIR)/$(STD_DRV).o
$(LIBDIR)/$(MT_DRV).$(DED_EXT): $(OBJDIR)/$(MT_DRV).o
@echo "linking multi-threaded driver:"
$(LD) $(LDFLAGS) -o $@ $<
-
-$(LIBDIR):
- -mkdir -p $(LIBDIR)
-
-$(OBJDIR):
- -mkdir -p $(OBJDIR)
-
diff --git a/lib/megaco/test/Makefile b/lib/megaco/test/Makefile
index 682b83d368..88f6f06e73 100644
--- a/lib/megaco/test/Makefile
+++ b/lib/megaco/test/Makefile
@@ -754,5 +754,5 @@ release_tests_spec: tests
# $(HRL_FILES) $(ERL_FILES) \
# $(RELSYSDIR)
#
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
diff --git a/lib/megaco/vsn.mk b/lib/megaco/vsn.mk
index 5f71712360..c1476488ca 100644
--- a/lib/megaco/vsn.mk
+++ b/lib/megaco/vsn.mk
@@ -18,6 +18,6 @@
# %CopyrightEnd%
APPLICATION = megaco
-MEGACO_VSN = 3.15.1
+MEGACO_VSN = 3.15.1.1
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(MEGACO_VSN)$(PRE_VSN)"
diff --git a/lib/mnesia/doc/src/Mnesia_chap7.xmlsrc b/lib/mnesia/doc/src/Mnesia_chap7.xmlsrc
index 7078499fbf..ae41a216f4 100644
--- a/lib/mnesia/doc/src/Mnesia_chap7.xmlsrc
+++ b/lib/mnesia/doc/src/Mnesia_chap7.xmlsrc
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -473,6 +473,13 @@ dets:close(N). </pre>
<c>mnesia:table_info(Tab, master_nodes)</c> may be used to
obtain information about the potential master nodes.
</p>
+ <p>Determining which data to keep after communication failure is outside
+ the scope of Mnesia. One approach would be to determine which "island"
+ contains a majority of the nodes. Using the <c>{majority,true}</c> option
+ for critical tables can be a way of ensuring that nodes that are not part
+ of a "majority island" are not able to update those tables. Note that this
+ constitutes a reduction in service on the minority nodes. This would be
+ a tradeoff in favour of higher consistency guarantees.</p>
<p>The function <c>mnesia:force_load_table(Tab)</c> may be used to
force load the table regardless of which table load mechanism
is activated.
diff --git a/lib/mnesia/doc/src/mnesia.xml b/lib/mnesia/doc/src/mnesia.xml
index 16e78ea0af..19ec70118f 100644
--- a/lib/mnesia/doc/src/mnesia.xml
+++ b/lib/mnesia/doc/src/mnesia.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2010</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -161,6 +161,14 @@ If a new item is inserted with the same key as
</p>
</item>
<item>
+ <p><c>majority</c> This attribute can be either <c>true</c> or
+ <c>false</c> (default is <c>false</c>). When <c>true</c>, a majority
+ of the table replicas must be available for an update to succeed.
+ Majority checking can be enabled on tables with mission-critical data,
+ where it is vital to avoid inconsistencies due to network splits.
+ </p>
+ </item>
+ <item>
<p><c>snmp</c> Each (set based) Mnesia table can be
automatically turned into an SNMP ordered table as well.
This property specifies the types of the SNMP keys.
@@ -238,7 +246,7 @@ If a new item is inserted with the same key as
</p>
</item>
<item>
- <p><c>{max,MaxTabs}</c><c>MaxTabs</c> is a list of
+ <p><c>{max,MaxTabs}</c>. <c>MaxTabs</c> is a list of
tables that should be included in the checkpoint. The
default is []. For these tables, the redundancy will be
maximized and checkpoint information will be retained together
@@ -266,7 +274,7 @@ If a new item is inserted with the same key as
</p>
</item>
<item>
- <p><c>{ram_overrides_dump,Bool} </c> Only applicable
+ <p><c>{ram_overrides_dump,Bool}</c>. Only applicable
for <c>ram_copies</c>. <c>Bool</c> allows you to choose
to backup the table state as it is in RAM, or as it is on
disc. <c>true</c> means that the latest committed
@@ -650,6 +658,17 @@ mnesia:change_table_copy_type(person, node(), disc_copies)
</desc>
</func>
<func>
+ <name>change_table_majority(Tab, Majority) -> {aborted, R} | {atomic, ok}</name>
+ <fsummary>Change the majority check setting for the table.</fsummary>
+ <desc>
+ <p><c>Majority</c> must be a boolean; the default is <c>false</c>.
+ When <c>true</c>, a majority of the table's replicas must be available
+ for an update to succeed. When used on fragmented tables, <c>Tab</c>
+ must be the name base table. Directly changing the majority setting on
+ individual fragments is not allowed.</p>
+ </desc>
+ </func>
+ <func>
<name>clear_table(Tab) -> {aborted, R} | {atomic, ok}</name>
<fsummary>Deletes all entries in a table.</fsummary>
<desc>
@@ -753,6 +772,14 @@ mnesia:change_table_copy_type(person, node(), disc_copies)
priority will be loaded first at startup.
</p>
</item>
+ <item>
+ <p><c>{majority, Flag}</c>, where <c>Flag</c> must be a boolean.
+ If <c>true</c>, any (non-dirty) update to the table will abort unless
+ a majority of the table's replicas are available for the commit.
+ When used on a fragmented table, all fragments will be given
+ the same majority setting.
+ </p>
+ </item>
<item>
<p><c>{ram_copies, Nodelist}</c>, where
<c>Nodelist</c> is a list of the nodes where this table
@@ -1737,7 +1764,10 @@ mnesia:create_table(person,
<c>write</c> and <c>sticky_write</c> are supported.
</p>
<p>If the user wants to update the record it is more efficient to
- use <c>write/sticky_write</c> as the LockKind.
+ use <c>write/sticky_write</c> as the LockKind. If majority checking
+ is active on the table, it will be checked as soon as a write lock is
+ attempted. This can be used to quickly abort if the majority condition
+ isn't met.
</p>
</desc>
</func>
diff --git a/lib/mnesia/doc/src/mnesia_frag_hash.xml b/lib/mnesia/doc/src/mnesia_frag_hash.xml
index 73162c3974..665796f20d 100644
--- a/lib/mnesia/doc/src/mnesia_frag_hash.xml
+++ b/lib/mnesia/doc/src/mnesia_frag_hash.xml
@@ -64,7 +64,7 @@
<p>Note that the <c>add_frag/2</c> function will be invoked
one time each for the rest of the fragments (all but number 1)
as a part of the table creation procedure.</p>
- <p><c>State</c> is the initial value of the <c>hash_state</c><c>frag_property</c>. The <c>NewState</c> will be stored as
+ <p><c>State</c> is the initial value of the <c>hash_state</c> <c>frag_property</c>. The <c>NewState</c> will be stored as
<c>hash_state</c> among the other <c>frag_properties</c>.
</p>
</desc>
diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml
index ccf70b8373..8ef573a948 100644
--- a/lib/mnesia/doc/src/notes.xml
+++ b/lib/mnesia/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1996</year><year>2010</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -38,7 +38,110 @@
thus constitutes one section in this document. The title of each
section is the version number of Mnesia.</p>
- <section><title>Mnesia 4.4.17</title>
+ <section><title>Mnesia 4.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix protocol issues. Mnesia-4.4.19 could not communicate
+ with to older nodes.</p>
+ <p>
+ Own Id: OTP-9473</p>
+ </item>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Dump the log even if no transactions have been invoked on
+ local node, otherwise the log will grow forever with
+ decisions from the other nodes who have tables on disk.
+ Thanks Marek Majkowski.</p>
+ <p>
+ Own Id: OTP-9551</p>
+ </item>
+ <item>
+ <p>
+ Use dedicated api for clear_table, i.e. instead of
+ match_delete use delete_all_objects. Thanks KukHyun Lee.</p>
+ <p>
+ Own Id: OTP-9558</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.4.19</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Mnesia could crash if mnesia:add_table_index/2 was
+ invoked before the table was loaded on all nodes.</p>
+ <p>
+ Own Id: OTP-9285 Aux Id: seq11844 </p>
+ </item>
+ <item>
+ <p>
+ Add {majority, boolean()} per-table option.</p>
+ <p>
+ With {majority, true} set for a table, write transactions
+ will abort if they cannot commit to a majority of the
+ nodes that have a copy of the table. Currently, the
+ implementation hooks into the prepare_commit, and forces
+ an asymmetric transaction if the commit set affects any
+ table with the majority flag set. In the commit itself,
+ the transaction will abort if it cannot satisfy the
+ majority requirement for all tables involved in the
+ transaction.(Thanks to Ulf Wiger)</p>
+ <p>
+ Own Id: OTP-9304</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.4.18</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Call chmod without the "-f" flag</p>
+ <p>
+ "-f" is a non-standard chmod option which at least SGI
+ IRIX and HP UX do not support. As the only effect of the
+ "-f" flag is to suppress warning messages, it can be
+ safely omitted. (Thanks to Holger Wei�)</p>
+ <p>
+ Own Id: OTP-9170</p>
+ </item>
+ <item>
+ <p>
+ Mnesia sometimes failed to update meta-information in
+ large systems, which could cause table content to be
+ inconsistent between nodes.</p>
+ <p>
+ Own Id: OTP-9186 Aux Id: seq11728 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.4.17</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/mnesia/src/Makefile b/lib/mnesia/src/Makefile
index e032f563fa..1c8ec54605 100644
--- a/lib/mnesia/src/Makefile
+++ b/lib/mnesia/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2009. All Rights Reserved.
+# Copyright Ericsson AB 1996-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -113,6 +113,8 @@ clean:
docs:
+$(TARGET_FILES): $(HRL_FILES)
+
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
diff --git a/lib/mnesia/src/mnesia.appup.src b/lib/mnesia/src/mnesia.appup.src
index 0eff761b61..fe4e5e2e7a 100644
--- a/lib/mnesia/src/mnesia.appup.src
+++ b/lib/mnesia/src/mnesia.appup.src
@@ -1,25 +1,15 @@
%% -*- erlang -*-
{"%VSN%",
[
- {"4.4.16",[
- {update, mnesia_frag, soft, soft_purge, soft_purge, []},
- {update, mnesia_schema, soft, soft_purge, soft_purge, []}
- ]},
- {"4.4.15",[
- {update, mnesia_frag, soft, soft_purge, soft_purge, []},
- {update, mnesia, soft, soft_purge, soft_purge, []},
- {update, mnesia_dumper, soft, soft_purge, soft_purge, []}
- ]}
+ {"4.4.19", [{restart_application, mnesia}]},
+ {"4.4.18", [{restart_application, mnesia}]},
+ {"4.4.17", [{restart_application, mnesia}]},
+ {"4.4.16", [{restart_application, mnesia}]}
],
[
- {"4.4.16",[
- {update, mnesia_frag, soft, soft_purge, soft_purge, []},
- {update, mnesia_schema, soft, soft_purge, soft_purge, []}
- ]},
- {"4.4.15",[
- {update, mnesia_frag, soft, soft_purge, soft_purge, []},
- {update, mnesia, soft, soft_purge, soft_purge, []},
- {update, mnesia_dumper, soft, soft_purge, soft_purge, []}
- ]}
+ {"4.4.19", [{restart_application, mnesia}]},
+ {"4.4.18", [{restart_application, mnesia}]},
+ {"4.4.17", [{restart_application, mnesia}]},
+ {"4.4.16", [{restart_application, mnesia}]}
]
}.
diff --git a/lib/mnesia/src/mnesia.erl b/lib/mnesia/src/mnesia.erl
index 025b32f506..980a9c6213 100644
--- a/lib/mnesia/src/mnesia.erl
+++ b/lib/mnesia/src/mnesia.erl
@@ -39,6 +39,7 @@
%% Access within an activity - Lock acquisition
lock/2, lock/4,
+ lock_table/2,
read_lock_table/1,
write_lock_table/1,
@@ -92,7 +93,7 @@
add_table_copy/3, del_table_copy/2, move_table_copy/3,
add_table_index/2, del_table_index/2,
transform_table/3, transform_table/4,
- change_table_copy_type/3,
+ change_table_copy_type/3, change_table_majority/2,
read_table_property/2, write_table_property/2, delete_table_property/2,
change_table_frag/2,
clear_table/1, clear_table/4,
@@ -415,6 +416,9 @@ lock(LockItem, LockKind) ->
abort(no_transaction)
end.
+lock_table(Tab, LockKind) ->
+ lock({table, Tab}, LockKind).
+
lock(Tid, Ts, LockItem, LockKind) ->
case element(1, Tid) of
tid ->
@@ -467,6 +471,8 @@ lock_table(Tid, Ts, Tab, LockKind) when is_atom(Tab) ->
mnesia_locker:rlock_table(Tid, Store, Tab);
write ->
mnesia_locker:wlock_table(Tid, Store, Tab);
+ load ->
+ mnesia_locker:load_lock_table(Tid, Store, Tab);
sticky_write ->
mnesia_locker:sticky_wlock_table(Tid, Store, Tab);
none ->
@@ -2455,6 +2461,9 @@ change_table_access_mode(T, Access) ->
change_table_load_order(T, O) ->
mnesia_schema:change_table_load_order(T, O).
+change_table_majority(T, M) ->
+ mnesia_schema:change_table_majority(T, M).
+
set_master_nodes(Nodes) when is_list(Nodes) ->
UseDir = system_info(use_dir),
IsRunning = system_info(is_running),
diff --git a/lib/mnesia/src/mnesia.hrl b/lib/mnesia/src/mnesia.hrl
index d488d9364a..2375b72d59 100644
--- a/lib/mnesia/src/mnesia.hrl
+++ b/lib/mnesia/src/mnesia.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -62,6 +62,7 @@
disc_only_copies = [], % [Node]
load_order = 0, % Integer
access_mode = read_write, % read_write | read_only
+ majority = false, % true | false
index = [], % [Integer]
snmp = [], % Snmp Ustruct
local_content = false, % true | false
diff --git a/lib/mnesia/src/mnesia_controller.erl b/lib/mnesia/src/mnesia_controller.erl
index 021be8af2a..1d3bd55b48 100644
--- a/lib/mnesia/src/mnesia_controller.erl
+++ b/lib/mnesia/src/mnesia_controller.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -57,7 +57,8 @@
release_schema_commit_lock/0,
create_table/1,
get_disc_copy/1,
- get_cstructs/0,
+ get_remote_cstructs/0, % new function
+ get_cstructs/0, % old function
sync_and_block_table_whereabouts/4,
sync_del_table_copy_whereabouts/2,
block_table/1,
@@ -72,6 +73,7 @@
add_active_replica/4,
update/1,
change_table_access_mode/1,
+ change_table_majority/1,
del_active_replica/2,
wait_for_tables/2,
get_network_copy/2,
@@ -277,9 +279,51 @@ rec_tabs([], _, _, Init) ->
unlink(Init),
ok.
-get_cstructs() ->
+%% New function that does exactly what get_cstructs() used to do.
+%% When this function is called, we know that the calling node knows
+%% how to convert cstructs on the receiving end (should they differ).
+get_remote_cstructs() ->
call(get_cstructs).
+%% Old function kept for backwards compatibility; converts cstructs before sending.
+get_cstructs() ->
+ {cstructs, Cstructs, Running} = call(get_cstructs),
+ Node = node(group_leader()),
+ {cstructs, normalize_cstructs(Cstructs, Node), Running}.
+
+normalize_cstructs(Cstructs, Node) ->
+ %% backward-compatibility hack; normalize before returning
+ case rpc:call(Node, mnesia_lib, val, [{schema,cstruct}]) of
+ {badrpc, _} ->
+ %% assume it's not a schema merge
+ Cstructs;
+ #cstruct{} ->
+ %% same format
+ Cstructs;
+ Cstruct ->
+ %% some other format
+ RemoteFields = [F || {F,_} <- rpc:call(Node, mnesia_schema, cs2list, [Cstruct])],
+ [convert_cs(Cs, RemoteFields) || Cs <- Cstructs]
+ end.
+
+convert_cs(Cs, Fields) ->
+ MyFields = record_info(fields, cstruct),
+ convert(tl(tuple_to_list(Cs)), MyFields, Fields, []).
+
+convert([H|T], [F|FsL], [F|FsR], Acc) ->
+ convert(T, FsL, FsR, [H|Acc]);
+convert([H|T], [Fl|FsL] = L, [Fr|FsR] = R, Acc) ->
+ case {lists:member(Fl, FsR), lists:member(Fr, FsL)} of
+ {true, false} ->
+ convert(T, L, FsR, [H|Acc]);
+ {false, true} ->
+ %% Field Fl doesn't exist on receiver side; skip.
+ convert(T, FsL, R, Acc)
+ end;
+convert([], _, _, Acc) ->
+ list_to_tuple([cstruct|lists:reverse(Acc)]).
+
+
update(Fun) ->
call({update,Fun}).
@@ -457,7 +501,7 @@ connect_nodes2(Father, Ns, UserFun) ->
New1 = mnesia_lib:intersect(Ns, Connected),
New = New1 -- Current,
process_flag(trap_exit, true),
- Res = try_merge_schema(New, UserFun),
+ Res = try_merge_schema(New, [], UserFun),
Msg = {schema_is_merged, [], late_merge, []},
multicall([node()|Ns], Msg),
After = val({current, db_nodes}),
@@ -471,7 +515,7 @@ connect_nodes2(Father, Ns, UserFun) ->
merge_schema() ->
AllNodes = mnesia_lib:all_nodes(),
- case try_merge_schema(AllNodes, fun default_merge/1) of
+ case try_merge_schema(AllNodes, [node()], fun default_merge/1) of
ok ->
schema_is_merged();
{aborted, {throw, Str}} when is_list(Str) ->
@@ -483,11 +527,17 @@ merge_schema() ->
default_merge(F) ->
F([]).
-try_merge_schema(Nodes, UserFun) ->
+try_merge_schema(Nodes, Told0, UserFun) ->
case mnesia_schema:merge_schema(UserFun) of
{atomic, not_merged} ->
%% No more nodes that we need to merge the schema with
- ok;
+ %% Ensure we have told everybody that we are running
+ case val({current,db_nodes}) -- mnesia_lib:uniq(Told0) of
+ [] -> ok;
+ Tell ->
+ im_running(Tell, [node()]),
+ ok
+ end;
{atomic, {merged, OldFriends, NewFriends}} ->
%% Check if new nodes has been added to the schema
Diff = mnesia_lib:all_nodes() -- [node() | Nodes],
@@ -496,12 +546,18 @@ try_merge_schema(Nodes, UserFun) ->
%% Tell everybody to adopt orphan tables
im_running(OldFriends, NewFriends),
im_running(NewFriends, OldFriends),
-
- try_merge_schema(Nodes, UserFun);
+ Told = case lists:member(node(), NewFriends) of
+ true -> Told0 ++ OldFriends;
+ false -> Told0 ++ NewFriends
+ end,
+ try_merge_schema(Nodes, Told, UserFun);
{atomic, {"Cannot get cstructs", Node, Reason}} ->
dbg_out("Cannot get cstructs, Node ~p ~p~n", [Node, Reason]),
- timer:sleep(1000), % Avoid a endless loop look alike
- try_merge_schema(Nodes, UserFun);
+ timer:sleep(300), % Avoid a endless loop look alike
+ try_merge_schema(Nodes, Told0, UserFun);
+ {aborted, {shutdown, _}} -> %% One of the nodes is going down
+ timer:sleep(300), % Avoid a endless loop look alike
+ try_merge_schema(Nodes, Told0, UserFun);
Other ->
Other
end.
@@ -678,7 +734,8 @@ handle_call({update_where_to_write, [add, Tab, AddNode], _From}, _Dummy, State)
case lists:member(AddNode, Current) and
(State#state.schema_is_merged == true) of
true ->
- mnesia_lib:add_lsort({Tab, where_to_write}, AddNode);
+ mnesia_lib:add_lsort({Tab, where_to_write}, AddNode),
+ update_where_to_wlock(Tab);
false ->
ignore
end,
@@ -915,6 +972,7 @@ handle_cast(unblock_controller, State) ->
handle_cast({mnesia_down, Node}, State) ->
maybe_log_mnesia_down(Node),
mnesia_lib:del({current, db_nodes}, Node),
+ mnesia_lib:unset({node_up, Node}),
mnesia_checkpoint:tm_mnesia_down(Node),
Alltabs = val({schema, tables}),
reconfigure_tables(Node, Alltabs),
@@ -977,11 +1035,12 @@ handle_cast(Msg, State) when State#state.schema_is_merged /= true ->
%% This must be done after schema_is_merged otherwise adopt_orphan
%% might trigger a table load from wrong nodes as a result of that we don't
%% know which tables we can load safly first.
-handle_cast({im_running, _Node, NewFriends}, State) ->
+handle_cast({im_running, Node, NewFriends}, State) ->
LocalTabs = mnesia_lib:local_active_tables() -- [schema],
RemoveLocalOnly = fun(Tab) -> not val({Tab, local_content}) end,
Tabs = lists:filter(RemoveLocalOnly, LocalTabs),
- Ns = mnesia_lib:intersect(NewFriends, val({current, db_nodes})),
+ Nodes = mnesia_lib:union([Node],val({current, db_nodes})),
+ Ns = mnesia_lib:intersect(NewFriends, Nodes),
abcast(Ns, {adopt_orphans, node(), Tabs}),
noreply(State);
@@ -1042,30 +1101,33 @@ handle_cast({master_nodes_updated, Tab, Masters}, State) ->
end;
handle_cast({adopt_orphans, Node, Tabs}, State) ->
-
State2 = node_has_tabs(Tabs, Node, State),
- %% Register the other node as up and running
- mnesia_recover:log_mnesia_up(Node),
- verbose("Logging mnesia_up ~w~n",[Node]),
- mnesia_lib:report_system_event({mnesia_up, Node}),
-
- %% Load orphan tables
- LocalTabs = val({schema, local_tables}) -- [schema],
- Nodes = val({current, db_nodes}),
- {LocalOrphans, RemoteMasters} =
- orphan_tables(LocalTabs, Node, Nodes, [], []),
- Reason = {adopt_orphan, node()},
- mnesia_late_loader:async_late_disc_load(node(), LocalOrphans, Reason),
-
- Fun =
- fun(N) ->
- RemoteOrphans =
- [Tab || {Tab, Ns} <- RemoteMasters,
- lists:member(N, Ns)],
- mnesia_late_loader:maybe_async_late_disc_load(N, RemoteOrphans, Reason)
- end,
- lists:foreach(Fun, Nodes),
+ case ?catch_val({node_up,Node}) of
+ true -> ignore;
+ _ ->
+ %% Register the other node as up and running
+ set({node_up, Node}, true),
+ mnesia_recover:log_mnesia_up(Node),
+ verbose("Logging mnesia_up ~w~n",[Node]),
+ mnesia_lib:report_system_event({mnesia_up, Node}),
+ %% Load orphan tables
+ LocalTabs = val({schema, local_tables}) -- [schema],
+ Nodes = val({current, db_nodes}),
+ {LocalOrphans, RemoteMasters} =
+ orphan_tables(LocalTabs, Node, Nodes, [], []),
+ Reason = {adopt_orphan, node()},
+ mnesia_late_loader:async_late_disc_load(node(), LocalOrphans, Reason),
+
+ Fun =
+ fun(N) ->
+ RemoteOrphans =
+ [Tab || {Tab, Ns} <- RemoteMasters,
+ lists:member(N, Ns)],
+ mnesia_late_loader:maybe_async_late_disc_load(N, RemoteOrphans, Reason)
+ end,
+ lists:foreach(Fun, Nodes)
+ end,
noreply(State2);
handle_cast(Msg, State) ->
@@ -1673,6 +1735,8 @@ add_active_replica(Tab, Node, Storage, AccessMode) ->
set(Var, mark_blocked_tab(Blocked, Del)),
mnesia_lib:del({Tab, where_to_write}, Node)
end,
+
+ update_where_to_wlock(Tab),
add({Tab, active_replicas}, Node).
del_active_replica(Tab, Node) ->
@@ -1682,7 +1746,8 @@ del_active_replica(Tab, Node) ->
New = lists:sort(Del),
set(Var, mark_blocked_tab(Blocked, New)), % where_to_commit
mnesia_lib:del({Tab, active_replicas}, Node),
- mnesia_lib:del({Tab, where_to_write}, Node).
+ mnesia_lib:del({Tab, where_to_write}, Node),
+ update_where_to_wlock(Tab).
change_table_access_mode(Cs) ->
W = fun() ->
@@ -1691,7 +1756,22 @@ change_table_access_mode(Cs) ->
val({Tab, active_replicas}))
end,
update(W).
-
+
+change_table_majority(Cs) ->
+ W = fun() ->
+ Tab = Cs#cstruct.name,
+ set({Tab, majority}, Cs#cstruct.majority),
+ update_where_to_wlock(Tab)
+ end,
+ update(W).
+
+update_where_to_wlock(Tab) ->
+ WNodes = val({Tab, where_to_write}),
+ Majority = case catch val({Tab, majority}) of
+ true -> true;
+ _ -> false
+ end,
+ set({Tab, where_to_wlock}, {WNodes, Majority}).
%% node To now has tab loaded, but this must be undone
%% This code is rpc:call'ed from the tab_copier process
diff --git a/lib/mnesia/src/mnesia_dumper.erl b/lib/mnesia/src/mnesia_dumper.erl
index 644133cf5d..f8d7664156 100644
--- a/lib/mnesia/src/mnesia_dumper.erl
+++ b/lib/mnesia/src/mnesia_dumper.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -214,7 +214,12 @@ insert_rec(Rec, InPlace, InitBy, LogV) when is_record(Rec, commit) ->
{Tid, committed} ->
do_insert_rec(Tid, Rec, InPlace, InitBy, LogV);
{Tid, aborted} ->
- mnesia_schema:undo_prepare_commit(Tid, Rec)
+ case InitBy of
+ startup ->
+ mnesia_schema:undo_prepare_commit(Tid, Rec);
+ _ ->
+ ok
+ end
end;
insert_rec(H, _InPlace, _InitBy, _LogV) when is_record(H, log_header) ->
CurrentVersion = mnesia_log:version(),
@@ -359,7 +364,7 @@ dets_insert(Op,Tab,Key,Val) ->
ok = dets:delete_object(Tab, Val);
clear_table ->
dets_cleared(Tab),
- ok = dets:match_delete(Tab, '_')
+ ok = dets:delete_all_objects(Tab)
end.
dets_updated(Tab,Key) ->
@@ -871,7 +876,11 @@ insert_op(Tid, _, {op, add_index, Pos, TabDef}, InPlace, InitBy) ->
startup ->
ignore;
_ ->
- mnesia_index:init_indecies(Tab, Storage, [Pos])
+ case val({Tab,where_to_read}) of
+ nowhere -> ignore;
+ _ ->
+ mnesia_index:init_indecies(Tab, Storage, [Pos])
+ end
end;
insert_op(Tid, _, {op, del_index, Pos, TabDef}, InPlace, InitBy) ->
@@ -896,6 +905,14 @@ insert_op(Tid, _, {op, change_table_access_mode,TabDef, _OldAccess, _Access}, In
end,
insert_cstruct(Tid, Cs, true, InPlace, InitBy);
+insert_op(Tid, _, {op, change_table_majority,TabDef, _OldAccess, _Access}, InPlace, InitBy) ->
+ Cs = mnesia_schema:list2cs(TabDef),
+ case InitBy of
+ startup -> ignore;
+ _ -> mnesia_controller:change_table_majority(Cs)
+ end,
+ insert_cstruct(Tid, Cs, true, InPlace, InitBy);
+
insert_op(Tid, _, {op, change_table_load_order, TabDef, _OldLevel, _Level}, InPlace, InitBy) ->
Cs = mnesia_schema:list2cs(TabDef),
insert_cstruct(Tid, Cs, true, InPlace, InitBy);
diff --git a/lib/mnesia/src/mnesia_lib.erl b/lib/mnesia/src/mnesia_lib.erl
index 36bcfe8de9..ae6631646c 100644
--- a/lib/mnesia/src/mnesia_lib.erl
+++ b/lib/mnesia/src/mnesia_lib.erl
@@ -96,6 +96,8 @@
exists/1,
fatal/2,
get_node_number/0,
+ have_majority/2,
+ have_majority/3,
fix_error/1,
important/2,
incr_counter/1,
@@ -411,7 +413,7 @@ pr_other(Var, Other) ->
[self(), process_info(self(), registered_name),
Var, Other, Why]),
case Other of
- {badarg, [{ets, lookup_element, _}|_]} ->
+ {badarg, [{ets, lookup_element, _, _}|_]} ->
exit(Why);
_ ->
erlang:error(Why)
@@ -660,6 +662,14 @@ proc_info(_) -> false.
get_node_number() ->
{node(), self()}.
+have_majority(Tab, HaveNodes) ->
+ have_majority(Tab, val({Tab, all_nodes}), HaveNodes).
+
+have_majority(_Tab, AllNodes, HaveNodes) ->
+ Missing = AllNodes -- HaveNodes,
+ Present = AllNodes -- Missing,
+ length(Present) > length(Missing).
+
read_log_files() ->
[{F, catch file:read_file(F)} || F <- mnesia_log:log_files()].
@@ -1131,12 +1141,18 @@ db_erase(ram_copies, Tab, Key) -> ?ets_delete(Tab, Key), ok;
db_erase(disc_copies, Tab, Key) -> ?ets_delete(Tab, Key), ok;
db_erase(disc_only_copies, Tab, Key) -> dets:delete(Tab, Key).
+db_match_erase(Tab, '_') ->
+ db_delete_all(val({Tab, storage_type}),Tab);
db_match_erase(Tab, Pat) ->
db_match_erase(val({Tab, storage_type}), Tab, Pat).
db_match_erase(ram_copies, Tab, Pat) -> ?ets_match_delete(Tab, Pat), ok;
db_match_erase(disc_copies, Tab, Pat) -> ?ets_match_delete(Tab, Pat), ok;
db_match_erase(disc_only_copies, Tab, Pat) -> dets:match_delete(Tab, Pat).
+db_delete_all(ram_copies, Tab) -> ets:delete_all_objects(Tab);
+db_delete_all(disc_copies, Tab) -> ets:delete_all_objects(Tab);
+db_delete_all(disc_only_copies, Tab) -> dets:delete_all_objects(Tab).
+
db_first(Tab) ->
db_first(val({Tab, storage_type}), Tab).
db_first(ram_copies, Tab) -> ?ets_first(Tab);
diff --git a/lib/mnesia/src/mnesia_loader.erl b/lib/mnesia/src/mnesia_loader.erl
index 3de329503e..c4b22814a8 100644
--- a/lib/mnesia/src/mnesia_loader.erl
+++ b/lib/mnesia/src/mnesia_loader.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The 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,7 +27,6 @@
net_load_table/4,
send_table/3]).
--export([old_node_init_table/6]). %% Spawned old node protocol conversion hack
-export([spawned_receiver/8]). %% Spawned lock taking process
-import(mnesia_lib, [set/2, fatal/2, verbose/2, dbg_out/2]).
@@ -36,7 +35,7 @@
val(Var) ->
case ?catch_val(Var) of
- {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
+ {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
Value -> Value
end.
@@ -51,7 +50,7 @@ disc_load_table(Tab, Reason) ->
?eval_debug_fun({?MODULE, do_get_disc_copy},
[{tab, Tab},
{reason, Reason},
- {storage, Storage},
+ {storage, Storage},
{type, Type}]),
do_get_disc_copy2(Tab, Reason, Storage, Type).
@@ -63,19 +62,19 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_copies ->
%% NOW we create the actual table
Repair = mnesia_monitor:get_env(auto_repair),
Args = [{keypos, 2}, public, named_table, Type],
- case Reason of
+ case Reason of
{dumper, _} -> %% Resources allready allocated
ignore;
_ ->
mnesia_monitor:mktab(Tab, Args),
- Count = mnesia_log:dcd2ets(Tab, Repair),
+ Count = mnesia_log:dcd2ets(Tab, Repair),
case ets:info(Tab, size) of
X when X < Count * 4 ->
- ok = mnesia_log:ets2dcd(Tab);
+ ok = mnesia_log:ets2dcd(Tab);
_ ->
ignore
end
- end,
+ end,
mnesia_index:init_index(Tab, Storage),
snmpify(Tab, Storage),
set({Tab, load_node}, node()),
@@ -84,7 +83,7 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_copies ->
do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == ram_copies ->
Args = [{keypos, 2}, public, named_table, Type],
- case Reason of
+ case Reason of
{dumper, _} -> %% Resources allready allocated
ignore;
_ ->
@@ -94,12 +93,12 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == ram_copies ->
Repair = mnesia_monitor:get_env(auto_repair),
case mnesia_monitor:use_dir() of
true ->
- case mnesia_lib:exists(Fname) of
+ case mnesia_lib:exists(Fname) of
true -> mnesia_log:dcd2ets(Tab, Repair);
false ->
case mnesia_lib:exists(Datname) of
true ->
- mnesia_lib:dets_to_ets(Tab, Tab, Datname,
+ mnesia_lib:dets_to_ets(Tab, Tab, Datname,
Type, Repair, no);
false ->
false
@@ -154,11 +153,11 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_only_copies -
%% Disable rehashing of table
%% Release read lock on table
%% Send table to receiver in chunks
-%%
+%%
%% Grab read lock on table
%% Block dirty updates
%% Update wherabouts
-%%
+%%
%% Cancel the update subscription
%% Process the subscription events
%% Optionally dump to disc
@@ -166,7 +165,7 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_only_copies -
%% Release read lock on table
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--define(MAX_TRANSFER_SIZE, 7500).
+-define(MAX_TRANSFER_SIZE, 7500).
-define(MAX_RAM_FILE_SIZE, 1000000).
-define(MAX_RAM_TRANSFERS, (?MAX_RAM_FILE_SIZE div ?MAX_TRANSFER_SIZE) + 1).
-define(MAX_NOPACKETS, 20).
@@ -187,14 +186,14 @@ try_net_load_table(Tab, Reason, Ns, Cs) ->
do_get_network_copy(Tab, _Reason, _Ns, unknown, _Cs) ->
verbose("Local table copy of ~p has recently been deleted, ignored.~n", [Tab]),
{not_loaded, storage_unknown};
-do_get_network_copy(Tab, Reason, Ns, Storage, Cs) ->
+do_get_network_copy(Tab, Reason, Ns, Storage, Cs) ->
[Node | Tail] = Ns,
case lists:member(Node,val({current, db_nodes})) of
true ->
dbg_out("Getting table ~p (~p) from node ~p: ~p~n",
[Tab, Storage, Node, Reason]),
?eval_debug_fun({?MODULE, do_get_network_copy},
- [{tab, Tab}, {reason, Reason},
+ [{tab, Tab}, {reason, Reason},
{nodes, Ns}, {storage, Storage}]),
case init_receiver(Node, Tab, Storage, Cs, Reason) of
ok ->
@@ -208,7 +207,7 @@ do_get_network_copy(Tab, Reason, Ns, Storage, Cs) ->
restart ->
try_net_load_table(Tab, Reason, Tail ++ [Node], Cs);
down ->
- try_net_load_table(Tab, Reason, Tail, Cs)
+ try_net_load_table(Tab, Reason, Tail, Cs)
end;
false ->
try_net_load_table(Tab, Reason, Tail, Cs)
@@ -223,10 +222,10 @@ do_snmpify(Tab, Us, Storage) ->
Snmp = mnesia_snmp_hook:create_table(Us, Tab, Storage),
set({Tab, {index, snmp}}, Snmp).
-%% Start the recieiver
+%% Start the recieiver
init_receiver(Node, Tab, Storage, Cs, Reas={dumper,add_table_copy}) ->
case start_remote_sender(Node, Tab, Storage) of
- {SenderPid, TabSize, DetsData} ->
+ {SenderPid, TabSize, DetsData} ->
start_receiver(Tab,Storage,Cs,SenderPid,TabSize,DetsData,Reas);
Else ->
Else
@@ -234,21 +233,21 @@ init_receiver(Node, Tab, Storage, Cs, Reas={dumper,add_table_copy}) ->
init_receiver(Node, Tab,Storage,Cs,Reason) ->
%% Grab a schema lock to avoid deadlock between table_loader and schema_commit dumping.
%% Both may grab tables-locks in different order.
- Load =
- fun() ->
- {_,Tid,Ts} = get(mnesia_activity_state),
+ Load =
+ fun() ->
+ {_,Tid,Ts} = get(mnesia_activity_state),
mnesia_locker:rlock(Tid, Ts#tidstore.store, {schema, Tab}),
- %% Check that table still exists
+ %% Check that table still exists
Active = val({Tab, active_replicas}),
%% Check that we havn't loaded it already
case val({Tab,where_to_read}) == node() of
true -> ok;
_ ->
- %% And that sender still got a copy
- %% (something might have happend while
+ %% And that sender still got a copy
+ %% (something might have happend while
%% we where waiting for the lock)
true = lists:member(Node, Active),
- {SenderPid, TabSize, DetsData} =
+ {SenderPid, TabSize, DetsData} =
start_remote_sender(Node,Tab,Storage),
Init = table_init_fun(SenderPid),
Args = [self(),Tab,Storage,Cs,SenderPid,
@@ -258,18 +257,18 @@ init_receiver(Node, Tab,Storage,Cs,Reason) ->
wait_on_load_complete(Pid)
end
end,
- Res =
+ Res =
case mnesia:transaction(Load, 20) of
- {atomic, {error,Result}} when
- element(1,Reason) == dumper ->
+ {atomic, {error,Result}} when
+ element(1,Reason) == dumper ->
{error,Result};
- {atomic, {error,Result}} ->
+ {atomic, {error,Result}} ->
fatal("Cannot create table ~p: ~p~n",
[[Tab, Storage], Result]);
{atomic, Result} -> Result;
{aborted, nomore} -> restart;
- {aborted, _Reas} ->
- verbose("Receiver failed on ~p from ~p:~nReason: ~p~n",
+ {aborted, _Reas} ->
+ verbose("Receiver failed on ~p from ~p:~nReason: ~p~n",
[Tab,Node,_Reas]),
down %% either this node or sender is dying
end,
@@ -279,7 +278,7 @@ init_receiver(Node, Tab,Storage,Cs,Reason) ->
start_remote_sender(Node,Tab,Storage) ->
mnesia_controller:start_remote_sender(Node, Tab, self(), Storage),
put(mnesia_table_sender_node, {Tab, Node}),
- receive
+ receive
{SenderPid, {first, TabSize}} ->
{SenderPid, TabSize, false};
{SenderPid, {first, TabSize, DetsData}} ->
@@ -291,22 +290,14 @@ start_remote_sender(Node,Tab,Storage) ->
end.
table_init_fun(SenderPid) ->
- PConv = mnesia_monitor:needs_protocol_conversion(node(SenderPid)),
- MeMyselfAndI = self(),
fun(read) ->
- Receiver =
- if
- PConv == true ->
- MeMyselfAndI ! {actual_tabrec, self()},
- MeMyselfAndI; %% Old mnesia
- PConv == false -> self()
- end,
+ Receiver = self(),
SenderPid ! {Receiver, more},
get_data(SenderPid, Receiver)
end.
%% Add_table_copy get's it's own locks.
-start_receiver(Tab,Storage,Cs,SenderPid,TabSize,DetsData,{dumper,add_table_copy}) ->
+start_receiver(Tab,Storage,Cs,SenderPid,TabSize,DetsData,{dumper,add_table_copy}) ->
Init = table_init_fun(SenderPid),
case do_init_table(Tab,Storage,Cs,SenderPid,TabSize,DetsData,self(), Init) of
Err = {error, _} ->
@@ -317,8 +308,8 @@ start_receiver(Tab,Storage,Cs,SenderPid,TabSize,DetsData,{dumper,add_table_copy}
end.
spawned_receiver(ReplyTo,Tab,Storage,Cs, SenderPid,TabSize,DetsData, Init) ->
- process_flag(trap_exit, true),
- Done = do_init_table(Tab,Storage,Cs,
+ process_flag(trap_exit, true),
+ Done = do_init_table(Tab,Storage,Cs,
SenderPid,TabSize,DetsData,
ReplyTo, Init),
ReplyTo ! {self(),Done},
@@ -327,17 +318,17 @@ spawned_receiver(ReplyTo,Tab,Storage,Cs, SenderPid,TabSize,DetsData, Init) ->
exit(normal).
wait_on_load_complete(Pid) ->
- receive
- {Pid, Res} ->
+ receive
+ {Pid, Res} ->
Res;
- {'EXIT', Pid, Reason} ->
+ {'EXIT', Pid, Reason} ->
exit(Reason);
- Else ->
+ Else ->
Pid ! Else,
wait_on_load_complete(Pid)
end.
-do_init_table(Tab,Storage,Cs,SenderPid,
+do_init_table(Tab,Storage,Cs,SenderPid,
TabSize,DetsInfo,OrigTabRec,Init) ->
case create_table(Tab, TabSize, Storage, Cs) of
{Storage,Tab} ->
@@ -345,11 +336,9 @@ do_init_table(Tab,Storage,Cs,SenderPid,
Node = node(SenderPid),
put(mnesia_table_receiver, {Tab, Node, SenderPid}),
mnesia_tm:block_tab(Tab),
- PConv = mnesia_monitor:needs_protocol_conversion(Node),
-
- case init_table(Tab,Storage,Init,PConv,DetsInfo,SenderPid) of
- ok ->
- tab_receiver(Node,Tab,Storage,Cs,PConv,OrigTabRec);
+ case init_table(Tab,Storage,Init,DetsInfo,SenderPid) of
+ ok ->
+ tab_receiver(Node,Tab,Storage,Cs,OrigTabRec);
Reason ->
Msg = "[d]ets:init table failed",
verbose("~s: ~p: ~p~n", [Msg, Tab, Reason]),
@@ -360,7 +349,7 @@ do_init_table(Tab,Storage,Cs,SenderPid,
end.
create_table(Tab, TabSize, Storage, Cs) ->
- if
+ if
Storage == disc_only_copies ->
mnesia_lib:lock_table(Tab),
Tmp = mnesia_lib:tab2tmp(Tab),
@@ -390,54 +379,30 @@ create_table(Tab, TabSize, Storage, Cs) ->
end
end.
-tab_receiver(Node, Tab, Storage, Cs, PConv, OrigTabRec) ->
+tab_receiver(Node, Tab, Storage, Cs, OrigTabRec) ->
receive
- {SenderPid, {no_more, DatBin}} when PConv == false ->
+ {SenderPid, {no_more, DatBin}} ->
finish_copy(Storage,Tab,Cs,SenderPid,DatBin,OrigTabRec);
-
- %% Protocol conversion hack
- {SenderPid, {no_more, DatBin}} when is_pid(PConv) ->
- PConv ! {SenderPid, no_more},
- receive
- {old_init_table_complete, ok} ->
- finish_copy(Storage, Tab, Cs, SenderPid, DatBin,OrigTabRec);
- {old_init_table_complete, Reason} ->
- Msg = "OLD: [d]ets:init table failed",
- verbose("~s: ~p: ~p~n", [Msg, Tab, Reason]),
- down(Tab, Storage)
- end;
-
- {actual_tabrec, Pid} ->
- tab_receiver(Node, Tab, Storage, Cs, Pid,OrigTabRec);
-
- {SenderPid, {more, [Recs]}} when is_pid(PConv) ->
- PConv ! {SenderPid, {more, Recs}}, %% Forward Msg to OldNodes
- tab_receiver(Node, Tab, Storage, Cs, PConv,OrigTabRec);
- {'EXIT', PConv, Reason} -> %% [d]ets:init process crashed
- Msg = "Receiver crashed",
- verbose("~s: ~p: ~p~n", [Msg, Tab, Reason]),
- down(Tab, Storage);
-
%% Protocol conversion hack
{copier_done, Node} ->
verbose("Sender of table ~p crashed on node ~p ~n", [Tab, Node]),
down(Tab, Storage);
-
+
{'EXIT', Pid, Reason} ->
handle_exit(Pid, Reason),
- tab_receiver(Node, Tab, Storage, Cs, PConv,OrigTabRec)
+ tab_receiver(Node, Tab, Storage, Cs, OrigTabRec)
end.
make_table_fun(Pid, TabRec) ->
fun(close) ->
ok;
(read) ->
- get_data(Pid, TabRec)
+ get_data(Pid, TabRec)
end.
get_data(Pid, TabRec) ->
- receive
+ receive
{Pid, {more_z, CompressedRecs}} when is_binary(CompressedRecs) ->
Pid ! {TabRec, more},
{zlib_uncompress(CompressedRecs), make_table_fun(Pid,TabRec)};
@@ -448,7 +413,7 @@ get_data(Pid, TabRec) ->
end_of_input;
{copier_done, Node} ->
case node(Pid) of
- Node ->
+ Node ->
{copier_done, Node};
_ ->
get_data(Pid, TabRec)
@@ -458,13 +423,13 @@ get_data(Pid, TabRec) ->
get_data(Pid, TabRec)
end.
-init_table(Tab, disc_only_copies, Fun, false, DetsInfo,Sender) ->
+init_table(Tab, disc_only_copies, Fun, DetsInfo,Sender) ->
ErtsVer = erlang:system_info(version),
case DetsInfo of
- {ErtsVer, DetsData} ->
+ {ErtsVer, DetsData} ->
Res = (catch dets:is_compatible_bchunk_format(Tab, DetsData)),
case Res of
- {'EXIT',{undef,[{dets,_,_}|_]}} ->
+ {'EXIT',{undef,[{dets,_,_,_}|_]}} ->
Sender ! {self(), {old_protocol, Tab}},
dets:init_table(Tab, Fun); %% Old dets version
{'EXIT', What} ->
@@ -481,28 +446,19 @@ init_table(Tab, disc_only_copies, Fun, false, DetsInfo,Sender) ->
_ ->
dets:init_table(Tab, Fun)
end;
-init_table(Tab, _, Fun, false, _DetsInfo,_) ->
+init_table(Tab, _, Fun, _DetsInfo,_) ->
case catch ets:init_table(Tab, Fun) of
true ->
ok;
{'EXIT', Else} -> Else
- end;
-init_table(Tab, Storage, Fun, true, _DetsInfo, Sender) -> %% Old Nodes
- spawn_link(?MODULE, old_node_init_table,
- [Tab, Storage, Fun, self(), false, Sender]),
- ok.
+ end.
-old_node_init_table(Tab, Storage, Fun, TabReceiver, DetsInfo,Sender) ->
- Res = init_table(Tab, Storage, Fun, false, DetsInfo,Sender),
- TabReceiver ! {old_init_table_complete, Res},
- unlink(TabReceiver),
- ok.
finish_copy(Storage,Tab,Cs,SenderPid,DatBin,OrigTabRec) ->
TabRef = {Storage, Tab},
subscr_receiver(TabRef, Cs#cstruct.record_name),
case handle_last(TabRef, Cs#cstruct.type, DatBin) of
- ok ->
+ ok ->
mnesia_index:init_index(Tab, Storage),
snmpify(Tab, Storage),
%% OrigTabRec must not be the spawned tab-receiver
@@ -534,7 +490,7 @@ subscr_receiver(TabRef = {_, Tab}, RecName) ->
ok
end.
-handle_event(TabRef, write, Rec) ->
+handle_event(TabRef, write, Rec) ->
db_put(TabRef, Rec);
handle_event(TabRef, delete, {_Tab, Key}) ->
db_erase(TabRef, Key);
@@ -545,8 +501,8 @@ handle_event(TabRef, clear_table, {_Tab, _Key}) ->
handle_last({disc_copies, Tab}, _Type, nobin) ->
Ret = mnesia_log:ets2dcd(Tab),
- Fname = mnesia_lib:tab2dat(Tab),
- case mnesia_lib:exists(Fname) of
+ Fname = mnesia_lib:tab2dat(Tab),
+ case mnesia_lib:exists(Fname) of
true -> %% Remove old .DAT files.
file:delete(Fname);
false ->
@@ -653,31 +609,29 @@ send_table(Pid, Tab, RemoteS) ->
{error, {no_exists, Tab}};
Storage ->
%% Send first
- TabSize = mnesia:table_info(Tab, size),
- Pconvert = mnesia_monitor:needs_protocol_conversion(node(Pid)),
+ TabSize = mnesia:table_info(Tab, size),
KeysPerTransfer = calc_nokeys(Storage, Tab),
ChunkData = dets:info(Tab, bchunk_format),
- UseDetsChunk =
- Storage == RemoteS andalso
- Storage == disc_only_copies andalso
- ChunkData /= undefined andalso
- Pconvert == false,
- if
+ UseDetsChunk =
+ Storage == RemoteS andalso
+ Storage == disc_only_copies andalso
+ ChunkData /= undefined,
+ if
UseDetsChunk == true ->
DetsInfo = erlang:system_info(version),
Pid ! {self(), {first, TabSize, {DetsInfo, ChunkData}}};
true ->
Pid ! {self(), {first, TabSize}}
end,
-
+
%% Debug info
put(mnesia_table_sender, {Tab, node(Pid), Pid}),
{Init, Chunk} = reader_funcs(UseDetsChunk, Tab, Storage, KeysPerTransfer),
-
+
SendIt = fun() ->
prepare_copy(Pid, Tab, Storage),
- send_more(Pid, 1, Chunk, Init(), Tab, Pconvert),
+ send_more(Pid, 1, Chunk, Init(), Tab),
finish_copy(Pid, Tab, Storage, RemoteS)
end,
@@ -698,11 +652,11 @@ send_table(Pid, Tab, RemoteS) ->
{error, Reason}
end
end.
-
+
prepare_copy(Pid, Tab, Storage) ->
Trans =
fun() ->
- mnesia:write_lock_table(Tab),
+ mnesia:lock_table(Tab, load),
mnesia_subscr:subscribe(Pid, {table, Tab}),
update_where_to_write(Tab, node(Pid)),
mnesia_lib:db_fixtable(Storage, Tab, true),
@@ -717,11 +671,11 @@ prepare_copy(Pid, Tab, Storage) ->
update_where_to_write(Tab, Node) ->
case val({Tab, access_mode}) of
- read_only ->
+ read_only ->
ignore;
- read_write ->
+ read_write ->
Current = val({current, db_nodes}),
- Ns =
+ Ns =
case lists:member(Node, Current) of
true -> Current;
false -> [Node | Current]
@@ -729,27 +683,27 @@ update_where_to_write(Tab, Node) ->
update_where_to_write(Ns, Tab, Node)
end.
-update_where_to_write([], _, _) ->
+update_where_to_write([], _, _) ->
ok;
update_where_to_write([H|T], Tab, AddNode) ->
- rpc:call(H, mnesia_controller, call,
+ rpc:call(H, mnesia_controller, call,
[{update_where_to_write, [add, Tab, AddNode], self()}]),
update_where_to_write(T, Tab, AddNode).
-send_more(Pid, N, Chunk, DataState, Tab, OldNode) ->
+send_more(Pid, N, Chunk, DataState, Tab) ->
receive
{NewPid, more} ->
- case send_packet(N - 1, NewPid, Chunk, DataState, OldNode) of
- New when is_integer(New) ->
+ case send_packet(N - 1, NewPid, Chunk, DataState) of
+ New when is_integer(New) ->
New - 1;
NewData ->
- send_more(NewPid, ?MAX_NOPACKETS, Chunk, NewData, Tab, OldNode)
+ send_more(NewPid, ?MAX_NOPACKETS, Chunk, NewData, Tab)
end;
{_NewPid, {old_protocol, Tab}} ->
Storage = val({Tab, storage_type}),
- {Init, NewChunk} =
+ {Init, NewChunk} =
reader_funcs(false, Tab, Storage, calc_nokeys(Storage, Tab)),
- send_more(Pid, 1, NewChunk, Init(), Tab, OldNode);
+ send_more(Pid, 1, NewChunk, Init(), Tab);
{copier_done, Node} when Node == node(Pid)->
verbose("Receiver of table ~p crashed on ~p (more)~n", [Tab, Node]),
@@ -770,7 +724,7 @@ dets_bchunk(Tab, Chunk) -> %% Arrg
case dets:bchunk(Tab, Chunk) of
{Cont, Data} -> {Data, Cont};
Else -> Else
- end.
+ end.
zlib_compress(Data, Level) ->
BinData = term_to_binary(Data),
@@ -793,28 +747,20 @@ compression_level() ->
Val -> Val
end.
-send_packet(N, Pid, _Chunk, '$end_of_table', OldNode) ->
- case OldNode of
- true -> ignore; %% Old nodes can't handle the new no_more
- false -> Pid ! {self(), no_more}
- end,
+send_packet(N, Pid, _Chunk, '$end_of_table') ->
+ Pid ! {self(), no_more},
N;
-send_packet(N, Pid, Chunk, {[], Cont}, OldNode) ->
- send_packet(N, Pid, Chunk, Chunk(Cont), OldNode);
-send_packet(N, Pid, Chunk, {Recs, Cont}, OldNode) when N < ?MAX_NOPACKETS ->
- case OldNode of
- true ->
- Pid ! {self(), {more, [Recs]}}; %% Old need's wrapping list
- false ->
- case compression_level() of
- 0 ->
- Pid ! {self(), {more, Recs}};
- Level ->
- Pid ! {self(), {more_z, zlib_compress(Recs, Level)}}
- end
+send_packet(N, Pid, Chunk, {[], Cont}) ->
+ send_packet(N, Pid, Chunk, Chunk(Cont));
+send_packet(N, Pid, Chunk, {Recs, Cont}) when N < ?MAX_NOPACKETS ->
+ case compression_level() of
+ 0 ->
+ Pid ! {self(), {more, Recs}};
+ Level ->
+ Pid ! {self(), {more_z, zlib_compress(Recs, Level)}}
end,
- send_packet(N+1, Pid, Chunk, Chunk(Cont), OldNode);
-send_packet(_N, _Pid, _Chunk, DataState, _OldNode) ->
+ send_packet(N+1, Pid, Chunk, Chunk(Cont));
+send_packet(_N, _Pid, _Chunk, DataState) ->
DataState.
finish_copy(Pid, Tab, Storage, RemoteS) ->
@@ -855,5 +801,5 @@ dat2bin(_Tab, _LocalS, _RemoteS) ->
handle_exit(Pid, Reason) when node(Pid) == node() ->
exit(Reason);
-handle_exit(_Pid, _Reason) -> %% Not from our node, this will be handled by
+handle_exit(_Pid, _Reason) -> %% Not from our node, this will be handled by
ignore. %% mnesia_down soon.
diff --git a/lib/mnesia/src/mnesia_locker.erl b/lib/mnesia/src/mnesia_locker.erl
index ca0cc79c45..0492d794f3 100644
--- a/lib/mnesia/src/mnesia_locker.erl
+++ b/lib/mnesia/src/mnesia_locker.erl
@@ -40,7 +40,8 @@
sticky_wlock_table/3,
wlock/3,
wlock_no_exist/4,
- wlock_table/3
+ wlock_table/3,
+ load_lock_table/3
]).
%% sys callback functions
@@ -656,16 +657,17 @@ rwlock(Tid, Store, Oid) ->
Lock = write,
case need_lock(Store, Tab, Key, Lock) of
yes ->
- Ns = w_nodes(Tab),
+ {Ns, Majority} = w_nodes(Tab),
+ check_majority(Majority, Tab, Ns),
Res = get_rwlocks_on_nodes(Ns, rwlock, Node, Store, Tid, Oid),
?ets_insert(Store, {{locks, Tab, Key}, Lock}),
Res;
no ->
if
Key == ?ALL ->
- w_nodes(Tab);
+ element(2, w_nodes(Tab));
Tab == ?GLOBAL ->
- w_nodes(Tab);
+ element(2, w_nodes(Tab));
true ->
dirty_rpc(Node, Tab, Key, Lock)
end
@@ -677,12 +679,34 @@ rwlock(Tid, Store, Oid) ->
%% in the local store under the key == nodes
w_nodes(Tab) ->
- Nodes = ?catch_val({Tab, where_to_write}),
- case Nodes of
- [_ | _] -> Nodes;
+ case ?catch_val({Tab, where_to_wlock}) of
+ {[_ | _], _} = Where -> Where;
_ -> mnesia:abort({no_exists, Tab})
end.
+%% If the table has the 'majority' flag set, we can
+%% only take a write lock if we see a majority of the
+%% nodes.
+
+
+check_majority(true, Tab, HaveNs) ->
+ check_majority(Tab, HaveNs);
+check_majority(false, _, _) ->
+ ok.
+
+check_majority(Tab, HaveNs) ->
+ case ?catch_val({Tab, majority}) of
+ true ->
+ case mnesia_lib:have_majority(Tab, HaveNs) of
+ true ->
+ ok;
+ false ->
+ mnesia:abort({no_majority, Tab})
+ end;
+ _ ->
+ ok
+ end.
+
%% aquire a sticky wlock, a sticky lock is a lock
%% which remains at this node after the termination of the
%% transaction.
@@ -708,12 +732,14 @@ sticky_lock(Tid, Store, {Tab, Key} = Oid, Lock) ->
end.
do_sticky_lock(Tid, Store, {Tab, Key} = Oid, Lock) ->
+ {WNodes, Majority} = w_nodes(Tab),
+ sticky_check_majority(Lock, Tab, Majority, WNodes),
?MODULE ! {self(), {test_set_sticky, Tid, Oid, Lock}},
N = node(),
receive
{?MODULE, N, granted} ->
?ets_insert(Store, {{locks, Tab, Key}, write}),
- [?ets_insert(Store, {nodes, Node}) || Node <- w_nodes(Tab)],
+ [?ets_insert(Store, {nodes, Node}) || Node <- WNodes],
granted;
{?MODULE, N, {granted, Val}} -> %% for rwlocks
case opt_lookup_in_client(Val, Oid, write) of
@@ -721,7 +747,7 @@ do_sticky_lock(Tid, Store, {Tab, Key} = Oid, Lock) ->
exit({aborted, C});
Val2 ->
?ets_insert(Store, {{locks, Tab, Key}, write}),
- [?ets_insert(Store, {nodes, Node}) || Node <- w_nodes(Tab)],
+ [?ets_insert(Store, {nodes, Node}) || Node <- WNodes],
Val2
end;
{?MODULE, N, {not_granted, Reason}} ->
@@ -737,6 +763,16 @@ do_sticky_lock(Tid, Store, {Tab, Key} = Oid, Lock) ->
dirty_sticky_lock(Tab, Key, [N], Lock)
end.
+sticky_check_majority(W, Tab, true, WNodes) when W==write; W==read_write ->
+ case mnesia_lib:have_majority(Tab, WNodes) of
+ true ->
+ ok;
+ false ->
+ mnesia:abort({no_majority, Tab})
+ end;
+sticky_check_majority(_, _, _, _) ->
+ ok.
+
not_stuck(Tid, Store, Tab, _Key, Oid, _Lock, N) ->
rlock(Tid, Store, {Tab, ?ALL}), %% needed?
wlock(Tid, Store, Oid), %% perfect sync
@@ -773,22 +809,33 @@ sticky_wlock_table(Tid, Store, Tab) ->
%% local store when we have aquired the lock.
%%
wlock(Tid, Store, Oid) ->
+ wlock(Tid, Store, Oid, _CheckMajority = true).
+
+wlock(Tid, Store, Oid, CheckMajority) ->
{Tab, Key} = Oid,
case need_lock(Store, Tab, Key, write) of
yes ->
- Ns = w_nodes(Tab),
+ {Ns, Majority} = w_nodes(Tab),
+ if CheckMajority ->
+ check_majority(Majority, Tab, Ns);
+ true ->
+ ignore
+ end,
Op = {self(), {write, Tid, Oid}},
?ets_insert(Store, {{locks, Tab, Key}, write}),
get_wlocks_on_nodes(Ns, Ns, Store, Op, Oid);
no when Key /= ?ALL, Tab /= ?GLOBAL ->
[];
no ->
- w_nodes(Tab)
+ element(2, w_nodes(Tab))
end.
wlock_table(Tid, Store, Tab) ->
wlock(Tid, Store, {Tab, ?ALL}).
+load_lock_table(Tid, Store, Tab) ->
+ wlock(Tid, Store, {Tab, ?ALL}, _CheckMajority = false).
+
%% Write lock even if the table does not exist
wlock_no_exist(Tid, Store, Tab, Ns) ->
diff --git a/lib/mnesia/src/mnesia_log.erl b/lib/mnesia/src/mnesia_log.erl
index 9e804cc4c2..94153473cb 100644
--- a/lib/mnesia/src/mnesia_log.erl
+++ b/lib/mnesia/src/mnesia_log.erl
@@ -1021,7 +1021,8 @@ add_recs([LogH|Rest], N)
LogH#log_header.log_version >= "1.0" ->
add_recs(Rest, N);
add_recs([{{Tab, _Key}, _Val, clear_table} | Rest], N) ->
- true = ets:match_delete(Tab, '_'),
- add_recs(Rest, N+ets:info(Tab, size));
+ Size = ets:info(Tab, size),
+ true = ets:delete_all_objects(Tab),
+ add_recs(Rest, N+Size);
add_recs([], N) ->
N.
diff --git a/lib/mnesia/src/mnesia_monitor.erl b/lib/mnesia/src/mnesia_monitor.erl
index b6eda9ad3a..e110ad3241 100644
--- a/lib/mnesia/src/mnesia_monitor.erl
+++ b/lib/mnesia/src/mnesia_monitor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -76,13 +76,13 @@
-include("mnesia.hrl").
--record(state, {supervisor, pending_negotiators = [],
+-record(state, {supervisor, pending_negotiators = [],
going_down = [], tm_started = false, early_connects = [],
connecting, mq = []}).
--define(current_protocol_version, {7,6}).
+-define(current_protocol_version, {8,0}).
--define(previous_protocol_version, {7,5}).
+-define(previous_protocol_version, {7,6}).
start() ->
gen_server:start_link({local, ?MODULE}, ?MODULE,
@@ -151,12 +151,12 @@ check_protocol([{Node, {accept, Mon, Version, Protocol}} | Tail], Protocols) ->
case lists:member(Protocol, Protocols) of
true ->
case Protocol == protocol_version() of
- true ->
+ true ->
set({protocol, Node}, {Protocol, false});
false ->
set({protocol, Node}, {Protocol, true})
end,
- [node(Mon) | check_protocol(Tail, Protocols)];
+ [node(Mon) | check_protocol(Tail, Protocols)];
false ->
verbose("Failed to connect with ~p. ~p protocols rejected. "
"expected version = ~p, expected protocol = ~p~n",
@@ -179,7 +179,7 @@ check_protocol([], [Protocol | _Protocols]) ->
set(protocol_version, Protocol),
[].
-protocol_version() ->
+protocol_version() ->
case ?catch_val(protocol_version) of
{'EXIT', _} -> ?current_protocol_version;
Version -> Version
@@ -189,14 +189,14 @@ protocol_version() ->
%% preferred protocols are first in the list
acceptable_protocol_versions() ->
[protocol_version(), ?previous_protocol_version].
-
+
needs_protocol_conversion(Node) ->
case {?catch_val({protocol, Node}), protocol_version()} of
{{'EXIT', _}, _} ->
false;
- {{_, Bool}, ?current_protocol_version} ->
+ {{_, Bool}, ?current_protocol_version} ->
Bool;
- {{_, Bool}, _} ->
+ {{_, Bool}, _} ->
not Bool
end.
@@ -255,15 +255,15 @@ terminate_proc(Who, Reason, _State) ->
%%----------------------------------------------------------------------
init([Parent]) ->
process_flag(trap_exit, true),
- ?ets_new_table(mnesia_gvar, [set, public, named_table]),
- ?ets_new_table(mnesia_stats, [set, public, named_table]),
+ ?ets_new_table(mnesia_gvar, [set, public, named_table]),
+ ?ets_new_table(mnesia_stats, [set, public, named_table]),
set(subscribers, []),
set(activity_subscribers, []),
mnesia_lib:verbose("~p starting: ~p~n", [?MODULE, self()]),
Version = mnesia:system_info(version),
set(version, Version),
dbg_out("Version: ~p~n", [Version]),
-
+
case catch process_config_args(env()) of
ok ->
mnesia_lib:set({'$$$_report', current_pos}, 0),
@@ -283,7 +283,7 @@ init([Parent]) ->
set(checkpoints, []),
set(pending_checkpoints, []),
set(pending_checkpoint_pids, []),
-
+
{ok, #state{supervisor = Parent}};
{'EXIT', Reason} ->
mnesia_lib:report_fatal("Bad configuration: ~p~n", [Reason]),
@@ -398,9 +398,9 @@ handle_call({unsafe_close_log, Name}, _From, State) ->
disk_log:close(Name),
{reply, ok, State};
-handle_call({negotiate_protocol, Mon, _Version, _Protocols}, _From, State)
+handle_call({negotiate_protocol, Mon, _Version, _Protocols}, _From, State)
when State#state.tm_started == false ->
- State2 = State#state{early_connects = [node(Mon) | State#state.early_connects]},
+ State2 = State#state{early_connects = [node(Mon) | State#state.early_connects]},
{reply, {node(), {reject, self(), uninitialized, uninitialized}}, State2};
%% From remote monitor..
@@ -412,7 +412,7 @@ handle_call({negotiate_protocol, Mon, Version, Protocols}, From, State)
true ->
accept_protocol(Mon, MyVersion, Protocol, From, State);
false ->
- %% in this release we should be able to handle the previous
+ %% in this release we should be able to handle the previous
%% protocol
case hd(Protocols) of
?previous_protocol_version ->
@@ -427,7 +427,7 @@ handle_call({negotiate_protocol, Mon, Version, Protocols}, From, State)
end;
%% Local request to negotiate with other monitors (nodes).
-handle_call({negotiate_protocol, Nodes}, From, State) ->
+handle_call({negotiate_protocol, Nodes}, From, State) ->
case mnesia_lib:intersect(State#state.going_down, Nodes) of
[] ->
spawn_link(?MODULE, negotiate_protocol_impl, [Nodes, From]),
@@ -461,7 +461,7 @@ accept_protocol(Mon, Version, Protocol, From, State) ->
%% No need for wait
link(Mon), %% link to remote Monitor
case Protocol == protocol_version() of
- true ->
+ true ->
set({protocol, Node}, {Protocol, false});
false ->
set({protocol, Node}, {Protocol, true})
@@ -509,7 +509,7 @@ handle_cast({disconnect, Node}, State) ->
ignore;
undefined ->
ignore;
- RemoteMon when is_pid(RemoteMon) ->
+ RemoteMon when is_pid(RemoteMon) ->
unlink(RemoteMon)
end,
{noreply, State};
@@ -534,7 +534,7 @@ handle_info({'EXIT', Pid, R}, State) when Pid == State#state.supervisor ->
dbg_out("~p was ~p by supervisor~n",[?MODULE, R]),
{stop, R, State};
-handle_info({'EXIT', Pid, fatal}, State) when node(Pid) == node() ->
+handle_info({'EXIT', Pid, fatal}, State) when node(Pid) == node() ->
dbg_out("~p got FATAL ERROR from: ~p~n",[?MODULE, Pid]),
exit(State#state.supervisor, shutdown),
{noreply, State};
@@ -550,7 +550,7 @@ handle_info(Msg = {'EXIT',Pid,_}, State) ->
Node /= node() ->
{noreply, State#state{mq = State#state.mq ++ [{info, Msg}]}};
true ->
- %% We have probably got an exit signal from
+ %% We have probably got an exit signal from
%% disk_log or dets
Hint = "Hint: check that the disk still is writable",
fatal("~p got unexpected info: ~p; ~p~n",
@@ -567,10 +567,10 @@ handle_info({nodeup, Node}, State) ->
%% Let's check if Mnesia is running there in order
%% to detect if the network has been partitioned
%% due to communication failure.
-
+
HasDown = mnesia_recover:has_mnesia_down(Node),
ImRunning = mnesia_lib:is_running(),
-
+
if
%% If I'm not running the test will be made later.
HasDown == true, ImRunning == yes ->
@@ -589,7 +589,7 @@ handle_info({disk_log, _Node, Log, Info}, State) ->
{truncated, _No} ->
ok;
_ ->
- mnesia_lib:important("Warning Log file ~p error reason ~s~n",
+ mnesia_lib:important("Warning Log file ~p error reason ~s~n",
[Log, disk_log:format_error(Info)])
end,
{noreply, State};
@@ -681,38 +681,38 @@ env() ->
send_compressed
].
-default_env(access_module) ->
+default_env(access_module) ->
mnesia;
-default_env(auto_repair) ->
+default_env(auto_repair) ->
true;
-default_env(backup_module) ->
+default_env(backup_module) ->
mnesia_backup;
-default_env(debug) ->
+default_env(debug) ->
none;
default_env(dir) ->
Name = lists:concat(["Mnesia.", node()]),
filename:absname(Name);
-default_env(dump_log_load_regulation) ->
+default_env(dump_log_load_regulation) ->
false;
-default_env(dump_log_time_threshold) ->
+default_env(dump_log_time_threshold) ->
timer:minutes(3);
-default_env(dump_log_update_in_place) ->
+default_env(dump_log_update_in_place) ->
true;
default_env(dump_log_write_threshold) ->
1000;
-default_env(embedded_mnemosyne) ->
+default_env(embedded_mnemosyne) ->
false;
-default_env(event_module) ->
+default_env(event_module) ->
mnesia_event;
-default_env(extra_db_nodes) ->
+default_env(extra_db_nodes) ->
[];
-default_env(ignore_fallback_at_startup) ->
+default_env(ignore_fallback_at_startup) ->
false;
default_env(fallback_error_function) ->
{mnesia, lkill};
-default_env(max_wait_for_decision) ->
+default_env(max_wait_for_decision) ->
infinity;
-default_env(schema_location) ->
+default_env(schema_location) ->
opt_disc;
default_env(core_dir) ->
false;
@@ -732,7 +732,7 @@ check_type(Env, Val) ->
NewVal ->
NewVal
end.
-
+
do_check_type(access_module, A) when is_atom(A) -> A;
do_check_type(auto_repair, B) -> bool(B);
do_check_type(backup_module, B) when is_atom(B) -> B;
@@ -749,7 +749,7 @@ do_check_type(dump_log_update_in_place, B) -> bool(B);
do_check_type(dump_log_write_threshold, I) when is_integer(I), I > 0 -> I;
do_check_type(event_module, A) when is_atom(A) -> A;
do_check_type(ignore_fallback_at_startup, B) -> bool(B);
-do_check_type(fallback_error_function, {Mod, Func})
+do_check_type(fallback_error_function, {Mod, Func})
when is_atom(Mod), is_atom(Func) -> {Mod, Func};
do_check_type(embedded_mnemosyne, B) -> bool(B);
do_check_type(extra_db_nodes, L) when is_list(L) ->
@@ -804,8 +804,8 @@ detect_inconcistency(Nodes, Context) ->
has_remote_mnesia_down(Node) ->
HasDown = mnesia_recover:has_mnesia_down(Node),
Master = mnesia_recover:get_master_nodes(schema),
- if
- HasDown == true, Master == [] ->
+ if
+ HasDown == true, Master == [] ->
{true, node()};
true ->
{false, node()}
diff --git a/lib/mnesia/src/mnesia_recover.erl b/lib/mnesia/src/mnesia_recover.erl
index b3eed1de6e..4750291a10 100644
--- a/lib/mnesia/src/mnesia_recover.erl
+++ b/lib/mnesia/src/mnesia_recover.erl
@@ -227,11 +227,13 @@ do_log_decision(D, DoTell, NodeD) ->
note_outcome(D2),
case mnesia_monitor:use_dir() of
true ->
- mnesia_log:append(latest_log, D2),
if
DoTell == true, Outcome /= unclear ->
tell_im_certain(NodeD#decision.disc_nodes--[node()],D2),
- tell_im_certain(NodeD#decision.ram_nodes--[node()], D2);
+ tell_im_certain(NodeD#decision.ram_nodes--[node()], D2),
+ mnesia_log:log(D2);
+ Outcome /= unclear ->
+ mnesia_log:log(D2);
true ->
ignore
end;
diff --git a/lib/mnesia/src/mnesia_schema.erl b/lib/mnesia/src/mnesia_schema.erl
index d1d892a387..05be474aea 100644
--- a/lib/mnesia/src/mnesia_schema.erl
+++ b/lib/mnesia/src/mnesia_schema.erl
@@ -37,6 +37,7 @@
change_table_copy_type/3,
change_table_access_mode/2,
change_table_load_order/2,
+ change_table_majority/2,
change_table_frag/2,
clear_table/1,
create_table/1,
@@ -99,7 +100,7 @@
]).
%% Needed outside to be able to use/set table_properties
-%% from user (not supported)
+%% from user (not supported)
-export([schema_transaction/1,
insert_schema_ops/2,
do_create_table/1,
@@ -117,9 +118,9 @@
%% Here comes the init function which also resides in
%% this module, it is called upon by the trans server
%% at startup of the system
-%%
+%%
%% We have a meta table which looks like
-%% {table, schema,
+%% {table, schema,
%% {type, set},
%% {disc_copies, all},
%% {arity, 2}
@@ -148,14 +149,14 @@ exit_on_error(GoodRes) ->
val(Var) ->
case ?catch_val(Var) of
- {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
- Value -> Value
+ {'EXIT', Reason} -> mnesia_lib:other_val(Var, Reason);
+ Value -> Value
end.
%% This function traverses all cstructs in the schema and
%% sets all values in mnesia_gvar accordingly for each table/cstruct
-set_schema('$end_of_table') ->
+set_schema('$end_of_table') ->
[];
set_schema(Tab) ->
do_set_schema(Tab),
@@ -178,6 +179,8 @@ do_set_schema(Tab, Cs) ->
set({Tab, disc_only_copies}, Cs#cstruct.disc_only_copies),
set({Tab, load_order}, Cs#cstruct.load_order),
set({Tab, access_mode}, Cs#cstruct.access_mode),
+ set({Tab, majority}, Cs#cstruct.majority),
+ set({Tab, all_nodes}, mnesia_lib:cs_to_nodes(Cs)),
set({Tab, snmp}, Cs#cstruct.snmp),
set({Tab, user_properties}, Cs#cstruct.user_properties),
[set({Tab, user_property, element(1, P)}, P) || P <- Cs#cstruct.user_properties],
@@ -250,8 +253,8 @@ version() ->
incr_version(Cs) ->
{{Major, Minor}, _} = Cs#cstruct.version,
Nodes = mnesia_lib:intersect(val({schema, disc_copies}),
- mnesia_lib:cs_to_nodes(Cs)),
- V =
+ mnesia_lib:cs_to_nodes(Cs)),
+ V =
case Nodes -- val({Cs#cstruct.name, active_replicas}) of
[] -> {Major + 1, 0}; % All replicas are active
_ -> {Major, Minor + 1} % Some replicas are inactive
@@ -356,7 +359,7 @@ delete_schema2() ->
{error, Reason} ->
{error, Reason}
end.
-
+
ensure_no_schema([H|T]) when is_atom(H) ->
case rpc:call(H, ?MODULE, remote_read_schema, []) of
{badrpc, Reason} ->
@@ -404,7 +407,7 @@ opt_create_dir(UseDir, Dir) when UseDir == true->
check_can_write(Dir);
false ->
case file:make_dir(Dir) of
- ok ->
+ ok ->
verbose("Create Directory ~p~n", [Dir]),
ok;
{error, Reason} ->
@@ -414,7 +417,7 @@ opt_create_dir(UseDir, Dir) when UseDir == true->
end;
opt_create_dir(false, _) ->
{error, {has_no_disc, node()}}.
-
+
check_can_write(Dir) ->
case file:read_file_info(Dir) of
{ok, FI} when FI#file_info.type == directory,
@@ -447,7 +450,7 @@ read_schema(Keep) ->
read_schema(Keep, IgnoreFallback) ->
lock_schema(),
- Res =
+ Res =
case mnesia:system_info(is_running) of
yes ->
{ok, ram, get_create_list(schema)};
@@ -474,7 +477,7 @@ read_disc_schema(Keep, IgnoreFallback) ->
case mnesia_bup:fallback_exists() of
true when IgnoreFallback == false, Running /= yes ->
mnesia_bup:fallback_to_schema();
- _ ->
+ _ ->
%% If we're running, we read the schema file even
%% if fallback exists
Dat = mnesia_lib:tab2dat(schema),
@@ -496,7 +499,7 @@ read_disc_schema(Keep, IgnoreFallback) ->
end.
do_read_disc_schema(Fname, Keep) ->
- T =
+ T =
case Keep of
false ->
Args = [{keypos, 2}, public, set],
@@ -520,7 +523,7 @@ do_read_disc_schema(Fname, Keep) ->
get_initial_schema(SchemaStorage, Nodes) ->
Cs = #cstruct{name = schema,
record_name = schema,
- attributes = [table, cstruct]},
+ attributes = [table, cstruct]},
Cs2 =
case SchemaStorage of
ram_copies -> Cs#cstruct{ram_copies = Nodes};
@@ -529,7 +532,7 @@ get_initial_schema(SchemaStorage, Nodes) ->
cs2list(Cs2).
read_cstructs_from_disc() ->
- %% Assumptions:
+ %% Assumptions:
%% - local schema lock in global
%% - use_dir is true
%% - Mnesia is not running
@@ -549,14 +552,14 @@ read_cstructs_from_disc() ->
end,
Cstructs = dets:traverse(Tab, Fun),
dets:close(Tab),
- {ok, Cstructs};
+ {ok, Cstructs};
{error, Reason} ->
{error, Reason}
end;
false ->
{error, "No schema file exists"}
end.
-
+
%% We run a very special type of transactions when we
%% we want to manipulate the schema.
@@ -590,20 +593,20 @@ schema_transaction(Fun) ->
%% This process may dump the transaction log, and should
%% therefore not be run in an application process
-%%
+%%
schema_coordinator(Client, _Fun, undefined) ->
Res = {aborted, {node_not_running, node()}},
Client ! {transaction_done, Res, self()},
unlink(Client);
-
+
schema_coordinator(Client, Fun, Controller) when is_pid(Controller) ->
%% Do not trap exit in order to automatically die
%% when the controller dies
link(Controller),
unlink(Client),
-
- %% Fulfull the transaction even if the client dies
+
+ %% Fulfull the transaction even if the client dies
Res = mnesia:transaction(Fun),
Client ! {transaction_done, Res, self()},
unlink(Controller), % Avoids spurious exit message
@@ -616,7 +619,7 @@ schema_coordinator(Client, Fun, Controller) when is_pid(Controller) ->
insert_schema_ops({_Mod, _Tid, Ts}, SchemaIOps) ->
do_insert_schema_ops(Ts#tidstore.store, SchemaIOps).
-
+
do_insert_schema_ops(Store, [Head | Tail]) ->
?ets_insert(Store, Head),
do_insert_schema_ops(Store, Tail);
@@ -625,15 +628,56 @@ do_insert_schema_ops(_Store, []) ->
cs2list(Cs) when is_record(Cs, cstruct) ->
Tags = record_info(fields, cstruct),
- rec2list(Tags, 2, Cs);
+ rec2list(Tags, Tags, 2, Cs);
cs2list(CreateList) when is_list(CreateList) ->
- CreateList.
-
-rec2list([Tag | Tags], Pos, Rec) ->
+ CreateList;
+%% 4.4.19
+cs2list(Cs) when element(1, Cs) == cstruct, tuple_size(Cs) == 18 ->
+ Tags = [name,type,ram_copies,disc_copies,disc_only_copies,
+ load_order,access_mode,majority,index,snmp,local_content,
+ record_name,attributes,user_properties,frag_properties,
+ cookie,version],
+ rec2list(Tags, Tags, 2, Cs);
+%% 4.4.18 and earlier
+cs2list(Cs) when element(1, Cs) == cstruct, tuple_size(Cs) == 17 ->
+ Tags = [name,type,ram_copies,disc_copies,disc_only_copies,
+ load_order,access_mode,index,snmp,local_content,
+ record_name,attributes,user_properties,frag_properties,
+ cookie,version],
+ rec2list(Tags, Tags, 2, Cs).
+
+cs2list(false, Cs) ->
+ cs2list(Cs);
+cs2list(ver4_4_18, Cs) ->
+ Orig = record_info(fields, cstruct),
+ Tags = [name,type,ram_copies,disc_copies,disc_only_copies,
+ load_order,access_mode,index,snmp,local_content,
+ record_name,attributes,user_properties,frag_properties,
+ cookie,version],
+ rec2list(Tags, Orig, 2, Cs);
+cs2list(ver4_4_19, Cs) ->
+ Orig = record_info(fields, cstruct),
+ Tags = [name,type,ram_copies,disc_copies,disc_only_copies,
+ load_order,access_mode,majority,index,snmp,local_content,
+ record_name,attributes,user_properties,frag_properties,
+ cookie,version],
+ rec2list(Tags, Orig, 2, Cs).
+
+rec2list([Tag | Tags], [Tag | Orig], Pos, Rec) ->
Val = element(Pos, Rec),
- [{Tag, Val} | rec2list(Tags, Pos + 1, Rec)];
-rec2list([], _Pos, _Rec) ->
- [].
+ [{Tag, Val} | rec2list(Tags, Orig, Pos + 1, Rec)];
+rec2list([], _, _Pos, _Rec) ->
+ [];
+rec2list(Tags, [_|Orig], Pos, Rec) ->
+ rec2list(Tags, Orig, Pos+1, Rec).
+
+api_list2cs(List) when is_list(List) ->
+ Name = pick(unknown, name, List, must),
+ Keys = check_keys(Name, List, record_info(fields, cstruct)),
+ check_duplicates(Name, Keys),
+ list2cs(List);
+api_list2cs(Other) ->
+ mnesia:abort({badarg, Other}).
list2cs(List) when is_list(List) ->
Name = pick(unknown, name, List, must),
@@ -651,6 +695,7 @@ list2cs(List) when is_list(List) ->
Snmp = pick(Name, snmp, List, []),
LoadOrder = pick(Name, load_order, List, 0),
AccessMode = pick(Name, access_mode, List, read_write),
+ Majority = pick(Name, majority, List, false),
UserProps = pick(Name, user_properties, List, []),
verify({alt, [nil, list]}, mnesia_lib:etype(UserProps),
{bad_type, Name, {user_properties, UserProps}}),
@@ -663,10 +708,7 @@ list2cs(List) when is_list(List) ->
Frag = pick(Name, frag_properties, List, []),
verify({alt, [nil, list]}, mnesia_lib:etype(Frag),
- {badarg, Name, {frag_properties, Frag}}),
-
- Keys = check_keys(Name, List, record_info(fields, cstruct)),
- check_duplicates(Name, Keys),
+ {badarg, Name, {frag_properties, Frag}}),
#cstruct{name = Name,
ram_copies = Rc,
disc_copies = Dc,
@@ -676,15 +718,14 @@ list2cs(List) when is_list(List) ->
snmp = Snmp,
load_order = LoadOrder,
access_mode = AccessMode,
+ majority = Majority,
local_content = LC,
record_name = RecName,
attributes = Attrs,
user_properties = lists:sort(UserProps),
frag_properties = lists:sort(Frag),
cookie = Cookie,
- version = Version};
-list2cs(Other) ->
- mnesia:abort({badarg, Other}).
+ version = Version}.
pick(Tab, Key, List, Default) ->
case lists:keysearch(Key, 1, List) of
@@ -703,7 +744,7 @@ attr_tab_to_pos(_Tab, Pos) when is_integer(Pos) ->
Pos;
attr_tab_to_pos(Tab, Attr) ->
attr_to_pos(Attr, val({Tab, attributes})).
-
+
%% Convert attribute name to integer if neccessary
attr_to_pos(Pos, _Attrs) when is_integer(Pos) ->
Pos;
@@ -718,7 +759,7 @@ attr_to_pos(Attr, [_ | Attrs], Pos) ->
attr_to_pos(Attr, Attrs, Pos + 1);
attr_to_pos(Attr, _, _) ->
mnesia:abort({bad_type, Attr}).
-
+
check_keys(Tab, [{Key, _Val} | Tail], Items) ->
case lists:member(Key, Items) of
true -> [Key | check_keys(Tab, Tail, Items)];
@@ -754,7 +795,7 @@ verify_cstruct(Cs) when is_record(Cs, cstruct) ->
{bad_type, Tab, {type, Type}}),
%% Currently ordered_set is not supported for disk_only_copies.
- if
+ if
Type == ordered_set, Cs#cstruct.disc_only_copies /= [] ->
mnesia:abort({bad_type, Tab, {not_supported, Type, disc_only_copies}});
true ->
@@ -771,10 +812,10 @@ verify_cstruct(Cs) when is_record(Cs, cstruct) ->
Arity = length(Attrs) + 1,
verify(true, Arity > 2, {bad_type, Tab, {attributes, Attrs}}),
-
+
lists:foldl(fun(Attr,_Other) when Attr == snmp ->
mnesia:abort({bad_type, Tab, {attributes, [Attr]}});
- (Attr,Other) ->
+ (Attr,Other) ->
verify(atom, mnesia_lib:etype(Attr),
{bad_type, Tab, {attributes, [Attr]}}),
verify(false, lists:member(Attr, Other),
@@ -787,7 +828,7 @@ verify_cstruct(Cs) when is_record(Cs, cstruct) ->
Index = Cs#cstruct.index,
verify({alt, [nil, list]}, mnesia_lib:etype(Index),
{bad_type, Tab, {index, Index}}),
-
+
IxFun =
fun(Pos) ->
verify(true, fun() ->
@@ -802,14 +843,23 @@ verify_cstruct(Cs) when is_record(Cs, cstruct) ->
{bad_type, Tab, {index, [Pos]}})
end,
lists:foreach(IxFun, Index),
-
+
LC = Cs#cstruct.local_content,
verify({alt, [true, false]}, LC,
{bad_type, Tab, {local_content, LC}}),
Access = Cs#cstruct.access_mode,
verify({alt, [read_write, read_only]}, Access,
{bad_type, Tab, {access_mode, Access}}),
-
+ Majority = Cs#cstruct.majority,
+ verify({alt, [true, false]}, Majority,
+ {bad_type, Tab, {majority, Majority}}),
+ case Majority of
+ true ->
+ verify(false, LC,
+ {combine_error, Tab, [{local_content,true},{majority,true}]});
+ false ->
+ ok
+ end,
Snmp = Cs#cstruct.snmp,
verify(true, mnesia_snmp_hook:check_ustruct(Snmp),
{badarg, Tab, {snmp, Snmp}}),
@@ -820,7 +870,7 @@ verify_cstruct(Cs) when is_record(Cs, cstruct) ->
lists:foreach(CheckProp, Cs#cstruct.user_properties),
case Cs#cstruct.cookie of
- {{MegaSecs, Secs, MicroSecs}, _Node}
+ {{MegaSecs, Secs, MicroSecs}, _Node}
when is_integer(MegaSecs), is_integer(Secs),
is_integer(MicroSecs), is_atom(node) ->
ok;
@@ -856,15 +906,15 @@ verify_nodes(Cs) ->
end,
verify(integer, mnesia_lib:etype(LoadOrder),
{bad_type, Tab, {load_order, LoadOrder}}),
-
+
Nodes = Ram ++ Disc ++ DiscOnly,
verify(list, mnesia_lib:etype(Nodes),
{combine_error, Tab,
[{ram_copies, []}, {disc_copies, []}, {disc_only_copies, []}]}),
verify(false, has_duplicates(Nodes), {combine_error, Tab, Nodes}),
- AtomCheck = fun(N) -> verify(atom, mnesia_lib:etype(N), {bad_type, Tab, N}) end,
+ AtomCheck = fun(N) -> verify(atom, mnesia_lib:etype(N), {bad_type, Tab, N}) end,
lists:foreach(AtomCheck, Nodes).
-
+
verify(Expected, Fun, Error) when is_function(Fun) ->
do_verify(Expected, catch Fun(), Error);
verify(Expected, Actual, Error) ->
@@ -895,7 +945,7 @@ ensure_active(Cs, What) ->
W = {Tab, What},
ensure_non_empty(W),
Nodes = mnesia_lib:intersect(val({schema, disc_copies}),
- mnesia_lib:cs_to_nodes(Cs)),
+ mnesia_lib:cs_to_nodes(Cs)),
case Nodes -- val(W) of
[] ->
ok;
@@ -922,7 +972,7 @@ ensure_non_empty({Tab, Vhat}) ->
ensure_not_active(Tab = schema, Node) ->
Active = val({Tab, active_replicas}),
- case lists:member(Node, Active) of
+ case lists:member(Node, Active) of
false when Active =/= [] ->
ok;
false ->
@@ -956,7 +1006,7 @@ create_table(TabDef) ->
do_multi_create_table(TabDef) ->
get_tid_ts_and_lock(schema, write),
ensure_writable(schema),
- Cs = list2cs(TabDef),
+ Cs = api_list2cs(TabDef),
case Cs#cstruct.frag_properties of
[] ->
do_create_table(Cs);
@@ -985,7 +1035,7 @@ unsafe_make_create_table(Cs) ->
{_Mod, Tid, Ts} = get_tid_ts_and_lock(schema, none),
verify_cstruct(Cs),
Tab = Cs#cstruct.name,
-
+
%% Check that we have all disc replica nodes running
DiscNodes = Cs#cstruct.disc_copies ++ Cs#cstruct.disc_only_copies,
RunningNodes = val({current, db_nodes}),
@@ -1003,7 +1053,7 @@ unsafe_make_create_table(Cs) ->
check_if_exists(Tab) ->
TidTs = get_tid_ts_and_lock(schema, write),
{_, _, Ts} = TidTs,
- Store = Ts#tidstore.store,
+ Store = Ts#tidstore.store,
ets:foldl(
fun({op, create_table, [{name, T}|_]}, _Acc) when T==Tab ->
true;
@@ -1040,7 +1090,7 @@ make_delete_table(Tab, Mode) ->
%% nodes etc.
TidTs = get_tid_ts_and_lock(schema, write),
{_, _, Ts} = TidTs,
- Store = Ts#tidstore.store,
+ Store = Ts#tidstore.store,
Deleted = ets:select_delete(
Store, [{{op,'$1',[{name,Tab}|'_']},
[{'or',
@@ -1063,9 +1113,9 @@ make_delete_table(Tab, Mode) ->
[] ->
[make_delete_table2(Tab)];
_Props ->
- %% Check if it is a base table
- mnesia_frag:lookup_frag_hash(Tab),
-
+ %% Check if it is a base table
+ mnesia_frag:lookup_frag_hash(Tab),
+
%% Check for foreigners
F = mnesia_frag:lookup_foreigners(Tab),
verify([], F, {combine_error,
@@ -1087,7 +1137,7 @@ make_delete_table2(Tab) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Change fragmentation of a table
-
+
change_table_frag(Tab, Change) ->
schema_transaction(fun() -> do_change_table_frag(Tab, Change) end).
@@ -1098,7 +1148,7 @@ do_change_table_frag(Tab, Change) when is_atom(Tab), Tab /= schema ->
ok;
do_change_table_frag(Tab, _Change) ->
mnesia:abort({bad_type, Tab}).
-
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Clear a table
@@ -1136,7 +1186,7 @@ make_add_table_copy(Tab, Node, Storage) ->
verify(false, lists:member(Node, Ns), {already_exists, Tab, Node}),
Cs2 = new_cs(Cs, Node, Storage, add),
verify_cstruct(Cs2),
-
+
%% Check storage and if node is running
IsRunning = lists:member(Node, val({current, db_nodes})),
if
@@ -1163,21 +1213,21 @@ del_table_copy(Tab, Node) ->
do_del_table_copy(Tab, Node) when is_atom(Node) ->
TidTs = get_tid_ts_and_lock(schema, write),
-%% get_tid_ts_and_lock(Tab, write),
+%% get_tid_ts_and_lock(Tab, write),
insert_schema_ops(TidTs, make_del_table_copy(Tab, Node));
do_del_table_copy(Tab, Node) ->
mnesia:abort({badarg, Tab, Node}).
-
+
make_del_table_copy(Tab, Node) ->
ensure_writable(schema),
Cs = incr_version(val({Tab, cstruct})),
Storage = mnesia_lib:schema_cs_to_storage_type(Node, Cs),
- Cs2 = new_cs(Cs, Node, Storage, del),
+ Cs2 = new_cs(Cs, Node, Storage, del),
case mnesia_lib:cs_to_nodes(Cs2) of
[] when Tab == schema ->
mnesia:abort({combine_error, Tab, "Last replica"});
[] ->
- ensure_active(Cs),
+ ensure_active(Cs),
dbg_out("Last replica deleted in table ~p~n", [Tab]),
make_delete_table(Tab, whole_table);
_ when Tab == schema ->
@@ -1196,14 +1246,14 @@ remove_node_from_tabs([], _Node) ->
[];
remove_node_from_tabs([schema|Rest], Node) ->
remove_node_from_tabs(Rest, Node);
-remove_node_from_tabs([Tab|Rest], Node) ->
- {Cs, IsFragModified} =
+remove_node_from_tabs([Tab|Rest], Node) ->
+ {Cs, IsFragModified} =
mnesia_frag:remove_node(Node, incr_version(val({Tab, cstruct}))),
case mnesia_lib:schema_cs_to_storage_type(Node, Cs) of
unknown ->
case IsFragModified of
true ->
- [{op, change_table_frag, {del_node, Node}, cs2list(Cs)} |
+ [{op, change_table_frag, {del_node, Node}, cs2list(Cs)} |
remove_node_from_tabs(Rest, Node)];
false ->
remove_node_from_tabs(Rest, Node)
@@ -1232,7 +1282,7 @@ new_cs(Cs, Node, ram_copies, del) ->
new_cs(Cs, Node, disc_copies, del) ->
Cs#cstruct{disc_copies = lists:delete(Node , Cs#cstruct.disc_copies)};
new_cs(Cs, Node, disc_only_copies, del) ->
- Cs#cstruct{disc_only_copies =
+ Cs#cstruct{disc_only_copies =
lists:delete(Node , Cs#cstruct.disc_only_copies)};
new_cs(Cs, _Node, Storage, _Op) ->
mnesia:abort({badarg, Cs#cstruct.name, Storage}).
@@ -1264,7 +1314,7 @@ make_move_table(Tab, FromNode, ToNode) ->
Running = val({current, db_nodes}),
Storage = mnesia_lib:schema_cs_to_storage_type(FromNode, Cs),
verify(true, lists:member(ToNode, Running), {not_active, schema, ToNode}),
-
+
Cs2 = new_cs(Cs, ToNode, Storage, add),
Cs3 = new_cs(Cs2, FromNode, Storage, del),
verify_cstruct(Cs3),
@@ -1292,7 +1342,7 @@ make_change_table_copy_type(Tab, Node, unknown) ->
make_change_table_copy_type(Tab, Node, ToS) ->
ensure_writable(schema),
Cs = incr_version(val({Tab, cstruct})),
- FromS = mnesia_lib:storage_type_at_node(Node, Tab),
+ FromS = mnesia_lib:storage_type_at_node(Node, Tab),
case compare_storage_type(false, FromS, ToS) of
{same, _} ->
@@ -1306,12 +1356,12 @@ make_change_table_copy_type(Tab, Node, ToS) ->
Cs2 = new_cs(Cs, Node, FromS, del),
Cs3 = new_cs(Cs2, Node, ToS, add),
verify_cstruct(Cs3),
-
+
[{op, change_table_copy_type, Node, FromS, ToS, cs2list(Cs3)}].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% change index functions ....
-%% Pos is allready added by 1 in both of these functions
+%% Pos is allready added by 1 in both of these functions
add_table_index(Tab, Pos) ->
schema_transaction(fun() -> do_add_table_index(Tab, Pos) end).
@@ -1398,14 +1448,14 @@ make_del_snmp(Tab) ->
[{op, del_snmp, cs2list(Cs2)}].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
+%%
-transform_table(Tab, Fun, NewAttrs, NewRecName)
- when is_function(Fun), is_list(NewAttrs), is_atom(NewRecName) ->
+transform_table(Tab, Fun, NewAttrs, NewRecName)
+ when is_function(Fun), is_list(NewAttrs), is_atom(NewRecName) ->
schema_transaction(fun() -> do_transform_table(Tab, Fun, NewAttrs, NewRecName) end);
-transform_table(Tab, ignore, NewAttrs, NewRecName)
- when is_list(NewAttrs), is_atom(NewRecName) ->
+transform_table(Tab, ignore, NewAttrs, NewRecName)
+ when is_list(NewAttrs), is_atom(NewRecName) ->
schema_transaction(fun() -> do_transform_table(Tab, ignore, NewAttrs, NewRecName) end);
transform_table(Tab, Fun, NewAttrs, NewRecName) ->
@@ -1424,7 +1474,7 @@ make_transform(Tab, Fun, NewAttrs, NewRecName) ->
ensure_active(Cs),
ensure_writable(Tab),
case mnesia_lib:val({Tab, index}) of
- [] ->
+ [] ->
Cs2 = Cs#cstruct{attributes = NewAttrs, record_name = NewRecName},
verify_cstruct(Cs2),
[{op, transform, Fun, cs2list(Cs2)}];
@@ -1450,7 +1500,7 @@ make_transform(Tab, Fun, NewAttrs, NewRecName) ->
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
+%%
change_table_access_mode(Tab, Mode) ->
schema_transaction(fun() -> do_change_table_access_mode(Tab, Mode) end).
@@ -1495,6 +1545,43 @@ make_change_table_load_order(Tab, LoadOrder) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+change_table_majority(Tab, Majority) when is_boolean(Majority) ->
+ schema_transaction(fun() -> do_change_table_majority(Tab, Majority) end).
+
+do_change_table_majority(schema, _Majority) ->
+ mnesia:abort({bad_type, schema});
+do_change_table_majority(Tab, Majority) ->
+ TidTs = get_tid_ts_and_lock(schema, write),
+ get_tid_ts_and_lock(Tab, none),
+ insert_schema_ops(TidTs, make_change_table_majority(Tab, Majority)).
+
+make_change_table_majority(Tab, Majority) ->
+ ensure_writable(schema),
+ Cs = incr_version(val({Tab, cstruct})),
+ ensure_active(Cs),
+ OldMajority = Cs#cstruct.majority,
+ Cs2 = Cs#cstruct{majority = Majority},
+ FragOps = case lists:keyfind(base_table, 1, Cs#cstruct.frag_properties) of
+ {_, Tab} ->
+ FragNames = mnesia_frag:frag_names(Tab) -- [Tab],
+ lists:map(
+ fun(T) ->
+ get_tid_ts_and_lock(Tab, none),
+ CsT = incr_version(val({T, cstruct})),
+ ensure_active(CsT),
+ CsT2 = CsT#cstruct{majority = Majority},
+ verify_cstruct(CsT2),
+ {op, change_table_majority, cs2list(CsT2),
+ OldMajority, Majority}
+ end, FragNames);
+ false -> [];
+ {_, _} -> mnesia:abort({bad_type, Tab})
+ end,
+ verify_cstruct(Cs2),
+ [{op, change_table_majority, cs2list(Cs2), OldMajority, Majority} | FragOps].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
write_table_property(Tab, Prop) when is_tuple(Prop), size(Prop) >= 1 ->
schema_transaction(fun() -> do_write_table_property(Tab, Prop) end);
write_table_property(Tab, Prop) ->
@@ -1547,9 +1634,9 @@ change_prop_in_existing_op(Tab, Prop, How, Store) ->
false ->
false
end.
-
-update_existing_op([{op, Op, L = [{name,Tab}|_], _OldProp}|Ops],
- Tab, Prop, How, Acc) when Op == write_property;
+
+update_existing_op([{op, Op, L = [{name,Tab}|_], _OldProp}|Ops],
+ Tab, Prop, How, Acc) when Op == write_property;
Op == delete_property ->
%% Apparently, mnesia_dumper doesn't care about OldProp here -- just L,
%% so we will throw away OldProp (not that it matters...) and insert Prop.
@@ -1574,7 +1661,7 @@ update_existing_op([], _, _, _, _) ->
do_read_table_property(Tab, Key) ->
TidTs = get_tid_ts_and_lock(schema, read),
{_, _, Ts} = TidTs,
- Store = Ts#tidstore.store,
+ Store = Ts#tidstore.store,
Props = ets:foldl(
fun({op, create_table, [{name, T}|Opts]}, _Acc)
when T==Tab ->
@@ -1638,7 +1725,7 @@ do_delete_table_property(Tab, PropKey) ->
[Tab,PropKey]),
%% this must be an existing table
get_tid_ts_and_lock(Tab, none),
- insert_schema_ops(TidTs,
+ insert_schema_ops(TidTs,
make_delete_table_properties(Tab, [PropKey]))
end.
@@ -1660,17 +1747,17 @@ make_delete_table_properties(_Tab, [], _Cs) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Ensure that the transaction can be committed even
+%% Ensure that the transaction can be committed even
%% if the node crashes and Mnesia is restarted
prepare_commit(Tid, Commit, WaitFor) ->
case Commit#commit.schema_ops of
[] ->
{false, Commit, optional};
OrigOps ->
- {Modified, Ops, DumperMode} =
+ {Modified, Ops, DumperMode} =
prepare_ops(Tid, OrigOps, WaitFor, false, [], optional),
InitBy = schema_prepare,
- GoodRes = {Modified,
+ GoodRes = {Modified,
Commit#commit{schema_ops = lists:reverse(Ops)},
DumperMode},
case DumperMode of
@@ -1686,7 +1773,7 @@ prepare_commit(Tid, Commit, WaitFor) ->
end
end,
case Ops of
- [] ->
+ [] ->
ignore;
_ ->
%% We need to grab a dumper lock here, the log may not
@@ -1698,20 +1785,20 @@ prepare_commit(Tid, Commit, WaitFor) ->
prepare_ops(Tid, [Op | Ops], WaitFor, Changed, Acc, DumperMode) ->
case prepare_op(Tid, Op, WaitFor) of
- {true, mandatory} ->
+ {true, mandatory} ->
prepare_ops(Tid, Ops, WaitFor, Changed, [Op | Acc], mandatory);
- {true, optional} ->
+ {true, optional} ->
prepare_ops(Tid, Ops, WaitFor, Changed, [Op | Acc], DumperMode);
- {true, Ops2, mandatory} ->
+ {true, Ops2, mandatory} ->
prepare_ops(Tid, Ops, WaitFor, true, Ops2 ++ Acc, mandatory);
- {true, Ops2, optional} ->
+ {true, Ops2, optional} ->
prepare_ops(Tid, Ops, WaitFor, true, Ops2 ++ Acc, DumperMode);
- {false, optional} ->
+ {false, optional} ->
prepare_ops(Tid, Ops, WaitFor, true, Acc, DumperMode)
end;
prepare_ops(_Tid, [], _WaitFor, Changed, Acc, DumperMode) ->
{Changed, Acc, DumperMode}.
-
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Prepare for commit
%% returns true if Op should be included, i.e. unmodified
@@ -1730,19 +1817,22 @@ prepare_op(_Tid, {op, rec, unknown, Rec}, _WaitFor) ->
prepare_op(_Tid, {op, announce_im_running, Node, SchemaDef, Running, RemoteRunning}, _WaitFor) ->
SchemaCs = list2cs(SchemaDef),
- if
- Node == node() -> %% Announce has already run on local node
+ if
+ Node == node() -> %% Announce has already run on local node
ignore; %% from do_merge_schema
true ->
- NewNodes = mnesia_lib:uniq(Running++RemoteRunning) -- val({current,db_nodes}),
+ %% If a node has restarted it may still linger in db_nodes,
+ %% but have been removed from recover_nodes
+ Current = mnesia_lib:intersect(val({current,db_nodes}), [node()|val(recover_nodes)]),
+ NewNodes = mnesia_lib:uniq(Running++RemoteRunning) -- Current,
mnesia_lib:set(prepare_op, {announce_im_running,NewNodes}),
announce_im_running(NewNodes, SchemaCs)
end,
{false, optional};
-prepare_op(_Tid, {op, sync_trans}, {part, CoordPid}) ->
+prepare_op(_Tid, {op, sync_trans}, {part, CoordPid}) ->
CoordPid ! {sync_trans, self()},
- receive
+ receive
{sync_trans, CoordPid} ->
{false, optional};
{mnesia_down, _Node} = Else ->
@@ -1753,7 +1843,7 @@ prepare_op(_Tid, {op, sync_trans}, {part, CoordPid}) ->
mnesia:abort(Else)
end;
-prepare_op(_Tid, {op, sync_trans}, {coord, Nodes}) ->
+prepare_op(_Tid, {op, sync_trans}, {coord, Nodes}) ->
case receive_sync(Nodes, []) of
{abort, Reason} ->
mnesia_lib:verbose("sync_op terminated due to ~p~n", [Reason]),
@@ -1784,7 +1874,7 @@ prepare_op(Tid, {op, create_table, TabDef}, _WaitFor) ->
create_ram_table(Tab, Cs#cstruct.type),
create_disc_table(Tab),
insert_cstruct(Tid, Cs, false),
- {true, optional};
+ {true, optional};
disc_only_copies ->
mnesia_lib:set({Tab, create_table},true),
create_disc_only_table(Tab,Cs#cstruct.type),
@@ -1803,15 +1893,15 @@ prepare_op(Tid, {op, add_table_copy, Storage, Node, TabDef}, _WaitFor) ->
if
Tab == schema ->
{true, optional};
-
+
Node == node() ->
- case mnesia_lib:val({schema, storage_type}) of
- ram_copies when Storage /= ram_copies ->
+ case mnesia_lib:val({schema, storage_type}) of
+ ram_copies when Storage /= ram_copies ->
Error = {combine_error, Tab, "has no disc", Node},
mnesia:abort(Error);
_ ->
ok
- end,
+ end,
%% Tables are created by mnesia_loader get_network code
insert_cstruct(Tid, Cs, true),
case mnesia_controller:get_network_copy(Tab, Cs) of
@@ -1848,22 +1938,22 @@ prepare_op(Tid, {op, add_table_copy, Storage, Node, TabDef}, _WaitFor) ->
prepare_op(Tid, {op, del_table_copy, _Storage, Node, TabDef}, _WaitFor) ->
Cs = list2cs(TabDef),
Tab = Cs#cstruct.name,
-
+
if
%% Schema table lock is always required to run a schema op.
%% No need to look it.
- node(Tid#tid.pid) == node(), Tab /= schema ->
+ node(Tid#tid.pid) == node(), Tab /= schema ->
Self = self(),
Pid = spawn_link(fun() -> lock_del_table(Tab, Node, Cs, Self) end),
put(mnesia_lock, Pid),
- receive
- {Pid, updated} ->
+ receive
+ {Pid, updated} ->
{true, optional};
{Pid, FailReason} ->
mnesia:abort(FailReason);
{'EXIT', Pid, Reason} ->
mnesia:abort(Reason)
- end;
+ end;
true ->
{true, optional}
end;
@@ -1874,12 +1964,12 @@ prepare_op(_Tid, {op, change_table_copy_type, N, FromS, ToS, TabDef}, _WaitFor)
Tab = Cs#cstruct.name,
NotActive = mnesia_lib:not_active_here(Tab),
-
- if
+
+ if
NotActive == true ->
mnesia:abort({not_active, Tab, node()});
-
- Tab == schema ->
+
+ Tab == schema ->
case {FromS, ToS} of
{ram_copies, disc_copies} ->
case mnesia:system_info(schema_location) of
@@ -1889,7 +1979,7 @@ prepare_op(_Tid, {op, change_table_copy_type, N, FromS, ToS, TabDef}, _WaitFor)
mnesia:abort({combine_error, Tab, node(),
"schema_location must be opt_disc"})
end,
- Dir = mnesia_lib:dir(),
+ Dir = mnesia_lib:dir(),
case opt_create_dir(true, Dir) of
ok ->
purge_dir(Dir, []),
@@ -1913,18 +2003,18 @@ prepare_op(_Tid, {op, change_table_copy_type, N, FromS, ToS, TabDef}, _WaitFor)
_ ->
mnesia:abort({combine_error, Tab, ToS})
end;
-
- FromS == ram_copies ->
+
+ FromS == ram_copies ->
case mnesia_monitor:use_dir() of
- true ->
+ true ->
Dat = mnesia_lib:tab2dcd(Tab),
case mnesia_lib:exists(Dat) of
true ->
mnesia:abort({combine_error, Tab, node(),
"Table dump exists"});
false ->
- case ToS of
- disc_copies ->
+ case ToS of
+ disc_copies ->
mnesia_log:ets2dcd(Tab, dmp);
disc_only_copies ->
mnesia_dumper:raw_named_dump_table(Tab, dmp)
@@ -1934,7 +2024,7 @@ prepare_op(_Tid, {op, change_table_copy_type, N, FromS, ToS, TabDef}, _WaitFor)
false ->
mnesia:abort({has_no_disc, node()})
end;
-
+
FromS == disc_copies, ToS == disc_only_copies ->
mnesia_dumper:raw_named_dump_table(Tab, dmp);
FromS == disc_only_copies ->
@@ -1966,7 +2056,7 @@ prepare_op(_Tid, {op, dump_table, unknown, TabDef}, _WaitFor) ->
case lists:member(node(), Cs#cstruct.ram_copies) of
true ->
case mnesia_monitor:use_dir() of
- true ->
+ true ->
mnesia_log:ets2dcd(Tab, dmp),
Size = mnesia:table_info(Tab, size),
{true, [{op, dump_table, Size, TabDef}], optional};
@@ -2004,7 +2094,7 @@ prepare_op(_Tid, {op, transform, Fun, TabDef}, _WaitFor) ->
mnesia_lib:db_fixtable(Storage, Tab, true),
Key = mnesia_lib:db_first(Tab),
Op = {op, transform, Fun, TabDef},
- case catch transform_objs(Fun, Tab, RecName,
+ case catch transform_objs(Fun, Tab, RecName,
Key, NewArity, Storage, Type, [Op]) of
{'EXIT', Reason} ->
mnesia_lib:db_fixtable(Storage, Tab, false),
@@ -2018,7 +2108,7 @@ prepare_op(_Tid, {op, transform, Fun, TabDef}, _WaitFor) ->
prepare_op(_Tid, {op, merge_schema, TabDef}, _WaitFor) ->
Cs = list2cs(TabDef),
case verify_merge(Cs) of
- ok ->
+ ok ->
{true, optional};
Error ->
verbose("Merge_Schema ~p failed on ~p: ~p~n", [_Tid,node(),Error]),
@@ -2039,7 +2129,7 @@ create_ram_table(Tab, Type) ->
create_disc_table(Tab) ->
File = mnesia_lib:tab2dcd(Tab),
file:delete(File),
- FArg = [{file, File}, {name, {mnesia,create}},
+ FArg = [{file, File}, {name, {mnesia,create}},
{repair, false}, {mode, read_write}],
case mnesia_monitor:open_log(FArg) of
{ok,Log} ->
@@ -2070,7 +2160,7 @@ receive_sync([], Pids) ->
receive_sync(Nodes, Pids) ->
receive
{sync_trans, Pid} ->
- Node = node(Pid),
+ Node = node(Pid),
receive_sync(lists:delete(Node, Nodes), [Pid | Pids]);
Else ->
{abort, Else}
@@ -2086,16 +2176,16 @@ lock_del_table(Tab, Node, Cs, Father) ->
false;
({badrpc, {'EXIT', {undef, _}}}) ->
%% This will be the case we talks with elder nodes
- %% than 3.8.2, they will set where_to_read without
- %% getting a lock.
+ %% than 3.8.2, they will set where_to_read without
+ %% getting a lock.
false;
(_) ->
true
end,
case lists:filter(Filter, Res) of
- [] ->
+ [] ->
Father ! {self(), updated},
- %% When transaction is commited the process dies
+ %% When transaction is commited the process dies
%% and the lock is released.
receive _ -> ok end;
Err ->
@@ -2112,7 +2202,7 @@ lock_del_table(Tab, Node, Cs, Father) ->
exit(normal).
set_where_to_read(Tab, Node, Cs) ->
- case mnesia_lib:val({Tab, where_to_read}) of
+ case mnesia_lib:val({Tab, where_to_read}) of
Node ->
case Cs#cstruct.local_content of
true ->
@@ -2131,16 +2221,16 @@ transform_objs(_Fun, _Tab, _RT, '$end_of_table', _NewArity, _Storage, _Type, Acc
transform_objs(Fun, Tab, RecName, Key, A, Storage, Type, Acc) ->
Objs = mnesia_lib:db_get(Tab, Key),
NextKey = mnesia_lib:db_next_key(Tab, Key),
- Oid = {Tab, Key},
+ Oid = {Tab, Key},
NewObjs = {Ws, Ds} = transform_obj(Tab, RecName, Key, Fun, Objs, A, Type, [], []),
- if
- NewObjs == {[], []} ->
+ if
+ NewObjs == {[], []} ->
transform_objs(Fun, Tab, RecName, NextKey, A, Storage, Type, Acc);
- Type == bag ->
+ Type == bag ->
transform_objs(Fun, Tab, RecName, NextKey, A, Storage, Type,
[{op, rec, Storage, {Oid, Ws, write}},
{op, rec, Storage, {Oid, [Oid], delete}} | Acc]);
- Ds == [] ->
+ Ds == [] ->
%% Type is set or ordered_set, no need to delete the record first
transform_objs(Fun, Tab, RecName, NextKey, A, Storage, Type,
[{op, rec, Storage, {Oid, Ws, write}} | Acc]);
@@ -2161,15 +2251,15 @@ transform_obj(Tab, RecName, Key, Fun, [Obj|Rest], NewArity, Type, Ws, Ds) ->
NewObj == Obj ->
transform_obj(Tab, RecName, Key, Fun, Rest, NewArity, Type, Ws, Ds);
RecName == element(1, NewObj), Key == element(2, NewObj) ->
- transform_obj(Tab, RecName, Key, Fun, Rest, NewArity,
+ transform_obj(Tab, RecName, Key, Fun, Rest, NewArity,
Type, [NewObj | Ws], Ds);
- NewObj == delete ->
- case Type of
+ NewObj == delete ->
+ case Type of
bag -> %% Just don't write that object
- transform_obj(Tab, RecName, Key, Fun, Rest,
- NewArity, Type, Ws, Ds);
+ transform_obj(Tab, RecName, Key, Fun, Rest,
+ NewArity, Type, Ws, Ds);
_ ->
- transform_obj(Tab, RecName, Key, Fun, Rest, NewArity,
+ transform_obj(Tab, RecName, Key, Fun, Rest, NewArity,
Type, Ws, [NewObj | Ds])
end;
true ->
@@ -2193,7 +2283,7 @@ undo_prepare_commit(Tid, Commit) ->
%% Undo in reverse order
undo_prepare_ops(Tid, [Op | Ops]) ->
- case element(1, Op) of
+ case element(1, Op) of
TheOp when TheOp /= op, TheOp /= restore_op ->
undo_prepare_ops(Tid, Ops);
_ ->
@@ -2220,7 +2310,7 @@ undo_prepare_op(Tid, {op, create_table, TabDef}) ->
mnesia_lib:unset({Tab, create_table}),
delete_cstruct(Tid, Cs),
case mnesia_lib:cs_to_storage_type(node(), Cs) of
- unknown ->
+ unknown ->
ok;
ram_copies ->
ram_delete_table(Tab, ram_copies);
@@ -2235,7 +2325,7 @@ undo_prepare_op(Tid, {op, create_table, TabDef}) ->
%% disc_delete_table(Tab, Storage),
file:delete(Dat)
end;
-
+
undo_prepare_op(Tid, {op, add_table_copy, Storage, Node, TabDef}) ->
Cs = list2cs(TabDef),
Tab = Cs#cstruct.name,
@@ -2260,21 +2350,21 @@ undo_prepare_op(Tid, {op, add_table_copy, Storage, Node, TabDef}) ->
Cs2 = new_cs(Cs, Node, Storage, del),
insert_cstruct(Tid, Cs2, true) % Don't care about the version
end;
-
-undo_prepare_op(_Tid, {op, del_table_copy, _, Node, TabDef})
+
+undo_prepare_op(_Tid, {op, del_table_copy, _, Node, TabDef})
when Node == node() ->
Cs = list2cs(TabDef),
Tab = Cs#cstruct.name,
mnesia_lib:set({Tab, where_to_read}, Node);
-undo_prepare_op(_Tid, {op, change_table_copy_type, N, FromS, ToS, TabDef})
+undo_prepare_op(_Tid, {op, change_table_copy_type, N, FromS, ToS, TabDef})
when N == node() ->
Cs = list2cs(TabDef),
Tab = Cs#cstruct.name,
mnesia_checkpoint:tm_change_table_copy_type(Tab, ToS, FromS),
Dmp = mnesia_lib:tab2dmp(Tab),
-
+
case {FromS, ToS} of
{ram_copies, disc_copies} when Tab == schema ->
file:delete(Dmp),
@@ -2328,9 +2418,9 @@ ram_delete_table(Tab, Storage) ->
ignore;
disc_only_copies ->
ignore;
- _Else ->
+ _Else ->
%% delete possible index files and data .....
- %% Got to catch this since if no info has been set in the
+ %% Got to catch this since if no info has been set in the
%% mnesia_gvar it will crash
catch mnesia_index:del_transient(Tab, Storage),
case ?catch_val({Tab, {index, snmp}}) of
@@ -2400,7 +2490,7 @@ has_known_suffix(File, [Suffix | Tail], false) ->
has_known_suffix(File, Tail, lists:suffix(Suffix, File));
has_known_suffix(_File, [], Bool) ->
Bool.
-
+
known_suffixes() -> real_suffixes() ++ tmp_suffixes().
real_suffixes() -> [".DAT", ".LOG", ".BUP", ".DCL", ".DCD"].
@@ -2423,11 +2513,11 @@ info2(Tab, [{frag_hash, _V} | Tail]) -> % Ignore frag_hash
info2(Tab, [{P, V} | Tail]) ->
io:format("~-20w -> ~p~n",[P,V]),
info2(Tab, Tail);
-info2(_, []) ->
+info2(_, []) ->
io:format("~n", []).
get_table_properties(Tab) ->
- case catch mnesia_lib:db_match_object(ram_copies,
+ case catch mnesia_lib:db_match_object(ram_copies,
mnesia_gvar, {{Tab, '_'}, '_'}) of
{'EXIT', _} ->
mnesia:abort({no_exists, Tab, all});
@@ -2455,9 +2545,9 @@ get_table_properties(Tab) ->
recs = error_recs
}).
-restore(Opaque) ->
+restore(Opaque) ->
restore(Opaque, [], mnesia_monitor:get_env(backup_module)).
-restore(Opaque, Args) when is_list(Args) ->
+restore(Opaque, Args) when is_list(Args) ->
restore(Opaque, Args, mnesia_monitor:get_env(backup_module));
restore(_Opaque, BadArg) ->
{aborted, {badarg, BadArg}}.
@@ -2468,7 +2558,7 @@ restore(Opaque, Args, Module) when is_list(Args), is_atom(Module) ->
case mnesia_bup:read_schema(R#r.module, Opaque) of
{error, Reason} ->
{aborted, Reason};
- BupSchema ->
+ BupSchema ->
schema_transaction(fun() -> do_restore(R, BupSchema) end)
end;
{'EXIT', Reason} ->
@@ -2502,8 +2592,8 @@ check_restore_arg({keep_tables, List}, R) when is_list(List) ->
check_restore_arg({skip_tables, List}, R) when is_list(List) ->
TableList = [{Tab, skip_tables} || Tab <- List],
R#r{table_options = R#r.table_options ++ TableList};
-check_restore_arg({default_op, Op}, R) ->
- case Op of
+check_restore_arg({default_op, Op}, R) ->
+ case Op of
clear_tables -> ok;
recreate_tables -> ok;
keep_tables -> ok;
@@ -2534,12 +2624,12 @@ restore_items([Rec | Recs], Header, Schema, R) ->
case lists:keysearch(Tab, 1, R#r.tables) of
{value, {Tab, Where0, Snmp, RecName}} ->
Where = case Where0 of
- undefined ->
+ undefined ->
val({Tab, where_to_commit});
_ ->
Where0
end,
- {Rest, NRecs} = restore_tab_items([Rec | Recs], Tab,
+ {Rest, NRecs} = restore_tab_items([Rec | Recs], Tab,
RecName, Where, Snmp,
R#r.recs, R#r.insert_op),
restore_items(Rest, Header, Schema, R#r{recs = NRecs});
@@ -2547,12 +2637,12 @@ restore_items([Rec | Recs], Header, Schema, R) ->
Rest = skip_tab_items(Recs, Tab),
restore_items(Rest, Header, Schema, R)
end;
-
+
restore_items([], _Header, _Schema, R) ->
R.
restore_func(Tab, R) ->
- case lists:keysearch(Tab, 1, R#r.table_options) of
+ case lists:keysearch(Tab, 1, R#r.table_options) of
{value, {Tab, OP}} ->
OP;
false ->
@@ -2564,24 +2654,24 @@ where_to_commit(Tab, CsList) ->
Disc = [{N, disc_copies} || N <- pick(Tab, disc_copies, CsList, [])],
DiscO = [{N, disc_only_copies} || N <- pick(Tab, disc_only_copies, CsList, [])],
Ram ++ Disc ++ DiscO.
-
+
%% Changes of the Meta info of schema itself is not allowed
restore_schema([{schema, schema, _List} | Schema], R) ->
restore_schema(Schema, R);
restore_schema([{schema, Tab, List} | Schema], R) ->
case restore_func(Tab, R) of
- clear_tables ->
+ clear_tables ->
do_clear_table(Tab),
- Snmp = val({Tab, snmp}),
- RecName = val({Tab, record_name}),
+ Snmp = val({Tab, snmp}),
+ RecName = val({Tab, record_name}),
R2 = R#r{tables = [{Tab, undefined, Snmp, RecName} | R#r.tables]},
restore_schema(Schema, R2);
- recreate_tables ->
+ recreate_tables ->
case ?catch_val({Tab, cstruct}) of
- {'EXIT', _} ->
+ {'EXIT', _} ->
TidTs = {_Mod, Tid, Ts} = get(mnesia_activity_state),
RunningNodes = val({current, db_nodes}),
- Nodes = mnesia_lib:intersect(mnesia_lib:cs_to_nodes(list2cs(List)),
+ Nodes = mnesia_lib:intersect(mnesia_lib:cs_to_nodes(list2cs(List)),
RunningNodes),
mnesia_locker:wlock_no_exist(Tid, Ts#tidstore.store, Tab, Nodes),
TidTs;
@@ -2589,20 +2679,20 @@ restore_schema([{schema, Tab, List} | Schema], R) ->
TidTs = get_tid_ts_and_lock(Tab, write)
end,
NC = {cookie, ?unique_cookie},
- List2 = lists:keyreplace(cookie, 1, List, NC),
+ List2 = lists:keyreplace(cookie, 1, List, NC),
Where = where_to_commit(Tab, List2),
Snmp = pick(Tab, snmp, List2, []),
RecName = pick(Tab, record_name, List2, Tab),
insert_schema_ops(TidTs, [{op, restore_recreate, List2}]),
R2 = R#r{tables = [{Tab, Where, Snmp, RecName} | R#r.tables]},
restore_schema(Schema, R2);
- keep_tables ->
+ keep_tables ->
get_tid_ts_and_lock(Tab, write),
Snmp = val({Tab, snmp}),
- RecName = val({Tab, record_name}),
+ RecName = val({Tab, record_name}),
R2 = R#r{tables = [{Tab, undefined, Snmp, RecName} | R#r.tables]},
restore_schema(Schema, R2);
- skip_tables ->
+ skip_tables ->
restore_schema(Schema, R)
end;
@@ -2613,7 +2703,7 @@ restore_schema([{schema, Tab} | Schema], R) ->
restore_schema([], R) ->
R.
-restore_tab_items([Rec | Rest], Tab, RecName, Where, Snmp, Recs, Op)
+restore_tab_items([Rec | Rest], Tab, RecName, Where, Snmp, Recs, Op)
when element(1, Rec) == Tab ->
NewRecs = Op(Rec, Recs, RecName, Where, Snmp),
restore_tab_items(Rest, Tab, RecName, Where, Snmp, NewRecs, Op);
@@ -2621,7 +2711,7 @@ restore_tab_items([Rec | Rest], Tab, RecName, Where, Snmp, Recs, Op)
restore_tab_items(Rest, _Tab, _RecName, _Where, _Snmp, Recs, _Op) ->
{Rest, Recs}.
-skip_tab_items([Rec| Rest], Tab)
+skip_tab_items([Rec| Rest], Tab)
when element(1, Rec) == Tab ->
skip_tab_items(Rest, Tab);
skip_tab_items(Recs, _) ->
@@ -2656,7 +2746,6 @@ merge_schema() ->
merge_schema(UserFun) ->
schema_transaction(fun() -> UserFun(fun(Arg) -> do_merge_schema(Arg) end) end).
-
do_merge_schema(LockTabs0) ->
{_Mod, Tid, Ts} = get_tid_ts_and_lock(schema, write),
LockTabs = [{T, tab_to_nodes(T)} || T <- LockTabs0],
@@ -2678,14 +2767,14 @@ do_merge_schema(LockTabs0) ->
[mnesia_locker:wlock_no_exist(
Tid, Store, T, mnesia_lib:intersect(Ns, OtherNodes))
|| {T,Ns} <- LockTabs],
- case rpc:call(Node, mnesia_controller, get_cstructs, []) of
+ case fetch_cstructs(Node) of
{cstructs, Cstructs, RemoteRunning1} ->
LockedAlready = Running ++ [Node],
{New, Old} = mnesia_recover:connect_nodes(RemoteRunning1),
RemoteRunning = mnesia_lib:intersect(New ++ Old, RemoteRunning1),
- if
+ if
RemoteRunning /= RemoteRunning1 ->
- mnesia_lib:error("Mnesia on ~p could not connect to node(s) ~p~n",
+ mnesia_lib:error("Mnesia on ~p could not connect to node(s) ~p~n",
[node(), RemoteRunning1 -- RemoteRunning]),
mnesia:abort({node_not_running, RemoteRunning1 -- RemoteRunning});
true -> ok
@@ -2695,24 +2784,24 @@ do_merge_schema(LockTabs0) ->
[mnesia_locker:wlock_no_exist(Tid, Store, T,
mnesia_lib:intersect(Ns,NeedsLock))
|| {T,Ns} <- LockTabs],
- {value, SchemaCs} =
- lists:keysearch(schema, #cstruct.name, Cstructs),
+ NeedsConversion = need_old_cstructs(NeedsLock ++ LockedAlready),
+ {value, SchemaCs} = lists:keysearch(schema, #cstruct.name, Cstructs),
+ SchemaDef = cs2list(NeedsConversion, SchemaCs),
%% Announce that Node is running
- A = [{op, announce_im_running, node(),
- cs2list(SchemaCs), Running, RemoteRunning}],
+ A = [{op, announce_im_running, node(), SchemaDef, Running, RemoteRunning}],
do_insert_schema_ops(Store, A),
-
+
%% Introduce remote tables to local node
- do_insert_schema_ops(Store, make_merge_schema(Node, Cstructs)),
-
+ do_insert_schema_ops(Store, make_merge_schema(Node, NeedsConversion, Cstructs)),
+
%% Introduce local tables to remote nodes
Tabs = val({schema, tables}),
Ops = [{op, merge_schema, get_create_list(T)}
|| T <- Tabs,
not lists:keymember(T, #cstruct.name, Cstructs)],
do_insert_schema_ops(Store, Ops),
-
+
%% Ensure that the txn will be committed on all nodes
NewNodes = RemoteRunning -- Running,
mnesia_lib:set(prepare_op, {announce_im_running,NewNodes}),
@@ -2728,19 +2817,49 @@ do_merge_schema(LockTabs0) ->
not_merged
end.
+fetch_cstructs(Node) ->
+ case mnesia_monitor:needs_protocol_conversion(Node) of
+ true ->
+ case rpc:call(Node, mnesia_controller, get_cstructs, []) of
+ {cstructs, Cs0, RR} ->
+ {cstructs, [list2cs(cs2list(Cs)) || Cs <- Cs0], RR};
+ Err -> Err
+ end;
+ false ->
+ rpc:call(Node, mnesia_controller, get_remote_cstructs, [])
+ end.
+
+need_old_cstructs(Nodes) ->
+ Filter = fun(Node) -> not mnesia_monitor:needs_protocol_conversion(Node) end,
+ case lists:dropwhile(Filter, Nodes) of
+ [] -> false;
+ [Node|_] ->
+ case rpc:call(Node, mnesia_lib, val, [{schema,cstruct}]) of
+ #cstruct{} ->
+ %% mnesia_lib:warning("Mnesia on ~p do not need to convert cstruct (~p)~n",
+ %% [node(), Node]),
+ false;
+ {badrpc, _} ->
+ need_old_cstructs(lists:delete(Node,Nodes));
+ Cs when element(1, Cs) == cstruct, tuple_size(Cs) == 17 ->
+ ver4_4_18; % Without majority
+ Cs when element(1, Cs) == cstruct, tuple_size(Cs) == 18 ->
+ ver4_4_19 % With majority
+ end
+ end.
+
tab_to_nodes(Tab) when is_atom(Tab) ->
Cs = val({Tab, cstruct}),
mnesia_lib:cs_to_nodes(Cs).
-make_merge_schema(Node, [Cs | Cstructs]) ->
- Ops = do_make_merge_schema(Node, Cs),
- Ops ++ make_merge_schema(Node, Cstructs);
-make_merge_schema(_Node, []) ->
+make_merge_schema(Node, NeedsConv, [Cs | Cstructs]) ->
+ Ops = do_make_merge_schema(Node, NeedsConv, Cs),
+ Ops ++ make_merge_schema(Node, NeedsConv, Cstructs);
+make_merge_schema(_Node, _, []) ->
[].
%% Merge definitions of schema table
-do_make_merge_schema(Node, RemoteCs)
- when RemoteCs#cstruct.name == schema ->
+do_make_merge_schema(Node, NeedsConv, RemoteCs = #cstruct{name = schema}) ->
Cs = val({schema, cstruct}),
Masters = mnesia_recover:get_master_nodes(schema),
HasRemoteMaster = lists:member(Node, Masters),
@@ -2750,15 +2869,15 @@ do_make_merge_schema(Node, RemoteCs)
StCsLocal = mnesia_lib:cs_to_storage_type(node(), Cs),
StRcsLocal = mnesia_lib:cs_to_storage_type(node(), RemoteCs),
StCsRemote = mnesia_lib:cs_to_storage_type(Node, Cs),
- StRcsRemote = mnesia_lib:cs_to_storage_type(Node, RemoteCs),
-
+ StRcsRemote = mnesia_lib:cs_to_storage_type(Node, RemoteCs),
+
if
Cs#cstruct.cookie == RemoteCs#cstruct.cookie,
Cs#cstruct.version == RemoteCs#cstruct.version ->
%% Great, we have the same cookie and version
%% and do not need to merge cstructs
[];
-
+
Cs#cstruct.cookie /= RemoteCs#cstruct.cookie,
Cs#cstruct.disc_copies /= [],
RemoteCs#cstruct.disc_copies /= [] ->
@@ -2769,14 +2888,14 @@ do_make_merge_schema(Node, RemoteCs)
HasRemoteMaster == false ->
%% Choose local cstruct,
%% since it's the master
- [{op, merge_schema, cs2list(Cs)}];
+ [{op, merge_schema, cs2list(NeedsConv, Cs)}];
HasRemoteMaster == true,
HasLocalMaster == false ->
%% Choose remote cstruct,
%% since it's the master
- [{op, merge_schema, cs2list(RemoteCs)}];
-
+ [{op, merge_schema, cs2list(NeedsConv, RemoteCs)}];
+
true ->
Str = io_lib:format("Incompatible schema cookies. "
"Please, restart from old backup."
@@ -2784,12 +2903,12 @@ do_make_merge_schema(Node, RemoteCs)
[Node, cs2list(RemoteCs), node(), cs2list(Cs)]),
throw(Str)
end;
-
+
StCsLocal /= StRcsLocal, StRcsLocal /= unknown, StCsLocal /= ram_copies ->
Str = io_lib:format("Incompatible schema storage types (local). "
"on ~w storage ~w, on ~w storage ~w~n",
[node(), StCsLocal, Node, StRcsLocal]),
- throw(Str);
+ throw(Str);
StCsRemote /= StRcsRemote, StCsRemote /= unknown, StRcsRemote /= ram_copies ->
Str = io_lib:format("Incompatible schema storage types (remote). "
"on ~w cs ~w, on ~w rcs ~w~n",
@@ -2800,27 +2919,27 @@ do_make_merge_schema(Node, RemoteCs)
%% Choose local cstruct,
%% since it involves disc nodes
MergedCs = merge_cstructs(Cs, RemoteCs, Force),
- [{op, merge_schema, cs2list(MergedCs)}];
-
+ [{op, merge_schema, cs2list(NeedsConv, MergedCs)}];
+
RemoteCs#cstruct.disc_copies /= [] ->
%% Choose remote cstruct,
%% since it involves disc nodes
MergedCs = merge_cstructs(RemoteCs, Cs, Force),
- [{op, merge_schema, cs2list(MergedCs)}];
+ [{op, merge_schema, cs2list(NeedsConv, MergedCs)}];
Cs > RemoteCs ->
%% Choose remote cstruct
MergedCs = merge_cstructs(RemoteCs, Cs, Force),
- [{op, merge_schema, cs2list(MergedCs)}];
-
+ [{op, merge_schema, cs2list(NeedsConv, MergedCs)}];
+
true ->
%% Choose local cstruct
MergedCs = merge_cstructs(Cs, RemoteCs, Force),
- [{op, merge_schema, cs2list(MergedCs)}]
+ [{op, merge_schema, cs2list(NeedsConv, MergedCs)}]
end;
%% Merge definitions of normal table
-do_make_merge_schema(Node, RemoteCs) ->
+do_make_merge_schema(Node, NeedsConv, RemoteCs = #cstruct{}) ->
Tab = RemoteCs#cstruct.name,
Masters = mnesia_recover:get_master_nodes(schema),
HasRemoteMaster = lists:member(Node, Masters),
@@ -2829,27 +2948,27 @@ do_make_merge_schema(Node, RemoteCs) ->
case ?catch_val({Tab, cstruct}) of
{'EXIT', _} ->
%% A completely new table, created while Node was down
- [{op, merge_schema, cs2list(RemoteCs)}];
+ [{op, merge_schema, cs2list(NeedsConv, RemoteCs)}];
Cs when Cs#cstruct.cookie == RemoteCs#cstruct.cookie ->
if
Cs#cstruct.version == RemoteCs#cstruct.version ->
%% We have exactly the same version of the
%% table def
[];
-
+
Cs#cstruct.version > RemoteCs#cstruct.version ->
%% Oops, we have different versions
%% of the table def, lets merge them.
%% The only changes that may have occurred
%% is that new replicas may have been added.
MergedCs = merge_cstructs(Cs, RemoteCs, Force),
- [{op, merge_schema, cs2list(MergedCs)}];
-
+ [{op, merge_schema, cs2list(NeedsConv, MergedCs)}];
+
Cs#cstruct.version < RemoteCs#cstruct.version ->
%% Oops, we have different versions
%% of the table def, lets merge them
MergedCs = merge_cstructs(RemoteCs, Cs, Force),
- [{op, merge_schema, cs2list(MergedCs)}]
+ [{op, merge_schema, cs2list(NeedsConv, MergedCs)}]
end;
Cs ->
%% Different cookies, not possible to merge
@@ -2858,14 +2977,14 @@ do_make_merge_schema(Node, RemoteCs) ->
HasRemoteMaster == false ->
%% Choose local cstruct,
%% since it's the master
- [{op, merge_schema, cs2list(Cs)}];
+ [{op, merge_schema, cs2list(NeedsConv, Cs)}];
HasRemoteMaster == true,
HasLocalMaster == false ->
%% Choose remote cstruct,
%% since it's the master
- [{op, merge_schema, cs2list(RemoteCs)}];
-
+ [{op, merge_schema, cs2list(NeedsConv, RemoteCs)}];
+
true ->
Str = io_lib:format("Bad cookie in table definition"
" ~w: ~w = ~w, ~w = ~w~n",
@@ -2935,7 +3054,7 @@ compare_storage_type(true, One, Another) ->
compare_storage_type(false, Another, One);
compare_storage_type(false, _One, _Another) ->
incompatible.
-
+
change_storage_type(N, ram_copies, Cs) ->
Nodes = [N | Cs#cstruct.ram_copies],
Cs#cstruct{ram_copies = mnesia_lib:uniq(Nodes)};
@@ -2971,6 +3090,7 @@ merge_versions(AnythingNew, Cs, RemoteCs, Force) ->
Cs#cstruct.index == RemoteCs#cstruct.index,
Cs#cstruct.snmp == RemoteCs#cstruct.snmp,
Cs#cstruct.access_mode == RemoteCs#cstruct.access_mode,
+ Cs#cstruct.majority == RemoteCs#cstruct.majority,
Cs#cstruct.load_order == RemoteCs#cstruct.load_order,
Cs#cstruct.user_properties == RemoteCs#cstruct.user_properties ->
do_merge_versions(AnythingNew, Cs, RemoteCs);
@@ -3016,14 +3136,14 @@ verify_merge(RemoteCs) ->
if
StCsLocal == StRcsLocal -> ok;
StCsLocal == unknown -> ok;
- (StRcsLocal == unknown), (HasRemoteMaster == false) ->
+ (StRcsLocal == unknown), (HasRemoteMaster == false) ->
{merge_error, Cs, RemoteCs};
%% Trust the merger
true -> ok
end
end.
-announce_im_running([N | Ns], SchemaCs) ->
+announce_im_running([N | Ns], SchemaCs) ->
{L1, L2} = mnesia_recover:connect_nodes([N]),
case lists:member(N, L1) or lists:member(N, L2) of
true ->
@@ -3040,7 +3160,7 @@ announce_im_running([], _) ->
unannounce_im_running([N | Ns]) ->
mnesia_lib:del({current, db_nodes}, N),
- mnesia_controller:del_active_replica(schema, N),
+ mnesia_controller:del_active_replica(schema, N),
unannounce_im_running(Ns);
unannounce_im_running([]) ->
ok.
diff --git a/lib/mnesia/src/mnesia_text.erl b/lib/mnesia/src/mnesia_text.erl
index ab1362f6b6..0906d18da9 100644
--- a/lib/mnesia/src/mnesia_text.erl
+++ b/lib/mnesia/src/mnesia_text.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -181,9 +181,6 @@ read_term_from_stream(Stream, File, Line) ->
Str = Mod:format_error(What),
io:format("Error in line:~p of:~p ~s\n",
[NewLine, File, Str]),
- error;
- T ->
- io:format("Error2 **~p~n",[T]),
error
end;
{eof,_EndLine} ->
diff --git a/lib/mnesia/src/mnesia_tm.erl b/lib/mnesia/src/mnesia_tm.erl
index bb8e788b40..f62f7cb7c8 100644
--- a/lib/mnesia/src/mnesia_tm.erl
+++ b/lib/mnesia/src/mnesia_tm.erl
@@ -64,7 +64,8 @@
prev_tab = [], % initiate to a non valid table name
prev_types,
prev_snmp,
- types
+ types,
+ majority = []
}).
-record(participant, {tid, pid, commit, disc_nodes = [],
@@ -1100,9 +1101,12 @@ t_commit(Type) ->
case arrange(Tid, Store, Type) of
{N, Prep} when N > 0 ->
multi_commit(Prep#prep.protocol,
+ majority_attr(Prep),
Tid, Prep#prep.records, Store);
{0, Prep} ->
- multi_commit(read_only, Tid, Prep#prep.records, Store)
+ multi_commit(read_only,
+ majority_attr(Prep),
+ Tid, Prep#prep.records, Store)
end;
true ->
%% nested commit
@@ -1117,6 +1121,10 @@ t_commit(Type) ->
do_commit_nested
end.
+majority_attr(#prep{majority = M}) ->
+ M.
+
+
%% This function arranges for all objects we shall write in S to be
%% in a list of {Node, CommitRecord}
%% Important function for the performance of mnesia.
@@ -1222,11 +1230,13 @@ prepare_items(Tid, Tab, Key, Items, Prep) ->
{blocked, _} ->
unblocked = req({unblock_me, Tab}),
prepare_items(Tid, Tab, Key, Items, Prep);
- _ ->
+ _ ->
+ Majority = needs_majority(Tab, Prep),
Snmp = val({Tab, snmp}),
Recs2 = do_prepare_items(Tid, Tab, Key, Types,
Snmp, Items, Prep#prep.records),
Prep2 = Prep#prep{records = Recs2, prev_tab = Tab,
+ majority = Majority,
prev_types = Types, prev_snmp = Snmp},
check_prep(Prep2, Types)
end.
@@ -1235,6 +1245,33 @@ do_prepare_items(Tid, Tab, Key, Types, Snmp, Items, Recs) ->
Recs2 = prepare_snmp(Tid, Tab, Key, Types, Snmp, Items, Recs), % May exit
prepare_nodes(Tid, Types, Items, Recs2, normal).
+
+needs_majority(Tab, #prep{majority = M}) ->
+ case lists:keymember(Tab, 1, M) of
+ true ->
+ M;
+ false ->
+ case ?catch_val({Tab, majority}) of
+ {'EXIT', _} ->
+ M;
+ false ->
+ M;
+ true ->
+ CopyHolders = val({Tab, all_nodes}),
+ [{Tab, CopyHolders} | M]
+ end
+ end.
+
+have_majority([], _) ->
+ ok;
+have_majority([{Tab, AllNodes} | Rest], Nodes) ->
+ case mnesia_lib:have_majority(Tab, AllNodes, Nodes) of
+ true ->
+ have_majority(Rest, Nodes);
+ false ->
+ {error, Tab}
+ end.
+
prepare_snmp(Tab, Key, Items) ->
case val({Tab, snmp}) of
[] ->
@@ -1261,10 +1298,15 @@ prepare_snmp(Tid, Tab, Key, Types, Us, Items, Recs) ->
prepare_nodes(Tid, Types, [{clear_table, Tab}], Recs, snmp)
end.
-check_prep(Prep, Types) when Prep#prep.types == Types ->
+check_prep(#prep{majority = [], types = Types} = Prep, Types) ->
Prep;
-check_prep(Prep, Types) when Prep#prep.types == undefined ->
- Prep#prep{types = Types};
+check_prep(#prep{majority = M, types = undefined} = Prep, Types) ->
+ Protocol = if M == [] ->
+ Prep#prep.protocol;
+ true ->
+ asym_trans
+ end,
+ Prep#prep{protocol = Protocol, types = Types};
check_prep(Prep, _Types) ->
Prep#prep{protocol = asym_trans}.
@@ -1311,7 +1353,7 @@ prepare_node(_Node, _Storage, [], Rec, _Kind) ->
%% multi_commit((Protocol, Tid, CommitRecords, Store)
%% Local work is always performed in users process
-multi_commit(read_only, Tid, CR, _Store) ->
+multi_commit(read_only, _Maj = [], Tid, CR, _Store) ->
%% This featherweight commit protocol is used when no
%% updates has been performed in the transaction.
@@ -1324,7 +1366,7 @@ multi_commit(read_only, Tid, CR, _Store) ->
?MODULE ! {delete_transaction, Tid},
do_commit;
-multi_commit(sym_trans, Tid, CR, Store) ->
+multi_commit(sym_trans, _Maj = [], Tid, CR, Store) ->
%% This lightweight commit protocol is used when all
%% the involved tables are replicated symetrically.
%% Their storage types must match on each node.
@@ -1376,7 +1418,7 @@ multi_commit(sym_trans, Tid, CR, Store) ->
[{tid, Tid}, {outcome, Outcome}]),
Outcome;
-multi_commit(sync_sym_trans, Tid, CR, Store) ->
+multi_commit(sync_sym_trans, _Maj = [], Tid, CR, Store) ->
%% This protocol is the same as sym_trans except that it
%% uses syncronized calls to disk_log and syncronized commits
%% when several nodes are involved.
@@ -1408,7 +1450,7 @@ multi_commit(sync_sym_trans, Tid, CR, Store) ->
[{tid, Tid}, {outcome, Outcome}]),
Outcome;
-multi_commit(asym_trans, Tid, CR, Store) ->
+multi_commit(asym_trans, Majority, Tid, CR, Store) ->
%% This more expensive commit protocol is used when
%% table definitions are changed (schema transactions).
%% It is also used when the involved tables are
@@ -1469,6 +1511,10 @@ multi_commit(asym_trans, Tid, CR, Store) ->
{D2, CR2} = commit_decision(D, CR, [], []),
DiscNs = D2#decision.disc_nodes,
RamNs = D2#decision.ram_nodes,
+ case have_majority(Majority, DiscNs ++ RamNs) of
+ ok -> ok;
+ {error, Tab} -> mnesia:abort({no_majority, Tab})
+ end,
Pending = mnesia_checkpoint:tm_enter_pending(Tid, DiscNs, RamNs),
?ets_insert(Store, Pending),
{WaitFor, Local} = ask_commit(asym_trans, Tid, CR2, DiscNs, RamNs),
diff --git a/lib/mnesia/test/.gitignore b/lib/mnesia/test/.gitignore
new file mode 100644
index 0000000000..1e9a9933ed
--- /dev/null
+++ b/lib/mnesia/test/.gitignore
@@ -0,0 +1,9 @@
+
+
+# Test generates
+MnesiaCore*
+Mnesia.*
+
+tempfile*
+mnesia_test_case_info
+test_log* \ No newline at end of file
diff --git a/lib/mnesia/test/Makefile b/lib/mnesia/test/Makefile
index 973ac2900a..ae4c9626c7 100644
--- a/lib/mnesia/test/Makefile
+++ b/lib/mnesia/test/Makefile
@@ -42,6 +42,7 @@ MODULES= \
mnesia_dirty_access_test \
mnesia_atomicity_test \
mnesia_consistency_test \
+ mnesia_majority_test \
mnesia_isolation_test \
mnesia_durability_test \
mnesia_recovery_test \
@@ -110,7 +111,7 @@ release_tests_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) mnesia.spec mnesia.cover $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)
$(INSTALL_SCRIPT) mt $(INSTALL_PROGS) $(RELSYSDIR)
-# chmod -f -R u+w $(RELSYSDIR)
+# chmod -R u+w $(RELSYSDIR)
# @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/mnesia/test/mnesia_SUITE.erl b/lib/mnesia/test/mnesia_SUITE.erl
index 8ba8427213..2267a94164 100644
--- a/lib/mnesia/test/mnesia_SUITE.erl
+++ b/lib/mnesia/test/mnesia_SUITE.erl
@@ -78,12 +78,14 @@ groups() ->
[{group, install}, {group, atomicity},
{group, isolation}, {group, durability},
{group, recovery}, {group, consistency},
+ {group, majority},
{group, mnesia_frag_test, medium}]},
{atomicity, [], [{mnesia_atomicity_test, all}]},
{isolation, [], [{mnesia_isolation_test, all}]},
{durability, [], [{mnesia_durability_test, all}]},
{recovery, [], [{mnesia_recovery_test, all}]},
{consistency, [], [{mnesia_consistency_test, all}]},
+ {majority, [], [{mnesia_majority_test, all}]},
%% The 'heavy' test suite runs some resource consuming tests and
%% benchmarks
{heavy, [], [{group, measure}]},
diff --git a/lib/mnesia/test/mnesia_durability_test.erl b/lib/mnesia/test/mnesia_durability_test.erl
index 55205d1222..2fee72f066 100644
--- a/lib/mnesia/test/mnesia_durability_test.erl
+++ b/lib/mnesia/test/mnesia_durability_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -119,8 +119,8 @@ load_latest_data(Config) when is_list(Config) ->
?match([], mnesia_test_lib:kill_mnesia([N2])),
?match(ok, mnesia:dirty_write(Rec1)),
- ?match([], mnesia_test_lib:kill_mnesia([N1])),
?match([], mnesia_test_lib:kill_mnesia([N3])),
+ ?match([], mnesia_test_lib:kill_mnesia([N1])),
?match([], mnesia_test_lib:start_mnesia([N2], [])),
%% Should wait for N1
diff --git a/lib/mnesia/test/mnesia_majority_test.erl b/lib/mnesia/test/mnesia_majority_test.erl
new file mode 100644
index 0000000000..41ba0fd601
--- /dev/null
+++ b/lib/mnesia/test/mnesia_majority_test.erl
@@ -0,0 +1,186 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(mnesia_majority_test).
+-author('[email protected]').
+-compile(export_all).
+-include("mnesia_test_lib.hrl").
+
+init_per_testcase(Func, Conf) ->
+ mnesia_test_lib:init_per_testcase(Func, Conf).
+
+end_per_testcase(Func, Conf) ->
+ mnesia_test_lib:end_per_testcase(Func, Conf).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+all() ->
+ [
+ write
+ , wread
+ , delete
+ , clear_table
+ , frag
+ , change_majority
+ , frag_change_majority
+ ].
+
+write(suite) -> [];
+write(Config) when is_list(Config) ->
+ [N1, N2, N3] = ?acquire_nodes(3, Config),
+ Tab = t,
+ Schema = [{name, Tab}, {ram_copies, [N1,N2,N3]}, {majority,true}],
+ ?match({atomic, ok}, mnesia:create_table(Schema)),
+ ?match({[ok,ok,ok],[]},
+ rpc:multicall([N1,N2,N3], mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match({atomic,ok},
+ mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)),
+ mnesia_test_lib:kill_mnesia([N3]),
+ ?match({atomic,ok},
+ mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)),
+ mnesia_test_lib:kill_mnesia([N2]),
+ ?match({aborted,{no_majority,Tab}},
+ mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)).
+
+wread(suite) -> [];
+wread(Config) when is_list(Config) ->
+ [N1, N2] = ?acquire_nodes(2, Config),
+ Tab = t,
+ Schema = [{name, Tab}, {ram_copies, [N1,N2]}, {majority,true}],
+ ?match({atomic, ok}, mnesia:create_table(Schema)),
+ ?match({[ok,ok],[]},
+ rpc:multicall([N1,N2], mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match({atomic,[]},
+ mnesia:transaction(fun() -> mnesia:read(t,1,write) end)),
+ mnesia_test_lib:kill_mnesia([N2]),
+ ?match({aborted,{no_majority,Tab}},
+ mnesia:transaction(fun() -> mnesia:read(t,1,write) end)).
+
+delete(suite) -> [];
+delete(Config) when is_list(Config) ->
+ [N1, N2] = ?acquire_nodes(2, Config),
+ Tab = t,
+ Schema = [{name, Tab}, {ram_copies, [N1,N2]}, {majority,true}],
+ ?match({atomic, ok}, mnesia:create_table(Schema)),
+ ?match({[ok,ok],[]},
+ rpc:multicall([N1,N2], mnesia, wait_for_tables, [[Tab], 3000])),
+ %% works as expected with majority of nodes present
+ ?match({atomic,ok},
+ mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)),
+ ?match({atomic,ok},
+ mnesia:transaction(fun() -> mnesia:delete({t,1}) end)),
+ ?match({atomic,[]},
+ mnesia:transaction(fun() -> mnesia:read({t,1}) end)),
+ %% put the record back
+ ?match({atomic,ok},
+ mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)),
+ ?match({atomic,[{t,1,a}]},
+ mnesia:transaction(fun() -> mnesia:read({t,1}) end)),
+ mnesia_test_lib:kill_mnesia([N2]),
+ ?match({aborted,{no_majority,Tab}},
+ mnesia:transaction(fun() -> mnesia:delete({t,1}) end)).
+
+clear_table(suite) -> [];
+clear_table(Config) when is_list(Config) ->
+ [N1, N2] = ?acquire_nodes(2, Config),
+ Tab = t,
+ Schema = [{name, Tab}, {ram_copies, [N1,N2]}, {majority,true}],
+ ?match({atomic, ok}, mnesia:create_table(Schema)),
+ ?match({[ok,ok],[]},
+ rpc:multicall([N1,N2], mnesia, wait_for_tables, [[Tab], 3000])),
+ %% works as expected with majority of nodes present
+ ?match({atomic,ok},
+ mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)),
+ ?match({atomic,ok}, mnesia:clear_table(t)),
+ ?match({atomic,[]},
+ mnesia:transaction(fun() -> mnesia:read({t,1}) end)),
+ %% put the record back
+ ?match({atomic,ok},
+ mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)),
+ ?match({atomic,[{t,1,a}]},
+ mnesia:transaction(fun() -> mnesia:read({t,1}) end)),
+ mnesia_test_lib:kill_mnesia([N2]),
+ ?match({aborted,{no_majority,Tab}}, mnesia:clear_table(t)).
+
+frag(suite) -> [];
+frag(Config) when is_list(Config) ->
+ [N1] = ?acquire_nodes(1, Config),
+ Tab = t,
+ Schema = [
+ {name, Tab}, {ram_copies, [N1]},
+ {majority,true},
+ {frag_properties, [{n_fragments, 2}]}
+ ],
+ ?match({atomic, ok}, mnesia:create_table(Schema)),
+ ?match(true, mnesia:table_info(t, majority)),
+ ?match(true, mnesia:table_info(t_frag2, majority)).
+
+change_majority(suite) -> [];
+change_majority(Config) when is_list(Config) ->
+ [N1,N2] = ?acquire_nodes(2, Config),
+ Tab = t,
+ Schema = [
+ {name, Tab}, {ram_copies, [N1,N2]},
+ {majority,false}
+ ],
+ ?match({atomic, ok}, mnesia:create_table(Schema)),
+ ?match(false, mnesia:table_info(t, majority)),
+ ?match({atomic, ok},
+ mnesia:change_table_majority(t, true)),
+ ?match(true, mnesia:table_info(t, majority)),
+ ?match(ok,
+ mnesia:activity(transaction, fun() ->
+ mnesia:write({t,1,a})
+ end)),
+ mnesia_test_lib:kill_mnesia([N2]),
+ ?match({'EXIT',{aborted,{no_majority,_}}},
+ mnesia:activity(transaction, fun() ->
+ mnesia:write({t,1,a})
+ end)).
+
+frag_change_majority(suite) -> [];
+frag_change_majority(Config) when is_list(Config) ->
+ [N1,N2] = ?acquire_nodes(2, Config),
+ Tab = t,
+ Schema = [
+ {name, Tab}, {ram_copies, [N1,N2]},
+ {majority,false},
+ {frag_properties,
+ [{n_fragments, 2},
+ {n_ram_copies, 2},
+ {node_pool, [N1,N2]}]}
+ ],
+ ?match({atomic, ok}, mnesia:create_table(Schema)),
+ ?match(false, mnesia:table_info(t, majority)),
+ ?match(false, mnesia:table_info(t_frag2, majority)),
+ ?match({aborted,{bad_type,t_frag2}},
+ mnesia:change_table_majority(t_frag2, true)),
+ ?match({atomic, ok},
+ mnesia:change_table_majority(t, true)),
+ ?match(true, mnesia:table_info(t, majority)),
+ ?match(true, mnesia:table_info(t_frag2, majority)),
+ ?match(ok,
+ mnesia:activity(transaction, fun() ->
+ mnesia:write({t,1,a})
+ end, mnesia_frag)),
+ mnesia_test_lib:kill_mnesia([N2]),
+ ?match({'EXIT',{aborted,{no_majority,_}}},
+ mnesia:activity(transaction, fun() ->
+ mnesia:write({t,1,a})
+ end, mnesia_frag)).
diff --git a/lib/mnesia/test/mnesia_qlc_test.erl b/lib/mnesia/test/mnesia_qlc_test.erl
index 141de71d01..5f46840ae9 100644
--- a/lib/mnesia/test/mnesia_qlc_test.erl
+++ b/lib/mnesia/test/mnesia_qlc_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -70,6 +70,7 @@ init_testcases(Type,Config) ->
end,
All = fun() -> [Write(Id) || Id <- lists:seq(1,10)], ok end,
?match({atomic, ok}, mnesia:sync_transaction(All)),
+ ?match({atomic, [{b, {b,100-1}, 1}]}, mnesia:transaction(fun() -> mnesia:read({b, {b, 99}}) end)),
Nodes.
%% Test cases
diff --git a/lib/mnesia/test/mnesia_test_lib.erl b/lib/mnesia/test/mnesia_test_lib.erl
index 182c240084..9da45975d5 100644
--- a/lib/mnesia/test/mnesia_test_lib.erl
+++ b/lib/mnesia/test/mnesia_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -413,32 +413,28 @@ test_driver([T|TestCases], Config) ->
[L1|L2];
test_driver({Module, TestCases}, Config) when is_list(TestCases)->
test_driver(default_module(Module, TestCases), Config);
-test_driver({_, {Module, TestCase}}, Config) ->
- test_driver({Module, TestCase}, Config);
+test_driver({Module, all}, Config) ->
+ get_suite(Module, all, Config);
+test_driver({Module, G={group, _}}, Config) ->
+ get_suite(Module, G, Config);
+test_driver({_, {group, Module, Group}}, Config) ->
+ get_suite(Module, {group, Group}, Config);
+
test_driver({Module, TestCase}, Config) ->
Sec = timer:seconds(1) * 1000,
- case get_suite(Module, TestCase) of
- [] when Config == suite ->
+ case Config of
+ suite ->
{Module, TestCase, 'IMPL'};
- [] ->
+ _ ->
log("Eval test case: ~w~n", [{Module, TestCase}]),
- {T, Res} =
- timer:tc(?MODULE, eval_test_case, [Module, TestCase, Config]),
- log("Tested ~w in ~w sec~n", [TestCase, T div Sec]),
- {T div Sec, Res};
- Suite when is_list(Suite), Config == suite ->
- Res = test_driver(default_module(Module, Suite), Config),
- {{Module, TestCase}, Res};
- Suite when is_list(Suite) ->
- log("Expand test case ~w~n", [{Module, TestCase}]),
- Def = default_module(Module, Suite),
- {T, Res} = timer:tc(?MODULE, test_driver, [Def, Config]),
- {T div Sec, {{Module, TestCase}, Res}};
- 'NYI' when Config == suite ->
- {Module, TestCase, 'NYI'};
- 'NYI' ->
- log("<WARNING> Test case ~w NYI~n", [{Module, TestCase}]),
- {0, {skip, {Module, TestCase}, "NYI"}}
+ try timer:tc(?MODULE, eval_test_case, [Module, TestCase, Config]) of
+ {T, Res} ->
+ log("Tested ~w in ~w sec~n", [TestCase, T div Sec]),
+ {T div Sec, Res}
+ catch error:function_clause ->
+ log("<WARNING> Test case ~w NYI~n", [{Module, TestCase}]),
+ {0, {skip, {Module, TestCase}, "NYI"}}
+ end
end;
test_driver(TestCase, Config) ->
DefaultModule = mnesia_SUITE,
@@ -449,18 +445,50 @@ test_driver(TestCase, Config) ->
default_module(DefaultModule, TestCases) when is_list(TestCases) ->
Fun = fun(T) ->
case T of
+ {group, _} -> {true, {DefaultModule, T}};
{_, _} -> true;
T -> {true, {DefaultModule, T}}
end
end,
lists:zf(Fun, TestCases).
+get_suite(Module, TestCase, Config) ->
+ case get_suite(Module, TestCase) of
+ Suite when is_list(Suite), Config == suite ->
+ Res = test_driver(default_module(Module, Suite), Config),
+ {{Module, TestCase}, Res};
+ Suite when is_list(Suite) ->
+ log("Expand test case ~w~n", [{Module, TestCase}]),
+ Def = default_module(Module, Suite),
+ {T, Res} = timer:tc(?MODULE, test_driver, [Def, Config]),
+ Sec = timer:seconds(1) * 1000,
+ {T div Sec, {{Module, TestCase}, Res}};
+ 'NYI' when Config == suite ->
+ {Module, TestCase, 'NYI'};
+ 'NYI' ->
+ log("<WARNING> Test case ~w NYI~n", [{Module, TestCase}]),
+ {0, {skip, {Module, TestCase}, "NYI"}}
+ end.
+
%% Returns a list (possibly empty) or the atom 'NYI'
-get_suite(Mod, Fun) ->
- case catch (apply(Mod, Fun, [suite])) of
+get_suite(Mod, {group, Suite}) ->
+ try
+ Groups = Mod:groups(),
+ {_, _, TCList} = lists:keyfind(Suite, 1, Groups),
+ TCList
+ catch
+ _:Reason ->
+ io:format("Not implemented ~p ~p (~p ~p)~n",
+ [Mod,Suite,Reason, erlang:get_stacktrace()]),
+ 'NYI'
+ end;
+get_suite(Mod, all) ->
+ case catch (apply(Mod, all, [])) of
{'EXIT', _} -> 'NYI';
List when is_list(List) -> List
- end.
+ end;
+get_suite(_Mod, _Fun) ->
+ [].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -503,9 +531,13 @@ wait_for_evaluator(Pid, Mod, Fun, Config) ->
test_case_evaluator(Mod, Fun, [Config]) ->
NewConfig = Mod:init_per_testcase(Fun, Config),
- R = apply(Mod, Fun, [NewConfig]),
- Mod:end_per_testcase(Fun, NewConfig),
- exit({test_case_ok, R}).
+ try
+ R = apply(Mod, Fun, [NewConfig]),
+ Mod:end_per_testcase(Fun, NewConfig),
+ exit({test_case_ok, R})
+ catch error:function_clause ->
+ exit({skipped, 'NYI'})
+ end.
activity_evaluator(Coordinator) ->
activity_evaluator_loop(Coordinator),
diff --git a/lib/mnesia/test/mnesia_trans_access_test.erl b/lib/mnesia/test/mnesia_trans_access_test.erl
index 55ba4dd761..ca3f0fbf49 100644
--- a/lib/mnesia/test/mnesia_trans_access_test.erl
+++ b/lib/mnesia/test/mnesia_trans_access_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1102,9 +1102,9 @@ create_live_table_index_disc_only(Config) when is_list(Config) ->
create_live_table_index(Config, disc_only_copies).
create_live_table_index(Config, Storage) ->
- [Node1] = Nodes = ?acquire_nodes(1, Config),
+ [N1,N2,N3] = Nodes = ?acquire_nodes(3, Config),
Tab = create_live_table_index,
- Schema = [{name, Tab}, {attributes, [k, v]}, {Storage, [Node1]}],
+ Schema = [{name, Tab}, {attributes, [k, v]}, {Storage, Nodes}],
?match({atomic, ok}, mnesia:create_table(Schema)),
ValPos = 3,
mnesia:dirty_write({Tab, 1, 2}),
@@ -1115,9 +1115,35 @@ create_live_table_index(Config, Storage) ->
end,
?match({atomic, ok}, mnesia:transaction(Fun)),
?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)),
+ IRead = fun() -> lists:sort(mnesia:index_read(Tab, 2, ValPos)) end,
+ ?match({atomic, [{Tab, 1, 2},{Tab, 2, 2}]}, mnesia:transaction(IRead)),
+ ?match({atomic, ok}, mnesia:del_table_index(Tab, ValPos)),
+
+ %% Bug when adding index when table is still unloaded
+ %% By setting load order we hopefully will trigger the bug
+ mnesia:change_table_copy_type(Tab, N2, ram_copies),
+ mnesia:change_table_copy_type(Tab, N3, ram_copies),
+ ?match({atomic,ok}, mnesia:change_table_copy_type(schema, N2, ram_copies)),
+ ?match({atomic,ok}, mnesia:change_table_copy_type(schema, N3, ram_copies)),
+
+ Create = fun(N) ->
+ TabN = list_to_atom("tab_" ++ integer_to_list(N)),
+ Def = [{ram_copies, Nodes}, {load_order, N}],
+ mnesia:create_table(TabN, Def)
+ end,
+
+ ?match([{atomic,ok}|_], [Create(N) || N <- lists:seq(1,50)]),
+
+ ?match([], mnesia_test_lib:stop_mnesia([N2,N3])),
+ ?match(ok, rpc:call(N2, mnesia, start, [[{extra_db_nodes,[N1]}]])),
+ ?match(ok, rpc:call(N3, mnesia, start, [[{extra_db_nodes,[N1]}]])),
+
+ ?match({atomic, ok}, mnesia:add_table_index(Tab, ValPos)),
+
+ ?match({atomic, [{Tab, 1, 2},{Tab, 2, 2}]}, mnesia:transaction(IRead)),
?match({atomic, [{Tab, 1, 2},{Tab, 2, 2}]},
- mnesia:transaction(fun() -> lists:sort(mnesia:index_read(Tab, 2, ValPos))
- end)),
+ rpc:call(N2, mnesia, transaction, [IRead])),
+
?verify_mnesia(Nodes, []).
%% Drop table index
diff --git a/lib/mnesia/test/mt.erl b/lib/mnesia/test/mt.erl
index f69c4a11fd..f1152a7bc4 100644
--- a/lib/mnesia/test/mt.erl
+++ b/lib/mnesia/test/mt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -57,6 +57,7 @@ alias(heavy) -> {mnesia_SUITE, heavy};
alias(install) -> mnesia_install_test;
alias(isolation) -> mnesia_isolation_test;
alias(light) -> {mnesia_SUITE, light};
+alias(majority) -> mnesia_majority_test;
alias(measure) -> mnesia_measure_test;
alias(medium) -> {mnesia_SUITE, medium};
alias(nice) -> mnesia_nice_coverage_test;
@@ -76,17 +77,24 @@ resolve(Suite0) when is_atom(Suite0) ->
Suite when is_atom(Suite) ->
{Suite, all};
{Suite, Case} ->
- {Suite, Case}
+ {Suite, is_group(Suite,Case)}
end;
resolve({Suite0, Case}) when is_atom(Suite0), is_atom(Case) ->
case alias(Suite0) of
Suite when is_atom(Suite) ->
- {Suite, Case};
+ {Suite, is_group(Suite,Case)};
{Suite, Case2} ->
- {Suite, Case2}
+ {Suite, is_group(Suite,Case2)}
end;
resolve(List) when is_list(List) ->
[resolve(Case) || Case <- List].
+
+is_group(Mod, Case) ->
+ try {_,_,_} = lists:keyfind(Case, 1, Mod:groups()),
+ {group, Case}
+ catch _:{badmatch,_} ->
+ Case
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Run one or more test cases
diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk
index 5247657b68..a21ab007ef 100644
--- a/lib/mnesia/vsn.mk
+++ b/lib/mnesia/vsn.mk
@@ -1 +1 @@
-MNESIA_VSN = 4.4.17
+MNESIA_VSN = 4.5
diff --git a/lib/observer/doc/src/notes.xml b/lib/observer/doc/src/notes.xml
index b3b9937f1c..baa1354268 100644
--- a/lib/observer/doc/src/notes.xml
+++ b/lib/observer/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,22 @@
<p>This document describes the changes made to the Observer
application.</p>
+<section><title>Observer 0.9.10</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Do not install *.bat files on non-win32 machines (Thanks
+ to Hans Ulrich Niedermann)</p>
+ <p>
+ Own Id: OTP-9515</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Observer 0.9.9</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/observer/doc/src/ttb.xml b/lib/observer/doc/src/ttb.xml
index 2c80891925..4e63aecbf2 100644
--- a/lib/observer/doc/src/ttb.xml
+++ b/lib/observer/doc/src/ttb.xml
@@ -25,11 +25,12 @@
<title>ttb</title>
<prepared>Siri hansen</prepared>
+ <prepared>Bartlomiej Puzon</prepared>
<responsible></responsible>
<docno>1</docno>
<approved></approved>
<checked></checked>
- <date>2002-02-25</date>
+ <date>2010-08-13</date>
<rev>PA1</rev>
<file>ttb.sgml</file>
</header>
@@ -43,6 +44,35 @@
</description>
<funcs>
<func>
+ <name>start_trace(Nodes, Patterns, FlagSpec, Opts) -> Result</name>
+ <fsummary>Start a trace port on each given node.</fsummary>
+ <type>
+ <v>Result = see p/2</v>
+ <v>Nodes = see tracer/2</v>
+ <v>Patterns = [tuple()]</v>
+ <v>FlagSpec = {Procs, Flags}</v>
+ <v>Proc = see p/2</v>
+ <v>Flags = see p/2</v>
+ <v>Opts = see tracer/2</v>
+ </type>
+ <desc>
+ <p>This function is a shortcut allowing to start a trace with one command. Each
+ tuple in <c>Patterns</c> is converted to list which is in turn passed to
+ <c>ttb:tpl</c>.
+ The call:<code type="none">
+ttb:start_trace([Node, OtherNode],
+[{mod, foo, []}, {mod, bar, 2}],
+{all, call},
+[{file, File}, {handler,{fun myhandler/4, S}}])</code>
+ is equivalent to <code type="none">
+ttb:start_trace([Node, OtherNode], [{file, File}, {handler,{fun myhandler/4, S}}]),
+ttb:tpl(mod, foo, []),
+ttb:tpl(mod, bar, 2, []),
+ttb:p(all, call)</code>
+ </p>
+ </desc>
+ </func>
+ <func>
<name>tracer() -> Result</name>
<fsummary>This is equivalent to tracer(node()).</fsummary>
<desc>
@@ -50,6 +80,17 @@
</desc>
</func>
<func>
+ <name>tracer(Shortcut) -> Result</name>
+ <fsummary>Handy shortcuts for common tracing settings</fsummary>
+ <type>
+ <v>Shortcut = shell | dbg</v>
+ </type>
+ <desc>
+ <p><c>shell</c> is equivalent to <c>tracer(node(),[{file, {local, "ttb"}}, shell])</c>.</p>
+ <p><c>dbg</c> is equivalent to <c>tracer(node(),[{shell, only}])</c>.</p>
+ </desc>
+ </func>
+ <func>
<name>tracer(Nodes) -> Result</name>
<fsummary>This is equivalent to tracer(Nodes,[]).</fsummary>
<desc>
@@ -62,14 +103,21 @@
<type>
<v>Result = {ok, ActivatedNodes} | {error,Reason}</v>
<v>Nodes = atom() | [atom()] | all | existing | new</v>
- <v>Opts = [Opt]</v>
- <v>Opt = {file,Client} | {handler, FormatHandler} | {process_info,PI}</v>
+ <v>Opts = Opt | [Opt]</v>
+ <v>Opt = {file,Client} | {handler, FormatHandler} | {process_info,PI} |
+ shell | {shell, ShellSpec} | {timer, TimerSpec} | {overload, {MSec, Module, Function}}
+ | {flush, MSec} | resume | {resume, FetchTimeout}</v>
+ <v>TimerSpec = MSec | {MSec, StopOpts}</v>
+ <v>MSec = FetchTimeout = integer()</v>
+ <v>Module = Function = atom() </v>
+ <v>StopOpts = see stop/2</v>
<v>Client = File | {local, File}</v>
<v>File = Filename | Wrap</v>
<v>Filename = string()</v>
<v>Wrap = {wrap,Filename} | {wrap,Filename,Size,Count}</v>
<v>FormatHandler = See format/2</v>
<v>PI = true | false </v>
+ <v>ShellSpec = true | false | only</v>
</type>
<desc>
<p>This function starts a file trace port on all given nodes
@@ -96,7 +144,70 @@
is the process' registered name its globally registered name,
or its initial function. It is possible to turn off this
functionality by setting <c>PI = false</c>.
- </p>
+ </p>
+ <p>The <c>{shell, ShellSpec}</c> option indicates that the trace messages should
+ be printed on the console as they are received by the tracing
+ process. This implies <c>{local, File}</c> trace client. If the ShellSpec
+ is <c>only</c> (instead of <c>true</c>), no trace logs are stored.
+ </p>
+ <p>The <c>shell</c> option is a shortcut for <c>{shell, true}</c>.</p>
+ <p>The <c>timer</c> option indicates that the trace should be
+ automatically stopped after <c>MSec</c> milliseconds. <c>StopOpts</c>
+ are passed to <c>ttb:stop/2</c> command if specified (default is <c>[]</c>).
+ Note that the timing is approximate, as delays related to
+ network communication are always present. The timer starts after
+ <c>ttb:p/2</c> is issued, so you can set up your trace patterns before.
+ </p>
+ <p>The <c>overload</c> option allows to enable overload
+ checking on the nodes under trace. <c>Module:Function(check)</c>
+ is performed each <c>MSec</c> milliseconds. If the check returns
+ <c>true</c>, the tracing is disabled on a given node.<br/>
+ <c>Module:Function</c> should be able to handle at least three
+ atoms: <c>init</c>, <c>check</c> and <c>stop</c>. <c>init</c> and
+ <c>stop</c> give the user a possibility to initialize and clean
+ up the check environment.<br/>
+ When a node gets overloaded, it is not possible to issue <c>ttb:p</c>
+ nor any command from the <c>ttb:tp</c> family, as it would lead to
+ inconsistent tracing state (different trace specifications on
+ different node).
+ </p>
+ <p>The <c>flush</c> option periodically flushes all file trace
+ port clients (see <c>dbg:flush_trace_port/1</c>). When enabled,
+ the buffers are freed each <c>MSec</c> milliseconds. This option is
+ not allowed with <c>{file, {local, File}}</c> tracing.
+ </p>
+ <p><c>{resume, FetchTimeout}</c> enables the autoresume feature.
+ Whenever enabled, remote nodes try to reconnect to the controlling node
+ in case they were restarted. The feature requires <c>runtime_tools</c>
+ application to be started (so it has to be present in the <c>.boot</c>
+ scripts if the traced nodes run with embedded erlang). If this is
+ not possible, resume may be performed manually by starting
+ <c>runtime_tools</c> remotely using <c>rpc:call/4</c>.<br/>
+ <c>ttb</c> tries to fetch all logs from a reconnecting node before
+ reinitializing the trace. This has to finish within FetchTimeout milliseconds
+ or is aborted<br/>
+ By default, autostart information is stored in a file called
+ <c>ttb_autostart.bin</c> on each node. If this is not desired
+ (i.e. on diskless nodes), a custom module to handle autostart
+ information storage and retrieval can be provided by specifying
+ <c>ttb_autostart_module</c> environment variable for the <c>runtime_tools</c>
+ application. The module has to respond to the following API:
+ <taglist>
+ <tag><c>write_config(Data) -> ok</c></tag>
+ <item>Store the provided data for further retrieval. It is
+ important to realize that the data storage used must not
+ be affected by the node crash.</item>
+ <tag><c>read_config() -> {ok, Data} | {error, Error}</c></tag>
+ <item>Retrieve configuration stored with <c>write_config(Data)</c>.</item>
+ <tag><c>delete_config() -> ok</c></tag>
+ <item>Delete configuration stored with <c>write_config(Data)</c>.
+ Note that after this call any subsequent calls to <c>read_config</c>
+ must return <c>{error, Error}</c>.
+ </item>
+ </taglist>
+ </p>
+ <p>The <c>resume</c> option implies the default <c>FetchTimeout</c>, which is
+ 10 seconds</p>
</desc>
</func>
<func>
@@ -110,7 +221,7 @@
</type>
<desc>
<p>This function sets the given trace flags on the given
- processes.
+ processes. The <c>timestamp</c> flag is always turned on.
</p>
<p>Please turn to the Reference manual for module <c>dbg</c>
for details about the possible trace flags. The parameter
@@ -119,6 +230,9 @@
registered names or process identifiers. If a registered name
is given, the flags are set on processes with this name on all
active nodes.</p>
+ <p>Issuing this command starts the timer for this trace if
+ <c>timer</c> option was specified with <c>tracer/2</c>.
+ </p>
</desc>
</func>
<func>
@@ -155,6 +269,18 @@
<tag><c>ctpg</c></tag>
<item>Clear trace pattern on global function calls</item>
</taglist>
+ <p>With <c>tp</c> and <c>tpl</c> one of match specification shortcuts
+ may be used (example: <c>ttb:tp(foo_module, caller)</c>). The shortcuts are:
+ <taglist>
+ <item><c>return</c> - for <c>[{'_',[],[{return_trace}]}]</c>
+ (report the return value)</item>
+ <item><c>caller</c> - for <c>[{'_',[],[{message,{caller}}]}]</c>
+ (report the calling function)</item>
+ <item><c>{codestr, Str}</c> - for <c>dbg:fun2ms/1</c> arguments
+ passed as strings (example: <c>"fun(_) -> return_trace() end"</c>)
+ </item>
+ </taglist>
+ </p>
</desc>
</func>
<func>
@@ -189,7 +315,7 @@
</desc>
</func>
<func>
- <name>write_config(ConfigFile,Config,Opt) -> ok | {error,Reason}</name>
+ <name>write_config(ConfigFile,Config,Opts) -> ok | {error,Reason}</name>
<fsummary>Creates a config file.</fsummary>
<type>
<v>ConfigFile = string()</v>
@@ -197,7 +323,8 @@
<v>Mod = atom()</v>
<v>Func = atom()</v>
<v>Args = [term()]</v>
- <v>Opt = [] | [append]</v>
+ <v>Opts = Opt | [Opt]</v>
+ <v>Opt = append</v>
</type>
<desc>
<p>This function creates or extends a config file which can be
@@ -213,9 +340,9 @@
should be a list of integers pointing out the entries to be
stored.
</p>
- <p>If <c>Opt</c> is not given or if it is <c>[]</c>,
+ <p>If <c>Opts</c> is not given or if it is <c>[]</c>,
<c>ConfigFile</c> is deleted and a new file is created. If
- <c>Opt = [append]</c>, <c>ConfigFile</c> will not be deleted.
+ <c>Opts = [append]</c>, <c>ConfigFile</c> will not be deleted.
The new information will be appended at the end of the file.</p>
</desc>
</func>
@@ -226,7 +353,9 @@
<v>ConfigFile = string()</v>
</type>
<desc>
- <p>Executes all entries in the given config file.</p>
+ <p>Executes all entries in the given config file. Note that the history
+ of the last trace is always available in the file named
+ <c>ttb_last_config</c>.</p>
</desc>
</func>
<func>
@@ -243,6 +372,9 @@
</p>
<p>The content of a config file can be listed with
<c>list_config/1</c>.</p>
+ <p> Note that the history
+ of the last trace is always available in the file named
+ <c>ttb_last_config</c>.</p>
</desc>
</func>
<func>
@@ -334,29 +466,51 @@
</desc>
</func>
<func>
- <name>stop(Opts) -> stopped</name>
+ <name>stop(Opts) -> stopped | {stopped, Dir}</name>
<fsummary>Stop tracing and fetch/format logs from all nodes</fsummary>
<type>
- <v>Opts = [Opt]</v>
- <v>Opt = fetch | format</v>
+ <v>Opts = Opt | [Opt]</v>
+ <v>Opt = nofetch | {fetch_dir, Dir} | format | {format, FormatOpts} | return_fetch_dir</v>
+ <v>Dir = string()</v>
+ <v>FormatOpts = see format/2</v>
</type>
<desc>
- <p>Stops tracing on all nodes.
- </p>
- <p>The <c>fetch</c> option indicates that trace logs shall be
- collected from all nodes after tracing is stopped. This option
- is useful if nodes on remote machines are traced. Logs and
- trace information files are then sent to the trace control
+ <p>Stops tracing on all nodes. Logs and
+ trace information files are sent to the trace control
node and stored in a directory named
- <c>ttb_upload-Timestamp</c>, where <c>Timestamp</c> is on the
+ <c>ttb_upload_FileName-Timestamp</c>, where <c>Filename</c> is
+ the one provided with <c>{file, File}</c> during trace setup
+ and <c>Timestamp</c> is of the
form <c>yyyymmdd-hhmmss</c>. Even logs from nodes on the same
machine as the trace control node are moved to this directory.
- </p>
+ The history list is saved to a file named <c>ttb_last_config</c>
+ for further reference (as it will be not longer accessible
+ through history and configuration management functions (like
+ <c>ttb:list_history/0</c>).
+ </p>
+ <p>The <c>nofetch</c> option indicates that trace logs shall not be
+ collected after tracing is stopped.
+ </p>
+ <p>The <c>{fetch, Dir}</c> option allows to specify the directory
+ to fetch the data to. If the directory already exists, an
+ error is thrown.
+ </p>
<p>The <c>format</c> option indicates that the trace logs
- shall be formatted after tracing is stopped. Note that this
- option also implies the <c>fetch</c> option, i.e. logs are
- collected in a new directory on the trace control node before
- formatting. All logs in the directory will be merged.</p>
+ shall be formatted after tracing is stopped. All logs in the fetch directory will be merged.
+ You may use <c>{format, FormatOpts}</c> to pass additional
+ arguments to <c>format/2</c>.</p>
+ <p>The <c>return_fetch_dir</c> option indicates that the return value
+ should be <c>{stopped, Dir}</c> and not just <c>stopped</c>.
+ This implies <c>fetch</c>.
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name>get_et_handler()</name>
+ <fsummary>Returns <c>et</c> handler.</fsummary>
+ <desc>
+ <p>The <c>et</c> handler returned by the function may be used with <c>format/2</c>
+ or <c>tracer/2</c>. Example: <c>ttb:format(Dir, [{handler, ttb:get_et_handler()}])</c>.</p>
</desc>
</func>
<func>
@@ -372,37 +526,40 @@
<type>
<v>File = string() | [string()]</v>
<d>This can be the name of a binary log, a list of such logs or the name of a directory containing one or more binary logs.</d>
- <v>Options = [Opt]</v>
- <v>Opt = {out,Out} | {handler,FormatHandler}</v>
+ <v>Options = Opt | [Opt]</v>
+ <v>Opt = {out,Out} | {handler,FormatHandler} | disable_sort</v>
<v>Out = standard_io | string()</v>
- <v>FormatHandler = {Function, InitialState} | et</v>
+ <v>FormatHandler = {Function, InitialState}</v>
<v>Function = fun(Fd,Trace,TraceInfo,State) -> State</v>
<v>Fd = standard_io | FileDescriptor</v>
<d>This is the file descriptor of the destination file <c>Out</c></d>
<v>Trace = tuple()</v>
<d>This is the trace message. Please turn to the Reference manual for the <c>erlang</c>module for details.</d>
<v>TraceInfo = [{Key,ValueList}]</v>
- <d>This includes the keys <c>flags</c>, <c>client</c>and <c>node</c>, and if <c>handler</c>is given as option to the tracer function, this is also included. In addition all information written with the <c>write_trace_info/2</c>function is included. </d>
+ <d>This includes the keys <c>flags</c>, <c>client</c> and <c>node</c>, and if <c>handler</c> is given as option to the tracer function, this is also included. In addition all information written with the <c>write_trace_info/2</c>function is included. </d>
</type>
<desc>
- <p>Reads the given binary trace log(s). If a directory or a
- list of logs is given and the <c>timestamp</c> flag was set
- during tracing, the trace messages from the different logs are
- merged according to the timestamps.
- </p>
+ <p>Reads the given binary trace log(s). The logs are processed
+ in the order of their timestamp as long as <c>disable_sort</c>
+ option is not given.
+ </p>
<p>If <c>FormatHandler = {Function,InitialState}</c>,
<c>Function</c> will be called for each trace message. If
- <c>FormatHandler = et</c>, <c>et_viewer</c> in the <em>Event Tracer</em> application (<c>et</c>) is used for presenting the
- trace log graphically. <c>ttb</c> provides a few different
+ <c>FormatHandler = get_et_handler()</c>, <c>et_viewer</c> in
+ the <em>Event Tracer</em> application (<c>et</c>) is used for presenting
+ the trace log graphically. <c>ttb</c> provides a few different
filters which can be selected from the Filter menu in the
<c>et_viewer</c>. If <c>FormatHandler</c> is not given, a
default handler is used which presents each trace message as a
line of text.
</p>
+ <p>The state returned from each call of <c>Function</c> is passed to the next call,
+ even if next call is to format a message from another log file.
+ </p>
<p>If <c>Out</c> is given, <c>FormatHandler</c> gets the
- filedescriptor to <c>Out</c> as the first parameter.
+ file descriptor to <c>Out</c> as the first parameter.
</p>
- <p><c>Out</c> is ignored if <c>FormatHandler = et</c>.
+ <p><c>Out</c> is ignored if <c>et</c> format handler is used.
</p>
<p>Wrap logs can be formatted one by one or all in one go. To
format one of the wrap logs in a set, give the exact name of
diff --git a/lib/observer/doc/src/ttb_ug.xml b/lib/observer/doc/src/ttb_ug.xml
index 44b7b08fd3..4f2b55a22a 100644
--- a/lib/observer/doc/src/ttb_ug.xml
+++ b/lib/observer/doc/src/ttb_ug.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2002</year><year>2009</year>
+ <year>2002</year><year>2010</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -48,11 +48,13 @@
<item>Formatting of binary trace logs and merging of logs from
multiple nodes.</item>
</list>
- <p>Even though the intention of the Trace Tool Builder is to serve
- as a base for tailor made trace tools, it is of course possible
- to use it directly from the erlang shell. The application only
- allows the use of file port tracer, so if you would like would
- like to use other types of trace clients you will be better off
+ <p>The intention of the Trace Tool Builder is to serve
+ as a base for tailor made trace tools, but you may use it directly
+ from the erlang shell (it may mimic <c>dbg</c> behaviour while
+ still providing useful additions like match specification shortcuts).
+ The application only
+ allows the use of file port tracer, so if you would like
+ to use other types of trace clients you will be better off
using <c>dbg</c> directly instead.</p>
</section>
@@ -64,14 +66,15 @@
trace flags on the processes you want to trace with
<c>ttb:p/2</c>. Then, when the tracing is completed, you must stop
the tracer with <c>ttb:stop/0/1</c> and format the trace log with
- <c>ttb:format/1/2</c>.
+ <c>ttb:format/1/2</c> (as long as there is anything to format, of
+ course).
</p>
- <p><c>ttb:tracer/0/1/2</c> opens a file trace port on each node
- that shall be traced. All trace messages will be written to this
- port and end up in a binary file (the binary trace log).
+ <p><c>ttb:tracer/0/1/2</c> opens a trace port on each node
+ that shall be traced. By default, trace messages are written
+ to binary files on remote nodes(the binary trace log).
</p>
- <p><c>ttb:p/2</c> specifies which processes that shall be
- traced. Trace flags given in this call specifies what to trace on
+ <p><c>ttb:p/2</c> specifies which processes shall be
+ traced. Trace flags given in this call specify what to trace on
each process. You can call this function several times if you like
different trace flags to be set on different processes.
</p>
@@ -105,14 +108,15 @@
-export([f/0]).
f() ->
receive
- From when pid(From) ->
+ From when is_pid(From) ->
Now = erlang:now(),
From ! {self(),Now}
end. </code>
<p>The following example shows the basic use of <c>ttb</c> from
the erlang shell. Default options are used both for starting the
- tracer and for formatting. This gives a trace log named
- <c>Node-ttb</c>, where <c>Node</c> is the name of the node. The
+ tracer and for formatting (the custom fetch dir is however provided).
+ This gives a trace log named <c>Node-ttb</c> in the newly-created
+ directory, where <c>Node</c> is the name of the node. The
default handler prints the formatted trace messages in the
shell.</p>
<code type="none"><![CDATA[
@@ -131,11 +135,11 @@ f() ->
(tiger@durin)50>
(tiger@durin)50> %% Here I set a trace pattern on erlang:now/0
(tiger@durin)50> %% The trace pattern is a simple match spec
-(tiger@durin)50> %% generated by dbg:fun2ms/1. It indicates that
-(tiger@durin)50> %% the return value shall be traced.
-(tiger@durin)50> MS = dbg:fun2ms(fun(_) -> return_trace() end).
-[{'_',[],[{return_trace}]}]
-(tiger@durin)51> ttb:tp(erlang,now,MS).
+(tiger@durin)50> %% indicating that the return value should be
+(tiger@durin)50> %% traced. Refer to the reference_manual for
+(tiger@durin)50> %% the full list of match spec shortcuts
+(tiger@durin)50> %% available.
+(tiger@durin)51> ttb:tp(erlang,now,return).
{ok,[{matched,tiger@durin,1},{saved,1}]}
(tiger@durin)52>
(tiger@durin)52> %% I run my test (i.e. send a message to
@@ -145,11 +149,11 @@ f() ->
(tiger@durin)53>
(tiger@durin)53> %% And then I have to stop ttb in order to flush
(tiger@durin)53> %% the trace port buffer
-(tiger@durin)53> ttb:stop().
-stopped
+(tiger@durin)53> ttb:stop([return, {fetch_dir, "fetch"}]).
+{stopped, "fetch"}
(tiger@durin)54>
(tiger@durin)54> %% Finally I format my trace log
-(tiger@durin)54> ttb:format("tiger@durin-ttb").
+(tiger@durin)54> ttb:format("fetch").
({<0.125.0>,{m,f,0},tiger@durin}) call erlang:now()
({<0.125.0>,{m,f,0},tiger@durin}) returned from erlang:now/0 ->
{1031,133451,667611}
@@ -166,11 +170,9 @@ ok ]]></code>
-module(mydebug).
-export([start/0,trc/1,stop/0,format/1]).
-export([print/4]).
-
%% Include ms_transform.hrl so that I can use dbg:fun2ms/2 to
%% generate match specifications.
-include_lib("stdlib/include/ms_transform.hrl").
-
%%% -------------Tool API-------------
%%% ----------------------------------
%%% Star the "mydebug" tool
@@ -180,28 +182,28 @@ start() ->
%% module shall be used as format handler
ttb:tracer(all,[{file,"debug_log"},{handler,{{?MODULE,print},0}}]),
%% All processes (existing and new) shall trace function calls
- %% and include a timestamp in each trace message
- ttb:p(all,[call,timestamp]).
+ %% We want trace messages to be sorted upon format, which requires
+ %% timestamp flag. The flag is however enabled by default in ttb.
+ ttb:p(all,call).
%%% Set trace pattern on function(s)
-trc(M) when atom(M) ->
+trc(M) when is_atom(M) ->
trc({M,'_','_'});
-trc({M,F}) when atom(M), atom(F) ->
+trc({M,F}) when is_atom(M), is_atom(F) ->
trc({M,F,'_'});
-trc({M,F,_A}=MFA) when atom(M), atom(F) ->
- %% This match spec specifies that return values shall
- %% be traced. NOTE that ms_transform.hrl must be included
- %% if dbg:fun2ms/1 shall be used!
+trc({M,F,_A}=MFA) when is_atom(M), is_atom(F) ->
+ %% This match spec shortcut specifies that return values shall
+ %% be traced.
MatchSpec = dbg:fun2ms(fun(_) -> return_trace() end),
ttb:tpl(MFA,MatchSpec).
%%% Format a binary trace log
-format(File) ->
- ttb:format(File).
+format(Dir) ->
+ ttb:format(Dir).
%%% Stop the "mydebug" tool
stop() ->
- ttb:stop().
+ ttb:stop(return).
%%% --------Internal functions--------
%%% ----------------------------------
@@ -226,9 +228,9 @@ do_print(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
[N,Ts,P,M,F,A,R]). ]]></code>
<p>To distinguish trace logs produced with this tool from other
logs, the <c>file</c> option is used in <c>tracer/2</c>. The
- logs will therefore be named <c>Node-debug_log</c>, where
- <c>Node</c> is the name of the node where the log is produced.
- </p>
+ logs will therefore be fetched to a directory named
+ <c>ttb_upload_debug_log-YYYYMMDD-HHMMSS</c>
+ </p>
<p>By using the <c>handler</c> option when starting the tracer,
the information about how to format the file is stored in the
trace information file (<c>.ti</c>). This is not necessary, as
@@ -278,13 +280,157 @@ do_print(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
must be given to the <c>tracer/2</c> function with the value
<c>{local, File}</c>, e.g.</p>
<code type="none">
-(trace_control@durin)1> ttb:tracer(mynode@diskless,[{file,{local,
-{wrap,"mytrace"}}}]).
+(trace_control@durin)1> ttb:tracer(mynode@diskless,{file,{local,
+{wrap,"mytrace"}}}).
{ok,[mynode@diskless]} </code>
</section>
</section>
<section>
+ <title>Additional tracing options</title>
+ <p>When setting up a trace, several features may be turned on:</p>
+ <list type="bulleted">
+ <item>time-constrained tracing,</item>
+ <item>overload protection,</item>
+ <item>autoresuming.</item>
+ </list>
+ <section>
+ <title>Time-constrained tracing</title>
+ <p>Sometimes, it may be helpful to enable trace for a
+ given period of time (i.e. to monitor a system for 24 hours
+ or half of a second). This may be done by issuing additional
+ <c>{timer, TimerSpec}</c> option. If <c>TimerSpec</c> has the
+ form of <c>MSec</c>, the trace is stopped after <c>MSec</c>
+ milliseconds using <c>ttb:stop/0</c>. If any additional options
+ are provided (<c>TimerSpec = {MSec, Opts}</c>), <c>ttb:stop/1</c>
+ is called instead with <c>Opts</c> as the arguments. The timer
+ is started with <c>ttb:p/2</c>, so any trace patterns should
+ be set up before. <c>ttb:start_trace/4</c>
+ always sets up all pattern before invoking <c>ttb:p/2</c>.
+ Note that due to network and processing delays the the period
+ of tracing is approximate.
+ The example below shows how to set up a trace which will be
+ automatically stopped and formatted after 5 seconds
+ </p><code>
+(tiger@durin)1>ttb:start_trace([node()],
+ [{erlang, now,[]}],
+ {all, call},
+ [{timer, {5000, format}}]).
+</code>
+ </section>
+ <section>
+ <label>Overload protection</label>
+ <p>When tracing live systems, special care needs to be always taken
+ not to overload a node with too heavy tracing. <c>ttb</c> provides
+ the <c>overload</c> option to help to address the problem.</p>
+ <p><c>{overload, MSec, Module, Function}</c> instructs the ttb backend
+ (called <c>observer_backend</c>, part of the <c>runtime_tools</c>
+ application) to perform overload check every <c>MSec</c> milliseconds.
+ If the check (namely <c>Module:Function(check)</c>) returns
+ <c>true</c>, tracing is disabled on the selected node.</p>
+ <p>Overload protection activated on one node does not
+ affect other nodes, where the tracing continues as normal.
+ <c>ttb:stop/0/1</c> fetches data from all clients, including everything
+ that has been collected before overload protection was activated.
+ Note that
+ changing trace details (with <c>ttb:p</c> and <c>ttb:tp/tpl...</c>)
+ once overload protection gets activated in one of the traced
+ nodes is not permitted in order not to allow trace setup
+ to be inconsistent between nodes.
+ </p>
+ <p><c>Module:Function</c> provided with the <c>overload</c> option must
+ handle three calls: <c>init</c>, <c>check</c> and <c>stop</c>. <c>init</c>
+ and <c>stop</c> allows to perform some setup and teardown required by
+ the check. An overload check module could look like this (note that
+ <c>check</c> is always called by the same process, so <c>put</c> and
+ <c>get</c> are possible).
+ </p><code>
+-module(overload).
+-export([check/1]).
+
+check(init) ->
+ Pid = sophisticated_module:start(),
+ put(pid, Pid);
+check(check) ->
+ get(pid) ! is_overloaded,
+ receive
+ Reply ->
+ Reply
+ after 5000 ->
+ true
+ end;
+check(stop) ->
+ get(pid) ! stop.</code>
+ </section>
+ <section>
+ <title>Autoresume</title>
+ <p>It is possible that a node (probably a buggy one, hence traced)
+ crashes. In order to automatically resume tracing on the node
+ as soon as it gets back, <c>resume</c> has to be used. When
+ it is, the failing node tries to reconnect
+ to trace control node as soon as <c>runtime tools</c> is started.
+ This implies that <c>runtime_tools</c> must be included in
+ other node's startup chain (if it is not, one could still
+ resume tracing by starting <c>runtime_tools</c> manually,
+ i.e. by an RPC call).</p>
+ <p>In order not to loose the data that the failing node stored
+ up to the point of crash, the control node will try to fetch
+ it before restarting trace. This must happen within the allowed
+ time frame or is aborted (default is 10 seconds, can be customized with
+ <c>{resume, MSec}</c>). The data fetched this way is then
+ merged with all other traces.</p>
+ <p>Autostart feature requires additional data to be stored on
+ traced nodes. By default, the data is stored automatically
+ to the file called "ttb_autostart.bin" in the traced node's cwd.
+ Users may decide to change this behaviour (i.e. on diskless
+ nodes) by specifying their own module to handle autostart data
+ storage and retrieval (<c>ttb_autostart_module</c>
+ environment variable of <c>runtime_tools</c>). Please see the
+ ttb's reference manual to see the module's API. This example
+ shows the default handler</p>
+ <code>
+-module(ttb_autostart).
+-export([read_config/0,
+ write_config/1,
+ delete_config/0]).
+
+-define(AUTOSTART_FILENAME, "ttb_autostart.bin").
+
+delete_config() ->
+ file:delete(?AUTOSTART_FILENAME).
+
+read_config() ->
+ case file:read_file(?AUTOSTART_FILENAME) of
+ {ok, Data} -> {ok, binary_to_term(Data)};
+ Error -> Error
+ end.
+
+write_config(Data) ->
+ file:write_file(?AUTOSTART_FILENAME, term_to_binary(Data)).
+ </code>
+ <p>Remember that file trace ports buffer the data
+ by default. If the node crashes, trace messages are not
+ flushed to the binary log. If the chance of failure is
+ high, it might be a good idea to automatically flush
+ the buffers every now and then. Passing <c>{flush, MSec}</c>
+ as one of <c>ttb:tracer/2</c> option flushes all buffers
+ every <c>MSec</c> milliseconds.</p>
+ </section>
+ <section>
+ <title>dbg mode</title>
+ <p>The <c>{shell, ShellType}</c> option allows to make <c>ttb</c>
+ operation similar to <c>dbg</c>. Using <c>{shell, true}</c>
+ displays all trace messages in the shell before storing them.
+ <c>{shell, only}</c> additionally disables message storage
+ (so that the tool behaves exactly like dbg). This is allowed
+ only with ip trace ports (<c>{trace, {local, File}}</c>).
+ </p>
+ <p>The command <c>ttb:tracer(dbg)</c> is a shortcut for the pure-dbg
+ mode (<c>{shell, only}</c>).</p>
+ </section>
+ </section>
+
+ <section>
<marker id="trace_info"></marker>
<title>Trace Information and the .ti File</title>
<p>In addition to the trace log file(s), a file with the extension
@@ -292,13 +438,9 @@ do_print(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
is the trace information file. It is a binary file, and it
contains the process information, trace flags used, the name of
the node to which it belongs and all information written with the
- <c>write_trace_info/2</c> function.
- </p>
- <p>To be able to use all this information during formatting, it is
- important that the trace information file exists in the same
- directory as the trace log, and that it has the same name as the
- trace log with the additional extension <c>.ti</c>.
- </p>
+ <c>write_trace_info/2</c> function. .ti files are always fetched
+ with other logs when the trace is stopped.
+ </p>
<p>Except for the process information, everything in the trace
information file is passed on to the handler function when
formatting. The <c>TI</c> parameter is a list of
@@ -327,7 +469,12 @@ do_print(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
each log. <c>ttb</c> will create a new binary log each time a log
reaches the maximum size. When the the maximum number of logs are
reached, the oldest log is deleted before a new one is created.
- </p>
+ </p>
+ <p>Note that the overall size of data generated by ttb may be greater
+ than the wrap specification would suggest - if a traced node restarts
+ and autoresume is enabled, old wrap log is always stored and
+ a new one is created.
+ </p>
<p>Wrap logs can be formatted one by one or all at once. See
<seealso marker="#format">Formatting</seealso>.
</p>
@@ -348,12 +495,10 @@ do_print(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
present the trace log graphically (see <seealso marker="#et_viewer">Presenting trace logs with Event Tracer</seealso>).
</p>
<p>The first argument to <c>ttb:format/1/2</c> specifies which
- binary log(s) to format. This can be the name of one binary log, a
- list of such logs or the name of a directory containing one or
- more binary logs. If this argument indicates more than one log,
- and the <c>timestamp</c> flag was set when tracing, the trace
- messages from the different logs will be merged according to the
- timestamps in each message.
+ binary log(s) to format. This is usually the name of a directory
+ that ttb created during log fetch. Unless there is the <c>disable_sort</c>
+ option provided, the logs from different files are always sorted
+ according to timestamp in traces.
</p>
<p>The second argument to <c>ttb:format/2</c> is a list of
options. The <c>out</c> option specifies the destination where the
@@ -363,7 +508,10 @@ do_print(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
option is not given, the <c>handler</c> option given when starting
the tracer is used. If the <c>handler</c> option was not given
when starting the tracer either, a default handler is used, which
- prints each trace message as a line of text.
+ prints each trace message as a line of text. The <c>disable_sort</c>
+ option indicates that there logs should not be merged according to
+ timestamp, but processed one file after another (this might be
+ a bit faster).
</p>
<p>A format handler is a fun taking four arguments. This fun will
be called for each trace message in the binary log(s). A simple
@@ -396,10 +544,24 @@ end </code>
<c>handle_gc/4</c> in the module <c>multitrace.erl</c> which can
be found in the <c>src</c> directory of the Observer application.
</p>
- <p>By giving the format handler <c>et</c>, you can have the trace
+ <p>The actual trace message is passed as the second argument (<c>Trace</c>).
+ The possible values of <c>Trace</c> are:</p>
+ <list type="bulleted">
+ <item>all trace messages described in <c>erlang:trace/3</c> documentation,
+ </item>
+ <item><c>{drop, N}</c> if ip tracer is used (see <c>dbg:trace_port/2</c>),
+ </item>
+ <item><c>end_of_trace</c> received once when all trace messages have
+ been processed.</item>
+ </list>
+ <p>By giving the format handler <c>ttb:get_et_handler()</c>, you can have the trace
log presented graphically with <c>et_viewer</c> in the Event
Tracer application (see <seealso marker="#et_viewer">Presenting trace logs with Event Tracer</seealso>).
- </p>
+ </p>
+ <p>You may always decide not to format the whole trace data contained
+ in the fetch directory, but analyze single files instead. In order
+ to do so, a single file (or list of files) have to be passed as
+ the first argument to <c>format/1/2</c>.</p>
<p>Wrap logs can be formatted one by one or all in one go. To
format one of the wrap logs in a set, give the exact name of the
file. To format the whole set of wrap logs, give the name with '*'
@@ -407,7 +569,7 @@ end </code>
</p>
<p>Start tracing:</p>
<code type="none">
-(tiger@durin)1> ttb:tracer(node(),[{file,{wrap,"trace"}}]).
+(tiger@durin)1> ttb:tracer(node(),{file,{wrap,"trace"}}).
{ok,[tiger@durin]}
(tiger@durin)2> ttb:p(...)
... </code>
@@ -443,7 +605,7 @@ ok
to the User's Guide and Reference Manuals for the <c>et</c>
application.
</p>
- <p>By giving the format handler <c>et</c>, you can have the
+ <p>By giving the format handler <c>ttb:get_et_handler()</c>, you can have the
trace log presented graphically with <c>et_viewer</c> in the
Event Tracer application. <c>ttb</c> provides a few different
filters which can be selected from the Filter menu in the
@@ -495,9 +657,23 @@ ok
filters respectively, except that each module or function can
have several vertical lines, one for each process it resides on.
</p>
- <p>As an example this module is used, and the function
- <c>bar:f1()</c> is called from another module <c>foo</c>.</p>
+ <p>In the next example, modules <c>foo</c> and <c>bar</c> are used:</p>
<code type="none">
+-module(foo).
+-export([start/0,go/0]).
+
+start() ->
+ spawn(?MODULE, go, []).
+
+go() ->
+ receive
+ stop ->
+ ok;
+ go ->
+ bar:f1(),
+ go()
+ end.
+</code><code type="none">
-module(bar).
-export([f1/0,f3/0]).
f1() ->
@@ -506,12 +682,23 @@ f1() ->
f2() ->
spawn(?MODULE,f3,[]).
f3() ->
- ok. </code>
- <p>The <c>call</c> and <c>return_to</c> flags are used, and
- trace pattern is set on local calls in module <c>bar</c>.
- </p>
- <p><c>ttb:format("tiger@durin-ttb", [{handler, et}])</c> gives the
- following result:
+ ok.</code>
+
+ <p>Now let's set up the trace.</p>
+<code>
+(tiger@durin)1>%%First we retrieve the Pid to limit traced processes set
+(tiger@durin)1>Pid = foo:start().
+(tiger@durin)2>%%Now we set up tracing
+(tiger@durin)2>ttb:tracer().
+(tiger@durin)3>ttb:p(Pid, [call, return_to, procs, set_on_spawn]).
+(tiger@durin)4>ttb:tpl(bar, []).
+(tiger@durin)5>%%Invoke our test function and see output with et viewer
+(tiger@durin)5>Pid ! go.
+(tiger@durin)6>ttb:stop({format, {handler, ttb:get_et_handler()}}).
+</code>
+
+ <p>This shoud render a result similar to the
+ following:
</p>
<p></p>
<image file="et_processes.gif">
@@ -520,25 +707,37 @@ f3() ->
<image file="et_modsprocs.gif">
<icaption>Filter: "mods_and_procs"</icaption>
</image>
+
+ <p>Note, that we can use <c>ttb:start_trace/4</c> function to help
+ us here:</p>
+<code>
+(tiger@durin)1>Pid = foo:start().
+(tiger@durin)2>ttb:start_trace([node()],
+ [{bar,[]}],
+ {Pid, [call, return_to, procs, set_on_spawn]}
+ {handler, ttb:get_et_handler()}).
+(tiger@durin)3>Pid ! go.
+(tiger@durin)4>ttb:stop(format).
+</code>
+
</section>
</section>
<section>
<marker id="fetch_format"></marker>
<title>Automatically collect and format logs from all nodes</title>
- <p>If the option <c>fetch</c> is given to the <c>ttb:stop/1</c>
- function, trace logs and trace information files are fetched
- from all nodes after tracing is stopped. The logs are stored in a
- new directory named <c>ttb_upload-Timestamp</c> under the working
- directory of the trace control node.
+ <p>By default <c>ttb:stop/1</c> fetches trace logs and
+ trace information files from all nodes. The logs are stored in a
+ new directory named <c>ttb_upload-Filename-Timestamp</c> under the working
+ directory of the trace control node. Fetching may be disabled by
+ providing the <c>nofetch</c> option to <c>ttb:stop/1</c>. User can
+ specify a fetch directory of his choice passing the
+ <c>{fetch_dir, Dir}</c> option.
</p>
<p>If the option <c>format</c> is given to <c>ttb:stop/1</c>, the
trace logs are automatically formatted after tracing is
- stopped. Note that <c>format</c> also implies <c>fetch</c>,
- i.e. the trace logs will be collected from all nodes as for the
- <c>fetch</c> option before they are formatted. All logs in the
- upload directory are merged during formatting.
- </p>
+ stopped.
+ </p>
</section>
<section>
@@ -546,13 +745,18 @@ f3() ->
<p>For the tracing functionality, <c>dbg</c> could be used instead
of the <c>ttb</c> for setting trace flags on processes and trace
patterns for call trace, i.e. the functions <c>p</c>, <c>tp</c>,
- <c>tpl</c>, <c>ctp</c>, <c>ctpl</c> and <c>ctpg</c>. The only
- thing added by <c>ttb</c> for these functions is that all calls
- are stored in the history buffer and can be recalled and stored in
- a configuration file. This makes it easy to setup the same trace
- environment e.g. if you want to compare two test runs. It also
- reduces the amount of typing when using <c>ttb</c> from the erlang
- shell.
+ <c>tpl</c>, <c>ctp</c>, <c>ctpl</c> and <c>ctpg</c>. There are only
+ two things added by <c>ttb</c> for these functions:
+ <list type="bulleted">
+ <item>all calls are stored in the history buffer and can be
+ recalled and stored in a configuration file. This makes it
+ easy to setup the same trace environment e.g. if you want to
+ compare two test runs. It also reduces the amount of
+ typing when using <c>ttb</c> from the erlang shell;</item>
+ <item>shortcuts are provided for the most common match
+ specifications (in order not to force the user to use
+ <c>dbg:fun2ms</c> continually</item>).
+ </list>
</p>
<p>Use <c>list_history/0</c> to see the content of the history
buffer, and <c>run_history/1</c> to re-execute one of the entries.
@@ -574,7 +778,8 @@ f3() ->
selected entries from the history by calling
<c>ttb:write_config(ConfigFile,NumList)</c>, where
<c>NumList</c> is a list of integers pointing out the history
- entries to write.
+ entries to write. Moreover, the history buffer is always dumped
+ to <c>ttb_last_config</c> when <c>ttb:stop/0/1</c> is called.
</p>
<p>User defined entries can also be written to a config file by
calling the function
@@ -720,9 +925,7 @@ ok
{ok,[{matched,1},{saved,1}]}
(tiger@durin)113> dbg:get_tracer(), seq_trace:reset_trace().
true
-(tiger@durin)114> ttb:stop().
-ok
-(tiger@durin)115> ttb:format("tiger@durin-ttb").
+(tiger@durin)114> ttb:stop(format).
({<0.158.0>,{shell,evaluator,3},tiger@durin}) call dbg:get_tracer()
SeqTrace [0]: ({<0.158.0>,{shell,evaluator,3},tiger@durin})
{<0.237.0>,dbg,tiger@durin} ! {<0.158.0>,{get_tracer,tiger@durin}}
@@ -743,9 +946,7 @@ ok
(tiger@durin)117> seq_trace:set_token(send,true), dbg:get_tracer(),
seq_trace:reset_trace().
true
-(tiger@durin)118> ttb:stop().
-ok
-(tiger@durin)119> ttb:format("tiger@durin-ttb").
+(tiger@durin)118> ttb:stop(format).
SeqTrace [0]: ({<0.158.0>,{shell,evaluator,3},tiger@durin})
{<0.246.0>,dbg,tiger@durin} ! {<0.158.0>,{get_tracer,tiger@durin}}
[Serial: {0,1}]
diff --git a/lib/observer/src/Makefile b/lib/observer/src/Makefile
index 2d06cb6bc4..3875b62101 100644
--- a/lib/observer/src/Makefile
+++ b/lib/observer/src/Makefile
@@ -56,13 +56,16 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
PRIVDIR= ../priv
WEBTOOLFILES= $(PRIVDIR)/crashdump_viewer.tool
BINDIR= $(PRIVDIR)/bin
+ifeq ($(findstring win32,$(TARGET)),win32)
+WIN32_EXECUTABLES= $(BINDIR)/etop.bat $(BINDIR)/getop.bat $(BINDIR)/cdv.bat
+else
+WIN32_EXECUTABLES=
+endif
EXECUTABLES= \
$(BINDIR)/etop \
$(BINDIR)/getop \
$(BINDIR)/cdv \
- $(BINDIR)/etop.bat \
- $(BINDIR)/getop.bat \
- $(BINDIR)/cdv.bat
+ $(WIN32_EXECUTABLES)
CDVDIR= $(PRIVDIR)/crashdump_viewer
GIF_FILES= \
$(CDVDIR)/collapsd.gif \
diff --git a/lib/observer/src/ttb.erl b/lib/observer/src/ttb.erl
index 221b71df6a..072aa165e7 100644
--- a/lib/observer/src/ttb.erl
+++ b/lib/observer/src/ttb.erl
@@ -18,9 +18,11 @@
%%
-module(ttb).
-author('[email protected]').
+-author('[email protected]').
%% API
--export([tracer/0,tracer/1,tracer/2,p/2,stop/0,stop/1]).
+-export([tracer/0,tracer/1,tracer/2,p/2,stop/0,stop/1,start_trace/4]).
+-export([get_et_handler/0]).
-export([tp/2, tp/3, tp/4, ctp/0, ctp/1, ctp/2, ctp/3, tpl/2, tpl/3, tpl/4,
ctpl/0, ctpl/1, ctpl/2, ctpl/3, ctpg/0, ctpg/1, ctpg/2, ctpg/3]).
-export([seq_trigger_ms/0,seq_trigger_ms/1]).
@@ -34,24 +36,38 @@
-include_lib("kernel/include/file.hrl").
-define(meta_time,5000).
+-define(fetch_time, 10000).
-define(history_table,ttb_history_table).
-define(seq_trace_flags,[send,'receive',print,timestamp]).
--define(upload_dir,"ttb_upload").
+-define(upload_dir(Logname),"ttb_upload_"++Logname).
+-define(last_config, "ttb_last_config").
+-define(partial_dir, "ttb_partial_result").
-ifdef(debug).
--define(get_status,;get_status -> erlang:display(dict:to_list(NodeInfo)),loop(NodeInfo)).
+-define(get_status,;get_status -> erlang:display(dict:to_list(NodeInfo),loop(NodeInfo, TraceInfo)).
-else.
-define(get_status,).
-endif.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% Shortcut
+start_trace(Nodes, Patterns, {Procs, Flags}, Options) ->
+ {ok, _} = tracer(Nodes, Options),
+ [{ok, _} = apply(?MODULE, tpl, tuple_to_list(Args)) || Args <- Patterns],
+ {ok, _} = p(Procs, Flags).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Open a trace port on all given nodes and create the meta data file
tracer() -> tracer(node()).
+tracer(shell) -> tracer(node(), shell);
+tracer(dbg) -> tracer(node(), {shell, only});
tracer(Nodes) -> tracer(Nodes,[]).
tracer(Nodes,Opt) ->
- start(),
- store(tracer,[Nodes,Opt]),
{PI,Client,Traci} = opt(Opt),
- do_tracer(Nodes,PI,Client,Traci).
+ %%We use initial Traci as SessionInfo for loop/2
+ Pid = start(Traci),
+ store(tracer,[Nodes,Opt]),
+ do_tracer(Nodes,PI,Client,[{ttb_control, Pid}|Traci]).
do_tracer(Nodes0,PI,Client,Traci) ->
Nodes = nods(Nodes0),
@@ -59,9 +75,14 @@ do_tracer(Nodes0,PI,Client,Traci) ->
do_tracer(Clients,PI,Traci).
do_tracer(Clients,PI,Traci) ->
+ ShellOutput = proplists:get_value(shell, Traci, false),
{ClientSucc,Succ} =
lists:foldl(
fun({N,{local,File},TF},{CS,S}) ->
+ TF2 = case ShellOutput of
+ only -> none;
+ _ -> TF
+ end,
[_Sname,Host] = string:tokens(atom_to_list(N),"@"),
case catch dbg:tracer(N,port,dbg:trace_port(ip,0)) of
{ok,N} ->
@@ -69,8 +90,8 @@ do_tracer(Clients,PI,Traci) ->
{ok,T} = dbg:get_tracer(N),
rpc:call(N,seq_trace,set_system_tracer,[T]),
dbg:trace_client(ip,{Host,Port},
- {fun ip_to_file/2,{file,File}}),
- {[{N,{local,File,Port},TF}|CS], [N|S]};
+ {fun ip_to_file/2,{{file,File}, ShellOutput}}),
+ {[{N,{local,File,Port},TF2}|CS], [N|S]};
Other ->
display_warning(N,{cannot_open_ip_trace_port,
Host,
@@ -98,17 +119,54 @@ do_tracer(Clients,PI,Traci) ->
{ok,Succ}
end.
+opt(Opt) when is_list(Opt) ->
+ opt(Opt,{true,?MODULE,[]});
opt(Opt) ->
- opt(Opt,{true,?MODULE,[]}).
+ opt([Opt]).
opt([{process_info,PI}|O],{_,Client,Traci}) ->
opt(O,{PI,Client,Traci});
opt([{file,Client}|O],{PI,_,Traci}) ->
- opt(O,{PI,Client,Traci});
+ opt(O,{PI,Client,[{logfile,get_logname(Client)}|Traci]});
opt([{handler,Handler}|O],{PI,Client,Traci}) ->
opt(O,{PI,Client,[{handler,Handler}|Traci]});
+opt([{timer, {MSec, StopOpts}}|O],{PI,Client,Traci}) ->
+ opt(O,{PI,Client,[{timer,{MSec, StopOpts}}|Traci]});
+opt([{timer, MSec}|O],{PI,Client,Traci}) ->
+ opt(O,{PI,Client,[{timer,{MSec, []}}|Traci]});
+opt([{overload_check, {MSec,M,F}}|O],{PI,Client,Traci}) ->
+ opt(O,{PI,Client,[{overload_check,{MSec,M,F}}|Traci]});
+opt([shell|O],{PI,Client,Traci}) ->
+ opt(O,{PI,Client,[{shell, true}|Traci]});
+opt([{shell,Type}|O],{PI,Client,Traci}) ->
+ opt(O,{PI,Client,[{shell, Type}|Traci]});
+opt([resume|O],{PI,Client,Traci}) ->
+ opt(O,{PI,Client,[{resume, {true, ?fetch_time}}|Traci]});
+opt([{resume,MSec}|O],{PI,Client,Traci}) ->
+ opt(O,{PI,Client,[{resume, {true, MSec}}|Traci]});
+opt([{flush,MSec}|O],{PI,Client,Traci}) ->
+ opt(O,{PI,Client,[{flush, MSec}|Traci]});
opt([],Opt) ->
- Opt.
+ ensure_opt(Opt).
+
+ensure_opt({PI,Client,Traci}) ->
+ case {proplists:get_value(flush, Traci), Client} of
+ {undefined, _} -> ok;
+ {_, {local, _}} -> exit(flush_unsupported_with_ip_trace_port);
+ {_,_} -> ok
+ end,
+ NeedIpTracer = proplists:get_value(shell, Traci, false) /= false,
+ case {NeedIpTracer, Client} of
+ {false, _} -> {PI, Client, Traci};
+ {true, ?MODULE} -> {PI, {local, ?MODULE}, Traci};
+ {true, {local, File}} -> {PI, {local, File}, Traci};
+ {true, _} -> exit(local_client_required_on_shell_tracing)
+ end.
+
+get_logname({local, F}) -> get_logname(F);
+get_logname({wrap, F}) -> filename:basename(F);
+get_logname({wrap, F, _, _}) -> filename:basename(F);
+get_logname(F) -> filename:basename(F).
nods(all) ->
Nodes1 = remove_active([node()|nodes()]),
@@ -205,17 +263,29 @@ run_history([H|T]) ->
ok -> run_history(T);
{error,not_found} -> {error,{not_found,H}}
end;
+
+run_history(all) ->
+ CurrentHist = ets:tab2list(?history_table),
+ ets:delete_all_objects(?history_table),
+ [run_printed(MFA,true) || {_, MFA} <- CurrentHist];
+run_history(all_silent) ->
+ CurrentHist = ets:tab2list(?history_table),
+ ets:delete_all_objects(?history_table),
+ [run_printed(MFA,false) || {_, MFA} <- CurrentHist];
run_history([]) ->
ok;
run_history(N) ->
case catch ets:lookup(?history_table,N) of
[{N,{M,F,A}}] ->
- print_func(M,F,A),
- R = apply(M,F,A),
- print_result(R);
+ run_printed({M,F,A},true);
_ ->
{error, not_found}
end.
+
+run_printed({M,F,A},Verbose) ->
+ Verbose andalso print_func(M,F,A),
+ R = apply(M,F,A),
+ Verbose andalso print_result(R).
write_config(ConfigFile,all) ->
write_config(ConfigFile,['_']);
@@ -223,6 +293,8 @@ write_config(ConfigFile,Config) ->
write_config(ConfigFile,Config,[]).
write_config(ConfigFile,all,Opt) ->
write_config(ConfigFile,['_'],Opt);
+write_config(ConfigFile,Config,Opt) when not(is_list(Opt)) ->
+ write_config(ConfigFile,Config,[Opt]);
write_config(ConfigFile,Nums,Opt) when is_list(Nums), is_integer(hd(Nums));
Nums=:=['_'] ->
F = fun(N) -> ets:select(?history_table,
@@ -313,6 +385,7 @@ arg_list([A1|A],Acc) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Set trace flags on processes
p(Procs0,Flags0) ->
+ ensure_no_overloaded_nodes(),
store(p,[Procs0,Flags0]),
no_store_p(Procs0,Flags0).
no_store_p(Procs0,Flags0) ->
@@ -327,11 +400,12 @@ no_store_p(Procs0,Flags0) ->
{error,Reason} ->
display_warning(P,Reason),
{PMatched,Ps}
- end
+ end
end,{[],[]},Procs) of
{[],[]} -> {error, no_match};
{SuccMatched,Succ} ->
no_store_write_trace_info(flags,{Succ,Flags}),
+ ?MODULE ! trace_started,
{ok,SuccMatched}
end
end.
@@ -339,7 +413,7 @@ no_store_p(Procs0,Flags0) ->
transform_flags([clear]) ->
[clear];
transform_flags(Flags) ->
- dbg:transform_flags(Flags).
+ dbg:transform_flags([timestamp | Flags]).
procs(Procs) when is_list(Procs) ->
@@ -365,24 +439,30 @@ proc({global,Name}) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Trace pattern
tp(A,B) ->
- store(tp,[A,B]),
- dbg:tp(A,B).
+ ensure_no_overloaded_nodes(),
+ store(tp,[A,ms(B)]),
+ dbg:tp(A,ms(B)).
tp(A,B,C) ->
- store(tp,[A,B,C]),
- dbg:tp(A,B,C).
+ ensure_no_overloaded_nodes(),
+ store(tp,[A,B,ms(C)]),
+ dbg:tp(A,B,ms(C)).
tp(A,B,C,D) ->
- store(tp,[A,B,C,D]),
- dbg:tp(A,B,C,D).
+ ensure_no_overloaded_nodes(),
+ store(tp,[A,B,C,ms(D)]),
+ dbg:tp(A,B,C,ms(D)).
tpl(A,B) ->
- store(tpl,[A,B]),
- dbg:tpl(A,B).
+ ensure_no_overloaded_nodes(),
+ store(tpl,[A,ms(B)]),
+ dbg:tpl(A,ms(B)).
tpl(A,B,C) ->
- store(tpl,[A,B,C]),
- dbg:tpl(A,B,C).
+ ensure_no_overloaded_nodes(),
+ store(tpl,[A,B,ms(C)]),
+ dbg:tpl(A,B,ms(C)).
tpl(A,B,C,D) ->
- store(tpl,[A,B,C,D]),
- dbg:tpl(A,B,C,D).
+ ensure_no_overloaded_nodes(),
+ store(tpl,[A,B,C,ms(D)]),
+ dbg:tpl(A,B,C,ms(D)).
ctp() ->
store(ctp,[]),
@@ -423,6 +503,56 @@ ctpg(A,B,C) ->
store(ctpg,[A,B,C]),
dbg:ctpg(A,B,C).
+ms(return) ->
+ [{'_',[],[{return_trace}]}];
+ms(caller) ->
+ [{'_',[],[{message,{caller}}]}];
+ms({codestr, FunStr}) ->
+ {ok, MS} = string2ms(FunStr),
+ MS;
+ms(Other) ->
+ Other.
+
+ensure_no_overloaded_nodes() ->
+ Overloaded = case whereis(?MODULE) of
+ undefined ->
+ [];
+ _ ->
+ ?MODULE ! {get_overloaded, self()},
+ receive O -> O end
+ end,
+ case Overloaded of
+ [] -> ok;
+ Overloaded -> exit({error, overload_protection_active, Overloaded})
+ end.
+
+-spec string2ms(string()) -> {ok, list()} | {error, fun_format}.
+string2ms(FunStr) ->
+ case erl_scan:string(fix_dot(FunStr)) of
+ {ok, Tokens, _} ->
+ case erl_parse:parse_exprs(Tokens) of
+ {ok, [Expression]} ->
+ case Expression of
+ {_, _, {clauses, Clauses}} ->
+ {ok, ms_transform:transform_from_shell(dbg, Clauses, [])};
+ _ ->
+ {error, fun_format}
+ end;
+ _ ->
+ {error, fun_format}
+ end;
+ _ ->{error, fun_format}
+ end.
+
+-spec fix_dot(string()) -> string().
+fix_dot(FunStr) ->
+ [H | Rest] = lists:reverse(FunStr),
+ case H of
+ $. ->
+ FunStr;
+ H ->
+ lists:reverse([$., H | Rest])
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Support for sequential trace
@@ -457,66 +587,109 @@ no_store_write_trace_info(Key,What) ->
%%% Stop tracing on all nodes
stop() ->
stop([]).
-stop(Opts) ->
+stop(Opts) when is_list(Opts) ->
Fetch = stop_opts(Opts),
- case whereis(?MODULE) of
- undefined -> ok;
- Pid when is_pid(Pid) ->
- ?MODULE ! {stop,Fetch,self()},
- receive {?MODULE,stopped} -> ok end
+ Result =
+ case whereis(?MODULE) of
+ undefined -> ok;
+ Pid when is_pid(Pid) ->
+ ?MODULE ! {stop,Fetch,self()},
+ receive {?MODULE,R} -> R end
+ end,
+ case {Fetch, Result} of
+ {nofetch, _} ->
+ ok;
+ {_, {stopped, _}} ->
+ %% Printout moved out of the ttb loop to avoid occasional deadlock
+ io:format("Stored logs in ~s~n", [element(2, Result)]);
+ {_, _} ->
+ ok
end,
- stopped.
+ stop_return(Result,Opts);
+stop(Opts) ->
+ stop([Opts]).
stop_opts(Opts) ->
- case lists:member(format,Opts) of
- true ->
- format; % format implies fetch
- false ->
- case lists:member(fetch,Opts) of
- true -> fetch;
- false -> nofetch
- end
+ FetchDir = proplists:get_value(fetch_dir, Opts),
+ ensure_fetch_dir(FetchDir),
+ FormatData = case proplists:get_value(format, Opts) of
+ undefined -> false;
+ true -> {format, []};
+ FOpts -> {format, FOpts}
+ end,
+ case {FormatData, lists:member(return_fetch_dir, Opts)} of
+ {false, true} ->
+ {fetch, FetchDir}; % if we specify return_fetch_dir, the data should be fetched
+ {false, false} ->
+ case lists:member(nofetch,Opts) of
+ false -> {fetch, FetchDir};
+ true -> nofetch
+ end;
+ {FormatData, _} ->
+ {FormatData, FetchDir}
+ end.
+
+ensure_fetch_dir(undefined) -> ok;
+ensure_fetch_dir(Dir) ->
+ case filelib:is_file(Dir) of
+ true ->
+ throw({error, exists, Dir});
+ false ->
+ ok
+ end.
+
+stop_return(R,Opts) ->
+ case {lists:member(return_fetch_dir,Opts),R} of
+ {true,_} ->
+ R;
+ {false,{stopped,_}} ->
+ stopped;
+ {false,_} ->
+ %% Anything other than 'stopped' would not be bw compatible...
+ stopped
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Process implementation
-start() ->
+start(SessionInfo) ->
case whereis(?MODULE) of
undefined ->
Parent = self(),
- Pid = spawn(fun() -> init(Parent) end),
- receive {started,Pid} -> ok end;
+ Pid = spawn(fun() -> init(Parent, SessionInfo) end),
+ receive {started,Pid} -> ok end,
+ Pid;
Pid when is_pid(Pid) ->
- ok
+ Pid
end.
-
-init(Parent) ->
+init(Parent, SessionInfo) ->
register(?MODULE,self()),
ets:new(?history_table,[ordered_set,named_table,public]),
Parent ! {started,self()},
- loop(dict:new()).
+ NewSessionInfo = [{partials, 0}, {dead_nodes, []} | SessionInfo],
+ try_send_flush_tick(NewSessionInfo),
+ loop(dict:new(), NewSessionInfo).
-loop(NodeInfo) ->
+loop(NodeInfo, SessionInfo) ->
receive
{init_node,Node,MetaFile,PI,Traci} ->
erlang:monitor_node(Node,true),
- MetaPid =
+ {AbsoluteMetaFile, MetaPid} =
case rpc:call(Node,
observer_backend,
ttb_init_node,
[MetaFile,PI,Traci]) of
- {ok,MP} ->
- MP;
+ {ok,MF,MP} ->
+ {MF,MP};
{badrpc,nodedown} ->
%% We will get a nodedown message
- undefined
+ {MetaFile,undefined}
end,
- loop(dict:store(Node,{MetaFile,MetaPid},NodeInfo));
+ loop(dict:store(Node,{AbsoluteMetaFile,MetaPid},NodeInfo), SessionInfo);
{get_nodes,Sender} ->
Sender ! {?MODULE,dict:fetch_keys(NodeInfo)},
- loop(NodeInfo);
+ loop(NodeInfo, SessionInfo);
{write_trace_info,Key,What} ->
dict:fold(fun(Node,{_MetaFile,MetaPid},_) ->
rpc:call(Node,observer_backend,
@@ -524,55 +697,121 @@ loop(NodeInfo) ->
end,
ok,
NodeInfo),
- loop(NodeInfo);
+ loop(NodeInfo, SessionInfo);
{nodedown,Node} ->
- loop(dict:erase(Node,NodeInfo));
- {stop,nofetch,Sender} ->
- dict:fold(
- fun(Node,{_,MetaPid},_) ->
- rpc:call(Node,observer_backend,ttb_stop,[MetaPid])
- end,
- ok,
- NodeInfo),
- dbg:stop_clear(),
- ets:delete(?history_table),
- Sender ! {?MODULE,stopped};
- {stop,FetchOrFormat,Sender} ->
- Localhost = host(node()),
- Dir = ?upload_dir++ts(),
- file:make_dir(Dir),
- %% The nodes are traversed twice here because
- %% the meta tracing in observer_backend must be
- %% stopped before dbg is stopped, and dbg must
- %% be stopped before the trace logs are moved orelse
- %% windows complains.
- AllNodesAndMeta =
- dict:fold(
- fun(Node,{MetaFile,MetaPid},Nodes) ->
- rpc:call(Node,observer_backend,ttb_stop,[MetaPid]),
- [{Node,MetaFile}|Nodes]
- end,
- [],
- NodeInfo),
- dbg:stop_clear(),
- AllNodes =
- lists:map(
- fun({Node,MetaFile}) ->
- spawn(fun() -> fetch(Localhost,Dir,Node,MetaFile) end),
- Node
- end,
- AllNodesAndMeta),
- ets:delete(?history_table),
- wait_for_fetch(AllNodes),
- io:format("Stored logs in ~s~n",[filename:absname(Dir)]),
- case FetchOrFormat of
- format -> format(Dir);
- fetch -> ok
+ NewState = make_node_dead(Node, NodeInfo, SessionInfo),
+ loop(dict:erase(Node,NodeInfo), NewState);
+ {noderesumed,Node,Reporter} ->
+ {MetaFile, CurrentSuffix, NewState} = make_node_alive(Node, SessionInfo),
+ fetch_partial_result(Node, MetaFile, CurrentSuffix),
+ spawn(fun() -> resume_trace(Reporter) end),
+ loop(NodeInfo, NewState);
+ {timeout, StopOpts} ->
+ spawn(?MODULE, stop, [StopOpts]),
+ loop(NodeInfo, SessionInfo);
+ {node_overloaded, Node} ->
+ io:format("Overload check activated on node: ~p.~n", [Node]),
+ {Overloaded, SI} = {proplists:get_value(overloaded, SessionInfo, []),
+ lists:keydelete(overloaded, 1, SessionInfo)},
+ loop(NodeInfo, [{overloaded, [Node|Overloaded]} | SI]);
+ {get_overloaded, Pid} ->
+ Pid ! proplists:get_value(overloaded, SessionInfo, []),
+ loop(NodeInfo, SessionInfo);
+ trace_started ->
+ case proplists:get_value(timer, SessionInfo) of
+ undefined -> ok;
+ {MSec, StopOpts} -> erlang:send_after(MSec, self(), {timeout, StopOpts})
end,
- Sender ! {?MODULE,stopped}
- ?get_status
+ loop(NodeInfo, SessionInfo);
+ flush_timeout ->
+ [ dbg:flush_trace_port(Node) || Node <- dict:fetch_keys(NodeInfo) ],
+ try_send_flush_tick(SessionInfo),
+ loop(NodeInfo, SessionInfo);
+ {stop,nofetch,Sender} ->
+ do_stop(nofetch, Sender, NodeInfo, SessionInfo);
+ {stop,FetchSpec,Sender} ->
+ case proplists:get_value(shell, SessionInfo, false) of
+ only -> do_stop(nofetch, Sender, NodeInfo, SessionInfo);
+ _ -> do_stop(FetchSpec, Sender, NodeInfo, SessionInfo)
+ end
+ end.
+
+do_stop(nofetch, Sender, NodeInfo, _) ->
+ write_config(?last_config, all),
+ dict:fold(
+ fun(Node,{_,MetaPid},_) ->
+ rpc:call(Node,observer_backend,ttb_stop,[MetaPid])
+ end,
+ ok,
+ NodeInfo),
+ dbg:stop_clear(),
+ ets:delete(?history_table),
+ Sender ! {?MODULE, stopped};
+
+do_stop({FetchOrFormat, UserDir}, Sender, NodeInfo, SessionInfo) ->
+ write_config(?last_config, all),
+ Localhost = host(node()),
+ Dir = get_fetch_dir(UserDir, proplists:get_value(logfile, SessionInfo)),
+ file:make_dir(Dir),
+ %% The nodes are traversed twice here because
+ %% the meta tracing in observer_backend must be
+ %% stopped before dbg is stopped, and dbg must
+ %% be stopped before the trace logs are moved orelse
+ %% windows complains.
+ AllNodesAndMeta =
+ dict:fold(
+ fun(Node,{MetaFile,MetaPid},Nodes) ->
+ rpc:call(Node,observer_backend,ttb_stop,[MetaPid]),
+ [{Node,MetaFile}|Nodes]
+ end,
+ [],
+ NodeInfo),
+ dbg:stop_clear(),
+ AllNodes =
+ lists:map(
+ fun({Node,MetaFile}) ->
+ spawn(fun() -> fetch_report(Localhost,Dir,Node,MetaFile) end),
+ Node
+ end,
+ AllNodesAndMeta),
+ ets:delete(?history_table),
+ wait_for_fetch(AllNodes),
+ copy_partials(Dir, proplists:get_value(partials, SessionInfo)),
+ Absname = filename:absname(Dir),
+ case FetchOrFormat of
+ fetch -> ok;
+ {format, Opts} -> format(Dir, Opts)
+ end,
+ Sender ! {?MODULE,{stopped,Absname}}.
+
+make_node_dead(Node, NodeInfo, SessionInfo) ->
+ {MetaFile,_} = dict:fetch(Node, NodeInfo),
+ NewDeadNodes = [{Node, MetaFile} | proplists:get_value(dead_nodes, SessionInfo)],
+ [{dead_nodes, NewDeadNodes} | lists:keydelete(dead_nodes, 1, SessionInfo)].
+
+make_node_alive(Node, SessionInfo) ->
+ DeadNodes = proplists:get_value(dead_nodes, SessionInfo),
+ Partials = proplists:get_value(partials, SessionInfo),
+ {value, {_, MetaFile}, Dn2} = lists:keytake(Node, 1, DeadNodes),
+ SessionInfo2 = lists:keyreplace(dead_nodes, 1, SessionInfo, {dead_nodes, Dn2}),
+ {MetaFile, Partials + 1, lists:keyreplace(partials, 1, SessionInfo2, {partials, Partials + 1})}.
+
+try_send_flush_tick(State) ->
+ case proplists:get_value(flush, State) of
+ undefined ->
+ ok;
+ MSec ->
+ erlang:send_after(MSec, self(), flush_timeout)
end.
+get_fetch_dir(undefined,undefined) -> ?upload_dir(?MODULE_STRING) ++ ts();
+get_fetch_dir(undefined,Logname) -> ?upload_dir(Logname) ++ ts();
+get_fetch_dir(Dir,_) -> Dir.
+
+resume_trace(Reporter) ->
+ ?MODULE:run_history(all_silent),
+ Reporter ! trace_resumed.
+
get_nodes() ->
?MODULE ! {get_nodes,self()},
receive {?MODULE,Nodes} -> Nodes end.
@@ -582,19 +821,40 @@ ts() ->
io_lib:format("-~4.4.0w~2.2.0w~2.2.0w-~2.2.0w~2.2.0w~2.2.0w",
[Y,M,D,H,Min,S]).
+copy_partials(_, 0) ->
+ ok;
+copy_partials(Dir, Num) ->
+ PartialDir = ?partial_dir ++ integer_to_list(Num),
+ file:rename(PartialDir, filename:join(Dir,PartialDir)),
+ copy_partials(Dir, Num - 1).
+
+fetch_partial_result(Node,MetaFile,Current) ->
+ DirName = ?partial_dir ++ integer_to_list(Current),
+ case file:list_dir(DirName) of
+ {error, enoent} ->
+ ok;
+ {ok, Files} ->
+ [ file:delete(filename:join(DirName, File)) || File <- Files ],
+ file:del_dir(DirName)
+ end,
+ file:make_dir(DirName),
+ fetch(host(node()), DirName, Node, MetaFile).
+fetch_report(Localhost, Dir, Node, MetaFile) ->
+ fetch(Localhost,Dir,Node,MetaFile),
+ ?MODULE ! {fetch_complete,Node}.
fetch(Localhost,Dir,Node,MetaFile) ->
- case host(Node) of
- Localhost -> % same host, just move the files
- Files = rpc:call(Node,observer_backend,ttb_get_filenames,[MetaFile]),
+ case (host(Node) == Localhost) orelse is_local(MetaFile) of
+ true -> % same host, just move the files
+ Files = get_filenames(Node,MetaFile),
lists:foreach(
- fun(File0) ->
- File = filename:join(Dir,filename:basename(File0)),
- file:rename(File0,File)
- end,
- Files);
- _Otherhost ->
+ fun(File0) ->
+ Dest = filename:join(Dir,filename:basename(File0)),
+ file:rename(File0, Dest)
+ end,
+ Files);
+ false ->
{ok, LSock} = gen_tcp:listen(0, [binary,{packet,2},{active,false}]),
{ok,Port} = inet:port(LSock),
rpc:cast(Node,observer_backend,ttb_fetch,
@@ -603,8 +863,17 @@ fetch(Localhost,Dir,Node,MetaFile) ->
receive_files(Dir,Sock,undefined),
ok = gen_tcp:close(LSock),
ok = gen_tcp:close(Sock)
- end,
- ?MODULE ! {fetch_complete,Node}.
+ end.
+
+is_local({local, _, _}) ->
+ true;
+is_local(_) ->
+ false.
+
+get_filenames(_N, {local,F,_}) ->
+ observer_backend:ttb_get_filenames(F);
+get_filenames(N, F) ->
+ rpc:call(N, observer_backend,ttb_get_filenames,[F]).
receive_files(Dir,Sock,Fd) ->
case gen_tcp:recv(Sock, 0) of
@@ -646,9 +915,16 @@ wait_for_fetch(Nodes) ->
%%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
write_info(Nodes,PI,Traci) ->
- lists:foreach(fun({N,{local,C,_},F}) ->
- MetaFile = F ++ ".ti",
- file:delete(MetaFile),
+ {ok, Cwd} = file:get_cwd(),
+ lists:foreach(fun({N,{local,C,_},F}) ->
+ MetaFile = case F of
+ none ->
+ none;
+ F ->
+ AbsFile = filename:join(Cwd, F) ++ ".ti",
+ file:delete(AbsFile),
+ AbsFile
+ end,
Traci1 = [{node,N},{file,C}|Traci],
{ok,Port} = dbg:get_tracer(N),
?MODULE !
@@ -662,38 +938,35 @@ write_info(Nodes,PI,Traci) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Format binary trace logs
+get_et_handler() ->
+ {fun ttb_et:handler/4, initial}.
+
format(Files) ->
format(Files,[]).
format(Files,Opt) ->
- {Out,Handler} = format_opt(Opt),
+ {Out,Handler,DisableSort} = format_opt(Opt),
ets:new(?MODULE,[named_table]),
- format(Files,Out,Handler).
-format(File,Out,Handler) when is_list(File), is_integer(hd(File)) ->
+ format(Files,Out,Handler, DisableSort).
+format(File,Out,Handler,DisableSort) when is_list(File), is_integer(hd(File)) ->
Files =
case filelib:is_dir(File) of
true -> % will merge all files in the directory
- MetaFiles = filelib:wildcard(filename:join(File,"*.ti")),
- lists:map(fun(M) ->
- Sub = string:left(M,length(M)-3),
- case filelib:is_file(Sub) of
- true -> Sub;
- false -> Sub++".*.wrp"
- end
- end,
- MetaFiles);
+ List = filelib:wildcard(filename:join(File, ?partial_dir++"*")),
+ lists:append(collect_files([File | List]));
false -> % format one file
[File]
end,
- format(Files,Out,Handler);
-format(Files,Out,Handler) when is_list(Files), is_list(hd(Files)) ->
+ format(Files,Out,Handler,DisableSort);
+format(Files,Out,Handler,DisableSort) when is_list(Files), is_list(hd(Files)) ->
StopDbg = case whereis(dbg) of
undefined -> true;
_ -> false
end,
- Details = lists:foldl(fun(File,Acc) -> [prepare(File,Handler)|Acc] end,
+ Details = lists:foldl(fun(File,Acc) -> [prepare(File)|Acc] end,
[],Files),
Fd = get_fd(Out),
- R = do_format(Fd,Details),
+ RealHandler = get_handler(Handler, Files),
+ R = do_format(Fd,Details,DisableSort,RealHandler),
file:close(Fd),
ets:delete(?MODULE),
case StopDbg of
@@ -702,7 +975,30 @@ format(Files,Out,Handler) when is_list(Files), is_list(hd(Files)) ->
end,
R.
-prepare(File,Handler) ->
+collect_files(Dirs) ->
+ lists:map(fun(Dir) ->
+ MetaFiles = filelib:wildcard(filename:join(Dir,"*.ti")),
+ lists:map(fun(M) ->
+ Sub = string:left(M,length(M)-3),
+ case filelib:is_file(Sub) of
+ true -> Sub;
+ false -> Sub++".*.wrp"
+ end
+ end,
+ MetaFiles)
+ end, Dirs).
+
+get_handler(undefined, Files) ->
+ %%We retrieve traci from the first available file
+ {Traci, _} = read_traci(hd(Files)),
+ case dict:find(handler, Traci) of
+ error -> {fun defaulthandler/4, initial};
+ {ok, [Handler]} -> Handler
+ end;
+get_handler(Handler, _) ->
+ Handler.
+
+prepare(File) ->
{Traci,Proci} = read_traci(File),
Node = get_node(Traci),
lists:foreach(fun({Pid,PI}) ->
@@ -714,19 +1010,21 @@ prepare(File,Handler) ->
ets:insert(?MODULE,{Pid,PI,Node})
end,Proci),
FileOrWrap = get_file(File,Traci),
- Handler1 = get_handler(Handler,Traci),
- {FileOrWrap,Traci,Handler1}.
+ {FileOrWrap,Traci}.
-format_opt(Opt) ->
+format_opt(Opt) when is_list(Opt) ->
Out = case lists:keysearch(out,1,Opt) of
{value,{out,O}} -> O;
_ -> standard_io
end,
Handler = case lists:keysearch(handler,1,Opt) of
- {value,{handler,H}} -> H;
- _ -> undefined
+ {value,{handler,H}} -> H;
+ _ -> undefined
end,
- {Out,Handler}.
+ DisableSort = proplists:get_value(disable_sort, Opt, false),
+ {Out,Handler,DisableSort};
+format_opt(Opt) ->
+ format_opt([Opt]).
read_traci(File) ->
@@ -800,75 +1098,61 @@ check_client(Client,File) when is_tuple(Client),element(2,Client)==wrap ->
check_exists(File) ->
case file:read_file_info(File) of
{ok,#file_info{type=regular}} -> File;
- _ ->
+ _ ->
exit({error,no_file})
end.
-
-get_handler(Handler,Traci) ->
- case Handler of
- undefined ->
- case dict:find(handler,Traci) of
- {ok,[H]} -> H;
- error -> undefined
- end;
- _ ->
- Handler
- end.
-do_format(Fd,Details) ->
- Clients = lists:foldl(fun({FileOrWrap,Traci,Handler},Acc) ->
- [start_client(FileOrWrap,Traci,Handler)
- |Acc]
+do_format(Fd,Details,DisableSort,Handler) ->
+ Clients = lists:foldl(fun({FileOrWrap,Traci},Acc) ->
+ [start_client(FileOrWrap,Traci)|Acc]
end,[],Details),
- init_collector(Fd,Clients).
-
-
-start_client(FileOrWrap,Traci,et) ->
- dbg:trace_client(file, FileOrWrap,
- {fun handler/2,
- {dict:to_list(Traci),{{ttb_et,handler},initial}}});
-start_client(FileOrWrap,Traci,undefined) ->
- dbg:trace_client(file, FileOrWrap,
- {fun handler/2,
- {dict:to_list(Traci),{fun defaulthandler/4,initial}}});
-start_client(FileOrWrap,Traci,Handler) ->
- dbg:trace_client(file, FileOrWrap,
- {fun handler/2, {dict:to_list(Traci),Handler}}).
-
-handler(Trace,State) ->
- %% State here is only used for the initial state. The accumulated
- %% State is maintained by collector!!!
- receive
- {get,Collector} -> Collector ! {self(),{Trace,State}};
+ init_collector(Fd,Clients,DisableSort,Handler).
+
+start_client(FileOrWrap,Traci) ->
+ dbg:trace_client(file, FileOrWrap,
+ {fun handler/2, dict:to_list(Traci)}).
+
+handler(Trace,Traci) ->
+ %%We return our own Traci so that it not necesarry to look it up
+ %%This may take time if something huge has been written to it
+ receive
+ {get,Collector} -> Collector ! {self(),{Trace,Traci}};
done -> ok
end,
- State.
+ Traci.
-handler1(Trace,{Fd,{Traci,{Fun,State}}}) when is_function(Fun) ->
- {Traci,{Fun,Fun(Fd,Trace,Traci,State)}};
-handler1(Trace,{Fd,{Traci,{{M,F},State}}}) when is_atom(M), is_atom(F) ->
- {Traci,{{M,F},M:F(Fd,Trace,Traci,State)}}.
+%%Used to handle common state (the same for all clients)
+handler2(Trace,{Fd,Traci,{Fun,State}}) when is_function(Fun) ->
+ {Fun, Fun(Fd, Trace, Traci, State)};
+handler2(Trace,{Fd,Traci,{{M,F},State}}) when is_atom(M), is_atom(F) ->
+ {{M,F}, M:F(Fd, Trace, Traci, State)}.
defaulthandler(Fd,Trace,_Traci,initial) ->
dbg:dhandler(Trace,Fd);
defaulthandler(_Fd,Trace,_Traci,State) ->
dbg:dhandler(Trace,State).
-init_collector(Fd,Clients) ->
+init_collector(Fd,Clients,DisableSort,Handler) ->
Collected = get_first(Clients),
- collector(Fd,sort(Collected)).
+ case DisableSort of
+ true -> collector(Fd,Collected, DisableSort, Handler);
+ false -> collector(Fd,sort(Collected), DisableSort, Handler)
+ end.
-collector(Fd,[{_,{Client,{Trace,State}}}|Rest]) ->
+collector(Fd,[{_,{Client,{Trace,Traci}}} |Rest], DisableSort, CommonState) ->
Trace1 = update_procinfo(Trace),
- State1 = handler1(Trace1,{Fd,State}),
- case get_next(Client,State1) of
- end_of_trace ->
- handler1(end_of_trace,{Fd,State1}),
- collector(Fd,Rest);
- Next -> collector(Fd,sort([Next|Rest]))
+ CommonState2 = handler2(Trace1, {Fd, Traci, CommonState}),
+ case get_next(Client) of
+ end_of_trace ->
+ collector(Fd,Rest,DisableSort, CommonState2);
+ Next -> case DisableSort of
+ false -> collector(Fd,sort([Next|Rest]), DisableSort, CommonState2);
+ true -> collector(Fd,[Next|Rest], DisableSort, CommonState2)
+ end
end;
-collector(_Fd,[]) ->
+collector(Fd,[], _, CommonState) ->
+ handler2(end_of_trace, {Fd, end_of_trace, CommonState}),
ok.
update_procinfo({drop,_N}=Trace) ->
@@ -895,7 +1179,7 @@ update_procinfo(Trace) ->
ProcInfo = get_procinfo(Pid),
setelement(2,Trace,ProcInfo).
-get_procinfo(Pid) when is_pid(Pid) ->
+get_procinfo(Pid) when is_pid(Pid); is_port(Pid) ->
case ets:lookup(?MODULE,Pid) of
[PI] -> PI;
[] -> Pid
@@ -913,21 +1197,21 @@ get_procinfo({Name,Node}) when is_atom(Name) ->
get_first([Client|Clients]) ->
Client ! {get,self()},
- receive
- {Client,{end_of_trace,_}} ->
+ receive
+ {Client,{end_of_trace,_}} ->
get_first(Clients);
- {Client,{Trace,_State}}=Next ->
+ {Client,{Trace,_}}=Next ->
[{timestamp(Trace),Next}|get_first(Clients)]
end;
get_first([]) -> [].
-get_next(Client,State) when is_pid(Client) ->
+get_next(Client) when is_pid(Client) ->
Client ! {get,self()},
- receive
- {Client,{end_of_trace,_}} ->
+ receive
+ {Client,{end_of_trace,_}} ->
end_of_trace;
- {Client,{Trace,_OldState}} ->
- {timestamp(Trace),{Client,{Trace,State}}} % inserting new state!!
+ {Client,{Trace, Traci}} ->
+ {timestamp(Trace),{Client,{Trace,Traci}}}
end.
sort(List) ->
@@ -971,19 +1255,34 @@ display_warning(Item,Warning) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Trace client which reads an IP port and puts data directly to a file.
%%% This is used when tracing remote nodes with no file system.
-ip_to_file(Trace,{file,File}) ->
+ip_to_file({metadata,_,_},{_, only} = State) ->
+ State;
+ip_to_file(Trace, {_, only} = State) ->
+ dbg:dhandler(Trace, standard_io),
+ State;
+ip_to_file(Trace,{{file,File}, ShellOutput}) ->
Fun = dbg:trace_port(file,File), %File can be a filename or a wrap spec
Port = Fun(),
- ip_to_file(Trace,Port);
-ip_to_file({metadata,MetaFile,MetaData},Port) ->
+ case Trace of
+ {metadata, _, _} -> ok;
+ Trace -> show_trace(Trace, ShellOutput)
+ end,
+ ip_to_file(Trace,{Port,ShellOutput});
+ip_to_file({metadata,MetaFile,MetaData},State) ->
{ok,MetaFd} = file:open(MetaFile,[write,raw,append]),
file:write(MetaFd,MetaData),
file:close(MetaFd),
- Port;
-ip_to_file(Trace,Port) ->
+ State;
+ip_to_file(Trace,{Port, ShellOutput}) ->
+ show_trace(Trace, ShellOutput),
B = term_to_binary(Trace),
erlang:port_command(Port,B),
- Port.
+ {Port, ShellOutput}.
+
+show_trace(Trace, true) ->
+ dbg:dhandler(Trace, standard_io);
+show_trace(_, _) ->
+ ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% For debugging
@@ -996,5 +1295,3 @@ dump_ti(<<>>,Acc) ->
dump_ti(B,Acc) ->
{Term,Rest} = get_term(B),
dump_ti(Rest,[Term|Acc]).
-
-
diff --git a/lib/observer/test/Makefile b/lib/observer/test/Makefile
index 6073e6ea00..bf99f07081 100644
--- a/lib/observer/test/Makefile
+++ b/lib/observer/test/Makefile
@@ -22,7 +22,10 @@ MODULES = \
observer_SUITE \
crashdump_viewer_SUITE \
etop_SUITE \
+ ttb_helper \
ttb_SUITE \
+ client \
+ server \
crashdump_helper
ERL_FILES= $(MODULES:%=%.erl)
diff --git a/lib/observer/test/client.erl b/lib/observer/test/client.erl
new file mode 100644
index 0000000000..e756f9d6e8
--- /dev/null
+++ b/lib/observer/test/client.erl
@@ -0,0 +1,28 @@
+-module(client).
+-compile(export_all).
+
+init(Node) ->
+ application:start(runtime_tools),
+ net_kernel:connect_node(Node).
+
+init() ->
+ init(server_node()).
+
+restart() ->
+ init:restart().
+
+server_node() ->
+ {ok,HostName} = inet:gethostname(),
+ list_to_atom("server@" ++ HostName).
+
+get() ->
+ erlang:send({server,server_node()}, {get,self()}),
+ receive Data -> Data
+ after 1000 -> no_reply
+ end.
+
+put(Thing) ->
+ erlang:send({server,server_node()}, {put,self(),Thing}),
+ receive ok -> ok
+ after 1000 -> no_reply
+ end.
diff --git a/lib/observer/test/crashdump_helper.erl b/lib/observer/test/crashdump_helper.erl
index 43b3db738f..d1c65f97e8 100644
--- a/lib/observer/test/crashdump_helper.erl
+++ b/lib/observer/test/crashdump_helper.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The 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,7 +19,7 @@
-module(crashdump_helper).
-export([n1_proc/2,remote_proc/2]).
--compile(r11).
+-compile(r12).
-include("test_server.hrl").
n1_proc(N2,Creator) ->
diff --git a/lib/observer/test/server.erl b/lib/observer/test/server.erl
new file mode 100644
index 0000000000..c1b1fea562
--- /dev/null
+++ b/lib/observer/test/server.erl
@@ -0,0 +1,43 @@
+-module(server).
+-compile(export_all).
+
+start() ->
+ application:start(runtime_tools),
+ Pid = spawn(?MODULE,loop,[[], 0]),
+ register(server,Pid).
+
+stop() ->
+ case lists:member(server, registered()) of
+ true ->
+ server ! stop;
+ false ->
+ ok
+ end.
+
+loop(Data, Num) ->
+ receive
+ {put,From,Ting} -> From ! ok,
+ received(From,Ting),
+ loop([Ting|Data], Num+1);
+ {get,From} -> From ! Data,
+ loop(Data, Num+1);
+ stop -> stopped;
+ clear -> loop([], Num+1);
+ {cnt, From} -> From ! Num,
+ loop(Data, Num)
+ end.
+
+counter() ->
+ server ! {cnt, self()},
+ receive
+ Num ->
+ Num
+ end.
+
+received(From, Thing) ->
+ case Thing of
+ never_send_this_atom ->
+ loop(Thing, 0);
+ _ ->
+ {return, 27, Thing, From}
+ end.
diff --git a/lib/observer/test/ttb_SUITE.erl b/lib/observer/test/ttb_SUITE.erl
index 24b4a22aa9..1fd8b4c892 100644
--- a/lib/observer/test/ttb_SUITE.erl
+++ b/lib/observer/test/ttb_SUITE.erl
@@ -1,7 +1,7 @@
-%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2011. 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
@@ -33,9 +33,17 @@
-include_lib("test_server/include/test_server.hrl").
-define(default_timeout, ?t:minutes(1)).
+-define(OUTPUT, "handler_output").
+-define(FNAME, "temptest").
+-define(DIRNAME, "ddtemp").
init_per_testcase(_Case, Config) ->
ttb:stop(),
+ os:cmd("rm -rf " ++ ?OUTPUT),
+ os:cmd("rm -rf ttb_upload*"),
+ os:cmd("rm -rf " ++ ?DIRNAME),
+ os:cmd("rm -rf *@*"),
+ os:cmd("rm -rf ttb_last_config"),
?line Dog=test_server:timetrap(?default_timeout),
[{watchdog, Dog}|Config].
end_per_testcase(_Case, Config) ->
@@ -49,7 +57,25 @@ all() ->
[file, file_no_pi, file_fetch, wrap, wrap_merge,
wrap_merge_fetch_format, write_config1, write_config2,
write_config3, history, write_trace_info, seq_trace,
- diskless, otp_4967_1, otp_4967_2].
+ diskless, diskless_wrap, otp_4967_1, otp_4967_2,
+ fetch_when_no_option_given, basic_ttb_run_ip_port, basic_ttb_run_file_port,
+ return_fetch_dir_implies_fetch, logfile_name_in_fetch_dir, upload_to_my_logdir,
+ upload_to_my_existing_logdir, fetch_with_options_not_as_list,
+ error_when_formatting_multiple_files_4393, format_on_trace_stop,
+ trace_to_remote_files_on_localhost_with_different_pwd,
+ trace_to_local_files_on_localhost_with_different_pwd,
+ trace_to_remote_files_on_localhost_with_different_pwd_abs,
+ changing_cwd_on_control_node, changing_cwd_on_remote_node,
+ changing_cwd_on_control_node_with_local_trace,
+ one_command_trace_setup, dbg_style_fetch, shell_tracing_init,
+ only_one_state_for_format_handler, only_one_state_with_default_format_handler,
+ only_one_state_with_initial_format_handler, run_trace_with_shortcut1,
+ run_trace_with_shortcut2, run_trace_with_shortcut3, run_trace_with_shortcut4,
+ cant_specify_local_and_flush, trace_sorted_by_default,disable_sorting,
+ trace_resumed_after_node_restart, trace_resumed_after_node_restart_ip,
+ trace_resumed_after_node_restart_wrap,
+ trace_resumed_after_node_restart_wrap_mult
+].
groups() ->
[].
@@ -92,15 +118,15 @@ file(Config) when is_list(Config) ->
?line {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop(),
+ ?line ttb:stop([nofetch]),
?line ?t:stop_node(OtherNode),
?line ok = ttb:format(filename:join(Privdir,atom_to_list(Node)++"-file")),
?line ok = ttb:format(filename:join(Privdir,
atom_to_list(OtherNode)++"-file")),
- ?line [{trace,{S,_,Node},call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace,
- {trace,{_,_,OtherNode},call,{?MODULE,foo,[]}},
+ {trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
ok.
@@ -123,15 +149,15 @@ file_no_pi(Config) when is_list(Config) ->
?line {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop(),
+ ?line ttb:stop([nofetch]),
?line ?t:stop_node(OtherNode),
?line ok = ttb:format(filename:join(Privdir,atom_to_list(Node)++"-file")),
?line ok = ttb:format(filename:join(Privdir,
atom_to_list(OtherNode)++"-file")),
- ?line [{trace,LocalProc,call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,LocalProc,call,{?MODULE,foo,[]}, {_,_,_}},
end_of_trace,
- {trace,RemoteProc,call,{?MODULE,foo,[]}},
+ {trace_ts,RemoteProc,call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
?line true = is_pid(LocalProc),
?line true = is_pid(RemoteProc),
@@ -170,7 +196,7 @@ file_fetch(Config) when is_list(Config) ->
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
?line ?t:capture_start(),
- ?line ttb:stop([fetch]),
+ ?line ttb:stop([return_fetch_dir]),
?line ?t:capture_stop(),
?line [StoreString] = ?t:capture_get(),
?line UploadDir =
@@ -194,9 +220,9 @@ file_fetch(Config) when is_list(Config) ->
?line ok = ttb:format(filename:join(UploadDir,
atom_to_list(OtherNode)++"-file_fetch")),
- ?line [{trace,{S,_,Node},call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace,
- {trace,{_,_,OtherNode},call,{?MODULE,foo,[]}},
+ {trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
?line ok = file:set_cwd(Cwd),
@@ -224,19 +250,19 @@ wrap(Config) when is_list(Config) ->
?line rpc:call(OtherNode,?MODULE,foo,[]),
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop(),
+ ?line ttb:stop([nofetch]),
?line ?t:stop_node(OtherNode),
?line ok = ttb:format(filename:join(Privdir,
atom_to_list(Node)++"-wrap.*.wrp")),
- ?line [{trace,{S,_,Node},call,{?MODULE,foo,[]}},
- {trace,{S,_,Node},call,{?MODULE,foo,[]}},
- {trace,{S,_,Node},call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
?line ok = ttb:format(filename:join(Privdir,
atom_to_list(OtherNode)++"-wrap.*.wrp")),
- ?line [{trace,{_,_,OtherNode},call,{?MODULE,foo,[]}},
- {trace,{_,_,OtherNode},call,{?MODULE,foo,[]}},
- {trace,{_,_,OtherNode},call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
%% Check that merge does not crash even if the timestamp flag is not on.
@@ -244,14 +270,13 @@ wrap(Config) when is_list(Config) ->
[filename:join(Privdir,
atom_to_list(Node)++"-wrap.*.wrp"),
filename:join(Privdir,
- atom_to_list(OtherNode)++"-wrap.*.wrp")]),
- ?line [{trace,{S,_,Node},call,{?MODULE,foo,[]}},
- {trace,{S,_,Node},call,{?MODULE,foo,[]}},
- {trace,{S,_,Node},call,{?MODULE,foo,[]}},
- end_of_trace,
- {trace,{_,_,OtherNode},call,{?MODULE,foo,[]}},
- {trace,{_,_,OtherNode},call,{?MODULE,foo,[]}},
- {trace,{_,_,OtherNode},call,{?MODULE,foo,[]}},
+ atom_to_list(OtherNode)++"-wrap.*.wrp")],[{disable_sort,true}]),
+ ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
ok.
@@ -277,7 +302,7 @@ wrap_merge(Config) when is_list(Config) ->
?line rpc:call(OtherNode,?MODULE,foo,[]),
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop(),
+ ?line ttb:stop([nofetch]),
?line ?t:stop_node(OtherNode),
?line ok = ttb:format(
[filename:join(Privdir,
@@ -289,7 +314,6 @@ wrap_merge(Config) when is_list(Config) ->
{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},_},
{trace_ts,_,call,{?MODULE,foo,[]},_},
{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},_},
- end_of_trace,
{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},_},
end_of_trace] = flush(),
ok.
@@ -330,7 +354,6 @@ wrap_merge_fetch_format(Config) when is_list(Config) ->
{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},_},
{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},_},
{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},_},
- end_of_trace,
{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},_},
end_of_trace] = flush(),
@@ -360,16 +383,15 @@ write_config1(Config) when is_list(Config) ->
?line ok = ttb:run_config(File),
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop(),
+ ?line ttb:stop([nofetch]),
?line ?t:stop_node(OtherNode),
?line ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-write_config1"),
filename:join(Privdir,
atom_to_list(OtherNode)++"-write_config1")]),
- ?line [{trace,{S,_,Node},call,{?MODULE,foo,[]}},
- end_of_trace,
- {trace,Other,call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,Other,call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
case metatest(Other,OtherNode,Privdir,"-write_config1.ti") of
@@ -410,16 +432,15 @@ write_config2(Config) when is_list(Config) ->
?line ok = ttb:run_config(File),
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop(),
+ ?line ttb:stop([nofetch]),
?line ?t:stop_node(OtherNode),
?line ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-write_config2"),
filename:join(Privdir,
atom_to_list(OtherNode)++"-write_config2")]),
- ?line [{trace,{S,_,Node},call,{?MODULE,foo,[]}},
- end_of_trace,
- {trace,Other,call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,Other,call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
case metatest(Other,OtherNode,Privdir,"-write_config2.ti") of
@@ -455,18 +476,18 @@ write_config3(Config) when is_list(Config) ->
?line {ok,[{all,[{matched,_,_},{matched,_,_}]}]} = ttb:p(all,call),
?line {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
?line ok = ttb:write_config(File,[1,2]),
- ?line ttb:stop(),
+ ?line ttb:stop([nofetch]),
?line [_,_] = ttb:list_config(File),
?line ok = ttb:run_config(File),
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop(),
+ ?line ttb:stop([nofetch]),
?line ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-write_config3"),
filename:join(Privdir,
atom_to_list(OtherNode)++"-write_config3")]),
- ?line [] = flush(), %foo is not traced
+ ?line [end_of_trace] = flush(), %foo is not traced
?line ok = ttb:write_config(File,[{ttb,tp,[?MODULE,foo,[]]}],
[append]),
@@ -474,16 +495,15 @@ write_config3(Config) when is_list(Config) ->
?line ok = ttb:run_config(File),
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop(),
+ ?line ttb:stop([nofetch]),
?line ?t:stop_node(OtherNode),
?line ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-write_config3"),
filename:join(Privdir,
atom_to_list(OtherNode)++"-write_config3")]),
- ?line [{trace,{S,_,Node},call,{?MODULE,foo,[]}},
- end_of_trace,
- {trace,Other,call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ {trace_ts,Other,call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
case metatest(Other,OtherNode,Privdir,"-write_config3.ti") of
@@ -531,12 +551,12 @@ history(Config) when is_list(Config) ->
?line ?MODULE:foo(),
?line ok = ttb:run_history([3,4]),
?line ?MODULE:foo(),
- ?line ttb:stop(),
+ ?line ttb:stop([nofetch]),
?line ?t:stop_node(OtherNode),
?line ok = ttb:format(
[filename:join(Privdir,atom_to_list(Node)++"-history"),
filename:join(Privdir,atom_to_list(OtherNode)++"-history")]),
- ?line [{trace,{S,_,Node},call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
ok.
@@ -561,17 +581,16 @@ write_trace_info(Config) when is_list(Config) ->
?line ok = ttb:write_trace_info(mytraceinfo,fun() -> node() end),
?line ?MODULE:foo(),
?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop(),
+ ?line ttb:stop([nofetch]),
?line ?t:stop_node(OtherNode),
?line ok = ttb:format(
[filename:join(Privdir,atom_to_list(Node)++"-write_trace_info"),
filename:join(Privdir,
atom_to_list(OtherNode)++"-write_trace_info")],
[{handler,{fun otherhandler/4,S}}]),
- ?line [{{trace,{S,_,Node},call,{?MODULE,foo,[]}},[Node]},
- {end_of_trace,[Node]},
- {{trace,{_,_,OtherNode},call,{?MODULE,foo,[]}},[OtherNode]},
- {end_of_trace,[OtherNode]}] = flush(),
+ ?line [{{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},[Node]},
+ {{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},[OtherNode]},
+ end_of_trace] = flush(),
ok.
@@ -593,10 +612,10 @@ seq_trace(Config) when is_list(Config) ->
?line Start = spawn(fun() -> seq() end),
?line timer:sleep(300),
- ?line ttb:stop(),
+ ?line ttb:stop([nofetch]),
?line ok = ttb:format(
[filename:join(Privdir,atom_to_list(Node)++"-seq_trace")]),
- ?line [{trace,StartProc,call,{?MODULE,seq,[]}},
+ ?line [{trace_ts,StartProc,call,{?MODULE,seq,[]},{_,_,_}},
{seq_trace,0,{send,{0,1},StartProc,P1Proc,{Start,P2}}},
{seq_trace,0,{send,{1,2},P1Proc,P2Proc,{P1,Start}}},
{seq_trace,0,{send,{2,3},P2Proc,StartProc,{P2,P1}}},
@@ -660,15 +679,41 @@ diskless(Config) when is_list(Config) ->
?line rpc:call(RemoteNode,?MODULE,foo,[]),
?line timer:sleep(500), % needed for the IP port to flush
- ?line ttb:stop(),
+ ?line ttb:stop([nofetch]),
?line ?t:stop_node(RemoteNode),
?line ok = ttb:format(filename:join(Privdir,
atom_to_list(RemoteNode)++"-diskless")),
- ?line [{trace,{_,_,RemoteNode},call,{?MODULE,foo,[]}},
+ ?line [{trace_ts,{_,_,RemoteNode},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
ok.
+diskless_wrap(suite) ->
+ [];
+diskless_wrap(doc) ->
+ ["Start tracing on diskless remote node, save to local wrapped file"];
+diskless_wrap(Config) when is_list(Config) ->
+ ?line {ok,RemoteNode} = ?t:start_node(node2,slave,[]),
+ ?line c:nl(?MODULE),
+ ?line S = self(),
+ ?line Privdir=?config(priv_dir, Config),
+ ?line File = filename:join(Privdir,"diskless"),
+ ?line {ok,[RemoteNode]} =
+ ttb:tracer([RemoteNode],[{file, {local, {wrap,File,200,3}}},
+ {handler,{fun myhandler/4, S}}]),
+ ?line {ok,[{all,[{matched,RemoteNode,_}]}]} = ttb:p(all,call),
+ ?line {ok,[{matched,RemoteNode,1}]} = ttb:tp(?MODULE,foo,[]),
+
+ ?line rpc:call(RemoteNode,?MODULE,foo,[]),
+ ?line timer:sleep(500), % needed for the IP port to flush
+ ?line ttb:stop([nofetch]),
+ ?line ?t:stop_node(RemoteNode),
+ ?line ok = ttb:format(filename:join(Privdir,
+ atom_to_list(RemoteNode)++"-diskless.*.wrp")),
+
+ ?line [{trace_ts,{_,_,RemoteNode},call,{?MODULE,foo,[]},{_,_,_}},
+ end_of_trace] = flush(),
+ ok.
otp_4967_1(suite) ->
[];
@@ -715,7 +760,7 @@ otp_4967_2(Config) when is_list(Config) ->
io:format("11: ~p",[now()]),
?line true = lists:member(heihopp,Msgs), % the heihopp message itself
io:format("13: ~p",[now()]),
- ?line {value,{trace,_,send,heihopp,{_,otp_4967,Node}}} =
+ ?line {value,{trace_ts,_,send,heihopp,{_,otp_4967,Node},{_,_,_}}} =
lists:keysearch(heihopp,4,Msgs), % trace trace of the heihopp message
io:format("14: ~p",[now()]),
?line end_of_trace = lists:last(Msgs), % end of the trace
@@ -728,6 +773,30 @@ myhandler(_Fd,Trace,_,Relay) ->
Relay ! Trace,
Relay.
+simple_call_handler() ->
+ {fun(A, {trace_ts, _, call, _, _} ,_,_) -> io:format(A, "ok.~n", []);
+ (_, end_of_trace, _, _) -> ok end, []}.
+
+marking_call_handler() ->
+ {fun(_, _, _, initial) -> file:write_file("HANDLER_OK", []);
+ (_,_,_,_) -> ok end, initial}.
+
+counter_call_handler() ->
+ {fun(_, {trace_ts, _, call, _, _} ,_,State) -> State + 1;
+ (A, end_of_trace, _, State) -> io:format(A,"~p.~n", [State]) end, 0}.
+
+ret_caller_call_handler() ->
+ {fun(A, {trace_ts, _, call, _, _, _} ,_,_) -> io:format(A, "ok.~n", []);
+ (A, {trace_ts, _, return_from, _, _, _}, _, _) -> io:format(A, "ok.~n", []);
+ (_, _, _, _) -> ok end, []}.
+
+node_call_handler() ->
+ {fun(A, {trace_ts, {_,_,Node}, call, _, _} ,_,_) -> io:format(A, "~p.~n", [Node]);
+ (_, end_of_trace, _, _) -> ok end, []}.
+
+otherhandler(_Fd,_,end_of_trace,Relay) ->
+ Relay ! end_of_trace,
+ Relay;
otherhandler(_Fd,Trace,TI,Relay) ->
{value,{mytraceinfo,I}} = lists:keysearch(mytraceinfo,1,TI),
Relay ! {Trace,I},
@@ -794,3 +863,568 @@ check_gone(Dir,File) ->
false ->
ok
end.
+
+start_client_and_server() ->
+ ?line {ok,ClientNode} = ?t:start_node(client,slave,[]),
+ ?line ok = ttb_helper:c(code, add_paths, [code:get_path()]),
+ ?line {ok,ServerNode} = ?t:start_node(server,slave,[]),
+ ?line ok = ttb_helper:s(code, add_paths, [code:get_path()]),
+ ?line ttb_helper:clear(),
+ {ServerNode, ClientNode}.
+
+begin_trace(ServerNode, ClientNode, Dest) ->
+ ?line {ok, _} =
+ ttb:tracer([ServerNode,ClientNode],[{file, Dest}]),
+ ?line ttb:p(all, call),
+ ?line ttb:tp(server, received, []),
+ ?line ttb:tp(client, put, []),
+ ?line ttb:tp(client, get, []).
+
+begin_trace_local(ServerNode, ClientNode, Dest) ->
+ ?line {ok, _} =
+ ttb:tracer([ServerNode,ClientNode],[{file, Dest}]),
+ ?line ttb:p(all, call),
+ ?line ttb:tpl(server, received, []),
+ ?line ttb:tpl(client, put, []),
+ ?line ttb:tpl(client, get, []).
+
+check_size(N, Dest, Output, ServerNode, ClientNode) ->
+ ?line begin_trace(ServerNode, ClientNode, Dest),
+ ?line case Dest of
+ {local, _} ->
+ ?line ttb_helper:msgs_ip(N);
+ _ ->
+ ?line ttb_helper:msgs(N)
+ end,
+ ?line {_, D} = ttb:stop([fetch, return_fetch_dir]),
+ ?line ttb:format(D, [{out, Output}, {handler, simple_call_handler()}]),
+ ?line {ok, Ret} = file:consult(Output),
+ ?line true = (N + 1 == length(Ret)).
+
+fetch_when_no_option_given(suite) ->
+ [];
+fetch_when_no_option_given(doc) ->
+ ["Fetch when no option given"];
+fetch_when_no_option_given(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line {ok, Privdir} = file:get_cwd(),
+ ?line [] = filelib:wildcard(filename:join(Privdir,"ttb_upload_temptest*")),
+ begin_trace(ServerNode, ClientNode, ?FNAME),
+ ?line ttb_helper:msgs(4),
+ ?line stopped = ttb:stop(),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode),
+ ?line [_] = filelib:wildcard(filename:join(Privdir,"ttb_upload_temptest*")).
+
+basic_ttb_run_ip_port(suite) ->
+ [];
+basic_ttb_run_ip_port(doc) ->
+ ["Basic ttb run ip port"];
+basic_ttb_run_ip_port(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line check_size(1, {local, ?FNAME}, ?OUTPUT, ServerNode, ClientNode),
+ ?line check_size(2, {local, ?FNAME}, ?OUTPUT, ServerNode, ClientNode),
+ ?line check_size(10, {local, ?FNAME}, ?OUTPUT, ServerNode, ClientNode),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode).
+
+basic_ttb_run_file_port(suite) ->
+ [];
+basic_ttb_run_file_port(doc) ->
+ ["Basic ttb run file port"];
+basic_ttb_run_file_port(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line check_size(1, ?FNAME, ?OUTPUT, ServerNode, ClientNode),
+ ?line check_size(2, ?FNAME, ?OUTPUT, ServerNode, ClientNode),
+ ?line check_size(10, ?FNAME, ?OUTPUT, ServerNode, ClientNode),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode).
+
+return_fetch_dir_implies_fetch(suite) ->
+ [];
+return_fetch_dir_implies_fetch(doc) ->
+ ["Return_fetch_dir implies fetch"];
+return_fetch_dir_implies_fetch(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace(ServerNode, ClientNode, ?FNAME),
+ ?line ttb_helper:msgs(2),
+ ?line {_,_} = ttb:stop([return_fetch_dir]),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode).
+
+logfile_name_in_fetch_dir(suite) ->
+ [];
+logfile_name_in_fetch_dir(doc) ->
+ ["Logfile name in fetch dir"];
+logfile_name_in_fetch_dir(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace(ServerNode, ClientNode, {local, ?FNAME}),
+ ?line {_,Dir} = ttb:stop([return_fetch_dir]),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode),
+ ?line P1 = lists:nth(3, string:tokens(filename:basename(Dir), "_")),
+ ?line P2 = hd(string:tokens(P1, "-")),
+ ?line _File = P2.
+
+upload_to_my_logdir(suite) ->
+ [];
+upload_to_my_logdir(doc) ->
+ ["Upload to my logdir"];
+upload_to_my_logdir(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line {ok, _} =
+ ttb:tracer([ServerNode,ClientNode],[{file, ?FNAME}]),
+ ?line {stopped,_} = ttb:stop([return_fetch_dir, {fetch_dir, ?DIRNAME}]),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode),
+ ?line true = filelib:is_file(?DIRNAME),
+ ?line [] = filelib:wildcard("ttb_upload_"++?FNAME).
+
+upload_to_my_existing_logdir(suite) ->
+ [];
+upload_to_my_existing_logdir(doc) ->
+ ["Upload to my existing logdir"];
+upload_to_my_existing_logdir(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line ok = file:make_dir(?DIRNAME),
+ ?line {ok, _} =
+ ttb:tracer([ServerNode,ClientNode],[{file, ?FNAME}]),
+ ?line {error,_,_} = (catch ttb:stop([return_fetch_dir, {fetch_dir, ?DIRNAME}])),
+ ?line {stopped,_} = ttb:stop(return_fetch_dir),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode).
+
+fetch_with_options_not_as_list(suite) ->
+ [];
+fetch_with_options_not_as_list(doc) ->
+ ["Fetch with options not as list"];
+fetch_with_options_not_as_list(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line {ok, _} =
+ ttb:tracer([ServerNode,ClientNode],[{file, ?FNAME}]),
+ ?line {stopped, D} = ttb:stop(return_fetch_dir),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode),
+ ?line false = filelib:is_file(?OUTPUT),
+ ?line ttb:format(D, {out, ?OUTPUT}),
+ ?line true = filelib:is_file(?OUTPUT).
+
+error_when_formatting_multiple_files_4393(suite) ->
+ [];
+error_when_formatting_multiple_files_4393(doc) ->
+ ["Error when formatting multiple files"];
+error_when_formatting_multiple_files_4393(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace(ServerNode, ClientNode, ?FNAME),
+ ?line ttb_helper:msgs(2),
+ ?line {_, Dir} = ttb:stop(return_fetch_dir),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode),
+ ?line Files = [filename:join(Dir, atom_to_list(ttb_helper:get_node(server)) ++ "-" ++ ?FNAME),
+ filename:join(Dir, atom_to_list(ttb_helper:get_node(client)) ++ "-" ++ ?FNAME)],
+ ?line ok = ttb:format(Files).
+
+format_on_trace_stop(suite) ->
+ [];
+format_on_trace_stop(doc) ->
+ ["Format on trace stop"];
+format_on_trace_stop(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace(ServerNode, ClientNode, {local, ?FNAME}),
+ ?line ttb_helper:msgs_ip(2),
+ ?line file:delete("HANDLER_OK"),
+ ?line {_,_} = ttb:stop([fetch, return_fetch_dir, {format, {handler, marking_call_handler()}}]),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode),
+ ?line true = filelib:is_file("HANDLER_OK"),
+ ?line ok = file:delete("HANDLER_OK").
+
+%% The following three tests are for the issue "fixes fetch fail when nodes on the same host
+%% have different cwd"
+trace_to_remote_files_on_localhost_with_different_pwd(suite) ->
+ [];
+trace_to_remote_files_on_localhost_with_different_pwd(doc) ->
+ ["Trace to remote files on localhost with different pwd"];
+trace_to_remote_files_on_localhost_with_different_pwd(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line ok = file:set_cwd(".."),
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line check_size(2, ?FNAME, ?OUTPUT, ServerNode, ClientNode),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode),
+ ?line ok = file:set_cwd(OldDir).
+
+trace_to_local_files_on_localhost_with_different_pwd(suite) ->
+ [];
+trace_to_local_files_on_localhost_with_different_pwd(doc) ->
+ ["Trace to local files on localhost with different pwd"];
+trace_to_local_files_on_localhost_with_different_pwd(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line ok = file:set_cwd(".."),
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line check_size(2, {local, ?FNAME}, ?OUTPUT, ServerNode, ClientNode),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode),
+ ?line ok = file:set_cwd(OldDir).
+
+trace_to_remote_files_on_localhost_with_different_pwd_abs(suite) ->
+ [];
+trace_to_remote_files_on_localhost_with_different_pwd_abs(doc) ->
+ ["Trace to remote files on localhost with different pwd abs"];
+trace_to_remote_files_on_localhost_with_different_pwd_abs(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line ok = file:set_cwd(".."),
+ ?line {ok, Path} = file:get_cwd(),
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line File = filename:join(Path, ?FNAME),
+ ?line check_size(2, File, ?OUTPUT, ServerNode, ClientNode),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode),
+ ?line ok = file:set_cwd(OldDir).
+
+%% Trace is not affected by changes of cwd on control node or remote nodes during tracing
+%% (three tests)
+changing_cwd_on_control_node(suite) ->
+ [];
+changing_cwd_on_control_node(doc) ->
+ ["Changing cwd on control node during tracing is safe"];
+changing_cwd_on_control_node(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace(ServerNode, ClientNode, ?FNAME),
+ ?line NumMsgs = 3,
+ ?line ttb_helper:msgs(NumMsgs),
+ ?line ok = file:set_cwd(".."),
+ ?line ttb_helper:msgs(NumMsgs),
+ ?line {_, D} = ttb:stop([fetch, return_fetch_dir]),
+ ?line ttb:format(D, [{out, ?OUTPUT}, {handler, simple_call_handler()}]),
+ ?line {ok, Ret} = file:consult(?OUTPUT),
+ ?line true = (2*(NumMsgs + 1) == length(Ret)),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode),
+ ?line ok = file:set_cwd(OldDir).
+
+changing_cwd_on_control_node_with_local_trace(suite) ->
+ [];
+changing_cwd_on_control_node_with_local_trace(doc) ->
+ ["Changing cwd on control node during local tracing is safe"];
+changing_cwd_on_control_node_with_local_trace(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace(ServerNode, ClientNode, {local, ?FNAME}),
+ ?line NumMsgs = 3,
+ ?line ttb_helper:msgs_ip(NumMsgs),
+ ?line ok = file:set_cwd(".."),
+ ?line ttb_helper:msgs_ip(NumMsgs),
+ ?line {_, D} = ttb:stop([fetch, return_fetch_dir]),
+ ?line ttb:format(D, [{out, ?OUTPUT}, {handler, simple_call_handler()}]),
+ ?line {ok, Ret} = file:consult(?OUTPUT),
+ ?line true = (2*(NumMsgs + 1) == length(Ret)),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode),
+ ?line ok = file:set_cwd(OldDir).
+
+changing_cwd_on_remote_node(suite) ->
+ [];
+changing_cwd_on_remote_node(doc) ->
+ ["Changing cwd on remote node during tracing is safe"];
+changing_cwd_on_remote_node(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace(ServerNode, ClientNode, ?FNAME),
+ ?line NumMsgs = 2,
+ ?line ttb_helper:msgs(NumMsgs),
+ ?line ok = rpc:call(ClientNode, file, set_cwd, [".."]),
+ ?line ttb_helper:msgs(NumMsgs),
+ ?line {_, D} = ttb:stop([fetch, return_fetch_dir]),
+ ?line ttb:format(D, [{out, ?OUTPUT}, {handler, simple_call_handler()}]),
+ ?line {ok, Ret} = file:consult(?OUTPUT),
+ ?line true = (2*(NumMsgs + 1) == length(Ret)),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode).
+
+one_command_trace_setup(suite) ->
+ [];
+one_command_trace_setup(doc) ->
+ ["One command trace setup"];
+one_command_trace_setup(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line ttb:start_trace([ttb_helper:get_node(client), ttb_helper:get_node(server)],
+ [{server, received, '_', []},
+ {client, put, 1, []},
+ {client, get, '_', []}],
+ {all, call},
+ [{file, ?FNAME}]),
+ ?line ttb_helper:msgs(2),
+ ?line {_, D} = ttb:stop(return_fetch_dir),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode),
+ ?line ttb:format(D, [{out, ?OUTPUT}, {handler, simple_call_handler()}]),
+ ?line {ok, Ret} = file:consult(?OUTPUT),
+ ?line 5 = length(Ret).
+
+dbg_style_fetch(suite) ->
+ [];
+dbg_style_fetch(doc) ->
+ ["Dbg style fetch"];
+dbg_style_fetch(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line DirSize = length(element(2, file:list_dir("."))),
+ ?line ttb:start_trace([ttb_helper:get_node(client), ttb_helper:get_node(server)],
+ [{server, received, '_', []},
+ {client, put, 1, []},
+ {client, get, '_', []}],
+ {all, call},
+ [{shell, only}]),
+ ?line DirSize = length(element(2, file:list_dir("."))),
+ ?line ttb_helper:msgs(2),
+ ?line DirSize = length(element(2, file:list_dir("."))),
+ ?line stopped, ttb:stop(format),
+ %%+1 -> ttb_last_trace
+ ?line true = (DirSize + 1 == length(element(2, file:list_dir(".")))),
+ ?line {ok,[{all, [{matched,_,_}, {matched,_,_}]}]} =
+ ttb:start_trace([ttb_helper:get_node(client), ttb_helper:get_node(server)],
+ [{server, received, '_', []},
+ {client, put, 1, []},
+ {client, get, '_', []}],
+ {all, call},
+ [{shell, only}]),
+ ?line ttb:stop(),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode).
+
+shell_tracing_init(suite) ->
+ [];
+shell_tracing_init(doc) ->
+ ["Shell tracing init"];
+shell_tracing_init(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line ttb:tracer([ttb_helper:get_node(client), ttb_helper:get_node(server)], shell),
+ ?line ttb:stop(),
+ ?line ttb:tracer([ttb_helper:get_node(client), ttb_helper:get_node(server)],
+ [{file, {local, ?FNAME}}, shell]),
+ ?line ttb:stop(),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode),
+ ?line local_client_required_on_shell_tracing = try ttb:tracer([ttb_helper:get_node(client), ttb_helper:get_node(server)],
+ [{file, ?FNAME}, shell])
+ catch
+ exit:local_client_required_on_shell_tracing ->
+ local_client_required_on_shell_tracing
+ end.
+
+only_one_state_for_format_handler(suite) ->
+ [];
+only_one_state_for_format_handler(doc) ->
+ ["Only one state for format handler"];
+only_one_state_for_format_handler(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace_local(ServerNode, ClientNode, ?FNAME),
+ ?line ttb_helper:msgs(2),
+ ?line {_, D} = ttb:stop([return_fetch_dir]),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode),
+ ?line ttb:format(D, [{out, ?OUTPUT}, {handler, counter_call_handler()}]),
+ ?line {ok, Ret} = file:consult(?OUTPUT),
+ ?line [5] = Ret.
+
+only_one_state_with_default_format_handler(suite) ->
+ [];
+only_one_state_with_default_format_handler(doc) ->
+ ["Only one state with default format handler"];
+only_one_state_with_default_format_handler(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace_local(ServerNode, ClientNode, ?FNAME),
+ ?line ttb_helper:msgs(2),
+ ?line {_, D} = ttb:stop([return_fetch_dir]),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode),
+ ?line ttb:format(D, [{out, ?OUTPUT}]),
+ ?line true = filelib:is_file(?OUTPUT).
+
+only_one_state_with_initial_format_handler(suite) ->
+ [];
+only_one_state_with_initial_format_handler(doc) ->
+ ["Only one state with initial format handler"];
+only_one_state_with_initial_format_handler(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line {ok, _} =
+ ttb:tracer([ServerNode,ClientNode],[{file, ?FNAME}, {handler, counter_call_handler()}]),
+ ?line ttb:p(all, call),
+ ?line ttb:tpl(server, received, []),
+ ?line ttb:tpl(client, put, []),
+ ?line ttb:tpl(client, get, []),
+ ?line ttb_helper:msgs(2),
+ ?line {_, D} = ttb:stop([return_fetch_dir]),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode),
+ ?line ttb:format(D, [{out, ?OUTPUT}]),
+ ?line {ok, Ret} = file:consult(?OUTPUT),
+ ?line [5] = Ret.
+
+run_trace_with_shortcut(Shortcut, Ret, F) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line {ok, _} =
+ ttb:tracer([ServerNode,ClientNode],[{file, ?FNAME}]),
+ ?line ttb:p(all, call),
+ ?line ttb:F(client, put, Shortcut),
+ ?line ttb_helper:msgs(2),
+ ?line {_, D} = ttb:stop([return_fetch_dir]),
+ ?line ttb:format(D, [{out, ?OUTPUT}, {handler, ret_caller_call_handler()}]),
+ ?line {ok, Ret} =file:consult(?OUTPUT),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode).
+
+fun_for(return) ->
+ {codestr, "fun(_) -> return_trace() end"};
+fun_for(msg_false) ->
+ {codestr, "fun(_) -> message(false) end"}.
+
+run_trace_with_shortcut1(suite) ->
+ [];
+run_trace_with_shortcut1(doc) ->
+ ["Run trace with shortcut 1"];
+run_trace_with_shortcut1(Config) when is_list(Config) ->
+ ?line run_trace_with_shortcut(caller, [ok,ok], tp),
+ ?line run_trace_with_shortcut(caller, [ok,ok], tpl).
+
+run_trace_with_shortcut2(suite) ->
+ [];
+run_trace_with_shortcut2(doc) ->
+ ["Run trace with shortcut 2"];
+run_trace_with_shortcut2(Config) when is_list(Config) ->
+ ?line run_trace_with_shortcut(return, [ok,ok], tp),
+ ?line run_trace_with_shortcut(return, [ok,ok], tpl).
+
+run_trace_with_shortcut3(suite) ->
+ [];
+run_trace_with_shortcut3(doc) ->
+ ["Run trace with shortcut 3"];
+run_trace_with_shortcut3(Config) when is_list(Config) ->
+ ?line run_trace_with_shortcut(fun_for(return), [ok,ok], tp),
+ ?line run_trace_with_shortcut(fun_for(return), [ok,ok], tpl).
+
+run_trace_with_shortcut4(suite) ->
+ [];
+run_trace_with_shortcut4(doc) ->
+ ["Run trace with shortcut 4"];
+run_trace_with_shortcut4(Config) when is_list(Config) ->
+ ?line run_trace_with_shortcut(fun_for(msg_false), [], tp),
+ ?line run_trace_with_shortcut(fun_for(msg_false), [], tpl).
+
+cant_specify_local_and_flush(suite) ->
+ [];
+cant_specify_local_and_flush(doc) ->
+ ["Can't specify local and flush"];
+cant_specify_local_and_flush(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line flush_unsupported_with_ip_trace_port = try ttb:tracer([ServerNode, ClientNode], [{flush, 1000}, {file, {local, ?FNAME}}])
+ catch
+ exit:flush_unsupported_with_ip_trace_port ->
+ flush_unsupported_with_ip_trace_port
+ end,
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode).
+
+trace_sorted_by_default(suite) ->
+ [];
+trace_sorted_by_default(doc) ->
+ ["Trace sorted by default"];
+trace_sorted_by_default(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace_local(ServerNode, ClientNode, ?FILE),
+ ?line ttb_helper:msgs(2),
+ ?line {_, D} = ttb:stop([return_fetch_dir]),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode),
+ ?line ttb:format(D, [{out, ?OUTPUT}, {handler, node_call_handler()}, {disable_sort, false}]),
+ {ok, Ret} = file:consult(?OUTPUT),
+ ?line [ClientNode,ServerNode,ClientNode,ServerNode,ServerNode] = Ret.
+
+disable_sorting(suite) ->
+ [];
+disable_sorting(doc) ->
+ ["Disable sorting"];
+disable_sorting(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace_local(ServerNode, ClientNode, ?FILE),
+ ?line ttb_helper:msgs(2),
+ ?line {_, D} = ttb:stop([return_fetch_dir]),
+ ?line ?t:stop_node(ServerNode),
+ ?line ?t:stop_node(ClientNode),
+ ?line ttb:format(D, [{out, ?OUTPUT}, {handler, node_call_handler()}, {disable_sort, true}]),
+ {ok, Ret} = file:consult(?OUTPUT),
+ ?line [ClientNode,ClientNode,ServerNode,ServerNode,ServerNode] = Ret.
+
+%% -----------------------------------------------------------------------------
+%% tests for autoresume of tracing
+%% -----------------------------------------------------------------------------
+
+trace_resumed_after_node_restart(suite) ->
+ [];
+trace_resumed_after_node_restart(doc) ->
+ ["Test trace resumed after node restart, trace to files on remote node."];
+trace_resumed_after_node_restart(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace_with_resume(ServerNode, ClientNode, ?FNAME),
+ ?line logic(2,6,file).
+
+trace_resumed_after_node_restart_ip(suite) ->
+ [];
+trace_resumed_after_node_restart_ip(doc) ->
+ ["Test trace resumed after node restart, trace via tcp/ip to local node."];
+trace_resumed_after_node_restart_ip(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace_with_resume(ServerNode, ClientNode, {local, ?FNAME}),
+ ?line logic(2,6,local).
+
+trace_resumed_after_node_restart_wrap(suite) ->
+ [];
+trace_resumed_after_node_restart_wrap(doc) ->
+ ["Test trace resumed after node restart, wrap option."];
+trace_resumed_after_node_restart_wrap(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace_with_resume(ServerNode, ClientNode, {wrap, ?FNAME, 10, 4}),
+ ?line logic(1,4,file).
+
+trace_resumed_after_node_restart_wrap_mult(suite) ->
+ [];
+trace_resumed_after_node_restart_wrap_mult(doc) ->
+ ["Test trace resumed after node restart, wrap option, multiple files."];
+trace_resumed_after_node_restart_wrap_mult(Config) when is_list(Config) ->
+ ?line {ServerNode, ClientNode} = start_client_and_server(),
+ ?line begin_trace_with_resume(ServerNode, ClientNode, {wrap, ?FNAME, 10, 4}),
+ ?line logic(20,8,file).
+
+logic(N, M, TracingType) ->
+ helper_msgs(N, TracingType),
+ ?t:stop_node(ttb_helper:get_node(client)),
+ timer:sleep(2500),
+ ?line {ok,ClientNode} = ?t:start_node(client,slave,[]),
+ ?line ok = ttb_helper:c(code, add_paths, [code:get_path()]),
+ ?line ttb_helper:c(client, init, []),
+ ?line helper_msgs(N, TracingType),
+ ?line {_, D} = ttb:stop([return_fetch_dir]),
+ ?line ?t:stop_node(ttb_helper:get_node(server)),
+ ?line ?t:stop_node(ClientNode),
+ ?line ttb:format(D, [{out, ?OUTPUT}, {handler, ret_caller_call_handler2()}]),
+ ?line {ok, Ret} = file:consult(?OUTPUT),
+ ?line M = length(Ret).
+
+begin_trace_with_resume(ServerNode, ClientNode, Dest) ->
+ ?line {ok, _} = ttb:tracer([ServerNode,ClientNode], [{file, Dest}, resume]),
+ ?line ttb:p(all, [call, timestamp]),
+ ?line ttb:tp(server, received, []),
+ ?line ttb:tp(client, put, []),
+ ?line ttb:tp(client, get, []).
+
+ret_caller_call_handler2() ->
+ {fun(A, {trace_ts, _, call, _, _} ,_,_) -> io:format(A, "ok.~n", []);
+ (_, _, _, _) -> ok end, []}.
+
+helper_msgs(N, TracingType) ->
+ case TracingType of
+ local ->
+ ttb_helper:msgs_ip(N);
+ _ ->
+ ttb_helper:msgs(N)
+ end.
diff --git a/lib/observer/test/ttb_helper.erl b/lib/observer/test/ttb_helper.erl
new file mode 100644
index 0000000000..19fdc0e159
--- /dev/null
+++ b/lib/observer/test/ttb_helper.erl
@@ -0,0 +1,157 @@
+-module(ttb_helper). %%Nodes control
+-compile(export_all).
+
+%%API
+%%get() -> client:get()
+%%put(X) -> client:put(X)
+%%msgs(N) -> N times client:put(test_msg)
+%%clear() -> restart server
+%%ensure_running() / stop() -> start/stop nodes
+%%get_node(atom) -> return atom@hostname
+
+-define(NODE_CMD(Name),
+ "erl -sname " ++ atom_to_list(Name) ++
+ " -pa .. -pa . -detached -run ttb_helper send_ok").
+-define(REG_NAME, nc_testing).
+
+new_fun() ->
+ fun(_, end_of_trace, _, Dict) -> io:format("~p~n", [dict:to_list(Dict)]);
+ (_, T, _, Dict) -> case element(2, T) of
+ {Pid, _, _} ->
+ dict:update_counter(Pid, 1, Dict);
+ Pid ->
+ dict:update_counter(Pid, 1, Dict)
+ end
+ end.
+
+new_fun_2() ->
+ fun(_, end_of_trace, _, Dict) -> io:format("~p~n", [dict:to_list(Dict)]);
+ (_, T, _, Dict) -> case element(2, T) of
+ {_, Name, _} when is_atom(Name)->
+ dict:update_counter(Name, 1, Dict);
+ Pid ->
+ dict:update_counter(Pid, 1, Dict)
+ end
+
+ end.
+
+
+ensure_running() ->
+ try_start_node(server),
+ try_start_node(client),
+ clear().
+
+try_start_node(Node) ->
+ global:unregister_name(?REG_NAME),
+ global:register_name(?REG_NAME, self()),
+ global:sync(),
+ N = get_node(Node),
+ case net_adm:ping(N) of
+ pong ->
+ io:format("Node ~p already running~n", [N]);
+ _ ->
+ io:format("Starting node ~p... ~p ", [Node, os:cmd(?NODE_CMD(Node))]),
+ recv()
+ end.
+
+clear() ->
+ s(server, stop, []),
+ init().
+
+stop() ->
+ s(init, stop, []),
+ c(init, stop, []).
+
+msgs(N) ->
+ [c(client, put, [test_msg]) || _ <- lists:seq(1, N)],
+ s(server, received, [a,b]),
+ [dbg:flush_trace_port(Node) || Node <- [get_node(client), get_node(server)]].
+
+msgs_ip(N) ->
+ [c(client, put, [test_msg]) || _ <- lists:seq(1, N)],
+ s(server, received, [a,b]),
+ timer:sleep(100). %% allow trace messages to arrive over tcp/ip
+
+run() ->
+ ttb({local, "A"}),
+ msgs(2),
+ c(erlang, whereis, [ttbt]).
+
+get() -> c(client, get, []).
+put(Thing) -> c(client, put, [Thing]).
+
+get_node(Node) ->
+ {ok, Host} = inet:gethostname(),
+ list_to_atom(atom_to_list(Node) ++ "@" ++ Host).
+
+trace_setup() ->
+ ttb:p(all, call),
+ ttb:tp(server, received, []),
+ ttb:tp(client, put, []),
+ ttb:tp(client, get, []).
+
+ttb() -> ttb("A").
+ttb(File) ->
+ ttb:tracer([get_node(client), get_node(server)], [{file, File}, resume]),
+ ttb:p(all, [call, timestamp]),
+ ttb:tp(client, put, []),
+ ttb:tp(client, get, []),
+ ttb:tp(server, received, []).
+
+tc() ->
+ TC = example_config_gen:create_trace_case("dummy comment"),
+ Patterns = example_config_gen:create_pattern(client, put, 1, return),
+ Flags = example_config_gen:create_flags(all, call),
+ Merge = example_config_gen:create_merge_conf(show_handler(), "dummy merge comment"),
+ Merge2 = example_config_gen:create_merge_conf(undefined, "dummy merge comment"),
+ TC2 = example_config_gen:add_pattern(Patterns, TC),
+ TC3 = example_config_gen:add_flags(Flags, TC2),
+ TC4 = example_config_gen:add_merge_conf(Merge, TC3),
+ TC5 = example_config_gen:add_merge_conf(Merge2, TC4),
+ example_config_gen:add_nodes([get_node(client), get_node(server)], TC5).
+
+
+show(X) ->
+ io:format(user, "Showing: ~p~n", [X]).
+
+state_handler() ->
+ {fun(_,_,I,S) -> io:format(user, "Got from ~p: ~p~n", [I,S]), S+1 end, 0}.
+
+show_handler() ->
+ {fun(A,B,_,_) -> io:format(A, "~p~n", [B]) end, []}.
+
+opts() ->
+ [[get_node(client), get_node(server)],
+ [{server, received, '_', []},
+ {client, put, '_', []},
+ {client, get, '_', []}],
+ {all, call},
+ [{file, "TEST"}]].
+
+overload_check(check) ->
+ true;
+overload_check(_) ->
+ ok.
+%%%Internal
+s(M, F, A) -> rpc:call(get_node(server), M, F, A).
+c(M, F, A) -> rpc:call(get_node(client), M, F, A).
+
+send_ok() ->
+ pong = net_adm:ping(get_node(test)),
+ global:sync(),
+ global:send(?REG_NAME, node()).
+
+init() ->
+ True = s(server, start, []),
+ io:format("ok1: ~p~n", [True]),
+ true = c(client, init, [get_node(server)]).
+
+recv() ->
+ receive
+ Node ->
+ io:format("Node ~p ready.~n", [Node]),
+ ok
+ after 5000 ->
+ io:format("Startup failed~n",[]),
+ throw(startup_failed)
+ end.
diff --git a/lib/observer/vsn.mk b/lib/observer/vsn.mk
index 14c8f54ba3..76e2f591fa 100644
--- a/lib/observer/vsn.mk
+++ b/lib/observer/vsn.mk
@@ -1 +1 @@
-OBSERVER_VSN = 0.9.9
+OBSERVER_VSN = 0.9.10
diff --git a/lib/odbc/c_src/Makefile.in b/lib/odbc/c_src/Makefile.in
index ed3eeb1d42..dda896bcd2 100644
--- a/lib/odbc/c_src/Makefile.in
+++ b/lib/odbc/c_src/Makefile.in
@@ -89,9 +89,10 @@ TARGET_FLAGS = @TARGET_FLAGS@
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
+_create_dirs := $(shell mkdir -p $(OBJ_DIR) $(BIN_DIR))
ifdef EXE_TARGET
-opt debug: create_dirs $(EXE_TARGET)
+opt debug: $(EXE_TARGET)
else
opt debug:
endif
@@ -119,10 +120,6 @@ endif
$(OBJ_DIR)/odbcserver.o: odbcserver.c
$(CC) $(CFLAGS) $(INCLUDES) $(TARGET_FLAGS) -o $@ -c odbcserver.c
-create_dirs:
- $(INSTALL_DIR) $(OBJ_DIR)
- $(INSTALL_DIR) $(BIN_DIR)
-
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
diff --git a/lib/odbc/c_src/odbcserver.c b/lib/odbc/c_src/odbcserver.c
index d61ce940c3..ab2d7fe210 100644
--- a/lib/odbc/c_src/odbcserver.c
+++ b/lib/odbc/c_src/odbcserver.c
@@ -90,7 +90,7 @@
Datatype - USER_INT | USER_SMALL_INT | {USER_DECIMAL, Precision, Scale} |
{USER_NMERIC, Precision, Scale} | {USER_CHAR, Max} | {USER_VARCHAR, Max} |
{USER_WVARCHAR, Max} | {USER_FLOAT, Precision} | USER_REAL | USER_DOUBLE |
- USER_TIMESTAMP
+ USER_TIMESTAMP | {USER_WLONGVARCHAR, Max}
Scale - integer
Precision - integer
Max - integer
@@ -173,7 +173,7 @@ static db_result_msg encode_row_count(SQLINTEGER num_of_rows,
db_state *state);
static void encode_column_dyn(db_column column, int column_nr,
db_state *state);
-static void encode_data_type(SQLINTEGER sql_type, SQLINTEGER size,
+static void encode_data_type(SQLSMALLINT sql_type, SQLINTEGER size,
SQLSMALLINT decimal_digits, db_state *state);
static Boolean decode_params(db_state *state, byte *buffer, int *index, param_array **params,
int i, int j);
@@ -221,7 +221,7 @@ static void init_param_column(param_array *params, byte *buffer, int *index,
int num_param_values, db_state* state);
static void init_param_statement(int cols,
- int num_param_values,
+ SQLLEN num_param_values,
db_state *state,
param_status *status);
@@ -435,7 +435,7 @@ static db_result_msg db_connect(byte *args, db_state *state)
diagnos diagnos;
byte *connStrIn;
int erl_auto_commit_mode, erl_trace_driver,
- use_srollable_cursors, tuple_row_state, binary_strings;
+ use_srollable_cursors, tuple_row_state, binary_strings;
erl_auto_commit_mode = args[0];
erl_trace_driver = args[1];
@@ -757,8 +757,9 @@ static db_result_msg db_select(byte *args, db_state *state)
static db_result_msg db_param_query(byte *buffer, db_state *state)
{
byte *sql;
- db_result_msg msg;
- int i, num_param_values, ver = 0,
+ db_result_msg msg;
+ SQLLEN num_param_values;
+ int i, ver = 0,
erl_type = 0, index = 0, size = 0, cols = 0;
long long_num_param_values;
param_status param_status;
@@ -771,6 +772,7 @@ static db_result_msg db_param_query(byte *buffer, db_state *state)
}
associated_result_set(state) = FALSE;
param_query(state) = TRUE;
+ out_params(state) = FALSE;
msg = encode_empty_message();
@@ -785,7 +787,7 @@ static db_result_msg db_param_query(byte *buffer, db_state *state)
ei_decode_long(buffer, &index, &long_num_param_values);
- num_param_values = (int)long_num_param_values;
+ num_param_values = (SQLLEN)long_num_param_values;
ei_decode_list_header(buffer, &index, &cols);
@@ -1002,12 +1004,16 @@ static db_result_msg encode_result(db_state *state)
db_result_msg msg;
int elements, update, num_of_rows = 0;
char *atom;
+ diagnos diagnos;
msg = encode_empty_message();
if(!sql_success(SQLNumResultCols(statement_handle(state),
&num_of_columns))) {
- DO_EXIT(EXIT_COLS);
+ diagnos = get_diagnos(SQL_HANDLE_STMT, statement_handle(state));
+ msg = encode_error_message(diagnos.error_msg);
+ clean_state(state);
+ return msg;
}
if (num_of_columns == 0) {
@@ -1021,7 +1027,10 @@ static db_result_msg encode_result(db_state *state)
}
if(!sql_success(SQLRowCount(statement_handle(state), &RowCountPtr))) {
- DO_EXIT(EXIT_ROWS);
+ diagnos = get_diagnos(SQL_HANDLE_STMT, statement_handle(state));
+ msg = encode_error_message(diagnos.error_msg);
+ clean_state(state);
+ return msg;
}
if(param_query(state) && update) {
@@ -1220,7 +1229,7 @@ static db_result_msg encode_column_name_list(SQLSMALLINT num_of_columns,
&nullable)))
DO_EXIT(EXIT_DESC);
- if(sql_type == SQL_LONGVARCHAR || sql_type == SQL_LONGVARBINARY)
+ if(sql_type == SQL_LONGVARCHAR || sql_type == SQL_LONGVARBINARY || sql_type == SQL_WLONGVARCHAR)
size = MAXCOLSIZE;
(columns(state)[i]).type.decimal_digits = dec_digits;
@@ -1452,7 +1461,7 @@ static void encode_column_dyn(db_column column, int column_nr,
}
}
-static void encode_data_type(SQLINTEGER sql_type, SQLINTEGER size,
+static void encode_data_type(SQLSMALLINT sql_type, SQLINTEGER size,
SQLSMALLINT decimal_digits, db_state *state)
{
switch(sql_type) {
@@ -1529,6 +1538,11 @@ static void encode_data_type(SQLINTEGER sql_type, SQLINTEGER size,
case SQL_LONGVARCHAR:
ei_x_encode_atom(&dynamic_buffer(state), "SQL_LONGVARCHAR");
break;
+ case SQL_WLONGVARCHAR:
+ ei_x_encode_tuple_header(&dynamic_buffer(state), 2);
+ ei_x_encode_atom(&dynamic_buffer(state), "sql_wlongvarchar");
+ ei_x_encode_long(&dynamic_buffer(state), size);
+ break;
case SQL_VARBINARY:
ei_x_encode_atom(&dynamic_buffer(state), "SQL_VARBINARY");
break;
@@ -2007,7 +2021,7 @@ static void init_driver(int erl_auto_commit_mode, int erl_trace_driver,
db_state *state)
{
- int auto_commit_mode, trace_driver;
+ SQLLEN auto_commit_mode, trace_driver;
if(erl_auto_commit_mode == ON) {
auto_commit_mode = SQL_AUTOCOMMIT_ON;
@@ -2057,7 +2071,7 @@ static void init_param_column(param_array *params, byte *buffer, int *index,
ei_decode_long(buffer, index, &user_type);
- params->type.strlen_or_indptr = (SQLINTEGER)NULL;
+ params->type.strlen_or_indptr = (SQLLEN)NULL;
params->type.strlen_or_indptr_array = NULL;
params->type.decimal_digits = (SQLINTEGER)0;
@@ -2131,10 +2145,14 @@ static void init_param_column(param_array *params, byte *buffer, int *index,
break;
case USER_WCHAR:
case USER_WVARCHAR:
- if(user_type == USER_WCHAR) {
- params->type.sql = SQL_WCHAR;
- } else {
- params->type.sql = SQL_WVARCHAR;
+ case USER_WLONGVARCHAR:
+ switch (user_type) {
+ case USER_WCHAR:
+ params->type.sql = SQL_WCHAR; break;
+ case USER_WVARCHAR:
+ params->type.sql = SQL_WVARCHAR; break;
+ default:
+ params->type.sql = SQL_WLONGVARCHAR; break;
}
ei_decode_long(buffer, index, &length);
/* Max string length + string terminator */
@@ -2206,7 +2224,7 @@ static void init_param_column(param_array *params, byte *buffer, int *index,
}
-static void init_param_statement(int cols, int num_param_values,
+static void init_param_statement(int cols, SQLLEN num_param_values,
db_state *state, param_status *status)
{
int i;
@@ -2234,11 +2252,11 @@ static void init_param_statement(int cols, int num_param_values,
DO_EXIT(EXIT_PARAM_ARRAY);
}
- /* Note the (int *) cast is correct as the API function SQLSetStmtAttr
+ /* Note the (SQLLEN *) cast is correct as the API function SQLSetStmtAttr
takes either an interger or a pointer depending on the attribute */
if(!sql_success(SQLSetStmtAttr(statement_handle(state),
SQL_ATTR_PARAMSET_SIZE,
- (int *)num_param_values,
+ (SQLLEN *)num_param_values,
0))) {
DO_EXIT(EXIT_PARAM_ARRAY);
}
@@ -2300,6 +2318,7 @@ static db_result_msg map_sql_2_c_column(db_column* column)
break;
case SQL_WCHAR:
case SQL_WVARCHAR:
+ case SQL_WLONGVARCHAR:
column -> type.len = (column -> type.col_size + 1)*sizeof(SQLWCHAR);
column -> type.c = SQL_C_WCHAR;
column -> type.strlen_or_indptr = SQL_NTS;
@@ -2308,21 +2327,21 @@ static db_result_msg map_sql_2_c_column(db_column* column)
case SQL_DECIMAL:
map_dec_num_2_c_column(&(column -> type), column -> type.col_size,
column -> type.decimal_digits);
- column -> type.strlen_or_indptr = (SQLINTEGER)NULL;
+ column -> type.strlen_or_indptr = (SQLLEN)NULL;
break;
case SQL_TINYINT:
case SQL_INTEGER:
case SQL_SMALLINT:
column -> type.len = sizeof(SQLINTEGER);
column -> type.c = SQL_C_SLONG;
- column -> type.strlen_or_indptr = (SQLINTEGER)NULL;
+ column -> type.strlen_or_indptr = (SQLLEN)NULL;
break;
case SQL_REAL:
case SQL_FLOAT:
case SQL_DOUBLE:
column -> type.len = sizeof(double);
column -> type.c = SQL_C_DOUBLE;
- column -> type.strlen_or_indptr = (SQLINTEGER)NULL;
+ column -> type.strlen_or_indptr = (SQLLEN)NULL;
break;
case SQL_TYPE_DATE:
case SQL_TYPE_TIME:
@@ -2334,17 +2353,17 @@ static db_result_msg map_sql_2_c_column(db_column* column)
case SQL_TYPE_TIMESTAMP:
column -> type.len = sizeof(TIMESTAMP_STRUCT);
column -> type.c = SQL_C_TYPE_TIMESTAMP;
- column -> type.strlen_or_indptr = (SQLINTEGER)NULL;
+ column -> type.strlen_or_indptr = (SQLLEN)NULL;
break;
case SQL_BIGINT:
column -> type.len = DEC_NUM_LENGTH;
column -> type.c = SQL_C_CHAR;
- column -> type.strlen_or_indptr = (SQLINTEGER)NULL;
+ column -> type.strlen_or_indptr = (SQLLEN)NULL;
break;
case SQL_BIT:
column -> type.len = sizeof(byte);
column -> type.c = SQL_C_BIT;
- column -> type.strlen_or_indptr = (SQLINTEGER)NULL;
+ column -> type.strlen_or_indptr = (SQLLEN)NULL;
break;
case SQL_UNKNOWN_TYPE:
msg = encode_error_message("Unknown column type");
diff --git a/lib/odbc/c_src/odbcserver.h b/lib/odbc/c_src/odbcserver.h
index 3e2b22ab7d..56b6148777 100644
--- a/lib/odbc/c_src/odbcserver.h
+++ b/lib/odbc/c_src/odbcserver.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -115,6 +115,7 @@
#define USER_WCHAR 12
#define USER_WVARCHAR 13
#define USER_TIMESTAMP 14
+#define USER_WLONGVARCHAR 15
/*------------------------ TYPDEFS ----------------------------------*/
diff --git a/lib/odbc/doc/src/databases.xml b/lib/odbc/doc/src/databases.xml
index a6ba0e5245..34e1d51255 100644
--- a/lib/odbc/doc/src/databases.xml
+++ b/lib/odbc/doc/src/databases.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2002</year><year>2010</year>
+ <year>2002</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -205,6 +205,10 @@ when p >= 16 </cell>
<cell align="left" valign="middle">String | Binary (configurable)</cell>
</row>
<row>
+ <cell align="left" valign="middle">SQL_WLONGVARCHAR(size) </cell>
+ <cell align="left" valign="middle">Unicode binary encoded as UTF16 little endian.</cell>
+ </row>
+ <row>
<cell align="left" valign="middle">SQL_BINARY</cell>
<cell align="left" valign="middle">String | Binary (configurable)</cell>
</row>
diff --git a/lib/odbc/doc/src/notes.xml b/lib/odbc/doc/src/notes.xml
index b88c7cf1cd..9c6ca8a017 100644
--- a/lib/odbc/doc/src/notes.xml
+++ b/lib/odbc/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,7 +31,49 @@
<p>This document describes the changes made to the odbc application.
</p>
- <section><title>ODBC 2.10.10</title>
+ <section><title>ODBC 2.10.11</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ When using output parameters the internal odbc state was
+ not correctly cleaned causing the next call to
+ param_query to misbehave.</p>
+ <p>
+ Own Id: OTP-9444</p>
+ </item>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add code to handle old ODBC drivers on solaris. Also adds
+ tests with MySQL.</p>
+ <p>
+ Own Id: OTP-8407</p>
+ </item>
+ <item>
+ <p>
+ Odbc now supports SQL_WLONGVARCHAR, thanks to Hanfei Shen
+ for the patch.</p>
+ <p>
+ Own Id: OTP-8493</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>ODBC 2.10.10</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/odbc/doc/src/odbc.xml b/lib/odbc/doc/src/odbc.xml
index 70d8cfbe22..8a58dc2848 100644
--- a/lib/odbc/doc/src/odbc.xml
+++ b/lib/odbc/doc/src/odbc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1999</year><year>2010</year>
+ <year>1999</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -102,7 +102,7 @@
{sql_decimal, precision(), scale()} |
{sql_numeric, precision(), scale()} |
{sql_char, size()} | {sql_wchar, size()} | {sql_varchar, size()} | {sql_wvarchar, size()}| {sql_float, precision()} |
- {sql_float, precision()} | sql_real | sql_double | sql_bit | atom()
+ {sql_wlongvarchar, size()} | {sql_float, precision()} | sql_real | sql_double | sql_bit | atom()
</code>
<code type="none">
precision() = integer() </code>
@@ -138,7 +138,7 @@
<fsummary>Opens a connection to the database. </fsummary>
<type>
<v>ConnectStr = string()</v>
- <d>An example of a connection string:<c>"DSN=sql-server;UID=aladdin;PWD=sesame"</c>where DSN is your ODBC Data Source Name, UID is a database user id and PWD is the password for that user. These are usually the attributes required in the connection string, but some drivers have other driver specific attributes, for example<c>"DSN=Oracle8;DBQ=gandalf;UID=aladdin;PWD=sesame"</c>where DBQ is your TNSNAMES.ORA entry name e.g. some Oracle specific configuration attribute.</d>
+ <d>An example of a connection string: <c>"DSN=sql-server;UID=aladdin;PWD=sesame"</c> where DSN is your ODBC Data Source Name, UID is a database user id and PWD is the password for that user. These are usually the attributes required in the connection string, but some drivers have other driver specific attributes, for example <c>"DSN=Oracle8;DBQ=gandalf;UID=aladdin;PWD=sesame"</c> where DBQ is your TNSNAMES.ORA entry name e.g. some Oracle specific configuration attribute.</d>
<v>Options = [] | [option()]</v>
<d>All options has default values. </d>
<v>option() = {auto_commit, on | off} | {timeout, milliseconds()}
@@ -432,7 +432,7 @@
<desc>
<p>Selects <c>N</c> consecutive rows of the result set. If
<c>Position</c> is <c>next</c> it is semantically equivalent
- of calling <c>next/[1,2]</c><c>N</c> times. If
+ of calling <c>next/[1,2]</c> <c>N</c> times. If
<c>Position</c> is <c>{relative, Pos}</c>, <c>Pos</c> will be
used as an offset from the current cursor position to
determine the first selected row. If <c>Position</c> is
diff --git a/lib/odbc/src/odbc.appup.src b/lib/odbc/src/odbc.appup.src
index 2a6667ccd3..f3a3af8c29 100644
--- a/lib/odbc/src/odbc.appup.src
+++ b/lib/odbc/src/odbc.appup.src
@@ -1,8 +1,10 @@
%% -*- erlang -*-
{"%VSN%",
[
- {"2.10.9", [{restart_application, ssl}]}
+ {"2.10.10", [{restart_application, odbc}]},
+ {"2.10.9", [{restart_application, odbc}]}
],
[
- {"2.10.9", [{restart_application, ssl}]}
+ {"2.10.10", [{restart_application, odbc}]},
+ {"2.10.9", [{restart_application, odbc}]}
]}.
diff --git a/lib/odbc/src/odbc.erl b/lib/odbc/src/odbc.erl
index 83d9f33102..68497292db 100644
--- a/lib/odbc/src/odbc.erl
+++ b/lib/odbc/src/odbc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -431,7 +431,7 @@ init(Args) ->
erlang:monitor(process, ClientPid),
- Inet = case gen_tcp:listen(0, [inet6]) of
+ Inet = case gen_tcp:listen(0, [inet6, {ip, loopback}]) of
{ok, Dummyport} ->
gen_tcp:close(Dummyport),
inet6;
@@ -925,6 +925,9 @@ fix_params({{sql_wchar, Max}, InOut, Values}) ->
fix_params({{sql_wvarchar, Max}, InOut, Values}) ->
NewValues = string_terminate(Values),
{?USER_WVARCHAR, Max, fix_inout(InOut), NewValues};
+fix_params({{sql_wlongvarchar, Max}, InOut, Values}) ->
+ NewValues = string_terminate(Values),
+ {?USER_WLONGVARCHAR, Max, fix_inout(InOut), NewValues};
fix_params({{sql_float, Precision}, InOut, Values}) ->
{?USER_FLOAT, Precision, fix_inout(InOut), Values};
fix_params({sql_real, InOut, Values}) ->
diff --git a/lib/odbc/src/odbc_internal.hrl b/lib/odbc/src/odbc_internal.hrl
index aa60120f9a..bd80cdc659 100644
--- a/lib/odbc/src/odbc_internal.hrl
+++ b/lib/odbc/src/odbc_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -72,6 +72,7 @@
-define(USER_WCHAR, 12).
-define(USER_WVARCHAR, 13).
-define(USER_TIMESTAMP, 14).
+-define(USER_WLONGVARCHAR, 15).
%% INPUT & OUTPUT TYPE
-define(IN, 0).
diff --git a/lib/odbc/test/Makefile b/lib/odbc/test/Makefile
index ec2bcc67b5..bc6449242e 100644
--- a/lib/odbc/test/Makefile
+++ b/lib/odbc/test/Makefile
@@ -34,7 +34,8 @@ MODULES= \
odbc_test_lib \
oracle \
sqlserver \
- postgres
+ postgres \
+ mysql
EBIN = .
diff --git a/lib/odbc/test/mysql.erl b/lib/odbc/test/mysql.erl
new file mode 100644
index 0000000000..c990793213
--- /dev/null
+++ b/lib/odbc/test/mysql.erl
@@ -0,0 +1,277 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(mysql).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+%-------------------------------------------------------------------------
+connection_string() ->
+ case test_server:os_type() of
+ {unix, linux} ->
+ "DSN=MySQL;Database=odbctest;Uid=odbctest;Pwd=gurka;CHARSET=utf8;SSTMT=SET NAMES 'utf8';";
+ {unix, sunos} ->
+ solaris_str();
+ {unix, darwin} ->
+ "DSN=MySQLMac;Database=odbctest;Uid=odbctest;Pwd=gurka;CHARSET=utf8;SSTMT=SET NAMES 'utf8';"
+ end.
+
+solaris_str() ->
+ case erlang:system_info(system_architecture) of
+ "sparc" ++ _ ->
+ "DSN=MySQLSolaris10;Database=odbctest;Uid=odbctest;Pwd=gurka;CHARSET=utf8;SSTMT=SET NAMES 'utf8';";
+ "i386" ++ _ ->
+ "DSN=MySQLSolaris10i386;Database=odbctest;Uid=odbctest;Pwd=gurka;CHARSET=utf8;SSTMT=SET NAMES 'utf8';"
+ end.
+
+%-------------------------------------------------------------------------
+insert_result() ->
+ {selected,["ID","DATA"],[{1,"bar"}]}.
+
+update_result() ->
+ {selected,["ID","DATA"],[{1,"foo"}]}.
+
+selected_ID(N, next) ->
+ {selected,["ID"],[{N}]};
+
+selected_ID(_, _) ->
+ {error, driver_does_not_support_function}.
+
+selected_next_N(1)->
+ {selected,["ID"],
+ [{1},
+ {2},
+ {3}]};
+
+selected_next_N(2)->
+ {selected,["ID"],
+ [{4},
+ {5}]}.
+
+selected_relative_N(_)->
+ {error, driver_does_not_support_function}.
+
+selected_absolute_N(_)->
+ {error, driver_does_not_support_function}.
+
+selected_list_rows() ->
+ {selected,["ID", "DATA"],[[1, "bar"],[2,"foo"]]}.
+
+first_list_rows() ->
+ {error, driver_does_not_support_function}.
+last_list_rows() ->
+ {error, driver_does_not_support_function}.
+prev_list_rows() ->
+ {error, driver_does_not_support_function}.
+next_list_rows() ->
+ {selected,["ID","DATA"],[[1,"bar"]]}.
+
+multiple_select()->
+ [{selected,["ID", "DATA"],[{1, "bar"},{2, "foo"}]},
+ {selected,["ID"],[{"foo"}]}].
+
+multiple_mix()->
+ [{updated, 1},{updated, 1},
+ {selected,["ID", "DATA"],[{1, "foobar"},{2, "foo"}]},
+ {updated, 1}, {selected,["DATA"],[{"foo"}]}].
+
+%-------------------------------------------------------------------------
+var_char_min() ->
+ 0.
+var_char_max() ->
+ 65535.
+
+create_var_char_table(Size) ->
+ " (FIELD varchar(" ++ integer_to_list(Size) ++ "))".
+
+%-------------------------------------------------------------------------
+text_min() ->
+ 1.
+text_max() ->
+ 2147483646. % 2147483647. %% 2^31 - 1
+
+create_text_table() ->
+ " (FIELD text)".
+
+%-------------------------------------------------------------------------
+create_timestamp_table() ->
+ " (FIELD TIMESTAMP)".
+
+%-------------------------------------------------------------------------
+tiny_int_min() ->
+ -128.
+tiny_int_max() ->
+ 127.
+
+create_tiny_int_table() ->
+ " (FIELD tinyint)".
+
+tiny_int_min_selected() ->
+ {selected,["FIELD"],[{tiny_int_min()}]}.
+
+tiny_int_max_selected() ->
+ {selected,["FIELD"], [{tiny_int_max()}]}.
+
+%-------------------------------------------------------------------------
+small_int_min() ->
+ -32768.
+small_int_max() ->
+ 32767.
+
+create_small_int_table() ->
+ " (FIELD smallint)".
+
+small_int_min_selected() ->
+ {selected,["FIELD"],[{-32768}]}.
+
+small_int_max_selected() ->
+ {selected,["FIELD"], [{32767}]}.
+
+%-------------------------------------------------------------------------
+int_min() ->
+ -2147483648.
+int_max() ->
+ 2147483647.
+
+create_int_table() ->
+ " (FIELD int)".
+
+int_min_selected() ->
+ {selected,["FIELD"],[{-2147483648}]}.
+
+int_max_selected() ->
+ {selected,["FIELD"], [{2147483647}]}.
+
+%-------------------------------------------------------------------------
+big_int_min() ->
+ -9223372036854775808.
+
+big_int_max() ->
+ 9223372036854775807.
+
+create_big_int_table() ->
+ " (FIELD bigint )".
+
+big_int_min_selected() ->
+ {selected,["FIELD"], [{"-9223372036854775808"}]}.
+
+big_int_max_selected() ->
+ {selected,["FIELD"], [{"9223372036854775807"}]}.
+
+%-------------------------------------------------------------------------
+bit_false() ->
+ 0.
+bit_true() ->
+ 1.
+
+create_bit_table() ->
+ " (FIELD bit)".
+
+bit_false_selected() ->
+ {selected,["FIELD"],[{"0"}]}.
+
+bit_true_selected() ->
+ {selected,["FIELD"], [{"1"}]}.
+
+%-------------------------------------------------------------------------
+
+%% Do not test float min/max as value is only theoretical defined in
+%% mysql and may vary depending on hardware.
+
+create_float_table() ->
+ " (FIELD float)".
+
+float_zero_selected() ->
+ {selected,["FIELD"],[{0.00000e+0}]}.
+
+%-------------------------------------------------------------------------
+real_min() ->
+ -3.40e+38.
+real_max() ->
+ 3.40e+38.
+
+real_underflow() ->
+ "-3.41e+38".
+
+real_overflow() ->
+ "3.41e+38".
+
+create_real_table() ->
+ " (FIELD real)".
+
+real_zero_selected() ->
+ {selected,["FIELD"],[{0.00000e+0}]}.
+
+%-------------------------------------------------------------------------
+param_select_small_int() ->
+ {selected,["FIELD"],[{1}, {2}]}.
+
+param_select_int() ->
+ Int = small_int_max() + 1,
+ {selected,["FIELD"],[{1}, {Int}]}.
+
+param_select_decimal() ->
+ {selected,["FIELD"],[{1},{2}]}.
+
+param_select_numeric() ->
+ {selected,["FIELD"],[{1},{2}]}.
+
+param_select_float() ->
+ {selected,["FIELD"],[{1.30000},{1.20000}]}.
+
+param_select_real() ->
+ {selected,["FIELD"],[{1.30000},{1.20000}]}.
+
+param_select_double() ->
+ {selected,["FIELD"],[{1.30000},{1.20000}]}.
+
+param_select_mix() ->
+ {selected,["ID","DATA"],[{1, "foo"}, {2, "bar"}]}.
+
+param_update() ->
+ {selected,["ID","DATA"],[{1, "foobar"}, {2, "foobar"}, {3, "baz"}]}.
+
+param_delete() ->
+ {selected,["ID","DATA"],[{3, "baz"}]}.
+
+param_select() ->
+ {selected,["ID","DATA"],[{1, "foo"},{3, "foo"}]}.
+
+%-------------------------------------------------------------------------
+describe_integer() ->
+ {ok,[{"myint1",sql_smallint},
+ {"myint2",sql_integer},
+ {"myint3",sql_integer}]}.
+
+describe_string() ->
+ {ok,[{"str1",{sql_char,10}},
+ {"str2",{sql_char,10}},
+ {"str3",{sql_varchar,10}},
+ {"str4",{sql_varchar,10}}]}.
+
+describe_floating() ->
+ {ok,[{"f",sql_real},{"r",sql_double},{"d",sql_double}]}.
+describe_dec_num() ->
+ {ok,[{"mydec",{sql_decimal,9,3}},{"mynum",{sql_decimal,9,2}}]}.
+
+describe_timestamp() ->
+ {ok, [{"FIELD", sql_timestamp}]}.
diff --git a/lib/odbc/test/odbc.dynspec b/lib/odbc/test/odbc.dynspec
deleted file mode 100644
index bb15edceed..0000000000
--- a/lib/odbc/test/odbc.dynspec
+++ /dev/null
@@ -1,31 +0,0 @@
-%% -*- erlang -*-
-%% You can test this file using this command.
-%% file:script("odbc.dynspec", [{'Os',"Unix"}]).
-
-Exists =
-fun() ->
- case code:lib_dir(odbc) of
- {error,bad_name} ->
- false;
- P ->
- %% Make sure that the odbc directory really
- %% contains the application (and not only documentation).
- case filelib:is_file(filename:join(P, "ebin/odbc.beam")) of
- false -> false;
- true ->
- %% We know that we don't have any odbc libraries
- %% installed on this computer.
- {ok,Host} = inet:gethostname(),
- Host =/= "netsim200"
- end
- end
-end,
-case Exists() of
- false ->
- NoOdbc = "No odbc application",
- [{skip, {odbc_connect_SUITE, NoOdbc}},
- {skip, {odbc_data_type_SUITE, NoOdbc}},
- {skip, {odbc_query_SUITE, NoOdbc}}];
- true ->
- []
-end.
diff --git a/lib/odbc/test/odbc.spec b/lib/odbc/test/odbc.spec
index edaf821c91..653f1a780e 100644
--- a/lib/odbc/test/odbc.spec
+++ b/lib/odbc/test/odbc.spec
@@ -1,25 +1 @@
{suites,"../odbc_test",all}.
-{skip_cases,"../odbc_test",odbc_data_type_SUITE,
- [varchar_upper_limit],
- "Known bug in database"}.
-{skip_cases,"../odbc_test",odbc_data_type_SUITE,
- [text_upper_limit],
- "Consumes too much resources"}.
-{skip_cases,"../odbc_test",odbc_data_type_SUITE,
- [bit_true],
- "Not supported by driver"}.
-{skip_cases,"../odbc_test",odbc_data_type_SUITE,
- [bit_false],
- "Not supported by driver"}.
-{skip_cases,"../odbc_test",odbc_query_SUITE,
- [multiple_select_result_sets],
- "Not supported by driver"}.
-{skip_cases,"../odbc_test",odbc_query_SUITE,
- [multiple_mix_result_sets],
- "Not supported by driver"}.
-{skip_cases,"../odbc_test",odbc_query_SUITE,
- [multiple_result_sets_error],
- "Not supported by driver"}.
-{skip_cases,"../odbc_test",odbc_query_SUITE,
- [param_insert_tiny_int],
- "Not supported by driver"}.
diff --git a/lib/odbc/test/odbc.spec.win b/lib/odbc/test/odbc.spec.win
deleted file mode 100644
index 1fd349d2c3..0000000000
--- a/lib/odbc/test/odbc.spec.win
+++ /dev/null
@@ -1,5 +0,0 @@
-{topcase, {dir, "../odbc_test"}}.
-{skip, {odbc_data_type_SUITE, big_int_lower_limit, "Not supported by sqlserver 7.0"}}.
-{skip, {odbc_data_type_SUITE, big_int_upper_limit, "Not supported by sqlserver7.0"}}.
-{skip, {odbc_data_type_SUITE, text_upper_limit, "Consumes too much resources"}}.
-
diff --git a/lib/odbc/test/odbc_connect_SUITE.erl b/lib/odbc/test/odbc_connect_SUITE.erl
index 6a2268f40e..a076c4dfff 100644
--- a/lib/odbc/test/odbc_connect_SUITE.erl
+++ b/lib/odbc/test/odbc_connect_SUITE.erl
@@ -76,16 +76,26 @@ end_per_group(_GroupName, Config) ->
%% 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) ->
- application:start(odbc),
- case catch odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]) of
- {ok, Ref} ->
- odbc:disconnect(Ref),
- [{tableName, odbc_test_lib:unique_table_name()} | Config];
- _ ->
- {skip, "ODBC is not properly setup"}
- end.
+init_per_suite(Config) when is_list(Config) ->
+ case odbc_test_lib:skip() of
+ true ->
+ {skip, "ODBC not supported"};
+ false ->
+ case (catch odbc:start()) of
+ ok ->
+ case catch odbc:connect(?RDBMS:connection_string(),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()) of
+ {ok, Ref} ->
+ odbc:disconnect(Ref),
+ [{tableName, odbc_test_lib:unique_table_name()} | Config];
+ _ ->
+ {skip, "ODBC is not properly setup"}
+ end;
+ _ ->
+ {skip,"ODBC not startable"}
+ end
+ end.
+
%%--------------------------------------------------------------------
%% Function: end_per_suite(Config) -> _
%% Config - [tuple()]
@@ -93,8 +103,7 @@ init_per_suite(Config) ->
%% Description: Cleanup after the whole suite
%%--------------------------------------------------------------------
end_per_suite(_Config) ->
- application:stop(odbc),
- ok.
+ application:stop(odbc).
%%--------------------------------------------------------------------
%% Function: init_per_testcase(Case, Config) -> Config
@@ -124,15 +133,13 @@ init_per_testcase(_TestCase, Config) ->
%% Description: Cleanup after each test case
%%--------------------------------------------------------------------
end_per_testcase(_TestCase, Config) ->
- %% Clean up if needed
Table = ?config(tableName, Config),
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
- Result = odbc:sql_query(Ref, "DROP TABLE " ++ Table),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
+ Result = odbc:sql_query(Ref, "DROP TABLE " ++ Table),
io:format("Drop table: ~p ~p~n", [Table, Result]),
odbc:disconnect(Ref),
Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
+ test_server:timetrap_cancel(Dog).
%%-------------------------------------------------------------------------
%% Test cases starts here.
@@ -142,13 +149,15 @@ commit(doc)->
commit(suite) -> [];
commit(Config) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
+ TransStr = transaction_support_str(?RDBMS),
+
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
- " (ID integer, DATA varchar(10))"),
+ " (ID integer, DATA varchar(10))" ++ TransStr),
{updated, 1} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(1,'bar')"),
@@ -173,50 +182,47 @@ commit(Config) ->
{'EXIT', {function_clause, _}} =
(catch odbc:commit(Ref, commit, -1)),
- ok = odbc:disconnect(Ref),
-
- ok.
+ ok = odbc:disconnect(Ref).
%%-------------------------------------------------------------------------
rollback(doc)->
["Test the use of explicit rollback"];
rollback(suite) -> [];
rollback(Config) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
- {updated, _} =
- odbc:sql_query(Ref,
+ TransStr = transaction_support_str(?RDBMS),
+
+ {updated, _} =
+ odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
- " (ID integer, DATA varchar(10))"),
- {updated, 1} =
+ " (ID integer, DATA varchar(10))" ++ TransStr),
+ {updated, 1} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++ " VALUES(1,'bar')"),
ok = odbc:commit(Ref, commit),
- {updated, 1} =
+ {updated, 1} =
odbc:sql_query(Ref, "UPDATE " ++ Table ++
- " SET DATA = 'foo' WHERE ID = 1"),
+ " SET DATA = 'foo' WHERE ID = 1"),
ok = odbc:commit(Ref, rollback),
InsertResult = ?RDBMS:insert_result(),
- InsertResult =
+ InsertResult =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
-
- {updated, 1} =
+ {updated, 1} =
odbc:sql_query(Ref, "UPDATE " ++ Table ++
- " SET DATA = 'foo' WHERE ID = 1"),
+ " SET DATA = 'foo' WHERE ID = 1"),
ok = odbc:commit(Ref, rollback, ?TIMEOUT),
InsertResult = ?RDBMS:insert_result(),
- InsertResult =
+ InsertResult =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
+ {'EXIT', {function_clause, _}} =
+ (catch odbc:commit(Ref, rollback, -1)),
- {'EXIT', {function_clause, _}} =
- (catch odbc:commit(Ref, rollback, -1)),
-
- ok = odbc:disconnect(Ref),
- ok.
+ ok = odbc:disconnect(Ref).
%%-------------------------------------------------------------------------
not_explicit_commit(doc) ->
@@ -224,20 +230,20 @@ not_explicit_commit(doc) ->
not_explicit_commit(suite) -> [];
not_explicit_commit(_Config) ->
{ok, Ref} =
- odbc:connect(?RDBMS:connection_string(), [{auto_commit, on}]),
+ odbc:connect(?RDBMS:connection_string(), [{auto_commit, on}] ++
+ odbc_test_lib:platform_options()),
{error, _} = odbc:commit(Ref, commit),
- ok = odbc:disconnect(Ref),
- ok.
+ ok = odbc:disconnect(Ref).
%%-------------------------------------------------------------------------
not_exist_db(doc) ->
["Tests valid data format but invalid data in the connection parameters."];
not_exist_db(suite) -> [];
not_exist_db(_Config) ->
- {error, _} = odbc:connect("DSN=foo;UID=bar;PWD=foobar", []),
+ {error, _} = odbc:connect("DSN=foo;UID=bar;PWD=foobar",
+ odbc_test_lib:platform_options()),
%% So that the odbc control server can be stoped "in the correct way"
- test_server:sleep(100),
- ok.
+ test_server:sleep(100).
%%-------------------------------------------------------------------------
no_c_node(doc) ->
@@ -252,7 +258,8 @@ no_c_node(_Config) ->
FileName2 = filename:nativename(filename:join(Dir, "odbcsrv")),
ok = file:rename(FileName1, FileName2),
Result =
- case catch odbc:connect(?RDBMS:connection_string(), []) of
+ case catch odbc:connect(?RDBMS:connection_string(),
+ odbc_test_lib:platform_options()) of
{error, port_program_executable_not_found} ->
ok;
Else ->
@@ -267,7 +274,7 @@ port_dies(doc) ->
"Tests what happens if the port program dies";
port_dies(suite) -> [];
port_dies(_Config) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
{status, _} = process_info(Ref, status),
process_flag(trap_exit, true),
Port = lists:last(erlang:ports()),
@@ -275,26 +282,23 @@ port_dies(_Config) ->
%% Wait for exit_status from port 5000 ms (will not get a exit
%% status in this case), then wait a little longer to make sure
%% the port and the controlprocess has had time to terminate.
- test_server:sleep(7000),
- undefined = process_info(Ref, status),
- ok.
+ test_server:sleep(10000),
+ undefined = process_info(Ref, status).
%%-------------------------------------------------------------------------
control_process_dies(doc) ->
"Tests what happens if the Erlang control process dies";
control_process_dies(suite) -> [];
control_process_dies(_Config) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
process_flag(trap_exit, true),
Port = lists:last(erlang:ports()),
{connected, Ref} = erlang:port_info(Port, connected),
exit(Ref, kill),
- test_server:sleep(100),
- undefined = erlang:port_info(Port, connected),
+ test_server:sleep(500),
+ undefined = erlang:port_info(Port, connected).
%% Check for c-program still running, how?
- ok.
-%%-------------------------------------------------------------------------
%%-------------------------------------------------------------------------
client_dies_normal(doc) ->
@@ -319,7 +323,7 @@ client_dies_normal(Config) when is_list(Config) ->
end.
client_normal(Pid) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
Pid ! {dbRef, Ref},
receive
continue ->
@@ -351,7 +355,7 @@ client_dies_timeout(Config) when is_list(Config) ->
end.
client_timeout(Pid) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
Pid ! {dbRef, Ref},
receive
continue ->
@@ -383,7 +387,7 @@ client_dies_error(Config) when is_list(Config) ->
end.
client_error(Pid) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
Pid ! {dbRef, Ref},
receive
continue ->
@@ -398,7 +402,10 @@ connect_timeout(doc) ->
connect_timeout(suite) -> [];
connect_timeout(Config) when is_list(Config) ->
{'EXIT',timeout} = (catch odbc:connect(?RDBMS:connection_string(),
- [{timeout, 0}])),
+ [{timeout, 0}] ++
+ odbc_test_lib:platform_options())),
+ %% Need to return ok here "{'EXIT',timeout} return value" will
+ %% be interpreted as that the testcase has timed out.
ok.
%%-------------------------------------------------------------------------
timeout(doc) ->
@@ -411,10 +418,12 @@ timeout(Config) when is_list(Config) ->
[{auto_commit, off}]),
Table = ?config(tableName, Config),
+ TransStr = transaction_support_str(?RDBMS),
+
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
- " (ID integer, DATA varchar(10), PRIMARY KEY(ID))"),
+ " (ID integer, DATA varchar(10), PRIMARY KEY(ID))" ++ TransStr),
{updated, 1} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++ " VALUES(1,'bar')"),
@@ -446,14 +455,12 @@ timeout(Config) when is_list(Config) ->
["DATA"] = odbc_test_lib:to_upper(Fields),
ok = odbc:commit(Ref, commit),
- ok = odbc:disconnect(Ref),
- ok.
-
+ ok = odbc:disconnect(Ref).
update_table_timeout(Table, TimeOut, Pid) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
UpdateQuery = "UPDATE " ++ Table ++ " SET DATA = 'foobar' WHERE ID = 1",
case catch odbc:sql_query(Ref, UpdateQuery, TimeOut) of
@@ -474,15 +481,16 @@ update_table_timeout(Table, TimeOut, Pid) ->
odbc:sql_query(Ref, "SELECT DATA FROM " ++ Table ++ " WHERE ID = 2"),
["DATA"] = odbc_test_lib:to_upper(Fields),
- {updated, 1} = odbc:sql_query(Ref, UpdateQuery, TimeOut),
+ %% Do not check {updated, 1} as some drivers will return 0
+ %% even though the update is done, which is checked by the test
+ %% case when the altered message is recived.
+ {updated, _} = odbc:sql_query(Ref, UpdateQuery, TimeOut),
ok = odbc:commit(Ref, commit),
Pid ! altered,
- ok = odbc:disconnect(Ref),
-
- ok.
+ ok = odbc:disconnect(Ref).
%%-------------------------------------------------------------------------
many_timeouts(doc) ->
["Tests that many consecutive timeouts lead to that the connection "
@@ -490,14 +498,15 @@ many_timeouts(doc) ->
many_timeouts(suite) -> [];
many_timeouts(Config) when is_list(Config) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
+ TransStr = transaction_support_str(?RDBMS),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
- " (ID integer, DATA varchar(10), PRIMARY KEY(ID))"),
+ " (ID integer, DATA varchar(10), PRIMARY KEY(ID))" ++ TransStr),
{updated, 1} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++ " VALUES(1,'bar')"),
@@ -517,22 +526,20 @@ many_timeouts(Config) when is_list(Config) ->
end,
ok = odbc:commit(Ref, commit),
- ok = odbc:disconnect(Ref),
- ok.
+ ok = odbc:disconnect(Ref).
update_table_many_timeouts(Table, TimeOut, Pid) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
UpdateQuery = "UPDATE " ++ Table ++ " SET DATA = 'foobar' WHERE ID = 1",
ok = loop_many_timouts(Ref, UpdateQuery, TimeOut),
Pid ! many_timeouts_occurred,
- ok = odbc:disconnect(Ref),
- ok.
+ ok = odbc:disconnect(Ref).
loop_many_timouts(Ref, UpdateQuery, TimeOut) ->
@@ -546,18 +553,19 @@ loop_many_timouts(Ref, UpdateQuery, TimeOut) ->
end.
%%-------------------------------------------------------------------------
timeout_reset(doc) ->
- ["Check that the number of consecutive timouts is reset to 0 when "
+ ["Check that the number of consecutive timouts is reset to 0 when "
"a successful call to the database is made."];
timeout_reset(suite) -> [];
timeout_reset(Config) when is_list(Config) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
+ TransStr = transaction_support_str(?RDBMS),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
- " (ID integer, DATA varchar(10), PRIMARY KEY(ID))"),
+ " (ID integer, DATA varchar(10), PRIMARY KEY(ID))" ++ TransStr),
{updated, 1} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++ " VALUES(1,'bar')"),
@@ -593,13 +601,12 @@ timeout_reset(Config) when is_list(Config) ->
["DATA"] = odbc_test_lib:to_upper(Fields),
ok = odbc:commit(Ref, commit),
- ok = odbc:disconnect(Ref),
- ok.
+ ok = odbc:disconnect(Ref).
update_table_timeout_reset(Table, TimeOut, Pid) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
UpdateQuery = "UPDATE " ++ Table ++ " SET DATA = 'foobar' WHERE ID = 1",
ok = loop_timout_reset(Ref, UpdateQuery, TimeOut,
@@ -616,15 +623,16 @@ update_table_timeout_reset(Table, TimeOut, Pid) ->
odbc:sql_query(Ref, "SELECT DATA FROM " ++ Table ++ " WHERE ID = 2"),
["DATA"] = odbc_test_lib:to_upper(Fields),
- {updated,1} = odbc:sql_query(Ref, UpdateQuery, TimeOut),
+ %% Do not check {updated, 1} as some drivers will return 0
+ %% even though the update is done, which is checked by the test
+ %% case when the altered message is recived.
+ {updated, _} = odbc:sql_query(Ref, UpdateQuery, TimeOut),
ok = odbc:commit(Ref, commit),
Pid ! altered,
- ok = odbc:disconnect(Ref),
-
- ok.
+ ok = odbc:disconnect(Ref).
loop_timout_reset(_, _, _, 0) ->
ok;
@@ -648,13 +656,14 @@ disconnect_on_timeout(suite) -> [];
disconnect_on_timeout(Config) when is_list(Config) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
+ TransStr = transaction_support_str(?RDBMS),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
- " (ID integer, DATA varchar(10), PRIMARY KEY(ID))"),
+ " (ID integer, DATA varchar(10), PRIMARY KEY(ID))" ++ TransStr),
{updated, 1} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++ " VALUES(1,'bar')"),
@@ -678,7 +687,7 @@ disconnect_on_timeout(Config) when is_list(Config) ->
update_table_disconnect_on_timeout(Table, TimeOut, Pid) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
UpdateQuery = "UPDATE " ++ Table ++ " SET DATA = 'foobar' WHERE ID = 1",
case catch odbc:sql_query(Ref, UpdateQuery, TimeOut) of
@@ -695,7 +704,7 @@ connection_closed(doc) ->
" use a connection that has been closed"];
connection_closed(suite) -> [];
connection_closed(Config) when is_list(Config) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
{updated, _} =
@@ -714,8 +723,7 @@ connection_closed(Config) when is_list(Config) ->
{error, connection_closed} = odbc:next(Ref),
{error, connection_closed} = odbc:prev(Ref),
{error, connection_closed} = odbc:select(Ref, next, 3),
- {error, connection_closed} = odbc:commit(Ref, commit),
- ok.
+ {error, connection_closed} = odbc:commit(Ref, commit).
%%-------------------------------------------------------------------------
disable_scrollable_cursors(doc) ->
@@ -753,8 +761,7 @@ disable_scrollable_cursors(Config) when is_list(Config) ->
{error, scrollable_cursors_disabled} =
odbc:select(Ref, {absolute, 2}, 5),
- {selected, _ColNames,[]} = odbc:select(Ref, next, 1),
- ok.
+ {selected, _ColNames,[]} = odbc:select(Ref, next, 1).
%%-------------------------------------------------------------------------
return_rows_as_lists(doc)->
@@ -763,7 +770,7 @@ return_rows_as_lists(doc)->
return_rows_as_lists(suite) -> [];
return_rows_as_lists(Config) when is_list(Config) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{tuple_row, off}]),
+ [{tuple_row, off}] ++ odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
@@ -784,16 +791,21 @@ return_rows_as_lists(Config) when is_list(Config) ->
{ok, _} = odbc:select_count(Ref, "SELECT * FROM " ++ Table),
- First = ?RDBMS:first_list_rows(),
- Last = ?RDBMS:last_list_rows(),
- Prev = ?RDBMS:prev_list_rows(),
- Next = ?RDBMS:next_list_rows(),
-
- Last = odbc:last(Ref),
- Prev = odbc:prev(Ref),
- First = odbc:first(Ref),
- Next = odbc:next(Ref),
- ok.
+ case proplists:get_value(scrollable_cursors, odbc_test_lib:platform_options()) of
+ off ->
+ Next = ?RDBMS:next_list_rows(),
+ Next = odbc:next(Ref);
+ _ ->
+ First = ?RDBMS:first_list_rows(),
+ Last = ?RDBMS:last_list_rows(),
+ Prev = ?RDBMS:prev_list_rows(),
+ Next = ?RDBMS:next_list_rows(),
+
+ Last = odbc:last(Ref),
+ Prev = odbc:prev(Ref),
+ First = odbc:first(Ref),
+ Next = odbc:next(Ref)
+ end.
%%-------------------------------------------------------------------------
@@ -802,22 +814,27 @@ api_missuse(doc)->
api_missuse(suite) -> [];
api_missuse(Config) when is_list(Config)->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
%% Serious programming fault, connetion will be shut down
gen_server:call(Ref, {self(), foobar, 10}, infinity),
test_server:sleep(10),
undefined = process_info(Ref, status),
- {ok, Ref2} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref2} = odbc:connect(?RDBMS:connection_string(),
+ odbc_test_lib:platform_options()),
%% Serious programming fault, connetion will be shut down
gen_server:cast(Ref2, {self(), foobar, 10}),
test_server:sleep(10),
undefined = process_info(Ref2, status),
- {ok, Ref3} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref3} = odbc:connect(?RDBMS:connection_string(),
+ odbc_test_lib:platform_options()),
%% Could be an innocent misstake the connection lives.
Ref3 ! foobar,
test_server:sleep(10),
- {status, _} = process_info(Ref3, status),
- ok.
+ {status, _} = process_info(Ref3, status).
+transaction_support_str(mysql) ->
+ "ENGINE = InnoDB";
+transaction_support_str(_) ->
+ "".
diff --git a/lib/odbc/test/odbc_data_type_SUITE.erl b/lib/odbc/test/odbc_data_type_SUITE.erl
index bfb1e4b329..d61a91f973 100644
--- a/lib/odbc/test/odbc_data_type_SUITE.erl
+++ b/lib/odbc/test/odbc_data_type_SUITE.erl
@@ -44,24 +44,29 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
case odbc_test_lib:odbc_check() of
ok ->
- [{group, char}, {group, int}, {group, floats},
+ [{group, char},{group, fixed_char}, {group, binary_char},
+ {group, fixed_binary_char}, {group, unicode},
+ {group, int}, {group, floats},
{group, dec_and_num}, timestamp];
Other -> {skip, Other}
end.
groups() ->
[{char, [],
- [char_fixed_lower_limit, char_fixed_upper_limit,
- char_fixed_padding, varchar_lower_limit,
+ [varchar_lower_limit,
varchar_upper_limit, varchar_no_padding,
- text_lower_limit, text_upper_limit, unicode]},
+ text_lower_limit, text_upper_limit]},
+ {fixed_char, [],
+ [char_fixed_lower_limit, char_fixed_upper_limit,
+ char_fixed_padding]},
{binary_char, [],
- [binary_char_fixed_lower_limit,
- binary_char_fixed_upper_limit,
- binary_char_fixed_padding, binary_varchar_lower_limit,
+ [binary_varchar_lower_limit,
binary_varchar_upper_limit, binary_varchar_no_padding,
- binary_text_lower_limit, binary_text_upper_limit,
- unicode]},
+ binary_text_lower_limit, binary_text_upper_limit]},
+ {fixed_binary_char, [], [binary_char_fixed_lower_limit,
+ binary_char_fixed_upper_limit,
+ binary_char_fixed_padding]},
+ {unicode, [], [utf8, nchar, nvarchar]},
{int, [],
[tiny_int_lower_limit, tiny_int_upper_limit,
small_int_lower_limit, small_int_upper_limit,
@@ -74,14 +79,31 @@ groups() ->
[dec_long, dec_double, dec_bignum, num_long, num_double,
num_bignum]}].
+init_per_group(GroupName, Config) when GroupName == fixed_char;
+ GroupName == fixed_binary_char ->
+ case ?RDBMS of
+ mysql ->
+ {skip, "No supported by MYSQL"};
+ _ ->
+ Config
+ end;
+
+init_per_group(unicode, Config) ->
+ case {os:type(), erlang:system_info({wordsize, external})} of
+ {{unix, _}, 4} ->
+ Config;
+ {{unix, _}, _} ->
+ {skip, "Postgres drivers pre version psqlODBC 08.04.0200 have utf8-problems"};
+ _ ->
+ Config
+ end;
+
init_per_group(_GroupName, Config) ->
Config.
end_per_group(_GroupName, Config) ->
Config.
-
-
%%--------------------------------------------------------------------
%% Function: init_per_suite(Config) -> Config
%% Config - [tuple()]
@@ -91,10 +113,18 @@ end_per_group(_GroupName, Config) ->
%% 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) ->
- application:start(odbc),
- [{tableName, odbc_test_lib:unique_table_name()} | Config].
-
+init_per_suite(Config) when is_list(Config) ->
+ case odbc_test_lib:skip() of
+ true ->
+ {skip, "ODBC not supported"};
+ false ->
+ case (catch odbc:start()) of
+ ok ->
+ [{tableName, odbc_test_lib:unique_table_name()}| Config];
+ _ ->
+ {skip, "ODBC not startable"}
+ end
+ end.
%%--------------------------------------------------------------------
%% Function: end_per_suite(Config) -> _
%% Config - [tuple()]
@@ -117,22 +147,81 @@ end_per_suite(_Config) ->
%% 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_testcase(Case, Config) when Case == varchar_upper_limit;
+ Case == binary_varchar_upper_limit;
+ Case == varchar_no_padding;
+ Case == binary_varchar_no_padding ->
+ case is_fixed_upper_limit(?RDBMS) of
+ true ->
+ common_init_per_testcase(Case, Config);
+ false ->
+ {skip, "Upper limit is not fixed in" ++ atom_to_list(?RDBMS)}
+ end;
+
+init_per_testcase(text_upper_limit, _Config) ->
+ {skip, "Consumes too much resources"};
+
+init_per_testcase(Case, Config) when Case == bit_true; Case == bit_false ->
+ case is_supported_bit(?RDBMS) of
+ true ->
+ common_init_per_testcase(Case, Config);
+ false ->
+ {skip, "Not supported by driver"}
+ end;
+
+init_per_testcase(param_insert_tiny_int = Case, Config) ->
+ case is_supported_tinyint(?RDBMS) of
+ true ->
+ common_init_per_testcase(Case, Config);
+ false ->
+ {skip, "Not supported by driver"}
+ end;
+
+init_per_testcase(Case, Config) when Case == nchar;
+ Case == nvarchar ->
+ case ?RDBMS of
+ sqlserver ->
+ common_init_per_testcase(Case, Config);
+ _ ->
+ {skip, "Not supported by driver"}
+ end;
+
init_per_testcase(Case, Config) ->
+ common_init_per_testcase(Case, Config).
+
+common_init_per_testcase(Case, Config) ->
+ PlatformOptions = odbc_test_lib:platform_options(),
case atom_to_list(Case) of
"binary" ++ _ ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{binary_strings, on}]);
- "unicode" ->
+ [{binary_strings, on}] ++ PlatformOptions);
+ LCase when LCase == "utf8";
+ LCase == "nchar";
+ LCase == "nvarchar" ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{binary_strings, on}]);
+ [{binary_strings, on}] ++ PlatformOptions);
_ ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), [])
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), PlatformOptions)
end,
+ odbc_test_lib:strict(Ref, ?RDBMS),
Dog = test_server:timetrap(?default_timeout),
Temp = lists:keydelete(connection_ref, 1, Config),
NewConfig = lists:keydelete(watchdog, 1, Temp),
[{watchdog, Dog}, {connection_ref, Ref} | NewConfig].
+is_fixed_upper_limit(mysql) ->
+ false;
+is_fixed_upper_limit(_) ->
+ true.
+is_supported_tinyint(sqlserver) ->
+ true;
+is_supported_tinyint(_) ->
+ false.
+is_supported_bit(sqlserver) ->
+ true;
+is_supported_bit(_) ->
+ false.
+
%%--------------------------------------------------------------------
%% Function: end_per_testcase(Case, Config) -> _
%% Case - atom()
@@ -146,7 +235,7 @@ end_per_testcase(_TestCase, Config) ->
ok = odbc:disconnect(Ref),
%% Clean up if needed
Table = ?config(tableName, Config),
- {ok, NewRef} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, NewRef} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
odbc:sql_query(NewRef, "DROP TABLE " ++ Table),
odbc:disconnect(NewRef),
Dog = ?config(watchdog, Config),
@@ -169,18 +258,18 @@ char_fixed_lower_limit(Config) when is_list(Config) ->
{error, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
- ?RDBMS:create_fixed_char_table(
+ ?RDBMS:create_fixed_char_table(
(?RDBMS:fixed_char_min() - 1))),
%% Lower limit
{updated, _} = % Value == 0 || -1 driver dependent!
odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
- ?RDBMS:create_fixed_char_table(
- ?RDBMS:fixed_char_min())),
+ ?RDBMS:create_fixed_char_table(
+ ?RDBMS:fixed_char_min())),
%% Right length data
{updated, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- "'" ++ string:chars($a, ?RDBMS:fixed_char_min())
+ "'" ++ string:chars($a, ?RDBMS:fixed_char_min())
++ "')"),
%% Select data
{selected, Fields,[{"a"}]} =
@@ -191,11 +280,11 @@ char_fixed_lower_limit(Config) when is_list(Config) ->
%% Too long data
{error, _} =
odbc:sql_query(Ref,"INSERT INTO " ++ Table ++" VALUES(" ++
- "'" ++ string:chars($a,
- (?RDBMS:fixed_char_min()
- + 1))
- ++ "')"),
- ok.
+ "'" ++ string:chars($a,
+ (?RDBMS:fixed_char_min()
+ + 1))
+ ++ "')").
+
%%-------------------------------------------------------------------------
char_fixed_upper_limit(doc) ->
@@ -243,8 +332,7 @@ char_fixed_upper_limit(Config) when is_list(Config) ->
{error, _} =
odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
?RDBMS:create_fixed_char_table(
- (?RDBMS:fixed_char_max() + 1))),
- ok
+ (?RDBMS:fixed_char_max() + 1)))
end.
%%-------------------------------------------------------------------------
@@ -261,20 +349,20 @@ char_fixed_padding(Config) when is_list(Config) ->
%% Data should be padded with blanks
{updated, _} = % Value == 0 || -1 driver dependent!
odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
- ?RDBMS:create_fixed_char_table(
- ?RDBMS:fixed_char_max())),
+ ?RDBMS:create_fixed_char_table(
+ ?RDBMS:fixed_char_max())),
- {updated, _} =
+ {updated, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- "'" ++ string:chars($a,
- ?RDBMS:fixed_char_min())
+ "'" ++ string:chars($a,
+ ?RDBMS:fixed_char_min())
++ "')"),
{selected, Fields, [{CharStr}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
true = length(CharStr) == ?RDBMS:fixed_char_max(),
- ["FIELD"] = odbc_test_lib:to_upper(Fields),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields).
+
%%-------------------------------------------------------------------------
varchar_lower_limit(doc) ->
@@ -287,33 +375,33 @@ varchar_lower_limit(Config) when is_list(Config) ->
%% Below limit
{error, _} =
- odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
- ?RDBMS:create_var_char_table(
- ?RDBMS:var_char_min() - 1)),
+ odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
+ ?RDBMS:create_var_char_table(
+ ?RDBMS:var_char_min() - 1)),
%% Lower limit
{updated, _} = % Value == 0 || -1 driver dependent!
odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
- ?RDBMS:create_var_char_table(
- ?RDBMS:var_char_min())),
+ ?RDBMS:create_var_char_table(
+ ?RDBMS:var_char_min())),
+
+ Str = string:chars($a, ?RDBMS:var_char_min()),
%% Right length data
{updated, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- "'" ++ string:chars($a, ?RDBMS:var_char_min())
- ++ "')"),
+ "'" ++ Str ++ "')"),
%% Select data
- {selected, Fields, [{"a"}]} =
+ {selected, Fields, [{Str}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
["FIELD"] = odbc_test_lib:to_upper(Fields),
- %% Too long data
- {error, _} =
- odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- "'" ++ string:chars($a,
- (?RDBMS:var_char_min()+1))
- ++ "')"),
- ok.
+ %% Too long datae
+ {error, _} =
+ odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
+ "'" ++ string:chars($a,
+ (?RDBMS:var_char_min()+1))
+ ++ "')").
%%-------------------------------------------------------------------------
@@ -389,8 +477,7 @@ varchar_no_padding(Config) when is_list(Config) ->
{selected, Fields, [{CharStr}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
true = length(CharStr) /= ?RDBMS:var_char_max(),
- ["FIELD"] = odbc_test_lib:to_upper(Fields),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields).
%%-------------------------------------------------------------------------
@@ -413,8 +500,7 @@ text_lower_limit(Config) when is_list(Config) ->
{selected, Fields, [{"a"}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ["FIELD"] = odbc_test_lib:to_upper(Fields),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields).
%%-------------------------------------------------------------------------
@@ -444,8 +530,7 @@ text_upper_limit(Config) when is_list(Config) ->
%% {error, _} =
%% odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
%% "'" ++ string:chars($a, (?RDBMS:text_max()+1))
-%% ++ "')"),
-%% ok.
+%% ++ "')").
%%-------------------------------------------------------------------------
@@ -469,13 +554,18 @@ binary_char_fixed_lower_limit(Config) when is_list(Config) ->
?RDBMS:create_fixed_char_table(
?RDBMS:fixed_char_min())),
+ Str = string:chars($a, ?RDBMS:fixed_char_min()),
+
%% Right length data
{updated, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- "'" ++ string:chars($a, ?RDBMS:fixed_char_min())
+ "'" ++ Str
++ "')"),
+
+ Bin = list_to_binary(Str),
+
%% Select data
- {selected, Fields,[{<<"a">>}]} =
+ {selected, Fields,[{Bin}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
["FIELD"] = odbc_test_lib:to_upper(Fields),
@@ -486,8 +576,7 @@ binary_char_fixed_lower_limit(Config) when is_list(Config) ->
"'" ++ string:chars($a,
(?RDBMS:fixed_char_min()
+ 1))
- ++ "')"),
- ok.
+ ++ "')").
%%-------------------------------------------------------------------------
binary_char_fixed_upper_limit(doc) ->
@@ -565,8 +654,8 @@ binary_char_fixed_padding(Config) when is_list(Config) ->
{selected, Fields, [{CharBin}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
true = size(CharBin) == ?RDBMS:fixed_char_max(),
- ["FIELD"] = odbc_test_lib:to_upper(Fields),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields).
+
%%-------------------------------------------------------------------------
binary_varchar_lower_limit(doc) ->
@@ -588,13 +677,17 @@ binary_varchar_lower_limit(Config) when is_list(Config) ->
?RDBMS:create_var_char_table(
?RDBMS:var_char_min())),
+ Str = string:chars($a, ?RDBMS:var_char_min()),
+
%% Right length data
{updated, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- "'" ++ string:chars($a, ?RDBMS:var_char_min())
+ "'" ++ Str
++ "')"),
+ BinStr = list_to_binary(Str),
+
%% Select data
- {selected, Fields, [{<<"a">>}]} =
+ {selected, Fields, [{BinStr}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
["FIELD"] = odbc_test_lib:to_upper(Fields),
@@ -604,8 +697,7 @@ binary_varchar_lower_limit(Config) when is_list(Config) ->
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ string:chars($a,
(?RDBMS:var_char_min()+1))
- ++ "')"),
- ok.
+ ++ "')").
%%-------------------------------------------------------------------------
@@ -654,8 +746,7 @@ binary_varchar_upper_limit(Config) when is_list(Config) ->
{error, _} =
odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
?RDBMS:create_var_char_table(
- (?RDBMS:var_char_max() + 1))),
- ok
+ (?RDBMS:var_char_max() + 1)))
end.
%%-------------------------------------------------------------------------
@@ -681,8 +772,7 @@ binary_varchar_no_padding(Config) when is_list(Config) ->
{selected, Fields, [{CharBin}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
true = size(CharBin) /= ?RDBMS:var_char_max(),
- ["FIELD"] = odbc_test_lib:to_upper(Fields),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields).
%%-------------------------------------------------------------------------
@@ -705,8 +795,7 @@ binary_text_lower_limit(Config) when is_list(Config) ->
{selected, Fields, [{<<"a">>}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ["FIELD"] = odbc_test_lib:to_upper(Fields),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields).
%%-------------------------------------------------------------------------
@@ -736,11 +825,7 @@ binary_text_upper_limit(Config) when is_list(Config) ->
%% {error, _} =
%% odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
%% "'" ++ string:chars($a, (?RDBMS:text_max()+1))
-%% ++ "')"),
-%% ok.
-
-
-%%-------------------------------------------------------------------------
+%% ++ "')").
%%-------------------------------------------------------------------------
@@ -774,8 +859,7 @@ tiny_int_lower_limit(Config) when is_list(Config) ->
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(?RDBMS:tiny_int_min()
- 1)
- ++ "')"),
- ok
+ ++ "')")
end.
%%-------------------------------------------------------------------------
@@ -809,8 +893,7 @@ tiny_int_upper_limit(Config) when is_list(Config) ->
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(?RDBMS:tiny_int_max()
+ 1)
- ++ "')"),
- ok
+ ++ "')")
end.
%%-------------------------------------------------------------------------
@@ -840,8 +923,7 @@ small_int_lower_limit(Config) when is_list(Config) ->
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(?RDBMS:small_int_min()
- 1)
- ++ "')"),
- ok.
+ ++ "')").
%%-------------------------------------------------------------------------
@@ -870,8 +952,7 @@ small_int_upper_limit(Config) when is_list(Config) ->
odbc:sql_query(Ref,"INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(?RDBMS:small_int_max()
+ 1)
- ++ "')"),
- ok.
+ ++ "')").
%%-------------------------------------------------------------------------
int_lower_limit(doc) ->
@@ -898,8 +979,7 @@ int_lower_limit(Config) when is_list(Config) ->
{error, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(?RDBMS:int_min() - 1)
- ++ "')"),
- ok.
+ ++ "')").
%%-------------------------------------------------------------------------
@@ -927,8 +1007,7 @@ int_upper_limit(Config) when is_list(Config) ->
{error, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(?RDBMS:int_max() + 1)
- ++ "')"),
- ok.
+ ++ "')").
%%-------------------------------------------------------------------------
@@ -957,8 +1036,7 @@ big_int_lower_limit(Config) when is_list(Config) ->
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(?RDBMS:big_int_min()
- 1)
- ++ "')"),
- ok.
+ ++ "')").
%%-------------------------------------------------------------------------
@@ -987,8 +1065,7 @@ big_int_upper_limit(Config) when is_list(Config) ->
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(?RDBMS:big_int_max()
+ 1)
- ++ "')"),
- ok.
+ ++ "')").
%%-------------------------------------------------------------------------
bit_false(doc) ->
@@ -1020,8 +1097,7 @@ bit_false(Config) when is_list(Config) ->
{error, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(-1)
- ++ "')"),
- ok
+ ++ "')")
end.
%%-------------------------------------------------------------------------
@@ -1056,14 +1132,10 @@ bit_true(Config) when is_list(Config) ->
{error, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
"'" ++ integer_to_list(-1)
- ++ "')"),
- ok
+ ++ "')")
end.
%%-------------------------------------------------------------------------
-
-
-%%-------------------------------------------------------------------------
float_lower_limit(doc) ->
[""];
float_lower_limit(suite) ->
@@ -1073,44 +1145,45 @@ float_lower_limit(Config) when is_list(Config) ->
Ref = ?config(connection_ref, Config),
Table = ?config(tableName, Config),
- {updated, _} = % Value == 0 || -1 driver dependent!
- odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
- ?RDBMS:create_float_table()),
-
- {updated, _} =
- odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- "'" ++ float_to_list(
- ?RDBMS:float_min())
- ++ "')"),
- {selected,[_ColName],[{MinFloat}]} =
- odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
-
- true = ?RDBMS:float_min() == MinFloat,
-
case ?RDBMS of
- oracle ->
- {updated, _} = % Value == 0 || -1 driver dependent!
- odbc:sql_query(Ref, "DROP TABLE " ++ Table),
-
+ mysql ->
+ {skip, "Not clearly defined in MYSQL"};
+ _ ->
{updated, _} = % Value == 0 || -1 driver dependent!
odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
- ?RDBMS:create_float_table()),
+ ?RDBMS:create_float_table()),
{updated, _} =
- odbc:sql_query(Ref,
- "INSERT INTO " ++ Table ++" VALUES(" ++
- ?RDBMS:float_underflow() ++ ")"),
-
- SelectResult = ?RDBMS:float_zero_selected(),
- SelectResult =
- odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table);
- _ ->
- {error, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- ?RDBMS:float_underflow() ++ ")")
- end,
- ok.
+ "'" ++ float_to_list(
+ ?RDBMS:float_min())
+ ++ "')"),
+ {selected,[_ColName],[{MinFloat}]} =
+ odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
+ true = ?RDBMS:float_min() == MinFloat,
+
+ case ?RDBMS of
+ oracle ->
+ {updated, _} = % Value == 0 || -1 driver dependent!
+ odbc:sql_query(Ref, "DROP TABLE " ++ Table),
+
+ {updated, _} = % Value == 0 || -1 driver dependent!
+ odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
+ ?RDBMS:create_float_table()),
+ {updated, _} =
+ odbc:sql_query(Ref,
+ "INSERT INTO " ++ Table ++" VALUES(" ++
+ ?RDBMS:float_underflow() ++ ")"),
+ SelectResult = ?RDBMS:float_zero_selected(),
+ SelectResult =
+ odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table);
+ _ ->
+ {error, _} =
+ odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
+ ?RDBMS:float_underflow() ++ ")")
+ end
+ end.
%%-------------------------------------------------------------------------
float_upper_limit(doc) ->
@@ -1121,26 +1194,28 @@ float_upper_limit(Config) when is_list(Config) ->
Ref = ?config(connection_ref, Config),
Table = ?config(tableName, Config),
- {updated, _} = % Value == 0 || -1 driver dependent!
- odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
- ?RDBMS:create_float_table()),
-
- {updated, _} =
- odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- "'" ++ float_to_list(
- ?RDBMS:float_max())
- ++ "')"),
-
+ case ?RDBMS of
+ mysql ->
+ {skip, "Not clearly defined in MYSQL"};
+ _->
+ {updated, _} = % Value == 0 || -1 driver dependent!
+ odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
+ ?RDBMS:create_float_table()),
- {selected,[_ColName],[{MaxFloat}]}
- = odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
+ {updated, _} =
+ odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
+ "'" ++ float_to_list(
+ ?RDBMS:float_max())
+ ++ "')"),
+ {selected,[_ColName],[{MaxFloat}]}
+ = odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- true = ?RDBMS:float_max() == MaxFloat,
+ true = ?RDBMS:float_max() == MaxFloat,
- {error, _} =
- odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
- ?RDBMS:float_overflow() ++ ")"),
- ok.
+ {error, _} =
+ odbc:sql_query(Ref, "INSERT INTO " ++ Table ++" VALUES(" ++
+ ?RDBMS:float_overflow() ++ ")")
+ end.
%%-------------------------------------------------------------------------
float_zero(doc) ->
@@ -1160,8 +1235,7 @@ float_zero(Config) when is_list(Config) ->
SelectResult = ?RDBMS:float_zero_selected(),
SelectResult =
- odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ok.
+ odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table).
%%-------------------------------------------------------------------------
real_zero(doc) ->
["Test the real value zero."];
@@ -1185,10 +1259,8 @@ real_zero(Config) when is_list(Config) ->
SelectResult = ?RDBMS:real_zero_selected(),
SelectResult =
- odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ok
+ odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table)
end.
-%%-------------------------------------------------------------------------
%%------------------------------------------------------------------------
dec_long(doc) ->
[""];
@@ -1207,8 +1279,7 @@ dec_long(Config) when is_list(Config) ->
{selected, Fields, [{2}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ["FIELD"] = odbc_test_lib:to_upper(Fields),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields).
%%------------------------------------------------------------------------
dec_double(doc) ->
[""];
@@ -1255,8 +1326,7 @@ dec_double(Config) when is_list(Config) ->
{selected, Fields2, [{1.60000}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ["FIELD"] = odbc_test_lib:to_upper(Fields2),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields2).
%%------------------------------------------------------------------------
dec_bignum(doc) ->
@@ -1289,8 +1359,7 @@ dec_bignum(Config) when is_list(Config) ->
{selected, Fields1, [{"1.6"}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ["FIELD"] = odbc_test_lib:to_upper(Fields1),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields1).
%%------------------------------------------------------------------------
num_long(doc) ->
[""];
@@ -1309,8 +1378,7 @@ num_long(Config) when is_list(Config) ->
{selected, Fields, [{2}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ["FIELD"] = odbc_test_lib:to_upper(Fields),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields).
%%------------------------------------------------------------------------
num_double(doc) ->
[""];
@@ -1356,8 +1424,7 @@ num_double(Config) when is_list(Config) ->
{selected, Fields2, [{1.6000}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ["FIELD"] = odbc_test_lib:to_upper(Fields2),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields2).
%%------------------------------------------------------------------------
num_bignum(doc) ->
[""];
@@ -1389,21 +1456,19 @@ num_bignum(Config) when is_list(Config) ->
{selected, Fields1, [{"1.6"}]} =
odbc:sql_query(Ref,"SELECT FIELD FROM " ++ Table),
- ["FIELD"] = odbc_test_lib:to_upper(Fields1),
- ok.
+ ["FIELD"] = odbc_test_lib:to_upper(Fields1).
%%------------------------------------------------------------------------
-unicode(doc) ->
+utf8(doc) ->
["Test unicode support"];
-unicode(suit) ->
+utf8(suit) ->
[];
-unicode(Config) when is_list(Config) ->
+utf8(Config) when is_list(Config) ->
Ref = ?config(connection_ref, Config),
Table = ?config(tableName, Config),
- {updated, _} = % Value == 0 || -1 driver dependent!
- odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
- ?RDBMS:create_unicode_table()),
+ odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++ "(FIELD text)"),
+
Latin1Data = ["���������",
"testasdf",
"Row 3",
@@ -1416,39 +1481,7 @@ unicode(Config) when is_list(Config) ->
"Row 10",
"Row 11",
"Row 12"],
-
- case ?RDBMS of
- sqlserver ->
- w_char_support_win(Ref, Table, Latin1Data);
- postgres ->
- direct_utf8(Ref, Table, Latin1Data);
- oracle ->
- {skip, "not currently supported"}
- end.
-
-w_char_support_win(Ref, Table, Latin1Data) ->
- UnicodeIn = lists:map(fun(S) ->
- unicode:characters_to_binary(S,latin1,{utf16,little})
- end,
- Latin1Data),
-
- test_server:format("UnicodeIn (utf 16): ~p ~n",[UnicodeIn]),
- {updated, _} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++ "(FIELD) values(?)",
- [{{sql_wvarchar,50},UnicodeIn}]),
-
- {selected,_,UnicodeOut} = odbc:sql_query(Ref,"SELECT * FROM " ++ Table),
-
- test_server:format("UnicodeOut: ~p~n", [UnicodeOut]),
-
- Result = lists:map(fun({Unicode}) ->
- unicode:characters_to_list(Unicode,{utf16,little})
- end,
- UnicodeOut),
- Latin1Data = Result.
-
-
-direct_utf8(Ref, Table, Latin1Data) ->
UnicodeIn = lists:map(fun(String) ->
unicode:characters_to_binary(String,latin1,utf8)
end,
@@ -1469,6 +1502,37 @@ direct_utf8(Ref, Table, Latin1Data) ->
test_server:format("Result: ~p ~n", [Result]),
Latin1Data = Result.
+%%------------------------------------------------------------------------
+
+nchar(doc) ->
+ ["Test unicode nchar support in sqlserver"];
+nchar(suit) ->
+ [];
+nchar(Config) when is_list(Config) ->
+ Ref = ?config(connection_ref, Config),
+ Table = ?config(tableName, Config),
+
+ {updated, _} = % Value == 0 || -1 driver dependent!
+ odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
+ "(FIELD nchar(50))"),
+
+ w_char_support(Ref, Table, sql_wvarchar, 50).
+
+%%------------------------------------------------------------------------
+
+nvarchar(doc) ->
+ ["Test 'unicode' nvarchar support"];
+nvarchar(suit) ->
+ [];
+nvarchar(Config) when is_list(Config) ->
+ Ref = ?config(connection_ref, Config),
+ Table = ?config(tableName, Config),
+
+ {updated, _} = % Value == 0 || -1 driver dependent!
+ odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
+ "(FIELD nvarchar(50))"),
+
+ w_char_support(Ref, Table, sql_wlongvarchar, 50).
%%------------------------------------------------------------------------
timestamp(doc) ->
@@ -1497,3 +1561,43 @@ timestamp(Config) when is_list(Config) ->
TimeStamps = lists:map(fun(Value) -> {Value} end, Data),
{selected,_, TimeStamps} = odbc:sql_query(Ref, "SELECT * FROM " ++ Table).
+%%------------------------------------------------------------------------
+
+w_char_support(Ref, Table, CharType, Size) ->
+ Latin1Data = ["���������",
+ "testasdf",
+ "Row 3",
+ "Row 4",
+ "Row 5",
+ "Row 6",
+ "Row 7",
+ "Row 8",
+ "Row 9",
+ "Row 10",
+ "Row 11",
+ "Row 12"],
+
+ UnicodeIn = lists:map(fun(S) ->
+ unicode:characters_to_binary(S,latin1,{utf16,little})
+ end,
+ Latin1Data),
+
+ test_server:format("UnicodeIn (utf 16): ~p ~n",[UnicodeIn]),
+
+ {updated, _} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++ "(FIELD) values(?)",
+ [{{CharType, Size},UnicodeIn}]),
+
+ {selected,_,UnicodeOut} = odbc:sql_query(Ref,"SELECT * FROM " ++ Table),
+
+ test_server:format("UnicodeOut: ~p~n", [UnicodeOut]),
+
+ PadResult = lists:map(fun({Unicode}) ->
+ unicode:characters_to_list(Unicode,{utf16,little})
+ end,
+ UnicodeOut),
+
+ test_server:format("Result: ~p~n", [PadResult]),
+
+ Result = lists:map(fun(Str) -> string:strip(Str) end, PadResult),
+
+ Latin1Data = Result.
diff --git a/lib/odbc/test/odbc_query_SUITE.erl b/lib/odbc/test/odbc_query_SUITE.erl
index 8b8d1e7a40..1852678b4b 100644
--- a/lib/odbc/test/odbc_query_SUITE.erl
+++ b/lib/odbc/test/odbc_query_SUITE.erl
@@ -43,19 +43,22 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
case odbc_test_lib:odbc_check() of
ok ->
- [sql_query, first, last, next, prev, select_count,
+ [sql_query, next, {group, scrollable_cursors}, select_count,
select_next, select_relative, select_absolute,
create_table_twice, delete_table_twice, duplicate_key,
not_connection_owner, no_result_set, query_error,
- multiple_select_result_sets, multiple_mix_result_sets,
- multiple_result_sets_error,
+ {group, multiple_result_sets},
{group, parameterized_queries}, {group, describe_table},
delete_nonexisting_row];
Other -> {skip, Other}
end.
groups() ->
- [{parameterized_queries, [],
+ [{multiple_result_sets, [], [multiple_select_result_sets,
+ multiple_mix_result_sets,
+ multiple_result_sets_error]},
+ {scrollable_cursors, [], [first, last, prev]},
+ {parameterized_queries, [],
[{group, param_integers}, param_insert_decimal,
param_insert_numeric, {group, param_insert_string},
param_insert_float, param_insert_real,
@@ -72,15 +75,27 @@ groups() ->
[describe_integer, describe_string, describe_floating,
describe_dec_num, describe_no_such_table]}].
-init_per_group(_GroupName, Config) ->
+init_per_group(multiple_result_sets, Config) ->
+ case is_supported_multiple_resultsets(?RDBMS) of
+ true ->
+ Config;
+ false ->
+ {skip, "Not supported by " ++ atom_to_list(?RDBMS) ++ "driver"}
+ end;
+init_per_group(scrollable_cursors, Config) ->
+ case proplists:get_value(scrollable_cursors, odbc_test_lib:platform_options()) of
+ off ->
+ {skip, "Not supported by driver"};
+ _ ->
+ Config
+ end;
+
+init_per_group(_,Config) ->
Config.
end_per_group(_GroupName, Config) ->
Config.
-
-
-
%%--------------------------------------------------------------------
%% Function: init_per_suite(Config) -> Config
%% Config - [tuple()]
@@ -91,8 +106,17 @@ end_per_group(_GroupName, Config) ->
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_suite(Config) when is_list(Config) ->
- application:start(odbc),
- [{tableName, odbc_test_lib:unique_table_name()}| Config].
+ case odbc_test_lib:skip() of
+ true ->
+ {skip, "ODBC not supported"};
+ false ->
+ case (catch odbc:start()) of
+ ok ->
+ [{tableName, odbc_test_lib:unique_table_name()}| Config];
+ _ ->
+ {skip, "ODBC not startable"}
+ end
+ end.
%%--------------------------------------------------------------------
%% Function: end_per_suite(Config) -> _
@@ -117,7 +141,8 @@ end_per_suite(_Config) ->
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_testcase(_Case, Config) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
+ odbc_test_lib:strict(Ref, ?RDBMS),
Dog = test_server:timetrap(?default_timeout),
Temp = lists:keydelete(connection_ref, 1, Config),
NewConfig = lists:keydelete(watchdog, 1, Temp),
@@ -136,7 +161,7 @@ end_per_testcase(_Case, Config) ->
ok = odbc:disconnect(Ref),
%% Clean up if needed
Table = ?config(tableName, Config),
- {ok, NewRef} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, NewRef} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
odbc:sql_query(NewRef, "DROP TABLE " ++ Table),
odbc:disconnect(NewRef),
Dog = ?config(watchdog, Config),
@@ -663,9 +688,6 @@ multiple_result_sets_error(Config) when is_list(Config) ->
end.
%%-------------------------------------------------------------------------
-
-%%-------------------------------------------------------------------------
-%%-------------------------------------------------------------------------
param_insert_tiny_int(doc)->
["Test insertion of tiny ints by parameterized queries."];
param_insert_tiny_int(suite) ->
@@ -901,8 +923,6 @@ param_insert_numeric(Config) when is_list(Config) ->
ok.
%%-------------------------------------------------------------------------
-
-%%-------------------------------------------------------------------------
param_insert_char(doc)->
["Test insertion of fixed length string by parameterized queries."];
param_insert_char(suite) ->
@@ -1325,8 +1345,6 @@ param_select(Config) when is_list(Config) ->
ok.
%%-------------------------------------------------------------------------
-
-%%-------------------------------------------------------------------------
describe_integer(doc) ->
["Test describe_table/[2,3] for integer columns."];
describe_integer(suite) ->
@@ -1338,7 +1356,7 @@ describe_integer(Config) when is_list(Config) ->
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
- " (int1 SMALLINT, int2 INT, int3 INTEGER)"),
+ " (myint1 SMALLINT, myint2 INT, myint3 INTEGER)"),
Decs = ?RDBMS:describe_integer(),
%% Make sure to test timeout clause
@@ -1399,7 +1417,7 @@ describe_dec_num(Config) when is_list(Config) ->
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
- " (dec DECIMAL(9,3), num NUMERIC(9,2))"),
+ " (mydec DECIMAL(9,3), mynum NUMERIC(9,2))"),
Decs = ?RDBMS:describe_dec_num(),
@@ -1451,3 +1469,7 @@ is_driver_error(Error) ->
false ->
test_server:fail(Error)
end.
+is_supported_multiple_resultsets(sqlserver) ->
+ true;
+is_supported_multiple_resultsets(_) ->
+ false.
diff --git a/lib/odbc/test/odbc_start_SUITE.erl b/lib/odbc/test/odbc_start_SUITE.erl
index 65b990133f..e3a3440559 100644
--- a/lib/odbc/test/odbc_start_SUITE.erl
+++ b/lib/odbc/test/odbc_start_SUITE.erl
@@ -39,11 +39,18 @@
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- case code:which(odbc) of
- non_existing ->
- {skip, "No ODBC built"};
- _ ->
- [{tableName, odbc_test_lib:unique_table_name()} | Config]
+ case odbc_test_lib:skip() of
+ true ->
+ {skip, "ODBC not supported"};
+ false ->
+ case code:which(odbc) of
+ non_existing ->
+ {skip, "No ODBC built"};
+ _ ->
+ %% Make sure odbc is not already started
+ odbc:stop(),
+ [{tableName, odbc_test_lib:unique_table_name()} | Config]
+ end
end.
%%--------------------------------------------------------------------
@@ -125,14 +132,16 @@ start(doc) ->
start(suite) ->
[];
start(Config) when is_list(Config) ->
- {error,odbc_not_started} = odbc:connect(?RDBMS:connection_string(), []),
+ PlatformOptions = odbc_test_lib:platform_options(),
+ {error,odbc_not_started} = odbc:connect(?RDBMS:connection_string(),
+ PlatformOptions),
odbc:start(),
- case odbc:connect(?RDBMS:connection_string(), []) of
+ case odbc:connect(?RDBMS:connection_string(), PlatformOptions) of
{ok, Ref0} ->
ok = odbc:disconnect(Ref0),
odbc:stop(),
{error,odbc_not_started} =
- odbc:connect(?RDBMS:connection_string(), []),
+ odbc:connect(?RDBMS:connection_string(), PlatformOptions),
start_odbc(transient),
start_odbc(permanent);
{error, odbc_not_started} ->
@@ -144,7 +153,7 @@ start(Config) when is_list(Config) ->
start_odbc(Type) ->
ok = odbc:start(Type),
- case odbc:connect(?RDBMS:connection_string(), []) of
+ case odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()) of
{ok, Ref} ->
ok = odbc:disconnect(Ref),
odbc:stop();
diff --git a/lib/odbc/test/odbc_test.hrl b/lib/odbc/test/odbc_test.hrl
index 87f50043db..f7bb338a7f 100644
--- a/lib/odbc/test/odbc_test.hrl
+++ b/lib/odbc/test/odbc_test.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The 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,9 +25,16 @@
-define(RDBMS, case os:type() of
{unix, sunos} ->
- postgres;
+ mysql;
{unix,linux} ->
- postgres;
+ case erlang:system_info({wordsize, external}) of
+ 4 ->
+ mysql;
+ _ ->
+ postgres
+ end;
+ {unix, darwin} ->
+ mysql;
{win32, _} ->
sqlserver
end).
diff --git a/lib/odbc/test/odbc_test_lib.erl b/lib/odbc/test/odbc_test_lib.erl
index 012eb96e43..a8439d5fb6 100644
--- a/lib/odbc/test/odbc_test_lib.erl
+++ b/lib/odbc/test/odbc_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -36,29 +36,25 @@ match_float(Float, Match, Delta) ->
(Float < Match + Delta) and (Float > Match - Delta).
odbc_check() ->
- case erlang:system_info(wordsize) of
- 4 ->
- case test_server:os_type() of
- {unix, sunos} ->
- ok;
- {unix, linux} ->
- ok;
- {win32, _} ->
+ case os:type() of
+ {unix,darwin} ->
+ lists:flatten(
+ io_lib:format("Currently we have no working drivers for MAC",
+ []));
+ _ ->
+ case erlang:system_info({wordsize, external}) of
+ 4 ->
ok;
Other ->
- lists:flatten(
- io_lib:format("Platform not supported: ~w",
- [Other]))
- end;
- Other ->
- case os:type() of
- {unix, linux} ->
- ok;
- Platform ->
- lists:flatten(
- io_lib:format("Word on platform ~w size"
- " ~w not supported", [Other,
- Platform]))
+ case os:type() of
+ {unix, linux} ->
+ ok;
+ Platform ->
+ lists:flatten(
+ io_lib:format("Word on platform ~w size"
+ " ~w not supported", [Other,
+ Platform]))
+ end
end
end.
@@ -75,3 +71,46 @@ check_row_count(Expected, Count) ->
to_upper(List) ->
lists:map(fun(Str) -> string:to_upper(Str) end, List).
+
+strict(Ref, mysql) ->
+ odbc:sql_query(Ref, "SET sql_mode='STRICT_ALL_TABLES,STRICT_TRANS_TABLES';");
+strict(_,_) ->
+ ok.
+
+platform_options() ->
+ [].
+
+skip() ->
+ case os:type() of
+ {unix, linux} ->
+ Issue = linux_issue(),
+ is_sles9(Issue);
+ {unix, sunos} ->
+ not supported_solaris();
+ _ ->
+ false
+ end.
+
+supported_solaris() ->
+ case os:version() of
+ {_,10,_} ->
+ true;
+ _ ->
+ false
+ end.
+
+linux_issue() ->
+ {ok, Binary} = file:read_file("/etc/issue"),
+ string:tokens(binary_to_list(Binary), " ").
+
+is_sles11(IssueTokens) ->
+ lists:member("11", IssueTokens).
+
+is_sles10(IssueTokens) ->
+ lists:member("10", IssueTokens).
+
+is_sles9(IssueTokens) ->
+ lists:member("9", IssueTokens).
+
+is_ubuntu(IssueTokens) ->
+ lists:member("Ubuntu", IssueTokens).
diff --git a/lib/odbc/test/oracle.erl b/lib/odbc/test/oracle.erl
index ebf6dbb6bf..d74863d8c1 100644
--- a/lib/odbc/test/oracle.erl
+++ b/lib/odbc/test/oracle.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The 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,10 +108,6 @@ create_text_table() ->
" (FIELD long)". %Oracle long is variable length char data
%-------------------------------------------------------------------------
-create_unicode_table() ->
- " (FIELD nvarchar(50))".
-
-%-------------------------------------------------------------------------
create_timestamp_table() ->
" (FIELD DATETIME)".
@@ -231,8 +227,8 @@ param_select() ->
%-------------------------------------------------------------------------
describe_integer() ->
- {ok,[{"INT1",{sql_decimal,38,0}},{"INT2",{sql_decimal,38,0}},
- {"INT3",{sql_decimal,38,0}}]}.
+ {ok,[{"MYINT1",{sql_decimal,38,0}},{"MYINT2",{sql_decimal,38,0}},
+ {"MYINT3",{sql_decimal,38,0}}]}.
describe_string() ->
{ok,[{"STR1",{sql_char,10}},
@@ -243,4 +239,4 @@ describe_string() ->
describe_floating() ->
{ok,[{"F",sql_double},{"R",sql_double},{"D",sql_double}]}.
describe_dec_num() ->
- {ok,[{"DEC",{sql_decimal,9,3}},{"NUM",{sql_decimal,9,2}}]}.
+ {ok,[{"MYDEC",{sql_decimal,9,3}},{"MYNUM",{sql_decimal,9,2}}]}.
diff --git a/lib/odbc/test/postgres.erl b/lib/odbc/test/postgres.erl
index 169ca26e43..d564dbd5ff 100644
--- a/lib/odbc/test/postgres.erl
+++ b/lib/odbc/test/postgres.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
%%
%% The 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,7 +30,7 @@ connection_string() ->
{unix, sunos} ->
"DSN=Postgres;UID=odbctest";
{unix, linux} ->
- Size = erlang:system_info(wordsize),
+ Size = erlang:system_info({wordsize, external}),
linux_dist_connection_string(Size)
end.
@@ -43,7 +43,12 @@ linux_dist_connection_string(4) ->
end;
linux_dist_connection_string(_) ->
- "DSN=PostgresLinux64;UID=odbctest".
+ case linux_dist() of
+ "ubuntu" ->
+ "DSN=PostgresLinux64Ubuntu;UID=odbctest";
+ _ ->
+ "DSN=PostgresLinux64;UID=odbctest"
+ end.
linux_dist() ->
case file:read_file("/etc/issue") of
@@ -135,10 +140,6 @@ create_text_table() ->
" (FIELD text)".
%-------------------------------------------------------------------------
-create_unicode_table() ->
- " (FIELD text)".
-
-%-------------------------------------------------------------------------
create_timestamp_table() ->
" (FIELD TIMESTAMP)".
@@ -275,9 +276,9 @@ param_select() ->
%-------------------------------------------------------------------------
describe_integer() ->
- {ok,[{"int1",sql_smallint},
- {"int2",sql_integer},
- {"int3",sql_integer}]}.
+ {ok,[{"myint1",sql_smallint},
+ {"myint2",sql_integer},
+ {"myint3",sql_integer}]}.
describe_string() ->
{ok,[{"str1",{sql_char,10}},
@@ -288,7 +289,7 @@ describe_string() ->
describe_floating() ->
{ok,[{"f",sql_real},{"r",sql_real},{"d",{sql_float,15}}]}.
describe_dec_num() ->
- {ok,[{"dec",{sql_numeric,9,3}},{"num",{sql_numeric,9,2}}]}.
+ {ok,[{"mydec",{sql_numeric,9,3}},{"mynum",{sql_numeric,9,2}}]}.
describe_timestamp() ->
{ok, [{"field", sql_timestamp}]}.
diff --git a/lib/odbc/test/sqlserver.erl b/lib/odbc/test/sqlserver.erl
index e3fe30e0bc..59252d4276 100644
--- a/lib/odbc/test/sqlserver.erl
+++ b/lib/odbc/test/sqlserver.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -123,10 +123,6 @@ create_text_table() ->
" (FIELD text)".
%-------------------------------------------------------------------------
-create_unicode_table() ->
- " (FIELD nvarchar(50))".
-
-%-------------------------------------------------------------------------
create_timestamp_table() ->
" (FIELD DATETIME)".
@@ -279,8 +275,8 @@ param_select() ->
%-------------------------------------------------------------------------
describe_integer() ->
- {ok,[{"int1", sql_smallint},{"int2", sql_integer},
- {"int3", sql_integer}]}.
+ {ok,[{"myint1", sql_smallint},{"myint2", sql_integer},
+ {"myint3", sql_integer}]}.
describe_string() ->
{ok,[{"str1",{sql_char,10}},
@@ -292,7 +288,7 @@ describe_floating() ->
{ok,[{"f", sql_real},{"r", sql_real}, {"d", {sql_float, 53}}]}.
describe_dec_num() ->
- {ok,[{"dec",{sql_decimal,9,3}},{"num",{sql_numeric,9,2}}]}.
+ {ok,[{"mydec",{sql_decimal,9,3}},{"mynum",{sql_numeric,9,2}}]}.
describe_timestamp() ->
{ok, [{"field", sql_timestamp}]}.
diff --git a/lib/odbc/vsn.mk b/lib/odbc/vsn.mk
index 42a51be33e..120ed9ee3d 100644
--- a/lib/odbc/vsn.mk
+++ b/lib/odbc/vsn.mk
@@ -1 +1 @@
-ODBC_VSN = 2.10.10
+ODBC_VSN = 2.10.11
diff --git a/lib/orber/COSS/CosNaming/Makefile b/lib/orber/COSS/CosNaming/Makefile
index d3deec7600..28b4d9cacc 100644
--- a/lib/orber/COSS/CosNaming/Makefile
+++ b/lib/orber/COSS/CosNaming/Makefile
@@ -124,13 +124,15 @@ docs:
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
-$(GEN_FILES): cos_naming_ext.idl cos_naming.idl
+IDL-GENERATED: cos_naming_ext.idl cos_naming.idl
erlc $(ERL_IDL_FLAGS) +'{this,"CosNaming::NamingContext"}' \
+'{this,"CosNaming::NamingContextExt"}' cos_naming_ext.idl
erlc $(ERL_IDL_FLAGS) +'{this,"CosNaming::NamingContext"}' cos_naming.idl
+ >IDL-GENERATED
-# echo "ic:gen(cos_naming, [{this, \"CosNaming::NamingContext\"}]), halt()."| $(ERL) $(ERL_IDL_FLAGS)
+$(GEN_FILES): IDL-GENERATED
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Target
diff --git a/lib/orber/doc/src/Orber/ignore_config_record.inf b/lib/orber/doc/src/Orber/ignore_config_record.inf
deleted file mode 100644
index 0a5053eba3..0000000000
--- a/lib/orber/doc/src/Orber/ignore_config_record.inf
+++ /dev/null
@@ -1 +0,0 @@
-This file makes clearmake use the -T switch for this subdirectory
diff --git a/lib/orber/doc/src/notes.xml b/lib/orber/doc/src/notes.xml
index 589123ef73..c8477d9252 100644
--- a/lib/orber/doc/src/notes.xml
+++ b/lib/orber/doc/src/notes.xml
@@ -32,6 +32,36 @@
<file>notes.xml</file>
</header>
+ <section><title>Orber 3.6.22</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section>
+ <title>Orber 3.6.21</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>
+ Eliminated Dialyzer warnings.</p>
+ <p>
+ Own Id: OTP-9326 Aux Id:</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
<section>
<title>Orber 3.6.20</title>
diff --git a/lib/orber/doc/src/orber_ifr.xml b/lib/orber/doc/src/orber_ifr.xml
index 021082e101..2d47d57476 100644
--- a/lib/orber/doc/src/orber_ifr.xml
+++ b/lib/orber/doc/src/orber_ifr.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2009</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -297,7 +297,7 @@
</desc>
</func>
<func>
- <name>describe_contents(Objref,Limit_type,Exclude_inherited,Max_returned_objs) -> Return</name>
+ <name>describe_contents(Objref, Limit_type, Exclude_inherited, Max_returned_objs) -> Return</name>
<fsummary>Return a list of descriptions of the IFR objects contained by the target Container object</fsummary>
<type>
<v>Objref = #IFR_objref</v>
diff --git a/lib/orber/examples/Stack/Makefile b/lib/orber/examples/Stack/Makefile
index 6e7f292a04..ccb65038a3 100644
--- a/lib/orber/examples/Stack/Makefile
+++ b/lib/orber/examples/Stack/Makefile
@@ -64,6 +64,8 @@ HRL_FILES=
ERL_FILES= $(MODULES:%=%.erl)
+GEN_FILES = $(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES)
+
JAVA_CLASSES = \
StackClient
@@ -101,9 +103,13 @@ docs:
test: $(TEST_TARGET_FILES)
-
-$(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES): stack.idl
+IDL-GENERATED: stack.idl
erlc $(ERL_IDL_FLAGS) stack.idl
+ >IDL-GENERATED
+
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Target
diff --git a/lib/orber/include/Makefile b/lib/orber/include/Makefile
deleted file mode 100644
index 219b7085e6..0000000000
--- a/lib/orber/include/Makefile
+++ /dev/null
@@ -1,66 +0,0 @@
-#
-# %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%
-#
-#
-include $(ERL_TOP)/make/target.mk
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(ORBER_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/orber-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-EXTERNAL_HRL_FILES= ../include/corba.hrl \
- ../include/ifr_types.hrl \
- ../include/orber_pi.hrl
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-debug opt clean docs:
-
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-
-release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(EXTERNAL_HRL_FILES) $(RELSYSDIR)/include
-
-
-release_docs_spec:
-
-
diff --git a/lib/orber/src/Makefile b/lib/orber/src/Makefile
index ccc449333c..ed62c94b98 100644
--- a/lib/orber/src/Makefile
+++ b/lib/orber/src/Makefile
@@ -227,15 +227,14 @@ docs:
# Special Build Targets
# ----------------------------------------------------
-$(GEN_ERL_FILES1) $(GEN_HRL_FILES1): $(ERL_TOP)/lib/ic/include/erlang.idl
+IDL-GENERATED: $(ERL_TOP)/lib/ic/include/erlang.idl CORBA.idl OrberIFR.idl
erlc $(ERL_IDL_FLAGS) $(ERL_TOP)/lib/ic/include/erlang.idl
-
-$(GEN_ERL_FILES2) $(GEN_HRL_FILES2): CORBA.idl
erlc $(ERL_IDL_FLAGS) CORBA.idl
+ erlc $(ERL_IDL_FLAGS) +'{this,"Orber::IFR"}' OrberIFR.idl
+ >IDL-GENERATED
-$(GEN_ERL_FILES3) $(GEN_HRL_FILES3): OrberIFR.idl
- erlc $(ERL_IDL_FLAGS) +'{this,"Orber::IFR"}' \
- OrberIFR.idl
+$(GEN_ERL_FILES): IDL-GENERATED
+$(TARGET_FILES): IDL-GENERATED
$(GEN_ASN_ERL) $(GEN_ASN_HRL): OrberCSIv2.asn1 OrberCSIv2.set.asn
erlc $(ERL_COMPILE_FLAGS) $(ASN_FLAGS) +'{inline,"OrberCSIv2"}' OrberCSIv2.set.asn
diff --git a/lib/orber/src/corba.erl b/lib/orber/src/corba.erl
index ecec768544..989e84f581 100644
--- a/lib/orber/src/corba.erl
+++ b/lib/orber/src/corba.erl
@@ -947,7 +947,7 @@ handle_cast2(M, F, A, InternalState, State, Ctx) ->
{noreply, {InternalState, NewState}}
end.
-handle_exit(InternalState, State, {undef, [{M, F, _}|_]} = Reason,
+handle_exit(InternalState, State, {undef, [{M, F, _, _}|_]} = Reason,
OnewayOp, {M, F}, A) ->
case catch check_exports(M:module_info(exports), F) of
{'EXIT',{undef,_}} ->
@@ -979,7 +979,7 @@ handle_exit(InternalState, State, {undef, [{M, F, _}|_]} = Reason,
#'OBJ_ADAPTER'{minor=(?ORBER_VMCID bor 4),
completion_status=?COMPLETED_MAYBE})
end;
-handle_exit(InternalState, State, {undef, [{M2, F2, A2}|_]} = Reason,
+handle_exit(InternalState, State, {undef, [{M2, F2, A2, _}|_]} = Reason,
OnewayOp, {M, F}, A) ->
case catch check_exports(M2:module_info(exports), F2) of
{'EXIT',{undef,_}} ->
diff --git a/lib/orber/src/orber.erl b/lib/orber/src/orber.erl
index 665b3cb383..386c07d227 100644
--- a/lib/orber/src/orber.erl
+++ b/lib/orber/src/orber.erl
@@ -245,7 +245,7 @@ create_nodes(Host, N, Port, Options, Errors, NodeData) ->
create_node(Host, Port, Options) ->
- case slave:start_link(Host, Port) of
+ case slave:start_link(Host, list_to_atom(integer_to_list(Port))) of
{ok, NewNode} ->
case net_adm:ping(NewNode) of
pong ->
diff --git a/lib/orber/src/orber_diagnostics.erl b/lib/orber/src/orber_diagnostics.erl
index c12dbfa896..c115d79524 100644
--- a/lib/orber/src/orber_diagnostics.erl
+++ b/lib/orber/src/orber_diagnostics.erl
@@ -130,10 +130,10 @@ missing_modules_helper([[Mod, Type]|T], ErrorsFound) when Type == ?IFR_StructDef
end;
missing_modules_helper([[Mod, Type]|T], ErrorsFound) when Type == ?IFR_InterfaceDef ->
case catch Mod:oe_get_interface() of
- {'EXIT', {undef,[{Mod, _, _}|_]}} ->
+ {'EXIT', {undef,[{Mod, _, _, _}|_]}} ->
io:format("Missing (Interface): ~p~n", [Mod]),
missing_modules_helper(T, ErrorsFound + 1);
- {'EXIT', {undef,[{OtherMod, _, _}|_]}} ->
+ {'EXIT', {undef,[{OtherMod, _, _, _}|_]}} ->
io:format("Missing (Inherited by the ~p Interface): ~p~n",
[Mod, OtherMod]),
missing_modules_helper(T, ErrorsFound + 1);
diff --git a/lib/orber/src/orber_ifr.erl b/lib/orber/src/orber_ifr.erl
index e56672be93..9631a268e4 100644
--- a/lib/orber/src/orber_ifr.erl
+++ b/lib/orber/src/orber_ifr.erl
@@ -500,7 +500,7 @@ get_tc(Id, Type) ->
case catch Module:tc() of
{'EXIT', Reason} ->
case Reason of
- {undef,[{Module, tc,[]}|_]} ->
+ {undef,[{Module, tc,[],_}|_]} ->
orber:dbg("[~p] ~p:get_tc(~p);~nMissing ~p:tc()~n",
[?LINE, ?MODULE, Id, Module], ?DEBUG_LEVEL),
corba:raise(#'UNKNOWN'{minor=(?ORBER_VMCID bor 1),
diff --git a/lib/orber/test/Makefile b/lib/orber/test/Makefile
index 88aeacbfe8..996d0d1874 100644
--- a/lib/orber/test/Makefile
+++ b/lib/orber/test/Makefile
@@ -184,31 +184,17 @@ docs:
# Special Targets
# ----------------------------------------------------
-#
-# Each IDL file produces many target files so no pattern
-# rule can be used.
-#
-TGT_ORBER = \
- $(GEN_HRL_ORBER:%=$(IDLOUTDIR)/%) \
- $(GEN_MOD_ORBER:%=$(IDLOUTDIR)/%.erl)
-TGT_IIOP = \
- $(GEN_HRL_IIOP:%=$(IDLOUTDIR)/%) \
- $(GEN_MOD_IIOP:%=$(IDLOUTDIR)/%.erl)
-
-TGT_TEST_SERVER = \
- $(GEN_HRL_TEST_SERVER:%=$(IDLOUTDIR)/%) \
- $(GEN_MOD_TEST_SERVER:%=$(IDLOUTDIR)/%.erl)
-
-$(TGT_ORBER): orber_test.idl
+IDL-GENERATED: orber_test.idl iiop_test.idl orber_test_server.idl
erlc $(ERL_IDL_FLAGS) -o$(IDLOUTDIR) orber_test.idl
-
-$(TGT_IIOP): iiop_test.idl
erlc $(ERL_IDL_FLAGS) -o$(IDLOUTDIR) \
+'{preproc_flags,"-I../COSS/CosNaming"}' iiop_test.idl
-
-$(TGT_TEST_SERVER): orber_test_server.idl
erlc $(ERL_IDL_FLAGS) -o$(IDLOUTDIR) \
+'{cfgfile,"orber_test_server.cfg"}' orber_test_server.idl
+ >IDL-GENERATED
+
+$(GEN_FILES): IDL-GENERATED
+
+$(TARGET_FILES): IDL-GENERATED
# ----------------------------------------------------
# Release Targets
@@ -226,7 +212,7 @@ release_tests_spec: tests
$(INSTALL_DATA) $(IDL_FILES) $(TEST_SPEC_FILE) $(COVER_FILE) \
$(ERL_FILES) $(RELSYSDIR)
$(INSTALL_DATA) $(SUITE_TARGET_FILES) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
$(INSTALL_DIR) $(RELSYSDIR)/$(IDLOUTDIR)
$(INSTALL_DATA) $(GEN_TARGET_FILES) $(GEN_FILES) \
$(RELSYSDIR)/$(IDLOUTDIR)
diff --git a/lib/orber/vsn.mk b/lib/orber/vsn.mk
index 5f17cda229..29b21e8e01 100644
--- a/lib/orber/vsn.mk
+++ b/lib/orber/vsn.mk
@@ -1,3 +1,3 @@
-ORBER_VSN = 3.6.20
+ORBER_VSN = 3.6.22
diff --git a/lib/os_mon/c_src/Makefile.in b/lib/os_mon/c_src/Makefile.in
index 1a371eb380..b81d3f564b 100644
--- a/lib/os_mon/c_src/Makefile.in
+++ b/lib/os_mon/c_src/Makefile.in
@@ -82,13 +82,9 @@ ALL_CFLAGS = @CFLAGS@ @DEFS@ $(CFLAGS)
# Targets
# ----------------------------------------------------
-debug opt: $(OBJDIR) $(BINDIR) $(TARGET_FILES)
+_create_dirs := $(shell mkdir -p $(OBJDIR) $(BINDIR))
-$(OBJDIR):
- -@mkdir -p $(OBJDIR)
-
-$(BINDIR):
- -@mkdir -p $(BINDIR)
+debug opt: $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES)
diff --git a/lib/os_mon/c_src/cpu_sup.c b/lib/os_mon/c_src/cpu_sup.c
index fbf318c614..9c5f9a6aa5 100644
--- a/lib/os_mon/c_src/cpu_sup.c
+++ b/lib/os_mon/c_src/cpu_sup.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -191,7 +191,10 @@ int main(int argc, char** argv) {
static cpu_t *read_procstat(FILE *fp, cpu_t *cpu) {
char buffer[BUFFERSIZE];
- fgets(buffer, BUFFERSIZE, fp);
+ if (fgets(buffer, BUFFERSIZE, fp) == NULL) {
+ memset(cpu, 0, sizeof(cpu_t));
+ return cpu;
+ }
sscanf(buffer, "cpu%u %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu",
&(cpu->id),
&(cpu->user),
@@ -223,7 +226,11 @@ static void util_measure(unsigned int **result_vec, int *result_sz) {
return;
}
- fgets(buffer, BUFFERSIZE, fp); /*ignore read*/
+ /*ignore read*/
+ if (fgets(buffer, BUFFERSIZE, fp) == NULL) {
+ *result_sz = 0;
+ return;
+ }
rv = *result_vec;
rv[0] = no_of_cpus;
rv[1] = CU_VALUES;
@@ -447,8 +454,12 @@ static void sendv(unsigned int data[], int ints) {
}
static void error(char* err_msg) {
- write(FD_ERR, err_msg, strlen(err_msg));
- write(FD_ERR, "\n", 1);
+ /*
+ * if we get error here we have trouble,
+ * silence unnecessary warnings
+ */
+ if(write(FD_ERR, err_msg, strlen(err_msg)));
+ if(write(FD_ERR, "\n", 1));
exit(-1);
}
diff --git a/lib/os_mon/doc/src/notes.xml b/lib/os_mon/doc/src/notes.xml
index 1062b07dfd..f641bbd828 100644
--- a/lib/os_mon/doc/src/notes.xml
+++ b/lib/os_mon/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,6 +30,49 @@
</header>
<p>This document describes the changes made to the OS_Mon application.</p>
+<section><title>Os_Mon 2.2.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Remove misc. compiler warnings</p>
+ <p>
+ Own Id: OTP-9542</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Os_Mon 2.2.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Add NetBSD support to memsup and disksup (Thanks to
+ Andrew Thompson)</p>
+ <p>
+ Own Id: OTP-9216</p>
+ </item>
+ <item>
+ <p>
+ Add support for DragonFlyBSD to memsup</p>
+ <p>
+ DragonFly was partially supported by os_mon already but
+ when trying to start the os_mon application it'd crash
+ with an error about an unknown operating system in
+ memsup. This patch changes memsup to use the FreeBSD
+ sysctl method to get memory information when on
+ DragonFly. (Thanks to Andrew Thompson )</p>
+ <p>
+ Own Id: OTP-9217</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Os_Mon 2.2.5</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/os_mon/mibs/Makefile b/lib/os_mon/mibs/Makefile
index cbbc337491..a361fef378 100644
--- a/lib/os_mon/mibs/Makefile
+++ b/lib/os_mon/mibs/Makefile
@@ -78,6 +78,9 @@ $(SNMP_BIN_TARGET_DIR)/OTP-MIB.bin: $(ERL_TOP)/lib/$(OTP_MIBDIR)/mibs/OTP-MI
v1/%.mib.v1: %.mib
$(ERL_TOP)/lib/snmp/bin/snmp-v2tov1 -o $@ $<
+$(SNMP_BIN_TARGET_DIR)/OTP-OS-MON-MIB.bin: \
+ $(SNMP_BIN_TARGET_DIR)/OTP-REG.bin \
+ $(SNMP_BIN_TARGET_DIR)/OTP-MIB.bin \
# ----------------------------------------------------
# Release Target
diff --git a/lib/os_mon/src/disksup.erl b/lib/os_mon/src/disksup.erl
index 3340f7ee72..308cd1b7fa 100644
--- a/lib/os_mon/src/disksup.erl
+++ b/lib/os_mon/src/disksup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,6 +103,7 @@ init([]) ->
Flavor==darwin;
Flavor==linux;
Flavor==openbsd;
+ Flavor==netbsd;
Flavor==irix64;
Flavor==irix ->
start_portprogram();
@@ -267,6 +268,9 @@ check_disk_space({unix, freebsd}, Port, Threshold) ->
check_disk_space({unix, openbsd}, Port, Threshold) ->
Result = my_cmd("/bin/df -k -t ffs", Port),
check_disks_solaris(skip_to_eol(Result), Threshold);
+check_disk_space({unix, netbsd}, Port, Threshold) ->
+ Result = my_cmd("/bin/df -k -t ffs", Port),
+ check_disks_solaris(skip_to_eol(Result), Threshold);
check_disk_space({unix, sunos4}, Port, Threshold) ->
Result = my_cmd("df", Port),
check_disks_solaris(skip_to_eol(Result), Threshold);
diff --git a/lib/os_mon/src/memsup.erl b/lib/os_mon/src/memsup.erl
index 822e1f939c..ba07a529bc 100644
--- a/lib/os_mon/src/memsup.erl
+++ b/lib/os_mon/src/memsup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -176,9 +176,11 @@ init([]) ->
PortMode = case OS of
{unix, darwin} -> false;
{unix, freebsd} -> false;
+ {unix, dragonfly} -> false;
% Linux supports this.
{unix, linux} -> true;
{unix, openbsd} -> true;
+ {unix, netbsd} -> true;
{unix, irix64} -> true;
{unix, irix} -> true;
{unix, sunos} -> true;
@@ -610,8 +612,10 @@ code_change(Vsn, PrevState, "1.8") ->
PortMode = case OS of
{unix, darwin} -> false;
{unix, freebsd} -> false;
+ {unix, dragonfly} -> false;
{unix, linux} -> false;
{unix, openbsd} -> true;
+ {unix, netbsd} -> true;
{unix, sunos} -> true;
{win32, _OSname} -> false;
vxworks -> true
@@ -687,6 +691,7 @@ get_os_wordsize({unix, linux}) -> get_os_wordsize_with_uname();
get_os_wordsize({unix, darwin}) -> get_os_wordsize_with_uname();
get_os_wordsize({unix, netbsd}) -> get_os_wordsize_with_uname();
get_os_wordsize({unix, freebsd}) -> get_os_wordsize_with_uname();
+get_os_wordsize({unix, dragonfly}) -> get_os_wordsize_with_uname();
get_os_wordsize({unix, openbsd}) -> get_os_wordsize_with_uname();
get_os_wordsize(_) -> unsupported_os.
@@ -736,7 +741,7 @@ get_memory_usage({unix,darwin}) ->
%% FreeBSD: Look in /usr/include/sys/vmmeter.h for the format of struct
%% vmmeter
-get_memory_usage({unix,freebsd}) ->
+get_memory_usage({unix,OSname}) when OSname == freebsd; OSname == dragonfly ->
PageSize = freebsd_sysctl("vm.stats.vm.v_page_size"),
PageCount = freebsd_sysctl("vm.stats.vm.v_page_count"),
FreeCount = freebsd_sysctl("vm.stats.vm.v_free_count"),
@@ -779,6 +784,9 @@ get_ext_memory_usage(OS, {Alloc, Total}) ->
{unix, freebsd} ->
[{total_memory, Total}, {free_memory, Total-Alloc},
{system_total_memory, Total}];
+ {unix, dragonfly} ->
+ [{total_memory, Total}, {free_memory, Total-Alloc},
+ {system_total_memory, Total}];
{unix, darwin} ->
[{total_memory, Total}, {free_memory, Total-Alloc},
{system_total_memory, Total}];
diff --git a/lib/os_mon/vsn.mk b/lib/os_mon/vsn.mk
index ecc47e70d8..f000e24a8f 100644
--- a/lib/os_mon/vsn.mk
+++ b/lib/os_mon/vsn.mk
@@ -1 +1 @@
-OS_MON_VSN = 2.2.5
+OS_MON_VSN = 2.2.7
diff --git a/lib/parsetools/doc/src/leex.xml b/lib/parsetools/doc/src/leex.xml
index 12abfd244f..d5c24c303d 100644
--- a/lib/parsetools/doc/src/leex.xml
+++ b/lib/parsetools/doc/src/leex.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2009</year><year>2009</year>
+ <year>2009</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -79,6 +79,10 @@ Token = tuple()</code>
<item><p>Causes warnings to be printed as they occur. Default is
<c>true</c>.</p>
</item>
+ <tag><c>warnings_as_errors</c></tag>
+ <item>
+ <p>Causes warnings to be treated as errors.</p>
+ </item>
<tag><c>{report, bool()}</c></tag>
<item><p>This is a short form for both <c>report_errors</c> and
<c>report_warnings</c>.</p>
diff --git a/lib/parsetools/doc/src/notes.xml b/lib/parsetools/doc/src/notes.xml
index 77b3a1a657..0c611db1ec 100644
--- a/lib/parsetools/doc/src/notes.xml
+++ b/lib/parsetools/doc/src/notes.xml
@@ -30,6 +30,52 @@
</header>
<p>This document describes the changes made to the Parsetools application.</p>
+<section><title>Parsetools 2.0.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Dialyzer warnings have been removed. </p>
+ <p>
+ Own Id: OTP-8318</p>
+ </item>
+ <item>
+ <p>
+ yecc: add warnings_as_errors option(Thanks to Tuncer
+ ayaz)</p>
+ <p>
+ Own Id: OTP-9376</p>
+ </item>
+ <item>
+ <p>
+ Fix incorrect order of pseudo variables in yecc example</p>
+ <p>
+ The example is for converting from infix to prefix. This
+ change uses to correct ordering of the triplet. (Thanks
+ to Garret Smith)</p>
+ <p>
+ Own Id: OTP-9484</p>
+ </item>
+ <item>
+ <p>
+ Implement or fix -Werror option</p>
+ <p>
+ If -Werror is enabled and there are warnings no output
+ file is written. Also make sure that error/warning
+ reporting is consistent. (Thanks to Tuncer Ayaz)</p>
+ <p>
+ Own Id: OTP-9536</p>
+ </item>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Parsetools 2.0.5</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/parsetools/doc/src/yecc.xml b/lib/parsetools/doc/src/yecc.xml
index 81f1550b0a..66bc6f4795 100644
--- a/lib/parsetools/doc/src/yecc.xml
+++ b/lib/parsetools/doc/src/yecc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -95,6 +95,10 @@
<item>This is a short form for both <c>report_errors</c> and
<c>report_warnings</c>.
</item>
+ <tag><c>warnings_as_errors</c></tag>
+ <item>
+ <p>Causes warnings to be treated as errors.</p>
+ </item>
<tag><c>{return_errors, bool()}</c>.</tag>
<item>If this flag is set, <c>{error, Errors, Warnings}</c>
is returned when there are errors. Default is
@@ -332,7 +336,7 @@ element -> list : '$1'. </code>
<code type="none">
{cons, {atom, 1, a,} {cons, {atom, 1, b},
{cons, {atom, 1, c}, nil}}} </code>
- <p>The associated code contains <c>pseudo variables</c><c>'$1'</c>, <c>'$2'</c>, <c>'$3'</c>, etc. which refer to (are
+ <p>The associated code contains <c>pseudo variables</c> <c>'$1'</c>, <c>'$2'</c>, <c>'$3'</c>, etc. which refer to (are
bound to) the values associated previously by the parser with
the symbols of the right hand side of the rule. When these
symbols are terminal categories, the values are token tuples of
@@ -421,9 +425,9 @@ myparser:parse_and_scan({Mod, Tokenizer, Args}) </code>
Nonterminals E T F.
Terminals '+' '*' '(' ')' number.
Rootsymbol E.
-E -> E '+' T: ['$1', '$2', '$3'].
+E -> E '+' T: ['$2', '$1', '$3'].
E -> T : '$1'.
-T -> T '*' F: ['$1', '$2', '$3'].
+T -> T '*' F: ['$2', '$1', '$3'].
T -> F : '$1'.
F -> '(' E ')' : '$2'.
F -> number : '$1'. </code>
@@ -434,8 +438,8 @@ Terminals '+' '*' '(' ')' number.
Rootsymbol E.
Left 100 '+'.
Left 200 '*'.
-E -> E '+' E : ['$1', '$2', '$3'].
-E -> E '*' E : ['$1', '$2', '$3'].
+E -> E '+' E : ['$2', '$1', '$3'].
+E -> E '*' E : ['$2', '$1', '$3'].
E -> '(' E ')' : '$2'.
E -> number : '$1'. </code>
<p>3. An overloaded minus operator:</p>
diff --git a/lib/parsetools/include/yeccpre.hrl b/lib/parsetools/include/yeccpre.hrl
index 80a3afbdb6..f638529aa4 100644
--- a/lib/parsetools/include/yeccpre.hrl
+++ b/lib/parsetools/include/yeccpre.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -67,7 +67,7 @@ yeccpars0(Tokens, Tzr, State, States, Vstack) ->
Error
end.
-yecc_error_type(function_clause, [{?MODULE,F,ArityOrArgs} | _]) ->
+yecc_error_type(function_clause, [{?MODULE,F,ArityOrArgs,_} | _]) ->
case atom_to_list(F) of
"yeccgoto_" ++ SymbolL ->
{ok,[{atom,_,Symbol}],_} = erl_scan:string(SymbolL),
diff --git a/lib/parsetools/src/leex.erl b/lib/parsetools/src/leex.erl
index d0b4b9efe7..cdf20461d9 100644
--- a/lib/parsetools/src/leex.erl
+++ b/lib/parsetools/src/leex.erl
@@ -35,7 +35,7 @@
-export([compile/3,file/1,file/2,format_error/1]).
-import(lists, [member/2,reverse/1,sort/1,delete/2,
- keysort/2,keydelete/3,keyfind/3,
+ keysort/2,keydelete/3,
map/2,foldl/3,foreach/2,flatmap/2]).
-import(string, [substr/2,substr/3,span/2]).
-import(ordsets, [is_element/2,add_element/2,union/2]).
@@ -58,7 +58,7 @@
gfile=[], % Graph file
module, % Module name
opts=[], % Options
- posix=false, % POSIX regular expressions
+ % posix=false, % POSIX regular expressions
errors=[],
warnings=[]
}).
@@ -73,12 +73,15 @@
%%% Interface to erl_compile.
compile(Input0, Output0,
- #options{warning = WarnLevel, verbose=Verbose, includes=Includes}) ->
+ #options{warning = WarnLevel, verbose=Verbose, includes=Includes,
+ specific=Specific}) ->
Input = assure_extension(shorten_filename(Input0), ".xrl"),
Output = assure_extension(shorten_filename(Output0), ".erl"),
Includefile = lists:sublist(Includes, 1),
+ Werror = proplists:get_bool(warnings_as_errors, Specific),
Opts = [{scannerfile,Output},{includefile,Includefile},{verbose,Verbose},
- {report_errors,true},{report_warnings,WarnLevel > 0}],
+ {report_errors,true},{report_warnings,WarnLevel > 0},
+ {warnings_as_errors, Werror}],
case file(Input, Opts) of
{ok, _} ->
ok;
@@ -107,10 +110,15 @@ file(File, Opts0) ->
St = try
{ok,REAs,Actions,Code,St2} = parse_file(St1),
{DFA,DF} = make_dfa(REAs, St2),
- St3 = out_file(St2, DFA, DF, Actions, Code),
- case lists:member(dfa_graph, St3#leex.opts) of
- true -> out_dfa_graph(St3, DFA, DF);
- false -> St3
+ case werror(St2) of
+ false ->
+ St3 = out_file(St2, DFA, DF, Actions, Code),
+ case lists:member(dfa_graph, St3#leex.opts) of
+ true -> out_dfa_graph(St3, DFA, DF);
+ false -> St3
+ end;
+ true ->
+ St2
end
catch #leex{}=St4 ->
St4
@@ -131,8 +139,8 @@ format_error({regexp,E})->
"unterminated " ++ Cs;
{illegal_char,Cs} ->
"illegal character " ++ Cs;
- {posix_cc,What} ->
- ["illegal POSIX character class ",io_lib:write_string(What)];
+%% {posix_cc,What} ->
+%% ["illegal POSIX character class ",io_lib:write_string(What)];
{char_class,What} ->
["illegal character class ",io_lib:write_string(What)]
end,
@@ -163,7 +171,8 @@ options(Options0) when is_list(Options0) ->
(T) -> [T]
end, Options0),
options(Options, [scannerfile,includefile,report_errors,
- report_warnings,return_errors,return_warnings,
+ report_warnings,warnings_as_errors,
+ return_errors,return_warnings,
verbose,dfa_graph], [])
catch error: _ -> badarg
end;
@@ -217,6 +226,7 @@ default_option(dfa_graph) -> false;
default_option(includefile) -> [];
default_option(report_errors) -> true;
default_option(report_warnings) -> true;
+default_option(warnings_as_errors) -> false;
default_option(return_errors) -> false;
default_option(return_warnings) -> false;
default_option(scannerfile) -> [];
@@ -225,6 +235,7 @@ default_option(verbose) -> false.
atom_option(dfa_graph) -> {dfa_graph,true};
atom_option(report_errors) -> {report_errors,true};
atom_option(report_warnings) -> {report_warnings,true};
+atom_option(warnings_as_errors) -> {warnings_as_errors,true};
atom_option(return_errors) -> {return_errors,true};
atom_option(return_warnings) -> {return_warnings,true};
atom_option(verbose) -> {verbose,true};
@@ -251,19 +262,29 @@ leex_ret(St) ->
report_warnings(St),
Es = pack_errors(St#leex.errors),
Ws = pack_warnings(St#leex.warnings),
+ Werror = werror(St),
if
+ Werror ->
+ do_error_return(St, Es, Ws);
Es =:= [] ->
case member(return_warnings, St#leex.opts) of
true -> {ok, St#leex.efile, Ws};
false -> {ok, St#leex.efile}
end;
- true ->
- case member(return_errors, St#leex.opts) of
- true -> {error, Es, Ws};
- false -> error
- end
+ true ->
+ do_error_return(St, Es, Ws)
+ end.
+
+do_error_return(St, Es, Ws) ->
+ case member(return_errors, St#leex.opts) of
+ true -> {error, Es, Ws};
+ false -> error
end.
+werror(St) ->
+ St#leex.warnings =/= []
+ andalso member(warnings_as_errors, St#leex.opts).
+
pack_errors([{File,_} | _] = Es) ->
[{File, flatmap(fun({_,E}) -> [E] end, sort(Es))}];
pack_errors([]) ->
@@ -286,16 +307,26 @@ report_errors(St) ->
end, report_errors, St#leex.opts).
report_warnings(St) ->
- when_opt(fun () ->
- foreach(fun({File,{none,Mod,W}}) ->
- io:fwrite("~s: Warning: ~s\n",
- [File,Mod:format_error(W)]);
- ({File,{Line,Mod,W}}) ->
- io:fwrite("~s:~w: Warning: ~s\n",
- [File,Line,Mod:format_error(W)])
- end, sort(St#leex.warnings))
- end, report_warnings, St#leex.opts).
-
+ Werror = member(warnings_as_errors, St#leex.opts),
+ Prefix = case Werror of
+ true -> "";
+ false -> "Warning: "
+ end,
+ ReportWerror = Werror andalso member(report_errors, St#leex.opts),
+ ShouldReport = member(report_warnings, St#leex.opts) orelse ReportWerror,
+ when_bool(fun () ->
+ foreach(fun({File,{none,Mod,W}}) ->
+ io:fwrite("~s: ~s~s\n",
+ [File,Prefix,
+ Mod:format_error(W)]);
+ ({File,{Line,Mod,W}}) ->
+ io:fwrite("~s:~w: ~s~s\n",
+ [File,Line,Prefix,
+ Mod:format_error(W)])
+ end, sort(St#leex.warnings))
+ end, ShouldReport).
+
+-spec add_error(_, #leex{}) -> no_return().
add_error(E, St) ->
add_error(St#leex.xfile, E, St).
@@ -341,6 +372,12 @@ when_opt(Do, Opt, Opts) ->
false -> ok
end.
+when_bool(Do, Bool) ->
+ case Bool of
+ true -> Do();
+ false -> ok
+ end.
+
verbose_print(St, Format, Args) ->
when_opt(fun () -> io:fwrite(Format, Args) end, verbose, St#leex.opts).
@@ -644,14 +681,14 @@ re_repeat1([$*|Cs], Sn, S, St) -> re_repeat1(Cs, Sn, {kclosure,S}, St);
re_repeat1([$+|Cs], Sn, S, St) -> re_repeat1(Cs, Sn, {pclosure,S}, St);
re_repeat1([$?|Cs], Sn, S, St) -> re_repeat1(Cs, Sn, {optional,S}, St);
%% { only starts interval when ere is true, otherwise normal character.
-re_repeat1([${|Cs0], Sn, S, #leex{posix=true}=St) -> % $}
- case re_interval_range(Cs0) of
- {Min,Max,[$}|Cs1]} when is_integer(Min), is_integer(Max), Min =< Max ->
- re_repeat1(Cs1, Sn, {interval,S,Min,Max}, St);
- {Min,Max,[$}|Cs1]} when is_integer(Min), is_atom(Max) ->
- re_repeat1(Cs1, Sn, {interval,S,Min,Max}, St);
- {_,_,Cs1} -> parse_error({interval_range,string_between([${|Cs0], Cs1)})
- end;
+%% re_repeat1([${|Cs0], Sn, S, #leex{posix=true}=St) -> % $}
+%% case re_interval_range(Cs0) of
+%% {Min,Max,[$}|Cs1]} when is_integer(Min), is_integer(Max), Min =< Max ->
+%% re_repeat1(Cs1, Sn, {interval,S,Min,Max}, St);
+%% {Min,Max,[$}|Cs1]} when is_integer(Min), is_atom(Max) ->
+%% re_repeat1(Cs1, Sn, {interval,S,Min,Max}, St);
+%% {_,_,Cs1} -> parse_error({interval_range,string_between([${|Cs0], Cs1)})
+%% end;
re_repeat1(Cs, Sn, S, _) -> {S,Sn,Cs}.
%% re_single(Chars, SubNumber, State) -> {RegExp,SubNumber,Chars}.
@@ -733,7 +770,7 @@ special_char($|, _) -> true;
special_char($*, _) -> true;
special_char($+, _) -> true;
special_char($?, _) -> true;
-special_char(${, #leex{posix=true}) -> true; % Only when POSIX set
+%% special_char(${, #leex{posix=true}) -> true; % Only when POSIX set
special_char($\\, _) -> true;
special_char(_, _) -> false.
@@ -744,12 +781,12 @@ re_char_class([$]|Cs], St) -> % Must special case this.
re_char_class(Cs, [$]], St);
re_char_class(Cs, St) -> re_char_class(Cs, [], St).
-re_char_class("[:" ++ Cs0, Cc, #leex{posix=true}=St) ->
- %% POSIX char class only.
- case posix_cc(Cs0) of
- {Pcl,":]" ++ Cs1} -> re_char_class(Cs1, [{posix,Pcl}|Cc], St);
- {_,Cs1} -> parse_error({posix_cc,string_between(Cs0, Cs1)})
- end;
+%% re_char_class("[:" ++ Cs0, Cc, #leex{posix=true}=St) ->
+%% %% POSIX char class only.
+%% case posix_cc(Cs0) of
+%% {Pcl,":]" ++ Cs1} -> re_char_class(Cs1, [{posix,Pcl}|Cc], St);
+%% {_,Cs1} -> parse_error({posix_cc,string_between(Cs0, Cs1)})
+%% end;
re_char_class([C1|Cs0], Cc, St) when C1 =/= $] ->
case re_char(C1, Cs0) of
{Cf,[$-,C2|Cs1]} when C2 =/= $] ->
@@ -766,19 +803,19 @@ re_char_class(Cs, Cc, _) -> {reverse(Cc),Cs}. % Preserve order
%% posix_cc(String) -> {PosixClass,RestString}.
%% Handle POSIX character classes.
-posix_cc("alnum" ++ Cs) -> {alnum,Cs};
-posix_cc("alpha" ++ Cs) -> {alpha,Cs};
-posix_cc("blank" ++ Cs) -> {blank,Cs};
-posix_cc("cntrl" ++ Cs) -> {cntrl,Cs};
-posix_cc("digit" ++ Cs) -> {digit,Cs};
-posix_cc("graph" ++ Cs) -> {graph,Cs};
-posix_cc("lower" ++ Cs) -> {lower,Cs};
-posix_cc("print" ++ Cs) -> {print,Cs};
-posix_cc("punct" ++ Cs) -> {punct,Cs};
-posix_cc("space" ++ Cs) -> {space,Cs};
-posix_cc("upper" ++ Cs) -> {upper,Cs};
-posix_cc("xdigit" ++ Cs) -> {xdigit,Cs};
-posix_cc(Cs) -> parse_error({posix_cc,substr(Cs, 1, 5)}).
+%% posix_cc("alnum" ++ Cs) -> {alnum,Cs};
+%% posix_cc("alpha" ++ Cs) -> {alpha,Cs};
+%% posix_cc("blank" ++ Cs) -> {blank,Cs};
+%% posix_cc("cntrl" ++ Cs) -> {cntrl,Cs};
+%% posix_cc("digit" ++ Cs) -> {digit,Cs};
+%% posix_cc("graph" ++ Cs) -> {graph,Cs};
+%% posix_cc("lower" ++ Cs) -> {lower,Cs};
+%% posix_cc("print" ++ Cs) -> {print,Cs};
+%% posix_cc("punct" ++ Cs) -> {punct,Cs};
+%% posix_cc("space" ++ Cs) -> {space,Cs};
+%% posix_cc("upper" ++ Cs) -> {upper,Cs};
+%% posix_cc("xdigit" ++ Cs) -> {xdigit,Cs};
+%% posix_cc(Cs) -> parse_error({posix_cc,substr(Cs, 1, 5)}).
escape_char($n) -> $\n; % \n = LF
escape_char($r) -> $\r; % \r = CR
@@ -797,24 +834,24 @@ escape_char(C) -> C. % Pass it straight through
%% Int, -> Int,any
%% Int1,Int2 -> Int1,Int2
-re_interval_range(Cs0) ->
- case re_number(Cs0) of
- {none,Cs1} -> {none,none,Cs1};
- {N,[$,|Cs1]} ->
- case re_number(Cs1) of
- {none,Cs2} -> {N,any,Cs2};
- {M,Cs2} -> {N,M,Cs2}
- end;
- {N,Cs1} -> {N,none,Cs1}
- end.
+%% re_interval_range(Cs0) ->
+%% case re_number(Cs0) of
+%% {none,Cs1} -> {none,none,Cs1};
+%% {N,[$,|Cs1]} ->
+%% case re_number(Cs1) of
+%% {none,Cs2} -> {N,any,Cs2};
+%% {M,Cs2} -> {N,M,Cs2}
+%% end;
+%% {N,Cs1} -> {N,none,Cs1}
+%% end.
-re_number([C|Cs]) when C >= $0, C =< $9 ->
- re_number(Cs, C - $0);
-re_number(Cs) -> {none,Cs}.
+%% re_number([C|Cs]) when C >= $0, C =< $9 ->
+%% re_number(Cs, C - $0);
+%% re_number(Cs) -> {none,Cs}.
-re_number([C|Cs], Acc) when C >= $0, C =< $9 ->
- re_number(Cs, 10*Acc + (C - $0));
-re_number(Cs, Acc) -> {Acc,Cs}.
+%% re_number([C|Cs], Acc) when C >= $0, C =< $9 ->
+%% re_number(Cs, 10*Acc + (C - $0));
+%% re_number(Cs, Acc) -> {Acc,Cs}.
string_between(Cs1, Cs2) ->
substr(Cs1, 1, length(Cs1)-length(Cs2)).
diff --git a/lib/parsetools/src/yecc.erl b/lib/parsetools/src/yecc.erl
index 4119e2631b..b0792a6ed8 100644
--- a/lib/parsetools/src/yecc.erl
+++ b/lib/parsetools/src/yecc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -133,12 +133,15 @@
%%% Interface to erl_compile.
compile(Input0, Output0,
- #options{warning = WarnLevel, verbose=Verbose, includes=Includes}) ->
+ #options{warning = WarnLevel, verbose=Verbose, includes=Includes,
+ specific=Specific}) ->
Input = shorten_filename(Input0),
Output = shorten_filename(Output0),
Includefile = lists:sublist(Includes, 1),
+ Werror = proplists:get_bool(warnings_as_errors, Specific),
Opts = [{parserfile,Output}, {includefile,Includefile}, {verbose,Verbose},
- {report_errors, true}, {report_warnings, WarnLevel > 0}],
+ {report_errors, true}, {report_warnings, WarnLevel > 0},
+ {warnings_as_errors, Werror}],
case file(Input, Opts) of
{ok, _OutFile} ->
ok;
@@ -278,8 +281,8 @@ options(Options0) when is_list(Options0) ->
(T) -> [T]
end, Options0),
options(Options, [file_attributes, includefile, parserfile,
- report_errors, report_warnings, return_errors,
- return_warnings, time, verbose], [])
+ report_errors, report_warnings, warnings_as_errors,
+ return_errors, return_warnings, time, verbose], [])
catch error: _ -> badarg
end;
options(Option) ->
@@ -333,6 +336,7 @@ default_option(includefile) -> [];
default_option(parserfile) -> [];
default_option(report_errors) -> true;
default_option(report_warnings) -> true;
+default_option(warnings_as_errors) -> false;
default_option(return_errors) -> false;
default_option(return_warnings) -> false;
default_option(time) -> false;
@@ -341,6 +345,7 @@ default_option(verbose) -> false.
atom_option(file_attributes) -> {file_attributes, true};
atom_option(report_errors) -> {report_errors, true};
atom_option(report_warnings) -> {report_warnings, true};
+atom_option(warnings_as_errors) -> {warnings_as_errors,true};
atom_option(return_errors) -> {return_errors, true};
atom_option(return_warnings) -> {return_warnings, true};
atom_option(time) -> {time, true};
@@ -409,12 +414,16 @@ infile(Parent, Infilex, Options) ->
{error, Reason} ->
add_error(St0#yecc.infile, none, {file_error, Reason}, St0)
end,
- case St#yecc.errors of
- [] -> ok;
+ case {St#yecc.errors, werror(St)} of
+ {[], false} -> ok;
_ -> _ = file:delete(St#yecc.outfile)
end,
Parent ! {self(), yecc_ret(St)}.
+werror(St) ->
+ St#yecc.warnings =/= []
+ andalso member(warnings_as_errors, St#yecc.options).
+
outfile(St0) ->
case file:open(St0#yecc.outfile, [write, delayed_write]) of
{ok, Outport} ->
@@ -777,17 +786,23 @@ yecc_ret(St0) ->
report_warnings(St),
Es = pack_errors(St#yecc.errors),
Ws = pack_warnings(St#yecc.warnings),
+ Werror = werror(St),
if
+ Werror ->
+ do_error_return(St, Es, Ws);
Es =:= [] ->
case member(return_warnings, St#yecc.options) of
true -> {ok, St#yecc.outfile, Ws};
false -> {ok, St#yecc.outfile}
end;
true ->
- case member(return_errors, St#yecc.options) of
- true -> {error, Es, Ws};
- false -> error
- end
+ do_error_return(St, Es, Ws)
+ end.
+
+do_error_return(St, Es, Ws) ->
+ case member(return_errors, St#yecc.options) of
+ true -> {error, Es, Ws};
+ false -> error
end.
check_expected(St0) ->
@@ -837,14 +852,22 @@ report_errors(St) ->
end.
report_warnings(St) ->
- case member(report_warnings, St#yecc.options) of
+ Werror = member(warnings_as_errors, St#yecc.options),
+ Prefix = case Werror of
+ true -> "";
+ false -> "Warning: "
+ end,
+ ReportWerror = Werror andalso member(report_errors, St#yecc.options),
+ case member(report_warnings, St#yecc.options) orelse ReportWerror of
true ->
foreach(fun({File,{none,Mod,W}}) ->
- io:fwrite(<<"~s: Warning: ~s\n">>,
- [File,Mod:format_error(W)]);
+ io:fwrite(<<"~s: ~s~s\n">>,
+ [File,Prefix,
+ Mod:format_error(W)]);
({File,{Line,Mod,W}}) ->
- io:fwrite(<<"~s:~w: Warning: ~s\n">>,
- [File,Line,Mod:format_error(W)])
+ io:fwrite(<<"~s:~w: ~s~s\n">>,
+ [File,Line,Prefix,
+ Mod:format_error(W)])
end, sort(St#yecc.warnings));
false ->
ok
diff --git a/lib/parsetools/src/yeccparser.erl b/lib/parsetools/src/yeccparser.erl
index 63127802ee..e4b8b06db5 100644
--- a/lib/parsetools/src/yeccparser.erl
+++ b/lib/parsetools/src/yeccparser.erl
@@ -17,7 +17,7 @@ line_of(Token) ->
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -83,7 +83,7 @@ yeccpars0(Tokens, Tzr, State, States, Vstack) ->
Error
end.
-yecc_error_type(function_clause, [{?MODULE,F,ArityOrArgs} | _]) ->
+yecc_error_type(function_clause, [{?MODULE,F,ArityOrArgs,_} | _]) ->
case atom_to_list(F) of
"yeccgoto_" ++ SymbolL ->
{ok,[{atom,_,Symbol}],_} = erl_scan:string(SymbolL),
diff --git a/lib/parsetools/test/Makefile b/lib/parsetools/test/Makefile
index dfb686d7ba..624c4e6975 100644
--- a/lib/parsetools/test/Makefile
+++ b/lib/parsetools/test/Makefile
@@ -72,7 +72,7 @@ release_spec: opt
release_tests_spec: make_emakefile
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) parsetools.spec parsetools.cover $(EMAKEFILE) $(ERL_FILES) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
# @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/parsetools/test/leex_SUITE.erl b/lib/parsetools/test/leex_SUITE.erl
index 23ad16f98d..1e50aedf07 100644
--- a/lib/parsetools/test/leex_SUITE.erl
+++ b/lib/parsetools/test/leex_SUITE.erl
@@ -152,6 +152,24 @@ file(Config) when is_list(Config) ->
?line writable(Dotfile),
file:delete(Dotfile),
+ ok = file:delete(Scannerfile),
+ Warn = <<"Definitions.1998\n"
+ "D = [0-9]\n"
+ "Rules.\n"
+ "{L}+ : {token,{word,TokenLine,TokenChars}}.\n"
+ "Erlang code.\n">>,
+ ok = file:write_file(Filename, Warn),
+ error = leex:file(Filename, [warnings_as_errors]),
+ false = filelib:is_regular(Scannerfile),
+ error = leex:file(Filename, [return_warnings,warnings_as_errors]),
+ false = filelib:is_regular(Scannerfile),
+ {error,_,[{Filename,[{1,leex,ignored_characters}]}]} =
+ leex:file(Filename, [return_errors,warnings_as_errors]),
+ false = filelib:is_regular(Scannerfile),
+ {ok,Scannerfile,[{Filename,[{1,leex,ignored_characters}]}]} =
+ leex:file(Filename, [return_warnings]),
+ true = filelib:is_regular(Scannerfile),
+
file:delete(Filename),
ok.
@@ -551,7 +569,7 @@ ex2(Config) when is_list(Config) ->
<<"
%%% File : erlang_scan.xrl
%%% Author : Robert Virding
-%%% Purpose : Tkoen definitions for Erlang.
+%%% Purpose : Token definitions for Erlang.
Definitions.
O = [0-7]
diff --git a/lib/parsetools/test/yecc_SUITE.erl b/lib/parsetools/test/yecc_SUITE.erl
index 1de87b3bff..a5f66b48e9 100644
--- a/lib/parsetools/test/yecc_SUITE.erl
+++ b/lib/parsetools/test/yecc_SUITE.erl
@@ -173,6 +173,7 @@ syntax(Config) when is_list(Config) ->
%% Report errors. Very simple test of format_error/1.
Ret = [return, {report, true}],
Filename = filename:join(Dir, "file.yrl"),
+ Parserfile = filename:join(Dir, "file.erl"),
Parserfile1 = filename:join(Dir, "a file"),
?line ok = file:write_file(Filename, <<"">>),
@@ -247,6 +248,19 @@ syntax(Config) when is_list(Config) ->
?line {ok,_,[{_,[{2,yecc,bad_declaration}]}]} =
yecc:file(Filename, Ret),
+ %% Bad declaration with warnings_as_errors.
+ ok = file:delete(Parserfile),
+ error = yecc:file(Filename, [warnings_as_errors]),
+ false = filelib:is_regular(Parserfile),
+ error = yecc:file(Filename, [return_warnings,warnings_as_errors]),
+ false = filelib:is_regular(Parserfile),
+ {error,_,[{_,[{2,yecc,bad_declaration}]}]} =
+ yecc:file(Filename, [return_errors,warnings_as_errors]),
+ false = filelib:is_regular(Parserfile),
+ {ok,_,[{_,[{2,yecc,bad_declaration}]}]} =
+ yecc:file(Filename, [return_warnings]),
+ true = filelib:is_regular(Parserfile),
+
%% Bad declaration.
?line ok = file:write_file(Filename,
<<"Nonterminals nt. Terminals t.
diff --git a/lib/parsetools/vsn.mk b/lib/parsetools/vsn.mk
index 812bf21f03..093523f0e7 100644
--- a/lib/parsetools/vsn.mk
+++ b/lib/parsetools/vsn.mk
@@ -1 +1 @@
-PARSETOOLS_VSN = 2.0.5
+PARSETOOLS_VSN = 2.0.6
diff --git a/lib/percept/doc/src/notes.xml b/lib/percept/doc/src/notes.xml
index 33bfa7baab..95c2bbda56 100644
--- a/lib/percept/doc/src/notes.xml
+++ b/lib/percept/doc/src/notes.xml
@@ -32,6 +32,32 @@
</header>
<p>This document describes the changes made to the Percept application.</p>
+<section><title>Percept 0.8.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix message handling in select requests</p>
+ <p>
+ percept_db used to send results in untagged messages, and
+ use a non selective receive to extract them. When percept
+ is used from the shell process, this can confuse other
+ messages with the actual result.</p>
+ <p>
+ Add a tag to the message to be {result, Result}. Add
+ demonitor to avoid keeping DOWN message in the queue fix
+ one spec in do_start/0</p>
+ <p>
+ (Thanks to Ahmed Omar)</p>
+ <p>
+ Own Id: OTP-9490</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Percept 0.8.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/percept/src/percept_db.erl b/lib/percept/src/percept_db.erl
index 52e9afb78f..68eb38d298 100644
--- a/lib/percept/src/percept_db.erl
+++ b/lib/percept/src/percept_db.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The 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,7 +92,7 @@ restart(PerceptDB)->
stop_sync(PerceptDB),
do_start().
-%% @spec do_start(pid()) -> pid()
+%% @spec do_start() -> pid()
%% @private
%% @doc starts the percept database.
@@ -131,6 +131,7 @@ stop_sync(Pid)->
{'DOWN', MonitorRef, _Type, Pid, _Info}->
true
after ?STOP_TIMEOUT->
+ erlang:demonitor(MonitorRef, [flush]),
exit(Pid, kill)
end.
@@ -166,14 +167,14 @@ insert(Trace) ->
select(Query) ->
percept_db ! {select, self(), Query},
- receive Match -> Match end.
+ receive {result, Match} -> Match end.
%% @spec select(atom(), list()) -> Result
%% @equiv select({Table,Options})
select(Table, Options) ->
percept_db ! {select, self(), {Table, Options}},
- receive Match -> Match end.
+ receive {result, Match} -> Match end.
%% @spec consolidate() -> Result
%% @doc Checks timestamp and state-flow inconsistencies in the
@@ -213,7 +214,7 @@ loop_percept_db() ->
insert_trace(clean_trace(Trace)),
loop_percept_db();
{select, Pid, Query} ->
- Pid ! select_query(Query),
+ Pid ! {result, select_query(Query)},
loop_percept_db();
{action, stop} ->
stopped;
@@ -222,7 +223,7 @@ loop_percept_db() ->
loop_percept_db();
{operate, Pid, {Table, {Fun, Start}}} ->
Result = ets:foldl(Fun, Start, Table),
- Pid ! Result,
+ Pid ! {result, Result},
loop_percept_db();
Unhandled ->
io:format("loop_percept_db, unhandled query: ~p~n", [Unhandled]),
diff --git a/lib/percept/test/Makefile b/lib/percept/test/Makefile
index 5e8c438c5c..d927386d1c 100644
--- a/lib/percept/test/Makefile
+++ b/lib/percept/test/Makefile
@@ -83,7 +83,7 @@ release_spec: opt
release_tests_spec: make_emakefile
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) percept.spec percept.cover $(EMAKEFILE) $(SOURCE) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/percept/vsn.mk b/lib/percept/vsn.mk
index 2a302991aa..3b4d9bbb64 100644
--- a/lib/percept/vsn.mk
+++ b/lib/percept/vsn.mk
@@ -1 +1 @@
-PERCEPT_VSN = 0.8.5
+PERCEPT_VSN = 0.8.6
diff --git a/lib/public_key/asn1/Makefile b/lib/public_key/asn1/Makefile
index 94abec083c..c4f8d65aa7 100644
--- a/lib/public_key/asn1/Makefile
+++ b/lib/public_key/asn1/Makefile
@@ -65,7 +65,7 @@ EBIN = ../ebin
EXTRA_ERLC_FLAGS =
ERL_COMPILE_FLAGS += $(EXTRA_ERLC_FLAGS)
-ASN_FLAGS = -bber_bin +der +compact_bit_string +optimize +noobj +asn1config +inline
+ASN_FLAGS = -bber_bin +der +compact_bit_string +optimize +noobj +asn1config +inline +nif
# ----------------------------------------------------
# Targets
@@ -79,7 +79,7 @@ clean:
docs:
-%.erl: %.set.asn
+%.erl %.hrl: %.set.asn
erlc $(ASN_FLAGS) $<
$(HRL_FILES): $(ASN_HRLS)
diff --git a/lib/public_key/asn1/README b/lib/public_key/asn1/README
index 5fb8cf9725..2a880e2d51 100644
--- a/lib/public_key/asn1/README
+++ b/lib/public_key/asn1/README
@@ -46,6 +46,6 @@ diff -r1.1 PKIXAttributeCertificate.asn1
---
> version AttCertVersion, -- version is v2
-4. Defenitions of publuic keys from PKCS-1.asn1 present in
+4. Definitions of public keys from PKCS-1.asn1 present in
PKIX1Algorithms88.asn1 where removed as we take them directly from
PKCS-1.asn1 \ No newline at end of file
diff --git a/lib/public_key/doc/src/Makefile b/lib/public_key/doc/src/Makefile
index 298c28a740..afb17399da 100644
--- a/lib/public_key/doc/src/Makefile
+++ b/lib/public_key/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2010. All Rights Reserved.
+# Copyright Ericsson AB 2008-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -52,6 +52,7 @@ XML_CHAPTER_FILES = \
introduction.xml \
public_key_records.xml \
cert_records.xml \
+ using_public_key.xml \
notes.xml
BOOK_FILES = book.xml
diff --git a/lib/public_key/doc/src/introduction.xml b/lib/public_key/doc/src/introduction.xml
index 8cf11ee10e..a21fcf3576 100644
--- a/lib/public_key/doc/src/introduction.xml
+++ b/lib/public_key/doc/src/introduction.xml
@@ -48,5 +48,13 @@
of the concepts of using public keys.</p>
</section>
+ <section>
+ <title>Performance tips</title>
+ <p>The public_key decode and encode functions will try to use the nifs
+ which are in the asn1 compilers runtime modules if they can be found.
+ So for the best performance you want to have the asn1 application in the
+ path of your system. </p>
+ </section>
+
</chapter>
diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml
index 14b43041ce..efd4a37eb9 100644
--- a/lib/public_key/doc/src/notes.xml
+++ b/lib/public_key/doc/src/notes.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2008</year>
- <year>2010</year>
+ <year>2011</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -34,6 +34,39 @@
<file>notes.xml</file>
</header>
+<section><title>Public_Key 0.13</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ replace "a ssl" with "an ssl" reindent
+ pkix_path_validation/3 Trivial documentation fixes
+ (Thanks to Christian von Roques )</p>
+ <p>
+ Own Id: OTP-9464</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Public_Key 0.12</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The public_key application now supports encode/decode of
+ ssh public-key files.</p>
+ <p>
+ Own Id: OTP-9144</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Public_Key 0.11</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/public_key/doc/src/part.xml b/lib/public_key/doc/src/part.xml
index c338a71613..ea3123b5bd 100644
--- a/lib/public_key/doc/src/part.xml
+++ b/lib/public_key/doc/src/part.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE part SYSTEM "part.dtd">
<part xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -38,5 +38,6 @@
<xi:include href="introduction.xml"/>
<xi:include href="public_key_records.xml"/>
<xi:include href="cert_records.xml"/>
+ <xi:include href="using_public_key.xml"/>
</part>
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index c5f57214b1..9a3832c68b 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -43,7 +43,7 @@
<note><p>All records used in this manual
<!-- except #policy_tree_node{} -->
- are generated from asn1 specifications
+ are generated from ASN.1 specifications
and are documented in the User's Guide. See <seealso
marker="public_key_records">Public key records</seealso> and <seealso
marker="cert_records">X.509 Certificate records</seealso>.
@@ -63,7 +63,7 @@
<p><code>pki_asn1_type() = 'Certificate' | 'RSAPrivateKey'| 'RSAPublicKey'
'DSAPrivateKey' | 'DSAPublicKey' | 'DHParameter' | 'SubjectPublicKeyInfo'</code></p>
- <p><code>pem_entry () = {pki_asn1_type(), binary() %% DER or encrypted DER
+ <p><code>pem_entry () = {pki_asn1_type(), binary(), %% DER or encrypted DER
not_encrypted | {"DES-CBC" | "DES-EDE3-CBC", crypto:rand_bytes(8)}}.</code></p>
<p><code>rsa_public_key() = #'RSAPublicKey'{}</code></p>
@@ -72,8 +72,6 @@
<p><code>dsa_public_key() = {integer(), #'Dss-Parms'{}} </code></p>
- <p><code>rsa_private_key() = #'RSAPrivateKey'{} </code></p>
-
<p><code>dsa_private_key() = #'DSAPrivateKey'{}</code></p>
<p><code> public_crypt_options() = [{rsa_pad, rsa_padding()}]. </code></p>
@@ -149,13 +147,13 @@
<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
+ <v>Asn1Type = atom()</v>
+ <d> ASN.1 type present in the public_key applications
asn1 specifications.</d>
<v>Der = der_encoded()</v>
</type>
<desc>
- <p> Decodes a public key asn1 der encoded entity.</p>
+ <p> Decodes a public key ASN.1 der encoded entity.</p>
</desc>
</func>
@@ -165,25 +163,26 @@
<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>
+ ASN.1 specifications.</d>
+ <v>Entity = term()</v>
+ <d>The erlang representation of <c>Asn1Type</c></d>
</type>
<desc>
- <p> Encodes a public key entity with asn1 DER encoding.</p>
+ <p> Encodes a public key entity with ASN.1 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>
+ entries as ASN.1 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>
+ entries as ASN.1 der encoded entities.</p>
</desc>
</func>
@@ -218,12 +217,13 @@
<fsummary> Creates a pem entry that can be fed to pem_encode/1.</fsummary>
<type>
<v>Asn1Type = pki_asn1_type()</v>
- <v>Entity = term() - The Erlang representation of
+ <v>Entity = term()</v>
+ <d>The Erlang representation of
<c>Asn1Type</c>. If <c>Asn1Type</c> is 'SubjectPublicKeyInfo'
then <c>Entity</c> must be either an rsa_public_key() or a
dsa_public_key() and this function will create the appropriate
'SubjectPublicKeyInfo' entry.
- </v>
+ </d>
<v>CipherInfo = {"DES-CBC" | "DES-EDE3-CBC", crypto:rand_bytes(8)}</v>
<v>Password = string()</v>
</type>
@@ -258,13 +258,13 @@
<func>
<name>pkix_decode_cert(Cert, otp|plain) -> #'Certificate'{} | #'OTPCertificate'{}</name>
- <fsummary> Decodes an asn1 der encoded pkix x509 certificate.</fsummary>
+ <fsummary> Decodes an ASN.1 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
+ <p>Decodes an ASN.1 der encoded pkix certificate. The otp option
+ will use the customized ASN.1 specification OTP-PKIX.asn1 for
decoding and also recursively decode most of the standard
parts.</p>
</desc>
@@ -276,12 +276,12 @@
certificate.</fsummary>
<type>
<v>Asn1Type = atom()</v>
- <d>The asn1 type can be 'Certificate', 'OTPCertificate' or a subtype of either .</d>
+ <d>The ASN.1 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
+ that are decoded/created in the otp format, whereas for the plain format this
function will directly call der_encode/2. </p>
</desc>
</func>
@@ -394,7 +394,7 @@
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>
+ <v>Key = rsa_private_key() | dsa_private_key()</v>
</type>
<desc>
<p> Creates a digital signature.</p>
diff --git a/lib/public_key/doc/src/using_public_key.xml b/lib/public_key/doc/src/using_public_key.xml
new file mode 100644
index 0000000000..f0eaeb8654
--- /dev/null
+++ b/lib/public_key/doc/src/using_public_key.xml
@@ -0,0 +1,504 @@
+<?xml version="1.0" encoding="iso-8859-1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2011</year><year>2011</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>Using the public_key API</title>
+ <file>using_public_key.xml</file>
+ </header>
+
+ <section>
+ <title>General information</title>
+
+ <p> This chapter is dedicated to showing some
+ examples of how to use the public_key API. Keys and certificates
+ used in the following sections are generated only for the purpose
+ of testing the public key application.</p>
+
+ <p>Note that some shell printouts, in the following examples,
+ have been abbreviated for increased readability.</p>
+
+ </section>
+
+ <section>
+ <title>PEM files</title>
+ <p> Pulic key data (keys, certificates etc) may be stored in PEM format. PEM files
+ comes from the Private Enhanced Mail Internet standard and has a
+ structure that looks like this:</p>
+
+ <code>&lt;text&gt;
+ -----BEGIN &lt;SOMETHING&gt;-----
+ &lt;Attribute&gt; : &lt;Value&gt;
+ &lt;Base64 encoded DER data&gt;
+ -----END &lt;SOMETHING&gt;-----
+ &lt;text&gt;</code>
+
+ <p>A file can contain several BEGIN/END blocks. Text lines between
+ blocks are ignored. Attributes, if present, are currently ignored except
+ for <c>Proc-Type</c> and <c>DEK-Info</c> that are used when the DER data is
+ encrypted.</p>
+
+ <section>
+ <title>DSA private key</title>
+
+ <p>Note file handling is not done by the public_key application. </p>
+ <code>1> {ok, PemBin} = file:read_file("dsa.pem").
+{ok,&lt;&lt;"-----BEGIN DSA PRIVATE KEY-----\nMIIBuw"...&gt;&gt;}</code>
+
+ <p>This PEM file only has one entry a private DSA key.</p>
+ <code>2> [DSAEntry] = public_key:pem_decode(PemBin).
+[{'DSAPrivateKey',&lt;&lt;48,130,1,187,2,1,0,2,129,129,0,183,
+ 179,230,217,37,99,144,157,21,228,204,
+ 162,207,61,246,...&gt;&gt;,
+ not_encrypted}]</code>
+
+ <code>3> Key = public_key:pem_entry_decode(DSAEntry).
+#'DSAPrivateKey'{version = 0,
+ p = 12900045185019966618...6593,
+ q = 1216700114794736143432235288305776850295620488937,
+ g = 10442040227452349332...47213,
+ y = 87256807980030509074...403143,
+ x = 510968529856012146351317363807366575075645839654}</code>
+ </section>
+
+ <section>
+ <title>RSA private key encrypted with a password.</title>
+
+ <code>1> {ok, PemBin} = file:read_file("rsa.pem").
+{ok,&lt;&lt;"Bag Attribut"...&gt;&gt;}</code>
+
+ <p>This PEM file only has one entry a private RSA key.</p>
+ <code>2>[RSAEntry] = public_key:pem_decode(PemBin).
+[{'RSAPrivateKey',&lt;&lt;224,108,117,203,152,40,15,77,128,126,
+ 221,195,154,249,85,208,202,251,109,
+ 119,120,57,29,89,19,9,...&gt;&gt;,
+ {"DES-EDE3-CBC",&lt;&lt;"k�e��p�L"&gt;&gt;}}]
+
+ </code>
+
+ <p>In this example the password is "abcd1234".</p>
+ <code>3> Key = public_key:pem_entry_decode(RSAEntry, "abcd1234").
+ #'RSAPrivateKey'{version = 'two-prime',
+ modulus = 1112355156729921663373...2737107,
+ publicExponent = 65537,
+ privateExponent = 58064406231183...2239766033,
+ prime1 = 11034766614656598484098...7326883017,
+ prime2 = 10080459293561036618240...77738643771,
+ exponent1 = 77928819327425934607...22152984217,
+ exponent2 = 36287623121853605733...20588523793,
+ coefficient = 924840412626098444...41820968343,
+ otherPrimeInfos = asn1_NOVALUE}</code>
+ </section>
+
+ <section>
+ <title>X509 Certificates</title>
+
+ <code>1> {ok, PemBin} = file:read_file("cacerts.pem").
+{ok,&lt;&lt;"-----BEGIN CERTIFICATE-----\nMIIC7jCCAl"...&gt;&gt;}</code>
+
+ <p>This file includes two certificates</p>
+ <code>2> [CertEntry1, CertEntry2] = public_key:pem_decode(PemBin).
+[{'Certificate',&lt;&lt;48,130,2,238,48,130,2,87,160,3,2,1,2,2,
+ 9,0,230,145,97,214,191,2,120,150,48,13,
+ ...&gt;&gt;,
+ not_encrypted},
+ {'Certificate',&lt;&lt;48,130,3,200,48,130,3,49,160,3,2,1,2,2,1,
+ 1,48,13,6,9,42,134,72,134,247,...&gt;&gt;>,
+ not_encrypted}]</code>
+
+ <p>Certificates may of course be decoded as usual ... </p>
+ <code>2> Cert = public_key:pem_entry_decode(CertEntry1).
+#'Certificate'{
+ tbsCertificate =
+ #'TBSCertificate'{
+ version = v3,serialNumber = 16614168075301976214,
+ signature =
+ #'AlgorithmIdentifier'{
+ algorithm = {1,2,840,113549,1,1,5},
+ parameters = &lt;&lt;5,0&gt;&gt;},
+ issuer =
+ {rdnSequence,
+ [[#'AttributeTypeAndValue'{
+ type = {2,5,4,3},
+ value = &lt;&lt;19,8,101,114,108,97,110,103,67,65&gt;&gt;}],
+ [#'AttributeTypeAndValue'{
+ type = {2,5,4,11},
+ value = &lt;&lt;19,10,69,114,108,97,110,103,32,79,84,80&gt;&gt;}],
+ [#'AttributeTypeAndValue'{
+ type = {2,5,4,10},
+ value = &lt;&lt;19,11,69,114,105,99,115,115,111,110,32,65,66&gt;&gt;}],
+ [#'AttributeTypeAndValue'{
+ type = {2,5,4,7},
+ value = &lt;&lt;19,9,83,116,111,99,107,104,111,108,109&gt;&gt;}],
+ [#'AttributeTypeAndValue'{
+ type = {2,5,4,6},
+ value = &lt;&lt;19,2,83,69&gt;&gt;}],
+ [#'AttributeTypeAndValue'{
+ type = {1,2,840,113549,1,9,1},
+ value = &lt;&lt;22,22,112,101,116,101,114,64,101,114,...&gt;&gt;}]]},
+ validity =
+ #'Validity'{
+ notBefore = {utcTime,"080109082929Z"},
+ notAfter = {utcTime,"080208082929Z"}},
+ subject =
+ {rdnSequence,
+ [[#'AttributeTypeAndValue'{
+ type = {2,5,4,3},
+ value = &lt;&lt;19,8,101,114,108,97,110,103,67,65&gt;&gt;}],
+ [#'AttributeTypeAndValue'{
+ type = {2,5,4,11},
+ value = &lt;&lt;19,10,69,114,108,97,110,103,32,79,84,80&gt;&gt;}],
+ [#'AttributeTypeAndValue'{
+ type = {2,5,4,10},
+ value = &lt;&lt;19,11,69,114,105,99,115,115,111,110,32,...&gt;&gt;}],
+ [#'AttributeTypeAndValue'{
+ type = {2,5,4,7},
+ value = &lt;&lt;19,9,83,116,111,99,107,104,111,108,...&gt;&gt;}],
+ [#'AttributeTypeAndValue'{
+ type = {2,5,4,6},
+ value = &lt;&lt;19,2,83,69&gt;&gt;}],
+ [#'AttributeTypeAndValue'{
+ type = {1,2,840,113549,1,9,1},
+ value = &lt;&lt;22,22,112,101,116,101,114,64,...&gt;&gt;}]]},
+ subjectPublicKeyInfo =
+ #'SubjectPublicKeyInfo'{
+ algorithm =
+ #'AlgorithmIdentifier'{
+ algorithm = {1,2,840,113549,1,1,1},
+ parameters = &lt;&lt;5,0&gt;&gt;},
+ subjectPublicKey =
+ {0,&lt;&lt;48,129,137,2,129,129,0,203,209,187,77,73,231,90,...&gt;&gt;}},
+ issuerUniqueID = asn1_NOVALUE,
+ subjectUniqueID = asn1_NOVALUE,
+ extensions =
+ [#'Extension'{
+ extnID = {2,5,29,19},
+ critical = true,
+ extnValue = [48,3,1,1,255]},
+ #'Extension'{
+ extnID = {2,5,29,15},
+ critical = false,
+ extnValue = [3,2,1,6]},
+ #'Extension'{
+ extnID = {2,5,29,14},
+ critical = false,
+ extnValue = [4,20,27,217,65,152,6,30,142|...]},
+ #'Extension'{
+ extnID = {2,5,29,17},
+ critical = false,
+ extnValue = [48,24,129,22,112,101,116,101|...]}]},
+ signatureAlgorithm =
+ #'AlgorithmIdentifier'{
+ algorithm = {1,2,840,113549,1,1,5},
+ parameters = &lt;&lt;5,0&gt;&gt;},
+ signature =
+ {0,
+ &lt;&lt;163,186,7,163,216,152,63,47,154,234,139,73,154,96,120,
+ 165,2,52,196,195,109,167,192,...&gt;&gt;}}
+</code>
+
+ <p> Parts of certificates can be decoded with
+ public_key:der_decode/2 using that parts ASN.1 type.
+ Although application specific certificate
+ extension requires application specific ASN.1 decode/encode-functions.
+ Example, the first value of the rdnSequence above is of ASN.1 type
+ 'X520CommonName'. ({2,5,4,3} = ?id-at-commonName)</p>
+
+ <code>public_key:der_decode('X520CommonName', &lt;&lt;19,8,101,114,108,97,110,103,67,65&gt;&gt;).
+{printableString,"erlangCA"}</code>
+
+ <p>... but certificates can also be decode using the pkix_decode_cert/2 that
+ can customize and recursively decode standard parts of a certificate.</p>
+ <code>3>{_, DerCert, _} = CertEntry1.</code>
+ <code>4> public_key:pkix_decode_cert(DerCert, otp).
+#'OTPCertificate'{
+ tbsCertificate =
+ #'OTPTBSCertificate'{
+ version = v3,serialNumber = 16614168075301976214,
+ signature =
+ #'SignatureAlgorithm'{
+ algorithm = {1,2,840,113549,1,1,5},
+ parameters = 'NULL'},
+ issuer =
+ {rdnSequence,
+ [[#'AttributeTypeAndValue'{
+ type = {2,5,4,3},
+ value = {printableString,"erlangCA"}}],
+ [#'AttributeTypeAndValue'{
+ type = {2,5,4,11},
+ value = {printableString,"Erlang OTP"}}],
+ [#'AttributeTypeAndValue'{
+ type = {2,5,4,10},
+ value = {printableString,"Ericsson AB"}}],
+ [#'AttributeTypeAndValue'{
+ type = {2,5,4,7},
+ value = {printableString,"Stockholm"}}],
+ [#'AttributeTypeAndValue'{type = {2,5,4,6},value = "SE"}],
+ [#'AttributeTypeAndValue'{
+ type = {1,2,840,113549,1,9,1},
+ value = "[email protected]"}]]},
+ validity =
+ #'Validity'{
+ notBefore = {utcTime,"080109082929Z"},
+ notAfter = {utcTime,"080208082929Z"}},
+ subject =
+ {rdnSequence,
+ [[#'AttributeTypeAndValue'{
+ type = {2,5,4,3},
+ value = {printableString,"erlangCA"}}],
+ [#'AttributeTypeAndValue'{
+ type = {2,5,4,11},
+ value = {printableString,"Erlang OTP"}}],
+ [#'AttributeTypeAndValue'{
+ type = {2,5,4,10},
+ value = {printableString,"Ericsson AB"}}],
+ [#'AttributeTypeAndValue'{
+ type = {2,5,4,7},
+ value = {printableString,"Stockholm"}}],
+ [#'AttributeTypeAndValue'{type = {2,5,4,6},value = "SE"}],
+ [#'AttributeTypeAndValue'{
+ type = {1,2,840,113549,1,9,1},
+ value = "[email protected]"}]]},
+ subjectPublicKeyInfo =
+ #'OTPSubjectPublicKeyInfo'{
+ algorithm =
+ #'PublicKeyAlgorithm'{
+ algorithm = {1,2,840,113549,1,1,1},
+ parameters = 'NULL'},
+ subjectPublicKey =
+ #'RSAPublicKey'{
+ modulus =
+ 1431267547247997...37419,
+ publicExponent = 65537}},
+ issuerUniqueID = asn1_NOVALUE,
+ subjectUniqueID = asn1_NOVALUE,
+ extensions =
+ [#'Extension'{
+ extnID = {2,5,29,19},
+ critical = true,
+ extnValue =
+ #'BasicConstraints'{
+ cA = true,pathLenConstraint = asn1_NOVALUE}},
+ #'Extension'{
+ extnID = {2,5,29,15},
+ critical = false,
+ extnValue = [keyCertSign,cRLSign]},
+ #'Extension'{
+ extnID = {2,5,29,14},
+ critical = false,
+ extnValue = [27,217,65,152,6,30,142,132,245|...]},
+ #'Extension'{
+ extnID = {2,5,29,17},
+ critical = false,
+ extnValue = [{rfc822Name,"[email protected]"}]}]},
+ signatureAlgorithm =
+ #'SignatureAlgorithm'{
+ algorithm = {1,2,840,113549,1,1,5},
+ parameters = 'NULL'},
+ signature =
+ {0,
+ &lt;&lt;163,186,7,163,216,152,63,47,154,234,139,73,154,96,120,
+ 165,2,52,196,195,109,167,192,...&gt;&gt;}}
+</code>
+
+ <p>This call is equivalent to public_key:pem_entry_decode(CertEntry1)</p>
+ <code>5> public_key:pkix_decode_cert(DerCert, plain).
+#'Certificate'{ ...}
+</code>
+ </section>
+
+ <section>
+ <title>Encoding public key data to PEM format</title>
+
+ <p>If you have public key data and and want to create a PEM file
+ you can do that by calling the functions
+ public_key:pem_entry_encode/2 and pem_encode/1 and then saving the
+ result to a file. For example assume you have PubKey =
+ 'RSAPublicKey'{} then you can create a PEM-"RSA PUBLIC KEY" file
+ (ASN.1 type 'RSAPublicKey') or a PEM-"PUBLIC KEY" file
+ ('SubjectPublicKeyInfo' ASN.1 type).</p>
+
+ <p> The second element of the PEM-entry will be the ASN.1 DER encoded
+ key data.</p>
+
+ <code>1> PemEntry = public_key:pem_entry_encode('RSAPublicKey', RSAPubKey).
+{'RSAPublicKey', &lt;&lt;48,72,...&gt;&gt;, not_encrypted}
+
+2> PemBin = public_key:pem_encode([PemEntry]).
+&lt;&lt;"-----BEGIN RSA PUBLIC KEY-----\nMEgC...&gt;&gt;
+
+3> file:write_file("rsa_pub_key.pem", PemBin).
+ok</code>
+
+ <p> or </p>
+
+ <code>1> PemBin = public_key:pem_entry_encode('SubjectPublicKeyInfo', RSAPubKey).
+{'SubjectPublicKeyInfo', &lt;&lt;48,92...&gt;&gt;, not_encrypted}
+
+2> PemBin = public_key:pem_encode([PemEntry]).
+&lt;&lt;"-----BEGIN PUBLIC KEY-----\nMFw...&gt;&gt;
+
+3> file:write_file("pub_key.pem", PemBin).
+ok</code>
+
+ </section>
+</section>
+
+<section>
+ <title>RSA public key cryptography </title>
+ <p> Suppose you have PrivateKey = #'RSAPrivateKey{}' and the
+ plaintext Msg = binary() and the corresponding public key
+ PublicKey = #'RSAPublicKey'{} then you can do the following.
+ Note that you normally will only do one of the encrypt or
+ decrypt operations and the peer will do the other.
+ </p>
+
+ <p>Encrypt with the private key </p>
+ <code>RsaEncrypted = public_key:encrypt_private(Msg, PrivateKey),
+Msg = public_key:decrypt_public(RsaEncrypted, PublicKey),</code>
+
+ <p>Encrypt with the public key </p>
+ <code>RsaEncrypted = public_key:encrypt_public(Msg, PublicKey),
+Msg = public_key:decrypt_private(RsaEncrypted, PrivateKey),</code>
+ </section>
+
+ <section>
+ <title>Digital signatures</title>
+
+ <p> Suppose you have PrivateKey = #'RSAPrivateKey{}'or
+ #'DSAPrivateKey'{} and the plaintext Msg = binary() and the
+ corresponding public key PublicKey = #'RSAPublicKey'{} or
+ {integer(), #'DssParams'{}} then you can do the following. Note
+ that you normally will only do one of the sign or verify operations
+ and the peer will do the other. </p>
+
+ <code>Signature = public_key:sign(Msg, sha, PrivateKey),
+true = public_key:verify(Msg, sha, Signature, PublicKey),</code>
+
+ <p>It might be appropriate to calculate the message digest before
+ calling sign or verify and then you can use the none as second
+ argument.</p>
+
+ <code>Digest = crypto:sha(Msg),
+Signature = public_key:sign(Digest, none, PrivateKey),
+true = public_key:verify(Digest, none, Signature, PublicKey),
+ </code>
+
+ </section>
+
+ <section>
+ <title>SSH files</title>
+
+ <p>SSH typically uses PEM files for private keys but has its
+ own file format for storing public keys. The erlang public_key
+ application can be used to parse the content of SSH public key files.</p>
+
+ <section>
+ <title> RFC 4716 SSH public key files </title>
+
+ <p>RFC 4716 SSH files looks confusingly like PEM files,
+ but there are some differences.</p>
+ <code>1> {ok, SshBin} = file:read_file("ssh2_rsa_pub").
+{ok, &lt;&lt;"---- BEGIN SSH2 PUBLIC KEY ----\nAAAA"...&gt;&gt;}</code>
+
+ <p>This is equivalent to calling public_key:ssh_decode(SshBin, rfc4716_public_key).
+ </p>
+ <code>2> public_key:ssh_decode(SshBin, public_key).
+[{#'RSAPublicKey'{modulus = 794430685...91663,
+ publicExponent = 35}, []}]
+</code>
+
+ </section>
+
+ <section>
+ <title> Openssh public key format </title>
+ <code>1> {ok, SshBin} = file:read_file("openssh_dsa_pub").
+{ok,&lt;&lt;"ssh-dss AAAAB3Nza"...&gt;&gt;}</code>
+
+ <p>This is equivalent to calling public_key:ssh_decode(SshBin, openssh_public_key).
+ </p>
+ <code>2> public_key:ssh_decode(SshBin, public_key).
+[{{15642692...694280725,
+ #'Dss-Parms'{p = 17291273936...696123221,
+ q = 1255626590179665817295475654204371833735706001853,
+ g = 10454211196...480338645}},
+ [{comment,"dhopson@VMUbuntu-DSH"}]}]
+</code>
+ </section>
+
+ <section>
+ <title> Known hosts - openssh format</title>
+
+ <code>1> {ok, SshBin} = file:read_file("known_hosts").
+{ok,&lt;&lt;"hostname.domain.com,192.168.0.1 ssh-rsa AAAAB...&gt;&gt;}</code>
+
+ <p>Returns a list of public keys and their related attributes
+ each pair of key and attributes corresponds to one entry in
+ the known hosts file.</p>
+
+ <code>2> public_key:ssh_decode(SshBin, known_hosts).
+[{#'RSAPublicKey'{modulus = 1498979460408...72721699,
+ publicExponent = 35},
+ [{hostnames,["hostname.domain.com","192.168.0.1"]}]},
+ {#'RSAPublicKey'{modulus = 14989794604088...2721699,
+ publicExponent = 35},
+ [{comment,"[email protected]"},
+ {hostnames,["|1|BWO5qDxk/cFH0wa05JLdHn+j6xQ=|rXQvIxh5cDD3C43k5DPDamawVNA="]}]}]
+</code>
+ </section>
+
+ <section>
+ <title> Authorized keys - openssh format</title>
+
+ <code>1> {ok, SshBin} = file:read_file("auth_keys").
+{ok, &lt;&lt;"command=\"dump /home\",no-pty,no-port-forwarding ssh-rsa AAA...&gt;&gt;}</code>
+
+ <p>Returns a list of public keys and their related attributes
+ each pair of key and attributes corresponds to one entry in
+ the authorized key file.</p>
+
+ <code>2> public_key:ssh_decode(SshBin, auth_keys).
+[{#'RSAPublicKey'{modulus = 794430685...691663,
+ publicExponent = 35},
+ [{comment,"dhopson@VMUbuntu-DSH"},
+ {options,["command=\"dump/home\"","no-pty",
+ "no-port-forwarding"]}]},
+ {{1564269258491...607694280725,
+ #'Dss-Parms'{p = 17291273936185...763696123221,
+ q = 1255626590179665817295475654204371833735706001853,
+ g = 10454211195705...60511039590076780999046480338645}},
+ [{comment,"dhopson@VMUbuntu-DSH"}]}]
+</code>
+ </section>
+
+ <section>
+ <title> Creating an SSH file from public key data </title>
+
+ <p>If you got a public key <c>PubKey</c> and a related list of
+ attributes <c>Attributes</c> as returned
+ by ssh_decode/2 you can create a new ssh file for example</p>
+ <code>N> SshBin = public_key:ssh_encode([{PubKey, Attributes}], openssh_public_key),
+&lt;&lt;"ssh-rsa "...&gt;&gt;
+N+1> file:write_file("id_rsa.pub", SshBin).
+ok</code>
+ </section>
+ </section>
+</chapter>
diff --git a/lib/public_key/src/public_key.appup.src b/lib/public_key/src/public_key.appup.src
index c65ac7bc99..4986801dad 100644
--- a/lib/public_key/src/public_key.appup.src
+++ b/lib/public_key/src/public_key.appup.src
@@ -1,6 +1,16 @@
%% -*- erlang -*-
{"%VSN%",
[
+ {"0.11",
+ [
+ {update, public_key, soft, soft_purge, soft_purge, []},
+ {update, pubkey_pem, soft, soft_purge, soft_purge, []},
+ {add_module, pubkey_ssh, soft, soft_purge, soft_purge},
+ {update, pubkey_cert, soft, soft_purge, soft_purge, []},
+ {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
+ ]
+ },
+
{"0.10",
[
{update, public_key, soft, soft_purge, soft_purge, []},
@@ -25,6 +35,16 @@
}
],
[
+ {"0.11",
+ [
+ {update, public_key, soft, soft_purge, soft_purge, []},
+ {update, pubkey_pem, soft, soft_purge, soft_purge, []},
+ {delete_module, pubkey_ssh, soft, soft_purge, soft_purge},
+ {update, pubkey_cert, soft, soft_purge, soft_purge, []},
+ {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
+ ]
+ },
+
{"0.10",
[
{update, public_key, soft, soft_purge, soft_purge, []},
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 2901020e83..33fcce2c44 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -488,9 +488,10 @@ pkix_path_validation(PathErr, [Cert | Chain], Options0) when is_atom(PathErr)->
_:_ ->
{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_path_validation(TrustedCert, CertChain, Options)
+ when is_binary(TrustedCert) ->
+ OtpCert = pkix_decode_cert(TrustedCert, otp),
+ pkix_path_validation(OtpCert, CertChain, Options);
pkix_path_validation(#'OTPCertificate'{} = TrustedCert, CertChain, Options)
when is_list(CertChain), is_list(Options) ->
diff --git a/lib/public_key/test/Makefile b/lib/public_key/test/Makefile
index e20b903942..6889ae9a8a 100644
--- a/lib/public_key/test/Makefile
+++ b/lib/public_key/test/Makefile
@@ -80,7 +80,7 @@ release_tests_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(SPEC_FILES) $(ERL_FILES) $(COVER_FILE) $(HRL_FILES) $(RELSYSDIR)
$(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/public_key/test/pkits_SUITE.erl b/lib/public_key/test/pkits_SUITE.erl
index 660af4e8ab..a325a975e9 100644
--- a/lib/public_key/test/pkits_SUITE.erl
+++ b/lib/public_key/test/pkits_SUITE.erl
@@ -26,7 +26,6 @@
-compile(export_all).
-include_lib("public_key/include/public_key.hrl").
-%%-include("public_key.hrl").
-define(error(Format,Args), error(Format,Args,?FILE,?LINE)).
-define(warning(Format,Args), warning(Format,Args,?FILE,?LINE)).
@@ -42,18 +41,65 @@
-define(NIST5, "2.16.840.1.101.3.2.1.48.5").
-define(NIST6, "2.16.840.1.101.3.2.1.48.6").
+-record(verify_state, {
+ certs_db,
+ crl_info,
+ revoke_state}).
%%
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]}].
all() ->
- [signature_verification, validity_periods,
- verifying_name_chaining,
- verifying_paths_with_self_issued_certificates,
- verifying_basic_constraints, key_usage,
- name_constraints, private_certificate_extensions].
+ [{group, signature_verification},
+ {group, validity_periods},
+ {group, verifying_name_chaining},
+ {group, verifying_paths_with_self_issued_certificates},
+ %%{group, basic_certificate_revocation_tests},
+ %%{group, delta_crls},
+ %%{group, distribution_points},
+ {group, verifying_basic_constraints},
+ {group, key_usage},
+ {group, name_constraints},
+ {group, private_certificate_extensions}].
groups() ->
- [].
+ [{signature_verification, [], [valid_rsa_signature,
+ invalid_rsa_signature, valid_dsa_signature,
+ invalid_dsa_signature]},
+ {validity_periods, [],
+ [not_before_invalid, not_before_valid, not_after_invalid, not_after_valid]},
+ {verifying_name_chaining, [],
+ [invalid_name_chain, whitespace_name_chain, capitalization_name_chain,
+ uid_name_chain, attrib_name_chain, string_name_chain]},
+ {verifying_paths_with_self_issued_certificates, [],
+ [basic_valid, basic_invalid, crl_signing_valid, crl_signing_invalid]},
+ %% {basic_certificate_revocation_tests, [],
+ %% [missing_CRL, revoked_CA, revoked_peer, invalid_CRL_signature,
+ %% invalid_CRL_issuer, invalid_CRL, valid_CRL,
+ %% unknown_CRL_extension, old_CRL, fresh_CRL, valid_serial,
+ %% invalid_serial, valid_seperate_keys, invalid_separate_keys]},
+ %% {delta_crls, [], [delta_without_crl, valid_delta_crls, invalid_delta_crls]},
+ %% {distribution_points, [], [valid_distribution_points,
+ %% valid_distribution_points_no_issuing_distribution_point,
+ %% invalid_distribution_points, valid_only_contains,
+ %% invalid_only_contains, valid_only_some_reasons,
+ %% invalid_only_some_reasons, valid_indirect_crl,
+ %% invalid_indirect_crl, valid_crl_issuer, invalid_crl_issuer]},
+ {verifying_basic_constraints,[],
+ [missing_basic_constraints, valid_basic_constraint, invalid_path_constraints,
+ valid_path_constraints]},
+ {key_usage, [],
+ [invalid_key_usage, valid_key_usage]},
+ {name_constraints, [],
+ [valid_DN_name_constraints, invalid_DN_name_constraints,
+ valid_rfc822_name_constraints,
+ invalid_rfc822_name_constraints, valid_DN_and_rfc822_name_constraints,
+ invalid_DN_and_rfc822_name_constraints, valid_dns_name_constraints,
+ invalid_dns_name_constraints, valid_uri_name_constraints,
+ invalid_uri_name_constraints]},
+ {private_certificate_extensions, [],
+ [unknown_critical_extension, unknown_not_critical_extension]}
+ ].
init_per_group(_GroupName, Config) ->
Config.
@@ -61,112 +107,706 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
+init_per_testcase(_Func, Config) ->
+ Datadir = proplists:get_value(data_dir, Config),
+ put(datadir, Datadir),
+ Config.
+
+end_per_testcase(_Func, Config) ->
+ Config.
+
+init_per_suite(Config) ->
+ {skip, "PKIX Conformance test certificates expired 14 of April 2011,"
+ " new conformance test suite uses new format so skip until PKCS-12 support is implemented"}.
+ %% try crypto:start() of
+ %% ok ->
+ %% Config
+ %% catch _:_ ->
+ %% {skip, "Crypto did not start"}
+ %% end.
+
+end_per_suite(_Config) ->
+ application:stop(crypto).
+
+%%-----------------------------------------------------------------------------
+valid_rsa_signature(doc) ->
+ ["Test rsa signatur verification"];
+valid_rsa_signature(suite) ->
+ [];
+valid_rsa_signature(Config) when is_list(Config) ->
+ run([{ "4.1.1", "Valid Signatures Test1", ok}]).
+
+invalid_rsa_signature(doc) ->
+ ["Test rsa signatur verification"];
+invalid_rsa_signature(suite) ->
+ [];
+invalid_rsa_signature(Config) when is_list(Config) ->
+ run([{ "4.1.2", "Invalid CA Signature Test2", {bad_cert,invalid_signature}},
+ { "4.1.3", "Invalid EE Signature Test3", {bad_cert,invalid_signature}}]).
+
+valid_dsa_signature(doc) ->
+ ["Test dsa signatur verification"];
+valid_dsa_signature(suite) ->
+ [];
+valid_dsa_signature(Config) when is_list(Config) ->
+ run([{ "4.1.4", "Valid DSA Signatures Test4", ok},
+ { "4.1.5", "Valid DSA Parameter Inheritance Test5", ok}]).
+
+invalid_dsa_signature(doc) ->
+ ["Test dsa signatur verification"];
+invalid_dsa_signature(suite) ->
+ [];
+invalid_dsa_signature(Config) when is_list(Config) ->
+ run([{ "4.1.6", "Invalid DSA Signature Test6",{bad_cert,invalid_signature}}]).
+%%-----------------------------------------------------------------------------
+not_before_invalid(doc) ->
+ [""];
+not_before_invalid(suite) ->
+ [];
+not_before_invalid(Config) when is_list(Config) ->
+ run([{ "4.2.1", "Invalid CA notBefore Date Test1",{bad_cert, cert_expired}},
+ { "4.2.2", "Invalid EE notBefore Date Test2",{bad_cert, cert_expired}}]).
+
+not_before_valid(doc) ->
+ [""];
+not_before_valid(suite) ->
+ [];
+not_before_valid(Config) when is_list(Config) ->
+ run([{ "4.2.3", "Valid pre2000 UTC notBefore Date Test3", ok},
+ { "4.2.4", "Valid GeneralizedTime notBefore Date Test4", ok}]).
+
+not_after_invalid(doc) ->
+ [""];
+not_after_invalid(suite) ->
+ [];
+not_after_invalid(Config) when is_list(Config) ->
+ run([{ "4.2.5", "Invalid CA notAfter Date Test5", {bad_cert, cert_expired}},
+ { "4.2.6", "Invalid EE notAfter Date Test6", {bad_cert, cert_expired}},
+ { "4.2.7", "Invalid pre2000 UTC EE notAfter Date Test7",{bad_cert, cert_expired}}]).
+
+not_after_valid(doc) ->
+ [""];
+not_after_valid(suite) ->
+ [];
+not_after_valid(Config) when is_list(Config) ->
+ run([{ "4.2.8", "Valid GeneralizedTime notAfter Date Test8", ok}]).
+%%-----------------------------------------------------------------------------
+invalid_name_chain(doc) ->
+ [""];
+invalid_name_chain(suite) ->
+ [];
+invalid_name_chain(Config) when is_list(Config) ->
+ run([{ "4.3.1", "Invalid Name Chaining EE Test1", {bad_cert, invalid_issuer}},
+ { "4.3.2", "Invalid Name Chaining Order Test2", {bad_cert, invalid_issuer}}]).
+
+whitespace_name_chain(doc) ->
+ [""];
+whitespace_name_chain(suite) ->
+ [];
+whitespace_name_chain(Config) when is_list(Config) ->
+ run([{ "4.3.3", "Valid Name Chaining Whitespace Test3", ok},
+ { "4.3.4", "Valid Name Chaining Whitespace Test4", ok}]).
+
+capitalization_name_chain(doc) ->
+ [""];
+capitalization_name_chain(suite) ->
+ [];
+capitalization_name_chain(Config) when is_list(Config) ->
+ run([{ "4.3.5", "Valid Name Chaining Capitalization Test5",ok}]).
+
+uid_name_chain(doc) ->
+ [""];
+uid_name_chain(suite) ->
+ [];
+uid_name_chain(Config) when is_list(Config) ->
+ run([{ "4.3.6", "Valid Name Chaining UIDs Test6",ok}]).
+
+attrib_name_chain(doc) ->
+ [""];
+attrib_name_chain(suite) ->
+ [];
+attrib_name_chain(Config) when is_list(Config) ->
+ run([{ "4.3.7", "Valid RFC3280 Mandatory Attribute Types Test7", ok},
+ { "4.3.8", "Valid RFC3280 Optional Attribute Types Test8", ok}]).
+
+string_name_chain(doc) ->
+ [""];
+string_name_chain(suite) ->
+ [];
+string_name_chain(Config) when is_list(Config) ->
+ run([{ "4.3.9", "Valid UTF8String Encoded Names Test9", ok},
+ { "4.3.10", "Valid Rollover from PrintableString to UTF8String Test10", ok},
+ { "4.3.11", "Valid UTF8String Case Insensitive Match Test11", ok}]).
+
+%%-----------------------------------------------------------------------------
+
+basic_valid(doc) ->
+ [""];
+basic_valid(suite) ->
+ [];
+basic_valid(Config) when is_list(Config) ->
+ run([{ "4.5.1", "Valid Basic Self-Issued Old With New Test1", ok},
+ { "4.5.3", "Valid Basic Self-Issued New With Old Test3", ok},
+ { "4.5.4", "Valid Basic Self-Issued New With Old Test4", ok}
+ ]).
+
+basic_invalid(doc) ->
+ [""];
+basic_invalid(suite) ->
+ [];
+basic_invalid(Config) when is_list(Config) ->
+ run([{"4.5.2", "Invalid Basic Self-Issued Old With New Test2",
+ {bad_cert, {revoked, keyCompromise}}},
+ {"4.5.5", "Invalid Basic Self-Issued New With Old Test5",
+ {bad_cert, {revoked, keyCompromise}}}
+ ]).
+
+crl_signing_valid(doc) ->
+ [""];
+crl_signing_valid(suite) ->
+ [];
+crl_signing_valid(Config) when is_list(Config) ->
+ run([{ "4.5.6", "Valid Basic Self-Issued CRL Signing Key Test6", ok}]).
+
+crl_signing_invalid(doc) ->
+ [""];
+crl_signing_invalid(suite) ->
+ [];
+crl_signing_invalid(Config) when is_list(Config) ->
+ run([{ "4.5.7", "Invalid Basic Self-Issued CRL Signing Key Test7",
+ {bad_cert, {revoked, keyCompromise}}},
+ { "4.5.8", "Invalid Basic Self-Issued CRL Signing Key Test8",
+ {bad_cert, invalid_key_usage}}
+ ]).
+
+%%-----------------------------------------------------------------------------
+missing_CRL(doc) ->
+ [""];
+missing_CRL(suite) ->
+ [];
+missing_CRL(Config) when is_list(Config) ->
+ run([{ "4.4.1", "Missing CRL Test1",{bad_cert,
+ revocation_status_undetermined}}]).
+
+revoked_CA(doc) ->
+ [""];
+revoked_CA(suite) ->
+ [];
+revoked_CA(Config) when is_list(Config) ->
+ run([{ "4.4.2", "Invalid Revoked CA Test2", {bad_cert,
+ {revoked, keyCompromise}}}]).
+
+revoked_peer(doc) ->
+ [""];
+revoked_peer(suite) ->
+ [];
+revoked_peer(Config) when is_list(Config) ->
+ run([{ "4.4.3", "Invalid Revoked EE Test3", {bad_cert,
+ {revoked, keyCompromise}}}]).
+
+invalid_CRL_signature(doc) ->
+ [""];
+invalid_CRL_signature(suite) ->
+ [];
+invalid_CRL_signature(Config) when is_list(Config) ->
+ run([{ "4.4.4", "Invalid Bad CRL Signature Test4",
+ {bad_cert, revocation_status_undetermined}}]).
+
+invalid_CRL_issuer(doc) ->
+ [""];
+invalid_CRL_issuer(suite) ->
+ [];
+invalid_CRL_issuer(Config) when is_list(Config) ->
+ run({ "4.4.5", "Invalid Bad CRL Issuer Name Test5",
+ {bad_cert, revocation_status_undetermined}}).
+
+invalid_CRL(doc) ->
+ [""];
+invalid_CRL(suite) ->
+ [];
+invalid_CRL(Config) when is_list(Config) ->
+ run([{ "4.4.6", "Invalid Wrong CRL Test6",
+ {bad_cert, revocation_status_undetermined}}]).
+
+valid_CRL(doc) ->
+ [""];
+valid_CRL(suite) ->
+ [];
+valid_CRL(Config) when is_list(Config) ->
+ run([{ "4.4.7", "Valid Two CRLs Test7", ok}]).
+
+unknown_CRL_extension(doc) ->
+ [""];
+unknown_CRL_extension(suite) ->
+ [];
+unknown_CRL_extension(Config) when is_list(Config) ->
+ run([{ "4.4.8", "Invalid Unknown CRL Entry Extension Test8",
+ {bad_cert, {revoked, keyCompromise}}},
+ { "4.4.9", "Invalid Unknown CRL Extension Test9",
+ {bad_cert, {revoked, keyCompromise}}},
+ { "4.4.10", "Invalid Unknown CRL Extension Test10",
+ {bad_cert, revocation_status_undetermined}}]).
+
+old_CRL(doc) ->
+ [""];
+old_CRL(suite) ->
+ [];
+old_CRL(Config) when is_list(Config) ->
+ run([{ "4.4.11", "Invalid Old CRL nextUpdate Test11",
+ {bad_cert, revocation_status_undetermined}},
+ { "4.4.12", "Invalid pre2000 CRL nextUpdate Test12",
+ {bad_cert, revocation_status_undetermined}}]).
+
+fresh_CRL(doc) ->
+ [""];
+fresh_CRL(suite) ->
+ [];
+fresh_CRL(Config) when is_list(Config) ->
+ run([{ "4.4.13", "Valid GeneralizedTime CRL nextUpdate Test13", ok}]).
+
+valid_serial(doc) ->
+ [""];
+valid_serial(suite) ->
+ [];
+valid_serial(Config) when is_list(Config) ->
+ run([
+ { "4.4.14", "Valid Negative Serial Number Test14",ok},
+ { "4.4.16", "Valid Long Serial Number Test16", ok},
+ { "4.4.17", "Valid Long Serial Number Test17", ok}
+ ]).
+
+invalid_serial(doc) ->
+ [""];
+invalid_serial(suite) ->
+ [];
+invalid_serial(Config) when is_list(Config) ->
+ run([{ "4.4.15", "Invalid Negative Serial Number Test15",
+ {bad_cert, {revoked, keyCompromise}}},
+ { "4.4.18", "Invalid Long Serial Number Test18",
+ {bad_cert, {revoked, keyCompromise}}}]).
+
+valid_seperate_keys(doc) ->
+ [""];
+valid_seperate_keys(suite) ->
+ [];
+valid_seperate_keys(Config) when is_list(Config) ->
+ run([{ "4.4.19", "Valid Separate Certificate and CRL Keys Test19", ok}]).
+
+invalid_separate_keys(doc) ->
+ [""];
+invalid_separate_keys(suite) ->
+ [];
+invalid_separate_keys(Config) when is_list(Config) ->
+ run([{ "4.4.20", "Invalid Separate Certificate and CRL Keys Test20",
+ {bad_cert, {revoked, keyCompromise}}},
+ { "4.4.21", "Invalid Separate Certificate and CRL Keys Test21",
+ {bad_cert, revocation_status_undetermined}}
+ ]).
+%%-----------------------------------------------------------------------------
+missing_basic_constraints(doc) ->
+ [""];
+missing_basic_constraints(suite) ->
+ [];
+missing_basic_constraints(Config) when is_list(Config) ->
+ run([{ "4.6.1", "Invalid Missing basicConstraints Test1",
+ {bad_cert, missing_basic_constraint}},
+ { "4.6.2", "Invalid cA False Test2",
+ {bad_cert, missing_basic_constraint}},
+ { "4.6.3", "Invalid cA False Test3",
+ {bad_cert, missing_basic_constraint}}]).
+
+valid_basic_constraint(doc) ->
+ [""];
+valid_basic_constraint(suite) ->
+ [];
+valid_basic_constraint(Config) when is_list(Config) ->
+ run([{"4.6.4", "Valid basicConstraints Not Critical Test4", ok}]).
+
+invalid_path_constraints(doc) ->
+ [""];
+invalid_path_constraints(suite) ->
+ [];
+invalid_path_constraints(Config) when is_list(Config) ->
+ run([{ "4.6.5", "Invalid pathLenConstraint Test5", {bad_cert, max_path_length_reached}},
+ { "4.6.6", "Invalid pathLenConstraint Test6", {bad_cert, max_path_length_reached}},
+ { "4.6.9", "Invalid pathLenConstraint Test9", {bad_cert, max_path_length_reached}},
+ { "4.6.10", "Invalid pathLenConstraint Test10", {bad_cert, max_path_length_reached}},
+ { "4.6.11", "Invalid pathLenConstraint Test11", {bad_cert, max_path_length_reached}},
+ { "4.6.12", "Invalid pathLenConstraint Test12", {bad_cert, max_path_length_reached}},
+ { "4.6.16", "Invalid Self-Issued pathLenConstraint Test16",
+ {bad_cert, max_path_length_reached}}]).
-signature_verification(doc) -> [""];
-signature_verification(suite) -> [];
-signature_verification(Config) when is_list(Config) ->
- run(signature_verification()).
-validity_periods(doc) -> [""];
-validity_periods(suite) -> [];
-validity_periods(Config) when is_list(Config) ->
- run(validity_periods()).
-verifying_name_chaining(doc) -> [""];
-verifying_name_chaining(suite) -> [];
-verifying_name_chaining(Config) when is_list(Config) ->
- run(verifying_name_chaining()).
-basic_certificate_revocation_tests(doc) -> [""];
-basic_certificate_revocation_tests(suite) -> [];
-basic_certificate_revocation_tests(Config) when is_list(Config) ->
- run(basic_certificate_revocation_tests()).
-verifying_paths_with_self_issued_certificates(doc) -> [""];
-verifying_paths_with_self_issued_certificates(suite) -> [];
-verifying_paths_with_self_issued_certificates(Config) when is_list(Config) ->
- run(verifying_paths_with_self_issued_certificates()).
-verifying_basic_constraints(doc) -> [""];
-verifying_basic_constraints(suite) -> [];
-verifying_basic_constraints(Config) when is_list(Config) ->
- run(verifying_basic_constraints()).
-key_usage(doc) -> [""];
-key_usage(suite) -> [];
-key_usage(Config) when is_list(Config) ->
- run(key_usage()).
+valid_path_constraints(doc) ->
+ [""];
+valid_path_constraints(suite) ->
+ [];
+valid_path_constraints(Config) when is_list(Config) ->
+ run([{ "4.6.7", "Valid pathLenConstraint Test7", ok},
+ { "4.6.8", "Valid pathLenConstraint Test8", ok},
+ { "4.6.13", "Valid pathLenConstraint Test13", ok},
+ { "4.6.14", "Valid pathLenConstraint Test14", ok},
+ { "4.6.15", "Valid Self-Issued pathLenConstraint Test15", ok},
+ { "4.6.17", "Valid Self-Issued pathLenConstraint Test17", ok}]).
+
+%%-----------------------------------------------------------------------------
+invalid_key_usage(doc) ->
+ [""];
+invalid_key_usage(suite) ->
+ [];
+invalid_key_usage(Config) when is_list(Config) ->
+ run([{ "4.7.1", "Invalid keyUsage Critical keyCertSign False Test1",
+ {bad_cert,invalid_key_usage} },
+ { "4.7.2", "Invalid keyUsage Not Critical keyCertSign False Test2",
+ {bad_cert,invalid_key_usage}},
+ { "4.7.4", "Invalid keyUsage Critical cRLSign False Test4",
+ {bad_cert, revocation_status_undetermined}},
+ { "4.7.5", "Invalid keyUsage Not Critical cRLSign False Test5",
+ {bad_cert, revocation_status_undetermined}}
+ ]).
+
+valid_key_usage(doc) ->
+ [""];
+valid_key_usage(suite) ->
+ [];
+valid_key_usage(Config) when is_list(Config) ->
+ run([{ "4.7.3", "Valid keyUsage Not Critical Test3", ok}]).
+
+%%-----------------------------------------------------------------------------
certificate_policies(doc) -> [""];
certificate_policies(suite) -> [];
certificate_policies(Config) when is_list(Config) ->
run(certificate_policies()).
+%%-----------------------------------------------------------------------------
require_explicit_policy(doc) -> [""];
require_explicit_policy(suite) -> [];
require_explicit_policy(Config) when is_list(Config) ->
run(require_explicit_policy()).
+%%-----------------------------------------------------------------------------
policy_mappings(doc) -> [""];
policy_mappings(suite) -> [];
policy_mappings(Config) when is_list(Config) ->
run(policy_mappings()).
+%%-----------------------------------------------------------------------------
inhibit_policy_mapping(doc) -> [""];
inhibit_policy_mapping(suite) -> [];
inhibit_policy_mapping(Config) when is_list(Config) ->
run(inhibit_policy_mapping()).
+%%-----------------------------------------------------------------------------
inhibit_any_policy(doc) -> [""];
inhibit_any_policy(suite) -> [];
inhibit_any_policy(Config) when is_list(Config) ->
run(inhibit_any_policy()).
-name_constraints(doc) -> [""];
-name_constraints(suite) -> [];
-name_constraints(Config) when is_list(Config) ->
- run(name_constraints()).
-distribution_points(doc) -> [""];
-distribution_points(suite) -> [];
-distribution_points(Config) when is_list(Config) ->
- run(distribution_points()).
-delta_crls(doc) -> [""];
-delta_crls(suite) -> [];
-delta_crls(Config) when is_list(Config) ->
- run(delta_crls()).
-private_certificate_extensions(doc) -> [""];
-private_certificate_extensions(suite) -> [];
-private_certificate_extensions(Config) when is_list(Config) ->
- run(private_certificate_extensions()).
-
-run() ->
- Tests =
- [signature_verification(),
- validity_periods(),
- verifying_name_chaining(),
- %%basic_certificate_revocation_tests(),
- verifying_paths_with_self_issued_certificates(),
- verifying_basic_constraints(),
- key_usage(),
- %%certificate_policies(),
- %%require_explicit_policy(),
- %%policy_mappings(),
- %%inhibit_policy_mapping(),
- %%inhibit_any_policy(),
- name_constraints(),
- %distribution_points(),
- %delta_crls(),
- private_certificate_extensions()
- ],
- run(lists:append(Tests)).
+%%-----------------------------------------------------------------------------
+
+valid_DN_name_constraints(doc) ->
+ [""];
+valid_DN_name_constraints(suite) ->
+ [];
+valid_DN_name_constraints(Config) when is_list(Config) ->
+ run([{ "4.13.1", "Valid DN nameConstraints Test1", ok},
+ { "4.13.4", "Valid DN nameConstraints Test4", ok},
+ { "4.13.5", "Valid DN nameConstraints Test5", ok},
+ { "4.13.6", "Valid DN nameConstraints Test6", ok},
+ { "4.13.11", "Valid DN nameConstraints Test11", ok},
+ { "4.13.14", "Valid DN nameConstraints Test14", ok},
+ { "4.13.18", "Valid DN nameConstraints Test18", ok},
+ { "4.13.19", "Valid Self-Issued DN nameConstraints Test19", ok}]).
+
+invalid_DN_name_constraints(doc) ->
+ [""];
+invalid_DN_name_constraints(suite) ->
+ [];
+invalid_DN_name_constraints(Config) when is_list(Config) ->
+ run([{ "4.13.2", "Invalid DN nameConstraints Test2", {bad_cert, name_not_permitted}},
+ { "4.13.3", "Invalid DN nameConstraints Test3", {bad_cert, name_not_permitted}},
+ { "4.13.7", "Invalid DN nameConstraints Test7", {bad_cert, name_not_permitted}},
+ { "4.13.8", "Invalid DN nameConstraints Test8", {bad_cert, name_not_permitted}},
+ { "4.13.9", "Invalid DN nameConstraints Test9", {bad_cert, name_not_permitted}},
+ { "4.13.10", "Invalid DN nameConstraints Test10",{bad_cert, name_not_permitted}},
+ { "4.13.12", "Invalid DN nameConstraints Test12",{bad_cert, name_not_permitted}},
+ { "4.13.13", "Invalid DN nameConstraints Test13",{bad_cert, name_not_permitted}},
+ { "4.13.15", "Invalid DN nameConstraints Test15",{bad_cert, name_not_permitted}},
+ { "4.13.16", "Invalid DN nameConstraints Test16",{bad_cert, name_not_permitted}},
+ { "4.13.17", "Invalid DN nameConstraints Test17",{bad_cert, name_not_permitted}},
+ { "4.13.20", "Invalid Self-Issued DN nameConstraints Test20",
+ {bad_cert, name_not_permitted}}]).
+
+valid_rfc822_name_constraints(doc) ->
+ [""];
+valid_rfc822_name_constraints(suite) ->
+ [];
+valid_rfc822_name_constraints(Config) when is_list(Config) ->
+ run([{ "4.13.21", "Valid RFC822 nameConstraints Test21", ok},
+ { "4.13.23", "Valid RFC822 nameConstraints Test23", ok},
+ { "4.13.25", "Valid RFC822 nameConstraints Test25", ok}]).
+
+
+invalid_rfc822_name_constraints(doc) ->
+ [""];
+invalid_rfc822_name_constraints(suite) ->
+ [];
+invalid_rfc822_name_constraints(Config) when is_list(Config) ->
+ run([{ "4.13.22", "Invalid RFC822 nameConstraints Test22",
+ {bad_cert, name_not_permitted}},
+ { "4.13.24", "Invalid RFC822 nameConstraints Test24",
+ {bad_cert, name_not_permitted}},
+ { "4.13.26", "Invalid RFC822 nameConstraints Test26",
+ {bad_cert, name_not_permitted}}]).
+
+valid_DN_and_rfc822_name_constraints(doc) ->
+ [""];
+valid_DN_and_rfc822_name_constraints(suite) ->
+ [];
+valid_DN_and_rfc822_name_constraints(Config) when is_list(Config) ->
+ run([{ "4.13.27", "Valid DN and RFC822 nameConstraints Test27", ok}]).
+
+invalid_DN_and_rfc822_name_constraints(doc) ->
+ [""];
+invalid_DN_and_rfc822_name_constraints(suite) ->
+ [];
+invalid_DN_and_rfc822_name_constraints(Config) when is_list(Config) ->
+ run([{ "4.13.28", "Invalid DN and RFC822 nameConstraints Test28",
+ {bad_cert, name_not_permitted}},
+ { "4.13.29", "Invalid DN and RFC822 nameConstraints Test29",
+ {bad_cert, name_not_permitted}}]).
+
+valid_dns_name_constraints(doc) ->
+ [""];
+valid_dns_name_constraints(suite) ->
+ [];
+valid_dns_name_constraints(Config) when is_list(Config) ->
+ run([{ "4.13.30", "Valid DNS nameConstraints Test30", ok},
+ { "4.13.32", "Valid DNS nameConstraints Test32", ok}]).
+
+invalid_dns_name_constraints(doc) ->
+ [""];
+invalid_dns_name_constraints(suite) ->
+ [];
+invalid_dns_name_constraints(Config) when is_list(Config) ->
+ run([{ "4.13.31", "Invalid DNS nameConstraints Test31", {bad_cert, name_not_permitted}},
+ { "4.13.33", "Invalid DNS nameConstraints Test33", {bad_cert, name_not_permitted}},
+ { "4.13.38", "Invalid DNS nameConstraints Test38", {bad_cert, name_not_permitted}}]).
+
+valid_uri_name_constraints(doc) ->
+ [""];
+valid_uri_name_constraints(suite) ->
+ [];
+valid_uri_name_constraints(Config) when is_list(Config) ->
+ run([{ "4.13.34", "Valid URI nameConstraints Test34", ok},
+ { "4.13.36", "Valid URI nameConstraints Test36", ok}]).
+
+invalid_uri_name_constraints(doc) ->
+ [""];
+invalid_uri_name_constraints(suite) ->
+ [];
+invalid_uri_name_constraints(Config) when is_list(Config) ->
+ run([{ "4.13.35", "Invalid URI nameConstraints Test35",{bad_cert, name_not_permitted}},
+ { "4.13.37", "Invalid URI nameConstraints Test37",{bad_cert, name_not_permitted}}]).
+
+%%-----------------------------------------------------------------------------
+delta_without_crl(doc) ->
+ [""];
+delta_without_crl(suite) ->
+ [];
+delta_without_crl(Config) when is_list(Config) ->
+ run([{ "4.15.1", "Invalid deltaCRLIndicator No Base Test1",{bad_cert,
+ revocation_status_undetermined}},
+ {"4.15.10", "Invalid delta-CRL Test10", {bad_cert,
+ revocation_status_undetermined}}]).
+
+valid_delta_crls(doc) ->
+ [""];
+valid_delta_crls(suite) ->
+ [];
+valid_delta_crls(Config) when is_list(Config) ->
+ run([{ "4.15.2", "Valid delta-CRL Test2", ok},
+ { "4.15.5", "Valid delta-CRL Test5", ok},
+ { "4.15.7", "Valid delta-CRL Test7", ok},
+ { "4.15.8", "Valid delta-CRL Test8", ok}
+ ]).
+
+invalid_delta_crls(doc) ->
+ [""];
+invalid_delta_crls(suite) ->
+ [];
+invalid_delta_crls(Config) when is_list(Config) ->
+ run([{ "4.15.3", "Invalid delta-CRL Test3", {bad_cert,{revoked, keyCompromise}}},
+ { "4.15.4", "Invalid delta-CRL Test4", {bad_cert,{revoked, keyCompromise}}},
+ { "4.15.6", "Invalid delta-CRL Test6", {bad_cert,{revoked, keyCompromise}}},
+ { "4.15.9", "Invalid delta-CRL Test9", {bad_cert,{revoked, keyCompromise}}}]).
+
+%%-----------------------------------------------------------------------------
+
+valid_distribution_points(doc) ->
+ [""];
+valid_distribution_points(suite) ->
+ [];
+valid_distribution_points(Config) when is_list(Config) ->
+ run([{ "4.14.1", "Valid distributionPoint Test1", ok},
+ { "4.14.4", "Valid distributionPoint Test4", ok},
+ { "4.14.5", "Valid distributionPoint Test5", ok},
+ { "4.14.7", "Valid distributionPoint Test7", ok}
+ ]).
+
+valid_distribution_points_no_issuing_distribution_point(doc) ->
+ [""];
+valid_distribution_points_no_issuing_distribution_point(suite) ->
+ [];
+valid_distribution_points_no_issuing_distribution_point(Config) when is_list(Config) ->
+ run([{ "4.14.10", "Valid No issuingDistributionPoint Test10", ok}
+ ]).
+
+invalid_distribution_points(doc) ->
+ [""];
+invalid_distribution_points(suite) ->
+ [];
+invalid_distribution_points(Config) when is_list(Config) ->
+ run([{ "4.14.2", "Invalid distributionPoint Test2", {bad_cert,{revoked, keyCompromise}}},
+ { "4.14.3", "Invalid distributionPoint Test3", {bad_cert,
+ revocation_status_undetermined}},
+ { "4.14.6", "Invalid distributionPoint Test6", {bad_cert,{revoked, keyCompromise}}},
+ { "4.14.8", "Invalid distributionPoint Test8", {bad_cert,
+ revocation_status_undetermined}},
+ { "4.14.9", "Invalid distributionPoint Test9", {bad_cert,
+ revocation_status_undetermined}}
+ ]).
+
+valid_only_contains(doc) ->
+ [""];
+valid_only_contains(suite) ->
+ [];
+valid_only_contains(Config) when is_list(Config) ->
+ run([{ "4.14.13", "Valid onlyContainsCACerts CRL Test13", ok}]).
+
+invalid_only_contains(doc) ->
+ [""];
+invalid_only_contains(suite) ->
+ [];
+invalid_only_contains(Config) when is_list(Config) ->
+ run([{ "4.14.11", "Invalid onlyContainsUserCerts CRL Test11",
+ {bad_cert, revocation_status_undetermined}},
+ { "4.14.12", "Invalid onlyContainsCACerts CRL Test12",
+ {bad_cert, revocation_status_undetermined}},
+ { "4.14.14", "Invalid onlyContainsAttributeCerts Test14",
+ {bad_cert, revocation_status_undetermined}}
+ ]).
+
+valid_only_some_reasons(doc) ->
+ [""];
+valid_only_some_reasons(suite) ->
+ [];
+valid_only_some_reasons(Config) when is_list(Config) ->
+ run([{ "4.14.18", "Valid onlySomeReasons Test18", ok},
+ { "4.14.19", "Valid onlySomeReasons Test19", ok}
+ ]).
+
+invalid_only_some_reasons(doc) ->
+ [""];
+invalid_only_some_reasons(suite) ->
+ [];
+invalid_only_some_reasons(Config) when is_list(Config) ->
+ run([{ "4.14.15", "Invalid onlySomeReasons Test15",
+ {bad_cert,{revoked, keyCompromise}}},
+ { "4.14.16", "Invalid onlySomeReasons Test16",
+ {bad_cert,{revoked, certificateHold}}},
+ { "4.14.17", "Invalid onlySomeReasons Test17",
+ {bad_cert, revocation_status_undetermined}},
+ { "4.14.20", "Invalid onlySomeReasons Test20",
+ {bad_cert,{revoked, keyCompromise}}},
+ { "4.14.21", "Invalid onlySomeReasons Test21",
+ {bad_cert,{revoked, affiliationChanged}}}
+ ]).
+
+valid_indirect_crl(doc) ->
+ [""];
+valid_indirect_crl(suite) ->
+ [];
+valid_indirect_crl(Config) when is_list(Config) ->
+ run([{ "4.14.22", "Valid IDP with indirectCRL Test22", ok},
+ { "4.14.24", "Valid IDP with indirectCRL Test24", ok},
+ { "4.14.25", "Valid IDP with indirectCRL Test25", ok}
+ ]).
+
+invalid_indirect_crl(doc) ->
+ [""];
+invalid_indirect_crl(suite) ->
+ [];
+invalid_indirect_crl(Config) when is_list(Config) ->
+ run([{ "4.14.23", "Invalid IDP with indirectCRL Test23",
+ {bad_cert,{revoked, keyCompromise}}},
+ { "4.14.26", "Invalid IDP with indirectCRL Test26",
+ {bad_cert, revocation_status_undetermined}}
+ ]).
+
+valid_crl_issuer(doc) ->
+ [""];
+valid_crl_issuer(suite) ->
+ [];
+valid_crl_issuer(Config) when is_list(Config) ->
+ run([{ "4.14.28", "Valid cRLIssuer Test28", ok}%%,
+ %%{ "4.14.29", "Valid cRLIssuer Test29", ok},
+ %%{ "4.14.33", "Valid cRLIssuer Test33", ok}
+ ]).
+
+invalid_crl_issuer(doc) ->
+ [""];
+invalid_crl_issuer(suite) ->
+ [];
+invalid_crl_issuer(Config) when is_list(Config) ->
+ run([
+ { "4.14.27", "Invalid cRLIssuer Test27", {bad_cert, revocation_status_undetermined}},
+ { "4.14.31", "Invalid cRLIssuer Test31", {bad_cert,{revoked, keyCompromise}}},
+ { "4.14.32", "Invalid cRLIssuer Test32", {bad_cert,{revoked, keyCompromise}}},
+ { "4.14.34", "Invalid cRLIssuer Test34", {bad_cert,{revoked, keyCompromise}}},
+ { "4.14.35", "Invalid cRLIssuer Test35", {bad_cert, revocation_status_undetermined}}
+ ]).
+
+
+%%distribution_points() ->
+ %%{ "4.14", "Distribution Points" },
+%% [
+ %% Although this test is valid it has a circular dependency. As a result
+ %% an attempt is made to reursively checks a CRL path and rejected due to
+ %% a CRL path validation error. PKITS notes suggest this test does not
+ %% need to be run due to this issue.
+%% { "4.14.30", "Valid cRLIssuer Test30", 54 }].
+
+
+%%-----------------------------------------------------------------------------
+
+unknown_critical_extension(doc) ->
+ [""];
+unknown_critical_extension(suite) ->
+ [];
+unknown_critical_extension(Config) when is_list(Config) ->
+ run([{ "4.16.2", "Invalid Unknown Critical Certificate Extension Test2",
+ {bad_cert,unknown_critical_extension}}]).
+
+unknown_not_critical_extension(doc) ->
+ [""];
+unknown_not_critical_extension(suite) ->
+ [];
+unknown_not_critical_extension(Config) when is_list(Config) ->
+ run([{ "4.16.1", "Valid Unknown Not Critical Certificate Extension Test1", ok}]).
+
+%%-----------------------------------------------------------------------------
run(Tests) ->
File = file(?CERTS,"TrustAnchorRootCertificate.crt"),
{ok, TA} = file:read_file(File),
run(Tests, TA).
run({Chap, Test, Result}, TA) ->
- CertChain = sort_chain(read_certs(Test),TA, [], false),
- try public_key:pkix_path_validation(TA, CertChain, []) of
- {Result, _} -> ok;
+ CertChain = sort_chain(read_certs(Test),TA, [], false, Chap),
+ Options = path_validation_options(TA, Chap,Test),
+ try public_key:pkix_path_validation(TA, CertChain, Options) of
+ {Result, _} -> ok;
{error,Result} when Result =/= ok ->
ok;
- {error,Error} when is_integer(Result) ->
- ?warning(" ~p~n Got ~p expected ~p~n",[Test, Error, Result]);
- {error,Error} when Result =/= ok ->
- ?error(" minor ~p~n Got ~p expected ~p~n",[Test, Error, Result]);
{error, Error} ->
?error(" ~p ~p~n Expected ~p got ~p ~n", [Chap, Test, Result, Error]),
fail;
- {ok, _} when Result =/= ok ->
+ {ok, _OK} when Result =/= ok ->
?error(" ~p ~p~n Expected ~p got ~p ~n", [Chap, Test, Result, ok]),
fail
catch Type:Reason ->
@@ -181,14 +821,318 @@ run([Test|Rest],TA) ->
run(Rest,TA);
run([],_) -> ok.
+path_validation_options(TA, Chap, Test) ->
+ case needs_crl_options(Chap) of
+ true ->
+ crl_options(TA, Test);
+ false ->
+ Fun =
+ fun(_,{bad_cert, _} = Reason, _) ->
+ {fail, Reason};
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, Valid, UserState) when Valid == valid;
+ Valid == valid_peer ->
+ {valid, UserState}
+ end,
+ [{verify_fun, {Fun, []}}]
+ end.
+
+needs_crl_options("4.4" ++ _) ->
+ true;
+needs_crl_options("4.5" ++ _) ->
+ true;
+needs_crl_options("4.7.4" ++ _) ->
+ true;
+needs_crl_options("4.7.5" ++ _) ->
+ true;
+needs_crl_options("4.14" ++ _) ->
+ true;
+needs_crl_options("4.15" ++ _) ->
+ true;
+needs_crl_options(_) ->
+ false.
+
+crl_options(TA, Test) ->
+ case read_crls(Test) of
+ [] ->
+ [];
+ CRLs ->
+ Fun =
+ fun(_,{bad_cert, _} = Reason, _) ->
+ {fail, Reason};
+ (_,{extension,
+ #'Extension'{extnID = ?'id-ce-cRLDistributionPoints',
+ extnValue = Value}}, UserState0) ->
+ UserState = update_crls(Value, UserState0),
+ {valid, UserState};
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (OtpCert, Valid, UserState) when Valid == valid;
+ Valid == valid_peer ->
+ {ErlCerts, CRLs} = UserState#verify_state.crl_info,
+ CRLInfo0 =
+ crl_info(OtpCert,
+ ErlCerts,[{DerCRL, public_key:der_decode('CertificateList',
+ DerCRL)} || DerCRL <- CRLs],
+ []),
+ CRLInfo = lists:reverse(CRLInfo0),
+ Certs = UserState#verify_state.certs_db,
+ Fun = fun(DP, CRLtoValidate, Id, CertsDb) ->
+ trusted_cert_and_path(DP, CRLtoValidate, Id, CertsDb)
+ end,
+ Ignore = ignore_sign_test_when_building_path(Test),
+ case public_key:pkix_crls_validate(OtpCert, CRLInfo,
+ [{issuer_fun,{Fun, {Ignore, Certs}}}]) of
+ valid ->
+ {valid, UserState};
+ Reason ->
+ {fail, Reason}
+ end
+ end,
+
+ Certs = read_certs(Test),
+ ErlCerts = [public_key:pkix_decode_cert(Cert, otp) || Cert <- Certs],
+
+ [{verify_fun, {Fun, #verify_state{certs_db = [TA| Certs],
+ crl_info = {ErlCerts, CRLs}}}}]
+ end.
+
+crl_info(_, _, [], Acc) ->
+ Acc;
+crl_info(OtpCert, Certs, [{_, #'CertificateList'{tbsCertList =
+ #'TBSCertList'{issuer = Issuer,
+ crlExtensions = CRLExtensions}}}
+ = CRL | Rest], Acc) ->
+ OtpTBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
+ Extensions = OtpTBSCert#'OTPTBSCertificate'.extensions,
+ ExtList = pubkey_cert:extensions_list(CRLExtensions),
+ DPs = case pubkey_cert:select_extension(?'id-ce-cRLDistributionPoints', Extensions) of
+ #'Extension'{extnValue = Value} ->
+ lists:map(fun(Point) -> pubkey_cert_records:transform(Point, decode) end, Value);
+ _ ->
+ case same_issuer(OtpCert, Issuer) of
+ true ->
+ [make_dp(ExtList, asn1_NOVALUE, Issuer)];
+ false ->
+ [make_dp(ExtList, Issuer, ignore)]
+ end
+ end,
+ DPsCRLs = lists:map(fun(DP) -> {DP, CRL} end, DPs),
+ crl_info(OtpCert, Certs, Rest, DPsCRLs ++ Acc).
+
+ignore_sign_test_when_building_path("Invalid Bad CRL Signature Test4") ->
+ true;
+ignore_sign_test_when_building_path(_) ->
+ false.
+
+same_issuer(OTPCert, Issuer) ->
+ DecIssuer = pubkey_cert_records:transform(Issuer, decode),
+ OTPTBSCert = OTPCert#'OTPCertificate'.tbsCertificate,
+ CertIssuer = OTPTBSCert#'OTPTBSCertificate'.issuer,
+ pubkey_cert:is_issuer(DecIssuer, CertIssuer).
+
+make_dp(Extensions, Issuer0, DpInfo) ->
+ {Issuer, Point} = mk_issuer_dp(Issuer0, DpInfo),
+ case pubkey_cert:select_extension('id-ce-cRLReason', Extensions) of
+ #'Extension'{extnValue = Reasons} ->
+ #'DistributionPoint'{cRLIssuer = Issuer,
+ reasons = Reasons,
+ distributionPoint = Point};
+ _ ->
+ #'DistributionPoint'{cRLIssuer = Issuer,
+ reasons = [unspecified, keyCompromise,
+ cACompromise, affiliationChanged, superseded,
+ cessationOfOperation, certificateHold,
+ removeFromCRL, privilegeWithdrawn, aACompromise],
+ distributionPoint = Point}
+ end.
+
+mk_issuer_dp(asn1_NOVALUE, Issuer) ->
+ {asn1_NOVALUE, {fullName, [{directoryName, Issuer}]}};
+mk_issuer_dp(Issuer, _) ->
+ {[{directoryName, Issuer}], asn1_NOVALUE}.
+
+update_crls(_, State) ->
+ State.
+
+trusted_cert_and_path(DP, CRL, Id, {Ignore, CertsList}) ->
+ case crl_issuer(crl_issuer_name(DP), CRL, Id, CertsList, CertsList, Ignore) of
+ {ok, IssuerCert, DerIssuerCert} ->
+ Certs = [{public_key:pkix_decode_cert(Cert, otp), Cert} || Cert <- CertsList],
+ CertChain = build_chain(Certs, Certs, IssuerCert, Ignore, [DerIssuerCert]),
+ {ok, public_key:pkix_decode_cert(hd(CertChain), otp), CertChain};
+ Other ->
+ Other
+ end.
+
+crl_issuer_name(#'DistributionPoint'{cRLIssuer = asn1_NOVALUE}) ->
+ undefined;
+crl_issuer_name(#'DistributionPoint'{cRLIssuer = [{directoryName, Issuer}]}) ->
+ pubkey_cert_records:transform(Issuer, decode).
+
+build_chain([],_, _, _,Acc) ->
+ Acc;
+
+build_chain([{First, DerFirst}|Certs], All, Cert, Ignore, Acc) ->
+ case public_key:pkix_is_self_signed(Cert) andalso is_test_root(Cert) of
+ true ->
+ Acc;
+ false ->
+ case public_key:pkix_is_issuer(Cert, First)
+ %%andalso check_extension_cert_signer(First)
+ andalso is_signer(First, Cert, Ignore)
+ of
+ true ->
+ build_chain(All, All, First, Ignore, [DerFirst | Acc]);
+ false ->
+ build_chain(Certs, All, Cert, Ignore, Acc)
+ end
+ end.
+
+is_signer(_,_, true) ->
+ true;
+is_signer(Signer, #'OTPCertificate'{} = Cert,_) ->
+ TBSCert = Signer#'OTPCertificate'.tbsCertificate,
+ PublicKeyInfo = TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo,
+ PublicKey = PublicKeyInfo#'OTPSubjectPublicKeyInfo'.subjectPublicKey,
+ AlgInfo = PublicKeyInfo#'OTPSubjectPublicKeyInfo'.algorithm,
+ PublicKeyParams = AlgInfo#'PublicKeyAlgorithm'.parameters,
+ try pubkey_cert:validate_signature(Cert, public_key:pkix_encode('OTPCertificate',
+ Cert, otp),
+ PublicKey, PublicKeyParams, true, ?DEFAULT_VERIFYFUN) of
+ true ->
+ true
+ catch
+ _:_ ->
+ false
+ end;
+is_signer(Signer, #'CertificateList'{} = CRL, _) ->
+ TBSCert = Signer#'OTPCertificate'.tbsCertificate,
+ PublicKeyInfo = TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo,
+ PublicKey = PublicKeyInfo#'OTPSubjectPublicKeyInfo'.subjectPublicKey,
+ AlgInfo = PublicKeyInfo#'OTPSubjectPublicKeyInfo'.algorithm,
+ PublicKeyParams = AlgInfo#'PublicKeyAlgorithm'.parameters,
+ pubkey_crl:verify_crl_signature(CRL, public_key:pkix_encode('CertificateList',
+ CRL, plain),
+ PublicKey, PublicKeyParams).
+
+is_test_root(OtpCert) ->
+ TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
+ {rdnSequence, AtterList} = TBSCert#'OTPTBSCertificate'.issuer,
+ lists:member([{'AttributeTypeAndValue',{2,5,4,3},{printableString,"Trust Anchor"}}],
+ AtterList).
+
+check_extension_cert_signer(OtpCert) ->
+ TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
+ Extensions = TBSCert#'OTPTBSCertificate'.extensions,
+ case pubkey_cert:select_extension(?'id-ce-keyUsage', Extensions) of
+ #'Extension'{extnValue = KeyUse} ->
+ lists:member(keyCertSign, KeyUse);
+ _ ->
+ true
+ end.
+
+check_extension_crl_signer(OtpCert) ->
+ TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
+ Extensions = TBSCert#'OTPTBSCertificate'.extensions,
+ case pubkey_cert:select_extension(?'id-ce-keyUsage', Extensions) of
+ #'Extension'{extnValue = KeyUse} ->
+ lists:member(cRLSign, KeyUse);
+ _ ->
+ true
+ end.
+
+crl_issuer(undefined, CRL, issuer_not_found, _, CertsList, Ignore) ->
+ crl_issuer(CRL, CertsList, Ignore);
+
+crl_issuer(IssuerName, CRL, issuer_not_found, CertsList, CertsList, Ignore) ->
+ crl_issuer(IssuerName, CRL, IssuerName, CertsList, CertsList, Ignore);
+
+crl_issuer(undefined, CRL, Id, [Cert | Rest], All, false) ->
+ ErlCert = public_key:pkix_decode_cert(Cert, otp),
+ TBSCertificate = ErlCert#'OTPCertificate'.tbsCertificate,
+ SerialNumber = TBSCertificate#'OTPTBSCertificate'.serialNumber,
+ Issuer = public_key:pkix_normalize_name(
+ TBSCertificate#'OTPTBSCertificate'.subject),
+ Bool = is_signer(ErlCert, CRL, false),
+ case {SerialNumber, Issuer} of
+ Id when Bool == true ->
+ {ok, ErlCert, Cert};
+ _ ->
+ crl_issuer(undefined, CRL, Id, Rest, All, false)
+ end;
+
+crl_issuer(IssuerName, CRL, Id, [Cert | Rest], All, false) ->
+ ErlCert = public_key:pkix_decode_cert(Cert, otp),
+ TBSCertificate = ErlCert#'OTPCertificate'.tbsCertificate,
+ SerialNumber = TBSCertificate#'OTPTBSCertificate'.serialNumber,
+ %%Issuer = public_key:pkix_normalize_name(
+ %% TBSCertificate#'OTPTBSCertificate'.subject),
+ Bool = is_signer(ErlCert, CRL, false),
+ case {SerialNumber, IssuerName} of
+ Id when Bool == true ->
+ {ok, ErlCert, Cert};
+ {_, IssuerName} when Bool == true ->
+ {ok, ErlCert, Cert};
+ _ ->
+ crl_issuer(IssuerName, CRL, Id, Rest, All, false)
+ end;
+
+crl_issuer(undefined, CRL, _, [], CertsList, Ignore) ->
+ crl_issuer(CRL, CertsList, Ignore);
+crl_issuer(CRLName, CRL, _, [], CertsList, Ignore) ->
+ crl_issuer(CRLName, CRL, CertsList, Ignore).
+
+
+crl_issuer(_, [],_) ->
+ {error, issuer_not_found};
+crl_issuer(CRL, [Cert | Rest], Ignore) ->
+ ErlCert = public_key:pkix_decode_cert(Cert, otp),
+ case public_key:pkix_is_issuer(CRL, ErlCert) andalso
+ check_extension_crl_signer(ErlCert) andalso
+ is_signer(ErlCert, CRL, Ignore)
+ of
+ true ->
+ {ok, ErlCert,Cert};
+ false ->
+ crl_issuer(CRL, Rest, Ignore)
+ end.
+
+crl_issuer(_,_, [],_) ->
+ {error, issuer_not_found};
+crl_issuer(IssuerName, CRL, [Cert | Rest], Ignore) ->
+ ErlCert = public_key:pkix_decode_cert(Cert, otp),
+ TBSCertificate = ErlCert#'OTPCertificate'.tbsCertificate,
+ Issuer = public_key:pkix_normalize_name(
+ TBSCertificate#'OTPTBSCertificate'.subject),
+
+ case
+ public_key:pkix_is_issuer(CRL, ErlCert) andalso
+ check_extension_crl_signer(ErlCert) andalso
+ is_signer(ErlCert, CRL, Ignore)
+ of
+ true ->
+ case pubkey_cert:is_issuer(Issuer, IssuerName) of
+ true ->
+ {ok, ErlCert,Cert};
+ false ->
+ crl_issuer(IssuerName, CRL, Rest, Ignore)
+ end;
+ false ->
+ crl_issuer(IssuerName, CRL, Rest, Ignore)
+ end.
read_certs(Test) ->
File = test_file(Test),
- %% io:format("Read ~p ",[File]),
Ders = erl_make_certs:pem_to_der(File),
- %% io:format("Ders ~p ~n",[length(Ders)]),
[Cert || {'Certificate', Cert, not_encrypted} <- Ders].
+read_crls(Test) ->
+ File = test_file(Test),
+ Ders = erl_make_certs:pem_to_der(File),
+ [CRL || {'CertificateList', CRL, not_encrypted} <- Ders].
+
test_file(Test) ->
file(?CONV, lists:append(string:tokens(Test, " -")) ++ ".pem").
@@ -206,118 +1150,89 @@ file(Sub,File) ->
end,
AbsFile.
-sort_chain([First|Certs], TA, Try, Found) ->
+sort_chain(Certs, TA, Acc, Bool, Chap) when Chap == "4.5.3"->
+ [CA, Entity, Self] = do_sort_chain(Certs, TA, Acc, Bool, Chap),
+ [CA, Self, Entity];
+sort_chain(Certs, TA, Acc, Bool, Chap) when Chap == "4.5.4";
+ Chap == "4.5.5" ->
+ [CA, Entity, _Self] = do_sort_chain(Certs, TA, Acc, Bool, Chap),
+ [CA, Entity];
+
+sort_chain(Certs, TA, Acc, Bool, Chap) when Chap == "4.14.24";
+ Chap == "4.14.25";
+ Chap == "4.14.26";
+ Chap == "4.14.27";
+ Chap == "4.14.31";
+ Chap == "4.14.32";
+ Chap == "4.14.33" ->
+ [_OtherCA, Entity, CA] = do_sort_chain(Certs, TA, Acc, Bool, Chap),
+ [CA, Entity];
+
+sort_chain(Certs, TA, Acc, Bool, Chap) when Chap == "4.14.28";
+ Chap == "4.14.29" ->
+ [CA, _OtherCA, Entity] = do_sort_chain(Certs, TA, Acc, Bool, Chap),
+ [CA, Entity];
+
+
+sort_chain(Certs, TA, Acc, Bool, Chap) when Chap == "4.14.33" ->
+ [Entity, CA, _OtherCA] = do_sort_chain(Certs, TA, Acc, Bool, Chap),
+ [CA, Entity];
+
+
+sort_chain(Certs, TA, Acc, Bool, Chap) ->
+ do_sort_chain(Certs, TA, Acc, Bool, Chap).
+
+do_sort_chain([First], TA, Try, Found, Chap) when Chap == "4.5.6";
+ Chap == "4.5.7";
+ Chap == "4.4.19";
+ Chap == "4.4.20";
+ Chap == "4.4.21"->
case public_key:pkix_is_issuer(First,TA) of
true ->
- [First|sort_chain(Certs,First,Try,true)];
+ [First|do_sort_chain([],First,Try,true, Chap)];
false ->
- sort_chain(Certs,TA,[First|Try],Found)
+ do_sort_chain([],TA,[First|Try],Found, Chap)
end;
-sort_chain([], _, [],_) -> [];
-sort_chain([], Valid, Check, true) ->
- sort_chain(lists:reverse(Check), Valid, [], false);
-sort_chain([], _Valid, Check, false) ->
+do_sort_chain([First|Certs], TA, Try, Found, Chap) when Chap == "4.5.6";
+ Chap == "4.5.7";
+ Chap == "4.4.19";
+ Chap == "4.4.20";
+ Chap == "4.4.21"->
+%% case check_extension_cert_signer(public_key:pkix_decode_cert(First, otp)) of
+%% true ->
+ case public_key:pkix_is_issuer(First,TA) of
+ true ->
+ [First|do_sort_chain(Certs,First,Try,true, Chap)];
+ false ->
+ do_sort_chain(Certs,TA,[First|Try],Found, Chap)
+ end;
+%% false ->
+%% do_sort_chain(Certs, TA, Try, Found, Chap)
+%% end;
+
+do_sort_chain([First|Certs], TA, Try, Found, Chap) ->
+ case public_key:pkix_is_issuer(First,TA) of
+ true ->
+ [First|do_sort_chain(Certs,First,Try,true, Chap)];
+ false ->
+ do_sort_chain(Certs,TA,[First|Try],Found, Chap)
+ end;
+
+do_sort_chain([], _, [],_, _) -> [];
+do_sort_chain([], Valid, Check, true, Chap) ->
+ do_sort_chain(lists:reverse(Check), Valid, [], false, Chap);
+do_sort_chain([], _Valid, Check, false, _) ->
Check.
-signature_verification() ->
- %% "4.1", "Signature Verification" ,
- [{ "4.1.1", "Valid Signatures Test1", ok},
- { "4.1.2", "Invalid CA Signature Test2", {bad_cert,invalid_signature}},
- { "4.1.3", "Invalid EE Signature Test3", {bad_cert,invalid_signature}},
- { "4.1.4", "Valid DSA Signatures Test4", ok},
- { "4.1.5", "Valid DSA Parameter Inheritance Test5", ok},
- { "4.1.6", "Invalid DSA Signature Test6", {bad_cert,invalid_signature}}].
-validity_periods() ->
- %% { "4.2", "Validity Periods" },
- [{ "4.2.1", "Invalid CA notBefore Date Test1", {bad_cert, cert_expired}},
- { "4.2.2", "Invalid EE notBefore Date Test2", {bad_cert, cert_expired}},
- { "4.2.3", "Valid pre2000 UTC notBefore Date Test3", ok},
- { "4.2.4", "Valid GeneralizedTime notBefore Date Test4", ok},
- { "4.2.5", "Invalid CA notAfter Date Test5", {bad_cert, cert_expired}},
- { "4.2.6", "Invalid EE notAfter Date Test6", {bad_cert, cert_expired}},
- { "4.2.7", "Invalid pre2000 UTC EE notAfter Date Test7", {bad_cert, cert_expired}},
- { "4.2.8", "Valid GeneralizedTime notAfter Date Test8", ok}].
-verifying_name_chaining() ->
- %%{ "4.3", "Verifying Name Chaining" },
- [{ "4.3.1", "Invalid Name Chaining EE Test1", {bad_cert, invalid_issuer}},
- { "4.3.2", "Invalid Name Chaining Order Test2", {bad_cert, invalid_issuer}},
- { "4.3.3", "Valid Name Chaining Whitespace Test3", ok},
- { "4.3.4", "Valid Name Chaining Whitespace Test4", ok},
- { "4.3.5", "Valid Name Chaining Capitalization Test5", ok},
- { "4.3.6", "Valid Name Chaining UIDs Test6", ok},
- { "4.3.7", "Valid RFC3280 Mandatory Attribute Types Test7", ok},
- { "4.3.8", "Valid RFC3280 Optional Attribute Types Test8", ok},
- { "4.3.9", "Valid UTF8String Encoded Names Test9", ok},
- { "4.3.10", "Valid Rollover from PrintableString to UTF8String Test10", ok},
- { "4.3.11", "Valid UTF8String Case Insensitive Match Test11", ok}].
-basic_certificate_revocation_tests() ->
- %%{ "4.4", "Basic Certificate Revocation Tests" },
- [{ "4.4.1", "Missing CRL Test1", 3 },
- { "4.4.2", "Invalid Revoked CA Test2", 23 },
- { "4.4.3", "Invalid Revoked EE Test3", 23 },
- { "4.4.4", "Invalid Bad CRL Signature Test4", 8 },
- { "4.4.5", "Invalid Bad CRL Issuer Name Test5", 3 },
- { "4.4.6", "Invalid Wrong CRL Test6", 3 },
- { "4.4.7", "Valid Two CRLs Test7", ok},
-
- %% The test document suggests these should return certificate revoked...
- %% Subsquent discussion has concluded they should not due to unhandle
- %% critical CRL extensions.
- { "4.4.8", "Invalid Unknown CRL Entry Extension Test8", 36 },
- { "4.4.9", "Invalid Unknown CRL Extension Test9", 36 },
-
- { "4.4.10", "Invalid Unknown CRL Extension Test10", 36 },
- { "4.4.11", "Invalid Old CRL nextUpdate Test11", 12 },
- { "4.4.12", "Invalid pre2000 CRL nextUpdate Test12", 12 },
- { "4.4.13", "Valid GeneralizedTime CRL nextUpdate Test13", ok},
- { "4.4.14", "Valid Negative Serial Number Test14", ok},
- { "4.4.15", "Invalid Negative Serial Number Test15", 23 },
- { "4.4.16", "Valid Long Serial Number Test16", ok},
- { "4.4.17", "Valid Long Serial Number Test17", ok},
- { "4.4.18", "Invalid Long Serial Number Test18", 23 },
- { "4.4.19", "Valid Separate Certificate and CRL Keys Test19", ok},
- { "4.4.20", "Invalid Separate Certificate and CRL Keys Test20", 23 },
-
- %% CRL path is revoked so get a CRL path validation error
- { "4.4.21", "Invalid Separate Certificate and CRL Keys Test21", 54 }].
-verifying_paths_with_self_issued_certificates() ->
- %%{ "4.5", "Verifying Paths with Self-Issued Certificates" },
- [{ "4.5.1", "Valid Basic Self-Issued Old With New Test1", ok},
- %%{ "4.5.2", "Invalid Basic Self-Issued Old With New Test2", 23 },
- %%{ "4.5.3", "Valid Basic Self-Issued New With Old Test3", ok},
- %%{ "4.5.4", "Valid Basic Self-Issued New With Old Test4", ok},
- { "4.5.5", "Invalid Basic Self-Issued New With Old Test5", 23 },
- %%{ "4.5.6", "Valid Basic Self-Issued CRL Signing Key Test6", ok},
- { "4.5.7", "Invalid Basic Self-Issued CRL Signing Key Test7", 23 },
- { "4.5.8", "Invalid Basic Self-Issued CRL Signing Key Test8", {bad_cert,invalid_key_usage} }].
-verifying_basic_constraints() ->
- [%%{ "4.6", "Verifying Basic Constraints" },
- { "4.6.1", "Invalid Missing basicConstraints Test1",
- {bad_cert, missing_basic_constraint} },
- { "4.6.2", "Invalid cA False Test2", {bad_cert, missing_basic_constraint}},
- { "4.6.3", "Invalid cA False Test3", {bad_cert, missing_basic_constraint}},
- { "4.6.4", "Valid basicConstraints Not Critical Test4", ok},
- { "4.6.5", "Invalid pathLenConstraint Test5", {bad_cert, max_path_length_reached}},
- { "4.6.6", "Invalid pathLenConstraint Test6", {bad_cert, max_path_length_reached}},
- { "4.6.7", "Valid pathLenConstraint Test7", ok},
- { "4.6.8", "Valid pathLenConstraint Test8", ok},
- { "4.6.9", "Invalid pathLenConstraint Test9", {bad_cert, max_path_length_reached}},
- { "4.6.10", "Invalid pathLenConstraint Test10", {bad_cert, max_path_length_reached}},
- { "4.6.11", "Invalid pathLenConstraint Test11", {bad_cert, max_path_length_reached}},
- { "4.6.12", "Invalid pathLenConstraint Test12", {bad_cert, max_path_length_reached}},
- { "4.6.13", "Valid pathLenConstraint Test13", ok},
- { "4.6.14", "Valid pathLenConstraint Test14", ok},
- { "4.6.15", "Valid Self-Issued pathLenConstraint Test15", ok},
- { "4.6.16", "Invalid Self-Issued pathLenConstraint Test16", {bad_cert, max_path_length_reached}},
- { "4.6.17", "Valid Self-Issued pathLenConstraint Test17", ok}].
-key_usage() ->
- %%{ "4.7", "Key Usage" },
- [{ "4.7.1", "Invalid keyUsage Critical keyCertSign False Test1", {bad_cert,invalid_key_usage} },
- { "4.7.2", "Invalid keyUsage Not Critical keyCertSign False Test2", {bad_cert,invalid_key_usage} },
- { "4.7.3", "Valid keyUsage Not Critical Test3", ok}
- %%,{ "4.7.4", "Invalid keyUsage Critical cRLSign False Test4", 35 }
- %%,{ "4.7.5", "Invalid keyUsage Not Critical cRLSign False Test5", 35 }
- ].
+error(Format, Args, File0, Line) ->
+ File = filename:basename(File0),
+ Pid = group_leader(),
+ Pid ! {failed, File, Line},
+ io:format(Pid, "~s(~p): ERROR"++Format, [File,Line|Args]).
+
+warning(Format, Args, File0, Line) ->
+ File = filename:basename(File0),
+ io:format("~s(~p): Warning "++Format, [File,Line|Args]).
%% Certificate policy tests need special handling. They can have several
%% sub tests and we need to check the outputs are correct.
@@ -425,182 +1340,3 @@ inhibit_any_policy() ->
{"4.12.8", "Invalid Self-Issued inhibitAnyPolicy Test8", 43 },
{"4.12.9", "Valid Self-Issued inhibitAnyPolicy Test9", ok},
{"4.12.10", "Invalid Self-Issued inhibitAnyPolicy Test10", 43 }].
-
-name_constraints() ->
- %%{ "4.13", "Name Constraints" },
- [{ "4.13.1", "Valid DN nameConstraints Test1", ok},
- { "4.13.2", "Invalid DN nameConstraints Test2", {bad_cert, name_not_permitted}},
- { "4.13.3", "Invalid DN nameConstraints Test3", {bad_cert, name_not_permitted}},
- { "4.13.4", "Valid DN nameConstraints Test4", ok},
- { "4.13.5", "Valid DN nameConstraints Test5", ok},
- { "4.13.6", "Valid DN nameConstraints Test6", ok},
- { "4.13.7", "Invalid DN nameConstraints Test7", {bad_cert, name_not_permitted}},
- { "4.13.8", "Invalid DN nameConstraints Test8", {bad_cert, name_not_permitted}},
- { "4.13.9", "Invalid DN nameConstraints Test9", {bad_cert, name_not_permitted}},
- { "4.13.10", "Invalid DN nameConstraints Test10", {bad_cert, name_not_permitted}},
- { "4.13.11", "Valid DN nameConstraints Test11", ok},
- { "4.13.12", "Invalid DN nameConstraints Test12", {bad_cert, name_not_permitted}},
- { "4.13.13", "Invalid DN nameConstraints Test13", {bad_cert, name_not_permitted}},
- { "4.13.14", "Valid DN nameConstraints Test14", ok},
- { "4.13.15", "Invalid DN nameConstraints Test15", {bad_cert, name_not_permitted}},
- { "4.13.16", "Invalid DN nameConstraints Test16", {bad_cert, name_not_permitted}},
- { "4.13.17", "Invalid DN nameConstraints Test17", {bad_cert, name_not_permitted}},
- { "4.13.18", "Valid DN nameConstraints Test18", ok},
- { "4.13.19", "Valid Self-Issued DN nameConstraints Test19", ok},
- { "4.13.20", "Invalid Self-Issued DN nameConstraints Test20", {bad_cert, name_not_permitted} },
- { "4.13.21", "Valid RFC822 nameConstraints Test21", ok},
- { "4.13.22", "Invalid RFC822 nameConstraints Test22", {bad_cert, name_not_permitted} },
- { "4.13.23", "Valid RFC822 nameConstraints Test23", ok},
- { "4.13.24", "Invalid RFC822 nameConstraints Test24", {bad_cert, name_not_permitted} },
- { "4.13.25", "Valid RFC822 nameConstraints Test25", ok},
- { "4.13.26", "Invalid RFC822 nameConstraints Test26", {bad_cert, name_not_permitted}},
- { "4.13.27", "Valid DN and RFC822 nameConstraints Test27", ok},
- { "4.13.28", "Invalid DN and RFC822 nameConstraints Test28", {bad_cert, name_not_permitted} },
- { "4.13.29", "Invalid DN and RFC822 nameConstraints Test29", {bad_cert, name_not_permitted} },
- { "4.13.30", "Valid DNS nameConstraints Test30", ok},
- { "4.13.31", "Invalid DNS nameConstraints Test31", {bad_cert, name_not_permitted} },
- { "4.13.32", "Valid DNS nameConstraints Test32", ok},
- { "4.13.33", "Invalid DNS nameConstraints Test33", {bad_cert, name_not_permitted}},
- { "4.13.34", "Valid URI nameConstraints Test34", ok},
- { "4.13.35", "Invalid URI nameConstraints Test35", {bad_cert, name_not_permitted} },
- { "4.13.36", "Valid URI nameConstraints Test36", ok},
- { "4.13.37", "Invalid URI nameConstraints Test37", {bad_cert, name_not_permitted}},
- { "4.13.38", "Invalid DNS nameConstraints Test38", {bad_cert, name_not_permitted} }].
-distribution_points() ->
- %%{ "4.14", "Distribution Points" },
- [{ "4.14.1", "Valid distributionPoint Test1", ok},
- { "4.14.2", "Invalid distributionPoint Test2", 23 },
- { "4.14.3", "Invalid distributionPoint Test3", 44 },
- { "4.14.4", "Valid distributionPoint Test4", ok},
- { "4.14.5", "Valid distributionPoint Test5", ok},
- { "4.14.6", "Invalid distributionPoint Test6", 23 },
- { "4.14.7", "Valid distributionPoint Test7", ok},
- { "4.14.8", "Invalid distributionPoint Test8", 44 },
- { "4.14.9", "Invalid distributionPoint Test9", 44 },
- { "4.14.10", "Valid No issuingDistributionPoint Test10", ok},
- { "4.14.11", "Invalid onlyContainsUserCerts CRL Test11", 44 },
- { "4.14.12", "Invalid onlyContainsCACerts CRL Test12", 44 },
- { "4.14.13", "Valid onlyContainsCACerts CRL Test13", ok},
- { "4.14.14", "Invalid onlyContainsAttributeCerts Test14", 44 },
- { "4.14.15", "Invalid onlySomeReasons Test15", 23 },
- { "4.14.16", "Invalid onlySomeReasons Test16", 23 },
- { "4.14.17", "Invalid onlySomeReasons Test17", 3 },
- { "4.14.18", "Valid onlySomeReasons Test18", ok},
- { "4.14.19", "Valid onlySomeReasons Test19", ok},
- { "4.14.20", "Invalid onlySomeReasons Test20", 23 },
- { "4.14.21", "Invalid onlySomeReasons Test21", 23 },
- { "4.14.22", "Valid IDP with indirectCRL Test22", ok},
- { "4.14.23", "Invalid IDP with indirectCRL Test23", 23 },
- { "4.14.24", "Valid IDP with indirectCRL Test24", ok},
- { "4.14.25", "Valid IDP with indirectCRL Test25", ok},
- { "4.14.26", "Invalid IDP with indirectCRL Test26", 44 },
- { "4.14.27", "Invalid cRLIssuer Test27", 3 },
- { "4.14.28", "Valid cRLIssuer Test28", ok},
- { "4.14.29", "Valid cRLIssuer Test29", ok},
-
- %% Although this test is valid it has a circular dependency. As a result
- %% an attempt is made to reursively checks a CRL path and rejected due to
- %% a CRL path validation error. PKITS notes suggest this test does not
- %% need to be run due to this issue.
- { "4.14.30", "Valid cRLIssuer Test30", 54 },
- { "4.14.31", "Invalid cRLIssuer Test31", 23 },
- { "4.14.32", "Invalid cRLIssuer Test32", 23 },
- { "4.14.33", "Valid cRLIssuer Test33", ok},
- { "4.14.34", "Invalid cRLIssuer Test34", 23 },
- { "4.14.35", "Invalid cRLIssuer Test35", 44 }].
-delta_crls() ->
- %%{ "4.15", "Delta-CRLs" },
- [{ "4.15.1", "Invalid deltaCRLIndicator No Base Test1", 3 },
- { "4.15.2", "Valid delta-CRL Test2", ok},
- { "4.15.3", "Invalid delta-CRL Test3", 23 },
- { "4.15.4", "Invalid delta-CRL Test4", 23 },
- { "4.15.5", "Valid delta-CRL Test5", ok},
- { "4.15.6", "Invalid delta-CRL Test6", 23 },
- { "4.15.7", "Valid delta-CRL Test7", ok},
- { "4.15.8", "Valid delta-CRL Test8", ok},
- { "4.15.9", "Invalid delta-CRL Test9", 23 },
- { "4.15.10", "Invalid delta-CRL Test10", 12 }].
-private_certificate_extensions() ->
- %%{ "4.16", "Private Certificate Extensions" },
- [{ "4.16.1", "Valid Unknown Not Critical Certificate Extension Test1", ok},
- { "4.16.2", "Invalid Unknown Critical Certificate Extension Test2",
- {bad_cert,unknown_critical_extension}}].
-
-
-convert() ->
- Tests = [signature_verification(),
- validity_periods(),
- verifying_name_chaining(),
- basic_certificate_revocation_tests(),
- verifying_paths_with_self_issued_certificates(),
- verifying_basic_constraints(),
- key_usage(),
- certificate_policies(),
- require_explicit_policy(),
- policy_mappings(),
- inhibit_policy_mapping(),
- inhibit_any_policy(),
- name_constraints(),
- distribution_points(),
- delta_crls(),
- private_certificate_extensions()],
- [convert(Test) || Test <- lists:flatten(Tests)].
-
-convert({_,Test,_}) ->
- convert1(Test);
-convert({_,Test,_,_,_,_,_}) ->
- convert1(Test).
-
-convert1(Test) ->
- FName = lists:append(string:tokens(Test, " -")),
- File = filename:join(?MIME, "Signed" ++ FName ++ ".eml"),
- io:format("Convert ~p~n",[File]),
- {ok, Mail} = file:read_file(File),
- Base64 = skip_lines(Mail),
- %%io:format("~s",[Base64]),
- Tmp = base64:mime_decode(Base64),
- file:write_file("pkits/smime-pem/tmp-pkcs7.der", Tmp),
- Cmd = "openssl pkcs7 -inform der -in pkits/smime-pem/tmp-pkcs7.der"
- " -print_certs -out pkits/smime-pem/" ++ FName ++ ".pem",
- case os:cmd(Cmd) of
- "" -> ok;
- Err ->
- io:format("~s",[Err]),
- erlang:error(bad_cmd)
- end.
-
-skip_lines(<<"\r\n\r\n", Rest/binary>>) -> Rest;
-skip_lines(<<"\n\n", Rest/binary>>) -> Rest;
-skip_lines(<<_:8, Rest/binary>>) ->
- skip_lines(Rest).
-
-init_per_testcase(_Func, Config) ->
- Datadir = proplists:get_value(data_dir, Config),
- put(datadir, Datadir),
- Config.
-
-end_per_testcase(_Func, Config) ->
- %% Nodes = select_nodes(all, Config, ?FILE, ?LINE),
- %% rpc:multicall(Nodes, mnesia, lkill, []),
- Config.
-
-init_per_suite(Config) ->
- try crypto:start() of
- ok ->
- Config
- catch _:_ ->
- {skip, "Crypto did not start"}
- end.
-
-end_per_suite(_Config) ->
- application:stop(crypto).
-
-error(Format, Args, File0, Line) ->
- File = filename:basename(File0),
- Pid = group_leader(),
- Pid ! {failed, File, Line},
- io:format(Pid, "~s(~p): ERROR"++Format, [File,Line|Args]).
-
-warning(Format, Args, File0, Line) ->
- File = filename:basename(File0),
- io:format("~s(~p): Warning "++Format, [File,Line|Args]).
diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk
index c99fd6fee1..66ac78a65d 100644
--- a/lib/public_key/vsn.mk
+++ b/lib/public_key/vsn.mk
@@ -1 +1 @@
-PUBLIC_KEY_VSN = 0.11
+PUBLIC_KEY_VSN = 0.13
diff --git a/lib/reltool/doc/src/notes.xml b/lib/reltool/doc/src/notes.xml
index a791f2ce03..5304b996a4 100644
--- a/lib/reltool/doc/src/notes.xml
+++ b/lib/reltool/doc/src/notes.xml
@@ -37,7 +37,61 @@
thus constitutes one section in this document. The title of each
section is the version number of Reltool.</p>
- <section><title>Reltool 0.5.5</title>
+ <section><title>Reltool 0.5.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ If a module was duplicated in the library directories
+ visible to reltool, and the configuration did not point
+ out which file to use, then reltool:start would always
+ fail. A pop-up is added which asks if you want to
+ continue with a safe and minimal configuration.</p>
+ <p>
+ Own Id: OTP-9383</p>
+ </item>
+ <item>
+ <p>
+ wx would sometimes crash due to an empty radiobox on the
+ 'releases' tab of the system window. This radiobox is
+ removed, and replaced by a listbox which will always
+ contain at least kernel and stdlib applications.</p>
+ <p>
+ Own Id: OTP-9384</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Reltool 0.5.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The system level option <c>app_files</c> is documented to
+ allow the values <c>keep | strip | all</c>, but it only
+ allowed <c>keep</c>. This is corrected.</p>
+ <p>
+ Own Id: OTP-9135</p>
+ </item>
+ <item>
+ <p>
+ Allow the same module name in multiple applications
+ visible to reltool, as long as all but one of the
+ applications/modules are explicitely excluded. (Thanks to
+ Andrew Gopienko and Jay Nelson)</p>
+ <p>
+ Own Id: OTP-9229</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Reltool 0.5.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/reltool/src/reltool_server.erl b/lib/reltool/src/reltool_server.erl
index 9743289ca6..692baea0a4 100644
--- a/lib/reltool/src/reltool_server.erl
+++ b/lib/reltool/src/reltool_server.erl
@@ -465,16 +465,16 @@ analyse(#state{common = C,
[MissingApp2 | Apps2]
end,
app_propagate_is_used_by(C, Apps3),
- Apps4 = read_apps(C, Sys, Apps3, []),
+ {Apps4,Status4} = app_recap_dependencies(C, Sys, Apps3, [], Status3),
%% io:format("Missing app: ~p\n",
%% [lists:keysearch(?MISSING_APP_NAME, #app.name, Apps4)]),
Sys2 = Sys#sys{apps = Apps4},
- case verify_config(RelApps2, Sys2, Status3) of
- {ok, _Warnings} = Status4 ->
- {S#state{sys = Sys2}, Status4};
- {error, _} = Status4 ->
- {S, Status4}
+ case verify_config(RelApps2, Sys2, Status4) of
+ {ok, _Warnings} = Status5 ->
+ {S#state{sys = Sys2}, Status5};
+ {error, _} = Status5 ->
+ {S, Status5}
end.
apps_in_rels(Rels, Apps, Status) ->
@@ -548,21 +548,24 @@ app_init_is_included(C,
{derived, [_ | _]} -> % App is included in at least one rel
{true, undefined, true, Status}
end,
- A2 = A#app{is_pre_included = IsPreIncl,
+ {Mods2,Status3} = lists:mapfoldl(fun(Mod,Acc) ->
+ mod_init_is_included(C,
+ Mod,
+ ModCond,
+ AppCond,
+ Default,
+ Acc)
+ end,
+ Status2,
+ Mods),
+ A2 = A#app{mods = Mods2,
+ is_pre_included = IsPreIncl,
is_included = IsIncl,
rels = Rels},
ets:insert(C#common.app_tab, A2),
- lists:foreach(fun(Mod) ->
- mod_init_is_included(C,
- Mod,
- ModCond,
- AppCond,
- Default)
- end,
- Mods),
- {A2, Status2}.
-
-mod_init_is_included(C, M, ModCond, AppCond, Default) ->
+ {A2, Status3}.
+
+mod_init_is_included(C, M, ModCond, AppCond, Default, Status) ->
%% print(M#mod.name, hipe, "incl_cond -> ~p\n", [AppCond]),
IsIncl =
case AppCond of
@@ -595,9 +598,52 @@ mod_init_is_included(C, M, ModCond, AppCond, Default) ->
Default
end
end,
+
M2 = M#mod{is_pre_included = IsIncl, is_included = IsIncl},
+
+ Status2 =
+ case ets:lookup(C#common.mod_tab,M#mod.name) of
+ [Existing] ->
+ case {Existing#mod.is_included,IsIncl} of
+ {false,_} ->
+ Warning =
+ lists:concat(
+ ["Module ",M#mod.name,
+ " exists in applications ", Existing#mod.app_name,
+ " and ", M#mod.app_name,
+ ". Using module from application ",
+ M#mod.app_name, "."]),
+ ets:insert(C#common.mod_tab, M2),
+ reltool_utils:add_warning(Status,Warning);
+ {_,false} ->
+ Warning =
+ lists:concat(
+ ["Module ",M#mod.name,
+ " exists in applications ", Existing#mod.app_name,
+ " and ", M#mod.app_name,
+ ". Using module from application ",
+ Existing#mod.app_name, "."]),
+
+ %% Don't insert in mod_tab - using Existing
+ reltool_utils:add_warning(Status,Warning);
+ {_,_} ->
+ Error =
+ lists:concat(
+ ["Module ",M#mod.name,
+ " potentially included by ",
+ "two different applications: ",
+ Existing#mod.app_name, " and ",
+ M#mod.app_name, "."]),
+ %% Don't insert in mod_tab - using Existing
+ reltool_utils:return_first_error(Status,Error)
+ end;
+ [] ->
+ ets:insert(C#common.mod_tab, M2),
+ Status
+ end,
+
%% print(M#mod.name, hipe, "~p -> ~p\n", [M2, IsIncl]),
- ets:insert(C#common.mod_tab, M2).
+ {M2,Status2}.
false_to_undefined(Bool) ->
case Bool of
@@ -612,21 +658,27 @@ app_propagate_is_included(_C, _Sys, [], Acc) ->
Acc.
mod_propagate_is_included(C, Sys, A, [#mod{name = ModName} | Mods], Acc) ->
- [M2] = ets:lookup(C#common.mod_tab, ModName),
- %% print(ModName, file, "Maybe Prop ~p -> ~p\n",
- %% [M2, M2#mod.is_included]),
- %% print(ModName, filename, "Maybe Prop ~p -> ~p\n",
- %% [M2, M2#mod.is_included]),
Acc2 =
- case M2#mod.is_included of
- true ->
- %% Propagate include mark
- mod_mark_is_included(C, Sys, ModName, M2#mod.uses_mods, Acc);
- false ->
- Acc;
- undefined ->
- Acc
- end,
+ case ets:lookup(C#common.mod_tab, ModName) of
+ [M2] when M2#mod.app_name=:=A#app.name ->
+ %% print(ModName, file, "Maybe Prop ~p -> ~p\n",
+ %% [M2, M2#mod.is_included]),
+ %% print(ModName, filename, "Maybe Prop ~p -> ~p\n",
+ %% [M2, M2#mod.is_included]),
+ case M2#mod.is_included of
+ true ->
+ %% Propagate include mark
+ mod_mark_is_included(C,Sys,ModName,M2#mod.uses_mods,Acc);
+ false ->
+ Acc;
+ undefined ->
+ Acc
+ end;
+ [_] ->
+ %% This module is currently used from a different application
+ %% Ignore
+ Acc
+ end,
mod_propagate_is_included(C, Sys, A, Mods, Acc2);
mod_propagate_is_included(_C, _Sys, _A, [], Acc) ->
Acc.
@@ -740,9 +792,10 @@ mod_propagate_is_used_by(C, [#mod{name = ModName} | Mods]) ->
mod_propagate_is_used_by(_C, []) ->
ok.
-read_apps(C, Sys, [#app{mods = Mods, is_included = IsIncl} = A | Apps], Acc) ->
- {Mods2, IsIncl2} = read_apps(C, Sys, A, Mods, [], IsIncl),
- Status =
+app_recap_dependencies(C, Sys, [#app{mods = Mods, is_included = IsIncl} = A | Apps], Acc, Status) ->
+ {Mods2, IsIncl2, Status2} =
+ mod_recap_dependencies(C, Sys, A, Mods, [], IsIncl, Status),
+ AppStatus =
case lists:keymember(missing, #mod.status, Mods2) of
true -> missing;
false -> ok
@@ -759,34 +812,52 @@ read_apps(C, Sys, [#app{mods = Mods, is_included = IsIncl} = A | Apps], Acc) ->
UsedByApps2 = lists:usort(UsedByApps),
A2 = A#app{mods = Mods2,
- status = Status,
+ status = AppStatus,
uses_mods = UsesMods2,
used_by_mods = UsedByMods2,
uses_apps = UsesApps2,
used_by_apps = UsedByApps2,
is_included = IsIncl2},
- read_apps(C, Sys, Apps, [A2 | Acc]);
-read_apps(_C, _Sys, [], Acc) ->
- lists:reverse(Acc).
-
-read_apps(C, Sys, A, [#mod{name = ModName} | Mods], Acc, IsIncl) ->
- [M2] = ets:lookup(C#common.mod_tab, ModName),
- Status = do_get_status(M2),
- %% print(M2#mod.name, hipe, "status -> ~p\n", [Status]),
- {IsIncl2, M3} =
- case M2#mod.is_included of
- true ->
- UsedByMods =
- [N || {_, N} <- ets:lookup(C#common.mod_used_by_tab,
- ModName)],
- {true, M2#mod{status = Status, used_by_mods = UsedByMods}};
- _ ->
- {IsIncl, M2#mod{status = Status, used_by_mods = []}}
- end,
- ets:insert(C#common.mod_tab, M3),
- read_apps(C, Sys, A, Mods, [M3 | Acc], IsIncl2);
-read_apps(_C, _Sys, _A, [], Acc, IsIncl) ->
- {lists:reverse(Acc), IsIncl}.
+ ets:insert(C#common.app_tab,A2),
+ app_recap_dependencies(C, Sys, Apps, [A2 | Acc], Status2);
+app_recap_dependencies(_C, _Sys, [], Acc, Status) ->
+ {lists:reverse(Acc), Status}.
+
+mod_recap_dependencies(C, Sys, A, [#mod{name = ModName}=M1 | Mods], Acc, IsIncl, Status) ->
+ case ets:lookup(C#common.mod_tab, ModName) of
+ [M2] when M2#mod.app_name=:=A#app.name ->
+ ModStatus = do_get_status(M2),
+ %% print(M2#mod.name, hipe, "status -> ~p\n", [ModStatus]),
+ {IsIncl2, M3} =
+ case M2#mod.is_included of
+ true ->
+ UsedByMods =
+ [N || {_, N} <- ets:lookup(C#common.mod_used_by_tab,
+ ModName)],
+ {true, M2#mod{status = ModStatus, used_by_mods = UsedByMods}};
+ _ ->
+ {IsIncl, M2#mod{status = ModStatus, used_by_mods = []}}
+ end,
+ ets:insert(C#common.mod_tab, M3),
+ mod_recap_dependencies(C, Sys, A, Mods, [M3 | Acc], IsIncl2, Status);
+ [_] when A#app.is_included==false; M1#mod.incl_cond==exclude ->
+ %% App is explicitely excluded so it is ok that the module
+ %% record does not exist for this module in this
+ %% application.
+ mod_recap_dependencies(C, Sys, A, Mods, [M1 | Acc], IsIncl, Status);
+ [M2] ->
+ %% A module is potensially included by multiple
+ %% applications. This is not allowed!
+ Error =
+ lists:concat(
+ ["Module ",ModName,
+ " potentially included by two different applications: ",
+ A#app.name, " and ", M2#mod.app_name, "."]),
+ Status2 = reltool_utils:return_first_error(Status,Error),
+ mod_recap_dependencies(C, Sys, A, Mods, [M1 | Acc], IsIncl, Status2)
+ end;
+mod_recap_dependencies(_C, _Sys, _A, [], Acc, IsIncl, Status) ->
+ {lists:reverse(Acc), IsIncl, Status}.
do_get_status(M) ->
if
diff --git a/lib/reltool/src/reltool_sys_win.erl b/lib/reltool/src/reltool_sys_win.erl
index dbb8e32aa2..8b0f64eb45 100644
--- a/lib/reltool/src/reltool_sys_win.erl
+++ b/lib/reltool/src/reltool_sys_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -54,7 +54,9 @@
whitelist,
blacklist,
derived,
- fgraph_wins
+ fgraph_wins,
+ app_box,
+ mod_box
}).
-define(WIN_WIDTH, 800).
@@ -86,6 +88,11 @@
-define(blacklist, "Excluded").
-define(derived, "Derived").
+-define(safe_config,{sys,[{incl_cond,exclude},
+ {app,kernel,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]}]}).
+
-record(root_data, {dir}).
-record(lib_data, {dir, tree, item}).
-record(escript_data, {file, tree, item}).
@@ -102,7 +109,7 @@
start_link(Opts) ->
proc_lib:start_link(?MODULE,
init,
- [[{parent, self()} | Opts]],
+ [[{safe_config, false}, {parent, self()} | Opts]],
infinity,
[]).
@@ -126,53 +133,73 @@ init(Options) ->
exit({Reason, erlang:get_stacktrace()})
end.
-do_init([{parent, Parent} | Options]) ->
+do_init([{safe_config, Safe}, {parent, Parent} | Options]) ->
case reltool_server:start_link(Options) of
{ok, ServerPid, C, Sys} ->
process_flag(trap_exit, C#common.trap_exit),
- S = #state{parent_pid = Parent,
- server_pid = ServerPid,
- common = C,
- config_file = filename:absname("config.reltool"),
- target_dir = filename:absname("reltool_target_dir"),
- app_wins = [],
- sys = Sys,
- fgraph_wins = []},
wx:new(),
wx:debug(C#common.wx_debug),
- S2 = create_window(S),
%% wx_misc:beginBusyCursor(),
case reltool_server:get_status(ServerPid) of
{ok, Warnings} ->
exit_dialog(Warnings),
- {ok, Sys2} = reltool_server:get_sys(ServerPid),
- S3 = S2#state{sys = Sys2},
+ {ok, Sys} = reltool_server:get_sys(ServerPid),
+ S = #state{parent_pid = Parent,
+ server_pid = ServerPid,
+ common = C,
+ config_file = filename:absname("config.reltool"),
+ target_dir = filename:absname("reltool_target_dir"),
+ app_wins = [],
+ sys = Sys,
+ fgraph_wins = []},
+ S2 = create_window(S),
S5 = wx:batch(fun() ->
Title = atom_to_list(?APPLICATION),
- wxFrame:setTitle(S3#state.frame,
+ wxFrame:setTitle(S2#state.frame,
Title),
%% wxFrame:setMinSize(Frame,
%% {?WIN_WIDTH, ?WIN_HEIGHT}),
wxStatusBar:setStatusText(
- S3#state.status_bar,
+ S2#state.status_bar,
"Done."),
- S4 = redraw_apps(S3),
- redraw_libs(S4)
+ S3 = redraw_apps(S2),
+ S4 = redraw_libs(S3),
+ redraw_config_page(S4)
end),
%% wx_misc:endBusyCursor(),
%% wxFrame:destroy(Frame),
proc_lib:init_ack(S#state.parent_pid, {ok, self()}),
loop(S5);
{error, Reason} ->
- io:format("~p(~p): <ERROR> ~p\n", [?MODULE, ?LINE, Reason]),
- exit(Reason)
+ restart_server_safe_config(Safe,Parent,Reason)
end;
{error, Reason} ->
io:format("~p(~p): <ERROR> ~p\n", [?MODULE, ?LINE, Reason]),
exit(Reason)
end.
+restart_server_safe_config(true,_Parent,Reason) ->
+ io:format("~p(~p): <ERROR> ~p\n", [?MODULE, ?LINE, Reason]),
+ exit(Reason);
+restart_server_safe_config(false,Parent,Reason) ->
+ Strings =
+ [{?wxBLACK,"Could not start reltool server:\n\n"},
+ {?wxRED,Reason++"\n\n"},
+ {?wxBLACK,
+ io_lib:format(
+ "Resetting the configuration to:~n~n ~p~n~n"
+ "Do you want to continue with this configuration?",
+ [?safe_config])}],
+
+ case question_dialog_2("Reltool server start error", Strings) of
+ ?wxID_OK ->
+ do_init([{safe_config,true},{parent,Parent},?safe_config]);
+ ?wxID_CANCEL ->
+ io:format("~p(~p): <ERROR> ~p\n", [?MODULE, ?LINE, Reason]),
+ exit(Reason)
+ end.
+
exit_dialog([]) ->
ok;
exit_dialog(Warnings) ->
@@ -606,6 +633,13 @@ create_config_page(#state{sys = Sys, book = Book} = S) ->
{proportion, 1}]),
wxPanel:setSizer(Panel, Sizer),
wxNotebook:addPage(Book, Panel, ?SYS_PAGE, []),
+ S#state{app_box = AppBox, mod_box = ModBox}.
+
+redraw_config_page(#state{sys = Sys, app_box = AppBox, mod_box = ModBox} = S) ->
+ AppChoice = reltool_utils:incl_cond_to_index(Sys#sys.incl_cond),
+ wxRadioBox:setSelection(AppBox, AppChoice),
+ ModChoice = reltool_utils:mod_cond_to_index(Sys#sys.mod_cond),
+ wxRadioBox:setSelection(ModBox, ModChoice),
S.
create_main_release_page(#state{book = Book} = S) ->
@@ -640,15 +674,15 @@ create_main_release_page(#state{book = Book} = S) ->
add_release_page(Book, #rel{name = RelName, rel_apps = RelApps}) ->
Panel = wxPanel:new(Book, []),
Sizer = wxBoxSizer:new(?wxHORIZONTAL),
- RelBox = wxRadioBox:new(Panel,
- ?wxID_ANY,
- "Applications included in the release " ++ RelName,
- ?wxDefaultPosition,
- ?wxDefaultSize,
- [atom_to_list(RA#rel_app.name) || RA <- RelApps],
- []),
- %% wxRadioBox:setSelection(RelBox, 2), % mandatory
- wxEvtHandler:connect(RelBox, command_radiobox_selected,
+ AppNames = [kernel, stdlib |
+ [RA#rel_app.name || RA <- RelApps] -- [kernel, stdlib]],
+ RelBox = wxListBox:new(
+ Panel,?wxID_ANY,
+ [{pos,?wxDefaultPosition},
+ {size,?wxDefaultSize},
+ {choices,[[atom_to_list(AppName)] || AppName <- AppNames]},
+ {style,?wxLB_EXTENDED}]),
+ wxEvtHandler:connect(RelBox, command_listbox_selected,
[{userData, {config_rel_cond, RelName}}]),
RelToolTip = "Choose which applications that shall "
"be included in the release resource file.",
@@ -1092,17 +1126,23 @@ move_app(S, {_ItemNo, AppBase}, Action) ->
OldApp#app{incl_cond = AppCond}.
do_set_app(#state{server_pid = ServerPid, app_wins = AppWins} = S, NewApp) ->
- {ok, AnalysedApp, Warnings} = reltool_server:set_app(ServerPid, NewApp),
+ Result = reltool_server:set_app(ServerPid, NewApp),
[ok = reltool_app_win:refresh(AW#app_win.pid) || AW <- AppWins],
S2 = redraw_apps(S),
- case Warnings of
- [] ->
- ignore;
- _ ->
- Msg = lists:flatten([[W, $\n] || W <- Warnings]),
- display_message(Msg, ?wxICON_WARNING)
- end,
- {ok, AnalysedApp, S2}.
+ ReturnApp =
+ case Result of
+ {ok, AnalysedApp, []} ->
+ AnalysedApp;
+ {ok, AnalysedApp, Warnings} ->
+ Msg = lists:flatten([[W, $\n] || W <- Warnings]),
+ display_message(Msg, ?wxICON_WARNING),
+ AnalysedApp;
+ {error, Reason} ->
+ display_message(Reason, ?wxICON_ERROR),
+ {ok,OldApp} = reltool_server:get_app(ServerPid, NewApp#app.name),
+ OldApp
+ end,
+ {ok, ReturnApp, S2}.
redraw_apps(#state{server_pid = ServerPid,
source = SourceCtrl,
@@ -1357,7 +1397,8 @@ refresh(S) ->
[ok = reltool_app_win:refresh(AW#app_win.pid) || AW <- S#state.app_wins],
S2 = S#state{sys = Sys},
S3 = redraw_libs(S2),
- redraw_apps(S3).
+ S4 = redraw_apps(S3),
+ redraw_config_page(S4).
question_dialog(Question, Details) ->
%% Parent = S#state.frame,
@@ -1414,6 +1455,44 @@ display_message(Message, Icon) ->
wxMessageDialog:showModal(Dialog),
wxMessageDialog:destroy(Dialog).
+%% Strings = [{Color,String}]
+question_dialog_2(DialogLabel, Strings) ->
+ %% Parent = S#state.frame,
+ Parent = wx:typeCast(wx:null(), wxWindow),
+ %% [{style, ?wxYES_NO bor ?wxICON_ERROR bor ?wx}]),
+ DialogStyle = ?wxRESIZE_BORDER bor ?wxCAPTION bor ?wxSYSTEM_MENU bor
+ ?wxMINIMIZE_BOX bor ?wxMAXIMIZE_BOX bor ?wxCLOSE_BOX,
+ Dialog = wxDialog:new(Parent, ?wxID_ANY, DialogLabel,
+ [{style, DialogStyle}]),
+ Color = wxWindow:getBackgroundColour(Dialog),
+ TextStyle = ?wxTE_READONLY bor ?wxTE_MULTILINE bor ?wxHSCROLL,
+ Text = wxTextCtrl:new(Dialog, ?wxID_ANY,
+ [{size, {600, 400}}, {style, TextStyle}]),
+ wxWindow:setBackgroundColour(Text, Color),
+ TextAttr = wxTextAttr:new(),
+ add_text(Text,TextAttr,Strings),
+ Sizer = wxBoxSizer:new(?wxVERTICAL),
+ wxSizer:add(Sizer, Text, [{border, 2}, {flag, ?wxEXPAND}, {proportion, 1}]),
+ ButtSizer = wxDialog:createStdDialogButtonSizer(Dialog, ?wxOK bor ?wxCANCEL),
+ wxSizer:add(Sizer, ButtSizer, [{border, 2}, {flag, ?wxEXPAND}]),
+ wxPanel:setSizer(Dialog, Sizer),
+ wxSizer:fit(Sizer, Dialog),
+ wxSizer:setSizeHints(Sizer, Dialog),
+ Answer = wxDialog:showModal(Dialog),
+ wxDialog:destroy(Dialog),
+ Answer.
+
+add_text(Text,Attr,[{Color,String}|Strings]) ->
+ wxTextAttr:setTextColour(Attr, Color),
+ wxTextCtrl:setDefaultStyle(Text, Attr),
+ wxTextCtrl:appendText(Text, String),
+ add_text(Text,Attr,Strings);
+add_text(_,_,[]) ->
+ ok.
+
+
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% sys callbacks
diff --git a/lib/reltool/test/Makefile b/lib/reltool/test/Makefile
index abd2e81cdf..767454b66a 100644
--- a/lib/reltool/test/Makefile
+++ b/lib/reltool/test/Makefile
@@ -76,8 +76,8 @@ release_tests_spec: opt
$(INSTALL_DATA) reltool.spec reltool.cover $(ERL_FILES) $(HRL_FILES) $(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 -)
+ chmod -R u+w $(RELSYSDIR)
+ @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/reltool/test/reltool_server_SUITE.erl b/lib/reltool/test/reltool_server_SUITE.erl
index b77560db94..9ed79e8c95 100644
--- a/lib/reltool/test/reltool_server_SUITE.erl
+++ b/lib/reltool/test/reltool_server_SUITE.erl
@@ -25,6 +25,7 @@
-compile(export_all).
-include("reltool_test_lib.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(NODE_NAME, '__RELTOOL__TEMPORARY_TEST__NODE__').
-define(WORK_DIR, "reltool_work_dir").
@@ -53,7 +54,7 @@ all() ->
[start_server, set_config, create_release,
create_script, create_target, create_embedded,
create_standalone, create_old_target,
- otp_9135].
+ otp_9135, otp_9229_exclude_app, otp_9229_exclude_mod].
groups() ->
[].
@@ -361,6 +362,114 @@ create_old_target(_Config) ->
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% OTP-9229 - handle duplicated module names, i.e. same module name
+%% exists in two applications.
+
+%% Include on app, exclude the other
+otp_9229_exclude_app(Config) ->
+ DataDir = ?config(data_dir,Config),
+ LibDir = filename:join(DataDir,"otp_9229"),
+
+ %% Configure the server
+ ExclApp =
+ {sys,
+ [
+ {root_dir, code:root_dir()},
+ {lib_dirs, [LibDir]},
+ {incl_cond,exclude},
+ {app,x,[{incl_cond,include}]},
+ {app,y,[{incl_cond,exclude}]},
+ {app,kernel,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]}
+ ]},
+
+ %% Generate target file
+ TargetDir = filename:join([?WORK_DIR, "target_dupl_mod_excl_app"]),
+ ?m(ok, reltool_utils:recursive_delete(TargetDir)),
+ ?m(ok, file:make_dir(TargetDir)),
+ ?log("SPEC: ~p\n", [reltool:get_target_spec([{config, ExclApp}])]),
+ {ok,["Module mylib exists in applications x and y. Using module from application x."]} = reltool:get_status([{config, ExclApp}]),
+ ?m(ok, reltool:create_target([{config, ExclApp}], TargetDir)),
+
+ Erl = filename:join([TargetDir, "bin", "erl"]),
+ {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)),
+
+ AbsTargetDir = filename:absname(TargetDir),
+ XArchive = "x-1.0.ez",
+ AbsXArchive = filename:join([AbsTargetDir,lib,XArchive]),
+ XEbin = ["ebin","x-1.0",XArchive],
+ YArchive = "y-1.0.ez",
+ AbsYArchive = filename:join([AbsTargetDir,lib,YArchive]),
+
+ ?m(true, filelib:is_file(AbsXArchive)),
+ ?m(XEbin, mod_path(Node,x)),
+ ?m(XEbin, mod_path(Node,mylib)),
+ ?m(false, filelib:is_file(AbsYArchive)),
+ ?m(non_existing, mod_path(Node,y)),
+
+ ?msym(ok, stop_node(Node)),
+
+ ok.
+
+%% Include both apps, but exclude common module from one app
+otp_9229_exclude_mod(Config) ->
+ DataDir = ?config(data_dir,Config),
+ LibDir = filename:join(DataDir,"otp_9229"),
+
+ %% Configure the server
+ ExclMod =
+ {sys,
+ [
+ {root_dir, code:root_dir()},
+ {lib_dirs, [LibDir]},
+ {incl_cond,exclude},
+ {app,x,[{incl_cond,include}]},
+ {app,y,[{incl_cond,include},{mod, mylib,[{incl_cond,exclude}]}]},
+ {app,kernel,[{incl_cond,include}]},
+ {app,stdlib,[{incl_cond,include}]},
+ {app,sasl,[{incl_cond,include}]}
+ ]},
+
+ %% Generate target file
+ TargetDir = filename:join([?WORK_DIR, "target_dupl_mod_excl_mod"]),
+ ?m(ok, reltool_utils:recursive_delete(TargetDir)),
+ ?m(ok, file:make_dir(TargetDir)),
+ ?log("SPEC: ~p\n", [reltool:get_target_spec([{config, ExclMod}])]),
+ {ok,["Module mylib exists in applications x and y. Using module from application x."]} = reltool:get_status([{config, ExclMod}]),
+ ?m(ok, reltool:create_target([{config, ExclMod}], TargetDir)),
+
+ Erl = filename:join([TargetDir, "bin", "erl"]),
+ {ok, Node} = ?msym({ok, _}, start_node(?NODE_NAME, Erl)),
+
+ AbsTargetDir = filename:absname(TargetDir),
+ XArchive = "x-1.0.ez",
+ AbsXArchive = filename:join([AbsTargetDir,lib,XArchive]),
+ XEbin = ["ebin","x-1.0",XArchive],
+ YArchive = "y-1.0.ez",
+ AbsYArchive = filename:join([AbsTargetDir,lib,YArchive]),
+ YEbin = ["ebin","y-1.0",YArchive],
+
+ ?m(true, filelib:is_file(AbsXArchive)),
+ ?m(XEbin, mod_path(Node,x)),
+ ?m(XEbin, mod_path(Node,mylib)),
+ ?m(true, filelib:is_file(AbsYArchive)),
+ ?m(YEbin, mod_path(Node,y)),
+
+ %% Remove path to XEbin and check that mylib is not located in YEbin
+ Mylib = rpc:call(Node,code,which,[mylib]),
+ rpc:call(Node,code,del_path,[filename:dirname(Mylib)]),
+ ?m(non_existing, mod_path(Node,mylib)),
+
+ ?msym(ok, stop_node(Node)),
+
+ ok.
+
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Library functions
erl_libs() ->
@@ -407,6 +516,20 @@ os_cmd(Cmd) when is_list(Cmd) ->
end
end.
+%% Returns the location (directory) of the given module. Split,
+%% reverted and relative to the lib dir.
+mod_path(Node,Mod) ->
+ case rpc:call(Node,code,which,[Mod]) of
+ Path when is_list(Path) ->
+ lists:takewhile(
+ fun("lib") -> false;
+ (_) -> true
+ end,
+ lists:reverse(filename:split(filename:dirname(Path))));
+ Other ->
+ Other
+ end.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Node handling
diff --git a/lib/reltool/test/reltool_server_SUITE_data/Makefile.src b/lib/reltool/test/reltool_server_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..049e8dd6cc
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/Makefile.src
@@ -0,0 +1,19 @@
+EFLAGS=+debug_info
+
+OTP9229= \
+ otp_9229/x-1.0/ebin/x.@EMULATOR@ \
+ otp_9229/x-1.0/ebin/mylib.@EMULATOR@ \
+ otp_9229/y-1.0/ebin/y.@EMULATOR@ \
+ otp_9229/y-1.0/ebin/mylib.@EMULATOR@
+
+
+all: $(OTP9229)
+
+otp_9229/x-1.0/ebin/x.@EMULATOR@: otp_9229/x-1.0/src/x.erl
+ erlc $(EFLAGS) -ootp_9229/x-1.0/ebin otp_9229/x-1.0/src/x.erl
+otp_9229/x-1.0/ebin/mylib.@EMULATOR@: otp_9229/x-1.0/src/mylib.erl
+ erlc $(EFLAGS) -ootp_9229/x-1.0/ebin otp_9229/x-1.0/src/mylib.erl
+otp_9229/y-1.0/ebin/y.@EMULATOR@: otp_9229/y-1.0/src/y.erl
+ erlc $(EFLAGS) -ootp_9229/y-1.0/ebin otp_9229/y-1.0/src/y.erl
+otp_9229/y-1.0/ebin/mylib.@EMULATOR@: otp_9229/y-1.0/src/mylib.erl
+ erlc $(EFLAGS) -ootp_9229/y-1.0/ebin otp_9229/y-1.0/src/mylib.erl
diff --git a/lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/ebin/x.app b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/ebin/x.app
new file mode 100644
index 0000000000..e597704b19
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/ebin/x.app
@@ -0,0 +1,7 @@
+%% -*- erlang -*-
+{application, x,
+ [{description, "X CXC 138 11"},
+ {vsn, "1.0"},
+ {modules, [x, mylib]},
+ {registered, []},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/src/mylib.erl b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/src/mylib.erl
new file mode 100644
index 0000000000..c8603d1a8e
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/src/mylib.erl
@@ -0,0 +1,4 @@
+-module(mylib).
+-export([foo/0]).
+
+foo() -> erlang:time().
diff --git a/lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/src/x.erl b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/src/x.erl
new file mode 100644
index 0000000000..17ff84f08f
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/x-1.0/src/x.erl
@@ -0,0 +1,4 @@
+-module(x).
+-export([x/0]).
+
+x() ->mylib:foo().
diff --git a/lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/ebin/y.app b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/ebin/y.app
new file mode 100644
index 0000000000..5b327862e3
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/ebin/y.app
@@ -0,0 +1,7 @@
+%% -*- erlang -*-
+{application, y,
+ [{description, "Y CXC 138 11"},
+ {vsn, "1.0"},
+ {modules, [y, mylib]},
+ {registered, []},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/src/mylib.erl b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/src/mylib.erl
new file mode 100644
index 0000000000..c8603d1a8e
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/src/mylib.erl
@@ -0,0 +1,4 @@
+-module(mylib).
+-export([foo/0]).
+
+foo() -> erlang:time().
diff --git a/lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/src/y.erl b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/src/y.erl
new file mode 100644
index 0000000000..342e7da7d5
--- /dev/null
+++ b/lib/reltool/test/reltool_server_SUITE_data/otp_9229/y-1.0/src/y.erl
@@ -0,0 +1,4 @@
+-module(y).
+-export([y/0]).
+
+y() ->mylib:foo().
diff --git a/lib/reltool/vsn.mk b/lib/reltool/vsn.mk
index 484f84788d..751f9bb6db 100644
--- a/lib/reltool/vsn.mk
+++ b/lib/reltool/vsn.mk
@@ -1 +1 @@
-RELTOOL_VSN = 0.5.5
+RELTOOL_VSN = 0.5.7
diff --git a/lib/runtime_tools/c_src/Makefile.in b/lib/runtime_tools/c_src/Makefile.in
index 840de39f07..73ab6cdc11 100644
--- a/lib/runtime_tools/c_src/Makefile.in
+++ b/lib/runtime_tools/c_src/Makefile.in
@@ -89,42 +89,31 @@ endif
# Targets
# ----------------------------------------------------
-debug opt: $(OBJDIR) $(BINDIR) $(SOLIBS)
+_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
-$(OBJDIR):
- -@mkdir -p $(OBJDIR)
-
-$(BINDIR):
- -@mkdir -p $(BINDIR)
+debug opt: $(SOLIBS)
$(OBJDIR)/%.o: %.c
- $(INSTALL_DIR) $(OBJDIR)
$(CC) -c -o $@ $(ALL_CFLAGS) $<
$(LIBDIR)/trace_ip_drv.so: $(TRACE_IP_DRV_OBJS)
- $(INSTALL_DIR) $(LIBDIR)
$(LD) $(LDFLAGS) -o $@ $^ -lc $(LIBS)
$(LIBDIR)/trace_file_drv.so: $(TRACE_FILE_DRV_OBJS)
- $(INSTALL_DIR) $(LIBDIR)
$(LD) $(LDFLAGS) -o $@ $^ -lc $(LIBS)
$(LIBDIR)/trace_ip_drv.dll: $(TRACE_IP_DRV_OBJS)
- $(INSTALL_DIR) $(LIBDIR)
$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
$(LIBDIR)/trace_file_drv.dll: $(TRACE_FILE_DRV_OBJS)
- $(INSTALL_DIR) $(LIBDIR)
$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
#
# VxWorks is simply to different from Unix in this sense.
# Here are the inference rules for VxWorks
#
$(LIBDIR)/trace_ip_drv.eld: $(TRACE_IP_DRV_OBJS)
- $(INSTALL_DIR) $(LIBDIR)
$(LD) $(LDFLAGS) -o $@ $^
$(LIBDIR)/trace_file_drv.eld: $(TRACE_FILE_DRV_OBJS)
- $(INSTALL_DIR) $(LIBDIR)
$(LD) $(LDFLAGS) -o $@ $^
clean:
diff --git a/lib/runtime_tools/doc/src/dbg.xml b/lib/runtime_tools/doc/src/dbg.xml
index 0e63649c09..c7c5cd4ff0 100644
--- a/lib/runtime_tools/doc/src/dbg.xml
+++ b/lib/runtime_tools/doc/src/dbg.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -316,7 +316,8 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c
<v>Module = atom() | '_'</v>
<v>Function = atom() | '_'</v>
<v>Arity = integer() |'_'</v>
- <v>MatchSpec = integer() | atom() | [] | match_spec()</v>
+ <v>MatchSpec = integer() | Built-inAlias | [] | match_spec()</v>
+ <v>Built-inAlias = x | c | cx</v>
<v>MatchDesc = [MatchInfo]</v>
<v>MatchInfo = {saved, integer()} | MatchNum</v>
<v>MatchNum = {matched, node(), integer()} | {matched, node(), 0, RPCError}</v>
@@ -349,8 +350,9 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c
if the MatchSpec is other
than []. The integer <c>N</c> may then be used in
subsequent calls to this function and will stand as an
- "alias" for the given expression. There are also built-in
- aliases named with atoms (see also <c>ltp/0</c> below).</p>
+ "alias" for the given expression. There are also a couple of
+ built-in aliases for common expressions, see <c>ltp/0</c> below
+ for details.</p>
<p>If an error is returned, it can be due to errors in
compilation of the match specification. Such errors are
presented as a list of tuples <c>{error, string()}</c> where
@@ -528,6 +530,21 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c
<p>Match specifications used can be saved in a file (if a
read-write file system is present) for use in later
debugging sessions, see <c>wtp/1</c> and <c>rtp/1</c></p>
+ <p>There are three built-in trace patterns:
+ <c>exception_trace</c>, <c>caller_trace</c>
+ and <c>caller_exception_trace</c> (or <c>x</c>, <c>c</c> and
+ <c>cx</c> respectively).
+ Exception trace sets a trace which will show function names,
+ parameters, return values and exceptions thrown from functions.
+ Caller traces display function names, parameters and information
+ about which function called it. An example using a built-in alias:</p>
+ <pre>
+(x@y)4> <input>dbg:tp(lists,sort,cx).</input>
+{ok,[{matched,nonode@nohost,2},{saved,cx}]}
+(x@y)4> <input>lists:sort([2,1]).</input>
+(&lt;0.32.0&gt;) call lists:sort([2,1]) ({erl_eval,do_apply,5})
+(&lt;0.32.0&gt;) returned from lists:sort/1 -> [1,2]
+[1,2]</pre>
</desc>
</func>
<func>
@@ -706,7 +723,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c
value from the last invocation of the fun. The initial value
of the second parameter is specified in the <c>InitialData</c>
part of the <c>HandlerSpec</c>. The <c>HandlerFun</c> may
- chose any appropriate action to take when invoked, and can
+ choose any appropriate action to take when invoked, and can
save a state for the next invocation by returning it.
</p>
<p>If <c>Type</c> is a port, then the second parameter should
@@ -766,7 +783,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c
<p>This function creates a trace port generating <em>fun</em>.
The <em>fun</em> takes no arguments and returns a newly opened
trace port. The return value from this function is suitable as
- a second parameter to tracer/2, i. e. <c>dbg:tracer(port, dbg:trace_port(ip, 4711))</c>. </p>
+ a second parameter to tracer/2, i.e. <c>dbg:tracer(port, dbg:trace_port(ip, 4711))</c>. </p>
<p>A trace port is an
Erlang port to a dynamically linked in driver that handles
trace messages directly, without the overhead of sending them
@@ -852,9 +869,9 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard) c
<desc>
<p>This function is used to do a control operation on the
active trace port driver on the given node
- (<c>Nodename</c>). Which operations that are allowed as well
- as their return values are depending on which trace driver
- that is used.</p>
+ (<c>Nodename</c>). Which operations are allowed as well
+ as their return values depend on which trace driver
+ is used.</p>
<p>Returns either <c>ok</c> or <c>{ok, Result}</c>
if the operation was successful, or <c>{error, Reason}</c>
if the current tracer is a process
diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml
index b27a3a0996..0bb76e1ea4 100644
--- a/lib/runtime_tools/doc/src/notes.xml
+++ b/lib/runtime_tools/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,23 @@
<p>This document describes the changes made to the Runtime_Tools
application.</p>
+<section><title>Runtime_Tools 1.8.6</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Two new built-in trace pattern aliases have been added:
+ caller_trace (c) and caller_exception_trace (cx). See the
+ dbg:ltp/0 documentation for more info.</p>
+ <p>
+ Own Id: OTP-9458</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Runtime_Tools 1.8.5</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/runtime_tools/src/Makefile b/lib/runtime_tools/src/Makefile
index 4f831f3dd8..46b570210a 100644
--- a/lib/runtime_tools/src/Makefile
+++ b/lib/runtime_tools/src/Makefile
@@ -46,7 +46,8 @@ MODULES= \
runtime_tools_sup \
dbg \
percept_profile \
- observer_backend
+ observer_backend \
+ ttb_autostart
HRL_FILES= ../include/observer_backend.hrl
ERL_FILES= $(MODULES:%=%.erl)
diff --git a/lib/runtime_tools/src/dbg.erl b/lib/runtime_tools/src/dbg.erl
index 56283f4d3d..446de63064 100644
--- a/lib/runtime_tools/src/dbg.erl
+++ b/lib/runtime_tools/src/dbg.erl
@@ -1449,6 +1449,19 @@ new_pattern_table() ->
ets:insert(PT,
{exception_trace,
term_to_binary(x)}),
+ ets:insert(PT,
+ {c,
+ term_to_binary([{'_',[],[{message,{caller}}]}])}),
+ ets:insert(PT,
+ {caller_trace,
+ term_to_binary(c)}),
+ ets:insert(PT,
+ {cx,
+ term_to_binary([{'_',[],[{exception_trace},
+ {message,{caller}}]}])}),
+ ets:insert(PT,
+ {caller_exception_trace,
+ term_to_binary(cx)}),
PT.
diff --git a/lib/runtime_tools/src/observer_backend.erl b/lib/runtime_tools/src/observer_backend.erl
index 0f428de07a..9c1f9da5b1 100644
--- a/lib/runtime_tools/src/observer_backend.erl
+++ b/lib/runtime_tools/src/observer_backend.erl
@@ -31,6 +31,7 @@
ttb_write_binary/2,
ttb_stop/1,
ttb_fetch/2,
+ ttb_resume_trace/0,
ttb_get_filenames/1]).
-define(CHUNKSIZE,8191). % 8 kbytes - 1 byte
@@ -92,16 +93,22 @@ etop_collect([], Acc) -> Acc.
%%
%% ttb backend
%%
-ttb_init_node(MetaFile,PI,Traci) ->
+ttb_init_node(MetaFile_0,PI,Traci) ->
if
- is_list(MetaFile);
- is_atom(MetaFile) ->
+ is_list(MetaFile_0);
+ is_atom(MetaFile_0) ->
+ {ok, Cwd} = file:get_cwd(),
+ MetaFile = filename:join(Cwd, MetaFile_0),
file:delete(MetaFile);
true -> % {local,_,_}
- ok
+ MetaFile = MetaFile_0
+ end,
+ case proplists:get_value(resume, Traci) of
+ {true, _} -> (autostart_module()):write_config(Traci);
+ _ -> ok
end,
Self = self(),
- MetaPid = spawn(fun() -> ttb_meta_tracer(MetaFile,PI,Self) end),
+ MetaPid = spawn(fun() -> ttb_meta_tracer(MetaFile,PI,Self,Traci) end),
receive {MetaPid,started} -> ok end,
MetaPid ! {metadata,Traci},
case PI of
@@ -111,13 +118,14 @@ ttb_init_node(MetaFile,PI,Traci) ->
false ->
ok
end,
- {ok,MetaPid}.
+ {ok,MetaFile,MetaPid}.
ttb_write_trace_info(MetaPid,Key,What) ->
MetaPid ! {metadata,Key,What},
ok.
-ttb_meta_tracer(MetaFile,PI,Parent) ->
+ttb_meta_tracer(MetaFile,PI,Parent,SessionData) ->
+ erlang:monitor(process, proplists:get_value(ttb_control, SessionData)),
case PI of
true ->
ReturnMS = [{'_',[],[{return_trace}]}],
@@ -130,22 +138,29 @@ ttb_meta_tracer(MetaFile,PI,Parent) ->
ok
end,
Parent ! {self(),started},
- ttb_meta_tracer_loop(MetaFile,PI,dict:new()).
+ case proplists:get_value(overload_check, SessionData) of
+ {Ms, M, F} ->
+ catch M:F(init),
+ erlang:send_after(Ms, self(), overload_check);
+ _ ->
+ ok
+ end,
+ ttb_meta_tracer_loop(MetaFile,PI,dict:new(),SessionData).
-ttb_meta_tracer_loop(MetaFile,PI,Acc) ->
+ttb_meta_tracer_loop(MetaFile,PI,Acc,State) ->
receive
{trace_ts,_,call,{erlang,register,[Name,Pid]},_} ->
ttb_store_meta({pid,{Pid,Name}},MetaFile),
- ttb_meta_tracer_loop(MetaFile,PI,Acc);
+ ttb_meta_tracer_loop(MetaFile,PI,Acc,State);
{trace_ts,_,call,{global,register_name,[Name,Pid]},_} ->
ttb_store_meta({pid,{Pid,{global,Name}}},MetaFile),
- ttb_meta_tracer_loop(MetaFile,PI,Acc);
+ ttb_meta_tracer_loop(MetaFile,PI,Acc,State);
{trace_ts,CallingPid,call,{erlang,spawn_opt,[{M,F,Args,_}]},_} ->
MFA = {M,F,length(Args)},
NewAcc = dict:update(CallingPid,
fun(Old) -> [MFA|Old] end, [MFA],
Acc),
- ttb_meta_tracer_loop(MetaFile,PI,NewAcc);
+ ttb_meta_tracer_loop(MetaFile,PI,NewAcc,State);
{trace_ts,CallingPid,return_from,{erlang,spawn_opt,_Arity},Ret,_} ->
case Ret of
{NewPid,_Mref} when is_pid(NewPid) -> ok;
@@ -158,14 +173,14 @@ ttb_meta_tracer_loop(MetaFile,PI,Acc) ->
T
end,
Acc),
- ttb_meta_tracer_loop(MetaFile,PI,NewAcc);
+ ttb_meta_tracer_loop(MetaFile,PI,NewAcc,State);
{trace_ts,CallingPid,call,{erlang,Spawn,[M,F,Args]},_}
when Spawn==spawn;Spawn==spawn_link ->
MFA = {M,F,length(Args)},
NewAcc = dict:update(CallingPid,
fun(Old) -> [MFA|Old] end, [MFA],
Acc),
- ttb_meta_tracer_loop(MetaFile,PI,NewAcc);
+ ttb_meta_tracer_loop(MetaFile,PI,NewAcc,State);
{trace_ts,CallingPid,return_from,{erlang,Spawn,_Arity},NewPid,_}
when Spawn==spawn;Spawn==spawn_link ->
@@ -176,28 +191,53 @@ ttb_meta_tracer_loop(MetaFile,PI,Acc) ->
T
end,
Acc),
- ttb_meta_tracer_loop(MetaFile,PI,NewAcc);
+ ttb_meta_tracer_loop(MetaFile,PI,NewAcc,State);
{metadata,Data} when is_list(Data) ->
ttb_store_meta(Data,MetaFile),
- ttb_meta_tracer_loop(MetaFile,PI,Acc);
+ ttb_meta_tracer_loop(MetaFile,PI,Acc,State);
{metadata,Key,Fun} when is_function(Fun) ->
ttb_store_meta([{Key,Fun()}],MetaFile),
- ttb_meta_tracer_loop(MetaFile,PI,Acc);
+ ttb_meta_tracer_loop(MetaFile,PI,Acc,State);
{metadata,Key,What} ->
ttb_store_meta([{Key,What}],MetaFile),
- ttb_meta_tracer_loop(MetaFile,PI,Acc);
-
- stop when PI=:=true ->
- erlang:trace_pattern({erlang,spawn,3},false,[meta]),
+ ttb_meta_tracer_loop(MetaFile,PI,Acc,State);
+ overload_check ->
+ {Ms, M, F} = proplists:get_value(overload_check, State),
+ case catch M:F(check) of
+ true ->
+ erlang:trace(all, false, [all]),
+ ControlPid = proplists:get_value(ttb_control, State),
+ ControlPid ! {node_overloaded, node()},
+ catch M:F(stop),
+ ttb_meta_tracer_loop(MetaFile,PI,Acc,lists:keydelete(overload_check, 1, State));
+ _ ->
+ erlang:send_after(Ms, self(), overload_check),
+ ttb_meta_tracer_loop(MetaFile,PI,Acc, State)
+ end;
+ {'DOWN', _, _, _, _} ->
+ stop_seq_trace(),
+ self() ! stop,
+ ttb_meta_tracer_loop(MetaFile,PI,Acc, State);
+ stop when PI=:=true ->
+ try_stop_resume(State),
+ try_stop_overload_check(State),
+ erlang:trace_pattern({erlang,spawn,3},false,[meta]),
erlang:trace_pattern({erlang,spawn_link,3},false,[meta]),
erlang:trace_pattern({erlang,spawn_opt,1},false,[meta]),
erlang:trace_pattern({erlang,register,2},false,[meta]),
erlang:trace_pattern({global,register_name,2},false,[meta]);
stop ->
- ok
+ try_stop_resume(State),
+ try_stop_overload_check(State)
+ end.
+
+try_stop_overload_check(State) ->
+ case proplists:get_value(overload, State) of
+ undefined -> ok;
+ {_, M, F} -> catch M:F(stop)
end.
pnames() ->
@@ -222,6 +262,40 @@ pinfo(P,Globals) ->
undefined -> [] % the process has terminated
end.
+autostart_module() ->
+ element(2, application:get_env(runtime_tools, ttb_autostart_module)).
+
+try_stop_resume(State) ->
+ case proplists:get_value(resume, State) of
+ true -> (autostart_module()):delete_config();
+ _ -> ok
+ end.
+
+ttb_resume_trace() ->
+ case (autostart_module()):read_config() of
+ {error, _} ->
+ ok;
+ {ok, Data} ->
+ Pid = proplists:get_value(ttb_control, Data),
+ {_, Timeout} = proplists:get_value(resume, Data),
+ case rpc:call(node(Pid), erlang, whereis, [ttb]) of
+ Pid ->
+ Pid ! {noderesumed, node(), self()},
+ wait_for_fetch_ready(Timeout);
+ _ ->
+ ok
+ end,
+ (autostart_module()):delete_config(),
+ ok
+ end.
+
+wait_for_fetch_ready(Timeout) ->
+ receive
+ trace_resumed ->
+ ok
+ after Timeout ->
+ ok
+ end.
ttb_store_meta(Data,{local,MetaFile,Port}) when is_list(Data) ->
ttb_send_to_port(Port,MetaFile,Data);
@@ -273,6 +347,9 @@ ttb_stop(MetaPid) ->
%% returns, and then the Port (in {local,MetaFile,Port})
%% cannot be accessed any more.
receive {'DOWN', Ref, process, MetaPid, _Info} -> ok end,
+ stop_seq_trace().
+
+stop_seq_trace() ->
seq_trace:reset_trace(),
seq_trace:set_system_tracer(false).
@@ -287,7 +364,7 @@ ttb_fetch(MetaFile,{Port,Host}) ->
send_files({Sock,Host},[File|Files]) ->
{ok,Fd} = file:open(File,[raw,read,binary]),
- gen_tcp:send(Sock,<<1,(list_to_binary(File))/binary>>),
+ gen_tcp:send(Sock,<<1,(list_to_binary(filename:basename(File)))/binary>>),
send_chunks(Sock,Fd),
file:delete(File),
send_files({Sock,Host},Files);
diff --git a/lib/runtime_tools/src/runtime_tools.app.src b/lib/runtime_tools/src/runtime_tools.app.src
index e6dc7a21d4..095567b165 100644
--- a/lib/runtime_tools/src/runtime_tools.app.src
+++ b/lib/runtime_tools/src/runtime_tools.app.src
@@ -22,7 +22,8 @@
{modules, [dbg,observer_backend,percept_profile,
inviso_rt,inviso_rt_lib,inviso_rt_meta,
inviso_as_lib,inviso_autostart,inviso_autostart_server,
- runtime_tools,runtime_tools_sup,erts_alloc_config]},
+ runtime_tools,runtime_tools_sup,erts_alloc_config,
+ ttb_autostart]},
{registered, [runtime_tools_sup,inviso_rt,inviso_rt_meta]},
{applications, [kernel, stdlib]},
% {env, [{inviso_autostart_mod,your_own_autostart_module}]},
diff --git a/lib/runtime_tools/src/runtime_tools_sup.erl b/lib/runtime_tools/src/runtime_tools_sup.erl
index 1a872c355d..4fcb2292d0 100644
--- a/lib/runtime_tools/src/runtime_tools_sup.erl
+++ b/lib/runtime_tools/src/runtime_tools_sup.erl
@@ -38,6 +38,8 @@
init(AutoModArgs) ->
Flags = {one_for_one, 0, 3600},
Children = [{inviso_rt, {inviso_rt, start_link_auto, [AutoModArgs]},
- temporary, 3000, worker, [inviso_rt]}],
+ temporary, 3000, worker, [inviso_rt]},
+ {ttb_autostart, {ttb_autostart, start_link, []},
+ temporary, 3000, worker, [ttb_autostart]}],
{ok, {Flags, Children}}.
%% -----------------------------------------------------------------------------
diff --git a/lib/runtime_tools/src/ttb_autostart.erl b/lib/runtime_tools/src/ttb_autostart.erl
new file mode 100644
index 0000000000..4c6971c119
--- /dev/null
+++ b/lib/runtime_tools/src/ttb_autostart.erl
@@ -0,0 +1,55 @@
+%%%-------------------------------------------------------------------
+%%% File : ttb_autostart.erl
+%%% Author : BartÅ‚omiej PuzoÅ„ <[email protected]>
+%%% Description : This supervisor is used to resume ttb tracing
+%%% Users are able to provide custom restart modules for *_config, as
+%%% file:write/read/delete may not be possible on diskless nodes.
+%%%
+%%% Created : 31 Jul 2010 by <[email protected]>
+%%%-------------------------------------------------------------------
+-module(ttb_autostart).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0,
+ read_config/0,
+ write_config/1,
+ delete_config/0]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+-define(DEF_AUTOSTART_MODULE, ?MODULE).
+-define(AUTOSTART_FILENAME, "ttb_autostart.bin").
+
+start_link() ->
+ gen_server:start_link(?MODULE, no_args, []).
+
+delete_config() ->
+ file:delete(?AUTOSTART_FILENAME).
+
+read_config() ->
+ case file:read_file(?AUTOSTART_FILENAME) of
+ {ok, Data} -> {ok, binary_to_term(Data)};
+ Error -> Error
+ end.
+
+write_config(Data) ->
+ file:write_file(?AUTOSTART_FILENAME, term_to_binary(Data)).
+
+init(no_args) ->
+ case application:get_env(runtime_tools, ttb_autostart_module) of
+ {ok, _} -> ok;
+ undefined -> application:set_env(runtime_tools, ttb_autostart_module, ?DEF_AUTOSTART_MODULE)
+ end,
+ observer_backend:ttb_resume_trace(),
+ %%As the process is not needed any more, it will shut itself down
+ {ok, no_args, 10000}.
+
+handle_call(_,_,_) -> {noreply, no_args}.
+handle_cast(_,_) -> {noreply, no_args}.
+handle_info(timeout,_) -> {stop, normal, no_args}.
+terminate(_,_) -> ok.
+code_change(_,_,_) -> {ok, no_args}.
diff --git a/lib/runtime_tools/test/Makefile b/lib/runtime_tools/test/Makefile
index 7dc7a015e1..cfaf420d65 100644
--- a/lib/runtime_tools/test/Makefile
+++ b/lib/runtime_tools/test/Makefile
@@ -59,7 +59,7 @@ release_tests_spec: make_emakefile
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) runtime_tools.spec runtime_tools.cover $(ERL_FILES) $(RELSYSDIR)
$(INSTALL_DATA) $(EMAKEFILE) runtime_tools.cover $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk
index 6ed98f697e..0bcd261861 100644
--- a/lib/runtime_tools/vsn.mk
+++ b/lib/runtime_tools/vsn.mk
@@ -1 +1 @@
-RUNTIME_TOOLS_VSN = 1.8.5
+RUNTIME_TOOLS_VSN = 1.8.6
diff --git a/lib/sasl/Makefile b/lib/sasl/Makefile
index 2affcf1e40..4073e5af85 100644
--- a/lib/sasl/Makefile
+++ b/lib/sasl/Makefile
@@ -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,7 +23,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
# Macros
#
-SUB_DIRECTORIES = src doc/src
+SUB_DIRECTORIES = src doc/src examples/src
include vsn.mk
VSN = $(SASL_VSN)
diff --git a/lib/sasl/doc/src/notes.xml b/lib/sasl/doc/src/notes.xml
index 7941e371a0..01cdc4b29e 100644
--- a/lib/sasl/doc/src/notes.xml
+++ b/lib/sasl/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,6 +30,200 @@
</header>
<p>This document describes the changes made to the SASL application.</p>
+<section><title>SASL 2.1.10</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The release_handler functionality on windows services was
+ broken. This has been corrected.</p>
+ <p>
+ Own Id: OTP-9306</p>
+ </item>
+ <item>
+ <p>
+ If a new version of an application did not include any
+ erlang module changes, the code path of the application
+ was not updated by the release_handler unless a
+ 'load_object_code' instruction was added for the
+ application. This would be a problem if e.g. only some
+ files in the priv dir were changed since calls to
+ code:lib_dir or code:priv_dir would then point to the old
+ location of the application. This has been corrected -
+ now code:replace_path/2 will be called for all
+ applications that are changed (i.e. when the
+ application's vsn is changed in the .rel file).</p>
+ <p>
+ Own Id: OTP-9402</p>
+ </item>
+ <item>
+ <p>
+ The appup instruction 'delete_module' would cause a crash
+ during upgrade if the module to be deleted was not
+ loaded. This has been corrected.</p>
+ <p>
+ Own Id: OTP-9417</p>
+ </item>
+ <item>
+ <p>
+ If a path was given as ONLY 'ebin' and not for example
+ './ebin', then systools:make_tar would fail with a
+ <c>function_clause</c> exception in filename:join/1. This
+ has been corrected. (Thanks to Nikola Skoric for
+ reporting).</p>
+ <p>
+ Own Id: OTP-9507</p>
+ </item>
+ <item>
+ <p>
+ Implement or fix -Werror option</p>
+ <p>
+ If -Werror is enabled and there are warnings no output
+ file is written. Also make sure that error/warning
+ reporting is consistent. (Thanks to Tuncer Ayaz)</p>
+ <p>
+ Own Id: OTP-9536</p>
+ </item>
+ <item>
+ <p>
+ Improved error information for timeouts during
+ release_handler:install_release.</p>
+ <p>
+ This patch addresses two cases where a timeout will occur
+ during upgrade. 1) if a supervisor is suspended (call to
+ get children from supervisor will hang) 2) if the child
+ spec for a supervisor incorrectly states that it is a
+ worker with a dynamic set of modules (call to get modules
+ from gen_event will hang)</p>
+ <p>
+ An error report will now be printed, and the return value
+ of release_handler:install_release will indicate what
+ happened. (Thanks to joe williams)</p>
+ <p>
+ Own Id: OTP-9546</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ <c>release_handler:install_release</c> could be very slow
+ when there are many processes in the system. Some
+ optimization work has been done both in erts and in the
+ release handler in order to improve this. </p>
+ <p>
+ A new option, <c>purge</c>, is added to
+ <c>release_handler:check_install_release</c> which can be
+ called first in order to speed up the execution of
+ <c>release_handler:install_release</c>.</p>
+ <p>
+ Own Id: OTP-9395</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SASL 2.1.9.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Remove traces of release_handler reading from filesystem
+ when it has Masters list</p>
+ <p>
+ There are a couple of places in release_handler and
+ release_handler_1 that assumed it has a disk to read
+ from, which in the case of an erl_prim_loader Loader
+ other than efile is not necessarily true</p>
+ <p>
+ Add check_paths/2 to do the equivalent of check_path/1
+ for when there is a Masters list</p>
+ <p>
+ Change get_vsn to no longer get sent File paths but
+ instead use the Bin since beam_lib:version being sent a
+ file path causes it to read the local file system</p>
+ <p>
+ Add get_current_vsn/1 as an equivalent to
+ beam_lib:version(code:which(Mod)), but using
+ erl_prim_loader:get_file instead of reading from local
+ file system</p>
+ <p>
+ (Thanks to Steven Gravell)</p>
+ <p>
+ Own Id: OTP-9142</p>
+ </item>
+ <item>
+ <p>
+ rb:stop did sometimes return {error,running}. This came
+ from supervisor:delete_child and happened when the
+ rb_server has not yet terminated when this function was
+ called. Instead of having a separate gen_server call to
+ rb_server for stopping the process,
+ supervisor:terminate_child is now called. This is a
+ synchronous function - i.e. it waits for the process to
+ actually terminate before it returns.</p>
+ <p>
+ A file descriptor leak in rb:scan_files is corrected. The
+ index file was never closed after reading.</p>
+ <p>
+ A mismatch in the behavior of rb:filter, when filter
+ included 'no', is corrected. Such filters will now return
+ *all* non-matching reports, not only the 'proplist'
+ reports.</p>
+ <p>
+ Own Id: OTP-9149</p>
+ </item>
+ <item>
+ <p>
+ Start and end date for rb:filter/2 was specified as
+ {{Y-M-D},...} in the help text instead of {{Y,M,D},...}.
+ This has been corrected.</p>
+ <p>
+ Own Id: OTP-9166</p>
+ </item>
+ <item>
+ <p>
+ If some, but not all, of the sasl environment variables
+ related to the log_mf_h error handler were missing sasl
+ would successfully start but silently skip starting
+ log_mf_h. This is corrected so sasl startup will now fail
+ if one or two of the three variables are given. If none
+ of the variables are given, sasl will start as before
+ without starting log_mf_h.</p>
+ <p>
+ Own Id: OTP-9185</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Change default behaviour to not check src code when
+ creating release</p>
+ <p>
+ Add new option <c>src_tests</c> to systools:make_script
+ and systools:make_tar. The old option
+ <c>no_module_tests</c> is now ignored as this is the
+ default behaviour.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9146 Aux Id: seq11803 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SASL 2.1.9.3</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/sasl/doc/src/release_handler.xml b/lib/sasl/doc/src/release_handler.xml
index 4a973bc5ed..5ac0dc1acc 100644
--- a/lib/sasl/doc/src/release_handler.xml
+++ b/lib/sasl/doc/src/release_handler.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -159,9 +159,12 @@ old reboot_old permanent
<funcs>
<func>
<name>check_install_release(Vsn) -> {ok, OtherVsn, Descr} | {error, Reason}</name>
+ <name>check_install_release(Vsn,Opts) -> {ok, OtherVsn, Descr} | {error, Reason}</name>
<fsummary>Check installation of a release in the system.</fsummary>
<type>
<v>Vsn = OtherVsn = string()</v>
+ <v>Opts = [Opt]</v>
+ <v>Opt = purge</v>
<v>Descr = term()</v>
<v>Reason = term()</v>
</type>
@@ -179,6 +182,11 @@ old reboot_old permanent
upgrade script.</p>
<p>Returns the same as <c>install_release/1</c>. <c>Descr</c>
defaults to "" if no <c>relup</c> file is found.</p>
+ <p>If the option <c>purge</c> is given, all old code that can
+ be soft purged will be purged after all other checks are
+ successfully completed. This can be useful in order to
+ reduce the time needed by <seealso
+ marker="#install_release/1">install_release</seealso>.</p>
</desc>
</func>
<func>
@@ -299,6 +307,24 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
<c>{update_paths,true}</c>, afterwards
<c>code:lib_dir(myapp)</c> will return
<c>/home/user/myapp-1.0</c>.</p>
+ <note>
+ <p>Installing a new release might be quite time consuming if
+ there are many processes in the system. The reason is that
+ each process must be checked for references to old code
+ before a module can be purged. This check might lead to
+ garbage collections and copying of data.</p>
+ <p>If you wish to speed up the execution of
+ <c>install_release</c>, then you may call <seealso
+ marker="#check_install_release/1">check_install_release</seealso>
+ first, using the option <c>purge</c>. This will do the same
+ check for old code, and then purge all modules that can be
+ soft purged. The purged modules will then no longer have any
+ old code, and <c>install_release</c> will not need to do the
+ checks.</p>
+ <p>Obviously, this will not reduce the overall time for the
+ upgrade, but it will allow checks and purge to be executed
+ in the background before the real upgrade is started.</p>
+ </note>
</desc>
</func>
<func>
diff --git a/lib/sasl/doc/src/sasl_app.xml b/lib/sasl/doc/src/sasl_app.xml
index a7fecfc440..446baccb08 100644
--- a/lib/sasl/doc/src/sasl_app.xml
+++ b/lib/sasl/doc/src/sasl_app.xml
@@ -4,7 +4,7 @@
<appref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -67,6 +67,11 @@
<p>This error logger writes <em>all</em> events sent to
the error logger to disk. It installs the <c>log_mf_h</c>
event handler in the <c>error_logger</c> process.</p>
+ <p>To activate this event handler, the following three sasl
+ configuration parameters must be set:
+ <c>error_logger_mf_dir</c>, <c>error_logger_mf_maxbytes</c>
+ and <c>error_logger_mf_maxfiles</c>. See below for more
+ information about the configuration parameters.</p>
</item>
</taglist>
</section>
diff --git a/lib/sasl/doc/src/systools.xml b/lib/sasl/doc/src/systools.xml
index e28cd25f27..8c1c327d74 100644
--- a/lib/sasl/doc/src/systools.xml
+++ b/lib/sasl/doc/src/systools.xml
@@ -45,7 +45,8 @@
<v>Name = string()</v>
<v>UpFrom = DownTo = [Name | {Name,Descr}]</v>
<v>&nbsp;Descr = term()</v>
- <v>Opt = {path,[Dir]} | restart_emulator | silent | noexec | {outdir,Dir}</v>
+ <v>Opt = {path,[Dir]} | restart_emulator | silent | noexec | {outdir,Dir}
+ | warnings_as_errors</v>
<v>&nbsp;Dir = string()</v>
<v>Result = ok | error | {ok,Relup,Module,Warnings} | {error,Module,Error}</v>
<v>&nbsp;Relup - see relup(4)</v>
@@ -122,6 +123,8 @@
<p>If the option <c>noexec</c> is provided, the function returns
the same values as for <c>silent</c> but no <c>relup</c> file
is created.</p>
+ <p>If the option <c>warnings_as_errors</c> is provided, warnings
+ are treated as errors.</p>
</desc>
</func>
<func>
@@ -130,7 +133,8 @@
<fsummary>Generate a boot script <c>.script/.boot</c>.</fsummary>
<type>
<v>Name = string()</v>
- <v>Opt = no_module_tests | {path,[Dir]} | local | {variables,[Var]} | exref | {exref,[App]}] | silent | {outdir,Dir}</v>
+ <v>Opt = src_tests | {path,[Dir]} | local | {variables,[Var]} | exref | {exref,[App]}]
+ | silent | {outdir,Dir} | warnings_as_errors</v>
<v>&nbsp;Dir = string()</v>
<v>&nbsp;Var = {VarName,Prefix}</v>
<v>&nbsp;&nbsp;VarName = Prefix = string()</v>
@@ -174,15 +178,13 @@
the applications.</p>
</item>
<item>
- <p>There should no duplicated modules, that is, modules with
+ <p>There should be no duplicated modules, that is, modules with
the same name but belonging to different applications.</p>
</item>
<item>
- <p>A warning is issued if the source code for a module is
- missing or newer than the object code. <br></br>
-
- If the <c>no_module_tests</c> option is specified, this
- check is omitted.</p>
+ <p>If the <c>src_tests</c> option is specified, a
+ warning is issued if the source code for a module is
+ missing or newer than the object code.</p>
</item>
</list>
<p>The applications are sorted according to the dependencies
@@ -234,6 +236,8 @@
Warnings and errors can be converted to strings by calling
<c>Module:format_warning(Warnings)</c> or
<c>Module:format_error(Error)</c>.</p>
+ <p>If the option <c>warnings_as_errors</c> is provided, warnings
+ are treated as errors.</p>
</desc>
</func>
<func>
@@ -242,7 +246,7 @@
<fsummary>Create a release package.</fsummary>
<type>
<v>Name = string()</v>
- <v>Opt = {dirs,[IncDir]} | {path,[Dir]} | {variables,[Var]} | {var_tar,VarTar} | {erts,Dir} | no_module_tests | exref | {exref,[App]} | silent | {outdir,Dir}</v>
+ <v>Opt = {dirs,[IncDir]} | {path,[Dir]} | {variables,[Var]} | {var_tar,VarTar} | {erts,Dir} | src_tests | exref | {exref,[App]} | silent | {outdir,Dir}</v>
<v>&nbsp;Dir = string()</v>
<v>&nbsp;IncDir = src | include | atom()</v>
<v>&nbsp;Var = {VarName,PreFix}</v>
@@ -330,7 +334,7 @@ myapp-1/ebin/myapp.app
system <c>{erts,Dir}</c> is copied to <c>erts-ErtsVsn/bin</c>.</p>
<p>All checks performed with the <c>make_script</c> function
are performed before the release package is created. The
- <c>no_module_tests</c> and <c>exref</c> options are also
+ <c>src_tests</c> and <c>exref</c> options are also
valid here.</p>
<p>The return value and the handling of errors and warnings
are the same as described for <c>make_script</c> above.</p>
diff --git a/lib/sasl/examples/ebin/.gitignore b/lib/sasl/examples/ebin/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/sasl/examples/ebin/.gitignore
diff --git a/lib/sasl/examples/src/Makefile b/lib/sasl/examples/src/Makefile
new file mode 100644
index 0000000000..9cf0d4c25d
--- /dev/null
+++ b/lib/sasl/examples/src/Makefile
@@ -0,0 +1,78 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, 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=$(SASL_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/sasl-$(VSN)
+
+# ----------------------------------------------------
+# Common Macros
+# ----------------------------------------------------
+EXTRA_ERLC_FLAGS = +warn_unused_vars
+ERL_COMPILE_FLAGS += $(EXTRA_ERLC_FLAGS)
+
+
+MODULES = target_system
+
+ERL_FILES= $(MODULES:%=%.erl)
+
+TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+# ----------------------------------------------------
+# 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/src
+ $(INSTALL_DIR) $(RELSYSDIR)/examples/ebin
+ (cd ..; tar cf - src ebin | (cd $(RELSYSDIR)/examples; tar xf -))
+ chmod -R ug+w $(RELSYSDIR)/examples
+
+release_docs_spec:
+
+
+
+
+
+
+
diff --git a/lib/sasl/examples/src/target_system.erl b/lib/sasl/examples/src/target_system.erl
new file mode 100644
index 0000000000..0e1e0b2324
--- /dev/null
+++ b/lib/sasl/examples/src/target_system.erl
@@ -0,0 +1,259 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(target_system).
+-export([create/1, create/2, install/2]).
+
+%% Note: RelFileName below is the *stem* without trailing .rel,
+%% .script etc.
+%%
+
+%% create(RelFileName)
+%%
+create(RelFileName) ->
+ create(RelFileName,[]).
+
+create(RelFileName,SystoolsOpts) ->
+ RelFile = RelFileName ++ ".rel",
+ Dir = filename:dirname(RelFileName),
+ PlainRelFileName = filename:join(Dir,"plain"),
+ PlainRelFile = PlainRelFileName ++ ".rel",
+ io:fwrite("Reading file: ~p ...~n", [RelFile]),
+ {ok, [RelSpec]} = file:consult(RelFile),
+ io:fwrite("Creating file: ~p from ~p ...~n",
+ [PlainRelFile, RelFile]),
+ {release,
+ {RelName, RelVsn},
+ {erts, ErtsVsn},
+ AppVsns} = RelSpec,
+ PlainRelSpec = {release,
+ {RelName, RelVsn},
+ {erts, ErtsVsn},
+ lists:filter(fun({kernel, _}) ->
+ true;
+ ({stdlib, _}) ->
+ true;
+ (_) ->
+ false
+ end, AppVsns)
+ },
+ {ok, Fd} = file:open(PlainRelFile, [write]),
+ io:fwrite(Fd, "~p.~n", [PlainRelSpec]),
+ file:close(Fd),
+
+ io:fwrite("Making \"~s.script\" and \"~s.boot\" files ...~n",
+ [PlainRelFileName,PlainRelFileName]),
+ make_script(PlainRelFileName,SystoolsOpts),
+
+ io:fwrite("Making \"~s.script\" and \"~s.boot\" files ...~n",
+ [RelFileName, RelFileName]),
+ make_script(RelFileName,SystoolsOpts),
+
+ TarFileName = filename:join(Dir,RelFileName ++ ".tar.gz"),
+ io:fwrite("Creating tar file ~p ...~n", [TarFileName]),
+ make_tar(RelFileName,SystoolsOpts),
+
+ TmpDir = filename:join(Dir,"tmp"),
+ io:fwrite("Creating directory ~p ...~n",[TmpDir]),
+ file:make_dir(TmpDir),
+
+ io:fwrite("Extracting ~p into directory ~p ...~n", [TarFileName,TmpDir]),
+ extract_tar(TarFileName, TmpDir),
+
+ TmpBinDir = filename:join([TmpDir, "bin"]),
+ ErtsBinDir = filename:join([TmpDir, "erts-" ++ ErtsVsn, "bin"]),
+ io:fwrite("Deleting \"erl\" and \"start\" in directory ~p ...~n",
+ [ErtsBinDir]),
+ file:delete(filename:join([ErtsBinDir, "erl"])),
+ file:delete(filename:join([ErtsBinDir, "start"])),
+
+ io:fwrite("Creating temporary directory ~p ...~n", [TmpBinDir]),
+ file:make_dir(TmpBinDir),
+
+ io:fwrite("Copying file \"~s.boot\" to ~p ...~n",
+ [PlainRelFileName, filename:join([TmpBinDir, "start.boot"])]),
+ copy_file(PlainRelFileName++".boot",filename:join([TmpBinDir, "start.boot"])),
+
+ io:fwrite("Copying files \"epmd\", \"run_erl\" and \"to_erl\" from \n"
+ "~p to ~p ...~n",
+ [ErtsBinDir, TmpBinDir]),
+ copy_file(filename:join([ErtsBinDir, "epmd"]),
+ filename:join([TmpBinDir, "epmd"]), [preserve]),
+ copy_file(filename:join([ErtsBinDir, "run_erl"]),
+ filename:join([TmpBinDir, "run_erl"]), [preserve]),
+ copy_file(filename:join([ErtsBinDir, "to_erl"]),
+ filename:join([TmpBinDir, "to_erl"]), [preserve]),
+
+ StartErlDataFile = filename:join([TmpDir, "releases", "start_erl.data"]),
+ io:fwrite("Creating ~p ...~n", [StartErlDataFile]),
+ StartErlData = io_lib:fwrite("~s ~s~n", [ErtsVsn, RelVsn]),
+ write_file(StartErlDataFile, StartErlData),
+
+ io:fwrite("Recreating tar file ~p from contents in directory ~p ...~n",
+ [TarFileName,TmpDir]),
+ {ok, Tar} = erl_tar:open(TarFileName, [write, compressed]),
+ %% {ok, Cwd} = file:get_cwd(),
+ %% file:set_cwd("tmp"),
+ ErtsDir = "erts-"++ErtsVsn,
+ erl_tar:add(Tar, filename:join(TmpDir,"bin"), "bin", []),
+ erl_tar:add(Tar, filename:join(TmpDir,ErtsDir), ErtsDir, []),
+ erl_tar:add(Tar, filename:join(TmpDir,"releases"), "releases", []),
+ erl_tar:add(Tar, filename:join(TmpDir,"lib"), "lib", []),
+ erl_tar:close(Tar),
+ %% file:set_cwd(Cwd),
+ io:fwrite("Removing directory ~p ...~n",[TmpDir]),
+ remove_dir_tree(TmpDir),
+ ok.
+
+
+install(RelFileName, RootDir) ->
+ TarFile = RelFileName ++ ".tar.gz",
+ io:fwrite("Extracting ~p ...~n", [TarFile]),
+ extract_tar(TarFile, RootDir),
+ StartErlDataFile = filename:join([RootDir, "releases", "start_erl.data"]),
+ {ok, StartErlData} = read_txt_file(StartErlDataFile),
+ [ErlVsn, _RelVsn| _] = string:tokens(StartErlData, " \n"),
+ ErtsBinDir = filename:join([RootDir, "erts-" ++ ErlVsn, "bin"]),
+ BinDir = filename:join([RootDir, "bin"]),
+ io:fwrite("Substituting in erl.src, start.src and start_erl.src to\n"
+ "form erl, start and start_erl ...\n"),
+ subst_src_scripts(["erl", "start", "start_erl"], ErtsBinDir, BinDir,
+ [{"FINAL_ROOTDIR", RootDir}, {"EMU", "beam"}],
+ [preserve]),
+ io:fwrite("Creating the RELEASES file ...\n"),
+ create_RELEASES(RootDir,
+ filename:join([RootDir, "releases", RelFileName])).
+
+%% LOCALS
+
+%% make_script(RelFileName,Opts)
+%%
+make_script(RelFileName,Opts) ->
+ systools:make_script(RelFileName, [no_module_tests,
+ {outdir,filename:dirname(RelFileName)}
+ |Opts]).
+
+%% make_tar(RelFileName,Opts)
+%%
+make_tar(RelFileName,Opts) ->
+ RootDir = code:root_dir(),
+ systools:make_tar(RelFileName, [{erts, RootDir},
+ {outdir,filename:dirname(RelFileName)}
+ |Opts]).
+
+%% extract_tar(TarFile, DestDir)
+%%
+extract_tar(TarFile, DestDir) ->
+ erl_tar:extract(TarFile, [{cwd, DestDir}, compressed]).
+
+create_RELEASES(DestDir, RelFileName) ->
+ release_handler:create_RELEASES(DestDir, RelFileName ++ ".rel").
+
+subst_src_scripts(Scripts, SrcDir, DestDir, Vars, Opts) ->
+ lists:foreach(fun(Script) ->
+ subst_src_script(Script, SrcDir, DestDir,
+ Vars, Opts)
+ end, Scripts).
+
+subst_src_script(Script, SrcDir, DestDir, Vars, Opts) ->
+ subst_file(filename:join([SrcDir, Script ++ ".src"]),
+ filename:join([DestDir, Script]),
+ Vars, Opts).
+
+subst_file(Src, Dest, Vars, Opts) ->
+ {ok, Conts} = read_txt_file(Src),
+ NConts = subst(Conts, Vars),
+ write_file(Dest, NConts),
+ case lists:member(preserve, Opts) of
+ true ->
+ {ok, FileInfo} = file:read_file_info(Src),
+ file:write_file_info(Dest, FileInfo);
+ false ->
+ ok
+ end.
+
+%% subst(Str, Vars)
+%% Vars = [{Var, Val}]
+%% Var = Val = string()
+%% Substitute all occurrences of %Var% for Val in Str, using the list
+%% of variables in Vars.
+%%
+subst(Str, Vars) ->
+ subst(Str, Vars, []).
+
+subst([$%, C| Rest], Vars, Result) when $A =< C, C =< $Z ->
+ subst_var([C| Rest], Vars, Result, []);
+subst([$%, C| Rest], Vars, Result) when $a =< C, C =< $z ->
+ subst_var([C| Rest], Vars, Result, []);
+subst([$%, C| Rest], Vars, Result) when C == $_ ->
+ subst_var([C| Rest], Vars, Result, []);
+subst([C| Rest], Vars, Result) ->
+ subst(Rest, Vars, [C| Result]);
+subst([], _Vars, Result) ->
+ lists:reverse(Result).
+
+subst_var([$%| Rest], Vars, Result, VarAcc) ->
+ Key = lists:reverse(VarAcc),
+ case lists:keysearch(Key, 1, Vars) of
+ {value, {Key, Value}} ->
+ subst(Rest, Vars, lists:reverse(Value, Result));
+ false ->
+ subst(Rest, Vars, [$%| VarAcc ++ [$%| Result]])
+ end;
+subst_var([C| Rest], Vars, Result, VarAcc) ->
+ subst_var(Rest, Vars, Result, [C| VarAcc]);
+subst_var([], Vars, Result, VarAcc) ->
+ subst([], Vars, [VarAcc ++ [$%| Result]]).
+
+copy_file(Src, Dest) ->
+ copy_file(Src, Dest, []).
+
+copy_file(Src, Dest, Opts) ->
+ {ok,_} = file:copy(Src, Dest),
+ case lists:member(preserve, Opts) of
+ true ->
+ {ok, FileInfo} = file:read_file_info(Src),
+ file:write_file_info(Dest, FileInfo);
+ false ->
+ ok
+ end.
+
+write_file(FName, Conts) ->
+ {ok, Fd} = file:open(FName, [write]),
+ file:write(Fd, Conts),
+ file:close(Fd).
+
+read_txt_file(File) ->
+ {ok, Bin} = file:read_file(File),
+ {ok, binary_to_list(Bin)}.
+
+remove_dir_tree(Dir) ->
+ remove_all_files(".", [Dir]).
+
+remove_all_files(Dir, Files) ->
+ lists:foreach(fun(File) ->
+ FilePath = filename:join([Dir, File]),
+ case filelib:is_dir(FilePath) of
+ true ->
+ {ok, DirFiles} = file:list_dir(FilePath),
+ remove_all_files(FilePath, DirFiles),
+ file:del_dir(FilePath);
+ _ ->
+ file:delete(FilePath)
+ end
+ end, Files).
diff --git a/lib/sasl/src/erlsrv.erl b/lib/sasl/src/erlsrv.erl
index f9804c41dc..086dc7c651 100644
--- a/lib/sasl/src/erlsrv.erl
+++ b/lib/sasl/src/erlsrv.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The 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,14 +75,21 @@ write_all_data(Port,[H|T]) ->
write_all_data(Port,T).
read_all_data(Port) ->
+ lists:reverse(read_all_data(Port,[],[])).
+read_all_data(Port,Line,Lines) ->
receive
+ {Port, {data, {noeol,Data}}} ->
+ read_all_data(Port,Line++Data,Lines);
{Port, {data, {eol,Data}}} ->
- [ Data | read_all_data(Port)];
- _ ->
+ read_all_data(Port,[],[Line++Data|Lines]);
+ {Port,_Other} ->
Port ! {self(), close},
receive
{Port, closed} ->
- []
+ case Line of
+ [] -> Lines;
+ _ -> [Line|Lines]
+ end
end
end.
@@ -208,7 +215,7 @@ store_service(EmulatorVersion,Service) ->
false ->
{error, no_servicename};
{value, {_,Name}} ->
- {Action,Service1} = case get_service(Name) of
+ {Action,Service1} = case get_service(EmulatorVersion,Name) of
{error, no_such_service} ->
{"add",Service};
_ ->
@@ -377,8 +384,14 @@ pick_argument(_,[],Acc) ->
{Acc, ""};
pick_argument(normal,[$ |T],Acc) ->
{Acc,T};
+pick_argument(normal,[$\\|T],Acc) ->
+ pick_argument(normal_escaped,T,[$\\|Acc]);
pick_argument(normal,[$"|T],Acc) ->
pick_argument(quoted,T,[$"|Acc]);
+pick_argument(normal_escaped,[$"|T],Acc) ->
+ pick_argument(bquoted,T,[$"|Acc]);
+pick_argument(normal_escaped,[A|T],Acc) ->
+ pick_argument(normal,T,[A|Acc]);
pick_argument(quoted_escaped,[H|T],Acc) ->
pick_argument(quoted,T,[H|Acc]);
pick_argument(quoted,[$"|T],Acc) ->
@@ -387,6 +400,14 @@ pick_argument(quoted,[$\\|T],Acc) ->
pick_argument(quoted_escaped,T,[$\\|Acc]);
pick_argument(quoted,[H|T],Acc) ->
pick_argument(quoted,T,[H|Acc]);
+pick_argument(bquoted_escaped,[$"|T],Acc) ->
+ pick_argument(normal,T,[$"|Acc]);
+pick_argument(bquoted_escaped,[H|T],Acc) ->
+ pick_argument(bquoted,T,[H|Acc]);
+pick_argument(bquoted,[$\\|T],Acc) ->
+ pick_argument(bquoted_escaped,T,[$\\|Acc]);
+pick_argument(bquoted,[H|T],Acc) ->
+ pick_argument(bquoted,T,[H|Acc]);
pick_argument(normal,[H|T],Acc) ->
pick_argument(normal,T,[H|Acc]).
diff --git a/lib/sasl/src/rb.erl b/lib/sasl/src/rb.erl
index 38e486b7a7..8004ef2c5a 100644
--- a/lib/sasl/src/rb.erl
+++ b/lib/sasl/src/rb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,8 +53,7 @@ start_link(Options) ->
gen_server:start_link({local, rb_server}, rb, Options, []).
stop() ->
- call(stop),
- supervisor:delete_child(sasl_sup, rb_server).
+ supervisor:terminate_child(sasl_sup, rb_server).
rescan() -> rescan([]).
rescan(Options) ->
@@ -169,7 +168,7 @@ print_filters() ->
print_dates() ->
io:format(" - {StartDate, EndDate}~n"),
- io:format(" StartDate = EndDate = {{Y-M-D},{H,M,S}} ~n"),
+ io:format(" StartDate = EndDate = {{Y,M,D},{H,M,S}} ~n"),
io:format(" prints the reports with date between StartDate and EndDate~n"),
io:format(" - {StartDate, from}~n"),
io:format(" prints the reports with date greater than StartDate~n"),
@@ -205,8 +204,6 @@ handle_call({rescan, Options}, _From, State) ->
NewState = State#state{data = Data, max = Max, type = Type,
device = Device, abort = Abort, log = Log1},
{reply, ok, NewState};
-handle_call(stop, _From, State) ->
- {stop, normal, stopped, State};
handle_call(_, _From, #state{data = undefined}) ->
{reply, {error, no_data}, #state{}};
handle_call({list, Type}, _From, State) ->
@@ -312,11 +309,14 @@ scan_files(RptDir, Max, Type) ->
{ok, Fd} ->
case catch file:read(Fd, 1) of
{ok, [LastWritten]} ->
+ file:close(Fd),
Files = make_file_list(RptDir, LastWritten),
scan_files(RptDir, Files, Max, Type);
- _ -> exit("cannot read the index file")
+ _X ->
+ file:close(Fd),
+ exit("cannot read the index file")
end;
- _ -> exit("cannot read the index file")
+ _X -> exit("cannot read the index file")
end.
make_file_list(Dir, FirstFileNo) ->
@@ -789,7 +789,7 @@ filter_report([{Key, RegExp, re}|T], Msg) ->
filter_report([{Key, RegExp, re, no}|T], Msg) ->
case proplists:get_value(Key, Msg) of
undefined ->
- false;
+ true;
Value ->
Subject = lists:flatten(io_lib:format("~p",[Value])),
case run_re(Subject, RegExp) of
diff --git a/lib/sasl/src/release_handler.erl b/lib/sasl/src/release_handler.erl
index b60aa847df..bc08f94dff 100644
--- a/lib/sasl/src/release_handler.erl
+++ b/lib/sasl/src/release_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,8 +25,8 @@
-export([start_link/0,
create_RELEASES/1, create_RELEASES/2, create_RELEASES/4,
unpack_release/1,
- check_install_release/1, install_release/1, install_release/2,
- remove_release/1,
+ check_install_release/1, check_install_release/2,
+ install_release/1, install_release/2, remove_release/1,
which_releases/0, make_permanent/1, reboot_old_release/1,
set_unpacked/2, set_removed/1, install_file/2]).
-export([upgrade_app/2, downgrade_app/2, downgrade_app/3,
@@ -149,15 +149,35 @@ unpack_release(ReleaseName) ->
%%-----------------------------------------------------------------
%% Purpose: Checks the relup script for the specified version.
%% The release must be unpacked.
+%% Options = [purge] - all old code that can be soft purged
+%% will be purged if all checks succeeds. This can be usefull
+%% in order to reduce time needed in the following call to
+%% install_release.
%% Returns: {ok, FromVsn, Descr} | {error, Reason}
-%% Reason = {already_installed, Vsn} |
+%% Reason = {illegal_option, IllegalOpt} |
+%% {already_installed, Vsn} |
%% {bad_relup_file, RelFile} |
%% {no_such_release, Vsn} |
%% {no_such_from_vsn, Vsn} |
%% exit_reason()
%%-----------------------------------------------------------------
check_install_release(Vsn) ->
- call({check_install_release, Vsn}).
+ check_install_release(Vsn, []).
+
+check_install_release(Vsn, Opts) ->
+ case check_check_install_options(Opts, false) of
+ {ok,Purge} ->
+ call({check_install_release, Vsn, Purge});
+ Error ->
+ Error
+ end.
+
+check_check_install_options([purge|Opts], _) ->
+ check_check_install_options(Opts, true);
+check_check_install_options([Illegal|_],_Purge) ->
+ {error,{illegal_option,Illegal}};
+check_check_install_options([],Purge) ->
+ {ok,Purge}.
%%-----------------------------------------------------------------
@@ -291,7 +311,8 @@ check_script(Script, LibDirs) ->
release_handler_1:check_script(Script, LibDirs).
%%-----------------------------------------------------------------
-%% eval_script(Script, Apps, LibDirs, Opts) -> {ok, UnPurged} |
+%% eval_script(Script, Apps, LibDirs, NewLibs, Opts) ->
+%% {ok, UnPurged} |
%% restart_new_emulator |
%% {error, Error}
%% {'EXIT', Reason}
@@ -299,9 +320,13 @@ check_script(Script, LibDirs) ->
%% net_kernel:monitor_nodes(true) before calling this function.
%% No! No other process than the release_handler can ever call this
%% function, if sync_nodes is used.
-%%-----------------------------------------------------------------
-eval_script(Script, Apps, LibDirs, Opts) ->
- catch release_handler_1:eval_script(Script, Apps, LibDirs, Opts).
+%%
+%% LibDirs is a list of all applications, while NewLibs is a list of
+%% applications that have changed version between the current and the
+%% new release.
+%% -----------------------------------------------------------------
+eval_script(Script, Apps, LibDirs, NewLibs, Opts) ->
+ catch release_handler_1:eval_script(Script, Apps, LibDirs, NewLibs, Opts).
%%-----------------------------------------------------------------
%% Func: create_RELEASES(Root, RelFile, LibDirs) -> ok | {error, Reason}
@@ -405,6 +430,7 @@ eval_appup_script(App, ToVsn, ToDir, Script) ->
Res = release_handler_1:eval_script(Script,
[], % [AppSpec]
[{App, ToVsn, ToDir}],
+ [{App, ToVsn, ToDir}],
[]), % [Opt]
case Res of
{ok, _Unpurged} ->
@@ -535,11 +561,12 @@ handle_call({unpack_release, ReleaseName}, _From, S)
handle_call({unpack_release, _ReleaseName}, _From, S) ->
{reply, {error, client_node}, S};
-handle_call({check_install_release, Vsn}, _From, S) ->
+handle_call({check_install_release, Vsn, Purge}, _From, S) ->
case catch do_check_install_release(S#state.rel_dir,
Vsn,
S#state.releases,
- S#state.masters) of
+ S#state.masters,
+ Purge) of
{ok, CurrentVsn, Descr} ->
{reply, {ok, CurrentVsn, Descr}, S};
{error, Reason} ->
@@ -849,7 +876,7 @@ check_path_response(Path, {ok, _Info}) ->
check_path_response(Path, {error, _Reason}) ->
throw({error, {no_such_directory, Path}}).
-do_check_install_release(RelDir, Vsn, Releases, Masters) ->
+do_check_install_release(RelDir, Vsn, Releases, Masters, Purge) ->
case lists:keysearch(Vsn, #release.vsn, Releases) of
{value, #release{status = current}} ->
{error, {already_installed, Vsn}};
@@ -874,7 +901,20 @@ do_check_install_release(RelDir, Vsn, Releases, Masters) ->
case get_rh_script(LatestRelease, Release, RelDir, Masters) of
{ok, {CurrentVsn, Descr, Script}} ->
case catch check_script(Script, Libs) of
- ok ->
+ {ok,SoftPurgeMods} when Purge=:=true ->
+ %% Get modules with brutal_purge
+ %% instructions, but that can be
+ %% soft purged
+ {ok,BrutalPurgeMods} =
+ release_handler_1:check_old_processes(
+ Script,brutal_purge),
+ lists:foreach(
+ fun(Mod) ->
+ catch erlang:purge_module(Mod)
+ end,
+ SoftPurgeMods ++ BrutalPurgeMods),
+ {ok, CurrentVsn, Descr};
+ {ok,_} ->
{ok, CurrentVsn, Descr};
Else ->
Else
@@ -890,6 +930,7 @@ do_check_install_release(RelDir, Vsn, Releases, Masters) ->
end.
do_install_release(#state{start_prg = StartPrg,
+ root = RootDir,
rel_dir = RelDir, releases = Releases,
masters = Masters,
static_emulator = Static},
@@ -905,7 +946,9 @@ do_install_release(#state{start_prg = StartPrg,
EnvBefore = application_controller:prep_config_change(),
Apps = change_appl_data(RelDir, Release, Masters),
LibDirs = Release#release.libs,
- case eval_script(Script, Apps, LibDirs, Opts) of
+ NewLibs = get_new_libs(LatestRelease#release.libs,
+ Release#release.libs),
+ case eval_script(Script, Apps, LibDirs, NewLibs, Opts) of
{ok, []} ->
application_controller:config_change(EnvBefore),
mon_nodes(false),
@@ -926,8 +969,8 @@ do_install_release(#state{start_prg = StartPrg,
NReleases = set_status(Vsn, current, Releases),
NReleases2 = set_status(Vsn,tmp_current,NReleases),
write_releases(RelDir, NReleases2, Masters),
- prepare_restart_new_emulator(StartPrg, RelDir,
- Release,
+ prepare_restart_new_emulator(StartPrg, RootDir,
+ RelDir, Release,
PermanentRelease,
Masters),
{restart_new_emulator, CurrentVsn, Descr};
@@ -997,7 +1040,7 @@ do_make_services_permanent(PermanentVsn,Vsn, PermanentEVsn, EVsn) ->
throw(Error4)
end
end.
-
+
do_make_permanent(#state{releases = Releases,
rel_dir = RelDir, unpurged = Unpurged,
masters = Masters,
@@ -1409,8 +1452,8 @@ prepare_restart_nt(#release{erts_vsn = EVsn, vsn = Vsn},
FutureServiceName = hd(string:tokens(atom_to_list(node()),"@"))
++ "_" ++ Vsn,
CurrentService = case erlsrv:get_service(PermEVsn,CurrentServiceName) of
- {error, Reason} ->
- throw({error, Reason});
+ {error, _} = Error1 ->
+ throw(Error1);
CS ->
CS
end,
@@ -1425,37 +1468,33 @@ prepare_restart_nt(#release{erts_vsn = EVsn, vsn = Vsn},
CurrentServiceName),
case erlsrv:store_service(EVsn, FutureService) of
- {error, Rison} ->
- throw({error,Rison});
- _ ->
+ {error, _} = Error2 ->
+ throw(Error2);
+ _X ->
erlsrv:disable_service(EVsn, FutureServiceName),
ErlSrv = filename:nativename(erlsrv:erlsrv(EVsn)),
- case heart:set_cmd(ErlSrv ++ " enable " ++ FutureServiceName ++
- " & " ++ ErlSrv ++ " start " ++
- FutureServiceName ++
- " & " ++ ErlSrv ++ " disable " ++
- FutureServiceName) of
+ StartDisabled = ErlSrv ++ " start_disabled " ++ FutureServiceName,
+ case heart:set_cmd(StartDisabled) of
ok ->
ok;
- Error ->
- throw({error, {'heart:set_cmd() error', Error}})
+ Error3 ->
+ throw({error, {'heart:set_cmd() error', Error3}})
end
end.
-
%%-----------------------------------------------------------------
%% Set things up for restarting the new emulator. The actual
%% restart is performed by calling init:reboot() higher up.
%%-----------------------------------------------------------------
-prepare_restart_new_emulator(StartPrg, RelDir,
- Release, PRelease,
- Masters) ->
+prepare_restart_new_emulator(StartPrg, RootDir, RelDir,
+ Release, PRelease, Masters) ->
#release{erts_vsn = EVsn, vsn = Vsn} = Release,
Data = EVsn ++ " " ++ Vsn,
DataFile = write_new_start_erl(Data, RelDir, Masters),
%% Tell heart to use DataFile instead of start_erl.data
case os:type() of
{win32,nt} ->
+ write_ini_file(RootDir,EVsn,Masters),
prepare_restart_nt(Release,PRelease,DataFile);
{unix,_} ->
StartP = check_start_prg(StartPrg, Masters),
@@ -1832,50 +1871,10 @@ write_start(File, Data, false) ->
end;
write_start(File, Data, Masters) ->
all_masters(Masters),
- write_start_m(File, Data, Masters).
+ safe_write_file_m(File, Data, Masters).
%%-----------------------------------------------------------------
-%% Write the "start_erl.data" file at all master nodes.
-%% 1. Save "start_erl.backup" at all nodes.
-%% 2. Write the "start_erl.change" file at all nodes.
-%% 3. Move "start_erl.change" to "start_erl.data".
-%% 4. Remove "start_erl.backup" at all nodes.
-%%
-%% If one of the steps above fails, all steps is recovered from
-%% (as long as possible), except for 4 which is allowed to fail.
-%%-----------------------------------------------------------------
-write_start_m(File, Data, Masters) ->
- Dir = filename:dirname(File),
- Backup = filename:join(Dir, "start_erl.backup"),
- Change = filename:join(Dir, "start_erl.change"),
- case at_all_masters(Masters, ?MODULE, do_copy_files,
- [File, [Backup]]) of
- ok ->
- case at_all_masters(Masters, ?MODULE, do_write_file,
- [Change, Data]) of
- ok ->
- case at_all_masters(Masters, file, rename,
- [Change, File]) of
- ok ->
- remove_files(all, [Backup, Change], Masters),
- ok;
- {error, {Master, R}} ->
- takewhile(Master, Masters, file, rename,
- [Backup, File]),
- remove_files(all, [Backup, Change], Masters),
- throw({error, {Master, R, move_start_erl}})
- end;
- {error, {Master, R}} ->
- remove_files(all, [Backup, Change], Masters),
- throw({error, {Master, R, write_start_erl}})
- end;
- {error, {Master, R}} ->
- remove_files(Master, [Backup], Masters),
- throw({error, {Master, R, backup_start_erl}})
- end.
-
-%%-----------------------------------------------------------------
%% Copy the "start.boot" and "sys.config" from SrcDir to DestDir at all
%% master nodes.
%% 1. Save DestDir/"start.backup" and DestDir/"sys.backup" at all nodes.
@@ -1917,3 +1916,97 @@ set_static_files(SrcDir, DestDir, Masters) ->
remove_files(Master, [BackupBoot, BackupConf], Masters),
throw({error, {Master, R, backup_start_config}})
end.
+
+%%-----------------------------------------------------------------
+%% Write erl.ini
+%% Writes the erl.ini file used by erl.exe when (re)starting the erlang node.
+%% At first installation, this is done by Install.exe, which means that if
+%% the format of this file for some reason is changed, then Install.c must
+%% also be updated (and probably some other c-files which read erl.ini)
+%%-----------------------------------------------------------------
+write_ini_file(RootDir,EVsn,Masters) ->
+ BinDir = filename:join([RootDir,"erts-"++EVsn,"bin"]),
+ Str0 = io_lib:format("[erlang]~n"
+ "Bindir=~s~n"
+ "Progname=erl~n"
+ "Rootdir=~s~n",
+ [filename:nativename(BinDir),
+ filename:nativename(RootDir)]),
+ Str = re:replace(Str0,"\\\\","\\\\\\\\",[{return,list},global]),
+ IniFile = filename:join(BinDir,"erl.ini"),
+ do_write_ini_file(IniFile,Str,Masters).
+
+do_write_ini_file(File,Data,false) ->
+ case do_write_file(File, Data) of
+ ok -> ok;
+ Error -> throw(Error)
+ end;
+do_write_ini_file(File,Data,Masters) ->
+ all_masters(Masters),
+ safe_write_file_m(File, Data, Masters).
+
+
+%%-----------------------------------------------------------------
+%% Write the given file at all master nodes.
+%% 1. Save <File>.backup at all nodes.
+%% 2. Write <File>.change at all nodes.
+%% 3. Move <File>.change to <File>
+%% 4. Remove <File>.backup at all nodes.
+%%
+%% If one of the steps above fails, all steps are recovered from
+%% (as long as possible), except for 4 which is allowed to fail.
+%%-----------------------------------------------------------------
+safe_write_file_m(File, Data, Masters) ->
+ Backup = File ++ ".backup",
+ Change = File ++ ".change",
+ case at_all_masters(Masters, ?MODULE, do_copy_files,
+ [File, [Backup]]) of
+ ok ->
+ case at_all_masters(Masters, ?MODULE, do_write_file,
+ [Change, Data]) of
+ ok ->
+ case at_all_masters(Masters, file, rename,
+ [Change, File]) of
+ ok ->
+ remove_files(all, [Backup, Change], Masters),
+ ok;
+ {error, {Master, R}} ->
+ takewhile(Master, Masters, file, rename,
+ [Backup, File]),
+ remove_files(all, [Backup, Change], Masters),
+ throw({error, {Master, R, rename,
+ filename:basename(Change),
+ filename:basename(File)}})
+ end;
+ {error, {Master, R}} ->
+ remove_files(all, [Backup, Change], Masters),
+ throw({error, {Master, R, write, filename:basename(Change)}})
+ end;
+ {error, {Master, R}} ->
+ remove_files(Master, [Backup], Masters),
+ throw({error, {Master, R, backup,
+ filename:basename(File),
+ filename:basename(Backup)}})
+ end.
+
+%%-----------------------------------------------------------------
+%% Figure out which applications that have changed version between the
+%% two releases. The paths for these applications must always be
+%% updated, even if the relup script does not load any modules. See
+%% OTP-9402.
+%%
+%% A different situation is when the same application version is used
+%% in old and new release, but the path has changed. This is not
+%% handled here - instead it must be explicitely indicated by the
+%% 'update_paths' option to release_handler:install_release/2 if the
+%% code path shall be updated then.
+%% -----------------------------------------------------------------
+get_new_libs([{App,Vsn,_LibDir}|CurrentLibs], NewLibs) ->
+ case lists:keyfind(App,1,NewLibs) of
+ {App,NewVsn,_} = LibInfo when NewVsn =/= Vsn ->
+ [LibInfo | get_new_libs(CurrentLibs,NewLibs)];
+ _ ->
+ get_new_libs(CurrentLibs,NewLibs)
+ end;
+get_new_libs([],_) ->
+ [].
diff --git a/lib/sasl/src/release_handler_1.erl b/lib/sasl/src/release_handler_1.erl
index 8d050fb7b0..8d0baf3ab1 100644
--- a/lib/sasl/src/release_handler_1.erl
+++ b/lib/sasl/src/release_handler_1.erl
@@ -19,8 +19,9 @@
-module(release_handler_1).
%% External exports
--export([eval_script/3, eval_script/4, check_script/2]).
--export([get_current_vsn/1]). %% exported because used in a test case
+-export([eval_script/1, eval_script/5,
+ check_script/2, check_old_processes/2]).
+-export([get_current_vsn/1, get_supervised_procs/0]). %% exported because used in a test case
-record(eval_state, {bins = [], stopped = [], suspended = [], apps = [],
libdirs, unpurged = [], vsns = [], newlibs = [],
@@ -33,11 +34,11 @@
%% libdirs = [{Lib, LibVsn, LibDir}] - Maps Lib to Vsn and Directory
%% unpurged = [{Mod, soft_purge | brutal_purge}]
%% vsns = [{Mod, OldVsn, NewVsn}] - remember the old vsn of a mod
-%% before it is removed/a new vsn is loaded; the new vsn
+%% before a new vsn is loaded; the new vsn
%% is kept in case of a downgrade, where the code_change
%% function receives the vsn of the module to downgrade
%% *to*.
-%% newlibs = [{Lib, Dir}] - list of all new libs; used to change
+%% newlibs = [{Lib, LibVsn, LibDir}] - list of all new libs; used to change
%% the code path
%% opts = [{Tag, Value}] - list of options
%%-----------------------------------------------------------------
@@ -47,34 +48,39 @@
%%% This is a low-level release handler.
%%%-----------------------------------------------------------------
check_script(Script, LibDirs) ->
- case catch check_old_processes(Script) of
- ok ->
+ case catch check_old_processes(Script,soft_purge) of
+ {ok, PurgeMods} ->
{Before, _After} = split_instructions(Script),
case catch lists:foldl(fun(Instruction, EvalState1) ->
eval(Instruction, EvalState1)
end,
#eval_state{libdirs = LibDirs},
Before) of
- EvalState2 when is_record(EvalState2, eval_state) -> ok;
- {error, Error} -> {error, Error};
- Other -> {error, Other}
+ EvalState2 when is_record(EvalState2, eval_state) ->
+ {ok,PurgeMods};
+ {error, Error} ->
+ {error, Error};
+ Other ->
+ {error, Other}
end;
{error, Mod} ->
{error, {old_processes, Mod}}
end.
-eval_script(Script, Apps, LibDirs) ->
- eval_script(Script, Apps, LibDirs, []).
+%% eval_script/1 - For testing only - no apps added, just testing instructions
+eval_script(Script) ->
+ eval_script(Script, [], [], [], []).
-eval_script(Script, Apps, LibDirs, Opts) ->
- case catch check_old_processes(Script) of
- ok ->
+eval_script(Script, Apps, LibDirs, NewLibs, Opts) ->
+ case catch check_old_processes(Script,soft_purge) of
+ {ok,_} ->
{Before, After} = split_instructions(Script),
case catch lists:foldl(fun(Instruction, EvalState1) ->
eval(Instruction, EvalState1)
end,
#eval_state{apps = Apps,
libdirs = LibDirs,
+ newlibs = NewLibs,
opts = Opts},
Before) of
EvalState2 when is_record(EvalState2, eval_state) ->
@@ -110,32 +116,63 @@ split_instructions([], Before) ->
{[], lists:reverse(Before)}.
%%-----------------------------------------------------------------
-%% Func: check_old_processes/1
+%% Func: check_old_processes/2
%% Args: Script = [instruction()]
+%% PrePurgeMethod = soft_purge | brutal_purge
%% Purpose: Check if there is any process that runs an old version
-%% of a module that should be soft_purged, (i.e. not purged
-%% at all if there is any such process). Returns {error, Mod}
-%% if so, ok otherwise.
-%% Returns: ok | {error, Mod}
+%% of a module that should be purged according to PrePurgeMethod.
+%% Returns a list of modules that can be soft_purged.
+%%
+%% If PrePurgeMethod == soft_purge, the function will succeed
+%% only if there is no process running old code of any of the
+%% modules. Else it will throw {error,Mod}, where Mod is the
+%% first module found that can not be soft_purged.
+%%
+%% If PrePurgeMethod == brutal_purge, the function will
+%% always succeed and return a list of all modules that are
+%% specified in the script with PrePurgeMethod brutal_purge,
+%% but that can be soft_purged.
+%%
+%% Returns: {ok,PurgeMods} | {error, Mod}
+%% PurgeMods = [Mod]
%% Mod = atom()
%%-----------------------------------------------------------------
-check_old_processes(Script) ->
- lists:foreach(fun({load, {Mod, soft_purge, _PostPurgeMethod}}) ->
- check_old_code(Mod);
- ({remove, {Mod, soft_purge, _PostPurgeMethod}}) ->
- check_old_code(Mod);
- (_) -> ok
- end,
- Script).
+check_old_processes(Script,PrePurgeMethod) ->
+ Procs = erlang:processes(),
+ {ok,lists:flatmap(
+ fun({load, {Mod, PPM, _PostPurgeMethod}}) when PPM==PrePurgeMethod ->
+ check_old_code(Mod,Procs,PrePurgeMethod);
+ ({remove, {Mod, PPM, _PostPurgeMethod}}) when PPM==PrePurgeMethod ->
+ check_old_code(Mod,Procs,PrePurgeMethod);
+ (_) -> []
+ end,
+ Script)}.
+
+check_old_code(Mod,Procs,PrePurgeMethod) ->
+ case erlang:check_old_code(Mod) of
+ true when PrePurgeMethod==soft_purge ->
+ do_check_old_code(Mod,Procs);
+ true when PrePurgeMethod==brutal_purge ->
+ case catch do_check_old_code(Mod,Procs) of
+ {error,Mod} -> [];
+ R -> R
+ end;
+ false ->
+ []
+ end.
+
+
+do_check_old_code(Mod,Procs) ->
+ lists:foreach(
+ fun(Pid) ->
+ case erlang:check_process_code(Pid, Mod) of
+ false -> ok;
+ true -> throw({error, Mod})
+ end
+ end,
+ Procs),
+ [Mod].
-check_old_code(Mod) ->
- lists:foreach(fun(Pid) ->
- case erlang:check_process_code(Pid, Mod) of
- false -> ok;
- true -> throw({error, Mod})
- end
- end,
- erlang:processes()).
%%-----------------------------------------------------------------
%% An unpurged module is a module for which there exist an old
@@ -214,16 +251,15 @@ check_old_code(Mod) ->
%%-----------------------------------------------------------------
eval({load_object_code, {Lib, LibVsn, Modules}}, EvalState) ->
case lists:keysearch(Lib, 1, EvalState#eval_state.libdirs) of
- {value, {Lib, LibVsn, LibDir}} ->
- Ebin = filename:join(LibDir, "ebin"),
+ {value, {Lib, LibVsn, LibDir} = LibInfo} ->
Ext = code:objfile_extension(),
{NewBins, NewVsns} =
lists:foldl(fun(Mod, {Bins, Vsns}) ->
File = lists:concat([Mod, Ext]),
- FName = filename:join(Ebin, File),
+ FName = filename:join([LibDir, "ebin", File]),
case erl_prim_loader:get_file(FName) of
{ok, Bin, FName2} ->
- NVsns = add_new_vsn(Mod, Bin, Vsns),
+ NVsns = add_vsns(Mod, Bin, Vsns),
{[{Mod, Bin, FName2} | Bins],NVsns};
error ->
throw({error, {no_such_file,FName}})
@@ -232,7 +268,7 @@ eval({load_object_code, {Lib, LibVsn, Modules}}, EvalState) ->
{EvalState#eval_state.bins,
EvalState#eval_state.vsns},
Modules),
- NewLibs = [{Lib, Ebin} | EvalState#eval_state.newlibs],
+ NewLibs = lists:keystore(Lib,1,EvalState#eval_state.newlibs,LibInfo),
EvalState#eval_state{bins = NewBins,
newlibs = NewLibs,
vsns = NewVsns};
@@ -242,15 +278,14 @@ eval({load_object_code, {Lib, LibVsn, Modules}}, EvalState) ->
eval(point_of_no_return, EvalState) ->
Libs = case get_opt(update_paths, EvalState, false) of
false ->
- EvalState#eval_state.newlibs; % [{Lib, Path}]
+ EvalState#eval_state.newlibs;
true ->
- lists:map(fun({Lib, _LibVsn, LibDir}) ->
- Ebin= filename:join(LibDir,"ebin"),
- {Lib, Ebin}
- end,
- EvalState#eval_state.libdirs)
+ EvalState#eval_state.libdirs
end,
- lists:foreach(fun({Lib, Path}) -> code:replace_path(Lib, Path) end,
+ lists:foreach(fun({Lib, _LibVsn, LibDir}) ->
+ Ebin = filename:join(LibDir,"ebin"),
+ code:replace_path(Lib, Ebin)
+ end,
Libs),
EvalState;
eval({load, {Mod, _PrePurgeMethod, PostPurgeMethod}}, EvalState) ->
@@ -258,32 +293,21 @@ eval({load, {Mod, _PrePurgeMethod, PostPurgeMethod}}, EvalState) ->
{value, {_Mod, Bin, File}} = lists:keysearch(Mod, 1, Bins),
% load_binary kills all procs running old code
% if soft_purge, we know that there are no such procs now
- Vsns = EvalState#eval_state.vsns,
- NewVsns = add_old_vsn(Mod, Vsns),
code:load_binary(Mod, File, Bin),
% Now, the prev current is old. There might be procs
% running it. Find them.
Unpurged = do_soft_purge(Mod,PostPurgeMethod,EvalState#eval_state.unpurged),
EvalState#eval_state{bins = lists:keydelete(Mod, 1, Bins),
- unpurged = Unpurged,
- vsns = NewVsns};
+ unpurged = Unpurged};
eval({remove, {Mod, _PrePurgeMethod, PostPurgeMethod}}, EvalState) ->
- % purge kills all procs running old code
- % if soft_purge, we know that there are no such procs now
- Vsns = EvalState#eval_state.vsns,
- NewVsns = add_old_vsn(Mod, Vsns),
+ %% purge kills all procs running old code
+ %% if soft_purge, we know that there are no such procs now
code:purge(Mod),
code:delete(Mod),
- % Now, the prev current is old. There might be procs
- % running it. Find them.
- Unpurged =
- case code:soft_purge(Mod) of
- true -> EvalState#eval_state.unpurged;
- false -> [{Mod, PostPurgeMethod} | EvalState#eval_state.unpurged]
- end,
-%% Bins = EvalState#eval_state.bins,
-%% EvalState#eval_state{bins = lists:keydelete(Mod, 1, Bins),
- EvalState#eval_state{unpurged = Unpurged, vsns = NewVsns};
+ %% Now, the prev current is old. There might be procs
+ %% running it. Find them.
+ Unpurged = do_soft_purge(Mod,PostPurgeMethod,EvalState#eval_state.unpurged),
+ EvalState#eval_state{unpurged = Unpurged};
eval({purge, Modules}, EvalState) ->
% Now, if there are any processes still executing old code, OR
% if some new processes started after suspend but before load,
@@ -469,6 +493,19 @@ start(Procs) ->
%% supervisor module, we should load the new version, and then
%% delete the old. Then we should perform the start changes
%% manually, by adding/deleting children.
+%%
+%% Recent changes to this code cause the upgrade error out and
+%% log the case where a suspended supervisor has which_children
+%% called against it. This retains the behavior of causing a VM
+%% restart to the *old* version of a release but has the
+%% advantage of logging the pid and supervisor that had the
+%% issue.
+%%
+%% A second case where this can occur is if a child spec is
+%% incorrect and get_modules is called against a process that
+%% can't respond to the gen:call. Again an error is logged,
+%% an error returned and a VM restart is issued.
+%%
%% Returns: [{SuperPid, ChildName, ChildPid, Mods}]
%%-----------------------------------------------------------------
%% OTP-3452. For each application the first item contains the pid
@@ -478,49 +515,81 @@ start(Procs) ->
get_supervised_procs() ->
lists:foldl(
fun(Application, Procs) ->
- case application_controller:get_master(Application) of
- Pid when is_pid(Pid) ->
- {Root, _AppMod} = application_master:get_child(Pid),
- case get_supervisor_module(Root) of
- {ok, SupMod} ->
- get_procs(supervisor:which_children(Root),
- Root) ++
- [{undefined, undefined, Root, [SupMod]} |
- Procs];
- {error, _} ->
- error_logger:error_msg("release_handler: "
- "cannot find top "
- "supervisor for "
- "application ~w~n",
- [Application]),
- get_procs(supervisor:which_children(Root),
- Root) ++ Procs
- end;
- _ -> Procs
- end
+ get_master_procs(Application,
+ Procs,
+ application_controller:get_master(Application))
end,
[],
- lists:map(fun({Application, _Name, _Vsn}) ->
- Application
- end,
- application:which_applications())).
+ get_application_names()).
+
+get_supervised_procs(_, Root, Procs, {ok, SupMod}) ->
+ get_procs(maybe_supervisor_which_children(get_proc_state(Root), SupMod, Root), Root) ++
+ [{undefined, undefined, Root, [SupMod]} | Procs];
+get_supervised_procs(Application, Root, Procs, {error, _}) ->
+ error_logger:error_msg("release_handler: cannot find top supervisor for "
+ "application ~w~n", [Application]),
+ get_procs(maybe_supervisor_which_children(get_proc_state(Root), Application, Root), Root) ++ Procs.
+
+get_application_names() ->
+ lists:map(fun({Application, _Name, _Vsn}) ->
+ Application
+ end,
+ application:which_applications()).
+
+get_master_procs(Application, Procs, Pid) when is_pid(Pid) ->
+ {Root, _AppMod} = application_master:get_child(Pid),
+ get_supervised_procs(Application, Root, Procs, get_supervisor_module(Root));
+get_master_procs(_, Procs, _) ->
+ Procs.
get_procs([{Name, Pid, worker, dynamic} | T], Sup) when is_pid(Pid) ->
- Mods = get_dynamic_mods(Pid),
+ Mods = maybe_get_dynamic_mods(Name, Pid),
[{Sup, Name, Pid, Mods} | get_procs(T, Sup)];
get_procs([{Name, Pid, worker, Mods} | T], Sup) when is_pid(Pid), is_list(Mods) ->
[{Sup, Name, Pid, Mods} | get_procs(T, Sup)];
get_procs([{Name, Pid, supervisor, Mods} | T], Sup) when is_pid(Pid) ->
- [{Sup, Name, Pid, Mods} | get_procs(T, Sup)] ++
- get_procs(supervisor:which_children(Pid), Pid);
+ [{Sup, Name, Pid, Mods} | get_procs(T, Sup)] ++
+ get_procs(maybe_supervisor_which_children(get_proc_state(Pid), Name, Pid), Pid);
get_procs([_H | T], Sup) ->
get_procs(T, Sup);
get_procs(_, _Sup) ->
[].
-get_dynamic_mods(Pid) ->
- {ok,Res} = gen:call(Pid, self(), get_modules),
- Res.
+get_proc_state(Proc) ->
+ {status, _, {module, _}, [_, State, _, _, _]} = sys:get_status(Proc),
+ State.
+
+maybe_supervisor_which_children(suspended, Name, Pid) ->
+ error_logger:error_msg("release_handler: a which_children call"
+ " to ~p (~p) was avoided. This supervisor"
+ " is suspended and should likely be upgraded"
+ " differently. Exiting ...~n", [Name, Pid]),
+ error(suspended_supervisor);
+
+maybe_supervisor_which_children(State, Name, Pid) ->
+ case catch supervisor:which_children(Pid) of
+ Res when is_list(Res) ->
+ Res;
+ Other ->
+ error_logger:error_msg("release_handler: ~p~nerror during"
+ " a which_children call to ~p (~p)."
+ " [State: ~p] Exiting ... ~n",
+ [Other, Name, Pid, State]),
+ error(which_children_failed)
+ end.
+
+maybe_get_dynamic_mods(Name, Pid) ->
+ case catch gen:call(Pid, self(), get_modules) of
+ {ok, Res} ->
+ Res;
+ Other ->
+ error_logger:error_msg("release_handler: ~p~nerror during a"
+ " get_modules call to ~p (~p),"
+ " there may be an error in it's"
+ " childspec. Exiting ...~n",
+ [Other, Name, Pid]),
+ error(get_modules_failed)
+ end.
%% XXXX
%% Note: The following is a terrible hack done in order to resolve the
@@ -606,26 +675,20 @@ sync_nodes(Id, Nodes) ->
end,
NNodes).
-add_old_vsn(Mod, Vsns) ->
+add_vsns(Mod, NewBin, Vsns) ->
+ OldVsn = get_current_vsn(Mod),
+ NewVsn = get_vsn(NewBin),
case lists:keysearch(Mod, 1, Vsns) of
- {value, {Mod, undefined, NewVsn}} ->
- OldVsn = get_current_vsn(Mod),
- lists:keyreplace(Mod, 1, Vsns, {Mod, OldVsn, NewVsn});
- {value, {Mod, _OldVsn, _NewVsn}} ->
- Vsns;
+ {value, {Mod, OldVsn0, NewVsn0}} ->
+ lists:keyreplace(Mod, 1, Vsns, {Mod,
+ replace_undefined(OldVsn0,OldVsn),
+ replace_undefined(NewVsn0,NewVsn)});
false ->
- OldVsn = get_current_vsn(Mod),
- [{Mod, OldVsn, undefined} | Vsns]
+ [{Mod, OldVsn, NewVsn} | Vsns]
end.
-add_new_vsn(Mod, Bin, Vsns) ->
- NewVsn = get_vsn(Bin),
- case lists:keysearch(Mod, 1, Vsns) of
- {value, {Mod, OldVsn, undefined}} ->
- lists:keyreplace(Mod, 1, Vsns, {Mod, OldVsn, NewVsn});
- false ->
- [{Mod, undefined, NewVsn} | Vsns]
- end.
+replace_undefined(undefined,Vsn) -> Vsn;
+replace_undefined(Vsn,_) -> Vsn.
%%-----------------------------------------------------------------
%% Func: get_current_vsn/1
@@ -645,7 +708,9 @@ get_current_vsn(Mod) ->
{ok, Bin, _File2} ->
get_vsn(Bin);
error ->
- throw({error, {no_such_file, File}})
+ %% This is the case when a new module is added, there will
+ %% be no current version of it at the time of this call.
+ undefined
end.
%%-----------------------------------------------------------------
diff --git a/lib/sasl/src/sasl.erl b/lib/sasl/src/sasl.erl
index d1babaffff..989f99dc82 100644
--- a/lib/sasl/src/sasl.erl
+++ b/lib/sasl/src/sasl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -81,27 +81,38 @@ get_mf() ->
Dir = get_mf_dir(),
MaxB = get_mf_maxb(),
MaxF = get_mf_maxf(),
- {Dir, MaxB, MaxF}.
+ case {Dir, MaxB, MaxF} of
+ {undefined,undefined,undefined} = R ->
+ R;
+ {undefined,_,_} ->
+ exit({missing_config, {sasl, error_logger_mf_dir}});
+ {_,undefined,_} ->
+ exit({missing_config, {sasl, error_logger_mf_maxbytes}});
+ {_,_,undefined} ->
+ exit({missing_config, {sasl, error_logger_mf_maxfiles}});
+ R ->
+ R
+ end.
get_mf_dir() ->
case application:get_env(sasl, error_logger_mf_dir) of
- {ok, false} -> throw(undefined);
+ {ok, false} -> undefined;
{ok, Dir} when is_list(Dir) -> Dir;
- undefined -> throw(undefined);
+ undefined -> undefined;
{ok, Bad} -> exit({bad_config, {sasl, {error_logger_mf_dir, Bad}}})
end.
get_mf_maxb() ->
case application:get_env(sasl, error_logger_mf_maxbytes) of
{ok, MaxB} when is_integer(MaxB) -> MaxB;
- undefined -> throw(undefined);
+ undefined -> undefined;
{ok, Bad} -> exit({bad_config, {sasl, {error_logger_mf_maxbytes, Bad}}})
end.
get_mf_maxf() ->
case application:get_env(sasl, error_logger_mf_maxfiles) of
{ok, MaxF} when is_integer(MaxF), MaxF > 0, MaxF < 256 -> MaxF;
- undefined -> throw(undefined);
+ undefined -> undefined;
{ok, Bad} -> exit({bad_config, {sasl, {error_logger_mf_maxfiles, Bad}}})
end.
diff --git a/lib/sasl/src/systools_lib.erl b/lib/sasl/src/systools_lib.erl
index b652c109fe..1b6ea125d9 100644
--- a/lib/sasl/src/systools_lib.erl
+++ b/lib/sasl/src/systools_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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([file_term2binary/2, read_term/1, read_term_from_stream/2,
- get_dirs/1, get_path/1]).
+ get_dirs/1, get_path/1, werror/2]).
-include_lib("kernel/include/file.hrl").
@@ -176,21 +176,26 @@ add_dirs(RegName, Dirs, Root) ->
regexp_match(RegName, D0, Root) ->
case file:list_dir(D0) of
{ok, Files} when length(Files) > 0 ->
- FR = fun(F) ->
- case regexp:match(F, RegName) of
- {match,1,N} when N == length(F) ->
- DirF = join(D0, F, Root),
- case dir_p(DirF) of
- true ->
- {true, DirF};
+ case re:compile(RegName) of
+ {ok, MP} ->
+ FR = fun(F) ->
+ case re:run(F, MP) of
+ {match,[{0,N}]} when N == length(F) ->
+ DirF = join(D0, F, Root),
+ case dir_p(DirF) of
+ true ->
+ {true, DirF};
+ _ ->
+ false
+ end;
_ ->
false
- end;
- _ ->
- false
- end
- end,
- {true,lists:zf(FR, Files)};
+ end
+ end,
+ {true,lists:zf(FR, Files)};
+ _ ->
+ false
+ end;
_ ->
false
end.
@@ -214,6 +219,7 @@ flat([H|T], Ack) ->
flat(T, [H|Ack]);
flat([], Ack) ->
lists:reverse(Ack).
-
-
+
+werror(Options, Warnings) ->
+ lists:member(warnings_as_errors, Options) andalso Warnings =/= [].
diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl
index 20a142c763..7f400f5cce 100644
--- a/lib/sasl/src/systools_make.erl
+++ b/lib/sasl/src/systools_make.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -44,13 +44,15 @@
%%-----------------------------------------------------------------
%% Create a boot script from a release file.
-%% Options is a list of {path, Path} | silent | local where path sets
-%% the search path, silent supresses error message printing on console,
-%% local generates a script with references to the directories there
-%% the applications are found.
+%% Options is a list of {path, Path} | silent | local
+%% | warnings_as_errors
+%% where path sets the search path, silent supresses error message
+%% printing on console, local generates a script with references
+%% to the directories there the applications are found,
+%% and warnings_as_errors treats warnings as errors.
%%
%% New options: {path,Path} can contain wildcards
-%% no_module_tests
+%% src_tests
%% {variables,[{Name,AbsString}]}
%% {machine, jam | beam | vee}
%% exref | {exref, [AppName]}
@@ -82,15 +84,19 @@ make_script(RelName, Output, Flags) when is_list(RelName),
Path0 = get_path(Flags),
Path1 = mk_path(Path0), % expand wildcards etc.
Path = make_set(Path1 ++ code:get_path()),
- ModTestP = {not member(no_module_tests, Flags),
- xref_p(Flags)},
+ ModTestP = {member(src_tests, Flags),xref_p(Flags)},
case get_release(RelName, Path, ModTestP, machine(Flags)) of
{ok, Release, Appls, Warnings} ->
- case generate_script(Output,Release,Appls,Flags) of
- ok ->
+ case systools_lib:werror(Flags, Warnings) of
+ true ->
return(ok,Warnings,Flags);
- Error ->
- return(Error,Warnings,Flags)
+ false ->
+ case generate_script(Output,Release,Appls,Flags) of
+ ok ->
+ return(ok,Warnings,Flags);
+ Error ->
+ return(Error,Warnings,Flags)
+ end
end;
Error ->
return(Error,[],Flags)
@@ -131,10 +137,21 @@ get_outdir(Flags) ->
return(ok,Warnings,Flags) ->
case member(silent,Flags) of
true ->
- {ok,?MODULE,Warnings};
+ case systools_lib:werror(Flags, Warnings) of
+ true ->
+ error;
+ false ->
+ {ok,?MODULE,Warnings}
+ end;
_ ->
- io:format("~s",[format_warning(Warnings)]),
- ok
+ case member(warnings_as_errors,Flags) of
+ true ->
+ io:format("~s",[format_warning(Warnings, true)]),
+ error;
+ false ->
+ io:format("~s",[format_warning(Warnings)]),
+ ok
+ end
end;
return({error,Mod,Error},_,Flags) ->
case member(silent,Flags) of
@@ -155,7 +172,7 @@ return({error,Mod,Error},_,Flags) ->
%% should be included in the release package and there it can be found.
%%
%% New options: {path,Path} can contain wildcards
-%% no_module_tests
+%% src_tests
%% exref | {exref, [AppName]}
%% {variables,[{Name,AbsString}]}
%% {machine, jam | beam | vee}
@@ -190,8 +207,7 @@ make_tar(RelName, Flags) when is_list(RelName), is_list(Flags) ->
Path0 = get_path(Flags),
Path1 = mk_path(Path0),
Path = make_set(Path1 ++ code:get_path()),
- ModTestP = {not member(no_module_tests, Flags),
- xref_p(Flags)},
+ ModTestP = {member(src_tests, Flags),xref_p(Flags)},
case get_release(RelName, Path, ModTestP, machine(Flags)) of
{ok, Release, Appls, Warnings} ->
case catch mk_tar(RelName, Release, Appls, Flags, Path1) of
@@ -218,7 +234,7 @@ make_tar(RelName, Flags) ->
%% {ok, #release, [{{Name,Vsn},#application}], Warnings} | {error, What}
get_release(File, Path) ->
- get_release(File, Path, true, false).
+ get_release(File, Path, {false,false}, false).
get_release(File, Path, ModTestP) ->
get_release(File, Path, ModTestP, false).
@@ -771,36 +787,40 @@ get_mod_vsn([]) ->
%% Use the module extension of the running machine as extension for
%% the checked modules.
-check_mods(Modules, Appls, Path, {true, XrefP}, Machine) ->
- Ext = objfile_extension(Machine),
- IncPath = create_include_path(Appls, Path),
- Res = append(map(fun(ModT) ->
- {Mod,_Vsn,App,_,Dir} = ModT,
- case check_mod(Mod,App,Dir,Ext,IncPath) of
- ok ->
- [];
- {error, Error} ->
- [{error,{Error, ModT}}];
- {warning, Warn} ->
- [{warning,{Warn,ModT}}]
- end
- end,
- Modules)),
- Res2 = Res ++ check_xref(Appls, Path, XrefP),
+check_mods(Modules, Appls, Path, {SrcTestP, XrefP}, Machine) ->
+ SrcTestRes = check_src(Modules, Appls, Path, SrcTestP, Machine),
+ XrefRes = check_xref(Appls, Path, XrefP),
+ Res = SrcTestRes ++ XrefRes,
case filter(fun({error, _}) -> true;
(_) -> false
end,
- Res2) of
+ Res) of
[] ->
{ok, filter(fun({warning, _}) -> true;
(_) -> false
end,
- Res2)};
+ Res)};
Errors ->
{error, Errors}
- end;
-check_mods(_, _, _, _, _) ->
- {ok, []}.
+ end.
+
+check_src(Modules, Appls, Path, true, Machine) ->
+ Ext = objfile_extension(Machine),
+ IncPath = create_include_path(Appls, Path),
+ append(map(fun(ModT) ->
+ {Mod,_Vsn,App,_,Dir} = ModT,
+ case check_mod(Mod,App,Dir,Ext,IncPath) of
+ ok ->
+ [];
+ {error, Error} ->
+ [{error,{Error, ModT}}];
+ {warning, Warn} ->
+ [{warning,{Warn,ModT}}]
+ end
+ end,
+ Modules));
+check_src(_, _, _, _, _) ->
+ [].
check_xref(_Appls, _Path, false) ->
[];
@@ -1610,9 +1630,9 @@ var_dir(_Dir, _, _, []) ->
false.
appDir(AppDir) ->
- case reverse(filename:split(AppDir)) of
- ["ebin"|Dir] -> filename:join(reverse(Dir));
- _ -> AppDir
+ case filename:basename(AppDir) of
+ "ebin" -> filename:dirname(AppDir);
+ _ -> AppDir
end.
add_modules(Modules, Tar, AppDir, ToDir, Ext) ->
@@ -1831,74 +1851,89 @@ get_flag(_,_) -> false.
%% Check Options for make_script
check_args_script(Args) ->
cas(Args,
- {undef, undef, undef, undef, undef, undef, undef, undef, []}).
+ {undef, undef, undef, undef, undef, undef, undef, undef,
+ undef, []}).
-cas([], {_Path,_Sil,_Loc,_Test,_Var,_Mach,_Xref,_XrefApps, X}) ->
+cas([], {_Path,_Sil,_Loc,_Test,_Var,_Mach,_Xref,_XrefApps,_Werror, X}) ->
X;
%%% path ---------------------------------------------------------------
-cas([{path, P} | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) when is_list(P) ->
+cas([{path, P} | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) when is_list(P) ->
case check_path(P) of
ok ->
- cas(Args, {P, Sil, Loc, Test, Var, Mach, Xref, XrefApps,X});
+ cas(Args, {P, Sil, Loc, Test, Var, Mach, Xref, XrefApps,
+ Werror, X});
error ->
cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps,
- X++[{path,P}]})
+ Werror, X++[{path,P}]})
end;
%%% silent -------------------------------------------------------------
-cas([silent | Args], {Path, _Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) ->
- cas(Args, {Path, silent, Loc, Test, Var, Mach, Xref, XrefApps, X});
+cas([silent | Args], {Path, _Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) ->
+ cas(Args, {Path, silent, Loc, Test, Var, Mach, Xref, XrefApps,
+ Werror, X});
%%% local --------------------------------------------------------------
-cas([local | Args], {Path, Sil, _Loc, Test, Var, Mach,
- Xref, XrefApps, X}) ->
- cas(Args, {Path, Sil, local, Test, Var, Mach, Xref, XrefApps, X});
-%%% no_module_tests ----------------------------------------------------
-cas([no_module_tests | Args], {Path, Sil, Loc, _Test, Var, Mach,
- Xref, XrefApps, X}) ->
+cas([local | Args], {Path, Sil, _Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) ->
+ cas(Args, {Path, Sil, local, Test, Var, Mach, Xref, XrefApps,
+ Werror, X});
+%%% src_tests -------------------------------------------------------
+cas([src_tests | Args], {Path, Sil, Loc, _Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) ->
cas(Args,
- {Path, Sil, Loc, no_module_tests, Var, Mach, Xref, XrefApps,X});
+ {Path, Sil, Loc, src_tests, Var, Mach, Xref, Werror, XrefApps,X});
%%% variables ----------------------------------------------------------
-cas([{variables, V} | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) when is_list(V) ->
+cas([{variables, V} | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) when is_list(V) ->
case check_vars(V) of
ok ->
cas(Args,
- {Path, Sil, Loc, Test, V, Mach, Xref, XrefApps, X});
+ {Path, Sil, Loc, Test, V, Mach, Xref, XrefApps, Werror, X});
error ->
cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps,
- X++[{variables, V}]})
+ Werror, X++[{variables, V}]})
end;
%%% machine ------------------------------------------------------------
-cas([{machine, M} | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) when is_atom(M) ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, X});
+cas([{machine, M} | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) when is_atom(M) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, Werror, X});
%%% exref --------------------------------------------------------------
-cas([exref | Args], {Path, Sil, Loc, Test, Var, Mach,
- _Xref, XrefApps, X}) ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach, exref, XrefApps, X});
+cas([exref | Args], {Path, Sil, Loc, Test, Var, Mach, _Xref,
+ XrefApps, Werror, X}) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, exref, XrefApps, Werror, X});
%%% exref Apps ---------------------------------------------------------
-cas([{exref, Apps} | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) when is_list(Apps) ->
+cas([{exref, Apps} | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) when is_list(Apps) ->
case check_apps(Apps) of
ok ->
cas(Args, {Path, Sil, Loc, Test, Var, Mach,
- Xref, Apps, X});
+ Xref, Apps, Werror, X});
error ->
cas(Args, {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X++[{exref, Apps}]})
+ Xref, XrefApps, Werror, X++[{exref, Apps}]})
end;
%%% outdir Dir ---------------------------------------------------------
-cas([{outdir, Dir} | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) when is_list(Dir) ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, X});
+cas([{outdir, Dir} | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) when is_list(Dir) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, Werror, X});
%%% otp_build (secret, not documented) ---------------------------------
-cas([otp_build | Args], {Path, Sil, Loc, Test, Var, Mach,
- Xref, XrefApps, X}) ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, X});
+cas([otp_build | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, Werror, X});
+%%% no_module_tests (kept for backwards compatibility, but ignored) ----
+cas([no_module_tests | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, Werror, X}) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, Werror, X});
+%%% warnings_as_errors (kept for backwards compatibility, but ignored) ----
+cas([warnings_as_errors | Args], {Path, Sil, Loc, Test, Var, Mach, Xref,
+ XrefApps, _Werror, X}) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps,
+ warnings_as_errors, X});
%%% ERROR --------------------------------------------------------------
-cas([Y | Args], {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, X}) ->
- cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps,X++[Y]}).
+cas([Y | Args], {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps,
+ Werror, X}) ->
+ cas(Args, {Path, Sil, Loc, Test, Var, Mach, Xref, XrefApps, Werror,
+ X++[Y]}).
@@ -1935,10 +1970,10 @@ cat([{dirs, D} | Args], {Path, Sil, Dirs, Erts, Test,
cat([{erts, E} | Args], {Path, Sil, Dirs, _Erts, Test,
Var, VarTar, Mach, Xref, XrefApps, X}) when is_list(E)->
cat(Args, {Path, Sil, Dirs, E, Test, Var, VarTar, Mach, Xref, XrefApps, X});
-%%% no_module_tests ----------------------------------------------------
-cat([no_module_tests | Args], {Path, Sil, Dirs, Erts, _Test, Var, VarTar, Mach, Xref, XrefApps, X}) ->
- cat(Args, {Path, Sil, Dirs, Erts, no_module_tests, Var, VarTar, Mach,
- Xref, XrefApps, X});
+%%% src_tests ----------------------------------------------------
+cat([src_tests | Args], {Path, Sil, Dirs, Erts, _Test, Var, VarTar, Mach, Xref, XrefApps, X}) ->
+ cat(Args, {Path, Sil, Dirs, Erts, src_tests, Var, VarTar, Mach,
+ Xref, XrefApps, X});
%%% variables ----------------------------------------------------------
cat([{variables, V} | Args], {Path, Sil, Dirs, Erts, Test, Var, VarTar, Mach, Xref, XrefApps, X}) when is_list(V) ->
case check_vars(V) of
@@ -1982,6 +2017,9 @@ cat([{outdir, Dir} | Args], {Path, Sil, Dirs, Erts, Test, Var, VarTar, Mach, Xre
%%% otp_build (secret, not documented) ---------------------------------
cat([otp_build | Args], {Path, Sil, Dirs, Erts, Test, Var, VarTar, Mach, Xref, XrefApps, X}) ->
cat(Args, {Path, Sil, Dirs, Erts, Test, Var, VarTar, Mach, Xref, XrefApps, X});
+%%% no_module_tests (kept for backwards compatibility, but ignored) ----
+cat([no_module_tests | Args], {Path, Sil, Dirs, Erts, Test, Var, VarTar, Mach, Xref, XrefApps, X}) ->
+ cat(Args, {Path, Sil, Dirs, Erts, Test, Var, VarTar, Mach, Xref, XrefApps, X});
%%% ERROR --------------------------------------------------------------
cat([Y | Args], {Path, Sil, Dirs, Erts, Test, Var, VarTar, Mach, Xref, XrefApps, X}) ->
cat(Args, {Path, Sil, Dirs, Erts, Test, Var, VarTar, Mach, Xref, XrefApps, X++[Y]}).
@@ -2021,7 +2059,6 @@ check_apps([H|T]) when is_atom(H) ->
check_apps(_) ->
error.
-
%% Format error
format_error(badly_formatted_release) ->
@@ -2135,21 +2172,31 @@ form_tar_err({add, File, Error}) ->
%% Format warning
format_warning(Warnings) ->
- map(fun({warning,W}) -> form_warn(W) end, Warnings).
-
-form_warn({source_not_found,{Mod,_,App,_,_}}) ->
- io_lib:format("*WARNING* ~p: Source code not found: ~p.erl~n",
- [App,Mod]);
-form_warn({{parse_error, File},{_,_,App,_,_}}) ->
- io_lib:format("*WARNING* ~p: Parse error: ~p~n",
- [App,File]);
-form_warn({obj_out_of_date,{Mod,_,App,_,_}}) ->
- io_lib:format("*WARNING* ~p: Object code (~p) out of date~n",[App,Mod]);
-form_warn({exref_undef, Undef}) ->
- F = fun({M,F,A}) ->
- io_lib:format("*WARNING* Undefined function ~p:~p/~p~n",
- [M,F,A])
+ format_warning(Warnings, false).
+
+format_warning(Warnings, Werror) ->
+ Prefix = case Werror of
+ true ->
+ "";
+ false ->
+ "*WARNING* "
+ end,
+ map(fun({warning,W}) -> form_warn(Prefix, W) end, Warnings).
+
+form_warn(Prefix, {source_not_found,{Mod,_,App,_,_}}) ->
+ io_lib:format("~s~p: Source code not found: ~p.erl~n",
+ [Prefix,App,Mod]);
+form_warn(Prefix, {{parse_error, File},{_,_,App,_,_}}) ->
+ io_lib:format("~s~p: Parse error: ~p~n",
+ [Prefix,App,File]);
+form_warn(Prefix, {obj_out_of_date,{Mod,_,App,_,_}}) ->
+ io_lib:format("~s~p: Object code (~p) out of date~n",
+ [Prefix,App,Mod]);
+form_warn(Prefix, {exref_undef, Undef}) ->
+ F = fun({M,F,A}) ->
+ io_lib:format("~sUndefined function ~p:~p/~p~n",
+ [Prefix,M,F,A])
end,
map(F, Undef);
-form_warn(What) ->
- io_lib:format("*WARNING* ~p~n", [What]).
+form_warn(Prefix, What) ->
+ io_lib:format("~s ~p~n", [Prefix,What]).
diff --git a/lib/sasl/src/systools_relup.erl b/lib/sasl/src/systools_relup.erl
index 6b0f77703e..6d9e922900 100644
--- a/lib/sasl/src/systools_relup.erl
+++ b/lib/sasl/src/systools_relup.erl
@@ -122,7 +122,7 @@
%% rel_filename() = description() = string()
%% Opts = [opt()]
%% opt() = {path, [path()]} | silent | noexec | restart_emulator
-%% | {outdir, string()}
+%% | {outdir, string()} | warnings_as_errors
%% path() = [string()]
%% Ret = ok | error | {ok, Relup, Module, Warnings} | {error, Module, Error}
%%
@@ -139,8 +139,9 @@
%%
%% The option `path' sets search path, `silent' suppresses printing of
%% error messages to the console, `noexec' inhibits the creation of
-%% the output "relup" file, and restart_emulator ensures that the new
-%% emulator is restarted (as the final step).
+%% the output "relup" file, restart_emulator ensures that the new
+%% emulator is restarted (as the final step), and `warnings_as_errors'
+%% treats warnings as errors.
%% ----------------------------------------------------------------
mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs) ->
mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs, []).
@@ -153,14 +154,29 @@ mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs, Opts) ->
{false, false} ->
case R of
{ok, _Res, _Mod, Ws} ->
- print_warnings(Ws),
- ok;
+ print_warnings(Ws, Opts),
+ case systools_lib:werror(Opts, Ws) of
+ true ->
+ error;
+ false ->
+ ok
+ end;
Other ->
print_error(Other),
error
end;
- _ ->
- R
+ _ ->
+ case R of
+ {ok, _Res, _Mod, Ws} ->
+ case systools_lib:werror(Opts, Ws) of
+ true ->
+ error;
+ false ->
+ R
+ end;
+ R ->
+ R
+ end
end;
BadArg ->
erlang:error({badarg, BadArg})
@@ -179,8 +195,7 @@ check_opts([]) ->
[].
do_mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs, Path, Opts) ->
- ModTest = false,
- case systools_make:get_release(to_list(TopRelFile), Path, ModTest) of
+ case systools_make:get_release(to_list(TopRelFile), Path) of
%%
%% TopRel = #release
%% NameVsnApps = [{{Name, Vsn}, #application}]
@@ -196,7 +211,12 @@ do_mk_relup(TopRelFile, BaseUpRelDcs, BaseDnRelDcs, Path, Opts) ->
{Dn, Ws2} = foreach_baserel_dn(TopRel, TopApps, BaseDnRelDcs,
Path, Opts, Ws1),
Relup = {TopRel#release.vsn, Up, Dn},
- write_relup_file(Relup, Opts),
+ case systools_lib:werror(Opts, Ws2) of
+ true ->
+ ok;
+ false ->
+ write_relup_file(Relup, Opts)
+ end,
{ok, Relup, ?MODULE, Ws2};
Other ->
throw(Other)
@@ -246,9 +266,8 @@ foreach_baserel_up(TopRel, TopApps, [BaseRelDc|BaseRelDcs], Path, Opts,
{RUs4, Ws4} =
check_for_emulator_restart(TopRel, BaseRel, RUs3, Ws3, Opts),
- ModTest = false,
BaseApps =
- case systools_make:get_release(BaseRelFile, Path, ModTest) of
+ case systools_make:get_release(BaseRelFile, Path) of
{ok, _, NameVsnApps, _Warns} ->
lists:map(fun({_,App}) -> App end, NameVsnApps);
Other1 ->
@@ -283,9 +302,8 @@ foreach_baserel_dn(TopRel, TopApps, [BaseRelDc|BaseRelDcs], Path, Opts,
%%
{RUs1, Ws1} = collect_appup_scripts(dn, TopApps, BaseRel, Ws, []),
- ModTest = false,
{BaseApps, Ws2} =
- case systools_make:get_release(BaseRelFile, Path, ModTest) of
+ case systools_make:get_release(BaseRelFile, Path) of
%%
%% NameVsnApps = [{{Name, Vsn}, #application}]
{ok, _, NameVsnApps, Warns} ->
@@ -530,20 +548,29 @@ format_error(Error) ->
io:format("~p~n", [Error]).
-print_warnings(Ws) when is_list(Ws) ->
- lists:foreach(fun(W) -> print_warning(W) end, Ws);
-print_warnings(W) ->
- print_warning(W).
+print_warnings(Ws, Opts) when is_list(Ws) ->
+ lists:foreach(fun(W) -> print_warning(W, Opts) end, Ws);
+print_warnings(W, Opts) ->
+ print_warning(W, Opts).
-print_warning(W) ->
- S = format_warning(W),
+print_warning(W, Opts) ->
+ Prefix = case lists:member(warnings_as_errors, Opts) of
+ true ->
+ "";
+ false ->
+ "*WARNING* "
+ end,
+ S = format_warning(Prefix, W),
io:format("~s", [S]).
-format_warning({erts_vsn_changed, {Rel1, Rel2}}) ->
- io_lib:format("*WARNING* The ERTS version changed between ~p and ~p~n",
- [Rel1, Rel2]);
-format_warning(What) ->
- io_lib:format("*WARNING* ~p~n",[What]).
+format_warning(W) ->
+ format_warning("*WARNING* ", W).
+
+format_warning(Prefix, {erts_vsn_changed, {Rel1, Rel2}}) ->
+ io_lib:format("~sThe ERTS version changed between ~p and ~p~n",
+ [Prefix, Rel1, Rel2]);
+format_warning(Prefix, What) ->
+ io_lib:format("~s~p~n",[Prefix, What]).
get_reason({error, {open, _, _}}) -> open;
diff --git a/lib/sasl/test/.gitignore b/lib/sasl/test/.gitignore
new file mode 100644
index 0000000000..76e706b874
--- /dev/null
+++ b/lib/sasl/test/.gitignore
@@ -0,0 +1,5 @@
+#
+# Don't ignore *.beam files in any sub-directory.
+#
+
+!*.beam
diff --git a/lib/sasl/test/Makefile b/lib/sasl/test/Makefile
new file mode 100644
index 0000000000..65be134462
--- /dev/null
+++ b/lib/sasl/test/Makefile
@@ -0,0 +1,92 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, 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= \
+ sasl_SUITE \
+ alarm_handler_SUITE \
+ installer \
+ release_handler_SUITE \
+ systools_SUITE \
+ systools_rc_SUITE \
+ overload_SUITE \
+ rb_SUITE \
+ rh_test_lib
+
+ERL_FILES= $(MODULES:%=%.erl)
+
+TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+INSTALL_PROGS= $(TARGET_FILES)
+
+EMAKEFILE=Emakefile
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/sasl_test
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ERL_MAKE_FLAGS +=
+ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include \
+ -I$(ERL_TOP)/lib/sasl/src
+
+EBIN = .
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+make_emakefile:
+ $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) '*_SUITE_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) $(ERL_FILES) $(RELSYSDIR)
+ $(INSTALL_DATA) sasl.spec sasl.cover $(EMAKEFILE) $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
+ @tar cfh - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+
+release_docs_spec:
diff --git a/lib/sasl/test/alarm_handler_SUITE.erl b/lib/sasl/test/alarm_handler_SUITE.erl
new file mode 100644
index 0000000000..a98e8c9c67
--- /dev/null
+++ b/lib/sasl/test/alarm_handler_SUITE.erl
@@ -0,0 +1,179 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(alarm_handler_SUITE).
+
+-include_lib("test_server/include/test_server.hrl").
+
+%%-----------------------------------------------------------------
+%% We will add an own alarm handler in order to verify that the
+%% alarm_handler deliver the expected events.
+%%-----------------------------------------------------------------
+
+-export([init_per_suite/1, end_per_suite/1, all/0,groups/0,
+ init_per_group/2,end_per_group/2,
+ set_alarm/1, clear_alarm/1, swap/1]).
+
+-export([init/1, handle_event/2, handle_call/2, handle_info/2,
+ terminate/2]).
+
+
+init_per_suite(Config) ->
+ application:start(sasl),
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+all() ->
+ [set_alarm, clear_alarm, swap].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+
+%%-----------------------------------------------------------------
+
+set_alarm(suite) -> [];
+set_alarm(Config) when is_list(Config) ->
+ ?line gen_event:add_handler(alarm_handler, ?MODULE, self()),
+ Alarm1 = {alarm1, "this is the alarm"},
+ Alarm2 = {"alarm2", this_is_the_alarm},
+ Alarm3 = {{alarm3}, {this_is,"the_alarm"}},
+ ?line ok = alarm_handler:set_alarm(Alarm1),
+ reported(set_alarm, Alarm1),
+ ?line ok = alarm_handler:set_alarm(Alarm2),
+ reported(set_alarm, Alarm2),
+ ?line ok = alarm_handler:set_alarm(Alarm3),
+ reported(set_alarm, Alarm3),
+
+ ?line [Alarm3,Alarm2,Alarm1] = alarm_handler:get_alarms(),
+ alarm_handler:clear_alarm(alarm1),
+ alarm_handler:clear_alarm("alarm2"),
+ alarm_handler:clear_alarm({alarm3}),
+ ?line [] = alarm_handler:get_alarms(),
+
+ test_server:messages_get(),
+ ?line my_yes = gen_event:delete_handler(alarm_handler, ?MODULE, []),
+ ok.
+
+%%-----------------------------------------------------------------
+
+clear_alarm(suite) -> [];
+clear_alarm(Config) when is_list(Config) ->
+ ?line gen_event:add_handler(alarm_handler, ?MODULE, self()),
+ Alarm1 = {alarm1, "this is the alarm"},
+ Alarm2 = {"alarm2", this_is_the_alarm},
+ Alarm3 = {{alarm3}, {this_is,"the_alarm"}},
+ alarm_handler:set_alarm(Alarm1),
+ alarm_handler:set_alarm(Alarm2),
+ alarm_handler:set_alarm(Alarm3),
+ test_server:messages_get(),
+
+ ?line ok = alarm_handler:clear_alarm(alarm1),
+ reported(clear_alarm, alarm1),
+ ?line ok = alarm_handler:clear_alarm("alarm2"),
+ reported(clear_alarm, "alarm2"),
+ ?line ok = alarm_handler:clear_alarm({alarm3}),
+ reported(clear_alarm, {alarm3}),
+ ?line [] = alarm_handler:get_alarms(),
+
+ ?line my_yes = gen_event:delete_handler(alarm_handler, ?MODULE, []),
+ ok.
+
+%%-----------------------------------------------------------------
+
+swap(suite) -> [];
+swap(Config) when is_list(Config) ->
+ ?line Alarm1 = {alarm1, "this is the alarm"},
+ ?line Alarm2 = {"alarm2", this_is_the_alarm},
+ ?line Alarm3 = {{alarm3}, {this_is,"the_alarm"}},
+ ?line alarm_handler:set_alarm(Alarm1),
+ ?line alarm_handler:set_alarm(Alarm2),
+ ?line alarm_handler:set_alarm(Alarm3),
+
+ ?line foo,
+ case gen_event:which_handlers(alarm_handler) of
+ [alarm_handler] ->
+ ?line ok = gen_event:swap_handler(alarm_handler,
+ {alarm_handler, swap},
+ {?MODULE, self()}),
+ ?line [?MODULE] = gen_event:which_handlers(alarm_handler),
+ Alarms = [Alarm3, Alarm2, Alarm1],
+ reported(swap_alarms, Alarms),
+
+ %% get_alarms is only valid with the default handler installed.
+ ?line {error, _} = alarm_handler:get_alarms(),
+
+ ?line my_yes = gen_event:delete_handler(alarm_handler,
+ ?MODULE, []),
+ ?line gen_event:add_handler(alarm_handler, alarm_handler, []),
+ ok;
+ _ ->
+ alarm_handler:clear_alarm(alarm1),
+ alarm_handler:clear_alarm("alarm2"),
+ alarm_handler:clear_alarm({alarm3}),
+ ok
+ end.
+
+%%-----------------------------------------------------------------
+%% Check that the alarm has been received.
+%%-----------------------------------------------------------------
+reported(Tag, Data) ->
+ receive
+ {Tag, Data} ->
+ test_server:messages_get(),
+ ok
+ after 1000 ->
+ test_server:fail(no_alarm_received)
+ end.
+
+%%-----------------------------------------------------------------
+%% The error_logger handler (gen_event behaviour).
+%% Sends a notification to the Tester process about the events
+%% generated by the Tester process.
+%%-----------------------------------------------------------------
+init(Tester) when is_pid(Tester) ->
+ {ok, Tester};
+init({Tester, {alarm_handler,Alarms}}) -> % Swap from default handler.
+ Tester ! {swap_alarms, Alarms},
+ {ok, Tester}.
+
+handle_event({set_alarm, Alarm}, Tester) ->
+ Tester ! {set_alarm, Alarm},
+ {ok, Tester};
+handle_event({clear_alarm, AlarmId}, Tester) ->
+ Tester ! {clear_alarm, AlarmId},
+ {ok, Tester};
+handle_event(_Event, Tester) ->
+ {ok, Tester}.
+
+handle_info(_, Tester) ->
+ {ok, Tester}.
+
+handle_call(_Query, Tester) -> {ok, {error, bad_query}, Tester}.
+
+terminate(_Reason, _Tester) ->
+ my_yes.
diff --git a/lib/sasl/test/installer.erl b/lib/sasl/test/installer.erl
new file mode 100644
index 0000000000..f5ceab0dc4
--- /dev/null
+++ b/lib/sasl/test/installer.erl
@@ -0,0 +1,816 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(installer).
+
+%%-compile(export_all).
+-export([install_1/2]).
+-export([install_2/1]).
+-export([install_3/2]).
+-export([install_3a/1]).
+-export([install_4/1]).
+-export([install_5/1]).
+-export([install_5a/1]).
+-export([install_6/1]).
+-export([install_7/1]).
+-export([install_8/1]).
+-export([install_9/1]).
+-export([install_10/1]).
+-export([install_11/1]).
+-export([client1_1/4]).
+-export([client2/3]).
+-export([stop/1]).
+-export([unpack_p1h/2]).
+-export([permanent_p1h/1]).
+-export([reg_proc/1]).
+-export([registered_loop/1]).
+
+-define(print(List), {rh_print, TestNode} ! {print, {?MODULE, ?LINE}, List}).
+-define(print_line(Line,List), {rh_print, TestNode} ! {print, {?MODULE, Line}, List}).
+-define(fail(Term), exit({?MODULE, ?LINE, Term})).
+-define(fail_line(Line,Term), exit({?MODULE, Line, Term})).
+
+-define(check_release(Vsn,Status,Apps),
+ check_release(TestNode,node(),Vsn,Status,Apps,?LINE)).
+-define(check_release_client(Node,Vsn,Status,Apps),
+ check_release(TestNode,Node,Vsn,Status,Apps,?LINE)).
+
+-define(check_running_app(App,Vsn),
+ check_running_app(TestNode,node(),App,Vsn,?LINE)).
+-define(check_running_app_client(Node,App,Vsn),
+ check_running_app(TestNode,Node,App,Vsn,?LINE)).
+
+
+install_1(TestNode,PrivDir) ->
+ ?print([TestNode]),
+ ?print(["install_1 start"]),
+
+ % Unpack and install P1H
+ {ok, "P1H"} = unpack_release(PrivDir,"rel1"),
+ ?print(["unpack_release P1H ok"]),
+ ?check_release("P1H",unpacked,["a-1.0"]),
+ {ok,"P1G",[new_appl]} = release_handler:install_release("P1H"),
+ ?print(["install_release P1H ok"]),
+ ?check_release("P1H",current,["a-1.0"]),
+ ?check_running_app(a,"1.0"),
+ X = a:a(),
+ ?print(["X", X]),
+ {key2, val2} = lists:keyfind(key2, 1, X),
+ {key1, val1} = lists:keyfind(key1, 1, X),
+ ?print(["install_1 end OK"]),
+ ok.
+ % release_handler_SUITE will reboot this node now!
+
+install_2(TestNode) ->
+ ?print(["install_2 start"]),
+
+ % Check that P1H is still unpacked, install it and make_permanent
+ ?check_release("P1H",unpacked,["a-1.0"]),
+ ?print(["install_2 P1H unpacked"]),
+ {ok,"P1G",[new_appl]} = release_handler:install_release("P1H"),
+ ?print(["install_2 install_release ok"]),
+ ?check_release("P1H",current,["a-1.0"]),
+ ?check_running_app(a,"1.0"),
+ ok = release_handler:make_permanent("P1H").
+ % release_handler_SUITE will reboot this node now!
+
+install_3(TestNode,PrivDir) ->
+ ?print(["install_3 start"]),
+
+ % Check that P1H is permanent
+ ?check_release("P1H",permanent,["a-1.0"]),
+ X = a:a(),
+ {key2, val2} = lists:keyfind(key2, 1, X),
+ {key1, val1} = lists:keyfind(key1, 1, X),
+
+ % Unpack and install P1I
+ {ok, "P1I"} = unpack_release(PrivDir,"rel2"),
+ ?print(["install_3 unpack_release P1I ok"]),
+ ?check_release("P1I",unpacked,["a-1.1"]),
+ {ok,"P1H",[{extra, gott}]} = release_handler:check_install_release("P1I"),
+ {error,_} = release_handler:check_install_release("P1J"),
+ {ok,"P1H",[{extra, gott}]} = release_handler:install_release("P1I"),
+ ?print(["install_3 install_release P1I ok"]),
+ ?check_release("P1I",current,["a-1.1"]),
+ ?check_running_app(a,"1.1"),
+ X2 = a:a(),
+ {key2, newval2} = lists:keyfind(key2, 1, X2),
+ {key1, val1} = lists:keyfind(key1, 1, X2),
+ {ok, bval} = a:b(),
+
+ % Unpack and install P2A
+ {ok, "P2A"} = unpack_release(PrivDir,"rel3"),
+ ?print(["install_3 unpack_release P2A ok"]),
+ ?check_release("P2A",unpacked,["a-1.1"]),
+ {ok, "P1I", [new_emu]} = release_handler:check_install_release("P2A"),
+ ?print(["install_3 check_install_release P2A ok"]),
+ ok = release_handler:make_permanent("P1I"),
+ ?print(["install_3 make_permanent P1I ok"]),
+ ?check_release("P1I",permanent,["a-1.1"]),
+ ok.
+
+install_3a(TestNode) ->
+ {ok, "P1I", [new_emu]} = release_handler:install_release("P2A"),
+ %% Node is rebooted by the release_handler:install_release
+ %% (init:reboot) because P2A includes a new erts vsn and the relup
+ %% file contains a 'restart_new_emulator' instruction.
+ ?print(["install_3 P2A installed"]),
+ ok.
+
+
+
+install_4(TestNode) ->
+ ?print(["install_4 start"]),
+
+ % Check that P2A is in use.
+ ?check_release("P2A",current,["a-1.1"]),
+ ?check_running_app(a,"1.1"),
+ X = a:a(),
+ {key2, newval2} = lists:keyfind(key2, 1, X),
+ {key1, val1} = lists:keyfind(key1, 1, X),
+ {ok, bval} = a:b(),
+ ok.
+ % release_handler_SUITE will reboot this node now!
+
+install_5(TestNode) ->
+ ?print(["install_5 start"]),
+
+ % Check that P1I is used
+ {ok, "P1I", [new_emu]} = release_handler:check_install_release("P2A"),
+ ok.
+
+install_5a(TestNode) ->
+ % Install P2A again
+ {ok, "P1I", [new_emu]} = release_handler:install_release("P2A"),
+ %% Node is rebooted by the release_handler:install_release
+ %% (init:reboot) because P2A includes a new erts vsn and the relup
+ %% file contains a 'restart_new_emulator' instruction.
+ ?print(["install_5 P2A installed"]),
+ ok.
+
+install_6(TestNode) ->
+ ?print(["install_6 start"]),
+
+ % Check that P2A is used
+ ?check_release("P2A",current,["a-1.1"]),
+ ?check_running_app(a,"1.1"),
+ X = a:a(),
+ {key2, newval2} = lists:keyfind(key2, 1, X),
+ {key1, val1} = lists:keyfind(key1, 1, X),
+ {ok, bval} = a:b(),
+ ok = release_handler:make_permanent("P2A").
+ % release_handler_SUITE will reboot this node now!
+
+
+install_7(TestNode) ->
+ ?print(["install_7 start"]),
+
+ % Check that P2A is used
+ ?check_release("P2A",permanent,["a-1.1"]),
+
+ % Install old P1H
+ ok = release_handler:reboot_old_release("P1H"),
+ ok.
+
+install_8(TestNode) ->
+ ?print(["install_8 start"]),
+
+ % Check that P1H is permanent
+ ?check_release("P1H",permanent,["a-1.0"]),
+ X = a:a(),
+ {key2, val2} = lists:keyfind(key2, 1, X),
+ {key1, val1} = lists:keyfind(key1, 1, X),
+
+ %% Remove P1I and P2A and check that a-1.1 and erts-<latest> are removed
+ ok = release_handler:remove_release("P2A"),
+ ok = release_handler:remove_release("P1I"),
+ {ok, Libs} = file:list_dir(code:lib_dir()),
+ {_,_,StdlibVsn} = lists:keyfind(stdlib,1,application:which_applications()),
+ true = lists:member("stdlib-"++StdlibVsn, Libs),
+ true = lists:member("a-1.0", Libs),
+ false = lists:member("a-1.1", Libs),
+ {ok, Dirs} = file:list_dir(code:root_dir()),
+ ["erts-4.4"] = lists:filter(fun(Dir) -> lists:prefix("erts-",Dir) end, Dirs),
+ ok.
+ % release_handler_SUITE will reboot this node now!
+
+install_9(TestNode) ->
+ ?print(["install_9 start"]),
+
+ % Check that P1H is permanent
+ ?check_release("P1H",permanent,["a-1.0"]),
+ X = a:a(),
+ {key2, val2} = lists:keyfind(key2, 1, X),
+ {key1, val1} = lists:keyfind(key1, 1, X),
+
+ % Install old P1G
+ ok = release_handler:reboot_old_release("P1G"),
+ ok.
+
+install_10(TestNode) ->
+ ?print(["install_10 start"]),
+
+ % Check that P1G is permanent
+ ?check_release("P1G",permanent,[]),
+ ?check_release("P1H",old,["a-1.0"]),
+
+ %% Remove P1H and check that both versions of application a is removed
+ ok = release_handler:remove_release("P1H"),
+ {ok, Libs} = file:list_dir(code:lib_dir()),
+ {_,_,StdlibVsn} = lists:keyfind(stdlib,1,application:which_applications()),
+ true = lists:member("stdlib-"++StdlibVsn, Libs),
+ false = lists:member("a-1.0", Libs),
+ false = lists:member("a-1.1", Libs),
+ ok.
+ % release_handler_SUITE will reboot this node now!
+
+install_11(TestNode) ->
+ ?print(["install_11 start"]),
+
+ % Check that P1G is permanent
+ ?check_release("P1G",permanent,[]),
+ ok.
+
+
+
+%%-----------------------------------------------------------------
+%% This test starts a client node which uses this node as master
+%% for the release_handler.
+%% The client node runs all tests as in installer/1 test case.
+%% Thus, the client node will be rebooted several times.
+%% The to_erl /tmp/NODENAME@HOSTNAME/ command can be used to connect
+%% to the client node.
+%% run_erl logs for the client can be found in the directory:
+%% code:root_dir() ++ "/clients/type1/NODENAME@HOSTNAME/log
+%%-----------------------------------------------------------------
+
+
+client1_1(TestNode,PrivDir,MasterDir,ClientSname) ->
+ TestHost = test_host(),
+ ?print(["client1_1 start"]),
+
+ {ok,IP} = inet:getaddr(TestHost,inet),
+ erl_boot_server:start([IP]),
+
+ ok = net_kernel:monitor_nodes(true),
+ Node = start_client(TestNode,client1,ClientSname),
+ trace_disallowed_calls(Node),
+
+ %% Check env var for SASL on client node
+ SaslEnv = rpc:call(Node, application, get_all_env, [sasl]),
+ ?print([{client1_1,sasl_env},SaslEnv]),
+ {_,CliDir} = lists:keyfind(client_directory,1,SaslEnv),
+ {_,[Master]} = lists:keyfind(masters,1,SaslEnv),
+ {_,StartCli} = lists:keyfind(start_prg,1,SaslEnv),
+ NodeStr = atom_to_list(Node),
+ [NodeStr,"type1","clients"|_] = lists:reverse(filename:split(CliDir)),
+ true = (Master =:= node()),
+ case os:type() of
+ {unix,_} ->
+ true = (StartCli =:= filename:join([CliDir,"bin","start"]));
+ _ ->
+ ok
+ end,
+
+ %% Unpack P1H on master
+ {ok, "P1H"} = unpack_release(PrivDir,"rel1"),
+
+ %% Unpack and install P1H on client
+ Root = code:root_dir(),
+ P1HDir = filename:join([Root, "releases", "P1H"]),
+
+ %% The AppDirs argument (last arg to set_unpacked) below is really
+ %% not necessary, it could just be [] since the path is the same
+ %% as default. But it is given here in order to force hitting the
+ %% release_handler:check_path function so it can be checked that
+ %% it does not use file:read_file_info on the client node, see
+ %% trace_disallowed_calls/1 and check_disallowed_calls/0 below.
+ %% (OTP-9142)
+ {ok, "P1H"} = rpc:call(Node, release_handler, set_unpacked,
+ [filename:join(P1HDir, "rel1.rel"),
+ [{a,"1.0",filename:join(MasterDir,lib)}]]),
+
+ ?check_release_client(Node,"P1H",unpacked,["a-1.0"]),
+
+ ok = rpc:call(Node, release_handler, install_file,
+ ["P1H", filename:join(P1HDir, "start.boot")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ ["P1H", filename:join(P1HDir, "sys.config")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ ["P1H", filename:join(P1HDir, "relup")]),
+ ?print([{release_handler_state, Node},
+ rpc:call(Node, sys, get_status, [release_handler])]),
+
+ {ok,"P1G",[new_appl]} =
+ rpc:call(Node, release_handler, check_install_release, ["P1H"]),
+
+ {ok,"P1G",[new_appl]} =
+ rpc:call(Node, release_handler, install_release, ["P1H"]),
+
+ Apps = rpc:call(Node, application, which_applications, []),
+ {a,"A CXC 138 11","1.0"} = lists:keyfind(a, 1, Apps),
+ X = rpc:call(Node, a, a, []),
+ {key2, val2} = lists:keyfind(key2, 1, X),
+ {key1, val1} = lists:keyfind(key1, 1, X),
+
+ check_disallowed_calls(),
+ reboot(TestNode,Node),
+ trace_disallowed_calls(Node),
+
+ client1_2(TestNode,PrivDir,Node).
+
+client1_2(TestNode,PrivDir,Node) ->
+ ?print(["client1_2 start"]),
+
+ %% Check that P1H is still unpacked, install it and make_permanent
+ ?check_release_client(Node,"P1H",unpacked,["a-1.0"]),
+
+ {ok,"P1G",[new_appl]} =
+ rpc:call(Node, release_handler, install_release, ["P1H"]),
+ ?check_release_client(Node,"P1H",current,["a-1.0"]),
+ ?check_running_app_client(Node,a,"1.0"),
+
+ ok = rpc:call(Node, release_handler, make_permanent, ["P1H"]),
+ ?check_release_client(Node,"P1H",permanent,["a-1.0"]),
+
+ check_disallowed_calls(),
+ reboot(TestNode,Node),
+ trace_disallowed_calls(Node),
+
+ client1_3(TestNode,PrivDir,Node).
+
+client1_3(TestNode,PrivDir,Node) ->
+ ?print(["client1_3 start"]),
+
+ %% Check that P1H is permanent
+ ?check_release_client(Node,"P1H",permanent,["a-1.0"]),
+ X = rpc:call(Node, a, a, []),
+ {key2, val2} = lists:keyfind(key2, 1, X),
+ {key1, val1} = lists:keyfind(key1, 1, X),
+
+ %% Unpack P1I on master
+ {ok, "P1I"} = unpack_release(PrivDir,"rel2"),
+
+ MasterRoot = code:root_dir(),
+
+ %% Unpack and install P1I on client
+ P1IDir = filename:join([MasterRoot, "releases", "P1I"]),
+ {ok, "P1I"} = rpc:call(Node, release_handler, set_unpacked,
+ [filename:join(P1IDir, "rel2.rel"),[]]),
+
+ ?check_release_client(Node,"P1I",unpacked,["a-1.1"]),
+
+ ok = rpc:call(Node, release_handler, install_file,
+ ["P1I", filename:join(P1IDir, "start.boot")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ ["P1I", filename:join(P1IDir, "sys.config")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ ["P1I", filename:join(P1IDir, "relup")]),
+
+ {ok,"P1H",[{extra, gott}]} =
+ rpc:call(Node, release_handler, check_install_release, ["P1I"]),
+ {error,_} = rpc:call(Node, release_handler, check_install_release, ["P1J"]),
+ {ok,"P1H",[{extra, gott}]} =
+ rpc:call(Node, release_handler, install_release, ["P1I"]),
+
+ ?check_running_app_client(Node,a,"1.1"),
+ X2 = rpc:call(Node, a, a, []),
+ {key2, newval2} = lists:keyfind(key2, 1, X2),
+ {key1, val1} = lists:keyfind(key1, 1, X2),
+ {ok, bval} = rpc:call(Node, a, b, []),
+
+ %% Unpack P2A on master
+ {ok, "P2A"} = unpack_release(PrivDir,"rel3"),
+
+ %% Unpack and install P2A on client
+ P2ADir = filename:join([MasterRoot, "releases", "P2A"]),
+ {ok, "P2A"} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [filename:join(P2ADir, "rel3.rel"),[]]),
+
+ ok = rpc:call(Node, release_handler, install_file,
+ ["P2A", filename:join(P2ADir, "start.boot")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ ["P2A", filename:join(P2ADir, "sys.config")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ ["P2A", filename:join(P2ADir, "relup")]),
+
+ {ok, "P1I", [new_emu]} =
+ rpc:call(Node, release_handler, check_install_release, ["P2A"]),
+ ok = rpc:call(Node, release_handler, make_permanent, ["P1I"]),
+ ?check_release_client(Node,"P1I",permanent,["a-1.1"]),
+
+ %% since the install_release below reboot the node...
+ check_disallowed_calls(),
+ cover_client(TestNode,Node,stop_cover),
+
+ {ok, "P1I", [new_emu]} =
+ rpc:call(Node, release_handler, install_release, ["P2A"]),
+ %% Reboots the client !
+
+ check_reboot(TestNode,Node),
+ trace_disallowed_calls(Node),
+
+ client1_4(TestNode,Node).
+
+client1_4(TestNode,Node) ->
+ ?print(["client1_4 start"]),
+
+ %% Check that P2A is in use.
+ ?check_release_client(Node,"P2A",current,["a-1.1"]),
+ ?check_running_app_client(Node,a,"1.1"),
+ X = rpc:call(Node, a, a, []),
+ {key2, newval2} = lists:keyfind(key2, 1, X),
+ {key1, val1} = lists:keyfind(key1, 1, X),
+ {ok, bval} = rpc:call(Node, a, b, []),
+
+ %% Reboot from P1I
+ check_disallowed_calls(),
+ reboot(TestNode,Node),
+ trace_disallowed_calls(Node),
+
+ client1_5(TestNode,Node).
+
+client1_5(TestNode,Node) ->
+ ?print(["client1_5 start"]),
+
+ %% Check that P1I is used
+ {ok, "P1I", [new_emu]} =
+ rpc:call(Node, release_handler, check_install_release, ["P2A"]),
+
+ %% since the install_release below will reboot the node...
+ check_disallowed_calls(),
+ cover_client(TestNode,Node,stop_cover),
+
+ %% Install P2A again
+ {ok, "P1I", [new_emu]} =
+ rpc:call(Node, release_handler, install_release, ["P2A"]),
+
+ %% We are rebooted again.
+ check_reboot(TestNode,Node),
+ trace_disallowed_calls(Node),
+
+ client1_6(TestNode,Node).
+
+client1_6(TestNode,Node) ->
+ ?print(["client1_6 start"]),
+
+ %% Check that P2A is used
+ ?check_release_client(Node,"P2A",current,["a-1.1"]),
+ ?check_running_app_client(Node,a,"1.1"),
+ X = rpc:call(Node, a, a, []),
+ {key2, newval2} = lists:keyfind(key2, 1, X),
+ {key1, val1} = lists:keyfind(key1, 1, X),
+ {ok, bval} = rpc:call(Node, a, b, []),
+
+ %% Make P2A permanent
+ ok = rpc:call(Node, release_handler, make_permanent, ["P2A"]),
+
+ %% Reboot from P2A
+ check_disallowed_calls(),
+ reboot(TestNode,Node),
+ trace_disallowed_calls(Node),
+
+ client1_7(TestNode,Node).
+
+client1_7(TestNode,Node) ->
+ ?print(["client1_7 start"]),
+
+ %% Check that P2A is used
+ ?check_release_client(Node,"P2A",permanent,["a-1.1"]),
+
+ %% since the reboot_old_release below will reboot the node
+ check_disallowed_calls(),
+ cover_client(TestNode,Node,stop_cover),
+
+ %% Install old P1H
+ rpc:call(Node, release_handler, reboot_old_release, ["P1H"]),
+ %% We are rebooted.
+ check_reboot(TestNode,Node),
+ trace_disallowed_calls(Node),
+
+ client1_8(TestNode,Node).
+
+client1_8(TestNode,Node) ->
+ ?print(["client1_8 start"]),
+
+ %% Check that P1H is permanent
+ ?check_release_client(Node,"P1H",permanent,["a-1.0"]),
+ X = rpc:call(Node, a, a, []),
+ {key2, val2} = lists:keyfind(key2, 1, X),
+ {key1, val1} = lists:keyfind(key1, 1, X),
+
+ %% Remove P1I and P2I from client
+ ok = rpc:call(Node, release_handler, set_removed, ["P2A"]),
+ ok = rpc:call(Node, release_handler, set_removed, ["P1I"]),
+
+ check_disallowed_calls(),
+ reboot(TestNode,Node),
+ trace_disallowed_calls(Node),
+
+ client1_9(TestNode,Node).
+
+client1_9(TestNode,Node) ->
+ ?print(["client1_9 start"]),
+
+ %% Check that P2A and P1I does not exists and that PiH is permanent.
+ Rels = rpc:call(Node, release_handler, which_releases, []),
+ false = lists:keysearch("P2A", 2, Rels),
+ false = lists:keysearch("P1I", 2, Rels),
+ ?check_release_client(Node,"P1H",permanent,["a-1.0"]),
+ X = rpc:call(Node, a, a, []),
+ {key2, val2} = lists:keyfind(key2, 1, X),
+ {key1, val1} = lists:keyfind(key1, 1, X),
+
+ %% since the reboot_old_release below will reboot the node
+ check_disallowed_calls(),
+ cover_client(TestNode,Node,stop_cover),
+
+ %% Install old P1G
+ rpc:call(Node, release_handler, reboot_old_release, ["P1G"]),
+ %% We are rebooted.
+ check_reboot(TestNode,Node),
+ trace_disallowed_calls(Node),
+
+ client1_10(TestNode,Node).
+
+client1_10(TestNode,Node) ->
+ ?print(["client1_10 start"]),
+
+ %% Check that P1G is permanent
+ ?check_release_client(Node,"P1G",permanent,[]),
+ ?check_release_client(Node,"P1H",old,["a-1.0"]),
+ {error,client_node} = rpc:call(Node,release_handler,remove_release,["P1H"]),
+ ok = rpc:call(Node, release_handler, set_removed, ["P1H"]),
+
+ check_disallowed_calls(),
+ reboot(TestNode,Node),
+ trace_disallowed_calls(Node),
+
+ client1_11(TestNode,Node).
+
+client1_11(TestNode,Node) ->
+ ?print(["client1_11 start"]),
+
+ %% Check that P1G is permanent
+ ?check_release_client(Node,"P1G",permanent,[]),
+
+ check_disallowed_calls(),
+ stop_client(TestNode,Node), %% TEST IS OK !!
+ net_kernel:monitor_nodes(false),
+
+ ok = release_handler:remove_release("P2A"),
+ ok = release_handler:remove_release("P1I"),
+ ok = release_handler:remove_release("P1H"),
+ ok.
+
+%% Start tracing of the file module on the client node. This module
+%% shall never be called, since
+%% 1) the node is a client from the release_handler's point of view,
+%% so all file access should be done via rpc calls to the master
+%% 2) it is started with erl_prim_loader loader set to 'inet' so all
+%% code loading should be done via the inet to the master
+%% (OTP-9142)
+%% This function is called each time the client node is started and to
+%% check if a call has been made, call check_disallowed_node/0
+trace_disallowed_calls(Node) ->
+ MasterProc = self(),
+ rpc:call(Node,dbg,tracer,[process,{fun(T,_) -> MasterProc ! T end,[]}]),
+ rpc:call(Node,dbg,p,[all,call]),
+ rpc:call(Node,dbg,tp,[file,[{'_',[],[{message,{caller}}]}]]).
+
+check_disallowed_calls() ->
+ receive
+ Trace when element(1,Trace)==trace ->
+ exit({disallowed_function_call,Trace})
+ after 0 ->
+ ok
+ end.
+
+start_client(TestNode,Client,Sname) ->
+ Node = list_to_atom(lists:concat([Sname,"@",test_host()])),
+ case os:type() of
+ {unix,_} -> start_client_unix(TestNode,Sname,Node);
+ {win32,_} -> start_client_win32(TestNode,Client,Sname)
+ end,
+ receive
+ {nodeup, Node} ->
+ wait_started(TestNode,Node)
+ after 30000 ->
+ ?print([{start_client,failed,Node},net_adm:ping(Node)]),
+ ?fail({"can not start", Node})
+ end.
+
+start_client_unix(TestNode,Sname,Node) ->
+ Start = filename:join(["clients", "type1", Node, "bin", "start"]),
+ Cmd = lists:concat(["env NODENAME=",Sname," ",
+ filename:join(code:root_dir(), Start)]),
+ ?print([{start_client,Sname},Cmd]),
+ Res = os:cmd(Cmd),
+ ?print([{start_client,result},Res]).
+
+start_client_win32(TestNode,Client,ClientSname) ->
+ Name = atom_to_list(ClientSname) ++ "_P1G",
+ RootDir = code:root_dir(),
+ ErtsBinDir = filename:join(RootDir,"erts-4.4/bin"),
+
+ {ClientArgs,RelClientDir} = rh_test_lib:get_client_args(Client,ClientSname,
+ RootDir),
+ StartErlArgs = rh_test_lib:get_start_erl_args(RootDir,RelClientDir,
+ ClientArgs),
+ ServiceArgs = rh_test_lib:get_service_args(RootDir, RelClientDir,
+ ClientSname, StartErlArgs),
+
+ ?print([{start_client,ClientSname},ServiceArgs]),
+ Erlsrv = filename:nativename(filename:join(ErtsBinDir,"erlsrv")),
+ rh_test_lib:erlsrv(Erlsrv,stop,Name),
+ rh_test_lib:erlsrv(Erlsrv,remove,Name),
+ ok = rh_test_lib:erlsrv(Erlsrv,add,Name,ServiceArgs),
+ ok = rh_test_lib:erlsrv(Erlsrv,start,Name),
+ ?print([{start_client,result},ok]),
+ ok.
+
+reboot(TestNode,Node) ->
+ cover_client(TestNode,Node,stop_cover),
+ rpc:call(Node, init, reboot, []),
+ check_reboot(TestNode,Node).
+
+%% This way of checking that the node is rebooted will only work if
+%% the nodes are automatically re-connected after the reboot. This
+%% happens for master/client (when sasl is started on the client).
+check_reboot(TestNode,Node) ->
+ receive
+ {nodedown, Node} ->
+ receive
+ {nodeup, Node} -> wait_started(TestNode,Node)
+ after 30000 ->
+ ?fail({Node, "not rebooted",net_adm:ping(Node)})
+ end
+ after 30000 ->
+ ?fail({Node, "not closing down",net_adm:ping(Node)})
+ end.
+
+stop_client(TestNode,Node) ->
+ cover_client(TestNode,Node,stop_cover),
+ rpc:call(Node, init, stop, []),
+ receive
+ {nodedown, Node} -> ok
+ after 30000 ->
+ ?fail({Node, "not stopping"})
+ end.
+
+wait_started(TestNode,Node) ->
+ case rpc:call(Node, init, get_status, []) of
+ {started, _} ->
+ cover_client(TestNode,Node,start_cover),
+ Node;
+ _ ->
+ timer:sleep(1000),
+ wait_started(TestNode,Node)
+ end.
+
+cover_client(TestNode,Node,Func) ->
+ R = rpc:call(TestNode,release_handler_SUITE,Func,[Node]),
+ ?print([{Func,Node,R}]).
+
+
+%%-----------------------------------------------------------------
+%% This test starts a client node which uses this node as master
+%% for the release_handler.
+%% The client node has the name cli2@HOSTNAME.
+%% The client node is not allowed to do ANY release updates
+%% as it also have another (non-existing) master node.
+%%
+%% The to_erl /tmp/cli2@HOSTNAME/ command can be used to connect
+%% to the client node.
+%% run_erl logs for the client can be found in the directory:
+%% code:root_dir() ++ "/clients/type1/cli2@HOSTNAME/log
+%%-----------------------------------------------------------------
+client2(TestNode,PrivDir,ClientSname) ->
+ TestHost = test_host(),
+ ?print(["client2 start"]),
+
+ %% Clean up if previous test case failed
+ release_handler:remove_release("P1H"),
+
+ ok = net_kernel:monitor_nodes(true),
+ Node = start_client(TestNode,client2,ClientSname),
+
+ %% Check env var for SASL on client node
+ SaslEnv = rpc:call(Node, application, get_all_env, [sasl]),
+ ?print([{client1_1,sasl_env},SaslEnv]),
+ {_,CliDir} = lists:keyfind(client_directory,1,SaslEnv),
+ {_,[Master,Master2]} = lists:keyfind(masters,1,SaslEnv),
+ {_,StartCli} = lists:keyfind(start_prg,1,SaslEnv),
+ NodeStr = atom_to_list(Node),
+ [NodeStr,"type1","clients"|_] = lists:reverse(filename:split(CliDir)),
+ true = (Master =:= node()),
+ true = (Master2 =:= list_to_atom("master2@"++TestHost)),
+ case os:type() of
+ {unix,_} ->
+ true = (StartCli =:= filename:join([CliDir,"bin","start"]));
+ _ ->
+ ok
+ end,
+
+ {ok, "P1H"} = unpack_release(PrivDir,"rel1"),
+
+ Root = code:root_dir(),
+ {error,{bad_masters,[Master2]}} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [filename:join([Root, "releases", "P1H", "rel1.rel"]),[]]),
+
+ {error,{no_such_release,"P1H"}} =
+ rpc:call(Node, release_handler, check_install_release, ["P1H"]),
+
+ stop_client(TestNode,Node), %% TEST IS OK !!
+ net_kernel:monitor_nodes(false),
+
+ release_handler:remove_release("P1H"),
+ ok.
+
+
+stop(Now) ->
+ %% The timestamp is only used for debugging. It is printed by
+ %% release_handler_SUITE also.
+ R = init:stop(),
+ erlang:display({init_stop,Now,R}),
+ R.
+
+unpack_p1h(TestNode,PrivDir) ->
+ {ok, "P1H"} = unpack_release(PrivDir,"rel1"),
+ ?check_release("P1H",unpacked,["a-1.0"]),
+ ok.
+
+permanent_p1h(TestNode) ->
+ ?check_release("P1H",unpacked,["a-1.0"]),
+ {ok,"P1G",[new_appl]} = release_handler:install_release("P1H"),
+ ?check_release("P1H",current,["a-1.0"]),
+ ok = release_handler:make_permanent("P1H"),
+ ?check_release("P1H",permanent,["a-1.0"]),
+ ok.
+
+
+reg_proc(Name) ->
+ catch unregister(Name),
+ Pid = spawn_link(?MODULE, registered_loop, [Name]),
+ global:register_name(Name, Pid),
+ ok.
+
+registered_loop(_Name) ->
+ receive
+ kill ->
+ exit(killed)
+ end.
+
+check_release(TestNode,Node,Vsn,Status,Apps,Line) ->
+ case rpc:call(Node,release_handler,which_releases,[]) of
+ {badrpc,_}=Error ->
+ ?fail_line(Line,{check_release,Node,Vsn,Status,Error});
+ Rels ->
+ ?print_line(Line,["check_release:", Rels]),
+ {"SASL-test", Vsn, Libs, Status} = lists:keyfind(Vsn, 2, Rels),
+ true = lists:all(fun(App) -> lists:member(App,Libs) end,Apps),
+ ok
+ end.
+
+check_running_app(TestNode,Node,App,Vsn,Line) ->
+ case rpc:call(Node,application,which_applications,[]) of
+ {badrpc,_}=Error ->
+ ?fail_line(Line,{check_running_app,Node,App,Vsn,Error});
+ Apps ->
+ ?print_line(Line,["check_running_app:", Apps]),
+ {App, _, Vsn} = lists:keyfind(a, 1, Apps),
+ ok
+ end.
+
+test_host() ->
+ {ok,Host} = inet:gethostname(),
+ Host.
+
+unpack_release(PrivDir,Rel) ->
+ copy(filename:join([PrivDir,Rel,Rel++".tar.gz"]),
+ filename:join(code:root_dir(),releases)),
+ release_handler:unpack_release(Rel).
+
+copy(Src, DestDir) ->
+ Dest = filename:join(DestDir, filename:basename(Src)),
+ {ok,_} = file:copy(Src, Dest),
+ ok.
+
diff --git a/lib/sasl/test/overload_SUITE.erl b/lib/sasl/test/overload_SUITE.erl
new file mode 100644
index 0000000000..92b1aaed6e
--- /dev/null
+++ b/lib/sasl/test/overload_SUITE.erl
@@ -0,0 +1,175 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(overload_SUITE).
+-include("test_server.hrl").
+
+-compile(export_all).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+all() -> [info, set_config_data, set_env_vars, request, timeout].
+all(suite) -> all().
+
+init_per_testcase(_Case,Config) ->
+ restart_sasl(),
+ Config.
+
+end_per_testcase(Case,Config) ->
+ try apply(?MODULE,Case,[cleanup,Config])
+ catch error:undef -> ok
+ end,
+ ok.
+
+%%%-----------------------------------------------------------------
+info(suite) -> [];
+info(_Config) ->
+ ?line Info = overload:get_overload_info(),
+ ?line [{total_intensity,0.0},
+ {accept_intensity,0.0},
+ {max_intensity,0.8},
+ {weight,0.1},
+ {total_requests,0},
+ {accepted_requests,0}] = Info.
+
+%%%-----------------------------------------------------------------
+set_config_data(suite) -> [];
+set_config_data(_Config) ->
+ ?line InfoDefault = overload:get_overload_info(),
+ ?line ok = check_info(0.8,0.1,InfoDefault),
+ ?line ok = overload:set_config_data(0.5,0.4),
+ ?line Info1 = overload:get_overload_info(),
+ ?line ok = check_info(0.5,0.4,Info1),
+ ok.
+
+%%%-----------------------------------------------------------------
+set_env_vars(suite) -> [];
+set_env_vars(_Config) ->
+ ?line InfoDefault = overload:get_overload_info(),
+ ?line ok = check_info(0.8,0.1,InfoDefault),
+ ?line ok = application:set_env(sasl,overload_max_intensity,0.5),
+ ?line ok = application:set_env(sasl,overload_weight,0.4),
+ ?line ok = application:stop(sasl),
+ ?line ok = application:start(sasl),
+ ?line Info1 = overload:get_overload_info(),
+ ?line ok = check_info(0.5,0.4,Info1),
+ ok.
+set_env_vars(cleanup,_Config) ->
+ application:unset_env(sasl,overload_max_intensity),
+ application:unset_env(sasl,overload_weight),
+ ok.
+
+%%%-----------------------------------------------------------------
+request(suite) -> [];
+request(_Config) ->
+ %% Find number of request that can be done with default settings
+ %% and no delay
+ ?line overload:set_config_data(0.8, 0.1),
+ ?line NDefault = do_many_requests(0),
+ ?line restart_sasl(),
+ ?line ?t:format("NDefault: ~p",[NDefault]),
+
+ %% Check that the number of requests increases when max_intensity
+ %% increases
+ ?line overload:set_config_data(2, 0.1),
+ ?line NLargeMI = do_many_requests(0),
+ ?line restart_sasl(),
+ ?line ?t:format("NLargeMI: ~p",[NLargeMI]),
+ ?line true = NLargeMI > NDefault,
+
+ %% Check that the number of requests decreases when weight
+ %% increases
+ ?line overload:set_config_data(0.8, 1),
+ ?line NLargeWeight = do_many_requests(0),
+ ?line restart_sasl(),
+ ?line ?t:format("NLargeWeight: ~p",[NLargeWeight]),
+ ?line true = NLargeWeight < NDefault,
+
+ %% Check that number of requests increases when delay between
+ %% requests increases.
+ %% (Keeping same config and comparing to large weight in order to
+ %% minimize the time needed for this case.)
+ ?line overload:set_config_data(0.8, 1),
+ ?line NLargeTime = do_many_requests(500),
+ ?line restart_sasl(),
+ ?line ?t:format("NLargeTime: ~p",[NLargeTime]),
+ ?line true = NLargeTime > NLargeWeight,
+ ok.
+
+%%%-----------------------------------------------------------------
+timeout(suite) -> [];
+timeout(_Config) ->
+ ?line overload:set_config_data(0.8, 1),
+ ?line _N = do_many_requests(0),
+
+ %% Check that the overload alarm is raised
+ ?line [{overload,_}] = alarm_handler:get_alarms(),
+
+ %% Fake a clear timeout in overload.erl and check that, since it
+ %% came very soon after the overload situation, the alarm is not
+ %% cleared
+ ?line overload ! timeout,
+ ?line timer:sleep(1000),
+ ?line [{overload,_}] = alarm_handler:get_alarms(),
+
+ %% A bit later, try again and check that this time the alarm is
+ %% cleared
+ ?line overload ! timeout,
+ ?line timer:sleep(1000),
+ ?line [] = alarm_handler:get_alarms(),
+
+ ok.
+
+
+%%%-----------------------------------------------------------------
+%%% INTERNAL FUNCTIONS
+
+%%%-----------------------------------------------------------------
+%%% Call overload:request/0 up to 30 times with the given time delay
+%%% between. Stop when 'reject' is returned.
+do_many_requests(T) ->
+ 30 - do_requests(30,T).
+
+do_requests(0,_) ->
+ ?t:fail(never_rejected);
+do_requests(N,T) ->
+ case overload:request() of
+ accept ->
+ timer:sleep(T),
+ do_requests(N-1,T);
+ reject ->
+ N
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Restart the sasl application
+restart_sasl() ->
+ application:stop(sasl),
+ application:start(sasl),
+ ok.
+
+%%%-----------------------------------------------------------------
+%%% Check that max_intensity and weight is set as expected
+check_info(MI,W,Info) ->
+ case {lists:keyfind(max_intensity,1,Info), lists:keyfind(weight,1,Info)} of
+ {{_,MI},{_,W}} -> ok;
+ _ -> ?t:fail({unexpected_info,MI,W,Info})
+ end.
+
+
diff --git a/lib/sasl/test/rb_SUITE.erl b/lib/sasl/test/rb_SUITE.erl
new file mode 100644
index 0000000000..b53c382609
--- /dev/null
+++ b/lib/sasl/test/rb_SUITE.erl
@@ -0,0 +1,606 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(rb_SUITE).
+-include("test_server.hrl").
+
+-compile(export_all).
+
+-define(SUP,rb_SUITE_sup).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+all() ->
+ no_group_cases() ++ [{group,running_error_logger}].
+
+no_group_cases() ->
+ [help,
+ start_error_stop].
+
+groups() ->
+ [{running_error_logger,[shuffle],[show,
+ list,
+ rescan,
+ start_stop_log,
+ grep,
+ filter_filter,
+ filter_date,
+ filter_filter_and_date,
+ filter_re_no
+ ]}].
+
+
+all(suite) ->
+ no_group_cases() ++
+ [{conf,
+ install_mf_h,
+ element(3,lists:keyfind(running_error_logger,1,groups())),
+ remove_mf_h}
+ ].
+
+
+init_per_suite(Config) ->
+ ?line PrivDir = ?config(priv_dir,Config),
+ ?line RbDir = filename:join(PrivDir,rb),
+ ?line ok = file:make_dir(RbDir),
+ NewConfig = [{rb_dir,RbDir}|Config],
+ reset_sasl(NewConfig),
+ NewConfig.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(running_error_logger,Config) ->
+ install_mf_h(Config).
+
+end_per_group(running_error_logger,Config) ->
+ remove_mf_h(Config).
+
+init_per_testcase(_Case,Config) ->
+ case whereis(?SUP) of
+ undefined -> ok;
+ Pid -> kill(Pid)
+ end,
+ empty_error_logs(Config),
+ Config.
+
+kill(Pid) ->
+ Ref = erlang:monitor(process,Pid),
+ exit(Pid,kill),
+ receive {'DOWN', Ref, process, Pid, _Info} -> ok end.
+
+end_per_testcase(Case,Config) ->
+ try apply(?MODULE,Case,[cleanup,Config])
+ catch error:undef -> ok
+ end,
+ ok.
+
+
+%%%-----------------------------------------------------------------
+
+help() -> help(suite).
+help(suite) -> [];
+help(_Config) ->
+ ?line Help = capture(fun() -> rb:h() end),
+ ?line "Report Browser Tool - usage" = hd(Help),
+ ?line "rb:stop - stop the rb_server" = lists:last(Help),
+ ok.
+
+
+start_error_stop() -> start_error_stop(suite).
+start_error_stop(suite) -> [];
+start_error_stop(Config) ->
+ ?line RbDir = ?config(rb_dir,Config),
+
+ ?line {error,{"cannot locate report directory",_}} = rb:start(),
+
+
+ ?line ok = application:set_env(sasl,error_logger_mf_dir,"invaliddir"),
+ ?line ok = application:set_env(sasl,error_logger_mf_maxbytes,1000),
+ ?line ok = application:set_env(sasl,error_logger_mf_maxfiles,2),
+ ?line restart_sasl(),
+ ?line {error,{"cannot read the index file",_}} = rb:start(),
+ ?line ok = application:set_env(sasl,error_logger_mf_dir,RbDir),
+ ?line restart_sasl(),
+ ?line {ok,_} = rb:start(),
+
+ ?line ok = rb:stop(),
+ ok.
+
+
+%% start_opts(suite) -> [];
+%% start_opts(Config) ->
+%% PrivDir = ?config(priv_dir,Config),
+%% RbDir = filename:join(PrivDir,rb_opts),
+%% ok = file:make_dir(RbDir),
+
+
+install_mf_h(Config) ->
+ ?line RbDir = ?config(rb_dir,Config),
+ ?line ok = application:set_env(sasl,error_logger_mf_dir,RbDir),
+ ?line ok = application:set_env(sasl,error_logger_mf_maxbytes,5000),
+ ?line ok = application:set_env(sasl,error_logger_mf_maxfiles,2),
+ ?line restart_sasl(),
+ Config.
+
+remove_mf_h(_Config) ->
+ ok.
+
+
+
+show() -> show(suite).
+show(suite) -> [];
+show(Config) ->
+ ?line PrivDir = ?config(priv_dir,Config),
+ ?line OutFile = filename:join(PrivDir,"rb_SUITE_log.txt"),
+
+ %% Insert some reports in the error log and start rb
+ init_error_logs(),
+ ?line ok = start_rb(OutFile),
+
+ %% Show all reports
+ ?line All = check_report(fun() -> rb:show() end,OutFile),
+
+ %% Show by number
+ ?line [{_,First}] = check_report(fun() -> rb:show(1) end,OutFile),
+ ?line {1,First} = lists:keyfind(1,1,All),
+
+ %% Show by type
+ ?line [{_,CR}] = check_report(fun() -> rb:show(crash_report) end,OutFile),
+ ?line true = contains(CR,"rb_test_crash"),
+ ?line [{_,EC},{_,EM}] = check_report(fun() -> rb:show(error) end,OutFile),
+ ?line true = contains(EC,"rb_test_crash"),
+ ?line true = contains(EM,"rb_test_error_msg"),
+ ?line [{_,ER}] = check_report(fun() -> rb:show(error_report) end,OutFile),
+ ?line true = contains(ER,"rb_test_error"),
+ ?line [{_,IR}] = check_report(fun() -> rb:show(info_report) end,OutFile),
+ ?line true = contains(IR,"rb_test_info"),
+ ?line [{_,IM}] = check_report(fun() -> rb:show(info_msg) end,OutFile),
+ ?line true = contains(IM,"rb_test_info_msg"),
+ ?line [_|_] = check_report(fun() -> rb:show(progress) end,OutFile),
+ ?line [{_,SR}] = check_report(fun() -> rb:show(supervisor_report) end,
+ OutFile),
+ ?line true = contains(SR,"child_terminated"),
+ ?line true = contains(SR,"{rb_SUITE,rb_test_crash}"),
+
+ ok.
+
+list() -> list(suite).
+list(suite) -> [];
+list(Config) ->
+ ?line PrivDir = ?config(priv_dir,Config),
+ ?line OutFile = filename:join(PrivDir,"rb_SUITE_log.txt"),
+
+ %% Insert some reports in the error log and start rb
+ init_error_logs(),
+ ?line ok = start_rb(OutFile),
+
+ ?line All = capture(fun() -> rb:list() end),
+ ?line [{crash_report,[_]=CR},
+ {error,[_,_]=EM},
+ {error_report,[_]=ER},
+ {info_msg,[_]=IM},
+ {info_report,[_]=IR},
+ {progress,[_|_]=P},
+ {supervisor_report,[_]=SR}] = sort_list(All),
+
+ ?line [{crash_report,CR}] =
+ sort_list(capture(fun() -> rb:list(crash_report) end)),
+ ?line [{error,EM}] =
+ sort_list(capture(fun() -> rb:list(error) end)),
+ ?line [{error_report,ER}] =
+ sort_list(capture(fun() -> rb:list(error_report) end)),
+ ?line [{info_msg,IM}] =
+ sort_list(capture(fun() -> rb:list(info_msg) end)),
+ ?line [{info_report,IR}] =
+ sort_list(capture(fun() -> rb:list(info_report) end)),
+ ?line [{progress,P}] =
+ sort_list(capture(fun() -> rb:list(progress) end)),
+ ?line [{supervisor_report,SR}] =
+ sort_list(capture(fun() -> rb:list(supervisor_report) end)),
+
+ ok.
+
+
+grep() -> grep(suite).
+grep(suite) -> [];
+grep(Config) ->
+ ?line PrivDir = ?config(priv_dir,Config),
+ ?line OutFile = filename:join(PrivDir,"rb_SUITE_log.txt"),
+
+ %% Insert some reports in the error log and start rb
+ init_error_logs(),
+ ?line ok = start_rb(OutFile),
+
+ ?line [{_,S},
+ {_,CR},
+ {_,EC},
+ {_,IM},
+ {_,IR},
+ {_,EM},
+ {_,ER}]= check_report(fun() -> rb:grep("rb_test_") end,OutFile),
+ ?line true = contains(S, "rb_test_crash"),
+ ?line true = contains(CR, "rb_test_crash"),
+ ?line true = contains(EC, "rb_test_crash"),
+ ?line true = contains(IM, "rb_test_info_msg"),
+ ?line true = contains(IR, "rb_test_info"),
+ ?line true = contains(EM, "rb_test_error_msg"),
+ ?line true = contains(ER, "rb_test_error"),
+ ok.
+
+
+filter_filter() -> filter_filter(suite).
+filter_filter(suite) -> [];
+filter_filter(Config) ->
+ ?line PrivDir = ?config(priv_dir,Config),
+ ?line OutFile = filename:join(PrivDir,"rb_SUITE_log.txt"),
+
+ %% Insert some reports in the error log and start rb
+ init_error_logs(),
+ ?line ok = start_rb(OutFile),
+
+ ?line All = check_report(fun() -> rb:show() end,OutFile),
+
+ ?line ER = [_] = rb_filter([{rb_SUITE,rb_test_error}],OutFile),
+ ?line [] = rb_filter([{rb_SUITE,rb_test}],OutFile),
+ ?line _E = [_,_] = rb_filter([{rb_SUITE,"rb_test",re}],OutFile),
+ ?line AllButER = rb_filter([{rb_SUITE,rb_test_error,no}],OutFile),
+
+ {_,AllRep} = lists:unzip(All),
+ {_,ERRep} = lists:unzip(ER),
+ {_,AllButERRep} = lists:unzip(AllButER),
+ ?line AllButERRep = AllRep -- ERRep,
+
+ ok.
+
+filter_date() -> filter_date(suite).
+filter_date(suite) -> [];
+filter_date(Config) ->
+ ?line PrivDir = ?config(priv_dir,Config),
+ ?line OutFile = filename:join(PrivDir,"rb_SUITE_log.txt"),
+
+
+ %% Insert some reports in the error log and start rb
+ init_error_logs(),
+ Between1 = calendar:local_time(),
+ timer:sleep(1000),
+ Between2 = calendar:local_time(),
+ ?line ok = start_rb(OutFile),
+
+ ?line All = check_report(fun() -> rb:show() end,OutFile),
+
+ Before = calendar:gregorian_seconds_to_datetime(
+ calendar:datetime_to_gregorian_seconds(calendar:local_time()) - 10),
+ After = calendar:gregorian_seconds_to_datetime(
+ calendar:datetime_to_gregorian_seconds(calendar:local_time()) + 1),
+
+ ?line All = rb_filter([],{Before,from},OutFile),
+ ?line All = rb_filter([],{After,to},OutFile),
+ ?line [] = rb_filter([],{Before,to},OutFile),
+ ?line [] = rb_filter([],{After,from},OutFile),
+ ?line All = rb_filter([],{Before,After},OutFile),
+
+ %%?t:format("~p~n",[All]),
+ ?line AllButLast = [{N-1,R} || {N,R} <- tl(All)],
+ ?line AllButLast = rb_filter([],{Before,Between1},OutFile),
+
+ ?line Last = hd(All),
+ ?line [Last] = rb_filter([],{Between2,After},OutFile),
+
+ ok.
+
+filter_filter_and_date() -> filter_filter_and_date(suite).
+filter_filter_and_date(suite) -> [];
+filter_filter_and_date(Config) ->
+ ?line PrivDir = ?config(priv_dir,Config),
+ ?line OutFile = filename:join(PrivDir,"rb_SUITE_log.txt"),
+
+
+ %% Insert some reports in the error log and start rb
+ init_error_logs(),
+ Between1 = calendar:local_time(),
+ timer:sleep(1000),
+ Between2 = calendar:local_time(),
+ ?line error_logger:error_report([{rb_SUITE,rb_test_filter}]),
+ ?line ok = start_rb(OutFile),
+
+ Before = calendar:gregorian_seconds_to_datetime(
+ calendar:datetime_to_gregorian_seconds(calendar:local_time()) - 10),
+ After = calendar:gregorian_seconds_to_datetime(
+ calendar:datetime_to_gregorian_seconds(calendar:local_time()) + 1),
+
+ ?line All = check_report(fun() -> rb:show() end,OutFile),
+ ?line Last = hd(All),
+
+ ?line [_,_,_] = rb_filter([{rb_SUITE,"rb_test",re}],{Before,After},OutFile),
+ ?line [_,_] = rb_filter([{rb_SUITE,"rb_test",re}],{Before,Between1},OutFile),
+ ?line [_] = rb_filter([{rb_SUITE,"rb_test",re}],{Between2,After},OutFile),
+ ?line [_] = rb_filter([{rb_SUITE,rb_test_filter}],{Before,After},OutFile),
+ ?line [] = rb_filter([{rb_SUITE,rb_test_filter}],{Before,Between1},OutFile),
+ ?line [Last] = rb_filter([{rb_SUITE,rb_test_filter,no}],{Between2,After},OutFile),
+ ?line {_,Str} = Last,
+ ?line false = contains(Str,"rb_test_filter"),
+
+ ok.
+
+
+filter_re_no() -> filter_re_no(suite).
+filter_re_no(suite) -> [];
+filter_re_no(Config) ->
+ ?line PrivDir = ?config(priv_dir,Config),
+ ?line OutFile = filename:join(PrivDir,"rb_SUITE_log.txt"),
+
+ %% Insert some reports in the error log and start rb
+ init_error_logs(),
+ ?line ok = start_rb(OutFile),
+
+ ?line All = check_report(fun() -> rb:show() end,OutFile),
+
+ ?line E = [_,_] = rb_filter([{rb_SUITE,"rb_test",re}],OutFile),
+ ?line AllButE = rb_filter([{rb_SUITE,"rb_test",re,no}],OutFile),
+
+ {_,AllRep} = lists:unzip(All),
+ {_,ERep} = lists:unzip(E),
+ {_,AllButERep} = lists:unzip(AllButE),
+ ?line AllButERep = AllRep -- ERep,
+
+ ok.
+
+
+rescan() -> rescan(suite).
+rescan(suite) -> [];
+rescan(Config) ->
+ ?line PrivDir = ?config(priv_dir,Config),
+ ?line OutFile = filename:join(PrivDir,"rb_SUITE_log.txt"),
+
+ %% Start rb
+ ?line ok = start_rb(OutFile),
+
+ %% Insert one more report and check that the list is longer. Note
+ %% that there might be two more reports, since the progress report
+ %% from starting rb_server might not be included before the rescan.
+ ?line AllBefore = capture(fun() -> rb:list() end),
+ ?line error_logger:error_report([{rb_SUITE,rb_test_rescan}]),
+ ?line ok = rb:rescan(),
+ ?line AllAfter = capture(fun() -> rb:list() end),
+ ?line Diff = length(AllAfter) - length(AllBefore),
+ ?line true = (Diff >= 1),
+
+ ok.
+
+
+start_stop_log() -> start_stop_log(suite).
+start_stop_log(suite) -> [];
+start_stop_log(Config) ->
+ ?line PrivDir = ?config(priv_dir,Config),
+ ?line OutFile = filename:join(PrivDir,"rb_SUITE_log.txt"),
+ ?line ok = file:write_file(OutFile,[]),
+
+ %% Start rb and check that show is printed to standard_io
+ ?line ok = start_rb(),
+ ?line StdioResult = [_|_] = capture(fun() -> rb:show(1) end),
+ ?line {ok,<<>>} = file:read_file(OutFile),
+
+ %% Start log and check that show is printed to log and not to standad_io
+ ?line ok = rb:start_log(OutFile),
+ ?line [] = capture(fun() -> rb:show(1) end),
+ ?line {ok,Bin} = file:read_file(OutFile),
+ ?line true = (Bin =/= <<>>),
+
+ %% Stop log and check that show is printed to standard_io and not to log
+ ?line ok = rb:stop_log(),
+ ?line ok = file:write_file(OutFile,[]),
+ ?line StdioResult = capture(fun() -> rb:show(1) end),
+ ?line {ok,<<>>} = file:read_file(OutFile),
+
+ %% Test that standard_io is used if log file can not be opened
+ ?line ok = rb:start_log(filename:join(nonexistingdir,"newfile.txt")),
+ ?line StdioResult = capture(fun() -> rb:show(1) end),
+ ?line {ok,<<>>} = file:read_file(OutFile),
+
+ ok.
+
+
+%%%-----------------------------------------------------------------
+%%% INTERNAL FUNCTIONS
+
+restart_sasl() ->
+ application:stop(sasl),
+ ok = application:start(sasl),
+ wait_for_sasl().
+
+reset_sasl(Config) ->
+ application:unset_env(sasl,error_logger_mf_dir),
+ application:unset_env(sasl,error_logger_mf_maxbytes),
+ application:unset_env(sasl,error_logger_mf_maxfiles),
+ empty_error_logs(Config).
+
+empty_error_logs(Config) ->
+ application:stop(sasl),
+ catch delete_content(?config(rb_dir, Config)),
+ ok = application:start(sasl),
+ wait_for_sasl().
+
+wait_for_sasl() ->
+ wait_for_sasl(50).
+wait_for_sasl(0) ->
+ ?t:fail("sasl application did not start within 5 seconds");
+wait_for_sasl(N) ->
+ case lists:keymember(sasl,1,application:which_applications()) of
+ true ->
+ ok;
+ false ->
+ timer:sleep(100),
+ wait_for_sasl(N-1)
+ end.
+
+start_rb(OutFile) ->
+ do_start_rb([{start_log,OutFile}]).
+start_rb() ->
+ do_start_rb([]).
+
+do_start_rb(Opts) ->
+ {ok,Pid} = rb:start(Opts),
+
+ %% Wait for process to started, then wait a little bit more
+ sys:get_status(Pid),
+ timer:sleep(500),
+
+ %% Make sure printouts (e.g. from rb:list(), come to the test log,
+ %% and that they can be captured.
+ group_leader(group_leader(),Pid),
+ ok.
+
+
+delete_tree(Dir) ->
+ case filelib:is_dir(Dir) of
+ true ->
+ delete_content(Dir),
+ file:del_dir(Dir);
+ false ->
+ ok = file:delete(Dir)
+ end.
+
+delete_content(Dir) ->
+ {ok,Files} = file:list_dir(Dir),
+ lists:foreach(fun(File) -> delete_tree(filename:join(Dir,File)) end,
+ Files).
+
+init_error_logs() ->
+ ?line error_logger:error_report([{rb_SUITE,rb_test_error}]),
+ ?line error_logger:error_msg("rb_test_error_msg"),
+ ?line error_logger:info_report([{rb_SUITE,rb_test_info}]),
+ ?line error_logger:info_msg("rb_test_info_msg"),
+ ?line _Pid = start(),
+ ?line Ref = erlang:monitor(process,?MODULE),
+ ?line gen_server:cast(?MODULE,crash),
+ ?line receive {'DOWN',Ref,process,_,{rb_SUITE,rb_test_crash}} -> ok
+ after 2000 ->
+ ?t:format("Got: ~p~n",[process_info(self(),messages)]),
+ ?t:fail("rb_SUITE server never died")
+ end,
+ ?line erlang:demonitor(Ref),
+ ?line wait_for_server(),
+ ok.
+
+wait_for_server() ->
+ case whereis(?MODULE) of
+ undefined ->
+ wait_for_server();
+ Pid ->
+ timer:sleep(100), % allow the supervisor report to be written
+ Pid
+ end.
+
+capture(Fun) ->
+ ?t:capture_start(),
+ ok = Fun(),
+ timer:sleep(1000),
+ ?t:capture_stop(),
+ string:tokens(lists:append(?t:capture_get()),"\n").
+
+
+rb_filter(Filter,OutFile) ->
+ check_report(fun() -> rb:filter(Filter) end, OutFile).
+rb_filter(Filter,Dates,OutFile) ->
+ check_report(fun() -> rb:filter(Filter,Dates) end, OutFile).
+
+
+%% This function first empties the given report file, then executes
+%% the fun and returns a list of {N,Report}, where Report is a report
+%% read from the file and N is an integer. The newest report has the
+%% lowest number.
+%% If the fun was a call to rb:show() (i.e. with no arguments), then
+%% the numbering (N) will be the same as rb's own numbering (as shown
+%% by rb:list()).
+check_report(Fun,File) ->
+ file:delete(File),
+ rb:rescan([{start_log,File}]),
+ ok = Fun(),
+ {ok,Bin} = file:read_file(File),
+ Reports = split_reports(binary_to_list(Bin),[],[]),
+ lists:zip(lists:seq(1,length(Reports)),Reports).
+
+-define(report_header_line,"\n===============================================================================\n").
+split_reports([],Report,Reports) ->
+ add_report(Report,Reports);
+split_reports(Text,Report,Reports) ->
+ case Text of
+ ?report_header_line++Rest ->
+ {Heading,PrevReport} = lists:splitwith(fun($\n) -> false;
+ (_) -> true
+ end,
+ Report),
+ split_reports(Rest,
+ ?report_header_line++Heading,
+ add_report(PrevReport,Reports));
+ [Ch|Rest] ->
+ split_reports(Rest,[Ch|Report],Reports)
+ end.
+
+add_report(Report,Reports) ->
+ case string:strip(Report,both,$\n) of
+ [] -> Reports;
+ Report1 -> [lists:reverse(Report1)|Reports]
+ end.
+
+%% Returns true if Substr is a substring of Str.
+contains(Str,Substr) ->
+ 0 =/= string:str(Str,Substr).
+
+%% Sort the result of rb_list after report type
+sort_list(List) ->
+ sort_list(List,dict:new()).
+sort_list([H|T],D) ->
+ case re:run(H,"\s+[0-9]+\s+([a-z_]+)",[{capture,all_but_first,list}]) of
+ nomatch ->
+ sort_list(T,D);
+ {match,[TypeStr]} ->
+ sort_list(T,dict:append(list_to_atom(TypeStr),H,D))
+ end;
+sort_list([],D) ->
+ lists:sort(dict:to_list(D)).
+
+
+%%%-----------------------------------------------------------------
+%%% A dummy supervisor and gen_server used for creating crash- and
+%%% supervisor reports
+start() ->
+ {ok,Pid} =
+ supervisor:start_link({local, ?SUP}, ?MODULE, i_am_supervisor),
+ unlink(Pid),
+ Pid.
+start_server() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, i_am_server, []).
+init(i_am_server) ->
+ {ok, state};
+init(i_am_supervisor) ->
+ AChild = {?SUP,{?MODULE,start_server,[]},
+ permanent,2000,worker,[?MODULE]},
+ {ok,{{one_for_all,1,1}, [AChild]}}.
+handle_call(_Request, _From, State) ->
+ Reply = ok,
+ {reply, Reply, State}.
+handle_cast(crash, State) ->
+ exit({rb_SUITE,rb_test_crash}),
+ {noreply, State}.
+handle_info(_Info, State) ->
+ {noreply, State}.
+terminate(_Reason, _State) ->
+ ok.
+
diff --git a/lib/sasl/test/release_handler_SUITE.erl b/lib/sasl/test/release_handler_SUITE.erl
new file mode 100644
index 0000000000..af2183bfff
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE.erl
@@ -0,0 +1,2219 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(release_handler_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+
+-compile(export_all).
+
+% Default timetrap timeout (set in init_per_testcase).
+%-define(default_timeout, ?t:minutes(40)).
+-define(default_timeout, ?t:minutes(10)).
+
+suite() ->
+ [{ct_hooks, [ts_install_cth]}].
+
+init_per_suite(Config) ->
+ application:start(sasl),
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+all() ->
+ case os:type() of
+ {unix, _} -> unix_cases();
+ {win32, _} -> win32_cases()
+ end.
+
+unix_cases() ->
+ RunErl = filename:join([code:root_dir(),"bin","run_erl"]),
+ RunErlCases = case filelib:is_file(RunErl) of
+ true -> [{group, release}];
+ false -> [no_run_erl]
+ end,
+ [target_system] ++ RunErlCases ++ cases().
+
+win32_cases() ->
+ [{group,release} | cases()].
+
+%% Cases that can be run on all platforms
+cases() ->
+ [otp_2740, otp_2760, otp_5761, otp_9402, otp_9417,
+ otp_9395_check_old_code, otp_9395_check_and_purge,
+ otp_9395_update_many_mods, otp_9395_rm_many_mods,
+ instructions, eval_appup, supervisor_which_children_timeout].
+
+groups() ->
+ [{release,[],
+ [
+ {group,release_single},
+ {group,release_gg}
+ ]},
+ {release_single,[],
+ [
+ upgrade,
+ client1,
+ client2
+ ]},
+ {release_gg,[],
+ [
+ upgrade_gg
+ ]}].
+
+%% {group,release}
+%% Top group for all cases using run_erl
+init_per_group(release, Config) ->
+ Dog = ?t:timetrap(?default_timeout),
+ P1gInstall = filename:join(priv_dir(Config),p1g_install),
+ ok = do_create_p1g(Config,P1gInstall),
+ ok = create_p1h(Config),
+ ?t:timetrap_cancel(Dog);
+
+%% {group,release_single}
+%% Subgroup of {group,release}, contains all cases that are not
+%% related to global_group
+init_per_group(release_single, Config) ->
+ Dog = ?t:timetrap(?default_timeout),
+
+ %% Create some more releases to upgrade to
+ ok = create_p1i(Config),
+ ok = create_p2a(Config),
+
+ ?t:timetrap_cancel(Dog);
+
+%% {group,release_gg}
+%% Subgroup of {group,release}. global_group tests.
+init_per_group(release_gg, Config0) ->
+ Config = [{sname_prefix,release_gg}|Config0],
+
+ PrivDir = priv_dir(Config),
+ Dog = ?t:timetrap(?default_timeout),
+
+ reg_print_proc(), %% starts a printer process on this node
+
+ Snames = [Gg1Sname,Gg2Sname,Gg3Sname,Gg4Sname,Gg5Sname,Gg6Sname] =
+ gg_node_snames(Config),
+
+ %% kill all possible nodes which are to be used
+ ok = stop_nodes([node_name(Sname) || Sname <- Snames]),
+
+ %% For gg1, gg3, gg4 and gg5: create a target system running
+ %% P1G, and with P1H unpacked.
+ %% For gg2 and gg6: create a target system running P1H.
+ %% Use gg2 for unpacking and permanenting P1H.
+ ok = copy_installed(Config,p1g_install,[Gg2Sname]),
+ InstallNode = unpack_p1h(Config,Gg2Sname),
+ ok = copy_installed(Config,Gg2Sname,[Gg1Sname,Gg3Sname,Gg4Sname,Gg5Sname]),
+ ok = permanent_p1h(InstallNode),
+ ok = stop_nodes([InstallNode]),
+ ok = copy_installed(Config,Gg2Sname,[Gg6Sname]),
+
+ %% Replace the sys.config files
+ %% The reason for not creating the releases with these configs in
+ %% the first place (create_p1g, create_p1h) is that then the
+ %% InstallNode (gg2) will be very slow started since it will try
+ %% to synch with the other nodes in the global group.
+ %% Also, the rpc call for installing the P1H release (in
+ %% permanent_p1h/1) would return {rpc,nodedown} due to change of
+ %% global groups.
+ lists:foreach(
+ fun(Sname) ->
+ ReleasesDir = filename:join([PrivDir,Sname,"releases"]),
+ write_term_file(filename:join([ReleasesDir,"P1G","sys.config"]),
+ gg_config([Gg1Sname,Gg3Sname,Gg4Sname,Gg5Sname])),
+ write_term_file(filename:join([ReleasesDir,"P1H","sys.config"]),
+ gg_config([Gg1Sname,Gg2Sname,Gg4Sname,
+ Gg5Sname,Gg6Sname]))
+ end,
+ Snames),
+
+ ?t:timetrap_cancel(Dog),
+ [{snames,Snames}|Config].
+
+
+end_per_group(release, Config) ->
+ Dog = ?t:timetrap(?default_timeout),
+ stop_print_proc(),
+ case os:type() of
+ {win32,_} -> delete_all_services();
+ _ -> ok
+ end,
+ delete_release(Config),
+ ?t:timetrap_cancel(Dog),
+ Config;
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+init_per_testcase(Case, Config0) ->
+ Dog = test_server:timetrap(?default_timeout),
+ Config = [{sname_prefix,Case},{watchdog, Dog}|Config0],
+ try apply(?MODULE,Case,[cleanup,Config])
+ catch error:undef -> ok
+ end,
+ ?t:format("~n======= init_per_testcase done =======~n",[]),
+ Config.
+
+end_per_testcase(Case, Config) ->
+ ?t:format("~n======= start end_per_testcase =======~n",[]),
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+
+ try apply(?MODULE,Case,[cleanup,Config])
+ catch error:undef -> ok
+ end,
+
+ %% DEBUG
+ case ?config(tc_status,Config) of
+ ok ->
+ ok;
+ _Fail ->
+ %% save logs from master and client nodes
+ PrivDir = priv_dir(Config),
+ SaveDir = filename:join(PrivDir,save),
+ FailDir = filename:join(SaveDir,lists:concat(["failed-",Case])),
+ ok = filelib:ensure_dir(filename:join(FailDir,"*")),
+
+ LogDirs = filelib:wildcard(filename:join([PrivDir,"*",log])),
+
+ lists:foreach(
+ fun(LogDir) ->
+ ["log",Sname|_] = lists:reverse(filename:split(LogDir)),
+ copy_tree(Config,LogDir,Sname,FailDir)
+ end,
+ LogDirs),
+
+ case filelib:is_file("sasl_erl_crash.dump") of
+ true ->
+ copy_file("sasl_erl_crash.dump",FailDir);
+ _ ->
+ ok
+ end
+
+ end,
+ %% End DEBUG
+
+ %% Remove any remaining sasl_erl_crash.dump
+ %% These can occur when a new master@<host> is started, before
+ %% the old usage of the name is unregistered, causing the node to
+ %% terminate. (This has no effect on the test case, as the node is
+ %% immediately restarted by heart and the test cases wait until
+ %% the node is actually up and running -- see wait_nodes_up/2)
+ file:delete("sasl_erl_crash.dump"),
+ ok.
+
+gg_node_snames(Config) ->
+ [tc_sname(Config,X) || X <- [gg1,gg2,gg3,gg4,gg5,gg6]].
+
+
+%%%-----------------------------------------------------------------
+%%% TEST CASES
+
+
+%% Executed instead of release group when no run_erl program exists
+no_run_erl(Config) when is_list(Config) ->
+ {comment, "No run_erl program"}.
+
+break(Config) ->
+ erlang:display(test_break),
+ ?t:break(priv_dir(Config)),
+ ok.
+
+%% Test upgrade and downgrade of erts
+upgrade(Conf) when is_list(Conf) ->
+ reg_print_proc(), %% starts a printer process on test_server node
+ ?t:format("upgrade ~p~n",[reg_print_proc]),
+ PrivDir = priv_dir(Conf),
+ Sname = tc_sname(Conf), % nodename for use in this testcase
+
+ %% Copy the P1G release to a directory for use in this testcase
+ ok = copy_installed(Conf,p1g_install,[Sname]),
+
+ %% start the test node
+ [TestNode] = start_nodes(Conf,[Sname],"upgrade start"),
+
+ %% unpack and install P1H
+ ok = rpc_inst(TestNode, install_1, [PrivDir]),
+ stop_cover(TestNode),
+ reboot_and_wait(TestNode,"install_1"),
+
+ %% reinstall P1H and make it permanent
+ ok = rpc_inst(TestNode, install_2, []),
+ stop_cover(TestNode),
+ reboot_and_wait(TestNode,"install_2",[a]),
+
+ %% check that P1H is permanent, unpack and install P1I, unpack and install P2A
+ TestNodeInit1 = rpc:call(TestNode,erlang,whereis,[init]),
+ ok = rpc_inst(TestNode, install_3, [PrivDir]),
+ stop_cover(TestNode),
+ ok = rpc_inst(TestNode, install_3a, []),
+ wait_nodes_up([{TestNode,TestNodeInit1}],"install_3",[a]),
+
+ %% check that P2A is used, reboot from P1I
+ ok = rpc_inst(TestNode, install_4, []),
+ stop_cover(TestNode),
+ reboot_and_wait(TestNode,"install_4",[a]),
+
+ %% check that P1I, reinstall P2A
+ TestNodeInit2 = rpc:call(TestNode,erlang,whereis,[init]),
+ ok = rpc_inst(TestNode, install_5, []),
+ stop_cover(TestNode),
+ ok = rpc_inst(TestNode, install_5a, []),
+ wait_nodes_up([{TestNode,TestNodeInit2}],"install_5",[a]),
+
+ %% check that P2A is used, make P2A permanent
+ ok = rpc_inst(TestNode, install_6, []),
+ stop_cover(TestNode),
+ reboot_and_wait(TestNode,"install_6",[a]),
+
+ %% check that P2A is permanent, install old P1H
+ TestNodeInit3 = rpc:call(TestNode,erlang,whereis,[init]),
+ stop_cover(TestNode),
+ ok = rpc_inst(TestNode, install_7, []),
+ wait_nodes_up([{TestNode,TestNodeInit3}],"install_7",[a]),
+
+ %% check that P1H is permanent, remove P1I and P2A
+ ok = rpc_inst(TestNode, install_8, []),
+ stop_cover(TestNode),
+ reboot_and_wait(TestNode,"install_8",[a]),
+
+ %% check that P1H is permanent, reboot old P1G
+ TestNodeInit4 = rpc:call(TestNode,erlang,whereis,[init]),
+ stop_cover(TestNode),
+ ok = rpc_inst(TestNode, install_9, []),
+ wait_nodes_up([{TestNode,TestNodeInit4}],"install_9"),
+
+ %% check that P1G is permanent, remove P1H
+ ok = rpc_inst(TestNode, install_10, []),
+ stop_cover(TestNode),
+ reboot_and_wait(TestNode,"install_10"),
+
+ %% check that P1G is permanent
+ ok = rpc_inst(TestNode, install_11, []),
+
+ ok.
+
+upgrade(cleanup,Config) ->
+ TestNode = tc_full_node_name(Config),
+ ok = stop_nodes([TestNode]).
+
+reboot_and_wait(Node,Tag) ->
+ reboot_and_wait(Node,Tag,[]).
+
+reboot_and_wait(Node,Tag,Apps) ->
+ InitPid = rpc:call(Node,erlang,whereis,[init]),
+ ok = rpc:call(Node,init,reboot,[]),
+ wait_nodes_up([{Node,InitPid}],Tag,Apps).
+
+
+%% Test upgrade and downgrade of erts, diskless
+client1(Conf) when is_list(Conf) ->
+ reg_print_proc(), %% starts a printer process on test_server node
+ PrivDir = priv_dir(Conf),
+ Master = tc_sname(Conf,master),
+ Client = tc_sname(Conf,client),
+ MasterDir = filename:join(PrivDir,Master),
+
+ %% Copy the P1G release to a directory for use in this testcase
+ ok = copy_installed(Conf,p1g_install,[Master]),
+ ok = copy_client(Conf,Master,Client,client1),
+
+ %% start the master node
+ [TestNode] = start_nodes(Conf,[Master],"client1"),
+
+ ok = rpc_inst(TestNode, client1_1, [PrivDir,MasterDir,Client]),
+
+ ok.
+
+client1(cleanup,Config) ->
+ MasterNode = tc_full_node_name(Config,master),
+ ClientNode = tc_full_node_name(Config,client),
+ ok = stop_nodes([MasterNode,ClientNode]).
+
+
+
+%% Test diskless release handling when illegal master node
+client2(Conf) when is_list(Conf) ->
+ reg_print_proc(), %% starts a printer process on test_server node
+ PrivDir = priv_dir(Conf),
+ Master = tc_sname(Conf,master),
+ Client = tc_sname(Conf,client),
+
+ %% Copy the P1G release to a directory for use in this testcase
+ ok = copy_installed(Conf,p1g_install,[Master]),
+ ok = copy_client(Conf,Master,Client,client2),
+
+ %% start the master node
+ [TestNode] = start_nodes(Conf,[Master],"client2"),
+
+ ok = rpc_inst(TestNode, client2, [PrivDir,Client]),
+
+ ok.
+
+client2(cleanup,Config) ->
+ MasterNode = tc_full_node_name(Config,master),
+ ClientNode = tc_full_node_name(Config,client),
+ ok = stop_nodes([MasterNode,ClientNode]).
+
+
+
+%% Test instructions _not_ tested by the installer module.
+instructions(Conf) when is_list(Conf) ->
+ DataDir = ?config(data_dir, Conf),
+
+ Dir = filename:join(DataDir, "c"),
+ true = code:add_path(Dir),
+ check_bstate("no", []),
+ ok = application:start(c),
+ ok = wait_for(bb),
+ check_bstate("first", []),
+ FirstBB = whereis(bb),
+
+ case whereis(cc) of
+ Pid when is_pid(Pid) -> ok;
+ _ -> ?t:fail("cc not started")
+ end,
+
+ %% Stop and start cc process
+ S1 = [point_of_no_return,
+ {stop, [aa]},
+ {apply, {?MODULE, no_cc, []}},
+ {start, [aa]}],
+ {ok, _} = release_handler_1:eval_script(S1),
+
+ case whereis(cc) of
+ Pid2 when is_pid(Pid2) -> ok;
+ _ -> ?t:fail("cc not started")
+ end,
+
+ %% Make bb run old version of b.
+ S2 = [point_of_no_return,
+ {remove, {b, soft_purge, soft_purge}}],
+ {ok, [{b, soft_purge}]} = release_handler_1:eval_script(S2),
+ check_bstate("first", [FirstBB]),
+
+ false = code:is_loaded(b),
+ {error,{old_processes,b}} = release_handler_1:eval_script(S2),
+ check_bstate("first", [FirstBB]),
+
+ %% Let supervisor restart bb with new code
+ S3 = [point_of_no_return,
+ {purge, [b]}],
+ {ok, []} = release_handler_1:eval_script(S3),
+ ok = wait_for(bb),
+ check_bstate("second", []),
+ SecondBB = whereis(bb),
+
+ if
+ SecondBB =:= FirstBB -> ?t:fail("bb not killed");
+ true -> ok
+ end,
+
+ %% Restart bb yet another time
+ ok = application:stop(c),
+ ok = application:start(c),
+ ok = wait_for(bb),
+ check_bstate("third", []),
+ ThirdBB = whereis(bb),
+
+ case ThirdBB of
+ _ when is_pid(ThirdBB) -> ok;
+ undefined -> ?t:fail("bb not started")
+ end,
+
+ %% Make bb run old version of b.
+ %%c:l(b),
+ check_bstate("third", []),
+ false = code:purge(b),
+ check_bstate("third", []),
+ {module,b} = code:load_file(b),
+ check_bstate("third", [ThirdBB]),
+
+ %% Let supervisor restart bb yet another time
+ S4 = [point_of_no_return,
+ {remove, {b, brutal_purge, soft_purge}}],
+ {ok, HopefullyEmpty} = release_handler_1:eval_script(S4),
+ ok = wait_for(bb),
+ FourthBB = whereis(bb),
+
+ case HopefullyEmpty of
+ [{b, soft_purge}] ->
+ %% The process managed to start between purge and delete
+ check_bstate("fourth", [FourthBB]);
+ [] ->
+ %% The process started after delete
+ check_bstate("fourth", [])
+ end,
+
+ application:stop(c),
+ check_bstate("no", []),
+ ok.
+
+instructions(cleanup,Conf) ->
+ application:stop(c),
+ really_del_code([aa,b,c_sup]),
+ code:del_path(filename:join(?config(data_dir,Conf), "c")),
+ ok.
+
+really_del_code(Mods) ->
+ lists:foreach(fun(Mod) ->
+ code:purge(Mod), % remove old code
+ code:delete(Mod),% make current code old
+ code:purge(Mod) % remove old code
+ end,
+ Mods).
+
+check_bstate(Slogan,ExpectedProcs) ->
+ BB = whereis(bb),
+ ActualProcs = lists:sort([P || P <- processes(),
+ erlang:check_process_code(P, b)]),
+ ExpectedProcs2 = lists:sort(ExpectedProcs),
+ ?t:format("check_bstate:~n~p~n~p~n",
+ [{"bb process", Slogan, BB},
+ {"Processes running old b code", ActualProcs}]),
+ if
+ Slogan =:= "no", BB =/= undefined ->
+ ?t:fail("instructions failed; process bb is running");
+ Slogan =/= "no", BB =:= undefined ->
+ ?t:fail("instructions failed; process bb is not running");
+ ExpectedProcs2 =:= [], ActualProcs =/= ExpectedProcs2 ->
+ ?t:fail("instructions failed; old b processes are running");
+ ActualProcs =/= ExpectedProcs2 ->
+ ?t:fail("instructions failed; wrong number of old b processes are running");
+ true ->
+ ok
+ end.
+
+wait_for(Name) ->
+ case whereis(Name) of
+ undefined ->
+ timer:sleep(100),
+ wait_for(Name);
+ Pid when is_pid(Pid) ->
+ ok
+ end.
+
+no_cc() ->
+ case whereis(cc) of
+ Pid when is_pid(Pid) -> ?t:fail("cc not stopped");
+ _ -> ok
+ end.
+
+
+
+%%%-----------------------------------------------------------------
+%%% Testing of reported bugs and other tickets.
+%%%-----------------------------------------------------------------
+
+%%-----------------------------------------------------------------
+%% release_handler_1:get_supervised_procs/0 test
+%%-----------------------------------------------------------------
+supervisor_which_children_timeout(Conf) ->
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"supervisor_which_children_timeout"),
+ DataDir = ?config(data_dir,Conf),
+ LibDir = filename:join([DataDir,release_handler_timeouts]),
+
+ Rel1 = create_and_install_fake_first_release(Dir,[{dummy,"0.1",LibDir}]),
+
+ {ok, Node} = t_start_node(supervisor_which_children_timeout, Rel1, []),
+ Proc = rpc:call(Node, erlang, whereis, [dummy_sup_2]),
+ ok = rpc:call(Node, sys, suspend, [Proc]),
+ Result = {badrpc, {'EXIT', {suspended_supervisor, _}}} =
+ rpc:call(Node, release_handler_1, get_supervised_procs, []),
+ ?t:format("release_handler_1:get_supervised_procs/0: ~p~n", [Result]),
+
+ ok.
+
+supervisor_which_children_timeout(cleanup, Conf) ->
+ stop_node(node_name(supervisor_which_children_timeout)).
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-2740
+%% Slogan: vsn not numeric doesn't work so good in release_handling
+%%-----------------------------------------------------------------
+%% Test vsn.
+otp_2740(Conf) ->
+ DataDir = ?config(data_dir, Conf),
+ Dir = filename:join(DataDir, "otp_2740"),
+ true = code:add_path(Dir),
+
+ {module, vsn_numeric} = c:l(vsn_numeric),
+ {module, vsn_tuple} = c:l(vsn_tuple),
+ {module, vsn_list} = c:l(vsn_list),
+ {module, vsn_atom} = c:l(vsn_atom),
+ {module, vsn_string} = c:l(vsn_string),
+
+ 231894 = release_handler_1:get_current_vsn(vsn_numeric),
+ {tuple,["of",terms]} = release_handler_1:get_current_vsn(vsn_tuple),
+ [list,"of",{some,terms}] = release_handler_1:get_current_vsn(vsn_list),
+ atom = release_handler_1:get_current_vsn(vsn_atom),
+ "a string" = release_handler_1:get_current_vsn(vsn_string),
+
+ true = code:del_path(Dir),
+ ok.
+
+%%-----------------------------------------------------------------
+%% Ticket: OTP-2760
+%% Slogan: when an application is removed from a node it is not unloaded
+%%-----------------------------------------------------------------
+%% Test that when an application is removed from a node it is also unloaded.
+otp_2760(Conf) ->
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"otp_2760"),
+ DataDir = ?config(data_dir,Conf),
+ LibDir = filename:join([DataDir,app1_app2,lib1]),
+
+ Rel1 = create_and_install_fake_first_release(Dir,[{app1,"1.0",LibDir}]),
+ Rel2 = create_fake_upgrade_release(Dir,"after",[],{[Rel1],[Rel1],[LibDir]}),
+ Rel2Dir = filename:dirname(Rel2),
+
+ %% Start a node with Rel1.boot and check that the app1 module is loaded
+ {ok, Node} = t_start_node(otp_2760, Rel1, []),
+ {file, _} = rpc:call(Node, code, is_loaded, [app1]),
+
+ %% Execute the relup script and check that app1 is unloaded
+ {ok, [{"after", [{_Rel1Vsn, _Descr, Script}], _}]} =
+ file:consult(filename:join(Rel2Dir, "relup")),
+ {ok, []} = rpc:call(Node, release_handler_1, eval_script, [Script]),
+ false = rpc:call(Node, code, is_loaded, [app1]),
+
+ ok.
+
+otp_2760(cleanup,_Conf) ->
+ stop_node(node_name(otp_2760)).
+
+
+%% Test upgrade using other filesystem than the defined in OTP and
+%% option {update_paths, true}
+otp_5761(Conf) when is_list(Conf) ->
+
+ %% In the following test case, the release upgrade is somewhat
+ %% simplified (since it is not this procedure in itself we want to
+ %% test, but that application code directories are set correctly.)
+ %% Existing Erlang release is used as base, instead of creating
+ %% a new one.
+
+ %% Set some paths
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"otp_5761"),
+ RelDir = filename:join(?config(data_dir, Conf), "app1_app2"),
+ LibDir1 = filename:join(RelDir, "lib1"),
+ LibDir2 = filename:join(RelDir, "lib2"),
+
+ %% Create the releases
+ Rel1 = create_and_install_fake_first_release(Dir,
+ [{app1,"1.0",LibDir1},
+ {app2,"1.0",LibDir1}]),
+ Rel2 = create_fake_upgrade_release(Dir,
+ "2",
+ [{app1,"2.0",LibDir2},
+ {app2,"1.0",LibDir2}],
+ {[Rel1],[Rel1],[LibDir1]}),
+ Rel1Dir = filename:dirname(Rel1),
+ Rel2Dir = filename:dirname(Rel2),
+
+ %% Start a slave node
+ {ok, Node} = t_start_node(otp_5761, Rel1, filename:join(Rel1Dir,"sys.config")),
+
+ %% Bind some variable names that will be used in patternmatching below
+ App11Dir = filename:join([LibDir1, "app1-1.0"]),
+ App12Dir = filename:join([LibDir2, "app1-2.0"]),
+ App2aDir = filename:join([LibDir1, "app2-1.0"]),
+ App2bDir = filename:join([LibDir2, "app2-1.0"]),
+
+ %% Make sure correct code paths are used
+ App11Dir = rpc:call(Node, code, lib_dir, [app1]),
+ App2aDir = rpc:call(Node, code, lib_dir, [app2]),
+
+ %% Unpack rel2 (make sure it does not work if an AppDir is bad)
+ LibDir3 = filename:join(RelDir, "lib3"),
+ {error, {no_such_directory, _}} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", [{app1,"2.0",LibDir2}, {app2,"1.0",LibDir3}]]),
+ {ok, RelVsn2} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", [{app1,"2.0",LibDir2}, {app2,"1.0",LibDir2}]]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "relup")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "start.boot")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "sys.config")]),
+
+ %% Install RelVsn2 without {update_paths, true} option
+ {ok, RelVsn1, []} =
+ rpc:call(Node, release_handler, install_release, [RelVsn2]),
+ App12Dir = rpc:call(Node, code, lib_dir, [app1]),
+ App2aDir = rpc:call(Node, code, lib_dir, [app2]),
+
+ %% Install RelVsn1 again
+ {ok, RelVsn1, []} =
+ rpc:call(Node, release_handler, install_release, [RelVsn1]),
+
+ %% Install RelVsn2 with {update_paths, true} option
+ {ok, RelVsn1, []} =
+ rpc:call(Node, release_handler, install_release,
+ [RelVsn2, [{update_paths, true}]]),
+ App12Dir = rpc:call(Node, code, lib_dir, [app1]),
+ App2bDir = rpc:call(Node, code, lib_dir, [app2]),
+
+ %% Install RelVsn1 again
+ {ok, RelVsn1, []} =
+ rpc:call(Node, release_handler, install_release,
+ [RelVsn1, [{update_paths, true}]]),
+ App11Dir = rpc:call(Node, code, lib_dir, [app1]),
+ App2aDir = rpc:call(Node, code, lib_dir, [app2]),
+
+ ok.
+
+otp_5761(cleanup,_Conf) ->
+ stop_node(node_name(otp_5761)).
+
+
+%% When a new version of an application is added, but no module is
+%% changed - the path was not updated - i.e. code:priv_dir would point
+%% to the old location.
+otp_9402(Conf) when is_list(Conf) ->
+ %% Set some paths
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"otp_9402"),
+ LibDir = filename:join(?config(data_dir, Conf), "lib"),
+
+ %% Create the releases
+ Rel1 = create_and_install_fake_first_release(Dir,
+ [{a,"1.1",LibDir}]),
+ Rel2 = create_fake_upgrade_release(Dir,
+ "2",
+ [{a,"1.2",LibDir}],
+ {[Rel1],[Rel1],[LibDir]}),
+ Rel1Dir = filename:dirname(Rel1),
+ Rel2Dir = filename:dirname(Rel2),
+
+ %% Start a slave node
+ {ok, Node} = t_start_node(otp_9402, Rel1, filename:join(Rel1Dir,"sys.config")),
+
+ %% Check path
+ Dir1 = filename:join([LibDir, "a-1.1"]),
+ Dir1 = rpc:call(Node, code, lib_dir, [a]),
+ ABeam = rpc:call(Node, code, which, [a]),
+
+ %% Install second release, with no changed modules
+ {ok, RelVsn2} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", [{a,"1.2",LibDir}]]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "relup")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "start.boot")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "sys.config")]),
+
+ {ok, RelVsn1, []} =
+ rpc:call(Node, release_handler, install_release, [RelVsn2]),
+
+ %% Check path
+ Dir2 = filename:join([LibDir, "a-1.2"]),
+ Dir2 = rpc:call(Node, code, lib_dir, [a]),
+ APrivDir2 = rpc:call(Node, code, priv_dir, [a]),
+ true = filelib:is_regular(filename:join(APrivDir2,"file")),
+
+ %% Just to make sure no modules have been re-loaded
+ ABeam = rpc:call(Node, code, which, [a]),
+
+ %% Install RelVsn1 again
+ {ok, _OtherVsn, []} =
+ rpc:call(Node, release_handler, install_release, [RelVsn1]),
+
+ %% Check path
+ Dir1 = rpc:call(Node, code, lib_dir, [a]),
+ APrivDir1 = rpc:call(Node, code, priv_dir, [a]),
+ false = filelib:is_regular(filename:join(APrivDir1,"file")),
+
+ %% Just to make sure no modules have been re-loaded
+ ABeam = rpc:call(Node, code, which, [a]),
+
+ ok.
+
+otp_9402(cleanup,_Conf) ->
+ stop_node(node_name(otp_9402)).
+
+
+%% When a module is deleted in an appup instruction, the upgrade
+%% failed if the module was not loaded.
+otp_9417(Conf) when is_list(Conf) ->
+ %% Set some paths
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"otp_9417"),
+ LibDir = filename:join(?config(data_dir, Conf), "lib"),
+
+ %% Create the releases
+ Rel1 = create_and_install_fake_first_release(Dir,
+ [{b,"1.0",LibDir}]),
+ Rel2 = create_fake_upgrade_release(Dir,
+ "2",
+ [{b,"2.0",LibDir}],
+ {[Rel1],[Rel1],[LibDir]}),
+ Rel1Dir = filename:dirname(Rel1),
+ Rel2Dir = filename:dirname(Rel2),
+
+ %% Start a slave node
+ {ok, Node} = t_start_node(otp_9417, Rel1, filename:join(Rel1Dir,"sys.config")),
+
+ %% Check paths
+ Dir1 = filename:join([LibDir, "b-1.0"]),
+ Dir1 = rpc:call(Node, code, lib_dir, [b]),
+ BLibBeam = filename:join([Dir1,"ebin","b_lib.beam"]),
+ BLibBeam = rpc:call(Node,code,which,[b_lib]),
+ false = rpc:call(Node,code,is_loaded,[b_lib]),
+ false = rpc:call(Node,code,is_loaded,[b_server]),
+
+ %% Install second release, which removes b_lib module
+ {ok, RelVsn2} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", [{b,"2.0",LibDir}]]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "relup")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "start.boot")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "sys.config")]),
+
+ {ok, _RelVsn1, []} =
+ rpc:call(Node, release_handler, install_release, [RelVsn2]),
+
+ %% Check that the module does no longer exist
+ false = rpc:call(Node, code, is_loaded, [b_lib]),
+ non_existing = rpc:call(Node, code, which, [b_lib]),
+
+ %% And check some paths
+ Dir2 = filename:join([LibDir, "b-2.0"]),
+ Dir2 = rpc:call(Node, code, lib_dir, [b]),
+ BServerBeam = filename:join([Dir2,"ebin","b_server.beam"]),
+ {file,BServerBeam} = rpc:call(Node,code,is_loaded,[b_server]),
+ ok.
+
+otp_9417(cleanup,_Conf) ->
+ stop_node(node_name(otp_9417)).
+
+
+%% OTP-9395 - performance problems when there are MANY processes
+%% Test that the procedure of checking for old code before an upgrade
+%% can be started is "very much faster" when there is no old code in
+%% the system.
+otp_9395_check_old_code(Conf) when is_list(Conf) ->
+
+ NProcs = 1000,
+ MPath = filename:join([?config(data_dir,Conf),"lib","many_mods-1.0","ebin"]),
+ code:add_path(MPath),
+
+ %% Start NProc processes, each referencing each module
+ {Modules,Pids} = m:start(NProcs),
+
+ %% Load each module again in order to get old code
+ [code:load_file(Mod) || Mod <- Modules],
+ true = erlang:check_old_code(m10),
+
+ S = [point_of_no_return |
+ [{remove,{M,soft_purge,soft_purge}} || M <- Modules]],
+
+ %% Do the old code check, then purge, and redo
+ {T1,{ok,PurgeMods}} = timer:tc(release_handler_1,check_script,[S,[]]),
+ true = (lists:sort(PurgeMods) == lists:sort(Modules)),
+ [code:purge(M) || M <- PurgeMods],
+ {T2,{ok,[]}} = timer:tc(release_handler_1,check_script,[S,[]]),
+
+ %% Cleanup
+ lists:foreach(fun(Pid) -> Pid ! stop end, Pids),
+ lists:foreach(fun(Mod) -> code:purge(Mod),
+ code:delete(Mod),
+ code:purge(Mod)
+ end, Modules),
+ code:del_path(MPath),
+
+ %% Test that second run was much faster than the first
+ if T2 > 0 ->
+ X = T1/T2,
+ ct:log("~p procs, ~p mods -> ~n"
+ "\tWith old code: ~.2f sec~n"
+ "\tAfter purge: ~.2f sec~n"
+ "\tT1/T2: ~.2f",
+ [NProcs,length(Modules),T1/1000000,T2/1000000,X]),
+ if X < 1000 ->
+ ct:fail({not_enough_improvement_after_purge,round(X)});
+ true ->
+ ok
+ end;
+ T1 > 0 -> %% Means T1/T2 = infinite
+ ok;
+ true ->
+ ct:fail({unexpected_values,T1,T2})
+ end,
+ ok.
+
+
+%% OTP-9395 - performance problems when there are MANY processes
+%% Added option 'purge' to check_install_release
+otp_9395_check_and_purge(Conf) when is_list(Conf) ->
+ %% Set some paths
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"otp_9395_check_and_purge"),
+ LibDir = filename:join(?config(data_dir, Conf), "lib"),
+
+ %% Create the releases
+ Rel1 = create_and_install_fake_first_release(Dir,
+ [{b,"1.0",LibDir}]),
+ Rel2 = create_fake_upgrade_release(Dir,
+ "2",
+ [{b,"2.0",LibDir}],
+ {[Rel1],[Rel1],[LibDir]}),
+ Rel1Dir = filename:dirname(Rel1),
+ Rel2Dir = filename:dirname(Rel2),
+
+ %% Start a slave node
+ {ok, Node} = t_start_node(otp_9395_check_and_purge, Rel1,
+ filename:join(Rel1Dir,"sys.config")),
+
+ %% Make sure there is old code for b_lib and b_server
+ rpc:call(Node,code,load_file,[b_lib]),
+ rpc:call(Node,code,load_file,[b_lib]),
+ rpc:call(Node,code,load_file,[b_server]),
+ rpc:call(Node,code,load_file,[b_server]),
+ true = rpc:call(Node,erlang,check_old_code,[b_lib]),
+ true = rpc:call(Node,erlang,check_old_code,[b_server]),
+
+ %% Unpack second release, which removes b_lib module and loads b_server
+ {ok, RelVsn2} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", [{b,"2.0",LibDir}]]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "relup")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "start.boot")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "sys.config")]),
+
+ %% Do check_install_release, and check that old code still exists
+ {ok, _RelVsn1, []} =
+ rpc:call(Node, release_handler, check_install_release, [RelVsn2]),
+ true = rpc:call(Node,erlang,check_old_code,[b_lib]),
+ true = rpc:call(Node,erlang,check_old_code,[b_server]),
+
+ %% Do check_install_release with option 'purge' and check that old
+ %% code is gone
+ {ok, _RelVsn1, []} =
+ rpc:call(Node, release_handler, check_install_release, [RelVsn2,[purge]]),
+ false = rpc:call(Node,erlang,check_old_code,[b_lib]),
+ false = rpc:call(Node,erlang,check_old_code,[b_server]),
+
+ ok.
+
+otp_9395_check_and_purge(cleanup,_Conf) ->
+ stop_node(node_name(otp_9395_check_and_purge)).
+
+
+%% OTP-9395 - performance problems when there are MANY processes
+%% Upgrade which updates many modules (brutal_purge)
+otp_9395_update_many_mods(Conf) when is_list(Conf) ->
+ %% Set some paths
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"otp_9395_update_many_mods"),
+ LibDir = filename:join(?config(data_dir, Conf), "lib"),
+
+ %% Create the releases
+ Rel1 = create_and_install_fake_first_release(Dir,
+ [{many_mods,"1.0",LibDir}]),
+ Rel2 = create_fake_upgrade_release(Dir,
+ "2",
+ [{many_mods,"1.1",LibDir}],
+ {[Rel1],[Rel1],[LibDir]}),
+ Rel1Dir = filename:dirname(Rel1),
+ Rel2Dir = filename:dirname(Rel2),
+
+ %% Start a slave node
+ {ok, Node} = t_start_node(otp_9395_update_many_mods, Rel1,
+ filename:join(Rel1Dir,"sys.config")),
+
+ %% Start a lot of processes on the new node, all with refs to each
+ %% module that will be updated
+ NProcs = 1000,
+ {Modules,Pids1} = rpc:call(Node,m,start,[NProcs]),
+
+ %% Then load modules in order to get old code
+ [rpc:call(Node,code,load_file,[Mod]) || Mod <- Modules],
+ true = rpc:call(Node,erlang,check_old_code,[m10]),
+
+ %% Unpack second release, which updates all mX modules
+ {ok, RelVsn2} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", [{many_mods,"1.1",LibDir}]]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "relup")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "start.boot")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "sys.config")]),
+
+ %% First, install release directly and check how much time it takes
+ {TInst0,{ok, _, []}} =
+ timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn2]]),
+ ct:log("install_release: ~.2f",[TInst0/1000000]),
+
+ %% Restore to old release, spawn processes again and load to get old code
+ {_,RelVsn1} = init:script_id(),
+ {_TInst1,{ok, _, []}} =
+ timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn1]]),
+% ct:log("install_release: ~.2f",[_TInst1/1000000]),
+
+ [exit(Pid,kill) || Pid <- Pids1],
+ {Modules,_Pids2} = rpc:call(Node,m,start,[NProcs]),
+ [rpc:call(Node,code,load_file,[Mod]) || Mod <- Modules],
+ true = rpc:call(Node,erlang,check_old_code,[m10]),
+
+ %% Run check_install_release with purge before install this time
+ {TCheck,{ok, _RelVsn1, []}} =
+ timer:tc(rpc,call,[Node, release_handler, check_install_release,
+ [RelVsn2,[purge]]]),
+ ct:log("check_install_release with purge: ~.2f",[TCheck/1000000]),
+
+ %% Finally install release after check and purge, and check that
+ %% this install was faster than the first.
+ {TInst2,{ok, _RelVsn1, []}} =
+ timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn2]]),
+ ct:log("install_release: ~.2f",[TInst2/1000000]),
+
+ true = (TInst2 < TInst0),
+
+ ok.
+
+otp_9395_update_many_mods(cleanup,_Conf) ->
+ stop_node(node_name(otp_9395_update_many_mods)).
+
+
+%% OTP-9395 - performance problems when there are MANY processes
+%% Upgrade which removes many modules (brutal_purge)
+otp_9395_rm_many_mods(Conf) when is_list(Conf) ->
+ %% Set some paths
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"otp_9395_rm_many_mods"),
+ LibDir = filename:join(?config(data_dir, Conf), "lib"),
+
+ %% Create the releases
+ Rel1 = create_and_install_fake_first_release(Dir,
+ [{many_mods,"1.0",LibDir}]),
+ Rel2 = create_fake_upgrade_release(Dir,
+ "2",
+ [{many_mods,"2.0",LibDir}],
+ {[Rel1],[Rel1],[LibDir]}),
+ Rel1Dir = filename:dirname(Rel1),
+ Rel2Dir = filename:dirname(Rel2),
+
+ %% Start a slave node
+ {ok, Node} = t_start_node(otp_9395_rm_many_mods, Rel1,
+ filename:join(Rel1Dir,"sys.config")),
+
+ %% Start a lot of processes on the new node, all with refs to each
+ %% module that will be updated
+ NProcs = 1000,
+ {Modules,Pids1} = rpc:call(Node,m,start,[NProcs]),
+
+ %% Then load modules in order to get old code
+ [rpc:call(Node,code,load_file,[Mod]) || Mod <- Modules],
+ true = rpc:call(Node,erlang,check_old_code,[m10]),
+
+ %% Unpack second release, which removes all mX modules
+ {ok, RelVsn2} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", [{many_mods,"2.0",LibDir}]]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "relup")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "start.boot")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "sys.config")]),
+
+ %% First, install release directly and check how much time it takes
+ {TInst0,{ok, _, []}} =
+ timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn2]]),
+ ct:log("install_release: ~.2f",[TInst0/1000000]),
+
+ %% Restore to old release, spawn processes again and load to get old code
+ {_,RelVsn1} = init:script_id(),
+ {_TInst1,{ok, _, []}} =
+ timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn1]]),
+% ct:log("install_release: ~.2f",[_TInst1/1000000]),
+
+ [exit(Pid,kill) || Pid <- Pids1],
+ {Modules,_Pids2} = rpc:call(Node,m,start,[NProcs]),
+ [rpc:call(Node,code,load_file,[Mod]) || Mod <- Modules],
+ true = rpc:call(Node,erlang,check_old_code,[m10]),
+
+ %% Run check_install_release with purge before install this time
+ {TCheck,{ok, _RelVsn1, []}} =
+ timer:tc(rpc,call,[Node, release_handler, check_install_release,
+ [RelVsn2,[purge]]]),
+ ct:log("check_install_release with purge: ~.2f",[TCheck/1000000]),
+
+ %% Finally install release after check and purge, and check that
+ %% this install was faster than the first.
+ {TInst2,{ok, _RelVsn1, []}} =
+ timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn2]]),
+ ct:log("install_release: ~.2f",[TInst2/1000000]),
+
+ true = (TInst2 =< TInst0),
+
+ ok.
+
+otp_9395_rm_many_mods(cleanup,_Conf) ->
+ stop_node(node_name(otp_9395_rm_many_mods)).
+
+
+
+%% Test upgrade and downgrade of applications
+eval_appup(Conf) when is_list(Conf) ->
+
+ %% OTP-6162
+ %% Create an ETS table which is updated by app1 if there is any
+ %% change made to the application configuration parameter 'var'
+ %% (see config_change/3 in myrel/lib1|2/app1-1|2.0/src/app1.erl)
+ ets:new(otp_6162, [set, public, named_table]),
+
+ %% Set some paths
+ RelDir = filename:join(?config(data_dir, Conf), "app1_app2"),
+ App11Dir = filename:join([RelDir, "lib1", "app1-1.0"]),
+ App12Dir = filename:join([RelDir, "lib2", "app1-2.0"]),
+ EbinDir = filename:join(App11Dir, "ebin"),
+
+ %% Start app1-1.0
+ code:add_patha(EbinDir),
+ ok = application:start(app1),
+ App11Dir = code:lib_dir(app1),
+ ok = gen_server:call(harry, error),
+
+ %% Upgrade to app1-2.0
+ {ok, []} = release_handler:upgrade_app(app1, App12Dir),
+ App12Dir = code:lib_dir(app1),
+ error = gen_server:call(harry, error),
+
+ %% OTP-6162
+ %% Value of config parameter 'var' should now be 'val2'
+ %% (see myrel/lib2/app1-2.0/ebin/app1.app)
+ [{var,val2}] = ets:lookup(otp_6162, var),
+
+ %% Downgrade to app1-1.0
+ {ok, []} = release_handler:downgrade_app(app1,"1.0",App11Dir),
+ App11Dir = code:lib_dir(app1),
+ ok = gen_server:call(harry, error),
+
+ %% OTP-6162
+ %% Value of config parameter 'var' should now be 'val1'
+ %% (see myrel/lib1/app1-1.0/ebin/app1.app)
+ [{var,val1}] = ets:lookup(otp_6162, var),
+
+ ok = application:stop(app1),
+ ok = application:unload(app1),
+
+ true = code:del_path(EbinDir),
+ ok.
+
+
+%% Test the example/target_system.erl module
+target_system(Conf) when is_list(Conf) ->
+ PrivDir = priv_dir(Conf),
+ DataDir = ?config(data_dir,Conf),
+
+ TargetCreateDir = filename:join([PrivDir,"target_system","create"]),
+ TargetInstallDir = filename:join([PrivDir,"target_system","install"]),
+
+ ok = filelib:ensure_dir(filename:join(TargetCreateDir,"xx")),
+ ok = filelib:ensure_dir(filename:join(TargetInstallDir,"xx")),
+
+
+ %% Create the .rel file
+ ErtsVsn = erlang:system_info(version),
+ RelName = filename:join(TargetCreateDir,"ts-1.0"),
+ RelFile = RelName++".rel",
+ RelVsn = "R1A",
+ create_rel_file(RelFile,RelName,RelVsn,ErtsVsn,[{a, "1.0"}]),
+
+ %% Build the target_system module
+ ExamplesEbin = filename:join([code:lib_dir(sasl),examples,ebin]),
+ TSPath =
+ case filelib:is_file(filename:join(ExamplesEbin,"target_system.beam")) of
+ true ->
+ ExamplesEbin;
+ false ->
+ {ok,_} =
+ compile:file(filename:join(DataDir,"target_system.erl"),
+ [{outdir,TargetCreateDir}]),
+ TargetCreateDir
+ end,
+ code:add_path(TSPath),
+
+ %% Create the release
+ target_system:create(RelName,[{path,[filename:join([DataDir,
+ lib,
+ "a-1.0",
+ ebin])]}]),
+
+ %% Install the release
+ target_system:install(RelName,TargetInstallDir),
+
+ code:del_path(TSPath),
+
+ %% Check that all files exist in installation
+ true = filelib:is_dir(filename:join(TargetInstallDir,"erts-"++ErtsVsn)),
+ LibDir = filename:join(TargetInstallDir,lib),
+ {ok,KernelVsn} = application:get_key(kernel,vsn),
+ {ok,StdlibVsn} = application:get_key(stdlib,vsn),
+ {ok,SaslVsn} = application:get_key(sasl,vsn),
+ true = filelib:is_dir(filename:join(LibDir,"kernel-"++KernelVsn)),
+ true = filelib:is_dir(filename:join(LibDir,"stdlib-"++StdlibVsn)),
+ true = filelib:is_dir(filename:join(LibDir,"sasl-"++SaslVsn)),
+ true = filelib:is_dir(filename:join(LibDir,"a-1.0")),
+ RelDir = filename:join(TargetInstallDir,releases),
+ true = filelib:is_regular(filename:join(RelDir,"RELEASES")),
+ true = filelib:is_regular(filename:join(RelDir,"start_erl.data")),
+ true = filelib:is_regular(filename:join(RelDir,
+ filename:basename(RelFile))),
+ true = filelib:is_dir(filename:join(RelDir,RelVsn)),
+ true = filelib:is_regular(filename:join([RelDir,RelVsn,"start.boot"])),
+ BinDir = filename:join(TargetInstallDir,bin),
+ true = filelib:is_regular(filename:join(BinDir,"start.boot")),
+ true = filelib:is_regular(filename:join(BinDir,erl)),
+ true = filelib:is_regular(filename:join(BinDir,start_erl)),
+ true = filelib:is_regular(filename:join(BinDir,start)),
+ true = filelib:is_regular(filename:join(BinDir,epmd)),
+ true = filelib:is_regular(filename:join(BinDir,run_erl)),
+ true = filelib:is_regular(filename:join(BinDir,to_erl)),
+
+ %% Check content of files
+ {ok,SED} = file:read_file(filename:join(RelDir,"start_erl.data")),
+ [ErtsVsn,RelVsn] = string:tokens(binary_to_list(SED),"\s\n"),
+ ok.
+
+
+
+%%%=================================================================
+%%% Testing global groups.
+%%%=================================================================
+
+%% This test case involves P1G and P1H with the sys.config as
+%% specified in gg_config/1. The test case checks that the global
+%% group information is correct before and after the upgrade and also
+%% after terminating one of the nodes. The flow is as follows:
+%% 1. Start all four nodes of global group gg1 with P1G
+%% 2. Terminate one of the nodes, and upgrade the others to P1H. P1H
+%% config adds to more nodes to the global group.
+%% 3. Start the two remaining nodes with P1H
+upgrade_gg(Conf) ->
+ [Gg1Sname,Gg2Sname,Gg3Sname,Gg4Sname,Gg5Sname,Gg6Sname] =
+ ?config(snames,Conf),
+
+ %% start gg1, gg3, gg4, gg5 and check that global group info is ok
+ Nodes1 = [Gg1,Gg3,Gg4,Gg5] =
+ start_nodes(Conf,[Gg1Sname,Gg3Sname,Gg4Sname,Gg5Sname],"upgrade_gg"),
+
+ %% Give some time to synch nodes, then check global group info.
+ timer:sleep(1000),
+ [check_gg_info(Node,Nodes1,[],Nodes1--[Node]) || Node <- Nodes1],
+
+ %% register a process on each of the nodes
+ ok = rpc:call(Gg1, installer, reg_proc, [reg1]),
+ ok = rpc:call(Gg3, installer, reg_proc, [reg3]),
+ ok = rpc:call(Gg4, installer, reg_proc, [reg4]),
+ ok = rpc:call(Gg5, installer, reg_proc, [reg5]),
+ are_names_reg_gg(Gg1, [reg1, reg3, reg4, reg5]),
+
+ %% Stop gg3, then upgrade gg1, gg4 and gg5 to P1H
+ ok = stop_nodes([Gg3]),
+
+ ok = install_release_changed_gg(Gg1,"P1H"),
+ ok = install_release_changed_gg(Gg4,"P1H"),
+ ok = install_release_changed_gg(Gg5,"P1H"),
+
+ %% Check global group info
+ Gg2 = node_name(Gg2Sname),
+ Gg6 = node_name(Gg6Sname),
+ Nodes2 = [Gg1,Gg4,Gg5],
+ [check_gg_info(Node,Nodes2,[Gg2,Gg6],Nodes2--[Node]) || Node <- Nodes2],
+
+ %% start gg2 and gg6
+ [Gg2,Gg6] = start_nodes(Conf,[Gg2Sname,Gg6Sname],"upgrade_gg start gg2/gg6"),
+
+ %% reg proc on each of the nodes
+ ok = rpc:call(Gg2, installer, reg_proc, [reg2]),
+ ok = rpc:call(Gg6, installer, reg_proc, [reg6]),
+ are_names_reg_gg(Gg1, [reg1, reg2, reg4, reg5, reg6]),
+
+ %% Check global group info
+ Nodes3 = [Gg1,Gg2,Gg4,Gg5,Gg6],
+ [check_gg_info(Node,Nodes3,[],Nodes3--[Node]) || Node <- Nodes3],
+
+ ok.
+
+upgrade_gg(cleanup,Config) ->
+ Snames = ?config(snames,Config),
+ NodeNames = [node_name(Sname) || Sname <- Snames],
+ ok = stop_nodes(NodeNames).
+
+
+
+
+%%%=================================================================
+%%% Misceleaneous functions
+%%%=================================================================
+stop_nodes(Nodes) ->
+ ?t:format("Stopping nodes: ~p~n",[Nodes]),
+ Running =
+ lists:foldl(fun(Node,Acc) ->
+ Now = now(),
+ stop_cover(Node),
+ case rpc:call(Node,installer,stop,[Now]) of
+ {badrpc,nodedown} ->
+ Acc;
+ Other ->
+ ?t:format("Stop ~p(~p): ~p~n",
+ [Node,Now,Other]),
+ [Node|Acc]
+ end
+ end, [], Nodes),
+ wait_nodes_down(Running).
+
+
+wait_nodes_down(Nodes) ->
+ ?t:format( "wait_nodes_down ~p:",[Nodes]),
+ wait_nodes_down(Nodes, 30).
+
+wait_nodes_down(Nodes, 0) ->
+ test_server:fail({error, {"could not kill nodes", Nodes}});
+wait_nodes_down(Nodes, N) ->
+ Fun = fun(Node, A) ->
+ case net_adm:ping(Node) of
+ pong ->
+ ?t:format( " net_adm:ping(~p) = pong", [Node]),
+ [Node|A];
+ pang ->
+ ?t:format( " net_adm:ping(~p) = pang", [Node]),
+ A
+ end
+ end,
+ Pang = lists:foldl(Fun, [], Nodes),
+ case Pang of
+ [] ->
+ ?t:format("",[]),
+ ok;
+ _ ->
+ timer:sleep(1000),
+ wait_nodes_down(Pang, N-1)
+ end.
+
+
+
+wait_nodes_up(Nodes, Tag) ->
+ wait_nodes_up(Nodes, Tag, []).
+
+wait_nodes_up(Nodes0, Tag, Apps) ->
+ ?t:format("wait_nodes_up(~p, ~p, ~p):",[Nodes0, Tag, Apps]),
+ Nodes = fix_nodes(Nodes0),
+ wait_nodes_up(Nodes, Tag, lists:umerge(Apps,[kernel,stdlib,sasl]), 30).
+
+fix_nodes([{Node,InitPid}|Nodes]) ->
+ [{Node,InitPid} | fix_nodes(Nodes)];
+fix_nodes([Node|Nodes]) ->
+ [{Node,fake_init_pid} | fix_nodes(Nodes)];
+fix_nodes([]) ->
+ [].
+
+wait_nodes_up(Nodes, Tag, Apps, 0) ->
+ test_server:fail({error, {"nodes not started", Nodes, Tag, Apps}});
+wait_nodes_up(Nodes, Tag, Apps, N) ->
+ Fun =
+ fun(NodeInfo={Node,OldInitPid}, A) ->
+ case rpc:call(Node, application, which_applications, []) of
+ {badrpc, nodedown} ->
+ ?t:format( " ~p = {badarg, nodedown}",[Node]),
+ [NodeInfo | A];
+ List when is_list(List)->
+ ?t:format( " ~p = [~p]",[Node, List]),
+ case lists:all(fun(App) ->
+ lists:keymember(App,1,List)
+ end, Apps) of
+ true ->
+ case rpc:call(Node,erlang,whereis,[init]) of
+ OldInitPid ->
+ [NodeInfo | A];
+ _ ->
+ start_cover(Node),
+ A
+ end;
+ false ->
+ [NodeInfo | A]
+ end
+ end
+ end,
+ Pang = lists:foldl(Fun,[],Nodes),
+ case Pang of
+ [] ->
+ ?t:format("",[]),
+ ok;
+ _ ->
+ timer:sleep(1000),
+ wait_nodes_up(Pang, Tag, Apps, N-1)
+ end.
+
+
+
+
+are_names_reg_gg(Node, Names) ->
+ ?t:format( "are_names_reg_gg ~p~n",[Names]),
+ are_names_reg_gg(Node, Names, 30).
+
+are_names_reg_gg(Node, Names, N) ->
+ case lists:sort(rpc:call(Node, global, registered_names, [])) of
+ Names ->
+ ok;
+ Regs when N > 0 ->
+ timer:sleep(1000),
+ ?t:format( "are_names_reg_gg Regs ~p~n",[Regs]),
+ are_names_reg_gg(Node, Names, N-1);
+ Regs ->
+ ?t:fail({error, {"Names not registered",
+ {{"should :", Names},
+ {"was :", Regs}}}})
+ end.
+
+
+
+t_start_node(Name, Boot, SysConfig) ->
+ Args =
+ case Boot of
+ [] -> [];
+ _ -> " -boot " ++ Boot
+ end ++
+ case SysConfig of
+ [] -> [];
+ _ -> " -config " ++ SysConfig
+ end,
+ test_server:start_node(Name, slave, [{args, Args}]).
+
+stop_node(Node) ->
+ ?t:stop_node(Node).
+
+
+copy_client(Conf,Master,Sname,Client) ->
+ io:format("copy_client(Conf)"),
+
+ DataDir = ?config(data_dir, Conf),
+ MasterDir = filename:join(priv_dir(Conf),Master),
+
+ {ClientArgs,RelCliDir} = rh_test_lib:get_client_args(Client,Sname,MasterDir,
+ node_name(Master)),
+
+ Cli = filename:join([MasterDir, RelCliDir]),
+ ok = filelib:ensure_dir(filename:join([Cli,"bin","."])),
+ ok = filelib:ensure_dir(filename:join([Cli,"releases","."])),
+ ok = filelib:ensure_dir(filename:join([Cli,"log","."])),
+
+ P1GOrig = filename:join([MasterDir, "releases", "P1G"]),
+ ok = copy_tree(Conf,P1GOrig,filename:join(Cli,"releases")),
+
+ case os:type() of
+ {unix,_} ->
+ ok = subst_file(filename:join([DataDir, "start_client"]),
+ filename:join([Cli,"bin","start"]),
+ [{"ROOT",MasterDir},
+ {"CLIENTARGS",ClientArgs}],
+ [{chmod,8#0755}]);
+ _ ->
+ ok
+ end,
+
+ StartErlData = filename:join([MasterDir, "releases", "start_erl.data"]),
+ CliRelDir = filename:join([Cli, "releases"]),
+ copy_file(StartErlData, CliRelDir),
+
+ RR = filename:join([MasterDir, "releases", "RELEASES"]),
+ copy_file(RR, CliRelDir),
+
+ ok.
+
+
+delete_release(Conf) ->
+ PrivDir = priv_dir(Conf),
+
+ {ok, OrigWd} = file:get_cwd(),
+
+ ok = file:set_cwd(PrivDir),
+ ?t:format("======== current dir ~p~n",[PrivDir]),
+ {ok, Dirs} = file:list_dir(PrivDir),
+ ?t:format("======== deleting ~p~n",[Dirs]),
+
+ ok = delete_release_os(Dirs--["save"]),
+ {ok,Remaining} = file:list_dir(PrivDir),
+ ?t:format("======== remaining ~p~n",[Remaining]),
+
+ case Remaining of
+ [] ->
+ ok;
+ _ ->
+ delete_release_os(Remaining),
+ Remaining2 = file:list_dir(PrivDir),
+ ?t:format("======== remaining after second try ~p~n",[Remaining2])
+ end,
+
+ ok = file:set_cwd(OrigWd),
+ ok.
+
+
+delete_release_os(Dirs) ->
+ case os:type() of
+ {unix, _} ->
+ delete_release_unix(Dirs);
+ {win32, _} ->
+ delete_release_win32(Dirs);
+ Os ->
+ test_server:fail({error, {not_yet_implemented_os, Os}})
+ end.
+
+
+delete_release_unix([]) ->
+ ok;
+delete_release_unix(["save"|Dirs]) ->
+ delete_release_unix(Dirs);
+delete_release_unix([Dir|Dirs]) ->
+ Rm = string:concat("rm -rf ", Dir),
+ ?t:format("============== COMMAND ~p~n",[Rm]),
+ case file:list_dir(Dir) of
+ {error, enotdir} ->
+ ok;
+ X ->
+ ?t:format("------- Dir ~p~n ~p~n",[Dir, X])
+ end,
+ case os:cmd(Rm) of
+ [] ->
+ ?t:format("------- Result of COMMAND ~p~n",[ok]);
+ Y ->
+ ?t:format("!!!!!!! delete ERROR Dir ~p Error ~p~n",[Dir, Y]),
+ ?t:format("------- ls -al ~p~n",[os:cmd("ls -al " ++ Dir)])
+ end,
+
+ delete_release_unix(Dirs).
+
+delete_release_win32([]) ->
+ ok;
+delete_release_win32(["save"|Dirs]) ->
+ delete_release_win32(Dirs);
+delete_release_win32([Dir|Dirs]) ->
+ Rm =
+ case filelib:is_dir(Dir) of
+ true ->
+ string:concat("rmdir /s /q ", Dir);
+ false ->
+ string:concat("del /q ", Dir)
+ end,
+ ?t:format("============== COMMAND ~p~n",[Rm]),
+ [] = os:cmd(Rm),
+ delete_release_win32(Dirs).
+
+
+node_name(Sname) when is_atom(Sname) ->
+ {ok,Host} = inet:gethostname(),
+ list_to_atom(atom_to_list(Sname) ++ "@" ++ Host).
+
+copy_file(Src, Dest) ->
+ copy_file(Src, Dest, []).
+copy_file(Src, Dest, Opts) ->
+ case file:copy(Src,Dest) of
+ {ok,_} ->
+ preserve(Src,Dest,Opts),
+ chmod(Dest,Opts),
+ ok;
+ {error,eisdir} ->
+ NewDest = filename:join(Dest, filename:basename(Src)),
+ case file:copy(Src,NewDest) of
+ {ok,_} ->
+ preserve(Src,NewDest,Opts),
+ chmod(NewDest,Opts);
+ {error,Reason} ->
+ copy_error(Src,Dest,Reason)
+ end;
+ {error,Reason} ->
+ copy_error(Src,Dest,Reason)
+ end.
+
+preserve(Src,Dest,Opts) ->
+ case lists:member(preserve, Opts) of
+ true ->
+ {ok, FileInfo} = file:read_file_info(Src),
+ ok = file:write_file_info(Dest, FileInfo);
+ false ->
+ ok
+ end.
+
+chmod(Dest,Opts) ->
+ case lists:keyfind(chmod,1,Opts) of
+ {chmod,Mode} ->
+ ok = file:change_mode(Dest, Mode);
+ false ->
+ ok
+ end.
+
+
+
+copy_error(Src, Dest, Reason) ->
+ io:format("Copy ~s to ~s failed: ~s\n",
+ [Src,Dest,file:format_error(Reason)]),
+ ?t:fail(file_copy_failed).
+
+copy_tree(Conf, Src, DestDir) ->
+ case catch copy_tree(Conf, Src, filename:basename(Src), DestDir) of
+ ok ->
+ ok;
+ {'EXIT', {{badmatch,Error},_Stack}} ->
+ %% Most probably, an erl_tar call has failed.
+ %% Known to happen on some platforms (symbolic_link_too_long)
+ Error;
+ {'EXIT', Reason} ->
+ {error, Reason}
+ end.
+
+copy_tree(Conf, Src, NewName, DestDir) ->
+ PrivDir = priv_dir(Conf),
+ TempTarName = filename:join(PrivDir, "temp_tar_file.tar"),
+ %% Not compressing tar file here since that would increase test
+ %% suite time by almost 100%, and the tar file is deleted
+ %% imediately anyway.
+ {ok,Tar} = erl_tar:open(TempTarName, [write]),
+ ok = erl_tar:add(Tar, Src, NewName, []),
+ ok = erl_tar:close(Tar),
+ ok = erl_tar:extract(TempTarName, [{cwd,DestDir}]),
+ ok = file:delete(TempTarName),
+ ok.
+
+%% subst_file(Src, Dest, Vars)
+%% Src = Dest = string(), filename and path
+%% Vars = [{Var, Val}]
+%% Var = Val = string()
+%% Substitute all occurrences of %Var% for Val in Src, using the list
+%% of variables in Vars. Result is written to Dest.
+%%
+subst_file(Src, Dest, Vars) ->
+ subst_file(Src, Dest, Vars, []).
+subst_file(Src, Dest, Vars, Opts) ->
+ {ok, Bin} = file:read_file(Src),
+ Conts = binary_to_list(Bin),
+ NConts = subst(Conts, Vars),
+ ok = file:write_file(Dest, NConts),
+ preserve(Src,Dest,Opts),
+ chmod(Dest,Opts).
+
+subst(Str, Vars) ->
+ subst(Str, Vars, []).
+
+subst([$%, C| Rest], Vars, Result) when $A =< C, C =< $Z ->
+ subst_var([C| Rest], Vars, Result, []);
+subst([$%, C| Rest], Vars, Result) when $a =< C, C =< $z ->
+ subst_var([C| Rest], Vars, Result, []);
+subst([$%, C| Rest], Vars, Result) when C == $_ ->
+ subst_var([C| Rest], Vars, Result, []);
+subst([C| Rest], Vars, Result) ->
+ subst(Rest, Vars, [C| Result]);
+subst([], _Vars, Result) ->
+ lists:reverse(Result).
+
+subst_var([$%| Rest], Vars, Result, VarAcc) ->
+ Key = lists:reverse(VarAcc),
+ case lists:keysearch(Key, 1, Vars) of
+ {value, {Key, Value}} ->
+ subst(Rest, Vars, lists:reverse(Value, Result));
+ false ->
+ subst(Rest, Vars, [$%| VarAcc ++ [$%| Result]])
+ end;
+subst_var([C| Rest], Vars, Result, VarAcc) ->
+ subst_var(Rest, Vars, Result, [C| VarAcc]);
+subst_var([], Vars, Result, VarAcc) ->
+ subst([], Vars, [VarAcc ++ [$%| Result]]).
+
+
+priv_dir(Conf) ->
+%% filename:absname(?config(priv_dir, Conf)). % Get rid of trailing slash
+ %% Due to problem with long paths on windows => creating a new
+ %% priv_dir under data_dir
+ Dir = filename:absname(filename:join(?config(data_dir, Conf),priv_dir)),
+ filelib:ensure_dir(filename:join(Dir,"*")),
+ Dir.
+
+latest_version(Dir) ->
+ List = filelib:wildcard(Dir ++ "*"),
+ lists:last(lists:sort(List)).
+
+%% A printer process which receives messages from other nodes and
+%% prints in the log
+reg_print_proc() ->
+ catch unregister(rh_print),
+ Pid = spawn_link(?MODULE, rh_print, []),
+ register(rh_print, Pid),
+ ok.
+
+rh_print() ->
+ receive
+ {print, {Module,Line}, [H|T]} ->
+ ?t:format("=== ~p:~p - ~p",[Module,Line,H]),
+ lists:foreach(fun(Term) -> ?t:format(" ~p",[Term]) end, T),
+ ?t:format("",[]),
+ rh_print();
+ kill ->
+ exit(normal)
+ end.
+
+stop_print_proc() ->
+ case whereis(rh_print) of %%removes the printer process
+ undefined ->
+ ok;
+ Pid when is_pid(Pid) ->
+ rh_print ! kill
+ end.
+
+%% Create the first target release, vsn P1G. This release is used for
+%% all test cases in {group,release}
+create_p1g(Conf,Sname) ->
+ do_create_p1g(Conf,filename:join(priv_dir(Conf),Sname)).
+
+do_create_p1g(Conf,TargetDir) ->
+ PrivDir = priv_dir(Conf),
+ DataDir = ?config(data_dir,Conf),
+ ErtsVsn = "4.4",
+ ErtsDir = "erts-"++ErtsVsn,
+
+ %% Create dirs
+ BinDir = filename:join(TargetDir,bin),
+ ReleasesDir = filename:join(TargetDir,releases),
+ LogDir = filename:join(TargetDir,log),
+ ok = filelib:ensure_dir(filename:join(BinDir,"*")),
+ ok = filelib:ensure_dir(filename:join(ReleasesDir,"*")),
+ ok = filelib:ensure_dir(filename:join(LogDir,"*")),
+
+ %% Copy stuff
+ ErtsLatest = latest_version(filename:join(code:root_dir(),"erts")),
+ ok = copy_tree(Conf, ErtsLatest, ErtsDir, TargetDir),
+ ErtsBinDir = filename:join([TargetDir,ErtsDir,bin]),
+
+ case os:type() of
+ {unix, _} ->
+ copy_file(filename:join([ErtsBinDir, "epmd"]), BinDir, [preserve]),
+ copy_file(filename:join([ErtsBinDir, "run_erl"]), BinDir, [preserve]),
+ copy_file(filename:join([ErtsBinDir, "to_erl"]), BinDir, [preserve]),
+
+ %% Create the start_erl shell script
+ ok = subst_file(filename:join([ErtsBinDir,"start_erl.src"]),
+ filename:join([BinDir,"start_erl"]),
+ [{"EMU","beam"}],
+ [{chmod,8#0755}]);
+ {win32,_} ->
+ %% Add a batch file to use as HEART_COMMAND
+ ok = copy_file(filename:join(DataDir, "heart_restart.bat"),
+ ErtsBinDir,[preserve])
+ end,
+
+ copy_file(filename:join(DataDir, "../installer.beam"),
+ filename:join([DataDir,lib,"installer-1.0",ebin])),
+ copy_file(filename:join(DataDir, "../rh_test_lib.beam"),
+ filename:join([DataDir,lib,"installer-1.0",ebin])),
+
+ %% Create .rel, .script and .boot files
+ RelName = "rel0",
+ RelVsn = "P1G",
+ RelDir = filename:join(PrivDir,RelName),
+ RelFileName = filename:join(RelDir,RelName),
+ RelFile = RelFileName ++ ".rel",
+ ok = filelib:ensure_dir(RelFile),
+ LibPath = filename:join([DataDir,lib,"*",ebin]),
+
+ TarFile = create_basic_release(Conf, RelFile, RelVsn, {ErtsVsn,false},
+ LibPath, [], [], [], []),
+
+ %% Extract tar file in target directory (i.e. same directory as erts etc.)
+ ok = erl_tar:extract(TarFile, [{cwd, TargetDir}, compressed]),
+
+ %% Create start_erl.data
+ StartErlDataFile = filename:join([ReleasesDir, "start_erl.data"]),
+ StartErlData = io_lib:fwrite("~s ~s~n", [ErtsVsn, RelVsn]),
+ ok = file:write_file(StartErlDataFile, StartErlData),
+
+ %% Create RELEASES
+ ok = release_handler:create_RELEASES(TargetDir,ReleasesDir,RelFile,[]),
+
+ ok.
+
+%% Create version P1H - which is P1G + a-1.0
+%% Must have run create_p1g first!!
+create_p1h(Conf) ->
+ create_upgrade_release(Conf,"rel1","P1H",{"4.4",false},[{a,"1.0"}],
+ [{a,[{key2,val2}]}],{"rel0",[new_appl]}).
+
+%% Create version P1I - which is P1H, but with application a upgraded to a-1.1
+%% Must have run create_p1h first!!
+create_p1i(Conf) ->
+ create_upgrade_release(Conf,"rel2","P1I",{"4.4",false},[{a,"1.1"}],
+ [{a,[{key2,newval2}]}],
+ {"rel1",[{extra,gott}]}).
+
+%% Create version P2A - which is P1I, but with erts-<latest>
+%% Must have run create_p1i first!!
+create_p2a(Conf) ->
+ ErtsVsn = erlang:system_info(version),
+ create_upgrade_release(Conf,"rel3","P2A",{ErtsVsn,code:root_dir()},
+ [{a,"1.1"}],[{a,[{key2,newval2}]}],
+ {"rel2",[new_emu]}).
+
+%% Create a release tar package which can be installed on top of P1G
+create_upgrade_release(Conf,RelName,RelVsn,Erts,Apps,Config,{UpFromName,Descr}) ->
+ PrivDir = priv_dir(Conf),
+ DataDir = ?config(data_dir,Conf),
+
+ RelDir = filename:join(PrivDir,RelName),
+ RelFileName = filename:join(RelDir,RelName),
+ RelFile = RelFileName ++ ".rel",
+ ok = filelib:ensure_dir(RelFile),
+ LibPath = filename:join([DataDir,lib,"*",ebin]),
+
+ UpFrom = [{filename:join([PrivDir,UpFromName,UpFromName]),Descr}],
+
+ create_basic_release(Conf, RelFile, RelVsn, Erts, LibPath,
+ Apps, Config, UpFrom, []),
+ ok.
+
+%% Create .rel, .script, .boot, sys.config and tar
+create_basic_release(Conf, RelFile,RelVsn,{ErtsVsn,ErtsDir},LibPath,ExtraApps,Config,UpFrom,DownTo) ->
+ RelDir = filename:dirname(RelFile),
+ RelFileName = filename:rootname(RelFile),
+
+ %% Create .rel file
+ create_installer_rel_file(RelFile,RelVsn,ErtsVsn,ExtraApps),
+
+ %% Generate .script and .boot
+ ok = systools:make_script(RelFileName,
+ [{path,[LibPath]},
+ {outdir,RelDir}]),
+
+ %% Generate relup
+ ok = systools:make_relup(RelFileName,UpFrom,DownTo,[{path,[LibPath]},
+ {outdir,RelDir}]),
+
+ %% Create sys.config
+ ok = write_term_file(filename:join(RelDir,"sys.config"),Config),
+
+
+ %% Create tar file (i.e. collect all lib/app-*/* and system files)
+ ok = systools:make_tar(RelFileName,
+ [{path,[LibPath]},
+ {outdir,RelDir} |
+ case ErtsDir of
+ false -> [];
+ _ -> [{erts,ErtsDir}]
+ end]),
+
+ TarFileName = RelFileName ++ ".tar.gz",
+
+ case os:type() of
+ {win32,_} when ErtsDir=/=false -> modify_tar_win32(Conf, TarFileName);
+ _ -> ok
+ end,
+
+ TarFileName.
+
+%% Create a .rel file
+create_installer_rel_file(RelFile,RelVsn,ErtsVsn,ExtraApps) ->
+ create_rel_file(RelFile,"SASL-test",RelVsn,ErtsVsn,
+ [{installer,"1.0"}|ExtraApps]).
+
+create_rel_file(RelFile,RelName,RelVsn,ErtsVsn,ExtraApps) ->
+ {ok,KernelVsn} = application:get_key(kernel,vsn),
+ {ok,StdlibVsn} = application:get_key(stdlib,vsn),
+ {ok,SaslVsn} = application:get_key(sasl,vsn),
+ application:load(tools),
+ {ok,ToolsVsn} = application:get_key(tools,vsn),
+ application:load(runtime_tools),
+ {ok,RuntimeToolsVsn} = application:get_key(runtime_tools,vsn),
+
+ RelFileContent = {release,
+ {RelName, RelVsn},
+ {erts, ErtsVsn},
+ [{kernel, KernelVsn},
+ {stdlib, StdlibVsn},
+ {sasl, SaslVsn},
+ {runtime_tools, RuntimeToolsVsn},
+ {tools, ToolsVsn} |
+ ExtraApps]},
+ ok = write_term_file(RelFile,RelFileContent).
+
+%% Insert a term in a file, which can be read with file:consult/1.
+write_term_file(File,Term) ->
+ ok = file:write_file(File,io_lib:format("~p.~n",[Term])).
+
+
+%% Check that global group info is correct
+check_gg_info(Node,OtherAlive,OtherDead,Synced) ->
+ GGI = rpc:call(Node, global_group, info, []),
+ GI = rpc:call(Node, global, info,[]),
+ try do_check_gg_info(OtherAlive,OtherDead,Synced,GGI,GI)
+ catch _:E ->
+ ?t:format("~ncheck_gg_info failed for ~p: ~p~nwhen GGI was: ~p~n"
+ "and GI was: ~p~n",
+ [Node,E,GGI,GI]),
+ ?t:fail("check_gg_info failed")
+ end.
+
+do_check_gg_info(OtherAlive,OtherDead,Synced,GGI,GI) ->
+ {_,gg1} = lists:keyfind(own_group_name,1,GGI),
+ {_,synced} = lists:keyfind(state,1,GGI),
+ {_,AllNodes} = lists:keyfind(own_group_nodes,1,GGI),
+ true = lists:sort(AllNodes) =:= lists:sort(OtherAlive++OtherDead),
+ {_,[]} = lists:keyfind(sync_error,1,GGI),
+ {_,[{gg2,[_,_]}]} = lists:keyfind(other_groups,1,GGI),
+
+ %% There is a known bug in global_group (OTP-9177) which causes
+ %% the following to fail every now and then:
+ %% {_,SyncedNodes} = lists:keyfind(synced_nodes,1,GGI),
+ %% true = lists:sort(SyncedNodes) =:= lists:sort(Synced),
+ %% {_,NoContact} = lists:keyfind(no_contact,1,GGI),
+ %% true = lists:sort(NoContact) =:= lists:sort(OtherDead),
+
+ %% Therefore we use global:info instead for this part
+ {state,_,_,SyncedNodes,_,_,_,_,_,_,_} = GI,
+ true = lists:sort(SyncedNodes) =:= lists:sort(Synced),
+
+ %% .. and we only check that all OtherDead are listed as
+ %% no_contact (due to th bug there might be more nodes in this
+ %% list)
+ {_,NoContact} = lists:keyfind(no_contact,1,GGI),
+ true =
+ lists:sort(OtherDead) =:=
+ lists:sort([NC || NC <- NoContact,lists:member(NC,OtherDead)]),
+
+ ok.
+
+%% Return the configuration (to be inserted in sys.config) for global group tests
+gg_config(Snames) ->
+ Nodes = [node_name(Sname) || Sname <- Snames],
+ [{kernel, [{sync_nodes_optional, Nodes},
+ {sync_nodes_timeout, 10000},
+ {global_groups,
+ [{gg1, Nodes},
+ {gg2, [node_name(Sname) || Sname <- [ggq,ggw]]}]}]},
+ {a, [{key2, val2}]}].
+
+%% Start a node with short name SnameStr, and unpack P1H
+unpack_p1h(Conf,Sname) ->
+ PrivDir = priv_dir(Conf),
+ [Node] = start_nodes(Conf,[Sname],"create_p1h"),
+ ok = rpc_inst(Node, unpack_p1h, [PrivDir]),
+ Node.
+
+%% On the given node, install P1H and make it permanent
+%% This function is to be called after unpack_p1h/2, with the same node.
+permanent_p1h(Node) ->
+ ok = rpc_inst(Node, permanent_p1h, []).
+
+%% For each node in ToNodes, create a target installation which is
+%% indentical to the target installation for FromNode.
+copy_installed(Conf,FromNode,ToNodes) ->
+ PrivDir = priv_dir(Conf),
+ DataDir = ?config(data_dir,Conf),
+
+ %% Instead of using copy_tree on the complete node directory, I'm
+ %% splitting this in separate tar files per subdirectory so the
+ %% log directory can be completely skipped. The reason for this is
+ %% that the tar file might become faulty if the node is alive and
+ %% writing to the log while the tar is created.
+ FromDir = filename:join(PrivDir,FromNode),
+ {ok,FromDirNames} = file:list_dir(FromDir),
+ TempTarFiles =
+ [begin
+ TempTarFile = filename:join(PrivDir,"temp_" ++ FDN ++ ".tar"),
+ {ok,Tar} = erl_tar:open(TempTarFile,[write]),
+ ok = erl_tar:add(Tar,filename:join(FromDir,FDN),FDN,[]),
+ ok = erl_tar:close(Tar),
+ TempTarFile
+ end || FDN <- FromDirNames, FDN=/="log"],
+ lists:foreach(
+ fun(Node) ->
+ NodeDir = filename:join(PrivDir,Node),
+ ok = filelib:ensure_dir(filename:join([NodeDir,"log","*"])),
+ lists:foreach(
+ fun(TempTarFile) ->
+ ok = erl_tar:extract(TempTarFile,[{cwd,NodeDir}])
+ end, TempTarFiles),
+ case os:type() of
+ {unix,_} ->
+ %% Create start script
+ %% Using a customized start script from DataDir
+ %% where some options (heart and nodename) are
+ %% added compared to the start.src in the erlang
+ %% distribution.
+ ok = subst_file(filename:join(DataDir, "start"),
+ filename:join([NodeDir, "bin", "start"]),
+ [{"ROOT",NodeDir}],
+ [preserve]);
+ {win32,_} ->
+ %% Write erl.ini
+ ErtsDirs =
+ filelib:wildcard(filename:join(NodeDir,"erts-*")),
+ lists:foreach(
+ fun(ErtsDir) ->
+ ok = subst_file(
+ filename:join(DataDir, "erl.ini.src"),
+ filename:join([ErtsDir, "bin", "erl.ini"]),
+ [{"ROOTDIR",NodeDir},
+ {"BINDIR",filename:join(ErtsDir,"bin")}])
+ end,
+ ErtsDirs),
+
+ %% The service on windows runs as local
+ %% administrator (not otptest user), so we need
+ %% to chmod the release in order to allow the
+ %% executing node to install releases, write
+ %% logs etc.
+ chmod_release_win32(NodeDir)
+ end
+ end,
+ ToNodes),
+
+ lists:foreach(fun(TempTarFile) -> file:delete(TempTarFile) end, TempTarFiles),
+ ok.
+
+chmod_release_win32(Dir) ->
+ os:cmd("echo y|cacls " ++ Dir ++ " /T /E /G Administrators:F").
+
+start_nodes(Conf,Snames,Tag) ->
+ PrivDir = priv_dir(Conf),
+ Nodes =
+ lists:map(
+ fun(Sname) ->
+ NodeDir = filename:join(PrivDir,Sname),
+ Node = node_name(Sname),
+
+ case os:type() of
+ {unix,_} ->
+ start_node_unix(Sname,NodeDir);
+ {win32,_} ->
+ start_node_win32(Sname,NodeDir)
+ end,
+ Node
+ end,
+ Snames),
+ wait_nodes_up(Nodes,Tag),
+ Nodes.
+
+start_node_unix(Sname,NodeDir) ->
+ Script = filename:join([NodeDir,"bin","start"]),
+ Cmd = "env NODENAME="++atom_to_list(Sname) ++ " " ++ Script,
+ %% {ok,StartFile} = file:read_file(Cmd),
+ %% io:format("~s:\n~s~n~n",[Start,binary_to_list(StartFile)]),
+ Res = os:cmd(Cmd),
+ io:format("Start ~p: ~p~n=>\t~p~n", [Sname,Cmd,Res]).
+
+start_node_win32(Sname,NodeDir) ->
+ Name = atom_to_list(Sname) ++ "_P1G",
+ ErtsBinDir = filename:join(NodeDir,"erts-4.4/bin"),
+
+ StartErlArgs = rh_test_lib:get_start_erl_args(NodeDir),
+ ServiceArgs = rh_test_lib:get_service_args(NodeDir, Sname, StartErlArgs),
+
+ Erlsrv = filename:nativename(filename:join(ErtsBinDir,"erlsrv")),
+ rh_test_lib:erlsrv(Erlsrv,stop,Name),
+ rh_test_lib:erlsrv(Erlsrv,remove,Name),
+ ok = rh_test_lib:erlsrv(Erlsrv,add,Name,ServiceArgs),
+ ok = rh_test_lib:erlsrv(Erlsrv,start,Name),
+ ok.
+
+%% Create a unique node name for each test case
+tc_sname(Config) ->
+ tc_sname(Config,"").
+tc_sname(Config,Fix) when is_atom(Fix) ->
+ tc_sname(Config,atom_to_list(Fix));
+tc_sname(Config,Fix) when is_list(Fix) ->
+ list_to_atom(
+ atom_to_list(?MODULE)
+ ++ "-" ++ atom_to_list(?config(sname_prefix, Config)) ++
+ case Fix of
+ "" -> "";
+ _ -> "-" ++ Fix
+ end).
+
+tc_full_node_name(Config) ->
+ tc_full_node_name(Config,"").
+tc_full_node_name(Config,Fix) ->
+ node_name(tc_sname(Config,Fix)).
+
+
+%% When installing a release for which the sys.config includes added
+%% or changed global group(s), this node (test_sever@host) will be
+%% disconnected from the test node (Node) by global_group.erl. This
+%% will cause the rpc:call to terminate with {badrpc,nodedown} even if
+%% the installation succeeds. This function installs the release,
+%% accepts the faulty return value and then checks if the release was
+%% successfully installed.
+install_release_changed_gg(Node,RelVsn) ->
+ stop_cover(Node),
+ {badrpc,nodedown} = rpc:call(Node,release_handler,install_release,[RelVsn]),
+ timer:sleep(100),
+ wait_installed(Node,RelVsn,4).
+
+wait_installed(Node,RelVsn,0) ->
+ ?t:fail("install_release_changed_gg failed for " ++ RelVsn ++
+ " on " ++ atom_to_list(Node));
+wait_installed(Node,RelVsn,N) ->
+ Rels = rpc:call(Node,release_handler,which_releases,[]),
+ case lists:keyfind(RelVsn, 2, Rels) of
+ {"SASL-test", RelVsn, _Libs, current} ->
+ start_cover(Node),
+ ok;
+ _ ->
+ timer:sleep(500),
+ wait_installed(Node,RelVsn,N-1)
+ end.
+
+%% Start/stop cover measurements on the given node
+start_cover(Node) ->
+ cover_fun(Node,start).
+stop_cover(Node) ->
+ cover_fun(Node,stop).
+
+cover_fun(Node,Func) ->
+ case ?t:is_cover() of
+ true ->
+ cover:Func(Node);
+ false ->
+ ok
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Create a fake release ....
+
+%% This function will create and install a release build on the
+%% current running OTP release. It includes kernel, stdlib and sasl,
+%% and possibly other applications if they are listed in AppDirs =
+%% [{App,Vsn,LibDir}]
+create_and_install_fake_first_release(Dir,AppDirs) ->
+ %% Create the first release
+ {RelName,RelVsn} = init:script_id(),
+ {Rel,_} = create_fake_release(Dir,RelName,RelVsn,AppDirs),
+ ReleasesDir = filename:join(Dir, "releases"),
+ RelDir = filename:dirname(Rel),
+
+ %% And install it
+ RelVsnDir = filename:join(ReleasesDir, RelVsn),
+ ok = filelib:ensure_dir(filename:join(RelVsnDir,"*")),
+
+ ok = copy_file(Rel++".rel",RelVsnDir),
+ ok = copy_file(Rel++".boot",filename:join(RelVsnDir, "start.boot")),
+ ok = copy_file(filename:join(RelDir,"sys.config"),RelVsnDir),
+
+ ok = release_handler:create_RELEASES(code:root_dir(),
+ ReleasesDir,
+ Rel++".rel",
+ AppDirs),
+
+ Rel.
+
+%% This function create a new release, including a relup file. It can
+%% be upgraded to from the release created by
+%% create_and_install_fake_first_release/2. Unpack first by calls to
+%% release_handler:set_unpacked and release_handler:install_file.
+create_fake_upgrade_release(Dir,RelVsn,AppDirs,{UpFrom,DownTo,ExtraLibs}) ->
+ %% Create a new release
+ {RelName,_} = init:script_id(),
+ {Rel,Paths} = create_fake_release(Dir,RelName,RelVsn,AppDirs),
+ RelDir = filename:dirname(Rel),
+
+ %% And a relup file so it can be upgraded to
+ RelupPath = Paths ++ [filename:join([Lib,"*","ebin"]) || Lib <- ExtraLibs],
+ ok = systools:make_relup(Rel,UpFrom,DownTo,[{path,RelupPath},
+ {outdir,RelDir}]),
+
+ Rel.
+
+
+create_fake_release(Dir,RelName,RelVsn,AppDirs) ->
+ %% Create .rel files
+ RelDir = filename:join(Dir,"rel_" ++ RelVsn),
+ Rel = filename:join([RelDir,"rel_" ++ RelVsn]),
+ ok = filelib:ensure_dir(Rel),
+ ErtsVsn = erlang:system_info(version),
+
+ {Apps,Paths} =
+ lists:foldl(fun({App,Vsn,Lib},{As,Ps}) ->
+ {[{App,Vsn}|As],
+ lists:umerge([filename:join([Lib,"*",ebin])],Ps)}
+ end,
+ {[],[]},
+ AppDirs),
+
+ create_rel_file(Rel++".rel",RelName,RelVsn,ErtsVsn,Apps),
+
+ %% Generate boot scripts
+ ok = systools:make_script(Rel,[local,
+ {path, Paths},
+ {outdir,RelDir}]),
+ ok = copy_file(Rel++".boot", filename:join(RelDir,"start.boot")),
+
+ %% Use an own 'releases' directory - we don't want to change the
+ %% contents of $OTP_ROOT/releases
+ %% Inform SASL about this via sys.config
+ ReleasesDir = filename:join(Dir, "releases"),
+ Config = [{sasl,[{releases_dir,ReleasesDir}]}],
+ ok = write_term_file(filename:join(RelDir,"sys.config"), Config),
+
+ {Rel,Paths}.
+
+
+rpc_inst(Node,Func,Args) ->
+ rpc:call(Node,installer,Func,[node()|Args]).
+
+delete_all_services() ->
+ ErlSrv = erlsrv:erlsrv(erlang:system_info(version)),
+ [_|Serviceinfo] = string:tokens(os:cmd(ErlSrv ++ " list"),"\n"),
+ Services =
+ [lists:takewhile(fun($\t) -> false; (_) -> true end,S)
+ || S <- Serviceinfo],
+ ?t:format("Services to remove: ~p~n",[Services]),
+ lists:foreach(fun(S) ->
+ rh_test_lib:erlsrv(ErlSrv,stop,S),
+ rh_test_lib:erlsrv(ErlSrv,remove,S)
+ end,
+ Services).
+
+modify_tar_win32(Conf, TarFileName) ->
+ DataDir = ?config(data_dir,Conf),
+ PrivDir = priv_dir(Conf),
+ TmpDir = filename:join(PrivDir,"tmp_modify_tar_win32"),
+ ok = erl_tar:extract(TarFileName,[{cwd,TmpDir},compressed]),
+
+ ErtsBinDir = filelib:wildcard(filename:join([TmpDir,"erts-*","bin"])),
+ ok = copy_file(filename:join(DataDir, "heart_restart.bat"),
+ ErtsBinDir,[preserve]),
+
+ {ok,Fs} = file:list_dir(TmpDir),
+ {ok,T} = erl_tar:open(TarFileName,[write,compressed]),
+ [ok = erl_tar:add(T,filename:join(TmpDir,F),F,[]) || F <- Fs],
+ ok = erl_tar:close(T),
+ ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/Makefile.src b/lib/sasl/test/release_handler_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..edb446413d
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/Makefile.src
@@ -0,0 +1,211 @@
+EFLAGS=+debug_info
+
+P2B= \
+ P2B/a-2.0/ebin/a.@EMULATOR@ \
+ P2B/a-2.0/ebin/a_sup.@EMULATOR@
+
+LIB= \
+ lib/a-1.2/ebin/a.@EMULATOR@ \
+ lib/a-1.2/ebin/a_sup.@EMULATOR@ \
+ lib/a-1.1/ebin/a.@EMULATOR@ \
+ lib/a-1.1/ebin/a_sup.@EMULATOR@ \
+ lib/a-1.0/ebin/a.@EMULATOR@ \
+ lib/a-1.0/ebin/a_sup.@EMULATOR@ \
+ lib/b-1.0/ebin/b_server.@EMULATOR@ \
+ lib/b-1.0/ebin/b_lib.@EMULATOR@ \
+ lib/b-2.0/ebin/b_server.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m1.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m2.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m3.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m4.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m5.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m6.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m7.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m8.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m9.@EMULATOR@ \
+ lib/many_mods-1.0/ebin/m10.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m1.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m2.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m3.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m4.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m5.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m6.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m7.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m8.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m9.@EMULATOR@ \
+ lib/many_mods-1.1/ebin/m10.@EMULATOR@ \
+ lib/many_mods-2.0/ebin/m.@EMULATOR@
+
+APP= \
+ app1_app2/lib1/app1-1.0/ebin/app1_sup.@EMULATOR@ \
+ app1_app2/lib1/app1-1.0/ebin/app1_server.@EMULATOR@ \
+ app1_app2/lib1/app1-1.0/ebin/app1.@EMULATOR@ \
+ app1_app2/lib1/app2-1.0/ebin/app2_sup.@EMULATOR@ \
+ app1_app2/lib1/app2-1.0/ebin/app2_server.@EMULATOR@ \
+ app1_app2/lib1/app2-1.0/ebin/app2.@EMULATOR@ \
+ app1_app2/lib2/app1-2.0/ebin/app1_sup.@EMULATOR@ \
+ app1_app2/lib2/app1-2.0/ebin/app1_server.@EMULATOR@ \
+ app1_app2/lib2/app1-2.0/ebin/app1.@EMULATOR@ \
+ app1_app2/lib2/app2-1.0/ebin/app2_sup.@EMULATOR@ \
+ app1_app2/lib2/app2-1.0/ebin/app2_server.@EMULATOR@ \
+ app1_app2/lib2/app2-1.0/ebin/app2.@EMULATOR@
+
+OTP2740= \
+ otp_2740/vsn_atom.@EMULATOR@ \
+ otp_2740/vsn_list.@EMULATOR@ \
+ otp_2740/vsn_numeric.@EMULATOR@ \
+ otp_2740/vsn_tuple.@EMULATOR@ \
+ otp_2740/vsn_string.@EMULATOR@
+
+C= \
+ c/aa.@EMULATOR@ \
+ c/b.@EMULATOR@ \
+ c/c_sup.@EMULATOR@
+
+SUP= \
+ release_handler_timeouts/dummy-0.1/ebin/dummy_app.@EMULATOR@ \
+ release_handler_timeouts/dummy-0.1/ebin/dummy_server.@EMULATOR@ \
+ release_handler_timeouts/dummy-0.1/ebin/dummy_sup.@EMULATOR@ \
+ release_handler_timeouts/dummy-0.1/ebin/dummy_sup_2.@EMULATOR@
+
+all: $(P2B) $(LIB) $(APP) $(OTP2740) $(C) $(SUP)
+
+P2B/a-2.0/ebin/a.@EMULATOR@: P2B/a-2.0/src/a.erl
+ erlc $(EFLAGS) -oP2B/a-2.0/ebin P2B/a-2.0/src/a.erl
+P2B/a-2.0/ebin/a_sup.@EMULATOR@: P2B/a-2.0/src/a_sup.erl
+ erlc $(EFLAGS) -oP2B/a-2.0/ebin P2B/a-2.0/src/a_sup.erl
+
+
+lib/a-1.0/ebin/a.@EMULATOR@: lib/a-1.0/src/a.erl
+ erlc $(EFLAGS) -olib/a-1.0/ebin lib/a-1.0/src/a.erl
+lib/a-1.0/ebin/a_sup.@EMULATOR@: lib/a-1.0/src/a_sup.erl
+ erlc $(EFLAGS) -olib/a-1.0/ebin lib/a-1.0/src/a_sup.erl
+
+
+lib/a-1.1/ebin/a.@EMULATOR@: lib/a-1.1/src/a.erl
+ erlc $(EFLAGS) -olib/a-1.1/ebin lib/a-1.1/src/a.erl
+lib/a-1.1/ebin/a_sup.@EMULATOR@: lib/a-1.1/src/a_sup.erl
+ erlc $(EFLAGS) -olib/a-1.1/ebin lib/a-1.1/src/a_sup.erl
+
+
+lib/a-1.2/ebin/a.@EMULATOR@: lib/a-1.2/src/a.erl
+ erlc $(EFLAGS) -olib/a-1.2/ebin lib/a-1.2/src/a.erl
+lib/a-1.2/ebin/a_sup.@EMULATOR@: lib/a-1.2/src/a_sup.erl
+ erlc $(EFLAGS) -olib/a-1.2/ebin lib/a-1.2/src/a_sup.erl
+
+lib/b-1.0/ebin/b_server.@EMULATOR@: lib/b-1.0/src/b_server.erl
+ erlc $(EFLAGS) -olib/b-1.0/ebin lib/b-1.0/src/b_server.erl
+lib/b-1.0/ebin/b_lib.@EMULATOR@: lib/b-1.0/src/b_lib.erl
+ erlc $(EFLAGS) -olib/b-1.0/ebin lib/b-1.0/src/b_lib.erl
+
+lib/b-2.0/ebin/b_server.@EMULATOR@: lib/b-2.0/src/b_server.erl
+ erlc $(EFLAGS) -olib/b-2.0/ebin lib/b-2.0/src/b_server.erl
+
+lib/many_mods-1.0/ebin/m.@EMULATOR@: lib/many_mods-1.0/src/m.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m.erl
+lib/many_mods-1.0/ebin/m1.@EMULATOR@: lib/many_mods-1.0/src/m1.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m1.erl
+lib/many_mods-1.0/ebin/m2.@EMULATOR@: lib/many_mods-1.0/src/m2.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m2.erl
+lib/many_mods-1.0/ebin/m3.@EMULATOR@: lib/many_mods-1.0/src/m3.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m3.erl
+lib/many_mods-1.0/ebin/m4.@EMULATOR@: lib/many_mods-1.0/src/m4.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m4.erl
+lib/many_mods-1.0/ebin/m5.@EMULATOR@: lib/many_mods-1.0/src/m5.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m5.erl
+lib/many_mods-1.0/ebin/m6.@EMULATOR@: lib/many_mods-1.0/src/m6.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m6.erl
+lib/many_mods-1.0/ebin/m7.@EMULATOR@: lib/many_mods-1.0/src/m7.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m7.erl
+lib/many_mods-1.0/ebin/m8.@EMULATOR@: lib/many_mods-1.0/src/m8.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m8.erl
+lib/many_mods-1.0/ebin/m9.@EMULATOR@: lib/many_mods-1.0/src/m9.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m9.erl
+lib/many_mods-1.0/ebin/m10.@EMULATOR@: lib/many_mods-1.0/src/m10.erl
+ erlc $(EFLAGS) -olib/many_mods-1.0/ebin lib/many_mods-1.0/src/m10.erl
+lib/many_mods-1.1/ebin/m.@EMULATOR@: lib/many_mods-1.1/src/m.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m.erl
+lib/many_mods-1.1/ebin/m1.@EMULATOR@: lib/many_mods-1.1/src/m1.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m1.erl
+lib/many_mods-1.1/ebin/m2.@EMULATOR@: lib/many_mods-1.1/src/m2.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m2.erl
+lib/many_mods-1.1/ebin/m3.@EMULATOR@: lib/many_mods-1.1/src/m3.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m3.erl
+lib/many_mods-1.1/ebin/m4.@EMULATOR@: lib/many_mods-1.1/src/m4.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m4.erl
+lib/many_mods-1.1/ebin/m5.@EMULATOR@: lib/many_mods-1.1/src/m5.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m5.erl
+lib/many_mods-1.1/ebin/m6.@EMULATOR@: lib/many_mods-1.1/src/m6.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m6.erl
+lib/many_mods-1.1/ebin/m7.@EMULATOR@: lib/many_mods-1.1/src/m7.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m7.erl
+lib/many_mods-1.1/ebin/m8.@EMULATOR@: lib/many_mods-1.1/src/m8.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m8.erl
+lib/many_mods-1.1/ebin/m9.@EMULATOR@: lib/many_mods-1.1/src/m9.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m9.erl
+lib/many_mods-1.1/ebin/m10.@EMULATOR@: lib/many_mods-1.1/src/m10.erl
+ erlc $(EFLAGS) -olib/many_mods-1.1/ebin lib/many_mods-1.1/src/m10.erl
+lib/many_mods-2.0/ebin/m.@EMULATOR@: lib/many_mods-2.0/src/m.erl
+ erlc $(EFLAGS) -olib/many_mods-2.0/ebin lib/many_mods-2.0/src/m.erl
+
+
+app1_app2/lib1/app1-1.0/ebin/app1_sup.@EMULATOR@: app1_app2/lib1/app1-1.0/src/app1_sup.erl
+ erlc $(EFLAGS) -oapp1_app2/lib1/app1-1.0/ebin app1_app2/lib1/app1-1.0/src/app1_sup.erl
+app1_app2/lib1/app1-1.0/ebin/app1_server.@EMULATOR@: app1_app2/lib1/app1-1.0/src/app1_server.erl
+ erlc $(EFLAGS) -oapp1_app2/lib1/app1-1.0/ebin app1_app2/lib1/app1-1.0/src/app1_server.erl
+app1_app2/lib1/app1-1.0/ebin/app1.@EMULATOR@: app1_app2/lib1/app1-1.0/src/app1.erl
+ erlc $(EFLAGS) -oapp1_app2/lib1/app1-1.0/ebin app1_app2/lib1/app1-1.0/src/app1.erl
+
+
+app1_app2/lib1/app2-1.0/ebin/app2_sup.@EMULATOR@: app1_app2/lib1/app2-1.0/src/app2_sup.erl
+ erlc $(EFLAGS) -oapp1_app2/lib1/app2-1.0/ebin app1_app2/lib1/app2-1.0/src/app2_sup.erl
+app1_app2/lib1/app2-1.0/ebin/app2_server.@EMULATOR@: app1_app2/lib1/app2-1.0/src/app2_server.erl
+ erlc $(EFLAGS) -oapp1_app2/lib1/app2-1.0/ebin app1_app2/lib1/app2-1.0/src/app2_server.erl
+app1_app2/lib1/app2-1.0/ebin/app2.@EMULATOR@: app1_app2/lib1/app2-1.0/src/app2.erl
+ erlc $(EFLAGS) -oapp1_app2/lib1/app2-1.0/ebin app1_app2/lib1/app2-1.0/src/app2.erl
+
+
+app1_app2/lib2/app1-2.0/ebin/app1_sup.@EMULATOR@: app1_app2/lib2/app1-2.0/src/app1_sup.erl
+ erlc $(EFLAGS) -oapp1_app2/lib2/app1-2.0/ebin app1_app2/lib2/app1-2.0/src/app1_sup.erl
+app1_app2/lib2/app1-2.0/ebin/app1_server.@EMULATOR@: app1_app2/lib2/app1-2.0/src/app1_server.erl
+ erlc $(EFLAGS) -oapp1_app2/lib2/app1-2.0/ebin app1_app2/lib2/app1-2.0/src/app1_server.erl
+app1_app2/lib2/app1-2.0/ebin/app1.@EMULATOR@: app1_app2/lib2/app1-2.0/src/app1.erl
+ erlc $(EFLAGS) -oapp1_app2/lib2/app1-2.0/ebin app1_app2/lib2/app1-2.0/src/app1.erl
+
+
+app1_app2/lib2/app2-1.0/ebin/app2_sup.@EMULATOR@: app1_app2/lib2/app2-1.0/src/app2_sup.erl
+ erlc $(EFLAGS) -oapp1_app2/lib2/app2-1.0/ebin app1_app2/lib2/app2-1.0/src/app2_sup.erl
+app1_app2/lib2/app2-1.0/ebin/app2_server.@EMULATOR@: app1_app2/lib2/app2-1.0/src/app2_server.erl
+ erlc $(EFLAGS) -oapp1_app2/lib2/app2-1.0/ebin app1_app2/lib2/app2-1.0/src/app2_server.erl
+app1_app2/lib2/app2-1.0/ebin/app2.@EMULATOR@: app1_app2/lib2/app2-1.0/src/app2.erl
+ erlc $(EFLAGS) -oapp1_app2/lib2/app2-1.0/ebin app1_app2/lib2/app2-1.0/src/app2.erl
+
+
+otp_2740/vsn_atom.@EMULATOR@: otp_2740/vsn_atom.erl
+ erlc $(EFLAGS) -ootp_2740 otp_2740/vsn_atom.erl
+otp_2740/vsn_list.@EMULATOR@: otp_2740/vsn_list.erl
+ erlc $(EFLAGS) -ootp_2740 otp_2740/vsn_list.erl
+otp_2740/vsn_numeric.@EMULATOR@: otp_2740/vsn_numeric.erl
+ erlc $(EFLAGS) -ootp_2740 otp_2740/vsn_numeric.erl
+otp_2740/vsn_tuple.@EMULATOR@: otp_2740/vsn_tuple.erl
+ erlc $(EFLAGS) -ootp_2740 otp_2740/vsn_tuple.erl
+otp_2740/vsn_string.@EMULATOR@: otp_2740/vsn_string.erl
+ erlc $(EFLAGS) -ootp_2740 otp_2740/vsn_string.erl
+
+c/aa.@EMULATOR@: c/aa.erl
+ erlc $(EFLAGS) -oc c/aa.erl
+c/b.@EMULATOR@: c/b.erl
+ erlc $(EFLAGS) -oc c/b.erl
+c/c_sup.@EMULATOR@: c/c_sup.erl
+ erlc $(EFLAGS) -oc c/c_sup.erl
+
+release_handler_timeouts/dummy-0.1/ebin/dummy_app.@EMULATOR@: release_handler_timeouts/dummy-0.1/src/dummy_app.erl
+ erlc $(EFLAGS) -orelease_handler_timeouts/dummy-0.1/ebin release_handler_timeouts/dummy-0.1/src/dummy_app.erl
+release_handler_timeouts/dummy-0.1/ebin/dummy_server.@EMULATOR@: release_handler_timeouts/dummy-0.1/src/dummy_server.erl
+ erlc $(EFLAGS) -orelease_handler_timeouts/dummy-0.1/ebin release_handler_timeouts/dummy-0.1/src/dummy_server.erl
+release_handler_timeouts/dummy-0.1/ebin/dummy_sup.@EMULATOR@: release_handler_timeouts/dummy-0.1/src/dummy_sup.erl
+ erlc $(EFLAGS) -orelease_handler_timeouts/dummy-0.1/ebin release_handler_timeouts/dummy-0.1/src/dummy_sup.erl
+release_handler_timeouts/dummy-0.1/ebin/dummy_sup_2.@EMULATOR@: release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl
+ erlc $(EFLAGS) -orelease_handler_timeouts/dummy-0.1/ebin release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl
diff --git a/lib/sasl/test/release_handler_SUITE_data/P2B/a-2.0/ebin/a.app b/lib/sasl/test/release_handler_SUITE_data/P2B/a-2.0/ebin/a.app
new file mode 100644
index 0000000000..200cfcfe47
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/P2B/a-2.0/ebin/a.app
@@ -0,0 +1,8 @@
+{application, a,
+ [{description, "A CXC 138 11"},
+ {vsn, "2.0"},
+ {modules, [{a, 1}, {a_sup,1}]},
+ {registered, [a_sup]},
+ {applications, [kernel, stdlib]},
+ {env, [{key1, val1}]},
+ {mod, {a_sup, []}}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/P2B/a-2.0/src/a.erl b/lib/sasl/test/release_handler_SUITE_data/P2B/a-2.0/src/a.erl
new file mode 100644
index 0000000000..cfe38b55ce
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/P2B/a-2.0/src/a.erl
@@ -0,0 +1,47 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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$
+%%
+-module(a).
+
+
+-behaviour(gen_server).
+
+%% External exports
+-export([start_link/0, a/0]).
+%% Internal exports
+-export([init/1, handle_call/3, handle_info/2, terminate/2]).
+
+start_link() -> gen_server:start_link({local, aa}, a, [], []).
+
+a() -> gen_server:call(aa, a).
+
+%%-----------------------------------------------------------------
+%% Callback functions from gen_server
+%%-----------------------------------------------------------------
+init([]) ->
+ process_flag(trap_exit, true),
+ {ok, state}.
+
+handle_call(a, _From, State) ->
+ X = application:get_all_env(a),
+ {reply, X, State}.
+
+handle_info(_, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/P2B/a-2.0/src/a_sup.erl b/lib/sasl/test/release_handler_SUITE_data/P2B/a-2.0/src/a_sup.erl
new file mode 100644
index 0000000000..a141c1767b
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/P2B/a-2.0/src/a_sup.erl
@@ -0,0 +1,37 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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$
+%%
+-module(a_sup).
+
+
+-behaviour(supervisor).
+
+%% External exports
+-export([start/2]).
+
+%% Internal exports
+-export([init/1]).
+
+start(_, _) ->
+ supervisor:start_link({local, a_sup}, a_sup, []).
+
+init([]) ->
+ SupFlags = {one_for_one, 4, 3600},
+ Config = {a,
+ {a, start_link, []},
+ permanent, 2000, worker, [a]},
+ {ok, {SupFlags, [Config]}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app1-1.0/ebin/app1.app b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app1-1.0/ebin/app1.app
new file mode 100644
index 0000000000..0489cb2595
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app1-1.0/ebin/app1.app
@@ -0,0 +1,9 @@
+{application, app1,
+ [{description, "very simple example application"},
+ {id, "app1"},
+ {vsn, "1.0"},
+ {modules, [app1, app1_sup, app1_server]},
+ {registered, [harry]},
+ {applications, [kernel, stdlib, sasl]},
+ {env, [{var,val1}]},
+ {mod, {app1, []}}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app1-1.0/src/app1.erl b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app1-1.0/src/app1.erl
new file mode 100644
index 0000000000..f123c8f470
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app1-1.0/src/app1.erl
@@ -0,0 +1,22 @@
+-module(app1).
+
+-behaviour(application).
+
+%% Application callbacks
+-export([start/2, stop/1]).
+-export([config_change/3]).
+
+start(_Type, _StartArgs) ->
+ case app1_sup:start_link() of
+ {ok, Pid} ->
+ {ok, Pid};
+ Error ->
+ Error
+ end.
+
+stop(_State) ->
+ ok.
+
+config_change(Changed, _New, _Removed) ->
+ catch ets:insert(otp_6162, hd(Changed)),
+ ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app1-1.0/src/app1_server.erl b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app1-1.0/src/app1_server.erl
new file mode 100644
index 0000000000..9b49e772cc
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app1-1.0/src/app1_server.erl
@@ -0,0 +1,32 @@
+-module(app1_server).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+start_link() ->
+ gen_server:start_link({local, harry}, ?MODULE, [], []).
+
+init([]) ->
+ {ok, []}.
+
+handle_call(_Request, _From, State) ->
+ Reply = ok,
+ {reply, Reply, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app1-1.0/src/app1_sup.erl b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app1-1.0/src/app1_sup.erl
new file mode 100644
index 0000000000..e6ad9b6967
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app1-1.0/src/app1_sup.erl
@@ -0,0 +1,17 @@
+-module(app1_sup).
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/0]).
+
+%% Supervisor callbacks
+-export([init/1]).
+
+start_link() ->
+ supervisor:start_link(?MODULE, []).
+
+init([]) ->
+ AChild = {harry,{app1_server,start_link,[]},
+ permanent,2000,worker,[app1_server]},
+ {ok,{{one_for_all,0,1}, [AChild]}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app2-1.0/ebin/app2.app b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app2-1.0/ebin/app2.app
new file mode 100644
index 0000000000..d48018cbda
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app2-1.0/ebin/app2.app
@@ -0,0 +1,9 @@
+{application, app2,
+ [{description, "very simple example application"},
+ {id, "app2"},
+ {vsn, "1.0"},
+ {modules, [app2, app2_sup, app2_server]},
+ {registered, [ginny]},
+ {applications, [kernel, stdlib, sasl]},
+ {env, []},
+ {mod, {app2, []}}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app2-1.0/src/app2.erl b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app2-1.0/src/app2.erl
new file mode 100644
index 0000000000..a41c39730c
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app2-1.0/src/app2.erl
@@ -0,0 +1,17 @@
+-module(app2).
+
+-behaviour(application).
+
+%% Application callbacks
+-export([start/2, stop/1]).
+
+start(_Type, _StartArgs) ->
+ case app2_sup:start_link() of
+ {ok, Pid} ->
+ {ok, Pid};
+ Error ->
+ Error
+ end.
+
+stop(_State) ->
+ ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app2-1.0/src/app2_server.erl b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app2-1.0/src/app2_server.erl
new file mode 100644
index 0000000000..d8440230ff
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app2-1.0/src/app2_server.erl
@@ -0,0 +1,32 @@
+-module(app2_server).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+start_link() ->
+ gen_server:start_link({local, ginny}, ?MODULE, [], []).
+
+init([]) ->
+ {ok, []}.
+
+handle_call(_Request, _From, State) ->
+ Reply = ok,
+ {reply, Reply, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app2-1.0/src/app2_sup.erl b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app2-1.0/src/app2_sup.erl
new file mode 100644
index 0000000000..80b0952d4b
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib1/app2-1.0/src/app2_sup.erl
@@ -0,0 +1,17 @@
+-module(app2_sup).
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/0]).
+
+%% Supervisor callbacks
+-export([init/1]).
+
+start_link() ->
+ supervisor:start_link(?MODULE, []).
+
+init([]) ->
+ AChild = {ginny,{app2_server,start_link,[]},
+ permanent,2000,worker,[app2_server]},
+ {ok,{{one_for_all,0,1}, [AChild]}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/ebin/app1.app b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/ebin/app1.app
new file mode 100644
index 0000000000..3c65adfbb3
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/ebin/app1.app
@@ -0,0 +1,9 @@
+{application, app1,
+ [{description, "very simple example application"},
+ {id, "app1"},
+ {vsn, "2.0"},
+ {modules, [app1, app1_sup, app1_server]},
+ {registered, [harry]},
+ {applications, [kernel, stdlib, sasl]},
+ {env, [{var,val2}]},
+ {mod, {app1, []}}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/ebin/app1.appup b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/ebin/app1.appup
new file mode 100644
index 0000000000..e5e0cbda0e
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/ebin/app1.appup
@@ -0,0 +1,4 @@
+{"2.0",
+ [{"1.0", [{load_module, app1_server}]}],
+ [{"1.0", [{load_module, app1_server}]}]
+}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/src/app1.erl b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/src/app1.erl
new file mode 100644
index 0000000000..f123c8f470
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/src/app1.erl
@@ -0,0 +1,22 @@
+-module(app1).
+
+-behaviour(application).
+
+%% Application callbacks
+-export([start/2, stop/1]).
+-export([config_change/3]).
+
+start(_Type, _StartArgs) ->
+ case app1_sup:start_link() of
+ {ok, Pid} ->
+ {ok, Pid};
+ Error ->
+ Error
+ end.
+
+stop(_State) ->
+ ok.
+
+config_change(Changed, _New, _Removed) ->
+ catch ets:insert(otp_6162, hd(Changed)),
+ ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/src/app1_server.erl b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/src/app1_server.erl
new file mode 100644
index 0000000000..660d095ebf
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/src/app1_server.erl
@@ -0,0 +1,35 @@
+-module(app1_server).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+start_link() ->
+ gen_server:start_link({local, harry}, ?MODULE, [], []).
+
+init([]) ->
+ {ok, []}.
+
+handle_call(error, _From, State) ->
+ Reply = error,
+ {reply, Reply, State};
+handle_call(_Request, _From, State) ->
+ Reply = ok,
+ {reply, Reply, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/src/app1_sup.erl b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/src/app1_sup.erl
new file mode 100644
index 0000000000..e6ad9b6967
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app1-2.0/src/app1_sup.erl
@@ -0,0 +1,17 @@
+-module(app1_sup).
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/0]).
+
+%% Supervisor callbacks
+-export([init/1]).
+
+start_link() ->
+ supervisor:start_link(?MODULE, []).
+
+init([]) ->
+ AChild = {harry,{app1_server,start_link,[]},
+ permanent,2000,worker,[app1_server]},
+ {ok,{{one_for_all,0,1}, [AChild]}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app2-1.0/ebin/app2.app b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app2-1.0/ebin/app2.app
new file mode 100644
index 0000000000..d48018cbda
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app2-1.0/ebin/app2.app
@@ -0,0 +1,9 @@
+{application, app2,
+ [{description, "very simple example application"},
+ {id, "app2"},
+ {vsn, "1.0"},
+ {modules, [app2, app2_sup, app2_server]},
+ {registered, [ginny]},
+ {applications, [kernel, stdlib, sasl]},
+ {env, []},
+ {mod, {app2, []}}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app2-1.0/src/app2.erl b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app2-1.0/src/app2.erl
new file mode 100644
index 0000000000..a41c39730c
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app2-1.0/src/app2.erl
@@ -0,0 +1,17 @@
+-module(app2).
+
+-behaviour(application).
+
+%% Application callbacks
+-export([start/2, stop/1]).
+
+start(_Type, _StartArgs) ->
+ case app2_sup:start_link() of
+ {ok, Pid} ->
+ {ok, Pid};
+ Error ->
+ Error
+ end.
+
+stop(_State) ->
+ ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app2-1.0/src/app2_server.erl b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app2-1.0/src/app2_server.erl
new file mode 100644
index 0000000000..d8440230ff
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app2-1.0/src/app2_server.erl
@@ -0,0 +1,32 @@
+-module(app2_server).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+start_link() ->
+ gen_server:start_link({local, ginny}, ?MODULE, [], []).
+
+init([]) ->
+ {ok, []}.
+
+handle_call(_Request, _From, State) ->
+ Reply = ok,
+ {reply, Reply, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app2-1.0/src/app2_sup.erl b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app2-1.0/src/app2_sup.erl
new file mode 100644
index 0000000000..80b0952d4b
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/app1_app2/lib2/app2-1.0/src/app2_sup.erl
@@ -0,0 +1,17 @@
+-module(app2_sup).
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/0]).
+
+%% Supervisor callbacks
+-export([init/1]).
+
+start_link() ->
+ supervisor:start_link(?MODULE, []).
+
+init([]) ->
+ AChild = {ginny,{app2_server,start_link,[]},
+ permanent,2000,worker,[app2_server]},
+ {ok,{{one_for_all,0,1}, [AChild]}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/c/aa.erl b/lib/sasl/test/release_handler_SUITE_data/c/aa.erl
new file mode 100644
index 0000000000..1c853c85b2
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/c/aa.erl
@@ -0,0 +1,41 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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$
+%%
+-module(aa).
+
+
+-behaviour(gen_server).
+
+%% External exports
+-export([start_link/0]).
+%% Internal exports
+-export([init/1, handle_info/2, terminate/2]).
+
+start_link() -> gen_server:start_link({local, cc}, aa, [], []).
+
+%%-----------------------------------------------------------------
+%% Callback functions from gen_server
+%%-----------------------------------------------------------------
+init([]) ->
+ process_flag(trap_exit, true),
+ {ok, state}.
+
+handle_info(_, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/c/b.erl b/lib/sasl/test/release_handler_SUITE_data/c/b.erl
new file mode 100644
index 0000000000..d8426a515e
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/c/b.erl
@@ -0,0 +1,38 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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$
+%%
+-module(b).
+
+
+%% External exports
+-export([start_link/0]).
+%% Internal exports
+-export([init/0]).
+
+start_link() -> {ok, proc_lib:spawn_link(b, init, [])}.
+
+%%-----------------------------------------------------------------
+%% Callback functions from gen_server
+%%-----------------------------------------------------------------
+init() ->
+ register(bb, self()),
+ loop().
+
+loop() ->
+ receive
+ hej -> ok
+ end.
diff --git a/lib/sasl/test/release_handler_SUITE_data/c/c.app b/lib/sasl/test/release_handler_SUITE_data/c/c.app
new file mode 100644
index 0000000000..908a94cf2d
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/c/c.app
@@ -0,0 +1,8 @@
+{application, c,
+ [{description, "C CXC 138 11"},
+ {vsn, "1.0"},
+ {modules, [b, {aa, 1}, {c_sup,1}]},
+ {registered, [cc,bb,c_sup]},
+ {applications, [kernel, stdlib]},
+ {env, [{key1, val1}]},
+ {mod, {c_sup, []}}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/c/c_sup.erl b/lib/sasl/test/release_handler_SUITE_data/c/c_sup.erl
new file mode 100644
index 0000000000..069eb3b99b
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/c/c_sup.erl
@@ -0,0 +1,40 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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$
+%%
+-module(c_sup).
+
+
+-behaviour(supervisor).
+
+%% External exports
+-export([start/2]).
+
+%% Internal exports
+-export([init/1]).
+
+start(_, _) ->
+ supervisor:start_link({local, c_sup}, c_sup, []).
+
+init([]) ->
+ SupFlags = {one_for_one, 4, 3600},
+ Config1 = {c,
+ {aa, start_link, []},
+ permanent, 2000, worker, [aa]},
+ Config2 = {b,
+ {b, start_link, []},
+ permanent, 2000, worker, [b]},
+ {ok, {SupFlags, [Config1, Config2]}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/erl.ini.src b/lib/sasl/test/release_handler_SUITE_data/erl.ini.src
new file mode 100644
index 0000000000..b8791e75a5
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/erl.ini.src
@@ -0,0 +1,4 @@
+[erlang]
+Bindir=%BINDIR%
+Progname=erl
+Rootdir=%ROOTDIR%
diff --git a/lib/sasl/test/release_handler_SUITE_data/heart_restart.bat b/lib/sasl/test/release_handler_SUITE_data/heart_restart.bat
new file mode 100755
index 0000000000..ede1ad4ff3
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/heart_restart.bat
@@ -0,0 +1,3 @@
+@echo off
+%ERLSRV_EXECUTABLE% stop %ERLSRV_SERVICE_NAME%
+%ERLSRV_EXECUTABLE% start %ERLSRV_SERVICE_NAME% \ No newline at end of file
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/README b/lib/sasl/test/release_handler_SUITE_data/lib/README
new file mode 100644
index 0000000000..639a4ca0fb
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/README
@@ -0,0 +1,33 @@
+a-1.0:
+start version
+
+a-1.1:
+can be upgraded to from a-1.0. Module a has changed
+
+a-1.2:
+can be upgraded to from a-1.1.
+No module have changed, but priv dir is added including one 'file'
+
+b-1.0:
+start version, includes b_lib and b_server
+
+b-2.0:
+can be upgraded to from b-1.0.
+Removes b_lib (soft_purge) and updates b_server (brutal_purge)
+* The diff in purge method is important for test "check_and_purge", in
+ order to check that the purge option to check_install_release works
+ for both methods.
+
+many_mods-1.0:
+start version.
+m:start/1 starts N procs, each calling Mod:bar() in all other modules (m1-m10).
+m1-m10: implements bar() which returns a big constant.
+The point is to get many processes with references to many modules,
+and then load the modules again so that old code exists. See tests
+otp_9395_update_many_mods and otp_9395_rm_many_mods.
+
+many_mods-1.1:
+can be upgraded to from many_mods-1.0. Updates modules m1-m10.
+
+many_mods-2.0:
+can be upgraded to from many_mods-1.0. Removes modules m1-m10. \ No newline at end of file
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-1.0/ebin/a.app b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.0/ebin/a.app
new file mode 100644
index 0000000000..e938137f67
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.0/ebin/a.app
@@ -0,0 +1,8 @@
+{application, a,
+ [{description, "A CXC 138 11"},
+ {vsn, "1.0"},
+ {modules, [{a, 1}, {a_sup,1}]},
+ {registered, [a_sup]},
+ {applications, [kernel, stdlib]},
+ {env, [{key1, val1}]},
+ {mod, {a_sup, []}}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-1.0/src/a.erl b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.0/src/a.erl
new file mode 100644
index 0000000000..bb500bed69
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.0/src/a.erl
@@ -0,0 +1,49 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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$
+%%
+-module(a).
+
+
+-behaviour(gen_server).
+
+-vsn(1).
+
+%% External exports
+-export([start_link/0, a/0]).
+%% Internal exports
+-export([init/1, handle_call/3, handle_info/2, terminate/2]).
+
+start_link() -> gen_server:start_link({local, aa}, a, [], []).
+
+a() -> gen_server:call(aa, a).
+
+%%-----------------------------------------------------------------
+%% Callback functions from gen_server
+%%-----------------------------------------------------------------
+init([]) ->
+ process_flag(trap_exit, true),
+ {ok, state}.
+
+handle_call(a, _From, State) ->
+ X = application:get_all_env(a),
+ {reply, X, State}.
+
+handle_info(_, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-1.0/src/a_sup.erl b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.0/src/a_sup.erl
new file mode 100644
index 0000000000..a141c1767b
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.0/src/a_sup.erl
@@ -0,0 +1,37 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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$
+%%
+-module(a_sup).
+
+
+-behaviour(supervisor).
+
+%% External exports
+-export([start/2]).
+
+%% Internal exports
+-export([init/1]).
+
+start(_, _) ->
+ supervisor:start_link({local, a_sup}, a_sup, []).
+
+init([]) ->
+ SupFlags = {one_for_one, 4, 3600},
+ Config = {a,
+ {a, start_link, []},
+ permanent, 2000, worker, [a]},
+ {ok, {SupFlags, [Config]}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-1.1/ebin/a.app b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.1/ebin/a.app
new file mode 100644
index 0000000000..1c3053b2fa
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.1/ebin/a.app
@@ -0,0 +1,8 @@
+{application, a,
+ [{description, "A CXC 138 11"},
+ {vsn, "1.1"},
+ {modules, [{a, 2}, {a_sup,1}]},
+ {registered, [a_sup]},
+ {applications, [kernel, stdlib]},
+ {env, [{key1, val1}]},
+ {mod, {a_sup, []}}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-1.1/ebin/a.appup b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.1/ebin/a.appup
new file mode 100644
index 0000000000..05db4cb541
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.1/ebin/a.appup
@@ -0,0 +1,3 @@
+{"1.1",
+ [{"1.0",[{update,a,{advanced,extra_par}}]}],
+ []}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-1.1/src/a.erl b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.1/src/a.erl
new file mode 100644
index 0000000000..c082ad5339
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.1/src/a.erl
@@ -0,0 +1,54 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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$
+%%
+-module(a).
+
+
+-behaviour(gen_server).
+
+%% External exports
+-export([start_link/0, a/0, b/0]).
+%% Internal exports
+-export([init/1, handle_call/3, handle_info/2, terminate/2, code_change/3]).
+
+start_link() -> gen_server:start_link({local, aa}, a, [], []).
+
+a() -> gen_server:call(aa, a).
+b() -> gen_server:call(aa, b).
+
+%%-----------------------------------------------------------------
+%% Callback functions from gen_server
+%%-----------------------------------------------------------------
+init([]) ->
+ process_flag(trap_exit, true),
+ {ok, {state, bval}}.
+
+handle_call(a, _From, State) ->
+ X = application:get_all_env(a),
+ {reply, X, State};
+
+handle_call(b, _From, State) ->
+ {reply, {ok, element(2, State)}, State}.
+
+handle_info(_, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(1, Extra, State) ->
+ {ok, {state, bval}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-1.1/src/a_sup.erl b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.1/src/a_sup.erl
new file mode 100644
index 0000000000..a141c1767b
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.1/src/a_sup.erl
@@ -0,0 +1,37 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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$
+%%
+-module(a_sup).
+
+
+-behaviour(supervisor).
+
+%% External exports
+-export([start/2]).
+
+%% Internal exports
+-export([init/1]).
+
+start(_, _) ->
+ supervisor:start_link({local, a_sup}, a_sup, []).
+
+init([]) ->
+ SupFlags = {one_for_one, 4, 3600},
+ Config = {a,
+ {a, start_link, []},
+ permanent, 2000, worker, [a]},
+ {ok, {SupFlags, [Config]}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/ebin/a.app b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/ebin/a.app
new file mode 100644
index 0000000000..b38722f06d
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/ebin/a.app
@@ -0,0 +1,8 @@
+{application, a,
+ [{description, "A CXC 138 11"},
+ {vsn, "1.2"},
+ {modules, [{a, 2}, {a_sup,1}]},
+ {registered, [a_sup]},
+ {applications, [kernel, stdlib]},
+ {env, [{key1, val1}]},
+ {mod, {a_sup, []}}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/ebin/a.appup b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/ebin/a.appup
new file mode 100644
index 0000000000..3df0546316
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/ebin/a.appup
@@ -0,0 +1,3 @@
+{"1.2",
+ [{"1.1",[]}],
+ [{"1.1",[]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/priv/file b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/priv/file
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/priv/file
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/src/a.erl b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/src/a.erl
new file mode 100644
index 0000000000..c082ad5339
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/src/a.erl
@@ -0,0 +1,54 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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$
+%%
+-module(a).
+
+
+-behaviour(gen_server).
+
+%% External exports
+-export([start_link/0, a/0, b/0]).
+%% Internal exports
+-export([init/1, handle_call/3, handle_info/2, terminate/2, code_change/3]).
+
+start_link() -> gen_server:start_link({local, aa}, a, [], []).
+
+a() -> gen_server:call(aa, a).
+b() -> gen_server:call(aa, b).
+
+%%-----------------------------------------------------------------
+%% Callback functions from gen_server
+%%-----------------------------------------------------------------
+init([]) ->
+ process_flag(trap_exit, true),
+ {ok, {state, bval}}.
+
+handle_call(a, _From, State) ->
+ X = application:get_all_env(a),
+ {reply, X, State};
+
+handle_call(b, _From, State) ->
+ {reply, {ok, element(2, State)}, State}.
+
+handle_info(_, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(1, Extra, State) ->
+ {ok, {state, bval}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/src/a_sup.erl b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/src/a_sup.erl
new file mode 100644
index 0000000000..a141c1767b
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/a-1.2/src/a_sup.erl
@@ -0,0 +1,37 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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$
+%%
+-module(a_sup).
+
+
+-behaviour(supervisor).
+
+%% External exports
+-export([start/2]).
+
+%% Internal exports
+-export([init/1]).
+
+start(_, _) ->
+ supervisor:start_link({local, a_sup}, a_sup, []).
+
+init([]) ->
+ SupFlags = {one_for_one, 4, 3600},
+ Config = {a,
+ {a, start_link, []},
+ permanent, 2000, worker, [a]},
+ {ok, {SupFlags, [Config]}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/ebin/b.app b/lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/ebin/b.app
new file mode 100644
index 0000000000..00347b2754
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/ebin/b.app
@@ -0,0 +1,7 @@
+%% -*- erlang -*-
+{application, b,
+ [{description, "B CXC 138 12"},
+ {vsn, "1.0"},
+ {modules, [{b_server, 1},{b_lib, 1}]},
+ {registered, [b_server]},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/src/b_lib.erl b/lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/src/b_lib.erl
new file mode 100644
index 0000000000..7e8a308a5e
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/src/b_lib.erl
@@ -0,0 +1,3 @@
+-module(b_lib).
+-compile(export_all).
+foo() -> ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/src/b_server.erl b/lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/src/b_server.erl
new file mode 100644
index 0000000000..e1a80a076f
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/b-1.0/src/b_server.erl
@@ -0,0 +1,37 @@
+-module(b_server).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+-define(SERVER, ?MODULE).
+
+-record(state, {}).
+
+start_link() ->
+ gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+
+init([]) ->
+ {ok, #state{}}.
+
+handle_call(_Request, _From, State) ->
+ Reply = ok,
+ {reply, Reply, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(OldVsn, State, Extra) ->
+ file:write_file("/tmp/b_server",io_lib:format("~p~n",[{"1.0",OldVsn,Extra}])),
+ {ok, State}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/ebin/b.app b/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/ebin/b.app
new file mode 100644
index 0000000000..73c8e42b32
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/ebin/b.app
@@ -0,0 +1,7 @@
+%% -*- erlang -*-
+{application, b,
+ [{description, "B CXC 138 12"},
+ {vsn, "2.0"},
+ {modules, [{b_server, 1}]},
+ {registered, [b_server]},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/ebin/b.appup b/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/ebin/b.appup
new file mode 100644
index 0000000000..001255a88c
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/ebin/b.appup
@@ -0,0 +1,6 @@
+%% -*- erlang -*-
+{"2.0",
+ [{"1.0",[{remove_module,b_lib,soft_purge,soft_purge,[]},
+ {update,b_server,{advanced,[]}}]}],
+ [{"1.0",[{add_module,b_lib},
+ {update,b_server,{advanced,[]}}]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/src/b_lib.erl b/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/src/b_lib.erl
new file mode 100644
index 0000000000..7e8a308a5e
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/src/b_lib.erl
@@ -0,0 +1,3 @@
+-module(b_lib).
+-compile(export_all).
+foo() -> ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/src/b_server.erl b/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/src/b_server.erl
new file mode 100644
index 0000000000..f8bfbdaff7
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/b-2.0/src/b_server.erl
@@ -0,0 +1,37 @@
+-module(b_server).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+-define(SERVER, ?MODULE).
+
+-record(state, {}).
+
+start_link() ->
+ gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+
+init([]) ->
+ {ok, #state{}}.
+
+handle_call(_Request, _From, State) ->
+ Reply = ok,
+ {reply, Reply, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(OldVsn, State, Extra) ->
+ file:write_file("/tmp/b_server",io_lib:format("~p~n",[{"2.0",OldVsn,Extra}])),
+ {ok, State}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/ebin/installer.app b/lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/ebin/installer.app
new file mode 100644
index 0000000000..e1391c0605
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/ebin/installer.app
@@ -0,0 +1,6 @@
+{application, installer,
+ [{description, "Installer application"},
+ {vsn, "1.0"},
+ {modules, [installer,rh_test_lib]},
+ {registered, []},
+ {applications, [kernel, stdlib, sasl]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/src/installer.erl b/lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/src/installer.erl
new file mode 120000
index 0000000000..c2f93b822d
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/src/installer.erl
@@ -0,0 +1 @@
+../../../../installer.erl \ No newline at end of file
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/ebin/many_mods.app b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/ebin/many_mods.app
new file mode 100644
index 0000000000..aa39adfffa
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/ebin/many_mods.app
@@ -0,0 +1,17 @@
+%% -*- erlang -*-
+{application, many_mods,
+ [{description, "Application with many modules CXC 138 11"},
+ {vsn, "1.0"},
+ {modules, [{m, 1},
+ {m1,1},
+ {m2,1},
+ {m3,1},
+ {m4,1},
+ {m5,1},
+ {m6,1},
+ {m7,1},
+ {m8,1},
+ {m9,1},
+ {m10,1}]},
+ {registered, []},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m.erl
new file mode 100644
index 0000000000..418102bebb
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m.erl
@@ -0,0 +1,11 @@
+-module(m).
+-compile(export_all).
+
+start(NProcs) ->
+ Modules = [m1,m2,m3,m4,m5,m6,m7,m8,m9,m10],
+ Pids = [spawn_link(fun() ->
+ Cs = [M:bar() || M <- Modules],
+ receive stop -> Cs end
+ end) ||
+ _ <- lists:seq(1,NProcs)],
+ {Modules,Pids}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m1.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m1.erl
new file mode 100644
index 0000000000..cacc13f5d7
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m1.erl
@@ -0,0 +1,4 @@
+-module(m1).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m10.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m10.erl
new file mode 100644
index 0000000000..81e120b891
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m10.erl
@@ -0,0 +1,4 @@
+-module(m10).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m2.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m2.erl
new file mode 100644
index 0000000000..481276ba7b
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m2.erl
@@ -0,0 +1,4 @@
+-module(m2).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m3.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m3.erl
new file mode 100644
index 0000000000..9a04ed5fc9
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m3.erl
@@ -0,0 +1,4 @@
+-module(m3).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m4.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m4.erl
new file mode 100644
index 0000000000..90de9a30c9
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m4.erl
@@ -0,0 +1,4 @@
+-module(m4).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m5.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m5.erl
new file mode 100644
index 0000000000..8a9b690dfa
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m5.erl
@@ -0,0 +1,4 @@
+-module(m5).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m6.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m6.erl
new file mode 100644
index 0000000000..cd0d3977ed
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m6.erl
@@ -0,0 +1,4 @@
+-module(m6).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m7.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m7.erl
new file mode 100644
index 0000000000..1f79918d6e
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m7.erl
@@ -0,0 +1,4 @@
+-module(m7).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m8.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m8.erl
new file mode 100644
index 0000000000..2ce03a0b7e
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m8.erl
@@ -0,0 +1,4 @@
+-module(m8).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m9.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m9.erl
new file mode 100644
index 0000000000..1c5f72e628
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.0/src/m9.erl
@@ -0,0 +1,4 @@
+-module(m9).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/ebin/many_mods.app b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/ebin/many_mods.app
new file mode 100644
index 0000000000..36c50caf2f
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/ebin/many_mods.app
@@ -0,0 +1,17 @@
+%% -*- erlang -*-
+{application, many_mods,
+ [{description, "Application with many modules CXC 138 11"},
+ {vsn, "1.1"},
+ {modules, [{m, 1},
+ {m1,1},
+ {m2,1},
+ {m3,1},
+ {m4,1},
+ {m5,1},
+ {m6,1},
+ {m7,1},
+ {m8,1},
+ {m9,1},
+ {m10,1}]},
+ {registered, []},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/ebin/many_mods.appup b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/ebin/many_mods.appup
new file mode 100644
index 0000000000..696435e06f
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/ebin/many_mods.appup
@@ -0,0 +1,22 @@
+%% -*- erlang -*-
+{"1.1",
+ [{"1.0",[{update,m1},
+ {update,m2},
+ {update,m3},
+ {update,m4},
+ {update,m5},
+ {update,m6},
+ {update,m7},
+ {update,m8},
+ {update,m9},
+ {update,m10}]}],
+ [{"1.0",[{update,m1},
+ {update,m2},
+ {update,m3},
+ {update,m4},
+ {update,m5},
+ {update,m6},
+ {update,m7},
+ {update,m8},
+ {update,m9},
+ {update,m10}]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m.erl
new file mode 100644
index 0000000000..418102bebb
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m.erl
@@ -0,0 +1,11 @@
+-module(m).
+-compile(export_all).
+
+start(NProcs) ->
+ Modules = [m1,m2,m3,m4,m5,m6,m7,m8,m9,m10],
+ Pids = [spawn_link(fun() ->
+ Cs = [M:bar() || M <- Modules],
+ receive stop -> Cs end
+ end) ||
+ _ <- lists:seq(1,NProcs)],
+ {Modules,Pids}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m1.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m1.erl
new file mode 100644
index 0000000000..cacc13f5d7
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m1.erl
@@ -0,0 +1,4 @@
+-module(m1).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m10.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m10.erl
new file mode 100644
index 0000000000..81e120b891
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m10.erl
@@ -0,0 +1,4 @@
+-module(m10).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m2.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m2.erl
new file mode 100644
index 0000000000..481276ba7b
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m2.erl
@@ -0,0 +1,4 @@
+-module(m2).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m3.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m3.erl
new file mode 100644
index 0000000000..9a04ed5fc9
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m3.erl
@@ -0,0 +1,4 @@
+-module(m3).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m4.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m4.erl
new file mode 100644
index 0000000000..90de9a30c9
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m4.erl
@@ -0,0 +1,4 @@
+-module(m4).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m5.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m5.erl
new file mode 100644
index 0000000000..8a9b690dfa
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m5.erl
@@ -0,0 +1,4 @@
+-module(m5).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m6.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m6.erl
new file mode 100644
index 0000000000..cd0d3977ed
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m6.erl
@@ -0,0 +1,4 @@
+-module(m6).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m7.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m7.erl
new file mode 100644
index 0000000000..1f79918d6e
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m7.erl
@@ -0,0 +1,4 @@
+-module(m7).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m8.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m8.erl
new file mode 100644
index 0000000000..2ce03a0b7e
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m8.erl
@@ -0,0 +1,4 @@
+-module(m8).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m9.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m9.erl
new file mode 100644
index 0000000000..1c5f72e628
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-1.1/src/m9.erl
@@ -0,0 +1,4 @@
+-module(m9).
+-compile(export_all).
+%% A module with a big constant...
+bar() -> {now(),[{1,'1',"1"},{2,'2',"2"},{3,'3',"3"},{4,'4',"4"},{5,'5',"5"},{6,'6',"6"},{7,'7',"7"},{8,'8',"8"},{9,'9',"9"},{10,'10',"10"},{11,'11',"11"},{12,'12',"12"},{13,'13',"13"},{14,'14',"14"},{15,'15',"15"},{16,'16',"16"},{17,'17',"17"},{18,'18',"18"},{19,'19',"19"},{20,'20',"20"},{21,'21',"21"},{22,'22',"22"},{23,'23',"23"},{24,'24',"24"},{25,'25',"25"},{26,'26',"26"},{27,'27',"27"},{28,'28',"28"},{29,'29',"29"},{30,'30',"30"},{31,'31',"31"},{32,'32',"32"},{33,'33',"33"},{34,'34',"34"},{35,'35',"35"},{36,'36',"36"},{37,'37',"37"},{38,'38',"38"},{39,'39',"39"},{40,'40',"40"},{41,'41',"41"},{42,'42',"42"},{43,'43',"43"},{44,'44',"44"},{45,'45',"45"},{46,'46',"46"},{47,'47',"47"},{48,'48',"48"},{49,'49',"49"},{50,'50',"50"},{51,'51',"51"},{52,'52',"52"},{53,'53',"53"},{54,'54',"54"},{55,'55',"55"},{56,'56',"56"},{57,'57',"57"},{58,'58',"58"},{59,'59',"59"},{60,'60',"60"},{61,'61',"61"},{62,'62',"62"},{63,'63',"63"},{64,'64',"64"},{65,'65',"65"},{66,'66',"66"},{67,'67',"67"},{68,'68',"68"},{69,'69',"69"},{70,'70',"70"},{71,'71',"71"},{72,'72',"72"},{73,'73',"73"},{74,'74',"74"},{75,'75',"75"},{76,'76',"76"},{77,'77',"77"},{78,'78',"78"},{79,'79',"79"},{80,'80',"80"},{81,'81',"81"},{82,'82',"82"},{83,'83',"83"},{84,'84',"84"},{85,'85',"85"},{86,'86',"86"},{87,'87',"87"},{88,'88',"88"},{89,'89',"89"},{90,'90',"90"},{91,'91',"91"},{92,'92',"92"},{93,'93',"93"},{94,'94',"94"},{95,'95',"95"},{96,'96',"96"},{97,'97',"97"},{98,'98',"98"},{99,'99',"99"},{100,'100',"100"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/ebin/many_mods.app b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/ebin/many_mods.app
new file mode 100644
index 0000000000..98f6527750
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/ebin/many_mods.app
@@ -0,0 +1,7 @@
+%% -*- erlang -*-
+{application, many_mods,
+ [{description, "Application with many modules CXC 138 11"},
+ {vsn, "2.0"},
+ {modules, [{m, 1}]},
+ {registered, []},
+ {applications, [kernel, stdlib]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/ebin/many_mods.appup b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/ebin/many_mods.appup
new file mode 100644
index 0000000000..3a34db78c1
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/ebin/many_mods.appup
@@ -0,0 +1,24 @@
+%% -*- erlang -*-
+{"2.0",
+ [{"1.0",[{update,m},
+ {delete_module,m1},
+ {delete_module,m2},
+ {delete_module,m3},
+ {delete_module,m4},
+ {delete_module,m5},
+ {delete_module,m6},
+ {delete_module,m7},
+ {delete_module,m8},
+ {delete_module,m9},
+ {delete_module,m10}]}],
+ [{"1.0",[{update,m},
+ {add_module,m1},
+ {add_module,m2},
+ {add_module,m3},
+ {add_module,m4},
+ {add_module,m5},
+ {add_module,m6},
+ {add_module,m7},
+ {add_module,m8},
+ {add_module,m9},
+ {add_module,m10}]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/src/m.erl b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/src/m.erl
new file mode 100644
index 0000000000..2edc1e6be4
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/many_mods-2.0/src/m.erl
@@ -0,0 +1,11 @@
+-module(m).
+-compile(export_all).
+
+start(NProcs) ->
+ Modules = [],
+ Pids = [spawn_link(fun() ->
+ Cs = [M:bar() || M <- Modules],
+ receive stop -> Cs end
+ end) ||
+ _ <- lists:seq(1,NProcs)],
+ {Modules,Pids}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_atom.erl b/lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_atom.erl
new file mode 100644
index 0000000000..883688c231
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_atom.erl
@@ -0,0 +1,26 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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$
+%%
+
+-module(vsn_atom).
+
+-vsn(atom).
+
+-export([ok/0]).
+
+ok() ->
+ ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_list.erl b/lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_list.erl
new file mode 100644
index 0000000000..34c38307ba
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_list.erl
@@ -0,0 +1,26 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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$
+%%
+
+-module(vsn_list).
+
+-vsn([list, "of", {some, terms}]).
+
+-export([ok/0]).
+
+ok() ->
+ ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_numeric.erl b/lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_numeric.erl
new file mode 100644
index 0000000000..6bf52753fd
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_numeric.erl
@@ -0,0 +1,26 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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$
+%%
+
+-module(vsn_numeric).
+
+-vsn(231894).
+
+-export([ok/0]).
+
+ok() ->
+ ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_string.erl b/lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_string.erl
new file mode 100644
index 0000000000..aa430a0bb3
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_string.erl
@@ -0,0 +1,26 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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$
+%%
+
+-module(vsn_string).
+
+-vsn("a string").
+
+-export([ok/0]).
+
+ok() ->
+ ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_tuple.erl b/lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_tuple.erl
new file mode 100644
index 0000000000..3ff1018994
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/otp_2740/vsn_tuple.erl
@@ -0,0 +1,26 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance 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$
+%%
+
+-module(vsn_tuple).
+
+-vsn({tuple, ["of", terms]}).
+
+-export([ok/0]).
+
+ok() ->
+ ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/ebin/dummy.app b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/ebin/dummy.app
new file mode 100644
index 0000000000..9efdc2e5da
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/ebin/dummy.app
@@ -0,0 +1,7 @@
+{application,dummy,
+ [{description,"a dummy app"},
+ {vsn,"0.1"},
+ {registered,[dummy_app]},
+ {mod,{dummy_app,[]}},
+ {applications,[kernel,stdlib,sasl]},
+ {modules,[dummy_app,dummy_server,dummy_sup,dummy_sup_2]}]}. \ No newline at end of file
diff --git a/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_app.erl b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_app.erl
new file mode 100644
index 0000000000..51363b3630
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_app.erl
@@ -0,0 +1,9 @@
+-module(dummy_app).
+-behaviour(application).
+
+-export([start/2, stop/1]).
+
+start(_,_) ->
+ dummy_sup:start_link().
+
+stop(_) -> ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_server.erl b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_server.erl
new file mode 100644
index 0000000000..382251eba7
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_server.erl
@@ -0,0 +1,56 @@
+-module(dummy_server).
+-behaviour(gen_server).
+
+-export([start_link/0, set_state/1, get_state/0]).
+
+-export([init/1,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ terminate/2,
+ code_change/3]).
+
+%%
+
+start_link() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
+set_state(What) ->
+ gen_server:call(?MODULE, {set_state, What}).
+
+get_state() ->
+ gen_server:call(?MODULE, get_state).
+
+
+%%
+
+init([]) ->
+ say("init, setting state to 0", []),
+ {ok, 0}.
+
+
+handle_call({set_state, NewState}, _From, _State) ->
+ {reply, {ok, NewState}, NewState};
+
+handle_call(get_state, _From, State) ->
+ {reply, State, State}.
+
+handle_cast('__not_implemented', State) ->
+ {noreply, State}.
+
+handle_info(_Info, State) ->
+ say("info ~p, ~p.", [_Info, State]),
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ say("terminate ~p, ~p", [_Reason, _State]),
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ say("code_change ~p, ~p, ~p", [_OldVsn, State, _Extra]),
+ {ok, State}.
+
+%% Internal
+
+say(Format, Data) ->
+ io:format("~p:~p: ~s~n", [?MODULE, self(), io_lib:format(Format, Data)]).
diff --git a/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup.erl b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup.erl
new file mode 100644
index 0000000000..3d7b5060df
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup.erl
@@ -0,0 +1,15 @@
+-module(dummy_sup).
+-behaviour(supervisor).
+
+-export([start_link/0]).
+-export([init/1]).
+
+start_link() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+init([]) ->
+ DummySup2 = {dummy_sup_2,
+ {dummy_sup_2, start_link, []},
+ permanent, 5000, supervisor, [dummy_sup_2]},
+
+ {ok, {{one_for_one, 10, 10}, [DummySup2]}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl
new file mode 100644
index 0000000000..d936cbcbd6
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl
@@ -0,0 +1,15 @@
+-module(dummy_sup_2).
+-behaviour(supervisor).
+
+-export([start_link/0]).
+-export([init/1]).
+
+start_link() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+init([]) ->
+ Dummy = {dummy_server,
+ {dummy_server, start_link, []},
+ permanent, 5000, worker, [dummy_server]},
+
+ {ok, {{one_for_one, 10, 10}, [Dummy]}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/start b/lib/sasl/test/release_handler_SUITE_data/start
new file mode 100755
index 0000000000..45e526c15f
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/start
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# This program invokes the erlang emulator by calling run_erl.
+# It should only be used at an embedded target system.
+# It should be modified to give the correct flags to erl (via start_erl),
+# e.g -mode embedded -sname XXX
+#
+# Usage: start [Data]
+#
+ROOTDIR=%ROOT%
+
+if [ "x${NODENAME}" = "x" ]
+then
+ echo "ERROR: Variable \$NODENAME is not set!!"
+ exit 1
+fi
+
+if [ -z "$RELDIR" ]
+then
+ RELDIR=$ROOTDIR/releases
+fi
+
+HEART_COMMAND=$ROOTDIR/bin/start
+HW_WD_DISABLE=true
+export HW_WD_DISABLE HEART_COMMAND
+
+START_ERL_DATA=${1:-$RELDIR/start_erl.data}
+
+$ROOTDIR/bin/run_erl /tmp/ $ROOTDIR/log "exec $ROOTDIR/bin/start_erl $ROOTDIR $RELDIR $START_ERL_DATA -heart -sname $NODENAME" > $ROOTDIR/log/run_erl.out 2>&1 &
diff --git a/lib/sasl/test/release_handler_SUITE_data/start_client b/lib/sasl/test/release_handler_SUITE_data/start_client
new file mode 100755
index 0000000000..5ea94d6f7c
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/start_client
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# This program invokes the erlang emulator by calling run_erl.
+# It should only be used at an embedded target system.
+# It should be modified to give the correct flags to erl (via start_erl),
+# e.g -mode embedded -sname XXX
+#
+# Usage: start [Data]
+#
+
+if [ "x${NODENAME}" = "x" ]
+then
+ echo "ERROR: Variable \$NODENAME is not set!!"
+ exit 1
+fi
+
+TESTHOST=`hostname | sed 's/[.].*//'`
+
+ROOTDIR=%ROOT%
+CLIENTDIR=$ROOTDIR/clients/type1/$NODENAME@$TESTHOST
+
+RELDIR=$CLIENTDIR/releases
+
+# Note that this scripts is modified an copied to $CLIENTDIR/bin/start
+# in release_handler_SUITE:copy_client - therefore HEART_COMMAND is as follows:
+HEART_COMMAND=$CLIENTDIR/bin/start
+HW_WD_DISABLE=true
+export HW_WD_DISABLE HEART_COMMAND
+
+START_ERL_DATA=${1:-$RELDIR/start_erl.data}
+
+if [ ! -d /tmp/$NODENAME@$TESTHOST ]
+then
+ mkdir /tmp/$NODENAME@$TESTHOST
+fi
+
+$ROOTDIR/bin/run_erl /tmp/$NODENAME@$TESTHOST/ $CLIENTDIR/log "exec $ROOTDIR/bin/start_erl $ROOTDIR $RELDIR $START_ERL_DATA -heart -sname $NODENAME %CLIENTARGS%" > $CLIENTDIR/log/run_erl.out 2>&1 &
diff --git a/lib/sasl/test/release_handler_SUITE_data/target_system.erl b/lib/sasl/test/release_handler_SUITE_data/target_system.erl
new file mode 120000
index 0000000000..4d36c59632
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/target_system.erl
@@ -0,0 +1 @@
+../../examples/src/target_system.erl \ No newline at end of file
diff --git a/lib/sasl/test/rh_test_lib.erl b/lib/sasl/test/rh_test_lib.erl
new file mode 100644
index 0000000000..99a7f919a7
--- /dev/null
+++ b/lib/sasl/test/rh_test_lib.erl
@@ -0,0 +1,100 @@
+-module(rh_test_lib).
+
+-export([erlsrv/3,
+ erlsrv/4]).
+-export([get_service_args/3,
+ get_service_args/4,
+ get_start_erl_args/1,
+ get_start_erl_args/3,
+ get_client_args/3,
+ get_client_args/4]).
+
+
+erlsrv(Erlsrv,Action,Name) ->
+ erlsrv(Erlsrv,Action,Name,"").
+erlsrv(Erlsrv,Action,Name,Rest) ->
+ Cmd = Erlsrv ++ " " ++ atom_to_list(Action) ++ " " ++ Name ++ " " ++ Rest,
+ io:format("erlsrv cmd: ~p~n",[Cmd]),
+ Port = open_port({spawn, Cmd}, [stream, {line, 100}, eof, in]),
+ Res = recv_prog_output(Port),
+ case Res of
+ [] ->
+ failed;
+ _Y ->
+ io:format("erlsrv res: ~p~n",[_Y]),
+ ok
+ end.
+
+recv_prog_output(Port) ->
+ receive
+ {Port, {data, {eol,Data}}} ->
+ %%io:format("Got data: ~s~n", [Data]),
+ [ Data, "\n" | recv_prog_output(Port)];
+ {Port, {data, {noeol,Data}}} ->
+ %%io:format("Got data: ~s~n", [Data]),
+ [ Data | recv_prog_output(Port)];
+ {Port, _Other} ->
+ %%io:format("Got ~p from port~n", [_Other]),
+ Port ! {self(), close},
+ receive
+ {Port,closed} ->
+ []
+ end
+ end.
+
+get_service_args(RootDir, Sname, StartErlArgs) ->
+ get_service_args(RootDir, "", Sname, StartErlArgs).
+get_service_args(RootDir, RelClientDir, Sname, StartErlArgs) ->
+ LogDir = filename:nativename(filename:join([RootDir,RelClientDir,"log"])),
+ %% start_erl.exe will be found since it is in the same directory as erlsrv.exe
+ %% And heart_restart.bat will be found since the erts bin dir is
+ %% always in the path for the erlang virtual machine.
+ " -machine start_erl.exe -workdir " ++ LogDir ++
+ " -debugtype new -sname " ++ atom_to_list(Sname) ++
+ " -env HEART_COMMAND=heart_restart.bat -args \"" ++ StartErlArgs ++ "\"".
+
+get_start_erl_args(RootDir) ->
+ get_start_erl_args(RootDir,"","").
+get_start_erl_args(RootDir,RelClientDir,ExtraArgs) ->
+ Cookie = atom_to_list(erlang:get_cookie()),
+ RelDir = filename:join([RootDir,RelClientDir,"releases"]),
+ ExtraArgs ++ " -setcookie " ++ Cookie ++
+ " -heart ++ -rootdir " ++ filename:nativename(RootDir) ++
+ " -reldir " ++ filename:nativename(RelDir).
+
+%% Must be called on the master node
+get_client_args(Client,Sname,RootDir) ->
+ get_client_args(Client,Sname,RootDir,node()).
+get_client_args(Client,Sname,RootDir,Master) ->
+ {ok,Host} = inet:gethostname(),
+ Node = atom_to_list(Sname) ++ "@" ++ Host,
+ RelClientDir = filename:join(["clients","type1",Node]),
+ ClientDir = filename:join([RootDir,RelClientDir]),
+ StartPrg = filename:join([ClientDir,"bin","start"]),
+ {" -sasl start_prg \\\\\\\"" ++ StartPrg ++ "\\\\\\\" masters \[" ++
+ single_quote() ++ atom_to_list(Master) ++ single_quote() ++
+ get_client_extra_master(Client,Host) ++
+ "\] client_directory \\\\\\\"" ++ ClientDir ++ "\\\\\\\"" ++
+ get_client_loader_args(Client,Sname,Host),
+ RelClientDir}.
+
+get_client_loader_args(client1,Sname,Host) ->
+ {ok,IpTuple} = inet:getaddr(Host,inet),
+ IpAddr = inet_parse:ntoa(IpTuple),
+ " -loader inet -id " ++
+ atom_to_list(Sname) ++ " -hosts " ++ IpAddr;
+get_client_loader_args(_,_,_) ->
+ "".
+
+get_client_extra_master(client2,Host) ->
+ "," ++ single_quote() ++ "master2@" ++ Host ++ single_quote();
+get_client_extra_master(_,_) ->
+ "".
+
+single_quote() ->
+ case os:type() of
+ {win32,_} ->
+ "\'";
+ _ ->
+ "\\'"
+ end.
diff --git a/lib/sasl/test/sasl.cover b/lib/sasl/test/sasl.cover
new file mode 100644
index 0000000000..d19d3d0180
--- /dev/null
+++ b/lib/sasl/test/sasl.cover
@@ -0,0 +1,2 @@
+{incl_app,sasl,details}.
+
diff --git a/lib/sasl/test/sasl.spec b/lib/sasl/test/sasl.spec
new file mode 100644
index 0000000000..f3de90c9aa
--- /dev/null
+++ b/lib/sasl/test/sasl.spec
@@ -0,0 +1 @@
+{suites,"../sasl_test",all}.
diff --git a/lib/sasl/test/sasl_SUITE.erl b/lib/sasl/test/sasl_SUITE.erl
new file mode 100644
index 0000000000..454095db6a
--- /dev/null
+++ b/lib/sasl/test/sasl_SUITE.erl
@@ -0,0 +1,98 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(sasl_SUITE).
+-include_lib("common_test/include/ct.hrl").
+
+
+% Default timetrap timeout (set in init_per_testcase).
+-define(default_timeout, ?t:minutes(1)).
+-define(application, sasl).
+
+% Test server specific exports
+-export([all/0,groups/0,init_per_group/2,end_per_group/2]).
+-export([init_per_testcase/2, end_per_testcase/2]).
+
+% Test cases must be exported.
+-export([app_test/1,
+ log_mf_h_env/1]).
+
+all() ->
+ [app_test, log_mf_h_env].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+init_per_testcase(_Case, Config) ->
+ ?line Dog=test_server:timetrap(?default_timeout),
+ [{watchdog, Dog}|Config].
+end_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(sasl, allow),
+ ok.
+
+%% OTP-9185 - fail sasl start if some but not all log_mf_h env vars
+%% are given.
+log_mf_h_env(Config) ->
+ PrivDir = ?config(priv_dir,Config),
+ LogDir = filename:join(PrivDir,sasl_SUITE_log_dir),
+ ok = file:make_dir(LogDir),
+ application:stop(sasl),
+ SaslEnv = application:get_all_env(sasl),
+ lists:foreach(fun({E,_V}) -> application:unset_env(sasl,E) end, SaslEnv),
+
+ ok = application:set_env(sasl,error_logger_mf_dir,LogDir),
+ match_error(missing_config,application:start(sasl)),
+
+ ok = application:set_env(sasl,error_logger_mf_maxbytes,"xx"),
+ match_error(bad_config,application:start(sasl)),
+
+ ok = application:set_env(sasl,error_logger_mf_maxbytes,50000),
+ match_error(missing_config,application:start(sasl)),
+
+ ok = application:set_env(sasl,error_logger_mf_maxfiles,"xx"),
+ match_error(bad_config,application:start(sasl)),
+
+ ok = application:set_env(sasl,error_logger_mf_maxfiles,2),
+ ok = application:unset_env(sasl,error_logger_mf_dir),
+ match_error(missing_config,application:start(sasl)),
+
+ ok = application:set_env(sasl,error_logger_mf_dir,xx),
+ match_error(bad_config,application:start(sasl)),
+
+ ok = application:set_env(sasl,error_logger_mf_dir,LogDir),
+ ok = application:start(sasl).
+
+
+%%-----------------------------------------------------------------
+%% Internal
+match_error(Expected,{error,{bad_return,{_,{'EXIT',{Expected,{sasl,_}}}}}}) ->
+ ok;
+match_error(Expected,Actual) ->
+ ?t:fail({unexpected_return,Expected,Actual}).
diff --git a/lib/sasl/test/systools_SUITE.erl b/lib/sasl/test/systools_SUITE.erl
new file mode 100644
index 0000000000..e352247d44
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE.erl
@@ -0,0 +1,2191 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 suite for the systools module.
+%%
+%% The systools module is a wrapper for a number of modules that
+%% handle large parts of the release building functionality
+%% (e.g. checking app files, building a tar file, building
+%% release upgrad scripts.
+%%
+
+
+-module(systools_SUITE).
+
+%-define(debug, true).
+
+-include_lib("test_server/include/test_server.hrl").
+-define(format(S, A), ok).
+-define(datadir, ?config(data_dir, Config)).
+-define(privdir, ?config(priv_dir, Config)).
+-define(copydir, ?config(copy_dir, Config)).
+
+-include_lib("kernel/include/file.hrl").
+
+-export([all/0,suite/0,groups/0,init_per_group/2,end_per_group/2]).
+
+-export([ script_options/1, normal_script/1, no_mod_vsn_script/1,
+ wildcard_script/1, variable_script/1,
+ abnormal_script/1, src_tests_script/1, crazy_script/1,
+ warn_shadow_script/1,
+ included_script/1, included_override_script/1,
+ included_fail_script/1, included_bug_script/1, exref_script/1]).
+-export([ tar_options/1, normal_tar/1, no_mod_vsn_tar/1, variable_tar/1,
+ src_tests_tar/1, shadow_tar/1, var_tar/1,
+ exref_tar/1, link_tar/1, otp_9507/1]).
+-export([ normal_relup/1, abnormal_relup/1, no_appup_relup/1,
+ bad_appup_relup/1, app_start_type_relup/1, otp_3065/1]).
+-export([
+ otp_6226/1]).
+-export([init_per_suite/1, end_per_suite/1,
+ init_per_testcase/2, end_per_testcase/2]).
+
+-import(lists, [foldl/3]).
+
+-define(default_timeout, ?t:minutes(20)).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+suite() ->
+ [{ct_hooks, [ts_install_cth]}].
+
+all() ->
+ [{group, script}, {group, tar}, {group, relup},
+ {group, tickets}].
+
+groups() ->
+ [{script, [],
+ [script_options, normal_script, no_mod_vsn_script,
+ wildcard_script, variable_script, abnormal_script,
+ src_tests_script, crazy_script, warn_shadow_script,
+ included_script, included_override_script,
+ included_fail_script, included_bug_script, exref_script,
+ otp_3065]},
+ {tar, [],
+ [tar_options, normal_tar, no_mod_vsn_tar, variable_tar,
+ src_tests_tar, shadow_tar, var_tar,
+ exref_tar, link_tar, otp_9507]},
+ {relup, [],
+ [normal_relup, abnormal_relup, no_appup_relup,
+ bad_appup_relup, app_start_type_relup]},
+ {tickets, [], [otp_6226]}].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+init_per_suite(Config) when is_list(Config) ->
+ %% Make of copy of the data directory.
+ DataDir = ?datadir,
+ PrivDir = ?privdir,
+ ?line CopyDir = fname(PrivDir, "datacopy"),
+ ?line TarFile = fname(PrivDir, "datacopy.tgz"),
+ ?line {ok, Tar} = erl_tar:open(TarFile, [write, compressed]),
+ ?line ok = erl_tar:add(Tar, DataDir, CopyDir, [compressed]),
+ ?line ok = erl_tar:close(Tar),
+ ?line ok = erl_tar:extract(TarFile, [compressed]),
+ ?line ok = file:delete(TarFile),
+
+ %% Compile source files in the copy directory.
+ ?line Sources = filelib:wildcard(fname([CopyDir,'*','*','*','*','*.erl'])),
+ ?line lists:foreach(fun compile_source/1, Sources),
+
+ %% To use in end_per_testcase
+ Path = code:get_path(),
+ {ok,Cwd} = file:get_cwd(),
+
+ [{copy_dir, CopyDir}, {cwd,Cwd}, {path,Path} | Config].
+
+compile_source(File) ->
+ %% The compiler will no longer create a Beam file
+ %% with a module name that does not match the output
+ %% file, so we must compile to a binary and write
+ %% the output file ourselves.
+ U = filename:dirname(filename:dirname(File)),
+ Base = filename:rootname(filename:basename(File)),
+ OutFile = filename:join([U,"ebin",Base++".beam"]),
+ OutFileTemp = OutFile ++ "#",
+ {ok,_,Code} = compile:file(File, [binary]),
+ ok = file:write_file(OutFileTemp, Code),
+ file:rename(OutFileTemp, OutFile).
+
+end_per_suite(Conf) when is_list(Conf) ->
+ %% Nothing.
+ Conf.
+
+init_per_testcase(link_tar, Config) ->
+ case os:type() of
+ {unix, _} -> init_per_testcase(dummy, Config);
+ {win32, _} -> {skip, "Skip on windows"}
+ end;
+init_per_testcase(_Case, Config) ->
+ ?line Dog = test_server:timetrap(?default_timeout),
+ [{watchdog, Dog}|Config].
+
+end_per_testcase(_Case, Config) ->
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ case {?config(path,Config),?config(cwd,Config)} of
+ {undefined,undefined} ->
+ ok;
+ {Path,Cwd} ->
+ true = code:set_path(Path),
+ ok = file:set_cwd(Cwd)
+ end,
+ ok.
+
+
+
+%% Usage:
+%% systools:make_script("RelName")
+%% Make a boot file from RelName.rel.
+%% Generates RelName.{script,boot}
+%% systools:make_tar("RelName")
+%% Make a release package from RelName.rel.
+%% Generates RelName.tar,Z
+%% systools:script2boot(File)
+%% File.script -> File.boot
+%% systools:make_relup("Target", ["UpFromRel"...], ["DownToRel"...], Opts)
+%% Gather all appup scripts to the relup file
+%%
+
+
+%% make_script
+%%
+script_options(suite) -> [];
+script_options(doc) ->
+ ["Check illegal script options."];
+script_options(Config) when is_list(Config) ->
+ ?line {'EXIT',{{badarg,[{path,["Path",12,"Another"]}]}, _}} =
+ (catch systools:make_script("release", [{path,["Path",12,"Another"]}])),
+ ?line {'EXIT',{{badarg,[sillent]}, _}} =
+ (catch systools:make_script("release",
+ [{path,["Path","Another"]},sillent])),
+ ?line {'EXIT',{{badarg,[locall]}, _}} =
+ (catch systools:make_script("release",
+ [{path,["Path","Another"]},locall])),
+ ?line {'EXIT',{{badarg,[src_testsxx]}, _}} =
+ (catch systools:make_script("release",
+ [{path,["Path"]},src_testsxx])),
+ ?line {'EXIT',{{badarg,[{variables, {"TEST", "/home/lib"}}]}, _}} =
+ (catch systools:make_script("release",
+ [{variables, {"TEST", "/home/lib"}}])),
+ ?line {'EXIT',{{badarg,[{variables, [{a, b}, {"a", "b"}]}]}, _}} =
+ (catch systools:make_script("release",
+ [{variables, [{a, b}, {"a", "b"}]}])),
+ ?line {'EXIT',{{badarg,[exreff]}, _}} =
+ (catch systools:make_script("release",
+ [{path,["Path","Another"]},exreff])),
+ ?line {'EXIT',{{badarg,[{exref,["appl"]}]}, _}} =
+ (catch systools:make_script("release", [{exref,["appl"]}])),
+ ?line {'EXIT',{{badarg,[{machine, "appl"}]}, _}} =
+ (catch systools:make_script("release", [{machine,"appl"}])),
+ ok.
+
+
+%% make_script
+%%
+normal_script(suite) -> [];
+normal_script(doc) ->
+ ["Check that make_script handles normal case."];
+normal_script(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line PSAVE = code:get_path(), % Save path
+
+ ?line {LatestDir, LatestName} = create_script(latest,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line LibDir = fname([DataDir, d_normal, lib]),
+ ?line P1 = fname([LibDir, 'db-2.1', ebin]),
+ ?line P2 = fname([LibDir, 'fe-3.1', ebin]),
+
+ ?line true = code:add_patha(P1),
+ ?line true = code:add_patha(P2),
+
+ ?line ok = file:set_cwd(LatestDir),
+
+ ?line ok = systools:make_script(filename:basename(LatestName)),
+ ?line {ok, _} = read_script_file(LatestName), % Check readabillity
+
+ %% Check the same but w. silent flag
+ ?line {ok, _, []} = systools:make_script(LatestName, [silent]),
+
+ %% Use the local option
+ ?line ok = systools:make_script(LatestName, [local]),
+ ?line ok = check_script_path(LatestName),
+
+ %% use the path option
+ ?line code:set_path(PSAVE), % Restore path
+ %% Mess up std path:
+ ?line true = code:add_patha(fname([LibDir, 'db-1.0', ebin])),
+ ?line true = code:add_patha(fname([LibDir, 'fe-2.1', ebin])),
+
+ ?line error = systools:make_script(LatestName), %should fail
+ ?line ok = systools:make_script(LatestName,[{path, [P1, P2]}]),
+
+ ?line ok = file:set_cwd(OldDir),
+ ?line code:set_path(PSAVE), % Restore path
+ ok.
+
+
+%% make_script
+%%
+no_mod_vsn_script(suite) -> [];
+no_mod_vsn_script(doc) ->
+ ["Check that make_script handles normal case.",
+ "Modules specified without version in .app file (db-3.1)."
+ "Note that this is now the normal way - i.e. systools now "
+ "ignores the module versions in the .app file."];
+no_mod_vsn_script(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line PSAVE = code:get_path(), % Save path
+
+ ?line {LatestDir, LatestName} = create_script(latest_no_mod_vsn,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line LibDir = fname([DataDir, d_normal, lib]),
+ ?line P1 = fname([LibDir, 'db-3.1', ebin]),
+ ?line P2 = fname([LibDir, 'fe-3.1', ebin]),
+
+ ?line true = code:add_patha(P1),
+ ?line true = code:add_patha(P2),
+
+ ?line ok = file:set_cwd(LatestDir),
+
+ ?line ok = systools:make_script(filename:basename(LatestName)),
+ ?line {ok, _} = read_script_file(LatestName), % Check readabillity
+
+ %% Check the same but w. silent flag
+ ?line {ok, _, []} = systools:make_script(LatestName, [silent]),
+
+ %% Use the local option
+ ?line ok = systools:make_script(LatestName, [local]),
+ ?line ok = check_script_path(LatestName),
+
+ %% use the path option
+ ?line code:set_path(PSAVE), % Restore path
+ %% Mess up std path:
+ ?line true = code:add_patha(fname([LibDir, 'db-1.0', ebin])),
+ ?line true = code:add_patha(fname([LibDir, 'fe-2.1', ebin])),
+
+ ?line error = systools:make_script(LatestName), %should fail
+ ?line ok = systools:make_script(LatestName,
+ [{path, [P1, P2]}]),
+
+ ?line ok = file:set_cwd(OldDir),
+ ?line code:set_path(PSAVE), % Restore path
+ ok.
+
+
+%% make_script
+%%
+wildcard_script(suite) -> [];
+wildcard_script(doc) ->
+ ["Check that make_script handles wildcards in path."];
+wildcard_script(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+
+ ?line {LatestDir, LatestName} = create_script(latest,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line LibDir = fname([DataDir, d_normal, lib]),
+ ?line WildDir = fname([LibDir, '*', ebin]),
+
+ ?line ok = file:set_cwd(LatestDir),
+
+ ?line error = systools:make_script(filename:basename(LatestName)),
+
+ ?line ok = systools:make_script(LatestName,
+ [{path, [WildDir]}]),
+
+ ?line {ok, _} = read_script_file(LatestName), % Check readabillity
+
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+
+%% make_script
+%%
+variable_script(suite) -> [];
+variable_script(doc) ->
+ ["Add own installation dependent variable in script."];
+variable_script(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+
+ ?line {LatestDir, LatestName} = create_script(latest,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line LibDir = fname([DataDir, d_normal, lib]),
+ ?line P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
+
+ ?line ok = file:set_cwd(LatestDir),
+
+ ?line ok = systools:make_script(LatestName,
+ [{path, P},
+ {variables, [{"TEST", LibDir}]}]),
+
+ %% Check variables
+ ?line ok = check_var_script_file([fname(['$TEST', 'db-2.1', ebin]),
+ fname(['$TEST', 'fe-3.1', ebin])],
+ P,
+ LatestName),
+
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+%% make_script
+%%
+abnormal_script(suite) -> [];
+abnormal_script(doc) ->
+ ["Abnormal cases."];
+abnormal_script(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+
+ ?line {LatestDir, LatestName} = create_script(latest,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+
+ ?line ok = file:set_cwd(LatestDir),
+ ?line LibDir = fname([DataDir, d_bad_app_vsn, lib]),
+ ?line P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
+
+ %% Check wrong app vsn
+ ?line error = systools:make_script(LatestName, [{path, P}]),
+ ?line {error,
+ systools_make,
+ [{error_reading, {db, {no_valid_version,
+ {{"should be","2.1"},
+ {"found file", _, "2.0"}}}}}]} =
+ systools:make_script(LatestName, [silent, {path, P}]),
+
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+
+%% make_script
+%%
+src_tests_script(suite) -> [];
+src_tests_script(doc) ->
+ ["Do not check date of object file or that source code can be found."];
+src_tests_script(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line PSAVE = code:get_path(), % Save path
+
+ ?line {LatestDir, LatestName} = create_script(latest,Config),
+ ?line BootFile = LatestName ++ ".boot",
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line LibDir = fname([DataDir, d_missing_src, lib]),
+ ?line P1 = fname([LibDir, 'db-2.1', ebin]),
+ ?line P2 = fname([LibDir, 'fe-3.1', ebin]),
+ N = [P1, P2],
+
+ ?line ok = file:set_cwd(LatestDir),
+
+ %% Manipulate the modification date of a beam file so it seems
+ %% older than its .erl file
+ ?line Erl = filename:join([P1,"..","src","db1.erl"]),
+ ?line {ok, FileInfo=#file_info{mtime={{Y,M,D},T}}} = file:read_file_info(Erl),
+ ?line Beam = filename:join(P1,"db1.beam"),
+ ?line ok=file:write_file_info(Beam, FileInfo#file_info{mtime={{Y-1,M,D},T}}),
+
+ %% Remove a .erl file
+ ?line Erl2 = filename:join([P1,"..","src","db2.erl"]),
+ ?line file:delete(Erl2),
+
+ %% Then make script
+
+ %% .boot file should not exist
+ ?line ok = file:delete(BootFile),
+ ?line false = filelib:is_regular(BootFile),
+ %% With warnings_as_errors and src_tests option, an error should be issued
+ ?line error =
+ systools:make_script(LatestName, [silent, {path, N}, src_tests,
+ warnings_as_errors]),
+ ?line error =
+ systools:make_script(LatestName, [{path, N}, src_tests,
+ warnings_as_errors]),
+
+ %% due to warnings_as_errors .boot file should still not exist
+ ?line false = filelib:is_regular(BootFile),
+
+ %% Two warnings should be issued when src_tests is given
+ %% 1. old object code for db1.beam
+ %% 2. missing source code for db2.beam
+ ?line {ok, _, [{warning,{obj_out_of_date,_}},
+ {warning,{source_not_found,_}}]} =
+ systools:make_script(LatestName, [silent, {path, N}, src_tests]),
+
+ %% .boot file should exist now
+ ?line true = filelib:is_regular(BootFile),
+
+ %% Without the src_tests option, no warning should be issued
+ ?line {ok, _, []} =
+ systools:make_script(LatestName, [silent, {path, N}]),
+
+ %% Check that the old no_module_tests option (from the time when
+ %% it was default to do the src_test) is ignored
+ ?line {ok, _, [{warning,{obj_out_of_date,_}},
+ {warning,{source_not_found,_}}]} =
+ systools:make_script(LatestName, [silent,
+ {path, N},
+ no_module_tests,
+ src_tests]),
+
+ ?line ok = file:set_cwd(OldDir),
+ ?line code:set_path(PSAVE),
+ ok.
+
+%% make_script
+%%
+warn_shadow_script(suite) -> [];
+warn_shadow_script(doc) ->
+ ["Check that jam file out of date warning doesn't",
+ "shadow bad module version error."];
+warn_shadow_script(Config) when is_list(Config) ->
+ %% This test has been removed since the 'vsn' attribute is
+ %% not used any more, starting with R6. No warning
+ %% 'obj_out_of_date' seemed to be generated.
+ true.
+
+
+%% make_script
+%%
+crazy_script(suite) -> [];
+crazy_script(doc) ->
+ ["Do the crazy cases."];
+crazy_script(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+
+ ?line {LatestDir, LatestName} = create_script(latest, Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line LibDir = fname([DataDir, d_normal, lib]),
+ ?line P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
+
+ ?line ok = file:set_cwd(LatestDir),
+
+ %% Run with bad path
+ ?line error = systools:make_script(LatestName),
+ ?line {error, _, [{error_reading, _}, {error_reading, _}]} =
+ systools:make_script(LatestName, [silent]),
+
+ %% Run with .rel file lacking kernel
+ ?line {LatestDir2, LatestName2} = create_script(latest_nokernel, Config),
+ ?line ok = file:set_cwd(LatestDir2),
+
+ ?line error = systools:make_script(LatestName2),
+ ?line {error, _, {missing_mandatory_app,[kernel,stdlib]}} =
+ systools:make_script(LatestName2, [silent,{path,P}]),
+
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+%% make_script
+%%
+included_script(suite) -> [];
+included_script(doc) ->
+ ["Check that make_script handles generation of script",
+ "for applications with included applications."];
+included_script(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line {LatestDir, LatestName} = create_include_files(inc1, Config),
+ ?line ok = file:set_cwd(LatestDir),
+ ?line ok = systools:make_script(LatestName),
+ ?line ok = check_include_script(LatestName,
+ [t1, t2, t3, t5, t4, t6],
+ [t1, t3, t6]),
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+%% make_script
+%%
+included_override_script(suite) -> [];
+included_override_script(doc) ->
+ ["Check that make_script handles generation of script",
+ "for applications with included applications which are override by",
+ "the .rel file."];
+included_override_script(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line {LatestDir, LatestName} = create_include_files(inc2, Config),
+ ?line ok = file:set_cwd(LatestDir),
+ ?line ok = systools:make_script(LatestName),
+ ?line ok = check_include_script(LatestName,
+ [t1, t2, t3, t4, t6, t5],
+ [t1, t3, t6, t5]),
+
+ ?line {_, LatestName1} = create_include_files(inc3, Config),
+ ?line ok = systools:make_script(LatestName1),
+ ?line ok = check_include_script(LatestName1,
+ [t3, t5, t4, t6, t1, t2],
+ [t3, t6, t1, t2]),
+
+ ?line {_, LatestName2} = create_include_files(inc4, Config),
+ ?line ok = systools:make_script(LatestName2),
+ ?line ok = check_include_script(LatestName2,
+ [t3, t4, t6, t5, t1, t2],
+ [t3, t6, t5, t1, t2]),
+
+ ?line {_, LatestName3} = create_include_files(inc5, Config),
+ ?line ok = systools:make_script(LatestName3),
+ ?line ok = check_include_script(LatestName3,
+ [t3, t4, t6, t1, t2],
+ [t3, t6, t1, t2]),
+
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+%% make_script
+%%
+included_fail_script(suite) -> [];
+included_fail_script(doc) ->
+ ["Check that make_script handles errors then generating",
+ "script with included applications."];
+included_fail_script(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line {LatestDir, LatestName} = create_include_files(inc6, Config),
+ ?line ok = file:set_cwd(LatestDir),
+ ?line {error, _, {undefined_applications,[t2]}} =
+ systools:make_script(LatestName, [silent]),
+
+ ?line {_, LatestName1} = create_include_files(inc7, Config),
+ ?line {error, _, {duplicate_include,[{{t5,t7,_,_},{t5,t6,_,_}}]}} =
+ systools:make_script(LatestName1, [silent]),
+
+ ?line {_, LatestName3} = create_include_files(inc9, Config),
+ ?line {error, _, {circular_dependencies,[{t10,_},{t8,_}]}} =
+ systools:make_script(LatestName3, [silent]),
+
+ ?line {_, LatestName4} = create_include_files(inc10, Config),
+ ?line {error, _, [{error_reading,{t9,{override_include,[t7]}}}]} =
+ systools:make_script(LatestName4, [silent]),
+
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+%% make_script
+%%
+included_bug_script(suite) -> [];
+included_bug_script(doc) ->
+ ["Check that make_script handles generation of script",
+ "with difficult dependency for included applications."];
+included_bug_script(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line {LatestDir, LatestName} = create_include_files(inc11, Config),
+ ?line ok = file:set_cwd(LatestDir),
+ ?line ok = systools:make_script(LatestName),
+ ?line ok = check_include_script(LatestName,
+ [t13, t11, t12],
+ [t11, t12]),
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+
+%% make_script
+%%
+otp_3065(suite) -> [];
+otp_3065(doc) ->
+ ["Circular dependencies in systools:make_script()."];
+otp_3065(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line {LatestDir, LatestName} = create_include_files(otp_3065, Config),
+ ?line ok = file:set_cwd(LatestDir),
+ ?line ok = systools:make_script(LatestName),
+ ?line ok = check_include_script(LatestName,
+ [aa12, chAts, chTraffic],
+ [chTraffic]),
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+
+%% make_script
+%%
+exref_script(suite) -> [];
+exref_script(doc) ->
+ ["Check that make_script exref option works."];
+exref_script(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line PSAVE = code:get_path(), % Save path
+
+ ?line {LatestDir, LatestName} = create_script(latest,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line LibDir = fname([DataDir, d_normal, lib]),
+ ?line P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
+
+ ?line ok = file:set_cwd(LatestDir),
+
+ ?line {ok, _, _} = systools:make_script(LatestName, [{path,P}, silent]),
+
+ %% Complete exref
+ ?line {ok, _, W1} =
+ systools:make_script(LatestName, [exref, {path,P}, silent]),
+ ?line check_exref_warnings(with_db1, W1),
+ ?line {ok, _} = read_script_file(LatestName), % Check readabillity
+
+ %% Only exref the db application.
+ ?line {ok, _, W2} =
+ systools:make_script(LatestName, [{exref,[db]}, {path,P}, silent]),
+ ?line check_exref_warnings(with_db1, W2),
+ ?line {ok, _} = read_script_file(LatestName), % Check readabillity
+
+ %% Only exref the fe application.
+ ?line {ok, _, W3} =
+ systools:make_script(LatestName, [{exref,[fe]}, {path,P}, silent]),
+ ?line check_exref_warnings(without_db1, W3),
+ ?line {ok, _} = read_script_file(LatestName), % Check readabillity
+
+ %% exref the db and stdlib applications.
+ ?line {ok, _, W4} =
+ systools:make_script(LatestName, [{exref,[db,stdlib]}, {path,P}, silent]),
+ ?line check_exref_warnings(with_db1, W4),
+ ?line {ok, _} = read_script_file(LatestName), % Check readabillity
+ ?line ok = file:set_cwd(OldDir),
+ ?line code:set_path(PSAVE), % Restore path
+ ok.
+
+check_exref_warnings(with_db1, W) ->
+ case get_exref(undef, W) of
+ {ok, [{db2,non_existing_func,0},
+ {fe2,non_existing_func,0},
+ {lists,non_existing_func,1}]} ->
+ ok;
+ {ok, L} ->
+ test_server:fail({exref_warning_undef, L});
+ _E ->
+ test_server:fail({bad_undef,_E})
+ end;
+check_exref_warnings(without_db1, W) ->
+ case get_exref(undef, W) of
+ false ->
+ ok;
+ {ok, L} ->
+ test_server:fail({exref_warning_undef, L})
+ end.
+
+get_exref(undef, W) -> filter(no_hipe(get_exref1(exref_undef, W))).
+
+filter(false) ->
+ false;
+filter({ok, W}) ->
+ {ok, filter(W)};
+filter(L) ->
+ lists:filter(fun%({hipe_consttab,_,_}) -> false;
+ ({int,_,_}) -> false;
+ ({i,_,_}) -> false;
+ ({crypto,_,_}) -> false;
+ (_) -> true
+ end,
+ L).
+
+get_exref1(T, [{warning, {T, Value}}|_]) -> {ok, Value};
+get_exref1(T, [_|W]) -> get_exref1(T, W);
+get_exref1(_, []) -> false.
+
+no_hipe(false) ->
+ false;
+no_hipe({ok, Value}) ->
+ case erlang:system_info(hipe_architecture) of
+ undefined ->
+ Hipe = "hipe",
+ Fun = fun({M,_,_}) -> not lists:prefix(Hipe, atom_to_list(M)) end,
+ NewValue = lists:filter(Fun, Value),
+ {ok, NewValue};
+ _Arch ->
+ {ok, Value}
+ end.
+
+%% tar_options
+%%
+tar_options(suite) -> [];
+tar_options(doc) ->
+ ["Check illegal tar options."];
+tar_options(Config) when is_list(Config) ->
+ ?line {'EXIT',{{badarg,[{path,["Path",12,"Another"]}]}, _}} =
+ (catch systools:make_tar("release", [{path,["Path",12,"Another"]}])),
+ ?line {'EXIT',{{badarg,[sillent]}, _}} =
+ (catch systools:make_tar("release",
+ [{path,["Path","Another"]},sillent])),
+ ?line {'EXIT',{{badarg,[{dirs,["dirs"]}]}, _}} =
+ (catch systools:make_tar("release", [{dirs, ["dirs"]}])),
+ ?line {'EXIT',{{badarg,[{erts, illegal}]}, _}} =
+ (catch systools:make_tar("release", [{erts, illegal}])),
+ ?line {'EXIT',{{badarg,[src_testsxx]}, _}} =
+ (catch systools:make_tar("release",
+ [{path,["Path"]},src_testsxx])),
+ ?line {'EXIT',{{badarg,[{variables, [{a, b}, {"a", "b"}]}]}, _}} =
+ (catch systools:make_tar("release",
+ [{variables, [{a, b}, {"a", "b"}]}])),
+ ?line {'EXIT',{{badarg,[{var_tar, illegal}]}, _}} =
+ (catch systools:make_tar("release", [{var_tar, illegal}])),
+ ?line {'EXIT',{{badarg,[exreff]}, _}} =
+ (catch systools:make_tar("release",
+ [{path,["Path","Another"]},exreff])),
+ ?line {'EXIT',{{badarg,[{exref,["appl"]}]}, _}} =
+ (catch systools:make_tar("release", [{exref,["appl"]}])),
+ ?line {'EXIT',{{badarg,[{machine, "appl"}]}, _}} =
+ (catch systools:make_tar("release", [{machine,"appl"}])),
+ ok.
+
+
+%% normal_tar
+%%
+normal_tar(suite) -> [];
+normal_tar(doc) ->
+ ["Check normal case"];
+normal_tar(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+
+ ?line {LatestDir, LatestName} = create_script(latest,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line LibDir = fname([DataDir, d_normal, lib]),
+ ?line P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
+
+ ?line ok = file:set_cwd(LatestDir),
+
+ ?line {ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]),
+ ?line ok = systools:make_tar(LatestName, [{path, P}]),
+ ?line ok = check_tar(fname([lib,'db-2.1',ebin,'db.app']), LatestName),
+ ?line {ok, _, _} = systools:make_tar(LatestName, [{path, P}, silent]),
+ ?line ok = check_tar(fname([lib,'fe-3.1',ebin,'fe.app']), LatestName),
+
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+%% no_mod_vsn_tar
+%%
+no_mod_vsn_tar(suite) -> [];
+no_mod_vsn_tar(doc) ->
+ ["Check normal case",
+ "Modules specified without version in .app file (db-3.1)."
+ "Note that this is now the normal way - i.e. systools now "
+ "ignores the module versions in the .app file."];
+no_mod_vsn_tar(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+
+ ?line {LatestDir, LatestName} = create_script(latest_no_mod_vsn,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line LibDir = fname([DataDir, d_normal, lib]),
+ ?line P = [fname([LibDir, 'db-3.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
+
+ ?line ok = file:set_cwd(LatestDir),
+
+ ?line {ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]),
+ ?line ok = systools:make_tar(LatestName, [{path, P}]),
+ ?line ok = check_tar(fname([lib,'db-3.1',ebin,'db.app']), LatestName),
+ ?line {ok, _, _} = systools:make_tar(LatestName, [{path, P}, silent]),
+ ?line ok = check_tar(fname([lib,'fe-3.1',ebin,'fe.app']), LatestName),
+
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+%% variable_tar
+%%
+variable_tar(suite) -> [];
+variable_tar(doc) ->
+ ["Use variable and create separate tar (included in generated tar)."];
+variable_tar(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+
+ ?line {LatestDir, LatestName} = create_script(latest,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line LibDir = fname([DataDir, d_normal, lib]),
+ ?line P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
+
+ ?line ok = file:set_cwd(LatestDir),
+
+ ?line {ok, _, _} = systools:make_script(LatestName,
+ [silent,
+ {path, P},
+ {variables,[{"TEST", LibDir}]}]),
+
+ ?line ok = systools:make_tar(LatestName, [{path, P},
+ {variables,[{"TEST", LibDir}]}]),
+ ?line ok = check_var_tar("TEST", LatestName),
+
+ ?line {ok, _, _} = systools:make_tar(LatestName,
+ [{path, P}, silent,
+ {variables,[{"TEST", LibDir}]}]),
+ ?line ok = check_var_tar("TEST", LatestName),
+
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+%% link_tar
+%%
+link_tar(suite) -> [];
+link_tar(doc) ->
+ ["Check that symlinks in applications are handled correctly"];
+link_tar(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+
+ ?line {LatestDir, LatestName} = create_script(latest,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line LibDir = fname([DataDir, d_links, lib]),
+ ?line P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
+
+ %% Make some links
+ ?line Db1Erl = fname(['db-2.1',src,'db1.erl']),
+ ?line NormalDb1Erl = fname([DataDir,d_normal,lib,Db1Erl]),
+ ?line LinkDb1Erl = fname([LibDir, Db1Erl]),
+ ?line ok = file:make_symlink(NormalDb1Erl, LinkDb1Erl),
+ ?line Db1Beam = fname(['db-2.1',ebin,'db1.beam']),
+ ?line NormalDb1Beam = fname([DataDir,d_normal,lib,Db1Beam]),
+ ?line LinkDb1Beam = fname([LibDir, Db1Beam]),
+ ?line ok = file:make_symlink(NormalDb1Beam, LinkDb1Beam),
+ ?line FeApp = fname(['fe-3.1',ebin,'fe.app']),
+ ?line NormalFeApp = fname([DataDir,d_normal,lib,FeApp]),
+ ?line LinkFeApp = fname([LibDir, FeApp]),
+ ?line ok = file:make_symlink(NormalFeApp, LinkFeApp),
+
+ %% Create the tar and check that the linked files are included as
+ %% regular files
+ ?line ok = file:set_cwd(LatestDir),
+
+ ?line {ok,_,[]} = systools:make_script(LatestName, [{path, P},silent]),
+
+ ?line {ok, _, []} = systools:make_tar(LatestName, [{path, P}, silent]),
+ ?line ok = check_tar_regular(?privdir,
+ [fname([lib,FeApp]),
+ fname([lib,Db1Beam])],
+ LatestName),
+
+ ?line {ok, _, []} = systools:make_tar(LatestName, [{path, P}, silent,
+ {dirs, [src]}]),
+ ?line ok = check_tar_regular(?privdir,
+ [fname([lib,FeApp]),
+ fname([lib,Db1Beam]),
+ fname([lib,Db1Erl])],
+ LatestName),
+
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+%% src_tests_tar
+%%
+src_tests_tar(suite) -> [];
+src_tests_tar(doc) ->
+ ["Do not check date of object file or that source code can be found."];
+src_tests_tar(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+
+ ?line {LatestDir, LatestName} = create_script(latest,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line LibDir = fname([DataDir, d_missing_src, lib]),
+ ?line P1 = fname([LibDir, 'db-2.1', ebin]),
+ ?line P2 = fname([LibDir, 'fe-3.1', ebin]),
+ P = [P1, P2],
+
+ ?line ok = file:set_cwd(LatestDir),
+
+ %% Manipulate the modification date of a beam file so it seems
+ %% older than the .erl file
+ Erl = filename:join([P1,"..","src","db1.erl"]),
+ {ok, FileInfo=#file_info{mtime={{Y,M,D},T}}} = file:read_file_info(Erl),
+ Beam = filename:join(P1,"db1.beam"),
+ ok = file:write_file_info(Beam, FileInfo#file_info{mtime={{Y-1,M,D},T}}),
+
+ %% Remove a .erl file
+ ?line Erl2 = filename:join([P1,"..","src","db2.erl"]),
+ ?line file:delete(Erl2),
+
+ ?line ok = systools:make_script(LatestName, [{path, P}]),
+
+ %% Then make tar - two warnings should be issued when
+ %% src_tests is given
+ %% 1. old object code for db1.beam
+ %% 2. missing source code for db2.beam
+ ?line {ok, _, [{warning,{obj_out_of_date,_}},
+ {warning,{source_not_found,_}}]} =
+ systools:make_tar(LatestName, [{path, P}, silent,
+ {dirs, [src]},
+ src_tests]),
+ ?line ok = check_tar(fname([lib,'db-2.1',src,'db1.erl']), LatestName),
+
+ %% Without the src_tests option, no warning should be issued
+ ?line {ok, _, []} = systools:make_tar(LatestName, [{path, P}, silent,
+ {dirs, [src]}]),
+ ?line ok = check_tar(fname([lib,'db-2.1',src,'db1.erl']), LatestName),
+
+ %% Check that the old no_module_tests option (from the time when
+ %% it was default to do the src_test) is ignored
+ ?line {ok, _, [{warning,{obj_out_of_date,_}},
+ {warning,{source_not_found,_}}]} =
+ systools:make_tar(LatestName, [{path, P}, silent,
+ {dirs, [src]},
+ no_module_tests,
+ src_tests]),
+ ?line ok = check_tar(fname([lib,'db-2.1',src,'db1.erl']), LatestName),
+
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+%% shadow_tar
+%%
+shadow_tar(suite) -> [];
+shadow_tar(doc) ->
+ ["Check that jam file out of date warning doesn't",
+ "shadow bad module version error."];
+shadow_tar(Config) when is_list(Config) ->
+ % This test has been commented out since the 'vsn' attribute is not used
+ % any more, starting with R6. No warning 'obj_out_of_date' seemed to be
+ % generated.
+ true;
+shadow_tar(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line PSAVE = code:get_path(), % Save path
+
+ ?line {LatestDir, LatestName} = create_script(latest,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line LibDir = fname([DataDir, 'd_bad_mod+warn', lib]),
+ ?line P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
+
+ ?line ok = file:set_cwd(LatestDir),
+
+ ?line {error, _, _} = systools:make_tar(LatestName, [{path, P}, silent]),
+ ?line {error, _, _} = systools:make_tar(LatestName, [{path, P}, silent,
+ {dirs, [src]}]),
+ ?line ok = file:set_cwd(OldDir),
+ ?line code:set_path(PSAVE),
+ ok.
+
+
+%% var_tar
+%%
+var_tar(suite) -> [];
+var_tar(doc) ->
+ ["Check that make_tar handles generation and placement of tar",
+ "files for variables outside the main tar file.",
+ "Test the {var_tar, include | ownfile | omit} option."];
+var_tar(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+ ?line PSAVE = code:get_path(), % Save path
+
+ ?line {LatestDir, LatestName} = create_script(latest,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line LibDir = fname([DataDir, d_normal, lib]),
+ ?line P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
+
+ ?line ok = file:set_cwd(LatestDir),
+
+ ?line {ok, _, _} = systools:make_script(LatestName,
+ [silent,
+ {path, P},
+ {variables,[{"TEST", LibDir}]}]),
+
+ ?line ok = systools:make_tar(LatestName, [{path, P},
+ {var_tar, ownfile},
+ {variables,[{"TEST", LibDir}]}]),
+
+ ?line true = exists_tar_file("TEST"), %% Also removes the file !
+ ?line {error, {not_generated, _}} = check_var_tar("TEST", LatestName),
+
+ ?line ok = systools:make_tar(LatestName, [{path, P},
+ {var_tar, omit},
+ {variables,[{"TEST", LibDir}]}]),
+
+ ?line {error, {not_generated, _}} = check_var_tar("TEST", LatestName),
+ ?line false = exists_tar_file("TEST"),
+
+ ?line ok = systools:make_tar(LatestName, [{path, P},
+ {var_tar, include},
+ {variables,[{"TEST", LibDir}]}]),
+
+ ?line ok = check_var_tar("TEST", LatestName),
+ ?line false = exists_tar_file("TEST"),
+
+ ?line ok = file:set_cwd(OldDir),
+ ?line code:set_path(PSAVE),
+ ok.
+
+
+%% exref_tar
+%%
+exref_tar(suite) -> [];
+exref_tar(doc) ->
+ ["Check exref option."];
+exref_tar(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+
+ ?line {LatestDir, LatestName} = create_script(latest,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line LibDir = fname([DataDir, d_normal, lib]),
+ ?line P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
+
+ ?line ok = file:set_cwd(LatestDir),
+
+ ?line {ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]),
+
+ %% Complete exref
+ ?line {ok, _, W1} =
+ systools:make_tar(LatestName, [exref, {path, P}, silent]),
+ ?line check_exref_warnings(with_db1, W1),
+ ?line ok = check_tar(fname([lib,'db-2.1',ebin,'db.app']), LatestName),
+
+ %% Only exref the db application.
+ ?line {ok, _, W2} =
+ systools:make_tar(LatestName, [{exref, [db]}, {path, P}, silent]),
+ ?line check_exref_warnings(with_db1, W2),
+ ?line ok = check_tar(fname([lib,'fe-3.1',ebin,'fe.app']), LatestName),
+
+ %% Only exref the fe application.
+ ?line {ok, _, W3} =
+ systools:make_tar(LatestName, [{exref, [fe]}, {path, P}, silent]),
+ ?line check_exref_warnings(without_db1, W3),
+ ?line ok = check_tar(fname([lib,'db-2.1',ebin,'db.app']), LatestName),
+
+ %% exref the db and stdlib applications.
+ ?line {ok, _, W4} =
+ systools:make_tar(LatestName, [{exref, [db, stdlib]},
+ {path, P}, silent]),
+ ?line check_exref_warnings(with_db1, W4),
+ ?line ok = check_tar(fname([lib,'fe-3.1',ebin,'fe.app']), LatestName),
+
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+
+
+%% otp_9507
+%%
+otp_9507(suite) -> [];
+otp_9507(doc) ->
+ ["make_tar failed when path given as just 'ebin'."];
+otp_9507(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+
+ ?line {LatestDir, LatestName} = create_script(latest_small,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line LibDir = fname([DataDir, d_normal, lib]),
+ ?line FeDir = fname([LibDir, 'fe-3.1']),
+
+ ?line ok = file:set_cwd(FeDir),
+
+ RelName = fname([LatestDir,LatestName]),
+
+ ?line P1 = ["./ebin",
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin])],
+ ?line {ok, _, _} = systools:make_script(RelName, [silent, {path, P1}]),
+ ?line ok = systools:make_tar(RelName, [{path, P1}]),
+ ?line Content1 = tar_contents(RelName),
+
+ ?line P2 = ["ebin",
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin])],
+
+ %% Tickets solves the following line - it used to fail with
+ %% {function_clause,[{filename,join,[[]]},...}
+ ?line ok = systools:make_tar(RelName, [{path, P2}]),
+ ?line Content2 = tar_contents(RelName),
+ true = (Content1 == Content2),
+
+ ?line ok = file:set_cwd(OldDir),
+
+ ok.
+
+
+%% The relup stuff.
+%%
+%%
+
+
+%% make_relup
+%%
+normal_relup(suite) -> [];
+normal_relup(doc) ->
+ ["Check normal case"];
+normal_relup(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+
+ ?line {LatestDir,LatestName} = create_script(latest0,Config),
+ ?line {_LatestDir1,LatestName1} = create_script(latest1,Config),
+ ?line {_LatestDir2,LatestName2} = create_script(latest2,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line LibDir = [fname([DataDir, d_normal, lib])],
+ ?line P = [fname([LibDir, '*', ebin]),
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin])],
+
+ ?line ok = file:set_cwd(LatestDir),
+
+ %% OTP-2561: Check that the option 'restart_emulator' generates a
+ %% "restart_new_emulator" instruction.
+ ?line {ok, _ , _, []} =
+ systools:make_relup(LatestName, [LatestName1], [LatestName1],
+ [{path, P},restart_emulator,silent]),
+ ?line ok = check_relup([{db, "2.1"}], [{db, "1.0"}]),
+ ?line ok = check_restart_emulator(),
+
+ %% This is the ultra normal case
+ ?line ok = systools:make_relup(LatestName, [LatestName1], [LatestName1],
+ [{path, P}]),
+ ?line ok = check_relup([{db, "2.1"}], [{db, "1.0"}]),
+ ?line {ok, _, _, []} =
+ systools:make_relup(LatestName, [LatestName1], [LatestName1],
+ [{path, P}, silent]),
+ ?line ok = check_relup([{db, "2.1"}], [{db, "1.0"}]),
+
+ %% file should not be written if warnings_as_errors is enabled.
+ %% delete before running tests.
+ ?line ok = file:delete("relup"),
+
+ %% Check that warnings are treated as errors
+ ?line error =
+ systools:make_relup(LatestName, [LatestName2], [LatestName1],
+ [{path, P}, warnings_as_errors]),
+ ?line error =
+ systools:make_relup(LatestName, [LatestName2], [LatestName1],
+ [{path, P}, silent, warnings_as_errors]),
+
+ %% relup file should not exist
+ ?line false = filelib:is_regular("relup"),
+
+ %% Check that warnings get through
+ ?line ok = systools:make_relup(LatestName, [LatestName2], [LatestName1],
+ [{path, P}]),
+ ?line ok = check_relup([{fe, "3.1"}, {db, "2.1"}], [{db, "1.0"}]),
+ ?line {ok, _, _, [{erts_vsn_changed, _}]} =
+ systools:make_relup(LatestName, [LatestName2], [LatestName1],
+ [{path, P}, silent]),
+ ?line ok = check_relup([{fe, "3.1"}, {db, "2.1"}], [{db, "1.0"}]),
+
+ %% relup file should exist now
+ ?line true = filelib:is_regular("relup"),
+
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+
+%% This test fails if wrong version numbers are seen in the relup file
+%% or if any application is missing. This was triggered by OTP-1360.
+check_relup(UpVsnL, DnVsnL) ->
+ {ok, [{_V1, [{_, _, Up}], [{_, _, Dn}]}]} = file:consult(relup),
+ [] = foldl(fun(X, Acc) ->
+ true = lists:member(X, Acc),
+ lists:delete(X, Acc) end,
+ UpVsnL,
+ [{App, Vsn} || {load_object_code,{App,Vsn,_}} <- Up]),
+ [] = foldl(fun(X, Acc) ->
+ true = lists:member(X, Acc),
+ lists:delete(X, Acc) end,
+ DnVsnL,
+ [{App, Vsn} || {load_object_code,{App,Vsn,_}} <- Dn]),
+ ok.
+
+check_restart_emulator() ->
+ {ok, [{_V1, [{_, _, Up}], [{_, _, Dn}]}]} = file:consult(relup),
+ restart_new_emulator = lists:last(Up),
+ restart_new_emulator = lists:last(Dn),
+ ok.
+
+%% make_relup
+%%
+no_appup_relup(suite) -> [];
+no_appup_relup(doc) ->
+ ["Check that appup files may be missing, but only if we don't need them."];
+no_appup_relup(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+
+ ?line {LatestDir,LatestName} = create_script(latest_small,Config),
+ ?line {_LatestDir0,LatestName0} = create_script(latest_small0,Config),
+ ?line {_LatestDir1,LatestName1} = create_script(latest_small1,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line P1 = [fname([DataDir, d_no_appup, lib, 'fe-3.1', ebin]),
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin])],
+
+ ?line ok = file:set_cwd(LatestDir),
+
+ %% Check that appup might be missing
+ ?line ok =
+ systools:make_relup(LatestName, [LatestName], [], [{path, P1}]),
+ ?line {ok,_, _, []} =
+ systools:make_relup(LatestName, [LatestName], [],
+ [silent, {path, P1}]),
+
+ %% Check that appup might NOT be missing when we need it
+ ?line error =
+ systools:make_relup(LatestName, [LatestName0], [], [{path, P1}]),
+ ?line {error,_,{file_problem, {_,{error,{open,_,_}}}}} =
+ systools:make_relup(LatestName, [], [LatestName0],
+ [silent, {path, P1}]),
+
+ %% Check that appups missing vsn traps
+ ?line P2 = [fname([DataDir, d_no_appup, lib, 'fe-2.1', ebin]),
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin])],
+
+ ?line error =
+ systools:make_relup(LatestName0, [LatestName1], [], [{path, P2}]),
+ ?line {error,_,{no_relup, _, _, _}} =
+ systools:make_relup(LatestName0, [], [LatestName1],
+ [silent, {path, P2}]),
+
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+%% make_relup
+%%
+bad_appup_relup(suite) -> [];
+bad_appup_relup(doc) ->
+ ["Check that badly written appup files are detected"];
+bad_appup_relup(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+
+ ?line {LatestDir,LatestName} = create_script(latest_small,Config),
+ ?line {_LatestDir0,LatestName0} = create_script(latest_small0,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line N2 = [fname([DataDir, d_bad_appup, lib, 'fe-3.1', ebin]),
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin])],
+
+ ?line ok = file:set_cwd(LatestDir),
+
+ %% Check that bad appup is trapped
+ ?line error =
+ systools:make_relup(LatestName, [LatestName0], [], [{path, N2}]),
+ ?line {error,_,{file_problem, {_, {error, {parse,_, _}}}}} =
+ systools:make_relup(LatestName, [], [LatestName0],
+ [silent, {path, N2}]),
+
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+%% make_relup
+%%
+abnormal_relup(suite) -> [];
+abnormal_relup(doc) ->
+ ["Check some abnormal cases"];
+abnormal_relup(Config) when is_list(Config) ->
+ ?line {ok, OldDir} = file:get_cwd(),
+
+ ?line {LatestDir,LatestName} = create_script(latest0,Config),
+ ?line {_LatestDir1,LatestName1} = create_script(latest1,Config),
+
+ %% Check wrong app vsn
+ ?line DataDir = filename:absname(?copydir),
+ ?line P = [fname([DataDir, d_bad_app_vsn, lib, 'db-2.1', ebin]),
+ fname([DataDir, d_bad_app_vsn, lib, 'fe-3.1', ebin]),
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin])],
+
+ ?line ok = file:set_cwd(LatestDir),
+
+ ?line error = systools:make_relup(LatestName, [LatestName1], [LatestName1],
+ [{path, P}]),
+ ?line R0 = systools:make_relup(LatestName, [LatestName1], [LatestName1],
+ [silent, {path, P}]),
+ ?line {error,systools_make,
+ [{error_reading,{db,{no_valid_version,
+ {{"should be","2.1"},
+ {"found file", _, "2.0"}}}}}]} = R0,
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+
+%% Check that application start type is used in relup
+app_start_type_relup(suite) ->
+ [];
+app_start_type_relup(doc) ->
+ ["Release upgrade file with various application start types"];
+app_start_type_relup(Config) when is_list(Config) ->
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line {Dir1,Name1} = create_script(latest_app_start_type1,Config),
+ ?line {Dir2,Name2} = create_script(latest_app_start_type2,Config),
+ ?line Release1 = filename:join(Dir1,Name1),
+ ?line Release2 = filename:join(Dir2,Name2),
+
+ ?line {ok, Release2Relup, systools_relup, []} = systools:make_relup(Release2, [Release1], [Release1], [{outdir, PrivDir}, silent]),
+ ?line {"2", [{"1",[], UpInstructions}], [{"1",[], DownInstructions}]} = Release2Relup,
+ %% ?t:format("Up: ~p",[UpInstructions]),
+ %% ?t:format("Dn: ~p",[DownInstructions]),
+ ?line [{load_object_code, {mnesia, _, _}},
+ {load_object_code, {sasl, _, _}},
+ {load_object_code, {webtool, _, _}},
+ {load_object_code, {snmp, _, _}},
+ {load_object_code, {xmerl, _, _}},
+ point_of_no_return
+ | UpInstructionsT] = UpInstructions,
+ ?line true = lists:member({apply,{application,start,[mnesia,permanent]}}, UpInstructionsT),
+ ?line true = lists:member({apply,{application,start,[sasl,transient]}}, UpInstructionsT),
+ ?line true = lists:member({apply,{application,start,[webtool,temporary]}}, UpInstructionsT),
+ ?line true = lists:member({apply,{application,load,[snmp]}}, UpInstructionsT),
+ ?line false = lists:any(fun({apply,{application,_,[xmerl|_]}}) -> true; (_) -> false end, UpInstructionsT),
+ ?line [point_of_no_return | DownInstructionsT] = DownInstructions,
+ ?line true = lists:member({apply,{application,stop,[mnesia]}}, DownInstructionsT),
+ ?line true = lists:member({apply,{application,stop,[sasl]}}, DownInstructionsT),
+ ?line true = lists:member({apply,{application,stop,[webtool]}}, DownInstructionsT),
+ ?line true = lists:member({apply,{application,stop,[snmp]}}, DownInstructionsT),
+ ?line true = lists:member({apply,{application,stop,[xmerl]}}, DownInstructionsT),
+ ?line true = lists:member({apply,{application,unload,[mnesia]}}, DownInstructionsT),
+ ?line true = lists:member({apply,{application,unload,[sasl]}}, DownInstructionsT),
+ ?line true = lists:member({apply,{application,unload,[webtool]}}, DownInstructionsT),
+ ?line true = lists:member({apply,{application,unload,[snmp]}}, DownInstructionsT),
+ ?line true = lists:member({apply,{application,unload,[xmerl]}}, DownInstructionsT),
+ ok.
+
+
+otp_6226(suite) ->
+ [];
+otp_6226(doc) ->
+ ["{outdir,Dir} option for systools:make_script()"];
+otp_6226(Config) when is_list(Config) ->
+ PrivDir = ?privdir,
+ ?line {ok, OldDir} = file:get_cwd(),
+
+ ?line {LatestDir, LatestName} = create_script(latest0,Config),
+ ?line {_LatestDir, LatestName1} = create_script(latest1,Config),
+
+ ?line DataDir = filename:absname(?copydir),
+ ?line LibDir = fname([DataDir, d_normal, lib]),
+ ?line P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'db-1.0', ebin]),
+ fname([LibDir, 'fe-3.1', ebin]),
+ fname([DataDir, lib, kernel, ebin]),
+ fname([DataDir, lib, stdlib, ebin])],
+
+ ?line ok = file:set_cwd(LatestDir),
+
+
+ %% Create an outdir1 directory
+ ?line ok = file:make_dir("outdir1"),
+
+ %% ==== Now test systools:make_script ====
+ %% a) badarg
+ ?line {'EXIT', {{badarg,[{outdir,outdir1}]}, _}} =
+ (catch systools:make_script(LatestName, [{outdir,outdir1},
+ {path,P},silent])),
+
+ %% b) absolute path
+ Outdir1 = filename:join(PrivDir, "outdir1"),
+ ?line {ok,_,[]} = systools:make_script(LatestName, [{outdir,Outdir1},
+ {path,P},silent]),
+ ?line Script1 = filename:join(Outdir1, LatestName ++ ".script"),
+ ?line Boot1 = filename:join(Outdir1, LatestName ++ ".boot"),
+ ?line true = filelib:is_file(Script1),
+ ?line true = filelib:is_file(Boot1),
+ ?line ok = file:delete(Script1),
+ ?line ok = file:delete(Boot1),
+
+ %% c) relative path
+ ?line {ok,_,[]} = systools:make_script(LatestName, [{outdir,"./outdir1"},
+ {path,P},silent]),
+ ?line true = filelib:is_file(Script1),
+ ?line true = filelib:is_file(Boot1),
+ ?line ok = file:delete(Script1),
+ ?line ok = file:delete(Boot1),
+
+ %% d) absolute but incorrect path
+ ?line Outdir2 = filename:join(PrivDir, "outdir2"),
+ ?line Script2 = filename:join(Outdir2, LatestName ++ ".script"),
+ ?line {error,_,{open,Script2,_}} =
+ systools:make_script(LatestName, [{outdir,Outdir2},{path,P},silent]),
+
+ %% e) relative but incorrect path
+ ?line {error,_,{open,_,_}} =
+ systools:make_script(LatestName, [{outdir,"./outdir2"},{path,P},silent]),
+
+ %% f) with .rel in another directory than cwd
+ ?line ok = file:set_cwd(Outdir1),
+ ?line {ok,_,[]} = systools:make_script(filename:join(PrivDir, LatestName),
+ [{outdir,"."},{path,P},silent]),
+ ?line true = filelib:is_file(LatestName ++ ".script"),
+ ?line true = filelib:is_file(LatestName ++ ".boot"),
+ ?line ok = file:delete(LatestName ++ ".script"),
+ ?line ok = file:delete(LatestName ++ ".boot"),
+ ?line ok = file:set_cwd(LatestDir),
+
+ %% ==== Now test systools:make_tar =====
+ ?line {ok,_,[]} = systools:make_script(LatestName, [{path,P},silent]),
+ %% a) badarg
+ ?line {'EXIT', {{badarg, [{outdir,outdir1}]}, _}} =
+ (catch systools:make_tar(LatestName,[{outdir,outdir1},{path,P},silent])),
+
+ %% b) absolute path
+ ?line {ok,_,[]} = systools:make_tar(LatestName, [{outdir,Outdir1},
+ {path,P},silent]),
+ ?line Tar1 = filename:join(Outdir1,LatestName++".tar.gz"),
+ ?line true = filelib:is_file(Tar1),
+ ?line ok = file:delete(Tar1),
+
+ %% c) relative path
+ ?line {ok,_,[]} = systools:make_tar(LatestName, [{outdir,"./outdir1"},
+ {path,P},silent]),
+ ?line true = filelib:is_file(Tar1),
+ ?line ok = file:delete(Tar1),
+
+ %% d) absolute but incorrect path
+ ?line Tar2 = filename:join(Outdir2,LatestName++".tar.gz"),
+ ?line {error,_,{tar_error,{open,Tar2,{Tar2,enoent}}}} =
+ systools:make_tar(LatestName, [{outdir,Outdir2},{path,P},silent]),
+
+ %% e) relative but incorrect path
+ ?line {error,_,{tar_error,{open,_,_}}} =
+ systools:make_tar(LatestName, [{outdir,"./outdir2"},{path,P},silent]),
+
+ %% f) with .rel in another directory than cwd
+ ?line ok = file:set_cwd(Outdir1),
+ ?line {ok,_,[]} = systools:make_tar(filename:join(PrivDir, LatestName),
+ [{outdir,"."},{path,P},silent]),
+ ?line true = filelib:is_file(Tar1),
+ ?line ok = file:set_cwd(LatestDir),
+
+ %% ===== Now test systools:make_relup =====
+ %% a) badarg
+ ?line {'EXIT', {{badarg, [{outdir,outdir1}]}, _}} =
+ (catch systools:make_relup(LatestName,[LatestName1],[LatestName1],
+ [{outdir,outdir1},
+ {path,P},silent])),
+
+ %% b) absolute path
+ Relup = filename:join(Outdir1, "relup"),
+ ?line {ok,_,_,[]} = systools:make_relup(LatestName,[LatestName1],[LatestName1],
+ [{outdir,Outdir1},
+ {path,P},silent]),
+ ?line true = filelib:is_file(Relup),
+ ?line ok = file:delete(Relup),
+
+ %% c) relative path
+ ?line {ok,_,_,[]} = systools:make_relup(LatestName,[LatestName1],[LatestName1],
+ [{outdir,"./outdir1"},
+ {path,P},silent]),
+ ?line true = filelib:is_file(Relup),
+ ?line ok = file:delete(Relup),
+
+ %% d) absolute but incorrect path
+ ?line {error,_,{file_problem,{"relup",enoent}}} =
+ systools:make_relup(LatestName,[LatestName1],[LatestName1],
+ [{outdir,Outdir2},{path,P},silent]),
+
+ %% e) relative but incorrect path
+ ?line {error,_,{file_problem,{"relup",enoent}}} =
+ systools:make_relup(LatestName,[LatestName1],[LatestName1],
+ [{outdir,"./outdir2"},{path,P},silent]),
+
+ %% f) with .rel in another directory than cwd
+ %% -- not necessary to test since relup by default is placed in
+ %% cwd, not in the same directory as the .rel file --
+
+ %% Change back to previous working directory
+ ?line ok = file:set_cwd(OldDir),
+ ok.
+
+
+%%%%%%
+%%%%%% Utilities
+%%%%%%
+
+check_script_path(RelName) ->
+ {ok, [Conts]} = read_script_file(RelName),
+ {script, {_, _}, ListOfThings} = Conts,
+ case lists:keysearch(path, 1, ListOfThings) of
+ {value, {path, [$$,$R,$O,$O,$T | _]}} -> %"$ROOT..."
+ false;
+ _ -> ok
+ end.
+
+check_var_script_file(VarDirs, NoExistDirs, RelName) ->
+ {ok, [Conts]} = read_script_file(RelName),
+ {script, {_, _}, ListOfThings} = Conts,
+ AllPaths = lists:append(lists:map(fun({path, P}) -> P;
+ (_) -> []
+ end,
+ ListOfThings)),
+ case lists:filter(fun(VarDir) -> lists:member(VarDir, AllPaths) end,
+ VarDirs) of
+ VarDirs ->
+ ok;
+ _ ->
+ test_server:fail("All variable dirs not in generated script")
+ end,
+ case lists:filter(fun(NoExistDir) -> lists:member(NoExistDir, AllPaths) end,
+ NoExistDirs) of
+ [] ->
+ ok;
+ _ ->
+ test_server:fail("Unexpected dirs in generated script")
+ end.
+
+check_include_script(RelName, ExpectedLoad, ExpectedStart) ->
+ {ok, [Conts]} = read_script_file(RelName),
+ {script, {_, _}, ListOfThings} = Conts,
+
+ %% Check that the applications are loaded in given order !
+ ActualLoad =
+ [App || {apply,{application,load,[{application,App,_}]}} <- ListOfThings,
+ App=/=kernel,
+ App=/=stdlib],
+
+ if ActualLoad =:= ExpectedLoad -> ok;
+ true -> test_server:fail({bad_load_order, ActualLoad, ExpectedLoad})
+ end,
+
+ %% Check that applications are started in given order !
+ ActualStart =
+ [App || {apply,{application,start_boot,[App|_]}} <- ListOfThings,
+ App =/= kernel,
+ App =/= stdlib],
+
+ if ActualStart =:= ExpectedStart -> ok;
+ true -> test_server:fail({bad_start_order, ActualStart,ExpectedStart})
+ end,
+
+ ok.
+
+read_script_file(RelName) ->
+ file:consult(RelName ++ ".script").
+
+check_var_tar(Variable, RelName) ->
+ Expected = tar_name(Variable),
+ case check_tar(Expected,RelName) of
+ ok ->
+ ok;
+ {error, {erroneous_tar_file, _, missing, _}} ->
+ {error, {not_generated, Expected}}
+ end.
+
+exists_tar_file(Name) ->
+ File = tar_name(Name),
+ case filelib:is_regular(File) of
+ true ->
+ ok = file:delete(File),
+ true;
+ _ ->
+ false
+ end.
+
+%% Take a snap of the generated tar file and check if a certain
+%% file is included.
+%% This ensures at least that the tar file is generated.
+check_tar(File, RelName) ->
+ TarContents = tar_contents(RelName),
+ case lists:member(File,TarContents) of
+ true -> ok;
+ _ -> {error, {erroneous_tar_file, tar_name(RelName), missing, File}}
+ end.
+
+%% Check that the given files exist in the tar file, and that they are
+%% not symlinks
+check_tar_regular(PrivDir, Files, RelName) ->
+ TmpDir = fname(PrivDir,tmp),
+ ok = file:make_dir(TmpDir),
+ ok = erl_tar:extract(tar_name(RelName),
+ [{files,Files},{cwd,TmpDir},compressed]),
+ R = lists:foldl(fun(File,Acc) ->
+ case file:read_link_info(fname(TmpDir,File)) of
+ {ok,#file_info{type=regular}} ->
+ Acc;
+ {ok,#file_info{type=Other}} ->
+ [{File,Other}|Acc];
+ _ ->
+ [{File,missing}|Acc]
+ end
+ end,
+ [],
+ Files),
+ delete_tree(TmpDir),
+ case R of
+ [] ->
+ ok;
+ NotThere ->
+ {error,{erroneous_tar_file,tar_name(RelName),NotThere}}
+ end.
+
+delete_tree(Dir) ->
+ case filelib:is_dir(Dir) of
+ true ->
+ {ok,Files} = file:list_dir(Dir),
+ lists:foreach(fun(File) -> delete_tree(filename:join(Dir,File)) end,
+ Files),
+ file:del_dir(Dir);
+ false ->
+ ok = file:delete(Dir)
+ end.
+
+tar_contents(Name) ->
+ {ok, Cont} = erl_tar:table(Name ++ ".tar.gz", [compressed]),
+ Cont.
+
+tar_name(Name) ->
+ Name ++ ".tar.gz".
+
+create_script(latest,Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, latest),
+ ?line Apps = application_controller:which_applications(),
+ ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+ ?line {ok,Fd} = file:open(Name++".rel",write),
+ ?line io:format(Fd,
+ "{release, {\"Test release 3\", \"LATEST\"}, \n"
+ " {erts, \"4.4\"}, \n"
+ " [{kernel, \"~s\"}, {stdlib, \"~s\"}, \n"
+ " {db, \"2.1\"}, {fe, \"3.1\"}]}.\n",
+ [KernelVer,StdlibVer]),
+ ?line ok = file:close(Fd),
+ {filename:dirname(Name), filename:basename(Name)};
+create_script(latest_no_mod_vsn,Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, latest),
+ ?line Apps = application_controller:which_applications(),
+ ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+ ?line {ok,Fd} = file:open(Name++".rel",write),
+ ?line io:format(Fd,
+ "{release, {\"Test release 3\", \"LATESTNOMOD\"}, \n"
+ " {erts, \"4.4\"}, \n"
+ " [{kernel, \"~s\"}, {stdlib, \"~s\"}, \n"
+ " {db, \"3.1\"}, {fe, \"3.1\"}]}.\n",
+ [KernelVer,StdlibVer]),
+ ?line ok = file:close(Fd),
+ {filename:dirname(Name), filename:basename(Name)};
+create_script(latest0,Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, 'latest-1'),
+ ?line {ok,Fd} = file:open(Name++".rel",write),
+ ?line io:format(Fd,
+ "{release, {\"Test release 2\", \"LATEST0\"}, \n"
+ " {erts, \"4.4\"}, \n"
+ " [{kernel, \"1.0\"}, {stdlib, \"1.0\"}, \n"
+ " {db, \"2.1\"}, {fe, \"3.1\"}]}.\n",
+ []),
+ ?line ok = file:close(Fd),
+ {filename:dirname(Name), filename:basename(Name)};
+create_script(latest1,Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, latest),
+ ?line {ok,Fd} = file:open(Name++".rel",write),
+ ?line io:format(Fd,
+ "{release, {\"Test release 2\", \"LATEST1\"}, \n"
+ " {erts, \"4.4\"}, \n"
+ " [{kernel, \"1.0\"}, {stdlib, \"1.0\"}, \n"
+ " {db, \"1.0\"}, {fe, \"3.1\"}]}.\n",
+ []),
+ ?line ok = file:close(Fd),
+ {filename:dirname(Name), filename:basename(Name)};
+create_script(latest2,Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, 'latest-2'),
+ ?line {ok,Fd} = file:open(Name++".rel",write),
+ ?line io:format(Fd,
+ "{release, {\"Test release 1\", \"LATEST2\"}, \n"
+ " {erts, \"4.3\"}, \n"
+ " [{kernel, \"1.0\"}, {stdlib, \"1.0\"}, \n"
+ " {db, \"1.0\"}, {fe, \"2.1\"}]}.\n",
+ []),
+ ?line ok = file:close(Fd),
+ {filename:dirname(Name), filename:basename(Name)};
+create_script(latest_small,Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, 'latest-small'),
+ ?line {ok,Fd} = file:open(Name++".rel",write),
+ ?line io:format(Fd,
+ "{release, {\"Test release 2\", \"LATEST_SMALL\"}, \n"
+ " {erts, \"4.4\"}, \n"
+ " [{kernel, \"1.0\"}, {stdlib, \"1.0\"}, \n"
+ " {fe, \"3.1\"}]}.\n",
+ []),
+ ?line ok = file:close(Fd),
+ {filename:dirname(Name), filename:basename(Name)};
+create_script(latest_small0,Config) -> %Differs in fe vsn
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, 'latest-small0'),
+ ?line {ok,Fd} = file:open(Name++".rel",write),
+ ?line io:format(Fd,
+ "{release, {\"Test release 2\", \"LATEST_SMALL0\"}, \n"
+ " {erts, \"4.4\"}, \n"
+ " [{kernel, \"1.0\"}, {stdlib, \"1.0\"}, \n"
+ " {fe, \"2.1\"}]}.\n",
+ []),
+ ?line ok = file:close(Fd),
+ {filename:dirname(Name), filename:basename(Name)};
+create_script(latest_small1,Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, 'latest-small1'),
+ ?line {ok,Fd} = file:open(Name++".rel",write),
+ ?line io:format(Fd,
+ "{release, {\"Test release 2\", \"LATEST_SMALL1\"}, \n"
+ " {erts, \"4.4\"}, \n"
+ " [{kernel, \"1.0\"}, {stdlib, \"1.0\"}, \n"
+ " {fe, \"500.18.7\"}]}.\n",
+ []),
+ ?line ok = file:close(Fd),
+ {filename:dirname(Name), filename:basename(Name)};
+create_script(latest_nokernel,Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, 'latest-nokernel'),
+ ?line {ok,Fd} = file:open(Name++".rel",write),
+ ?line io:format(Fd,
+ "{release, {\"Test release 3\", \"LATEST_NOKERNEL\"}, \n"
+ " {erts, \"4.4\"}, \n"
+ " [{db, \"2.1\"}, {fe, \"3.1\"}]}.\n",
+ []),
+ ?line ok = file:close(Fd),
+ {filename:dirname(Name), filename:basename(Name)};
+create_script(latest_app_start_type1,Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, latest_app_start_type1),
+ ?line ErtsVer = erlang:system_info(version),
+ ?line Apps = application_controller:which_applications(),
+ ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+ ?line {ok,Fd} = file:open(Name++".rel",write),
+ ?line RelfileContent =
+ {release,{"Test release", "1"},
+ {erts,ErtsVer},
+ [{kernel,KernelVer},
+ {stdlib,StdlibVer}]},
+ ?line io:format(Fd,"~p.~n",[RelfileContent]),
+ ?line ok = file:close(Fd),
+ {filename:dirname(Name), filename:basename(Name)};
+create_script(latest_app_start_type2,Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, latest_app_start_type2),
+ ?line ErtsVer = erlang:system_info(version),
+ ?line Apps = application_controller:which_applications(),
+ ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+ ?line OtherApps = [{mnesia,permanent},
+ {sasl,transient},
+ {webtool,temporary},
+ {snmp,load},
+ {xmerl,none}],
+ ?line lists:foreach(fun({App,_}) -> application:load(App) end,
+ OtherApps),
+ ?line Loaded = application:loaded_applications(),
+ ?line OtherAppsRel =
+ lists:map(fun({App,StartType}) ->
+ {_,_,Ver} = lists:keyfind(App,1,Loaded),
+ {App,Ver,StartType}
+ end,
+ OtherApps),
+ ?line {ok,Fd} = file:open(Name++".rel",write),
+ ?line RelfileContent =
+ {release,{"Test release", "2"},
+ {erts,ErtsVer},
+ [{kernel,KernelVer},
+ {stdlib,StdlibVer} | OtherAppsRel]},
+ ?line io:format(Fd,"~p.~n",[RelfileContent]),
+ ?line ok = file:close(Fd),
+ {filename:dirname(Name), filename:basename(Name)}.
+
+create_include_files(inc1, Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, inc1),
+ create_apps(PrivDir),
+
+ ?line Apps = application_controller:which_applications(),
+ ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+
+ Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
+ " [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
+ ++ StdlibVer ++ "\"},\n"
+ " {t6, \"1.0\"}, {t5, \"1.0\"}, \n"
+ " {t4, \"1.0\"}, {t3, \"1.0\"}, {t2, \"1.0\"}, \n"
+ " {t1, \"1.0\"}]}.\n",
+ file:write_file(Name ++ ".rel", list_to_binary(Rel)),
+ {filename:dirname(Name), filename:basename(Name)};
+
+create_include_files(inc2, Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, inc2),
+ create_apps(PrivDir),
+
+ ?line Apps = application_controller:which_applications(),
+ ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+
+ %% t6 does not include t5 !
+ Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
+ " [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
+ ++ StdlibVer ++ "\"},\n"
+ " {t6, \"1.0\", [t4]}, {t5, \"1.0\"}, \n"
+ " {t4, \"1.0\"}, {t3, \"1.0\"}, {t2, \"1.0\"}, \n"
+ " {t1, \"1.0\"}]}.\n",
+ file:write_file(Name ++ ".rel", list_to_binary(Rel)),
+ {filename:dirname(Name), filename:basename(Name)};
+
+create_include_files(inc3, Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, inc3),
+ create_apps(PrivDir),
+
+ ?line Apps = application_controller:which_applications(),
+ ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+
+ %% t3 does not include t2 !
+ Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
+ " [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
+ ++ StdlibVer ++ "\"},\n"
+ " {t6, \"1.0\"}, {t5, \"1.0\"}, \n"
+ " {t4, \"1.0\"}, {t3, \"1.0\", []}, {t2, \"1.0\"}, \n"
+ " {t1, \"1.0\"}]}.\n",
+ file:write_file(Name ++ ".rel", list_to_binary(Rel)),
+ {filename:dirname(Name), filename:basename(Name)};
+
+create_include_files(inc4, Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, inc4),
+ create_apps(PrivDir),
+
+ ?line Apps = application_controller:which_applications(),
+ ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+
+ %% t3 does not include t2 !
+ %% t6 does not include t5 !
+ Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
+ " [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
+ ++ StdlibVer ++ "\"},\n"
+ " {t6, \"1.0\", [t4]}, {t5, \"1.0\"}, \n"
+ " {t4, \"1.0\"}, {t3, \"1.0\", []}, {t2, \"1.0\"}, \n"
+ " {t1, \"1.0\"}]}.\n",
+ file:write_file(Name ++ ".rel", list_to_binary(Rel)),
+ {filename:dirname(Name), filename:basename(Name)};
+
+create_include_files(inc5, Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, inc5),
+ create_apps(PrivDir),
+
+ ?line Apps = application_controller:which_applications(),
+ ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+
+ %% t6 does not include t5 !
+ %% exclude t5.
+ Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
+ " [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
+ ++ StdlibVer ++ "\"},\n"
+ " {t6, \"1.0\", [t4]}, \n"
+ " {t4, \"1.0\"}, {t3, \"1.0\", []}, {t2, \"1.0\"}, \n"
+ " {t1, \"1.0\"}]}.\n",
+ file:write_file(Name ++ ".rel", list_to_binary(Rel)),
+ {filename:dirname(Name), filename:basename(Name)};
+
+create_include_files(inc6, Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, inc6),
+ create_apps(PrivDir),
+
+ ?line Apps = application_controller:which_applications(),
+ ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+
+ %% t3 does include non existing t2 !
+ Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
+ " [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
+ ++ StdlibVer ++ "\"},\n"
+ " {t6, \"1.0\"}, {t5, \"1.0\"}, \n"
+ " {t4, \"1.0\"}, {t3, \"1.0\"}, \n"
+ " {t1, \"1.0\"}]}.\n",
+ file:write_file(Name ++ ".rel", list_to_binary(Rel)),
+ {filename:dirname(Name), filename:basename(Name)};
+
+create_include_files(inc7, Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, inc7),
+ create_apps(PrivDir),
+ create_app(t7, PrivDir),
+
+ ?line Apps = application_controller:which_applications(),
+ ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+
+ %% t7 and t6 does include t5 !
+ Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
+ " [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
+ ++ StdlibVer ++ "\"},\n"
+ " {t7, \"1.0\"}, {t6, \"1.0\"}, {t5, \"1.0\"}, \n"
+ " {t4, \"1.0\"}, {t3, \"1.0\"}, {t2, \"1.0\"}, \n"
+ " {t1, \"1.0\"}]}.\n",
+ file:write_file(Name ++ ".rel", list_to_binary(Rel)),
+ {filename:dirname(Name), filename:basename(Name)};
+
+create_include_files(inc8, Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, inc8),
+ create_circular_apps(PrivDir),
+
+ ?line Apps = application_controller:which_applications(),
+ ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+
+ %% t8 uses t9 and t10 includes t9 !
+ Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
+ " [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
+ ++ StdlibVer ++ "\"},\n"
+ " {t8, \"1.0\"}, {t9, \"1.0\"}, {t10, \"1.0\"}]}.\n",
+ file:write_file(Name ++ ".rel", list_to_binary(Rel)),
+ {filename:dirname(Name), filename:basename(Name)};
+
+create_include_files(inc9, Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, inc9),
+ create_circular_apps(PrivDir),
+
+ ?line Apps = application_controller:which_applications(),
+ ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+
+ %% t8 uses t9, t9 uses t10 and t10 includes t8 ==> circular !!
+ Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
+ " [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
+ ++ StdlibVer ++ "\"},\n"
+ " {t8, \"1.0\"}, {t9, \"1.0\"}, {t10, \"1.0\", [t8]}]}.\n",
+ file:write_file(Name ++ ".rel", list_to_binary(Rel)),
+ {filename:dirname(Name), filename:basename(Name)};
+
+create_include_files(inc10, Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, inc10),
+ create_circular_apps(PrivDir),
+
+ ?line Apps = application_controller:which_applications(),
+ ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+
+ %% t9 tries to include not specified (in .app file) application !
+ Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
+ " [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
+ ++ StdlibVer ++ "\"},\n"
+ " {t8, \"1.0\"}, {t9, \"1.0\", [t7]}, {t10, \"1.0\"}]}.\n",
+ file:write_file(Name ++ ".rel", list_to_binary(Rel)),
+ {filename:dirname(Name), filename:basename(Name)};
+
+create_include_files(inc11, Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, inc11),
+ create_apps2(PrivDir),
+
+ ?line Apps = application_controller:which_applications(),
+ ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+
+ Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
+ " [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
+ ++ StdlibVer ++ "\"},\n"
+ " {t11, \"1.0\"}, \n"
+ " {t12, \"1.0\"}, \n"
+ " {t13, \"1.0\"}]}.\n",
+ file:write_file(Name ++ ".rel", list_to_binary(Rel)),
+ {filename:dirname(Name), filename:basename(Name)};
+
+create_include_files(otp_3065, Config) ->
+ ?line PrivDir = ?privdir,
+ ?line Name = fname(PrivDir, otp_3065),
+ create_apps_3065(PrivDir),
+
+ ?line Apps = application_controller:which_applications(),
+ ?line {value,{_,_,KernelVer}} = lists:keysearch(kernel,1,Apps),
+ ?line {value,{_,_,StdlibVer}} = lists:keysearch(stdlib,1,Apps),
+
+ Rel = "{release, {\"test\",\"R1A\"}, {erts, \"45\"},\n"
+ " [{kernel, \"" ++ KernelVer ++ "\"}, {stdlib, \""
+ ++ StdlibVer ++ "\"},\n"
+ " {chAts, \"1.0\"}, {aa12, \"1.0\"}, \n"
+ " {chTraffic, \"1.0\"}]}.\n",
+ file:write_file(Name ++ ".rel", list_to_binary(Rel)),
+ {filename:dirname(Name), filename:basename(Name)}.
+
+create_apps(Dir) ->
+ T1 = "{application, t1,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, [kernel, stdlib]},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't1.app'), list_to_binary(T1)),
+
+ T2 = "{application, t2,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, [t1]},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't2.app'), list_to_binary(T2)),
+
+ T3 = "{application, t3,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, []},\n"
+ " {included_applications, [t2]},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't3.app'), list_to_binary(T3)),
+
+ T4 = "{application, t4,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, [t3]},\n"
+ " {included_applications, []},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't4.app'), list_to_binary(T4)),
+
+ T5 = "{application, t5,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, [t3]},\n"
+ " {included_applications, []},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't5.app'), list_to_binary(T5)),
+
+ T6 = "{application, t6,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, []},\n"
+ " {included_applications, [t4, t5]},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't6.app'), list_to_binary(T6)).
+
+create_app(t7, Dir) ->
+ T7 = "{application, t7,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, []},\n"
+ " {included_applications, [t5]},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't7.app'), list_to_binary(T7)).
+
+create_circular_apps(Dir) ->
+ T8 = "{application, t8,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, [t9]},\n"
+ " {included_applications, []},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't8.app'), list_to_binary(T8)),
+
+ T9 = "{application, t9,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, [t10]},\n"
+ " {included_applications, []},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't9.app'), list_to_binary(T9)),
+
+ T10 = "{application, t10,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, []},\n"
+ " {included_applications, [t8, t9]},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't10.app'), list_to_binary(T10)).
+
+create_apps2(Dir) ->
+ T11 = "{application, t11,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, []},\n"
+ " {included_applications, [t13]},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't11.app'), list_to_binary(T11)),
+
+ T12 = "{application, t12,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, [t11]},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't12.app'), list_to_binary(T12)),
+
+ T13 = "{application, t13,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, []},\n"
+ " {included_applications, []},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 't13.app'), list_to_binary(T13)).
+
+
+
+create_apps_3065(Dir) ->
+ T11 = "{application, chTraffic,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, []},\n"
+ " {included_applications, [chAts]},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 'chTraffic.app'), list_to_binary(T11)),
+
+ T12 = "{application, chAts,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, []},\n"
+ " {included_applications, [aa12]},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 'chAts.app'), list_to_binary(T12)),
+
+ T13 = "{application, aa12,\n"
+ " [{vsn, \"1.0\"},\n"
+ " {description, \"test\"},\n"
+ " {modules, []},\n"
+ " {applications, [chAts]},\n"
+ " {included_applications, []},\n"
+ " {registered, []}]}.\n",
+ file:write_file(fname(Dir, 'aa12.app'), list_to_binary(T13)).
+
+fname(N) ->
+ filename:join(N).
+
+fname(Dir, Basename) ->
+ filename:join(Dir, Basename).
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/db-2.1/ebin/db.app b/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/db-2.1/ebin/db.app
new file mode 100644
index 0000000000..d375768b99
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/db-2.1/ebin/db.app
@@ -0,0 +1,8 @@
+{application, db,
+ [{description, "ERICSSON NR FOR DB"},
+ {vsn, "2.0"},
+ {modules, [{db1, "1.0"}, {db2, "1.0"}]},
+ {registered, []},
+ {applications, []},
+ {env, []},
+ {start, {db1, start, []}}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/db-2.1/ebin/db.appup b/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/db-2.1/ebin/db.appup
new file mode 100644
index 0000000000..621838f0b4
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/db-2.1/ebin/db.appup
@@ -0,0 +1,20 @@
+%%
+%% Release upgrade script for db (data base)
+%%
+
+{
+ "2.1",
+%%% Upgrade from:
+ [
+ {"1.0", [{update, db1, soft, soft_purge, soft_purge, []},
+ {update, db2, soft, soft_purge, soft_purge, [db1]}]},
+ {"1.1", [{update, db1, soft, soft_purge, soft_purge, []},
+ {update, db2, soft, soft_purge, soft_purge, [db1]}]}
+ ],
+
+%%% Downgrade to:
+ [
+ {"1.0", [{update, db1, soft, soft_purge, soft_purge, []},
+ {update, db2, soft, soft_purge, soft_purge, [db1]}]}
+ ]
+}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/db-2.1/src/db1.erl b/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/db-2.1/src/db1.erl
new file mode 100644
index 0000000000..a17640316e
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/db-2.1/src/db1.erl
@@ -0,0 +1,2 @@
+-module(db2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/db-2.1/src/db2.erl b/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/db-2.1/src/db2.erl
new file mode 100644
index 0000000000..a17640316e
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/db-2.1/src/db2.erl
@@ -0,0 +1,2 @@
+-module(db2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/ebin/fe.app b/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/ebin/fe.app
new file mode 100644
index 0000000000..d3bd85cda6
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/ebin/fe.app
@@ -0,0 +1,8 @@
+{application, fe,
+ [{description, "ERICSSON NR FOR FE"},
+ {vsn, "3.1"},
+ {modules, [{fe1, "1.0"}, {fe2, "1.0"}, {fe3, "2.0"}]},
+ {registered, []},
+ {applications, []},
+ {env, []},
+ {start, {fe2, start, []}}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/ebin/fe.appup b/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/ebin/fe.appup
new file mode 100644
index 0000000000..4ab13c1bae
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/ebin/fe.appup
@@ -0,0 +1,27 @@
+%%
+%% Release upgrade script for fe (front end)
+%%
+
+{
+ "3.1",
+%%% Upgrade from:
+ [
+ {"2.1.1", [{update, fe1, soft, soft_purge, soft_purge, []},
+ {update, fe2, soft, soft_purge, soft_purge, [fe1]},
+ {update, fe3, {{advanced, extra}, soft_purge, soft_purge,
+ [fe1, fe2]}
+ ]},
+
+ {"2.1", [{update, fe1, soft, soft_purge, soft_purge, []},
+ {update, fe2, soft, soft_purge, soft_purge, [fe1]},
+ {update, fe3, {advanced, extra}, soft_purge, soft_purge, [fe1, fe2]}
+ ]}
+ ],
+
+%%% Downgrade to:
+ [
+ {"2.1", [{update, fe2, soft, soft_purge, soft_purge, []},
+ {update, fe3, {advanced, extra}, soft_purge, soft_purge, [fe2]}
+ ]}
+ ]
+}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/src/fe1.erl b/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/src/fe1.erl
new file mode 100644
index 0000000000..aa5bfa8098
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/src/fe1.erl
@@ -0,0 +1,2 @@
+-module(fe1).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/src/fe2.erl b/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/src/fe2.erl
new file mode 100644
index 0000000000..869f3b93c8
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/src/fe2.erl
@@ -0,0 +1,2 @@
+-module(fe2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/src/fe3.erl b/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/src/fe3.erl
new file mode 100644
index 0000000000..6473342f52
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_app_vsn/lib/fe-3.1/src/fe3.erl
@@ -0,0 +1,2 @@
+-module(fe3).
+-vsn("2.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_appup/lib/fe-3.1/ebin/fe.app b/lib/sasl/test/systools_SUITE_data/d_bad_appup/lib/fe-3.1/ebin/fe.app
new file mode 100644
index 0000000000..0696e2494c
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_appup/lib/fe-3.1/ebin/fe.app
@@ -0,0 +1,7 @@
+{application, fe,
+ [{description, "ERICSSON NR FOR FE"},
+ {vsn, "3.1"},
+ {modules, [{fe1, "1.0"}, {fe2, "1.0"}, {fe3, "2.0"}]},
+ {registered, []},
+ {applications, []},
+ {mod, {fe1, []}}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_appup/lib/fe-3.1/ebin/fe.appup b/lib/sasl/test/systools_SUITE_data/d_bad_appup/lib/fe-3.1/ebin/fe.appup
new file mode 100644
index 0000000000..dac4c00851
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_appup/lib/fe-3.1/ebin/fe.appup
@@ -0,0 +1,27 @@
+%%
+%% Release upgrade script for fe (front end)
+%%
+
+{
+ "3.1",
+%%% Upgrade from:
+ [
+ {"2.1.1" [{update, fe1, soft, soft_purge, soft_purge, []},
+ {update, fe2, soft, soft_purge, soft_purge, [fe1]},
+ {update, fe3, {advanced, extra}, soft_purge, soft_purge,
+ [fe1, fe2]}
+ ]},
+
+ {"2.1", [{update, fe1, soft, soft_purge, soft_purge, []},
+ {update, fe2, soft, soft_purge, soft_purge, [fe1]},
+ {update, fe3, {advanced, extra}, soft_purge, soft_purge, [fe1, fe2]}
+ ]}
+ ],
+
+%%% Downgrade to:
+ [
+ {"2.1", [{update, fe2, soft, soft_purge, soft_purge, []},
+ {update, fe3, {advanced, extra}, soft_purge, soft_purge, [fe2]}
+ ]}
+ ]
+}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/db-2.1/ebin/db.app b/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/db-2.1/ebin/db.app
new file mode 100644
index 0000000000..191919f8d3
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/db-2.1/ebin/db.app
@@ -0,0 +1,8 @@
+{application, db,
+ [{description, "ERICSSON NR FOR DB"},
+ {vsn, "2.1"},
+ {modules, [{db1, "1.0"}, {db2, "1.0"}]},
+ {registered, []},
+ {applications, []},
+ {env, []},
+ {start, {db1, start, []}}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/db-2.1/ebin/db.appup b/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/db-2.1/ebin/db.appup
new file mode 100644
index 0000000000..621838f0b4
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/db-2.1/ebin/db.appup
@@ -0,0 +1,20 @@
+%%
+%% Release upgrade script for db (data base)
+%%
+
+{
+ "2.1",
+%%% Upgrade from:
+ [
+ {"1.0", [{update, db1, soft, soft_purge, soft_purge, []},
+ {update, db2, soft, soft_purge, soft_purge, [db1]}]},
+ {"1.1", [{update, db1, soft, soft_purge, soft_purge, []},
+ {update, db2, soft, soft_purge, soft_purge, [db1]}]}
+ ],
+
+%%% Downgrade to:
+ [
+ {"1.0", [{update, db1, soft, soft_purge, soft_purge, []},
+ {update, db2, soft, soft_purge, soft_purge, [db1]}]}
+ ]
+}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/db-2.1/src/db1.erl b/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/db-2.1/src/db1.erl
new file mode 100644
index 0000000000..a17640316e
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/db-2.1/src/db1.erl
@@ -0,0 +1,2 @@
+-module(db2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/db-2.1/src/db2.erl b/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/db-2.1/src/db2.erl
new file mode 100644
index 0000000000..a17640316e
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/db-2.1/src/db2.erl
@@ -0,0 +1,2 @@
+-module(db2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/ebin/fe.app b/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/ebin/fe.app
new file mode 100644
index 0000000000..d3bd85cda6
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/ebin/fe.app
@@ -0,0 +1,8 @@
+{application, fe,
+ [{description, "ERICSSON NR FOR FE"},
+ {vsn, "3.1"},
+ {modules, [{fe1, "1.0"}, {fe2, "1.0"}, {fe3, "2.0"}]},
+ {registered, []},
+ {applications, []},
+ {env, []},
+ {start, {fe2, start, []}}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/ebin/fe.appup b/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/ebin/fe.appup
new file mode 100644
index 0000000000..2db69eba76
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/ebin/fe.appup
@@ -0,0 +1,27 @@
+%%
+%% Release upgrade script for fe (front end)
+%%
+
+{
+ "3.1",
+%%% Upgrade from:
+ [
+ {"2.1.1", [{update, fe1, soft, soft_purge, soft_purge, []},
+ {update, fe2, soft, soft_purge, soft_purge, [fe1]},
+ {update, fe3, {advanced, extra}, soft_purge, soft_purge,
+ [fe1, fe2]}
+ ]},
+
+ {"2.1", [{update, fe1, soft, soft_purge, soft_purge, []},
+ {update, fe2, soft, soft_purge, soft_purge, [fe1]},
+ {update, fe3, {advanced, extra}, soft_purge, soft_purge, [fe1, fe2]}
+ ]}
+ ],
+
+%%% Downgrade to:
+ [
+ {"2.1", [{update, fe2, soft, soft_purge, soft_purge, []},
+ {update, fe3, {advanced, extra}, soft_purge, soft_purge, [fe2]}
+ ]}
+ ]
+}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/src/fe1.erl b/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/src/fe1.erl
new file mode 100644
index 0000000000..cdbb9ef532
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/src/fe1.erl
@@ -0,0 +1,2 @@
+-module(fe1).
+-vsn("1.1").
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/src/fe2.erl b/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/src/fe2.erl
new file mode 100644
index 0000000000..869f3b93c8
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/src/fe2.erl
@@ -0,0 +1,2 @@
+-module(fe2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/src/fe3.erl b/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/src/fe3.erl
new file mode 100644
index 0000000000..6473342f52
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_bad_mod+warn/lib/fe-3.1/src/fe3.erl
@@ -0,0 +1,2 @@
+-module(fe3).
+-vsn("2.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_links/lib/db-2.1/ebin/db.app b/lib/sasl/test/systools_SUITE_data/d_links/lib/db-2.1/ebin/db.app
new file mode 100644
index 0000000000..3e0ac3c3c9
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_links/lib/db-2.1/ebin/db.app
@@ -0,0 +1,8 @@
+{application, db,
+ [{description, "ERICSSON NR FOR DB"},
+ {vsn, "2.1"},
+ {modules, [{db1, "1.0"}, {db2, "1.0"}, {db3, "2.0"}]},
+ {registered, []},
+ {applications, []},
+ {env, []},
+ {start, {db1, start, []}}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_links/lib/db-2.1/ebin/db.appup b/lib/sasl/test/systools_SUITE_data/d_links/lib/db-2.1/ebin/db.appup
new file mode 100644
index 0000000000..621838f0b4
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_links/lib/db-2.1/ebin/db.appup
@@ -0,0 +1,20 @@
+%%
+%% Release upgrade script for db (data base)
+%%
+
+{
+ "2.1",
+%%% Upgrade from:
+ [
+ {"1.0", [{update, db1, soft, soft_purge, soft_purge, []},
+ {update, db2, soft, soft_purge, soft_purge, [db1]}]},
+ {"1.1", [{update, db1, soft, soft_purge, soft_purge, []},
+ {update, db2, soft, soft_purge, soft_purge, [db1]}]}
+ ],
+
+%%% Downgrade to:
+ [
+ {"1.0", [{update, db1, soft, soft_purge, soft_purge, []},
+ {update, db2, soft, soft_purge, soft_purge, [db1]}]}
+ ]
+}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_links/lib/db-2.1/src/db2.erl b/lib/sasl/test/systools_SUITE_data/d_links/lib/db-2.1/src/db2.erl
new file mode 100644
index 0000000000..a17640316e
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_links/lib/db-2.1/src/db2.erl
@@ -0,0 +1,2 @@
+-module(db2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_links/lib/db-2.1/src/db3.erl b/lib/sasl/test/systools_SUITE_data/d_links/lib/db-2.1/src/db3.erl
new file mode 100644
index 0000000000..6473342f52
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_links/lib/db-2.1/src/db3.erl
@@ -0,0 +1,2 @@
+-module(fe3).
+-vsn("2.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_links/lib/fe-3.1/ebin/fe.appup b/lib/sasl/test/systools_SUITE_data/d_links/lib/fe-3.1/ebin/fe.appup
new file mode 100644
index 0000000000..4ab13c1bae
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_links/lib/fe-3.1/ebin/fe.appup
@@ -0,0 +1,27 @@
+%%
+%% Release upgrade script for fe (front end)
+%%
+
+{
+ "3.1",
+%%% Upgrade from:
+ [
+ {"2.1.1", [{update, fe1, soft, soft_purge, soft_purge, []},
+ {update, fe2, soft, soft_purge, soft_purge, [fe1]},
+ {update, fe3, {{advanced, extra}, soft_purge, soft_purge,
+ [fe1, fe2]}
+ ]},
+
+ {"2.1", [{update, fe1, soft, soft_purge, soft_purge, []},
+ {update, fe2, soft, soft_purge, soft_purge, [fe1]},
+ {update, fe3, {advanced, extra}, soft_purge, soft_purge, [fe1, fe2]}
+ ]}
+ ],
+
+%%% Downgrade to:
+ [
+ {"2.1", [{update, fe2, soft, soft_purge, soft_purge, []},
+ {update, fe3, {advanced, extra}, soft_purge, soft_purge, [fe2]}
+ ]}
+ ]
+}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_links/lib/fe-3.1/src/fe1.erl b/lib/sasl/test/systools_SUITE_data/d_links/lib/fe-3.1/src/fe1.erl
new file mode 100644
index 0000000000..aa5bfa8098
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_links/lib/fe-3.1/src/fe1.erl
@@ -0,0 +1,2 @@
+-module(fe1).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_links/lib/fe-3.1/src/fe2.erl b/lib/sasl/test/systools_SUITE_data/d_links/lib/fe-3.1/src/fe2.erl
new file mode 100644
index 0000000000..869f3b93c8
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_links/lib/fe-3.1/src/fe2.erl
@@ -0,0 +1,2 @@
+-module(fe2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_links/lib/fe-3.1/src/fe3.erl b/lib/sasl/test/systools_SUITE_data/d_links/lib/fe-3.1/src/fe3.erl
new file mode 100644
index 0000000000..6473342f52
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_links/lib/fe-3.1/src/fe3.erl
@@ -0,0 +1,2 @@
+-module(fe3).
+-vsn("2.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/ebin/db.app b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/ebin/db.app
new file mode 100644
index 0000000000..191919f8d3
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/ebin/db.app
@@ -0,0 +1,8 @@
+{application, db,
+ [{description, "ERICSSON NR FOR DB"},
+ {vsn, "2.1"},
+ {modules, [{db1, "1.0"}, {db2, "1.0"}]},
+ {registered, []},
+ {applications, []},
+ {env, []},
+ {start, {db1, start, []}}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/ebin/db.appup b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/ebin/db.appup
new file mode 100644
index 0000000000..621838f0b4
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/ebin/db.appup
@@ -0,0 +1,20 @@
+%%
+%% Release upgrade script for db (data base)
+%%
+
+{
+ "2.1",
+%%% Upgrade from:
+ [
+ {"1.0", [{update, db1, soft, soft_purge, soft_purge, []},
+ {update, db2, soft, soft_purge, soft_purge, [db1]}]},
+ {"1.1", [{update, db1, soft, soft_purge, soft_purge, []},
+ {update, db2, soft, soft_purge, soft_purge, [db1]}]}
+ ],
+
+%%% Downgrade to:
+ [
+ {"1.0", [{update, db1, soft, soft_purge, soft_purge, []},
+ {update, db2, soft, soft_purge, soft_purge, [db1]}]}
+ ]
+}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/src/db1.erl b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/src/db1.erl
new file mode 100644
index 0000000000..a17640316e
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/src/db1.erl
@@ -0,0 +1,2 @@
+-module(db2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/src/db2.erl b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/src/db2.erl
new file mode 100644
index 0000000000..a17640316e
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/src/db2.erl
@@ -0,0 +1,2 @@
+-module(db2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/ebin/fe.app b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/ebin/fe.app
new file mode 100644
index 0000000000..d3bd85cda6
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/ebin/fe.app
@@ -0,0 +1,8 @@
+{application, fe,
+ [{description, "ERICSSON NR FOR FE"},
+ {vsn, "3.1"},
+ {modules, [{fe1, "1.0"}, {fe2, "1.0"}, {fe3, "2.0"}]},
+ {registered, []},
+ {applications, []},
+ {env, []},
+ {start, {fe2, start, []}}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/ebin/fe.appup b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/ebin/fe.appup
new file mode 100644
index 0000000000..4ab13c1bae
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/ebin/fe.appup
@@ -0,0 +1,27 @@
+%%
+%% Release upgrade script for fe (front end)
+%%
+
+{
+ "3.1",
+%%% Upgrade from:
+ [
+ {"2.1.1", [{update, fe1, soft, soft_purge, soft_purge, []},
+ {update, fe2, soft, soft_purge, soft_purge, [fe1]},
+ {update, fe3, {{advanced, extra}, soft_purge, soft_purge,
+ [fe1, fe2]}
+ ]},
+
+ {"2.1", [{update, fe1, soft, soft_purge, soft_purge, []},
+ {update, fe2, soft, soft_purge, soft_purge, [fe1]},
+ {update, fe3, {advanced, extra}, soft_purge, soft_purge, [fe1, fe2]}
+ ]}
+ ],
+
+%%% Downgrade to:
+ [
+ {"2.1", [{update, fe2, soft, soft_purge, soft_purge, []},
+ {update, fe3, {advanced, extra}, soft_purge, soft_purge, [fe2]}
+ ]}
+ ]
+}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/src/fe1.erl b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/src/fe1.erl
new file mode 100644
index 0000000000..cdbb9ef532
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/src/fe1.erl
@@ -0,0 +1,2 @@
+-module(fe1).
+-vsn("1.1").
diff --git a/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/src/fe2.erl b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/src/fe2.erl
new file mode 100644
index 0000000000..869f3b93c8
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/src/fe2.erl
@@ -0,0 +1,2 @@
+-module(fe2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/src/fe3.erl b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/src/fe3.erl
new file mode 100644
index 0000000000..6473342f52
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/fe-3.1/src/fe3.erl
@@ -0,0 +1,2 @@
+-module(fe3).
+-vsn("2.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_no_appup/lib/fe-2.1/ebin/fe.app b/lib/sasl/test/systools_SUITE_data/d_no_appup/lib/fe-2.1/ebin/fe.app
new file mode 100644
index 0000000000..47ea248720
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_no_appup/lib/fe-2.1/ebin/fe.app
@@ -0,0 +1,8 @@
+{application, fe,
+ [{description, "ERICSSON NR FOR FE"},
+ {vsn, "2.1"},
+ {modules, [{fe1, "1.0"}, {fe2, "1.0"}, {fe3, "2.0"}]},
+ {registered, []},
+ {applications, []},
+ {env, []},
+ {start, {fe2, start, []}}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_no_appup/lib/fe-2.1/ebin/fe.appup b/lib/sasl/test/systools_SUITE_data/d_no_appup/lib/fe-2.1/ebin/fe.appup
new file mode 100644
index 0000000000..2db69eba76
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_no_appup/lib/fe-2.1/ebin/fe.appup
@@ -0,0 +1,27 @@
+%%
+%% Release upgrade script for fe (front end)
+%%
+
+{
+ "3.1",
+%%% Upgrade from:
+ [
+ {"2.1.1", [{update, fe1, soft, soft_purge, soft_purge, []},
+ {update, fe2, soft, soft_purge, soft_purge, [fe1]},
+ {update, fe3, {advanced, extra}, soft_purge, soft_purge,
+ [fe1, fe2]}
+ ]},
+
+ {"2.1", [{update, fe1, soft, soft_purge, soft_purge, []},
+ {update, fe2, soft, soft_purge, soft_purge, [fe1]},
+ {update, fe3, {advanced, extra}, soft_purge, soft_purge, [fe1, fe2]}
+ ]}
+ ],
+
+%%% Downgrade to:
+ [
+ {"2.1", [{update, fe2, soft, soft_purge, soft_purge, []},
+ {update, fe3, {advanced, extra}, soft_purge, soft_purge, [fe2]}
+ ]}
+ ]
+}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_no_appup/lib/fe-3.1/ebin/fe.app b/lib/sasl/test/systools_SUITE_data/d_no_appup/lib/fe-3.1/ebin/fe.app
new file mode 100644
index 0000000000..0696e2494c
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_no_appup/lib/fe-3.1/ebin/fe.app
@@ -0,0 +1,7 @@
+{application, fe,
+ [{description, "ERICSSON NR FOR FE"},
+ {vsn, "3.1"},
+ {modules, [{fe1, "1.0"}, {fe2, "1.0"}, {fe3, "2.0"}]},
+ {registered, []},
+ {applications, []},
+ {mod, {fe1, []}}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.0/ebin/db.app b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.0/ebin/db.app
new file mode 100644
index 0000000000..22530ee335
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.0/ebin/db.app
@@ -0,0 +1,8 @@
+{application, db,
+ [{description, "ERICSSON NR FOR DB"},
+ {vsn, "1.0"},
+ {modules, [{db1, "1.0"}, {db2, "1.0"}]},
+ {registered, []},
+ {applications, []},
+ {env, []},
+ {start, {db1, start, []}}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.0/src/db1.erl b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.0/src/db1.erl
new file mode 100644
index 0000000000..a17640316e
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.0/src/db1.erl
@@ -0,0 +1,2 @@
+-module(db2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.0/src/db2.erl b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.0/src/db2.erl
new file mode 100644
index 0000000000..a17640316e
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.0/src/db2.erl
@@ -0,0 +1,2 @@
+-module(db2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.1/ebin/db.app b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.1/ebin/db.app
new file mode 100644
index 0000000000..7243a0a96a
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.1/ebin/db.app
@@ -0,0 +1,8 @@
+{application, db,
+ [{description, "ERICSSON NR FOR DB"},
+ {vsn, "1.1"},
+ {modules, [{db1, "1.0"}, {db2, "1.0"}]},
+ {registered, []},
+ {applications, []},
+ {env, []},
+ {start, {db1, start, []}}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.1/src/db1.erl b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.1/src/db1.erl
new file mode 100644
index 0000000000..a17640316e
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.1/src/db1.erl
@@ -0,0 +1,2 @@
+-module(db2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.1/src/db2.erl b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.1/src/db2.erl
new file mode 100644
index 0000000000..a17640316e
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-1.1/src/db2.erl
@@ -0,0 +1,2 @@
+-module(db2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-2.1/ebin/db.app b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-2.1/ebin/db.app
new file mode 100644
index 0000000000..202d7f1234
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-2.1/ebin/db.app
@@ -0,0 +1,7 @@
+{application, db,
+ [{description, "ERICSSON NR FOR DB"},
+ {vsn, "2.1"},
+ {modules, [{db1, "1.0"}, {db2, "1.0"}]},
+ {registered, []},
+ {applications, []},
+ {mod, {db1, []}}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-2.1/ebin/db.appup b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-2.1/ebin/db.appup
new file mode 100644
index 0000000000..621838f0b4
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-2.1/ebin/db.appup
@@ -0,0 +1,20 @@
+%%
+%% Release upgrade script for db (data base)
+%%
+
+{
+ "2.1",
+%%% Upgrade from:
+ [
+ {"1.0", [{update, db1, soft, soft_purge, soft_purge, []},
+ {update, db2, soft, soft_purge, soft_purge, [db1]}]},
+ {"1.1", [{update, db1, soft, soft_purge, soft_purge, []},
+ {update, db2, soft, soft_purge, soft_purge, [db1]}]}
+ ],
+
+%%% Downgrade to:
+ [
+ {"1.0", [{update, db1, soft, soft_purge, soft_purge, []},
+ {update, db2, soft, soft_purge, soft_purge, [db1]}]}
+ ]
+}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-2.1/src/db1.erl b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-2.1/src/db1.erl
new file mode 100644
index 0000000000..7cddf6bb63
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-2.1/src/db1.erl
@@ -0,0 +1,13 @@
+-module(db1).
+-vsn("1.0").
+
+-export([a/0]).
+
+a() ->
+ lists:non_existing_func("dummy_list"),
+ b().
+
+b() ->
+ fe2:non_existing_func(),
+ db2:non_existing_func(),
+ fe1:a().
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-2.1/src/db2.erl b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-2.1/src/db2.erl
new file mode 100644
index 0000000000..a17640316e
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-2.1/src/db2.erl
@@ -0,0 +1,2 @@
+-module(db2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-3.1/ebin/db.app b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-3.1/ebin/db.app
new file mode 100644
index 0000000000..97643561eb
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-3.1/ebin/db.app
@@ -0,0 +1,7 @@
+{application, db,
+ [{description, "ERICSSON NR FOR DB"},
+ {vsn, "3.1"},
+ {modules, [db1, db2]},
+ {registered, []},
+ {applications, []},
+ {mod, {db1, []}}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-3.1/ebin/db.appup b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-3.1/ebin/db.appup
new file mode 100644
index 0000000000..e636eee158
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-3.1/ebin/db.appup
@@ -0,0 +1,20 @@
+%%
+%% Release upgrade script for db (data base)
+%%
+
+{
+ "3.1",
+%%% Upgrade from:
+ [
+ {"1.0", [{update, db1, soft, soft_purge, soft_purge, []},
+ {update, db2, soft, soft_purge, soft_purge, [db1]}]},
+ {"1.1", [{update, db1, soft, soft_purge, soft_purge, []},
+ {update, db2, soft, soft_purge, soft_purge, [db1]}]}
+ ],
+
+%%% Downgrade to:
+ [
+ {"1.0", [{update, db1, soft, soft_purge, soft_purge, []},
+ {update, db2, soft, soft_purge, soft_purge, [db1]}]}
+ ]
+}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-3.1/src/db1.erl b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-3.1/src/db1.erl
new file mode 100644
index 0000000000..a17640316e
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-3.1/src/db1.erl
@@ -0,0 +1,2 @@
+-module(db2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-3.1/src/db2.erl b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-3.1/src/db2.erl
new file mode 100644
index 0000000000..a17640316e
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/db-3.1/src/db2.erl
@@ -0,0 +1,2 @@
+-module(db2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1.1/ebin/fe.app b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1.1/ebin/fe.app
new file mode 100644
index 0000000000..c7ba1dfe91
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1.1/ebin/fe.app
@@ -0,0 +1,8 @@
+{application, fe,
+ [{description, "ERICSSON NR FOR FE"},
+ {vsn, "2.1.1"},
+ {modules, [{fe1, "1.0"}, {fe2, "1.0"}, {fe3, "2.0"}]},
+ {registered, []},
+ {applications, []},
+ {env, []},
+ {start, {fe2, start, []}}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1.1/src/fe1.erl b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1.1/src/fe1.erl
new file mode 100644
index 0000000000..aa5bfa8098
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1.1/src/fe1.erl
@@ -0,0 +1,2 @@
+-module(fe1).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1.1/src/fe2.erl b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1.1/src/fe2.erl
new file mode 100644
index 0000000000..869f3b93c8
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1.1/src/fe2.erl
@@ -0,0 +1,2 @@
+-module(fe2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1.1/src/fe3.erl b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1.1/src/fe3.erl
new file mode 100644
index 0000000000..6473342f52
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1.1/src/fe3.erl
@@ -0,0 +1,2 @@
+-module(fe3).
+-vsn("2.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1/ebin/fe.app b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1/ebin/fe.app
new file mode 100644
index 0000000000..47ea248720
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1/ebin/fe.app
@@ -0,0 +1,8 @@
+{application, fe,
+ [{description, "ERICSSON NR FOR FE"},
+ {vsn, "2.1"},
+ {modules, [{fe1, "1.0"}, {fe2, "1.0"}, {fe3, "2.0"}]},
+ {registered, []},
+ {applications, []},
+ {env, []},
+ {start, {fe2, start, []}}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1/src/fe1.erl b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1/src/fe1.erl
new file mode 100644
index 0000000000..aa5bfa8098
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1/src/fe1.erl
@@ -0,0 +1,2 @@
+-module(fe1).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1/src/fe2.erl b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1/src/fe2.erl
new file mode 100644
index 0000000000..869f3b93c8
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1/src/fe2.erl
@@ -0,0 +1,2 @@
+-module(fe2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1/src/fe3.erl b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1/src/fe3.erl
new file mode 100644
index 0000000000..6473342f52
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-2.1/src/fe3.erl
@@ -0,0 +1,2 @@
+-module(fe3).
+-vsn("2.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/ebin/fe.app b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/ebin/fe.app
new file mode 100644
index 0000000000..0696e2494c
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/ebin/fe.app
@@ -0,0 +1,7 @@
+{application, fe,
+ [{description, "ERICSSON NR FOR FE"},
+ {vsn, "3.1"},
+ {modules, [{fe1, "1.0"}, {fe2, "1.0"}, {fe3, "2.0"}]},
+ {registered, []},
+ {applications, []},
+ {mod, {fe1, []}}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/ebin/fe.appup b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/ebin/fe.appup
new file mode 100644
index 0000000000..2db69eba76
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/ebin/fe.appup
@@ -0,0 +1,27 @@
+%%
+%% Release upgrade script for fe (front end)
+%%
+
+{
+ "3.1",
+%%% Upgrade from:
+ [
+ {"2.1.1", [{update, fe1, soft, soft_purge, soft_purge, []},
+ {update, fe2, soft, soft_purge, soft_purge, [fe1]},
+ {update, fe3, {advanced, extra}, soft_purge, soft_purge,
+ [fe1, fe2]}
+ ]},
+
+ {"2.1", [{update, fe1, soft, soft_purge, soft_purge, []},
+ {update, fe2, soft, soft_purge, soft_purge, [fe1]},
+ {update, fe3, {advanced, extra}, soft_purge, soft_purge, [fe1, fe2]}
+ ]}
+ ],
+
+%%% Downgrade to:
+ [
+ {"2.1", [{update, fe2, soft, soft_purge, soft_purge, []},
+ {update, fe3, {advanced, extra}, soft_purge, soft_purge, [fe2]}
+ ]}
+ ]
+}.
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/src/fe1.erl b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/src/fe1.erl
new file mode 100644
index 0000000000..8aca89b2c7
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/src/fe1.erl
@@ -0,0 +1,7 @@
+-module(fe1).
+-vsn("1.0").
+
+-export([a/0]).
+
+a() ->
+ ok.
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/src/fe2.erl b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/src/fe2.erl
new file mode 100644
index 0000000000..869f3b93c8
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/src/fe2.erl
@@ -0,0 +1,2 @@
+-module(fe2).
+-vsn("1.0").
diff --git a/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/src/fe3.erl b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/src/fe3.erl
new file mode 100644
index 0000000000..6473342f52
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_normal/lib/fe-3.1/src/fe3.erl
@@ -0,0 +1,2 @@
+-module(fe3).
+-vsn("2.0").
diff --git a/lib/sasl/test/systools_SUITE_data/lib/kernel/ebin/kernel.app b/lib/sasl/test/systools_SUITE_data/lib/kernel/ebin/kernel.app
new file mode 100644
index 0000000000..e33314be7a
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/lib/kernel/ebin/kernel.app
@@ -0,0 +1,6 @@
+{application, kernel,
+ [{description, "FAKE KERNEL"},
+ {vsn, "1.0"},
+ {modules, []},
+ {registered, []},
+ {applications, []}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/lib/kernel/ebin/kernel.appup b/lib/sasl/test/systools_SUITE_data/lib/kernel/ebin/kernel.appup
new file mode 100644
index 0000000000..c53f07591f
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/lib/kernel/ebin/kernel.appup
@@ -0,0 +1,12 @@
+%%
+%% Fake release upgrade script for kernel
+%%
+
+{
+ "4.4.1",
+ [
+ ],
+
+ [
+ ]
+}.
diff --git a/lib/sasl/test/systools_SUITE_data/lib/stdlib/ebin/stdlib.app b/lib/sasl/test/systools_SUITE_data/lib/stdlib/ebin/stdlib.app
new file mode 100644
index 0000000000..288fcfe74e
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/lib/stdlib/ebin/stdlib.app
@@ -0,0 +1,6 @@
+{application, stdlib,
+ [{description, "FAKE STDLIB"},
+ {vsn, "1.0"},
+ {modules, []},
+ {registered, []},
+ {applications, []}]}.
diff --git a/lib/sasl/test/systools_SUITE_data/lib/stdlib/ebin/stdlib.appup b/lib/sasl/test/systools_SUITE_data/lib/stdlib/ebin/stdlib.appup
new file mode 100644
index 0000000000..b521eb5d71
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/lib/stdlib/ebin/stdlib.appup
@@ -0,0 +1,12 @@
+%%
+%% Fake release upgrade script for stdlib
+%%
+
+{
+ "1.1",
+ [
+ ],
+
+ [
+ ]
+}.
diff --git a/lib/sasl/test/systools_rc_SUITE.erl b/lib/sasl/test/systools_rc_SUITE.erl
new file mode 100644
index 0000000000..bb93f38fa7
--- /dev/null
+++ b/lib/sasl/test/systools_rc_SUITE.erl
@@ -0,0 +1,488 @@
+%%
+%% %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(systools_rc_SUITE).
+
+-include_lib("test_server/include/test_server.hrl").
+-include_lib("sasl/src/systools.hrl").
+-export([all/0,groups/0,init_per_group/2,end_per_group/2,
+ syntax_check/1, translate/1, translate_app/1]).
+
+%%-----------------------------------------------------------------
+%% erl -compile systools_rc_SUITE @i ../src/ @i ../../test_server/include/
+%% c(systools_rc_SUITE, [{i, "../src"}, {i, "../../test_server/include"}]).
+%%-----------------------------------------------------------------
+all() ->
+ [syntax_check, translate, translate_app].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+syntax_check(suite) -> [];
+syntax_check(Config) when is_list(Config) ->
+ PreApps =
+ [#application{name = test,
+ description = "TEST",
+ vsn = "0.1",
+ modules = [{foo,1},{bar,1},{baz,1},{old_mod,1}],
+ regs = [],
+ mod = {sasl, []}},
+ #application{name = snmp,
+ description = "SNMP",
+ vsn = "1.0",
+ modules = [snmp],
+ regs = [],
+ mod = {snmp, []}}],
+ Apps =
+ [#application{name = test,
+ description = "TEST",
+ vsn = "1.0",
+ modules = [{foo,1},{bar,1},{baz,1},{new_mod,1}],
+ regs = [],
+ mod = {sasl, []}}],
+ S1 = [
+ {update, bar, {advanced, extra}, brutal_purge, brutal_purge, []},
+ {update, foo, soft, soft_purge, soft_purge, [bar]},
+ {update, baz, 5000, soft, brutal_purge, brutal_purge, []},
+ {add_module, new_mod},
+ {remove_application, snmp}
+ ],
+ ?line {ok, _} = systools_rc:translate_scripts([S1], Apps, PreApps),
+ S2 = [
+ {apply, {m, f, [a]}},
+ {load_object_code, {tst, "1.0", [new_mod]}},
+ point_of_no_return,
+ {update, bar, {advanced, extra}, brutal_purge, brutal_purge, []},
+ {update, foo, soft, soft_purge, soft_purge, [bar]},
+ {load, {new_mod, soft_purge, soft_purge}},
+ {remove, {old_mod, soft_purge, soft_purge}},
+ {purge, [m1, m2]},
+ {suspend, [m1]},
+ {code_change, [{m1, extra}]},
+ {resume, [m1]},
+ {stop, [m3,m4]},
+ {start, [m3,m4]},
+ {sync_nodes, id1, {m, f, [a]}},
+ {sync_nodes, id2, [cp1, cp2]},
+ {apply, {m,f,[a]}},
+ restart_new_emulator
+ ],
+ ?line {ok, _} = systools_rc:translate_scripts([S2], Apps, []),
+ S3 = [{apply, {m, f, a}}],
+ ?line {error, _, _} = systools_rc:translate_scripts([S3], Apps, []),
+ S3_1 = [{apply, {m, 3, a}}],
+ ?line {error, _, _} = systools_rc:translate_scripts([S3_1], Apps, []),
+ S4 = [{apply, {m, f}}],
+ ?line {error, _, _} = systools_rc:translate_scripts([S4], Apps, []),
+ S5 = [{load_object_code, hej}],
+ ?line {error, _, _} = systools_rc:translate_scripts([S5], Apps, []),
+ S6 = [{load_object_code, {342, "1.0", [foo]}}],
+ ?line {error, _, _} = systools_rc:translate_scripts([S6], Apps, []),
+ S7 = [{load_object_code, {tets, "1.0", foo}}],
+ ?line {error, _, _} = systools_rc:translate_scripts([S7], Apps, []),
+ S8 = [{suspend, [m1]}, point_of_no_return],
+ ?line {error, _, _} = systools_rc:translate_scripts([S8], Apps, []),
+ S9 = [{update, ba, {advanced, extra}, brutal_purge, brutal_purge, []}],
+ ?line {error, _, _} = systools_rc:translate_scripts([S9], Apps, []),
+ S10 = [{update, bar, {advanced, extra}, brutal_purge, brutal_purge, [baz]}],
+ ?line {error, _, _} = systools_rc:translate_scripts([S10], Apps, []),
+ S11 = [{update, bar, {advanced, extra}, brutal_purge, brutal_purge, [ba]}],
+ ?line {error, _, _} = systools_rc:translate_scripts([S11], Apps, []),
+ S12 = [{update, bar, advanced, brutal_purge, brutal_purge, []}],
+ ?line {error, _, _} = systools_rc:translate_scripts([S12], Apps, []),
+ S13 = [{update, bar, {advanced, extra}, rutal_purge, brutal_purge, [ba]}],
+ ?line {error, _, _} = systools_rc:translate_scripts([S13], Apps, []),
+ S14 = [{update, bar, {advanced, extra}, brutal_purge, rutal_purge, [ba]}],
+ ?line {error, _, _} = systools_rc:translate_scripts([S14], Apps, []),
+ S15 = [{update, bar, {advanced, extra}, brutal_purge, brutal_purge, ba}],
+ ?line {error, _, _} = systools_rc:translate_scripts([S15], Apps, []),
+ S16 = [{code_change, [module]}],
+ ?line {error, _, _} = systools_rc:translate_scripts([S16], Apps, []),
+ ?line ok.
+
+translate(suite) -> [];
+translate(Config) when is_list(Config) ->
+ Apps =
+ [#application{name = test,
+ description = "TEST",
+ vsn = "1.0",
+ modules = [{foo,1},{bar,1},{baz,1},
+ {x,1},{y,1},{z,1}],
+ regs = [],
+ mod = {sasl, []}}],
+ %% Simple translation (1)
+ Up1 = [{update, foo, soft, soft_purge, soft_purge, []}],
+ ?line {ok, X1} = systools_rc:translate_scripts([Up1], Apps, []),
+ ?line [{load_object_code, {test,"1.0",[foo]}},
+ point_of_no_return,
+ {suspend,[foo]},
+ {load,{foo,soft_purge,soft_purge}},
+ {resume,[foo]}] = X1,
+
+ %% Simple translation (2)
+ Up2 = [{update, foo, {advanced, extra}, soft_purge, soft_purge, []}],
+ ?line {ok, X2} = systools_rc:translate_scripts([Up2], Apps, []),
+ ?line [{load_object_code, {test,"1.0",[foo]}},
+ point_of_no_return,
+ {suspend,[foo]},
+ {load,{foo,soft_purge,soft_purge}},
+ {code_change, up, [{foo, extra}]},
+ {resume,[foo]}] = X2,
+
+ ?line {ok, X22} = systools_rc:translate_scripts(dn,[Up2], Apps, []),
+ ?line [{load_object_code, {test,"1.0",[foo]}},
+ point_of_no_return,
+ {suspend,[foo]},
+ {code_change, down, [{foo, extra}]},
+ {load,{foo,soft_purge,soft_purge}},
+ {resume,[foo]}] = X22,
+
+ Up2a = [{update, foo, static, default, {advanced,extra},
+ soft_purge, soft_purge, []}],
+ ?line {ok, X2a} = systools_rc:translate_scripts([Up2a], Apps, []),
+ ?line [{load_object_code, {test,"1.0",[foo]}},
+ point_of_no_return,
+ {suspend,[foo]},
+ {load,{foo,soft_purge,soft_purge}},
+ {code_change, up, [{foo, extra}]},
+ {resume,[foo]}] = X2a,
+
+ ?line {ok, X22a} = systools_rc:translate_scripts(dn,[Up2a], Apps, []),
+ ?line [{load_object_code, {test,"1.0",[foo]}},
+ point_of_no_return,
+ {suspend,[foo]},
+ {load,{foo,soft_purge,soft_purge}},
+ {code_change, down, [{foo, extra}]},
+ {resume,[foo]}] = X22a,
+
+ %% Simple dependency (1)
+ Up3 = [{update, foo, soft, soft_purge, soft_purge, [bar]},
+ {update, bar, soft, soft_purge, soft_purge, []}],
+ ?line {ok, X31} = systools_rc:translate_scripts([Up3], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,bar]}},
+ point_of_no_return,
+ {suspend,[foo,bar]},
+ {load,{bar,soft_purge,soft_purge}},
+ {load,{foo,soft_purge,soft_purge}},
+ {resume,[bar,foo]}] = X31,
+ ?line {ok, X32} = systools_rc:translate_scripts(dn,[Up3], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,bar]}},
+ point_of_no_return,
+ {suspend,[foo,bar]},
+ {load,{foo,soft_purge,soft_purge}},
+ {load,{bar,soft_purge,soft_purge}},
+ {resume,[bar,foo]}] = X32,
+
+ Up3a = [{update, foo, static, default, soft, soft_purge, soft_purge, [bar]},
+ {update, bar, static, default, soft, soft_purge, soft_purge, []}],
+ ?line {ok, X3a1} = systools_rc:translate_scripts([Up3a], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,bar]}},
+ point_of_no_return,
+ {suspend,[foo, bar]},
+ {load,{bar,soft_purge,soft_purge}},
+ {load,{foo,soft_purge,soft_purge}},
+ {resume,[bar,foo]}] = X3a1,
+ ?line {ok, X3a2} = systools_rc:translate_scripts(dn,[Up3a], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,bar]}},
+ point_of_no_return,
+ {suspend,[foo,bar]},
+ {load,{foo,soft_purge,soft_purge}},
+ {load,{bar,soft_purge,soft_purge}},
+ {resume,[bar,foo]}] = X3a2,
+
+ %% Simple dependency (2)
+ Up4 = [{update, foo, soft, soft_purge, soft_purge, [bar]},
+ {update, bar, {advanced, []}, soft_purge, soft_purge, []}],
+ ?line {ok, X4} = systools_rc:translate_scripts(up,[Up4], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,bar]}},
+ point_of_no_return,
+ {suspend,[foo,bar]},
+ {load,{bar,soft_purge,soft_purge}},
+ {load,{foo,soft_purge,soft_purge}},
+ {code_change,up,[{bar,[]}]},
+ {resume,[bar,foo]}] = X4,
+
+ ?line {ok, X42} = systools_rc:translate_scripts(dn,[Up4], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,bar]}},
+ point_of_no_return,
+ {suspend,[foo,bar]},
+ {code_change,down,[{bar,[]}]},
+ {load,{foo,soft_purge,soft_purge}},
+ {load,{bar,soft_purge,soft_purge}},
+ {resume,[bar,foo]}] = X42,
+
+ Up4a = [{update, foo, soft, soft_purge, soft_purge, [bar]},
+ {update, bar, static, infinity, {advanced, []},
+ soft_purge, soft_purge, []}],
+ ?line {ok, X4a} = systools_rc:translate_scripts(up,[Up4a], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,bar]}},
+ point_of_no_return,
+ {suspend,[foo,{bar,infinity}]},
+ {load,{bar,soft_purge,soft_purge}},
+ {load,{foo,soft_purge,soft_purge}},
+ {code_change,up,[{bar,[]}]},
+ {resume,[bar,foo]}] = X4a,
+
+ ?line {ok, X42a} = systools_rc:translate_scripts(dn,[Up4a], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,bar]}},
+ point_of_no_return,
+ {suspend,[foo,{bar,infinity}]},
+ {load,{foo,soft_purge,soft_purge}},
+ {load,{bar,soft_purge,soft_purge}},
+ {code_change,down,[{bar,[]}]},
+ {resume,[bar,foo]}] = X42a,
+
+ Up4b = [{update, foo, soft, soft_purge, soft_purge, [bar]},
+ {update, bar, dynamic, infinity, {advanced, []},
+ soft_purge, soft_purge, []}],
+ ?line {ok, X4b} = systools_rc:translate_scripts(up,[Up4b], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,bar]}},
+ point_of_no_return,
+ {suspend,[foo,{bar,infinity}]},
+ {load,{bar,soft_purge,soft_purge}},
+ {load,{foo,soft_purge,soft_purge}},
+ {code_change,up,[{bar,[]}]},
+ {resume,[bar,foo]}] = X4b,
+
+ ?line {ok, X42b} = systools_rc:translate_scripts(dn,[Up4b], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,bar]}},
+ point_of_no_return,
+ {suspend,[foo,{bar,infinity}]},
+ {code_change,down,[{bar,[]}]},
+ {load,{foo,soft_purge,soft_purge}},
+ {load,{bar,soft_purge,soft_purge}},
+ {resume,[bar,foo]}] = X42b,
+
+ %% More complex dependency
+ Up5 = [{update, foo, soft, soft_purge, soft_purge, [bar, baz]},
+ {update, bar, {advanced, []}, soft_purge, soft_purge, []},
+ {update, baz, {advanced, baz}, soft_purge, soft_purge, [bar]}],
+ ?line {ok, X5} = systools_rc:translate_scripts([Up5], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,baz,bar]}},
+ point_of_no_return,
+ {suspend,[foo,baz,bar]},
+ {load,{bar,soft_purge,soft_purge}},
+ {load,{baz,soft_purge,soft_purge}},
+ {load,{foo,soft_purge,soft_purge}},
+ {code_change,up,[{baz,baz},{bar,[]}]},
+ {resume,[bar,baz,foo]}] = X5,
+
+ ?line {ok, X52} = systools_rc:translate_scripts(dn,[Up5], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,baz,bar]}},
+ point_of_no_return,
+ {suspend,[foo,baz,bar]},
+ {code_change,down,[{baz,baz},{bar,[]}]},
+ {load,{foo,soft_purge,soft_purge}},
+ {load,{baz,soft_purge,soft_purge}},
+ {load,{bar,soft_purge,soft_purge}},
+ {resume,[bar,baz,foo]}] = X52,
+
+ Up5a = [{update, foo, dynamic, infinity, soft, soft_purge,
+ soft_purge, [bar, baz]},
+ {update, bar, static, 7000, {advanced, []}, soft_purge,
+ soft_purge, []},
+ {update, baz, dynamic, default, {advanced, baz}, soft_purge,
+ soft_purge, [bar]}],
+ ?line {ok, X5a} = systools_rc:translate_scripts([Up5a], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,baz,bar]}},
+ point_of_no_return,
+ {suspend,[{foo,infinity},baz,{bar,7000}]},
+ {load,{bar,soft_purge,soft_purge}},
+ {load,{baz,soft_purge,soft_purge}},
+ {load,{foo,soft_purge,soft_purge}},
+ {code_change,up,[{baz,baz}, {bar,[]}]},
+ {resume,[bar,baz,foo]}] = X5a,
+
+ ?line {ok, X52a} = systools_rc:translate_scripts(dn,[Up5a], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,baz,bar]}},
+ point_of_no_return,
+ {suspend,[{foo,infinity},baz,{bar,7000}]},
+ {code_change,down,[{baz,baz}]},
+ {load,{foo,soft_purge,soft_purge}},
+ {load,{baz,soft_purge,soft_purge}},
+ {load,{bar,soft_purge,soft_purge}},
+ {code_change,down,[{bar,[]}]},
+ {resume,[bar,baz,foo]}] = X52a,
+
+ Up5b = [{update, foo, dynamic, infinity, soft, soft_purge,
+ soft_purge, [bar, baz]},
+ {update, bar, dynamic, 7000, {advanced, []}, soft_purge,
+ soft_purge, []},
+ {update, baz, static, default, {advanced, baz}, soft_purge,
+ soft_purge, [bar]}],
+ ?line {ok, X5b} = systools_rc:translate_scripts([Up5b], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,baz,bar]}},
+ point_of_no_return,
+ {suspend,[{foo,infinity},baz,{bar,7000}]},
+ {load,{bar,soft_purge,soft_purge}},
+ {load,{baz,soft_purge,soft_purge}},
+ {load,{foo,soft_purge,soft_purge}},
+ {code_change,up,[{baz,baz},{bar,[]}]},
+ {resume,[bar,baz,foo]}] = X5b,
+
+ ?line {ok, X52b} = systools_rc:translate_scripts(dn,[Up5b], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,baz,bar]}},
+ point_of_no_return,
+ {suspend,[{foo,infinity},baz,{bar,7000}]},
+ {code_change,down,[{bar,[]}]},
+ {load,{foo,soft_purge,soft_purge}},
+ {load,{baz,soft_purge,soft_purge}},
+ {load,{bar,soft_purge,soft_purge}},
+ {code_change,down,[{baz,baz}]},
+ {resume,[bar,baz,foo]}] = X52b,
+
+ %% Simple circular dependency (1)
+ Up6 = [{update, foo, soft, soft_purge, soft_purge, [bar]},
+ {update, bar, soft, soft_purge, soft_purge, [foo]}],
+ ?line {ok, X61} = systools_rc:translate_scripts([Up6], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,bar]}},
+ point_of_no_return,
+ {suspend,[foo,bar]},
+ {load,{bar,soft_purge,soft_purge}},
+ {load,{foo,soft_purge,soft_purge}},
+ {resume,[bar,foo]}] = X61,
+ ?line {ok, X62} = systools_rc:translate_scripts(dn,[Up6], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,bar]}},
+ point_of_no_return,
+ {suspend,[foo,bar]},
+ {load,{foo,soft_purge,soft_purge}},
+ {load,{bar,soft_purge,soft_purge}},
+ {resume,[bar,foo]}] = X62,
+
+ %% Simple circular dependency (2)
+ Up7 = [{update, foo, soft, soft_purge, soft_purge, [bar, baz]},
+ {update, bar, soft, soft_purge, soft_purge, [foo]},
+ {update, baz, soft, soft_purge, soft_purge, [bar]}],
+ ?line {ok, X71} = systools_rc:translate_scripts([Up7], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,bar,baz]}},
+ point_of_no_return,
+ {suspend,[foo,bar,baz]},
+ {load,{baz,soft_purge,soft_purge}},
+ {load,{bar,soft_purge,soft_purge}},
+ {load,{foo,soft_purge,soft_purge}},
+ {resume,[baz, bar, foo]}] = X71,
+ ?line {ok, X72} = systools_rc:translate_scripts(dn,[Up7], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,bar,baz]}},
+ point_of_no_return,
+ {suspend,[foo,bar,baz]},
+ {load,{foo,soft_purge,soft_purge}},
+ {load,{bar,soft_purge,soft_purge}},
+ {load,{baz,soft_purge,soft_purge}},
+ {resume,[baz,bar,foo]}] = X72,
+
+ %% Complex circular dependencies, check only order
+ %%
+ Up8 = [{update, foo, soft, soft_purge, soft_purge, [baz]},
+ {update, y, soft, soft_purge, soft_purge, [bar]},
+ {update, x, soft, soft_purge, soft_purge, [y, z]},
+ {update, z, soft, soft_purge, soft_purge, [x]},
+ {update, bar, soft, soft_purge, soft_purge, [baz]},
+ {update, baz, soft, soft_purge, soft_purge, [bar]}],
+ ?line {ok, X8} = systools_rc:translate_scripts([Up8], Apps, []),
+ ?line {value, {suspend, Order}} = lists:keysearch(suspend, 1, X8),
+ ?line Rest = case lists:reverse(Order) of
+ [bar, baz | R] -> R;
+ [baz, bar | R] -> R
+ end,
+ ?line case Rest of
+ [y, z, x, foo] -> ok;
+ [y, x, z, foo] -> ok;
+ [foo, y, z, x] -> ok;
+ [foo, y, x, z] -> ok;
+ [y, foo, z, x] -> ok;
+ [y, foo, x, z] -> ok
+ end,
+
+ %% Check that order among other instructions isn't changed
+ Up9 = [{update, foo, soft, soft_purge, soft_purge, [baz]},
+ {apply, {m, f, [1]}},
+ {update, y, soft, soft_purge, soft_purge, [bar]},
+ {apply, {m, f, [2]}},
+ {update, x, soft, soft_purge, soft_purge, [y, z]},
+ {apply, {m, f, [3]}},
+ {update, z, soft, soft_purge, soft_purge, [x]},
+ {apply, {m, f, [4]}},
+ {update, bar, soft, soft_purge, soft_purge, [baz]},
+ {apply, {m, f, [5]}},
+ {update, baz, soft, soft_purge, soft_purge, [bar]},
+ {apply, {m, f, [6]}}],
+ ?line {ok, X9} = systools_rc:translate_scripts([Up9], Apps, []),
+ Other2 = [X || {apply, {m, f, [X]}} <- X9],
+ ?line [1,2,3,4,5,6] = lists:sort(Other2),
+ ?line ok.
+
+
+translate_app(suite) -> [];
+translate_app(Config) when is_list(Config) ->
+ PreApps =
+ [#application{name = test,
+ description = "TEST",
+ vsn = "1.0",
+ modules = [{foo,1},{bar,1},{baz,1}],
+ regs = [],
+ mod = {sasl, []}},
+ #application{name = pelle,
+ description = "PELLE",
+ vsn = "1.0",
+ modules = [pelle, kalle],
+ regs = [],
+ mod = {pelle, []}}],
+ Apps =
+ [#application{name = test,
+ description = "TEST",
+ vsn = "1.0",
+ modules = [{foo,1},{bar,1},{baz,1}],
+ regs = [],
+ mod = {sasl, []}}],
+ %% Simple translation (1)
+ Up1 = [{add_module, foo},
+ {add_module, bar}],
+ ?line {ok, X1} = systools_rc:translate_scripts([Up1], Apps, []),
+ ?line [{load_object_code,{test,"1.0",[foo,bar]}},
+ point_of_no_return,
+ {load,{foo,brutal_purge,brutal_purge}},
+ {load,{bar,brutal_purge,brutal_purge}}] = X1,
+
+ %% Simple translation (2)
+ Up2 = [{add_application, test}],
+ ?line {ok, X2} = systools_rc:translate_scripts([Up2], Apps, []),
+io:format("X2=~p~n", [X2]),
+ ?line [{load_object_code,{test,"1.0",[foo,bar,baz]}},
+ point_of_no_return,
+ {load,{foo,brutal_purge,brutal_purge}},
+ {load,{bar,brutal_purge,brutal_purge}},
+ {load,{baz,brutal_purge,brutal_purge}},
+ {apply,{application,start,[test,permanent]}}] = X2,
+
+ %% Simple translation (3)
+ Up3 = [{remove_application, pelle}],
+ ?line {ok, X3} = systools_rc:translate_scripts([Up3], Apps, PreApps),
+ ?line [point_of_no_return,
+ {apply,{application,stop,[pelle]}},
+ {remove,{pelle,brutal_purge,brutal_purge}},
+ {remove,{kalle,brutal_purge,brutal_purge}},
+ {purge,[pelle,kalle]},
+ {apply,{application,unload,[pelle]}}] = X3,
+ ?line ok.
diff --git a/lib/sasl/vsn.mk b/lib/sasl/vsn.mk
index 8112d145dd..2db134af48 100644
--- a/lib/sasl/vsn.mk
+++ b/lib/sasl/vsn.mk
@@ -1 +1 @@
-SASL_VSN = 2.1.9.3
+SASL_VSN = 2.1.10
diff --git a/lib/snmp/Makefile b/lib/snmp/Makefile
index 20e3d4692a..4264531112 100644
--- a/lib/snmp/Makefile
+++ b/lib/snmp/Makefile
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2009. All Rights Reserved.
+# Copyright Ericsson AB 1996-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -67,7 +67,7 @@ do_configure: configure
configure: configure.in
autoconf
-.PHONY: info
+.PHONY: info gclean
info:
@echo "OS: $(OS)"
@@ -76,6 +76,9 @@ info:
@echo "SNMP_VSN: $(SNMP_VSN)"
@echo "APP_VSN: $(APP_VSN)"
+gclean:
+ git clean -fXd
+
# ----------------------------------------------------
# Application (source) release targets
diff --git a/lib/snmp/doc/src/Makefile b/lib/snmp/doc/src/Makefile
index 35ed63e103..aa9431477c 100644
--- a/lib/snmp/doc/src/Makefile
+++ b/lib/snmp/doc/src/Makefile
@@ -152,6 +152,7 @@ $(TOP_PDF_FILE): $(XML_FILES)
pdf: $(TOP_PDF_FILE)
html: gifs $(HTML_REF_MAN_FILE)
+html2: html $(INDEX_TARGET)
clean clean_docs: clean_html clean_man clean_pdf
rm -f errs core *~
@@ -228,6 +229,7 @@ clean_man:
clean_html:
@echo "cleaning html:"
rm -rf $(HTMLDIR)/*
+ rm -f $(INDEX_TARGET)
$(MAN7DIR)/%.7: $(MIBSDIR)/%.mib
@echo "processing $*"
@@ -286,7 +288,7 @@ release_docs_spec: docs
$(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
$(INSTALL_DIR) $(RELEASE_PATH)/man/man1
$(INSTALL_DATA) $(MAN1_FILES) $(RELEASE_PATH)/man/man1
- $(INSTALL_DIR) $(RELEASE_PATH)/man/man
+ $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
$(INSTALL_DATA) $(MAN3_FILES) $(RELEASE_PATH)/man/man3
$(INSTALL_DIR) $(RELEASE_PATH)/man/man6
$(INSTALL_DATA) $(MAN6_FILES) $(RELEASE_PATH)/man/man6
diff --git a/lib/snmp/doc/src/files.mk b/lib/snmp/doc/src/files.mk
index bd94cd6bac..61c91c9729 100644
--- a/lib/snmp/doc/src/files.mk
+++ b/lib/snmp/doc/src/files.mk
@@ -157,4 +157,5 @@ MIB_FILES = \
$(MIBSDIR)/SNMP-VIEW-BASED-ACM-MIB.mib \
$(MIBSDIR)/SNMP-USM-AES-MIB.mib \
$(MIBSDIR)/INET-ADDRESS-MIB.mib \
+ $(MIBSDIR)/TRANSPORT-ADDRESS-MIB.mib \
$(MIBSDIR)/OTP-SNMPEA-MIB.mib
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index 2efeb8ae3f..9e1a060dee 100644
--- a/lib/snmp/doc/src/notes.xml
+++ b/lib/snmp/doc/src/notes.xml
@@ -33,6 +33,302 @@
</header>
<section>
+ <title>SNMP Development Toolkit 4.21.1</title>
+ <p>Version 4.21.1 supports code replacement in runtime from/to
+ version 4.20.1, 4.20 and 4.19. </p>
+
+ <section>
+ <title>Improvements and new features</title>
+<!--
+ <p>-</p>
+-->
+ <list type="bulleted">
+ <item>
+ <p>[compiler] Used wrong variable name (for
+ warnings-as-errors variable), which caused the
+ compiler to crash when using the snmpc (e)script. </p>
+ <p>Also added the option
+ <seealso marker="snmpc(command)#option_werror">--Werror</seealso>
+ for the SNMP MIB compiler (escript) frontend (to mimic
+ <seealso marker="erts:erlc">erlc</seealso>),
+ which specifies whether warnings should be treated as errors. </p>
+ <p>Own Id: OTP-9447</p>
+ </item>
+
+ <item>
+ <p>[agent] Some very minor debugging improvements. </p>
+ <p>Own Id: OTP-9446</p>
+ </item>
+ </list>
+
+ </section>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <p>-</p>
+
+<!--
+ <list type="bulleted">
+ <item>
+ <p>The snmp config tool could not handle (manager) audit trail config
+ because the option seqno was not handled. </p>
+ <p>Own Id: OTP-9354</p>
+ </item>
+
+ </list>
+-->
+ </section>
+
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+
+ </section> <!-- 4.21.1 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.21</title>
+ <p>Version 4.21 supports code replacement in runtime from/to
+ version 4.20.1, 4.20 and 4.19. </p>
+
+ <section>
+ <title>Improvements and new features</title>
+<!--
+ <p>-</p>
+-->
+ <list type="bulleted">
+ <item>
+ <p>[manager] There was no way to specify transport domain.
+ The transport domains was assumed to be IPv4 (transportDomainUdpIpv4).
+ This has now been changed so that it can also be IPv6
+ (transportDomainUdpIpv6).
+ To facilitate this, the transport domain, <c>tdomain</c>,
+ is now a (new) valid option when
+ <seealso marker="snmpm#register_agent">registering</seealso>
+ a new agent (and
+ <seealso marker="snmpm#update_agent_info">updating</seealso>
+ agent info). </p>
+ <p>This also mean that the transport behaviour has changed. </p>
+ <p>Own Id: OTP-9305</p>
+ <p>Aux Id: Seq 11847</p>
+ </item>
+
+ <item>
+ <p>[compiler] Added the option
+ <seealso marker="snmpc#compile">warnings_as_errors</seealso>
+ (for the SNMP MIB compiler (escript) frontend, the option
+ <seealso marker="snmpc(command)#option_wae">--wae</seealso> is used)
+ which specifies whether warnings should be treated as errors. </p>
+ <p>Tuncer Ayaz</p>
+ <p>Own Id: OTP-9437</p>
+ </item>
+ </list>
+
+ </section>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+<!--
+ <p>-</p>
+-->
+
+ <list type="bulleted">
+ <item>
+ <p>The snmp config tool could not handle (manager) audit trail config
+ because the option seqno was not handled. </p>
+ <p>Own Id: OTP-9354</p>
+ </item>
+
+ <item>
+ <p>[agent] The SNMP ACM cache was not properly updated when
+ changes where made to the VACM security-to-group, access and
+ view-tree-family tables. </p>
+ <p>Own Id: OTP-9367</p>
+ <p>Aux Id: Seq 11858</p>
+ </item>
+
+ <item>
+ <p>Fixed install directory typo for man3. </p>
+ <p>Peter Lemenkov</p>
+ <p>Hans Ulrich Niedermann</p>
+ <p>Own Id: OTP-9442</p>
+ </item>
+
+ </list>
+ </section>
+
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+
+ </section> <!-- 4.21 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.20.1</title>
+ <p>Version 4.20.1 supports code replacement in runtime from/to
+ version 4.20, 4.19 and 4.18.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+<!--
+ <list type="bulleted">
+ <item>
+ <p>Added type specs for functions that do not return. </p>
+ <p>Kostis Sagonas</p>
+ <p>Own Id: OTP-9208</p>
+ </item>
+ </list>
+-->
+ </section>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+<!--
+ <p>-</p>
+-->
+ <list type="bulleted">
+ <item>
+ <p>[agent] Did not handle transport domains properly in some cases,
+ for instance trap sending. </p>
+ <p>Own Id: OTP-9400</p>
+ </item>
+
+ <item>
+ <p>[agent] Wrong default transport domain, snmpUDPDomain, instead
+ of transportDomainUdpIpv4. </p>
+ <p>Own Id: OTP-9425</p>
+ <p>Aux Id: Seq 11874</p>
+ </item>
+
+ </list>
+ </section>
+
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+
+ </section> <!-- 4.20.1 -->
+
+
+ <section>
+ <title>SNMP Development Toolkit 4.20</title>
+ <p>Version 4.20 supports code replacement in runtime from/to
+ version 4.19 and 4.18.</p>
+
+ <section>
+ <title>Improvements and new features</title>
+<!--
+ <p>-</p>
+-->
+ <list type="bulleted">
+ <item>
+ <p>[agent] Added support for sending traps to IPv6 targets. </p>
+ <p>See the
+ <seealso marker="snmp_agent_config_files#target_addr">target address config file</seealso>,
+ the <seealso marker="snmpa_conf#target_addr_entry">target_addr_entry/11</seealso> function or
+ <seealso marker="snmp_target_mib#add_addr">add_addr/11</seealso> for more info. </p>
+ <p>Own Id: OTP-9088</p>
+ <p>Aux Id: Seq 11790</p>
+ </item>
+
+
+ <item>
+ <p>[agent] To be able to handle multiple engine-id(s) when
+ sending trap(s), the function
+ <seealso marker="snmp_community_mib#add_community">
+ add_community/6</seealso> has been added. </p>
+ <p>Own Id: OTP-9119</p>
+ <p>Aux Id: Seq 11792</p>
+ </item>
+
+ <item>
+ <p>[manager] The API for snmp requests has been augmented to
+ allow the caller to override some configuration. </p>
+ <p>This has been done by introducing a new set of API functions, see
+ <seealso marker="snmpm#sync_get2">sync_get2/3,4</seealso>,
+ <seealso marker="snmpm#async_get2">async_get2/3,4</seealso>,
+ <seealso marker="snmpm#sync_get_next2">sync_get_next2/3,4</seealso>,
+ <seealso marker="snmpm#async_get_next2">async_get_next2/3,4</seealso>,
+ <seealso marker="snmpm#sync_get_bulk2">sync_get_bulk2/5,6</seealso>,
+ <seealso marker="snmpm#async_get_bulk2">async_get_bulk2/5,6</seealso>,
+ <seealso marker="snmpm#sync_set2">sync_set2/3,4</seealso> and
+ <seealso marker="snmpm#async_set2">async_set2/3,4</seealso>
+ for more info. </p>
+ <p>Own Id: OTP-9162</p>
+ </item>
+
+ <item>
+ <p>[manager] The old API functions (for get and set
+ requests:
+ snmpm:g/3,4,5,6,7, snmpm:ag/3,4,5,6,7,
+ snmpm:gn/3,4,5,6,7, snmpm:agn/3,4,5,6,7,
+ snmpm:s/3,4,5,6,7, snmpm:s/3,4,5,6,7,
+ snmpm:gb/5,6,7,8,9 and snmpm:agb/5,6,7,8,9)
+ are now officially deprecated.
+ They will be removed as of R16B. </p>
+ <p>Own Id: OTP-9174</p>
+ </item>
+
+ <item>
+ <p>[agent] Pass extra info through the agent to the net-if
+ process when sending notifications. </p>
+ <p>See
+ <seealso marker="snmpa#send_notification2">
+ snmpa:send_notification2/3</seealso> for more info.
+ See also the incomming net-if messages when sending a
+ <seealso marker="snmp_agent_netif#im_send_pdu">trap</seealso>
+ (send_pdu message) and
+ <seealso marker="snmp_agent_netif#im_send_pdu_req">
+ notification</seealso> (send_pdu_req message). </p>
+ <p>Own Id: OTP-9183</p>
+ <p>Aux Id: Seq 11817</p>
+ </item>
+
+ <item>
+ <p>Added type specs for functions that do not return. </p>
+ <p>Kostis Sagonas</p>
+ <p>Own Id: OTP-9208</p>
+ </item>
+ </list>
+ </section>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+<!--
+ <p>-</p>
+-->
+
+ <list type="bulleted">
+ <item>
+ <p>Fixed endode/decode of values of type <c>Counter32</c>. </p>
+ <p>This type (<c>Counter32</c>) is an unsigned integer 32,
+ but is actually encoded as an signed integer 32.
+ The encode/decode functions however, treated it as if it was
+ encodeded as an unsigned integer 32. </p>
+ <p>Own Id: OTP-9022</p>
+ </item>
+
+ </list>
+ </section>
+
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+
+ </section> <!-- 4.20 -->
+
+
+ <section>
<title>SNMP Development Toolkit 4.19</title>
<p>Version 4.19 supports code replacement in runtime from/to
version 4.18.</p>
@@ -126,6 +422,7 @@ snmp_view_basec_acm_mib:vacmAccessTable(set, RowIndex, Cols).
</section> <!-- 4.19 -->
+
<section>
<title>SNMP Development Toolkit 4.18</title>
<p>Version 4.18 supports code replacement in runtime from/to
@@ -226,7 +523,7 @@ snmp_view_basec_acm_mib:vacmAccessTable(set, RowIndex, Cols).
<p>The config utility
(<seealso marker="snmp#config">snmp:config/0</seealso>)
generated a default notify.conf
- with a bad name for the starndard trap entry (was "stadard trap",
+ with a bad name for the standard trap entry (was "stadard trap",
but should have been "standard trap"). This has been corrected. </p>
<p>Kenji Rikitake</p>
<p>Own Id: OTP-8433</p>
@@ -430,7 +727,7 @@ snmp_view_basec_acm_mib:vacmAccessTable(set, RowIndex, Cols).
<p>The config utility
(<seealso marker="snmp#config">snmp:config/0</seealso>)
generated a default notify.conf
- with a bad name for the starndard trap entry (was "stadard trap",
+ with a bad name for the standard trap entry (was "stadard trap",
but should have been "standard trap"). This has been corrected. </p>
<p>Kenji Rikitake</p>
<p>Own Id: OTP-8433</p>
diff --git a/lib/snmp/doc/src/snmp_agent_config_files.xml b/lib/snmp/doc/src/snmp_agent_config_files.xml
index b62269d506..bd5c537522 100644
--- a/lib/snmp/doc/src/snmp_agent_config_files.xml
+++ b/lib/snmp/doc/src/snmp_agent_config_files.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>
@@ -367,56 +367,50 @@
<marker id="target_addr"></marker>
<title>Target Address Definitions</title>
<p>The information about Target Address Definitions should be
- stored in a file called
- <c>target_addr.conf</c>.
- </p>
+ stored in a file called <c>target_addr.conf</c>. </p>
<p>The corresponding tables are <c>snmpTargetAddrTable</c> in the
- SNMP-TARGET-MIB and <c>snmpTargetAddrExtTable</c> in the SNMP-COMMUNITY-MIB.
- </p>
- <p>Each entry is a term:
- </p>
- <p><c>{TargetName, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId}.</c> or <br></br>
-<c>{TargetName, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize}.</c></p>
+ SNMP-TARGET-MIB and <c>snmpTargetAddrExtTable</c> in the
+ SNMP-COMMUNITY-MIB. </p>
+ <p>Each entry is a term: </p>
+ <p><c>{TargetName, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId}.</c> <br></br> or <br></br>
+<c>{TargetName, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize}.</c> <br></br> or <br></br>
+<c>{TargetName, Domain, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize}.</c></p>
<list type="bulleted">
<item>
<p><c>TargetName</c> is a unique non-empty string.
</p>
</item>
<item>
- <p><c>Ip</c> is a list of four integers.
- </p>
+ <p><c>Domain</c> is one of the atoms:
+ <c>transportDomainUdpIpv4</c> | <c>transportDomainUdpIpv6</c>. </p>
</item>
<item>
- <p><c>Udp</c> is an integer.
- </p>
+ <p><c>Ip</c> is a list of four or eight integers. </p>
</item>
<item>
- <p><c>Timeout</c> is an integer.
- </p>
+ <p><c>Udp</c> is an integer. </p>
</item>
<item>
- <p><c>RetryCount</c> is an integer.
- </p>
+ <p><c>Timeout</c> is an integer. </p>
</item>
<item>
- <p><c>TagList</c> is a string.
- </p>
+ <p><c>RetryCount</c> is an integer. </p>
</item>
<item>
- <p><c>ParamsName</c> is a string.
- </p>
+ <p><c>TagList</c> is a string. </p>
</item>
<item>
- <p><c>EngineId</c> is a string or the atom <c>discovery</c>.
- </p>
+ <p><c>ParamsName</c> is a string. </p>
</item>
<item>
- <p><c>TMask</c> is a string of size 0, or size 6 (default: []).
- </p>
+ <p><c>EngineId</c> is a string or the atom <c>discovery</c>. </p>
</item>
<item>
- <p><c>MaxMessageSize</c> is an integer (default: 2048).
- </p>
+ <p><c>TMask</c> is a list of integer() of size 0,
+ size 6 or size 10 (default: []). </p>
+ </item>
+ <item>
+ <p><c>MaxMessageSize</c> is an integer (default: 2048). </p>
</item>
</list>
<p>Note that if <c>EngineId</c> has the value <c>discovery</c>,
@@ -429,14 +423,10 @@
<marker id="target_params"></marker>
<title>Target Parameters Definitions</title>
<p>The information about Target Parameters Definitions should be
- stored in a file called
- <c>target_params.conf</c>.
- </p>
+ stored in a file called <c>target_params.conf</c>. </p>
<p>The corresponding table is <c>snmpTargetParamsTable</c> in the
- SNMP-TARGET-MIB.
- </p>
- <p>Each entry is a term:
- </p>
+ SNMP-TARGET-MIB. </p>
+ <p>Each entry is a term: </p>
<p><c>{ParamsName, MPModel, SecurityModel, SecurityName, SecurityLevel}.</c></p>
<list type="bulleted">
<item>
diff --git a/lib/snmp/doc/src/snmp_agent_netif.xml b/lib/snmp/doc/src/snmp_agent_netif.xml
index 1f2dbe80db..8f1d860d58 100644
--- a/lib/snmp/doc/src/snmp_agent_netif.xml
+++ b/lib/snmp/doc/src/snmp_agent_netif.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>1997</year><year>2009</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -65,16 +65,19 @@
</section>
<section>
+ <marker id="messages"></marker>
<title>Messages</title>
<p>The section <em>Messages</em> describes mandatory messages, which
Net if must send and be able to receive.
</p>
<section>
+ <marker id="outgoing_messages"></marker>
<title>Outgoing Messages</title>
<p>Net if must send the following message when it receives an
- SNMP PDU from the network that is aimed for the MasterAgent:
- </p>
+ SNMP PDU from the network that is aimed for the MasterAgent:
+ </p>
+ <marker id="om_snmp_pdu"></marker>
<pre>
MasterAgent ! {snmp_pdu, Vsn, Pdu, PduMS, ACMData, From, Extra}
</pre>
@@ -106,16 +109,18 @@ MasterAgent ! {snmp_pdu, Vsn, Pdu, PduMS, ACMData, From, Extra}
the request.</item>
</list>
<p>The following message is used to report that a response to a
- request has been received. The only request an agent can send
- is an Inform-Request.
- </p>
+ request has been received. The only request an agent can send
+ is an Inform-Request.
+ </p>
+ <marker id="om_snmp_response_received"></marker>
<pre>
Pid ! {snmp_response_received, Vsn, Pdu, From}
</pre>
<list type="bulleted">
<item><c>Pid</c> is the Process that waits for the response
for the request. The Pid was specified in the
- <c>send_pdu_req</c> message <seealso marker="#message">(see below)</seealso>.
+ <c>send_pdu_req</c> message
+ <seealso marker="#im_send_pdu_req">(see below)</seealso>.
</item>
<item><c>Vsn</c> is either <c>'version-1'</c>, <c>'version-2'</c>, or
<c>'version-3'</c>.
@@ -131,119 +136,153 @@ Pid ! {snmp_response_received, Vsn, Pdu, From}
</section>
<section>
+ <marker id="incoming_messages"></marker>
<title>Incoming Messages</title>
<p>This section describes the incoming messages which a Net if
- process must be able to receive.
- </p>
+ process must be able to receive.
+ </p>
<list type="bulleted">
<item>
+ <marker id="im_snmp_response"></marker>
<p><c>{snmp_response, Vsn, Pdu, Type, ACMData, To, Extra}</c></p>
<p>This message is sent to the Net if process from a master
agent as a response to a previously received request.
</p>
<list type="bulleted">
- <item><c>Vsn</c> is either <c>'version-1'</c>,
- <c>'version-2'</c>, or <c>'version-3'</c>.
+ <item>
+ <p><c>Vsn</c> is either <c>'version-1'</c>,
+ <c>'version-2'</c>, or <c>'version-3'</c>. </p>
</item>
- <item><c>Pdu</c> is an SNMP PDU record (as defined in
- snmp_types.hrl) with the SNMP response.
+ <item>
+ <p><c>Pdu</c> is an SNMP PDU record (as defined in
+ snmp_types.hrl) with the SNMP response. </p>
</item>
- <item><c>Type</c> is the <c>#pdu.type</c> of the original
- request.
+ <item>
+ <p><c>Type</c> is the <c>#pdu.type</c>
+ of the original request. </p>
</item>
- <item><c>ACMData</c> is data used by the Access Control
- Module in use. Normally this is just sent to
- <c>snmpa_mpd:generate_response_message</c> (see Reference Manual).
+ <item>
+ <p><c>ACMData</c> is data used by the Access Control
+ Module in use. Normally this is just sent to
+ <c>snmpa_mpd:generate_response_message</c>
+ (see Reference Manual). </p>
</item>
- <item><c>To</c> is the destination address. If UDP over IP
- is used, this should be a 2-tuple <c>{IP, UDPport}</c>,
- where <c>IP</c> is a 4-tuple with the IP address, and
- <c>UDPport</c> is an integer.
+ <item>
+ <p><c>To</c> is the destination address. If UDP over IP
+ is used, this should be a 2-tuple <c>{IP, UDPport}</c>,
+ where <c>IP</c> is a 4-tuple with the IP address, and
+ <c>UDPport</c> is an integer. </p>
</item>
- <item><c>Extra</c> is the term that the Net if process
- sent to the agent when the request was sent to the agent.
+ <item>
+ <p><c>Extra</c> is the term that the Net if process
+ sent to the agent when the request was sent to the agent. </p>
</item>
</list>
</item>
<item>
+ <marker id="im_discarded_pdu"></marker>
<p><c>{discarded_pdu, Vsn, ReqId, ACMData, Variable, Extra}</c></p>
<p>This message is sent from a master agent if it for some
- reason decided to discard the pdu.
- </p>
+ reason decided to discard the pdu. </p>
<list type="bulleted">
- <item><c>Vsn</c> is either <c>'version-1'</c>,
- <c>'version-2'</c>, or <c>'version-3'</c>.
+ <item>
+ <p><c>Vsn</c> is either <c>'version-1'</c>,
+ <c>'version-2'</c>, or <c>'version-3'</c>. </p>
</item>
- <item><c>ReqId</c> is the request id of the original
- request.
+ <item>
+ <p><c>ReqId</c> is the request id of the original request. </p>
</item>
- <item><c>ACMData</c> is data used by the Access Control
- Module in use. Normally this is just sent to
- <c>snmpa_mpd:generate_response_message</c> (see Reference Manual).
+ <item>
+ <p><c>ACMData</c> is data used by the Access Control
+ Module in use. Normally this is just sent to
+ <c>snmpa_mpd:generate_response_message</c>
+ (see Reference Manual). </p>
</item>
- <item><c>Variable</c> is the name of an snmp counter that
- represents the error, e.g. <c>snmpInBadCommunityUses</c>.
+ <item>
+ <p><c>Variable</c> is the name of an snmp counter that
+ represents the error, e.g. <c>snmpInBadCommunityUses</c>. </p>
</item>
- <item><c>Extra</c> is the term that the Net if process
- sent to the agent when the request was sent to the agent.
+ <item>
+ <p><c>Extra</c> is the term that the Net if process
+ sent to the agent when the request was sent to the agent. </p>
</item>
</list>
</item>
<item>
- <p><c>{send_pdu, Vsn, Pdu, MsgData, To}</c></p>
+ <marker id="im_send_pdu"></marker>
+ <p><c>{send_pdu, Vsn, Pdu, MsgData, To, Extra}</c></p>
<p>This message is sent from a master agent when a trap is
- to be sent.
- </p>
+ to be sent. </p>
<list type="bulleted">
- <item><c>Vsn</c> is either <c>'version-1'</c>,
- <c>'version-2'</c>, or <c>'version-3'</c>.
+ <item>
+ <p><c>Vsn</c> is either <c>'version-1'</c>,
+ <c>'version-2'</c>, or <c>'version-3'</c>.</p>
</item>
- <item><c>Pdu</c> is an SNMP PDU record (as defined in
- snmp_types.hrl) with the SNMP response.
+ <item>
+ <p><c>Pdu</c> is an SNMP PDU record (as defined in
+ snmp_types.hrl) with the SNMP response. </p>
+ </item>
+ <item>
+ <p><c>MsgData</c> is the message specific data used in
+ the SNMP message. This value is normally sent to
+ <c>snmpa_mpd:generate_message/4</c>. In SNMPv1 and
+ SNMPv2c, this message data is the community string. In
+ SNMPv3, it is the context information. </p>
</item>
- <item><c>MsgData</c> is the message specific data used in
- the SNMP message. This value is normally sent to
- <c>snmpa_mpd:generate_message/4</c>. In SNMPv1 and
- SNMPv2c, this message data is the community string. In
- SNMPv3, it is the context information.
+ <item>
+ <p><c>To</c> is a list of the destination addresses and
+ their corresponding security parameters. This value is
+ normally sent to <c>snmpa_mpd:generate_message/4</c>. </p>
</item>
- <item><c>To</c> is a list of the destination addresses and
- their corresponding security parameters. This value is
- normally sent to <c>snmpa_mpd:generate_message/4</c>.
+ <item>
+ <p><c>Extra</c> is any term that the notification sender
+ wishes to pass to the Net if process when sending a notification
+ (see
+ <seealso marker="snmpa#send_notification2">send notification
+ </seealso> for more info). </p>
</item>
</list>
</item>
<item>
- <p><c>{send_pdu_req, Vsn, Pdu, MsgData, To, Pid}</c></p>
- <p>This <marker id="message"></marker>
- message is sent from a master
- agent when a request is
- to be sent. The only request an agent can send is
- Inform-Request. The net if process needs to remember the
- request id and the Pid, and when a response is received for
- the request id, send it to Pid, using a
- <c>snmp_response_received</c> message.
- </p>
- <list type="bulleted">
- <item><c>Vsn</c> is either <c>'version-1'</c>,
- <c>'version-2'</c>, or <c>'version-3'</c>.
- </item>
- <item><c>Pdu</c> is an SNMP PDU record (as defined in
- snmp_types.hrl) with the SNMP response.
- </item>
- <item><c>MsgData</c> is the message specific data used in
- the SNMP message. This value is normally sent to
- <c>snmpa_mpd:generate_message/4</c>. In SNMPv1 and
- SNMPv2c, this message data is the community string. In
- SNMPv3, it is the context information.
+ <marker id="im_send_pdu_req"></marker>
+ <p><c>{send_pdu_req, Vsn, Pdu, MsgData, To, Pid, Extra}</c></p>
+ <p>This message is sent from a master agent when a request is to
+ be sent. The only request an agent can send is Inform-Request.
+ The net if process needs to remember the request id and the Pid,
+ and when a response is received for the request id, send it to Pid,
+ using a <c>snmp_response_received</c> message. </p>
+ <list type="bulleted">
+ <item>
+ <p><c>Vsn</c> is either <c>'version-1'</c>,
+ <c>'version-2'</c>, or <c>'version-3'</c>.</p>
+ </item>
+ <item>
+ <p><c>Pdu</c> is an SNMP PDU record (as defined in
+ snmp_types.hrl) with the SNMP response. </p>
+ </item>
+ <item>
+ <p><c>MsgData</c> is the message specific data used in
+ the SNMP message. This value is normally sent to
+ <c>snmpa_mpd:generate_message/4</c>. In SNMPv1 and
+ SNMPv2c, this message data is the community string. In
+ SNMPv3, it is the context information. </p>
+ </item>
+ <item>
+ <p><c>To</c> is a list of the destination addresses and
+ their corresponding security parameters. This value is
+ normally sent to <c>snmpa_mpd:generate_message/4</c>. </p>
+ </item>
+ <item>
+ <p><c>Pid</c> is a process identifier. </p>
+ </item>
+ <item>
+ <p><c>Extra</c> is any term that the notification sender
+ wishes to pass to the Net if process when sending a notification
+ (see
+ <seealso marker="snmpa#send_notification2">send notification
+ </seealso> for more info). </p>
</item>
- <item><c>To</c> is a list of the destination addresses and
- their corresponding security parameters. This value is
- normally sent to <c>snmpa_mpd:generate_message/4</c>.
- </item>
- <item><c>Pid</c> is a process identifier.
- </item>
- </list>
+ </list>
</item>
</list>
</section>
diff --git a/lib/snmp/doc/src/snmp_community_mib.xml b/lib/snmp/doc/src/snmp_community_mib.xml
index 7c7386af19..5e7bca3e27 100644
--- a/lib/snmp/doc/src/snmp_community_mib.xml
+++ b/lib/snmp/doc/src/snmp_community_mib.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
<header>
<copyright>
- <year>1999</year><year>2009</year>
+ <year>1999</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -35,11 +35,13 @@
<modulesummary>Instrumentation Functions for SNMP-COMMUNITY-MIB</modulesummary>
<description>
<p>The module <c>snmp_community_mib</c> implements the instrumentation
- functions for the
- SNMP-COMMUNITY-MIB, and functions for configuring the database.
- </p>
+ functions for the SNMP-COMMUNITY-MIB, and functions for configuring the
+ database. </p>
<p>The configuration files are described in the SNMP User's Manual.</p>
+
+ <marker id="configure"></marker>
</description>
+
<funcs>
<func>
<name>configure(ConfDir) -> void()</name>
@@ -68,8 +70,11 @@
</p>
<p>The configuration file read is: <c>community.conf</c>.
</p>
+
+ <marker id="reconfigure"></marker>
</desc>
</func>
+
<func>
<name>reconfigure(ConfDir) -> void()</name>
<fsummary>Configure the SNMP-COMMUNITY-MIB</fsummary>
@@ -96,28 +101,35 @@
where the configuration files are found.
</p>
<p>The configuration file read is: <c>community.conf</c>.</p>
+
<marker id="add_community"></marker>
</desc>
</func>
+
<func>
<name>add_community(Idx, CommName, SecName, CtxName, TransportTag) -> Ret</name>
+ <name>add_community(Idx, CommName, SecName, EngineId, CtxName, TransportTag) -> Ret</name>
<fsummary>Added one community</fsummary>
<type>
<v>Idx = string()</v>
<v>CommName = string()</v>
<v>SecName = string()</v>
+ <v>EngineId = string()</v>
<v>CtxName = string()</v>
<v>TransportTag = string()</v>
<v>Ret = {ok, Key} | {error, Reason}</v>
<v>Key = term()</v>
- <v>Reason = term()</v>
+ <v>Reason = term()</v>
</type>
<desc>
<p>Adds a community to the agent config.
- Equivalent to one line in the <c>community.conf</c> file.</p>
+ Equivalent to one line in the <c>community.conf</c> file.</p>
+ <p>With the <c>EngineId</c> argument it is possible to
+ override the configured engine-id (SNMP-FRAMEWORK-MIB).</p>
<marker id="delete_community"></marker>
</desc>
</func>
+
<func>
<name>delete_community(Key) -> Ret</name>
<fsummary>Delete one community</fsummary>
diff --git a/lib/snmp/doc/src/snmp_target_mib.xml b/lib/snmp/doc/src/snmp_target_mib.xml
index 4a36be19a3..d5151d41de 100644
--- a/lib/snmp/doc/src/snmp_target_mib.xml
+++ b/lib/snmp/doc/src/snmp_target_mib.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
<header>
<copyright>
- <year>1998</year><year>2009</year>
+ <year>1998</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -39,9 +39,21 @@
and functions for configuring the database. </p>
<p>The configuration files are described in the SNMP User's Manual.</p>
- <marker id="configure"></marker>
+ <marker id="types"></marker>
</description>
+ <section>
+ <title>DATA TYPES</title>
+ <code type="none"><![CDATA[
+transportDomain() = transportDomainUdpIpv4 | transportDomainUdpIpv6
+transportAddressIPv4() = [integer()], length 4
+transportAddressIPv6() = [integer()], length 8
+transportAddressMask() = [integer()], length 0 (default), 6 (IPv4) or 10 (IPv6)
+ ]]></code>
+
+ <marker id="configure"></marker>
+ </section>
+
<funcs>
<func>
<name>configure(ConfDir) -> void()</name>
@@ -118,17 +130,19 @@
<func>
<name>add_addr(Name, Ip, Port, Timeout, Retry, TagList, Params, EngineId, TMask, MMS) -> Ret</name>
+ <name>add_addr(Name, Domain, Ip, Port, Timeout, Retry, TagList, Params, EngineId, TMask, MMS) -> Ret</name>
<fsummary>Add one target address definition</fsummary>
<type>
<v>Name = string()</v>
- <v>Ip = [integer()], length 4</v>
+ <v>Domain = transportDomain()</v>
+ <v>Ip = transportAddressIPv4() | transportAddressIPv6() (depends on the value of Domain)</v>
<v>Port = integer()</v>
<v>Timeout = integer()</v>
<v>Retry = integer()</v>
<v>TagList = string()</v>
<v>ParamsName = string()</v>
<v>EngineId = string()</v>
- <v>TMask = string(), length 0 or 6</v>
+ <v>TMask = transportAddressMask() (depends on Domain)</v>
<v>MMS = integer()</v>
<v>Ret = {ok, Key} | {error, Reason}</v>
<v>Key = term()</v>
diff --git a/lib/snmp/doc/src/snmpa.xml b/lib/snmp/doc/src/snmpa.xml
index 1d680e80f5..27d89ea4e3 100644
--- a/lib/snmp/doc/src/snmpa.xml
+++ b/lib/snmp/doc/src/snmpa.xml
@@ -872,10 +872,138 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2).
then that sub-agent will be unregistered from all trees in
<c>Agent</c>. </p>
- <marker id="send_notification"></marker>
+ <marker id="send_notification2"></marker>
</desc>
</func>
+
+ <func>
+ <name>send_notification2(Agent, Notification, SendOpts) -> void()</name>
+ <fsummary>Send notification</fsummary>
+ <type>
+ <v>Agent = pid() | atom()</v>
+ <v>Notification = atom()</v>
+ <v>SendOpts = [send_option()]</v>
+ <v>send_option() = {receiver, receiver()} | {name, notify_name()} | {context, context_name()} | {varbinds, varbinds()} | {local_engine_id, string()} | {extra, extra_info()}</v>
+ <v>receiver() = no_receiver | {tag(), tag_receiver()} | notification_delivery_info()</v>
+ <v>tag() = term(()</v>
+ <v>tag_receiver() = pid() | registered_name() | {Mod, Func, Args}</v>
+ <v>registered_name() = atom()</v>
+ <v>Mod = atom()</v>
+ <v>Func = atom()</v>
+ <v>Args = list()</v>
+ <v>notify_name() = string()</v>
+ <v>context_name() = string()</v>
+ <v>varbinds() = [varbind()]</v>
+ <v>varbind() = {variable(), value()} | {column(), row_index(), value()} | {oid(), value()}</v>
+ <v>variable() = atom()</v>
+ <v>value() = term()</v>
+ <v>column() = atom()</v>
+ <v>row_index() = [int()]</v>
+ <v>extra_info() = term()</v>
+ </type>
+ <desc>
+ <p>Send the notification <c>Notification</c> to the management
+ targets defined for notify-name (<c>name</c>) in the
+ <c>snmpNotifyTable</c> in SNMP-NOTIFICATION-MIB from the
+ specified <c>context</c>. </p>
+
+ <p>If no <c>name</c> is specified (or if it is <c>""</c>), the
+ notification is sent to all management targets. </p>
+
+ <p>If no <c>context</c> is specified, the default context, <c>""</c>,
+ is used. </p>
+
+ <p>The send option <c>receiver</c> specifies where information
+ about delivery of Inform-Requests should be sent. The agent
+ sends Inform-Requests and waits for acknowledgments from the
+ management targets.
+ The <c>receiver</c> can have three values: </p>
+
+ <list type="bulleted">
+ <item>
+ <p><c>no_receiver</c> - No information is delivered. </p>
+ </item>
+
+ <item>
+ <p><c>notification_delivery_info()</c> - The information is
+ delivered via a function call according to this data. See the
+ <seealso marker="#data_types">DATA TYPES</seealso> section
+ above for details. </p>
+ </item>
+
+ <item>
+ <p><c>{tag(), tag_receiver()}</c> - The information is delivered
+ either via messages or via a function call according to the value
+ of <c>tag_receiver()</c>. </p>
+ <p>Delivery is done differently depending on the value
+ of <c>tag_receiver()</c>: </p>
+
+ <list>
+ <item>
+ <p><c>pid() | registered_name()</c> - The info will be delivered in
+ the following messages: </p>
+ <list>
+ <item>
+ <p><c>{snmp_targets, tag(), Addresses}</c></p>
+ <p>This informs the user which target addresses the
+ notification was sent to. </p>
+ </item>
+ <item>
+ <p><c>{snmp_notification, tag(), {got_response, Address}}</c></p>
+ <p>This informs the user that this target address
+ acknowledged the notification. </p>
+ </item>
+ <item>
+ <p><c>{snmp_notification, tag(), {no_response, Address}}</c></p>
+ <p>This informs the user that this target address
+ did not acknowledge the notification. </p>
+ </item>
+ </list>
+ <p>The notification is sent as an Inform-Request to each
+ target address in <c>Addresses</c> and if there are no
+ targets for which an Inform-Request is sent, <c>Addresses</c>
+ is the empty list <c>[]</c>. </p>
+ <p>The <c>tag_receiver()</c> will first be sent the
+ <c>snmp_targets</c> message, and then for each address in
+ <c>Addresses</c> list, one of the two <c>snmp_notification</c>
+ messages. </p>
+ </item>
+
+ <item>
+ <p><c>{Mod, Func, Args}</c> - The info will be delivered via
+ the function call: </p>
+ <p><c>Mod:Func([Msg | Args])</c></p>
+ <p>where <c>Msg</c> has the same content and purpose as the
+ messages descrived above.</p>
+ </item>
+
+ </list>
+ </item>
+ </list>
+
+ <note>
+ <p>The <c>extra</c> info is not normally interpreted by the agent,
+ instead it is passed through to the
+ <seealso marker="snmp_agent_netif">net-if</seealso> process. It is
+ up to the implementor of that process to make use of this data. </p>
+ <p>The version of net-if provided by this application makes no use
+ of this data, with one exception:
+ Any tuple containing the atom
+ <c>snmpa_default_notification_extra_info</c>
+ may be used by the agent and is therefor <em>reserved</em>. </p>
+ <p>See the net-if incomming messages for sending a
+ <seealso marker="snmp_agent_netif#im_send_pdu">
+ trap</seealso> and
+ <seealso marker="snmp_agent_netif#im_send_pdu_req">
+ notification</seealso> for more info. </p>
+ </note>
+
+ <marker id="send_notification"></marker>
+ </desc>
+ </func>
+
+
<func>
<name>send_notification(Agent, Notification, Receiver)</name>
<name>send_notification(Agent, Notification, Receiver, Varbinds)</name>
@@ -907,18 +1035,19 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2).
</type>
<desc>
<p>Sends the notification <c>Notification</c> to the
- management targets defined for <c>NotifyName</c> in the
- <c>snmpNotifyTable</c> in SNMP-NOTIFICATION-MIB from the
- specified context. If no <c>NotifyName</c> is specified (or
- if it is <c>""</c>), the notification is sent to all
- management targets (<c>Addresses</c> below). If no <c>ContextName</c>
- is specified, the default <c>""</c> context is used.
- </p>
+ management targets defined for <c>NotifyName</c> in the
+ <c>snmpNotifyTable</c> in SNMP-NOTIFICATION-MIB from the
+ specified context. </p>
+ <p>If no <c>NotifyName</c> is specified (or if it is <c>""</c>),
+ the notification is sent to all management targets
+ (<c>Addresses</c> below). </p>
+ <p>If no <c>ContextName</c> is specified, the default <c>""</c>
+ context is used. </p>
<p>The parameter <c>Receiver</c> specifies where information
- about delivery of Inform-Requests should be sent. The agent
- sends Inform-Requests and waits for acknowledgments from the
- managers. <c>Receiver</c> can have three values: </p>
+ about delivery of Inform-Requests should be sent. The agent
+ sends Inform-Requests and waits for acknowledgments from the
+ managers. <c>Receiver</c> can have three values: </p>
<list type="bulleted">
<item>
@@ -926,17 +1055,18 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2).
</item>
<item>
- <p><c>{Tag, Recv}</c> - The information is delivered either via messages
- or via a function call according to the value of <c>Recv</c>. </p>
- </item>
-
- <item>
<p><c>notification_delivery_info()</c> - The information is
delivered via a function call according to this data. See the
<seealso marker="#data_types">DATA TYPES</seealso> section
above for details. </p>
</item>
+ <item>
+ <p><c>{Tag, Recv}</c> - The information is delivered either via
+ messages or via a function call according to the value of
+ <c>Recv</c>. </p>
+ </item>
+
</list>
@@ -1064,86 +1194,20 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2).
(see SNMP-FRAMEWORK-MIB). </p>
</note>
-<!--
- <marker id="send_trap"></marker>
--->
- <marker id="discovery"></marker>
+ <p><c>ExtraInfo</c> is not normally used in any way by the agent.
+ It is intended to be passed along to the net-if process, which is
+ a component that a user can implement themself. The users own net-if
+ may then make use of ExtraInfo. The net-if provided with this
+ application does not process ExtraInfo. </p>
+ <p>There is one exception. <em>Any</em> tuple containing the atom
+ <c>snmpa_default_notification_extra_info</c> will, in this context,
+ be considered belonging to this application, and may be processed
+ by the agent. </p>
+
+ <marker id="discovery"></marker>
</desc>
</func>
-<!--
- <func>
- <name>send_trap(Agent,Trap,Community)</name>
- <name>send_trap(Agent,Trap,Community,Varbinds) -> void()</name>
- <fsummary>Send a trap</fsummary>
- <type>
- <v>Agent = pid() | atom()</v>
- <v>Trap = atom()</v>
- <v>Community = string()</v>
- <v>Varbinds = [Varbind]</v>
- <v>Varbind = {Variable, Value} | {Column, RowIndex, Value} | {OID, Value}</v>
- <v>Variable = atom()</v>
- <v>Column = atom()</v>
- <v>OID = oid()</v>
- <v>Value = term()</v>
- <v>RowIndex = [int()]</v>
- </type>
- <desc>
- <p>Note! This function is only kept for backwards
- compatibility reasons. Use <c>send_notification</c> instead.
- </p>
- <p>Sends the trap <c>Trap</c> to the managers defined for
- <c>Community</c> in the <c>intTrapDestTable</c> in
- OTP-SNMPEA-MIB. The optional argument <c>Varbinds</c> defines
- values for the objects in the trap. If no value is given for
- an object, the <c>Agent</c> performs a get-operation to
- retrieve the value.
- </p>
- <p><c>Varbinds</c> is a list of <c>Varbind</c>, where each
- <c>Varbind</c> is one of:
- </p>
- <list type="bulleted">
- <item><c>{Variable, Value}</c>, where <c>Variable</c> is the
- symbolic name of a scalar variable referred to in the trap
- specification.
- </item>
- <item><c>{Column, RowIndex, Value}</c>, where <c>Column</c>
- is the symbolic name of a column variable.
- <c>RowIndex</c> is a list of indices for the specified
- element. If this is the case, the OBJECT IDENTIFIER sent
- in the trap is the <c>RowIndex</c> appended to the OBJECT
- IDENTIFIER for the table column. This is the OBJECT
- IDENTIFIER which specifies the element.
- </item>
- <item><c>{OID, Value}</c>, where <c>OID</c> is the OBJECT
- IDENTIFIER for an instance of an object, scalar variable,
- or column variable.
- </item>
- </list>
- <p>For example, to specify that <c>sysLocation</c> should have the
- value <c>"upstairs"</c> in the trap, we could use one of:
- </p>
- <list type="bulleted">
- <item><c>{sysLocation, "upstairs"}</c> or</item>
- <item><c>{[1,3,6,1,2,1,1,6,0], "upstairs"}</c> or</item>
- <item><c>{?sysLocation_instance, "upstairs"}</c> (provided
- that the generated <c>.hrl</c> file is included)</item>
- </list>
- <p>If a variable in the trap is a table element, the
- <c>RowIndex</c> for the element must be given in the
- <c>Varbinds</c> list. In this case, the OBJECT IDENTIFIER sent
- in the trap is the OBJECT IDENTIFIER that identifies this
- element. This OBJECT IDENTIFIER could be used in a get
- operation later.
- </p>
- <p>This function is asynchronous, and does not return any
- information. If an error occurs, <c>snmp_error:user_err/2</c>
- is called and the trap is discarded. </p>
-
- <marker id="discovery"></marker>
- </desc>
- </func>
--->
<func>
<name>discovery(TargetName, Notification) -> {ok, ManagerEngineID} | {error, Reason}</name>
diff --git a/lib/snmp/doc/src/snmpa_conf.xml b/lib/snmp/doc/src/snmpa_conf.xml
index d873574c6e..a533c179ee 100644
--- a/lib/snmp/doc/src/snmpa_conf.xml
+++ b/lib/snmp/doc/src/snmpa_conf.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
<header>
<copyright>
- <year>2006</year><year>2010</year>
+ <year>2006</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -38,8 +38,21 @@
used for manipulating (write/append/read) the config files of the
SNMP agent. </p>
- <marker id="agent_entry"></marker>
+ <marker id="types"></marker>
</description>
+
+ <section>
+ <title>DATA TYPES</title>
+ <code type="none"><![CDATA[
+transportDomain() = transportDomainUdpIpv4 | transportDomainUdpIpv6
+transportAddressIPv4() = [integer()], length 4
+transportAddressIPv6() = [integer()], length 8
+transportAddressMask() = [integer()], length 0 (default), 6 (IPv4) or 10 (IPv6)
+ ]]></code>
+
+ <marker id="agent_entry"></marker>
+ </section>
+
<funcs>
<func>
<name>agent_entry(Tag, Val) -> agent_entry()</name>
@@ -381,17 +394,19 @@
<name>target_addr_entry(Name, Ip, TagList, ParamsName, EngineId, TMask) -> target_addr_entry()</name>
<name>target_addr_entry(Name, Ip, Udp, TagList, ParamsName, EngineId, TMask, MaxMessageSize) -> target_addr_entry()</name>
<name>target_addr_entry(Name, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize) -> target_addr_entry()</name>
+ <name>target_addr_entry(Name, Domain, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize) -> target_addr_entry()</name>
<fsummary>Create an target_addr entry</fsummary>
<type>
<v>Name = string()</v>
- <v>Ip = string()</v>
+ <v>Domain = transportDomain()</v>
+ <v>Ip = transportAddressIPv4() | transportAddressIPv6() (depends on Domain)</v>
<v>Udp = integer()</v>
<v>Timeout = integer()</v>
<v>RetryCount = integer()</v>
<v>TagList = string()</v>
<v>ParamsName = string()</v>
<v>EngineId = string()</v>
- <v>TMask = string()</v>
+ <v>TMask = transportAddressMask() (depends on Domain)</v>
<v>MaxMessageSize = integer()</v>
<v>target_addr_entry() = term()</v>
</type>
diff --git a/lib/snmp/doc/src/snmpc.xml b/lib/snmp/doc/src/snmpc.xml
index 771629492d..61d19251c5 100644
--- a/lib/snmp/doc/src/snmpc.xml
+++ b/lib/snmp/doc/src/snmpc.xml
@@ -48,7 +48,11 @@
<type>
<v>File = string()</v>
<v>Options = [opt()]</v>
- <v>opt() = db() | relaxed_row_name_assign_check() | deprecated() | description() | reference() | group_check() | i() | il() | imports() | module() | module_identity() | module_compliance() | agent_capabilities() | outdir() | no_defs() | verbosity() | warnings()</v>
+ <v>opt() = db() | relaxed_row_name_assign_check() | deprecated() |
+ description() | reference() | group_check() | i() | il() |
+ imports() | module() | module_identity() | module_compliance() |
+ agent_capabilities() | outdir() | no_defs() | verbosity() |
+ warnings() | warnings_as_errors()</v>
<v>db() = {db, volatile|persistent|mnesia}</v>
<v>deprecated() = {deprecated, bool()}</v>
<v>relaxed_row_name_assign_check() = relaxed_row_name_assign_check</v>
@@ -66,6 +70,7 @@
<v>outdir() = {outdir, dir()}</v>
<v>verbosity() = {verbosity, silence|warning|info|log|debug|trace}</v>
<v>warnings() = {warnings, bool()}</v>
+ <v>warnings_as_errors() = warnings_as_errors</v>
<v>dir() = string()</v>
<v>BinFileName = string()</v>
</type>
@@ -200,11 +205,17 @@
<item>
<p>The option <c>warnings</c> specifies whether warning
- messages should be shown. </p>
+ messages should be shown. </p>
<p>Default is <c>true</c>. </p>
</item>
+ <item>
+ <p>The option <c>warnings_as_errors</c>, if present, specifies
+ whether warnings should be treated as errors.</p>
+ </item>
+
</list>
+
<p>The MIB compiler understands both SMIv1 and SMIv2 MIBs. It
uses the <c>MODULE-IDENTITY</c> statement to determine if the MIB is
version 1 or 2.
diff --git a/lib/snmp/doc/src/snmpc_cmd.xml b/lib/snmp/doc/src/snmpc_cmd.xml
index 9358382a10..971f8a3cff 100644
--- a/lib/snmp/doc/src/snmpc_cmd.xml
+++ b/lib/snmp/doc/src/snmpc_cmd.xml
@@ -50,6 +50,8 @@
with definitions of Erlang constants for the objects in
the MIB, see
<seealso marker="snmpc#mib_to_hrl">mib_to_hrl/1</seealso>. </p>
+
+ <marker id="options"></marker>
</desc>
</func>
</funcs>
@@ -58,15 +60,18 @@
<title>Compiler options</title>
<p>The following options are supported (note that most of these relate
to the compilation of the MIB file):</p>
+ <marker id="option_help"></marker>
<taglist>
<tag>--help</tag>
<item>
<p>Prints help info.</p>
+ <marker id="option_version"></marker>
</item>
<tag>--version</tag>
<item>
<p>Prints application and mib format version.</p>
+ <marker id="option_verbosity"></marker>
</item>
<tag>--verbosity <em>verbosity</em></tag>
@@ -74,11 +79,22 @@
<p>Print debug info. </p>
<p><c>verbosity</c> = <c>trace</c> | <c>debug</c> | <c>log</c> | <c>info</c> | <c>silence</c></p>
<p>Defaults to <c>silence</c>.</p>
+ <marker id="option_w"></marker>
+ <marker id="option_warnings"></marker>
</item>
- <tag>--warnings</tag>
+ <tag>--warnings | --W</tag>
<item>
<p>Print warning messages. </p>
+ <marker id="option_wae"></marker>
+ <marker id="option_werror"></marker>
+ </item>
+
+ <tag>--wae | --Werror</tag>
+ <item>
+ <p>Warnings as errors.
+ Indicates that warnings shall be treated as errors. </p>
+ <marker id="option_odir"></marker>
</item>
<tag>--o <em>directory</em></tag>
@@ -86,6 +102,7 @@
<p>The directory where the compiler should place the output files.
If not specified, output files will be placed in the current working
directory.</p>
+ <marker id="option_idir"></marker>
</item>
<tag>--i <em>Directory</em></tag>
@@ -94,6 +111,7 @@
By default, the current working directory is always included. </p>
<p>This option can be present several times, each time specifying
<em>one</em> path. </p>
+ <marker id="option_ildir"></marker>
</item>
<tag>--il <em>Directory</em></tag>
@@ -106,6 +124,7 @@
the current version may be in the system). The current directory
and the "snmp-home"/priv/mibs/ are always listed last in the
include path. </p>
+ <marker id="option_sgc"></marker>
</item>
<tag>--sgc</tag>
@@ -114,42 +133,50 @@
group check of the mib compiler.
That is, should the OBJECT-GROUP and the NOTIFICATION-GROUP
macro(s) be checked for correctness or not. </p>
+ <marker id="option_dep"></marker>
</item>
<tag>--dep</tag>
<item>
<p>Keep deprecated definition(s).
If not specified the compiler will ignore deprecated definitions. </p>
+ <marker id="option_desc"></marker>
</item>
<tag>--desc</tag>
<item>
<p>The DESCRIPTION field will be included. </p>
+ <marker id="option_ref"></marker>
</item>
<tag>--ref</tag>
<item>
<p>The REFERENCE field will be included. </p>
+ <marker id="option_imp"></marker>
</item>
<tag>--imp</tag>
<item>
<p>The IMPORTS field will be included. </p>
+ <marker id="option_mi"></marker>
</item>
<tag>--mi</tag>
<item>
<p>The MODULE-IDENTITY field will be included. </p>
+ <marker id="option_mc"></marker>
</item>
<tag>--mc</tag>
<item>
<p>The MODULE-COMPLIANCE field will be included. </p>
+ <marker id="option_ac"></marker>
</item>
<tag>--ac</tag>
<item>
<p>The AGENT-CAPABILITIES field will be included. </p>
+ <marker id="option_mod"></marker>
</item>
<tag>--mod <em>module</em></tag>
@@ -157,6 +184,7 @@
<p>The module which implements all the instrumentation functions. </p>
<p>The name of all instrumentation functions must be the
same as the corresponding managed object it implements. </p>
+ <marker id="option_nd"></marker>
</item>
<tag>--nd</tag>
@@ -165,6 +193,7 @@
used if a managed object have no instrumentation function.
Instead this will be reported as an error, and the compilation
aborts. </p>
+ <marker id="option_rrnac"></marker>
</item>
<tag>--rrnac</tag>
@@ -176,6 +205,7 @@
This means that the error will be converted to a warning. </p>
<p>By default it is not included, but if this option is present
it will be. </p>
+ <marker id="see_also"></marker>
</item>
</taglist>
@@ -183,7 +213,7 @@
<section>
<title>SEE ALSO</title>
- <p><seealso marker="erlc">erlc(1)</seealso>,
+ <p><seealso marker="erts:erlc">erlc(1)</seealso>,
<seealso marker="compiler:compile">compile(3)</seealso>,
<seealso marker="snmp:snmpc">snmpc(3)</seealso></p>
</section>
diff --git a/lib/snmp/doc/src/snmpm.xml b/lib/snmp/doc/src/snmpm.xml
index 1ee391d9ba..c36a1b2a24 100644
--- a/lib/snmp/doc/src/snmpm.xml
+++ b/lib/snmp/doc/src/snmpm.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -63,6 +63,10 @@ value_type() = o ('OBJECT IDENTIFIER') |
c64 ('Counter64') |
tt ('TimeTicks')
value() = term()
+community() = string()
+sec_model() = any | v1 | v2c | usm
+sec_name() = string()
+sec_level() = noAuthNoPriv | authNoPriv | authPriv
]]></code>
<marker id="monitor"></marker>
@@ -279,27 +283,27 @@ sec_level = noAuthNoPriv | authNoPriv | authPriv
<v>TargetName = target_name()</v>
<v>Config = [agent_config()]</v>
<v>agent_config() = {Item, Val}</v>
- <v>Item = engine_id | address | port | community | timeout | max_message_size | version | sec_model | sec_name | sec_level</v>
+ <v>Item = engine_id | address | port | community | timeout | max_message_size | version | sec_model | sec_name | sec_level | tdomain</v>
<v>Val = term()</v>
<v>Reason = term()</v>
</type>
<desc>
<p>Explicitly instruct the manager to handle this agent, with
- <c>UserId</c> as the responsible user. </p>
- <p>Called to instruct the manager that this agent
- shall be handled. This function is used when
- the user knows in advance which agents the
- manager shall handle.
- Note that there is an alternate way to do the same thing:
- Add the agent to the manager config files (see
- <seealso marker="snmp_manager_config_files#agents">agents.conf</seealso>).</p>
+ <c>UserId</c> as the responsible user. </p>
+ <p>Called to instruct the manager that this agent shall be handled.
+ This function is used when the user knows in advance which agents
+ the manager shall handle.
+ Note that there is an alternate way to do the same thing:
+ Add the agent to the manager config files (see
+ <seealso marker="snmp_manager_config_files#agents">agents.conf</seealso>).</p>
<p><c>TargetName</c> is a non-empty string,
- uniquely identifying the agent. </p>
- <p>The type of <c>Val</c> depends on <c>Item</c>: </p>
+ uniquely identifying the agent. </p>
+ <p>The type of <c>Val</c> depends on <c>Item</c>: </p>
<code type="none"><![CDATA[
[mandatory] engine_id = string()
[mandatory] address = ip_address()
[optional] port = integer()
+[optional] tdomain = transportDomainUdpIpv4 | transportDomainUdpIpv6
[optional] community = string()
[optional] timeout = integer() | snmp_timer()
[optional] max_message_size = integer()
@@ -308,7 +312,9 @@ sec_level = noAuthNoPriv | authNoPriv | authPriv
[optional] sec_name = string()
[optional] sec_level = noAuthNoPriv | authNoPriv | authPriv
]]></code>
- <p>Note that if no <c>Port</c> is given, the default value is used.</p>
+ <p>Note that if no <c>tdomain</c> is given, the default value,
+ <c>transportDomainUdpIpv4</c>, is used.</p>
+ <p>Note that if no <c>port</c> is given, the default value is used.</p>
<marker id="unregister_agent"></marker>
</desc>
@@ -344,17 +350,25 @@ sec_level = noAuthNoPriv | authNoPriv | authPriv
</func>
<func>
+ <name>update_agent_info(UserId, TargetName, Info) -> ok | {error, Reason}</name>
<name>update_agent_info(UserId, TargetName, Item, Val) -> ok | {error, Reason}</name>
<fsummary>Update agent config</fsummary>
<type>
<v>UserId = term()</v>
<v>TargetName = target_name()</v>
- <v>Item = atom()</v>
- <v>Val = term()</v>
+ <v>Info = [{item(), item_value()}]</v>
+ <v>Item = item()</v>
+ <v>item() = atom()</v>
+ <v>Val = item_value()</v>
+ <v>item_value() = term()</v>
<v>Reason = term()</v>
</type>
<desc>
- <p>Update agent config.</p>
+ <p>Update agent config. The function <c>update_agent_info/3</c>
+ should be used when several values needs to be updated atomically. </p>
+ <p>See function
+ <seealso marker="#register_agent">register_agent</seealso>)
+ for more info about what kind of items are allowed. </p>
<marker id="which_agents"></marker>
</desc>
@@ -482,11 +496,65 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<p>Get a list of all registered usm users with engine-id
<c>EngineID</c>.</p>
- <marker id="sync_get"></marker>
+ <marker id="sync_get2"></marker>
</desc>
</func>
<func>
+ <name>sync_get2(UserId, TargetName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name>sync_get2(UserId, TargetName, Oids, SendOpts) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <fsummary>Synchronous <c>get-request</c></fsummary>
+ <type>
+ <v>UserId = term()</v>
+ <v>TargetName = target_name()</v>
+ <v>Oids = [oid()]</v>
+ <v>SendOpts = send_opts()</v>
+ <v>send_opts() = [send_opt()]</v>
+ <v>send_opt() = {context, string()} | {timeout, pos_integer()} | {extra, term()} | {community, community()} | {sec_model, sec_model()} | {sec_name, string()} | {sec_level, sec_level()} | {max_message_size, pos_integer()}</v>
+ <v>SnmpReply = snmp_reply()</v>
+ <v>Remaining = integer()</v>
+ <v>Reason = {send_failed, ReqId, ActualReason} | {invalid_sec_info, SecInfo, SnmpInfo} | term()</v>
+ <v>ReqId = term()</v>
+ <v>ActualReason = term()</v>
+ <v>SecInfo = [sec_info()]</v>
+ <v>sec_info() = {sec_tag(), ExpectedValue, ReceivedValue}</v>
+ <v>sec_tag() = atom()</v>
+ <v>ExpectedValue = ReceivedValue = term()</v>
+ <v>SnmpInfo = term()</v>
+ </type>
+ <desc>
+ <p>Synchronous <c>get-request</c>. </p>
+
+ <p><c>Remaining</c> is the remaining time of the given (or default)
+ timeout time.</p>
+
+ <p>When <em>Reason</em> is <em>{send_failed, ...}</em> it means that
+ the net_if process failed to send the message. This could happen
+ because of any number of reasons, i.e. encoding error.
+ <em>ActualReason</em> is the actual reason in this case. </p>
+
+ <p>The send option <c>extra</c> specifies an opaque data structure
+ passed on to the net-if process. The net-if process included in this
+ application makes, with one exception, no use of this info,
+ so the only use for it in such a option (when using the built in
+ net-if) would be tracing. The one usage exception is:
+ <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
+ element is reserved for internal use. </p>
+
+ <p>Some of the send options (<c>community</c>, <c>sec_model</c>,
+ <c>sec_name</c>, <c>sec_level</c> and <c>max_message_size</c>)
+ are <c>override options</c>. That is,
+ for <em>this</em> request, they override any configuration done
+ when the agent was registered. </p>
+
+ <p>For <c>SnmpInfo</c>, see the user callback function
+ <seealso marker="snmpm_user#handle_report">handle_report</seealso>.</p>
+
+ <marker id="sync_get"></marker>
+ </desc>
+ </func>
+
+ <func>
<name>sync_get(UserId, TargetName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
<name>sync_get(UserId, TargetName, ContextName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
<name>sync_get(UserId, TargetName, Oids, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
@@ -513,19 +581,63 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<desc>
<p>Synchronous <c>get-request</c>. </p>
<p><c>Remaining</c> is the remaining time of the given or
- default timeout time.</p>
+ default timeout time.</p>
<p>When <em>Reason</em> is <em>{send_failed, ...}</em> it means that
- the net_if process failed to send the message. This could happen
- because of any number of reasons, i.e. encoding error. <em>R</em>
- is the actual reason in this case. </p>
- <p><c>ExtraInfo</c> is an opaque data structure passed on to
- the net-if process. The net-if process included in this
- application makes no use of this info, so the only use for it
- in such a configuration (when using the built in net-if) would
- be tracing.</p>
+ the net_if process failed to send the message. This could happen
+ because of any number of reasons, i.e. encoding error. <em>R</em>
+ is the actual reason in this case. </p>
+ <p><c>ExtraInfo</c> is an opaque data structure passed on to
+ the net-if process. The net-if process included in this
+ application makes, with one exception, no use of this info,
+ so the only use for it in such a configuration (when using the
+ built in net-if) would be tracing. The one usage exception is:
+ <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
+ element is reserved for internal use. </p>
<p>For <c>SnmpInfo</c>, see the user callback function
<seealso marker="snmpm_user#handle_report">handle_report</seealso>.</p>
+ <marker id="async_get2"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>async_get2(UserId, TargetName, Oids) -> {ok, ReqId} | {error, Reason}</name>
+ <name>async_get2(UserId, TargetName, Oids, SendOpts) -> {ok, ReqId} | {error, Reason}</name>
+ <fsummary>Asynchronous <c>get-request</c></fsummary>
+ <type>
+ <v>UserId = term()</v>
+ <v>TargetName = target_name()</v>
+ <v>Oids = [oid()]</v>
+ <v>SendOpts = send_opts()</v>
+ <v>send_opts() = [send_opt()]</v>
+ <v>send_opt() = {context, string()} | {timeout, pos_integer()} | {extra, term()} | {community, community()} | {sec_model, sec_model()} | {sec_name, string()} | {sec_level, sec_level()} | {max_message_size, pos_integer()}</v>
+ <v>ReqId = term()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Asynchronous <c>get-request</c>.</p>
+
+ <p>The reply, if it arrives, will be delivered to the user
+ through a call to the snmpm_user callback function
+ <c>handle_pdu</c>.</p>
+
+ <p>The send option <c>timeout</c> specifies for how long the request is
+ valid (after which the manager is free to delete it).</p>
+
+ <p>The send option <c>extra</c> specifies an opaque data structure
+ passed on to the net-if process. The net-if process included in this
+ application makes, with one exception, no use of this info,
+ so the only use for it in such a option (when using the built in
+ net-if) would be tracing. The one usage exception is:
+ <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
+ element is reserved for internal use. </p>
+
+ <p>Some of the send options (<c>community</c>, <c>sec_model</c>,
+ <c>sec_name</c>, <c>sec_level</c> and <c>max_message_size</c>)
+ are <c>override options</c>. That is,
+ for <em>this</em> request, they override any configuration done
+ when the agent was registered. </p>
+
<marker id="async_get"></marker>
</desc>
</func>
@@ -550,17 +662,73 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<desc>
<p>Asynchronous <c>get-request</c>.</p>
<p>The reply, if it arrives, will be delivered to the user
- through a call to the snmpm_user callback function
- <c>handle_pdu</c>.</p>
- <p>The <c>Expire</c> time indicates for how long the request is
- valid (after which the manager is free to delete it).</p>
- <p><c>ExtraInfo</c> is an opaque data structure passed on to
- the net-if process. The net-if process included in this
- application makes no use of this info, so the only use for it
- in such a configuration (when using the built in net-if) would
- be tracing.</p>
-
- <marker id="sync_get_next"></marker>
+ through a call to the snmpm_user callback function
+ <c>handle_pdu</c>.</p>
+ <p>The <c>Expire</c> time indicates for how long the request is
+ valid (after which the manager is free to delete it).</p>
+ <p><c>ExtraInfo</c> is an opaque data structure passed on to
+ the net-if process. The net-if process included in this
+ application makes, with one exception, no use of this info,
+ so the only use for it in such a configuration (when using the
+ built in net-if) would be tracing. The one usage exception is:
+ <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
+ element is reserved for internal use. </p>
+
+ <marker id="sync_get_next2"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>sync_get_next2(UserId, TargetName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name>sync_get_next2(UserId, TargetName, Oids, SendOpts) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <fsummary>Synchronous <c>get-next-request</c></fsummary>
+ <type>
+ <v>UserId = term()</v>
+ <v>TargetName = target_name()</v>
+ <v>Oids = [oid()]</v>
+ <v>SendOpts = send_opts()</v>
+ <v>send_opts() = [send_opt()]</v>
+ <v>send_opt() = {context, string()} | {timeout, pos_integer()} | {extra, term()} | {community, community()} | {sec_model, sec_model()} | {sec_name, string()} | {sec_level, sec_level()} | {max_message_size, pos_integer()}</v>
+ <v>SnmpReply = snmp_reply()</v>
+ <v>Remaining = integer()</v>
+ <v>Reason = {send_failed, ReqId, ActualReason} | {invalid_sec_info, SecInfo, SnmpInfo} | term()</v>
+ <v>ReqId = term()</v>
+ <v>ActualReason = term()</v>
+ <v>SecInfo = [sec_info()]</v>
+ <v>sec_info() = {sec_tag(), ExpectedValue, ReceivedValue}</v>
+ <v>sec_tag() = atom()</v>
+ <v>ExpectedValue = ReceivedValue = term()</v>
+ <v>SnmpInfo = term()</v>
+ </type>
+ <desc>
+ <p>Synchronous <c>get-next-request</c>. </p>
+
+ <p><c>Remaining</c> is the remaining time of the given (or default)
+ timeout time.</p>
+
+ <p>When <em>Reason</em> is <em>{send_failed, ...}</em> it means that
+ the net_if process failed to send the message. This could happen
+ because of any number of reasons, i.e. encoding error.
+ <em>ActualReason</em> is the actual reason in this case. </p>
+
+ <p>The send option <c>extra</c> specifies an opaque data structure
+ passed on to the net-if process. The net-if process included in this
+ application makes, with one exception, no use of this info,
+ so the only use for it in such a option (when using the built in
+ net-if) would be tracing. The one usage exception is:
+ <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
+ element is reserved for internal use. </p>
+
+ <p>Some of the send options (<c>community</c>, <c>sec_model</c>,
+ <c>sec_name</c>, <c>sec_level</c> and <c>max_message_size</c>)
+ are <c>override options</c>. That is,
+ for <em>this</em> request, they override any configuration done
+ when the agent was registered. </p>
+
+ <p>For <c>SnmpInfo</c>, see the user callback function
+ <seealso marker="snmpm_user#handle_report">handle_report</seealso>.</p>
+
+ <marker id="sync_get_next"></marker>
</desc>
</func>
@@ -587,16 +755,57 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<p>Synchronous <c>get-next-request</c>. </p>
<p><c>Remaining</c> time of the given or default timeout time.</p>
<p>When <em>Reason</em> is <em>{send_failed, ...}</em> it means that
- the net_if process failed to send the message. This could happen
- because of any number of reasons, i.e. encoding error. <em>R</em>
- is the actual reason in this case. </p>
- <p><c>ExtraInfo</c> is an opaque data structure passed on to
- the net-if process. The net-if process included in this
- application makes no use of this info, so the only use for it
- in such a configuration (when using the built in net-if) would
- be tracing.</p>
-
- <marker id="async_get_next"></marker>
+ the net_if process failed to send the message. This could happen
+ because of any number of reasons, i.e. encoding error. <em>R</em>
+ is the actual reason in this case. </p>
+ <p><c>ExtraInfo</c> is an opaque data structure passed on to
+ the net-if process. The net-if process included in this
+ application makes, with one exception, no use of this info,
+ so the only use for it in such a configuration (when using the
+ built in net-if) would be tracing. The one usage exception is:
+ <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
+ element is reserved for internal use. </p>
+
+ <marker id="async_get_next2"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>async_get_next2(UserId, TargetName, Oids) -> {ok, ReqId} | {error, Reason}</name>
+ <name>async_get_next2(UserId, TargetName, Oids, SendOpts) -> {ok, ReqId} | {error, Reason}</name>
+ <fsummary>Asynchronous <c>get-next-request</c></fsummary>
+ <type>
+ <v>UserId = term()</v>
+ <v>TargetName = target_name()</v>
+ <v>Oids = [oid()]</v>
+ <v>send_opt() = {context, string()} | {timeout, pos_integer()} | {extra, term()} | {community, community()} | {sec_model, sec_model()} | {sec_name, string()} | {sec_level, sec_level()} | {max_message_size, pos_integer()}</v>
+ <v>ReqId = integer()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Asynchronous <c>get-next-request</c>. </p>
+
+ <p>The reply will be delivered to the user through a call
+ to the snmpm_user callback function <c>handle_pdu</c>.</p>
+
+ <p>The send option <c>timeout</c> specifies for how long the request is
+ valid (after which the manager is free to delete it).</p>
+
+ <p>The send option <c>extra</c> specifies an opaque data structure
+ passed on to the net-if process. The net-if process included in this
+ application makes, with one exception, no use of this info,
+ so the only use for it in such a option (when using the built in
+ net-if) would be tracing. The one usage exception is:
+ <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
+ element is reserved for internal use. </p>
+
+ <p>Some of the send options (<c>community</c>, <c>sec_model</c>,
+ <c>sec_name</c>, <c>sec_level</c> and <c>max_message_size</c>)
+ are <c>override options</c>. That is,
+ for <em>this</em> request, they override any configuration done
+ when the agent was registered. </p>
+
+ <marker id="async_get_next"></marker>
</desc>
</func>
@@ -620,11 +829,75 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<desc>
<p>Asynchronous <c>get-next-request</c>. </p>
<p>The reply will be delivered to the user through a call
- to the snmpm_user callback function <c>handle_pdu</c>.</p>
+ to the snmpm_user callback function <c>handle_pdu</c>.</p>
<p>The <c>Expire</c> time indicates for how long the request is
- valid (after which the manager is free to delete it).</p>
+ valid (after which the manager is free to delete it).</p>
+ <p><c>ExtraInfo</c> is an opaque data structure passed on to
+ the net-if process. The net-if process included in this
+ application makes, with one exception, no use of this info,
+ so the only use for it in such a configuration (when using the
+ built in net-if) would be tracing. The one usage exception is:
+ <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
+ element is reserved for internal use. </p>
+
+ <marker id="sync_set2"></marker>
+ </desc>
+ </func>
- <marker id="sync_set"></marker>
+ <func>
+ <name>sync_set2(UserId, TargetName, VarsAndVals) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name>sync_set2(UserId, TargetName, VarsAndVals, SendOpts) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <fsummary>Synchronous <c>set-request</c></fsummary>
+ <type>
+ <v>UserId = term()</v>
+ <v>TargetName = target_name()</v>
+ <v>VarsAndVals = vars_and_vals()</v>
+ <v>SendOpts = send_opts()</v>
+ <v>send_opts() = [send_opt()]</v>
+ <v>send_opt() = {context, string()} | {timeout, pos_integer()} | {extra, term()} | {community, community()} | {sec_model, sec_model()} | {sec_name, string()} | {sec_level, sec_level()} | {max_message_size, pos_integer()}</v>
+ <v>SnmpReply = snmp_reply()</v>
+ <v>Remaining = integer()</v>
+ <v>Reason = {send_failed, ReqId, ActualReason} | {invalid_sec_info, SecInfo, SnmpInfo} | term()</v>
+ <v>ReqId = term()</v>
+ <v>ActualReason = term()</v>
+ <v>SecInfo = [sec_info()]</v>
+ <v>sec_info() = {sec_tag(), ExpectedValue, ReceivedValue}</v>
+ <v>sec_tag() = atom()</v>
+ <v>ExpectedValue = ReceivedValue = term()</v>
+ <v>SnmpInfo = term()</v>
+ </type>
+ <desc>
+ <p>Synchronous <c>set-request</c>. </p>
+
+ <p><c>Remaining</c> is the remaining time of the given (or default)
+ timeout time.</p>
+
+ <p>When <em>Reason</em> is <em>{send_failed, ...}</em> it means that
+ the net_if process failed to send the message. This could happen
+ because of any number of reasons, i.e. encoding error.
+ <em>ActualReason</em> is the actual reason in this case. </p>
+
+ <p>When <em>var_and_val()</em> is <em>{oid(), value()}</em>, the
+ manager makes an educated guess based on the loaded mibs. </p>
+
+ <p>The send option <c>extra</c> specifies an opaque data structure
+ passed on to the net-if process. The net-if process included in this
+ application makes, with one exception, no use of this info,
+ so the only use for it in such a option (when using the built in
+ net-if) would be tracing. The one usage exception is:
+ <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
+ element is reserved for internal use. </p>
+
+ <p>Some of the send options (<c>community</c>, <c>sec_model</c>,
+ <c>sec_name</c>, <c>sec_level</c> and <c>max_message_size</c>)
+ are <c>override options</c>. That is,
+ for <em>this</em> request, they override any configuration done
+ when the agent was registered. </p>
+
+ <p>For <c>SnmpInfo</c>, see the user callback function
+ <seealso marker="snmpm_user#handle_report">handle_report</seealso>.</p>
+
+ <marker id="sync_set"></marker>
</desc>
</func>
@@ -651,18 +924,64 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<p>Synchronous <c>set-request</c>. </p>
<p><c>Remaining</c> time of the given or default timeout time.</p>
<p>When <em>Reason</em> is <em>{send_failed, ...}</em> it means that
- the net_if process failed to send the message. This could happen
- because of any number of reasons, i.e. encoding error. <em>R</em>
- is the actual reason in this case. </p>
- <p>When <em>var_and_val()</em> is <em>{oid(), value()}</em>, the
- manager makes an educated guess based on the loaded mibs. </p>
- <p><c>ExtraInfo</c> is an opaque data structure passed on to
- the net-if process. The net-if process included in this
- application makes no use of this info, so the only use for it
- in such a configuration (when using the built in net-if) would
- be tracing.</p>
-
- <marker id="async_set"></marker>
+ the net_if process failed to send the message. This could happen
+ because of any number of reasons, i.e. encoding error. <em>R</em>
+ is the actual reason in this case. </p>
+ <p>When <em>var_and_val()</em> is <em>{oid(), value()}</em>, the
+ manager makes an educated guess based on the loaded mibs. </p>
+ <p><c>ExtraInfo</c> is an opaque data structure passed on to
+ the net-if process. The net-if process included in this
+ application makes, with one exception, no use of this info,
+ so the only use for it in such a configuration (when using the
+ built in net-if) would be tracing. The one usage exception is:
+ <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
+ element is reserved for internal use. </p>
+
+ <marker id="async_set2"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>async_set2(UserId, TargetName, VarsAndVals) -> {ok, ReqId} | {error, Reason}</name>
+ <name>async_set2(UserId, TargetName, VarsAndVals, SendOpts) -> {ok, ReqId} | {error, Reason}</name>
+ <fsummary>Asynchronous <c>set-request</c></fsummary>
+ <type>
+ <v>UserId = term()</v>
+ <v>TargetName = target_name()</v>
+ <v>VarsAndVals = vars_and_vals()</v>
+ <v>SendOpts = send_opts()</v>
+ <v>send_opts() = [send_opt()]</v>
+ <v>send_opt() = {context, string()} | {timeout, pos_integer()} | {extra, term()} | {community, community()} | {sec_model, sec_model()} | {sec_name, string()} | {sec_level, sec_level()} | {max_message_size, pos_integer()}</v>
+ <v>ReqId = term()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Asynchronous <c>set-request</c>. </p>
+
+ <p>The reply will be delivered to the user through a call
+ to the snmpm_user callback function <c>handle_pdu</c>.</p>
+
+ <p>The send option <c>timeout</c> specifies for how long the request is
+ valid (after which the manager is free to delete it).</p>
+
+ <p>When <em>var_and_val()</em> is <em>{oid(), value()}</em>, the
+ manager makes an educated guess based on the loaded mibs. </p>
+
+ <p>The send option <c>extra</c> specifies an opaque data structure
+ passed on to the net-if process. The net-if process included in this
+ application makes, with one exception, no use of this info,
+ so the only use for it in such a option (when using the built in
+ net-if) would be tracing. The one usage exception is:
+ <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
+ element is reserved for internal use. </p>
+
+ <p>Some of the send options (<c>community</c>, <c>sec_model</c>,
+ <c>sec_name</c>, <c>sec_level</c> and <c>max_message_size</c>)
+ are <c>override options</c>. That is,
+ for <em>this</em> request, they override any configuration done
+ when the agent was registered. </p>
+
+ <marker id="async_set"></marker>
</desc>
</func>
@@ -685,18 +1004,76 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<desc>
<p>Asynchronous <c>set-request</c>. </p>
<p>The reply will be delivered to the user through a call
- to the snmpm_user callback function <c>handle_pdu</c>.</p>
+ to the snmpm_user callback function <c>handle_pdu</c>.</p>
<p>The <c>Expire</c> time indicates for how long the request is
- valid (after which the manager is free to delete it).</p>
- <p>When <em>var_and_val()</em> is <em>{oid(), value()}</em>, the
- manager makes an educated guess based on the loaded mibs. </p>
- <p><c>ExtraInfo</c> is an opaque data structure passed on to
- the net-if process. The net-if process included in this
- application makes no use of this info, so the only use for it
- in such a configuration (when using the built in net-if) would
- be tracing.</p>
-
- <marker id="sync_get_bulk"></marker>
+ valid (after which the manager is free to delete it).</p>
+ <p>When <em>var_and_val()</em> is <em>{oid(), value()}</em>, the
+ manager makes an educated guess based on the loaded mibs. </p>
+ <p><c>ExtraInfo</c> is an opaque data structure passed on to
+ the net-if process. The net-if process included in this
+ application makes, with one exception, no use of this info,
+ so the only use for it in such a configuration (when using the
+ built in net-if) would be tracing. The one usage exception is:
+ <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
+ element is reserved for internal use. </p>
+
+ <marker id="sync_get_bulk2"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>sync_get_bulk2(UserId, TragetName, NonRep, MaxRep, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <name>sync_get_bulk2(UserId, TragetName, NonRep, MaxRep, Oids, SendOpts) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
+ <fsummary>Synchronous <c>get-bulk-request</c></fsummary>
+ <type>
+ <v>UserId = term()</v>
+ <v>TargetName = target_name()</v>
+ <v>NonRep = integer()</v>
+ <v>MaxRep = integer()</v>
+ <v>Oids = [oid()]</v>
+ <v>SendOpts = send_opts()</v>
+ <v>send_opts() = [send_opt()]</v>
+ <v>send_opt() = {context, string()} | {timeout, pos_integer()} | {extra, term()} | {community, community()} | {sec_model, sec_model()} | {sec_name, string()} | {sec_level, sec_level()} | {max_message_size, pos_integer()}</v>
+ <v>SnmpReply = snmp_reply()</v>
+ <v>Remaining = integer()</v>
+ <v>Reason = {send_failed, ReqId, ActualReason} | {invalid_sec_info, SecInfo, SnmpInfo} | term()</v>
+ <v>ReqId = term()</v>
+ <v>ActualReason = term()</v>
+ <v>SecInfo = [sec_info()]</v>
+ <v>sec_info() = {sec_tag(), ExpectedValue, ReceivedValue}</v>
+ <v>sec_tag() = atom()</v>
+ <v>ExpectedValue = ReceivedValue = term()</v>
+ <v>SnmpInfo = term()</v>
+ </type>
+ <desc>
+ <p>Synchronous <c>get-bulk-request</c> (See RFC1905).</p>
+
+ <p><c>Remaining</c> is the remaining time of the given (or default)
+ timeout time.</p>
+
+ <p>When <em>Reason</em> is <em>{send_failed, ...}</em> it means that
+ the net_if process failed to send the message. This could happen
+ because of any number of reasons, i.e. encoding error.
+ <em>ActualReason</em> is the actual reason in this case. </p>
+
+ <p>The send option <c>extra</c> specifies an opaque data structure
+ passed on to the net-if process. The net-if process included in this
+ application makes, with one exception, no use of this info,
+ so the only use for it in such a option (when using the built in
+ net-if) would be tracing. The one usage exception is:
+ <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
+ element is reserved for internal use. </p>
+
+ <p>Some of the send options (<c>community</c>, <c>sec_model</c>,
+ <c>sec_name</c>, <c>sec_level</c> and <c>max_message_size</c>)
+ are <c>override options</c>. That is,
+ for <em>this</em> request, they override any configuration done
+ when the agent was registered. </p>
+
+ <p>For <c>SnmpInfo</c>, see the user callback function
+ <seealso marker="snmpm_user#handle_report">handle_report</seealso>.</p>
+
+ <marker id="sync_get_bulk"></marker>
</desc>
</func>
@@ -723,17 +1100,60 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<desc>
<p>Synchronous <c>get-bulk-request</c> (See RFC1905).</p>
<p><c>Remaining</c> time of the given or default timeout time.</p>
- <p>When <em>Reason</em> is <em>{send_failed, ...}</em> it means that
- the net_if process failed to send the message. This could happen
- because of any number of reasons, i.e. encoding error. <em>R</em>
- is the actual reason in this case. </p>
- <p><c>ExtraInfo</c> is an opaque data structure passed on to
- the net-if process. The net-if process included in this
- application makes no use of this info, so the only use for it
- in such a configuration (when using the built in net-if) would
- be tracing.</p>
-
- <marker id="async_get_bulk"></marker>
+ <p>When <em>Reason</em> is <em>{send_failed, ...}</em> it means that
+ the net_if process failed to send the message. This could happen
+ because of any number of reasons, i.e. encoding error. <em>R</em>
+ is the actual reason in this case. </p>
+ <p><c>ExtraInfo</c> is an opaque data structure passed on to
+ the net-if process. The net-if process included in this
+ application makes, with one exception, no use of this info,
+ so the only use for it in such a configuration (when using the
+ built in net-if) would be tracing. The one usage exception is:
+ <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
+ element is reserved for internal use. </p>
+
+ <marker id="async_get_bulk2"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids) -> {ok, ReqId} | {error, Reason}</name>
+ <name>async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts) -> {ok, ReqId} | {error, Reason}</name>
+ <fsummary>Asynchronous <c>get-bulk-request</c></fsummary>
+ <type>
+ <v>UserId = term()</v>
+ <v>TargetName = target_name()</v>
+ <v>NonRep = integer()</v>
+ <v>MaxRep = integer()</v>
+ <v>Oids = [oid()]</v>
+ <v>SendOpts = send_opts()</v>
+ <v>send_opts() = [send_opt()]</v>
+ <v>send_opt() = {context, string()} | {timeout, pos_integer()} | {extra, term()} | {community, community()} | {sec_model, sec_model()} | {sec_name, string()} | {sec_level, sec_level()} | {max_message_size, pos_integer()}</v>
+ <v>ReqId = integer()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Asynchronous <c>get-bulk-request</c> (See RFC1905).</p>
+
+ <p>The reply will be delivered to the user through a call
+ to the snmpm_user callback function <c>handle_pdu</c>.</p>
+
+ <p>The send option <c>timeout</c> specifies for how long the request is
+ valid (after which the manager is free to delete it).</p>
+
+ <p>The send option <c>extra</c> specifies an opaque data structure
+ passed on to the net-if process. The net-if process included in this
+ application makes no use of this info, so the only use for it
+ in such a configuration (when using the built in net-if) would
+ be tracing.</p>
+
+ <p>Some of the send options (<c>community</c>, <c>sec_model</c>,
+ <c>sec_name</c>, <c>sec_level</c> and <c>max_message_size</c>)
+ are <c>override options</c>. That is,
+ for <em>this</em> request, they override any configuration done
+ when the agent was registered. </p>
+
+ <marker id="async_get_bulk"></marker>
</desc>
</func>
@@ -759,9 +1179,16 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<desc>
<p>Asynchronous <c>get-bulk-request</c> (See RFC1905).</p>
<p>The reply will be delivered to the user through a call
- to the snmpm_user callback function <c>handle_pdu</c>.</p>
+ to the snmpm_user callback function <c>handle_pdu</c>.</p>
<p>The <c>Expire</c> time indicates for how long the request is
- valid (after which the manager is free to delete it).</p>
+ valid (after which the manager is free to delete it).</p>
+ <p><c>ExtraInfo</c> is an opaque data structure passed on to
+ the net-if process. The net-if process included in this
+ application makes, with one exception, no use of this info,
+ so the only use for it in such a configuration (when using the
+ built in net-if) would be tracing. The one usage exception is:
+ <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
+ element is reserved for internal use. </p>
<marker id="cancel_async_request"></marker>
</desc>
diff --git a/lib/snmp/mibs/Makefile.in b/lib/snmp/mibs/Makefile.in
index 7aefb0ea34..993a67c6f2 100644
--- a/lib/snmp/mibs/Makefile.in
+++ b/lib/snmp/mibs/Makefile.in
@@ -41,8 +41,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/snmp-$(VSN)
# ----------------------------------------------------
# NOTE:
-# 1) Order is important; some MIBs include others
-# 2) The OTP-REG mib actually belongs to another
+# The OTP-REG mib actually belongs to another
# application (otp_mibs), and is exported by this
# app. But since that app is built later, we have
# to built it here in order to be able to build
@@ -61,7 +60,8 @@ MIBS_A = \
SNMP-USER-BASED-SM-MIB \
SNMP-VIEW-BASED-ACM-MIB \
SNMP-USM-AES-MIB \
- INET-ADDRESS-MIB
+ INET-ADDRESS-MIB \
+ TRANSPORT-ADDRESS-MIB
MIBS_B = OTP-SNMPEA-MIB
@@ -147,6 +147,35 @@ $(ERL_TOP)/lib/snmp/bin/snmp-v2tov1: $(ERL_TOP)/lib/snmp/bin/snmp-v2tov1.src
$(SNMP_BIN_TARGET_DIR)/OTP-REG.bin: $(ERL_TOP)/lib/$(OTP_MIBDIR)/mibs/OTP-REG.mib
$(ERLC) -pa $(SNMP_TOOLKIT)/ebin -I $(SNMP_TOOLKIT)/priv/mibs $(SNMP_FLAGS) -o $(SNMP_BIN_TARGET_DIR) $<
+# To support parallel make, we'll need explicit dependencies
+# to ensure that an imported MIB has been compiled when it's needed.
+
+$(SNMP_BIN_TARGET_DIR)/STANDARD-MIB.bin: \
+ $(SNMP_BIN_TARGET_DIR)/RFC1213-MIB.bin
+
+$(SNMP_BIN_TARGET_DIR)/SNMP-TARGET-MIB.bin: \
+ $(SNMP_BIN_TARGET_DIR)/SNMP-FRAMEWORK-MIB.bin
+
+$(SNMP_BIN_TARGET_DIR)/SNMP-NOTIFICATION-MIB.bin: \
+ $(SNMP_BIN_TARGET_DIR)/SNMP-FRAMEWORK-MIB.bin \
+ $(SNMP_BIN_TARGET_DIR)/SNMP-TARGET-MIB.bin
+
+$(SNMP_BIN_TARGET_DIR)/SNMP-COMMUNITY-MIB.bin: \
+ $(SNMP_BIN_TARGET_DIR)/SNMP-FRAMEWORK-MIB.bin \
+ $(SNMP_BIN_TARGET_DIR)/SNMP-TARGET-MIB.bin
+
+$(SNMP_BIN_TARGET_DIR)/SNMP-USER-BASED-SM-MIB.bin: \
+ $(SNMP_BIN_TARGET_DIR)/SNMP-FRAMEWORK-MIB.bin
+
+$(SNMP_BIN_TARGET_DIR)/SNMP-VIEW-BASED-ACM-MIB.bin: \
+ $(SNMP_BIN_TARGET_DIR)/SNMP-FRAMEWORK-MIB.bin
+
+$(SNMP_BIN_TARGET_DIR)/SNMP-USM-AES-MIB.bin: \
+ $(SNMP_BIN_TARGET_DIR)/SNMP-FRAMEWORK-MIB.bin
+
+$(SNMP_BIN_TARGET_DIR)/OTP-SNMPEA-MIB.bin: \
+ $(SNMP_BIN_TARGET_DIR)/OTP-REG.bin
+
clean:
rm -f $(TARGET_FILES)
@@ -184,7 +213,7 @@ info:
@echo "VSN = $(VSN)"
@echo "RELSYSDIR = $(RELSYSDIR)"
-v1/%.mib.v1: %.mib
+v1/%.mib.v1: %.mib $(ERL_TOP)/lib/snmp/bin/snmp-v2tov1
$(ERL_TOP)/lib/snmp/bin/snmp-v2tov1 -o $@ $<
diff --git a/lib/snmp/mibs/TRANSPORT-ADDRESS-MIB.mib b/lib/snmp/mibs/TRANSPORT-ADDRESS-MIB.mib
new file mode 100644
index 0000000000..7d450fbc2a
--- /dev/null
+++ b/lib/snmp/mibs/TRANSPORT-ADDRESS-MIB.mib
@@ -0,0 +1,417 @@
+TRANSPORT-ADDRESS-MIB DEFINITIONS ::= BEGIN
+
+IMPORTS
+ MODULE-IDENTITY, OBJECT-IDENTITY, mib-2 FROM SNMPv2-SMI
+ TEXTUAL-CONVENTION FROM SNMPv2-TC;
+
+transportAddressMIB MODULE-IDENTITY
+ LAST-UPDATED "200211010000Z"
+ ORGANIZATION
+ "IETF Operations and Management Area"
+ CONTACT-INFO
+ "Juergen Schoenwaelder (Editor)
+ TU Braunschweig
+ Bueltenweg 74/75
+ 38106 Braunschweig, Germany
+ Phone: +49 531 391-3289
+
+ Send comments to <[email protected]>."
+ DESCRIPTION
+ "This MIB module provides commonly used transport
+ address definitions.
+
+ Copyright (C) The Internet Society (2002). This version of
+ this MIB module is part of RFC 3419; see the RFC itself for
+ full legal notices."
+
+ -- Revision log
+
+ REVISION "200211010000Z"
+ DESCRIPTION
+ "Initial version, published as RFC 3419."
+ ::= { mib-2 100 }
+
+
+transportDomains OBJECT IDENTIFIER ::= { transportAddressMIB 1 }
+
+transportDomainUdpIpv4 OBJECT-IDENTITY
+ STATUS current
+ DESCRIPTION
+ "The UDP over IPv4 transport domain. The corresponding
+ transport address is of type TransportAddressIPv4 for
+ global IPv4 addresses."
+ ::= { transportDomains 1 }
+
+transportDomainUdpIpv6 OBJECT-IDENTITY
+ STATUS current
+ DESCRIPTION
+ "The UDP over IPv6 transport domain. The corresponding
+ transport address is of type TransportAddressIPv6 for
+ global IPv6 addresses."
+ ::= { transportDomains 2 }
+
+transportDomainUdpIpv4z OBJECT-IDENTITY
+ STATUS current
+ DESCRIPTION
+ "The UDP over IPv4 transport domain. The corresponding
+ transport address is of type TransportAddressIPv4z for
+ scoped IPv4 addresses with a zone index."
+ ::= { transportDomains 3 }
+
+transportDomainUdpIpv6z OBJECT-IDENTITY
+ STATUS current
+ DESCRIPTION
+ "The UDP over IPv6 transport domain. The corresponding
+ transport address is of type TransportAddressIPv6z for
+ scoped IPv6 addresses with a zone index."
+ ::= { transportDomains 4 }
+
+transportDomainTcpIpv4 OBJECT-IDENTITY
+ STATUS current
+ DESCRIPTION
+ "The TCP over IPv4 transport domain. The corresponding
+ transport address is of type TransportAddressIPv4 for
+ global IPv4 addresses."
+ ::= { transportDomains 5 }
+
+transportDomainTcpIpv6 OBJECT-IDENTITY
+ STATUS current
+ DESCRIPTION
+ "The TCP over IPv6 transport domain. The corresponding
+ transport address is of type TransportAddressIPv6 for
+ global IPv6 addresses."
+ ::= { transportDomains 6 }
+
+transportDomainTcpIpv4z OBJECT-IDENTITY
+ STATUS current
+ DESCRIPTION
+ "The TCP over IPv4 transport domain. The corresponding
+ transport address is of type TransportAddressIPv4z for
+ scoped IPv4 addresses with a zone index."
+ ::= { transportDomains 7 }
+
+transportDomainTcpIpv6z OBJECT-IDENTITY
+ STATUS current
+ DESCRIPTION
+ "The TCP over IPv6 transport domain. The corresponding
+ transport address is of type TransportAddressIPv6z for
+ scoped IPv6 addresses with a zone index."
+ ::= { transportDomains 8 }
+
+transportDomainSctpIpv4 OBJECT-IDENTITY
+ STATUS current
+ DESCRIPTION
+ "The SCTP over IPv4 transport domain. The corresponding
+ transport address is of type TransportAddressIPv4 for
+ global IPv4 addresses. This transport domain usually
+ represents the primary address on multihomed SCTP
+ endpoints."
+ ::= { transportDomains 9 }
+
+transportDomainSctpIpv6 OBJECT-IDENTITY
+ STATUS current
+ DESCRIPTION
+ "The SCTP over IPv6 transport domain. The corresponding
+ transport address is of type TransportAddressIPv6 for
+ global IPv6 addresses. This transport domain usually
+ represents the primary address on multihomed SCTP
+ endpoints."
+ ::= { transportDomains 10 }
+
+transportDomainSctpIpv4z OBJECT-IDENTITY
+ STATUS current
+ DESCRIPTION
+ "The SCTP over IPv4 transport domain. The corresponding
+ transport address is of type TransportAddressIPv4z for
+ scoped IPv4 addresses with a zone index. This transport
+ domain usually represents the primary address on
+ multihomed SCTP endpoints."
+ ::= { transportDomains 11 }
+
+transportDomainSctpIpv6z OBJECT-IDENTITY
+ STATUS current
+ DESCRIPTION
+ "The SCTP over IPv6 transport domain. The corresponding
+ transport address is of type TransportAddressIPv6z for
+ scoped IPv6 addresses with a zone index. This transport
+ domain usually represents the primary address on
+ multihomed SCTP endpoints."
+ ::= { transportDomains 12 }
+
+transportDomainLocal OBJECT-IDENTITY
+ STATUS current
+ DESCRIPTION
+ "The Posix Local IPC transport domain. The corresponding
+ transport address is of type TransportAddressLocal.
+
+ The Posix Local IPC transport domain incorporates the
+ well-known UNIX domain sockets."
+ ::= { transportDomains 13 }
+
+transportDomainUdpDns OBJECT-IDENTITY
+ STATUS current
+ DESCRIPTION
+ "The UDP transport domain using fully qualified domain
+ names. The corresponding transport address is of type
+ TransportAddressDns."
+ ::= { transportDomains 14 }
+
+transportDomainTcpDns OBJECT-IDENTITY
+ STATUS current
+ DESCRIPTION
+ "The TCP transport domain using fully qualified domain
+ names. The corresponding transport address is of type
+ TransportAddressDns."
+ ::= { transportDomains 15 }
+
+transportDomainSctpDns OBJECT-IDENTITY
+ STATUS current
+ DESCRIPTION
+ "The SCTP transport domain using fully qualified domain
+ names. The corresponding transport address is of type
+ TransportAddressDns."
+ ::= { transportDomains 16 }
+
+TransportDomain ::= TEXTUAL-CONVENTION
+ STATUS current
+ DESCRIPTION
+ "A value that represents a transport domain.
+
+ Some possible values, such as transportDomainUdpIpv4, are
+ defined in this module. Other possible values can be
+ defined in other MIB modules."
+ SYNTAX OBJECT IDENTIFIER
+
+--
+-- The enumerated values of the textual convention below should
+-- be identical to the last sub-identifier of the OID registered
+-- for the same domain.
+--
+
+TransportAddressType ::= TEXTUAL-CONVENTION
+ STATUS current
+ DESCRIPTION
+ "A value that represents a transport domain. This is the
+ enumerated version of the transport domain registrations
+ in this MIB module. The enumerated values have the
+ following meaning:
+
+ unknown(0) unknown transport address type
+ udpIpv4(1) transportDomainUdpIpv4
+ udpIpv6(2) transportDomainUdpIpv6
+ udpIpv4z(3) transportDomainUdpIpv4z
+ udpIpv6z(4) transportDomainUdpIpv6z
+ tcpIpv4(5) transportDomainTcpIpv4
+ tcpIpv6(6) transportDomainTcpIpv6
+ tcpIpv4z(7) transportDomainTcpIpv4z
+ tcpIpv6z(8) transportDomainTcpIpv6z
+ sctpIpv4(9) transportDomainSctpIpv4
+ sctpIpv6(10) transportDomainSctpIpv6
+ sctpIpv4z(11) transportDomainSctpIpv4z
+ sctpIpv6z(12) transportDomainSctpIpv6z
+ local(13) transportDomainLocal
+ udpDns(14) transportDomainUdpDns
+ tcpDns(15) transportDomainTcpDns
+ sctpDns(16) transportDomainSctpDns
+
+ This textual convention can be used to represent transport
+ domains in situations where a syntax of TransportDomain is
+ unwieldy (for example, when used as an index).
+
+ The usage of this textual convention implies that additional
+ transport domains can only be supported by updating this MIB
+ module. This extensibility restriction does not apply for the
+ TransportDomain textual convention which allows MIB authors
+ to define additional transport domains independently in
+ other MIB modules."
+ SYNTAX INTEGER {
+ unknown(0),
+ udpIpv4(1),
+ udpIpv6(2),
+ udpIpv4z(3),
+ udpIpv6z(4),
+ tcpIpv4(5),
+ tcpIpv6(6),
+ tcpIpv4z(7),
+ tcpIpv6z(8),
+ sctpIpv4(9),
+ sctpIpv6(10),
+ sctpIpv4z(11),
+ sctpIpv6z(12),
+ local(13),
+ udpDns(14),
+ tcpDns(15),
+ sctpDns(16)
+ }
+
+TransportAddress ::= TEXTUAL-CONVENTION
+ STATUS current
+ DESCRIPTION
+ "Denotes a generic transport address.
+
+ A TransportAddress value is always interpreted within the
+ context of a TransportAddressType or TransportDomain value.
+ Every usage of the TransportAddress textual convention MUST
+ specify the TransportAddressType or TransportDomain object
+ which provides the context. Furthermore, MIB authors SHOULD
+ define a separate TransportAddressType or TransportDomain
+ object for each TransportAddress object. It is suggested that
+ the TransportAddressType or TransportDomain is logically
+ registered before the object(s) which use the
+ TransportAddress textual convention if they appear in the
+ same logical row.
+
+ The value of a TransportAddress object must always be
+ consistent with the value of the associated
+ TransportAddressType or TransportDomain object. Attempts
+ to set a TransportAddress object to a value which is
+ inconsistent with the associated TransportAddressType or
+ TransportDomain must fail with an inconsistentValue error.
+
+ When this textual convention is used as a syntax of an
+ index object, there may be issues with the limit of 128
+ sub-identifiers specified in SMIv2, STD 58. In this case,
+ the OBJECT-TYPE declaration MUST include a 'SIZE' clause
+ to limit the number of potential instance sub-identifiers."
+ SYNTAX OCTET STRING (SIZE (0..255))
+
+TransportAddressIPv4 ::= TEXTUAL-CONVENTION
+ DISPLAY-HINT "1d.1d.1d.1d:2d"
+ STATUS current
+ DESCRIPTION
+ "Represents a transport address consisting of an IPv4
+ address and a port number (as used for example by UDP,
+ TCP and SCTP):
+
+ octets contents encoding
+ 1-4 IPv4 address network-byte order
+ 5-6 port number network-byte order
+
+ This textual convention SHOULD NOT be used directly in object
+ definitions since it restricts addresses to a specific format.
+ However, if it is used, it MAY be used either on its own or
+ in conjunction with TransportAddressType or TransportDomain
+ as a pair."
+ SYNTAX OCTET STRING (SIZE (6))
+
+TransportAddressIPv6 ::= TEXTUAL-CONVENTION
+ DISPLAY-HINT "0a[2x:2x:2x:2x:2x:2x:2x:2x]0a:2d"
+ STATUS current
+ DESCRIPTION
+ "Represents a transport address consisting of an IPv6
+ address and a port number (as used for example by UDP,
+ TCP and SCTP):
+
+ octets contents encoding
+ 1-16 IPv6 address network-byte order
+ 17-18 port number network-byte order
+
+ This textual convention SHOULD NOT be used directly in object
+ definitions since it restricts addresses to a specific format.
+ However, if it is used, it MAY be used either on its own or
+ in conjunction with TransportAddressType or TransportDomain
+ as a pair."
+ SYNTAX OCTET STRING (SIZE (18))
+
+TransportAddressIPv4z ::= TEXTUAL-CONVENTION
+ DISPLAY-HINT "1d.1d.1d.1d%4d:2d"
+ STATUS current
+ DESCRIPTION
+ "Represents a transport address consisting of an IPv4
+ address, a zone index and a port number (as used for
+ example by UDP, TCP and SCTP):
+
+ octets contents encoding
+ 1-4 IPv4 address network-byte order
+ 5-8 zone index network-byte order
+ 9-10 port number network-byte order
+
+ This textual convention SHOULD NOT be used directly in object
+ definitions since it restricts addresses to a specific format.
+ However, if it is used, it MAY be used either on its own or
+ in conjunction with TransportAddressType or TransportDomain
+ as a pair."
+ SYNTAX OCTET STRING (SIZE (10))
+
+TransportAddressIPv6z ::= TEXTUAL-CONVENTION
+ DISPLAY-HINT "0a[2x:2x:2x:2x:2x:2x:2x:2x%4d]0a:2d"
+ STATUS current
+ DESCRIPTION
+ "Represents a transport address consisting of an IPv6
+ address, a zone index and a port number (as used for
+ example by UDP, TCP and SCTP):
+
+ octets contents encoding
+ 1-16 IPv6 address network-byte order
+ 17-20 zone index network-byte order
+ 21-22 port number network-byte order
+
+ This textual convention SHOULD NOT be used directly in object
+ definitions since it restricts addresses to a specific format.
+ However, if it is used, it MAY be used either on its own or
+ in conjunction with TransportAddressType or TransportDomain
+ as a pair."
+ SYNTAX OCTET STRING (SIZE (22))
+
+TransportAddressLocal ::= TEXTUAL-CONVENTION
+ DISPLAY-HINT "1a"
+ STATUS current
+ DESCRIPTION
+ "Represents a POSIX Local IPC transport address:
+
+ octets contents encoding
+ all POSIX Local IPC address string
+
+ The Posix Local IPC transport domain subsumes UNIX domain
+ sockets.
+
+ This textual convention SHOULD NOT be used directly in object
+ definitions since it restricts addresses to a specific format.
+ However, if it is used, it MAY be used either on its own or
+ in conjunction with TransportAddressType or TransportDomain
+ as a pair.
+
+ When this textual convention is used as a syntax of an
+ index object, there may be issues with the limit of 128
+ sub-identifiers specified in SMIv2, STD 58. In this case,
+ the OBJECT-TYPE declaration MUST include a 'SIZE' clause
+ to limit the number of potential instance sub-identifiers."
+ REFERENCE
+ "Protocol Independent Interfaces (IEEE POSIX 1003.1g)"
+ SYNTAX OCTET STRING (SIZE (1..255))
+
+TransportAddressDns ::= TEXTUAL-CONVENTION
+ DISPLAY-HINT "1a"
+ STATUS current
+ DESCRIPTION
+ "Represents a DNS domain name followed by a colon ':'
+ (ASCII character 0x3A) and a port number in ASCII.
+ The name SHOULD be fully qualified whenever possible.
+
+ Values of this textual convention are not directly useable as
+ transport-layer addressing information, and require runtime
+ resolution. As such, applications that write them must be
+ prepared for handling errors if such values are not
+ supported, or cannot be resolved (if resolution occurs at the
+ time of the management operation).
+
+ The DESCRIPTION clause of TransportAddress objects that may
+ have TransportAddressDns values must fully describe how (and
+ when) such names are to be resolved to IP addresses and vice
+ versa.
+
+ This textual convention SHOULD NOT be used directly in object
+ definitions since it restricts addresses to a specific format.
+ However, if it is used, it MAY be used either on its own or
+ in conjunction with TransportAddressType or TransportDomain
+ as a pair.
+
+ When this textual convention is used as a syntax of an
+ index object, there may be issues with the limit of 128
+ sub-identifiers specified in SMIv2, STD 58. In this case,
+ the OBJECT-TYPE declaration MUST include a 'SIZE' clause
+ to limit the number of potential instance sub-identifiers."
+ SYNTAX OCTET STRING (SIZE (1..255))
+
+END
diff --git a/lib/snmp/priv/conf/agent/target_addr.conf b/lib/snmp/priv/conf/agent/target_addr.conf
index 33a5d0d4c4..f48a6645a3 100644
--- a/lib/snmp/priv/conf/agent/target_addr.conf
+++ b/lib/snmp/priv/conf/agent/target_addr.conf
@@ -3,9 +3,13 @@
%% The data is inserted into the snmpTargetAddrTable defined
%% in SNMP-TARGET-MIB, and in the snmpTargeAddrExtTabke defined
%% in SNMP-COMMUNITY-MIB.
-%% Each row is a 9-tuple:
-%% {Name, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId,
-%% TMask, MaxMessageSize}.
+%% Each row is a 10 or 11-tuple (Domain is optional):
+%% {Name,
+%% Domain, Ip, Port,
+%% Timeout, RetryCount, TagList, ParamsName, EngineId,
+%% TMask, MaxMessageSize}.
+%% The value of Domain decide the format of the Ip and TMask values.
+%% If not present, classic Ipv4 is assumed.
%% The EngineId value is only used if Inform-Requests are sent to this
%% target. If Informs are not sent, this value is ignored, and can be
%% e.g. an empty string. However, if Informs are sent, it is essential
diff --git a/lib/snmp/src/agent/snmp_community_mib.erl b/lib/snmp/src/agent/snmp_community_mib.erl
index 5644a43345..77307aa7ad 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-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
%%
%% The 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,7 +25,7 @@
snmpTargetAddrExtTable/3,
community2vacm/2, vacm2community/2,
get_target_addr_ext_mms/2]).
--export([add_community/5, delete_community/1]).
+-export([add_community/5, add_community/6, delete_community/1]).
-export([check_community/1]).
-include("SNMP-COMMUNITY-MIB.hrl").
@@ -128,12 +128,16 @@ read_community_config_files(Dir) ->
Comms.
check_community({Index, CommunityName, SecName, CtxName, TransportTag}) ->
+ EngineID = get_engine_id(),
+ check_community({Index, CommunityName, SecName,
+ EngineID, CtxName, TransportTag});
+check_community({Index, CommunityName, SecName,
+ EngineID, CtxName, TransportTag}) ->
snmp_conf:check_string(Index,{gt,0}),
snmp_conf:check_string(CommunityName),
snmp_conf:check_string(SecName),
snmp_conf:check_string(CtxName),
snmp_conf:check_string(TransportTag),
- EngineID = get_engine_id(),
Comm = {Index, CommunityName, SecName, EngineID, CtxName, TransportTag,
?'StorageType_nonVolatile', ?'RowStatus_active'},
{ok, Comm};
@@ -173,6 +177,13 @@ table_del_row(Tab, Key) ->
%% FIXME: does not work with mnesia
add_community(Idx, CommName, SecName, CtxName, TransportTag) ->
Community = {Idx, CommName, SecName, CtxName, TransportTag},
+ do_add_community(Community).
+
+add_community(Idx, CommName, SecName, EngineId, CtxName, TransportTag) ->
+ Community = {Idx, CommName, SecName, EngineId, CtxName, TransportTag},
+ do_add_community(Community).
+
+do_add_community(Community) ->
case (catch check_community(Community)) of
{ok, Row} ->
Key = element(1, Row),
diff --git a/lib/snmp/src/agent/snmp_notification_mib.erl b/lib/snmp/src/agent/snmp_notification_mib.erl
index 1cd69b430f..720ac749b8 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-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -273,9 +273,12 @@ find_targets(Key, TargAddrs, Db, Res) ->
get_targets([{TagList, Addr, TargetName, Params, Timeout, Retry}|T],
Tag, Type, Name) ->
case snmp_misc:is_tag_member(Tag, TagList) of
- true -> [{Name, {Addr, TargetName, Params, type(Type, Timeout, Retry)}}|
- get_targets(T, Tag, Type, Name)];
+ true ->
+ ?vtrace("tag ~w *is* member", [Tag]),
+ [{Name, {Addr, TargetName, Params, type(Type, Timeout, Retry)}}|
+ get_targets(T, Tag, Type, Name)];
false ->
+ ?vtrace("tag ~w is *not* member", [Tag]),
get_targets(T, Tag, Type, Name)
end;
get_targets([], _Tag, _Type, _Name) ->
diff --git a/lib/snmp/src/agent/snmp_target_mib.erl b/lib/snmp/src/agent/snmp_target_mib.erl
index 270a5fd5b6..60bd3e0912 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-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The 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,16 +26,18 @@
snmpTargetParamsTable/1, snmpTargetParamsTable/3,
get_target_addrs/0, get_target_engine_id/1, set_target_engine_id/2,
is_valid_tag/3, get/3, table_next/2]).
--export([add_addr/10, delete_addr/1,
+-export([add_addr/10, add_addr/11, delete_addr/1,
add_params/5, delete_params/1]).
-export([check_target_addr/1, check_target_params/1]).
+-export([default_domain/0]).
--include("snmp_types.hrl").
--include("snmp_tables.hrl").
--include("SNMP-TARGET-MIB.hrl").
--include("SNMPv2-TC.hrl").
--include("SNMPv2-TM.hrl").
--include("SNMP-FRAMEWORK-MIB.hrl").
+-include_lib("snmp/include/snmp_types.hrl").
+-include_lib("snmp/include/snmp_tables.hrl").
+-include_lib("snmp/include/SNMP-TARGET-MIB.hrl").
+-include_lib("snmp/include/SNMPv2-TC.hrl").
+-include_lib("snmp/include/SNMPv2-TM.hrl").
+-include_lib("snmp/include/SNMP-FRAMEWORK-MIB.hrl").
+-include_lib("snmp/include/TRANSPORT-ADDRESS-MIB.hrl").
-define(VMODULE,"TARGET-MIB").
-include("snmp_verbosity.hrl").
@@ -49,6 +51,12 @@
%%-----------------------------------------------------------------
+
+default_domain() ->
+ snmpUDPDomain.
+
+
+%%-----------------------------------------------------------------
%% Func: configure/1
%% Args: Dir is the directory where the configuration files are found.
%% Purpose: If the tables doesn't exist, this function reads
@@ -139,39 +147,51 @@ read_target_config_files(Dir) ->
%% {Name, Ip, Udp, Timeout, RetryCount, TagList, Params, EngineId,
%% TMask, MMS}
%%-----------------------------------------------------------------
-check_target_addr({Name, Ip, Udp, Timeout, RetryCount, TagList,
- Params, EngineId, TMask, MMS}) ->
+
+check_target_addr({Name, Domain, Ip, Udp, Timeout, RetryCount, TagList,
+ Params, EngineId, TMask, MMS}) ->
?vtrace("check target address with:"
- "~n Name: ~s"
- "~n Ip: ~p"
- "~n Udp: ~p"
- "~n Timeout: ~p"
- "~n RetryCount: ~p"
- "~n TagList: ~p"
- "~n Params: ~p"
- "~n EngineId: ~p"
- "~n TMask: ~p"
- "~n MMS: ~p",
- [Name,Ip,Udp,Timeout,RetryCount,
- TagList,Params,EngineId,TMask,MMS]),
+ "~n Name: ~s"
+ "~n Domain: ~p"
+ "~n Ip: ~p"
+ "~n Udp: ~p"
+ "~n Timeout: ~p"
+ "~n RetryCount: ~p"
+ "~n TagList: ~p"
+ "~n Params: ~p"
+ "~n EngineId: ~p"
+ "~n TMask: ~p"
+ "~n MMS: ~p",
+ [Name,
+ Domain, Ip, Udp,
+ Timeout, RetryCount,
+ TagList, Params, EngineId, TMask, MMS]),
snmp_conf:check_string(Name,{gt,0}),
- snmp_conf:check_ip(Ip),
+ snmp_conf:check_domain(Domain),
+ snmp_conf:check_ip(Domain, Ip),
snmp_conf:check_integer(Udp, {gt, 0}),
snmp_conf:check_integer(Timeout, {gte, 0}),
snmp_conf:check_integer(RetryCount, {gte,0}),
snmp_conf:check_string(TagList),
snmp_conf:check_string(Params),
check_engine_id(EngineId),
- TAddr = Ip ++ [Udp div 256, Udp rem 256],
- check_mask(TMask, TAddr),
+ TAddress = snmp_conf:mk_taddress(Domain, Ip, Udp),
+ TDomain = snmp_conf:mk_tdomain(Domain),
+ check_tmask(TDomain, TMask, TAddress),
snmp_conf:check_packet_size(MMS),
?vtrace("check target address done",[]),
-
- Addr = {Name, ?snmpUDPDomain, TAddr, Timeout,
+ Addr = {Name, TDomain, TAddress, Timeout,
RetryCount, TagList, Params,
?'StorageType_nonVolatile', ?'RowStatus_active', EngineId,
TMask, MMS}, % Values for Augmenting table in SNMP-COMMUNITY-MIB
{ok, Addr};
+check_target_addr({Name, Ip, Udp, Timeout, RetryCount, TagList,
+ Params, EngineId, TMask, MMS}) ->
+ Domain = default_domain(),
+ check_target_addr({Name,
+ Domain, Ip, Udp,
+ Timeout, RetryCount, TagList,
+ Params, EngineId, TMask, MMS});
check_target_addr({Name, Ip, Udp, Timeout, RetryCount, TagList, Params,
EngineId}) ->
check_target_addr({Name, Ip, Udp, Timeout, RetryCount, TagList,
@@ -194,12 +214,13 @@ check_engine_id(discovery) ->
check_engine_id(EngineId) ->
snmp_conf:check_string(EngineId).
-check_mask([], _TAddr) ->
+
+check_tmask(_TDomain, [], _TAddress) ->
ok;
-check_mask(TMask, TAddr) when length(TMask) == length(TAddr) ->
- snmp_conf:check_taddress(TMask);
-check_mask(TMask, _TAddr) ->
- throw({error, {invalid_mask, TMask}}).
+check_tmask(TDomain, TMask, TAddress) when length(TMask) =:= length(TAddress) ->
+ snmp_conf:check_taddress(TDomain, TMask);
+check_tmask(_TDomain, TMask, _TAddr) ->
+ throw({error, {invalid_tmask, TMask}}).
%%-----------------------------------------------------------------
@@ -261,7 +282,13 @@ table_del_row(Tab, Key) ->
add_addr(Name, Ip, Port, Timeout, Retry, TagList,
Params, EngineId, TMask, MMS) ->
- Addr = {Name, Ip, Port, Timeout, Retry, TagList,
+ Domain = default_domain(),
+ add_addr(Name, Domain, Ip, Port, Timeout, Retry, TagList,
+ Params, EngineId, TMask, MMS).
+
+add_addr(Name, Domain, Ip, Port, Timeout, Retry, TagList,
+ Params, EngineId, TMask, MMS) ->
+ Addr = {Name, Domain, Ip, Port, Timeout, Retry, TagList,
Params, EngineId, TMask, MMS},
case (catch check_target_addr(Addr)) of
{ok, Row} ->
@@ -341,8 +368,11 @@ maybe_create_var(Var) ->
init_var(Var) -> ets:insert(snmp_agent_table, {Var, 0}).
vars() ->
- [snmpUnavailableContexts,
- snmpUnknownContexts].
+ [
+ snmpUnavailableContexts,
+ snmpUnknownContexts
+ ].
+
%%-----------------------------------------------------------------
%% API functions
@@ -353,10 +383,18 @@ is_valid_tag(Tag, TDomain, TAddress) ->
is_valid_tag(TDomain, TAddress, Tag, []).
is_valid_tag(TDomain, TAddress, Tag, Key) ->
+ ?vtrace("is_valid_tag -> entry with"
+ "~n TDomain: ~p"
+ "~n TAddress: ~p"
+ "~n Tag: ~p"
+ "~n Key: ~p", [TDomain, TAddress, Tag, Key]),
case table_next(snmpTargetAddrTable, Key) of
endOfTable ->
+ ?vtrace("is_valid_tag -> endOfTable", []),
false;
NextKey ->
+ ?vtrace("is_valid_tag -> next key found"
+ "~n NextKey: ~p", [NextKey]),
case get(snmpTargetAddrTable, NextKey, [?snmpTargetAddrTDomain,
?snmpTargetAddrTAddress,
?snmpTargetAddrTagList,
@@ -365,6 +403,8 @@ is_valid_tag(TDomain, TAddress, Tag, Key) ->
{value, TAddress}, % RFC2576: chapters 5.2.1 & 5.3
{value, TagList},
{value, []}] ->
+ ?vtrace("is_valid_tag -> found with exact match"
+ "~n TagList: ~p", [TagList]),
case snmp_misc:is_tag_member(Tag, TagList) of
true ->
?vtrace("is_valid_tag -> exact: "
@@ -380,9 +420,14 @@ is_valid_tag(TDomain, TAddress, Tag, Key) ->
{value, TAddress2},
{value, TagList},
{value, TMask}] when TMask =/= [] ->
+ ?vtrace("is_valid_tag -> found with exact match"
+ "~n TagList: ~p"
+ "~n TMask: ~p", [TagList, TMask]),
case snmp_misc:is_tmask_match(TAddress, TAddress2,
TMask) of
true ->
+ ?vtrace("is_valid_tag -> "
+ "tmask match - now check tag member", []),
case snmp_misc:is_tag_member(Tag, TagList) of
true ->
?vtrace("is_valid_tag -> masked: "
@@ -395,10 +440,12 @@ is_valid_tag(TDomain, TAddress, Tag, Key) ->
Tag, NextKey)
end;
false ->
+ ?vtrace("is_valid_tag -> tmask NO match", []),
is_valid_tag(TDomain, TAddress,
Tag, NextKey)
end;
_ ->
+ ?vtrace("is_valid_tag -> not found - try next", []),
is_valid_tag(TDomain, TAddress, Tag, NextKey)
end
end.
@@ -561,7 +608,9 @@ snmpTargetAddrTable(print) ->
[Prefix, element(?snmpTargetAddrName, Row),
Prefix, element(?snmpTargetAddrTDomain, Row),
case element(?snmpTargetAddrTDomain, Row) of
- ?snmpUDPDomain -> udp;
+ ?snmpUDPDomain -> snmpUDPDomain;
+ ?transportDomainUdpIpv4 -> transportDomainUdpIpv4;
+ ?transportDomainUdpIpv6 -> transportDomainUdpIpv6;
_ -> undefined
end,
Prefix, element(?snmpTargetAddrTAddress, Row),
@@ -610,14 +659,14 @@ snmpTargetAddrTable(get, RowIndex, Cols) ->
snmpTargetAddrTable(get_next, RowIndex, Cols) ->
next(snmpTargetAddrTable, RowIndex, Cols);
snmpTargetAddrTable(set, RowIndex, Cols0) ->
- %% BMK BMK BMK
- case (catch verify_targetAddrTable_cols(Cols0, [])) of
+ %% BMK BMK
+ case (catch verify_targetAddrTable_cols(Cols0)) of
{ok, Cols} ->
snmp_notification_mib:invalidate_cache(),
%% Add columns for augmenting table snmpTargetAddrExtTable and for
- %% target engine ID. Target engine ID is set to "". The function
+ %% target engine ID. Target engine ID is set to "". The function
%% get_target_engine_id will return "" unless a value is set using
- %% set_target_engine_id. If it is "" Informs can't be sent to the
+ %% set_target_engine_id. If it is "" Informs can't be sent to the
%% target.
NCols = Cols ++ [{?snmpTargetAddrEngineId, ""},
{?snmpTargetAddrTMask, []},
@@ -628,12 +677,12 @@ snmpTargetAddrTable(set, RowIndex, Cols0) ->
Error
end;
snmpTargetAddrTable(is_set_ok, RowIndex, Cols0) ->
- case (catch verify_targetAddrTable_cols(Cols0, [])) of
+ case (catch verify_targetAddrTable_cols(Cols0)) of
{ok, Cols} ->
%% Add columns for augmenting table snmpTargetAddrExtTable and for
- %% target engine ID. Target engine ID is set to "". The function
+ %% target engine ID. Target engine ID is set to "". The function
%% get_target_engine_id will return "" unless a value is set using
- %% set_target_engine_id. If it is "" Informs can't be sent to the
+ %% set_target_engine_id. If it is "" Informs can't be sent to the
%% target.
NCols = Cols ++ [{?snmpTargetAddrEngineId, ""},
{?snmpTargetAddrTMask, []},
@@ -647,55 +696,83 @@ snmpTargetAddrTable(Op, Arg1, Arg2) ->
Db = db(snmpTargetAddrTable),
snmp_generic:table_func(Op, Arg1, Arg2, Db).
+verify_targetAddrTable_cols(Cols) ->
+ ValidCols0 = verify_targetAddrTable_cols(Cols, []),
+ %% Make a last pass to verify TDomain and TAddress.
+ ValidCols0.
+
verify_targetAddrTable_cols([], Cols) ->
{ok, lists:reverse(Cols)};
-verify_targetAddrTable_cols([{Col, Val0}|Cols], Acc) ->
- Val = verify_targetAddrTable_col(Col, Val0),
- verify_targetAddrTable_cols(Cols, [{Col, Val}|Acc]).
+verify_targetAddrTable_cols([{Col, Val0}|Cols], ValidCols) ->
+ Val = verify_targetAddrTable_col(Col, Val0, ValidCols),
+ verify_targetAddrTable_cols(Cols, [{Col, Val}|ValidCols]).
-verify_targetAddrTable_col(?snmpTargetAddrName, Name) ->
+verify_targetAddrTable_col(?snmpTargetAddrName, Name, _) ->
case (catch snmp_conf:check_string(Name)) of
ok ->
Name;
_ ->
wrongValue(?snmpTargetAddrName)
end;
-verify_targetAddrTable_col(?snmpTargetAddrTAddress, TAddr) ->
- case (catch snmp_conf:check_taddress(TAddr)) of
+verify_targetAddrTable_col(?snmpTargetAddrTDomain, TDomain, _) ->
+ case (catch snmp_conf:check_tdomain(TDomain)) of
ok ->
- TAddr;
+ TDomain;
_ ->
- wrongValue(?snmpTargetAddrTAddress)
+ wrongValue(?snmpTargetAddrTDomain)
+ end;
+%% In order to (properly) validate the TAddress,
+%% the TDomain must already have been validated
+%% (the format of TAddress depends on TDomain).
+verify_targetAddrTable_col(?snmpTargetAddrTAddress, TAddress, ValidCols) ->
+ case lists:keysearch(?snmpTargetAddrTDomain, 1, ValidCols) of
+ {value, {?snmpTargetAddrTDomain, TDomain}} ->
+ case (catch snmp_conf:check_taddress(TDomain, TAddress)) of
+ ok ->
+ TAddress;
+ _ ->
+ wrongValue(?snmpTargetAddrTAddress)
+ end;
+ false ->
+ %% The user did not provide us with a TDomain, which
+ %% must mean that he/she intends to use the old domain.
+ TDomain = snmp_conf:mk_tdomain(default_domain()),
+ case (catch snmp_conf:check_taddress(TDomain, TAddress)) of
+ ok ->
+ TAddress;
+ _ ->
+ wrongValue(?snmpTargetAddrTAddress)
+ end
end;
-verify_targetAddrTable_col(?snmpTargetAddrTimeout, Timeout) ->
+verify_targetAddrTable_col(?snmpTargetAddrTimeout, Timeout, _) ->
case (catch snmp_conf:check_integer(Timeout)) of
ok when Timeout >= 0 ->
Timeout;
_ ->
wrongValue(?snmpTargetAddrTimeout)
end;
-verify_targetAddrTable_col(?snmpTargetAddrRetryCount, Retry) ->
+verify_targetAddrTable_col(?snmpTargetAddrRetryCount, Retry, _) ->
case (catch snmp_conf:check_integer(Retry)) of
ok when Retry >= 0 ->
Retry;
_ ->
wrongValue(?snmpTargetAddrRetryCount)
end;
-verify_targetAddrTable_col(?snmpTargetAddrTagList, TagList) ->
+verify_targetAddrTable_col(?snmpTargetAddrTagList, TagList, _) ->
case (catch snmp_conf:check_string(TagList)) of
ok ->
TagList;
_ ->
wrongValue(?snmpTargetAddrTagList)
end;
-verify_targetAddrTable_col(?snmpTargetAddrParams, Params) ->
+verify_targetAddrTable_col(?snmpTargetAddrParams, Params, _) ->
case (catch snmp_conf:check_string(Params)) of
ok ->
Params;
_ ->
wrongValue(?snmpTargetAddrParams)
end;
-verify_targetAddrTable_col(_, Val) ->
+verify_targetAddrTable_col(_, Val, _) ->
Val.
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 28469a7b4e..37f6dd3f26 100644
--- a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
+++ b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
@@ -247,6 +247,7 @@ add_sec2group(SecModel, SecName, GroupName) ->
Key = [Key1, length(Key2) | Key2],
case table_cre_row(vacmSecurityToGroupTable, Key, Row) of
true ->
+ snmpa_agent:invalidate_ca_cache(),
{ok, Key};
false ->
{error, create_failed}
@@ -260,6 +261,7 @@ add_sec2group(SecModel, SecName, GroupName) ->
delete_sec2group(Key) ->
case table_del_row(vacmSecurityToGroupTable, Key) of
true ->
+ snmpa_agent:invalidate_ca_cache(),
ok;
false ->
{error, delete_failed}
@@ -279,6 +281,7 @@ add_access(GroupName, Prefix, SecModel, SecLevel, Match, RV, WV, NV) ->
Key3 = [SM, SL],
Key = Key1 ++ Key2 ++ Key3,
snmpa_vacm:insert([{Key, Row}], false),
+ snmpa_agent:invalidate_ca_cache(),
{ok, Key};
{error, Reason} ->
{error, Reason};
@@ -287,6 +290,7 @@ add_access(GroupName, Prefix, SecModel, SecLevel, Match, RV, WV, NV) ->
end.
delete_access(Key) ->
+ snmpa_agent:invalidate_ca_cache(),
snmpa_vacm:delete(Key).
@@ -299,6 +303,7 @@ add_view_tree_fam(ViewIndex, SubTree, Status, Mask) ->
Key = [length(Key1) | Key1] ++ [length(Key2) | Key2],
case table_cre_row(vacmViewTreeFamilyTable, Key, Row) of
true ->
+ snmpa_agent:invalidate_ca_cache(),
{ok, Key};
false ->
{error, create_failed}
@@ -312,6 +317,7 @@ add_view_tree_fam(ViewIndex, SubTree, Status, Mask) ->
delete_view_tree_fam(Key) ->
case table_del_row(vacmViewTreeFamilyTable, Key) of
true ->
+ snmpa_agent:invalidate_ca_cache(),
ok;
false ->
{error, delete_failed}
diff --git a/lib/snmp/src/agent/snmpa.erl b/lib/snmp/src/agent/snmpa.erl
index 22fbd33add..50b169e4e7 100644
--- a/lib/snmp/src/agent/snmpa.erl
+++ b/lib/snmp/src/agent/snmpa.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -60,6 +60,7 @@
register_subagent/3, unregister_subagent/2,
+ send_notification2/3,
send_notification/3, send_notification/4, send_notification/5,
send_notification/6, send_notification/7,
send_trap/3, send_trap/4,
@@ -108,8 +109,9 @@
-export([print_mib_info/0, print_mib_tables/0, print_mib_variables/0]).
-include("snmpa_atl.hrl").
+-include("snmpa_internal.hrl").
--define(EXTRA_INFO, undefined).
+-define(DISCO_EXTRA_INFO, undefined).
%%-----------------------------------------------------------------
@@ -596,22 +598,56 @@ set_request_limit(Agent, NewLimit) ->
%% -
+send_notification2(Agent, Notification, SendOpts) ->
+ snmpa_agent:send_notification(Agent, Notification, SendOpts).
+
send_notification(Agent, Notification, Recv) ->
- send_notification(Agent, Notification, Recv, "", "", []).
+ SendOpts =
+ [
+ {receiver, Recv},
+ {varbinds, []},
+ {name, ""},
+ {context, ""},
+ {extra, ?DEFAULT_NOTIF_EXTRA_INFO}
+ ],
+ send_notification2(Agent, Notification, SendOpts).
send_notification(Agent, Notification, Recv, Varbinds) ->
- send_notification(Agent, Notification, Recv, "", "", Varbinds).
+ SendOpts =
+ [
+ {receiver, Recv},
+ {varbinds, Varbinds},
+ {name, ""},
+ {context, ""},
+ {extra, ?DEFAULT_NOTIF_EXTRA_INFO}
+ ],
+ send_notification2(Agent, Notification, SendOpts).
send_notification(Agent, Notification, Recv, NotifyName, Varbinds) ->
- send_notification(Agent, Notification, Recv, NotifyName, "", Varbinds).
+ SendOpts =
+ [
+ {receiver, Recv},
+ {varbinds, Varbinds},
+ {name, NotifyName},
+ {context, ""},
+ {extra, ?DEFAULT_NOTIF_EXTRA_INFO}
+ ],
+ send_notification2(Agent, Notification, SendOpts).
send_notification(Agent, Notification, Recv, NotifyName,
ContextName, Varbinds)
when (is_list(NotifyName) andalso
is_list(ContextName) andalso
is_list(Varbinds)) ->
- snmpa_agent:send_trap(Agent, Notification, NotifyName,
- ContextName, Recv, Varbinds).
+ SendOpts =
+ [
+ {receiver, Recv},
+ {varbinds, Varbinds},
+ {name, NotifyName},
+ {context, ContextName},
+ {extra, ?DEFAULT_NOTIF_EXTRA_INFO}
+ ],
+ send_notification2(Agent, Notification, SendOpts).
send_notification(Agent, Notification, Recv,
NotifyName, ContextName, Varbinds, LocalEngineID)
@@ -619,8 +655,16 @@ send_notification(Agent, Notification, Recv,
is_list(ContextName) andalso
is_list(Varbinds) andalso
is_list(LocalEngineID)) ->
- snmpa_agent:send_trap(Agent, Notification, NotifyName,
- ContextName, Recv, Varbinds, LocalEngineID).
+ SendOpts =
+ [
+ {receiver, Recv},
+ {varbinds, Varbinds},
+ {name, NotifyName},
+ {context, ContextName},
+ {extra, ?DEFAULT_NOTIF_EXTRA_INFO},
+ {local_engine_id, LocalEngineID}
+ ],
+ send_notification2(Agent, Notification, SendOpts).
%% Kept for backwards compatibility
send_trap(Agent, Trap, Community) ->
@@ -655,7 +699,7 @@ discovery(TargetName, Notification, Varbinds, DiscoHandler)
discovery(TargetName, Notification, ContextName, Varbinds, DiscoHandler).
discovery(TargetName, Notification, ContextName, Varbinds, DiscoHandler) ->
- ExtraInfo = ?EXTRA_INFO,
+ ExtraInfo = ?DISCO_EXTRA_INFO,
discovery(TargetName, Notification, ContextName, Varbinds, DiscoHandler,
ExtraInfo).
diff --git a/lib/snmp/src/agent/snmpa_acm.erl b/lib/snmp/src/agent/snmpa_acm.erl
index 6ad4f0b442..42a0d4d6a3 100644
--- a/lib/snmp/src/agent/snmpa_acm.erl
+++ b/lib/snmp/src/agent/snmpa_acm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -62,11 +62,13 @@
%% {error, Reason} |
%% {discarded, Variable, Reason}
%% Types: Pdu = #pdu
-%% ACMData = acm_data() = {community, Community, Address} |
-%% {v3, MsgID, SecModel, SecName, SecLevel,
-%% ContextEngineID, ContextName, SecData}
+%% ACMData = acm_data() =
+%% {community, SecModel, Community, TDomain, TAddress} |
+%% {v3, MsgID, SecModel, SecName, SecLevel,
+%% ContextEngineID, ContextName, SecData}
%% Community = string()
-%% Address = ip() ++ udp() (list)
+%% TDomain = ?transportDomainUdpIpv4 | ?transportDomainUdpIpv6
+%% TAddress = ip() ++ udp() (list)
%% MsgID = integer() <not used>
%% SecModel = ?SEC_* (see snmp_types.hrl)
%% SecName = string()
@@ -114,7 +116,10 @@ error2status(_) -> genErr.
%% discarded: no error response is sent
%% authentication_failure: no error response is sent, a trap is generated
%%-----------------------------------------------------------------
-init_ca(Pdu, {community, SecModel, Community, TAddr}) ->
+init_ca(Pdu, {community, SecModel, Community, TAddress}) ->
+ TDomain = snmp_conf:mk_tdomain(snmp_target_mib:default_domain()),
+ init_ca(Pdu, {community, SecModel, Community, TDomain, TAddress});
+init_ca(Pdu, {community, SecModel, Community, TDomain, TAddress}) ->
%% This is a v1 or v2c request. Use SNMP-COMMUNITY-MIB to
%% map the community to vacm parameters.
?vtrace("check access for ~n"
@@ -126,18 +131,18 @@ init_ca(Pdu, {community, SecModel, Community, TAddr}) ->
_ -> read
end,
?vtrace("View type: ~p", [ViewType]),
- CaCacheKey = {Community, SecModel, TAddr, ViewType},
+ CaCacheKey = {Community, SecModel, TDomain, TAddress, ViewType},
case check_ca_cache(CaCacheKey) of
false ->
- case snmp_community_mib:community2vacm(Community,
- {?snmpUDPDomain,TAddr}) of
+ case snmp_community_mib:community2vacm(Community,
+ {TDomain, TAddress}) of
{SecName, _ContextEngineId, ContextName} ->
%% Maybe we should check that the contextEngineID
%% matches the local engineID?
%% It better, since we don't impl. proxy.
?vtrace("get mib view"
"~n Security name: ~p"
- "~n Context name: ~p",[SecName,ContextName]),
+ "~n Context name: ~p",[SecName, ContextName]),
case snmpa_vacm:get_mib_view(ViewType, SecModel, SecName,
?'SnmpSecurityLevel_noAuthNoPriv',
ContextName) of
@@ -153,7 +158,7 @@ init_ca(Pdu, {community, SecModel, Community, TAddr}) ->
end;
undefined ->
{authentication_failure, snmpInBadCommunityNames,
- {bad_community_name, TAddr, Community}}
+ {bad_community_name, TDomain, TAddress, Community}}
end;
Res ->
Res
@@ -219,6 +224,7 @@ upd_ca_cache(KeyVal) ->
invalidate_ca_cache() ->
erase(ca_cache).
+
%%-----------------------------------------------------------------
%% Func: check(Res) -> {ok, MibView} | {discarded, Variable, Reason}
%% Args: Res = {ok, AccessFunc} |
diff --git a/lib/snmp/src/agent/snmpa_agent.erl b/lib/snmp/src/agent/snmpa_agent.erl
index f70885b2ec..6322f0f21d 100644
--- a/lib/snmp/src/agent/snmpa_agent.erl
+++ b/lib/snmp/src/agent/snmpa_agent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,7 +30,7 @@
-export([subagent_set/2,
load_mibs/2, unload_mibs/2, which_mibs/1, whereis_mib/2, info/1,
register_subagent/3, unregister_subagent/2,
- send_trap/6, send_trap/7,
+ send_notification/3,
register_notification_filter/5,
unregister_notification_filter/2,
which_notification_filter/1,
@@ -62,10 +62,16 @@
-export([increment_counter/3]).
-export([restart_worker/1, restart_set_worker/1]).
+%% For backward compatibillity
+-export([send_trap/6, send_trap/7]).
+
%% Internal exports
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3, tr_var/2, tr_varbind/1,
- handle_pdu/7, worker/2, worker_loop/1, do_send_trap/7]).
+ handle_pdu/7, worker/2, worker_loop/1,
+ do_send_trap/7, do_send_trap/8]).
+
+-include("snmpa_internal.hrl").
-ifndef(default_verbosity).
-define(default_verbosity,silence).
@@ -527,6 +533,11 @@ which_notification_filter(Agent) ->
call(Agent, which_notification_filter).
+send_notification(Agent, Notification, SendOpts) ->
+ Msg = {send_notif, Notification, SendOpts},
+ maybe_call(Agent, Msg).
+
+%% <BACKWARD-COMPAT>
send_trap(Agent, Trap, NotifyName, CtxName, Recv, Varbinds) ->
?d("send_trap -> entry with"
"~n self(): ~p"
@@ -538,13 +549,33 @@ send_trap(Agent, Trap, NotifyName, CtxName, Recv, Varbinds) ->
"~n Varbinds: ~p",
[self(), Agent, wis(Agent),
Trap, NotifyName, CtxName, Recv, Varbinds]),
- Msg = {send_trap, Trap, NotifyName, CtxName, Recv, Varbinds},
- case (wis(Agent) =:= self()) of
- false ->
- call(Agent, Msg);
- true ->
- Agent ! Msg
- end.
+ SendOpts = [
+ {receiver, Recv},
+ {varbinds, Varbinds},
+ {name, NotifyName},
+ {context, CtxName},
+ {extra, ?DEFAULT_NOTIF_EXTRA_INFO}
+ ],
+ send_notification(Agent, Trap, SendOpts).
+
+%% send_trap(Agent, Trap, NotifyName, CtxName, Recv, Varbinds) ->
+%% ?d("send_trap -> entry with"
+%% "~n self(): ~p"
+%% "~n Agent: ~p [~p]"
+%% "~n Trap: ~p"
+%% "~n NotifyName: ~p"
+%% "~n CtxName: ~p"
+%% "~n Recv: ~p"
+%% "~n Varbinds: ~p",
+%% [self(), Agent, wis(Agent),
+%% Trap, NotifyName, CtxName, Recv, Varbinds]),
+%% Msg = {send_trap, Trap, NotifyName, CtxName, Recv, Varbinds},
+%% case (wis(Agent) =:= self()) of
+%% false ->
+%% call(Agent, Msg);
+%% true ->
+%% Agent ! Msg
+%% end.
send_trap(Agent, Trap, NotifyName, CtxName, Recv, Varbinds, LocalEngineID) ->
?d("send_trap -> entry with"
@@ -558,14 +589,38 @@ send_trap(Agent, Trap, NotifyName, CtxName, Recv, Varbinds, LocalEngineID) ->
"~n LocalEngineID: ~p",
[self(), Agent, wis(Agent),
Trap, NotifyName, CtxName, Recv, Varbinds, LocalEngineID]),
- Msg =
- {send_trap, Trap, NotifyName, CtxName, Recv, Varbinds, LocalEngineID},
- case (wis(Agent) =:= self()) of
- false ->
- call(Agent, Msg);
- true ->
- Agent ! Msg
- end.
+ SendOpts = [
+ {receiver, Recv},
+ {varbinds, Varbinds},
+ {name, NotifyName},
+ {context, CtxName},
+ {extra, ?DEFAULT_NOTIF_EXTRA_INFO},
+ {local_engine_id, LocalEngineID}
+ ],
+ send_notification(Agent, Trap, SendOpts).
+
+%% send_trap(Agent, Trap, NotifyName, CtxName, Recv, Varbinds, LocalEngineID) ->
+%% ?d("send_trap -> entry with"
+%% "~n self(): ~p"
+%% "~n Agent: ~p [~p]"
+%% "~n Trap: ~p"
+%% "~n NotifyName: ~p"
+%% "~n CtxName: ~p"
+%% "~n Recv: ~p"
+%% "~n Varbinds: ~p"
+%% "~n LocalEngineID: ~p",
+%% [self(), Agent, wis(Agent),
+%% Trap, NotifyName, CtxName, Recv, Varbinds, LocalEngineID]),
+%% Msg =
+%% {send_trap, Trap, NotifyName, CtxName, Recv, Varbinds, LocalEngineID},
+%% case (wis(Agent) =:= self()) of
+%% false ->
+%% call(Agent, Msg);
+%% true ->
+%% Agent ! Msg
+%% end.
+
+%% </BACKWARD-COMPAT>
%% -- Discovery functions --
@@ -655,7 +710,14 @@ wis(Atom) when is_atom(Atom) ->
forward_trap(Agent, TrapRecord, NotifyName, CtxName, Recv, Varbinds) ->
- Agent ! {forward_trap, TrapRecord, NotifyName, CtxName, Recv, Varbinds}.
+ ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
+ forward_trap(Agent, TrapRecord, NotifyName, CtxName, Recv, Varbinds,
+ ExtraInfo).
+
+forward_trap(Agent, TrapRecord, NotifyName, CtxName, Recv, Varbinds,
+ ExtraInfo) ->
+ Agent ! {forward_trap, TrapRecord, NotifyName, CtxName, Recv, Varbinds,
+ ExtraInfo}.
%%-----------------------------------------------------------------
@@ -745,6 +807,22 @@ handle_info(worker_available, S) ->
?vdebug("worker available",[]),
{noreply, S#state{worker_state = ready}};
+handle_info({send_notif, Notification, SendOpts}, S) ->
+ ?vlog("[handle_info] send trap request:"
+ "~n Notification: ~p"
+ "~n SendOpts: ~p",
+ [Notification, SendOpts]),
+ case (catch handle_send_trap(cast, S, Notification, SendOpts)) of
+ {ok, NewS} ->
+ {noreply, NewS};
+ {'EXIT', R} ->
+ ?vinfo("Trap not sent:~n ~p", [R]),
+ {noreply, S};
+ _ ->
+ {noreply, S}
+ end;
+
+%% <BACKWARD-COMPAT>
handle_info({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds}, S) ->
?vlog("[handle_info] send trap request:"
"~n Trap: ~p"
@@ -753,9 +831,10 @@ handle_info({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds}, S) ->
"~n Recv: ~p"
"~n Varbinds: ~p",
[Trap, NotifyName, ContextName, Recv, Varbinds]),
+ ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID,
- case catch handle_send_trap(S, Trap, NotifyName, ContextName,
- Recv, Varbinds, LocalEngineID) of
+ case (catch handle_send_trap(S, Trap, NotifyName, ContextName,
+ Recv, Varbinds, LocalEngineID, ExtraInfo)) of
{ok, NewS} ->
{noreply, NewS};
{'EXIT', R} ->
@@ -775,8 +854,9 @@ handle_info({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds,
"~n Varbinds: ~p"
"~n LocalEngineID: ~p",
[Trap, NotifyName, ContextName, Recv, Varbinds, LocalEngineID]),
- case catch handle_send_trap(S, Trap, NotifyName, ContextName,
- Recv, Varbinds, LocalEngineID) of
+ ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
+ case (catch handle_send_trap(S, Trap, NotifyName, ContextName,
+ Recv, Varbinds, LocalEngineID, ExtraInfo)) of
{ok, NewS} ->
{noreply, NewS};
{'EXIT', R} ->
@@ -785,8 +865,31 @@ handle_info({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds,
_ ->
{noreply, S}
end;
+%% </BACKWARD-COMPAT>
handle_info({forward_trap, TrapRecord, NotifyName, ContextName,
+ Recv, Varbinds, ExtraInfo}, S) ->
+ ?vlog("[handle_info] forward trap request:"
+ "~n TrapRecord: ~p"
+ "~n NotifyName: ~p"
+ "~n ContextName: ~p"
+ "~n Recv: ~p"
+ "~n Varbinds: ~p",
+ [TrapRecord, NotifyName, ContextName, Recv, Varbinds]),
+ LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID,
+ case (catch maybe_send_trap(S, TrapRecord, NotifyName, ContextName,
+ Recv, Varbinds, LocalEngineID, ExtraInfo)) of
+ {ok, NewS} ->
+ {noreply, NewS};
+ {'EXIT', R} ->
+ ?vinfo("Trap not sent:~n ~p", [R]),
+ {noreply, S};
+ _ ->
+ {noreply, S}
+ end;
+
+%% <BACKWARD-COMPAT>
+handle_info({forward_trap, TrapRecord, NotifyName, ContextName,
Recv, Varbinds}, S) ->
?vlog("[handle_info] forward trap request:"
"~n TrapRecord: ~p"
@@ -795,9 +898,10 @@ handle_info({forward_trap, TrapRecord, NotifyName, ContextName,
"~n Recv: ~p"
"~n Varbinds: ~p",
[TrapRecord, NotifyName, ContextName, Recv, Varbinds]),
+ ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID,
case (catch maybe_send_trap(S, TrapRecord, NotifyName, ContextName,
- Recv, Varbinds, LocalEngineID)) of
+ Recv, Varbinds, LocalEngineID, ExtraInfo)) of
{ok, NewS} ->
{noreply, NewS};
{'EXIT', R} ->
@@ -806,6 +910,7 @@ handle_info({forward_trap, TrapRecord, NotifyName, ContextName,
_ ->
{noreply, S}
end;
+%% </BACKWARD-COMPAT>
handle_info({backup_done, Reply}, #state{backup = {_, From}} = S) ->
?vlog("[handle_info] backup done:"
@@ -908,6 +1013,23 @@ handle_call(restart_set_worker, _From, #state{set_worker = Pid} = S) ->
end,
{reply, ok, S};
+handle_call({send_notif, Notification, SendOpts}, _From, S) ->
+ ?vlog("[handle_info] send trap request:"
+ "~n Notification: ~p"
+ "~n SendOpts: ~p",
+ [Notification, SendOpts]),
+ case (catch handle_send_trap(call, S, Notification, SendOpts)) of
+ {ok, NewS} ->
+ {reply, ok, NewS};
+ {'EXIT', Reason} ->
+ ?vinfo("Trap not sent:~n ~p", [Reason]),
+ {reply, {error, {send_failed, Reason}}, S};
+ _ ->
+ ?vinfo("Trap not sent", []),
+ {reply, {error, send_failed}, S}
+ end;
+
+%% <BACKWARD-COMPAT>
handle_call({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds},
_From, S) ->
?vlog("[handle_call] send trap request:"
@@ -917,19 +1039,20 @@ handle_call({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds},
"~n Recv: ~p"
"~n Varbinds: ~p",
[Trap, NotifyName, ContextName, Recv, Varbinds]),
+ ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
LocalEngineID =
case S#state.type of
master_agent ->
?DEFAULT_LOCAL_ENGINE_ID;
_ ->
%% subagent -
- %% we don't need this, eventually the trap sent request
- %% will reach the master-agent and then it will look up
- %% the proper engine id.
+ %% we don't need this now, eventually the trap send
+ %% request will reach the master-agent and then it
+ %% will look up the proper engine id.
ignore
end,
case (catch handle_send_trap(S, Trap, NotifyName, ContextName,
- Recv, Varbinds, LocalEngineID)) of
+ Recv, Varbinds, LocalEngineID, ExtraInfo)) of
{ok, NewS} ->
{reply, ok, NewS};
{'EXIT', Reason} ->
@@ -951,8 +1074,9 @@ handle_call({send_trap, Trap, NotifyName,
"~n Varbinds: ~p"
"~n LocalEngineID: ~p",
[Trap, NotifyName, ContextName, Recv, Varbinds, LocalEngineID]),
+ ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
case (catch handle_send_trap(S, Trap, NotifyName, ContextName,
- Recv, Varbinds, LocalEngineID)) of
+ Recv, Varbinds, LocalEngineID, ExtraInfo)) of
{ok, NewS} ->
{reply, ok, NewS};
{'EXIT', Reason} ->
@@ -962,6 +1086,7 @@ handle_call({send_trap, Trap, NotifyName,
?vinfo("Trap not sent", []),
{reply, {error, send_failed}, S}
end;
+%% </BACKWARD-COMPAT>
handle_call({discovery,
TargetName, Notification, ContextName, Vbs, DiscoHandler,
@@ -1470,7 +1595,10 @@ handle_backup_res([{Who, Crap}|Results], Acc) ->
%% because we (for some reason) support the function
%% snmpa:current_community().
%%-----------------------------------------------------------------
-cheat({community, _SecModel, Community, _IpUdp}, Address, ContextName) ->
+cheat({community, SecModel, Community, _TAddress}, Address, ContextName) ->
+ {Community, Address, ContextName};
+cheat({community, _SecModel, Community, _TDomain, _TAddress},
+ Address, ContextName) ->
{Community, Address, ContextName};
cheat(_, Address, ContextName) ->
{"", Address, ContextName}.
@@ -1498,7 +1626,7 @@ invalidate_ca_cache() ->
MasterAgent ! invalidate_ca_cache;
false ->
%% This is running on a sub-agent node,
- %% so sent skip it
+ %% so skip it
ok
end;
_ -> % Not on this node
@@ -1523,19 +1651,24 @@ spawn_thread(Vsn, Pdu, PduMS, ACMData, Address, Extra) ->
proc_lib:spawn_link(?MODULE, handle_pdu, Args).
spawn_trap_thread(TrapRec, NotifyName, ContextName, Recv, Vbs,
- LocalEngineID) ->
+ LocalEngineID, ExtraInfo) ->
Dict = get(),
proc_lib:spawn_link(?MODULE, do_send_trap,
[TrapRec, NotifyName, ContextName,
- Recv, Vbs, LocalEngineID, Dict]).
+ Recv, Vbs, LocalEngineID, ExtraInfo, Dict]).
do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs,
LocalEngineID, Dict) ->
+ ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
+ do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs,
+ LocalEngineID, ExtraInfo, Dict).
+do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs,
+ LocalEngineID, ExtraInfo, Dict) ->
lists:foreach(fun({Key, Val}) -> put(Key, Val) end, Dict),
put(sname,trap_sender_short_name(get(sname))),
?vlog("starting",[]),
snmpa_trap:send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs,
- LocalEngineID, get(net_if)).
+ LocalEngineID, ExtraInfo, get(net_if)).
worker(Master, Dict) ->
lists:foreach(fun({Key, Val}) -> put(Key, Val) end, Dict),
@@ -1550,21 +1683,34 @@ worker_loop(Master) ->
handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, Extra),
Master ! worker_available;
- %% We don't trap exits!
+ %% We don't trap EXITs!
{TrapRec, NotifyName, ContextName, Recv, Vbs} ->
?vtrace("worker_loop -> send trap:"
"~n ~p", [TrapRec]),
snmpa_trap:send_trap(TrapRec, NotifyName,
- ContextName, Recv, Vbs, get(net_if)),
+ ContextName, Recv, Vbs,
+ ?DEFAULT_NOTIF_EXTRA_INFO,
+ get(net_if)),
Master ! worker_available;
- %% We don't trap exits!
+ %% We don't trap EXITs!
{send_trap,
TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID} ->
?vtrace("worker_loop -> send trap:"
"~n ~p", [TrapRec]),
snmpa_trap:send_trap(TrapRec, NotifyName,
- ContextName, Recv, Vbs, LocalEngineID,
+ ContextName, Recv, Vbs,
+ LocalEngineID, ?DEFAULT_NOTIF_EXTRA_INFO,
+ get(net_if)),
+ Master ! worker_available;
+
+ {send_trap,
+ TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID, ExtraInfo} ->
+ ?vtrace("worker_loop -> send trap:"
+ "~n ~p", [TrapRec]),
+ snmpa_trap:send_trap(TrapRec, NotifyName,
+ ContextName, Recv, Vbs,
+ LocalEngineID, ExtraInfo,
get(net_if)),
Master ! worker_available;
@@ -1713,34 +1859,79 @@ handle_acm_error(Vsn, Reason, Pdu, ACMData, Address, Extra) ->
ok
end.
+get_opt(Key, Default, SendOpts) ->
+ case lists:keysearch(Key, 1, SendOpts) of
+ {value, {Key, Value}} ->
+ Value;
+ false ->
+ Default
+ end.
-handle_send_trap(S, TrapName, NotifyName, ContextName, Recv, Varbinds,
- LocalEngineID) ->
+handle_send_trap(call, #state{type = master_agent} = S,
+ Notification, SendOpts) ->
+ SendOpts2 =
+ case lists:keymember(local_engine_id, 1, SendOpts) of
+ true ->
+ SendOpts;
+ false ->
+ [{local_engine_id, ?DEFAULT_LOCAL_ENGINE_ID}|SendOpts]
+ end,
+ handle_send_trap(S, Notification, SendOpts2);
+handle_send_trap(call, S, Notification, SendOpts) ->
+ SendOpts2 =
+ case lists:keymember(local_engine_id, 1, SendOpts) of
+ true ->
+ SendOpts;
+ false ->
+ %% subagent -
+ %% we don't need this now, eventually the trap send
+ %% request will reach the master-agent and then it
+ %% will look up the proper engine id.
+ [{local_engine_id, ignore}|SendOpts]
+ end,
+ handle_send_trap(S, Notification, SendOpts2);
+handle_send_trap(_, S, Notification, SendOpts) ->
+ handle_send_trap(S, Notification, SendOpts).
+
+handle_send_trap(S, Notification, SendOpts) ->
+ NotifyName = get_opt(name, "", SendOpts),
+ ContextName = get_opt(context, "", SendOpts),
+ Recv = get_opt(receiver, no_receiver, SendOpts),
+ Varbinds = get_opt(varbinds, [], SendOpts),
+ ExtraInfo = get_opt(extra, ?DEFAULT_NOTIF_EXTRA_INFO, SendOpts),
+ LocalEngineID =
+ get_opt(local_engine_id, ?DEFAULT_LOCAL_ENGINE_ID, SendOpts),
+ handle_send_trap(S, Notification, NotifyName, ContextName, Recv, Varbinds,
+ LocalEngineID, ExtraInfo).
+
+handle_send_trap(#state{type = Type} = S,
+ Notification, NotifyName, ContextName, Recv, Varbinds,
+ LocalEngineID, ExtraInfo) ->
?vtrace("handle_send_trap -> entry with"
- "~n S#state.type: ~p"
+ "~n Agent type: ~p"
"~n TrapName: ~p"
"~n NotifyName: ~p"
"~n ContextName: ~p"
"~n LocalEngineID: ~p",
- [S#state.type, TrapName, NotifyName, ContextName, LocalEngineID]),
- case snmpa_trap:construct_trap(TrapName, Varbinds) of
+ [Type, Notification, NotifyName, ContextName, LocalEngineID]),
+ case snmpa_trap:construct_trap(Notification, Varbinds) of
{ok, TrapRecord, VarList} ->
?vtrace("handle_send_trap -> construction complete: "
"~n TrapRecord: ~p"
"~n VarList: ~p",
[TrapRecord, VarList]),
- case S#state.type of
+ case Type of
subagent ->
?vtrace("handle_send_trap -> [sub] forward trap",[]),
maybe_forward_trap(S, TrapRecord, NotifyName,
- ContextName, Recv, VarList),
+ ContextName, Recv, VarList, ExtraInfo),
{ok, S};
master_agent ->
?vtrace("handle_send_trap -> "
"[master] handle send trap",[]),
maybe_send_trap(S, TrapRecord, NotifyName,
ContextName, Recv, VarList,
- LocalEngineID)
+ LocalEngineID, ExtraInfo)
end;
error ->
error
@@ -1748,7 +1939,7 @@ handle_send_trap(S, TrapName, NotifyName, ContextName, Recv, Varbinds,
maybe_forward_trap(#state{parent = Parent, nfilters = NFs} = S,
- TrapRec, NotifyName, ContextName, Recv, V) ->
+ TrapRec, NotifyName, ContextName, Recv, V, ExtraInfo) ->
?vtrace("maybe_forward_trap -> entry with"
"~n NFs: ~p", [NFs]),
case filter_notification(NFs, [], TrapRec) of
@@ -1764,13 +1955,15 @@ maybe_forward_trap(#state{parent = Parent, nfilters = NFs} = S,
{send, [], TrapRec2} ->
?vtrace("maybe_forward_trap -> forward trap:"
"~n ~p", [TrapRec2]),
- forward_trap(Parent, TrapRec2, NotifyName, ContextName, Recv, V),
+ forward_trap(Parent, TrapRec2, NotifyName, ContextName, Recv, V,
+ ExtraInfo),
{ok, S};
{send, Removed, TrapRec2} ->
?vtrace("maybe_forward_trap -> forward trap:"
"~n ~p", [TrapRec2]),
- forward_trap(Parent, TrapRec2, NotifyName, ContextName, Recv, V),
+ forward_trap(Parent, TrapRec2, NotifyName, ContextName, Recv, V,
+ ExtraInfo),
NFs2 = del_notification_filter(Removed, NFs),
{ok, S#state{nfilters = NFs2}}
end.
@@ -1778,7 +1971,7 @@ maybe_forward_trap(#state{parent = Parent, nfilters = NFs} = S,
maybe_send_trap(#state{nfilters = NFs} = S,
TrapRec, NotifyName, ContextName, Recv, Varbinds,
- LocalEngineID) ->
+ LocalEngineID, ExtraInfo) ->
?vtrace("maybe_send_trap -> entry with"
"~n NFs: ~p", [NFs]),
case filter_notification(NFs, [], TrapRec) of
@@ -1796,7 +1989,7 @@ maybe_send_trap(#state{nfilters = NFs} = S,
"~n ~p", [TrapRec2]),
do_handle_send_trap(S, TrapRec2,
NotifyName, ContextName, Recv, Varbinds,
- LocalEngineID);
+ LocalEngineID, ExtraInfo);
{send, Removed, TrapRec2} ->
?vtrace("maybe_send_trap -> send trap:"
@@ -1804,36 +1997,37 @@ maybe_send_trap(#state{nfilters = NFs} = S,
NFs2 = del_notification_filter(Removed, NFs),
do_handle_send_trap(S#state{nfilters = NFs2}, TrapRec2,
NotifyName, ContextName, Recv, Varbinds,
- LocalEngineID)
+ LocalEngineID, ExtraInfo)
end.
do_handle_send_trap(S, TrapRec, NotifyName, ContextName, Recv, Varbinds,
- LocalEngineID) ->
+ LocalEngineID, ExtraInfo) ->
Vbs = snmpa_trap:try_initialise_vars(get(mibserver), Varbinds),
case S#state.type of
subagent ->
forward_trap(S#state.parent, TrapRec, NotifyName, ContextName,
- Recv, Vbs),
+ Recv, Vbs, ExtraInfo),
{ok, S};
master_agent when S#state.multi_threaded =:= false ->
?vtrace("do_handle_send_trap -> send trap:"
"~n ~p", [TrapRec]),
snmpa_trap:send_trap(TrapRec, NotifyName, ContextName,
- Recv, Vbs, LocalEngineID, get(net_if)),
+ Recv, Vbs, LocalEngineID, ExtraInfo,
+ get(net_if)),
{ok, S};
master_agent when S#state.worker_state =:= busy ->
%% Main worker busy => create new worker
?vtrace("do_handle_send_trap -> main worker busy: "
"spawn a trap sender", []),
spawn_trap_thread(TrapRec, NotifyName, ContextName, Recv, Vbs,
- LocalEngineID),
+ LocalEngineID, ExtraInfo),
{ok, S};
master_agent ->
%% Send to main worker
?vtrace("do_handle_send_trap -> send to main worker",[]),
S#state.worker ! {send_trap,
TrapRec, NotifyName, ContextName, Recv, Vbs,
- LocalEngineID},
+ LocalEngineID, ExtraInfo},
{ok, S#state{worker_state = busy}}
end.
@@ -1932,7 +2126,7 @@ send_discovery(S, From,
TargetName, Record, ContextName, InitVars,
DiscoHandler, ExtraInfo) ->
case snmpa_trap:send_discovery(TargetName, Record, ContextName,
- InitVars, get(net_if)) of
+ InitVars, get(net_if), ExtraInfo) of
{ok, Sender, SecLevel} ->
Disco = #disco{from = From,
rec = Record,
@@ -2009,9 +2203,12 @@ handle_discovery_response(#state{disco = #disco{target = TargetName,
#disco{rec = Record,
ctx = ContextName,
ivbs = InitVars} = Disco,
- case snmpa_trap:send_discovery(TargetName, Record,
+ case snmpa_trap:send_discovery(TargetName,
+ Record,
ContextName,
- InitVars, get(net_if)) of
+ InitVars,
+ get(net_if),
+ ExtraInfo) of
{ok, Sender, _SecLevel} ->
?vdebug("handle_discovery_response(1) -> "
"stage 2 trap sent", []),
@@ -3971,6 +4168,14 @@ user_err(F, A) ->
%% ---------------------------------------------------------------------
+maybe_call(Server, Req) ->
+ case (wis(Server) =:= self()) of
+ false ->
+ call(Server, Req);
+ true ->
+ Server ! Req
+ end.
+
call(Server, Req) ->
gen_server:call(Server, Req, infinity).
diff --git a/lib/snmp/src/agent/snmpa_authentication_service.erl b/lib/snmp/src/agent/snmpa_authentication_service.erl
index 572fab7fbf..b5ff8460c6 100644
--- a/lib/snmp/src/agent/snmpa_authentication_service.erl
+++ b/lib/snmp/src/agent/snmpa_authentication_service.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The 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,11 +29,12 @@ behaviour_info(_) ->
%%-----------------------------------------------------------------
%% init_check_access(Pdu, ACMData)
%% Pdu = #pdu
-%% ACMData = acm_data() = {community, Community, Address} |
-%% {v3, MsgID, SecModel, SecName, SecLevel,
-%% ContextEngineID, ContextName, SecData}
+%% ACMData = acm_data() = {community, SecModel, Community, TDomain, TAddress} |
+%% {v3, MsgID, SecModel, SecName, SecLevel,
+%% ContextEngineID, ContextName, SecData}
%% Community = string()
-%% Address = ip() ++ udp() (list)
+%% TDomain = ?transportDomainUdpIpv4 | ?transportDomainUdpIpv6
+%% TAddress = ip() ++ udp() (list)
%% MsgID = integer() <not used>
%% SecModel = ?SEC_* (see snmp_types.hrl)
%% SecName = string()
diff --git a/lib/snmp/src/agent/snmpa_conf.erl b/lib/snmp/src/agent/snmpa_conf.erl
index b4fc716b3e..c17a6abbd7 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-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -48,7 +48,7 @@
%% target_addr.conf
target_addr_entry/5, target_addr_entry/6,
- target_addr_entry/8, target_addr_entry/10,
+ target_addr_entry/8, target_addr_entry/10, target_addr_entry/11,
write_target_addr_config/2, write_target_addr_config/3,
append_target_addr_config/2,
read_target_addr_config/1,
@@ -424,7 +424,8 @@ target_addr_entry(Name,
EngineId,
TMask) ->
target_addr_entry(Name, Ip, 162, TagList,
- ParamsName, EngineId, TMask, 2048).
+ ParamsName, EngineId,
+ TMask, 2048).
target_addr_entry(Name,
Ip,
@@ -435,7 +436,8 @@ target_addr_entry(Name,
TMask,
MaxMessageSize) ->
target_addr_entry(Name, Ip, Udp, 1500, 3, TagList,
- ParamsName, EngineId, TMask, MaxMessageSize).
+ ParamsName, EngineId,
+ TMask, MaxMessageSize).
target_addr_entry(Name,
Ip,
@@ -447,7 +449,24 @@ target_addr_entry(Name,
EngineId,
TMask,
MaxMessageSize) ->
+ target_addr_entry(Name, snmp_target_mib:default_domain(), Ip, Udp,
+ Timeout, RetryCount, TagList,
+ ParamsName, EngineId,
+ TMask, MaxMessageSize).
+
+target_addr_entry(Name,
+ Domain,
+ Ip,
+ Udp,
+ Timeout,
+ RetryCount,
+ TagList,
+ ParamsName,
+ EngineId,
+ TMask,
+ MaxMessageSize) ->
{Name,
+ Domain,
Ip,
Udp,
Timeout,
@@ -465,9 +484,13 @@ write_target_addr_config(Dir, Conf) ->
"%% The data is inserted into the snmpTargetAddrTable defined\n"
"%% in SNMP-TARGET-MIB, and in the snmpTargetAddrExtTable defined\n"
"%% in SNMP-COMMUNITY-MIB.\n"
-"%% Each row is a 10-tuple:\n"
-"%% {Name, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId,\n"
-"%% TMask, MaxMessageSize}.\n"
+"%% Each row is a 10 or 11-tuple (Domain is optional):\n"
+"%% {Name, \n"
+"%% Domain, Ip, Port, \n"
+"%% Timeout, RetryCount, TagList, ParamsName, EngineId,\n"
+"%% TMask, MaxMessageSize}.\n"
+"%% The value of Domain decide the format of the Ip and TMask values. \n"
+"%% If not present, classic Ipv4 is assumed. \n"
"%% The EngineId value is only used if Inform-Requests are sent to this\n"
"%% target. If Informs are not sent, this value is ignored, and can be\n"
"%% e.g. an empty string. However, if Informs are sent, it is essential\n"
@@ -521,16 +544,31 @@ write_target_addr_conf(Fd, Hdr, Conf) ->
write_target_addr_conf(Fd, Conf) ->
Fun = fun(Entry) -> do_write_target_addr_conf(Fd, Entry) end,
- lists:foreach(Fun, Conf).
+ lists:foreach(Fun, Conf),
+ ok.
do_write_target_addr_conf(Fd,
- {Name, Ip, Udp,
+ {Name,
+ Ip, Udp,
+ Timeout, RetryCount, TagList,
+ ParamsName, EngineId,
+ TMask, MaxMessageSize}) ->
+ Domain = snmp_target_mib:default_domain(),
+ do_write_target_addr_conf(Fd,
+ {Name,
+ Domain, Ip, Udp,
+ Timeout, RetryCount, TagList,
+ ParamsName, EngineId,
+ TMask, MaxMessageSize});
+do_write_target_addr_conf(Fd,
+ {Name,
+ Domain, Ip, Udp,
Timeout, RetryCount, TagList,
ParamsName, EngineId,
TMask, MaxMessageSize}) ->
io:format(Fd,
- "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n",
- [Name, Ip, Udp, Timeout, RetryCount, TagList,
+ "{\"~s\", ~w, ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n",
+ [Name, Domain, Ip, Udp, Timeout, RetryCount, TagList,
ParamsName, EngineId, TMask, MaxMessageSize]);
do_write_target_addr_conf(_Fd, Crap) ->
error({bad_target_addr_config, Crap}).
@@ -546,13 +584,13 @@ target_params_entry(Name, Vsn) ->
target_params_entry(Name, Vsn, SecName, SecLevel).
target_params_entry(Name, Vsn, SecName, SecLevel) ->
- MPModel = if Vsn == v1 -> v1;
- Vsn == v2 -> v2c;
- Vsn == v3 -> v3
+ MPModel = if Vsn =:= v1 -> v1;
+ Vsn =:= v2 -> v2c;
+ Vsn =:= v3 -> v3
end,
- SecModel = if Vsn == v1 -> v1;
- Vsn == v2 -> v2c;
- Vsn == v3 -> usm
+ SecModel = if Vsn =:= v1 -> v1;
+ Vsn =:= v2 -> v2c;
+ Vsn =:= v3 -> usm
end,
target_params_entry(Name, MPModel, SecModel, SecName, SecLevel).
diff --git a/lib/snmp/src/agent/snmpa_internal.hrl b/lib/snmp/src/agent/snmpa_internal.hrl
index 9fa874f119..a490a78f84 100644
--- a/lib/snmp/src/agent/snmpa_internal.hrl
+++ b/lib/snmp/src/agent/snmpa_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
%%
%% The 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,7 @@
-include_lib("snmp/src/app/snmp_internal.hrl").
-define(DEFAULT_LOCAL_ENGINE_ID, snmp_framework_mib:get_engine_id()).
+-define(DEFAULT_NOTIF_EXTRA_INFO, {snmpa_default_notification_extra_info}).
-define(snmpa_info(F, A), ?snmp_info("agent", F, A)).
-define(snmpa_warning(F, A), ?snmp_warning("agent", F, A)).
diff --git a/lib/snmp/src/agent/snmpa_mpd.erl b/lib/snmp/src/agent/snmpa_mpd.erl
index fd75b98f84..4f50b1a674 100644
--- a/lib/snmp/src/agent/snmpa_mpd.erl
+++ b/lib/snmp/src/agent/snmpa_mpd.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The 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,6 +32,7 @@
-include("SNMP-MPD-MIB.hrl").
-include("SNMPv2-TM.hrl").
-include("SNMP-FRAMEWORK-MIB.hrl").
+-include("TRANSPORT-ADDRESS-MIB.hrl").
-define(VMODULE,"MPD").
-include("snmp_verbosity.hrl").
@@ -115,8 +116,8 @@ reset() ->
%% Func: process_packet(Packet, TDomain, TAddress, State, Log) ->
%% {ok, SnmpVsn, Pdu, PduMS, ACMData} | {discarded, Reason}
%% Types: Packet = binary()
-%% TDomain = snmpUDPDomain | atom()
-%% TAddress = {Ip, Udp}
+%% TDomain = snmpUDPDomain | transportDomain()
+%% TAddress = {Ip, Udp} (*but* depends on TDomain)
%% State = #state
%% Purpose: This is the main Message Dispatching function. (see
%% section 4.2.1 in rfc2272)
@@ -182,24 +183,30 @@ discarded_pdu(Variable) -> inc(Variable).
%%-----------------------------------------------------------------
%% Handles a Community based message (v1 or v2c).
%%-----------------------------------------------------------------
-v1_v2c_proc(Vsn, NoteStore, Community, snmpUDPDomain,
+v1_v2c_proc(Vsn, NoteStore, Community, Domain,
{Ip, Udp}, LocalEngineID,
Data, HS, Log, Packet) ->
- TAddress = tuple_to_list(Ip) ++ [Udp div 256, Udp rem 256],
- AgentMS = get_engine_max_message_size(LocalEngineID),
- MgrMS = snmp_community_mib:get_target_addr_ext_mms(?snmpUDPDomain,
- TAddress),
- PduMS = case MgrMS of
- {ok, MMS} when MMS < AgentMS -> MMS - HS;
- _ -> AgentMS - HS
- end,
+ TDomain = snmp_conf:mk_tdomain(Domain),
+ TAddress = snmp_conf:mk_taddress(Domain, Ip, Udp),
+ AgentMS = get_engine_max_message_size(LocalEngineID),
+ MgrMS = snmp_community_mib:get_target_addr_ext_mms(TDomain, TAddress),
+ PduMS = case MgrMS of
+ {ok, MMS} when MMS < AgentMS -> MMS - HS;
+ _ -> AgentMS - HS
+ end,
case (catch snmp_pdus:dec_pdu(Data)) of
Pdu when is_record(Pdu, pdu) ->
Log(Pdu#pdu.type, Packet),
inc_snmp_in_vars(Pdu),
#pdu{request_id = ReqId} = Pdu,
- OkRes = {ok, Vsn, Pdu, PduMS,
- {community, sec_model(Vsn), Community, TAddress}},
+
+ %% <TDomain>
+ %% We have added TDomain, what are the consequences?
+ ACMData =
+ {community, sec_model(Vsn), Community, TDomain, TAddress},
+ OkRes = {ok, Vsn, Pdu, PduMS, ACMData},
+ %% </TDomain>
+
%% Make sure that we don't process duplicate SET request
%% twice. We don't know what could happen in that case.
%% The mgr does, so he has to generate a new SET request.
@@ -216,8 +223,6 @@ v1_v2c_proc(Vsn, NoteStore, Community, snmpUDPDomain,
snmp_note_store:set_note(NoteStore,
100, Key, true),
%% Uses ACMData that snmpa_acm knows of.
- %% snmpUDPDomain is implicit, since that's the only
- %% one we handle.
OkRes;
true ->
{discarded, duplicate_pdu}
@@ -275,12 +280,12 @@ v3_proc(NoteStore, Packet, LocalEngineID, V3Hdr, Data, Log) ->
"~n msgSecurityParameters = ~w",
[MsgID, MMS, MsgFlags, MsgSecurityModel, SecParams]),
%% 7.2.4
- SecModule = get_security_module(MsgSecurityModel),
+ SecModule = get_security_module(MsgSecurityModel),
%% 7.2.5
- SecLevel = check_sec_level(MsgFlags),
+ SecLevel = check_sec_level(MsgFlags),
IsReportable = snmp_misc:is_reportable(MsgFlags),
%% 7.2.6
- ?vtrace("v3_proc -> [7.2.6]"
+ ?vtrace("v3_proc -> [7.2.4-7.2.6]"
"~n SecModule = ~p"
"~n SecLevel = ~p"
"~n IsReportable = ~p",
@@ -531,7 +536,7 @@ check_sec_module_result(Res, V3Hdr, Data, LocalEngineID, IsReportable, Log) ->
?vdebug("security module result [7.2.6-b]:"
"~n Reason: ~p", [Reason]),
throw({discarded, {securityError, Reason}});
- {error, Reason, ErrorInfo} when IsReportable == true -> % case 7.2.6 a
+ {error, Reason, ErrorInfo} when IsReportable =:= true -> % case 7.2.6 a
?vdebug("security module result when reportable [7.2.6-a]:"
"~n Reason: ~p"
"~n ErrorInfo: ~p", [Reason, ErrorInfo]),
@@ -574,7 +579,7 @@ generate_response_msg(Vsn, RePdu, Type, ACMData, LocalEngineID, Log) ->
generate_response_msg(Vsn, RePdu, Type, ACMData, LocalEngineID, Log, 1).
generate_response_msg(Vsn, RePdu, Type,
- {community, _SecModel, Community, _IpUdp},
+ {community, _SecModel, Community, _TDomain, _TAddress},
LocalEngineID,
Log, _) ->
case catch snmp_pdus:enc_pdu(RePdu) of
@@ -977,12 +982,15 @@ generate_discovery_msg2(NoteStore, Pdu,
discovery_note_timeout(Timeout) ->
(Timeout div 100) + 1.
-generate_discovery_msg(NoteStore, {?snmpUDPDomain, [A,B,C,D,U1,U2]},
+generate_discovery_msg(NoteStore, {TDomain, TAddress},
Pdu, ScopedPduBytes,
ContextEngineID, ManagerEngineID,
SecModel, SecName, SecLevelFlag,
InitialUserName,
ContextName, Timeout) ->
+
+ {ok, {_Domain, Address}} = transform_taddr(TDomain, TAddress),
+
%% 7.1.7
?vdebug("generate_discovery_msg -> 7.1.7 (~w)", [ManagerEngineID]),
MsgID = generate_msg_id(),
@@ -1023,7 +1031,7 @@ generate_discovery_msg(NoteStore, {?snmpUDPDomain, [A,B,C,D,U1,U2]},
%% Log(Packet),
inc_snmp_out_vars(Pdu),
?vdebug("generate_discovery_msg -> done", []),
- {Packet, {{A,B,C,D}, U1 bsl 8 + U2}};
+ {Packet, Address};
Error ->
throw(Error)
@@ -1053,6 +1061,34 @@ generate_sec_discovery_msg(Message, SecModule,
end.
+transform_taddr(?snmpUDPDomain, TAddress) ->
+ transform_taddr(?transportDomainUdpIpv4, TAddress);
+transform_taddr(?transportDomainUdpIpv4, [A, B, C, D, P1, P2]) ->
+ Domain = transportDomainUdpIpv4,
+ Addr = {A,B,C,D},
+ Port = P1 bsl 8 + P2,
+ Address = {Addr, Port},
+ {ok, {Domain, Address}};
+transform_taddr(?transportDomainUdpIpv4, BadAddr) ->
+ {error, {bad_transportDomainUdpIpv4_address, BadAddr}};
+transform_taddr(?transportDomainUdpIpv6,
+ [A1, A2, A3, A4, A5, A6, A7, A8, P1, P2]) ->
+ Domain = transportDomainUdpIpv6,
+ Addr = {A1, A2, A3, A4, A5, A6, A7, A8},
+ Port = P1 bsl 8 + P2,
+ Address = {Addr, Port},
+ {ok, {Domain, Address}};
+transform_taddr(?transportDomainUdpIpv6, BadAddr) ->
+ {error, {bad_transportDomainUdpIpv6_address, BadAddr}};
+transform_taddr(BadTDomain, TAddress) ->
+ case lists:member(BadTDomain, snmp_conf:all_tdomains()) of
+ true ->
+ {error, {unsupported_tdomain, BadTDomain, TAddress}};
+ false ->
+ {error, {unknown_tdomain, BadTDomain, TAddress}}
+ end.
+
+
process_taddrs(Dests) ->
?vtrace("process_taddrs -> entry with"
"~n Dests: ~p", [Dests]),
@@ -1062,46 +1098,44 @@ process_taddrs([], Acc) ->
?vtrace("process_taddrs -> entry when done with"
"~n Acc: ~p", [Acc]),
lists:reverse(Acc);
-
+
%% v3
-process_taddrs([{{?snmpUDPDomain, [A,B,C,D,U1,U2]}, SecData} | T], Acc) ->
+process_taddrs([{{TDomain, TAddress}, SecData} | T], Acc) ->
?vtrace("process_taddrs -> entry when v3 with"
- "~n A: ~p"
- "~n B: ~p"
- "~n C: ~p"
- "~n D: ~p"
- "~n U1: ~p"
- "~n U2: ~p"
- "~n SecData: ~p", [A, B, C, D, U1, U2, SecData]),
- Entry = {{snmpUDPDomain, {{A,B,C,D}, U1 bsl 8 + U2}}, SecData},
- process_taddrs(T, [Entry | Acc]);
-%% Bad v3
-process_taddrs([{{TDomain, TAddr}, _SecData} | T], Acc) ->
- ?vtrace("process_taddrs -> entry when bad v3 with"
- "~n TDomain: ~p"
- "~n TAddr: ~p", [TDomain, TAddr]),
- user_err("Bad TDomain/TAddr: ~w/~w", [TDomain, TAddr]),
- process_taddrs(T, Acc);
+ "~n TDomain: ~p"
+ "~n TAddress: ~p"
+ "~n SecData: ~p", [TDomain, TAddress, SecData]),
+ case transform_taddr(TDomain, TAddress) of
+ {ok, DestAddr} ->
+ ?vtrace("process_taddrs -> transformed: "
+ "~n DestAddr: ~p", [DestAddr]),
+ Entry = {DestAddr, SecData},
+ process_taddrs(T, [Entry | Acc]);
+ {error, Reason} ->
+ ?vinfo("Failed transforming v3 domain and address"
+ "~n Reason: ~p", [Reason]),
+ user_err("Bad TDomain/TAddress: ~w/~w", [TDomain, TAddress]),
+ process_taddrs(T, Acc)
+ end;
%% v1 & v2
-process_taddrs([{?snmpUDPDomain, [A,B,C,D,U1,U2]} | T], Acc) ->
+process_taddrs([{TDomain, TAddress} | T], Acc) ->
?vtrace("process_taddrs -> entry when v1/v2 with"
- "~n A: ~p"
- "~n B: ~p"
- "~n C: ~p"
- "~n D: ~p"
- "~n U1: ~p"
- "~n U2: ~p", [A, B, C, D, U1, U2]),
- Entry = {snmpUDPDomain, {{A,B,C,D}, U1 bsl 8 + U2}},
- process_taddrs(T, [Entry | Acc]);
-%% Bad v1 or v2
-process_taddrs([{TDomain, TAddr} | T], Acc) ->
- ?vtrace("process_taddrs -> entry when bad v1/v2 with"
- "~n TDomain: ~p"
- "~n TAddr: ~p", [TDomain, TAddr]),
- user_err("Bad TDomain/TAddr: ~w/~w", [TDomain, TAddr]),
- process_taddrs(T, Acc);
+ "~n TDomain: ~p"
+ "~n TAddress: ~p", [TDomain, TAddress]),
+ case transform_taddr(TDomain, TAddress) of
+ {ok, DestAddr} ->
+ ?vtrace("process_taddrs -> transformed: "
+ "~n DestAddr: ~p", [DestAddr]),
+ Entry = DestAddr,
+ process_taddrs(T, [Entry | Acc]);
+ {error, Reason} ->
+ ?vinfo("Failed transforming v1/v2 domain and address: "
+ "~n Reason: ~p", [Reason]),
+ user_err("Bad TDomain/TAddress: ~w/~w", [TDomain, TAddress]),
+ process_taddrs(T, Acc)
+ end;
process_taddrs(Crap, Acc) ->
- throw({error, {taddrs_crap, Crap, Acc}}).
+ throw({error, {bad_taddrs, Crap, Acc}}).
mk_v1_v2_packet_list(To, Packet, Len, Pdu) ->
diff --git a/lib/snmp/src/agent/snmpa_net_if.erl b/lib/snmp/src/agent/snmpa_net_if.erl
index 97a7a63dee..79c85a6e4e 100644
--- a/lib/snmp/src/agent/snmpa_net_if.erl
+++ b/lib/snmp/src/agent/snmpa_net_if.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -314,6 +314,14 @@ loop(S) ->
NewS = maybe_handle_send_pdu(S, Vsn, Pdu, MsgData, To, undefined),
loop(NewS);
+ %% We dont use the extra-info at this time, ...
+ {send_pdu, Vsn, Pdu, MsgData, To, _ExtraInfo} ->
+ ?vdebug("send pdu: "
+ "~n Pdu: ~p"
+ "~n To: ~p", [Pdu, To]),
+ NewS = maybe_handle_send_pdu(S, Vsn, Pdu, MsgData, To, undefined),
+ loop(NewS);
+
%% Informs
{send_pdu_req, Vsn, Pdu, MsgData, To, From} ->
?vdebug("send pdu request: "
@@ -324,7 +332,18 @@ loop(S) ->
NewS = maybe_handle_send_pdu(S, Vsn, Pdu, MsgData, To, From),
loop(NewS);
+ %% We dont use the extra-info at this time, ...
+ {send_pdu_req, Vsn, Pdu, MsgData, To, From, _ExtraInfo} ->
+ ?vdebug("send pdu request: "
+ "~n Pdu: ~p"
+ "~n To: ~p"
+ "~n From: ~p",
+ [Pdu, To, toname(From)]),
+ NewS = maybe_handle_send_pdu(S, Vsn, Pdu, MsgData, To, From),
+ loop(NewS);
+
%% Discovery Inform
+ %% <BACKWARD-COMPAT>
{send_discovery, Pdu, MsgData, To, From} ->
?vdebug("received send discovery request: "
"~n Pdu: ~p"
@@ -333,6 +352,18 @@ loop(S) ->
[Pdu, To, toname(From)]),
NewS = handle_send_discovery(S, Pdu, MsgData, To, From),
loop(NewS);
+ %% </BACKWARD-COMPAT>
+
+ %% Discovery Inform
+ {send_discovery, Pdu, MsgData, To, From, ExtraInfo} ->
+ ?vdebug("received send discovery request: "
+ "~n Pdu: ~p"
+ "~n To: ~p"
+ "~n From: ~p"
+ "~n ExtraInfo: ~p",
+ [Pdu, To, toname(From), ExtraInfo]),
+ NewS = handle_send_discovery(S, Pdu, MsgData, To, From),
+ loop(NewS);
{discarded_pdu, _Vsn, ReqId, _ACMData, Variable, _Extra} ->
?vdebug("discard PDU: ~p", [Variable]),
@@ -504,7 +535,6 @@ handle_discovery_response(_Ip, _Port, #pdu{request_id = ReqId} = Pdu,
S
end.
-
handle_recv(#state{usock = Sock,
mpd_state = MpdState,
note_store = NS,
@@ -513,7 +543,9 @@ handle_recv(#state{usock = Sock,
LogF = fun(Type, Data) ->
log(Log, Type, Data, Ip, Port)
end,
- case (catch snmpa_mpd:process_packet(Packet, snmpUDPDomain, {Ip, Port},
+ Domain = snmp_conf:which_domain(Ip), % What the ****...
+ case (catch snmpa_mpd:process_packet(Packet,
+ Domain, {Ip, Port},
MpdState, NS, LogF)) of
{ok, _Vsn, Pdu, _PduMS, {discovery, ManagerEngineId}} ->
handle_discovery_response(Ip, Port, Pdu, ManagerEngineId, S);
@@ -636,7 +668,6 @@ process_taddrs([{{_Domain, AddrAndPort}, _SecData}|T], Acc) ->
process_taddrs([{_Domain, AddrAndPort}|T], Acc) ->
process_taddrs(T, [AddrAndPort|Acc]).
-
merge_taddrs(To1, To2) ->
merge_taddrs(To1, To2, []).
@@ -776,15 +807,49 @@ handle_send_pdu1(#state{log = Log,
usock = Sock,
filter = FilterMod}, Type, Addresses) ->
SendFun =
- fun({snmpUDPDomain, {Ip, Port}, Packet}) when is_binary(Packet) ->
- ?vdebug("sending packet:"
+ fun({snmpUDPDomain, {Ip, Port}, Packet})
+ when is_binary(Packet) ->
+ ?vdebug("[snmpUDPDomain] sending packet:"
+ "~n size: ~p"
+ "~n to: ~p:~p",
+ [sz(Packet), Ip, Port]),
+ maybe_udp_send(FilterMod, Log, Type, Sock, Ip, Port, Packet);
+
+ ({snmpUDPDomain, {Ip, Port}, {Packet, _LogData}})
+ when is_binary(Packet) ->
+ ?vdebug("[snmpUDPDomain] sending encrypted packet:"
+ "~n size: ~p"
+ "~n to: ~p:~p",
+ [sz(Packet), Ip, Port]),
+ maybe_udp_send(FilterMod, Log, Type, Sock, Ip, Port, Packet);
+
+ ({transportDomainUdpIpv4, {Ip, Port}, Packet})
+ when is_binary(Packet) ->
+ ?vdebug("[transportDomainUdpIpv4] sending packet:"
+ "~n size: ~p"
+ "~n to: ~p:~p",
+ [sz(Packet), Ip, Port]),
+ maybe_udp_send(FilterMod, Log, Type, Sock, Ip, Port, Packet);
+
+ ({transportDomainUdpIpv4, {Ip, Port}, {Packet, _LogData}})
+ when is_binary(Packet) ->
+ ?vdebug("[transportDomainUdpIpv4] sending encrypted packet:"
+ "~n size: ~p"
+ "~n to: ~p:~p",
+ [sz(Packet), Ip, Port]),
+ maybe_udp_send(FilterMod, Log, Type, Sock, Ip, Port, Packet);
+
+ ({transportDomainUdpIpv6, {Ip, Port}, Packet})
+ when is_binary(Packet) ->
+ ?vdebug("[transportDomainUdpIpv6] sending packet:"
"~n size: ~p"
"~n to: ~p:~p",
[sz(Packet), Ip, Port]),
maybe_udp_send(FilterMod, Log, Type, Sock, Ip, Port, Packet);
- ({snmpUDPDomain, {Ip, Port}, {Packet, _LogData}}) when is_binary(Packet) ->
- ?vdebug("sending encrypted packet:"
+ ({transportDomainUdpIpv6, {Ip, Port}, {Packet, _LogData}})
+ when is_binary(Packet) ->
+ ?vdebug("[transportDomainUdpIpv6] sending encrypted packet:"
"~n size: ~p"
"~n to: ~p:~p",
[sz(Packet), Ip, Port]),
diff --git a/lib/snmp/src/agent/snmpa_set_lib.erl b/lib/snmp/src/agent/snmpa_set_lib.erl
index 191029f6db..00c77a0cdb 100644
--- a/lib/snmp/src/agent/snmpa_set_lib.erl
+++ b/lib/snmp/src/agent/snmpa_set_lib.erl
@@ -378,15 +378,15 @@ dbg_apply(M,F,A) ->
Res
end,
case Result of
- {'EXIT', {undef, [{M, F, A} | _]}} ->
+ {'EXIT', {undef, [{M, F, A, _} | _]}} ->
{'EXIT', {hook_undef, {M, F, A}}};
- {'EXIT', {function_clause, [{M, F, A} | _]}} ->
+ {'EXIT', {function_clause, [{M, F, A, _} | _]}} ->
{'EXIT', {hook_function_clause, {M, F, A}}};
% XXX: Old format for compatibility
- {'EXIT', {undef, {M, F, A}}} ->
+ {'EXIT', {undef, {M, F, A, _}}} ->
{'EXIT', {hook_undef, {M, F, A}}};
- {'EXIT', {function_clause, {M, F, A}}} ->
+ {'EXIT', {function_clause, {M, F, A, _}}} ->
{'EXIT', {hook_function_clause, {M, F, A}}};
Result ->
diff --git a/lib/snmp/src/agent/snmpa_trap.erl b/lib/snmp/src/agent/snmpa_trap.erl
index 450cb2e9f4..567de020c0 100644
--- a/lib/snmp/src/agent/snmpa_trap.erl
+++ b/lib/snmp/src/agent/snmpa_trap.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,27 +24,34 @@
%% External exports
-export([construct_trap/2,
try_initialise_vars/2,
- send_trap/6, send_trap/7]).
--export([send_discovery/5]).
+ send_trap/6, send_trap/7, send_trap/8]).
+-export([send_discovery/6]).
%% Internal exports
--export([init_v2_inform/9,
- init_v3_inform/9, init_v3_inform/10,
+-export([init_v2_inform/9, init_v2_inform/10,
+ init_v3_inform/9, init_v3_inform/10, init_v3_inform/11,
send_inform/6]).
--export([init_discovery_inform/12, send_discovery_inform/5]).
-
--include("snmp_types.hrl").
--include("snmpa_internal.hrl").
--include("SNMPv2-MIB.hrl").
--include("SNMPv2-TM.hrl").
--include("SNMPv2-TC.hrl").
--include("SNMP-FRAMEWORK-MIB.hrl").
--include("SNMP-TARGET-MIB.hrl").
+-export([init_discovery_inform/13, send_discovery_inform/5]).
+
+%% <BACKWARD-COMPAT>
+-export([send_discovery/5,
+ init_discovery_inform/12]).
+%% </BACKWARD-COMPAT>
+
+-include_lib("snmp/include/snmp_types.hrl").
+-include_lib("snmp/src/agent/snmpa_internal.hrl").
+-include_lib("snmp/include/SNMPv2-MIB.hrl").
+-include_lib("snmp/include/SNMPv2-TM.hrl").
+-include_lib("snmp/include/SNMPv2-TC.hrl").
+-include_lib("snmp/include/SNMP-FRAMEWORK-MIB.hrl").
+-include_lib("snmp/include/SNMP-TARGET-MIB.hrl").
+-include_lib("snmp/include/TRANSPORT-ADDRESS-MIB.hrl").
-define(enterpriseSpecific, 6).
-define(VMODULE,"TRAP").
-include("snmp_verbosity.hrl").
+-include("snmpa_internal.hrl").
%%-----------------------------------------------------------------
@@ -335,25 +342,36 @@ make_varbind_list(Varbinds) ->
%% SnmpTargetAddrTable (using the Tag).
%%-----------------------------------------------------------------
send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, NetIf) ->
+ ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
+ LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID,
+ send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs,
+ LocalEngineID, ExtraInfo, NetIf).
+
+send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, ExtraInfo, NetIf) ->
LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID,
send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs,
- LocalEngineID, NetIf).
+ LocalEngineID, ExtraInfo, NetIf).
-send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID, NetIf) ->
+send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID,
+ ExtraInfo, NetIf) ->
(catch do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs,
- LocalEngineID, NetIf)).
+ LocalEngineID, ExtraInfo, NetIf)).
do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs,
- LocalEngineID, NetIf) ->
+ LocalEngineID, ExtraInfo, NetIf) ->
VarbindList = make_varbind_list(Vbs),
Dests = find_dests(NotifyName),
send_trap_pdus(Dests, ContextName, {TrapRec, VarbindList}, [], [], [],
- Recv, LocalEngineID, NetIf).
+ Recv, LocalEngineID, ExtraInfo, NetIf).
send_discovery(TargetName, Record, ContextName, Vbs, NetIf) ->
+ ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
+ send_discovery(TargetName, Record, ContextName, Vbs, NetIf, ExtraInfo).
+send_discovery(TargetName, Record, ContextName, Vbs, NetIf, ExtraInfo) ->
case find_dest(TargetName) of
{ok, Dest} ->
- send_discovery_pdu(Dest, Record, ContextName, Vbs, NetIf);
+ send_discovery_pdu(Dest, Record, ContextName, Vbs, NetIf,
+ ExtraInfo);
Error ->
Error
end.
@@ -440,11 +458,13 @@ split_variables([]) -> {[], []}.
%% NOTE: This function is executed in the master agent's context
%%-----------------------------------------------------------------
find_dests("") ->
+ ?vtrace("find destinations", []),
snmp_notification_mib:get_targets();
find_dests(NotifyName) ->
+ ?vtrace("find destinations for ~p", [NotifyName]),
case snmp_notification_mib:get_targets(NotifyName) of
[] ->
- ?vlog("No dests found for snmpNotifyName: ~p",[NotifyName]),
+ ?vlog("No dests found for NotifyName: ~p", [NotifyName]),
[];
Dests ->
Dests
@@ -529,7 +549,8 @@ find_dest(TargetName) ->
send_discovery_pdu({Dest, TargetName, {SecModel, SecName, SecLevel},
Timeout, Retry},
- Record, ContextName, Vbs, NetIf) ->
+ Record, ContextName, Vbs, NetIf,
+ ExtraInfo) ->
?vdebug("send_discovery_pdu -> entry with "
"~n Destination address: ~p"
"~n Target name: ~p"
@@ -539,9 +560,10 @@ send_discovery_pdu({Dest, TargetName, {SecModel, SecName, SecLevel},
"~n Timeout: ~p"
"~n Retry: ~p"
"~n Record: ~p"
- "~n ContextName: ~p",
+ "~n ContextName: ~p"
+ "~n ExtraInfo: ~p",
[Dest, TargetName, SecModel, SecName, SecLevel,
- Timeout, Retry, Record, ContextName]),
+ Timeout, Retry, Record, ContextName, ExtraInfo]),
case get_mib_view(SecModel, SecName, SecLevel, ContextName) of
{ok, MibView} ->
case check_all_varbinds(Record, Vbs, MibView) of
@@ -551,7 +573,7 @@ send_discovery_pdu({Dest, TargetName, {SecModel, SecName, SecLevel},
SecModel, SecName, SecLevel,
TargetName, ContextName,
Timeout, Retry,
- SysUpTime, NetIf);
+ SysUpTime, NetIf, ExtraInfo);
false ->
{error, {mibview_validation_failed, Vbs, MibView}}
end;
@@ -561,7 +583,7 @@ send_discovery_pdu({Dest, TargetName, {SecModel, SecName, SecLevel},
send_discovery_pdu(Record, Dest, Vbs,
SecModel, SecName, SecLevel, TargetName,
- ContextName, Timeout, Retry, SysUpTime, NetIf) ->
+ ContextName, Timeout, Retry, SysUpTime, NetIf, ExtraInfo) ->
{_Oid, IVbs} = mk_v2_trap(Record, Vbs, SysUpTime), % v2 refers to SMIv2;
Sender = proc_lib:spawn_link(?MODULE, init_discovery_inform,
[self(),
@@ -570,13 +592,25 @@ send_discovery_pdu(Record, Dest, Vbs,
ContextName,
Timeout, Retry,
IVbs, NetIf,
- get(verbosity)]),
+ get(verbosity),
+ ExtraInfo]),
{ok, Sender, SecLevel}.
init_discovery_inform(Parent,
Dest,
SecModel, SecName, SecLevel, TargetName,
ContextName, Timeout, Retry, Vbs, NetIf, Verbosity) ->
+ ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
+ init_discovery_inform(Parent,
+ Dest,
+ SecModel, SecName, SecLevel, TargetName,
+ ContextName, Timeout, Retry, Vbs, NetIf,
+ Verbosity, ExtraInfo).
+init_discovery_inform(Parent,
+ Dest,
+ SecModel, SecName, SecLevel, TargetName,
+ ContextName, Timeout, Retry, Vbs, NetIf,
+ Verbosity, ExtraInfo) ->
put(verbosity, Verbosity),
put(sname, madis),
Pdu = make_discovery_pdu(Vbs),
@@ -584,7 +618,7 @@ init_discovery_inform(Parent,
SecLevelFlag = mk_flag(SecLevel),
SecData = {SecModel, SecName, SecLevelFlag, TargetName},
MsgData = {SecData, ContextEngineId, ContextName},
- Msg = {send_discovery, Pdu, MsgData, Dest, self()},
+ Msg = {send_discovery, Pdu, MsgData, Dest, self(), ExtraInfo},
?MODULE:send_discovery_inform(Parent, Timeout*10, Retry, Msg, NetIf).
%% note_timeout(Timeout, Retry)
@@ -628,11 +662,11 @@ send_discovery_inform(Parent, Timeout, Retry, Msg, NetIf) ->
%% should be used for the target, and determine the message
%% specific parameters to be used.
%%-----------------------------------------------------------------
-send_trap_pdus([{DestAddr, TargetName, {MpModel, SecModel, SecName, SecLevel},
- Type} | T],
+send_trap_pdus([{DestAddr, TargetName,
+ {MpModel, SecModel, SecName, SecLevel}, Type} | T],
ContextName,
{TrapRec, Vbs}, V1Res, V2Res, V3Res, Recv,
- LocalEngineID, NetIf) ->
+ LocalEngineID, ExtraInfo, NetIf) ->
?vdebug("send trap pdus: "
"~n Destination address: ~p"
"~n Target name: ~p"
@@ -658,13 +692,13 @@ send_trap_pdus([{DestAddr, TargetName, {MpModel, SecModel, SecName, SecLevel},
send_trap_pdus(T, ContextName, {TrapRec, Vbs},
[{DestAddr, Community} | V1Res],
V2Res, V3Res, Recv,
- LocalEngineID, NetIf);
+ LocalEngineID, ExtraInfo, NetIf);
undefined ->
?vdebug("No community found for v1 dest: ~p",
[element(2, DestAddr)]),
send_trap_pdus(T, ContextName, {TrapRec, Vbs},
V1Res, V2Res, V3Res, Recv,
- LocalEngineID, NetIf)
+ LocalEngineID, ExtraInfo, NetIf)
end;
true when MpModel =:= ?MP_V2C ->
?vtrace("send_trap_pdus -> v2c mp model",[]),
@@ -679,13 +713,14 @@ send_trap_pdus([{DestAddr, TargetName, {MpModel, SecModel, SecName, SecLevel},
send_trap_pdus(T, ContextName, {TrapRec, Vbs},
V1Res,
[{DestAddr, Community, Type}|V2Res],
- V3Res, Recv, LocalEngineID, NetIf);
+ V3Res, Recv,
+ LocalEngineID, ExtraInfo, NetIf);
undefined ->
?vdebug("No community found for v2c dest: ~p",
[element(2, DestAddr)]),
send_trap_pdus(T, ContextName, {TrapRec, Vbs},
V1Res, V2Res, V3Res, Recv,
- LocalEngineID, NetIf)
+ LocalEngineID, ExtraInfo, NetIf)
end;
true when MpModel =:= ?MP_V3 ->
?vtrace("send_trap_pdus -> v3 mp model",[]),
@@ -694,20 +729,20 @@ send_trap_pdus([{DestAddr, TargetName, {MpModel, SecModel, SecName, SecLevel},
send_trap_pdus(T, ContextName, {TrapRec, Vbs},
V1Res, V2Res,
[{DestAddr, MsgData, Type} | V3Res],
- Recv, LocalEngineID, NetIf);
+ Recv, LocalEngineID, ExtraInfo, NetIf);
true ->
?vlog("bad MpModel ~p for dest ~p",
[MpModel, element(2, DestAddr)]),
send_trap_pdus(T, ContextName, {TrapRec, Vbs},
V1Res, V2Res, V3Res, Recv,
- LocalEngineID, NetIf);
+ LocalEngineID, ExtraInfo, NetIf);
_ ->
?vlog("no access for dest: "
"~n ~p in target ~p",
[element(2, DestAddr), TargetName]),
send_trap_pdus(T, ContextName, {TrapRec, Vbs},
V1Res, V2Res, V3Res, Recv,
- LocalEngineID, NetIf)
+ LocalEngineID, ExtraInfo, NetIf)
end;
{discarded, Reason} ->
?vlog("mib view error ~p for"
@@ -715,24 +750,27 @@ send_trap_pdus([{DestAddr, TargetName, {MpModel, SecModel, SecName, SecLevel},
"~n SecName: ~w",
[Reason, element(2, DestAddr), SecName]),
send_trap_pdus(T, ContextName, {TrapRec, Vbs},
- V1Res, V2Res, V3Res, Recv, LocalEngineID, NetIf)
+ V1Res, V2Res, V3Res, Recv,
+ LocalEngineID, ExtraInfo, NetIf)
end;
-send_trap_pdus([], ContextName, {TrapRec, Vbs}, V1Res, V2Res, V3Res,
- Recv, LocalEngineID, NetIf) ->
+send_trap_pdus([], ContextName, {TrapRec, Vbs},
+ V1Res, V2Res, V3Res, Recv,
+ LocalEngineID, ExtraInfo,
+ NetIf) ->
SysUpTime = snmp_standard_mib:sys_up_time(),
?vdebug("send trap pdus with sysUpTime ~p", [SysUpTime]),
InformRecvs = get_inform_recvs(V2Res ++ V3Res),
InformTargets = [Addr || {Addr, _, _, _} <- InformRecvs],
deliver_recv(Recv, snmp_targets, InformTargets),
- send_v1_trap(TrapRec, V1Res, Vbs, NetIf, SysUpTime),
- send_v2_trap(TrapRec, V2Res, Vbs, Recv, NetIf, SysUpTime),
- send_v3_trap(TrapRec, V3Res, Vbs, Recv, LocalEngineID, NetIf,
+ send_v1_trap(TrapRec, V1Res, Vbs, ExtraInfo, NetIf, SysUpTime),
+ send_v2_trap(TrapRec, V2Res, Vbs, Recv, ExtraInfo, NetIf, SysUpTime),
+ send_v3_trap(TrapRec, V3Res, Vbs, Recv, LocalEngineID, ExtraInfo, NetIf,
SysUpTime, ContextName).
-send_v1_trap(_TrapRec, [], _Vbs, _NetIf, _SysUpTime) ->
+send_v1_trap(_TrapRec, [], _Vbs, _ExtraInfo, _NetIf, _SysUpTime) ->
ok;
send_v1_trap(#trap{enterpriseoid = Enter, specificcode = Spec},
- V1Res, Vbs, NetIf, SysUpTime) ->
+ V1Res, Vbs, ExtraInfo, NetIf, SysUpTime) ->
?vdebug("prepare to send v1 trap "
"~n '~p'"
"~n with"
@@ -744,9 +782,10 @@ send_v1_trap(#trap{enterpriseoid = Enter, specificcode = Spec},
lists:foreach(fun({Community, Addrs}) ->
?vtrace("send v1 trap pdu to ~p",[Addrs]),
NetIf ! {send_pdu, 'version-1', TrapPdu,
- {community, Community}, Addrs}
+ {community, Community}, Addrs, ExtraInfo}
end, AddrCommunities);
-send_v1_trap(#notification{oid = Oid}, V1Res, Vbs, NetIf, SysUpTime) ->
+send_v1_trap(#notification{oid = Oid}, V1Res, Vbs, ExtraInfo, NetIf,
+ SysUpTime) ->
%% Use alg. in rfc2089 to map a v2 trap to a v1 trap
% delete Counter64 objects from vbs
?vdebug("prepare to send v1 trap '~p'",[Oid]),
@@ -768,31 +807,31 @@ send_v1_trap(#notification{oid = Oid}, V1Res, Vbs, NetIf, SysUpTime) ->
lists:foreach(fun({Community, Addrs}) ->
?vtrace("send v1 trap to ~p",[Addrs]),
NetIf ! {send_pdu, 'version-1', TrapPdu,
- {community, Community}, Addrs}
+ {community, Community}, Addrs, ExtraInfo}
end, AddrCommunities).
-send_v2_trap(_TrapRec, [], _Vbs, _Recv, _NetIf, _SysUpTime) ->
+send_v2_trap(_TrapRec, [], _Vbs, _Recv, _ExtraInfo, _NetIf, _SysUpTime) ->
ok;
-send_v2_trap(TrapRec, V2Res, Vbs, Recv, NetIf, SysUpTime) ->
+send_v2_trap(TrapRec, V2Res, Vbs, Recv, ExtraInfo, NetIf, SysUpTime) ->
?vdebug("prepare to send v2 trap",[]),
{_Oid, IVbs} = mk_v2_trap(TrapRec, Vbs, SysUpTime),
- TrapRecvs = get_trap_recvs(V2Res),
- InformRecvs = get_inform_recvs(V2Res),
- do_send_v2_trap(TrapRecvs, IVbs, NetIf),
- do_send_v2_inform(InformRecvs, IVbs, Recv, NetIf).
+ TrapRecvs = get_trap_recvs(V2Res),
+ InformRecvs = get_inform_recvs(V2Res),
+ do_send_v2_trap(TrapRecvs, IVbs, ExtraInfo, NetIf),
+ do_send_v2_inform(InformRecvs, IVbs, Recv, ExtraInfo, NetIf).
-send_v3_trap(_TrapRec, [], _Vbs, _Recv, _LocalEngineID,
+send_v3_trap(_TrapRec, [], _Vbs, _Recv, _LocalEngineID, _ExtraInfo,
_NetIf, _SysUpTime, _ContextName) ->
ok;
-send_v3_trap(TrapRec, V3Res, Vbs, Recv, LocalEngineID,
+send_v3_trap(TrapRec, V3Res, Vbs, Recv, LocalEngineID, ExtraInfo,
NetIf, SysUpTime, ContextName) ->
?vdebug("prepare to send v3 trap",[]),
{_Oid, IVbs} = mk_v2_trap(TrapRec, Vbs, SysUpTime), % v2 refers to SMIv2;
TrapRecvs = get_trap_recvs(V3Res), % same SMI for v3
InformRecvs = get_inform_recvs(V3Res),
- do_send_v3_trap(TrapRecvs, ContextName, IVbs, NetIf),
+ do_send_v3_trap(TrapRecvs, ContextName, IVbs, ExtraInfo, NetIf),
do_send_v3_inform(InformRecvs, ContextName, IVbs, Recv,
- LocalEngineID, NetIf).
+ LocalEngineID, ExtraInfo, NetIf).
mk_v2_trap(#notification{oid = Oid}, Vbs, SysUpTime) ->
@@ -830,60 +869,70 @@ get_inform_recvs(InformRecvs) ->
[{Addr, MsgData, Timeout, Retry} ||
{Addr, MsgData, {inform, Timeout, Retry}} <- InformRecvs].
-do_send_v2_trap([], _Vbs, _NetIf) ->
+do_send_v2_trap([], _Vbs, _ExtraInfo, _NetIf) ->
ok;
-do_send_v2_trap(Recvs, Vbs, NetIf) ->
+do_send_v2_trap(Recvs, Vbs, ExtraInfo, NetIf) ->
TrapPdu = make_v2_notif_pdu(Vbs, 'snmpv2-trap'),
AddrCommunities = mk_addr_communities(Recvs),
lists:foreach(fun({Community, Addrs}) ->
?vtrace("~n send v2 trap to ~p",[Addrs]),
NetIf ! {send_pdu, 'version-2', TrapPdu,
- {community, Community}, Addrs}
+ {community, Community}, Addrs, ExtraInfo}
end, AddrCommunities),
ok.
-do_send_v2_inform([], _Vbs, _Recv, _NetIf) ->
+do_send_v2_inform([], _Vbs, _Recv, _ExtraInfo, _NetIf) ->
ok;
-do_send_v2_inform(Recvs, Vbs, Recv, NetIf) ->
+do_send_v2_inform(Recvs, Vbs, Recv, ExtraInfo, NetIf) ->
lists:foreach(
fun({Addr, Community, Timeout, Retry}) ->
?vtrace("~n start inform sender to send v2 inform to ~p",
[Addr]),
proc_lib:spawn_link(?MODULE, init_v2_inform,
[Addr, Timeout, Retry, Vbs,
- Recv, NetIf, Community,
+ Recv, ExtraInfo, NetIf, Community,
get(verbosity), get(sname)])
end,
Recvs).
-do_send_v3_trap([], _ContextName, _Vbs, _NetIf) ->
+do_send_v3_trap([], _ContextName, _Vbs, _ExtraInfo, _NetIf) ->
ok;
-do_send_v3_trap(Recvs, ContextName, Vbs, NetIf) ->
+do_send_v3_trap(Recvs, ContextName, Vbs, ExtraInfo, NetIf) ->
TrapPdu = make_v2_notif_pdu(Vbs, 'snmpv2-trap'), % Yes, v2
ContextEngineId = snmp_framework_mib:get_engine_id(),
lists:foreach(fun(Recv) ->
?vtrace("~n send v3 notif to ~p",[Recv]),
NetIf ! {send_pdu, 'version-3', TrapPdu,
- {v3, ContextEngineId, ContextName}, [Recv]}
+ {v3, ContextEngineId, ContextName},
+ [Recv], ExtraInfo}
end, Recvs),
ok.
-do_send_v3_inform([], _ContextName, _Vbs, _Recv, _LocalEngineID, _NetIf) ->
+do_send_v3_inform([], _ContextName, _Vbs, _Recv,
+ _LocalEngineID, _ExtraInfo, _NetIf) ->
ok;
-do_send_v3_inform(Recvs, ContextName, Vbs, Recv, LocalEngineID, NetIf) ->
+do_send_v3_inform(Recvs, ContextName, Vbs, Recv,
+ LocalEngineID, ExtraInfo, NetIf) ->
lists:foreach(
fun({Addr, MsgData, Timeout, Retry}) ->
?vtrace("~n start inform sender to send v3 inform to ~p",
[Addr]),
proc_lib:spawn_link(?MODULE, init_v3_inform,
[{Addr, MsgData}, Timeout, Retry, Vbs,
- Recv, LocalEngineID, NetIf, ContextName,
+ Recv, LocalEngineID, ExtraInfo,
+ NetIf, ContextName,
get(verbosity), get(sname)])
end,
Recvs).
%% New process
-init_v2_inform(Addr, Timeout, Retry, Vbs, Recv, NetIf, Community,V,S) ->
+init_v2_inform(Addr, Timeout, Retry, Vbs, Recv, NetIf, Community, V, S) ->
+ ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
+ init_v2_inform(Addr, Timeout, Retry, Vbs, Recv, ExtraInfo, NetIf,
+ Community, V, S).
+
+init_v2_inform(Addr, Timeout, Retry, Vbs, Recv, ExtraInfo, NetIf,
+ Community, V, S) ->
%% Make a new Inform for each recipient; they need unique
%% request-ids!
put(verbosity,V),
@@ -892,17 +941,26 @@ init_v2_inform(Addr, Timeout, Retry, Vbs, Recv, NetIf, Community,V,S) ->
[Timeout,Retry]),
InformPdu = make_v2_notif_pdu(Vbs, 'inform-request'),
Msg = {send_pdu_req, 'version-2', InformPdu, {community, Community},
- [Addr], self()},
+ [Addr], self(), ExtraInfo},
?MODULE:send_inform(Addr, Timeout*10, Retry, Msg, Recv, NetIf).
%% New process
init_v3_inform(Addr, Timeout, Retry, Vbs, Recv, NetIf, ContextName, V, S) ->
+ ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID,
- init_v3_inform(Addr, Timeout, Retry, Vbs, Recv, LocalEngineID,
+ init_v3_inform(Addr, Timeout, Retry, Vbs, Recv,
+ LocalEngineID, ExtraInfo,
+ NetIf, ContextName, V, S).
+
+init_v3_inform(Addr, Timeout, Retry, Vbs, Recv, LocalEngineID, NetIf,
+ ContextName, V, S) ->
+ ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
+ init_v3_inform(Addr, Timeout, Retry, Vbs, Recv,
+ LocalEngineID, ExtraInfo,
NetIf, ContextName, V, S).
-init_v3_inform(Addr, Timeout, Retry, Vbs, Recv, LocalEngineID,
+init_v3_inform(Addr, Timeout, Retry, Vbs, Recv, LocalEngineID, ExtraInfo,
NetIf, ContextName, V, S) ->
%% Make a new Inform for each recipient; they need unique
%% request-ids!
@@ -913,7 +971,7 @@ init_v3_inform(Addr, Timeout, Retry, Vbs, Recv, LocalEngineID,
InformPdu = make_v2_notif_pdu(Vbs, 'inform-request'), % Yes, v2
ContextEngineId = LocalEngineID,
Msg = {send_pdu_req, 'version-3', InformPdu,
- {v3, ContextEngineId, ContextName}, [Addr], self()},
+ {v3, ContextEngineId, ContextName}, [Addr], self(), ExtraInfo},
?MODULE:send_inform(Addr, Timeout*10, Retry, Msg, Recv, NetIf).
send_inform(Addr, _Timeout, -1, _Msg, Recv, _NetIf) ->
@@ -1001,9 +1059,27 @@ transform_taddr({?snmpUDPDomain, [A1, A2, A3, A4, P1, P2]}) -> % v2
Addr = {A1, A2, A3, A4},
Port = P1 bsl 8 + P2,
{Addr, Port};
+transform_taddr({?transportDomainUdpIpv4, [A1, A2, A3, A4, P1, P2]}) -> % v2
+ Addr = {A1, A2, A3, A4},
+ Port = P1 bsl 8 + P2,
+ {Addr, Port};
+transform_taddr({?transportDomainUdpIpv6,
+ [A1, A2, A3, A4, A5, A6, A7, A8, P1, P2]}) -> % v2
+ Addr = {A1, A2, A3, A4, A5, A6, A7, A8},
+ Port = P1 bsl 8 + P2,
+ {Addr, Port};
transform_taddr({{?snmpUDPDomain, [A1, A2, A3, A4, P1, P2]}, _MsgData}) -> % v3
Addr = {A1, A2, A3, A4},
Port = P1 bsl 8 + P2,
+ {Addr, Port};
+transform_taddr({{?transportDomainUdpIpv4, [A1, A2, A3, A4, P1, P2]}, _MsgData}) -> % v3
+ Addr = {A1, A2, A3, A4},
+ Port = P1 bsl 8 + P2,
+ {Addr, Port};
+transform_taddr({{?transportDomainUdpIpv6,
+ [A1, A2, A3, A4, A5, A6, A7, A8, P1, P2]}, _MsgData}) -> % v3
+ Addr = {A1, A2, A3, A4, A5, A6, A7, A8},
+ Port = P1 bsl 8 + P2,
{Addr, Port}.
@@ -1053,13 +1129,14 @@ mk_addr_communities(Recvs) ->
[{Addr, Comm} | T] = lists:keysort(2, Recvs),
mic(T, Comm, [Addr], []).
-mic([{Addr, Comm} | T], CurComm, AddrList, Res) when Comm == CurComm ->
+mic([{Addr, Comm} | T], CurComm, AddrList, Res) when Comm =:= CurComm ->
mic(T, CurComm, [Addr | AddrList], Res);
mic([{Addr, Comm} | T], CurComm, AddrList, Res) ->
mic(T, Comm, [Addr], [{CurComm, AddrList} | Res]);
mic([], CurComm, AddrList, Res) ->
[{CurComm, AddrList} | Res].
+
%%-----------------------------------------------------------------
%% Convert the SecurityLevel into a flag value used by snmpa_mpd
%%-----------------------------------------------------------------
diff --git a/lib/snmp/src/agent/snmpa_usm.erl b/lib/snmp/src/agent/snmpa_usm.erl
index f35d1f1916..6f54307f9f 100644
--- a/lib/snmp/src/agent/snmpa_usm.erl
+++ b/lib/snmp/src/agent/snmpa_usm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -330,7 +330,6 @@ non_authoritative(SecName,
end
end.
-
is_auth(?usmNoAuthProtocol, _, _, _, SecName, _, _, _, _) -> % 3.2.5
error(usmStatsUnsupportedSecLevels,
?usmStatsUnsupportedSecLevels_instance, SecName); % OTP-5464
@@ -613,8 +612,7 @@ authenticate_outgoing(Message, UsmSecParams,
end,
?vtrace("authenticate_outgoing -> encode message only",[]),
snmp_pdus:enc_message_only(Message2).
-
-
+
%%-----------------------------------------------------------------
%% Auth and priv algorithms
@@ -753,14 +751,19 @@ set_engine_latest_time(SnmpEngineID, EngineTime) ->
%%-----------------------------------------------------------------
%% Utility functions
%%-----------------------------------------------------------------
+-spec error(term()) -> no_return().
error(Reason) ->
throw({error, Reason}).
+-spec error(term(), term()) -> no_return().
error(Reason, ErrorInfo) ->
throw({error, Reason, ErrorInfo}).
+-spec error(term(), term(), term()) -> no_return().
error(Variable, Oid, SecName) ->
error(Variable, Oid, SecName, []).
+
+-spec error(term(), term(), term(), [term()]) -> no_return().
error(Variable, Oid, SecName, Opts) ->
Val = inc(Variable),
ErrorInfo = {#varbind{oid = Oid,
@@ -772,7 +775,6 @@ error(Variable, Oid, SecName, Opts) ->
inc(Name) -> ets:update_counter(snmp_agent_table, Name, 1).
-
get_counter(Name) ->
case (catch ets:lookup(snmp_agent_table, Name)) of
[{_, Val}] ->
@@ -780,8 +782,3 @@ get_counter(Name) ->
_ ->
0
end.
-
-
-
-
-
diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src
index de0e5d6e14..0b6ea93231 100644
--- a/lib/snmp/src/app/snmp.appup.src
+++ b/lib/snmp/src/app/snmp.appup.src
@@ -22,30 +22,92 @@
%% ----- U p g r a d e -------------------------------------------------------
[
- {"4.18",
+ {"4.21",
[
+ {load_module, snmp_target_mib, soft_purge, soft_purge, []}
+ ]
+ },
+ {"4.20.1",
+ [
+ {load_module, snmp_target_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
+ {load_module, snmpm, soft_purge, soft_purge,
+ [snmpm_server, snmpm_config, snmp_config]},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge,
+ [snmp_conf, snmp_config, snmpm_config]},
+ {load_module, snmpa_mpd, soft_purge, soft_purge,
+ [snmp_conf, snmp_config]},
+ {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_config]},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mpd]},
+ {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]},
+ {update, snmpm_server, soft, soft_purge, soft_purge,
+ [snmpm_net_if, snmpm_mpd, snmpm_config]},
+ {update, snmpm_net_if, soft, soft_purge, soft_purge,
+ [snmp_conf, snmpm_mpd, snmpm_config]}
+ ]
+ },
+ {"4.20",
+ [
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_target_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmpm, soft_purge, soft_purge,
+ [snmpm_server, snmpm_config, snmp_config]},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge,
+ [snmp_conf, snmp_config, snmpm_config]},
+ {load_module, snmpa_mpd, soft_purge, soft_purge,
+ [snmp_conf, snmp_config]},
+ {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_config]},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mpd]},
+ {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]},
+ {update, snmpm_server, soft, soft_purge, soft_purge,
+ [snmpm_net_if, snmpm_mpd, snmpm_config]},
+ {update, snmpm_net_if, soft, soft_purge, soft_purge,
+ [snmp_conf, snmpm_mpd, snmpm_config]}
+ ]
+ },
+ {"4.19",
+ [
+ {load_module, snmpa, soft_purge, soft_purge, []},
+ {load_module, snmpm, soft_purge, soft_purge,
+ [snmpm_server, snmpm_config, snmp_config]},
+ {load_module, snmpa_usm, soft_purge, soft_purge, []},
+ {load_module, snmpm_usm, soft_purge, soft_purge, []},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmpa_conf, soft_purge, soft_purge,
+ [snmp_conf, snmp_config]},
{load_module, snmp_misc, soft_purge, soft_purge, []},
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {load_module, snmpa, soft_purge, soft_purge,
- [snmp_community_mib,
- snmp_framework_mib,
- snmp_standard_mib,
- snmp_target_mib,
- snmp_user_based_sm_mib,
- snmp_view_based_acm_mib]},
- {load_module, snmp_community_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_target_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
- [snmpa_mib_lib, snmpa_vacm]},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmpa_mpd, soft_purge, soft_purge,
+ [snmp_conf, snmp_config]},
+ {load_module, snmpm_mpd, soft_purge, soft_purge,
+ [snmp_conf, snmp_config, snmpm_config]},
+ {load_module, snmpa_trap, soft_purge, soft_purge,
+ [snmpa_mpd, snmp_notification_mib, snmp_target_mib, snmpa_net_if]},
+ {load_module, snmpa_acm, soft_purge, soft_purge,
+ [snmp_conf, snmpa_mpd, snmp_target_mib]},
+ {load_module, snmpa_conf, soft_purge, soft_purge,
+ [snmp_config, snmp_notification_mib]},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge,
+ [snmp_conf, snmp_target_mib]},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_target_mib, soft_purge, soft_purge,
+ [snmp_conf]},
+ {update, snmpm_net_if, soft, soft_purge, soft_purge,
+ [snmp_conf, snmpm_mpd, snmpm_config]},
+ {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]},
+ {update, snmpm_server, soft, soft_purge, soft_purge,
+ [snmpm_net_if, snmpm_mpd, snmpm_config]},
+ {update, snmpa_net_if, soft, soft_purge, soft_purge,
+ [snmp_conf, snmpa_mpd]},
+ {update, snmpa_agent, soft, soft_purge, soft_purge,
+ [snmpa_acm, snmpa_mpd, snmpa_trap]}
]
}
],
@@ -53,30 +115,92 @@
%% ------D o w n g r a d e ---------------------------------------------------
[
- {"4.18",
+ {"4.21",
[
- {load_module, snmp_misc, soft_purge, soft_purge, []},
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {load_module, snmpa, soft_purge, soft_purge,
- [snmp_community_mib,
- snmp_framework_mib,
- snmp_standard_mib,
- snmp_target_mib,
- snmp_user_based_sm_mib,
- snmp_view_based_acm_mib]},
- {load_module, snmp_community_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_framework_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_standard_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_target_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge,
- [snmpa_mib_lib]},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge,
- [snmpa_mib_lib, snmpa_vacm]},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}
+ {load_module, snmp_target_mib, soft_purge, soft_purge, []}
+ ]
+ },
+ {"4.20.1",
+ [
+ {load_module, snmp_target_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
+ {load_module, snmpm, soft_purge, soft_purge,
+ [snmpm_server, snmpm_config, snmp_config]},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge,
+ [snmp_conf, snmp_config, snmpm_config]},
+ {load_module, snmpa_mpd, soft_purge, soft_purge,
+ [snmp_conf, snmp_config]},
+ {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_config]},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mpd]},
+ {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]},
+ {update, snmpm_server, soft, soft_purge, soft_purge,
+ [snmpm_net_if, snmpm_mpd, snmpm_config]},
+ {update, snmpm_net_if, soft, soft_purge, soft_purge,
+ [snmp_conf, snmpm_mpd, snmpm_config]}
+ ]
+ },
+ {"4.20",
+ [
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_target_mib, soft_purge, soft_purge, [snmp_conf]},
+ {load_module, snmpm, soft_purge, soft_purge,
+ [snmpm_server, snmpm_config, snmp_config]},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge,
+ [snmp_conf, snmp_config, snmpm_config]},
+ {load_module, snmpa_mpd, soft_purge, soft_purge,
+ [snmp_conf, snmp_config]},
+ {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_config]},
+ {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mpd]},
+ {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]},
+ {update, snmpm_server, soft, soft_purge, soft_purge,
+ [snmpm_net_if, snmpm_mpd, snmpm_config]},
+ {update, snmpm_net_if, soft, soft_purge, soft_purge,
+ [snmp_conf, snmpm_mpd, snmpm_config]}
+ ]
+ },
+ {"4.19",
+ [
+ {load_module, snmpa, soft_purge, soft_purge, []},
+ {load_module, snmpm, soft_purge, soft_purge,
+ [snmpm_server, snmpm_config, snmp_config]},
+ {load_module, snmpa_usm, soft_purge, soft_purge, []},
+ {load_module, snmpm_usm, soft_purge, soft_purge, []},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+ {load_module, snmp_conf, soft_purge, soft_purge, []},
+ {load_module, snmpa_conf, soft_purge, soft_purge,
+ [snmp_conf, snmp_config]},
+ {load_module, snmp_misc, soft_purge, soft_purge, []},
+ {load_module, snmp_config, soft_purge, soft_purge, []},
+ {load_module, snmpa_mpd, soft_purge, soft_purge,
+ [snmp_conf, snmp_config]},
+ {load_module, snmpm_mpd, soft_purge, soft_purge,
+ [snmp_conf, snmp_config, snmpm_config]},
+ {load_module, snmpa_trap, soft_purge, soft_purge,
+ [snmpa_mpd, snmp_notification_mib, snmp_target_mib, snmpa_net_if]},
+ {load_module, snmpa_acm, soft_purge, soft_purge,
+ [snmp_conf, snmpa_mpd, snmp_target_mib]},
+ {load_module, snmpa_conf, soft_purge, soft_purge,
+ [snmp_config, snmp_notification_mib]},
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_notification_mib, soft_purge, soft_purge,
+ [snmp_conf, snmp_target_mib]},
+ {load_module, snmp_community_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_target_mib, soft_purge, soft_purge,
+ [snmp_conf]},
+ {update, snmpm_net_if, soft, soft_purge, soft_purge,
+ [snmp_conf, snmpm_mpd, snmpm_config]},
+ {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]},
+ {update, snmpm_server, soft, soft_purge, soft_purge,
+ [snmpm_net_if, snmpm_mpd, snmpm_config]},
+ {update, snmpa_net_if, soft, soft_purge, soft_purge,
+ [snmp_conf, snmpa_mpd]},
+ {update, snmpa_agent, soft, soft_purge, soft_purge,
+ [snmpa_acm, snmpa_mpd, snmpa_trap]}
]
}
]
diff --git a/lib/snmp/src/compile/Makefile b/lib/snmp/src/compile/Makefile
index 0ceaf276a6..627af6f185 100644
--- a/lib/snmp/src/compile/Makefile
+++ b/lib/snmp/src/compile/Makefile
@@ -45,11 +45,10 @@ RELSYSDIR = $(RELEASE_PATH)/lib/snmp-$(VSN)
include modules.mk
-ESCRIPT_BIN = $(ESCRIPT_SRC:%.src=$(BIN)/%)
-
-ERL_FILES = $(MODULES:%=%.erl)
-
-TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(ESCRIPT_BIN)
+ESCRIPT_BIN = $(ESCRIPT_SRC:%.src=$(BIN)/%)
+ERL_FILES = $(MODULES:%=%.erl)
+EBIN_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+TARGET_FILES = $(EBIN_FILES) $(ESCRIPT_BIN)
GENERATED_PARSER = $(PARSER_MODULE:%=%.erl)
@@ -125,7 +124,7 @@ release_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)/src/compiler
$(INSTALL_DATA) $(ESCRIPT_SRC) $(PARSER_SRC) $(ERL_FILES) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src/compiler
$(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DATA) $(EBIN_FILES) $(RELSYSDIR)/ebin
$(INSTALL_DIR) $(RELSYSDIR)/bin
$(INSTALL_SCRIPT) $(ESCRIPT_BIN) $(RELSYSDIR)/bin
diff --git a/lib/snmp/src/compile/snmpc.erl b/lib/snmp/src/compile/snmpc.erl
index 195c238184..5e6b81f1ec 100644
--- a/lib/snmp/src/compile/snmpc.erl
+++ b/lib/snmp/src/compile/snmpc.erl
@@ -108,6 +108,7 @@ compile(FileName) ->
%% {i, [import_dir_string()]} ["./"]
%% {il, [import_lib_dir_string()]} []
%% {warnings, bool()} true
+%% warnings_as_errors
%% {outdir, string()} "./"
%% description
%% reference
@@ -199,6 +200,8 @@ get_options([reference|Opts], Formats, Args) ->
get_options(Opts, ["~n reference"|Formats], Args);
get_options([{warnings, Val}|Opts], Formats, Args) ->
get_options(Opts, ["~n warnings: ~w"|Formats], [Val|Args]);
+get_options([warnings_as_errors|Opts], Formats, Args) ->
+ get_options(Opts, ["~n warnings_as_errors"|Formats], Args);
get_options([{verbosity, Val}|Opts], Formats, Args) ->
get_options(Opts, ["~n verbosity: ~w"|Formats], [Val|Args]);
get_options([imports|Opts], Formats, Args) ->
@@ -261,6 +264,8 @@ check_options([{group_check, Atom} | T]) when is_atom(Atom) ->
check_options([{warnings, Bool} | T]) ->
check_bool(warnings, Bool),
check_options(T);
+check_options([warnings_as_errors | T]) ->
+ check_options(T);
check_options([{db, volatile} | T]) ->
check_options(T);
check_options([{db, persistent} | T]) ->
@@ -331,6 +336,9 @@ get_agent_capabilities(Options) ->
get_module_compliance(Options) ->
get_bool_option(module_compliance, Options).
+get_warnings_as_errors(Options) ->
+ lists:member(warnings_as_errors, Options).
+
get_relaxed_row_name_assign_check(Options) ->
lists:member(relaxed_row_name_assign_check, Options).
@@ -409,6 +417,7 @@ init(From, MibFileName, Options) ->
put(reference, get_reference(Options)),
put(agent_capabilities, get_agent_capabilities(Options)),
put(module_compliance, get_module_compliance(Options)),
+ put(warnings_as_errors, get_warnings_as_errors(Options)),
File = filename:rootname(MibFileName, ".mib"),
put(filename, filename:basename(File ++ ".mib")),
R = case catch c_impl(File) of
diff --git a/lib/snmp/src/compile/snmpc.src b/lib/snmp/src/compile/snmpc.src
index 5f9b154bfa..f993335b89 100644
--- a/lib/snmp/src/compile/snmpc.src
+++ b/lib/snmp/src/compile/snmpc.src
@@ -46,11 +46,12 @@
agent_capabilities = false,
module,
no_defaults = false,
- relaxed_row_name_assigne_check = false,
+ relaxed_row_name_assign_check = false,
%% The default verbosity (silence) will be filled in
%% during argument processing.
verbosity,
- warnings = false
+ warnings = false,
+ warnings_as_errors = false
}).
@@ -74,6 +75,7 @@
%% --version
%% --verbosity V
%% --warnings
+%% --Werror | --wae | --warnings_as_errors
main(Args) when is_list(Args) ->
case (catch process_args(Args)) of
ok ->
@@ -152,11 +154,12 @@ mk_mib_options(#state{outdir = OutDir,
agent_capabilities = AC,
module = Mod,
no_defaults = ND,
- relaxed_row_name_assigne_check = RRNAC,
+ relaxed_row_name_assign_check = RRNAC,
%% The default verbosity (silence) will be filled in
%% during argument processing.
verbosity = V,
- warnings = W}) ->
+ warnings = W,
+ warnings_as_errors = WAE}) ->
[{outdir, OutDir},
{db, DB},
{i, IDs},
@@ -178,7 +181,8 @@ mk_mib_options(#state{outdir = OutDir,
maybe_option(Imp, imports) ++
maybe_option(MI, module_identity) ++
maybe_option(MC, module_compliance) ++
- maybe_option(AC, agent_capabilities).
+ maybe_option(AC, agent_capabilities) ++
+ maybe_option(WAE, warnings_as_errors).
maybe_option(true, Opt) -> [Opt];
maybe_option(_, _) -> [].
@@ -230,6 +234,8 @@ process_args(["--verbosity", Verbosity0|Args], #state{verbosity = V} = State)
process_args(["--verbosity"|_Args], #state{verbosity = V})
when (V =/= undefined) ->
e(lists:flatten(io_lib:format("Verbosity already set to ~w", [V])));
+process_args(["--w"|Args], State) ->
+ process_args(Args, State#state{warnings = true});
process_args(["--warnings"|Args], State) ->
process_args(Args, State#state{warnings = true});
process_args(["--o", Dir|Args], State) ->
@@ -291,7 +297,13 @@ process_args(["--mod"|_Args], #state{module = M})
process_args(["--nd"|Args], State) ->
process_args(Args, State#state{no_defaults = true});
process_args(["--rrnac"|Args], State) ->
- process_args(Args, State#state{relaxed_row_name_assigne_check = true});
+ process_args(Args, State#state{relaxed_row_name_assign_check = true});
+process_args(["--Werror"|Args], State) ->
+ process_args(Args, State#state{warnings_as_errors = true});
+process_args(["--wae"|Args], State) ->
+ process_args(Args, State#state{warnings_as_errors = true});
+process_args(["--warnings_as_errors"|Args], State) ->
+ process_args(Args, State#state{warnings_as_errors = true});
process_args([MIB], State) ->
Ext = filename:extension(MIB),
if
@@ -326,7 +338,7 @@ usage() ->
"~n --verbosity <verbosity> - Print debug info."
"~n verbosity = trace | debug | log | info | silence"
"~n Defaults to silence."
- "~n --warnings - Print warning messages."
+ "~n --warnings | --W - Print warning messages."
"~n --o <output dir> - The output dir."
"~n Defaults to current working dir."
"~n --i <include dir> - Add this dir to the list of dirs that will be"
@@ -334,16 +346,19 @@ usage() ->
"~n The current workin dir will always be included. "
"~n --il <include_lib dir> - Add this dir to the list of dirs that will be"
"~n searched for imported (compiled) MIB files."
- "~n It assumes that the first element in the dir name"
- "~n correspond to an OTP application. For example snmp/mibs/"
- "~n The current workin dir and the <snmp-home>/priv/mibs "
+ "~n It assumes that the first element in the dir "
+ "~n name correspond to an OTP application. "
+ "~n For example snmp/mibs/ "
+ "~n The current workin dir and the "
+ "~n <snmp-home>/priv/mibs "
"~n are always listed last the includ path. "
"~n --db <DB> - Database to used for the default instrumentation."
"~n Defaults to volatile."
- "~n --sgc - This option (skip group check), if present, disables "
- "~n the \"group check\" of the mib compiler. "
- "~n That is, should the OBJECT-GROUP and the NOTIFICATION-GROUP "
- "~n macro(s) be checked for correctness or not. "
+ "~n --sgc - This option (skip group check), if present, "
+ "~n disables the \"group check\" of the mib compiler. "
+ "~n That is, should the OBJECT-GROUP and the "
+ "~n NOTIFICATION-GROUP macro(s) be checked for "
+ "~n correctness or not. "
"~n By default the check is done. "
"~n --dep - Keep deprecated definition(s)."
"~n If not specified the compiler will ignore"
@@ -354,23 +369,27 @@ usage() ->
"~n --mi - The MODULE-IDENTITY field will be included."
"~n --mc - The MODULE-COMPLIANCE field will be included."
"~n --ac - The AGENT-CAPABILITIES field will be included."
- "~n --mod <module> - The module which implements all the instrumentation"
- "~n functions. "
+ "~n --mod <module> - The module which implements all the "
+ "~n instrumentation functions. "
"~n The name of all instrumentation functions must"
"~n be the same as the corresponding managed object"
"~n it implements."
- "~n --nd - The default instrumentation functions will *not* be used"
- "~n if a managed object have no instrumentation function. "
- "~n Instead this will be reported as an error, and the "
- "~n compilation aborts. "
- "~n --rrnac - This option, if present, specifies that the row name "
- "~n assign check shall not be done strictly according to"
- "~n the SMI (which allows only the value 1). "
- "~n With this option, all values greater than zero is allowed"
- "~n (>= 1). This means that the error will be converted to "
+ "~n --nd - The default instrumentation functions will *not* "
+ "~n be used if a managed object have no "
+ "~n instrumentation function. Instead this will be "
+ "~n reported as an error, and the compilation aborts. "
+ "~n --rrnac - This option, if present, specifies that the row "
+ "~n name assign check shall not be done strictly "
+ "~n according to the SMI (which allows only the "
+ "~n value 1). With this option, all values greater "
+ "~n than zero is allowed (>= 1). "
+ "~n This means that the error will be converted to "
"~n a warning. "
- "~n By default it is not included, but if this option is "
- "~n present it will be. "
+ "~n By default it is not included, but if this "
+ "~n option is present it will be. "
+ "~n --wae | --Werror - Warnings as errors. "
+ "~n Indicates that warnings shall be treated as "
+ "~n errors. "
"~n "
"~n", []),
halt(1).
diff --git a/lib/snmp/src/compile/snmpc_lib.erl b/lib/snmp/src/compile/snmpc_lib.erl
index 4f71c47bfa..38bb8f3ac6 100644
--- a/lib/snmp/src/compile/snmpc_lib.erl
+++ b/lib/snmp/src/compile/snmpc_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1754,12 +1754,12 @@ error(FormatStr, Data, Line) when is_list(FormatStr) ->
exit(error).
print_error(FormatStr, Data) when is_list(FormatStr) ->
- ok = io:format("~s: Error: " ++ FormatStr,[get(filename)|Data]),
+ ok = io:format("~s: " ++ FormatStr,[get(filename)|Data]),
put(errors,yes),
io:format("~n").
print_error(FormatStr, Data,Line) when is_list(FormatStr) ->
- ok = io:format("~s: ~w: Error: " ++ FormatStr,[get(filename), Line |Data]),
+ ok = io:format("~s: ~w: " ++ FormatStr,[get(filename), Line |Data]),
put(errors,yes),
io:format("~n").
diff --git a/lib/snmp/src/compile/snmpc_lib.hrl b/lib/snmp/src/compile/snmpc_lib.hrl
index 000486e728..35ec9abd03 100644
--- a/lib/snmp/src/compile/snmpc_lib.hrl
+++ b/lib/snmp/src/compile/snmpc_lib.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
%%
%% The 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,17 @@
-ifndef(snmpc_lib).
-define(snmpc_lib, true).
--define(vwarning(F, A), ?verbosity(warning, F, A, ignore)).
--define(vwarning2(F, A, MibLine), ?verbosity(warning, F, A, MibLine)).
+-define(vwarning(F, A),
+ case get(warnings_as_errors) of
+ true -> snmpc_lib:error(F, A);
+ _ -> ?verbosity(warning, F, A, ignore)
+ end).
+
+-define(vwarning2(F, A, MibLine),
+ case get(warnings_as_errors) of
+ true -> snmpc_lib:error(F, A, MibLine);
+ _ -> ?verbosity(warning, F, A, MibLine)
+ end).
-define(vinfo(F, A), ?verbosity(info, F, A, ignore)).
-define(vinfo2(F, A, MibLine), ?verbosity(info, F, A, MibLine)).
-define(vlog(F, A), ?verbosity(log, F, A, ignore)).
diff --git a/lib/snmp/src/manager/snmpm.erl b/lib/snmp/src/manager/snmpm.erl
index 5b6321b4c3..6d2ac8d747 100644
--- a/lib/snmp/src/manager/snmpm.erl
+++ b/lib/snmp/src/manager/snmpm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The 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,22 +50,23 @@
register_agent/2, register_agent/3, register_agent/4,
unregister_agent/2, unregister_agent/3,
which_agents/0, which_agents/1,
- agent_info/2, update_agent_info/4,
+ agent_info/2, update_agent_info/3, update_agent_info/4,
register_usm_user/3, unregister_usm_user/2,
which_usm_users/0, which_usm_users/1,
usm_user_info/3, update_usm_user_info/4,
%%
- %% Basic SNMP API
- sync_get/3, sync_get/4, sync_get/5, sync_get/6,
- async_get/3, async_get/4, async_get/5, async_get/6,
- sync_get_next/3, sync_get_next/4, sync_get_next/5, sync_get_next/6,
- async_get_next/3, async_get_next/4, async_get_next/5, async_get_next/6,
- sync_set/3, sync_set/4, sync_set/5, sync_set/6,
- async_set/3, async_set/4, async_set/5, async_set/6,
- sync_get_bulk/5, sync_get_bulk/6, sync_get_bulk/7, sync_get_bulk/8,
- async_get_bulk/5, async_get_bulk/6, async_get_bulk/7, async_get_bulk/8,
+ %% Basic SNMP API (version "3").
+ sync_get2/3, sync_get2/4,
+ async_get2/3, async_get2/4,
+ sync_get_next2/3, sync_get_next2/4,
+ async_get_next2/3, async_get_next2/4,
+ sync_set2/3, sync_set2/4,
+ async_set2/3, async_set2/4,
+ sync_get_bulk2/5, sync_get_bulk2/6,
+ async_get_bulk2/5, async_get_bulk2/6,
+
cancel_async_request/2,
%%
@@ -91,7 +92,61 @@
-export([format_reason/1, format_reason/2]).
-%% Backward compatibillity exports
+%% Backward compatibility exports (API version "2")
+-export([
+ sync_get/3, sync_get/4, sync_get/5, sync_get/6,
+ async_get/3, async_get/4, async_get/5, async_get/6,
+ sync_get_next/3, sync_get_next/4, sync_get_next/5, sync_get_next/6,
+ async_get_next/3, async_get_next/4, async_get_next/5, async_get_next/6,
+ sync_set/3, sync_set/4, sync_set/5, sync_set/6,
+ async_set/3, async_set/4, async_set/5, async_set/6,
+ sync_get_bulk/5, sync_get_bulk/6, sync_get_bulk/7, sync_get_bulk/8,
+ async_get_bulk/5, async_get_bulk/6, async_get_bulk/7, async_get_bulk/8
+ ]).
+
+%% Backward compatibility exports (API version "1")
+-deprecated({agent_info, 3}).
+-deprecated({update_agent_info, 5}).
+-deprecated({g, 3}).
+-deprecated({g, 4}).
+-deprecated({g, 5}).
+-deprecated({g, 6}).
+-deprecated({g, 7}).
+-deprecated({ag, 3}).
+-deprecated({ag, 4}).
+-deprecated({ag, 5}).
+-deprecated({ag, 6}).
+-deprecated({ag, 7}).
+-deprecated({gn, 3}).
+-deprecated({gn, 4}).
+-deprecated({gn, 5}).
+-deprecated({gn, 6}).
+-deprecated({gn, 7}).
+-deprecated({agn, 3}).
+-deprecated({agn, 4}).
+-deprecated({agn, 5}).
+-deprecated({agn, 6}).
+-deprecated({agn, 7}).
+-deprecated({gb, 5}).
+-deprecated({gb, 6}).
+-deprecated({gb, 7}).
+-deprecated({gb, 8}).
+-deprecated({gb, 9}).
+-deprecated({agb, 5}).
+-deprecated({agb, 6}).
+-deprecated({agb, 7}).
+-deprecated({agb, 8}).
+-deprecated({agb, 9}).
+-deprecated({s, 3}).
+-deprecated({s, 4}).
+-deprecated({s, 5}).
+-deprecated({s, 6}).
+-deprecated({s, 7}).
+-deprecated({as, 3}).
+-deprecated({as, 4}).
+-deprecated({as, 5}).
+-deprecated({as, 6}).
+-deprecated({as, 7}).
-export([
agent_info/3, update_agent_info/5,
g/3, g/4, g/5, g/6, g/7,
@@ -108,12 +163,13 @@
-export([start_link/3, snmpm_start_verify/2, snmpm_start_verify/3]).
--include("snmp_debug.hrl").
+-include_lib("snmp/src/misc/snmp_debug.hrl").
+-include_lib("snmp/include/snmp_types.hrl").
-include("snmpm_atl.hrl").
--include("snmp_types.hrl").
+-include("snmpm_internal.hrl").
+-include("snmp_verbosity.hrl").
-define(DEFAULT_AGENT_PORT, 161).
--define(DEFAULT_CONTEXT, "").
%% This function is called when the snmp application
@@ -332,23 +388,23 @@ register_agent(UserId, TargetName, Config)
is_list(Config)) ->
do_register_agent(UserId, TargetName, [{reg_type, target_name} | Config]);
-%% Backward compatibillity
+%% Backward compatibility
%% Note that the agent engine id is a mandatory config option,
%% so this function *will* fail!
register_agent(UserId, Addr, Port) when is_integer(Port) ->
register_agent(UserId, Addr, Port, []);
-%% Backward compatibillity
+%% Backward compatibility
register_agent(UserId, Addr, Config) when is_list(Config) ->
register_agent(UserId, Addr, ?DEFAULT_AGENT_PORT, Config).
-%% Backward compatibillity
+%% Backward compatibility
%% Note that the agent engine id is a mandatory config option,
%% so this function *will* fail!
register_agent(UserId, Addr) ->
register_agent(UserId, Addr, ?DEFAULT_AGENT_PORT, []).
-%% Backward compatibillity
+%% Backward compatibility
register_agent(UserId, Addr, Port, Config0) ->
case lists:keymember(target_name, 1, Config0) of
false ->
@@ -368,7 +424,7 @@ register_agent(UserId, Addr, Port, Config0) ->
unregister_agent(UserId, TargetName) when is_list(TargetName) ->
snmpm_config:unregister_agent(UserId, TargetName);
-%% Backward compatibillity functions
+%% Backward compatibility functions
unregister_agent(UserId, Addr) ->
unregister_agent(UserId, Addr, ?DEFAULT_AGENT_PORT).
@@ -383,7 +439,7 @@ unregister_agent(UserId, Addr, Port) ->
agent_info(TargetName, Item) ->
snmpm_config:agent_info(TargetName, Item).
-%% Backward compatibillity
+%% Backward compatibility
agent_info(Addr, Port, Item) ->
case target_name(Addr, Port) of
{ok, TargetName} ->
@@ -392,25 +448,16 @@ agent_info(Addr, Port, Item) ->
Error
end.
+update_agent_info(UserId, TargetName, Info) when is_list(Info) ->
+ snmpm_config:update_agent_info(UserId, TargetName, Info).
+
update_agent_info(UserId, TargetName, Item, Val) ->
-%% p("update_agent_info -> entry with"
-%% "~n UserId: ~p"
-%% "~n TargetName: ~p"
-%% "~n Item: ~p"
-%% "~n Val: ~p", [UserId, TargetName, Item, Val]),
- snmpm_config:update_agent_info(UserId, TargetName, Item, Val).
-
-%% Backward compatibillity functions
+ update_agent_info(UserId, TargetName, [{Item, Val}]).
+
+%% Backward compatibility functions
update_agent_info(UserId, Addr, Port, Item, Val) ->
-%% p("update_agent_info -> entry with"
-%% "~n UserId: ~p"
-%% "~n Addr: ~p"
-%% "~n Port: ~p"
-%% "~n Item: ~p"
-%% "~n Val: ~p", [UserId, Addr, Port, Item, Val]),
case target_name(Addr, Port) of
{ok, TargetName} ->
-%% p("update_agent_info -> TargetName: ~p", [TargetName]),
update_agent_info(UserId, TargetName, Item, Val);
Error ->
Error
@@ -472,94 +519,54 @@ which_usm_users(EngineID) when is_list(EngineID) ->
%% --- synchroneous get-request ---
%%
+sync_get2(UserId, TargetName, Oids) ->
+ sync_get2(UserId, TargetName, Oids, []).
+
+sync_get2(UserId, TargetName, Oids, SendOpts)
+ when is_list(Oids) andalso is_list(SendOpts) ->
+ snmpm_server:sync_get2(UserId, TargetName, Oids, SendOpts).
+
+%% <BACKWARD-COMPAT>
sync_get(UserId, TargetName, Oids) ->
-%% p("sync_get -> entry with"
-%% "~n UserId: ~p"
-%% "~n TargetName: ~p"
-%% "~n Oids: ~p", [UserId, TargetName, Oids]),
- sync_get(UserId, TargetName, ?DEFAULT_CONTEXT, Oids).
-
-sync_get(UserId, TargetName, Context, Oids) when is_list(Oids) ->
-%% p("sync_get -> entry with"
-%% "~n UserId: ~p"
-%% "~n TargetName: ~p"
-%% "~n Context: ~p"
-%% "~n Oids: ~p", [UserId, TargetName, Context, Oids]),
- snmpm_server:sync_get(UserId, TargetName, Context, Oids);
-
-sync_get(UserId, TargetName, Oids, Timeout) when is_integer(Timeout) ->
-%% p("sync_get -> entry with"
-%% "~n UserId: ~p"
-%% "~n TargetName: ~p"
-%% "~n Oids: ~p"
-%% "~n Timeout: ~p", [UserId, TargetName, Oids, Timeout]),
- sync_get(UserId, TargetName, ?DEFAULT_CONTEXT, Oids, Timeout).
+ sync_get2(UserId, TargetName, Oids).
+
+sync_get(UserId, TargetName, Oids, Timeout)
+ when is_list(Oids) andalso is_integer(Timeout) ->
+ SendOpts = [{timeout, Timeout}],
+ sync_get2(UserId, TargetName, Oids, SendOpts);
+sync_get(UserId, TargetName, Context, [OH|_] = Oids)
+ when is_list(Context) andalso is_list(OH) ->
+ SendOpts = [{context, Context}],
+ sync_get2(UserId, TargetName, Oids, SendOpts).
sync_get(UserId, TargetName, Context, Oids, Timeout) ->
-%% p("sync_get -> entry with"
-%% "~n UserId: ~p"
-%% "~n TargetName: ~p"
-%% "~n Context: ~p"
-%% "~n Oids: ~p"
-%% "~n Timeout: ~p", [UserId, TargetName, Context, Oids, Timeout]),
- snmpm_server:sync_get(UserId, TargetName, Context, Oids, Timeout).
+ SendOpts = [{context, Context}, {timeout, Timeout}],
+ sync_get2(UserId, TargetName, Oids, SendOpts).
sync_get(UserId, TargetName, Context, Oids, Timeout, ExtraInfo) ->
-%% p("sync_get -> entry with"
-%% "~n UserId: ~p"
-%% "~n TargetName: ~p"
-%% "~n Context: ~p"
-%% "~n Oids: ~p"
-%% "~n Timeout: ~p"
-%% "~n ExtraInfo: ~p",
-%% [UserId, TargetName, Context, Oids, Timeout, ExtraInfo]),
- snmpm_server:sync_get(UserId, TargetName, Context, Oids, Timeout,
- ExtraInfo).
+ SendOpts = [{context, Context}, {timeout, Timeout}, {extra, ExtraInfo}],
+ sync_get2(UserId, TargetName, Oids, SendOpts).
+%% </BACKWARD-COMPAT>
+%% <DEPRECATED>
g(UserId, Addr, Oids) ->
-%% p("g -> entry with"
-%% "~n UserId: ~p"
-%% "~n Addr: ~p"
-%% "~n Oids: ~p", [UserId, Addr, Oids]),
g(UserId, Addr, ?DEFAULT_AGENT_PORT, Oids).
g(UserId, Addr, CtxName, Oids) when is_list(CtxName) andalso is_list(Oids) ->
-%% p("g -> entry with"
-%% "~n UserId: ~p"
-%% "~n Addr: ~p"
-%% "~n CtxName: ~p"
-%% "~n Oids: ~p", [UserId, Addr, CtxName, Oids]),
g(UserId, Addr, ?DEFAULT_AGENT_PORT, CtxName, Oids);
g(UserId, Addr, Port, Oids) when is_integer(Port) andalso is_list(Oids) ->
-%% p("g -> entry with"
-%% "~n UserId: ~p"
-%% "~n Addr: ~p"
-%% "~n Port: ~p"
-%% "~n Oids: ~p", [UserId, Addr, Port, Oids]),
g(UserId, Addr, Port, ?DEFAULT_CONTEXT, Oids);
g(UserId, Addr, Oids, Timeout)
when is_list(Oids) andalso is_integer(Timeout) ->
-%% p("g -> entry with"
-%% "~n UserId: ~p"
-%% "~n Addr: ~p"
-%% "~n Oids: ~p"
-%% "~n Timeout: ~p", [UserId, Addr, Oids, Timeout]),
g(UserId, Addr, ?DEFAULT_AGENT_PORT, Oids, Timeout).
g(UserId, Addr, Port, CtxName, Oids)
when is_integer(Port) andalso is_list(CtxName) andalso is_list(Oids) ->
-%% p("g -> entry with"
-%% "~n UserId: ~p"
-%% "~n Addr: ~p"
-%% "~n Port: ~p"
-%% "~n Context: ~p"
-%% "~n Oids: ~p", [UserId, Addr, Port, CtxName, Oids]),
case target_name(Addr, Port) of
{ok, TargetName} ->
-%% p("g -> TargetName: ~p", [TargetName]),
sync_get(UserId, TargetName, CtxName, Oids);
Error ->
Error
@@ -567,59 +574,28 @@ g(UserId, Addr, Port, CtxName, Oids)
g(UserId, Addr, Port, Oids, Timeout)
when is_integer(Port) andalso is_list(Oids) andalso is_integer(Timeout) ->
-%% p("g -> entry with"
-%% "~n UserId: ~p"
-%% "~n Addr: ~p"
-%% "~n Oids: ~p"
-%% "~n Timeout: ~p",
-%% [UserId, Addr, Oids, Timeout]),
g(UserId, Addr, Port, ?DEFAULT_CONTEXT, Oids, Timeout);
g(UserId, Addr, CtxName, Oids, Timeout)
when is_list(CtxName) andalso is_list(Oids) andalso is_integer(Timeout) ->
-%% p("g -> entry with"
-%% "~n UserId: ~p"
-%% "~n Addr: ~p"
-%% "~n CtxName: ~p"
-%% "~n Oids: ~p"
-%% "~n Timeout: ~p",
-%% [UserId, Addr, CtxName, Oids, Timeout]),
g(UserId, Addr, ?DEFAULT_AGENT_PORT, CtxName, Oids, Timeout).
g(UserId, Addr, Port, CtxName, Oids, Timeout) ->
-%% p("g -> entry with"
-%% "~n UserId: ~p"
-%% "~n Addr: ~p"
-%% "~n Port: ~p"
-%% "~n CtxName: ~p"
-%% "~n Oids: ~p"
-%% "~n Timeout: ~p",
-%% [UserId, Addr, Port, CtxName, Oids, Timeout]),
case target_name(Addr, Port) of
{ok, TargetName} ->
-%% p("g -> TargetName: ~p", [TargetName]),
sync_get(UserId, TargetName, CtxName, Oids, Timeout);
Error ->
Error
end.
g(UserId, Addr, Port, CtxName, Oids, Timeout, ExtraInfo) ->
-%% p("g -> entry with"
-%% "~n UserId: ~p"
-%% "~n Addr: ~p"
-%% "~n Port: ~p"
-%% "~n CtxName: ~p"
-%% "~n Oids: ~p"
-%% "~n Timeout: ~p"
-%% "~n ExtraInfo: ~p",
-%% [UserId, Addr, Port, CtxName, Oids, Timeout, ExtraInfo]),
case target_name(Addr, Port) of
{ok, TargetName} ->
-%% p("g -> TargetName: ~p", [TargetName]),
sync_get(UserId, TargetName, CtxName, Oids, Timeout, ExtraInfo);
Error ->
Error
end.
+%% </DEPRECATED>
@@ -629,23 +605,36 @@ g(UserId, Addr, Port, CtxName, Oids, Timeout, ExtraInfo) ->
%% through a call to handle_pdu/5
%%
-async_get(UserId, TargetName, Oids) ->
- async_get(UserId, TargetName, ?DEFAULT_CONTEXT, Oids).
+async_get2(UserId, TargetName, Oids) ->
+ async_get2(UserId, TargetName, Oids, []).
-async_get(UserId, TargetName, Context, Oids) when is_list(Oids) ->
- snmpm_server:async_get(UserId, TargetName, Context, Oids);
+async_get2(UserId, TargetName, Oids, SendOpts)
+ when is_list(Oids) andalso is_list(SendOpts) ->
+ snmpm_server:async_get2(UserId, TargetName, Oids, SendOpts).
+
+%% <BACKWARD-COMPAT>
+async_get(UserId, TargetName, Oids) ->
+ async_get2(UserId, TargetName, Oids).
async_get(UserId, TargetName, Oids, Expire) when is_integer(Expire) ->
- async_get(UserId, TargetName, ?DEFAULT_CONTEXT, Oids, Expire).
+ SendOpts = [{timeout, Expire}],
+ async_get2(UserId, TargetName, Oids, SendOpts);
+async_get(UserId, TargetName, Context, Oids)
+ when is_list(Context) andalso is_list(Oids) ->
+ SendOpts = [{context, Context}],
+ async_get2(UserId, TargetName, Oids, SendOpts).
async_get(UserId, TargetName, Context, Oids, Expire) ->
- snmpm_server:async_get(UserId, TargetName, Context, Oids, Expire).
+ SendOpts = [{timeout, Expire}, {context, Context}],
+ async_get2(UserId, TargetName, Oids, SendOpts).
async_get(UserId, TargetName, Context, Oids, Expire, ExtraInfo) ->
- snmpm_server:async_get(UserId, TargetName, Context, Oids, Expire,
- ExtraInfo).
+ SendOpts = [{timeout, Expire}, {context, Context}, {extra, ExtraInfo}],
+ async_get2(UserId, TargetName, Oids, SendOpts).
+%% </BACKWARD-COMPAT>
+%% <DEPRECATED>
ag(UserId, Addr, Oids) ->
ag(UserId, Addr, ?DEFAULT_AGENT_PORT, Oids).
@@ -690,31 +679,44 @@ ag(UserId, Addr, Port, CtxName, Oids, Expire, ExtraInfo) ->
Error ->
Error
end.
+%% </DEPRECATED>
%% --- synchroneous get_next-request ---
%%
-sync_get_next(UserId, TargetName, Oids) ->
- sync_get_next(UserId, TargetName, ?DEFAULT_CONTEXT, Oids).
+sync_get_next2(UserId, TargetName, Oids) ->
+ sync_get_next2(UserId, TargetName, Oids, []).
-sync_get_next(UserId, TargetName, Context, Oids)
- when is_list(Context) andalso is_list(Oids) ->
- snmpm_server:sync_get_next(UserId, TargetName, Context, Oids);
+sync_get_next2(UserId, TargetName, Oids, SendOpts)
+ when is_list(Oids) andalso is_list(SendOpts) ->
+ snmpm_server:sync_get_next2(UserId, TargetName, Oids, SendOpts).
+
+%% <BACKWARD-COMPAT>
+sync_get_next(UserId, TargetName, Oids) ->
+ sync_get_next2(UserId, TargetName, Oids).
sync_get_next(UserId, TargetName, Oids, Timeout)
when is_list(Oids) andalso is_integer(Timeout) ->
- sync_get_next(UserId, TargetName, ?DEFAULT_CONTEXT, Oids, Timeout).
+ SendOpts = [{timeout, Timeout}],
+ sync_get_next2(UserId, TargetName, Oids, SendOpts);
+sync_get_next(UserId, TargetName, Context, Oids)
+ when is_list(Context) andalso is_list(Oids) ->
+ SendOpts = [{context, Context}],
+ sync_get_next2(UserId, TargetName, Oids, SendOpts).
sync_get_next(UserId, TargetName, Context, Oids, Timeout) ->
- snmpm_server:sync_get_next(UserId, TargetName, Context, Oids, Timeout).
+ SendOpts = [{timeout, Timeout}, {context, Context}],
+ sync_get_next2(UserId, TargetName, Oids, SendOpts).
sync_get_next(UserId, TargetName, Context, Oids, Timeout, ExtraInfo) ->
- snmpm_server:sync_get_next(UserId, TargetName, Context, Oids, Timeout,
- ExtraInfo).
+ SendOpts = [{timeout, Timeout}, {context, Context}, {extra, ExtraInfo}],
+ sync_get_next2(UserId, TargetName, Oids, SendOpts).
+%% </BACKWARD-COMPAT>
+%% <DEPRECATED>
gn(UserId, Addr, Oids) ->
gn(UserId, Addr, ?DEFAULT_AGENT_PORT, Oids).
@@ -759,30 +761,44 @@ gn(UserId, Addr, Port, CtxName, Oids, Timeout, ExtraInfo) ->
Error ->
Error
end.
+%% </DEPRECATED>
%% --- asynchroneous get_next-request ---
%%
+async_get_next2(UserId, TargetName, Oids) ->
+ async_get_next2(UserId, TargetName, Oids, []).
+
+async_get_next2(UserId, TargetName, Oids, SendOpts)
+ when is_list(Oids) andalso is_list(SendOpts) ->
+ snmpm_server:async_get_next2(UserId, TargetName, Oids, SendOpts).
+
+%% <BACKWARD-COMPAT>
async_get_next(UserId, TargetName, Oids) ->
- async_get_next(UserId, TargetName, ?DEFAULT_CONTEXT, Oids).
+ async_get_next2(UserId, TargetName, Oids).
+async_get_next(UserId, TargetName, Oids, Expire)
+ when is_list(Oids) andalso is_integer(Expire) ->
+ SendOpts = [{timeout, Expire}],
+ async_get_next2(UserId, TargetName, Oids, SendOpts);
async_get_next(UserId, TargetName, Context, Oids)
when is_list(Context) andalso is_list(Oids) ->
- snmpm_server:async_get_next(UserId, TargetName, Context, Oids);
+ SendOpts = [{context, Context}],
+ async_get_next2(UserId, TargetName, Oids, SendOpts).
-async_get_next(UserId, TargetName, Oids, Timeout)
- when is_list(Oids) andalso is_integer(Timeout) ->
- async_get_next(UserId, TargetName, ?DEFAULT_CONTEXT, Oids, Timeout).
+async_get_next(UserId, TargetName, Context, Oids, Expire) ->
+ SendOpts = [{timeout, Expire}, {context, Context}],
+ async_get_next2(UserId, TargetName, Oids, SendOpts).
-async_get_next(UserId, TargetName, Context, Oids, Timeout) ->
- snmpm_server:async_get_next(UserId, TargetName, Context, Oids, Timeout).
+async_get_next(UserId, TargetName, Context, Oids, Expire, ExtraInfo) ->
+ SendOpts = [{timeout, Expire}, {context, Context}, {extra, ExtraInfo}],
+ async_get_next2(UserId, TargetName, Oids, SendOpts).
+%% </BACKWARD-COMPAT>
-async_get_next(UserId, TargetName, Context, Oids, Timeout, ExtraInfo) ->
- snmpm_server:async_get_next(UserId, TargetName, Context, Oids, Timeout,
- ExtraInfo).
+%% <DEPRECATED>
agn(UserId, Addr, Oids) ->
agn(UserId, Addr, ?DEFAULT_AGENT_PORT, Oids).
@@ -828,31 +844,44 @@ agn(UserId, Addr, Port, CtxName, Oids, Expire, ExtraInfo) ->
Error ->
Error
end.
+%% </DEPRECATED>
%% --- synchroneous set-request ---
%%
-sync_set(UserId, TargetName, VarsAndVals) ->
- sync_set(UserId, TargetName, ?DEFAULT_CONTEXT, VarsAndVals).
+sync_set2(UserId, TargetName, VarsAndVals) ->
+ sync_set2(UserId, TargetName, VarsAndVals, []).
-sync_set(UserId, TargetName, Context, VarsAndVals)
- when is_list(Context) andalso is_list(VarsAndVals) ->
- snmpm_server:sync_set(UserId, TargetName, Context, VarsAndVals);
+sync_set2(UserId, TargetName, VarsAndVals, SendOpts)
+ when is_list(VarsAndVals) andalso is_list(SendOpts) ->
+ snmpm_server:sync_set2(UserId, TargetName, VarsAndVals, SendOpts).
+
+%% <BACKWARD-COMPAT>
+sync_set(UserId, TargetName, VarsAndVals) ->
+ sync_set2(UserId, TargetName, VarsAndVals).
sync_set(UserId, TargetName, VarsAndVals, Timeout)
when is_list(VarsAndVals) andalso is_integer(Timeout) ->
- sync_set(UserId, TargetName, ?DEFAULT_CONTEXT, VarsAndVals, Timeout).
+ SendOpts = [{timeout, Timeout}],
+ sync_set2(UserId, TargetName, VarsAndVals, SendOpts);
+sync_set(UserId, TargetName, Context, VarsAndVals)
+ when is_list(Context) andalso is_list(VarsAndVals) ->
+ SendOpts = [{context, Context}],
+ sync_set2(UserId, TargetName, VarsAndVals, SendOpts).
sync_set(UserId, TargetName, Context, VarsAndVals, Timeout) ->
- snmpm_server:sync_set(UserId, TargetName, Context, VarsAndVals, Timeout).
+ SendOpts = [{timeout, Timeout}, {context, Context}],
+ sync_set2(UserId, TargetName, VarsAndVals, SendOpts).
sync_set(UserId, TargetName, Context, VarsAndVals, Timeout, ExtraInfo) ->
- snmpm_server:sync_set(UserId, TargetName, Context, VarsAndVals, Timeout,
- ExtraInfo).
+ SendOpts = [{timeout, Timeout}, {context, Context}, {extra, ExtraInfo}],
+ sync_set2(UserId, TargetName, VarsAndVals, SendOpts).
+%% </BACKWARD-COMPAT>
+%% <DEPRECATED>
s(UserId, Addr, VarsAndVals) ->
s(UserId, Addr, ?DEFAULT_AGENT_PORT, VarsAndVals).
@@ -906,31 +935,44 @@ s(UserId, Addr, Port, CtxName, VarsAndVals, Timeout, ExtraInfo) ->
Error ->
Error
end.
+%% </DEPRECATED>
%% --- asynchroneous set-request ---
%%
-async_set(UserId, TargetName, VarsAndVals) ->
- async_set(UserId, TargetName, ?DEFAULT_CONTEXT, VarsAndVals).
+async_set2(UserId, TargetName, VarsAndVals) ->
+ async_set2(UserId, TargetName, VarsAndVals, []).
-async_set(UserId, TargetName, Context, VarsAndVals)
- when is_list(Context) andalso is_list(VarsAndVals) ->
- snmpm_server:async_set(UserId, TargetName, Context, VarsAndVals);
+async_set2(UserId, TargetName, VarsAndVals, SendOpts)
+ when is_list(VarsAndVals) andalso is_list(SendOpts) ->
+ snmpm_server:async_set2(UserId, TargetName, VarsAndVals, SendOpts).
+
+%% <BACKWARD-COMPAT>
+async_set(UserId, TargetName, VarsAndVals) ->
+ async_set2(UserId, TargetName, VarsAndVals).
async_set(UserId, TargetName, VarsAndVals, Expire)
when is_list(VarsAndVals) andalso is_integer(Expire) ->
- async_set(UserId, TargetName, ?DEFAULT_CONTEXT, VarsAndVals, Expire).
+ SendOpts = [{timeout, Expire}],
+ async_set2(UserId, TargetName, VarsAndVals, SendOpts);
+async_set(UserId, TargetName, Context, VarsAndVals)
+ when is_list(Context) andalso is_list(VarsAndVals) ->
+ SendOpts = [{context, Context}],
+ async_set2(UserId, TargetName, VarsAndVals, SendOpts).
async_set(UserId, TargetName, Context, VarsAndVals, Expire) ->
- snmpm_server:async_set(UserId, TargetName, Context, VarsAndVals, Expire).
+ SendOpts = [{timeout, Expire}, {context, Context}],
+ async_set2(UserId, TargetName, VarsAndVals, SendOpts).
async_set(UserId, TargetName, Context, VarsAndVals, Expire, ExtraInfo) ->
- snmpm_server:async_set(UserId, TargetName, Context, VarsAndVals, Expire,
- ExtraInfo).
+ SendOpts = [{timeout, Expire}, {context, Context}, {extra, ExtraInfo}],
+ async_set2(UserId, TargetName, VarsAndVals, SendOpts).
+%% </BACKWARD-COMPAT>
+%% <DEPRECATED>
as(UserId, Addr, VarsAndVals) ->
as(UserId, Addr, ?DEFAULT_AGENT_PORT, VarsAndVals).
@@ -984,44 +1026,77 @@ as(UserId, Addr, Port, CtxName, VarsAndVals, Expire, ExtraInfo) ->
Error ->
Error
end.
-
-
+%% </DEPRECATED>
%% --- synchroneous get-bulk ---
%%
-sync_get_bulk(UserId, TargetName, NonRep, MaxRep, Oids) ->
- sync_get_bulk(UserId, TargetName, NonRep, MaxRep, ?DEFAULT_CONTEXT, Oids).
+sync_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids) ->
+ sync_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, []).
-sync_get_bulk(UserId, TargetName, NonRep, MaxRep, Context, Oids)
+sync_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts)
when is_integer(NonRep) andalso
is_integer(MaxRep) andalso
- is_list(Context) andalso
- is_list(Oids) ->
- snmpm_server:sync_get_bulk(UserId, TargetName,
- NonRep, MaxRep,
- Context, Oids);
+ is_list(Oids) andalso
+ is_list(SendOpts) ->
+ %% p("sync_get_bulk -> entry with"
+ %% "~n UserId: ~p"
+ %% "~n TargetName: ~p"
+ %% "~n NonRep: ~p"
+ %% "~n MaxRep: ~p"
+ %% "~n Oids: ~p"
+ %% "~n SendOpts: ~p",
+ %% [UserId, TargetName, NonRep, MaxRep, Oids, SendOpts]),
+ snmpm_server:sync_get_bulk2(UserId, TargetName,
+ NonRep, MaxRep, Oids, SendOpts).
+
+%% <BACKWARD-COMPAT>
+sync_get_bulk(UserId, TargetName, NonRep, MaxRep, Oids) ->
+ sync_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids).
sync_get_bulk(UserId, TargetName, NonRep, MaxRep, Oids, Timeout)
when is_integer(NonRep) andalso
is_integer(MaxRep) andalso
is_list(Oids) andalso
is_integer(Timeout) ->
- sync_get_bulk(UserId, TargetName, NonRep, MaxRep,
- ?DEFAULT_CONTEXT, Oids, Timeout).
+ SendOpts = [{timeout, Timeout}],
+ sync_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts);
+sync_get_bulk(UserId, TargetName, NonRep, MaxRep, Context, Oids)
+ when is_integer(NonRep) andalso
+ is_integer(MaxRep) andalso
+ is_list(Context) andalso
+ is_list(Oids) ->
+ %% p("sync_get_bulk -> entry with"
+ %% "~n UserId: ~p"
+ %% "~n TargetName: ~p"
+ %% "~n NonRep: ~p"
+ %% "~n MaxRep: ~p"
+ %% "~n Context: ~p"
+ %% "~n Oids: ~p", [UserId, TargetName, NonRep, MaxRep, Context, Oids]),
+ SendOpts = [{context, Context}],
+ sync_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts).
sync_get_bulk(UserId, TargetName, NonRep, MaxRep, Context, Oids, Timeout) ->
- snmpm_server:sync_get_bulk(UserId, TargetName, NonRep, MaxRep,
- Context, Oids, Timeout).
+ SendOpts = [{timeout, Timeout}, {context, Context}],
+ sync_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts).
sync_get_bulk(UserId, TargetName, NonRep, MaxRep, Context, Oids, Timeout,
ExtraInfo) ->
- snmpm_server:sync_get_bulk(UserId, TargetName, NonRep, MaxRep,
- Context, Oids, Timeout, ExtraInfo).
+ SendOpts = [{timeout, Timeout}, {context, Context}, {extra, ExtraInfo}],
+ sync_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts).
+%% </BACKWARD-COMPAT>
+%% <DEPRECATED>
gb(UserId, Addr, NonRep, MaxRep, Oids) ->
+ %% p("gb -> entry with"
+ %% "~n UserId: ~p"
+ %% "~n Addr: ~p"
+ %% "~n NonRep: ~p"
+ %% "~n MaxRep: ~p"
+ %% "~n Oids: ~p",
+ %% [UserId, Addr, NonRep, MaxRep, Oids]),
gb(UserId, Addr, ?DEFAULT_AGENT_PORT, NonRep, MaxRep, Oids).
gb(UserId, Addr, Port, NonRep, MaxRep, Oids)
@@ -1029,6 +1104,14 @@ gb(UserId, Addr, Port, NonRep, MaxRep, Oids)
is_integer(NonRep) andalso
is_integer(MaxRep) andalso
is_list(Oids) ->
+ %% p("gb -> entry with"
+ %% "~n UserId: ~p"
+ %% "~n Addr: ~p"
+ %% "~n Port: ~p"
+ %% "~n NonRep: ~p"
+ %% "~n MaxRep: ~p"
+ %% "~n Oids: ~p",
+ %% [UserId, Addr, Port, NonRep, MaxRep, Oids]),
gb(UserId, Addr, Port, NonRep, MaxRep, ?DEFAULT_CONTEXT, Oids);
gb(UserId, Addr, NonRep, MaxRep, CtxName, Oids)
@@ -1036,6 +1119,14 @@ gb(UserId, Addr, NonRep, MaxRep, CtxName, Oids)
is_integer(MaxRep) andalso
is_list(CtxName) andalso
is_list(Oids) ->
+ %% p("gb -> entry with"
+ %% "~n UserId: ~p"
+ %% "~n Addr: ~p"
+ %% "~n NonRep: ~p"
+ %% "~n MaxRep: ~p"
+ %% "~n CtxName: ~p"
+ %% "~n Oids: ~p",
+ %% [UserId, Addr, NonRep, MaxRep, CtxName, Oids]),
gb(UserId, Addr, ?DEFAULT_AGENT_PORT, NonRep, MaxRep, CtxName, Oids);
gb(UserId, Addr, NonRep, MaxRep, Oids, Timeout)
@@ -1043,6 +1134,14 @@ gb(UserId, Addr, NonRep, MaxRep, Oids, Timeout)
is_integer(MaxRep) andalso
is_list(Oids) andalso
is_integer(Timeout) ->
+ %% p("gb -> entry with"
+ %% "~n UserId: ~p"
+ %% "~n Addr: ~p"
+ %% "~n NonRep: ~p"
+ %% "~n MaxRep: ~p"
+ %% "~n Oids: ~p"
+ %% "~n Timeout: ~p",
+ %% [UserId, Addr, NonRep, MaxRep, Oids, Timeout]),
gb(UserId, Addr, ?DEFAULT_AGENT_PORT, NonRep, MaxRep, Oids, Timeout).
gb(UserId, Addr, Port, NonRep, MaxRep, CtxName, Oids)
@@ -1051,8 +1150,18 @@ gb(UserId, Addr, Port, NonRep, MaxRep, CtxName, Oids)
is_integer(MaxRep) andalso
is_list(CtxName) andalso
is_list(Oids) ->
+ %% p("gb -> entry with"
+ %% "~n UserId: ~p"
+ %% "~n Addr: ~p"
+ %% "~n Port: ~p"
+ %% "~n NonRep: ~p"
+ %% "~n MaxRep: ~p"
+ %% "~n CtxName: ~p"
+ %% "~n Oids: ~p",
+ %% [UserId, Addr, Port, NonRep, MaxRep, CtxName, Oids]),
case target_name(Addr, Port) of
{ok, TargetName} ->
+ %% p("gb -> TargetName: ~p", [TargetName]),
sync_get_bulk(UserId, TargetName, NonRep, MaxRep, CtxName, Oids);
Error ->
Error
@@ -1064,6 +1173,15 @@ gb(UserId, Addr, Port, NonRep, MaxRep, Oids, Timeout)
is_integer(MaxRep) andalso
is_list(Oids) andalso
is_integer(Timeout) ->
+ %% p("gb -> entry with"
+ %% "~n UserId: ~p"
+ %% "~n Addr: ~p"
+ %% "~n Port: ~p"
+ %% "~n NonRep: ~p"
+ %% "~n MaxRep: ~p"
+ %% "~n Oids: ~p"
+ %% "~n Timeout: ~p",
+ %% [UserId, Addr, Port, NonRep, MaxRep, Oids, Timeout]),
gb(UserId, Addr, Port, NonRep, MaxRep, ?DEFAULT_CONTEXT, Oids, Timeout);
gb(UserId, Addr, NonRep, MaxRep, CtxName, Oids, Timeout)
@@ -1072,10 +1190,29 @@ gb(UserId, Addr, NonRep, MaxRep, CtxName, Oids, Timeout)
is_list(CtxName) andalso
is_list(Oids) andalso
is_integer(Timeout) ->
+ %% p("gb -> entry with"
+ %% "~n UserId: ~p"
+ %% "~n Addr: ~p"
+ %% "~n NonRep: ~p"
+ %% "~n MaxRep: ~p"
+ %% "~n CtxName: ~p"
+ %% "~n Oids: ~p"
+ %% "~n Timeout: ~p",
+ %% [UserId, Addr, NonRep, MaxRep, CtxName, Oids, Timeout]),
gb(UserId, Addr, ?DEFAULT_AGENT_PORT, NonRep, MaxRep, CtxName, Oids,
Timeout).
gb(UserId, Addr, Port, NonRep, MaxRep, CtxName, Oids, Timeout) ->
+ %% p("gb -> entry with"
+ %% "~n UserId: ~p"
+ %% "~n Addr: ~p"
+ %% "~n Port: ~p"
+ %% "~n NonRep: ~p"
+ %% "~n MaxRep: ~p"
+ %% "~n CtxName: ~p"
+ %% "~n Oids: ~p"
+ %% "~n Timeout: ~p",
+ %% [UserId, Addr, Port, NonRep, MaxRep, CtxName, Oids, Timeout]),
case target_name(Addr, Port) of
{ok, TargetName} ->
sync_get_bulk(UserId, TargetName,
@@ -1085,6 +1222,17 @@ gb(UserId, Addr, Port, NonRep, MaxRep, CtxName, Oids, Timeout) ->
end.
gb(UserId, Addr, Port, NonRep, MaxRep, CtxName, Oids, Timeout, ExtraInfo) ->
+ %% p("gb -> entry with"
+ %% "~n UserId: ~p"
+ %% "~n Addr: ~p"
+ %% "~n Port: ~p"
+ %% "~n NonRep: ~p"
+ %% "~n MaxRep: ~p"
+ %% "~n CtxName: ~p"
+ %% "~n Oids: ~p"
+ %% "~n Timeout: ~p"
+ %% "~n ExtraInfo: ~p",
+ %% [UserId, Addr, Port, NonRep, MaxRep, CtxName, Oids, Timeout, ExtraInfo]),
case target_name(Addr, Port) of
{ok, TargetName} ->
sync_get_bulk(UserId, TargetName,
@@ -1092,42 +1240,55 @@ gb(UserId, Addr, Port, NonRep, MaxRep, CtxName, Oids, Timeout, ExtraInfo) ->
Error ->
Error
end.
+%% </DEPRECATED>
%% --- asynchroneous get-bulk ---
%%
-async_get_bulk(UserId, TargetName, NonRep, MaxRep, Oids) ->
- async_get_bulk(UserId, TargetName, NonRep, MaxRep, ?DEFAULT_CONTEXT, Oids).
+async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids) ->
+ async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, []).
-async_get_bulk(UserId, TargetName, NonRep, MaxRep, Context, Oids)
+async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts)
when is_integer(NonRep) andalso
is_integer(MaxRep) andalso
- is_list(Context) andalso
- is_list(Oids) ->
- snmpm_server:async_get_bulk(UserId, TargetName,
- NonRep, MaxRep, Context, Oids);
+ is_list(Oids) andalso
+ is_list(SendOpts) ->
+ snmpm_server:async_get_bulk2(UserId, TargetName,
+ NonRep, MaxRep, Oids, SendOpts).
+
+%% <BACKWARD-COMPAT>
+async_get_bulk(UserId, TargetName, NonRep, MaxRep, Oids) ->
+ async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids).
async_get_bulk(UserId, TargetName, NonRep, MaxRep, Oids, Expire)
when is_integer(NonRep) andalso
is_integer(MaxRep) andalso
is_list(Oids) andalso
is_integer(Expire) ->
- async_get_bulk(UserId, TargetName,
- NonRep, MaxRep, ?DEFAULT_CONTEXT, Oids, Expire).
+ SendOpts = [{timeout, Expire}],
+ async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts);
+async_get_bulk(UserId, TargetName, NonRep, MaxRep, Context, Oids)
+ when is_integer(NonRep) andalso
+ is_integer(MaxRep) andalso
+ is_list(Context) andalso
+ is_list(Oids) ->
+ SendOpts = [{context, Context}],
+ async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts).
async_get_bulk(UserId, TargetName, NonRep, MaxRep, Context, Oids, Expire) ->
- snmpm_server:async_get_bulk(UserId, TargetName,
- NonRep, MaxRep, Context, Oids, Expire).
+ SendOpts = [{timeout, Expire}, {context, Context}],
+ async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts).
async_get_bulk(UserId, TargetName, NonRep, MaxRep, Context, Oids, Expire,
ExtraInfo) ->
- snmpm_server:async_get_bulk(UserId, TargetName,
- NonRep, MaxRep,
- Context, Oids, Expire, ExtraInfo).
+ SendOpts = [{timeout, Expire}, {context, Context}, {extra, ExtraInfo}],
+ async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts).
+%% </BACKWARD-COMPAT>
+%% <DEPRECATED>
agb(UserId, Addr, NonRep, MaxRep, Oids) ->
agb(UserId, Addr, ?DEFAULT_AGENT_PORT, NonRep, MaxRep, Oids).
@@ -1200,6 +1361,7 @@ agb(UserId, Addr, Port, NonRep, MaxRep, CtxName, Oids, Expire, ExtraInfo) ->
Error ->
Error
end.
+%% </DEPRECATED>
cancel_async_request(UserId, ReqId) ->
@@ -1207,7 +1369,7 @@ cancel_async_request(UserId, ReqId) ->
%%%-----------------------------------------------------------------
-%%% Audit Trail Log functions (for backward compatibillity)
+%%% Audit Trail Log functions (for backward compatibility)
%%%-----------------------------------------------------------------
log_to_txt(LogDir, Mibs) ->
OutFile = "snmpm_log.txt",
diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl
index fd6da3e71a..c2e57abddb 100644
--- a/lib/snmp/src/manager/snmpm_config.erl
+++ b/lib/snmp/src/manager/snmpm_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -36,7 +36,8 @@
user_info/0, user_info/1, user_info/2,
register_agent/3, unregister_agent/2,
- agent_info/0, agent_info/2, agent_info/3, update_agent_info/4,
+ agent_info/0, agent_info/2, agent_info/3,
+ update_agent_info/3, update_agent_info/4,
which_agents/0, which_agents/1,
is_known_engine_id/2,
@@ -84,7 +85,9 @@
backup/1,
- mk_target_name/3
+ mk_target_name/3,
+
+ default_transport_domain/0
]).
@@ -127,23 +130,24 @@
%% Macros and Constants:
--define(SERVER, ?MODULE).
--define(BACKUP_DB, snmpm_config_backup).
--define(CONFIG_DB, snmpm_config_db).
+-define(SERVER, ?MODULE).
+-define(BACKUP_DB, snmpm_config_backup).
+-define(CONFIG_DB, snmpm_config_db).
-define(DEFAULT_USER, default_user).
-define(DEFAULT_AGENT_PORT, 161).
--define(IRB_DEFAULT, auto).
-%% -define(IRB_DEFAULT, {user, timer:seconds(15)}).
+-define(IRB_DEFAULT, auto).
+%% -define(IRB_DEFAULT, {user, timer:seconds(15)}).
--define(USER_MOD_DEFAULT, snmpm_user_default).
--define(USER_DATA_DEFAULT, undefined).
+-define(USER_MOD_DEFAULT, snmpm_user_default).
+-define(USER_DATA_DEFAULT, undefined).
%% -define(DEF_ADDR_TAG, default_addr_tag).
-define(DEFAULT_TARGETNAME, default_agent).
--define(DEF_PORT_TAG, default_port_tag).
+-define(DEF_PORT_TAG, default_port_tag).
+-define(SUPPORTED_DOMAINS, [transportDomainUdpIpv4, transportDomainUdpIpv6]).
-ifdef(snmp_debug).
-define(GS_START_LINK(Opts),
@@ -159,6 +163,11 @@
%%%-------------------------------------------------------------------
%%% API
%%%-------------------------------------------------------------------
+
+default_transport_domain() ->
+ transportDomainUdpIpv4.
+
+
start_link(Opts) ->
?d("start_link -> entry with"
"~n Opts: ~p", [Opts]),
@@ -269,9 +278,10 @@ do_user_info(_UserId, BadItem) ->
error({not_found, BadItem}).
-%% A target-name constructed in this way is a string with the following
+%% A target-name constructed in this way is a string with the following:
%% <IP-address>:<Port>-<Version>
-%%
+%% This is intended for backward compatibility and therefor has
+%% only support for IPv4 addresses and *no* other transport domain.
mk_target_name(Addr0, Port, Config) when is_list(Config) ->
Version =
case lists:keysearch(version, 1, Config) of
@@ -280,7 +290,6 @@ mk_target_name(Addr0, Port, Config) when is_list(Config) ->
false ->
select_lowest_supported_version()
end,
-%% p("mk_target_name -> Version: ~p", [Version]),
case normalize_address(Addr0) of
{A, B, C, D} ->
lists:flatten(
@@ -308,57 +317,99 @@ select_lowest_supported_version([H|T], Versions) ->
end.
-register_agent(UserId, _TargetName, _Config) when (UserId =:= user_id) ->
+register_agent(UserId, _TargetName, _Config0) when (UserId =:= user_id) ->
{error, {bad_user_id, UserId}};
-register_agent(UserId, TargetName, Config)
+register_agent(UserId, TargetName, Config0)
when (is_list(TargetName) andalso
(length(TargetName) > 0) andalso
- is_list(Config)) ->
+ is_list(Config0)) ->
-%% p("register_agent -> entry with"
-%% "~n UserId: ~p"
-%% "~n TargetName: ~p"
-%% "~n Config: ~p", [UserId, TargetName, Config]),
+ ?vtrace("register_agent -> entry with"
+ "~n UserId: ~p"
+ "~n TargetName: ~p"
+ "~n Config0: ~p", [UserId, TargetName, Config0]),
%% Check:
%% 1) That the mandatory configs are present
- %% 2) That the illegal config user_id (used internally) is
- %% not present
+ %% 2) That no illegal config, e.g. user_id (used internally),
+ %% is not present
%% 3) Check that there are no invalid or erroneous configs
- %% 4) Chack that the manager is capable to use the selected version
- case verify_agent_config(Config) of
- ok ->
+ %% 4) Check that the manager is capable of using the selected version
+ case verify_agent_config(Config0) of
+ {ok, Config} ->
call({register_agent, UserId, TargetName, Config});
Error ->
Error
end.
-verify_agent_config(Conf) ->
- ok = verify_mandatory(Conf, [engine_id, address, reg_type]),
- case verify_invalid(Conf, [user_id]) of
- ok ->
- case verify_agent_config2(Conf) of
- ok ->
- {ok, Vsns} = system_info(versions),
- Vsn =
- case lists:keysearch(version, 1, Conf) of
- {value, {version, V}} ->
- V;
- false ->
- v1
- end,
- case lists:member(Vsn, Vsns) of
- true ->
- ok;
- false ->
- {error, {version_not_supported_by_manager, Vsn, Vsns}}
- end
- end;
- Error ->
+verify_agent_config(Conf0) ->
+ try
+ begin
+ verify_mandatory(Conf0, [engine_id, address, reg_type]),
+ verify_invalid(Conf0, [user_id]),
+ Conf = verify_agent_config3(Conf0),
+ Vsns = versions(),
+ Vsn = which_version(Conf),
+ verify_version(Vsn, Vsns),
+ {ok, Conf}
+ end
+ catch
+ throw:Error ->
Error
end.
+versions() ->
+ case system_info(versions) of
+ {ok, Vsns} ->
+ Vsns;
+ {error, _} = ERROR ->
+ throw(ERROR)
+ end.
+
+which_version(Conf) ->
+ case lists:keysearch(version, 1, Conf) of
+ {value, {version, V}} ->
+ V;
+ false ->
+ v1
+ end.
+
+verify_version(Vsn, Vsns) ->
+ case lists:member(Vsn, Vsns) of
+ true ->
+ ok;
+ false ->
+ Reason = {version_not_supported_by_manager, Vsn, Vsns},
+ throw({error, Reason})
+ end.
+
+verify_agent_config3(Conf0) ->
+ %% Fix (transport) address and domain
+ {TDomain, Conf1} =
+ case lists:keysearch(tdomain, 1, Conf0) of
+ {value, {tdomain, Dom}} ->
+ {Dom, Conf0};
+ false ->
+ Dom = default_transport_domain(),
+ {Dom, [{tdomain, Dom} | Conf0]}
+ end,
+ Conf2 = case lists:keysearch(address, 1, Conf1) of
+ {value, {address, Address}} ->
+ lists:keyreplace(address, 1, Conf1,
+ {address, {TDomain, Address}});
+ false ->
+ %% This is a mandatory config option,
+ %% a later test will detect this
+ Conf1
+ end,
+ case verify_agent2(Conf2) of
+ {ok, Conf} ->
+ Conf;
+ {error, _} = ERROR ->
+ throw(ERROR)
+ end.
+
verify_agent_config2(Conf) ->
verify_agent2(Conf).
@@ -366,6 +417,7 @@ verify_agent_config2(Conf) ->
unregister_agent(UserId, TargetName) ->
call({unregister_agent, UserId, TargetName}).
+%% This is the old style agent unregistration (using Addr and Port).
unregister_agent(UserId, Addr0, Port) ->
Addr = normalize_address(Addr0),
case do_agent_info(Addr, Port, target_name) of
@@ -421,17 +473,51 @@ which_agents(UserId) ->
Agents = ets:match(snmpm_agent_table, Pat),
[TargetName || [TargetName] <- Agents].
-
-update_agent_info(UserId, TargetName, Item, Val0)
- when (Item =/= user_id) ->
- case (catch verify_val(Item, Val0)) of
- {ok, Val} ->
- call({update_agent_info, UserId, TargetName, Item, Val});
- Error ->
+
+verify_agent_info(TargetName, Info0) ->
+ try
+ begin
+ verify_invalid(Info0, [user_id]),
+ %% Check if address is part of the list and
+ %% if so update it with the domain info.
+ Info =
+ case lists:keysearch(address, 1, Info0) of
+ {value, {address, Addr}} ->
+ %% If domain is part of the info, then use it.
+ %% If not, lookup what is already stored for
+ %% this agent and use that.
+ Domain =
+ case lists:keysearch(tdomain, 1, Info0) of
+ {value, {tdomain, Dom}} ->
+ Dom;
+ false ->
+ {ok, Dom} =
+ agent_info(TargetName, tdomain),
+ Dom
+ end,
+ Addr2 = {Domain, Addr},
+ lists:keyreplace(address, 1, Info0, {address, Addr2});
+ false ->
+ Info0
+ end,
+ verify_agent2(Info)
+ end
+ catch
+ throw:Error ->
Error
end.
-%% Backward compatibillity
+update_agent_info(UserId, TargetName, Info) ->
+ call({update_agent_info, UserId, TargetName, Info}).
+
+%% <BACKWARD-COMPAT-2>
+%% This is wrapped in the interface module, so this function is
+%% only here to catch code-upgrade problems.
+update_agent_info(UserId, TargetName, Item, Val) ->
+ update_agent_info(UserId, TargetName, [{Item, Val}]).
+%% </BACKWARD-COMPAT-2>
+
+%% <BACKWARD-COMPAT-1>
update_agent_info(UserId, Addr, Port, Item, Val) ->
case agent_info(Addr, Port, target_name) of
{ok, TargetName} ->
@@ -439,6 +525,7 @@ update_agent_info(UserId, Addr, Port, Item, Val) ->
Error ->
Error
end.
+%% </BACKWARD-COMPAT-1>
is_known_engine_id(EngineID, TargetName) ->
case agent_info(TargetName, engine_id) of
@@ -650,22 +737,14 @@ unregister_usm_user(EngineID, Name)
call({unregister_usm_user, EngineID, Name}).
verify_usm_user_config(EngineID, Name, Config) ->
- %% case verify_mandatory(Config, []) of
- %% ok ->
- %% case verify_invalid(Config, [engine_id, name]) of
- %% ok ->
- %% verify_usm_user_config2(EngineID, Name, Config);
- %% Error ->
- %% Error
- %% end;
- %% Error ->
- %% Error
- %% end.
- ok = verify_mandatory(Config, []),
- case verify_invalid(Config, [engine_id, name]) of
- ok ->
- verify_usm_user_config2(EngineID, Name, Config);
- Error ->
+ try
+ begin
+ verify_mandatory(Config, []),
+ verify_invalid(Config, [engine_id, name]),
+ verify_usm_user_config2(EngineID, Name, Config)
+ end
+ catch
+ throw:Error ->
Error
end.
@@ -1590,6 +1669,7 @@ check_agent_config2(Agent) ->
throw(Err)
end.
+%% For backward compatibility
check_agent_config({UserId,
TargetName,
Community,
@@ -1597,10 +1677,27 @@ check_agent_config({UserId,
EngineId,
Timeout, MaxMessageSize,
Version, SecModel, SecName, SecLevel}) ->
+ TDomain = default_transport_domain(),
+ check_agent_config({UserId,
+ TargetName,
+ Community,
+ TDomain, Ip, Port,
+ EngineId,
+ Timeout, MaxMessageSize,
+ Version, SecModel, SecName, SecLevel});
+
+check_agent_config({UserId,
+ TargetName,
+ Community,
+ TDomain, Ip, Port,
+ EngineId,
+ Timeout, MaxMessageSize,
+ Version, SecModel, SecName, SecLevel}) ->
?vtrace("check_agent_config -> entry with"
"~n UserId: ~p"
"~n TargetName: ~p"
"~n Community: ~p"
+ "~n TDomain: ~p"
"~n Ip: ~p"
"~n Port: ~p"
"~n EngineId: ~p"
@@ -1610,15 +1707,16 @@ check_agent_config({UserId,
"~n SecModel: ~p"
"~n SecName: ~p"
"~n SecLevel: ~p",
- [UserId, TargetName, Community, Ip, Port,
+ [UserId, TargetName, Community,
+ TDomain, Ip, Port,
EngineId, Timeout, MaxMessageSize,
Version, SecModel, SecName, SecLevel]),
- Addr = normalize_address(Ip),
+ Addr = normalize_address(TDomain, Ip),
?vtrace("check_agent_config -> Addr: ~p", [Addr]),
Agent = {UserId,
TargetName,
Community,
- Addr, Port,
+ TDomain, Addr, Port,
EngineId,
Timeout, MaxMessageSize,
Version, SecModel, SecName, SecLevel},
@@ -1644,6 +1742,7 @@ init_agent_config({UserId, TargetName, Config}) ->
end.
+%% For backward compatibility
verify_agent({UserId,
TargetName,
Comm,
@@ -1651,48 +1750,68 @@ verify_agent({UserId,
EngineId,
Timeout, MMS,
Version, SecModel, SecName, SecLevel}) ->
- ?vtrace("verify_agent -> entry with"
+ TDomain = default_transport_domain(),
+ verify_agent({UserId,
+ TargetName,
+ Comm,
+ TDomain, Ip, Port,
+ EngineId,
+ Timeout, MMS,
+ Version, SecModel, SecName, SecLevel});
+
+verify_agent({UserId,
+ TargetName,
+ Comm,
+ TDomain, Ip, Port,
+ EngineId,
+ Timeout, MMS,
+ Version, SecModel, SecName, SecLevel}) ->
+ ?vdebug("verify_agent -> entry with"
"~n UserId: ~p"
"~n TargetName: ~p", [UserId, TargetName]),
snmp_conf:check_string(TargetName, {gt, 0}),
- case verify_val(address, Ip) of
- {ok, Addr} ->
- snmp_conf:check_integer(Port, {gt, 0}),
- Conf =
- [{reg_type, target_name},
- {address, Addr},
- {port, Port},
- {community, Comm},
- {engine_id, EngineId},
- {timeout, Timeout},
- {max_message_size, MMS},
- {version, Version},
- {sec_model, SecModel},
- {sec_name, SecName},
- {sec_level, SecLevel}
- ],
- case verify_agent2(Conf) of
- ok ->
- {UserId, TargetName, Conf, Version};
- Err ->
- throw(Err)
- end;
-
- Error ->
- ?vlog("verify_agent -> failed: ~n ~p", [Error]),
- throw(Error)
+ snmp_conf:check_integer(Port, {gt, 0}),
+ %% Note that the order of Conf *is* important.
+ %% Some properties may depend on others, so that
+ %% in order to verify one property, another must
+ %% be already verified (and present). An example
+ %% of this is the property 'address', for which
+ %% the property tdomain is needed.
+ Conf0 =
+ [{reg_type, target_name},
+ {tdomain, TDomain},
+ %% This should be taddress, but what the*...
+ {address, {TDomain, Ip}},
+ {port, Port},
+ {community, Comm},
+ {engine_id, EngineId},
+ {timeout, Timeout},
+ {max_message_size, MMS},
+ {version, Version},
+ {sec_model, SecModel},
+ {sec_name, SecName},
+ {sec_level, SecLevel}
+ ],
+ case verify_agent2(Conf0) of
+ {ok, Conf} ->
+ {UserId, TargetName, Conf, Version};
+ Err ->
+ throw(Err)
end.
-verify_agent2([]) ->
- ok;
-verify_agent2([{Item, Val}|Items]) ->
- case verify_val(Item, Val) of
- {ok, _Val} ->
- verify_agent2(Items);
+verify_agent2(Conf) ->
+ verify_agent2(Conf, []).
+
+verify_agent2([], VerifiedConf) ->
+ {ok, VerifiedConf};
+verify_agent2([{Item, Val0}|Items], VerifiedConf) ->
+ case verify_val(Item, Val0) of
+ {ok, Val} ->
+ verify_agent2(Items, [{Item, Val} | VerifiedConf]);
Err ->
Err
end;
-verify_agent2([Bad|_]) ->
+verify_agent2([Bad|_], _VerifiedConf) ->
{error, {bad_agent_config, Bad}}.
@@ -1708,14 +1827,28 @@ read_users_config_file(Dir) ->
check_user_config({Id, Mod, Data}) ->
+ ?vtrace("check_user_config -> entry with"
+ "~n Id: ~p"
+ "~n Mod: ~p"
+ "~n Data: ~p", [Id, Mod, Data]),
check_user_config({Id, Mod, Data, []});
-check_user_config({Id, Mod, _Data, DefaultAgentConfig} = User)
+check_user_config({Id, Mod, Data, DefaultAgentConfig} = _User)
when (Id =/= ?DEFAULT_USER) andalso is_list(DefaultAgentConfig) ->
+ ?vtrace("check_user_config -> entry with"
+ "~n Id: ~p"
+ "~n Mod: ~p"
+ "~n Data: ~p"
+ "~n DefaultAgentConfig: ~p",
+ [Id, Mod, Data, DefaultAgentConfig]),
case (catch verify_user_behaviour(Mod)) of
ok ->
+ ?vtrace("check_user_config -> user behaviour verified", []),
case verify_user_agent_config(DefaultAgentConfig) of
- ok ->
- {ok, User};
+ {ok, DefAgentConf} ->
+ ?vtrace("check_user_config -> "
+ "user agent (default) config verified", []),
+ User2 = {Id, Mod, Data, DefAgentConf},
+ {ok, User2};
{error, Reason} ->
error({bad_default_agent_config, Reason})
end;
@@ -1756,16 +1889,16 @@ verify_user({Id, UserMod, UserData}) ->
verify_user({Id, UserMod, UserData, DefaultAgentConfig})
when (Id =/= ?DEFAULT_USER) andalso is_list(DefaultAgentConfig) ->
?d("verify_user -> entry with"
- "~n Id: ~p"
- "~n UserMod: ~p"
- "~n UserData: ~p"
+ "~n Id: ~p"
+ "~n UserMod: ~p"
+ "~n UserData: ~p"
"~n DefaultAgentConfig: ~p",
[Id, UserMod, UserData, DefaultAgentConfig]),
case (catch verify_user_behaviour(UserMod)) of
ok ->
case verify_user_agent_config(DefaultAgentConfig) of
- ok ->
- Config = default_agent_config(DefaultAgentConfig),
+ {ok, DefAgentConf} ->
+ Config = default_agent_config(DefAgentConf),
{ok, #user{id = Id,
mod = UserMod,
data = UserData,
@@ -1783,10 +1916,15 @@ verify_user({Id, _, _, _}) ->
{error, {bad_user_id, Id}}.
verify_user_agent_config(Conf) ->
- case verify_invalid(Conf, [user_id, engine_id, address]) of
- ok ->
- verify_agent_config2(Conf);
- Error ->
+ try
+ begin
+ verify_invalid(Conf, [user_id, engine_id, address]),
+ verify_agent_config2(Conf)
+ end
+ catch
+ throw:Error ->
+ ?vdebug("verify_user_agent_config -> throw"
+ "~n Error: ~p", [Error]),
Error
end.
@@ -2147,6 +2285,16 @@ handle_call({unregister_agent, UserId, TargetName}, _From, State) ->
Reply = handle_unregister_agent(UserId, TargetName),
{reply, Reply, State};
+handle_call({update_agent_info, UserId, TargetName, Info},
+ _From, State) ->
+ ?vlog("received update_agent_info request: "
+ "~n UserId: ~p"
+ "~n TargetName: ~p"
+ "~n Info: ~p", [UserId, TargetName, Info]),
+ Reply = handle_update_agent_info(UserId, TargetName, Info),
+ {reply, Reply, State};
+
+%% <BACKWARD-COMPAT>
handle_call({update_agent_info, UserId, TargetName, Item, Val},
_From, State) ->
?vlog("received update_agent_info request: "
@@ -2156,6 +2304,7 @@ handle_call({update_agent_info, UserId, TargetName, Item, Val},
"~n Val: ~p", [UserId, TargetName, Item, Val]),
Reply = handle_update_agent_info(UserId, TargetName, Item, Val),
{reply, Reply, State};
+%% </BACKWARD-COMPAT>
handle_call({register_usm_user, User}, _From, State) ->
?vlog("received register_usm_user request: "
@@ -2517,16 +2666,27 @@ handle_register_agent(UserId, TargetName, Config) ->
"~n Config: ~p", [UserId, TargetName, Config]),
case (catch agent_info(TargetName, user_id)) of
{error, _} ->
+ ?vtrace("handle_register_agent -> user_id not found in config", []),
case ets:lookup(snmpm_user_table, UserId) of
[#user{default_agent_config = DefConfig}] ->
+ ?vtrace("handle_register_agent -> "
+ "~n DefConfig: ~p", [DefConfig]),
+ %% First, insert this users default config
+ ?vtrace("handle_register_agent -> store default config", []),
do_handle_register_agent(TargetName, DefConfig),
+ %% Second, insert the config for this agent
+ ?vtrace("handle_register_agent -> store config", []),
do_handle_register_agent(TargetName,
[{user_id, UserId}|Config]),
%% <DIRTY-BACKWARD-COMPATIBILLITY>
%% And now for some (backward compatibillity)
%% dirty crossref stuff
+ ?vtrace("handle_register_agent -> lookup address", []),
{ok, Addr} = agent_info(TargetName, address),
+ ?vtrace("handle_register_agent -> Addr: ~p, lookup Port",
+ [Addr]),
{ok, Port} = agent_info(TargetName, port),
+ ?vtrace("handle_register_agent -> register cross-ref fix", []),
ets:insert(snmpm_agent_table,
{{Addr, Port, target_name}, TargetName}),
%% </DIRTY-BACKWARD-COMPATIBILLITY>
@@ -2551,10 +2711,18 @@ handle_register_agent(UserId, TargetName, Config) ->
do_handle_register_agent(_TargetName, []) ->
ok;
do_handle_register_agent(TargetName, [{Item, Val}|Rest]) ->
+ ?vtrace("handle_register_agent -> entry with"
+ "~n TargetName: ~p"
+ "~n Item: ~p"
+ "~n Val: ~p"
+ "~n Rest: ~p", [TargetName, Item, Val, Rest]),
case (catch do_update_agent_info(TargetName, Item, Val)) of
ok ->
do_handle_register_agent(TargetName, Rest);
{error, Reason} ->
+ ?vtrace("handle_register_agent -> failed updating ~p"
+ "~n Item: ~p"
+ "~n Reason: ~p", [Item, Reason]),
ets:match_delete(snmpm_agent_table, {TargetName, '_'}),
{error, Reason}
end;
@@ -2589,41 +2757,61 @@ handle_unregister_agent(UserId, TargetName) ->
end.
-handle_update_agent_info(UserId, TargetName, Item, Val) ->
+handle_update_agent_info(UserId, TargetName, Info) ->
?vdebug("handle_update_agent_info -> entry with"
"~n UserId: ~p"
"~n TargetName: ~p"
- "~n Item: ~p"
- "~n Val: ~p", [UserId, TargetName, Item, Val]),
+ "~n Info: ~p", [UserId, TargetName, Info]),
+ %% Verify ownership
case (catch agent_info(TargetName, user_id)) of
- {ok, UserId} ->
- do_update_agent_info(TargetName, Item, Val);
+ {ok, UserId} ->
+ handle_update_agent_info(TargetName, Info);
{ok, OtherUserId} ->
{error, {not_owner, OtherUserId}};
Error ->
Error
end.
-do_update_agent_info(TargetName, Item, Val0) ->
-%% p("do_update_agent_info -> entry with"
-%% "~n TargetName: ~p"
-%% "~n Item: ~p"
-%% "~n Val0: ~p", [TargetName, Item, Val0]),
- case verify_val(Item, Val0) of
- {ok, Val} ->
-%% p("do_update_agent_info -> verified value"
-%% "~n Val: ~p", [Val]),
- ets:insert(snmpm_agent_table, {{TargetName, Item}, Val}),
- ok;
+handle_update_agent_info(TargetName, Info0) ->
+ ?vtrace("handle_update_agent_info -> entry with"
+ "~n TargetName: ~p"
+ "~n Info0: ~p", [TargetName, Info0]),
+ %% Verify info
+ try verify_agent_info(TargetName, Info0) of
+ {ok, Info} ->
+ do_update_agent_info(TargetName, Info);
Error ->
- ?vlog("do_update_agent_info -> verify value failed: "
- "~n TargetName: ~p"
- "~n Item: ~p"
- "~n Val0: ~p"
- "~n Error: ~p", [TargetName, Item, Val0, Error]),
- {error, {bad_agent_val, TargetName, Item, Val0}}
+ Error
+ catch
+ throw:Error ->
+ Error;
+ T:E ->
+ {error, {failed_info_verification, Info0, T, E}}
end.
+handle_update_agent_info(UserId, TargetName, Item, Val) ->
+ ?vdebug("handle_update_agent_info -> entry with"
+ "~n UserId: ~p"
+ "~n TargetName: ~p"
+ "~n Item: ~p"
+ "~n Val: ~p", [UserId, TargetName, Item, Val]),
+ handle_update_agent_info(TargetName, [{Item, Val}]).
+
+do_update_agent_info(TargetName, Info) ->
+ InsertItem =
+ fun({Item, Val}) ->
+ ets:insert(snmpm_agent_table, {{TargetName, Item}, Val})
+ end,
+ lists:foreach(InsertItem, Info).
+
+do_update_agent_info(TargetName, Item, Val) ->
+ ?vtrace("do_update_agent_info -> entry with"
+ "~n TargetName: ~p"
+ "~n Item: ~p"
+ "~n Val: ~p", [TargetName, Item, Val]),
+ ets:insert(snmpm_agent_table, {{TargetName, Item}, Val}),
+ ok.
+
handle_register_usm_user(#usm_user{engine_id = EngineID,
name = Name} = User) ->
@@ -2791,7 +2979,7 @@ verify_mandatory(Conf, [Mand|Mands]) ->
true ->
verify_mandatory(Conf, Mands);
false ->
- {error, {missing_mandatory_config, Mand}}
+ throw({error, {missing_mandatory_config, Mand}})
end.
verify_invalid(_, []) ->
@@ -2801,7 +2989,7 @@ verify_invalid(Conf, [Inv|Invs]) ->
false ->
verify_invalid(Conf, Invs);
true ->
- {error, {illegal_config, Inv}}
+ throw({error, {illegal_config, Inv}})
end.
@@ -2810,10 +2998,26 @@ verify_val(user_id, UserId) ->
verify_val(reg_type, RegType)
when (RegType =:= addr_port) orelse (RegType =:= target_name) ->
{ok, RegType};
-verify_val(address, Addr0) ->
- case normalize_address(Addr0) of
+verify_val(tdomain = Item, snmpUDPDomain = _Domain) ->
+ verify_val(Item, transportDomainUdpIpv4);
+verify_val(tdomain, Domain) ->
+ case lists:member(Domain, ?SUPPORTED_DOMAINS) of
+ true ->
+ {ok, Domain};
+ false ->
+ case lists:member(Domain, snmp_conf:all_domains()) of
+ true ->
+ error({unsupported_domain, Domain});
+ false ->
+ error({unknown_domain, Domain})
+ end
+ end;
+verify_val(address, {Domain, Addr0}) ->
+ case normalize_address(Domain, Addr0) of
{_A1, _A2, _A3, _A4} = Addr ->
{ok, Addr};
+ {_A1, _A2, _A3, _A4, _A5, _A6, _A7, _A8} = Addr ->
+ {ok, Addr};
_ when is_list(Addr0) ->
case (catch snmp_conf:check_ip(Addr0)) of
ok ->
@@ -2824,6 +3028,8 @@ verify_val(address, Addr0) ->
_ ->
error({bad_address, Addr0})
end;
+verify_val(address, BadAddress) ->
+ error({bad_address, BadAddress});
verify_val(port, Port) ->
case (catch snmp_conf:check_integer(Port, {gt, 0})) of
ok ->
@@ -2875,7 +3081,7 @@ verify_val(sec_name, BadName) ->
verify_val(sec_level, Level) ->
(catch snmp_conf:check_sec_level(Level));
verify_val(Item, _) ->
- {error, {no_such_item, Item}}.
+ {error, {unknown_item, Item}}.
%%%-------------------------------------------------------------------
@@ -3034,11 +3240,17 @@ init_mini_mib_elems(MibName, [_|T], Res) ->
%%----------------------------------------------------------------------
normalize_address(Addr) ->
- case inet:getaddr(Addr, inet) of
+ normalize_address(snmpUDPDomain, Addr).
+
+normalize_address(snmpUDPDomain, Addr) ->
+ normalize_address(transportDomainUdpIpv4, Addr);
+
+normalize_address(Domain, Addr) ->
+ case inet:getaddr(Addr, td2fam(Domain)) of
{ok, Addr2} ->
Addr2;
_ when is_list(Addr) ->
- case (catch snmp_conf:check_ip(Addr)) of
+ case (catch snmp_conf:check_ip(Domain, Addr)) of
ok ->
list_to_tuple(Addr);
_ ->
@@ -3048,6 +3260,9 @@ normalize_address(Addr) ->
Addr
end.
+td2fam(transportDomainUdpIpv4) -> inet;
+td2fam(transportDomainUdpIpv6) -> inet6.
+
%%----------------------------------------------------------------------
diff --git a/lib/snmp/src/manager/snmpm_internal.hrl b/lib/snmp/src/manager/snmpm_internal.hrl
index 5d9b32e3f6..53ad41c6b0 100644
--- a/lib/snmp/src/manager/snmpm_internal.hrl
+++ b/lib/snmp/src/manager/snmpm_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
%%
%% The 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,11 @@
-ifndef(snmpm_internal).
-define(snmpm_internal, true).
+-define(DEFAULT_CONTEXT, "").
+-define(SNMPM_EXTRA_INFO_TAG, snmpm_extra_info_tag).
+-define(DEFAULT_EXTRA_INFO, {?SNMPM_EXTRA_INFO_TAG}).
+
+
-include_lib("snmp/src/app/snmp_internal.hrl").
-define(snmpm_info(F, A), ?snmp_info("manager", F, A)).
diff --git a/lib/snmp/src/manager/snmpm_mpd.erl b/lib/snmp/src/manager/snmpm_mpd.erl
index 7712370d28..103c87d32b 100644
--- a/lib/snmp/src/manager/snmpm_mpd.erl
+++ b/lib/snmp/src/manager/snmpm_mpd.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The 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,7 +92,7 @@ reset(#state{v3 = V3}) ->
%% Purpose: This is the main Message Dispatching function. (see
%% section 4.2.1 in rfc2272)
%%-----------------------------------------------------------------
-process_msg(Msg, TDomain, Addr, Port, State, NoteStore, Logger) ->
+process_msg(Msg, Domain, Addr, Port, State, NoteStore, Logger) ->
inc(snmpInPkts),
@@ -102,18 +102,18 @@ process_msg(Msg, TDomain, Addr, Port, State, NoteStore, Logger) ->
#message{version = 'version-1', vsn_hdr = Community, data = Data}
when State#state.v1 =:= true ->
HS = ?empty_msg_size + length(Community),
- process_v1_v2c_msg('version-1', NoteStore, Msg, TDomain,
- Addr, Port,
+ process_v1_v2c_msg('version-1', NoteStore, Msg,
+ Domain, Addr, Port,
Community, Data, HS, Logger);
%% Version 2
#message{version = 'version-2', vsn_hdr = Community, data = Data}
when State#state.v2c =:= true ->
HS = ?empty_msg_size + length(Community),
- process_v1_v2c_msg('version-2', NoteStore, Msg, TDomain,
- Addr, Port,
- Community, Data, HS, Logger);
-
+ (catch process_v1_v2c_msg('version-2', NoteStore, Msg,
+ Domain, Addr, Port,
+ Community, Data, HS, Logger));
+
%% Version 3
#message{version = 'version-3', vsn_hdr = H, data = Data}
when State#state.v3 =:= true ->
@@ -148,17 +148,30 @@ process_msg(Msg, TDomain, Addr, Port, State, NoteStore, Logger) ->
%%-----------------------------------------------------------------
%% Handles a Community based message (v1 or v2c).
%%-----------------------------------------------------------------
-process_v1_v2c_msg(Vsn, _NoteStore, Msg, snmpUDPDomain,
+process_v1_v2c_msg(Vsn, _NoteStore, Msg, Domain,
Addr, Port,
Community, Data, HS, Log) ->
?vdebug("process_v1_v2c_msg -> entry with"
"~n Vsn: ~p"
+ "~n Domain: ~p"
"~n Addr: ~p"
"~n Port: ~p"
"~n Community: ~p"
- "~n HS: ~p", [Vsn, Addr, Port, Community, HS]),
+ "~n HS: ~p", [Vsn, Domain, Addr, Port, Community, HS]),
+ {TDomain, TAddress} =
+ try
+ begin
+ TD = snmp_conf:mk_tdomain(Domain),
+ TA = snmp_conf:mk_taddress(Domain, Addr, Port),
+ {TD, TA}
+ end
+ catch
+ throw:{error, TReason} ->
+ throw({discarded, {badarg, Domain, TReason}})
+ end,
+
Max = get_max_message_size(),
AgentMax = get_agent_max_message_size(Addr, Port),
PduMS = pdu_ms(Max, AgentMax, HS),
@@ -170,14 +183,14 @@ process_v1_v2c_msg(Vsn, _NoteStore, Msg, snmpUDPDomain,
?vtrace("process_v1_v2c_msg -> was a pdu", []),
Log(Msg),
inc_snmp_in(Pdu),
- MsgData = {Community, sec_model(Vsn)},
+ MsgData = {Community, sec_model(Vsn), TDomain, TAddress},
{ok, Vsn, Pdu, PduMS, MsgData};
Trap when is_record(Trap, trappdu) ->
?vtrace("process_v1_v2c_msg -> was a trap", []),
Log(Msg),
inc_snmp_in(Trap),
- MsgData = {Community, sec_model(Vsn)},
+ MsgData = {Community, sec_model(Vsn), TDomain, TAddress},
{ok, Vsn, Trap, PduMS, MsgData};
{'EXIT', Reason} ->
@@ -185,11 +198,7 @@ process_v1_v2c_msg(Vsn, _NoteStore, Msg, snmpUDPDomain,
"~n Reason: ~p", [Reason]),
inc(snmpInASNParseErrs),
{discarded, Reason}
- end;
-process_v1_v2c_msg(_Vsn, _NoteStore, _Msg, TDomain,
- _Addr, _Port,
- _Comm, _HS, _Data, _Log) ->
- {discarded, {badarg, TDomain}}.
+ end.
pdu_ms(MgrMMS, AgentMMS, HS) when AgentMMS < MgrMMS ->
AgentMMS - HS;
@@ -482,8 +491,8 @@ generate_msg('version-3', NoteStore, Pdu,
generate_v3_msg(NoteStore, Pdu,
SecModel, SecName, SecLevel, CtxEngineID, CtxName,
TargetName, Log);
-generate_msg(Vsn, _NoteStore, Pdu, {Community, _SecModel}, Log) ->
- generate_v1_v2c_msg(Vsn, Pdu, Community, Log).
+generate_msg(Vsn, _NoteStore, Pdu, {Comm, _SecModel}, Log) ->
+ generate_v1_v2c_msg(Vsn, Pdu, Comm, Log).
generate_v3_msg(NoteStore, Pdu,
@@ -627,6 +636,8 @@ generate_response_msg('version-3', Pdu,
generate_v3_response_msg(Pdu, MsgID, SecModel, SecName, SecLevel,
CtxEngineID, CtxName, SecData, Log);
generate_response_msg(Vsn, Pdu, {Comm, _SecModel}, Log) ->
+ generate_v1_v2c_response_msg(Vsn, Pdu, Comm, Log);
+generate_response_msg(Vsn, Pdu, {Comm, _SecModel, _TDomain, _TAddress}, Log) ->
generate_v1_v2c_response_msg(Vsn, Pdu, Comm, Log).
diff --git a/lib/snmp/src/manager/snmpm_net_if.erl b/lib/snmp/src/manager/snmpm_net_if.erl
index 07156dacd9..4d6bd9aa33 100644
--- a/lib/snmp/src/manager/snmpm_net_if.erl
+++ b/lib/snmp/src/manager/snmpm_net_if.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The 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,7 +28,8 @@
start_link/2,
stop/1,
send_pdu/6, % Backward compatibillity
- send_pdu/7,
+ send_pdu/7, % Backward compatibillity
+ send_pdu/8,
inform_response/4,
@@ -99,18 +100,23 @@ stop(Pid) ->
call(Pid, stop).
send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port) ->
- send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port, undefined).
+ send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port, ?DEFAULT_EXTRA_INFO).
-send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo)
+send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo) ->
+ Domain = snmpm_config:default_transport_domain(),
+ send_pdu(Pid, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo).
+
+send_pdu(Pid, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo)
when is_record(Pdu, pdu) ->
?d("send_pdu -> entry with"
"~n Pid: ~p"
"~n Pdu: ~p"
"~n Vsn: ~p"
"~n MsgData: ~p"
+ "~n Domain: ~p"
"~n Addr: ~p"
- "~n Port: ~p", [Pid, Pdu, Vsn, MsgData, Addr, Port]),
- cast(Pid, {send_pdu, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo}).
+ "~n Port: ~p", [Pid, Pdu, Vsn, MsgData, Domain, Addr, Port]),
+ cast(Pid, {send_pdu, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo}).
note_store(Pid, NoteStore) ->
call(Pid, {note_store, NoteStore}).
@@ -380,14 +386,17 @@ handle_call(Req, From, State) ->
%% {noreply, State, Timeout} |
%% {stop, Reason, State} (terminate/2 is called)
%%--------------------------------------------------------------------
-handle_cast({send_pdu, Pdu, Vsn, MsgData, Addr, Port, _ExtraInfo}, State) ->
+handle_cast({send_pdu, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo},
+ State) ->
?vlog("received send_pdu message with"
"~n Pdu: ~p"
"~n Vsn: ~p"
"~n MsgData: ~p"
+ "~n Domain: ~p"
"~n Addr: ~p"
- "~n Port: ~p", [Pdu, Vsn, MsgData, Addr, Port]),
- maybe_handle_send_pdu(Pdu, Vsn, MsgData, Addr, Port, State),
+ "~n Port: ~p", [Pdu, Vsn, MsgData, Domain, Addr, Port]),
+ maybe_process_extra_info(ExtraInfo),
+ maybe_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, State),
{noreply, State};
handle_cast({inform_response, Ref, Addr, Port}, State) ->
@@ -544,8 +553,9 @@ handle_recv_msg(Addr, Port, Bytes,
mpd_state = MpdState,
sock = Sock,
log = Log} = State) ->
+ Domain = snmp_conf:which_domain(Addr), % What the ****...
Logger = logger(Log, read, Addr, Port),
- case (catch snmpm_mpd:process_msg(Bytes, snmpUDPDomain, Addr, Port,
+ case (catch snmpm_mpd:process_msg(Bytes, Domain, Addr, Port,
MpdState, NoteStore, Logger)) of
{ok, Vsn, Pdu, MS, ACM} ->
@@ -733,17 +743,17 @@ irgc_stop(Ref) ->
(catch erlang:cancel_timer(Ref)).
-maybe_handle_send_pdu(Pdu, Vsn, MsgData, Addr, Port,
+maybe_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port,
#state{filter = FilterMod} = State) ->
case (catch FilterMod:accept_send_pdu(Addr, Port, pdu_type_of(Pdu))) of
false ->
inc(netIfPduOutDrops),
ok;
_ ->
- handle_send_pdu(Pdu, Vsn, MsgData, Addr, Port, State)
+ handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, State)
end.
-handle_send_pdu(Pdu, Vsn, MsgData, Addr, Port,
+handle_send_pdu(Pdu, Vsn, MsgData, _Domain, Addr, Port,
#state{server = Pid,
note_store = NoteStore,
sock = Sock,
@@ -999,6 +1009,19 @@ pdu_type_of(TrapPdu) when is_record(TrapPdu, trappdu) ->
%% -------------------------------------------------------------------
+%% At this point this function is used during testing
+maybe_process_extra_info(?DEFAULT_EXTRA_INFO) ->
+ ok;
+maybe_process_extra_info({?SNMPM_EXTRA_INFO_TAG, Fun})
+ when is_function(Fun, 0) ->
+ (catch Fun()),
+ ok;
+maybe_process_extra_info(_ExtraInfo) ->
+ ok.
+
+
+%% -------------------------------------------------------------------
+
t() ->
{A,B,C} = erlang:now(),
A*1000000000+B*1000+(C div 1000).
diff --git a/lib/snmp/src/manager/snmpm_server.erl b/lib/snmp/src/manager/snmpm_server.erl
index d64b5b1d53..484954addb 100644
--- a/lib/snmp/src/manager/snmpm_server.erl
+++ b/lib/snmp/src/manager/snmpm_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The 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,14 +32,14 @@
register_user/4, register_user_monitor/4, unregister_user/1,
- sync_get/4, sync_get/5, sync_get/6,
- async_get/4, async_get/5, async_get/6,
- sync_get_next/4, sync_get_next/5, sync_get_next/6,
- async_get_next/4, async_get_next/5, async_get_next/6,
- sync_get_bulk/6, sync_get_bulk/7, sync_get_bulk/8,
- async_get_bulk/6, async_get_bulk/7, async_get_bulk/8,
- sync_set/4, sync_set/5, sync_set/6,
- async_set/4, async_set/5, async_set/6,
+ sync_get2/4,
+ async_get2/4,
+ sync_get_next2/4,
+ async_get_next2/4,
+ sync_get_bulk2/6,
+ async_get_bulk2/6,
+ sync_set2/4,
+ async_set2/4,
cancel_async_request/2,
%% discovery/2, discovery/3, discovery/4, discovery/5, discovery/6,
@@ -55,6 +55,20 @@
]).
+%% <BACKWARD-COMPAT>
+-export([sync_get/4, sync_get/5, sync_get/6,
+ async_get/4, async_get/5, async_get/6,
+ sync_get_next/4, sync_get_next/5, sync_get_next/6,
+ async_get_next/4, async_get_next/5, async_get_next/6,
+ sync_get_bulk/6, sync_get_bulk/7, sync_get_bulk/8,
+ async_get_bulk/6, async_get_bulk/7, async_get_bulk/8,
+ sync_set/4, sync_set/5, sync_set/6,
+ async_set/4, async_set/5, async_set/6
+ ]).
+%% </BACKWARD-COMPAT>
+
+
+
%% Internal exports
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
code_change/3, terminate/2]).
@@ -75,13 +89,39 @@
-define(SERVER, ?MODULE).
--define(SYNC_GET_TIMEOUT, 5000).
--define(SYNC_SET_TIMEOUT, 5000).
--define(DEFAULT_ASYNC_EXPIRE, 5000).
--define(EXTRA_INFO, undefined).
-
--define(SNMP_AGENT_PORT, 161).
-
+-define(DEFAULT_SYNC_TIMEOUT, timer:seconds(5)).
+-define(DEFAULT_SYNC_GET_TIMEOUT, ?DEFAULT_SYNC_TIMEOUT).
+-define(DEFAULT_SYNC_GET_NEXT_TIMEOUT, ?DEFAULT_SYNC_TIMEOUT).
+-define(DEFAULT_SYNC_GET_BULK_TIMEOUT, ?DEFAULT_SYNC_TIMEOUT).
+-define(DEFAULT_SYNC_SET_TIMEOUT, ?DEFAULT_SYNC_TIMEOUT).
+
+-define(DEFAULT_ASYNC_TIMEOUT, timer:seconds(5)).
+-define(DEFAULT_ASYNC_GET_TIMEOUT, ?DEFAULT_ASYNC_TIMEOUT).
+-define(DEFAULT_ASYNC_GET_NEXT_TIMEOUT, ?DEFAULT_ASYNC_TIMEOUT).
+-define(DEFAULT_ASYNC_GET_BULK_TIMEOUT, ?DEFAULT_ASYNC_TIMEOUT).
+-define(DEFAULT_ASYNC_SET_TIMEOUT, ?DEFAULT_ASYNC_TIMEOUT).
+
+-define(SNMP_AGENT_PORT, 161).
+
+-define(SYNC_GET_TIMEOUT(SendOpts),
+ get_opt(timeout, ?DEFAULT_SYNC_GET_TIMEOUT, SendOpts)).
+-define(SYNC_GET_NEXT_TIMEOUT(SendOpts),
+ get_opt(timeout, ?DEFAULT_SYNC_GET_NEXT_TIMEOUT, SendOpts)).
+-define(SYNC_GET_BULK_TIMEOUT(SendOpts),
+ get_opt(timeout, ?DEFAULT_SYNC_GET_BULK_TIMEOUT, SendOpts)).
+-define(SYNC_SET_TIMEOUT(SendOpts),
+ get_opt(timeout, ?DEFAULT_SYNC_SET_TIMEOUT, SendOpts)).
+
+-define(ASYNC_GET_TIMEOUT(SendOpts),
+ get_opt(timeout, ?DEFAULT_ASYNC_GET_TIMEOUT, SendOpts)).
+-define(ASYNC_GET_NEXT_TIMEOUT(SendOpts),
+ get_opt(timeout, ?DEFAULT_ASYNC_GET_NEXT_TIMEOUT, SendOpts)).
+-define(ASYNC_GET_BULK_TIMEOUT(SendOpts),
+ get_opt(timeout, ?DEFAULT_ASYNC_GET_BULK_TIMEOUT, SendOpts)).
+-define(ASYNC_SET_TIMEOUT(SendOpts),
+ get_opt(timeout, ?DEFAULT_ASYNC_SET_TIMEOUT, SendOpts)).
+
+-define(GET_EXTRA(SendOpts), get_opt(extra, ?DEFAULT_EXTRA_INFO, SendOpts)).
-ifdef(snmp_debug).
-define(GS_START_LINK(Args),
@@ -121,7 +161,8 @@
{id,
user_id,
reg_type,
- target,
+ target,
+ domain,
addr,
port,
type,
@@ -192,82 +233,140 @@ unregister_user(UserId) ->
%% -- [sync] get --
+%% The reason why we have a sync_get2 is to simplify backward
+%% compatibillity.
+
+%% sync_get2(UserId, TargetName, Oids) ->
+%% sync_get2(UserId, TargetName, Oids, []).
+sync_get2(UserId, TargetName, Oids, Opts) ->
+ call({sync_get, self(), UserId, TargetName, Oids, Opts}).
+
+
+%% <BACKWARD-COMPAT>
sync_get(UserId, TargetName, CtxName, Oids) ->
sync_get(UserId, TargetName, CtxName, Oids,
- ?SYNC_GET_TIMEOUT).
+ ?DEFAULT_SYNC_GET_TIMEOUT).
sync_get(UserId, TargetName, CtxName, Oids, Timeout) ->
- sync_get(UserId, TargetName, CtxName, Oids, Timeout, ?EXTRA_INFO).
+ sync_get(UserId, TargetName, CtxName, Oids, Timeout, ?DEFAULT_EXTRA_INFO).
sync_get(UserId, TargetName, CtxName, Oids, Timeout, ExtraInfo)
when is_list(TargetName) andalso
is_list(CtxName) andalso
is_list(Oids) andalso
is_integer(Timeout) ->
- call({sync_get, self(), UserId, TargetName, CtxName, Oids, Timeout, ExtraInfo}).
+ Opts = [{context, CtxName}, {timeout, Timeout}, {extra, ExtraInfo}],
+ sync_get2(UserId, TargetName, Oids, Opts).
+%% </BACKWARD-COMPAT>
+
+
%% -- [async] get --
+%% async_get2(UserId, TargetName, Oids) ->
+%% async_get2(UserId, TargetName, Oids, []).
+async_get2(UserId, TargetName, Oids, SendOpts) ->
+ call({async_get, self(), UserId, TargetName, Oids, SendOpts}).
+
+
+%% <BACKWARD-COMPAT>
async_get(UserId, TargetName, CtxName, Oids) ->
async_get(UserId, TargetName, CtxName, Oids,
- ?DEFAULT_ASYNC_EXPIRE, ?EXTRA_INFO).
+ ?DEFAULT_ASYNC_GET_TIMEOUT, ?DEFAULT_EXTRA_INFO).
async_get(UserId, TargetName, CtxName, Oids, Expire) ->
- async_get(UserId, TargetName, CtxName, Oids, Expire, ?EXTRA_INFO).
+ async_get(UserId, TargetName, CtxName, Oids, Expire, ?DEFAULT_EXTRA_INFO).
async_get(UserId, TargetName, CtxName, Oids, Expire, ExtraInfo)
when (is_list(TargetName) andalso
is_list(CtxName) andalso
is_list(Oids) andalso
is_integer(Expire) andalso (Expire >= 0)) ->
- call({async_get, self(), UserId, TargetName, CtxName, Oids, Expire,
- ExtraInfo}).
+ SendOpts = [{context, CtxName}, {expire, Expire}, {extra, ExtraInfo}],
+ async_get2(UserId, TargetName, Oids, SendOpts).
+%% </BACKWARD-COMPAT>
+
+
%% -- [sync] get-next --
+%% sync_get_next2(UserId, TargetName, Oids) ->
+%% sync_get_next2(UserId, TargetName, Oids, []).
+sync_get_next2(UserId, TargetName, Oids, SendOpts) ->
+ call({sync_get_next, self(), UserId, TargetName, Oids, SendOpts}).
+
+
+%% <BACKWARD-COMPAT>
sync_get_next(UserId, TargetName, CtxName, Oids) ->
- sync_get_next(UserId, TargetName, CtxName, Oids, ?SYNC_GET_TIMEOUT,
- ?EXTRA_INFO).
+ sync_get_next(UserId, TargetName, CtxName, Oids,
+ ?DEFAULT_SYNC_GET_TIMEOUT, ?DEFAULT_EXTRA_INFO).
sync_get_next(UserId, TargetName, CtxName, Oids, Timeout) ->
- sync_get_next(UserId, TargetName, CtxName, Oids, Timeout, ?EXTRA_INFO).
+ sync_get_next(UserId, TargetName, CtxName, Oids, Timeout,
+ ?DEFAULT_EXTRA_INFO).
sync_get_next(UserId, TargetName, CtxName, Oids, Timeout, ExtraInfo)
when is_list(TargetName) andalso
is_list(CtxName) andalso
is_list(Oids) andalso
is_integer(Timeout) ->
- call({sync_get_next, self(), UserId, TargetName, CtxName, Oids, Timeout,
- ExtraInfo}).
+ SendOpts = [{context, CtxName}, {timeout, Timeout}, {extra, ExtraInfo}],
+ sync_get_next2(UserId, TargetName, Oids, SendOpts).
+%% <BACKWARD-COMPAT>
+
+
%% -- [async] get-next --
+%% async_get_next2(UserId, TargetName, Oids) ->
+%% async_get_next2(UserId, TargetName, Oids, []).
+async_get_next2(UserId, TargetName, Oids, SendOpts) ->
+ call({async_get_next, self(), UserId, TargetName, Oids, SendOpts}).
+
+
async_get_next(UserId, TargetName, CtxName, Oids) ->
async_get_next(UserId, TargetName, CtxName, Oids,
- ?DEFAULT_ASYNC_EXPIRE, ?EXTRA_INFO).
+ ?DEFAULT_ASYNC_GET_NEXT_TIMEOUT, ?DEFAULT_EXTRA_INFO).
async_get_next(UserId, TargetName, CtxName, Oids, Expire) ->
- async_get_next(UserId, TargetName, CtxName, Oids, Expire, ?EXTRA_INFO).
+ async_get_next(UserId, TargetName, CtxName, Oids, Expire,
+ ?DEFAULT_EXTRA_INFO).
async_get_next(UserId, TargetName, CtxName, Oids, Expire, ExtraInfo)
when (is_list(TargetName) andalso
is_list(CtxName) andalso
is_list(Oids) andalso
is_integer(Expire) andalso (Expire >= 0)) ->
- call({async_get_next, self(), UserId, TargetName, CtxName, Oids,
- Expire, ExtraInfo}).
+ SendOpts = [{context, CtxName}, {expire, Expire}, {extra, ExtraInfo}],
+ async_get_next2(UserId, TargetName, Oids, SendOpts).
+
+
%% -- [sync] get-bulk --
+%% sync_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids) ->
+%% sync_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, []).
+sync_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts) ->
+ %% p("sync_get_bulk2 -> entry with"
+ %% "~n UserId: ~p"
+ %% "~n TargetName: ~p"
+ %% "~n NonRep: ~p"
+ %% "~n MaxRep: ~p"
+ %% "~n Oids: ~p"
+ %% "~n SendOpts: ~p",
+ %% [UserId, TargetName, NonRep, MaxRep, Oids, SendOpts]),
+ call({sync_get_bulk, self(), UserId, TargetName,
+ NonRep, MaxRep, Oids, SendOpts}).
+
sync_get_bulk(UserId, TargetName, NonRep, MaxRep, CtxName, Oids) ->
sync_get_bulk(UserId, TargetName,
NonRep, MaxRep, CtxName, Oids,
- ?SYNC_GET_TIMEOUT, ?EXTRA_INFO).
+ ?DEFAULT_SYNC_GET_TIMEOUT, ?DEFAULT_EXTRA_INFO).
sync_get_bulk(UserId, TargetName, NonRep, MaxRep, CtxName, Oids, Timeout) ->
sync_get_bulk(UserId, TargetName,
NonRep, MaxRep, CtxName, Oids,
- Timeout, ?EXTRA_INFO).
+ Timeout, ?DEFAULT_EXTRA_INFO).
sync_get_bulk(UserId, TargetName, NonRep, MaxRep, CtxName, Oids, Timeout,
ExtraInfo)
@@ -277,20 +376,28 @@ sync_get_bulk(UserId, TargetName, NonRep, MaxRep, CtxName, Oids, Timeout,
is_list(CtxName) andalso
is_list(Oids) andalso
is_integer(Timeout) ->
- call({sync_get_bulk, self(), UserId, TargetName,
- NonRep, MaxRep, CtxName, Oids, Timeout, ExtraInfo}).
+ SendOpts = [{context, CtxName}, {timeout, Timeout}, {extra, ExtraInfo}],
+ sync_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts).
+
%% -- [async] get-bulk --
+%% async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids) ->
+%% async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, []).
+async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts) ->
+ call({async_get_bulk, self(), UserId, TargetName, NonRep, MaxRep,
+ Oids, SendOpts}).
+
+
async_get_bulk(UserId, TargetName, NonRep, MaxRep, CtxName, Oids) ->
async_get_bulk(UserId, TargetName,
NonRep, MaxRep, CtxName, Oids,
- ?DEFAULT_ASYNC_EXPIRE, ?EXTRA_INFO).
+ ?DEFAULT_ASYNC_GET_BULK_TIMEOUT, ?DEFAULT_EXTRA_INFO).
async_get_bulk(UserId, TargetName, NonRep, MaxRep, CtxName, Oids, Expire) ->
async_get_bulk(UserId, TargetName,
NonRep, MaxRep, CtxName, Oids,
- Expire, ?EXTRA_INFO).
+ Expire, ?DEFAULT_EXTRA_INFO).
async_get_bulk(UserId, TargetName, NonRep, MaxRep, CtxName, Oids, Expire,
ExtraInfo)
@@ -300,45 +407,61 @@ async_get_bulk(UserId, TargetName, NonRep, MaxRep, CtxName, Oids, Expire,
is_list(CtxName) andalso
is_list(Oids) andalso
is_integer(Expire) ->
- call({async_get_bulk, self(), UserId, TargetName,
- NonRep, MaxRep, CtxName, Oids, Expire, ExtraInfo}).
+ SendOpts = [{context, CtxName}, {expire, Expire}, {extra, ExtraInfo}],
+ async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts).
+
+
%% -- [sync] set --
%% VarsAndValues is: {PlainOid, o|s|i, Value} (unknown mibs) | {Oid, Value}
+%% sync_set2(UserId, TargetName, VarsAndVals) ->
+%% sync_set2(UserId, TargetName, VarsAndVals, []).
+sync_set2(UserId, TargetName, VarsAndVals, SendOpts) ->
+ call({sync_set, self(), UserId, TargetName, VarsAndVals, SendOpts}).
+
+
sync_set(UserId, TargetName, CtxName, VarsAndVals) ->
sync_set(UserId, TargetName, CtxName, VarsAndVals,
- ?SYNC_SET_TIMEOUT, ?EXTRA_INFO).
+ ?DEFAULT_SYNC_SET_TIMEOUT, ?DEFAULT_EXTRA_INFO).
sync_set(UserId, TargetName, CtxName, VarsAndVals, Timeout) ->
sync_set(UserId, TargetName, CtxName, VarsAndVals,
- Timeout, ?EXTRA_INFO).
+ Timeout, ?DEFAULT_EXTRA_INFO).
sync_set(UserId, TargetName, CtxName, VarsAndVals, Timeout, ExtraInfo)
when is_list(TargetName) andalso
is_list(CtxName) andalso
is_list(VarsAndVals) andalso
is_integer(Timeout) ->
- call({sync_set, self(), UserId, TargetName,
- CtxName, VarsAndVals, Timeout, ExtraInfo}).
+ SendOpts = [{context, CtxName}, {timeout, Timeout}, {extra, ExtraInfo}],
+ sync_set2(UserId, TargetName, VarsAndVals, SendOpts).
+
+
%% -- [async] set --
+%% async_set2(UserId, TargetName, VarsAndVals) ->
+%% async_set2(UserId, TargetName, VarsAndVals, []).
+async_set2(UserId, TargetName, VarsAndVals, SendOpts) ->
+ call({async_set, self(), UserId, TargetName, VarsAndVals, SendOpts}).
+
+
async_set(UserId, TargetName, CtxName, VarsAndVals) ->
async_set(UserId, TargetName, CtxName, VarsAndVals,
- ?DEFAULT_ASYNC_EXPIRE, ?EXTRA_INFO).
+ ?DEFAULT_ASYNC_SET_TIMEOUT, ?DEFAULT_EXTRA_INFO).
async_set(UserId, TargetName, CtxName, VarsAndVals, Expire) ->
async_set(UserId, TargetName, CtxName, VarsAndVals,
- Expire, ?EXTRA_INFO).
+ Expire, ?DEFAULT_EXTRA_INFO).
async_set(UserId, TargetName, CtxName, VarsAndVals, Expire, ExtraInfo)
when (is_list(TargetName) andalso
is_list(CtxName) andalso
is_list(VarsAndVals) andalso
is_integer(Expire) andalso (Expire >= 0)) ->
- call({async_set, self(), UserId, TargetName,
- CtxName, VarsAndVals, Expire, ExtraInfo}).
+ SendOpts = [{context, CtxName}, {expire, Expire}, {extra, ExtraInfo}],
+ async_set2(UserId, TargetName, VarsAndVals, SendOpts).
cancel_async_request(UserId, ReqId) ->
@@ -571,9 +694,26 @@ handle_call({unregister_user, UserId}, _From, State) ->
%% We will reply to this request later, when the reply comes in from the
%% agent, or when the timeout hits (unless we get an error now).
-handle_call({sync_get, Pid, UserId, TargetName, CtxName, Oids, Timeout, ExtraInfo},
+handle_call({sync_get, Pid, UserId, TargetName, Oids, SendOpts},
From, State) ->
- ?vlog("received sync_get [~p] request", [CtxName]),
+ ?vlog("[~p,~p] received sync_get request for: "
+ "~n ~p", [UserId, TargetName, Oids]),
+ case (catch handle_sync_get(Pid,
+ UserId, TargetName, Oids, SendOpts,
+ From, State)) of
+ ok ->
+ {noreply, State};
+ Error ->
+ {reply, Error, State}
+ end;
+
+%% <BACKWARD-COMPAT>
+%% The only case where this would be called is during code upgrade
+handle_call({sync_get,
+ Pid, UserId, TargetName, CtxName, Oids, Timeout, ExtraInfo},
+ From, State) ->
+ ?vlog("[~p,~p,~p] received sync_get request for: "
+ "~n ~p", [UserId, TargetName, CtxName, Oids]),
case (catch handle_sync_get(Pid,
UserId, TargetName, CtxName, Oids,
Timeout, ExtraInfo, From, State)) of
@@ -582,10 +722,30 @@ handle_call({sync_get, Pid, UserId, TargetName, CtxName, Oids, Timeout, ExtraInf
Error ->
{reply, Error, State}
end;
+%% </BACKWARD-COMPAT>
-handle_call({sync_get_next, Pid, UserId, TargetName, CtxName, Oids, Timeout, ExtraInfo}, From, State) ->
- ?vlog("received sync_get_next [~p] request", [CtxName]),
+handle_call({sync_get_next, Pid, UserId, TargetName, Oids, SendOpts},
+ From, State) ->
+ ?vlog("[~p,~p] received sync_get_next request for: "
+ "~n ~p", [UserId, TargetName, SendOpts]),
+ case (catch handle_sync_get_next(Pid,
+ UserId, TargetName, Oids, SendOpts,
+ From, State)) of
+ ok ->
+ {noreply, State};
+ Error ->
+ {reply, Error, State}
+ end;
+
+
+%% <BACKWARD-COMPAT>
+%% The only case where this would be called is during code upgrade
+handle_call({sync_get_next,
+ Pid, UserId, TargetName, CtxName, Oids, Timeout, ExtraInfo},
+ From, State) ->
+ ?vlog("[~p,~p,~p] received sync_get_next request for"
+ "~n ~p", [UserId, TargetName, CtxName, Oids]),
case (catch handle_sync_get_next(Pid,
UserId, TargetName, CtxName, Oids,
Timeout, ExtraInfo, From, State)) of
@@ -594,13 +754,31 @@ handle_call({sync_get_next, Pid, UserId, TargetName, CtxName, Oids, Timeout, Ext
Error ->
{reply, Error, State}
end;
+%% </BACKWARD-COMPAT>
%% Check agent version? This op not in v1
+handle_call({sync_get_bulk,
+ Pid, UserId, TargetName, NonRep, MaxRep, Oids, SendOpts},
+ From, State) ->
+ ?vlog("[~p,~p] received sync_get_bulk request for: "
+ "~n ~p", [UserId, TargetName, Oids]),
+ case (catch handle_sync_get_bulk(Pid,
+ UserId, TargetName, NonRep, MaxRep, Oids,
+ SendOpts, From, State)) of
+ ok ->
+ {noreply, State};
+ Error ->
+ {reply, Error, State}
+ end;
+
+%% <BACKWARD-COMPAT>
+%% The only case where this would be called is during code upgrade
handle_call({sync_get_bulk, Pid, UserId, TargetName,
NonRep, MaxRep, CtxName, Oids, Timeout, ExtraInfo},
From, State) ->
- ?vlog("received sync_get_bulk [~p] request", [CtxName]),
+ ?vlog("[~p,~p] received sync_get_bulk request for: ~p"
+ "~n ~p", [UserId, TargetName, CtxName, Oids]),
case (catch handle_sync_get_bulk(Pid,
UserId, TargetName, CtxName,
NonRep, MaxRep, Oids,
@@ -610,12 +788,31 @@ handle_call({sync_get_bulk, Pid, UserId, TargetName,
Error ->
{reply, Error, State}
end;
+%% </BACKWARD-COMPAT>
+
+
+handle_call({sync_set,
+ Pid, UserId, TargetName, VarsAndVals, SendOpts},
+ From, State) ->
+ ?vlog("[~p,~p] received sync_set request for: "
+ "~n ~p", [UserId, TargetName, VarsAndVals]),
+ case (catch handle_sync_set(Pid,
+ UserId, TargetName, VarsAndVals, SendOpts,
+ From, State)) of
+ ok ->
+ {noreply, State};
+ Error ->
+ {reply, Error, State}
+ end;
+%% <BACKWARD-COMPAT>
+%% The only case where this would be called is during code upgrade
handle_call({sync_set, Pid, UserId, TargetName,
CtxName, VarsAndVals, Timeout, ExtraInfo},
From, State) ->
- ?vlog("received sync_set [~p] request", [CtxName]),
+ ?vlog("[~p,~p,~p] received sync_set request for: "
+ "~n ~p", [UserId, TargetName, CtxName, VarsAndVals]),
case (catch handle_sync_set(Pid,
UserId, TargetName, CtxName, VarsAndVals,
Timeout, ExtraInfo, From, State)) of
@@ -624,45 +821,105 @@ handle_call({sync_set, Pid, UserId, TargetName,
Error ->
{reply, Error, State}
end;
+%% </BACKWARD-COMPAT>
+handle_call({async_get, Pid, UserId, TargetName, Oids, SendOpts},
+ _From, State) ->
+ ?vlog("[~p,~p] received async_get request for: "
+ "~n ~p", [UserId, TargetName, Oids]),
+ Reply = (catch handle_async_get(Pid,
+ UserId, TargetName, Oids, SendOpts,
+ State)),
+ {reply, Reply, State};
+
+
+%% <BACKWARD-COMPAT>
+%% The only case where this would be called is during code upgrade
handle_call({async_get, Pid, UserId, TargetName,
CtxName, Oids, Expire, ExtraInfo},
_From, State) ->
- ?vlog("received async_get [~p] request", [CtxName]),
+ ?vlog("[~p,~p,~p] received async_get request for: "
+ "~n ~p", [UserId, TargetName, CtxName, Oids]),
Reply = (catch handle_async_get(Pid, UserId, TargetName, CtxName, Oids,
Expire, ExtraInfo, State)),
{reply, Reply, State};
+%% </BACKWARD-COMPAT>
+handle_call({async_get_next, Pid, UserId, TargetName, Oids, SendOpts},
+ _From, State) ->
+ ?vlog("[~p,~p] received async_get_next request for: "
+ "~n ~p", [UserId, TargetName, Oids]),
+ Reply = (catch handle_async_get_next(Pid,
+ UserId, TargetName, Oids, SendOpts,
+ State)),
+ {reply, Reply, State};
+
+
+%% <BACKWARD-COMPAT>
+%% The only case where this would be called is during code upgrade
handle_call({async_get_next, Pid, UserId, TargetName,
CtxName, Oids, Expire, ExtraInfo},
_From, State) ->
- ?vlog("received async_get_next [~p] request", [CtxName]),
+ ?vlog("[~p,~p,~p] received async_get_next request for: ",
+ [UserId, TargetName, CtxName, Oids]),
Reply = (catch handle_async_get_next(Pid, UserId, TargetName, CtxName,
Oids, Expire, ExtraInfo, State)),
{reply, Reply, State};
+%% </BACKWARD-COMPAT>
%% Check agent version? This op not in v1
+handle_call({async_get_bulk,
+ Pid, UserId, TargetName, NonRep, MaxRep, Oids, SendOpts},
+ _From, State) ->
+ ?vlog("[~p,~p] received async_get_bulk request for: "
+ "~n ~p", [UserId, TargetName, Oids]),
+ Reply = (catch handle_async_get_bulk(Pid,
+ UserId, TargetName,
+ NonRep, MaxRep, Oids, SendOpts,
+ State)),
+ {reply, Reply, State};
+
+
+%% <BACKWARD-COMPAT>
+%% The only case where this would be called is during code upgrade
handle_call({async_get_bulk, Pid, UserId, TargetName,
NonRep, MaxRep, CtxName, Oids, Expire, ExtraInfo},
_From, State) ->
- ?vlog("received async_get_bulk [~p] request", [CtxName]),
+ ?vlog("[~p,~p,~p] received async_get_bulk request for: "
+ "~n ~p", [UserId, TargetName, CtxName, Oids]),
Reply = (catch handle_async_get_bulk(Pid,
UserId, TargetName, CtxName,
NonRep, MaxRep, Oids,
Expire, ExtraInfo, State)),
{reply, Reply, State};
+%% </BACKWARD-COMPAT>
+handle_call({async_set,
+ Pid, UserId, TargetName, VarsAndVals, SendOpts},
+ _From, State) ->
+ ?vlog("[~p,~p] received async_set request for: "
+ "~n ~p", [UserId, TargetName, VarsAndVals]),
+ Reply = (catch handle_async_set(Pid,
+ UserId, TargetName, VarsAndVals, SendOpts,
+ State)),
+ {reply, Reply, State};
+
+
+%% <BACKWARD-COMPAT>
+%% The only case where this would be called is during code upgrade
handle_call({async_set, Pid, UserId, TargetName,
CtxName, VarsAndVals, Expire, ExtraInfo},
_From, State) ->
- ?vlog("received async_set [~p] request", [CtxName]),
+ ?vlog("[~p,~p,~p] received async_set request for: "
+ "~n ~p", [UserId, TargetName, CtxName, VarsAndVals]),
Reply = (catch handle_async_set(Pid, UserId, TargetName, CtxName,
VarsAndVals, Expire, ExtraInfo, State)),
{reply, Reply, State};
+%% </BACKWARD-COMPAT>
handle_call({cancel_async_request, UserId, ReqId}, _From, State) ->
@@ -901,36 +1158,48 @@ terminate(Reason, #state{gct = GCT}) ->
handle_sync_get(Pid, UserId, TargetName, CtxName, Oids, Timeout, ExtraInfo,
From, State) ->
+ SendOpts =
+ [
+ {context, CtxName},
+ {timeout, Timeout},
+ {extra, ExtraInfo}
+ ],
+ handle_sync_get(Pid, UserId, TargetName, Oids, SendOpts, From, State).
+
+handle_sync_get(Pid, UserId, TargetName, Oids, SendOpts, From, State) ->
?vtrace("handle_sync_get -> entry with"
"~n Pid: ~p"
"~n UserId: ~p"
"~n TargetName: ~p"
- "~n CtxName: ~p"
"~n Oids: ~p"
- "~n Timeout: ~p"
+ "~n SendOpts: ~p"
"~n From: ~p",
- [Pid, UserId, TargetName, CtxName, Oids, Timeout, From]),
- case agent_data(TargetName, CtxName) of
- {ok, RegType, Addr, Port, Vsn, MsgData} ->
+ [Pid, UserId, TargetName, Oids, SendOpts, From]),
+ case agent_data(TargetName, SendOpts) of
+ {ok, RegType, Domain, Addr, Port, Vsn, MsgData} ->
?vtrace("handle_sync_get -> send a ~p message", [Vsn]),
- ReqId = send_get_request(Oids, Vsn, MsgData, Addr, Port,
- ExtraInfo, State),
+ Extra = ?GET_EXTRA(SendOpts),
+ ReqId = send_get_request(Oids, Vsn, MsgData,
+ Domain, Addr, Port,
+ Extra, State),
?vdebug("handle_sync_get -> ReqId: ~p", [ReqId]),
- Msg = {sync_timeout, ReqId, From},
- Ref = erlang:send_after(Timeout, self(), Msg),
- MonRef = erlang:monitor(process, Pid),
+ Msg = {sync_timeout, ReqId, From},
+ Timeout = ?SYNC_GET_TIMEOUT(SendOpts),
+ Ref = erlang:send_after(Timeout, self(), Msg),
+ MonRef = erlang:monitor(process, Pid),
?vtrace("handle_sync_get -> MonRef: ~p", [MonRef]),
- Req = #request{id = ReqId,
- user_id = UserId,
- reg_type = RegType,
- target = TargetName,
- addr = Addr,
- port = Port,
- type = get,
- data = MsgData,
- ref = Ref,
- mon = MonRef,
- from = From},
+ Req = #request{id = ReqId,
+ user_id = UserId,
+ reg_type = RegType,
+ target = TargetName,
+ domain = Domain,
+ addr = Addr,
+ port = Port,
+ type = get,
+ data = MsgData,
+ ref = Ref,
+ mon = MonRef,
+ from = From},
ets:insert(snmpm_request_table, Req),
ok;
Error ->
@@ -940,39 +1209,51 @@ handle_sync_get(Pid, UserId, TargetName, CtxName, Oids, Timeout, ExtraInfo,
Error
end.
-
handle_sync_get_next(Pid, UserId, TargetName, CtxName, Oids, Timeout,
ExtraInfo, From, State) ->
+ SendOpts =
+ [
+ {context, CtxName},
+ {timeout, Timeout},
+ {extra, ExtraInfo}
+ ],
+ handle_sync_get_next(Pid, UserId, TargetName, Oids, SendOpts, From, State).
+
+handle_sync_get_next(Pid, UserId, TargetName, Oids, SendOpts,
+ From, State) ->
?vtrace("handle_sync_get_next -> entry with"
"~n Pid: ~p"
"~n UserId: ~p"
"~n TargetName: ~p"
- "~n CtxName: ~p"
"~n Oids: ~p"
- "~n Timeout: ~p"
+ "~n SendOpts: ~p"
"~n From: ~p",
- [Pid, UserId, TargetName, CtxName, Oids, Timeout, From]),
- case agent_data(TargetName, CtxName) of
- {ok, RegType, Addr, Port, Vsn, MsgData} ->
+ [Pid, UserId, TargetName, Oids, SendOpts, From]),
+ case agent_data(TargetName, SendOpts) of
+ {ok, RegType, Domain, Addr, Port, Vsn, MsgData} ->
?vtrace("handle_sync_get_next -> send a ~p message", [Vsn]),
- ReqId = send_get_next_request(Oids, Vsn, MsgData,
- Addr, Port, ExtraInfo, State),
+ Extra = ?GET_EXTRA(SendOpts),
+ ReqId = send_get_next_request(Oids, Vsn, MsgData,
+ Domain, Addr, Port,
+ Extra, State),
?vdebug("handle_sync_get_next -> ReqId: ~p", [ReqId]),
- Msg = {sync_timeout, ReqId, From},
- Ref = erlang:send_after(Timeout, self(), Msg),
- MonRef = erlang:monitor(process, Pid),
+ Msg = {sync_timeout, ReqId, From},
+ Timeout = ?SYNC_GET_NEXT_TIMEOUT(SendOpts),
+ Ref = erlang:send_after(Timeout, self(), Msg),
+ MonRef = erlang:monitor(process, Pid),
?vtrace("handle_sync_get_next -> MonRef: ~p", [MonRef]),
- Req = #request{id = ReqId,
- user_id = UserId,
- reg_type = RegType,
- target = TargetName,
- addr = Addr,
- port = Port,
- type = get_next,
- data = MsgData,
- ref = Ref,
- mon = MonRef,
- from = From},
+ Req = #request{id = ReqId,
+ user_id = UserId,
+ reg_type = RegType,
+ target = TargetName,
+ domain = Domain,
+ addr = Addr,
+ port = Port,
+ type = get_next,
+ data = MsgData,
+ ref = Ref,
+ mon = MonRef,
+ from = From},
ets:insert(snmpm_request_table, Req),
ok;
@@ -987,39 +1268,52 @@ handle_sync_get_next(Pid, UserId, TargetName, CtxName, Oids, Timeout,
handle_sync_get_bulk(Pid, UserId, TargetName, CtxName,
NonRep, MaxRep, Oids, Timeout,
ExtraInfo, From, State) ->
+ SendOpts =
+ [
+ {context, CtxName},
+ {timeout, Timeout},
+ {extra, ExtraInfo}
+ ],
+ handle_sync_get_bulk(Pid, UserId, TargetName, NonRep, MaxRep, Oids,
+ SendOpts, From, State).
+
+handle_sync_get_bulk(Pid, UserId, TargetName, NonRep, MaxRep, Oids, SendOpts,
+ From, State) ->
?vtrace("handle_sync_get_bulk -> entry with"
"~n Pid: ~p"
"~n UserId: ~p"
"~n TargetName: ~p"
- "~n CtxName: ~p"
"~n NonRep: ~p"
"~n MaxRep: ~p"
"~n Oids: ~p"
- "~n Timeout: ~p"
+ "~n SendOpts: ~p"
"~n From: ~p",
- [Pid, UserId, TargetName, CtxName, NonRep, MaxRep, Oids,
- Timeout, From]),
- case agent_data(TargetName, CtxName) of
- {ok, RegType, Addr, Port, Vsn, MsgData} ->
+ [Pid, UserId, TargetName, NonRep, MaxRep, Oids, SendOpts, From]),
+ case agent_data(TargetName, SendOpts) of
+ {ok, RegType, Domain, Addr, Port, Vsn, MsgData} ->
?vtrace("handle_sync_get_bulk -> send a ~p message", [Vsn]),
- ReqId = send_get_bulk_request(Oids, Vsn, MsgData, Addr, Port,
- NonRep, MaxRep, ExtraInfo, State),
+ Extra = ?GET_EXTRA(SendOpts),
+ ReqId = send_get_bulk_request(Oids, Vsn, MsgData,
+ Domain, Addr, Port,
+ NonRep, MaxRep, Extra, State),
?vdebug("handle_sync_get_bulk -> ReqId: ~p", [ReqId]),
- Msg = {sync_timeout, ReqId, From},
- Ref = erlang:send_after(Timeout, self(), Msg),
- MonRef = erlang:monitor(process, Pid),
+ Msg = {sync_timeout, ReqId, From},
+ Timeout = ?SYNC_GET_BULK_TIMEOUT(SendOpts),
+ Ref = erlang:send_after(Timeout, self(), Msg),
+ MonRef = erlang:monitor(process, Pid),
?vtrace("handle_sync_get_bulk -> MonRef: ~p", [MonRef]),
- Req = #request{id = ReqId,
- user_id = UserId,
- reg_type = RegType,
- target = TargetName,
- addr = Addr,
- port = Port,
- type = get_bulk,
- data = MsgData,
- ref = Ref,
- mon = MonRef,
- from = From},
+ Req = #request{id = ReqId,
+ user_id = UserId,
+ reg_type = RegType,
+ target = TargetName,
+ domain = Domain,
+ addr = Addr,
+ port = Port,
+ type = get_bulk,
+ data = MsgData,
+ ref = Ref,
+ mon = MonRef,
+ from = From},
ets:insert(snmpm_request_table, Req),
ok;
@@ -1033,36 +1327,49 @@ handle_sync_get_bulk(Pid, UserId, TargetName, CtxName,
handle_sync_set(Pid, UserId, TargetName, CtxName, VarsAndVals, Timeout,
ExtraInfo, From, State) ->
+ SendOpts =
+ [
+ {context, CtxName},
+ {timeout, Timeout},
+ {extra, ExtraInfo}
+ ],
+ handle_sync_set(Pid, UserId, TargetName, VarsAndVals, SendOpts,
+ From, State).
+
+handle_sync_set(Pid, UserId, TargetName, VarsAndVals, SendOpts, From, State) ->
?vtrace("handle_sync_set -> entry with"
"~n Pid: ~p"
"~n UserId: ~p"
"~n TargetName: ~p"
- "~n CtxName: ~p"
"~n VarsAndVals: ~p"
- "~n Timeout: ~p"
+ "~n SendOpts: ~p"
"~n From: ~p",
- [Pid, UserId, TargetName, CtxName, VarsAndVals, Timeout, From]),
- case agent_data(TargetName, CtxName) of
- {ok, RegType, Addr, Port, Vsn, MsgData} ->
+ [Pid, UserId, TargetName, VarsAndVals, From]),
+ case agent_data(TargetName, SendOpts) of
+ {ok, RegType, Domain, Addr, Port, Vsn, MsgData} ->
?vtrace("handle_sync_set -> send a ~p message", [Vsn]),
- ReqId = send_set_request(VarsAndVals, Vsn, MsgData,
- Addr, Port, ExtraInfo, State),
+ Extra = ?GET_EXTRA(SendOpts),
+ ReqId = send_set_request(VarsAndVals, Vsn, MsgData,
+ Domain, Addr, Port,
+ Extra, State),
?vdebug("handle_sync_set -> ReqId: ~p", [ReqId]),
- Msg = {sync_timeout, ReqId, From},
- Ref = erlang:send_after(Timeout, self(), Msg),
- MonRef = erlang:monitor(process, Pid),
+ Msg = {sync_timeout, ReqId, From},
+ Timeout = ?SYNC_SET_TIMEOUT(SendOpts),
+ Ref = erlang:send_after(Timeout, self(), Msg),
+ MonRef = erlang:monitor(process, Pid),
?vtrace("handle_sync_set -> MonRef: ~p", [MonRef]),
- Req = #request{id = ReqId,
- user_id = UserId,
- reg_type = RegType,
- target = TargetName,
- addr = Addr,
- port = Port,
- type = set,
- data = MsgData,
- ref = Ref,
- mon = MonRef,
- from = From},
+ Req = #request{id = ReqId,
+ user_id = UserId,
+ reg_type = RegType,
+ target = TargetName,
+ domain = Domain,
+ addr = Addr,
+ port = Port,
+ type = set,
+ data = MsgData,
+ ref = Ref,
+ mon = MonRef,
+ from = From},
ets:insert(snmpm_request_table, Req),
ok;
@@ -1076,24 +1383,36 @@ handle_sync_set(Pid, UserId, TargetName, CtxName, VarsAndVals, Timeout,
handle_async_get(Pid, UserId, TargetName, CtxName, Oids, Expire, ExtraInfo,
State) ->
+ SendOpts =
+ [
+ {context, CtxName},
+ {timeout, Expire},
+ {extra, ExtraInfo}
+ ],
+ handle_async_get(Pid, UserId, TargetName, Oids, SendOpts, State).
+
+handle_async_get(Pid, UserId, TargetName, Oids, SendOpts, State) ->
?vtrace("handle_async_get -> entry with"
"~n Pid: ~p"
"~n UserId: ~p"
"~n TargetName: ~p"
- "~n CtxName: ~p"
"~n Oids: ~p"
- "~n Expire: ~p",
- [Pid, UserId, TargetName, CtxName, Oids, Expire]),
- case agent_data(TargetName, CtxName) of
- {ok, RegType, Addr, Port, Vsn, MsgData} ->
+ "~n SendOpts: ~p",
+ [Pid, UserId, TargetName, Oids, SendOpts]),
+ case agent_data(TargetName, SendOpts) of
+ {ok, RegType, Domain, Addr, Port, Vsn, MsgData} ->
?vtrace("handle_async_get -> send a ~p message", [Vsn]),
- ReqId = send_get_request(Oids, Vsn, MsgData, Addr, Port,
- ExtraInfo, State),
+ Extra = ?GET_EXTRA(SendOpts),
+ ReqId = send_get_request(Oids, Vsn, MsgData,
+ Domain, Addr, Port,
+ Extra, State),
?vdebug("handle_async_get -> ReqId: ~p", [ReqId]),
+ Expire = ?ASYNC_GET_TIMEOUT(SendOpts),
Req = #request{id = ReqId,
user_id = UserId,
reg_type = RegType,
target = TargetName,
+ domain = Domain,
addr = Addr,
port = Port,
type = get,
@@ -1114,24 +1433,36 @@ handle_async_get(Pid, UserId, TargetName, CtxName, Oids, Expire, ExtraInfo,
handle_async_get_next(Pid, UserId, TargetName, CtxName, Oids, Expire,
ExtraInfo, State) ->
+ SendOpts =
+ [
+ {context, CtxName},
+ {timeout, Expire},
+ {extra, ExtraInfo}
+ ],
+ handle_async_get_next(Pid, UserId, TargetName, Oids, SendOpts, State).
+
+handle_async_get_next(Pid, UserId, TargetName, Oids, SendOpts, State) ->
?vtrace("handle_async_get_next -> entry with"
"~n Pid: ~p"
"~n UserId: ~p"
"~n TargetName: ~p"
- "~n CtxName: ~p"
"~n Oids: ~p"
- "~n Expire: ~p",
- [Pid, UserId, TargetName, CtxName, Oids, Expire]),
- case agent_data(TargetName, CtxName) of
- {ok, RegType, Addr, Port, Vsn, MsgData} ->
+ "~n SendOpts: ~p",
+ [Pid, UserId, TargetName, Oids, SendOpts]),
+ case agent_data(TargetName, SendOpts) of
+ {ok, RegType, Domain, Addr, Port, Vsn, MsgData} ->
?vtrace("handle_async_get_next -> send a ~p message", [Vsn]),
+ Extra = ?GET_EXTRA(SendOpts),
ReqId = send_get_next_request(Oids, Vsn, MsgData,
- Addr, Port, ExtraInfo, State),
+ Domain, Addr, Port,
+ Extra, State),
?vdebug("handle_async_get_next -> ReqId: ~p", [ReqId]),
+ Expire = ?ASYNC_GET_NEXT_TIMEOUT(SendOpts),
Req = #request{id = ReqId,
user_id = UserId,
reg_type = RegType,
target = TargetName,
+ domain = Domain,
addr = Addr,
port = Port,
type = get_next,
@@ -1153,26 +1484,42 @@ handle_async_get_next(Pid, UserId, TargetName, CtxName, Oids, Expire,
handle_async_get_bulk(Pid, UserId, TargetName, CtxName,
NonRep, MaxRep, Oids, Expire,
ExtraInfo, State) ->
+ SendOpts =
+ [
+ {context, CtxName},
+ {timeout, Expire},
+ {extra, ExtraInfo}
+ ],
+ handle_async_get_bulk(Pid,
+ UserId, TargetName, NonRep, MaxRep, Oids, SendOpts,
+ State).
+
+handle_async_get_bulk(Pid,
+ UserId, TargetName, NonRep, MaxRep, Oids, SendOpts,
+ State) ->
?vtrace("handle_async_get_bulk -> entry with"
"~n Pid: ~p"
"~n UserId: ~p"
"~n TargetName: ~p"
- "~n CtxName: ~p"
"~n NonRep: ~p"
"~n MaxRep: ~p"
"~n Oids: ~p"
- "~n Expire: ~p",
- [Pid, UserId, TargetName, CtxName, NonRep, MaxRep, Oids, Expire]),
- case agent_data(TargetName, CtxName) of
- {ok, RegType, Addr, Port, Vsn, MsgData} ->
+ "~n SendOpts: ~p",
+ [Pid, UserId, TargetName, NonRep, MaxRep, Oids, SendOpts]),
+ case agent_data(TargetName, SendOpts) of
+ {ok, RegType, Domain, Addr, Port, Vsn, MsgData} ->
?vtrace("handle_async_get_bulk -> send a ~p message", [Vsn]),
- ReqId = send_get_bulk_request(Oids, Vsn, MsgData, Addr, Port,
- NonRep, MaxRep, ExtraInfo, State),
+ Extra = ?GET_EXTRA(SendOpts),
+ ReqId = send_get_bulk_request(Oids, Vsn, MsgData,
+ Domain, Addr, Port,
+ NonRep, MaxRep, Extra, State),
?vdebug("handle_async_get_bulk -> ReqId: ~p", [ReqId]),
+ Expire = ?ASYNC_GET_BULK_TIMEOUT(SendOpts),
Req = #request{id = ReqId,
user_id = UserId,
reg_type = RegType,
target = TargetName,
+ domain = Domain,
addr = Addr,
port = Port,
type = get_bulk,
@@ -1192,24 +1539,36 @@ handle_async_get_bulk(Pid, UserId, TargetName, CtxName,
handle_async_set(Pid, UserId, TargetName, CtxName, VarsAndVals, Expire,
ExtraInfo, State) ->
+ SendOpts =
+ [
+ {context, CtxName},
+ {timeout, Expire},
+ {extra, ExtraInfo}
+ ],
+ handle_async_set(Pid, UserId, TargetName, VarsAndVals, SendOpts, State).
+
+handle_async_set(Pid, UserId, TargetName, VarsAndVals, SendOpts, State) ->
?vtrace("handle_async_set -> entry with"
"~n Pid: ~p"
"~n UserId: ~p"
"~n TargetName: ~p"
- "~n CtxName: ~p"
"~n VarsAndVals: ~p"
- "~n Expire: ~p",
- [Pid, UserId, TargetName, CtxName, VarsAndVals, Expire]),
- case agent_data(TargetName, CtxName) of
- {ok, RegType, Addr, Port, Vsn, MsgData} ->
+ "~n SendOpts: ~p",
+ [Pid, UserId, TargetName, VarsAndVals, SendOpts]),
+ case agent_data(TargetName, SendOpts) of
+ {ok, RegType, Domain, Addr, Port, Vsn, MsgData} ->
?vtrace("handle_async_set -> send a ~p message", [Vsn]),
+ Extra = ?GET_EXTRA(SendOpts),
ReqId = send_set_request(VarsAndVals, Vsn, MsgData,
- Addr, Port, ExtraInfo, State),
+ Domain, Addr, Port,
+ Extra, State),
?vdebug("handle_async_set -> ReqId: ~p", [ReqId]),
+ Expire = ?ASYNC_SET_TIMEOUT(SendOpts),
Req = #request{id = ReqId,
user_id = UserId,
reg_type = RegType,
target = TargetName,
+ domain = Domain,
addr = Addr,
port = Port,
type = set,
@@ -2565,7 +2924,7 @@ do_gc(Key, Now) ->
%%
%%----------------------------------------------------------------------
-send_get_request(Oids, Vsn, MsgData, Addr, Port, ExtraInfo,
+send_get_request(Oids, Vsn, MsgData, Domain, Addr, Port, ExtraInfo,
#state{net_if = NetIf,
net_if_mod = Mod,
mini_mib = MiniMIB}) ->
@@ -2576,34 +2935,39 @@ send_get_request(Oids, Vsn, MsgData, Addr, Port, ExtraInfo,
"~n Pdu: ~p"
"~n Vsn: ~p"
"~n MsgData: ~p"
+ "~n Domain: ~p"
"~n Addr: ~p"
- "~n Port: ~p", [Mod, NetIf, Pdu, Vsn, MsgData, Addr, Port]),
- (catch Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo)),
+ "~n Port: ~p",
+ [Mod, NetIf, Pdu, Vsn, MsgData, Domain, Addr, Port]),
+ Res = (catch Mod:send_pdu(NetIf, Pdu, Vsn, MsgData,
+ Domain, Addr, Port, ExtraInfo)),
+ ?vtrace("send_get_request -> send result:"
+ "~n ~p", [Res]),
Pdu#pdu.request_id.
-send_get_next_request(Oids, Vsn, MsgData, Addr, Port, ExtraInfo,
+send_get_next_request(Oids, Vsn, MsgData, Domain, Addr, Port, ExtraInfo,
#state{mini_mib = MiniMIB,
net_if = NetIf,
net_if_mod = Mod}) ->
Pdu = make_pdu(get_next, Oids, MiniMIB),
- Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo),
+ Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo),
Pdu#pdu.request_id.
-send_get_bulk_request(Oids, Vsn, MsgData, Addr, Port,
+send_get_bulk_request(Oids, Vsn, MsgData, Domain, Addr, Port,
NonRep, MaxRep, ExtraInfo,
#state{mini_mib = MiniMIB,
net_if = NetIf,
net_if_mod = Mod}) ->
Pdu = make_pdu(bulk, {NonRep, MaxRep, Oids}, MiniMIB),
- Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo),
+ Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo),
Pdu#pdu.request_id.
-send_set_request(VarsAndVals, Vsn, MsgData, Addr, Port, ExtraInfo,
+send_set_request(VarsAndVals, Vsn, MsgData, Domain, Addr, Port, ExtraInfo,
#state{mini_mib = MiniMIB,
net_if = NetIf,
net_if_mod = Mod}) ->
Pdu = make_pdu(set, VarsAndVals, MiniMIB),
- Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo),
+ Mod:send_pdu(NetIf, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo),
Pdu#pdu.request_id.
%% send_discovery(Vsn, MsgData, Addr, Port, ExtraInfo,
@@ -2798,10 +3162,7 @@ request_id() ->
%%----------------------------------------------------------------------
-agent_data(TargetName, CtxName) ->
- agent_data(TargetName, CtxName, []).
-
-agent_data(TargetName, CtxName, Config) ->
+agent_data(TargetName, SendOpts) ->
case snmpm_config:agent_info(TargetName, all) of
{ok, Info} ->
Version = agent_data_item(version, Info),
@@ -2813,15 +3174,18 @@ agent_data(TargetName, CtxName, Config) ->
DefSecLevel = agent_data_item(sec_level, Info),
EngineId = agent_data_item(engine_id, Info),
+ CtxName = agent_data_item(context,
+ SendOpts,
+ ?DEFAULT_CONTEXT),
SecModel = agent_data_item(sec_model,
- Config,
+ SendOpts,
DefSecModel),
SecName = agent_data_item(sec_name,
- Config,
+ SendOpts,
DefSecName),
SecLevel = agent_data_item(sec_level,
- Config,
+ SendOpts,
DefSecLevel),
{SecModel, SecName, mk_sec_level_flag(SecLevel),
@@ -2831,18 +3195,19 @@ agent_data(TargetName, CtxName, Config) ->
DefSecModel = agent_data_item(sec_model, Info),
Comm = agent_data_item(community,
- Config,
+ SendOpts,
DefComm),
SecModel = agent_data_item(sec_model,
- Config,
+ SendOpts,
DefSecModel),
{Comm, SecModel}
end,
+ Domain = agent_data_item(tdomain, Info),
Addr = agent_data_item(address, Info),
Port = agent_data_item(port, Info),
RegType = agent_data_item(reg_type, Info),
- {ok, RegType, Addr, Port, version(Version), MsgData};
+ {ok, RegType, Domain, Addr, Port, version(Version), MsgData};
Error ->
Error
end.
@@ -3003,6 +3368,12 @@ default_agent_config() ->
%%----------------------------------------------------------------------
+get_opt(Key, Default, Opts) ->
+ proplists:get_value(Key, Opts, Default).
+
+
+%%----------------------------------------------------------------------
+
is_started(#state{net_if = _Pid, net_if_mod = _Mod}) ->
%% Mod:is_started(Pid) and snmpm_config:is_started().
case snmpm_config:is_started() of
diff --git a/lib/snmp/src/manager/snmpm_usm.erl b/lib/snmp/src/manager/snmpm_usm.erl
index 449127844a..497d6d6102 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-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -476,14 +476,19 @@ set_engine_latest_time(SnmpEngineID, EngineTime) ->
%%-----------------------------------------------------------------
%% Utility functions
%%-----------------------------------------------------------------
+-spec error(term()) -> no_return().
error(Reason) ->
throw({error, Reason}).
+-spec error(term(), term()) -> no_return().
error(Reason, ErrorInfo) ->
throw({error, Reason, ErrorInfo}).
+-spec error(term(), term(), term()) -> no_return().
error(Variable, Oid, SecName) ->
error(Variable, Oid, SecName, []).
+
+-spec error(term(), term(), term(), [term()]) -> no_return().
error(Variable, Oid, SecName, Opts) ->
Val = inc(Variable),
ErrorInfo = {#varbind{oid = Oid,
diff --git a/lib/snmp/src/misc/snmp_conf.erl b/lib/snmp/src/misc/snmp_conf.erl
index 4d2f5d8f92..7249def24e 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-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,15 @@
check_timer/1,
- check_ip/1, check_taddress/1,
+ all_domains/0,
+ check_domain/1,
+ all_tdomains/0,
+ check_tdomain/1,
+ mk_tdomain/1,
+ which_domain/1,
+ check_ip/1, check_ip/2,
+ check_taddress/1, check_taddress/2,
+ mk_taddress/3,
check_packet_size/1,
@@ -52,8 +60,10 @@
-define(SNMP_USE_V3, true).
--include("snmp_types.hrl").
--include("SNMP-FRAMEWORK-MIB.hrl").
+-include_lib("snmp/include/snmp_types.hrl").
+-include_lib("snmp/include/SNMP-FRAMEWORK-MIB.hrl").
+-include_lib("snmp/include/TRANSPORT-ADDRESS-MIB.hrl").
+-include_lib("snmp/include/SNMPv2-TM.hrl").
-define(VMODULE,"CONF").
-include("snmp_verbosity.hrl").
@@ -337,16 +347,98 @@ check_sec_level(BadSecLevel) ->
%% ---------
+all_tdomains() ->
+ [
+ ?transportDomainUdpIpv4,
+ ?transportDomainUdpIpv6,
+ ?transportDomainUdpIpv4z,
+ ?transportDomainUdpIpv6z,
+ ?transportDomainTcpIpv4,
+ ?transportDomainTcpIpv6,
+ ?transportDomainTcpIpv4z,
+ ?transportDomainTcpIpv6z,
+ ?transportDomainSctpIpv4,
+ ?transportDomainSctpIpv6,
+ ?transportDomainSctpIpv4z,
+ ?transportDomainSctpIpv6z,
+ ?transportDomainLocal,
+ ?transportDomainUdpDns,
+ ?transportDomainTcpDns,
+ ?transportDomainSctpDns
+ ].
+
+check_tdomain(TDomain) ->
+ SupportedTDomains =
+ [
+ ?snmpUDPDomain,
+ ?transportDomainUdpIpv4,
+ ?transportDomainUdpIpv6
+ ],
+ AllTDomains = all_tdomains(),
+ case lists:member(TDomain, SupportedTDomains) of
+ true ->
+ ok;
+ false ->
+ case lists:member(TDomain, AllTDomains) of
+ true ->
+ error({unsupported_tdomain, TDomain});
+ false ->
+ error({unknown_tdomain, TDomain})
+ end
+ end.
+
+
+%% ---------
+
+mk_tdomain(snmpUDPDomain) ->
+ mk_tdomain(transportDomainUdpIpv4);
+mk_tdomain(transportDomainUdpIpv4) ->
+ ?transportDomainUdpIpv4;
+mk_tdomain(transportDomainUdpIpv6) ->
+ ?transportDomainUdpIpv6;
+mk_tdomain(BadDomain) ->
+ error({bad_domain, BadDomain}).
+
+
+%% ---------
+
+check_taddress(X) ->
+ check_taddress(snmpUDPDomain, X).
+
+check_taddress(?snmpUDPDomain, X) ->
+ check_taddress(transportDomainUdpIpv4, X);
+check_taddress(snmpUDPDomain, X) ->
+ check_taddress(transportDomainUdpIpv4, X);
-check_taddress(X) when is_list(X) andalso (length(X) =:= 6) ->
+check_taddress(?transportDomainUdpIpv4, X) ->
+ check_taddress(transportDomainUdpIpv4, X);
+check_taddress(transportDomainUdpIpv4, X)
+ when is_list(X) andalso (length(X) =:= 6) ->
case (catch all_integer(X)) of
true ->
ok;
false ->
error({invalid_taddress, X})
end;
-check_taddress(X) ->
- error({invalid_taddress, X}).
+check_taddress(transportDomainUdpIpv4, X) ->
+ error({invalid_taddress, X});
+
+check_taddress(?transportDomainUdpIpv6, X) ->
+ check_taddress(transportDomainUdpIpv6, X);
+check_taddress(transportDomainUdpIpv6, X)
+ when is_list(X) andalso (length(X) =:= 10) ->
+ case (catch all_integer(X)) of
+ true ->
+ ok;
+ false ->
+ error({invalid_taddress, X})
+ end;
+check_taddress(transportDomainUdpIpv6, X) ->
+ error({invalid_taddress, X});
+
+check_taddress(BadDomain, _X) ->
+ error({invalid_tdomain, BadDomain}).
+
%% ---------
@@ -385,15 +477,117 @@ do_check_timer(WaitFor, Factor, Incr, Retry) ->
%% ---------
-check_ip(X) when is_list(X) andalso (length(X) =:= 4) ->
+all_domains() ->
+ [
+ transportDomainUdpIpv4,
+ transportDomainUdpIpv6,
+ transportDomainUdpIpv4z,
+ transportDomainUdpIpv6z,
+ transportDomainTcpIpv4,
+ transportDomainTcpIpv6,
+ transportDomainTcpIpv4z,
+ transportDomainTcpIpv6z,
+ transportDomainSctpIpv4,
+ transportDomainSctpIpv6,
+ transportDomainSctpIpv4z,
+ transportDomainSctpIpv6z,
+ transportDomainLocal,
+ transportDomainUdpDns,
+ transportDomainTcpDns,
+ transportDomainSctpDns
+ ].
+
+check_domain(Domain) ->
+ SupportedDomains =
+ [
+ snmpUDPDomain,
+ transportDomainUdpIpv4,
+ transportDomainUdpIpv6
+ ],
+ AllDomains = all_domains(),
+ case lists:member(Domain, SupportedDomains) of
+ true ->
+ ok;
+ false ->
+ case lists:member(Domain, AllDomains) of
+ true ->
+ error({unsupported_domain, Domain});
+ false ->
+ error({unknown_domain, Domain})
+ end
+ end.
+
+
+%% ---------
+
+%% The values of Ip and Port has both been checked at this
+%% point, so we dont need to do that again.
+mk_taddress(snmpUDPDomain, Ip, Port) ->
+ mk_taddress(transportDomainUdpIpv4, Ip, Port);
+mk_taddress(transportDomainUdpIpv4, Ip, Port) when is_list(Ip) ->
+ Ip ++ [Port div 256, Port rem 256];
+mk_taddress(transportDomainUdpIpv4 = Domain, Ip, Port) when is_tuple(Ip) ->
+ mk_taddress(Domain, tuple_to_list(Ip), Port);
+mk_taddress(transportDomainUdpIpv6, Ip, Port) when is_list(Ip) ->
+ Ip ++ [Port div 256, Port rem 256];
+mk_taddress(transportDomainUdpIpv6 = Domain, Ip, Port) when is_tuple(Ip) ->
+ mk_taddress(Domain, tuple_to_list(Ip), Port);
+
+%% These are just for convenience
+mk_taddress(?snmpUDPDomain, Ip, Port) ->
+ mk_taddress(snmpUDPDomain, Ip, Port);
+mk_taddress(?transportDomainUdpIpv4, Ip, Port) ->
+ mk_taddress(transportDomainUdpIpv4, Ip, Port);
+mk_taddress(?transportDomainUdpIpv6, Ip, Port) ->
+ mk_taddress(transportDomainUdpIpv6, Ip, Port);
+
+%% Bad domain
+mk_taddress(BadDomain, _Ip, _Port) ->
+ error({bad_domain, BadDomain}).
+
+
+%% ---------
+
+which_domain(Ip) when is_list(Ip) andalso (length(Ip) =:= 4) ->
+ transportDomainUdpIpv4;
+which_domain(Ip) when is_tuple(Ip) andalso (size(Ip) =:= 4) ->
+ transportDomainUdpIpv4;
+which_domain(Ip) when is_list(Ip) andalso (length(Ip) =:= 8) ->
+ transportDomainUdpIpv6;
+which_domain(Ip) when is_tuple(Ip) andalso (size(Ip) =:= 8) ->
+ transportDomainUdpIpv6.
+
+
+%% ---------
+
+check_ip(X) ->
+ check_ip(snmpUDPDomain, X).
+
+check_ip(snmpUDPDomain, X) ->
+ check_ip(transportDomainUdpIpv4, X);
+check_ip(transportDomainUdpIpv4, X) when is_list(X) andalso (length(X) =:= 4) ->
case (catch all_integer(X)) of
true ->
ok;
false ->
error({invalid_ip_address, X})
end;
-check_ip(X) ->
- error({invalid_ip_address, X}).
+check_ip(transportDomainUdpIpv4, X) ->
+ error({invalid_ip_address, X});
+
+check_ip(transportDomainUdpIpv6, X) when is_list(X) andalso (length(X) =:= 8) ->
+ case (catch all_integer(X)) of
+ true ->
+ ok;
+ false ->
+ error({invalid_ip_address, X})
+ end;
+check_ip(transportDomainUdpIpv6, X) ->
+ error({invalid_ip_address, X});
+
+check_ip(BadDomain, _X) ->
+ error({invalid_domain, BadDomain}).
+
%% ---------
diff --git a/lib/snmp/src/misc/snmp_config.erl b/lib/snmp/src/misc/snmp_config.erl
index 25350e08cb..6ab20e3e48 100644
--- a/lib/snmp/src/misc/snmp_config.erl
+++ b/lib/snmp/src/misc/snmp_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -337,7 +337,7 @@ config_agent_sys() ->
{dir, ATLDir},
{size, ATLSize},
{repair, ATLRepair},
- {seqno, ATLSeqNo}]}];
+ {seqno, ATLSeqNo}]}];
no ->
[]
end,
@@ -491,6 +491,9 @@ config_agent_snmp(Dir, Vsns) ->
Host = host(),
AgentIP = ask("5. IP address for the agent (only used as id ~n"
" when sending traps)", Host, fun verify_address/1),
+ %% We intentionally skip TDomain...
+ %% If the user wish to use IPv6, the user must create an dummy entry here
+ %% and then manually edit these entries later.
ManagerIP = ask("6. IP address for the manager (only this manager ~n"
" will have access to the agent, traps are sent ~n"
" to this one)", Host, fun verify_address/1),
@@ -565,7 +568,7 @@ config_agent_snmp(Dir, Vsns) ->
false ->
ok
end,
- i("The following agent files were written: agent.conf, "
+ i("The following agent files where written: agent.conf, "
"community.conf,~n"
"standard.conf, target_addr.conf, "
"target_params.conf, ~n"
@@ -773,7 +776,7 @@ config_manager_snmp(Dir, Vsns) ->
Users, Agents, Usms)) of
ok ->
i("~n- - - - - - - - - - - - -"),
- i("The following manager files were written: "
+ i("The following manager files where written: "
"manager.conf, agents.conf " ++
case lists:member(v3, Vsns) of
true ->
@@ -1062,9 +1065,19 @@ verify_sec_type(ST) -> {error, "invalid security type: " ++ ST}.
verify_address(A) ->
- case (catch snmp_misc:ip(A)) of
+ verify_address(A, snmpUDPDomain).
+
+verify_address(A, snmpUDPDomain = _Domain) ->
+ do_verify_address(A, inet);
+verify_address(A, transportDomainUdpIpv4 = _Domain) ->
+ do_verify_address(A, inet);
+verify_address(A, transportDomainUdpIpv6 = _Domain) ->
+ do_verify_address(A, inet6).
+
+do_verify_address(A, Family) ->
+ case (catch snmp_misc:ip(A, Family)) of
{ok, IP} ->
- {ok, tuple_to_list(IP)};
+ {ok, tuple_to_list(IP)};
{error, _} ->
{error, "invalid address: " ++ A};
_E ->
@@ -1721,10 +1734,12 @@ write_agent_snmp_target_addr_conf(Dir, ManagerIp, UDP,
Hdr = header() ++ Comment,
F = fun(v1 = Vsn, Acc) ->
[{mk_ip(ManagerIp, Vsn),
+ snmp_target_mib:default_domain(),
ManagerIp, UDP, Timeout, RetryCount,
"std_trap", mk_param(Vsn), "", [], 2048}| Acc];
(v2 = Vsn, Acc) ->
[{mk_ip(ManagerIp, Vsn),
+ snmp_target_mib:default_domain(),
ManagerIp, UDP, Timeout, RetryCount,
"std_trap", mk_param(Vsn), "", [], 2048},
{lists:flatten(io_lib:format("~s.2",[mk_ip(ManagerIp, Vsn)])),
@@ -1732,6 +1747,7 @@ write_agent_snmp_target_addr_conf(Dir, ManagerIp, UDP,
"std_inform", mk_param(Vsn), "", [], 2048}| Acc];
(v3 = Vsn, Acc) ->
[{mk_ip(ManagerIp, Vsn),
+ snmp_target_mib:default_domain(),
ManagerIp, UDP, Timeout, RetryCount,
"std_trap", mk_param(Vsn), "", [], 2048},
{lists:flatten(io_lib:format("~s.3",[mk_ip(ManagerIp, Vsn)])),
@@ -2334,7 +2350,9 @@ write_sys_config_file_manager_atl_opt(Fid, {type, Type}) ->
write_sys_config_file_manager_atl_opt(Fid, {size, Size}) ->
ok = io:format(Fid, "{size, ~w}", [Size]);
write_sys_config_file_manager_atl_opt(Fid, {repair, Rep}) ->
- ok = io:format(Fid, "{repair, ~w}", [Rep]).
+ ok = io:format(Fid, "{repair, ~w}", [Rep]);
+write_sys_config_file_manager_atl_opt(Fid, {seqno, SeqNo}) ->
+ ok = io:format(Fid, "{seqno, ~w}", [SeqNo]).
header() ->
diff --git a/lib/snmp/src/misc/snmp_log.erl b/lib/snmp/src/misc/snmp_log.erl
index f9aa911817..2c781810ef 100644
--- a/lib/snmp/src/misc/snmp_log.erl
+++ b/lib/snmp/src/misc/snmp_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -266,9 +266,6 @@ validate_loop(eof, _Log, _Validatior, _PrevTS, _PrevSN) ->
ok;
validate_loop({error, _} = Error, _Log, _Validator, _PrevTS, _PrevSN) ->
Error;
-validate_loop({corrupt_log_file, _} = Reason,
- _Log, _Validator, _PrevTS, _PrevSN) ->
- {error, Reason};
validate_loop({Cont, Terms}, Log, Validator, PrevTS, PrevSN) ->
?vtrace("validate_loop -> entry with"
"~n Terms: ~p"
@@ -508,8 +505,6 @@ loop(eof, _Log, _Write) ->
ok;
loop({error, _} = Error, _Log, _Write) ->
Error;
-loop({corrupt_log_file, _} = Reason, _Log, _Write) ->
- {error, Reason};
loop({Cont, Terms}, Log, Write) ->
case (catch lists:foreach(Write, Terms)) of
{'EXIT', Reason} ->
diff --git a/lib/snmp/src/misc/snmp_misc.erl b/lib/snmp/src/misc/snmp_misc.erl
index 1b535743a4..a061dcd97c 100644
--- a/lib/snmp/src/misc/snmp_misc.erl
+++ b/lib/snmp/src/misc/snmp_misc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,7 +40,7 @@
get_option/2,
get_option/3,
get_sec_level/1,
- ip/1,
+ ip/1, ip/2,
is_auth/1,
is_BitString/1,
is_oid/1,
@@ -347,10 +347,15 @@ bits_to_int([Kibble|Ks],Kibbles,Res) ->
%%----------------------------------------------------------------------
-%% Returns: {ok, {int(),int(),int(),int()}} | {error, Reason}
+%% Returns: {ok, {int(),int(),int(),int()}} |
+%% {ok, {int(),int(),int(),int()},int(),int(),int(),int()} |
+%% {error, Reason}
%%----------------------------------------------------------------------
ip(Host) ->
- inet:getaddr(Host, inet).
+ ip(Host, inet).
+
+ip(Host, Family) ->
+ inet:getaddr(Host, Family).
ensure_trailing_dir_delimiter([]) -> "/";
ensure_trailing_dir_delimiter(DirSuggestion) ->
diff --git a/lib/snmp/src/misc/snmp_pdus.erl b/lib/snmp/src/misc/snmp_pdus.erl
index dc8900c8cd..0788d86b2d 100644
--- a/lib/snmp/src/misc/snmp_pdus.erl
+++ b/lib/snmp/src/misc/snmp_pdus.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -269,24 +269,35 @@ dec_value([64 | Bytes]) ->
{Value, Rest} = dec_oct_str_notag(Bytes),
{{'IpAddress', Value}, Rest};
dec_value([65 | Bytes]) ->
+ %% Counter32 is an unsigned 32 but is actually encoded as
+ %% a signed integer 32 (INTEGER).
{Value, Rest} = dec_integer_notag(Bytes),
- if Value >= 0, Value =< 4294967295 ->
- {{'Counter32', Value}, Rest};
- true ->
- exit({error, {bad_counter32, Value}})
- end;
+ Value2 =
+ if
+ (Value >= 0) andalso (Value =< 16#ffffffff) ->
+ %% We accept value above 16#7fffffff
+ %% in order to be backward bug-compatible
+ Value;
+ (Value < 0) ->
+ 16#ffffffff + Value + 1;
+ true ->
+ exit({error, {bad_counter32, Value}})
+ end,
+ {{'Counter32', Value2}, Rest};
dec_value([66 | Bytes]) ->
{Value, Rest} = dec_integer_notag(Bytes),
- if Value >= 0, Value =< 4294967295 ->
+ if
+ (Value >= 0) andalso (Value =< 4294967295) ->
{{'Unsigned32', Value}, Rest};
- true ->
+ true ->
exit({error, {bad_unsigned32, Value}})
end;
dec_value([67 | Bytes]) ->
{Value, Rest} = dec_integer_notag(Bytes),
- if Value >= 0, Value =< 4294967295 ->
+ if
+ (Value >= 0) andalso (Value =< 4294967295) ->
{{'TimeTicks', Value}, Rest};
- true ->
+ true ->
exit({error, {bad_timeticks, Value}})
end;
dec_value([68 | Bytes]) ->
@@ -642,6 +653,21 @@ enc_value(_Type, endOfMibView) ->
[130,0];
enc_value('NULL', _Val) ->
[5,0];
+enc_value('Counter32', Val) ->
+ Val2 =
+ if
+ Val > 16#ffffffff ->
+ exit({error, {bad_counter32, Val}});
+ Val >= 16#80000000 ->
+ (Val band 16#7fffffff) - 16#80000000;
+ Val >= 0 ->
+ Val;
+ true ->
+ exit({error, {bad_counter32, Val}})
+ end,
+ Bytes2 = enc_integer_notag(Val2),
+ Len2 = elength(length(Bytes2)),
+ lists:append([65 | Len2],Bytes2);
enc_value('Counter64', Val) ->
Val2 =
if
diff --git a/lib/snmp/test/Makefile b/lib/snmp/test/Makefile
index 86af2460f5..78ffb1c255 100644
--- a/lib/snmp/test/Makefile
+++ b/lib/snmp/test/Makefile
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2009. All Rights Reserved.
+# Copyright Ericsson AB 1997-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -145,9 +145,12 @@ endif
# ----------------------------------------------------
EBIN = .
-ERL_COMPILE_FLAGS += -I../src \
+ERL_COMPILE_FLAGS += -I../../snmp/src/app \
+ -I../../snmp/src/misc \
+ -I../../snmp/src/agent \
+ -I../../snmp/src/manager \
-I$(ERL_TOP)/lib/test_server/include \
- -I../include \
+ -I../../snmp/include \
-Dsnmp_test_data=snmp_test_data \
-Dversion=\"$(VSN)$(PRE_VSN)\" \
+'{parse_transform,sys_pre_attributes}' \
@@ -217,6 +220,10 @@ appup: make
$(MAYBE_ESTOP)
+$(SNMP_BIN_TARGET_DIR)/Klas4.bin: $(SNMP_BIN_TARGET_DIR)/Klas3.bin
+
+$(SNMP_BIN_TARGET_DIR)/SA-MIB.bin: $(SNMP_BIN_TARGET_DIR)/OLD-SNMPEA-MIB.bin
+
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
@@ -227,7 +234,7 @@ release_spec:
release_tests_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(RELTEST_FILES) $(COVER_SPEC_FILE) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
tar cf - snmp_test_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl
index 692d29fda0..468280db02 100644
--- a/lib/snmp/test/snmp_agent_test.erl
+++ b/lib/snmp/test/snmp_agent_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -81,13 +81,12 @@
case get(vsn) of
v1 -> V1;
v2 -> V2;
- _ -> V3
+ _ -> V3
end).
all() ->
- Reqs = [mnesia, distribution, {local_slave_nodes, 2},
- {time, 360}],
+ %% Reqs = [mnesia, distribution, {local_slave_nodes, 2}, {time, 360}],
Conf1 = [{group, all_tcs}],
Conf2 = [{group, tickets2}],
Conf1 ++ Conf2.
@@ -95,67 +94,138 @@ all() ->
groups() ->
[{all_tcs, [], cases()},
{mib_storage, [],
- [{group, mib_storage_ets}, {group, mib_storage_dets},
+ [
+ {group, mib_storage_ets},
+ {group, mib_storage_dets},
{group, mib_storage_mnesia},
{group, mib_storage_size_check_ets},
{group, mib_storage_size_check_dets},
{group, mib_storage_size_check_mnesia},
{group, mib_storage_varm_dets},
- {group, mib_storage_varm_mnesia}]},
- {mib_storage_ets, [], mib_storage_ets_cases()},
- {mib_storage_dets, [], mib_storage_dets_cases()},
- {mib_storage_mnesia, [], mib_storage_mnesia_cases()},
- {mib_storage_size_check_ets, [],
- mse_size_check_cases()},
- {mib_storage_size_check_dets, [],
- msd_size_check_cases()},
- {mib_storage_size_check_mnesia, [],
- msm_size_check_cases()},
- {mib_storage_varm_dets, [],
- varm_mib_storage_dets_cases()},
- {mib_storage_varm_mnesia, [],
- varm_mib_storage_mnesia_cases()},
- {misc, [], misc_cases()}, {test_v1, [], v1_cases()},
- {test_v2, [], v2_cases()},
- {test_v1_v2, [], v1_v2_cases()},
- {test_v3, [], v3_cases()},
- {test_multi_threaded, [], mt_cases()},
- {multiple_reqs, [], mul_cases()},
- {multiple_reqs_2, [], mul_cases_2()},
- {v2_inform, [], [v2_inform_i]},
+ {group, mib_storage_varm_mnesia}
+ ]
+ },
+ {mib_storage_ets, [], mib_storage_ets_cases()},
+ {mib_storage_dets, [], mib_storage_dets_cases()},
+ {mib_storage_mnesia, [], mib_storage_mnesia_cases()},
+ {mib_storage_size_check_ets, [], mse_size_check_cases()},
+ {mib_storage_size_check_dets, [], msd_size_check_cases()},
+ {mib_storage_size_check_mnesia, [], msm_size_check_cases()},
+ {mib_storage_varm_dets, [], varm_mib_storage_dets_cases()},
+ {mib_storage_varm_mnesia, [], varm_mib_storage_mnesia_cases()},
+ {misc, [], misc_cases()},
+ {test_v1, [], v1_cases()},
+ {test_v2, [], v2_cases()},
+ {test_v1_v2, [], v1_v2_cases()},
+ {test_v3, [], v3_cases()},
+ {test_multi_threaded, [], mt_cases()},
+ {multiple_reqs, [], mul_cases()},
+ {multiple_reqs_2, [], mul_cases_2()},
+ {v2_inform, [],
+ [
+ v2_inform_i
+ ]
+ },
{v3_security, [],
- [v3_crypto_basic, v3_md5_auth, v3_sha_auth,
- v3_des_priv]},
+ [
+ v3_crypto_basic,
+ v3_md5_auth,
+ v3_sha_auth,
+ v3_des_priv
+ ]
+ },
{standard_mibs, [],
- [snmp_standard_mib, snmp_community_mib,
- snmp_framework_mib, snmp_target_mib,
- snmp_notification_mib, snmp_view_based_acm_mib]},
+ [
+ snmp_standard_mib,
+ snmp_community_mib,
+ snmp_framework_mib,
+ snmp_target_mib,
+ snmp_notification_mib,
+ snmp_view_based_acm_mib
+ ]
+ },
{standard_mibs_2, [],
- [snmpv2_mib_2, snmp_community_mib_2,
- snmp_framework_mib_2, snmp_target_mib_2,
- snmp_notification_mib_2, snmp_view_based_acm_mib_2]},
+ [
+ snmpv2_mib_2,
+ snmp_community_mib_2,
+ snmp_framework_mib_2,
+ snmp_target_mib_2,
+ snmp_notification_mib_2,
+ snmp_view_based_acm_mib_2
+ ]
+ },
{standard_mibs_3, [],
- [snmpv2_mib_3, snmp_framework_mib_3, snmp_mpd_mib_3,
- snmp_target_mib_3, snmp_notification_mib_3,
- snmp_view_based_acm_mib_3, snmp_user_based_sm_mib_3]},
+ [
+ snmpv2_mib_3,
+ snmp_framework_mib_3,
+ snmp_mpd_mib_3,
+ snmp_target_mib_3,
+ snmp_notification_mib_3,
+ snmp_view_based_acm_mib_3,
+ snmp_user_based_sm_mib_3
+ ]
+ },
{reported_bugs, [],
- [otp_1128, otp_1129, otp_1131, otp_1162, otp_1222,
- otp_1298, otp_1331, otp_1338, otp_1342, otp_2776,
- otp_2979, otp_3187, otp_3725]},
+ [
+ otp_1128,
+ otp_1129,
+ otp_1131,
+ otp_1162,
+ otp_1222,
+ otp_1298,
+ otp_1331,
+ otp_1338,
+ otp_1342,
+ otp_2776,
+ otp_2979,
+ otp_3187,
+ otp_3725
+ ]
+ },
{reported_bugs_2, [],
- [otp_1128_2, otp_1129_2, otp_1131_2, otp_1162_2,
- otp_1222_2, otp_1298_2, otp_1331_2, otp_1338_2,
- otp_1342_2, otp_2776_2, otp_2979_2, otp_3187_2]},
+ [
+ otp_1128_2,
+ otp_1129_2,
+ otp_1131_2,
+ otp_1162_2,
+ otp_1222_2,
+ otp_1298_2,
+ otp_1331_2,
+ otp_1338_2,
+ otp_1342_2,
+ otp_2776_2,
+ otp_2979_2,
+ otp_3187_2
+ ]
+ },
{reported_bugs_3, [],
- [otp_1128_3, otp_1129_3, otp_1131_3, otp_1162_3,
- otp_1222_3, otp_1298_3, otp_1331_3, otp_1338_3,
- otp_1342_3, otp_2776_3, otp_2979_3, otp_3187_3,
- otp_3542]},
- {tickets1, [], [{group, otp_4394}, {group, otp_7157}]},
+ [
+ otp_1128_3,
+ otp_1129_3,
+ otp_1131_3,
+ otp_1162_3,
+ otp_1222_3,
+ otp_1298_3,
+ otp_1331_3,
+ otp_1338_3,
+ otp_1342_3,
+ otp_2776_3,
+ otp_2979_3,
+ otp_3187_3,
+ otp_3542
+ ]
+ },
+ {tickets1, [],
+ [
+ {group, otp_4394},
+ {group, otp_7157}
+ ]
+ },
{tickets2, [], [otp8395]},
{otp_4394, [], [otp_4394_test]},
- {otp_7157, [],
- begin Reqs = [], Conf = [otp_7157_test], Conf end}].
+ {otp_7157, [], [otp_7157_test]
+ }
+ ].
init_per_group(all_tcs, Config) ->
init_all(Config);
@@ -378,17 +448,29 @@ end_per_testcase2(_Case, Config) ->
cases() ->
-case ?OSTYPE() of
- vxworks ->
- [{group, misc}, {group, test_v1}, {group, test_v2},
- {group, test_v1_v2}, {group, test_multi_threaded},
- {group, mib_storage}, {group, tickets1}];
- _Else ->
- [{group, misc}, {group, test_v1}, {group, test_v2},
- {group, test_v1_v2}, {group, test_v3},
- {group, test_multi_threaded}, {group, mib_storage},
- {group, tickets1}]
-end.
+ case ?OSTYPE() of
+ vxworks ->
+ [
+ {group, misc},
+ {group, test_v1},
+ {group, test_v2},
+ {group, test_v1_v2},
+ {group, test_multi_threaded},
+ {group, mib_storage},
+ {group, tickets1}
+ ];
+ _Else ->
+ [
+ {group, misc},
+ {group, test_v1},
+ {group, test_v2},
+ {group, test_v1_v2},
+ {group, test_v3},
+ {group, test_multi_threaded},
+ {group, mib_storage},
+ {group, tickets1}
+ ]
+ end.
%%%-----------------------------------------------------------------
@@ -1071,11 +1153,29 @@ app_dir(App) ->
%v1_cases() -> [loop_mib];
v1_cases() ->
-[simple, db_notify_client, v1_processing, big, big2,
- loop_mib, api, subagent, mnesia, {group, multiple_reqs},
- sa_register, v1_trap, sa_error, next_across_sa, undo,
- {group, reported_bugs}, {group, standard_mibs},
- sparse_table, cnt_64, opaque, change_target_addr_config].
+ [
+ simple,
+ db_notify_client,
+ v1_processing,
+ big,
+ big2,
+ loop_mib,
+ api,
+ subagent,
+ mnesia,
+ {group, multiple_reqs},
+ sa_register,
+ v1_trap,
+ sa_error,
+ next_across_sa,
+ undo,
+ {group, reported_bugs},
+ {group, standard_mibs},
+ sparse_table,
+ cnt_64,
+ opaque,
+ change_target_addr_config
+ ].
init_v1(Config) when is_list(Config) ->
?line SaNode = ?config(snmp_sa, Config),
@@ -1094,12 +1194,31 @@ finish_v1(Config) when is_list(Config) ->
v2_cases() ->
-[simple_2, v2_processing, big_2, big2_2, loop_mib_2,
- api_2, subagent_2, mnesia_2, {group, multiple_reqs_2},
- sa_register_2, v2_trap, {group, v2_inform}, sa_error_2,
- next_across_sa_2, undo_2, {group, reported_bugs_2},
- {group, standard_mibs_2}, v2_types, implied,
- sparse_table_2, cnt_64_2, opaque_2, v2_caps].
+ [
+ simple_2,
+ v2_processing,
+ big_2,
+ big2_2,
+ loop_mib_2,
+ api_2,
+ subagent_2,
+ mnesia_2,
+ {group, multiple_reqs_2},
+ sa_register_2,
+ v2_trap,
+ {group, v2_inform},
+ sa_error_2,
+ next_across_sa_2,
+ undo_2,
+ {group, reported_bugs_2},
+ {group, standard_mibs_2},
+ v2_types,
+ implied,
+ sparse_table_2,
+ cnt_64_2,
+ opaque_2,
+ v2_caps
+ ].
init_v2(Config) when is_list(Config) ->
SaNode = ?config(snmp_sa, Config),
@@ -1118,7 +1237,7 @@ finish_v2(Config) when is_list(Config) ->
v1_v2_cases() ->
-[simple_bi].
+ [simple_bi].
init_v1_v2(Config) when is_list(Config) ->
SaNode = ?config(snmp_sa, Config),
@@ -1137,13 +1256,32 @@ finish_v1_v2(Config) when is_list(Config) ->
v3_cases() ->
-[simple_3, v3_processing, big_3, big2_3, api_3,
- subagent_3, mnesia_3, loop_mib_3, multiple_reqs_3,
- sa_register_3, v3_trap, v3_inform, sa_error_3,
- next_across_sa_3, undo_3, {group, reported_bugs_3},
- {group, standard_mibs_3}, {group, v3_security},
- v2_types_3, implied_3, sparse_table_3, cnt_64_3,
- opaque_3, v2_caps_3].
+ [
+ simple_3,
+ v3_processing,
+ big_3,
+ big2_3,
+ api_3,
+ subagent_3,
+ mnesia_3,
+ loop_mib_3,
+ multiple_reqs_3,
+ sa_register_3,
+ v3_trap,
+ v3_inform,
+ sa_error_3,
+ next_across_sa_3,
+ undo_3,
+ {group, reported_bugs_3},
+ {group, standard_mibs_3},
+ {group, v3_security},
+ v2_types_3,
+ implied_3,
+ sparse_table_3,
+ cnt_64_3,
+ opaque_3,
+ v2_caps_3
+ ].
init_v3(Config) when is_list(Config) ->
%% Make sure crypto works, otherwise start_agent will fail
diff --git a/lib/snmp/test/snmp_agent_test_lib.erl b/lib/snmp/test/snmp_agent_test_lib.erl
index 9e89aa889c..a18d9f3201 100644
--- a/lib/snmp/test/snmp_agent_test_lib.erl
+++ b/lib/snmp/test/snmp_agent_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1311,10 +1311,12 @@ rewrite_target_addr_conf(Dir, NewPort) ->
"~n NewPort: ~p", [NewPort]),
TAFile = filename:join(Dir, "target_addr.conf"),
case file:read_file_info(TAFile) of
- {ok, _} -> ok;
- {error, R} -> ?ERR("failure reading file info of "
- "target address config file: ~p",[R]),
- ok
+ {ok, _} ->
+ ok;
+ {error, R} ->
+ ?ERR("failure reading file info of "
+ "target address config file: ~p",[R]),
+ ok
end,
?line [TrapAddr|Addrs] =
@@ -1335,8 +1337,9 @@ rewrite_target_addr_conf(Dir, NewPort) ->
rewrite_target_addr_conf_check(O) ->
{ok,O}.
-rewrite_target_addr_conf2(NewPort,{Name,Ip,_Port,Timeout,Retry,
- "std_trap",EngineId}) ->
+rewrite_target_addr_conf2(NewPort,
+ {Name, Ip, _Port, Timeout, Retry,
+ "std_trap", EngineId}) ->
?LOG("rewrite_target_addr_conf2 -> entry with std_trap",[]),
{Name,Ip,NewPort,Timeout,Retry,"std_trap",EngineId};
rewrite_target_addr_conf2(_NewPort,O) ->
diff --git a/lib/snmp/test/snmp_compiler_test.erl b/lib/snmp/test/snmp_compiler_test.erl
index 2e6020ae7a..c964b08168 100644
--- a/lib/snmp/test/snmp_compiler_test.erl
+++ b/lib/snmp/test/snmp_compiler_test.erl
@@ -47,6 +47,7 @@
module_identity/1,
agent_capabilities/1,
module_compliance/1,
+ warnings_as_errors/1,
otp_6150/1,
otp_8574/1,
@@ -97,9 +98,10 @@ all() ->
description,
oid_conflicts,
imports,
- module_identity,
- agent_capabilities,
- module_compliance,
+ module_identity,
+ agent_capabilities,
+ module_compliance,
+ warnings_as_errors,
{group, tickets}
].
@@ -152,6 +154,8 @@ description(Config) when is_list(Config) ->
ok.
+%%======================================================================
+
oid_conflicts(suite) -> [];
oid_conflicts(Config) when is_list(Config) ->
put(tname,oid_conflicts),
@@ -165,18 +169,24 @@ oid_conflicts(Config) when is_list(Config) ->
ok.
+%%======================================================================
+
imports(suite) ->
[];
imports(Config) when is_list(Config) ->
?SKIP(not_yet_implemented).
+%%======================================================================
+
module_identity(suite) ->
[];
module_identity(Config) when is_list(Config) ->
?SKIP(not_yet_implemented).
+%%======================================================================
+
agent_capabilities(suite) ->
[];
agent_capabilities(Config) when is_list(Config) ->
@@ -218,6 +228,8 @@ agent_capabilities(Config) when is_list(Config) ->
ok.
+%%======================================================================
+
module_compliance(suite) ->
[];
module_compliance(Config) when is_list(Config) ->
@@ -259,6 +271,32 @@ module_compliance(Config) when is_list(Config) ->
ok.
+%%======================================================================
+
+warnings_as_errors(suite) ->
+ ["OTP-9437"];
+warnings_as_errors(Config) when is_list(Config) ->
+ put(tname,warnings_as_errors),
+ p("starting with Config: ~p~n", [Config]),
+ Dir = ?config(comp_dir, Config),
+ MibDir = ?config(mib_dir, Config),
+ MibFile = join(MibDir, "OTP8574-MIB.mib"),
+ OutFile = join(Dir, "OTP8574-MIB.bin"),
+ Opts = [{group_check, false},
+ {outdir, Dir},
+ {verbosity, trace},
+ relaxed_row_name_assign_check],
+ {error, compilation_failed} =
+ snmpc:compile(MibFile, [warnings_as_errors|Opts]),
+ false = filelib:is_regular(OutFile),
+ {ok, _} = snmpc:compile(MibFile, Opts),
+ true = filelib:is_regular(OutFile),
+ ok = file:delete(OutFile),
+ ok.
+
+
+%%======================================================================
+
otp_6150(suite) ->
[];
otp_6150(Config) when is_list(Config) ->
@@ -273,6 +311,8 @@ otp_6150(Config) when is_list(Config) ->
ok.
+%%======================================================================
+
otp_8574(suite) ->
[];
otp_8574(Config) when is_list(Config) ->
@@ -304,6 +344,8 @@ otp_8574(Config) when is_list(Config) ->
end.
+%%======================================================================
+
otp_8595(suite) ->
[];
otp_8595(Config) when is_list(Config) ->
diff --git a/lib/snmp/test/snmp_manager_test.erl b/lib/snmp/test/snmp_manager_test.erl
index 50836db731..d18f20d359 100644
--- a/lib/snmp/test/snmp_manager_test.erl
+++ b/lib/snmp/test/snmp_manager_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
%%
%% The 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,13 +37,16 @@
-include_lib("snmp/include/snmp_types.hrl").
-include_lib("snmp/include/STANDARD-MIB.hrl").
+-include_lib("snmp/src/manager/snmpm_internal.hrl").
%%----------------------------------------------------------------------
%% External exports
%%----------------------------------------------------------------------
-export([
- all/0,groups/0,init_per_group/2,end_per_group/2,
+ all/0,
+ groups/0,
+ init_per_group/2, end_per_group/2,
init_per_testcase/2, end_per_testcase/2,
@@ -54,49 +57,46 @@
notify_started01/1,
notify_started02/1,
-
register_user1/1,
-
register_agent1/1,
register_agent2/1,
+ register_agent3/1,
-
info/1,
-
-
-
simple_sync_get1/1,
simple_sync_get2/1,
+ simple_sync_get3/1,
simple_async_get1/1,
simple_async_get2/1,
-
+ simple_async_get3/1,
simple_sync_get_next1/1,
simple_sync_get_next2/1,
+ simple_sync_get_next3/1,
simple_async_get_next1/1,
simple_async_get_next2/1,
-
+ simple_async_get_next3/1,
simple_sync_set1/1,
simple_sync_set2/1,
+ simple_sync_set3/1,
simple_async_set1/1,
simple_async_set2/1,
-
+ simple_async_set3/1,
simple_sync_get_bulk1/1,
simple_sync_get_bulk2/1,
+ simple_sync_get_bulk3/1,
simple_async_get_bulk1/1,
simple_async_get_bulk2/1,
-
+ simple_async_get_bulk3/1,
misc_async1/1,
misc_async2/1,
discovery/1,
-
-
trap1/1,
trap2/1,
@@ -109,8 +109,6 @@
report/1,
-
-
otp8015_1/1,
otp8395_1/1
@@ -220,7 +218,7 @@ init_per_testcase2(Case, Config) ->
Conf2.
init_per_testcase3(Case, Config) ->
- OldApiCases =
+ ApiCases01 =
[
simple_sync_get1,
simple_async_get1,
@@ -232,7 +230,7 @@ init_per_testcase3(Case, Config) ->
simple_async_get_bulk1,
misc_async1
],
- NewApiCases =
+ ApiCases02 =
[
simple_sync_get2,
simple_async_get2,
@@ -245,6 +243,17 @@ init_per_testcase3(Case, Config) ->
misc_async2,
otp8395_1
],
+ ApiCases03 =
+ [
+ simple_sync_get3,
+ simple_async_get3,
+ simple_sync_get_next3,
+ simple_async_get_next3,
+ simple_sync_set3,
+ simple_async_set3,
+ simple_sync_get_bulk3,
+ simple_async_get_bulk3
+ ],
Cases =
[
trap1,
@@ -256,8 +265,9 @@ init_per_testcase3(Case, Config) ->
inform_swarm,
report
] ++
- OldApiCases ++
- NewApiCases,
+ ApiCases01 ++
+ ApiCases02 ++
+ ApiCases03,
case lists:member(Case, Cases) of
true ->
NoAutoInformCases = [inform1, inform2, inform3, inform_swarm],
@@ -279,7 +289,7 @@ init_per_testcase3(Case, Config) ->
Conf2 = init_agent(Conf1),
Conf3 = init_manager(AutoInform, Conf2),
Conf4 = init_mgr_user(Conf3),
- case lists:member(Case, NewApiCases) of
+ case lists:member(Case, ApiCases02 ++ ApiCases03) of
true ->
init_mgr_user_data2(Conf4);
false ->
@@ -301,7 +311,7 @@ end_per_testcase(Case, Config) when is_list(Config) ->
Conf2.
end_per_testcase2(Case, Config) ->
- OldApiCases =
+ ApiCases01 =
[
simple_sync_get1,
simple_async_get1,
@@ -313,7 +323,7 @@ end_per_testcase2(Case, Config) ->
simple_async_get_bulk1,
misc_async1
],
- NewApiCases =
+ ApiCases02 =
[
simple_sync_get2,
simple_async_get2,
@@ -326,6 +336,17 @@ end_per_testcase2(Case, Config) ->
misc_async2,
otp8395_1
],
+ ApiCases03 =
+ [
+ simple_sync_get3,
+ simple_async_get3,
+ simple_sync_get_next3,
+ simple_async_get_next3,
+ simple_sync_set3,
+ simple_async_set3,
+ simple_sync_get_bulk3,
+ simple_async_get_bulk3
+ ],
Cases =
[
trap1,
@@ -337,11 +358,12 @@ end_per_testcase2(Case, Config) ->
inform_swarm,
report
] ++
- OldApiCases ++
- NewApiCases,
+ ApiCases01 ++
+ ApiCases02 ++
+ ApiCases03,
case lists:member(Case, Cases) of
true ->
- Conf1 = case lists:member(Case, NewApiCases) of
+ Conf1 = case lists:member(Case, ApiCases02 ++ ApiCases03) of
true ->
fin_mgr_user_data2(Config);
false ->
@@ -360,42 +382,130 @@ end_per_testcase2(Case, Config) ->
%%======================================================================
all() ->
-[{group, start_and_stop_tests}, {group, misc_tests},
- {group, user_tests}, {group, agent_tests},
- {group, request_tests}, {group, event_tests}, discovery,
- {group, tickets}].
+ [
+ {group, start_and_stop_tests},
+ {group, misc_tests},
+ {group, user_tests},
+ {group, agent_tests},
+ {group, request_tests},
+ {group, event_tests},
+ discovery,
+ {group, tickets}
+ ].
groups() ->
- [{start_and_stop_tests, [],
- [simple_start_and_stop1, simple_start_and_stop2,
- simple_start_and_monitor_crash1,
- simple_start_and_monitor_crash2, notify_started01,
- notify_started02]},
- {misc_tests, [], [info]},
- {user_tests, [], [register_user1]},
- {agent_tests, [], [register_agent1, register_agent2]},
- {request_tests, [],
- [{group, get_tests}, {group, get_next_tests},
- {group, set_tests}, {group, bulk_tests},
- {group, misc_request_tests}]},
- {get_tests, [],
- [simple_sync_get1, simple_sync_get2, simple_async_get1,
- simple_async_get2]},
- {get_next_tests, [],
- [simple_sync_get_next1, simple_sync_get_next2,
- simple_async_get_next1, simple_async_get_next2]},
- {set_tests, [],
- [simple_sync_set1, simple_sync_set2, simple_async_set1,
- simple_async_set2]},
- {bulk_tests, [],
- [simple_sync_get_bulk1, simple_sync_get_bulk2,
- simple_async_get_bulk1, simple_async_get_bulk2]},
- {misc_request_tests, [], [misc_async1, misc_async2]},
- {event_tests, [],
- [trap1, trap2, inform1, inform2, inform3, inform4,
- inform_swarm, report]},
- {tickets, [], [{group, otp8015}, {group, otp8395}]},
- {otp8015, [], [otp8015_1]}, {otp8395, [], [otp8395_1]}].
+ [
+ {start_and_stop_tests, [],
+ [
+ simple_start_and_stop1,
+ simple_start_and_stop2,
+ simple_start_and_monitor_crash1,
+ simple_start_and_monitor_crash2,
+ notify_started01,
+ notify_started02
+ ]
+ },
+ {misc_tests, [],
+ [
+ info
+ ]
+ },
+ {user_tests, [],
+ [
+ register_user1
+ ]
+ },
+ {agent_tests, [],
+ [
+ register_agent1,
+ register_agent2,
+ register_agent3
+ ]
+ },
+ {request_tests, [],
+ [
+ {group, get_tests},
+ {group, get_next_tests},
+ {group, set_tests},
+ {group, bulk_tests},
+ {group, misc_request_tests}
+ ]
+ },
+ {get_tests, [],
+ [
+ simple_sync_get1,
+ simple_sync_get2,
+ simple_sync_get3,
+ simple_async_get1,
+ simple_async_get2,
+ simple_async_get3
+ ]
+ },
+ {get_next_tests, [],
+ [
+ simple_sync_get_next1,
+ simple_sync_get_next2,
+ simple_sync_get_next3,
+ simple_async_get_next1,
+ simple_async_get_next2,
+ simple_async_get_next3
+ ]
+ },
+ {set_tests, [],
+ [
+ simple_sync_set1,
+ simple_sync_set2,
+ simple_sync_set3,
+ simple_async_set1,
+ simple_async_set2,
+ simple_async_set3
+ ]
+ },
+ {bulk_tests, [],
+ [
+ simple_sync_get_bulk1,
+ simple_sync_get_bulk2,
+ simple_sync_get_bulk3,
+ simple_async_get_bulk1,
+ simple_async_get_bulk2,
+ simple_async_get_bulk3
+ ]
+ },
+ {misc_request_tests, [],
+ [
+ misc_async1,
+ misc_async2
+ ]
+ },
+ {event_tests, [],
+ [
+ trap1%% ,
+ %% trap2,
+ %% inform1,
+ %% inform2,
+ %% inform3,
+ %% inform4,
+ %% inform_swarm,
+ %% report
+ ]
+ },
+ {tickets, [],
+ [
+ {group, otp8015},
+ {group, otp8395}
+ ]
+ },
+ {otp8015, [],
+ [
+ otp8015_1
+ ]
+ },
+ {otp8395, [],
+ [
+ otp8395_1
+ ]
+ }
+ ].
init_per_group(_GroupName, Config) ->
Config.
@@ -404,21 +514,6 @@ end_per_group(_GroupName, Config) ->
Config.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
%%======================================================================
%% Test functions
%%======================================================================
@@ -1041,6 +1136,7 @@ register_agent1(suite) ->
register_agent1(Config) when is_list(Config) ->
process_flag(trap_exit, true),
put(tname,ra1),
+
p("starting with Config: ~p~n", [Config]),
ManagerNode = start_manager_node(),
@@ -1071,7 +1167,7 @@ register_agent1(Config) when is_list(Config) ->
p("manager info: ~p~n", [mgr_info(ManagerNode)]),
- p("register user(s) calvin & hobbe"),
+ p("register user(s) user_alfa & user_beta"),
?line ok = mgr_register_user(ManagerNode, user_alfa, snmpm_user_default, []),
?line ok = mgr_register_user(ManagerNode, user_beta, snmpm_user_default, []),
p("manager info: ~p~n", [mgr_info(ManagerNode)]),
@@ -1200,7 +1296,7 @@ register_agent2(Config) when is_list(Config) ->
p("manager info: ~p~n", [mgr_info(ManagerNode)]),
- p("register user(s) calvin & hobbe"),
+ p("register user(s) user_alfa & user_beta"),
?line ok = mgr_register_user(ManagerNode, user_alfa, snmpm_user_default, []),
?line ok = mgr_register_user(ManagerNode, user_beta, snmpm_user_default, []),
p("manager info: ~p~n", [mgr_info(ManagerNode)]),
@@ -1255,7 +1351,7 @@ register_agent2(Config) when is_list(Config) ->
end,
p("manager info: ~p~n", [mgr_info(ManagerNode)]),
-
+
p("unregister user user_alfa"),
?line ok = mgr_unregister_user(ManagerNode, user_alfa),
@@ -1284,7 +1380,157 @@ register_agent2(Config) when is_list(Config) ->
p("manager info: ~p~n", [mgr_info(ManagerNode)]),
- p("unregister user hobbe"),
+ p("unregister user user_beta"),
+ ?line ok = mgr_unregister_user(ManagerNode, user_beta),
+
+ p("manager info: ~p~n", [mgr_info(ManagerNode)]),
+
+ ?SLEEP(1000),
+
+ p("stop snmp application (with only manager)"),
+ ?line ok = stop_snmp(ManagerNode),
+
+ ?SLEEP(1000),
+
+ stop_node(ManagerNode),
+
+ ?SLEEP(1000),
+
+ p("end"),
+ ok.
+
+
+%%======================================================================
+
+register_agent3(doc) ->
+ ["Test registration of agents with the NEW interface functions "
+ "and specifying transport domain"];
+register_agent3(suite) ->
+ [];
+register_agent3(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ put(tname, ra3),
+ p("starting with Config: ~p~n", [Config]),
+
+ ManagerNode = start_manager_node(),
+
+ ConfDir = ?config(manager_conf_dir, Config),
+ DbDir = ?config(manager_db_dir, Config),
+ LocalHost = snmp_test_lib:localhost(),
+
+
+ write_manager_conf(ConfDir),
+
+ Opts = [{server, [{verbosity, trace}]},
+ {net_if, [{verbosity, trace}]},
+ {note_store, [{verbosity, trace}]},
+ {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}],
+
+
+ p("load snmp application"),
+ ?line ok = load_snmp(ManagerNode),
+
+ p("set manager env for the snmp application"),
+ ?line ok = set_mgr_env(ManagerNode, Opts),
+
+ p("starting snmp application (with only manager)"),
+ ?line ok = start_snmp(ManagerNode),
+
+ p("started"),
+
+ ?SLEEP(1000),
+
+ p("manager info: ~p~n", [mgr_info(ManagerNode)]),
+
+ p("register user(s) user_alfa & user_beta"),
+ ?line ok = mgr_register_user(ManagerNode, user_alfa, snmpm_user_default, []),
+ ?line ok = mgr_register_user(ManagerNode, user_beta, snmpm_user_default, []),
+ p("manager info: ~p~n", [mgr_info(ManagerNode)]),
+
+ p("register agent(s)"),
+ TargetName1 = "agent2",
+ ?line ok = mgr_register_agent(ManagerNode, user_alfa, TargetName1,
+ [{tdomain, transportDomainUdpIpv4},
+ {address, LocalHost},
+ {port, 5001},
+ {engine_id, "agentEngineId-1"}]),
+ TargetName2 = "agent3",
+ ?line ok = mgr_register_agent(ManagerNode, user_alfa, TargetName2,
+ [{tdomain, transportDomainUdpIpv6},
+ {address, LocalHost},
+ {port, 5002},
+ {engine_id, "agentEngineId-2"}]),
+ TargetName3 = "agent4",
+ ?line {error, {unsupported_domain, _} = Reason4} =
+ mgr_register_agent(ManagerNode, user_beta, TargetName3,
+ [{tdomain, transportDomainTcpIpv4},
+ {address, LocalHost},
+ {port, 5003},
+ {engine_id, "agentEngineId-3"}]),
+ p("Expected registration failure: ~p", [Reason4]),
+ TargetName4 = "agent5",
+ ?line {error, {unknown_domain, _} = Reason5} =
+ mgr_register_agent(ManagerNode, user_beta, TargetName4,
+ [{tdomain, transportDomainUdpIpv4_bad},
+ {address, LocalHost},
+ {port, 5004},
+ {engine_id, "agentEngineId-4"}]),
+ p("Expected registration failure: ~p", [Reason5]),
+
+ p("verify all agent(s): expect 2"),
+ case mgr_which_agents(ManagerNode) of
+ Agents1 when length(Agents1) =:= 2 ->
+ p("all agents: ~p~n", [Agents1]),
+ ok;
+ Agents1 ->
+ ?FAIL({agent_registration_failure, Agents1})
+ end,
+
+ p("verify user_alfa agent(s)"),
+ case mgr_which_agents(ManagerNode, user_alfa) of
+ Agents2 when length(Agents2) =:= 2 ->
+ p("calvin agents: ~p~n", [Agents2]),
+ ok;
+ Agents2 ->
+ ?FAIL({agent_registration_failure, Agents2})
+ end,
+
+ p("verify user_beta agent(s)"),
+ case mgr_which_agents(ManagerNode, user_beta) of
+ Agents3 when length(Agents3) =:= 0 ->
+ p("hobbe agents: ~p~n", [Agents3]),
+ ok;
+ Agents3 ->
+ ?FAIL({agent_registration_failure, Agents3})
+ end,
+
+ p("manager info: ~p~n", [mgr_info(ManagerNode)]),
+
+ p("unregister user user_alfa"),
+ ?line ok = mgr_unregister_user(ManagerNode, user_alfa),
+
+ p("verify all agent(s): expect 0"),
+ case mgr_which_agents(ManagerNode) of
+ Agents4 when length(Agents4) =:= 0 ->
+ p("all agents: ~p~n", [Agents4]),
+ ok;
+ Agents4 ->
+ ?FAIL({agent_unregistration_failure, Agents4})
+ end,
+ p("manager info: ~p~n", [mgr_info(ManagerNode)]),
+
+ p("verify all agent(s): expect 0"),
+ case mgr_which_agents(ManagerNode) of
+ [] ->
+ ok;
+ Agents5 ->
+ p("all agents: ~p~n", [Agents5]),
+ ?FAIL({agent_unregistration_failure, Agents5})
+ end,
+
+ p("manager info: ~p~n", [mgr_info(ManagerNode)]),
+
+ p("unregister user user_beta"),
?line ok = mgr_unregister_user(ManagerNode, user_beta),
p("manager info: ~p~n", [mgr_info(ManagerNode)]),
@@ -1319,15 +1565,15 @@ simple_sync_get1(Config) when is_list(Config) ->
p("issue get-request without loading the mib"),
Oids1 = [?sysObjectID_instance, ?sysDescr_instance, ?sysUpTime_instance],
- ?line ok = do_simple_get(Node, Addr, Port, Oids1),
+ ?line ok = do_simple_sync_get(Node, Addr, Port, Oids1),
p("issue get-request after first loading the mibs"),
?line ok = mgr_user_load_mib(Node, std_mib()),
Oids2 = [[sysObjectID, 0], [sysDescr, 0], [sysUpTime, 0]],
- ?line ok = do_simple_get(Node, Addr, Port, Oids2),
+ ?line ok = do_simple_sync_get(Node, Addr, Port, Oids2),
ok.
-do_simple_get(Node, Addr, Port, Oids) ->
+do_simple_sync_get(Node, Addr, Port, Oids) ->
?line {ok, Reply, Rem} = mgr_user_sync_get(Node, Addr, Port, Oids),
?DBG("~n Reply: ~p"
@@ -1360,14 +1606,22 @@ do_simple_get(Node, Addr, Port, Oids) ->
%%======================================================================
-simple_sync_get2(doc) -> ["Simple sync get-request - New style (TargetName)"];
+simple_sync_get2(doc) ->
+ ["Simple sync get-request - Version 2 API (TargetName)"];
simple_sync_get2(suite) -> [];
simple_sync_get2(Config) when is_list(Config) ->
process_flag(trap_exit, true),
put(tname, ssg2),
- do_simple_get(Config).
+ do_simple_sync_get2(Config).
-do_simple_get(Config) ->
+do_simple_sync_get2(Config) ->
+ Get = fun(Node, TargetName, Oids) ->
+ mgr_user_sync_get(Node, TargetName, Oids)
+ end,
+ PostVerify = fun() -> ok end,
+ do_simple_sync_get2(Config, Get, PostVerify).
+
+do_simple_sync_get2(Config, Get, PostVerify) ->
p("starting with Config: ~p~n", [Config]),
Node = ?config(manager_node, Config),
@@ -1375,20 +1629,21 @@ do_simple_get(Config) ->
p("issue get-request without loading the mib"),
Oids1 = [?sysObjectID_instance, ?sysDescr_instance, ?sysUpTime_instance],
- ?line ok = do_simple_get(Node, TargetName, Oids1),
+ ?line ok = do_simple_sync_get2(Node, TargetName, Oids1, Get, PostVerify),
p("issue get-request after first loading the mibs"),
?line ok = mgr_user_load_mib(Node, std_mib()),
Oids2 = [[sysObjectID, 0], [sysDescr, 0], [sysUpTime, 0]],
- ?line ok = do_simple_get(Node, TargetName, Oids2),
+ ?line ok = do_simple_sync_get2(Node, TargetName, Oids2, Get, PostVerify),
ok.
-
-do_simple_get(Node, TargetName, Oids) ->
- ?line {ok, Reply, Rem} = mgr_user_sync_get(Node, TargetName, Oids),
+
+do_simple_sync_get2(Node, TargetName, Oids, Get, PostVerify)
+ when is_function(Get, 3) andalso is_function(PostVerify, 0) ->
+ ?line {ok, Reply, Rem} = Get(Node, TargetName, Oids),
?DBG("~n Reply: ~p"
"~n Rem: ~w", [Reply, Rem]),
-
+
%% verify that the operation actually worked:
%% The order should be the same, so no need to seach
?line ok = case Reply of
@@ -1403,7 +1658,7 @@ do_simple_get(Node, TargetName, Oids) ->
"~n SysDescr: ~s"
"~n SysUpTime: ~w",
[SysObjectID, SysDescr, SysUpTime]),
- ok;
+ PostVerify();
{noError, 0, Vbs} ->
p("unexpected varbinds: ~n~p", [Vbs]),
{error, {unexpected_vbs, Vbs}};
@@ -1416,6 +1671,38 @@ do_simple_get(Node, TargetName, Oids) ->
%%======================================================================
+simple_sync_get3(doc) ->
+ ["Simple sync get-request - Version 3 API (TargetName and send-opts)"];
+simple_sync_get3(suite) -> [];
+simple_sync_get3(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ put(tname, ssg3),
+ do_simple_sync_get3(Config).
+
+do_simple_sync_get3(Config) ->
+ Self = self(),
+ Msg = simple_sync_get3,
+ Fun = fun() -> Self ! Msg end,
+ Extra = {?SNMPM_EXTRA_INFO_TAG, Fun},
+ SendOpts =
+ [
+ {extra, Extra}
+ ],
+ Get = fun(Node, TargetName, Oids) ->
+ mgr_user_sync_get2(Node, TargetName, Oids, SendOpts)
+ end,
+ PostVerify =
+ fun() ->
+ receive
+ Msg ->
+ ok
+ end
+ end,
+ do_simple_sync_get2(Config, Get, PostVerify).
+
+
+%%======================================================================
+
simple_async_get1(doc) -> ["Simple (async) get-request - "
"Old style (Addr & Port)"];
simple_async_get1(suite) -> [];
@@ -1435,40 +1722,41 @@ simple_async_get1(Config) when is_list(Config) ->
?line ok = agent_load_mib(AgentNode, Test2Mib),
Exec = fun(Data) ->
- async_g_exec1(MgrNode, Addr, Port, Data)
+ async_g_exec1(MgrNode, Addr, Port, Data)
end,
- Requests = [
- { 1,
- [?sysObjectID_instance],
- Exec,
- fun(X) -> sag_verify(X, [?sysObjectID_instance]) end},
- { 2,
- [?sysDescr_instance, ?sysUpTime_instance],
- Exec,
- fun(X) ->
- sag_verify(X, [?sysObjectID_instance,
- ?sysUpTime_instance])
- end},
- { 3,
- [[sysObjectID, 0], [sysDescr, 0], [sysUpTime, 0]],
- Exec,
- fun(X) ->
- sag_verify(X, [?sysObjectID_instance,
- ?sysDescr_instance,
- ?sysUpTime_instance])
- end},
- { 4,
- [?sysObjectID_instance,
- ?sysDescr_instance,
- ?sysUpTime_instance],
- Exec,
- fun(X) ->
- sag_verify(X, [?sysObjectID_instance,
- ?sysDescr_instance,
- ?sysUpTime_instance])
- end}
- ],
+ Requests =
+ [
+ { 1,
+ [?sysObjectID_instance],
+ Exec,
+ fun(X) -> sag_verify(X, [?sysObjectID_instance]) end },
+ { 2,
+ [?sysDescr_instance, ?sysUpTime_instance],
+ Exec,
+ fun(X) ->
+ sag_verify(X, [?sysObjectID_instance,
+ ?sysUpTime_instance])
+ end },
+ { 3,
+ [[sysObjectID, 0], [sysDescr, 0], [sysUpTime, 0]],
+ Exec,
+ fun(X) ->
+ sag_verify(X, [?sysObjectID_instance,
+ ?sysDescr_instance,
+ ?sysUpTime_instance])
+ end },
+ { 4,
+ [?sysObjectID_instance,
+ ?sysDescr_instance,
+ ?sysUpTime_instance],
+ Exec,
+ fun(X) ->
+ sag_verify(X, [?sysObjectID_instance,
+ ?sysDescr_instance,
+ ?sysUpTime_instance])
+ end }
+ ],
p("manager info when starting test: ~n~p", [mgr_info(MgrNode)]),
p("agent info when starting test: ~n~p", [agent_info(AgentNode)]),
@@ -1516,66 +1804,76 @@ sag_verify_vbs([Vb|_], [E|_]) ->
%%======================================================================
-simple_async_get2(doc) -> ["Simple (async) get-request - "
- "New style (TargetName)"];
+simple_async_get2(doc) ->
+ ["Simple (async) get-request - Version 2 API (TargetName)"];
simple_async_get2(suite) -> [];
simple_async_get2(Config) when is_list(Config) ->
process_flag(trap_exit, true),
put(tname, sag2),
p("starting with Config: ~p~n", [Config]),
-
MgrNode = ?config(manager_node, Config),
AgentNode = ?config(agent_node, Config),
TargetName = ?config(manager_agent_target_name, Config),
+ Get = fun(Oids) -> async_g_exec2(MgrNode, TargetName, Oids) end,
+ PostVerify = fun(Res) -> Res end,
+ do_simple_async_sync_get2(Config, MgrNode, AgentNode, Get, PostVerify).
+do_simple_async_sync_get2(Config, MgrNode, AgentNode, Get, PostVerify) ->
?line ok = mgr_user_load_mib(MgrNode, std_mib()),
Test2Mib = test2_mib(Config),
?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
?line ok = agent_load_mib(AgentNode, Test2Mib),
-
- Exec = fun(Data) ->
- async_g_exec2(MgrNode, TargetName, Data)
- end,
-
- Requests = [
- { 1,
- [?sysObjectID_instance],
- Exec,
- fun(X) -> sag_verify(X, [?sysObjectID_instance]) end},
- { 2,
- [?sysDescr_instance, ?sysUpTime_instance],
- Exec,
- fun(X) ->
- sag_verify(X, [?sysObjectID_instance,
- ?sysUpTime_instance])
- end},
- { 3,
- [[sysObjectID, 0], [sysDescr, 0], [sysUpTime, 0]],
- Exec,
- fun(X) ->
- sag_verify(X, [?sysObjectID_instance,
- ?sysDescr_instance,
- ?sysUpTime_instance])
- end},
- { 4,
- [?sysObjectID_instance,
- ?sysDescr_instance,
- ?sysUpTime_instance],
- Exec,
- fun(X) ->
- sag_verify(X, [?sysObjectID_instance,
- ?sysDescr_instance,
- ?sysUpTime_instance])
- end}
- ],
+ do_simple_async_sync_get2(fun() -> mgr_info(MgrNode) end,
+ fun() -> agent_info(AgentNode) end,
+ Get, PostVerify).
+
+do_simple_async_sync_get2(MgrInfo, AgentInfo, Get, PostVerify)
+ when is_function(MgrInfo, 0) andalso
+ is_function(AgentInfo, 0) andalso
+ is_function(Get, 1) andalso
+ is_function(PostVerify, 1) ->
+ Requests =
+ [
+ { 1,
+ [?sysObjectID_instance],
+ Get,
+ fun(X) ->
+ PostVerify(sag_verify(X, [?sysObjectID_instance])) end},
+ { 2,
+ [?sysDescr_instance, ?sysUpTime_instance],
+ Get,
+ fun(X) ->
+ PostVerify(sag_verify(X, [?sysObjectID_instance,
+ ?sysUpTime_instance]))
+ end},
+ { 3,
+ [[sysObjectID, 0], [sysDescr, 0], [sysUpTime, 0]],
+ Get,
+ fun(X) ->
+ PostVerify(sag_verify(X, [?sysObjectID_instance,
+ ?sysDescr_instance,
+ ?sysUpTime_instance]))
+
+ end},
+ { 4,
+ [?sysObjectID_instance,
+ ?sysDescr_instance,
+ ?sysUpTime_instance],
+ Get,
+ fun(X) ->
+ PostVerify(sag_verify(X, [?sysObjectID_instance,
+ ?sysDescr_instance,
+ ?sysUpTime_instance]))
+ end}
+ ],
- p("manager info when starting test: ~n~p", [mgr_info(MgrNode)]),
- p("agent info when starting test: ~n~p", [agent_info(AgentNode)]),
+ p("manager info when starting test: ~n~p", [MgrInfo()]),
+ p("agent info when starting test: ~n~p", [AgentInfo()]),
?line ok = async_exec(Requests, []),
- p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]),
- p("agent info when ending test: ~n~p", [agent_info(AgentNode)]),
+ p("manager info when ending test: ~n~p", [MgrInfo()]),
+ p("agent info when ending test: ~n~p", [AgentInfo()]),
ok.
@@ -1585,6 +1883,36 @@ async_g_exec2(Node, TargetName, Oids) ->
%%======================================================================
+simple_async_get3(doc) ->
+ ["Simple (async) get-request - Version 3 API (TargetName and send-opts)"];
+simple_async_get3(suite) -> [];
+simple_async_get3(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ put(tname, sag3),
+ p("starting with Config: ~p~n", [Config]),
+ MgrNode = ?config(manager_node, Config),
+ AgentNode = ?config(agent_node, Config),
+ TargetName = ?config(manager_agent_target_name, Config),
+ Self = self(),
+ Msg = simple_async_get3,
+ Fun = fun() -> Self ! Msg end,
+ Extra = {?SNMPM_EXTRA_INFO_TAG, Fun},
+ SendOpts =
+ [
+ {extra, Extra}
+ ],
+ Get = fun(Oids) -> async_g_exec3(MgrNode, TargetName, Oids, SendOpts) end,
+ PostVerify = fun(ok) -> receive Msg -> ok end;
+ (Error) -> Error
+ end,
+ do_simple_async_sync_get2(Config, MgrNode, AgentNode, Get, PostVerify).
+
+async_g_exec3(Node, TargetName, Oids, SendOpts) ->
+ mgr_user_async_get2(Node, TargetName, Oids, SendOpts).
+
+
+%%======================================================================
+
simple_sync_get_next1(doc) -> ["Simple (sync) get_next-request - "
"Old style (Addr & Port)"];
simple_sync_get_next1(suite) -> [];
@@ -1722,23 +2050,33 @@ check_ssgn_vbs([Vb|_], [E|_]) ->
%%======================================================================
-simple_sync_get_next2(doc) -> ["Simple (sync) get_next-request - "
- "New style (TargetName)"];
+simple_sync_get_next2(doc) ->
+ ["Simple (sync) get_next-request - Version 2 API (TargetName)"];
simple_sync_get_next2(suite) -> [];
simple_sync_get_next2(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- put(tname, ssgn),
+ put(tname, ssgn2),
p("starting with Config: ~p~n", [Config]),
- MgrNode = ?config(manager_node, Config),
- AgentNode = ?config(agent_node, Config),
+ GetNext = fun(Node, TargetName, Oids) ->
+ mgr_user_sync_get_next(Node, TargetName, Oids)
+ end,
+ PostVerify = fun(Res) -> Res end,
+ do_simple_sync_get_next2(Config, GetNext, PostVerify).
+
+do_simple_sync_get_next2(Config, GetNext, PostVerify)
+ when is_function(GetNext, 3) andalso is_function(PostVerify, 1) ->
+
+ MgrNode = ?config(manager_node, Config),
+ AgentNode = ?config(agent_node, Config),
TargetName = ?config(manager_agent_target_name, Config),
%% -- 1 --
Oids01 = [[1,3,7,1]],
VF01 = fun(X) -> verify_ssgn_reply1(X, [{[1,3,7,1],endOfMibView}]) end,
?line ok = do_simple_get_next(1,
- MgrNode, TargetName, Oids01, VF01),
+ MgrNode, TargetName, Oids01, VF01,
+ GetNext, PostVerify),
?line ok = mgr_user_load_mib(MgrNode, std_mib()),
@@ -1748,7 +2086,8 @@ simple_sync_get_next2(Config) when is_list(Config) ->
verify_ssgn_reply1(X, [?sysDescr_instance, endOfMibView])
end,
?line ok = do_simple_get_next(2,
- MgrNode, TargetName, Oids02, VF02),
+ MgrNode, TargetName, Oids02, VF02,
+ GetNext, PostVerify),
Test2Mib = test2_mib(Config),
?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
@@ -1761,7 +2100,8 @@ simple_sync_get_next2(Config) when is_list(Config) ->
verify_ssgn_reply1(X, [{fl([TCnt2,2]), 100}])
end,
?line ok = do_simple_get_next(3,
- MgrNode, TargetName, Oids03, VF03),
+ MgrNode, TargetName, Oids03, VF03,
+ GetNext, PostVerify),
%% -- 4 --
Oids04 = [[TCnt2, 2]],
@@ -1769,7 +2109,8 @@ simple_sync_get_next2(Config) when is_list(Config) ->
verify_ssgn_reply1(X, [{fl([TCnt2,2]), endOfMibView}])
end,
?line ok = do_simple_get_next(4,
- MgrNode, TargetName, Oids04, VF04),
+ MgrNode, TargetName, Oids04, VF04,
+ GetNext, PostVerify),
%% -- 5 --
?line {ok, [TGenErr1|_]} = mgr_user_name_to_oid(MgrNode, tGenErr1),
@@ -1778,7 +2119,8 @@ simple_sync_get_next2(Config) when is_list(Config) ->
verify_ssgn_reply2(X, {genErr, 1, [TGenErr1]})
end,
?line ok = do_simple_get_next(5,
- MgrNode, TargetName, Oids05, VF05),
+ MgrNode, TargetName, Oids05, VF05,
+ GetNext, PostVerify),
%% -- 6 --
?line {ok, [TGenErr2|_]} = mgr_user_name_to_oid(MgrNode, tGenErr2),
@@ -1787,7 +2129,8 @@ simple_sync_get_next2(Config) when is_list(Config) ->
verify_ssgn_reply2(X, {genErr, 1, [TGenErr2]})
end,
?line ok = do_simple_get_next(6,
- MgrNode, TargetName, Oids06, VF06),
+ MgrNode, TargetName, Oids06, VF06,
+ GetNext, PostVerify),
%% -- 7 --
?line {ok, [TGenErr3|_]} = mgr_user_name_to_oid(MgrNode, tGenErr3),
@@ -1797,7 +2140,8 @@ simple_sync_get_next2(Config) when is_list(Config) ->
[?sysDescr, TGenErr3]})
end,
?line ok = do_simple_get_next(7,
- MgrNode, TargetName, Oids07, VF07),
+ MgrNode, TargetName, Oids07, VF07,
+ GetNext, PostVerify),
%% -- 8 --
?line {ok, [TTooBig|_]} = mgr_user_name_to_oid(MgrNode, tTooBig),
@@ -1806,18 +2150,19 @@ simple_sync_get_next2(Config) when is_list(Config) ->
verify_ssgn_reply2(X, {tooBig, 0, []})
end,
?line ok = do_simple_get_next(8,
- MgrNode, TargetName, Oids08, VF08),
+ MgrNode, TargetName, Oids08, VF08,
+ GetNext, PostVerify),
ok.
-do_simple_get_next(N, Node, TargetName, Oids, Verify) ->
+do_simple_get_next(N, Node, TargetName, Oids, Verify, GetNext, PostVerify) ->
p("issue get-next command ~w", [N]),
- case mgr_user_sync_get_next(Node, TargetName, Oids) of
+ case GetNext(Node, TargetName, Oids) of
{ok, Reply, Rem} ->
?DBG("get-next ok:"
"~n Reply: ~p"
"~n Rem: ~w", [Reply, Rem]),
- Verify(Reply);
+ PostVerify(Verify(Reply));
Error ->
{error, {unexpected_reply, Error}}
@@ -1826,6 +2171,33 @@ do_simple_get_next(N, Node, TargetName, Oids, Verify) ->
%%======================================================================
+simple_sync_get_next3(doc) ->
+ ["Simple (sync) get_next-request - "
+ "Version 3 API (TargetName with send-opts)"];
+simple_sync_get_next3(suite) -> [];
+simple_sync_get_next3(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ put(tname, ssgn3),
+ p("starting with Config: ~p~n", [Config]),
+ Self = self(),
+ Msg = simple_sync_get_next3,
+ Fun = fun() -> Self ! Msg end,
+ Extra = {?SNMPM_EXTRA_INFO_TAG, Fun},
+ SendOpts =
+ [
+ {extra, Extra}
+ ],
+ GetNext = fun(Node, TargetName, Oids) ->
+ mgr_user_sync_get_next2(Node, TargetName, Oids, SendOpts)
+ end,
+ PostVerify = fun(ok) -> receive Msg -> ok end;
+ (Error) -> Error
+ end,
+ do_simple_sync_get_next2(Config, GetNext, PostVerify).
+
+
+%%======================================================================
+
simple_async_get_next1(doc) -> ["Simple (async) get_next-request - "
"Old style (Addr & Port)"];
simple_async_get_next1(suite) -> [];
@@ -1923,8 +2295,8 @@ async_gn_exec1(Node, Addr, Port, Oids) ->
%%======================================================================
-simple_async_get_next2(doc) -> ["Simple (async) get_next-request - "
- "New style (TargetName)"];
+simple_async_get_next2(doc) ->
+ ["Simple (async) get_next-request - Version 2 API (TargetName)"];
simple_async_get_next2(suite) -> [];
simple_async_get_next2(Config) when is_list(Config) ->
process_flag(trap_exit, true),
@@ -1939,11 +2311,14 @@ simple_async_get_next2(Config) when is_list(Config) ->
Test2Mib = test2_mib(Config),
?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
?line ok = agent_load_mib(AgentNode, Test2Mib),
-
- Exec = fun(X) ->
- async_gn_exec2(MgrNode, TargetName, X)
- end,
-
+ GetNext = fun(Oids) ->
+ async_gn_exec2(MgrNode, TargetName, Oids)
+ end,
+ PostVerify = fun(Res) -> Res end,
+ do_simple_async_get_next2(MgrNode, AgentNode, GetNext, PostVerify).
+
+do_simple_async_get_next2(MgrNode, AgentNode, GetNext, PostVerify)
+ when is_function(GetNext, 1) andalso is_function(PostVerify, 1) ->
?line {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2),
?line {ok, [TGenErr1|_]} = mgr_user_name_to_oid(MgrNode, tGenErr1),
?line {ok, [TGenErr2|_]} = mgr_user_name_to_oid(MgrNode, tGenErr2),
@@ -1954,51 +2329,60 @@ simple_async_get_next2(Config) when is_list(Config) ->
[
{1,
[[1,3,7,1]],
- Exec,
+ GetNext,
fun(X) ->
- verify_ssgn_reply1(X, [{[1,3,7,1], endOfMibView}])
+ PostVerify(
+ verify_ssgn_reply1(X, [{[1,3,7,1], endOfMibView}]))
+
end},
{2,
[[sysDescr], [1,3,7,1]],
- Exec,
+ GetNext,
fun(X) ->
- verify_ssgn_reply1(X, [?sysDescr_instance, endOfMibView])
+ PostVerify(
+ verify_ssgn_reply1(X, [?sysDescr_instance, endOfMibView]))
end},
{3,
[[TCnt2, 1]],
- Exec,
+ GetNext,
fun(X) ->
- verify_ssgn_reply1(X, [{fl([TCnt2,2]), 100}])
+ PostVerify(
+ verify_ssgn_reply1(X, [{fl([TCnt2,2]), 100}]))
end},
{4,
[[TCnt2, 2]],
- Exec,
+ GetNext,
fun(X) ->
- verify_ssgn_reply1(X, [{fl([TCnt2,2]), endOfMibView}])
+ PostVerify(
+ verify_ssgn_reply1(X, [{fl([TCnt2,2]), endOfMibView}]))
end},
{5,
[TGenErr1],
- Exec,
+ GetNext,
fun(X) ->
- verify_ssgn_reply2(X, {genErr, 1, [TGenErr1]})
+ PostVerify(
+ verify_ssgn_reply2(X, {genErr, 1, [TGenErr1]}))
end},
{6,
[TGenErr2],
- Exec,
+ GetNext,
fun(X) ->
- verify_ssgn_reply2(X, {genErr, 1, [TGenErr2]})
+ PostVerify(
+ verify_ssgn_reply2(X, {genErr, 1, [TGenErr2]}))
end},
{7,
[[sysDescr], TGenErr3],
- Exec,
+ GetNext,
fun(X) ->
- verify_ssgn_reply2(X, {genErr, 2, [TGenErr3]})
+ PostVerify(
+ verify_ssgn_reply2(X, {genErr, 2, [TGenErr3]}))
end},
{8,
[TTooBig],
- Exec,
+ GetNext,
fun(X) ->
- verify_ssgn_reply2(X, {tooBig, 0, []})
+ PostVerify(
+ verify_ssgn_reply2(X, {tooBig, 0, []}))
end}
],
@@ -2019,6 +2403,48 @@ async_gn_exec2(Node, TargetName, Oids) ->
%%======================================================================
+simple_async_get_next3(doc) ->
+ ["Simple (async) get_next-request - "
+ "Version 3 API (TargetName with send-opts)"];
+simple_async_get_next3(suite) -> [];
+simple_async_get_next3(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ put(tname, ssgn2),
+ p("starting with Config: ~p~n", [Config]),
+
+ MgrNode = ?config(manager_node, Config),
+ AgentNode = ?config(agent_node, Config),
+ TargetName = ?config(manager_agent_target_name, Config),
+
+ ?line ok = mgr_user_load_mib(MgrNode, std_mib()),
+ Test2Mib = test2_mib(Config),
+ ?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
+ ?line ok = agent_load_mib(AgentNode, Test2Mib),
+
+ Self = self(),
+ Msg = simple_async_get_next3,
+ Fun = fun() -> Self ! Msg end,
+ Extra = {?SNMPM_EXTRA_INFO_TAG, Fun},
+ SendOpts =
+ [
+ {extra, Extra}
+ ],
+
+ GetNext = fun(Oids) ->
+ async_gn_exec3(MgrNode, TargetName, Oids, SendOpts)
+ end,
+ PostVerify = fun(ok) -> receive Msg -> ok end;
+ (Error) -> Error
+ end,
+
+ do_simple_async_get_next2(MgrNode, AgentNode, GetNext, PostVerify).
+
+async_gn_exec3(Node, TargetName, Oids, SendOpts) ->
+ mgr_user_async_get_next2(Node, TargetName, Oids, SendOpts).
+
+
+%%======================================================================
+
simple_sync_set1(doc) -> ["Simple (sync) set-request - "
"Old style (Addr & Port)"];
simple_sync_set1(suite) -> [];
@@ -2088,14 +2514,25 @@ value_of_vavs([{_Oid, Val}|VAVs], Acc) ->
%%======================================================================
-simple_sync_set2(doc) -> ["Simple (sync) set-request - New style (TargetName)"];
+simple_sync_set2(doc) ->
+ ["Simple (sync) set-request - Version 2 API (TargetName)"];
simple_sync_set2(suite) -> [];
simple_sync_set2(Config) when is_list(Config) ->
process_flag(trap_exit, true),
put(tname, sss2),
p("starting with Config: ~p~n", [Config]),
- Node = ?config(manager_node, Config),
+ Set = fun(Node, TargetName, VAVs) ->
+ mgr_user_sync_set(Node, TargetName, VAVs)
+ end,
+ PostVerify = fun() -> ok end,
+
+ do_simple_sync_set2(Config, Set, PostVerify).
+
+do_simple_sync_set2(Config, Set, PostVerify)
+ when is_function(Set, 3) andalso is_function(PostVerify, 0) ->
+
+ Node = ?config(manager_node, Config),
TargetName = ?config(manager_agent_target_name, Config),
p("issue set-request without loading the mib"),
@@ -2105,7 +2542,7 @@ simple_sync_set2(Config) when is_list(Config) ->
{?sysName_instance, s, Val11},
{?sysLocation_instance, s, Val12}
],
- ?line ok = do_simple_set2(Node, TargetName, VAVs1),
+ ?line ok = do_simple_set2(Node, TargetName, VAVs1, Set, PostVerify),
p("issue set-request after first loading the mibs"),
?line ok = mgr_user_load_mib(Node, std_mib()),
@@ -2115,12 +2552,12 @@ simple_sync_set2(Config) when is_list(Config) ->
{[sysName, 0], Val21},
{[sysLocation, 0], Val22}
],
- ?line ok = do_simple_set2(Node, TargetName, VAVs2),
+ ?line ok = do_simple_set2(Node, TargetName, VAVs2, Set, PostVerify),
ok.
-do_simple_set2(Node, TargetName, VAVs) ->
+do_simple_set2(Node, TargetName, VAVs, Set, PostVerify) ->
[SysName, SysLoc] = value_of_vavs(VAVs),
- ?line {ok, Reply, Rem} = mgr_user_sync_set(Node, TargetName, VAVs),
+ ?line {ok, Reply, Rem} = Set(Node, TargetName, VAVs),
?DBG("~n Reply: ~p"
"~n Rem: ~w", [Reply, Rem]),
@@ -2133,7 +2570,7 @@ do_simple_set2(Node, TargetName, VAVs) ->
value = SysName},
#varbind{oid = ?sysLocation_instance,
value = SysLoc}]} ->
- ok;
+ PostVerify();
{noError, 0, Vbs} ->
{error, {unexpected_vbs, Vbs}};
Else ->
@@ -2145,6 +2582,33 @@ do_simple_set2(Node, TargetName, VAVs) ->
%%======================================================================
+simple_sync_set3(doc) ->
+ ["Simple (sync) set-request - Version 3 API (TargetName with send-opts)"];
+simple_sync_set3(suite) -> [];
+simple_sync_set3(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ put(tname, sss3),
+ p("starting with Config: ~p~n", [Config]),
+
+ Self = self(),
+ Msg = simple_sync_set3,
+ Fun = fun() -> Self ! Msg end,
+ Extra = {?SNMPM_EXTRA_INFO_TAG, Fun},
+ SendOpts =
+ [
+ {extra, Extra}
+ ],
+
+ Set = fun(Node, TargetName, VAVs) ->
+ mgr_user_sync_set2(Node, TargetName, VAVs, SendOpts)
+ end,
+ PostVerify = fun() -> receive Msg -> ok end end,
+
+ do_simple_sync_set2(Config, Set, PostVerify).
+
+
+%%======================================================================
+
simple_async_set1(doc) -> ["Simple (async) set-request - "
"Old style (Addr & Port)"];
simple_async_set1(suite) -> [];
@@ -2237,8 +2701,8 @@ sas_verify_vbs([Vb|_], [E|_]) ->
%%======================================================================
-simple_async_set2(doc) -> ["Simple (async) set-request - "
- "New style (TargetName)"];
+simple_async_set2(doc) ->
+ ["Simple (async) set-request - Version 2 API (TargetName)"];
simple_async_set2(suite) -> [];
simple_async_set2(Config) when is_list(Config) ->
process_flag(trap_exit, true),
@@ -2254,31 +2718,40 @@ simple_async_set2(Config) when is_list(Config) ->
?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
?line ok = agent_load_mib(AgentNode, Test2Mib),
- Exec = fun(X) ->
- async_s_exec2(MgrNode, TargetName, X)
- end,
+ Set =
+ fun(Oids) ->
+ async_s_exec2(MgrNode, TargetName, Oids)
+ end,
+ PostVerify = fun(Res) -> Res end,
+
+ do_simple_async_set2(MgrNode, AgentNode, Set, PostVerify).
+do_simple_async_set2(MgrNode, AgentNode, Set, PostVerify) ->
Requests =
[
{1,
[{?sysName_instance, s, "Arne Anka"}],
- Exec,
+ Set,
fun(X) ->
- sas_verify(X, [?sysName_instance])
+ PostVerify(sas_verify(X, [?sysName_instance]))
end},
{2,
[{?sysLocation_instance, s, "Stockholm"},
{?sysName_instance, s, "Arne Anka"}],
- Exec,
+ Set,
fun(X) ->
- sas_verify(X, [?sysLocation_instance, ?sysName_instance])
+ PostVerify(sas_verify(X,
+ [?sysLocation_instance,
+ ?sysName_instance]))
end},
{3,
[{[sysName, 0], "Gothenburg"},
{[sysLocation, 0], "Sune Anka"}],
- Exec,
+ Set,
fun(X) ->
- sas_verify(X, [?sysName_instance, ?sysLocation_instance])
+ PostVerify(sas_verify(X,
+ [?sysName_instance,
+ ?sysLocation_instance]))
end}
],
@@ -2299,6 +2772,48 @@ async_s_exec2(Node, TargetName, VAVs) ->
%%======================================================================
+simple_async_set3(doc) ->
+ ["Simple (async) set-request - Version 3 API (TargetName with send-opts)"];
+simple_async_set3(suite) -> [];
+simple_async_set3(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ put(tname, sas3),
+ p("starting with Config: ~p~n", [Config]),
+
+ MgrNode = ?config(manager_node, Config),
+ AgentNode = ?config(agent_node, Config),
+ TargetName = ?config(manager_agent_target_name, Config),
+
+ ?line ok = mgr_user_load_mib(MgrNode, std_mib()),
+ Test2Mib = test2_mib(Config),
+ ?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
+ ?line ok = agent_load_mib(AgentNode, Test2Mib),
+
+ Self = self(),
+ Msg = simple_async_set3,
+ Fun = fun() -> Self ! Msg end,
+ Extra = {?SNMPM_EXTRA_INFO_TAG, Fun},
+ SendOpts =
+ [
+ {extra, Extra}
+ ],
+
+ Set =
+ fun(Oids) ->
+ async_s_exec3(MgrNode, TargetName, Oids, SendOpts)
+ end,
+ PostVerify = fun(ok) -> receive Msg -> ok end;
+ (Res) -> Res
+ end,
+
+ do_simple_async_set2(MgrNode, AgentNode, Set, PostVerify).
+
+async_s_exec3(Node, TargetName, VAVs, SendOpts) ->
+ mgr_user_async_set2(Node, TargetName, VAVs, SendOpts).
+
+
+%%======================================================================
+
simple_sync_get_bulk1(doc) -> ["Simple (sync) get_bulk-request - "
"Old style (Addr & Port)"];
simple_sync_get_bulk1(suite) -> [];
@@ -2470,8 +2985,8 @@ check_ssgb_vbs([R|_], [E|_]) ->
%%======================================================================
-simple_sync_get_bulk2(doc) -> ["Simple (sync) get_bulk-request - "
- "New style (TargetName)"];
+simple_sync_get_bulk2(doc) ->
+ ["Simple (sync) get_bulk-request - Version 2 API (TargetName)"];
simple_sync_get_bulk2(suite) -> [];
simple_sync_get_bulk2(Config) when is_list(Config) ->
process_flag(trap_exit, true),
@@ -2482,20 +2997,33 @@ simple_sync_get_bulk2(Config) when is_list(Config) ->
AgentNode = ?config(agent_node, Config),
TargetName = ?config(manager_agent_target_name, Config),
+ GetBulk =
+ fun(NonRep, MaxRep, Oids) ->
+ mgr_user_sync_get_bulk(MgrNode, TargetName,
+ NonRep, MaxRep, Oids)
+ end,
+ PostVerify = fun(Res) -> Res end,
+
+ do_simple_sync_get_bulk2(Config, MgrNode, AgentNode, GetBulk, PostVerify).
+
+do_simple_sync_get_bulk2(Config, MgrNode, AgentNode, GetBulk, PostVerify) ->
%% -- 1 --
?line ok = do_simple_get_bulk2(1,
- MgrNode, TargetName, 1, 1, [],
- fun verify_ssgb_reply1/1),
+ 1, 1, [],
+ fun verify_ssgb_reply1/1,
+ GetBulk, PostVerify),
%% -- 2 --
?line ok = do_simple_get_bulk2(2,
- MgrNode, TargetName, -1, 1, [],
- fun verify_ssgb_reply1/1),
+ -1, 1, [],
+ fun verify_ssgb_reply1/1,
+ GetBulk, PostVerify),
%% -- 3 --
?line ok = do_simple_get_bulk2(3,
- MgrNode, TargetName, -1, -1, [],
- fun verify_ssgb_reply1/1),
+ -1, -1, [],
+ fun verify_ssgb_reply1/1,
+ GetBulk, PostVerify),
?line ok = mgr_user_load_mib(MgrNode, std_mib()),
%% -- 4 --
@@ -2503,13 +3031,13 @@ simple_sync_get_bulk2(Config) when is_list(Config) ->
verify_ssgb_reply2(X, [?sysDescr_instance, endOfMibView])
end,
?line ok = do_simple_get_bulk2(4,
- MgrNode, TargetName,
- 2, 0, [[sysDescr],[1,3,7,1]], VF04),
+ 2, 0, [[sysDescr],[1,3,7,1]], VF04,
+ GetBulk, PostVerify),
%% -- 5 --
?line ok = do_simple_get_bulk2(5,
- MgrNode, TargetName,
- 1, 2, [[sysDescr],[1,3,7,1]], VF04),
+ 1, 2, [[sysDescr],[1,3,7,1]], VF04,
+ GetBulk, PostVerify),
%% -- 6 --
VF06 = fun(X) ->
@@ -2518,8 +3046,8 @@ simple_sync_get_bulk2(Config) when is_list(Config) ->
?sysObjectID_instance, endOfMibView])
end,
?line ok = do_simple_get_bulk2(6,
- MgrNode, TargetName,
- 0, 2, [[sysDescr],[1,3,7,1]], VF06),
+ 0, 2, [[sysDescr],[1,3,7,1]], VF06,
+ GetBulk, PostVerify),
%% -- 7 --
VF07 = fun(X) ->
@@ -2529,10 +3057,10 @@ simple_sync_get_bulk2(Config) when is_list(Config) ->
?sysObjectID_instance, endOfMibView])
end,
?line ok = do_simple_get_bulk2(7,
- MgrNode, TargetName,
2, 2,
[[sysDescr],[1,3,7,1],[sysDescr],[1,3,7,1]],
- VF07),
+ VF07,
+ GetBulk, PostVerify),
Test2Mib = test2_mib(Config),
?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
@@ -2545,17 +3073,17 @@ simple_sync_get_bulk2(Config) when is_list(Config) ->
?sysDescr_instance])
end,
?line ok = do_simple_get_bulk2(8,
- MgrNode, TargetName,
1, 2,
[[sysDescr],[sysDescr],[tTooBig]],
- VF08),
+ VF08,
+ GetBulk, PostVerify),
%% -- 9 --
?line ok = do_simple_get_bulk2(9,
- MgrNode, TargetName,
1, 12,
[[tDescr2], [sysDescr]],
- fun verify_ssgb_reply1/1),
+ fun verify_ssgb_reply1/1,
+ GetBulk, PostVerify),
%% -- 10 --
VF10 = fun(X) ->
@@ -2566,13 +3094,13 @@ simple_sync_get_bulk2(Config) when is_list(Config) ->
{?sysDescr, 'NULL'}])
end,
?line ok = do_simple_get_bulk2(10,
- MgrNode, TargetName,
2, 2,
[[sysDescr],
[sysObjectID],
[tGenErr1],
[sysDescr]],
- VF10),
+ VF10,
+ GetBulk, PostVerify),
%% -- 11 --
?line {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2),
@@ -2583,20 +3111,25 @@ simple_sync_get_bulk2(Config) when is_list(Config) ->
{fl([TCnt2,2]), endOfMibView}])
end,
?line ok = do_simple_get_bulk2(11,
- MgrNode, TargetName,
0, 2,
- [[TCnt2, 1]], VF11),
+ [[TCnt2, 1]], VF11,
+ GetBulk, PostVerify),
ok.
-do_simple_get_bulk2(N, Node, TargetName, NonRep, MaxRep, Oids, Verify) ->
+do_simple_get_bulk2(N,
+ NonRep, MaxRep, Oids,
+ Verify, GetBulk, PostVerify)
+ when is_function(Verify, 1) andalso
+ is_function(GetBulk, 3) andalso
+ is_function(PostVerify) ->
p("issue get-bulk command ~w", [N]),
- case mgr_user_sync_get_bulk(Node, TargetName, NonRep, MaxRep, Oids) of
+ case GetBulk(NonRep, MaxRep, Oids) of
{ok, Reply, Rem} ->
?DBG("get-bulk ok:"
"~n Reply: ~p"
"~n Rem: ~w", [Reply, Rem]),
- Verify(Reply);
+ PostVerify(Verify(Reply));
Error ->
{error, {unexpected_reply, Error}}
@@ -2605,6 +3138,42 @@ do_simple_get_bulk2(N, Node, TargetName, NonRep, MaxRep, Oids, Verify) ->
%%======================================================================
+simple_sync_get_bulk3(doc) ->
+ ["Simple (sync) get_bulk-request - "
+ "Version 3 API (TargetName with send-opts)"];
+simple_sync_get_bulk3(suite) -> [];
+simple_sync_get_bulk3(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ put(tname, ssgb3),
+ p("starting with Config: ~p~n", [Config]),
+
+ MgrNode = ?config(manager_node, Config),
+ AgentNode = ?config(agent_node, Config),
+ TargetName = ?config(manager_agent_target_name, Config),
+
+ Self = self(),
+ Msg = simple_async_set3,
+ Fun = fun() -> Self ! Msg end,
+ Extra = {?SNMPM_EXTRA_INFO_TAG, Fun},
+ SendOpts =
+ [
+ {extra, Extra}
+ ],
+
+ GetBulk =
+ fun(NonRep, MaxRep, Oids) ->
+ mgr_user_sync_get_bulk2(MgrNode, TargetName,
+ NonRep, MaxRep, Oids, SendOpts)
+ end,
+ PostVerify = fun(ok) -> receive Msg -> ok end;
+ (Res) -> Res
+ end,
+
+ do_simple_sync_get_bulk2(Config, MgrNode, AgentNode, GetBulk, PostVerify).
+
+
+%%======================================================================
+
simple_async_get_bulk1(doc) -> ["Simple (async) get_bulk-request - "
"Old style (Addr & Port)"];
simple_async_get_bulk1(suite) -> [];
@@ -2748,8 +3317,8 @@ async_gb_exec1(Node, Addr, Port, {NR, MR, Oids}) ->
%%======================================================================
-simple_async_get_bulk2(doc) -> ["Simple (async) get_bulk-request - "
- "New style (TargetName)"];
+simple_async_get_bulk2(doc) ->
+ ["Simple (async) get_bulk-request - Version 2 API (TargetName)"];
simple_async_get_bulk2(suite) -> [];
simple_async_get_bulk2(Config) when is_list(Config) ->
process_flag(trap_exit, true),
@@ -2765,111 +3334,122 @@ simple_async_get_bulk2(Config) when is_list(Config) ->
?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
?line ok = agent_load_mib(AgentNode, Test2Mib),
- Exec = fun(Data) ->
- async_gb_exec2(MgrNode, TargetName, Data)
- end,
+ GetBulk =
+ fun(Data) ->
+ async_gb_exec2(MgrNode, TargetName, Data)
+ end,
+ PostVerify = fun(Res) -> Res end,
+
+ do_simple_async_get_bulk2(MgrNode, AgentNode, GetBulk, PostVerify).
+do_simple_async_get_bulk2(MgrNode, AgentNode, GetBulk, PostVerify) ->
%% We re-use the verification functions from the ssgb test-case
VF04 = fun(X) ->
- verify_ssgb_reply2(X, [?sysDescr_instance, endOfMibView])
+ PostVerify(
+ verify_ssgb_reply2(X, [?sysDescr_instance, endOfMibView]))
end,
VF06 = fun(X) ->
- verify_ssgb_reply2(X,
- [?sysDescr_instance, endOfMibView,
- ?sysObjectID_instance, endOfMibView])
+ PostVerify(
+ verify_ssgb_reply2(X,
+ [?sysDescr_instance, endOfMibView,
+ ?sysObjectID_instance, endOfMibView]))
end,
VF07 = fun(X) ->
- verify_ssgb_reply2(X,
- [?sysDescr_instance, endOfMibView,
- ?sysDescr_instance, endOfMibView,
- ?sysObjectID_instance, endOfMibView])
+ PostVerify(
+ verify_ssgb_reply2(X,
+ [?sysDescr_instance, endOfMibView,
+ ?sysDescr_instance, endOfMibView,
+ ?sysObjectID_instance, endOfMibView]))
end,
VF08 = fun(X) ->
- verify_ssgb_reply2(X,
- [?sysDescr_instance,
- ?sysDescr_instance])
+ PostVerify(
+ verify_ssgb_reply2(X,
+ [?sysDescr_instance,
+ ?sysDescr_instance]))
end,
VF10 = fun(X) ->
- verify_ssgb_reply3(X,
- [{?sysDescr, 'NULL'},
- {?sysObjectID, 'NULL'},
- {?tGenErr1, 'NULL'},
- {?sysDescr, 'NULL'}])
+ PostVerify(
+ verify_ssgb_reply3(X,
+ [{?sysDescr, 'NULL'},
+ {?sysObjectID, 'NULL'},
+ {?tGenErr1, 'NULL'},
+ {?sysDescr, 'NULL'}]))
end,
?line {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2),
VF11 = fun(X) ->
- verify_ssgb_reply2(X,
- [{fl([TCnt2,2]), 100},
- {fl([TCnt2,2]), endOfMibView}])
+ PostVerify(
+ verify_ssgb_reply2(X,
+ [{fl([TCnt2,2]), 100},
+ {fl([TCnt2,2]), endOfMibView}]))
end,
Requests = [
{ 1,
{1, 1, []},
- Exec,
- fun verify_ssgb_reply1/1},
+ GetBulk,
+ fun(X) -> PostVerify(verify_ssgb_reply1(X)) end},
{ 2,
{-1, 1, []},
- Exec,
- fun verify_ssgb_reply1/1},
+ GetBulk,
+ fun(X) -> PostVerify(verify_ssgb_reply1(X)) end},
{ 3,
{-1, -1, []},
- Exec,
- fun verify_ssgb_reply1/1},
+ GetBulk,
+ fun(X) -> PostVerify(verify_ssgb_reply1(X)) end},
{ 4,
{2, 0, [[sysDescr],[1,3,7,1]]},
- Exec,
+ GetBulk,
VF04},
{ 5,
{1, 2, [[sysDescr],[1,3,7,1]]},
- Exec,
+ GetBulk,
VF04},
{ 6,
{0, 2, [[sysDescr],[1,3,7,1]]},
- Exec,
+ GetBulk,
VF06},
{ 7,
{2, 2, [[sysDescr],[1,3,7,1],[sysDescr],[1,3,7,1]]},
- Exec,
+ GetBulk,
VF07},
{ 8,
{1, 2, [[sysDescr],[sysDescr],[tTooBig]]},
- Exec,
+ GetBulk,
VF08},
{ 9,
{1, 12, [[tDescr2], [sysDescr]]},
- Exec,
- fun verify_ssgb_reply1/1},
+ GetBulk,
+ fun(X) -> PostVerify(verify_ssgb_reply1(X)) end},
{10,
{2, 2, [[sysDescr],[sysObjectID], [tGenErr1],[sysDescr]]},
- Exec,
+ GetBulk,
VF10},
{11,
{0, 2, [[TCnt2, 1]]},
- Exec,
+ GetBulk,
VF11},
{12,
{2, 0, [[sysDescr],[1,3,7,1]]},
- Exec,
+ GetBulk,
VF04},
{13,
{1, 12, [[tDescr2], [sysDescr]]},
- Exec,
- fun verify_ssgb_reply1/1},
+ GetBulk,
+ fun(X) -> PostVerify(verify_ssgb_reply1(X)) end},
{14,
{2, 2, [[sysDescr],[sysObjectID],[tGenErr1],[sysDescr]]},
- Exec,
+ GetBulk,
VF10},
{15,
{0, 2, [[TCnt2, 1]]},
- Exec,
+ GetBulk,
VF11},
{16,
{2, 2, [[sysDescr],[1,3,7,1],[sysDescr],[1,3,7,1]]},
- Exec,
+ GetBulk,
VF07},
{17,
{2, 2, [[sysDescr],[sysObjectID], [tGenErr1],[sysDescr]]},
- Exec,
+ GetBulk,
VF10}
],
@@ -2890,6 +3470,49 @@ async_gb_exec2(Node, TargetName, {NR, MR, Oids}) ->
%%======================================================================
+simple_async_get_bulk3(doc) ->
+ ["Simple (async) get_bulk-request - "
+ "Version 3 API (TargetName with send-opts)"];
+simple_async_get_bulk3(suite) -> [];
+simple_async_get_bulk3(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ put(tname, sagb3),
+ p("starting with Config: ~p~n", [Config]),
+
+ MgrNode = ?config(manager_node, Config),
+ AgentNode = ?config(agent_node, Config),
+ TargetName = ?config(manager_agent_target_name, Config),
+
+ ?line ok = mgr_user_load_mib(MgrNode, std_mib()),
+ Test2Mib = test2_mib(Config),
+ ?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
+ ?line ok = agent_load_mib(AgentNode, Test2Mib),
+
+ Self = self(),
+ Msg = simple_async_get_bulk3,
+ Fun = fun() -> Self ! Msg end,
+ Extra = {?SNMPM_EXTRA_INFO_TAG, Fun},
+ SendOpts =
+ [
+ {extra, Extra}
+ ],
+
+ GetBulk =
+ fun(Data) ->
+ async_gb_exec3(MgrNode, TargetName, Data, SendOpts)
+ end,
+ PostVerify = fun(ok) -> receive Msg -> ok end;
+ (Res) -> Res
+ end,
+
+ do_simple_async_get_bulk2(MgrNode, AgentNode, GetBulk, PostVerify).
+
+async_gb_exec3(Node, TargetName, {NR, MR, Oids}, SendOpts) ->
+ mgr_user_async_get_bulk2(Node, TargetName, NR, MR, Oids, SendOpts).
+
+
+%%======================================================================
+
misc_async1(doc) -> ["Misc (async) request(s) - "
"Old style (Addr & Port)"];
misc_async1(suite) -> [];
@@ -3079,8 +3702,8 @@ misc_async1(Config) when is_list(Config) ->
%%======================================================================
-misc_async2(doc) -> ["Misc (async) request(s) - "
- "New style (TargetName)"];
+misc_async2(doc) ->
+ ["Misc (async) request(s) - Version 2 API (TargetName)"];
misc_async2(suite) -> [];
misc_async2(Config) when is_list(Config) ->
process_flag(trap_exit, true),
@@ -4440,7 +5063,7 @@ otp8395_1(suite) -> [];
otp8395_1(Config) when is_list(Config) ->
process_flag(trap_exit, true),
put(tname, otp8395_1),
- do_simple_get(Config).
+ do_simple_sync_get2(Config).
%%======================================================================
@@ -4986,6 +5609,9 @@ mgr_user_sync_get(Node, Addr_or_TargetName, Oids) ->
mgr_user_sync_get(Node, Addr, Port, Oids) ->
rcall(Node, snmp_manager_user, sync_get, [Addr, Port, Oids]).
+mgr_user_sync_get2(Node, TargetName, Oids, SendOpts) ->
+ rcall(Node, snmp_manager_user, sync_get2, [TargetName, Oids, SendOpts]).
+
%% mgr_user_async_get(Node, Oids) ->
%% mgr_user_async_get(Node, ?LOCALHOST(), ?AGENT_PORT, Oids).
mgr_user_async_get(Node, Addr_or_TargetName, Oids) ->
@@ -4993,6 +5619,9 @@ mgr_user_async_get(Node, Addr_or_TargetName, Oids) ->
mgr_user_async_get(Node, Addr, Port, Oids) ->
rcall(Node, snmp_manager_user, async_get, [Addr, Port, Oids]).
+mgr_user_async_get2(Node, TargetName, Oids, SendOpts) ->
+ rcall(Node, snmp_manager_user, async_get2, [TargetName, Oids, SendOpts]).
+
%% mgr_user_sync_get_next(Node, Oids) ->
%% mgr_user_sync_get_next(Node, ?LOCALHOST(), ?AGENT_PORT, Oids).
mgr_user_sync_get_next(Node, Addr_or_TargetName, Oids) ->
@@ -5000,6 +5629,9 @@ mgr_user_sync_get_next(Node, Addr_or_TargetName, Oids) ->
mgr_user_sync_get_next(Node, Addr, Port, Oids) ->
rcall(Node, snmp_manager_user, sync_get_next, [Addr, Port, Oids]).
+mgr_user_sync_get_next2(Node, TargetName, Oids, SendOpts) ->
+ rcall(Node, snmp_manager_user, sync_get_next2, [TargetName, Oids, SendOpts]).
+
%% mgr_user_async_get_next(Node, Oids) ->
%% mgr_user_async_get_next(Node, ?LOCALHOST(), ?AGENT_PORT, Oids).
mgr_user_async_get_next(Node, Addr_or_TargetName, Oids) ->
@@ -5007,6 +5639,9 @@ mgr_user_async_get_next(Node, Addr_or_TargetName, Oids) ->
mgr_user_async_get_next(Node, Addr, Port, Oids) ->
rcall(Node, snmp_manager_user, async_get_next, [Addr, Port, Oids]).
+mgr_user_async_get_next2(Node, TargetName, Oids, SendOpts) ->
+ rcall(Node, snmp_manager_user, async_get_next2, [TargetName, Oids, SendOpts]).
+
%% mgr_user_sync_set(Node, VAV) ->
%% mgr_user_sync_set(Node, ?LOCALHOST(), ?AGENT_PORT, VAV).
mgr_user_sync_set(Node, Addr_or_TargetName, VAV) ->
@@ -5014,6 +5649,9 @@ mgr_user_sync_set(Node, Addr_or_TargetName, VAV) ->
mgr_user_sync_set(Node, Addr, Port, VAV) ->
rcall(Node, snmp_manager_user, sync_set, [Addr, Port, VAV]).
+mgr_user_sync_set2(Node, TargetName, VAV, SendOpts) ->
+ rcall(Node, snmp_manager_user, sync_set2, [TargetName, VAV, SendOpts]).
+
%% mgr_user_async_set(Node, VAV) ->
%% mgr_user_async_set(Node, ?LOCALHOST(), ?AGENT_PORT, VAV).
mgr_user_async_set(Node, Addr_or_TargetName, VAV) ->
@@ -5021,26 +5659,37 @@ mgr_user_async_set(Node, Addr_or_TargetName, VAV) ->
mgr_user_async_set(Node, Addr, Port, VAV) ->
rcall(Node, snmp_manager_user, async_set, [Addr, Port, VAV]).
+mgr_user_async_set2(Node, TargetName, VAV, SendOpts) ->
+ rcall(Node, snmp_manager_user, async_set2, [TargetName, VAV, SendOpts]).
+
%% mgr_user_sync_get_bulk(Node, NonRep, MaxRep, Oids) ->
%% mgr_user_sync_get_bulk(Node, ?LOCALHOST(), ?AGENT_PORT,
%% NonRep, MaxRep, Oids).
mgr_user_sync_get_bulk(Node, Addr_or_TargetName, NonRep, MaxRep, Oids) ->
rcall(Node, snmp_manager_user, sync_get_bulk,
- [Addr_or_TargetName, NonRep, MaxRep, Oids]).
+ [Addr_or_TargetName, NonRep, MaxRep, Oids]).
mgr_user_sync_get_bulk(Node, Addr, Port, NonRep, MaxRep, Oids) ->
rcall(Node, snmp_manager_user, sync_get_bulk,
[Addr, Port, NonRep, MaxRep, Oids]).
+mgr_user_sync_get_bulk2(Node, TargetName, NonRep, MaxRep, Oids, SendOpts) ->
+ rcall(Node, snmp_manager_user, sync_get_bulk2,
+ [TargetName, NonRep, MaxRep, Oids, SendOpts]).
+
%% mgr_user_async_get_bulk(Node, NonRep, MaxRep, Oids) ->
%% mgr_user_async_get_bulk(Node, ?LOCALHOST(), ?AGENT_PORT,
%% NonRep, MaxRep, Oids).
mgr_user_async_get_bulk(Node, Addr_or_TargetName, NonRep, MaxRep, Oids) ->
rcall(Node, snmp_manager_user, async_get_bulk,
- [Addr_or_TargetName, NonRep, MaxRep, Oids]).
+ [Addr_or_TargetName, NonRep, MaxRep, Oids]).
mgr_user_async_get_bulk(Node, Addr, Port, NonRep, MaxRep, Oids) ->
rcall(Node, snmp_manager_user, async_get_bulk,
[Addr, Port, NonRep, MaxRep, Oids]).
+mgr_user_async_get_bulk2(Node, TargetName, NonRep, MaxRep, Oids, SendOpts) ->
+ rcall(Node, snmp_manager_user, async_get_bulk2,
+ [TargetName, NonRep, MaxRep, Oids, SendOpts]).
+
mgr_user_purify_oid(Node, Oid) ->
rcall(Node, snmp_manager_user, purify_oid, [Oid]).
diff --git a/lib/snmp/test/snmp_manager_user.erl b/lib/snmp/test/snmp_manager_user.erl
index b0e192344d..1b62b04960 100644
--- a/lib/snmp/test/snmp_manager_user.erl
+++ b/lib/snmp/test/snmp_manager_user.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The 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,14 +50,14 @@
update_agent_info/3, update_agent_info/4,
which_all_agents/0, which_own_agents/0,
load_mib/1, unload_mib/1,
- sync_get/1, sync_get/2, sync_get/3,
- async_get/1, async_get/2, async_get/3,
- sync_get_next/1, sync_get_next/2, sync_get_next/3,
- async_get_next/1, async_get_next/2, async_get_next/3,
- sync_set/1, sync_set/2, sync_set/3,
- async_set/1, async_set/2, async_set/3,
- sync_get_bulk/3, sync_get_bulk/4, sync_get_bulk/5,
- async_get_bulk/3, async_get_bulk/4, async_get_bulk/5,
+ sync_get/1, sync_get/2, sync_get/3, sync_get2/3,
+ async_get/1, async_get/2, async_get/3, async_get2/3,
+ sync_get_next/1, sync_get_next/2, sync_get_next/3, sync_get_next2/3,
+ async_get_next/1, async_get_next/2, async_get_next/3, async_get_next2/3,
+ sync_set/1, sync_set/2, sync_set/3, sync_set2/3,
+ async_set/1, async_set/2, async_set/3, async_set2/3,
+ sync_get_bulk/3, sync_get_bulk/4, sync_get_bulk/5, sync_get_bulk2/5,
+ async_get_bulk/3, async_get_bulk/4, async_get_bulk/5, async_get_bulk2/5,
name_to_oid/1, oid_to_name/1,
purify_oid/1
]).
@@ -171,6 +171,10 @@ sync_get(Addr_or_TargetName, Oids) ->
sync_get(Addr, Port, Oids) ->
call({sync_get, Addr, Port, Oids}).
+sync_get2(TargetName, Oids, SendOpts) ->
+ call({sync_get2, TargetName, Oids, SendOpts}).
+
+
%% --
async_get(Oids) ->
@@ -182,6 +186,9 @@ async_get(Addr_or_TargetName, Oids) ->
async_get(Addr, Port, Oids) ->
call({async_get, Addr, Port, Oids}).
+async_get2(TargetName, Oids, SendOpts) ->
+ call({async_get2, TargetName, Oids, SendOpts}).
+
%% --
sync_get_next(Oids) ->
@@ -193,6 +200,9 @@ sync_get_next(Addr_or_TargetName, Oids) ->
sync_get_next(Addr, Port, Oids) ->
call({sync_get_next, Addr, Port, Oids}).
+sync_get_next2(TargetName, Oids, SendOpts) ->
+ call({sync_get_next2, TargetName, Oids, SendOpts}).
+
%% --
async_get_next(Oids) ->
@@ -204,6 +214,9 @@ async_get_next(Addr_or_TargetName, Oids) ->
async_get_next(Addr, Port, Oids) ->
call({async_get_next, Addr, Port, Oids}).
+async_get_next2(TargetName, Oids, SendOpts) ->
+ call({async_get_next2, TargetName, Oids, SendOpts}).
+
%% --
sync_set(VAV) ->
@@ -215,6 +228,9 @@ sync_set(Addr_or_TargetName, VAV) ->
sync_set(Addr, Port, VAV) ->
call({sync_set, Addr, Port, VAV}).
+sync_set2(TargetName, VAV, SendOpts) ->
+ call({sync_set2, TargetName, VAV, SendOpts}).
+
%% --
async_set(VAV) ->
@@ -226,6 +242,9 @@ async_set(Addr_or_TargetName, VAV) ->
async_set(Addr, Port, VAV) ->
call({async_set, Addr, Port, VAV}).
+async_set2(TargetName, VAV, SendOpts) ->
+ call({async_set2, TargetName, VAV, SendOpts}).
+
%% --
sync_get_bulk(NonRep, MaxRep, Oids) ->
@@ -237,6 +256,9 @@ sync_get_bulk(Addr_or_TargetName, NonRep, MaxRep, Oids) ->
sync_get_bulk(Addr, Port, NonRep, MaxRep, Oids) ->
call({sync_get_bulk, Addr, Port, NonRep, MaxRep, Oids}).
+sync_get_bulk2(TargetName, NonRep, MaxRep, Oids, SendOpts) ->
+ call({sync_get_bulk2, TargetName, NonRep, MaxRep, Oids, SendOpts}).
+
%% --
async_get_bulk(NonRep, MaxRep, Oids) ->
@@ -248,6 +270,9 @@ async_get_bulk(Addr_or_TargetName, NonRep, MaxRep, Oids) ->
async_get_bulk(Addr, Port, NonRep, MaxRep, Oids) ->
call({async_get_bulk, Addr, Port, NonRep, MaxRep, Oids}).
+async_get_bulk2(TargetName, NonRep, MaxRep, Oids, SendOpts) ->
+ call({async_get_bulk2, TargetName, NonRep, MaxRep, Oids, SendOpts}).
+
%% --
name_to_oid(Name) ->
@@ -400,6 +425,16 @@ loop(#state{parent = Parent, id = Id} = S) ->
%% -- (sync) get-request --
%%
+ {{sync_get2, TargetName, Oids, SendOpts}, From, Ref}
+ when is_list(TargetName) ->
+ d("loop -> received sync_get2 request with"
+ "~n TargetName: ~p"
+ "~n Oids: ~p"
+ "~n SendOpts: ~p", [TargetName, Oids, SendOpts]),
+ Res = snmpm:sync_get2(Id, TargetName, Oids, SendOpts),
+ reply(From, Res, Ref),
+ loop(S);
+
%% No agent specified, so send it to all of them
{{sync_get, Oids}, From, Ref} ->
d("loop -> received sync_get request "
@@ -439,6 +474,16 @@ loop(#state{parent = Parent, id = Id} = S) ->
%% -- (async) get-request --
%%
+ {{async_get2, TargetName, Oids, SendOpts}, From, Ref}
+ when is_list(TargetName) ->
+ d("loop -> received async_get2 request with"
+ "~n TargetName: ~p"
+ "~n Oids: ~p"
+ "~n SendOpts: ~p", [TargetName, Oids, SendOpts]),
+ Res = snmpm:async_get2(Id, TargetName, Oids, SendOpts),
+ reply(From, Res, Ref),
+ loop(S);
+
%% No agent specified, so send it to all of them
{{async_get, Oids}, From, Ref} ->
d("loop -> received async_get request"),
@@ -472,6 +517,16 @@ loop(#state{parent = Parent, id = Id} = S) ->
%% -- (sync) get_next-request --
%%
+ {{sync_get_next2, TargetName, Oids, SendOpts}, From, Ref}
+ when is_list(TargetName) ->
+ d("loop -> received sync_get_next2 request with"
+ "~n TargetName: ~p"
+ "~n Oids: ~p"
+ "~n SendOpts: ~p", [TargetName, Oids, SendOpts]),
+ Res = snmpm:sync_get_next2(Id, TargetName, Oids, SendOpts),
+ reply(From, Res, Ref),
+ loop(S);
+
%% No agent specified, so send it to all of them
{{sync_get_next, Oids}, From, Ref} ->
d("loop -> received sync_get_next request"),
@@ -505,6 +560,16 @@ loop(#state{parent = Parent, id = Id} = S) ->
%% -- (async) get_next-request --
%%
+ {{async_get_next2, TargetName, Oids, SendOpts}, From, Ref}
+ when is_list(TargetName) ->
+ d("loop -> received async_get_next2 request with"
+ "~n TargetName: ~p"
+ "~n Oids: ~p"
+ "~n SendOpts: ~p", [TargetName, Oids, SendOpts]),
+ Res = snmpm:async_get_next2(Id, TargetName, Oids, SendOpts),
+ reply(From, Res, Ref),
+ loop(S);
+
%% No agent specified, so send it to all of them
{{async_get_next, Oids}, From, Ref} ->
d("loop -> received async_get_next request"),
@@ -538,6 +603,16 @@ loop(#state{parent = Parent, id = Id} = S) ->
%% -- (sync) set-request --
%%
+ {{sync_set2, TargetName, VAV, SendOpts}, From, Ref}
+ when is_list(TargetName) ->
+ d("loop -> received sync_set2 request with"
+ "~n TargetName: ~p"
+ "~n VAV: ~p"
+ "~n SendOpts: ~p", [TargetName, VAV, SendOpts]),
+ Res = snmpm:sync_set2(Id, TargetName, VAV, SendOpts),
+ reply(From, Res, Ref),
+ loop(S);
+
{{sync_set, VAV}, From, Ref} ->
d("loop -> received sync_set request"),
Res = [snmpm:sync_set(Id, TargetName, VAV) ||
@@ -568,6 +643,16 @@ loop(#state{parent = Parent, id = Id} = S) ->
%% -- (async) set-request --
%%
+ {{async_set2, TargetName, VAV, SendOpts}, From, Ref}
+ when is_list(TargetName) ->
+ d("loop -> received async_set2 request with"
+ "~n TargetName: ~p"
+ "~n VAV: ~p"
+ "~n SendOpts: ~p", [TargetName, VAV, SendOpts]),
+ Res = snmpm:async_set2(Id, TargetName, VAV, SendOpts),
+ reply(From, Res, Ref),
+ loop(S);
+
{{async_set, VAV}, From, Ref} ->
d("loop -> received async_set request"),
Res = [snmpm:async_set(Id, TargetName, VAV) ||
@@ -598,6 +683,20 @@ loop(#state{parent = Parent, id = Id} = S) ->
%% -- (sync) get-bulk-request --
%%
+ {{sync_get_bulk2, TargetName, NonRep, MaxRep, Oids, SendOpts}, From, Ref}
+ when is_list(TargetName) ->
+ d("loop -> received sync_get_bulk request with"
+ "~n TargetName: ~p"
+ "~n NonRep: ~w"
+ "~n MaxRep: ~w"
+ "~n Oids: ~p"
+ "~n SendOpts: ~p",
+ [TargetName, NonRep, MaxRep, Oids, SendOpts]),
+ Res = snmpm:sync_get_bulk2(Id, TargetName,
+ NonRep, MaxRep, Oids, SendOpts),
+ reply(From, Res, Ref),
+ loop(S);
+
%% No agent specified, so send it to all of them
{{sync_get_bulk, NonRep, MaxRep, Oids}, From, Ref} ->
d("loop -> received sync_get_bulk request with"
@@ -645,6 +744,20 @@ loop(#state{parent = Parent, id = Id} = S) ->
%% -- (async) get-bulk-request --
%%
+ {{async_get_bulk2, TargetName, NonRep, MaxRep, Oids, SendOpts},
+ From, Ref} when is_list(TargetName) ->
+ d("loop -> received async_get_bulk2 request with"
+ "~n TargetName: ~p"
+ "~n NonRep: ~w"
+ "~n MaxRep: ~w"
+ "~n Oids: ~p"
+ "~n SendOpts: ~p",
+ [TargetName, NonRep, MaxRep, Oids, SendOpts]),
+ Res = snmpm:async_get_bulk2(Id, TargetName,
+ NonRep, MaxRep, Oids, SendOpts),
+ reply(From, Res, Ref),
+ loop(S);
+
%% No agent specified, so send it to all of them
{{async_get_bulk, NonRep, MaxRep, Oids}, From, Ref} ->
d("loop -> received async_get_bulk request with"
@@ -847,7 +960,11 @@ call(Req, To) when is_integer(To) ->
{error, timeout}
end.
-reply(Pid, Reply, Ref) ->
+reply(Pid, Reply, Ref) ->
+ d("reply -> entry with"
+ "~n Pid: ~p"
+ "~n Reply: ~p"
+ "~n Ref: ~p", [Pid, Reply, Ref]),
Pid ! {Reply, Ref}.
cast(Msg) ->
diff --git a/lib/snmp/test/snmp_pdus_test.erl b/lib/snmp/test/snmp_pdus_test.erl
index ef510ad62e..07b6d6b657 100644
--- a/lib/snmp/test/snmp_pdus_test.erl
+++ b/lib/snmp/test/snmp_pdus_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
%%
%% The 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 @@
otp7575/1,
otp8563/1,
+ otp9022/1,
+
init_per_testcase/2, end_per_testcase/2
]).
@@ -75,7 +77,7 @@ all() ->
[{group, tickets}].
groups() ->
- [{tickets, [], [otp7575, otp8563]}].
+ [{tickets, [], [otp7575, otp8563, otp9022]}].
init_per_group(_GroupName, Config) ->
Config.
@@ -169,7 +171,56 @@ otp8563(Config) when is_list(Config) ->
Unexpected7 ->
exit({unexpected_encode_result, Unexpected7, Val7})
end,
-
+
+ ok.
+
+
+otp9022(suite) -> [];
+otp9022(doc) -> ["OTP-9022"];
+otp9022(Config) when is_list(Config) ->
+ Val1 = 16#7fffffff,
+ io:format("try encode and decode ~w~n", [Val1]),
+ Enc1 = snmp_pdus:enc_value('Counter32', Val1),
+ {{'Counter32', Val1}, []} = snmp_pdus:dec_value(Enc1),
+
+ Val2 = Val1 + 1,
+ io:format("try encode and decode ~w~n", [Val2]),
+ Enc2 = snmp_pdus:enc_value('Counter32', Val2),
+ {{'Counter32', Val2}, []} = snmp_pdus:dec_value(Enc2),
+
+ Val3 = Val2 + 1,
+ io:format("try encode and decode ~w~n", [Val3]),
+ Enc3 = snmp_pdus:enc_value('Counter32', Val3),
+ {{'Counter32', Val3}, []} = snmp_pdus:dec_value(Enc3),
+
+ Val4 = 16#fffffffe,
+ io:format("try encode and decode ~w~n", [Val4]),
+ Enc4 = snmp_pdus:enc_value('Counter32', Val4),
+ {{'Counter32', Val4}, []} = snmp_pdus:dec_value(Enc4),
+
+ Val5 = Val4 + 1,
+ io:format("try encode and decode ~w~n", [Val5]),
+ Enc5 = snmp_pdus:enc_value('Counter32', Val5),
+ {{'Counter32', Val5}, []} = snmp_pdus:dec_value(Enc5),
+
+ Val6 = 16#ffffffff + 1,
+ io:format("try and fail to encode ~w~n", [Val6]),
+ case (catch snmp_pdus:enc_value('Counter32', Val6)) of
+ {'EXIT', {error, {bad_counter32, Val6}}} ->
+ ok;
+ Unexpected6 ->
+ exit({unexpected_encode_result, Unexpected6, Val6})
+ end,
+
+ Val7 = -1,
+ io:format("try and fail to encode ~w~n", [Val7]),
+ case (catch snmp_pdus:enc_value('Counter32', Val7)) of
+ {'EXIT', {error, {bad_counter32, Val7}}} ->
+ ok;
+ Unexpected7 ->
+ exit({unexpected_encode_result, Unexpected7, Val7})
+ end,
+
ok.
diff --git a/lib/snmp/test/test_config/Makefile b/lib/snmp/test/test_config/Makefile
index d7bebbc431..d65bb8abe2 100644
--- a/lib/snmp/test/test_config/Makefile
+++ b/lib/snmp/test/test_config/Makefile
@@ -155,23 +155,23 @@ release_spec:
release_tests_spec: clean opt
$(INSTALL_DIR) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
$(INSTALL_DIR) $(RELSYSDIR)/agent
- chmod -f -R u+w $(RELSYSDIR)/agent
+ chmod -R u+w $(RELSYSDIR)/agent
$(INSTALL_DIR) $(RELSYSDIR)/agent/conf
- chmod -f -R u+w $(RELSYSDIR)/agent/conf
+ chmod -R u+w $(RELSYSDIR)/agent/conf
$(INSTALL_DIR) $(RELSYSDIR)/agent/db
- chmod -f -R u+w $(RELSYSDIR)/agent/db
+ chmod -R u+w $(RELSYSDIR)/agent/db
$(INSTALL_DIR) $(RELSYSDIR)/agent/log
- chmod -f -R u+w $(RELSYSDIR)/agent/log
+ chmod -R u+w $(RELSYSDIR)/agent/log
$(INSTALL_DIR) $(RELSYSDIR)/manager
- chmod -f -R u+w $(RELSYSDIR)/manager
+ chmod -R u+w $(RELSYSDIR)/manager
$(INSTALL_DIR) $(RELSYSDIR)/manager/conf
- chmod -f -R u+w $(RELSYSDIR)/manager/conf
+ chmod -R u+w $(RELSYSDIR)/manager/conf
$(INSTALL_DIR) $(RELSYSDIR)/manager/db
- chmod -f -R u+w $(RELSYSDIR)/manager/db
+ chmod -R u+w $(RELSYSDIR)/manager/db
$(INSTALL_DIR) $(RELSYSDIR)/manager/log
- chmod -f -R u+w $(RELSYSDIR)/manager/log
+ chmod -R u+w $(RELSYSDIR)/manager/log
$(INSTALL_DATA) $(SYS_CONFIG_FILES) $(RELSYSDIR)
$(INSTALL_DATA) $(AGENT_CONFIG_FILES) $(RELSYSDIR)/agent/conf
$(INSTALL_DATA) $(MANAGER_CONFIG_FILES) $(RELSYSDIR)/manager/conf
diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk
index e70c97dcb8..c95e0a22d1 100644
--- a/lib/snmp/vsn.mk
+++ b/lib/snmp/vsn.mk
@@ -17,6 +17,6 @@
#
# %CopyrightEnd%
-SNMP_VSN = 4.19
+SNMP_VSN = 4.21.1
PRE_VSN =
APP_VSN = "snmp-$(SNMP_VSN)$(PRE_VSN)"
diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml
index af667b1a71..6fc4fdc43d 100644
--- a/lib/ssh/doc/src/notes.xml
+++ b/lib/ssh/doc/src/notes.xml
@@ -29,6 +29,61 @@
<file>notes.xml</file>
</header>
+<section><title>Ssh 2.0.8</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Calling ssh_sftp:stop_channel/1 resulted in that the trap_exit flag was
+ set to true for the invoking process.</p>
+ <p>
+ Own Id: OTP-9386 Aux Id: seq11865</p>
+ </item>
+ </list>
+ </section>
+</section>
+
+<section><title>Ssh 2.0.7</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ An unexpected message would crash the ssh_connection_handler and close
+ the connection. Now an error message is generated instead.</p>
+ <p>
+ Own Id: OTP-9273</p>
+ </item>
+ </list>
+ </section>
+</section>
+
+<section><title>Ssh 2.0.6</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A memory leak has been fixed. I.e. per terminated connection the size of
+ a pid and the length of a user name string was not cleared.</p>
+ <p>
+ Own Id: OTP-9232</p>
+ </item>
+ </list>
+ </section>
+</section>
+
+<section><title>Ssh 2.0.5</title>
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Strengthened random number generation. (Thanks to Geoff Cant)</p>
+ <p>
+ Own Id: OTP-9225</p>
+ </item>
+ </list>
+ </section>
+</section>
+
<section><title>Ssh 2.0.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile
index 42880fa80b..e7cf2c6723 100644
--- a/lib/ssh/src/Makefile
+++ b/lib/ssh/src/Makefile
@@ -127,13 +127,10 @@ $(APP_TARGET): $(APP_SRC) ../vsn.mk
$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
sed -e 's;%VSN%;$(VSN);' $< > $@
-%.hrl: %.asn1
- erlc $(ASN_FLAGS) $<
+%.erl %.hrl: %.asn1
+ $(ERLC) $(ASN_FLAGS) $<
-DSS.hrl DSS.erl: DSS.asn1
-PKCS-1.hrl PKCS-1.erl: PKCS-1.asn1
-
-$(EBIN)/ssh_file.$(EMULATOR): $(ASN_HRLS)
+$(EBIN)/ssh_file.$(EMULATOR) $(EBIN)/ssh_rsa.$(EMULATOR): $(ASN_HRLS)
docs:
diff --git a/lib/ssh/src/ssh.appup.src b/lib/ssh/src/ssh.appup.src
index 501da8ceb9..150b7d86dd 100644
--- a/lib/ssh/src/ssh.appup.src
+++ b/lib/ssh/src/ssh.appup.src
@@ -19,34 +19,20 @@
{"%VSN%",
[
- {"2.0.3", [{load_module, ssh_file, soft_purge, soft_purge, []},
- {load_module, ssh, soft_purge, soft_purge, []},
- {load_module, ssh_rsa, soft_purge, soft_purge, []},
- {load_module, ssh_acceptor, soft_purge, soft_purge, []},
- {load_module, ssh_transport, soft_purge, soft_purge, []},
- {load_module, ssh_connection_manager, soft_purge, soft_purge, []}]},
- {"2.0.2", [{load_module, ssh_file, soft_purge, soft_purge, []},
- {load_module, ssh, soft_purge, soft_purge, []},
- {load_module, ssh_rsa, soft_purge, soft_purge, []},
- {load_module, ssh_acceptor, soft_purge, soft_purge, []},
- {load_module, ssh_transport, soft_purge, soft_purge, []},
- {load_module, ssh_connection_manager, soft_purge, soft_purge, []}]},
- {"2.0.1", [{restart_application, ssh}]}
+ {"2.0.7", [{load_module, ssh_sftp, soft_purge, soft_purge, []}]},
+ {"2.0.6", [{load_module, ssh_userreg, soft_purge, soft_purge, []},
+ {load_module, ssh_sftp, soft_purge, soft_purge, []}]},
+ {"2.0.5", [{load_module, ssh_userreg, soft_purge, soft_purge, []},
+ {load_module, ssh_sftp, soft_purge, soft_purge, []},
+ {load_module, ssh_connection_handler, soft_purge, soft_purge, [ssh_userreg]}]}
],
[
- {"2.0.3", [{load_module, ssh_file, soft_purge, soft_purge, []},
- {load_module, ssh, soft_purge, soft_purge, []},
- {load_module, ssh_rsa, soft_purge, soft_purge, []},
- {load_module, ssh_acceptor, soft_purge, soft_purge, []},
- {load_module, ssh_transport, soft_purge, soft_purge, []},
- {load_module, ssh_connection_manager, soft_purge, soft_purge, []}]},
- {"2.0.2", [{load_module, ssh_file, soft_purge, soft_purge, []},
- {load_module, ssh, soft_purge, soft_purge, []},
- {load_module, ssh_rsa, soft_purge, soft_purge, []},
- {load_module, ssh_acceptor, soft_purge, soft_purge, []},
- {load_module, ssh_transport, soft_purge, soft_purge, []},
- {load_module, ssh_connection_manager, soft_purge, soft_purge, []}]},
- {"2.0.1", [{restart_application, ssh}]}
+ {"2.0.7", [{load_module, ssh_sftp, soft_purge, soft_purge, []}]},
+ {"2.0.6", [{load_module, ssh_userreg, soft_purge, soft_purge, []},
+ {load_module, ssh_sftp, soft_purge, soft_purge, []}]},
+ {"2.0.5", [{load_module, ssh_userreg, soft_purge, soft_purge, []},
+ {load_module, ssh_sftp, soft_purge, soft_purge, []},
+ {load_module, ssh_connection_handler, soft_purge, soft_purge, [ssh_userreg]}]}
]
}.
diff --git a/lib/ssh/src/ssh_bits.erl b/lib/ssh/src/ssh_bits.erl
index 399581a0fd..3f0a06575c 100755
--- a/lib/ssh/src/ssh_bits.erl
+++ b/lib/ssh/src/ssh_bits.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The 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 @@
%% integer utils
-export([isize/1]).
-export([irandom/1, irandom/3]).
--export([random/1, random/3]).
+-export([random/1]).
-export([xor_bits/2, fill_bits/2]).
-export([i2bin/2, bin2i/1]).
@@ -401,9 +401,6 @@ xor_bits(XBits, YBits) ->
irandom(Bits) ->
irandom(Bits, 1, 0).
-%% irandom_odd(Bits) ->
-%% irandom(Bits, 1, 1).
-
%%
%% irandom(N, Top, Bottom)
%%
@@ -414,57 +411,16 @@ irandom(Bits) ->
%% Bot = 0 - do not set the least signifcant bit
%% Bot = 1 - set the least signifcant bit (i.e always odd)
%%
-irandom(0, _Top, _Bottom) ->
- 0;
-irandom(Bits, Top, Bottom) ->
- Bytes = (Bits+7) div 8,
- Skip = (8-(Bits rem 8)) rem 8,
- TMask = case Top of
- 0 -> 0;
- 1 -> 16#80;
- 2 -> 16#c0
- end,
- BMask = case Bottom of
- 0 -> 0;
- 1 -> (1 bsl Skip)
- end,
- <<X:Bits/big-unsigned-integer, _:Skip>> = random(Bytes, TMask, BMask),
- X.
+irandom(Bits, Top, Bottom) when is_integer(Top),
+ 0 =< Top, Top =< 2 ->
+ crypto:erlint(crypto:strong_rand_mpint(Bits, Top - 1, Bottom)).
%%
%% random/1
%% Generate N random bytes
%%
random(N) ->
- random(N, 0, 0).
-
-random(N, TMask, BMask) ->
- list_to_binary(rnd(N, TMask, BMask)).
-
-%% random/3
-%% random(Bytes, TopMask, BotMask)
-%% where
-%% Bytes is the number of bytes to generate
-%% TopMask is bitwised or'ed to the first byte
-%% BotMask is bitwised or'ed to the last byte
-%%
-rnd(0, _TMask, _BMask) ->
- [];
-rnd(1, TMask, BMask) ->
- [(rand8() bor TMask) bor BMask];
-rnd(N, TMask, BMask) ->
- [(rand8() bor TMask) | rnd_n(N-1, BMask)].
-
-rnd_n(1, BMask) ->
- [rand8() bor BMask];
-rnd_n(I, BMask) ->
- [rand8() | rnd_n(I-1, BMask)].
-
-rand8() ->
- (rand32() bsr 8) band 16#ff.
-
-rand32() ->
- random:uniform(16#100000000) -1.
+ crypto:strong_rand_bytes(N).
%%
%% Base 64 encode/decode
diff --git a/lib/ssh/src/ssh_cli.erl b/lib/ssh/src/ssh_cli.erl
index cb78acb84c..781e01b9d1 100644
--- a/lib/ssh/src/ssh_cli.erl
+++ b/lib/ssh/src/ssh_cli.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index 0ba11b0a26..00b30e5434 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -106,8 +106,6 @@ peer_address(ConnectionHandler) ->
%% initialize.
%%--------------------------------------------------------------------
init([Role, Manager, Socket, SshOpts]) ->
- {A,B,C} = erlang:now(),
- random:seed(A, B, C),
{NumVsn, StrVsn} = ssh_transport:versions(Role, SshOpts),
ssh_bits:install_messages(ssh_transport:transport_messages(NumVsn)),
{Protocol, Callback, CloseTag} =
@@ -571,7 +569,19 @@ handle_info({CloseTag, _Socket}, _StateName,
#state{transport_close_tag = CloseTag, %%manager = Pid,
ssh_params = #ssh{role = _Role, opts = _Opts}} = State) ->
%%ok = ssh_connection_manager:delivered(Pid),
- {stop, normal, State}.
+ {stop, normal, State};
+handle_info(UnexpectedMessage, StateName, #state{ssh_params = SshParams} = State) ->
+ Msg = lists:flatten(io_lib:format(
+ "Unexpected message '~p' received in state '~p'\n"
+ "Role: ~p\n"
+ "Peer: ~p\n"
+ "Local Address: ~p\n", [UnexpectedMessage, StateName,
+ SshParams#ssh.role, SshParams#ssh.peer,
+ proplists:get_value(address, SshParams#ssh.opts)])),
+ error_logger:info_report(Msg),
+ {next_state, StateName, State}.
+
+
%%--------------------------------------------------------------------
%% Function: terminate(Reason, StateName, State) -> void()
%% Description:This function is called by a gen_fsm when it is about
@@ -580,7 +590,9 @@ handle_info({CloseTag, _Socket}, _StateName,
%% Reason. The return value is ignored.
%%--------------------------------------------------------------------
terminate(normal, _, #state{transport_cb = Transport,
- socket = Socket}) ->
+ socket = Socket,
+ manager = Pid}) ->
+ (catch ssh_userreg:delete_user(Pid)),
(catch Transport:close(Socket)),
ok;
@@ -812,7 +824,7 @@ handle_disconnect(#ssh_msg_disconnect{} = Msg,
#state{ssh_params = Ssh0, manager = Pid} = State) ->
{SshPacket, Ssh} = ssh_transport:ssh_packet(Msg, Ssh0),
try
- send_msg(SshPacket, State),
+ send_msg(SshPacket, State),
ssh_connection_manager:event(Pid, Msg)
catch
exit:{noproc, _Reason} ->
@@ -824,6 +836,7 @@ handle_disconnect(#ssh_msg_disconnect{} = Msg,
[Msg, Exit]),
error_logger:info_report(Report)
end,
+ (catch ssh_userreg:delete_user(Pid)),
{stop, normal, State#state{ssh_params = Ssh}}.
counterpart_versions(NumVsn, StrVsn, #ssh{role = server} = Ssh) ->
diff --git a/lib/ssh/src/ssh_sftp.erl b/lib/ssh/src/ssh_sftp.erl
index 59e09fdd0f..f000558100 100755
--- a/lib/ssh/src/ssh_sftp.erl
+++ b/lib/ssh/src/ssh_sftp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -130,9 +130,9 @@ start_channel(Host, Port, Opts) ->
end.
stop_channel(Pid) ->
- case process_info(Pid, [trap_exit]) of
- [{trap_exit, Bool}] ->
- process_flag(trap_exit, true),
+ case is_process_alive(Pid) of
+ true ->
+ OldValue = process_flag(trap_exit, true),
link(Pid),
exit(Pid, ssh_sftp_stop_channel),
receive
@@ -145,9 +145,9 @@ stop_channel(Pid) ->
ok
end
end,
- process_flag(trap_exit, Bool),
+ process_flag(trap_exit, OldValue),
ok;
- undefined ->
+ false ->
ok
end.
diff --git a/lib/ssh/src/ssh_userreg.erl b/lib/ssh/src/ssh_userreg.erl
index 33c801f490..f901461aea 100644
--- a/lib/ssh/src/ssh_userreg.erl
+++ b/lib/ssh/src/ssh_userreg.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The 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,11 +25,18 @@
-behaviour(gen_server).
%% API
--export([start_link/0, register_user/2, lookup_user/1]).
+-export([start_link/0,
+ register_user/2,
+ lookup_user/1,
+ delete_user/1]).
%% gen_server callbacks
--export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- terminate/2, code_change/3]).
+-export([init/1,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ terminate/2,
+ code_change/3]).
-record(state, {user_db = []}).
@@ -46,6 +53,9 @@ start_link() ->
register_user(User, Cm) ->
gen_server:cast(?MODULE, {register, {User, Cm}}).
+delete_user(Cm) ->
+ gen_server:cast(?MODULE, {delete, Cm}).
+
lookup_user(Cm) ->
gen_server:call(?MODULE, {get_user, Cm}, infinity).
@@ -82,9 +92,10 @@ handle_call({get_user, Cm}, _From, #state{user_db = Db} = State) ->
%% {stop, Reason, State}
%% Description: Handling cast messages
%%--------------------------------------------------------------------
-handle_cast({register, UserCm}, State0) ->
- State = insert(UserCm, State0),
- {noreply, State}.
+handle_cast({register, UserCm}, State) ->
+ {noreply, insert(UserCm, State)};
+handle_cast({delete, UserCm}, State) ->
+ {noreply, delete(UserCm, State)}.
%%--------------------------------------------------------------------
%% Function: handle_info(Info, State) -> {noreply, State} |
@@ -118,6 +129,9 @@ code_change(_OldVsn, State, _Extra) ->
insert({User, Cm}, #state{user_db = Db} = State) ->
State#state{user_db = [{User, Cm} | Db]}.
+delete(Cm, #state{user_db = Db} = State) ->
+ State#state{user_db = lists:keydelete(Cm, 2, Db)}.
+
lookup(_, []) ->
undefined;
lookup(Cm, [{User, Cm} | _Rest]) ->
diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile
new file mode 100644
index 0000000000..1820924ed6
--- /dev/null
+++ b/lib/ssh/test/Makefile
@@ -0,0 +1,121 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2004-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, 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=$(GS_VSN)
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+MODULES= \
+ ssh_test_lib \
+ ssh_SUITE \
+ ssh_basic_SUITE \
+ ssh_to_openssh_SUITE \
+ ssh_sftp_SUITE \
+ ssh_sftpd_SUITE \
+ ssh_sftpd_erlclient_SUITE
+
+HRL_FILES_NEEDED_IN_TEST= \
+ $(ERL_TOP)/lib/ssh/src/ssh.hrl \
+ $(ERL_TOP)/lib/ssh/src/ssh_xfer.hrl
+
+ERL_FILES= $(MODULES:%=%.erl)
+
+TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+DATA_DIRS = $(MODULES:%=%_data)
+
+INCLUDES = -I$(ERL_TOP)/lib/test_server/include \
+ -I$(ERL_TOP)/lib/ssh/src \
+
+EMAKEFILE=Emakefile
+MAKE_EMAKE = $(wildcard $(ERL_TOP)/make/make_emakefile)
+
+ifeq ($(MAKE_EMAKE),)
+BUILDTARGET = $(TARGET_FILES)
+RELTEST_FILES = $(INETS_SPECS) $(SOURCE)
+else
+BUILDTARGET = emakebuild
+RELTEST_FILES = $(EMAKEFILE) $(INETS_SPECS) $(SOURCE)
+endif
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/ssh_test
+
+# ----------------------------------------------------
+# FLAGS
+# The path to the test_server ebin dir is needed when
+# running the target "targets".
+# ----------------------------------------------------
+ERL_COMPILE_FLAGS += -pa ../../../internal_tools/test_server/ebin \
+ $(INCLUDES)
+
+EBIN = .
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+tests debug opt: $(BUILDTARGET)
+
+targets: $(TARGET_FILES)
+
+.PHONY: emakebuild
+
+emakebuild: $(EMAKEFILE)
+
+$(EMAKEFILE):
+ $(MAKE_EMAKE) $(ERL_COMPILE_FLAGS) -o$(EBIN) '*_SUITE_make' | grep -v Warning > $(EMAKEFILE)
+ $(MAKE_EMAKE) $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) | grep -v Warning >> $(EMAKEFILE)
+
+clean:
+ rm -f $(EMAKEFILE)
+ rm -f $(TARGET_FILES)
+ rm -f core
+docs:
+
+info:
+ @echo "TARGET_FILES = $(TARGET_FILES)"
+ @echo "DATA_DIRS = $(DATA_DIRS)"
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+
+release_tests_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)
+ $(INSTALL_DATA) ssh.spec ssh.cover $(RELSYSDIR)
+ $(INSTALL_DATA) $(HRL_FILES_NEEDED_IN_TEST) $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
+ @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+
+release_docs_spec:
diff --git a/lib/ssh/test/ssh.cover b/lib/ssh/test/ssh.cover
new file mode 100644
index 0000000000..a4221fbbbe
--- /dev/null
+++ b/lib/ssh/test/ssh.cover
@@ -0,0 +1,2 @@
+{incl_app,ssh,details}.
+
diff --git a/lib/ssh/test/ssh.spec b/lib/ssh/test/ssh.spec
new file mode 100644
index 0000000000..8de0fe44e4
--- /dev/null
+++ b/lib/ssh/test/ssh.spec
@@ -0,0 +1,7 @@
+{suites,"../ssh_test",all}.
+{skip_cases,"../ssh_test",ssh_ssh_SUITE,
+ [ssh],
+ "Current implementation is timingdependent and\nhence will succeed/fail on a whim"}.
+{skip_cases,"../ssh_test",ssh_ssh_SUITE,
+ [ssh_compressed],
+ "Current implementation is timingdependent hence will succeed/fail on a whim"}.
diff --git a/lib/ssh/test/ssh.spec.vxworks b/lib/ssh/test/ssh.spec.vxworks
new file mode 100644
index 0000000000..81f665283c
--- /dev/null
+++ b/lib/ssh/test/ssh.spec.vxworks
@@ -0,0 +1,3 @@
+{topcase, {dir, "../ssh_test"}}.
+{require_nodenames, 1}.
+%{skip, {M, F, "Not yet implemented"}}.
diff --git a/lib/ssh/test/ssh_SUITE.erl b/lib/ssh/test/ssh_SUITE.erl
new file mode 100644
index 0000000000..953c9080f9
--- /dev/null
+++ b/lib/ssh/test/ssh_SUITE.erl
@@ -0,0 +1,72 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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:ssh application test suite.
+%%%-----------------------------------------------------------------
+-module(ssh_SUITE).
+-include_lib("common_test/include/ct.hrl").
+-include("test_server_line.hrl").
+
+% Default timetrap timeout (set in init_per_testcase).
+-define(default_timeout, ?t:minutes(1)).
+-define(application, ssh).
+
+% Test server specific exports
+-export([all/0,groups/0,init_per_group/2,end_per_group/2]).
+-export([init_per_testcase/2, end_per_testcase/2]).
+
+% Test cases must be exported.
+-export([app_test/1]).
+-define(cases, [app_test]).
+
+%%
+%% all/1
+%%
+all() ->
+ [app_test].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+init_per_testcase(_Case, Config) ->
+ Dog=test_server:timetrap(?default_timeout),
+ [{watchdog, Dog}|Config].
+end_per_testcase(_Case, Config) ->
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ ok.
+%
+% Test cases starts here.
+%
+app_test(suite) ->
+ [];
+app_test(doc) ->
+ ["Application consistency test."];
+app_test(Config) when is_list(Config) ->
+ ?t:app_test(?application),
+ ok.
diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl
new file mode 100644
index 0000000000..5ea0d98980
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE.erl
@@ -0,0 +1,389 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(ssh_basic_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+-include("test_server_line.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-define(NEWLINE, <<"\r\n">>).
+
+%%--------------------------------------------------------------------
+%% 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(Config) ->
+ case catch crypto:start() of
+ ok ->
+ Dir = ?config(priv_dir, Config),
+ {ok, _} = ssh_test_lib:get_id_keys(Dir),
+ ssh_test_lib:make_dsa_files(Config),
+ Config;
+ _Else ->
+ {skip, "Crypto could not be started!"}
+ end.
+
+%%--------------------------------------------------------------------
+%% 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) ->
+ Dir = ?config(priv_dir, Config),
+ crypto:stop(),
+ ssh_test_lib:remove_id_keys(Dir),
+ ok.
+
+%%--------------------------------------------------------------------
+%% 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(_TestCase, Config) ->
+ ssh_test_lib:known_hosts(backup),
+ ssh:start(),
+ 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(_TestCase, _Config) ->
+ ssh:stop(),
+ ssh_test_lib:known_hosts(restore),
+ ok.
+
+%%--------------------------------------------------------------------
+%% 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() ->
+ [exec, exec_compressed, shell, daemon_already_started,
+ server_password_option, server_userpassword_option,
+ known_hosts].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+%% Test cases starts here.
+%%--------------------------------------------------------------------
+sign_and_verify_rsa(doc) ->
+ ["Test api function ssh:sign_data and ssh:verify_data"];
+
+sign_and_verify_rsa(suite) ->
+ [];
+sign_and_verify_rsa(Config) when is_list(Config) ->
+ Data = ssh:sign_data(<<"correct data">>, "ssh-rsa"),
+ ok = ssh:verify_data(<<"correct data">>, Data, "ssh-rsa"),
+ {error,invalid_signature} = ssh:verify_data(<<"incorrect data">>, Data,"ssh-rsa").
+
+
+exec(doc) ->
+ ["Test api function ssh_connection:exec"];
+
+exec(suite) ->
+ [];
+
+exec(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ SystemDir = ?config(data_dir, Config),
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+ ConnectionRef =
+ ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user_interaction, false}]),
+ {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity),
+ success = ssh_connection:exec(ConnectionRef, ChannelId0,
+ "1+1.", infinity),
+ Data0 = {ssh_cm, ConnectionRef, {data, ChannelId0, 0, <<"2\n">>}},
+ case ssh_test_lib:receive_exec_result(Data0) of
+ expected ->
+ ok;
+ Other0 ->
+ test_server:fail(Other0)
+ end,
+ ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId0),
+
+ %% Test that it is possible to start a new channel and
+ %% run an other exec on the same connection.
+ {ok, ChannelId1} = ssh_connection:session_channel(ConnectionRef, infinity),
+ success = ssh_connection:exec(ConnectionRef, ChannelId1,
+ "2+2.", infinity),
+ Data1 = {ssh_cm, ConnectionRef, {data, ChannelId1, 0, <<"4\n">>}},
+ case ssh_test_lib:receive_exec_result(Data1) of
+ expected ->
+ ok;
+ Other1 ->
+ test_server:fail(Other1)
+ end,
+ ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId1),
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+exec_compressed(doc) ->
+ ["Test that compression option works"];
+
+exec_compressed(suite) ->
+ [];
+
+exec_compressed(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ SystemDir = ?config(data_dir, Config),
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {compression, zlib},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+
+ ConnectionRef =
+ ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user_interaction, false}]),
+ {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
+ success = ssh_connection:exec(ConnectionRef, ChannelId,
+ "1+1.", infinity),
+ Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"2\n">>}},
+ case ssh_test_lib:receive_exec_result(Data) of
+ expected ->
+ ok;
+ Other ->
+ test_server:fail(Other)
+ end,
+ ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId),
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+
+shell(doc) ->
+ ["Test that ssh:shell/2 works"];
+
+shell(suite) ->
+ [];
+
+shell(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ SystemDir = ?config(data_dir, Config),
+ {_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+ test_server:sleep(500),
+
+ IO = ssh_test_lib:start_io_server(),
+ Shell = ssh_test_lib:start_shell(Port, IO),
+ receive
+ ErlShellStart ->
+ test_server:format("Erlang shell start: ~p~n", [ErlShellStart])
+ end,
+ receive
+ ErlPrompt0 ->
+ test_server:format("Erlang prompt: ~p~n", [ErlPrompt0])
+ end,
+ IO ! {input, self(), "1+1.\r\n"},
+ receive
+ Echo0 ->
+ test_server:format("Echo: ~p ~n", [Echo0])
+ end,
+ receive
+ ?NEWLINE ->
+ ok
+ end,
+ receive
+ Result0 = <<"2">> ->
+ test_server:format("Result: ~p~n", [Result0])
+ end,
+ receive
+ ?NEWLINE ->
+ ok
+ end,
+ receive
+ ErlPrompt1 ->
+ test_server:format("Erlang prompt: ~p~n", [ErlPrompt1])
+ end,
+ exit(Shell, kill),
+ %% Does not seem to work in the testserver!
+ %% IO ! {input, self(), "q().\r\n"},
+ %% receive
+ %% ?NEWLINE ->
+ %% ok
+ %% end,
+ %% receive
+ %% Echo1 ->
+ %% test_server:format("Echo: ~p ~n", [Echo1])
+ %% end,
+ %% receive
+ %% ?NEWLINE ->
+ %% ok
+ %% end,
+ %% receive
+ %% Result1 ->
+ %% test_server:format("Result: ~p~n", [Result1])
+ %% end,
+ receive
+ {'EXIT', Shell, killed} ->
+ ok
+ end.
+
+%%--------------------------------------------------------------------
+daemon_already_started(doc) ->
+ ["Test that get correct error message if you try to start a daemon",
+ "on an adress that already runs a daemon see also seq10667" ];
+
+daemon_already_started(suite) ->
+ [];
+
+daemon_already_started(Config) when is_list(Config) ->
+ SystemDir = ?config(data_dir, Config),
+ {Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+ {error, eaddrinuse} = ssh_test_lib:daemon(Port, [{system_dir, SystemDir},
+ {failfun,
+ fun ssh_test_lib:failfun/2}]),
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+server_password_option(doc) ->
+ ["validate to server that uses the 'password' option"];
+server_password_option(suite) ->
+ [];
+server_password_option(Config) when is_list(Config) ->
+ UserDir = ?config(data_dir, Config), % to make sure we don't use
+ SysDir = ?config(data_dir, Config), % public-key-auth
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
+ {password, "morot"}]),
+
+ ConnectionRef =
+ ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "foo"},
+ {password, "morot"},
+ {user_interaction, false},
+ {user_dir, UserDir}]),
+ {error, Reason} =
+ ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "vego"},
+ {password, "foo"},
+ {user_interaction, false},
+ {user_dir, UserDir}]),
+
+ test_server:format("Test of wrong password: Error msg: ~p ~n", [Reason]),
+
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+
+server_userpassword_option(doc) ->
+ ["validate to server that uses the 'password' option"];
+server_userpassword_option(suite) ->
+ [];
+server_userpassword_option(Config) when is_list(Config) ->
+ UserDir = ?config(data_dir, Config), % to make sure we don't use
+ SysDir = ?config(data_dir, Config), % public-key-auth
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_passwords, [{"vego", "morot"}]}]),
+
+ ConnectionRef =
+ ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "vego"},
+ {password, "morot"},
+ {user_interaction, false},
+ {user_dir, UserDir}]),
+ ssh:close(ConnectionRef),
+
+ {error, Reason0} =
+ ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "foo"},
+ {password, "morot"},
+ {user_interaction, false},
+ {user_dir, UserDir}]),
+
+ test_server:format("Test of user foo that does not exist. "
+ "Error msg: ~p ~n", [Reason0]),
+
+ {error, Reason1} =
+ ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "vego"},
+ {password, "foo"},
+ {user_interaction, false},
+ {user_dir, UserDir}]),
+ test_server:format("Test of wrong Password. "
+ "Error msg: ~p ~n", [Reason1]),
+
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+known_hosts(doc) ->
+ ["check that known_hosts is updated correctly"];
+known_hosts(suite) ->
+ [];
+known_hosts(Config) when is_list(Config) ->
+ SystemDir = ?config(data_dir, Config),
+ UserDir = ?config(priv_dir, Config),
+
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+
+ KnownHosts = filename:join(UserDir, "known_hosts"),
+ file:delete(KnownHosts),
+ {error, enoent} = file:read_file(KnownHosts),
+ ConnectionRef =
+ ssh_test_lib:connect(Host, Port, [{user_dir, UserDir},
+ {user_interaction, false},
+ silently_accept_hosts]),
+ {ok, _Channel} = ssh_connection:session_channel(ConnectionRef, infinity),
+ ok = ssh:close(ConnectionRef),
+ {ok, Binary} = file:read_file(KnownHosts),
+ Lines = string:tokens(binary_to_list(Binary), "\n"),
+ [Line] = Lines,
+ [HostAndIp, Alg, _KeyData] = string:tokens(Line, " "),
+ [Host, _Ip] = string:tokens(HostAndIp, ","),
+ "ssh-" ++ _ = Alg,
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+%% Internal functions
+%%--------------------------------------------------------------------
diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl
new file mode 100644
index 0000000000..c96b6de3ea
--- /dev/null
+++ b/lib/ssh/test/ssh_sftp_SUITE.erl
@@ -0,0 +1,543 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(ssh_sftp_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include("test_server_line.hrl").
+
+-include_lib("kernel/include/file.hrl").
+
+% Default timetrap timeout
+-define(default_timeout, ?t:minutes(1)).
+
+-define(SFPD_PORT, 9999).
+-define(USER, "Alladin").
+-define(PASSWD, "Sesame").
+
+%% Test server callback functions
+%%--------------------------------------------------------------------
+%% 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) ->
+ case {catch crypto:start(),catch ssh:start()} of
+ {ok,ok} ->
+ Dir = ?config(priv_dir, Config),
+ {ok, _} = ssh_test_lib:get_id_keys(Dir),
+ ssh_test_lib:make_dsa_files(Config),
+ Config;
+ {ok,_} ->
+ {skip,"Could not start ssh!"};
+ {_,ok} ->
+ {skip,"Could not start crypto!"};
+ {_,_} ->
+ {skip,"Could not start crypto and ssh!"}
+ end.
+
+%%--------------------------------------------------------------------
+%% 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) ->
+ crypto:stop(),
+ Dir = ?config(priv_dir, Config),
+ ssh_test_lib:remove_id_keys(Dir),
+ Config.
+
+%%--------------------------------------------------------------------
+%% 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: Initiation 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: Initiation before each test case
+%%--------------------------------------------------------------------
+init_per_testcase(_Case, Config) ->
+ prep(Config),
+ TmpConfig0 = lists:keydelete(watchdog, 1, Config),
+ TmpConfig = lists:keydelete(sftp, 1, TmpConfig0),
+ Dog = test_server:timetrap(?default_timeout),
+ Dir = ?config(priv_dir, Config),
+ SysDir = ?config(data_dir, Config),
+ Host = ssh_test_lib:hostname(),
+
+ Sftp = case (catch ssh_sftp:start_channel(Host,
+ [{user_dir, Dir},
+ {user_interaction, false},
+ {silently_accept_hosts, true}])) of
+ {ok, ChannelPid, Connection} ->
+ {ChannelPid, Connection};
+ _Error ->
+ {_Sftpd, _Host, _Port} =
+ ssh_test_lib:daemon(Host, ?SFPD_PORT,
+ [{system_dir, SysDir},
+ {user_passwords,
+ [{?USER, ?PASSWD}]},
+ {failfun,
+ fun ssh_test_lib:failfun/2}]),
+ Result = (catch ssh_sftp:start_channel(Host, ?SFPD_PORT,
+ [{user, ?USER},
+ {password, ?PASSWD},
+ {user_interaction, false},
+ {silently_accept_hosts, true}])),
+ {ok, ChannelPid, Connection} = Result,
+ {ChannelPid, Connection}
+ end,
+
+ [{sftp, Sftp}, {watchdog, Dog} | TmpConfig].
+
+%%--------------------------------------------------------------------
+%% 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(_Case, Config) ->
+ {Sftp, Connection} = ?config(sftp, Config),
+ ssh_sftp:stop_channel(Sftp),
+ ssh:close(Connection),
+ Dog = ?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+%%--------------------------------------------------------------------
+%% 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() ->
+ [open_close_file, open_close_dir, read_file, read_dir,
+ write_file, rename_file, mk_rm_dir, remove_file, links,
+ retrieve_attributes, set_attributes, async_read,
+ async_write, position, pos_read, pos_write].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+%% Test cases starts here.
+%%--------------------------------------------------------------------
+open_close_file(doc) ->
+ ["Test API functions open/3 and close/2"];
+open_close_file(suite) ->
+ [];
+open_close_file(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "sftp.txt"),
+
+ {Sftp, _} = ?config(sftp, Config),
+
+ ok = open_close_file(Sftp, FileName, [read]),
+ ok = open_close_file(Sftp, FileName, [write]),
+ ok = open_close_file(Sftp, FileName, [write, creat]),
+ ok = open_close_file(Sftp, FileName, [write, trunc]),
+ ok = open_close_file(Sftp, FileName, [append]),
+ ok = open_close_file(Sftp, FileName, [read, binary]),
+
+ ok.
+
+open_close_file(Server, File, Mode) ->
+ {ok, Handle} = ssh_sftp:open(Server, File, Mode),
+ ok = ssh_sftp:close(Server, Handle),
+ ok.
+
+
+%%--------------------------------------------------------------------
+open_close_dir(doc) ->
+ ["Test API functions opendir/2 and close/2"];
+open_close_dir(suite) ->
+ [];
+open_close_dir(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ {Sftp, _} = ?config(sftp, Config),
+ FileName = filename:join(PrivDir, "sftp.txt"),
+
+ {ok, Handle} = ssh_sftp:opendir(Sftp, PrivDir),
+ ok = ssh_sftp:close(Sftp, Handle),
+ {error, _} = ssh_sftp:opendir(Sftp, FileName),
+
+ ok.
+%%--------------------------------------------------------------------
+read_file(doc) ->
+ ["Test API funtion read_file/2"];
+read_file(suite) ->
+ [];
+read_file(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "sftp.txt"),
+
+ {Sftp, _} = ?config(sftp, Config),
+
+ {ok, Data} = ssh_sftp:read_file(Sftp, FileName),
+
+ {ok, Data} = file:read_file(FileName),
+
+ ok.
+%%--------------------------------------------------------------------
+read_dir(doc) ->
+ ["Test API function list_dir/2"];
+read_dir(suite) ->
+ [];
+read_dir(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ {Sftp, _} = ?config(sftp, Config),
+ {ok, Files} = ssh_sftp:list_dir(Sftp, PrivDir),
+ test_server:format("sftp list dir: ~p~n", [Files]),
+ ok.
+
+%%--------------------------------------------------------------------
+write_file(doc) ->
+ ["Test API function write_file/2"];
+write_file(suite) ->
+ [];
+write_file(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "sftp.txt"),
+
+ {Sftp, _} = ?config(sftp, Config),
+
+ Data = list_to_binary("Hej hopp!"),
+
+ ssh_sftp:write_file(Sftp, FileName, [Data]),
+
+ {ok, Data} = file:read_file(FileName),
+
+ ok.
+
+%%--------------------------------------------------------------------
+remove_file(doc) ->
+ ["Test API function delete/2"];
+remove_file(suite) ->
+ [];
+remove_file(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "sftp.txt"),
+
+ {Sftp, _} = ?config(sftp, Config),
+
+ {ok, Files} = ssh_sftp:list_dir(Sftp, PrivDir),
+
+ true = lists:member(filename:basename(FileName), Files),
+
+ ok = ssh_sftp:delete(Sftp, FileName),
+
+ {ok, NewFiles} = ssh_sftp:list_dir(Sftp, PrivDir),
+
+ false = lists:member(filename:basename(FileName), NewFiles),
+
+ {error, _} = ssh_sftp:delete(Sftp, FileName),
+
+ ok.
+
+%%--------------------------------------------------------------------
+rename_file(doc) ->
+ ["Test API function rename_file/2"];
+rename_file(suite) ->
+ [];
+rename_file(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "sftp.txt"),
+ NewFileName = filename:join(PrivDir, "test.txt"),
+
+ {Sftp, _} = ?config(sftp, Config),
+
+ {ok, Files} = ssh_sftp:list_dir(Sftp, PrivDir),
+
+ test_server:format("FileName: ~p, Files: ~p~n", [FileName, Files]),
+
+ true = lists:member(filename:basename(FileName), Files),
+ false = lists:member(filename:basename(NewFileName), Files),
+
+ ok = ssh_sftp:rename(Sftp, FileName, NewFileName),
+
+ {ok, NewFiles} = ssh_sftp:list_dir(Sftp, PrivDir),
+
+ test_server:format("FileName: ~p, Files: ~p~n", [FileName, NewFiles]),
+
+ false = lists:member(filename:basename(FileName), NewFiles),
+ true = lists:member(filename:basename(NewFileName), NewFiles),
+
+ ok.
+
+%%--------------------------------------------------------------------
+mk_rm_dir(doc) ->
+ ["Test API functions make_dir/2, del_dir/2"];
+mk_rm_dir(suite) ->
+ [];
+mk_rm_dir(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ {Sftp, _} = ?config(sftp, Config),
+ DirName = filename:join(PrivDir, "test"),
+
+ ok = ssh_sftp:make_dir(Sftp, DirName),
+ ok = ssh_sftp:del_dir(Sftp, DirName),
+
+ NewDirName = filename:join(PrivDir, "foo/bar"),
+
+ {error, _} = ssh_sftp:make_dir(Sftp, NewDirName),
+ {error, _} = ssh_sftp:del_dir(Sftp, PrivDir),
+
+ ok.
+
+%%--------------------------------------------------------------------
+links(doc) ->
+ ["Tests API function make_symlink/3"];
+links(suite) ->
+ [];
+links(Config) when is_list(Config) ->
+ case test_server:os_type() of
+ {win32, _} ->
+ {skip, "Links are not fully supported by windows"};
+ _ ->
+ {Sftp, _} = ?config(sftp, Config),
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "sftp.txt"),
+ LinkFileName = filename:join(PrivDir, "link_test.txt"),
+
+ ok = ssh_sftp:make_symlink(Sftp, FileName, LinkFileName),
+ {ok, FileName} = ssh_sftp:read_link(Sftp, LinkFileName),
+ ok
+ end.
+
+%%--------------------------------------------------------------------
+retrieve_attributes(doc) ->
+ ["Test API function read_file_info/3"];
+retrieve_attributes(suite) ->
+ [];
+retrieve_attributes(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "sftp.txt"),
+ {Sftp, _} = ?config(sftp, Config),
+
+ {ok, FileInfo} = ssh_sftp:read_file_info(Sftp, FileName),
+
+ {ok, NewFileInfo} = file:read_file_info(FileName),
+
+ %% TODO comparison. There are some differences now is that ok?
+ test_server:format("SFTP: ~p FILE: ~p~n", [FileInfo, NewFileInfo]),
+ ok.
+
+%%--------------------------------------------------------------------
+set_attributes(doc) ->
+ ["Test API function write_file_info/3"];
+set_attributes(suite) ->
+ [];
+set_attributes(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "test.txt"),
+ {Sftp, _} = ?config(sftp, Config),
+
+ {ok,Fd} = file:open(FileName, write),
+ io:put_chars(Fd,"foo"),
+
+ ok = ssh_sftp:write_file_info(Sftp, FileName, #file_info{mode=8#400}),
+ {error, eacces} = file:write_file(FileName, "hello again"),
+ ssh_sftp:write_file_info(Sftp, FileName, #file_info{mode=8#600}),
+ ok = file:write_file(FileName, "hello again"),
+
+ ok.
+
+%%--------------------------------------------------------------------
+
+async_read(doc) ->
+ ["Test API aread/3"];
+async_read(suite) ->
+ [];
+async_read(Config) when is_list(Config) ->
+ {Sftp, _} = ?config(sftp, Config),
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "sftp.txt"),
+ {ok, Handle} = ssh_sftp:open(Sftp, FileName, [read]),
+ {async, Ref} = ssh_sftp:aread(Sftp, Handle, 20),
+
+ receive
+ {async_reply, Ref, {ok, Data}} ->
+ test_server:format("Data: ~p~n", [Data]),
+ ok;
+ Msg ->
+ test_server:fail(Msg)
+ end,
+ ok.
+%%--------------------------------------------------------------------
+async_write(doc) ->
+ ["Test API awrite/3"];
+async_write(suite) ->
+ [];
+async_write(Config) when is_list(Config) ->
+ {Sftp, _} = ?config(sftp, Config),
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "test.txt"),
+ {ok, Handle} = ssh_sftp:open(Sftp, FileName, [write]),
+ Data = list_to_binary("foobar"),
+ {async, Ref} = ssh_sftp:awrite(Sftp, Handle, Data),
+
+ receive
+ {async_reply, Ref, ok} ->
+ {ok, Data} = file:read_file(FileName);
+ Msg ->
+ test_server:fail(Msg)
+ end,
+ ok.
+
+%%--------------------------------------------------------------------
+
+position(doc) ->
+ ["Test API functions position/3"];
+position(suite) ->
+ [];
+position(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "test.txt"),
+ {Sftp, _} = ?config(sftp, Config),
+
+ Data = list_to_binary("1234567890"),
+ ssh_sftp:write_file(Sftp, FileName, [Data]),
+
+ {ok, Handle} = ssh_sftp:open(Sftp, FileName, [read]),
+
+ {ok, 3} = ssh_sftp:position(Sftp, Handle, {bof, 3}),
+ {ok, "4"} = ssh_sftp:read(Sftp, Handle, 1),
+
+ {ok, 10} = ssh_sftp:position(Sftp, Handle, eof),
+ eof = ssh_sftp:read(Sftp, Handle, 1),
+
+ {ok, 6} = ssh_sftp:position(Sftp, Handle, {bof, 6}),
+ {ok, "7"} = ssh_sftp:read(Sftp, Handle, 1),
+
+ {ok, 9} = ssh_sftp:position(Sftp, Handle, {cur, 2}),
+ {ok, "0"} = ssh_sftp:read(Sftp, Handle, 1),
+
+ {ok, 0} = ssh_sftp:position(Sftp, Handle, bof),
+ {ok, "1"} = ssh_sftp:read(Sftp, Handle, 1),
+
+ {ok, 1} = ssh_sftp:position(Sftp, Handle, cur),
+ {ok, "2"} = ssh_sftp:read(Sftp, Handle, 1),
+
+ ok.
+
+%%--------------------------------------------------------------------
+pos_read(doc) ->
+ ["Test API functions pread/3 and apread/3"];
+pos_read(suite) ->
+ [];
+pos_read(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "test.txt"),
+ {Sftp, _} = ?config(sftp, Config),
+ Data = list_to_binary("Hej hopp!"),
+ ssh_sftp:write_file(Sftp, FileName, [Data]),
+
+ {ok, Handle} = ssh_sftp:open(Sftp, FileName, [read]),
+
+ {async, Ref} = ssh_sftp:apread(Sftp, Handle, {bof, 5}, 4),
+
+ NewData = "opp!",
+
+ receive
+ {async_reply, Ref, {ok, NewData}} ->
+ ok;
+ Msg ->
+ test_server:fail(Msg)
+ end,
+
+ NewData1 = "hopp",
+
+ {ok, NewData1} = ssh_sftp:pread(Sftp, Handle, {bof, 4}, 4),
+
+ ok.
+%%--------------------------------------------------------------------
+pos_write(doc) ->
+ ["Test API functions pwrite/4 and apwrite/4"];
+pos_write(suite) ->
+ [];
+pos_write(Config) when is_list(Config) ->
+
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "test.txt"),
+ {Sftp, _} = ?config(sftp, Config),
+
+ {ok, Handle} = ssh_sftp:open(Sftp, FileName, [write]),
+
+ Data = list_to_binary("Bye,"),
+ ssh_sftp:write_file(Sftp, FileName, [Data]),
+
+ NewData = list_to_binary(" see you tomorrow"),
+ {async, Ref} = ssh_sftp:apwrite(Sftp, Handle, {bof, 4}, NewData),
+ receive
+ {async_reply, Ref, ok} ->
+ ok;
+ Msg ->
+ test_server:fail(Msg)
+ end,
+
+ ok = ssh_sftp:pwrite(Sftp, Handle, eof, list_to_binary("!")),
+
+ NewData1 = list_to_binary("Bye, see you tomorrow!"),
+ {ok, NewData1} = ssh_sftp:read_file(Sftp, FileName),
+
+ ok.
+
+%% Internal functions
+%%--------------------------------------------------------------------
+prep(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ TestFile = filename:join(PrivDir, "sftp.txt"),
+ TestFile1 = filename:join(PrivDir, "test.txt"),
+ TestLink = filename:join(PrivDir, "link_test.txt"),
+
+ file:delete(TestFile),
+ file:delete(TestFile1),
+ file:delete(TestLink),
+
+ %% Initial config
+ DataDir = ?config(data_dir, Config),
+ FileName = filename:join(DataDir, "sftp.txt"),
+ file:copy(FileName, TestFile),
+ Mode = 8#00400 bor 8#00200 bor 8#00040, % read & write owner, read group
+ {ok, FileInfo} = file:read_file_info(TestFile),
+ ok = file:write_file_info(TestFile,
+ FileInfo#file_info{mode = Mode}).
diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa b/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa
new file mode 100644
index 0000000000..7e3f885f5d
--- /dev/null
+++ b/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICWwIBAAKBgQDLKYTdRnGzphcN+pF8UuI3sYB7rxZUHbOT87K3vh8XOLkDOsS3
+8VREtNS8Wb3uYXsRtyDoUvrLIDnyllOfJSDupWLr4ibckUZd/nhFAaC6WryVmH6k
+GlQLLp9KU+vcn2DwYeo14gbwHYDB3pmv4CWAlnO1m/BkX4aLz1zC314OkQIBIwKB
+gD/Z2UzboBPjvhpWEHeHw3CW3zzQoJ4X9pw2peH57IOkHOPCA0/A3/hWFvleCH4e
+owWRU3w3ViKVGYbBh/7RJ5rllN+ENUmVn536srJTxLKUtvb5jRGj3W6EWgAGHSUB
+hm83Kt9Lb5hprL7dPrNGvSseBm/LQSfBQ4vUUyiVRKGPAkEA/rPxWoLdBBP+FZtE
+fGzz9izPM6Fe6o8ZGNZIlRBProOhgEvvIqdgzQWObgLVVrw+M/YApPpiYS3PEmWj
+b2b+jwJBAMwyYeL6coKTl8swDu8HvLnshgUFJFTtHhOTXsKtXQNI1b24xhUrB3Sb
+X8fmoByyRNRpOfvg4Jdqi3Z6KfIcsN8CQQDEfC83McBw3DkJWoVKCugVrYnmACSm
+USH9N5cT6AL0VupNB2C0VTwL37cEaJXyc/V4ipLIaWHV8CNl9qKmZWVJAkEAurG4
+lQI8zyfbPW3EgsU+1d+QeZ5NGnJkpC73jWtNudwxIn0M4CdXRgpmMxwAGjyWs5No
+Nr75OfsDKn5SPHIAywJAKrtONlOizgDiG3EvAXZlwFtOb+HkQ7lrFwczrQu9m7yi
+brSAcnTrLKI6CrR33b/QJLvb9C/HTEZojFABGq8M7A==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa.pub b/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa.pub
new file mode 100644
index 0000000000..77f57de4af
--- /dev/null
+++ b/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAyymE3UZxs6YXDfqRfFLiN7GAe68WVB2zk/Oyt74fFzi5AzrEt/FURLTUvFm97mF7Ebcg6FL6yyA58pZTnyUg7qVi6+Im3JFGXf54RQGgulq8lZh+pBpUCy6fSlPr3J9g8GHqNeIG8B2Awd6Zr+AlgJZztZvwZF+Gi89cwt9eDpE= jakob@balin
diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/sftp.txt b/lib/ssh/test/ssh_sftp_SUITE_data/sftp.txt
new file mode 100644
index 0000000000..2a878ae255
--- /dev/null
+++ b/lib/ssh/test/ssh_sftp_SUITE_data/sftp.txt
@@ -0,0 +1,252 @@
+There are 5 KeySyms per KeyCode; KeyCodes range from 8 to 254.
+
+ KeyCode Keysym (Keysym) ...
+ Value Value (Name) ...
+
+ 8
+ 9
+ 10
+ 11 0x0041 (A)
+ 12 0x0042 (B)
+ 13 0x0043 (C)
+ 14 0x0044 (D)
+ 15 0x0065 (e) 0x0045 (E) 0x20ac (EuroSign)
+ 16 0x0046 (F)
+ 17 0x0047 (G)
+ 18 0x0048 (H)
+ 19 0x0049 (I)
+ 20 0x004a (J)
+ 21 0x004b (K)
+ 22 0x004c (L)
+ 23 0x004d (M)
+ 24 0x004e (N)
+ 25 0x004f (O)
+ 26 0x0050 (P)
+ 27 0x0051 (Q)
+ 28 0x0052 (R)
+ 29 0x0053 (S)
+ 30 0x0054 (T)
+ 31 0x0055 (U)
+ 32 0x0056 (V)
+ 33 0x0057 (W)
+ 34 0x0058 (X)
+ 35 0x0059 (Y)
+ 36 0x005a (Z)
+ 37 0x0031 (1) 0x0021 (exclam)
+ 38 0x0032 (2) 0x0022 (quotedbl) 0x0040 (at)
+ 39 0x0033 (3) 0x0023 (numbersign) 0x00a3 (sterling)
+ 40 0x0034 (4) 0x00a4 (currency) 0x0024 (dollar)
+ 41 0x0035 (5) 0x0025 (percent)
+ 42 0x0036 (6) 0x0026 (ampersand)
+ 43 0x0037 (7) 0x002f (slash) 0x007b (braceleft)
+ 44 0x0038 (8) 0x0028 (parenleft) 0x005b (bracketleft)
+ 45 0x0039 (9) 0x0029 (parenright) 0x005d (bracketright)
+ 46 0x0030 (0) 0x003d (equal) 0x007d (braceright)
+ 47 0xff0d (Return)
+ 48 0xff1b (Escape)
+ 49 0xff08 (BackSpace)
+ 50 0xff09 (Tab)
+ 51 0x0020 (space)
+ 52 0x002b (plus) 0x003f (question) 0x005c (backslash)
+ 53 0x1005ff03 (SunFA_Acute) 0x1005ff00 (SunFA_Grave)
+ 54 0x00c5 (Aring)
+ 55 0x1005ff04 (SunFA_Diaeresis) 0x005e (asciicircum) 0x007e (asciitilde)
+ 56
+ 57 0x0027 (apostrophe) 0x002a (asterisk) 0x0060 (grave)
+ 58 0x00d6 (Odiaeresis)
+ 59 0x00c4 (Adiaeresis)
+ 60 0x00a7 (section) 0x00bd (onehalf)
+ 61 0x002c (comma) 0x003b (semicolon)
+ 62 0x002e (period) 0x003a (colon)
+ 63 0x002d (minus) 0x005f (underscore)
+ 64 0xffe5 (Caps_Lock)
+ 65 0xffbe (F1)
+ 66 0xffbf (F2)
+ 67 0xffc0 (F3)
+ 68 0xffc1 (F4)
+ 69 0xffc2 (F5)
+ 70 0xffc3 (F6)
+ 71 0xffc4 (F7)
+ 72 0xffc5 (F8)
+ 73 0xffc6 (F9)
+ 74 0xffc7 (F10)
+ 75 0x1005ff10 (SunF36)
+ 76 0x1005ff11 (SunF37)
+ 77 0xffd3 (F22) 0xffd3 (F22) 0xff61 (Print) 0x1005ff60 (SunSys_Req)
+ 78 0xffd4 (F23) 0xffd4 (F23) 0xff14 (Scroll_Lock)
+ 79 0xffd2 (F21) 0xffd2 (F21) 0xff13 (Pause) 0xff6b (Break)
+ 80 0xff63 (Insert)
+ 81 0xff50 (Home)
+ 82 0xff55 (Prior)
+ 83 0xffff (Delete)
+ 84 0xff57 (End)
+ 85 0xff56 (Next)
+ 86 0xff53 (Right)
+ 87 0xff51 (Left)
+ 88 0xff54 (Down)
+ 89 0xff52 (Up)
+ 90 0xff7f (Num_Lock)
+ 91 0xffd6 (F25) 0xffd6 (F25) 0xffaf (KP_Divide)
+ 92 0xffd7 (F26) 0xffd7 (F26) 0xffaa (KP_Multiply)
+ 93 0xffd5 (F24) 0xffd5 (F24) 0xffad (KP_Subtract)
+ 94 0xffab (KP_Add)
+ 95 0xff8d (KP_Enter)
+ 96 0xffde (F33) 0xffde (F33) 0xffb1 (KP_1) 0xff57 (End)
+ 97 0xff54 (Down) 0xffdf (F34) 0xffb2 (KP_2)
+ 98 0xffe0 (F35) 0xffe0 (F35) 0xffb3 (KP_3) 0xff56 (Next)
+ 99 0xff51 (Left) 0xffdb (F30) 0xffb4 (KP_4)
+ 100 0xffdc (F31) 0xffdc (F31) 0xffb5 (KP_5)
+ 101 0xff53 (Right) 0xffdd (F32) 0xffb6 (KP_6)
+ 102 0xffd8 (F27) 0xffd8 (F27) 0xffb7 (KP_7) 0xff50 (Home)
+ 103 0xff52 (Up) 0xffd9 (F28) 0xffb8 (KP_8)
+ 104 0xffda (F29) 0xffda (F29) 0xffb9 (KP_9) 0xff55 (Prior)
+ 105 0xff9e (KP_Insert) 0xff9e (KP_Insert) 0xffb0 (KP_0)
+ 106 0xffff (Delete) 0xffff (Delete) 0xffac (KP_Separator)
+ 107 0x003c (less) 0x003e (greater) 0x007c (bar)
+ 108 0xff20 (Multi_key)
+ 109 0x1005ff76 (SunPowerSwitch) 0x1005ff7d (SunPowerSwitchShift)
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123 0xffce (F17) 0xffce (F17) 0x1005ff73 (SunOpen)
+ 124 0xff6a (Help)
+ 125 0xffca (F13) 0xffca (F13) 0x1005ff70 (SunProps)
+ 126 0xffcc (F15) 0xffcc (F15) 0x1005ff71 (SunFront)
+ 127 0xffc8 (F11) 0xffc8 (F11) 0xff69 (Cancel)
+ 128 0xffc9 (F12) 0xffc9 (F12) 0xff66 (Redo)
+ 129 0xffcb (F14) 0xffcb (F14) 0xff65 (Undo)
+ 130 0xffd1 (F20) 0xffd1 (F20) 0x1005ff75 (SunCut)
+ 131 0xffcd (F16) 0xffcd (F16) 0x1005ff72 (SunCopy)
+ 132 0xffcf (F18) 0xffcf (F18) 0x1005ff74 (SunPaste)
+ 133 0xffd0 (F19) 0xffd0 (F19) 0xff68 (Find)
+ 134 0x1005ff78 (SunAudioMute) 0x1005ff7a (SunVideoDegauss)
+ 135 0x1005ff79 (SunAudioRaiseVolume) 0x1005ff7c (SunVideoRaiseBrightness)
+ 136 0x1005ff77 (SunAudioLowerVolume) 0x1005ff7b (SunVideoLowerBrightness)
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231 0xffe3 (Control_L)
+ 232 0xffe1 (Shift_L)
+ 233 0xffe9 (Alt_L)
+ 234 0xffe7 (Meta_L)
+ 235
+ 236 0xffe2 (Shift_R)
+ 237 0xff7e (Mode_switch)
+ 238 0xffe8 (Meta_R)
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl
new file mode 100644
index 0000000000..bfe54a3e75
--- /dev/null
+++ b/lib/ssh/test/ssh_sftpd_SUITE.erl
@@ -0,0 +1,934 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(ssh_sftpd_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include("test_server_line.hrl").
+-include("ssh_xfer.hrl").
+-include("ssh.hrl").
+
+-include_lib("kernel/include/file.hrl").
+
+-define(SFPD_PORT, 9999).
+-define(USER, "Alladin").
+-define(PASSWD, "Sesame").
+-define(XFER_PACKET_SIZE, 32768).
+-define(XFER_WINDOW_SIZE, 4*?XFER_PACKET_SIZE).
+-define(TIMEOUT, 10000).
+-define(REG_ATTERS, <<0,0,0,0,1>>).
+-define(UNIX_EPOCH, 62167219200).
+
+-define(is_set(F, Bits),
+ ((F) band (Bits)) == (F)).
+
+%% Test server callback functions
+%%--------------------------------------------------------------------
+%% 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) ->
+ case {catch ssh:stop(),catch crypto:start()} of
+ {ok,ok} ->
+ ssh_test_lib:make_dsa_files(Config),
+ Config;
+ {ok,_} ->
+ {skip,"Could not start ssh!"};
+ {_,ok} ->
+ {skip,"Could not start crypto!"};
+ {_,_} ->
+ {skip,"Could not start crypto and ssh!"}
+ end.
+
+%%--------------------------------------------------------------------
+%% 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) ->
+ crypto:stop(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% 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: Initiation 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: Initiation before each test case
+%%--------------------------------------------------------------------
+init_per_testcase(TestCase, Config) ->
+ ssh:start(),
+ prep(Config),
+ SysDir = ?config(data_dir, Config),
+ {ok, Sftpd} =
+ ssh_sftpd:listen(?SFPD_PORT, [{system_dir, SysDir},
+ {user_passwords,[{?USER, ?PASSWD}]},
+ {pwdfun, fun(_,_) -> true end}]),
+
+ Cm = ssh_test_lib:connect(?SFPD_PORT,
+ [{system_dir, SysDir},
+ {user_dir, SysDir},
+ {user, ?USER}, {password, ?PASSWD},
+ {user_interaction, false},
+ {silently_accept_hosts, true},
+ {pwdfun, fun(_,_) -> true end}]),
+ {ok, Channel} =
+ ssh_connection:session_channel(Cm, ?XFER_WINDOW_SIZE,
+ ?XFER_PACKET_SIZE, ?TIMEOUT),
+
+ success = ssh_connection:subsystem(Cm, Channel, "sftp", ?TIMEOUT),
+
+ ProtocolVer = case atom_to_list(TestCase) of
+ "ver3_" ++ _ ->
+ 3;
+ _ ->
+ ?SSH_SFTP_PROTOCOL_VERSION
+ end,
+
+ Data = <<?UINT32(ProtocolVer)>> ,
+
+ Size = 1 + size(Data),
+
+ ssh_connection:send(Cm, Channel, << ?UINT32(Size),
+ ?SSH_FXP_INIT, Data/binary >>),
+
+ {ok, <<?SSH_FXP_VERSION, ?UINT32(Version), _Ext/binary>>, _}
+ = reply(Cm, Channel),
+
+ test_server:format("Client: ~p Server ~p~n", [ProtocolVer, Version]),
+
+ [{sftp, {Cm, Channel}}, {sftpd, Sftpd }| 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(_TestCase, Config) ->
+ ssh_sftpd:stop(?config(sftpd, Config)),
+ {Cm, Channel} = ?config(sftp, Config),
+ ssh_connection:close(Cm, Channel),
+ ssh:close(Cm),
+ ssh:stop(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% 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() ->
+ [open_close_file, open_close_dir, read_file, read_dir,
+ write_file, rename_file, mk_rm_dir, remove_file,
+ real_path, retrieve_attributes, set_attributes, links,
+ ver3_rename_OTP_6352, seq10670, sshd_read_file].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+%% Test cases starts here.
+%%--------------------------------------------------------------------
+open_close_file(doc) ->
+ ["Test SSH_FXP_OPEN and SSH_FXP_CLOSE commands"];
+open_close_file(suite) ->
+ [];
+open_close_file(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "test.txt"),
+ {Cm, Channel} = ?config(sftp, Config),
+ ReqId = 0,
+
+ {ok, <<?SSH_FXP_HANDLE, ?UINT32(ReqId), Handle/binary>>, _} =
+ open_file(FileName, Cm, Channel, ReqId,
+ ?ACE4_READ_DATA bor ?ACE4_READ_ATTRIBUTES,
+ ?SSH_FXF_OPEN_EXISTING),
+
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId),
+ ?UINT32(?SSH_FX_OK), _/binary>>, _} = close(Handle, ReqId,
+ Cm, Channel),
+ NewReqId = ReqId + 1,
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId),
+ ?UINT32(?SSH_FX_INVALID_HANDLE), _/binary>>, _} =
+ close(Handle, ReqId, Cm, Channel),
+
+ NewReqId1 = NewReqId + 1,
+ %% {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId), % Ver 6 we have 5
+ %% ?UINT32(?SSH_FX_FILE_IS_A_DIRECTORY), _/binary>>, _} =
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId1),
+ ?UINT32(?SSH_FX_FAILURE), _/binary>>, _} =
+ open_file(PrivDir, Cm, Channel, NewReqId1,
+ ?ACE4_READ_DATA bor ?ACE4_READ_ATTRIBUTES,
+ ?SSH_FXF_OPEN_EXISTING),
+
+ ok.
+
+%%--------------------------------------------------------------------
+open_close_dir(doc) ->
+ ["Test SSH_FXP_OPENDIR and SSH_FXP_CLOSE commands"];
+open_close_dir(suite) ->
+ [];
+open_close_dir(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ {Cm, Channel} = ?config(sftp, Config),
+ FileName = filename:join(PrivDir, "test.txt"),
+ ReqId = 0,
+
+ {ok, <<?SSH_FXP_HANDLE, ?UINT32(ReqId), Handle/binary>>, _} =
+ open_dir(PrivDir, Cm, Channel, ReqId),
+
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId),
+ ?UINT32(?SSH_FX_OK), _/binary>>, _} = close(Handle, ReqId,
+ Cm, Channel),
+
+ NewReqId = 1,
+ case open_dir(FileName, Cm, Channel, NewReqId) of
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId),
+ ?UINT32(?SSH_FX_NOT_A_DIRECTORY), _/binary>>, _} ->
+ %% Only if server is using vsn > 5.
+ ok;
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId),
+ ?UINT32(?SSH_FX_FAILURE), _/binary>>, _} ->
+ ok
+ end.
+
+%%--------------------------------------------------------------------
+read_file(doc) ->
+ ["Test SSH_FXP_READ command"];
+read_file(suite) ->
+ [];
+read_file(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "test.txt"),
+
+ ReqId = 0,
+ {Cm, Channel} = ?config(sftp, Config),
+
+ {ok, <<?SSH_FXP_HANDLE, ?UINT32(ReqId), Handle/binary>>, _} =
+ open_file(FileName, Cm, Channel, ReqId,
+ ?ACE4_READ_DATA bor ?ACE4_READ_ATTRIBUTES,
+ ?SSH_FXF_OPEN_EXISTING),
+
+ NewReqId = 1,
+
+ {ok, <<?SSH_FXP_DATA, ?UINT32(NewReqId), ?UINT32(_Length),
+ Data/binary>>, _} =
+ read_file(Handle, 100, 0, Cm, Channel, NewReqId),
+
+ {ok, Data} = file:read_file(FileName),
+
+ ok.
+%%--------------------------------------------------------------------
+read_dir(doc) ->
+ ["Test SSH_FXP_READDIR command"];
+read_dir(suite) ->
+ [];
+read_dir(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ {Cm, Channel} = ?config(sftp, Config),
+ ReqId = 0,
+ {ok, <<?SSH_FXP_HANDLE, ?UINT32(ReqId), Handle/binary>>, _} =
+ open_dir(PrivDir, Cm, Channel, ReqId),
+ ok = read_dir(Handle, Cm, Channel, ReqId),
+ ok.
+
+%%--------------------------------------------------------------------
+write_file(doc) ->
+ ["Test SSH_FXP_WRITE command"];
+write_file(suite) ->
+ [];
+write_file(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "test.txt"),
+
+ ReqId = 0,
+ {Cm, Channel} = ?config(sftp, Config),
+
+ {ok, <<?SSH_FXP_HANDLE, ?UINT32(ReqId), Handle/binary>>, _} =
+ open_file(FileName, Cm, Channel, ReqId,
+ ?ACE4_WRITE_DATA bor ?ACE4_WRITE_ATTRIBUTES,
+ ?SSH_FXF_OPEN_EXISTING),
+
+ NewReqId = 1,
+ Data = list_to_binary("Write file test"),
+
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId), ?UINT32(?SSH_FX_OK),
+ _/binary>>, _}
+ = write_file(Handle, Data, 0, Cm, Channel, NewReqId),
+
+ {ok, Data} = file:read_file(FileName),
+
+ ok.
+
+%%--------------------------------------------------------------------
+remove_file(doc) ->
+ ["Test SSH_FXP_REMOVE command"];
+remove_file(suite) ->
+ [];
+remove_file(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "test.txt"),
+ ReqId = 0,
+ {Cm, Channel} = ?config(sftp, Config),
+
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId),
+ ?UINT32(?SSH_FX_OK), _/binary>>, _} =
+ remove(FileName, Cm, Channel, ReqId),
+
+ NewReqId = 1,
+ %% {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId), % ver 6 we have 5
+ %% ?UINT32(?SSH_FX_FILE_IS_A_DIRECTORY ), _/binary>>, _} =
+
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId),
+ ?UINT32(?SSH_FX_FAILURE), _/binary>>, _} =
+ remove(PrivDir, Cm, Channel, NewReqId),
+
+ ok.
+
+%%--------------------------------------------------------------------
+rename_file(doc) ->
+ ["Test SSH_FXP_RENAME command"];
+rename_file(suite) ->
+ [];
+rename_file(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "test.txt"),
+ NewFileName = filename:join(PrivDir, "test1.txt"),
+ ReqId = 0,
+ {Cm, Channel} = ?config(sftp, Config),
+
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId),
+ ?UINT32(?SSH_FX_OK), _/binary>>, _} =
+ rename(FileName, NewFileName, Cm, Channel, ReqId, 6, 0),
+
+ NewReqId = ReqId + 1,
+
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId),
+ ?UINT32(?SSH_FX_OK), _/binary>>, _} =
+ rename(NewFileName, FileName, Cm, Channel, NewReqId, 6,
+ ?SSH_FXP_RENAME_OVERWRITE),
+
+ NewReqId1 = NewReqId + 1,
+ file:copy(FileName, NewFileName),
+
+ %% No owerwrite
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId1),
+ ?UINT32(?SSH_FX_FILE_ALREADY_EXISTS), _/binary>>, _} =
+ rename(FileName, NewFileName, Cm, Channel, NewReqId1, 6,
+ ?SSH_FXP_RENAME_NATIVE),
+
+ NewReqId2 = NewReqId1 + 1,
+
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId2),
+ ?UINT32(?SSH_FX_OP_UNSUPPORTED), _/binary>>, _} =
+ rename(FileName, NewFileName, Cm, Channel, NewReqId2, 6,
+ ?SSH_FXP_RENAME_ATOMIC),
+
+ ok.
+
+%%--------------------------------------------------------------------
+mk_rm_dir(doc) ->
+ ["Test SSH_FXP_MKDIR and SSH_FXP_RMDIR command"];
+mk_rm_dir(suite) ->
+ [];
+mk_rm_dir(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ {Cm, Channel} = ?config(sftp, Config),
+ DirName = filename:join(PrivDir, "test"),
+ ReqId = 0,
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId), ?UINT32(?SSH_FX_OK),
+ _/binary>>, _} = mkdir(DirName, Cm, Channel, ReqId),
+
+ NewReqId = 1,
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId), ?UINT32(?SSH_FX_FAILURE),
+ _/binary>>, _} = mkdir(DirName, Cm, Channel, NewReqId),
+
+ NewReqId1 = 2,
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId1), ?UINT32(?SSH_FX_OK),
+ _/binary>>, _} = rmdir(DirName, Cm, Channel, NewReqId1),
+
+ NewReqId2 = 3,
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId2), ?UINT32(?SSH_FX_NO_SUCH_FILE),
+ _/binary>>, _} = rmdir(DirName, Cm, Channel, NewReqId2),
+
+ ok.
+%%--------------------------------------------------------------------
+real_path(doc) ->
+ ["Test SSH_FXP_REALPATH command"];
+real_path(suite) ->
+ [];
+real_path(Config) when is_list(Config) ->
+ case test_server:os_type() of
+ {win32, _} ->
+ {skip, "Not a relevant test on windows"};
+ _ ->
+ ReqId = 0,
+ {Cm, Channel} = ?config(sftp, Config),
+ PrivDir = ?config(priv_dir, Config),
+ TestDir = filename:join(PrivDir, "ssh_test"),
+ ok = file:make_dir(TestDir),
+
+ OrigPath = filename:join(TestDir, ".."),
+
+ {ok, <<?SSH_FXP_NAME, ?UINT32(ReqId), ?UINT32(_), ?UINT32(Len),
+ Path:Len/binary, _/binary>>, _}
+ = real_path(OrigPath, Cm, Channel, ReqId),
+
+ RealPath = filename:absname(binary_to_list(Path)),
+ AbsPrivDir = filename:absname(PrivDir),
+
+ test_server:format("Path: ~p PrivDir: ~p~n", [RealPath, AbsPrivDir]),
+
+ true = RealPath == AbsPrivDir,
+
+ ok
+ end.
+
+%%--------------------------------------------------------------------
+links(doc) ->
+ [];
+links(suite) ->
+ [];
+links(Config) when is_list(Config) ->
+ case test_server:os_type() of
+ {win32, _} ->
+ {skip, "Links are not fully supported by windows"};
+ _ ->
+ ReqId = 0,
+ {Cm, Channel} = ?config(sftp, Config),
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "test.txt"),
+ LinkFileName = filename:join(PrivDir, "link_test.txt"),
+
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId),
+ ?UINT32(?SSH_FX_OK), _/binary>>, _} =
+ create_link(LinkFileName, FileName, Cm, Channel, ReqId),
+
+ NewReqId = 1,
+ {ok, <<?SSH_FXP_NAME, ?UINT32(NewReqId), ?UINT32(_), ?UINT32(Len),
+ Path:Len/binary, _/binary>>, _}
+ = read_link(LinkFileName, Cm, Channel, NewReqId),
+
+
+ true = binary_to_list(Path) == FileName,
+
+ test_server:format("Path: ~p~n", [binary_to_list(Path)]),
+ ok
+ end.
+
+%%--------------------------------------------------------------------
+retrieve_attributes(doc) ->
+ ["Test SSH_FXP_STAT, SSH_FXP_LSTAT AND SSH_FXP_FSTAT commands"];
+retrieve_attributes(suite) ->
+ [];
+retrieve_attributes(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "test.txt"),
+ ReqId = 0,
+ {Cm, Channel} = ?config(sftp, Config),
+
+ {ok, FileInfo} = file:read_file_info(FileName),
+
+ AttrValues =
+ retrive_attributes(FileName, Cm, Channel, ReqId),
+
+ Type = encode_file_type(FileInfo#file_info.type),
+ Size = FileInfo#file_info.size,
+ Owner = FileInfo#file_info.uid,
+ Group = FileInfo#file_info.gid,
+ Permissions = FileInfo#file_info.mode,
+ Atime = calendar:datetime_to_gregorian_seconds(
+ erlang:localtime_to_universaltime(FileInfo#file_info.atime))
+ - ?UNIX_EPOCH,
+ Mtime = calendar:datetime_to_gregorian_seconds(
+ erlang:localtime_to_universaltime(FileInfo#file_info.mtime))
+ - ?UNIX_EPOCH,
+ Ctime = calendar:datetime_to_gregorian_seconds(
+ erlang:localtime_to_universaltime(FileInfo#file_info.ctime))
+ - ?UNIX_EPOCH,
+
+ lists:foreach(fun(Value) ->
+ <<?UINT32(Flags), _/binary>> = Value,
+ true = ?is_set(?SSH_FILEXFER_ATTR_SIZE,
+ Flags),
+ true = ?is_set(?SSH_FILEXFER_ATTR_PERMISSIONS,
+ Flags),
+ true = ?is_set(?SSH_FILEXFER_ATTR_ACCESSTIME,
+ Flags),
+ true = ?is_set(?SSH_FILEXFER_ATTR_CREATETIME,
+ Flags),
+ true = ?is_set(?SSH_FILEXFER_ATTR_MODIFYTIME,
+ Flags),
+ true = ?is_set(?SSH_FILEXFER_ATTR_OWNERGROUP,
+ Flags),
+ false = ?is_set(?SSH_FILEXFER_ATTR_ACL,
+ Flags),
+ false = ?is_set(?SSH_FILEXFER_ATTR_SUBSECOND_TIMES,
+ Flags),
+ false = ?is_set(?SSH_FILEXFER_ATTR_BITS,
+ Flags),
+ false = ?is_set(?SSH_FILEXFER_ATTR_EXTENDED,
+ Flags),
+
+ <<?UINT32(_Flags), ?BYTE(Type),
+ ?UINT64(Size),
+ ?UINT32(OwnerLen), BinOwner:OwnerLen/binary,
+ ?UINT32(GroupLen), BinGroup:GroupLen/binary,
+ ?UINT32(Permissions),
+ ?UINT64(Atime),
+ ?UINT64(Ctime),
+ ?UINT64(Mtime)>> = Value,
+
+ Owner = list_to_integer(binary_to_list(BinOwner)),
+ Group = list_to_integer(binary_to_list(BinGroup))
+ end, AttrValues),
+
+ ok.
+%%--------------------------------------------------------------------
+set_attributes(doc) ->
+ ["Test SSH_FXP_SETSTAT AND SSH_FXP_FSETSTAT commands"];
+set_attributes(suite) ->
+ [];
+set_attributes(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "test.txt"),
+ ReqId = 0,
+ {Cm, Channel} = ?config(sftp, Config),
+
+ {ok, FileInfo} = file:read_file_info(FileName),
+
+ OrigPermissions = FileInfo#file_info.mode,
+ Permissions = 8#400, %% User read-only
+
+ Flags = ?SSH_FILEXFER_ATTR_PERMISSIONS,
+
+ Atters = [?uint32(Flags), ?byte(?SSH_FILEXFER_TYPE_REGULAR),
+ ?uint32(Permissions)],
+
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId),
+ ?UINT32(?SSH_FX_OK), _/binary>>, _} =
+ set_attributes_file(FileName, Atters, Cm, Channel, ReqId),
+
+ {ok, NewFileInfo} = file:read_file_info(FileName),
+ NewPermissions = NewFileInfo#file_info.mode,
+
+ %% Can not test that NewPermissions = Permissions as
+ %% on Unix platforms, other bits than those listed in the
+ %% API may be set.
+ test_server:format("Org: ~p New: ~p~n", [OrigPermissions, NewPermissions]),
+ true = OrigPermissions =/= NewPermissions,
+
+ test_server:format("Try to open the file"),
+ NewReqId = 2,
+ {ok, <<?SSH_FXP_HANDLE, ?UINT32(NewReqId), Handle/binary>>, _} =
+ open_file(FileName, Cm, Channel, NewReqId,
+ ?ACE4_READ_DATA bor ?ACE4_WRITE_ATTRIBUTES,
+ ?SSH_FXF_OPEN_EXISTING),
+
+ NewAtters = [?uint32(Flags), ?byte(?SSH_FILEXFER_TYPE_REGULAR),
+ ?uint32(OrigPermissions)],
+
+ NewReqId1 = 3,
+
+ test_server:format("Set original permissions on the now open file"),
+
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId1),
+ ?UINT32(?SSH_FX_OK), _/binary>>, _} =
+ set_attributes_open_file(Handle, NewAtters, Cm, Channel, NewReqId1),
+
+ {ok, NewFileInfo1} = file:read_file_info(FileName),
+ OrigPermissions = NewFileInfo1#file_info.mode,
+
+ ok.
+
+%%--------------------------------------------------------------------
+ver3_rename_OTP_6352(doc) ->
+ ["Test that ver3 rename message is handled"];
+
+ver3_rename_OTP_6352(suite) ->
+ [];
+
+ver3_rename_OTP_6352(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "test.txt"),
+ NewFileName = filename:join(PrivDir, "test1.txt"),
+ ReqId = 0,
+ {Cm, Channel} = ?config(sftp, Config),
+
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId),
+ ?UINT32(?SSH_FX_OK), _/binary>>, _} =
+ rename(FileName, NewFileName, Cm, Channel, ReqId, 3, 0),
+
+ ok.
+
+%%--------------------------------------------------------------------
+seq10670(doc) ->
+ ["Check that realpath works ok"];
+
+seq10670(suite) ->
+ [];
+
+seq10670(Config) when is_list(Config) ->
+ ReqId = 0,
+ {Cm, Channel} = ?config(sftp, Config),
+
+ case test_server:os_type() of
+ {win32, _} ->
+ {skip, "Not a relevant test on windows"};
+ _ ->
+ {ok, <<?SSH_FXP_NAME, ?UINT32(ReqId), ?UINT32(_), ?UINT32(Len),
+ Root:Len/binary, _/binary>>, _}
+ = real_path("/..", Cm, Channel, ReqId),
+
+ <<"/">> = Root,
+
+ {ok, <<?SSH_FXP_NAME, ?UINT32(ReqId), ?UINT32(_), ?UINT32(Len),
+ Path:Len/binary, _/binary>>, _}
+ = real_path("/usr/bin/../..", Cm, Channel, ReqId),
+
+ Root = Path
+ end.
+
+%% Internal functions
+%%--------------------------------------------------------------------
+prep(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ TestFile = filename:join(PrivDir, "test.txt"),
+ TestFile1 = filename:join(PrivDir, "test1.txt"),
+
+ file:delete(TestFile),
+ file:delete(TestFile1),
+
+ %% Initial config
+ DataDir = ?config(data_dir, Config),
+ FileName = filename:join(DataDir, "test.txt"),
+ file:copy(FileName, TestFile),
+ Mode = 8#00400 bor 8#00200 bor 8#00040, % read & write owner, read group
+ {ok, FileInfo} = file:read_file_info(TestFile),
+ ok = file:write_file_info(TestFile,
+ FileInfo#file_info{mode = Mode}).
+
+reply(Cm, Channel) ->
+ reply(Cm, Channel,<<>>).
+
+reply(Cm, Channel, RBuf) ->
+ receive
+ {ssh_cm, Cm, {data, Channel, 0, Data}} ->
+ case <<RBuf/binary, Data/binary>> of
+ <<?UINT32(Len),Reply:Len/binary,Rest/binary>> ->
+ {ok, Reply, Rest};
+ RBuf2 ->
+ reply(Cm, Channel, RBuf2)
+ end;
+ {ssh_cm, Cm, {eof, Channel}} ->
+ eof;
+ {ssh_cm, Cm, {closed, Channel}} ->
+ closed;
+ {ssh_cm, Cm, Msg} ->
+ test_server:fail(Msg)
+ end.
+
+
+open_file(File, Cm, Channel, ReqId, Access, Flags) ->
+
+ Data = list_to_binary([?uint32(ReqId),
+ ?binary(list_to_binary(File)),
+ ?uint32(Access),
+ ?uint32(Flags),
+ ?REG_ATTERS]),
+ Size = 1 + size(Data),
+ ssh_connection:send(Cm, Channel, <<?UINT32(Size),
+ ?SSH_FXP_OPEN, Data/binary>>),
+ reply(Cm, Channel).
+
+
+
+close(Handle, ReqId, Cm , Channel) ->
+ Data = list_to_binary([?uint32(ReqId), Handle]),
+
+ Size = 1 + size(Data),
+
+ ssh_connection:send(Cm, Channel, <<?UINT32(Size), ?SSH_FXP_CLOSE,
+ Data/binary>>),
+
+ reply(Cm, Channel).
+
+
+
+open_dir(Dir, Cm, Channel, ReqId) ->
+ Data = list_to_binary([?uint32(ReqId),
+ ?binary(list_to_binary(Dir))]),
+ Size = 1 + size(Data),
+ ssh_connection:send(Cm, Channel, <<?UINT32(Size),
+ ?SSH_FXP_OPENDIR, Data/binary>>),
+ reply(Cm, Channel).
+
+
+rename(OldName, NewName, Cm, Channel, ReqId, Version, Flags) ->
+ Data =
+ case Version of
+ 3 ->
+ list_to_binary([?uint32(ReqId),
+ ?binary(list_to_binary(OldName)),
+ ?binary(list_to_binary(NewName))]);
+ _ ->
+ list_to_binary([?uint32(ReqId),
+ ?binary(list_to_binary(OldName)),
+ ?binary(list_to_binary(NewName)),
+ ?uint32(Flags)])
+ end,
+ Size = 1 + size(Data),
+ ssh_connection:send(Cm, Channel, <<?UINT32(Size),
+ ?SSH_FXP_RENAME, Data/binary>>),
+ reply(Cm, Channel).
+
+
+mkdir(Dir, Cm, Channel, ReqId)->
+ Data = list_to_binary([?uint32(ReqId),
+ ?binary(list_to_binary(Dir)),
+ ?REG_ATTERS]),
+ Size = 1 + size(Data),
+ ssh_connection:send(Cm, Channel, <<?UINT32(Size),
+ ?SSH_FXP_MKDIR, Data/binary>>),
+ reply(Cm, Channel).
+
+
+rmdir(Dir, Cm, Channel, ReqId) ->
+ Data = list_to_binary([?uint32(ReqId),
+ ?binary(list_to_binary(Dir))]),
+ Size = 1 + size(Data),
+ ssh_connection:send(Cm, Channel, <<?UINT32(Size),
+ ?SSH_FXP_RMDIR, Data/binary>>),
+ reply(Cm, Channel).
+
+remove(File, Cm, Channel, ReqId) ->
+ Data = list_to_binary([?uint32(ReqId),
+ ?binary(list_to_binary(File))]),
+ Size = 1 + size(Data),
+ ssh_connection:send(Cm, Channel, <<?UINT32(Size),
+ ?SSH_FXP_REMOVE, Data/binary>>),
+ reply(Cm, Channel).
+
+
+read_dir(Handle, Cm, Channel, ReqId) ->
+
+ Data = list_to_binary([?uint32(ReqId), Handle]),
+ Size = 1 + size(Data),
+ ssh_connection:send(Cm, Channel, <<?UINT32(Size),
+ ?SSH_FXP_READDIR, Data/binary>>),
+ case reply(Cm, Channel) of
+ {ok, <<?SSH_FXP_NAME, ?UINT32(ReqId), ?UINT32(Count),
+ ?UINT32(Len), Listing:Len/binary, _/binary>>, _} ->
+ test_server:format("Count: ~p Listing: ~p~n",
+ [Count, binary_to_list(Listing)]),
+ read_dir(Handle, Cm, Channel, ReqId);
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId),
+ ?UINT32(?SSH_FX_EOF), _/binary>>, _} ->
+ ok
+ end.
+
+read_file(Handle, MaxLength, OffSet, Cm, Channel, ReqId) ->
+ Data = list_to_binary([?uint32(ReqId), Handle,
+ ?uint64(OffSet),
+ ?uint32(MaxLength)]),
+ Size = 1 + size(Data),
+ ssh_connection:send(Cm, Channel, <<?UINT32(Size),
+ ?SSH_FXP_READ, Data/binary>>),
+ reply(Cm, Channel).
+
+
+write_file(Handle, FileData, OffSet, Cm, Channel, ReqId) ->
+ Data = list_to_binary([?uint32(ReqId), Handle,
+ ?uint64(OffSet),
+ ?binary(FileData)]),
+ Size = 1 + size(Data),
+ ssh_connection:send(Cm, Channel, <<?UINT32(Size),
+ ?SSH_FXP_WRITE, Data/binary>>),
+ reply(Cm, Channel).
+
+
+real_path(OrigPath, Cm, Channel, ReqId) ->
+ Data = list_to_binary([?uint32(ReqId),
+ ?binary(list_to_binary(OrigPath))]),
+ Size = 1 + size(Data),
+ ssh_connection:send(Cm, Channel, <<?UINT32(Size),
+ ?SSH_FXP_REALPATH, Data/binary>>),
+ reply(Cm, Channel).
+
+create_link(LinkPath, Path, Cm, Channel, ReqId) ->
+ Data = list_to_binary([?uint32(ReqId),
+ ?binary(list_to_binary(LinkPath)),
+ ?binary(list_to_binary(Path))]),
+ Size = 1 + size(Data),
+ ssh_connection:send(Cm, Channel, <<?UINT32(Size),
+ ?SSH_FXP_SYMLINK, Data/binary>>),
+ reply(Cm, Channel).
+
+
+read_link(Link, Cm, Channel, ReqId) ->
+ Data = list_to_binary([?uint32(ReqId),
+ ?binary(list_to_binary(Link))]),
+ Size = 1 + size(Data),
+ ssh_connection:send(Cm, Channel, <<?UINT32(Size),
+ ?SSH_FXP_READLINK, Data/binary>>),
+ reply(Cm, Channel).
+
+retrive_attributes_file(FilePath, Flags, Cm, Channel, ReqId) ->
+ Data = list_to_binary([?uint32(ReqId),
+ ?binary(list_to_binary(FilePath)),
+ ?uint32(Flags)]),
+ Size = 1 + size(Data),
+ ssh_connection:send(Cm, Channel, <<?UINT32(Size),
+ ?SSH_FXP_STAT, Data/binary>>),
+ reply(Cm, Channel).
+
+retrive_attributes_file_or_link(FilePath, Flags, Cm, Channel, ReqId) ->
+ Data = list_to_binary([?uint32(ReqId),
+ ?binary(list_to_binary(FilePath)),
+ ?uint32(Flags)]),
+ Size = 1 + size(Data),
+ ssh_connection:send(Cm, Channel, <<?UINT32(Size),
+ ?SSH_FXP_LSTAT, Data/binary>>),
+ reply(Cm, Channel).
+
+retrive_attributes_open_file(Handle, Flags, Cm, Channel, ReqId) ->
+
+ Data = list_to_binary([?uint32(ReqId),
+ Handle,
+ ?uint32(Flags)]),
+ Size = 1 + size(Data),
+ ssh_connection:send(Cm, Channel, <<?UINT32(Size),
+ ?SSH_FXP_FSTAT, Data/binary>>),
+ reply(Cm, Channel).
+
+retrive_attributes(FileName, Cm, Channel, ReqId) ->
+
+ Attr = ?SSH_FILEXFER_ATTR_SIZE,
+
+ {ok, <<?SSH_FXP_ATTRS, ?UINT32(ReqId), Value/binary>>, _}
+ = retrive_attributes_file(FileName, Attr,
+ Cm, Channel, ReqId),
+
+ NewReqId = ReqId + 1,
+ {ok, <<?SSH_FXP_ATTRS, ?UINT32(NewReqId), Value1/binary>>, _}
+ = retrive_attributes_file_or_link(FileName,
+ Attr, Cm, Channel, NewReqId),
+
+ NewReqId1 = NewReqId + 1,
+ {ok, <<?SSH_FXP_HANDLE, ?UINT32(NewReqId1), Handle/binary>>, _} =
+ open_file(FileName, Cm, Channel, NewReqId1,
+ ?ACE4_READ_DATA bor ?ACE4_READ_ATTRIBUTES,
+ ?SSH_FXF_OPEN_EXISTING),
+
+ NewReqId2 = NewReqId1 + 1,
+ {ok, <<?SSH_FXP_ATTRS, ?UINT32(NewReqId2), Value2/binary>>, _}
+ = retrive_attributes_open_file(Handle, Attr, Cm, Channel, NewReqId2),
+
+ [Value, Value1, Value2].
+
+set_attributes_file(FilePath, Atters, Cm, Channel, ReqId) ->
+ Data = list_to_binary([?uint32(ReqId),
+ ?binary(list_to_binary(FilePath)),
+ Atters]),
+ Size = 1 + size(Data),
+ ssh_connection:send(Cm, Channel, <<?UINT32(Size),
+ ?SSH_FXP_SETSTAT, Data/binary>>),
+ reply(Cm, Channel).
+
+
+set_attributes_open_file(Handle, Atters, Cm, Channel, ReqId) ->
+
+ Data = list_to_binary([?uint32(ReqId),
+ Handle,
+ Atters]),
+ Size = 1 + size(Data),
+ ssh_connection:send(Cm, Channel, <<?UINT32(Size),
+ ?SSH_FXP_FSETSTAT, Data/binary>>),
+ reply(Cm, Channel).
+
+
+encode_file_type(Type) ->
+ case Type of
+ regular -> ?SSH_FILEXFER_TYPE_REGULAR;
+ directory -> ?SSH_FILEXFER_TYPE_DIRECTORY;
+ symlink -> ?SSH_FILEXFER_TYPE_SYMLINK;
+ special -> ?SSH_FILEXFER_TYPE_SPECIAL;
+ unknown -> ?SSH_FILEXFER_TYPE_UNKNOWN;
+ other -> ?SSH_FILEXFER_TYPE_UNKNOWN;
+ socket -> ?SSH_FILEXFER_TYPE_SOCKET;
+ char_device -> ?SSH_FILEXFER_TYPE_CHAR_DEVICE;
+ block_device -> ?SSH_FILEXFER_TYPE_BLOCK_DEVICE;
+ fifo -> ?SSH_FILEXFER_TYPE_FIFO;
+ undefined -> ?SSH_FILEXFER_TYPE_UNKNOWN
+ end.
+
+%%--------------------------------------------------------------------
+sshd_read_file(doc) ->
+ ["Test SSH_FXP_READ command, using sshd-server"];
+sshd_read_file(suite) ->
+ [];
+sshd_read_file(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(PrivDir, "test.txt"),
+
+ ReqId = 0,
+ {Cm, Channel} = ?config(sftp, Config),
+
+ {ok, <<?SSH_FXP_HANDLE, ?UINT32(ReqId), Handle/binary>>, _} =
+ open_file(FileName, Cm, Channel, ReqId,
+ ?ACE4_READ_DATA bor ?ACE4_READ_ATTRIBUTES,
+ ?SSH_FXF_OPEN_EXISTING),
+
+ NewReqId = 1,
+
+ {ok, <<?SSH_FXP_DATA, ?UINT32(NewReqId), ?UINT32(_Length),
+ Data/binary>>, _} =
+ read_file(Handle, 100, 0, Cm, Channel, NewReqId),
+
+ {ok, Data} = file:read_file(FileName),
+
+ ok.
diff --git a/lib/ssh/test/ssh_sftpd_SUITE_data/test.txt b/lib/ssh/test/ssh_sftpd_SUITE_data/test.txt
new file mode 100644
index 0000000000..681bff80a0
--- /dev/null
+++ b/lib/ssh/test/ssh_sftpd_SUITE_data/test.txt
@@ -0,0 +1 @@
+Sftp test file. \ No newline at end of file
diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
new file mode 100644
index 0000000000..2209af05d5
--- /dev/null
+++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
@@ -0,0 +1,328 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(ssh_sftpd_erlclient_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include("test_server_line.hrl").
+
+-include_lib("kernel/include/file.hrl").
+
+-define(SSHD_PORT, 9999).
+-define(USER, "Alladin").
+-define(PASSWD, "Sesame").
+-define(SSH_MAX_PACKET_SIZE, 32768).
+
+%% Test server callback functions
+%%--------------------------------------------------------------------
+%% 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) ->
+ catch ssh:stop(),
+ case catch crypto:start() of
+ ok ->
+ DataDir = ?config(data_dir, Config),
+ FileAlt = filename:join(DataDir, "ssh_sftpd_file_alt.erl"),
+ c:c(FileAlt),
+ FileName = filename:join(DataDir, "test.txt"),
+ {ok, FileInfo} = file:read_file_info(FileName),
+ ok = file:write_file_info(FileName,
+ FileInfo#file_info{mode = 8#400}),
+ ssh_test_lib:make_dsa_files(Config),
+ Config;
+ _Else ->
+ {skip,"Could not start ssh!"}
+ end.
+
+%%--------------------------------------------------------------------
+%% 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) ->
+ crypto:stop(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% 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: Initiation 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: Initiation before each test case
+%%--------------------------------------------------------------------
+init_per_testcase(TestCase, Config) ->
+ ssh:start(),
+ DataDir = ?config(data_dir, Config),
+
+ Options =
+ case atom_to_list(TestCase) of
+ "file_cb" ++ _ ->
+ Spec =
+ ssh_sftpd:subsystem_spec([{file_handler,
+ ssh_sftpd_file_alt}]),
+ [{user_passwords,[{?USER, ?PASSWD}]},
+ {pwdfun, fun(_,_) -> true end},
+ {system_dir, DataDir},
+ {user_dir, DataDir},
+ {subsystems, [Spec]}];
+ "root_dir" ->
+ Privdir = ?config(priv_dir, Config),
+ Root = filename:join(Privdir, root),
+ file:make_dir(Root),
+ Spec = ssh_sftpd:subsystem_spec([{root,Root}]),
+ [{user_passwords,[{?USER, ?PASSWD}]},
+ {pwdfun, fun(_,_) -> true end},
+ {system_dir, DataDir},
+ {user_dir, DataDir},
+ {subsystems, [Spec]}];
+ "list_dir_limited" ->
+ Spec =
+ ssh_sftpd:subsystem_spec([{max_files,1}]),
+ [{user_passwords,[{?USER, ?PASSWD}]},
+ {pwdfun, fun(_,_) -> true end},
+ {system_dir, DataDir},
+ {user_dir, DataDir},
+ {subsystems, [Spec]}];
+
+ _ ->
+ [{user_passwords,[{?USER, ?PASSWD}]},
+ {pwdfun, fun(_,_) -> true end},
+ {user_dir, DataDir},
+ {system_dir, DataDir}]
+ end,
+
+ {Sftpd, Host, _Port} = ssh_test_lib:daemon(any, ?SSHD_PORT, Options),
+
+ {ok, ChannelPid, Connection} =
+ ssh_sftp:start_channel(Host, ?SSHD_PORT,
+ [{silently_accept_hosts, true},
+ {user, ?USER}, {password, ?PASSWD},
+ {pwdfun, fun(_,_) -> true end},
+ {system_dir, DataDir},
+ {user_dir, DataDir},
+ {timeout, 30000}]),
+ TmpConfig = lists:keydelete(sftp, 1, Config),
+ NewConfig = lists:keydelete(sftpd, 1, TmpConfig),
+ [{sftp, {ChannelPid, Connection}}, {sftpd, Sftpd} | NewConfig].
+
+%%--------------------------------------------------------------------
+%% 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(_TestCase, Config) ->
+ catch ssh_sftpd:stop(?config(sftpd, Config)),
+ {Sftp, Connection} = ?config(sftp, Config),
+ catch ssh_sftp:stop_channel(Sftp),
+ catch ssh:close(Connection),
+ ssh:stop(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% 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() ->
+ [close_file_OTP_6350, quit_OTP_6349, file_cb_OTP_6356,
+ root_dir, list_dir_limited].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+%% Test cases starts here.
+%%--------------------------------------------------------------------
+close_file_OTP_6350(doc) ->
+ ["Test that sftpd closes its fildescriptors after compleating the "
+ "transfer"];
+
+close_file_OTP_6350(suite) ->
+ [];
+
+close_file_OTP_6350(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ FileName = filename:join(DataDir, "test.txt"),
+
+ {Sftp, _} = ?config(sftp, Config),
+
+ NumOfPorts = length(erlang:ports()),
+
+ test_server:format("Number of open ports: ~p~n", [NumOfPorts]),
+
+ {ok, <<_/binary>>} = ssh_sftp:read_file(Sftp, FileName),
+
+ NumOfPorts = length(erlang:ports()),
+
+ test_server:format("Number of open ports: ~p~n",
+ [length(erlang:ports())]),
+
+ ok.
+
+%%--------------------------------------------------------------------
+
+quit_OTP_6349(doc) ->
+ [" When the sftp client ends the session the "
+ "server will now behave correctly and not leave the "
+ "client hanging."];
+
+quit_OTP_6349(suite) ->
+ [];
+
+quit_OTP_6349(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ FileName = filename:join(DataDir, "test.txt"),
+
+ {Sftp, _} = ?config(sftp, Config),
+
+ {ok, <<_/binary>>} = ssh_sftp:read_file(Sftp, FileName),
+
+ ok = ssh_sftp:stop_channel(Sftp),
+
+ Host = ssh_test_lib:hostname(),
+
+ timer:sleep(5000),
+ {ok, NewSftp, _Conn} = ssh_sftp:start_channel(Host, ?SSHD_PORT,
+ [{silently_accept_hosts, true},
+ {pwdfun, fun(_,_) -> true end},
+ {system_dir, DataDir},
+ {user_dir, DataDir},
+ {user, ?USER}, {password, ?PASSWD}]),
+
+ {ok, <<_/binary>>} = ssh_sftp:read_file(NewSftp, FileName),
+
+ ok = ssh_sftp:stop_channel(NewSftp),
+ ok.
+
+%%--------------------------------------------------------------------
+
+file_cb_OTP_6356(doc) ->
+ ["Test that it is possible to change the callback module for"
+ " the sftpds filehandling."];
+
+file_cb_OTP_6356(suite) ->
+ [];
+
+file_cb_OTP_6356(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ FileName = filename:join(DataDir, "test.txt"),
+
+ register(sftpd_file_alt_tester, self()),
+
+ {Sftp, _} = ?config(sftp, Config),
+
+ {ok, Bin} = ssh_sftp:read_file(Sftp, FileName),
+ alt_file_handler_check(alt_open),
+ alt_file_handler_check(alt_read_file_info),
+ alt_file_handler_check(alt_position),
+ alt_file_handler_check(alt_read),
+ alt_file_handler_check(alt_position),
+ alt_file_handler_check(alt_read),
+ alt_file_handler_check(alt_close),
+
+
+ NewFileName = filename:join(PrivDir, "test.txt"),
+ ok = ssh_sftp:write_file(Sftp, NewFileName, Bin),
+ alt_file_handler_check(alt_open),
+ alt_file_handler_check(alt_read_file_info),
+ alt_file_handler_check(alt_position),
+ alt_file_handler_check(alt_write),
+ alt_file_handler_check(alt_close),
+
+ ReFileName = filename:join(PrivDir, "test1.txt"),
+ ok = ssh_sftp:rename(Sftp, NewFileName, ReFileName),
+ alt_file_handler_check(alt_rename),
+
+ ok = ssh_sftp:delete(Sftp, ReFileName),
+ alt_file_handler_check(alt_delete),
+
+ NewDir = filename:join(PrivDir, "testdir"),
+ ok = ssh_sftp:make_dir(Sftp, NewDir),
+ alt_file_handler_check(alt_make_dir),
+
+ ok = ssh_sftp:del_dir(Sftp, NewDir),
+ alt_file_handler_check(alt_read_link_info),
+ alt_file_handler_check(alt_write_file_info),
+ alt_file_handler_check(alt_del_dir),
+ ok.
+
+root_dir(doc) ->
+ [""];
+root_dir(suite) ->
+ [];
+root_dir(Config) when is_list(Config) ->
+ {Sftp, _} = ?config(sftp, Config),
+ FileName = "test.txt",
+ Bin = <<"Test file for root dir option">>,
+ ok = ssh_sftp:write_file(Sftp, FileName, Bin),
+ {ok, Bin} = ssh_sftp:read_file(Sftp, FileName),
+ {ok, Listing} =
+ ssh_sftp:list_dir(Sftp, "."),
+ test_server:format("Listing: ~p~n", [Listing]),
+ ok.
+
+list_dir_limited(doc) ->
+ [""];
+list_dir_limited(suite) ->
+ [];
+list_dir_limited(Config) when is_list(Config) ->
+ {Sftp, _} = ?config(sftp, Config),
+ {ok, Listing} =
+ ssh_sftp:list_dir(Sftp, "."),
+ test_server:format("Listing: ~p~n", [Listing]),
+ ok.
+
+alt_file_handler_check(Msg) ->
+ receive
+ Msg ->
+ ok;
+ Other ->
+ test_server:fail({Msg, Other})
+ after 10000 ->
+ test_server:fail("Not alt file handler")
+ end.
diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_sftpd_file_alt.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_sftpd_file_alt.erl
new file mode 100644
index 0000000000..9e119c4929
--- /dev/null
+++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_sftpd_file_alt.erl
@@ -0,0 +1,100 @@
+%%
+%% %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%
+%%
+
+%%
+
+%%% Description: Dummy Callback module for ssh_sftpd to test
+%%% the possibility to switch file handling implementation.
+
+-module(ssh_sftpd_file_alt).
+
+-behaviour(ssh_sftpd_file_api).
+
+%% API
+-export([close/2, delete/2, del_dir/2, get_cwd/1, is_dir/2, list_dir/2,
+ make_dir/2, make_symlink/3, open/3, position/3, read/3,
+ read_file_info/2, read_link/2, read_link_info/2, rename/3,
+ write/3, write_file_info/3]).
+
+close(IoDevice, State) ->
+ sftpd_file_alt_tester ! alt_close,
+ {file:close(IoDevice), State}.
+
+delete(Path, State) ->
+ sftpd_file_alt_tester ! alt_delete,
+ {file:delete(Path), State}.
+
+del_dir(Path, State) ->
+ sftpd_file_alt_tester ! alt_del_dir,
+ {file:del_dir(Path), State}.
+
+get_cwd(State) ->
+ {file:get_cwd(), State}.
+
+is_dir(AbsPath, State) ->
+ sftpd_file_alt_tester ! alt_is_dir,
+ {filelib:is_dir(AbsPath), State}.
+
+list_dir(AbsPath, State) ->
+ sftpd_file_alt_tester ! alt_list_dir,
+ {file:list_dir(AbsPath), State}.
+
+make_dir(Dir, State) ->
+ sftpd_file_alt_tester ! alt_make_dir,
+ {file:make_dir(Dir), State}.
+
+make_symlink(Path2, Path, State) ->
+ sftpd_file_alt_tester ! alt_make_symlink,
+ {file:make_symlink(Path2, Path), State}.
+
+open(Path, Flags, State) ->
+ sftpd_file_alt_tester ! alt_open,
+ {file:open(Path, Flags), State}.
+
+position(IoDevice, Offs, State) ->
+ sftpd_file_alt_tester ! alt_position,
+ {file:position(IoDevice, Offs), State}.
+
+read(IoDevice, Len, State) ->
+ sftpd_file_alt_tester ! alt_read,
+ {file:read(IoDevice, Len), State}.
+
+read_link(Path, State) ->
+ sftpd_file_alt_tester ! alt_read_link,
+ {file:read_link(Path), State}.
+
+read_link_info(Path, State) ->
+ sftpd_file_alt_tester ! alt_read_link_info,
+ {file:read_link_info(Path), State}.
+
+read_file_info(Path, State) ->
+ sftpd_file_alt_tester ! alt_read_file_info,
+ {file:read_file_info(Path), State}.
+
+rename(Path, Path2, State) ->
+ sftpd_file_alt_tester ! alt_rename,
+ {file:rename(Path, Path2), State}.
+
+write(IoDevice, Data, State) ->
+ sftpd_file_alt_tester ! alt_write,
+ {file:write(IoDevice, Data), State}.
+
+write_file_info(Path,Info, State) ->
+ sftpd_file_alt_tester ! alt_write_file_info,
+ {file:write_file_info(Path, Info), State}.
diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/test.txt b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/test.txt
new file mode 100644
index 0000000000..681bff80a0
--- /dev/null
+++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/test.txt
@@ -0,0 +1 @@
+Sftp test file. \ No newline at end of file
diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl
new file mode 100644
index 0000000000..425fae22c1
--- /dev/null
+++ b/lib/ssh/test/ssh_test_lib.erl
@@ -0,0 +1,684 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(ssh_test_lib).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("public_key/include/public_key.hrl").
+-include("test_server.hrl").
+-include("test_server_line.hrl").
+
+-define(TIMEOUT, 50000).
+
+connect(Options) ->
+ connect(hostname(), inet_port(), Options).
+
+connect(Port, Options) when is_integer(Port) ->
+ connect(hostname(), Port, Options);
+connect(any, Options) ->
+ connect(hostname(), inet_port(), Options);
+connect(Host, Options) ->
+ connect(Host, inet_port(), Options).
+
+connect(any, Port, Options) ->
+ connect(hostname(), Port, Options);
+connect(Host, Port, Options) ->
+ case ssh:connect(Host, Port, Options) of
+ {ok, ConnectionRef} ->
+ ConnectionRef;
+ Error ->
+ Error
+ end.
+
+daemon(Options) ->
+ daemon(any, inet_port(), Options).
+
+daemon(Port, Options) when is_integer(Port) ->
+ daemon(any, Port, Options);
+daemon(Host, Options) ->
+ daemon(Host, inet_port(), Options).
+
+daemon(Host, Port, Options) ->
+ case ssh:daemon(Host, Port, Options) of
+ {ok, Pid} when Host == any ->
+ {Pid, hostname(), Port};
+ {ok, Pid} ->
+ {Pid, Host, Port};
+ Error ->
+ Error
+ end.
+
+
+
+
+start_shell(Port, IOServer) ->
+ spawn_link(?MODULE, init_shell, [Port, IOServer]).
+
+init_shell(Port, IOServer) ->
+ Host = hostname(),
+ UserDir = get_user_dir(),
+ Options = [{user_interaction, false}, {silently_accept_hosts,
+ true}] ++ UserDir,
+ group_leader(IOServer, self()),
+ loop_shell(Host, Port, Options).
+
+loop_shell(Host, Port, Options) ->
+ ssh:shell(Host, Port, Options).
+
+start_io_server() ->
+ spawn_link(?MODULE, init_io_server, [self()]).
+
+init_io_server(TestCase) ->
+ process_flag(trap_exit, true),
+ loop_io_server(TestCase, []).
+
+loop_io_server(TestCase, Buff0) ->
+ receive
+ {input, TestCase, Line} ->
+ %io:format("~p~n",[{input, TestCase, Line}]),
+ loop_io_server(TestCase, Buff0 ++ [Line]);
+ {io_request, From, ReplyAs, Request} ->
+ %io:format("request -> ~p~n",[Request]),
+ {ok, Reply, Buff} = io_request(Request, TestCase, From,
+ ReplyAs, Buff0),
+ %io:format("reply -> ~p~n",[Reply]),
+ io_reply(From, ReplyAs, Reply),
+ loop_io_server(TestCase, Buff);
+ {'EXIT',_, _} ->
+ erlang:display('EXIT'),
+ ok
+ end.
+
+io_request({put_chars, Chars}, TestCase, _, _, Buff) ->
+ reply(TestCase, Chars),
+ {ok, ok, Buff};
+io_request({put_chars, Enc, Chars}, TestCase, _, _, Buff) ->
+ reply(TestCase, unicode:characters_to_binary(Chars,Enc,latin1)),
+ {ok, ok, Buff};
+
+io_request({get_line, _} = Request, _, From, ReplyAs, [] = Buff) ->
+ erlang:send_after(1000, self(), {io_request, From, ReplyAs, Request}),
+ {ok, [], Buff};
+io_request({get_line, _Enc, _Prompt} = Request, _, From, ReplyAs, [] = Buff) ->
+ erlang:send_after(1000, self(), {io_request, From, ReplyAs, Request}),
+ {ok, [], Buff};
+
+io_request({get_line, _Enc,_}, _, _, _, [Line | Buff]) ->
+ {ok, Line, Buff}.
+
+io_reply(_, _, []) ->
+ ok;
+io_reply(From, ReplyAs, Reply) ->
+ From ! {io_reply, ReplyAs, Reply}.
+
+reply(_, []) ->
+ ok;
+reply(TestCase, Result) ->
+ TestCase ! Result.
+
+receive_exec_result(Msg) ->
+ test_server:format("Expect data! ~p", [Msg]),
+ receive
+ Msg ->
+ test_server:format("1: Collected data ~p", [Msg]),
+ expected;
+ Other ->
+ {unexpected_msg, Other}
+ end.
+receive_exec_end(ConnectionRef, ChannelId) ->
+ Eof = {ssh_cm, ConnectionRef, {eof, ChannelId}},
+ ExitStatus = {ssh_cm, ConnectionRef, {exit_status, ChannelId, 0}},
+ Closed = {ssh_cm, ConnectionRef,{closed, ChannelId}},
+ case receive_exec_result(ExitStatus) of
+ {unexpected_msg, Eof} -> %% Open ssh seems to not allways send these messages
+ %% in the same order!
+ test_server:format("2: Collected data ~p", [Eof]),
+ case receive_exec_result(ExitStatus) of
+ expected ->
+ expected = receive_exec_result(Closed);
+ {unexpected_msg, Closed} ->
+ test_server:format("3: Collected data ~p", [Closed])
+ end;
+ expected ->
+ test_server:format("4: Collected data ~p", [ExitStatus]),
+ expected = receive_exec_result(Eof),
+ expected = receive_exec_result(Closed);
+ Other ->
+ test_server:fail({unexpected_msg, Other})
+ end.
+
+receive_exec_result(Data, ConnectionRef, ChannelId) ->
+ Eof = {ssh_cm, ConnectionRef, {eof, ChannelId}},
+ Closed = {ssh_cm, ConnectionRef,{closed, ChannelId}},
+ expected = receive_exec_result(Data),
+ expected = receive_exec_result(Eof),
+ expected = receive_exec_result(Closed).
+
+
+inet_port()->
+ {ok, Socket} = gen_tcp:listen(0, [{reuseaddr, true}]),
+ {ok, Port} = inet:port(Socket),
+ gen_tcp:close(Socket),
+ Port.
+
+
+%% copy private keys to given dir from ~/.ssh
+get_id_keys(DstDir) ->
+ SrcDir = filename:join(os:getenv("HOME"), ".ssh"),
+ RsaOk = copyfile(SrcDir, DstDir, "id_rsa"),
+ DsaOk = copyfile(SrcDir, DstDir, "id_dsa"),
+ case {RsaOk, DsaOk} of
+ {{ok, _}, {ok, _}} -> {ok, both};
+ {{ok, _}, _} -> {ok, rsa};
+ {_, {ok, _}} -> {ok, dsa};
+ {Error, _} -> Error
+ end.
+
+remove_id_keys(Dir) ->
+ file:delete(filename:join(Dir, "id_rsa")),
+ file:delete(filename:join(Dir, "id_dsa")).
+
+copyfile(SrcDir, DstDir, Fn) ->
+ file:copy(filename:join(SrcDir, Fn),
+ filename:join(DstDir, Fn)).
+
+failfun(_User, {authmethod,none}) ->
+ ok;
+failfun(User, Reason) ->
+ error_logger:format("~p failed XXX to login: ~p~n", [User, Reason]).
+
+hostname() ->
+ {ok,Host} = inet:gethostname(),
+ Host.
+
+known_hosts(BR) ->
+ KnownHosts = ssh_file:file_name(user, "known_hosts", []),
+ B = KnownHosts ++ "xxx",
+ case BR of
+ backup ->
+ file:rename(KnownHosts, B);
+ restore ->
+ file:delete(KnownHosts),
+ file:rename(B, KnownHosts)
+ end.
+
+
+get_user_dir() ->
+ case os:type() of
+ {win32, _} ->
+ [{user_dir, filename:join([os:getenv("HOME"), ".ssh"])}];
+ _ ->
+ []
+ end.
+
+
+make_dsa_cert_files(Config) ->
+ make_dsa_cert_files("", Config).
+
+make_dsa_cert_files(RoleStr, Config) ->
+
+ CaInfo = {CaCert, _} = make_cert([{key, dsa}]),
+ {Cert, CertKey} = make_cert([{key, dsa}, {issuer, CaInfo}]),
+ CaCertFile = filename:join([?config(data_dir, Config),
+ RoleStr, "dsa_cacerts.pem"]),
+ CertFile = filename:join([?config(data_dir, Config),
+ RoleStr, "dsa_cert.pem"]),
+ KeyFile = filename:join([?config(data_dir, Config),
+ RoleStr, "dsa_key.pem"]),
+
+ der_to_pem(CaCertFile, [{'Certificate', CaCert, not_encrypted}]),
+ der_to_pem(CertFile, [{'Certificate', Cert, not_encrypted}]),
+ der_to_pem(KeyFile, [CertKey]),
+ {CaCertFile, CertFile, KeyFile}.
+
+make_dsa_files(Config) ->
+ make_dsa_files(Config, rfc4716_public_key).
+make_dsa_files(Config, Type) ->
+ {DSA, EncodedKey} = ssh_test_lib:gen_dsa(128, 20),
+ PKey = DSA#'DSAPrivateKey'.y,
+ P = DSA#'DSAPrivateKey'.p,
+ Q = DSA#'DSAPrivateKey'.q,
+ G = DSA#'DSAPrivateKey'.g,
+ Dss = #'Dss-Parms'{p=P, q=Q, g=G},
+ {ok, Hostname} = inet:gethostname(),
+ {ok, {A, B, C, D}} = inet:getaddr(Hostname, inet),
+ IP = lists:concat([A, ".", B, ".", C, ".", D]),
+ Attributes = [], % Could be [{comment,"user@" ++ Hostname}],
+ HostNames = [{hostnames,[IP, IP]}],
+ PublicKey = [{{PKey, Dss}, Attributes}],
+ KnownHosts = [{{PKey, Dss}, HostNames}],
+
+ KnownHostsEnc = public_key:ssh_encode(KnownHosts, known_hosts),
+ KnownHosts = public_key:ssh_decode(KnownHostsEnc, known_hosts),
+
+ PublicKeyEnc = public_key:ssh_encode(PublicKey, Type),
+% PublicKey = public_key:ssh_decode(PublicKeyEnc, Type),
+
+ SystemTmpDir = ?config(data_dir, Config),
+ filelib:ensure_dir(SystemTmpDir),
+ file:make_dir(SystemTmpDir),
+
+ DSAFile = filename:join(SystemTmpDir, "ssh_host_dsa_key.pub"),
+ file:delete(DSAFile),
+
+ DSAPrivateFile = filename:join(SystemTmpDir, "ssh_host_dsa_key"),
+ file:delete(DSAPrivateFile),
+
+ KHFile = filename:join(SystemTmpDir, "known_hosts"),
+ file:delete(KHFile),
+
+ PemBin = public_key:pem_encode([EncodedKey]),
+
+ file:write_file(DSAFile, PublicKeyEnc),
+ file:write_file(KHFile, KnownHostsEnc),
+ file:write_file(DSAPrivateFile, PemBin),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Create and return a der encoded certificate
+%% Option Default
+%% -------------------------------------------------------
+%% digest sha1
+%% validity {date(), date() + week()}
+%% version 3
+%% subject [] list of the following content
+%% {name, Name}
+%% {email, Email}
+%% {city, City}
+%% {state, State}
+%% {org, Org}
+%% {org_unit, OrgUnit}
+%% {country, Country}
+%% {serial, Serial}
+%% {title, Title}
+%% {dnQualifer, DnQ}
+%% issuer = {Issuer, IssuerKey} true (i.e. a ca cert is created)
+%% (obs IssuerKey migth be {Key, Password}
+%% key = KeyFile|KeyBin|rsa|dsa Subject PublicKey rsa or dsa generates key
+%%
+%%
+%% (OBS: The generated keys are for testing only)
+%% make_cert([{::atom(), ::term()}]) -> {Cert::binary(), Key::binary()}
+%%--------------------------------------------------------------------
+make_cert(Opts) ->
+ SubjectPrivateKey = get_key(Opts),
+ {TBSCert, IssuerKey} = make_tbs(SubjectPrivateKey, Opts),
+ Cert = public_key:pkix_sign(TBSCert, IssuerKey),
+ true = verify_signature(Cert, IssuerKey, undef), %% verify that the keys where ok
+ {Cert, encode_key(SubjectPrivateKey)}.
+
+%%--------------------------------------------------------------------
+%% Writes cert files in Dir with FileName and FileName ++ Suffix
+%% write_cert(::string(), ::string(), {Cert,Key}) -> ok
+%%--------------------------------------------------------------------
+write_cert(Dir, FileName, Suffix, {Cert, Key = {_,_,not_encrypted}}) when is_binary(Cert) ->
+ ok = der_to_pem(filename:join(Dir, FileName),
+ [{'Certificate', Cert, not_encrypted}]),
+ ok = der_to_pem(filename:join(Dir, FileName ++ Suffix), [Key]).
+
+%%--------------------------------------------------------------------
+%% Creates a rsa key (OBS: for testing only)
+%% the size are in bytes
+%% gen_rsa(::integer()) -> {::atom(), ::binary(), ::opaque()}
+%%--------------------------------------------------------------------
+gen_rsa(Size) when is_integer(Size) ->
+ Key = gen_rsa2(Size),
+ {Key, encode_key(Key)}.
+
+%%--------------------------------------------------------------------
+%% Creates a dsa key (OBS: for testing only)
+%% the sizes are in bytes
+%% gen_dsa(::integer()) -> {::atom(), ::binary(), ::opaque()}
+%%--------------------------------------------------------------------
+gen_dsa(LSize,NSize) when is_integer(LSize), is_integer(NSize) ->
+ Key = gen_dsa2(LSize, NSize),
+ {Key, encode_key(Key)}.
+
+%%--------------------------------------------------------------------
+%% Verifies cert signatures
+%% verify_signature(::binary(), ::tuple()) -> ::boolean()
+%%--------------------------------------------------------------------
+verify_signature(DerEncodedCert, DerKey, _KeyParams) ->
+ Key = decode_key(DerKey),
+ case Key of
+ #'RSAPrivateKey'{modulus=Mod, publicExponent=Exp} ->
+ public_key:pkix_verify(DerEncodedCert,
+ #'RSAPublicKey'{modulus=Mod, publicExponent=Exp});
+ #'DSAPrivateKey'{p=P, q=Q, g=G, y=Y} ->
+ public_key:pkix_verify(DerEncodedCert, {Y, #'Dss-Parms'{p=P, q=Q, g=G}})
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%% Implementation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+get_key(Opts) ->
+ case proplists:get_value(key, Opts) of
+ undefined -> make_key(rsa, Opts);
+ rsa -> make_key(rsa, Opts);
+ dsa -> make_key(dsa, Opts);
+ Key ->
+ Password = proplists:get_value(password, Opts, no_passwd),
+ decode_key(Key, Password)
+ end.
+
+decode_key({Key, Pw}) ->
+ decode_key(Key, Pw);
+decode_key(Key) ->
+ decode_key(Key, no_passwd).
+
+
+decode_key(#'RSAPublicKey'{} = Key,_) ->
+ Key;
+decode_key(#'RSAPrivateKey'{} = Key,_) ->
+ Key;
+decode_key(#'DSAPrivateKey'{} = Key,_) ->
+ Key;
+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),
+ {'RSAPrivateKey', list_to_binary(Der), not_encrypted};
+encode_key(Key = #'DSAPrivateKey'{}) ->
+ {ok, Der} = 'OTP-PUB-KEY':encode('DSAPrivateKey', Key),
+ {'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))),
+
+ 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,
+ subjectPublicKeyInfo = publickey(SubjectKey),
+ version = Version,
+ extensions = extensions(Opts)
+ }, IssuerKey}.
+
+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, _}|_]} = pem_to_der(File),
+ {issuer_der(Cert), decode_key(IssuerKey)}.
+
+issuer_der(Issuer) ->
+ Decoded = public_key:pkix_decode_cert(Issuer, otp),
+ #'OTPCertificate'{tbsCertificate=Tbs} = Decoded,
+ #'OTPTBSCertificate'{subject=Subject} = Tbs,
+ Subject.
+
+subject(undefined, IsRootCA) ->
+ User = if IsRootCA -> "RootCA"; true -> os:getenv("USER") end,
+ Opts = [{email, User ++ "@erlang.org"},
+ {name, User},
+ {city, "Stockholm"},
+ {country, "SE"},
+ {org, "erlang"},
+ {org_unit, "testing dep"}],
+ subject(Opts);
+subject(Opts, _) ->
+ subject(Opts).
+
+subject(SubjectOpts) when is_list(SubjectOpts) ->
+ Encode = fun(Opt) ->
+ {Type,Value} = subject_enc(Opt),
+ [#'AttributeTypeAndValue'{type=Type, value=Value}]
+ end,
+ {rdnSequence, [Encode(Opt) || Opt <- SubjectOpts]}.
+
+%% Fill in the blanks
+subject_enc({name, Name}) -> {?'id-at-commonName', {printableString, Name}};
+subject_enc({email, Email}) -> {?'id-emailAddress', Email};
+subject_enc({city, City}) -> {?'id-at-localityName', {printableString, City}};
+subject_enc({state, State}) -> {?'id-at-stateOrProvinceName', {printableString, State}};
+subject_enc({org, Org}) -> {?'id-at-organizationName', {printableString, Org}};
+subject_enc({org_unit, OrgUnit}) -> {?'id-at-organizationalUnitName', {printableString, OrgUnit}};
+subject_enc({country, Country}) -> {?'id-at-countryName', Country};
+subject_enc({serial, Serial}) -> {?'id-at-serialNumber', Serial};
+subject_enc({title, Title}) -> {?'id-at-title', {printableString, Title}};
+subject_enc({dnQualifer, DnQ}) -> {?'id-at-dnQualifier', DnQ};
+subject_enc(Other) -> Other.
+
+
+extensions(Opts) ->
+ case proplists:get_value(extensions, Opts, []) of
+ false ->
+ asn1_NOVALUE;
+ Exts ->
+ lists:flatten([extension(Ext) || Ext <- default_extensions(Exts)])
+ end.
+
+default_extensions(Exts) ->
+ Def = [{key_usage,undefined},
+ {subject_altname, undefined},
+ {issuer_altname, undefined},
+ {basic_constraints, default},
+ {name_constraints, undefined},
+ {policy_constraints, undefined},
+ {ext_key_usage, undefined},
+ {inhibit_any, undefined},
+ {auth_key_id, undefined},
+ {subject_key_id, undefined},
+ {policy_mapping, undefined}],
+ Filter = fun({Key, _}, D) -> lists:keydelete(Key, 1, D) end,
+ Exts ++ lists:foldl(Filter, Def, Exts).
+
+extension({_, undefined}) -> [];
+extension({basic_constraints, Data}) ->
+ case Data of
+ default ->
+ #'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue = #'BasicConstraints'{cA=true},
+ critical=true};
+ false ->
+ [];
+ Len when is_integer(Len) ->
+ #'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue = #'BasicConstraints'{cA=true, pathLenConstraint=Len},
+ critical=true};
+ _ ->
+ #'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue = Data}
+ end;
+extension({Id, Data, Critical}) ->
+ #'Extension'{extnID = Id, extnValue = Data, critical = Critical}.
+
+
+publickey(#'RSAPrivateKey'{modulus=N, publicExponent=E}) ->
+ Public = #'RSAPublicKey'{modulus=N, publicExponent=E},
+ Algo = #'PublicKeyAlgorithm'{algorithm= ?rsaEncryption, parameters='NULL'},
+ #'OTPSubjectPublicKeyInfo'{algorithm = Algo,
+ subjectPublicKey = Public};
+publickey(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) ->
+ Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-dsa',
+ parameters={params, #'Dss-Parms'{p=P, q=Q, g=G}}},
+ #'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y}.
+
+validity(Opts) ->
+ 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,
+ #'Validity'{notBefore={generalTime, Format(DefFrom)},
+ notAfter ={generalTime, Format(DefTo)}}.
+
+sign_algorithm(#'RSAPrivateKey'{}, Opts) ->
+ Type = case proplists:get_value(digest, Opts, sha1) of
+ sha1 -> ?'sha1WithRSAEncryption';
+ sha512 -> ?'sha512WithRSAEncryption';
+ sha384 -> ?'sha384WithRSAEncryption';
+ sha256 -> ?'sha256WithRSAEncryption';
+ md5 -> ?'md5WithRSAEncryption';
+ md2 -> ?'md2WithRSAEncryption'
+ end,
+ {Type, 'NULL'};
+sign_algorithm(#'DSAPrivateKey'{p=P, q=Q, g=G}, _Opts) ->
+ {?'id-dsa-with-sha1', {params,#'Dss-Parms'{p=P, q=Q, g=G}}}.
+
+make_key(rsa, _Opts) ->
+ %% (OBS: for testing only)
+ gen_rsa2(64);
+make_key(dsa, _Opts) ->
+ gen_dsa2(128, 20). %% Bytes i.e. {1024, 160}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% RSA key generation (OBS: for testing only)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-define(SMALL_PRIMES, [65537,97,89,83,79,73,71,67,61,59,53,
+ 47,43,41,37,31,29,23,19,17,13,11,7,5,3]).
+
+gen_rsa2(Size) ->
+ P = prime(Size),
+ Q = prime(Size),
+ N = P*Q,
+ Tot = (P - 1) * (Q - 1),
+ [E|_] = lists:dropwhile(fun(Candidate) -> (Tot rem Candidate) == 0 end, ?SMALL_PRIMES),
+ {D1,D2} = extended_gcd(E, Tot),
+ D = erlang:max(D1,D2),
+ case D < E of
+ true ->
+ gen_rsa2(Size);
+ false ->
+ {Co1,Co2} = extended_gcd(Q, P),
+ Co = erlang:max(Co1,Co2),
+ #'RSAPrivateKey'{version = 'two-prime',
+ modulus = N,
+ publicExponent = E,
+ privateExponent = D,
+ prime1 = P,
+ prime2 = Q,
+ exponent1 = D rem (P-1),
+ exponent2 = D rem (Q-1),
+ coefficient = Co
+ }
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% DSA key generation (OBS: for testing only)
+%% See http://en.wikipedia.org/wiki/Digital_Signature_Algorithm
+%% and the fips_186-3.pdf
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+gen_dsa2(LSize, NSize) ->
+ Q = prime(NSize), %% Choose N-bit prime Q
+ X0 = prime(LSize),
+ P0 = prime((LSize div 2) +1),
+
+ %% Choose L-bit prime modulus P such that p-1 is a multiple of q.
+ case dsa_search(X0 div (2*Q*P0), P0, Q, 1000) of
+ error ->
+ gen_dsa2(LSize, NSize);
+ P ->
+ G = crypto:mod_exp(2, (P-1) div Q, P), % Choose G a number whose multiplicative order modulo p is q.
+ %% such that This may be done by setting g = h^(p-1)/q mod p, commonly h=2 is used.
+
+ X = prime(20), %% Choose x by some random method, where 0 < x < q.
+ Y = crypto:mod_exp(G, X, P), %% Calculate y = g^x mod p.
+
+ #'DSAPrivateKey'{version=0, p=P, q=Q, g=G, y=Y, x=X}
+ end.
+
+%% See fips_186-3.pdf
+dsa_search(T, P0, Q, Iter) when Iter > 0 ->
+ P = 2*T*Q*P0 + 1,
+ case is_prime(crypto:mpint(P), 50) of
+ true -> P;
+ false -> dsa_search(T+1, P0, Q, Iter-1)
+ end;
+dsa_search(_,_,_,_) ->
+ error.
+
+
+%%%%%%% Crypto Math %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+prime(ByteSize) ->
+ Rand = odd_rand(ByteSize),
+ crypto:erlint(prime_odd(Rand, 0)).
+
+prime_odd(Rand, N) ->
+ case is_prime(Rand, 50) of
+ true ->
+ Rand;
+ false ->
+ NotPrime = crypto:erlint(Rand),
+ prime_odd(crypto:mpint(NotPrime+2), N+1)
+ end.
+
+%% see http://en.wikipedia.org/wiki/Fermat_primality_test
+is_prime(_, 0) -> true;
+is_prime(Candidate, Test) ->
+ CoPrime = odd_rand(<<0,0,0,4, 10000:32>>, Candidate),
+ case crypto:mod_exp(CoPrime, Candidate, Candidate) of
+ CoPrime -> is_prime(Candidate, Test-1);
+ _ -> false
+ end.
+
+odd_rand(Size) ->
+ Min = 1 bsl (Size*8-1),
+ Max = (1 bsl (Size*8))-1,
+ odd_rand(crypto:mpint(Min), crypto:mpint(Max)).
+
+odd_rand(Min,Max) ->
+ Rand = <<Sz:32, _/binary>> = crypto:rand_uniform(Min,Max),
+ BitSkip = (Sz+4)*8-1,
+ case Rand of
+ Odd = <<_:BitSkip, 1:1>> -> Odd;
+ Even = <<_:BitSkip, 0:1>> ->
+ crypto:mpint(crypto:erlint(Even)+1)
+ end.
+
+extended_gcd(A, B) ->
+ case A rem B of
+ 0 ->
+ {0, 1};
+ N ->
+ {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/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl
new file mode 100644
index 0000000000..f959d50484
--- /dev/null
+++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl
@@ -0,0 +1,458 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(ssh_to_openssh_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+-include("test_server_line.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-define(TIMEOUT, 50000).
+-define(SSH_DEFAULT_PORT, 22).
+
+%% 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(Config) ->
+ case catch crypto:start() of
+ ok ->
+ ssh_test_lib:make_dsa_files(Config),
+ Config;
+ _Else ->
+ {skip,"Could not start crypto!"}
+ end.
+
+%%--------------------------------------------------------------------
+%% 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) ->
+ crypto:stop(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% 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(_TestCase, Config) ->
+ ssh:start(),
+ 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(_TestCase, _Config) ->
+ ssh:stop(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% 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() ->
+ case os:find_executable("ssh") of
+ false ->
+ {skip, "openSSH not installed on host"};
+ _ ->
+ [erlang_shell_client_openssh_server,
+ erlang_client_openssh_server_exec,
+ erlang_client_openssh_server_exec_compressed,
+ erlang_server_openssh_client_exec,
+ erlang_server_openssh_client_exec_compressed,
+ erlang_client_openssh_server_setenv,
+ erlang_client_openssh_server_publickey_rsa,
+ erlang_client_openssh_server_publickey_dsa,
+ erlang_server_openssh_client_pulic_key_dsa,
+ erlang_client_openssh_server_password]
+ end.
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+%% TEST cases starts here.
+%%--------------------------------------------------------------------
+erlang_shell_client_openssh_server(doc) ->
+ ["Test that ssh:shell/2 works"];
+
+erlang_shell_client_openssh_server(suite) ->
+ [];
+
+erlang_shell_client_openssh_server(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ IO = ssh_test_lib:start_io_server(),
+ Shell = ssh_test_lib:start_shell(?SSH_DEFAULT_PORT, IO),
+ IO ! {input, self(), "echo Hej\n"},
+ receive_hej(),
+ IO ! {input, self(), "exit\n"},
+ receive
+ <<"logout">> ->
+ receive
+ <<"Connection closed">> ->
+ ok
+ end;
+ Other0 ->
+ test_server:fail({unexpected_msg, Other0})
+ end,
+ receive
+ {'EXIT', Shell, normal} ->
+ ok;
+ Other1 ->
+ test_server:fail({unexpected_msg, Other1})
+ end.
+
+%--------------------------------------------------------------------
+erlang_client_openssh_server_exec(doc) ->
+ ["Test api function ssh_connection:exec"];
+
+erlang_client_openssh_server_exec(suite) ->
+ [];
+
+erlang_client_openssh_server_exec(Config) when is_list(Config) ->
+ ConnectionRef = ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true},
+ {user_interaction, false}]),
+ {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity),
+ success = ssh_connection:exec(ConnectionRef, ChannelId0,
+ "echo testing", infinity),
+ Data0 = {ssh_cm, ConnectionRef, {data, ChannelId0, 0, <<"testing\n">>}},
+ case ssh_test_lib:receive_exec_result(Data0) of
+ expected ->
+ ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId0);
+ {unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId0, 0}}
+ = ExitStatus0} ->
+ test_server:format("0: Collected data ~p", [ExitStatus0]),
+ ssh_test_lib:receive_exec_result(Data0,
+ ConnectionRef, ChannelId0);
+ Other0 ->
+ test_server:fail(Other0)
+ end,
+
+ {ok, ChannelId1} = ssh_connection:session_channel(ConnectionRef, infinity),
+ success = ssh_connection:exec(ConnectionRef, ChannelId1,
+ "echo testing1", infinity),
+ Data1 = {ssh_cm, ConnectionRef, {data, ChannelId1, 0, <<"testing1\n">>}},
+ case ssh_test_lib:receive_exec_result(Data1) of
+ expected ->
+ ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId1);
+ {unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId1, 0}}
+ = ExitStatus1} ->
+ test_server:format("0: Collected data ~p", [ExitStatus1]),
+ ssh_test_lib:receive_exec_result(Data1,
+ ConnectionRef, ChannelId1);
+ Other1 ->
+ test_server:fail(Other1)
+ end.
+
+%%--------------------------------------------------------------------
+erlang_client_openssh_server_exec_compressed(doc) ->
+ ["Test that compression option works"];
+
+erlang_client_openssh_server_exec_compressed(suite) ->
+ [];
+
+erlang_client_openssh_server_exec_compressed(Config) when is_list(Config) ->
+ ConnectionRef = ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true},
+ {user_interaction, false},
+ {compression, zlib}]),
+ {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
+ success = ssh_connection:exec(ConnectionRef, ChannelId,
+ "echo testing", infinity),
+ Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"testing\n">>}},
+ case ssh_test_lib:receive_exec_result(Data) of
+ expected ->
+ ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId);
+ {unexpected_msg,{ssh_cm, ConnectionRef,
+ {exit_status, ChannelId, 0}} = ExitStatus} ->
+ test_server:format("0: Collected data ~p", [ExitStatus]),
+ ssh_test_lib:receive_exec_result(Data, ConnectionRef, ChannelId);
+ Other ->
+ test_server:fail(Other)
+ end.
+
+%%--------------------------------------------------------------------
+erlang_server_openssh_client_exec(doc) ->
+ ["Test that exec command works."];
+
+erlang_server_openssh_client_exec(suite) ->
+ [];
+
+erlang_server_openssh_client_exec(Config) when is_list(Config) ->
+ SystemDir = ?config(data_dir, Config),
+
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+
+
+ test_server:sleep(500),
+
+ Cmd = "ssh -p " ++ integer_to_list(Port) ++
+ " -o StrictHostKeyChecking=no "++ Host ++ " 1+1.",
+ SshPort = open_port({spawn, Cmd}, [binary]),
+
+ receive
+ {SshPort,{data, <<"2\n">>}} ->
+ ok
+ after ?TIMEOUT ->
+ test_server:fail("Did not receive answer")
+
+ end,
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+erlang_server_openssh_client_exec_compressed(doc) ->
+ ["Test that exec command works."];
+
+erlang_server_openssh_client_exec_compressed(suite) ->
+ [];
+
+erlang_server_openssh_client_exec_compressed(Config) when is_list(Config) ->
+ SystemDir = ?config(data_dir, Config),
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {compression, zlib},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+
+ test_server:sleep(500),
+
+ Cmd = "ssh -p " ++ integer_to_list(Port) ++
+ " -o StrictHostKeyChecking=no -C "++ Host ++ " 1+1.",
+ SshPort = open_port({spawn, Cmd}, [binary]),
+
+ receive
+ {SshPort,{data, <<"2\n">>}} ->
+ ok
+ after ?TIMEOUT ->
+ test_server:fail("Did not receive answer")
+
+ end,
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+erlang_client_openssh_server_setenv(doc) ->
+ ["Test api function ssh_connection:setenv"];
+
+erlang_client_openssh_server_setenv(suite) ->
+ [];
+
+erlang_client_openssh_server_setenv(Config) when is_list(Config) ->
+ ConnectionRef =
+ ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true},
+ {user_interaction, false}]),
+ {ok, ChannelId} =
+ ssh_connection:session_channel(ConnectionRef, infinity),
+ Env = case ssh_connection:setenv(ConnectionRef, ChannelId,
+ "ENV_TEST", "testing_setenv",
+ infinity) of
+ success ->
+ <<"tesing_setenv\n">>;
+ failure ->
+ <<"\n">>
+ end,
+ success = ssh_connection:exec(ConnectionRef, ChannelId,
+ "echo $ENV_TEST", infinity),
+ Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, Env}},
+ case ssh_test_lib:receive_exec_result(Data) of
+ expected ->
+ ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId);
+ {unexpected_msg,{ssh_cm, ConnectionRef,
+ {data,0,1, UnxpectedData}}} ->
+ %% Some os may return things as
+ %% ENV_TEST: Undefined variable.\n"
+ test_server:format("UnxpectedData: ~p", [UnxpectedData]),
+ ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId);
+ {unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId, 0}}
+ = ExitStatus} ->
+ test_server:format("0: Collected data ~p", [ExitStatus]),
+ ssh_test_lib:receive_exec_result(Data,
+ ConnectionRef, ChannelId);
+ Other ->
+ test_server:fail(Other)
+ end.
+
+%%--------------------------------------------------------------------
+
+%% setenv not meaningfull on erlang ssh daemon!
+
+%%--------------------------------------------------------------------
+erlang_client_openssh_server_publickey_rsa(doc) ->
+ ["Validate using rsa publickey."];
+erlang_client_openssh_server_publickey_rsa(suite) ->
+ [];
+erlang_client_openssh_server_publickey_rsa(Config) when is_list(Config) ->
+ {ok,[[Home]]} = init:get_argument(home),
+ SrcDir = filename:join(Home, ".ssh"),
+ UserDir = ?config(priv_dir, Config),
+ case ssh_test_lib:copyfile(SrcDir, UserDir, "id_rsa") of
+ {ok, _} ->
+ ConnectionRef =
+ ssh_test_lib:connect(?SSH_DEFAULT_PORT,
+ [{user_dir, UserDir},
+ {public_key_alg, ssh_rsa},
+ {user_interaction, false},
+ silently_accept_hosts]),
+ {ok, Channel} =
+ ssh_connection:session_channel(ConnectionRef, infinity),
+ ok = ssh_connection:close(ConnectionRef, Channel),
+ ok = ssh:close(ConnectionRef),
+ ok = file:delete(filename:join(UserDir, "id_rsa"));
+ {error, enoent} ->
+ {skip, "no ~/.ssh/id_rsa"}
+ end.
+
+%%--------------------------------------------------------------------
+erlang_client_openssh_server_publickey_dsa(doc) ->
+ ["Validate using dsa publickey."];
+erlang_client_openssh_server_publickey_dsa(suite) ->
+ [];
+erlang_client_openssh_server_publickey_dsa(Config) when is_list(Config) ->
+ {ok,[[Home]]} = init:get_argument(home),
+ SrcDir = filename:join(Home, ".ssh"),
+ UserDir = ?config(priv_dir, Config),
+ case ssh_test_lib:copyfile(SrcDir, UserDir, "id_dsa") of
+ {ok, _} ->
+ ConnectionRef =
+ ssh_test_lib:connect(?SSH_DEFAULT_PORT,
+ [{user_dir, UserDir},
+ {public_key_alg, ssh_dsa},
+ {user_interaction, false},
+ silently_accept_hosts]),
+ {ok, Channel} =
+ ssh_connection:session_channel(ConnectionRef, infinity),
+ ok = ssh_connection:close(ConnectionRef, Channel),
+ ok = ssh:close(ConnectionRef),
+ ok = file:delete(filename:join(UserDir, "id_dsa"));
+ {error, enoent} ->
+ {skip, "no ~/.ssh/id_dsa"}
+ end.
+
+%%--------------------------------------------------------------------
+erlang_server_openssh_client_pulic_key_dsa(doc) ->
+ ["Validate using dsa publickey."];
+
+erlang_server_openssh_client_pulic_key_dsa(suite) ->
+ [];
+
+erlang_server_openssh_client_pulic_key_dsa(Config) when is_list(Config) ->
+ SystemDir = ?config(data_dir, Config),
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {public_key_alg, ssh_dsa},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+
+ test_server:sleep(500),
+
+ Cmd = "ssh -p " ++ integer_to_list(Port) ++
+ " -o StrictHostKeyChecking=no "++ Host ++ " 1+1.",
+ SshPort = open_port({spawn, Cmd}, [binary]),
+
+ receive
+ {SshPort,{data, <<"2\n">>}} ->
+ ok
+ after ?TIMEOUT ->
+ test_server:fail("Did not receive answer")
+
+ end,
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+erlang_client_openssh_server_password(doc) ->
+ ["Test client password option"];
+
+erlang_client_openssh_server_password(suite) ->
+ [];
+
+erlang_client_openssh_server_password(Config) when is_list(Config) ->
+ %% to make sure we don't public-key-auth
+ UserDir = ?config(data_dir, Config),
+ {error, Reason0} =
+ ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true},
+ {user, "foo"},
+ {password, "morot"},
+ {user_interaction, false},
+ {user_dir, UserDir}]),
+
+ test_server:format("Test of user foo that does not exist. "
+ "Error msg: ~p~n", [Reason0]),
+
+ User = string:strip(os:cmd("whoami"), right, $\n),
+
+ case length(string:tokens(User, " ")) of
+ 1 ->
+ {error, Reason1} =
+ ssh_test_lib:connect(?SSH_DEFAULT_PORT,
+ [{silently_accept_hosts, true},
+ {user, User},
+ {password, "foo"},
+ {user_interaction, false},
+ {user_dir, UserDir}]),
+ test_server:format("Test of wrong Pasword. "
+ "Error msg: ~p~n", [Reason1]);
+ _ ->
+ test_server:format("Whoami failed reason: ~n", [])
+ end.
+
+%%--------------------------------------------------------------------
+%
+%% Not possible to send password with openssh without user interaction
+%%
+%%--------------------------------------------------------------------
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+receive_hej() ->
+ receive
+ <<"Hej\n">> = Hej->
+ test_server:format("Expected result: ~p~n", [Hej]);
+ Info ->
+ test_server:format("Extra info: ~p~n", [Info]),
+ receive_hej()
+ end.
diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk
index 51f9f47446..fe2b915d17 100644
--- a/lib/ssh/vsn.mk
+++ b/lib/ssh/vsn.mk
@@ -1,5 +1,5 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
-SSH_VSN = 2.0.4
+SSH_VSN = 2.0.8
APP_VSN = "ssh-$(SSH_VSN)"
diff --git a/lib/ssl/Makefile b/lib/ssl/Makefile
index daad7dc3e6..a7a95004a6 100644
--- a/lib/ssl/Makefile
+++ b/lib/ssl/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2010. All Rights Reserved.
+# Copyright Ericsson AB 1999-2011. All Rights Reserved.
#
# The 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,7 +25,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
# Macros
#
-SUB_DIRECTORIES = src c_src doc/src examples/certs examples/src
+SUB_DIRECTORIES = src doc/src examples/certs examples/src
include vsn.mk
VSN = $(SSL_VSN)
diff --git a/lib/ssl/c_src/Makefile b/lib/ssl/c_src/Makefile
deleted file mode 100644
index 52d9140153..0000000000
--- a/lib/ssl/c_src/Makefile
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2009. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-
-#
-
-#
-# Invoke with GNU make or clearmake -C gnu.
-#
-
-include $(ERL_TOP)/make/run_make.mk
diff --git a/lib/ssl/c_src/Makefile.dist b/lib/ssl/c_src/Makefile.dist
deleted file mode 100644
index 2468468921..0000000000
--- a/lib/ssl/c_src/Makefile.dist
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2009. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-
-# Makefile for SSL on Unix
-#
-# Placed in obj directory.
-#
-CC = gcc
-
-BINDIR = %BINDIR%
-LIBS = %LIBS%
-SSL_LIBDIR = %SSL_LIBDIR%
-OBJS = %OBJS%
-
-$(BINDIR)/ssl_esock: $(OBJS)
- $(CC) -L$(SSL_LIBDIR) -Wl,-R$(SSL_LIBDIR) -o $@ $^ \
- $(LIBS) -lssl -lcrypto
diff --git a/lib/ssl/c_src/Makefile.in b/lib/ssl/c_src/Makefile.in
deleted file mode 100644
index 49a209f2eb..0000000000
--- a/lib/ssl/c_src/Makefile.in
+++ /dev/null
@@ -1,213 +0,0 @@
-#
-# %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%
-#
-
-#
-# Makefile only for Unix and Win32/Cygwin.
-#
-
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-# ----------------------------------------------------
-# SSL locations and include options from configure
-# ----------------------------------------------------
-SSL_LIBDIR = @SSL_LIBDIR@
-SSL_INCLUDE = @SSL_INCLUDE@
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(SSL_VSN)
-
-# ----------------------------------------------------
-# Commands
-# ----------------------------------------------------
-CC = @CC@
-LD = @LD@
-SHELL = /bin/sh
-LIBS = @LIBS@
-PLAIN_CFLAGS = @CFLAGS@
-
-# ----------------------------------------------------
-# Includes and libs
-# ----------------------------------------------------
-
-ALL_CFLAGS = @WFLAGS@ @CFLAGS@ @DEFS@ $(TYPE_FLAGS)
-TARGET = @host@
-
-ifeq ($(TYPE),debug)
-TYPEMARKER = .debug
-TYPE_FLAGS = -g -DDEBUG @DEBUG_FLAGS@
-else
-TYPEMARKER =
-TYPE_FLAGS = -O2
-endif
-
-PRIVDIR = ../priv
-BINDIR = $(PRIVDIR)/bin/$(TARGET)
-OBJDIR = $(PRIVDIR)/obj/$(TARGET)
-
-# ----------------------------------------------------
-# File suffixes
-# ----------------------------------------------------
-exe = @EXEEXT@
-obj = .@OBJEXT@
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/ssl-$(VSN)
-
-# ----------------------------------------------------
-# Common Macros
-# ----------------------------------------------------
-OBJS = $(OBJDIR)/esock$(obj) \
- $(OBJDIR)/debuglog$(obj) \
- $(OBJDIR)/esock_poll$(obj) \
- $(OBJDIR)/esock_osio$(obj) \
- $(OBJDIR)/esock_utils$(obj) \
- $(OBJDIR)/esock_posix_str$(obj) \
- $(OBJDIR)/esock_openssl$(obj)
-
-PORT_PROGRAM = $(BINDIR)/ssl_esock$(exe)
-
-SKIP_BUILDING_BINARIES := false
-
-# Try to be BC for R10
-ifeq ($(findstring @SSL_,@SSL_DYNAMIC_ONLY@),@SSL_)
-DYNAMIC_CRYPTO_LIB=yes
-else
-DYNAMIC_CRYPTO_LIB=@SSL_DYNAMIC_ONLY@
-endif
-
-
-ifeq ($(DYNAMIC_CRYPTO_LIB),yes)
-
-ifneq ($(findstring win32,$(TARGET)),win32)
-SSL_MAKEFILE = $(OBJDIR)/Makefile
-else
-SSL_MAKEFILE =
-endif
-
-CC_R_FLAG=@CFLAG_RUNTIME_LIBRARY_PATH@
-
-ifeq ($(findstring @,$(CC_R_FLAG)),@)
-# Old erts configure used which hasn't replaced @CFLAG_RUNTIME_LIBRARY_PATH@;
-# we try our best here instead...
-
-ifeq ($(findstring darwin,$(TARGET)),darwin) # darwin: no flag
-CC_R_FLAG =
-else
-ifeq ($(findstring osf,$(TARGET)),osf) # osf1: -Wl,-rpath,
-CC_R_FLAG = -Wl,-rpath,
-else # Default: -Wl,-R
-CC_R_FLAG = -Wl,-R
-endif
-endif
-endif
-
-ifeq ($(strip $(CC_R_FLAG)),)
-CC_R_OPT =
-else
-CC_R_OPT = $(CC_R_FLAG)$(SSL_LIBDIR)
-endif
-
-SSL_CC_RUNTIME_LIBRARY_PATH=@SSL_CC_RUNTIME_LIBRARY_PATH@
-# Sigh...
-ifeq ($(findstring @,$(SSL_CC_RUNTIME_LIBRARY_PATH)),@)
-SSL_CC_RUNTIME_LIBRARY_PATH = $(CC_R_OPT)
-endif
-
-SSL_LINK_LIB=-L$(SSL_LIBDIR) -lssl -lcrypto
-else
-# not dynamic crypto lib (default from R11B-5)
-NEED_KERBEROS=@SSL_LINK_WITH_KERBEROS@
-NEED_ZLIB=@SSL_LINK_WITH_ZLIB@
-SSL_MAKEFILE =
-CC_R_OPT =
-SSL_CC_RUNTIME_LIBRARY_PATH=
-SSL_LINK_LIB = $(SSL_LIBDIR)/libssl.a $(SSL_LIBDIR)/libcrypto.a
-ifeq ($(NEED_KERBEROS),yes)
-SSL_LINK_LIB += @STATIC_KERBEROS_LIBS@
-endif
-ifeq ($(NEED_ZLIB),yes)
-SSL_LINK_LIB += @STATIC_ZLIB_LIBS@
-endif
-endif
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt: $(OBJDIR) $(BINDIR) $(OBJS) $(PORT_PROGRAM) $(SSL_MAKEFILE)
-
-$(OBJDIR):
- -@mkdir -p $(OBJDIR)
-
-$(BINDIR):
- -@mkdir -p $(BINDIR)
-
-$(OBJDIR)/esock_openssl$(obj): esock_openssl.c
- $(CC) -c -o $@ $(ALL_CFLAGS) $(SSL_INCLUDE) $<
-
-$(OBJDIR)/%$(obj): %.c
- $(CC) -c -o $@ $(ALL_CFLAGS) $<
-
-# Unix
-$(BINDIR)/ssl_esock: $(OBJS)
- $(CC) $(PLAIN_CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) $(SSL_CC_RUNTIME_LIBRARY_PATH) $(SSL_LINK_LIB)
-
-# Win32/Cygwin
-$(BINDIR)/ssl_esock.exe: $(OBJS)
- $(LD) $(SSL_CC_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) -o $@ $^ -lwsock32 -llibeay32 -lssleay32
-
-# Unix only, and only when linking statically
-$(SSL_MAKEFILE):
- sed -e "s;%BINDIR%;../../bin/$(TARGET);" \
- -e "s;%SSL_LIBDIR%;$(SSL_LIBDIR);" \
- -e "s;%OBJS;$(OBJS);" \
- -e "s;%LIBS%;$(LIBS);" ./Makefile.dist \
- > $(OBJDIR)/Makefile
-
-
-clean:
- rm -f $(PORT_PROGRAM) $(OBJS) core *~ $(SSL_MAKEFILE)
-
-docs:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/priv/bin
- $(INSTALL_PROGRAM) $(PORT_PROGRAM) $(RELSYSDIR)/priv/bin
-ifneq ($(SSL_MAKEFILE),)
- $(INSTALL_DIR) $(RELSYSDIR)/priv/obj
- $(INSTALL_DATA) $(OBJS) $(RELSYSDIR)/priv/obj
- sed -e "s;%BINDIR%;../bin;" \
- -e "s;%SSL_LIBDIR%;$(SSL_LIBDIR);" \
- -e "s;%OBJS;$(OBJS);" \
- -e "s;%LIBS%;$(LIBS);" ./Makefile.dist \
- > $(RELSYSDIR)/priv/obj/Makefile
-endif
-
-release_docs_spec:
-
diff --git a/lib/ssl/c_src/Makefile.win32 b/lib/ssl/c_src/Makefile.win32
deleted file mode 100644
index 668cd2a28d..0000000000
--- a/lib/ssl/c_src/Makefile.win32
+++ /dev/null
@@ -1,147 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2009. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-
-#
-# SSL - Makefile for Windows NT
-#
-# It is assumed that the following environment variables have been set:
-#
-# INCLUDE X:\MSDEV\INCLUDE
-# LIB X:\MSDEV\LIB
-#
-# so that standard include files, and the socket library can be found.
-#
-# When ssl_esock.exe is run, the PATH environment variable must contain
-# the name of a directory that contains ssleay32.dll and libeay32.dll,
-# and windows socket dll.
-#
-
-# Roots
-!ifndef OPENSSL_ROOT
-! error "Makefile.win32: ssl: OPENSSL_ROOT not set"
-!endif
-
-TARGET = win32
-
-BINDIR = ..\priv\bin\$(TARGET)
-OBJDIR = ..\priv\obj\$(TARGET)
-
-!if !exist($(BINDIR))
-! if [mkdir $(BINDIR)]
-! error "SSL: cannot create BINDIR"
-! endif
-!endif
-
-!if !exist($(OBJDIR))
-! if [mkdir $(OBJDIR)]
-! error "SSL: cannot create OBJDIR"
-! endif
-!endif
-
-# Includes
-#
-OPENSSL_INCLUDE = $(OPENSSL_ROOT)\inc32
-
-INCLUDES = /I. /I$(OPENSSL_INCLUDE)
-
-# Libraries
-#
-OPENSSL_LIBDIR = $(OPENSSL_ROOT)\out32dll
-OPENSSL_LIBS = \
- $(OPENSSL_LIBDIR)\ssleay32.lib \
- $(OPENSSL_LIBDIR)\libeay32.lib
-
-!ifdef ESOCK_WINSOCK2
-WINSOCK_LIB = ws2_32.lib
-DEFS = -DESOCK_WINSOCK2
-!else
-WINSOCK_LIB = wsock32.lib
-!endif
-
-# Compiler options
-#
-# NOTE: Size of fd_set is set in esock_winsock.h but can be overridden
-# with a -D option here.
-#
-OPTS = /MDd /G5 /Ox /O2 /Ob2 /Z7
-DEFS = -D__WIN32__ -DWIN32 $(DEFS)
-CFLAGS = $(INCLUDES) /nologo $(OPTS) $(DEFS)
-
-# Object files
-#
-SSL_BASE_OBJS = \
- $(OBJDIR)\esock.obj \
- $(OBJDIR)\debuglog.obj \
- $(OBJDIR)\esock_poll$(obj) \
- $(OBJDIR)\esock_osio.obj \
- $(OBJDIR)\esock_utils.obj \
- $(OBJDIR)\esock_posix_str.obj
-
-OPENSSL_OBJS = \
- $(OBJDIR)\esock_openssl.obj
-
-#
-# Targets
-#
-
-all: $(SSL_BASE_OBJS) $(OPENSSL_OBJS) $(BINDIR)\ssl_esock.exe
-
-clean:
- del $(BINDIR)\*.exe
- del $(OBJDIR)\*.obj
-
-# Inference rule .c.obj:
-#
-{.}.c{$(OBJDIR)}.obj:
- $(CC) $(CFLAGS) /c /Fo$@ $(*B).c
-
-# Binary
-#
-$(BINDIR)\ssl_esock.exe: $(SSL_BASE_OBJS) $(OPENSSL_OBJS)
- $(CC) /nologo $(SSL_BASE_OBJS) $(OPENSSL_OBJS) $(OPENSSL_LIBS) \
- $(WINSOCK_LIB) /Fe$(BINDIR)\ssl_esock.exe
-
-
-
-# Dependencies
-#
-$(OBJDIR)\esock.o: esock.h debuglog.h esock_ssl.h esock_osio.h \
- esock_utils.h esock_winsock.h
-$(OBJDIR)\debuglog.o: debuglog.h esock_ssl.h esock_utils.h
-$(OBJDIR)\esock_osio.o: esock_osio.h esock.h debuglog.h esock_utils.h \
- esock_winsock.h
-$(OBJDIR)\esock_utils.o: esock_utils.h
-$(OBJDIR)\esock_posix_str.o: esock_posix_str.h esock_winsock.h
-
-$(OBJDIR)\esock_openssl.o: esock.h esock_ssl.h debuglog.h esock_utils.h \
- $(OPENSSL_INCLUDE)\crypto.h \
- $(OPENSSL_INCLUDE)\ssl.h \
- $(OPENSSL_INCLUDE)\err.h
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ssl/c_src/Makefile.win32.dist b/lib/ssl/c_src/Makefile.win32.dist
deleted file mode 100644
index 8510c44e08..0000000000
--- a/lib/ssl/c_src/Makefile.win32.dist
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2009. All Rights Reserved.
-#
-# The contents of this file are subject to the Erlang Public License,
-# Version 1.1, (the "License"); you may not use this file except in
-# compliance with the License. You should have received a copy of the
-# Erlang Public License along with this software. If not, it can be
-# retrieved online at http://www.erlang.org/.
-#
-# Software distributed under the License is distributed on an "AS IS"
-# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-# the License for the specific language governing rights and limitations
-# under the License.
-#
-# %CopyrightEnd%
-#
-
-# Makefile.win32.dist for SSL
-#
-# To be placed in obj directory.
-#
-
-CC = cl
-
-BINDIR = %BINDIR%
-
-OPENSSL_LIBS = \
- $(BINDIR)\ssleay32.lib \
- $(BINDIR)\libeay32.lib
-
-WINSOCK_LIB = ws2_32.lib
-
-SSL_BASE_OBJS = esock.obj debuglog.obj esock_osio.obj esock_utils.obj \
- esock_posix_str.obj
-
-OPENSSL_OBJS = esock_openssl.obj
-
-$(BINDIR)\ssl_esock.exe: $(SSL_BASE_OBJS) $(OPENSSL_OBJS)
- $(CC) /nologo $(SSL_BASE_OBJS) $(OPENSSL_OBJS) $(OPENSSL_LIBS) \
- $(WINSOCK_LIB) /Fe$(BINDIR)\ssl_esock.exe
-
-
-
diff --git a/lib/ssl/c_src/debuglog.c b/lib/ssl/c_src/debuglog.c
deleted file mode 100644
index e2e55df4b2..0000000000
--- a/lib/ssl/c_src/debuglog.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*<copyright>
- * <year>1999-2008</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>
- */
-/*
- * Purpose: Various routines for debug printouts and logs.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-#include "debuglog.h"
-#include "esock_utils.h"
-
-#ifndef __WIN32__
-static char tr_format_buf[256];
-static char *tr_format(const char *format);
-static int vfprintclistf(FILE *fp, const char *format, va_list args);
-#endif
-
-int debug = 0;
-int debugmsg = 0;
-FILE *ssllogfp = NULL;
-FILE *__locallogfp = NULL;
-
-void open_ssllog(char *path)
-{
- ssllogfp = openlog(path);
-}
-
-void close_ssllog(void)
-{
- if (ssllogfp)
- closelog(ssllogfp);
-}
-
-FILE *openlog(char *s)
-{
- FILE *fp;
- time_t t = time(NULL);
-
- if ((fp = fopen(s, "a"))) {
- setbuf(fp, NULL);
- fprintf(fp, "===== Opened [%s] %s", s, ctime(&t));
- }
- return fp;
-}
-
-void closelog(FILE *fp)
-{
- time_t t = time(NULL);
-
- if (fp) {
- fprintf(fp, "Closed %s", ctime(&t));
- fclose(fp);
- }
-}
-
-int __debugprintf(const char *format, ...)
-{
- va_list args;
- int ret;
-#ifndef __WIN32__
- char *newformat;
-
- va_start(args, format);
- newformat = tr_format(format);
- ret = vfprintf(stderr, newformat, args);
- if (newformat != format && newformat != tr_format_buf)
- esock_free(newformat);
-#else
- va_start(args, format);
- ret = vfprintf(stderr, format, args);
-#endif
- va_end(args);
- if (ssllogfp) {
- va_start(args, format);
- vfprintf(ssllogfp, format, args);
- va_end(args);
- }
- return ret;
-}
-
-int __debugprintclistf(const char *format, ...)
-{
- va_list args;
- int ret;
-#ifndef __WIN32__
- char *newformat;
-
- va_start(args, format);
- newformat = tr_format(format);
- ret = vfprintclistf(stderr, newformat, args);
- if (newformat != format && newformat != tr_format_buf)
- esock_free(newformat);
-#else
- va_start(args, format);
- ret = vfprintclistf(stderr, format, args);
-#endif
- if (ssllogfp)
- vfprintclistf(ssllogfp, format, args);
- va_end(args);
- return ret;
-}
-
-int __debuglogf(const char *format, ...)
-{
- va_list args;
- int ret;
-
- va_start(args, format);
- ret = vfprintf(__locallogfp, format, args);
- va_end(args);
- return ret;
-}
-
-#ifndef __WIN32__
-
-/* Insert `\r' before each `\n' i format */
-static char *tr_format(const char *format)
-{
- char *newformat, *s, *t;
- int len;
-
- len = strlen(format);
- if ((newformat = (len > 127) ? esock_malloc(len) : tr_format_buf)) {
- for (s = (char *)format, t = newformat; *s; *t++ = *s++)
- if (*s == '\n')
- *t++ = '\r';
- *t = '\0';
- } else
- newformat = (char *)format;
- return newformat;
-}
-
-#endif
-
-/* This function is for printing arrays of characters with formats
- * %FPa or %FPb, where F and P are the ordinary specifiers for
- * field width and precision, respectively.
- *
- * The conversion specifier `a' implies hex-string output, while
- * the `b' specifier provides character output (for non-printable
- * characters a `.' is written.
- *
- * The F specifier contains the width for each character. The
- * P specifier tells how many characters to print.
- *
- * Example: Suppose we have a function myprintf(char *format, ...)
- * that calls our vfprintclistf(), and that
- *
- * char buf[] = "h\r\n";
- * len = 3;
- *
- * Then
- *
- * myprintf("%.2b", buf) prints "h."
- * myprintf("%2.3b", buf) prints "h . . "
- * myprintf("%3.*a", len, buf) prints "68 0d 0a"
- *
- */
-
-static int vfprintclistf(FILE *fp, const char *format, va_list args)
-{
-
- int i, len, width, prec, written = 0;
- char *s, *prevs, *fstart;
- unsigned char *buf;
-
- if (!format || !*format)
- return 0;
-
- /* %{[0-9]*|\*}{.{[0-9]*|\*}{a|b} */
-
- prevs = (char *)format; /* format is const */
- s = strchr(format, '%');
- while (s && *s) {
- if (s - prevs > 0)
- written += fprintf(fp, "%.*s", s - prevs, prevs);
- width = prec = 0;
- fstart = s;
- s++;
- if (*s != '%') { /* otherwise it is not a format */
- if (*s == '*') { /* width in arg */
- s++;
- width = va_arg(args, int);
- } else if ((len = strspn(s, "0123456789"))) { /* const width */
- width = atoi(s);
- s += len;
- } else
- width = 0;
- if (*s == '.') { /* precision specified */
- s++;
- if (*s == '*') { /* precision in arg */
- s++;
- prec = va_arg(args, int);
- } else if ((len = strspn(s, "0123456789"))) { /* const prec */
- prec = atoi(s);
- s += len;
- } else /* no precision value, defaults to zero */
- prec = 0;
- } else
- prec = 0; /* no precision defaults to zero */
- if (*s == 'a' || *s == 'b') { /* only valid specifiers */
- buf = va_arg(args, unsigned char *);
- if (*s == 'a') {
- for (i = 0; i < prec; i++)
- written += fprintf(fp, "%*.2x", width, buf[i]);
- }else if (*s == 'b') {
- for (i = 0; i < prec; i++) {
- if (isprint(buf[i]))
- written += fprintf(fp, "%*c", width, buf[i]);
- else
- written += fprintf(fp, "%*c", width, '.');
- }
- }
- } else {
- fprintf(stderr, "fprintclistf: format \"%s\" invalid.\n",
- format);
- va_end(args);
- return written;
- }
- }
- s++;
- /* Now s points to the next character after the format */
- prevs = s;
- s = strchr(s, '%');
- }
- if (format + strlen(format) + 1 - prevs > 0)
- written += fprintf(fp, "%s", prevs);
- return written;
-}
-
diff --git a/lib/ssl/c_src/debuglog.h b/lib/ssl/c_src/debuglog.h
deleted file mode 100644
index 5699e6b495..0000000000
--- a/lib/ssl/c_src/debuglog.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*<copyright>
- * <year>1998-2008</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>
- */
-/*
- * Purpose: Debug functions and macros.
- *
- */
-
-#ifndef __DEBUGLOG_H_
-#define __DEBUGLOG_H_
-
-#include <stdio.h>
-#include "esock_ssl.h"
-
-#define DEBUGF(x) if (debug) __debugprintf x;
-#define DEBUGMSGF(x) if (debugmsg) __debugprintclistf x;
-#define LOGF(fp, x) if (fp) { __locallogfp = fp; __debuglogf x; }
-#define SSLDEBUGF() if (debug) { esock_ssl_print_errors_fp(stderr); \
- if (ssllogfp) esock_ssl_print_errors_fp(ssllogfp); }
-
-int debug;
-int debugmsg;
-FILE *ssllogfp;
-FILE *__locallogfp;
-
-void open_ssllog(char *path);
-void close_ssllog(void);
-FILE *openlog(char *);
-void closelog(FILE *);
-int __debugprintf(const char *, ...);
-int __debugprintclistf(const char *, ...);
-int __debuglogf(const char *, ...);
-
-#endif
diff --git a/lib/ssl/c_src/esock.c b/lib/ssl/c_src/esock.c
deleted file mode 100644
index 78d08f7c29..0000000000
--- a/lib/ssl/c_src/esock.c
+++ /dev/null
@@ -1,1904 +0,0 @@
-/*<copyright>
- * <year>1999-2008</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>
- */
-
-/*
- * Purpose: Implementation of Secure Socket Layer (SSL).
- *
- * This is an "SSL proxy" for Erlang in the form of a port
- * program.
- *
- * The implementation has borrowed somewhat from the original
- * implementation of `socket' by Claes Wikstr�m, and the former
- * implementation of `ssl_socket' by Helen Ariyan.
- *
- * All I/O is now non-blocking.
- *
- * When a connection (cp) is in the state JOINED we have the following
- * picture:
- *
- * proxy->fd fd
- * | |
- * proxy->eof | --------> wq -----------> | bp
- * | |
- * Erlang | | SSL
- * | |
- * proxy->bp | <------ proxy->wq --------- | eof
- * | |
- *
- * We read from Erlang (proxy->fd) and write to SSL (fd); and read from
- * SSL (fd) and write to Erlang (proxy->fd).
- *
- * The variables bp (broken pipe) and eof (end of file) take the
- * values 0 and 1.
- *
- * What has been read and cannot be immediately written is put in a
- * write queue (wq). A wq is emptied before reads are continued, which
- * means that at most one chunk that is read can be in a wq.
- *
- * The proxy-to-ssl part of a cp is valid iff
- *
- * !bp && (wq.len > 0 || !proxy->eof).
- *
- * The ssl-to-proxy part of a cp is valid iff
- *
- * !proxy->bp && (proxy->wq.len > 0 || !eof).
- *
- * The connection is valid if any of the above parts are valid, i.e.
- * invalid if both parts are invalid.
- *
- * Every SELECT_TIMEOUT second we try to write to those file
- * descriptors that have non-empty wq's (the only way to detect that a
- * far end has gone away is to write to it).
- *
- * STATE TRANSITIONS
- *
- * Below (*) means that the corresponding file descriptor is published
- * (i.e. kwown outside this port program) when the state is entered,
- * and thus cannot be closed without synchronization with the
- * ssl_server.
- *
- * Listen:
- *
- * STATE_NONE ---> (*) PASSIVE_LISTENING <---> ACTIVE_LISTENING
- *
- * Accept:
- *
- * STATE_NONE ---> SSL_ACCEPT ---> (*) CONNECTED ---> JOINED --->
- * ---> SSL_SHUTDOWN ---> DEFUNCT
- *
- * Connect:
- *
- * STATE_NONE ---> (*) WAIT_CONNECT ---> SSL_CONNECT ---> CONNECTED --->
- * ---> JOINED ---> SSL_SHUTDOWN ---> DEFUNCT
- *
- * In states where file descriptors has been published, and where
- * something goes wrong, the state of the connection is set to
- * DEFUNCT. A connection in such a state can only be closed by a CLOSE
- * message from Erlang (a reception of such a message is registered in
- * cp->closed). The possible states are: WAIT_CONNECT, SSL_CONNECT,
- * CONNECTED, JOINED, and SSL_SHUTDOWN.
- *
- * A connection in state SSL_ACCEPT can be closed and removed without
- * synchronization.
- *
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef __WIN32__
-#include "esock_winsock.h"
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <time.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <errno.h>
-
-#ifdef __WIN32__
-#include <process.h>
-#else
-#include <unistd.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <sys/time.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#endif
-
-#ifndef INADDR_NONE
-#define INADDR_NONE 0xffffffff /* Should be in <netinet/in.h>. */
-#endif
-
-#include "esock.h"
-#include "debuglog.h"
-#include "esock_utils.h"
-#include "esock_ssl.h"
-#include "esock_osio.h"
-#include "esock_posix_str.h"
-#include "esock_poll.h"
-
-#define MAJOR_VERSION 2
-#define MINOR_VERSION 0
-#define MAXREPLYBUF 256
-#define RWBUFLEN (32*1024)
-#define IS_CLIENT 0
-#define IS_SERVER 1
-#define SELECT_TIMEOUT 2 /* seconds */
-
-#define psx_errstr() esock_posix_str(sock_errno())
-#define ssl_errstr() esock_ssl_errstr
-
-#define PROXY_TO_SSL_VALID(cp) (!(cp)->bp && \
- ((cp)->wq.len > 0 || !(cp)->proxy->eof))
-
-#define SSL_TO_PROXY_VALID(cp) (!(cp)->proxy->bp && \
- ((cp)->proxy->wq.len > 0 || !(cp)->eof))
-
-#define JOINED_STATE_INVALID(cp) (!(PROXY_TO_SSL_VALID(cp)) && \
- !(SSL_TO_PROXY_VALID(cp)))
-static int loop(void);
-static int set_poll_conns(Connection *cp, EsockPoll *ep, int verbose);
-static Connection *next_polled_conn(Connection *cp, Connection **cpnext,
- EsockPoll *ep, int set_wq_fds);
-
-static void leave_joined_state(Connection *cp);
-static void do_shutdown(Connection *cp);
-static void close_and_remove_connection(Connection *cp);
-static int reply(int cmd, char *fmt, ...);
-static int input(char *fmt, ...);
-static int put_pars(unsigned char *buf, char *fmt, va_list args);
-static int get_pars(unsigned char *buf, char *fmt, va_list args);
-static FD do_connect(char *lipstring, int lport, char *fipstring, int fport);
-static FD do_listen(char *ipstring, int lport, int backlog, int *aport);
-static FD do_accept(FD listensock, struct sockaddr *saddr, int *len);
-static void print_connections(void);
-static void dump_connections(void);
-static int check_num_sock_fds(FD fd);
-static void safe_close(FD fd);
-static Connection *new_connection(int state, FD fd);
-static Connection *get_connection(FD fd);
-static void remove_connection(Connection *conn);
-static Proxy *get_proxy_by_peerport(int port);
-static Proxy *new_proxy(FD fd);
-static void remove_proxy(Proxy *proxy);
-static void ensure_write_queue(WriteQueue *wq, int size);
-static void clean_up(void);
-
-static Connection *connections = NULL;
-static int num_sock_fds; /* On UNIX all file descriptors */
-static Proxy *proxies = NULL;
-static int proxy_listensock = INVALID_FD;
-static int proxy_listenport = 0;
-static int proxy_backlog = 128;
-static int proxysock_last_err = 0;
-static int proxysock_err_cnt = 0;
-static char rwbuf[RWBUFLEN];
-static unsigned char *ebuf = NULL; /* Set by read_ctrl() */
-
-static char *connstr[] = {
- "STATE_NONE",
- "ACTIVE_LISTENING",
- "PASSIVE_LISTENING",
- "CONNECTED",
- "WAIT_CONNECT",
- "SSL_CONNECT",
- "SSL_ACCEPT",
- "TRANSPORT_ACCEPT",
- "JOINED",
- "SSL_SHUTDOWN",
- "DEFUNCT"
-};
-
-static char *originstr[] = {
- "listen",
- "accept",
- "connect"
-};
-
-int main(int argc, char **argv)
-{
- char *logfile = NULL;
- int i;
- esock_version *vsn;
- char *ciphers;
-#ifdef __WIN32__
- int pid;
- WORD version;
- WSADATA wsa_data;
-
- set_binary_mode();
- setvbuf(stderr, NULL, _IONBF, 0);
- /* Two sockets for the stdin socket pipe (local thread). */
- num_sock_fds = 2;
-#else
- pid_t pid;
- num_sock_fds = 3; /* 0, 1, 2 */
-#endif
-
- pid = getpid();
- i = 1;
- while (i < argc) {
- if (strcmp(argv[i], "-d") == 0) {
- debug = 1;
- i++;
- } else if (strcmp(argv[i], "-dm") == 0) {
- debugmsg = 1;
- i++;
- } else if (strcmp(argv[i], "-pp") == 0) {
- i++;
- proxy_listenport = atoi(argv[i]);
- i++;
- } else if (strcmp(argv[i], "-pb") == 0) {
- i++;
- proxy_backlog = atoi(argv[i]);
- i++;
- } else if (strcmp(argv[i], "-pv") == 0) {
- i++;
- protocol_version = atoi(argv[i]);
- i++;
- } else if (strcmp(argv[i], "-dd") == 0) {
- i++;
- logfile = esock_malloc(strlen(argv[i]) + 64);
- sprintf(logfile, "%s/ssl_esock.%d.log", argv[i], (int)pid);
- i++;
- } else if (strcmp(argv[i], "-ersa") == 0) {
- ephemeral_rsa = 1;
- i++;
- } else if (strcmp(argv[i], "-edh") == 0) {
- ephemeral_dh = 1;
- i++;
- }
- }
- if (debug || debugmsg) {
- DEBUGF(("Starting ssl_esock\n"));
- if (logfile) {
- open_ssllog(logfile);
-#ifndef __WIN32__
- num_sock_fds++;
-#endif
- }
- atexit(close_ssllog);
- DEBUGF(("pid = %d\n", getpid()));
- }
- if (esock_ssl_init() < 0) {
- fprintf(stderr, "esock: Could not do esock_ssl_init\n");
- exit(EXIT_FAILURE);
- }
-
- atexit(esock_ssl_finish);
-
-#ifdef __WIN32__
- /* Start Windows' sockets */
- version = MAKEWORD(MAJOR_VERSION, MINOR_VERSION);
- if (WSAStartup(version, &wsa_data) != 0) {
- fprintf(stderr, "esock: Could not start up Windows' sockets\n");
- exit(EXIT_FAILURE);
- }
- atexit((void (*)(void))WSACleanup);
- if (LOBYTE(wsa_data.wVersion) < MAJOR_VERSION ||
- (LOBYTE(wsa_data.wVersion) == MAJOR_VERSION &&
- HIBYTE(wsa_data.wVersion) < MINOR_VERSION)) {
- fprintf(stderr, "esock: Windows socket version error. "
- "Requested version:"
- "%d.%d, version found: %d.%d\n", MAJOR_VERSION,
- MINOR_VERSION, LOBYTE(wsa_data.wVersion),
- HIBYTE(wsa_data.wVersion));
- exit(EXIT_FAILURE);
- }
- DEBUGF(("Using Windows socket version: %d.%d\n",
- LOBYTE(wsa_data.wVersion), HIBYTE(wsa_data.wVersion)));
- DEBUGF(("Maximum number of sockets available: %d\n",
- wsa_data.iMaxSockets));
-
- if (esock_osio_init() < 0) {
- fprintf(stderr, "esock: Could not init osio\n");
- exit(EXIT_FAILURE);
- }
- atexit(esock_osio_finish);
-#endif
-
- /* Create the local proxy listen socket and set it to non-blocking */
- proxy_listensock = do_listen("127.0.0.1", proxy_listenport,
- proxy_backlog, &proxy_listenport);
- if (proxy_listensock == INVALID_FD) {
- fprintf(stderr, "esock: Cannot create local listen socket\n");
- exit(EXIT_FAILURE);
- }
- SET_NONBLOCKING(proxy_listensock);
- DEBUGF(("Local proxy listen socket: fd = %d, port = %d\n",
- proxy_listensock, proxy_listenport));
-
- vsn = esock_ssl_version();
- ciphers = esock_ssl_ciphers();
-
- /* Report: port number of the local proxy listen socket, the native
- * os pid, the compile and lib versions of the ssl library, and
- * the list of available ciphers. */
- reply(ESOCK_PROXY_PORT_REP, "24sss", proxy_listenport, (int)pid,
- vsn->compile_version, vsn->lib_version, ciphers);
-
- atexit(clean_up);
-
- loop();
-
- if (logfile)
- esock_free(logfile);
- exit(EXIT_SUCCESS);
-}
-
-
-/*
- * Local functions
- *
- */
-
-static int loop(void)
-{
- EsockPoll pollfd;
- FD fd, msgsock, listensock, connectsock, proxysock;
- int cc, wc, fport, lport, pport, length, backlog, intref, op;
- int value;
- char *lipstring, *fipstring;
- char *flags;
- char *protocol_vsn, *cipher;
- unsigned char *cert, *bin;
- int certlen, binlen;
- struct sockaddr_in iserv_addr;
- int sret = 1;
- Connection *cp, *cpnext, *newcp;
- Proxy *pp;
- time_t last_time = 0, now = 0;
- int set_wq_fds;
-
- esock_poll_init(&pollfd);
-
- while(1) {
- esock_poll_zero(&pollfd);
- esock_poll_fd_set_read(&pollfd, proxy_listensock);
- esock_poll_fd_set_read(&pollfd, local_read_fd);
-
- set_wq_fds = 0;
-
- if (sret) /* sret == 1 the first time. */
- DEBUGF(("==========LOOP=============\n"));
-
- cc = set_poll_conns(connections, &pollfd, sret) + 1;
-
- if (sret) {
- print_connections();
- DEBUGF(("Before poll/select: %d descriptor%s (total %d)\n",
- cc, (cc == 1) ? "" : "s", num_sock_fds));
- }
-
- sret = esock_poll(&pollfd, SELECT_TIMEOUT);
- if (sret < 0) {
- DEBUGF(("select/poll error: %s\n", psx_errstr()));
- continue;
- }
-
- time(&now);
- if (now >= last_time + SELECT_TIMEOUT) {
- set_wq_fds = 1;
- last_time = now;
- }
- /*
- * First accept as many connections as possible on the
- * proxy listen socket. We record the peer port, which
- * is later used as a reference for joining a proxy
- * connection with a network connection.
- */
-
- if (esock_poll_fd_isset_read(&pollfd, proxy_listensock)) {
- while (1) {
- length = sizeof(iserv_addr);
- proxysock = do_accept(proxy_listensock,
- (struct sockaddr *)&iserv_addr,
- (int*)&length);
- if(proxysock == INVALID_FD) {
- if (sock_errno() != ERRNO_BLOCK) {
- /* We can here for example get the error
- * EMFILE, i.e. no more file descriptors
- * available, but we do not have any specific
- * connection to report the error to. We
- * increment the error counter and saves the
- * last err.
- */
- proxysock_err_cnt++;
- proxysock_last_err = sock_errno();
- DEBUGF(("accept error (proxy_listensock): %s\n",
- psx_errstr()));
- }
- break;
- } else {
- /* Get peer port number */
-/* length = sizeof(iserv_addr); */
-/* if (getpeername(proxysock, (struct sockaddr *)&iserv_addr, */
-/* &length) < 0) { */
-/* DEBUGF(("Can't get peername of proxy socket")); */
-/* safe_close(proxysock); */
-/* } else { */
- /* Add to pending proxy connections */
- SET_NONBLOCKING(proxysock);
- pp = new_proxy(proxysock);
- pp->peer_port = ntohs(iserv_addr.sin_port);
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("[PROXY_LISTEN_SOCK] conn accepted: "
- "proxyfd = %d, "
- "peer port = %d\n", proxysock, pp->peer_port));
-/* } */
- }
- }
- }
-
- /*
- * Read control messages from Erlang
- */
- if (esock_poll_fd_isset_read(&pollfd, local_read_fd)) {
- cc = read_ctrl(&ebuf);
- if ( cc < 0 ) {
- DEBUGF(("Read loop -1 or 0\n"));
- return -1;
- } else if (cc == 0) { /* not eof */
- DEBUGF(("GOT empty string \n"));
-
- } else {
-
- switch((int)*ebuf) {
-
- case ESOCK_SET_SEED_CMD:
- /*
- * ebuf = {cmd(1), binary(N) }
- */
- input("b", &binlen, &bin);
- DEBUGF(("[SET_SEED_CMD]\n"));
- esock_ssl_seed(bin, binlen);
- /* no reply */
- break;
-
- case ESOCK_GETPEERNAME_CMD:
- /*
- * ebuf = {cmd(1), fd(4)}
- */
- input("4", &fd);
- DEBUGF(("[GETPEERNAME_CMD] fd = %d\n", fd));
- cp = get_connection(fd);
- length = sizeof(iserv_addr);
- if (!cp) {
- sock_set_errno(ERRNO_NOTSOCK);
- reply(ESOCK_GETPEERNAME_ERR, "4s", fd, psx_errstr());
- } else if (getpeername(fd,
- (struct sockaddr *) &iserv_addr,
- &length) < 0) {
- reply(ESOCK_GETPEERNAME_ERR, "4s", fd, psx_errstr());
- } else {
- /*
- * reply = {cmd(1), fd(4), port(2),
- * ipstring(N), 0(1)}
- */
- reply(ESOCK_GETPEERNAME_REP, "42s", fd,
- ntohs(iserv_addr.sin_port),
- inet_ntoa(iserv_addr.sin_addr));
- }
- break;
-
- case ESOCK_GETSOCKNAME_CMD:
- /*
- * ebuf = {cmd(1), fd(4)}
- */
- input("4", &fd);
- DEBUGF(("[GETSOCKNAME_CMD] fd = %d\n", fd));
- cp = get_connection(fd);
- length = sizeof(iserv_addr);
- if (!cp) {
- sock_set_errno(ERRNO_NOTSOCK);
- reply(ESOCK_GETSOCKNAME_ERR, "4s", fd, psx_errstr());
- } else if (getsockname(fd,
- (struct sockaddr *)&iserv_addr,
- &length) < 0) {
- reply(ESOCK_GETSOCKNAME_ERR, "4s", fd, psx_errstr());
- } else {
- /*
- * reply = {cmd(1), fd(4), port(2),
- * ipstring(N), 0(1)}
- */
- reply(ESOCK_GETSOCKNAME_REP, "42s", fd,
- ntohs(iserv_addr.sin_port),
- inet_ntoa(iserv_addr.sin_addr));
- }
- break;
-
- case ESOCK_GETCONNINFO_CMD:
- /*
- * ebuf = {cmd(1), fd(4)}
- */
- input("4", &fd);
- DEBUGF(("[GETCONNINFO_CMD] fd = %d\n", fd));
- cp = get_connection(fd);
- if (!cp) {
- sock_set_errno(ERRNO_NOTSOCK);
- reply(ESOCK_GETCONNINFO_ERR, "4s", fd, psx_errstr());
- } else {
- if (esock_ssl_getprotocol_version(cp,
- &protocol_vsn) < 0)
- reply(ESOCK_GETCONNINFO_ERR, "4s", fd, psx_errstr());
- else if (esock_ssl_getcipher(cp, &cipher) < 0)
- reply(ESOCK_GETCONNINFO_ERR, "4s", fd, psx_errstr());
- else
- /*
- * reply = {cmd(1), fd(4), protocol(N), 0(1),
- * cipher(N), 0(1)}
- */
- reply(ESOCK_GETCONNINFO_REP, "4ss", fd,
- protocol_vsn, cipher);
- }
- break;
-
- case ESOCK_GETPEERCERT_CMD:
- /*
- * ebuf = {cmd(1), fd(4)}
- */
- input("4", &fd);
- DEBUGF(("[GETPEERCERT_CMD] fd = %d\n", fd));
- cp = get_connection(fd);
- if (!cp) {
- sock_set_errno(ERRNO_NOTSOCK);
- reply(ESOCK_GETPEERCERT_ERR, "4s", fd, psx_errstr());
- } else {
- if ((certlen = esock_ssl_getpeercert(cp, &cert)) < 0)
- reply(ESOCK_GETPEERCERT_ERR, "4s", fd, psx_errstr());
- else {
- /*
- * reply = {cmd(1), fd(4), certlen(4), cert(N)}
- */
- reply(ESOCK_GETPEERCERT_REP, "4b", fd,
- certlen, cert);
- esock_free(cert);
- }
- }
- break;
-
- case ESOCK_CONNECT_CMD:
- /*
- * ebuf = {cmd(1), intref(4),
- * lport(2), lipstring(N), 0(1), -- local
- * fport(2), fipstring(N), 0(1), -- foreign
- * flags(N), 0(1)}
- */
- input("42s2ss", &intref, &lport, &lipstring,
- &fport, &fipstring, &flags);
- DEBUGF(("[CONNECT_CMD] intref = %d, "
- "lipstring = %s lport = %d, "
- "fipstring = %s fport = %d, "
- "flags = %s\n", intref, lipstring, lport,
- fipstring, fport, flags));
- connectsock = do_connect(lipstring, lport,
- fipstring, fport);
- if(connectsock == INVALID_FD) {
- reply(ESOCK_CONNECT_SYNC_ERR, "4s", intref, psx_errstr());
- break;
- }
- DEBUGF((" fd = %d\n", connectsock));
- cp = new_connection(ESOCK_WAIT_CONNECT, connectsock);
- cp->origin = ORIG_CONNECT;
- length = strlen(flags);
- cp->flags = esock_malloc(length + 1);
- strcpy(cp->flags, flags);
- DEBUGF(("-> WAIT_CONNECT fd = %d\n", connectsock));
- /* Publish connectsock */
- reply(ESOCK_CONNECT_WAIT_REP, "44", intref, connectsock);
- break;
-
- case ESOCK_TERMINATE_CMD:
- /*
- * ebuf = {cmd(1)}
- */
- exit(EXIT_SUCCESS);
- break;
-
- case ESOCK_CLOSE_CMD:
- /*
- * ebuf = {cmd(1), fd(4)}
- */
- input("4", &fd);
- if ((cp = get_connection(fd))) {
- DEBUGF(("%s[CLOSE_CMD]: fd = %d\n",
- connstr[cp->state], fd));
- if (cp->proxy)
- cp->proxy->bp = 1;
- switch (cp->state) {
- case ESOCK_JOINED:
- cp->close = 1;
- if (JOINED_STATE_INVALID(cp))
- leave_joined_state(cp);
- break;
- case ESOCK_SSL_SHUTDOWN:
- cp->close = 1;
- DEBUGF((" close flag set\n"));
- break;
- default:
- DEBUGF(("-> (removal)\n"));
- close_and_remove_connection(cp);
- }
- } else
- DEBUGF(("[CLOSE_CMD]: ERROR: fd = %d not found\n", fd));
- break;
-
- case ESOCK_SET_SOCKOPT_CMD:
- /*
- * ebuf = {cmd(1), fd(4), op(1), on(1)}
- */
- input("411", &fd, &op, &value);
- switch(op) {
- case ESOCK_SET_TCP_NODELAY:
- if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
- (void *)&value, sizeof(value)) < 0) {
- DEBUGF(("Error: setsockopt TCP_NODELAY\n"));
- reply(ESOCK_IOCTL_ERR, "4s", fd, psx_errstr());
- } else {
- reply(ESOCK_IOCTL_OK, "4", fd);
- }
- break;
- default:
- DEBUGF(("Error: set_sock_opt - Not implemented\n"));
- sock_set_errno(ERRNO_OPNOTSUPP);
- reply(ESOCK_IOCTL_ERR, "4", fd, psx_errstr());
- break;
- }
- break;
-
- case ESOCK_LISTEN_CMD:
- /*
- * ebuf = {cmd(1), intref(4), lport(2), ipstring(N), 0(1),
- * backlog(2), flags(N), 0(1)}
- */
- input("42s2s", &intref, &lport, &lipstring, &backlog,
- &flags);
- DEBUGF(("[LISTEN_CMD] intref = %d, port = %d, "
- "ipstring = %s, backlog = %d, flags = %s\n",
- intref, lport, lipstring, backlog, flags));
-
- listensock = do_listen(lipstring, lport, backlog, &lport);
- if(listensock == INVALID_FD) {
- reply(ESOCK_LISTEN_SYNC_ERR, "4s", intref, psx_errstr());
- break;
- }
- cp = new_connection(ESOCK_PASSIVE_LISTENING, listensock);
- /* Flags may be an empty string */
- length = strlen(flags);
- cp->flags = esock_malloc(length + 1);
- strcpy(cp->flags, flags);
-
- cp->origin = ORIG_LISTEN;
- if (esock_ssl_listen_init(cp) < 0) {
- DEBUGF(("esock_ssl_listen_init() failed.\n"));
- reply(ESOCK_LISTEN_SYNC_ERR, "4s", intref,
- ssl_errstr());
- close_and_remove_connection(cp);
- break;
- }
- DEBUGF(("-> PASSIVE_LISTENING (fd = %d)\n", listensock));
- /* Publish listensock */
- reply(ESOCK_LISTEN_REP, "442", intref, listensock,
- ntohs(iserv_addr.sin_port));
- break;
-
- case ESOCK_TRANSPORT_ACCEPT_CMD:
- /*
- * ebuf = { op(1), fd(4), flags(N), 0(1)}
- */
- input("4s", &fd, &flags);
- DEBUGF(("[TRANSPORT_ACCEPT_CMD] listenfd = %d, flags = %s\n", fd,
- flags));
- cp = get_connection(fd);
- if (cp) {
- /* We store the flags in the listen socket's
- * connection, and overwrite previous flags.
- */
- if ((length = strlen(flags)) > 0) {
- if (cp->flags)
- cp->flags = esock_realloc(cp->flags,
- length + 1);
- else
- cp->flags = esock_malloc(length + 1);
- strcpy(cp->flags, flags);
- }
- if (cp->flags && cp->flags[0] != '\0') {
- cp->acceptors++;
- cp->state = ESOCK_ACTIVE_LISTENING;
- DEBUGF(("-> ACTIVE_LISTENING\n"));
- break;
- }
- DEBUGF(("ERROR: flags empty\n"));
- }
- reply(ESOCK_TRANSPORT_ACCEPT_ERR, "4s", fd, "ebadf");
- break;
-
- case ESOCK_SSL_ACCEPT_CMD:
- input("4s", &fd, &flags);
- DEBUGF(("[SSL_ACCEPT_CMD] fd = %d, flags = %s\n", fd, flags));
- cp = get_connection(fd);
- if (cp)
- cp->state = ESOCK_SSL_ACCEPT;
- //reply(ESOCK_SSL_ACCEPT_REP, "4", fd);
- break;
-
- case ESOCK_NOACCEPT_CMD:
- /*
- * ebuf = {cmd(1), fd(4)}
- */
- input("4", &fd);
- DEBUGF(("[NOACCEPT_CMD] listenfd = %d\n", fd));
- cp = get_connection(fd);
- if (cp && (--cp->acceptors <= 0)) {
- cp->acceptors = 0;
- cp->state = ESOCK_PASSIVE_LISTENING;
- esock_poll_clear_event(&pollfd, fd);
- DEBUGF(("-> PASSIVE_LISTENING\n"));
- }
- break;
-
- case ESOCK_PROXY_JOIN_CMD:
- /*
- * ebuf = {cmd(1), fd(4), portnum(2)}
- *
- * fd - file descriptor of a connection in state
- * CONNECTED
- * portnum - port number of the Erlang proxy peer
- */
- input("42", &fd, &pport);
- cp = get_connection(fd);
- pp = get_proxy_by_peerport(pport);
- if (cp && cp->state == ESOCK_CONNECTED && pp) {
- DEBUGF(("CONNECTED[PROXY_JOIN_CMD] fd = %d "
- "portnum = %d\n", fd, pport));
- cp->proxy = pp;
- pp->conn = cp;
- reply(ESOCK_PROXY_JOIN_REP, "4", fd);
- cp->state = ESOCK_JOINED;
- DEBUGF(("-> JOINED\n"));
- break;
- }
- if (!cp) {
- DEBUGF(("[PROXY_JOIN_CMD] ERROR: No connection "
- "having fd = %d\n", fd));
- reply(ESOCK_PROXY_JOIN_ERR, "4s", fd, "ebadsocket");
- } else if (cp->state != ESOCK_CONNECTED) {
- DEBUGF(("%s[PROXY_JOIN_CMD] ERROR: Bad state: "
- "fd = %d\n", connstr[cp->state], cp->fd));
- reply(ESOCK_PROXY_JOIN_ERR, "4s", fd, "ebadstate");
- } else {
- DEBUGF(("ERROR: No proxy: fd = %d, pport = %d\n",
- fd, pport));
- if (proxysock_err_cnt > 0) {
- proxysock_err_cnt--;
- reply(ESOCK_PROXY_JOIN_ERR, "4s", fd,
- esock_posix_str(proxysock_last_err));
- } else {
- reply(ESOCK_PROXY_JOIN_ERR, "4s", fd,
- "enoproxysocket");
- }
- cp->state = ESOCK_DEFUNCT;
- }
- break;
-
- case ESOCK_DUMP_STATE_CMD:
- dump_connections();
- break;
-
- case ESOCK_SET_DEBUG_CMD:
- /*
- * ebuf = {cmd(1), debug(1)}
- */
- input("1", &debug);
- break;
-
- case ESOCK_SET_DEBUGMSG_CMD:
- /*
- * ebuf = {cmd(1), debugmsg(1)}
- */
- input("1", &debugmsg);
- break;
-
- default:
- fprintf(stderr, "esock: default value in loop %c\n",
- *ebuf);
- exit(EXIT_FAILURE);
- break;
- }
- }
- }
-
- /* Go through all connections that have their file descriptors
- set. */
-
- /* Note: We may remove the current connection (cp). Thus we
- * must be careful not to read cp->next after cp has been
- * removed. */
- for (cp = next_polled_conn(connections, &cpnext, &pollfd, set_wq_fds);
- cp != NULL;
- cp = next_polled_conn(cpnext, &cpnext, &pollfd, set_wq_fds)
- ) {
-
- switch(cp->state) {
-
- case ESOCK_PASSIVE_LISTENING:
- DEBUGF(("-----------------------------------\n"));
- fprintf(stderr, "esock: Got connect request while PASSIVE\n");
- exit(EXIT_FAILURE);
- break;
-
- case ESOCK_ACTIVE_LISTENING:
- /* new connect from network */
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("ACTIVE_LISTENING - trying to accept on %d\n",
- cp->fd));
- length = sizeof(iserv_addr);
- msgsock = do_accept(cp->fd, (struct sockaddr*)&iserv_addr,
- (int*)&length);
- if(msgsock == INVALID_FD) {
- DEBUGF(("accept error: %s\n", psx_errstr()));
- reply(ESOCK_TRANSPORT_ACCEPT_ERR, "4s", cp->fd, psx_errstr());
- break;
- }
- SET_NONBLOCKING(msgsock);
- if (--cp->acceptors <= 0) {
- cp->acceptors = 0;
- cp->state = ESOCK_PASSIVE_LISTENING;
- DEBUGF(("-> PASSIVE_LISTENING\n"));
- }
- DEBUGF(("server accepted connection on fd %d\n", msgsock));
- newcp = new_connection(ESOCK_TRANSPORT_ACCEPT, msgsock);
- newcp->origin = ORIG_ACCEPT;
- reply(ESOCK_TRANSPORT_ACCEPT_REP, "44", cp->fd, msgsock);
- newcp->listen_fd = cp->fd; /* Needed for ESOCK_ACCEPT_ERR */
- length = strlen(cp->flags);
- /* XXX new flags are not needed */
- newcp->flags = esock_malloc(length + 1);
- strcpy(newcp->flags, cp->flags); /* XXX Why? */
- if (esock_ssl_accept_init(newcp, cp->opaque) < 0) {
- cp->errstr = ssl_errstr();
- break;
- }
- newcp->ssl_want = ESOCK_SSL_WANT_READ;
- break;
-
- case ESOCK_SSL_ACCEPT:
- /* SSL accept handshake. msgsock is *not* published yet. */
- msgsock = cp->fd;
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("SSL_ACCEPT fd = %d\n", msgsock));
- if (cp->errstr != NULL) { /* this means we got an error in ssl_accept_init */
- /* N.B.: The *listen fd* is reported. */
- reply(ESOCK_SSL_ACCEPT_ERR, "4s", msgsock, cp->errstr);
- close_and_remove_connection(cp);
- break;
- }
- if (esock_ssl_accept(cp) < 0) {
- if (sock_errno() != ERRNO_BLOCK) {
- /* Handshake failed. */
- reply(ESOCK_SSL_ACCEPT_ERR, "4s", msgsock,
- ssl_errstr());
- DEBUGF(("ERROR: handshake: %s\n", ssl_errstr()));
- close_and_remove_connection(cp);
- }
- } else {
- /* SSL handshake successful: publish */
- reply(ESOCK_SSL_ACCEPT_REP, "4", msgsock);
- DEBUGF(("-> CONNECTED\n"));
- DEBUGF((" Session was %sreused.\n",
- (esock_ssl_session_reused(cp)) ? "" : "NOT "));
- cp->state = ESOCK_CONNECTED;
- }
- break;
-
- case ESOCK_CONNECTED:
- /* Should not happen. We do not read or write until
- the connection is in state JOINED. */
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("CONNECTED: Error: should not happen. fd = %d\n",
- cp->fd));
- break;
-
- case ESOCK_JOINED:
- /*
- * Reading from Proxy, writing to SSL
- */
- if (esock_poll_fd_isset_write(&pollfd, cp->fd)) {
- /* If there is a write queue, write to ssl only */
- if (cp->wq.len > 0) {
- /* The write retry semantics of SSL_write in
- * the OpenSSL package is strange. Partial
- * writes never occur, only complete writes or
- * failures. A failure, however, still
- * consumes all data written, although not all
- * encrypted data could be written to the
- * underlying socket. To retry a write we have
- * to provide the same buf and length as in
- * the original call, in our case rwbuf and
- * the original buffer length. Hence the
- * strange memcpy(). Note that wq.offset will
- * always be zero when we use OpenSSL.
- */
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("JOINED: writing to ssl "
- "fd = %d, from write queue only, wc = %d\n",
- cp->fd, cp->wq.len - cp->wq.offset));
- memcpy(rwbuf, cp->wq.buf, cp->wq.len - cp->wq.offset);
-
- /* esock_ssl_write sets cp->eof, cp->bp when return
- * value is zero */
- wc = esock_ssl_write(cp, rwbuf,
- cp->wq.len - cp->wq.offset);
- if (wc < 0) {
- if (sock_errno() != ERRNO_BLOCK) {
- /* Assume broken SSL pipe */
- DEBUGF(("broken SSL pipe\n"));
- cp->bp = 1;
- shutdown(cp->proxy->fd, SHUTDOWN_READ);
- cp->proxy->eof = 1;
- if (JOINED_STATE_INVALID(cp)) {
- leave_joined_state(cp);
- break;
- }
- }
- } else if (wc == 0) {
- /* SSL broken pipe */
- DEBUGF(("broken SSL pipe\n"));
- cp->bp = 1;
- shutdown(cp->proxy->fd, SHUTDOWN_READ);
- cp->proxy->eof = 1;
- if (JOINED_STATE_INVALID(cp)) {
- leave_joined_state(cp);
- break;
- }
- } else {
- cp->wq.offset += wc;
- if (cp->wq.offset == cp->wq.len)
- cp->wq.len = 0;
- }
- }
- } else if (esock_poll_fd_isset_read(&pollfd, cp->proxy->fd)) {
- /* Read from proxy and write to SSL */
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("JOINED: reading from proxy, "
- "proxyfd = %d\n", cp->proxy->fd));
- cc = sock_read(cp->proxy->fd, rwbuf, RWBUFLEN);
- DEBUGF(("read from proxyfd = %d, cc = %d\n",
- cp->proxy->fd, cc));
- if (cc > 0) {
- /* esock_ssl_write sets cp->eof, cp->bp when return
- * value is zero */
- wc = esock_ssl_write(cp, rwbuf, cc);
- if (wc < 0) {
- if (sock_errno() != ERRNO_BLOCK) {
- /* Assume broken pipe */
- DEBUGF(("broken SSL pipe\n"));
- cp->bp = 1;
- shutdown(cp->proxy->fd, SHUTDOWN_READ);
- cp->proxy->eof = 1;
- if (JOINED_STATE_INVALID(cp)) {
- leave_joined_state(cp);
- break;
- }
- } else {
- /* add to write queue */
- DEBUGF(("adding all to write queue "
- "%d bytes\n", cc));
- ensure_write_queue(&cp->wq, cc);
- memcpy(cp->wq.buf, rwbuf, cc);
- cp->wq.len = cc;
- cp->wq.offset = 0;
- }
- } else if (wc == 0) {
- /* Broken SSL pipe */
- DEBUGF(("broken SSL pipe\n"));
- cp->bp = 1;
- shutdown(cp->proxy->fd, SHUTDOWN_READ);
- cp->proxy->eof = 1;
- if (JOINED_STATE_INVALID(cp)) {
- leave_joined_state(cp);
- break;
- }
- } else if (wc < cc) {
- /* add remainder to write queue */
- DEBUGF(("adding remainder to write queue "
- "%d bytes\n", cc - wc));
- ensure_write_queue(&cp->wq, cc - wc);
- memcpy(cp->wq.buf, rwbuf + wc, cc - wc);
- cp->wq.len = cc - wc;
- cp->wq.offset = 0;
- }
- } else {
- /* EOF proxy or error */
- DEBUGF(("proxy eof or error %d\n", errno));
- cp->proxy->eof = 1;
- if (cp->wq.len == 0) {
- esock_ssl_shutdown(cp);
- cp->bp = 1;
- }
- if (JOINED_STATE_INVALID(cp)) {
- leave_joined_state(cp);
- break;
- }
- }
- }
- /*
- * Reading from SSL, writing to proxy
- */
- if (esock_poll_fd_isset_write(&pollfd, cp->proxy->fd)) {
- /* If there is a write queue, write to proxy only */
- if (cp->proxy->wq.len > 0) {
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("JOINED: writing to proxyfd = %d, "
- "from write queue only, wc = %d\n",
- cp->proxy->fd, cp->proxy->wq.len -
- cp->proxy->wq.offset));
- wc = sock_write(cp->proxy->fd, cp->proxy->wq.buf +
- cp->proxy->wq.offset,
- cp->proxy->wq.len -
- cp->proxy->wq.offset);
- if (wc < 0) {
- if (sock_errno() != ERRNO_BLOCK) {
- /* Assume broken pipe */
- DEBUGF(("broken proxy pipe\n"));
- cp->proxy->bp = 1;
- /* There is no SSL shutdown for read */
- cp->eof = 1;
- if (JOINED_STATE_INVALID(cp)) {
- leave_joined_state(cp);
- break;
- }
- }
- } else {
- cp->proxy->wq.offset += wc;
- if (cp->proxy->wq.offset == cp->proxy->wq.len)
- cp->proxy->wq.len = 0;
- }
- }
- } else if (esock_poll_fd_isset_read(&pollfd, cp->fd)) {
- /* Read from SSL and write to proxy */
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("JOINED: read from ssl fd = %d\n",
- cp->fd));
- cc = esock_ssl_read(cp, rwbuf, RWBUFLEN);
- DEBUGF(("read from fd = %d, cc = %d\n", cp->fd, cc));
- if (cc > 0) {
- wc = sock_write(cp->proxy->fd, rwbuf, cc);
- if (wc < 0) {
- if (sock_errno() != ERRNO_BLOCK) {
- DEBUGF(("broken proxy pipe\n"));
- /* Assume broken pipe */
- cp->proxy->bp = 1;
- /* There is no SSL shutdown for read */
- cp->eof = 1;
- if (JOINED_STATE_INVALID(cp)) {
- leave_joined_state(cp);
- break;
- }
- } else {
- /* add all to write queue */
- DEBUGF(("adding to write queue %d bytes\n",
- cc));
- ensure_write_queue(&cp->proxy->wq, cc);
- memcpy(cp->proxy->wq.buf, rwbuf, cc);
- cp->proxy->wq.len = cc;
- cp->proxy->wq.offset = 0;
- }
- } else if (wc < cc) {
- /* add to write queue */
- DEBUGF(("adding to write queue %d bytes\n",
- cc - wc));
- ensure_write_queue(&cp->proxy->wq, cc - wc);
- memcpy(cp->proxy->wq.buf, rwbuf + wc, cc - wc);
- cp->proxy->wq.len = cc - wc;
- cp->proxy->wq.offset = 0;
- }
- } else if (cc == 0) {
- /* SSL eof */
- DEBUGF(("SSL eof\n"));
- cp->eof = 1;
- if (cp->proxy->wq.len == 0) {
- shutdown(cp->proxy->fd, SHUTDOWN_WRITE);
- cp->proxy->bp = 1;
- }
- if (JOINED_STATE_INVALID(cp)) {
- leave_joined_state(cp);
- break;
- }
- } else {
- /* This may very well happen when reading from SSL. */
- DEBUGF(("NOTE: readmask set, cc < 0, fd = %d, "
- "is ok\n", cp->fd));
- }
- }
- break;
-
- case ESOCK_SSL_SHUTDOWN:
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("SSL_SHUTDOWN: fd = %d\n", cp->fd));
- do_shutdown(cp);
- break;
-
- case ESOCK_DEFUNCT:
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("DEFUNCT: ERROR: should not happen. fd = %d\n",
- cp->fd));
- break;
-
- case ESOCK_WAIT_CONNECT:
- /* New connection shows up */
- connectsock = cp->fd;/* Is published */
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("WAIT_CONNECT fd = %d\n", connectsock));
-
- /* If the connection did succeed it's possible to
- * fetch the peer name (UNIX); or failure shows in
- * exceptmask (WIN32). Sorry for the mess below, but
- * we have to have balanced paren's in #ifdefs in
- * order not to confuse Emacs' indentation. */
- length = sizeof(iserv_addr);
- if (
-#ifdef __WIN32__
- esock_poll_fd_isset_exception(&pollfd, connectsock)
-#else
- getpeername(connectsock, (struct sockaddr *)&iserv_addr,
- &length) < 0
-#endif
- ) {
- sock_set_errno(ERRNO_CONNREFUSED);
- DEBUGF(("connect error: %s\n", psx_errstr()));
- reply(ESOCK_CONNECT_ERR, "4s", connectsock, psx_errstr());
- cp->state = ESOCK_DEFUNCT;
- break;
- }
- if (esock_ssl_connect_init(cp) < 0) {
- DEBUGF(("esock_ssl_connect_init() failed\n"));
- reply(ESOCK_CONNECT_ERR, "4s", connectsock, ssl_errstr());
- cp->state = ESOCK_DEFUNCT;
- break;
- }
- DEBUGF(("-> SSL_CONNECT\n"));
- cp->state = ESOCK_SSL_CONNECT;
- cp->ssl_want = ESOCK_SSL_WANT_WRITE;
- break;
-
- case ESOCK_SSL_CONNECT:
- /* SSL connect handshake. connectsock is published. */
- connectsock = cp->fd;
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("SSL_CONNECT fd = %d\n", connectsock));
- if (esock_ssl_connect(cp) < 0) {
- if (sock_errno() != ERRNO_BLOCK) {
- /* Handshake failed */
- DEBUGF(("ERROR: handshake: %s\n", ssl_errstr()));
- reply(ESOCK_CONNECT_ERR, "4s", connectsock,
- ssl_errstr());
- cp->state = ESOCK_DEFUNCT;
- }
- } else {
- /* SSL connect handshake successful */
- DEBUGF(("-> CONNECTED\n"));
- reply(ESOCK_CONNECT_REP, "4", connectsock);
- cp->state = ESOCK_CONNECTED;
- }
- break;
-
- default:
- DEBUGF(("ERROR: Connection in unknown state.\n"));
- }
- }
- }
-}
-
-static int set_poll_conns(Connection *cp, EsockPoll *ep, int verbose)
-{
- int i = 0;
-
- if (verbose)
- DEBUGF(("MASKS SET FOR FD: "));
- while (cp) {
- switch (cp->state) {
- case ESOCK_ACTIVE_LISTENING:
- if (verbose)
- DEBUGF(("%d (read) ", cp->fd));
- esock_poll_fd_set_read(ep, cp->fd);
- break;
- case ESOCK_WAIT_CONNECT:
- if (verbose)
- DEBUGF(("%d (write) ", cp->fd));
- esock_poll_fd_set_write(ep, cp->fd);
-#ifdef __WIN32__
- esock_poll_fd_set_exception(ep, cp->fd); /* Failure shows in exceptions */
-#endif
- break;
- case ESOCK_SSL_CONNECT:
- case ESOCK_SSL_ACCEPT:
- if (cp->ssl_want == ESOCK_SSL_WANT_READ) {
- if (verbose)
- DEBUGF(("%d (read) ", cp->fd));
- esock_poll_fd_set_read(ep, cp->fd);
- } else if (cp->ssl_want == ESOCK_SSL_WANT_WRITE) {
- if (verbose)
- DEBUGF(("%d (write) ", cp->fd));
- esock_poll_fd_set_write(ep, cp->fd);
- }
- break;
- case ESOCK_JOINED:
- if (!cp->bp) {
- if (cp->wq.len) {
- if (verbose)
- DEBUGF(("%d (write) ", cp->fd));
- esock_poll_fd_set_write(ep, cp->fd);
- } else if (!cp->proxy->eof) {
- if (verbose)
- DEBUGF(("%d (read) ", cp->proxy->fd));
- esock_poll_fd_set_read(ep, cp->proxy->fd);
- }
- }
- if (!cp->proxy->bp) {
- if (cp->proxy->wq.len) {
- if (verbose)
- DEBUGF(("%d (write) ", cp->proxy->fd));
- esock_poll_fd_set_write(ep, cp->proxy->fd);
- } else if (!cp->eof) {
- if (verbose)
- DEBUGF(("%d (read) ", cp->fd));
- esock_poll_fd_set_read(ep, cp->fd);
- }
- }
- break;
- case ESOCK_SSL_SHUTDOWN:
- if (cp->ssl_want == ESOCK_SSL_WANT_READ) {
- if (verbose)
- DEBUGF(("%d (read) ", cp->fd));
- esock_poll_fd_set_read(ep, cp->fd);
- } else if (cp->ssl_want == ESOCK_SSL_WANT_WRITE) {
- if (verbose)
- DEBUGF(("%d (write) ", cp->fd));
- esock_poll_fd_set_write(ep, cp->fd);
- }
- break;
- default:
- break;
- }
- i++;
- cp = cp->next;
- }
- if (verbose)
- DEBUGF(("\n"));
- return i;
-}
-
-
-static Connection *next_polled_conn(Connection *cp, Connection **cpnext,
- EsockPoll *ep, int set_wq_fds)
-{
- while(cp) {
- if (esock_poll_fd_isset_read(ep, cp->fd) ||
- (cp->proxy && esock_poll_fd_isset_read(ep, cp->proxy->fd)) ||
- (esock_poll_fd_isset_write(ep, cp->fd)) ||
- (cp->proxy && esock_poll_fd_isset_write(ep, cp->proxy->fd))
-#ifdef __WIN32__
- || esock_poll_fd_isset_exception(ep, cp->fd) /* Connect failure in WIN32 */
-#endif
- || (set_wq_fds && (cp->wq.len ||
- (cp->proxy && cp->proxy->wq.len)))
- || cp->errstr != NULL) {
- *cpnext = cp->next;
- return cp;
- }
- cp = cp->next;
- }
- *cpnext = NULL;
- return NULL;
-}
-
-static void leave_joined_state(Connection *cp)
-{
- shutdown(cp->proxy->fd, SHUTDOWN_ALL);
- if (((cp->bp || cp->eof) && cp->clean) ||
- (!cp->bp && !cp->eof)) {
- DEBUGF(("-> SSL_SHUTDOWN\n"));
- cp->state = ESOCK_SSL_SHUTDOWN;
- cp->ssl_want = ESOCK_SSL_WANT_WRITE;
- do_shutdown(cp);
- } else if (cp->close) {
- DEBUGF(("-> (removal)\n"));
- close_and_remove_connection(cp);
- } else {
- DEBUGF(("-> DEFUNCT\n"));
- cp->state = ESOCK_DEFUNCT;
- }
-}
-
-/* We are always in state SHUTDOWN here */
-static void do_shutdown(Connection *cp)
-{
- int ret;
-
- ret = esock_ssl_shutdown(cp);
- if (ret < 0) {
- if (sock_errno() == ERRNO_BLOCK) {
- return;
- } else {
- /* Something is wrong -- close and remove or move to DEFUNCT */
- DEBUGF(("Error in SSL shutdown\n"));
- if (cp->close) {
- DEBUGF(("-> (removal)\n"));
- close_and_remove_connection(cp);
- } else {
- DEBUGF(("-> DEFUNCT\n"));
- cp->state = ESOCK_DEFUNCT;
- }
- }
- } else if (ret == 0) {
- /* `close_notify' has been sent. Wait for reception of
- same. */
- return;
- } else if (ret == 1) {
- /* `close_notify' has been sent, and received. */
- if (cp->close) {
- DEBUGF(("-> (removal)\n"));
- close_and_remove_connection(cp);
- } else {
- DEBUGF(("-> DEFUNCT\n"));
- cp->state = ESOCK_DEFUNCT;
- }
- }
-}
-
-static void close_and_remove_connection(Connection *cp)
-{
- safe_close(cp->fd);
- remove_connection(cp);
-}
-
-static int reply(int cmd, char *fmt, ...)
-{
- static unsigned char replybuf[MAXREPLYBUF];
- unsigned char *buf = replybuf;
- va_list args;
- int len;
-
- va_start(args, fmt);
- len = put_pars(NULL, fmt, args);
- va_end(args);
- len++;
- if (len > sizeof(replybuf))
- buf = esock_malloc(len);
-
- PUT_INT8(cmd, buf);
- va_start(args, fmt);
- (void) put_pars(buf + 1, fmt, args);
- va_end(args);
- write_ctrl(buf, len);
- if (buf != replybuf)
- esock_free(buf);
- return len;
-}
-
-static int input(char *fmt, ...)
-{
- va_list args;
- int len;
-
- va_start(args, fmt);
- len = get_pars(ebuf + 1, fmt, args);
- va_end(args);
- return len + 1;
-}
-
-static int put_pars(unsigned char *buf, char *fmt, va_list args)
-{
- char *s, *str, *bin;
- int val, len, pos = 0;
-
- s = fmt;
- while (*s) {
- switch (*s) {
- case '1':
- val = va_arg(args, int);
- if (buf)
- PUT_INT8(val, buf + pos);
- pos++;
- break;
- case '2':
- val = va_arg(args, int);
- if (buf)
- PUT_INT16(val, buf + pos);
- pos += 2;
- break;
- case '4':
- val = va_arg(args, int);
- if (buf)
- PUT_INT32(val, buf + pos);
- pos += 4;
- break;
- case 's': /* string */
- str = va_arg(args, char *);
- if (buf)
- strcpy((char *)(buf + pos), str);
- pos += strlen(str) + 1;
- break;
- case 'b': /* binary */
- len = va_arg(args, int);
- if (buf)
- PUT_INT32(len, buf + pos);
- pos += 4;
- bin = va_arg(args, char *);
- if (buf)
- memcpy(buf + pos, bin, len);
- pos += len;
- break;
- default:
- fprintf(stderr, "esock: Invalid format character: %c\n", *s);
- exit(EXIT_FAILURE);
- break;
- }
- s++;
- }
- return pos;
-}
-
-
-static int get_pars(unsigned char *buf, char *fmt, va_list args)
-{
- int *ip;
- char *s, **strp, **bin;
- int pos = 0;
-
- s = fmt;
- while (*s) {
- switch (*s) {
- case '1':
- ip = va_arg(args, int *);
- *ip = GET_INT8(buf + pos);
- pos++;
- break;
- case '2':
- ip = va_arg(args, int *);
- *ip = GET_INT16(buf + pos);
- pos += 2;
- break;
- case '4':
- ip = va_arg(args, int *);
- *ip = GET_INT32(buf + pos);
- pos += 4;
- break;
- case 's':
- strp = va_arg(args, char **);
- *strp = (char *)(buf + pos);
- pos += strlen(*strp) + 1;
- break;
- case 'b':
- ip = va_arg(args, int *);
- *ip = GET_INT32(buf + pos);
- pos += 4;
- bin = va_arg(args, char **);
- *bin = (char *)(buf + pos);
- pos += *ip;
- break;
- default:
- fprintf(stderr, "esock: Invalid format character: %c\n", *s);
- exit(EXIT_FAILURE);
- break;
- }
- s++;
- }
- return pos;
-}
-
-static FD do_connect(char *lipstring, int lport, char *fipstring, int fport)
-{
- struct sockaddr_in sock_addr;
- long inaddr;
- FD fd;
-
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_FD) {
- DEBUGF(("Error calling socket()\n"));
- return fd;
- }
- if (check_num_sock_fds(fd) < 0)
- return INVALID_FD;
- DEBUGF((" fd = %d\n", fd));
-
- /* local */
- if ((inaddr = inet_addr(lipstring)) == INADDR_NONE) {
- DEBUGF(("Error in inet_addr(): lipstring = %s\n", lipstring));
- safe_close(fd);
- sock_set_errno(ERRNO_ADDRNOTAVAIL);
- return INVALID_FD;
- }
- memset(&sock_addr, 0, sizeof(sock_addr));
- sock_addr.sin_family = AF_INET;
- sock_addr.sin_addr.s_addr = inaddr;
- sock_addr.sin_port = htons(lport);
- if(bind(fd, (struct sockaddr*) &sock_addr, sizeof(sock_addr)) < 0) {
- DEBUGF(("Error in bind()\n"));
- safe_close(fd);
- /* XXX Set error code for bind error */
- return INVALID_FD;
- }
-
- /* foreign */
- if ((inaddr = inet_addr(fipstring)) == INADDR_NONE) {
- DEBUGF(("Error in inet_addr(): fipstring = %s\n", fipstring));
- safe_close(fd);
- sock_set_errno(ERRNO_ADDRNOTAVAIL);
- return INVALID_FD;
- }
- memset(&sock_addr, 0, sizeof(sock_addr));
- sock_addr.sin_family = AF_INET;
- sock_addr.sin_addr.s_addr = inaddr;
- sock_addr.sin_port = htons(fport);
-
- SET_NONBLOCKING(fd);
-
- if(connect(fd, (struct sockaddr*)&sock_addr, sizeof(sock_addr)) < 0) {
- if (sock_errno() != ERRNO_PROGRESS && /* UNIX */
- sock_errno() != ERRNO_BLOCK) { /* WIN32 */
- DEBUGF(("Error in connect()\n"));
- safe_close(fd);
- return INVALID_FD;
- }
- }
- return fd;
-}
-
-static FD do_listen(char *ipstring, int lport, int backlog, int *aport)
-{
- static int one = 1; /* Type must be int, not long */
- struct sockaddr_in sock_addr;
- long inaddr;
- int length;
- FD fd;
-
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_FD) {
- DEBUGF(("Error calling socket()\n"));
- return fd;
- }
- if (check_num_sock_fds(fd) < 0)
- return INVALID_FD;
- DEBUGF((" fd = %d\n", fd));
- if ((inaddr = inet_addr(ipstring)) == INADDR_NONE) {
- DEBUGF(("Error in inet_addr(): ipstring = %s\n", ipstring));
- safe_close(fd);
- sock_set_errno(ERRNO_ADDRNOTAVAIL);
- return INVALID_FD;
- }
- memset(&sock_addr, 0, sizeof(sock_addr));
- sock_addr.sin_family = AF_INET;
- sock_addr.sin_addr.s_addr = inaddr;
- sock_addr.sin_port = htons(lport);
-
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one));
-
- if(bind(fd, (struct sockaddr*) &sock_addr, sizeof(sock_addr)) < 0) {
- DEBUGF(("Error in bind()\n"));
- safe_close(fd);
- return INVALID_FD;
- }
- if (listen(fd, backlog) < 0) {
- DEBUGF(("Error in listen()\n"));
- safe_close(fd);
- return INVALID_FD;
- }
- /* find out assigned local port number */
- length = sizeof(sock_addr);
- if (getsockname(fd, (struct sockaddr *)&sock_addr, &length) < 0) {
- DEBUGF(("Error in getsockname()\n"));
- safe_close(fd);
- return INVALID_FD;
- }
- if (aport)
- *aport = ntohs(sock_addr.sin_port);
- return fd;
-}
-
-static FD do_accept(FD listensock, struct sockaddr *saddr, int *len)
-{
- FD fd;
-
- if ((fd = accept(listensock, saddr, len)) == INVALID_FD) {
- DEBUGF(("Error calling accept()\n"));
- return fd;
- }
- if (check_num_sock_fds(fd) < 0)
- return INVALID_FD;
- return fd;
-}
-
-static Connection *new_connection(int state, FD fd)
-{
- Connection *cp;
-
- if (!(cp = esock_malloc(sizeof(Connection))))
- return NULL;
- cp->state = state;
- cp->acceptors = 0;
- cp->fd = fd;
- cp->listen_fd = INVALID_FD;
- cp->proxy = NULL;
- cp->opaque = NULL;
- cp->ssl_want = 0;
- cp->eof = 0;
- cp->bp = 0;
- cp->clean = 0; /* XXX Used? */
- cp->close = 0;
- cp->origin = -1;
- cp->flags = NULL;
- cp->logfp = NULL;
- cp->wq.size = 0;
- cp->wq.buf = NULL;
- cp->wq.len = 0;
- cp->wq.offset = 0;
- cp->next = connections;
- cp->errstr = NULL;
- connections = cp;
- return cp;
-}
-
-
-static void print_connections(void)
-{
- if (debug) {
- Connection *cp = connections;
- DEBUGF(("CONNECTIONS:\n"));
- while (cp) {
- if (cp->state == ESOCK_JOINED) {
- DEBUGF((" - %s [%8p] (origin = %s)\n"
- " (fd = %d, eof = %d, wq = %d, bp = %d)\n"
- " (proxyfd = %d, eof = %d, wq = %d, bp = %d)\n",
- connstr[cp->state], cp, originstr[cp->origin],
- cp->fd, cp->eof, cp->wq.len, cp->bp,
- cp->proxy->fd, cp->proxy->eof, cp->proxy->wq.len,
- cp->proxy->bp));
- } else if (cp->state == ESOCK_ACTIVE_LISTENING) {
- DEBUGF((" - %s [%8p] (fd = %d, acceptors = %d)\n",
- connstr[cp->state], cp, cp->fd, cp->acceptors));
- } else {
- DEBUGF((" - %s [%8p] (fd = %d)\n", connstr[cp->state], cp,
- cp->fd));
- }
- cp= cp->next;
- }
- }
-}
-
-static void dump_connections(void)
-{
- Connection *cp = connections;
- Proxy *pp = proxies;
- time_t t = time(NULL);
- int length = 0;
- struct sockaddr_in iserv_addr;
-
- __debugprintf("CONNECTIONS %s", ctime(&t));
- while (cp) {
- if (cp->state == ESOCK_JOINED) {
- __debugprintf(" - %s [%8p] (origin = %s)\n"
- " (fd = %d, eof = %d, wq = %d, bp = %d), close = %d\n"
- " (proxyfd = %d, eof = %d, wq = %d, bp = %d)\n",
- connstr[cp->state], cp, originstr[cp->origin],
- cp->fd, cp->eof, cp->wq.len, cp->bp, cp->close,
- cp->proxy->fd, cp->proxy->eof, cp->proxy->wq.len,
- cp->proxy->bp);
- } else if (cp->state == ESOCK_ACTIVE_LISTENING) {
- __debugprintf(" - %s [%8p] (fd = %d, acceptors = %d)\n",
- connstr[cp->state], cp, cp->fd, cp->acceptors);
- } else {
- __debugprintf(" - %s [%8p] (fd = %d)\n", connstr[cp->state], cp,
- cp->fd);
- }
- length = sizeof(iserv_addr);
- if ((cp->state == ESOCK_ACTIVE_LISTENING) ||
- (cp->state == ESOCK_PASSIVE_LISTENING)) {
- getsockname(cp->fd, (struct sockaddr *) &iserv_addr, &length);
- __debugprintf(" (ip = %s, port = %d)\n",
- inet_ntoa(iserv_addr.sin_addr),
- ntohs(iserv_addr.sin_port));
- }
- else {
- getsockname(cp->fd, (struct sockaddr *) &iserv_addr, &length);
- __debugprintf(" (local_ip = %s, local_port = %d)\n",
- inet_ntoa(iserv_addr.sin_addr),
- ntohs(iserv_addr.sin_port));
- length = sizeof(iserv_addr);
- getpeername(cp->fd, (struct sockaddr *) &iserv_addr, &length);
- __debugprintf(" (remote_ip = %s, remote_port = %d)\n",
- inet_ntoa(iserv_addr.sin_addr),
- ntohs(iserv_addr.sin_port));
- }
- cp=cp->next;
- }
-
- __debugprintf("PROXIES\n");
- while (pp) {
- __debugprintf(" - fd = %d [%8p] (external_fd = %d, peer_port = %d,"
- " eof = %d)\n", pp->fd, pp, pp->conn->fd, pp->peer_port,
- pp->eof);
-
- pp= pp->next;
- }
-}
-
-static Connection *get_connection(FD fd)
-{
- Connection *cp = connections;
-
- while(cp) {
- if(cp->fd == fd)
- return cp;
- cp = cp->next;
- }
- return NULL;
-}
-
-/*
- * Remove a connection from the list of connection, close the proxy
- * socket and free all resources. The main socket (fd) is *not*
- * closed here, because the closing of that socket has to be synchronized
- * with the Erlang process controlling this port program.
- */
-static void remove_connection(Connection *conn)
-{
- Connection **prev = &connections;
- Connection *cp = connections;
-
- while (cp) {
- if(cp == conn) {
- DEBUGF(("remove_connection: fd = %d\n", cp->fd));
- esock_ssl_free(cp); /* frees cp->opaque only */
- esock_free(cp->flags);
- closelog(cp->logfp); /* XXX num_sock_fds */
- esock_free(cp->wq.buf);
- if (cp->proxy) {
- safe_close(cp->proxy->fd);
- remove_proxy(cp->proxy);
- }
- *prev = cp->next;
- esock_free(cp);
- return;
- }
- prev = &cp->next;
- cp = cp->next;
- }
-}
-
-static Proxy *get_proxy_by_peerport(int port)
-{
- Proxy *p = proxies;
-
- while(p) {
- if (p->peer_port == port)
- return p;
- p = p->next;
- }
- return NULL;
-}
-
-static Proxy *new_proxy(FD fd)
-{
- Proxy *p;
-
- if (!(p = esock_malloc(sizeof(Proxy))))
- return NULL;
-
- p->fd = fd;
- p->peer_port = -1;
- p->eof = 0;
- p->bp = 0;
- p->conn = NULL;
- p->wq.size = 0;
- p->wq.buf = NULL;
- p->wq.len = 0;
- p->wq.offset = 0;
- p->next = proxies;
- proxies = p;
- return p;
-}
-
-static void remove_proxy(Proxy *proxy)
-{
- Proxy *p = proxies, **pp = &proxies;
-
- while(p) {
- if (p == proxy) {
- DEBUGF(("remove_proxyfd = %d\n", p->fd));
- esock_free(p->wq.buf);
- *pp = p->next;
- esock_free(p);
- return;
- }
- pp = &p->next;
- p = p->next;
- }
-}
-
-static int check_num_sock_fds(FD fd)
-{
- num_sock_fds++; /* fd is valid */
-#ifdef USE_SELECT
- if (num_sock_fds > FD_SETSIZE) {
- num_sock_fds--;
- sock_set_errno(ERRNO_MFILE);
- safe_close(fd);
- return -1;
- }
-#endif
- return 0;
-}
-
-static void safe_close(FD fd)
-{
- int err;
-
- err = sock_errno();
- DEBUGF(("safe_close fd = %d\n", fd));
- if (sock_close(fd) < 0) {
- DEBUGF(("safe_close failed\n"));
- } else {
- num_sock_fds--;
- }
- sock_set_errno(err);
-}
-
-static void clean_up(void)
-{
- Connection *cp, *cpnext;
- Proxy *pp, *ppnext;
-
- cp = connections;
- while (cp) {
- safe_close(cp->fd);
- cpnext = cp->next;
- remove_connection(cp);
- cp = cpnext;
- }
-
- pp = proxies;
- while (pp) {
- safe_close(pp->fd);
- ppnext = pp->next;
- remove_proxy(pp);
- pp = ppnext;
- }
-}
-
-static void ensure_write_queue(WriteQueue *wq, int size)
-{
- if (wq->size < size) {
- wq->buf = esock_realloc(wq->buf, size);
- wq->size = size;
- }
-}
-
-
-
-
-
-
-
diff --git a/lib/ssl/c_src/esock.h b/lib/ssl/c_src/esock.h
deleted file mode 100644
index 16c9faa530..0000000000
--- a/lib/ssl/c_src/esock.h
+++ /dev/null
@@ -1,273 +0,0 @@
-/*<copyright>
- * <year>1999-2008</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>
- */
-/*
- * Purpose: Implementation of Secure Socket Layer (SSL).
- *
- */
-
-#ifndef ESOCK_H
-#define ESOCK_H
-
-#ifdef __WIN32__
-#include "esock_winsock.h"
-#endif
-#include <stdio.h>
-
-#ifdef __WIN32__
-#define INVALID_FD INVALID_SOCKET
-
-#define sock_read(fd, buf, len) recv((fd), (buf), (len), 0)
-#define sock_write(fd, buf, len) send((fd), (buf), (len), 0)
-#define sock_close(fd) closesocket(fd)
-#define sock_errno() WSAGetLastError()
-#define sock_set_errno(err) WSASetLastError(err)
-
-#define ERRNO_NONE 0
-#define ERRNO_BLOCK WSAEWOULDBLOCK
-#define ERRNO_CONNREFUSED WSAECONNREFUSED
-#define ERRNO_PROGRESS WSAEINPROGRESS
-#define ERRNO_PROTONOSUPPORT WSAEPROTONOSUPPORT
-#define ERRNO_INVAL WSAEINVAL
-#define ERRNO_ADDRNOTAVAIL WSAEADDRNOTAVAIL
-#define ERRNO_NOTSOCK WSAENOTSOCK
-#define ERRNO_OPNOTSUPP WSAEOPNOTSUPP
-#define ERRNO_MFILE WSAEMFILE
-#define SET_BLOCKING(fd) do { \
- unsigned long zeroval = 0; \
- ioctlsocket((fd), FIONBIO, &zeroval); \
- } while (0)
-#define SET_NONBLOCKING(fd) do { \
- unsigned long oneval = 1; \
- ioctlsocket((fd), FIONBIO, &oneval); \
- } while (0)
-#else
-#define INVALID_FD (-1)
-
-#define sock_read(fd, buf, len) read((fd), (buf), (len))
-#define sock_write(fd, buf, len) write((fd), (buf), (len))
-#define sock_close(fd) close(fd)
-#define sock_errno() errno
-#define sock_set_errno(err) do {errno = (err);} while(0)
-
-#define ERRNO_NONE 0
-#define ERRNO_BLOCK EAGAIN
-#define ERRNO_CONNREFUSED ECONNREFUSED
-#define ERRNO_PROGRESS EINPROGRESS
-#define ERRNO_PROTONOSUPPORT EPROTONOSUPPORT
-#define ERRNO_INVAL EINVAL
-#define ERRNO_ADDRNOTAVAIL EADDRNOTAVAIL
-#define ERRNO_NOTSOCK ENOTSOCK
-#define ERRNO_OPNOTSUPP EOPNOTSUPP
-#define ERRNO_MFILE EMFILE
-#define SET_BLOCKING(fd) fcntl((fd), F_SETFL, \
- fcntl((fd), F_GETFL, 0) & ~O_NONBLOCK)
-#define SET_NONBLOCKING(fd) fcntl((fd), F_SETFL, \
- fcntl((fd), F_GETFL, 0) | O_NONBLOCK)
-#endif
-
-#define GET_INT8(s) ((s)[0])
-#define GET_INT16(s) (((s)[0] << 8) | (s)[1])
-#define GET_INT32(s) (((s)[0] << 24) | ((s)[1] << 16) | \
- ((s)[2] << 8) | (s)[3])
-
-#define PUT_INT8(x, s) do { (s)[0] = x; } while(0)
-#define PUT_INT16(x, s) do { (s)[0] = ((x) >> 8) & 0xff; \
- (s)[1] = ((x) & 0xff); } while(0)
-#define PUT_INT32(x, s) do { (s)[0] = ((x) >> 24) & 0xff; \
- (s)[1] = ((x) >> 16) & 0xff; \
- (s)[2] = ((x) >> 8) & 0xff; \
- (s)[3] = (x) & 0xff; } while(0)
-
-/* type for Connections */
-#define ESOCK_STATE_NONE 0
-#define ESOCK_ACTIVE_LISTENING 1
-#define ESOCK_PASSIVE_LISTENING 2
-#define ESOCK_CONNECTED 3
-#define ESOCK_WAIT_CONNECT 4
-#define ESOCK_SSL_CONNECT 5
-#define ESOCK_SSL_ACCEPT 6
-#define ESOCK_TRANSPORT_ACCEPT 7
-#define ESOCK_JOINED 8
-#define ESOCK_SSL_SHUTDOWN 9
-#define ESOCK_DEFUNCT 10
-
-#ifdef __WIN32__
- typedef SOCKET FD;
-#else
- typedef int FD;
-#endif
-
-/* For the shutdown(fd, how) call */
-#ifdef __WIN32__
-#define SHUTDOWN_READ SD_RECEIVE
-#define SHUTDOWN_WRITE SD_SEND
-#define SHUTDOWN_ALL SD_BOTH
-#else
-#define SHUTDOWN_READ 0
-#define SHUTDOWN_WRITE 1
-#define SHUTDOWN_ALL 2
-#endif
-
-#define ORIG_LISTEN 0
-#define ORIG_ACCEPT 1
-#define ORIG_CONNECT 2
-
-typedef struct {
- int size; /* Total size of buf */
- unsigned char *buf;
- int len; /* Current number of bytes in buf */
- int offset; /* Bytes already written */
-} WriteQueue;
-
-typedef struct _proxy Proxy;
-
-typedef struct Connection {
- FD fd;
- FD listen_fd; /* Needed for async listen error */
- unsigned char state;
- int acceptors; /* Count acceptors for listen socket */
- Proxy *proxy;
- void *opaque; /* Any suitable ssl structure */
- int ssl_want; /* read/write flags */
- int eof; /* end of file (read) */
- int bp; /* broken pipe (write) */
- int clean; /* Clean SSL shutdown initiated */
- int close; /* Close if set */
- int origin; /* listen, accept or connect */
- int encrypted; /* 1 = SSL encrypted, 0 = normal, unencrypted tcp */
- char *flags; /* ssl parameters */
- FILE *logfp; /* connection log file (not used) */
- WriteQueue wq;
- struct Connection* next;
- const char* errstr; /* only used to report errors from ssl_accept_init in SSL_ACCEPT */
-} Connection;
-
-struct _proxy {
- FD fd;
- int peer_port;
- int eof; /* end of file (read) */
- int bp; /* broken pipe (write) */
- Connection *conn;
- WriteQueue wq;
- Proxy *next;
-};
-
-/* Commands, replies, and error responses */
-
-#define ESOCK_CONNECT_CMD 1
-#define ESOCK_CONNECT_WAIT_REP 2
-#define ESOCK_CONNECT_REP 3
-#define ESOCK_CONNECT_ERR 4
-
-#define ESOCK_TERMINATE_CMD 5
-#define ESOCK_CLOSE_CMD 6
-
-#define ESOCK_LISTEN_CMD 7
-#define ESOCK_LISTEN_REP 8
-#define ESOCK_LISTEN_ERR 9
-
-#define ESOCK_TRANSPORT_ACCEPT_CMD 10
-#define ESOCK_NOACCEPT_CMD 11
-#define ESOCK_TRANSPORT_ACCEPT_REP 12
-#define ESOCK_TRANSPORT_ACCEPT_ERR 13
-
-#define ESOCK_FROMNET_CLOSE_REP 14
-
-#define ESOCK_CONNECT_SYNC_ERR 15
-#define ESOCK_LISTEN_SYNC_ERR 16
-
-#define ESOCK_PROXY_PORT_REP 23
-#define ESOCK_PROXY_JOIN_CMD 24
-#define ESOCK_PROXY_JOIN_REP 25
-#define ESOCK_PROXY_JOIN_ERR 26
-
-#define ESOCK_SET_SOCKOPT_CMD 27
-#define ESOCK_IOCTL_OK 28
-#define ESOCK_IOCTL_ERR 29
-
-#define ESOCK_GETPEERNAME_CMD 30
-#define ESOCK_GETPEERNAME_REP 31
-#define ESOCK_GETPEERNAME_ERR 32
-
-#define ESOCK_GETSOCKNAME_CMD 33
-#define ESOCK_GETSOCKNAME_REP 34
-#define ESOCK_GETSOCKNAME_ERR 35
-
-#define ESOCK_GETPEERCERT_CMD 36
-#define ESOCK_GETPEERCERT_REP 37
-#define ESOCK_GETPEERCERT_ERR 38
-
-#define ESOCK_GETVERSION_CMD 39
-#define ESOCK_GETVERSION_REP 40
-
-#define ESOCK_SET_SEED_CMD 41
-
-#define ESOCK_GETCONNINFO_CMD 42
-#define ESOCK_GETCONNINFO_REP 43
-#define ESOCK_GETCONNINFO_ERR 44
-
-#define ESOCK_SSL_ACCEPT_CMD 45
-#define ESOCK_SSL_ACCEPT_REP 46
-#define ESOCK_SSL_ACCEPT_ERR 47
-
-#define ESOCK_DUMP_STATE_CMD 48
-#define ESOCK_SET_DEBUG_CMD 49
-#define ESOCK_SET_DEBUGMSG_CMD 50
-
-
-/* Option codes for ESOCK_SET_SOCKOPT_CMD */
-#define ESOCK_SET_TCP_NODELAY 1
-
-/* SSL want to read or write */
-#define ESOCK_SSL_WANT_READ 1
-#define ESOCK_SSL_WANT_WRITE 2
-
-/* Protocol version according to ssl_server */
-#define ESOCK_SSLv2 1
-#define ESOCK_SSLv3 2
-#define ESOCK_TLSv1 4
-
-
-#endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ssl/c_src/esock_openssl.c b/lib/ssl/c_src/esock_openssl.c
deleted file mode 100644
index 2621c9934e..0000000000
--- a/lib/ssl/c_src/esock_openssl.c
+++ /dev/null
@@ -1,1213 +0,0 @@
-/*<copyright>
- * <year>1999-2008</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>
- */
-/*
- * Purpose: Adaptions for the OpenSSL package.
- *
- * This file implements the functions defined in esock_ssl.h for
- * the OpenSSL package.
- *
- * The following holds true for non-blockling I/O:
- *
- * Function Return values
- * -------- -------------
- * SSL_accept() success: 1, failure: =<0
- * SSL_connect() success: 1, failure: =<0
- * SSL_read() success: >0, eof: 0, failure: <0
- * SSL_write() success: > 0, failure: =<0
- * SSL_shutdown() success: 1, not finished: 0
- *
- * If the return value of any of the above functions is `ret' and the
- * ssl connection is `ssl', the call
- *
- * ssl_error = SSL_get_error(ssl, ret);
- *
- * returns one of the following eight values:
- *
- * SSL_ERROR_NONE ret > 0
- * SSL_ERROR_ZERO_RETURN ret = 0
- * SSL_ERROR_WANT_READ ret < 0 and ssl wants to read
- * SSL_ERROR_WANT_WRITE ret < 0 and ssl wants to write
- * SSL_ERROR_SYSCALL ret < 0 or ret = 0
- * SSL_ERROR_SSL if there was an ssl internal error
- * SSL_ERROR_WANT_X509_LOOKUP ret < 0 and ssl wants x509 lookup
- * SSL_ERROR_WANT_CONNECT ret < 0 and ssl wants connect
- *
- * It is the case that SSL_read() sometimes returns -1, even when the
- * underlying file descriptor is ready for reading.
- *
- * Also, sometimes we may have SSL_ERROR_SSL in SSL_accept() and SSL_connect()
- * when a retry should be done.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#ifndef __WIN32__
-# include <fcntl.h>
-# include <unistd.h>
-#endif
-
-#include "esock.h"
-#include "esock_ssl.h"
-#include "debuglog.h"
-#include "esock_utils.h"
-#include "esock_posix_str.h"
-
-#include <openssl/crypto.h>
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-#include <openssl/rand.h>
-
-int ephemeral_rsa = 0;
-int ephemeral_dh = 0; /* XXX Not used yet */
-int protocol_version = 0;
-
-char *esock_ssl_errstr = "";
-
-#define FLAGSBUFSIZE 512
-#define X509BUFSIZE 256
-#define DEFAULT_VERIFY_DEPTH 1
-
-#define SET_WANT(cp, ssl_error) \
- switch((ssl_error)) { \
- case SSL_ERROR_WANT_READ: \
- (cp)->ssl_want = ESOCK_SSL_WANT_READ; \
- break; \
- case SSL_ERROR_WANT_WRITE: \
- (cp)->ssl_want = ESOCK_SSL_WANT_WRITE; \
- break; \
- default: \
- (cp)->ssl_want = 0; \
- break; \
- }
-
-#define RESET_ERRSTR() \
- esock_ssl_errstr = "";
-
-#define MAYBE_SET_ERRSTR(s) \
- if (!esock_ssl_errstr[0]) \
- esock_ssl_errstr = (s);
-
-typedef struct {
- int code;
- char *text;
-} err_entry;
-
-typedef struct {
- SSL_CTX *ctx;
- char *passwd;
- int verify_depth;
-} callback_data;
-
-static char *ssl_error_str(int error);
-static void end_ssl_call(int ret, Connection *cp, int ssl_error);
-static void check_shutdown(Connection *cp);
-static int set_ssl_parameters(Connection *cp, SSL_CTX *ctx);
-static int verify_callback(int ok, X509_STORE_CTX *ctx);
-static int passwd_callback(char *buf, int num, int rwflag, void *userdata);
-static void info_callback(const SSL *ssl, int where, int ret);
-static void callback_data_free(void *parent, void *ptr,
- CRYPTO_EX_DATA *ad,
- int idx, long arg1, void *argp);
-static RSA *tmp_rsa_callback(SSL *ssl, int is_export, int keylen);
-static void restrict_protocols(SSL_CTX *ctx);
-
-static err_entry errs[] = {
- {SSL_ERROR_NONE, "SSL_ERROR_NONE"},
- {SSL_ERROR_ZERO_RETURN, "SSL_ERROR_ZERO_RETURN"},
- {SSL_ERROR_WANT_READ, "SSL_ERROR_WANT_READ"},
- {SSL_ERROR_WANT_WRITE, "SSL_ERROR_WANT_WRITE"},
- {SSL_ERROR_SYSCALL, "SSL_ERROR_SYSCALL"},
- {SSL_ERROR_SSL, "SSL_ERROR_SSL"},
- {SSL_ERROR_WANT_X509_LOOKUP, "SSL_ERROR_WANT_X509_LOOKUP"},
- {SSL_ERROR_WANT_CONNECT, "SSL_ERROR_WANT_CONNECT"}
-};
-
-static SSL_METHOD *method; /* for listen and connect init */
-static char x509_buf[X509BUFSIZE]; /* for verify_callback */
-static int callback_data_index = -1; /* for ctx ex_data */
-static unsigned char randvec[1024]; /* XXX */
-
-#if defined(__WIN32__) || OPEN_MAX > 256
-# define FOPEN_WORKAROUND(var, expr) var = (expr)
-# define VOID_FOPEN_WORKAROUND(expr) expr
-#else
-/*
- * This is an ugly workaround. On Solaris, fopen() will return NULL if
- * it gets a file descriptor > 255. To avoid that, we'll make sure that
- * there is always one low-numbered file descriptor available when
- * fopen() is called.
- */
-static int reserved_fd; /* Reserve a low-numbered file descriptor */
-# define USE_FOPEN_WORKAROUND 1
-
-# define FOPEN_WORKAROUND(var, expr) \
-do { \
- close(reserved_fd); \
- var = (expr); \
- reserved_fd = open("/dev/null", O_RDONLY); \
-} while (0)
-
-# define VOID_FOPEN_WORKAROUND(expr) \
-do { \
- close(reserved_fd); \
- expr; \
- reserved_fd = open("/dev/null", O_RDONLY); \
-} while (0)
-#endif
-
-esock_version *esock_ssl_version(void)
-{
- static esock_version vsn;
-
- vsn.compile_version = OPENSSL_VERSION_TEXT;
- vsn.lib_version = SSLeay_version(SSLEAY_VERSION);
- return &vsn;
-}
-
-char *esock_ssl_ciphers(void)
-{
- SSL_CTX *ctx;
- SSL *ssl;
- char *ciphers;
- const char *cp;
- int i = 0, used = 0, len, incr = 1024;
-
- if (!(ctx = SSL_CTX_new(method)))
- return NULL;
- restrict_protocols(ctx);
- if (!(ssl = SSL_new(ctx))) {
- SSL_CTX_free(ctx);
- return NULL;
- }
-
- ciphers = esock_malloc(incr);
- len = incr;
- *ciphers = '\0';
-
- while (1) {
- if (!(cp = SSL_get_cipher_list(ssl, i)))
- break;
- if (i > 0) {
- if (used == len) {
- len += incr;
- ciphers = esock_realloc(ciphers, len);
- }
- strcat(ciphers, ":");
- used++;
- }
- if (strlen(cp) + used >= len) {
- len += incr;
- ciphers = esock_realloc(ciphers, len);
- }
- strcat(ciphers, cp);
- used += strlen(cp);
- i++;
- }
- SSL_free(ssl);
- SSL_CTX_free(ctx);
- return ciphers;
-}
-
-void esock_ssl_seed(void *buf, int len)
-{
- RAND_seed(buf, len);
-
- /* XXX Maybe we should call RAND_status() and check if we have got
- * enough randomness.
- */
-}
-
-int esock_ssl_init(void)
-{
- method = SSLv23_method(); /* SSLv2, SSLv3 and TLSv1, may be restricted
- in listen and connect */
- SSL_load_error_strings();
- SSL_library_init();
- esock_ssl_seed(randvec, sizeof(randvec));
- callback_data_index = SSL_CTX_get_ex_new_index(0, "callback_data",
- NULL, NULL,
- callback_data_free);
-#ifdef USE_FOPEN_WORKAROUND
- reserved_fd = open("/dev/null", O_RDONLY);
- DEBUGF(("init: reserved_fd=%d\r\n", reserved_fd));
-#endif
- return 0;
-}
-
-
-void esock_ssl_finish(void)
-{
- /* Nothing */
-}
-
-
-void esock_ssl_free(Connection *cp)
-{
- SSL *ssl = cp->opaque;
- SSL_CTX *ctx;
-
- if (ssl) {
- ctx = SSL_get_SSL_CTX(ssl);
- SSL_free(ssl);
- if (cp->origin != ORIG_ACCEPT)
- SSL_CTX_free(ctx);
- cp->opaque = NULL;
- }
-}
-
-
-/*
- * Print SSL specific errors.
- */
-void esock_ssl_print_errors_fp(FILE *fp)
-{
- ERR_print_errors_fp(fp);
-}
-
-
-int esock_ssl_accept_init(Connection *cp, void *listenssl)
-{
- SSL_CTX *listenctx;
- SSL *ssl;
-
- RESET_ERRSTR();
- MAYBE_SET_ERRSTR("esslacceptinit");
-
- if(!listenssl) {
- DEBUGF(("esock_ssl_accept_init: listenssl null\n"));
- return -1;
- }
- if (!(listenctx = SSL_get_SSL_CTX(listenssl))) {
- DEBUGF(("esock_ssl_accept_init: SSL_get_SSL_CTX\n"));
- return -1;
- }
- if (!(ssl = cp->opaque = SSL_new(listenctx))) {
- DEBUGF(("esock_ssl_accept_init: SSL_new(listenctx)\n"));
- return -1;
- }
- SSL_set_fd(ssl, cp->fd);
- return 0;
-
-}
-
-
-int esock_ssl_connect_init(Connection *cp)
-{
- SSL_CTX *ctx;
- SSL *ssl;
-
- RESET_ERRSTR();
- MAYBE_SET_ERRSTR("esslconnectinit");
-
- if (!(ctx = SSL_CTX_new(method)))
- return -1;
- if (set_ssl_parameters(cp, ctx) < 0) {
- SSL_CTX_free(ctx);
- return -1;
- }
- restrict_protocols(ctx);
- if (!(ssl = cp->opaque = SSL_new(ctx))) {
- SSL_CTX_free(ctx);
- return -1;
- }
- SSL_set_fd(ssl, cp->fd);
- return 0;
-}
-
-
-int esock_ssl_listen_init(Connection *cp)
-{
- SSL_CTX *ctx;
- SSL *ssl;
-
- RESET_ERRSTR();
- MAYBE_SET_ERRSTR("essllisteninit");
-
- if (!(ctx = SSL_CTX_new(method)))
- return -1;
- if (set_ssl_parameters(cp, ctx) < 0) {
- SSL_CTX_free(ctx);
- return -1;
- }
- restrict_protocols(ctx);
-
- /* The allocation of ctx is for setting ssl parameters, so that
- * accepts can inherit them. We allocate ssl to be able to
- * refer to it via cp->opaque, but will not be used otherwise.
- */
- if (!(ssl = cp->opaque = SSL_new(ctx))) {
- SSL_CTX_free(ctx);
- return -1;
- }
- /* Set callback for temporary ephemeral RSA key generation.
- * Note: for servers only. */
- SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_callback);
- return 0;
-}
-
-/*
- * esock_ssl_accept(Connection *cp)
- *
- */
-int esock_ssl_accept(Connection *cp)
-{
- int ret, ssl_error;
- SSL *ssl = cp->opaque;
-
- RESET_ERRSTR();
-
- DEBUGF(("esock_ssl_accept: calling SSL_accept fd = %d\n"
- " state before: %s\n", cp->fd, SSL_state_string(ssl)));
- ret = SSL_accept(ssl);
- DEBUGF((" sock_errno %d errno %d \n", sock_errno(), errno));
- ssl_error = SSL_get_error(ssl, ret);
- DEBUGF((" SSL_accept = %d\n"
- " ssl_error: %s\n"
- " state after: %s\n",
- ret, ssl_error_str(ssl_error), SSL_state_string(ssl)));
- DEBUGF((" ret %d os error %s\n", ret, strerror(errno)));
- if (ret > 0)
- return ret;
- else if (ret == 0) {
- const char* f; int l; unsigned int e;
- while ((e = ERR_get_error_line(&f, &l))) {
- DEBUGF((" error %s:%d %s\n", f, l, ssl_error_str(e)));
- }
- /* permanent accept error */
- sock_set_errno(ERRNO_NONE);
- MAYBE_SET_ERRSTR("esslaccept");
- return -1;
- }
- end_ssl_call(ret, cp, ssl_error);
- return ret;
-}
-
-/*
- * esock_ssl_connect(Connection *cp)
- *
- */
-int esock_ssl_connect(Connection *cp)
-{
- int ret, ssl_error;
- SSL *ssl = cp->opaque;
-
- RESET_ERRSTR();
-
- DEBUGF(("esock_ssl_connect: calling SSL_connect fd = %d\n"
- " state before: %s\n", cp->fd, SSL_state_string(ssl)));
- ret = SSL_connect(ssl);
- ssl_error = SSL_get_error(ssl, ret);
- DEBUGF((" SSL_connect() = %d\n"
- " ssl_error: %s\n"
- " state after: %s\n",
- ret, ssl_error_str(ssl_error), SSL_state_string(ssl)));
- if (ret > 0)
- return ret;
- else if (ret == 0) {
- /* permanent connect error */
- sock_set_errno(ERRNO_NONE);
- MAYBE_SET_ERRSTR("esslconnect");
- return -1;
- }
- end_ssl_call(ret, cp, ssl_error);
- return ret;
-}
-
-
-int esock_ssl_session_reused(Connection *cp)
-{
- SSL *ssl = cp->opaque;
-
- return SSL_session_reused(ssl);
-}
-
-
-/* esock_ssl_read(Connection *cp, char *buf, int len)
- *
- * Read at most `len' chars into `buf'. Returns number of chars
- * read ( > 0), or 0 at EOF, or -1 on error. Sets cp->eof, cp->bp if
- * appropriate.
- */
-
-int esock_ssl_read(Connection *cp, char *buf, int len)
-{
- int ret, ssl_error;
- SSL *ssl = cp->opaque;
-
- RESET_ERRSTR();
- DEBUGF(("esock_ssl_read: calling SSL_read fd = %d\n"
- " state before: %s\n", cp->fd, SSL_state_string(ssl)));
-
- ret = SSL_read(ssl, buf, len);
- ssl_error = SSL_get_error(ssl, ret);
-
- DEBUGF((" SSL_read = %d\n"
- " ssl_error: %s\n"
- " state after: %s\n",
- ret, ssl_error_str(ssl_error), SSL_state_string(ssl)));
-
- if (ssl_error == SSL_ERROR_NONE) {
- DEBUGMSGF(("message (hex) : [%3.*a]\n", ret, buf));
- DEBUGMSGF(("message (char): [%3.*b]\n", ret, buf));
- }
- if (ret > 0)
- return ret;
- if (ret == 0) {
- check_shutdown(cp);
- return ret;
- }
- end_ssl_call(ret, cp, ssl_error);
- return ret;
-}
-
-/*
- * esock_ssl_write(Connection *cp, char *buf, int len)
- *
- * Writes at most `len' chars from `buf'. Returns number of chars
- * written, or -1 on error.
- */
-int esock_ssl_write(Connection *cp, char *buf, int len)
-{
- int ret, ssl_error;
- SSL *ssl = cp->opaque;
-
- RESET_ERRSTR();
- DEBUGF(("esock_ssl_write: calling SSL_write fd = %d\n"
- " state before: %s\n", cp->fd, SSL_state_string(ssl)));
- ret = SSL_write(ssl, buf, len);
- ssl_error = SSL_get_error(ssl, ret);
- DEBUGF((" SSL_write = %d\n"
- " ssl_error: %s\n"
- " state after: %s\n",
- ret, ssl_error_str(ssl_error), SSL_state_string(ssl)));
- if (ssl_error == SSL_ERROR_NONE) {
- DEBUGMSGF(("message (hex) : [%3.*a]\n", ret, buf));
- DEBUGMSGF(("message (char): [%3.*b]\n", ret, buf));
- }
- if (ret > 0)
- return ret;
- if (ret == 0) {
- check_shutdown(cp);
- return ret;
- }
- end_ssl_call(ret, cp, ssl_error);
- return ret;
-}
-
-
-int esock_ssl_shutdown(Connection *cp)
-{
- int ret, ssl_error;
- SSL *ssl = cp->opaque;
-
- RESET_ERRSTR();
- DEBUGF(("esock_ssl_shutdown: calling SSL_shutdown fd = %d\n"
- " state before: %s\n", cp->fd, SSL_state_string(ssl)));
- ret = SSL_shutdown(ssl);
- ssl_error = SSL_get_error(ssl, ret);
- DEBUGF((" SSL_shutdown = %d\n"
- " ssl_error: %s\n"
- " state after: %s\n",
- ret, ssl_error_str(ssl_error), SSL_state_string(ssl)));
- if (ret >= 0) {
- check_shutdown(cp);
- return ret;
- }
- end_ssl_call(ret, cp, ssl_error);
- return ret;
-}
-
-
-/* Returns total number of bytes in DER encoded cert pointed to by
- * *buf, which is allocated by this function, unless return < 0.
- * XXX X509_free ??
- */
-int esock_ssl_getpeercert(Connection *cp, unsigned char **buf)
-{
- int len;
- SSL *ssl = cp->opaque;
- X509 *x509;
- unsigned char *tmp;
-
- RESET_ERRSTR();
- if((x509 = SSL_get_peer_certificate(ssl)) == NULL) {
- MAYBE_SET_ERRSTR("enopeercert"); /* XXX doc */
- return -1;
- }
-
- if ((len = i2d_X509(x509, NULL)) <= 0) {
- MAYBE_SET_ERRSTR("epeercert");
- return -1;
- }
-
- tmp = *buf = esock_malloc(len);
-
- /* We must use a temporary value here, since i2d_X509(X509 *x,
- * unsigned char **out) increments *out.
- */
- if (i2d_X509(x509, &tmp) < 0) {
- esock_free(tmp);
- MAYBE_SET_ERRSTR("epeercert");
- return -1;
- }
- return len;
-}
-
-/* Returns total number of bytes in chain of certs. Each cert begins
- * with a 4-bytes length. The last cert is ended with 4-bytes of
- * zeros. The result is returned in *buf, which is allocated unless
- * the return value is < 0.
- * XXX X509_free ? sk_X509_free ?
- * XXX X509_free is reference counting.
- */
-int esock_ssl_getpeercertchain(Connection *cp, unsigned char **buf)
-{
- SSL *ssl = cp->opaque;
- STACK_OF(X509) *x509_stack;
- X509 *x509;
- int num, i, totlen, pos, *der_len;
- unsigned char *vbuf;
-
- RESET_ERRSTR();
- if((x509_stack = SSL_get_peer_cert_chain(ssl)) == NULL) {
- MAYBE_SET_ERRSTR("enopeercertchain"); /* XXX doc */
- return -1;
- }
-
- num = sk_X509_num(x509_stack);
- der_len = esock_malloc(num * sizeof(int));
- totlen = 0;
-
- for (i = 0; i < num; i++) {
- x509 = sk_X509_value(x509_stack, i);
- totlen += 4;
- if ((der_len[i] = i2d_X509(x509, NULL)) < 0) {
- MAYBE_SET_ERRSTR("epeercertchain");
- esock_free(der_len);
- return -1;
- }
- totlen += der_len[i];
- }
- totlen += 4;
-
- vbuf = *buf = esock_malloc(totlen);
- pos = 0;
-
- for (i = 0; i < num; i++) {
- x509 = sk_X509_value(x509_stack, i);
- PUT_INT32(der_len[i], vbuf);
- vbuf += 4;
- /* Note: i2d_X509 increments vbuf */
- if (i2d_X509(x509, &vbuf) < 0) {
- MAYBE_SET_ERRSTR("epeercertchain");
- esock_free(*buf);
- esock_free(der_len);
- return -1;
- }
- }
- esock_free(der_len);
- return totlen;
-}
-
-
-int esock_ssl_getprotocol_version(Connection *cp, char **buf)
-{
- SSL *ssl = cp->opaque;
-
- RESET_ERRSTR();
- if (!ssl) {
- MAYBE_SET_ERRSTR("enoent");
- return -1;
- }
- *buf = (char *) SSL_get_version(ssl);
-
- return 0;
-}
-
-
-int esock_ssl_getcipher(Connection *cp, char **buf)
-{
- SSL *ssl = cp->opaque;
-
- RESET_ERRSTR();
- if (!ssl) {
- MAYBE_SET_ERRSTR("enoent");
- return -1;
- }
- *buf = (char *) SSL_get_cipher(ssl);
-
- return 0;
-}
-
-/* Local functions */
-
-static char *ssl_error_str(int ssl_error)
-{
- int i;
- static char buf[128];
-
- for (i = 0; i < sizeof(errs)/sizeof(err_entry); i ++) {
- if (ssl_error == errs[i].code)
- return errs[i].text;
- }
- sprintf(buf, "esock_openssl: SSL_error unknown: %d", ssl_error);
- return buf;
-}
-
-void end_ssl_call(int ret, Connection *cp, int ssl_error)
-{
- SET_WANT(cp, ssl_error);
- switch (ssl_error) {
- case SSL_ERROR_SYSCALL:
- /* Typically sock_errno() is equal to ERRNO_BLOCK */
- MAYBE_SET_ERRSTR(esock_posix_str(sock_errno()));
- break;
- case SSL_ERROR_SSL:
- sock_set_errno(ERRNO_NONE);
- MAYBE_SET_ERRSTR("esslerrssl");
- break;
- case SSL_ERROR_WANT_X509_LOOKUP:
- SSLDEBUGF();
- sock_set_errno(ERRNO_NONE);
- MAYBE_SET_ERRSTR("ex509lookup");
- break;
- case SSL_ERROR_WANT_CONNECT:
- SSLDEBUGF();
- sock_set_errno(ERRNO_NONE);
- MAYBE_SET_ERRSTR("ewantconnect");
- break;
- default:
- break;
- }
-}
-
-void check_shutdown(Connection *cp)
-{
- int sd_mode;
- SSL *ssl = cp->opaque;
-
- sd_mode = SSL_get_shutdown(ssl);
- if (sd_mode & SSL_RECEIVED_SHUTDOWN)
- cp->eof = 1;
- if (sd_mode & SSL_SENT_SHUTDOWN) {
- DEBUGF(("check_shutdown SSL_SENT_SHUTDOWN\n"));
- cp->bp = 1;
- }
-}
-
-/*
- * set_ssl_parameters
- *
- * Set ssl parameters from connection structure. Only called for
- * listen and connect.
- *
- * Note: The -cacertdir option is not documented.
- */
-static int set_ssl_parameters(Connection *cp, SSL_CTX *ctx)
-{
- char *cacertfile = NULL, *cacertdir = NULL, *certfile = NULL;
- char *keyfile = NULL, *ciphers = NULL, *password = NULL;
- int verify = 0, verify_depth = DEFAULT_VERIFY_DEPTH, verify_mode;
- int i, argc;
- char **argv;
- callback_data *cb_data;
-
- RESET_ERRSTR();
-
- argc = esock_build_argv(cp->flags, &argv);
-
- DEBUGF(("Argv:\n"));
- for (i = 0; i < argc; i++) {
- DEBUGF(("%d: %s\n", i, argv[i]));
- }
-
- for (i = 0; i < argc; i++) {
- if (strcmp(argv[i], "-verify") == 0) {
- verify = atoi(argv[++i]);
- } else if (strcmp(argv[i], "-depth") == 0) {
- verify_depth = atoi(argv[++i]);
- } else if (strcmp(argv[i], "-log") == 0) {
- /* XXX ignored: logging per connection not supported */
- i++;
- } else if (strcmp(argv[i], "-certfile") == 0) {
- certfile = argv[++i];
- } else if (strcmp(argv[i], "-keyfile") == 0) {
- keyfile = argv[++i];
- } else if (strcmp(argv[i], "-password") == 0) {
- password = argv[++i];
- } else if (strcmp(argv[i], "-cacertfile") == 0) {
- cacertfile = argv[++i];
- } else if (strcmp(argv[i], "-cacertdir") == 0) {
- cacertdir = argv[++i];
- } else if (strcmp(argv[i], "-d") == 0) {
- /* XXX ignored: debug per connection not supported */
- i++;
- } else if (strcmp(argv[i], "-ciphers") == 0) {
- ciphers = argv[++i];
- } else {
- /* XXX Error: now ignored */
- }
- }
- DEBUGF(("set_ssl_parameters: all arguments read\n"));
-
- if (cp->origin == ORIG_LISTEN && !certfile) {
- DEBUGF(("ERROR: Server must have certificate\n"));
- MAYBE_SET_ERRSTR("enoservercert");
- goto err_end;
- }
-
- /* Define callback data */
- /* XXX Check for NULL */
- cb_data = esock_malloc(sizeof(callback_data));
- cb_data->ctx = ctx;
- if (password) {
- cb_data->passwd = esock_malloc(strlen(password) + 1);
- strcpy(cb_data->passwd, password);
- } else
- cb_data->passwd = NULL;
- cb_data->verify_depth = verify_depth;
- SSL_CTX_set_ex_data(ctx, callback_data_index, cb_data);
-
- /* password callback */
- SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
- SSL_CTX_set_default_passwd_cb_userdata(ctx, cb_data);
-
- /* Set location for "trusted" certificates */
- if (cacertfile || cacertdir) {
- int res;
- DEBUGF(("set_ssl_parameters: SSL_CTX_load_verify_locations\n"));
- FOPEN_WORKAROUND(res, SSL_CTX_load_verify_locations(ctx, cacertfile,
- cacertdir));
- if (!res) {
- DEBUGF(("ERROR: Cannot load verify locations\n"));
- MAYBE_SET_ERRSTR("ecacertfile");
- goto err_end;
- }
- } else {
- int res;
- DEBUGF(("set_ssl_parameters: SSL_CTX_set_default_verify_paths\n"));
- FOPEN_WORKAROUND(res, SSL_CTX_set_default_verify_paths(ctx));
- if (!res) {
- DEBUGF(("ERROR: Cannot set default verify paths\n"));
- MAYBE_SET_ERRSTR("ecacertfile");
- goto err_end;
- }
- }
-
- /* For a server the following sets the list of CA distinguished
- * names that it sends to its client when it requests the
- * certificate from the client.
- * XXX The names of certs in cacertdir ignored.
- */
- if (cp->origin == ORIG_LISTEN && cacertfile) {
- DEBUGF(("set_ssl_parameters: SSL_CTX_set_client_CA_list\n"));
- VOID_FOPEN_WORKAROUND(SSL_CTX_set_client_CA_list(ctx,
- SSL_load_client_CA_file(cacertfile)));
- if (!SSL_CTX_get_client_CA_list(ctx)) {
- DEBUGF(("ERROR: Cannot set client CA list\n"));
- MAYBE_SET_ERRSTR("ecacertfile");
- goto err_end;
- }
- }
-
- /* Use certificate file if key file has not been set. */
- if (!keyfile)
- keyfile = certfile;
-
- if (certfile) {
- int res;
- DEBUGF(("set_ssl_parameters: SSL_CTX_use_certificate_file\n"));
- FOPEN_WORKAROUND(res, SSL_CTX_use_certificate_file(ctx, certfile,
- SSL_FILETYPE_PEM));
- if (res <= 0) {
- DEBUGF(("ERROR: Cannot set certificate file\n"));
- MAYBE_SET_ERRSTR("ecertfile");
- goto err_end;
- }
- }
- if (keyfile) {
- int res;
- DEBUGF(("set_ssl_parameters: SSL_CTX_use_PrivateKey_file\n"));
- FOPEN_WORKAROUND(res, SSL_CTX_use_PrivateKey_file(ctx, keyfile,
- SSL_FILETYPE_PEM));
- if (res <= 0) {
- DEBUGF(("ERROR: Cannot set private key file\n"));
- MAYBE_SET_ERRSTR("ekeyfile");
- goto err_end;
- }
- }
- if(certfile && keyfile) {
- DEBUGF(("set_ssl_parameters: SSL_CTX_check_private_key\n"));
- if (!SSL_CTX_check_private_key(ctx)) {
- DEBUGF(("ERROR: Private key does not match the certificate\n"));
- MAYBE_SET_ERRSTR("ekeymismatch");
- goto err_end;
- }
- }
-
- /* Ciphers */
- if (ciphers) {
- DEBUGF(("set_ssl_parameters: SSL_CTX_set_cipher_list\n"));
- if (!SSL_CTX_set_cipher_list(ctx, ciphers)) {
- DEBUGF(("ERROR: Cannot set cipher list\n"));
- MAYBE_SET_ERRSTR("ecipher");
- goto err_end;
- }
- }
-
- /* Verify depth */
- DEBUGF(("set_ssl_parameters: SSL_CTX_set_verify_depth (depth = %d)\n",
- verify_depth));
- SSL_CTX_set_verify_depth(ctx, verify_depth);
-
- /* Verify mode and callback */
- /* XXX Why precisely these modes? */
- switch (verify) {
- case 0:
- verify_mode = SSL_VERIFY_NONE;
- break;
- case 1:
- verify_mode = SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE;
- break;
- case 2:
- verify_mode = SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE|
- SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
- break;
- default:
- verify_mode = SSL_VERIFY_NONE;
- }
- DEBUGF(("set_ssl_parameters: SSL_CTX_set_verify (verify = %d)\n",
- verify));
- SSL_CTX_set_verify(ctx, verify_mode, verify_callback);
-
- /* Session id context. Should be an option really. */
- if (cp->origin == ORIG_LISTEN) {
- unsigned char *sid = "Erlang/OTP/ssl";
- SSL_CTX_set_session_id_context(ctx, sid, strlen(sid));
- }
-
- /* info callback */
- if (debug)
- SSL_CTX_set_info_callback(ctx, info_callback);
-
- DEBUGF(("set_ssl_parameters: done\n"));
- /* Free arg list */
- for (i = 0; argv[i]; i++)
- esock_free(argv[i]);
- esock_free(argv);
- return 0;
-
- err_end:
- DEBUGF(("set_ssl_parameters: error\n"));
- /* Free arg list */
- for (i = 0; argv[i]; i++)
- esock_free(argv[i]);
- esock_free(argv);
- return -1;
-}
-
-/* Call back functions */
-
-static int verify_callback(int ok, X509_STORE_CTX *x509_ctx)
-{
- X509 *cert;
- int cert_err, depth;
- SSL *ssl;
- SSL_CTX *ctx;
- callback_data *cb_data;
-
- cert = X509_STORE_CTX_get_current_cert(x509_ctx);
- cert_err = X509_STORE_CTX_get_error(x509_ctx);
- depth = X509_STORE_CTX_get_error_depth(x509_ctx);
-
- ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
- SSL_get_ex_data_X509_STORE_CTX_idx());
- ctx = SSL_get_SSL_CTX(ssl);
- cb_data = SSL_CTX_get_ex_data(ctx, callback_data_index);
-
- X509_NAME_oneline(X509_get_subject_name(cert), x509_buf, sizeof(x509_buf));
- DEBUGF((" +vfy: depth = %d\n", depth));
- DEBUGF((" subject = %s\n", x509_buf));
- X509_NAME_oneline(X509_get_issuer_name(cert), x509_buf, sizeof(x509_buf));
- DEBUGF((" issuer = %s\n", x509_buf));
-
- if (!ok) {
- DEBUGF((" +vfy: error = %d [%s]\n", cert_err,
- X509_verify_cert_error_string(cert_err)));
- if (depth >= cb_data->verify_depth)
- ok = 1;
- }
-
- switch (cert_err) {
- case X509_V_OK:
- case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
- ok = 1;
- break;
- case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
- case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
- MAYBE_SET_ERRSTR("enoissuercert");
- break;
- case X509_V_ERR_CERT_HAS_EXPIRED:
- MAYBE_SET_ERRSTR("epeercertexpired");
- break;
- case X509_V_ERR_CERT_NOT_YET_VALID:
- case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
- case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
- MAYBE_SET_ERRSTR("epeercertinvalid");
- break;
- case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
- MAYBE_SET_ERRSTR("eselfsignedcert");
- break;
- case X509_V_ERR_CERT_CHAIN_TOO_LONG:
- MAYBE_SET_ERRSTR("echaintoolong");
- break;
- default:
- MAYBE_SET_ERRSTR("epeercert");
- break;
- }
- DEBUGF((" +vfy: return = %d\n",ok));
- return ok;
-}
-
-static int passwd_callback(char *buf, int num, int rwflag, void *userdata)
-{
- callback_data *cb_data = userdata;
- int len;
-
- if (cb_data && cb_data->passwd) {
- DEBUGF((" +passwd: %s\n", cb_data->passwd));
- strncpy(buf, cb_data->passwd, num);
- len = strlen(cb_data->passwd);
- return len;
- }
- DEBUGF((" +passwd: ERROR: No password set.\n"));
- return 0;
-}
-
-static void info_callback(const SSL *ssl, int where, int ret)
-{
- char *str;
-
- if (where & SSL_CB_LOOP) {
- DEBUGF((" info: %s\n",SSL_state_string_long(ssl)));
- } else if (where & SSL_CB_ALERT) {
- str = (where & SSL_CB_READ) ? "read" : "write";
- DEBUGF((" info: SSL3 alert %s:%s:%s\n", str,
- SSL_alert_type_string_long(ret),
- SSL_alert_desc_string_long(ret)));
- } else if (where & SSL_CB_EXIT) {
- if (ret == 0) {
- DEBUGF((" info: failed in %s\n", SSL_state_string_long(ssl)));
- } else if (ret < 0) {
- DEBUGF((" info: error in %s\n", SSL_state_string_long(ssl)));
- }
- }
-}
-
-/* This function is called whenever a SSL_CTX *ctx structure is
- * freed.
-*/
-static void callback_data_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
- int idx, long arg1, void *argp)
-{
- callback_data *cb_data = ptr;
-
- if (cb_data) {
- if (cb_data->passwd)
- esock_free(cb_data->passwd);
- esock_free(cb_data);
- }
-}
-
-static RSA *tmp_rsa_callback(SSL *ssl, int is_export, int keylen)
-{
- static RSA *rsa512 = NULL;
- static RSA *rsa1024 = NULL;
-
- switch (keylen) {
- case 512:
- if (!rsa512)
- rsa512 = RSA_generate_key(keylen, RSA_F4, NULL, NULL);
- return rsa512;
- break;
- case 1024:
- if (!rsa1024)
- rsa1024 = RSA_generate_key(keylen, RSA_F4, NULL, NULL);
- return rsa1024;
- break;
- default:
- if (rsa1024)
- return rsa1024;
- if (rsa512)
- return rsa512;
- rsa512 = RSA_generate_key(keylen, RSA_F4, NULL, NULL);
- return rsa512;
- }
-}
-
-/* Restrict protocols (SSLv2, SSLv3, TLSv1) */
-static void restrict_protocols(SSL_CTX *ctx)
-{
- long options = 0;
-
- if (protocol_version) {
- if ((protocol_version & ESOCK_SSLv2) == 0)
- options |= SSL_OP_NO_SSLv2;
- if ((protocol_version & ESOCK_SSLv3) == 0)
- options |= SSL_OP_NO_SSLv3;
- if ((protocol_version & ESOCK_TLSv1) == 0)
- options |= SSL_OP_NO_TLSv1;
- SSL_CTX_set_options(ctx, options);
- }
-}
-
-
-static unsigned char randvec [] = {
- 181, 177, 237, 240, 107, 24, 43, 148,
- 105, 4, 248, 13, 199, 255, 23, 58,
- 71, 181, 57, 151, 156, 25, 165, 7,
- 73, 80, 80, 231, 70, 110, 96, 162,
- 24, 205, 178, 178, 67, 122, 210, 180,
- 92, 6, 156, 182, 84, 159, 85, 6,
- 175, 66, 165, 167, 137, 34, 179, 237,
- 77, 90, 87, 185, 21, 106, 92, 115,
- 137, 65, 233, 42, 164, 153, 208, 133,
- 160, 172, 129, 202, 46, 220, 98, 66,
- 115, 66, 46, 28, 226, 200, 140, 145,
- 207, 194, 58, 71, 56, 203, 113, 34,
- 221, 116, 63, 114, 188, 210, 45, 238,
- 200, 123, 35, 150, 2, 78, 160, 22,
- 226, 167, 162, 10, 182, 75, 109, 97,
- 86, 252, 93, 125, 117, 214, 220, 37,
- 105, 160, 56, 158, 97, 57, 22, 14,
- 73, 169, 111, 190, 222, 176, 14, 82,
- 111, 42, 87, 90, 136, 236, 22, 209,
- 156, 207, 40, 251, 88, 141, 51, 211,
- 31, 158, 153, 91, 119, 83, 255, 60,
- 55, 94, 5, 115, 119, 210, 224, 185,
- 163, 163, 5, 3, 197, 106, 110, 206,
- 109, 132, 50, 190, 177, 133, 175, 129,
- 225, 161, 156, 244, 77, 150, 99, 38,
- 17, 111, 46, 230, 152, 64, 50, 164,
- 19, 78, 3, 164, 169, 175, 104, 97,
- 103, 158, 91, 168, 186, 191, 73, 88,
- 118, 112, 41, 188, 219, 0, 198, 209,
- 206, 7, 5, 169, 127, 180, 80, 74,
- 124, 4, 4, 108, 197, 67, 204, 29,
- 101, 95, 174, 147, 64, 163, 89, 160,
- 10, 5, 56, 134, 209, 69, 209, 55,
- 214, 136, 45, 212, 113, 85, 159, 133,
- 141, 249, 75, 40, 175, 91, 142, 13,
- 179, 179, 51, 0, 136, 63, 148, 175,
- 103, 162, 8, 214, 4, 24, 59, 71,
- 9, 185, 48, 127, 159, 165, 8, 8,
- 135, 151, 92, 214, 132, 151, 204, 169,
- 24, 112, 229, 59, 236, 81, 238, 64,
- 150, 196, 97, 213, 140, 159, 20, 24,
- 79, 210, 191, 53, 130, 33, 157, 87,
- 16, 180, 175, 217, 56, 123, 115, 196,
- 130, 6, 155, 37, 220, 80, 232, 129,
- 240, 57, 199, 249, 196, 152, 28, 111,
- 124, 192, 59, 46, 29, 21, 178, 51,
- 156, 17, 248, 61, 254, 80, 201, 131,
- 203, 59, 227, 191, 71, 121, 134, 181,
- 55, 79, 130, 225, 246, 36, 179, 224,
- 189, 243, 200, 75, 73, 41, 251, 41,
- 71, 251, 78, 146, 99, 101, 104, 69,
- 18, 122, 65, 24, 232, 84, 246, 242,
- 209, 18, 241, 114, 3, 65, 177, 99,
- 49, 99, 215, 59, 9, 175, 195, 11,
- 25, 46, 43, 120, 109, 179, 159, 250,
- 239, 246, 135, 78, 2, 238, 214, 237,
- 64, 170, 50, 44, 68, 67, 111, 232,
- 225, 230, 224, 124, 76, 32, 52, 158,
- 151, 54, 184, 135, 122, 66, 211, 215,
- 121, 90, 124, 158, 55, 73, 116, 137,
- 240, 15, 38, 31, 183, 86, 93, 49,
- 148, 184, 125, 250, 155, 216, 84, 246,
- 27, 172, 141, 54, 80, 158, 227, 254,
- 189, 164, 238, 229, 68, 26, 231, 11,
- 198, 222, 15, 141, 98, 8, 124, 219,
- 60, 125, 170, 213, 114, 24, 189, 65,
- 80, 186, 71, 126, 223, 153, 20, 141,
- 110, 73, 173, 218, 214, 63, 205, 177,
- 132, 115, 184, 28, 122, 232, 210, 72,
- 237, 41, 93, 17, 152, 95, 242, 138,
- 79, 98, 47, 197, 36, 17, 137, 230,
- 15, 73, 193, 1, 181, 123, 0, 186,
- 185, 135, 142, 200, 139, 78, 57, 145,
- 191, 32, 98, 250, 113, 188, 71, 32,
- 205, 81, 219, 99, 60, 87, 42, 95,
- 249, 252, 121, 125, 246, 230, 74, 162,
- 73, 59, 179, 142, 178, 47, 163, 161,
- 236, 14, 123, 219, 18, 6, 102, 140,
- 215, 210, 76, 9, 119, 147, 252, 63,
- 13, 51, 161, 172, 180, 116, 212, 129,
- 116, 237, 38, 64, 213, 222, 35, 14,
- 183, 237, 78, 204, 250, 250, 5, 41,
- 142, 5, 207, 154, 65, 183, 108, 82,
- 1, 43, 149, 233, 89, 195, 25, 233,
- 4, 34, 19, 122, 16, 58, 121, 5,
- 118, 168, 22, 213, 49, 226, 163, 169,
- 21, 78, 179, 232, 125, 216, 198, 147,
- 245, 196, 199, 138, 185, 167, 179, 82,
- 175, 53, 6, 162, 5, 141, 180, 212,
- 95, 201, 234, 169, 111, 175, 138, 197,
- 177, 246, 154, 41, 185, 201, 134, 187,
- 88, 99, 231, 23, 190, 36, 72, 174,
- 244, 185, 205, 50, 230, 226, 210, 119,
- 175, 107, 109, 244, 12, 122, 84, 51,
- 146, 95, 68, 74, 76, 212, 221, 103,
- 244, 71, 63, 133, 149, 233, 48, 3,
- 176, 168, 6, 98, 88, 226, 120, 190,
- 205, 249, 38, 157, 205, 148, 250, 203,
- 147, 62, 195, 229, 219, 109, 177, 119,
- 120, 43, 165, 99, 253, 210, 180, 32,
- 227, 180, 174, 64, 156, 139, 251, 53,
- 205, 132, 210, 208, 3, 199, 115, 64,
- 59, 27, 249, 164, 224, 191, 124, 241,
- 142, 10, 19, 120, 227, 46, 174, 231,
- 48, 65, 41, 56, 51, 38, 185, 95,
- 250, 182, 100, 40, 196, 124, 173, 119,
- 162, 148, 170, 34, 51, 68, 175, 60,
- 242, 201, 225, 34, 146, 157, 159, 0,
- 144, 148, 82, 72, 149, 53, 201, 10,
- 248, 206, 154, 126, 33, 153, 56, 48,
- 5, 90, 194, 22, 251, 173, 211, 202,
- 203, 253, 112, 147, 188, 200, 142, 206,
- 206, 175, 233, 76, 93, 104, 125, 41,
- 64, 145, 202, 53, 130, 251, 23, 90,
- 28, 199, 13, 128, 185, 154, 53, 194,
- 195, 55, 80, 56, 151, 216, 195, 138,
- 7, 170, 143, 236, 74, 141, 229, 174,
- 32, 165, 131, 68, 174, 104, 35, 143,
- 183, 41, 80, 191, 120, 79, 166, 240,
- 123, 55, 60, 2, 128, 56, 4, 199,
- 122, 85, 90, 76, 246, 29, 13, 6,
- 126, 229, 14, 203, 244, 73, 121, 42,
- 169, 35, 44, 202, 18, 69, 153, 120,
- 141, 77, 124, 191, 215, 18, 115, 187,
- 108, 246, 135, 151, 225, 192, 50, 89,
- 128, 45, 39, 253, 149, 234, 203, 84,
- 51, 174, 15, 237, 17, 57, 76, 81,
- 39, 107, 40, 36, 22, 52, 92, 39};
diff --git a/lib/ssl/c_src/esock_osio.c b/lib/ssl/c_src/esock_osio.c
deleted file mode 100644
index 41c5271c16..0000000000
--- a/lib/ssl/c_src/esock_osio.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/*<copyright>
- * <year>1999-2008</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>
- */
-/*
- * Purpose: Std filedescriptors, break handler
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef __WIN32__
-#include "esock_winsock.h"
-#include <process.h>
-#include <io.h>
-#include <fcntl.h>
-#else
-#include <unistd.h>
-#include <signal.h>
-#endif
-
-#include "esock.h"
-#include "debuglog.h"
-#include "esock_utils.h"
-#include "esock_osio.h"
-
-#ifdef __WIN32__
-#define write _write
-#define read _read
-#define LOCALHOSTADDR "127.0.0.1"
-#define LOCBUFSIZE 1024
-#endif
-
-#define PACKET_SIZE 4
-#define EBUFSIZE 256
-
-FD local_read_fd = 0;
-
-static int inc_rbuf(int size);
-static void free_rbuf(void);
-static int read_fill(unsigned char *buf, int len);
-#ifdef __WIN32__
-static int create_local_thread(void);
-static DWORD WINAPI local_thread(LPVOID lpvParam);
-static BOOL WINAPI signal_handler(DWORD ctrl);
-#endif
-
-static unsigned char *rbuf = NULL;
-static int rbuf_malloced = 0;
-#ifdef __WIN32__
-static unsigned long one = 1, zero = 0;
-static int local_portno;
-static char *local_buf;
-#endif
-
-int set_break_handler(void)
-{
-#ifndef __WIN32__
- struct sigaction act;
-
- /* Ignore SIGPIPE signal */
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
- act.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &act, NULL);
- return 0;
-#else
- SetConsoleCtrlHandler(signal_handler, TRUE);
- return 0;
-#endif
-}
-
-
-#ifdef __WIN32__
-
-int set_binary_mode(void)
-{
- _setmode(0, _O_BINARY);
- _setmode(1, _O_BINARY);
- return 0;
-}
-
-int esock_osio_init(void)
-{
- return create_local_thread();
-}
-
-void esock_osio_finish(void)
-{
- sock_close(local_read_fd);
-}
-
-#endif
-
-int read_ctrl(unsigned char **ebufp)
-{
- int tbh, cc;
- unsigned char *mbuf;
-
- if (inc_rbuf(EBUFSIZE) < 0) {
- fprintf(stderr, "read_ctrl: cannot alloc rbuf\n");
- return -1;
- }
- cc = read_fill(rbuf, PACKET_SIZE);
- if (cc < 0) {
- free_rbuf();
- return -1;
- }
- if (cc == 0) {
- free_rbuf();
- return -1; /* XXX 0 ?? */
- }
- tbh = GET_INT32(rbuf);
-
- if (tbh > rbuf_malloced - 4) {
- if (inc_rbuf(tbh + 4) < 0)
- return -1;
- }
-
- mbuf = rbuf + PACKET_SIZE;
- cc = read_fill(mbuf, tbh);
- DEBUGF(("-----------------------------------\n"));
- DEBUGF(("read_ctrl: cc = %d\n", cc));
- if(cc > 0) {
- DEBUGMSGF(("message (hex) : [%3.*a]\n", cc, mbuf));
- DEBUGMSGF(("message (char): [%3.*b]\n", cc, mbuf));
- }
- *ebufp = mbuf;
- return cc;
-}
-
-int write_ctrl(unsigned char *buf, int len)
-{
- unsigned char lb[4];
-
- PUT_INT32(len, lb);
- DEBUGF(("write_ctrl: len = %d\n", len));
- DEBUGMSGF(("message (hex) : [%3.*a] [%3.*a]\n", PACKET_SIZE, lb,
- len, buf));
- DEBUGMSGF(("message (char): [%3.*b] [%3.*b]\n", PACKET_SIZE, lb,
- len, buf));
-
- if (write(1, lb, PACKET_SIZE) != PACKET_SIZE) { /* XXX */
- fprintf(stderr, "write_ctrl: Bad write \n");
- return -1;
- }
- if (write(1, buf, len) != len) { /* XXX */
- fprintf(stderr, "write_ctrl: Bad write \n");
- return -1;
- }
- return len;
-}
-
-
-/*
- * Local functions
- *
- */
-
-static int inc_rbuf(int size)
-{
- unsigned char *nbuf;
-
- if (rbuf_malloced >= size)
- return 0;
- if (rbuf != NULL)
- nbuf = esock_realloc(rbuf, size);
- else
- nbuf = esock_malloc(size);
- if(nbuf != NULL) {
- rbuf = nbuf;
- rbuf_malloced = size;
- return 0;
- }
- return -1;
-}
-
-static void free_rbuf(void)
-{
- if (rbuf != NULL) {
- esock_free(rbuf);
- rbuf = NULL;
- rbuf_malloced = 0;
- }
-}
-
-/* Fill buffer, return buffer length, 0 for EOF, < 0 for error. */
-
-static int read_fill(unsigned char *buf, int len)
-{
- int i, got = 0;
-
- do {
- if ((i = sock_read(local_read_fd, buf+got, len-got)) <= 0)
- return i;
- got += i;
- } while (got < len);
- return len;
-}
-
-
-#ifdef __WIN32__
-
-/*
- * This routine creates a local thread, which reads from standard input
- * and writes to a socket.
- */
-
-static int create_local_thread(void)
-{
- struct sockaddr_in iserv_addr;
- SOCKET tmpsock;
- int length;
- unsigned threadaddr;
-
- local_buf = esock_malloc(LOCBUFSIZE);
- if ((tmpsock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
- fprintf(stderr, "create_local_thread could not create socket.\n");
- return -1;
- }
- memset(&iserv_addr, 0, sizeof(iserv_addr));
- iserv_addr.sin_family = AF_INET;
- iserv_addr.sin_addr.s_addr = inet_addr(LOCALHOSTADDR);
- iserv_addr.sin_port = htons(0); /* Have any port */
-
- if (bind(tmpsock, (struct sockaddr *) &iserv_addr,
- sizeof(iserv_addr)) < 0) {
- fprintf(stderr, "create_local_thread could not bind.\n");
- closesocket(tmpsock);
- return -1;
- }
- listen(tmpsock, 1);
- length = sizeof(iserv_addr);
- if (getsockname(tmpsock, (struct sockaddr *) &iserv_addr, &length) < 0) {
- fprintf(stderr, "create_local_thread could not getsockname.\n");
- closesocket(tmpsock);
- return -1;
- }
- local_portno = ntohs(iserv_addr.sin_port);
-
- if (_beginthreadex(NULL, 0, local_thread, NULL, 0, &threadaddr) == 0) {
- fprintf(stderr, "create_local_thread could not _beginthreadex().\n");
- closesocket(tmpsock);
- return -1;
- }
- local_read_fd = accept(tmpsock, (struct sockaddr *) NULL, (int *) NULL);
- if (local_read_fd == INVALID_FD) {
- fprintf(stderr, "create_local_thread could not accept.\n");
- closesocket(tmpsock);
- return -1;
- }
- closesocket(tmpsock);
- return 0;
-}
-
-static DWORD WINAPI local_thread(LPVOID lpvParam)
-{
- SOCKET sock;
- struct hostent *host;
- char hostname[64];
- struct sockaddr_in iserv_addr;
- unsigned long addr;
- int len;
- HANDLE thread;
-
- sock = socket(AF_INET, SOCK_STREAM, 0);
- memset(&iserv_addr, 0, sizeof(struct sockaddr_in));
- iserv_addr.sin_family = AF_INET;
- iserv_addr.sin_addr.s_addr = inet_addr(LOCALHOSTADDR);
- iserv_addr.sin_port = htons(local_portno);
- if(connect(sock, (struct sockaddr*)&iserv_addr, sizeof iserv_addr) ==
- SOCKET_ERROR) {
- fprintf(stderr, "local_thread thread could not connect\n");
- closesocket(sock);
- return 0;
- }
- setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
-
- /* read from 0 and write to sock */
- while (1) {
- if ((len = read(0, local_buf, LOCBUFSIZE)) <= 0) {
- closesocket(sock);
- close(0);
- return 0;
- }
- if (send(sock, local_buf, len, 0) != len ) {
- closesocket(sock);
- close(0);
- return 0;
- }
- }
- return 0;
-}
-
-/* Signal handler */
-
-static BOOL WINAPI signal_handler(DWORD ctrl)
-{
- switch (ctrl) {
- case CTRL_C_EVENT:
- case CTRL_BREAK_EVENT:
- break;
- case CTRL_LOGOFF_EVENT:
- if (!getenv("ERLSRV_SERVICE_NAME"))
- return FALSE;
- break;
- default:
- exit(1);
- }
- return TRUE;
-}
-
-#endif
diff --git a/lib/ssl/c_src/esock_osio.h b/lib/ssl/c_src/esock_osio.h
deleted file mode 100644
index 8742c3b05b..0000000000
--- a/lib/ssl/c_src/esock_osio.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2009. All Rights Reserved.
- *
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * %CopyrightEnd%
- */
-
-#ifndef ESOCK_OSIO_H
-#define ESOCK_OSIO_H
-
-extern FD local_read_fd;
-
-#ifdef __WIN32__
-int set_binary_mode(void);
-int esock_osio_init(void);
-void esock_osio_finish(void);
-#endif
-int set_break_handler(void);
-int read_ctrl(unsigned char **ebufp);
-int write_ctrl(unsigned char *buf, int len);
-
-#endif
diff --git a/lib/ssl/c_src/esock_poll.c b/lib/ssl/c_src/esock_poll.c
deleted file mode 100644
index e982eba881..0000000000
--- a/lib/ssl/c_src/esock_poll.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/*<copyright>
- * <year>2005-2008</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>
- */
-
-/*
- * Purpose: Hide poll() and select() behind an API so that we
- * can use either one.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef __WIN32__
-#include "esock_winsock.h"
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <time.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <errno.h>
-
-#ifdef __WIN32__
-#include <process.h>
-#else
-#include <unistd.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <sys/time.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#endif
-
-#include "esock.h"
-#include "esock_ssl.h"
-#include "esock_utils.h"
-#include "esock_poll.h"
-#include "debuglog.h"
-
-#if !defined(USE_SELECT)
-
-/* At least on FreeBSD, we need POLLRDNORM for normal files, not POLLIN. */
-/* Whether this is a bug in FreeBSD, I don't know. */
-#ifdef POLLRDNORM
-#define POLL_INPUT (POLLIN | POLLRDNORM)
-#else
-#define POLL_INPUT POLLIN
-#endif
-
-static void poll_fd_set(EsockPoll *ep, FD fd, short events)
-{
- int i, j;
- int prev_num_fds = ep->num_fds;
-
- if (ep->num_fds <= fd) {
- ep->num_fds = fd + 64;
- ep->fd_to_poll = (int *) esock_realloc(ep->fd_to_poll,
- ep->num_fds*sizeof(int));
- for (j = prev_num_fds; j < ep->num_fds; j++)
- ep->fd_to_poll[j] = -1;
- }
- i = ep->fd_to_poll[fd];
- if (i > 0 && i < ep->active && ep->fds[i].fd == fd) {
- /* Already present in poll array */
- ep->fds[i].events |= events;
- } else {
- /* Append to poll array */
- if (ep->active >= ep->allocated) {
- ep->allocated *= 2;
- ep->fds = (struct pollfd *)
- esock_realloc(ep->fds, ep->allocated*sizeof(struct pollfd));
- }
- ep->fd_to_poll[fd] = ep->active;
- ep->fds[ep->active].fd = fd;
- ep->fds[ep->active].events = events;
- ep->fds[ep->active].revents = 0;
- ep->active++;
- }
-}
-
-static int poll_is_set(EsockPoll *ep, FD fd, short mask)
-{
- if (fd >= ep->num_fds) {
- return 0;
- } else {
- int i = ep->fd_to_poll[fd];
- return 0 <= i && i < ep->active && ep->fds[i].fd == fd &&
- (ep->fds[i].revents & mask) != 0;
- }
-}
-
-#endif
-
-void esock_poll_init(EsockPoll *ep)
-{
-#ifdef USE_SELECT
- /* Nothing to do here */
-#else
- ep->allocated = 2;
- ep->fds = (struct pollfd *) esock_malloc(ep->allocated*sizeof(struct pollfd));
- ep->num_fds = 1;
- ep->fd_to_poll = esock_malloc(ep->num_fds*sizeof(int));
-#endif
-}
-
-void esock_poll_zero(EsockPoll *ep)
-{
-#ifdef USE_SELECT
- FD_ZERO(&ep->readmask);
- FD_ZERO(&ep->writemask);
- FD_ZERO(&ep->exceptmask);
-#else
- int i;
-
- for (i = 0; i < ep->num_fds; i++)
- ep->fd_to_poll[i] = -1;
- ep->active = 0;
-#endif
-}
-
-void esock_poll_fd_set_read(EsockPoll *ep, FD fd)
-{
-#ifdef USE_SELECT
- FD_SET(fd, &ep->readmask);
-#else
- poll_fd_set(ep, fd, POLL_INPUT);
-#endif
-}
-
-void esock_poll_fd_set_write(EsockPoll *ep, FD fd)
-{
-#ifdef USE_SELECT
- FD_SET(fd, &ep->writemask);
-#else
- poll_fd_set(ep, fd, POLLOUT);
-#endif
-}
-
-int esock_poll_fd_isset_read(EsockPoll *ep, FD fd)
-{
-#ifdef USE_SELECT
- return FD_ISSET(fd, &ep->readmask);
-#else
- return poll_is_set(ep, fd, (POLL_INPUT|POLLHUP|POLLERR|POLLNVAL));
-#endif
-}
-
-int esock_poll_fd_isset_write(EsockPoll *ep, FD fd)
-{
-#ifdef USE_SELECT
- return FD_ISSET(fd, &ep->writemask);
-#else
- return poll_is_set(ep, fd, (POLLOUT|POLLHUP|POLLERR|POLLNVAL));
-#endif
-}
-
-#ifdef __WIN32__
-void esock_poll_fd_set_exception(EsockPoll *ep, FD fd)
-{
- FD_SET(fd, &ep->exceptmask);
-}
-
-int esock_poll_fd_isset_exception(EsockPoll *ep, FD fd)
-{
- return FD_ISSET(fd, &ep->exceptmask);
-}
-#endif
-
-int esock_poll(EsockPoll *ep, int seconds)
-{
- int sret;
-
-#ifdef USE_SELECT
- struct timeval tv;
-
- tv.tv_sec = seconds;
- tv.tv_usec = 0;
- sret = select(FD_SETSIZE, &ep->readmask, &ep->writemask, &ep->exceptmask, &tv);
- if (sret == 0) {
- FD_ZERO(&ep->readmask);
- FD_ZERO(&ep->writemask);
- FD_ZERO(&ep->exceptmask);
- }
-#else
- sret = poll(ep->fds, ep->active, 1000*seconds);
-#endif
- return sret;
-}
-
-void esock_poll_clear_event(EsockPoll* ep, FD fd)
-{
-#ifdef USE_SELECT
- FD_CLR(fd, &ep->readmask);
- FD_CLR(fd, &ep->writemask);
- FD_CLR(fd, &ep->exceptmask);
-#else
- int i = ep->fd_to_poll[fd];
- if (i > 0 && ep->fds[i].fd == fd)
- ep->fds[i].revents = 0;
-#endif
-}
diff --git a/lib/ssl/c_src/esock_poll.h b/lib/ssl/c_src/esock_poll.h
deleted file mode 100644
index 639976dfa9..0000000000
--- a/lib/ssl/c_src/esock_poll.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*<copyright>
- * <year>2005-2008</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>
- */
-#ifndef ESOCK_POLL_SELECT_H
-#define ESOCK_POLL_SELECT_H
-
-#if !defined(USE_SELECT)
-#include <poll.h>
-#endif
-
-typedef struct esock_poll {
-#ifdef USE_SELECT
- fd_set readmask;
- fd_set writemask;
- fd_set exceptmask;
-#else
- int* fd_to_poll; /* Map from fd to index into poll
- * descriptor array.
- */
- int num_fds; /* Number of entries in fd_to_poll. */
- struct pollfd* fds; /* Array of poll descriptors. */
- int allocated; /* Allocated number of fds. */
- int active; /* Active number of fds */
-#endif
-} EsockPoll;
-
-void esock_poll_init(EsockPoll *ep);
-void esock_poll_zero(EsockPoll *ep);
-
-void esock_poll_fd_set_read(EsockPoll *ep, FD fd);
-void esock_poll_fd_set_write(EsockPoll *ep, FD fd);
-
-void esock_poll_clear_event(EsockPoll *ep, FD fd);
-
-int esock_poll_fd_isset_read(EsockPoll *ep, FD fd);
-int esock_poll_fd_isset_write(EsockPoll *ep, FD fd);
-
-#ifdef __WIN32__
-void esock_poll_fd_set_exception(EsockPoll *ep, FD fd);
-int esock_poll_fd_isset_exception(EsockPoll *ep, FD fd);
-#endif
-
-int esock_poll(EsockPoll *ep, int seconds);
-#endif
diff --git a/lib/ssl/c_src/esock_posix_str.c b/lib/ssl/c_src/esock_posix_str.c
deleted file mode 100644
index 31062baaaf..0000000000
--- a/lib/ssl/c_src/esock_posix_str.c
+++ /dev/null
@@ -1,642 +0,0 @@
-/*
- * %ExternalCopyright%
- */
-
-/*
- * Original: tclPosixStr.c --
- *
- * This file contains procedures that generate strings
- * corresponding to various POSIX-related codes, such
- * as errno and signals.
- *
- * Copyright (c) 1991-1994 The Regents of the University of California.
- * Copyright (c) 1994-1996 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * SCCS: @(#) tclPosixStr.c 1.32 96/10/10 10:09:42
- */
-
-/* Copy of erl_posix_str.c */
-
-#ifdef __WIN32__
-#include "esock_winsock.h"
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-#include "esock_posix_str.h"
-
-/*
- *----------------------------------------------------------------------
- *
- * esock_posix_str --
- *
- * Return a textual identifier for the given errno value.
- *
- * Results:
- * This procedure returns a machine-readable textual identifier
- * that corresponds to the current errno value (e.g. "eperm").
- * The identifier is the same as the #define name in errno.h,
- * except that it is in lowercase.
- *
- *----------------------------------------------------------------------
- */
-
-static char errstrbuf[32];
-
-char *esock_posix_str(int error)
-{
- switch (error) {
-#ifdef E2BIG
- case E2BIG: return "e2big";
-#endif
-#ifdef EACCES
- case EACCES: return "eacces";
-#endif
-#ifdef EADDRINUSE
- case EADDRINUSE: return "eaddrinuse";
-#endif
-#ifdef EADDRNOTAVAIL
- case EADDRNOTAVAIL: return "eaddrnotavail";
-#endif
-#ifdef EADV
- case EADV: return "eadv";
-#endif
-#ifdef EAFNOSUPPORT
- case EAFNOSUPPORT: return "eafnosupport";
-#endif
-#ifdef EAGAIN
- case EAGAIN: return "eagain";
-#endif
-#ifdef EALIGN
- case EALIGN: return "ealign";
-#endif
-#if defined(EALREADY) && (!defined(EBUSY) || (EALREADY != EBUSY ))
- case EALREADY: return "ealready";
-#endif
-#ifdef EBADE
- case EBADE: return "ebade";
-#endif
-#ifdef EBADF
- case EBADF: return "ebadf";
-#endif
-#ifdef EBADFD
- case EBADFD: return "ebadfd";
-#endif
-#ifdef EBADMSG
- case EBADMSG: return "ebadmsg";
-#endif
-#ifdef EBADR
- case EBADR: return "ebadr";
-#endif
-#ifdef EBADRPC
- case EBADRPC: return "ebadrpc";
-#endif
-#ifdef EBADRQC
- case EBADRQC: return "ebadrqc";
-#endif
-#ifdef EBADSLT
- case EBADSLT: return "ebadslt";
-#endif
-#ifdef EBFONT
- case EBFONT: return "ebfont";
-#endif
-#ifdef EBUSY
- case EBUSY: return "ebusy";
-#endif
-#ifdef ECHILD
- case ECHILD: return "echild";
-#endif
-#ifdef ECHRNG
- case ECHRNG: return "echrng";
-#endif
-#ifdef ECOMM
- case ECOMM: return "ecomm";
-#endif
-#ifdef ECONNABORTED
- case ECONNABORTED: return "econnaborted";
-#endif
-#ifdef ECONNREFUSED
- case ECONNREFUSED: return "econnrefused";
-#endif
-#ifdef ECONNRESET
- case ECONNRESET: return "econnreset";
-#endif
-#if defined(EDEADLK) && (!defined(EWOULDBLOCK) || (EDEADLK != EWOULDBLOCK))
- case EDEADLK: return "edeadlk";
-#endif
-#if defined(EDEADLOCK) && (!defined(EDEADLK) || (EDEADLOCK != EDEADLK))
- case EDEADLOCK: return "edeadlock";
-#endif
-#ifdef EDESTADDRREQ
- case EDESTADDRREQ: return "edestaddrreq";
-#endif
-#ifdef EDIRTY
- case EDIRTY: return "edirty";
-#endif
-#ifdef EDOM
- case EDOM: return "edom";
-#endif
-#ifdef EDOTDOT
- case EDOTDOT: return "edotdot";
-#endif
-#ifdef EDQUOT
- case EDQUOT: return "edquot";
-#endif
-#ifdef EDUPPKG
- case EDUPPKG: return "eduppkg";
-#endif
-#ifdef EEXIST
- case EEXIST: return "eexist";
-#endif
-#ifdef EFAULT
- case EFAULT: return "efault";
-#endif
-#ifdef EFBIG
- case EFBIG: return "efbig";
-#endif
-#ifdef EHOSTDOWN
- case EHOSTDOWN: return "ehostdown";
-#endif
-#ifdef EHOSTUNREACH
- case EHOSTUNREACH: return "ehostunreach";
-#endif
-#if defined(EIDRM) && (!defined(EINPROGRESS) || (EIDRM != EINPROGRESS))
- case EIDRM: return "eidrm";
-#endif
-#ifdef EINIT
- case EINIT: return "einit";
-#endif
-#ifdef EINPROGRESS
- case EINPROGRESS: return "einprogress";
-#endif
-#ifdef EINTR
- case EINTR: return "eintr";
-#endif
-#ifdef EINVAL
- case EINVAL: return "einval";
-#endif
-#ifdef EIO
- case EIO: return "eio";
-#endif
-#ifdef EISCONN
- case EISCONN: return "eisconn";
-#endif
-#ifdef EISDIR
- case EISDIR: return "eisdir";
-#endif
-#ifdef EISNAME
- case EISNAM: return "eisnam";
-#endif
-#ifdef ELBIN
- case ELBIN: return "elbin";
-#endif
-#ifdef EL2HLT
- case EL2HLT: return "el2hlt";
-#endif
-#ifdef EL2NSYNC
- case EL2NSYNC: return "el2nsync";
-#endif
-#ifdef EL3HLT
- case EL3HLT: return "el3hlt";
-#endif
-#ifdef EL3RST
- case EL3RST: return "el3rst";
-#endif
-#ifdef ELIBACC
- case ELIBACC: return "elibacc";
-#endif
-#ifdef ELIBBAD
- case ELIBBAD: return "elibbad";
-#endif
-#ifdef ELIBEXEC
- case ELIBEXEC: return "elibexec";
-#endif
-#ifdef ELIBMAX
- case ELIBMAX: return "elibmax";
-#endif
-#ifdef ELIBSCN
- case ELIBSCN: return "elibscn";
-#endif
-#ifdef ELNRNG
- case ELNRNG: return "elnrng";
-#endif
-#if defined(ELOOP) && (!defined(ENOENT) || (ELOOP != ENOENT))
- case ELOOP: return "eloop";
-#endif
-#ifdef EMFILE
- case EMFILE: return "emfile";
-#endif
-#ifdef EMLINK
- case EMLINK: return "emlink";
-#endif
-#ifdef EMSGSIZE
- case EMSGSIZE: return "emsgsize";
-#endif
-#ifdef EMULTIHOP
- case EMULTIHOP: return "emultihop";
-#endif
-#ifdef ENAMETOOLONG
- case ENAMETOOLONG: return "enametoolong";
-#endif
-#ifdef ENAVAIL
- case ENAVAIL: return "enavail";
-#endif
-#ifdef ENET
- case ENET: return "enet";
-#endif
-#ifdef ENETDOWN
- case ENETDOWN: return "enetdown";
-#endif
-#ifdef ENETRESET
- case ENETRESET: return "enetreset";
-#endif
-#ifdef ENETUNREACH
- case ENETUNREACH: return "enetunreach";
-#endif
-#ifdef ENFILE
- case ENFILE: return "enfile";
-#endif
-#ifdef ENOANO
- case ENOANO: return "enoano";
-#endif
-#if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR))
- case ENOBUFS: return "enobufs";
-#endif
-#ifdef ENOCSI
- case ENOCSI: return "enocsi";
-#endif
-#if defined(ENODATA) && (!defined(ECONNREFUSED) || (ENODATA != ECONNREFUSED))
- case ENODATA: return "enodata";
-#endif
-#ifdef ENODEV
- case ENODEV: return "enodev";
-#endif
-#ifdef ENOENT
- case ENOENT: return "enoent";
-#endif
-#ifdef ENOEXEC
- case ENOEXEC: return "enoexec";
-#endif
-#ifdef ENOLCK
- case ENOLCK: return "enolck";
-#endif
-#ifdef ENOLINK
- case ENOLINK: return "enolink";
-#endif
-#ifdef ENOMEM
- case ENOMEM: return "enomem";
-#endif
-#ifdef ENOMSG
- case ENOMSG: return "enomsg";
-#endif
-#ifdef ENONET
- case ENONET: return "enonet";
-#endif
-#ifdef ENOPKG
- case ENOPKG: return "enopkg";
-#endif
-#ifdef ENOPROTOOPT
- case ENOPROTOOPT: return "enoprotoopt";
-#endif
-#ifdef ENOSPC
- case ENOSPC: return "enospc";
-#endif
-#if defined(ENOSR) && (!defined(ENAMETOOLONG) || (ENAMETOOLONG != ENOSR))
- case ENOSR: return "enosr";
-#endif
-#if defined(ENOSTR) && (!defined(ENOTTY) || (ENOTTY != ENOSTR))
- case ENOSTR: return "enostr";
-#endif
-#ifdef ENOSYM
- case ENOSYM: return "enosym";
-#endif
-#ifdef ENOSYS
- case ENOSYS: return "enosys";
-#endif
-#ifdef ENOTBLK
- case ENOTBLK: return "enotblk";
-#endif
-#ifdef ENOTCONN
- case ENOTCONN: return "enotconn";
-#endif
-#ifdef ENOTDIR
- case ENOTDIR: return "enotdir";
-#endif
-#if defined(ENOTEMPTY) && (!defined(EEXIST) || (ENOTEMPTY != EEXIST))
- case ENOTEMPTY: return "enotempty";
-#endif
-#ifdef ENOTNAM
- case ENOTNAM: return "enotnam";
-#endif
-#ifdef ENOTSOCK
- case ENOTSOCK: return "enotsock";
-#endif
-#ifdef ENOTSUP
- case ENOTSUP: return "enotsup";
-#endif
-#ifdef ENOTTY
- case ENOTTY: return "enotty";
-#endif
-#ifdef ENOTUNIQ
- case ENOTUNIQ: return "enotuniq";
-#endif
-#ifdef ENXIO
- case ENXIO: return "enxio";
-#endif
-#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || EOPNOTSUPP != ENOTSUP)
- case EOPNOTSUPP: return "eopnotsupp";
-#endif
-#ifdef EPERM
- case EPERM: return "eperm";
-#endif
-#if defined(EPFNOSUPPORT) && (!defined(ENOLCK) || (ENOLCK != EPFNOSUPPORT))
- case EPFNOSUPPORT: return "epfnosupport";
-#endif
-#ifdef EPIPE
- case EPIPE: return "epipe";
-#endif
-#ifdef EPROCLIM
- case EPROCLIM: return "eproclim";
-#endif
-#ifdef EPROCUNAVAIL
- case EPROCUNAVAIL: return "eprocunavail";
-#endif
-#ifdef EPROGMISMATCH
- case EPROGMISMATCH: return "eprogmismatch";
-#endif
-#ifdef EPROGUNAVAIL
- case EPROGUNAVAIL: return "eprogunavail";
-#endif
-#ifdef EPROTO
- case EPROTO: return "eproto";
-#endif
-#ifdef EPROTONOSUPPORT
- case EPROTONOSUPPORT: return "eprotonosupport";
-#endif
-#ifdef EPROTOTYPE
- case EPROTOTYPE: return "eprototype";
-#endif
-#ifdef ERANGE
- case ERANGE: return "erange";
-#endif
-#if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED))
- case EREFUSED: return "erefused";
-#endif
-#ifdef EREMCHG
- case EREMCHG: return "eremchg";
-#endif
-#ifdef EREMDEV
- case EREMDEV: return "eremdev";
-#endif
-#ifdef EREMOTE
- case EREMOTE: return "eremote";
-#endif
-#ifdef EREMOTEIO
- case EREMOTEIO: return "eremoteio";
-#endif
-#ifdef EREMOTERELEASE
- case EREMOTERELEASE: return "eremoterelease";
-#endif
-#ifdef EROFS
- case EROFS: return "erofs";
-#endif
-#ifdef ERPCMISMATCH
- case ERPCMISMATCH: return "erpcmismatch";
-#endif
-#ifdef ERREMOTE
- case ERREMOTE: return "erremote";
-#endif
-#ifdef ESHUTDOWN
- case ESHUTDOWN: return "eshutdown";
-#endif
-#ifdef ESOCKTNOSUPPORT
- case ESOCKTNOSUPPORT: return "esocktnosupport";
-#endif
-#ifdef ESPIPE
- case ESPIPE: return "espipe";
-#endif
-#ifdef ESRCH
- case ESRCH: return "esrch";
-#endif
-#ifdef ESRMNT
- case ESRMNT: return "esrmnt";
-#endif
-#ifdef ESTALE
- case ESTALE: return "estale";
-#endif
-#ifdef ESUCCESS
- case ESUCCESS: return "esuccess";
-#endif
-#if defined(ETIME) && (!defined(ELOOP) || (ETIME != ELOOP))
- case ETIME: return "etime";
-#endif
-#if defined(ETIMEDOUT) && (!defined(ENOSTR) || (ETIMEDOUT != ENOSTR))
- case ETIMEDOUT: return "etimedout";
-#endif
-#ifdef ETOOMANYREFS
- case ETOOMANYREFS: return "etoomanyrefs";
-#endif
-#ifdef ETXTBSY
- case ETXTBSY: return "etxtbsy";
-#endif
-#ifdef EUCLEAN
- case EUCLEAN: return "euclean";
-#endif
-#ifdef EUNATCH
- case EUNATCH: return "eunatch";
-#endif
-#ifdef EUSERS
- case EUSERS: return "eusers";
-#endif
-#ifdef EVERSION
- case EVERSION: return "eversion";
-#endif
-#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
- case EWOULDBLOCK: return "ewouldblock";
-#endif
-#ifdef EXDEV
- case EXDEV: return "exdev";
-#endif
-#ifdef EXFULL
- case EXFULL: return "exfull";
-#endif
-#ifdef WSAEINTR
- case WSAEINTR: return "eintr";
-#endif
-#ifdef WSAEBADF
- case WSAEBADF: return "ebadf";
-#endif
-#ifdef WSAEACCES
- case WSAEACCES: return "eacces";
-#endif
-#ifdef WSAEFAULT
- case WSAEFAULT: return "efault";
-#endif
-#ifdef WSAEINVAL
- case WSAEINVAL: return "einval";
-#endif
-#ifdef WSAEMFILE
- case WSAEMFILE: return "emfile";
-#endif
-#ifdef WSAEWOULDBLOCK
- case WSAEWOULDBLOCK: return "ewouldblock";
-#endif
-#ifdef WSAEINPROGRESS
- case WSAEINPROGRESS: return "einprogress";
-#endif
-#ifdef WSAEALREADY
- case WSAEALREADY: return "ealready";
-#endif
-#ifdef WSAENOTSOCK
- case WSAENOTSOCK: return "enotsock";
-#endif
-#ifdef WSAEDESTADDRREQ
- case WSAEDESTADDRREQ: return "edestaddrreq";
-#endif
-#ifdef WSAEMSGSIZE
- case WSAEMSGSIZE: return "emsgsize";
-#endif
-#ifdef WSAEPROTOTYPE
- case WSAEPROTOTYPE: return "eprototype";
-#endif
-#ifdef WSAENOPROTOOPT
- case WSAENOPROTOOPT: return "enoprotoopt";
-#endif
-#ifdef WSAEPROTONOSUPPORT
- case WSAEPROTONOSUPPORT: return "eprotonosupport";
-#endif
-#ifdef WSAESOCKTNOSUPPORT
- case WSAESOCKTNOSUPPORT: return "esocktnosupport";
-#endif
-#ifdef WSAEOPNOTSUPP
- case WSAEOPNOTSUPP: return "eopnotsupp";
-#endif
-#ifdef WSAEPFNOSUPPORT
- case WSAEPFNOSUPPORT: return "epfnosupport";
-#endif
-#ifdef WSAEAFNOSUPPORT
- case WSAEAFNOSUPPORT: return "eafnosupport";
-#endif
-#ifdef WSAEADDRINUSE
- case WSAEADDRINUSE: return "eaddrinuse";
-#endif
-#ifdef WSAEADDRNOTAVAIL
- case WSAEADDRNOTAVAIL: return "eaddrnotavail";
-#endif
-#ifdef WSAENETDOWN
- case WSAENETDOWN: return "enetdown";
-#endif
-#ifdef WSAENETUNREACH
- case WSAENETUNREACH: return "enetunreach";
-#endif
-#ifdef WSAENETRESET
- case WSAENETRESET: return "enetreset";
-#endif
-#ifdef WSAECONNABORTED
- case WSAECONNABORTED: return "econnaborted";
-#endif
-#ifdef WSAECONNRESET
- case WSAECONNRESET: return "econnreset";
-#endif
-#ifdef WSAENOBUFS
- case WSAENOBUFS: return "enobufs";
-#endif
-#ifdef WSAEISCONN
- case WSAEISCONN: return "eisconn";
-#endif
-#ifdef WSAENOTCONN
- case WSAENOTCONN: return "enotconn";
-#endif
-#ifdef WSAESHUTDOWN
- case WSAESHUTDOWN: return "eshutdown";
-#endif
-#ifdef WSAETOOMANYREFS
- case WSAETOOMANYREFS: return "etoomanyrefs";
-#endif
-#ifdef WSAETIMEDOUT
- case WSAETIMEDOUT: return "etimedout";
-#endif
-#ifdef WSAECONNREFUSED
- case WSAECONNREFUSED: return "econnrefused";
-#endif
-#ifdef WSAELOOP
- case WSAELOOP: return "eloop";
-#endif
-#ifdef WSAENAMETOOLONG
- case WSAENAMETOOLONG: return "enametoolong";
-#endif
-#ifdef WSAEHOSTDOWN
- case WSAEHOSTDOWN: return "ehostdown";
-#endif
-#ifdef WSAEHOSTUNREACH
- case WSAEHOSTUNREACH: return "ehostunreach";
-#endif
-#ifdef WSAENOTEMPTY
- case WSAENOTEMPTY: return "enotempty";
-#endif
-#ifdef WSAEPROCLIM
- case WSAEPROCLIM: return "eproclim";
-#endif
-#ifdef WSAEUSERS
- case WSAEUSERS: return "eusers";
-#endif
-#ifdef WSAEDQUOT
- case WSAEDQUOT: return "edquot";
-#endif
-#ifdef WSAESTALE
- case WSAESTALE: return "estale";
-#endif
-#ifdef WSAEREMOTE
- case WSAEREMOTE: return "eremote";
-#endif
-#ifdef WSASYSNOTREADY
- case WSASYSNOTREADY: return "sysnotready";
-#endif
-#ifdef WSAVERNOTSUPPORTED
- case WSAVERNOTSUPPORTED: return "vernotsupported";
-#endif
-#ifdef WSANOTINITIALISED
- case WSANOTINITIALISED: return "notinitialised";
-#endif
-#ifdef WSAEDISCON
- case WSAEDISCON: return "ediscon";
-#endif
-#ifdef WSAENOMORE
- case WSAENOMORE: return "enomore";
-#endif
-#ifdef WSAECANCELLED
- case WSAECANCELLED: return "ecancelled";
-#endif
-#ifdef WSAEINVALIDPROCTABLE
- case WSAEINVALIDPROCTABLE: return "einvalidproctable";
-#endif
-#ifdef WSAEINVALIDPROVIDER
- case WSAEINVALIDPROVIDER: return "einvalidprovider";
-#endif
-#ifdef WSAEPROVIDERFAILEDINIT
- case WSAEPROVIDERFAILEDINIT: return "eproviderfailedinit";
-#endif
-#ifdef WSASYSCALLFAILURE
- case WSASYSCALLFAILURE: return "syscallfailure";
-#endif
-#ifdef WSASERVICE_NOT_FOUND
- case WSASERVICE_NOT_FOUND: return "service_not_found";
-#endif
-#ifdef WSATYPE_NOT_FOUND
- case WSATYPE_NOT_FOUND: return "type_not_found";
-#endif
-#ifdef WSA_E_NO_MORE
- case WSA_E_NO_MORE: return "e_no_more";
-#endif
-#ifdef WSA_E_CANCELLED
- case WSA_E_CANCELLED: return "e_cancelled";
-#endif
- default:
- sprintf(errstrbuf, "unknown:%d", error);
- return errstrbuf;
- }
-}
-
diff --git a/lib/ssl/c_src/esock_posix_str.h b/lib/ssl/c_src/esock_posix_str.h
deleted file mode 100644
index 53916c888a..0000000000
--- a/lib/ssl/c_src/esock_posix_str.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2009. All Rights Reserved.
- *
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * %CopyrightEnd%
- */
-
-/* esock_posix_str.h */
-
-#ifndef ESOCK_POSIX_STR_H
-#define ESOCK_POSIX_STR_H
-
-char *esock_posix_str(int error);
-
-#endif
-
diff --git a/lib/ssl/c_src/esock_ssl.h b/lib/ssl/c_src/esock_ssl.h
deleted file mode 100644
index 535e9a6491..0000000000
--- a/lib/ssl/c_src/esock_ssl.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*<copyright>
- * <year>1999-2008</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>
- */
-/*
- * Purpose: Header file for adaptions to various SSL packages.
- */
-
-#ifndef ESOCK_SSL_H
-#define ESOCK_SSL_H
-
-#include <sys/types.h>
-#include <stdio.h>
-#include "esock.h"
-
-typedef struct {
- const char *compile_version;/* version of OpenSSL when compiling esock */
- const char *lib_version; /* version of OpenSSL in library */
-} esock_version;
-
-/* Variables to be set by certain functions (see below) */
-char *esock_ssl_errstr;
-
-/* Ephemeral RSA and DH */
-int ephemeral_rsa, ephemeral_dh;
-
-/* Protocol version (sslv2, sslv3, tlsv1) */
-int protocol_version;
-
-/* version info */
-esock_version *esock_ssl_version(void);
-
-/* ciphers info */
-char *esock_ssl_ciphers(void);
-
-/* seeding */
-void esock_ssl_seed(void *buf, int len);
-
-/* Initialization and finalization of SSL */
-
-int esock_ssl_init(void);
-void esock_ssl_finish(void);
-
-/* Freeing of SSL resources for a connection */
-
-void esock_ssl_free(Connection *cp);
-
-/* Print error diagnostics to a file pointer */
-
-void esock_ssl_print_errors_fp(FILE *fp);
-
-/* All functions below have to return >= 0 on success, and < 0 on
- * failure.
- *
- * If the return indicates a failure (return value < 0) and the failure
- * is temporary the error context (sock_errno()/sock_set_errno()) must
- * be set to ERRNO_BLOCK.
- *
- * If the failure is permanent, the error context must be set to something
- * else than ERRNO_BLOCK, and `esock_ssl_errstr' must be set to point to
- * short diagnostic string describing the error.
- */
-
-int esock_ssl_accept_init(Connection *cp, void *listenssl);
-int esock_ssl_connect_init(Connection *cp);
-int esock_ssl_listen_init(Connection *cp);
-
-/* All functions below may involve non-blocking I/O with a temporary
- * failure. Hence they have to have the error context set to
- * ERRNO_BLOCK, or else have esock_ssl_errstr set to point to a
- * diagnostic string, in case the return value is < 0. If the return
- * value is 0, cp->eof and cp->bp are set, if appropritate.
- */
-
-int esock_ssl_accept(Connection *cp);
-int esock_ssl_connect(Connection *cp);
-
-int esock_ssl_read(Connection *cp, char *buf, int len);
-int esock_ssl_write(Connection *cp, char *buf, int len);
-
-int esock_ssl_shutdown(Connection *cp);
-
-/* Peer certificate */
-
-int esock_ssl_getpeercert(Connection *cp, unsigned char **buf);
-int esock_ssl_getpeercertchain(Connection *cp, unsigned char **buf);
-
-/* Sessions */
-int esock_ssl_session_reused(Connection *cp);
-
-/* Protocol version and cipher of established connection */
-int esock_ssl_getprotocol_version(Connection *cp, char **buf);
-int esock_ssl_getcipher(Connection *cp, char **buf);
-
-#endif
diff --git a/lib/ssl/c_src/esock_utils.c b/lib/ssl/c_src/esock_utils.c
deleted file mode 100644
index 0098a4f5f6..0000000000
--- a/lib/ssl/c_src/esock_utils.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2009. All Rights Reserved.
- *
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * %CopyrightEnd%
- */
-
-/*
- * Purpose: Safe memory allocation and other utilities.
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "esock_utils.h"
-
-static char *strtok_quote(char *s1, const char *s2);
-
-
-void *esock_malloc(size_t size)
-{
- void *p;
-
- p = malloc(size);
- if (!p) {
- fprintf(stderr, "esock_malloc: cannot alloc %d bytes\n", size);
- exit(EXIT_FAILURE);
- }
- return p;
-}
-
-void *esock_realloc(void *p, size_t size)
-{
- void *np;
-
- np = realloc(p, size);
- if (!np) {
- fprintf(stderr, "esock_realloc: cannot realloc %d bytes\n", size);
- exit(EXIT_FAILURE);
- }
- return np;
-}
-
-void esock_free(void *p)
-{
- free(p);
-}
-
-/* Builds an argv array from cmd. Spaces and tabs within double quotes
- * are not considered delimiters. Double quotes are removed.
- *
- * The return value is argc, and the pointer to char ** is set. argc
- * is non-negative, argv[0], ..., argv[argc - 1] are pointers to
- * strings, and argv[argc] == NULL. All argv[0], ..., argv[argc - 1]
- * must be freed by the user, and also the argv pointer itself.
- *
- * Example: cmd = abc"/program files/"olle nisse, results in
- * argv[0] = abc/program files/olle, argv[1] = nisse, argc = 2.
- *
- */
-int esock_build_argv(char *cmd, char ***argvp)
-{
- int argvsize = 10, argc = 0;
- char *args, *tokp, *argp;
- char **argv;
-
- argv = esock_malloc(argvsize * sizeof(char *));
- args = esock_malloc(strlen(cmd) + 1);
- strcpy(args, cmd);
- tokp = strtok_quote(args, " \t");
- while (tokp != NULL) {
- if (argc + 1 >= argvsize) {
- argvsize += 10;
- argv = esock_realloc(argv, argvsize * sizeof(char *));
- }
- argp = esock_malloc(strlen(tokp) + 1);
- strcpy(argp, tokp);
- argv[argc++] = argp;
- tokp = strtok_quote(NULL, " \t");
- }
- esock_free(args);
- argv[argc] = NULL;
- *argvp = argv;
- return argc;
-}
-
-/* strtok_quote
- * Works as strtok, but characters within pairs of double quotes are not
- * considered as delimiters. Quotes are removed.
- */
-static char *strtok_quote(char *s1, const char *s2)
-{
- static char *last;
- char *s, *t, *u;
-
- s = (s1) ? s1 : last;
- if (!s)
- return last = NULL;
-
- while (*s != '"' && *s != '\0' && strchr(s2, *s))
- s++;
- t = s;
-
- while (1) {
- if (*t == '"') {
- t++;
- while (*t != '"' && *t != '\0')
- t++;
- if (*t == '\0') {
- last = NULL;
- goto end;
- }
- t++;
- }
- while(*t != '"' && *t != '\0' && !strchr(s2, *t))
- t++;
- if (*t == '\0') {
- last = NULL;
- goto end;
- } else if (*t != '"') {
- *t = '\0';
- last = t + 1;
- goto end;
- }
- }
-end:
- /* Remove quotes */
- u = t = s;
- while (*u) {
- if (*u == '"')
- u++;
- else
- *t++ = *u++;
- }
- *t = '\0';
- return s;
-}
-
diff --git a/lib/ssl/c_src/esock_utils.h b/lib/ssl/c_src/esock_utils.h
deleted file mode 100644
index 99ed6c23e3..0000000000
--- a/lib/ssl/c_src/esock_utils.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2009. All Rights Reserved.
- *
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * %CopyrightEnd%
- */
-
-#ifndef ESOCK_UTILS_H
-#define ESOCK_UTILS_H
-
-#include <stdlib.h>
-
-void *esock_malloc(size_t size);
-void *esock_realloc(void *p, size_t size);
-void esock_free(void *p);
-int esock_build_argv(char *cmd, char ***argvp);
-
-#endif
-
-
diff --git a/lib/ssl/c_src/esock_winsock.h b/lib/ssl/c_src/esock_winsock.h
deleted file mode 100644
index 069782a18d..0000000000
--- a/lib/ssl/c_src/esock_winsock.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*<copyright>
- * <year>2003-2008</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>
- */
-/*
- * Purpose: Control winsock version and setting of FD_SETSIZE.
- *
- */
-
-/* Maybe set FD_SETSIZE */
-
-#ifdef ESOCK_WINSOCK2
-#include <winsock2.h>
-#else
-#include <winsock.h>
-/* These are defined in winsock2.h but not in winsock.h */
-#define SD_RECEIVE 0x00
-#define SD_SEND 0x01
-#define SD_BOTH 0x02
-#endif
-
diff --git a/lib/ssl/doc/src/Makefile b/lib/ssl/doc/src/Makefile
index 3119d37af0..5d808d6727 100644
--- a/lib/ssl/doc/src/Makefile
+++ b/lib/ssl/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2010. All Rights Reserved.
+# Copyright Ericsson AB 1999-2011. All Rights Reserved.
#
# The 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 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# Target Specs
# ----------------------------------------------------
XML_APPLICATION_FILES = refman.xml
-XML_REF3_FILES = ssl.xml old_ssl.xml ssl_session_cache_api.xml
+XML_REF3_FILES = ssl.xml ssl_session_cache_api.xml
XML_REF6_FILES = ssl_app.xml
XML_PART_FILES = release_notes.xml usersguide.xml
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index 52ee9c086a..5df2632149 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.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>
@@ -28,59 +28,99 @@
<rev>G</rev>
<file>notes.xml</file>
</header>
- <p>This document describes the changes made to the SSL application.
- </p>
+ <p>This document describes the changes made to the SSL application.</p>
+
+ <section><title>SSL 4.1.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ replace "a ssl" with "an ssl" reindent
+ pkix_path_validation/3 Trivial documentation fixes
+ (Thanks to Christian von Roques )</p>
+ <p>
+ Own Id: OTP-9464</p>
+ </item>
+ </list>
+ </section>
- <section><title>SSL 4.1.4</title>
<section><title>Improvements and New Features</title>
<list>
<item>
<p>
- Reduced memory footprint of an ssl connection.</p>
+ Adds function clause to avoid denial of service attack.
+ Thanks to Vinod for reporting this vulnerability.</p>
<p>
- Handshake hashes, premaster secret and "public_key_info"
- does not need to be saved when the connection has been
- established. The own certificate is no longer duplicated
- in the state.</p>
- <p>
- Own Id: OTP-9021</p>
+ Own Id: OTP-9364</p>
</item>
<item>
<p>
- Add the option {hibernate_after, int()} to ssl:connect
- and ssl:listen</p>
+ Error handling code now takes care of inet:getopts/2 and
+ inets:setopts/2 crashes. Thanks to Richard Jones for
+ reporting this.</p>
<p>
- Own Id: OTP-9106</p>
+ Own Id: OTP-9382</p>
</item>
- </list>
- </section>
-
-</section>
-
-<section><title>SSL 4.1.3</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
<item>
<p>
- Fixed error in cache-handling fix from ssl-4.1.2</p>
+ Support explicit use of packet option httph and httph_bin</p>
<p>
- Own Id: OTP-9018 Aux Id: seq11739 </p>
+ Own Id: OTP-9461</p>
</item>
<item>
<p>
- Verification of a critical extended_key_usage-extension
- corrected</p>
+ Decoding of hello extensions could fail to come to the
+ correct conclusion due to an error in a binary match
+ pattern. Thanks to Ben Murphy.</p>
<p>
- Own Id: OTP-9029 Aux Id: seq11541 </p>
+ Own Id: OTP-9589</p>
</item>
</list>
</section>
</section>
-<section><title>SSL 4.1.2</title>
+<section>
+ <title>SSL 4.1.5</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Calling gen_tcp:connect with option {ip, {127,0,0,1}} results in
+ an exit with reason badarg. Neither SSL nor INETS This was not
+ catched, resulting in crashes with incomprehensible reasons.</p>
+ <p>Own Id: OTP-9289 Aux Id: seq11845</p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+ <section>
+ <title>SSL 4.1.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed error in cache-handling fix from ssl-4.1.2</p>
+ <p>
+ Own Id: OTP-9018 Aux Id: seq11739 </p>
+ </item>
+ <item>
+ <p>Verification of a critical extended_key_usage-extension
+ corrected</p>
+ <p>Own Id: OTP-9029 Aux Id: seq11541 </p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+ <section>
+ <title>SSL 4.1.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
@@ -566,7 +606,7 @@
Own Id: OTP-8224</p>
</item>
<item>
- <p>A ssl:ssl_accept/3 could crash a connection if the
+ <p>An ssl:ssl_accept/3 could crash a connection if the
timing was wrong.</p> <p>Removed info message if the
socket closed without a proper disconnect from the ssl
layer. </p> <p>ssl:send/2 is now blocking until the
@@ -782,7 +822,7 @@
<item>
<p>
The new ssl implementation released as a alfa in this
- version supports upgrading of a tcp connection to a ssl
+ version supports upgrading of a tcp connection to an ssl
connection so that http client and servers may implement
RFC 2817.</p>
<p>
@@ -801,7 +841,7 @@
very crippled as the control of the ssl-socket was deep
down in openssl making it hard if not impossible to
support all inet options, ipv6 and upgrade of a tcp
- connection to a ssl connection. The alfa version has a
+ connection to an ssl connection. The alfa version has a
few limitations that will be removed before the ssl-4.0
release. Main differences and limitations in the alfa are
listed below.</p>
diff --git a/lib/ssl/doc/src/old_ssl.xml b/lib/ssl/doc/src/old_ssl.xml
deleted file mode 100644
index 0d2e1afdbd..0000000000
--- a/lib/ssl/doc/src/old_ssl.xml
+++ /dev/null
@@ -1,709 +0,0 @@
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1999</year><year>2010</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- The contents of this file are subject to the Erlang Public License,
- Version 1.1, (the "License"); you may not use this file except in
- compliance with the License. You should have received a copy of the
- Erlang Public License along with this software. If not, it can be
- retrieved online at http://www.erlang.org/.
-
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- the License for the specific language governing rights and limitations
- under the License.
-
- </legalnotice>
-
- <title>ssl</title>
- <prepared>Peter H&ouml;gfeldt</prepared>
- <responsible>Peter H&ouml;gfeldt</responsible>
- <docno></docno>
- <approved>Peter H&ouml;gfeldt</approved>
- <checked></checked>
- <date>2003-03-25</date>
- <rev>D</rev>
- <file>old_ssl.xml</file>
- </header>
- <module>old_ssl</module>
- <modulesummary>Interface Functions for Secure Socket Layer</modulesummary>
- <description>
- <p>This module contains interface functions to the Secure Socket Layer.</p>
- </description>
-
- <section>
- <title>General</title>
-
- <p>This manual page describes functions that are defined
- in the ssl module and represents the old ssl implementation
- that coexists with the new one until it has been
- totally phased out. </p>
-
- <p>The old implementation can be
- accessed by providing the option {ssl_imp, old} to the
- ssl:connect and ssl:listen functions.</p>
-
- <p>The reader is advised to also read the <c>ssl(6)</c> manual page
- describing the SSL application.
- </p>
- <warning>
- <p>It is strongly advised to seed the random generator after
- the ssl application has been started (see <c>seed/1</c>
- below), and before any connections are established. Although
- the port program interfacing to the ssl libraries does a
- "random" seeding of its own in order to make everything work
- properly, that seeding is by no means random for the world
- since it has a constant value which is known to everyone
- reading the source code of the port program.</p>
- </warning>
- </section>
-
- <section>
- <title>Common data types</title>
- <p>The following datatypes are used in the functions below:
- </p>
- <list type="bulleted">
- <item>
- <p><c>options() = [option()]</c></p>
- </item>
- <item>
- <p><c>option() = socketoption() | ssloption()</c></p>
- </item>
- <item>
- <p><c>socketoption() = {mode, list} | {mode, binary} | binary | {packet, packettype()} | {header, integer()} | {nodelay, boolean()} | {active, activetype()} | {backlog, integer()} | {ip, ipaddress()} | {port, integer()}</c></p>
- </item>
- <item>
- <p><c>ssloption() = {verify, code()} | {depth, depth()} | {certfile, path()} | {keyfile, path()} | {password, string()} | {cacertfile, path()} | {ciphers, string()}</c></p>
- </item>
- <item>
- <p><c>packettype()</c> (see inet(3))</p>
- </item>
- <item>
- <p><c>activetype()</c> (see inet(3))</p>
- </item>
- <item>
- <p><c>reason() = atom() | {atom(), string()}</c></p>
- </item>
- <item>
- <p><c>bytes() = [byte()]</c></p>
- </item>
- <item>
- <p><c>string() = [byte()]</c></p>
- </item>
- <item>
- <p><c>byte() = 0 | 1 | 2 | ... | 255</c></p>
- </item>
- <item>
- <p><c>code() = 0 | 1 | 2</c></p>
- </item>
- <item>
- <p><c>depth() = byte()</c></p>
- </item>
- <item>
- <p><c>address() = hostname() | ipstring() | ipaddress()</c></p>
- </item>
- <item>
- <p><c>ipaddress() = ipstring() | iptuple()</c></p>
- </item>
- <item>
- <p><c>hostname() = string()</c></p>
- </item>
- <item>
- <p><c>ipstring() = string()</c></p>
- </item>
- <item>
- <p><c>iptuple() = {byte(), byte(), byte(), byte()}</c></p>
- </item>
- <item>
- <p><c>sslsocket()</c></p>
- </item>
- <item>
- <p><c>protocol() = sslv2 | sslv3 | tlsv1</c></p>
- </item>
- <item>
- <p><c></c></p>
- </item>
- </list>
- <p>The socket option <c>{backlog, integer()}</c> is for
- <c>listen/2</c> only, and the option <c>{port, integer()}</c>
- is for <c>connect/3/4</c> only.
- </p>
- <p>The following socket options are set by default: <c>{mode, list}</c>, <c>{packet, 0}</c>, <c>{header, 0}</c>, <c>{nodelay, false}</c>, <c>{active, true}</c>, <c>{backlog, 5}</c>,
- <c>{ip, {0,0,0,0}}</c>, and <c>{port, 0}</c>.
- </p>
- <p>Note that the options <c>{mode, binary}</c> and <c>binary</c>
- are equivalent. Similarly <c>{mode, list}</c> and the absence of
- option <c>binary</c> are equivalent.
- </p>
- <p>The ssl options are for setting specific SSL parameters as follows:
- </p>
- <list type="bulleted">
- <item>
- <p><c>{verify, code()}</c> Specifies type of verification:
- 0 = do not verify peer; 1 = verify peer, 2 = verify peer,
- fail if no peer certificate. The default value is 0.
- </p>
- </item>
- <item>
- <p><c>{depth, depth()}</c> 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.
- </p>
- <p>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.
- </p>
- <p>The default value is 1.
- </p>
- </item>
- <item>
- <p><c>{certfile, path()}</c> Path to a file containing the
- user's certificate.
- chain of PEM encoded certificates.</p>
- </item>
- <item>
- <p><c>{keyfile, path()}</c> Path to file containing user's
- private PEM encoded key.</p>
- </item>
- <item>
- <p><c>{password, string()}</c> String containing the user's
- password. Only used if the private keyfile is password protected.</p>
- </item>
- <item>
- <p><c>{cacertfile, path()}</c> Path to file containing PEM encoded
- CA certificates (trusted certificates used for verifying a peer
- certificate).</p>
- </item>
- <item>
- <p><c>{ciphers, string()}</c> String of ciphers as a colon
- separated list of ciphers. The function <c>ciphers/0</c> can
- be used to find all available ciphers.</p>
- </item>
- </list>
- <p>The type <c>sslsocket()</c> is opaque to the user.
- </p>
- <p>The owner of a socket is the one that created it by a call to
- <c>transport_accept/[1,2]</c>, <c>connect/[3,4]</c>,
- or <c>listen/2</c>.
- </p>
- <p>When a socket is in active mode (the default), data from the
- socket is delivered to the owner of the socket in the form of
- messages:
- </p>
- <list type="bulleted">
- <item>
- <p><c>{ssl, Socket, Data}</c></p>
- </item>
- <item>
- <p><c>{ssl_closed, Socket}</c></p>
- </item>
- <item>
- <p><c>{ssl_error, Socket, Reason}</c></p>
- </item>
- </list>
- <p>A <c>Timeout</c> argument specifies a timeout in milliseconds. The
- default value for a <c>Timeout</c> argument is <c>infinity</c>.
- </p>
- <p>Functions listed below may return the value <c>{error, closed}</c>, which only indicates that the SSL socket is
- considered closed for the operation in question. It is for
- instance possible to have <c>{error, closed}</c> returned from
- an call to <c>send/2</c>, and a subsequent call to <c>recv/3</c>
- returning <c>{ok, Data}</c>.
- </p>
- <p>Hence a return value of <c>{error, closed}</c> must not be
- interpreted as if the socket was completely closed. On the
- contrary, in order to free all resources occupied by an SSL
- socket, <c>close/1</c> must be called, or else the process owning
- the socket has to terminate.
- </p>
- <p>For each SSL socket there is an Erlang process representing the
- socket. When a socket is opened, that process links to the
- calling client process. Implementations that want to detect
- abnormal exits from the socket process by receiving <c>{'EXIT', Pid, Reason}</c> messages, should use the function <c>pid/1</c>
- to retrieve the process identifier from the socket, in order to
- be able to match exit messages properly.</p>
- </section>
- <funcs>
- <func>
- <name>ciphers() -> {ok, string()} | {error, enotstarted}</name>
- <fsummary>Get supported ciphers.</fsummary>
- <desc>
- <p>Returns a string consisting of colon separated cipher
- designations that are supported by the current SSL library
- implementation.
- </p>
- <p>The SSL application has to be started to return the string
- of ciphers.</p>
- </desc>
- </func>
- <func>
- <name>close(Socket) -> ok | {error, Reason}</name>
- <fsummary>Close a socket returned by <c>transport_accept/[1,2]</c>, <c>connect/3/4</c>, or <c>listen/2</c>.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- </type>
- <desc>
- <p>Closes a socket returned by <c>transport_accept/[1,2]</c>,
- <c>connect/[3,4]</c>, or <c>listen/2</c></p>
- </desc>
- </func>
- <func>
- <name>connect(Address, Port, Options) -> {ok, Socket} | {error, Reason}</name>
- <name>connect(Address, Port, Options, Timeout) -> {ok, Socket} | {error, Reason}</name>
- <fsummary>Connect to <c>Port</c>at <c>Address</c>.</fsummary>
- <type>
- <v>Address = address()</v>
- <v>Port = integer()</v>
- <v>Options = [connect_option()]</v>
- <v>connect_option() = {mode, list} | {mode, binary} | binary | {packet, packettype()} | {header, integer()} | {nodelay, boolean()} | {active, activetype()} | {ip, ipaddress()} | {port, integer()} | {verify, code()} | {depth, depth()} | {certfile, path()} | {keyfile, path()} | {password, string()} | {cacertfile, path()} | {ciphers, string()}</v>
- <v>Timeout = integer()</v>
- <v>Socket = sslsocket()</v>
- </type>
- <desc>
- <p>Connects to <c>Port</c> at <c>Address</c>. If the optional
- <c>Timeout</c> argument is specified, and a connection could not
- be established within the given time, <c>{error, timeout}</c> is
- returned. The default value for <c>Timeout</c> is <c>infinity</c>.
- </p>
- <p>The <c>ip</c> and <c>port</c> options are for binding to a
- particular <em>local</em> address and port, respectively.</p>
- </desc>
- </func>
- <func>
- <name>connection_info(Socket) -> {ok, {Protocol, Cipher}} | {error, Reason}</name>
- <fsummary>Get current protocol version and cipher.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>Protocol = protocol()</v>
- <v>Cipher = string()</v>
- </type>
- <desc>
- <p>Gets the chosen protocol version and cipher for an established
- connection (accepted och connected). </p>
- </desc>
- </func>
- <func>
- <name>controlling_process(Socket, NewOwner) -> ok | {error, Reason}</name>
- <fsummary>Assign a new controlling process to the socket.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>NewOwner = pid()</v>
- </type>
- <desc>
- <p>Assigns a new controlling process to <c>Socket</c>. A controlling
- process is the owner of a socket, and receives all messages from
- the socket.</p>
- </desc>
- </func>
- <func>
- <name>format_error(ErrorCode) -> string()</name>
- <fsummary>Return an error string.</fsummary>
- <type>
- <v>ErrorCode = term()</v>
- </type>
- <desc>
- <p>Returns a diagnostic string describing an error.</p>
- </desc>
- </func>
- <func>
- <name>getopts(Socket, OptionsTags) -> {ok, Options} | {error, Reason}</name>
- <fsummary>Get options set for socket</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>OptionTags = [optiontag()]()</v>
- </type>
- <desc>
- <p>Returns the options the tags of which are <c>OptionTags</c> for
- for the socket <c>Socket</c>. </p>
- </desc>
- </func>
- <func>
- <name>listen(Port, Options) -> {ok, ListenSocket} | {error, Reason}</name>
- <fsummary>Set up a socket to listen on a port on the local host.</fsummary>
- <type>
- <v>Port = integer()</v>
- <v>Options = [listen_option()]</v>
- <v>listen_option() = {mode, list} | {mode, binary} | binary | {packet, packettype()} | {header, integer()} | {active, activetype()} | {backlog, integer()} | {ip, ipaddress()} | {verify, code()} | {depth, depth()} | {certfile, path()} | {keyfile, path()} | {password, string()} | {cacertfile, path()} | {ciphers, string()}</v>
- <v>ListenSocket = sslsocket()</v>
- </type>
- <desc>
- <p>Sets up a socket to listen on port <c>Port</c> at the local host.
- If <c>Port</c> is zero, <c>listen/2</c> picks an available port
- number (use <c>port/1</c> to retrieve it).
- </p>
- <p>The listen queue size defaults to 5. If a different value is
- wanted, the option <c>{backlog, Size}</c> should be added to the
- list of options.
- </p>
- <p>An empty <c>Options</c> list is considered an error, and
- <c>{error, enooptions}</c> is returned.
- </p>
- <p>The returned <c>ListenSocket</c> can only be used in calls to
- <c>transport_accept/[1,2]</c>.</p>
- </desc>
- </func>
- <func>
- <name>peercert(Socket) -> {ok, Cert} | {error, Reason}</name>
- <fsummary>Return the peer certificate.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>Cert = binary()()</v>
- <v>Subject = term()()</v>
- </type>
- <desc>
- <p>Returns the DER encoded peer certificate, the certificate can be decoded with
- <c>public_key:pkix_decode_cert/2</c>.
- </p>
- </desc>
- </func>
- <func>
- <name>peername(Socket) -> {ok, {Address, Port}} | {error, Reason}</name>
- <fsummary>Return peer address and port.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>Address = ipaddress()</v>
- <v>Port = integer()</v>
- </type>
- <desc>
- <p>Returns the address and port number of the peer.</p>
- </desc>
- </func>
- <func>
- <name>pid(Socket) -> pid()</name>
- <fsummary>Return the pid of the socket process.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- </type>
- <desc>
- <p>Returns the pid of the socket process. The returned pid should
- only be used for receiving exit messages.</p>
- </desc>
- </func>
- <func>
- <name>recv(Socket, Length) -> {ok, Data} | {error, Reason}</name>
- <name>recv(Socket, Length, Timeout) -> {ok, Data} | {error, Reason}</name>
- <fsummary>Receive data on socket.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>Length = integer() >= 0</v>
- <v>Timeout = integer()</v>
- <v>Data = bytes() | binary()</v>
- </type>
- <desc>
- <p>Receives data on socket <c>Socket</c> when the socket is in
- passive mode, i.e. when the option <c>{active, false}</c>
- has been specified.
- </p>
- <p>A notable return value is <c>{error, closed}</c> which
- indicates that the socket is closed.
- </p>
- <p>A positive value of the <c>Length</c> argument is only
- valid when the socket is in raw mode (option <c>{packet, 0}</c> is set, and the option <c>binary</c> is <em>not</em>
- set); otherwise it should be set to 0, whence all available
- bytes are returned.
- </p>
- <p>If the optional <c>Timeout</c> parameter is specified, and
- no data was available within the given time, <c>{error, timeout}</c> is returned. The default value for
- <c>Timeout</c> is <c>infinity</c>.</p>
- </desc>
- </func>
- <func>
- <name>seed(Data) -> ok | {error, Reason}</name>
- <fsummary>Seed the ssl random generator.</fsummary>
- <type>
- <v>Data = iolist() | binary()</v>
- </type>
- <desc>
- <p>Seeds the ssl random generator.
- </p>
- <p>It is strongly advised to seed the random generator after
- the ssl application has been started, and before any
- connections are established. Although the port program
- interfacing to the OpenSSL libraries does a "random" seeding
- of its own in order to make everything work properly, that
- seeding is by no means random for the world since it has a
- constant value which is known to everyone reading the source
- code of the seeding.
- </p>
- <p>A notable return value is <c>{error, edata}}</c> indicating that
- <c>Data</c> was not a binary nor an iolist.</p>
- </desc>
- </func>
- <func>
- <name>send(Socket, Data) -> ok | {error, Reason}</name>
- <fsummary>Write data to a socket.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>Data = iolist() | binary()</v>
- </type>
- <desc>
- <p>Writes <c>Data</c> to <c>Socket</c>. </p>
- <p>A notable return value is <c>{error, closed}</c> indicating that
- the socket is closed.</p>
- </desc>
- </func>
- <func>
- <name>setopts(Socket, Options) -> ok | {error, Reason}</name>
- <fsummary>Set socket options.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>Options = [socketoption]()</v>
- </type>
- <desc>
- <p>Sets options according to <c>Options</c> for the socket
- <c>Socket</c>. </p>
- </desc>
- </func>
- <func>
- <name>ssl_accept(Socket) -> ok | {error, Reason}</name>
- <name>ssl_accept(Socket, Timeout) -> ok | {error, Reason}</name>
- <fsummary>Perform server-side SSL handshake and key exchange</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>Timeout = integer()</v>
- <v>Reason = atom()</v>
- </type>
- <desc>
- <p>The <c>ssl_accept</c> function establish the SSL connection
- on the server side. It should be called directly after
- <c>transport_accept</c>, in the spawned server-loop.</p>
- <p>Note that the ssl connection is not complete until <c>ssl_accept</c>
- has returned <c>true</c>, and if an error is returned, the socket
- is unavailable and for instance <c>close/1</c> will crash.</p>
- </desc>
- </func>
- <func>
- <name>sockname(Socket) -> {ok, {Address, Port}} | {error, Reason}</name>
- <fsummary>Return the local address and port.</fsummary>
- <type>
- <v>Socket = sslsocket()</v>
- <v>Address = ipaddress()</v>
- <v>Port = integer()</v>
- </type>
- <desc>
- <p>Returns the local address and port number of the socket
- <c>Socket</c>.</p>
- </desc>
- </func>
- <func>
- <name>transport_accept(Socket) -> {ok, NewSocket} | {error, Reason}</name>
- <name>transport_accept(Socket, Timeout) -> {ok, NewSocket} | {error, Reason}</name>
- <fsummary>Accept an incoming connection and prepare for <c>ssl_accept</c></fsummary>
- <type>
- <v>Socket = NewSocket = sslsocket()</v>
- <v>Timeout = integer()</v>
- <v>Reason = atom()</v>
- </type>
- <desc>
- <p>Accepts an incoming connection request on a listen socket.
- <c>ListenSocket</c> must be a socket returned from <c>listen/2</c>.
- The socket returned should be passed to <c>ssl_accept</c> to
- complete ssl handshaking and establishing the connection.</p>
- <warning>
- <p>The socket returned can only be used with <c>ssl_accept</c>,
- no traffic can be sent or received before that call.</p>
- </warning>
- <p>The accepted socket inherits the options set for <c>ListenSocket</c>
- in <c>listen/2</c>.</p>
- <p>The default value for <c>Timeout</c> is <c>infinity</c>. If
- <c>Timeout</c> is specified, and no connection is accepted within
- the given time, <c>{error, timeout}</c> is returned.</p>
- </desc>
- </func>
- <func>
- <name>version() -> {ok, {SSLVsn, CompVsn, LibVsn}}</name>
- <fsummary>Return the version of SSL.</fsummary>
- <type>
- <v>SSLVsn = CompVsn = LibVsn = string()()</v>
- </type>
- <desc>
- <p>Returns the SSL application version (<c>SSLVsn</c>), the library
- version used when compiling the SSL application port program
- (<c>CompVsn</c>), and the actual library version used when
- dynamically linking in runtime (<c>LibVsn</c>).
- </p>
- <p>If the SSL application has not been started, <c>CompVsn</c> and
- <c>LibVsn</c> are empty strings.
- </p>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>ERRORS</title>
- <p>The possible error reasons and the corresponding diagnostic strings
- returned by <c>format_error/1</c> are either the same as those defined
- in the <c>inet(3)</c> reference manual, or as follows:
- </p>
- <taglist>
- <tag><c>closed</c></tag>
- <item>
- <p>Connection closed for the operation in question.
- </p>
- </item>
- <tag><c>ebadsocket</c></tag>
- <item>
- <p>Connection not found (internal error).
- </p>
- </item>
- <tag><c>ebadstate</c></tag>
- <item>
- <p>Connection not in connect state (internal error).
- </p>
- </item>
- <tag><c>ebrokertype</c></tag>
- <item>
- <p>Wrong broker type (internal error).
- </p>
- </item>
- <tag><c>ecacertfile</c></tag>
- <item>
- <p>Own CA certificate file is invalid.
- </p>
- </item>
- <tag><c>ecertfile</c></tag>
- <item>
- <p>Own certificate file is invalid.
- </p>
- </item>
- <tag><c>echaintoolong</c></tag>
- <item>
- <p>The chain of certificates provided by peer is too long.
- </p>
- </item>
- <tag><c>ecipher</c></tag>
- <item>
- <p>Own list of specified ciphers is invalid.
- </p>
- </item>
- <tag><c>ekeyfile</c></tag>
- <item>
- <p>Own private key file is invalid.
- </p>
- </item>
- <tag><c>ekeymismatch</c></tag>
- <item>
- <p>Own private key does not match own certificate.
- </p>
- </item>
- <tag><c>enoissuercert</c></tag>
- <item>
- <p>Cannot find certificate of issuer of certificate provided
- by peer.
- </p>
- </item>
- <tag><c>enoservercert</c></tag>
- <item>
- <p>Attempt to do accept without having set own certificate.
- </p>
- </item>
- <tag><c>enotlistener</c></tag>
- <item>
- <p>Attempt to accept on a non-listening socket.
- </p>
- </item>
- <tag><c>enoproxysocket</c></tag>
- <item>
- <p>No proxy socket found (internal error).
- </p>
- </item>
- <tag><c>enooptions</c></tag>
- <item>
- <p>The list of options is empty.
- </p>
- </item>
- <tag><c>enotstarted</c></tag>
- <item>
- <p>The SSL application has not been started.
- </p>
- </item>
- <tag><c>eoptions</c></tag>
- <item>
- <p>Invalid list of options.
- </p>
- </item>
- <tag><c>epeercert</c></tag>
- <item>
- <p>Certificate provided by peer is in error.
- </p>
- </item>
- <tag><c>epeercertexpired</c></tag>
- <item>
- <p>Certificate provided by peer has expired.
- </p>
- </item>
- <tag><c>epeercertinvalid</c></tag>
- <item>
- <p>Certificate provided by peer is invalid.
- </p>
- </item>
- <tag><c>eselfsignedcert</c></tag>
- <item>
- <p>Certificate provided by peer is self signed.
- </p>
- </item>
- <tag><c>esslaccept</c></tag>
- <item>
- <p>Server SSL handshake procedure between client and server failed.
- </p>
- </item>
- <tag><c>esslconnect</c></tag>
- <item>
- <p>Client SSL handshake procedure between client and server failed.
- </p>
- </item>
- <tag><c>esslerrssl</c></tag>
- <item>
- <p>SSL protocol failure. Typically because of a fatal alert
- from peer.
- </p>
- </item>
- <tag><c>ewantconnect</c></tag>
- <item>
- <p>Protocol wants to connect, which is not supported in
- this version of the SSL application.
- </p>
- </item>
- <tag><c>ex509lookup</c></tag>
- <item>
- <p>Protocol wants X.509 lookup, which is not supported in
- this version of the SSL application.
- </p>
- </item>
- <tag><c>{badcall, Call}</c></tag>
- <item>
- <p>Call not recognized for current mode (active or passive) and
- state of socket.
- </p>
- </item>
- <tag><c>{badcast, Cast}</c></tag>
- <item>
- <p>Call not recognized for current mode (active or passive) and
- state of socket.
- </p>
- </item>
- <tag><c>{badinfo, Info}</c></tag>
- <item>
- <p>Call not recognized for current mode (active or passive) and
- state of socket.
- </p>
- </item>
- </taglist>
- </section>
-
- <section>
- <title>SEE ALSO</title>
- <p>gen_tcp(3), inet(3) public_key(3) </p>
- </section>
-
-</erlref>
-
-
diff --git a/lib/ssl/doc/src/refman.xml b/lib/ssl/doc/src/refman.xml
index 68f84660f3..011819e82b 100644
--- a/lib/ssl/doc/src/refman.xml
+++ b/lib/ssl/doc/src/refman.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE application SYSTEM "application.dtd">
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>1999</year><year>2010</year>
+ <year>1999</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -45,7 +45,6 @@
</description>
<xi:include href="ssl_app.xml"/>
<xi:include href="ssl.xml"/>
- <xi:include href="old_ssl.xml"/>
<xi:include href="ssl_session_cache_api.xml"/>
</application>
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index cd5c9281cd..70122e4393 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -35,7 +35,7 @@
<title>SSL</title>
<list type="bulleted">
- <item>ssl requires the crypto an public_key applications.</item>
+ <item>ssl requires the crypto and public_key applications.</item>
<item>Supported SSL/TLS-versions are SSL-3.0 and TLS-1.0 </item>
<item>For security reasons sslv2 is not supported.</item>
<item>Ephemeral Diffie-Hellman cipher suites are supported
@@ -53,13 +53,11 @@
<p>The following data types are used in the functions below:
</p>
- <p><c>boolean() = true | false</c></p>
-
- <p><c>property() = atom()</c></p>
-
+ <p><c>boolean() = true | false</c></p>
+
<p><c>option() = socketoption() | ssloption() | transportoption()</c></p>
- <p><c>socketoption() = [{property(), term()}] - defaults to
+ <p><c>socketoption() = proplists:property() - The default socket options are
[{mode,list},{packet, 0},{header, 0},{active, true}].
</c></p>
@@ -123,8 +121,6 @@
<p> <c>hash() = md5 | sha
</c></p>
- <p><c>ssl_imp() = new | old - default is new.</c></p>
-
</section>
<section>
@@ -179,9 +175,9 @@
by the peer also.
</item>
- <tag>{ssl_imp, ssl_imp()}</tag>
- <item>Specify which ssl implementation you want to use. Defaults to
- new.
+ <tag>{ssl_imp, new | old}</tag>
+ <item>No longer has any meaning as the old implementation has
+ been removed, it will be ignored.
</item>
<tag>{secure_renegotiate, boolean()}</tag>
@@ -218,7 +214,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
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
+ application. Note that 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:cert_records">the public_key User's
@@ -266,7 +262,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<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>
+<p> {bad_cert, cert_expired}, {bad_cert, invalid_issuer}, {bad_cert, invalid_signature}, {bad_cert, unknown_ca},{bad_cert, selfsigned_peer}, {bad_cert, name_not_permitted}, {bad_cert, missing_basic_constraint}, {bad_cert, invalid_key_usage}</p>
</item>
<tag>{hibernate_after, integer()|undefined}</tag>
@@ -328,10 +324,10 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
</item>
<tag>{fail_if_no_peer_cert, boolean()}</tag>
- <item>Used together with {verify, verify_peer} by a ssl server.
+ <item>Used together with {verify, verify_peer} by an 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
+ false it will only fail if the client sends an invalid
certificate (an empty certificate is considered valid).
</item>
@@ -345,10 +341,10 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
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.
+ only meaningful if <c>reuse_sessions</c> is set to true.
SuggestedSessionId is a binary(), PeerCert is a DER encoded
certificate, Compression is an enumeration integer
- and CipherSuite of type ciphersuite().
+ and CipherSuite is of type ciphersuite().
</item>
</taglist>
@@ -357,7 +353,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<section>
<title>General</title>
- <p>When a ssl socket is in active mode (the default), data from the
+ <p>When an ssl socket is in active mode (the default), data from the
socket is delivered to the owner of the socket in the form of
messages:
</p>
@@ -398,7 +394,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<name>connect(Socket, SslOptions, Timeout) -> {ok, SslSocket}
| {error, Reason}</name>
<fsummary> Upgrades a gen_tcp, or
- equivalent, connected socket to a ssl socket. </fsummary>
+ equivalent, connected socket to an ssl socket. </fsummary>
<type>
<v>Socket = socket()</v>
<v>SslOptions = [ssloption()]</v>
@@ -407,7 +403,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<v>Reason = term()</v>
</type>
<desc> <p>Upgrades a gen_tcp, or equivalent,
- connected socket to a ssl socket i.e. performs the
+ connected socket to an ssl socket i.e. performs the
client-side ssl handshake.</p>
</desc>
</func>
@@ -430,12 +426,12 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<func>
<name>close(SslSocket) -> ok | {error, Reason}</name>
- <fsummary>Close a ssl connection</fsummary>
+ <fsummary>Close an ssl connection</fsummary>
<type>
<v>SslSocket = sslsocket()</v>
<v>Reason = term()</v>
</type>
- <desc><p>Close a ssl connection.</p>
+ <desc><p>Close an ssl connection.</p>
</desc>
</func>
@@ -452,7 +448,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<v>Reason = term()</v>
</type>
<desc><p>Assigns a new controlling process to the ssl-socket. A
- controlling process is the owner of a ssl-socket, and receives
+ controlling process is the owner of an ssl-socket, and receives
all messages from the socket.</p>
</desc>
</func>
@@ -482,17 +478,15 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
</func>
<func>
- <name>getopts(Socket) -> </name>
<name>getopts(Socket, OptionNames) ->
{ok, [socketoption()]} | {error, Reason}</name>
<fsummary>Get the value of the specified options.</fsummary>
<type>
<v>Socket = sslsocket()</v>
- <v>OptionNames = [property()]</v>
+ <v>OptionNames = [atom()]</v>
</type>
<desc>
- <p>Get the value of the specified socket options, if no
- options are specified all options are returned.
+ <p>Get the value of the specified socket options.
</p>
</desc>
</func>
@@ -500,14 +494,14 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<func>
<name>listen(Port, Options) ->
{ok, ListenSocket} | {error, Reason}</name>
- <fsummary>Creates a ssl listen socket.</fsummary>
+ <fsummary>Creates an ssl listen socket.</fsummary>
<type>
<v>Port = integer()</v>
<v>Options = options()</v>
<v>ListenSocket = sslsocket()</v>
</type>
<desc>
- <p>Creates a ssl listen socket.</p>
+ <p>Creates an ssl listen socket.</p>
</desc>
</func>
@@ -583,7 +577,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<fsummary>Write data to a socket.</fsummary>
<type>
<v>Socket = sslsocket()</v>
- <v>Data = iolist() | binary()</v>
+ <v>Data = iodata()</v>
</type>
<desc>
<p>Writes <c>Data</c> to <c>Socket</c>. </p>
@@ -591,6 +585,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
the socket is closed.</p>
</desc>
</func>
+
<func>
<name>setopts(Socket, Options) -> ok | {error, Reason}</name>
<fsummary>Set socket options.</fsummary>
@@ -650,12 +645,12 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
</type>
<desc>
<p> Upgrades a gen_tcp, or
- equivalent, socket to a ssl socket i.e. performs the
+ equivalent, socket to an ssl socket i.e. performs the
ssl server-side handshake.</p>
- <p><warning>Note that the listen socket should be in {active, false} mode
+ <warning><p>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.</warning></p>
+ or may not succeed depending on timing.</p></warning>
</desc>
</func>
diff --git a/lib/ssl/doc/src/ssl_distribution.xml b/lib/ssl/doc/src/ssl_distribution.xml
index 7bcc12eb5f..4ae4ead3ee 100644
--- a/lib/ssl/doc/src/ssl_distribution.xml
+++ b/lib/ssl/doc/src/ssl_distribution.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2010</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,36 +33,32 @@
</header>
<p>This chapter describes how the Erlang distribution can use
SSL to get additional verification and security.
-
- <note><p>Note this
- documentation is written for the old ssl implementation and
- will be updated for the new one once this functionality is
- supported by the new implementation.</p></note>
</p>
<section>
<title>Introduction</title>
<p>The Erlang distribution can in theory use almost any connection
based protocol as bearer. A module that implements the protocol
- specific parts of connection setup is however needed. The
+ specific parts of the connection setup is however needed. The
default distribution module is <c>inet_tcp_dist</c> which is
included in the Kernel application. When starting an
Erlang node distributed, <c>net_kernel</c> uses this module to
setup listen ports and connections. </p>
- <p>In the SSL application there is an additional distribution
- module, <c>inet_ssl_dist</c> which can be used as an
+
+ <p>In the SSL application there is an additional distribution
+ module, <c>inet_tls_dist</c> which can be used as an
alternative. All distribution connections will be using SSL and
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 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
- differentiate between two different Erlang networks.</p>
+
+ <p>The security level depends on the parameters provided to the
+ SSL connection setup. Erlang node cookies are however always
+ used, as they can be used to differentiate between two different
+ Erlang networks.</p>
<p>Setting up Erlang distribution over SSL involves some simple but
necessary steps:</p>
- <list type="bulleted">
+
+ <list type="bulleted">
<item>Building boot scripts including the SSL application</item>
<item>Specifying the distribution module for net_kernel</item>
<item>Specifying security options and other SSL options</item>
@@ -77,122 +73,135 @@
SASL application. Refer to the SASL documentations
for more information on systools. This is only an example of
what can be done.</p>
- <p>The simplest boot script possible includes only the Kernel
+
+ <p>The simplest boot script possible includes only the Kernel
and STDLIB applications. Such a script is located in the
Erlang distributions bin directory. The source for the script
can be found under the Erlang installation top directory under
- <c><![CDATA[releases/<OTP version>start_clean.rel]]></c>. Copy that
+ <c><![CDATA[releases/<OTP version>/start_clean.rel]]></c>. Copy that
script to another location (and preferably another name)
- and add the SSL application with its current version number
+ and add the applications crypto, public_key and SSL with their current version numbers
after the STDLIB application.</p>
<p>An example .rel file with SSL added may look like this:</p>
+
<code type="none">
-{release, {"OTP APN 181 01","P7A"}, {erts, "5.0"},
- [{kernel,"2.5"},
- {stdlib,"1.8.1"},
- {ssl,"2.2.1"}]}. </code>
- <p>Note that the version numbers surely will differ in your system.
- Whenever one of the applications included in the script is
- upgraded, the script has to be changed.</p>
- <p>Assuming the above .rel file is stored in a file
- <c>start_ssl.rel</c> in the current directory, a boot script
- can be built like this:</p>
- <code type="none">
-1> systools:make_script("start_ssl",[]). </code>
- <p>There will now be a file <c>start_ssl.boot</c> in the current
- directory. To test the boot script, start Erlang with the
- <c>-boot</c> command line parameter specifying this boot script
- (with its full path but without the <c>.boot</c> suffix), in
- Unix it could look like this:</p>
- <p></p>
- <code type="none"><![CDATA[
+ {release, {"OTP APN 181 01","R15A"}, {erts, "5.9"},
+ [{kernel,"2.15"},
+ {stdlib,"1.18"},
+ {crypto, "2.0.3"},
+ {public_key, "0.12"},
+ {ssl, "5.0"}
+ ]}.
+ </code>
+
+ <p>Note that the version numbers surely will differ in your system.
+ Whenever one of the applications included in the script is
+ upgraded, the script has to be changed.</p>
+ <p>Assuming the above .rel file is stored in a file
+ <c>start_ssl.rel</c> in the current directory, a boot script
+ can be built like this:</p>
+
+ <code type="none">
+ 1> systools:make_script("start_ssl",[]). </code>
+
+ <p>There will now be a file <c>start_ssl.boot</c> in the current
+ directory. To test the boot script, start Erlang with the
+ <c>-boot</c> command line parameter specifying this boot script
+ (with its full path but without the <c>.boot</c> suffix), in
+ Unix it could look like this:</p>
+ <p></p>
+
+ <code type="none"><![CDATA[
$ erl -boot /home/me/ssl/start_ssl
Erlang (BEAM) emulator version 5.0
Eshell V5.0 (abort with ^G)
-1> whereis(ssl_server).
-<0.32.0> ]]></code>
+1> whereis(ssl_manager).
+<0.41.0> ]]></code>
<p>The <c>whereis</c> function call verifies that the SSL
application is really started.</p>
- <p>As an alternative to building a bootscript, one can explicitly
- add the path to the ssl <c>ebin</c> directory on the command
+
+ <p>As an alternative to building a bootscript, one can explicitly
+ add the path to the SSL <c>ebin</c> directory on the command
line. This is done with the command line option <c>-pa</c>. This
- works as the ssl application really need not be started for the
- distribution to come up, a primitive version of the ssl server
- is started by the distribution module itself, so as long as the
- primitive code server can reach the code, the distribution will
+ works as the SSL application does not need to be started for the
+ distribution to come up, as a clone of the SSL application is
+ hooked into the kernel application, so as long as the
+ SSL applications code can be reached, the distribution will
start. The <c>-pa</c> method is only recommended for testing
purposes.</p>
+
+ <note><p>Note that the clone of the SSL application is necessary to
+ enable the use of the SSL code in such an early bootstage as
+ needed to setup the distribution, however this will make it
+ impossible to soft upgrade the SSL application.</p></note>
</section>
<section>
<title>Specifying distribution module for net_kernel</title>
- <p>The distribution module for SSL is named <c>inet_ssl_dist</c>
- and is specified on the command line whit the <c>-proto_dist</c>
+ <p>The distribution module for SSL is named <c>inet_tls_dist</c>
+ and is specified on the command line with the <c>-proto_dist</c>
option. The argument to <c>-proto_dist</c> should be the module
name without the <c>_dist</c> suffix, so this distribution
- module is specified with <c>-proto_dist inet_ssl</c> on the
+ module is specified with <c>-proto_dist inet_tls</c> on the
command line.</p>
<p></p>
+
<p>Extending the command line from above gives us the following:</p>
<code type="none">
-$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_ssl </code>
- <p>For the distribution to actually be started, we need to give
- the emulator a name as well:</p>
+$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls </code>
+
+<p>For the distribution to actually be started, we need to give
+the emulator a name as well:</p>
<code type="none">
-$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_ssl -sname ssl_test
+$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls -sname ssl_test
Erlang (BEAM) emulator version 5.0 [source]
Eshell V5.0 (abort with ^G)
(ssl_test@myhost)1> </code>
<p>Note however that a node started in this way will refuse to talk
- to other nodes, as no certificates or key files are supplied
+ to other nodes, as no ssl parameters are supplied
(see below).</p>
- <p>When the SSL distribution starts, the OTP system is in its
- early boot stage, why neither <c>application</c> nor <c>code</c>
- are usable. As SSL needs to start a port program in this early
- stage, it tries to determine the path to that program from the
- primitive code loaders code path. If this fails, one need to
- specify the directory where the port program resides. This can
- be done either with an environment variable
- <c>ERL_SSL_PORTPROGRAM_DIR</c> or with the command line option
- <c>-ssl_portprogram_dir</c>. The value should be the directory
- where the <c>ssl_esock</c> port program is located. Note that
- this option is never needed in a normal Erlang installation.</p>
</section>
<section>
- <title>Specifying security options and other SSL options</title>
- <p>For SSL to work, you either need certificate files or a
- key file. Certificate files can be specified both when working as
- client and as server (connecting or accepting). </p>
- <p></p>
+ <title>Specifying SSL options</title> <p>For SSL to work, at least
+ a public key and certificate needs to be specified for the server
+ side. In the following example the PEM-files consists of two
+ entries the servers certificate and its private key.</p>
+
<p>On the <c>erl</c> command line one can specify options that the
- ssl distribution will add when creation a socket. It is
- mandatory to specify at least a key file or client and server
- certificates. One can specify any <em>SSL option</em> on the
- command line, but must not specify any socket options (like
- packet size and such). The SSL options are listed in the
- Reference Manual. The only difference between the
- options in the reference manual and the ones that can be
- specified to the distribution on the command line is that
- <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_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
- SSL options/option values. The <c>-ssl_dist_opt</c> argument can
- be repeated any number of times.</p>
- <p>An example command line would now look something like this
+ SSL distribution will add when creating a socket.</p>
+
+ <p>One can specify the simpler SSL options certfile, keyfile,
+ password, cacertfile, verify, reuse_sessions,
+ secure_renegotiate, depth, hibernate_after and ciphers (use old
+ string format) by adding the prefix server_ or client_ to the
+ option name. The server can also take the options dhfile and
+ fail_if_no_peer_cert (also prefixed).
+ <c>client_</c>-prfixed options are used when the distribution initiates a
+ connection to another node and the <c>server_</c>-prefixed options are used
+ when accepting a connection from a remote node. </p>
+
+ <p> More complex options such as verify_fun are not available at
+ the moment but a mechanism to handle such options may be added in
+ a future release. </p>
+
+ <p> Raw socket options such as packet and size must not be specified on
+ the command line</p>.
+
+ <p>The command line argument for specifying the SSL options is named
+ <c>-ssl_dist_opt</c> and should be followed by pairs of
+ SSL options and their values. The <c>-ssl_dist_opt</c> argument can
+ be repeated any number of times.</p>
+
+ <p>An example command line would now look something like this
(line breaks in the command are for readability,
they should not be there when typed):</p>
<code type="none">
-$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_ssl
- -ssl_dist_opt client_certfile "/home/me/ssl/erlclient.pem"
+$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls
-ssl_dist_opt server_certfile "/home/me/ssl/erlserver.pem"
- -ssl_dist_opt verify 1 depth 1
+ -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true
-sname ssl_test
Erlang (BEAM) emulator version 5.0 [source]
@@ -211,12 +220,11 @@ Eshell V5.0 (abort with ^G)
subsequent invocations of Erlang.</p>
<p></p>
<p>In a Unix (Bourne) shell it could look like this (line breaks for
- readability):</p>
+ readability, they should not be there when typed):</p>
<code type="none">
-$ ERL_FLAGS="-boot \\"/home/me/ssl/start_ssl\\" -proto_dist inet_ssl
- -ssl_dist_opt client_certfile \\"/home/me/ssl/erlclient.pem\\"
- -ssl_dist_opt server_certfile \\"/home/me/ssl/erlserver.pem\\"
- -ssl_dist_opt verify 1 -ssl_dist_opt depth 1"
+$ ERL_FLAGS="-boot /home/me/ssl/start_ssl -proto_dist inet_tls
+ -ssl_dist_opt server_certfile /home/me/ssl/erlserver.pem
+ -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true"
$ export ERL_FLAGS
$ erl -sname ssl_test
Erlang (BEAM) emulator version 5.0 [source]
@@ -227,15 +235,12 @@ Eshell V5.0 (abort with ^G)
{progname,["erl "]},
{sname,["ssl_test"]},
{boot,["/home/me/ssl/start_ssl"]},
- {proto_dist,["inet_ssl"]},
- {ssl_dist_opt,["client_certfile","/home/me/ssl/erlclient.pem"]},
+ {proto_dist,["inet_tls"]},
{ssl_dist_opt,["server_certfile","/home/me/ssl/erlserver.pem"]},
- {ssl_dist_opt,["verify","1"]},
- {ssl_dist_opt,["depth","1"]},
+ {ssl_dist_opt,["server_secure_renegotiate","true",
+ "client_secure_renegotiate","true"]
{home,["/home/me"]}] </code>
<p>The <c>init:get_arguments()</c> call verifies that the correct
arguments are supplied to the emulator. </p>
</section>
</chapter>
-
-
diff --git a/lib/ssl/doc/src/ssl_protocol.xml b/lib/ssl/doc/src/ssl_protocol.xml
index 6936408881..17268a634d 100644
--- a/lib/ssl/doc/src/ssl_protocol.xml
+++ b/lib/ssl/doc/src/ssl_protocol.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2010</year>
+ <year>2003</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -25,18 +25,18 @@
<file>ssl_protocol.xml</file>
</header>
- <p>The erlang ssl application currently supports SSL 3.0 and TLS 1.0
+ <p>The erlang SSL application currently supports SSL 3.0 and TLS 1.0
RFC 2246, and will in the future also support later versions of TLS.
SSL 2.0 is not supported.
</p>
- <p>By default erlang ssl is run over the TCP/IP protocol even
- though you could plug in an other reliable transport protocol
+ <p>By default erlang SSL is run over the TCP/IP protocol even
+ though you could plug in any other reliable transport protocol
with the same API as gen_tcp.</p>
<p>If a client and server wants to use an upgrade mechanism, such as
- defined by RFC2817, to upgrade a regular TCP/IP connection to a ssl
- connection the erlang ssl API supports this. This can be useful for
+ defined by RFC2817, to upgrade a regular TCP/IP connection to an SSL
+ connection the erlang SSL API supports this. This can be useful for
things such as supporting HTTP and HTTPS on the same port and
implementing virtual hosting.
</p>
@@ -131,7 +131,7 @@
connections. Sessions are used to avoid the expensive negotiation
of new security parameters for each connection."</p>
- <p>Session data is by default kept by the ssl application in a
+ <p>Session data is by default kept by the SSL application in a
memory storage hence session data will be lost at application
restart or takeover. Users may define their own callback module
to handle session data storage if persistent data storage is
@@ -140,8 +140,8 @@
possible to configure the amount of time the session data should be
saved.</p>
- <p>Ssl clients will by default try to reuse an available session,
- ssl servers will by default agree to reuse sessions when clients
+ <p>SSL clients will by default try to reuse an available session,
+ SSL servers will by default agree to reuse sessions when clients
ask to do so.</p>
</section>
diff --git a/lib/ssl/doc/src/using_ssl.xml b/lib/ssl/doc/src/using_ssl.xml
index 605290b6f9..ab837a156a 100644
--- a/lib/ssl/doc/src/using_ssl.xml
+++ b/lib/ssl/doc/src/using_ssl.xml
@@ -56,7 +56,7 @@
<code type="erl">1 server> ssl:start().
ok</code>
- <p>Create a ssl listen socket</p>
+ <p>Create an ssl listen socket</p>
<code type="erl">2 server> {ok, ListenSocket} =
ssl:listen(9999, [{certfile, "cert.pem"}, {keyfile, "key.pem"},{reuseaddr, true}]).
{ok,{sslsocket, [...]}}</code>
@@ -90,7 +90,7 @@ ok</code>
<section>
<title>Upgrade example</title>
- <note><p> To upgrade a TCP/IP connection to a ssl connection the
+ <note><p> To upgrade a TCP/IP connection to an ssl connection the
client and server have to aggre to do so. Agreement
may be accompliced by using a protocol such the one used by HTTP
specified in RFC 2817.</p> </note>
@@ -114,7 +114,7 @@ ok</code>
<code type="erl">2 client> {ok, Socket} = gen_tcp:connect("localhost", 9999, [], infinity).</code>
<p>Make sure active is set to false before trying
- to upgrade a connection to a ssl connection, otherwhise
+ to upgrade a connection to an ssl connection, otherwhise
ssl handshake messages may be deliverd to the wrong process.</p>
<code type="erl">4 server> inet:setopts(Socket, [{active, false}]).
ok</code>
@@ -124,7 +124,7 @@ ok</code>
{certfile, "cert.pem"}, {keyfile, "key.pem"}]).
{ok,{sslsocket,[...]}}</code>
- <p> Upgrade to a ssl connection. Note that the client and server
+ <p> Upgrade to an ssl connection. Note that the client and server
must agree upon the upgrade and the server must call
ssl:accept/2 before the client calls ssl:connect/3.</p>
<code type="erl">3 client>{ok, SSLSocket} = ssl:connect(Socket, [{cacertfile, "cacerts.pem"},
diff --git a/lib/ssl/examples/certs/Makefile b/lib/ssl/examples/certs/Makefile
index b811b461dc..a4f067ade6 100644
--- a/lib/ssl/examples/certs/Makefile
+++ b/lib/ssl/examples/certs/Makefile
@@ -57,5 +57,5 @@ release_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)/examples/certs
tar cf - etc | \
(cd $(RELSYSDIR)/examples/certs; tar xf -)
- chmod -f -R ug+rw $(RELSYSDIR)/examples
+ chmod -R ug+rw $(RELSYSDIR)/examples
release_docs_spec:
diff --git a/lib/ssl/examples/src/Makefile b/lib/ssl/examples/src/Makefile
index 46c0507b3a..c5f31b689c 100644
--- a/lib/ssl/examples/src/Makefile
+++ b/lib/ssl/examples/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2009. All Rights Reserved.
+# Copyright Ericsson AB 2003-2011. All Rights Reserved.
#
# The 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,7 +66,7 @@ release_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)/examples/src
$(INSTALL_DIR) $(RELSYSDIR)/examples/ebin
(cd ..; tar cf - src ebin | (cd $(RELSYSDIR)/examples; tar xf -))
- chmod -f -R ug+w $(RELSYSDIR)/examples
+ chmod -R ug+w $(RELSYSDIR)/examples
release_docs_spec:
diff --git a/lib/ssl/src/Makefile b/lib/ssl/src/Makefile
index 7514ad2aa2..dc69b53b28 100644
--- a/lib/ssl/src/Makefile
+++ b/lib/ssl/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2010. All Rights Reserved.
+# Copyright Ericsson AB 1999-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -41,12 +41,9 @@ MODULES= \
ssl \
ssl_alert \
ssl_app \
- ssl_broker \
- ssl_broker_sup \
- ssl_server \
+ ssl_dist_sup\
ssl_sup \
- ssl_prim \
- inet_ssl_dist \
+ inet_tls_dist \
ssl_certificate\
ssl_certificate_db\
ssl_cipher \
@@ -62,9 +59,10 @@ MODULES= \
ssl_ssl2 \
ssl_ssl3 \
ssl_tls1 \
+ ssl_tls_dist_proxy
INTERNAL_HRL_FILES = \
- ssl_int.hrl ssl_broker_int.hrl ssl_debug.hrl \
+ ssl_debug.hrl \
ssl_alert.hrl ssl_cipher.hrl ssl_handshake.hrl ssl_internal.hrl \
ssl_record.hrl
diff --git a/lib/ssl/src/inet_ssl_dist.erl b/lib/ssl/src/inet_ssl_dist.erl
deleted file mode 100644
index 6c0fbc0618..0000000000
--- a/lib/ssl/src/inet_ssl_dist.erl
+++ /dev/null
@@ -1,456 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, 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(inet_ssl_dist).
-
-%% Handles the connection setup phase with other Erlang nodes.
-
--export([childspecs/0, listen/1, accept/1, accept_connection/5,
- setup/5, close/1, select/1, is_node_name/1]).
-
-%% internal exports
-
--export([accept_loop/2,do_accept/6,do_setup/6, getstat/1,tick/1]).
-
--import(error_logger,[error_msg/2]).
-
--include("net_address.hrl").
-
-
-
--define(to_port(Socket, Data, Opts),
- case ssl_prim:send(Socket, Data, Opts) of
- {error, closed} ->
- self() ! {ssl_closed, Socket},
- {error, closed};
- R ->
- R
- end).
-
-
--include("dist.hrl").
--include("dist_util.hrl").
-
-%% -------------------------------------------------------------
-%% This function should return a valid childspec, so that
-%% the primitive ssl_server gets supervised
-%% -------------------------------------------------------------
-childspecs() ->
- {ok, [{ssl_server_prim,{ssl_server, start_link_prim, []},
- permanent, 2000, worker, [ssl_server]}]}.
-
-
-%% ------------------------------------------------------------
-%% Select this protocol based on node name
-%% select(Node) => Bool
-%% ------------------------------------------------------------
-
-select(Node) ->
- case split_node(atom_to_list(Node), $@, []) of
- [_,_Host] -> true;
- _ -> false
- end.
-
-%% ------------------------------------------------------------
-%% Create the listen socket, i.e. the port that this erlang
-%% node is accessible through.
-%% ------------------------------------------------------------
-
-listen(Name) ->
- case ssl_prim:listen(0, [{active, false}, {packet,4}] ++
- get_ssl_options(server)) of
- {ok, Socket} ->
- TcpAddress = get_tcp_address(Socket),
- {_,Port} = TcpAddress#net_address.address,
- {ok, Creation} = erl_epmd:register_node(Name, Port),
- {ok, {Socket, TcpAddress, Creation}};
- Error ->
- Error
- end.
-
-%% ------------------------------------------------------------
-%% Accepts new connection attempts from other Erlang nodes.
-%% ------------------------------------------------------------
-
-accept(Listen) ->
- spawn_link(?MODULE, accept_loop, [self(), Listen]).
-
-accept_loop(Kernel, Listen) ->
- process_flag(priority, max),
- case ssl_prim:accept(Listen) of
- {ok, Socket} ->
- Kernel ! {accept,self(),Socket,inet,ssl},
- controller(Kernel, Socket),
- accept_loop(Kernel, Listen);
- Error ->
- exit(Error)
- end.
-
-controller(Kernel, Socket) ->
- receive
- {Kernel, controller, Pid} ->
- flush_controller(Pid, Socket),
- ssl_prim:controlling_process(Socket, Pid),
- flush_controller(Pid, Socket),
- Pid ! {self(), controller};
- {Kernel, unsupported_protocol} ->
- exit(unsupported_protocol)
- end.
-
-flush_controller(Pid, Socket) ->
- receive
- {ssl, Socket, Data} ->
- Pid ! {ssl, Socket, Data},
- flush_controller(Pid, Socket);
- {ssl_closed, Socket} ->
- Pid ! {ssl_closed, Socket},
- flush_controller(Pid, Socket)
- after 0 ->
- ok
- end.
-
-%% ------------------------------------------------------------
-%% Accepts a new connection attempt from another Erlang node.
-%% Performs the handshake with the other side.
-%% ------------------------------------------------------------
-
-accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
- spawn_link(?MODULE, do_accept,
- [self(), AcceptPid, Socket, MyNode,
- Allowed, SetupTime]).
-
-%% Suppress dialyzer warning, we do not really care about old ssl code
-%% as we intend to remove it.
--spec(do_accept(_,_,_,_,_,_) -> no_return()).
-do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
- process_flag(priority, max),
- receive
- {AcceptPid, controller} ->
- Timer = dist_util:start_timer(SetupTime),
- case check_ip(Socket) of
- true ->
- HSData = #hs_data{
- kernel_pid = Kernel,
- this_node = MyNode,
- socket = Socket,
- timer = Timer,
- this_flags = 0,
- allowed = Allowed,
- f_send = fun(S,D) -> ssl_prim:send(S,D) end,
- f_recv = fun(S,N,T) -> ssl_prim:recv(S,N,T)
- end,
- f_setopts_pre_nodeup =
- fun(S) ->
- ssl_prim:setopts(S,
- [{active, false}])
- end,
- f_setopts_post_nodeup =
- fun(S) ->
- ssl_prim:setopts(S,
- [{deliver, port},
- {active, true}])
- end,
- f_getll = fun(S) ->
- ssl_prim:getll(S)
- end,
- f_address = fun get_remote_id/2,
- mf_tick = fun ?MODULE:tick/1,
- mf_getstat = fun ?MODULE:getstat/1
- },
- dist_util:handshake_other_started(HSData);
- {false,IP} ->
- error_msg("** Connection attempt from "
- "disallowed IP ~w ** ~n", [IP]),
- ?shutdown(no_node)
- end
- end.
-
-%% ------------------------------------------------------------
-%% Get remote information about a Socket.
-%% ------------------------------------------------------------
-
-get_remote_id(Socket, Node) ->
- {ok, Address} = ssl_prim:peername(Socket),
- [_, Host] = split_node(atom_to_list(Node), $@, []),
- #net_address {
- address = Address,
- host = Host,
- protocol = ssl,
- family = inet }.
-
-%% ------------------------------------------------------------
-%% Setup a new connection to another Erlang node.
-%% Performs the handshake with the other side.
-%% ------------------------------------------------------------
-
-setup(Node, Type, MyNode, LongOrShortNames,SetupTime) ->
- spawn_link(?MODULE, do_setup, [self(),
- Node,
- Type,
- MyNode,
- LongOrShortNames,
- SetupTime]).
-
-%% Suppress dialyzer warning, we do not really care about old ssl code
-%% as we intend to remove it.
--spec(do_setup(_,_,_,_,_,_) -> no_return()).
-do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) ->
- process_flag(priority, max),
- ?trace("~p~n",[{inet_ssl_dist,self(),setup,Node}]),
- [Name, Address] = splitnode(Node, LongOrShortNames),
- case inet:getaddr(Address, inet) of
- {ok, Ip} ->
- Timer = dist_util:start_timer(SetupTime),
- case erl_epmd:port_please(Name, Ip) of
- {port, TcpPort, Version} ->
- ?trace("port_please(~p) -> version ~p~n",
- [Node,Version]),
- dist_util:reset_timer(Timer),
- case ssl_prim:connect(Ip, TcpPort,
- [{active, false},
- {packet,4}] ++
- get_ssl_options(client)) of
- {ok, Socket} ->
- HSData = #hs_data{
- kernel_pid = Kernel,
- other_node = Node,
- this_node = MyNode,
- socket = Socket,
- timer = Timer,
- this_flags = 0,
- other_version = Version,
- f_send = fun(S,D) ->
- ssl_prim:send(S,D)
- end,
- f_recv = fun(S,N,T) ->
- ssl_prim:recv(S,N,T)
- end,
- f_setopts_pre_nodeup =
- fun(S) ->
- ssl_prim:setopts
- (S,
- [{active, false}])
- end,
- f_setopts_post_nodeup =
- fun(S) ->
- ssl_prim:setopts
- (S,
- [{deliver, port},{active, true}])
- end,
- f_getll = fun(S) ->
- ssl_prim:getll(S)
- end,
- f_address =
- fun(_,_) ->
- #net_address {
- address = {Ip,TcpPort},
- host = Address,
- protocol = ssl,
- family = inet}
- end,
- mf_tick = fun ?MODULE:tick/1,
- mf_getstat = fun ?MODULE:getstat/1,
- request_type = Type
- },
- dist_util:handshake_we_started(HSData);
- _ ->
- %% Other Node may have closed since
- %% port_please !
- ?trace("other node (~p) "
- "closed since port_please.~n",
- [Node]),
- ?shutdown(Node)
- end;
- _ ->
- ?trace("port_please (~p) "
- "failed.~n", [Node]),
- ?shutdown(Node)
- end;
- _Other ->
- ?trace("inet_getaddr(~p) "
- "failed (~p).~n", [Node,Other]),
- ?shutdown(Node)
- end.
-
-%%
-%% Close a socket.
-%%
-close(Socket) ->
- ssl_prim:close(Socket).
-
-
-%% If Node is illegal terminate the connection setup!!
-splitnode(Node, LongOrShortNames) ->
- case split_node(atom_to_list(Node), $@, []) of
- [Name|Tail] when Tail =/= [] ->
- Host = lists:append(Tail),
- case split_node(Host, $., []) of
- [_] when LongOrShortNames == longnames ->
- error_msg("** System running to use "
- "fully qualified "
- "hostnames **~n"
- "** Hostname ~s is illegal **~n",
- [Host]),
- ?shutdown(Node);
- [_, _ | _] when LongOrShortNames == shortnames ->
- error_msg("** System NOT running to use fully qualified "
- "hostnames **~n"
- "** Hostname ~s is illegal **~n",
- [Host]),
- ?shutdown(Node);
- _ ->
- [Name, Host]
- end;
- [_] ->
- error_msg("** Nodename ~p illegal, no '@' character **~n",
- [Node]),
- ?shutdown(Node);
- _ ->
- error_msg("** Nodename ~p illegal **~n", [Node]),
- ?shutdown(Node)
- end.
-
-split_node([Chr|T], Chr, Ack) -> [lists:reverse(Ack)|split_node(T, Chr, [])];
-split_node([H|T], Chr, Ack) -> split_node(T, Chr, [H|Ack]);
-split_node([], _, Ack) -> [lists:reverse(Ack)].
-
-%% ------------------------------------------------------------
-%% Fetch local information about a Socket.
-%% ------------------------------------------------------------
-get_tcp_address(Socket) ->
- {ok, Address} = ssl_prim:sockname(Socket),
- {ok, Host} = inet:gethostname(),
- #net_address {
- address = Address,
- host = Host,
- protocol = ssl,
- family = inet
- }.
-
-%% ------------------------------------------------------------
-%% Do only accept new connection attempts from nodes at our
-%% own LAN, if the check_ip environment parameter is true.
-%% ------------------------------------------------------------
-check_ip(Socket) ->
- case application:get_env(check_ip) of
- {ok, true} ->
- case get_ifs(Socket) of
- {ok, IFs, IP} ->
- check_ip(IFs, IP);
- _ ->
- ?shutdown(no_node)
- end;
- _ ->
- true
- end.
-
-get_ifs(Socket) ->
- case ssl_prim:peername(Socket) of
- {ok, {IP, _}} ->
- case ssl_prim:getif(Socket) of
- {ok, IFs} -> {ok, IFs, IP};
- Error -> Error
- end;
- Error ->
- Error
- end.
-
-check_ip([{OwnIP, _, Netmask}|IFs], PeerIP) ->
- case {mask(Netmask, PeerIP), mask(Netmask, OwnIP)} of
- {M, M} -> true;
- _ -> check_ip(IFs, PeerIP)
- end;
-check_ip([], PeerIP) ->
- {false, PeerIP}.
-
-mask({M1,M2,M3,M4}, {IP1,IP2,IP3,IP4}) ->
- {M1 band IP1,
- M2 band IP2,
- M3 band IP3,
- M4 band IP4}.
-
-is_node_name(Node) when is_atom(Node) ->
- case split_node(atom_to_list(Node), $@, []) of
- [_, _Host] -> true;
- _ -> false
- end;
-is_node_name(_Node) ->
- false.
-tick(Sock) ->
- ?to_port(Sock,[],[force]).
-getstat(Socket) ->
- case ssl_prim:getstat(Socket, [recv_cnt, send_cnt, send_pend]) of
- {ok, Stat} ->
- split_stat(Stat,0,0,0);
- Error ->
- Error
- end.
-
-split_stat([{recv_cnt, R}|Stat], _, W, P) ->
- split_stat(Stat, R, W, P);
-split_stat([{send_cnt, W}|Stat], R, _, P) ->
- split_stat(Stat, R, W, P);
-split_stat([{send_pend, P}|Stat], R, W, _) ->
- split_stat(Stat, R, W, P);
-split_stat([], R, W, P) ->
- {ok, R, W, P}.
-
-
-get_ssl_options(Type) ->
- case init:get_argument(ssl_dist_opt) of
- {ok, Args} ->
- ssl_options(Type, Args);
- _ ->
- []
- end.
-
-ssl_options(_,[]) ->
- [];
-ssl_options(server, [["server_certfile", Value]|T]) ->
- [{certfile, Value} | ssl_options(server,T)];
-ssl_options(client, [["client_certfile", Value]|T]) ->
- [{certfile, Value} | ssl_options(client,T)];
-ssl_options(server, [["server_cacertfile", Value]|T]) ->
- [{cacertfile, Value} | ssl_options(server,T)];
-ssl_options(server, [["server_keyfile", Value]|T]) ->
- [{keyfile, Value} | ssl_options(server,T)];
-ssl_options(Type, [["client_certfile", _Value]|T]) ->
- ssl_options(Type,T);
-ssl_options(Type, [["server_certfile", _Value]|T]) ->
- ssl_options(Type,T);
-ssl_options(Type, [[Item, Value]|T]) ->
- [{atomize(Item),fixup(Value)} | ssl_options(Type,T)];
-ssl_options(Type, [[Item,Value |T1]|T2]) ->
- ssl_options(atomize(Type),[[Item,Value],T1|T2]);
-ssl_options(_,_) ->
- exit(malformed_ssl_dist_opt).
-
-fixup(Value) ->
- case catch list_to_integer(Value) of
- {'EXIT',_} ->
- Value;
- Int ->
- Int
- end.
-
-atomize(List) when is_list(List) ->
- list_to_atom(List);
-atomize(Atom) when is_atom(Atom) ->
- Atom.
diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl
new file mode 100644
index 0000000000..115527aae0
--- /dev/null
+++ b/lib/ssl/src/inet_tls_dist.erl
@@ -0,0 +1,275 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(inet_tls_dist).
+
+-export([childspecs/0, listen/1, accept/1, accept_connection/5,
+ setup/5, close/1, select/1, is_node_name/1]).
+
+-include_lib("kernel/include/net_address.hrl").
+-include_lib("kernel/include/dist.hrl").
+-include_lib("kernel/include/dist_util.hrl").
+
+childspecs() ->
+ {ok, [{ssl_dist_sup,{ssl_dist_sup, start_link, []},
+ permanent, 2000, worker, [ssl_dist_sup]}]}.
+
+select(Node) ->
+ case split_node(atom_to_list(Node), $@, []) of
+ [_,_Host] ->
+ true;
+ _ ->
+ false
+ end.
+
+is_node_name(Node) when is_atom(Node) ->
+ select(Node);
+is_node_name(_) ->
+ false.
+
+listen(Name) ->
+ ssl_tls_dist_proxy:listen(Name).
+
+accept(Listen) ->
+ ssl_tls_dist_proxy:accept(Listen).
+
+accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
+ Kernel = self(),
+ spawn_link(fun() -> do_accept(Kernel, AcceptPid, Socket,
+ MyNode, Allowed, SetupTime) end).
+
+setup(Node, Type, MyNode, LongOrShortNames,SetupTime) ->
+ Kernel = self(),
+ spawn(fun() -> do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) end).
+
+do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
+ [Name, Address] = splitnode(Node, LongOrShortNames),
+ case inet:getaddr(Address, inet) of
+ {ok, Ip} ->
+ Timer = dist_util:start_timer(SetupTime),
+ case erl_epmd:port_please(Name, Ip) of
+ {port, TcpPort, Version} ->
+ ?trace("port_please(~p) -> version ~p~n",
+ [Node,Version]),
+ dist_util:reset_timer(Timer),
+ case ssl_tls_dist_proxy:connect(Ip, TcpPort) of
+ {ok, Socket} ->
+ HSData = connect_hs_data(Kernel, Node, MyNode, Socket,
+ Timer, Version, Ip, TcpPort, Address,
+ Type),
+ dist_util:handshake_we_started(HSData);
+ _ ->
+ %% Other Node may have closed since
+ %% port_please !
+ ?trace("other node (~p) "
+ "closed since port_please.~n",
+ [Node]),
+ ?shutdown(Node)
+ end;
+ _ ->
+ ?trace("port_please (~p) "
+ "failed.~n", [Node]),
+ ?shutdown(Node)
+ end;
+ _Other ->
+ ?trace("inet_getaddr(~p) "
+ "failed (~p).~n", [Node,Other]),
+ ?shutdown(Node)
+ end.
+
+close(Socket) ->
+ try
+ erlang:error(foo)
+ catch _:_ ->
+ io:format("close called ~p ~p~n",[Socket, erlang:get_stacktrace()])
+ end,
+ gen_tcp:close(Socket),
+ ok.
+
+do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
+ process_flag(priority, max),
+ receive
+ {AcceptPid, controller} ->
+ Timer = dist_util:start_timer(SetupTime),
+ case check_ip(Socket) of
+ true ->
+ HSData = accept_hs_data(Kernel, MyNode, Socket, Timer, Allowed),
+ dist_util:handshake_other_started(HSData);
+ {false,IP} ->
+ error_logger:error_msg("** Connection attempt from "
+ "disallowed IP ~w ** ~n", [IP]),
+ ?shutdown(no_node)
+ end
+ end.
+%% ------------------------------------------------------------
+%% Do only accept new connection attempts from nodes at our
+%% own LAN, if the check_ip environment parameter is true.
+%% ------------------------------------------------------------
+check_ip(Socket) ->
+ case application:get_env(check_ip) of
+ {ok, true} ->
+ case get_ifs(Socket) of
+ {ok, IFs, IP} ->
+ check_ip(IFs, IP);
+ _ ->
+ ?shutdown(no_node)
+ end;
+ _ ->
+ true
+ end.
+
+get_ifs(Socket) ->
+ case inet:peername(Socket) of
+ {ok, {IP, _}} ->
+ case inet:getif(Socket) of
+ {ok, IFs} -> {ok, IFs, IP};
+ Error -> Error
+ end;
+ Error ->
+ Error
+ end.
+
+check_ip([{OwnIP, _, Netmask}|IFs], PeerIP) ->
+ case {mask(Netmask, PeerIP), mask(Netmask, OwnIP)} of
+ {M, M} -> true;
+ _ -> check_ip(IFs, PeerIP)
+ end;
+check_ip([], PeerIP) ->
+ {false, PeerIP}.
+
+mask({M1,M2,M3,M4}, {IP1,IP2,IP3,IP4}) ->
+ {M1 band IP1,
+ M2 band IP2,
+ M3 band IP3,
+ M4 band IP4};
+
+mask({M1,M2,M3,M4, M5, M6, M7, M8}, {IP1,IP2,IP3,IP4, IP5, IP6, IP7, IP8}) ->
+ {M1 band IP1,
+ M2 band IP2,
+ M3 band IP3,
+ M4 band IP4,
+ M5 band IP5,
+ M6 band IP6,
+ M7 band IP7,
+ M8 band IP8}.
+
+
+%% If Node is illegal terminate the connection setup!!
+splitnode(Node, LongOrShortNames) ->
+ case split_node(atom_to_list(Node), $@, []) of
+ [Name|Tail] when Tail =/= [] ->
+ Host = lists:append(Tail),
+ check_node(Name, Node, Host, LongOrShortNames);
+ [_] ->
+ error_logger:error_msg("** Nodename ~p illegal, no '@' character **~n",
+ [Node]),
+ ?shutdown(Node);
+ _ ->
+ error_logger:error_msg("** Nodename ~p illegal **~n", [Node]),
+ ?shutdown(Node)
+ end.
+
+check_node(Name, Node, Host, LongOrShortNames) ->
+ case split_node(Host, $., []) of
+ [_] when LongOrShortNames == longnames ->
+ error_logger:error_msg("** System running to use "
+ "fully qualified "
+ "hostnames **~n"
+ "** Hostname ~s is illegal **~n",
+ [Host]),
+ ?shutdown(Node);
+ [_, _ | _] when LongOrShortNames == shortnames ->
+ error_logger:error_msg("** System NOT running to use fully qualified "
+ "hostnames **~n"
+ "** Hostname ~s is illegal **~n",
+ [Host]),
+ ?shutdown(Node);
+ _ ->
+ [Name, Host]
+ end.
+
+split_node([Chr|T], Chr, Ack) ->
+ [lists:reverse(Ack)|split_node(T, Chr, [])];
+split_node([H|T], Chr, Ack) ->
+ split_node(T, Chr, [H|Ack]);
+split_node([], _, Ack) ->
+ [lists:reverse(Ack)].
+
+connect_hs_data(Kernel, Node, MyNode, Socket, Timer, Version, Ip, TcpPort, Address, Type) ->
+ common_hs_data(Kernel, MyNode, Socket, Timer,
+ #hs_data{other_node = Node,
+ other_version = Version,
+ f_address =
+ fun(_,_) ->
+ #net_address{address = {Ip,TcpPort},
+ host = Address,
+ protocol = proxy,
+ family = inet}
+ end,
+ request_type = Type
+ }).
+
+accept_hs_data(Kernel, MyNode, Socket, Timer, Allowed) ->
+ common_hs_data(Kernel, MyNode, Socket, Timer, #hs_data{
+ allowed = Allowed,
+ f_address = fun(S, N) ->
+ ssl_tls_dist_proxy:get_remote_id(S, N)
+ end
+ }).
+
+common_hs_data(Kernel, MyNode, Socket, Timer, HsData) ->
+ HsData#hs_data{
+ kernel_pid = Kernel,
+ this_node = MyNode,
+ socket = Socket,
+ timer = Timer,
+ this_flags = 0,
+ f_send =
+ fun(S,D) ->
+ gen_tcp:send(S,D)
+ end,
+ f_recv =
+ fun(S,N,T) ->
+ gen_tcp:recv(S,N,T)
+ end,
+ f_setopts_pre_nodeup =
+ fun(S) ->
+ inet:setopts(S, [{active, false}, {packet, 4}])
+ end,
+ f_setopts_post_nodeup =
+ fun(S) ->
+ inet:setopts(S, [{deliver, port},{active, true}])
+ end,
+ f_getll =
+ fun(S) ->
+ inet:getll(S)
+ end,
+ mf_tick =
+ fun(S) ->
+ gen_tcp:send(S, <<>>)
+ end,
+ mf_getstat =
+ fun(S) ->
+ {ok, Stats} = inet:getstat(S, [recv_cnt, send_cnt, send_pend]),
+ R = proplists:get_value(recv_cnt, Stats, 0),
+ W = proplists:get_value(send_cnt, Stats, 0),
+ P = proplists:get_value(send_pend, Stats, 0),
+ {ok, R,W,P}
+ end}.
diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src
index b9716786e6..13d5eaf4d7 100644
--- a/lib/ssl/src/ssl.app.src
+++ b/lib/ssl/src/ssl.app.src
@@ -4,11 +4,9 @@
{modules, [ssl,
ssl_app,
ssl_sup,
- ssl_server,
- ssl_broker,
- ssl_broker_sup,
- ssl_prim,
- inet_ssl_dist,
+ inet_tls_dist,
+ ssl_tls_dist_proxy,
+ ssl_dist_sup,
ssl_tls1,
ssl_ssl3,
ssl_ssl2,
@@ -26,7 +24,7 @@
ssl_certificate,
ssl_alert
]},
- {registered, [ssl_sup, ssl_server, ssl_broker_sup]},
+ {registered, [ssl_sup, ssl_manager]},
{applications, [crypto, public_key, kernel, stdlib]},
{env, []},
{mod, {ssl_app, []}}]}.
diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src
index d3e426f254..29674f30da 100644
--- a/lib/ssl/src/ssl.appup.src
+++ b/lib/ssl/src/ssl.appup.src
@@ -1,17 +1,21 @@
%% -*- erlang -*-
{"%VSN%",
[
+ {"4.1.5", [{restart_application, ssl}]},
+ {"4.1.4", [{restart_application, ssl}]},
{"4.1.3", [{restart_application, ssl}]},
{"4.1.2", [{restart_application, ssl}]},
{"4.1.1", [{restart_application, ssl}]},
- {"4.1", [{restart_application, ssl}]},
+ {"4.1", [{restart_application, ssl}]},
{"4.0.1", [{restart_application, ssl}]}
],
[
+ {"4.1.5", [{restart_application, ssl}]},
+ {"4.1.4", [{restart_application, ssl}]},
{"4.1.3", [{restart_application, ssl}]},
{"4.1.2", [{restart_application, ssl}]},
{"4.1.1", [{restart_application, ssl}]},
- {"4.1", [{restart_application, ssl}]},
+ {"4.1", [{restart_application, ssl}]},
{"4.0.1", [{restart_application, ssl}]}
]}.
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 7b1fda4cf9..35f9410562 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -25,18 +25,15 @@
-export([start/0, start/1, stop/0, transport_accept/1,
transport_accept/2, ssl_accept/1, ssl_accept/2, ssl_accept/3,
- ciphers/0, cipher_suites/0, cipher_suites/1, close/1, shutdown/2,
+ cipher_suites/0, cipher_suites/1, close/1, shutdown/2,
connect/3, connect/2, connect/4, connection_info/1,
- controlling_process/2, listen/2, pid/1, peername/1, recv/2, recv/3,
- send/2, getopts/2, setopts/2, seed/1, sockname/1, peercert/1,
- peercert/2, version/0, versions/0, session_info/1, format_error/1,
+ controlling_process/2, listen/2, pid/1, peername/1, peercert/1,
+ recv/2, recv/3, send/2, getopts/2, setopts/2, sockname/1,
+ versions/0, session_info/1, format_error/1,
renegotiate/1]).
-%% Should be deprecated as soon as old ssl is removed
-%%-deprecated({pid, 1, next_major_release}).
--deprecated({peercert, 2, next_major_release}).
+-deprecated({pid, 1, next_major_release}).
--include("ssl_int.hrl").
-include("ssl_internal.hrl").
-include("ssl_record.hrl").
-include("ssl_cipher.hrl").
@@ -49,10 +46,12 @@
inet_ssl, %% inet options for internal ssl socket
cb %% Callback info
}).
--type option() :: socketoption() | ssloption() | transportoption().
--type socketoption() :: [{property(), term()}]. %% See gen_tcp and inet
--type property() :: atom().
--type ssloption() :: {verify, verify_type()} |
+-type connect_option() :: socket_connect_option() | ssl_option() | transport_option().
+-type socket_connect_option() :: gen_tcp:connect_option().
+-type listen_option() :: socket_listen_option() | ssl_option() | transport_option().
+-type socket_listen_option() :: gen_tcp:listen_option().
+
+-type ssl_option() :: {verify, verify_type()} |
{verify_fun, {fun(), InitialUserState::term()}} |
{fail_if_no_peer_cert, boolean()} | {depth, integer()} |
{cert, Der::binary()} | {certfile, path()} | {key, Der::binary()} |
@@ -67,7 +66,7 @@
string(). % (according to old API)
-type ssl_imp() :: new | old.
--type transportoption() :: {CallbackModule::atom(), DataTag::atom(), ClosedTag::atom()}.
+-type transport_option() :: {cb_info, {CallbackModule::atom(), DataTag::atom(), ClosedTag::atom()}}.
%%--------------------------------------------------------------------
@@ -97,15 +96,15 @@ stop() ->
application:stop(ssl).
%%--------------------------------------------------------------------
--spec connect(host() | port(), [option()]) -> {ok, #sslsocket{}} |
+-spec connect(host() | port(), [connect_option()]) -> {ok, #sslsocket{}} |
{error, reason()}.
--spec connect(host() | port(), [option()] | port_num(), timeout() | list()) ->
+-spec connect(host() | port(), [connect_option()] | inet:port_number(), timeout() | list()) ->
{ok, #sslsocket{}} | {error, reason()}.
--spec connect(host() | port(), port_num(), list(), timeout()) ->
+-spec connect(host() | port(), inet:port_number(), list(), timeout()) ->
{ok, #sslsocket{}} | {error, reason()}.
%%
-%% Description: Connect to a ssl server.
+%% Description: Connect to an ssl server.
%%--------------------------------------------------------------------
connect(Socket, SslOptions) when is_port(Socket) ->
connect(Socket, SslOptions, infinity).
@@ -113,7 +112,7 @@ connect(Socket, SslOptions) when is_port(Socket) ->
connect(Socket, SslOptions0, Timeout) when is_port(Socket) ->
EmulatedOptions = emulated_options(),
{ok, InetValues} = inet:getopts(Socket, EmulatedOptions),
- inet:setopts(Socket, internal_inet_values()),
+ ok = inet:setopts(Socket, internal_inet_values()),
try handle_options(SslOptions0 ++ InetValues, client) of
{ok, #config{cb=CbInfo, ssl=SslOptions, emulated=EmOpts}} ->
case inet:peername(Socket) of
@@ -132,59 +131,49 @@ connect(Socket, SslOptions0, Timeout) when is_port(Socket) ->
connect(Host, Port, Options) ->
connect(Host, Port, Options, infinity).
-connect(Host, Port, Options0, Timeout) ->
- case proplists:get_value(ssl_imp, Options0, new) of
- new ->
- new_connect(Host, Port, Options0, Timeout);
- old ->
- %% Allow the option reuseaddr to be present
- %% so that new and old ssl can be run by the same
- %% code, however the option will be ignored by old ssl
- %% that hardcodes reuseaddr to true in its portprogram.
- Options1 = proplists:delete(reuseaddr, Options0),
- Options = proplists:delete(ssl_imp, Options1),
- old_connect(Host, Port, Options, Timeout);
- Value ->
- {error, {eoptions, {ssl_imp, Value}}}
+connect(Host, Port, Options, Timeout) ->
+ try handle_options(Options, client) of
+ {ok, Config} ->
+ do_connect(Host,Port,Config,Timeout)
+ catch
+ throw:Error ->
+ Error
end.
%%--------------------------------------------------------------------
--spec listen(port_num(), [option()]) ->{ok, #sslsocket{}} | {error, reason()}.
+-spec listen(inet:port_number(), [listen_option()]) ->{ok, #sslsocket{}} | {error, reason()}.
%%
-%% Description: Creates a ssl listen socket.
+%% Description: Creates an ssl listen socket.
%%--------------------------------------------------------------------
listen(_Port, []) ->
{error, enooptions};
listen(Port, Options0) ->
- case proplists:get_value(ssl_imp, Options0, new) of
- new ->
- new_listen(Port, Options0);
- old ->
- %% Allow the option reuseaddr to be present
- %% so that new and old ssl can be run by the same
- %% code, however the option will be ignored by old ssl
- %% that hardcodes reuseaddr to true in its portprogram.
- Options1 = proplists:delete(reuseaddr, Options0),
- Options = proplists:delete(ssl_imp, Options1),
- old_listen(Port, Options);
- Value ->
- {error, {eoptions, {ssl_imp, Value}}}
+ try
+ {ok, Config} = handle_options(Options0, server),
+ #config{cb={CbModule, _, _, _},inet_user=Options} = Config,
+ case CbModule:listen(Port, Options) of
+ {ok, ListenSocket} ->
+ {ok, #sslsocket{pid = {ListenSocket, Config}, fd = new_ssl}};
+ Err = {error, _} ->
+ Err
+ end
+ catch
+ Error = {error, _} ->
+ Error
end.
-
%%--------------------------------------------------------------------
-spec transport_accept(#sslsocket{}) -> {ok, #sslsocket{}} |
{error, reason()}.
-spec transport_accept(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} |
{error, reason()}.
%%
-%% Description: Performs transport accept on a ssl listen socket
+%% Description: Performs transport accept on an ssl listen socket
%%--------------------------------------------------------------------
transport_accept(ListenSocket) ->
transport_accept(ListenSocket, infinity).
-transport_accept(#sslsocket{pid = {ListenSocket, #config{cb=CbInfo, ssl=SslOpts}},
- fd = new_ssl}, Timeout) ->
+transport_accept(#sslsocket{pid = {ListenSocket, #config{cb=CbInfo, ssl=SslOpts}}}, Timeout) ->
%% The setopt could have been invoked on the listen socket
%% and options should be inherited.
@@ -206,40 +195,30 @@ transport_accept(#sslsocket{pid = {ListenSocket, #config{cb=CbInfo, ssl=SslOpts}
end;
{error, Reason} ->
{error, Reason}
- end;
-
-transport_accept(#sslsocket{} = ListenSocket, Timeout) ->
- ensure_old_ssl_started(),
- {ok, Pid} = ssl_broker:start_broker(acceptor),
- ssl_broker:transport_accept(Pid, ListenSocket, Timeout).
+ end.
%%--------------------------------------------------------------------
-spec ssl_accept(#sslsocket{}) -> ok | {error, reason()}.
--spec ssl_accept(#sslsocket{} | port(), timeout()| [option()]) ->
+-spec ssl_accept(#sslsocket{} | port(), timeout()| [ssl_option() | transport_option()]) ->
ok | {ok, #sslsocket{}} | {error, reason()}.
--spec ssl_accept(port(), [option()], timeout()) -> {ok, #sslsocket{}} | {error, reason()}.
+-spec ssl_accept(port(), [ssl_option()| transport_option()], timeout()) -> {ok, #sslsocket{}} | {error, reason()}.
%%
-%% Description: Performs accept on a ssl listen socket. e.i. performs
+%% Description: Performs accept on an ssl listen socket. e.i. performs
%% ssl handshake.
%%--------------------------------------------------------------------
ssl_accept(ListenSocket) ->
ssl_accept(ListenSocket, infinity).
-ssl_accept(#sslsocket{fd = new_ssl} = Socket, Timeout) ->
+ssl_accept(#sslsocket{} = Socket, Timeout) ->
ssl_connection:handshake(Socket, Timeout);
ssl_accept(ListenSocket, SslOptions) when is_port(ListenSocket) ->
- ssl_accept(ListenSocket, SslOptions, infinity);
-
-%% Old ssl
-ssl_accept(#sslsocket{} = Socket, Timeout) ->
- ensure_old_ssl_started(),
- ssl_broker:ssl_accept(Socket, Timeout).
+ ssl_accept(ListenSocket, SslOptions, infinity).
ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket) ->
EmulatedOptions = emulated_options(),
{ok, InetValues} = inet:getopts(Socket, EmulatedOptions),
- inet:setopts(Socket, internal_inet_values()),
+ ok = inet:setopts(Socket, internal_inet_values()),
try handle_options(SslOptions ++ InetValues, server) of
{ok, #config{cb=CbInfo,ssl=SslOpts, emulated=EmOpts}} ->
{ok, Port} = inet:port(Socket),
@@ -253,27 +232,20 @@ ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket) ->
%%--------------------------------------------------------------------
-spec close(#sslsocket{}) -> term().
%%
-%% Description: Close a ssl connection
+%% Description: Close an ssl connection
%%--------------------------------------------------------------------
-close(#sslsocket{pid = {ListenSocket, #config{cb={CbMod,_, _, _}}}, fd = new_ssl}) ->
+close(#sslsocket{pid = {ListenSocket, #config{cb={CbMod,_, _, _}}}}) ->
CbMod:close(ListenSocket);
-close(#sslsocket{pid = Pid, fd = new_ssl}) ->
- ssl_connection:close(Pid);
-close(Socket = #sslsocket{}) ->
- ensure_old_ssl_started(),
- ssl_broker:close(Socket).
+close(#sslsocket{pid = Pid}) ->
+ ssl_connection:close(Pid).
%%--------------------------------------------------------------------
--spec send(#sslsocket{}, iolist()) -> ok | {error, reason()}.
+-spec send(#sslsocket{}, iodata()) -> ok | {error, reason()}.
%%
%% Description: Sends data over the ssl connection
%%--------------------------------------------------------------------
-send(#sslsocket{pid = Pid, fd = new_ssl}, Data) ->
- ssl_connection:send(Pid, Data);
-
-send(#sslsocket{} = Socket, Data) ->
- ensure_old_ssl_started(),
- ssl_broker:send(Socket, Data).
+send(#sslsocket{pid = Pid}, Data) ->
+ ssl_connection:send(Pid, Data).
%%--------------------------------------------------------------------
-spec recv(#sslsocket{}, integer()) -> {ok, binary()| list()} | {error, reason()}.
@@ -284,11 +256,7 @@ send(#sslsocket{} = Socket, Data) ->
recv(Socket, Length) ->
recv(Socket, Length, infinity).
recv(#sslsocket{pid = Pid, fd = new_ssl}, Length, Timeout) ->
- ssl_connection:recv(Pid, Length, Timeout);
-
-recv(Socket = #sslsocket{}, Length, Timeout) ->
- ensure_old_ssl_started(),
- ssl_broker:recv(Socket, Length, Timeout).
+ ssl_connection:recv(Pid, Length, Timeout).
%%--------------------------------------------------------------------
-spec controlling_process(#sslsocket{}, pid()) -> ok | {error, reason()}.
@@ -296,13 +264,8 @@ recv(Socket = #sslsocket{}, Length, Timeout) ->
%% Description: Changes process that receives the messages when active = true
%% or once.
%%--------------------------------------------------------------------
-controlling_process(#sslsocket{pid = Pid, fd = new_ssl}, NewOwner)
- when is_pid(Pid) ->
- ssl_connection:new_user(Pid, NewOwner);
-
-controlling_process(Socket, NewOwner) when is_pid(NewOwner) ->
- ensure_old_ssl_started(),
- ssl_broker:controlling_process(Socket, NewOwner).
+controlling_process(#sslsocket{pid = Pid}, NewOwner) when is_pid(Pid) ->
+ ssl_connection:new_user(Pid, NewOwner).
%%--------------------------------------------------------------------
-spec connection_info(#sslsocket{}) -> {ok, {tls_atom_version(), erl_cipher_suite()}} |
@@ -310,82 +273,31 @@ controlling_process(Socket, NewOwner) when is_pid(NewOwner) ->
%%
%% Description: Returns ssl protocol and cipher used for the connection
%%--------------------------------------------------------------------
-connection_info(#sslsocket{pid = Pid, fd = new_ssl}) ->
- ssl_connection:info(Pid);
+connection_info(#sslsocket{pid = Pid}) ->
+ ssl_connection:info(Pid).
-connection_info(#sslsocket{} = Socket) ->
- ensure_old_ssl_started(),
- ssl_broker:connection_info(Socket).
+%%--------------------------------------------------------------------
+-spec peername(#sslsocket{}) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, reason()}.
+%%
+%% Description: same as inet:peername/1.
+%%--------------------------------------------------------------------
+peername(#sslsocket{pid = Pid}) ->
+ ssl_connection:peername(Pid).
%%--------------------------------------------------------------------
--spec peercert(#sslsocket{}) ->{ok, der_cert()} | {error, reason()}.
+-spec peercert(#sslsocket{}) ->{ok, DerCert::binary()} | {error, reason()}.
%%
%% Description: Returns the peercert.
%%--------------------------------------------------------------------
-peercert(Socket) ->
- peercert(Socket, []).
-
-peercert(#sslsocket{pid = Pid, fd = new_ssl}, Opts) ->
+peercert(#sslsocket{pid = Pid}) ->
case ssl_connection:peer_certificate(Pid) of
{ok, undefined} ->
{error, no_peercert};
- {ok, BinCert} ->
- decode_peercert(BinCert, Opts);
- {error, Reason} ->
- {error, Reason}
- end;
-
-peercert(#sslsocket{} = Socket, Opts) ->
- ensure_old_ssl_started(),
- case ssl_broker:peercert(Socket) of
- {ok, Bin} ->
- decode_peercert(Bin, Opts);
- {error, Reason} ->
- {error, Reason}
- end.
-
-
-decode_peercert(BinCert, Opts) ->
- PKOpts = [case Opt of ssl -> otp; pkix -> plain end ||
- Opt <- Opts, Opt =:= ssl orelse Opt =:= pkix],
- case PKOpts of
- [Opt] ->
- select_part(Opt, public_key:pkix_decode_cert(BinCert, Opt), Opts);
- [] ->
- {ok, BinCert}
- end.
-
-select_part(otp, Cert, Opts) ->
- case lists:member(subject, Opts) of
- true ->
- TBS = Cert#'OTPCertificate'.tbsCertificate,
- {ok, TBS#'OTPTBSCertificate'.subject};
- false ->
- {ok, Cert}
- end;
-
-select_part(plain, Cert, Opts) ->
- case lists:member(subject, Opts) of
- true ->
- TBS = Cert#'Certificate'.tbsCertificate,
- {ok, TBS#'TBSCertificate'.subject};
- false ->
- {ok, Cert}
+ Result ->
+ Result
end.
%%--------------------------------------------------------------------
--spec peername(#sslsocket{}) -> {ok, {tuple(), port_num()}} | {error, reason()}.
-%%
-%% Description: same as inet:peername/1.
-%%--------------------------------------------------------------------
-peername(#sslsocket{fd = new_ssl, pid = Pid}) ->
- ssl_connection:peername(Pid);
-
-peername(#sslsocket{} = Socket) ->
- ensure_old_ssl_started(),
- ssl_broker:peername(Socket).
-
-%%--------------------------------------------------------------------
-spec cipher_suites() -> [erl_cipher_suite()].
-spec cipher_suites(erlang | openssl) -> [erl_cipher_suite()] | [string()].
@@ -403,67 +315,74 @@ 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{}, [gen_tcp:option_name()]) ->
+ {ok, [gen_tcp:option()]} | {error, reason()}.
%%
-%% Description:
-%%--------------------------------------------------------------------
-getopts(#sslsocket{fd = new_ssl, pid = Pid}, OptTags) when is_pid(Pid) ->
- ssl_connection:get_opts(Pid, OptTags);
-getopts(#sslsocket{fd = new_ssl, pid = {ListenSocket, _}}, OptTags) ->
- inet:getopts(ListenSocket, OptTags);
-getopts(#sslsocket{} = Socket, Options) ->
- ensure_old_ssl_started(),
- ssl_broker:getopts(Socket, Options).
+%% Description: Gets options
+%%--------------------------------------------------------------------
+getopts(#sslsocket{pid = Pid}, OptionTags) when is_pid(Pid), is_list(OptionTags) ->
+ ssl_connection:get_opts(Pid, OptionTags);
+getopts(#sslsocket{pid = {ListenSocket, _}}, OptionTags) when is_list(OptionTags) ->
+ try inet:getopts(ListenSocket, OptionTags) of
+ {ok, _} = Result ->
+ Result;
+ {error, InetError} ->
+ {error, {eoptions, {inet_options, OptionTags, InetError}}}
+ catch
+ _:_ ->
+ {error, {eoptions, {inet_options, OptionTags}}}
+ end;
+getopts(#sslsocket{}, OptionTags) ->
+ {error, {eoptions, {inet_options, OptionTags}}}.
%%--------------------------------------------------------------------
--spec setopts(#sslsocket{}, [{atom(), term()}]) -> ok | {error, reason()}.
+-spec setopts(#sslsocket{}, [gen_tcp:option()]) -> ok | {error, reason()}.
%%
-%% Description:
+%% Description: Sets options
%%--------------------------------------------------------------------
-setopts(#sslsocket{fd = new_ssl, pid = Pid}, Opts0) when is_pid(Pid) ->
- Opts = proplists:expand([{binary, [{mode, binary}]},
- {list, [{mode, list}]}], Opts0),
- ssl_connection:set_opts(Pid, Opts);
-setopts(#sslsocket{fd = new_ssl, pid = {ListenSocket, _}}, OptTags) ->
- inet:setopts(ListenSocket, OptTags);
-setopts(#sslsocket{} = Socket, Options) ->
- ensure_old_ssl_started(),
- ssl_broker:setopts(Socket, Options).
+setopts(#sslsocket{pid = Pid}, Options0) when is_pid(Pid), is_list(Options0) ->
+ try proplists:expand([{binary, [{mode, binary}]},
+ {list, [{mode, list}]}], Options0) of
+ Options ->
+ ssl_connection:set_opts(Pid, Options)
+ catch
+ _:_ ->
+ {error, {eoptions, {not_a_proplist, Options0}}}
+ end;
+
+setopts(#sslsocket{pid = {ListenSocket, _}}, Options) when is_list(Options) ->
+ try inet:setopts(ListenSocket, Options) of
+ ok ->
+ ok;
+ {error, InetError} ->
+ {error, {eoptions, {inet_options, Options, InetError}}}
+ catch
+ _:Error ->
+ {error, {eoptions, {inet_options, Options, Error}}}
+ end;
+setopts(#sslsocket{}, Options) ->
+ {error, {eoptions,{not_a_proplist, Options}}}.
%%---------------------------------------------------------------
-spec shutdown(#sslsocket{}, read | write | read_write) -> ok | {error, reason()}.
%%
%% Description: Same as gen_tcp:shutdown/2
%%--------------------------------------------------------------------
-shutdown(#sslsocket{pid = {ListenSocket, #config{cb={CbMod,_, _, _}}}, fd = new_ssl}, How) ->
+shutdown(#sslsocket{pid = {ListenSocket, #config{cb={CbMod,_, _, _}}}}, How) ->
CbMod:shutdown(ListenSocket, How);
-shutdown(#sslsocket{pid = Pid, fd = new_ssl}, How) ->
+shutdown(#sslsocket{pid = Pid}, How) ->
ssl_connection:shutdown(Pid, How).
%%--------------------------------------------------------------------
--spec sockname(#sslsocket{}) -> {ok, {tuple(), port_num()}} | {error, reason()}.
+-spec sockname(#sslsocket{}) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, reason()}.
%%
%% Description: Same as inet:sockname/1
%%--------------------------------------------------------------------
-sockname(#sslsocket{fd = new_ssl, pid = {ListenSocket, _}}) ->
+sockname(#sslsocket{pid = {ListenSocket, _}}) ->
inet:sockname(ListenSocket);
-sockname(#sslsocket{fd = new_ssl, pid = Pid}) ->
- ssl_connection:sockname(Pid);
-
-sockname(#sslsocket{} = Socket) ->
- ensure_old_ssl_started(),
- ssl_broker:sockname(Socket).
-
-%%---------------------------------------------------------------
--spec seed(term()) ->term().
-%%
-%% Description: Only used by old ssl.
-%%--------------------------------------------------------------------
-%% TODO: crypto:seed ?
-seed(Data) ->
- ensure_old_ssl_started(),
- ssl_server:seed(Data).
+sockname(#sslsocket{pid = Pid}) ->
+ ssl_connection:sockname(Pid).
%%---------------------------------------------------------------
-spec session_info(#sslsocket{}) -> {ok, list()} | {error, reason()}.
@@ -519,63 +438,6 @@ format_error(esslconnect) ->
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" ++ _ ->
@@ -589,16 +451,7 @@ format_error(Error) ->
%%%--------------------------------------------------------------
%%% Internal functions
%%%--------------------------------------------------------------------
-new_connect(Address, Port, Options, Timeout) when is_list(Options) ->
- try handle_options(Options, client) of
- {ok, Config} ->
- do_new_connect(Address,Port,Config,Timeout)
- catch
- throw:Error ->
- Error
- end.
-
-do_new_connect(Address, Port,
+do_connect(Address, Port,
#config{cb=CbInfo, inet_user=UserOpts, ssl=SslOpts,
emulated=EmOpts,inet_ssl=SocketOpts},
Timeout) ->
@@ -612,39 +465,15 @@ do_new_connect(Address, Port,
catch
exit:{function_clause, _} ->
{error, {eoptions, {cb_info, CbInfo}}};
+ exit:badarg ->
+ {error, {eoptions, {inet_options, UserOpts}}};
exit:{badarg, _} ->
- {error,{eoptions, {inet_options, UserOpts}}}
- end.
-
-old_connect(Address, Port, Options, Timeout) ->
- ensure_old_ssl_started(),
- {ok, Pid} = ssl_broker:start_broker(connector),
- ssl_broker:connect(Pid, Address, Port, Options, Timeout).
-
-new_listen(Port, Options0) ->
- try
- {ok, Config} = handle_options(Options0, server),
- #config{cb={CbModule, _, _, _},inet_user=Options} = Config,
- case CbModule:listen(Port, Options) of
- {ok, ListenSocket} ->
- {ok, #sslsocket{pid = {ListenSocket, Config}, fd = new_ssl}};
- Err = {error, _} ->
- Err
- end
- catch
- Error = {error, _} ->
- Error
+ {error, {eoptions, {inet_options, UserOpts}}}
end.
-
-old_listen(Port, Options) ->
- ensure_old_ssl_started(),
- {ok, Pid} = ssl_broker:start_broker(listener),
- ssl_broker:listen(Pid, Port, Options).
handle_options(Opts0, _Role) ->
Opts = proplists:expand([{binary, [{mode, binary}]},
{list, [{mode, list}]}], Opts0),
-
ReuseSessionFun = fun(_, _, _, _) -> true end,
DefaultVerifyNoneFun =
@@ -711,7 +540,8 @@ handle_options(Opts0, _Role) ->
secure_renegotiate = handle_option(secure_renegotiate, Opts, false),
renegotiate_at = handle_option(renegotiate_at, Opts, ?DEFAULT_RENEGOTIATE_AT),
debug = handle_option(debug, Opts, []),
- hibernate_after = handle_option(hibernate_after, Opts, undefined)
+ hibernate_after = handle_option(hibernate_after, Opts, undefined),
+ erl_dist = handle_option(erl_dist, Opts, false)
},
CbInfo = proplists:get_value(cb_info, Opts, {gen_tcp, tcp, tcp_closed, tcp_error}),
@@ -720,7 +550,7 @@ handle_options(Opts0, _Role) ->
depth, cert, certfile, key, keyfile,
password, cacerts, cacertfile, dh, dhfile, ciphers,
debug, reuse_session, reuse_sessions, ssl_imp,
- cb_info, renegotiate_at, secure_renegotiate, hibernate_after],
+ cb_info, renegotiate_at, secure_renegotiate, hibernate_after, erl_dist],
SockOpts = lists:foldl(fun(Key, PropList) ->
proplists:delete(Key, PropList)
@@ -737,8 +567,6 @@ handle_option(OptionName, Opts, Default) ->
validate_option(versions, Versions) ->
validate_versions(Versions, Versions);
-validate_option(ssl_imp, Value) when Value == new; Value == old ->
- Value;
validate_option(verify, Value)
when Value == verify_none; Value == verify_peer ->
Value;
@@ -831,6 +659,9 @@ validate_option(hibernate_after, undefined) ->
undefined;
validate_option(hibernate_after, Value) when is_integer(Value), Value >= 0 ->
Value;
+validate_option(erl_dist,Value) when Value == true;
+ Value == false ->
+ Value;
validate_option(Opt, Value) ->
throw({error, {eoptions, {Opt, Value}}}).
@@ -878,7 +709,6 @@ emulated_options() ->
internal_inet_values() ->
[{packet_size,0},{packet, 0},{header, 0},{active, false},{mode,binary}].
- %%[{packet, ssl},{header, 0},{active, false},{mode,binary}].
socket_options(InetValues) ->
#socket_options{
@@ -939,47 +769,14 @@ cipher_suites(Version, Ciphers0) ->
no_format(Error) ->
lists:flatten(io_lib:format("No format string for error: \"~p\" available.", [Error])).
-
-%% Start old ssl port program if needed.
-ensure_old_ssl_started() ->
- case whereis(ssl_server) of
- undefined ->
- (catch supervisor:start_child(ssl_sup,
- {ssl_server, {ssl_server, start_link, []},
- permanent, 2000, worker, [ssl_server]}));
- _ ->
- ok
- end.
-
-%%%%%%%%%%%%%%%% Deprecated %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-ciphers() ->
- ensure_old_ssl_started(),
- case (catch ssl_server:ciphers()) of
- {'EXIT', _} ->
- {error, enotstarted};
- Res = {ok, _} ->
- Res
- end.
-
-version() ->
- ensure_old_ssl_started(),
- SSLVsn = ?VSN,
- {CompVsn, LibVsn} = case (catch ssl_server:version()) of
- {'EXIT', _} ->
- {"", ""};
- {ok, Vsns} ->
- Vsns
- end,
- {ok, {SSLVsn, CompVsn, LibVsn}}.
-
%% Only used to remove exit messages from old ssl
%% First is a nonsense clause to provide some
-%% backward compability for orber that uses this
+%% backward compatibility for orber that uses this
%% function in a none recommended way, but will
%% work correctly if a valid pid is returned.
+%% Deprcated to be removed in r16
pid(#sslsocket{fd = new_ssl}) ->
- whereis(ssl_connection_sup);
+ whereis(ssl_connection_sup);
pid(#sslsocket{pid = Pid}) ->
- Pid.
+ Pid.
diff --git a/lib/ssl/src/ssl_broker.erl b/lib/ssl/src/ssl_broker.erl
deleted file mode 100644
index 7ef88baf2b..0000000000
--- a/lib/ssl/src/ssl_broker.erl
+++ /dev/null
@@ -1,1188 +0,0 @@
-%%
-%% %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 : SSL broker
-
--module(ssl_broker).
--behaviour(gen_server).
-
-%% This module implements brokers for ssl. A broker is either a connector,
-%% an acceptor, or a listener. All brokers are children to ssl_broker_sup,
-%% to which they are linked. Each broker is also linked to ssl_server, and
-%% to its client.
-%%
-%% The purpose of the broker is to set up SSL connections through calls to
-%% ssl_server and gen_tcp. All control information goes to the server,
-%% while all data is exchanged directly between gen_tcp and the port program
-%% of the ssl_server.
-%%
-%% A broker is created by a call to start_broker/3 (do *not* use start_link/4
-%% - it is for ssl_broker_sup to call that one), and then call listen/3,
-%% accept/4, or connect/5.
-%%
-%% The following table shows all functions dependency on status, active
-%% mode etc.
-%%
-%% Permitted status transitions:
-%%
-%% nil -> open
-%% open -> closing | closed (termination)
-%% closing -> closed (termination)
-%%
-%% We are rather sloppy about nil, and consider open/closing == !closed,
-%% open/closing/closed === any etc.
-%%
-%%
-%% function/ valid mode new
-%% message status state
-%%
-%% calls
-%% -----
-%% recv open passive ditto
-%% send open any ditto
-%% transport_accept nil any open
-%% ssl_accept nil any open
-%% connect nil any open
-%% listen nil any open
-%% peername open/closing any ditto
-%% setopts open/closing any ditto
-%% getopts open/closing any ditto
-%% sockname open/closing any ditto
-%% peercert open/closing any ditto
-%% inhibit any any ditto
-%% release any any ditto
-%% close any any closed (1)
-%%
-%% info
-%% ----
-%% tcp open active ditto
-%% tcp_closed open | closing active closing
-%% tcp_error open | closing active closing
-%%
-%% (1) We just terminate.
-%%
-%% TODO
-%%
-%% XXX Timeouts are not checked (integer or infinity).
-%%
-%% XXX The collector thing is not gen_server compliant.
-%%
-%% NOTE: There are three different "modes": (a) passive or active mode,
-%% specified as {active, bool()}, and (b) list or binary mode, specified
-%% as {mode, list | binary}, and (c) encrypted or clear mode
-%%
-
--include("ssl_int.hrl").
-
-%% External exports
-
--export([start_broker/1, start_broker/2, start_link/3,
- transport_accept/3, ssl_accept/2,
- close/1, connect/5, connection_info/1, controlling_process/2,
- listen/3, recv/3, send/2, getopts/2, getopts/3, setopts/2,
- sockname/1, peername/1, peercert/1]).
-
--export([listen_prim/5, connect_prim/8,
- transport_accept_prim/5, ssl_accept_prim/6]).
-
-%% Internal exports
-
--export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- code_change/3, terminate/2, collector_init/1]).
-
--include("ssl_broker_int.hrl").
-
-%% start_broker(Type) -> {ok, Pid} | {error, Reason}
-%% start_broker(Type, GenOpts) -> {ok, Pid} | {error, Reason}
-%% Type = accept | connect | listen
-%% GenOpts = /standard gen_server options/
-%%
-%% This is the function to be called from the interface module ssl.erl.
-%% Links to the caller.
-%%
-start_broker(Type) ->
- start_broker(Type, []).
-
-start_broker(Type, GenOpts) ->
- case lists:member(Type, [listener, acceptor, connector]) of
- true ->
- case supervisor:start_child(ssl_broker_sup,
- [self(), Type, GenOpts]) of
- {ok, Pid} ->
- link(Pid),
- {ok, Pid};
- {error, Reason} ->
- {error, Reason}
- end;
- false ->
- {error, ebrokertype}
- end.
-
-%% start_link(Client, Type, GenOpts) -> {ok, Pid} | {error, Reason}
-%%
-%% Type = accept | connect | listen
-%% GenOpts = /standard gen_server options/
-%%
-%% This function is called by ssl_broker_sup and must *not* be called
-%% from an interface module (ssl.erl).
-
-start_link(Client, Type, GenOpts) ->
- gen_server:start_link(?MODULE, [Client, Type], GenOpts).
-
-
-%% accept(Pid, ListenSocket, Timeout) -> {ok, Socket} | {error, Reason}
-%%
-%% Types: Pid = pid() of acceptor
-%% ListenSocket = Socket = sslsocket()
-%% Timeout = timeout()
-%%
-%% accept(Pid, ListenSocket, Timeout)
-%% when is_pid(Pid), is_record(ListenSocket, sslsocket) ->
-%% Req = {accept, self(), ListenSocket, Timeout},
-%% gen_server:call(Pid, Req, infinity).
-
-%% transport_accept(Pid, ListenSocket, Timeout) -> {ok, Socket} |
-%% {error, Reason}
-%%
-%% Types: Pid = pid() of acceptor
-%% ListenSocket = Socket = sslsocket()
-%% Timeout = timeout()
-%%
-transport_accept(Pid, #sslsocket{} = ListenSocket, Timeout) when is_pid(Pid) ->
- Req = {transport_accept, self(), ListenSocket, Timeout},
- gen_server:call(Pid, Req, infinity).
-
-%% ssl_accept(Pid, Socket, Timeout) -> {ok, Socket} | {error, Reason}
-%%
-%% Types: Pid = pid() of acceptor
-%% ListenSocket = Socket = sslsocket()
-%% Timeout = timeout()
-%%
-ssl_accept(#sslsocket{pid = Pid} = Socket, Timeout) ->
- Req = {ssl_accept, self(), Socket, Timeout},
- gen_server:call(Pid, Req, infinity).
-
-%% close(Socket) -> ok | {error, Reason}
-%%
-%% Types: Socket = sslsocket() | pid()
-%%
-close(#sslsocket{pid = Pid}) ->
- close(Pid);
-close(Pid) when is_pid(Pid) ->
- gen_server:call(Pid, {close, self()}, infinity).
-
-%% connect(Pid, Address, Port, Opts, Timeout) -> {ok, Socket} | {error, Reason}
-%%
-%% Types: Pid = pid() of connector
-%% Address = string() | {byte(), byte(), byte(), byte()}
-%% Port = int()
-%% Opts = options()
-%% Timeout = timeout()
-%% Socket = sslsocket()
-%%
-connect(Pid, Address, Port, Opts, Timeout) when is_pid(Pid), is_list(Opts) ->
- case are_connect_opts(Opts) of
- true ->
- Req = {connect, self(), Address, Port, Opts, Timeout},
- gen_server:call(Pid, Req, infinity);
- false ->
- {error, eoptions}
- end.
-
-%%
-%% connection_info(Socket) -> {ok, {Protocol, Cipher} | {error, Reason}
-%%
-connection_info(#sslsocket{pid = Pid}) ->
- Req = {connection_info, self()},
- gen_server:call(Pid, Req, infinity).
-
-%% controlling_process(Socket, NewOwner) -> ok | {error, Reason}
-
-controlling_process(#sslsocket{pid = Pid}, NewOwner) when is_pid(NewOwner) ->
- case gen_server:call(Pid, {inhibit_msgs, self()}, infinity) of
- ok ->
- transfer_messages(Pid, NewOwner),
- gen_server:call(Pid, {release_msgs, self(), NewOwner}, infinity);
- Error ->
- Error
- end.
-
-%% listen(Pid, Port, Opts) -> {ok, ListenSocket} | {error, Reason}
-%%
-%% Types: Pid = pid() of listener
-%% Port = int()
-%% Opts = options()
-%% ListenSocket = sslsocket()
-%%
-listen(Pid, Port, Opts) when is_pid(Pid) ->
- case are_listen_opts(Opts) of
- true ->
- Req = {listen, self(), Port, Opts},
- gen_server:call(Pid, Req, infinity);
- false ->
- {error, eoptions}
- end.
-
-
-%%
-%% peername(Socket) -> {ok, {Address, Port}} | {error, Reason}
-%%
-peername(#sslsocket{pid = Pid}) ->
- Req = {peername, self()},
- gen_server:call(Pid, Req, infinity).
-
-
-%% recv(Socket, Length, Timeout) -> {ok, Data} | {error, Reason}
-%%
-%% Types: Socket = sslsocket()
-%% Length = Timeout = integer()
-%% Data = bytes() | binary()
-%%
-recv(#sslsocket{pid = Pid}, Length, Timeout) ->
- Req = {recv, self(), Length, Timeout},
- gen_server:call(Pid, Req, infinity).
-
-
-%% send(Socket, Data) -> ok | {error, Reason}
-%%
-%% Types: Socket = sslsocket()
-%%
-send(#sslsocket{pid = Pid}, Data) ->
- gen_server:call(Pid, {send, self(), Data}, infinity).
-
-
-%% getopts(Socket, OptTags) -> {ok, Opts} | {error, einval}
-%%
-%% Types: Pid = pid() of broker
-%% Timeout = timeout()
-%% OptTags = option_tags()
-%% Opts = options()
-%%
-getopts(Socket, OptTags) ->
- getopts(Socket, OptTags, infinity).
-
-getopts(#sslsocket{pid = Pid}, OptTags, Timeout) when is_list(OptTags) ->
- Req = {getopts, self(), OptTags},
- gen_server:call(Pid, Req, Timeout).
-
-
-%%
-%% setopts(Socket, Opts) -> ok | {error, Reason}
-%%
-setopts(#sslsocket{pid = Pid}, Opts) ->
- Req = {setopts, self(), Opts},
- gen_server:call(Pid, Req, infinity).
-
-%%
-%% sockname(Socket) -> {ok, {Address, Port}} | {error, Reason}
-%%
-sockname(#sslsocket{pid = Pid}) ->
- Req = {sockname, self()},
- gen_server:call(Pid, Req, infinity).
-
-
-%%
-%% peercert(Socket) -> {ok, Cert} | {error, Reason}
-%%
-peercert(#sslsocket{pid = Pid}) ->
- Req = {peercert, self()},
- gen_server:call(Pid, Req, infinity).
-
-%%
-%% INIT
-%%
-
-%% init
-%%
-init([Client, Type]) ->
- process_flag(trap_exit, true),
- link(Client),
- Debug = case application:get_env(ssl, edebug) of
- {ok, true} ->
- true;
- _ ->
- case application:get_env(ssl, debug) of
- {ok, true} ->
- true;
- _ ->
- os:getenv("ERL_SSL_DEBUG") =/= false
- end
- end,
- Server = whereis(ssl_server),
- if
- is_pid(Server) ->
- link(Server),
- debug1(Debug, Type, "in start, client = ~w", [Client]),
- {ok, #st{brokertype = Type, server = Server, client = Client,
- collector = Client, debug = Debug}};
- true ->
- {stop, no_ssl_server}
- end.
-
-
-%%
-%% HANDLE CALL
-%%
-
-%% recv - passive mode
-%%
-handle_call({recv, Client, Length, Timeout}, _From,
- #st{active = false, proxysock = Proxysock, status = Status} = St) ->
- debug(St, "recv: client = ~w~n", [Client]),
- if
- Status =/= open ->
- {reply, {error, closed}, St};
- true ->
- case gen_tcp:recv(Proxysock, Length, Timeout) of
- {ok, Data} ->
- {reply, {ok, Data}, St};
- {error, timeout} ->
- {reply, {error, timeout}, St};
- {error, Reason} ->
- {reply, {error, Reason}, St#st{status = closing}}
- end
- end;
-
-%% send
-%%
-handle_call({send, Client, Data}, _From, St) ->
- debug(St, "send: client = ~w~n", [Client]),
- if
- St#st.status =/= open ->
- {reply, {error, closed}, St};
- true ->
- case gen_tcp:send(St#st.proxysock, Data) of
- ok ->
- {reply, ok, St};
- {error, _Reason} ->
- {reply, {error, closed}, St#st{status = closing}}
- end
- end;
-
-%% transport_accept
-%%
-%% Client = pid of client
-%% ListenSocket = sslsocket()
-%%
-handle_call({transport_accept, Client, ListenSocket, Timeout}, _From, St) ->
- debug(St, "transport_accept: client = ~w, listensocket = ~w~n",
- [Client, ListenSocket]),
- case getopts(ListenSocket, tcp_listen_opt_tags(), ?DEF_TIMEOUT) of
- {ok, LOpts} ->
- case transport_accept_prim(
- ssl_server, ListenSocket#sslsocket.fd, LOpts, Timeout, St) of
- {ok, ThisSocket, NSt} ->
- {reply, {ok, ThisSocket}, NSt};
- {error, Reason, St} ->
- What = what(Reason),
- {stop, normal, {error, What}, St}
- end;
- {error, Reason} ->
- What = what(Reason),
- {stop, normal, {error, What}, St}
- end;
-
-%% ssl_accept
-%%
-%% Client = pid of client
-%% ListenSocket = sslsocket()
-%%
-handle_call({ssl_accept, Client, Socket, Timeout}, _From, St) ->
- debug(St, "ssl_accept: client = ~w, socket = ~w~n", [Client, Socket]),
- case ssl_accept_prim(ssl_server, gen_tcp, Client, St#st.opts, Timeout, St#st{thissock=Socket}) of
- {ok, Socket, NSt} ->
- {reply, ok, NSt};
- {error, Reason, St} ->
- What = what(Reason),
- {stop, normal, {error, What}, St}
- end;
-
-%% connect
-%%
-%% Client = client pid
-%% Address = hostname | ipstring | IP
-%% Port = integer()
-%% Opts = options()
-%%
-handle_call({connect, Client, Address, Port, Opts, Timeout}, _From, St) ->
- debug(St, "connect: client = ~w, address = ~p, port = ~w~n",
- [Client, Address, Port]),
- case connect_prim(ssl_server, gen_tcp, Client, Address, Port, Opts,
- Timeout, St) of
- {ok, Res, NSt} ->
- {reply, {ok, Res}, NSt};
- {error, Reason, NSt} ->
- What = what(Reason),
- {stop, normal, {error, What}, NSt}
- end;
-
-%% connection_info
-%%
-handle_call({connection_info, Client}, _From, St) ->
- debug(St, "connection_info: client = ~w~n", [Client]),
- Reply = ssl_server:connection_info(St#st.fd),
- {reply, Reply, St};
-
-%% close from client
-%%
-handle_call({close, Client}, _From, St) ->
- debug(St, "close: client = ~w~n", [Client]),
- %% Terminate
- {stop, normal, ok, St#st{status = closed}};
-
-%% listen
-%%
-%% Client = pid of client
-%% Port = int()
-%% Opts = options()
-%%
-handle_call({listen, Client, Port, Opts}, _From, St) ->
- debug(St, "listen: client = ~w, port = ~w~n",
- [Client, Port]),
- case listen_prim(ssl_server, Client, Port, Opts, St) of
- {ok, Res, NSt} ->
- {reply, {ok, Res}, NSt};
- {error, Reason, NSt} ->
- What = what(Reason),
- {stop, normal, {error, What}, NSt}
- end;
-
-%% peername
-%%
-handle_call({peername, Client}, _From, St) ->
- debug(St, "peername: client = ~w~n", [Client]),
- Reply = case ssl_server:peername(St#st.fd) of
- {ok, {Address, Port}} ->
- {ok, At} = inet_parse:ipv4_address(Address),
- {ok, {At, Port}};
- Error ->
- Error
- end,
- {reply, Reply, St};
-
-%% setopts
-%%
-handle_call({setopts, Client, Opts0}, _From, St0) ->
- debug(St0, "setopts: client = ~w~n", [Client]),
- OptsOK = case St0#st.brokertype of
- listener ->
- are_opts(fun is_tcp_listen_opt/1, Opts0);
- acceptor ->
- are_opts(fun is_tcp_accept_opt/1, Opts0);
- connector ->
- are_opts(fun is_tcp_connect_opt/1, Opts0)
- end,
- if
- OptsOK =:= false ->
- {reply, {error, eoptions}, St0};
- true ->
- Opts1 = lists:keydelete(nodelay, 1, Opts0),
- case inet:setopts(St0#st.proxysock, Opts1) of
- ok ->
- Opts2 = replace_opts(Opts1, St0#st.opts),
- Active = get_active(Opts2),
- St2 = St0#st{opts = Opts2,
- active = Active},
- case get_nodelay(Opts0) of
- empty ->
- {reply, ok, St2};
- Bool ->
- case setnodelay(ssl_server, St0, Bool) of
- ok ->
- Opts3 = replace_opts([{nodelay, Bool}],
- Opts2),
- St3 = St0#st{opts = Opts3,
- active = Active},
- {reply, ok, St3};
- {error, Reason} ->
- {reply, {error, Reason}, St2}
- end
- end;
- {error, Reason} ->
- {reply, {error, Reason}, St0}
- end
- end;
-
-%% sockname
-%%
-handle_call({sockname, Client}, _From, St) ->
- debug(St, "sockname: client = ~w~n", [Client]),
- Reply = case ssl_server:sockname(St#st.fd) of
- {ok, {Address, Port}} ->
- {ok, At} = inet_parse:ipv4_address(Address),
- {ok, {At, Port}};
- Error ->
- Error
- end,
- {reply, Reply, St};
-
-%% peercert
-%%
-handle_call({peercert, Client}, _From, St) ->
- debug(St, "peercert: client = ~w~n", [Client]),
- Reply = ssl_server:peercert(St#st.fd),
- {reply, Reply, St};
-
-%% inhibit msgs
-%%
-handle_call({inhibit_msgs, Client}, _From, #st{client = Client} = St) ->
- debug(St, "inhibit_msgs: client = ~w~n", [Client]),
- {ok, Collector} = start_collector(),
- {reply, ok, St#st{collector = Collector}};
-
-%% release msgs
-%%
-handle_call({release_msgs, Client, NewClient}, _From,
- #st{client = Client, collector = Collector} = St) ->
- debug(St, "release_msgs: client = ~w~n", [Client]),
- unlink(Client),
- link(NewClient),
- release_collector(Collector, NewClient),
- NSt = St#st{client = NewClient, collector = NewClient},
- {reply, ok, NSt};
-
-%% getopts
-%%
-handle_call({getopts, Client, OptTags}, _From, St) ->
- debug(St, "getopts: client = ~w~n", [Client]),
- Reply = case are_opt_tags(St#st.brokertype, OptTags) of
- true ->
- {ok, extract_opts(OptTags, St#st.opts)};
- _ ->
- {error, einval}
- end,
- {reply, Reply, St};
-
-%% bad call
-%%
-handle_call(Request, _From, St) ->
- debug(St, "++++ ssl_broker: bad call: ~w~n", [Request]),
- {reply, {error, {badcall, Request}}, St}.
-
-%%
-%% HANDLE CAST
-%%
-
-handle_cast(Request, St) ->
- debug(St, "++++ ssl_broker: bad cast: ~w~n", [Request]),
- {stop, {error, {badcast, Request}}, St}.
-
-%%
-%% HANDLE INFO
-%%
-
-%% tcp - active mode
-%%
-%% The collector is different from client only during change of
-%% controlling process.
-%%
-handle_info({tcp, Socket, Data},
- #st{active = Active, collector = Collector, status = open,
- proxysock = Socket, thissock = Thissock} = St)
- when Active =/= false ->
- debug(St, "tcp: socket = ~w~n", [Socket]),
- Msg = {ssl, Thissock, Data},
- Collector ! Msg,
- if
- Active =:= once ->
- {noreply, St#st{active = false}};
- true ->
- {noreply, St}
- end;
-
-%% tcp_closed - from proxy socket, active mode
-%%
-%%
-handle_info({tcp_closed, Socket},
- #st{active = Active, collector = Collector,
- proxysock = Socket, thissock = Thissock} = St)
- when Active =/= false ->
- debug(St, "tcp_closed: socket = ~w~n", [Socket]),
- Msg = {ssl_closed, Thissock},
- Collector ! Msg,
- if
- Active =:= once ->
- {noreply, St#st{status = closing, active = false}};
- true ->
- {noreply, St#st{status = closing}}
- end;
-
-%% tcp_error - from proxy socket, active mode
-%%
-%%
-handle_info({tcp_error, Socket, Reason},
- #st{active = Active, collector = Collector,
- proxysock = Socket} = St)
- when Active =/= false ->
- debug(St, "tcp_error: socket = ~w, reason = ~w~n", [Socket, Reason]),
- Msg = {ssl_error, Socket, Reason},
- Collector ! Msg,
- if
- Active =:= once ->
- {noreply, St#st{status = closing, active = false}};
- true ->
- {noreply, St#st{status = closing}}
- end;
-
-%% EXIT - from client
-%%
-%%
-handle_info({'EXIT', Client, Reason}, #st{client = Client} = St) ->
- debug(St, "exit client: client = ~w, reason = ~w~n", [Client, Reason]),
- {stop, normal, St#st{status = closed}}; % do not make noise
-
-%% EXIT - from server
-%%
-%%
-handle_info({'EXIT', Server, Reason}, #st{server = Server} = St) ->
- debug(St, "exit server: reason = ~w~n", [Reason]),
- {stop, Reason, St};
-
-%% handle info catch all
-%%
-handle_info(Info, St) ->
- debug(St, " bad info: ~w~n", [Info]),
- {stop, {error, {badinfo, Info}}, St}.
-
-
-%% terminate
-%%
-%%
-terminate(Reason, St) ->
- debug(St, "in terminate reason: ~w, state: ~w~n", [Reason, St]),
- ok.
-
-%% code_change
-%%
-%%
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%
-%% Primitive interface
-%%
-listen_prim(ServerName, Client, Port, Opts, St) ->
- LOpts = get_tcp_listen_opts(Opts),
- SSLOpts = get_ssl_opts(Opts),
- FlagStr =mk_ssl_optstr(SSLOpts),
- BackLog = get_backlog(LOpts),
- IP = get_ip(LOpts),
- case ssl_server:listen_prim(ServerName, IP, Port, FlagStr, BackLog) of
- {ok, ListenFd, _Port0} ->
- ThisSocket = #sslsocket{fd = ListenFd, pid = self()},
- StOpts = add_default_tcp_listen_opts(LOpts) ++
- add_default_ssl_opts(SSLOpts),
- NSt = St#st{fd = ListenFd,
- active = get_active(LOpts), % irrelevant for listen
- opts = StOpts,
- thissock = ThisSocket,
- status = open},
- debug(St, "listen: ok: client = ~w, listenfd = ~w~n",
- [Client, ListenFd]),
- {ok, ThisSocket, NSt};
- {error, Reason} ->
- {error, Reason, St}
- end.
-
-connect_prim(ServerName, TcpModule, Client, FAddress, FPort, Opts,
- Timeout, St) ->
- COpts = get_tcp_connect_opts(Opts),
- SSLOpts = get_ssl_opts(Opts),
- FlagStr = mk_ssl_optstr(SSLOpts),
- case inet:getaddr(FAddress, inet) of
- {ok, FIP} ->
- %% Timeout is gen_server timeout - hence catch
- LIP = get_ip(COpts),
- LPort = get_port(COpts),
- case (catch ssl_server:connect_prim(ServerName,
- LIP, LPort, FIP, FPort,
- FlagStr, Timeout)) of
- {ok, Fd, ProxyPort} ->
- case connect_proxy(ServerName, TcpModule, Fd,
- ProxyPort, COpts, Timeout) of
- {ok, Socket} ->
- ThisSocket = #sslsocket{fd = Fd, pid = self()},
- StOpts = add_default_tcp_connect_opts(COpts) ++
- add_default_ssl_opts(SSLOpts),
- NSt = St#st{fd = Fd,
- active = get_active(COpts),
- opts = StOpts,
- thissock = ThisSocket,
- proxysock = Socket,
- status = open},
- case get_nodelay(COpts) of
- true -> setnodelay(ServerName, NSt, true);
- _ -> ok
- end,
- debug(St, "connect: ok: client = ~w, fd = ~w~n",
- [Client, Fd]),
- {ok, ThisSocket, NSt};
- {error, Reason} ->
- {error, Reason, St}
- end;
- {'EXIT', Reason} ->
- {error, Reason, St};
- {error, Reason} ->
- {error, Reason, St}
- end;
- {error, Reason} ->
- {error, Reason, St}
- end.
-
-transport_accept_prim(ServerName, ListenFd, LOpts, Timeout, St) ->
- AOpts = get_tcp_accept_opts(LOpts),
- FlagStr = "",
- %% Timeout is gen_server timeout - hence catch.
- case (catch ssl_server:transport_accept_prim(ServerName, ListenFd,
- FlagStr, Timeout)) of
- {ok, Fd, ProxyPort} ->
- ThisSocket = #sslsocket{fd = Fd, pid = self()},
- NSt = St#st{fd = Fd,
- active = get_active(AOpts),
- opts = AOpts,
- thissock = ThisSocket,
- proxyport = ProxyPort,
- encrypted = false},
- debug(St, "transport_accept: ok: fd = ~w~n", [Fd]),
- {ok, ThisSocket, NSt};
- {'EXIT', Reason} ->
- debug(St, "transport_accept: EXIT: Reason = ~w~n", [Reason]),
- {error, Reason, St};
- {error, Reason} ->
- debug(St, "transport_accept: error: Reason = ~w~n", [Reason]),
- {error, Reason, St}
- end.
-
-ssl_accept_prim(ServerName, TcpModule, Client, LOpts, Timeout, St) ->
- FlagStr = [],
- SSLOpts = [],
- AOpts = get_tcp_accept_opts(LOpts),
- %% Timeout is gen_server timeout - hence catch.
- debug(St, "ssl_accept_prim: self() ~w Client ~w~n", [self(), Client]),
- Socket = St#st.thissock,
- Fd = Socket#sslsocket.fd,
- A = (catch ssl_server:ssl_accept_prim(ServerName, Fd, FlagStr, Timeout)),
- debug(St, "ssl_accept_prim: ~w~n", [A]),
- case A of
- ok ->
- B = connect_proxy(ServerName, TcpModule, Fd,
- St#st.proxyport, AOpts, Timeout),
- debug(St, "ssl_accept_prim: connect_proxy ~w~n", [B]),
- case B of
- {ok, Socket2} ->
- StOpts = add_default_tcp_accept_opts(AOpts) ++
- add_default_ssl_opts(SSLOpts),
- NSt = St#st{opts = StOpts,
- proxysock = Socket2,
- encrypted = true,
- status = open},
- case get_nodelay(AOpts) of
- true -> setnodelay(ServerName, NSt, true);
- _ -> ok
- end,
- debug(St, "transport_accept: ok: client = ~w, fd = ~w~n",
- [Client, Fd]),
- {ok, St#st.thissock, NSt};
- {error, Reason} ->
- {error, Reason, St}
- end;
- {'EXIT', Reason} ->
- {error, Reason, St};
- {error, Reason} ->
- {error, Reason, St}
- end.
-
-
-%%
-%% LOCAL FUNCTIONS
-%%
-
-%%
-%% connect_proxy(Fd, ProxyPort, TOpts, Timeout) -> {ok, Socket} |
-%% {error, Reason}
-%%
-connect_proxy(ServerName, TcpModule, Fd, ProxyPort, TOpts, Timeout) ->
- case TcpModule:connect({127, 0, 0, 1}, ProxyPort, TOpts, Timeout) of
- {ok, Socket} ->
- {ok, Port} = inet:port(Socket),
- A = ssl_server:proxy_join_prim(ServerName, Fd, Port),
- case A of
- ok ->
- {ok, Socket};
- Error ->
- Error
- end;
- Error ->
- Error
- end.
-
-
-setnodelay(ServerName, St, Bool) ->
- case ssl_server:setnodelay_prim(ServerName, St#st.fd, Bool) of
- ok ->
- case inet:setopts(St#st.proxysock, [{nodelay, Bool}]) of
- ok ->
- ok;
- {error, Reason} ->
- {error, Reason}
- end;
- {error, Reason} ->
- {error, Reason}
- end.
-
-%%
-%% start_collector()
-%%
-%% A collector is a little process that keeps messages during change of
-%% controlling process.
-%% XXX This is not gen_server compliant :-(.
-%%
-start_collector() ->
- Pid = spawn_link(?MODULE, collector_init, [self()]),
- {ok, Pid}.
-
-%%
-%% release_collector(Collector, NewOwner)
-%%
-release_collector(Collector, NewOwner) ->
- Collector ! {release, self(), NewOwner},
- receive
- %% Reap collector
- {'EXIT', Collector, normal} ->
- ok
- end.
-
-%%
-%% collector_init(Broker) -> void()
-%%
-collector_init(Broker) ->
- receive
- {release, Broker, NewOwner} ->
- transfer_messages(Broker, NewOwner)
- end.
-
-%%
-%% transfer_messages(Pid, NewOwner) -> void()
-%%
-transfer_messages(Pid, NewOwner) ->
- receive
- {ssl, Sock, Data} ->
- NewOwner ! {ssl, Sock, Data},
- transfer_messages(Pid, NewOwner);
- {ssl_closed, Sock} ->
- NewOwner ! {ssl_closed, Sock},
- transfer_messages(Pid, NewOwner);
- {ssl_error, Sock, Reason} ->
- NewOwner ! {ssl_error, Sock, Reason},
- transfer_messages(Pid, NewOwner)
- after 0 ->
- ok
- end.
-
-%%
-%% debug(St, Format, Args) -> void() - printouts
-%%
-debug(St, Format, Args) ->
- debug1(St#st.debug, St#st.brokertype, Format, Args).
-
-debug1(true, Type, Format0, Args) ->
- {_MS, S, MiS} = erlang:now(),
- Secs = S rem 100,
- MiSecs = MiS div 1000,
- Format = "++++ ~3..0w:~3..0w ssl_broker (~w)[~w]: " ++ Format0,
- io:format(Format, [Secs, MiSecs, self(), Type| Args]);
-debug1(_, _, _, _) ->
- ok.
-
-%%
-%% what(Reason) -> What
-%%
-what(Reason) when is_atom(Reason) ->
- Reason;
-what({'EXIT', Reason}) ->
- what(Reason);
-what({What, _Where}) when is_atom(What) ->
- What;
-what(Reason) ->
- Reason.
-
-
-%%
-%% OPTIONS
-%%
-%% Note that `accept' has no options when invoked, but get all its options
-%% by inheritance from `listen'.
-%%
-
-are_opt_tags(listener, OptTags) ->
- is_subset(OptTags, listen_opt_tags());
-are_opt_tags(acceptor, OptTags) ->
- is_subset(OptTags, accept_opt_tags());
-are_opt_tags(connector, OptTags) ->
- is_subset(OptTags, connect_opt_tags()).
-
-listen_opt_tags() ->
- tcp_listen_opt_tags() ++ ssl_opt_tags().
-
-accept_opt_tags() ->
- tcp_gen_opt_tags().
-
-connect_opt_tags() ->
- tcp_gen_opt_tags() ++ ssl_opt_tags().
-
-tcp_listen_opt_tags() ->
- tcp_gen_opt_tags() ++ tcp_listen_only_opt_tags().
-
-tcp_gen_opt_tags() ->
- %% All except `reuseaddr' and `deliver'.
- [nodelay, active, packet, mode, header].
-
-tcp_listen_only_opt_tags() ->
- [ip, backlog].
-
-ssl_opt_tags() ->
- %% XXX Should remove cachetimeout.
- [verify, depth, certfile, password, cacertfile, ciphers, cachetimeout].
-
-%% Options
-
-%%
-%% are_*_opts(Opts) -> boolean()
-%%
-are_connect_opts(Opts) ->
- are_opts(fun is_connect_opt/1, Opts).
-
-are_listen_opts(Opts) ->
- are_opts(fun is_listen_opt/1, Opts).
-
-are_opts(F, Opts) ->
- lists:all(F, transform_opts(Opts)).
-
-%%
-%% get_*_opts(Opts) -> Value
-%%
-get_tcp_accept_opts(Opts) ->
- [O || O <- transform_opts(Opts), is_tcp_accept_opt(O)].
-
-get_tcp_connect_opts(Opts) ->
- [O || O <- transform_opts(Opts), is_tcp_connect_opt(O)].
-
-get_tcp_listen_opts(Opts) ->
- [O || O <- transform_opts(Opts), is_tcp_listen_opt(O)].
-
-get_ssl_opts(Opts) ->
- [O || O <- transform_opts(Opts), is_ssl_opt(O)].
-
-get_active(Opts) ->
- get_tagged_opt(active, Opts, true).
-
-get_backlog(Opts) ->
- get_tagged_opt(backlog, Opts, ?DEF_BACKLOG).
-
-get_ip(Opts) ->
- get_tagged_opt(ip, Opts, {0, 0, 0, 0}).
-
-get_port(Opts) ->
- get_tagged_opt(port, Opts, 0).
-
-get_nodelay(Opts) ->
- get_tagged_opt(nodelay, Opts, empty).
-
-%%
-%% add_default_*_opts(Opts) -> NOpts
-%%
-
-add_default_tcp_accept_opts(Opts) ->
- add_default_opts(Opts, default_tcp_accept_opts()).
-
-add_default_tcp_connect_opts(Opts) ->
- add_default_opts(Opts, default_tcp_connect_opts()).
-
-add_default_tcp_listen_opts(Opts) ->
- add_default_opts(Opts, default_tcp_listen_opts()).
-
-add_default_ssl_opts(Opts) ->
- add_default_opts(Opts, default_ssl_opts()).
-
-add_default_opts(Opts, DefOpts) ->
- TOpts = transform_opts(Opts),
- TOpts ++ [DP || {DTag, _DVal} = DP <- DefOpts,
- not lists:keymember(DTag, 1, TOpts)].
-
-default_tcp_accept_opts() ->
- [O || O <- default_opts(), is_tcp_accept_opt(O)].
-
-default_tcp_connect_opts() ->
- [O || O <- default_opts(), is_tcp_connect_opt(O)].
-
-default_tcp_listen_opts() ->
- [O || O <- default_opts(), is_tcp_listen_opt(O)].
-
-default_ssl_opts() ->
- [O || O <- default_opts(), is_ssl_opt(O)].
-
-default_opts() ->
- [{mode, list}, {packet, 0}, {nodelay, false}, {active, true},
- {backlog, ?DEF_BACKLOG}, {ip, {0, 0, 0, 0}},
- {verify, 0}, {depth, 1}].
-
-
-%% Transform from old to new options, and also from old gen_tcp
-%% options to new ones. All returned options are tagged options.
-%%
-transform_opts(Opts) ->
- lists:flatmap(fun transform_opt/1, Opts).
-
-transform_opt(binary) -> [{mode, binary}];
-transform_opt(list) -> [{mode, list}];
-transform_opt({packet, raw}) -> [{packet, 0}];
-transform_opt(raw) -> [];
-transform_opt(Opt) -> [Opt].
-
-%% NOTE: The is_*_opt/1 functions must be applied on transformed options
-%% only.
-
-is_connect_opt(Opt) ->
- is_tcp_connect_opt(Opt) or is_ssl_opt(Opt).
-
-is_listen_opt(Opt) ->
- is_tcp_listen_opt(Opt) or is_ssl_opt(Opt).
-
-is_tcp_accept_opt(Opt) ->
- is_tcp_gen_opt(Opt).
-
-is_tcp_connect_opt(Opt) ->
- is_tcp_gen_opt(Opt) or is_tcp_connect_only_opt(Opt).
-
-is_tcp_listen_opt(Opt) ->
- is_tcp_gen_opt(Opt) or is_tcp_listen_only_opt(Opt).
-
-%% General options supported by gen_tcp: All except `reuseaddr' and
-%% `deliver'.
-is_tcp_gen_opt({mode, list}) -> true;
-is_tcp_gen_opt({mode, binary}) -> true;
-is_tcp_gen_opt({header, Sz}) when is_integer(Sz), 0 =< Sz -> true;
-is_tcp_gen_opt({packet, Sz}) when is_integer(Sz), 0 =< Sz, Sz =< 4-> true;
-is_tcp_gen_opt({packet, sunrm}) -> true;
-is_tcp_gen_opt({packet, asn1}) -> true;
-is_tcp_gen_opt({packet, cdr}) -> true;
-is_tcp_gen_opt({packet, fcgi}) -> true;
-is_tcp_gen_opt({packet, line}) -> true;
-is_tcp_gen_opt({packet, tpkt}) -> true;
-is_tcp_gen_opt({packet, http}) -> true;
-is_tcp_gen_opt({packet, httph}) -> true;
-is_tcp_gen_opt({nodelay, true}) -> true;
-is_tcp_gen_opt({nodelay, false}) -> true;
-is_tcp_gen_opt({active, true}) -> true;
-is_tcp_gen_opt({active, false}) -> true;
-is_tcp_gen_opt({active, once}) -> true;
-is_tcp_gen_opt({keepalive, true}) -> true;
-is_tcp_gen_opt({keepalive, false}) -> true;
-is_tcp_gen_opt({ip, Addr}) -> is_ip_address(Addr);
-is_tcp_gen_opt(_Opt) -> false.
-
-is_tcp_listen_only_opt({backlog, Size}) when is_integer(Size), 0 =< Size ->
- true;
-is_tcp_listen_only_opt({reuseaddr, Bool}) when is_boolean(Bool) ->
- true;
-is_tcp_listen_only_opt(_Opt) -> false.
-
-is_tcp_connect_only_opt({port, Port}) when is_integer(Port), 0 =< Port -> true;
-is_tcp_connect_only_opt(_Opt) -> false.
-
-%% SSL options
-
-is_ssl_opt({verify, Code}) when 0 =< Code, Code =< 2 -> true;
-is_ssl_opt({depth, Depth}) when 0 =< Depth -> true;
-is_ssl_opt({certfile, String}) -> is_string(String);
-is_ssl_opt({keyfile, String}) -> is_string(String);
-is_ssl_opt({password, String}) -> is_string(String);
-is_ssl_opt({cacertfile, String}) -> is_string(String);
-is_ssl_opt({ciphers, String}) -> is_string(String);
-is_ssl_opt({cachetimeout, Timeout}) when Timeout >= 0 -> true;
-is_ssl_opt(_Opt) -> false.
-
-%% Various types
-is_string(String) when is_list(String) ->
- lists:all(fun (C) when is_integer(C), 0 =< C, C =< 255 -> true;
- (_C) -> false end,
- String);
-is_string(_) ->
- false.
-
-is_ip_address(Addr) when tuple_size(Addr) =:= 4 ->
- is_string(tuple_to_list(Addr));
-is_ip_address(Addr) when is_list(Addr) ->
- is_string(Addr);
-is_ip_address(_) ->
- false.
-
-get_tagged_opt(Tag, Opts, Default) ->
- case lists:keysearch(Tag, 1, Opts) of
- {value, {_, Value}} ->
- Value;
- _Other ->
- Default
- end.
-
-%%
-%% mk_ssl_optstr(Opts) -> string()
-%%
-%% Makes a "command line" string of SSL options
-%%
-mk_ssl_optstr(Opts) ->
- lists:flatten([mk_one_ssl_optstr(O) || O <- Opts]).
-
-mk_one_ssl_optstr({verify, Code}) ->
- [" -verify ", integer_to_list(Code)];
-mk_one_ssl_optstr({depth, Depth}) ->
- [" -depth ", integer_to_list(Depth)];
-mk_one_ssl_optstr({certfile, String}) ->
- [" -certfile ", String];
-mk_one_ssl_optstr({keyfile, String}) ->
- [" -keyfile ", String];
-mk_one_ssl_optstr({password, String}) ->
- [" -password ", String];
-mk_one_ssl_optstr({cacertfile, String}) ->
- [" -cacertfile ", String];
-mk_one_ssl_optstr({ciphers, String}) ->
- [" -ciphers ", String];
-mk_one_ssl_optstr({cachetimeout, Timeout}) ->
- [" -cachetimeout ", integer_to_list(Timeout)];
-mk_one_ssl_optstr(_) ->
- "".
-
-extract_opts(OptTags, Opts) ->
- [O || O = {Tag,_} <- Opts, lists:member(Tag, OptTags)].
-
-replace_opts(NOpts, Opts) ->
- lists:foldl(fun({Key, Val}, Acc) ->
- lists:keyreplace(Key, 1, Acc, {Key, Val});
- %% XXX Check. Patch from Chandrashekhar Mullaparthi.
- (binary, Acc) ->
- lists:keyreplace(mode, 1, Acc, {mode, binary})
- end,
- Opts, NOpts).
-
-%% Misc
-
-is_subset(A, B) ->
- [] =:= A -- B.
diff --git a/lib/ssl/src/ssl_broker_int.hrl b/lib/ssl/src/ssl_broker_int.hrl
deleted file mode 100644
index b791485725..0000000000
--- a/lib/ssl/src/ssl_broker_int.hrl
+++ /dev/null
@@ -1,38 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-
-%% Purpose: record definitions shared between ssl_prim.erl and ssl_broker.erl
-
--record(st, {brokertype = nil, % connector | listener | acceptor
- server = nil, % pid of ssl_server
- client = nil, % client pid
- collector = nil, % client pid, or collector during change of
- % controlling process
- fd = nil, % fd of "external" socket in port program
- active = true, % true | false | once
- opts = [], % options
- thissock = nil, % this sslsocket
- proxysock = nil, % local proxy socket within Erlang
- proxyport = nil, % local port for proxy within Erlang
- status = nil, % open | closing | closed
- encrypted = false, %
- debug = false %
- }).
diff --git a/lib/ssl/src/ssl_broker_sup.erl b/lib/ssl/src/ssl_broker_sup.erl
deleted file mode 100644
index 6d56a5fcf6..0000000000
--- a/lib/ssl/src/ssl_broker_sup.erl
+++ /dev/null
@@ -1,46 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-
-%%% Purpose : Supervisor for brokers
-
--module(ssl_broker_sup).
-
--behaviour(supervisor).
-
--export([start_link/0]).
-
-%% supervisor callbacks
--export([init/1]).
-
-start_link() ->
- supervisor:start_link({local, ssl_broker_sup}, ssl_broker_sup,
- []).
-
-init([]) ->
- {ok, {{simple_one_for_one, 10, 3600},
- [{ssl_broker,
- {ssl_broker, start_link, []},
- temporary,
- 100,
- worker,
- [ssl_broker]}
- ]}}.
-
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl
index 8c0c2bfa5d..422ea6404b 100644
--- a/lib/ssl/src/ssl_certificate.erl
+++ b/lib/ssl/src/ssl_certificate.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The 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,9 +30,9 @@
-include("ssl_internal.hrl").
-include_lib("public_key/include/public_key.hrl").
--export([trusted_cert_and_path/2,
- certificate_chain/2,
- file_to_certificats/1,
+-export([trusted_cert_and_path/3,
+ certificate_chain/3,
+ file_to_certificats/2,
validate_extension/3,
is_valid_extkey_usage/2,
is_valid_key_usage/2,
@@ -46,14 +46,14 @@
%%====================================================================
%%--------------------------------------------------------------------
--spec trusted_cert_and_path([der_cert()], certdb_ref()) ->
+-spec trusted_cert_and_path([der_cert()], db_handle(), 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) ->
+trusted_cert_and_path(CertChain, CertDbHandle, CertDbRef) ->
Path = [Cert | _] = lists:reverse(CertChain),
OtpCert = public_key:pkix_decode_cert(Cert, otp),
SignedAndIssuerID =
@@ -66,7 +66,7 @@ trusted_cert_and_path(CertChain, CertDbRef) ->
{ok, IssuerId} ->
{other, IssuerId};
{error, issuer_not_found} ->
- case find_issuer(OtpCert, no_candidate) of
+ case find_issuer(OtpCert, no_candidate, CertDbHandle) of
{ok, IssuerId} ->
{other, IssuerId};
Other ->
@@ -82,7 +82,7 @@ trusted_cert_and_path(CertChain, CertDbRef) ->
{self, _} when length(Path) == 1 ->
{selfsigned_peer, Path};
{_ ,{SerialNr, Issuer}} ->
- case ssl_manager:lookup_trusted_cert(CertDbRef, SerialNr, Issuer) of
+ case ssl_manager:lookup_trusted_cert(CertDbHandle, CertDbRef, SerialNr, Issuer) of
{ok, {BinCert,_}} ->
{BinCert, Path};
_ ->
@@ -92,23 +92,23 @@ trusted_cert_and_path(CertChain, CertDbRef) ->
end.
%%--------------------------------------------------------------------
--spec certificate_chain(undefined | binary(), certdb_ref()) ->
+-spec certificate_chain(undefined | binary(), db_handle(), certdb_ref()) ->
{error, no_cert} | {ok, [der_cert()]}.
%%
%% Description: Return the certificate chain to send to peer.
%%--------------------------------------------------------------------
-certificate_chain(undefined, _CertsDbRef) ->
+certificate_chain(undefined, _, _) ->
{error, no_cert};
-certificate_chain(OwnCert, CertsDbRef) ->
+certificate_chain(OwnCert, CertDbHandle, CertsDbRef) ->
ErlCert = public_key:pkix_decode_cert(OwnCert, otp),
- certificate_chain(ErlCert, OwnCert, CertsDbRef, [OwnCert]).
+ certificate_chain(ErlCert, OwnCert, CertDbHandle, CertsDbRef, [OwnCert]).
%%--------------------------------------------------------------------
--spec file_to_certificats(string()) -> [der_cert()].
+-spec file_to_certificats(string(), term()) -> [der_cert()].
%%
%% Description: Return list of DER encoded certificates.
%%--------------------------------------------------------------------
-file_to_certificats(File) ->
- {ok, List} = ssl_manager:cache_pem_file(File),
+file_to_certificats(File, DbHandle) ->
+ {ok, List} = ssl_manager:cache_pem_file(File, DbHandle),
[Bin || {'Certificate', Bin, not_encrypted} <- List].
%%--------------------------------------------------------------------
-spec validate_extension(term(), #'Extension'{} | {bad_cert, atom()} | valid,
@@ -180,7 +180,7 @@ signature_type(?'id-dsa-with-sha1') ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-certificate_chain(OtpCert, _Cert, CertsDbRef, Chain) ->
+certificate_chain(OtpCert, _Cert, CertDbHandle, CertsDbRef, Chain) ->
IssuerAndSelfSigned =
case public_key:pkix_is_self_signed(OtpCert) of
true ->
@@ -191,11 +191,11 @@ certificate_chain(OtpCert, _Cert, CertsDbRef, Chain) ->
case IssuerAndSelfSigned of
{_, true = SelfSigned} ->
- certificate_chain(CertsDbRef, Chain, ignore, ignore, SelfSigned);
+ certificate_chain(CertDbHandle, CertsDbRef, Chain, ignore, ignore, SelfSigned);
{{error, issuer_not_found}, SelfSigned} ->
- case find_issuer(OtpCert, no_candidate) of
+ case find_issuer(OtpCert, no_candidate, CertDbHandle) of
{ok, {SerialNr, Issuer}} ->
- certificate_chain(CertsDbRef, Chain,
+ certificate_chain(CertDbHandle, CertsDbRef, Chain,
SerialNr, Issuer, SelfSigned);
_ ->
%% Guess the the issuer must be the root
@@ -205,19 +205,19 @@ certificate_chain(OtpCert, _Cert, CertsDbRef, Chain) ->
{ok, lists:reverse(Chain)}
end;
{{ok, {SerialNr, Issuer}}, SelfSigned} ->
- certificate_chain(CertsDbRef, Chain, SerialNr, Issuer, SelfSigned)
+ certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, SelfSigned)
end.
-certificate_chain(_CertsDbRef, Chain, _SerialNr, _Issuer, true) ->
+certificate_chain(_,_, Chain, _SerialNr, _Issuer, true) ->
{ok, lists:reverse(Chain)};
-certificate_chain(CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned) ->
- case ssl_manager:lookup_trusted_cert(CertsDbRef,
+certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned) ->
+ case ssl_manager:lookup_trusted_cert(CertDbHandle, CertsDbRef,
SerialNr, Issuer) of
{ok, {IssuerCert, ErlCert}} ->
ErlCert = public_key:pkix_decode_cert(IssuerCert, otp),
certificate_chain(ErlCert, IssuerCert,
- CertsDbRef, [IssuerCert | Chain]);
+ CertDbHandle, CertsDbRef, [IssuerCert | Chain]);
_ ->
%% The trusted cert may be obmitted from the chain as the
%% counter part needs to have it anyway to be able to
@@ -227,8 +227,8 @@ certificate_chain(CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned) ->
{ok, lists:reverse(Chain)}
end.
-find_issuer(OtpCert, PrevCandidateKey) ->
- case ssl_manager:issuer_candidate(PrevCandidateKey) of
+find_issuer(OtpCert, PrevCandidateKey, CertDbHandle) ->
+ case ssl_manager:issuer_candidate(PrevCandidateKey, CertDbHandle) of
no_more_candidates ->
{error, issuer_not_found};
{Key, {_Cert, ErlCertCandidate}} ->
@@ -236,7 +236,7 @@ find_issuer(OtpCert, PrevCandidateKey) ->
true ->
public_key:pkix_issuer_id(ErlCertCandidate, self);
false ->
- find_issuer(OtpCert, Key)
+ find_issuer(OtpCert, Key, CertDbHandle)
end
end.
diff --git a/lib/ssl/src/ssl_certificate_db.erl b/lib/ssl/src/ssl_certificate_db.erl
index 3eceefa304..0560a02110 100644
--- a/lib/ssl/src/ssl_certificate_db.erl
+++ b/lib/ssl/src/ssl_certificate_db.erl
@@ -26,8 +26,8 @@
-include_lib("public_key/include/public_key.hrl").
-export([create/0, remove/1, add_trusted_certs/3,
- remove_trusted_certs/2, lookup_trusted_cert/3, issuer_candidate/1,
- lookup_cached_certs/1, cache_pem_file/4, uncache_pem_file/2, lookup/2]).
+ remove_trusted_certs/2, lookup_trusted_cert/4, issuer_candidate/2,
+ lookup_cached_certs/2, cache_pem_file/4, uncache_pem_file/2, lookup/2]).
-type time() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}.
@@ -36,19 +36,19 @@
%%====================================================================
%%--------------------------------------------------------------------
--spec create() -> certdb_ref().
+-spec create() -> [db_handle()].
%%
%% Description: Creates a new certificate db.
-%% Note: lookup_trusted_cert/3 may be called from any process but only
+%% Note: lookup_trusted_cert/4 may be called from any process but only
%% the process that called create may call the other functions.
%%--------------------------------------------------------------------
create() ->
- [ets:new(certificate_db_name(), [named_table, set, protected]),
- ets:new(ssl_file_to_ref, [named_table, set, protected]),
+ [ets:new(ssl_otp_certificate_db, [set, protected]),
+ ets:new(ssl_file_to_ref, [set, protected]),
ets:new(ssl_pid_to_file, [bag, private])].
%%--------------------------------------------------------------------
--spec remove(certdb_ref()) -> term().
+-spec remove([db_handle()]) -> term().
%%
%% Description: Removes database db
%%--------------------------------------------------------------------
@@ -56,7 +56,7 @@ remove(Dbs) ->
lists:foreach(fun(Db) -> true = ets:delete(Db) end, Dbs).
%%--------------------------------------------------------------------
--spec lookup_trusted_cert(reference(), serialnumber(), issuer()) ->
+-spec lookup_trusted_cert(db_handle(), certdb_ref(), serialnumber(), issuer()) ->
undefined | {ok, {der_cert(), #'OTPCertificate'{}}}.
%%
@@ -64,19 +64,19 @@ remove(Dbs) ->
%% <SerialNumber, Issuer>. Ref is used as it is specified
%% for each connection which certificates are trusted.
%%--------------------------------------------------------------------
-lookup_trusted_cert(Ref, SerialNumber, Issuer) ->
- case lookup({Ref, SerialNumber, Issuer}, certificate_db_name()) of
+lookup_trusted_cert(DbHandle, Ref, SerialNumber, Issuer) ->
+ case lookup({Ref, SerialNumber, Issuer}, DbHandle) of
undefined ->
undefined;
[Certs] ->
{ok, Certs}
end.
-lookup_cached_certs(File) ->
- ets:lookup(certificate_db_name(), {file, File}).
+lookup_cached_certs(DbHandle, File) ->
+ ets:lookup(DbHandle, {file, File}).
%%--------------------------------------------------------------------
--spec add_trusted_certs(pid(), string() | {der, list()}, certdb_ref()) -> {ok, certdb_ref()}.
+-spec add_trusted_certs(pid(), string() | {der, list()}, [db_handle()]) -> {ok, [db_handle()]}.
%%
%% Description: Adds the trusted certificates from file <File> to the
%% runtime database. Returns Ref that should be handed to lookup_trusted_cert
@@ -100,7 +100,7 @@ add_trusted_certs(Pid, File, [CertsDb, FileToRefDb, PidToFileDb]) ->
insert(Pid, File, PidToFileDb),
{ok, Ref}.
%%--------------------------------------------------------------------
--spec cache_pem_file(pid(), string(), time(), certdb_ref()) -> term().
+-spec cache_pem_file(pid(), string(), time(), [db_handle()]) -> term().
%%
%% Description: Cache file as binary in DB
%%--------------------------------------------------------------------
@@ -112,7 +112,7 @@ cache_pem_file(Pid, File, Time, [CertsDb, _FileToRefDb, PidToFileDb]) ->
{ok, Content}.
%--------------------------------------------------------------------
--spec uncache_pem_file(string(), certdb_ref()) -> no_return().
+-spec uncache_pem_file(string(), [db_handle()]) -> no_return().
%%
%% Description: If a cached file is no longer valid (changed on disk)
%% we must terminate the connections using the old file content, and
@@ -130,7 +130,7 @@ uncache_pem_file(File, [_CertsDb, _FileToRefDb, PidToFileDb]) ->
%%--------------------------------------------------------------------
--spec remove_trusted_certs(pid(), certdb_ref()) -> term().
+-spec remove_trusted_certs(pid(), [db_handle()]) -> term().
%%
%% Description: Removes trusted certs originating from
@@ -161,7 +161,7 @@ remove_trusted_certs(Pid, [CertsDb, FileToRefDb, PidToFileDb]) ->
end.
%%--------------------------------------------------------------------
--spec issuer_candidate(no_candidate | cert_key() | {file, term()}) ->
+-spec issuer_candidate(no_candidate | cert_key() | {file, term()}, term()) ->
{cert_key(),{der_cert(), #'OTPCertificate'{}}} | no_more_candidates.
%%
%% Description: If a certificat does not define its issuer through
@@ -169,32 +169,30 @@ remove_trusted_certs(Pid, [CertsDb, FileToRefDb, PidToFileDb]) ->
%% try to find the issuer in the database over known
%% certificates.
%%--------------------------------------------------------------------
-issuer_candidate(no_candidate) ->
- Db = certificate_db_name(),
+issuer_candidate(no_candidate, Db) ->
case ets:first(Db) of
'$end_of_table' ->
no_more_candidates;
{file, _} = Key ->
- issuer_candidate(Key);
+ issuer_candidate(Key, Db);
Key ->
[Cert] = lookup(Key, Db),
{Key, Cert}
end;
-issuer_candidate(PrevCandidateKey) ->
- Db = certificate_db_name(),
+issuer_candidate(PrevCandidateKey, Db) ->
case ets:next(Db, PrevCandidateKey) of
'$end_of_table' ->
no_more_candidates;
{file, _} = Key ->
- issuer_candidate(Key);
+ issuer_candidate(Key, Db);
Key ->
[Cert] = lookup(Key, Db),
{Key, Cert}
end.
%%--------------------------------------------------------------------
--spec lookup(term(), term()) -> term() | undefined.
+-spec lookup(term(), db_handle()) -> term() | undefined.
%%
%% Description: Looks up an element in a certificat <Db>.
%%--------------------------------------------------------------------
@@ -212,9 +210,6 @@ lookup(Key, Db) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-certificate_db_name() ->
- ssl_otp_certificate_db.
-
insert(Key, Data, Db) ->
true = ets:insert(Db, {Key, Data}).
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index 574e1e9468..c772697f1d 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -34,7 +34,6 @@
-include("ssl_record.hrl").
-include("ssl_cipher.hrl").
-include("ssl_internal.hrl").
--include("ssl_int.hrl").
-include_lib("public_key/include/public_key.hrl").
%% Internal application API
@@ -70,6 +69,7 @@
%% {{md5_hash, sha_hash}, {prev_md5, prev_sha}} (binary())
tls_handshake_hashes, % see above
tls_cipher_texts, % list() received but not deciphered yet
+ cert_db, %
session, % #session{} from ssl_handshake.hrl
session_cache, %
session_cache_cb, %
@@ -107,12 +107,14 @@
%%====================================================================
%%--------------------------------------------------------------------
--spec send(pid(), iolist()) -> ok | {error, reason()}.
+-spec send(pid(), iodata()) -> ok | {error, reason()}.
%%
%% Description: Sends data over the ssl connection
%%--------------------------------------------------------------------
send(Pid, Data) ->
sync_send_all_state_event(Pid, {application_data,
+ %% iolist_to_binary should really
+ %% be called iodata_to_binary()
erlang:iolist_to_binary(Data)}, infinity).
%%--------------------------------------------------------------------
@@ -124,11 +126,11 @@ send(Pid, Data) ->
recv(Pid, Length, Timeout) ->
sync_send_all_state_event(Pid, {recv, Length}, Timeout).
%%--------------------------------------------------------------------
--spec connect(host(), port_num(), port(), {#ssl_options{}, #socket_options{}},
+-spec connect(host(), inet:port_number(), port(), {#ssl_options{}, #socket_options{}},
pid(), tuple(), timeout()) ->
{ok, #sslsocket{}} | {error, reason()}.
%%
-%% Description: Connect to a ssl server.
+%% Description: Connect to an ssl server.
%%--------------------------------------------------------------------
connect(Host, Port, Socket, Options, User, CbInfo, Timeout) ->
try start_fsm(client, Host, Port, Socket, Options, User, CbInfo,
@@ -138,11 +140,11 @@ connect(Host, Port, Socket, Options, User, CbInfo, Timeout) ->
{error, ssl_not_started}
end.
%%--------------------------------------------------------------------
--spec ssl_accept(port_num(), port(), {#ssl_options{}, #socket_options{}},
+-spec ssl_accept(inet:port_number(), port(), {#ssl_options{}, #socket_options{}},
pid(), tuple(), timeout()) ->
{ok, #sslsocket{}} | {error, reason()}.
%%
-%% Description: Performs accept on a ssl listen socket. e.i. performs
+%% Description: Performs accept on an ssl listen socket. e.i. performs
%% ssl handshake.
%%--------------------------------------------------------------------
ssl_accept(Port, Socket, Opts, User, CbInfo, Timeout) ->
@@ -182,7 +184,7 @@ socket_control(Socket, Pid, CbModule) ->
%%--------------------------------------------------------------------
-spec close(pid()) -> ok | {error, reason()}.
%%
-%% Description: Close a ssl connection
+%% Description: Close an ssl connection
%%--------------------------------------------------------------------
close(ConnectionPid) ->
case sync_send_all_state_event(ConnectionPid, close) of
@@ -209,14 +211,14 @@ shutdown(ConnectionPid, How) ->
new_user(ConnectionPid, User) ->
sync_send_all_state_event(ConnectionPid, {new_user, User}).
%%--------------------------------------------------------------------
--spec sockname(pid()) -> {ok, {tuple(), port_num()}} | {error, reason()}.
+-spec sockname(pid()) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, reason()}.
%%
%% Description: Same as inet:sockname/1
%%--------------------------------------------------------------------
sockname(ConnectionPid) ->
sync_send_all_state_event(ConnectionPid, sockname).
%%--------------------------------------------------------------------
--spec peername(pid()) -> {ok, {tuple(), port_num()}} | {error, reason()}.
+-spec peername(pid()) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, reason()}.
%%
%% Description: Same as inet:peername/1
%%--------------------------------------------------------------------
@@ -274,7 +276,7 @@ renegotiation(ConnectionPid) ->
%%====================================================================
%%--------------------------------------------------------------------
--spec start_link(atom(), host(), port_num(), port(), list(), pid(), tuple()) ->
+-spec start_link(atom(), host(), inet:port_number(), port(), list(), pid(), tuple()) ->
{ok, pid()} | ignore | {error, reason()}.
%%
%% Description: Creates a gen_fsm process which calls Module:init/1 to
@@ -303,12 +305,13 @@ init([Role, Host, Port, Socket, {SSLOpts0, _} = Options,
Hashes0 = ssl_handshake:init_hashes(),
try ssl_init(SSLOpts0, Role) of
- {ok, Ref, CacheRef, OwnCert, Key, DHParams} ->
+ {ok, Ref, CertDbHandle, CacheHandle, OwnCert, Key, DHParams} ->
Session = State0#state.session,
State = State0#state{tls_handshake_hashes = Hashes0,
session = Session#session{own_certificate = OwnCert},
cert_db_ref = Ref,
- session_cache = CacheRef,
+ cert_db = CertDbHandle,
+ session_cache = CacheHandle,
private_key = Key,
diffie_hellman_params = DHParams},
{ok, hello, State, get_timeout(State)}
@@ -498,9 +501,10 @@ certify(#certificate{asn1_certificates = []},
certify(#certificate{} = Cert,
#state{negotiated_version = Version,
role = Role,
+ cert_db = CertDbHandle,
cert_db_ref = CertDbRef,
ssl_options = Opts} = State) ->
- case ssl_handshake:certify(Cert, CertDbRef, Opts#ssl_options.depth,
+ case ssl_handshake:certify(Cert, CertDbHandle, CertDbRef, Opts#ssl_options.depth,
Opts#ssl_options.verify,
Opts#ssl_options.verify_fun, Role) of
{PeerCert, PublicKeyInfo} ->
@@ -857,23 +861,23 @@ handle_sync_event({set_opts, Opts0}, _From, StateName,
#state{socket_options = Opts1,
socket = Socket,
user_data_buffer = Buffer} = State0) ->
- Opts = set_socket_opts(Socket, Opts0, Opts1, []),
+ {Reply, Opts} = set_socket_opts(Socket, Opts0, Opts1, []),
State1 = State0#state{socket_options = Opts},
if
Opts#socket_options.active =:= false ->
- {reply, ok, StateName, State1, get_timeout(State1)};
+ {reply, Reply, StateName, State1, get_timeout(State1)};
Buffer =:= <<>>, Opts1#socket_options.active =:= false ->
%% Need data, set active once
{Record, State2} = next_record_if_active(State1),
case next_state(StateName, Record, State2) of
{next_state, StateName, State, Timeout} ->
- {reply, ok, StateName, State, Timeout};
+ {reply, Reply, StateName, State, Timeout};
{stop, Reason, State} ->
{stop, Reason, State}
end;
Buffer =:= <<>> ->
%% Active once already set
- {reply, ok, StateName, State1, get_timeout(State1)};
+ {reply, Reply, StateName, State1, get_timeout(State1)};
true ->
case application_data(<<>>, State1) of
Stop = {stop,_,_} ->
@@ -881,7 +885,7 @@ handle_sync_event({set_opts, Opts0}, _From, StateName,
{Record, State2} ->
case next_state(StateName, Record, State2) of
{next_state, StateName, State, Timeout} ->
- {reply, ok, StateName, State, Timeout};
+ {reply, Reply, StateName, State, Timeout};
{stop, Reason, State} ->
{stop, Reason, State}
end
@@ -939,17 +943,23 @@ handle_info({Protocol, _, Data}, StateName,
handle_info({CloseTag, Socket}, _StateName,
#state{socket = Socket, close_tag = CloseTag,
- negotiated_version = Version, host = Host,
- port = Port, socket_options = Opts,
+ negotiated_version = Version,
+ socket_options = Opts,
user_application = {_Mon,Pid}, from = From,
- role = Role, session = Session} = State) ->
- %% Debug option maybe, the user do NOT want to see these in their logs
- %% error_logger:info_report("SSL: Peer did not send close notify alert."),
+ role = Role} = State) ->
+ %% Note that as of TLS 1.1,
+ %% failure to properly close a connection no longer requires that a
+ %% session not be resumed. This is a change from TLS 1.0 to conform
+ %% with widespread implementation practice.
case Version of
{1, N} when N >= 1 ->
ok;
_ ->
- invalidate_session(Role, Host, Port, Session)
+ %% As invalidate_sessions here causes performance issues,
+ %% we will conform to the widespread implementation
+ %% practice and go aginst the spec
+ %%invalidate_session(Role, Host, Port, Session)
+ ok
end,
alert_user(Opts#socket_options.active, Pid, From,
?ALERT_REC(?WARNING, ?CLOSE_NOTIFY), Role),
@@ -1022,7 +1032,8 @@ code_change(_OldVsn, StateName, State, _Extra) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-start_fsm(Role, Host, Port, Socket, Opts, User, {CbModule, _,_, _} = CbInfo,
+start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = false},_} = Opts,
+ User, {CbModule, _,_, _} = CbInfo,
Timeout) ->
try
{ok, Pid} = ssl_connection_sup:start_child([Role, Host, Port, Socket,
@@ -1033,22 +1044,43 @@ start_fsm(Role, Host, Port, Socket, Opts, User, {CbModule, _,_, _} = CbInfo,
catch
error:{badmatch, {error, _} = Error} ->
Error
+ end;
+
+start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = true},_} = Opts,
+ User, {CbModule, _,_, _} = CbInfo,
+ Timeout) ->
+ try
+ {ok, Pid} = ssl_connection_sup:start_child_dist([Role, Host, Port, Socket,
+ Opts, User, CbInfo]),
+ {ok, SslSocket} = socket_control(Socket, Pid, CbModule),
+ ok = handshake(SslSocket, Timeout),
+ {ok, SslSocket}
+ catch
+ error:{badmatch, {error, _} = Error} ->
+ Error
end.
ssl_init(SslOpts, Role) ->
- {ok, CertDbRef, CacheRef, OwnCert} = init_certificates(SslOpts, Role),
+
+ init_manager_name(SslOpts#ssl_options.erl_dist),
+
+ {ok, CertDbRef, CertDbHandle, CacheHandle, OwnCert} = init_certificates(SslOpts, Role),
PrivateKey =
- init_private_key(SslOpts#ssl_options.key, SslOpts#ssl_options.keyfile,
+ init_private_key(CertDbHandle, SslOpts#ssl_options.key, SslOpts#ssl_options.keyfile,
SslOpts#ssl_options.password, Role),
- DHParams = init_diffie_hellman(SslOpts#ssl_options.dh, SslOpts#ssl_options.dhfile, Role),
- {ok, CertDbRef, CacheRef, OwnCert, PrivateKey, DHParams}.
+ DHParams = init_diffie_hellman(CertDbHandle, SslOpts#ssl_options.dh, SslOpts#ssl_options.dhfile, Role),
+ {ok, CertDbRef, CertDbHandle, CacheHandle, OwnCert, PrivateKey, DHParams}.
+init_manager_name(false) ->
+ put(ssl_manager, ssl_manager);
+init_manager_name(true) ->
+ put(ssl_manager, ssl_manager_dist).
init_certificates(#ssl_options{cacerts = CaCerts,
cacertfile = CACertFile,
certfile = CertFile,
cert = Cert}, Role) ->
- {ok, CertDbRef, CacheRef} =
+ {ok, CertDbRef, CertDbHandle, CacheHandle} =
try
Certs = case CaCerts of
undefined ->
@@ -1056,44 +1088,44 @@ init_certificates(#ssl_options{cacerts = CaCerts,
_ ->
{der, CaCerts}
end,
- {ok, _, _} = ssl_manager:connection_init(Certs, Role)
+ {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(Cert, CertDbRef, CertDbHandle, CacheHandle, CertFile, Role).
-init_certificates(undefined, CertDbRef, CacheRef, "", _) ->
- {ok, CertDbRef, CacheRef, undefined};
+init_certificates(undefined, CertDbRef, CertDbHandle, CacheHandle, "", _) ->
+ {ok, CertDbRef, CertDbHandle, CacheHandle, undefined};
-init_certificates(undefined, CertDbRef, CacheRef, CertFile, client) ->
+init_certificates(undefined, CertDbRef, CertDbHandle, CacheHandle, CertFile, client) ->
try
- [OwnCert] = ssl_certificate:file_to_certificats(CertFile),
- {ok, CertDbRef, CacheRef, OwnCert}
+ [OwnCert] = ssl_certificate:file_to_certificats(CertFile, CertDbHandle),
+ {ok, CertDbRef, CertDbHandle, CacheHandle, OwnCert}
catch _Error:_Reason ->
- {ok, CertDbRef, CacheRef, undefined}
+ {ok, CertDbRef, CertDbHandle, CacheHandle, undefined}
end;
-init_certificates(undefined, CertDbRef, CacheRef, CertFile, server) ->
+init_certificates(undefined, CertDbRef, CertDbHandle, CacheRef, CertFile, server) ->
try
- [OwnCert] = ssl_certificate:file_to_certificats(CertFile),
- {ok, CertDbRef, CacheRef, OwnCert}
+ [OwnCert] = ssl_certificate:file_to_certificats(CertFile, CertDbHandle),
+ {ok, CertDbRef, CertDbHandle, CacheRef, OwnCert}
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_certificates(Cert, CertDbRef, CertDbHandle, CacheRef, _, _) ->
+ {ok, CertDbRef, CertDbHandle, CacheRef, Cert}.
-init_private_key(undefined, "", _Password, _Client) ->
+init_private_key(_, undefined, "", _Password, _Client) ->
undefined;
-init_private_key(undefined, KeyFile, Password, _) ->
+init_private_key(DbHandle, undefined, KeyFile, Password, _) ->
try
- {ok, List} = ssl_manager:cache_pem_file(KeyFile),
+ {ok, List} = ssl_manager:cache_pem_file(KeyFile, DbHandle),
[PemEntry] = [PemEntry || PemEntry = {PKey, _ , _} <- List,
- PKey =:= 'RSAPrivateKey' orelse
+ PKey =:= 'RSAPrivateKey' orelse
PKey =:= 'DSAPrivateKey'],
public_key:pem_entry_decode(PemEntry, Password)
catch
@@ -1102,9 +1134,9 @@ init_private_key(undefined, KeyFile, Password, _) ->
erlang:get_stacktrace())
end;
-init_private_key({rsa, PrivateKey}, _, _,_) ->
+init_private_key(_,{rsa, PrivateKey}, _, _,_) ->
public_key:der_decode('RSAPrivateKey', PrivateKey);
-init_private_key({dsa, PrivateKey},_,_,_) ->
+init_private_key(_,{dsa, PrivateKey},_,_,_) ->
public_key:der_decode('DSAPrivateKey', PrivateKey).
-spec(handle_file_error(_,_,_,_,_,_) -> no_return()).
@@ -1120,15 +1152,15 @@ file_error(Line, Error, Reason, File, Throw, Stack) ->
error_logger:error_report(Report),
throw(Throw).
-init_diffie_hellman(Params, _,_) when is_binary(Params)->
+init_diffie_hellman(_,Params, _,_) when is_binary(Params)->
public_key:der_decode('DHParameter', Params);
-init_diffie_hellman(_,_, client) ->
+init_diffie_hellman(_,_,_, client) ->
undefined;
-init_diffie_hellman(_,undefined, _) ->
+init_diffie_hellman(_,_,undefined, _) ->
?DEFAULT_DIFFIE_HELLMAN_PARAMS;
-init_diffie_hellman(_, DHParamFile, server) ->
+init_diffie_hellman(DbHandle,_, DHParamFile, server) ->
try
- {ok, List} = ssl_manager:cache_pem_file(DHParamFile),
+ {ok, List} = ssl_manager:cache_pem_file(DHParamFile,DbHandle),
case [Entry || Entry = {'DHParameter', _ , _} <- List] of
[Entry] ->
public_key:pem_entry_decode(Entry);
@@ -1172,11 +1204,12 @@ certify_client(#state{client_certificate_requested = true, role = client,
connection_states = ConnectionStates0,
transport_cb = Transport,
negotiated_version = Version,
+ cert_db = CertDbHandle,
cert_db_ref = CertDbRef,
session = #session{own_certificate = OwnCert},
socket = Socket,
tls_handshake_hashes = Hashes0} = State) ->
- Certificate = ssl_handshake:certificate(OwnCert, CertDbRef, client),
+ Certificate = ssl_handshake:certificate(OwnCert, CertDbHandle, CertDbRef, client),
{BinCert, ConnectionStates1, Hashes1} =
encode_handshake(Certificate, Version, ConnectionStates0, Hashes0),
Transport:send(Socket, BinCert),
@@ -1357,9 +1390,10 @@ certify_server(#state{transport_cb = Transport,
negotiated_version = Version,
connection_states = ConnectionStates,
tls_handshake_hashes = Hashes,
+ cert_db = CertDbHandle,
cert_db_ref = CertDbRef,
session = #session{own_certificate = OwnCert}} = State) ->
- case ssl_handshake:certificate(OwnCert, CertDbRef, server) of
+ case ssl_handshake:certificate(OwnCert, CertDbHandle, CertDbRef, server) of
CertMsg = #certificate{} ->
{BinCertMsg, NewConnectionStates, NewHashes} =
encode_handshake(CertMsg, Version, ConnectionStates, Hashes),
@@ -1446,12 +1480,13 @@ rsa_key_exchange(_, _) ->
request_client_cert(#state{ssl_options = #ssl_options{verify = verify_peer},
connection_states = ConnectionStates0,
+ cert_db = CertDbHandle,
cert_db_ref = CertDbRef,
tls_handshake_hashes = Hashes0,
negotiated_version = Version,
socket = Socket,
transport_cb = Transport} = State) ->
- Msg = ssl_handshake:certificate_request(ConnectionStates0, CertDbRef),
+ Msg = ssl_handshake:certificate_request(ConnectionStates0, CertDbHandle, CertDbRef),
{BinMsg, ConnectionStates1, Hashes1} =
encode_handshake(Msg, Version, ConnectionStates0, Hashes0),
Transport:send(Socket, BinMsg),
@@ -1764,7 +1799,8 @@ format_reply(binary, _, N, Data) when N > 0 -> % Header mode
format_reply(binary, _, _, Data) ->
Data;
format_reply(list, Packet, _, Data)
- when Packet == http; Packet == {http, headers}; Packet == http_bin; Packet == {http_bin, headers} ->
+ when Packet == http; Packet == {http, headers}; Packet == http_bin; Packet == {http_bin, headers}; Packet == httph;
+ Packet == httph_bin->
Data;
format_reply(list, _,_, Data) ->
binary_to_list(Data).
@@ -2032,31 +2068,69 @@ get_socket_opts(Socket, [active | Tags], SockOpts, Acc) ->
get_socket_opts(Socket, Tags, SockOpts,
[{active, SockOpts#socket_options.active} | Acc]);
get_socket_opts(Socket, [Tag | Tags], SockOpts, Acc) ->
- case inet:getopts(Socket, [Tag]) of
+ try inet:getopts(Socket, [Tag]) of
{ok, [Opt]} ->
get_socket_opts(Socket, Tags, SockOpts, [Opt | Acc]);
{error, Error} ->
- {error, Error}
- end.
+ {error, {eoptions, {inet_option, Tag, Error}}}
+ catch
+ %% So that inet behavior does not crash our process
+ _:Error -> {error, {eoptions, {inet_option, Tag, Error}}}
+ end;
+get_socket_opts(_,Opts, _,_) ->
+ {error, {eoptions, {inet_option, Opts, function_clause}}}.
set_socket_opts(_, [], SockOpts, []) ->
- SockOpts;
+ {ok, SockOpts};
set_socket_opts(Socket, [], SockOpts, Other) ->
%% Set non emulated options
- inet:setopts(Socket, Other),
- SockOpts;
-set_socket_opts(Socket, [{mode, Mode}| Opts], SockOpts, Other) ->
+ try inet:setopts(Socket, Other) of
+ ok ->
+ {ok, SockOpts};
+ {error, InetError} ->
+ {{error, {eoptions, {inet_options, Other, InetError}}}, SockOpts}
+ catch
+ _:Error ->
+ %% So that inet behavior does not crash our process
+ {{error, {eoptions, {inet_options, Other, Error}}}, SockOpts}
+ end;
+
+set_socket_opts(Socket, [{mode, Mode}| Opts], SockOpts, Other) when Mode == list; Mode == binary ->
set_socket_opts(Socket, Opts,
SockOpts#socket_options{mode = Mode}, Other);
-set_socket_opts(Socket, [{packet, Packet}| Opts], SockOpts, Other) ->
+set_socket_opts(_, [{mode, _} = Opt| _], SockOpts, _) ->
+ {{error, {eoptions, {inet_opt, Opt}}}, SockOpts};
+set_socket_opts(Socket, [{packet, Packet}| Opts], SockOpts, Other) when Packet == raw;
+ Packet == 0;
+ Packet == 1;
+ Packet == 2;
+ Packet == 4;
+ Packet == asn1;
+ Packet == cdr;
+ Packet == sunrm;
+ Packet == fcgi;
+ Packet == tpkt;
+ Packet == line;
+ Packet == http;
+ Packet == httph;
+ Packet == http_bin;
+ Packet == httph_bin ->
set_socket_opts(Socket, Opts,
SockOpts#socket_options{packet = Packet}, Other);
-set_socket_opts(Socket, [{header, Header}| Opts], SockOpts, Other) ->
+set_socket_opts(_, [{packet, _} = Opt| _], SockOpts, _) ->
+ {{error, {eoptions, {inet_opt, Opt}}}, SockOpts};
+set_socket_opts(Socket, [{header, Header}| Opts], SockOpts, Other) when is_integer(Header) ->
set_socket_opts(Socket, Opts,
SockOpts#socket_options{header = Header}, Other);
-set_socket_opts(Socket, [{active, Active}| Opts], SockOpts, Other) ->
+set_socket_opts(_, [{header, _} = Opt| _], SockOpts, _) ->
+ {{error,{eoptions, {inet_opt, Opt}}}, SockOpts};
+set_socket_opts(Socket, [{active, Active}| Opts], SockOpts, Other) when Active == once;
+ Active == true;
+ Active == false ->
set_socket_opts(Socket, Opts,
SockOpts#socket_options{active = Active}, Other);
+set_socket_opts(_, [{active, _} = Opt| _], SockOpts, _) ->
+ {{error, {eoptions, {inet_opt, Opt}} }, SockOpts};
set_socket_opts(Socket, [Opt | Opts], SockOpts, Other) ->
set_socket_opts(Socket, Opts, SockOpts, [Opt | Other]).
diff --git a/lib/ssl/src/ssl_connection_sup.erl b/lib/ssl/src/ssl_connection_sup.erl
index e9328d5f7c..78cfda5e63 100644
--- a/lib/ssl/src/ssl_connection_sup.erl
+++ b/lib/ssl/src/ssl_connection_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The 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,8 +26,8 @@
-behaviour(supervisor).
%% API
--export([start_link/0]).
--export([start_child/1]).
+-export([start_link/0, start_link_dist/0]).
+-export([start_child/1, start_child_dist/1]).
%% Supervisor callback
-export([init/1]).
@@ -38,9 +38,15 @@
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+start_link_dist() ->
+ supervisor:start_link({local, ssl_connection_sup_dist}, ?MODULE, []).
+
start_child(Args) ->
supervisor:start_child(?MODULE, Args).
+start_child_dist(Args) ->
+ supervisor:start_child(ssl_connection_sup_dist, Args).
+
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
diff --git a/lib/ssl/src/ssl_dist_sup.erl b/lib/ssl/src/ssl_dist_sup.erl
new file mode 100644
index 0000000000..c1912401d7
--- /dev/null
+++ b/lib/ssl/src/ssl_dist_sup.erl
@@ -0,0 +1,84 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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_dist_sup).
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/0]).
+
+%% Supervisor callback
+-export([init/1]).
+
+%%%=========================================================================
+%%% API
+%%%=========================================================================
+
+-spec start_link() -> {ok, pid()} | ignore | {error, term()}.
+
+start_link() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+%%%=========================================================================
+%%% Supervisor callback
+%%%=========================================================================
+-spec init([]) -> {ok, {SupFlags :: tuple(), [ChildSpec :: tuple()]}}.
+
+init([]) ->
+ SessionCertManager = session_and_cert_manager_child_spec(),
+ ConnetionManager = connection_manager_child_spec(),
+ ProxyServer = proxy_server_child_spec(),
+
+ {ok, {{one_for_all, 10, 3600}, [SessionCertManager, ConnetionManager,
+ ProxyServer]}}.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+session_and_cert_manager_child_spec() ->
+ Opts = ssl_sup:manager_opts(),
+ Name = ssl_manager_dist,
+ StartFunc = {ssl_manager, start_link_dist, [Opts]},
+ Restart = permanent,
+ Shutdown = 4000,
+ Modules = [ssl_manager],
+ Type = worker,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
+connection_manager_child_spec() ->
+ Name = ssl_connection_dist,
+ StartFunc = {ssl_connection_sup, start_link_dist, []},
+ Restart = permanent,
+ Shutdown = 4000,
+ Modules = [ssl_connection],
+ Type = supervisor,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
+proxy_server_child_spec() ->
+ Name = ssl_tls_dist_proxy,
+ StartFunc = {ssl_tls_dist_proxy, start_link, []},
+ Restart = permanent,
+ Shutdown = 4000,
+ Modules = [ssl_tls_dist_proxy],
+ Type = worker,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 1f4c44d115..f873a6a913 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -31,14 +31,16 @@
-include_lib("public_key/include/public_key.hrl").
-export([master_secret/4, client_hello/6, server_hello/4, hello/4,
- hello_request/0, certify/6, certificate/3,
+ hello_request/0, certify/7, certificate/4,
client_certificate_verify/5, certificate_verify/5,
- certificate_request/2, key_exchange/2, server_key_exchange_hash/2,
+ certificate_request/3, 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]).
+-export([dec_hello_extensions/2]).
+
-type tls_handshake() :: #client_hello{} | #server_hello{} |
#server_hello_done{} | #certificate{} | #certificate_request{} |
#client_key_exchange{} | #finished{} | #certificate_verify{} |
@@ -48,7 +50,7 @@
%% Internal application API
%%====================================================================
%%--------------------------------------------------------------------
--spec client_hello(host(), port_num(), #connection_states{},
+-spec client_hello(host(), inet:port_number(), #connection_states{},
#ssl_options{}, boolean(), der_cert()) -> #client_hello{}.
%%
%% Description: Creates a client hello message.
@@ -106,7 +108,7 @@ hello_request() ->
%%--------------------------------------------------------------------
-spec hello(#server_hello{} | #client_hello{}, #ssl_options{},
- #connection_states{} | {port_num(), #session{}, cache_ref(),
+ #connection_states{} | {inet:port_number(), #session{}, db_handle(),
atom(), #connection_states{}, binary()},
boolean()) -> {tls_version(), session_id(), #connection_states{}}|
{tls_version(), {resumed | new, #session{}},
@@ -173,13 +175,13 @@ hello(#client_hello{client_version = ClientVersion, random = Random,
end.
%%--------------------------------------------------------------------
--spec certify(#certificate{}, term(), integer() | nolimit,
+-spec certify(#certificate{}, db_handle(), certdb_ref(), integer() | nolimit,
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,
+certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
MaxPathLen, _Verify, VerifyFunAndState, Role) ->
[PeerCert | _] = ASN1Certs,
@@ -208,7 +210,7 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbRef,
end,
{TrustedErlCert, CertPath} =
- ssl_certificate:trusted_cert_and_path(ASN1Certs, CertDbRef),
+ ssl_certificate:trusted_cert_and_path(ASN1Certs, CertDbHandle, CertDbRef),
case public_key:pkix_path_validation(TrustedErlCert,
CertPath,
@@ -222,13 +224,13 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbRef,
end.
%%--------------------------------------------------------------------
--spec certificate(der_cert(), term(), client | server) -> #certificate{} | #alert{}.
+-spec certificate(der_cert(), db_handle(), certdb_ref(), client | server) -> #certificate{} | #alert{}.
%%
%% Description: Creates a certificate message.
%%--------------------------------------------------------------------
-certificate(OwnCert, CertDbRef, client) ->
+certificate(OwnCert, CertDbHandle, CertDbRef, client) ->
Chain =
- case ssl_certificate:certificate_chain(OwnCert, CertDbRef) of
+ case ssl_certificate:certificate_chain(OwnCert, CertDbHandle, CertDbRef) of
{ok, CertChain} ->
CertChain;
{error, _} ->
@@ -239,8 +241,8 @@ certificate(OwnCert, CertDbRef, client) ->
end,
#certificate{asn1_certificates = Chain};
-certificate(OwnCert, CertDbRef, server) ->
- case ssl_certificate:certificate_chain(OwnCert, CertDbRef) of
+certificate(OwnCert, CertDbHandle, CertDbRef, server) ->
+ case ssl_certificate:certificate_chain(OwnCert, CertDbHandle, CertDbRef) of
{ok, Chain} ->
#certificate{asn1_certificates = Chain};
{error, _} ->
@@ -302,17 +304,17 @@ certificate_verify(Signature, {?'id-dsa' = Algorithm, PublicKey, PublicKeyParams
%%--------------------------------------------------------------------
--spec certificate_request(#connection_states{}, certdb_ref()) ->
+-spec certificate_request(#connection_states{}, db_handle(), certdb_ref()) ->
#certificate_request{}.
%%
%% Description: Creates a certificate_request message, called by the server.
%%--------------------------------------------------------------------
-certificate_request(ConnectionStates, CertDbRef) ->
+certificate_request(ConnectionStates, CertDbHandle, CertDbRef) ->
#connection_state{security_parameters =
#security_parameters{cipher_suite = CipherSuite}} =
ssl_record:pending_connection_state(ConnectionStates, read),
Types = certificate_types(CipherSuite),
- Authorities = certificate_authorities(CertDbRef),
+ Authorities = certificate_authorities(CertDbHandle, CertDbRef),
#certificate_request{
certificate_types = Types,
certificate_authorities = Authorities
@@ -383,8 +385,9 @@ master_secret(Version, #session{master_secret = Mastersecret},
ConnectionStates, Role)
catch
exit:Reason ->
- error_logger:error_report("Key calculation failed due to ~p",
- [Reason]),
+ Report = io_lib:format("Key calculation failed due to ~p",
+ [Reason]),
+ error_logger:error_report(Report),
?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE)
end;
@@ -400,8 +403,9 @@ master_secret(Version, PremasterSecret, ConnectionStates, Role) ->
SecParams, ConnectionStates, Role)
catch
exit:Reason ->
- error_logger:error_report("Master secret calculation failed"
- " due to ~p", [Reason]),
+ Report = io_lib:format("Master secret calculation failed"
+ " due to ~p", [Reason]),
+ error_logger:error_report(Report),
?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE)
end.
@@ -910,9 +914,12 @@ dec_hello_extensions(<<?UINT16(?RENEGOTIATION_EXT), ?UINT16(Len), Info:Len/binar
end,
dec_hello_extensions(Rest, [{renegotiation_info,
#renegotiation_info{renegotiated_connection = RenegotiateInfo}} | Acc]);
-dec_hello_extensions(<<?UINT16(_), ?UINT16(Len), _Unknown:Len, Rest/binary>>, Acc) ->
+
+%% Ignore data following the ClientHello (i.e.,
+%% extensions) if not understood.
+dec_hello_extensions(<<?UINT16(_), ?UINT16(Len), _Unknown:Len/binary, Rest/binary>>, Acc) ->
dec_hello_extensions(Rest, Acc);
-%% Need this clause?
+%% This theoretically should not happen if the protocol is followed, but if it does it is ignored.
dec_hello_extensions(_, Acc) ->
Acc.
@@ -1071,8 +1078,8 @@ certificate_types({KeyExchange, _, _, _})
certificate_types(_) ->
<<?BYTE(?RSA_SIGN)>>.
-certificate_authorities(CertDbRef) ->
- Authorities = certificate_authorities_from_db(CertDbRef),
+certificate_authorities(CertDbHandle, CertDbRef) ->
+ Authorities = certificate_authorities_from_db(CertDbHandle, CertDbRef),
Enc = fun(#'OTPCertificate'{tbsCertificate=TBSCert}) ->
OTPSubj = TBSCert#'OTPTBSCertificate'.subject,
DNEncodedBin = public_key:pkix_encode('Name', OTPSubj, otp),
@@ -1084,18 +1091,18 @@ certificate_authorities(CertDbRef) ->
end,
list_to_binary([Enc(Cert) || {_, Cert} <- Authorities]).
-certificate_authorities_from_db(CertDbRef) ->
- certificate_authorities_from_db(CertDbRef, no_candidate, []).
+certificate_authorities_from_db(CertDbHandle, CertDbRef) ->
+ certificate_authorities_from_db(CertDbHandle, CertDbRef, no_candidate, []).
-certificate_authorities_from_db(CertDbRef, PrevKey, Acc) ->
- case ssl_manager:issuer_candidate(PrevKey) of
+certificate_authorities_from_db(CertDbHandle,CertDbRef, PrevKey, Acc) ->
+ case ssl_manager:issuer_candidate(PrevKey, CertDbHandle) of
no_more_candidates ->
lists:reverse(Acc);
{{CertDbRef, _, _} = Key, Cert} ->
- certificate_authorities_from_db(CertDbRef, Key, [Cert|Acc]);
+ certificate_authorities_from_db(CertDbHandle, CertDbRef, Key, [Cert|Acc]);
{Key, _Cert} ->
%% skip certs not from this ssl connection
- certificate_authorities_from_db(CertDbRef, Key, Acc)
+ certificate_authorities_from_db(CertDbHandle, CertDbRef, Key, Acc)
end.
digitally_signed(Hash, #'RSAPrivateKey'{} = Key) ->
diff --git a/lib/ssl/src/ssl_int.hrl b/lib/ssl/src/ssl_int.hrl
deleted file mode 100644
index 3686deffce..0000000000
--- a/lib/ssl/src/ssl_int.hrl
+++ /dev/null
@@ -1,99 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-
-%% op codes commands are in capital and reply codes in lower case
-
--define(CONNECT, 1).
--define(CONNECT_WAIT, 2).
--define(CONNECT_REP, 3).
--define(CONNECT_ERR, 4).
-
--define(TERMINATE, 5).
--define(CLOSE, 6).
-
--define(LISTEN, 7).
--define(LISTEN_REP, 8).
--define(LISTEN_ERR, 9).
-
--define(TRANSPORT_ACCEPT, 10).
--define(NOACCEPT, 11).
--define(TRANSPORT_ACCEPT_REP, 12).
--define(TRANSPORT_ACCEPT_ERR, 13).
-
--define(FROMNET_CLOSE, 14).
-
--define(CONNECT_SYNC_ERR, 15).
--define(LISTEN_SYNC_ERR, 16).
-
--define(PROXY_PORT, 23).
--define(PROXY_JOIN, 24).
--define(PROXY_JOIN_REP, 25).
--define(PROXY_JOIN_ERR, 26).
-
--define(SET_SOCK_OPT, 27).
--define(IOCTL_OK, 28).
--define(IOCTL_ERR, 29).
-
--define(GETPEERNAME, 30).
--define(GETPEERNAME_REP, 31).
--define(GETPEERNAME_ERR, 32).
-
--define(GETSOCKNAME, 33).
--define(GETSOCKNAME_REP, 34).
--define(GETSOCKNAME_ERR, 35).
-
--define(GETPEERCERT, 36).
--define(GETPEERCERT_REP, 37).
--define(GETPEERCERT_ERR, 38).
-
--define(GETVERSION, 39).
--define(GETVERSION_REP, 40).
-
--define(SET_SEED, 41).
-
--define(GETCONNINFO, 42).
--define(GETCONNINFO_REP, 43).
--define(GETCONNINFO_ERR, 44).
-
--define(SSL_ACCEPT, 45).
--define(SSL_ACCEPT_REP, 46).
--define(SSL_ACCEPT_ERR, 47).
-
--define(DUMP_CMD, 48).
--define(DEBUG_CMD, 49).
--define(DEBUGMSG_CMD, 50).
-
-%% --------------
-
--define(SSLv2, 1).
--define(SSLv3, 2).
--define(TLSv1, 4).
-
-
-%% Set socket options codes 'SET_SOCK_OPT'
--define(SET_TCP_NODELAY, 1).
-
--define(DEF_BACKLOG, 128).
-
--define(DEF_TIMEOUT, 10000).
-
--record(sslsocket, { fd = nil, pid = nil}).
-
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index c28daa271e..18cfcdcd68 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -24,17 +24,19 @@
-include_lib("public_key/include/public_key.hrl").
+%% Looks like it does for backwards compatibility reasons
+-record(sslsocket, {fd = nil, pid = nil}).
+
-type reason() :: term().
-type reply() :: term().
-type msg() :: term().
-type from() :: term().
--type host() :: string() | tuple().
--type port_num() :: integer().
+-type host() :: inet:ip_address() | inet:hostname().
-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 certdb_ref() :: reference().
+-type db_handle() :: term().
-type key_algo() :: null | rsa | dhe_rsa | dhe_dss | dh_anon.
-type der_cert() :: binary().
-type private_key() :: #'RSAPrivateKey'{} | #'DSAPrivateKey'{}.
@@ -99,10 +101,12 @@
renegotiate_at,
secure_renegotiate,
debug,
- hibernate_after % undefined if not hibernating,
+ hibernate_after,% undefined if not hibernating,
% or number of ms of inactivity
% after which ssl_connection will
% go into hibernation
+ %% This option should only be set to true by inet_tls_dist
+ erl_dist = false
}).
-record(socket_options,
diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl
index f845b1ecc0..dcf310c535 100644
--- a/lib/ssl/src/ssl_manager.erl
+++ b/lib/ssl/src/ssl_manager.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The 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,9 +27,9 @@
-include("ssl_internal.hrl").
%% Internal application API
--export([start_link/1,
- connection_init/2, cache_pem_file/1,
- lookup_trusted_cert/3, issuer_candidate/1, client_session_id/4,
+-export([start_link/1, start_link_dist/1,
+ connection_init/2, cache_pem_file/2,
+ lookup_trusted_cert/4, issuer_candidate/2, client_session_id/4,
server_session_id/4,
register_session/2, register_session/3, invalidate_session/2,
invalidate_session/3]).
@@ -50,13 +50,15 @@
session_cache_cb,
session_lifetime,
certificate_db,
- session_validation_timer
+ session_validation_timer,
+ last_delay_timer %% Keep for testing purposes
}).
-define('24H_in_msec', 8640000).
-define('24H_in_sec', 8640).
-define(SESSION_VALIDATION_INTERVAL, 60000).
-define(CERTIFICATE_CACHE_CLEANUP, 30000).
+-define(CLEAN_SESSION_DB, 60000).
%%====================================================================
%% API
@@ -64,51 +66,64 @@
%%--------------------------------------------------------------------
-spec start_link(list()) -> {ok, pid()} | ignore | {error, term()}.
%%
-%% Description: Starts the server
+%% Description: Starts the ssl manager that takes care of sessions
+%% and certificate caching.
%%--------------------------------------------------------------------
start_link(Opts) ->
- gen_server:start_link({local, ?MODULE}, ?MODULE, [Opts], []).
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [?MODULE, Opts], []).
%%--------------------------------------------------------------------
--spec connection_init(string()| {der, list()}, client | server) -> {ok, reference(), cache_ref()}.
+-spec start_link_dist(list()) -> {ok, pid()} | ignore | {error, term()}.
+%%
+%% Description: Starts a special instance of the ssl manager to
+%% be used by the erlang distribution. Note disables soft upgrade!
+%%--------------------------------------------------------------------
+start_link_dist(Opts) ->
+ gen_server:start_link({local, ssl_manager_dist}, ?MODULE, [ssl_manager_dist, Opts], []).
+
+%%--------------------------------------------------------------------
+-spec connection_init(string()| {der, list()}, client | server) ->
+ {ok, certdb_ref(), db_handle(), db_handle()}.
%%
%% Description: Do necessary initializations for a new connection.
%%--------------------------------------------------------------------
connection_init(Trustedcerts, Role) ->
call({connection_init, Trustedcerts, Role}).
%%--------------------------------------------------------------------
--spec cache_pem_file(string()) -> {ok, term()} | {error, reason()}.
+-spec cache_pem_file(string(), term()) -> {ok, term()} | {error, reason()}.
%%
%% Description: Cach a pem file and return its content.
%%--------------------------------------------------------------------
-cache_pem_file(File) ->
+cache_pem_file(File, DbHandle) ->
try file:read_file_info(File) of
{ok, #file_info{mtime = LastWrite}} ->
- cache_pem_file(File, LastWrite)
+ cache_pem_file(File, LastWrite, DbHandle)
catch
_:Reason ->
{error, Reason}
end.
%%--------------------------------------------------------------------
--spec lookup_trusted_cert(reference(), serialnumber(), issuer()) ->
+-spec lookup_trusted_cert(term(), reference(), serialnumber(), issuer()) ->
undefined |
{ok, {der_cert(), #'OTPCertificate'{}}}.
%%
%% 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).
+lookup_trusted_cert(DbHandle, Ref, SerialNumber, Issuer) ->
+ ssl_certificate_db:lookup_trusted_cert(DbHandle, Ref, SerialNumber, Issuer).
%%--------------------------------------------------------------------
--spec issuer_candidate(cert_key() | no_candidate) ->
- {cert_key(), {der_cert(), #'OTPCertificate'{}}} | no_more_candidates.
+-spec issuer_candidate(cert_key() | no_candidate, term()) ->
+ {cert_key(),
+ {der_cert(),
+ #'OTPCertificate'{}}} | no_more_candidates.
%%
%% Description: Return next issuer candidate.
%%--------------------------------------------------------------------
-issuer_candidate(PrevCandidateKey) ->
- ssl_certificate_db:issuer_candidate(PrevCandidateKey).
+issuer_candidate(PrevCandidateKey, DbHandle) ->
+ ssl_certificate_db:issuer_candidate(PrevCandidateKey, DbHandle).
%%--------------------------------------------------------------------
--spec client_session_id(host(), port_num(), #ssl_options{},
+-spec client_session_id(host(), inet:port_number(), #ssl_options{},
der_cert() | undefined) -> session_id().
%%
%% Description: Select a session id for the client.
@@ -117,7 +132,8 @@ client_session_id(Host, Port, SslOpts, OwnCert) ->
call({client_session_id, Host, Port, SslOpts, OwnCert}).
%%--------------------------------------------------------------------
--spec server_session_id(host(), port_num(), #ssl_options{}, der_cert()) -> session_id().
+-spec server_session_id(host(), inet:port_number(), #ssl_options{},
+ der_cert()) -> session_id().
%%
%% Description: Select a session id for the server.
%%--------------------------------------------------------------------
@@ -125,8 +141,8 @@ server_session_id(Port, SuggestedSessionId, SslOpts, OwnCert) ->
call({server_session_id, Port, SuggestedSessionId, SslOpts, OwnCert}).
%%--------------------------------------------------------------------
--spec register_session(port_num(), #session{}) -> ok.
--spec register_session(host(), port_num(), #session{}) -> ok.
+-spec register_session(inet:port_number(), #session{}) -> ok.
+-spec register_session(host(), inet:port_number(), #session{}) -> ok.
%%
%% Description: Make the session available for reuse.
%%--------------------------------------------------------------------
@@ -136,10 +152,12 @@ 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.
+-spec invalidate_session(inet:port_number(), #session{}) -> ok.
+-spec invalidate_session(host(), inet:port_number(), #session{}) -> ok.
%%
-%% Description: Make the session unavilable for reuse.
+%% Description: Make the session unavailable for reuse. After
+%% a the session has been marked "is_resumable = false" for some while
+%% it will be safe to remove the data from the session database.
%%--------------------------------------------------------------------
invalidate_session(Host, Port, Session) ->
cast({invalidate_session, Host, Port, Session}).
@@ -158,7 +176,8 @@ invalidate_session(Port, Session) ->
%%
%% Description: Initiates the server
%%--------------------------------------------------------------------
-init([Opts]) ->
+init([Name, Opts]) ->
+ put(ssl_manager, Name),
process_flag(trap_exit, true),
CacheCb = proplists:get_value(session_cb, Opts, ssl_session_cache),
SessionLifeTime =
@@ -185,19 +204,20 @@ init([Opts]) ->
%% Description: Handling call messages
%%--------------------------------------------------------------------
handle_call({{connection_init, "", _Role}, Pid}, _From,
- #state{session_cache = Cache} = State) ->
+ #state{certificate_db = [CertDb |_],
+ session_cache = Cache} = State) ->
erlang:monitor(process, Pid),
- Result = {ok, make_ref(), Cache},
+ Result = {ok, make_ref(),CertDb, Cache},
{reply, Result, State};
handle_call({{connection_init, Trustedcerts, _Role}, Pid}, _From,
- #state{certificate_db = Db,
+ #state{certificate_db = [CertDb|_] =Db,
session_cache = Cache} = State) ->
erlang:monitor(process, Pid),
Result =
try
{ok, Ref} = ssl_certificate_db:add_trusted_certs(Pid, Trustedcerts, Db),
- {ok, Ref, Cache}
+ {ok, Ref, CertDb, Cache}
catch
_:Reason ->
{error, Reason}
@@ -258,24 +278,32 @@ handle_cast({register_session, Port, Session},
CacheCb:update(Cache, {Port, NewSession#session.session_id}, NewSession),
{noreply, State};
-handle_cast({invalidate_session, Host, Port,
- #session{session_id = ID}},
+%%% When a session is invalidated we need to wait a while before deleting
+%%% it as there might be pending connections that rightfully needs to look
+%%% up the session data but new connections should not get to use this session.
+handle_cast({invalidate_session, Host, Port,
+ #session{session_id = ID} = Session},
#state{session_cache = Cache,
session_cache_cb = CacheCb} = State) ->
- CacheCb:delete(Cache, {{Host, Port}, ID}),
- {noreply, State};
+ CacheCb:update(Cache, {{Host, Port}, ID}, Session#session{is_resumable = false}),
+ TRef =
+ erlang:send_after(delay_time(), self(), {delayed_clean_session, {{Host, Port}, ID}}),
+ {noreply, State#state{last_delay_timer = TRef}};
-handle_cast({invalidate_session, Port, #session{session_id = ID}},
+handle_cast({invalidate_session, Port, #session{session_id = ID} = Session},
#state{session_cache = Cache,
session_cache_cb = CacheCb} = State) ->
- CacheCb:delete(Cache, {Port, ID}),
- {noreply, State};
+ CacheCb:update(Cache, {Port, ID}, Session#session{is_resumable = false}),
+ TRef =
+ erlang:send_after(delay_time(), self(), {delayed_clean_session, {Port, ID}}),
+ {noreply, State#state{last_delay_timer = TRef}};
handle_cast({recache_pem, File, LastWrite, Pid, From},
#state{certificate_db = [_, FileToRefDb, _]} = State0) ->
case ssl_certificate_db:lookup(File, FileToRefDb) of
undefined ->
- {reply, Msg, State} = handle_call({{cache_pem, File, LastWrite}, Pid}, From, State0),
+ {reply, Msg, State} =
+ handle_call({{cache_pem, File, LastWrite}, Pid}, From, State0),
gen_server:reply(From, Msg),
{noreply, State};
_ -> %% Send message to self letting cleanup messages be handled
@@ -302,6 +330,12 @@ handle_info(validate_sessions, #state{session_cache_cb = CacheCb,
start_session_validator(Cache, CacheCb, LifeTime),
{noreply, State#state{session_validation_timer = Timer}};
+handle_info({delayed_clean_session, Key}, #state{session_cache = Cache,
+ session_cache_cb = CacheCb
+ } = State) ->
+ CacheCb:delete(Cache, Key),
+ {noreply, State};
+
handle_info({'EXIT', _, _}, State) ->
%% Session validator died!! Do we need to take any action?
%% maybe error log
@@ -353,10 +387,10 @@ code_change(_OldVsn, State, _Extra) ->
%%% Internal functions
%%--------------------------------------------------------------------
call(Msg) ->
- gen_server:call(?MODULE, {Msg, self()}, infinity).
+ gen_server:call(get(ssl_manager), {Msg, self()}, infinity).
cast(Msg) ->
- gen_server:cast(?MODULE, Msg).
+ gen_server:cast(get(ssl_manager), Msg).
validate_session(Host, Port, Session, LifeTime) ->
case ssl_session:valid_session(Session, LifeTime) of
@@ -376,9 +410,10 @@ validate_session(Port, Session, LifeTime) ->
start_session_validator(Cache, CacheCb, LifeTime) ->
spawn_link(?MODULE, init_session_validator,
- [[Cache, CacheCb, LifeTime]]).
+ [[get(ssl_manager), Cache, CacheCb, LifeTime]]).
-init_session_validator([Cache, CacheCb, LifeTime]) ->
+init_session_validator([SslManagerName, Cache, CacheCb, LifeTime]) ->
+ put(ssl_manager, SslManagerName),
CacheCb:foldl(fun session_validation/2,
LifeTime, Cache).
@@ -389,8 +424,8 @@ session_validation({{Port, _}, Session}, LifeTime) ->
validate_session(Port, Session, LifeTime),
LifeTime.
-cache_pem_file(File, LastWrite) ->
- case ssl_certificate_db:lookup_cached_certs(File) of
+cache_pem_file(File, LastWrite, DbHandle) ->
+ case ssl_certificate_db:lookup_cached_certs(DbHandle,File) of
[{_, {Mtime, Content}}] ->
case LastWrite of
Mtime ->
@@ -401,3 +436,11 @@ cache_pem_file(File, LastWrite) ->
[] ->
call({cache_pem, File, LastWrite})
end.
+
+delay_time() ->
+ case application:get_env(ssl, session_delay_cleanup_time) of
+ {ok, Time} when is_integer(Time) ->
+ Time;
+ _ ->
+ ?CLEAN_SESSION_DB
+ end.
diff --git a/lib/ssl/src/ssl_prim.erl b/lib/ssl/src/ssl_prim.erl
deleted file mode 100644
index e3140a89d1..0000000000
--- a/lib/ssl/src/ssl_prim.erl
+++ /dev/null
@@ -1,173 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-
-%% Purpose: Primitive interface to SSL, without broker process (used by
-%% SSL distribution).
-
--module(ssl_prim).
-
--export([listen/2, connect/3, accept/1, close/1, send/2, send/3, recv/2, recv/3,
- getll/1, getstat/2, setopts/2, controlling_process/2, peername/1,
- sockname/1, getif/1]).
-
--include("ssl_int.hrl").
--include("ssl_broker_int.hrl").
-
-%-define(filter(Call), filter((catch Call))).
--define(filter(Call), filter(Call)).
-
-listen(Port, Opts) ->
- St = newstate(listener),
- ?filter(ssl_broker:listen_prim(ssl_server_prim, self(), Port, nonactive(Opts), St)).
-
-connect(Address, Port, Opts) ->
- St = newstate(connector),
- ?filter(ssl_broker:connect_prim(ssl_server_prim, inet_tcp, self(), Address,
- Port, nonactive(Opts), infinity, St)).
-
-accept(#st{} = ListenSt0) ->
- case transport_accept(ListenSt0) of
- {ok, ListenSt1} ->
- ssl_accept(ListenSt0, ListenSt1);
- Error ->
- Error
- end.
-
-transport_accept(#st{opts = ListenOpts, thissock = ListenSocket}) ->
- NewSt = newstate(acceptor),
- ListenFd = ListenSocket#sslsocket.fd,
- ?filter(ssl_broker:transport_accept_prim(ssl_server_prim, ListenFd,
- ListenOpts, infinity, NewSt)).
-
-ssl_accept(#st{opts = LOpts}, ListenSt1) ->
- ?filter(ssl_broker:ssl_accept_prim(ssl_server_prim, gen_tcp, self(),
- LOpts, infinity, ListenSt1)).
-
-close(#st{fd = Fd}) when is_integer(Fd) ->
- ssl_server:close_prim(ssl_server_prim, Fd),
- ok;
-close(_) ->
- ok.
-
-send(St, Data) ->
- send(St, Data, []).
-
-send(#st{proxysock = Proxysock, status = open}, Data, Opts) ->
- case inet_tcp:send(Proxysock, Data, Opts) of
- ok ->
- ok;
- {error, _} ->
- {error, closed}
- end;
-send(#st{}, _Data, _Opts) ->
- {error, closed}.
-
-recv(St, Length) ->
- recv(St, Length, infinity).
-
-recv(#st{proxysock = Proxysock, status = open}, Length, Tmo) ->
- inet_tcp:recv(Proxysock, Length, Tmo);
-recv(#st{}, _Length, _Tmo) ->
- {error, closed}.
-
-getll(#st{proxysock = Proxysock, status = open}) ->
- inet:getll(Proxysock);
-getll(#st{}) ->
- {error, closed}.
-
-getstat(#st{proxysock = Proxysock, status = open}, Opts) ->
- inet:getstat(Proxysock, Opts);
-getstat(#st{}, _Opts) ->
- {error, closed}.
-
-setopts(#st{proxysock = Proxysock, status = open}, Opts) ->
- case remove_supported(Opts) of
- [] ->
- inet:setopts(Proxysock, Opts);
- _ ->
- {error, enotsup}
- end;
-setopts(#st{}, _Opts) ->
- {error, closed}.
-
-
-controlling_process(#st{proxysock = Proxysock, status = open}, Pid)
- when is_pid(Pid) ->
- inet_tcp:controlling_process(Proxysock, Pid);
-controlling_process(#st{}, Pid) when is_pid(Pid) ->
- {error, closed}.
-
-peername(#st{fd = Fd, status = open}) ->
- case ssl_server:peername_prim(ssl_server_prim, Fd) of
- {ok, {Address, Port}} ->
- {ok, At} = inet_parse:ipv4_address(Address),
- {ok, {At, Port}};
- Error ->
- Error
- end;
-peername(#st{}) ->
- {error, closed}.
-
-sockname(#st{fd = Fd, status = open}) ->
- case ssl_server:sockname_prim(ssl_server_prim, Fd) of
- {ok, {Address, Port}} ->
- {ok, At} = inet_parse:ipv4_address(Address),
- {ok, {At, Port}};
- Error ->
- Error
- end;
-sockname(#st{}) ->
- {error, closed}.
-
-getif(#st{proxysock = Proxysock, status = open}) ->
- inet:getif(Proxysock);
-getif(#st{}) ->
- {error, closed}.
-
-remove_supported([{active, _}|T]) ->
- remove_supported(T);
-remove_supported([{packet,_}|T]) ->
- remove_supported(T);
-remove_supported([{deliver,_}|T]) ->
- remove_supported(T);
-remove_supported([H|T]) ->
- [H | remove_supported(T)];
-remove_supported([]) ->
- [].
-
-filter(Result) ->
- case Result of
- {ok, _Sock,St} ->
- {ok, St};
- {error, Reason, _St} ->
- {error,Reason}
- end.
-
-nonactive([{active,_}|T]) ->
- nonactive(T);
-nonactive([H|T]) ->
- [H | nonactive(T)];
-nonactive([]) ->
- [{active, false}].
-
-newstate(Type) ->
- #st{brokertype = Type, server = whereis(ssl_server_prim),
- client = undefined, collector = undefined, debug = false}.
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
index f1c0073965..72091fdd5f 100644
--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -62,6 +62,8 @@
-compile(inline).
+-define(INITIAL_BYTES, 5).
+
%%====================================================================
%% Internal application API
%%====================================================================
@@ -340,7 +342,7 @@ get_tls_records_aux(<<?BYTE(?CHANGE_CIPHER_SPEC),?BYTE(MajVer),?BYTE(MinVer),
get_tls_records_aux(Rest, [#ssl_tls{type = ?CHANGE_CIPHER_SPEC,
version = {MajVer, MinVer},
fragment = Data} | Acc]);
-%% Matches a ssl v2 client hello message.
+%% Matches an ssl v2 client hello message.
%% The server must be able to receive such messages, from clients that
%% are willing to use ssl v3 or higher, but have ssl v2 compatibility.
get_tls_records_aux(<<1:1, Length0:15, Data0:Length0/binary, Rest/binary>>,
@@ -360,16 +362,20 @@ get_tls_records_aux(<<1:1, Length0:15, Data0:Length0/binary, Rest/binary>>,
get_tls_records_aux(<<0:1, _CT:7, ?BYTE(_MajVer), ?BYTE(_MinVer),
?UINT16(Length), _/binary>>,
- _Acc) when Length > ?MAX_CIPHER_TEXT_LENGTH->
+ _Acc) when Length > ?MAX_CIPHER_TEXT_LENGTH ->
?ALERT_REC(?FATAL, ?RECORD_OVERFLOW);
get_tls_records_aux(<<1:1, Length0:15, _/binary>>,_Acc)
- when Length0 > ?MAX_CIPHER_TEXT_LENGTH->
+ when Length0 > ?MAX_CIPHER_TEXT_LENGTH ->
?ALERT_REC(?FATAL, ?RECORD_OVERFLOW);
get_tls_records_aux(Data, Acc) ->
- {lists:reverse(Acc), Data}.
-
+ case size(Data) =< ?MAX_CIPHER_TEXT_LENGTH + ?INITIAL_BYTES of
+ true ->
+ {lists:reverse(Acc), Data};
+ false ->
+ ?ALERT_REC(?FATAL, ?UNEXPECTED_MESSAGE)
+ end.
%%--------------------------------------------------------------------
-spec protocol_version(tls_atom_version() | tls_version()) ->
tls_version() | tls_atom_version().
diff --git a/lib/ssl/src/ssl_server.erl b/lib/ssl/src/ssl_server.erl
deleted file mode 100644
index b66e20a397..0000000000
--- a/lib/ssl/src/ssl_server.erl
+++ /dev/null
@@ -1,1378 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-
-%%% Purpose : SSL server
-
-%%
-%% TODO
-%%
-%% XXX The ip option in listen is not general enough. It is assumed
-%% to be a tuple, which is not always the case.
-
--module(ssl_server).
--behaviour(gen_server).
-
-%% External exports
--export([start_link/0]).
-
--export([transport_accept/2, transport_accept/3, ssl_accept/2, ssl_accept/3,
- ciphers/0, connect/5, connect/6,
- connection_info/1, close/1, listen/3, listen/4, peercert/1,
- peername/1, proxy_join/2, seed/1, setnodelay/2, sockname/1,
- version/0]).
-
--export([start_link_prim/0]).
--export([ssl_accept_prim/4, transport_accept_prim/4,
- connect_prim/7, close_prim/2,
- listen_prim/5, proxy_join_prim/3, peername_prim/2, setnodelay_prim/3,
- sockname_prim/2]).
-
--export([dump/0, dump/1]).
--export([enable_debug/0, disable_debug/0, set_debug/1]).
--export([enable_debugmsg/0, disable_debugmsg/0, set_debugmsg/1]).
-
-%% gen_server callbacks
--export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- code_change/3, terminate/2]).
-
--include("ssl_int.hrl").
-
--record(st, {
- port = [], % port() of port program
- progpid = [], % OS pid of port program
- debug = false, % debug printout flag
- cons = [], % All brokers except pending accepts
- paccepts = [], % Pending accept brokers
- proxylsport = [], % proxy listen socket port
- intref = 0, % internal reference counter
- compvsn = "", % ssl compile library version
- libvsn = "", % ssl library version
- ciphers = [] % available ciphers
- }).
-
-
-%% In all functions below IP is a four tuple, e.g. {192, 236, 52, 7}.
-%% Port, Fd and ListenFd are integers; Flags is a string of characters.
-%%
-%% The prefixes F and L mean foreign and local, respectively.
-%% Example: FIP (IP address for foreign end).
-
-%%
-%% start_link() -> {ok, Pid} | {error, Reason}
-%%
-start_link() ->
- gen_server:start_link({local, ssl_server}, ssl_server, [], []).
-
-start_link_prim() ->
- gen_server:start_link({local, ssl_server_prim}, ssl_server, [], []).
-
-%%
-%% transport_accept(ListenFd, Flags) -> {ok, Fd, ProxyLLPort} |
-%% {error, Reason}
-%%
-transport_accept(ListenFd, Flags) ->
- transport_accept(ListenFd, Flags, infinity).
-transport_accept(ListenFd, Flags, Timeout) ->
- transport_accept_prim(ssl_server,ListenFd, Flags, Timeout).
-
-transport_accept_prim(ServerName, ListenFd, Flags, Timeout) ->
- Req = {transport_accept, self(), ListenFd, Flags},
- gen_server:call(ServerName, Req, Timeout).
-
-%%
-%% ssl_accept(ListenFd, Flags) -> {ok, Fd, ProxyLLPort} |
-%% {error, Reason}
-%%
-ssl_accept(ListenFd, Flags) ->
- ssl_accept(ListenFd, Flags, infinity).
-ssl_accept(ListenFd, Flags, Timeout) ->
- ssl_accept_prim(ssl_server, ListenFd, Flags, Timeout).
-
-ssl_accept_prim(ServerName, Fd, Flags, Timeout) ->
- Req = {ssl_accept, Fd, Flags},
- gen_server:call(ServerName, Req, Timeout).
-
-%%
-%% ciphers() -> {ok, Ciphers}
-%%
-ciphers() ->
- gen_server:call(ssl_server, ciphers, infinity).
-
-%%
-%% close(Fd) -> ok
-%%
-close(Fd) ->
- close_prim(ssl_server, Fd).
-close_prim(ServerName, Fd) ->
- gen_server:call(ServerName, {close, self(), Fd}, infinity),
- ok.
-
-%%
-%% connect(LIP, LPort, FIP, FPort, Flags) -> {ok, Fd, ProxyLFPort} |
-%% {error, Reason}
-%%
-connect(LIP, LPort, FIP, FPort, Flags) ->
- connect(LIP, LPort, FIP, FPort, Flags, infinity).
-connect(LIP, LPort, FIP, FPort, Flags, Timeout) ->
- connect_prim(ssl_server, LIP, LPort, FIP, FPort, Flags, Timeout).
-
-connect_prim(ServerName, LIP, LPort, FIP, FPort, Flags, Timeout) ->
- Req = {connect, self(), LIP, LPort, FIP, FPort, Flags},
- gen_server:call(ServerName, Req, Timeout).
-
-%%
-%% connection_info(Fd) -> {ok, {Protocol, Cipher}} | {error, Reason}
-%%
-connection_info(Fd) ->
- Req = {connection_info, self(), Fd},
- gen_server:call(ssl_server, Req, infinity).
-
-%%
-%% listen(IP, LPort, Flags),
-%% listen(IP, LPort, Flags, BackLog) -> {ok, ListenFd, LPort0} |
-%% {error, Reason}
-%%
-listen(IP, LPort, Flags) ->
- listen(IP, LPort, Flags, ?DEF_BACKLOG).
-listen(IP, LPort, Flags, BackLog) ->
- listen_prim(ssl_server, IP, LPort, Flags, BackLog).
-listen_prim(ServerName, IP, LPort, Flags, BackLog) ->
- Req = {listen, self(), IP, LPort, Flags, BackLog},
- gen_server:call(ServerName, Req, infinity).
-
-%%
-%% peercert(Fd) -> {ok, Cert} | {error, Reason}
-%%
-peercert(Fd) ->
- Req = {peercert, self(), Fd},
- gen_server:call(ssl_server, Req, infinity).
-
-%%
-%% peername(Fd) -> {ok, {Address, Port}} | {error, Reason}
-%%
-peername(Fd) ->
- peername_prim(ssl_server, Fd).
-peername_prim(ServerName, Fd) ->
- Req = {peername, self(), Fd},
- gen_server:call(ServerName, Req, infinity).
-
-%%
-%% proxy_join(Fd, LPort) -> ok | {error, Reason}
-%%
-proxy_join(Fd, LPort) ->
- proxy_join_prim(ssl_server, Fd, LPort).
-proxy_join_prim(ServerName, Fd, LPort) ->
- Req = {proxy_join, self(), Fd, LPort},
- gen_server:call(ServerName, Req, infinity).
-
-%%
-%% seed(Data)
-%%
-seed(Data) ->
- Req = {seed, Data},
- gen_server:call(ssl_server, Req, infinity).
-
-%%
-%% set_nodelay(Fd, Boolean)
-%%
-setnodelay(Fd, Boolean) ->
- setnodelay_prim(ssl_server, Fd, Boolean).
-setnodelay_prim(ServerName, Fd, Boolean) ->
- Req = {setnodelay, self(), Fd, Boolean},
- gen_server:call(ServerName, Req, infinity).
-
-%%
-%% sockname(Fd) -> {ok, {Address, Port}} | {error, Reason}
-%%
-sockname(Fd) ->
- sockname_prim(ssl_server, Fd).
-sockname_prim(ServerName, Fd) ->
- Req = {sockname, self(), Fd},
- gen_server:call(ServerName, Req, infinity).
-
-%%
-%% version() -> {ok, {CompVsn, LibVsn}}
-%%
-version() ->
- gen_server:call(ssl_server, version, infinity).
-
-
-enable_debug() ->
- set_debug(true).
-
-disable_debug() ->
- set_debug(false).
-
-set_debug(Bool) ->
- set_debug(Bool, infinity).
-
-set_debug(Bool, Timeout) when is_boolean(Bool) ->
- Req = {set_debug, Bool, self()},
- gen_server:call(ssl_server, Req, Timeout).
-
-enable_debugmsg() ->
- set_debugmsg(true).
-
-disable_debugmsg() ->
- set_debugmsg(false).
-
-set_debugmsg(Bool) ->
- set_debugmsg(Bool, infinity).
-
-set_debugmsg(Bool, Timeout) when is_boolean(Bool) ->
- Req = {set_debugmsg, Bool, self()},
- gen_server:call(ssl_server, Req, Timeout).
-
-dump() ->
- dump(infinity).
-
-dump(Timeout) ->
- Req = {dump, self()},
- gen_server:call(ssl_server, Req, Timeout).
-
-%%
-%% init
-%%
-init([]) ->
- Debug = case application:get_env(ssl, edebug) of
- {ok, true} ->
- true;
- _ ->
- case application:get_env(ssl, debug) of
- {ok, true} ->
- true;
- _ ->
- os:getenv("ERL_SSL_DEBUG") =/= false
- end
- end,
- ProgDir =
- case init:get_argument(ssl_portprogram_dir) of
- {ok, [[D]]} ->
- D;
- _ ->
- find_priv_bin()
- end,
- {Program, Flags} = mk_cmd_line("ssl_esock"),
- Cmd = filename:join(ProgDir, Program) ++ " " ++ Flags,
- debug1(Debug, " start, Cmd = ~s~n", [Cmd]),
- case (catch open_port({spawn, Cmd}, [binary, {packet, 4}])) of
- Port when is_port(Port) ->
- process_flag(trap_exit, true),
- receive
- {Port, {data, Bin}} ->
- {ProxyLLPort, ProgPid, CompVsn, LibVsn, Ciphers} =
- decode_msg(Bin, [int16, int32, string, string,
- string]),
- debug1(Debug, "port program pid = ~w~n",
- [ProgPid]),
- {ok, #st{port = Port,
- proxylsport = ProxyLLPort,
- progpid = ProgPid,
- debug = Debug,
- compvsn = CompVsn,
- libvsn = LibVsn,
- ciphers = Ciphers}};
- {'EXIT', Port, Reason} ->
- {stop, Reason}
- end;
- {'EXIT', Reason} ->
- {stop, Reason}
- end.
-
-%%
-%% transport_accept
-%%
-handle_call({transport_accept, Broker, ListenFd, Flags}, From, St) ->
- debug(St, "transport_accept: broker = ~w, listenfd = ~w~n",
- [Broker, ListenFd]),
- case get_by_fd(ListenFd, St#st.cons) of
- {ok, {ListenFd, _, _}} ->
- send_cmd(St#st.port, ?TRANSPORT_ACCEPT, [int32(ListenFd), Flags, 0]),
- PAccepts = add({ListenFd, Broker, From}, St#st.paccepts),
- %%
- %% We reply when we get TRANSPORT_ACCEPT_REP or ASYNC_ACCEPT_ERR
- %%
- {noreply, St#st{paccepts = PAccepts}};
- _Other ->
- {reply, {error, ebadf}, St}
- end;
-
-%%
-%% ssl_accept
-%%
-handle_call({ssl_accept, Fd, Flags}, From, St) ->
- case replace_from_by_fd(Fd, St#st.cons, From) of
- {ok, _, Cons} = _Rep ->
- send_cmd(St#st.port, ?SSL_ACCEPT, [int32(Fd), Flags, 0]),
- %% We reply when we get SSL_ACCEPT_REP or ASYNC_ACCEPT_ERR
- {noreply, St#st{cons = Cons}};
- _Other ->
- {reply, {error, ebadf}, St}
- end;
-
-%%
-%% version
-%%
-handle_call(ciphers, From, St) ->
- debug(St, "ciphers: from = ~w~n", [From]),
- {reply, {ok, St#st.ciphers}, St};
-
-%%
-%% connect
-%%
-handle_call({connect, Broker, LIP, LPort, FIP, FPort, Flags}, From, St) ->
- debug(St, "connect: broker = ~w, ip = ~w, "
- "sport = ~w~n", [Broker, FIP, FPort]),
- Port = St#st.port,
- LIPStr = ip_to_string(LIP),
- FIPStr = ip_to_string(FIP),
- IntRef = new_intref(St),
- send_cmd(Port, ?CONNECT, [int32(IntRef),
- int16(LPort), LIPStr, 0,
- int16(FPort), FIPStr, 0,
- Flags, 0]),
- Cons = add({{intref, IntRef}, Broker, From}, St#st.cons),
- %% We reply when we have got CONNECT_SYNC_ERR, or CONNECT_WAIT
- %% and CONNECT_REP, or CONNECT_ERR.
- {noreply, St#st{cons = Cons, intref = IntRef}};
-
-%%
-%% connection_info
-%%
-handle_call({connection_info, Broker, Fd}, From, St) ->
- debug(St, "connection_info: broker = ~w, fd = ~w~n",
- [Broker, Fd]),
- case replace_from_by_fd(Fd, St#st.cons, From) of
- {ok, _, Cons} ->
- send_cmd(St#st.port, ?GETCONNINFO, [int32(Fd)]),
- %% We reply when we get GETCONNINFO_REP or GETCONNINFO_ERR.
- {noreply, St#st{cons = Cons}};
- _Other ->
- {reply, {error, ebadf}, St}
- end;
-
-%%
-%% close
-%%
-handle_call({close, Broker, Fd}, _From, St) ->
- debug(St, "close: broker = ~w, fd = ~w~n",
- [Broker, Fd]),
- #st{port = Port, cons = Cons0, paccepts = PAccepts0} = St,
- case delete_by_fd(Fd, Cons0) of
- %% Must match Broker pid; fd may be reused already.
- {ok, {Fd, Broker, _}, Cons} ->
- send_cmd(Port, ?CLOSE, int32(Fd)),
- %% If Fd is a listen socket fd, there might be pending
- %% accepts for that fd.
- case delete_all_by_fd(Fd, PAccepts0) of
- {ok, DelAccepts, RemAccepts} ->
- %% Reply {error, closed} to all pending accepts
- lists:foreach(fun({_, _, AccFrom}) ->
- gen_server:reply(AccFrom,
- {error, closed})
- end, DelAccepts),
- {reply, ok,
- St#st{cons = Cons, paccepts = RemAccepts}};
- _ ->
- {reply, ok, St#st{cons = Cons}}
- end;
- _ ->
- {reply, ok, St}
- end;
-
-%%
-%% listen
-%%
-handle_call({listen, Broker, IP, LPort, Flags, BackLog}, From, St) ->
- debug(St, "listen: broker = ~w, IP = ~w, "
- "sport = ~w~n", [Broker, IP, LPort]),
- Port = St#st.port,
- IPStr = ip_to_string(IP),
- IntRef = new_intref(St),
- send_cmd(Port, ?LISTEN, [int32(IntRef), int16(LPort), IPStr, 0,
- int16(BackLog), Flags, 0]),
- Cons = add({{intref, IntRef}, Broker, From}, St#st.cons),
- %% We reply when we have got LISTEN_REP.
- {noreply, St#st{cons = Cons, intref = IntRef}};
-
-%%
-%% peercert
-%%
-handle_call({peercert, Broker, Fd}, From, St) ->
- debug(St, "peercert: broker = ~w, fd = ~w~n",
- [Broker, Fd]),
- case replace_from_by_fd(Fd, St#st.cons, From) of
- {ok, _, Cons} ->
- send_cmd(St#st.port, ?GETPEERCERT, [int32(Fd)]),
- %% We reply when we get GETPEERCERT_REP or GETPEERCERT_ERR.
- {noreply, St#st{cons = Cons}};
- _Other ->
- {reply, {error, ebadf}, St}
- end;
-
-
-%%
-%% peername
-%%
-handle_call({peername, Broker, Fd}, From, St) ->
- debug(St, "peername: broker = ~w, fd = ~w~n",
- [Broker, Fd]),
- case replace_from_by_fd(Fd, St#st.cons, From) of
- {ok, _, Cons} ->
- send_cmd(St#st.port, ?GETPEERNAME, [int32(Fd)]),
- %% We reply when we get GETPEERNAME_REP or GETPEERNAME_ERR.
- {noreply, St#st{cons = Cons}};
- _Other ->
- {reply, {error, ebadf}, St}
- end;
-
-%%
-%% proxy join
-%%
-handle_call({proxy_join, Broker, Fd, LPort}, From, St) ->
- debug(St, "proxy_join: broker = ~w, fd = ~w, "
- "sport = ~w~n", [Broker, Fd, LPort]),
- case replace_from_by_fd(Fd, St#st.cons, From) of
- {ok, _, Cons} ->
- send_cmd(St#st.port, ?PROXY_JOIN, [int32(Fd),
- int16(LPort)]),
- %% We reply when we get PROXY_JOIN_REP, or PROXY_JOIN_ERR.
- {noreply, St#st{cons = Cons}};
- _Other ->
- {reply, {error, ebadf}, St}
- end;
-
-%%
-%% seed
-%%
-handle_call({seed, Data}, _From, St) when is_binary(Data) ->
- send_cmd(St#st.port, ?SET_SEED, [int32(byte_size(Data)), Data]),
- {reply, ok, St};
-
-handle_call({seed, Data}, From, St) ->
- case catch list_to_binary(Data) of
- {'EXIT', _} ->
- {reply, {error, edata}, St};
- Bin ->
- handle_call({seed, Bin}, From, St)
- end;
-
-%%
-%% setnodelay
-%%
-handle_call({setnodelay, Broker, Fd, Boolean}, From, St) ->
- debug(St, "setnodelay: broker = ~w, fd = ~w, "
- "boolean = ~w~n", [Broker, Fd, Boolean]),
- case replace_from_by_fd(Fd, St#st.cons, From) of
- {ok, _, Cons} ->
- Val = if Boolean == true -> 1; true -> 0 end,
- send_cmd(St#st.port, ?SET_SOCK_OPT,
- [int32(Fd), ?SET_TCP_NODELAY, Val]),
- %% We reply when we get IOCTL_OK or IOCTL_ERR.
- {noreply, St#st{cons = Cons}};
- _Other ->
- {reply, {error, ebadf}, St}
- end;
-
-%%
-%% sockname
-%%
-handle_call({sockname, Broker, Fd}, From, St) ->
- debug(St, "sockname: broker = ~w, fd = ~w~n",
- [Broker, Fd]),
- case replace_from_by_fd(Fd, St#st.cons, From) of
- {ok, _, Cons} ->
- send_cmd(St#st.port, ?GETSOCKNAME, [int32(Fd)]),
- %% We reply when we get GETSOCKNAME_REP or GETSOCKNAME_ERR.
- {noreply, St#st{cons = Cons}};
- _Other ->
- {reply, {error, ebadf}, St}
- end;
-
-%%
-%% version
-%%
-handle_call(version, From, St) ->
- debug(St, "version: from = ~w~n", [From]),
- {reply, {ok, {St#st.compvsn, St#st.libvsn}}, St};
-
-%%
-%% dump
-%%
-handle_call({dump, Broker}, _From, St) ->
- debug(St, "dump: broker = ~w", [Broker]),
- Port = St#st.port,
- send_cmd(Port, ?DUMP_CMD, []),
- {reply, ok, St};
-
-%%
-%% set_debug
-%%
-handle_call({set_debug, Bool, Broker}, _From, St) ->
- debug(St, "set_debug: broker = ~w", [Broker]),
- Value = case Bool of
- true ->
- 1;
- false ->
- 0
- end,
- Port = St#st.port,
- send_cmd(Port, ?DEBUG_CMD, [Value]),
- {reply, ok, St};
-
-%%
-%% set_debugmsg
-%%
-handle_call({set_debugmsg, Bool, Broker}, _From, St) ->
- debug(St, "set_debugmsg: broker = ~w", [Broker]),
- Value = case Bool of
- true ->
- 1;
- false ->
- 0
- end,
- Port = St#st.port,
- send_cmd(Port, ?DEBUGMSG_CMD, [Value]),
- {reply, ok, St};
-
-handle_call(Request, _From, St) ->
- debug(St, "unexpected call: ~w~n", [Request]),
- Reply = {error, {badcall, Request}},
- {reply, Reply, St}.
-
-%%
-%% handle_cast(Msg, St)
-%%
-
-
-handle_cast(Msg, St) ->
- debug(St, "unexpected cast: ~w~n", [Msg]),
- {noreply, St}.
-
-%%
-%% handle_info(Info, St)
-%%
-
-%% Data from port
-%%
-handle_info({Port, {data, Bin}},
- #st{cons = StCons, paccepts = Paccepts,
- port = Port, proxylsport = Proxylsport} = St)
- when is_binary(Bin) ->
- %% io:format("++++ ssl_server got from port: ~w~n", [Bin]),
- <<OpCode:8, _/binary>> = Bin,
- case OpCode of
- %%
- %% transport_accept
- %%
- ?TRANSPORT_ACCEPT_ERR when byte_size(Bin) >= 5 ->
- {ListenFd, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "transport_accept_err: listenfd = ~w, "
- "reason = ~w~n", [ListenFd, Reason]),
- case delete_last_by_fd(ListenFd, Paccepts) of
- {ok, {_, _, From}, PAccepts} ->
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{paccepts = PAccepts}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
- ?TRANSPORT_ACCEPT_REP when byte_size(Bin) >= 9 ->
- {ListenFd, Fd} = decode_msg(Bin, [int32, int32]),
- debug(St, "transport_accept_rep: listenfd = ~w, "
- "fd = ~w~n", [ListenFd, Fd]),
- case delete_last_by_fd(ListenFd, Paccepts) of
- {ok, {_, Broker, From}, PAccepts} ->
- Reply = {ok, Fd, Proxylsport},
- gen_server:reply(From, Reply),
- debug(St, "transport_accept_rep: From = ~w\n", [From]),
- Cons = add({Fd, Broker, From}, StCons),
- {noreply, St#st{cons = Cons, paccepts = PAccepts}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
-
- %%
- %% ssl_accept
- %%
- ?SSL_ACCEPT_ERR when byte_size(Bin) >= 5 ->
- {Fd, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "ssl_accept_err: listenfd = ~w, "
- "reason = ~w~n", [Fd, Reason]),
- %% JC: remove this?
- case delete_last_by_fd(Fd, StCons) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
- ?SSL_ACCEPT_REP when byte_size(Bin) >= 5 ->
- Fd = decode_msg(Bin, [int32]),
- debug(St, "ssl_accept_rep: Fd = ~w\n", [Fd]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, ok),
- {noreply, St#st{cons = Cons}};
- _ ->
- {noreply, St}
- end;
-
- %%
- %% connect
- %%
- ?CONNECT_SYNC_ERR when byte_size(Bin) >= 5 ->
- {IntRef, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "connect_sync_err: intref = ~w, "
- "reason = ~w~n", [IntRef, Reason]),
- case delete_by_intref(IntRef, StCons) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- {noreply, St}
- end;
- ?CONNECT_WAIT when byte_size(Bin) >= 9 ->
- {IntRef, Fd} = decode_msg(Bin, [int32, int32]),
- debug(St, "connect_wait: intref = ~w, "
- "fd = ~w~n", [IntRef, Fd]),
- case replace_fd_by_intref(IntRef, StCons, Fd) of
- {ok, _, Cons} ->
- %% We reply when we get CONNECT_REP or CONNECT_ERR
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% We have a new Fd which must be closed
- send_cmd(Port, ?CLOSE, int32(Fd)),
- {noreply, St}
- end;
- ?CONNECT_REP when byte_size(Bin) >= 5 ->
- %% after CONNECT_WAIT
- Fd = decode_msg(Bin, [int32]),
- debug(St, "connect_rep: fd = ~w~n", [Fd]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {ok, Fd, Proxylsport}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- {noreply, St}
- end;
- ?CONNECT_ERR when byte_size(Bin) >= 5 ->
- {Fd, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "connect_err: fd = ~w, "
- "reason = ~w~n", [Fd, Reason]),
- case delete_by_fd(Fd, StCons) of
- {ok, {_, _, From}, Cons} ->
- %% Fd not yet published - hence close ourselves
- send_cmd(Port, ?CLOSE, int32(Fd)),
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
-
- %%
- %% connection_info
- %%
- ?GETCONNINFO_REP when byte_size(Bin) >= 5 ->
- {Fd, Protocol, Cipher} = decode_msg(Bin, [int32, string, string]),
- debug(St, "connection_info_rep: fd = ~w, "
- "protcol = ~p, ip = ~p~n", [Fd, Protocol, Cipher]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {ok, {protocol_name(Protocol),
- Cipher}}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
- ?GETCONNINFO_ERR when byte_size(Bin) >= 5 ->
- {Fd, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "connection_info_err: fd = ~w, "
- "reason = ~w~n", [Fd, Reason]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
-
- %%
- %% listen
- %%
- ?LISTEN_SYNC_ERR when byte_size(Bin) >= 5 ->
- {IntRef, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "listen_sync_err: intref = ~w, "
- "reason = ~w~n", [IntRef, Reason]),
- case delete_by_intref(IntRef, StCons) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- {noreply, St}
- end;
- ?LISTEN_REP when byte_size(Bin) >= 11 ->
- {IntRef, ListenFd, LPort} = decode_msg(Bin, [int32, int32, int16]),
- debug(St, "listen_rep: intref = ~w, "
- "listenfd = ~w, sport = ~w~n", [IntRef, ListenFd, LPort]),
- case replace_fd_from_by_intref(IntRef, StCons, ListenFd, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {ok, ListenFd, LPort}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% ListenFd has to be closed.
- send_cmd(Port, ?CLOSE, int32(ListenFd)),
- {noreply, St}
- end;
-
- %%
- %% proxy join
- %%
- ?PROXY_JOIN_REP when byte_size(Bin) >= 5 ->
- Fd = decode_msg(Bin, [int32]),
- debug(St, "proxy_join_rep: fd = ~w~n",
- [Fd]),
- case get_by_fd(Fd, StCons) of
- {ok, {_, _, From}} ->
- gen_server:reply(From, ok),
- {noreply, St};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
- ?PROXY_JOIN_ERR when byte_size(Bin) >= 5 ->
- {Fd, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "proxy_join_rep: fd = ~w, "
- "reason = ~w~n", [Fd, Reason]),
- case delete_by_fd(Fd, StCons) of
- {ok, {_, _, From}, Cons} ->
- case Reason of
- enoproxysocket ->
- send_cmd(Port, ?CLOSE, int32(Fd));
- _ ->
- ok
- %% Must not close Fd since it is published
- end,
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
-
- %%
- %% peername
- %%
- ?GETPEERNAME_REP when byte_size(Bin) >= 5 ->
- {Fd, LPort, IPString} = decode_msg(Bin, [int32, int16, string]),
- debug(St, "getpeername_rep: fd = ~w, "
- "sport = ~w, ip = ~p~n", [Fd, LPort, IPString]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {ok, {IPString, LPort}}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
- ?GETPEERNAME_ERR when byte_size(Bin) >= 5 ->
- {Fd, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "getpeername_err: fd = ~w, "
- "reason = ~w~n", [Fd, Reason]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
-
- %%
- %% ioctl
- %%
- ?IOCTL_OK when byte_size(Bin) >= 5 ->
- Fd = decode_msg(Bin, [int32]),
- debug(St, "ioctl_ok: fd = ~w~n",
- [Fd]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, ok),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
- ?IOCTL_ERR when byte_size(Bin) >= 5 ->
- {Fd, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "ioctl_err: fd = ~w, "
- "reason = ~w~n", [Fd, Reason]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
-
- %%
- %% sockname
- %%
- ?GETSOCKNAME_REP when byte_size(Bin) >= 5 ->
- {Fd, LPort, IPString} = decode_msg(Bin, [int32, int16, string]),
- debug(St, "getsockname_rep: fd = ~w, "
- "sport = ~w, ip = ~p~n", [Fd, LPort, IPString]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {ok, {IPString, LPort}}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
- ?GETSOCKNAME_ERR when byte_size(Bin) >= 5 ->
- {Fd, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "getsockname_err: fd = ~w, "
- "reason = ~w~n", [Fd, Reason]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
-
- %%
- %% peercert
- %%
- ?GETPEERCERT_REP when byte_size(Bin) >= 5 ->
- {Fd, Cert} = decode_msg(Bin, [int32, bin]),
- debug(St, "getpeercert_rep: fd = ~w~n", [Fd]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {ok, Cert}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end;
- ?GETPEERCERT_ERR when byte_size(Bin) >= 5 ->
- {Fd, Reason} = decode_msg(Bin, [int32, atom]),
- debug(St, "getpeercert_err: fd = ~w, reason = ~w~n",
- [Fd, Reason]),
- case replace_from_by_fd(Fd, StCons, []) of
- {ok, {_, _, From}, Cons} ->
- gen_server:reply(From, {error, Reason}),
- {noreply, St#st{cons = Cons}};
- _Other ->
- %% Already closed
- {noreply, St}
- end
- end;
-
-%%
-%% EXIT
-%%
-handle_info({'EXIT', Pid, Reason}, St) when is_pid(Pid) ->
- debug(St, "exit pid = ~w, "
- "reason = ~w~n", [Pid, Reason]),
- case delete_by_pid(Pid, St#st.cons) of
- {ok, {{intref, _}, Pid, _}, Cons} ->
- {noreply, St#st{cons = Cons}};
- {ok, {Fd, Pid, _}, Cons} ->
- send_cmd(St#st.port, ?CLOSE, int32(Fd)),
- %% If Fd is a listen socket fd, there might be pending
- %% accepts for that fd.
- case delete_all_by_fd(Fd, St#st.paccepts) of
- {ok, DelAccepts, RemAccepts} ->
- %% Reply {error, closed} to all pending accepts.
- lists:foreach(fun({_, _, From}) ->
- gen_server:reply(From,
- {error, closed})
- end, DelAccepts),
- {noreply,
- St#st{cons = Cons, paccepts = RemAccepts}};
- _ ->
- {noreply, St#st{cons = Cons}}
- end;
- _ ->
- case delete_by_pid(Pid, St#st.paccepts) of
- {ok, {ListenFd, _, _}, PAccepts} ->
- %% decrement ref count in port program
- send_cmd(St#st.port, ?NOACCEPT, int32(ListenFd)),
- {noreply, St#st{paccepts = PAccepts}};
- _ ->
- {noreply, St}
- end
- end;
-
-%%
-%% 'badsig' means bad message to port. Port program is unaffected.
-%%
-handle_info({'EXIT', Port, badsig}, #st{port = Port} = St) ->
- debug(St, "badsig!!!~n", []),
- {noreply, St};
-
-handle_info({'EXIT', Port, Reason}, #st{port = Port} = St) ->
- {stop, Reason, St};
-
-handle_info(Info, St) ->
- debug(St, "unexpected info: ~w~n", [Info]),
- {noreply, St}.
-
-%%
-%% terminate(Reason, St) -> any
-%%
-terminate(_Reason, _St) ->
- ok.
-
-%%
-%% code_change(OldVsn, St, Extra) -> {ok, NSt}
-%%
-code_change(_OldVsn, St, _Extra) ->
- {ok, St}.
-
-%%%----------------------------------------------------------------------
-%%% Internal functions
-%%%----------------------------------------------------------------------
-
-%%
-%% Send binary command to sock
-%%
-send_cmd(Port, Cmd, Args) ->
- Port ! {self(), {command, [Cmd| Args]}}.
-
-%%
-%% add(Descr, Cons) -> NCons
-%%
-add(D, L) ->
- [D| L].
-
-%%
-%% get_by_fd(Fd, Cons) -> {ok, Descr} | not_found
-%%
-get_by_fd(Fd, Cons) ->
- get_by_pos(Fd, 1, Cons).
-
-%%
-%% delete_by_fd(Fd, Cons) -> {ok, OldDesc, NewCons} | not_found.
-%%
-delete_by_fd(Fd, Cons) ->
- delete_by_pos(Fd, 1, Cons).
-
-%%
-%% delete_all_by_fd(Fd, Cons) -> {ok, DelCons, RemCons} | not_found.
-%%
-delete_all_by_fd(Fd, Cons) ->
- delete_all_by_pos(Fd, 1, Cons).
-
-%%
-%% delete_by_intref(IntRef, Cons) -> {ok, OldDesc, NewCons} | not_found.
-%%
-delete_by_intref(IntRef, Cons) ->
- delete_by_pos({intref, IntRef}, 1, Cons).
-
-%%
-%% delete_by_pid(Pid, Cons) -> {ok, OldDesc, NewCons} | not_found.
-%%
-delete_by_pid(Pid, Cons) ->
- delete_by_pos(Pid, 2, Cons).
-
-%%
-%% delete_last_by_fd(Fd, Cons) -> {ok, OldDesc, NCons} | not_found
-%%
-delete_last_by_fd(Fd, Cons) ->
- case dlbf(Fd, Cons) of
- {X, L} ->
- {ok, X, L};
- _Other ->
- not_found
- end.
-
-dlbf(Fd, [H]) ->
- last_elem(Fd, H, []);
-dlbf(Fd, [H|T]) ->
- case dlbf(Fd, T) of
- {X, L} ->
- {X, [H|L]};
- L ->
- last_elem(Fd, H, L)
- end;
-dlbf(_Fd, []) ->
- [].
-
-last_elem(Fd, H, L) when element(1, H) == Fd ->
- {H, L};
-last_elem(_, H, L) ->
- [H|L].
-
-
-%%
-%% replace_from_by_fd(Fd, Cons, From) -> {ok, OldDesc, NewList} | not_found
-%%
-replace_from_by_fd(Fd, Cons, From) ->
- replace_posn_by_pos(Fd, 1, Cons, [{From, 3}]).
-
-%%
-%% replace_fd_by_intref(IntRef, Cons, Fd) -> {ok, OldDesc, NewList} | not_f.
-%%
-replace_fd_by_intref(IntRef, Cons, Fd) ->
- replace_posn_by_pos({intref, IntRef}, 1, Cons, [{Fd, 1}]).
-
-%%
-%% replace_fd_from_by_intref(IntRef, Cons, NFd, From) ->
-%% {ok, OldDesc, NewList} | not_found
-%%
-replace_fd_from_by_intref(IntRef, Cons, NFd, From) ->
- replace_posn_by_pos({intref, IntRef}, 1, Cons, [{NFd, 1}, {From, 3}]).
-
-
-%%
-%% All *_by_pos functions
-%%
-
-get_by_pos(Key, Pos, [H|_]) when element(Pos, H) == Key ->
- {ok, H};
-get_by_pos(Key, Pos, [_|T]) ->
- get_by_pos(Key, Pos, T);
-get_by_pos(_, _, []) ->
- not_found.
-
-delete_by_pos(Key, Pos, Cons) ->
- case delete_by_pos1(Key, Pos, {not_found, Cons}) of
- {not_found, _} ->
- not_found;
- {ODesc, NCons} ->
- {ok, ODesc, NCons}
- end.
-delete_by_pos1(Key, Pos, {_R, [H|T]}) when element(Pos, H) == Key ->
- {H, T};
-delete_by_pos1(Key, Pos, {R, [H|T]}) ->
- {R0, T0} = delete_by_pos1(Key, Pos, {R, T}),
- {R0, [H| T0]};
-delete_by_pos1(_, _, {R, []}) ->
- {R, []}.
-
-delete_all_by_pos(Key, Pos, Cons) ->
- case lists:foldl(fun(H, {Ds, Rs}) when element(Pos, H) == Key ->
- {[H|Ds], Rs};
- (H, {Ds, Rs}) ->
- {Ds, [H|Rs]}
- end, {[], []}, Cons) of
- {[], _} ->
- not_found;
- {DelCons, RemCons} ->
- {ok, DelCons, RemCons}
- end.
-
-replace_posn_by_pos(Key, Pos, Cons, Repls) ->
- replace_posn_by_pos1(Key, Pos, Cons, Repls, []).
-
-replace_posn_by_pos1(Key, Pos, [H0| T], Repls, Acc)
- when element(Pos, H0) =:= Key ->
- H = lists:foldl(fun({Val, VPos}, Tuple) ->
- setelement(VPos, Tuple, Val)
- end, H0, Repls),
- {ok, H0, lists:reverse(Acc, [H| T])};
-replace_posn_by_pos1(Key, Pos, [H|T], Repls, Acc) ->
- replace_posn_by_pos1(Key, Pos, T, Repls, [H| Acc]);
-replace_posn_by_pos1(_, _, [], _, _) ->
- not_found.
-
-%%
-%% Binary/integer conversions
-%%
-int16(I) ->
- %%[(I bsr 8) band 255, I band 255].
- <<I:16>>.
-
-int32(I) ->
- %% [(I bsr 24) band 255,
- %% (I bsr 16) band 255,
- %% (I bsr 8) band 255,
- %% I band 255].
- <<I:32>>.
-
-%% decode_msg(Bin, Format) -> Tuple | integer() | atom() | string() |
-%% list of binaries()
-%%
-%% Decode message from binary
-%% Format = [spec()]
-%% spec() = int16 | int32 | string | atom | bin | bins
-%%
-%% Notice: The first byte (op code) of the binary message is removed.
-%% Notice: bins returns a *list* of binaries.
-%%
-decode_msg(<<_, Bin/binary>>, Format) ->
- Dec = dec(Format, Bin),
- case Dec of
- [Dec1] -> Dec1;
- _ -> list_to_tuple(Dec)
- end.
-
-dec([], _) ->
- [];
-dec([int16| F], <<N:16, Bin/binary>>) ->
- [N| dec(F, Bin)];
-dec([int32| F], <<N:32, Bin/binary>>) ->
- [N| dec(F, Bin)];
-dec([string| F], Bin0) ->
- {Cs, Bin1} = dec_string(Bin0),
- [Cs| dec(F, Bin1)];
-dec([atom|F], Bin0) ->
- {Cs, Bin1} = dec_string(Bin0),
- [list_to_atom(Cs)| dec(F, Bin1)];
-
-dec([bin|F], Bin) ->
- {Bin1, Bin2} = dec_bin(Bin),
- [Bin1| dec(F, Bin2)].
-
-%% NOTE: This clause is not actually used yet.
-%% dec([bins|F], <<N:32, Bin0/binary>>) ->
-%% {Bins, Bin1} = dec_bins(N, Bin0),
-%% [Bins| dec(F, Bin1)].
-
-dec_string(Bin) ->
- dec_string(Bin, []).
-
-dec_string(<<0, Bin/binary>>, RCs) ->
- {lists:reverse(RCs), Bin};
-dec_string(<<C, Bin/binary>>, RCs) ->
- dec_string(Bin, [C| RCs]).
-
-dec_bin(<<L:32, Bin0/binary>>) ->
- <<Bin1:L/binary, Bin2/binary>> = Bin0,
- {Bin1, Bin2}.
-
-%% dec_bins(N, Bin) ->
-%% dec_bins(N, Bin, []).
-
-%% dec_bins(0, Bin, Acc) ->
-%% {lists:reverse(Acc), Bin};
-%% dec_bins(N, Bin0, Acc) when N > 0 ->
-%% {Bin1, Bin2} = dec_bin(Bin0),
-%% dec_bins(N - 1, Bin2, [Bin1| Acc]).
-
-%%
-%% new_intref
-%%
-new_intref(St) ->
- (St#st.intref + 1) band 16#ffffffff.
-
-%%
-%% {Program, Flags} = mk_cmd_line(DefaultProgram)
-%%
-mk_cmd_line(Default) ->
- {port_program(Default),
- lists:flatten([debug_flag(), " ", debug_port_flag(), " ",
- debugdir_flag(), " ",
- msgdebug_flag(), " ", proxylsport_flag(), " ",
- proxybacklog_flag(), " ", ephemeral_rsa_flag(), " ",
- ephemeral_dh_flag(), " ",
- protocol_version_flag(), " "])}.
-
-port_program(Default) ->
- case application:get_env(ssl, port_program) of
- {ok, Program} when is_list(Program) ->
- Program;
- _Other ->
- Default
- end.
-
-%%
-%% As this server may be started by the distribution, it is not safe to assume
-%% a working code server, neither a working file server.
-%% I try to utilize the most primitive interfaces available to determine
-%% the directory of the port_program.
-%%
-find_priv_bin() ->
- PrivDir = case (catch code:priv_dir(ssl)) of
- {'EXIT', _} ->
- %% Code server probably not startet yet
- {ok, P} = erl_prim_loader:get_path(),
- ModuleFile = atom_to_list(?MODULE) ++ extension(),
- Pd = (catch lists:foldl
- (fun(X,Acc) ->
- M = filename:join([X, ModuleFile]),
- %% The file server probably not started
- %% either, has to use raw interface.
- case file:raw_read_file_info(M) of
- {ok,_} ->
- %% Found our own module in the
- %% path, lets bail out with
- %% the priv_dir of this directory
- Y = filename:split(X),
- throw(filename:join
- (lists:sublist
- (Y,length(Y) - 1)
- ++ ["priv"]));
- _ ->
- Acc
- end
- end,
- false,P)),
- case Pd of
- false ->
- exit(ssl_priv_dir_indeterminate);
- _ ->
- Pd
- end;
- Dir ->
- Dir
- end,
- filename:join([PrivDir, "bin"]).
-
-extension() ->
- %% erlang:info(machine) returns machine name as text in all uppercase
- "." ++ string:to_lower(erlang:system_info(machine)).
-
-debug_flag() ->
- case os:getenv("ERL_SSL_DEBUG") of
- false ->
- get_env(debug, "-d");
- _ ->
- "-d"
- end.
-
-debug_port_flag() ->
- case os:getenv("ERL_SSL_DEBUGPORT") of
- false ->
- get_env(debug, "-d");
- _ ->
- "-d"
- end.
-
-msgdebug_flag() ->
- case os:getenv("ERL_SSL_MSGDEBUG") of
- false ->
- get_env(msgdebug, "-dm");
- _ ->
- "-dm"
- end.
-
-proxylsport_flag() ->
- case application:get_env(ssl, proxylsport) of
- {ok, PortNum} ->
- "-pp " ++ integer_to_list(PortNum);
- _Other ->
- ""
- end.
-
-proxybacklog_flag() ->
- case application:get_env(ssl, proxylsbacklog) of
- {ok, Size} ->
- "-pb " ++ integer_to_list(Size);
- _Other ->
- ""
- end.
-
-debugdir_flag() ->
- case os:getenv("ERL_SSL_DEBUG") of
- false ->
- case application:get_env(ssl, debugdir) of
- {ok, Dir} when is_list(Dir) ->
- "-dd " ++ Dir;
- _Other ->
- ""
- end;
- _ ->
- "-dd ./"
- end.
-
-ephemeral_rsa_flag() ->
- case application:get_env(ssl, ephemeral_rsa) of
- {ok, true} ->
- "-ersa ";
- _Other ->
- ""
- end.
-
-ephemeral_dh_flag() ->
- case application:get_env(ssl, ephemeral_dh) of
- {ok, true} ->
- "-edh ";
- _Other ->
- ""
- end.
-
-protocol_version_flag() ->
- case application:get_env(ssl, protocol_version) of
- {ok, []} ->
- "";
- {ok, Vsns} when is_list(Vsns) ->
- case transform_vsns(Vsns) of
- N when (N > 0) ->
- "-pv " ++ integer_to_list(N);
- _ ->
- ""
- end;
- _Other ->
- ""
- end.
-
-transform_vsns(Vsns) ->
- transform_vsns(Vsns, 0).
-
-transform_vsns([sslv2| Vsns], I) ->
- transform_vsns(Vsns, I bor ?SSLv2);
-transform_vsns([sslv3| Vsns], I) ->
- transform_vsns(Vsns, I bor ?SSLv3);
-transform_vsns([tlsv1| Vsns], I) ->
- transform_vsns(Vsns, I bor ?TLSv1);
-transform_vsns([_ | Vsns], I) ->
- transform_vsns(Vsns, I);
-transform_vsns([], I) ->
- I.
-
-protocol_name("SSLv2") -> sslv2;
-protocol_name("SSLv3") -> sslv3;
-protocol_name("TLSv1") -> tlsv1.
-
-get_env(Key, Val) ->
- case application:get_env(ssl, Key) of
- {ok, true} ->
- Val;
- _Other ->
- ""
- end.
-
-ip_to_string({A,B,C,D}) ->
- [integer_to_list(A),$.,integer_to_list(B),$.,
- integer_to_list(C),$.,integer_to_list(D)].
-
-debug(St, Format, Args) ->
- debug1(St#st.debug, Format, Args).
-
-debug1(true, Format0, Args) ->
- {_MS, S, MiS} = erlang:now(),
- Secs = S rem 100,
- MiSecs = MiS div 1000,
- Format = "++++ ~3..0w:~3..0w ssl_server (~w): " ++ Format0,
- io:format(Format, [Secs, MiSecs, self()| Args]);
-debug1(_, _, _) ->
- ok.
diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl
index dc4b7a711c..bf738649f6 100644
--- a/lib/ssl/src/ssl_session.erl
+++ b/lib/ssl/src/ssl_session.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -48,7 +48,7 @@ is_new(_ClientSuggestion, _ServerDecision) ->
true.
%%--------------------------------------------------------------------
--spec id({host(), port_num(), #ssl_options{}}, cache_ref(), atom(),
+-spec id({host(), inet:port_number(), #ssl_options{}}, db_handle(), atom(),
undefined | binary()) -> binary().
%%
%% Description: Should be called by the client side to get an id
@@ -63,7 +63,7 @@ id(ClientInfo, Cache, CacheCb, OwnCert) ->
end.
%%--------------------------------------------------------------------
--spec id(port_num(), binary(), #ssl_options{}, cache_ref(),
+-spec id(inet:port_number(), binary(), #ssl_options{}, db_handle(),
atom(), seconds(), binary()) -> binary().
%%
%% Description: Should be called by the server side to get an id
diff --git a/lib/ssl/src/ssl_session_cache.erl b/lib/ssl/src/ssl_session_cache.erl
index 823bf7acfa..93969f628f 100644
--- a/lib/ssl/src/ssl_session_cache.erl
+++ b/lib/ssl/src/ssl_session_cache.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The 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,10 +28,10 @@
-export([init/1, terminate/1, lookup/2, update/3, delete/2, foldl/3,
select_session/2]).
--type key() :: {{host(), port_num()}, session_id()} | {port_num(), session_id()}.
+-type key() :: {{host(), inet:port_number()}, session_id()} | {inet:port_number(), session_id()}.
%%--------------------------------------------------------------------
--spec init(list()) -> cache_ref(). %% Returns reference to the cache (opaque)
+-spec init(list()) -> db_handle(). %% Returns reference to the cache (opaque)
%%
%% Description: Return table reference. Called by ssl_manager process.
%%--------------------------------------------------------------------
@@ -39,7 +39,7 @@ init(_) ->
ets:new(cache_name(), [set, protected]).
%%--------------------------------------------------------------------
--spec terminate(cache_ref()) -> any(). %%
+-spec terminate(db_handle()) -> any().
%%
%% Description: Handles cache table at termination of ssl manager.
%%--------------------------------------------------------------------
@@ -47,7 +47,7 @@ terminate(Cache) ->
ets:delete(Cache).
%%--------------------------------------------------------------------
--spec lookup(cache_ref(), key()) -> #session{} | undefined.
+-spec lookup(db_handle(), key()) -> #session{} | undefined.
%%
%% Description: Looks up a cach entry. Should be callable from any
%% process.
@@ -61,7 +61,7 @@ lookup(Cache, Key) ->
end.
%%--------------------------------------------------------------------
--spec update(cache_ref(), key(), #session{}) -> any().
+-spec update(db_handle(), key(), #session{}) -> any().
%%
%% Description: Caches a new session or updates a already cached one.
%% Will only be called from the ssl_manager process.
@@ -70,7 +70,7 @@ update(Cache, Key, Session) ->
ets:insert(Cache, {Key, Session}).
%%--------------------------------------------------------------------
--spec delete(cache_ref(), key()) -> any().
+-spec delete(db_handle(), key()) -> any().
%%
%% Description: Delets a cache entry.
%% Will only be called from the ssl_manager process.
@@ -79,7 +79,7 @@ delete(Cache, Key) ->
ets:delete(Cache, Key).
%%--------------------------------------------------------------------
--spec foldl(fun(), term(), cache_ref()) -> term().
+-spec foldl(fun(), term(), db_handle()) -> term().
%%
%% Description: Calls Fun(Elem, AccIn) on successive elements of the
%% cache, starting with AccIn == Acc0. Fun/2 must return a new
@@ -91,7 +91,7 @@ foldl(Fun, Acc0, Cache) ->
ets:foldl(Fun, Acc0, Cache).
%%--------------------------------------------------------------------
--spec select_session(cache_ref(), {host(), port_num()} | port_num()) -> [#session{}].
+-spec select_session(db_handle(), {host(), inet:port_number()} | inet:port_number()) -> [#session{}].
%%
%% Description: Selects a session that could be reused. Should be callable
%% from any process.
diff --git a/lib/ssl/src/ssl_ssl2.erl b/lib/ssl/src/ssl_ssl2.erl
index b1005b1acb..a9ab6a2678 100644
--- a/lib/ssl/src/ssl_ssl2.erl
+++ b/lib/ssl/src/ssl_ssl2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The 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,7 +20,7 @@
%%
%%----------------------------------------------------------------------
%% Purpose: Handles sslv2 hello as clients supporting sslv2 and higher
-%% will send a sslv2 hello.
+%% will send an sslv2 hello.
%%----------------------------------------------------------------------
-module(ssl_ssl2).
diff --git a/lib/ssl/src/ssl_sup.erl b/lib/ssl/src/ssl_sup.erl
index 316ed8a4e9..cb10b1362a 100644
--- a/lib/ssl/src/ssl_sup.erl
+++ b/lib/ssl/src/ssl_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The 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 @@
-behaviour(supervisor).
%% API
--export([start_link/0]).
+-export([start_link/0, manager_opts/0]).
%% Supervisor callback
-export([init/1]).
@@ -51,17 +51,32 @@ init([]) ->
%% Does not start any port programs so it does matter
%% so much if it is not used!
- Child2 = {ssl_broker_sup, {ssl_broker_sup, start_link, []},
- permanent, 2000, supervisor, [ssl_broker_sup]},
+ %% Child2 = {ssl_broker_sup, {ssl_broker_sup, start_link, []},
+ %% permanent, 2000, supervisor, [ssl_broker_sup]},
%% New ssl
SessionCertManager = session_and_cert_manager_child_spec(),
ConnetionManager = connection_manager_child_spec(),
- {ok, {{one_for_all, 10, 3600}, [Child2, SessionCertManager,
- ConnetionManager]}}.
+ {ok, {{one_for_all, 10, 3600}, [SessionCertManager, ConnetionManager]}}.
+
+manager_opts() ->
+ CbOpts = case application:get_env(ssl, session_cb) of
+ {ok, Cb} when is_atom(Cb) ->
+ InitArgs = session_cb_init_args(),
+ [{session_cb, Cb}, {session_cb_init_args, InitArgs}];
+ _ ->
+ []
+ end,
+ case application:get_env(ssl, session_lifetime) of
+ {ok, Time} when is_integer(Time) ->
+ [{session_lifetime, Time}| CbOpts];
+ _ ->
+ CbOpts
+ end.
+
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
@@ -86,21 +101,6 @@ connection_manager_child_spec() ->
{Name, StartFunc, Restart, Shutdown, Type, Modules}.
-manager_opts() ->
- CbOpts = case application:get_env(ssl, session_cb) of
- {ok, Cb} when is_atom(Cb) ->
- InitArgs = session_cb_init_args(),
- [{session_cb, Cb}, {session_cb_init_args, InitArgs}];
- _ ->
- []
- end,
- case application:get_env(ssl, session_lifetime) of
- {ok, Time} when is_integer(Time) ->
- [{session_lifetime, Time}| CbOpts];
- _ ->
- CbOpts
- end.
-
session_cb_init_args() ->
case application:get_env(ssl, session_cb_init_args) of
{ok, Args} when is_list(Args) ->
diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl
new file mode 100644
index 0000000000..d63eada571
--- /dev/null
+++ b/lib/ssl/src/ssl_tls_dist_proxy.erl
@@ -0,0 +1,325 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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_tls_dist_proxy).
+
+
+-export([listen/1, accept/1, connect/2, get_remote_id/2]).
+-export([init/1, start_link/0, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3, ssl_options/2]).
+
+-include_lib("kernel/include/net_address.hrl").
+
+-record(state,
+ {listen,
+ accept_loop
+ }).
+
+-define(PPRE, 4).
+-define(PPOST, 4).
+
+
+%%====================================================================
+%% Internal application API
+%%====================================================================
+
+listen(Name) ->
+ gen_server:call(?MODULE, {listen, Name}, infinity).
+
+accept(Listen) ->
+ gen_server:call(?MODULE, {accept, Listen}, infinity).
+
+connect(Ip, Port) ->
+ gen_server:call(?MODULE, {connect, Ip, Port}, infinity).
+
+get_remote_id(Socket, Node) ->
+ gen_server:call(?MODULE, {get_remote_id, {Socket,Node}}, infinity).
+
+%%====================================================================
+%% gen_server callbacks
+%%====================================================================
+
+start_link() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
+init([]) ->
+ process_flag(priority, max),
+ {ok, #state{}}.
+
+handle_call({listen, Name}, _From, State) ->
+ case gen_tcp:listen(0, [{active, false}, {packet,?PPRE}]) of
+ {ok, Socket} ->
+ {ok, World} = gen_tcp:listen(0, [{active, false}, binary, {packet,?PPRE}]),
+ TcpAddress = get_tcp_address(Socket),
+ WorldTcpAddress = get_tcp_address(World),
+ {_,Port} = WorldTcpAddress#net_address.address,
+ {ok, Creation} = erl_epmd:register_node(Name, Port),
+ {reply, {ok, {Socket, TcpAddress, Creation}},
+ State#state{listen={Socket, World}}};
+ Error ->
+ {reply, Error, State}
+ end;
+
+handle_call({accept, Listen}, {From, _}, State = #state{listen={_, World}}) ->
+ Self = self(),
+ ErtsPid = spawn_link(fun() -> accept_loop(Self, erts, Listen, From) end),
+ WorldPid = spawn_link(fun() -> accept_loop(Self, world, World, Listen) end),
+ {reply, ErtsPid, State#state{accept_loop={ErtsPid, WorldPid}}};
+
+handle_call({connect, Ip, Port}, {From, _}, State) ->
+ Me = self(),
+ Pid = spawn_link(fun() -> setup_proxy(Ip, Port, Me) end),
+ receive
+ {Pid, go_ahead, LPort} ->
+ Res = {ok, Socket} = try_connect(LPort),
+ ok = gen_tcp:controlling_process(Socket, From),
+ flush_old_controller(From, Socket),
+ {reply, Res, State};
+ {Pid, Error} ->
+ {reply, Error, State}
+ end;
+
+handle_call({get_remote_id, {Socket,_Node}}, _From, State) ->
+ Address = get_tcp_address(Socket),
+ {reply, Address, State};
+
+handle_call(_What, _From, State) ->
+ {reply, ok, State}.
+
+handle_cast(_What, State) ->
+ {noreply, State}.
+
+handle_info(_What, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _St) ->
+ ok.
+
+code_change(_OldVsn, St, _Extra) ->
+ {ok, St}.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+get_tcp_address(Socket) ->
+ {ok, Address} = inet:sockname(Socket),
+ {ok, Host} = inet:gethostname(),
+ #net_address{
+ address = Address,
+ host = Host,
+ protocol = proxy,
+ family = inet
+ }.
+
+accept_loop(Proxy, erts = Type, Listen, Extra) ->
+ process_flag(priority, max),
+ case gen_tcp:accept(Listen) of
+ {ok, Socket} ->
+ Extra ! {accept,self(),Socket,inet,proxy},
+ receive
+ {_Kernel, controller, Pid} ->
+ ok = gen_tcp:controlling_process(Socket, Pid),
+ flush_old_controller(Pid, Socket),
+ Pid ! {self(), controller};
+ {_Kernel, unsupported_protocol} ->
+ exit(unsupported_protocol)
+ end;
+ Error ->
+ exit(Error)
+ end,
+ accept_loop(Proxy, Type, Listen, Extra);
+
+accept_loop(Proxy, world = Type, Listen, Extra) ->
+ process_flag(priority, max),
+ case gen_tcp:accept(Listen) of
+ {ok, Socket} ->
+ Opts = get_ssl_options(server),
+ case ssl:ssl_accept(Socket, Opts) of
+ {ok, SslSocket} ->
+ PairHandler =
+ spawn_link(fun() ->
+ setup_connection(SslSocket, Extra)
+ end),
+ ok = ssl:controlling_process(SslSocket, PairHandler),
+ flush_old_controller(PairHandler, SslSocket);
+ _ ->
+ gen_tcp:close(Socket)
+ end;
+ Error ->
+ exit(Error)
+ end,
+ accept_loop(Proxy, Type, Listen, Extra).
+
+try_connect(Port) ->
+ case gen_tcp:connect({127,0,0,1}, Port, [{active, false}, {packet,?PPRE}]) of
+ R = {ok, _S} ->
+ R;
+ {error, _R} ->
+ try_connect(Port)
+ end.
+
+setup_proxy(Ip, Port, Parent) ->
+ process_flag(trap_exit, true),
+ Opts = get_ssl_options(client),
+ case ssl:connect(Ip, Port, [{active, true}, binary, {packet,?PPRE}] ++ Opts) of
+ {ok, World} ->
+ {ok, ErtsL} = gen_tcp:listen(0, [{active, true}, binary, {packet,?PPRE}]),
+ #net_address{address={_,LPort}} = get_tcp_address(ErtsL),
+ Parent ! {self(), go_ahead, LPort},
+ case gen_tcp:accept(ErtsL) of
+ {ok, Erts} ->
+ %% gen_tcp:close(ErtsL),
+ loop_conn_setup(World, Erts);
+ Err ->
+ Parent ! {self(), Err}
+ end;
+ Err ->
+ Parent ! {self(), Err}
+ end.
+
+setup_connection(World, ErtsListen) ->
+ process_flag(trap_exit, true),
+ TcpAddress = get_tcp_address(ErtsListen),
+ {_Addr,Port} = TcpAddress#net_address.address,
+ {ok, Erts} = gen_tcp:connect({127,0,0,1}, Port, [{active, true}, binary, {packet,?PPRE}]),
+ ssl:setopts(World, [{active,true}, {packet,?PPRE}]),
+ loop_conn_setup(World, Erts).
+
+loop_conn_setup(World, Erts) ->
+ receive
+ {ssl, World, Data = <<$a, _/binary>>} ->
+ gen_tcp:send(Erts, Data),
+ ssl:setopts(World, [{packet,?PPOST}]),
+ inet:setopts(Erts, [{packet,?PPOST}]),
+ loop_conn(World, Erts);
+ {tcp, Erts, Data = <<$a, _/binary>>} ->
+ ssl:send(World, Data),
+ ssl:setopts(World, [{packet,?PPOST}]),
+ inet:setopts(Erts, [{packet,?PPOST}]),
+ loop_conn(World, Erts);
+ {ssl, World, Data = <<_, _/binary>>} ->
+ gen_tcp:send(Erts, Data),
+ loop_conn_setup(World, Erts);
+ {tcp, Erts, Data = <<_, _/binary>>} ->
+ ssl:send(World, Data),
+ loop_conn_setup(World, Erts);
+ {ssl, World, Data} ->
+ gen_tcp:send(Erts, Data),
+ loop_conn_setup(World, Erts);
+ {tcp, Erts, Data} ->
+ ssl:send(World, Data),
+ loop_conn_setup(World, Erts)
+ end.
+
+loop_conn(World, Erts) ->
+ receive
+ {ssl, World, Data} ->
+ gen_tcp:send(Erts, Data),
+ loop_conn(World, Erts);
+ {tcp, Erts, Data} ->
+ ssl:send(World, Data),
+ loop_conn(World, Erts);
+ {tcp_closed, Erts} ->
+ ssl:close(World);
+ {ssl_closed, World} ->
+ gen_tcp:close(Erts)
+ end.
+
+get_ssl_options(Type) ->
+ case init:get_argument(ssl_dist_opt) of
+ {ok, Args} ->
+ [{erl_dist, true} | ssl_options(Type, lists:append(Args))];
+ _ ->
+ [{erl_dist, true}]
+ end.
+
+ssl_options(_,[]) ->
+ [];
+ssl_options(server, ["client_" ++ _, _Value |T]) ->
+ ssl_options(server,T);
+ssl_options(client, ["server_" ++ _, _Value|T]) ->
+ ssl_options(client,T);
+ssl_options(server, ["server_certfile", Value|T]) ->
+ [{certfile, Value} | ssl_options(server,T)];
+ssl_options(client, ["client_certfile", Value | T]) ->
+ [{certfile, Value} | ssl_options(client,T)];
+ssl_options(server, ["server_cacertfile", Value|T]) ->
+ [{cacertfile, Value} | ssl_options(server,T)];
+ssl_options(client, ["client_cacertfile", Value|T]) ->
+ [{cacertfile, Value} | ssl_options(client,T)];
+ssl_options(server, ["server_keyfile", Value|T]) ->
+ [{keyfile, Value} | ssl_options(server,T)];
+ssl_options(client, ["client_keyfile", Value|T]) ->
+ [{keyfile, Value} | ssl_options(client,T)];
+ssl_options(server, ["server_password", Value|T]) ->
+ [{password, Value} | ssl_options(server,T)];
+ssl_options(client, ["client_password", Value|T]) ->
+ [{password, Value} | ssl_options(client,T)];
+ssl_options(server, ["server_verify", Value|T]) ->
+ [{verify, atomize(Value)} | ssl_options(server,T)];
+ssl_options(client, ["client_verify", Value|T]) ->
+ [{verify, atomize(Value)} | ssl_options(client,T)];
+ssl_options(server, ["server_reuse_sessions", Value|T]) ->
+ [{reuse_sessions, atomize(Value)} | ssl_options(server,T)];
+ssl_options(client, ["client_reuse_sessions", Value|T]) ->
+ [{reuse_sessions, atomize(Value)} | ssl_options(client,T)];
+ssl_options(server, ["server_secure_renegotiate", Value|T]) ->
+ [{secure_renegotiate, atomize(Value)} | ssl_options(server,T)];
+ssl_options(client, ["client_secure_renegotiate", Value|T]) ->
+ [{secure_renegotiate, atomize(Value)} | ssl_options(client,T)];
+ssl_options(server, ["server_depth", Value|T]) ->
+ [{depth, list_to_integer(Value)} | ssl_options(server,T)];
+ssl_options(client, ["client_depth", Value|T]) ->
+ [{depth, list_to_integer(Value)} | ssl_options(client,T)];
+ssl_options(server, ["server_hibernate_after", Value|T]) ->
+ [{hibernate_after, list_to_integer(Value)} | ssl_options(server,T)];
+ssl_options(client, ["client_hibernate_after", Value|T]) ->
+ [{hibernate_after, list_to_integer(Value)} | ssl_options(client,T)];
+ssl_options(server, ["server_ciphers", Value|T]) ->
+ [{ciphers, Value} | ssl_options(server,T)];
+ssl_options(client, ["client_ciphers", Value|T]) ->
+ [{ciphers, Value} | ssl_options(client,T)];
+ssl_options(server, ["server_dhfile", Value|T]) ->
+ [{dhfile, Value} | ssl_options(server,T)];
+ssl_options(server, ["server_fail_if_no_peer_cert", Value|T]) ->
+ [{fail_if_no_peer_cert, atomize(Value)} | ssl_options(server,T)];
+ssl_options(_,_) ->
+ exit(malformed_ssl_dist_opt).
+
+atomize(List) when is_list(List) ->
+ list_to_atom(List);
+atomize(Atom) when is_atom(Atom) ->
+ Atom.
+
+flush_old_controller(Pid, Socket) ->
+ receive
+ {tcp, Socket, Data} ->
+ Pid ! {tcp, Socket, Data},
+ flush_old_controller(Pid, Socket);
+ {tcp_closed, Socket} ->
+ Pid ! {tcp_closed, Socket},
+ flush_old_controller(Pid, Socket);
+ {ssl, Socket, Data} ->
+ Pid ! {ssl, Socket, Data},
+ flush_old_controller(Pid, Socket);
+ {ssl_closed, Socket} ->
+ Pid ! {ssl_closed, Socket},
+ flush_old_controller(Pid, Socket)
+ after 0 ->
+ ok
+ end.
diff --git a/lib/ssl/test/Makefile b/lib/ssl/test/Makefile
index fd3b6d06ad..23a9a23190 100644
--- a/lib/ssl/test/Makefile
+++ b/lib/ssl/test/Makefile
@@ -35,34 +35,27 @@ VSN=$(GS_VSN)
# ----------------------------------------------------
MODULES = \
- ssl_test_lib \
+ ssl_test_lib \
ssl_basic_SUITE \
+ ssl_handshake_SUITE \
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 \
- old_ssl_passive_SUITE \
- old_ssl_verify_SUITE \
- old_ssl_peer_cert_SUITE \
- old_ssl_misc_SUITE \
- old_ssl_protocol_SUITE \
- old_transport_accept_SUITE \
- old_ssl_dist_SUITE \
+ ssl_dist_SUITE \
make_certs\
erl_make_certs
ERL_FILES = $(MODULES:%=%.erl)
-HRL_FILES = ssl_test_MACHINE.hrl
+HRL_FILES =
HRL_FILES_SRC = \
- ssl_int.hrl \
+ ssl_internal.hrl\
ssl_alert.hrl \
- ssl_handshake.hrl
+ ssl_handshake.hrl \
+ ssl_record.hrl
HRL_FILES_INC =
@@ -128,7 +121,7 @@ release_tests_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(HRL_FILES_NEEDED_IN_TEST) $(COVER_FILE) $(RELSYSDIR)
$(INSTALL_DATA) ssl.spec ssl.cover $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/ssl/test/old_ssl_active_SUITE.erl b/lib/ssl/test/old_ssl_active_SUITE.erl
deleted file mode 100644
index 52ff0bcc5d..0000000000
--- a/lib/ssl/test/old_ssl_active_SUITE.erl
+++ /dev/null
@@ -1,395 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, 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(old_ssl_active_SUITE).
-
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,
- end_per_testcase/2,
- cinit_return_chkclose/1,
- sinit_return_chkclose/1,
- cinit_big_return_chkclose/1,
- sinit_big_return_chkclose/1,
- cinit_big_echo_chkclose/1,
- cinit_huge_echo_chkclose/1,
- sinit_big_echo_chkclose/1,
- cinit_few_echo_chkclose/1,
- cinit_many_echo_chkclose/1,
- cinit_cnocert/1
- ]).
-
--import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
- test_server_only/6]).
-
--include_lib("test_server/include/test_server.hrl").
--include("ssl_test_MACHINE.hrl").
-
--define(MANYCONNS, ssl_test_MACHINE:many_conns()).
-
-init_per_testcase(_Case, Config) ->
- WatchDog = ssl_test_lib:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- WatchDog = ?config(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [cinit_return_chkclose, sinit_return_chkclose,
- cinit_big_return_chkclose, sinit_big_return_chkclose,
- cinit_big_echo_chkclose, cinit_huge_echo_chkclose,
- sinit_big_echo_chkclose, cinit_few_echo_chkclose,
- cinit_many_echo_chkclose, cinit_cnocert].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_suite(doc) ->
- "Want to se what Config contains, and record the number of available "
- "file descriptors";
-init_per_suite(suite) ->
- [];
-init_per_suite(Config) ->
- io:format("Config: ~p~n", [Config]),
- case os:type() of
- {unix, _} ->
- ?line io:format("Max fd value: ~s", [os:cmd("ulimit -n")]);
- _ ->
- ok
- end,
- %% XXX Also record: Erlang/SSL version, version of OpenSSL,
- %% operating system, version of OTP, Erts, kernel and stdlib.
-
- %% Check if SSL exists. If this case fails, all other cases are skipped
- case catch crypto:start() of
- ok ->
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config;
- _Else ->
- {skip,"Could not start crypto!"}
- end.
-
-end_per_suite(doc) ->
- "This test case has no mission other than closing the conf case";
-end_per_suite(suite) ->
- [];
-end_per_suite(Config) ->
- crypto:stop(),
- Config.
-
-cinit_return_chkclose(doc) ->
- "Client sends 1000 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Both have certs.";
-cinit_return_chkclose(suite) ->
- [];
-cinit_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize}, {send, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-sinit_return_chkclose(doc) ->
- "Server sends 1000 bytes to client, that receives them, sends them "
- "back, and closes. Server waits for close. Both have certs.";
-sinit_return_chkclose(suite) ->
- [];
-sinit_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, [{ssl_imp, old}|SsslOpts]},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {send, DataSize}, {recv, DataSize},
- await_close],
- CCmds = [{timeout, Timeout},
- {sslopts, [{ssl_imp, old}|CsslOpts]},
- {connect, {Host, LPort}},
- {recv, DataSize}, {send, DataSize},
- close],
-
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_big_return_chkclose(doc) ->
- "Client sends 50000 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Both have certs.";
-cinit_big_return_chkclose(suite) ->
- [];
-cinit_big_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize}, {send, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-sinit_big_return_chkclose(doc) ->
- "Server sends 50000 bytes to client, that receives them, sends them "
- "back, and closes. Server waits for close. Both have certs.";
-sinit_big_return_chkclose(suite) ->
- [];
-sinit_big_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {send, DataSize}, {recv, DataSize},
- await_close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {recv, DataSize}, {send, DataSize},
- close],
-
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_big_echo_chkclose(doc) ->
- "Client sends 50000 bytes to server, that echoes them back "
- "and closes. Client waits for close. Both have certs.";
-cinit_big_echo_chkclose(suite) ->
- [];
-cinit_big_echo_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {echo, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_huge_echo_chkclose(doc) ->
- "Client sends 500000 bytes to server, that echoes them back "
- "and closes. Client waits for close. Both have certs.";
-cinit_huge_echo_chkclose(suite) ->
- [];
-cinit_huge_echo_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 500000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {echo, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-sinit_big_echo_chkclose(doc) ->
- "Server sends 50000 bytes to client, that echoes them back "
- "and closes. Server waits for close. Both have certs.";
-sinit_big_echo_chkclose(suite) ->
- [];
-sinit_big_echo_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {send, DataSize}, {recv, DataSize},
- await_close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {echo, DataSize},
- close],
-
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-
-%% This case is repeated several times.
-
-cinit_few_echo_chkclose(X) -> cinit_many_echo_chkclose(X, 7).
-
-cinit_many_echo_chkclose(X) -> cinit_many_echo_chkclose(X, ?MANYCONNS).
-
-cinit_many_echo_chkclose(doc, _NConns) ->
- "N client sends 10000 bytes to server, that echoes them back "
- "and closes. Clients wait for close. All have certs.";
-cinit_many_echo_chkclose(suite, _NConns) ->
- [];
-cinit_many_echo_chkclose(Config, NConns) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 10000, LPort = 3456,
- Timeout = 80000,
-
- io:format("~w connections", [NConns]),
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {echo, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-
-cinit_cnocert(doc) ->
- "Client sends 1000 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Client has no cert, "
- "but server has.";
-cinit_cnocert(suite) ->
- [];
-cinit_cnocert(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3457,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {_CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize}, {send, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-
diff --git a/lib/ssl/test/old_ssl_active_once_SUITE.erl b/lib/ssl/test/old_ssl_active_once_SUITE.erl
deleted file mode 100644
index c7beadb301..0000000000
--- a/lib/ssl/test/old_ssl_active_once_SUITE.erl
+++ /dev/null
@@ -1,417 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, 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(old_ssl_active_once_SUITE).
-
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,
- end_per_testcase/2,
- server_accept_timeout/1,
- cinit_return_chkclose/1,
- sinit_return_chkclose/1,
- cinit_big_return_chkclose/1,
- sinit_big_return_chkclose/1,
- cinit_big_echo_chkclose/1,
- cinit_huge_echo_chkclose/1,
- sinit_big_echo_chkclose/1,
- cinit_few_echo_chkclose/1,
- cinit_many_echo_chkclose/1,
- cinit_cnocert/1
- ]).
-
--import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
- test_server_only/6]).
--include_lib("test_server/include/test_server.hrl").
--include("ssl_test_MACHINE.hrl").
-
--define(MANYCONNS, ssl_test_MACHINE:many_conns()).
-
-init_per_testcase(_Case, Config) ->
- WatchDog = ssl_test_lib:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- WatchDog = ?config(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [server_accept_timeout, cinit_return_chkclose,
- sinit_return_chkclose, cinit_big_return_chkclose,
- sinit_big_return_chkclose, cinit_big_echo_chkclose,
- cinit_huge_echo_chkclose, sinit_big_echo_chkclose,
- cinit_few_echo_chkclose, cinit_many_echo_chkclose,
- cinit_cnocert].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_suite(doc) ->
- "Want to se what Config contains.";
-init_per_suite(suite) ->
- [];
-init_per_suite(Config) ->
- io:format("Config: ~p~n", [Config]),
-
- %% Check if SSL exists. If this case fails, all other cases are skipped
- case catch crypto:start() of
- ok ->
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config;
- _Else ->
- {skip,"Could not start crypto"}
- end.
-
-end_per_suite(doc) ->
- "This test case has no mission other than closing the conf case";
-end_per_suite(suite) ->
- [];
-end_per_suite(Config) ->
- crypto:stop(),
- Config.
-
-server_accept_timeout(doc) ->
- "Server has one pending accept with timeout. Checks that return "
- "value is {error, timeout}.";
-server_accept_timeout(suite) ->
- [];
-server_accept_timeout(Config) when list(Config) ->
- process_flag(trap_exit, true),
- LPort = 3456,
- Timeout = 40000, NConns = 1,
- AccTimeout = 3000,
-
- ?line {ok, {_, SsslOpts}} = mk_ssl_cert_opts(Config),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, AccTimeout},
- accept_timeout],
- ?line test_server_only(NConns, LCmds, ACmds, Timeout, ?MODULE,
- Config).
-
-cinit_return_chkclose(doc) ->
- "Client sends 1000 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Both have certs.";
-cinit_return_chkclose(suite) ->
- [];
-cinit_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize}, {send, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, once}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-sinit_return_chkclose(doc) ->
- "Server sends 1000 bytes to client, that receives them, sends them "
- "back, and closes. Server waits for close. Both have certs.";
-sinit_return_chkclose(suite) ->
- [];
-sinit_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {send, DataSize}, {recv, DataSize},
- await_close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, once}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {recv, DataSize}, {send, DataSize},
- close],
-
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_big_return_chkclose(doc) ->
- "Client sends 50000 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Both have certs.";
-cinit_big_return_chkclose(suite) ->
- [];
-cinit_big_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- %% Set {active, false} so that accept is passive to begin with.
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {sockopts, [{active, once}]}, % {active, once} here.
- {recv, DataSize}, {send, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, once}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-sinit_big_return_chkclose(doc) ->
- "Server sends 50000 bytes to client, that receives them, sends them "
- "back, and closes. Server waits for close. Both have certs.";
-sinit_big_return_chkclose(suite) ->
- [];
-sinit_big_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {send, DataSize}, {recv, DataSize},
- await_close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, once}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {recv, DataSize}, {send, DataSize},
- close],
-
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_big_echo_chkclose(doc) ->
- "Client sends 50000 bytes to server, that echoes them back "
- "and closes. Client waits for close. Both have certs.";
-cinit_big_echo_chkclose(suite) ->
- [];
-cinit_big_echo_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {echo, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, once}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_huge_echo_chkclose(doc) ->
- "Client sends 500000 bytes to server, that echoes them back "
- "and closes. Client waits for close. Both have certs.";
-cinit_huge_echo_chkclose(suite) ->
- [];
-cinit_huge_echo_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 500000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {echo, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, once}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-sinit_big_echo_chkclose(doc) ->
- "Server sends 50000 bytes to client, that echoes them back "
- "and closes. Server waits for close. Both have certs.";
-sinit_big_echo_chkclose(suite) ->
- [];
-sinit_big_echo_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {send, DataSize}, {recv, DataSize},
- await_close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, once}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {echo, DataSize},
- close],
-
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_few_echo_chkclose(X) -> cinit_many_echo_chkclose(X, 7).
-
-cinit_many_echo_chkclose(X) -> cinit_many_echo_chkclose(X, ?MANYCONNS).
-
-cinit_many_echo_chkclose(doc, _NConns) ->
- "client send 10000 bytes to server, that echoes them back "
- "and closes. Clients wait for close. All have certs.";
-cinit_many_echo_chkclose(suite, _NConns) ->
- [];
-cinit_many_echo_chkclose(Config, NConns) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 10000, LPort = 3456,
- Timeout = 80000,
-
- io:format("~w connections", [NConns]),
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {echo, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, once}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_cnocert(doc) ->
- "Client sends 1000 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Client has no cert, "
- "but server has.";
-cinit_cnocert(suite) ->
- [];
-cinit_cnocert(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3457,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {_CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize}, {send, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, once}]},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-
diff --git a/lib/ssl/test/old_ssl_dist_SUITE.erl b/lib/ssl/test/old_ssl_dist_SUITE.erl
deleted file mode 100644
index 4544fb616a..0000000000
--- a/lib/ssl/test/old_ssl_dist_SUITE.erl
+++ /dev/null
@@ -1,617 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, 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 : ssl_dist_SUITE.erl
-%%% Author : Rickard Green
-%%% Description : Test that the Erlang distribution works over ssl.
-%%%
-%%% Created : 15 Nov 2007 by Rickard Green
-%%%-------------------------------------------------------------------
--module(old_ssl_dist_SUITE).
-
--include_lib("test_server/include/test_server.hrl").
-
--define(DEFAULT_TIMETRAP_SECS, 240).
-
--define(AWAIT_SLL_NODE_UP_TIMEOUT, 30000).
-
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
--export([init_per_suite/1,
- end_per_suite/1,
- init_per_testcase/2,
- end_per_testcase/2]).
--export([cnct2tstsrvr/1]).
-
--export([basic/1]).
-
--record(node_handle, {connection_handler, socket, name, nodename}).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [basic].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_suite(Config) ->
- try crypto:start() of
- ok ->
- add_ssl_opts_config(Config)
- catch _:_ ->
- {skip, "Crypto did not start"}
- end.
-
-end_per_suite(Config) ->
- application:stop(crypto),
- Config.
-
-init_per_testcase(Case, Config) when list(Config) ->
- Dog = ?t:timetrap(?t:seconds(?DEFAULT_TIMETRAP_SECS)),
- [{watchdog, Dog},{testcase, Case}|Config].
-
-end_per_testcase(_Case, Config) when list(Config) ->
- Dog = ?config(watchdog, Config),
- ?t:timetrap_cancel(Dog),
- ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% Testcases %%
-%% %%
-
-basic(doc) ->
- ["Test that two nodes can connect via ssl distribution"];
-basic(suite) ->
- [];
-basic(Config) when is_list(Config) ->
- ?line NH1 = start_ssl_node(Config),
- ?line Node1 = NH1#node_handle.nodename,
- ?line NH2 = start_ssl_node(Config),
- ?line Node2 = NH2#node_handle.nodename,
-
- ?line pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
-
- ?line [Node2] = apply_on_ssl_node(NH1, fun () -> nodes() end),
- ?line [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end),
-
- %% The test_server node has the same cookie as the ssl nodes
- %% but it should not be able to communicate with the ssl nodes
- %% via the erlang distribution.
- ?line pang = net_adm:ping(Node1),
- ?line pang = net_adm:ping(Node2),
-
-
- %%
- %% Check that we are able to communicate over the erlang
- %% distribution between the ssl nodes.
- %%
- ?line Ref = make_ref(),
- ?line spawn(fun () ->
- apply_on_ssl_node(
- NH1,
- fun () ->
- tstsrvr_format("Hi from ~p!~n",
- [node()]),
- send_to_tstcntrl({Ref, self()}),
- receive
- {From, ping} ->
- From ! {self(), pong}
- end
- end)
- end),
- ?line receive
- {Ref, SslPid} ->
- ?line ok = apply_on_ssl_node(
- NH2,
- fun () ->
- tstsrvr_format("Hi from ~p!~n",
- [node()]),
- SslPid ! {self(), ping},
- receive
- {SslPid, pong} ->
- ok
- end
- end)
- end,
-
- ?line stop_ssl_node(NH1),
- ?line stop_ssl_node(NH2),
- ?line success(Config).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% %%
-%% Internal functions %%
-%% %%
-
-%%
-%% ssl_node side api
-%%
-
-tstsrvr_format(Fmt, ArgList) ->
- send_to_tstsrvr({format, Fmt, ArgList}).
-
-send_to_tstcntrl(Message) ->
- send_to_tstsrvr({message, Message}).
-
-
-%%
-%% test_server side api
-%%
-
-apply_on_ssl_node(Node, M, F, A) when atom(M), atom(F), list(A) ->
- Ref = make_ref(),
- send_to_ssl_node(Node, {apply, self(), Ref, M, F, A}),
- receive
- {Ref, Result} ->
- Result
- end.
-
-apply_on_ssl_node(Node, Fun) when is_function(Fun, 0) ->
- Ref = make_ref(),
- send_to_ssl_node(Node, {apply, self(), Ref, Fun}),
- receive
- {Ref, Result} ->
- Result
- end.
-
-stop_ssl_node(#node_handle{connection_handler = Handler,
- socket = Socket,
- name = Name}) ->
- ?t:format("Trying to stop ssl node ~s.~n", [Name]),
- Mon = erlang:monitor(process, Handler),
- unlink(Handler),
- case gen_tcp:send(Socket, term_to_binary(stop)) of
- ok ->
- receive
- {'DOWN', Mon, process, Handler, Reason} ->
- case Reason of
- normal -> ok;
- _ -> exit(Reason)
- end
- end;
- Error ->
- erlang:demonitor(Mon, [flush]),
- exit(Error)
- end.
-
-start_ssl_node(Config) ->
- start_ssl_node(Config, "").
-
-start_ssl_node(Config, XArgs) ->
- Name = mk_node_name(Config),
- SSL = ?config(ssl_opts, Config),
- SSLDistOpts = setup_dist_opts(Name, ?config(priv_dir, Config)),
- start_ssl_node_raw(Name, SSL ++ " " ++ SSLDistOpts ++ XArgs).
-
-start_ssl_node_raw(Name, Args) ->
- {ok, LSock} = gen_tcp:listen(0,
- [binary, {packet, 4}, {active, false}]),
- {ok, ListenPort} = inet:port(LSock),
- CmdLine = mk_node_cmdline(ListenPort, Name, Args),
- ?t:format("Attempting to start ssl node ~s: ~s~n", [Name, CmdLine]),
- case open_port({spawn, CmdLine}, []) of
- Port when port(Port) ->
- unlink(Port),
- erlang:port_close(Port),
- case await_ssl_node_up(Name, LSock) of
- #node_handle{} = NodeHandle ->
- ?t:format("Ssl node ~s started.~n", [Name]),
- NodeName = list_to_atom(Name ++ "@" ++ host_name()),
- NodeHandle#node_handle{nodename = NodeName};
- Error ->
- exit({failed_to_start_node, Name, Error})
- end;
- Error ->
- exit({failed_to_start_node, Name, Error})
- end.
-
-%%
-%% command line creation
-%%
-
-host_name() ->
- [$@ | Host] = lists:dropwhile(fun ($@) -> false; (_) -> true end,
- atom_to_list(node())),
- Host.
-
-mk_node_name(Config) ->
- {A, B, C} = erlang:now(),
- Case = ?config(testcase, Config),
- atom_to_list(?MODULE)
- ++ "_"
- ++ atom_to_list(Case)
- ++ "_"
- ++ integer_to_list(A)
- ++ "-"
- ++ integer_to_list(B)
- ++ "-"
- ++ integer_to_list(C).
-
-mk_node_cmdline(ListenPort, Name, Args) ->
- Static = "-detached -noinput",
- Pa = filename:dirname(code:which(?MODULE)),
- Prog = case catch init:get_argument(progname) of
- {ok,[[P]]} -> P;
- _ -> exit(no_progname_argument_found)
- end,
- NameSw = case net_kernel:longnames() of
- false -> "-sname ";
- _ -> "-name "
- end,
- {ok, Pwd} = file:get_cwd(),
- Prog ++ " "
- ++ Static ++ " "
- ++ NameSw ++ " " ++ Name ++ " "
- ++ "-pa " ++ Pa ++ " "
- ++ "-run application start crypto -run application start public_key "
- ++ "-run " ++ atom_to_list(?MODULE) ++ " cnct2tstsrvr "
- ++ host_name() ++ " "
- ++ integer_to_list(ListenPort) ++ " "
- ++ Args ++ " "
- ++ "-env ERL_CRASH_DUMP " ++ Pwd ++ "/erl_crash_dump." ++ Name ++ " "
- ++ "-setcookie " ++ atom_to_list(erlang:get_cookie()).
-
-%%
-%% Connection handler test_server side
-%%
-
-await_ssl_node_up(Name, LSock) ->
- case gen_tcp:accept(LSock, ?AWAIT_SLL_NODE_UP_TIMEOUT) of
- timeout ->
- gen_tcp:close(LSock),
- ?t:format("Timeout waiting for ssl node ~s to come up~n",
- [Name]),
- timeout;
- {ok, Socket} ->
- gen_tcp:close(LSock),
- case gen_tcp:recv(Socket, 0) of
- {ok, Bin} ->
- check_ssl_node_up(Socket, Name, Bin);
- {error, closed} ->
- gen_tcp:close(Socket),
- exit({lost_connection_with_ssl_node_before_up, Name})
- end;
- {error, Error} ->
- gen_tcp:close(LSock),
- exit({accept_failed, Error})
- end.
-
-check_ssl_node_up(Socket, Name, Bin) ->
- case catch binary_to_term(Bin) of
- {'EXIT', _} ->
- gen_tcp:close(Socket),
- exit({bad_data_received_from_ssl_node, Name, Bin});
- {ssl_node_up, NodeName} ->
- case list_to_atom(Name++"@"++host_name()) of
- NodeName ->
- Parent = self(),
- Go = make_ref(),
- %% Spawn connection handler on test server side
- Pid = spawn_link(
- fun () ->
- receive Go -> ok end,
- tstsrvr_con_loop(Name, Socket, Parent)
- end),
- ok = gen_tcp:controlling_process(Socket, Pid),
- Pid ! Go,
- #node_handle{connection_handler = Pid,
- socket = Socket,
- name = Name};
- _ ->
- exit({unexpected_ssl_node_connected, NodeName})
- end;
- Msg ->
- exit({unexpected_msg_instead_of_ssl_node_up, Name, Msg})
- end.
-
-send_to_ssl_node(#node_handle{connection_handler = Hndlr}, Term) ->
- Hndlr ! {relay_to_ssl_node, term_to_binary(Term)},
- ok.
-
-tstsrvr_con_loop(Name, Socket, Parent) ->
- inet:setopts(Socket,[{active,once}]),
- receive
- {relay_to_ssl_node, Data} when is_binary(Data) ->
- case gen_tcp:send(Socket, Data) of
- ok ->
- ok;
- _Error ->
- gen_tcp:close(Socket),
- exit({failed_to_relay_data_to_ssl_node, Name, Data})
- end;
- {tcp, Socket, Bin} ->
- case catch binary_to_term(Bin) of
- {'EXIT', _} ->
- gen_tcp:close(Socket),
- exit({bad_data_received_from_ssl_node, Name, Bin});
- {format, FmtStr, ArgList} ->
- ?t:format(FmtStr, ArgList);
- {message, Msg} ->
- Parent ! Msg;
- {apply_res, To, Ref, Res} ->
- To ! {Ref, Res};
- bye ->
- ?t:format("Ssl node ~s stopped.~n", [Name]),
- gen_tcp:close(Socket),
- exit(normal);
- Unknown ->
- exit({unexpected_message_from_ssl_node, Name, Unknown})
- end;
- {tcp_closed, Socket} ->
- gen_tcp:close(Socket),
- exit({lost_connection_with_ssl_node, Name})
- end,
- tstsrvr_con_loop(Name, Socket, Parent).
-
-%%
-%% Connection handler ssl_node side
-%%
-
-% cnct2tstsrvr() is called via command line arg -run ...
-cnct2tstsrvr([Host, Port]) when list(Host), list(Port) ->
- %% Spawn connection handler on ssl node side
- ConnHandler
- = spawn(fun () ->
- case catch gen_tcp:connect(Host,
- list_to_integer(Port),
- [binary,
- {packet, 4},
- {active, false}]) of
- {ok, Socket} ->
- notify_ssl_node_up(Socket),
- ets:new(test_server_info,
- [set,
- public,
- named_table,
- {keypos, 1}]),
- ets:insert(test_server_info,
- {test_server_handler, self()}),
- ssl_node_con_loop(Socket);
- _Error ->
- halt("Failed to connect to test server")
- end
- end),
- spawn(fun () ->
- Mon = erlang:monitor(process, ConnHandler),
- receive
- {'DOWN', Mon, process, ConnHandler, Reason} ->
- receive after 1000 -> ok end,
- halt("test server connection handler terminated: "
- ++
- lists:flatten(io_lib:format("~p", [Reason])))
- end
- end).
-
-notify_ssl_node_up(Socket) ->
- case catch gen_tcp:send(Socket,
- term_to_binary({ssl_node_up, node()})) of
- ok -> ok;
- _ -> halt("Failed to notify test server that I'm up")
- end.
-
-send_to_tstsrvr(Term) ->
- case catch ets:lookup_element(test_server_info, test_server_handler, 2) of
- Hndlr when pid(Hndlr) ->
- Hndlr ! {relay_to_test_server, term_to_binary(Term)}, ok;
- _ ->
- receive after 200 -> ok end,
- send_to_tstsrvr(Term)
- end.
-
-ssl_node_con_loop(Socket) ->
- inet:setopts(Socket,[{active,once}]),
- receive
- {relay_to_test_server, Data} when is_binary(Data) ->
- case gen_tcp:send(Socket, Data) of
- ok ->
- ok;
- _Error ->
- gen_tcp:close(Socket),
- halt("Failed to relay data to test server")
- end;
- {tcp, Socket, Bin} ->
- case catch binary_to_term(Bin) of
- {'EXIT', _} ->
- gen_tcp:close(Socket),
- halt("test server sent me bad data");
- {apply, From, Ref, M, F, A} ->
- spawn_link(
- fun () ->
- send_to_tstsrvr({apply_res,
- From,
- Ref,
- (catch apply(M, F, A))})
- end);
- {apply, From, Ref, Fun} ->
- spawn_link(fun () ->
- send_to_tstsrvr({apply_res,
- From,
- Ref,
- (catch Fun())})
- end);
- stop ->
- gen_tcp:send(Socket, term_to_binary(bye)),
- gen_tcp:close(Socket),
- init:stop(),
- receive after infinity -> ok end;
- _Unknown ->
- halt("test server sent me an unexpected message")
- end;
- {tcp_closed, Socket} ->
- halt("Lost connection to test server")
- end,
- ssl_node_con_loop(Socket).
-
-%%
-%% Setup ssl dist info
-%%
-
-rand_bin(N) ->
- rand_bin(N, []).
-
-rand_bin(0, Acc) ->
- Acc;
-rand_bin(N, Acc) ->
- rand_bin(N-1, [random:uniform(256)-1|Acc]).
-
-make_randfile(Dir) ->
- {ok, IoDev} = file:open(filename:join([Dir, "RAND"]), [write]),
- {A, B, C} = erlang:now(),
- random:seed(A, B, C),
- ok = file:write(IoDev, rand_bin(1024)),
- file:close(IoDev).
-
-append_files(FileNames, ResultFileName) ->
- {ok, ResultFile} = file:open(ResultFileName, [write]),
- do_append_files(FileNames, ResultFile).
-
-do_append_files([], RF) ->
- ok = file:close(RF);
-do_append_files([F|Fs], RF) ->
- {ok, Data} = file:read_file(F),
- ok = file:write(RF, Data),
- do_append_files(Fs, RF).
-
-setup_dist_opts(Name, PrivDir) ->
- NodeDir = filename:join([PrivDir, Name]),
- RGenDir = filename:join([NodeDir, "rand_gen"]),
- ok = file:make_dir(NodeDir),
- ok = file:make_dir(RGenDir),
- make_randfile(RGenDir),
- make_certs:all(RGenDir, NodeDir),
- SDir = filename:join([NodeDir, "server"]),
- SC = filename:join([SDir, "cert.pem"]),
- SK = filename:join([SDir, "key.pem"]),
- SKC = filename:join([SDir, "keycert.pem"]),
- append_files([SK, SC], SKC),
- CDir = filename:join([NodeDir, "client"]),
- CC = filename:join([CDir, "cert.pem"]),
- CK = filename:join([CDir, "key.pem"]),
- CKC = filename:join([CDir, "keycert.pem"]),
- append_files([CK, CC], CKC),
- "-proto_dist inet_ssl "
- ++ "-ssl_dist_opt server_certfile " ++ SKC ++ " "
- ++ "-ssl_dist_opt client_certfile " ++ CKC ++ " "
-.% ++ "-ssl_dist_opt verify 1 depth 1".
-
-%%
-%% Start scripts etc...
-%%
-
-add_ssl_opts_config(Config) ->
- %%
- %% Start with boot scripts if on an installed system; otherwise,
- %% just point out ssl ebin with -pa.
- %%
- try
- Dir = ?config(priv_dir, Config),
- LibDir = code:lib_dir(),
- Apps = application:which_applications(),
- {value, {stdlib, _, STDL_VSN}} = lists:keysearch(stdlib, 1, Apps),
- {value, {kernel, _, KRNL_VSN}} = lists:keysearch(kernel, 1, Apps),
- StdlDir = filename:join([LibDir, "stdlib-" ++ STDL_VSN]),
- KrnlDir = filename:join([LibDir, "kernel-" ++ KRNL_VSN]),
- {ok, _} = file:read_file_info(StdlDir),
- {ok, _} = file:read_file_info(KrnlDir),
- SSL_VSN = vsn(ssl),
- VSN_CRYPTO = vsn(crypto),
- VSN_PKEY = vsn(public_key),
-
- SslDir = filename:join([LibDir, "ssl-" ++ SSL_VSN]),
- {ok, _} = file:read_file_info(SslDir),
- %% We are using an installed otp system, create the boot script.
- Script = filename:join(Dir, atom_to_list(?MODULE)),
- {ok, RelFile} = file:open(Script ++ ".rel", [write]),
- io:format(RelFile,
- "{release, ~n"
- " {\"SSL distribution test release\", \"~s\"},~n"
- " {erts, \"~s\"},~n"
- " [{kernel, \"~s\"},~n"
- " {stdlib, \"~s\"},~n"
- " {crypto, \"~s\"},~n"
- " {public_key, \"~s\"},~n"
- " {ssl, \"~s\"}]}.~n",
- [case catch erlang:system_info(otp_release) of
- {'EXIT', _} -> "R11B";
- Rel -> Rel
- end,
- erlang:system_info(version),
- KRNL_VSN,
- STDL_VSN,
- VSN_CRYPTO,
- VSN_PKEY,
- SSL_VSN]),
- ok = file:close(RelFile),
- ok = systools:make_script(Script, []),
- [{ssl_opts, "-boot " ++ Script} | Config]
- catch
- _:_ ->
- [{ssl_opts, "-pa " ++ filename:dirname(code:which(ssl))}
- | add_comment_config(
- "Bootscript wasn't used since the test wasn't run on an "
- "installed OTP system.",
- Config)]
- end.
-
-%%
-%% Add common comments to config
-%%
-
-add_comment_config(Comment, []) ->
- [{comment, Comment}];
-add_comment_config(Comment, [{comment, OldComment} | Cs]) ->
- [{comment, Comment ++ " " ++ OldComment} | Cs];
-add_comment_config(Comment, [C|Cs]) ->
- [C|add_comment_config(Comment, Cs)].
-
-%%
-%% Call when test case success
-%%
-
-success(Config) ->
- case lists:keysearch(comment, 1, Config) of
- {value, {comment, _} = Res} -> Res;
- _ -> ok
- end.
-
-vsn(App) ->
- application:start(App),
- try
- {value,
- {ssl,
- _,
- VSN}} = lists:keysearch(App,
- 1,
- application:which_applications()),
- VSN
- after
- application:stop(ssl)
- end.
diff --git a/lib/ssl/test/old_ssl_misc_SUITE.erl b/lib/ssl/test/old_ssl_misc_SUITE.erl
deleted file mode 100644
index ea03e83867..0000000000
--- a/lib/ssl/test/old_ssl_misc_SUITE.erl
+++ /dev/null
@@ -1,117 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, 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(old_ssl_misc_SUITE).
-
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,
- end_per_testcase/2,
- seed/1,
- app/1
- ]).
-
--import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
- test_server_only/6]).
--include_lib("test_server/include/test_server.hrl").
--include("ssl_test_MACHINE.hrl").
-
--define(MANYCONNS, 5).
-
-init_per_testcase(_Case, Config) ->
- WatchDog = ssl_test_lib:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- WatchDog = ?config(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [seed, app].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_suite(doc) ->
- "Want to se what Config contains.";
-init_per_suite(suite) ->
- [];
-init_per_suite(Config) ->
- io:format("Config: ~p~n", [Config]),
-
- %% Check if SSL exists. If this case fails, all other cases are skipped
- case catch crypto:start() of
- ok ->
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config;
- _Else ->
- {skip,"Could not start crypto!"}
- end.
-
-end_per_suite(doc) ->
- "This test case has no mission other than closing the conf case";
-end_per_suite(suite) ->
- [];
-end_per_suite(Config) ->
- crypto:stop(),
- Config.
-
-seed(doc) ->
- "Test that ssl:seed/1 works.";
-seed(suite) ->
- [];
-seed(Config) when list(Config) ->
- process_flag(trap_exit, true),
- LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {_, SsslOpts}} = mk_ssl_cert_opts(Config),
-
- LCmds = [{seed, "tjosan"},
- {sockopts, [{backlog, NConns}, {active, once}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ?line test_server_only(NConns, LCmds, [], Timeout, ?MODULE,
- Config).
-
-app(doc) ->
- "Test that the ssl app file is ok";
-app(suite) ->
- [];
-app(Config) when list(Config) ->
- ?line ok = test_server:app_test(ssl).
-
-
diff --git a/lib/ssl/test/old_ssl_passive_SUITE.erl b/lib/ssl/test/old_ssl_passive_SUITE.erl
deleted file mode 100644
index 7b54fe876a..0000000000
--- a/lib/ssl/test/old_ssl_passive_SUITE.erl
+++ /dev/null
@@ -1,382 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, 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(old_ssl_passive_SUITE).
-
--export([all/0, suite/0,groups/0,init_per_suite/1,
- end_per_suite/1, init_per_group/2,end_per_group/2,
- init_per_testcase/2,
- end_per_testcase/2,
- server_accept_timeout/1,
- cinit_return_chkclose/1,
- sinit_return_chkclose/1,
- cinit_big_return_chkclose/1,
- sinit_big_return_chkclose/1,
- cinit_big_echo_chkclose/1,
- sinit_big_echo_chkclose/1,
- cinit_few_echo_chkclose/1,
- cinit_many_echo_chkclose/1,
- cinit_cnocert/1
- ]).
-
--import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
- test_server_only/6]).
-
--include_lib("test_server/include/test_server.hrl").
--include("ssl_test_MACHINE.hrl").
-
--define(MANYCONNS, ssl_test_MACHINE:many_conns()).
-
-init_per_testcase(_Case, Config) ->
- WatchDog = ssl_test_lib:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- WatchDog = ?config(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [server_accept_timeout, cinit_return_chkclose,
- sinit_return_chkclose, cinit_big_return_chkclose,
- sinit_big_return_chkclose, cinit_big_echo_chkclose,
- sinit_big_echo_chkclose, cinit_few_echo_chkclose,
- cinit_many_echo_chkclose, cinit_cnocert].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_suite(doc) ->
- "Want to se what Config contains.";
-init_per_suite(suite) ->
- [];
-init_per_suite(Config) ->
- io:format("Config: ~p~n", [Config]),
-
- %% Check if SSL exists. If this case fails, all other cases are skipped
- case catch crypto:start() of
- ok ->
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config;
- _Else ->
- {skip,"Could not start crypto"}
- end.
-
-end_per_suite(doc) ->
- "This test case has no mission other than closing the conf case";
-end_per_suite(suite) ->
- [];
-end_per_suite(Config) ->
- crypto:stop(),
- Config.
-
-server_accept_timeout(doc) ->
- "Server has one pending accept with timeout. Checks that return "
- "value is {error, timeout}.";
-server_accept_timeout(suite) ->
- [];
-server_accept_timeout(Config) when list(Config) ->
- process_flag(trap_exit, true),
- LPort = 3456,
- Timeout = 40000, NConns = 1,
- AccTimeout = 3000,
-
- ?line {ok, {_, SsslOpts}} = mk_ssl_cert_opts(Config),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, AccTimeout},
- accept_timeout],
- ?line test_server_only(NConns, LCmds, ACmds, Timeout, ?MODULE, Config).
-
-cinit_return_chkclose(doc) ->
- "Client sends 1000 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Both have certs.";
-cinit_return_chkclose(suite) ->
- [];
-cinit_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize}, {send, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, false}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-sinit_return_chkclose(doc) ->
- "Server sends 1000 bytes to client, that receives them, sends them "
- "back, and closes. Server waits for close. Both have certs.";
-sinit_return_chkclose(suite) ->
- [];
-sinit_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {send, DataSize}, {recv, DataSize},
- await_close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, false}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {recv, DataSize}, {send, DataSize},
- close],
-
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_big_return_chkclose(doc) ->
- "Client sends 50000 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Both have certs.";
-cinit_big_return_chkclose(suite) ->
- [];
-cinit_big_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize}, {send, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, false}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-sinit_big_return_chkclose(doc) ->
- "Server sends 50000 bytes to client, that receives them, sends them "
- "back, and closes. Server waits for close. Both have certs.";
-sinit_big_return_chkclose(suite) ->
- [];
-sinit_big_return_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {send, DataSize}, {recv, DataSize},
- await_close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, false}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {recv, DataSize}, {send, DataSize},
- close],
-
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_big_echo_chkclose(doc) ->
- "Client sends 50000 bytes to server, that echoes them back "
- "and closes. Client waits for close. Both have certs.";
-cinit_big_echo_chkclose(suite) ->
- [];
-cinit_big_echo_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {echo, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, false}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-sinit_big_echo_chkclose(doc) ->
- "Server sends 50000 bytes to client, that echoes them back "
- "and closes. Server waits for close. Both have certs.";
-sinit_big_echo_chkclose(suite) ->
- [];
-sinit_big_echo_chkclose(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 50000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {send, DataSize}, {recv, DataSize},
- await_close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, false}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {echo, DataSize},
- close],
-
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-
-cinit_few_echo_chkclose(X) -> cinit_many_echo_chkclose(X, 7).
-
-cinit_many_echo_chkclose(X) -> cinit_many_echo_chkclose(X, ?MANYCONNS).
-
-cinit_many_echo_chkclose(doc, _NConns) ->
- "clients send 10000 bytes to server, that echoes them back "
- "and closes. Clients wait for close. All have certs.";
-cinit_many_echo_chkclose(suite, _NConns) ->
- [];
-cinit_many_echo_chkclose(Config, NConns) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 10000, LPort = 3456,
- Timeout = 80000,
-
- io:format("~w connections", [NConns]),
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {echo, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, false}]},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
-cinit_cnocert(doc) ->
- "Client sends 1000 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Client has no cert, "
- "but server has.";
-cinit_cnocert(suite) ->
- [];
-cinit_cnocert(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3457,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {_CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}, {active, false}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize}, {send, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sockopts, [{active, false}]},
- {connect, {Host, LPort}},
- {send, DataSize}, {recv, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, ?MODULE,
- Config).
-
diff --git a/lib/ssl/test/old_ssl_peer_cert_SUITE.erl b/lib/ssl/test/old_ssl_peer_cert_SUITE.erl
deleted file mode 100644
index ee19bad175..0000000000
--- a/lib/ssl/test/old_ssl_peer_cert_SUITE.erl
+++ /dev/null
@@ -1,191 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, 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(old_ssl_peer_cert_SUITE).
-
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,
- end_per_testcase/2,
- cinit_plain/1,
- cinit_both_verify/1,
- cinit_cnocert/1
- ]).
-
--import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
- test_server_only/6]).
--include_lib("test_server/include/test_server.hrl").
--include("ssl_test_MACHINE.hrl").
-
-
-init_per_testcase(_Case, Config) ->
- WatchDog = ssl_test_lib:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- WatchDog = ?config(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [cinit_plain, cinit_both_verify, cinit_cnocert].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_suite(doc) ->
- "Want to se what Config contains.";
-init_per_suite(suite) ->
- [];
-init_per_suite(Config) ->
- io:format("Config: ~p~n", [Config]),
-
- %% Check if SSL exists. If this case fails, all other cases are skipped
- case catch crypto:start() of
- ok ->
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config;
- _Else ->
- {skip,"Could not start crypto"}
- end.
-
-end_per_suite(doc) ->
- "This test case has no mission other than closing the conf case";
-end_per_suite(suite) ->
- [];
-end_per_suite(Config) ->
- crypto:stop(),
- Config.
-
-cinit_plain(doc) ->
- "Server closes after accept, Client waits for close. Both have certs "
- "but both use the defaults for verify and depth, but still tries "
- "to retreive each others certificates.";
-cinit_plain(suite) ->
- [];
-cinit_plain(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts, SsslOpts}} = mk_ssl_cert_opts(Config),
-
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- nopeercert,
- {recv, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- peercert,
- {send, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout,
- ?MODULE, Config).
-
-cinit_both_verify(doc) ->
- "Server closes after accept, Client waits for close. Both have certs "
- "and both verify each other.";
-cinit_both_verify(suite) ->
- [];
-cinit_both_verify(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts0, SsslOpts0}} = mk_ssl_cert_opts(Config),
- ?line CsslOpts = [{verify, 2}, {depth, 2} | CsslOpts0],
- ?line SsslOpts = [{verify, 2}, {depth, 3} | SsslOpts0],
-
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- peercert,
- {recv, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- peercert,
- {send, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout,
- ?MODULE, Config).
-
-cinit_cnocert(doc) ->
- "Client has no cert. Nor the client, nor the server is verifying its "
- "peer. Server closes, client waits for close.";
-cinit_cnocert(suite) ->
- [];
-cinit_cnocert(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3457,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {_, SsslOpts0}} = mk_ssl_cert_opts(Config),
- ?line SsslOpts = [{verify, 0}, {depth, 2} | SsslOpts0],
-
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {connect, {Host, LPort}},
- peercert,
- {send, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout,
- ?MODULE, Config).
-
-
diff --git a/lib/ssl/test/old_ssl_protocol_SUITE.erl b/lib/ssl/test/old_ssl_protocol_SUITE.erl
deleted file mode 100644
index 9b9937c210..0000000000
--- a/lib/ssl/test/old_ssl_protocol_SUITE.erl
+++ /dev/null
@@ -1,185 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, 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(old_ssl_protocol_SUITE).
-
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2, end_per_testcase/2,
- sslv2/1, sslv3/1, tlsv1/1, sslv2_sslv3/1,
- sslv2_tlsv1/1, sslv3_tlsv1/1, sslv2_sslv3_tlsv1/1]).
-
--import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
- test_server_only/6]).
--include_lib("test_server/include/test_server.hrl").
--include("ssl_test_MACHINE.hrl").
-
-
-init_per_testcase(_Case, Config) ->
- WatchDog = test_server:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- WatchDog = ?config(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [sslv2, sslv3, tlsv1, sslv2_sslv3, sslv2_tlsv1,
- sslv3_tlsv1, sslv2_sslv3_tlsv1].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_suite(doc) ->
- "Want to se what Config contains.";
-init_per_suite(suite) ->
- [];
-init_per_suite(Config) ->
- io:format("Config: ~p~n", [Config]),
-
- %% Check if SSL exists. If this case fails, all other cases are skipped
- case catch crypto:start() of
- ok ->
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config;
- _Else ->
- {skip,"Could not start crypto"}
- end.
-
-end_per_suite(doc) ->
- "This test case has no other purpose than closing the conf case.";
-end_per_suite(suite) ->
- [];
-end_per_suite(Config) ->
- crypto:stop(),
- Config.
-
-%%%%%
-
-sslv2(doc) ->
- "Client has no cert. Nor the client, nor the server is verifying its "
- "peer. Server closes, client waits for close. "
- "Client and server choose SSLv2.";
-sslv2(suite) ->
- [];
-sslv2(Config) when list(Config) ->
- do_run_test(Config, [sslv2]).
-
-sslv3(doc) ->
- "Client has no cert. Nor the client, nor the server is verifying its "
- "peer. Server closes, client waits for close. "
- "Client and server choose SSLv3.";
-sslv3(suite) ->
- [];
-sslv3(Config) when list(Config) ->
- do_run_test(Config, [sslv3]).
-
-tlsv1(doc) ->
- "Client has no cert. Nor the client, nor the server is verifying its "
- "peer. Server closes, client waits for close. "
- "Client and server choose TLSv1.";
-tlsv1(suite) ->
- [];
-tlsv1(Config) when list(Config) ->
- do_run_test(Config, [tlsv1]).
-
-sslv2_sslv3(doc) ->
- "Client has no cert. Nor the client, nor the server is verifying its "
- "peer. Server closes, client waits for close. "
- "Client and server choose between SSLv2 and SSLv3.";
-sslv2_sslv3(suite) ->
- [];
-sslv2_sslv3(Config) when list(Config) ->
- do_run_test(Config, [sslv2, sslv3]).
-
-sslv2_tlsv1(doc) ->
- "Client has no cert. Nor the client, nor the server is verifying its "
- "peer. Server closes, client waits for close. "
- "Client and server choose between SSLv2 and TLSv1.";
-sslv2_tlsv1(suite) ->
- [];
-sslv2_tlsv1(Config) when list(Config) ->
- do_run_test(Config, [sslv2, tlsv1]).
-
-sslv3_tlsv1(doc) ->
- "Client has no cert. Nor the client, nor the server is verifying its "
- "peer. Server closes, client waits for close. "
- "Client and server choose between SSLv3 and TLSv1.";
-sslv3_tlsv1(suite) ->
- [];
-sslv3_tlsv1(Config) when list(Config) ->
- do_run_test(Config, [sslv3, tlsv1]).
-
-sslv2_sslv3_tlsv1(doc) ->
- "Client has no cert. Nor the client, nor the server is verifying its "
- "peer. Server closes, client waits for close. "
- "Client and server choose between SSLv2, SSLv3, and TLSv1.";
-sslv2_sslv3_tlsv1(suite) ->
- [];
-sslv2_sslv3_tlsv1(Config) when list(Config) ->
- do_run_test(Config, [sslv2, sslv3, tlsv1]).
-
-%%%%
-
-do_run_test(Config0, Protocols) ->
- process_flag(trap_exit, true),
- LPort = 3456,
- Timeout = 40000, NConns = 1,
- DataSize = 10,
-
- ?line {ok, {_, SsslOpts0}} = mk_ssl_cert_opts(Config0),
- ?line SsslOpts = [{verify, 0}, {depth, 2} | SsslOpts0],
-
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- connection_info,
- {recv, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {connect, {Host, LPort}},
- connection_info,
- {send, DataSize},
- await_close],
- Config1 = [{env, [{protocol_version, Protocols}]} | Config0],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout,
- ?MODULE, Config1).
-
-
diff --git a/lib/ssl/test/old_ssl_verify_SUITE.erl b/lib/ssl/test/old_ssl_verify_SUITE.erl
deleted file mode 100644
index 4c11ea6850..0000000000
--- a/lib/ssl/test/old_ssl_verify_SUITE.erl
+++ /dev/null
@@ -1,153 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, 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(old_ssl_verify_SUITE).
-
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,
- end_per_testcase/2,
- cinit_both_verify/1,
- cinit_cnocert/1
- ]).
-
--import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
- test_server_only/6]).
--include_lib("test_server/include/test_server.hrl").
--include("ssl_test_MACHINE.hrl").
-
-
-init_per_testcase(_Case, Config) ->
- WatchDog = ssl_test_lib:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- WatchDog = ?config(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [cinit_both_verify, cinit_cnocert].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_suite(doc) ->
- "Want to se what Config contains.";
-init_per_suite(suite) ->
- [];
-init_per_suite(Config) ->
- io:format("Config: ~p~n", [Config]),
-
- %% Check if SSL exists. If this case fails, all other cases are skipped
- case catch crypto:start() of
- ok ->
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config;
- _Else ->
- {skip,"Could not start crypto"}
- end.
-
-end_per_suite(doc) ->
- "This test case has no mission other than closing the conf case";
-end_per_suite(suite) ->
- [];
-end_per_suite(Config) ->
- crypto:stop(),
- Config.
-
-cinit_both_verify(doc) ->
- "Server closes after accept, Client waits for close. Both have certs "
- "and both verify each other.";
-cinit_both_verify(suite) ->
- [];
-cinit_both_verify(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3456,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {CsslOpts0, SsslOpts0}} = mk_ssl_cert_opts(Config),
- ?line CsslOpts = [{verify, 2}, {depth, 2} | CsslOpts0],
- ?line SsslOpts = [{verify, 2}, {depth, 3} | SsslOpts0],
-
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {sslopts, CsslOpts},
- {connect, {Host, LPort}},
- {send, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout,
- ?MODULE, Config).
-
-cinit_cnocert(doc) ->
- "Client has no cert. Nor the client, nor the server is verifying its "
- "peer. Server closes, client waits for close.";
-cinit_cnocert(suite) ->
- [];
-cinit_cnocert(Config) when list(Config) ->
- process_flag(trap_exit, true),
- DataSize = 1000, LPort = 3457,
- Timeout = 40000, NConns = 1,
-
- ?line {ok, {_, SsslOpts0}} = mk_ssl_cert_opts(Config),
- ?line SsslOpts = [{verify, 0}, {depth, 2} | SsslOpts0],
-
- ?line {ok, Host} = inet:gethostname(),
-
- LCmds = [{sockopts, [{backlog, NConns}]},
- {sslopts, SsslOpts},
- {listen, LPort},
- wait_sync,
- lclose],
- ACmds = [{timeout, Timeout},
- accept,
- {recv, DataSize},
- close],
- CCmds = [{timeout, Timeout},
- {connect, {Host, LPort}},
- {send, DataSize},
- await_close],
- ?line test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout,
- ?MODULE, Config).
-
-
diff --git a/lib/ssl/test/old_transport_accept_SUITE.erl b/lib/ssl/test/old_transport_accept_SUITE.erl
deleted file mode 100644
index 6f0c8e456b..0000000000
--- a/lib/ssl/test/old_transport_accept_SUITE.erl
+++ /dev/null
@@ -1,258 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, 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(old_transport_accept_SUITE).
--include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
-
-%% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(1)).
--define(application, ssh).
-
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2,
- end_per_testcase/2,
- config/1,
- echo_once/1,
- echo_twice/1,
- close_before_ssl_accept/1,
- server/5,
- tolerant_server/5,
- client/5
- ]).
-
-init_per_testcase(_Case, Config) ->
- WatchDog = ssl_test_lib:timetrap(?default_timeout),
- [{watchdog, WatchDog}, {protomod, gen_tcp}, {serialize_accept, true}|
- Config].
-
-end_per_testcase(_Case, Config) ->
- WatchDog = ?config(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [config, echo_once, echo_twice, close_before_ssl_accept].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- try crypto:start() of
- ok ->
- Config
- catch _:_ ->
- {skip, "Crypto did not start"}
- end.
-
-end_per_suite(_Config) ->
- application:stop(crypto),
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-config(doc) ->
- "Want to se what Config contains.";
-config(suite) ->
- [];
-config(Config) ->
- io:format("Config: ~p~n", [Config]),
- ok.
-
-echo_once(doc) ->
- "Client sends 256 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Both have certs.";
-echo_once(suite) ->
- [];
-echo_once(Config) when list(Config) ->
- process_flag(trap_exit, true),
- LPort = 3456,
- {ok, Host} = inet:gethostname(),
- {ok, {COpts, SOpts}} = ssl_test_MACHINE:mk_ssl_cert_opts(Config),
- N = 1,
- Msg = lists:seq(0, 255),
- Self = self(),
- Params = "-pa " ++ filename:dirname(code:which(?MODULE)),
- Node = start_node(server, Params),
- CNode = start_node(client, Params),
- Server = spawn_link(Node, ?MODULE, server, [Self, LPort, SOpts, Msg, N]),
- Client = spawn_link(Node, ?MODULE, client, [Host, LPort, COpts, Msg, N]),
- ok = receive
- {Server, listening} ->
- Client ! {Server, listening},
- ok;
- E ->
- io:format("bad receive (1) ~p\n", [E]),
- E
- end,
- receive
- {Server, done} ->
- ok
- end,
- test_server:stop_node(Node),
- test_server:stop_node(CNode).
-
-close_before_ssl_accept(doc) ->
- "Client sends 256 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Both have certs.";
-close_before_ssl_accept(suite) ->
- [];
-close_before_ssl_accept(Config) when list(Config) ->
- process_flag(trap_exit, true),
- LPort = 3456,
- {ok, Host} = inet:gethostname(),
- {ok, {COpts, SOpts}} = ssl_test_MACHINE:mk_ssl_cert_opts(Config),
- Msg = lists:seq(0, 255),
- Self = self(),
- Params = "-pa " ++ filename:dirname(code:which(?MODULE)),
- Node = start_node(server, Params),
- CNode = start_node(client, Params),
- Server = spawn_link(Node, ?MODULE, tolerant_server,
- [Self, LPort, SOpts, Msg, 2]),
- Client = spawn_link(Node, ?MODULE, client,
- [Host, LPort, COpts, Msg, 1]),
- ok = receive
- {Server, listening} ->
- {ok, S} = gen_tcp:connect(Host, LPort, []),
- gen_tcp:close(S),
- Client ! {Server, listening},
- ok;
- E ->
- io:format("bad receive (1) ~p\n", [E]),
- E
- end,
- receive
- {Server, done} ->
- ok
- end,
- test_server:stop_node(Node),
- test_server:stop_node(CNode).
-
-client(Host, LPort, COpts, Msg, N) ->
- ok = receive
- {_Server, listening} ->
- ok;
- E ->
- io:format("bad receive (2) ~p\n", [E]),
- E
- end,
- Opts = COpts ++ [{packet, raw}, {active, false}],
- app(),
- lists:foreach(fun(_) ->
- {ok, S} = ssl:connect(Host, LPort, Opts),
- ssl:send(S, Msg),
- {ok, Msg} = ssl:recv(S, length(Msg)),
- ssl:close(S)
- end, lists:seq(1, N)).
-
-echo_twice(doc) ->
- "Two clients sends 256 bytes to server, that receives them, sends them "
- "back, and closes. Client waits for close. Both have certs.";
-echo_twice(suite) ->
- [];
-echo_twice(Config) when list(Config) ->
- process_flag(trap_exit, true),
- LPort = 3456,
- {ok, Host} = inet:gethostname(),
- {ok, {COpts, SOpts}} = ssl_test_MACHINE:mk_ssl_cert_opts(Config),
- N = 2,
- Msg = lists:seq(0, 255),
- Self = self(),
- Params = "-pa " ++ filename:dirname(code:which(?MODULE)),
- Node = start_node(server, Params),
- CNode = start_node(client, Params),
- Server = spawn_link(Node, ?MODULE, server,
- [Self, LPort, SOpts, Msg, N]),
- Client = spawn_link(Node, ?MODULE, client,
- [Host, LPort, COpts, Msg, N]),
- ok = receive
- {Server, listening} ->
- Client ! {Server, listening},
- ok;
- E ->
- io:format("bad receive (3) ~p\n", [E]),
- E
- end,
- receive
- {Server, done} ->
- ok
- end,
- test_server:stop_node(Node),
- test_server:stop_node(CNode).
-
-server(Client, Port, SOpts, Msg, N) ->
- app(),
- process_flag(trap_exit, true),
- Opts = SOpts ++ [{packet, raw}, {active, false}],
- {ok, LSock} = ssl:listen(Port, Opts),
- Client ! {self(), listening},
- server_loop(Client, LSock, Msg, N).
-
-server_loop(Client, _, _, 0) ->
- Client ! {self(), done};
-server_loop(Client, LSock, Msg, N) ->
- {ok, S} = ssl:transport_accept(LSock),
- ok = ssl:ssl_accept(S),
- %% P = ssl:controlling_process(S, Proxy),
- {ok, Msg} = ssl:recv(S, length(Msg)),
- ok = ssl:send(S, Msg),
- ok = ssl:close(S),
- server_loop(Client, LSock, Msg, N-1).
-
-tolerant_server(Client, Port, SOpts, Msg, N) ->
- app(),
- process_flag(trap_exit, true),
- Opts = SOpts ++ [{packet, raw}, {active, false}],
- {ok, LSock} = ssl:listen(Port, Opts),
- Client ! {self(), listening},
- tolerant_server_loop(Client, LSock, Msg, N).
-
-tolerant_server_loop(Client, _, _, 0) ->
- Client ! {self(), done};
-tolerant_server_loop(Client, LSock, Msg, N) ->
- {ok, S} = ssl:transport_accept(LSock),
- case ssl:ssl_accept(S) of
- ok ->
- %% P = ssl:controlling_process(S, Proxy),
- {ok, Msg} = ssl:recv(S, length(Msg)),
- ok = ssl:send(S, Msg),
- ok = ssl:close(S);
- E ->
- io:format("ssl_accept error: ~p\n", [E])
- end,
- tolerant_server_loop(Client, LSock, Msg, N-1).
-
-app() ->
- crypto:start(),
- application:start(public_key),
- ssl:start().
-
-start_node(Kind, Params) ->
- S = atom_to_list(?MODULE)++"_" ++ atom_to_list(Kind),
- {ok, Node} = test_server:start_node(list_to_atom(S), slave, [{args, Params}]),
- Node.
-
diff --git a/lib/ssl/test/ssl.cover b/lib/ssl/test/ssl.cover
index 60774cc0f1..6b13e07a37 100644
--- a/lib/ssl/test/ssl.cover
+++ b/lib/ssl/test/ssl.cover
@@ -1,21 +1,4 @@
{incl_app,ssl,details}.
-{excl_mods, ssl, [ssl_pkix_oid,
- 'PKIX1Algorithms88',
- 'PKIX1Explicit88',
- 'PKIX1Implicit88',
- 'PKIXAttributeCertificate',
- 'SSL-PKIX',
- ssl_pem,
- ssl_pkix,
- ssl_base64,
- ssl_broker,
- ssl_broker_int,
- ssl_broker_sup,
- ssl_debug,
- ssl_server,
- ssl_prim,
- inet_ssl_dist,
- 'OTP-PKIX'
- ]}.
+{excl_mods, ssl, [ssl_debug]}.
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 4f0907027f..a9109c5a6e 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -25,11 +25,11 @@
-compile(export_all).
-include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
-include_lib("public_key/include/public_key.hrl").
-include("ssl_alert.hrl").
--include("ssl_int.hrl").
+-include("ssl_internal.hrl").
+-include("ssl_record.hrl").
-define('24H_in_sec', 86400).
-define(TIMEOUT, 60000).
@@ -206,10 +206,14 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[app, alerts, connection_info, protocol_versions,
empty_protocol_versions, controlling_process,
- controller_dies, client_closes_socket, peercert,
- connect_dist, peername, sockname, socket_options,
+ controller_dies, client_closes_socket,
+ connect_dist, peername, peercert, sockname, socket_options,
+ invalid_inet_get_option, invalid_inet_get_option_not_list,
+ invalid_inet_get_option_improper_list,
+ invalid_inet_set_option, invalid_inet_set_option_not_list,
+ invalid_inet_set_option_improper_list,
misc_ssl_options, versions, cipher_suites, upgrade,
- upgrade_with_timeout, tcp_connect, ipv6, ekeyfile,
+ upgrade_with_timeout, tcp_connect, tcp_connect_big, ipv6, ekeyfile,
ecertfile, ecacertfile, eoptions, shutdown,
shutdown_write, shutdown_both, shutdown_error,
ciphers_rsa_signed_certs, ciphers_rsa_signed_certs_ssl3,
@@ -248,11 +252,11 @@ all() ->
unknown_server_ca_fail, der_input,
unknown_server_ca_accept_verify_none,
unknown_server_ca_accept_verify_peer,
- unknown_server_ca_accept_backwardscompatibilty,
+ unknown_server_ca_accept_backwardscompatibility,
%%different_ca_peer_sign,
no_reuses_session_server_restart_new_cert,
no_reuses_session_server_restart_new_cert_file, reuseaddr,
- hibernate
+ hibernate, connect_twice
].
groups() ->
@@ -579,50 +583,6 @@ client_closes_socket(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server, {error,closed}).
%%--------------------------------------------------------------------
-
-peercert(doc) ->
- [""];
-
-peercert(suite) ->
- [];
-
-peercert(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, ClientNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, peercert_result, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, peercert_result, []}},
- {options, ClientOpts}]),
-
- CertFile = proplists:get_value(certfile, ServerOpts),
- [{'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}},
-
- test_server:format("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-peercert_result(Socket) ->
- Result1 = ssl:peercert(Socket),
- Result2 = ssl:peercert(Socket, [ssl]),
- {Result1, Result2}.
-
-%%--------------------------------------------------------------------
connect_dist(doc) ->
["Test a simple connect as is used by distribution"];
@@ -703,6 +663,44 @@ peername_result(S) ->
ssl:peername(S).
%%--------------------------------------------------------------------
+peercert(doc) ->
+ [""];
+peercert(suite) ->
+ [];
+peercert(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, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, peercert_result, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, peercert_result, []}},
+ {options, ClientOpts}]),
+
+ CertFile = proplists:get_value(certfile, ServerOpts),
+ [{'Certificate', BinCert, _}]= ssl_test_lib:pem_to_der(CertFile),
+
+ ServerMsg = {error, no_peercert},
+ ClientMsg = {ok, BinCert},
+
+ test_server:format("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+peercert_result(Socket) ->
+ ssl:peercert(Socket).
+
+%%--------------------------------------------------------------------
sockname(doc) ->
["Test API function sockname/1"];
@@ -808,8 +806,218 @@ socket_options_result(Socket, Options, DefaultValues, NewOptions, NewValues) ->
{ok,[{nodelay,false}]} = ssl:getopts(Socket, [nodelay]),
ssl:setopts(Socket, [{nodelay, true}]),
{ok,[{nodelay, true}]} = ssl:getopts(Socket, [nodelay]),
+ {ok, All} = ssl:getopts(Socket, []),
+ test_server:format("All opts ~p~n", [All]),
ok.
+
+
+%%--------------------------------------------------------------------
+invalid_inet_get_option(doc) ->
+ ["Test handling of invalid inet options in getopts"];
+
+invalid_inet_get_option(suite) ->
+ [];
+
+invalid_inet_get_option(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, get_invalid_inet_option, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ClientOpts}]),
+
+ test_server:format("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+get_invalid_inet_option(Socket) ->
+ {error, {eoptions, {inet_option, foo, _}}} = ssl:getopts(Socket, [foo]),
+ ok.
+
+%%--------------------------------------------------------------------
+invalid_inet_get_option_not_list(doc) ->
+ ["Test handling of invalid type in getopts"];
+
+invalid_inet_get_option_not_list(suite) ->
+ [];
+
+invalid_inet_get_option_not_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),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, get_invalid_inet_option_not_list, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ClientOpts}]),
+
+ test_server:format("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+get_invalid_inet_option_not_list(Socket) ->
+ {error, {eoptions, {inet_options, some_invalid_atom_here}}}
+ = ssl:getopts(Socket, some_invalid_atom_here),
+ ok.
+
+%%--------------------------------------------------------------------
+invalid_inet_get_option_improper_list(doc) ->
+ ["Test handling of invalid type in getopts"];
+
+invalid_inet_get_option_improper_list(suite) ->
+ [];
+
+invalid_inet_get_option_improper_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),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, get_invalid_inet_option_improper_list, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ClientOpts}]),
+
+ test_server:format("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+get_invalid_inet_option_improper_list(Socket) ->
+ {error, {eoptions, {inet_option, foo,_}}} = ssl:getopts(Socket, [packet | foo]),
+ ok.
+
+%%--------------------------------------------------------------------
+invalid_inet_set_option(doc) ->
+ ["Test handling of invalid inet options in setopts"];
+
+invalid_inet_set_option(suite) ->
+ [];
+
+invalid_inet_set_option(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, set_invalid_inet_option, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ClientOpts}]),
+
+ test_server:format("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+set_invalid_inet_option(Socket) ->
+ {error, {eoptions, {inet_opt, {packet, foo}}}} = ssl:setopts(Socket, [{packet, foo}]),
+ {error, {eoptions, {inet_opt, {header, foo}}}} = ssl:setopts(Socket, [{header, foo}]),
+ {error, {eoptions, {inet_opt, {active, foo}}}} = ssl:setopts(Socket, [{active, foo}]),
+ {error, {eoptions, {inet_opt, {mode, foo}}}} = ssl:setopts(Socket, [{mode, foo}]),
+ ok.
+%%--------------------------------------------------------------------
+invalid_inet_set_option_not_list(doc) ->
+ ["Test handling of invalid type in setopts"];
+
+invalid_inet_set_option_not_list(suite) ->
+ [];
+
+invalid_inet_set_option_not_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),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, set_invalid_inet_option_not_list, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ClientOpts}]),
+
+ test_server:format("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+set_invalid_inet_option_not_list(Socket) ->
+ {error, {eoptions, {not_a_proplist, some_invalid_atom_here}}}
+ = ssl:setopts(Socket, some_invalid_atom_here),
+ ok.
+
+%%--------------------------------------------------------------------
+invalid_inet_set_option_improper_list(doc) ->
+ ["Test handling of invalid tye in setopts"];
+
+invalid_inet_set_option_improper_list(suite) ->
+ [];
+
+invalid_inet_set_option_improper_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),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, set_invalid_inet_option_improper_list, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ClientOpts}]),
+
+ test_server:format("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+set_invalid_inet_option_improper_list(Socket) ->
+ {error, {eoptions, {not_a_proplist, [{packet, 0} | {foo, 2}]}}} =
+ ssl:setopts(Socket, [{packet, 0} | {foo, 2}]),
+ ok.
+
%%--------------------------------------------------------------------
misc_ssl_options(doc) ->
["Test what happens when we give valid options"];
@@ -1097,6 +1305,41 @@ tcp_connect(Config) when is_list(Config) ->
end
end.
+tcp_connect_big(doc) ->
+ ["Test what happens when a tcp tries to connect, i,e. a bad big (ssl) packet is sent first"];
+
+tcp_connect_big(suite) ->
+ [];
+
+tcp_connect_big(Config) when is_list(Config) ->
+ ServerOpts = ?config(server_opts, Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ TcpOpts = [binary, {reuseaddr, true}],
+
+ Server = ssl_test_lib:start_upgrade_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {timeout, 5000},
+ {mfa, {?MODULE, dummy, []}},
+ {tcp_options, TcpOpts},
+ {ssl_options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ {ok, Socket} = gen_tcp:connect(Hostname, Port, [binary, {packet, 0}]),
+ test_server:format("Testcase ~p connected to Server ~p ~n", [self(), Server]),
+
+ Rand = crypto:rand_bytes(?MAX_CIPHER_TEXT_LENGTH+1),
+ gen_tcp:send(Socket, <<?BYTE(0),
+ ?BYTE(3), ?BYTE(1), ?UINT16(?MAX_CIPHER_TEXT_LENGTH), Rand/binary>>),
+
+ receive
+ {tcp_closed, Socket} ->
+ receive
+ {Server, {error, timeout}} ->
+ test_server:fail("hangs");
+ {Server, {error, Error}} ->
+ test_server:format("Error ~p", [Error])
+ end
+ end.
dummy(_Socket) ->
%% Should not happen as the ssl connection will not be established
@@ -1278,7 +1521,6 @@ eoptions(Config) when is_list(Config) ->
end,
TestOpts = [{versions, [sslv2, sslv3]},
- {ssl_imp, cool},
{verify, 4},
{verify_fun, function},
{fail_if_no_peer_cert, 0},
@@ -1659,7 +1901,7 @@ reuse_session(Config) when is_list(Config) ->
Server =
ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, session_info_result, []}},
+ {mfa, {ssl_test_lib, session_info_result, []}},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
Client0 =
@@ -1681,7 +1923,7 @@ reuse_session(Config) when is_list(Config) ->
Client1 =
ssl_test_lib:start_client([{node, ClientNode},
{port, Port}, {host, Hostname},
- {mfa, {?MODULE, session_info_result, []}},
+ {mfa, {ssl_test_lib, session_info_result, []}},
{from, self()}, {options, ClientOpts}]),
receive
{Client1, SessionInfo} ->
@@ -1697,7 +1939,7 @@ reuse_session(Config) when is_list(Config) ->
Client2 =
ssl_test_lib:start_client([{node, ClientNode},
{port, Port}, {host, Hostname},
- {mfa, {?MODULE, session_info_result, []}},
+ {mfa, {ssl_test_lib, session_info_result, []}},
{from, self()}, {options, [{reuse_sessions, false}
| ClientOpts]}]),
receive
@@ -1713,7 +1955,7 @@ reuse_session(Config) when is_list(Config) ->
Server1 =
ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, session_info_result, []}},
+ {mfa, {ssl_test_lib, session_info_result, []}},
{options, [{reuse_sessions, false} | ServerOpts]}]),
Port1 = ssl_test_lib:inet_port(Server1),
@@ -1737,7 +1979,7 @@ reuse_session(Config) when is_list(Config) ->
Client4 =
ssl_test_lib:start_client([{node, ClientNode},
{port, Port1}, {host, Hostname},
- {mfa, {?MODULE, session_info_result, []}},
+ {mfa, {ssl_test_lib, session_info_result, []}},
{from, self()}, {options, ClientOpts}]),
receive
@@ -1756,9 +1998,6 @@ reuse_session(Config) when is_list(Config) ->
ssl_test_lib:close(Client3),
ssl_test_lib:close(Client4).
-session_info_result(Socket) ->
- ssl:session_info(Socket).
-
%%--------------------------------------------------------------------
reuse_session_expired(doc) ->
["Test sessions is not reused when it has expired"];
@@ -1774,7 +2013,7 @@ reuse_session_expired(Config) when is_list(Config) ->
Server =
ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, session_info_result, []}},
+ {mfa, {ssl_test_lib, session_info_result, []}},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
Client0 =
@@ -1796,7 +2035,7 @@ reuse_session_expired(Config) when is_list(Config) ->
Client1 =
ssl_test_lib:start_client([{node, ClientNode},
{port, Port}, {host, Hostname},
- {mfa, {?MODULE, session_info_result, []}},
+ {mfa, {ssl_test_lib, session_info_result, []}},
{from, self()}, {options, ClientOpts}]),
receive
{Client1, SessionInfo} ->
@@ -1815,7 +2054,7 @@ reuse_session_expired(Config) when is_list(Config) ->
Client2 =
ssl_test_lib:start_client([{node, ClientNode},
{port, Port}, {host, Hostname},
- {mfa, {?MODULE, session_info_result, []}},
+ {mfa, {ssl_test_lib, session_info_result, []}},
{from, self()}, {options, ClientOpts}]),
receive
{Client2, SessionInfo} ->
@@ -1844,7 +2083,7 @@ server_does_not_want_to_reuse_session(Config) when is_list(Config) ->
Server =
ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, session_info_result, []}},
+ {mfa, {ssl_test_lib, session_info_result, []}},
{options, [{reuse_session, fun(_,_,_,_) ->
false
end} |
@@ -1870,7 +2109,7 @@ server_does_not_want_to_reuse_session(Config) when is_list(Config) ->
Client1 =
ssl_test_lib:start_client([{node, ClientNode},
{port, Port}, {host, Hostname},
- {mfa, {?MODULE, session_info_result, []}},
+ {mfa, {ssl_test_lib, session_info_result, []}},
{from, self()}, {options, ClientOpts}]),
receive
{Client1, SessionInfo} ->
@@ -3035,11 +3274,11 @@ unknown_server_ca_accept_verify_peer(Config) when is_list(Config) ->
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
-unknown_server_ca_accept_backwardscompatibilty(doc) ->
+unknown_server_ca_accept_backwardscompatibility(doc) ->
["Test that old style verify_funs will work"];
-unknown_server_ca_accept_backwardscompatibilty(suite) ->
+unknown_server_ca_accept_backwardscompatibility(suite) ->
[];
-unknown_server_ca_accept_backwardscompatibilty(Config) when is_list(Config) ->
+unknown_server_ca_accept_backwardscompatibility(Config) when is_list(Config) ->
ClientOpts = ?config(client_opts, Config),
ServerOpts = ?config(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -3179,7 +3418,7 @@ no_reuses_session_server_restart_new_cert(Config) when is_list(Config) ->
Server =
ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, session_info_result, []}},
+ {mfa, {ssl_test_lib, session_info_result, []}},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
Client0 =
@@ -3207,7 +3446,7 @@ no_reuses_session_server_restart_new_cert(Config) when is_list(Config) ->
Client1 =
ssl_test_lib:start_client([{node, ClientNode},
{port, Port}, {host, Hostname},
- {mfa, {?MODULE, session_info_result, []}},
+ {mfa, {ssl_test_lib, session_info_result, []}},
{from, self()}, {options, ClientOpts}]),
receive
{Client1, SessionInfo} ->
@@ -3238,7 +3477,7 @@ no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) ->
Server =
ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, session_info_result, []}},
+ {mfa, {ssl_test_lib, session_info_result, []}},
{options, NewServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
Client0 =
@@ -3268,7 +3507,7 @@ no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) ->
Client1 =
ssl_test_lib:start_client([{node, ClientNode},
{port, Port}, {host, Hostname},
- {mfa, {?MODULE, session_info_result, []}},
+ {mfa, {ssl_test_lib, session_info_result, []}},
{from, self()}, {options, ClientOpts}]),
receive
{Client1, SessionInfo} ->
@@ -3304,6 +3543,7 @@ reuseaddr(Config) when is_list(Config) ->
{options, [{active, false} | ClientOpts]}]),
test_server:sleep(?SLEEP),
ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client),
Server1 =
ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
@@ -3361,6 +3601,54 @@ hibernate(Config) ->
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
+
+connect_twice(doc) ->
+ [""];
+connect_twice(suite) ->
+ [];
+connect_twice(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, []}},
+ {options, [{keepalive, true},{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, [{keepalive, true},{active, false}
+ | ClientOpts]}]),
+ Server ! listen,
+
+ {Client1, #sslsocket{}} =
+ ssl_test_lib:start_client([return_socket,
+ {node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, send_recv_result, []}},
+ {options, [{keepalive, true},{active, false}
+ | ClientOpts]}]),
+
+ test_server:format("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:check_result(Server, ok, Client1, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client),
+ ssl_test_lib:close(Client1).
+
+
+%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
send_recv_result(Socket) ->
@@ -3438,7 +3726,7 @@ 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) ->
+session_cache_process(_Type,Config) when is_list(Config) ->
reuse_session(Config).
init([Type]) ->
diff --git a/lib/ssl/test/ssl_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl
new file mode 100644
index 0000000000..23e9268f9b
--- /dev/null
+++ b/lib/ssl/test/ssl_dist_SUITE.erl
@@ -0,0 +1,725 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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_dist_SUITE).
+
+-include_lib("test_server/include/test_server.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-define(DEFAULT_TIMETRAP_SECS, 240).
+
+-define(AWAIT_SLL_NODE_UP_TIMEOUT, 30000).
+
+-record(node_handle,
+ {connection_handler,
+ socket,
+ name,
+ nodename}
+ ).
+
+%% Test server callback functions
+suite() ->
+ [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [basic, payload, plain_options, plain_verify_options].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+init_per_suite(Config0) ->
+ try crypto:start() of
+ ok ->
+ Config = add_ssl_opts_config(Config0),
+ setup_certs(Config),
+ Config
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(Config) ->
+ application:stop(crypto),
+ Config.
+
+init_per_testcase(Case, Config) when is_list(Config) ->
+ Dog = ?t:timetrap(?t:seconds(?DEFAULT_TIMETRAP_SECS)),
+ [{watchdog, Dog},{testcase, Case}|Config].
+
+end_per_testcase(_Case, Config) when is_list(Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+%%--------------------------------------------------------------------
+%% Test cases starts here.
+%%--------------------------------------------------------------------
+basic(doc) ->
+ ["Test that two nodes can connect via ssl distribution"];
+basic(Config) when is_list(Config) ->
+ NH1 = start_ssl_node(Config),
+ Node1 = NH1#node_handle.nodename,
+ NH2 = start_ssl_node(Config),
+ Node2 = NH2#node_handle.nodename,
+
+ pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
+
+ [Node2] = apply_on_ssl_node(NH1, fun () -> nodes() end),
+ [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end),
+
+ %% The test_server node has the same cookie as the ssl nodes
+ %% but it should not be able to communicate with the ssl nodes
+ %% via the erlang distribution.
+ pang = net_adm:ping(Node1),
+ pang = net_adm:ping(Node2),
+
+ %%
+ %% Check that we are able to communicate over the erlang
+ %% distribution between the ssl nodes.
+ %%
+ Ref = make_ref(),
+ spawn(fun () ->
+ apply_on_ssl_node(
+ NH1,
+ fun () ->
+ tstsrvr_format("Hi from ~p!~n", [node()]),
+ send_to_tstcntrl({Ref, self()}),
+ receive
+ {From, ping} ->
+ tstsrvr_format("Received ping ~p!~n", [node()]),
+ From ! {self(), pong}
+ end
+ end)
+ end),
+ receive
+ {Ref, SslPid} ->
+ ok = apply_on_ssl_node(
+ NH2,
+ fun () ->
+ tstsrvr_format("Hi from ~p!~n", [node()]),
+ SslPid ! {self(), ping},
+ receive
+ {SslPid, pong} ->
+ ok
+ end
+ end)
+ end,
+ stop_ssl_node(NH1),
+ stop_ssl_node(NH2),
+ success(Config).
+
+%%--------------------------------------------------------------------
+payload(doc) ->
+ ["Test that send a lot of data between the ssl distributed noes"];
+payload(Config) when is_list(Config) ->
+ NH1 = start_ssl_node(Config),
+ Node1 = NH1#node_handle.nodename,
+ NH2 = start_ssl_node(Config),
+ Node2 = NH2#node_handle.nodename,
+
+ pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
+
+ [Node2] = apply_on_ssl_node(NH1, fun () -> nodes() end),
+ [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end),
+
+ Ref = make_ref(),
+ spawn(fun () ->
+ apply_on_ssl_node(
+ NH1,
+ fun () ->
+ send_to_tstcntrl({Ref, self()}),
+ receive
+ {From, Msg} ->
+ From ! {self(), Msg}
+ end
+ end)
+ end),
+ receive
+ {Ref, SslPid} ->
+ ok = apply_on_ssl_node(
+ NH2,
+ fun () ->
+ Msg = crypto:rand_bytes(100000),
+ SslPid ! {self(), Msg},
+ receive
+ {SslPid, Msg} ->
+ ok
+ end
+ end)
+ end,
+ stop_ssl_node(NH1),
+ stop_ssl_node(NH2),
+ success(Config).
+%%--------------------------------------------------------------------
+plain_options(doc) ->
+ ["Test specifying additional options"];
+plain_options(Config) when is_list(Config) ->
+ DistOpts = "-ssl_dist_opt server_secure_renegotiate true "
+ "client_secure_renegotiate true "
+ "server_reuse_sessions true client_reuse_sessions true "
+ "client_verify verify_none server_verify verify_none "
+ "server_depth 1 client_depth 1 "
+ "server_hibernate_after 500 client_hibernate_after 500",
+
+ NH1 = start_ssl_node([{additional_dist_opts, DistOpts} | Config]),
+ Node1 = NH1#node_handle.nodename,
+ NH2 = start_ssl_node([{additional_dist_opts, DistOpts} | Config]),
+ Node2 = NH2#node_handle.nodename,
+
+ pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
+
+ [Node2] = apply_on_ssl_node(NH1, fun () -> nodes() end),
+ [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end),
+
+ stop_ssl_node(NH1),
+ stop_ssl_node(NH2),
+ success(Config).
+%%--------------------------------------------------------------------
+plain_verify_options(doc) ->
+ ["Test specifying additional options"];
+plain_verify_options(Config) when is_list(Config) ->
+ DistOpts = "-ssl_dist_opt server_secure_renegotiate true "
+ "client_secure_renegotiate true "
+ "server_reuse_sessions true client_reuse_sessions true "
+ "server_hibernate_after 500 client_hibernate_after 500",
+
+ NH1 = start_ssl_node([{additional_dist_opts, DistOpts}, {many_verify_opts, true} | Config]),
+ Node1 = NH1#node_handle.nodename,
+ NH2 = start_ssl_node([{additional_dist_opts, DistOpts}, {many_verify_opts, true} | Config]),
+ Node2 = NH2#node_handle.nodename,
+
+ pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
+
+ [Node2] = apply_on_ssl_node(NH1, fun () -> nodes() end),
+ [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end),
+
+ stop_ssl_node(NH1),
+ stop_ssl_node(NH2),
+ success(Config).
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+
+%% ssl_node side api
+%%
+
+tstsrvr_format(Fmt, ArgList) ->
+ send_to_tstsrvr({format, Fmt, ArgList}).
+
+send_to_tstcntrl(Message) ->
+ send_to_tstsrvr({message, Message}).
+
+
+%%
+%% test_server side api
+%%
+
+apply_on_ssl_node(Node, M, F, A) when is_atom(M), is_atom(F), is_list(A) ->
+ Ref = make_ref(),
+ send_to_ssl_node(Node, {apply, self(), Ref, M, F, A}),
+ receive
+ {Ref, Result} ->
+ Result
+ end.
+
+apply_on_ssl_node(Node, Fun) when is_function(Fun, 0) ->
+ Ref = make_ref(),
+ send_to_ssl_node(Node, {apply, self(), Ref, Fun}),
+ receive
+ {Ref, Result} ->
+ Result
+ end.
+
+stop_ssl_node(#node_handle{connection_handler = Handler,
+ socket = Socket,
+ name = Name}) ->
+ ?t:format("Trying to stop ssl node ~s.~n", [Name]),
+ Mon = erlang:monitor(process, Handler),
+ unlink(Handler),
+ case gen_tcp:send(Socket, term_to_binary(stop)) of
+ ok ->
+ receive
+ {'DOWN', Mon, process, Handler, Reason} ->
+ case Reason of
+ normal -> ok;
+ _ -> exit(Reason)
+ end
+ end;
+ Error ->
+ erlang:demonitor(Mon, [flush]),
+ exit(Error)
+ end.
+
+start_ssl_node(Config) ->
+ start_ssl_node(Config, "").
+
+start_ssl_node(Config, XArgs) ->
+ Name = mk_node_name(Config),
+ SSL = ?config(ssl_opts, Config),
+ SSLDistOpts = setup_dist_opts(Config),
+ start_ssl_node_raw(Name, SSL ++ " " ++ SSLDistOpts ++ XArgs).
+
+start_ssl_node_raw(Name, Args) ->
+ {ok, LSock} = gen_tcp:listen(0,
+ [binary, {packet, 4}, {active, false}]),
+ {ok, ListenPort} = inet:port(LSock),
+ CmdLine = mk_node_cmdline(ListenPort, Name, Args),
+ ?t:format("Attempting to start ssl node ~s: ~s~n", [Name, CmdLine]),
+ case open_port({spawn, CmdLine}, []) of
+ Port when is_port(Port) ->
+ unlink(Port),
+ erlang:port_close(Port),
+ case await_ssl_node_up(Name, LSock) of
+ #node_handle{} = NodeHandle ->
+ ?t:format("Ssl node ~s started.~n", [Name]),
+ NodeName = list_to_atom(Name ++ "@" ++ host_name()),
+ NodeHandle#node_handle{nodename = NodeName};
+ Error ->
+ exit({failed_to_start_node, Name, Error})
+ end;
+ Error ->
+ exit({failed_to_start_node, Name, Error})
+ end.
+
+%%
+%% command line creation
+%%
+
+host_name() ->
+ [$@ | Host] = lists:dropwhile(fun ($@) -> false; (_) -> true end,
+ atom_to_list(node())),
+ Host.
+
+mk_node_name(Config) ->
+ {A, B, C} = erlang:now(),
+ Case = ?config(testcase, Config),
+ atom_to_list(?MODULE)
+ ++ "_"
+ ++ atom_to_list(Case)
+ ++ "_"
+ ++ integer_to_list(A)
+ ++ "-"
+ ++ integer_to_list(B)
+ ++ "-"
+ ++ integer_to_list(C).
+
+mk_node_cmdline(ListenPort, Name, Args) ->
+ Static = "-detached -noinput",
+ Pa = filename:dirname(code:which(?MODULE)),
+ Prog = case catch init:get_argument(progname) of
+ {ok,[[P]]} -> P;
+ _ -> exit(no_progname_argument_found)
+ end,
+ NameSw = case net_kernel:longnames() of
+ false -> "-sname ";
+ _ -> "-name "
+ end,
+ {ok, Pwd} = file:get_cwd(),
+ Prog ++ " "
+ ++ Static ++ " "
+ ++ NameSw ++ " " ++ Name ++ " "
+ ++ "-pa " ++ Pa ++ " "
+ ++ "-run application start crypto -run application start public_key "
+ ++ "-run " ++ atom_to_list(?MODULE) ++ " cnct2tstsrvr "
+ ++ host_name() ++ " "
+ ++ integer_to_list(ListenPort) ++ " "
+ ++ Args ++ " "
+ ++ "-env ERL_CRASH_DUMP " ++ Pwd ++ "/erl_crash_dump." ++ Name ++ " "
+ ++ "-setcookie " ++ atom_to_list(erlang:get_cookie()).
+
+%%
+%% Connection handler test_server side
+%%
+
+await_ssl_node_up(Name, LSock) ->
+ case gen_tcp:accept(LSock, ?AWAIT_SLL_NODE_UP_TIMEOUT) of
+ timeout ->
+ gen_tcp:close(LSock),
+ ?t:format("Timeout waiting for ssl node ~s to come up~n",
+ [Name]),
+ timeout;
+ {ok, Socket} ->
+ gen_tcp:close(LSock),
+ case gen_tcp:recv(Socket, 0) of
+ {ok, Bin} ->
+ check_ssl_node_up(Socket, Name, Bin);
+ {error, closed} ->
+ gen_tcp:close(Socket),
+ exit({lost_connection_with_ssl_node_before_up, Name})
+ end;
+ {error, Error} ->
+ gen_tcp:close(LSock),
+ exit({accept_failed, Error})
+ end.
+
+check_ssl_node_up(Socket, Name, Bin) ->
+ case catch binary_to_term(Bin) of
+ {'EXIT', _} ->
+ gen_tcp:close(Socket),
+ exit({bad_data_received_from_ssl_node, Name, Bin});
+ {ssl_node_up, NodeName} ->
+ case list_to_atom(Name++"@"++host_name()) of
+ NodeName ->
+ Parent = self(),
+ Go = make_ref(),
+ %% Spawn connection handler on test server side
+ Pid = spawn_link(
+ fun () ->
+ receive Go -> ok end,
+ tstsrvr_con_loop(Name, Socket, Parent)
+ end),
+ ok = gen_tcp:controlling_process(Socket, Pid),
+ Pid ! Go,
+ #node_handle{connection_handler = Pid,
+ socket = Socket,
+ name = Name};
+ _ ->
+ exit({unexpected_ssl_node_connected, NodeName})
+ end;
+ Msg ->
+ exit({unexpected_msg_instead_of_ssl_node_up, Name, Msg})
+ end.
+
+send_to_ssl_node(#node_handle{connection_handler = Hndlr}, Term) ->
+ Hndlr ! {relay_to_ssl_node, term_to_binary(Term)},
+ ok.
+
+tstsrvr_con_loop(Name, Socket, Parent) ->
+ inet:setopts(Socket,[{active,once}]),
+ receive
+ {relay_to_ssl_node, Data} when is_binary(Data) ->
+ case gen_tcp:send(Socket, Data) of
+ ok ->
+ ok;
+ _Error ->
+ gen_tcp:close(Socket),
+ exit({failed_to_relay_data_to_ssl_node, Name, Data})
+ end;
+ {tcp, Socket, Bin} ->
+ case catch binary_to_term(Bin) of
+ {'EXIT', _} ->
+ gen_tcp:close(Socket),
+ exit({bad_data_received_from_ssl_node, Name, Bin});
+ {format, FmtStr, ArgList} ->
+ ?t:format(FmtStr, ArgList);
+ {message, Msg} ->
+ ?t:format("Got message ~p", [Msg]),
+ Parent ! Msg;
+ {apply_res, To, Ref, Res} ->
+ To ! {Ref, Res};
+ bye ->
+ ?t:format("Ssl node ~s stopped.~n", [Name]),
+ gen_tcp:close(Socket),
+ exit(normal);
+ Unknown ->
+ exit({unexpected_message_from_ssl_node, Name, Unknown})
+ end;
+ {tcp_closed, Socket} ->
+ gen_tcp:close(Socket),
+ exit({lost_connection_with_ssl_node, Name})
+ end,
+ tstsrvr_con_loop(Name, Socket, Parent).
+
+%%
+%% Connection handler ssl_node side
+%%
+
+% cnct2tstsrvr() is called via command line arg -run ...
+cnct2tstsrvr([Host, Port]) when is_list(Host), is_list(Port) ->
+ %% Spawn connection handler on ssl node side
+ ConnHandler
+ = spawn(fun () ->
+ case catch gen_tcp:connect(Host,
+ list_to_integer(Port),
+ [binary,
+ {packet, 4},
+ {active, false}]) of
+ {ok, Socket} ->
+ notify_ssl_node_up(Socket),
+ ets:new(test_server_info,
+ [set,
+ public,
+ named_table,
+ {keypos, 1}]),
+ ets:insert(test_server_info,
+ {test_server_handler, self()}),
+ ssl_node_con_loop(Socket);
+ _Error ->
+ halt("Failed to connect to test server")
+ end
+ end),
+ spawn(fun () ->
+ Mon = erlang:monitor(process, ConnHandler),
+ receive
+ {'DOWN', Mon, process, ConnHandler, Reason} ->
+ receive after 1000 -> ok end,
+ halt("test server connection handler terminated: "
+ ++
+ lists:flatten(io_lib:format("~p", [Reason])))
+ end
+ end).
+
+notify_ssl_node_up(Socket) ->
+ case catch gen_tcp:send(Socket,
+ term_to_binary({ssl_node_up, node()})) of
+ ok -> ok;
+ _ -> halt("Failed to notify test server that I'm up")
+ end.
+
+send_to_tstsrvr(Term) ->
+ case catch ets:lookup_element(test_server_info, test_server_handler, 2) of
+ Hndlr when is_pid(Hndlr) ->
+ Hndlr ! {relay_to_test_server, term_to_binary(Term)}, ok;
+ _ ->
+ receive after 200 -> ok end,
+ send_to_tstsrvr(Term)
+ end.
+
+ssl_node_con_loop(Socket) ->
+ inet:setopts(Socket,[{active,once}]),
+ receive
+ {relay_to_test_server, Data} when is_binary(Data) ->
+ case gen_tcp:send(Socket, Data) of
+ ok ->
+ ok;
+ _Error ->
+ gen_tcp:close(Socket),
+ halt("Failed to relay data to test server")
+ end;
+ {tcp, Socket, Bin} ->
+ case catch binary_to_term(Bin) of
+ {'EXIT', _} ->
+ gen_tcp:close(Socket),
+ halt("test server sent me bad data");
+ {apply, From, Ref, M, F, A} ->
+ spawn_link(
+ fun () ->
+ send_to_tstsrvr({apply_res,
+ From,
+ Ref,
+ (catch apply(M, F, A))})
+ end);
+ {apply, From, Ref, Fun} ->
+ spawn_link(fun () ->
+ send_to_tstsrvr({apply_res,
+ From,
+ Ref,
+ (catch Fun())})
+ end);
+ stop ->
+ gen_tcp:send(Socket, term_to_binary(bye)),
+ gen_tcp:close(Socket),
+ init:stop(),
+ receive after infinity -> ok end;
+ _Unknown ->
+ halt("test server sent me an unexpected message")
+ end;
+ {tcp_closed, Socket} ->
+ halt("Lost connection to test server")
+ end,
+ ssl_node_con_loop(Socket).
+
+%%
+%% Setup ssl dist info
+%%
+
+rand_bin(N) ->
+ rand_bin(N, []).
+
+rand_bin(0, Acc) ->
+ Acc;
+rand_bin(N, Acc) ->
+ rand_bin(N-1, [random:uniform(256)-1|Acc]).
+
+make_randfile(Dir) ->
+ {ok, IoDev} = file:open(filename:join([Dir, "RAND"]), [write]),
+ {A, B, C} = erlang:now(),
+ random:seed(A, B, C),
+ ok = file:write(IoDev, rand_bin(1024)),
+ file:close(IoDev).
+
+append_files(FileNames, ResultFileName) ->
+ {ok, ResultFile} = file:open(ResultFileName, [write]),
+ do_append_files(FileNames, ResultFile).
+
+do_append_files([], RF) ->
+ ok = file:close(RF);
+do_append_files([F|Fs], RF) ->
+ {ok, Data} = file:read_file(F),
+ ok = file:write(RF, Data),
+ do_append_files(Fs, RF).
+
+setup_certs(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ NodeDir = filename:join([PrivDir, "Certs"]),
+ RGenDir = filename:join([NodeDir, "rand_gen"]),
+ ok = file:make_dir(NodeDir),
+ ok = file:make_dir(RGenDir),
+ make_randfile(RGenDir),
+ make_certs:all(RGenDir, NodeDir),
+ SDir = filename:join([NodeDir, "server"]),
+ SC = filename:join([SDir, "cert.pem"]),
+ SK = filename:join([SDir, "key.pem"]),
+ SKC = filename:join([SDir, "keycert.pem"]),
+ append_files([SK, SC], SKC),
+ CDir = filename:join([NodeDir, "client"]),
+ CC = filename:join([CDir, "cert.pem"]),
+ CK = filename:join([CDir, "key.pem"]),
+ CKC = filename:join([CDir, "keycert.pem"]),
+ append_files([CK, CC], CKC).
+
+setup_dist_opts(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ DataDir = ?config(data_dir, Config),
+ Dhfile = filename:join([DataDir, "dHParam.pem"]),
+ NodeDir = filename:join([PrivDir, "Certs"]),
+ SDir = filename:join([NodeDir, "server"]),
+ CDir = filename:join([NodeDir, "client"]),
+ SC = filename:join([SDir, "cert.pem"]),
+ SK = filename:join([SDir, "key.pem"]),
+ SKC = filename:join([SDir, "keycert.pem"]),
+ SCA = filename:join([CDir, "cacerts.pem"]),
+ CC = filename:join([CDir, "cert.pem"]),
+ CK = filename:join([CDir, "key.pem"]),
+ CKC = filename:join([CDir, "keycert.pem"]),
+ CCA = filename:join([SDir, "cacerts.pem"]),
+
+ DistOpts = case proplists:get_value(many_verify_opts, Config, false) of
+ false ->
+ "-proto_dist inet_tls "
+ ++ "-ssl_dist_opt server_certfile " ++ SKC ++ " "
+ ++ "-ssl_dist_opt client_certfile " ++ CKC ++ " ";
+ true ->
+ "-proto_dist inet_tls "
+ ++ "-ssl_dist_opt server_certfile " ++ SC ++ " "
+ ++ "-ssl_dist_opt server_keyfile " ++ SK ++ " "
+ ++ "-ssl_dist_opt server_cacertfile " ++ SCA ++ " "
+ ++ "-ssl_dist_opt server_verify verify_peer "
+ ++ "-ssl_dist_opt server_fail_if_no_peer_cert true "
+ ++ "-ssl_dist_opt server_ciphers DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA "
+ ++ "-ssl_dist_opt server_dhfile " ++ Dhfile ++ " "
+ ++ "-ssl_dist_opt client_certfile " ++ CC ++ " "
+ ++ "-ssl_dist_opt client_keyfile " ++ CK ++ " "
+ ++ "-ssl_dist_opt client_cacertfile " ++ CCA ++ " "
+ ++ "-ssl_dist_opt client_verify verify_peer "
+ ++ "-ssl_dist_opt client_ciphers DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA "
+ end,
+ MoreOpts = proplists:get_value(additional_dist_opts, Config, []),
+ DistOpts ++ MoreOpts.
+
+%%
+%% Start scripts etc...
+%%
+
+add_ssl_opts_config(Config) ->
+ %%
+ %% Start with boot scripts if on an installed system; otherwise,
+ %% just point out ssl ebin with -pa.
+ %%
+ try
+ Dir = ?config(priv_dir, Config),
+ LibDir = code:lib_dir(),
+ Apps = application:which_applications(),
+ {value, {stdlib, _, STDL_VSN}} = lists:keysearch(stdlib, 1, Apps),
+ {value, {kernel, _, KRNL_VSN}} = lists:keysearch(kernel, 1, Apps),
+ StdlDir = filename:join([LibDir, "stdlib-" ++ STDL_VSN]),
+ KrnlDir = filename:join([LibDir, "kernel-" ++ KRNL_VSN]),
+ {ok, _} = file:read_file_info(StdlDir),
+ {ok, _} = file:read_file_info(KrnlDir),
+ SSL_VSN = vsn(ssl),
+ VSN_CRYPTO = vsn(crypto),
+ VSN_PKEY = vsn(public_key),
+
+ SslDir = filename:join([LibDir, "ssl-" ++ SSL_VSN]),
+ {ok, _} = file:read_file_info(SslDir),
+ %% We are using an installed otp system, create the boot script.
+ Script = filename:join(Dir, atom_to_list(?MODULE)),
+ {ok, RelFile} = file:open(Script ++ ".rel", [write]),
+ io:format(RelFile,
+ "{release, ~n"
+ " {\"SSL distribution test release\", \"~s\"},~n"
+ " {erts, \"~s\"},~n"
+ " [{kernel, \"~s\"},~n"
+ " {stdlib, \"~s\"},~n"
+ " {crypto, \"~s\"},~n"
+ " {public_key, \"~s\"},~n"
+ " {ssl, \"~s\"}]}.~n",
+ [case catch erlang:system_info(otp_release) of
+ {'EXIT', _} -> "R11B";
+ Rel -> Rel
+ end,
+ erlang:system_info(version),
+ KRNL_VSN,
+ STDL_VSN,
+ VSN_CRYPTO,
+ VSN_PKEY,
+ SSL_VSN]),
+ ok = file:close(RelFile),
+ ok = systools:make_script(Script, []),
+ [{ssl_opts, "-boot " ++ Script} | Config]
+ catch
+ _:_ ->
+ [{ssl_opts, "-pa " ++ filename:dirname(code:which(ssl))}
+ | add_comment_config(
+ "Bootscript wasn't used since the test wasn't run on an "
+ "installed OTP system.",
+ Config)]
+ end.
+
+%%
+%% Add common comments to config
+%%
+
+add_comment_config(Comment, []) ->
+ [{comment, Comment}];
+add_comment_config(Comment, [{comment, OldComment} | Cs]) ->
+ [{comment, Comment ++ " " ++ OldComment} | Cs];
+add_comment_config(Comment, [C|Cs]) ->
+ [C|add_comment_config(Comment, Cs)].
+
+%%
+%% Call when test case success
+%%
+
+success(Config) ->
+ case lists:keysearch(comment, 1, Config) of
+ {value, {comment, _} = Res} -> Res;
+ _ -> ok
+ end.
+
+vsn(App) ->
+ application:start(App),
+ try
+ {value,
+ {ssl,
+ _,
+ VSN}} = lists:keysearch(App,
+ 1,
+ application:which_applications()),
+ VSN
+ after
+ application:stop(ssl)
+ end.
diff --git a/lib/ssl/test/ssl_dist_SUITE_data/dHParam.pem b/lib/ssl/test/ssl_dist_SUITE_data/dHParam.pem
new file mode 100644
index 0000000000..feb581da30
--- /dev/null
+++ b/lib/ssl/test/ssl_dist_SUITE_data/dHParam.pem
@@ -0,0 +1,5 @@
+-----BEGIN DH PARAMETERS-----
+MIGHAoGBAMY5VmCZ22ZEy/KO8kjt94PH7ZtSG0Z0zitlMlvd4VsNkDzXsVeu+wkH
+FGDC3h3vgv6iwXGCbmrSOVk/FPZbzLhwZ8aLnkUFOBbOvVvb1JptQwOt8mf+eScG
+M2gGBktheQV5Nf1IrzOctG7VGt+neiqb/Y86uYCcDdL+M8++0qnLAgEC
+-----END DH PARAMETERS-----
diff --git a/lib/ssl/test/ssl_handshake_SUITE.erl b/lib/ssl/test/ssl_handshake_SUITE.erl
new file mode 100644
index 0000000000..08c23b2d47
--- /dev/null
+++ b/lib/ssl/test/ssl_handshake_SUITE.erl
@@ -0,0 +1,67 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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_handshake_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include("ssl_internal.hrl").
+-include("ssl_handshake.hrl").
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() -> [
+ decode_hello_handshake,
+ decode_single_hello_extension_correctly,
+ decode_unknown_hello_extension_correctly].
+
+decode_hello_handshake(_Config) ->
+ HelloPacket = <<16#02, 16#00, 16#00,
+ 16#44, 16#03, 16#03, 16#4e, 16#7f, 16#c1, 16#03, 16#35,
+ 16#c2, 16#07, 16#b9, 16#4a, 16#58, 16#af, 16#34, 16#07,
+ 16#a6, 16#7e, 16#ef, 16#52, 16#cb, 16#e0, 16#ea, 16#b7,
+ 16#aa, 16#47, 16#c8, 16#c2, 16#2c, 16#66, 16#fa, 16#f8,
+ 16#09, 16#42, 16#cf, 16#00, 16#c0, 16#30, 16#00, 16#00,
+ 16#1c,
+ 16#00, 16#0b, 16#00, 16#04, 16#03, 16#00, 16#01, 16#02, % ec_point_formats
+ 16#ff, 16#01, 16#00, 16#01, 16#00, %% renegotiate
+ 16#00, 16#23,
+ 16#00, 16#00, 16#33, 16#74, 16#00, 16#07, 16#06, 16#73,
+ 16#70, 16#64, 16#79, 16#2f, 16#32>>,
+
+ {Records, _Buffer} = ssl_handshake:get_tls_handshake(HelloPacket, <<>>),
+
+ {Hello, _Data} = hd(Records),
+ #renegotiation_info{renegotiated_connection = <<0>>} = Hello#server_hello.renegotiation_info.
+
+decode_single_hello_extension_correctly(_Config) ->
+ Renegotiation = <<?UINT16(?RENEGOTIATION_EXT), ?UINT16(1), 0>>,
+ Extensions = ssl_handshake:dec_hello_extensions(Renegotiation, []),
+ [{renegotiation_info,#renegotiation_info{renegotiated_connection = <<0>>}}] = Extensions.
+
+
+decode_unknown_hello_extension_correctly(_Config) ->
+ FourByteUnknown = <<16#CA,16#FE, ?UINT16(4), 3, 0, 1, 2>>,
+ Renegotiation = <<?UINT16(?RENEGOTIATION_EXT), ?UINT16(1), 0>>,
+ Extensions = ssl_handshake:dec_hello_extensions(<<FourByteUnknown/binary, Renegotiation/binary>>, []),
+ [{renegotiation_info,#renegotiation_info{renegotiated_connection = <<0>>}}] = Extensions.
+
diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl
index d22d5d2954..9d2599b778 100644
--- a/lib/ssl/test/ssl_packet_SUITE.erl
+++ b/lib/ssl/test/ssl_packet_SUITE.erl
@@ -151,6 +151,9 @@ all() ->
packet_cdr_decode, packet_cdr_decode_list,
packet_http_decode, packet_http_decode_list,
packet_http_bin_decode_multi, packet_http_error_passive,
+ packet_httph_active, packet_httph_bin_active,
+ packet_httph_active_once, packet_httph_bin_active_once,
+ packet_httph_passive, packet_httph_bin_passive,
packet_line_decode, packet_line_decode_list,
packet_asn1_decode, packet_asn1_decode_list,
packet_tpkt_decode, packet_tpkt_decode_list,
@@ -1594,7 +1597,7 @@ client_http_decode(Socket, HttpRequest) ->
%%--------------------------------------------------------------------
packet_http_decode_list(doc) ->
["Test setting the packet option {packet, http}, {mode, list}"
- "(Body will be litst too)"];
+ "(Body will be list too)"];
packet_http_decode_list(suite) ->
[];
packet_http_decode_list(Config) when is_list(Config) ->
@@ -1804,7 +1807,304 @@ server_http_decode_error(Socket, HttpResponse) ->
assert_packet_opt(Socket, http),
ok = ssl:send(Socket, HttpResponse),
ok.
+%%--------------------------------------------------------------------
+packet_httph_active(doc) ->
+ ["Test setting the packet option {packet, httph}"];
+packet_httph_active(suite) ->
+ [];
+packet_httph_active(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Trailer = "Content-Encoding: gzip\r\n"
+ "\r\n",
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_send_trailer,
+ [Trailer]}},
+ {options, [{active, true}, binary |
+ 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_trailer_active,
+ []}},
+ {options, [{active, true},
+ {packet, httph},
+ list |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+server_send_trailer(Socket, Trailer)->
+ ssl:send(Socket, Trailer),
+ ok.
+
+client_http_decode_trailer_active(Socket) ->
+ receive
+ {ssl, Socket,
+ {http_header,36,'Content-Encoding',undefined,"gzip"}} ->
+ ok;
+ Other1 ->
+ exit({?LINE, Other1})
+ end,
+ receive
+ {ssl, Socket, http_eoh} ->
+ ok;
+ Other2 ->
+ exit({?LINE, Other2})
+ end,
+ ok.
+
+%%--------------------------------------------------------------------
+packet_httph_bin_active(doc) ->
+ ["Test setting the packet option {packet, httph_bin}"];
+packet_httph_bin_active(suite) ->
+ [];
+packet_httph_bin_active(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Trailer = "Content-Encoding: gzip\r\n"
+ "\r\n",
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_send_trailer,
+ [Trailer]}},
+ {options, [{active, true}, binary |
+ 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_trailer_bin_active,
+ []}},
+ {options, [{active, true},
+ {packet, httph_bin},
+ list |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+client_http_decode_trailer_bin_active(Socket) ->
+ receive
+ {ssl, Socket,
+ {http_header,36,'Content-Encoding',undefined, <<"gzip">>}} ->
+ ok;
+ Other1 ->
+ exit({?LINE, Other1})
+ end,
+ receive
+ {ssl, Socket, http_eoh} ->
+ ok;
+ Other2 ->
+ exit({?LINE, Other2})
+ end,
+ ok.
+%%--------------------------------------------------------------------
+packet_httph_active_once(doc) ->
+ ["Test setting the packet option {packet, httph}"];
+packet_httph_active_once(suite) ->
+ [];
+packet_httph_active_once(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Trailer = "Content-Encoding: gzip\r\n"
+ "\r\n",
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_send_trailer,
+ [Trailer]}},
+ {options, [{active, true}, binary |
+ 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_trailer_active_once,
+ []}},
+ {options, [{active, false},
+ {packet, httph},
+ list |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+client_http_decode_trailer_active_once(Socket) ->
+ ssl:setopts(Socket, [{active, once}]),
+ receive
+ {ssl, Socket,
+ {http_header,36,'Content-Encoding',undefined,"gzip"}} ->
+ ok;
+ Other1 ->
+ exit({?LINE, Other1})
+ end,
+ ssl:setopts(Socket, [{active, once}]),
+ receive
+ {ssl, Socket, http_eoh} ->
+ ok;
+ Other2 ->
+ exit({?LINE, Other2})
+ end,
+ ok.
+%%--------------------------------------------------------------------
+packet_httph_bin_active_once(doc) ->
+ ["Test setting the packet option {packet, httph_bin}"];
+packet_httph_bin_active_once(suite) ->
+ [];
+packet_httph_bin_active_once(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Trailer = "Content-Encoding: gzip\r\n"
+ "\r\n",
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_send_trailer,
+ [Trailer]}},
+ {options, [{active, true}, binary |
+ 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_trailer_bin_active_once,
+ []}},
+ {options, [{active, false},
+ {packet, httph_bin},
+ list |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+client_http_decode_trailer_bin_active_once(Socket) ->
+ ssl:setopts(Socket, [{active, once}]),
+ receive
+ {ssl, Socket,
+ {http_header,36,'Content-Encoding',undefined, <<"gzip">>}} ->
+ ok;
+ Other1 ->
+ exit({?LINE, Other1})
+ end,
+ ssl:setopts(Socket, [{active, once}]),
+ receive
+ {ssl, Socket, http_eoh} ->
+ ok;
+ Other2 ->
+ exit({?LINE, Other2})
+ end,
+ ok.
+
+%%--------------------------------------------------------------------
+
+packet_httph_passive(doc) ->
+ ["Test setting the packet option {packet, httph}"];
+packet_httph_passive(suite) ->
+ [];
+packet_httph_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),
+
+ Trailer = "Content-Encoding: gzip\r\n"
+ "\r\n",
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_send_trailer,
+ [Trailer]}},
+ {options, [{active, true}, binary |
+ 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_trailer_passive,
+ []}},
+ {options, [{active, false},
+ {packet, httph},
+ list |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+client_http_decode_trailer_passive(Socket) ->
+ {ok,{http_header,36,'Content-Encoding',undefined,"gzip"}} = ssl:recv(Socket, 0),
+ {ok, http_eoh} = ssl:recv(Socket, 0),
+ ok.
+
+%%--------------------------------------------------------------------
+packet_httph_bin_passive(doc) ->
+ ["Test setting the packet option {packet, httph_bin}"];
+packet_httph_bin_passive(suite) ->
+ [];
+packet_httph_bin_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),
+
+ Trailer = "Content-Encoding: gzip\r\n"
+ "\r\n",
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_send_trailer,
+ [Trailer]}},
+ {options, [{active, true}, binary |
+ 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_trailer_bin_passive,
+ []}},
+ {options, [{active, false},
+ {packet, httph_bin},
+ list |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+client_http_decode_trailer_bin_passive(Socket) ->
+ {ok,{http_header,36,'Content-Encoding',undefined,<<"gzip">>}} = ssl:recv(Socket, 0),
+ {ok, http_eoh} = ssl:recv(Socket, 0),
+ ok.
%%--------------------------------------------------------------------
packet_line_decode(doc) ->
diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl
index a43b9ab586..5ea45018e6 100644
--- a/lib/ssl/test/ssl_session_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_session_cache_SUITE.erl
@@ -26,9 +26,11 @@
-include_lib("common_test/include/ct.hrl").
+-define(DELAY, 500).
-define(SLEEP, 500).
-define(TIMEOUT, 60000).
-define(LONG_TIMEOUT, 600000).
+
-behaviour(ssl_session_cache_api).
%% For the session cache tests
@@ -95,6 +97,16 @@ init_per_testcase(session_cache_process_mnesia, Config) ->
mnesia:start(),
init_customized_session_cache(mnesia, Config);
+init_per_testcase(session_cleanup, Config0) ->
+ Config = lists:keydelete(watchdog, 1, Config0),
+ Dog = test_server:timetrap(?TIMEOUT),
+ ssl:stop(),
+ application:load(ssl),
+ application:set_env(ssl, session_lifetime, 5),
+ application:set_env(ssl, session_delay_cleanup_time, ?DELAY),
+ ssl:start(),
+ [{watchdog, Dog} | Config];
+
init_per_testcase(_TestCase, Config0) ->
Config = lists:keydelete(watchdog, 1, Config0),
Dog = test_server:timetrap(?TIMEOUT),
@@ -128,6 +140,10 @@ end_per_testcase(session_cache_process_mnesia, Config) ->
ssl:stop(),
ssl:start(),
end_per_testcase(default_action, Config);
+end_per_testcase(session_cleanup, Config) ->
+ application:unset_env(ssl, session_delay_cleanup_time),
+ application:unset_env(ssl, session_lifetime),
+ end_per_testcase(default_action, Config);
end_per_testcase(_TestCase, Config) ->
Dog = ?config(watchdog, Config),
case Dog of
@@ -148,7 +164,8 @@ end_per_testcase(_TestCase, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [session_cache_process_list,
+ [session_cleanup,
+ session_cache_process_list,
session_cache_process_mnesia].
groups() ->
@@ -159,7 +176,95 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
+%%--------------------------------------------------------------------
+session_cleanup(doc) ->
+ ["Test that sessions are cleand up eventually, so that the session table "
+ "does not grow and grow ..."];
+session_cleanup(suite) ->
+ [];
+session_cleanup(Config)when is_list(Config) ->
+ process_flag(trap_exit, true),
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, session_info_result, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client =
+ ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {from, self()}, {options, ClientOpts}]),
+ SessionInfo =
+ receive
+ {Server, Info} ->
+ Info
+ end,
+
+ %% Make sure session is registered
+ test_server:sleep(?SLEEP),
+
+ {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = state(Prop),
+ Cache = element(2, State),
+ SessionTimer = element(6, State),
+
+ Id = proplists:get_value(session_id, SessionInfo),
+ CSession = ssl_session_cache:lookup(Cache, {{Hostname, Port}, Id}),
+ SSession = ssl_session_cache:lookup(Cache, {Port, Id}),
+
+ true = CSession =/= undefined,
+ true = SSession =/= undefined,
+
+ %% Make sure session has expired and been cleaned up
+ check_timer(SessionTimer),
+ test_server:sleep(?DELAY *2), %% Delay time + some extra time
+
+ DelayTimer = get_delay_timer(),
+
+ check_timer(DelayTimer),
+
+ test_server:sleep(?SLEEP), %% Make sure clean has had to run
+
+ undefined = ssl_session_cache:lookup(Cache, {{Hostname, Port}, Id}),
+ undefined = ssl_session_cache:lookup(Cache, {Port, Id}),
+
+ process_flag(trap_exit, false),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+state([{data,[{"State", State}]} | _]) ->
+ State;
+state([_ | Rest]) ->
+ state(Rest).
+
+check_timer(Timer) ->
+ case erlang:read_timer(Timer) of
+ false ->
+ {status, _, _, _} = sys:get_status(whereis(ssl_manager)),
+ ok;
+ Int ->
+ test_server:sleep(Int),
+ check_timer(Timer)
+ end.
+get_delay_timer() ->
+ {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = state(Prop),
+ case element(7, State) of
+ undefined ->
+ test_server:sleep(?SLEEP),
+ get_delay_timer();
+ DelayTimer ->
+ DelayTimer
+ end.
+%%--------------------------------------------------------------------
session_cache_process_list(doc) ->
["Test reuse of sessions (short handshake)"];
@@ -176,7 +281,6 @@ session_cache_process_mnesia(suite) ->
session_cache_process_mnesia(Config) when is_list(Config) ->
session_cache_process(mnesia,Config).
-
%%--------------------------------------------------------------------
%%% Session cache API callbacks
%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_test_MACHINE.erl b/lib/ssl/test/ssl_test_MACHINE.erl
deleted file mode 100644
index e0ffa15d80..0000000000
--- a/lib/ssl/test/ssl_test_MACHINE.erl
+++ /dev/null
@@ -1,940 +0,0 @@
-%%
-%% %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(ssl_test_MACHINE).
-
--export([many_conns/0, mk_ssl_cert_opts/1, test_one_listener/7,
- test_server_only/6]).
-
--export([process_init/3, do_start/1]).
-
-
--include("test_server.hrl").
--include("ssl_test_MACHINE.hrl").
-
--define(WAIT_TIMEOUT, 10000).
--define(CLOSE_WAIT, 1000).
-
-%%
-%% many_conns() -> ManyConnections
-%%
-%% Choose a suitable number of "many connections" depending on platform
-%% and current limit for file descriptors.
-%%
-many_conns() ->
- case os:type() of
- {unix,_} -> many_conns_1();
- _ -> 10
- end.
-
-many_conns_1() ->
- N0 = os:cmd("ulimit -n"),
- N1 = lists:reverse(N0),
- N2 = lists:dropwhile(fun($\r) -> true;
- ($\n) -> true;
- (_) -> false
- end, N1),
- N = list_to_integer(lists:reverse(N2)),
- lists:min([(N - 10) div 2, 501]).
-
-%%
-%% mk_ssl_cert_opts(Config) -> {ok, {COpts, SOpts}}
-%%
-%%
-mk_ssl_cert_opts(_Config) ->
- Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
- COpts = [{ssl_imp, old},
- {cacertfile, filename:join([Dir, "client", "cacerts.pem"])},
- {certfile, filename:join([Dir, "client", "cert.pem"])},
- {keyfile, filename:join([Dir, "client", "key.pem"])}],
- SOpts = [{ssl_imp, old},
- {cacertfile, filename:join([Dir, "server", "cacerts.pem"])},
- {certfile, filename:join([Dir, "server", "cert.pem"])},
- {keyfile, filename:join([Dir, "server", "key.pem"])}],
- {ok, {COpts, SOpts}}.
-
-%%
-%% Cmds:
-%% {protomod, gen_tcp | ssl} default = ssl
-%% {serialize_accept, true | false} default = false
-%% {timeout, Timeout}
-%% {sockopts, Opts}
-%% {sslopts, Opts}
-%% {protocols, Protocols} [sslv2|sslv3|tlsv1]
-%% {listen, Port}
-%% {lsock, LSock} listen socket for acceptor
-%% peercert
-%% accept
-%% {connect, {Host, Port}}
-%% {recv, N}
-%% {send, N}
-%% {echo, N} async echo back
-%% close close connection socket
-%% {close, Time} wait time and then close socket
-%% lclose close listen socket
-%% await_close wait for close
-%% wait_sync listener's wait for sync from parent
-%% connection_info
-%% {exit, Reason} exit
-%%
-%%
-%% We cannot have more than `backlog' acceptors at the same time.
-%%
-
-
-%%
-%% test_one_listener(NConns, LCmds, ACmds, CCmds, Timeout, Suite, Config)
-%%
-%% Creates one client and one server node, and runs one listener on
-%% the server node (according to LCmds), and creates NConns acceptors
-%% on the server node, and the same number of connectors on the client
-%% node. The acceptors and and connectors execute according to ACmds
-%% and CCmds, respectively.
-%%
-%% It is a good idea to have the backlog size in LCmds set to
-%% be at least as large as NConns.
-%%
-test_one_listener(NConns, LCmds0, ACmds0, CCmds0, Timeout, Suite, Config) ->
- ProtoMod = get_protomod(Config),
- SerializeAccept = get_serialize_accept(Config),
- ?line {ok, {CNode, SNode}} = start_client_server_nodes(Suite),
- case ProtoMod of
- ssl ->
- ?line ok = start_ssl([CNode, SNode], Config);
- gen_tcp ->
- ok
- end,
- LCmds = [{protomod, ProtoMod}| LCmds0],
- ACmds = [{protomod, ProtoMod}, {serialize_accept, SerializeAccept}|
- ACmds0],
- CCmds = [{protomod, ProtoMod}| CCmds0],
-
- ?line {ok, Listener} = start_process(SNode, self(), LCmds, listener),
- ?line {ok, LSock} = wait_lsock(Listener, ?WAIT_TIMEOUT),
- ?line {ok, Accs0} = start_processes(NConns, SNode, self(),
- [{lsock, LSock}| ACmds], acceptor),
- Accs = case ProtoMod of
- gen_tcp ->
- [Acc1| Accs1] = Accs0,
- Acc1 ! {continue_accept, self()},
- Accs1;
- ssl ->
- Accs0
- end,
- ?line {ok, Conns} = start_processes(NConns, CNode, self(),
- CCmds, connector),
- ?line case wait_ack(Accs, Accs0 ++ Conns, Timeout) of
- ok ->
- ?line sync([Listener]),
- ?line wait_ack([], [Listener], ?WAIT_TIMEOUT);
- {error, Reason} ->
- ?line stop_node(SNode),
- ?line stop_node(CNode),
- exit(Reason)
- end,
- ?line stop_node(SNode),
- ?line stop_node(CNode),
- ok.
-
-%%
-%% test_server_only(NConns, LCmds, ACmds, Timeout, Suite, Config)
-%%
-%% Creates only one server node, and runs one listener on
-%% the server node (according to LCmds), and creates NConns acceptors
-%% on the server node. The acceptors execute according to ACmds.
-%% There are no connectors.
-%%
-test_server_only(NConns, LCmds0, ACmds0, Timeout, Suite, Config) ->
- ProtoMod = get_protomod(Config),
- ?line {ok, SNode} = start_server_node(Suite),
- case ProtoMod of
- ssl ->
- ?line ok = start_ssl([SNode], Config);
- gen_tcp ->
- ok
- end,
- LCmds = [{protomod, ProtoMod}| LCmds0],
- ACmds = [{protomod, ProtoMod}| ACmds0],
- ?line {ok, Listener} = start_process(SNode, self(), LCmds, listener),
- ?line {ok, LSock} = wait_lsock(Listener, ?WAIT_TIMEOUT),
- ?line {ok, Accs0} = start_processes(NConns, SNode, self(),
- [{lsock, LSock}| ACmds], acceptor),
- Accs = case ProtoMod of
- gen_tcp ->
- [Acc1| Accs1] = Accs0,
- Acc1 ! {continue_accept, self()},
- Accs1;
- ssl ->
- Accs0
- end,
- ?line case wait_ack(Accs, Accs0, Timeout) of
- ok ->
- ?line sync([Listener]),
- ?line wait_ack([], [Listener], ?WAIT_TIMEOUT);
- {error, Reason} ->
- ?line stop_node(SNode),
- exit(Reason)
- end,
- ?line stop_node(SNode),
- ok.
-
-%%
-%% start_client_server_nodes(Suite) -> {ok, {CNode, SNode}}
-%%
-start_client_server_nodes(Suite) ->
- {ok, CNode} = start_client_node(Suite),
- {ok, SNode} = start_server_node(Suite),
- {ok, {CNode, SNode}}.
-
-start_client_node(Suite) ->
- start_node(lists:concat([Suite, "_client"])).
-
-start_server_node(Suite) ->
- start_node(lists:concat([Suite, "_server"])).
-
-%%
-%% start_ssl(Nodes, Config)
-%%
-start_ssl(Nodes, Config) ->
- Env0 = lists:flatten([Env00 || {env, Env00} <- Config]),
- Env1 = case os:getenv("SSL_DEBUG") of
- false ->
- [];
- _ ->
- Dir = ?config(priv_dir, Config),
- [{debug, true}, {debugdir, Dir}]
- end,
- Env = Env0 ++ Env1,
- lists:foreach(
- fun(Node) -> rpc:call(Node, ?MODULE, do_start, [Env]) end, Nodes),
- ok.
-
-do_start(Env) ->
- application:start(crypto),
- application:start(public_key),
- application:load(ssl),
- lists:foreach(
- fun({Par, Val}) -> application:set_env(ssl, Par, Val) end, Env),
- application:start(ssl).
-
-
-%%
-%% start_node(Name) -> {ok, Node}
-%% start_node(Name, ExtraParams) -> {ok, Node}
-%%
-start_node(Name) ->
- start_node(Name, []).
-start_node(Name, ExtraParams) ->
- Params = "-pa " ++ filename:dirname(code:which(?MODULE)) ++ " " ++
- ExtraParams,
- test_server:start_node(Name, slave, [{args, Params}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
-
-%%
-%% start_processes(N, Node, Parent, Cmds, Type) -> {ok, Pids}
-%%
-start_processes(M, Node, Parent, Cmds, Type) ->
- start_processes1(0, M, Node, Parent, Cmds, Type, []).
-start_processes1(M, M, _, _, _, _, Pids) ->
- {ok, lists:reverse(Pids)};
-start_processes1(N, M, Node, Parent, Cmds, Type, Pids) ->
- {ok, Pid} = start_process(Node, Parent, Cmds, {Type, N + 1}),
- start_processes1(N + 1, M, Node, Parent, Cmds, Type, [Pid| Pids]).
-
-%%
-%% start_process(Node, Parent, Cmds, Type) -> {ok, Pid}
-%%
-start_process(Node, Parent, Cmds0, Type) ->
- Cmds = case os:type() of
- {win32, _} ->
- lists:map(fun(close) -> {close, ?CLOSE_WAIT};
- (Term) -> Term end, Cmds0);
- _ ->
- Cmds0
- end,
- Pid = spawn_link(Node, ?MODULE, process_init, [Parent, Cmds, Type]),
- {ok, Pid}.
-
-process_init(Parent, Cmds, Type) ->
- ?debug("#### ~w start~n", [{Type, self()}]),
- pre_main_loop(Cmds, #st{parent = Parent, type = Type}).
-
-%%
-%% pre_main_loop
-%%
-pre_main_loop([], St) ->
- ?debug("#### ~w end~n", [{St#st.type, self()}]),
- main_loop([], St);
-pre_main_loop(Cmds, St) ->
- ?debug("#### ~w -> ~w~n",
- [{St#st.type, self(), St#st.sock, St#st.port,
- St#st.peer, St#st.active}, hd(Cmds)]),
- main_loop(Cmds, St).
-
-%%
-%% main_loop(Cmds, St)
-%%
-main_loop([{protomod, ProtoMod}| Cmds], St) ->
- pre_main_loop(Cmds, St#st{protomod = ProtoMod});
-
-main_loop([{serialize_accept, Bool}| Cmds], St) ->
- pre_main_loop(Cmds, St#st{serialize_accept = Bool});
-
-main_loop([{sockopts, Opts}| Cmds], St) ->
- pre_main_loop(Cmds, St#st{sockopts = Opts});
-
-main_loop([{sslopts, Opts}| Cmds], St) ->
- pre_main_loop(Cmds, St#st{sslopts = Opts});
-
-main_loop([{protocols, Protocols}| Cmds], St) ->
- pre_main_loop(Cmds, St#st{protocols = Protocols});
-
-main_loop([{timeout, T}| Cmds], St) ->
- pre_main_loop(Cmds, St#st{timeout = T});
-
-main_loop([{lsock, LSock}| Cmds], St) ->
- pre_main_loop(Cmds, St#st{lsock = LSock});
-
-main_loop([{seed, Data}| Cmds], St) ->
- case ssl:seed("tjosan") of
- ok ->
- pre_main_loop(Cmds, St);
- {error, Reason} ->
- ?error("#### ~w(~w) in seed: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([{listen, Port}| Cmds], St) ->
- case listen(St, Port) of
- {ok, LSock} ->
- ack_lsock(St#st.parent, LSock),
- NSt = get_active(St#st{port = Port, sock = LSock, lsock = LSock}),
- pre_main_loop(Cmds, St);
- {error, Reason} ->
- ?error("#### ~w(~w) in listen: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([accept| Cmds], St) ->
- case St#st.serialize_accept of
- true ->
- Parent = St#st.parent,
- receive
- {continue_accept, Parent} ->
- ok
- end;
- false ->
- ok
- end,
- case accept(St) of
- {ok, Sock, Port, Peer} ->
- case St#st.serialize_accept of
- true ->
- St#st.parent ! {one_accept_done, self()};
- false ->
- ok
- end,
- NSt = get_active(St#st{sock = Sock, port = Port, peer = Peer}),
- pre_main_loop(Cmds, NSt);
- {error, Reason} ->
- ?error("#### ~w(~w) in accept: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([accept_timeout| Cmds], St) ->
- case accept(St) of
- {error, timeout} ->
- pre_main_loop(Cmds, St);
- {error, Reason} ->
- ?error("#### ~w(~w) in accept_timeout: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-
-main_loop([{connect, {Host, Port}}| Cmds], St) ->
- case connect(St, Host, Port) of
- {ok, Sock, LPort, Peer} ->
- NSt = get_active(St#st{sock = Sock, port = LPort, peer = Peer}),
- pre_main_loop(Cmds, NSt);
- {error, Reason} ->
- ?error("#### ~w(~w) in connect: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([connection_info| Cmds], St) ->
- case connection_info(St) of
- {ok, ProtoInfo} ->
- io:fwrite("Got connection_info:~n~p~n", [ProtoInfo]),
- pre_main_loop(Cmds, St);
- {error, Reason} ->
- ?error("#### ~w(~w) in connection_info: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([peercert| Cmds], St) ->
- case peercert(St) of
- {ok, Cert} ->
- io:fwrite("Got cert:~n~p~n", [Cert]),
- pre_main_loop(Cmds, St);
- {error, Reason} ->
- ?error("#### ~w(~w) in peercert: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([nopeercert| Cmds], St) ->
- case peercert(St) of
- {error, Reason} ->
- io:fwrite("Got no cert as expected. reason:~n~p~n", [Reason]),
- pre_main_loop(Cmds, St);
- {ok, Cert} ->
- ?error("#### ~w(~w) in peercert: error: got cert: ~p~n",
- [St#st.type, self(), Cert]),
- exit(peercert)
- end;
-
-main_loop([{recv, N}| Cmds], St) ->
- recv_loop([{recv, N}| Cmds], fun recv/1, St); % Returns to main_loop/2.
-
-main_loop([{send, N}| Cmds], St) ->
- Msg = mk_msg(N),
- case send(St, Msg) of
- ok ->
- pre_main_loop(Cmds, St);
- {error, Reason} ->
- ?error("#### ~w(~w) in send: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([{echo, N}| Cmds], St) ->
- recv_loop([{echo, N}| Cmds], fun echo/1, St); % Returns to main_loop/2.
-
-main_loop([{close, WaitTime}| Cmds], St) ->
- wait(WaitTime),
- pre_main_loop([close| Cmds], St);
-
-main_loop([close| Cmds], St) ->
- case close(St) of
- ok ->
- pre_main_loop(Cmds, St#st{sock = nil});
- {error, Reason} ->
- ?error("#### ~w(~w) in close: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([lclose| Cmds], St) ->
- case lclose(St) of
- ok ->
- pre_main_loop(Cmds, St#st{lsock = nil});
- {error, Reason} ->
- ?error("#### ~w(~w) in lclose: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([await_close| Cmds], St) ->
- case await_close(St) of
- ok ->
- pre_main_loop(Cmds, St#st{sock = nil});
- {error, Reason} ->
- ?error("#### ~w(~w) in await_close: error: ~w~n",
- [St#st.type, self(), Reason]),
- exit(Reason)
- end;
-
-main_loop([wait_sync| Cmds], St) ->
- wait_sync(St),
- pre_main_loop(Cmds, St);
-
-main_loop({exit, Reason}, _St) ->
- exit(Reason);
-
-main_loop([], _St) ->
- ok.
-
-%%
-%% recv_loop(Cmds, F, St)
-%%
-%% F = recv/1 | echo/1
-%%
-recv_loop([{_Tag, 0}| Cmds], _, St) ->
- pre_main_loop(Cmds, St);
-recv_loop([{_Tag, N}| _Cmds], _, St) when N < 0 ->
- ?error("#### ~w(~w) in recv_loop: error: too much: ~w~n",
- [St#st.type, self(), N]),
- exit(toomuch); % XXX or {error, Reason}?
-recv_loop([{Tag, N}| Cmds], F, St) ->
- case F(St) of
- {ok, Len} ->
- NSt = St#st{active = new_active(St#st.active)},
- if
- Len == N ->
- pre_main_loop(Cmds, NSt);
- true ->
- ?debug("#### ~w -> ~w~n",
- [{NSt#st.type, self(), NSt#st.sock, NSt#st.port,
- NSt#st.peer, NSt#st.active}, {Tag, N - Len}]),
- recv_loop([{Tag, N - Len}| Cmds], F, NSt)
- end;
- {error, Reason} ->
- ?error("#### ~w(~w) in recv_loop: error: ~w, ~w bytes remain~n",
- [St#st.type, self(), Reason, N]),
- exit(Reason)
- end.
-
-new_active(once) ->
- false;
-new_active(A) ->
- A.
-
-get_active(St) ->
- A = case proplists:get_value(active, St#st.sockopts, undefined) of
- undefined ->
- Mod = case St#st.protomod of
- ssl ->
- ssl;
- gen_tcp ->
- inet
- end,
- {ok, [{active, Ax}]} = Mod:getopts(St#st.sock, [active]),
- Ax;
- Ay ->
- Ay
- end,
- ?debug("#### ~w(~w) get_active: ~p\n", [St#st.type, self(), A]),
- St#st{active = A}.
-
-
-%%
-%% SOCKET FUNCTIONS
-%%
-
-%%
-%% ssl
-%%
-
-%%
-%% listen(St, LPort) -> {ok, LSock} | {error, Reason}
-%%
-listen(St, LPort) ->
- case St#st.protomod of
- ssl ->
- ssl:listen(LPort, [{ssl_imp, old} | St#st.sockopts ++ St#st.sslopts]);
- gen_tcp ->
- gen_tcp:listen(LPort, St#st.sockopts)
- end.
-
-%%
-%% accept(St) -> {ok, Sock} | {error, Reason}
-%%
-accept(St) ->
- case St#st.protomod of
- ssl ->
- case ssl:transport_accept(St#st.lsock, St#st.timeout) of
- {ok, Sock} ->
- case ssl:ssl_accept(Sock, St#st.timeout) of
- ok ->
- {ok, Port} = ssl:sockname(Sock),
- {ok, Peer} = ssl:peername(Sock),
- {ok, Sock, Port, Peer};
- Other ->
- Other
- end;
- Other ->
- Other
- end;
- gen_tcp ->
- case gen_tcp:accept(St#st.lsock, St#st.timeout) of
- {ok, Sock} ->
- {ok, Port} = inet:port(Sock),
- {ok, Peer} = inet:peername(Sock),
- {ok, Sock, Port, Peer};
- Other ->
- Other
- end
- end.
-
-%%
-%% connect(St, Host, Port) -> {ok, Sock} | {error, Reason}
-%%
-connect(St, Host, Port) ->
-
- case St#st.protomod of
- ssl ->
- case ssl:connect(Host, Port,
- [{ssl_imp, old} | St#st.sockopts ++ St#st.sslopts],
- St#st.timeout) of
- {ok, Sock} ->
- {ok, LPort} = ssl:sockname(Sock),
- {ok, Peer} = ssl:peername(Sock),
- {ok, Sock, LPort, Peer};
- Other ->
- Other
- end;
- gen_tcp ->
- case gen_tcp:connect(Host, Port, St#st.sockopts, St#st.timeout) of
- {ok, Sock} ->
- {ok, LPort} = inet:port(Sock),
- {ok, Peer} = inet:peername(Sock),
- {ok, Sock, LPort, Peer};
- Other ->
- Other
- end
- end.
-
-%%
-%% peercert(St) -> {ok, Cert} | {error, Reason}
-%%
-peercert(St) ->
- case St#st.protomod of
- ssl ->
- ssl:peercert(St#st.sock, [ssl]);
- gen_tcp ->
- {ok, <<>>}
- end.
-
-%%
-%% connection_info(St) -> {ok, ProtoInfo} | {error, Reason}
-%%
-connection_info(St) ->
- case St#st.protomod of
- ssl ->
- case ssl:connection_info(St#st.sock) of
- Res = {ok, {Proto, _}} ->
- case St#st.protocols of
- [] ->
- Res;
- Protocols ->
- case lists:member(Proto, Protocols) of
- true ->
- Res;
- false ->
- {error, Proto}
- end
- end;
- Error ->
- Error
- end;
- gen_tcp ->
- {ok, <<>>}
- end.
-
-%%
-%% close(St) -> ok | {error, Reason}
-%%
-
-close(St) ->
- Mod = St#st.protomod,
- case St#st.sock of
- nil ->
- ok;
- _ ->
- Mod:close(St#st.sock)
- end.
-
-%%
-%% lclose(St) -> ok | {error, Reason}
-%%
-lclose(St) ->
- Mod = St#st.protomod,
- case St#st.lsock of
- nil ->
- ok;
- _ ->
- Mod:close(St#st.lsock)
- end.
-
-%%
-%% recv(St) = {ok, Len} | {error, Reason}
-%%
-recv(St) ->
- case do_recv(St) of
- {ok, Msg} ->
- {ok, length(Msg)};
- {error, Reason} ->
- {error, Reason}
- end.
-
-do_recv(St) when St#st.active == false ->
- %% First check that we do *not* have any ssl/gen_tcp messages in the
- %% message queue, then call the receive function.
- Sock = St#st.sock,
- case St#st.protomod of
- ssl ->
- receive
- M = {ssl, Sock, _Msg} ->
- {error, {unexpected_messagex, M}};
- M = {ssl_closed, Sock} ->
- {error, {unexpected_message, M}};
- M = {ssl_error, Sock, _Reason} ->
- {error, {unexpected_message, M}}
- after 0 ->
- ssl:recv(St#st.sock, 0, St#st.timeout)
- end;
- gen_tcp ->
- receive
- M = {tcp, Sock, _Msg} ->
- {error, {unexpected_message, M}};
- M = {tcp_closed, Sock} ->
- {error, {unexpected_message, M}};
- M = {tcp_error, Sock, _Reason} ->
- {error, {unexpected_message, M}}
- after 0 ->
- gen_tcp:recv(St#st.sock, 0, St#st.timeout)
- end
- end;
-do_recv(St) ->
- Sock = St#st.sock,
- Timeout = St#st.timeout,
- case St#st.protomod of
- ssl ->
- receive
- {ssl, Sock, Msg} ->
- {ok, Msg};
- {ssl_closed, Sock} ->
- {error, closed};
- {ssl_error, Sock, Reason} ->
- {error, Reason}
- after Timeout ->
- {error, timeout}
- end;
- gen_tcp ->
- receive
- {tcp, Sock, Msg} ->
- {ok, Msg};
- {tcp_closed, Sock} ->
- {error, closed};
- {tcp_error, Sock, Reason} ->
- {error, Reason}
- after Timeout ->
- {error, timeout}
- end
- end.
-
-%%
-%% echo(St) = {ok, Len} | {error, Reason}
-%%
-echo(St) ->
- Sock = St#st.sock,
- case do_recv(St) of
- {ok, Msg} ->
- Mod = St#st.protomod,
- case Mod:send(Sock, Msg) of
- ok ->
- {ok, length(Msg)};
- {error, Reason} ->
- {error, Reason}
- end;
- {error, Reason} ->
- {error, Reason}
- end.
-
-%%
-%% send(St, Msg) -> ok | {error, Reason}
-%%
-send(St, Msg) ->
- Mod = St#st.protomod,
- Mod:send(St#st.sock, Msg).
-
-%%
-%% await_close(St) -> ok | {error, Reason}
-%%
-await_close(St) when St#st.active == false ->
- %% First check that we do *not* have any ssl/gen_tcp messages in the
- %% message queue, then call the receive function.
- Sock = St#st.sock,
- Res = case St#st.protomod of
- ssl ->
- receive
- M = {ssl, Sock, _Msg0} ->
- {error, {unexpected_message, M}};
- M = {ssl_closed, Sock} ->
- {error, {unexpected_message, M}};
- M = {ssl_error, Sock, _Reason} ->
- {error, {unexpected_message, M}}
- after 0 ->
- ok
- end;
- gen_tcp ->
- receive
- M = {tcp, Sock, _Msg0} ->
- {error, {unexpected_message, M}};
- M = {tcp_closed, Sock} ->
- {error, {unexpected_message, M}};
- M = {tcp_error, Sock, _Reason} ->
- {error, {unexpected_message, M}}
- after 0 ->
- ok
- end
- end,
- case Res of
- ok ->
- Mod = St#st.protomod,
- case Mod:recv(St#st.sock, 0, St#st.timeout) of
- {ok, _Msg} ->
- {error, toomuch};
- {error, _} ->
- ok
- end;
- _ ->
- Res
- end;
-await_close(St) ->
- Sock = St#st.sock,
- Timeout = St#st.timeout,
- case St#st.protomod of
- ssl ->
- receive
- {ssl, Sock, _Msg} ->
- {error, toomuch};
- {ssl_closed, Sock} ->
- ok;
- {ssl_error, Sock, Reason} ->
- {error, Reason}
- after Timeout ->
- {error, timeout}
- end;
- gen_tcp ->
- receive
- {tcp, Sock, _Msg} ->
- {error, toomuch};
- {tcp_closed, Sock} ->
- ok;
- {tcp_error, Sock, Reason} ->
- {error, Reason}
- after Timeout ->
- {error, timeout}
- end
- end.
-
-
-%%
-%% HELP FUNCTIONS
-%%
-
-wait_ack(_, [], _) ->
- ok;
-wait_ack(AccPids0, Pids, Timeout) ->
- ?debug("#### CONTROLLER: waiting for ~w~n", [Pids]),
- receive
- {one_accept_done, Pid} ->
- case lists:delete(Pid, AccPids0) of
- [] ->
- wait_ack([], Pids, Timeout);
- [AccPid| AccPids1] ->
- AccPid ! {continue_accept, self()},
- wait_ack(AccPids1, Pids, Timeout)
- end;
- {'EXIT', Pid, normal} ->
- wait_ack(AccPids0, lists:delete(Pid, Pids), Timeout);
- {'EXIT', Pid, Reason} ->
- ?error("#### CONTROLLER got abnormal exit: ~w, ~w~n",
- [Pid, Reason]),
- {error, Reason}
- after Timeout ->
- ?error("#### CONTROLLER exiting because of timeout = ~w~n",
- [Timeout]),
- {error, Timeout}
- end.
-
-
-%%
-%% ack_lsock(Pid, LSock)
-%%
-ack_lsock(Pid, LSock) ->
- Pid ! {lsock, self(), LSock}.
-
-wait_lsock(Pid, Timeout) ->
- receive
- {lsock, Pid, LSock} ->
- {ok, LSock}
- after Timeout ->
- exit(timeout)
- end.
-
-%%
-%% sync(Pids)
-%%
-sync(Pids) ->
- lists:foreach(fun (Pid) -> Pid ! {self(), sync} end, Pids).
-
-%%
-%% wait_sync(St)
-%%
-wait_sync(St) ->
- Pid = St#st.parent,
- receive
- {Pid, sync} ->
- ok
- end.
-
-%%
-%% wait(Time)
-%%
-wait(Time) ->
- receive
- after Time ->
- ok
- end.
-
-%%
-%% mk_msg(Size)
-%%
-mk_msg(Size) ->
- mk_msg(0, Size, []).
-
-mk_msg(_, 0, Acc) ->
- Acc;
-mk_msg(Pos, Size, Acc) ->
- C = (((Pos + Size) rem 256) - 1) band 255,
- mk_msg(Pos, Size - 1, [C| Acc]).
-
-%%
-%% get_protomod(Config)
-%%
-get_protomod(Config) ->
- case lists:keysearch(protomod, 1, Config) of
- {value, {_, ProtoMod}} ->
- ProtoMod;
- false ->
- ssl
- end.
-
-%%
-%% get_serialize_accept(Config)
-%%
-get_serialize_accept(Config) ->
- case lists:keysearch(serialize_accept, 1, Config) of
- {value, {_, Val}} ->
- Val;
- false ->
- false
- end.
-
diff --git a/lib/ssl/test/ssl_test_MACHINE.hrl b/lib/ssl/test/ssl_test_MACHINE.hrl
deleted file mode 100644
index e78b33f505..0000000000
--- a/lib/ssl/test/ssl_test_MACHINE.hrl
+++ /dev/null
@@ -1,39 +0,0 @@
-%%
-%% %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%
-%%
-
--record(st, {protomod = ssl,
- serialize_accept = false,
- parent = nil,
- type = nil,
- active = nil,
- port = 0,
- peer = nil,
- lsock = nil,
- sock = nil,
- timeout = infinity,
- sockopts = [],
- sslopts = [],
- protocols = []}).
-
-%%-define(debug(X, Y), io:format(X, Y)).
--define(debug(X, Y), ok).
--define(error(X, Y), io:format(X, Y)).
-
--define(DEFAULT_TIMEOUT, 240000).
-
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index 40bbdf1dbd..b7916b96eb 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -670,3 +670,6 @@ cipher_result(Socket, Result) ->
Other ->
{unexpected, Other}
end.
+
+session_info_result(Socket) ->
+ ssl:session_info(Socket).
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index 2f1edfa186..8286201df4 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1 @@
-SSL_VSN = 4.1.4
+SSL_VSN = 4.1.6
diff --git a/lib/stdlib/doc/specs/.gitignore b/lib/stdlib/doc/specs/.gitignore
new file mode 100644
index 0000000000..322eebcb06
--- /dev/null
+++ b/lib/stdlib/doc/specs/.gitignore
@@ -0,0 +1 @@
+specs_*.xml
diff --git a/lib/stdlib/doc/src/Makefile b/lib/stdlib/doc/src/Makefile
index b558697d63..16e0a86e3b 100644
--- a/lib/stdlib/doc/src/Makefile
+++ b/lib/stdlib/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2010. All Rights Reserved.
+# Copyright Ericsson AB 1997-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -125,18 +125,24 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
+
+TOP_SPECS_FILE = specs.xml
+
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
XML_FLAGS +=
+SPECS_FLAGS = -I../../include -I../../../kernel/include
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-docs: pdf html man
+docs: man pdf html
$(TOP_PDF_FILE): $(XML_FILES)
@@ -155,8 +161,13 @@ clean clean_docs:
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+ rm -f $(SPECDIR)/*
rm -f errs core *~
+$(SPECDIR)/specs_erl_id_trans.xml:
+ escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
+ -o$(dir $@) -module erl_id_trans
+
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
diff --git a/lib/stdlib/doc/src/array.xml b/lib/stdlib/doc/src/array.xml
index 5c3ac6a2a9..a79fcd487e 100644
--- a/lib/stdlib/doc/src/array.xml
+++ b/lib/stdlib/doc/src/array.xml
@@ -3,7 +3,7 @@
<erlref>
<header>
<copyright>
- <year>2007</year><year>2009</year>
+ <year>2007</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -82,19 +82,35 @@ the default value cannot be confused with the values of set entries.</p>
%% allow accesses beyond the last set entry
{'EXIT',{badarg,_}} = (catch array:set(18, true, A3)).
{'EXIT',{badarg,_}} = (catch array:get(18, A3)).</pre></description>
-<section><title>DATA TYPES</title><marker id="types"/>
-
-<taglist>
-<tag><c>array()</c></tag>
-<item><marker id="type-array"/>
-<p>A functional, extendible array. The representation is
- not documented and is subject to change without notice. Note that
- arrays cannot be directly compared for equality.</p>
-</item>
-</taglist></section>
+<datatypes>
+ <datatype>
+ <name><marker id="type-array">array()</marker></name>
+ <desc>
+ <p>A functional, extendible array. The representation is
+ not documented and is subject to change without notice. Note that
+ arrays cannot be directly compared for equality.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="array_indx"/>
+ </datatype>
+ <datatype>
+ <name name="array_opts"/>
+ </datatype>
+ <datatype>
+ <name name="array_opt"/>
+ </datatype>
+ <datatype>
+ <name name="indx_pairs"/>
+ </datatype>
+ <datatype>
+ <name name="indx_pair"/>
+ </datatype>
+</datatypes>
+
<funcs>
<func>
-<name>default(Array::array()) -&gt; term()</name>
+<name name="default" arity="1"/>
<fsummary>Get the value used for uninitialized entries.</fsummary>
<desc><marker id="default-1"/>
@@ -104,7 +120,7 @@ the default value cannot be confused with the values of set entries.</p>
<p><em>See also:</em> <seealso marker="#new-2">new/2</seealso>.</p>
</desc></func>
<func>
-<name>fix(Array::array()) -&gt; array()</name>
+<name name="fix" arity="1"/>
<fsummary>Fix the size of the array.</fsummary>
<desc><marker id="fix-1"/>
@@ -114,105 +130,100 @@ the default value cannot be confused with the values of set entries.</p>
<p><em>See also:</em> <seealso marker="#relax-1">relax/1</seealso>.</p>
</desc></func>
<func>
-<name>foldl(Function, InitialAcc::term(), Array::array()) -&gt; term()</name>
+<name name="foldl" arity="3"/>
<fsummary>Fold the elements of the array using the given function and
initial accumulator value.</fsummary>
-<type>
-<v>Function = (Index::integer(), Value::term(), Acc::term()) -&gt; term()</v></type>
<desc><marker id="foldl-3"/>
-
<p>Fold the elements of the array using the given function and
initial accumulator value. The elements are visited in order from the
- lowest index to the highest. If <c>Function</c> is not a function, the
+ lowest index to the highest. If <c><anno>Function</anno></c> is not a function, the
call fails with reason <c>badarg</c>.
</p>
<p><em>See also:</em> <seealso marker="#foldr-3">foldr/3</seealso>, <seealso marker="#map-2">map/2</seealso>, <seealso marker="#sparse_foldl-3">sparse_foldl/3</seealso>.</p>
</desc></func>
<func>
-<name>foldr(Function, InitialAcc::term(), Array::array()) -&gt; term()</name>
+<name name="foldr" arity="3"/>
<fsummary>Fold the elements of the array right-to-left using the given
function and initial accumulator value.</fsummary>
-<type>
-<v>Function = (Index::integer(), Value::term(), Acc::term()) -&gt; term()</v></type>
<desc><marker id="foldr-3"/>
<p>Fold the elements of the array right-to-left using the given
function and initial accumulator value. The elements are visited in
- order from the highest index to the lowest. If <c>Function</c> is not a
+ order from the highest index to the lowest. If <c><anno>Function</anno></c> is not a
function, the call fails with reason <c>badarg</c>.
</p>
<p><em>See also:</em> <seealso marker="#foldl-3">foldl/3</seealso>, <seealso marker="#map-2">map/2</seealso>.</p>
</desc></func>
<func>
-<name>from_list(List::list()) -&gt; array()</name>
+<name name="from_list" arity="1"/>
<fsummary>Equivalent to from_list(List, undefined).
</fsummary>
<desc><marker id="from_list-1"/>
-<p>Equivalent to <seealso marker="#from_list-2">from_list(List, undefined)</seealso>.</p>
+<p>Equivalent to <seealso marker="#from_list-2">from_list(<anno>List</anno>, undefined)</seealso>.</p>
</desc></func>
<func>
-<name>from_list(List::list(), Default::term()) -&gt; array()</name>
+<name name="from_list" arity="2"/>
<fsummary>Convert a list to an extendible array.</fsummary>
<desc><marker id="from_list-2"/>
-<p>Convert a list to an extendible array. <c>Default</c> is used as the value
- for uninitialized entries of the array. If <c>List</c> is not a proper list,
+<p>Convert a list to an extendible array. <c><anno>Default</anno></c> is used as the value
+ for uninitialized entries of the array. If <c><anno>List</anno></c> is not a proper list,
the call fails with reason <c>badarg</c>.
</p>
<p><em>See also:</em> <seealso marker="#new-2">new/2</seealso>, <seealso marker="#to_list-1">to_list/1</seealso>.</p>
</desc></func>
<func>
-<name>from_orddict(Orddict::list()) -&gt; array()</name>
+<name name="from_orddict" arity="1"/>
<fsummary>Equivalent to from_orddict(Orddict, undefined).
</fsummary>
<desc><marker id="from_orddict-1"/>
-<p>Equivalent to <seealso marker="#from_orddict-2">from_orddict(Orddict, undefined)</seealso>.</p>
+<p>Equivalent to <seealso marker="#from_orddict-2">from_orddict(<anno>Orddict</anno>, undefined)</seealso>.</p>
</desc></func>
<func>
-<name>from_orddict(List::list(), Default::term()) -&gt; array()</name>
+<name name="from_orddict" arity="2"/>
<fsummary>Convert an ordered list of pairs {Index, Value} to a
corresponding extendible array.</fsummary>
<desc><marker id="from_orddict-2"/>
<p>Convert an ordered list of pairs <c>{Index, Value}</c> to a
- corresponding extendible array. <c>Default</c> is used as the value for
- uninitialized entries of the array. If <c>List</c> is not a proper,
+ corresponding extendible array. <c><anno>Default</anno></c> is used as the value for
+ uninitialized entries of the array. If <c><anno>Orddict</anno></c> is not a proper,
ordered list of pairs whose first elements are nonnegative
integers, the call fails with reason <c>badarg</c>.
</p>
<p><em>See also:</em> <seealso marker="#new-2">new/2</seealso>, <seealso marker="#to_orddict-1">to_orddict/1</seealso>.</p>
</desc></func>
<func>
-<name>get(I::integer(), Array::array()) -&gt; term()</name>
+<name name="get" arity="2"/>
<fsummary>Get the value of entry I.</fsummary>
<desc><marker id="get-2"/>
-<p>Get the value of entry <c>I</c>. If <c>I</c> is not a nonnegative
- integer, or if the array has fixed size and <c>I</c> is larger than the
+<p>Get the value of entry <c><anno>I</anno></c>. If <c><anno>I</anno></c> is not a nonnegative
+ integer, or if the array has fixed size and <c><anno>I</anno></c> is larger than the
maximum index, the call fails with reason <c>badarg</c>.</p>
<p>If the array does not have fixed size, this function will return the
- default value for any index <c>I</c> greater than <c>size(Array)-1</c>.</p>
+ default value for any index <c><anno>I</anno></c> greater than <c>size(<anno>Array</anno>)-1</c>.</p>
<p><em>See also:</em> <seealso marker="#set-3">set/3</seealso>.</p>
</desc></func>
<func>
-<name>is_array(X::term()) -&gt; bool()</name>
+<name name="is_array" arity="1"/>
<fsummary>Returns true if X appears to be an array, otherwise false.</fsummary>
<desc><marker id="is_array-1"/>
-<p>Returns <c>true</c> if <c>X</c> appears to be an array, otherwise <c>false</c>.
- Note that the check is only shallow; there is no guarantee that <c>X</c>
+<p>Returns <c>true</c> if <c><anno>X</anno></c> appears to be an array, otherwise <c>false</c>.
+ Note that the check is only shallow; there is no guarantee that <c><anno>X</anno></c>
is a well-formed array representation even if this function returns
<c>true</c>.</p>
</desc></func>
<func>
-<name>is_fix(Array::array()) -&gt; bool()</name>
+<name name="is_fix" arity="1"/>
<fsummary>Check if the array has fixed size.</fsummary>
<desc><marker id="is_fix-1"/>
@@ -222,20 +233,18 @@ the default value cannot be confused with the values of set entries.</p>
<p><em>See also:</em> <seealso marker="#fix-1">fix/1</seealso>.</p>
</desc></func>
<func>
-<name>map(Function, Array::array()) -&gt; array()</name>
+<name name="map" arity="2"/>
<fsummary>Map the given function onto each element of the array.</fsummary>
-<type>
-<v>Function = (Index::integer(), Value::term()) -&gt; term()</v></type>
<desc><marker id="map-2"/>
<p>Map the given function onto each element of the array. The
elements are visited in order from the lowest index to the highest.
- If <c>Function</c> is not a function, the call fails with reason <c>badarg</c>.
+ If <c><anno>Function</anno></c> is not a function, the call fails with reason <c>badarg</c>.
</p>
<p><em>See also:</em> <seealso marker="#foldl-3">foldl/3</seealso>, <seealso marker="#foldr-3">foldr/3</seealso>, <seealso marker="#sparse_map-2">sparse_map/2</seealso>.</p>
</desc></func>
<func>
-<name>new() -&gt; array()</name>
+<name name="new" arity="0"/>
<fsummary>Create a new, extendible array with initial size zero.</fsummary>
<desc><marker id="new-0"/>
@@ -244,7 +253,7 @@ the default value cannot be confused with the values of set entries.</p>
<p><em>See also:</em> <seealso marker="#new-1">new/1</seealso>, <seealso marker="#new-2">new/2</seealso>.</p>
</desc></func>
<func>
-<name>new(Options::term()) -&gt; array()</name>
+<name name="new" arity="1"/>
<fsummary>Create a new array according to the given options.</fsummary>
<desc><marker id="new-1"/>
@@ -253,10 +262,10 @@ the default value cannot be confused with the values of set entries.</p>
the array is extendible and has initial size zero. Array indices
start at 0.</p>
- <p><c>Options</c> is a single term or a list of terms, selected from the
+ <p><c><anno>Options</anno></c> is a single term or a list of terms, selected from the
following:
</p><taglist>
- <tag><c>N::integer()</c> or <c>{size, N::integer()}</c></tag>
+ <tag><c>N::integer() >= 0</c> or <c>{size, N::integer() >= 0}</c></tag>
<item><p>Specifies the initial size of the array; this also implies
<c>{fixed, true}</c>. If <c>N</c> is not a nonnegative integer, the call
fails with reason <c>badarg</c>.</p></item>
@@ -283,19 +292,19 @@ cannot be changed once the array has been created.</p>
<p><em>See also:</em> <seealso marker="#fix-1">fix/1</seealso>, <seealso marker="#from_list-2">from_list/2</seealso>, <seealso marker="#get-2">get/2</seealso>, <seealso marker="#new-0">new/0</seealso>, <seealso marker="#new-2">new/2</seealso>, <seealso marker="#set-3">set/3</seealso>.</p>
</desc></func>
<func>
-<name>new(Size::integer(), Options::term()) -&gt; array()</name>
+<name name="new" arity="2"/>
<fsummary>Create a new array according to the given size and options.</fsummary>
<desc><marker id="new-2"/>
<p>Create a new array according to the given size and options. If
- <c>Size</c> is not a nonnegative integer, the call fails with reason
+ <c><anno>Size</anno></c> is not a nonnegative integer, the call fails with reason
<c>badarg</c>. By default, the array has fixed size. Note that any size
- specifications in <c>Options</c> will override the <c>Size</c> parameter.</p>
+ specifications in <c><anno>Options</anno></c> will override the <c><anno>Size</anno></c> parameter.</p>
- <p>If <c>Options</c> is a list, this is simply equivalent to <c>new([{size,
- Size} | Options]</c>, otherwise it is equivalent to <c>new([{size, Size} |
- [Options]]</c>. However, using this function directly is more efficient.</p>
+ <p>If <c><anno>Options</anno></c> is a list, this is simply equivalent to <c>new([{size,
+ <anno>Size</anno>} | <anno>Options</anno>]</c>, otherwise it is equivalent to <c>new([{size, <anno>Size</anno>} |
+ [<anno>Options</anno>]]</c>. However, using this function directly is more efficient.</p>
<p>Example:
</p><pre> array:new(100, {default,0})</pre><p> creates a fixed-size array of size
@@ -304,7 +313,7 @@ cannot be changed once the array has been created.</p>
<p><em>See also:</em> <seealso marker="#new-1">new/1</seealso>.</p>
</desc></func>
<func>
-<name>relax(Array::array()) -&gt; array()</name>
+<name name="relax" arity="1"/>
<fsummary>Make the array resizable.</fsummary>
<desc><marker id="relax-1"/>
@@ -313,24 +322,24 @@ cannot be changed once the array has been created.</p>
<p><em>See also:</em> <seealso marker="#fix-1">fix/1</seealso>.</p>
</desc></func>
<func>
-<name>reset(I::integer(), Array::array()) -&gt; array()</name>
+<name name="reset" arity="2"/>
<fsummary>Reset entry I to the default value for the array.</fsummary>
<desc><marker id="reset-2"/>
-<p>Reset entry <c>I</c> to the default value for the array.
- If the value of entry <c>I</c> is the default value the array will be
+<p>Reset entry <c><anno>I</anno></c> to the default value for the array.
+ If the value of entry <c><anno>I</anno></c> is the default value the array will be
returned unchanged. Reset will never change size of the array.
Shrinking can be done explicitly by calling <seealso marker="#resize-2">resize/2</seealso>.</p>
- <p>If <c>I</c> is not a nonnegative integer, or if the array has fixed size
- and <c>I</c> is larger than the maximum index, the call fails with reason
+ <p>If <c><anno>I</anno></c> is not a nonnegative integer, or if the array has fixed size
+ and <c><anno>I</anno></c> is larger than the maximum index, the call fails with reason
<c>badarg</c>; cf. <seealso marker="#set-3">set/3</seealso>
</p>
<p><em>See also:</em> <seealso marker="#new-2">new/2</seealso>, <seealso marker="#set-3">set/3</seealso>.</p>
</desc></func>
<func>
-<name>resize(Array::array()) -&gt; array()</name>
+<name name="resize" arity="1"/>
<fsummary>Change the size of the array to that reported by sparse_size/1.</fsummary>
<desc><marker id="resize-1"/>
@@ -340,90 +349,84 @@ cannot be changed once the array has been created.</p>
<p><em>See also:</em> <seealso marker="#resize-2">resize/2</seealso>, <seealso marker="#sparse_size-1">sparse_size/1</seealso>.</p>
</desc></func>
<func>
-<name>resize(Size::integer(), Array::array()) -&gt; array()</name>
+<name name="resize" arity="2"/>
<fsummary>Change the size of the array.</fsummary>
<desc><marker id="resize-2"/>
-<p>Change the size of the array. If <c>Size</c> is not a nonnegative
+<p>Change the size of the array. If <c><anno>Size</anno></c> is not a nonnegative
integer, the call fails with reason <c>badarg</c>. If the given array has
fixed size, the resulting array will also have fixed size.</p>
</desc></func>
<func>
-<name>set(I::integer(), Value::term(), Array::array()) -&gt; array()</name>
+<name name="set" arity="3"/>
<fsummary>Set entry I of the array to Value.</fsummary>
<desc><marker id="set-3"/>
-<p>Set entry <c>I</c> of the array to <c>Value</c>. If <c>I</c> is not a
- nonnegative integer, or if the array has fixed size and <c>I</c> is larger
+<p>Set entry <c><anno>I</anno></c> of the array to <c><anno>Value</anno></c>. If <c><anno>I</anno></c> is not a
+ nonnegative integer, or if the array has fixed size and <c><anno>I</anno></c> is larger
than the maximum index, the call fails with reason <c>badarg</c>.</p>
- <p>If the array does not have fixed size, and <c>I</c> is greater than
- <c>size(Array)-1</c>, the array will grow to size <c>I+1</c>.
+ <p>If the array does not have fixed size, and <c><anno>I</anno></c> is greater than
+ <c>size(<anno>Array</anno>)-1</c>, the array will grow to size <c><anno>I</anno>+1</c>.
</p>
<p><em>See also:</em> <seealso marker="#get-2">get/2</seealso>, <seealso marker="#reset-2">reset/2</seealso>.</p>
</desc></func>
<func>
-<name>size(Array::array()) -&gt; integer()</name>
+<name name="size" arity="1"/>
<fsummary>Get the number of entries in the array.</fsummary>
<desc><marker id="size-1"/>
<p>Get the number of entries in the array. Entries are numbered
- from 0 to <c>size(Array)-1</c>; hence, this is also the index of the first
+ from 0 to <c>size(<anno>Array</anno>)-1</c>; hence, this is also the index of the first
entry that is guaranteed to not have been previously set.</p>
<p><em>See also:</em> <seealso marker="#set-3">set/3</seealso>, <seealso marker="#sparse_size-1">sparse_size/1</seealso>.</p>
</desc></func>
<func>
-<name>sparse_foldl(Function, InitialAcc::term(), Array::array()) -&gt; term()</name>
+<name name="sparse_foldl" arity="3"/>
<fsummary>Fold the elements of the array using the given function and
initial accumulator value, skipping default-valued entries.</fsummary>
-<type>
-<v>Function = (Index::integer(), Value::term(), Acc::term()) -&gt; term()</v></type>
<desc><marker id="sparse_foldl-3"/>
<p>Fold the elements of the array using the given function and
initial accumulator value, skipping default-valued entries. The
elements are visited in order from the lowest index to the highest.
- If <c>Function</c> is not a function, the call fails with reason <c>badarg</c>.
+ If <c><anno>Function</anno></c> is not a function, the call fails with reason <c>badarg</c>.
</p>
<p><em>See also:</em> <seealso marker="#foldl-3">foldl/3</seealso>, <seealso marker="#sparse_foldr-3">sparse_foldr/3</seealso>.</p>
</desc></func>
<func>
-<name>sparse_foldr(Function, InitialAcc::term(), Array::array()) -&gt; term()</name>
+<name name="sparse_foldr" arity="3"/>
<fsummary>Fold the elements of the array right-to-left using the given
function and initial accumulator value, skipping default-valued
entries.</fsummary>
-<type>
-<v>Function = (Index::integer(), Value::term(), Acc::term()) -&gt; term()</v></type>
<desc><marker id="sparse_foldr-3"/>
<p>Fold the elements of the array right-to-left using the given
function and initial accumulator value, skipping default-valued
entries. The elements are visited in order from the highest index to
- the lowest. If <c>Function</c> is not a function, the call fails with
+ the lowest. If <c><anno>Function</anno></c> is not a function, the call fails with
reason <c>badarg</c>.
</p>
<p><em>See also:</em> <seealso marker="#foldr-3">foldr/3</seealso>, <seealso marker="#sparse_foldl-3">sparse_foldl/3</seealso>.</p>
</desc></func>
<func>
-<name>sparse_map(Function, Array::array()) -&gt; array()</name>
+<name name="sparse_map" arity="2"/>
<fsummary>Map the given function onto each element of the array, skipping
default-valued entries.</fsummary>
-<type>
-<v>Function = (Index::integer(), Value::term()) -&gt; term()</v></type>
<desc><marker id="sparse_map-2"/>
<p>Map the given function onto each element of the array, skipping
default-valued entries. The elements are visited in order from the
- lowest index to the highest. If <c>Function</c> is not a function, the
+ lowest index to the highest. If <c><anno>Function</anno></c> is not a function, the
call fails with reason <c>badarg</c>.
</p>
<p><em>See also:</em> <seealso marker="#map-2">map/2</seealso>.</p>
</desc></func>
<func>
-<name>sparse_size(A::array()) -&gt; integer()</name>
+<name name="sparse_size" arity="1"/>
<fsummary>Get the number of entries in the array up until the last
non-default valued entry.</fsummary>
@@ -436,7 +439,7 @@ cannot be changed once the array has been created.</p>
<p><em>See also:</em> <seealso marker="#resize-1">resize/1</seealso>, <seealso marker="#size-1">size/1</seealso>.</p>
</desc></func>
<func>
-<name>sparse_to_list(Array::array()) -&gt; list()</name>
+<name name="sparse_to_list" arity="1"/>
<fsummary>Converts the array to a list, skipping default-valued entries.</fsummary>
<desc><marker id="sparse_to_list-1"/>
@@ -446,7 +449,7 @@ cannot be changed once the array has been created.</p>
<p><em>See also:</em> <seealso marker="#to_list-1">to_list/1</seealso>.</p>
</desc></func>
<func>
-<name>sparse_to_orddict(Array::array()) -&gt; [{Index::integer(), Value::term()}]</name>
+<name name="sparse_to_orddict" arity="1"/>
<fsummary>Convert the array to an ordered list of pairs {Index, Value},
skipping default-valued entries.</fsummary>
@@ -458,7 +461,7 @@ cannot be changed once the array has been created.</p>
<p><em>See also:</em> <seealso marker="#to_orddict-1">to_orddict/1</seealso>.</p>
</desc></func>
<func>
-<name>to_list(Array::array()) -&gt; list()</name>
+<name name="to_list" arity="1"/>
<fsummary>Converts the array to a list.</fsummary>
<desc><marker id="to_list-1"/>
@@ -468,7 +471,7 @@ cannot be changed once the array has been created.</p>
<p><em>See also:</em> <seealso marker="#from_list-2">from_list/2</seealso>, <seealso marker="#sparse_to_list-1">sparse_to_list/1</seealso>.</p>
</desc></func>
<func>
-<name>to_orddict(Array::array()) -&gt; [{Index::integer(), Value::term()}]</name>
+<name name="to_orddict" arity="1"/>
<fsummary>Convert the array to an ordered list of pairs {Index, Value}.</fsummary>
<desc><marker id="to_orddict-1"/>
diff --git a/lib/stdlib/doc/src/base64.xml b/lib/stdlib/doc/src/base64.xml
index d3fd7a843b..bfe8494a73 100644
--- a/lib/stdlib/doc/src/base64.xml
+++ b/lib/stdlib/doc/src/base64.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2007</year><year>2009</year>
+ <year>2007</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,32 +33,33 @@
<description>
<p>Implements base 64 encode and decode, see RFC2045. </p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="ascii_string"/>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>encode(Data) -> Base64 </name>
- <name>encode_to_string(Data) -> Base64String</name>
+ <name name="encode" arity="1"/>
+ <name name="encode_to_string" arity="1"/>
<fsummary>Encodes data into base64. </fsummary>
- <type>
- <v>Data = string() | binary()</v>
- <v>Base64 = binary()</v>
- <v>Base64String = string()</v>
- </type>
+ <type variable="Data"/>
+ <type variable="Base64" name_i="1"/>
+ <type variable="Base64String"/>
<desc>
<p>Encodes a plain ASCII string into base64. The result will
be 33% larger than the data.</p>
</desc>
</func>
<func>
- <name>decode(Base64) -> Data</name>
- <name>decode_to_string(Base64) -> DataString</name>
- <name>mime_decode(Base64) -> Data</name>
- <name>mime_decode_to_string(Base64) -> DataString</name>
+ <name name="decode" arity="1"/>
+ <name name="decode_to_string" arity="1"/>
+ <name name="mime_decode" arity="1"/>
+ <name name="mime_decode_to_string" arity="1"/>
<fsummary>Decodes a base64 encoded string to data. </fsummary>
- <type>
- <v>Base64 = string() | binary()</v>
- <v>Data = binary()</v>
- <v>DataString = string()</v>
- </type>
+ <type variable="Base64" name_i="1"/>
+ <type variable="Data" name_i="1"/>
+ <type variable="DataString" name_i="2"/>
<desc>
<p>Decodes a base64 encoded string to plain ASCII. See RFC4648.
<c>mime_decode/1</c> and <c>mime_decode_to_string/1</c>
diff --git a/lib/stdlib/doc/src/beam_lib.xml b/lib/stdlib/doc/src/beam_lib.xml
index adc411e272..db65eb3848 100644
--- a/lib/stdlib/doc/src/beam_lib.xml
+++ b/lib/stdlib/doc/src/beam_lib.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2010</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -88,7 +88,6 @@
it is recommended that it contains at least 32 characters and
that both upper and lower case letters as well as digits and
special characters are used.</p>
- <p></p>
<p>The default type -- and currently the only type -- of crypto
algorithm is <c>des3_cbc</c>, three rounds of DES. The key string
will be scrambled using <c>erlang:md5/1</c> to generate
@@ -154,70 +153,78 @@
</section>
</section>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-beam() -> Module | Filename | binary()
- Module = atom()
- Filename = string() | atom()</code>
- <p>Each of the functions described below accept either the module
- name, the filename, or a binary containing the beam module.</p>
- <code type="none">
-chunkdata() = {ChunkId, DataB} | {ChunkName, DataT}
- ChunkId = chunkid()
- DataB = binary()
- {ChunkName, DataT} =
- {abstract_code, AbstractCode}
- | {attributes, [{Attribute, [AttributeValue]}]}
- | {compile_info, [{InfoKey, [InfoValue]}]}
- | {exports, [{Function, Arity}]}
- | {labeled_exports, [{Function, Arity, Label}]}
- | {imports, [{Module, Function, Arity}]}
- | {indexed_imports, [{Index, Module, Function, Arity}]}
- | {locals, [{Function, Arity}]}]}
- | {labeled_locals, [{Function, Arity, Label}]}]}
- | {atoms, [{integer(), atom()}]}
- AbstractCode = {AbstVersion, Forms} | no_abstract_code
- AbstVersion = atom()
- Attribute = atom()
- AttributeValue = term()
- Module = Function = atom()
- Arity = int()
- Label = int()</code>
- <p>It is not checked that the forms conform to the abstract format
- indicated by <c>AbstVersion</c>. <c>no_abstract_code</c> means
- that the <c>"Abst"</c> chunk is present, but empty.</p>
- <p>The list of attributes is sorted on <c>Attribute</c>, and each
- attribute name occurs once in the list. The attribute values
- occur in the same order as in the file. The lists of functions
- are also sorted.</p>
- <code type="none">
-chunkid() = "Abst" | "Attr" | "CInf"
- | "ExpT" | "ImpT" | "LocT"
- | "Atom"
+ <datatypes>
+ <datatype>
+ <name name="beam"/>
+ <desc>
+ <p>Each of the functions described below accept either the
+ module name, the filename, or a binary containing the beam
+ module.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="chunkdata"/>
+ <desc>
+ <p>The list of attributes is sorted on <c>Attribute</c>
+ (in attrib_entry()), and each
+ attribute name occurs once in the list. The attribute values
+ occur in the same order as in the file. The lists of functions
+ are also sorted.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="chunkid"/>
+ <desc>
+ <p>"Abst" | "Attr" | "CInf" | "ExpT" | "ImpT" | "LocT" | "Atom"</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="dataB"/>
+ </datatype>
+ <datatype>
+ <name name="abst_code"/>
+ <desc>
+ <p>It is not checked that the forms conform to the abstract format
+ indicated by <c><anno>AbstVersion</anno></c>. <c>no_abstract_code</c> means
+ that the <c>"Abst"</c> chunk is present, but empty.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="forms"/>
+ </datatype>
+ <datatype>
+ <name name="compinfo_entry"/>
+ </datatype>
+ <datatype>
+ <name name="attrib_entry"/>
+ </datatype>
+ <datatype>
+ <name name="labeled_entry"/>
+ </datatype>
+ <datatype>
+ <name name="index"/>
+ </datatype>
+ <datatype>
+ <name name="label"/>
+ </datatype>
+ <datatype>
+ <name name="chunkref"/>
+ </datatype>
+ <datatype>
+ <name name="chunkname"/>
+ </datatype>
+ <datatype>
+ <name name="chnk_rsn"/>
+ </datatype>
+ <datatype>
+ <name name="info_rsn"/>
+ </datatype>
+ </datatypes>
-chunkname() = abstract_code | attributes | compile_info
- | exports | labeled_exports
- | imports | indexed_imports
- | locals | labeled_locals
- | atoms
-
-chunkref() = chunkname() | chunkid()</code>
- </section>
<funcs>
<func>
- <name>chunks(Beam, [ChunkRef]) -> {ok, {Module, [ChunkData]}} | {error, beam_lib, Reason}</name>
+ <name name="chunks" arity="2"/>
<fsummary>Read selected chunks from a BEAM file or binary</fsummary>
- <type>
- <v>Beam = beam()</v>
- <v>ChunkRef = chunkref()</v>
- <v>Module = atom()</v>
- <v>ChunkData = chunkdata()</v>
- <v>Reason = {unknown_chunk, Filename, atom()}</v>
- <v>&nbsp;&nbsp;| {key_missing_or_invalid, Filename, abstract_code}</v>
- <v>&nbsp;&nbsp;| Reason1 -- see info/1</v>
- <v>&nbsp;Filename = string()</v>
- </type>
<desc>
<p>Reads chunk data for selected chunks refs. The order of
the returned list of chunk data is determined by the order
@@ -225,43 +232,26 @@ chunkref() = chunkname() | chunkid()</code>
</desc>
</func>
<func>
- <name>chunks(Beam, [ChunkRef], [Option]) -> {ok, {Module, [ChunkResult]}} | {error, beam_lib, Reason}</name>
+ <name name="chunks" arity="3"/>
<fsummary>Read selected chunks from a BEAM file or binary</fsummary>
- <type>
- <v>Beam = beam()</v>
- <v>ChunkRef = chunkref()</v>
- <v>Module = atom()</v>
- <v>Option = allow_missing_chunks</v>
- <v>ChunkResult = {chunkref(), ChunkContents} | {chunkref(), missing_chunk}</v>
- <v>Reason = {missing_chunk, Filename, atom()}</v>
- <v>&nbsp;&nbsp;| {key_missing_or_invalid, Filename, abstract_code}</v>
- <v>&nbsp;&nbsp;| Reason1 -- see info/1</v>
- <v>&nbsp;Filename = string()</v>
- </type>
<desc>
<p>Reads chunk data for selected chunks refs. The order of
the returned list of chunk data is determined by the order
of the list of chunks references.</p>
- <p>By default, if any requested chunk is missing in <c>Beam</c>,
+ <p>By default, if any requested chunk is missing in <c><anno>Beam</anno></c>,
an <c>error</c> tuple is returned.
However, if the option <c>allow_missing_chunks</c> has been given,
a result will be returned even if chunks are missing.
In the result list, any missing chunks will be represented as
- <c>{ChunkRef,missing_chunk}</c>.
+ <c>{<anno>ChunkRef</anno>,missing_chunk}</c>.
Note, however, that if the <c>"Atom"</c> chunk if missing, that is
considered a fatal error and the return value will be an <c>error</c>
tuple.</p>
</desc>
</func>
<func>
- <name>version(Beam) -> {ok, {Module, [Version]}} | {error, beam_lib, Reason}</name>
+ <name name="version" arity="1"/>
<fsummary>Read the BEAM file's module version</fsummary>
- <type>
- <v>Beam = beam()</v>
- <v>Module = atom()</v>
- <v>Version = term()</v>
- <v>Reason -- see chunks/2</v>
- </type>
<desc>
<p>Returns the module version(s). A version is defined by
the module attribute <c>-vsn(Vsn)</c>. If this attribute is
@@ -282,51 +272,30 @@ chunkref() = chunkname() | chunkid()</code>
</desc>
</func>
<func>
- <name>md5(Beam) -> {ok, {Module, MD5}} | {error, beam_lib, Reason}</name>
+ <name name="md5" arity="1"/>
<fsummary>Read the BEAM file's module version</fsummary>
- <type>
- <v>Beam = beam()</v>
- <v>Module = atom()</v>
- <v>MD5 = binary()</v>
- <v>Reason -- see chunks/2</v>
- </type>
<desc>
<p>Calculates an MD5 redundancy check for the code of the module
(compilation date and other attributes are not included).</p>
</desc>
</func>
<func>
- <name>info(Beam) -> [{Item, Info}] | {error, beam_lib, Reason1}</name>
+ <name name="info" arity="1"/>
<fsummary>Information about a BEAM file</fsummary>
- <type>
- <v>Beam = beam()</v>
- <v>Item, Info -- see below</v>
- <v>Reason1 = {chunk_too_big, Filename, ChunkId, ChunkSize, FileSize}</v>
- <v>&nbsp;&nbsp;| {invalid_beam_file, Filename, Pos}</v>
- <v>&nbsp;&nbsp;| {invalid_chunk, Filename, ChunkId}</v>
- <v>&nbsp;&nbsp;| {missing_chunk, Filename, ChunkId}</v>
- <v>&nbsp;&nbsp;| {not_a_beam_file, Filename}</v>
- <v>&nbsp;&nbsp;| {file_error, Filename, Posix}</v>
- <v>&nbsp;Filename = string()</v>
- <v>&nbsp;ChunkId = chunkid()</v>
- <v>&nbsp;ChunkSize = FileSize = int()</v>
- <v>&nbsp;Pos = int()</v>
- <v>&nbsp;Posix = posix() -- see file(3)</v>
- </type>
<desc>
<p>Returns a list containing some information about a BEAM file
as tuples <c>{Item, Info}</c>:</p>
<taglist>
- <tag><c>{file, Filename} | {binary, Binary}</c></tag>
+ <tag><c>{file, <anno>Filename</anno>} | {binary, <anno>Binary</anno>}</c></tag>
<item>
<p>The name (string) of the BEAM file, or the binary from
which the information was extracted.</p>
</item>
- <tag><c>{module, Module}</c></tag>
+ <tag><c>{module, <anno>Module</anno>}</c></tag>
<item>
<p>The name (atom) of the module.</p>
</item>
- <tag><c>{chunks, [{ChunkId, Pos, Size}]}</c></tag>
+ <tag><c>{chunks, [{<anno>ChunkId</anno>, <anno>Pos</anno>, <anno>Size</anno>}]}</c></tag>
<item>
<p>For each chunk, the identifier (string) and the position
and size of the chunk data, in bytes.</p>
@@ -335,17 +304,9 @@ chunkref() = chunkname() | chunkid()</code>
</desc>
</func>
<func>
- <name>cmp(Beam1, Beam2) -> ok | {error, beam_lib, Reason}</name>
+ <name name="cmp" arity="2"/>
<fsummary>Compare two BEAM files</fsummary>
- <type>
- <v>Beam1 = Beam2 = beam()</v>
- <v>Reason = {modules_different, Module1, Module2}</v>
- <v>&nbsp;&nbsp;| {chunks_different, ChunkId}</v>
- <v>&nbsp;&nbsp;| different_chunks</v>
- <v>&nbsp;&nbsp;| Reason1 -- see info/1</v>
- <v>&nbsp;Module1 = Module2 = atom()</v>
- <v>&nbsp;ChunkId = chunkid()</v>
- </type>
+ <type name="cmp_rsn"/>
<desc>
<p>Compares the contents of two BEAM files. If the module names
are the same, and all chunks except for the <c>"CInf"</c> chunk
@@ -356,34 +317,23 @@ chunkref() = chunkname() | chunkid()</code>
</desc>
</func>
<func>
- <name>cmp_dirs(Dir1, Dir2) -> {Only1, Only2, Different} | {error, beam_lib, Reason1}</name>
+ <name name="cmp_dirs" arity="2"/>
<fsummary>Compare the BEAM files in two directories</fsummary>
- <type>
- <v>Dir1 = Dir2 = string() | atom()</v>
- <v>Different = [{Filename1, Filename2}]</v>
- <v>Only1 = Only2 = [Filename]</v>
- <v>Filename = Filename1 = Filename2 = string()</v>
- <v>Reason1 = {not_a_directory, term()} | -- see info/1</v>
- </type>
<desc>
<p>The <c>cmp_dirs/2</c> function compares the BEAM files in
two directories. Only files with extension <c>".beam"</c> are
- compared. BEAM files that exist in directory <c>Dir1</c>
- (<c>Dir2</c>) only are returned in <c>Only1</c>
- (<c>Only2</c>). BEAM files that exist on both directories but
+ compared. BEAM files that exist in directory <c><anno>Dir1</anno></c>
+ (<c><anno>Dir2</anno></c>) only are returned in <c><anno>Only1</anno></c>
+ (<c><anno>Only2</anno></c>). BEAM files that exist on both directories but
are considered different by <c>cmp/2</c> are returned as
- pairs {<c>Filename1</c>, <c>Filename2</c>} where
- <c>Filename1</c> (<c>Filename2</c>) exists in directory
- <c>Dir1</c> (<c>Dir2</c>).</p>
+ pairs {<c><anno>Filename1</anno></c>, <c><anno>Filename2</anno></c>} where
+ <c><anno>Filename1</anno></c> (<c><anno>Filename2</anno></c>) exists in directory
+ <c><anno>Dir1</anno></c> (<c><anno>Dir2</anno></c>).</p>
</desc>
</func>
<func>
- <name>diff_dirs(Dir1, Dir2) -> ok | {error, beam_lib, Reason1}</name>
+ <name name="diff_dirs" arity="2"/>
<fsummary>Compare the BEAM files in two directories</fsummary>
- <type>
- <v>Dir1 = Dir2 = string() | atom()</v>
- <v>Reason1 = {not_a_directory, term()} | -- see info/1</v>
- </type>
<desc>
<p>The <c>diff_dirs/2</c> function compares the BEAM files in
two directories the way <c>cmp_dirs/2</c> does, but names of
@@ -392,13 +342,8 @@ chunkref() = chunkname() | chunkid()</code>
</desc>
</func>
<func>
- <name>strip(Beam1) -> {ok, {Module, Beam2}} | {error, beam_lib, Reason1}</name>
+ <name name="strip" arity="1"/>
<fsummary>Removes chunks not needed by the loader from a BEAM file</fsummary>
- <type>
- <v>Beam1 = Beam2 = beam()</v>
- <v>Module = atom()</v>
- <v>Reason1 -- see info/1</v>
- </type>
<desc>
<p>The <c>strip/1</c> function removes all chunks from a BEAM
file except those needed by the loader. In particular,
@@ -406,15 +351,8 @@ chunkref() = chunkname() | chunkid()</code>
</desc>
</func>
<func>
- <name>strip_files(Files) -> {ok, [{Module, Beam2}]} | {error, beam_lib, Reason1}</name>
+ <name name="strip_files" arity="1"/>
<fsummary>Removes chunks not needed by the loader from BEAM files</fsummary>
- <type>
- <v>Files = [Beam1]</v>
- <v>&nbsp;Beam1 = beam()</v>
- <v>Module = atom()</v>
- <v>Beam2 = beam()</v>
- <v>Reason1 -- see info/1</v>
- </type>
<desc>
<p>The <c>strip_files/1</c> function removes all chunks except
those needed by the loader from BEAM files. In particular,
@@ -424,30 +362,20 @@ chunkref() = chunkname() | chunkid()</code>
</desc>
</func>
<func>
- <name>strip_release(Dir) -> {ok, [{Module, Filename]}} | {error, beam_lib, Reason1}</name>
+ <name name="strip_release" arity="1"/>
<fsummary>Removes chunks not needed by the loader from all BEAM files of a release</fsummary>
- <type>
- <v>Dir = string() | atom()</v>
- <v>Module = atom()</v>
- <v>Filename = string()</v>
- <v>Reason1 = {not_a_directory, term()} | -- see info/1</v>
- </type>
<desc>
<p>The <c>strip_release/1</c> function removes all chunks
except those needed by the loader from the BEAM files of a
- release. <c>Dir</c> should be the installation root
+ release. <c><anno>Dir</anno></c> should be the installation root
directory. For example, the current OTP release can be
stripped with the call
<c>beam_lib:strip_release(code:root_dir())</c>.</p>
</desc>
</func>
<func>
- <name>format_error(Reason) -> Chars</name>
+ <name name="format_error" arity="1"/>
<fsummary>Return an English description of a BEAM read error reply</fsummary>
- <type>
- <v>Reason -- see other functions</v>
- <v>Chars = [char() | Chars]</v>
- </type>
<desc>
<p>Given the error returned by any function in this module,
the function <c>format_error</c> returns a descriptive string
@@ -456,12 +384,11 @@ chunkref() = chunkname() | chunkid()</code>
</desc>
</func>
<func>
- <name>crypto_key_fun(CryptoKeyFun) -> ok | {error, Reason}</name>
+ <name name="crypto_key_fun" arity="1"/>
<fsummary>Register a fun that provides a crypto key</fsummary>
- <type>
- <v>CryptoKeyFun = fun() -- see below</v>
- <v>Reason = badfun | exists | term()</v>
- </type>
+ <type name="crypto_fun"/>
+ <type name="crypto_fun_arg"/>
+ <type name="mode"/>
<desc>
<p>The <c>crypto_key_fun/1</c> function registers a unary fun
that will be called if <c>beam_lib</c> needs to read an
@@ -495,11 +422,8 @@ chunkref() = chunkname() | chunkid()</code>
</desc>
</func>
<func>
- <name>clear_crypto_key_fun() -> {ok, Result}</name>
+ <name name="clear_crypto_key_fun" arity="0"/>
<fsummary>Unregister the current crypto key fun</fsummary>
- <type>
- <v>Result = undefined | term()</v>
- </type>
<desc>
<p>Unregisters the crypto key fun and terminates the process
holding it, started by <c>crypto_key_fun/1</c>.</p>
diff --git a/lib/stdlib/doc/src/binary.xml b/lib/stdlib/doc/src/binary.xml
index c81023862e..88ce77e0d0 100644
--- a/lib/stdlib/doc/src/binary.xml
+++ b/lib/stdlib/doc/src/binary.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2009</year>
- <year>2010</year>
+ <year>2011</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -53,37 +53,35 @@
module.
</p>
</note>
-
-
</description>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
- cp()
- - Opaque data-type representing a compiled search-pattern. Guaranteed to be a tuple()
- to allow programs to distinguish it from non precompiled search patterns.
- </code>
- <code type="none">
- part() = {Start,Length}
- Start = int()
- Length = int()
- - A representaion of a part (or range) in a binary. Start is a
+ <datatypes>
+ <datatype>
+ <name name="cp"/>
+ <desc><p>Opaque data-type representing a compiled
+ search-pattern. Guaranteed to be a tuple() to allow programs to
+ distinguish it from non precompiled search patterns.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="part"/>
+ <desc><p>A representaion of a part (or range) in a binary. Start is a
zero-based offset into a binary() and Length is the length of
that part. As input to functions in this module, a reverse
part specification is allowed, constructed with a negative
Length, so that the part of the binary begins at Start +
Length and is -Length long. This is useful for referencing the
last N bytes of a binary as {size(Binary), -N}. The functions
- in this module always return part()'s with positive Length.
- </code>
- </section>
+ in this module always return part()'s with positive Length.</p>
+ </desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>at(Subject, Pos) -> int()</name>
+ <name>at(Subject, Pos) -> byte()</name>
<fsummary>Returns the byte at a specific position in a binary</fsummary>
<type>
<v>Subject = binary()</v>
- <v>Pos = int() >= 0</v>
+ <v>Pos = integer() >= 0</v>
</type>
<desc>
@@ -95,7 +93,7 @@
</desc>
</func>
<func>
- <name>bin_to_list(Subject) -> list()</name>
+ <name>bin_to_list(Subject) -> [byte()]</name>
<fsummary>Convert a binary to a list of integers</fsummary>
<type>
<v>Subject = binary()</v>
@@ -105,7 +103,7 @@
</desc>
</func>
<func>
- <name>bin_to_list(Subject, PosLen) -> list()</name>
+ <name>bin_to_list(Subject, PosLen) -> [byte()]</name>
<fsummary>Convert a binary to a list of integers</fsummary>
<type>
<v>Subject = binary()</v>
@@ -113,7 +111,7 @@
</type>
<desc>
- <p>Converts <c>Subject</c> to a list of <c>int()</c>s, each representing
+ <p>Converts <c>Subject</c> to a list of <c>byte()</c>s, each representing
the value of one byte. The <c>part()</c> denotes which part of the
<c>binary()</c> to convert. Example:</p>
@@ -126,12 +124,12 @@
</desc>
</func>
<func>
- <name>bin_to_list(Subject, Pos, Len) -> list()</name>
+ <name>bin_to_list(Subject, Pos, Len) -> [byte()]</name>
<fsummary>Convert a binary to a list of integers</fsummary>
<type>
<v>Subject = binary()</v>
- <v>Pos = int()</v>
- <v>Len = int()</v>
+ <v>Pos = integer() >= 0</v>
+ <v>Len = integer() >= 0</v>
</type>
<desc>
<p>The same as<c> bin_to_list(Subject,{Pos,Len})</c>.</p>
@@ -185,7 +183,7 @@
<fsummary>Duplicates a binary N times and creates a new</fsummary>
<type>
<v>Subject = binary()</v>
- <v>N = int() >= 0</v>
+ <v>N = integer() >= 0</v>
</type>
<desc>
<p>Creates a binary with the content of <c>Subject</c> duplicated <c>N</c> times.</p>
@@ -211,7 +209,7 @@
<fsummary>Decode a whole binary into an integer of arbitrary size</fsummary>
<type>
<v>Subject = binary()</v>
- <v>Unsigned = int() >= 0</v>
+ <v>Unsigned = integer() >= 0</v>
</type>
<desc>
<p>The same as <c>decode_unsigned(Subject,big)</c>.</p>
@@ -223,12 +221,12 @@
<type>
<v>Subject = binary()</v>
<v>Endianess = big | little</v>
- <v>Unsigned = int() >= 0</v>
+ <v>Unsigned = integer() >= 0</v>
</type>
<desc>
<p>Converts the binary digit representation, in big or little
- endian, of a positive integer in <c>Subject</c> to an Erlang <c>int()</c>.</p>
+ endian, of a positive integer in <c>Subject</c> to an Erlang <c>integer()</c>.</p>
<p>Example:</p>
@@ -242,7 +240,7 @@
<name>encode_unsigned(Unsigned) -> binary()</name>
<fsummary>Encodes an unsigned integer into the minimal binary</fsummary>
<type>
- <v>Unsigned = int() >= 0</v>
+ <v>Unsigned = integer() >= 0</v>
</type>
<desc>
<p>The same as <c>encode_unsigned(Unsigned,big)</c>.</p>
@@ -252,7 +250,7 @@
<name>encode_unsigned(Unsigned,Endianess) -> binary()</name>
<fsummary>Encodes an unsigned integer into the minimal binary</fsummary>
<type>
- <v>Unsigned = int() >= 0</v>
+ <v>Unsigned = integer() >= 0</v>
<v>Endianess = big | little</v>
</type>
<desc>
@@ -270,7 +268,7 @@
</desc>
</func>
<func>
- <name>first(Subject) -> int()</name>
+ <name>first(Subject) -> byte()</name>
<fsummary>Returns the first byte of a binary</fsummary>
<type>
<v>Subject = binary()</v>
@@ -283,7 +281,7 @@
</desc>
</func>
<func>
- <name>last(Subject) -> int()</name>
+ <name>last(Subject) -> byte()</name>
<fsummary>Returns the last byte of a binary</fsummary>
<type>
<v>Subject = binary()</v>
@@ -306,7 +304,7 @@
</desc>
</func>
<func>
- <name>longest_common_prefix(Binaries) -> int()</name>
+ <name>longest_common_prefix(Binaries) -> integer() >= 0</name>
<fsummary>Returns length of longest common prefix for a set of binaries</fsummary>
<type>
<v>Binaries = [ binary() ]</v>
@@ -327,7 +325,7 @@
</desc>
</func>
<func>
- <name>longest_common_suffix(Binaries) -> int()</name>
+ <name>longest_common_suffix(Binaries) -> integer() >= 0</name>
<fsummary>Returns length of longest common suffix for a set of binaries</fsummary>
<type>
<v>Binaries = [ binary() ]</v>
@@ -450,7 +448,7 @@
[{1,4}]
</code>
- <p>The result shows that &lt;&lt;bcde"&gt;&gt; is selected instead of the
+ <p>The result shows that &lt;&lt;"bcde"&gt;&gt; is selected instead of the
shorter match &lt;&lt;"bc"&gt;&gt; (which would have given raise to one
more match,&lt;&lt;"de"&gt;&gt;). This corresponds to the behavior of posix
regular expressions (and programs like awk), but is not
@@ -506,15 +504,15 @@
<fsummary>Extracts a part of a binary</fsummary>
<type>
<v>Subject = binary()</v>
- <v>Pos = int()</v>
- <v>Len = int()</v>
+ <v>Pos = integer() >= 0</v>
+ <v>Len = integer() >= 0</v>
</type>
<desc>
<p>The same as <c>part(Subject, {Pos, Len})</c>.</p>
</desc>
</func>
<func>
- <name>referenced_byte_size(binary()) -> int()</name>
+ <name>referenced_byte_size(binary()) -> integer() >= 0</name>
<fsummary>Determines the size of the actual binary pointed out by a sub-binary</fsummary>
<desc>
@@ -581,42 +579,28 @@ store(Binary, GBSet) ->
</desc>
</func>
<func>
- <name>replace(Subject,Pattern,Replacement) -> Result</name>
+ <name name="replace" arity="3"/>
<fsummary>Replaces bytes in a binary according to a pattern</fsummary>
- <type>
- <v>Subject = binary()</v>
- <v>Pattern = binary() | [ binary() ] | cp()</v>
- <v>Replacement = binary()</v>
- <v>Result = binary()</v>
- </type>
<desc>
- <p>The same as <c>replace(Subject,Pattern,Replacement,[])</c>.</p>
+ <p>The same as <c>replace(<anno>Subject</anno>,<anno>Pattern</anno>,<anno>Replacement</anno>,[])</c>.</p>
</desc>
</func>
<func>
- <name>replace(Subject,Pattern,Replacement,Options) -> Result</name>
+ <name name="replace" arity="4"/>
<fsummary>Replaces bytes in a binary according to a pattern</fsummary>
- <type>
- <v>Subject = binary()</v>
- <v>Pattern = binary() | [ binary() ] | cp()</v>
- <v>Replacement = binary()</v>
- <v>Result = binary()</v>
- <v>Options = [ Option ]</v>
- <v>Option = global | {scope, part()} | {insert_replaced, InsPos}</v>
- <v>InsPos = OnePos | [ OnePos ]</v>
- <v>OnePos = int() =&lt; byte_size(Replacement)</v>
- </type>
+ <type_desc variable="OnePos">An integer() =&lt; byte_size(<anno>Replacement</anno>)
+ </type_desc>
<desc>
<p>Constructs a new binary by replacing the parts in
- <c>Subject</c> matching <c>Pattern</c> with the content of
- <c>Replacement</c>.</p>
+ <c><anno>Subject</anno></c> matching <c><anno>Pattern</anno></c> with the content of
+ <c><anno>Replacement</anno></c>.</p>
- <p>If the matching sub-part of <c>Subject</c> giving raise to the
+ <p>If the matching sub-part of <c><anno>Subject</anno></c> giving raise to the
replacement is to be inserted in the result, the option
- <c>{insert_replaced, InsPos}</c> will insert the matching part into
- <c>Replacement</c> at the given position (or positions) before actually
- inserting <c>Replacement</c> into the <c>Subject</c>. Example:</p>
+ <c>{insert_replaced, <anno>InsPos</anno>}</c> will insert the matching part into
+ <c><anno>Replacement</anno></c> at the given position (or positions) before actually
+ inserting <c><anno>Replacement</anno></c> into the <c><anno>Subject</anno></c>. Example:</p>
<code>
1> binary:replace(&lt;&lt;"abcde"&gt;&gt;,&lt;&lt;"b"&gt;&gt;,&lt;&lt;"[]"&gt;&gt;,[{insert_replaced,1}]).
@@ -632,42 +616,30 @@ store(Binary, GBSet) ->
&lt;&lt;"a[b-b]c[d-d]e"&gt;&gt;
</code>
- <p>If any position given in <c>InsPos</c> is greater than the size of the replacement binary, a <c>badarg</c> exception is raised.</p>
+ <p>If any position given in <c><anno>InsPos</anno></c> is greater than the size of the replacement binary, a <c>badarg</c> exception is raised.</p>
<p>The options <c>global</c> and <c>{scope, part()}</c> work as for <seealso marker="#split-3">split/3</seealso>. The return type is always a <c>binary()</c>.</p>
- <p>For a description of <c>Pattern</c>, see <seealso marker="#compile_pattern-1">compile_pattern/1</seealso>.</p>
+ <p>For a description of <c><anno>Pattern</anno></c>, see <seealso marker="#compile_pattern-1">compile_pattern/1</seealso>.</p>
</desc>
</func>
<func>
- <name>split(Subject,Pattern) -> Parts</name>
+ <name name="split" arity="2"/>
<fsummary>Splits a binary according to a pattern</fsummary>
- <type>
- <v>Subject = binary()</v>
- <v>Pattern = binary() | [ binary() ] | cp()</v>
- <v>Parts = [ binary() ]</v>
- </type>
<desc>
- <p>The same as <c>split(Subject, Pattern, [])</c>.</p>
+ <p>The same as <c>split(<anno>Subject</anno>, <anno>Pattern</anno>, [])</c>.</p>
</desc>
</func>
<func>
- <name>split(Subject,Pattern,Options) -> Parts</name>
+ <name name="split" arity="3"/>
<fsummary>Splits a binary according to a pattern</fsummary>
- <type>
- <v>Subject = binary()</v>
- <v>Pattern = binary() | [ binary() ] | cp()</v>
- <v>Parts = [ binary() ]</v>
- <v>Options = [ Option ]</v>
- <v>Option = {scope, part()} | trim | global</v>
- </type>
<desc>
- <p>Splits Binary into a list of binaries based on Pattern. If
+ <p>Splits <c><anno>Subject</anno></c> into a list of binaries based on <c><anno>Pattern</anno></c>. If
the option global is not given, only the first occurrence of
- Pattern in Subject will give rise to a split.</p>
+ <c><anno>Pattern</anno></c> in <c><anno>Subject</anno></c> will give rise to a split.</p>
- <p>The parts of Pattern actually found in Subject are not included in the result.</p>
+ <p>The parts of <c><anno>Pattern</anno></c> actually found in <c><anno>Subject</anno></c> are not included in the result.</p>
<p>Example:</p>
@@ -696,7 +668,7 @@ store(Binary, GBSet) ->
<tag>global</tag>
- <item><p>Repeats the split until the <c>Subject</c> is
+ <item><p>Repeats the split until the <c><anno>Subject</anno></c> is
exhausted. Conceptually the global option makes split work on
the positions returned by <seealso marker="#matches-3">matches/3</seealso>,
while it normally
@@ -716,12 +688,12 @@ store(Binary, GBSet) ->
</code>
<p>The return type is always a list of binaries that are all
- referencing <c>Subject</c>. This means that the data in <c>Subject</c> is not
- actually copied to new binaries and that <c>Subject</c> cannot be
+ referencing <c><anno>Subject</anno></c>. This means that the data in <c><anno>Subject</anno></c> is not
+ actually copied to new binaries and that <c><anno>Subject</anno></c> cannot be
garbage collected until the results of the split are no longer
referenced.</p>
- <p>For a description of <c>Pattern</c>, see <seealso marker="#compile_pattern-1">compile_pattern/1</seealso>.</p>
+ <p>For a description of <c><anno>Pattern</anno></c>, see <seealso marker="#compile_pattern-1">compile_pattern/1</seealso>.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/c.xml b/lib/stdlib/doc/src/c.xml
index 19e3ac1f08..ddae388a1b 100644
--- a/lib/stdlib/doc/src/c.xml
+++ b/lib/stdlib/doc/src/c.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -39,43 +39,33 @@
</description>
<funcs>
<func>
- <name>bt(Pid) -> void()</name>
+ <name name="bt" arity="1"/>
<fsummary>Stack backtrace for a process</fsummary>
- <type>
- <v>Pid = pid()</v>
- </type>
<desc>
<p>Stack backtrace for a process. Equivalent to
- <c>erlang:process_display(Pid, backtrace)</c>.</p>
+ <c>erlang:process_display(<anno>Pid</anno>, backtrace)</c>.</p>
</desc>
</func>
<func>
- <name>c(File) -> {ok, Module} | error</name>
- <name>c(File, Options) -> {ok, Module} | error</name>
+ <name name="c" arity="1"/>
+ <name name="c" arity="2"/>
<fsummary>Compile and load code in a file</fsummary>
- <type>
- <v>File = name() -- see filename(3)</v>
- <v>Options = [Opt] -- see compile:file/2</v>
- </type>
<desc>
<p><c>c/1,2</c> compiles and then purges and loads the code for
- a file. <c>Options</c> defaults to []. Compilation is
+ a file. <c><anno>Options</anno></c> defaults to []. Compilation is
equivalent to:</p>
<code type="none">
-compile:file(File, Options ++ [report_errors, report_warnings])</code>
+compile:file(<anno>File</anno>, <anno>Options</anno> ++ [report_errors, report_warnings])</code>
<p>Note that purging the code means that any processes
lingering in old code for the module are killed without
warning. See <c>code/3</c> for more information.</p>
</desc>
</func>
<func>
- <name>cd(Dir) -> void()</name>
+ <name name="cd" arity="1"/>
<fsummary>Change working directory</fsummary>
- <type>
- <v>Dir = name() -- see filename(3)</v>
- </type>
<desc>
- <p>Changes working directory to <c>Dir</c>, which may be a
+ <p>Changes working directory to <c><anno>Dir</anno></c>, which may be a
relative name, and then prints the name of the new working
directory.</p>
<pre>
@@ -84,14 +74,14 @@ compile:file(File, Options ++ [report_errors, report_warnings])</code>
</desc>
</func>
<func>
- <name>flush() -> void()</name>
+ <name name="flush" arity="0"/>
<fsummary>Flush any messages sent to the shell</fsummary>
<desc>
<p>Flushes any messages sent to the shell.</p>
</desc>
</func>
<func>
- <name>help() -> void()</name>
+ <name name="help" arity="0"/>
<fsummary>Help information</fsummary>
<desc>
<p>Displays help information: all valid shell internal commands,
@@ -99,8 +89,8 @@ compile:file(File, Options ++ [report_errors, report_warnings])</code>
</desc>
</func>
<func>
- <name>i() -> void()</name>
- <name>ni() -> void()</name>
+ <name name="i" arity="0"/>
+ <name name="ni" arity="0"/>
<fsummary>Information about the system</fsummary>
<desc>
<p><c>i/0</c> displays information about the system, listing
@@ -109,26 +99,20 @@ compile:file(File, Options ++ [report_errors, report_warnings])</code>
</desc>
</func>
<func>
- <name>i(X, Y, Z) -> void()</name>
+ <name name="i" arity="3"/>
<fsummary>Information about pid &lt;X.Y.Z&gt;</fsummary>
- <type>
- <v>X = Y = Z = int()</v>
- </type>
<desc>
<p>Displays information about a process, Equivalent to
- <c>process_info(pid(X, Y, Z))</c>, but location transparent.</p>
+ <c>process_info(pid(<anno>X</anno>, <anno>Y</anno>, <anno>Z</anno>))</c>, but location transparent.</p>
</desc>
</func>
<func>
- <name>l(Module) -> void()</name>
+ <name name="l" arity="1"/>
<fsummary>Load or reload module</fsummary>
- <type>
- <v>Module = atom()</v>
- </type>
<desc>
<p>Purges and loads, or reloads, a module by calling
- <c>code:purge(Module)</c> followed by
- <c>code:load_file(Module)</c>.</p>
+ <c>code:purge(<anno>Module</anno>)</c> followed by
+ <c>code:load_file(<anno>Module</anno>)</c>.</p>
<p>Note that purging the code means that any processes
lingering in old code for the module are killed without
warning. See <c>code/3</c> for more information.</p>
@@ -136,35 +120,33 @@ compile:file(File, Options ++ [report_errors, report_warnings])</code>
</func>
<func>
<name>lc(Files) -> ok</name>
- <fsummary>Compile a list of files</fsummary>
<type>
<v>Files = [File]</v>
- <v>&nbsp;File = name() -- see filename(3)</v>
+ <v>File = <seealso marker="file#type-filename">file:filename()
+ </seealso></v>
</type>
+ <fsummary>Compile a list of files</fsummary>
<desc>
<p>Compiles a list of files by calling <c>compile:file(File, [report_errors, report_warnings])</c> for each <c>File</c>
in <c>Files</c>.</p>
</desc>
</func>
<func>
- <name>ls() -> void()</name>
+ <name name="ls" arity="0"/>
<fsummary>List files in the current directory</fsummary>
<desc>
<p>Lists files in the current directory.</p>
</desc>
</func>
<func>
- <name>ls(Dir) -> void()</name>
+ <name name="ls" arity="1"/>
<fsummary>List files in a directory</fsummary>
- <type>
- <v>Dir = name() -- see filename(3)</v>
- </type>
<desc>
- <p>Lists files in directory <c>Dir</c>.</p>
+ <p>Lists files in directory <c><anno>Dir</anno></c>.</p>
</desc>
</func>
<func>
- <name>m() -> void()</name>
+ <name name="m" arity="0"/>
<fsummary>Which modules are loaded</fsummary>
<desc>
<p>Displays information about the loaded modules, including
@@ -172,84 +154,67 @@ compile:file(File, Options ++ [report_errors, report_warnings])</code>
</desc>
</func>
<func>
- <name>m(Module) -> void()</name>
+ <name name="m" arity="1"/>
<fsummary>Information about a module</fsummary>
- <type>
- <v>Module = atom()</v>
- </type>
<desc>
- <p>Displays information about <c>Module</c>.</p>
+ <p>Displays information about <c><anno>Module</anno></c>.</p>
</desc>
</func>
<func>
- <name>memory() -> [{Type, Size}]</name>
+ <name name="memory" arity="0"/>
<fsummary>Memory allocation information</fsummary>
- <type>
- <v>Type, Size -- see erlang:memory/0</v>
- </type>
<desc>
<p>Memory allocation information. Equivalent to
- <c>erlang:memory/0</c>.</p>
+ <seealso marker="erts:erlang#memory/0"><c>erlang:memory/0</c>
+ </seealso>.</p>
</desc>
</func>
<func>
- <name>memory(Type) -> Size</name>
- <name>memory([Type]) -> [{Type, Size}]</name>
+ <name name="memory" arity="1" clause_i="1"/>
+ <name name="memory" arity="1" clause_i="2"/>
<fsummary>Memory allocation information</fsummary>
- <type>
- <v>Type, Size -- see erlang:memory/0</v>
- </type>
<desc>
<p>Memory allocation information. Equivalent to
- <c>erlang:memory/1</c>.</p>
+ <seealso marker="erts:erlang#memory/1"><c>erlang:memory/1</c>
+ </seealso>.</p>
</desc>
</func>
<func>
- <name>nc(File) -> {ok, Module} | error</name>
- <name>nc(File, Options) -> {ok, Module} | error</name>
+ <name name="nc" arity="1"/>
+ <name name="nc" arity="2"/>
<fsummary>Compile and load code in a file on all nodes</fsummary>
- <type>
- <v>File = name() -- see filename(3)</v>
- <v>Options = [Opt] -- see compile:file/2</v>
- </type>
<desc>
<p>Compiles and then loads the code for a file on all nodes.
- <c>Options</c> defaults to []. Compilation is equivalent to:</p>
+ <c><anno>Options</anno></c> defaults to []. Compilation is equivalent to:</p>
<code type="none">
-compile:file(File, Opts ++ [report_errors, report_warnings])</code>
+compile:file(<anno>File</anno>, <anno>Options</anno> ++ [report_errors, report_warnings])</code>
</desc>
</func>
<func>
- <name>nl(Module) -> void()</name>
+ <name name="nl" arity="1"/>
<fsummary>Load module on all nodes</fsummary>
- <type>
- <v>Module = atom()</v>
- </type>
<desc>
- <p>Loads <c>Module</c> on all nodes.</p>
+ <p>Loads <c><anno>Module</anno></c> on all nodes.</p>
</desc>
</func>
<func>
- <name>pid(X, Y, Z) -> pid()</name>
+ <name name="pid" arity="3"/>
<fsummary>Convert X,Y,Z to a pid</fsummary>
- <type>
- <v>X = Y = Z = int()</v>
- </type>
<desc>
- <p>Converts <c>X</c>, <c>Y</c>, <c>Z</c> to the pid
+ <p>Converts <c><anno>X</anno></c>, <c><anno>Y</anno></c>, <c><anno>Z</anno></c> to the pid
<c><![CDATA[<X.Y.Z>]]></c>. This function should only be used when
debugging.</p>
</desc>
</func>
<func>
- <name>pwd() -> void()</name>
+ <name name="pwd" arity="0"/>
<fsummary>Print working directory</fsummary>
<desc>
<p>Prints the name of the working directory.</p>
</desc>
</func>
<func>
- <name>q() -> void()</name>
+ <name name="q" arity="0"/>
<fsummary>Quit - shorthand for <c>init:stop()</c></fsummary>
<desc>
<p>This function is shorthand for <c>init:stop()</c>, that is,
@@ -257,8 +222,8 @@ compile:file(File, Opts ++ [report_errors, report_warnings])</code>
</desc>
</func>
<func>
- <name>regs() -> void()</name>
- <name>nregs() -> void()</name>
+ <name name="regs" arity="0"/>
+ <name name="nregs" arity="0"/>
<fsummary>Information about registered processes</fsummary>
<desc>
<p><c>regs/0</c> displays information about all registered
diff --git a/lib/stdlib/doc/src/calendar.xml b/lib/stdlib/doc/src/calendar.xml
index 075c7f9c78..f8db48e00c 100644
--- a/lib/stdlib/doc/src/calendar.xml
+++ b/lib/stdlib/doc/src/calendar.xml
@@ -73,100 +73,120 @@
week number.</p>
</description>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-date() = {Year, Month, Day}
- Year = int()
- Month = 1..12
- Day = 1..31
-Year cannot be abbreviated. Example: 93 denotes year 93, not 1993.
-Valid range depends on the underlying OS.
-The date tuple must denote a valid date.
+ <datatypes>
+ <datatype>
+ <name name="datetime"/>
+ </datatype>
+ <datatype>
+ <name name="datetime1970"/>
+ </datatype>
+ <datatype>
+ <name name="date"/>
+ </datatype>
+ <datatype>
+ <name name="year"/>
+ <desc><p>Year cannot be abbreviated. Example: 93 denotes year
+ 93, not 1993. Valid range depends on the underlying OS. The
+ date tuple must denote a valid date.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="year1970"/>
+ </datatype>
+ <datatype>
+ <name name="month"/>
+ </datatype>
+ <datatype>
+ <name name="day"/>
+ </datatype>
+ <datatype>
+ <name name="time"/>
+ </datatype>
+ <datatype>
+ <name name="hour"/>
+ </datatype>
+ <datatype>
+ <name name="minute"/>
+ </datatype>
+ <datatype>
+ <name name="second"/>
+ </datatype>
+ <datatype>
+ <name name="daynum"/>
+ </datatype>
+ <datatype>
+ <name name="ldom"/>
+ </datatype>
+ <datatype>
+ <name name="yearweeknum"/>
+ </datatype>
+ <datatype>
+ <name name="weeknum"/>
+ </datatype>
+ </datatypes>
-time() = {Hour, Minute, Second}
- Hour = 0..23
- Minute = Second = 0..59</code>
- </section>
<funcs>
<func>
- <name>date_to_gregorian_days(Date) -> Days</name>
- <name>date_to_gregorian_days(Year, Month, Day) -> Days</name>
+ <name name="date_to_gregorian_days" arity="1"/>
+ <name name="date_to_gregorian_days" arity="3"/>
+ <type variable="Date" name_i="1"/>
+ <type variable="Year"/>
+ <type variable="Month"/>
+ <type variable="Day"/>
<fsummary>Compute the number of days from year 0 up to the given date</fsummary>
- <type>
- <v>Date = date()</v>
- <v>Days = int()</v>
- </type>
<desc>
<p>This function computes the number of gregorian days starting
with year 0 and ending at the given date.</p>
</desc>
</func>
<func>
- <name>datetime_to_gregorian_seconds({Date, Time}) -> Seconds</name>
+ <name name="datetime_to_gregorian_seconds" arity="1"/>
<fsummary>Compute the number of seconds from year 0 up to the given date and time</fsummary>
- <type>
- <v>Date = date()</v>
- <v>Time = time()</v>
- <v>Seconds = int()</v>
- </type>
<desc>
<p>This function computes the number of gregorian seconds
starting with year 0 and ending at the given date and time.</p>
</desc>
</func>
<func>
- <name>day_of_the_week(Date) -> DayNumber</name>
- <name>day_of_the_week(Year, Month, Day) -> DayNumber</name>
+ <name name="day_of_the_week" arity="1"/>
+ <name name="day_of_the_week" arity="3"/>
<fsummary>Compute the day of the week</fsummary>
- <type>
- <v>Date = date()</v>
- <v>DayNumber = 1..7</v>
- </type>
+ <type variable="Date" name_i="1"/>
+ <type variable="Year"/>
+ <type variable="Month"/>
+ <type variable="Day"/>
<desc>
- <p>This function computes the day of the week given <c>Year</c>,
- <c>Month</c> and <c>Day</c>. The return value denotes the day
+ <p>This function computes the day of the week given <c><anno>Year</anno></c>,
+ <c><anno>Month</anno></c> and <c><anno>Day</anno></c>. The return value denotes the day
of the week as <c>1</c>: Monday, <c>2</c>: Tuesday, and so on.</p>
</desc>
</func>
<func>
- <name>gregorian_days_to_date(Days) -> Date</name>
+ <name name="gregorian_days_to_date" arity="1"/>
<fsummary>Compute the date given the number of gregorian days</fsummary>
- <type>
- <v>Days = int()</v>
- <v>Date = date()</v>
- </type>
<desc>
<p>This function computes the date given the number of
gregorian days.</p>
</desc>
</func>
<func>
- <name>gregorian_seconds_to_datetime(Seconds) -> {Date, Time}</name>
+ <name name="gregorian_seconds_to_datetime" arity="1"/>
<fsummary>Compute the date given the number of gregorian days</fsummary>
- <type>
- <v>Seconds = int()</v>
- <v>Date = date()</v>
- <v>Time = time()</v>
- </type>
<desc>
<p>This function computes the date and time from the given
number of gregorian seconds.</p>
</desc>
</func>
<func>
- <name>is_leap_year(Year) -> bool()</name>
+ <name name="is_leap_year" arity="1"/>
<fsummary>Check if a year is a leap year</fsummary>
<desc>
<p>This function checks if a year is a leap year.</p>
</desc>
</func>
<func>
- <name>iso_week_number() -> IsoWeekNumber</name>
+ <name name="iso_week_number" arity="0"/>
<fsummary>Compute the iso week number for the actual date</fsummary>
- <type>
- <v>IsoWeekNumber = {int(), int()}</v>
- </type>
<desc>
<p>This function returns the tuple {Year, WeekNum} representing
the iso week number for the actual date. For determining the
@@ -174,42 +194,34 @@ time() = {Hour, Minute, Second}
</desc>
</func>
<func>
- <name>iso_week_number(Date) -> IsoWeekNumber</name>
+ <name name="iso_week_number" arity="1"/>
<fsummary>Compute the iso week number for the given date</fsummary>
- <type>
- <v>Date = date()</v>
- <v>IsoWeekNumber = {int(), int()}</v>
- </type>
<desc>
<p>This function returns the tuple {Year, WeekNum} representing
the iso week number for the given date.</p>
</desc>
</func>
<func>
- <name>last_day_of_the_month(Year, Month) -> int()</name>
+ <name name="last_day_of_the_month" arity="2"/>
<fsummary>Compute the number of days in a month</fsummary>
<desc>
<p>This function computes the number of days in a month.</p>
</desc>
</func>
<func>
- <name>local_time() -> {Date, Time}</name>
+ <name name="local_time" arity="0"/>
<fsummary>Compute local time</fsummary>
- <type>
- <v>Date = date()</v>
- <v>Time = time()</v>
- </type>
<desc>
<p>This function returns the local time reported by
the underlying operating system.</p>
</desc>
</func>
<func>
- <name>local_time_to_universal_time({Date1, Time1}) -> {Date2, Time2}</name>
+ <name name="local_time_to_universal_time" arity="1"/>
<fsummary>Convert from local time to universal time (deprecated)</fsummary>
<desc>
<p>This function converts from local time to Universal
- Coordinated Time (UTC). <c>Date1</c> must refer to a local
+ Coordinated Time (UTC). <c><anno>DateTime1</anno></c> must refer to a local
date after Jan 1, 1970.</p>
<warning>
<p>This function is deprecated. Use
@@ -222,15 +234,11 @@ time() = {Hour, Minute, Second}
</desc>
</func>
<func>
- <name>local_time_to_universal_time_dst({Date1, Time1}) -> [{Date, Time}]</name>
+ <name name="local_time_to_universal_time_dst" arity="1"/>
<fsummary>Convert from local time to universal time(s)</fsummary>
- <type>
- <v>Date1 = Date = date()</v>
- <v>Time1 = Time = time()</v>
- </type>
<desc>
<p>This function converts from local time to Universal
- Coordinated Time (UTC). <c>Date1</c> must refer to a local
+ Coordinated Time (UTC). <c><anno>DateTime1</anno></c> must refer to a local
date after Jan 1, 1970.</p>
<p>The return value is a list of 0, 1 or 2 possible UTC times:</p>
<taglist>
@@ -258,65 +266,48 @@ time() = {Hour, Minute, Second}
</desc>
</func>
<func>
- <name>now_to_local_time(Now) -> {Date, Time}</name>
+ <name name="now_to_local_time" arity="1"/>
<fsummary>Convert now to local date and time</fsummary>
- <type>
- <v>Now -- see erlang:now/0</v>
- <v>Date = date()</v>
- <v>Time = time()</v>
- </type>
<desc>
<p>This function returns local date and time converted from
the return value from <c>erlang:now()</c>.</p>
</desc>
</func>
<func>
- <name>now_to_universal_time(Now) -> {Date, Time}</name>
- <name>now_to_datetime(Now) -> {Date, Time}</name>
+ <name name="now_to_universal_time" arity="1"/>
+ <name name="now_to_datetime" arity="1"/>
<fsummary>Convert now to date and time</fsummary>
- <type>
- <v>Now -- see erlang:now/0</v>
- <v>Date = date()</v>
- <v>Time = time()</v>
- </type>
<desc>
<p>This function returns Universal Coordinated Time (UTC)
converted from the return value from <c>erlang:now()</c>.</p>
</desc>
</func>
<func>
- <name>seconds_to_daystime(Seconds) -> {Days, Time}</name>
+ <name name="seconds_to_daystime" arity="1"/>
<fsummary>Compute days and time from seconds</fsummary>
- <type>
- <v>Seconds = Days = int()</v>
- <v>Time = time()</v>
- </type>
<desc>
<p>This function transforms a given number of seconds into days,
- hours, minutes, and seconds. The <c>Time</c> part is always
- non-negative, but <c>Days</c> is negative if the argument
- <c>Seconds</c> is.</p>
+ hours, minutes, and seconds. The <c><anno>Time</anno></c> part is always
+ non-negative, but <c><anno>Days</anno></c> is negative if the argument
+ <c><anno>Seconds</anno></c> is.</p>
</desc>
</func>
<func>
- <name>seconds_to_time(Seconds) -> Time</name>
+ <name name="seconds_to_time" arity="1"/>
<fsummary>Compute time from seconds</fsummary>
- <type>
- <v>Seconds = int() &lt; 86400</v>
- <v>Time = time()</v>
- </type>
+ <type name="secs_per_day"/>
<desc>
<p>This function computes the time from the given number of
- seconds. <c>Seconds</c> must be less than the number of
+ seconds. <c><anno>Seconds</anno></c> must be less than the number of
seconds per day (86400).</p>
</desc>
</func>
<func>
- <name>time_difference(T1, T2) -> {Days, Time}</name>
+ <name name="time_difference" arity="2"/>
<fsummary>Compute the difference between two times (deprecated)</fsummary>
<desc>
- <p>This function returns the difference between two <c>{Date, Time}</c> tuples. <c>T2</c> should refer to an epoch later
- than <c>T1</c>.</p>
+ <p>This function returns the difference between two <c>{Date, Time}</c> tuples. <c><anno>T2</anno></c> should refer to an epoch later
+ than <c><anno>T1</anno></c>.</p>
<warning>
<p>This function is obsolete. Use the conversion functions for
gregorian days and seconds instead.</p>
@@ -324,24 +315,17 @@ time() = {Hour, Minute, Second}
</desc>
</func>
<func>
- <name>time_to_seconds(Time) -> Seconds</name>
+ <name name="time_to_seconds" arity="1"/>
<fsummary>Compute the number of seconds since midnight up to the given time</fsummary>
- <type>
- <v>Time = time()</v>
- <v>Seconds = int()</v>
- </type>
+ <type name="secs_per_day"/>
<desc>
<p>This function computes the number of seconds since midnight
up to the specified time.</p>
</desc>
</func>
<func>
- <name>universal_time() -> {Date, Time}</name>
+ <name name="universal_time" arity="0"/>
<fsummary>Compute universal time</fsummary>
- <type>
- <v>Date = date()</v>
- <v>Time = time()</v>
- </type>
<desc>
<p>This function returns the Universal Coordinated Time (UTC)
reported by the underlying operating system. Local time is
@@ -349,25 +333,22 @@ time() = {Hour, Minute, Second}
</desc>
</func>
<func>
- <name>universal_time_to_local_time({Date1, Time1}) -> {Date2, Time2}</name>
+ <name name="universal_time_to_local_time" arity="1"/>
<fsummary>Convert from universal time to local time</fsummary>
- <type>
- <v>Date1 = Date2 = date()</v>
- <v>Time1 = Time2 = time()</v>
- </type>
<desc>
<p>This function converts from Universal Coordinated Time (UTC)
- to local time. <c>Date1</c> must refer to a date after Jan 1,
+ to local time. <c><anno>DateTime</anno></c> must refer to a date after Jan 1,
1970.</p>
</desc>
</func>
<func>
- <name>valid_date(Date) -> bool()</name>
- <name>valid_date(Year, Month, Day) -> bool()</name>
+ <name name="valid_date" arity="1"/>
+ <name name="valid_date" arity="3"/>
+ <type variable="Date" name_i="1"/>
+ <type variable="Year"/>
+ <type variable="Month"/>
+ <type variable="Day"/>
<fsummary>Check if a date is valid</fsummary>
- <type>
- <v>Date = date()</v>
- </type>
<desc>
<p>This function checks if a date is a valid.</p>
</desc>
diff --git a/lib/stdlib/doc/src/dets.xml b/lib/stdlib/doc/src/dets.xml
index b002af6616..215ec154ed 100644
--- a/lib/stdlib/doc/src/dets.xml
+++ b/lib/stdlib/doc/src/dets.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2010</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -100,50 +100,99 @@
the process with the error tuple). If given badly formed
arguments, all functions exit the process with a <c>badarg</c>
message.</p>
- <p><em>Types</em></p>
- <pre>
-access() = read | read_write
-auto_save() = infinity | int()
-bindings_cont() = tuple()
-bool() = true | false
-file() = string()
-int() = integer() >= 0
-keypos() = integer() >= 1
-name() = atom() | reference()
-no_slots() = integer() >= 0 | default
-object() = tuple()
-object_cont() = tuple()
-select_cont() = tuple()
-type() = bag | duplicate_bag | set
-version() = 8 | 9 | default </pre>
</description>
+ <datatypes>
+ <datatype>
+ <name name="access"/>
+ </datatype>
+ <datatype>
+ <name name="auto_save"/>
+ </datatype>
+ <datatype>
+ <name name="bindings_cont"/>
+ <desc>
+ <p>Opaque continuation used by <seealso marker="#match/1">
+ <c>match/1</c></seealso> and <seealso marker="#match/3">
+ <c>match/3</c></seealso>.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="cont"/>
+ <desc>
+ <p>Opaque continuation used by <seealso marker="#bchunk/2">
+ <c>bchunk/2</c></seealso>.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="keypos"/>
+ </datatype>
+ <datatype>
+ <name name="match_spec"/>
+ <desc>
+ <p>Match&nbsp;specifications, see the <seealso
+ marker="erts:match_spec">match specification</seealso>
+ documentation in the ERTS User's Guide and <seealso
+ marker="ms_transform">ms_transform(3).</seealso></p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="no_slots"/>
+ </datatype>
+ <datatype>
+ <name name="object"/>
+ </datatype>
+ <datatype>
+ <name name="object_cont"/>
+ <desc>
+ <p>Opaque continuation used by <seealso marker="#match_object/1">
+ <c>match_object/1</c></seealso> and <seealso marker="#match_object/3">
+ <c>match_object/3</c></seealso>.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="pattern"/>
+ <desc>
+ <p>See <seealso marker="ets#match/2">ets:match/2</seealso> for a
+ description of patterns.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="select_cont"/>
+ <desc>
+ <p>Opaque continuation used by <seealso marker="#select/1">
+ <c>select/1</c></seealso> and <seealso marker="#select/3">
+ <c>select/3</c></seealso>.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="tab_name"/>
+ </datatype>
+ <datatype>
+ <name name="type"/>
+ </datatype>
+ <datatype>
+ <name name="version"/>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>all() -> [Name]</name>
+ <name name="all" arity="0"/>
<fsummary>Return a list of the names of all open Dets tables on this node.</fsummary>
- <type>
- <v>Name = name()</v>
- </type>
<desc>
<p>Returns a list of the names of all open tables on this
node.</p>
</desc>
</func>
<func>
- <name>bchunk(Name, Continuation) -> {Continuation2, Data} | '$end_of_table' | {error, Reason}</name>
+ <name name="bchunk" arity="2"/>
<fsummary>Return a chunk of objects stored in a Dets table.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>Continuation = start | cont()</v>
- <v>Continuation2 = cont()</v>
- <v>Data = binary() | tuple()</v>
- </type>
<desc>
<p>Returns a list of objects stored in a table. The exact
representation of the returned objects is not public. The
lists of data can be used for initializing a table by giving
the value <c>bchunk</c> to the <c>format</c> option of the
- <c>init_table/3</c> function. The Mnesia application uses this
+ <seealso marker="#init_table/3"><c>init_table/3</c></seealso>
+ function. The Mnesia application uses this
function for copying open tables.</p>
<p>Unless the table is protected using <c>safe_fixtable/2</c>,
calls to <c>bchunk/2</c> may not work as expected if
@@ -151,24 +200,23 @@ version() = 8 | 9 | default </pre>
<p>The first time <c>bchunk/2</c> is called, an initial
continuation, the atom <c>start</c>, must be provided.</p>
<p>The <c>bchunk/2</c> function returns a tuple
- <c>{Continuation2, Data}</c>, where <c>Data</c> is a list of
- objects. <c>Continuation2</c> is another continuation which is
+ <c>{<anno>Continuation2</anno>, <anno>Data</anno>}</c>,
+ where <c><anno>Data</anno></c> is a list of
+ objects. <c><anno>Continuation2</anno></c> is another continuation
+ which is
to be passed on to a subsequent call to <c>bchunk/2</c>. With
a series of calls to <c>bchunk/2</c> it is possible to extract
all objects of the table.
</p>
<p><c>bchunk/2</c> returns <c>'$end_of_table'</c> when all
- objects have been returned, or <c>{error, Reason}</c> if an
- error occurs.
+ objects have been returned, or <c>{error, <anno>Reason</anno>}</c>
+ if an error occurs.
</p>
</desc>
</func>
<func>
- <name>close(Name) -> ok | {error, Reason} </name>
+ <name name="close" arity="1"/>
<fsummary>Close a Dets table.</fsummary>
- <type>
- <v>Name = name()</v>
- </type>
<desc>
<p>Closes a table. Only processes that have opened a table are
allowed to close it.
@@ -180,22 +228,16 @@ version() = 8 | 9 | default </pre>
</desc>
</func>
<func>
- <name>delete(Name, Key) -> ok | {error, Reason}</name>
+ <name name="delete" arity="2"/>
<fsummary>Delete all objects with a given key from a Dets table.</fsummary>
- <type>
- <v>Name = name()</v>
- </type>
<desc>
- <p>Deletes all objects with the key <c>Key</c> from the table
- <c>Name</c>.</p>
+ <p>Deletes all objects with the key <c><anno>Key</anno></c> from
+ the table <c><anno>Name</anno></c>.</p>
</desc>
</func>
<func>
- <name>delete_all_objects(Name) -> ok | {error, Reason}</name>
+ <name name="delete_all_objects" arity="1"/>
<fsummary>Delete all objects from a Dets table.</fsummary>
- <type>
- <v>Name = name()</v>
- </type>
<desc>
<p>Deletes all objects from a table in almost constant time.
However, if the table if fixed, <c>delete_all_objects(T)</c>
@@ -203,12 +245,8 @@ version() = 8 | 9 | default </pre>
</desc>
</func>
<func>
- <name>delete_object(Name, Object) -> ok | {error, Reason}</name>
+ <name name="delete_object" arity="2"/>
<fsummary>Delete a given object from a Dets table.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>Object = object()</v>
- </type>
<desc>
<p>Deletes all instances of a given object from a table. If a
table is of type <c>bag</c> or <c>duplicate_bag</c>, the
@@ -218,18 +256,15 @@ version() = 8 | 9 | default </pre>
</desc>
</func>
<func>
- <name>first(Name) -> Key | '$end_of_table'</name>
+ <name name="first" arity="1"/>
<fsummary>Return the first key stored in a Dets table.</fsummary>
- <type>
- <v>Key = term()</v>
- <v>Name = name()</v>
- </type>
<desc>
- <p>Returns the first key stored in the table <c>Name</c>
+ <p>Returns the first key stored in the table <c><anno>Name</anno></c>
according to the table's internal order, or
<c>'$end_of_table'</c> if the table is empty.</p>
<p>Unless the table is protected using <c>safe_fixtable/2</c>,
- subsequent calls to <c>next/2</c> may not work as expected if
+ subsequent calls to <seealso marker="#next/2"><c>next/2</c></seealso>
+ may not work as expected if
concurrent updates are made to the table.</p>
<p>Should an error occur, the process is exited with an error
tuple <c>{error, Reason}</c>. The reason for not returning the
@@ -243,107 +278,78 @@ version() = 8 | 9 | default </pre>
</desc>
</func>
<func>
- <name>foldl(Function, Acc0, Name) -> Acc1 | {error, Reason}</name>
- <fsummary>Fold a function over a Dets table.</fsummary>
- <type>
- <v>Function = fun(Object, AccIn) -> AccOut</v>
- <v>Acc0 = Acc1 = AccIn = AccOut = term()</v>
- <v>Name = name()</v>
- <v>Object = object()</v>
- </type>
- <desc>
- <p>Calls <c>Function</c> on successive elements of the table
- <c>Name</c> together with an extra argument <c>AccIn</c>. The
- order in which the elements of the table are traversed is
- unspecified. <c>Function</c> must return a new accumulator
- which is passed to the next call. <c>Acc0</c> is returned if
- the table is empty.</p>
- </desc>
- </func>
- <func>
- <name>foldr(Function, Acc0, Name) -> Acc1 | {error, Reason}</name>
+ <name name="foldl" arity="3"/>
+ <name name="foldr" arity="3"/>
<fsummary>Fold a function over a Dets table.</fsummary>
- <type>
- <v>Function = fun(Object, AccIn) -> AccOut</v>
- <v>Acc0 = Acc1 = AccIn = AccOut = term()</v>
- <v>Name = name()</v>
- <v>Object = object()</v>
- </type>
<desc>
- <p>Calls <c>Function</c> on successive elements of the table
- <c>Name</c> together with an extra argument <c>AccIn</c>. The
+ <p>Calls <c><anno>Function</anno></c> on successive elements of
+ the table <c><anno>Name</anno></c> together with an extra argument
+ <c>AccIn</c>. The
order in which the elements of the table are traversed is
- unspecified. <c>Function</c> must return a new accumulator
- which is passed to the next call. <c>Acc0</c> is returned if
+ unspecified. <c><anno>Function</anno></c> must return a new
+ accumulator which is passed to the next call.
+ <c><anno>Acc0</anno></c> is returned if
the table is empty.</p>
</desc>
</func>
<func>
- <name>from_ets(Name, EtsTab) -> ok | {error, Reason}</name>
+ <name name="from_ets" arity="2"/>
<fsummary>Replace the objects of a Dets table with the objects of an Ets table.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>EtsTab = -&nbsp;see ets(3)&nbsp;-</v>
- </type>
<desc>
- <p>Deletes all objects of the table <c>Name</c> and then
- inserts all the objects of the Ets table <c>EtsTab</c>. The
- order in which the objects are inserted is not specified.
+ <p>Deletes all objects of the table <c><anno>Name</anno></c> and then
+ inserts all the objects of the Ets table <c><anno>EtsTab</anno></c>.
+ The order in which the objects are inserted is not specified.
Since <c>ets:safe_fixtable/2</c> is called the Ets table must
be public or owned by the calling process.</p>
</desc>
</func>
<func>
- <name>info(Name) -> InfoList | undefined</name>
+ <name name="info" arity="1"/>
<fsummary>Return information about a Dets table.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>InfoList = [{Item, Value}]</v>
- </type>
<desc>
- <p>Returns information about the table <c>Name</c> as a list of
- <c>{Item, Value}</c> tuples:</p>
+ <p>Returns information about the table <c><anno>Name</anno></c>
+ as a list of tuples:</p>
<list type="bulleted">
<item>
- <p><c>{file_size, int()}</c>, the size of the file in
+ <p><c>{file_size, integer() >= 0}</c>, the size of the file in
bytes.</p>
</item>
<item>
- <p><c>{filename, file()}</c>, the name of the file
- where objects are stored.</p>
+ <p><c>{filename, <seealso marker="file#type-name">file:name()</seealso>}</c>,
+ the name of the file where objects are stored.</p>
</item>
<item>
- <p><c>{keypos, keypos()}</c>, the position of the
- key.</p>
+ <p><c>{keypos, <seealso marker="#type-keypos">keypos()</seealso>}
+ </c>, the position of the key.</p>
</item>
<item>
- <p><c>{size, int()}</c>, the number of objects stored
+ <p><c>{size, integer() >= 0}</c>, the number of objects stored
in the table.</p>
</item>
<item>
- <p><c>{type, type()}</c>, the type of the table.</p>
+ <p><c>{type, <seealso marker="#type-type">type()</seealso>}</c>,
+ the type of the table.</p>
</item>
</list>
</desc>
</func>
<func>
- <name>info(Name, Item) -> Value | undefined</name>
+ <name name="info" arity="2"/>
<fsummary>Return the information associated with a given item for a Dets table.</fsummary>
- <type>
- <v>Name = name()</v>
- </type>
<desc>
- <p>Returns the information associated with <c>Item</c> for the
- table <c>Name</c>. In addition to the <c>{Item, Value}</c>
+ <p>Returns the information associated with <c><anno>Item</anno></c>
+ for the table <c><anno>Name</anno></c>.
+ In addition to the <c>{<anno>Item</anno>, <anno>Value</anno>}</c>
pairs defined for <c>info/1</c>, the following items are
allowed:</p>
<list type="bulleted">
<item>
- <p><c>{access, access()}</c>, the access mode.</p>
+ <p><c>{access, <seealso marker="#type-access">access()</seealso>}
+ </c>, the access mode.</p>
</item>
<item>
- <p><c>{auto_save, auto_save()}</c>, the auto save
- interval.</p>
+ <p><c>{auto_save, <seealso marker="#type-auto_save">
+ auto_save()</seealso>}</c>, the auto save interval.</p>
</item>
<item>
<p><c>{bchunk_format, binary()}</c>, an opaque binary
@@ -362,21 +368,22 @@ version() = 8 | 9 | default </pre>
<c>erlang:phash2/1</c> BIF is used.</p>
</item>
<item>
- <p><c>{memory, int()}</c>, the size of the file in
+ <p><c>{memory, integer() >= 0}</c>, the size of the file in
bytes. The same value is associated with the item
<c>file_size</c>.</p>
</item>
<item>
- <p><c>{no_keys, int()}</c>, the number of different
+ <p><c>{no_keys, integer >= 0()}</c>, the number of different
keys stored in the table. Only available for version 9
tables.</p>
</item>
<item>
- <p><c>{no_objects, int()}</c>, the number of objects
+ <p><c>{no_objects, integer >= 0()}</c>, the number of objects
stored in the table.</p>
</item>
<item>
- <p><c>{no_slots, {Min, Used, Max}}</c>, the number of
+ <p><c>{no_slots, {</c>Min<c>, </c>Used<c>, </c>Max<c>}}</c>,
+ the number of
slots of the table. <c>Min</c> is the minimum number of
slots, <c>Used</c> is the number of currently used slots,
and <c>Max</c> is the maximum number of slots. Only
@@ -387,7 +394,7 @@ version() = 8 | 9 | default </pre>
handles requests to the Dets table.</p>
</item>
<item>
- <p><c>{ram_file, bool()}</c>, whether the table is
+ <p><c>{ram_file, boolean()}</c>, whether the table is
kept in RAM.</p>
</item>
<item>
@@ -399,32 +406,28 @@ version() = 8 | 9 | default </pre>
table is not fixed, SafeFixed is the atom <c>false</c>.</p>
</item>
<item>
- <p><c>{version, int()}</c>, the version of the format
- of the table.</p>
+ <p><c>{version, integer()</c>, the version of the format of
+ the table.</p>
</item>
</list>
</desc>
</func>
<func>
- <name>init_table(Name, InitFun [, Options]) -> ok | {error, Reason}</name>
+ <name name="init_table" arity="2"/>
+ <name name="init_table" arity="3"/>
<fsummary>Replace all objects of a Dets table.</fsummary>
- <type>
- <v>Name = atom()</v>
- <v>InitFun = fun(Arg) -> Res</v>
- <v>Arg = read | close</v>
- <v>Res = end_of_input | {[object()], InitFun} | {Data, InitFun} | term()</v>
- <v>Data = binary() | tuple()</v>
- </type>
<desc>
- <p>Replaces the existing objects of the table <c>Name</c> with
- objects created by calling the input function <c>InitFun</c>,
+ <p>Replaces the existing objects of the table <c><anno>Name</anno></c>
+ with objects created by calling the input function
+ <c><anno>InitFun</anno></c>,
see below. The reason for using this function rather than
calling <c>insert/2</c> is that of efficiency. It should be
noted that the input functions are called by the process that
handles requests to the Dets table, not by the calling
process.</p>
<p>When called with the argument <c>read</c> the function
- <c>InitFun</c> is assumed to return <c>end_of_input</c> when
+ <c><anno>InitFun</anno></c> is assumed to return
+ <c>end_of_input</c> when
there is no more input, or <c>{Objects, Fun}</c>, where
<c>Objects</c> is a list of objects and <c>Fun</c> is a new
input function. Any other value Value is returned as an error
@@ -448,7 +451,8 @@ version() = 8 | 9 | default </pre>
item <c>no_slots</c>. See also the <c>min_no_slots</c> option
below.
</p>
- <p>The <c>Options</c> argument is a list of <c>{Key, Val}</c>
+ <p>The <c><anno>Options</anno></c> argument is a list of
+ <c>{Key, Val}</c>
tuples where the following values are allowed:</p>
<list type="bulleted">
<item>
@@ -461,87 +465,68 @@ version() = 8 | 9 | default </pre>
</item>
<item>
<p><c>{format, Format}</c>. Specifies the format of the
- objects returned by the function <c>InitFun</c>. If
+ objects returned by the function <c><anno>InitFun</anno></c>. If
<c>Format</c> is <c>term</c> (the default),
- <c>InitFun</c> is assumed to return a list of tuples. If
- <c>Format</c> is <c>bchunk</c>, <c>InitFun</c> is
- assumed to return <c>Data</c> as returned by
- <c>bchunk/2</c>. This option overrides the
+ <c><anno>InitFun</anno></c> is assumed to return a list of tuples. If
+ <c>Format</c> is <c>bchunk</c>, <c><anno>InitFun</anno></c> is
+ assumed to return <c><anno>Data</anno></c> as returned by
+ <seealso marker="#bchunk/2"><c>bchunk/2</c></seealso>.
+ This option overrides the
<c>min_no_slots</c> option.</p>
</item>
</list>
</desc>
</func>
<func>
- <name>insert(Name, Objects) -> ok | {error, Reason}</name>
+ <name name="insert" arity="2"/>
<fsummary>Insert one or more objects into a Dets table.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>Objects = object() | [object()]</v>
- </type>
<desc>
- <p>Inserts one or more objects into the table <c>Name</c>. If
- there already exists an object with a key matching the key of
+ <p>Inserts one or more objects into the table <c><anno>Name</anno></c>.
+ If there already exists an object with a key matching the key of
some of the given objects and the table type is <c>set</c>,
the old object will be replaced.</p>
</desc>
</func>
<func>
- <name>insert_new(Name, Objects) -> Bool</name>
+ <name name="insert_new" arity="2"/>
<fsummary>Insert one or more objects into a Dets table.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>Objects = object() | [object()]</v>
- <v>Bool = bool()</v>
- </type>
<desc>
- <p>Inserts one or more objects into the table <c>Name</c>. If
- there already exists some object with a key matching the key
+ <p>Inserts one or more objects into the table <c><anno>Name</anno></c>.
+ If there already exists some object with a key matching the key
of any of the given objects the table is not updated and
<c>false</c> is returned, otherwise the objects are inserted
and <c>true</c> returned.</p>
</desc>
</func>
<func>
- <name>is_compatible_bchunk_format(Name, BchunkFormat) -> Bool</name>
+ <name name="is_compatible_bchunk_format" arity="2"/>
<fsummary>Test compatibility of a table's chunk data.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>BchunkFormat = binary()</v>
- <v>Bool = bool()</v>
- </type>
<desc>
<p>Returns <c>true</c> if it would be possible to initialize
- the table <c>Name</c>, using <c>init_table/3</c> with the
+ the table <c><anno>Name</anno></c>, using
+ <seealso marker="#init_table/3"><c>init_table/3</c></seealso>
+ with the
option <c>{format,&nbsp;bchunk}</c>, with objects read with
- <c>bchunk/2</c> from some table <c>T</c> such that calling
+ <seealso marker="#bchunk/2"><c>bchunk/2</c></seealso> from some
+ table <c>T</c> such that calling
<c>info(T,&nbsp;bchunk_format)</c> returns
<c>BchunkFormat</c>.</p>
</desc>
</func>
<func>
- <name>is_dets_file(FileName) -> Bool | {error, Reason}</name>
+ <name name="is_dets_file" arity="1"/>
<fsummary>Test for a Dets table.</fsummary>
- <type>
- <v>FileName = file()</v>
- <v>Bool = bool()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if the file <c>FileName</c> is a Dets
- table, <c>false</c> otherwise.</p>
+ <p>Returns <c>true</c> if the file <c><anno>Filename</anno></c>
+ is a Dets table, <c>false</c> otherwise.</p>
</desc>
</func>
<func>
- <name>lookup(Name, Key) -> [Object] | {error, Reason}</name>
+ <name name="lookup" arity="2"/>
<fsummary>Return all objects with a given key stored in a Dets table.</fsummary>
- <type>
- <v>Key = term()</v>
- <v>Name = name()</v>
- <v>Object = object()</v>
- </type>
<desc>
- <p>Returns a list of all objects with the key <c>Key</c>
- stored in the table <c>Name</c>. For example:</p>
+ <p>Returns a list of all objects with the key <c><anno>Key</anno></c>
+ stored in the table <c><anno>Name</anno></c>. For example:</p>
<pre>
2> <input>dets:open_file(abc, [{type, bag}]).</input>
{ok,abc}
@@ -562,71 +547,57 @@ ok
</desc>
</func>
<func>
- <name>match(Continuation) -> {[Match], Continuation2} | '$end_of_table' | {error, Reason}</name>
+ <name name="match" arity="1"/>
<fsummary>Match a chunk of objects stored in a Dets table and return a list of variable bindings.</fsummary>
- <type>
- <v>Continuation = Continuation2 = bindings_cont()</v>
- <v>Match = [term()]</v>
- </type>
<desc>
<p>Matches some objects stored in a table and returns a
non-empty list of the bindings that match a given pattern in
some unspecified order. The table, the pattern, and the number
of objects that are matched are all defined by
- <c>Continuation</c>, which has been returned by a prior call
- to <c>match/1</c> or <c>match/3</c>.</p>
+ <c><anno>Continuation</anno></c>, which has been returned by a prior
+ call to <c>match/1</c> or <c>match/3</c>.</p>
<p>When all objects of the table have been matched,
<c>'$end_of_table'</c> is returned.</p>
</desc>
</func>
<func>
- <name>match(Name, Pattern) -> [Match] | {error, Reason}</name>
+ <name name="match" arity="2"/>
<fsummary>Match the objects stored in a Dets table and return a list of variable bindings.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>Pattern = tuple()</v>
- <v>Match = [term()]</v>
- </type>
<desc>
- <p>Returns for each object of the table <c>Name</c> that
- matches <c>Pattern</c> a list of bindings in some unspecified
- order. See <seealso marker="ets">ets(3)</seealso> for a
+ <p>Returns for each object of the table <c><anno>Name</anno></c> that
+ matches <c><anno>Pattern</anno></c> a list of bindings in some unspecified
+ order. See <seealso marker="ets#match/2">ets:match/2</seealso> for a
description of patterns. If the keypos'th element of
- <c>Pattern</c> is unbound, all objects of the table are
+ <c><anno>Pattern</anno></c> is unbound, all objects of the table are
matched. If the keypos'th element is bound, only the
objects with the right key are matched.</p>
</desc>
</func>
<func>
- <name>match(Name, Pattern, N) -> {[Match], Continuation} | '$end_of_table' | {error, Reason}</name>
+ <name name="match" arity="3"/>
<fsummary>Match the first chunk of objects stored in a Dets table and return a list of variable bindings.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>Pattern = tuple()</v>
- <v>N = default | int()</v>
- <v>Match = [term()]</v>
- <v>Continuation = bindings_cont()</v>
- </type>
<desc>
- <p>Matches some or all objects of the table <c>Name</c> and
+ <p>Matches some or all objects of the table <c><anno>Name</anno></c> and
returns a non-empty list of the bindings that match
- <c>Pattern</c> in some unspecified order. See <seealso marker="ets">ets(3)</seealso> for a description of
- patterns.</p>
+ <c><anno>Pattern</anno></c> in some unspecified order.
+ See <seealso marker="ets#match/2">ets:match/2</seealso> for a
+ description of patterns.</p>
<p>A tuple of the bindings and a continuation is returned,
unless the table is empty, in which case
<c>'$end_of_table'</c> is returned. The continuation is to be
used when matching further objects by calling
- <c>match/1</c>.</p>
- <p>If the keypos'th element of <c>Pattern</c> is bound, all
- objects of the table are matched. If the keypos'th element is
- unbound, all objects of the table are matched, <c>N</c>
+ <seealso marker="#match/1"><c>match/1</c></seealso>.</p>
+ <p>If the keypos'th element of <c><anno>Pattern</anno></c> is bound,
+ all objects of the table are matched. If the keypos'th element is
+ unbound, all objects of the table are matched, <c><anno>N</anno></c>
objects at a time, until at least one object matches or the
end of the table has been reached. The default, indicated by
- giving <c>N</c> the value <c>default</c>, is to let the number
+ giving <c><anno>N</anno></c> the value <c>default</c>,
+ is to let the number
of objects vary depending on the sizes of the objects. If
- <c>Name</c> is a version 9 table, all objects with the same
+ <c><anno>Name</anno></c> is a version 9 table, all objects with the same
key are always matched at the same time which implies that
- more than N objects may sometimes be matched.
+ more than <anno>N</anno> objects may sometimes be matched.
</p>
<p>The table should always be protected using
<c>safe_fixtable/2</c> before calling <c>match/3</c>, or
@@ -634,15 +605,11 @@ ok
</desc>
</func>
<func>
- <name>match_delete(Name, Pattern) -> ok | {error, Reason}</name>
+ <name name="match_delete" arity="2"/>
<fsummary>Delete all objects that match a given pattern from a Dets table.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>Pattern = tuple()</v>
- </type>
<desc>
- <p>Deletes all objects that match <c>Pattern</c> from the
- table <c>Name</c>.
+ <p>Deletes all objects that match <c><anno>Pattern</anno></c> from the
+ table <c><anno>Name</anno></c>.
See <seealso marker="ets#match/2">ets:match/2</seealso> for a
description of patterns.</p>
<p>If the keypos'th element of <c>Pattern</c> is bound,
@@ -650,17 +617,13 @@ ok
</desc>
</func>
<func>
- <name>match_object(Continuation) -> {[Object], Continuation2} | '$end_of_table' | {error, Reason}</name>
+ <name name="match_object" arity="1"/>
<fsummary>Match a chunk of objects stored in a Dets table and return a list of objects.</fsummary>
- <type>
- <v>Continuation = Continuation2 = object_cont()</v>
- <v>Object = object()</v>
- </type>
<desc>
<p>Returns a non-empty list of some objects stored in a table
that match a given pattern in some unspecified order. The
table, the pattern, and the number of objects that are matched
- are all defined by <c>Continuation</c>, which has been
+ are all defined by <c><anno>Continuation</anno></c>, which has been
returned by a prior call to <c>match_object/1</c> or
<c>match_object/3</c>.</p>
<p>When all objects of the table have been matched,
@@ -668,20 +631,17 @@ ok
</desc>
</func>
<func>
- <name>match_object(Name, Pattern) -> [Object] | {error, Reason}</name>
+ <name name="match_object" arity="2"/>
<fsummary>Match the objects stored in a Dets table and return a list of objects.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>Pattern = tuple()</v>
- <v>Object = object()</v>
- </type>
<desc>
- <p>Returns a list of all objects of the table <c>Name</c> that
- match <c>Pattern</c> in some unspecified order. See <seealso marker="ets">ets(3)</seealso> for a description of patterns.
+ <p>Returns a list of all objects of the table <c><anno>Name</anno></c> that
+ match <c><anno>Pattern</anno></c> in some unspecified order.
+ See <seealso marker="ets#match/2">ets:match/2</seealso> for a
+ description of patterns.
</p>
- <p>If the keypos'th element of <c>Pattern</c> is
+ <p>If the keypos'th element of <c><anno>Pattern</anno></c> is
unbound, all objects of the table are matched. If the
- keypos'th element of <c>Pattern</c> is bound, only the
+ keypos'th element of <c><anno>Pattern</anno></c> is bound, only the
objects with the right key are matched.</p>
<p>Using the <c>match_object</c> functions for traversing all
objects of a table is more efficient than calling
@@ -689,34 +649,28 @@ ok
</desc>
</func>
<func>
- <name>match_object(Name, Pattern, N) -> {[Object], Continuation} | '$end_of_table' | {error, Reason}</name>
+ <name name="match_object" arity="3"/>
<fsummary>Match the first chunk of objects stored in a Dets table and return a list of objects.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>Pattern = tuple()</v>
- <v>N = default | int()</v>
- <v>Object = object()</v>
- <v>Continuation = object_cont()</v>
- </type>
<desc>
- <p>Matches some or all objects stored in the table <c>Name</c>
+ <p>Matches some or all objects stored in the table <c><anno>Name</anno></c>
and returns a non-empty list of the objects that match
- <c>Pattern</c> in some unspecified order. See <seealso marker="ets">ets(3)</seealso> for a description of
- patterns.</p>
+ <c><anno>Pattern</anno></c> in some unspecified order.
+ See <seealso marker="ets#match/2">ets:match/2</seealso> for a
+ description of patterns.</p>
<p>A list of objects and a continuation is returned, unless
the table is empty, in which case <c>'$end_of_table'</c>
is returned. The continuation is to be used when matching
further objects by calling <c>match_object/1</c>.</p>
- <p>If the keypos'th element of <c>Pattern</c> is bound, all
+ <p>If the keypos'th element of <c><anno>Pattern</anno></c> is bound, all
objects of the table are matched. If the keypos'th element is
- unbound, all objects of the table are matched, <c>N</c>
+ unbound, all objects of the table are matched, <c><anno>N</anno></c>
objects at a time, until at least one object matches or the
end of the table has been reached. The default, indicated by
- giving <c>N</c> the value <c>default</c>, is to let the number
+ giving <c><anno>N</anno></c> the value <c>default</c>, is to let the number
of objects vary depending on the sizes of the objects. If
- <c>Name</c> is a version 9 table, all matching objects with
+ <c><anno>Name</anno></c> is a version 9 table, all matching objects with
the same key are always returned in the same reply which
- implies that more than N objects may sometimes be returned.
+ implies that more than <anno>N</anno> objects may sometimes be returned.
</p>
<p>The table should always be protected using
<c>safe_fixtable/2</c> before calling <c>match_object/3</c>,
@@ -724,43 +678,31 @@ ok
</desc>
</func>
<func>
- <name>member(Name, Key) -> Bool | {error, Reason}</name>
+ <name name="member" arity="2"/>
<fsummary>Test for occurrence of a key in a Dets table.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>Key = term()</v>
- <v>Bool = bool()</v>
- </type>
<desc>
<p>Works like <c>lookup/2</c>, but does not return the
objects. The function returns <c>true</c> if one or more
- elements of the table has the key <c>Key</c>, <c>false</c>
+ elements of the table has the key <c><anno>Key</anno></c>, <c>false</c>
otherwise.</p>
</desc>
</func>
<func>
- <name>next(Name, Key1) -> Key2 | '$end_of_table'</name>
+ <name name="next" arity="2"/>
<fsummary>Return the next key in a Dets table.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>Key1 = Key2 = term()</v>
- </type>
<desc>
- <p>Returns the key following <c>Key1</c> in the table
- <c>Name</c> according to the table's internal order, or
+ <p>Returns the key following <c><anno>Key1</anno></c> in the table
+ <c><anno>Name</anno></c> according to the table's internal order, or
<c>'$end_of_table'</c> if there is no next key.</p>
<p>Should an error occur, the process is exited with an error
tuple <c>{error, Reason}</c>.</p>
- <p>Use <c>first/1</c> to find the first key in the table.</p>
+ <p>Use <seealso marker="#first/1"><c>first/1</c></seealso> to find
+ the first key in the table.</p>
</desc>
</func>
<func>
- <name>open_file(Filename) -> {ok, Reference} | {error, Reason}</name>
+ <name name="open_file" arity="1"/>
<fsummary>Open an existing Dets table.</fsummary>
- <type>
- <v>FileName = file()</v>
- <v>Reference = reference()</v>
- </type>
<desc>
<p>Opens an existing table. If the table has not been properly
closed, it will be repaired. The returned reference is to be
@@ -769,15 +711,12 @@ ok
</desc>
</func>
<func>
- <name>open_file(Name, Args) -> {ok, Name} | {error, Reason}</name>
+ <name name="open_file" arity="2"/>
<fsummary>Open a Dets table.</fsummary>
- <type>
- <v>Name = atom()</v>
- </type>
<desc>
<p>Opens a table. An empty Dets table is created if no file
exists.</p>
- <p>The atom <c>Name</c> is the name of the table. The table
+ <p>The atom <c><anno>Name</anno></c> is the name of the table. The table
name must be provided in all subsequent operations on the
table. The name can be used by other processes as well, and
several process can share one table.
@@ -786,18 +725,20 @@ ok
name and arguments, then the table will have two users. If one
user closes the table, it still remains open until the second
user closes the table.</p>
- <p>The <c>Args</c> argument is a list of <c>{Key, Val}</c>
+ <p>The <c><anno>Args</anno></c> argument is a list of <c>{Key, Val}</c>
tuples where the following values are allowed:</p>
<list type="bulleted">
<item>
- <p><c>{access, access()}</c>. It is possible to open
+ <p><c>{access, <seealso marker="#type-access">
+ access()</seealso>}</c>. It is possible to open
existing tables in read-only mode. A table which is opened
in read-only mode is not subjected to the automatic file
reparation algorithm if it is later opened after a crash.
The default value is <c>read_write</c>.</p>
</item>
<item>
- <p><c>{auto_save, auto_save()}</c>, the auto save
+ <p><c>{auto_save, <seealso marker="#type-auto_save">
+ auto_save()</seealso>}</c>, the auto save
interval. If the interval is an integer <c>Time</c>, the
table is flushed to disk whenever it is not accessed for
<c>Time</c> milliseconds. A table that has been flushed
@@ -807,15 +748,18 @@ ok
is 180000 (3 minutes).</p>
</item>
<item>
- <p><c>{estimated_no_objects, int()}</c>. Equivalent to the
+ <p><c>{estimated_no_objects, <seealso marker="#type-no_slots">
+ no_slots()</seealso>}</c>. Equivalent to the
<c>min_no_slots</c> option.</p>
</item>
<item>
- <p><c>{file, file()}</c>, the name of the file to be
+ <p><c>{file, <seealso marker="file#type-name">
+ file:name()</seealso>}</c>, the name of the file to be
opened. The default value is the name of the table.</p>
</item>
<item>
- <p><c>{max_no_slots, no_slots()}</c>, the maximum number
+ <p><c>{max_no_slots, <seealso marker="#type-no_slots">
+ no_slots()</seealso>}</c>, the maximum number
of slots that will be used. The default value as well as
the maximal value is 32 M. Note that a higher value may
increase the fragmentation of the table, and conversely,
@@ -824,14 +768,16 @@ ok
9 tables.</p>
</item>
<item>
- <p><c>{min_no_slots, no_slots()}</c>. Application
+ <p><c>{min_no_slots, <seealso marker="#type-no_slots">
+ no_slots()</seealso>}</c>. Application
performance can be enhanced with this flag by specifying,
when the table is created, the estimated number of
different keys that will be stored in the table. The
default value as well as the minimum value is 256.</p>
</item>
<item>
- <p><c>{keypos, keypos()}</c>, the position of the
+ <p><c>{keypos, <seealso marker="#type-keypos">
+ keypos()</seealso>}</c>, the position of the
element of each object to be used as key. The default
value is 1. The ability to explicitly state the key
position is most convenient when we want to store Erlang
@@ -839,7 +785,7 @@ ok
name of the record type.</p>
</item>
<item>
- <p><c>{ram_file, bool()}</c>, whether the table is to
+ <p><c>{ram_file, boolean()}</c>, whether the table is to
be kept in RAM. Keeping the table in RAM may sound like an
anomaly, but can enhance the performance of applications
which open a table, insert a set of objects, and then
@@ -849,7 +795,7 @@ ok
</item>
<item>
<p><c>{repair, Value}</c>. <c>Value</c> can be either
- a <c>bool()</c> or the atom <c>force</c>. The flag
+ a <c>boolean()</c> or the atom <c>force</c>. The flag
specifies whether the Dets server should invoke the
automatic file reparation algorithm. The default is
<c>true</c>. If <c>false</c> is specified, there is no
@@ -868,11 +814,12 @@ ok
already open.</p>
</item>
<item>
- <p><c>{type, type()}</c>, the type of the table. The
- default value is <c>set</c>.</p>
+ <p><c>{type, <seealso marker="#type-type">type()</seealso>}</c>,
+ the type of the table. The default value is <c>set</c>.</p>
</item>
<item>
- <p><c>{version, version()}</c>, the version of the format
+ <p><c>{version, <seealso marker="#type-version">
+ version()</seealso>}</c>, the version of the format
used for the table. The default value is <c>9</c>. Tables
on the format used before OTP R8 can be created by giving
the value <c>8</c>. A version 8 table can be converted to
@@ -883,12 +830,8 @@ ok
</desc>
</func>
<func>
- <name>pid2name(Pid) -> {ok, Name} | undefined</name>
+ <name name="pid2name" arity="1"/>
<fsummary>Return the name of the Dets table handled by a pid.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>Pid = pid()</v>
- </type>
<desc>
<p>Returns the name of the table given the pid of a process
that handles requests to a table, or <c>undefined</c> if
@@ -897,12 +840,8 @@ ok
</desc>
</func>
<func>
- <name>repair_continuation(Continuation, MatchSpec) -> Continuation2</name>
+ <name name="repair_continuation" arity="2"/>
<fsummary>Repair a continuation from select/1 or select/3.</fsummary>
- <type>
- <v>Continuation = Continuation2 = select_cont()</v>
- <v>MatchSpec = match_spec()</v>
- </type>
<desc>
<p>This function can be used to restore an opaque continuation
returned by <c>select/3</c> or <c>select/1</c> if the
@@ -932,14 +871,11 @@ ok
</desc>
</func>
<func>
- <name>safe_fixtable(Name, Fix)</name>
+ <name name="safe_fixtable" arity="2"/>
<fsummary>Fix a Dets table for safe traversal.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>Fix = bool()</v>
- </type>
<desc>
- <p>If <c>Fix</c> is <c>true</c>, the table <c>Name</c> is
+ <p>If <c><anno>Fix</anno></c> is <c>true</c>, the table
+ <c><anno>Name</anno></c> is
fixed (once more) by the calling process, otherwise the table
is released. The table is also released when a fixing process
terminates.
@@ -961,17 +897,13 @@ ok
</desc>
</func>
<func>
- <name>select(Continuation) -> {Selection, Continuation2} | '$end_of_table' | {error, Reason}</name>
+ <name name="select" arity="1"/>
<fsummary>Apply a match specification to some objects stored in a Dets table.</fsummary>
- <type>
- <v>Continuation = Continuation2 = select_cont()</v>
- <v>Selection = [term()]</v>
- </type>
<desc>
<p>Applies a match specification to some objects stored in a
table and returns a non-empty list of the results. The
table, the match specification, and the number of objects
- that are matched are all defined by <c>Continuation</c>,
+ that are matched are all defined by <c><anno>Continuation</anno></c>,
which has been returned by a prior call to <c>select/1</c>
or <c>select/3</c>.</p>
<p>When all objects of the table have been matched,
@@ -979,20 +911,15 @@ ok
</desc>
</func>
<func>
- <name>select(Name, MatchSpec) -> Selection | {error, Reason}</name>
+ <name name="select" arity="2"/>
<fsummary>Apply a match specification to all objects stored in a Dets table.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>MatchSpec = match_spec()</v>
- <v>Selection = [term()]</v>
- </type>
<desc>
<p>Returns the results of applying the match specification
- <c>MatchSpec</c> to all or some objects stored in the table
- <c>Name</c>. The order of the objects is not specified. See
+ <c><anno>MatchSpec</anno></c> to all or some objects stored in the table
+ <c><anno>Name</anno></c>. The order of the objects is not specified. See
the ERTS User's Guide for a description of match
specifications.</p>
- <p>If the keypos'th element of <c>MatchSpec</c> is
+ <p>If the keypos'th element of <c><anno>MatchSpec</anno></c> is
unbound, the match specification is applied to all objects of
the table. If the keypos'th element is bound, the match
specification is applied to the objects with the right key(s)
@@ -1004,19 +931,12 @@ ok
</desc>
</func>
<func>
- <name>select(Name, MatchSpec, N) -> {Selection, Continuation} | '$end_of_table' | {error, Reason}</name>
+ <name name="select" arity="3"/>
<fsummary>Apply a match specification to the first chunk of objects stored in a Dets table.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>MatchSpec = match_spec()</v>
- <v>N = default | int()</v>
- <v>Selection = [term()]</v>
- <v>Continuation = select_cont()</v>
- </type>
<desc>
<p>Returns the results of applying the match specification
- <c>MatchSpec</c> to some or all objects stored in the table
- <c>Name</c>. The order of the objects is not specified. See
+ <c><anno>MatchSpec</anno></c> to some or all objects stored in the table
+ <c><anno>Name</anno></c>. The order of the objects is not specified. See
the ERTS User's Guide for a description of match
specifications.</p>
<p>A tuple of the results of applying the match specification
@@ -1024,18 +944,18 @@ ok
in which case <c>'$end_of_table'</c> is returned. The
continuation is to be used when matching further objects by
calling <c>select/1</c>.</p>
- <p>If the keypos'th element of <c>MatchSpec</c> is bound, the
+ <p>If the keypos'th element of <c><anno>MatchSpec</anno></c> is bound, the
match specification is applied to all objects of the table
with the right key(s). If the keypos'th element of
- <c>MatchSpec</c> is unbound, the match specification is
- applied to all objects of the table, <c>N</c> objects at a
+ <c><anno>MatchSpec</anno></c> is unbound, the match specification is
+ applied to all objects of the table, <c><anno>N</anno></c> objects at a
time, until at least one object matches or the end of the
table has been reached. The default, indicated by giving
- <c>N</c> the value <c>default</c>, is to let the number of
+ <c><anno>N</anno></c> the value <c>default</c>, is to let the number of
objects vary depending on the sizes of the objects. If
- <c>Name</c> is a version 9 table, all objects with the same
+ <c><anno>Name</anno></c> is a version 9 table, all objects with the same
key are always handled at the same time which implies that the
- match specification may be applied to more than N objects.
+ match specification may be applied to more than <anno>N</anno> objects.
</p>
<p>The table should always be protected using
<c>safe_fixtable/2</c> before calling <c>select/3</c>, or
@@ -1043,48 +963,35 @@ ok
</desc>
</func>
<func>
- <name>select_delete(Name, MatchSpec) -> N | {error, Reason}</name>
+ <name name="select_delete" arity="2"/>
<fsummary>Delete all objects that match a given pattern from a Dets table.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>MatchSpec = match_spec()</v>
- <v>N = int()</v>
- </type>
<desc>
- <p>Deletes each object from the table <c>Name</c> such that
- applying the match specification <c>MatchSpec</c> to the
+ <p>Deletes each object from the table <c><anno>Name</anno></c> such that
+ applying the match specification <c><anno>MatchSpec</anno></c> to the
object returns the value <c>true</c>. See the ERTS
User's Guide for a description of match
specifications. Returns the number of deleted objects.</p>
- <p>If the keypos'th element of <c>MatchSpec</c> is
+ <p>If the keypos'th element of <c><anno>MatchSpec</anno></c> is
bound, the match specification is applied to the objects
with the right key(s) only.</p>
</desc>
</func>
<func>
- <name>slot(Name, I) -> '$end_of_table' | [Object] | {error, Reason}</name>
+ <name name="slot" arity="2"/>
<fsummary>Return the list of objects associated with a slot of a Dets table.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>I = int()</v>
- <v>Object = object()</v>
- </type>
<desc>
<p>The objects of a table are distributed among slots,
starting with slot <c>0</c> and ending with slot n. This
function returns the list of objects associated with slot
- <c>I</c>. If <c>I</c> is greater than n <c>'$end_of_table'</c>
- is returned.</p>
+ <c><anno>I</anno></c>. If <c><anno>I</anno></c> is greater than n
+ <c>'$end_of_table'</c> is returned.</p>
</desc>
</func>
<func>
- <name>sync(Name) -> ok | {error, Reason}</name>
+ <name name="sync" arity="1"/>
<fsummary>Ensure that all updates made to a Dets table are written to disk.</fsummary>
- <type>
- <v>Name = name()</v>
- </type>
<desc>
- <p>Ensures that all updates made to the table <c>Name</c> are
+ <p>Ensures that all updates made to the table <c><anno>Name</anno></c> are
written to disk. This also applies to tables which have been
opened with the <c>ram_file</c> flag set to <c>true</c>. In
this case, the contents of the RAM file are flushed to
@@ -1095,25 +1002,16 @@ ok
</desc>
</func>
<func>
- <name>table(Name [, Options]) -> QueryHandle</name>
+ <name name="table" arity="1"/>
+ <name name="table" arity="2"/>
<fsummary>Return a QLC query handle.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>QueryHandle = -&nbsp;a query handle, see qlc(3)&nbsp;-</v>
- <v>Options = [Option] | Option</v>
- <v>Option = {n_objects, Limit} | {traverse, TraverseMethod}</v>
- <v>Limit = default | integer() >= 1</v>
- <v>TraverseMethod = first_next | select | {select, MatchSpec}</v>
- <v>MatchSpec = match_spec()</v>
- </type>
<desc>
- <p> <marker id="qlc_table"></marker>
-Returns a QLC (Query List
+ <p><marker id="qlc_table"></marker>Returns a QLC (Query List
Comprehension) query handle. The module <c>qlc</c>
implements a query language aimed mainly at Mnesia but Ets
tables, Dets tables, and lists are also recognized by <c>qlc</c>
as sources of data. Calling <c>dets:table/1,2</c> is the
- means to make the Dets table <c>Name</c> usable to <c>qlc</c>.</p>
+ means to make the Dets table <c><anno>Name</anno></c> usable to <c>qlc</c>.</p>
<p>When there are only simple restrictions on the key position
<c>qlc</c> uses <c>dets:lookup/2</c> to look up the keys, but when
that is not possible the whole table is traversed. The
@@ -1137,7 +1035,8 @@ Returns a QLC (Query List
specification that matches all objects.</p>
</item>
<item>
- <p><c>{select, MatchSpec}</c>. As for <c>select</c>
+ <p><c>{select, <seealso marker="#type-match_spec">
+ match_spec()}</seealso></c>. As for <c>select</c>
the table is traversed by calling <c>dets:select/3</c>
and <c>dets:select/1</c>. The difference is that the
match specification is explicitly given. This is how to
@@ -1166,35 +1065,23 @@ true </pre>
</desc>
</func>
<func>
- <name>to_ets(Name, EtsTab) -> EtsTab | {error, Reason}</name>
+ <name name="to_ets" arity="2"/>
<fsummary>Insert all objects of a Dets table into an Ets table.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>EtsTab = -&nbsp;see ets(3)&nbsp;-</v>
- </type>
<desc>
- <p>Inserts the objects of the Dets table <c>Name</c> into the
- Ets table <c>EtsTab</c>. The order in which the objects are
+ <p>Inserts the objects of the Dets table <c><anno>Name</anno></c> into the
+ Ets table <c><anno>EtsTab</anno></c>. The order in which the objects are
inserted is not specified. The existing objects of the Ets
table are kept unless overwritten.</p>
</desc>
</func>
<func>
- <name>traverse(Name, Fun) -> Return | {error, Reason}</name>
+ <name name="traverse" arity="2"/>
<fsummary>Apply a function to all or some objects stored in a Dets table.</fsummary>
- <type>
- <v>Fun = fun(Object) -> FunReturn</v>
- <v>FunReturn = continue | {continue, Val} | {done, Value}</v>
- <v>Val = Value = term()</v>
- <v>Name = name()</v>
- <v>Object = object()</v>
- <v>Return = [term()]</v>
- </type>
<desc>
- <p>Applies <c>Fun</c> to each object stored in the table
- <c>Name</c> in some unspecified order. Different actions are
- taken depending on the return value of <c>Fun</c>. The
- following <c>Fun</c> return values are allowed:</p>
+ <p>Applies <c><anno>Fun</anno></c> to each object stored in the table
+ <c><anno>Name</anno></c> in some unspecified order. Different actions are
+ taken depending on the return value of <c><anno>Fun</anno></c>. The
+ following <c><anno>Fun</anno></c> return values are allowed:</p>
<taglist>
<tag><c>continue</c></tag>
<item>
@@ -1206,35 +1093,31 @@ fun(X) -> io:format("~p~n", [X]), continue end. </pre>
</item>
<tag><c>{continue, Val}</c></tag>
<item>
- <p>Continue the traversal and accumulate <c>Val</c>. The
+ <p>Continue the traversal and accumulate <c><anno>Val</anno></c>. The
following function is supplied in order to collect all
objects of a table in a list: </p>
<pre>
fun(X) -> {continue, X} end. </pre>
</item>
- <tag><c>{done, Value}</c></tag>
+ <tag><c>{done, <anno>Value</anno>}</c></tag>
<item>
- <p>Terminate the traversal and return <c>[Value | Acc]</c>.</p>
+ <p>Terminate the traversal and return <c>[<anno>Value</anno> | Acc]</c>.</p>
</item>
</taglist>
- <p>Any other value returned by <c>Fun</c> terminates the
+ <p>Any other value <c><anno>OtherValue</anno></c> returned by <c><anno>Fun</anno></c> terminates the
traversal and is immediately returned.
</p>
</desc>
</func>
<func>
- <name>update_counter(Name, Key, Increment) -> Result</name>
+ <name name="update_counter" arity="3"/>
<fsummary>Update a counter object stored in a Dets table.</fsummary>
- <type>
- <v>Name = name()</v>
- <v>Key = term()</v>
- <v>Increment = {Pos, Incr} | Incr</v>
- <v>Pos = Incr = Result = integer()</v>
- </type>
<desc>
- <p>Updates the object with key <c>Key</c> stored in the table
- <c>Name</c> of type <c>set</c> by adding <c>Incr</c> to the
- element at the <c>Pos</c>:th position. The new counter value
+ <p>Updates the object with key <c><anno>Key</anno></c> stored in the
+ table <c><anno>Name</anno></c> of type <c>set</c> by adding
+ <c><anno>Incr</anno></c> to the
+ element at the <c><anno>Pos</anno></c>:th position.
+ The new counter value
is returned. If no position is specified, the element directly
following the key is updated.</p>
<p>This functions provides a way of updating a counter,
@@ -1252,4 +1135,3 @@ fun(X) -> {continue, X} end. </pre>
<seealso marker="qlc">qlc(3)</seealso></p>
</section>
</erlref>
-
diff --git a/lib/stdlib/doc/src/dict.xml b/lib/stdlib/doc/src/dict.xml
index 40e61d7d33..b01acd02bf 100644
--- a/lib/stdlib/doc/src/dict.xml
+++ b/lib/stdlib/doc/src/dict.xml
@@ -39,176 +39,120 @@
they do not compare equal (<c>==</c>).</p>
</description>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-dictionary()
- as returned by new/0</code>
- </section>
+ <datatypes>
+ <datatype>
+ <name><marker id="type-dict">dict()</marker></name>
+ <desc><p>Dictionary as returned by <c>new/0</c>.</p></desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>append(Key, Value, Dict1) -> Dict2</name>
+ <name name="append" arity="3"/>
<fsummary>Append a value to keys in a dictionary</fsummary>
- <type>
- <v>Key = Value = term()</v>
- <v>Dict1 = Dict2 = dictionary()</v>
- </type>
<desc>
- <p>This function appends a new <c>Value</c> to the current list
- of values associated with <c>Key</c>. An exception is
- generated if the initial value associated with <c>Key</c> is
- not a list of values.</p>
+ <p>This function appends a new <c><anno>Value</anno></c> to the current list
+ of values associated with <c><anno>Key</anno></c>.</p>
</desc>
</func>
<func>
- <name>append_list(Key, ValList, Dict1) -> Dict2</name>
+ <name name="append_list" arity="3"/>
<fsummary>Append new values to keys in a dictionary</fsummary>
- <type>
- <v>ValList = [Value]</v>
- <v>Key = Value = term()</v>
- <v>Dict1 = Dict2 = dictionary()</v>
- </type>
<desc>
- <p>This function appends a list of values <c>ValList</c> to
- the current list of values associated with <c>Key</c>. An
+ <p>This function appends a list of values <c><anno>ValList</anno></c> to
+ the current list of values associated with <c><anno>Key</anno></c>. An
exception is generated if the initial value associated with
- <c>Key</c> is not a list of values.</p>
+ <c><anno>Key</anno></c> is not a list of values.</p>
</desc>
</func>
<func>
- <name>erase(Key, Dict1) -> Dict2</name>
+ <name name="erase" arity="2"/>
<fsummary>Erase a key from a dictionary</fsummary>
- <type>
- <v>Key = term()</v>
- <v>Dict1 = Dict2 = dictionary()</v>
- </type>
<desc>
<p>This function erases all items with a given key from a
dictionary.</p>
</desc>
</func>
<func>
- <name>fetch(Key, Dict) -> Value</name>
+ <name name="fetch" arity="2"/>
<fsummary>Look-up values in a dictionary</fsummary>
- <type>
- <v>Key = Value = term()</v>
- <v>Dict = dictionary()</v>
- </type>
<desc>
- <p>This function returns the value associated with <c>Key</c>
- in the dictionary <c>Dict</c>. <c>fetch</c> assumes that
- the <c>Key</c> is present in the dictionary and an exception
- is generated if <c>Key</c> is not in the dictionary.</p>
+ <p>This function returns the value associated with <c><anno>Key</anno></c>
+ in the dictionary <c><anno>Dict</anno></c>. <c>fetch</c> assumes that
+ the <c><anno>Key</anno></c> is present in the dictionary and an exception
+ is generated if <c><anno>Key</anno></c> is not in the dictionary.</p>
</desc>
</func>
<func>
- <name>fetch_keys(Dict) -> Keys</name>
+ <name name="fetch_keys" arity="1"/>
<fsummary>Return all keys in a dictionary</fsummary>
- <type>
- <v>Dict = dictionary()</v>
- <v>Keys = [term()]</v>
- </type>
<desc>
<p>This function returns a list of all keys in the dictionary.</p>
</desc>
</func>
<func>
- <name>filter(Pred, Dict1) -> Dict2</name>
+ <name name="filter" arity="2"/>
<fsummary>Choose elements which satisfy a predicate</fsummary>
- <type>
- <v>Pred = fun(Key, Value) -> bool()</v>
- <v>&nbsp;Key = Value = term()</v>
- <v>Dict1 = Dict2 = dictionary()</v>
- </type>
<desc>
- <p><c>Dict2</c> is a dictionary of all keys and values in
- <c>Dict1</c> for which <c>Pred(Key, Value)</c> is <c>true</c>.</p>
+ <p><c><anno>Dict2</anno></c> is a dictionary of all keys and values in
+ <c><anno>Dict1</anno></c> for which <c><anno>Pred</anno>(<anno>Key</anno>, <anno>Value</anno>)</c> is <c>true</c>.</p>
</desc>
</func>
<func>
- <name>find(Key, Dict) -> {ok, Value} | error</name>
+ <name name="find" arity="2"/>
<fsummary>Search for a key in a dictionary</fsummary>
- <type>
- <v>Key = Value = term()</v>
- <v>Dict = dictionary()</v>
- </type>
<desc>
<p>This function searches for a key in a dictionary. Returns
- <c>{ok, Value}</c> where <c>Value</c> is the value associated
- with <c>Key</c>, or <c>error</c> if the key is not present in
+ <c>{ok, <anno>Value</anno>}</c> where <c><anno>Value</anno></c> is the value associated
+ with <c><anno>Key</anno></c>, or <c>error</c> if the key is not present in
the dictionary.</p>
</desc>
</func>
<func>
- <name>fold(Fun, Acc0, Dict) -> Acc1</name>
+ <name name="fold" arity="3"/>
<fsummary>Fold a function over a dictionary</fsummary>
- <type>
- <v>Fun = fun(Key, Value, AccIn) -> AccOut</v>
- <v>Key = Value = term()</v>
- <v>Acc0 = Acc1 = AccIn = AccOut = term()</v>
- <v>Dict = dictionary()</v>
- </type>
<desc>
- <p>Calls <c>Fun</c> on successive keys and values of
- <c>Dict</c> together with an extra argument <c>Acc</c>
- (short for accumulator). <c>Fun</c> must return a new
- accumulator which is passed to the next call. <c>Acc0</c> is
+ <p>Calls <c><anno>Fun</anno></c> on successive keys and values of
+ <c><anno>Dict</anno></c> together with an extra argument <c>Acc</c>
+ (short for accumulator). <c><anno>Fun</anno></c> must return a new
+ accumulator which is passed to the next call. <c><anno>Acc0</anno></c> is
returned if the list is empty. The evaluation order is
undefined.</p>
</desc>
</func>
<func>
- <name>from_list(List) -> Dict</name>
+ <name name="from_list" arity="1"/>
<fsummary>Convert a list of pairs to a dictionary</fsummary>
- <type>
- <v>List = [{Key, Value}]</v>
- <v>Dict = dictionary()</v>
- </type>
<desc>
- <p>This function converts the <c>Key</c> - <c>Value</c> list
- <c>List</c> to a dictionary.</p>
+ <p>This function converts the <c><anno>Key</anno></c> - <c><anno>Value</anno></c> list
+ <c><anno>List</anno></c> to a dictionary.</p>
</desc>
</func>
<func>
- <name>is_key(Key, Dict) -> bool()</name>
+ <name name="is_key" arity="2"/>
<fsummary>Test if a key is in a dictionary</fsummary>
- <type>
- <v>Key = term()</v>
- <v>Dict = dictionary()</v>
- </type>
<desc>
- <p>This function tests if <c>Key</c> is contained in
- the dictionary <c>Dict</c>.</p>
+ <p>This function tests if <c><anno>Key</anno></c> is contained in
+ the dictionary <c><anno>Dict</anno></c>.</p>
</desc>
</func>
<func>
- <name>map(Fun, Dict1) -> Dict2</name>
+ <name name="map" arity="2"/>
<fsummary>Map a function over a dictionary</fsummary>
- <type>
- <v>Fun = fun(Key, Value1) -> Value2</v>
- <v>&nbsp;Key = Value1 = Value2 = term()</v>
- <v>Dict1 = Dict2 = dictionary()</v>
- </type>
<desc>
- <p><c>map</c> calls <c>Func</c> on successive keys and values
- of <c>Dict</c> to return a new value for each key.
+ <p><c>map</c> calls <c><anno>Fun</anno></c> on successive keys and values
+ of <c><anno>Dict1</anno></c> to return a new value for each key.
The evaluation order is undefined.</p>
</desc>
</func>
<func>
- <name>merge(Fun, Dict1, Dict2) -> Dict3</name>
+ <name name="merge" arity="3"/>
<fsummary>Merge two dictionaries</fsummary>
- <type>
- <v>Fun = fun(Key, Value1, Value2) -> Value</v>
- <v>&nbsp;Key = Value1 = Value2 = Value3 = term()</v>
- <v>Dict1 = Dict2 = Dict3 = dictionary()</v>
- </type>
<desc>
- <p><c>merge</c> merges two dictionaries, <c>Dict1</c> and
- <c>Dict2</c>, to create a new dictionary. All the <c>Key</c>
- - <c>Value</c> pairs from both dictionaries are included in
+ <p><c>merge</c> merges two dictionaries, <c><anno>Dict1</anno></c> and
+ <c><anno>Dict2</anno></c>, to create a new dictionary. All the <c><anno>Key</anno></c>
+ - <c><anno>Value</anno></c> pairs from both dictionaries are included in
the new dictionary. If a key occurs in both dictionaries then
- <c>Fun</c> is called with the key and both values to return a
+ <c><anno>Fun</anno></c> is called with the key and both values to return a
new value. <c>merge</c> could be defined as:</p>
<code type="none">
merge(Fun, D1, D2) ->
@@ -219,75 +163,52 @@ merge(Fun, D1, D2) ->
</desc>
</func>
<func>
- <name>new() -> dictionary()</name>
+ <name name="new" arity="0"/>
<fsummary>Create a dictionary</fsummary>
<desc>
<p>This function creates a new dictionary.</p>
</desc>
</func>
<func>
- <name>size(Dict) -> int()</name>
+ <name name="size" arity="1"/>
<fsummary>Return the number of elements in a dictionary</fsummary>
- <type>
- <v>Dict = dictionary()</v>
- </type>
<desc>
- <p>Returns the number of elements in a <c>Dict</c>.</p>
+ <p>Returns the number of elements in a <c><anno>Dict</anno></c>.</p>
</desc>
</func>
<func>
- <name>store(Key, Value, Dict1) -> Dict2</name>
+ <name name="store" arity="3"/>
<fsummary>Store a value in a dictionary</fsummary>
- <type>
- <v>Key = Value = term()</v>
- <v>Dict1 = Dict2 = dictionary()</v>
- </type>
<desc>
- <p>This function stores a <c>Key</c> - <c>Value</c> pair in a
- dictionary. If the <c>Key</c> already exists in <c>Dict1</c>,
- the associated value is replaced by <c>Value</c>.</p>
+ <p>This function stores a <c><anno>Key</anno></c> - <c><anno>Value</anno></c> pair in a
+ dictionary. If the <c><anno>Key</anno></c> already exists in <c><anno>Dict1</anno></c>,
+ the associated value is replaced by <c><anno>Value</anno></c>.</p>
</desc>
</func>
<func>
- <name>to_list(Dict) -> List</name>
+ <name name="to_list" arity="1"/>
<fsummary>Convert a dictionary to a list of pairs</fsummary>
- <type>
- <v>Dict = dictionary()</v>
- <v>List = [{Key, Value}]</v>
- </type>
<desc>
<p>This function converts the dictionary to a list
representation.</p>
</desc>
</func>
<func>
- <name>update(Key, Fun, Dict1) -> Dict2</name>
+ <name name="update" arity="3"/>
<fsummary>Update a value in a dictionary</fsummary>
- <type>
- <v>Key = term()</v>
- <v>Fun = fun(Value1) -> Value2</v>
- <v>&nbsp;Value1 = Value2 = term()</v>
- <v>Dict1 = Dict2 = dictionary()</v>
- </type>
<desc>
- <p>Update a value in a dictionary by calling <c>Fun</c> on
+ <p>Update a value in a dictionary by calling <c><anno>Fun</anno></c> on
the value to get a new value. An exception is generated if
- <c>Key</c> is not present in the dictionary.</p>
+ <c><anno>Key</anno></c> is not present in the dictionary.</p>
</desc>
</func>
<func>
- <name>update(Key, Fun, Initial, Dict1) -> Dict2</name>
+ <name name="update" arity="4"/>
<fsummary>Update a value in a dictionary</fsummary>
- <type>
- <v>Key = Initial = term()</v>
- <v>Fun = fun(Value1) -> Value2</v>
- <v>&nbsp;Value1 = Value2 = term()</v>
- <v>Dict1 = Dict2 = dictionary()</v>
- </type>
<desc>
- <p>Update a value in a dictionary by calling <c>Fun</c> on
- the value to get a new value. If <c>Key</c> is not present
- in the dictionary then <c>Initial</c> will be stored as
+ <p>Update a value in a dictionary by calling <c><anno>Fun</anno></c> on
+ the value to get a new value. If <c><anno>Key</anno></c> is not present
+ in the dictionary then <c><anno>Initial</anno></c> will be stored as
the first value. For example <c>append/3</c> could be defined
as:</p>
<code type="none">
@@ -296,17 +217,12 @@ append(Key, Val, D) ->
</desc>
</func>
<func>
- <name>update_counter(Key, Increment, Dict1) -> Dict2</name>
+ <name name="update_counter" arity="3"/>
<fsummary>Increment a value in a dictionary</fsummary>
- <type>
- <v>Key = term()</v>
- <v>Increment = number()</v>
- <v>Dict1 = Dict2 = dictionary()</v>
- </type>
<desc>
- <p>Add <c>Increment</c> to the value associated with <c>Key</c>
- and store this value. If <c>Key</c> is not present in
- the dictionary then <c>Increment</c> will be stored as
+ <p>Add <c><anno>Increment</anno></c> to the value associated with <c><anno>Key</anno></c>
+ and store this value. If <c><anno>Key</anno></c> is not present in
+ the dictionary then <c><anno>Increment</anno></c> will be stored as
the first value.</p>
<p>This could be defined as:</p>
<code type="none">
diff --git a/lib/stdlib/doc/src/digraph.xml b/lib/stdlib/doc/src/digraph.xml
index ad256e671f..0afc70ebe0 100644
--- a/lib/stdlib/doc/src/digraph.xml
+++ b/lib/stdlib/doc/src/digraph.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -87,67 +87,79 @@
is a digraph that has no cycles.
</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="d_type"/>
+ </datatype>
+ <datatype>
+ <name name="d_cyclicity"/>
+ </datatype>
+ <datatype>
+ <name name="d_protection"/>
+ </datatype>
+ <datatype>
+ <name><marker id="type-digraph">digraph()</marker></name>
+ <desc><p>A digraph as returned by <c>new/0,1</c>.</p></desc>
+ </datatype>
+ <datatype>
+ <name><marker id="type-edge">edge()</marker></name>
+ </datatype>
+ <datatype>
+ <name name="label"/>
+ </datatype>
+ <datatype>
+ <name><marker id="type-vertex">vertex()</marker></name>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>add_edge(G, E, V1, V2, Label) -> edge() | {error, Reason}</name>
- <name>add_edge(G, V1, V2, Label) -> edge() | {error, Reason}</name>
- <name>add_edge(G, V1, V2) -> edge() | {error, Reason}</name>
+ <name name="add_edge" arity="3"/>
+ <name name="add_edge" arity="4"/>
+ <name name="add_edge" arity="5"/>
<fsummary>Add an edge to a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>E = edge()</v>
- <v>V1 = V2 = vertex()</v>
- <v>Label = label()</v>
- <v>Reason = {bad_edge, Path} | {bad_vertex, V}</v>
- <v>Path = [vertex()]</v>
- </type>
+ <type name="add_edge_err_rsn"/>
<desc>
- <p><c>add_edge/5</c> creates (or modifies) the edge <c>E</c>
- of the digraph <c>G</c>, using <c>Label</c> as the (new)
+ <p><c>add_edge/5</c> creates (or modifies) the edge <c><anno>E</anno></c>
+ of the digraph <c><anno>G</anno></c>, using <c><anno>Label</anno></c> as the (new)
<seealso marker="#label">label</seealso> of the edge. The
edge is <seealso marker="#emanate">emanating</seealso> from
- <c>V1</c> and <seealso marker="#incident">incident</seealso>
- on <c>V2</c>. Returns <c>E</c>.
+ <c><anno>V1</anno></c> and <seealso marker="#incident">incident</seealso>
+ on <c><anno>V2</anno></c>. Returns <c><anno>E</anno></c>.
</p>
- <p><c>add_edge(G,&nbsp;V1,&nbsp;V2,&nbsp;Label)</c> is
+ <p><c>add_edge(<anno>G</anno>,&nbsp;<anno>V1</anno>,&nbsp;<anno>V2</anno>,&nbsp;<anno>Label</anno>)</c> is
equivalent to
- <c>add_edge(G,&nbsp;E,&nbsp;V1,&nbsp;V2,&nbsp;Label)</c>,
- where <c>E</c> is a created edge. The created edge is
+ <c>add_edge(<anno>G</anno>,&nbsp;<anno>E</anno>,&nbsp;<anno>V1</anno>,&nbsp;<anno>V2</anno>,&nbsp;<anno>Label</anno>)</c>,
+ where <c><anno>E</anno></c> is a created edge. The created edge is
represented by the term <c>['$e'&nbsp;|&nbsp;N]</c>, where N
is an integer&nbsp;&gt;=&nbsp;0.
</p>
- <p><c>add_edge(G,&nbsp;V1,&nbsp;V2)</c> is equivalent to
- <c>add_edge(G,&nbsp;V1,&nbsp;V2,&nbsp;[])</c>.
+ <p><c>add_edge(<anno>G</anno>,&nbsp;<anno>V1</anno>,&nbsp;<anno>V2</anno>)</c> is equivalent to
+ <c>add_edge(<anno>G</anno>,&nbsp;<anno>V1</anno>,&nbsp;<anno>V2</anno>,&nbsp;[])</c>.
</p>
<p>If the edge would create a cycle in
an <seealso marker="#acyclic_digraph">acyclic digraph</seealso>,
- then <c>{error,&nbsp;{bad_edge,&nbsp;Path}}</c> is returned. If
- either of <c>V1</c> or <c>V2</c> is not a vertex of the
- digraph <c>G</c>, then
- <c>{error,&nbsp;{bad_vertex,&nbsp;</c>V<c>}}</c> is
- returned, V&nbsp;=&nbsp;<c>V1</c> or
- V&nbsp;=&nbsp;<c>V2</c>.
+ then <c>{error,&nbsp;{bad_edge,&nbsp;<anno>Path</anno>}}</c> is returned. If
+ either of <c><anno>V1</anno></c> or <c><anno>V2</anno></c> is not a vertex of the
+ digraph <c><anno>G</anno></c>, then
+ <c>{error,&nbsp;{bad_vertex,&nbsp;</c><anno>V</anno><c>}}</c> is
+ returned, <anno>V</anno>&nbsp;=&nbsp;<c><anno>V1</anno></c> or
+ <anno>V</anno>&nbsp;=&nbsp;<c><anno>V2</anno></c>.
</p>
</desc>
</func>
<func>
- <name>add_vertex(G, V, Label) -> vertex()</name>
- <name>add_vertex(G, V) -> vertex()</name>
- <name>add_vertex(G) -> vertex()</name>
+ <name name="add_vertex" arity="1"/>
+ <name name="add_vertex" arity="2"/>
+ <name name="add_vertex" arity="3"/>
<fsummary>Add or modify a vertex of a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>V = vertex()</v>
- <v>Label = label()</v>
- </type>
<desc>
- <p><c>add_vertex/3</c> creates (or modifies) the vertex <c>V</c>
- of the digraph <c>G</c>, using <c>Label</c> as the (new)
+ <p><c>add_vertex/3</c> creates (or modifies) the vertex <c><anno>V</anno></c>
+ of the digraph <c><anno>G</anno></c>, using <c><anno>Label</anno></c> as the (new)
<seealso marker="#label">label</seealso> of the
- vertex. Returns <c>V</c>.
+ vertex. Returns <c><anno>V</anno></c>.
</p>
- <p><c>add_vertex(G,&nbsp;V)</c> is equivalent to
- <c>add_vertex(G,&nbsp;V,&nbsp;[])</c>.
+ <p><c>add_vertex(<anno>G</anno>,&nbsp;<anno>V</anno>)</c> is equivalent to
+ <c>add_vertex(<anno>G</anno>,&nbsp;<anno>V</anno>,&nbsp;[])</c>.
</p>
<p><c>add_vertex/1</c> creates a vertex using the empty list
as label, and returns the created vertex. The created vertex
@@ -157,304 +169,227 @@
</desc>
</func>
<func>
- <name>del_edge(G, E) -> true</name>
+ <name name="del_edge" arity="2"/>
<fsummary>Delete an edge from a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>E = edge()</v>
- </type>
<desc>
- <p>Deletes the edge <c>E</c> from the digraph <c>G</c>.
+ <p>Deletes the edge <c><anno>E</anno></c> from the digraph <c><anno>G</anno></c>.
</p>
</desc>
</func>
<func>
- <name>del_edges(G, Edges) -> true</name>
+ <name name="del_edges" arity="2"/>
<fsummary>Delete edges from a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>Edges = [edge()]</v>
- </type>
<desc>
- <p>Deletes the edges in the list <c>Edges</c> from the digraph
- <c>G</c>.
+ <p>Deletes the edges in the list <c><anno>Edges</anno></c> from the digraph
+ <c><anno>G</anno></c>.
</p>
</desc>
</func>
<func>
- <name>del_path(G, V1, V2) -> true</name>
+ <name name="del_path" arity="3"/>
<fsummary>Delete paths from a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>V1 = V2 = vertex()</v>
- </type>
<desc>
- <p>Deletes edges from the digraph <c>G</c> until there are no
+ <p>Deletes edges from the digraph <c><anno>G</anno></c> until there are no
<seealso marker="#path">paths</seealso> from the vertex
- <c>V1</c> to the vertex <c>V2</c>.
+ <c><anno>V1</anno></c> to the vertex <c><anno>V2</anno></c>.
</p>
<p>A sketch of the procedure employed: Find an arbitrary
<seealso marker="#simple_path">simple path</seealso>
- v[1],&nbsp;v[2],&nbsp;...,&nbsp;v[k] from <c>V1</c> to
- <c>V2</c> in <c>G</c>. Remove all edges of
- <c>G</c> <seealso marker="#emanate">emanating</seealso> from v[i]
+ v[1],&nbsp;v[2],&nbsp;...,&nbsp;v[k] from <c><anno>V1</anno></c> to
+ <c><anno>V2</anno></c> in <c><anno>G</anno></c>. Remove all edges of
+ <c><anno>G</anno></c> <seealso marker="#emanate">emanating</seealso> from v[i]
and <seealso marker="#incident">incident</seealso> to v[i+1] for
1&nbsp;&lt;=&nbsp;i&nbsp;&lt;&nbsp;k (including multiple
- edges). Repeat until there is no path between <c>V1</c> and
- <c>V2</c>.
+ edges). Repeat until there is no path between <c><anno>V1</anno></c> and
+ <c><anno>V2</anno></c>.
</p>
</desc>
</func>
<func>
- <name>del_vertex(G, V) -> true</name>
+ <name name="del_vertex" arity="2"/>
<fsummary>Delete a vertex from a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>V = vertex()</v>
- </type>
<desc>
- <p>Deletes the vertex <c>V</c> from the digraph <c>G</c>. Any
+ <p>Deletes the vertex <c><anno>V</anno></c> from the digraph <c><anno>G</anno></c>. Any
edges <seealso marker="#emanate">emanating</seealso> from
- <c>V</c> or <seealso marker="#incident">incident</seealso>
- on <c>V</c> are also deleted.
+ <c><anno>V</anno></c> or <seealso marker="#incident">incident</seealso>
+ on <c><anno>V</anno></c> are also deleted.
</p>
</desc>
</func>
<func>
- <name>del_vertices(G, Vertices) -> true</name>
+ <name name="del_vertices" arity="2"/>
<fsummary>Delete vertices from a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>Vertices = [vertex()]</v>
- </type>
<desc>
- <p>Deletes the vertices in the list <c>Vertices</c> from the
- digraph <c>G</c>.
+ <p>Deletes the vertices in the list <c><anno>Vertices</anno></c> from the
+ digraph <c><anno>G</anno></c>.
</p>
</desc>
</func>
<func>
- <name>delete(G) -> true</name>
+ <name name="delete" arity="1"/>
<fsummary>Delete a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- </type>
<desc>
- <p>Deletes the digraph <c>G</c>. This call is important
- because digraphs are implemented with <c>Ets</c>. There is
- no garbage collection of <c>Ets</c> tables. The digraph
+ <p>Deletes the digraph <c><anno>G</anno></c>. This call is important
+ because digraphs are implemented with <c>ETS</c>. There is
+ no garbage collection of <c>ETS</c> tables. The digraph
will, however, be deleted if the process that created the
digraph terminates.
</p>
</desc>
</func>
<func>
- <name>edge(G, E) -> {E, V1, V2, Label} | false</name>
+ <name name="edge" arity="2"/>
<fsummary>Return the vertices and the label of an edge of a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>E = edge()</v>
- <v>V1 = V2 = vertex()</v>
- <v>Label = label()</v>
- </type>
<desc>
- <p>Returns <c>{E,&nbsp;V1,&nbsp;V2,&nbsp;Label}</c> where
- <c>Label</c> is the <seealso marker="#label">label</seealso>
+ <p>Returns <c>{<anno>E</anno>,&nbsp;<anno>V1</anno>,&nbsp;<anno>V2</anno>,&nbsp;<anno>Label</anno>}</c> where
+ <c><anno>Label</anno></c> is the <seealso marker="#label">label</seealso>
of the edge
- <c>E</c> <seealso marker="#emanate">emanating</seealso> from
- <c>V1</c> and <seealso marker="#incident">incident</seealso> on
- <c>V2</c> of the digraph <c>G</c>.
- If there is no edge <c>E</c> of the
- digraph <c>G</c>, then <c>false</c> is returned.
+ <c><anno>E</anno></c> <seealso marker="#emanate">emanating</seealso> from
+ <c><anno>V1</anno></c> and <seealso marker="#incident">incident</seealso> on
+ <c><anno>V2</anno></c> of the digraph <c><anno>G</anno></c>.
+ If there is no edge <c><anno>E</anno></c> of the
+ digraph <c><anno>G</anno></c>, then <c>false</c> is returned.
</p>
</desc>
</func>
<func>
- <name>edges(G) -> Edges</name>
+ <name name="edges" arity="1"/>
<fsummary>Return all edges of a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>Edges = [edge()]</v>
- </type>
<desc>
- <p>Returns a list of all edges of the digraph <c>G</c>, in
+ <p>Returns a list of all edges of the digraph <c><anno>G</anno></c>, in
some unspecified order.
</p>
</desc>
</func>
<func>
- <name>edges(G, V) -> Edges</name>
+ <name name="edges" arity="2"/>
<fsummary>Return the edges emanating from or incident on a vertex of a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>V = vertex()</v>
- <v>Edges = [edge()]</v>
- </type>
<desc>
<p>Returns a list of all
edges <seealso marker="#emanate">emanating</seealso> from
- or <seealso marker="#incident">incident</seealso> on <c>V</c>
- of the digraph <c>G</c>, in some unspecified order.</p>
+ or <seealso marker="#incident">incident</seealso> on <c><anno>V</anno></c>
+ of the digraph <c><anno>G</anno></c>, in some unspecified order.</p>
</desc>
</func>
<func>
- <name>get_cycle(G, V) -> Vertices | false</name>
+ <name name="get_cycle" arity="2"/>
<fsummary>Find one cycle in a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>V1 = V2 = vertex()</v>
- <v>Vertices = [vertex()]</v>
- </type>
<desc>
<p>If there is
a <seealso marker="#simple_cycle">simple cycle</seealso> of
length two or more through the vertex
- <c>V</c>, then the cycle is returned as a list
- <c>[V,&nbsp;...,&nbsp;V]</c> of vertices, otherwise if there
+ <c><anno>V</anno></c>, then the cycle is returned as a list
+ <c>[<anno>V</anno>,&nbsp;...,&nbsp;<anno>V</anno>]</c> of vertices, otherwise if there
is a <seealso marker="#loop">loop</seealso> through
- <c>V</c>, then the loop is returned as a list <c>[V]</c>. If
- there are no cycles through <c>V</c>, then <c>false</c> is
+ <c><anno>V</anno></c>, then the loop is returned as a list <c>[<anno>V</anno>]</c>. If
+ there are no cycles through <c><anno>V</anno></c>, then <c>false</c> is
returned.
</p>
<p><c>get_path/3</c> is used for finding a simple cycle
- through <c>V</c>.
+ through <c><anno>V</anno></c>.
</p>
</desc>
</func>
<func>
- <name>get_path(G, V1, V2) -> Vertices | false</name>
+ <name name="get_path" arity="3"/>
<fsummary>Find one path in a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>V1 = V2 = vertex()</v>
- <v>Vertices = [vertex()]</v>
- </type>
<desc>
<p>Tries to find
a <seealso marker="#simple_path">simple path</seealso> from
- the vertex <c>V1</c> to the vertex
- <c>V2</c> of the digraph <c>G</c>. Returns the path as a
- list <c>[V1,&nbsp;...,&nbsp;V2]</c> of vertices, or
- <c>false</c> if no simple path from <c>V1</c> to <c>V2</c>
+ the vertex <c><anno>V1</anno></c> to the vertex
+ <c><anno>V2</anno></c> of the digraph <c><anno>G</anno></c>. Returns the path as a
+ list <c>[<anno>V1</anno>,&nbsp;...,&nbsp;<anno>V2</anno>]</c> of vertices, or
+ <c>false</c> if no simple path from <c><anno>V1</anno></c> to <c><anno>V2</anno></c>
of length one or more exists.
</p>
- <p>The digraph <c>G</c> is traversed in a depth-first manner,
+ <p>The digraph <c><anno>G</anno></c> is traversed in a depth-first manner,
and the first path found is returned.
</p>
</desc>
</func>
<func>
- <name>get_short_cycle(G, V) -> Vertices | false</name>
+ <name name="get_short_cycle" arity="2"/>
<fsummary>Find one short cycle in a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>V1 = V2 = vertex()</v>
- <v>Vertices = [vertex()]</v>
- </type>
<desc>
<p>Tries to find an as short as
possible <seealso marker="#simple_cycle">simple cycle</seealso> through
- the vertex <c>V</c> of the digraph <c>G</c>. Returns the cycle
- as a list <c>[V,&nbsp;...,&nbsp;V]</c> of vertices, or
- <c>false</c> if no simple cycle through <c>V</c> exists.
+ the vertex <c><anno>V</anno></c> of the digraph <c>G</c>. Returns the cycle
+ as a list <c>[<anno>V</anno>,&nbsp;...,&nbsp;<anno>V</anno>]</c> of vertices, or
+ <c>false</c> if no simple cycle through <c><anno>V</anno></c> exists.
Note that a <seealso marker="#loop">loop</seealso> through
- <c>V</c> is returned as the list <c>[V,&nbsp;V]</c>.
+ <c><anno>V</anno></c> is returned as the list <c>[<anno>V</anno>,&nbsp;<anno>V</anno>]</c>.
</p>
<p><c>get_short_path/3</c> is used for finding a simple cycle
- through <c>V</c>.
+ through <c><anno>V</anno></c>.
</p>
</desc>
</func>
<func>
- <name>get_short_path(G, V1, V2) -> Vertices | false</name>
+ <name name="get_short_path" arity="3"/>
<fsummary>Find one short path in a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>V1 = V2 = vertex()</v>
- <v>Vertices = [vertex()]</v>
- </type>
<desc>
<p>Tries to find an as short as
possible <seealso marker="#simple_path">simple path</seealso> from
- the vertex <c>V1</c> to the vertex <c>V2</c> of the digraph <c>G</c>.
- Returns the path as a list <c>[V1,&nbsp;...,&nbsp;V2]</c> of
- vertices, or <c>false</c> if no simple path from <c>V1</c>
- to <c>V2</c> of length one or more exists.
+ the vertex <c><anno>V1</anno></c> to the vertex <c><anno>V2</anno></c> of the digraph <c><anno>G</anno></c>.
+ Returns the path as a list <c>[<anno>V1</anno>,&nbsp;...,&nbsp;<anno>V2</anno>]</c> of
+ vertices, or <c>false</c> if no simple path from <c><anno>V1</anno></c>
+ to <c><anno>V2</anno></c> of length one or more exists.
</p>
- <p>The digraph <c>G</c> is traversed in a breadth-first
+ <p>The digraph <c><anno>G</anno></c> is traversed in a breadth-first
manner, and the first path found is returned.
</p>
</desc>
</func>
<func>
- <name>in_degree(G, V) -> integer()</name>
+ <name name="in_degree" arity="2"/>
<fsummary>Return the in-degree of a vertex of a digraph.</fsummary>
- <type>
- <v>G= digraph()</v>
- <v>V = vertex()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#in_degree">in-degree</seealso> of the vertex
- <c>V</c> of the digraph <c>G</c>.
+ <c><anno>V</anno></c> of the digraph <c><anno>G</anno></c>.
</p>
</desc>
</func>
<func>
- <name>in_edges(G, V) -> Edges</name>
+ <name name="in_edges" arity="2"/>
<fsummary>Return all edges incident on a vertex of a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>V = vertex()</v>
- <v>Edges = [edge()]</v>
- </type>
<desc>
<p>Returns a list of all
edges <seealso marker="#incident">incident</seealso> on
- <c>V</c> of the digraph <c>G</c>, in some unspecified order.
+ <c><anno>V</anno></c> of the digraph <c><anno>G</anno></c>, in some unspecified order.
</p>
</desc>
</func>
<func>
- <name>in_neighbours(G, V) -> Vertices</name>
+ <name name="in_neighbours" arity="2"/>
<fsummary>Return all in-neighbours of a vertex of a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>V = vertex()</v>
- <v>Vertices = [vertex()]</v>
- </type>
<desc>
<p>Returns a list of
all <seealso marker="#in_neighbour">in-neighbours</seealso> of
- <c>V</c> of the digraph <c>G</c>, in some unspecified order.
+ <c><anno>V</anno></c> of the digraph <c><anno>G</anno></c>, in some unspecified order.
</p>
</desc>
</func>
<func>
- <name>info(G) -> InfoList</name>
+ <name name="info" arity="1"/>
<fsummary>Return information about a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>InfoList = [{cyclicity, Cyclicity}, {memory, NoWords}, {protection, Protection}]</v>
- <v>Cyclicity = cyclic | acyclic</v>
- <v>Protection = protected | private</v>
- <v>NoWords = integer() >= 0</v>
- </type>
+ <type name="d_cyclicity"/>
+ <type name="d_protection"/>
<desc>
<p>Returns a list of <c>{Tag, Value}</c> pairs describing the
- digraph <c>G</c>. The following pairs are returned:
+ digraph <c><anno>G</anno></c>. The following pairs are returned:
</p>
<list type="bulleted">
<item>
- <p><c>{cyclicity, Cyclicity}</c>, where <c>Cyclicity</c>
+ <p><c>{cyclicity, <anno>Cyclicity</anno>}</c>, where <c><anno>Cyclicity</anno></c>
is <c>cyclic</c> or <c>acyclic</c>, according to the
options given to <c>new</c>.</p>
</item>
<item>
- <p><c>{memory, NoWords}</c>, where <c>NoWords</c> is
- the number of words allocated to the <c>ets</c> tables.</p>
+ <p><c>{memory, <anno>NoWords</anno>}</c>, where <c><anno>NoWords</anno></c> is
+ the number of words allocated to the <c>ETS</c> tables.</p>
</item>
<item>
- <p><c>{protection, Protection}</c>, where <c>Protection</c>
+ <p><c>{protection, <anno>Protection</anno>}</c>, where <c><anno>Protection</anno></c>
is <c>protected</c> or <c>private</c>, according
to the options given to <c>new</c>.</p>
</item>
@@ -462,7 +397,7 @@
</desc>
</func>
<func>
- <name>new() -> digraph()</name>
+ <name name="new" arity="0"/>
<fsummary>Return a protected empty digraph, where cycles are allowed.</fsummary>
<desc>
<p>Equivalent to <c>new([])</c>.
@@ -470,15 +405,16 @@
</desc>
</func>
<func>
- <name>new(Type) -> digraph()</name>
+ <name name="new" arity="1"/>
<fsummary>Create a new empty digraph.</fsummary>
- <type>
- <v>Type = [cyclic | acyclic | private | protected]</v>
- </type>
+ <type variable="Type"/>
+ <type name="d_type"/>
+ <type name="d_cyclicity"/>
+ <type name="d_protection"/>
<desc>
<p>Returns
an <seealso marker="#empty_digraph">empty digraph</seealso> with
- properties according to the options in <c>Type</c>:</p>
+ properties according to the options in <c><anno>Type</anno></c>:</p>
<taglist>
<tag><c>cyclic</c></tag>
<item>Allow <seealso marker="#cycle">cycles</seealso> in the
@@ -491,101 +427,72 @@
<item>The digraph can be read and modified by the creating
process only.</item>
</taglist>
- <p>If an unrecognized type option <c>T</c> is given or <c>Type</c>
+ <p>If an unrecognized type option <c>T</c> is given or <c><anno>Type</anno></c>
is not a proper list, there will be a <c>badarg</c> exception.
</p>
</desc>
</func>
<func>
- <name>no_edges(G) -> integer() >= 0</name>
+ <name name="no_edges" arity="1"/>
<fsummary>Return the number of edges of the a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- </type>
<desc>
- <p>Returns the number of edges of the digraph <c>G</c>.
+ <p>Returns the number of edges of the digraph <c><anno>G</anno></c>.
</p>
</desc>
</func>
<func>
- <name>no_vertices(G) -> integer() >= 0</name>
+ <name name="no_vertices" arity="1"/>
<fsummary>Return the number of vertices of a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- </type>
<desc>
- <p>Returns the number of vertices of the digraph <c>G</c>.
+ <p>Returns the number of vertices of the digraph <c><anno>G</anno></c>.
</p>
</desc>
</func>
<func>
- <name>out_degree(G, V) -> integer()</name>
+ <name name="out_degree" arity="2"/>
<fsummary>Return the out-degree of a vertex of a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>V = vertex()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#out_degree">out-degree</seealso> of the vertex
- <c>V</c> of the digraph <c>G</c>.
+ <c><anno>V</anno></c> of the digraph <c><anno>G</anno></c>.
</p>
</desc>
</func>
<func>
- <name>out_edges(G, V) -> Edges</name>
+ <name name="out_edges" arity="2"/>
<fsummary>Return all edges emanating from a vertex of a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>V = vertex()</v>
- <v>Edges = [edge()]</v>
- </type>
<desc>
<p>Returns a list of all
edges <seealso marker="#emanate">emanating</seealso> from
- <c>V</c> of the digraph <c>G</c>, in some unspecified order.
+ <c><anno>V</anno></c> of the digraph <c><anno>G</anno></c>, in some unspecified order.
</p>
</desc>
</func>
<func>
- <name>out_neighbours(G, V) -> Vertices</name>
+ <name name="out_neighbours" arity="2"/>
<fsummary>Return all out-neighbours of a vertex of a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>V = vertex()</v>
- <v>Vertices = [vertex()]</v>
- </type>
<desc>
<p>Returns a list of
all <seealso marker="#out_neighbour">out-neighbours</seealso> of
- <c>V</c> of the digraph <c>G</c>, in some unspecified order.
+ <c><anno>V</anno></c> of the digraph <c><anno>G</anno></c>, in some unspecified order.
</p>
</desc>
</func>
<func>
- <name>vertex(G, V) -> {V, Label} | false</name>
+ <name name="vertex" arity="2"/>
<fsummary>Return the label of a vertex of a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>V = vertex()</v>
- <v>Label = label()</v>
- </type>
<desc>
- <p>Returns <c>{V,&nbsp;Label}</c> where <c>Label</c> is the
+ <p>Returns <c>{<anno>V</anno>,&nbsp;<anno>Label</anno>}</c> where <c><anno>Label</anno></c> is the
<seealso marker="#label">label</seealso> of the vertex
- <c>V</c> of the digraph <c>G</c>, or <c>false</c> if there
- is no vertex <c>V</c> of the digraph <c>G</c>.
+ <c><anno>V</anno></c> of the digraph <c><anno>G</anno></c>, or <c>false</c> if there
+ is no vertex <c><anno>V</anno></c> of the digraph <c><anno>G</anno></c>.
</p>
</desc>
</func>
<func>
- <name>vertices(G) -> Vertices</name>
+ <name name="vertices" arity="1"/>
<fsummary>Return all vertices of a digraph.</fsummary>
- <type>
- <v>G = digraph()</v>
- <v>Vertices = [vertex()]</v>
- </type>
<desc>
- <p>Returns a list of all vertices of the digraph <c>G</c>, in
+ <p>Returns a list of all vertices of the digraph <c><anno>G</anno></c>, in
some unspecified order.
</p>
</desc>
diff --git a/lib/stdlib/doc/src/digraph_utils.xml b/lib/stdlib/doc/src/digraph_utils.xml
index 4b137456b3..e44632bfd2 100644
--- a/lib/stdlib/doc/src/digraph_utils.xml
+++ b/lib/stdlib/doc/src/digraph_utils.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2009</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -119,49 +119,43 @@
considering all edges undirected.</p>
</description>
+ <datatypes>
+ <datatype>
+ <name><marker id="type-digraph">digraph()</marker></name>
+ <desc><p>A digraph as returned by <c>digraph:new/0,1</c>.</p></desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>arborescence_root(Digraph) -> no | {yes, Root}</name>
+ <name name="arborescence_root" arity="1"/>
<fsummary>Check if a digraph is an arborescence.</fsummary>
- <type>
- <v>Digraph = digraph()</v>
- <v>Root = vertex()</v>
- </type>
<desc>
-
- <p>Returns <c>{yes, Root}</c> if <c>Root</c> is
+ <p>Returns <c>{yes, <anno>Root</anno>}</c> if <c><anno>Root</anno></c> is
the <seealso marker="#root">root</seealso> of the arborescence
- <c>Digraph</c>, <c>no</c> otherwise.
+ <c><anno>Digraph</anno></c>, <c>no</c> otherwise.
</p>
</desc>
</func>
<func>
- <name>components(Digraph) -> [Component]</name>
+ <name name="components" arity="1"/>
<fsummary>Return the components of a digraph.</fsummary>
- <type>
- <v>Digraph = digraph()</v>
- <v>Component = [vertex()]</v>
- </type>
<desc>
<p>Returns a list
of <seealso marker="#components">connected components</seealso>.
Each component is represented by its
vertices. The order of the vertices and the order of the
components are arbitrary. Each vertex of the digraph
- <c>Digraph</c> occurs in exactly one component.
+ <c><anno>Digraph</anno></c> occurs in exactly one component.
</p>
</desc>
</func>
<func>
- <name>condensation(Digraph) -> CondensedDigraph</name>
+ <name name="condensation" arity="1"/>
<fsummary>Return a condensed graph of a digraph.</fsummary>
- <type>
- <v>Digraph = CondensedDigraph = digraph()</v>
- </type>
<desc>
<p>Creates a digraph where the vertices are
the <seealso marker="#strong_components">strongly connected
- components</seealso> of <c>Digraph</c> as returned by
+ components</seealso> of <c><anno>Digraph</anno></c> as returned by
<c>strong_components/1</c>. If X and Y are strongly
connected components, and there exist vertices x and y in X
and Y respectively such that there is an
@@ -169,7 +163,7 @@
and <seealso marker="#incident">incident</seealso> on y, then
an edge emanating from X and incident on Y is created.
</p>
- <p>The created digraph has the same type as <c>Digraph</c>.
+ <p>The created digraph has the same type as <c><anno>Digraph</anno></c>.
All vertices and edges have the
default <seealso marker="#label">label</seealso> <c>[]</c>.
</p>
@@ -181,12 +175,8 @@
</desc>
</func>
<func>
- <name>cyclic_strong_components(Digraph) -> [StrongComponent]</name>
+ <name name="cyclic_strong_components" arity="1"/>
<fsummary>Return the cyclic strong components of a digraph.</fsummary>
- <type>
- <v>Digraph = digraph()</v>
- <v>StrongComponent = [vertex()]</v>
- </type>
<desc>
<p>Returns a list of <seealso marker="#strong_components">strongly
connected components</seealso>.
@@ -194,67 +184,50 @@
by its vertices. The order of the vertices and the order of
the components are arbitrary. Only vertices that are
included in some <seealso marker="#cycle">cycle</seealso> in
- <c>Digraph</c> are returned, otherwise the returned list is
+ <c><anno>Digraph</anno></c> are returned, otherwise the returned list is
equal to that returned by <c>strong_components/1</c>.
</p>
</desc>
</func>
<func>
- <name>is_acyclic(Digraph) -> bool()</name>
+ <name name="is_acyclic" arity="1"/>
<fsummary>Check if a digraph is acyclic.</fsummary>
- <type>
- <v>Digraph = digraph()</v>
- </type>
<desc>
<p>Returns <c>true</c> if and only if the digraph
- <c>Digraph</c> is <seealso marker="#acyclic_digraph">acyclic</seealso>.</p>
+ <c><anno>Digraph</anno></c> is <seealso marker="#acyclic_digraph">acyclic</seealso>.</p>
</desc>
</func>
<func>
- <name>is_arborescence(Digraph) -> bool()</name>
+ <name name="is_arborescence" arity="1"/>
<fsummary>Check if a digraph is an arborescence.</fsummary>
- <type>
- <v>Digraph = digraph()</v>
- </type>
<desc>
<p>Returns <c>true</c> if and only if the digraph
- <c>Digraph</c> is
+ <c><anno>Digraph</anno></c> is
an <seealso marker="#arborescence">arborescence</seealso>.</p>
</desc>
</func>
<func>
- <name>is_tree(Digraph) -> bool()</name>
+ <name name="is_tree" arity="1"/>
<fsummary>Check if a digraph is a tree.</fsummary>
- <type>
- <v>Digraph = digraph()</v>
- </type>
<desc>
<p>Returns <c>true</c> if and only if the digraph
- <c>Digraph</c> is
+ <c><anno>Digraph</anno></c> is
a <seealso marker="#tree">tree</seealso>.</p>
</desc>
</func>
<func>
- <name>loop_vertices(Digraph) -> Vertices</name>
+ <name name="loop_vertices" arity="1"/>
<fsummary>Return the vertices of a digraph included in some loop.</fsummary>
- <type>
- <v>Digraph = digraph()</v>
- <v>Vertices = [vertex()]</v>
- </type>
<desc>
- <p>Returns a list of all vertices of <c>Digraph</c> that are
+ <p>Returns a list of all vertices of <c><anno>Digraph</anno></c> that are
included in some <seealso marker="#loop">loop</seealso>.</p>
</desc>
</func>
<func>
- <name>postorder(Digraph) -> Vertices</name>
+ <name name="postorder" arity="1"/>
<fsummary>Return the vertices of a digraph in post-order.</fsummary>
- <type>
- <v>Digraph = digraph()</v>
- <v>Vertices = [vertex()]</v>
- </type>
<desc>
- <p>Returns all vertices of the digraph <c>Digraph</c>. The
+ <p>Returns all vertices of the digraph <c><anno>Digraph</anno></c>. The
order is given by
a <seealso marker="#depth_first_traversal">depth-first
traversal</seealso> of the digraph, collecting visited
@@ -266,14 +239,10 @@
</desc>
</func>
<func>
- <name>preorder(Digraph) -> Vertices</name>
+ <name name="preorder" arity="1"/>
<fsummary>Return the vertices of a digraph in pre-order.</fsummary>
- <type>
- <v>Digraph = digraph()</v>
- <v>Vertices = [vertex()]</v>
- </type>
<desc>
- <p>Returns all vertices of the digraph <c>Digraph</c>. The
+ <p>Returns all vertices of the digraph <c><anno>Digraph</anno></c>. The
order is given by
a <seealso marker="#depth_first_traversal">depth-first
traversal</seealso> of the digraph, collecting visited
@@ -281,119 +250,94 @@
</desc>
</func>
<func>
- <name>reachable(Vertices, Digraph) -> Vertices</name>
+ <name name="reachable" arity="2"/>
<fsummary>Return the vertices reachable from some vertices of a digraph.</fsummary>
- <type>
- <v>Digraph = digraph()</v>
- <v>Vertices = [vertex()]</v>
- </type>
<desc>
<p>Returns an unsorted list of digraph vertices such that for
each vertex in the list, there is
- a <seealso marker="#path">path</seealso> in <c>Digraph</c> from some
- vertex of <c>Vertices</c> to the vertex. In particular,
+ a <seealso marker="#path">path</seealso> in <c><anno>Digraph</anno></c> from some
+ vertex of <c><anno>Vertices</anno></c> to the vertex. In particular,
since paths may have length zero, the vertices of
- <c>Vertices</c> are included in the returned list.
+ <c><anno>Vertices</anno></c> are included in the returned list.
</p>
</desc>
</func>
<func>
- <name>reachable_neighbours(Vertices, Digraph) -> Vertices</name>
+ <name name="reachable_neighbours" arity="2"/>
<fsummary>Return the neighbours reachable from some vertices of a digraph.</fsummary>
- <type>
- <v>Digraph = digraph()</v>
- <v>Vertices = [vertex()]</v>
- </type>
<desc>
<p>Returns an unsorted list of digraph vertices such that for
each vertex in the list, there is
- a <seealso marker="#path">path</seealso> in <c>Digraph</c> of length
- one or more from some vertex of <c>Vertices</c> to the
+ a <seealso marker="#path">path</seealso> in <c><anno>Digraph</anno></c> of length
+ one or more from some vertex of <c><anno>Vertices</anno></c> to the
vertex. As a consequence, only those vertices
- of <c>Vertices</c> that are included in
+ of <c><anno>Vertices</anno></c> that are included in
some <seealso marker="#cycle">cycle</seealso> are returned.
</p>
</desc>
</func>
<func>
- <name>reaching(Vertices, Digraph) -> Vertices</name>
+ <name name="reaching" arity="2"/>
<fsummary>Return the vertices that reach some vertices of a digraph.</fsummary>
- <type>
- <v>Digraph = digraph()</v>
- <v>Vertices = [vertex()]</v>
- </type>
<desc>
<p>Returns an unsorted list of digraph vertices such that for
each vertex in the list, there is
a <seealso marker="#path">path</seealso> from the vertex to some
- vertex of <c>Vertices</c>. In particular, since paths may have
- length zero, the vertices of <c>Vertices</c> are included in
+ vertex of <c><anno>Vertices</anno></c>. In particular, since paths may have
+ length zero, the vertices of <c><anno>Vertices</anno></c> are included in
the returned list.
</p>
</desc>
</func>
<func>
- <name>reaching_neighbours(Vertices, Digraph) -> Vertices</name>
+ <name name="reaching_neighbours" arity="2"/>
<fsummary>Return the neighbours that reach some vertices of a digraph.</fsummary>
- <type>
- <v>Digraph = digraph()</v>
- <v>Vertices = [vertex()]</v>
- </type>
<desc>
<p>Returns an unsorted list of digraph vertices such that for
each vertex in the list, there is
a <seealso marker="#path">path</seealso> of length one or more
- from the vertex to some vertex of <c>Vertices</c>. As a consequence,
- only those vertices of <c>Vertices</c> that are included in
+ from the vertex to some vertex of <c><anno>Vertices</anno></c>. As a consequence,
+ only those vertices of <c><anno>Vertices</anno></c> that are included in
some <seealso marker="#cycle">cycle</seealso> are returned.
</p>
</desc>
</func>
<func>
- <name>strong_components(Digraph) -> [StrongComponent]</name>
+ <name name="strong_components" arity="1"/>
<fsummary>Return the strong components of a digraph.</fsummary>
- <type>
- <v>Digraph = digraph()</v>
- <v>StrongComponent = [vertex()]</v>
- </type>
<desc>
<p>Returns a list of <seealso marker="#strong_components">strongly
connected components</seealso>.
Each strongly component is represented
by its vertices. The order of the vertices and the order of
the components are arbitrary. Each vertex of the digraph
- <c>Digraph</c> occurs in exactly one strong component.
+ <c><anno>Digraph</anno></c> occurs in exactly one strong component.
</p>
</desc>
</func>
<func>
- <name>subgraph(Digraph, Vertices [, Options]) -> Subgraph</name>
+ <name name="subgraph" arity="2"/>
+ <name name="subgraph" arity="3"/>
<fsummary>Return a subgraph of a digraph.</fsummary>
- <type>
- <v>Digraph = Subgraph = digraph()</v>
- <v>Options = [{type, SubgraphType}, {keep_labels, bool()}]</v>
- <v>SubgraphType = inherit | type()</v>
- <v>Vertices = [vertex()]</v>
- </type>
<desc>
<p>Creates a maximal <seealso marker="#subgraph">subgraph</seealso> of <c>Digraph</c> having
- as vertices those vertices of <c>Digraph</c> that are
- mentioned in <c>Vertices</c>.
+ as vertices those vertices of <c><anno>Digraph</anno></c> that are
+ mentioned in <c><anno>Vertices</anno></c>.
</p>
<p>If the value of the option <c>type</c> is <c>inherit</c>,
- which is the default, then the type of <c>Digraph</c> is used
+ which is the default, then the type of <c><anno>Digraph</anno></c> is used
for the subgraph as well. Otherwise the option value of <c>type</c>
is used as argument to <c>digraph:new/1</c>.
</p>
<p>If the value of the option <c>keep_labels</c> is <c>true</c>,
which is the default, then
the <seealso marker="#label">labels</seealso> of vertices and edges
- of <c>Digraph</c> are used for the subgraph as well. If the value
+ of <c><anno>Digraph</anno></c> are used for the subgraph as well. If the value
is <c>false</c>, then the default label, <c>[]</c>, is used
for the subgraph's vertices and edges.
</p>
- <p><c>subgraph(Digraph, Vertices)</c> is equivalent to
- <c>subgraph(Digraph, Vertices, [])</c>.
+ <p><c>subgraph(<anno>Digraph</anno>, <anno>Vertices</anno>)</c> is equivalent to
+ <c>subgraph(<anno>Digraph</anno>, <anno>Vertices</anno>, [])</c>.
</p>
<p>There will be a <c>badarg</c> exception if any of the arguments
are invalid.
@@ -401,16 +345,12 @@
</desc>
</func>
<func>
- <name>topsort(Digraph) -> Vertices | false</name>
+ <name name="topsort" arity="1"/>
<fsummary>Return a topological sorting of the vertices of a digraph.</fsummary>
- <type>
- <v>Digraph = digraph()</v>
- <v>Vertices = [vertex()]</v>
- </type>
<desc>
<p>Returns a <seealso marker="#topsort">topological
ordering</seealso> of the vertices of the digraph
- <c>Digraph</c> if such an ordering exists, <c>false</c>
+ <c><anno>Digraph</anno></c> if such an ordering exists, <c>false</c>
otherwise. For each vertex in the returned list, there are
no <seealso marker="#out_neighbour">out-neighbours</seealso>
that occur earlier in the list.</p>
diff --git a/lib/stdlib/doc/src/epp.xml b/lib/stdlib/doc/src/epp.xml
index e6b48b270a..488499581f 100644
--- a/lib/stdlib/doc/src/epp.xml
+++ b/lib/stdlib/doc/src/epp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2010</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -38,65 +38,61 @@
by <c>compile</c> to preprocess macros and include files before
the actual parsing takes place.</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="macros"></name>
+ </datatype>
+ <datatype>
+ <name name="epp_handle"></name>
+ <desc><p>Handle to the epp server.</p></desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>open(FileName, IncludePath) -> {ok,Epp} | {error, ErrorDescriptor}</name>
- <name>open(FileName, IncludePath, PredefMacros) -> {ok,Epp} | {error, ErrorDescriptor}</name>
+ <name name="open" arity="2"/>
+ <name name="open" arity="3"/>
<fsummary>Open a file for preprocessing</fsummary>
- <type>
- <v>FileName = atom() | string()</v>
- <v>IncludePath = [DirectoryName]</v>
- <v>DirectoryName = atom() | string()</v>
- <v>PredefMacros = [{atom(),term()}]</v>
- <v>Epp = pid() -- handle to the epp server</v>
- <v>ErrorDescriptor = term()</v>
- </type>
<desc>
<p>Opens a file for preprocessing.</p>
</desc>
</func>
<func>
- <name>close(Epp) -> ok</name>
+ <name name="close" arity="1"/>
<fsummary>Close the preprocessing of the file associated with <c>Epp</c></fsummary>
- <type>
- <v>Epp = pid() -- handle to the epp server</v>
- </type>
<desc>
<p>Closes the preprocessing of a file.</p>
</desc>
</func>
<func>
- <name>parse_erl_form(Epp) -> {ok, AbsForm} | {eof, Line} | {error, ErrorInfo}</name>
+ <name name="parse_erl_form" arity="1"/>
<fsummary>Return the next Erlang form from the opened Erlang source file</fsummary>
- <type>
- <v>Epp = pid()</v>
- <v>AbsForm = term()</v>
- <v>Line = integer()</v>
- <v>ErrorInfo = see separate description below.</v>
- </type>
<desc>
<p>Returns the next Erlang form from the opened Erlang source file.
- The tuple <c>{eof, Line}</c> is returned at end-of-file. The first
+ The tuple <c>{eof, <anno>Line</anno>}</c> is returned at end-of-file. The first
form corresponds to an implicit attribute <c>-file(File,1).</c>, where
<c>File</c> is the name of the file.</p>
</desc>
</func>
<func>
- <name>parse_file(FileName,IncludePath,PredefMacro) -> {ok,[Form]} | {error,OpenError}</name>
- <fsummary>Preprocesse and parse an Erlang source file</fsummary>
- <type>
- <v>FileName = atom() | string()</v>
- <v>IncludePath = [DirectoryName]</v>
- <v>DirectoryName = atom() | string()</v>
- <v>PredefMacros = [{atom(),term()}]</v>
- <v>Form = term() -- same as returned by erl_parse:parse_form</v>
- </type>
+ <name name="parse_file" arity="3"/>
+ <fsummary>Preprocess and parse an Erlang source file</fsummary>
<desc>
<p>Preprocesses and parses an Erlang source file.
- Note that the tuple <c>{eof, Line}</c> returned at end-of-file is
+ Note that the tuple <c>{eof, <anno>Line</anno>}</c> returned at end-of-file is
included as a "form".</p>
</desc>
</func>
+ <func>
+ <name name="format_error" arity="1"/>
+ <fsummary>Format an error descriptor</fsummary>
+ <desc>
+ <p>Takes an <c><anno>ErrorDescriptor</anno></c> and returns
+ a string which
+ describes the error or warning. This function is usually
+ called implicitly when processing an <c>ErrorInfo</c>
+ structure (see below).</p>
+ </desc>
+ </func>
</funcs>
<section>
diff --git a/lib/stdlib/doc/src/erl_eval.xml b/lib/stdlib/doc/src/erl_eval.xml
index 62af23c5eb..d0622594d9 100644
--- a/lib/stdlib/doc/src/erl_eval.xml
+++ b/lib/stdlib/doc/src/erl_eval.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -36,63 +36,108 @@
<description>
<p>This module provides an interpreter for Erlang expressions. The
expressions are in the abstract syntax as returned by
- <c>erl_parse</c>, the Erlang parser, or a call to
- <c>io:parse_erl_exprs/2</c>.</p>
+ <seealso marker="erl_parse"><c>erl_parse</c></seealso>,
+ the Erlang parser, or <seealso marker="io">
+ <c>io</c></seealso>.</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="bindings"/>
+ </datatype>
+ <datatype>
+ <name name="binding_struct"/>
+ <desc><p>A binding structure.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="expression"/>
+ </datatype>
+ <datatype>
+ <name name="expressions"/>
+ <desc><p>As returned by <seealso marker="erl_parse#parse_exprs/1">
+ <c>erl_parse:parse_exprs/1</c></seealso> or
+ <seealso marker="io#parse_erl_exprs/2">
+ <c>io:parse_erl_exprs/2</c></seealso>.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="expression_list"/>
+ </datatype>
+ <datatype>
+ <name name="func_spec"/>
+ </datatype>
+ <datatype>
+ <name name="lfun_eval_handler"/>
+ </datatype>
+ <datatype>
+ <name name="lfun_value_handler"/>
+ </datatype>
+ <datatype>
+ <name name="local_function_handler"/>
+ <desc><p>Further described
+ <seealso marker="#local_function_handler">below.</seealso></p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="name"/>
+ </datatype>
+ <datatype>
+ <name name="nlfun_handler"/>
+ </datatype>
+ <datatype>
+ <name name="non_local_function_handler"/>
+ <desc><p>Further described
+ <seealso marker="#non_local_function_handler">below.</seealso></p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="value"/>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>exprs(Expressions, Bindings) -> {value, Value, NewBindings}</name>
- <name>exprs(Expressions, Bindings, LocalFunctionHandler) -> {value, Value, NewBindings}</name>
- <name>exprs(Expressions, Bindings, LocalFunctionHandler, NonlocalFunctionHandler) -> {value, Value, NewBindings}</name>
+ <name name="exprs" arity="2"/>
+ <name name="exprs" arity="3"/>
+ <name name="exprs" arity="4"/>
<fsummary>Evaluate expressions</fsummary>
- <type>
- <v>Expressions = as returned by erl_parse or io:parse_erl_exprs/2</v>
- <v>Bindings = as returned by bindings/1</v>
- <v>LocalFunctionHandler = {value, Func} | {eval, Func} | none</v>
- <v>NonlocalFunctionHandler = {value, Func} | none</v>
- </type>
<desc>
- <p>Evaluates <c>Expressions</c> with the set of bindings
- <c>Bindings</c>, where <c>Expressions</c> is a sequence of
+ <p>Evaluates <c><anno>Expressions</anno></c> with the set of bindings
+ <c><anno>Bindings</anno></c>, where <c><anno>Expressions</anno></c>
+ is a sequence of
expressions (in abstract syntax) of a type which may be
- returned by <c>io:parse_erl_exprs/2</c>. See below for an
+ returned by <seealso marker="io#parse_erl_exprs/2">
+ <c>io:parse_erl_exprs/2</c></seealso>. See below for an
explanation of how and when to use the arguments
- <c>LocalFunctionHandler</c> and <c>NonlocalFunctionHandler</c>.
+ <c><anno>LocalFunctionHandler</anno></c> and
+ <c><anno>NonLocalFunctionHandler</anno></c>.
</p>
- <p>Returns <c>{value, Value, NewBindings}</c></p>
+ <p>Returns <c>{value, <anno>Value</anno>, <anno>NewBindings</anno>}</c>
+ </p>
</desc>
</func>
<func>
- <name>expr(Expression, Bindings) -> { value, Value, NewBindings }</name>
- <name>expr(Expression, Bindings, LocalFunctionHandler) -> { value, Value, NewBindings }</name>
- <name>expr(Expression, Bindings, LocalFunctionHandler, NonlocalFunctionHandler) -> { value, Value, NewBindings }</name>
- <name>expr(Expression, Bindings, LocalFunctionHandler, NonlocalFunctionHandler, ReturnFormat) -> { value, Value, NewBindings } | Value</name>
+ <name name="expr" arity="2"/>
+ <name name="expr" arity="3"/>
+ <name name="expr" arity="4"/>
+ <name name="expr" arity="5"/>
<fsummary>Evaluate expression</fsummary>
- <type>
- <v>Expression = as returned by io:parse_erl_form/2, for example</v>
- <v>Bindings = as returned by bindings/1</v>
- <v>LocalFunctionHandler = {value, Func} | {eval, Func} | none</v>
- <v>NonlocalFunctionHandler = {value, Func} | none</v>
- <v>ReturnFormat = value | none</v>
- </type>
<desc>
- <p>Evaluates <c>Expression</c> with the set of bindings
- <c>Bindings</c>. <c>Expression</c> is an expression (in
- abstract syntax) of a type which may be returned by
- <c>io:parse_erl_form/2</c>. See below for an explanation of
+ <p>Evaluates <c><anno>Expression</anno></c> with the set of bindings
+ <c><anno>Bindings</anno></c>. <c><anno>Expression</anno></c>
+ is an expression in
+ abstract syntax. See below for an explanation of
how and when to use the arguments
- <c>LocalFunctionHandler</c> and
- <c>NonlocalFunctionHandler</c>.
+ <c><anno>LocalFunctionHandler</anno></c> and
+ <c><anno>NonLocalFunctionHandler</anno></c>.
</p>
- <p>Returns <c>{value, Value, NewBindings}</c> by default. But
- if the <c>ReturnFormat</c> is <c>value</c> only the <c>Value</c>
- is returned.</p>
+ <p>Returns <c>{value, <anno>Value</anno>,
+ <anno>NewBindings</anno>}</c> by default. But if the
+ <c><anno>ReturnFormat</anno></c> is <c>value</c> only
+ the <c><anno>Value</anno></c> is returned.</p>
</desc>
</func>
<func>
- <name>expr_list(ExpressionList, Bindings) -> {ValueList, NewBindings}</name>
- <name>expr_list(ExpressionList, Bindings, LocalFunctionHandler) -> {ValueList, NewBindings}</name>
- <name>expr_list(ExpressionList, Bindings, LocalFunctionHandler, NonlocalFunctionHandler) -> {ValueList, NewBindings}</name>
+ <name name="expr_list" arity="2"/>
+ <name name="expr_list" arity="3"/>
+ <name name="expr_list" arity="4"/>
<fsummary>Evaluate a list of expressions</fsummary>
<desc>
<p>Evaluates a list of expressions in parallel, using the same
@@ -100,18 +145,19 @@
merge the bindings returned from each evaluation. This
function is useful in the <c>LocalFunctionHandler</c>. See below.
</p>
- <p>Returns <c>{ValueList, NewBindings}</c>.</p>
+ <p>Returns <c>{<anno>ValueList</anno>, <anno>NewBindings</anno>}</c>.
+ </p>
</desc>
</func>
<func>
- <name>new_bindings() -> BindingStruct</name>
+ <name name="new_bindings" arity="0"/>
<fsummary>Return a bindings structure</fsummary>
<desc>
<p>Returns an empty binding structure.</p>
</desc>
</func>
<func>
- <name>bindings(BindingStruct) -> Bindings</name>
+ <name name="bindings" arity="1"/>
<fsummary>Return bindings</fsummary>
<desc>
<p>Returns the list of bindings contained in the binding
@@ -119,25 +165,28 @@
</desc>
</func>
<func>
- <name>binding(Name, BindingStruct) -> Binding</name>
+ <name name="binding" arity="2"/>
<fsummary>Return bindings</fsummary>
<desc>
- <p>Returns the binding of <c>Name</c> in <c>BindingStruct</c>.</p>
+ <p>Returns the binding of <c><anno>Name</anno></c>
+ in <c><anno>BindingStruct</anno></c>.</p>
</desc>
</func>
<func>
- <name>add_binding(Name, Value, Bindings) -> BindingStruct</name>
+ <name name="add_binding" arity="3"/>
<fsummary>Add a binding</fsummary>
<desc>
- <p>Adds the binding <c>Name = Value</c> to <c>Bindings</c>.
+ <p>Adds the binding <c><anno>Name</anno> = <anno>Value</anno></c>
+ to <c><anno>BindingStruct</anno></c>.
Returns an updated binding structure.</p>
</desc>
</func>
<func>
- <name>del_binding(Name, Bindings) -> BindingStruct</name>
+ <name name="del_binding" arity="2"/>
<fsummary>Delete a binding</fsummary>
<desc>
- <p>Removes the binding of <c>Name</c> in <c>Bindings</c>.
+ <p>Removes the binding of <c><anno>Name</anno></c>
+ in <c><anno>BindingStruct</anno></c>.
Returns an updated binding structure.</p>
</desc>
</func>
@@ -145,7 +194,8 @@
<section>
<title>Local Function Handler</title>
- <p>During evaluation of a function, no calls can be made to local
+ <p><marker id="local_function_handler"></marker>
+ During evaluation of a function, no calls can be made to local
functions. An undefined function error would be
generated. However, the optional argument
<c>LocalFunctionHandler</c> may be used to define a function
@@ -191,7 +241,8 @@ Func(Name, Arguments, Bindings) </code>
<section>
<title>Non-local Function Handler</title>
- <p>The optional argument <c>NonlocalFunctionHandler</c> may be
+ <p><marker id="non_local_function_handler"></marker>
+ The optional argument <c>NonlocalFunctionHandler</c> may be
used to define a function which is called in the following
cases: a functional object (fun) is called; a built-in function
is called; a function is called using the M:F syntax, where M
diff --git a/lib/stdlib/doc/src/erl_expand_records.xml b/lib/stdlib/doc/src/erl_expand_records.xml
index c93248493f..8ead438b31 100644
--- a/lib/stdlib/doc/src/erl_expand_records.xml
+++ b/lib/stdlib/doc/src/erl_expand_records.xml
@@ -39,12 +39,8 @@
</description>
<funcs>
<func>
- <name>module(AbsForms, CompileOptions) -> AbsForms</name>
+ <name name="module" arity="2"/>
<fsummary>Expand all records in a module</fsummary>
- <type>
- <v>AbsForms = [term()]</v>
- <v>CompileOptions = [term()]</v>
- </type>
<desc>
<p>Expands all records in a module. The returned module has no
references to records, neither attributes nor code.</p>
diff --git a/lib/stdlib/doc/src/erl_id_trans.xml b/lib/stdlib/doc/src/erl_id_trans.xml
index cfb18ec131..18cc2460f9 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>2010</year>
+ <year>2011</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -48,8 +48,8 @@
<name>parse_transform(Forms, Options) -> Forms</name>
<fsummary>Transform Erlang forms</fsummary>
<type>
- <v>Forms = [erlang_form()]</v>
- <v>Options = [compiler_options()]</v>
+ <v>Forms = [<seealso marker="erl_parse#type-abstract_form">erl_parse:abstract_form()</seealso>]</v>
+ <v>Options = [<seealso marker="compile#type-option">compile:option()</seealso>]</v>
</type>
<desc>
<p>Performs an identity transformation on Erlang forms, as an example.</p>
diff --git a/lib/stdlib/doc/src/erl_internal.xml b/lib/stdlib/doc/src/erl_internal.xml
index 732d77c3ae..b8d5ad73b3 100644
--- a/lib/stdlib/doc/src/erl_internal.xml
+++ b/lib/stdlib/doc/src/erl_internal.xml
@@ -42,112 +42,75 @@
</description>
<funcs>
<func>
- <name>bif(Name, Arity) -> bool()</name>
+ <name name="bif" arity="2"/>
<fsummary>Test for an Erlang BIF</fsummary>
- <type>
- <v>Name = atom()</v>
- <v>Arity = integer()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Name/Arity</c> is an Erlang BIF
+ <p>Returns <c>true</c> if <c><anno>Name</anno>/<anno>Arity</anno></c> is an Erlang BIF
which is automatically recognized by the compiler, otherwise
<c>false</c>.</p>
</desc>
</func>
<func>
- <name>guard_bif(Name, Arity) -> bool()</name>
+ <name name="guard_bif" arity="2"/>
<fsummary>Test for an Erlang BIF allowed in guards</fsummary>
- <type>
- <v>Name = atom()</v>
- <v>Arity = integer()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Name/Arity</c> is an Erlang BIF
+ <p>Returns <c>true</c> if <c><anno>Name</anno>/<anno>Arity</anno></c> is an Erlang BIF
which is allowed in guards, otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>type_test(Name, Arity) -> bool()</name>
+ <name name="type_test" arity="2"/>
<fsummary>Test for a valid type test</fsummary>
- <type>
- <v>Name = atom()</v>
- <v>Arity = integer()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Name/Arity</c> is a valid Erlang
+ <p>Returns <c>true</c> if <c><anno>Name</anno>/<anno>Arity</anno></c> is a valid Erlang
type test, otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>arith_op(OpName, Arity) -> bool()</name>
+ <name name="arith_op" arity="2"/>
<fsummary>Test for an arithmetic operator</fsummary>
- <type>
- <v>OpName = atom()</v>
- <v>Arity = integer()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>OpName/Arity</c> is an arithmetic
+ <p>Returns <c>true</c> if <c><anno>OpName</anno>/<anno>Arity</anno></c> is an arithmetic
operator, otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>bool_op(OpName, Arity) -> bool()</name>
+ <name name="bool_op" arity="2"/>
<fsummary>Test for a Boolean operator</fsummary>
- <type>
- <v>OpName = atom()</v>
- <v>Arity = integer()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>OpName/Arity</c> is a Boolean
+ <p>Returns <c>true</c> if <c><anno>OpName</anno>/<anno>Arity</anno></c> is a Boolean
operator, otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>comp_op(OpName, Arity) -> bool()</name>
+ <name name="comp_op" arity="2"/>
<fsummary>Test for a comparison operator</fsummary>
- <type>
- <v>OpName = atom()</v>
- <v>Arity = integer()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>OpName/Arity</c> is a comparison
+ <p>Returns <c>true</c> if <c><anno>OpName</anno>/<anno>Arity</anno></c> is a comparison
operator, otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>list_op(OpName, Arity) -> bool()</name>
+ <name name="list_op" arity="2"/>
<fsummary>Test for a list operator</fsummary>
- <type>
- <v>OpName = atom()</v>
- <v>Arity = integer()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>OpName/Arity</c> is a list
+ <p>Returns <c>true</c> if <c><anno>OpName</anno>/<anno>Arity</anno></c> is a list
operator, otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>send_op(OpName, Arity) -> bool()</name>
+ <name name="send_op" arity="2"/>
<fsummary>Test for a send operator</fsummary>
- <type>
- <v>OpName = atom()</v>
- <v>Arity = integer()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>OpName/Arity</c> is a send
+ <p>Returns <c>true</c> if <c><anno>OpName</anno>/<anno>Arity</anno></c> is a send
operator, otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>op_type(OpName, Arity) -> Type</name>
+ <name name="op_type" arity="2"/>
<fsummary>Return operator type</fsummary>
- <type>
- <v>OpName = atom()</v>
- <v>Arity = integer()</v>
- <v>Type = arith | bool | comp | list | send</v>
- </type>
<desc>
- <p>Returns the <c>Type</c> of operator that <c>OpName/Arity</c>
+ <p>Returns the <c><anno>Type</anno></c> of operator that <c><anno>OpName</anno>/<anno>Arity</anno></c>
belongs to,
or generates a <c>function_clause</c> error if it is not an
operator at all.</p>
diff --git a/lib/stdlib/doc/src/erl_lint.xml b/lib/stdlib/doc/src/erl_lint.xml
index 8639d678fa..b7fbdd8799 100644
--- a/lib/stdlib/doc/src/erl_lint.xml
+++ b/lib/stdlib/doc/src/erl_lint.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2010</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -60,29 +60,30 @@
functions separately unless you have written your own Erlang
compiler.</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="error_info"/>
+ </datatype>
+ <datatype>
+ <name name="error_description"/>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>module(AbsForms) -> {ok,Warnings} | {error,Errors,Warnings}</name>
- <name>module(AbsForms, FileName) -> {ok,Warnings} | {error,Errors,Warnings}</name>
- <name>module(AbsForms, FileName, CompileOptions) -> {ok,Warnings} | {error,Errors,Warnings}</name>
+ <name name="module" arity="1"/>
+ <name name="module" arity="2"/>
+ <name name="module" arity="3"/>
<fsummary>Check a module for errors</fsummary>
- <type>
- <v>AbsForms = [term()]</v>
- <v>FileName = FileName2 = atom() | string()</v>
- <v>Warnings = Errors = [{Filename2,[ErrorInfo]}]</v>
- <v>ErrorInfo = see separate description below.</v>
- <v>CompileOptions = [term()]</v>
- </type>
<desc>
<p>This function checks all the forms in a module for errors.
It returns:
</p>
<taglist>
- <tag><c>{ok,Warnings}</c></tag>
+ <tag><c>{ok,<anno>Warnings</anno>}</c></tag>
<item>
<p>There were no errors in the module.</p>
</item>
- <tag><c>{error,Errors,Warnings}</c></tag>
+ <tag><c>{error,<anno>Errors</anno>,<anno>Warnings</anno>}</c></tag>
<item>
<p>There were errors in the module.</p>
</item>
@@ -93,14 +94,14 @@
elements of <c>Options</c> that control the warnings are
only described in <seealso marker="compiler:compile#erl_lint_options">compile(3)</seealso>.
</p>
- <p>The <c>AbsForms</c> of a module which comes from a file
+ <p>The <c><anno>AbsForms</anno></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:
</p>
<code type="none">
- [{FileName2,[ErrorInfo]}] </code>
+ [{<anno>FileName2</anno>,[<anno>ErrorInfo</anno>]}] </code>
<p>The errors and warnings are listed in the order in which
they are encountered in the forms. This means that the
errors from one file may be split into different entries in
@@ -108,27 +109,20 @@
</desc>
</func>
<func>
- <name>is_guard_test(Expr) -> bool()</name>
+ <name name="is_guard_test" arity="1"/>
<fsummary>Test for a guard test</fsummary>
- <type>
- <v>Expr = term()</v>
- </type>
<desc>
- <p>This function tests if <c>Expr</c> is a legal guard test.
- <c>Expr</c> is an Erlang term representing the abstract form
+ <p>This function tests if <c><anno>Expr</anno></c> is a legal guard test.
+ <c><anno>Expr</anno></c> is an Erlang term representing the abstract form
for the expression. <c>erl_parse:parse_exprs(Tokens)</c> can
- be used to generate a list of <c>Expr</c>.</p>
+ be used to generate a list of <c><anno>Expr</anno></c>.</p>
</desc>
</func>
<func>
- <name>format_error(ErrorDescriptor) -> Chars</name>
+ <name name="format_error" arity="1"/>
<fsummary>Format an error descriptor</fsummary>
- <type>
- <v>ErrorDescriptor = errordesc()</v>
- <v>Chars = [char() | Chars]</v>
- </type>
<desc>
- <p>Takes an <c>ErrorDescriptor</c> and returns a string which
+ <p>Takes an <c><anno>ErrorDescriptor</anno></c> and returns a string which
describes the error or warning. This function is usually
called implicitly when processing an <c>ErrorInfo</c>
structure (see below).</p>
diff --git a/lib/stdlib/doc/src/erl_parse.xml b/lib/stdlib/doc/src/erl_parse.xml
index 18b592deea..bafc2e0746 100644
--- a/lib/stdlib/doc/src/erl_parse.xml
+++ b/lib/stdlib/doc/src/erl_parse.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2010</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -36,31 +36,51 @@
<description>
<p>This module is the basic Erlang parser which converts tokens into
the abstract form of either forms (i.e., top-level constructs),
- expressions, or terms. The Abstract Format is described in the ERTS
- User's Guide.
+ expressions, or terms. The Abstract Format is described in the
+ <seealso marker="erts:absform">ERTS User's Guide</seealso>.
Note that a token list must end with the <em>dot</em> token in order
to be acceptable to the parse functions (see <seealso marker="erl_scan">erl_scan(3)</seealso>).</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="abstract_clause"></name>
+ <desc><p>Parse tree for Erlang clause.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="abstract_expr"></name>
+ <desc><p>Parse tree for Erlang expression.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="abstract_form"></name>
+ <desc><p>Parse tree for Erlang form.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="error_description"></name>
+ </datatype>
+ <datatype>
+ <name name="error_info"></name>
+ </datatype>
+ <datatype>
+ <name name="token"></name>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>parse_form(Tokens) -> {ok, AbsForm} | {error, ErrorInfo}</name>
+ <name name="parse_form" arity="1"/>
<fsummary>Parse an Erlang form</fsummary>
- <type>
- <v>Tokens = [Token]</v>
- <v>Token = {Tag,Line} | {Tag,Line,term()}</v>
- <v>Tag = atom()</v>
- <v>AbsForm = term()</v>
- <v>ErrorInfo = see section Error Information below.</v>
- </type>
<desc>
- <p>This function parses <c>Tokens</c> as if it were a form. It returns:</p>
+ <p>This function parses <c><anno>Tokens</anno></c> as if it were
+ a form. It returns:</p>
<taglist>
- <tag><c>{ok, AbsForm}</c></tag>
+ <tag><c>{ok, <anno>AbsForm</anno>}</c></tag>
<item>
- <p>The parsing was successful. <c>AbsForm</c> is the
+ <p>The parsing was successful. <c><anno>AbsForm</anno></c> is the
abstract form of the parsed form.</p>
</item>
- <tag><c>{error, ErrorInfo}</c></tag>
+ <tag><c>{error, <anno>ErrorInfo</anno>}</c></tag>
<item>
<p>An error occurred.</p>
</item>
@@ -68,25 +88,18 @@
</desc>
</func>
<func>
- <name>parse_exprs(Tokens) -> {ok, Expr_list} | {error, ErrorInfo}</name>
+ <name name="parse_exprs" arity="1"/>
<fsummary>Parse Erlang expressions</fsummary>
- <type>
- <v>Tokens = [Token]</v>
- <v>Token = {Tag,Line} | {Tag,Line,term()}</v>
- <v>Tag = atom()</v>
- <v>Expr_list = [AbsExpr]</v>
- <v>AbsExpr = term()</v>
- <v>ErrorInfo = see section Error Information below.</v>
- </type>
<desc>
- <p>This function parses <c>Tokens</c> as if it were a list of expressions. It returns:</p>
+ <p>This function parses <c><anno>Tokens</anno></c> as if it were
+ a list of expressions. It returns:</p>
<taglist>
- <tag><c>{ok, Expr_list}</c></tag>
+ <tag><c>{ok, <anno>ExprList</anno>}</c></tag>
<item>
- <p>The parsing was successful. <c>Expr_list</c> is a
+ <p>The parsing was successful. <c><anno>ExprList</anno></c> is a
list of the abstract forms of the parsed expressions.</p>
</item>
- <tag><c>{error, ErrorInfo}</c></tag>
+ <tag><c>{error, <anno>ErrorInfo</anno>}</c></tag>
<item>
<p>An error occurred.</p>
</item>
@@ -94,21 +107,15 @@
</desc>
</func>
<func>
- <name>parse_term(Tokens) -> {ok, Term} | {error, ErrorInfo}</name>
+ <name name="parse_term" arity="1"/>
<fsummary>Parse an Erlang term</fsummary>
- <type>
- <v>Tokens = [Token]</v>
- <v>Token = {Tag,Line} | {Tag,Line,term()}</v>
- <v>Tag = atom()</v>
- <v>Term = term()</v>
- <v>ErrorInfo = see section Error Information below.</v>
- </type>
<desc>
- <p>This function parses <c>Tokens</c> as if it were a term. It returns:</p>
+ <p>This function parses <c><anno>Tokens</anno></c> as if it were
+ a term. It returns:</p>
<taglist>
- <tag><c>{ok, Term}</c></tag>
+ <tag><c>{ok, <anno>Term</anno>}</c></tag>
<item>
- <p>The parsing was successful. <c>Term</c> is
+ <p>The parsing was successful. <c><anno>Term</anno></c> is
the Erlang term corresponding to the token list.</p>
</item>
<tag><c>{error, ErrorInfo}</c></tag>
@@ -122,7 +129,8 @@
<name>format_error(ErrorDescriptor) -> Chars</name>
<fsummary>Format an error descriptor</fsummary>
<type>
- <v>ErrorDescriptor = errordesc()</v>
+ <v>ErrorDescriptor = <seealso
+ marker="#type-error_info">error_description()</seealso></v>
<v>Chars = [char() | Chars]</v>
</type>
<desc>
@@ -133,44 +141,32 @@
</desc>
</func>
<func>
- <name>tokens(AbsTerm) -> Tokens</name>
- <name>tokens(AbsTerm, MoreTokens) -> Tokens</name>
+ <name name="tokens" arity="1"/>
+ <name name="tokens" arity="2"/>
<fsummary>Generate a list of tokens for an expression</fsummary>
- <type>
- <v>Tokens = MoreTokens = [Token]</v>
- <v>Token = {Tag,Line} | {Tag,Line,term()}</v>
- <v>Tag = atom()</v>
- <v>AbsTerm = term()</v>
- <v>ErrorInfo = see section Error Information below.</v>
- </type>
<desc>
<p>This function generates a list of tokens representing the abstract
- form <c>AbsTerm</c> of an expression. Optionally, it appends
- <c>Moretokens</c>.</p>
+ form <c><anno>AbsTerm</anno></c> of an expression. Optionally, it
+ appends <c><anno>MoreTokens</anno></c>.</p>
</desc>
</func>
<func>
- <name>normalise(AbsTerm) -> Data</name>
+ <name name="normalise" arity="1"/>
<fsummary>Convert abstract form to an Erlang term</fsummary>
- <type>
- <v>AbsTerm = Data = term()</v>
- </type>
<desc>
- <p>Converts the abstract form <c>AbsTerm</c> of a term into a
+ <p>Converts the abstract form <c><anno>AbsTerm</anno></c> of a
+ term into a
conventional Erlang data structure (i.e., the term itself).
This is the inverse of <c>abstract/1</c>.</p>
</desc>
</func>
<func>
- <name>abstract(Data) -> AbsTerm</name>
+ <name name="abstract" arity="1"/>
<fsummary>Convert an Erlang term into an abstract form</fsummary>
- <type>
- <v>Data = AbsTerm = term()</v>
- </type>
<desc>
- <p>Converts the Erlang data structure <c>Data</c> into an
- abstract form of type <c>AbsTerm</c>. This is the inverse of
- <c>normalise/1</c>.</p>
+ <p>Converts the Erlang data structure <c><anno>Data</anno></c> into an
+ abstract form of type <c><anno>AbsTerm</anno></c>.
+ This is the inverse of <c>normalise/1</c>.</p>
</desc>
</func>
</funcs>
diff --git a/lib/stdlib/doc/src/erl_pp.xml b/lib/stdlib/doc/src/erl_pp.xml
index 1fdda48893..57b5828bcd 100644
--- a/lib/stdlib/doc/src/erl_pp.xml
+++ b/lib/stdlib/doc/src/erl_pp.xml
@@ -43,93 +43,82 @@
<p>All functions can have an optional argument which specifies a hook
that is called if an attempt is made to print an unknown form.</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="hook_function"/>
+ <desc>
+ <p>The optional argument <marker id="hook_function">
+ <c>HookFunction</c></marker>, shown in the functions described below,
+ defines a function which is called when an unknown form occurs where there
+ should be a valid expression.</p>
+
+ <p>If <c>HookFunction</c> is equal to <c>none</c> there is no hook
+ function.</p>
+
+ <p>The called hook function should return a (possibly deep) list
+ of characters. <seealso marker="#expr/4"><c>expr/4</c></seealso>
+ is useful in a hook.
+ </p>
+ <p>If <c><anno>CurrentIndentation</anno></c> is negative, there will be no line
+ breaks and only a space is used as a separator.</p>
+ </desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>form(Form) -> DeepCharList</name>
- <name>form(Form, HookFunction) -> DeepCharList</name>
+ <name name="form" arity="1"/>
+ <name name="form" arity="2"/>
<fsummary>Pretty print a form</fsummary>
- <type>
- <v>Form = term()</v>
- <v>HookFunction = see separate description below.</v>
- <v>DeepCharList = [char()|DeepCharList]</v>
- </type>
<desc>
<p>Pretty prints a
- <c>Form</c> which is an abstract form of a type which is
- returned by <c>erl_parse:parse_form</c>.</p>
+ <c><anno>Form</anno></c> which is an abstract form of a type which is
+ returned by <seealso marker="erl_parse#parse_form/1">
+ <c>erl_parse:parse_form/1</c></seealso>.</p>
</desc>
</func>
<func>
- <name>attribute(Attribute) -> DeepCharList</name>
- <name>attribute(Attribute, HookFunction) -> DeepCharList</name>
+ <name name="attribute" arity="1"/>
+ <name name="attribute" arity="2"/>
<fsummary>Pretty print an attribute</fsummary>
- <type>
- <v>Attribute = term()</v>
- <v>HookFunction = see separate description below.</v>
- <v>DeepCharList = [char()|DeepCharList]</v>
- </type>
<desc>
<p>The same as <c>form</c>, but only for the attribute
- <c>Attribute</c>.</p>
+ <c><anno>Attribute</anno></c>.</p>
</desc>
</func>
<func>
- <name>function(Function) -> DeepCharList</name>
- <name>function(Function, HookFunction) -> DeepCharList</name>
+ <name name="function" arity="1"/>
+ <name name="function" arity="2"/>
<fsummary>Pretty print a function</fsummary>
- <type>
- <v>Function = term()</v>
- <v>HookFunction = see separate description below.</v>
- <v>DeepCharList = [char()|DeepCharList]</v>
- </type>
<desc>
<p>The same as <c>form</c>, but only for the function
- <c>Function</c>.</p>
+ <c><anno>Function</anno></c>.</p>
</desc>
</func>
<func>
- <name>guard(Guard) -> DeepCharList</name>
- <name>guard(Guard, HookFunction) -> DeepCharList</name>
+ <name name="guard" arity="1"/>
+ <name name="guard" arity="2"/>
<fsummary>Pretty print a guard</fsummary>
- <type>
- <v>Form = term()</v>
- <v>HookFunction = see separate description below.</v>
- <v>DeepCharList = [char()|DeepCharList]</v>
- </type>
<desc>
<p>The same as <c>form</c>, but only for the guard test
- <c>Guard</c>.</p>
+ <c><anno>Guard</anno></c>.</p>
</desc>
</func>
<func>
- <name>exprs(Expressions) -> DeepCharList</name>
- <name>exprs(Expressions, HookFunction) -> DeepCharList</name>
- <name>exprs(Expressions, Indent, HookFunction) -> DeepCharList</name>
+ <name name="exprs" arity="1"/>
+ <name name="exprs" arity="2"/>
+ <name name="exprs" arity="3"/>
<fsummary>Pretty print <c>Expressions</c></fsummary>
- <type>
- <v>Expressions = term()</v>
- <v>HookFunction = see separate description below.</v>
- <v>Indent = integer()</v>
- <v>DeepCharList = [char()|DeepCharList]</v>
- </type>
<desc>
<p>The same as <c>form</c>, but only for the sequence of
- expressions in <c>Expressions</c>.</p>
+ expressions in <c><anno>Expressions</anno></c>.</p>
</desc>
</func>
<func>
- <name>expr(Expression) -> DeepCharList</name>
- <name>expr(Expression, HookFunction) -> DeepCharList</name>
- <name>expr(Expression, Indent, HookFunction) -> DeepCharList</name>
- <name>expr(Expression, Indent, Precedence, HookFunction) ->-> DeepCharList</name>
+ <name name="expr" arity="1"/>
+ <name name="expr" arity="2"/>
+ <name name="expr" arity="3"/>
+ <name name="expr" arity="4"/>
<fsummary>Pretty print one <c>Expression</c></fsummary>
- <type>
- <v>Expression = term()</v>
- <v>HookFunction = see separate description below.</v>
- <v>Indent = integer()</v>
- <v>Precedence = </v>
- <v>DeepCharList = [char()|DeepCharList]</v>
- </type>
<desc>
<p>This function prints one expression. It is useful for implementing hooks (see below).</p>
</desc>
@@ -137,32 +126,6 @@
</funcs>
<section>
- <title>Unknown Expression Hooks</title>
- <p>The optional argument <c>HookFunction</c>, shown in the functions described above, defines a function which is called when an unknown form occurs where there
- should be a valid expression. It can have the following formats:</p>
- <taglist>
- <tag><c>Function</c></tag>
- <item>
- <p>The hook function is called by:</p>
- <code type="none">
-Function(Expr,
- CurrentIndentation,
- CurrentPrecedence,
- HookFunction) </code>
- </item>
- <tag><c>none</c></tag>
- <item>
- <p>There is no hook function</p>
- </item>
- </taglist>
- <p>The called hook function should return a (possibly deep) list
- of characters. <c>expr/4</c> is useful in a hook.
- </p>
- <p>If <c>CurrentIndentation</c> is negative, there will be no line
- breaks and only a space is used as a separator.</p>
- </section>
-
- <section>
<title>Bugs</title>
<p>It should be possible to have hook functions for unknown forms
at places other than expressions.</p>
diff --git a/lib/stdlib/doc/src/erl_scan.xml b/lib/stdlib/doc/src/erl_scan.xml
index 1199c34f0f..54240dea19 100644
--- a/lib/stdlib/doc/src/erl_scan.xml
+++ b/lib/stdlib/doc/src/erl_scan.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2010</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -37,56 +37,96 @@
<p>This module contains functions for tokenizing characters into
Erlang tokens.</p>
</description>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-category() = atom()
-column() = integer() > 0
-line() = integer()
-location() = line() | {line(), column()}
-reserved_word_fun() -> fun(atom()) -> bool()
-set_attribute_fun() -> fun(term()) -> term()
-symbol() = atom() | float() | integer() | string()
-token() = {category(), attributes()} | {category(), attributes(), symbol()}
-attributes() = line() | list() | tuple()</code>
- </section>
+ <datatypes>
+ <datatype>
+ <name name="attribute_info"></name>
+ </datatype>
+ <datatype>
+ <name name="attributes"></name>
+ </datatype>
+ <datatype>
+ <name name="attributes_data"></name>
+ </datatype>
+ <datatype>
+ <name name="category"></name>
+ </datatype>
+ <datatype>
+ <name name="column"></name>
+ </datatype>
+ <datatype>
+ <name name="error_description"></name>
+ </datatype>
+ <datatype>
+ <name name="error_info"></name>
+ </datatype>
+ <datatype>
+ <name name="info_line"></name>
+ </datatype>
+ <datatype>
+ <name name="info_location"></name>
+ </datatype>
+ <datatype>
+ <name name="line"></name>
+ </datatype>
+ <datatype>
+ <name name="location"></name>
+ </datatype>
+ <datatype>
+ <name name="option"></name>
+ </datatype>
+ <datatype>
+ <name name="options"></name>
+ </datatype>
+ <datatype>
+ <name name="symbol"></name>
+ </datatype>
+ <datatype>
+ <name name="resword_fun"></name>
+ </datatype>
+ <datatype>
+ <name name="token"></name>
+ </datatype>
+ <datatype>
+ <name name="token_info"></name>
+ </datatype>
+ <datatype>
+ <name name="tokens"></name>
+ </datatype>
+ <datatype>
+ <name name="tokens_result"></name>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>string(String) -> Return</name>
- <name>string(String, StartLocation) -> Return</name>
- <name>string(String, StartLocation, Options) -> Return</name>
+ <name name="string" arity="1"/>
+ <name name="string" arity="2"/>
+ <name name="string" arity="3"/>
<fsummary>Scan a string and return the Erlang tokens</fsummary>
- <type>
- <v>String = string()</v>
- <v>Return = {ok, Tokens, EndLocation} | Error</v>
- <v>Tokens = [token()]</v>
- <v>Error = {error, ErrorInfo, EndLocation}</v>
- <v>StartLocation = EndLocation = location()</v>
- <v>Options = Option | [Option]</v>
- <v>Option = {reserved_word_fun,reserved_word_fun()}
- | return_comments | return_white_spaces | return
- | text</v>
- </type>
<desc>
- <p>Takes the list of characters <c>String</c> and tries to
- scan (tokenize) them. Returns <c>{ok, Tokens, EndLocation}</c>,
- where <c>Tokens</c> are the Erlang tokens from
- <c>String</c>. <c>EndLocation</c> is the first location
- after the last token.</p>
- <p><c>{error, ErrorInfo, EndLocation}</c> is returned if an
- error occurs. <c>EndLocation</c> is the first location after
+ <p>Takes the list of characters <c><anno>String</anno></c> and tries to
+ scan (tokenize) them. Returns <c>{ok, <anno>Tokens</anno>,
+ <anno>EndLocation</anno>}</c>,
+ where <c><anno>Tokens</anno></c> are the Erlang tokens from
+ <c><anno>String</anno></c>. <c><anno>EndLocation</anno></c>
+ is the first location after the last token.</p>
+ <p><c>{error, <anno>ErrorInfo</anno>, <anno>ErrorLocation</anno>}</c>
+ is returned if an error occurs.
+ <c><anno>ErrorLocation</anno></c> is the first location after
the erroneous token.</p>
- <p><c>string(String)</c> is equivalent to
- <c>string(String, 1)</c>, and <c>string(String,
- StartLocation)</c> is equivalent to <c>string(String,
- StartLocation, [])</c>.</p>
- <p><c>StartLocation</c> indicates the initial location when
- scanning starts. If <c>StartLocation</c> is a line
- <c>attributes()</c> as well as <c>EndLocation</c> and
- <c>ErrorLocation</c> will be lines. If
- <c>StartLocation</c> is a pair of a line and a column
+ <p><c>string(<anno>String</anno>)</c> is equivalent to
+ <c>string(<anno>String</anno>, 1)</c>, and
+ <c>string(<anno>String</anno>,
+ <anno>StartLocation</anno>)</c> is equivalent to
+ <c>string(<anno>String</anno>,
+ <anno>StartLocation</anno>, [])</c>.</p>
+ <p><c><anno>StartLocation</anno></c> indicates the initial location
+ when scanning starts. If <c><anno>StartLocation</anno></c> is a line
+ <c>attributes()</c> as well as <c><anno>EndLocation</anno></c> and
+ <c><anno>ErrorLocation</anno></c> will be lines. If
+ <c><anno>StartLocation</anno></c> is a pair of a line and a column
<c>attributes()</c> takes the form of an opaque compound
- data type, and <c>EndLocation</c> and <c>ErrorLocation</c>
+ data type, and <c><anno>EndLocation</anno></c> and
+ <c><anno>ErrorLocation</anno></c>
will be pairs of a line and a column. The <em>token
attributes</em> contain information about the column and the
line where the token begins, as well as the text of the
@@ -134,148 +174,130 @@ attributes() = line() | list() | tuple()</code>
</desc>
</func>
<func>
- <name>tokens(Continuation, CharSpec, StartLocation) -> Return</name>
- <name>tokens(Continuation, CharSpec, StartLocation, Options) -> Return</name>
+ <name name="tokens" arity="3"/>
+ <name name="tokens" arity="4"/>
+ <type name="char_spec"/>
+ <type name="return_cont"/>
+ <type_desc name="return_cont">An opaque continuation</type_desc>
<fsummary>Re-entrant scanner</fsummary>
- <type>
- <v>Continuation = [] | Continuation1</v>
- <v>Return = {done, Result, LeftOverChars} | {more, Continuation1}</v>
- <v>LeftOverChars = CharSpec</v>
- <v>CharSpec = string() | eof</v>
- <v>Continuation1 = tuple()</v>
- <v>Result = {ok, Tokens, EndLocation} | {eof, EndLocation} | Error</v>
- <v>Tokens = [token()]</v>
- <v>Error = {error, ErrorInfo, EndLocation}</v>
- <v>StartLocation = EndLocation = location()</v>
- <v>Options = Option | [Option]</v>
- <v>Option = {reserved_word_fun,reserved_word_fun()}
- | return_comments | return_white_spaces | return
- | text</v>
- </type>
<desc>
<p>This is the re-entrant scanner which scans characters until
a <em>dot</em> ('.' followed by a white space) or
<c>eof</c> has been reached. It returns:</p>
<taglist>
- <tag><c>{done, Result, LeftOverChars}</c></tag>
+ <tag><c>{done, <anno>Result</anno>, <anno>LeftOverChars</anno>}</c>
+ </tag>
<item>
<p>This return indicates that there is sufficient input
- data to get a result. <c>Result</c> is:</p>
+ data to get a result. <c><anno>Result</anno></c> is:</p>
<taglist>
- <tag><c>{ok, Tokens, EndLocation}</c></tag>
+ <tag><c>{ok, Tokens, EndLocation}</c>
+ </tag>
<item>
- <p>The scanning was successful. <c>Tokens</c> is the
- list of tokens including <em>dot</em>.</p>
+ <p>The scanning was successful. <c>Tokens</c>
+ is the list of tokens including <em>dot</em>.</p>
</item>
<tag><c>{eof, EndLocation}</c></tag>
<item>
<p>End of file was encountered before any more tokens.</p>
</item>
- <tag><c>{error, ErrorInfo, EndLocation}</c></tag>
+ <tag><c>{error, ErrorInfo, EndLocation}</c>
+ </tag>
<item>
- <p>An error occurred. <c>LeftOverChars</c> is the remaining
- characters of the input data,
+ <p>An error occurred. <c><anno>LeftOverChars</anno></c>
+ is the remaining characters of the input data,
starting from <c>EndLocation</c>.</p>
</item>
</taglist>
</item>
- <tag><c>{more, Continuation1}</c></tag>
+ <tag><c>{more, <anno>Continuation1</anno>}</c></tag>
<item>
<p>More data is required for building a term.
- <c>Continuation1</c> must be passed in a new call to
+ <c><anno>Continuation1</anno></c> must be passed in a new call to
<c>tokens/3,4</c> when more data is available.</p>
</item>
</taglist>
- <p>The <c>CharSpec</c> <c>eof</c> signals end of file.
- <c>LeftOverChars</c> will then take the value <c>eof</c> as
- well.</p>
- <p><c>tokens(Continuation, CharSpec, StartLocation)</c> is
- equivalent to <c>tokens(Continuation, CharSpec,
- StartLocation, [])</c>.</p>
+ <p>The <c><anno>CharSpec</anno></c> <c>eof</c> signals end of file.
+ <c><anno>LeftOverChars</anno></c> will then take the value <c>eof</c>
+ as well.</p>
+ <p><c>tokens(<anno>Continuation</anno>, <anno>CharSpec</anno>,
+ <anno>StartLocation</anno>)</c> is equivalent to
+ <c>tokens(<anno>Continuation</anno>, <anno>CharSpec</anno>,
+ <anno>StartLocation</anno>, [])</c>.</p>
<p>See <seealso marker="#string/3">string/3</seealso> for a
description of the various options.</p>
</desc>
</func>
<func>
- <name>reserved_word(Atom) -> bool()</name>
+ <name name="reserved_word" arity="1"/>
<fsummary>Test for a reserved word</fsummary>
- <type>
- <v>Atom = atom()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Atom</c> is an Erlang reserved
- word, otherwise <c>false</c>.</p>
+ <p>Returns <c>true</c> if <c><anno>Atom</anno></c> is an Erlang
+ reserved word, otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>token_info(Token) -> TokenInfo</name>
+ <name name="token_info" arity="1"/>
<fsummary>Return information about a token</fsummary>
- <type>
- <v>Token = token()</v>
- <v>TokenInfo = [TokenInfoTuple]</v>
- <v>TokenInfoTuple = {TokenItem, Info}</v>
- <v>TokenItem = atom()</v>
- <v>Info = term()</v>
- </type>
<desc>
<p>Returns a list containing information about the token
- <c>Token</c>. The order of the <c>TokenInfoTuple</c>s is not
- defined. The following <c>TokenItem</c>s are returned:
- <c>category</c>, <c>column</c>, <c>length</c>,
- <c>line</c>, <c>symbol</c>, and <c>text</c>. See <seealso
+ <c><anno>Token</anno></c>. The order of the
+ <c><anno>TokenInfoTuple</anno></c>s is not
+ defined. See <seealso
marker="#token_info/2">token_info/2</seealso> for
information about specific
- <c>TokenInfoTuple</c>s.</p>
+ <c><anno>TokenInfoTuple</anno></c>s.</p>
<p>Note that if <c>token_info(Token, TokenItem)</c> returns
- <c>undefined</c> for some <c>TokenItem</c> in the list above, the
- item is not included in <c>TokenInfo</c>.</p>
+ <c>undefined</c> for some <c>TokenItem</c>, the
+ item is not included in <c><anno>TokenInfo</anno></c>.</p>
</desc>
</func>
<func>
- <name>token_info(Token, TokenItemSpec) -> TokenInfo</name>
+ <name name="token_info" arity="2" clause_i="1"/>
+ <name name="token_info" arity="2" clause_i="2"/>
+ <type name="token_item"/>
+ <type name="attribute_item"/>
<fsummary>Return information about a token</fsummary>
- <type>
- <v>Token = token()</v>
- <v>TokenItemSpec = TokenItem | [TokenItem]</v>
- <v>TokenInfo = TokenInfoTuple | undefined | [TokenInfoTuple]</v>
- <v>TokenInfoTuple = {TokenItem, Info}</v>
- <v>TokenItem = atom()</v>
- <v>Info = term()</v>
- </type>
<desc>
<p>Returns a list containing information about the token
- <c>Token</c>. If <c>TokenItemSpec</c> is a single
- <c>TokenItem</c>, the returned value is the corresponding
+ <c><anno>Token</anno></c>. If one single
+ <c><anno>TokenItem</anno></c> is given the returned value is
+ the corresponding
<c>TokenInfoTuple</c>, or <c>undefined</c> if the
- <c>TokenItem</c> has no value. If <c>TokenItemSpec</c> is a
- list of
- <c>TokenItem</c>, the result is a list of
- <c>TokenInfoTuple</c>. The <c>TokenInfoTuple</c>s will
- appear with the corresponding
- <c>TokenItem</c>s in the same order as the <c>TokenItem</c>s
- appeared in the list of <c>TokenItem</c>s. <c>TokenItem</c>s
- with no value are not included in the list of
- <c>TokenInfoTuple</c>.</p>
- <p>The following <c>TokenInfoTuple</c>s with corresponding
- <c>TokenItem</c>s are valid:</p>
+ <c>TokenItem</c> has no value. If a list of
+ <c><anno>TokenItem</anno></c>s is given the result is a list of
+ <c><anno>TokenInfoTuple</anno></c>. The
+ <c><anno>TokenInfoTuple</anno></c>s will
+ appear with the corresponding <c><anno>TokenItem</anno></c>s in
+ the same order as the <c><anno>TokenItem</anno></c>s
+ appear in the list of <c>TokenItem</c>s.
+ <c><anno>TokenItem</anno></c>s with no value are not included
+ in the list of <c><anno>TokenInfoTuple</anno></c>.</p>
+ <p>The following <c><anno>TokenInfoTuple</anno></c>s with corresponding
+ <c><anno>TokenItem</anno></c>s are valid:</p>
<taglist>
- <tag><c>{category, category()}</c></tag>
+ <tag><c>{category, <seealso marker="#type-category">
+ category()</seealso>}</c></tag>
<item><p>The category of the token.</p>
</item>
- <tag><c>{column, column()}</c></tag>
+ <tag><c>{column, <seealso marker="#type-column">
+ column()</seealso>}</c></tag>
<item><p>The column where the token begins.</p>
</item>
<tag><c>{length, integer() > 0}</c></tag>
<item><p>The length of the token's text.</p>
</item>
- <tag><c>{line, line()}</c></tag>
+ <tag><c>{line, <seealso marker="#type-line">
+ line()</seealso>}</c></tag>
<item><p>The line where the token begins.</p>
</item>
- <tag><c>{location, location()}</c></tag>
+ <tag><c>{location, <seealso marker="#type-location">
+ location()</seealso>}</c></tag>
<item><p>The line and column where the token begins, or
just the line if the column unknown.</p>
</item>
- <tag><c>{symbol, symbol()}</c></tag>
+ <tag><c>{symbol, <seealso marker="#type-symbol">
+ symbol()</seealso>}</c></tag>
<item><p>The token's symbol.</p>
</item>
<tag><c>{text, string()}</c></tag>
@@ -285,70 +307,59 @@ attributes() = line() | list() | tuple()</code>
</desc>
</func>
<func>
- <name>attributes_info(Attributes) -> AttributesInfo</name>
+ <name name="attributes_info" arity="1"/>
<fsummary>Return information about token attributes</fsummary>
- <type>
- <v>Attributes = attributes()</v>
- <v>AttributesInfo = [AttributeInfoTuple]</v>
- <v>AttributeInfoTuple = {AttributeItem, Info}</v>
- <v>AttributeItem = atom()</v>
- <v>Info = term()</v>
- </type>
<desc>
<p>Returns a list containing information about the token
- attributes <c>Attributes</c>. The order of the
- <c>AttributeInfoTuple</c>s is not defined. The following
- <c>AttributeItem</c>s are returned:
- <c>column</c>, <c>length</c>, <c>line</c>, and <c>text</c>.
+ attributes <c><anno>Attributes</anno></c>. The order of the
+ <c><anno>AttributeInfoTuple</anno></c>s is not defined.
See <seealso
marker="#attributes_info/2">attributes_info/2</seealso> for
information about specific
- <c>AttributeInfoTuple</c>s.</p>
+ <c><anno>AttributeInfoTuple</anno></c>s.</p>
<p>Note that if <c>attributes_info(Token, AttributeItem)</c>
returns <c>undefined</c> for some <c>AttributeItem</c> in
the list above, the item is not included in
- <c>AttributesInfo</c>.</p>
+ <c><anno>AttributesInfo</anno></c>.</p>
</desc>
</func>
<func>
- <name>attributes_info(Attributes, AttributeItemSpec) -> AttributesInfo</name>
+ <name name="attributes_info" arity="2" clause_i="1"/>
+ <name name="attributes_info" arity="2" clause_i="2"/>
<fsummary>Return information about a token attributes</fsummary>
- <type>
- <v>Attributes = attributes()</v>
- <v>AttributeItemSpec = AttributeItem | [AttributeItem]</v>
- <v>AttributesInfo = AttributeInfoTuple | undefined
- | [AttributeInfoTuple]</v>
- <v>AttributeInfoTuple = {AttributeItem, Info}</v>
- <v>AttributeItem = atom()</v>
- <v>Info = term()</v>
- </type>
+ <type name="attribute_item"/>
<desc>
<p>Returns a list containing information about the token
- attributes <c>Attributes</c>. If <c>AttributeItemSpec</c> is
- a single <c>AttributeItem</c>, the returned value is the
- corresponding <c>AttributeInfoTuple</c>, or <c>undefined</c>
- if the <c>AttributeItem</c> has no value. If
- <c>AttributeItemSpec</c> is a list of
- <c>AttributeItem</c>, the result is a list of
- <c>AttributeInfoTuple</c>. The <c>AttributeInfoTuple</c>s
- will appear with the corresponding <c>AttributeItem</c>s in
- the same order as the <c>AttributeItem</c>s appeared in the
- list of <c>AttributeItem</c>s. <c>AttributeItem</c>s with no
+ attributes <c><anno>Attributes</anno></c>. If one single
+ <c><anno>AttributeItem</anno></c> is given the returned value is the
+ corresponding <c><anno>AttributeInfoTuple</anno></c>,
+ or <c>undefined</c> if the <c><anno>AttributeItem</anno></c>
+ has no value. If a list of <c><anno>AttributeItem</anno></c>
+ is given the result is a list of
+ <c><anno>AttributeInfoTuple</anno></c>.
+ The <c><anno>AttributeInfoTuple</anno></c>s
+ will appear with the corresponding <c><anno>AttributeItem</anno></c>s
+ in the same order as the <c><anno>AttributeItem</anno></c>s
+ appear in the list of <c><anno>AttributeItem</anno></c>s.
+ <c><anno>AttributeItem</anno></c>s with no
value are not included in the list of
- <c>AttributeInfoTuple</c>.</p>
- <p>The following <c>AttributeInfoTuple</c>s with corresponding
- <c>AttributeItem</c>s are valid:</p>
+ <c><anno>AttributeInfoTuple</anno></c>.</p>
+ <p>The following <c><anno>AttributeInfoTuple</anno></c>s with
+ corresponding <c><anno>AttributeItem</anno></c>s are valid:</p>
<taglist>
- <tag><c>{column, column()}</c></tag>
+ <tag><c>{column, <seealso marker="#type-column">
+ column()</seealso>}</c></tag>
<item><p>The column where the token begins.</p>
</item>
<tag><c>{length, integer() > 0}</c></tag>
<item><p>The length of the token's text.</p>
</item>
- <tag><c>{line, line()}</c></tag>
+ <tag><c>{line, <seealso marker="#type-line">
+ line()</seealso>}</c></tag>
<item><p>The line where the token begins.</p>
</item>
- <tag><c>{location, location()}</c></tag>
+ <tag><c>{location, <seealso marker="#type-location">
+ location()</seealso>}</c></tag>
<item><p>The line and column where the token begins, or
just the line if the column unknown.</p>
</item>
@@ -359,29 +370,22 @@ attributes() = line() | list() | tuple()</code>
</desc>
</func>
<func>
- <name>set_attribute(AttributeItem, Attributes, SetAttributeFun) -> AttributesInfo</name>
+ <name name="set_attribute" arity="3"/>
<fsummary>Set a token attribute value</fsummary>
- <type>
- <v>AttributeItem = line</v>
- <v>Attributes = attributes()</v>
- <v>SetAttributeFun = set_attribute_fun()</v>
- </type>
<desc>
<p>Sets the value of the <c>line</c> attribute of the token
- attributes <c>Attributes</c>.</p>
- <p>The <c>SetAttributeFun</c> is called with the value of
+ attributes <c><anno>Attributes</anno></c>.</p>
+ <p>The <c><anno>SetAttributeFun</anno></c> is called with the value of
the <c>line</c> attribute, and is to return the new value of
the <c>line</c> attribute.</p>
</desc>
</func>
<func>
- <name>format_error(ErrorDescriptor) -> string()</name>
+ <name name="format_error" arity="1"/>
<fsummary>Format an error descriptor</fsummary>
- <type>
- <v>ErrorDescriptor = errordesc()</v>
- </type>
<desc>
- <p>Takes an <c>ErrorDescriptor</c> and returns a string which
+ <p>Takes an <c><anno>ErrorDescriptor</anno></c> and returns
+ a string which
describes the error or warning. This function is usually
called implicitly when processing an <c>ErrorInfo</c>
structure (see below).</p>
diff --git a/lib/stdlib/doc/src/erl_tar.xml b/lib/stdlib/doc/src/erl_tar.xml
index 929620bb88..fe166dbd01 100644
--- a/lib/stdlib/doc/src/erl_tar.xml
+++ b/lib/stdlib/doc/src/erl_tar.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2003</year><year>2009</year>
+ <year>2003</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -89,9 +89,8 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>The <marker id="add"></marker>
-<c>add/3</c> function adds a file to a tar file
- that has been opened for writing by
+ <p>The <marker id="add"></marker><c>add/3</c> function adds
+ a file to a tar file that has been opened for writing by
<seealso marker="#open">open/1</seealso>.</p>
<taglist>
<tag><c>dereference</c></tag>
@@ -138,8 +137,8 @@
<v>TarDescriptor = term()</v>
</type>
<desc>
- <p>The <marker id="close"></marker>
-<c>close/1</c> function closes a tar file
+ <p>The <marker id="close"></marker><c>close/1</c> function
+ closes a tar file
opened by <seealso marker="#open">open/1</seealso>.</p>
</desc>
</func>
@@ -151,11 +150,12 @@
<v>FileList = [Filename|{NameInArchive, binary()},{NameInArchive, Filename}]</v>
<v>Filename = filename()</v>
<v>NameInArchive = filename()</v>
- <v>RetValue = ok|{error,{Name,Reason}} &lt;V>Reason = term()</v>
+ <v>RetValue = ok|{error,{Name,Reason}}</v>
+ <v>Reason = term()</v>
</type>
<desc>
- <p>The <marker id="create_2"></marker>
-<c>create/2</c> function creates a tar file and
+ <p>The <marker id="create_2"></marker><c>create/2</c> function
+ creates a tar file and
archives the files whose names are given in <c>FileList</c> into it.
The files may either be read from disk or given as
binaries.</p>
@@ -171,11 +171,11 @@
<v>NameInArchive = filename()</v>
<v>OptionList = [Option]</v>
<v>Option = compressed|cooked|dereference|verbose</v>
- <v>RetValue = ok|{error,{Name,Reason}} &lt;V>Reason = term()</v>
+ <v>RetValue = ok|{error,{Name,Reason}}</v>
+ <v>Reason = term()</v>
</type>
<desc>
- <p>The <marker id="create_3"></marker>
-<c>create/3</c> function
+ <p>The <marker id="create_3"></marker><c>create/3</c> function
creates a tar file and archives the files whose names are given
in <c>FileList</c> into it. The files may either be read from
disk or given as binaries.</p>
@@ -220,9 +220,8 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>The <marker id="extract_1"></marker>
-<c>extract/1</c> function extracts
- all files from a tar archive.</p>
+ <p>The <marker id="extract_1"></marker><c>extract/1</c> function
+ extracts all files from a tar archive.</p>
<p>If the <c>Name</c> argument is given as "<c>{binary,Binary}</c>",
the contents of the binary is assumed to be a tar archive.
</p>
@@ -250,9 +249,8 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>The <marker id="extract_2"></marker>
-<c>extract/2</c> function extracts
- files from a tar archive.</p>
+ <p>The <marker id="extract_2"></marker><c>extract/2</c> function
+ extracts files from a tar archive.</p>
<p>If the <c>Name</c> argument is given as "<c>{binary,Binary}</c>",
the contents of the binary is assumed to be a tar archive.
</p>
@@ -322,8 +320,8 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>The <marker id="format_error_1"></marker>
-<c>format_error/1</c> converts
+ <p>The <marker id="format_error_1"></marker><c>format_error/1</c>
+ function converts
an error reason term to a human-readable error message string.</p>
</desc>
</func>
@@ -339,8 +337,8 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>The <marker id="open"></marker>
-<c>open/2</c> function creates a tar file for writing.
+ <p>The <marker id="open"></marker><c>open/2</c> function creates
+ a tar file for writing.
(Any existing file with the same name will be truncated.)</p>
<p>By convention, the name of a tar file should end in "<c>.tar</c>".
To abide to the convention, you'll need to add "<c>.tar</c>" yourself
@@ -373,7 +371,6 @@
You should not rely on the specific contents of the <c>TarDescriptor</c>
term, as it may change in future versions as more features are added
to the <c>erl_tar</c> module.</p>
- <p></p>
</warning>
</desc>
</func>
@@ -386,9 +383,8 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>The <marker id="table_1"></marker>
-<c>table/1</c> function retrieves
- the names of all files in the tar file <c>Name</c>.</p>
+ <p>The <marker id="table_1"></marker><c>table/1</c> function
+ retrieves the names of all files in the tar file <c>Name</c>.</p>
</desc>
</func>
<func>
@@ -398,9 +394,8 @@
<v>Name = filename()</v>
</type>
<desc>
- <p>The <marker id="table_2"></marker>
-<c>table/2</c> function retrieves
- the names of all files in the tar file <c>Name</c>.</p>
+ <p>The <marker id="table_2"></marker><c>table/2</c> function
+ retrieves the names of all files in the tar file <c>Name</c>.</p>
</desc>
</func>
<func>
@@ -410,8 +405,7 @@
<v>Name = filename()</v>
</type>
<desc>
- <p>The <marker id="t_1"></marker>
-<c>t/1</c> function prints the names
+ <p>The <marker id="t_1"></marker><c>t/1</c> function prints the names
of all files in the tar file <c>Name</c> to the Erlang shell.
(Similar to "<c>tar&nbsp;t</c>".)</p>
</desc>
@@ -423,8 +417,8 @@
<v>Name = filename()</v>
</type>
<desc>
- <p>The <marker id="tt_1"></marker>
-<c>tt/1</c> function prints names and
+ <p>The <marker id="tt_1"></marker><c>tt/1</c> function prints
+ names and
information about all files in the tar file <c>Name</c> to
the Erlang shell. (Similar to "<c>tar&nbsp;tv</c>".)</p>
</desc>
diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml
index 746f94d3f4..efd9514db6 100644
--- a/lib/stdlib/doc/src/ets.xml
+++ b/lib/stdlib/doc/src/ets.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2010</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -126,15 +126,30 @@
<em>ERTS User's Guide</em>.</p>
</section>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-match_spec()
- a match specification, see above
-
-tid()
- a table identifier, as returned by new/2</code>
- </section>
+ <datatypes>
+ <datatype>
+ <name><marker id="type-continuation">continuation()</marker></name>
+ <desc>
+ <p>Opaque continuation used by <seealso marker="#select/1">
+ <c>select/1</c></seealso> and <seealso marker="#select/3">
+ <c>select/3</c></seealso>.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="match_spec"/>
+ <desc><p>A match specification, see above.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="match_pattern"/>
+ </datatype>
+ <datatype>
+ <name name="tab"/>
+ </datatype>
+ <datatype>
+ <name name="tid"/>
+ <desc><p>A table identifier, as returned by new/2.</p></desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
<name>all() -> [Tab]</name>
@@ -197,37 +212,25 @@ tid()
</desc>
</func>
<func>
- <name>file2tab(Filename) -> {ok,Tab} | {error,Reason}</name>
+ <name name="file2tab" arity="1"/>
<fsummary>Read an ETS table from a file.</fsummary>
- <type>
- <v>Filename = string() | atom()</v>
- <v>Tab = tid() | atom()</v>
- <v>Reason = term()</v>
- </type>
<desc>
<p>Reads a file produced by <seealso
marker="#tab2file/2">tab2file/2</seealso> or
<seealso marker="#tab2file/3">tab2file/3</seealso> and creates the
- corresponding table <c>Tab</c>.</p>
- <p>Equivalent to <c>file2tab(Filename,[])</c>.</p>
+ corresponding table <c><anno>Tab</anno></c>.</p>
+ <p>Equivalent to <c>file2tab(<anno>Filename</anno>, [])</c>.</p>
</desc>
</func>
<func>
- <name>file2tab(Filename,Options) -> {ok,Tab} | {error,Reason}</name>
+ <name name="file2tab" arity="2"/>
<fsummary>Read an ETS table from a file.</fsummary>
- <type>
- <v>Filename = string() | atom()</v>
- <v>Tab = tid() | atom()</v>
- <v>Options = [Option]</v>
- <v>Option = {verify, bool()}</v>
- <v>Reason = term()</v>
- </type>
<desc>
<p>Reads a file produced by <seealso
marker="#tab2file/2">tab2file/2</seealso> or
<seealso marker="#tab2file/3">tab2file/3</seealso> and creates the
- corresponding table <c>Tab</c>.</p>
- <p>The currently only supported option is <c>{verify,bool()}</c>. If
+ corresponding table <c><anno>Tab</anno></c>.</p>
+ <p>The currently only supported option is <c>{verify,boolean()}</c>. If
verification is turned on (by means of specifying
<c>{verify,true}</c>), the function utilizes whatever
information is present in the file to assert that the
@@ -271,70 +274,52 @@ tid()
</desc>
</func>
<func>
- <name>foldl(Function, Acc0, Tab) -> Acc1</name>
+ <name name="foldl" arity="3"/>
<fsummary>Fold a function over an ETS table</fsummary>
- <type>
- <v>Function = fun(A, AccIn) -> AccOut</v>
- <v>Tab = tid() | atom()</v>
- <v>Acc0 = Acc1 = AccIn = AccOut = term()</v>
- </type>
<desc>
- <p><c>Acc0</c> is returned if the table is empty.
+ <p><c><anno>Acc0</anno></c> is returned if the table is empty.
This function is similar to <c>lists:foldl/3</c>. The order in
which the elements of the table are traversed is unspecified,
except for tables of type <c>ordered_set</c>, for which they
are traversed first to last.</p>
- <p>If <c>Function</c> inserts objects into the table, or another
+ <p>If <c><anno>Function</anno></c> inserts objects into the table, or another
process inserts objects into the table, those objects <em>may</em>
(depending on key ordering) be included in the traversal.</p>
</desc>
</func>
<func>
- <name>foldr(Function, Acc0, Tab) -> Acc1</name>
+ <name name="foldr" arity="3"/>
<fsummary>Fold a function over an ETS table</fsummary>
- <type>
- <v>Function = fun(A, AccIn) -> AccOut</v>
- <v>Tab = tid() | atom()</v>
- <v>Acc0 = Acc1 = AccIn = AccOut = term()</v>
- </type>
<desc>
- <p><c>Acc0</c> is returned if the table is empty.
+ <p><c><anno>Acc0</anno></c> is returned if the table is empty.
This function is similar to <c>lists:foldr/3</c>. The order in
which the elements of the table are traversed is unspecified,
except for tables of type <c>ordered_set</c>, for which they
are traversed last to first.</p>
- <p>If <c>Function</c> inserts objects into the table, or another
+ <p>If <c><anno>Function</anno></c> inserts objects into the table, or another
process inserts objects into the table, those objects <em>may</em>
(depending on key ordering) be included in the traversal.</p>
</desc>
</func>
<func>
- <name>from_dets(Tab, DetsTab) -> true</name>
+ <name name="from_dets" arity="2"/>
<fsummary>Fill an ETS table with objects from a Dets table.</fsummary>
- <type>
- <v>Tab = tid() | atom()</v>
- <v>DetsTab = atom()</v>
- </type>
<desc>
<p>Fills an already created ETS table with the objects in the
- already opened Dets table named <c>DetsTab</c>. The existing
+ already opened Dets table named <c><anno>DetsTab</anno></c>. The existing
objects of the ETS table are kept unless overwritten.</p>
<p>Throws a badarg error if any of the tables does not exist or the
dets table is not open.</p>
</desc>
</func>
<func>
- <name>fun2ms(LiteralFun) -> MatchSpec</name>
+ <name name="fun2ms" arity="1"/>
<fsummary>Pseudo function that transforms fun syntax to a match_spec.</fsummary>
- <type>
- <v>LiteralFun -- see below</v>
- <v>MatchSpec = match_spec()</v>
- </type>
<desc>
<p>Pseudo function that by means of a <c>parse_transform</c>
- translates <c>LiteralFun</c> typed as parameter in the
+ translates <c><anno>LiteralFun</anno></c> typed as parameter in the
function call to a
<seealso marker="#match_spec">match_spec</seealso>. With
"literal" is meant that the fun needs to textually be written
@@ -342,7 +327,7 @@ tid()
variable which in turn is passed to the function).</p>
<p>The parse transform is implemented in the module
<c>ms_transform</c> and the source <em>must</em> include the
- file <c>ms_transform.hrl</c> in <c>stdlib</c> for this
+ file <c>ms_transform.hrl</c> in STDLIB for this
pseudo function to work. Failing to include the hrl file in
the source will result in a runtime error, not a compile
time ditto. The include file is easiest included by adding
@@ -422,20 +407,17 @@ Error: fun containing local Erlang function calls
</desc>
</func>
<func>
- <name>i() -> ok</name>
+ <name name="i" arity="0"/>
<fsummary>Display information about all ETS tables on tty.</fsummary>
<desc>
<p>Displays information about all ETS tables on tty.</p>
</desc>
</func>
<func>
- <name>i(Tab) -> ok</name>
+ <name name="i" arity="1"/>
<fsummary>Browse an ETS table on tty.</fsummary>
- <type>
- <v>Tab = tid() | atom()</v>
- </type>
<desc>
- <p>Browses the table <c>Tab</c> on tty.</p>
+ <p>Browses the table <c><anno>Tab</anno></c> on tty.</p>
</desc>
</func>
<func>
@@ -454,7 +436,7 @@ Error: fun containing local Erlang function calls
correct type, this function fails with reason <c>badarg</c>.</p>
<list type="bulleted">
- <item><c>Item=memory, Value=int()</c> <br></br>
+ <item><c>Item=memory, Value=integer()</c> <br></br>
The number of words allocated to the table.</item>
<item><c>Item=owner, Value=pid()</c> <br></br>
@@ -466,7 +448,7 @@ Error: fun containing local Erlang function calls
<item><c>Item=name, Value=atom()</c> <br></br>
The name of the table.</item>
- <item><c>Item=size, Value=int()</c> <br></br>
+ <item><c>Item=size, Value=integer()</c> <br></br>
The number of objects inserted in the table.</item>
<item><c>Item=node, Value=atom()</c> <br></br>
@@ -479,7 +461,7 @@ Error: fun containing local Erlang function calls
<item><c>Item=type, Value=set|ordered_set|bag|duplicate_bag</c> <br></br>
The table type.</item>
- <item><c>Item=keypos, Value=int()</c> <br></br>
+ <item><c>Item=keypos, Value=integer()</c> <br></br>
The key position.</item>
<item><c>Item=protection, Value=public|protected|private</c> <br></br>
@@ -530,31 +512,27 @@ Error: fun containing local Erlang function calls
of the reference counter, keeping track of how many times
the table has been fixed by the process.</p>
<p>If the table never has been fixed, the call returns
- <c>false</c>.</p>
- </item>
+ <c>false</c>.</p></item>
+ <item><p><c>Item=stats, Value=tuple()</c> <br></br>
+ Returns internal statistics about set, bag and duplicate_bag tables on an internal format used by OTP test suites.
+ Not for production use.</p></item>
</list>
</desc>
</func>
<func>
- <name>init_table(Name, InitFun) -> true</name>
+ <name name="init_table" arity="2"/>
<fsummary>Replace all objects of an ETS table.</fsummary>
- <type>
- <v>Name = atom()</v>
- <v>InitFun = fun(Arg) -> Res</v>
- <v>Arg = read | close</v>
- <v>Res = end_of_input | {[object()], InitFun} | term()</v>
- </type>
<desc>
- <p>Replaces the existing objects of the table <c>Tab</c> with
- objects created by calling the input function <c>InitFun</c>,
+ <p>Replaces the existing objects of the table <c><anno>Tab</anno></c> with
+ objects created by calling the input function <c><anno>InitFun</anno></c>,
see below. This function is provided for compatibility with
the <c>dets</c> module, it is not more efficient than filling
a table by using <c>ets:insert/2</c>.
</p>
<p>When called with the argument <c>read</c> the function
- <c>InitFun</c> is assumed to return <c>end_of_input</c> when
- there is no more input, or <c>{Objects, Fun}</c>, where
- <c>Objects</c> is a list of objects and <c>Fun</c> is a new
+ <c><anno>InitFun</anno></c> is assumed to return <c>end_of_input</c> when
+ there is no more input, or <c>{<anno>Objects</anno>, Fun}</c>, where
+ <c><anno>Objects</anno></c> is a list of objects and <c>Fun</c> is a new
input function. Any other value Value is returned as an error
<c>{error, {init_fun, Value}}</c>. Each input function will be
called exactly once, and should an error occur, the last
@@ -594,7 +572,7 @@ Error: fun containing local Erlang function calls
</desc>
</func>
<func>
- <name>insert_new(Tab, ObjectOrObjects) -> bool()</name>
+ <name>insert_new(Tab, ObjectOrObjects) -> boolean()</name>
<fsummary>Insert an object into an ETS table if the key is not already present.</fsummary>
<type>
<v>Tab = tid() | atom()</v>
@@ -615,7 +593,7 @@ Error: fun containing local Erlang function calls
</desc>
</func>
<func>
- <name>is_compiled_ms(Term) -> bool()</name>
+ <name>is_compiled_ms(Term) -> boolean()</name>
<fsummary>Checks if an Erlang term is the result of ets:match_spec_compile</fsummary>
<type>
<v>Term = term()</v>
@@ -682,9 +660,9 @@ ets:is_compiled_ms(Broken).</code>
table. The difference being the same as between <c>=:=</c>
and <c>==</c>. As an example, one might insert an object
with the
- <c>integer()</c><c>1</c> as a key in an <c>ordered_set</c>
+ <c>integer()</c> <c>1</c> as a key in an <c>ordered_set</c>
and get the object returned as a result of doing a
- <c>lookup/2</c> with the <c>float()</c><c>1.0</c> as the
+ <c>lookup/2</c> with the <c>float()</c> <c>1.0</c> as the
key to search for.</p>
<p>If the table is of type <c>set</c> or <c>ordered_set</c>,
the function returns either the empty list or a list with one
@@ -708,7 +686,7 @@ ets:is_compiled_ms(Broken).</code>
<type>
<v>Tab = tid() | atom()</v>
<v>Key = term()</v>
- <v>Pos = int()</v>
+ <v>Pos = integer()</v>
<v>Elem = term() | [term()]</v>
</type>
<desc>
@@ -802,15 +780,11 @@ ets:is_compiled_ms(Broken).</code>
</desc>
</func>
<func>
- <name>match_delete(Tab, Pattern) -> true</name>
+ <name name="match_delete" arity="2"/>
<fsummary>Delete all objects which match a given pattern from an ETS table.</fsummary>
- <type>
- <v>Tab = tid() | atom()</v>
- <v>Pattern = tuple()</v>
- </type>
<desc>
- <p>Deletes all objects which match the pattern <c>Pattern</c>
- from the table <c>Tab</c>. See <c>match/2</c> for a
+ <p>Deletes all objects which match the pattern <c><anno>Pattern</anno></c>
+ from the table <c><anno>Tab</anno></c>. See <c>match/2</c> for a
description of patterns.</p>
</desc>
</func>
@@ -957,8 +931,8 @@ ets:select(Table,MatchSpec),</code>
<v>&nbsp;Option = Type | Access | named_table | {keypos,Pos} | {heir,pid(),HeirData} | {heir,none} | Tweaks</v>
<v>&nbsp;&nbsp;Type = set | ordered_set | bag | duplicate_bag</v>
<v>&nbsp;&nbsp;Access = public | protected | private</v>
- <v>&nbsp;&nbsp;Tweaks = {write_concurrency,bool()} | {read_concurrency,bool()} | compressed</v>
- <v>&nbsp;&nbsp;Pos = int()</v>
+ <v>&nbsp;&nbsp;Tweaks = {write_concurrency,boolean()} | {read_concurrency,boolean()} | compressed</v>
+ <v>&nbsp;&nbsp;Pos = integer()</v>
<v>&nbsp;&nbsp;HeirData = term()</v>
</type>
<desc>
@@ -971,7 +945,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},{read_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>
@@ -988,7 +962,7 @@ ets:select(Table,MatchSpec),</code>
<c>ordered_set</c> tables regard keys as equal when they
<em>compare equal</em>, not only when they match. This
means that to an <c>ordered_set</c>, the
- <c>integer()</c><c>1</c> and the <c>float()</c><c>1.0</c> are regarded as equal. This also means that the
+ <c>integer()</c> <c>1</c> and the <c>float()</c> <c>1.0</c> are regarded as equal. This also means that the
key used to lookup an element not necessarily
<em>matches</em> the key in the elements returned, if
<c>float()</c>'s and <c>integer()</c>'s are mixed in
@@ -1050,7 +1024,7 @@ ets:select(Table,MatchSpec),</code>
</item>
<item>
<marker id="new_2_write_concurrency"></marker>
- <p><c>{write_concurrency,bool()}</c>
+ <p><c>{write_concurrency,boolean()}</c>
Performance tuning. Default is <c>false</c>, in which case an operation that
mutates (writes to) the table will obtain exclusive access,
blocking any concurrent access of the same table until finished.
@@ -1074,7 +1048,7 @@ ets:select(Table,MatchSpec),</code>
</item>
<item>
<marker id="new_2_read_concurrency"></marker>
- <p><c>{read_concurrency,bool()}</c>
+ <p><c>{read_concurrency,boolean()}</c>
Performance tuning. Default is <c>false</c>. When set to
<c>true</c>, the table is optimized for concurrent read
operations. When this option is enabled on a runtime system with
@@ -1160,12 +1134,8 @@ ets:select(Table,MatchSpec),</code>
</desc>
</func>
<func>
- <name>repair_continuation(Continuation, MatchSpec) -> Continuation</name>
+ <name name="repair_continuation" arity="2"/>
<fsummary>Repair a continuation from ets:select/1 or ets:select/3 that has passed through external representation</fsummary>
- <type>
- <v>Continuation = term()</v>
- <v>MatchSpec = match_spec()</v>
- </type>
<desc>
<p>This function can be used to restore an opaque continuation
returned by <c>ets:select/3</c> or <c>ets:select/1</c> if the
@@ -1551,7 +1521,7 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code>
<fsummary>Return all objects in a given slot of an ETS table.</fsummary>
<type>
<v>Tab = tid() | atom()</v>
- <v>I = int()</v>
+ <v>I = integer()</v>
<v>Object = tuple()</v>
</type>
<desc>
@@ -1572,32 +1542,19 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code>
</desc>
</func>
<func>
- <name>tab2file(Tab, Filename) -> ok | {error,Reason}</name>
+ <name name="tab2file" arity="2"/>
<fsummary>Dump an ETS table to a file.</fsummary>
- <type>
- <v>Tab = tid() | atom()</v>
- <v>Filename = string() | atom()</v>
- <v>Reason = term()</v>
- </type>
<desc>
- <p>Dumps the table <c>Tab</c> to the file <c>Filename</c>.</p>
- <p>Equivalent to <c>tab2file(Tab, Filename,[])</c></p>
+ <p>Dumps the table <c><anno>Tab</anno></c> to the file <c><anno>Filename</anno></c>.</p>
+ <p>Equivalent to <c>tab2file(<anno>Tab</anno>, <anno>Filename</anno>,[])</c></p>
</desc>
</func>
<func>
- <name>tab2file(Tab, Filename, Options) -> ok | {error,Reason}</name>
+ <name name="tab2file" arity="3"/>
<fsummary>Dump an ETS table to a file.</fsummary>
- <type>
- <v>Tab = tid() | atom()</v>
- <v>Filename = string() | atom()</v>
- <v>Options = [Option]</v>
- <v>Option = {extended_info, [ExtInfo]}</v>
- <v>ExtInfo = object_count | md5sum</v>
- <v>Reason = term()</v>
- </type>
<desc>
- <p>Dumps the table <c>Tab</c> to the file <c>Filename</c>.</p>
+ <p>Dumps the table <c><anno>Tab</anno></c> to the file <c><anno>Filename</anno></c>.</p>
<p>When dumping the table, certain information about the table
is dumped to a header at the beginning of the dump. This
information contains data about the table type,
@@ -1634,26 +1591,15 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code>
</desc>
</func>
<func>
- <name>tab2list(Tab) -> [Object]</name>
+ <name name="tab2list" arity="1"/>
<fsummary>Return a list of all objects in an ETS table.</fsummary>
- <type>
- <v>Tab = tid() | atom()</v>
- <v>Object = tuple()</v>
- </type>
<desc>
- <p>Returns a list of all objects in the table <c>Tab</c>.</p>
+ <p>Returns a list of all objects in the table <c><anno>Tab</anno></c>.</p>
</desc>
</func>
<func>
- <name>tabfile_info(Filename) -> {ok, TableInfo} | {error, Reason}</name>
+ <name name="tabfile_info" arity="1"/>
<fsummary>Return a list of all objects in an ETS table.</fsummary>
- <type>
- <v>Filename = string() | atom()</v>
- <v>TableInfo = [InfoItem]</v>
- <v>InfoItem = {InfoTag, term()}</v>
- <v>InfoTag = name | type | protection | named_table | keypos | size | extended_info | version</v>
- <v>Reason = term()</v>
- </type>
<desc>
<p>Returns information about the table dumped to file by
<seealso marker="#tab2file/2">tab2file/2</seealso> or
@@ -1699,7 +1645,7 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code>
one or more of the atoms <c>object_count</c> and
<c>md5sum</c>.</item>
<tag>version</tag>
- <item>A tuple <c>{Major,Minor}</c> containing the major and
+ <item>A tuple <c>{<anno>Major</anno>,<anno>Minor</anno>}</c> containing the major and
minor version of the file format for ets table dumps. This
version field was added beginning with stdlib-1.5.1, files
dumped with older versions will return <c>{0,0}</c> in this
@@ -1712,20 +1658,11 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code>
</desc>
</func>
<func>
- <name>table(Tab [, Options]) -> QueryHandle</name>
+ <name name="table" arity="1"/>
+ <name name="table" arity="2"/>
<fsummary>Return a QLC query handle.</fsummary>
- <type>
- <v>Tab = tid() | atom()</v>
- <v>QueryHandle = -&nbsp;a query handle, see qlc(3)&nbsp;-</v>
- <v>Options = [Option] | Option</v>
- <v>Option = {n_objects, NObjects} | {traverse, TraverseMethod}</v>
- <v>NObjects = default | integer() > 0</v>
- <v>TraverseMethod = first_next | last_prev | select | {select, MatchSpec}</v>
- <v>MatchSpec = match_spec()</v>
- </type>
<desc>
- <p> <marker id="qlc_table"></marker>
-Returns a QLC (Query List
+ <p><marker id="qlc_table"></marker>Returns a QLC (Query List
Comprehension) query handle. The module <c>qlc</c> implements
a query language aimed mainly at Mnesia but ETS tables, Dets
tables, and lists are also recognized by QLC as sources of
@@ -1760,7 +1697,7 @@ Returns a QLC (Query List
that matches all objects.</p>
</item>
<item>
- <p><c>{select, MatchSpec}</c>. As for <c>select</c>
+ <p><c>{select, <anno>MatchSpec</anno>}</c>. As for <c>select</c>
the table is traversed by calling <c>ets:select/3</c> and
<c>ets:select/1</c>. The difference is that the
match_spec is explicitly given. This is how to state
@@ -1788,41 +1725,31 @@ true</pre>
</desc>
</func>
<func>
- <name>test_ms(Tuple, MatchSpec) -> {ok, Result} | {error, Errors}</name>
+ <name name="test_ms" arity="2"/>
<fsummary>Test a match_spec for use in ets:select/2.</fsummary>
- <type>
- <v>Tuple = tuple()</v>
- <v>MatchSpec = match_spec()</v>
- <v>Result = term()</v>
- <v>Errors = [{warning|error, string()}]</v>
- </type>
<desc>
<p>This function is a utility to test a
<seealso marker="#match_spec">match_spec</seealso> used in
calls to <c>ets:select/2</c>. The function both tests
- <c>MatchSpec</c> for "syntactic" correctness and runs the
- match_spec against the object <c>Tuple</c>. If the match_spec
- contains errors, the tuple <c>{error, Errors}</c> is returned
- where <c>Errors</c> is a list of natural language
+ <c><anno>MatchSpec</anno></c> for "syntactic" correctness and runs the
+ match_spec against the object <c><anno>Tuple</anno></c>. If the match_spec
+ contains errors, the tuple <c>{error, <anno>Errors</anno>}</c> is returned
+ where <c><anno>Errors</anno></c> is a list of natural language
descriptions of what was wrong with the match_spec. If the
match_spec is syntactically OK, the function returns
- <c>{ok,Term}</c> where <c>Term</c> is what would have been
+ <c>{ok,<anno>Result</anno>}</c> where <c><anno>Result</anno></c> is what would have been
the result in a real <c>ets:select/2</c> call or <c>false</c>
- if the match_spec does not match the object <c>Tuple</c>.</p>
+ if the match_spec does not match the object <c><anno>Tuple</anno></c>.</p>
<p>This is a useful debugging and test tool, especially when
writing complicated <c>ets:select/2</c> calls.</p>
</desc>
</func>
<func>
- <name>to_dets(Tab, DetsTab) -> DetsTab</name>
+ <name name="to_dets" arity="2"/>
<fsummary>Fill a Dets table with objects from an ETS table.</fsummary>
- <type>
- <v>Tab = tid() | atom()</v>
- <v>DetsTab = atom()</v>
- </type>
<desc>
<p>Fills an already created/opened Dets table with the objects
- in the already opened ETS table named <c>Tab</c>. The Dets
+ in the already opened ETS table named <c><anno>Tab</anno></c>. The Dets
table is emptied before the objects are inserted.</p>
</desc>
</func>
@@ -1835,7 +1762,7 @@ true</pre>
<v>Tab = tid() | atom()</v>
<v>Key = term()</v>
<v>UpdateOp = {Pos,Incr} | {Pos,Incr,Threshold,SetValue}</v>
- <v>Pos = Incr = Threshold = SetValue = Result = int()</v>
+ <v>Pos = Incr = Threshold = SetValue = Result = integer()</v>
</type>
<desc>
<p>This function provides an efficient way to update one or more
@@ -1897,7 +1824,7 @@ true</pre>
<type>
<v>Tab = tid() | atom()</v>
<v>Key = Value = term()</v>
- <v>Pos = int()</v>
+ <v>Pos = integer()</v>
</type>
<desc>
<p>This function provides an efficient way to update one or more
diff --git a/lib/stdlib/doc/src/file_sorter.xml b/lib/stdlib/doc/src/file_sorter.xml
index ccb32659a0..a6b3633066 100644
--- a/lib/stdlib/doc/src/file_sorter.xml
+++ b/lib/stdlib/doc/src/file_sorter.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2001</year><year>2010</year>
+ <year>2001</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -89,7 +89,7 @@
considerably. The <c>keysort</c>, <c>keymerge</c> and
<c>keycheck</c> functions do not accept ordering functions.
</item>
- <item><c>{unique, bool()}</c>. When sorting or merging files,
+ <item><c>{unique, boolean()}</c>. When sorting or merging files,
only the first of a sequence of terms that compare equal (<c>==</c>)
is output if this option is set to <c>true</c>. The default
value is <c>false</c> which implies that all terms that
@@ -112,7 +112,7 @@
overwritten. Temporary files are deleted unless some
uncaught EXIT signal occurs.
</item>
- <item><c>{compressed, bool()}</c>. Temporary files and the
+ <item><c>{compressed, boolean()}</c>. Temporary files and the
output file may be compressed. The default value
<c>false</c> implies that written files are not
compressed. Regardless of the value of the <c>compressed</c>
@@ -128,39 +128,6 @@
merged at a time. This option should rarely be needed.
</item>
</list>
- <p>To summarize, here is the syntax of the options:</p>
- <list type="bulleted">
- <item>
- <p><c>Options = [Option] | Option</c></p>
- </item>
- <item>
- <p><c>Option = {header, HeaderLength} | {format, Format} | {order, Order} | {unique, bool()} | {tmpdir, TempDirectory} | {compressed, bool()} | {size, Size} | {no_files, NoFiles}</c></p>
- </item>
- <item>
- <p><c>HeaderLength = int() > 0</c></p>
- </item>
- <item>
- <p><c>Format = binary_term | term | binary | FormatFun</c></p>
- </item>
- <item>
- <p><c>FormatFun = fun(Binary) -> Term</c></p>
- </item>
- <item>
- <p><c>Order = ascending | descending | OrderFun</c></p>
- </item>
- <item>
- <p><c>OrderFun = fun(Term, Term) -> bool()</c></p>
- </item>
- <item>
- <p><c>TempDirectory = "" | file_name()</c></p>
- </item>
- <item>
- <p><c>Size = int() >= 0</c></p>
- </item>
- <item>
- <p><c>NoFiles = int() > 1</c></p>
- </item>
- </list>
<p>As an alternative to sorting files, a function of one argument
can be given as input. When called with the argument <c>read</c>
the function is assumed to return <c>end_of_input</c> or
@@ -234,8 +201,8 @@ output(L) ->
occurs are:</p>
<list type="bulleted">
<item>
- <p><c>bad_object</c>, <c>{bad_object, FileName}</c>.
- Applying the format function failed for some binary,
+ <p><c>bad_object</c>, <c>{bad_object, FileName}</c>.
+ Applying the format function failed for some binary,
or the key(s) could not be extracted from some term.</p>
</item>
<item>
@@ -243,148 +210,181 @@ output(L) ->
to read some term.</p>
</item>
<item>
- <p><c>{file_error, FileName, Reason2}</c>. See
- <c>file(3)</c> for an explanation of <c>Reason2</c>.</p>
+ <p><c>{file_error, FileName, file:posix()}</c>. See
+ <c>file(3)</c> for an explanation of <c>file:posix()</c>.</p>
</item>
<item>
- <p><c>{premature_eof, FileName}</c>. End-of-file was
+ <p><c>{premature_eof, FileName}</c>. End-of-file was
encountered inside some binary term.</p>
</item>
</list>
- <p><em>Types</em></p>
- <pre>
-Binary = binary()
-FileName = file_name()
-FileNames = [FileName]
-ICommand = read | close
-IReply = end_of_input | {end_of_input, Value} | {[Object], Infun} | InputReply
-Infun = fun(ICommand) -> IReply
-Input = FileNames | Infun
-InputReply = Term
-KeyPos = int() > 0 | [int() > 0]
-OCommand = {value, Value} | [Object] | close
-OReply = Outfun | OutputReply
-Object = Term | Binary
-Outfun = fun(OCommand) -> OReply
-Output = FileName | Outfun
-OutputReply = Term
-Term = term()
-Value = Term</pre>
</description>
+
+ <datatypes>
+ <datatype>
+ <name name="file_name"/><br/>
+ </datatype>
+ <datatype>
+ <name name="file_names"/><br/>
+ </datatype>
+ <datatype>
+ <name name="i_command"/><br/>
+ </datatype>
+ <datatype>
+ <name name="i_reply"/><br/>
+ </datatype>
+ <datatype>
+ <name name="infun"/><br/>
+ </datatype>
+ <datatype>
+ <name name="input"/><br/>
+ </datatype>
+ <datatype>
+ <name name="input_reply"/><br/>
+ </datatype>
+ <datatype>
+ <name name="o_command"/><br/>
+ </datatype>
+ <datatype>
+ <name name="o_reply"/><br/>
+ </datatype>
+ <datatype>
+ <name name="object"/><br/>
+ </datatype>
+ <datatype>
+ <name name="outfun"/><br/>
+ </datatype>
+ <datatype>
+ <name name="output"/><br/>
+ </datatype>
+ <datatype>
+ <name name="output_reply"/><br/>
+ </datatype>
+ <datatype>
+ <name name="value"/><br/>
+ </datatype>
+ <datatype>
+ <name name="options"/><br/>
+ </datatype>
+ <datatype>
+ <name name="option"/><br/>
+ </datatype>
+ <datatype>
+ <name name="format"/><br/>
+ </datatype>
+ <datatype>
+ <name name="format_fun"/><br/>
+ </datatype>
+ <datatype>
+ <name name="header_length"/><br/>
+ </datatype>
+ <datatype>
+ <name name="key_pos"/><br/>
+ </datatype>
+ <datatype>
+ <name name="no_files"/><br/>
+ </datatype>
+ <datatype>
+ <name name="order"/><br/>
+ </datatype>
+ <datatype>
+ <name name="order_fun"/><br/>
+ </datatype>
+ <datatype>
+ <name name="size"/><br/>
+ </datatype>
+ <datatype>
+ <name name="tmp_directory"/><br/>
+ </datatype>
+ <datatype>
+ <name name="reason"/><br/>
+ </datatype>
+ </datatypes>
+
<funcs>
<func>
- <name>sort(FileName) -> Reply</name>
- <name>sort(Input, Output) -> Reply</name>
- <name>sort(Input, Output, Options) -> Reply</name>
+ <name name="sort" arity="1"/>
<fsummary>Sort terms on files.</fsummary>
- <type>
- <v>Reply = ok | {error, Reason} | InputReply | OutputReply</v>
- </type>
<desc>
- <p>Sorts terms on files.
- </p>
- <p><c>sort(FileName)</c> is equivalent to
- <c>sort([FileName], FileName)</c>.
- </p>
- <p><c>sort(Input, Output)</c> is equivalent to
- <c>sort(Input, Output, [])</c>.
- </p>
- <p></p>
+ <p>Sorts terms on files. <c>sort(FileName)</c> is equivalent
+ to <c>sort([FileName], FileName)</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="sort" arity="2"/>
+ <name name="sort" arity="3"/>
+ <fsummary>Sort terms on files.</fsummary>
+ <desc>
+ <p>Sorts terms on files. <c>sort(Input, Output)</c> is
+ equivalent to <c>sort(Input, Output, [])</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="keysort" arity="2"/>
+ <fsummary>Sort terms on files by key.</fsummary>
+ <desc>
+ <p>Sorts tuples on files. <c>keysort(N, FileName)</c> is
+ equivalent to <c>keysort(N, [FileName], FileName)</c>.</p>
</desc>
</func>
<func>
- <name>keysort(KeyPos, FileName) -> Reply</name>
- <name>keysort(KeyPos, Input, Output) -> Reply</name>
- <name>keysort(KeyPos, Input, Output, Options) -> Reply</name>
+ <name name="keysort" arity="3"/>
+ <name name="keysort" arity="4"/>
<fsummary>Sort terms on files by key.</fsummary>
- <type>
- <v>Reply = ok | {error, Reason} | InputReply | OutputReply</v>
- </type>
<desc>
<p>Sorts tuples on files. The sort is performed on the
- element(s) mentioned in <c>KeyPos</c>. If two tuples
- compare equal (<c>==</c>) on one element, next element according to
- <c>KeyPos</c> is compared. The sort is stable.
- </p>
- <p><c>keysort(N, FileName)</c> is equivalent to
- <c>keysort(N, [FileName], FileName)</c>.
- </p>
+ element(s) mentioned in <c><anno>KeyPos</anno></c>. If two
+ tuples compare equal (<c>==</c>) on one element, next
+ element according to <c><anno>KeyPos</anno></c>
+ is compared. The sort is stable.</p>
<p><c>keysort(N, Input, Output)</c> is equivalent to
- <c>keysort(N, Input, Output, [])</c>.
- </p>
- <p></p>
+ <c>keysort(N, Input, Output, [])</c>.</p>
</desc>
</func>
<func>
- <name>merge(FileNames, Output) -> Reply</name>
- <name>merge(FileNames, Output, Options) -> Reply</name>
+ <name name="merge" arity="2"/>
+ <name name="merge" arity="3"/>
<fsummary>Merge terms on files.</fsummary>
- <type>
- <v>Reply = ok | {error, Reason} | OutputReply</v>
- </type>
<desc>
<p>Merges terms on files. Each input file is assumed to be
- sorted.
- </p>
+ sorted.</p>
<p><c>merge(FileNames, Output)</c> is equivalent to
- <c>merge(FileNames, Output, [])</c>.
- </p>
+ <c>merge(FileNames, Output, [])</c>.</p>
</desc>
</func>
<func>
- <name>keymerge(KeyPos, FileNames, Output) -> Reply</name>
- <name>keymerge(KeyPos, FileNames, Output, Options) -> Reply</name>
+ <name name="keymerge" arity="3"/>
+ <name name="keymerge" arity="4"/>
<fsummary>Merge terms on files by key.</fsummary>
- <type>
- <v>Reply = ok | {error, Reason} | OutputReply</v>
- </type>
<desc>
<p>Merges tuples on files. Each input file is assumed to be
- sorted on key(s).
- </p>
+ sorted on key(s).</p>
<p><c>keymerge(KeyPos, FileNames, Output)</c> is equivalent
- to <c>keymerge(KeyPos, FileNames, Output, [])</c>.
- </p>
- <p></p>
+ to <c>keymerge(KeyPos, FileNames, Output, [])</c>.</p>
</desc>
</func>
<func>
- <name>check(FileName) -> Reply</name>
- <name>check(FileNames, Options) -> Reply</name>
+ <name name="check" arity="1"/>
+ <name name="check" arity="2"/>
<fsummary>Check whether terms on files are sorted.</fsummary>
- <type>
- <v>Reply = {ok, [Result]} | {error, Reason}</v>
- <v>Result = {FileName, TermPosition, Term}</v>
- <v>TermPosition = int() > 1</v>
- </type>
<desc>
<p>Checks files for sortedness. If a file is not sorted, the
first out-of-order element is returned. The first term on a
- file has position 1.
- </p>
+ file has position 1.</p>
<p><c>check(FileName)</c> is equivalent to
- <c>check([FileName], [])</c>.
- </p>
+ <c>check([FileName], [])</c>.</p>
</desc>
</func>
<func>
- <name>keycheck(KeyPos, FileName) -> CheckReply</name>
- <name>keycheck(KeyPos, FileNames, Options) -> Reply</name>
+ <name name="keycheck" arity="2"/>
+ <name name="keycheck" arity="3"/>
<fsummary>Check whether terms on files are sorted by key.</fsummary>
- <type>
- <v>Reply = {ok, [Result]} | {error, Reason}</v>
- <v>Result = {FileName, TermPosition, Term}</v>
- <v>TermPosition = int() > 1</v>
- </type>
<desc>
<p>Checks files for sortedness. If a file is not sorted, the
first out-of-order element is returned. The first term on a
- file has position 1.
- </p>
+ file has position 1.</p>
<p><c>keycheck(KeyPos, FileName)</c> is equivalent
- to <c>keycheck(KeyPos, [FileName], [])</c>.
- </p>
- <p></p>
+ to <c>keycheck(KeyPos, [FileName], [])</c>.</p>
</desc>
</func>
</funcs>
diff --git a/lib/stdlib/doc/src/filelib.xml b/lib/stdlib/doc/src/filelib.xml
index fab68ae77c..f3079c7337 100644
--- a/lib/stdlib/doc/src/filelib.xml
+++ b/lib/stdlib/doc/src/filelib.xml
@@ -41,62 +41,46 @@
<p>For more information about raw file names, see the <seealso marker="kernel:file">file</seealso> module.</p>
</description>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-filename() = string() | atom() | DeepList | RawFilename
- DeepList = [char() | atom() | DeepList]
- RawFilename = binary()
- If VM is in unicode filename mode, string() and char() are allowed to be > 255.
- RawFilename is a filename not subject to Unicode translation, meaning that it
- can contain characters not conforming to the Unicode encoding expected from the
- filesystem (i.e. non-UTF-8 characters although the VM is started in Unicode
- filename mode).
-dirname() = filename()</code>
- </section>
+ <datatypes>
+ <datatype>
+ <name name="filename"/>
+ </datatype>
+ <datatype>
+ <name name="dirname"/>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>ensure_dir(Name) -> ok | {error, Reason}</name>
+ <name name="ensure_dir" arity="1"/>
<fsummary>Ensure that all parent directories for a file or directory exist.</fsummary>
- <type>
- <v>Name = filename() | dirname()</v>
- <v>Reason = posix() -- see file(3)</v>
- </type>
<desc>
<p>The <c>ensure_dir/1</c> function ensures that all parent
- directories for the given file or directory name <c>Name</c>
+ directories for the given file or directory name <c><anno>Name</anno></c>
exist, trying to create them if necessary.</p>
<p>Returns <c>ok</c> if all parent directories already exist
- or could be created, or <c>{error, Reason}</c> if some parent
+ or could be created, or <c>{error, <anno>Reason</anno>}</c> if some parent
directory does not exist and could not be created for some
reason.</p>
</desc>
</func>
<func>
- <name>file_size(Filename) -> integer()</name>
+ <name name="file_size" arity="1"/>
<fsummary>Return the size in bytes of the file.</fsummary>
<desc>
<p>The <c>file_size</c> function returns the size of the given file.</p>
</desc>
</func>
<func>
- <name>fold_files(Dir, RegExp, Recursive, Fun, AccIn) -> AccOut </name>
+ <name name="fold_files" arity="5"/>
<fsummary>Fold over all files matching a regular expression.</fsummary>
- <type>
- <v>Dir = dirname()</v>
- <v>RegExp = regular_expression_string()</v>
- <v>Recursive = true|false</v>
- <v>Fun = fun(F, AccIn) -> AccOut</v>
- <v>AccIn = AccOut = term()</v>
- </type>
<desc>
<p>The <c>fold_files/5</c> function folds the function
- <c>Fun</c> over all (regular) files <c>F</c> in the
- directory <c>Dir</c> that match the regular expression <c>RegExp</c>
+ <c><anno>Fun</anno></c> over all (regular) files <c><anno>F</anno></c> in the
+ directory <c><anno>Dir</anno></c> that match the regular expression <c><anno>RegExp</anno></c>
(see the <seealso marker="re">re</seealso> module for a description
of the allowed regular expressions).
- If <c>Recursive</c> is true all sub-directories to <c>Dir</c>
+ If <c><anno>Recursive</anno></c> is true all sub-directories to <c>Dir</c>
are processed. The regular expression matching is done on just
the filename without the directory part.</p>
@@ -114,44 +98,32 @@ dirname() = filename()</code>
</desc>
</func>
<func>
- <name>is_dir(Name) -> true | false</name>
+ <name name="is_dir" arity="1"/>
<fsummary>Test whether Name refer to a directory or not</fsummary>
- <type>
- <v>Name = filename() | dirname()</v>
- </type>
<desc>
- <p>The <c>is_dir/1</c> function returns <c>true</c> if <c>Name</c>
+ <p>The <c>is_dir/1</c> function returns <c>true</c> if <c><anno>Name</anno></c>
refers to a directory, and <c>false</c> otherwise.</p>
</desc>
</func>
<func>
- <name>is_file(Name) -> true | false</name>
+ <name name="is_file" arity="1"/>
<fsummary>Test whether Name refer to a file or directory.</fsummary>
- <type>
- <v>Name = filename() | dirname()</v>
- </type>
<desc>
- <p>The <c>is_file/1</c> function returns <c>true</c> if <c>Name</c>
+ <p>The <c>is_file/1</c> function returns <c>true</c> if <c><anno>Name</anno></c>
refers to a file or a directory, and <c>false</c> otherwise.</p>
</desc>
</func>
<func>
- <name>is_regular(Name) -> true | false</name>
+ <name name="is_regular" arity="1"/>
<fsummary>Test whether Name refer to a (regular) file.</fsummary>
- <type>
- <v>Name = filename()</v>
- </type>
<desc>
- <p>The <c>is_regular/1</c> function returns <c>true</c> if <c>Name</c>
+ <p>The <c>is_regular/1</c> function returns <c>true</c> if <c><anno>Name</anno></c>
refers to a file (regular file), and <c>false</c> otherwise.</p>
</desc>
</func>
<func>
- <name>last_modified(Name) -> {{Year,Month,Day},{Hour,Min,Sec}} | 0</name>
+ <name name="last_modified" arity="1"/>
<fsummary>Return the local date and time when a file was last modified.</fsummary>
- <type>
- <v>Name = filename() | dirname()</v>
- </type>
<desc>
<p>The <c>last_modified/1</c> function returns the date and time the
given file or directory was last modified, or 0 if the file
@@ -159,14 +131,11 @@ dirname() = filename()</code>
</desc>
</func>
<func>
- <name>wildcard(Wildcard) -> list()</name>
+ <name name="wildcard" arity="1"/>
<fsummary>Match filenames using Unix-style wildcards.</fsummary>
- <type>
- <v>Wildcard = filename() | dirname()</v>
- </type>
<desc>
<p>The <c>wildcard/1</c> function returns a list of all files
- that match Unix-style wildcard-string <c>Wildcard</c>.</p>
+ that match Unix-style wildcard-string <c><anno>Wildcard</anno></c>.</p>
<p>The wildcard string looks like an ordinary filename, except
that certain "wildcard characters" are interpreted in a special
way. The following characters are special:
@@ -226,15 +195,11 @@ dirname() = filename()</code>
</desc>
</func>
<func>
- <name>wildcard(Wildcard, Cwd) -> list()</name>
+ <name name="wildcard" arity="2"/>
<fsummary>Match filenames using Unix-style wildcards starting at a specified directory.</fsummary>
- <type>
- <v>Wildcard = filename() | dirname()</v>
- <v>Cwd = dirname()</v>
- </type>
<desc>
<p>The <c>wildcard/2</c> function works like <c>wildcard/1</c>,
- except that instead of the actual working directory, <c>Cwd</c>
+ except that instead of the actual working directory, <c><anno>Cwd</anno></c>
will be used.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/filename.xml b/lib/stdlib/doc/src/filename.xml
index cdee6e4a81..bc3a616d39 100644
--- a/lib/stdlib/doc/src/filename.xml
+++ b/lib/stdlib/doc/src/filename.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2010</year>
+ <year>1997</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -47,28 +47,12 @@
<seealso marker="kernel:file#native_name_encoding/0">file:native_name_encoding/0</seealso>, a raw file name will also be returned. For example filename:join/1 provided with a path component being a binary (and also not being possible to interpret under the current native file name encoding) will result in a raw file name being returned (the join operation will have been performed of course). For more information about raw file names, see the <seealso marker="kernel:file">file</seealso> module.</p>
</description>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-name() = string() | atom() | DeepList | RawFilename
- DeepList = [char() | atom() | DeepList]
- RawFilename = binary()
- If VM is in unicode filename mode, string() and char() are allowed to be > 255.
- RawFilename is a filename not subject to Unicode translation, meaning that it
- can contain characters not conforming to the Unicode encoding expected from the
- filesystem (i.e. non-UTF-8 characters although the VM is started in Unicode
- filename mode).
- </code>
- </section>
<funcs>
<func>
- <name>absname(Filename) -> string()</name>
+ <name name="absname" arity="1"/>
<fsummary>Convert a filename to an absolute name, relative the working directory</fsummary>
- <type>
- <v>Filename = name()</v>
- </type>
<desc>
- <p>Converts a relative <c>Filename</c> and returns an absolute
+ <p>Converts a relative <c><anno>Filename</anno></c> and returns an absolute
name. No attempt is made to create the shortest absolute name,
because this can give incorrect results on file systems which
allow links.</p>
@@ -95,44 +79,33 @@ name() = string() | atom() | DeepList | RawFilename
</desc>
</func>
<func>
- <name>absname(Filename, Dir) -> string()</name>
+ <name name="absname" arity="2"/>
<fsummary>Convert a filename to an absolute name, relative a specified directory</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>Dir = string()</v>
- </type>
<desc>
<p>This function works like <c>absname/1</c>, except that
the directory to which the file name should be made relative
- is given explicitly in the <c>Dir</c> argument.</p>
+ is given explicitly in the <c><anno>Dir</anno></c> argument.</p>
</desc>
</func>
<func>
- <name>absname_join(Dir, Filename) -> string()</name>
+ <name name="absname_join" arity="2"/>
<fsummary>Join an absolute directory with a relative filename</fsummary>
- <type>
- <v>Dir = string()</v>
- <v>Filename = name()</v>
- </type>
<desc>
<p>Joins an absolute directory with a relative filename.
Similar to <c>join/2</c>, but on platforms with tight
restrictions on raw filename length and no support for
symbolic links (read: VxWorks), leading parent directory
- components in <c>Filename</c> are matched against trailing
- directory components in <c>Dir</c> so they can be removed
+ components in <c><anno>Filename</anno></c> are matched against trailing
+ directory components in <c><anno>Dir</anno></c> so they can be removed
from the result - minimizing its length.</p>
</desc>
</func>
<func>
- <name>basename(Filename) -> string()</name>
+ <name name="basename" arity="1"/>
<fsummary>Return the last component of a filename</fsummary>
- <type>
- <v>Filename = name()</v>
- </type>
<desc>
- <p>Returns the last component of <c>Filename</c>, or
- <c>Filename</c> itself if it does not contain any directory
+ <p>Returns the last component of <c><anno>Filename</anno></c>, or
+ <c><anno>Filename</anno></c> itself if it does not contain any directory
separators.</p>
<pre>
5> <input>filename:basename("foo").</input>
@@ -144,14 +117,11 @@ name() = string() | atom() | DeepList | RawFilename
</desc>
</func>
<func>
- <name>basename(Filename, Ext) -> string()</name>
+ <name name="basename" arity="2"/>
<fsummary>Return the last component of a filename, stripped of the specified extension</fsummary>
- <type>
- <v>Filename = Ext = name()</v>
- </type>
<desc>
- <p>Returns the last component of <c>Filename</c> with the
- extension <c>Ext</c> stripped. This function should be used
+ <p>Returns the last component of <c><anno>Filename</anno></c> with the
+ extension <c><anno>Ext</anno></c> stripped. This function should be used
to remove a specific extension which might, or might not, be
there. Use <c>rootname(basename(Filename))</c> to remove an
extension that exists, but you are not sure which one it is.</p>
@@ -169,13 +139,10 @@ name() = string() | atom() | DeepList | RawFilename
</desc>
</func>
<func>
- <name>dirname(Filename) -> string()</name>
+ <name name="dirname" arity="1"/>
<fsummary>Return the directory part of a path name</fsummary>
- <type>
- <v>Filename = name()</v>
- </type>
<desc>
- <p>Returns the directory part of <c>Filename</c>.</p>
+ <p>Returns the directory part of <c><anno>Filename</anno></c>.</p>
<pre>
13> <input>filename:dirname("/usr/src/kalle.erl").</input>
"/usr/src"
@@ -187,13 +154,10 @@ name() = string() | atom() | DeepList | RawFilename
</desc>
</func>
<func>
- <name>extension(Filename) -> string()</name>
+ <name name="extension" arity="1"/>
<fsummary>Return the file extension</fsummary>
- <type>
- <v>Filename = name()</v>
- </type>
<desc>
- <p>Returns the file extension of <c>Filename</c>, including
+ <p>Returns the file extension of <c><anno>Filename</anno></c>, including
the period. Returns an empty string if there is no extension.</p>
<pre>
15> <input>filename:extension("foo.erl").</input>
@@ -203,11 +167,8 @@ name() = string() | atom() | DeepList | RawFilename
</desc>
</func>
<func>
- <name>flatten(Filename) -> string()</name>
+ <name name="flatten" arity="1"/>
<fsummary>Convert a filename to a flat string</fsummary>
- <type>
- <v>Filename = name()</v>
- </type>
<desc>
<p>Converts a possibly deep list filename consisting of
characters and atoms into the corresponding flat string
@@ -215,14 +176,11 @@ name() = string() | atom() | DeepList | RawFilename
</desc>
</func>
<func>
- <name>join(Components) -> string()</name>
+ <name name="join" arity="1"/>
<fsummary>Join a list of filename components with directory separators</fsummary>
- <type>
- <v>Components = [string()]</v>
- </type>
<desc>
- <p>Joins a list of file name <c>Components</c> with directory
- separators. If one of the elements of <c>Components</c>
+ <p>Joins a list of file name <c><anno>Components</anno></c> with directory
+ separators. If one of the elements of <c><anno>Components</anno></c>
includes an absolute path, for example <c>"/xxx"</c>,
the preceding elements, if any, are removed from the result.</p>
<p>The result is "normalized":</p>
@@ -242,24 +200,18 @@ name() = string() | atom() | DeepList | RawFilename
</desc>
</func>
<func>
- <name>join(Name1, Name2) -> string()</name>
+ <name name="join" arity="2"/>
<fsummary>Join two filename components with directory separators</fsummary>
- <type>
- <v>Name1 = Name2 = string()</v>
- </type>
<desc>
<p>Joins two file name components with directory separators.
- Equivalent to <c>join([Name1, Name2])</c>.</p>
+ Equivalent to <c>join([<anno>Name1</anno>, <anno>Name2</anno>])</c>.</p>
</desc>
</func>
<func>
- <name>nativename(Path) -> string()</name>
+ <name name="nativename" arity="1"/>
<fsummary>Return the native form of a file path</fsummary>
- <type>
- <v>Path = string()</v>
- </type>
<desc>
- <p>Converts <c>Path</c> to a form accepted by the command shell
+ <p>Converts <c><anno>Path</anno></c> to a form accepted by the command shell
and native applications on the current platform. On Windows,
forward slashes is converted to backward slashes. On all
platforms, the name is normalized as done by <c>join/1</c>.</p>
@@ -272,7 +224,7 @@ name() = string() | atom() | DeepList | RawFilename
</desc>
</func>
<func>
- <name>pathtype(Path) -> absolute | relative | volumerelative</name>
+ <name name="pathtype" arity="1"/>
<fsummary>Return the type of a path</fsummary>
<desc>
<p>Returns the type of path, one of <c>absolute</c>,
@@ -302,16 +254,13 @@ name() = string() | atom() | DeepList | RawFilename
</desc>
</func>
<func>
- <name>rootname(Filename) -> string()</name>
- <name>rootname(Filename, Ext) -> string()</name>
+ <name name="rootname" arity="1"/>
+ <name name="rootname" arity="2"/>
<fsummary>Remove a filename extension</fsummary>
- <type>
- <v>Filename = Ext = name()</v>
- </type>
<desc>
<p>Remove a filename extension. <c>rootname/2</c> works as
<c>rootname/1</c>, except that the extension is removed only
- if it is <c>Ext</c>.</p>
+ if it is <c><anno>Ext</anno></c>.</p>
<pre>
20> <input>filename:rootname("/beam.src/kalle").</input>
/beam.src/kalle"
@@ -324,15 +273,11 @@ name() = string() | atom() | DeepList | RawFilename
</desc>
</func>
<func>
- <name>split(Filename) -> Components</name>
+ <name name="split" arity="1"/>
<fsummary>Split a filename into its path components</fsummary>
- <type>
- <v>Filename = name()</v>
- <v>Components = [string()]</v>
- </type>
<desc>
<p>Returns a list whose elements are the path components of
- <c>Filename</c>.</p>
+ <c><anno>Filename</anno></c>.</p>
<pre>
24> <input>filename:split("/usr/local/bin").</input>
["/","usr","local","bin"]
@@ -343,47 +288,38 @@ name() = string() | atom() | DeepList | RawFilename
</desc>
</func>
<func>
- <name>find_src(Beam) -> {SourceFile, Options} | {error,{ErrorReason,Module}}</name>
- <name>find_src(Beam, Rules) -> {SourceFile, Options} | {error,{ErrorReason,Module}}</name>
+ <name name="find_src" arity="1"/>
+ <name name="find_src" arity="2"/>
<fsummary>Find the filename and compiler options for a module</fsummary>
- <type>
- <v>Beam = Module | Filename</v>
- <v>&nbsp;Module = atom()</v>
- <v>&nbsp;Filename = string() | atom()</v>
- <v>SourceFile = string()</v>
- <v>Options = [Opt]</v>
- <v>&nbsp;Opt = {i, string()} | {outdir, string()} | {d, atom()}</v>
- <v>ErrorReason = non_existing | preloaded | interpreted</v>
- </type>
<desc>
<p>Finds the source filename and compiler options for a module.
The result can be fed to <c>compile:file/2</c> in order to
compile the file again.</p>
- <p>The <c>Beam</c> argument, which can be a string or an atom,
+ <p>The <c><anno>Beam</anno></c> argument, which can be a string or an atom,
specifies either the module name or the path to the source
code, with or without the <c>".erl"</c> extension. In either
case, the module must be known by the code server, i.e.
- <c>code:which(Module)</c> must succeed.</p>
- <p><c>Rules</c> describes how the source directory can be found,
+ <c>code:which(<anno>Module</anno>)</c> must succeed.</p>
+ <p><c><anno>Rules</anno></c> describes how the source directory can be found,
when the object code directory is known. It is a list of
- tuples <c>{BinSuffix, SourceSuffix}</c> and is interpreted
+ tuples <c>{<anno>BinSuffix</anno>, <anno>SourceSuffix</anno>}</c> and is interpreted
as follows: If the end of the directory name where the object
- is located matches <c>BinSuffix</c>, then the source code
- directory has the same name, but with <c>BinSuffix</c>
- replaced by <c>SourceSuffix</c>. <c>Rules</c> defaults to:</p>
+ is located matches <c><anno>BinSuffix</anno></c>, then the source code
+ directory has the same name, but with <c><anno>BinSuffix</anno></c>
+ replaced by <c><anno>SourceSuffix</anno></c>. <c><anno>Rules</anno></c> defaults to:</p>
<code type="none">
[{"", ""}, {"ebin", "src"}, {"ebin", "esrc"}]</code>
<p>If the source file is found in the resulting directory, then
the function returns that location together with
- <c>Options</c>. Otherwise, the next rule is tried, and so on.</p>
+ <c><anno>Options</anno></c>. Otherwise, the next rule is tried, and so on.</p>
- <p>The function returns <c>{SourceFile, Options}</c> if it succeeds.
- <c>SourceFile</c> is the absolute path to the source file
- without the <c>".erl"</c> extension. <c>Options</c> include
+ <p>The function returns <c>{<anno>SourceFile</anno>, <anno>Options</anno>}</c> if it succeeds.
+ <c><anno>SourceFile</anno></c> is the absolute path to the source file
+ without the <c>".erl"</c> extension. <c><anno>Options</anno></c> include
the options which are necessary to recompile the file with
<c>compile:file/2</c>, but excludes options such as
<c>report</c> or <c>verbose</c> which do not change the way
- code is generated. The paths in the <c>{outdir, Path}</c>
+ code is generated. The paths in the <c>{outdir, <anno>Path</anno>}</c>
and <c>{i, Path}</c> options are guaranteed to be
absolute.</p>
diff --git a/lib/stdlib/doc/src/gb_sets.xml b/lib/stdlib/doc/src/gb_sets.xml
index 60d8bcbfa3..f91fac9c82 100644
--- a/lib/stdlib/doc/src/gb_sets.xml
+++ b/lib/stdlib/doc/src/gb_sets.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2001</year><year>2010</year>
+ <year>2001</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -61,7 +61,6 @@
and do the same thing in the <c>sets</c> and <c>ordsets</c>
modules. That is, by only changing the module name for each call,
you can try out different set representations.</p>
- <p></p>
<list type="bulleted">
<item>
<p><c>add_element/2</c></p>
@@ -114,34 +113,32 @@
</list>
</section>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-gb_set() = a GB set</code>
- </section>
+ <datatypes>
+ <datatype>
+ <name><marker id="type-gb_set">gb_set()</marker></name>
+ <desc><p>A GB set.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="iter"/>
+ <desc><p>A GB set iterator.</p></desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>add(Element, Set1) -> Set2</name>
- <name>add_element(Element, Set1) -> Set2</name>
+ <name name="add" arity="2"/>
+ <name name="add_element" arity="2"/>
<fsummary>Add a (possibly existing) element to a gb_set</fsummary>
- <type>
- <v>Element = term()</v>
- <v>Set1 = Set2 = gb_set()</v>
- </type>
<desc>
- <p>Returns a new gb_set formed from <c>Set1</c> with
- <c>Element</c> inserted. If <c>Element</c> is already an
- element in <c>Set1</c>, nothing is changed.</p>
+ <p>Returns a new gb_set formed from <c><anno>Set1</anno></c> with
+ <c><anno>Element</anno></c> inserted. If <c><anno>Element</anno></c> is already an
+ element in <c><anno>Set1</anno></c>, nothing is changed.</p>
</desc>
</func>
<func>
- <name>balance(Set1) -> Set2</name>
+ <name name="balance" arity="1"/>
<fsummary>Rebalance tree representation of a gb_set</fsummary>
- <type>
- <v>Set1 = Set2 = gb_set()</v>
- </type>
<desc>
- <p>Rebalances the tree representation of <c>Set1</c>. Note that
+ <p>Rebalances the tree representation of <c><anno>Set1</anno></c>. Note that
this is rarely necessary, but may be motivated when a large
number of elements have been deleted from the tree without
further insertions. Rebalancing could then be forced in order
@@ -150,208 +147,144 @@ gb_set() = a GB set</code>
</desc>
</func>
<func>
- <name>delete(Element, Set1) -> Set2</name>
+ <name name="delete" arity="2"/>
<fsummary>Remove an element from a gb_set</fsummary>
- <type>
- <v>Element = term()</v>
- <v>Set1 = Set2 = gb_set()</v>
- </type>
<desc>
- <p>Returns a new gb_set formed from <c>Set1</c> with
- <c>Element</c> removed. Assumes that <c>Element</c> is present
- in <c>Set1</c>.</p>
+ <p>Returns a new gb_set formed from <c><anno>Set1</anno></c> with
+ <c><anno>Element</anno></c> removed. Assumes that <c><anno>Element</anno></c> is present
+ in <c><anno>Set1</anno></c>.</p>
</desc>
</func>
<func>
- <name>delete_any(Element, Set1) -> Set2</name>
- <name>del_element(Element, Set1) -> Set2</name>
+ <name name="delete_any" arity="2"/>
+ <name name="del_element" arity="2"/>
<fsummary>Remove a (possibly non-existing) element from a gb_set</fsummary>
- <type>
- <v>Element = term()</v>
- <v>Set1 = Set2 = gb_set()</v>
- </type>
<desc>
- <p>Returns a new gb_set formed from <c>Set1</c> with
- <c>Element</c> removed. If <c>Element</c> is not an element
- in <c>Set1</c>, nothing is changed.</p>
+ <p>Returns a new gb_set formed from <c><anno>Set1</anno></c> with
+ <c><anno>Element</anno></c> removed. If <c><anno>Element</anno></c> is not an element
+ in <c><anno>Set1</anno></c>, nothing is changed.</p>
</desc>
</func>
<func>
- <name>difference(Set1, Set2) -> Set3</name>
- <name>subtract(Set1, Set2) -> Set3</name>
+ <name name="difference" arity="2"/>
+ <name name="subtract" arity="2"/>
<fsummary>Return the difference of two gb_sets</fsummary>
- <type>
- <v>Set1 = Set2 = Set3 = gb_set()</v>
- </type>
<desc>
- <p>Returns only the elements of <c>Set1</c> which are not also
- elements of <c>Set2</c>.</p>
+ <p>Returns only the elements of <c><anno>Set1</anno></c> which are not also
+ elements of <c><anno>Set2</anno></c>.</p>
</desc>
</func>
<func>
- <name>empty() -> Set</name>
- <name>new() -> Set</name>
+ <name name="empty" arity="0"/>
+ <name name="new" arity="0"/>
<fsummary>Return an empty gb_set</fsummary>
- <type>
- <v>Set = gb_set()</v>
- </type>
<desc>
<p>Returns a new empty gb_set.</p>
</desc>
</func>
<func>
- <name>filter(Pred, Set1) -> Set2</name>
+ <name name="filter" arity="2"/>
<fsummary>Filter gb_set elements</fsummary>
- <type>
- <v>Pred = fun (E) -> bool()</v>
- <v>&nbsp;E = term()</v>
- <v>Set1 = Set2 = gb_set()</v>
- </type>
<desc>
- <p>Filters elements in <c>Set1</c> using predicate function
- <c>Pred</c>.</p>
+ <p>Filters elements in <c><anno>Set1</anno></c> using predicate function
+ <c><anno>Pred</anno></c>.</p>
</desc>
</func>
<func>
- <name>fold(Function, Acc0, Set) -> Acc1</name>
+ <name name="fold" arity="3"/>
<fsummary>Fold over gb_set elements</fsummary>
- <type>
- <v>Function = fun (E, AccIn) -> AccOut</v>
- <v>Acc0 = Acc1 = AccIn = AccOut = term()</v>
- <v>&nbsp;E = term()</v>
- <v>Set = gb_set()</v>
- </type>
<desc>
- <p>Folds <c>Function</c> over every element in <c>Set</c>
+ <p>Folds <c><anno>Function</anno></c> over every element in <c><anno>Set</anno></c>
returning the final value of the accumulator.</p>
</desc>
</func>
<func>
- <name>from_list(List) -> Set</name>
+ <name name="from_list" arity="1"/>
<fsummary>Convert a list into a gb_set</fsummary>
- <type>
- <v>List = [term()]</v>
- <v>Set = gb_set()</v>
- </type>
<desc>
- <p>Returns a gb_set of the elements in <c>List</c>, where
- <c>List</c> may be unordered and contain duplicates.</p>
+ <p>Returns a gb_set of the elements in <c><anno>List</anno></c>, where
+ <c><anno>List</anno></c> may be unordered and contain duplicates.</p>
</desc>
</func>
<func>
- <name>from_ordset(List) -> Set</name>
+ <name name="from_ordset" arity="1"/>
<fsummary>Make a gb_set from an ordset list</fsummary>
- <type>
- <v>List = [term()]</v>
- <v>Set = gb_set()</v>
- </type>
<desc>
- <p>Turns an ordered-set list <c>List</c> into a gb_set. The list
+ <p>Turns an ordered-set list <c><anno>List</anno></c> into a gb_set. The list
must not contain duplicates.</p>
</desc>
</func>
<func>
- <name>insert(Element, Set1) -> Set2</name>
+ <name name="insert" arity="2"/>
<fsummary>Add a new element to a gb_set</fsummary>
- <type>
- <v>Element = term()</v>
- <v>Set1 = Set2 = gb_set()</v>
- </type>
<desc>
- <p>Returns a new gb_set formed from <c>Set1</c> with
- <c>Element</c> inserted. Assumes that <c>Element</c> is not
- present in <c>Set1</c>.</p>
+ <p>Returns a new gb_set formed from <c><anno>Set1</anno></c> with
+ <c><anno>Element</anno></c> inserted. Assumes that <c><anno>Element</anno></c> is not
+ present in <c><anno>Set1</anno></c>.</p>
</desc>
</func>
<func>
- <name>intersection(Set1, Set2) -> Set3</name>
+ <name name="intersection" arity="2"/>
<fsummary>Return the intersection of two gb_sets</fsummary>
- <type>
- <v>Set1 = Set2 = Set3 = gb_set()</v>
- </type>
<desc>
- <p>Returns the intersection of <c>Set1</c> and <c>Set2</c>.</p>
+ <p>Returns the intersection of <c><anno>Set1</anno></c> and <c><anno>Set2</anno></c>.</p>
</desc>
</func>
<func>
- <name>intersection(SetList) -> Set</name>
+ <name name="intersection" arity="1"/>
<fsummary>Return the intersection of a list of gb_sets</fsummary>
- <type>
- <v>SetList = [gb_set()]</v>
- <v>Set = gb_set()</v>
- </type>
<desc>
<p>Returns the intersection of the non-empty list of gb_sets.</p>
</desc>
</func>
<func>
- <name>is_disjoint(Set1, Set2) -> bool()</name>
+ <name name="is_disjoint" arity="2"/>
<fsummary>Check whether two gb_sets are disjoint</fsummary>
- <type>
- <v>Set1 = Set2 = gb_set()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Set1</c> and
- <c>Set2</c> are disjoint (have no elements in common),
+ <p>Returns <c>true</c> if <c><anno>Set1</anno></c> and
+ <c><anno>Set2</anno></c> are disjoint (have no elements in common),
and <c>false</c> otherwise.</p>
</desc>
</func>
<func>
- <name>is_empty(Set) -> bool()</name>
+ <name name="is_empty" arity="1"/>
<fsummary>Test for empty gb_set</fsummary>
- <type>
- <v>Set = gb_set()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Set</c> is an empty set, and
+ <p>Returns <c>true</c> if <c><anno>Set</anno></c> is an empty set, and
<c>false</c> otherwise.</p>
</desc>
</func>
<func>
- <name>is_member(Element, Set) -> bool()</name>
- <name>is_element(Element, Set) -> bool()</name>
+ <name name="is_member" arity="2"/>
+ <name name="is_element" arity="2"/>
<fsummary>Test for membership of a gb_set</fsummary>
- <type>
- <v>Element = term()</v>
- <v>Set = gb_set()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Element</c> is an element of
- <c>Set</c>, otherwise <c>false</c>.</p>
+ <p>Returns <c>true</c> if <c><anno>Element</anno></c> is an element of
+ <c><anno>Set</anno></c>, otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>is_set(Term) -> bool()</name>
+ <name name="is_set" arity="1"/>
<fsummary>Test for a gb_set</fsummary>
- <type>
- <v>Term = term()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Set</c> appears to be a gb_set,
+ <p>Returns <c>true</c> if <c><anno>Term</anno></c> appears to be a gb_set,
otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>is_subset(Set1, Set2) -> bool()</name>
+ <name name="is_subset" arity="2"/>
<fsummary>Test for subset</fsummary>
- <type>
- <v>Set1 = Set2 = gb_set()</v>
- </type>
<desc>
- <p>Returns <c>true</c> when every element of <c>Set1</c> is
- also a member of <c>Set2</c>, otherwise <c>false</c>.</p>
+ <p>Returns <c>true</c> when every element of <c><anno>Set1</anno></c> is
+ also a member of <c><anno>Set2</anno></c>, otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>iterator(Set) -> Iter</name>
+ <name name="iterator" arity="1"/>
<fsummary>Return an iterator for a gb_set</fsummary>
- <type>
- <v>Set = gb_set()</v>
- <v>Iter = term()</v>
- </type>
<desc>
<p>Returns an iterator that can be used for traversing the
- entries of <c>Set</c>; see <c>next/1</c>. The implementation
+ entries of <c><anno>Set</anno></c>; see <c>next/1</c>. The implementation
of this is very efficient; traversing the whole set using
<c>next/1</c> is only slightly slower than getting the list
of all elements using <c>to_list/1</c> and traversing that.
@@ -361,118 +294,84 @@ gb_set() = a GB set</code>
</desc>
</func>
<func>
- <name>largest(Set) -> term()</name>
+ <name name="largest" arity="1"/>
<fsummary>Return largest element</fsummary>
- <type>
- <v>Set = gb_set()</v>
- </type>
<desc>
- <p>Returns the largest element in <c>Set</c>. Assumes that
- <c>Set</c> is nonempty.</p>
+ <p>Returns the largest element in <c><anno>Set</anno></c>. Assumes that
+ <c><anno>Set</anno></c> is nonempty.</p>
</desc>
</func>
<func>
- <name>next(Iter1) -> {Element, Iter2} | none</name>
+ <name name="next" arity="1"/>
<fsummary>Traverse a gb_set with an iterator</fsummary>
- <type>
- <v>Iter1 = Iter2 = Element = term()</v>
- </type>
<desc>
- <p>Returns <c>{Element, Iter2}</c> where <c>Element</c> is the
- smallest element referred to by the iterator <c>Iter1</c>,
- and <c>Iter2</c> is the new iterator to be used for
+ <p>Returns <c>{<anno>Element</anno>, <anno>Iter2</anno>}</c> where <c><anno>Element</anno></c> is the
+ smallest element referred to by the iterator <c><anno>Iter1</anno></c>,
+ and <c><anno>Iter2</anno></c> is the new iterator to be used for
traversing the remaining elements, or the atom <c>none</c> if
no elements remain.</p>
</desc>
</func>
<func>
- <name>singleton(Element) -> gb_set()</name>
+ <name name="singleton" arity="1"/>
<fsummary>Return a gb_set with one element</fsummary>
- <type>
- <v>Element = term()</v>
- </type>
<desc>
- <p>Returns a gb_set containing only the element <c>Element</c>.</p>
+ <p>Returns a gb_set containing only the element <c><anno>Element</anno></c>.</p>
</desc>
</func>
<func>
- <name>size(Set) -> int()</name>
+ <name name="size" arity="1"/>
<fsummary>Return the number of elements in a gb_set</fsummary>
- <type>
- <v>Set = gb_set()</v>
- </type>
<desc>
- <p>Returns the number of elements in <c>Set</c>.</p>
+ <p>Returns the number of elements in <c><anno>Set</anno></c>.</p>
</desc>
</func>
<func>
- <name>smallest(Set) -> term()</name>
+ <name name="smallest" arity="1"/>
<fsummary>Return smallest element</fsummary>
- <type>
- <v>Set = gb_set()</v>
- </type>
<desc>
- <p>Returns the smallest element in <c>Set</c>. Assumes that
- <c>Set</c> is nonempty.</p>
+ <p>Returns the smallest element in <c><anno>Set</anno></c>. Assumes that
+ <c><anno>Set</anno></c> is nonempty.</p>
</desc>
</func>
<func>
- <name>take_largest(Set1) -> {Element, Set2}</name>
+ <name name="take_largest" arity="1"/>
<fsummary>Extract largest element</fsummary>
- <type>
- <v>Set1 = Set2 = gb_set()</v>
- <v>Element = term()</v>
- </type>
<desc>
- <p>Returns <c>{Element, Set2}</c>, where <c>Element</c> is the
- largest element in <c>Set1</c>, and <c>Set2</c> is this set
- with <c>Element</c> deleted. Assumes that <c>Set1</c> is
+ <p>Returns <c>{<anno>Element</anno>, <anno>Set2</anno>}</c>, where <c><anno>Element</anno></c> is the
+ largest element in <c><anno>Set1</anno></c>, and <c><anno>Set2</anno></c> is this set
+ with <c><anno>Element</anno></c> deleted. Assumes that <c><anno>Set1</anno></c> is
nonempty.</p>
</desc>
</func>
<func>
- <name>take_smallest(Set1) -> {Element, Set2}</name>
+ <name name="take_smallest" arity="1"/>
<fsummary>Extract smallest element</fsummary>
- <type>
- <v>Set1 = Set2 = gb_set()</v>
- <v>Element = term()</v>
- </type>
<desc>
- <p>Returns <c>{Element, Set2}</c>, where <c>Element</c> is the
- smallest element in <c>Set1</c>, and <c>Set2</c> is this set
- with <c>Element</c> deleted. Assumes that <c>Set1</c> is
+ <p>Returns <c>{<anno>Element</anno>, <anno>Set2</anno>}</c>, where <c><anno>Element</anno></c> is the
+ smallest element in <c><anno>Set1</anno></c>, and <c><anno>Set2</anno></c> is this set
+ with <c><anno>Element</anno></c> deleted. Assumes that <c><anno>Set1</anno></c> is
nonempty.</p>
</desc>
</func>
<func>
- <name>to_list(Set) -> List</name>
+ <name name="to_list" arity="1"/>
<fsummary>Convert a gb_set into a list</fsummary>
- <type>
- <v>Set = gb_set()</v>
- <v>List = [term()]</v>
- </type>
<desc>
- <p>Returns the elements of <c>Set</c> as a list.</p>
+ <p>Returns the elements of <c><anno>Set</anno></c> as a list.</p>
</desc>
</func>
<func>
- <name>union(Set1, Set2) -> Set3</name>
+ <name name="union" arity="2"/>
<fsummary>Return the union of two gb_sets</fsummary>
- <type>
- <v>Set1 = Set2 = Set3 = gb_set()</v>
- </type>
<desc>
- <p>Returns the merged (union) gb_set of <c>Set1</c> and
- <c>Set2</c>.</p>
+ <p>Returns the merged (union) gb_set of <c><anno>Set1</anno></c> and
+ <c><anno>Set2</anno></c>.</p>
</desc>
</func>
<func>
- <name>union(SetList) -> Set</name>
+ <name name="union" arity="1"/>
<fsummary>Return the union of a list of gb_sets</fsummary>
- <type>
- <v>SetList = [gb_set()]</v>
- <v>Set = gb_set()</v>
- </type>
<desc>
<p>Returns the merged (union) gb_set of the list of gb_sets.</p>
</desc>
diff --git a/lib/stdlib/doc/src/gb_trees.xml b/lib/stdlib/doc/src/gb_trees.xml
index 94f40c28bd..65c866efbe 100644
--- a/lib/stdlib/doc/src/gb_trees.xml
+++ b/lib/stdlib/doc/src/gb_trees.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2001</year><year>2010</year>
+ <year>2001</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -57,20 +57,22 @@
trees. Behaviour is logarithmic (as it should be).</p>
</section>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-gb_tree() = a GB tree</code>
- </section>
+ <datatypes>
+ <datatype>
+ <name><marker id="type-gb_tree">gb_tree()</marker></name>
+ <desc><p>A GB tree.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="iter"/>
+ <desc><p>A GB tree iterator.</p></desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>balance(Tree1) -> Tree2</name>
+ <name name="balance" arity="1"/>
<fsummary>Rebalance a tree</fsummary>
- <type>
- <v>Tree1 = Tree2 = gb_tree()</v>
- </type>
<desc>
- <p>Rebalances <c>Tree1</c>. Note that this is rarely necessary,
+ <p>Rebalances <c><anno>Tree1</anno></c>. Note that this is rarely necessary,
but may be motivated when a large number of nodes have been
deleted from the tree without further insertions. Rebalancing
could then be forced in order to minimise lookup times, since
@@ -78,139 +80,97 @@ gb_tree() = a GB tree</code>
</desc>
</func>
<func>
- <name>delete(Key, Tree1) -> Tree2</name>
+ <name name="delete" arity="2"/>
<fsummary>Remove a node from a tree</fsummary>
- <type>
- <v>Key = term()</v>
- <v>Tree1 = Tree2 = gb_tree()</v>
- </type>
<desc>
- <p>Removes the node with key <c>Key</c> from <c>Tree1</c>;
+ <p>Removes the node with key <c><anno>Key</anno></c> from <c><anno>Tree1</anno></c>;
returns new tree. Assumes that the key is present in the tree,
crashes otherwise.</p>
</desc>
</func>
<func>
- <name>delete_any(Key, Tree1) -> Tree2</name>
+ <name name="delete_any" arity="2"/>
<fsummary>Remove a (possibly non-existing) node from a tree</fsummary>
- <type>
- <v>Key = term()</v>
- <v>Tree1 = Tree2 = gb_tree()</v>
- </type>
<desc>
- <p>Removes the node with key <c>Key</c> from <c>Tree1</c> if
+ <p>Removes the node with key <c><anno>Key</anno></c> from <c><anno>Tree1</anno></c> if
the key is present in the tree, otherwise does nothing;
returns new tree.</p>
</desc>
</func>
<func>
- <name>empty() -> Tree</name>
+ <name name="empty" arity="0"/>
<fsummary>Return an empty tree</fsummary>
- <type>
- <v>Tree = gb_tree()</v>
- </type>
<desc>
<p>Returns a new empty tree</p>
</desc>
</func>
<func>
- <name>enter(Key, Val, Tree1) -> Tree2</name>
+ <name name="enter" arity="3"/>
<fsummary>Insert or update key with value in a tree</fsummary>
- <type>
- <v>Key = Val = term()</v>
- <v>Tree1 = Tree2 = gb_tree()</v>
- </type>
<desc>
- <p>Inserts <c>Key</c> with value <c>Val</c> into <c>Tree1</c> if
+ <p>Inserts <c><anno>Key</anno></c> with value <c><anno>Val</anno></c> into <c><anno>Tree1</anno></c> if
the key is not present in the tree, otherwise updates
- <c>Key</c> to value <c>Val</c> in <c>Tree1</c>. Returns the
+ <c><anno>Key</anno></c> to value <c><anno>Val</anno></c> in <c><anno>Tree1</anno></c>. Returns the
new tree.</p>
</desc>
</func>
<func>
- <name>from_orddict(List) -> Tree</name>
+ <name name="from_orddict" arity="1"/>
<fsummary>Make a tree from an orddict</fsummary>
- <type>
- <v>List = [{Key, Val}]</v>
- <v>&nbsp;Key = Val = term()</v>
- <v>Tree = gb_tree()</v>
- </type>
<desc>
- <p>Turns an ordered list <c>List</c> of key-value tuples into a
+ <p>Turns an ordered list <c><anno>List</anno></c> of key-value tuples into a
tree. The list must not contain duplicate keys.</p>
</desc>
</func>
<func>
- <name>get(Key, Tree) -> Val</name>
+ <name name="get" arity="2"/>
<fsummary>Look up a key in a tree, if present</fsummary>
- <type>
- <v>Key = Val = term()</v>
- <v>Tree = gb_tree()</v>
- </type>
<desc>
- <p>Retrieves the value stored with <c>Key</c> in <c>Tree</c>.
+ <p>Retrieves the value stored with <c><anno>Key</anno></c> in <c><anno>Tree</anno></c>.
Assumes that the key is present in the tree, crashes
otherwise.</p>
</desc>
</func>
<func>
- <name>lookup(Key, Tree) -> {value, Val} | none</name>
+ <name name="lookup" arity="2"/>
<fsummary>Look up a key in a tree</fsummary>
- <type>
- <v>Key = Val = term()</v>
- <v>Tree = gb_tree()</v>
- </type>
<desc>
- <p>Looks up <c>Key</c> in <c>Tree</c>; returns
- <c>{value, Val}</c>, or <c>none</c> if <c>Key</c> is not
+ <p>Looks up <c><anno>Key</anno></c> in <c><anno>Tree</anno></c>; returns
+ <c>{value, <anno>Val</anno>}</c>, or <c>none</c> if <c><anno>Key</anno></c> is not
present.</p>
</desc>
</func>
<func>
- <name>insert(Key, Val, Tree1) -> Tree2</name>
+ <name name="insert" arity="3"/>
<fsummary>Insert a new key and value in a tree</fsummary>
- <type>
- <v>Key = Val = term()</v>
- <v>Tree1 = Tree2 = gb_tree()</v>
- </type>
<desc>
- <p>Inserts <c>Key</c> with value <c>Val</c> into <c>Tree1</c>;
+ <p>Inserts <c><anno>Key</anno></c> with value <c><anno>Val</anno></c> into <c><anno>Tree1</anno></c>;
returns the new tree. Assumes that the key is not present in
the tree, crashes otherwise.</p>
</desc>
</func>
<func>
- <name>is_defined(Key, Tree) -> bool()</name>
+ <name name="is_defined" arity="2"/>
<fsummary>Test for membership of a tree</fsummary>
- <type>
- <v>Tree = gb_tree()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Key</c> is present in <c>Tree</c>,
+ <p>Returns <c>true</c> if <c><anno>Key</anno></c> is present in <c><anno>Tree</anno></c>,
otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>is_empty(Tree) -> bool()</name>
+ <name name="is_empty" arity="1"/>
<fsummary>Test for empty tree</fsummary>
- <type>
- <v>Tree = gb_tree()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Tree</c> is an empty tree, and
+ <p>Returns <c>true</c> if <c><anno>Tree</anno></c> is an empty tree, and
<c>false</c> otherwise.</p>
</desc>
</func>
<func>
- <name>iterator(Tree) -> Iter</name>
+ <name name="iterator" arity="1"/>
<fsummary>Return an iterator for a tree</fsummary>
- <type>
- <v>Tree = gb_tree()</v>
- <v>Iter = term()</v>
- </type>
<desc>
<p>Returns an iterator that can be used for traversing the
- entries of <c>Tree</c>; see <c>next/1</c>. The implementation
+ entries of <c><anno>Tree</anno></c>; see <c>next/1</c>. The implementation
of this is very efficient; traversing the whole tree using
<c>next/1</c> is only slightly slower than getting the list
of all elements using <c>to_list/1</c> and traversing that.
@@ -220,141 +180,99 @@ gb_tree() = a GB tree</code>
</desc>
</func>
<func>
- <name>keys(Tree) -> [Key]</name>
+ <name name="keys" arity="1"/>
<fsummary>Return a list of the keys in a tree</fsummary>
- <type>
- <v>Tree = gb_tree()</v>
- <v>Key = term()</v>
- </type>
<desc>
- <p>Returns the keys in <c>Tree</c> as an ordered list.</p>
+ <p>Returns the keys in <c><anno>Tree</anno></c> as an ordered list.</p>
</desc>
</func>
<func>
- <name>largest(Tree) -> {Key, Val}</name>
+ <name name="largest" arity="1"/>
<fsummary>Return largest key and value</fsummary>
- <type>
- <v>Tree = gb_tree()</v>
- <v>Key = Val = term()</v>
- </type>
<desc>
- <p>Returns <c>{Key, Val}</c>, where <c>Key</c> is the largest
- key in <c>Tree</c>, and <c>Val</c> is the value associated
+ <p>Returns <c>{<anno>Key</anno>, <anno>Val</anno>}</c>, where <c><anno>Key</anno></c> is the largest
+ key in <c><anno>Tree</anno></c>, and <c><anno>Val</anno></c> is the value associated
with this key. Assumes that the tree is nonempty.</p>
</desc>
</func>
<func>
- <name>map(Function, Tree1) -> Tree2</name>
+ <name name="map" arity="2"/>
<fsummary>Return largest key and value</fsummary>
- <type>
- <v>Function = fun(K, V1) -> V2</v>
- <v>Tree1 = Tree2 = gb_tree()</v>
- </type>
- <desc><p>maps the function F(K, V1) -> V2 to all key-value pairs
- of the tree Tree1 and returns a new tree Tree2 with the same set of keys
- as Tree1 and the new set of values V2.</p>
+ <desc><p>Maps the function F(<anno>K</anno>, <anno>V1</anno>) -> <anno>V2</anno> to all key-value pairs
+ of the tree <c><anno>Tree1</anno></c> and returns a new tree <c><anno>Tree2</anno></c> with the same set of keys
+ as <c><anno>Tree1</anno></c> and the new set of values <c><anno>V2</anno></c>.</p>
</desc>
</func>
<func>
- <name>next(Iter1) -> {Key, Val, Iter2} | none</name>
+ <name name="next" arity="1"/>
<fsummary>Traverse a tree with an iterator</fsummary>
- <type>
- <v>Iter1 = Iter2 = Key = Val = term()</v>
- </type>
<desc>
- <p>Returns <c>{Key, Val, Iter2}</c> where <c>Key</c> is the
- smallest key referred to by the iterator <c>Iter1</c>, and
- <c>Iter2</c> is the new iterator to be used for
+ <p>Returns <c>{<anno>Key</anno>, <anno>Val</anno>, <anno>Iter2</anno>}</c> where <c><anno>Key</anno></c> is the
+ smallest key referred to by the iterator <c><anno>Iter1</anno></c>, and
+ <c><anno>Iter2</anno></c> is the new iterator to be used for
traversing the remaining nodes, or the atom <c>none</c> if no
nodes remain.</p>
</desc>
</func>
<func>
- <name>size(Tree) -> int()</name>
+ <name name="size" arity="1"/>
<fsummary>Return the number of nodes in a tree</fsummary>
- <type>
- <v>Tree = gb_tree()</v>
- </type>
<desc>
- <p>Returns the number of nodes in <c>Tree</c>.</p>
+ <p>Returns the number of nodes in <c><anno>Tree</anno></c>.</p>
</desc>
</func>
<func>
- <name>smallest(Tree) -> {Key, Val}</name>
+ <name name="smallest" arity="1"/>
<fsummary>Return smallest key and value</fsummary>
- <type>
- <v>Tree = gb_tree()</v>
- <v>Key = Val = term()</v>
- </type>
<desc>
- <p>Returns <c>{Key, Val}</c>, where <c>Key</c> is the smallest
- key in <c>Tree</c>, and <c>Val</c> is the value associated
+ <p>Returns <c>{<anno>Key</anno>, <anno>Val</anno>}</c>, where <c><anno>Key</anno></c> is the smallest
+ key in <c><anno>Tree</anno></c>, and <c><anno>Val</anno></c> is the value associated
with this key. Assumes that the tree is nonempty.</p>
</desc>
</func>
<func>
- <name>take_largest(Tree1) -> {Key, Val, Tree2}</name>
+ <name name="take_largest" arity="1"/>
<fsummary>Extract largest key and value</fsummary>
- <type>
- <v>Tree1 = Tree2 = gb_tree()</v>
- <v>Key = Val = term()</v>
- </type>
<desc>
- <p>Returns <c>{Key, Val, Tree2}</c>, where <c>Key</c> is the
- largest key in <c>Tree1</c>, <c>Val</c> is the value
- associated with this key, and <c>Tree2</c> is this tree with
+ <p>Returns <c>{<anno>Key</anno>, <anno>Val</anno>, <anno>Tree2</anno>}</c>, where <c><anno>Key</anno></c> is the
+ largest key in <c><anno>Tree1</anno></c>, <c><anno>Val</anno></c> is the value
+ associated with this key, and <c><anno>Tree2</anno></c> is this tree with
the corresponding node deleted. Assumes that the tree is
nonempty.</p>
</desc>
</func>
<func>
- <name>take_smallest(Tree1) -> {Key, Val, Tree2}</name>
+ <name name="take_smallest" arity="1"/>
<fsummary>Extract smallest key and value</fsummary>
- <type>
- <v>Tree1 = Tree2 = gb_tree()</v>
- <v>Key = Val = term()</v>
- </type>
<desc>
- <p>Returns <c>{Key, Val, Tree2}</c>, where <c>Key</c> is the
- smallest key in <c>Tree1</c>, <c>Val</c> is the value
- associated with this key, and <c>Tree2</c> is this tree with
+ <p>Returns <c>{<anno>Key</anno>, <anno>Val</anno>, <anno>Tree2</anno>}</c>, where <c><anno>Key</anno></c> is the
+ smallest key in <c><anno>Tree1</anno></c>, <c><anno>Val</anno></c> is the value
+ associated with this key, and <c><anno>Tree2</anno></c> is this tree with
the corresponding node deleted. Assumes that the tree is
nonempty.</p>
</desc>
</func>
<func>
- <name>to_list(Tree) -> [{Key, Val}]</name>
+ <name name="to_list" arity="1"/>
<fsummary>Convert a tree into a list</fsummary>
- <type>
- <v>Tree = gb_tree()</v>
- <v>Key = Val = term()</v>
- </type>
<desc>
<p>Converts a tree into an ordered list of key-value tuples.</p>
</desc>
</func>
<func>
- <name>update(Key, Val, Tree1) -> Tree2</name>
+ <name name="update" arity="3"/>
<fsummary>Update a key to new value in a tree</fsummary>
- <type>
- <v>Key = Val = term()</v>
- <v>Tree1 = Tree2 = gb_tree()</v>
- </type>
<desc>
- <p>Updates <c>Key</c> to value <c>Val</c> in <c>Tree1</c>;
+ <p>Updates <c><anno>Key</anno></c> to value <c><anno>Val</anno></c> in <c><anno>Tree1</anno></c>;
returns the new tree. Assumes that the key is present in the
tree.</p>
</desc>
</func>
<func>
- <name>values(Tree) -> [Val]</name>
+ <name name="values" arity="1"/>
<fsummary>Return a list of the values in a tree</fsummary>
- <type>
- <v>Tree = gb_tree()</v>
- <v>Val = term()</v>
- </type>
<desc>
- <p>Returns the values in <c>Tree</c> as an ordered list, sorted
+ <p>Returns the values in <c><anno>Tree</anno></c> as an ordered list, sorted
by their corresponding keys. Duplicates are not removed.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/gen_event.xml b/lib/stdlib/doc/src/gen_event.xml
index 2234a62ac3..24bcb419fe 100644
--- a/lib/stdlib/doc/src/gen_event.xml
+++ b/lib/stdlib/doc/src/gen_event.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2010</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -100,6 +100,20 @@ gen_event:stop -----> Module:terminate/2
the specified event manager does not exist or if bad arguments are
given.</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="handler"/>
+ </datatype>
+ <datatype>
+ <name name="handler_args"/>
+ </datatype>
+ <datatype>
+ <name name="add_handler_ret"/>
+ </datatype>
+ <datatype>
+ <name name="del_handler_ret"/>
+ </datatype>
+ </datatypes>
<funcs>
<func>
<name>start_link() -> Result</name>
diff --git a/lib/stdlib/doc/src/gen_fsm.xml b/lib/stdlib/doc/src/gen_fsm.xml
index d15383c621..421eeb4fd3 100644
--- a/lib/stdlib/doc/src/gen_fsm.xml
+++ b/lib/stdlib/doc/src/gen_fsm.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2010</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -430,7 +430,6 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4
denote a state of the state machine. <em>state data</em> is used
to denote the internal state of the Erlang process which
implements the state machine.</p>
- <p></p>
</section>
<funcs>
<func>
@@ -438,7 +437,7 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4
<fsummary>Initialize process and internal state name and state data.</fsummary>
<type>
<v>Args = term()</v>
- <v>Return = {ok,StateName,StateData} | {ok,StateName,StateData,Timeout}</v>
+ <v>Result = {ok,StateName,StateData} | {ok,StateName,StateData,Timeout}</v>
<v>&nbsp;&nbsp;| {ok,StateName,StateData,hibernate}</v>
<v>&nbsp;&nbsp;| {stop,Reason} | ignore</v>
<v>&nbsp;StateName = atom()</v>
@@ -639,9 +638,9 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4
<v>StateName = atom()</v>
<v>StateData = term()</v>
<v>Result = {next_state,NextStateName,NewStateData}</v>
- <v>&nbsp;>&nbsp;| {next_state,NextStateName,NewStateData,Timeout}</v>
- <v>&nbsp;>&nbsp;| {next_state,NextStateName,NewStateData,hibernate}</v>
- <v>&nbsp;>&nbsp;| {stop,Reason,NewStateData}</v>
+ <v>&nbsp;&nbsp;| {next_state,NextStateName,NewStateData,Timeout}</v>
+ <v>&nbsp;&nbsp;| {next_state,NextStateName,NewStateData,hibernate}</v>
+ <v>&nbsp;&nbsp;| {stop,Reason,NewStateData}</v>
<v>&nbsp;NextStateName = atom()</v>
<v>&nbsp;NewStateData = term()</v>
<v>&nbsp;Timeout = int()>0 | infinity</v>
diff --git a/lib/stdlib/doc/src/io.xml b/lib/stdlib/doc/src/io.xml
index 41e3e92c59..667d758e29 100644
--- a/lib/stdlib/doc/src/io.xml
+++ b/lib/stdlib/doc/src/io.xml
@@ -43,7 +43,7 @@
<p>As of R13A, data supplied to the <seealso
marker="#put_chars/2">put_chars</seealso> function should be in the
- <c>chardata()</c> format described below. This means that programs
+ <seealso marker="unicode#type-chardata"><c>unicode:chardata()</c></seealso> format. This means that programs
supplying binaries to this function need to convert them to UTF-8
before trying to output the data on an
<c>io_device()</c>.</p>
@@ -64,76 +64,84 @@
</description>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-io_device()
- as returned by file:open/2, a process handling IO protocols</code>
-
- <code type="none">
-unicode_binary() = binary() with characters encoded in UTF-8 coding standard
-unicode_char() = integer() representing valid unicode codepoint
-
-chardata() = charlist() | unicode_binary()
+ <datatypes>
+ <datatype>
+ <name name="device"/>
+ <desc>
+ <p>Either <c>standard_io</c>, <c>standard_error</c>, a
+ registered name, or a pid handling IO protocols (returned from
+ <seealso marker="file#open/2">file:open/2</seealso>).</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="opt_pair"/>
+ </datatype>
+ <datatype>
+ <name name="expand_fun"/>
+ </datatype>
+ <datatype>
+ <name name="encoding"/>
+ </datatype>
+ <datatype>
+ <name name="setopt"/>
+ </datatype>
+ <datatype>
+ <name name="format"/>
+ </datatype>
+ <datatype>
+ <name name="line"/>
+ </datatype>
+ <datatype>
+ <name name="prompt"/>
+ </datatype>
+ <datatype>
+ <name name="request_error"/>
+ </datatype>
+ <datatype>
+ <name name="error_description"/>
+ <desc><p>Whatever the I/O-server sends.</p></desc>
+ </datatype>
+ </datatypes>
-charlist() = [unicode_char() | unicode_binary() | charlist()]
- a unicode_binary is allowed as the tail of the list</code>
- </section>
<funcs>
<func>
- <name>columns() -> {ok,int()} | {error, enotsup}</name>
- <name>columns(IoDevice) -> {ok,int()} | {error, enotsup}</name>
+ <name name="columns" arity="0"/>
+ <name name="columns" arity="1"/>
<fsummary>Get the number of columns of a device</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- </type>
<desc>
<p>Retrieves the number of columns of the
- <c>IoDevice</c> (i.e. the width of a terminal). The function
+ <c><anno>IoDevice</anno></c> (i.e. the width of a terminal). The function
only succeeds for terminal devices, for all other devices
the function returns <c>{error, enotsup}</c></p>
</desc>
</func>
<func>
- <name>put_chars(IoData) -> ok</name>
- <name>put_chars(IoDevice, IoData) -> ok</name>
+ <name name="put_chars" arity="1"/>
+ <name name="put_chars" arity="2"/>
<fsummary>Write a list of characters</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>IoData = chardata()</v>
- </type>
<desc>
- <p>Writes the characters of <c>IoData</c> to the io_server()
- (<c>IoDevice</c>).</p>
+ <p>Writes the characters of <c><anno>CharData</anno></c> to the io_server()
+ (<c><anno>IoDevice</anno></c>).</p>
</desc>
</func>
<func>
- <name>nl() -> ok</name>
- <name>nl(IoDevice) -> ok</name>
+ <name name="nl" arity="0"/>
+ <name name="nl" arity="1"/>
<fsummary>Write a newline</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- </type>
<desc>
- <p>Writes new line to the standard output (<c>IoDevice</c>).</p>
+ <p>Writes new line to the standard output (<c><anno>IoDevice</anno></c>).</p>
</desc>
</func>
<func>
- <name>get_chars(Prompt, Count) -> Data | eof</name>
- <name>get_chars(IoDevice, Prompt, Count) -> Data | eof</name>
+ <name name="get_chars" arity="2"/>
+ <name name="get_chars" arity="3"/>
<fsummary>Read a specified number of characters</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Prompt = atom() | string()</v>
- <v>Count = int()</v>
- <v>Data = [ unicode_char() ] | unicode_binary()</v>
- </type>
<desc>
- <p>Reads <c>Count</c> characters from standard input
- (<c>IoDevice</c>), prompting it with <c>Prompt</c>. It
+ <p>Reads <c><anno>Count</anno></c> characters from standard input
+ (<c><anno>IoDevice</anno></c>), prompting it with <c><anno>Prompt</anno></c>. It
returns:</p>
<taglist>
- <tag><c>Data</c></tag>
+ <tag><c><anno>Data</anno></c></tag>
<item>
<p>The input characters. If the device supports Unicode,
the data may represent codepoints larger than 255 (the
@@ -145,7 +153,7 @@ charlist() = [unicode_char() | unicode_binary() | charlist()]
<item>
<p>End of file was encountered.</p>
</item>
- <tag><c>{error,Reason}</c></tag>
+ <tag><c>{error,<anno>Reason</anno>}</c></tag>
<item>
<p>Other (rare) error condition, for instance <c>{error,estale}</c>
if reading from an NFS file system.</p>
@@ -154,19 +162,14 @@ charlist() = [unicode_char() | unicode_binary() | charlist()]
</desc>
</func>
<func>
- <name>get_line(Prompt) -> Data | eof | {error,Reason}</name>
- <name>get_line(IoDevice, Prompt) -> Data | eof | {error,Reason}</name>
+ <name name="get_line" arity="1"/>
+ <name name="get_line" arity="2"/>
<fsummary>Read a line</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Prompt = atom() | string()</v>
- <v>Data = [ unicode_char() ] | unicode_binary()</v>
- </type>
<desc>
- <p>Reads a line from the standard input (<c>IoDevice</c>),
- prompting it with <c>Prompt</c>. It returns:</p>
+ <p>Reads a line from the standard input (<c><anno>IoDevice</anno></c>),
+ prompting it with <c><anno>Prompt</anno></c>. It returns:</p>
<taglist>
- <tag><c>Data</c></tag>
+ <tag><c><anno>Data</anno></c></tag>
<item>
<p>The characters in the line terminated by a LF (or end of
file). If the device supports Unicode,
@@ -179,7 +182,7 @@ charlist() = [unicode_char() | unicode_binary() | charlist()]
<item>
<p>End of file was encountered.</p>
</item>
- <tag><c>{error,Reason}</c></tag>
+ <tag><c>{error,<anno>Reason</anno>}</c></tag>
<item>
<p>Other (rare) error condition, for instance <c>{error,estale}</c>
if reading from an NFS file system.</p>
@@ -188,15 +191,9 @@ charlist() = [unicode_char() | unicode_binary() | charlist()]
</desc>
</func>
<func>
- <name>getopts() -> Opts</name>
- <name>getopts(IoDevice) -> Opts</name>
+ <name name="getopts" arity="0"/>
+ <name name="getopts" arity="1"/>
<fsummary>Get the supported options and values from an I/O-server</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Opts = [Opt]</v>
- <v>&nbsp;&nbsp;Opt = {atom(),Value}</v>
- <v>&nbsp;&nbsp;Value = term()</v>
- </type>
<desc>
<p>This function requests all available options and their current values for a specific io_device(). Example:</p>
<pre>
@@ -216,18 +213,11 @@ charlist() = [unicode_char() | unicode_binary() | charlist()]
</desc>
</func>
<func>
- <name>setopts(Opts) -> ok | {error, Reason}</name>
- <name>setopts(IoDevice, Opts) -> ok | {error, Reason}</name>
+ <name name="setopts" arity="1"/>
+ <name name="setopts" arity="2"/>
<fsummary>Set options</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Opts = [Opt]</v>
- <v>&nbsp;&nbsp;Opt = atom() | {atom(),Value}</v>
- <v>&nbsp;&nbsp;Value = term()</v>
- <v>Reason = term()</v>
- </type>
<desc>
- <p>Set options for the io_device() (<c>IoDevice</c>).</p>
+ <p>Set options for the io_device() (<c><anno>IoDevice</anno></c>).</p>
<p>Possible options and values vary depending on the actual
io_device(). For a list of supported options and their current values
@@ -236,17 +226,17 @@ charlist() = [unicode_char() | unicode_binary() | charlist()]
<p>The options and values supported by the current OTP io_devices are:</p>
<taglist>
- <tag><c>binary, list or {binary, bool()}</c></tag>
+ <tag><c>binary, list or {binary, boolean()}</c></tag>
<item>
<p>If set in binary mode (binary or {binary,true}), the io_server() sends binary data (encoded in UTF-8) as answers to the get_line, get_chars and, if possible, get_until requests (see the I/O protocol description in STDLIB User's Guide for details). The immediate effect is that <c>get_chars/2,3</c> and <c>get_line/1,2</c> return UTF-8 binaries instead of lists of chars for the affected device.</p>
<p>By default, all io_devices in OTP are set in list mode, but the io functions can handle any of these modes and so should other, user written, modules behaving as clients to I/O-servers.</p>
<p>This option is supported by the standard shell (group.erl), the 'oldshell' (user.erl) and the file I/O servers.</p>
</item>
- <tag><c>{echo, bool()}</c></tag>
+ <tag><c>{echo, boolean()}</c></tag>
<item>
<p>Denotes if the terminal should echo input. Only supported for the standard shell I/O-server (group.erl)</p>
</item>
- <tag><c>{expand_fun, fun()}</c></tag>
+ <tag><c>{expand_fun, expand_fun()}</c></tag>
<item>
<p>Provide a function for tab-completion (expansion)
like the erlang shell. This function is called
@@ -288,35 +278,24 @@ charlist() = [unicode_char() | unicode_binary() | charlist()]
</desc>
</func>
<func>
- <name>write(Term) -> ok</name>
- <name>write(IoDevice, Term) -> ok</name>
+ <name name="write" arity="1"/>
+ <name name="write" arity="2"/>
<fsummary>Write a term</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Term = term()</v>
- </type>
<desc>
- <p>Writes the term <c>Term</c> to the standard output
- (<c>IoDevice</c>).</p>
+ <p>Writes the term <c><anno>Term</anno></c> to the standard output
+ (<c><anno>IoDevice</anno></c>).</p>
</desc>
</func>
<func>
- <name>read(Prompt) -> Result</name>
- <name>read(IoDevice, Prompt) -> Result</name>
+ <name name="read" arity="1"/>
+ <name name="read" arity="2"/>
<fsummary>Read a term</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Prompt = atom() | string()</v>
- <v>Result = {ok, Term} | eof | {error, ErrorInfo}</v>
- <v>&nbsp;Term = term()</v>
- <v>&nbsp;ErrorInfo -- see section Error Information below</v>
- </type>
<desc>
- <p>Reads a term <c>Term</c> from the standard input
- (<c>IoDevice</c>), prompting it with <c>Prompt</c>. It
+ <p>Reads a term <c><anno>Term</anno></c> from the standard input
+ (<c><anno>IoDevice</anno></c>), prompting it with <c><anno>Prompt</anno></c>. It
returns:</p>
<taglist>
- <tag><c>{ok, Term}</c></tag>
+ <tag><c>{ok, <anno>Term</anno>}</c></tag>
<item>
<p>The parsing was successful.</p>
</item>
@@ -324,7 +303,7 @@ charlist() = [unicode_char() | unicode_binary() | charlist()]
<item>
<p>End of file was encountered.</p>
</item>
- <tag><c>{error, ErrorInfo}</c></tag>
+ <tag><c>{error, <anno>ErrorInfo</anno>}</c></tag>
<item>
<p>The parsing failed.</p>
</item>
@@ -332,31 +311,22 @@ charlist() = [unicode_char() | unicode_binary() | charlist()]
</desc>
</func>
<func>
- <name>read(IoDevice, Prompt, StartLine) -> Result</name>
+ <name name="read" arity="3"/>
<fsummary>Read a term</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Prompt = atom() | string()</v>
- <v>StartLine = int()</v>
- <v>Result = {ok, Term, EndLine} | {eof, EndLine} | {error, ErrorInfo, EndLine}</v>
- <v>&nbsp;Term = term()</v>
- <v>&nbsp;EndLine = int()</v>
- <v>&nbsp;ErrorInfo -- see section Error Information below</v>
- </type>
<desc>
- <p>Reads a term <c>Term</c> from <c>IoDevice</c>, prompting it
- with <c>Prompt</c>. Reading starts at line number
- <c>StartLine</c>. It returns:</p>
+ <p>Reads a term <c><anno>Term</anno></c> from <c><anno>IoDevice</anno></c>, prompting it
+ with <c><anno>Prompt</anno></c>. Reading starts at line number
+ <c><anno>StartLine</anno></c>. It returns:</p>
<taglist>
- <tag><c>{ok, Term, EndLine}</c></tag>
+ <tag><c>{ok, Term, <anno>EndLine</anno>}</c></tag>
<item>
<p>The parsing was successful.</p>
</item>
- <tag><c>{eof, EndLine}</c></tag>
+ <tag><c>{eof, <anno>EndLine</anno>}</c></tag>
<item>
<p>End of file was encountered.</p>
</item>
- <tag><c>{error, ErrorInfo, EndLine}</c></tag>
+ <tag><c>{error, <anno>ErrorInfo</anno>, <anno>ErrorLine</anno>}</c></tag>
<item>
<p>The parsing failed.</p>
</item>
@@ -364,24 +334,19 @@ charlist() = [unicode_char() | unicode_binary() | charlist()]
</desc>
</func>
<func>
- <name>fwrite(Format) -></name>
- <name>fwrite(Format, Data) -> ok</name>
- <name>fwrite(IoDevice, Format, Data) -> ok</name>
- <name>format(Format) -></name>
- <name>format(Format, Data) -> ok</name>
- <name>format(IoDevice, Format, Data) -> ok</name>
+ <name name="fwrite" arity="1"/>
+ <name name="fwrite" arity="2"/>
+ <name name="fwrite" arity="3"/>
+ <name name="format" arity="1"/>
+ <name name="format" arity="2"/>
+ <name name="format" arity="3"/>
<fsummary>Write formatted output</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Format = atom() | string() | binary()</v>
- <v>Data = [term()]</v>
- </type>
<desc>
- <p>Writes the items in <c>Data</c> (<c>[]</c>) on the standard
- output (<c>IoDevice</c>) in accordance with <c>Format</c>.
- <c>Format</c> contains plain characters which are copied to
+ <p>Writes the items in <c><anno>Data</anno></c> (<c>[]</c>) on the standard
+ output (<c><anno>IoDevice</anno></c>) in accordance with <c><anno>Format</anno></c>.
+ <c><anno>Format</anno></c> contains plain characters which are copied to
the output device, and control sequences for formatting, see
- below. If <c>Format</c> is an atom or a binary, it is first
+ below. If <c><anno>Format</anno></c> is an atom or a binary, it is first
converted to a list with the aid of <c>atom_to_list/1</c>
or <c>binary_to_list/1</c>.</p>
<pre>
@@ -474,7 +439,7 @@ ok</pre>
<item>
<p>Prints the argument with the <c>string</c> syntax. The
argument is, if no Unicode translation modifier is present, an
- <seealso marker="erts:erlang#iolist_definition">I/O list</seealso>, a binary, or an atom. If the Unicode translation modifier ('t') is in effect, the argument is chardata(), meaning that binaries are in UTF-8. The characters
+ iolist(), a binary, or an atom. If the Unicode translation modifier ('t') is in effect, the argument is unicode:chardata(), meaning that binaries are in UTF-8. The characters
are printed without quotes. The string is first truncated
by the given precision and then padded and justified
to the given field width. The default precision is the field width.</p>
@@ -673,23 +638,15 @@ ok
</desc>
</func>
<func>
- <name>fread(Prompt, Format) -> Result</name>
- <name>fread(IoDevice, Prompt, Format) -> Result</name>
+ <name name="fread" arity="2"/>
+ <name name="fread" arity="3"/>
<fsummary>Read formatted input</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Prompt = atom() | string()</v>
- <v>Format = string()</v>
- <v>Result = {ok, Terms} | eof | {error, What}</v>
- <v>&nbsp;Terms = [term()]</v>
- <v>&nbsp;What = term()</v>
- </type>
<desc>
- <p>Reads characters from the standard input (<c>IoDevice</c>),
- prompting it with <c>Prompt</c>. Interprets the characters in
- accordance with <c>Format</c>. <c>Format</c> contains control
+ <p>Reads characters from the standard input (<c><anno>IoDevice</anno></c>),
+ prompting it with <c><anno>Prompt</anno></c>. Interprets the characters in
+ accordance with <c><anno>Format</anno></c>. <c><anno>Format</anno></c> contains control
sequences which directs the interpretation of the input.</p>
- <p><c>Format</c> may contain:</p>
+ <p><c><anno>Format</anno></c> may contain:</p>
<list type="bulleted">
<item>
<p>White space characters (SPACE, TAB and NEWLINE) which
@@ -803,19 +760,19 @@ Prompt> <input>&lt;Character beyond latin1 range not printable in this medium&gt
</taglist>
<p>It returns:</p>
<taglist>
- <tag><c>{ok, Terms}</c></tag>
+ <tag><c>{ok, <anno>Terms</anno>}</c></tag>
<item>
- <p>The read was successful and <c>Terms</c> is the list
+ <p>The read was successful and <c><anno>Terms</anno></c> is the list
of successfully matched and read items.</p>
</item>
<tag><c>eof</c></tag>
<item>
<p>End of file was encountered.</p>
</item>
- <tag><c>{error, What}</c></tag>
+ <tag><c>{error, <anno>What</anno>}</c></tag>
<item>
<p>The read operation failed and the parameter
- <c>What</c> gives a hint about the error.</p>
+ <c><anno>What</anno></c> gives a hint about the error.</p>
</item>
</taglist>
</item>
@@ -834,33 +791,21 @@ enter><input>:</input> <input>alan</input> <input>:</input> <input>joe</in
</desc>
</func>
<func>
- <name>rows() -> {ok,int()} | {error, enotsup}</name>
- <name>rows(IoDevice) -> {ok,int()} | {error, enotsup}</name>
+ <name name="rows" arity="0"/>
+ <name name="rows" arity="1"/>
<fsummary>Get the number of rows of a device</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- </type>
<desc>
<p>Retrieves the number of rows of the
- <c>IoDevice</c> (i.e. the height of a terminal). The function
+ <c><anno>IoDevice</anno></c> (i.e. the height of a terminal). The function
only succeeds for terminal devices, for all other devices
the function returns <c>{error, enotsup}</c></p>
</desc>
</func>
<func>
- <name>scan_erl_exprs(Prompt) -></name>
- <name>scan_erl_exprs(Prompt, StartLine) -> Result</name>
- <name>scan_erl_exprs(IoDevice, Prompt, StartLine) -> Result</name>
+ <name name="scan_erl_exprs" arity="1"/>
+ <name name="scan_erl_exprs" arity="2"/>
+ <name name="scan_erl_exprs" arity="3"/>
<fsummary>Read and tokenize Erlang expressions</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Prompt = atom() | string()</v>
- <v>StartLine = int()</v>
- <v>Result = {ok, Tokens, EndLine} | {eof, EndLine} | {error, ErrorInfo, EndLine}</v>
- <v>&nbsp;Tokens -- see erl_scan(3)</v>
- <v>&nbsp;EndLine = int()</v>
- <v>&nbsp;ErrorInfo -- see section Error Information below</v>
- </type>
<desc>
<p>Reads data from the standard input (<c>IoDevice</c>),
prompting it with <c>Prompt</c>. Reading starts at line number
@@ -876,7 +821,7 @@ enter><input>:</input> <input>alan</input> <input>:</input> <input>joe</in
<item>
<p>End of file was encountered.</p>
</item>
- <tag><c>{error, ErrorInfo, EndLine}</c></tag>
+ <tag><c>{error, ErrorInfo, ErrorLine}</c></tag>
<item>
<p>An error occurred.</p>
</item>
@@ -892,23 +837,14 @@ enter><input>1.0er.</input>
</desc>
</func>
<func>
- <name>scan_erl_form(Prompt) -></name>
- <name>scan_erl_form(Prompt, StartLine) -> Result</name>
- <name>scan_erl_form(IoDevice, Prompt, StartLine) -> Result</name>
+ <name name="scan_erl_form" arity="1"/>
+ <name name="scan_erl_form" arity="2"/>
+ <name name="scan_erl_form" arity="3"/>
<fsummary>Read and tokenize an Erlang form</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Prompt = atom() | string()</v>
- <v>StartLine = int()</v>
- <v>Result = {ok, Tokens, EndLine} | {eof, EndLine} | {error, ErrorInfo, EndLine}</v>
- <v>&nbsp;Tokens -- see erl_scan(3)</v>
- <v>&nbsp;EndLine = int()</v>
- <v>&nbsp;ErrorInfo -- see section Error Information below</v>
- </type>
<desc>
- <p>Reads data from the standard input (<c>IoDevice</c>),
- prompting it with <c>Prompt</c>. Starts reading at line number
- <c>StartLine</c> (1). The data is tokenized as if it were an
+ <p>Reads data from the standard input (<c><anno>IoDevice</anno></c>),
+ prompting it with <c><anno>Prompt</anno></c>. Starts reading at line number
+ <c><anno>StartLine</anno></c> (1). The data is tokenized as if it were an
Erlang form - one of the valid Erlang expressions in an
Erlang source file - until a final <c>'.'</c> is reached.
This last token is also returned. The return values are the
@@ -916,27 +852,19 @@ enter><input>1.0er.</input>
</desc>
</func>
<func>
- <name>parse_erl_exprs(Prompt) -></name>
- <name>parse_erl_exprs(Prompt, StartLine) -> Result</name>
- <name>parse_erl_exprs(IoDevice, Prompt, StartLine) -> Result</name>
+ <name name="parse_erl_exprs" arity="1"/>
+ <name name="parse_erl_exprs" arity="2"/>
+ <name name="parse_erl_exprs" arity="3"/>
+ <type name="parse_ret"/>
<fsummary>Read, tokenize and parse Erlang expressions</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Prompt = atom() | string()</v>
- <v>StartLine = int()</v>
- <v>Result = {ok, Expr_list, EndLine} | {eof, EndLine} | {error, ErrorInfo, EndLine}</v>
- <v>&nbsp;Expr_list -- see erl_parse(3)</v>
- <v>&nbsp;EndLine = int()</v>
- <v>&nbsp;ErrorInfo -- see section Error Information below</v>
- </type>
<desc>
- <p>Reads data from the standard input (<c>IoDevice</c>),
- prompting it with <c>Prompt</c>. Starts reading at line number
- <c>StartLine</c> (1). The data is tokenized and parsed as if
+ <p>Reads data from the standard input (<c><anno>IoDevice</anno></c>),
+ prompting it with <c><anno>Prompt</anno></c>. Starts reading at line number
+ <c><anno>StartLine</anno></c> (1). The data is tokenized and parsed as if
it were a sequence of Erlang expressions until a final '.' is
reached. It returns:</p>
<taglist>
- <tag><c>{ok, Expr_list, EndLine}</c></tag>
+ <tag><c>{ok, ExprList, EndLine}</c></tag>
<item>
<p>The parsing was successful.</p>
</item>
@@ -944,7 +872,7 @@ enter><input>1.0er.</input>
<item>
<p>End of file was encountered.</p>
</item>
- <tag><c>{error, ErrorInfo, EndLine}</c></tag>
+ <tag><c>{error, ErrorInfo, ErrorLine}</c></tag>
<item>
<p>An error occurred.</p>
</item>
@@ -960,23 +888,15 @@ enter><input>abc("hey".</input>
</desc>
</func>
<func>
- <name>parse_erl_form(Prompt) -></name>
- <name>parse_erl_form(Prompt, StartLine) -> Result</name>
- <name>parse_erl_form(IoDevice, Prompt, StartLine) -> Result</name>
+ <name name="parse_erl_form" arity="1"/>
+ <name name="parse_erl_form" arity="2"/>
+ <name name="parse_erl_form" arity="3"/>
+ <type name="parse_form_ret"/>
<fsummary>Read, tokenize and parse an Erlang form</fsummary>
- <type>
- <v>IoDevice = io_device()</v>
- <v>Prompt = atom() | string()</v>
- <v>StartLine = int()</v>
- <v>Result = {ok, AbsForm, EndLine} | {eof, EndLine} | {error, ErrorInfo, EndLine}</v>
- <v>&nbsp;AbsForm -- see erl_parse(3)</v>
- <v>&nbsp;EndLine = int()</v>
- <v>&nbsp;ErrorInfo -- see section Error Information below</v>
- </type>
<desc>
- <p>Reads data from the standard input (<c>IoDevice</c>),
- prompting it with <c>Prompt</c>. Starts reading at line number
- <c>StartLine</c> (1). The data is tokenized and parsed as if
+ <p>Reads data from the standard input (<c><anno>IoDevice</anno></c>),
+ prompting it with <c><anno>Prompt</anno></c>. Starts reading at line number
+ <c><anno>StartLine</anno></c> (1). The data is tokenized and parsed as if
it were an Erlang form - one of the valid Erlang expressions
in an Erlang source file - until a final '.' is reached. It
returns:</p>
@@ -989,7 +909,7 @@ enter><input>abc("hey".</input>
<item>
<p>End of file was encountered.</p>
</item>
- <tag><c>{error, ErrorInfo, EndLine}</c></tag>
+ <tag><c>{error, ErrorInfo, ErrorLine}</c></tag>
<item>
<p>An error occurred.</p>
</item>
diff --git a/lib/stdlib/doc/src/io_lib.xml b/lib/stdlib/doc/src/io_lib.xml
index 399f968c5f..506c1792f1 100644
--- a/lib/stdlib/doc/src/io_lib.xml
+++ b/lib/stdlib/doc/src/io_lib.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -38,14 +38,22 @@
flattening deep lists.</p>
</description>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-chars() = [char() | chars()]</code>
- </section>
+ <datatypes>
+ <datatype>
+ <name name="chars"/>
+ </datatype>
+ <datatype>
+ <name name="continuation"/>
+ <desc><p>A continuation as returned by <seealso marker="#fread/3"><c>fread/3</c></seealso>.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="depth"/>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>nl() -> chars()</name>
+ <name name="nl" arity="0"/>
<fsummary>Write a newline</fsummary>
<desc>
<p>Returns a character list which represents a new line
@@ -53,16 +61,12 @@ chars() = [char() | chars()]</code>
</desc>
</func>
<func>
- <name>write(Term) -></name>
- <name>write(Term, Depth) -> chars()</name>
+ <name name="write" arity="1"/>
+ <name name="write" arity="2"/>
<fsummary>Write a term</fsummary>
- <type>
- <v>Term = term()</v>
- <v>Depth = int()</v>
- </type>
<desc>
- <p>Returns a character list which represents <c>Term</c>. The
- <c>Depth</c> (-1) argument controls the depth of the
+ <p>Returns a character list which represents <c><anno>Term</anno></c>. The
+ <c><anno>Depth</anno></c> (-1) argument controls the depth of the
structures written. When the specified depth is reached,
everything below this level is replaced by "...". For
example:</p>
@@ -74,36 +78,26 @@ chars() = [char() | chars()]</code>
</desc>
</func>
<func>
- <name>print(Term) -></name>
- <name>print(Term, Column, LineLength, Depth) -> chars()</name>
+ <name name="print" arity="1"/>
+ <name name="print" arity="4"/>
<fsummary>Pretty print a term</fsummary>
- <type>
- <v>Term = term()</v>
- <v>Column = LineLenght = Depth = int()</v>
- </type>
<desc>
<p>Also returns a list of characters which represents
- <c>Term</c>, but breaks representations which are longer than
+ <c><anno>Term</anno></c>, but breaks representations which are longer than
one line into many lines and indents each line sensibly. It
also tries to detect and output lists of printable characters
- as strings. <c>Column</c> is the starting column (1),
- <c>LineLength</c> the maximum line length (80), and
- <c>Depth</c> (-1) the maximum print depth.</p>
+ as strings. <c><anno>Column</anno></c> is the starting column (1),
+ <c><anno>LineLength</anno></c> the maximum line length (80), and
+ <c><anno>Depth</anno></c> (-1) the maximum print depth.</p>
</desc>
</func>
<func>
- <name>fwrite(Format, Data) -></name>
- <name>format(Format, Data) -> chars() | UnicodeList</name>
+ <name name="fwrite" arity="2"/>
+ <name name="format" arity="2"/>
<fsummary>Write formatted output</fsummary>
- <type>
- <v>Format = atom() | string() | binary()</v>
- <v>Data = [term()]</v>
- <v>UnicodeList = [Unicode]</v>
- <v>Unicode = int() representing valid unicode codepoint</v>
- </type>
<desc>
- <p>Returns a character list which represents <c>Data</c>
- formatted in accordance with <c>Format</c>. See
+ <p>Returns a character list which represents <c><anno>Data</anno></c>
+ formatted in accordance with <c><anno>Format</anno></c>. See
<seealso marker="io#fwrite/1">io:fwrite/1,2,3</seealso> for a detailed
description of the available formatting options. A fault is
generated if there is an error in the format string or
@@ -119,42 +113,32 @@ chars() = [char() | chars()]</code>
</desc>
</func>
<func>
- <name>fread(Format, String) -> Result</name>
+ <name name="fread" arity="2"/>
<fsummary>Read formatted input</fsummary>
- <type>
- <v>Format = String = string()</v>
- <v>Result = {ok, InputList, LeftOverChars} | {more, RestFormat, Nchars, InputStack} | {error, What}</v>
- <v>&nbsp;InputList = chars()</v>
- <v>&nbsp;LeftOverChars = string()</v>
- <v>&nbsp;RestFormat = string()</v>
- <v>&nbsp;Nchars = int()</v>
- <v>&nbsp;InputStack = chars()</v>
- <v>&nbsp;What = term()</v>
- </type>
<desc>
- <p>Tries to read <c>String</c> in accordance with the control
- sequences in <c>Format</c>. See
+ <p>Tries to read <c><anno>String</anno></c> in accordance with the control
+ sequences in <c><anno>Format</anno></c>. See
<seealso marker="io#fread/3">io:fread/3</seealso> for a detailed
description of the available formatting options. It is
- assumed that <c>String</c> contains whole lines. It returns:</p>
+ assumed that <c><anno>String</anno></c> contains whole lines. It returns:</p>
<taglist>
- <tag><c>{ok, InputList, LeftOverChars}</c></tag>
+ <tag><c>{ok, <anno>InputList</anno>, <anno>LeftOverChars</anno>}</c></tag>
<item>
- <p>The string was read. <c>InputList</c> is the list of
+ <p>The string was read. <c><anno>InputList</anno></c> is the list of
successfully matched and read items, and
- <c>LeftOverChars</c> are the input characters not used.</p>
+ <c><anno>LeftOverChars</anno></c> are the input characters not used.</p>
</item>
- <tag><c>{more, RestFormat, Nchars, InputStack}</c></tag>
+ <tag><c>{more, <anno>RestFormat</anno>, <anno>Nchars</anno>, <anno>InputStack</anno>}</c></tag>
<item>
<p>The string was read, but more input is needed in order
- to complete the original format string. <c>RestFormat</c>
- is the remaining format string, <c>NChars</c> the number
- of characters scanned, and <c>InputStack</c> is the
+ to complete the original format string. <c><anno>RestFormat</anno></c>
+ is the remaining format string, <c><anno>Nchars</anno></c> the number
+ of characters scanned, and <c><anno>InputStack</anno></c> is the
reversed list of inputs matched up to that point.</p>
</item>
- <tag><c>{error, What}</c></tag>
+ <tag><c>{error, <anno>What</anno>}</c></tag>
<item>
- <p>The read operation failed and the parameter <c>What</c>
+ <p>The read operation failed and the parameter <c><anno>What</anno></c>
gives a hint about the error.</p>
</item>
</taglist>
@@ -165,17 +149,8 @@ chars() = [char() | chars()]</code>
</desc>
</func>
<func>
- <name>fread(Continuation, String, Format) -> Return</name>
+ <name name="fread" arity="3"/>
<fsummary>Re-entrant formatted reader</fsummary>
- <type>
- <v>Continuation = see below</v>
- <v>String = Format = string()</v>
- <v>Return = {done, Result, LeftOverChars} | {more, Continuation}</v>
- <v>&nbsp;Result = {ok, InputList} | eof | {error, What}</v>
- <v>&nbsp;&nbsp;InputList = chars()</v>
- <v>&nbsp;&nbsp;What = term()()</v>
- <v>&nbsp;LeftOverChars = string()</v>
- </type>
<desc>
<p>This is the re-entrant formatted reader. The continuation of
the first call to the functions must be <c>[]</c>. Refer to
@@ -184,114 +159,92 @@ chars() = [char() | chars()]</code>
re-entrant input scheme works.</p>
<p>The function returns:</p>
<taglist>
- <tag><c>{done, Result, LeftOverChars}</c></tag>
+ <tag><c>{done, <anno>Result</anno>, <anno>LeftOverChars</anno>}</c></tag>
<item>
<p>The input is complete. The result is one of the
following:</p>
<taglist>
- <tag><c>{ok, InputList}</c></tag>
+ <tag><c>{ok, <anno>InputList</anno>}</c></tag>
<item>
- <p>The string was read. <c>InputList</c> is the list of
+ <p>The string was read. <c><anno>InputList</anno></c> is the list of
successfully matched and read items, and
- <c>LeftOverChars</c> are the remaining characters.</p>
+ <c><anno>LeftOverChars</anno></c> are the remaining characters.</p>
</item>
<tag><c>eof</c></tag>
<item>
<p>End of file has been encountered.
- <c>LeftOverChars</c> are the input characters not
+ <c><anno>LeftOverChars</anno></c> are the input characters not
used.</p>
</item>
- <tag><c>{error, What}</c></tag>
+ <tag><c>{error, <anno>What</anno>}</c></tag>
<item>
- <p>An error occurred and the parameter <c>What</c> gives
+ <p>An error occurred and the parameter <c><anno>What</anno></c> gives
a hint about the error.</p>
</item>
</taglist>
</item>
- <tag><c>{more, Continuation}</c></tag>
+ <tag><c>{more, <anno>Continuation</anno>}</c></tag>
<item>
<p>More data is required to build a term.
- <c>Continuation</c> must be passed to <c>fread/3</c>,
+ <c><anno>Continuation</anno></c> must be passed to <c>fread/3</c>,
when more data becomes available.</p>
</item>
</taglist>
</desc>
</func>
<func>
- <name>write_atom(Atom) -> chars()</name>
+ <name name="write_atom" arity="1"/>
<fsummary>Write an atom</fsummary>
- <type>
- <v>Atom = atom()</v>
- </type>
<desc>
<p>Returns the list of characters needed to print the atom
- <c>Atom</c>.</p>
+ <c><anno>Atom</anno></c>.</p>
</desc>
</func>
<func>
- <name>write_string(String) -> chars()</name>
+ <name name="write_string" arity="1"/>
<fsummary>Write a string</fsummary>
- <type>
- <v>String = string()</v>
- </type>
<desc>
- <p>Returns the list of characters needed to print <c>String</c>
+ <p>Returns the list of characters needed to print <c><anno>String</anno></c>
as a string.</p>
</desc>
</func>
<func>
- <name>write_char(Integer) -> chars()</name>
+ <name name="write_char" arity="1"/>
<fsummary>Write a character</fsummary>
- <type>
- <v>Integer = int()</v>
- </type>
<desc>
<p>Returns the list of characters needed to print a character
constant in the ISO-latin-1 character set.</p>
</desc>
</func>
<func>
- <name>indentation(String, StartIndent) -> int()</name>
+ <name name="indentation" arity="2"/>
<fsummary>Indentation after printing string</fsummary>
- <type>
- <v>String = string()</v>
- <v>StartIndent = int()</v>
- </type>
<desc>
- <p>Returns the indentation if <c>String</c> has been printed,
- starting at <c>StartIndent</c>.</p>
+ <p>Returns the indentation if <c><anno>String</anno></c> has been printed,
+ starting at <c><anno>StartIndent</anno></c>.</p>
</desc>
</func>
<func>
- <name>char_list(Term) -> bool()</name>
+ <name name="char_list" arity="1"/>
<fsummary>Test for a list of characters</fsummary>
- <type>
- <v>Term = term()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Term</c> is a flat list of
+ <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a flat list of
characters in the ISO-latin-1 range, otherwise it returns <c>false</c>.</p>
</desc>
</func>
<func>
- <name>deep_char_list(Term) -> bool()</name>
+ <name name="deep_char_list" arity="1"/>
<fsummary>Test for a deep list of characters</fsummary>
- <type>
- <v>Term = term()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Term</c> is a, possibly deep, list
+ <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a, possibly deep, list
of characters in the ISO-latin-1 range, otherwise it returns <c>false</c>.</p>
</desc>
</func>
<func>
- <name>printable_list(Term) -> bool()</name>
+ <name name="printable_list" arity="1"/>
<fsummary>Test for a list of printable ISO-latin-1 characters</fsummary>
- <type>
- <v>Term = term()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Term</c> is a flat list of
+ <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a flat list of
printable ISO-latin-1 characters, otherwise it returns <c>false</c>.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/lib.xml b/lib/stdlib/doc/src/lib.xml
index 046add48e8..19fb827cbf 100644
--- a/lib/stdlib/doc/src/lib.xml
+++ b/lib/stdlib/doc/src/lib.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -37,27 +37,23 @@
</description>
<funcs>
<func>
- <name>flush_receive() -> void()</name>
+ <name name="flush_receive" arity="0"/>
<fsummary>Flush messages</fsummary>
<desc>
<p>Flushes the message buffer of the current process.</p>
</desc>
</func>
<func>
- <name>error_message(Format, Args) -> ok</name>
+ <name name="error_message" arity="2"/>
<fsummary>Print error message</fsummary>
- <type>
- <v>Format = atom() | string() | binary()</v>
- <v>Args = [term()]</v>
- </type>
<desc>
- <p>Prints error message <c>Args</c> in accordance with
- <c>Format</c>. Similar to <c>io:format/2</c>, see
+ <p>Prints error message <c><anno>Args</anno></c> in accordance with
+ <c><anno>Format</anno></c>. Similar to <c>io:format/2</c>, see
<seealso marker="io#fwrite/1">io(3)</seealso>.</p>
</desc>
</func>
<func>
- <name>progname() -> atom()</name>
+ <name name="progname" arity="0"/>
<fsummary>Return name of Erlang start script</fsummary>
<desc>
<p>Returns the name of the script that started the current
@@ -65,37 +61,24 @@
</desc>
</func>
<func>
- <name>nonl(String1) -> String2</name>
+ <name name="nonl" arity="1"/>
<fsummary>Remove last newline</fsummary>
- <type>
- <v>String1 = String2 = string()</v>
- </type>
<desc>
<p>Removes the last newline character, if any, in
- <c>String1</c>.</p>
+ <c><anno>String1</anno></c>.</p>
</desc>
</func>
<func>
- <name>send(To, Msg)</name>
+ <name name="send" arity="2"/>
<fsummary>Send a message</fsummary>
- <type>
- <v>To = pid() | Name | {Name,Node}</v>
- <v>&nbsp;Name = Node = atom()</v>
- <v>Msg = term()</v>
- </type>
<desc>
<p>This function to makes it possible to send a message using
the <c>apply/3</c> BIF.</p>
</desc>
</func>
<func>
- <name>sendw(To, Msg)</name>
+ <name name="sendw" arity="2"/>
<fsummary>Send a message and wait for an answer</fsummary>
- <type>
- <v>To = pid() | Name | {Name,Node}</v>
- <v>&nbsp;Name = Node = atom()</v>
- <v>Msg = term()</v>
- </type>
<desc>
<p>As <c>send/2</c>, but waits for an answer. It is implemented
as follows:</p>
diff --git a/lib/stdlib/doc/src/lists.xml b/lib/stdlib/doc/src/lists.xml
index 92c4eb4f4c..7042c84437 100644
--- a/lib/stdlib/doc/src/lists.xml
+++ b/lib/stdlib/doc/src/lists.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2010</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -60,58 +60,41 @@
</description>
<funcs>
<func>
- <name>all(Pred, List) -> bool()</name>
+ <name name="all" arity="2"/>
<fsummary>Return true if all elements in the list satisfy<c>Pred</c></fsummary>
- <type>
- <v>Pred = fun(Elem) -> bool()</v>
- <v>&nbsp;Elem = term()</v>
- <v>List = [term()]</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Pred(Elem)</c> returns
- <c>true</c> for all elements <c>Elem</c> in <c>List</c>,
+ <p>Returns <c>true</c> if <c><anno>Pred</anno>(<anno>Elem</anno>)</c> returns
+ <c>true</c> for all elements <c><anno>Elem</anno></c> in <c><anno>List</anno></c>,
otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>any(Pred, List) -> bool()</name>
+ <name name="any" arity="2"/>
<fsummary>Return true if any of the elements in the list satisfies<c>Pred</c></fsummary>
- <type>
- <v>Pred = fun(Elem) -> bool()</v>
- <v>&nbsp;Elem = term()</v>
- <v>List = [term()]</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Pred(Elem)</c> returns
- <c>true</c> for at least one element <c>Elem</c> in
- <c>List</c>.</p>
+ <p>Returns <c>true</c> if <c><anno>Pred</anno>(<anno>Elem</anno>)</c> returns
+ <c>true</c> for at least one element <c><anno>Elem</anno></c> in
+ <c><anno>List</anno></c>.</p>
</desc>
</func>
<func>
- <name>append(ListOfLists) -> List1</name>
+ <name name="append" arity="1"/>
<fsummary>Append a list of lists</fsummary>
- <type>
- <v>ListOfLists = [List]</v>
- <v>List = List1 = [term()]</v>
- </type>
<desc>
<p>Returns a list in which all the sub-lists of
- <c>ListOfLists</c> have been appended. For example:</p>
+ <c><anno>ListOfLists</anno></c> have been appended. For example:</p>
<pre>
> <input>lists:append([[1, 2, 3], [a, b], [4, 5, 6]]).</input>
[1,2,3,a,b,4,5,6]</pre>
</desc>
</func>
<func>
- <name>append(List1, List2) -> List3</name>
+ <name name="append" arity="2"/>
<fsummary>Append two lists</fsummary>
- <type>
- <v>List1 = List2 = List3 = [term()]</v>
- </type>
<desc>
- <p>Returns a new list <c>List3</c> which is made from
- the elements of <c>List1</c> followed by the elements of
- <c>List2</c>. For example:</p>
+ <p>Returns a new list <c><anno>List3</anno></c> which is made from
+ the elements of <c><anno>List1</anno></c> followed by the elements of
+ <c><anno>List2</anno></c>. For example:</p>
<pre>
> <input>lists:append("abc", "def").</input>
"abcdef"</pre>
@@ -119,15 +102,11 @@
</desc>
</func>
<func>
- <name>concat(Things) -> string()</name>
+ <name name="concat" arity="1"/>
<fsummary>Concatenate a list of atoms</fsummary>
- <type>
- <v>Things = [Thing]</v>
- <v>&nbsp;Thing = atom() | integer() | float() | string()</v>
- </type>
<desc>
<p>Concatenates the text representation of the elements
- of <c>Things</c>. The elements of <c>Things</c> can be atoms,
+ of <c><anno>Things</anno></c>. The elements of <c><anno>Things</anno></c> can be atoms,
integers, floats or strings.</p>
<pre>
> <input>lists:concat([doc, '/', file, '.', 3]).</input>
@@ -135,87 +114,59 @@
</desc>
</func>
<func>
- <name>delete(Elem, List1) -> List2</name>
+ <name name="delete" arity="2"/>
<fsummary>Delete an element from a list</fsummary>
- <type>
- <v>Elem = term()</v>
- <v>List1 = List2 = [term()]</v>
- </type>
<desc>
- <p>Returns a copy of <c>List1</c> where the first element
- matching <c>Elem</c> is deleted, if there is such an
+ <p>Returns a copy of <c><anno>List1</anno></c> where the first element
+ matching <c><anno>Elem</anno></c> is deleted, if there is such an
element.</p>
</desc>
</func>
<func>
- <name>dropwhile(Pred, List1) -> List2</name>
+ <name name="dropwhile" arity="2"/>
<fsummary>Drop elements from a list while a predicate is true</fsummary>
- <type>
- <v>Pred = fun(Elem) -> bool()</v>
- <v>&nbsp;Elem = term()</v>
- <v>List1 = List2 = [term()]</v>
- </type>
<desc>
- <p>Drops elements <c>Elem</c> from <c>List1</c> while
- <c>Pred(Elem)</c> returns <c>true</c> and returns
+ <p>Drops elements <c><anno>Elem</anno></c> from <c><anno>List1</anno></c> while
+ <c><anno>Pred</anno>(<anno>Elem</anno>)</c> returns <c>true</c> and returns
the remaining list.</p>
</desc>
</func>
<func>
- <name>duplicate(N, Elem) -> List</name>
+ <name name="duplicate" arity="2"/>
<fsummary>Make N copies of element</fsummary>
- <type>
- <v>N = int()</v>
- <v>Elem = term()</v>
- <v>List = [term()]</v>
- </type>
<desc>
- <p>Returns a list which contains N copies of the term
- <c>Elem</c>. For example:</p>
+ <p>Returns a list which contains <c><anno>N</anno></c> copies of the term
+ <c><anno>Elem</anno></c>. For example:</p>
<pre>
> <input>lists:duplicate(5, xx).</input>
[xx,xx,xx,xx,xx]</pre>
</desc>
</func>
<func>
- <name>filter(Pred, List1) -> List2</name>
+ <name name="filter" arity="2"/>
<fsummary>Choose elements which satisfy a predicate</fsummary>
- <type>
- <v>Pred = fun(Elem) -> bool()</v>
- <v>&nbsp;Elem = term()</v>
- <v>List1 = List2 = [term()]</v>
- </type>
<desc>
- <p><c>List2</c> is a list of all elements <c>Elem</c> in
- <c>List1</c> for which <c>Pred(Elem)</c> returns
+ <p><c><anno>List2</anno></c> is a list of all elements <c><anno>Elem</anno></c> in
+ <c><anno>List1</anno></c> for which <c><anno>Pred</anno>(<anno>Elem</anno>)</c> returns
<c>true</c>.</p>
</desc>
</func>
<func>
- <name>flatlength(DeepList) -> int()</name>
+ <name name="flatlength" arity="1"/>
<fsummary>Length of flattened deep list</fsummary>
- <type>
- <v>DeepList = [term() | DeepList]</v>
- </type>
<desc>
- <p>Equivalent to <c>length(flatten(DeepList))</c>, but more
+ <p>Equivalent to <c>length(flatten(<anno>DeepList</anno>))</c>, but more
efficient.</p>
</desc>
</func>
<func>
- <name>flatmap(Fun, List1) -> List2</name>
+ <name name="flatmap" arity="2"/>
<fsummary>Map and flatten in one pass</fsummary>
- <type>
- <v>Fun = fun(A) -> [B]</v>
- <v>List1 = [A]</v>
- <v>List2 = [B]</v>
- <v>&nbsp;A = B = term()</v>
- </type>
<desc>
- <p>Takes a function from <c>A</c>s to lists of <c>B</c>s, and a
- list of <c>A</c>s (<c>List1</c>) and produces a list of
- <c>B</c>s by applying the function to every element in
- <c>List1</c> and appending the resulting lists.</p>
+ <p>Takes a function from <c><anno>A</anno></c>s to lists of <c><anno>B</anno></c>s, and a
+ list of <c><anno>A</anno></c>s (<c><anno>List1</anno></c>) and produces a list of
+ <c><anno>B</anno></c>s by applying the function to every element in
+ <c><anno>List1</anno></c> and appending the resulting lists.</p>
<p>That is, <c>flatmap</c> behaves as if it had been defined as
follows:</p>
<code type="none">
@@ -228,43 +179,29 @@ flatmap(Fun, List1) ->
</desc>
</func>
<func>
- <name>flatten(DeepList) -> List</name>
+ <name name="flatten" arity="1"/>
<fsummary>Flatten a deep list</fsummary>
- <type>
- <v>DeepList = [term() | DeepList]</v>
- <v>List = [term()]</v>
- </type>
<desc>
- <p>Returns a flattened version of <c>DeepList</c>.</p>
+ <p>Returns a flattened version of <c><anno>DeepList</anno></c>.</p>
</desc>
</func>
<func>
- <name>flatten(DeepList, Tail) -> List</name>
+ <name name="flatten" arity="2"/>
<fsummary>Flatten a deep list</fsummary>
- <type>
- <v>DeepList = [term() | DeepList]</v>
- <v>Tail = List = [term()]</v>
- </type>
<desc>
- <p>Returns a flattened version of <c>DeepList</c> with the tail
- <c>Tail</c> appended.</p>
+ <p>Returns a flattened version of <c><anno>DeepList</anno></c> with the tail
+ <c><anno>Tail</anno></c> appended.</p>
</desc>
</func>
<func>
- <name>foldl(Fun, Acc0, List) -> Acc1</name>
+ <name name="foldl" arity="3"/>
<fsummary>Fold a function over a list</fsummary>
- <type>
- <v>Fun = fun(Elem, AccIn) -> AccOut</v>
- <v>&nbsp;Elem = term()</v>
- <v>Acc0 = Acc1 = AccIn = AccOut = term()</v>
- <v>List = [term()]</v>
- </type>
<desc>
- <p>Calls <c>Fun(Elem, AccIn)</c> on successive elements <c>A</c>
- of <c>List</c>, starting with <c>AccIn == Acc0</c>.
- <c>Fun/2</c> must return a new accumulator which is passed to
+ <p>Calls <c><anno>Fun</anno>(<anno>Elem</anno>, <anno>AccIn</anno>)</c> on successive elements <c>A</c>
+ of <c><anno>List</anno></c>, starting with <c><anno>AccIn</anno> == <anno>Acc0</anno></c>.
+ <c><anno>Fun</anno>/2</c> must return a new accumulator which is passed to
the next call. The function returns the final value of
- the accumulator. <c>Acc0</c> is returned if the list is empty.
+ the accumulator. <c><anno>Acc0</anno></c> is returned if the list is empty.
For example:</p>
<pre>
> <input>lists:foldl(fun(X, Sum) -> X + Sum end, 0, [1,2,3,4,5]).</input>
@@ -274,14 +211,8 @@ flatmap(Fun, List1) ->
</desc>
</func>
<func>
- <name>foldr(Fun, Acc0, List) -> Acc1</name>
+ <name name="foldr" arity="3"/>
<fsummary>Fold a function over a list</fsummary>
- <type>
- <v>Fun = fun(Elem, AccIn) -> AccOut</v>
- <v>&nbsp;Elem = term()</v>
- <v>Acc0 = Acc1 = AccIn = AccOut = term()</v>
- <v>List = [term()]</v>
- </type>
<desc>
<p>Like <c>foldl/3</c>, but the list is traversed from right to
left. For example:</p>
@@ -297,33 +228,23 @@ flatmap(Fun, List1) ->
</desc>
</func>
<func>
- <name>foreach(Fun, List) -> void()</name>
+ <name name="foreach" arity="2"/>
<fsummary>Apply a function to each element of a list</fsummary>
- <type>
- <v>Fun = fun(Elem) -> void()</v>
- <v>&nbsp;Elem = term()</v>
- <v>List = [term()]</v>
- </type>
<desc>
- <p>Calls <c>Fun(Elem)</c> for each element <c>Elem</c> in
- <c>List</c>. This function is used for its side effects and
+ <p>Calls <c><anno>Fun</anno>(<anno>Elem</anno>)</c> for each element <c><anno>Elem</anno></c> in
+ <c><anno>List</anno></c>. This function is used for its side effects and
the evaluation order is defined to be the same as the order
of the elements in the list.</p>
</desc>
</func>
<func>
- <name>keydelete(Key, N, TupleList1) -> TupleList2</name>
+ <name name="keydelete" arity="3"/>
<fsummary>Delete an element from a list of tuples</fsummary>
- <type>
- <v>Key = term()</v>
- <v>N = 1..tuple_size(Tuple)</v>
- <v>TupleList1 = TupleList2 = [Tuple]</v>
- <v>&nbsp;Tuple = tuple()</v>
- </type>
+ <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
- <p>Returns a copy of <c>TupleList1</c> where the first
- occurrence of a tuple whose <c>N</c>th element compares equal to
- <c>Key</c> is deleted, if there is such a tuple.</p>
+ <p>Returns a copy of <c><anno>TupleList1</anno></c> where the first
+ occurrence of a tuple whose <c><anno>N</anno></c>th element compares equal to
+ <c><anno>Key</anno></c> is deleted, if there is such a tuple.</p>
</desc>
</func>
<func>
@@ -343,19 +264,14 @@ flatmap(Fun, List1) ->
</desc>
</func>
<func>
- <name>keymap(Fun, N, TupleList1) -> TupleList2</name>
+ <name name="keymap" arity="3"/>
<fsummary>Map a function over a list of tuples</fsummary>
- <type>
- <v>Fun = fun(Term1) -> Term2</v>
- <v>&nbsp;Term1 = Term2 = term()</v>
- <v>N = 1..tuple_size(Tuple)</v>
- <v>TupleList1 = TupleList2 = [tuple()]</v>
- </type>
+ <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
<p>Returns a list of tuples where, for each tuple in
- <c>TupleList1</c>, the <c>N</c>th element <c>Term1</c> of the tuple
+ <c><anno>TupleList1</anno></c>, the <c><anno>N</anno></c>th element <c><anno>Term1</anno></c> of the tuple
has been replaced with the result of calling
- <c>Fun(Term1)</c>.</p>
+ <c><anno>Fun</anno>(<anno>Term1</anno>)</c>.</p>
<p>Examples:</p>
<pre>
> <input>Fun = fun(Atom) -> atom_to_list(Atom) end.</input>
@@ -365,7 +281,7 @@ flatmap(Fun, List1) ->
</desc>
</func>
<func>
- <name>keymember(Key, N, TupleList) -> bool()</name>
+ <name>keymember(Key, N, TupleList) -> boolean()</name>
<fsummary>Test for membership of a list of tuples</fsummary>
<type>
<v>Key = term()</v>
@@ -380,37 +296,28 @@ flatmap(Fun, List1) ->
</desc>
</func>
<func>
- <name>keymerge(N, TupleList1, TupleList2) -> TupleList3</name>
+ <name name="keymerge" arity="3"/>
<fsummary>Merge two key-sorted lists of tuples</fsummary>
- <type>
- <v>N = 1..tuple_size(Tuple)</v>
- <v>TupleList1 = TupleList2 = TupleList3 = [Tuple]</v>
- <v>&nbsp;Tuple = tuple()</v>
- </type>
+ <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
- <p>Returns the sorted list formed by merging <c>TupleList1</c>
- and <c>TupleList2</c>. The merge is performed on
- the <c>N</c>th element of each tuple. Both <c>TupleList1</c> and
- <c>TupleList2</c> must be key-sorted prior to evaluating this
+ <p>Returns the sorted list formed by merging <c><anno>TupleList1</anno></c>
+ and <c><anno>TupleList2</anno></c>. The merge is performed on
+ the <c><anno>N</anno></c>th element of each tuple. Both <c><anno>TupleList1</anno></c> and
+ <c><anno>TupleList2</anno></c> must be key-sorted prior to evaluating this
function. When two tuples compare equal, the tuple from
- <c>TupleList1</c> is picked before the tuple from
- <c>TupleList2</c>.</p>
+ <c><anno>TupleList1</anno></c> is picked before the tuple from
+ <c><anno>TupleList2</anno></c>.</p>
</desc>
</func>
<func>
- <name>keyreplace(Key, N, TupleList1, NewTuple) -> TupleList2</name>
+ <name name="keyreplace" arity="4"/>
<fsummary>Replace an element in a list of tuples</fsummary>
- <type>
- <v>Key = term()</v>
- <v>N = 1..tuple_size(Tuple)</v>
- <v>TupleList1 = TupleList2 = [Tuple]</v>
- <v>NewTuple = Tuple = tuple()</v>
- </type>
+ <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
- <p>Returns a copy of <c>TupleList1</c> where the first
- occurrence of a <c>T</c> tuple whose <c>N</c>th element
- compares equal to <c>Key</c> is replaced with
- <c>NewTuple</c>, if there is such a tuple <c>T</c>.</p>
+ <p>Returns a copy of <c><anno>TupleList1</anno></c> where the first
+ occurrence of a <c>T</c> tuple whose <c><anno>N</anno></c>th element
+ compares equal to <c><anno>Key</anno></c> is replaced with
+ <c><anno>NewTuple</anno></c>, if there is such a tuple <c>T</c>.</p>
</desc>
</func>
<func>
@@ -433,95 +340,63 @@ flatmap(Fun, List1) ->
</desc>
</func>
<func>
- <name>keysort(N, TupleList1) -> TupleList2</name>
+ <name name="keysort" arity="2"/>
<fsummary>Sort a list of tuples</fsummary>
- <type>
- <v>N = 1..tuple_size(Tuple)</v>
- <v>TupleList1 = TupleList2 = [Tuple]</v>
- <v>&nbsp;Tuple = tuple()</v>
- </type>
+ <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
<p>Returns a list containing the sorted elements of the list
- <c>TupleList1</c>. Sorting is performed on the <c>N</c>th
+ <c><anno>TupleList1</anno></c>. Sorting is performed on the <c><anno>N</anno></c>th
element of the tuples. The sort is stable.</p>
</desc>
</func>
<func>
- <name>keystore(Key, N, TupleList1, NewTuple) -> TupleList2</name>
+ <name name="keystore" arity="4"/>
<fsummary>Store an element in a list of tuples</fsummary>
- <type>
- <v>Key = term()</v>
- <v>N = 1..tuple_size(Tuple)</v>
- <v>TupleList1 = TupleList2 = [Tuple]</v>
- <v>NewTuple = Tuple = tuple()</v>
- </type>
- <desc>
- <p>Returns a copy of <c>TupleList1</c> where the first
- occurrence of a tuple <c>T</c> whose <c>N</c>th element
- compares equal to <c>Key</c> is replaced with
- <c>NewTuple</c>, if there is such a tuple <c>T</c>. If there
- is no such tuple <c>T</c> a copy of <c>TupleList1</c> where
- [<c>NewTuple</c>] has been appended to the end is
+ <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
+ <desc>
+ <p>Returns a copy of <c><anno>TupleList1</anno></c> where the first
+ occurrence of a tuple <c>T</c> whose <c><anno>N</anno></c>th element
+ compares equal to <c><anno>Key</anno></c> is replaced with
+ <c><anno>NewTuple</anno></c>, if there is such a tuple <c>T</c>. If there
+ is no such tuple <c>T</c> a copy of <c><anno>TupleList1</anno></c> where
+ [<c><anno>NewTuple</anno></c>] has been appended to the end is
returned.</p>
</desc>
</func>
<func>
- <name>keytake(Key, N, TupleList1) -> {value, Tuple, TupleList2}
- | false</name>
+ <name name="keytake" arity="3"/>
<fsummary>Extract an element from a list of tuples</fsummary>
- <type>
- <v>Key = term()</v>
- <v>N = 1..tuple_size(Tuple)</v>
- <v>TupleList1 = TupleList2 = [Tuple]</v>
- <v>Tuple = tuple()</v>
- </type>
+ <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
- <p>Searches the list of tuples <c>TupleList1</c> for a tuple
- whose <c>N</c>th element compares equal to <c>Key</c>.
- Returns <c>{value, Tuple, TupleList2}</c> if such a tuple is
- found, otherwise <c>false</c>. <c>TupleList2</c> is a copy
- of <c>TupleList1</c> where the first occurrence of
- <c>Tuple</c> has been removed.</p>
+ <p>Searches the list of tuples <c><anno>TupleList1</anno></c> for a tuple
+ whose <c><anno>N</anno></c>th element compares equal to <c><anno>Key</anno></c>.
+ Returns <c>{value, <anno>Tuple</anno>, <anno>TupleList2</anno>}</c> if such a tuple is
+ found, otherwise <c>false</c>. <c><anno>TupleList2</anno></c> is a copy
+ of <c><anno>TupleList1</anno></c> where the first occurrence of
+ <c><anno>Tuple</anno></c> has been removed.</p>
</desc>
</func>
<func>
- <name>last(List) -> Last</name>
+ <name name="last" arity="1"/>
<fsummary>Return last element in a list</fsummary>
- <type>
- <v>List = [term()], length(List) > 0</v>
- <v>Last = term()</v>
- </type>
<desc>
- <p>Returns the last element in <c>List</c>.</p>
+ <p>Returns the last element in <c><anno>List</anno></c>.</p>
</desc>
</func>
<func>
- <name>map(Fun, List1) -> List2</name>
+ <name name="map" arity="2"/>
<fsummary>Map a function over a list</fsummary>
- <type>
- <v>Fun = fun(A) -> B</v>
- <v>List1 = [A]</v>
- <v>List2 = [B]</v>
- <v>&nbsp;A = B = term()</v>
- </type>
<desc>
- <p>Takes a function from <c>A</c>s to <c>B</c>s, and a list of
- <c>A</c>s and produces a list of <c>B</c>s by applying
+ <p>Takes a function from <c><anno>A</anno></c>s to <c><anno>B</anno></c>s, and a list of
+ <c><anno>A</anno></c>s and produces a list of <c><anno>B</anno></c>s by applying
the function to every element in the list. This function is
used to obtain the return values. The evaluation order is
implementation dependent.</p>
</desc>
</func>
<func>
- <name>mapfoldl(Fun, Acc0, List1) -> {List2, Acc1}</name>
+ <name name="mapfoldl" arity="3"/>
<fsummary>Map and fold in one pass</fsummary>
- <type>
- <v>Fun = fun(A, AccIn) -> {B, AccOut}</v>
- <v>Acc0 = Acc1 = AccIn = AccOut = term()</v>
- <v>List1 = [A]</v>
- <v>List2 = [B]</v>
- <v>&nbsp;A = B = term()</v>
- </type>
<desc>
<p><c>mapfoldl</c> combines the operations of <c>map/2</c> and
<c>foldl/3</c> into one pass. An example, summing
@@ -533,35 +408,24 @@ flatmap(Fun, List1) ->
</desc>
</func>
<func>
- <name>mapfoldr(Fun, Acc0, List1) -> {List2, Acc1}</name>
+ <name name="mapfoldr" arity="3"/>
<fsummary>Map and fold in one pass</fsummary>
- <type>
- <v>Fun = fun(A, AccIn) -> {B, AccOut}</v>
- <v>Acc0 = Acc1 = AccIn = AccOut = term()</v>
- <v>List1 = [A]</v>
- <v>List2 = [B]</v>
- <v>&nbsp;A = B = term()</v>
- </type>
<desc>
<p><c>mapfoldr</c> combines the operations of <c>map/2</c> and
<c>foldr/3</c> into one pass.</p>
</desc>
</func>
<func>
- <name>max(List) -> Max</name>
+ <name name="max" arity="1"/>
<fsummary>Return maximum element of a list</fsummary>
- <type>
- <v>List = [term()], length(List) > 0</v>
- <v>Max = term()</v>
- </type>
<desc>
- <p>Returns the first element of <c>List</c> that compares
+ <p>Returns the first element of <c><anno>List</anno></c> that compares
greater than or equal to all other elements of
- <c>List</c>.</p>
+ <c><anno>List</anno></c>.</p>
</desc>
</func>
<func>
- <name>member(Elem, List) -> bool()</name>
+ <name>member(Elem, List) -> boolean()</name>
<fsummary>Test for membership of a list</fsummary>
<type>
<v>Elem = term()</v>
@@ -573,112 +437,84 @@ flatmap(Fun, List1) ->
</desc>
</func>
<func>
- <name>merge(ListOfLists) -> List1</name>
+ <name name="merge" arity="1"/>
<fsummary>Merge a list of sorted lists</fsummary>
- <type>
- <v>ListOfLists = [List]</v>
- <v>List = List1 = [term()]</v>
- </type>
<desc>
<p>Returns the sorted list formed by merging all the sub-lists
- of <c>ListOfLists</c>. All sub-lists must be sorted prior to
+ of <c><anno>ListOfLists</anno></c>. All sub-lists must be sorted prior to
evaluating this function. When two elements compare equal,
the element from the sub-list with the lowest position in
- <c>ListOfLists</c> is picked before the other element.</p>
+ <c><anno>ListOfLists</anno></c> is picked before the other element.</p>
</desc>
</func>
<func>
- <name>merge(List1, List2) -> List3</name>
+ <name name="merge" arity="2"/>
<fsummary>Merge two sorted lists</fsummary>
- <type>
- <v>List1 = List2 = List3 = [term()]</v>
- </type>
<desc>
- <p>Returns the sorted list formed by merging <c>List1</c> and
- <c>List2</c>. Both <c>List1</c> and <c>List2</c> must be
+ <p>Returns the sorted list formed by merging <c><anno>List1</anno></c> and
+ <c><anno>List2</anno></c>. Both <c><anno>List1</anno></c> and <c><anno>List2</anno></c> must be
sorted prior to evaluating this function. When two elements
- compare equal, the element from <c>List1</c> is picked
- before the element from <c>List2</c>.</p>
+ compare equal, the element from <c><anno>List1</anno></c> is picked
+ before the element from <c><anno>List2</anno></c>.</p>
</desc>
</func>
<func>
- <name>merge(Fun, List1, List2) -> List3</name>
+ <name name="merge" arity="3"/>
<fsummary>Merge two sorted list</fsummary>
- <type>
- <v>Fun = fun(A, B) -> bool()</v>
- <v>List1 = [A]</v>
- <v>List2 = [B]</v>
- <v>List3 = [A | B]</v>
- <v>&nbsp;A = B = term()</v>
- </type>
<desc>
- <p>Returns the sorted list formed by merging <c>List1</c> and
- <c>List2</c>. Both <c>List1</c> and <c>List2</c> must be
+ <p>Returns the sorted list formed by merging <c><anno>List1</anno></c> and
+ <c><anno>List2</anno></c>. Both <c><anno>List1</anno></c> and <c><anno>List2</anno></c> must be
sorted according to the <seealso
marker="#ordering_function">ordering function</seealso>
- <c>Fun</c> prior to evaluating this function. <c>Fun(A,
- B)</c> should return <c>true</c> if <c>A</c> compares less
- than or equal to <c>B</c> in the ordering, <c>false</c>
+ <c><anno>Fun</anno></c> prior to evaluating this function. <c><anno>Fun</anno>(<anno>A</anno>,
+ <anno>B</anno>)</c> should return <c>true</c> if <c><anno>A</anno></c> compares less
+ than or equal to <c><anno>B</anno></c> in the ordering, <c>false</c>
otherwise. When two elements compare equal, the element from
- <c>List1</c> is picked before the element from
- <c>List2</c>.</p>
+ <c><anno>List1</anno></c> is picked before the element from
+ <c><anno>List2</anno></c>.</p>
</desc>
</func>
<func>
- <name>merge3(List1, List2, List3) -> List4</name>
+ <name name="merge3" arity="3"/>
<fsummary>Merge three sorted lists</fsummary>
- <type>
- <v>List1 = List2 = List3 = List4 = [term()]</v>
- </type>
<desc>
- <p>Returns the sorted list formed by merging <c>List1</c>,
- <c>List2</c> and <c>List3</c>. All of <c>List1</c>,
- <c>List2</c> and <c>List3</c> must be sorted prior to
+ <p>Returns the sorted list formed by merging <c><anno>List1</anno></c>,
+ <c><anno>List2</anno></c> and <c><anno>List3</anno></c>. All of <c><anno>List1</anno></c>,
+ <c><anno>List2</anno></c> and <c><anno>List3</anno></c> must be sorted prior to
evaluating this function. When two elements compare equal,
- the element from <c>List1</c>, if there is such an element,
+ the element from <c><anno>List1</anno></c>, if there is such an element,
is picked before the other element, otherwise the element
- from <c>List2</c> is picked before the element from
- <c>List3</c>.</p>
+ from <c><anno>List2</anno></c> is picked before the element from
+ <c><anno>List3</anno></c>.</p>
</desc>
</func>
<func>
- <name>min(List) -> Min</name>
+ <name name="min" arity="1"/>
<fsummary>Return minimum element of a list</fsummary>
- <type>
- <v>List = [term()], length(List) > 0</v>
- <v>Min = term()</v>
- </type>
<desc>
- <p>Returns the first element of <c>List</c> that compares
+ <p>Returns the first element of <c><anno>List</anno></c> that compares
less than or equal to all other elements of
- <c>List</c>.</p>
+ <c><anno>List</anno></c>.</p>
</desc>
</func>
<func>
- <name>nth(N, List) -> Elem</name>
+ <name name="nth" arity="2"/>
<fsummary>Return the Nth element of a list</fsummary>
- <type>
- <v>N = 1..length(List)</v>
- <v>List = [term()]</v>
- <v>Elem = term()</v>
- </type>
+ <type_desc variable="N">1..length(<anno>List</anno>)</type_desc>
<desc>
- <p>Returns the <c>N</c>th element of <c>List</c>. For example:</p>
+ <p>Returns the <c><anno>N</anno></c>th element of <c><anno>List</anno></c>. For example:</p>
<pre>
> <input>lists:nth(3, [a, b, c, d, e]).</input>
c</pre>
</desc>
</func>
<func>
- <name>nthtail(N, List1) -> Tail</name>
+ <name name="nthtail" arity="2"/>
<fsummary>Return the Nth tail of a list</fsummary>
- <type>
- <v>N = 0..length(List1)</v>
- <v>List1 = Tail = [term()]</v>
- </type>
+ <type_desc variable="N">0..length(<anno>List</anno>)</type_desc>
<desc>
- <p>Returns the <c>N</c>th tail of <c>List</c>, that is, the sublist of
- <c>List</c> starting at <c>N+1</c> and continuing up to
+ <p>Returns the <c><anno>N</anno></c>th tail of <c><anno>List</anno></c>, that is, the sublist of
+ <c><anno>List</anno></c> starting at <c><anno>N</anno>+1</c> and continuing up to
the end of the list. For example:</p>
<pre>
> <input>lists:nthtail(3, [a, b, c, d, e]).</input>
@@ -692,18 +528,13 @@ c</pre>
</desc>
</func>
<func>
- <name>partition(Pred, List) -> {Satisfying, NonSatisfying}</name>
+ <name name="partition" arity="2"/>
<fsummary>Partition a list into two lists based on a predicate</fsummary>
- <type>
- <v>Pred = fun(Elem) -> bool()</v>
- <v>&nbsp;Elem = term()</v>
- <v>List = Satisfying = NonSatisfying = [term()]</v>
- </type>
<desc>
- <p>Partitions <c>List</c> into two lists, where the first list
- contains all elements for which <c>Pred(Elem)</c> returns
+ <p>Partitions <c><anno>List</anno></c> into two lists, where the first list
+ contains all elements for which <c><anno>Pred</anno>(<anno>Elem</anno>)</c> returns
<c>true</c>, and the second list contains all elements for
- which <c>Pred(Elem)</c> returns <c>false</c>.</p>
+ which <c><anno>Pred</anno>(<anno>Elem</anno>)</c> returns <c>false</c>.</p>
<p>Examples:</p>
<pre>
> <input>lists:partition(fun(A) -> A rem 2 == 1 end, [1,2,3,4,5,6,7]).</input>
@@ -715,24 +546,18 @@ c</pre>
</desc>
</func>
<func>
- <name>prefix(List1, List2) -> bool()</name>
+ <name name="prefix" arity="2"/>
<fsummary>Test for list prefix</fsummary>
- <type>
- <v>List1 = List2 = [term()]</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>List1</c> is a prefix of
- <c>List2</c>, otherwise <c>false</c>.</p>
+ <p>Returns <c>true</c> if <c><anno>List1</anno></c> is a prefix of
+ <c><anno>List2</anno></c>, otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>reverse(List1) -> List2</name>
+ <name name="reverse" arity="1"/>
<fsummary>Reverse a list</fsummary>
- <type>
- <v>List1 = List2 = [term()]</v>
- </type>
<desc>
- <p>Returns a list with the top level elements in <c>List1</c>
+ <p>Returns a list with the elements in <c><anno>List1</anno></c>
in reverse order.</p>
</desc>
</func>
@@ -743,7 +568,7 @@ c</pre>
<v>List1 = Tail = List2 = [term()]</v>
</type>
<desc>
- <p>Returns a list with the top level elements in <c>List1</c>
+ <p>Returns a list with the elements in <c>List1</c>
in reverse order, with the tail <c>Tail</c> appended. For
example:</p>
<pre>
@@ -752,22 +577,18 @@ c</pre>
</desc>
</func>
<func>
- <name>seq(From, To) -> Seq</name>
- <name>seq(From, To, Incr) -> Seq</name>
+ <name name="seq" arity="2"/>
+ <name name="seq" arity="3"/>
<fsummary>Generate a sequence of integers</fsummary>
- <type>
- <v>From = To = Incr = int()</v>
- <v>Seq = [int()]</v>
- </type>
<desc>
- <p>Returns a sequence of integers which starts with <c>From</c>
- and contains the successive results of adding <c>Incr</c> to
- the previous element, until <c>To</c> has been reached or
- passed (in the latter case, <c>To</c> is not an element of
- the sequence). <c>Incr</c> defaults to 1.</p>
- <p>Failure: If <c><![CDATA[To<From-Incr]]></c> and <c>Incr</c>
- is positive, or if <c>To>From-Incr</c> and <c>Incr</c> is
- negative, or if <c>Incr==0</c> and <c>From/=To</c>.</p>
+ <p>Returns a sequence of integers which starts with <c><anno>From</anno></c>
+ and contains the successive results of adding <c><anno>Incr</anno></c> to
+ the previous element, until <c><anno>To</anno></c> has been reached or
+ passed (in the latter case, <c><anno>To</anno></c> is not an element of
+ the sequence). <c><anno>Incr</anno></c> defaults to 1.</p>
+ <p>Failure: If <c><anno>To</anno>&lt;<anno>From</anno>-<anno>Incr</anno></c> and <c><anno>Incr</anno></c>
+ is positive, or if <c><anno>To</anno>><anno>From</anno>-<anno>Incr</anno></c> and <c><anno>Incr</anno></c> is
+ negative, or if <c><anno>Incr</anno>==0</c> and <c><anno>From</anno>/=<anno>To</anno></c>.</p>
<p>The following equalities hold for all sequences:</p>
<code type="none">
length(lists:seq(From, To)) == To-From+1
@@ -787,57 +608,41 @@ length(lists:seq(From, To, Incr)) == (To-From+Incr) div Incr</code>
</desc>
</func>
<func>
- <name>sort(List1) -> List2</name>
+ <name name="sort" arity="1"/>
<fsummary>Sort a list</fsummary>
- <type>
- <v>List1 = List2 = [term()]</v>
- </type>
<desc>
<p>Returns a list containing the sorted elements of
- <c>List1</c>.</p>
+ <c><anno>List1</anno></c>.</p>
</desc>
</func>
<func>
- <name>sort(Fun, List1) -> List2</name>
+ <name name="sort" arity="2"/>
<fsummary>Sort a list</fsummary>
- <type>
- <v>Fun = fun(Elem1, Elem2) -> bool()</v>
- <v>&nbsp;Elem1 = Elem2 = term()</v>
- <v>List1 = List2 = [term()]</v>
- </type>
<desc>
<p>Returns a list containing the sorted elements of
- <c>List1</c>, according to the <seealso
+ <c><anno>List1</anno></c>, according to the <seealso
marker="#ordering_function">ordering function</seealso>
- <c>Fun</c>. <c>Fun(A, B)</c> should return <c>true</c> if
- <c>A</c> compares less than or equal to <c>B</c> in the
+ <c><anno>Fun</anno></c>. <c><anno>Fun</anno>(<anno>A</anno>, <anno>B</anno>)</c> should return <c>true</c> if
+ <c><anno>A</anno></c> compares less than or equal to <c><anno>B</anno></c> in the
ordering, <c>false</c> otherwise.</p>
</desc>
</func>
<func>
- <name>split(N, List1) -> {List2, List3}</name>
+ <name name="split" arity="2"/>
<fsummary>Split a list into two lists</fsummary>
- <type>
- <v>N = 0..length(List1)</v>
- <v>List1 = List2 = List3 = [term()]</v>
- </type>
+ <type_desc variable="N">0..length(<anno>List1</anno>)</type_desc>
<desc>
- <p>Splits <c>List1</c> into <c>List2</c> and <c>List3</c>.
- <c>List2</c> contains the first <c>N</c> elements and
- <c>List3</c> the rest of the elements (the <c>N</c>th tail).</p>
+ <p>Splits <c><anno>List1</anno></c> into <c><anno>List2</anno></c> and <c><anno>List3</anno></c>.
+ <c><anno>List2</anno></c> contains the first <c><anno>N</anno></c> elements and
+ <c><anno>List3</anno></c> the rest of the elements (the <c><anno>N</anno></c>th tail).</p>
</desc>
</func>
<func>
- <name>splitwith(Pred, List) -> {List1, List2}</name>
+ <name name="splitwith" arity="2"/>
<fsummary>Split a list into two lists based on a predicate</fsummary>
- <type>
- <v>Pred = fun(Elem) -> bool()</v>
- <v>&nbsp;Elem = term()</v>
- <v>List = List1 = List2 = [term()]</v>
- </type>
<desc>
- <p>Partitions <c>List</c> into two lists according to
- <c>Pred</c>. <c>splitwith/2</c> behaves as if it is defined
+ <p>Partitions <c><anno>List</anno></c> into two lists according to
+ <c><anno>Pred</anno></c>. <c>splitwith/2</c> behaves as if it is defined
as follows:</p>
<code type="none">
splitwith(Pred, List) ->
@@ -853,31 +658,23 @@ splitwith(Pred, List) ->
</desc>
</func>
<func>
- <name>sublist(List1, Len) -> List2</name>
+ <name name="sublist" arity="2"/>
<fsummary>Return a sub-list of a certain length, starting at the first position</fsummary>
- <type>
- <v>List1 = List2 = [term()]</v>
- <v>Len = int()</v>
- </type>
<desc>
- <p>Returns the sub-list of <c>List1</c> starting at position 1
- and with (max) <c>Len</c> elements. It is not an error for
- <c>Len</c> to exceed the length of the list -- in that case
+ <p>Returns the sub-list of <c><anno>List1</anno></c> starting at position 1
+ and with (max) <c><anno>Len</anno></c> elements. It is not an error for
+ <c><anno>Len</anno></c> to exceed the length of the list -- in that case
the whole list is returned.</p>
</desc>
</func>
<func>
- <name>sublist(List1, Start, Len) -> List2</name>
+ <name name="sublist" arity="3"/>
<fsummary>Return a sub-list starting at a given position and with a given number of elements</fsummary>
- <type>
- <v>List1 = List2 = [term()]</v>
- <v>Start = 1..(length(List1)+1)</v>
- <v>Len = int()</v>
- </type>
+ <type_desc variable="Start">1..(length(<anno>List1</anno>)+1)</type_desc>
<desc>
- <p>Returns the sub-list of <c>List1</c> starting at <c>Start</c>
- and with (max) <c>Len</c> elements. It is not an error for
- <c>Start+Len</c> to exceed the length of the list.</p>
+ <p>Returns the sub-list of <c><anno>List1</anno></c> starting at <c><anno>Start</anno></c>
+ and with (max) <c><anno>Len</anno></c> elements. It is not an error for
+ <c><anno>Start</anno>+<anno>Len</anno></c> to exceed the length of the list.</p>
<pre>
> <input>lists:sublist([1,2,3,4], 2, 2).</input>
[2,3]
@@ -888,15 +685,12 @@ splitwith(Pred, List) ->
</desc>
</func>
<func>
- <name>subtract(List1, List2) -> List3</name>
+ <name name="subtract" arity="2"/>
<fsummary>Subtract the element in one list from another list</fsummary>
- <type>
- <v>List1 = List2 = List3 = [term()]</v>
- </type>
<desc>
- <p>Returns a new list <c>List3</c> which is a copy of
- <c>List1</c>, subjected to the following procedure: for each
- element in <c>List2</c>, its first occurrence in <c>List1</c>
+ <p>Returns a new list <c><anno>List3</anno></c> which is a copy of
+ <c><anno>List1</anno></c>, subjected to the following procedure: for each
+ element in <c><anno>List2</anno></c>, its first occurrence in <c><anno>List1</anno></c>
is deleted. For example:</p>
<pre>
> <input>lists:subtract("123212", "212").</input>
@@ -911,151 +705,112 @@ splitwith(Pred, List) ->
</desc>
</func>
<func>
- <name>suffix(List1, List2) -> bool()</name>
+ <name name="suffix" arity="2"/>
<fsummary>Test for list suffix</fsummary>
<desc>
- <p>Returns <c>true</c> if <c>List1</c> is a suffix of
- <c>List2</c>, otherwise <c>false</c>.</p>
+ <p>Returns <c>true</c> if <c><anno>List1</anno></c> is a suffix of
+ <c><anno>List2</anno></c>, otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>sum(List) -> number()</name>
+ <name name="sum" arity="1"/>
<fsummary>Return sum of elements in a list</fsummary>
- <type>
- <v>List = [number()]</v>
- </type>
<desc>
- <p>Returns the sum of the elements in <c>List</c>.</p>
+ <p>Returns the sum of the elements in <c><anno>List</anno></c>.</p>
</desc>
</func>
<func>
- <name>takewhile(Pred, List1) -> List2</name>
+ <name name="takewhile" arity="2"/>
<fsummary>Take elements from a list while a predicate is true</fsummary>
- <type>
- <v>Pred = fun(Elem) -> bool()</v>
- <v>&nbsp;Elem = term()</v>
- <v>List1 = List2 = [term()]</v>
- </type>
<desc>
- <p>Takes elements <c>Elem</c> from <c>List1</c> while
- <c>Pred(Elem)</c> returns <c>true</c>, that is,
+ <p>Takes elements <c><anno>Elem</anno></c> from <c><anno>List1</anno></c> while
+ <c><anno>Pred</anno>(<anno>Elem</anno>)</c> returns <c>true</c>, that is,
the function returns the longest prefix of the list for which
all elements satisfy the predicate.</p>
</desc>
</func>
<func>
- <name>ukeymerge(N, TupleList1, TupleList2) -> TupleList3</name>
+ <name name="ukeymerge" arity="3"/>
<fsummary>Merge two key-sorted lists of tuples, removing duplicates</fsummary>
- <type>
- <v>N = 1..tuple_size(Tuple)</v>
- <v>TupleList1 = TupleList2 = TupleList3 = [Tuple]</v>
- <v>&nbsp;Tuple = tuple()</v>
- </type>
+ <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
- <p>Returns the sorted list formed by merging <c>TupleList1</c>
- and <c>TupleList2</c>. The merge is performed on the
- <c>N</c>th element of each tuple. Both <c>TupleList1</c> and
- <c>TupleList2</c> must be key-sorted without duplicates
+ <p>Returns the sorted list formed by merging <c><anno>TupleList1</anno></c>
+ and <c><anno>TupleList2</anno></c>. The merge is performed on the
+ <c><anno>N</anno></c>th element of each tuple. Both <c><anno>TupleList1</anno></c> and
+ <c><anno>TupleList2</anno></c> must be key-sorted without duplicates
prior to evaluating this function. When two tuples compare
- equal, the tuple from <c>TupleList1</c> is picked and the
- one from <c>TupleList2</c> deleted.</p>
+ equal, the tuple from <c><anno>TupleList1</anno></c> is picked and the
+ one from <c><anno>TupleList2</anno></c> deleted.</p>
</desc>
</func>
<func>
- <name>ukeysort(N, TupleList1) -> TupleList2</name>
+ <name name="ukeysort" arity="2"/>
<fsummary>Sort a list of tuples, removing duplicates</fsummary>
- <type>
- <v>N = 1..tuple_size(Tuple)</v>
- <v>TupleList1 = TupleList2 = [Tuple]</v>
- <v>&nbsp;Tuple = tuple()</v>
- </type>
+ <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
<desc>
<p>Returns a list containing the sorted elements of the list
- <c>TupleList1</c> where all but the first tuple of the
+ <c><anno>TupleList1</anno></c> where all but the first tuple of the
tuples comparing equal have been deleted. Sorting is
- performed on the <c>N</c>th element of the tuples.</p>
+ performed on the <c><anno>N</anno></c>th element of the tuples.</p>
</desc>
</func>
<func>
- <name>umerge(ListOfLists) -> List1</name>
+ <name name="umerge" arity="1"/>
<fsummary>Merge a list of sorted lists, removing duplicates</fsummary>
- <type>
- <v>ListOfLists = [List]</v>
- <v>List = List1 = [term()]</v>
- </type>
<desc>
<p>Returns the sorted list formed by merging all the sub-lists
- of <c>ListOfLists</c>. All sub-lists must be sorted and
+ of <c><anno>ListOfLists</anno></c>. All sub-lists must be sorted and
contain no duplicates prior to evaluating this function.
When two elements compare equal, the element from the
- sub-list with the lowest position in <c>ListOfLists</c> is
+ sub-list with the lowest position in <c><anno>ListOfLists</anno></c> is
picked and the other one deleted.</p>
</desc>
</func>
<func>
- <name>umerge(List1, List2) -> List3</name>
+ <name name="umerge" arity="2"/>
<fsummary>Merge two sorted lists, removing duplicates</fsummary>
- <type>
- <v>List1 = List2 = List3 = [term()]</v>
- </type>
<desc>
- <p>Returns the sorted list formed by merging <c>List1</c> and
- <c>List2</c>. Both <c>List1</c> and <c>List2</c> must be
+ <p>Returns the sorted list formed by merging <c><anno>List1</anno></c> and
+ <c><anno>List2</anno></c>. Both <c><anno>List1</anno></c> and <c><anno>List2</anno></c> must be
sorted and contain no duplicates prior to evaluating this
function. When two elements compare equal, the element from
- <c>List1</c> is picked and the one from <c>List2</c>
+ <c><anno>List1</anno></c> is picked and the one from <c><anno>List2</anno></c>
deleted.</p>
</desc>
</func>
<func>
- <name>umerge(Fun, List1, List2) -> List3</name>
+ <name name="umerge" arity="3"/>
<fsummary>Merge two sorted lists, removing duplicates</fsummary>
- <type>
- <v>Fun = fun(A, B) -> bool()</v>
- <v>List1 = [A]</v>
- <v>List2 = [B]</v>
- <v>List3 = [A | B]</v>
- <v>&nbsp;A = B = term()</v>
- </type>
<desc>
- <p>Returns the sorted list formed by merging <c>List1</c> and
- <c>List2</c>. Both <c>List1</c> and <c>List2</c> must be
+ <p>Returns the sorted list formed by merging <c><anno>List1</anno></c> and
+ <c><anno>List2</anno></c>. Both <c><anno>List1</anno></c> and <c><anno>List2</anno></c> must be
sorted according to the <seealso
marker="#ordering_function">ordering function</seealso>
<c>Fun</c> and contain no duplicates prior to evaluating
- this function. <c>Fun(A, B)</c> should return <c>true</c> if
- <c>A</c> compares less than or equal to <c>B</c> in the
+ this function. <c><anno>Fun</anno>(<anno>A</anno>, <anno>B</anno>)</c> should return <c>true</c> if
+ <c><anno>A</anno></c> compares less than or equal to <c><anno>B</anno></c> in the
ordering, <c>false</c> otherwise. When two elements compare
equal, the element from
- <c>List1</c> is picked and the one from <c>List2</c>
+ <c><anno>List1</anno></c> is picked and the one from <c><anno>List2</anno></c>
deleted.</p>
</desc>
</func>
<func>
- <name>umerge3(List1, List2, List3) -> List4</name>
+ <name name="umerge3" arity="3"/>
<fsummary>Merge three sorted lists, removing duplicates</fsummary>
- <type>
- <v>List1 = List2 = List3 = List4 = [term()]</v>
- </type>
<desc>
- <p>Returns the sorted list formed by merging <c>List1</c>,
- <c>List2</c> and <c>List3</c>. All of <c>List1</c>,
- <c>List2</c> and <c>List3</c> must be sorted and contain no
+ <p>Returns the sorted list formed by merging <c><anno>List1</anno></c>,
+ <c><anno>List2</anno></c> and <c><anno>List3</anno></c>. All of <c><anno>List1</anno></c>,
+ <c><anno>List2</anno></c> and <c><anno>List3</anno></c> must be sorted and contain no
duplicates prior to evaluating this function. When two
- elements compare equal, the element from <c>List1</c> is
+ elements compare equal, the element from <c><anno>List1</anno></c> is
picked if there is such an element, otherwise the element
- from <c>List2</c> is picked, and the other one deleted.</p>
+ from <c><anno>List2</anno></c> is picked, and the other one deleted.</p>
</desc>
</func>
<func>
- <name>unzip(List1) -> {List2, List3}</name>
+ <name name="unzip" arity="1"/>
<fsummary>Unzip a list of two-tuples into two lists</fsummary>
- <type>
- <v>List1 = [{X, Y}]</v>
- <v>List2 = [X]</v>
- <v>List3 = [Y]</v>
- <v>&nbsp;X = Y = term()</v>
- </type>
<desc>
<p>"Unzips" a list of two-tuples into two lists, where the first
list contains the first element of each tuple, and the second
@@ -1063,15 +818,8 @@ splitwith(Pred, List) ->
</desc>
</func>
<func>
- <name>unzip3(List1) -> {List2, List3, List4}</name>
+ <name name="unzip3" arity="1"/>
<fsummary>Unzip a list of three-tuples into three lists</fsummary>
- <type>
- <v>List1 = [{X, Y, Z}]</v>
- <v>List2 = [X]</v>
- <v>List3 = [Y]</v>
- <v>List4 = [Z]</v>
- <v>&nbsp;X = Y = Z = term()</v>
- </type>
<desc>
<p>"Unzips" a list of three-tuples into three lists, where
the first list contains the first element of each tuple,
@@ -1080,44 +828,30 @@ splitwith(Pred, List) ->
</desc>
</func>
<func>
- <name>usort(List1) -> List2</name>
+ <name name="usort" arity="1"/>
<fsummary>Sort a list, removing duplicates</fsummary>
- <type>
- <v>List1 = List2 = [term()]</v>
- </type>
<desc>
<p>Returns a list containing the sorted elements of
- <c>List1</c> where all but the first element of the elements
+ <c><anno>List1</anno></c> where all but the first element of the elements
comparing equal have been deleted.</p>
</desc>
</func>
<func>
- <name>usort(Fun, List1) -> List2</name>
+ <name name="usort" arity="2"/>
<fsummary>Sort a list, removing duplicates</fsummary>
- <type>
- <v>Fun = fun(Elem1, Elem2) -> bool()</v>
- <v>&nbsp;Elem1 = Elem2 = term()</v>
- <v>List1 = List2 = [term()]</v>
- </type>
<desc>
<p>Returns a list which contains the sorted elements of
- <c>List1</c> where all but the first element of the elements
+ <c><anno>List1</anno></c> where all but the first element of the elements
comparing equal according to the <seealso
marker="#ordering_function">ordering function</seealso>
- <c>Fun</c> have been deleted. <c>Fun(A, B)</c> should return
+ <c><anno>Fun</anno></c> have been deleted. <c><anno>Fun</anno>(A, B)</c> should return
<c>true</c> if <c>A</c> compares less than or equal to
<c>B</c> in the ordering, <c>false</c> otherwise.</p>
</desc>
</func>
<func>
- <name>zip(List1, List2) -> List3</name>
+ <name name="zip" arity="2"/>
<fsummary>Zip two lists into a list of two-tuples</fsummary>
- <type>
- <v>List1 = [X]</v>
- <v>List2 = [Y]</v>
- <v>List3 = [{X, Y}]</v>
- <v>&nbsp;X = Y = term()</v>
- </type>
<desc>
<p>"Zips" two lists of equal length into one list of two-tuples,
where the first element of each tuple is taken from the first
@@ -1126,15 +860,8 @@ splitwith(Pred, List) ->
</desc>
</func>
<func>
- <name>zip3(List1, List2, List3) -> List4</name>
+ <name name="zip3" arity="3"/>
<fsummary>Zip three lists into a list of three-tuples</fsummary>
- <type>
- <v>List1 = [X]</v>
- <v>List2 = [Y]</v>
- <v>List3 = [Z]</v>
- <v>List3 = [{X, Y, Z}]</v>
- <v>&nbsp;X = Y = Z = term()</v>
- </type>
<desc>
<p>"Zips" three lists of equal length into one list of
three-tuples, where the first element of each tuple is taken
@@ -1145,20 +872,13 @@ splitwith(Pred, List) ->
</desc>
</func>
<func>
- <name>zipwith(Combine, List1, List2) -> List3</name>
+ <name name="zipwith" arity="3"/>
<fsummary>Zip two lists into one list according to a fun</fsummary>
- <type>
- <v>Combine = fun(X, Y) -> T</v>
- <v>List1 = [X]</v>
- <v>List2 = [Y]</v>
- <v>List3 = [T]</v>
- <v>&nbsp;X = Y = T = term()</v>
- </type>
<desc>
<p>Combine the elements of two lists of equal length into one
- list. For each pair <c>X, Y</c> of list elements from the two
+ list. For each pair <c><anno>X</anno>, <anno>Y</anno></c> of list elements from the two
lists, the element in the result list will be
- <c>Combine(X, Y)</c>.</p>
+ <c><anno>Combine</anno>(<anno>X</anno>, <anno>Y</anno>)</c>.</p>
<p><c>zipwith(fun(X, Y) -> {X,Y} end, List1, List2)</c> is
equivalent to <c>zip(List1, List2)</c>.</p>
<p>Example:</p>
@@ -1168,21 +888,13 @@ splitwith(Pred, List) ->
</desc>
</func>
<func>
- <name>zipwith3(Combine, List1, List2, List3) -> List4</name>
+ <name name="zipwith3" arity="4"/>
<fsummary>Zip three lists into one list according to a fun</fsummary>
- <type>
- <v>Combine = fun(X, Y, Z) -> T</v>
- <v>List1 = [X]</v>
- <v>List2 = [Y]</v>
- <v>List3 = [Z]</v>
- <v>List4 = [T]</v>
- <v>&nbsp;X = Y = Z = T = term()</v>
- </type>
<desc>
<p>Combine the elements of three lists of equal length into one
- list. For each triple <c>X, Y, Z</c> of list elements from
+ list. For each triple <c><anno>X</anno>, <anno>Y</anno>, <anno>Z</anno></c> of list elements from
the three lists, the element in the result list will be
- <c>Combine(X, Y, Z)</c>.</p>
+ <c><anno>Combine</anno>(<anno>X</anno>, <anno>Y</anno>, <anno>Z</anno>)</c>.</p>
<p><c>zipwith3(fun(X, Y, Z) -> {X,Y,Z} end, List1, List2, List3)</c> is equivalent to <c>zip3(List1, List2, List3)</c>.</p>
<p>Examples:</p>
<pre>
diff --git a/lib/stdlib/doc/src/log_mf_h.xml b/lib/stdlib/doc/src/log_mf_h.xml
index f8e11339a7..f2b09b58eb 100644
--- a/lib/stdlib/doc/src/log_mf_h.xml
+++ b/lib/stdlib/doc/src/log_mf_h.xml
@@ -43,28 +43,27 @@
report files <c>1, 2, ....</c>.
</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="args"/>
+ <desc><p>Term to be sent to <seealso marker="gen_event#add_handler/3">
+ gen_event:add_handler/3</seealso>.</p></desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>init(Dir, MaxBytes, MaxFiles)</name>
- <name>init(Dir, MaxBytes, MaxFiles, Pred) -> Args</name>
+ <name name="init" arity="3"/>
+ <name name="init" arity="4"/>
<fsummary>Initiate the event handler</fsummary>
- <type>
- <v>Dir = string()</v>
- <v>MaxBytes = integer()</v>
- <v>MaxFiles = 0 &lt; integer() &lt; 256</v>
- <v>Pred = fun(Event) -> boolean()</v>
- <v>Event = term()</v>
- <v>Args = args()</v>
- </type>
<desc>
<p>Initiates the event handler. This function returns
- <c>Args</c>, which should be used in a call to
- <c>gen_event:add_handler(EventMgr, log_mf_h, Args)</c>.
+ <c><anno>Args</anno></c>, which should be used in a call to
+ <c>gen_event:add_handler(EventMgr, log_mf_h, <anno>Args</anno>)</c>.
</p>
- <p><c>Dir</c> specifies which directory to use for the log
- files. <c>MaxBytes</c> specifies the size of each individual
- file. <c>MaxFiles</c> specifies how many files are
- used. <c>Pred</c> is a predicate function used to filter the
+ <p><c><anno>Dir</anno></c> specifies which directory to use for the log
+ files. <c><anno>MaxBytes</anno></c> specifies the size of each individual
+ file. <c><anno>MaxFiles</anno></c> specifies how many files are
+ used. <c><anno>Pred</anno></c> is a predicate function used to filter the
events. If no predicate function is specified, all events are
logged.</p>
</desc>
diff --git a/lib/stdlib/doc/src/math.xml b/lib/stdlib/doc/src/math.xml
index 02e4d6e495..518457d5d8 100644
--- a/lib/stdlib/doc/src/math.xml
+++ b/lib/stdlib/doc/src/math.xml
@@ -45,7 +45,7 @@
</description>
<funcs>
<func>
- <name>pi() -> float()</name>
+ <name name="pi" arity="0"/>
<fsummary>A useful number</fsummary>
<desc>
<p>A useful number.</p>
diff --git a/lib/stdlib/doc/src/ms_transform.xml b/lib/stdlib/doc/src/ms_transform.xml
index ba9f89685b..f81f8bda96 100644
--- a/lib/stdlib/doc/src/ms_transform.xml
+++ b/lib/stdlib/doc/src/ms_transform.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2002</year><year>2010</year>
+ <year>2002</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -599,12 +599,9 @@ ets:select(Table, [{{'$1',test,'$2'},[],['$_']}]).</code>
</description>
<funcs>
<func>
- <name>parse_transform(Forms,_Options) -> Forms</name>
+ <name name="parse_transform" arity="2"/>
<fsummary>Transforms Erlang abstract format containing calls to ets/dbg:fun2ms into literal match specifications.</fsummary>
- <type>
- <v>Forms = Erlang abstract code format, see the erl_parse module description </v>
- <v>_Options = Option list, required but not used</v>
- </type>
+ <type_desc variable="Options">Option list, required but not used.</type_desc>
<desc>
<p>Implements the actual transformation at compile time. This
function is called by the compiler to do the source code
@@ -617,29 +614,21 @@ ets:select(Table, [{{'$1',test,'$2'},[],['$_']}]).</code>
</desc>
</func>
<func>
- <name>transform_from_shell(Dialect,Clauses,BoundEnvironment) -> term()</name>
+ <name name="transform_from_shell" arity="3"/>
<fsummary>Used when transforming fun's created in the shell into match_specifications.</fsummary>
- <type>
- <v>Dialect = ets | dbg</v>
- <v>Clauses = Erlang abstract form for a single fun</v>
- <v>BoundEnvironment = [{atom(), term()}, ...], list of variable bindings in the shell environment</v>
- </type>
+ <type_desc variable="BoundEnvironment">List of variable bindings in the shell environment.</type_desc>
<desc>
<p>Implements the actual transformation when the <c>fun2ms</c>
functions are called from the shell. In this case the abstract
form is for one single fun (parsed by the Erlang shell), and
all imported variables should be in the key-value list passed
- as <c>BoundEnvironment</c>. The result is a term, normalized,
+ as <c><anno>BoundEnvironment</anno></c>. The result is a term, normalized,
i.e. not in abstract format.</p>
</desc>
</func>
<func>
- <name>format_error(Errcode) -> ErrMessage</name>
+ <name name="format_error" arity="1"/>
<fsummary>Error formatting function as required by the parse_transform interface.</fsummary>
- <type>
- <v>Errcode = term()</v>
- <v>ErrMessage = string()</v>
- </type>
<desc>
<p>Takes an error code returned by one of the other functions
in the module and creates a textual description of the
diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml
index 8cd499f960..d9c220b996 100644
--- a/lib/stdlib/doc/src/notes.xml
+++ b/lib/stdlib/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,6 +30,349 @@
</header>
<p>This document describes the changes made to the STDLIB application.</p>
+<section><title>STDLIB 1.17.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ erl_tar:extract failed when executed inside a directory
+ with some parent directory to which the user has no read
+ access. This has been corrected.</p>
+ <p>
+ Own Id: OTP-9368</p>
+ </item>
+ <item>
+ <p> A bug in <c>erl_scan:set_attribute/3</c> has been
+ fixed. </p>
+ <p>
+ Own Id: OTP-9412</p>
+ </item>
+ <item>
+ <p> The contract of <c>io_lib:fread()</c> has been
+ corrected. </p>
+ <p>
+ Own Id: OTP-9413 Aux Id: seq11873 </p>
+ </item>
+ <item>
+ <p>
+ A crash in io_lib:fread/2 when end of input data was
+ encountered while trying to match literal characters,
+ which should return {more,_,_,_} but instead crashed, has
+ been corrected. Reported by Klas Johansson.</p>
+ <p>
+ A similar peculiarity for io:fread when encountering end
+ of file before any field data has also been corrected.</p>
+ <p>
+ Own Id: OTP-9439</p>
+ </item>
+ <item>
+ <p> The contract of <c>timer:now_diff()</c> has been
+ corrected. (Thanks to Alex Morarash). </p>
+ <p>
+ Own Id: OTP-9450</p>
+ </item>
+ <item>
+ <p>
+ Fix minor typo in gen_fsm documentation (Thanks to Haitao
+ Li)</p>
+ <p>
+ Own Id: OTP-9456</p>
+ </item>
+ <item>
+ <p>The contracts of <c>zip:zip_list_dir/1</c> and
+ <c>zip:zip_get/2</c> have been corrected. </p>
+ <p>
+ Own Id: OTP-9471 Aux Id: seq11887, OTP-9472 </p>
+ </item>
+ <item>
+ <p> A bug in <c>zip:zip_open()</c> has been fixed. </p>
+ <p>
+ Own Id: OTP-9472 Aux Id: seq11887, OTP-9471 </p>
+ </item>
+ <item>
+ <p>
+ Fix trivial documentation errors(Thanks to Matthias Lang)</p>
+ <p>
+ Own Id: OTP-9498</p>
+ </item>
+ <item>
+ <p>
+ Add a proplist() type</p>
+ <p>
+ Recently I was adding specs to an API and found that
+ there is no canonical proplist() type defined. (Thanks to
+ Ryan Zezeski)</p>
+ <p>
+ Own Id: OTP-9499</p>
+ </item>
+ <item>
+ <p>
+ fix supervisors restarting temporary children</p>
+ <p>
+ In the current implementation of supervisors, temporary
+ children should never be restarted. However, when a
+ temporary child is restarted as part of a one_for_all or
+ rest_for_one strategy where the failing process is not
+ the temporary child, the supervisor still tries to
+ restart it.</p>
+ <p>
+ Because the supervisor doesn't keep some of the MFA
+ information of temporary children, this causes the
+ supervisor to hit its restart limit and crash.</p>
+ <p>
+ This patch fixes the behaviour by inserting a clause in
+ terminate_children/2-3 (private function) that will omit
+ temporary children when building a list of killed
+ processes, to avoid having the supervisor trying to
+ restart them again.</p>
+ <p>
+ Only supervisors in need of restarting children used the
+ list, so the change should be of no impact for the
+ functions that called terminate_children/2-3 only to kill
+ all children.</p>
+ <p>
+ The documentation has been modified to make this
+ behaviour more explicit. (Thanks to Fred Hebert)</p>
+ <p>
+ Own Id: OTP-9502</p>
+ </item>
+ <item>
+ <p>
+ fix broken edoc annotations (Thanks to Richard Carlsson)</p>
+ <p>
+ Own Id: OTP-9516</p>
+ </item>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ <item>
+ <p>
+ Handle rare race in the crypto key server functionality</p>
+ <p>
+ Own Id: OTP-9586</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Types and specifications have been added. </p>
+ <p>
+ Own Id: OTP-9356</p>
+ </item>
+ <item>
+ <p> The contracts of the <c>queue</c> module have been
+ modified. </p>
+ <p>
+ Own Id: OTP-9418</p>
+ </item>
+ <item>
+ <p> Contracts in STDLIB and Kernel have been improved and
+ type errors have been corrected. </p>
+ <p>
+ Own Id: OTP-9485</p>
+ </item>
+ <item>
+ <p>
+ Types for several BIFs have been extended/corrected. Also
+ the types for types for <c>lists:keyfind/3</c>,
+ <c>lists:keysearch/3</c>, and <c>lists:keyemember/3</c>
+ have been corrected. The incorrect/incomplete types could
+ cause false dialyzer warnings.</p>
+ <p>
+ Own Id: OTP-9496</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 1.17.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> The default value <c>undefined</c> was added to
+ records field types in such a way that the result was not
+ always a well-formed type. This bug has been fixed. </p>
+ <p>
+ Own Id: OTP-9147</p>
+ </item>
+ <item>
+ <p>
+ Update index file atomically</p>
+ <p>
+ Since the log_mf_h index file might be read by other
+ processes than the error handler (e.g. by the rb tool),
+ this file should be updated atomically. This will avoid
+ hitting the time gap between opening the file in write
+ mode (and thus emptying the file) and the actual update
+ with the new contents. To do this, a temporary file is
+ written, and the file:rename/1 used to replace the real
+ index file.</p>
+ <p>
+ Own Id: OTP-9148</p>
+ </item>
+ <item>
+ <p>
+ Fixed various typos across the documentation (Thanks to
+ Tuncer Ayaz)</p>
+ <p>
+ Own Id: OTP-9154</p>
+ </item>
+ <item>
+ <p>
+ Supervisors should not save child-specs for temporary
+ processes when they terminate as they should not be
+ restarted. Saving the temporary child spec will result in
+ that you can not start a new temporary process with the
+ same child spec as an already terminated temporary
+ process. Since R14B02 you can not restart a temporary
+ temporary process as arguments are no longer saved, it
+ has however always been semantically incorrect to restart
+ a temporary process. Thanks to Filipe David Manana for
+ reporting this and suggesting a solution.</p>
+ <p>
+ Own Id: OTP-9167 Aux Id: OTP-9064 </p>
+ </item>
+ <item>
+ <p>
+ Various small documentation fixes (Thanks to Bernard
+ Duggan)</p>
+ <p>
+ Own Id: OTP-9172</p>
+ </item>
+ <item>
+ <p>
+ Fix format_status bug for unregistered gen_event
+ processes</p>
+ <p>
+ Port the gen_fsm code for format_status to gen_event in
+ order to prevent a lists:concat([...,pid()]) crash when
+ calling sys:get_status/1 on an unregistered gen_event
+ process.</p>
+ <p>
+ Refactor format_status header code from gen_* behaviours
+ to module gen.</p>
+ <p>
+ Extend the format_status tests in gen_event_SUITE to
+ cover format_status bugs with anonymous gen_event
+ processes. (Thanks To Geoff Cant)</p>
+ <p>
+ Own Id: OTP-9218</p>
+ </item>
+ <item>
+ <p>
+ List of pids changed to 'set' in supervisor for dynamic
+ temporary children. Accessing the list would not scale
+ well when adding/deleting many children. (Thanks to
+ Evgeniy Khramtsov)</p>
+ <p>
+ Own Id: OTP-9242</p>
+ </item>
+ <item>
+ <p>
+ Change pool module to attempt to attach to nodes that are
+ already running</p>
+ <p>
+ The pool module prints out an error message and takes no
+ further action for nodes that are already running. This
+ patch changes that behavior so that if the return from
+ slave:start/3 is {already_running, Node} then an attempt
+ to attach to the node is still made. This makes sense
+ because the node has been specified by the user in the
+ .hosts.erlang file indicating a wish for the node to be
+ part of the pool and a manual attach can be successfully
+ made after the pool is started.(Thanks to Kelly
+ McLaughlin)</p>
+ <p>
+ Own Id: OTP-9244</p>
+ </item>
+ <item>
+ <p>
+ unicode: document 16#FFFE and 16#FFFF (non chars)(Thanks
+ to Tuncer Ayaz)</p>
+ <p>
+ Own Id: OTP-9256</p>
+ </item>
+ <item>
+ <p>
+ re: remove gratuitous "it " in manpage (Thanks to Tuncer
+ Ayaz)</p>
+ <p>
+ Own Id: OTP-9307</p>
+ </item>
+ <item>
+ <p> A bug in erl_eval(3) has been fixed. </p>
+ <p>
+ Own Id: OTP-9322</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add <c>timer:tc/1</c> and remove the catch in <c>tc/2</c>
+ and <c>tc/3</c>. The time measuring functions will thus
+ no longer trap exits, errors or throws caused by the
+ measured function.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-9169</p>
+ </item>
+ <item>
+ <p>
+ Allow supervisor:terminate_child(SupRef,Pid) for
+ simple_one_for_one supervisors</p>
+ <p>
+ supervisor:terminate_child/2 was earlier not allowed if
+ the supervisor used restart strategy simple_one_for_one.
+ This is now changed so that children of this type of
+ supervisors can be terminated by specifying the child's
+ Pid.</p>
+ <p>
+ (Thanks to Vance Shipley.)</p>
+ <p>
+ Own Id: OTP-9201</p>
+ </item>
+ <item>
+ <p> Types and specifications have been added. </p>
+ <p>
+ Own Id: OTP-9267</p>
+ </item>
+ <item>
+ <p> Erlang types and specifications are used for
+ documentation. </p>
+ <p>
+ Own Id: OTP-9271</p>
+ </item>
+ <item>
+ <p>Allow Dets tablenames to be arbitrary terms.</p>
+ <p>
+ Own Id: OTP-9282</p>
+ </item>
+ <item>
+ <p> A specification that could cause problems for
+ Dialyzer has been fixed. An opaque type in erl_eval has
+ been turned in to a ordinary type. This is a temporary
+ fix. </p>
+ <p>
+ Own Id: OTP-9333</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>STDLIB 1.17.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -2451,7 +2794,7 @@
that is, also when starting a gen_server, gen_fsm etc. </p>
<p>This limitation has now been properly documented and the
behavior of the <c>gen_fsm</c>, <c>gen_server</c>, and
- <c>proc_lib</c><c>start</c> and <c>start_link</c>
+ <c>proc_lib</c> <c>start</c> and <c>start_link</c>
functions when providing this option has been changed
from hanging indefinitely to failing with reason
<c>badarg</c>.</p>
@@ -2568,7 +2911,6 @@
<c>join</c> option that can be used to force QLC to use a
particular kind of join in some QLC expression.</p>
<p>Several other changes have also been included:</p>
- <p></p>
<list type="bulleted">
<item>
<p>The new <c>tmpdir</c> option of <c>cursor/2</c>,
diff --git a/lib/stdlib/doc/src/orddict.xml b/lib/stdlib/doc/src/orddict.xml
index 1b8b74534b..319083d35b 100644
--- a/lib/stdlib/doc/src/orddict.xml
+++ b/lib/stdlib/doc/src/orddict.xml
@@ -46,176 +46,123 @@
(<c>==</c>).</p>
</description>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-ordered_dictionary()
- as returned by new/0</code>
- </section>
+ <datatypes>
+ <datatype>
+ <name name="orddict"/>
+ <desc><p>As returned by new/0.</p></desc>
+ </datatype>
+ </datatypes>
+
<funcs>
<func>
- <name>append(Key, Value, Orddict1) -> Orddict2</name>
+ <name name="append" arity="3"/>
<fsummary>Append a value to keys in a dictionary</fsummary>
- <type>
- <v>Key = Value = term()</v>
- <v>Orddict1 = Orddict2 = ordered_dictionary()</v>
- </type>
<desc>
- <p>This function appends a new <c>Value</c> to the current list
- of values associated with <c>Key</c>. An exception is
- generated if the initial value associated with <c>Key</c> is
+ <p>This function appends a new <c><anno>Value</anno></c> to the current list
+ of values associated with <c><anno>Key</anno></c>. An exception is
+ generated if the initial value associated with <c><anno>Key</anno></c> is
not a list of values.</p>
</desc>
</func>
<func>
- <name>append_list(Key, ValList, Orddict1) -> Orddict2</name>
+ <name name="append_list" arity="3"/>
<fsummary>Append new values to keys in a dictionary</fsummary>
- <type>
- <v>ValList = [Value]</v>
- <v>Key = Value = term()</v>
- <v>Orddict1 = Orddict2 = ordered_dictionary()</v>
- </type>
<desc>
- <p>This function appends a list of values <c>ValList</c> to
- the current list of values associated with <c>Key</c>. An
+ <p>This function appends a list of values <c><anno>ValList</anno></c> to
+ the current list of values associated with <c><anno>Key</anno></c>. An
exception is generated if the initial value associated with
- <c>Key</c> is not a list of values.</p>
+ <c><anno>Key</anno></c> is not a list of values.</p>
</desc>
</func>
<func>
- <name>erase(Key, Orddict1) -> Orddict2</name>
+ <name name="erase" arity="2"/>
<fsummary>Erase a key from a dictionary</fsummary>
- <type>
- <v>Key = term()</v>
- <v>Orddict1 = Orddict2 = ordered_dictionary()</v>
- </type>
<desc>
<p>This function erases all items with a given key from a
dictionary.</p>
</desc>
</func>
<func>
- <name>fetch(Key, Orddict) -> Value</name>
+ <name name="fetch" arity="2"/>
<fsummary>Look-up values in a dictionary</fsummary>
- <type>
- <v>Key = Value = term()</v>
- <v>Orddict = ordered_dictionary()</v>
- </type>
<desc>
- <p>This function returns the value associated with <c>Key</c>
- in the dictionary <c>Orddict</c>. <c>fetch</c> assumes that
- the <c>Key</c> is present in the dictionary and an exception
- is generated if <c>Key</c> is not in the dictionary.</p>
+ <p>This function returns the value associated with <c><anno>Key</anno></c>
+ in the dictionary <c><anno>Orddict</anno></c>. <c>fetch</c> assumes that
+ the <c><anno>Key</anno></c> is present in the dictionary and an exception
+ is generated if <c><anno>Key</anno></c> is not in the dictionary.</p>
</desc>
</func>
<func>
- <name>fetch_keys(Orddict) -> Keys</name>
+ <name name="fetch_keys" arity="1"/>
<fsummary>Return all keys in a dictionary</fsummary>
- <type>
- <v>Orddict = ordered_dictionary()</v>
- <v>Keys = [term()]</v>
- </type>
<desc>
<p>This function returns a list of all keys in the dictionary.</p>
</desc>
</func>
<func>
- <name>filter(Pred, Orddict1) -> Orddict2</name>
+ <name name="filter" arity="2"/>
<fsummary>Choose elements which satisfy a predicate</fsummary>
- <type>
- <v>Pred = fun(Key, Value) -> bool()</v>
- <v>&nbsp;Key = Value = term()</v>
- <v>Orddict1 = Orddict2 = ordered_dictionary()</v>
- </type>
<desc>
- <p><c>Orddict2</c> is a dictionary of all keys and values in
- <c>Orddict1</c> for which <c>Pred(Key, Value)</c> is <c>true</c>.</p>
+ <p><c><anno>Orddict2</anno></c> is a dictionary of all keys and values in
+ <c><anno>Orddict1</anno></c> for which <c><anno>Pred</anno>(<anno>Key</anno>, <anno>Value</anno>)</c> is <c>true</c>.</p>
</desc>
</func>
<func>
- <name>find(Key, Orddict) -> {ok, Value} | error</name>
+ <name name="find" arity="2"/>
<fsummary>Search for a key in a dictionary</fsummary>
- <type>
- <v>Key = Value = term()</v>
- <v>Orddict = ordered_dictionary()</v>
- </type>
<desc>
<p>This function searches for a key in a dictionary. Returns
- <c>{ok, Value}</c> where <c>Value</c> is the value associated
- with <c>Key</c>, or <c>error</c> if the key is not present in
+ <c>{ok, <anno>Value</anno>}</c> where <c><anno>Value</anno></c> is the value associated
+ with <c><anno>Key</anno></c>, or <c>error</c> if the key is not present in
the dictionary.</p>
</desc>
</func>
<func>
- <name>fold(Fun, Acc0, Orddict) -> Acc1</name>
+ <name name="fold" arity="3"/>
<fsummary>Fold a function over a dictionary</fsummary>
- <type>
- <v>Fun = fun(Key, Value, AccIn) -> AccOut</v>
- <v>Key = Value = term()</v>
- <v>Acc0 = Acc1 = AccIn = AccOut = term()</v>
- <v>Orddict = ordered_dictionary()</v>
- </type>
<desc>
- <p>Calls <c>Fun</c> on successive keys and values of
- <c>Orddict</c> together with an extra argument <c>Acc</c>
- (short for accumulator). <c>Fun</c> must return a new
- accumulator which is passed to the next call. <c>Acc0</c> is
+ <p>Calls <c><anno>Fun</anno></c> on successive keys and values of
+ <c><anno>Orddict</anno></c> together with an extra argument <c>Acc</c>
+ (short for accumulator). <c><anno>Fun</anno></c> must return a new
+ accumulator which is passed to the next call. <c><anno>Acc0</anno></c> is
returned if the list is empty. The evaluation order is
undefined.</p>
</desc>
</func>
<func>
- <name>from_list(List) -> Orddict</name>
+ <name name="from_list" arity="1"/>
<fsummary>Convert a list of pairs to a dictionary</fsummary>
- <type>
- <v>List = [{Key, Value}]</v>
- <v>Orddict = ordered_dictionary()</v>
- </type>
<desc>
- <p>This function converts the <c>Key</c> - <c>Value</c> list
- <c>List</c> to a dictionary.</p>
+ <p>This function converts the <c><anno>Key</anno></c> - <c><anno>Value</anno></c> list
+ <c><anno>List</anno></c> to a dictionary.</p>
</desc>
</func>
<func>
- <name>is_key(Key, Orddict) -> bool()</name>
+ <name name="is_key" arity="2"/>
<fsummary>Test if a key is in a dictionary</fsummary>
- <type>
- <v>Key = term()</v>
- <v>Orddict = ordered_dictionary()</v>
- </type>
<desc>
- <p>This function tests if <c>Key</c> is contained in
- the dictionary <c>Orddict</c>.</p>
+ <p>This function tests if <c><anno>Key</anno></c> is contained in
+ the dictionary <c><anno>Orddict</anno></c>.</p>
</desc>
</func>
<func>
- <name>map(Fun, Orddict1) -> Orddict2</name>
+ <name name="map" arity="2"/>
<fsummary>Map a function over a dictionary</fsummary>
- <type>
- <v>Fun = fun(Key, Value1) -> Value2</v>
- <v>&nbsp;Key = Value1 = Value2 = term()</v>
- <v>Orddict1 = Orddict2 = ordered_dictionary()</v>
- </type>
<desc>
- <p><c>map</c> calls <c>Func</c> on successive keys and values
- of <c>Orddict</c> to return a new value for each key.
+ <p><c>map</c> calls <c><anno>Fun</anno></c> on successive keys and values
+ of <c><anno>Orddict1</anno></c> to return a new value for each key.
The evaluation order is undefined.</p>
</desc>
</func>
<func>
- <name>merge(Fun, Orddict1, Orddict2) -> Orddict3</name>
+ <name name="merge" arity="3"/>
<fsummary>Merge two dictionaries</fsummary>
- <type>
- <v>Fun = fun(Key, Value1, Value2) -> Value</v>
- <v>&nbsp;Key = Value1 = Value2 = Value3 = term()</v>
- <v>Orddict1 = Orddict2 = Orddict3 = ordered_dictionary()</v>
- </type>
<desc>
- <p><c>merge</c> merges two dictionaries, <c>Orddict1</c> and
- <c>Orddict2</c>, to create a new dictionary. All the <c>Key</c>
- - <c>Value</c> pairs from both dictionaries are included in
+ <p><c>merge</c> merges two dictionaries, <c><anno>Orddict1</anno></c> and
+ <c><anno>Orddict2</anno></c>, to create a new dictionary. All the <c><anno>Key</anno></c>
+ - <c><anno>Value</anno></c> pairs from both dictionaries are included in
the new dictionary. If a key occurs in both dictionaries then
- <c>Fun</c> is called with the key and both values to return a
+ <c><anno>Fun</anno></c> is called with the key and both values to return a
new value. <c>merge</c> could be defined as:</p>
<code type="none">
merge(Fun, D1, D2) ->
@@ -226,75 +173,52 @@ merge(Fun, D1, D2) ->
</desc>
</func>
<func>
- <name>new() -> ordered_dictionary()</name>
+ <name name="new" arity="0"/>
<fsummary>Create a dictionary</fsummary>
<desc>
<p>This function creates a new dictionary.</p>
</desc>
</func>
<func>
- <name>size(Orddict) -> int()</name>
+ <name name="size" arity="1"/>
<fsummary>Return the number of elements in an ordered dictionary</fsummary>
- <type>
- <v>Orddict = ordered_dictionary()</v>
- </type>
<desc>
- <p>Returns the number of elements in an <c>Orddict</c>.</p>
+ <p>Returns the number of elements in an <c><anno>Orddict</anno></c>.</p>
</desc>
</func>
<func>
- <name>store(Key, Value, Orddict1) -> Orddict2</name>
+ <name name="store" arity="3"/>
<fsummary>Store a value in a dictionary</fsummary>
- <type>
- <v>Key = Value = term()</v>
- <v>Orddict1 = Orddict2 = ordered_dictionary()</v>
- </type>
<desc>
- <p>This function stores a <c>Key</c> - <c>Value</c> pair in a
- dictionary. If the <c>Key</c> already exists in <c>Orddict1</c>,
- the associated value is replaced by <c>Value</c>.</p>
+ <p>This function stores a <c><anno>Key</anno></c> - <c><anno>Value</anno></c> pair in a
+ dictionary. If the <c><anno>Key</anno></c> already exists in <c><anno>Orddict1</anno></c>,
+ the associated value is replaced by <c><anno>Value</anno></c>.</p>
</desc>
</func>
<func>
- <name>to_list(Orddict) -> List</name>
+ <name name="to_list" arity="1"/>
<fsummary>Convert a dictionary to a list of pairs</fsummary>
- <type>
- <v>Orddict = ordered_dictionary()</v>
- <v>List = [{Key, Value}]</v>
- </type>
<desc>
<p>This function converts the dictionary to a list
representation.</p>
</desc>
</func>
<func>
- <name>update(Key, Fun, Orddict1) -> Orddict2</name>
+ <name name="update" arity="3"/>
<fsummary>Update a value in a dictionary</fsummary>
- <type>
- <v>Key = term()</v>
- <v>Fun = fun(Value1) -> Value2</v>
- <v>&nbsp;Value1 = Value2 = term()</v>
- <v>Orddict1 = Orddict2 = ordered_dictionary()</v>
- </type>
<desc>
- <p>Update a value in a dictionary by calling <c>Fun</c> on
+ <p>Update a value in a dictionary by calling <c><anno>Fun</anno></c> on
the value to get a new value. An exception is generated if
- <c>Key</c> is not present in the dictionary.</p>
+ <c><anno>Key</anno></c> is not present in the dictionary.</p>
</desc>
</func>
<func>
- <name>update(Key, Fun, Initial, Orddict1) -> Orddict2</name>
+ <name name="update" arity="4"/>
<fsummary>Update a value in a dictionary</fsummary>
- <type>
- <v>Key = Initial = term()</v>
- <v>Fun = fun(Value1) -> Value2</v>
- <v>&nbsp;Value1 = Value2 = term()</v>
- <v>Orddict1 = Orddict2 = ordered_dictionary()</v>
- </type>
<desc>
- <p>Update a value in a dictionary by calling <c>Fun</c> on
- the value to get a new value. If <c>Key</c> is not present
- in the dictionary then <c>Initial</c> will be stored as
+ <p>Update a value in a dictionary by calling <c><anno>Fun</anno></c> on
+ the value to get a new value. If <c><anno>Key</anno></c> is not present
+ in the dictionary then <c><anno>Initial</anno></c> will be stored as
the first value. For example <c>append/3</c> could be defined
as:</p>
<code type="none">
@@ -303,17 +227,12 @@ append(Key, Val, D) ->
</desc>
</func>
<func>
- <name>update_counter(Key, Increment, Orddict1) -> Orddict2</name>
+ <name name="update_counter" arity="3"/>
<fsummary>Increment a value in a dictionary</fsummary>
- <type>
- <v>Key = term()</v>
- <v>Increment = number()</v>
- <v>Orddict1 = Orddict2 = ordered_dictionary()</v>
- </type>
<desc>
- <p>Add <c>Increment</c> to the value associated with <c>Key</c>
- and store this value. If <c>Key</c> is not present in
- the dictionary then <c>Increment</c> will be stored as
+ <p>Add <c><anno>Increment</anno></c> to the value associated with <c><anno>Key</anno></c>
+ and store this value. If <c><anno>Key</anno></c> is not present in
+ the dictionary then <c><anno>Increment</anno></c> will be stored as
the first value.</p>
<p>This could be defined as:</p>
<code type="none">
diff --git a/lib/stdlib/doc/src/ordsets.xml b/lib/stdlib/doc/src/ordsets.xml
index a20ab2d879..1e26fc2022 100644
--- a/lib/stdlib/doc/src/ordsets.xml
+++ b/lib/stdlib/doc/src/ordsets.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -45,202 +45,141 @@
different if and only if they do not compare equal (<c>==</c>).</p>
</description>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-ordered_set()
- as returned by new/0</code>
- </section>
+ <datatypes>
+ <datatype>
+ <name name="ordset" n_vars="1"/>
+ <desc><p>As returned by new/0.</p></desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>new() -> Ordset</name>
+ <name name="new" arity="0"/>
<fsummary>Return an empty set</fsummary>
- <type>
- <v>Ordset = ordered_set()</v>
- </type>
<desc>
<p>Returns a new empty ordered set.</p>
</desc>
</func>
<func>
- <name>is_set(Ordset) -> bool()</name>
+ <name name="is_set" arity="1"/>
<fsummary>Test for an <c>Ordset</c></fsummary>
- <type>
- <v>Ordset = term()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Ordset</c> is an ordered set of
+ <p>Returns <c>true</c> if <c><anno>Ordset</anno></c> is an ordered set of
elements, otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>size(Ordset) -> int()</name>
+ <name name="size" arity="1"/>
<fsummary>Return the number of elements in a set</fsummary>
- <type>
- <v>Ordset = term()</v>
- </type>
<desc>
- <p>Returns the number of elements in <c>Ordset</c>.</p>
+ <p>Returns the number of elements in <c><anno>Ordset</anno></c>.</p>
</desc>
</func>
<func>
- <name>to_list(Ordset) -> List</name>
+ <name name="to_list" arity="1"/>
<fsummary>Convert an <c>Ordset</c>into a list</fsummary>
- <type>
- <v>Ordset = ordered_set()</v>
- <v>List = [term()]</v>
- </type>
<desc>
- <p>Returns the elements of <c>Ordset</c> as a list.</p>
+ <p>Returns the elements of <c><anno>Ordset</anno></c> as a list.</p>
</desc>
</func>
<func>
- <name>from_list(List) -> Ordset</name>
+ <name name="from_list" arity="1"/>
<fsummary>Convert a list into an <c>Ordset</c></fsummary>
- <type>
- <v>List = [term()]</v>
- <v>Ordset = ordered_set()</v>
- </type>
<desc>
- <p>Returns an ordered set of the elements in <c>List</c>.</p>
+ <p>Returns an ordered set of the elements in <c><anno>List</anno></c>.</p>
</desc>
</func>
<func>
- <name>is_element(Element, Ordset) -> bool()</name>
+ <name name="is_element" arity="2"/>
<fsummary>Test for membership of an <c>Ordset</c></fsummary>
- <type>
- <v>Element = term()</v>
- <v>Ordset = ordered_set()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Element</c> is an element of
- <c>Ordset</c>, otherwise <c>false</c>.</p>
+ <p>Returns <c>true</c> if <c><anno>Element</anno></c> is an element of
+ <c><anno>Ordset</anno></c>, otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>add_element(Element, Ordset1) -> Ordset2</name>
+ <name name="add_element" arity="2"/>
<fsummary>Add an element to an <c>Ordset</c></fsummary>
- <type>
- <v>Element = term()</v>
- <v>Ordset1 = Ordset2 = ordered_set()</v>
- </type>
<desc>
- <p>Returns a new ordered set formed from <c>Ordset1</c> with
- <c>Element</c> inserted.</p>
+ <p>Returns a new ordered set formed from <c><anno>Ordset1</anno></c> with
+ <c><anno>Element</anno></c> inserted.</p>
</desc>
</func>
<func>
- <name>del_element(Element, Ordset1) -> Ordset2</name>
+ <name name="del_element" arity="2"/>
<fsummary>Remove an element from an <c>Ordset</c></fsummary>
- <type>
- <v>Element = term()</v>
- <v>Ordset1 = Ordset2 = ordered_set()</v>
- </type>
<desc>
- <p>Returns <c>Ordset1</c>, but with <c>Element</c> removed.</p>
+ <p>Returns <c><anno>Ordset1</anno></c>, but with <c><anno>Element</anno></c> removed.</p>
</desc>
</func>
<func>
- <name>union(Ordset1, Ordset2) -> Ordset3</name>
+ <name name="union" arity="2"/>
<fsummary>Return the union of two <c>Ordsets</c></fsummary>
- <type>
- <v>Ordset1 = Ordset2 = Ordset3 = ordered_set()</v>
- </type>
<desc>
- <p>Returns the merged (union) set of <c>Ordset1</c> and
- <c>Ordset2</c>.</p>
+ <p>Returns the merged (union) set of <c><anno>Ordset1</anno></c> and
+ <c><anno>Ordset2</anno></c>.</p>
</desc>
</func>
<func>
- <name>union(OrdsetList) -> Ordset</name>
+ <name name="union" arity="1"/>
<fsummary>Return the union of a list of <c>Ordsets</c></fsummary>
- <type>
- <v>OrdsetList = [ordered_set()]</v>
- <v>Ordset = ordered_set()</v>
- </type>
<desc>
<p>Returns the merged (union) set of the list of sets.</p>
</desc>
</func>
<func>
- <name>intersection(Ordset1, Ordset2) -> Ordset3</name>
+ <name name="intersection" arity="2"/>
<fsummary>Return the intersection of two <c>Ordsets</c></fsummary>
- <type>
- <v>Ordset1 = Ordset2 = Ordset3 = ordered_set()</v>
- </type>
<desc>
- <p>Returns the intersection of <c>Ordset1</c> and
- <c>Ordset2</c>.</p>
+ <p>Returns the intersection of <c><anno>Ordset1</anno></c> and
+ <c><anno>Ordset2</anno></c>.</p>
</desc>
</func>
<func>
- <name>intersection(OrdsetList) -> Ordset</name>
+ <name name="intersection" arity="1"/>
<fsummary>Return the intersection of a list of <c>Ordsets</c></fsummary>
- <type>
- <v>OrdsetList = [ordered_set()]</v>
- <v>Ordset = ordered_set()</v>
- </type>
<desc>
<p>Returns the intersection of the non-empty list of sets.</p>
</desc>
</func>
<func>
- <name>is_disjoint(Ordset1, Ordset2) -> bool()</name>
+ <name name="is_disjoint" arity="2"/>
<fsummary>Check whether two <c>Ordsets</c> are disjoint</fsummary>
- <type>
- <v>Ordset1 = Ordset2 = ordered_set()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Ordset1</c> and
- <c>Ordset2</c> are disjoint (have no elements in common),
+ <p>Returns <c>true</c> if <c><anno>Ordset1</anno></c> and
+ <c><anno>Ordset2</anno></c> are disjoint (have no elements in common),
and <c>false</c> otherwise.</p>
</desc>
</func>
<func>
- <name>subtract(Ordset1, Ordset2) -> Ordset3</name>
+ <name name="subtract" arity="2"/>
<fsummary>Return the difference of two <c>Ordsets</c></fsummary>
- <type>
- <v>Ordset1 = Ordset2 = Ordset3 = ordered_set()</v>
- </type>
<desc>
- <p>Returns only the elements of <c>Ordset1</c> which are not
- also elements of <c>Ordset2</c>.</p>
+ <p>Returns only the elements of <c><anno>Ordset1</anno></c> which are not
+ also elements of <c><anno>Ordset2</anno></c>.</p>
</desc>
</func>
<func>
- <name>is_subset(Ordset1, Ordset2) -> bool()</name>
+ <name name="is_subset" arity="2"/>
<fsummary>Test for subset</fsummary>
- <type>
- <v>Ordset1 = Ordset2 = ordered_set()</v>
- </type>
<desc>
- <p>Returns <c>true</c> when every element of <c>Ordset</c>1 is
- also a member of <c>Ordset2</c>, otherwise <c>false</c>.</p>
+ <p>Returns <c>true</c> when every element of <c><anno>Ordset1</anno></c> is
+ also a member of <c><anno>Ordset2</anno></c>, otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>fold(Function, Acc0, Ordset) -> Acc1</name>
+ <name name="fold" arity="3"/>
<fsummary>Fold over set elements</fsummary>
- <type>
- <v>Function = fun (E, AccIn) -> AccOut</v>
- <v>Acc0 = Acc1 = AccIn = AccOut = term()</v>
- <v>Ordset = ordered_set()</v>
- </type>
<desc>
- <p>Fold <c>Function</c> over every element in <c>Ordset</c>
+ <p>Fold <c><anno>Function</anno></c> over every element in <c><anno>Ordset</anno></c>
returning the final value of the accumulator.</p>
</desc>
</func>
<func>
- <name>filter(Pred, Ordset1) -> Set2</name>
+ <name name="filter" arity="2"/>
<fsummary>Filter set elements</fsummary>
- <type>
- <v>Pred = fun (E) -> bool()</v>
- <v>Set1 = Set2 = ordered_set()</v>
- </type>
<desc>
- <p>Filter elements in <c>Set1</c> with boolean function
- <c>Fun</c>.</p>
+ <p>Filter elements in <c><anno>Ordset1</anno></c> with boolean function
+ <c><anno>Pred</anno></c>.</p>
</desc>
</func>
</funcs>
diff --git a/lib/stdlib/doc/src/pg.xml b/lib/stdlib/doc/src/pg.xml
index b174d4f7d4..c56db8c6e6 100644
--- a/lib/stdlib/doc/src/pg.xml
+++ b/lib/stdlib/doc/src/pg.xml
@@ -51,77 +51,56 @@
</description>
<funcs>
<func>
- <name>create(PgName) -> ok | {error, Reason}</name>
+ <name name="create" arity="1"/>
<fsummary>Create an empty group</fsummary>
- <type>
- <v>PgName = term()</v>
- <v>Reason = already_created | term()</v>
- </type>
<desc>
- <p>Creates an empty group named <c>PgName</c> on the current
+ <p>Creates an empty group named <c><anno>PgName</anno></c> on the current
node.</p>
</desc>
</func>
<func>
- <name>create(PgName, Node) -> ok | {error, Reason}</name>
+ <name name="create" arity="2"/>
<fsummary>Create an empty group on another node</fsummary>
- <type>
- <v>PgName = term()</v>
- <v>Node = node()</v>
- <v>Reason = already_created | term()</v>
- </type>
<desc>
- <p>Creates an empty group named <c>PgName</c> on the node
- <c>Node</c>.</p>
+ <p>Creates an empty group named <c><anno>PgName</anno></c> on the node
+ <c><anno>Node</anno></c>.</p>
</desc>
</func>
<func>
- <name>join(PgName, Pid) -> Members</name>
+ <name name="join" arity="2"/>
<fsummary>Join a pid to a process group</fsummary>
- <type>
- <v>PgName = term()</v>
- <v>Pid = pid()</v>
- <v>Members = [pid()]</v>
- </type>
<desc>
- <p>Joins the pid <c>Pid</c> to the process group <c>PgName</c>.
+ <p>Joins the pid <c><anno>Pid</anno></c> to the process group
+ <c><anno>PgName</anno></c>.
Returns a list of all old members of the group.</p>
</desc>
</func>
<func>
- <name>send(PgName, Msg) -> void()</name>
+ <name name="send" arity="2"/>
<fsummary>Send a message to all members of a process group</fsummary>
- <type>
- <v>PgName = Msg = term()</v>
- </type>
<desc>
<p>Sends the tuple <c>{pg_message, From, PgName, Msg}</c> to
- all members of the process group <c>PgName</c>.</p>
- <p>Failure: <c>{badarg, {PgName, Msg}}</c> if <c>PgName</c> is
+ all members of the process group <c><anno>PgName</anno></c>.</p>
+ <p>Failure: <c>{badarg, {<anno>PgName</anno>, <anno>Msg</anno>}}</c>
+ if <c><anno>PgName</anno></c> is
not a process group (a globally registered name).</p>
</desc>
</func>
<func>
- <name>esend(PgName, Msg) -> void()</name>
+ <name name="esend" arity="2"/>
<fsummary>Send a message to all members of a process group, except ourselves</fsummary>
- <type>
- <v>PgName = Msg = term()</v>
- </type>
<desc>
<p>Sends the tuple <c>{pg_message, From, PgName, Msg}</c> to
- all members of the process group <c>PgName</c>, except
+ all members of the process group <c><anno>PgName</anno></c>, except
ourselves.</p>
- <p>Failure: <c>{badarg, {PgName, Msg}}</c> if <c>PgName</c> is
+ <p>Failure: <c>{badarg, {<anno>PgName</anno>, <anno>Msg</anno>}}</c>
+ if <c><anno>PgName</anno></c> is
not a process group (a globally registered name).</p>
</desc>
</func>
<func>
- <name>members(PgName) -> Members</name>
+ <name name="members" arity="1"/>
<fsummary>Return a list of all members of a process group</fsummary>
- <type>
- <v>PgName = term()</v>
- <v>Members = [pid()]</v>
- </type>
<desc>
<p>Returns a list of all members of the process group
<c>PgName</c>.</p>
diff --git a/lib/stdlib/doc/src/pool.xml b/lib/stdlib/doc/src/pool.xml
index 2b890352eb..39a79e5dc5 100644
--- a/lib/stdlib/doc/src/pool.xml
+++ b/lib/stdlib/doc/src/pool.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -48,23 +48,19 @@
</description>
<funcs>
<func>
- <name>start(Name) -></name>
- <name>start(Name, Args) -> Nodes</name>
+ <name name="start" arity="1"/>
+ <name name="start" arity="2"/>
<fsummary>>Start a new pool</fsummary>
- <type>
- <v>Name = atom()</v>
- <v>Args = string()</v>
- <v>Nodes = [node()]</v>
- </type>
<desc>
<p>Starts a new pool. The file <c>.hosts.erlang</c> is read to
find host names where the pool nodes can be started. See
section <seealso marker="#files">Files</seealso> below. The
start-up procedure fails if the file is not found.</p>
<p>The slave nodes are started with <c>slave:start/2,3</c>,
- passing along <c>Name</c> and, if provided, <c>Args</c>.
- <c>Name</c> is used as the first part of the node names,
- <c>Args</c> is used to specify command line arguments. See
+ passing along <c><anno>Name</anno></c> and, if provided,
+ <c><anno>Args</anno></c>.
+ <c><anno>Name</anno></c> is used as the first part of the node names,
+ <c><anno>Args</anno></c> is used to specify command line arguments. See
<seealso marker="slave#start/2">slave(3)</seealso>.</p>
<p>Access rights must be set so that all nodes in the pool have
the authority to access each other.</p>
@@ -73,59 +69,45 @@
</desc>
</func>
<func>
- <name>attach(Node) -> already_attached | attached</name>
+ <name name="attach" arity="1"/>
<fsummary>Ensure that a pool master is running</fsummary>
- <type>
- <v>Node = node()</v>
- </type>
<desc>
<p>This function ensures that a pool master is running and
- includes <c>Node</c> in the pool master's pool of nodes.</p>
+ includes <c><anno>Node</anno></c> in the pool master's pool of nodes.</p>
</desc>
</func>
<func>
- <name>stop() -> stopped</name>
+ <name name="stop" arity="0"/>
<fsummary>Stop the pool and kill all the slave nodes</fsummary>
<desc>
<p>Stops the pool and kills all the slave nodes.</p>
</desc>
</func>
<func>
- <name>get_nodes() -> Nodes</name>
+ <name name="get_nodes" arity="0"/>
<fsummary>Return a list of the current member nodes of the pool</fsummary>
- <type>
- <v>Nodes = [node()]</v>
- </type>
<desc>
<p>Returns a list of the current member nodes of the pool.</p>
</desc>
</func>
<func>
- <name>pspawn(Mod, Fun, Args) -> pid()</name>
+ <name name="pspawn" arity="3"/>
<fsummary>Spawn a process on the pool node with expected lowest future load</fsummary>
- <type>
- <v>Mod = Fun = atom()</v>
- <v>Args = [term()]</v>
- </type>
<desc>
<p>Spawns a process on the pool node which is expected to have
the lowest future load.</p>
</desc>
</func>
<func>
- <name>pspawn_link(Mod, Fun, Args) -> pid()</name>
+ <name name="pspawn_link" arity="3"/>
<fsummary>Spawn and link to a process on the pool node with expected lowest future load</fsummary>
- <type>
- <v>Mod = Fun = atom()</v>
- <v>Args = [term()]</v>
- </type>
<desc>
<p>Spawn links a process on the pool node which is expected to
have the lowest future load.</p>
</desc>
</func>
<func>
- <name>get_node() -> node()</name>
+ <name name="get_node" arity="0"/>
<fsummary>Return the node with the expected lowest future load</fsummary>
<desc>
<p>Returns the node with the expected lowest future load.</p>
diff --git a/lib/stdlib/doc/src/proc_lib.xml b/lib/stdlib/doc/src/proc_lib.xml
index 791001cb52..abc17c4a91 100644
--- a/lib/stdlib/doc/src/proc_lib.xml
+++ b/lib/stdlib/doc/src/proc_lib.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -60,19 +60,33 @@
information regarding other processes which terminate as a result
of this process terminating.</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="spawn_option"/>
+ <desc>
+ <p>See <seealso marker="erts:erlang#spawn_opt/4">
+ erlang:spawn_opt/2,3,4,5</seealso>.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="priority_level"/>
+ </datatype>
+ <datatype>
+ <name name="dict_or_pid"/>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>spawn(Fun) -> pid()</name>
- <name>spawn(Node, Fun) -> pid()</name>
- <name>spawn(Module, Function, Args) -> pid()</name>
- <name>spawn(Node, Module, Function, Args) -> pid()</name>
+ <name name="spawn" arity="1"/>
+ <name name="spawn" arity="2"/>
+ <name name="spawn" arity="3"/>
+ <name name="spawn" arity="4"/>
<fsummary>Spawn a new process.</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Fun = fun() -> void()</v>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- </type>
+ <type variable="Node"/>
+ <type variable="Fun" name_i="1"/>
+ <type variable="Module"/>
+ <type variable="Function"/>
+ <type variable="Args"/>
<desc>
<p>Spawns a new process and initializes it as described above.
The process is spawned using the
@@ -80,17 +94,16 @@
</desc>
</func>
<func>
- <name>spawn_link(Fun) -> pid()</name>
- <name>spawn_link(Node, Fun) -> pid()</name>
- <name>spawn_link(Module, Function, Args) -> pid()</name>
- <name>spawn_link(Node, Module, Function, Args) -> pid()</name>
+ <name name="spawn_link" arity="1"/>
+ <name name="spawn_link" arity="2"/>
+ <name name="spawn_link" arity="3"/>
+ <name name="spawn_link" arity="4"/>
<fsummary>Spawn and link to a new process.</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Fun = fun() -> void()</v>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- </type>
+ <type variable="Node"/>
+ <type variable="Fun" name_i="1"/>
+ <type variable="Module"/>
+ <type variable="Function"/>
+ <type variable="Args"/>
<desc>
<p>Spawns a new process and initializes it as described above.
The process is spawned using the
@@ -99,18 +112,17 @@
</desc>
</func>
<func>
- <name>spawn_opt(Fun, SpawnOpts) -> pid()</name>
- <name>spawn_opt(Node, Fun, SpawnOpts) -> pid()</name>
- <name>spawn_opt(Module, Function, Args, SpawnOpts) -> pid()</name>
- <name>spawn_opt(Node, Module, Func, Args, SpawnOpts) -> pid()</name>
+ <name name="spawn_opt" arity="2"/>
+ <name name="spawn_opt" arity="3"/>
+ <name name="spawn_opt" arity="4"/>
+ <name name="spawn_opt" arity="5"/>
<fsummary>Spawn a new process with given options.</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Fun = fun() -> void()</v>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- <v>SpawnOpts -- see erlang:spawn_opt/2,3,4,5</v>
- </type>
+ <type variable="Node"/>
+ <type variable="Fun" name_i="1"/>
+ <type variable="Module"/>
+ <type variable="Function"/>
+ <type variable="Args"/>
+ <type variable="SpawnOpts"/>
<desc>
<p>Spawns a new process and initializes it as described above.
The process is spawned using the
@@ -124,20 +136,13 @@
</desc>
</func>
<func>
- <name>start(Module, Function, Args) -> Ret</name>
- <name>start(Module, Function, Args, Time) -> Ret</name>
- <name>start(Module, Function, Args, Time, SpawnOpts) -> Ret</name>
- <name>start_link(Module, Function, Args) -> Ret</name>
- <name>start_link(Module, Function, Args, Time) -> Ret</name>
- <name>start_link(Module, Function, Args, Time, SpawnOpts) -> Ret</name>
+ <name name="start" arity="3"/>
+ <name name="start" arity="4"/>
+ <name name="start" arity="5"/>
+ <name name="start_link" arity="3"/>
+ <name name="start_link" arity="4"/>
+ <name name="start_link" arity="5"/>
<fsummary>Start a new process synchronously.</fsummary>
- <type>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- <v>Time = int() >= 0 | infinity</v>
- <v>SpawnOpts -- see erlang:spawn_opt/2,3,4,5</v>
- <v>Ret = term() | {error, Reason}</v>
- </type>
<desc>
<p>Starts a new process synchronously. Spawns the process and
waits for it to start. When the process has started, it
@@ -148,13 +153,13 @@
function. At this time, <c>Ret</c> is returned.</p>
<p>If the <c>start_link/3,4,5</c> function is used and
the process crashes before it has called <c>init_ack/1,2</c>,
- <c>{error, Reason}</c> is returned if the calling process
+ <c>{error, <anno>Reason</anno>}</c> is returned if the calling process
traps exits.</p>
- <p>If <c>Time</c> is specified as an integer, this function
- waits for <c>Time</c> milliseconds for the new process to call
+ <p>If <c><anno>Time</anno></c> is specified as an integer, this function
+ waits for <c><anno>Time</anno></c> milliseconds for the new process to call
<c>init_ack</c>, or <c>{error, timeout}</c> is returned, and
the process is killed.</p>
- <p>The <c>SpawnOpts</c> argument, if given, will be passed
+ <p>The <c><anno>SpawnOpts</anno></c> argument, if given, will be passed
as the last argument to the <c>spawn_opt/2,3,4,5</c> BIF.</p>
<note>
<p>Using the spawn option <c>monitor</c> is currently not
@@ -164,17 +169,13 @@
</desc>
</func>
<func>
- <name>init_ack(Parent, Ret) -> void()</name>
- <name>init_ack(Ret) -> void()</name>
+ <name name="init_ack" arity="1"/>
+ <name name="init_ack" arity="2"/>
<fsummary>Used by a process when it has started.</fsummary>
- <type>
- <v>Parent = pid()</v>
- <v>Ret = term()</v>
- </type>
<desc>
<p>This function must used by a process that has been started by
a <seealso marker="#start/3">start[_link]/3,4,5</seealso>
- function. It tells <c>Parent</c> that the process has
+ function. It tells <c><anno>Parent</anno></c> that the process has
initialized itself, has started, or has failed to initialize
itself.</p>
<p>The <c>init_ack/1</c> function uses the parent value
@@ -205,40 +206,30 @@ init(Parent) ->
</desc>
</func>
<func>
- <name>format(CrashReport) -> string()</name>
+ <name name="format" arity="1"/>
<fsummary>Format a crash report.</fsummary>
- <type>
- <v>CrashReport = term()</v>
- </type>
<desc>
<p>This function can be used by a user defined event handler to
format a crash report. The crash report is sent using
- <c>error_logger:error_report(crash_report, CrashReport)</c>.
+ <c>error_logger:error_report(crash_report, <anno>CrashReport</anno>)</c>.
That is, the event to be handled is of the format
- <c>{error_report, GL, {Pid, crash_report, CrashReport}}</c>
+ <c>{error_report, GL, {Pid, crash_report, <anno>CrashReport</anno>}}</c>
where <c>GL</c> is the group leader pid of the process
<c>Pid</c> which sent the crash report.</p>
</desc>
</func>
<func>
- <name>initial_call(Process) -> {Module,Function,Args} | false</name>
+ <name name="initial_call" arity="1"/>
<fsummary>Extract the initial call of a <c>proc_lib</c>spawned process.</fsummary>
- <type>
- <v>Process = pid() | {X,Y,Z} | ProcInfo</v>
- <v>&nbsp;X = Y = Z = int()</v>
- <v>&nbsp;ProcInfo = term()</v>
- <v>Module = Function = atom()</v>
- <v>Args = [atom()]</v>
- </type>
<desc>
<p>Extracts the initial call of a process that was started
using one of the spawn or start functions described above.
- <c>Process</c> can either be a pid, an integer tuple (from
+ <c><anno>Process</anno></c> can either be a pid, an integer tuple (from
which a pid can be created), or the process information of a
process <c>Pid</c> fetched through an
<c>erlang:process_info(Pid)</c> function call.</p>
- <note><p>The list <c>Args</c> no longer contains the actual arguments,
+ <note><p>The list <c><anno>Args</anno></c> no longer contains the actual arguments,
but the same number of atoms as the number of arguments; the first atom
is always <c>'Argument__1'</c>, the second <c>'Argument__2'</c>, and
so on. The reason is that the argument list could waste a significant
@@ -256,23 +247,15 @@ init(Parent) ->
</desc>
</func>
<func>
- <name>translate_initial_call(Process) -> {Module,Function,Arity} | Fun</name>
+ <name name="translate_initial_call" arity="1"/>
<fsummary>Extract and translate the initial call of a <c>proc_lib</c>spawned process.</fsummary>
- <type>
- <v>Process = pid() | {X,Y,Z} | ProcInfo</v>
- <v>&nbsp;X = Y = Z = int()</v>
- <v>&nbsp;ProcInfo = term()</v>
- <v>Module = Function = atom()</v>
- <v>Arity = int()</v>
- <v>Fun = fun() -> void()</v>
- </type>
<desc>
<p>This function is used by the <c>c:i/0</c> and
<c>c:regs/0</c> functions in order to present process
information.</p>
<p>Extracts the initial call of a process that was started
using one of the spawn or start functions described above,
- and translates it to more useful information. <c>Process</c>
+ and translates it to more useful information. <c><anno>Process</anno></c>
can either be a pid, an integer tuple (from which a pid can
be created), or the process information of a process
<c>Pid</c> fetched through an <c>erlang:process_info(Pid)</c>
@@ -280,15 +263,15 @@ init(Parent) ->
<p>If the initial call is to one of the system defined behaviors
such as <c>gen_server</c> or <c>gen_event</c>, it is
translated to more useful information. If a <c>gen_server</c>
- is spawned, the returned <c>Module</c> is the name of
- the callback module and <c>Function</c> is <c>init</c>
+ is spawned, the returned <c><anno>Module</anno></c> is the name of
+ the callback module and <c><anno>Function</anno></c> is <c>init</c>
(the function that initiates the new server).</p>
<p>A <c>supervisor</c> and a <c>supervisor_bridge</c> are also
<c>gen_server</c> processes. In order to return information
that this process is a supervisor and the name of the
- call-back module, <c>Module</c> is <c>supervisor</c> and
- <c>Function</c> is the name of the supervisor callback
- module. <c>Arity</c> is <c>1</c> since the <c>init/1</c>
+ call-back module, <c><anno>Module</anno></c> is <c>supervisor</c> and
+ <c><anno>Function</anno></c> is the name of the supervisor callback
+ module. <c><anno>Arity</anno></c> is <c>1</c> since the <c>init/1</c>
function is called initially in the callback module.</p>
<p>By default, <c>{proc_lib,init_p,5}</c> is returned if no
information about the initial call can be found. It is
@@ -297,12 +280,8 @@ init(Parent) ->
</desc>
</func>
<func>
- <name>hibernate(Module, Function, Args)</name>
+ <name name="hibernate" arity="3"/>
<fsummary>Hibernate a process until a message is sent to it</fsummary>
- <type>
- <v>Module = Function = atom()</v>
- <v>Args = [term()]</v>
- </type>
<desc>
<p>This function does the same as (and does call) the BIF
<seealso marker="erts:erlang#erlang:hibernate/3">hibernate/3</seealso>,
diff --git a/lib/stdlib/doc/src/proplists.xml b/lib/stdlib/doc/src/proplists.xml
index 9f1c5b24ad..225c5e97eb 100644
--- a/lib/stdlib/doc/src/proplists.xml
+++ b/lib/stdlib/doc/src/proplists.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2002</year><year>2010</year>
+ <year>2002</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -48,14 +48,15 @@
words, numbers are compared literally rather than by value, so that,
for instance, <c>1</c> and <c>1.0</c> are different keys.</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="property"/>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>append_values(Key, List) -> List</name>
+ <name name="append_values" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Key = term()</v>
- <v>List = [term()]</v>
- </type>
<desc>
<p>Similar to <c>get_all_values/2</c>, but each value is
wrapped in a list unless it is already itself a list, and the
@@ -65,11 +66,8 @@
</desc>
</func>
<func>
- <name>compact(List) -> List</name>
+ <name name="compact" arity="1"/>
<fsummary></fsummary>
- <type>
- <v>List = [term()]</v>
- </type>
<desc>
<p>Minimizes the representation of all entries in the list. This is
equivalent to <c><![CDATA[[property(P) || P <- List]]]></c>.</p>
@@ -77,33 +75,24 @@
</desc>
</func>
<func>
- <name>delete(Key, List) -> List</name>
+ <name name="delete" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Key = term()</v>
- <v>List = [term()]</v>
- </type>
<desc>
- <p>Deletes all entries associated with <c>Key</c> from
- <c>List</c>.</p>
+ <p>Deletes all entries associated with <c><anno>Key</anno></c> from
+ <c><anno>List</anno></c>.</p>
</desc>
</func>
<func>
- <name>expand(Expansions, List) -> List</name>
+ <name name="expand" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Key = term()</v>
- <v>Expansions = [{Property,[term()]}]</v>
- <v>Property = atom() | tuple()</v>
- </type>
<desc>
<p>Expands particular properties to corresponding sets of
- properties (or other terms). For each pair <c>{Property, Expansion}</c> in <c>Expansions</c>, if <c>E</c> is
- the first entry in <c>List</c> with the same key as
- <c>Property</c>, and <c>E</c> and <c>Property</c>
+ properties (or other terms). For each pair <c>{<anno>Property</anno>, <anno>Expansion</anno>}</c> in <c><anno>Expansions</anno></c>, if <c>E</c> is
+ the first entry in <c><anno>List</anno></c> with the same key as
+ <c><anno>Property</anno></c>, and <c>E</c> and <c><anno>Property</anno></c>
have equivalent normal forms, then <c>E</c> is replaced with
- the terms in <c>Expansion</c>, and any following entries with
- the same key are deleted from <c>List</c>.</p>
+ the terms in <c><anno>Expansion</anno></c>, and any following entries with
+ the same key are deleted from <c><anno>List</anno></c>.</p>
<p>For example, the following expressions all return <c>[fie, bar, baz, fum]</c>:</p>
<code type="none">
expand([{foo, [bar, baz]}],
@@ -120,103 +109,75 @@
<p>Note that if the original property term is to be preserved in the
result when expanded, it must be included in the expansion list. The
inserted terms are not expanded recursively. If
- <c>Expansions</c> contains more than one property with the same
+ <c><anno>Expansions</anno></c> contains more than one property with the same
key, only the first occurrence is used.</p>
<p>See also: <c>normalize/2</c>.</p>
</desc>
</func>
<func>
- <name>get_all_values(Key, List) -> [term()]</name>
+ <name name="get_all_values" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Key = term()</v>
- <v>List = [term()]</v>
- </type>
<desc>
<p>Similar to <c>get_value/2</c>, but returns the list of
values for <em>all</em> entries <c>{Key, Value}</c> in
- <c>List</c>. If no such entry exists, the result is the empty
+ <c><anno>List</anno></c>. If no such entry exists, the result is the empty
list.</p>
<p>See also: <c>get_value/2</c>.</p>
</desc>
</func>
<func>
- <name>get_bool(Key, List) -> bool()</name>
+ <name name="get_bool" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Key = term()</v>
- <v>List = [term()]</v>
- </type>
<desc>
<p>Returns the value of a boolean key/value option. If
- <c>lookup(Key, List)</c> would yield <c>{Key, true}</c>,
+ <c>lookup(<anno>Key</anno>, <anno>List</anno>)</c> would yield <c>{<anno>Key</anno>, true}</c>,
this function returns <c>true</c>; otherwise <c>false</c>
is returned.</p>
<p>See also: <c>get_value/2</c>, <c>lookup/2</c>.</p>
</desc>
</func>
<func>
- <name>get_keys(List) -> [term()]</name>
+ <name name="get_keys" arity="1"/>
<fsummary></fsummary>
- <type>
- <v>List = [term()]</v>
- </type>
<desc>
- <p>Returns an unordered list of the keys used in <c>List</c>,
+ <p>Returns an unordered list of the keys used in <c><anno>List</anno></c>,
not containing duplicates.</p>
</desc>
</func>
<func>
- <name>get_value(Key, List) -> term()</name>
+ <name name="get_value" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Key = term()</v>
- <v>List = [term()]</v>
- </type>
<desc>
- <p>Equivalent to <c>get_value(Key, List, undefined)</c>.</p>
+ <p>Equivalent to <c>get_value(<anno>Key</anno>, <anno>List</anno>, undefined)</c>.</p>
</desc>
</func>
<func>
- <name>get_value(Key, List, Default) -> term()</name>
+ <name name="get_value" arity="3"/>
<fsummary></fsummary>
- <type>
- <v>Key = term()</v>
- <v>Default = term()</v>
- <v>List = [term()]</v>
- </type>
<desc>
<p>Returns the value of a simple key/value property in
- <c>List</c>. If <c>lookup(Key, List)</c> would yield
- <c>{Key, Value}</c>, this function returns the corresponding
- <c>Value</c>, otherwise <c>Default</c> is returned.</p>
+ <c><anno>List</anno></c>. If <c>lookup(<anno>Key</anno>, <anno>List</anno>)</c> would yield
+ <c>{<anno>Key</anno>, Value}</c>, this function returns the corresponding
+ <c>Value</c>, otherwise <c><anno>Default</anno></c> is returned.</p>
<p>See also: <c>get_all_values/2</c>, <c>get_bool/2</c>,
<c>get_value/2</c>, <c>lookup/2</c>.</p>
</desc>
</func>
<func>
- <name>is_defined(Key, List) -> bool()</name>
+ <name name="is_defined" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Key = term()</v>
- <v>List = [term()]</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>List</c> contains at least
- one entry associated with <c>Key</c>, otherwise
+ <p>Returns <c>true</c> if <c><anno>List</anno></c> contains at least
+ one entry associated with <c><anno>Key</anno></c>, otherwise
<c>false</c> is returned.</p>
</desc>
</func>
<func>
- <name>lookup(Key, List) -> none | tuple()</name>
+ <name name="lookup" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Key = term()</v>
- <v>List = [term()]</v>
- </type>
<desc>
- <p>Returns the first entry associated with <c>Key</c> in
- <c>List</c>, if one exists, otherwise returns
+ <p>Returns the first entry associated with <c><anno>Key</anno></c> in
+ <c><anno>List</anno></c>, if one exists, otherwise returns
<c>none</c>. For an atom <c>A</c> in the list, the tuple
<c>{A, true}</c> is the entry associated with <c>A</c>.</p>
<p>See also: <c>get_bool/2</c>, <c>get_value/2</c>,
@@ -224,34 +185,20 @@
</desc>
</func>
<func>
- <name>lookup_all(Key, List) -> [tuple()]</name>
+ <name name="lookup_all" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Key = term()</v>
- <v>List = [term()]</v>
- </type>
<desc>
- <p>Returns the list of all entries associated with <c>Key</c>
- in <c>List</c>. If no such entry exists, the result is the
+ <p>Returns the list of all entries associated with <c><anno>Key</anno></c>
+ in <c><anno>List</anno></c>. If no such entry exists, the result is the
empty list.</p>
<p>See also: <c>lookup/2</c>.</p>
</desc>
</func>
<func>
- <name>normalize(List, Stages) -> List</name>
+ <name name="normalize" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>List = [term()]</v>
- <v>Stages = [Operation]</v>
- <v>Operation = {aliases, Aliases} | {negations, Negations} | {expand, Expansions}</v>
- <v>Aliases = [{Key, Key}]</v>
- <v>Negations = [{Key, Key}]</v>
- <v>Key = term()</v>
- <v>Expansions = [{Property, [term()]}]</v>
- <v>Property = atom() | tuple()</v>
- </type>
<desc>
- <p>Passes <c>List</c> through a sequence of
+ <p>Passes <c><anno>List</anno></c> through a sequence of
substitution/expansion stages. For an <c>aliases</c> operation,
the function <c>substitute_aliases/2</c> is applied using the
given list of aliases; for a <c>negations</c> operation,
@@ -270,51 +217,37 @@
</desc>
</func>
<func>
- <name>property(Property) -> Property</name>
+ <name name="property" arity="1"/>
<fsummary></fsummary>
- <type>
- <v>Property = atom() | tuple()</v>
- </type>
<desc>
<p>Creates a normal form (minimal) representation of a property. If
- <c>Property</c> is <c>{Key, true}</c> where <c>Key</c> is
+ <c><anno>Property</anno></c> is <c>{Key, true}</c> where <c>Key</c> is
an atom, this returns <c>Key</c>, otherwise the whole term
- <c>Property</c> is returned.</p>
+ <c><anno>Property</anno></c> is returned.</p>
<p>See also: <c>property/2</c>.</p>
</desc>
</func>
<func>
- <name>property(Key, Value) -> Property</name>
+ <name name="property" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Key = term()</v>
- <v>Value = term()</v>
- <v>Property = atom() | tuple()</v>
- </type>
<desc>
<p>Creates a normal form (minimal) representation of a simple
- key/value property. Returns <c>Key</c> if <c>Value</c> is
- <c>true</c> and <c>Key</c> is an atom, otherwise a tuple
- <c>{Key, Value}</c> is returned.</p>
+ key/value property. Returns <c><anno>Key</anno></c> if <c><anno>Value</anno></c> is
+ <c>true</c> and <c><anno>Key</anno></c> is an atom, otherwise a tuple
+ <c>{<anno>Key</anno>, <anno>Value</anno>}</c> is returned.</p>
<p>See also: <c>property/1</c>.</p>
</desc>
</func>
<func>
- <name>split(List, Keys) -> {Lists, Rest}</name>
+ <name name="split" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>List = [term()]</v>
- <v>Keys = [term()]</v>
- <v>Lists = [[term()]]</v>
- <v>Rest = [term()]</v>
- </type>
<desc>
- <p>Partitions <c>List</c> into a list of sublists and a
- remainder. <c>Lists</c> contains one sublist for each key in
- <c>Keys</c>, in the corresponding order. The relative order of
+ <p>Partitions <c><anno>List</anno></c> into a list of sublists and a
+ remainder. <c><anno>Lists</anno></c> contains one sublist for each key in
+ <c><anno>Keys</anno></c>, in the corresponding order. The relative order of
the elements in each sublist is preserved from the original
- <c>List</c>. <c>Rest</c> contains the elements in
- <c>List</c> that are not associated with any of the given keys,
+ <c><anno>List</anno></c>. <c><anno>Rest</anno></c> contains the elements in
+ <c><anno>List</anno></c> that are not associated with any of the given keys,
also with their original relative order preserved.</p>
<p>Example:
split([{c, 2}, {e, 1}, a, {c, 3, 4}, d, {b, 5}, b], [a, b, c])</p>
@@ -323,19 +256,14 @@
</desc>
</func>
<func>
- <name>substitute_aliases(Aliases, List) -> List</name>
+ <name name="substitute_aliases" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Aliases = [{Key, Key}]</v>
- <v>Key = term()</v>
- <v>List = [term()]</v>
- </type>
<desc>
<p>Substitutes keys of properties. For each entry in
- <c>List</c>, if it is associated with some key <c>K1</c>
- such that <c>{K1, K2}</c> occurs in <c>Aliases</c>, the
- key of the entry is changed to <c>Key2</c>. If the same
- <c>K1</c> occurs more than once in <c>Aliases</c>, only
+ <c><anno>List</anno></c>, if it is associated with some key <c>K1</c>
+ such that <c>{K1, K2}</c> occurs in <c><anno>Aliases</anno></c>, the
+ key of the entry is changed to <c>K2</c>. If the same
+ <c>K1</c> occurs more than once in <c><anno>Aliases</anno></c>, only
the first occurrence is used.</p>
<p>Example: <c>substitute_aliases([{color, colour}], L)</c>
will replace all tuples <c>{color, ...}</c> in <c>L</c>
@@ -345,24 +273,19 @@
</desc>
</func>
<func>
- <name>substitute_negations(Negations, List) -> List</name>
+ <name name="substitute_negations" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Negations = [{Key, Key}]</v>
- <v>Key = term()</v>
- <v>List = [term()]</v>
- </type>
<desc>
<p>Substitutes keys of boolean-valued properties and
simultaneously negates their values. For each entry in
- <c>List</c>, if it is associated with some key <c>K1</c>
- such that <c>{K1, K2}</c> occurs in <c>Negations</c>, then
+ <c><anno>List</anno></c>, if it is associated with some key <c>K1</c>
+ such that <c>{K1, K2}</c> occurs in <c><anno>Negations</anno></c>, then
if the entry was <c>{K1, true}</c> it will be replaced with
<c>{K2, false}</c>, otherwise it will be replaced with
<c>{K2, true}</c>, thus changing the name of the option and
simultaneously negating the value given by
<c>get_bool(List)</c>. If the same <c>K1</c> occurs more
- than once in <c>Negations</c>, only the first occurrence is
+ than once in <c><anno>Negations</anno></c>, only the first occurrence is
used.</p>
<p>Example: <c>substitute_negations([{no_foo, foo}], L)</c>
will replace any atom <c>no_foo</c> or tuple
@@ -374,13 +297,10 @@
</desc>
</func>
<func>
- <name>unfold(List) -> List</name>
+ <name name="unfold" arity="1"/>
<fsummary></fsummary>
- <type>
- <v>List = [term()]</v>
- </type>
<desc>
- <p>Unfolds all occurrences of atoms in <c>List</c> to tuples
+ <p>Unfolds all occurrences of atoms in <c><anno>List</anno></c> to tuples
<c>{Atom, true}</c>.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/qlc.xml b/lib/stdlib/doc/src/qlc.xml
index da24ee9914..ce50631ca9 100644
--- a/lib/stdlib/doc/src/qlc.xml
+++ b/lib/stdlib/doc/src/qlc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2009</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -45,7 +45,9 @@
tables</em>. Typical QLC tables are ETS, Dets, and Mnesia
tables. There is also support for user defined tables, see the
<seealso marker="#implementing_a_qlc_table">Implementing a QLC
- table</seealso> section. A <em>query</em> is stated using
+ table</seealso> section. <marker
+ id="query_list_comprehension"></marker>
+ A <em>query</em> is stated using
<em>Query List Comprehensions</em> (QLCs). The answers to a
query are determined by data in QLC tables that fulfill the
constraints expressed by the QLCs of the query. QLCs are similar
@@ -55,10 +57,11 @@
fact, in the absence of optimizations and options such as
<c>cache</c> and <c>unique</c> (see below), every QLC free of
QLC tables evaluates to the same list of answers as the
- identical ordinary list comprehension. </p>
+ identical ordinary list comprehension.</p>
<p>While ordinary list comprehensions evaluate to lists, calling
- <seealso marker="#q">qlc:q/1,2</seealso> returns a <em>Query
+ <seealso marker="#q">qlc:q/1,2</seealso> returns a <marker
+ id="query_handle"></marker><em> Query
Handle</em>. To obtain all the answers to a query, <seealso
marker="#eval">qlc:eval/1,2</seealso> should be called with the
query handle as first argument. Query handles are essentially
@@ -69,7 +72,8 @@
Code replacement is described in the <seealso
marker="doc/reference_manual:code_loading">Erlang Reference
Manual</seealso>. The list of answers can also be traversed in
- chunks by use of a <em>Query Cursor</em>. Query cursors are
+ chunks by use of a <marker
+ id="query_cursor"></marker><em>Query Cursor</em>. Query cursors are
created by calling <seealso
marker="#cursor">qlc:cursor/1,2</seealso> with a query handle as
first argument. Query cursors are essentially Erlang processes.
@@ -226,75 +230,6 @@
</section>
- <section><title>Common data types</title>
-
- <list type="bulleted">
- <item><p><c>QueryCursor = {qlc_cursor, term()}</c></p>
- </item>
- <item><p><c>QueryHandle = {qlc_handle, term()}</c></p>
- </item>
- <item><p><c>QueryHandleOrList = QueryHandle | list()</c></p>
- </item>
- <item><p><c>Answers = [Answer]</c></p>
- </item>
- <item><p><c>Answer = term()</c></p>
- </item>
- <item><p><c>AbstractExpression =&nbsp;</c> -&nbsp;parse trees
- for Erlang expressions, see the <seealso
- marker="erts:absform">abstract format</seealso>
- documentation in the ERTS User's Guide&nbsp;-</p>
- </item>
- <item><p><c>MatchExpression =&nbsp;</c>
- -&nbsp;match&nbsp;specifications, see the <seealso
- marker="erts:match_spec">match specification</seealso>
- documentation in the ERTS User's Guide and <seealso
- marker="ms_transform">ms_transform(3)</seealso>&nbsp;-</p>
- </item>
- <item><p><c>SpawnOptions = default | spawn_options()</c></p>
- </item>
- <item><p><c>SortOptions = [SortOption] | SortOption</c></p>
- </item>
- <item><p><c>SortOption = {compressed, bool()}
- | {no_files, NoFiles}
- | {order, Order}
- | {size, Size}
- | {tmpdir, TempDirectory}
- | {unique, bool()}&nbsp;</c>
- -&nbsp;see <seealso
- marker="file_sorter">file_sorter(3)</seealso>&nbsp;-</p>
- </item>
- <item><p><c>Order = ascending | descending | OrderFun</c></p>
- </item>
- <item><p><c>OrderFun = fun(term(), term()) -> bool()</c></p>
- </item>
- <item><p><c>TempDirectory = "" | filename()</c></p>
- </item>
- <item><p><c>Size = int() > 0</c></p>
- </item>
- <item><p><c>NoFiles = int() > 1</c></p>
- </item>
- <item><p><c>KeyPos = int() > 0 | [int() > 0]</c></p>
- </item>
- <item><p><c>MaxListSize = int() >= 0</c></p>
- </item>
- <item><p><c>bool() = true | false</c></p>
- </item>
- <item><p><c>Cache = ets | list | no</c></p>
- </item>
- <item><p><c>TmpFileUsage = allowed | not_allowed | info_msg
- | warning_msg | error_msg</c></p>
- </item>
- <item><p><c>filename() =&nbsp;</c> -&nbsp;see <seealso
- marker="filename">filename(3)</seealso>&nbsp;-</p>
- </item>
- <item><p><c>spawn_options() =&nbsp;</c> -&nbsp;see <seealso
- marker="erts:erlang">erlang(3)</seealso>&nbsp;-</p>
- </item>
-
- </list>
-
- </section>
-
<section><title>Getting started</title>
<p><marker id="getting_started"></marker> As already mentioned
@@ -679,34 +614,104 @@ ets:match_spec_run(ets:lookup(86033, {2,2}),
</section>
+ <datatypes>
+ <datatype>
+ <name name="abstract_expr"></name>
+ <desc><p>Parse trees for Erlang expression, see the <seealso
+ marker="erts:absform">abstract format</seealso>
+ documentation in the ERTS User's Guide.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="answer"></name>
+ </datatype>
+ <datatype>
+ <name name="answers"></name>
+ </datatype>
+ <datatype>
+ <name name="cache"></name>
+ </datatype>
+ <datatype>
+ <name name="match_expression"></name>
+ <desc><p>Match&nbsp;specification, see the <seealso
+ marker="erts:match_spec">match specification</seealso>
+ documentation in the ERTS User's Guide and <seealso
+ marker="ms_transform">ms_transform(3).</seealso></p></desc>
+ </datatype>
+ <datatype>
+ <name name="no_files"></name>
+ <desc><p>Actually an integer > 1.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="key_pos"></name>
+ </datatype>
+ <datatype>
+ <name name="max_list_size"></name>
+ </datatype>
+ <datatype>
+ <name name="order"></name>
+ </datatype>
+ <datatype>
+ <name name="order_fun"></name>
+ </datatype>
+ <datatype>
+ <name name="query_cursor"></name>
+ <desc><p>A <seealso marker="#query_cursor">query cursor</seealso>.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="query_handle"></name>
+ <desc><p>A <seealso marker="#query_handle">query handle</seealso>.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="query_handle_or_list"></name>
+ </datatype>
+ <datatype>
+ <name name="query_list_comprehension"></name>
+ <desc><p>A literal
+ <seealso marker="#query_list_comprehension">query
+ list comprehension</seealso>.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="spawn_options"></name>
+ </datatype>
+ <datatype>
+ <name name="sort_options"></name>
+ </datatype>
+ <datatype>
+ <name name="sort_option"></name>
+ <desc><p>See <seealso
+ marker="file_sorter">file_sorter(3)</seealso>.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="tmp_directory"></name>
+ </datatype>
+ <datatype>
+ <name name="tmp_file_usage"></name>
+ </datatype>
+ </datatypes>
+
<funcs>
<func>
- <name>append(QHL) -> QH</name>
+ <name name="append" arity="1"/>
<fsummary>Return a query handle.</fsummary>
- <type>
- <v>QHL = [QueryHandleOrList]</v>
- <v>QH = QueryHandle</v>
- </type>
<desc>
<p>Returns a query handle. When evaluating the query handle
- <c>QH</c> all answers to the first query handle in
- <c>QHL</c> is returned followed by all answers to the rest
- of the query handles in <c>QHL</c>.</p>
+ <c><anno>QH</anno></c> all answers to the first query handle in
+ <c><anno>QHL</anno></c> are returned followed by all answers
+ to the rest of the query handles in <c><anno>QHL</anno></c>.</p>
</desc>
</func>
<func>
- <name>append(QH1, QH2) -> QH3</name>
+ <name name="append" arity="2"/>
<fsummary>Return a query handle.</fsummary>
- <type>
- <v>QH1 = QH2 = QueryHandleOrList</v>
- <v>QH3 = QueryHandle</v>
- </type>
<desc>
<p>Returns a query handle. When evaluating the query handle
- <c>QH3</c> all answers to <c>QH1</c> are returned followed
- by all answers to <c>QH2</c>.</p>
+ <c><anno>QH3</anno></c> all answers to
+ <c><anno>QH1</anno></c> are returned followed by all answers
+ to <c><anno>QH2</anno></c>.</p>
<p><c>append(QH1,&nbsp;QH2)</c> is equivalent to
<c>append([QH1,&nbsp;QH2])</c>.</p>
@@ -714,17 +719,9 @@ ets:match_spec_run(ets:lookup(86033, {2,2}),
</func>
<func>
- <name>cursor(QueryHandleOrList [, Options]) -> QueryCursor</name>
+ <name name="cursor" arity="1"/>
+ <name name="cursor" arity="2"/>
<fsummary>Create a query cursor.</fsummary>
- <type>
- <v>Options = [Option] | Option</v>
- <v>Option = {cache_all, Cache} | cache_all
- | {max_list_size, MaxListSize}
- | {spawn_options, SpawnOptions}
- | {tmpdir_usage, TmpFileUsage}
- | {tmpdir, TempDirectory}
- | {unique_all, bool()} | unique_all</v>
- </type>
<desc>
<p><marker id="cursor"></marker>Creates a query cursor and
makes the calling process the owner of the cursor. The
@@ -746,11 +743,13 @@ ets:match_spec_run(ets:lookup(86033, {2,2}),
[{b,1},{b,2}]
4> <input>qlc:delete_cursor(QC).</input>
ok</pre>
+ <p><c>cursor(<anno>QH</anno>)</c> is equivalent to
+ <c>cursor(<anno>QH</anno>, [])</c>.</p>
</desc>
</func>
<func>
- <name>delete_cursor(QueryCursor) -> ok</name>
+ <name name="delete_cursor" arity="1"/>
<fsummary>Delete a query cursor.</fsummary>
<desc>
<p>Deletes a query cursor. Only the owner of the cursor can
@@ -759,19 +758,11 @@ ok</pre>
</func>
<func>
- <name>eval(QueryHandleOrList [, Options]) -> Answers | Error</name>
- <name>e(QueryHandleOrList [, Options]) -> Answers</name>
+ <name name="eval" arity="1"/>
+ <name name="eval" arity="2"/>
+ <name name="e" arity="1"/>
+ <name name="e" arity="2"/>
<fsummary>Return all answers to a query.</fsummary>
- <type>
- <v>Options = [Option] | Option</v>
- <v>Option = {cache_all, Cache} | cache_all
- | {max_list_size, MaxListSize}
- | {tmpdir_usage, TmpFileUsage}
- | {tmpdir, TempDirectory}
- | {unique_all, bool()} | unique_all</v>
- <v>Error = {error, module(), Reason}</v>
- <v>Reason =&nbsp;-&nbsp;as returned by file_sorter(3)&nbsp;-</v>
- </type>
<desc>
<p><marker id="eval"></marker>Evaluates a query handle in the
calling process and collects all answers in a list.</p>
@@ -780,47 +771,39 @@ ok</pre>
1> <input>QH = qlc:q([{X,Y} || X &lt;- [a,b], Y &lt;- [1,2]]),</input>
<input>qlc:eval(QH).</input>
[{a,1},{a,2},{b,1},{b,2}]</pre>
+ <p><c>eval(<anno>QH</anno>)</c> is equivalent to
+ <c>eval(<anno>QH</anno>, [])</c>.</p>
</desc>
</func>
<func>
- <name>fold(Function, Acc0, QueryHandleOrList [, Options]) ->
- Acc1 | Error</name>
+ <name name="fold" arity="3"/>
+ <name name="fold" arity="4"/>
<fsummary>Fold a function over the answers to a query.</fsummary>
- <type>
- <v>Function = fun(Answer, AccIn) -> AccOut</v>
- <v>Acc0 = Acc1 = AccIn = AccOut = term()</v>
- <v>Options = [Option] | Option</v>
- <v>Option = {cache_all, Cache} | cache_all
- | {max_list_size, MaxListSize}
- | {tmpdir_usage, TmpFileUsage}
- | {tmpdir, TempDirectory}
- | {unique_all, bool()} | unique_all</v>
- <v>Error = {error, module(), Reason}</v>
- <v>Reason =&nbsp;-&nbsp;as returned by file_sorter(3)&nbsp;-</v>
- </type>
<desc>
- <p>Calls <c>Function</c> on successive answers to the query
- handle together with an extra argument <c>AccIn</c>. The
- query handle and the function are evaluated in the calling
- process. <c>Function</c> must return a new accumulator which
- is passed to the next call. <c>Acc0</c> is returned if there
- are no answers to the query handle.</p>
+ <p>Calls <c><anno>Function</anno></c> on successive answers to
+ the query handle together with an extra argument
+ <c><anno>AccIn</anno></c>. The query handle and the function
+ are evaluated in the calling process.
+ <c><anno>Function</anno></c> must return a new accumulator
+ which is passed to the next call.
+ <c><anno>Acc0</anno></c> is returned if there are no answers
+ to the query handle.</p>
<pre>
1> <input>QH = [1,2,3,4,5,6],</input>
<input>qlc:fold(fun(X, Sum) -> X + Sum end, 0, QH).</input>
21</pre>
+ <p><c>fold(<anno>Function</anno>, <anno>Acc0</anno>,
+ <anno>QH</anno>)</c> is equivalent to
+ <c>fold(<anno>Function</anno>, <anno>Acc0</anno>,
+ <anno>QH</anno>, [])</c>.</p>
</desc>
</func>
<func>
- <name>format_error(Error) -> Chars</name>
+ <name name="format_error" arity="1"/>
<fsummary>Return an English description of a an error tuple.</fsummary>
- <type>
- <v>Error = {error, module(), term()}</v>
- <v>Chars = [char() | Chars]</v>
- </type>
<desc>
<p>Returns a descriptive string in English of an error tuple
returned by some of the functions of the <c>qlc</c> module
@@ -830,25 +813,9 @@ ok</pre>
</func>
<func>
- <name>info(QueryHandleOrList [, Options]) -> Info</name>
+ <name name="info" arity="1"/>
+ <name name="info" arity="2"/>
<fsummary>Return code describing a query handle.</fsummary>
- <type>
- <v>Options = [Option] | Option</v>
- <v>Option = EvalOption | ReturnOption</v>
- <v>EvalOption = {cache_all, Cache} | cache_all
- | {max_list_size, MaxListSize}
- | {tmpdir_usage, TmpFileUsage}
- | {tmpdir, TempDirectory}
- | {unique_all, bool()} | unique_all</v>
- <v>ReturnOption = {depth, Depth}
- | {flat, bool()}
- | {format, Format}
- | {n_elements, NElements}</v>
- <v>Depth = infinity | int() >= 0</v>
- <v>Format = abstract_code | string</v>
- <v>NElements = infinity | int() > 0</v>
- <v>Info = AbstractExpression | string()</v>
- </type>
<desc>
<p><marker id="info"></marker>Returns information about a
query handle. The information describes the simplifications
@@ -879,18 +846,18 @@ ok</pre>
<input>io:format("~s~n", [qlc:info(QH, unique_all)]).</input>
begin
V1 =
- qlc:q([
+ qlc:q([
SQV ||
SQV &lt;- [x,y]
],
[{unique,true}]),
V2 =
- qlc:q([
+ qlc:q([
SQV ||
SQV &lt;- [a,b]
],
[{unique,true}]),
- qlc:q([
+ qlc:q([
{X,Y} ||
X &lt;- V1,
Y &lt;- V2
@@ -913,19 +880,19 @@ end</pre>
<input>io:format("~s~n", [qlc:info(Q)]).</input>
begin
V1 =
- qlc:q([
+ qlc:q([
P0 ||
P0 = {W,Y} &lt;- ets:table(17)
]),
V2 =
- qlc:q([
+ qlc:q([
[G1|G2] ||
G2 &lt;- V1,
G1 &lt;- ets:table(16),
element(2, G1) =:= element(1, G2)
],
[{join,lookup}]),
- qlc:q([
+ qlc:q([
{X,Z,W} ||
[{X,Z}|{W,Y}] &lt;- V2
])
@@ -936,44 +903,43 @@ end</pre>
method chosen. A convention is used for lookup join: the
first generator (<c>G2</c>) is the one traversed, the second
one (<c>G1</c>) is the table where constants are looked up.</p>
+
+ <p><c>info(<anno>QH</anno>)</c> is equivalent to
+ <c>info(<anno>QH</anno>, [])</c>.</p>
</desc>
</func>
<func>
- <name>keysort(KeyPos, QH1 [, SortOptions]) -> QH2</name>
+ <name name="keysort" arity="2"/>
+ <name name="keysort" arity="3"/>
<fsummary>Return a query handle.</fsummary>
- <type>
- <v>QH1 = QueryHandleOrList</v>
- <v>QH2 = QueryHandle</v>
- </type>
<desc>
<p>Returns a query handle. When evaluating the query handle
- <c>QH2</c> the answers to the query handle <c>QH1</c> are
- sorted by <seealso
+ <c><anno>QH2</anno></c> the answers to the query handle
+ <c><anno>QH1</anno></c> are sorted by <seealso
marker="file_sorter">file_sorter:keysort/4</seealso>
according to the options.</p>
- <p>The sorter will use temporary files only if <c>QH1</c> does
- not evaluate to a list and the size of the binary
- representation of the answers exceeds <c>Size</c> bytes,
- where <c>Size</c> is the value of the <c>size</c> option.</p>
+ <p>The sorter will use temporary files only if
+ <c><anno>QH1</anno></c> does not evaluate to a list and the
+ size of the binary representation of the answers exceeds
+ <c>Size</c> bytes, where <c>Size</c> is the value of the
+ <c>size</c> option.</p>
+
+ <p><c>keysort(<anno>KeyPos</anno>, <anno>QH1</anno>)</c>
+ is equivalent to
+ <c>keysort(<anno>KeyPos</anno>, <anno>QH1</anno>, [])</c>.</p>
</desc>
</func>
<func>
- <name>next_answers(QueryCursor [, NumberOfAnswers]) ->
- Answers | Error</name>
+ <name name="next_answers" arity="1"/>
+ <name name="next_answers" arity="2"/>
<fsummary>Return some or all answers to a query.</fsummary>
- <type>
- <v>NumberOfAnswers = all_remaining | int() > 0</v>
- <v>Error = {error, module(), Reason}</v>
- <v>Reason =&nbsp;-&nbsp;as returned by file_sorter(3)&nbsp;-</v>
- </type>
<desc>
<p>Returns some or all of the remaining answers to a query
- cursor. Only the owner of <c>Cursor</c> can retrieve
- answers.</p>
-
+ cursor. Only the owner of <c><anno>QueryCursor</anno></c> can
+ retrieve answers.</p>
<p>The optional argument <c>NumberOfAnswers</c>determines the
maximum number of answers returned. The default value is
<c>10</c>. If less than the requested number of answers is
@@ -983,21 +949,9 @@ end</pre>
</func>
<func>
- <name>q(QueryListComprehension [, Options]) -> QueryHandle</name>
+ <name name="q" arity="1"/>
+ <name name="q" arity="2"/>
<fsummary>Return a handle for a query list comprehension.</fsummary>
- <type>
- <v>QueryListComprehension =&nbsp;
- -&nbsp;literal query listcomprehension&nbsp;-</v>
- <v>Options = [Option] | Option</v>
- <v>Option = {max_lookup, MaxLookup}
- | {cache, Cache} | cache
- | {join, Join}
- | {lookup, Lookup}
- | {unique, bool()} | unique</v>
- <v>MaxLookup = int() >= 0 | infinity</v>
- <v>Join = any | lookup | merge | nested_loop</v>
- <v>Lookup = bool() | any</v>
- </type>
<desc>
<p><marker id="q"></marker>Returns a query handle for a query
list comprehension. The query list comprehension must be the
@@ -1024,7 +978,7 @@ end</pre>
<pre>
...
-A = [X || {X} &lt;- [{1},{2}]],
+A = [X || {X} &lt;- [{1},{2}]],
QH = qlc:q(A),
...</pre>
@@ -1034,6 +988,9 @@ QH = qlc:q(A),
list comprehension"); the shell process stops with a
<c>badarg</c> reason.</p>
+ <p><c>q(<anno>QLC</anno>)</c> is equivalent to
+ <c>q(<anno>QLC</anno>, [])</c>.</p>
+
<p>The <c>{cache,&nbsp;ets}</c> option can be used to cache
the answers to a query list comprehension. The answers are
stored in one ETS table for each cached query list
@@ -1092,26 +1049,26 @@ QH = qlc:q(A),
<input>io:format("~s~n", [qlc:info(Q)]).</input>
begin
V1 =
- qlc:q([
+ qlc:q([
P0 ||
P0 = {X,Z} &lt;-
qlc:keysort(1, [{a,1},{b,4},{c,6}], [])
]),
V2 =
- qlc:q([
+ qlc:q([
P0 ||
P0 = {W,Y} &lt;-
qlc:keysort(2, [{2,a},{3,b},{4,c}], [])
]),
V3 =
- qlc:q([
+ qlc:q([
[G1|G2] ||
G1 &lt;- V1,
G2 &lt;- V2,
element(1, G1) == element(2, G2)
],
[{join,merge},{cache,list}]),
- qlc:q([
+ qlc:q([
{A,X,Z,W} ||
A &lt;- [a,b,c],
[{X,Z}|{W,Y}] &lt;- V3,
@@ -1170,7 +1127,7 @@ ets:match_spec_run(
elements of the key {X,&nbsp;Y} are compared separately.</p>
<p>The <c>{lookup,&nbsp;true}</c> option can be used to ensure
- that the <c>qlc</c> module will look up constants in some
+ that the <c>qlc</c> module will look up constants in some
QLC table. If there
are more than one QLC table among the generators' list
expressions, constants have to be looked up in at least one
@@ -1190,7 +1147,7 @@ ets:match_spec_run(
<c>{join,&nbsp;nested_loop}</c> invokes the method of
matching every pair of objects from two handles. The last
method is mostly very slow. The evaluation of the query
- fails if the <c>qlc</c> module cannot carry out the chosen
+ fails if the <c>qlc</c> module cannot carry out the chosen
join method. The
default value is <c>any</c> which means that some fast join
method will be used if possible.</p>
@@ -1198,47 +1155,33 @@ ets:match_spec_run(
</func>
<func>
- <name>sort(QH1 [, SortOptions]) -> QH2</name>
+ <name name="sort" arity="1"/>
+ <name name="sort" arity="2"/>
<fsummary>Return a query handle.</fsummary>
- <type>
- <v>QH1 = QueryHandleOrList</v>
- <v>QH2 = QueryHandle</v>
- </type>
<desc>
<p>Returns a query handle. When evaluating the query handle
- <c>QH2</c> the answers to the query handle <c>QH1</c> are
- sorted by <seealso
+ <c><anno>QH2</anno></c> the answers to the query handle
+ <c><anno>QH1</anno></c> are sorted by <seealso
marker="file_sorter">file_sorter:sort/3</seealso> according
to the options.</p>
- <p>The sorter will use temporary files only if <c>QH1</c> does
- not evaluate to a list and the size of the binary
- representation of the answers exceeds <c>Size</c> bytes,
- where <c>Size</c> is the value of the <c>size</c> option.</p>
+ <p>The sorter will use temporary files only if
+ <c><anno>QH1</anno></c> does not evaluate to a list and the
+ size of the binary representation of the answers exceeds
+ <c>Size</c> bytes, where <c>Size</c> is the value of the
+ <c>size</c> option.</p>
+
+ <p><c>sort(<anno>QH1</anno>)</c> is equivalent to
+ <c>sort(<anno>QH1</anno>, [])</c>.</p>
+
</desc>
</func>
<func>
- <name>string_to_handle(QueryString [, Options [, Bindings]]) ->
- QueryHandle | Error</name>
+ <name name="string_to_handle" arity="1"/>
+ <name name="string_to_handle" arity="2"/>
+ <name name="string_to_handle" arity="3"/>
<fsummary>Return a handle for a query list comprehension.</fsummary>
- <type>
- <v>QueryString = string()</v>
- <v>Options = [Option] | Option</v>
- <v>Option = {max_lookup, MaxLookup}
- | {cache, Cache} | cache
- | {join, Join}
- | {lookup, Lookup}
- | {unique, bool()} | unique</v>
- <v>MaxLookup = int() >= 0 | infinity</v>
- <v>Join = any | lookup | merge | nested_loop</v>
- <v>Lookup = bool() | any</v>
- <v>Bindings =&nbsp;-&nbsp;as returned by
- erl_eval:bindings/1&nbsp;-</v>
- <v>Error = {error, module(), Reason}</v>
- <v>Reason = &nbsp;-&nbsp;ErrorInfo as returned by
- erl_scan:string/1 or erl_parse:parse_exprs/1&nbsp;-</v>
- </type>
<desc>
<p>A string version of <c>qlc:q/1,2</c>. When the query handle
is evaluated the fun created by the parse transform is
@@ -1253,57 +1196,24 @@ ets:match_spec_run(
<input>qlc:eval(QH).</input>
[2,3,4]</pre>
+ <p><c>string_to_handle(<anno>QueryString</anno>)</c>
+ is equivalent to
+ <c>string_to_handle(<anno>QueryString</anno>, [])</c>.</p>
+
+ <p><c>string_to_handle(<anno>QueryString</anno>,
+ <anno>Options</anno>)</c>
+ is equivalent to
+ <c>string_to_handle(<anno>QueryString</anno>,
+ <anno>Options</anno>, erl_eval:new_bindings())</c>.</p>
+
<p>This function is probably useful mostly when called from
outside of Erlang, for instance from a driver written in C.</p>
</desc>
</func>
<func>
- <name>table(TraverseFun, Options) -> QueryHandle</name>
+ <name name="table" arity="2"/>
<fsummary>Return a query handle for a table.</fsummary>
- <type>
- <v>TraverseFun = TraverseFun0 | TraverseFun1</v>
- <v>TraverseFun0 = fun() -> TraverseResult</v>
- <v>TraverseFun1 = fun(MatchExpression) -> TraverseResult</v>
- <v>TraverseResult = Objects | term()</v>
- <v>Objects = [] | [term() | ObjectList]</v>
- <v>ObjectList = TraverseFun0 | Objects</v>
- <v>Options = [Option] | Option</v>
- <v>Option = {format_fun, FormatFun}
- | {info_fun, InfoFun}
- | {lookup_fun, LookupFun}
- | {parent_fun, ParentFun}
- | {post_fun, PostFun}
- | {pre_fun, PreFun}
- | {key_equality, KeyComparison}</v>
- <v>FormatFun = undefined | fun(SelectedObjects) -> FormatedTable</v>
- <v>SelectedObjects = all
- | {all, NElements, DepthFun}
- | {match_spec, MatchExpression}
- | {lookup, Position, Keys}
- | {lookup, Position, Keys, NElements, DepthFun}</v>
- <v>NElements = infinity | int() > 0</v>
- <v>DepthFun = fun(term()) -> term()</v>
- <v>FormatedTable = {Mod, Fun, Args}
- | AbstractExpression
- | character_list()</v>
- <v>InfoFun = undefined | fun(InfoTag) -> InfoValue</v>
- <v>InfoTag = indices | is_unique_objects | keypos | num_of_objects</v>
- <v>InfoValue = undefined | term()</v>
- <v>LookupFun = undefined | fun(Position, Keys) -> LookupResult</v>
- <v>LookupResult = [term()] | term()</v>
- <v>ParentFun = undefined | fun() -> ParentFunValue</v>
- <v>PostFun = undefined | fun() -> void()</v>
- <v>PreFun = undefined | fun([PreArg]) -> void()</v>
- <v>PreArg = {parent_value, ParentFunValue} | {stop_fun, StopFun}</v>
- <v>ParentFunValue = undefined | term()</v>
- <v>StopFun = undefined | fun() -> void()</v>
- <v>KeyComparison = '=:=' | '=='</v>
- <v>Position = int() > 0</v>
- <v>Keys = [term()]</v>
- <v>Mod = Fun = atom()</v>
- <v>Args = [term()]</v>
- </type>
<desc>
<p><marker id="table"></marker>Returns a query handle for a
QLC table. In Erlang/OTP there is support for ETS, Dets and
@@ -1315,77 +1225,90 @@ ets:match_spec_run(
as well as properties of the table are handled by callback
functions provided as options to <c>qlc:table/2</c>.</p>
- <p>The callback function <c>TraverseFun</c> is used for
- traversing the table. It is to return a list of objects
- terminated by either <c>[]</c> or a nullary fun to be used
- for traversing the not yet traversed objects of the table.
- Any other return value is immediately returned as value of
- the query evaluation. Unary <c>TraverseFun</c>s are to
- accept a match specification as argument. The match
- specification is created by the parse transform by analyzing
- the pattern of the generator calling <c>qlc:table/2</c> and
- filters using variables introduced in the pattern. If the
- parse transform cannot find a match specification equivalent
- to the pattern and filters, <c>TraverseFun</c> will be
- called with a match specification returning every object.
- Modules that can utilize match specifications for optimized
+ <p>The callback function <c><anno>TraverseFun</anno></c> is
+ used for traversing the table. It is to return a list of
+ objects terminated by either <c>[]</c> or a nullary fun to
+ be used for traversing the not yet traversed objects of the
+ table. Any other return value is immediately returned as
+ value of the query evaluation. Unary
+ <c><anno>TraverseFun</anno></c>s are to accept a match
+ specification as argument. The match specification is
+ created by the parse transform by analyzing the pattern of
+ the generator calling <c>qlc:table/2</c> and filters using
+ variables introduced in the pattern. If the parse transform
+ cannot find a match specification equivalent to the pattern
+ and filters, <c><anno>TraverseFun</anno></c> will be called
+ with a match specification returning every object. Modules
+ that can utilize match specifications for optimized
traversal of tables should call <c>qlc:table/2</c> with a
- unary <c>TraverseFun</c> while other modules can provide a
- nullary <c>TraverseFun</c>. <c>ets:table/2</c> is an example
- of the former; <c>gb_table:table/1</c> in the <seealso
- marker="#implementing_a_qlc_table">Implementing a QLC
- table</seealso> section is an example of the latter.</p>
-
- <p><c>PreFun</c> is a unary callback function that is called
- once before the table is read for the first time. If the
- call fails, the query evaluation fails. Similarly, the
- nullary callback function <c>PostFun</c> is called once
- after the table was last read. The return value, which is
- caught, is ignored. If <c>PreFun</c> has been called for a
- table, <c>PostFun</c> is guaranteed to be called for that
- table, even if the evaluation of the query fails for some
- reason. The order in which pre (post) functions for
+ unary
+ <c><anno>TraverseFun</anno></c> while other modules can
+ provide a nullary
+ <c><anno>TraverseFun</anno></c>. <c>ets:table/2</c> is an
+ example of the former; <c>gb_table:table/1</c> in the
+ <seealso marker="#implementing_a_qlc_table">Implementing a
+ QLC table</seealso> section is an example of the latter.</p>
+
+ <p><c><anno>PreFun</anno></c> is a unary callback function
+ that is called once before the table is read for the first
+ time. If the call fails, the query evaluation fails.
+ Similarly, the nullary callback function
+ <c><anno>PostFun</anno></c> is called once after the table
+ was last read. The return value, which is caught, is
+ ignored. If <c><anno>PreFun</anno></c> has been called for a
+ table,
+ <c><anno>PostFun</anno></c> is guaranteed to be called for
+ that table, even if the evaluation of the query fails for
+ some reason. The order in which pre (post) functions for
different tables are evaluated is not specified. Other table
- access than reading, such as calling <c>InfoFun</c>, is
- assumed to be OK at any time. The argument <c>PreArgs</c> is
- a list of tagged values. Currently there are two tags,
+ access than reading, such as calling
+ <c><anno>InfoFun</anno></c>, is assumed to be OK at any
+ time. The argument <c><anno>PreArgs</anno></c> is a list of
+ tagged values. Currently there are two tags,
<c>parent_value</c> and <c>stop_fun</c>, used by Mnesia for
managing transactions. The value of <c>parent_value</c> is
- the value returned by <c>ParentFun</c>, or <c>undefined</c>
- if there is no <c>ParentFun</c>. <c>ParentFun</c> is called
- once just before the call of <c>PreFun</c> in the context of
- the process calling <c>eval</c>, <c>fold</c>, or
+ the value returned by <c><anno>ParentFun</anno></c>, or
+ <c>undefined</c> if there is no <c>ParentFun</c>.
+ <c><anno>ParentFun</anno></c> is called once just before the
+ call of
+ <c><anno>PreFun</anno></c> in the context of the process
+ calling
+ <c>eval</c>, <c>fold</c>, or
<c>cursor</c>. The value of <c>stop_fun</c> is a nullary fun
that deletes the cursor if called from the parent, or
<c>undefined</c> if there is no cursor.</p>
<p><marker id="lookup_fun"></marker>The binary callback
- function <c>LookupFun</c> is used for looking up objects in
- the table. The first argument <c>Position</c> is the key
- position or an indexed position and the second argument
- <c>Keys</c> is a sorted list of unique values. The return
- value is to be a list of all objects (tuples) such that the
- element at <c>Position</c> is a member of <c>Keys</c>. Any
- other return value is immediately returned as value of the
- query evaluation. <c>LookupFun</c> is called instead of
+ function <c><anno>LookupFun</anno></c> is used for looking
+ up objects in the table. The first argument
+ <c><anno>Position</anno></c> is the key position or an
+ indexed position and the second argument
+ <c><anno>Keys</anno></c> is a sorted list of unique values.
+ The return value is to be a list of all objects (tuples)
+ such that the element at <c>Position</c> is a member of
+ <c><anno>Keys</anno></c>. Any other return value is
+ immediately returned as value of the query evaluation.
+ <c><anno>LookupFun</anno></c> is called instead of
traversing the table if the parse transform at compile time
can find out that the filters match and compare the element
- at <c>Position</c> in such a way that only <c>Keys</c> need
- to be looked up in order to find all potential answers. The
- key position is obtained by calling <c>InfoFun(keypos)</c>
- and the indexed positions by calling
- <c>InfoFun(indices)</c>. If the key position can be used for
- lookup it is always chosen, otherwise the indexed position
- requiring the least number of lookups is chosen. If there is
- a tie between two indexed positions the one occurring first
- in the list returned by <c>InfoFun</c> is chosen. Positions
- requiring more than <seealso
- marker="#max_lookup">max_lookup</seealso> lookups are
- ignored.</p>
-
- <p>The unary callback function <c>InfoFun</c> is to return
- information about the table. <c>undefined</c> should be
- returned if the value of some tag is unknown:</p>
+ at <c><anno>Position</anno></c> in such a way that only
+ <c><anno>Keys</anno></c> need to be looked up in order to
+ find all potential answers. The key position is obtained by
+ calling
+ <c><anno>InfoFun</anno>(keypos)</c> and the indexed
+ positions by calling
+ <c><anno>InfoFun</anno>(indices)</c>. If the key position
+ can be used for lookup it is always chosen, otherwise the
+ indexed position requiring the least number of lookups is
+ chosen. If there is a tie between two indexed positions the
+ one occurring first in the list returned by
+ <c><anno>InfoFun</anno></c> is chosen. Positions requiring
+ more than <seealso marker="#max_lookup">max_lookup</seealso>
+ lookups are ignored.</p>
+
+ <p>The unary callback function <c><anno>InfoFun</anno></c> is
+ to return information about the table. <c>undefined</c>
+ should be returned if the value of some tag is unknown:</p>
<list type="bulleted">
<item><c>indices</c>. Returns a list of indexed
@@ -1406,20 +1329,22 @@ ets:match_spec_run(
</item>
</list>
- <p>The unary callback function <c>FormatFun</c> is used by
- <seealso marker="#info">qlc:info/1,2</seealso> for
- displaying the call that created the table's query handle.
- The default value, <c>undefined</c>, means that
+ <p>The unary callback function <c><anno>FormatFun</anno></c>
+ is used by <seealso marker="#info">qlc:info/1,2</seealso>
+ for displaying the call that created the table's query
+ handle. The default value, <c>undefined</c>, means that
<c>info/1,2</c> displays a call to <c>'$MOD':'$FUN'/0</c>.
- It is up to <c>FormatFun</c> to present the selected objects
- of the table in a suitable way. However, if a character list
- is chosen for presentation it must be an Erlang expression
- that can be scanned and parsed (a trailing dot will be added
- by <c>qlc:info</c> though). <c>FormatFun</c> is called with
- an argument that describes the selected objects based on
- optimizations done as a result of analyzing the filters of
- the QLC where the call to <c>qlc:table/2</c> occurs. The
- possible values of the argument are:</p>
+ It is up to <c><anno>FormatFun</anno></c> to present the
+ selected objects of the table in a suitable way. However, if
+ a character list is chosen for presentation it must be an
+ Erlang expression that can be scanned and parsed (a trailing
+ dot will be added by <c>qlc:info</c> though).
+ <c><anno>FormatFun</anno></c> is called with an argument
+ that describes the selected objects based on optimizations
+ done as a result of analyzing the filters of the QLC where
+ the call to
+ <c>qlc:table/2</c> occurs. The possible values of the
+ argument are:</p>
<list type="bulleted">
<item><c>{lookup, Position, Keys, NElements, DepthFun}</c>.
@@ -1443,10 +1368,12 @@ ets:match_spec_run(
can be used for limiting the size of terms; calling
<c>DepthFun(Term)</c> substitutes <c>'...'</c> for parts of
<c>Term</c> below the depth specified by the <c>info/1,2</c>
- option <c>depth</c>. If calling <c>FormatFun</c> with an
- argument including <c>NElements</c> and <c>DepthFun</c>
- fails, <c>FormatFun</c> is called once again with an
- argument excluding <c>NElements</c> and <c>DepthFun</c>
+ option <c>depth</c>. If calling
+ <c><anno>FormatFun</anno></c> with an argument including
+ <c>NElements</c> and <c>DepthFun</c> fails,
+ <c><anno>FormatFun</anno></c> is called once again with an
+ argument excluding
+ <c>NElements</c> and <c>DepthFun</c>
(<c>{lookup,&nbsp;Position,&nbsp;Keys}</c> or
<c>all</c>).</p>
@@ -1458,7 +1385,7 @@ ets:match_spec_run(
<p>See <seealso marker="ets#qlc_table">ets(3)</seealso>,
<seealso marker="dets#qlc_table">dets(3)</seealso> and
- <seealso marker="mnesia:mnesia#qlc_table">mnesia(3)</seealso>
+ <seealso marker="mnesia:mnesia#qlc_table">mnesia(3)</seealso>
for the various options recognized by <c>table/1,2</c> in
respective module.</p>
</desc>
@@ -1472,12 +1399,12 @@ ets:match_spec_run(
<seealso marker="doc/reference_manual:users_guide">
Erlang Reference Manual</seealso>,
<seealso marker="erl_eval">erl_eval(3)</seealso>,
- <seealso marker="erts:erlang">erlang(3)</seealso>,
+ <seealso marker="erts:erlang">erlang(3)</seealso>,
<seealso marker="ets">ets(3)</seealso>,
- <seealso marker="kernel:file">file(3)</seealso>,
- <seealso marker="error_logger:file">error_logger(3)</seealso>,
+ <seealso marker="kernel:file">file(3)</seealso>,
+ <seealso marker="error_logger:file">error_logger(3)</seealso>,
<seealso marker="file_sorter">file_sorter(3)</seealso>,
- <seealso marker="mnesia:mnesia">mnesia(3)</seealso>,
+ <seealso marker="mnesia:mnesia">mnesia(3)</seealso>,
<seealso marker="doc/programming_examples:users_guide">
Programming Examples</seealso>,
<seealso marker="shell">shell(3)</seealso></p>
diff --git a/lib/stdlib/doc/src/queue.xml b/lib/stdlib/doc/src/queue.xml
index 5ada1c2c57..383f52d10d 100644
--- a/lib/stdlib/doc/src/queue.xml
+++ b/lib/stdlib/doc/src/queue.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -88,122 +88,94 @@
<title>Original API</title>
</section>
+ <datatypes>
+ <datatype>
+ <name><marker id="type-queue">queue()</marker></name>
+ <desc><p>As returned by <c>new/0</c>.</p></desc>
+ </datatype>
+ </datatypes>
+
<funcs>
<func>
- <name>new() -> Q</name>
+ <name name="new" arity="0"/>
<fsummary>Create an empty queue</fsummary>
- <type>
- <v>Q = queue()</v>
- </type>
<desc>
<p>Returns an empty queue.</p>
</desc>
</func>
<func>
- <name>is_queue(Term) -> true | false</name>
+ <name name="is_queue" arity="1"/>
<fsummary>Test if a term is a queue</fsummary>
- <type>
- <v>Term = term()</v>
- </type>
<desc>
- <p>Tests if <c>Q</c> is a queue and returns <c>true</c> if so and
+ <p>Tests if <c><anno>Term</anno></c> is a queue and returns <c>true</c> if so and
<c>false</c> otherwise.</p>
</desc>
</func>
<func>
- <name>is_empty(Q) -> true | false</name>
+ <name name="is_empty" arity="1"/>
<fsummary>Test if a queue is empty</fsummary>
- <type>
- <v>Q = queue()</v>
- </type>
<desc>
- <p>Tests if <c>Q</c> is empty and returns <c>true</c> if so and
+ <p>Tests if <c><anno>Q</anno></c> is empty and returns <c>true</c> if so and
<c>false</c> otherwise.</p>
</desc>
</func>
<func>
- <name>len(Q) -> N</name>
+ <name name="len" arity="1"/>
<fsummary>Get the length of a queue</fsummary>
- <type>
- <v>Q = queue()</v>
- <v>N = integer()</v>
- </type>
<desc>
- <p>Calculates and returns the length of queue <c>Q</c>.</p>
+ <p>Calculates and returns the length of queue <c><anno>Q</anno></c>.</p>
</desc>
</func>
<func>
- <name>in(Item, Q1) -> Q2</name>
+ <name name="in" arity="2"/>
<fsummary>Insert an item at the rear of a queue</fsummary>
- <type>
- <v>Item = term()</v>
- <v>Q1 = Q2 = queue()</v>
- </type>
<desc>
- <p>Inserts <c>Item</c> at the rear of queue <c>Q1</c>.
- Returns the resulting queue <c>Q2</c>.</p>
+ <p>Inserts <c><anno>Item</anno></c> at the rear of queue <c><anno>Q1</anno></c>.
+ Returns the resulting queue <c><anno>Q2</anno></c>.</p>
</desc>
</func>
<func>
- <name>in_r(Item, Q1) -> Q2</name>
+ <name name="in_r" arity="2"/>
<fsummary>Insert an item at the front of a queue</fsummary>
- <type>
- <v>Item = term()</v>
- <v>Q1 = Q2 = queue()</v>
- </type>
<desc>
- <p>Inserts <c>Item</c> at the front of queue <c>Q1</c>.
- Returns the resulting queue <c>Q2</c>.</p>
+ <p>Inserts <c><anno>Item</anno></c> at the front of queue <c><anno>Q1</anno></c>.
+ Returns the resulting queue <c><anno>Q2</anno></c>.</p>
</desc>
</func>
<func>
- <name>out(Q1) -> Result</name>
+ <name name="out" arity="1"/>
<fsummary>Remove the front item from a queue</fsummary>
- <type>
- <v>Result = {{value, Item}, Q2} | {empty, Q1}</v>
- <v>Q1 = Q2 = queue()</v>
- </type>
<desc>
- <p>Removes the item at the front of queue <c>Q1</c>. Returns the
- tuple <c>{{value, Item}, Q2}</c>, where <c>Item</c> is the
- item removed and <c>Q2</c> is the resulting queue. If <c>Q1</c> is
- empty, the tuple <c>{empty, Q1}</c> is returned.</p>
+ <p>Removes the item at the front of queue <c><anno>Q1</anno></c>. Returns the
+ tuple <c>{{value, <anno>Item</anno>}, <anno>Q2</anno>}</c>, where <c><anno>Item</anno></c> is the
+ item removed and <c><anno>Q2</anno></c> is the resulting queue. If <c><anno>Q1</anno></c> is
+ empty, the tuple <c>{empty, <anno>Q1</anno>}</c> is returned.</p>
</desc>
</func>
<func>
- <name>out_r(Q1) -> Result</name>
+ <name name="out_r" arity="1"/>
<fsummary>Remove the rear item from a queue</fsummary>
- <type>
- <v>Result = {{value, Item}, Q2} | {empty, Q1}</v>
- <v>Q1 = Q2 = queue()</v>
- </type>
<desc>
- <p>Removes the item at the rear of the queue <c>Q1</c>. Returns the
- tuple <c>{{value, Item}, Q2}</c>, where <c>Item</c> is the
- item removed and <c>Q2</c> is the new queue. If <c>Q1</c> is
- empty, the tuple <c>{empty, Q1}</c> is returned. </p>
+ <p>Removes the item at the rear of the queue <c><anno>Q1</anno></c>. Returns the
+ tuple <c>{{value, <anno>Item</anno>}, <anno>Q2</anno>}</c>, where <c><anno>Item</anno></c> is the
+ item removed and <c><anno>Q2</anno></c> is the new queue. If <c><anno>Q1</anno></c> is
+ empty, the tuple <c>{empty, <anno>Q1</anno>}</c> is returned. </p>
</desc>
</func>
<func>
- <name>from_list(L) -> queue()</name>
+ <name name="from_list" arity="1"/>
<fsummary>Convert a list to a queue</fsummary>
- <type>
- <v>L = list()</v>
- </type>
<desc>
- <p>Returns a queue containing the items in <c>L</c> in the
+ <p>Returns a queue containing the items in <c><anno>L</anno></c> in the
same order; the head item of the list will become the front
item of the queue.</p>
</desc>
</func>
<func>
- <name>to_list(Q) -> list()</name>
+ <name name="to_list" arity="1"/>
<fsummary>Convert a queue to a list</fsummary>
- <type>
- <v>Q = queue()</v>
- </type>
<desc>
<p>Returns a list of the items in the queue in the same order;
the front item of the queue will become the head of the list.</p>
@@ -211,57 +183,43 @@
</func>
<func>
- <name>reverse(Q1) -> Q2</name>
+ <name name="reverse" arity="1"/>
<fsummary>Reverse a queue</fsummary>
- <type>
- <v>Q1 = Q2 = queue()</v>
- </type>
<desc>
- <p>Returns a queue <c>Q2</c> that contains the items of
- <c>Q1</c> in the reverse order.</p>
+ <p>Returns a queue <c><anno>Q2</anno></c> that contains the items of
+ <c><anno>Q1</anno></c> in the reverse order.</p>
</desc>
</func>
<func>
- <name>split(N, Q1) -> {Q2,Q3}</name>
+ <name name="split" arity="2"/>
<fsummary>Split a queue in two</fsummary>
- <type>
- <v>N = integer()</v>
- <v>Q1 = Q2 = Q3 = queue()</v>
- </type>
<desc>
- <p>Splits <c>Q1</c> in two. The <c>N</c> front items
- are put in <c>Q2</c> and the rest in <c>Q3</c></p>
+ <p>Splits <c><anno>Q1</anno></c> in two. The <c><anno>N</anno></c> front items
+ are put in <c><anno>Q2</anno></c> and the rest in <c><anno>Q3</anno></c></p>
</desc>
</func>
<func>
- <name>join(Q1, Q2) -> Q3</name>
+ <name name="join" arity="2"/>
<fsummary>Join two queues</fsummary>
- <type>
- <v>Q1 = Q2 = Q3 = queue()</v>
- </type>
<desc>
- <p>Returns a queue <c>Q3</c> that is the result of joining
- <c>Q1</c> and <c>Q2</c> with <c>Q1</c> in front of
- <c>Q2</c>.</p>
+ <p>Returns a queue <c><anno>Q3</anno></c> that is the result of joining
+ <c><anno>Q1</anno></c> and <c><anno>Q2</anno></c> with <c><anno>Q1</anno></c> in front of
+ <c><anno>Q2</anno></c>.</p>
</desc>
</func>
<func>
- <name>filter(Fun, Q1) -> Q2</name>
+ <name name="filter" arity="2"/>
<fsummary>Filter a queue</fsummary>
- <type>
- <v>Fun = fun(Item) -> bool() | list()</v>
- <v>Q1 = Q2 = queue()</v>
- </type>
<desc>
- <p>Returns a queue <c>Q2</c> that is the result of calling
- <c>Fun(Item)</c> on all items in <c>Q1</c>,
+ <p>Returns a queue <c><anno>Q2</anno></c> that is the result of calling
+ <c><anno>Fun</anno>(<anno>Item</anno>)</c> on all items in <c><anno>Q1</anno></c>,
in order from front to rear.</p>
- <p>If <c>Fun(Item)</c> returns <c>true</c>, <c>Item</c>
+ <p>If <c><anno>Fun</anno>(<anno>Item</anno>)</c> returns <c>true</c>, <c>Item</c>
is copied to the result queue. If it returns <c>false</c>,
- <c>Item</c> is not copied. If it returns a list
+ <c><anno>Item</anno></c> is not copied. If it returns a list
the list elements are inserted instead of <c>Item</c> in the
result queue.</p>
- <p>So, <c>Fun(Item)</c> returning <c>[Item]</c> is thereby
+ <p>So, <c><anno>Fun</anno>(<anno>Item</anno>)</c> returning <c>[<anno>Item</anno>]</c> is thereby
semantically equivalent to returning <c>true</c>, just
as returning <c>[]</c> is semantically equivalent to
returning <c>false</c>. But returning a list builds
@@ -269,15 +227,11 @@
</desc>
</func>
<func>
- <name>member(Item, Q) -> bool()</name>
+ <name name="member" arity="2"/>
<fsummary>Test if an item is in a queue</fsummary>
- <type>
- <v>Item = term()</v>
- <v>Q = queue()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Item</c> matches some element
- in <c>Q</c>, otherwise <c>false</c>.</p>
+ <p>Returns <c>true</c> if <c><anno>Item</anno></c> matches some element
+ in <c><anno>Q</anno></c>, otherwise <c>false</c>.</p>
</desc>
</func>
</funcs>
@@ -290,77 +244,53 @@
<funcs>
<func>
- <name>get(Q) -> Item</name>
+ <name name="get" arity="1"/>
<fsummary>Return the front item of a queue</fsummary>
- <type>
- <v>Item = term()</v>
- <v>Q = queue()</v>
- </type>
<desc>
- <p>Returns <c>Item</c> at the front of queue <c>Q</c>.</p>
- <p>Fails with reason <c>empty</c> if <c>Q</c> is empty.</p>
+ <p>Returns <c><anno>Item</anno></c> at the front of queue <c><anno>Q</anno></c>.</p>
+ <p>Fails with reason <c>empty</c> if <c><anno>Q</anno></c> is empty.</p>
</desc>
</func>
<func>
- <name>get_r(Q) -> Item</name>
+ <name name="get_r" arity="1"/>
<fsummary>Return the rear item of a queue</fsummary>
- <type>
- <v>Item = term()</v>
- <v>Q = queue()</v>
- </type>
<desc>
- <p>Returns <c>Item</c> at the rear of queue <c>Q</c>.</p>
- <p>Fails with reason <c>empty</c> if <c>Q</c> is empty.</p>
+ <p>Returns <c><anno>Item</anno></c> at the rear of queue <c><anno>Q</anno></c>.</p>
+ <p>Fails with reason <c>empty</c> if <c><anno>Q</anno></c> is empty.</p>
</desc>
</func>
<func>
- <name>drop(Q1) -> Q2</name>
+ <name name="drop" arity="1"/>
<fsummary>Remove the front item from a queue</fsummary>
- <type>
- <v>Item = term()</v>
- <v>Q1 = Q2 = queue()</v>
- </type>
<desc>
- <p>Returns a queue <c>Q2</c> that is the result of removing
- the front item from <c>Q1</c>.</p>
- <p>Fails with reason <c>empty</c> if <c>Q1</c> is empty.</p>
+ <p>Returns a queue <c><anno>Q2</anno></c> that is the result of removing
+ the front item from <c><anno>Q1</anno></c>.</p>
+ <p>Fails with reason <c>empty</c> if <c><anno>Q1</anno></c> is empty.</p>
</desc>
</func>
<func>
- <name>drop_r(Q1) -> Q2</name>
+ <name name="drop_r" arity="1"/>
<fsummary>Remove the rear item from a queue</fsummary>
- <type>
- <v>Item = term()</v>
- <v>Q1 = Q2 = queue()</v>
- </type>
<desc>
- <p>Returns a queue <c>Q2</c> that is the result of removing
- the rear item from <c>Q1</c>.</p>
- <p>Fails with reason <c>empty</c> if <c>Q1</c> is empty.</p>
+ <p>Returns a queue <c><anno>Q2</anno></c> that is the result of removing
+ the rear item from <c><anno>Q1</anno></c>.</p>
+ <p>Fails with reason <c>empty</c> if <c><anno>Q1</anno></c> is empty.</p>
</desc>
</func>
<func>
- <name>peek(Q) -> {value,Item} | empty</name>
+ <name name="peek" arity="1"/>
<fsummary>Return the front item of a queue</fsummary>
- <type>
- <v>Item = term()</v>
- <v>Q = queue()</v>
- </type>
<desc>
- <p>Returns the tuple <c>{value, Item}</c> where <c>Item</c> is the
- front item of <c>Q</c>, or <c>empty</c> if <c>Q1</c> is empty.</p>
+ <p>Returns the tuple <c>{value, <anno>Item</anno>}</c> where <c><anno>Item</anno></c> is the
+ front item of <c><anno>Q</anno></c>, or <c>empty</c> if <c><anno>Q</anno></c> is empty.</p>
</desc>
</func>
<func>
- <name>peek_r(Q) -> {value,Item} | empty</name>
+ <name name="peek_r" arity="1"/>
<fsummary>Return the rear item of a queue</fsummary>
- <type>
- <v>Item = term()</v>
- <v>Q = queue()</v>
- </type>
<desc>
- <p>Returns the tuple <c>{value, Item}</c> where <c>Item</c> is the
- rear item of <c>Q</c>, or <c>empty</c> if <c>Q1</c> is empty.</p>
+ <p>Returns the tuple <c>{value, <anno>Item</anno>}</c> where <c><anno>Item</anno></c> is the
+ rear item of <c><anno>Q</anno></c>, or <c>empty</c> if <c><anno>Q</anno></c> is empty.</p>
</desc>
</func>
</funcs>
@@ -372,80 +302,56 @@
<funcs>
<func>
- <name>cons(Item, Q1) -> Q2</name>
+ <name name="cons" arity="2"/>
<fsummary>Insert an item at the head of a queue</fsummary>
- <type>
- <v>Item = term()</v>
- <v>Q1 = Q2 = queue()</v>
- </type>
<desc>
- <p>Inserts <c>Item</c> at the head of queue <c>Q1</c>. Returns
- the new queue <c>Q2</c>.</p>
+ <p>Inserts <c><anno>Item</anno></c> at the head of queue <c><anno>Q1</anno></c>. Returns
+ the new queue <c><anno>Q2</anno></c>.</p>
</desc>
</func>
<func>
- <name>head(Q) -> Item</name>
+ <name name="head" arity="1"/>
<fsummary>Return the item at the head of a queue</fsummary>
- <type>
- <v>Item = term()</v>
- <v>Q = queue()</v>
- </type>
<desc>
- <p>Returns <c>Item</c> from the head of queue <c>Q</c>.</p>
- <p>Fails with reason <c>empty</c> if <c>Q</c> is empty.</p>
+ <p>Returns <c><anno>Item</anno></c> from the head of queue <c><anno>Q</anno></c>.</p>
+ <p>Fails with reason <c>empty</c> if <c><anno>Q</anno></c> is empty.</p>
</desc>
</func>
<func>
- <name>tail(Q1) -> Q2</name>
+ <name name="tail" arity="1"/>
<fsummary>Remove the head item from a queue</fsummary>
- <type>
- <v>Item = term()</v>
- <v>Q1 = Q2 = queue()</v>
- </type>
<desc>
- <p>Returns a queue <c>Q2</c> that is the result of removing
- the head item from <c>Q1</c>.</p>
- <p>Fails with reason <c>empty</c> if <c>Q1</c> is empty.</p>
+ <p>Returns a queue <c><anno>Q2</anno></c> that is the result of removing
+ the head item from <c><anno>Q1</anno></c>.</p>
+ <p>Fails with reason <c>empty</c> if <c><anno>Q1</anno></c> is empty.</p>
</desc>
</func>
<func>
- <name>snoc(Q1, Item) -> Q2</name>
+ <name name="snoc" arity="2"/>
<fsummary>Insert an item at the tail of a queue</fsummary>
- <type>
- <v>Item = term()</v>
- <v>Q1 = Q2 = queue()</v>
- </type>
<desc>
- <p>Inserts <c>Item</c> as the tail item of queue <c>Q1</c>. Returns
- the new queue <c>Q2</c>.</p>
+ <p>Inserts <c><anno>Item</anno></c> as the tail item of queue <c><anno>Q1</anno></c>. Returns
+ the new queue <c><anno>Q2</anno></c>.</p>
</desc>
</func>
<func>
- <name>daeh(Q) -> Item</name>
- <name>last(Q) -> Item</name>
+ <name name="daeh" arity="1"/>
+ <name name="last" arity="1"/>
<fsummary>Return the tail item of a queue</fsummary>
- <type>
- <v>Item = term()</v>
- <v>Q = queue()</v>
- </type>
<desc>
- <p>Returns the tail item of queue <c>Q</c>.</p>
- <p>Fails with reason <c>empty</c> if <c>Q</c> is empty.</p>
+ <p>Returns the tail item of queue <c><anno>Q</anno></c>.</p>
+ <p>Fails with reason <c>empty</c> if <c><anno>Q</anno></c> is empty.</p>
</desc>
</func>
<func>
- <name>liat(Q1) -> Q2</name>
- <name>init(Q1) -> Q2</name>
- <name>lait(Q1) -> Q2</name>
+ <name name="liat" arity="1"/>
+ <name name="init" arity="1"/>
+ <name name="lait" arity="1"/>
<fsummary>Remove the tail item from a queue</fsummary>
- <type>
- <v>Item = term()</v>
- <v>Q1 = Q2 = queue()</v>
- </type>
<desc>
- <p>Returns a queue <c>Q2</c> that is the result of removing
- the tail item from <c>Q1</c>.</p>
- <p>Fails with reason <c>empty</c> if <c>Q1</c> is empty.</p>
+ <p>Returns a queue <c><anno>Q2</anno></c> that is the result of removing
+ the tail item from <c><anno>Q1</anno></c>.</p>
+ <p>Fails with reason <c>empty</c> if <c><anno>Q1</anno></c> is empty.</p>
<p>The name <c>lait/1</c> is a misspelling - do not use it anymore.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/random.xml b/lib/stdlib/doc/src/random.xml
index 26f22db48e..1b8fa44883 100644
--- a/lib/stdlib/doc/src/random.xml
+++ b/lib/stdlib/doc/src/random.xml
@@ -49,9 +49,15 @@
strong. If a strong cryptographic random number generator is needed for
example <c>crypto:rand_bytes/1</c> could be used instead.</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="ran"/>
+ <desc><p>The state.</p></desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>seed() -> ran()</name>
+ <name name="seed" arity="0"/>
<fsummary>Seeds random number generation with default values</fsummary>
<desc>
<p>Seeds random number generation with default (fixed) values
@@ -59,11 +65,8 @@
</desc>
</func>
<func>
- <name>seed(A1, A2, A3) -> undefined | ran()</name>
+ <name name="seed" arity="3"/>
<fsummary>Seeds random number generator</fsummary>
- <type>
- <v>A1 = A2 = A3 = integer()</v>
- </type>
<desc>
<p>Seeds random number generation with integer values in the process
dictionary, and returns the old state.</p>
@@ -76,26 +79,23 @@
</desc>
</func>
<func>
- <name>seed({A1, A2, A3}) -> undefined | ran()</name>
+ <name name="seed" arity="1"/>
<fsummary>Seeds random number generator</fsummary>
- <type>
- <v>A1 = A2 = A3 = integer()</v>
- </type>
<desc>
<p>
- <c>seed({A1, A2, A3})</c> is equivalent to <c>seed(A1, A2, A3)</c>.
+ <c>seed({<anno>A1</anno>, <anno>A2</anno>, <anno>A3</anno>})</c> is equivalent to <c>seed(<anno>A1</anno>, <anno>A2</anno>, <anno>A3</anno>)</c>.
</p>
</desc>
</func>
<func>
- <name>seed0() -> ran()</name>
+ <name name="seed0" arity="0"/>
<fsummary>Return default state for random number generation</fsummary>
<desc>
<p>Returns the default state.</p>
</desc>
</func>
<func>
- <name>uniform()-> float()</name>
+ <name name="uniform" arity="0"/>
<fsummary>Return a random float</fsummary>
<desc>
<p>Returns a random float uniformly distributed between <c>0.0</c>
@@ -103,39 +103,29 @@
</desc>
</func>
<func>
- <name>uniform(N) -> integer()</name>
+ <name name="uniform" arity="1"/>
<fsummary>Return a random integer</fsummary>
- <type>
- <v>N = integer()</v>
- </type>
<desc>
- <p>Given an integer <c>N >= 1</c>, <c>uniform/1</c> returns a
+ <p>Given an integer <c><anno>N</anno> >= 1</c>, <c>uniform/1</c> returns a
random integer uniformly distributed between <c>1</c> and
- <c>N</c>, updating the state in the process dictionary.</p>
+ <c><anno>N</anno></c>, updating the state in the process dictionary.</p>
</desc>
</func>
<func>
- <name>uniform_s(State0) -> {float(), State1}</name>
+ <name name="uniform_s" arity="1"/>
<fsummary>Return a random float</fsummary>
- <type>
- <v>State0 = State1 = ran()</v>
- </type>
<desc>
<p>Given a state, <c>uniform_s/1</c>returns a random float uniformly
distributed between <c>0.0</c> and <c>1.0</c>, and a new state.</p>
</desc>
</func>
<func>
- <name>uniform_s(N, State0) -> {integer(), State1}</name>
+ <name name="uniform_s" arity="2"/>
<fsummary>Return a random integer</fsummary>
- <type>
- <v>N = integer()</v>
- <v>State0 = State1 = ran()</v>
- </type>
<desc>
- <p>Given an integer <c>N >= 1</c> and a state, <c>uniform_s/2</c>
+ <p>Given an integer <c><anno>N</anno> >= 1</c> and a state, <c>uniform_s/2</c>
returns a random integer uniformly distributed between <c>1</c> and
- <c>N</c>, and a new state.</p>
+ <c><anno>N</anno></c>, and a new state.</p>
</desc>
</func>
</funcs>
diff --git a/lib/stdlib/doc/src/re.xml b/lib/stdlib/doc/src/re.xml
index 9091035392..18867cfb68 100644
--- a/lib/stdlib/doc/src/re.xml
+++ b/lib/stdlib/doc/src/re.xml
@@ -59,28 +59,24 @@
</description>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
- iodata() = iolist() | binary()
- iolist() = [char() | binary() | iolist()]
- - a binary is allowed as the tail of the list</code>
- <code type="none">
- unicode_binary() = binary() with characters encoded in UTF-8 coding standard
- unicode_char() = integer() representing a valid unicode codepoint
-
- chardata() = charlist() | unicode_binary()
-
- charlist() = [unicode_char() | unicode_binary() | charlist()]
- - a unicode_binary is allowed as the tail of the list</code>
-
- <code type="none">
- mp() = Opaque datatype containing a compiled regular expression.
- - The mp() is guaranteed to be a tuple() having the atom
+ <datatypes>
+ <datatype>
+ <name name="mp"/>
+ <desc>
+ <p>Opaque datatype containing a compiled regular expression.
+ The mp() is guaranteed to be a tuple() having the atom
're_pattern' as its first element, to allow for matching in
guards. The arity of the tuple() or the content of the other fields
- may change in future releases.</code>
- </section>
+ may change in future releases.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="nl_spec"/>
+ </datatype>
+ <datatype>
+ <name name="compile_option"/>
+ </datatype>
+ </datatypes>
<funcs>
<func>
<name>compile(Regexp) -> {ok, MP} | {error, ErrSpec}</name>
@@ -96,14 +92,14 @@
<name>compile(Regexp,Options) -> {ok, MP} | {error, ErrSpec}</name>
<fsummary>Compile a regular expression into a match program</fsummary>
<type>
- <v>Regexp = iodata() | charlist()</v>
+ <v>Regexp = iodata() | <seealso marker="unicode#type-charlist">io:charlist()</seealso></v>
<v>Options = [ Option ]</v>
- <v>Option = unicode | anchored | caseless | dollar_endonly | dotall | extended | firstline | multiline | no_auto_capture | dupnames | ungreedy | {newline, NLSpec}| bsr_anycrlf | bsr_unicode</v>
- <v>NLSpec = cr | crlf | lf | anycrlf | any </v>
- <v>MP = mp()</v>
+ <v>Option = <seealso marker="#type-compile_option">compile_option()</seealso></v>
+ <v>NLSpec = <seealso marker="#type-nl_spec">nl_spec()</seealso></v>
+ <v>MP = <seealso marker="#type-mp">mp()</seealso></v>
<v>ErrSpec = {ErrString, Position}</v>
<v>ErrString = string()</v>
- <v>Position = int()</v>
+ <v>Position = non_neg_integer()</v>
</type>
<desc>
<p>This function compiles a regular expression with the syntax
@@ -116,7 +112,7 @@
time one wants to match.</p>
<p>When the unicode option is given, the regular expression should be given as a valid unicode <c>charlist()</c>, otherwise as any valid <c>iodata()</c>.</p>
- <p>The options have the following meanings:</p>
+ <p><marker id="compile_options"/>The options have the following meanings:</p>
<taglist>
<tag><c>unicode</c></tag>
<item>The regular expression is given as a unicode <c>charlist()</c> and the resulting regular expression code is to be run against a valid unicode <c>charlist()</c> subject.</item>
@@ -137,7 +133,7 @@ This option makes it possible to include comments inside complicated patterns. N
<tag><c>multiline</c></tag>
<item><p>By default, PCRE treats the subject string as consisting of a single line of characters (even if it actually contains newlines). The "start of line" metacharacter (^) matches only at the start of the string, while the "end of line" metacharacter ($) matches only at the end of the string, or before a terminating newline (unless <c>dollar_endonly</c> is given). This is the same as Perl.</p>
-<p>When <c>multiline</c> it is given, the "start of line" and "end of line" constructs match immediately following or immediately before internal newlines in the subject string, respectively, as well as at the very start and end. This is equivalent to Perl's /m option, and it can be changed within a pattern by a (?m) option setting. If there are no newlines in a subject string, or no occurrences of ^ or $ in a pattern, setting <c>multiline</c> has no effect.</p> </item>
+<p>When <c>multiline</c> is given, the "start of line" and "end of line" constructs match immediately following or immediately before internal newlines in the subject string, respectively, as well as at the very start and end. This is equivalent to Perl's /m option, and it can be changed within a pattern by a (?m) option setting. If there are no newlines in a subject string, or no occurrences of ^ or $ in a pattern, setting <c>multiline</c> has no effect.</p> </item>
<tag><c>no_auto_capture</c></tag>
<item>Disables the use of numbered capturing parentheses in the pattern. Any opening parenthesis that is not followed by ? behaves as if it were followed by ?: but named parentheses can still be used for capturing (and they acquire numbers in the usual way). There is no equivalent of this option in Perl.
</item>
@@ -173,10 +169,10 @@ This option makes it possible to include comments inside complicated patterns. N
<name>run(Subject,RE) -> {match, Captured} | nomatch</name>
<fsummary>Match a subject against regular expression and capture subpatterns</fsummary>
<type>
- <v>Subject = iodata() | charlist()</v>
- <v>RE = mp() | iodata() | charlist()</v>
+ <v>Subject = iodata() | <seealso marker="unicode#type-charlist">io:charlist()</seealso></v>
+ <v>RE = <seealso marker="#type-mp">mp()</seealso> | iodata()</v>
<v>Captured = [ CaptureData ]</v>
- <v>CaptureData = {int(),int()}</v>
+ <v>CaptureData = {integer(),integer()}</v>
</type>
<desc>
<p>The same as <c>run(Subject,RE,[])</c>.</p>
@@ -186,18 +182,19 @@ This option makes it possible to include comments inside complicated patterns. N
<name>run(Subject,RE,Options) -> {match, Captured} | match | nomatch</name>
<fsummary>Match a subject against regular expression and capture subpatterns</fsummary>
<type>
- <v>Subject = iodata() | charlist()</v>
- <v>RE = mp() | iodata() | charlist()</v>
+ <v>Subject = iodata() | <seealso marker="unicode#type-charlist">io:charlist()</seealso></v>
+ <v>RE = <seealso marker="#type-mp">mp()</seealso> | iodata() | <seealso marker="unicode#type-charlist">io:charlist()</seealso></v>
<v>Options = [ Option ]</v>
- <v>Option = anchored | global | notbol | noteol | notempty | {offset, int()} | {newline, NLSpec} | bsr_anycrlf | bsr_unicode | {capture, ValueSpec} | {capture, ValueSpec, Type} | CompileOpt</v>
+ <v>Option = anchored | global | notbol | noteol | notempty | {offset, integer() >= 0} | {newline, NLSpec} | bsr_anycrlf | bsr_unicode | {capture, ValueSpec} | {capture, ValueSpec, Type} | CompileOpt</v>
<v>Type = index | list | binary</v>
<v>ValueSpec = all | all_but_first | first | none | ValueList</v>
<v>ValueList = [ ValueID ]</v>
- <v>ValueID = int() | string() | atom()</v>
- <v>CompileOpt = see compile/2 above</v>
- <v>NLSpec = cr | crlf | lf | anycrlf | any</v>
+ <v>ValueID = integer() | string() | atom()</v>
+ <v>CompileOpt = <seealso marker="#type-compile_option">compile_option()</seealso></v>
+ <d>See <seealso marker="#compile_options">compile/2</seealso> above.</d>
+ <v>NLSpec = <seealso marker="#type-nl_spec">nl_spec()</seealso></v>
<v>Captured = [ CaptureData ] | [ [ CaptureData ] ... ]</v>
- <v>CaptureData = {int(),int()} | ListConversionData | binary()</v>
+ <v>CaptureData = {integer(),integer()} | ListConversionData | binary()</v>
<v>ListConversionData = string() | {error, string(), binary()} | {incomplete, string(), binary()}</v>
</type>
<desc>
@@ -217,7 +214,7 @@ This option makes it possible to include comments inside complicated patterns. N
<p>If the regular expression is previously compiled, the option
list can only contain the options <c>anchored</c>,
<c>global</c>, <c>notbol</c>, <c>noteol</c>,
- <c>notempty</c>, <c>{offset, int()}</c>, <c>{newline,
+ <c>notempty</c>, <c>{offset, integer() >= 0}</c>, <c>{newline,
NLSpec}</c> and <c>{capture, ValueSpec}/{capture, ValueSpec,
Type}</c>. Otherwise all options valid for the
<c>re:compile/2</c> function are allowed as well. Options
@@ -360,7 +357,7 @@ This option makes it possible to include comments inside complicated patterns. N
behavior of the dollar metacharacter. It does not affect \Z or
\z.</item>
- <tag><c>{offset, int()}</c></tag>
+ <tag><c>{offset, integer() >= 0}</c></tag>
<item>Start matching at the offset (position) given in the
subject string. The offset is zero-based, so that the default is
@@ -503,42 +500,27 @@ This option makes it possible to include comments inside complicated patterns. N
</desc>
</func>
<func>
- <name>replace(Subject,RE,Replacement) -> iodata() | charlist()</name>
+ <name name="replace" arity="3"/>
<fsummary>Match a subject against regular expression and replace matching elements with Replacement</fsummary>
- <type>
- <v>Subject = iodata() | charlist()</v>
- <v>RE = mp() | iodata()</v>
- <v>Replacement = iodata() | charlist()</v>
- </type>
<desc>
- <p>The same as <c>replace(Subject,RE,Replacement,[])</c>.</p>
+ <p>The same as <c>replace(<anno>Subject</anno>,<anno>RE</anno>,<anno>Replacement</anno>,[])</c>.</p>
</desc>
</func>
<func>
- <name>replace(Subject,RE,Replacement,Options) -> iodata() | charlist() | binary() | list()</name>
+ <name name="replace" arity="4"/>
<fsummary>Match a subject against regular expression and replace matching elements with Replacement</fsummary>
- <type>
- <v>Subject = iodata() | charlist()</v>
- <v>RE = mp() | iodata() | charlist()</v>
- <v>Replacement = iodata() | charlist()</v>
- <v>Options = [ Option ]</v>
- <v>Option = anchored | global | notbol | noteol | notempty | {offset, int()} | {newline, NLSpec} | bsr_anycrlf | bsr_unicode | {return, ReturnType} | CompileOpt</v>
- <v>ReturnType = iodata | list | binary</v>
- <v>CompileOpt = see compile/2 above</v>
- <v>NLSpec = cr | crlf | lf | anycrlf | any </v>
- </type>
<desc>
- <p>Replaces the matched part of the <c>Subject</c> string with the contents of <c>Replacement</c>.</p>
+ <p>Replaces the matched part of the <c><anno>Subject</anno></c> string with the contents of <c><anno>Replacement</anno></c>.</p>
<p>The permissible options are the same as for <c>re:run/3</c>, except that the <c>capture</c> option is not allowed.
- Instead a <c>{return, ReturnType}</c> is present. The default return type is <c>iodata</c>, constructed in a
+ Instead a <c>{return, <anno>ReturnType</anno>}</c> is present. The default return type is <c>iodata</c>, constructed in a
way to minimize copying. The <c>iodata</c> result can be used directly in many i/o-operations. If a flat <c>list()</c> is
desired, specify <c>{return, list}</c> and if a binary is preferred, specify <c>{return, binary}</c>.</p>
<p>As in the <c>re:run/3</c> function, an <c>mp()</c> compiled
- with the <c>unicode</c> option requires the <c>Subject</c> to be
+ with the <c>unicode</c> option requires the <c><anno>Subject</anno></c> to be
a Unicode <c>charlist()</c>. If compilation is done implicitly
and the <c>unicode</c> compilation option is given to this
- function, both the regular expression and the <c>Subject</c>
+ function, both the regular expression and the <c><anno>Subject</anno></c>
should be given as valid Unicode <c>charlist()</c>s.</p>
<p>The replacement string can contain the special character
@@ -565,34 +547,17 @@ This option makes it possible to include comments inside complicated patterns. N
</desc>
</func>
<func>
- <name>split(Subject,RE) -> SplitList</name>
+ <name name="split" arity="2"/>
<fsummary>Split a string by tokens specified as a regular expression</fsummary>
- <type>
- <v>Subject = iodata() | charlist()</v>
- <v>RE = mp() | iodata()</v>
- <v>SplitList = [ iodata() | charlist() ]</v>
- </type>
<desc>
- <p>The same as <c>split(Subject,RE,[])</c>.</p>
+ <p>The same as <c>split(<anno>Subject</anno>,<anno>RE</anno>,[])</c>.</p>
</desc>
</func>
<func>
- <name>split(Subject,RE,Options) -> SplitList</name>
+ <name name="split" arity="3"/>
<fsummary>Split a string by tokens specified as a regular expression</fsummary>
- <type>
- <v>Subject = iodata() | charlist()</v>
- <v>RE = mp() | iodata() | charlist()</v>
- <v>Options = [ Option ]</v>
- <v>Option = anchored | global | notbol | noteol | notempty | {offset, int()} | {newline, NLSpec} | bsr_anycrlf | bsr_unicode | {return, ReturnType} | {parts, NumParts} | group | trim | CompileOpt</v>
- <v>NumParts = int() | infinity</v>
- <v>ReturnType = iodata | list | binary</v>
- <v>CompileOpt = see compile/2 above</v>
- <v>NLSpec = cr | crlf | lf | anycrlf | any </v>
- <v>SplitList = [ RetData ] | [ GroupedRetData ]</v>
- <v>GroupedRetData = [ RetData ]</v>
- <v>RetData = iodata() | charlist() | binary() | list()</v>
- </type>
+ <type_desc variable="CompileOpt">See <seealso marker="#compile_options">compile/2</seealso> above.</type_desc>
<desc>
<p>This function splits the input into parts by finding tokens
according to the regular expression supplied.</p>
@@ -602,10 +567,10 @@ This option makes it possible to include comments inside complicated patterns. N
of the string is removed from the output.</p>
<p>As in the <c>re:run/3</c> function, an <c>mp()</c> compiled
- with the <c>unicode</c> option requires the <c>Subject</c> to be
+ with the <c>unicode</c> option requires the <c><anno>Subject</anno></c> to be
a Unicode <c>charlist()</c>. If compilation is done implicitly
and the <c>unicode</c> compilation option is given to this
- function, both the regular expression and the <c>Subject</c>
+ function, both the regular expression and the <c><anno>Subject</anno></c>
should be given as valid Unicode <c>charlist()</c>s.</p>
<p>The result is given as a list of &quot;strings&quot;, the
@@ -722,7 +687,7 @@ This option makes it possible to include comments inside complicated patterns. N
<p>Summary of options not previously described for the <c>re:run/3</c> function:</p>
<taglist>
- <tag>{return,ReturnType}</tag>
+ <tag>{return,<anno>ReturnType</anno>}</tag>
<item><p>Specifies how the parts of the original string are presented in the result list. The possible types are:</p>
<taglist>
<tag>iodata</tag>
diff --git a/lib/stdlib/doc/src/regexp.xml b/lib/stdlib/doc/src/regexp.xml
index 8c4191c88f..35d8e1c3f8 100644
--- a/lib/stdlib/doc/src/regexp.xml
+++ b/lib/stdlib/doc/src/regexp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -40,176 +40,150 @@
<p>This module contains functions for regular expression
matching and substitution.</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="errordesc"></name>
+ </datatype>
+ <datatype>
+ <name name="regexp"></name>
+ <desc><p>Internal representation of a regular expression.</p></desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>match(String, RegExp) -> MatchRes</name>
+ <name name="match" arity="2"/>
<fsummary>Match a regular expression</fsummary>
- <type>
- <v>String = RegExp = string()</v>
- <v>MatchRes = {match,Start,Length} | nomatch | {error,errordesc()}</v>
- <v>Start = Length = integer()</v>
- </type>
<desc>
- <p>Finds the first, longest match of the regular expression <c>RegExp</c> in <c>String</c>. This function searches for the longest possible match and returns the first one found if there are several expressions of the same length. It returns as follows:</p>
+ <p>Finds the first, longest match of the regular expression <c><anno>RegExp</anno></c> in <c><anno>String</anno></c>. This function searches for the longest possible match and returns the first one found if there are several expressions of the same length. It returns as follows:</p>
<taglist>
- <tag><c>{match,Start,Length}</c></tag>
+ <tag><c>{match,<anno>Start</anno>,<anno>Length</anno>}</c></tag>
<item>
- <p>if the match succeeded. <c>Start</c> is the starting
- position of the match, and <c>Length</c> is the length of
+ <p>if the match succeeded. <c><anno>Start</anno></c> is the starting
+ position of the match, and <c><anno>Length</anno></c> is the length of
the matching string.</p>
</item>
<tag><c>nomatch</c></tag>
<item>
<p>if there were no matching characters.</p>
</item>
- <tag><c>{error,Error}</c></tag>
+ <tag><c>{error,<anno>Error</anno>}</c></tag>
<item>
- <p>if there was an error in <c>RegExp</c>.</p>
+ <p>if there was an error in <c><anno>RegExp</anno></c>.</p>
</item>
</taglist>
</desc>
</func>
<func>
- <name>first_match(String, RegExp) -> MatchRes</name>
+ <name name="first_match" arity="2"/>
<fsummary>Match a regular expression</fsummary>
- <type>
- <v>String = RegExp = string()</v>
- <v>MatchRes = {match,Start,Length} | nomatch | {error,errordesc()}</v>
- <v>Start = Length = integer()</v>
- </type>
<desc>
- <p>Finds the first match of the regular expression <c>RegExp</c> in <c>String</c>. This call is
+ <p>Finds the first match of the regular expression <c><anno>RegExp</anno></c> in <c><anno>String</anno></c>. This call is
usually faster than <c>match</c> and it is also a useful way to ascertain that a match exists. It returns as follows:</p>
<taglist>
- <tag><c>{match,Start,Length}</c></tag>
+ <tag><c>{match,<anno>Start</anno>,<anno>Length</anno>}</c></tag>
<item>
- <p>if the match succeeded. <c>Start</c> is the starting
- position of the match and <c>Length</c> is the length of
+ <p>if the match succeeded. <c><anno>Start</anno></c> is the starting
+ position of the match and <c><anno>Length</anno></c> is the length of
the matching string.</p>
</item>
<tag><c>nomatch</c></tag>
<item>
<p>if there were no matching characters.</p>
</item>
- <tag><c>{error,Error}</c></tag>
+ <tag><c>{error,<anno>Error</anno>}</c></tag>
<item>
- <p>if there was an error in <c>RegExp</c>.</p>
+ <p>if there was an error in <c><anno>RegExp</anno></c>.</p>
</item>
</taglist>
</desc>
</func>
<func>
- <name>matches(String, RegExp) -> MatchRes</name>
+ <name name="matches" arity="2"/>
<fsummary>Match a regular expression</fsummary>
- <type>
- <v>String = RegExp = string()</v>
- <v>MatchRes = {match, Matches} | {error, errordesc()}</v>
- <v>Matches = list()</v>
- </type>
<desc>
<p>Finds all non-overlapping matches of the
- expression <c>RegExp</c> in <c>String</c>.
+ expression <c><anno>RegExp</anno></c> in <c><anno>String</anno></c>.
It returns as follows:</p>
<taglist>
- <tag><c>{match, Matches}</c></tag>
+ <tag><c>{match, <anno>Matches</anno>}</c></tag>
<item>
<p>if the regular expression was correct.
- The list will be empty if there was no match. Each element in the list looks like <c>{Start, Length}</c>, where <c>Start</c> is the starting position of the match, and <c>Length</c> is the length of the matching string.</p>
+ The list will be empty if there was no match. Each element in the list looks like <c>{<anno>Start</anno>, <anno>Length</anno>}</c>, where <c><anno>Start</anno></c> is the starting position of the match, and <c><anno>Length</anno></c> is the length of the matching string.</p>
</item>
- <tag><c>{error,Error}</c></tag>
+ <tag><c>{error,<anno>Error</anno>}</c></tag>
<item>
- <p>if there was an error in <c>RegExp</c>.</p>
+ <p>if there was an error in <c><anno>RegExp</anno></c>.</p>
</item>
</taglist>
</desc>
</func>
<func>
- <name>sub(String, RegExp, New) -> SubRes</name>
+ <name name="sub" arity="3"/>
<fsummary>Substitute the first occurrence of a regular expression</fsummary>
- <type>
- <v>String = RegExp = New = string()</v>
- <v>SubRes = {ok,NewString,RepCount} | {error,errordesc()}</v>
- <v>RepCount = integer()</v>
- </type>
<desc>
- <p>Substitutes the first occurrence of a substring matching <c>RegExp</c> in <c>String</c> with the string <c>New</c>. A <c><![CDATA[&]]></c> in the string <c>New</c> is replaced by the matched substring of <c>String</c>. <c><![CDATA[\&]]></c> puts a literal <c><![CDATA[&]]></c> into the replacement string. It returns as follows:</p>
+ <p>Substitutes the first occurrence of a substring matching <c><anno>RegExp</anno></c> in <c><anno>String</anno></c> with the string <c><anno>New</anno></c>. A <c><![CDATA[&]]></c> in the string <c><anno>New</anno></c> is replaced by the matched substring of <c><anno>String</anno></c>. <c><![CDATA[\&]]></c> puts a literal <c><![CDATA[&]]></c> into the replacement string. It returns as follows:</p>
<taglist>
- <tag><c>{ok,NewString,RepCount}</c></tag>
+ <tag><c>{ok,<anno>NewString</anno>,<anno>RepCount</anno>}</c></tag>
<item>
- <p>if <c>RegExp</c> is correct. <c>RepCount</c> is the number of replacements which have been made
+ <p>if <c><anno>RegExp</anno></c> is correct. <c><anno>RepCount</anno></c> is the number of replacements which have been made
(this will be either 0 or 1).</p>
</item>
- <tag><c>{error, Error}</c></tag>
+ <tag><c>{error, <anno>Error</anno>}</c></tag>
<item>
- <p>if there is an error in <c>RegExp</c>.</p>
+ <p>if there is an error in <c><anno>RegExp</anno></c>.</p>
</item>
</taglist>
</desc>
</func>
<func>
- <name>gsub(String, RegExp, New) -> SubRes</name>
+ <name name="gsub" arity="3"/>
<fsummary>Substitute all occurrences of a regular expression</fsummary>
- <type>
- <v>String = RegExp = New = string()</v>
- <v>SubRes = {ok,NewString,RepCount} | {error,errordesc()}</v>
- <v>RepCount = integer()</v>
- </type>
<desc>
<p>The same as <c>sub</c>, except that all non-overlapping
occurrences of a substring matching
- <c>RegExp</c> in <c>String</c> are replaced by the string <c>New</c>. It returns:</p>
+ <c><anno>RegExp</anno></c> in <c><anno>String</anno></c> are replaced by the string <c><anno>New</anno></c>. It returns:</p>
<taglist>
- <tag><c>{ok,NewString,RepCount}</c></tag>
+ <tag><c>{ok,<anno>NewString</anno>,<anno>RepCount</anno>}</c></tag>
<item>
- <p>if <c>RegExp</c> is correct. <c>RepCount</c> is the number of replacements which have been made.</p>
+ <p>if <c><anno>RegExp</anno></c> is correct. <c><anno>RepCount</anno></c> is the number of replacements which have been made.</p>
</item>
- <tag><c>{error, Error}</c></tag>
+ <tag><c>{error, <anno>Error</anno>}</c></tag>
<item>
- <p>if there is an error in <c>RegExp</c>.</p>
+ <p>if there is an error in <c><anno>RegExp</anno></c>.</p>
</item>
</taglist>
</desc>
</func>
<func>
- <name>split(String, RegExp) -> SplitRes</name>
+ <name name="split" arity="2"/>
<fsummary>Split a string into fields</fsummary>
- <type>
- <v>String = RegExp = string()</v>
- <v>SubRes = {ok,FieldList} | {error,errordesc()}</v>
- <v>Fieldlist = [string()]</v>
- </type>
<desc>
- <p><c>String</c> is split into fields (sub-strings) by the
- regular expression <c>RegExp</c>.</p>
+ <p><c><anno>String</anno></c> is split into fields (sub-strings) by the
+ regular expression <c><anno>RegExp</anno></c>.</p>
<p>If the separator expression is <c>" "</c> (a single space),
then the fields are separated by blanks and/or tabs and
leading and trailing blanks and tabs are discarded. For all
other values of the separator, leading and trailing blanks
and tabs are not discarded. It returns:</p>
<taglist>
- <tag><c>{ok, FieldList}</c></tag>
+ <tag><c>{ok, <anno>FieldList</anno>}</c></tag>
<item>
<p>to indicate that the string has been split up into the fields of
- <c>FieldList</c>.</p>
+ <c><anno>FieldList</anno></c>.</p>
</item>
- <tag><c>{error, Error}</c></tag>
+ <tag><c>{error, <anno>Error</anno>}</c></tag>
<item>
- <p>if there is an error in <c>RegExp</c>.</p>
+ <p>if there is an error in <c><anno>RegExp</anno></c>.</p>
</item>
</taglist>
</desc>
</func>
<func>
- <name>sh_to_awk(ShRegExp) -> AwkRegExp</name>
+ <name name="sh_to_awk" arity="1"/>
<fsummary>Convert an <c>sh</c>regular expression into an <c>AWK</c>one</fsummary>
- <type>
- <v>ShRegExp AwkRegExp = string()</v>
- <v>SubRes = {ok,NewString,RepCount} | {error,errordesc()}</v>
- <v>RepCount = integer()</v>
- </type>
<desc>
<p>Converts the <c>sh</c> type regular expression
- <c>ShRegExp</c> into a full <c>AWK</c> regular
+ <c><anno>ShRegExp</anno></c> into a full <c>AWK</c> regular
expression. Returns the converted regular expression
string. <c>sh</c> expressions are used in the shell for
matching file names and have the following special
@@ -236,40 +210,32 @@
</desc>
</func>
<func>
- <name>parse(RegExp) -> ParseRes</name>
+ <name name="parse" arity="1"/>
<fsummary>Parse a regular expression</fsummary>
- <type>
- <v>RegExp = string()</v>
- <v>ParseRes = {ok,RE} | {error,errordesc()}</v>
- </type>
<desc>
- <p>Parses the regular expression <c>RegExp</c> and builds the
+ <p>Parses the regular expression <c><anno>RegExp</anno></c> and builds the
internal representation used in the other regular expression
functions. Such representations can be used in all of the
other functions instead of a regular expression string. This
is more efficient when the same regular expression is used
in many strings. It returns:</p>
<taglist>
- <tag><c>{ok, RE}</c>if <c>RegExp</c>is correct and <c>RE</c>is the internal representation.</tag>
+ <tag><c>{ok, <anno>RE</anno>}</c></tag>
<item>
- <p></p>
+ <p>if <c>RegExp</c> is correct and <c><anno>RE</anno></c> is the internal representation.</p>
</item>
- <tag><c>{error, Error}</c>if there is an error in <c>RegExpString</c>.</tag>
+ <tag><c>{error, <anno>Error</anno>}</c></tag>
<item>
- <p></p>
+ <p>if there is an error in <c><anno>RegExp</anno></c>.</p>
</item>
</taglist>
</desc>
</func>
<func>
- <name>format_error(ErrorDescriptor) -> Chars</name>
+ <name name="format_error" arity="1"/>
<fsummary>Format an error descriptor</fsummary>
- <type>
- <v>ErrorDescriptor = errordesc()</v>
- <v>Chars = [char() | Chars]</v>
- </type>
<desc>
- <p>Returns a string which describes the error <c>ErrorDescriptor</c>
+ <p>Returns a string which describes the error <c><anno>ErrorDescriptor</anno></c>
returned when there is an error in a regular expression.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/sets.xml b/lib/stdlib/doc/src/sets.xml
index 3610bb0184..071ee437cb 100644
--- a/lib/stdlib/doc/src/sets.xml
+++ b/lib/stdlib/doc/src/sets.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2009</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -43,202 +43,141 @@
different if and only if they do not compare equal (<c>==</c>).</p>
</description>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-set()
- as returned by new/0</code>
- </section>
+ <datatypes>
+ <datatype>
+ <name><marker id="type-dict">set()</marker></name>
+ <desc><p>As returned by <c>new/0</c>.</p></desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>new() -> Set</name>
+ <name name="new" arity="0"/>
<fsummary>Return an empty set</fsummary>
- <type>
- <v>Set = set()</v>
- </type>
<desc>
<p>Returns a new empty set.</p>
</desc>
</func>
<func>
- <name>is_set(Set) -> bool()</name>
+ <name name="is_set" arity="1"/>
<fsummary>Test for an <c>Set</c></fsummary>
- <type>
- <v>Set = term()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Set</c> is a set of
+ <p>Returns <c>true</c> if <c><anno>Set</anno></c> is a set of
elements, otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>size(Set) -> int()</name>
+ <name name="size" arity="1"/>
<fsummary>Return the number of elements in a set</fsummary>
- <type>
- <v>Set = term()</v>
- </type>
<desc>
- <p>Returns the number of elements in <c>Set</c>.</p>
+ <p>Returns the number of elements in <c><anno>Set</anno></c>.</p>
</desc>
</func>
<func>
- <name>to_list(Set) -> List</name>
+ <name name="to_list" arity="1"/>
<fsummary>Convert an <c>Set</c>into a list</fsummary>
- <type>
- <v>Set = set()</v>
- <v>List = [term()]</v>
- </type>
<desc>
- <p>Returns the elements of <c>Set</c> as a list.</p>
+ <p>Returns the elements of <c><anno>Set</anno></c> as a list.</p>
</desc>
</func>
<func>
- <name>from_list(List) -> Set</name>
+ <name name="from_list" arity="1"/>
<fsummary>Convert a list into an <c>Set</c></fsummary>
- <type>
- <v>List = [term()]</v>
- <v>Set = set()</v>
- </type>
<desc>
- <p>Returns an set of the elements in <c>List</c>.</p>
+ <p>Returns an set of the elements in <c><anno>List</anno></c>.</p>
</desc>
</func>
<func>
- <name>is_element(Element, Set) -> bool()</name>
+ <name name="is_element" arity="2"/>
<fsummary>Test for membership of an <c>Set</c></fsummary>
- <type>
- <v>Element = term()</v>
- <v>Set = set()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Element</c> is an element of
- <c>Set</c>, otherwise <c>false</c>.</p>
+ <p>Returns <c>true</c> if <c><anno>Element</anno></c> is an element of
+ <c><anno>Set</anno></c>, otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>add_element(Element, Set1) -> Set2</name>
+ <name name="add_element" arity="2"/>
<fsummary>Add an element to an <c>Set</c></fsummary>
- <type>
- <v>Element = term()</v>
- <v>Set1 = Set2 = set()</v>
- </type>
<desc>
- <p>Returns a new set formed from <c>Set1</c> with
- <c>Element</c> inserted.</p>
+ <p>Returns a new set formed from <c><anno>Set1</anno></c> with
+ <c><anno>Element</anno></c> inserted.</p>
</desc>
</func>
<func>
- <name>del_element(Element, Set1) -> Set2</name>
+ <name name="del_element" arity="2"/>
<fsummary>Remove an element from an <c>Set</c></fsummary>
- <type>
- <v>Element = term()</v>
- <v>Set1 = Set2 = set()</v>
- </type>
<desc>
- <p>Returns <c>Set1</c>, but with <c>Element</c> removed.</p>
+ <p>Returns <c><anno>Set1</anno></c>, but with <c><anno>Element</anno></c> removed.</p>
</desc>
</func>
<func>
- <name>union(Set1, Set2) -> Set3</name>
+ <name name="union" arity="2"/>
<fsummary>Return the union of two <c>Sets</c></fsummary>
- <type>
- <v>Set1 = Set2 = Set3 = set()</v>
- </type>
<desc>
- <p>Returns the merged (union) set of <c>Set1</c> and
- <c>Set2</c>.</p>
+ <p>Returns the merged (union) set of <c><anno>Set1</anno></c> and
+ <c><anno>Set2</anno></c>.</p>
</desc>
</func>
<func>
- <name>union(SetList) -> Set</name>
+ <name name="union" arity="1"/>
<fsummary>Return the union of a list of <c>Sets</c></fsummary>
- <type>
- <v>SetList = [set()]</v>
- <v>Set = set()</v>
- </type>
<desc>
<p>Returns the merged (union) set of the list of sets.</p>
</desc>
</func>
<func>
- <name>intersection(Set1, Set2) -> Set3</name>
+ <name name="intersection" arity="2"/>
<fsummary>Return the intersection of two <c>Sets</c></fsummary>
- <type>
- <v>Set1 = Set2 = Set3 = set()</v>
- </type>
<desc>
- <p>Returns the intersection of <c>Set1</c> and
- <c>Set2</c>.</p>
+ <p>Returns the intersection of <c><anno>Set1</anno></c> and
+ <c><anno>Set2</anno></c>.</p>
</desc>
</func>
<func>
- <name>intersection(SetList) -> Set</name>
+ <name name="intersection" arity="1"/>
<fsummary>Return the intersection of a list of <c>Sets</c></fsummary>
- <type>
- <v>SetList = [set()]</v>
- <v>Set = set()</v>
- </type>
<desc>
<p>Returns the intersection of the non-empty list of sets.</p>
</desc>
</func>
<func>
- <name>is_disjoint(Set1, Set2) -> bool()</name>
+ <name name="is_disjoint" arity="2"/>
<fsummary>Check whether two <c>Sets</c> are disjoint</fsummary>
- <type>
- <v>Set1 = Set2 = set()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if <c>Set1</c> and
- <c>Set2</c> are disjoint (have no elements in common),
+ <p>Returns <c>true</c> if <c><anno>Set1</anno></c> and
+ <c><anno>Set2</anno></c> are disjoint (have no elements in common),
and <c>false</c> otherwise.</p>
</desc>
</func>
<func>
- <name>subtract(Set1, Set2) -> Set3</name>
+ <name name="subtract" arity="2"/>
<fsummary>Return the difference of two <c>Sets</c></fsummary>
- <type>
- <v>Set1 = Set2 = Set3 = set()</v>
- </type>
<desc>
- <p>Returns only the elements of <c>Set1</c> which are not
- also elements of <c>Set2</c>.</p>
+ <p>Returns only the elements of <c><anno>Set1</anno></c> which are not
+ also elements of <c><anno>Set2</anno></c>.</p>
</desc>
</func>
<func>
- <name>is_subset(Set1, Set2) -> bool()</name>
+ <name name="is_subset" arity="2"/>
<fsummary>Test for subset</fsummary>
- <type>
- <v>Set1 = Set2 = set()</v>
- </type>
<desc>
- <p>Returns <c>true</c> when every element of <c>Set</c>1 is
- also a member of <c>Set2</c>, otherwise <c>false</c>.</p>
+ <p>Returns <c>true</c> when every element of <c><anno>Set1</anno></c>1 is
+ also a member of <c><anno>Set2</anno></c>, otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>fold(Function, Acc0, Set) -> Acc1</name>
+ <name name="fold" arity="3"/>
<fsummary>Fold over set elements</fsummary>
- <type>
- <v>Function = fun (E, AccIn) -> AccOut</v>
- <v>Acc0 = Acc1 = AccIn = AccOut = term()</v>
- <v>Set = set()</v>
- </type>
<desc>
- <p>Fold <c>Function</c> over every element in <c>Set</c>
+ <p>Fold <c><anno>Function</anno></c> over every element in <c><anno>Set</anno></c>
returning the final value of the accumulator.</p>
</desc>
</func>
<func>
- <name>filter(Pred, Set1) -> Set2</name>
+ <name name="filter" arity="2"/>
<fsummary>Filter set elements</fsummary>
- <type>
- <v>Pred = fun (E) -> bool()</v>
- <v>Set1 = Set2 = set()</v>
- </type>
<desc>
- <p>Filter elements in <c>Set1</c> with boolean function
- <c>Fun</c>.</p>
+ <p>Filter elements in <c><anno>Set1</anno></c> with boolean function
+ <c><anno>Pred</anno></c>.</p>
</desc>
</func>
</funcs>
diff --git a/lib/stdlib/doc/src/shell.xml b/lib/stdlib/doc/src/shell.xml
index 73cc1b33bd..bc2120c37d 100644
--- a/lib/stdlib/doc/src/shell.xml
+++ b/lib/stdlib/doc/src/shell.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2010</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -763,26 +763,20 @@ loop(N) ->
<funcs>
<func>
- <name>history(N) -> integer()</name>
+ <name name="history" arity="1"/>
<fsummary>Sets the number of previous commands to keep</fsummary>
- <type>
- <v>N = integer()</v>
- </type>
<desc>
<p>Sets the number of previous commands to keep in the
- history list to <c>N</c>. The previous number is returned.
+ history list to <c><anno>N</anno></c>. The previous number is returned.
The default number is 20.</p>
</desc>
</func>
<func>
- <name>results(N) -> integer()</name>
+ <name name="results" arity="1"/>
<fsummary>Sets the number of previous results to keep</fsummary>
- <type>
- <v>N = integer()</v>
- </type>
<desc>
<p>Sets the number of results from previous commands to keep in
- the history list to <c>N</c>. The previous number is returned.
+ the history list to <c><anno>N</anno></c>. The previous number is returned.
The default number is 20.</p>
</desc>
</func>
@@ -790,7 +784,7 @@ loop(N) ->
<name>catch_exception(Bool) -> Bool</name>
<fsummary>Sets the exception handling of the shell</fsummary>
<type>
- <v>Bool = bool()</v>
+ <v>Bool = boolean()</v>
</type>
<desc>
<p>Sets the exception handling of the evaluator process. The
@@ -804,38 +798,29 @@ loop(N) ->
</desc>
</func>
<func>
- <name>prompt_func(PromptFunc) -> prompt_func()</name>
+ <name name="prompt_func" arity="1"/>
<fsummary>Sets the shell prompt</fsummary>
- <type>
- <v>PromptFunc = prompt_func()</v>
- <v>prompt_func() = default | {Mod, Func}</v>
- <v>Mod = Func = atom()</v>
- </type>
<desc>
<p>Sets the shell prompt function to <c>PromptFunc</c>. The
previous prompt function is returned.</p>
</desc>
</func>
<func>
- <name>start_restricted(Module) -> ok | {error, Reason}</name>
+ <name name="start_restricted" arity="1"/>
<fsummary>Exits a normal shell and starts a restricted shell.</fsummary>
- <type>
- <v>Module = atom()</v>
- <v>Reason = atom()</v>
- </type>
<desc>
<p>Exits a normal shell and starts a restricted
- shell. <c>Module</c> specifies the callback module for the
+ shell. <c><anno>Module</anno></c> specifies the callback module for the
functions <c>local_allowed/3</c> and <c>non_local_allowed/3</c>.
The function is meant to be called from the shell.</p>
<p>If the callback module cannot be loaded, an error tuple is
- returned. The <c>Reason</c> in the error tuple is the one
+ returned. The <c><anno>Reason</anno></c> in the error tuple is the one
returned by the code loader when trying to load the code of the callback
module.</p>
</desc>
</func>
<func>
- <name>stop_restricted() -> ok</name>
+ <name name="stop_restricted" arity="0"/>
<fsummary>Exits a restricted shell and starts a normal shell.</fsummary>
<desc>
<p>Exits a restricted shell and starts a normal shell. The function
diff --git a/lib/stdlib/doc/src/slave.xml b/lib/stdlib/doc/src/slave.xml
index 168d83f301..15b6711731 100644
--- a/lib/stdlib/doc/src/slave.xml
+++ b/lib/stdlib/doc/src/slave.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -56,22 +56,16 @@
</description>
<funcs>
<func>
- <name>start(Host) -></name>
- <name>start(Host, Name) -></name>
- <name>start(Host, Name, Args) -> {ok, Node} | {error, Reason}</name>
+ <name name="start" arity="1"/>
+ <name name="start" arity="2"/>
+ <name name="start" arity="3"/>
<fsummary>Start a slave node on a host</fsummary>
- <type>
- <v>Host = Name = atom()</v>
- <v>Args = string()</v>
- <v>Node = node()</v>
- <v>Reason = timeout | no_rsh | {already_running, Node}</v>
- </type>
<desc>
- <p>Starts a slave node on the host <c>Host</c>. Host names need
+ <p>Starts a slave node on the host <c><anno>Host</anno></c>. Host names need
not necessarily be specified as fully qualified names; short
names can also be used. This is the same condition that
applies to names of distributed Erlang nodes.</p>
- <p>The name of the started node will be <c>Name@Host</c>. If no
+ <p>The name of the started node will be <c><anno>Name</anno>@<anno>Host</anno></c>. If no
name is provided, the name will be the same as the node which
executes the call (with the exception of the host name part of
the node name).</p>
@@ -79,7 +73,7 @@
terminal I/O which is produced at the slave is automatically
relayed to the master. Also, the file process will be relayed
to the master.</p>
- <p>The <c>Args</c> argument is used to set <c>erl</c> command
+ <p>The <c><anno>Args</anno></c> argument is used to set <c>erl</c> command
line arguments. If provided, it is passed to the new node and
can be used for a variety of purposes. See
<seealso marker="erts:erl#erl">erl(1)</seealso></p>
@@ -103,9 +97,9 @@
E = " -env DISPLAY " ++ net_adm:localhost() ++ ":0 ",
Arg = "-mnesia_dir " ++ M ++ " -pa " ++ Dir ++ E,
slave:start(H, Name, Arg).</code>
- <p>If successful, the function returns <c>{ok, Node}</c>,
- where <c>Node</c> is the name of the new node. Otherwise it
- returns <c>{error, Reason}</c>, where <c>Reason</c> can be
+ <p>If successful, the function returns <c>{ok, <anno>Node</anno>}</c>,
+ where <c><anno>Node</anno></c> is the name of the new node. Otherwise it
+ returns <c>{error, <anno>Reason</anno>}</c>, where <c><anno>Reason</anno></c> can be
one of:</p>
<taglist>
<tag><c>timeout</c></tag>
@@ -123,24 +117,18 @@ slave:start(H, Name, Arg).</code>
<item>
<p>There is no <c>rsh</c> program on the computer.</p>
</item>
- <tag><c>{already_running, Node}</c></tag>
+ <tag><c>{already_running, <anno>Node</anno>}</c></tag>
<item>
- <p>A node with the name <c>Name@Host</c> already exists.</p>
+ <p>A node with the name <c><anno>Name</anno>@<anno>Host</anno></c> already exists.</p>
</item>
</taglist>
</desc>
</func>
<func>
- <name>start_link(Host) -></name>
- <name>start_link(Host, Name) -></name>
- <name>start_link(Host, Name, Args) -> {ok, Node} | {error, Reason}</name>
+ <name name="start_link" arity="1"/>
+ <name name="start_link" arity="2"/>
+ <name name="start_link" arity="3"/>
<fsummary>Start and link to a slave node on a host</fsummary>
- <type>
- <v>Host = Name = atom()</v>
- <v>Args = string()</v>
- <v>Node = node()</v>
- <v>Reason = timeout | no_rsh | {already_running, Node}</v>
- </type>
<desc>
<p>Starts a slave node in the same way as <c>start/1,2,3</c>,
except that the slave node is linked to the currently
@@ -151,11 +139,8 @@ slave:start(H, Name, Arg).</code>
</desc>
</func>
<func>
- <name>stop(Node) -> ok</name>
+ <name name="stop" arity="1"/>
<fsummary>Stop (kill) a node</fsummary>
- <type>
- <v>Node = node()</v>
- </type>
<desc>
<p>Stops (kills) a node.</p>
</desc>
@@ -177,12 +162,8 @@ slave:start(H, Name, Arg).</code>
</desc>
</func>
<func>
- <name>pseudo(Master, ServerList) -> ok</name>
+ <name name="pseudo" arity="2"/>
<fsummary>Start a number of pseudo servers</fsummary>
- <type>
- <v>Master = node()</v>
- <v>ServerList = [atom()]</v>
- </type>
<desc>
<p>Starts a number of pseudo servers. A pseudo server is a
server with a registered name which does absolutely nothing
@@ -198,16 +179,13 @@ rpc:call(N, slave, pseudo, [node(), [pxw_server]]).</code>
</desc>
</func>
<func>
- <name>relay(Pid)</name>
+ <name name="relay" arity="1"/>
<fsummary>Run a pseudo server</fsummary>
- <type>
- <v>Pid = pid()</v>
- </type>
<desc>
<p>Runs a pseudo server. This function never returns any value
and the process which executes the function will receive
messages. All messages received will simply be passed on to
- <c>Pid</c>.</p>
+ <c><anno>Pid</anno></c>.</p>
</desc>
</func>
</funcs>
diff --git a/lib/stdlib/doc/src/sofs.xml b/lib/stdlib/doc/src/sofs.xml
index 729df1e678..2e7768a1df 100644
--- a/lib/stdlib/doc/src/sofs.xml
+++ b/lib/stdlib/doc/src/sofs.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2001</year><year>2010</year>
+ <year>2001</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -181,10 +181,11 @@
the <marker id="canonical_map"></marker><em>canonical map</em> is
the function that maps every element of X onto its equivalence class.
</p>
- <p>Relations as defined above (as sets of ordered pairs) will from
- now on be referred to as <em>binary relations</em>. We call a
- set of ordered sets (x[1],&nbsp;...,&nbsp;x[n])
- an <em>(n-ary) relation</em>, and say that the relation is a subset of
+ <p><marker id="binary_relation"></marker>Relations as defined above
+ (as sets of ordered pairs) will from now on be referred to as
+ <em>binary relations</em>. We call a set of ordered sets
+ (x[1],&nbsp;...,&nbsp;x[n]) an <marker id="n_ary_relation"></marker>
+ <em>(n-ary) relation</em>, and say that the relation is a subset of
the <marker id="Cartesian_product_tuple"></marker>Cartesian product
X[1]&nbsp;&times;&nbsp;...&nbsp;&times;&nbsp;X[n] where x[i] is
an element of X[i], 1&nbsp;&lt;=&nbsp;i&nbsp;&lt;=&nbsp;n.
@@ -293,7 +294,8 @@
<c>partition_family/2</c>, <c>projection/2</c>,
<c>restriction/3</c>, <c>substitution/2</c>) accept an Erlang
function as a means to modify each element of a given unordered
- set. Such a function, called SetFun in the following, can be
+ set. <marker id="set_fun"></marker>Such a function, called
+ SetFun in the following, can be
specified as a functional object (fun), a tuple
<c>{external,&nbsp;Fun}</c>, or an integer. If SetFun is
specified as a fun, the fun is applied to each element of the
@@ -337,34 +339,73 @@ fun(S) -> sofs:partition(1, S) end
message when given badly formed arguments or sets the types of
which are not compatible.</p>
<p>When comparing external sets the operator <c>==/2</c> is used.</p>
- <p><em>Types</em></p>
- <pre>
-anyset() = -&nbsp;an unordered, ordered or atomic set&nbsp;-
-binary_relation() = -&nbsp;a binary relation&nbsp;-
-bool() = true | false
-external_set() = -&nbsp;an external set&nbsp;-
-family() = -&nbsp;a family (of subsets)&nbsp;-
-function() = -&nbsp;a function&nbsp;-
-ordset() = -&nbsp;an ordered set&nbsp;-
-relation() = -&nbsp;an n-ary relation&nbsp;-
-set() = -&nbsp;an unordered set&nbsp;-
-set_of_sets() = -&nbsp;an unordered set of set()&nbsp;-
-set_fun() = integer() >= 1
- | {external, fun(external_set()) -> external_set()}
- | fun(anyset()) -> anyset()
-spec_fun() = {external, fun(external_set()) -> bool()}
- | fun(anyset()) -> bool()
-type() = -&nbsp;a type&nbsp;- </pre>
</description>
+ <datatypes>
+ <datatype>
+ <name name="anyset"></name>
+ <desc><p>Any kind of set (also included are the atomic sets).</p></desc>
+ </datatype>
+ <datatype>
+ <name name="binary_relation"></name>
+ <desc><p>A <seealso marker="#binary_relation">binary
+ relation</seealso>.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="external_set"></name>
+ <desc><p>An <seealso marker="#external_set">external
+ set</seealso>.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="family"></name>
+ <desc><p>A <seealso marker="#family">family</seealso> (of subsets).</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="a_function"></name>
+ <desc><p>A <seealso marker="#function">function</seealso>.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="ordset"></name>
+ <desc><p>An <seealso marker="#sets_definition">ordered
+ set</seealso>.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="relation"></name>
+ <desc><p>An <seealso marker="#n_ary_relation">n-ary relation</seealso>.
+ </p></desc>
+ </datatype>
+ <datatype>
+ <name name="a_set"></name>
+ <desc><p>An <seealso marker="#sets_definition">unordered
+ set</seealso>.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="set_of_sets"></name>
+ <desc><p>An <seealso marker="#sets_definition">unordered
+ set</seealso> of unordered sets.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="set_fun"></name>
+ <desc><p>A <seealso marker="#set_fun">SetFun</seealso>.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="spec_fun"></name>
+ </datatype>
+ <datatype>
+ <name name="type"></name>
+ <desc><p>A <seealso marker="#type">type</seealso>.</p></desc>
+ </datatype>
+ <datatype>
+ <!-- Parameterized opaque types are NYI: -->
+ <name><marker id="type-tuple_of">tuple_of(T)</marker></name>
+ <desc><p>A tuple where the elements are of type <c>T</c>.</p></desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>a_function(Tuples [, Type]) -> Function</name>
+ <name name="a_function" arity="1"/>
+ <name name="a_function" arity="2"/>
<fsummary>Create a function.</fsummary>
- <type>
- <v>Function = function()</v>
- <v>Tuples = [tuple()]</v>
- <v>Type = type()</v>
- </type>
<desc>
<p>Creates a <seealso marker="#function">function</seealso>.
<c>a_function(F,&nbsp;T)</c> is equivalent to
@@ -375,16 +416,12 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>canonical_relation(SetOfSets) -> BinRel</name>
+ <name name="canonical_relation" arity="1"/>
<fsummary>Return the canonical map.</fsummary>
- <type>
- <v>BinRel = binary_relation()</v>
- <v>SetOfSets = set_of_sets()</v>
- </type>
<desc>
<p>Returns the binary relation containing the elements
- (E,&nbsp;Set) such that Set belongs to SetOfSets and E
- belongs to Set. If SetOfSets is
+ (E,&nbsp;Set) such that Set belongs to <anno>SetOfSets</anno> and E
+ belongs to Set. If SetOfSets is
a <seealso marker="#partition">partition</seealso> of a set X and
R is the equivalence relation in X induced by SetOfSets, then the
returned relation is
@@ -398,14 +435,12 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>composite(Function1, Function2) -> Function3</name>
+ <name name="composite" arity="2"/>
<fsummary>Return the composite of two functions.</fsummary>
- <type>
- <v>Function1 = Function2 = Function3 = function()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#composite">composite</seealso> of
- the functions Function1 and Function2.</p>
+ the functions <anno>Function1</anno> and
+ <anno>Function2</anno>.</p>
<pre>
1> <input>F1 = sofs:a_function([{a,1},{b,2},{c,2}]),</input>
<input>F2 = sofs:a_function([{1,x},{2,y},{3,z}]),</input>
@@ -415,14 +450,9 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>constant_function(Set, AnySet) -> Function</name>
+ <name name="constant_function" arity="2"/>
<fsummary>Create the function that maps each element of a
set onto another set.</fsummary>
- <type>
- <v>AnySet = anyset()</v>
- <v>Function = function()</v>
- <v>Set = set()</v>
- </type>
<desc>
<p>Creates the <seealso marker="#function">function</seealso>
that maps each element of the set Set onto AnySet.</p>
@@ -435,14 +465,11 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>converse(BinRel1) -> BinRel2</name>
+ <name name="converse" arity="1"/>
<fsummary>Return the converse of a binary relation.</fsummary>
- <type>
- <v>BinRel1 = BinRel2 = binary_relation()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#converse">converse</seealso>
- of the binary relation BinRel1.</p>
+ of the binary relation <anno>BinRel1</anno>.</p>
<pre>
1> <input>R1 = sofs:relation([{1,a},{2,b},{3,a}]),</input>
<input>R2 = sofs:converse(R1),</input>
@@ -451,31 +478,25 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>difference(Set1, Set2) -> Set3</name>
+ <name name="difference" arity="2"/>
<fsummary>Return the difference of two sets.</fsummary>
- <type>
- <v>Set1 = Set2 = Set3 = set()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#difference">difference</seealso> of
- the sets Set1 and Set2.</p>
+ the sets <anno>Set1</anno> and <anno>Set2</anno>.</p>
</desc>
</func>
<func>
- <name>digraph_to_family(Graph [, Type]) -> Family</name>
+ <name name="digraph_to_family" arity="1"/>
+ <name name="digraph_to_family" arity="2"/>
<fsummary>Create a family from a directed graph.</fsummary>
- <type>
- <v>Graph = digraph() -&nbsp;see digraph(3)&nbsp;-</v>
- <v>Family = family()</v>
- <v>Type = type()</v>
- </type>
<desc>
<p>Creates a <seealso marker="#family">family</seealso> from
- the directed graph Graph. Each vertex a of Graph is
+ the directed graph <anno>Graph</anno>. Each vertex a of
+ <anno>Graph</anno> is
represented by a pair (a,&nbsp;{b[1],&nbsp;...,&nbsp;b[n]})
where the b[i]'s are the out-neighbours of a. If no type is
explicitly given, [{atom,&nbsp;[atom]}] is used as type of
- the family. It is assumed that Type is
+ the family. It is assumed that <anno>Type</anno> is
a <seealso marker="#valid_type">valid type</seealso> of the
external set of the family.</p>
<p>If G is a directed graph, it holds that the vertices and
@@ -484,15 +505,11 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>domain(BinRel) -> Set</name>
+ <name name="domain" arity="1"/>
<fsummary>Return the domain of a binary relation.</fsummary>
- <type>
- <v>BinRel = binary_relation()</v>
- <v>Set = set()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#domain">domain</seealso> of
- the binary relation BinRel.</p>
+ the binary relation <anno>BinRel</anno>.</p>
<pre>
1> <input>R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]),</input>
<input>S = sofs:domain(R),</input>
@@ -501,16 +518,13 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>drestriction(BinRel1, Set) -> BinRel2</name>
+ <name name="drestriction" arity="2"/>
<fsummary>Return a restriction of a binary relation.</fsummary>
- <type>
- <v>BinRel1 = BinRel2 = binary_relation()</v>
- <v>Set = set()</v>
- </type>
<desc>
- <p>Returns the difference between the binary relation BinRel1
+ <p>Returns the difference between the binary relation
+ <anno>BinRel1</anno>
and the <seealso marker="#restriction">restriction</seealso>
- of BinRel1 to Set.</p>
+ of <anno>BinRel1</anno> to <anno>Set</anno>.</p>
<pre>
1> <input>R1 = sofs:relation([{1,a},{2,b},{3,c}]),</input>
<input>S = sofs:set([2,4,6]),</input>
@@ -522,16 +536,13 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>drestriction(SetFun, Set1, Set2) -> Set3</name>
+ <name name="drestriction" arity="3"/>
<fsummary>Return a restriction of a relation.</fsummary>
- <type>
- <v>SetFun = set_fun()</v>
- <v>Set1 = Set2 = Set3 = set()</v>
- </type>
- <desc>
- <p>Returns a subset of Set1 containing those elements that do
- not yield an element in Set2 as the result of applying
- SetFun.</p>
+ <desc>
+ <p>Returns a subset of <anno>Set1</anno> containing those elements
+ that do
+ not yield an element in <anno>Set2</anno> as the result of applying
+ <anno>SetFun</anno>.</p>
<pre>
1> <input>SetFun = {external, fun({_A,B,C}) -> {B,C} end},</input>
<input>R1 = sofs:relation([{a,aa,1},{b,bb,2},{c,cc,3}]),</input>
@@ -544,11 +555,8 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>empty_set() -> Set</name>
+ <name name="empty_set" arity="0"/>
<fsummary>Return the untyped empty set.</fsummary>
- <type>
- <v>Set = set()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#sets_definition">untyped empty
set</seealso>. <c>empty_set()</c> is equivalent to
@@ -556,19 +564,14 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>extension(BinRel1, Set, AnySet) -> BinRel2</name>
+ <name name="extension" arity="3"/>
<fsummary>Extend the domain of a binary relation.</fsummary>
- <type>
- <v>AnySet = anyset()</v>
- <v>BinRel1 = BinRel2 = binary_relation()</v>
- <v>Set = set()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#extension">extension</seealso> of
- BinRel1 such that
- for each element E in Set that does not belong to the
- <seealso marker="#domain">domain</seealso> of BinRel1,
- BinRel2 contains the pair (E,&nbsp;AnySet).</p>
+ <anno>BinRel1</anno> such that
+ for each element E in <anno>Set</anno> that does not belong to the
+ <seealso marker="#domain">domain</seealso> of <anno>BinRel1</anno>,
+ <anno>BinRel2</anno> contains the pair (E,&nbsp;AnySet).</p>
<pre>
1> <input>S = sofs:set([b,c]),</input>
<input>A = sofs:empty_set(),</input>
@@ -579,13 +582,9 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>family(Tuples [, Type]) -> Family</name>
+ <name name="family" arity="1"/>
+ <name name="family" arity="2"/>
<fsummary>Create a family of subsets.</fsummary>
- <type>
- <v>Family = family()</v>
- <v>Tuples = [tuple()]</v>
- <v>Type = type()</v>
- </type>
<desc>
<p>Creates a <seealso marker="#family">family of subsets</seealso>.
<c>family(F,&nbsp;T)</c> is equivalent to
@@ -596,18 +595,17 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>family_difference(Family1, Family2) -> Family3</name>
+ <name name="family_difference" arity="2"/>
<fsummary>Return the difference of two families.</fsummary>
- <type>
- <v>Family1 = Family2 = Family3 = family()</v>
- </type>
<desc>
- <p>If Family1 and Family2
+ <p>If <anno>Family1</anno> and <anno>Family2</anno>
are <seealso marker="#family">families</seealso>, then
- Family3 is the family
+ <anno>Family3</anno> is the family
such that the index set is equal to the index set of
- Family1, and Family3[i] is the difference between Family1[i]
- and Family2[i] if Family2 maps i, Family1[i] otherwise.</p>
+ <anno>Family1</anno>, and <anno>Family3</anno>[i] is the
+ difference between <anno>Family1</anno>[i]
+ and <anno>Family2</anno>[i] if <anno>Family2</anno> maps i,
+ <anno>Family1</anno>[i] otherwise.</p>
<pre>
1> <input>F1 = sofs:family([{a,[1,2]},{b,[3,4]}]),</input>
<input>F2 = sofs:family([{b,[4,5]},{c,[6,7]}]),</input>
@@ -617,17 +615,18 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>family_domain(Family1) -> Family2</name>
+ <name name="family_domain" arity="1"/>
<fsummary>Return a family of domains.</fsummary>
- <type>
- <v>Family1 = Family2 = family()</v>
- </type>
- <desc>
- <p>If Family1 is a <seealso marker="#family">family</seealso>
- and Family1[i] is a binary relation for every i in the index
- set of Family1, then Family2 is the family with the same
- index set as Family1 such that Family2[i] is
- the <seealso marker="#domain">domain</seealso> of Family1[i].</p>
+ <desc>
+ <p>If <anno>Family1</anno> is
+ a <seealso marker="#family">family</seealso>
+ and <anno>Family1</anno>[i] is a binary relation for every i
+ in the index set of <anno>Family1</anno>,
+ then <anno>Family2</anno> is the family with the same index
+ set as <anno>Family1</anno> such
+ that <anno>Family2</anno>[i] is
+ the <seealso marker="#domain">domain</seealso> of
+ <anno>Family1</anno>[i].</p>
<pre>
1> <input>FR = sofs:from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),</input>
<input>F = sofs:family_domain(FR),</input>
@@ -636,17 +635,18 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>family_field(Family1) -> Family2</name>
+ <name name="family_field" arity="1"/>
<fsummary>Return a family of fields.</fsummary>
- <type>
- <v>Family1 = Family2 = family()</v>
- </type>
- <desc>
- <p>If Family1 is a <seealso marker="#family">family</seealso>
- and Family1[i] is a binary relation for every i in the index
- set of Family1, then Family2 is the family with the same
- index set as Family1 such that Family2[i] is
- the <seealso marker="#field">field</seealso> of Family1[i].</p>
+ <desc>
+ <p>If <anno>Family1</anno> is
+ a <seealso marker="#family">family</seealso>
+ and <anno>Family1</anno>[i] is a binary relation for every i
+ in the index set of <anno>Family1</anno>,
+ then <anno>Family2</anno> is the family with the same index
+ set as <anno>Family1</anno> such
+ that <anno>Family2</anno>[i] is
+ the <seealso marker="#field">field</seealso> of
+ <anno>Family1</anno>[i].</p>
<pre>
1> <input>FR = sofs:from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),</input>
<input>F = sofs:family_field(FR),</input>
@@ -657,21 +657,21 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>family_intersection(Family1) -> Family2</name>
+ <name name="family_intersection" arity="1"/>
<fsummary>Return the intersection of a family
of sets of sets.</fsummary>
- <type>
- <v>Family1 = Family2 = family()</v>
- </type>
- <desc>
- <p>If Family1 is a <seealso marker="#family">family</seealso>
- and Family1[i] is a set of sets for every i in the index set
- of Family1, then Family2 is the family with the same index
- set as Family1 such that Family2[i] is
- the <seealso marker="#intersection_n">intersection</seealso> of
- Family1[i].</p>
- <p>If Family1[i] is an empty set for some i, then the process
- exits with a <c>badarg</c> message.</p>
+ <desc>
+ <p>If <anno>Family1</anno> is
+ a <seealso marker="#family">family</seealso>
+ and <anno>Family1</anno>[i] is a set of sets for every i in
+ the index set of <anno>Family1</anno>,
+ then <anno>Family2</anno> is the family with the same index
+ set as <anno>Family1</anno> such
+ that <anno>Family2</anno>[i] is
+ the <seealso marker="#intersection_n">intersection</seealso>
+ of <anno>Family1</anno>[i].</p>
+ <p>If <anno>Family1</anno>[i] is an empty set for some i, then
+ the process exits with a <c>badarg</c> message.</p>
<pre>
1> <input>F1 = sofs:from_term([{a,[[1,2,3],[2,3,4]]},{b,[[x,y,z],[x,y]]}]),</input>
<input>F2 = sofs:family_intersection(F1),</input>
@@ -680,17 +680,16 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>family_intersection(Family1, Family2) -> Family3</name>
+ <name name="family_intersection" arity="2"/>
<fsummary>Return the intersection of two families.</fsummary>
- <type>
- <v>Family1 = Family2 = Family3 = family()</v>
- </type>
- <desc>
- <p>If Family1 and Family2
- are <seealso marker="#family">families</seealso>, then Family3
- is the family such that the index set is the intersection of
- Family1's and Family2's index sets, and Family3[i] is the
- intersection of Family1[i] and Family2[i].</p>
+ <desc>
+ <p>If <anno>Family1</anno> and <anno>Family2</anno>
+ are <seealso marker="#family">families</seealso>,
+ then <anno>Family3</anno> is the family such that the index
+ set is the intersection of <anno>Family1</anno>'s and
+ <anno>Family2</anno>'s index sets,
+ and <anno>Family3</anno>[i] is the intersection of
+ <anno>Family1</anno>[i] and <anno>Family2</anno>[i].</p>
<pre>
1> <input>F1 = sofs:family([{a,[1,2]},{b,[3,4]},{c,[5,6]}]),</input>
<input>F2 = sofs:family([{b,[4,5]},{c,[7,8]},{d,[9,10]}]),</input>
@@ -700,18 +699,16 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>family_projection(SetFun, Family1) -> Family2</name>
+ <name name="family_projection" arity="2"/>
<fsummary>Return a family of modified subsets.</fsummary>
- <type>
- <v>SetFun = set_fun()</v>
- <v>Family1 = Family2 = family()</v>
- <v>Set = set()</v>
- </type>
- <desc>
- <p>If Family1 is a <seealso marker="#family">family</seealso>
- then Family2 is the family with the same index set as
- Family1 such that Family2[i] is the result of calling SetFun
- with Family1[i] as argument.</p>
+ <desc>
+ <p>If <anno>Family1</anno> is
+ a <seealso marker="#family">family</seealso>
+ then <anno>Family2</anno> is the family with the same index
+ set as <anno>Family1</anno> such
+ that <anno>Family2</anno>[i] is the result of
+ calling <anno>SetFun</anno> with <anno>Family1</anno>[i] as
+ argument.</p>
<pre>
1> <input>F1 = sofs:from_term([{a,[[1,2],[2,3]]},{b,[[]]}]),</input>
<input>F2 = sofs:family_projection({sofs, union}, F1),</input>
@@ -720,17 +717,18 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>family_range(Family1) -> Family2</name>
+ <name name="family_range" arity="1"/>
<fsummary>Return a family of ranges.</fsummary>
- <type>
- <v>Family1 = Family2 = family()</v>
- </type>
- <desc>
- <p>If Family1 is a <seealso marker="#family">family</seealso>
- and Family1[i] is a binary relation for every i in the index
- set of Family1, then Family2 is the family with the same
- index set as Family1 such that Family2[i] is
- the <seealso marker="#range">range</seealso> of Family1[i].</p>
+ <desc>
+ <p>If <anno>Family1</anno> is
+ a <seealso marker="#family">family</seealso>
+ and <anno>Family1</anno>[i] is a binary relation for every i
+ in the index set of <anno>Family1</anno>,
+ then <anno>Family2</anno> is the family with the same index
+ set as <anno>Family1</anno> such
+ that <anno>Family2</anno>[i] is
+ the <seealso marker="#range">range</seealso> of
+ <anno>Family1</anno>[i].</p>
<pre>
1> <input>FR = sofs:from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),</input>
<input>F = sofs:family_range(FR),</input>
@@ -739,22 +737,21 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>family_specification(Fun, Family1) -> Family2</name>
+ <name name="family_specification" arity="2"/>
<fsummary>Select a subset of a family using a predicate.</fsummary>
- <type>
- <v>Fun = spec_fun()</v>
- <v>Family1 = Family2 = family()</v>
- </type>
- <desc>
- <p>If Family1 is a <seealso marker="#family">family</seealso>,
- then Family2 is
- the <seealso marker="#restriction">restriction</seealso> of
- Family1 to those elements i of the
- index set for which Fun applied to Family1[i] returns
- <c>true</c>. If Fun is a tuple <c>{external,&nbsp;Fun2}</c>,
- Fun2 is applied to
- the <seealso marker="#external_set">external set</seealso> of
- Family1[i], otherwise Fun is applied to Family1[i].</p>
+ <desc>
+ <p>If <anno>Family1</anno> is
+ a <seealso marker="#family">family</seealso>,
+ then <anno>Family2</anno> is
+ the <seealso marker="#restriction">restriction</seealso> of
+ <anno>Family1</anno> to those elements i of the index set
+ for which <anno>Fun</anno> applied
+ to <anno>Family1</anno>[i] returns
+ <c>true</c>. If <anno>Fun</anno> is a
+ tuple <c>{external,&nbsp;Fun2}</c>, Fun2 is applied to
+ the <seealso marker="#external_set">external set</seealso>
+ of <anno>Family1</anno>[i], otherwise <anno>Fun</anno> is
+ applied to <anno>Family1</anno>[i].</p>
<pre>
1> <input>F1 = sofs:family([{a,[1,2,3]},{b,[1,2]},{c,[1]}]),</input>
<input>SpecFun = fun(S) -> sofs:no_elements(S) =:= 2 end,</input>
@@ -764,24 +761,22 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>family_to_digraph(Family [, GraphType]) -> Graph</name>
+ <name name="family_to_digraph" arity="1"/>
+ <name name="family_to_digraph" arity="2"/>
<fsummary>Create a directed graph from a family.</fsummary>
- <type>
- <v>Graph = digraph()</v>
- <v>Family = family()</v>
- <v>GraphType = -&nbsp;see digraph(3)&nbsp;-</v>
- </type>
<desc>
<p>Creates a directed graph from
- the <seealso marker="#family">family</seealso> Family. For each
- pair (a,&nbsp;{b[1],&nbsp;...,&nbsp;b[n]}) of Family, the vertex
+ the <seealso marker="#family">family</seealso> <anno>Family</anno>.
+ For each pair (a,&nbsp;{b[1],&nbsp;...,&nbsp;b[n]})
+ of <anno>Family</anno>, the vertex
a as well the edges (a,&nbsp;b[i]) for
1&nbsp;&lt;=&nbsp;i&nbsp;&lt;=&nbsp;n are added to a newly
created directed graph.</p>
- <p>If no graph type is given, <c>digraph:new/1</c> is used for
- creating the directed graph, otherwise the GraphType
+ <p>If no graph type is given <seealso marker="digraph#new/0">
+ digraph:new/0</seealso> is used for
+ creating the directed graph, otherwise the <anno>GraphType</anno>
argument is passed on as second argument to
- <c>digraph:new/2</c>.</p>
+ <seealso marker="digraph#new/1">digraph:new/1</seealso>.</p>
<p>It F is a family, it holds that F is a subset of
<c>digraph_to_family(family_to_digraph(F),&nbsp;type(F))</c>.
Equality holds if <c>union_of_family(F)</c> is a subset of
@@ -791,17 +786,15 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>family_to_relation(Family) -> BinRel</name>
+ <name name="family_to_relation" arity="1"/>
<fsummary>Create a binary relation from a family.</fsummary>
- <type>
- <v>Family = family()</v>
- <v>BinRel = binary_relation()</v>
- </type>
- <desc>
- <p>If Family is a <seealso marker="#family">family</seealso>,
- then BinRel is the binary relation containing all pairs
- (i,&nbsp;x) such that i belongs to the index set of Family
- and x belongs to Family[i].</p>
+ <desc>
+ <p>If <anno>Family</anno> is
+ a <seealso marker="#family">family</seealso>,
+ then <anno>BinRel</anno> is the binary relation containing
+ all pairs (i,&nbsp;x) such that i belongs to the index set
+ of <anno>Family</anno> and x belongs
+ to <anno>Family</anno>[i].</p>
<pre>
1> <input>F = sofs:family([{a,[]}, {b,[1]}, {c,[2,3]}]),</input>
<input>R = sofs:family_to_relation(F),</input>
@@ -810,17 +803,18 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>family_union(Family1) -> Family2</name>
+ <name name="family_union" arity="1"/>
<fsummary>Return the union of a family of sets of sets.</fsummary>
- <type>
- <v>Family1 = Family2 = family()</v>
- </type>
- <desc>
- <p>If Family1 is a <seealso marker="#family">family</seealso>
- and Family1[i] is a set of sets for each i in the index set
- of Family1, then Family2 is the family with the same index
- set as Family1 such that Family2[i] is
- the <seealso marker="#union_n">union</seealso> of Family1[i].</p>
+ <desc>
+ <p>If <anno>Family1</anno> is
+ a <seealso marker="#family">family</seealso>
+ and <anno>Family1</anno>[i] is a set of sets for each i in
+ the index set of <anno>Family1</anno>,
+ then <anno>Family2</anno> is the family with the same index
+ set as <anno>Family1</anno> such
+ that <anno>Family2</anno>[i] is
+ the <seealso marker="#union_n">union</seealso> of
+ <anno>Family1</anno>[i].</p>
<pre>
1> <input>F1 = sofs:from_term([{a,[[1,2],[2,3]]},{b,[[]]}]),</input>
<input>F2 = sofs:family_union(F1),</input>
@@ -831,18 +825,18 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>family_union(Family1, Family2) -> Family3</name>
+ <name name="family_union" arity="2"/>
<fsummary>Return the union of two families.</fsummary>
- <type>
- <v>Family1 = Family2 = Family3 = family()</v>
- </type>
- <desc>
- <p>If Family1 and Family2
- are <seealso marker="#family">families</seealso>, then Family3
- is the family such that the index set is the union of Family1's
- and Family2's index sets, and Family3[i] is the union of
- Family1[i] and Family2[i] if both maps i, Family1[i] or
- Family2[i] otherwise.</p>
+ <desc>
+ <p>If <anno>Family1</anno> and <anno>Family2</anno>
+ are <seealso marker="#family">families</seealso>,
+ then <anno>Family3</anno> is the family such that the index
+ set is the union of <anno>Family1</anno>'s
+ and <anno>Family2</anno>'s index sets,
+ and <anno>Family3</anno>[i] is the union
+ of <anno>Family1</anno>[i] and <anno>Family2</anno>[i] if
+ both maps i, <anno>Family1</anno>[i]
+ or <anno>Family2</anno>[i] otherwise.</p>
<pre>
1> <input>F1 = sofs:family([{a,[1,2]},{b,[3,4]},{c,[5,6]}]),</input>
<input>F2 = sofs:family([{b,[4,5]},{c,[7,8]},{d,[9,10]}]),</input>
@@ -852,15 +846,11 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>field(BinRel) -> Set</name>
+ <name name="field" arity="1"/>
<fsummary>Return the field of a binary relation.</fsummary>
- <type>
- <v>BinRel = binary_relation()</v>
- <v>Set = set()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#field">field</seealso> of the
- binary relation BinRel.</p>
+ binary relation <anno>BinRel</anno>.</p>
<pre>
1> <input>R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]),</input>
<input>S = sofs:field(R),</input>
@@ -871,31 +861,24 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>from_external(ExternalSet, Type) -> AnySet</name>
+ <name name="from_external" arity="2"/>
<fsummary>Create a set.</fsummary>
- <type>
- <v>ExternalSet = external_set()</v>
- <v>AnySet = anyset()</v>
- <v>Type = type()</v>
- </type>
<desc>
<p>Creates a set from the <seealso marker="#external_set">external
- set</seealso> ExternalSet
- and the <seealso marker="#type">type</seealso> Type. It is
- assumed that Type is a <seealso marker="#valid_type">valid
- type</seealso> of ExternalSet.</p>
+ set</seealso> <anno>ExternalSet</anno>
+ and the <seealso marker="#type">type</seealso> <anno>Type</anno>.
+ It is assumed that <anno>Type</anno> is
+ a <seealso marker="#valid_type">valid
+ type</seealso> of <anno>ExternalSet</anno>.</p>
</desc>
</func>
<func>
- <name>from_sets(ListOfSets) -> Set</name>
+ <name name="from_sets" arity="1" clause_i="1"/>
<fsummary>Create a set out of a list of sets.</fsummary>
- <type>
- <v>Set = set()</v>
- <v>ListOfSets = [anyset()]</v>
- </type>
<desc>
<p>Returns the <seealso marker="#sets_definition">unordered
- set</seealso> containing the sets of the list ListOfSets.</p>
+ set</seealso> containing the sets of the list
+ <anno>ListOfSets</anno>.</p>
<pre>
1> <input>S1 = sofs:relation([{a,1},{b,2}]),</input>
<input>S2 = sofs:relation([{x,3},{y,4}]),</input>
@@ -905,38 +888,33 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>from_sets(TupleOfSets) -> Ordset</name>
+ <name name="from_sets" arity="1" clause_i="2"/>
<fsummary>Create an ordered set out of a tuple of sets.</fsummary>
- <type>
- <v>Ordset = ordset()</v>
- <v>TupleOfSets = tuple-of(anyset())</v>
- </type>
<desc>
<p>Returns the <seealso marker="#sets_definition">ordered
set</seealso> containing the sets of the non-empty tuple
- TupleOfSets.</p>
+ <anno>TupleOfSets</anno>.</p>
</desc>
</func>
<func>
- <name>from_term(Term [, Type]) -> AnySet</name>
+ <name name="from_term" arity="1"/>
+ <name name="from_term" arity="2"/>
<fsummary>Create a set.</fsummary>
- <type>
- <v>AnySet = anyset()</v>
- <v>Term = term()</v>
- <v>Type = type()</v>
- </type>
<desc>
<p><marker id="from_term"></marker>Creates an element
of <seealso marker="#sets_definition">Sets</seealso> by
- traversing the term Term, sorting lists, removing duplicates and
+ traversing the term <anno>Term</anno>, sorting lists,
+ removing duplicates and
deriving or verifying a <seealso marker="#valid_type">valid
type</seealso> for the so obtained external set. An
- explicitly given <seealso marker="#type">type</seealso> Type
+ explicitly given <seealso marker="#type">type</seealso>
+ <anno>Type</anno>
can be used to limit the depth of the traversal; an atomic
type stops the traversal, as demonstrated by this example
where "foo" and {"foo"} are left unmodified:</p>
<pre>
-1> <input>S = sofs:from_term([{{"foo"},[1,1]},{"foo",[2,2]}], [{atom,[atom]}]),</input>
+1> <input>S = sofs:from_term([{{"foo"},[1,1]},{"foo",[2,2]}],
+[{atom,[atom]}]),</input>
<input>sofs:to_external(S).</input>
[{{"foo"},[1]},{"foo",[2]}]</pre>
<p><c>from_term</c> can be used for creating atomic or ordered
@@ -963,15 +941,12 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>image(BinRel, Set1) -> Set2</name>
+ <name name="image" arity="2"/>
<fsummary>Return the image of a set under a binary relation.</fsummary>
- <type>
- <v>BinRel = binary_relation()</v>
- <v>Set1 = Set2 = set()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#image">image</seealso> of the
- set Set1 under the binary relation BinRel.</p>
+ set <anno>Set1</anno> under the binary
+ relation <anno>BinRel</anno>.</p>
<pre>
1> <input>R = sofs:relation([{1,a},{2,b},{2,c},{3,d}]),</input>
<input>S1 = sofs:set([1,2]),</input>
@@ -981,42 +956,32 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>intersection(SetOfSets) -> Set</name>
+ <name name="intersection" arity="1"/>
<fsummary>Return the intersection of a set of sets.</fsummary>
- <type>
- <v>Set = set()</v>
- <v>SetOfSets = set_of_sets()</v>
- </type>
<desc>
<p>Returns
the <seealso marker="#intersection_n">intersection</seealso> of
- the set of sets SetOfSets.</p>
+ the set of sets <anno>SetOfSets</anno>.</p>
<p>Intersecting an empty set of sets exits the process with a
<c>badarg</c> message.</p>
</desc>
</func>
<func>
- <name>intersection(Set1, Set2) -> Set3</name>
+ <name name="intersection" arity="2"/>
<fsummary>Return the intersection of two sets.</fsummary>
- <type>
- <v>Set1 = Set2 = Set3 = set()</v>
- </type>
<desc>
<p>Returns
the <seealso marker="#intersection">intersection</seealso> of
- Set1 and Set2.</p>
+ <anno>Set1</anno> and <anno>Set2</anno>.</p>
</desc>
</func>
<func>
- <name>intersection_of_family(Family) -> Set</name>
+ <name name="intersection_of_family" arity="1"/>
<fsummary>Return the intersection of a family.</fsummary>
- <type>
- <v>Family = family()</v>
- <v>Set = set()</v>
- </type>
<desc>
<p>Returns the intersection of
- the <seealso marker="#family">family</seealso> Family.</p>
+ the <seealso marker="#family">family</seealso> <anno>Family</anno>.
+ </p>
<p>Intersecting an empty family exits the process with a
<c>badarg</c> message.</p>
<pre>
@@ -1027,14 +992,11 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>inverse(Function1) -> Function2</name>
+ <name name="inverse" arity="1"/>
<fsummary>Return the inverse of a function.</fsummary>
- <type>
- <v>Function1 = Function2 = function()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#inverse">inverse</seealso>
- of the function Function1.</p>
+ of the function <anno>Function1</anno>.</p>
<pre>
1> <input>R1 = sofs:relation([{1,a},{2,b},{3,c}]),</input>
<input>R2 = sofs:inverse(R1),</input>
@@ -1043,16 +1005,13 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>inverse_image(BinRel, Set1) -> Set2</name>
+ <name name="inverse_image" arity="2"/>
<fsummary>Return the inverse image of a set under
a binary relation.</fsummary>
- <type>
- <v>BinRel = binary_relation()</v>
- <v>Set1 = Set2 = set()</v>
- </type>
<desc>
- <p>Returns the <seealso marker="#inverse_image">inverse
- image</seealso> of Set1 under the binary relation BinRel.</p>
+ <p>Returns the <seealso marker="#inverse_image">inverse
+ image</seealso> of <anno>Set1</anno> under the binary
+ relation <anno>BinRel</anno>.</p>
<pre>
1> <input>R = sofs:relation([{1,a},{2,b},{2,c},{3,d}]),</input>
<input>S1 = sofs:set([c,d,e]),</input>
@@ -1062,52 +1021,38 @@ type() = -&nbsp;a type&nbsp;- </pre>
</desc>
</func>
<func>
- <name>is_a_function(BinRel) -> Bool</name>
+ <name name="is_a_function" arity="1"/>
<fsummary>Test for a function.</fsummary>
- <type>
- <v>Bool = bool()</v>
- <v>BinRel = binary_relation()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if the binary relation BinRel is a
- <seealso marker="#function">function</seealso> or the
+ <p>Returns <c>true</c> if the binary relation <anno>BinRel</anno>
+ is a <seealso marker="#function">function</seealso> or the
untyped empty set, <c>false</c> otherwise.</p>
</desc>
</func>
<func>
- <name>is_disjoint(Set1, Set2) -> Bool</name>
+ <name name="is_disjoint" arity="2"/>
<fsummary>Test for disjoint sets.</fsummary>
- <type>
- <v>Bool = bool()</v>
- <v>Set1 = Set2 = set()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if Set1 and Set2
+ <p>Returns <c>true</c> if <anno>Set1</anno>
+ and <anno>Set2</anno>
are <seealso marker="#disjoint">disjoint</seealso>, <c>false</c>
otherwise.</p>
</desc>
</func>
<func>
- <name>is_empty_set(AnySet) -> Bool</name>
+ <name name="is_empty_set" arity="1"/>
<fsummary>Test for an empty set.</fsummary>
- <type>
- <v>AnySet = anyset()</v>
- <v>Bool = bool()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if Set is an empty unordered set,
- <c>false</c> otherwise.</p>
+ <p>Returns <c>true</c> if <anno>AnySet</anno> is an empty
+ unordered set, <c>false</c> otherwise.</p>
</desc>
</func>
<func>
- <name>is_equal(AnySet1, AnySet2) -> Bool</name>
+ <name name="is_equal" arity="2"/>
<fsummary>Test two sets for equality.</fsummary>
- <type>
- <v>AnySet1 = AnySet2 = anyset()</v>
- <v>Bool = bool()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if the AnySet1 and AnySet2
+ <p>Returns <c>true</c> if the <anno>AnySet1</anno>
+ and <anno>AnySet2</anno>
are <seealso marker="#equal">equal</seealso>, <c>false</c>
otherwise. This example shows that <c>==/2</c> is used when
comparing sets for equality:</p>
@@ -1119,67 +1064,49 @@ true</pre>
</desc>
</func>
<func>
- <name>is_set(AnySet) -> Bool</name>
+ <name name="is_set" arity="1"/>
<fsummary>Test for an unordered set.</fsummary>
- <type>
- <v>AnySet = anyset()</v>
- <v>Bool = bool()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if AnySet is
+ <p>Returns <c>true</c> if <anno>AnySet</anno> is
an <seealso marker="#sets_definition">unordered set</seealso>, and
- <c>false</c> if AnySet is an ordered set or an atomic set.</p>
+ <c>false</c> if <anno>AnySet</anno> is an ordered set or an
+ atomic set.</p>
</desc>
</func>
<func>
- <name>is_sofs_set(Term) -> Bool</name>
+ <name name="is_sofs_set" arity="1"/>
<fsummary>Test for an unordered set.</fsummary>
- <type>
- <v>Bool = bool()</v>
- <v>Term = term()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if Term is
+ <p>Returns <c>true</c> if <anno>Term</anno> is
an <seealso marker="#sets_definition">unordered set</seealso>, an
ordered set or an atomic set, <c>false</c> otherwise.</p>
</desc>
</func>
<func>
- <name>is_subset(Set1, Set2) -> Bool</name>
+ <name name="is_subset" arity="2"/>
<fsummary>Test two sets for subset.</fsummary>
- <type>
- <v>Bool = bool()</v>
- <v>Set1 = Set2 = set()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if Set1 is
- a <seealso marker="#subset">subset</seealso> of Set2, <c>false</c>
- otherwise.</p>
+ <p>Returns <c>true</c> if <anno>Set1</anno> is
+ a <seealso marker="#subset">subset</seealso>
+ of <anno>Set2</anno>, <c>false</c> otherwise.</p>
</desc>
</func>
<func>
- <name>is_type(Term) -> Bool</name>
+ <name name="is_type" arity="1"/>
<fsummary>Test for a type.</fsummary>
- <type>
- <v>Bool = bool()</v>
- <v>Term = term()</v>
- </type>
<desc>
- <p>Returns <c>true</c> if the term Term is
+ <p>Returns <c>true</c> if the term <anno>Term</anno> is
a <seealso marker="#type">type</seealso>.</p>
</desc>
</func>
<func>
- <name>join(Relation1, I, Relation2, J) -> Relation3</name>
+ <name name="join" arity="4"/>
<fsummary>Return the join of two relations.</fsummary>
- <type>
- <v>Relation1 = Relation2 = Relation3 = relation()</v>
- <v>I = J = integer() > 0</v>
- </type>
<desc>
<p>Returns the <seealso marker="#natural_join">natural
- join</seealso> of the relations Relation1 and Relation2 on
- coordinates I and J.</p>
+ join</seealso> of the relations <anno>Relation1</anno>
+ and <anno>Relation2</anno> on coordinates <anno>I</anno> and
+ <anno>J</anno>.</p>
<pre>
1> <input>R1 = sofs:relation([{a,x,1},{b,y,2}]),</input>
<input>R2 = sofs:relation([{1,f,g},{1,h,i},{2,3,4}]),</input>
@@ -1189,20 +1116,17 @@ true</pre>
</desc>
</func>
<func>
- <name>multiple_relative_product(TupleOfBinRels, BinRel1) -> BinRel2</name>
+ <name name="multiple_relative_product" arity="2"/>
<fsummary>Return the multiple relative product of a tuple of binary
relations and a relation.</fsummary>
- <type>
- <v>TupleOfBinRels = tuple-of(BinRel)</v>
- <v>BinRel = BinRel1 = BinRel2 = binary_relation()</v>
- </type>
- <desc>
- <p>If TupleOfBinRels is a non-empty tuple
- {R[1],&nbsp;...,&nbsp;R[n]} of binary relations and BinRel1
- is a binary relation, then BinRel2 is
+ <desc>
+ <p>If <anno>TupleOfBinRels</anno> is a non-empty tuple
+ {R[1],&nbsp;...,&nbsp;R[n]} of binary relations
+ and <anno>BinRel1</anno> is a binary relation,
+ then <anno>BinRel2</anno> is
the <seealso marker="#multiple_relative_product">multiple relative
product</seealso> of the ordered set
- (R[i],&nbsp;...,&nbsp;R[n]) and BinRel1.</p>
+ (R[i],&nbsp;...,&nbsp;R[n]) and <anno>BinRel1</anno>.</p>
<pre>
1> <input>Ri = sofs:relation([{a,1},{b,2},{c,3}]),</input>
<input>R = sofs:relation([{a,b},{b,c},{c,a}]),</input>
@@ -1212,29 +1136,21 @@ true</pre>
</desc>
</func>
<func>
- <name>no_elements(ASet) -> NoElements</name>
+ <name name="no_elements" arity="1"/>
<fsummary>Return the number of elements of a set.</fsummary>
- <type>
- <v>ASet = set() | ordset()</v>
- <v>NoElements = integer() >= 0 </v>
- </type>
<desc>
<p>Returns the number of elements of the ordered or unordered
- set ASet.</p>
+ set <anno>ASet</anno>.</p>
</desc>
</func>
<func>
- <name>partition(SetOfSets) -> Partition</name>
+ <name name="partition" arity="1"/>
<fsummary>Return the coarsest partition given a set of sets.</fsummary>
- <type>
- <v>SetOfSets = set_of_sets()</v>
- <v>Partition = set()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#partition">partition</seealso> of
- the union of the set of sets SetOfSets such that two
+ the union of the set of sets <anno>SetOfSets</anno> such that two
elements are considered equal if they belong to the same
- elements of SetOfSets.</p>
+ elements of <anno>SetOfSets</anno>.</p>
<pre>
1> <input>Sets1 = sofs:from_term([[a,b,c],[d,e,f],[g,h,i]]),</input>
<input>Sets2 = sofs:from_term([[b,c,d],[e,f,g],[h,i,j]]),</input>
@@ -1244,17 +1160,12 @@ true</pre>
</desc>
</func>
<func>
- <name>partition(SetFun, Set) -> Partition</name>
+ <name name="partition" arity="2"/>
<fsummary>Return a partition of a set.</fsummary>
- <type>
- <v>SetFun = set_fun()</v>
- <v>Partition = set()</v>
- <v>Set = set()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#partition">partition</seealso> of
- Set such that two elements are considered equal if the
- results of applying SetFun are equal.</p>
+ <anno>Set</anno> such that two elements are considered equal
+ if the results of applying <anno>SetFun</anno> are equal.</p>
<pre>
1> <input>Ss = sofs:from_term([[a],[b],[c,d],[e,f]]),</input>
<input>SetFun = fun(S) -> sofs:from_term(sofs:no_elements(S)) end,</input>
@@ -1264,19 +1175,16 @@ true</pre>
</desc>
</func>
<func>
- <name>partition(SetFun, Set1, Set2) -> {Set3, Set4}</name>
+ <name name="partition" arity="3"/>
<fsummary>Return a partition of a set.</fsummary>
- <type>
- <v>SetFun = set_fun()</v>
- <v>Set1 = Set2 = Set3 = Set4 = set()</v>
- </type>
<desc>
<p>Returns a pair of sets that, regarded as constituting a
set, forms a <seealso marker="#partition">partition</seealso> of
- Set1. If the
- result of applying SetFun to an element of Set1 yields an
- element in Set2, the element belongs to Set3, otherwise the
- element belongs to Set4.</p>
+ <anno>Set1</anno>. If the
+ result of applying <anno>SetFun</anno> to an element
+ of <anno>Set1</anno> yields an element in <anno>Set2</anno>,
+ the element belongs to <anno>Set3</anno>, otherwise the
+ element belongs to <anno>Set4</anno>.</p>
<pre>
1> <input>R1 = sofs:relation([{1,a},{2,b},{3,c}]),</input>
<input>S = sofs:set([2,4,6]),</input>
@@ -1289,21 +1197,17 @@ true</pre>
</desc>
</func>
<func>
- <name>partition_family(SetFun, Set) -> Family</name>
+ <name name="partition_family" arity="2"/>
<fsummary>Return a family indexing a partition.</fsummary>
- <type>
- <v>Family = family()</v>
- <v>SetFun = set_fun()</v>
- <v>Set = set()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#family">family</seealso>
- Family where the indexed set is
- a <seealso marker="#partition">partition</seealso> of Set
- such that two elements are considered equal if the results
- of applying SetFun are the same value i. This i is the index
- that Family maps onto
- the <seealso marker="#equivalence_class">equivalence
+ <anno>Family</anno> where the indexed set is
+ a <seealso marker="#partition">partition</seealso>
+ of <anno>Set</anno> such that two elements are considered
+ equal if the results of applying <anno>SetFun</anno> are the
+ same value i. This i is the index that <anno>Family</anno>
+ maps onto
+ the <seealso marker="#equivalence_class">equivalence
class</seealso>.</p>
<pre>
1> <input>S = sofs:relation([{a,a,a,a},{a,a,b,b},{a,b,b,b}]),</input>
@@ -1314,18 +1218,15 @@ true</pre>
</desc>
</func>
<func>
- <name>product(TupleOfSets) -> Relation</name>
+ <name name="product" arity="1"/>
<fsummary>Return the Cartesian product of a tuple of sets.</fsummary>
- <type>
- <v>Relation = relation()</v>
- <v>TupleOfSets = tuple-of(set())</v>
- </type>
<desc>
<p>Returns the <seealso marker="#Cartesian_product_tuple">Cartesian
product</seealso> of the non-empty tuple of sets
- TupleOfSets. If (x[1],&nbsp;...,&nbsp;x[n]) is an element of
- the n-ary relation Relation, then x[i] is drawn from element
- i of TupleOfSets.</p>
+ <anno>TupleOfSets</anno>. If (x[1],&nbsp;...,&nbsp;x[n]) is
+ an element of the n-ary relation <anno>Relation</anno>, then
+ x[i] is drawn from element i
+ of <anno>TupleOfSets</anno>.</p>
<pre>
1> <input>S1 = sofs:set([a,b]),</input>
<input>S2 = sofs:set([1,2]),</input>
@@ -1336,15 +1237,12 @@ true</pre>
</desc>
</func>
<func>
- <name>product(Set1, Set2) -> BinRel</name>
+ <name name="product" arity="2"/>
<fsummary>Return the Cartesian product of two sets.</fsummary>
- <type>
- <v>BinRel = binary_relation()</v>
- <v>Set1 = Set2 = set()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#Cartesian_product">Cartesian
- product</seealso> of Set1 and Set2.</p>
+ product</seealso> of <anno>Set1</anno>
+ and <anno>Set2</anno>.</p>
<pre>
1> <input>S1 = sofs:set([1,2]),</input>
<input>S2 = sofs:set([a,b]),</input>
@@ -1356,19 +1254,16 @@ true</pre>
</desc>
</func>
<func>
- <name>projection(SetFun, Set1) -> Set2</name>
+ <name name="projection" arity="2"/>
<fsummary>Return a set of substituted elements.</fsummary>
- <type>
- <v>SetFun = set_fun()</v>
- <v>Set1 = Set2 = set()</v>
- </type>
<desc>
<p>Returns the set created by substituting each element of
- Set1 by the result of applying SetFun to the element.</p>
- <p>If SetFun is a number i&nbsp;&gt;=&nbsp;1 and Set1 is a
- relation, then the returned set is
- the <seealso marker="#projection">projection</seealso> of Set1
- onto coordinate i.</p>
+ <anno>Set1</anno> by the result of
+ applying <anno>SetFun</anno> to the element.</p>
+ <p>If <anno>SetFun</anno> is a number i&nbsp;&gt;=&nbsp;1 and
+ <anno>Set1</anno> is a relation, then the returned set is
+ the <seealso marker="#projection">projection</seealso> of
+ <anno>Set1</anno> onto coordinate i.</p>
<pre>
1> <input>S1 = sofs:from_term([{1,a},{2,b},{3,a}]),</input>
<input>S2 = sofs:projection(2, S1),</input>
@@ -1377,15 +1272,11 @@ true</pre>
</desc>
</func>
<func>
- <name>range(BinRel) -> Set</name>
+ <name name="range" arity="1"/>
<fsummary>Return the range of a binary relation.</fsummary>
- <type>
- <v>BinRel = binary_relation()</v>
- <v>Set = set()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#range">range</seealso> of the
- binary relation BinRel.</p>
+ binary relation <anno>BinRel</anno>.</p>
<pre>
1> <input>R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]),</input>
<input>S = sofs:range(R),</input>
@@ -1394,41 +1285,33 @@ true</pre>
</desc>
</func>
<func>
- <name>relation(Tuples [, Type]) -> Relation</name>
+ <name name="relation" arity="1"/>
+ <name name="relation" arity="2"/>
<fsummary>Create a relation.</fsummary>
- <type>
- <v>N = integer()</v>
- <v>Type = N | type()</v>
- <v>Relation = relation()</v>
- <v>Tuples = [tuple()]</v>
- </type>
<desc>
<p>Creates a <seealso marker="#relation">relation</seealso>.
<c>relation(R,&nbsp;T)</c> is equivalent to
<c>from_term(R,&nbsp;T)</c>, if T is
a <seealso marker="#type">type</seealso> and the result is a
- relation. If Type is an integer N, then
+ relation. If <anno>Type</anno> is an integer N, then
<c>[{atom,&nbsp;...,&nbsp;atom}])</c>, where the size of the
tuple is N, is used as type of the relation. If no type is
- explicitly given, the size of the first tuple of Tuples is
+ explicitly given, the size of the first tuple of
+ <anno>Tuples</anno> is
used if there is such a tuple. <c>relation([])</c> is
equivalent to <c>relation([],&nbsp;2)</c>.</p>
</desc>
</func>
<func>
- <name>relation_to_family(BinRel) -> Family</name>
+ <name name="relation_to_family" arity="1"/>
<fsummary>Create a family from a binary relation.</fsummary>
- <type>
- <v>Family = family()</v>
- <v>BinRel = binary_relation()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#family">family</seealso>
- Family such that the index set is equal to
+ <anno>Family</anno> such that the index set is equal to
the <seealso marker="#domain">domain</seealso> of the binary
- relation BinRel, and Family[i] is
+ relation <anno>BinRel</anno>, and <anno>Family</anno>[i] is
the <seealso marker="#image">image</seealso> of the set of i
- under BinRel.</p>
+ under <anno>BinRel</anno>.</p>
<pre>
1> <input>R = sofs:relation([{b,1},{c,2},{c,3}]),</input>
<input>F = sofs:relation_to_family(R),</input>
@@ -1437,63 +1320,57 @@ true</pre>
</desc>
</func>
<func>
- <name>relative_product(TupleOfBinRels [, BinRel1]) -> BinRel2</name>
- <fsummary>Return the relative product of a tuple of binary relations
+ <name name="relative_product" arity="1"/>
+ <name name="relative_product" arity="2" clause_i="1"/>
+ <fsummary>Return the relative product of a list of binary relations
and a binary relation.</fsummary>
- <type>
- <v>TupleOfBinRels = tuple-of(BinRel)</v>
- <v>BinRel = BinRel1 = BinRel2 = binary_relation()</v>
- </type>
- <desc>
- <p>If TupleOfBinRels is a non-empty tuple
- {R[1],&nbsp;...,&nbsp;R[n]} of binary relations and BinRel1
- is a binary relation, then BinRel2 is
- the <seealso marker="#tuple_relative_product">relative
- product</seealso> of the ordered set (R[i],&nbsp;...,&nbsp;R[n])
- and BinRel1.</p>
- <p>If BinRel1 is omitted, the relation of equality between the
- elements of
- the <seealso marker="#Cartesian_product_tuple">Cartesian
- product</seealso> of the ranges of R[i],
+ <desc>
+ <p>If <anno>ListOfBinRels</anno> is a non-empty list
+ [R[1],&nbsp;...,&nbsp;R[n]] of binary relations and
+ <anno>BinRel1</anno>
+ is a binary relation, then <anno>BinRel2</anno> is the <seealso
+ marker="#tuple_relative_product">relative product</seealso>
+ of the ordered set (R[i],&nbsp;...,&nbsp;R[n]) and
+ <anno>BinRel1</anno>.</p>
+ <p>If <anno>BinRel1</anno> is omitted, the relation of equality
+ between the elements of
+ the <seealso marker="#Cartesian_product_tuple">Cartesian
+ product</seealso> of the ranges of R[i],
range&nbsp;R[1]&nbsp;&times;&nbsp;...&nbsp;&times;&nbsp;range&nbsp;R[n],
is used instead (intuitively, nothing is "lost").</p>
<pre>
1> <input>TR = sofs:relation([{1,a},{1,aa},{2,b}]),</input>
<input>R1 = sofs:relation([{1,u},{2,v},{3,c}]),</input>
-<input>R2 = sofs:relative_product({TR, R1}),</input>
+<input>R2 = sofs:relative_product([TR, R1]),</input>
<input>sofs:to_external(R2).</input>
[{1,{a,u}},{1,{aa,u}},{2,{b,v}}]</pre>
- <p>Note that <c>relative_product({R1},&nbsp;R2)</c> is
+ <p>Note that <c>relative_product([R1],&nbsp;R2)</c> is
different from <c>relative_product(R1,&nbsp;R2)</c>; the
- tuple of one element is not identified with the element
+ list of one element is not identified with the element
itself.</p>
</desc>
</func>
<func>
- <name>relative_product(BinRel1, BinRel2) -> BinRel3</name>
+ <name name="relative_product" arity="2" clause_i="2"/>
<fsummary>Return the relative product of
two binary relations.</fsummary>
- <type>
- <v>BinRel1 = BinRel2 = BinRel3 = binary_relation()</v>
- </type>
<desc>
<p><marker id="relprod_impl"></marker>Returns
the <seealso marker="#relative_product">relative
- product</seealso> of the binary relations BinRel1 and BinRel2.</p>
+ product</seealso> of the binary relations <anno>BinRel1</anno>
+ and <anno>BinRel2</anno>.</p>
</desc>
</func>
<func>
- <name>relative_product1(BinRel1, BinRel2) -> BinRel3</name>
+ <name name="relative_product1" arity="2"/>
<fsummary>Return the relative_product of
two binary relations.</fsummary>
- <type>
- <v>BinRel1 = BinRel2 = BinRel3 = binary_relation()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#relative_product">relative
product</seealso> of
the <seealso marker="#converse">converse</seealso> of the
- binary relation BinRel1 and the binary relation BinRel2.</p>
+ binary relation <anno>BinRel1</anno> and the binary
+ relation <anno>BinRel2</anno>.</p>
<pre>
1> <input>R1 = sofs:relation([{1,a},{1,aa},{2,b}]),</input>
<input>R2 = sofs:relation([{1,u},{2,v},{3,c}]),</input>
@@ -1505,15 +1382,12 @@ true</pre>
</desc>
</func>
<func>
- <name>restriction(BinRel1, Set) -> BinRel2</name>
+ <name name="restriction" arity="2"/>
<fsummary>Return a restriction of a binary relation.</fsummary>
- <type>
- <v>BinRel1 = BinRel2 = binary_relation()</v>
- <v>Set = set()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#restriction">restriction</seealso> of
- the binary relation BinRel1 to Set.</p>
+ the binary relation <anno>BinRel1</anno>
+ to <anno>Set</anno>.</p>
<pre>
1> <input>R1 = sofs:relation([{1,a},{2,b},{3,c}]),</input>
<input>S = sofs:set([1,2,4]),</input>
@@ -1523,15 +1397,12 @@ true</pre>
</desc>
</func>
<func>
- <name>restriction(SetFun, Set1, Set2) -> Set3</name>
+ <name name="restriction" arity="3"/>
<fsummary>Return a restriction of a set.</fsummary>
- <type>
- <v>SetFun = set_fun()</v>
- <v>Set1 = Set2 = Set3 = set()</v>
- </type>
<desc>
- <p>Returns a subset of Set1 containing those elements that
- yield an element in Set2 as the result of applying SetFun.</p>
+ <p>Returns a subset of <anno>Set1</anno> containing those
+ elements that yield an element in <anno>Set2</anno> as the
+ result of applying <anno>SetFun</anno>.</p>
<pre>
1> <input>S1 = sofs:relation([{1,a},{2,b},{3,c}]),</input>
<input>S2 = sofs:set([b,c,d]),</input>
@@ -1541,13 +1412,9 @@ true</pre>
</desc>
</func>
<func>
- <name>set(Terms [, Type]) -> Set</name>
+ <name name="set" arity="1"/>
+ <name name="set" arity="2"/>
<fsummary>Create a set of atoms or any type of sets.</fsummary>
- <type>
- <v>Set = set()</v>
- <v>Terms = [term()]</v>
- <v>Type = type()</v>
- </type>
<desc>
<p>Creates an <seealso marker="#sets_definition">unordered
set</seealso>. <c>set(L,&nbsp;T)</c> is equivalent to
@@ -1557,18 +1424,16 @@ true</pre>
</desc>
</func>
<func>
- <name>specification(Fun, Set1) -> Set2</name>
+ <name name="specification" arity="2"/>
<fsummary>Select a subset using a predicate.</fsummary>
- <type>
- <v>Fun = spec_fun()</v>
- <v>Set1 = Set2 = set()</v>
- </type>
<desc>
- <p>Returns the set containing every element of Set1 for which
- Fun returns <c>true</c>. If Fun is a tuple
+ <p>Returns the set containing every element
+ of <anno>Set1</anno> for which <anno>Fun</anno>
+ returns <c>true</c>. If <anno>Fun</anno> is a tuple
<c>{external,&nbsp;Fun2}</c>, Fun2 is applied to the
<seealso marker="#external_set">external set</seealso> of
- each element, otherwise Fun is applied to each element.</p>
+ each element, otherwise <anno>Fun</anno> is applied to each
+ element.</p>
<pre>
1> <input>R1 = sofs:relation([{a,1},{b,2}]),</input>
<input>R2 = sofs:relation([{x,1},{x,2},{y,3}]),</input>
@@ -1579,15 +1444,13 @@ true</pre>
</desc>
</func>
<func>
- <name>strict_relation(BinRel1) -> BinRel2</name>
+ <name name="strict_relation" arity="1"/>
<fsummary>Return the strict relation corresponding to
a given relation.</fsummary>
- <type>
- <v>BinRel1 = BinRel2 = binary_relation()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#strict_relation">strict
- relation</seealso> corresponding to the binary relation BinRel1.</p>
+ relation</seealso> corresponding to the binary
+ relation <anno>BinRel1</anno>.</p>
<pre>
1> <input>R1 = sofs:relation([{1,1},{1,2},{2,1},{2,2}]),</input>
<input>R2 = sofs:strict_relation(R1),</input>
@@ -1596,16 +1459,13 @@ true</pre>
</desc>
</func>
<func>
- <name>substitution(SetFun, Set1) -> Set2</name>
+ <name name="substitution" arity="2"/>
<fsummary>Return a function with a given set as domain.</fsummary>
- <type>
- <v>SetFun = set_fun()</v>
- <v>Set1 = Set2 = set()</v>
- </type>
- <desc>
- <p>Returns a function, the domain of which is Set1. The value
- of an element of the domain is the result of applying SetFun
- to the element.</p>
+ <desc>
+ <p>Returns a function, the domain of which
+ is <anno>Set1</anno>. The value of an element of the domain
+ is the result of applying <anno>SetFun</anno> to the
+ element.</p>
<pre>
1> <input>L = [{a,1},{b,2}].</input>
[{a,1},{b,2}]
@@ -1647,14 +1507,12 @@ images2(SetOfSets, BinRel) ->
</desc>
</func>
<func>
- <name>symdiff(Set1, Set2) -> Set3</name>
+ <name name="symdiff" arity="2"/>
<fsummary>Return the symmetric difference of two sets.</fsummary>
- <type>
- <v>Set1 = Set2 = Set3 = set()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#symmetric_difference">symmetric
- difference</seealso> (or the Boolean sum) of Set1 and Set2.</p>
+ difference</seealso> (or the Boolean sum)
+ of <anno>Set1</anno> and <anno>Set2</anno>.</p>
<pre>
1> <input>S1 = sofs:set([1,2,3]),</input>
<input>S2 = sofs:set([2,3,4]),</input>
@@ -1664,88 +1522,67 @@ images2(SetOfSets, BinRel) ->
</desc>
</func>
<func>
- <name>symmetric_partition(Set1, Set2) -> {Set3, Set4, Set5}</name>
+ <name name="symmetric_partition" arity="2"/>
<fsummary>Return a partition of two sets.</fsummary>
- <type>
- <v>Set1 = Set2 = Set3 = Set4 = Set5 = set()</v>
- </type>
<desc>
- <p>Returns a triple of sets: Set3 contains the elements
- of Set1 that do not belong to Set2; Set4 contains the
- elements of Set1 that belong to Set2; Set5 contains the
- elements of Set2 that do not belong to Set1.</p>
+ <p>Returns a triple of sets: <anno>Set3</anno> contains the
+ elements of <anno>Set1</anno> that do not belong
+ to <anno>Set2</anno>; <anno>Set4</anno> contains the
+ elements of <anno>Set1</anno> that belong
+ to <anno>Set2</anno>; <anno>Set5</anno> contains the
+ elements of <anno>Set2</anno> that do not belong
+ to <anno>Set1</anno>.</p>
</desc>
</func>
<func>
- <name>to_external(AnySet) -> ExternalSet</name>
+ <name name="to_external" arity="1"/>
<fsummary>Return the elements of a set.</fsummary>
- <type>
- <v>ExternalSet = external_set()</v>
- <v>AnySet = anyset()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#external_set">external
set</seealso> of an atomic, ordered or unordered set.</p>
</desc>
</func>
<func>
- <name>to_sets(ASet) -> Sets</name>
+ <name name="to_sets" arity="1"/>
<fsummary>Return a list or a tuple of the elements of set.</fsummary>
- <type>
- <v>ASet = set() | ordset()</v>
- <v>Sets = tuple_of(AnySet) | [AnySet]</v>
- </type>
<desc>
- <p>Returns the elements of the ordered set ASet as a tuple of
- sets, and the elements of the unordered set ASet as a sorted
- list of sets without duplicates.</p>
+ <p>Returns the elements of the ordered set <anno>ASet</anno>
+ as a tuple of sets, and the elements of the unordered set
+ <anno>ASet</anno> as a sorted list of sets without
+ duplicates.</p>
</desc>
</func>
<func>
- <name>type(AnySet) -> Type</name>
+ <name name="type" arity="1"/>
<fsummary>Return the type of a set.</fsummary>
- <type>
- <v>AnySet = anyset()</v>
- <v>Type = type()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#type">type</seealso> of an
atomic, ordered or unordered set.</p>
</desc>
</func>
<func>
- <name>union(SetOfSets) -> Set</name>
+ <name name="union" arity="1"/>
<fsummary>Return the union of a set of sets.</fsummary>
- <type>
- <v>Set = set()</v>
- <v>SetOfSets = set_of_sets()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#union_n">union</seealso> of the
- set of sets SetOfSets.</p>
+ set of sets <anno>SetOfSets</anno>.</p>
</desc>
</func>
<func>
- <name>union(Set1, Set2) -> Set3</name>
+ <name name="union" arity="2"/>
<fsummary>Return the union of two sets.</fsummary>
- <type>
- <v>Set1 = Set2 = Set3 = set()</v>
- </type>
<desc>
<p>Returns the <seealso marker="#union">union</seealso> of
- Set1 and Set2.</p>
+ <anno>Set1</anno> and <anno>Set2</anno>.</p>
</desc>
</func>
<func>
- <name>union_of_family(Family) -> Set</name>
+ <name name="union_of_family" arity="1"/>
<fsummary>Return the union of a family.</fsummary>
- <type>
- <v>Family = family()</v>
- <v>Set = set()</v>
- </type>
<desc>
<p>Returns the union of
- the <seealso marker="#family">family</seealso> Family.</p>
+ the <seealso marker="#family">family</seealso> <anno>Family</anno>.
+ </p>
<pre>
1> <input>F = sofs:family([{a,[0,2,4]},{b,[0,1,2]},{c,[2,3]}]),</input>
<input>S = sofs:union_of_family(F),</input>
@@ -1754,17 +1591,15 @@ images2(SetOfSets, BinRel) ->
</desc>
</func>
<func>
- <name>weak_relation(BinRel1) -> BinRel2</name>
+ <name name="weak_relation" arity="1"/>
<fsummary>Return the weak relation corresponding to
a given relation.</fsummary>
- <type>
- <v>BinRel1 = BinRel2 = binary_relation()</v>
- </type>
<desc>
<p>Returns a subset S of the <seealso marker="#weak_relation">weak
relation</seealso> W
- corresponding to the binary relation BinRel1. Let F be the
- <seealso marker="#field">field</seealso> of BinRel1. The
+ corresponding to the binary relation <anno>BinRel1</anno>.
+ Let F be the <seealso marker="#field">field</seealso> of
+ <anno>BinRel1</anno>. The
subset S is defined so that x S y if x W y for some x in F
and for some y in F.</p>
<pre>
diff --git a/lib/stdlib/doc/src/specs.xml b/lib/stdlib/doc/src/specs.xml
new file mode 100644
index 0000000000..98338b5ec2
--- /dev/null
+++ b/lib/stdlib/doc/src/specs.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="latin1" ?>
+<specs xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="../specs/specs_array.xml"/>
+ <xi:include href="../specs/specs_base64.xml"/>
+ <xi:include href="../specs/specs_beam_lib.xml"/>
+ <xi:include href="../specs/specs_binary.xml"/>
+ <xi:include href="../specs/specs_c.xml"/>
+ <xi:include href="../specs/specs_calendar.xml"/>
+ <xi:include href="../specs/specs_dets.xml"/>
+ <xi:include href="../specs/specs_dict.xml"/>
+ <xi:include href="../specs/specs_digraph.xml"/>
+ <xi:include href="../specs/specs_digraph_utils.xml"/>
+ <xi:include href="../specs/specs_epp.xml"/>
+ <xi:include href="../specs/specs_erl_eval.xml"/>
+ <xi:include href="../specs/specs_erl_expand_records.xml"/>
+ <xi:include href="../specs/specs_erl_id_trans.xml"/>
+ <xi:include href="../specs/specs_erl_internal.xml"/>
+ <xi:include href="../specs/specs_erl_lint.xml"/>
+ <xi:include href="../specs/specs_erl_parse.xml"/>
+ <xi:include href="../specs/specs_erl_pp.xml"/>
+ <xi:include href="../specs/specs_erl_scan.xml"/>
+ <xi:include href="../specs/specs_erl_tar.xml"/>
+ <xi:include href="../specs/specs_ets.xml"/>
+ <xi:include href="../specs/specs_file_sorter.xml"/>
+ <xi:include href="../specs/specs_filelib.xml"/>
+ <xi:include href="../specs/specs_filename.xml"/>
+ <xi:include href="../specs/specs_gb_sets.xml"/>
+ <xi:include href="../specs/specs_gb_trees.xml"/>
+ <xi:include href="../specs/specs_gen_event.xml"/>
+ <xi:include href="../specs/specs_gen_fsm.xml"/>
+ <xi:include href="../specs/specs_gen_server.xml"/>
+ <xi:include href="../specs/specs_io.xml"/>
+ <xi:include href="../specs/specs_io_lib.xml"/>
+ <xi:include href="../specs/specs_lib.xml"/>
+ <xi:include href="../specs/specs_lists.xml"/>
+ <xi:include href="../specs/specs_log_mf_h.xml"/>
+ <xi:include href="../specs/specs_math.xml"/>
+ <xi:include href="../specs/specs_ms_transform.xml"/>
+ <xi:include href="../specs/specs_orddict.xml"/>
+ <xi:include href="../specs/specs_ordsets.xml"/>
+ <xi:include href="../specs/specs_pg.xml"/>
+ <xi:include href="../specs/specs_pool.xml"/>
+ <xi:include href="../specs/specs_proc_lib.xml"/>
+ <xi:include href="../specs/specs_proplists.xml"/>
+ <xi:include href="../specs/specs_qlc.xml"/>
+ <xi:include href="../specs/specs_queue.xml"/>
+ <xi:include href="../specs/specs_random.xml"/>
+ <xi:include href="../specs/specs_re.xml"/>
+ <xi:include href="../specs/specs_regexp.xml"/>
+ <xi:include href="../specs/specs_sets.xml"/>
+ <xi:include href="../specs/specs_shell.xml"/>
+ <xi:include href="../specs/specs_shell_default.xml"/>
+ <xi:include href="../specs/specs_slave.xml"/>
+ <xi:include href="../specs/specs_sofs.xml"/>
+ <xi:include href="../specs/specs_string.xml"/>
+ <xi:include href="../specs/specs_supervisor.xml"/>
+ <xi:include href="../specs/specs_supervisor_bridge.xml"/>
+ <xi:include href="../specs/specs_sys.xml"/>
+ <xi:include href="../specs/specs_timer.xml"/>
+ <xi:include href="../specs/specs_unicode.xml"/>
+ <xi:include href="../specs/specs_win32reg.xml"/>
+ <xi:include href="../specs/specs_zip.xml"/>
+</specs>
diff --git a/lib/stdlib/doc/src/string.xml b/lib/stdlib/doc/src/string.xml
index de1b99a2d5..48867ffe72 100644
--- a/lib/stdlib/doc/src/string.xml
+++ b/lib/stdlib/doc/src/string.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -38,65 +38,46 @@
</description>
<funcs>
<func>
- <name>len(String) -> Length</name>
+ <name name="len" arity="1"/>
<fsummary>Return the length of a string</fsummary>
- <type>
- <v>String = string()</v>
- <v>Length = integer()</v>
- </type>
<desc>
<p>Returns the number of characters in the string.</p>
</desc>
</func>
<func>
- <name>equal(String1, String2) -> bool()</name>
+ <name name="equal" arity="2"/>
<fsummary>Test string equality</fsummary>
- <type>
- <v>String1 = String2 = string()</v>
- </type>
<desc>
<p>Tests whether two strings are equal. Returns <c>true</c> if
they are, otherwise <c>false</c>.</p>
</desc>
</func>
<func>
- <name>concat(String1, String2) -> String3</name>
+ <name name="concat" arity="2"/>
<fsummary>Concatenate two strings</fsummary>
- <type>
- <v>String1 = String2 = String3 = string()</v>
- </type>
<desc>
<p>Concatenates two strings to form a new string. Returns the
new string.</p>
</desc>
</func>
<func>
- <name>chr(String, Character) -> Index</name>
- <name>rchr(String, Character) -> Index</name>
+ <name name="chr" arity="2"/>
+ <name name="rchr" arity="2"/>
<fsummary>Return the index of the first/last occurrence of<c>Character</c>in <c>String</c></fsummary>
- <type>
- <v>String = string()</v>
- <v>Character = char()</v>
- <v>Index = integer()</v>
- </type>
<desc>
<p>Returns the index of the first/last occurrence of
- <c>Character</c> in <c>String</c>. <c>0</c> is returned if <c>Character</c> does not
+ <c><anno>Character</anno></c> in <c><anno>String</anno></c>. <c>0</c> is returned if <c><anno>Character</anno></c> does not
occur.</p>
</desc>
</func>
<func>
- <name>str(String, SubString) -> Index</name>
- <name>rstr(String, SubString) -> Index</name>
+ <name name="str" arity="2"/>
+ <name name="rstr" arity="2"/>
<fsummary>Find the index of a substring</fsummary>
- <type>
- <v>String = SubString = string()</v>
- <v>Index = integer()</v>
- </type>
<desc>
<p>Returns the position where the first/last occurrence of
- <c>SubString</c> begins in <c>String</c>. <c>0</c> is returned if <c>SubString</c>
- does not exist in <c>String</c>.
+ <c><anno>SubString</anno></c> begins in <c><anno>String</anno></c>. <c>0</c> is returned if <c><anno>SubString</anno></c>
+ does not exist in <c><anno>String</anno></c>.
For example:</p>
<code type="none">
> string:str(" Hello Hello World World ", "Hello World").
@@ -104,17 +85,13 @@
</desc>
</func>
<func>
- <name>span(String, Chars) -> Length </name>
- <name>cspan(String, Chars) -> Length</name>
+ <name name="span" arity="2"/>
+ <name name="cspan" arity="2"/>
<fsummary>Span characters at start of string</fsummary>
- <type>
- <v>String = Chars = string()</v>
- <v>Length = integer()</v>
- </type>
<desc>
<p>Returns the length of the maximum initial segment of
- String, which consists entirely of characters from (not
- from) Chars.</p>
+ <c><anno>String</anno></c>, which consists entirely of characters from (not
+ from) <c><anno>Chars</anno></c>.</p>
<p>For example:</p>
<code type="none">
> string:span("\t abcdef", " \t").
@@ -124,17 +101,13 @@
</desc>
</func>
<func>
- <name>substr(String, Start) -> SubString</name>
- <name>substr(String, Start, Length) -> Substring</name>
+ <name name="substr" arity="2"/>
+ <name name="substr" arity="3"/>
<fsummary>Return a substring of <c>String</c></fsummary>
- <type>
- <v>String = SubString = string()</v>
- <v>Start = Length = integer()</v>
- </type>
<desc>
- <p>Returns a substring of <c>String</c>, starting at the
- position <c>Start</c>, and ending at the end of the string or
- at length <c>Length</c>.</p>
+ <p>Returns a substring of <c><anno>String</anno></c>, starting at the
+ position <c><anno>Start</anno></c>, and ending at the end of the string or
+ at length <c><anno>Length</anno></c>.</p>
<p>For example:</p>
<code type="none">
> substr("Hello World", 4, 5).
@@ -142,15 +115,11 @@
</desc>
</func>
<func>
- <name>tokens(String, SeparatorList) -> Tokens</name>
+ <name name="tokens" arity="2"/>
<fsummary>Split string into tokens</fsummary>
- <type>
- <v>String = SeparatorList = string()</v>
- <v>Tokens = [string()]</v>
- </type>
<desc>
- <p>Returns a list of tokens in <c>String</c>, separated by the
- characters in <c>SeparatorList</c>.</p>
+ <p>Returns a list of tokens in <c><anno>String</anno></c>, separated by the
+ characters in <c><anno>SeparatorList</anno></c>.</p>
<p>For example:</p>
<code type="none">
> tokens("abc defxxghix jkl", "x ").
@@ -158,15 +127,11 @@
</desc>
</func>
<func>
- <name>join(StringList, Separator) -> String</name>
+ <name name="join" arity="2"/>
<fsummary>Join a list of strings with separator</fsummary>
- <type>
- <v>StringList = [string()]</v>
- <v>Separator = string()</v>
- </type>
<desc>
- <p>Returns a string with the elements of <c>StringList</c>
- separated by the string in <c>Seperator</c>.</p>
+ <p>Returns a string with the elements of <c><anno>StringList</anno></c>
+ separated by the string in <c><anno>Separator</anno></c>.</p>
<p>For example:</p>
<code type="none">
> join(["one", "two", "three"], ", ").
@@ -174,44 +139,30 @@
</desc>
</func>
<func>
- <name>chars(Character, Number) -> String</name>
- <name>chars(Character, Number, Tail) -> String</name>
+ <name name="chars" arity="2"/>
+ <name name="chars" arity="3"/>
<fsummary>Returns a string consisting of numbers of characters</fsummary>
- <type>
- <v>Character = char()</v>
- <v>Number = integer()</v>
- <v>String = string()</v>
- </type>
<desc>
- <p>Returns a string consisting of <c>Number</c> of characters
- <c>Character</c>. Optionally, the string can end with the
- string <c>Tail</c>.</p>
+ <p>Returns a string consisting of <c><anno>Number</anno></c> of characters
+ <c><anno>Character</anno></c>. Optionally, the string can end with the
+ string <c><anno>Tail</anno></c>.</p>
</desc>
</func>
<func>
- <name>copies(String, Number) -> Copies</name>
+ <name name="copies" arity="2"/>
<fsummary>Copy a string</fsummary>
- <type>
- <v>String = Copies = string()</v>
- <v>Number = integer()</v>
- </type>
<desc>
- <p>Returns a string containing <c>String</c> repeated
- <c>Number</c> times.</p>
+ <p>Returns a string containing <c><anno>String</anno></c> repeated
+ <c><anno>Number</anno></c> times.</p>
</desc>
</func>
<func>
- <name>words(String) -> Count</name>
- <name>words(String, Character) -> Count</name>
+ <name name="words" arity="1"/>
+ <name name="words" arity="2"/>
<fsummary>Count blank separated words</fsummary>
- <type>
- <v>String = string()</v>
- <v>Character = char()</v>
- <v>Count = integer()</v>
- </type>
<desc>
- <p>Returns the number of words in <c>String</c>, separated by
- blanks or <c>Character</c>.</p>
+ <p>Returns the number of words in <c><anno>String</anno></c>, separated by
+ blanks or <c><anno>Character</anno></c>.</p>
<p>For example:</p>
<code type="none">
> words(" Hello old boy!", $o).
@@ -219,17 +170,12 @@
</desc>
</func>
<func>
- <name>sub_word(String, Number) -> Word</name>
- <name>sub_word(String, Number, Character) -> Word</name>
+ <name name="sub_word" arity="2"/>
+ <name name="sub_word" arity="3"/>
<fsummary>Extract subword</fsummary>
- <type>
- <v>String = Word = string()</v>
- <v>Character = char()</v>
- <v>Number = integer()</v>
- </type>
<desc>
- <p>Returns the word in position <c>Number</c> of <c>String</c>.
- Words are separated by blanks or <c>Character</c>s.</p>
+ <p>Returns the word in position <c><anno>Number</anno></c> of <c><anno>String</anno></c>.
+ Words are separated by blanks or <c><anno>Character</anno></c>s.</p>
<p>For example:</p>
<code type="none">
> string:sub_word(" Hello old boy !",3,$o).
@@ -237,19 +183,14 @@
</desc>
</func>
<func>
- <name>strip(String) -> Stripped</name>
- <name>strip(String, Direction) -> Stripped</name>
- <name>strip(String, Direction, Character) -> Stripped</name>
+ <name name="strip" arity="1"/>
+ <name name="strip" arity="2"/>
+ <name name="strip" arity="3"/>
<fsummary>Strip leading or trailing characters</fsummary>
- <type>
- <v>String = Stripped = string()</v>
- <v>Direction = left | right | both</v>
- <v>Character = char()</v>
- </type>
<desc>
<p>Returns a string, where leading and/or trailing blanks or a
- number of <c>Character</c> have been removed.
- <c>Direction</c> can be <c>left</c>, <c>right</c>, or
+ number of <c><anno>Character</anno></c> have been removed.
+ <c><anno>Direction</anno></c> can be <c>left</c>, <c>right</c>, or
<c>both</c> and indicates from which direction blanks are to be
removed. The function <c>strip/1</c> is equivalent to
<c>strip(String, both)</c>.</p>
@@ -260,19 +201,14 @@
</desc>
</func>
<func>
- <name>left(String, Number) -> Left</name>
- <name>left(String, Number, Character) -> Left</name>
+ <name name="left" arity="2"/>
+ <name name="left" arity="3"/>
<fsummary>Adjust left end of string</fsummary>
- <type>
- <v>String = Left = string()</v>
- <v>Character = char</v>
- <v>Number = integer()</v>
- </type>
<desc>
- <p>Returns the <c>String</c> with the length adjusted in
- accordance with <c>Number</c>. The left margin is
- fixed. If the <c>length(String)</c> &lt; <c>Number</c>,
- <c>String</c> is padded with blanks or <c>Character</c>s.</p>
+ <p>Returns the <c><anno>String</anno></c> with the length adjusted in
+ accordance with <c><anno>Number</anno></c>. The left margin is
+ fixed. If the <c>length(<anno>String</anno>)</c> &lt; <c><anno>Number</anno></c>,
+ <c><anno>String</anno></c> is padded with blanks or <c><anno>Character</anno></c>s.</p>
<p>For example:</p>
<code type="none">
> string:left("Hello",10,$.).
@@ -280,19 +216,14 @@
</desc>
</func>
<func>
- <name>right(String, Number) -> Right</name>
- <name>right(String, Number, Character) -> Right</name>
+ <name name="right" arity="2"/>
+ <name name="right" arity="3"/>
<fsummary>Adjust right end of string</fsummary>
- <type>
- <v>String = Right = string()</v>
- <v>Character = char</v>
- <v>Number = integer()</v>
- </type>
<desc>
- <p>Returns the <c>String</c> with the length adjusted in
- accordance with <c>Number</c>. The right margin is
- fixed. If the length of <c>(String)</c> &lt; <c>Number</c>,
- <c>String</c> is padded with blanks or <c>Character</c>s.</p>
+ <p>Returns the <c><anno>String</anno></c> with the length adjusted in
+ accordance with <c><anno>Number</anno></c>. The right margin is
+ fixed. If the length of <c>(<anno>String</anno>)</c> &lt; <c><anno>Number</anno></c>,
+ <c><anno>String</anno></c> is padded with blanks or <c><anno>Character</anno></c>s.</p>
<p>For example:</p>
<code type="none">
> string:right("Hello", 10, $.).
@@ -300,32 +231,23 @@
</desc>
</func>
<func>
- <name>centre(String, Number) -> Centered</name>
- <name>centre(String, Number, Character) -> Centered</name>
+ <name name="centre" arity="2"/>
+ <name name="centre" arity="3"/>
<fsummary>Center a string</fsummary>
- <type>
- <v>String = Centered = string()</v>
- <v>Character = char</v>
- <v>Number = integer()</v>
- </type>
<desc>
- <p>Returns a string, where <c>String</c> is centred in the
+ <p>Returns a string, where <c><anno>String</anno></c> is centred in the
string and surrounded by blanks or characters. The resulting
- string will have the length <c>Number</c>.</p>
+ string will have the length <c><anno>Number</anno></c>.</p>
</desc>
</func>
<func>
- <name>sub_string(String, Start) -> SubString</name>
- <name>sub_string(String, Start, Stop) -> SubString</name>
+ <name name="sub_string" arity="2"/>
+ <name name="sub_string" arity="3"/>
<fsummary>Extract a substring</fsummary>
- <type>
- <v>String = SubString = string()</v>
- <v>Start = Stop = integer()</v>
- </type>
<desc>
- <p>Returns a substring of <c>String</c>, starting at the
- position <c>Start</c> to the end of the string, or to and
- including the <c>Stop</c> position.</p>
+ <p>Returns a substring of <c><anno>String</anno></c>, starting at the
+ position <c><anno>Start</anno></c> to the end of the string, or to and
+ including the <c><anno>Stop</anno></c> position.</p>
<p>For example:</p>
<code type="none">
sub_string("Hello World", 4, 8).
@@ -383,15 +305,15 @@ sub_string("Hello World", 4, 8).
</desc>
</func>
<func>
- <name>to_lower(String) -> Result</name>
- <name>to_lower(Char) -> CharResult</name>
- <name>to_upper(String) -> Result</name>
- <name>to_upper(Char) -> CharResult</name>
+ <name name="to_lower" arity="1" clause_i="1"/>
+ <name name="to_lower" arity="1" clause_i="2"/>
+ <name name="to_upper" arity="1" clause_i="1"/>
+ <name name="to_upper" arity="1" clause_i="2"/>
<fsummary>Convert case of string (ISO/IEC 8859-1)</fsummary>
- <type>
- <v>String = Result = string()</v>
- <v>Char = CharResult = integer()</v>
- </type>
+ <type variable="String" name_i="1"/>
+ <type variable="Result" name_i="1"/>
+ <type variable="Char"/>
+ <type variable="CharResult"/>
<desc>
<p>The given string or character is case-converted. Note that
the supported character set is ISO/IEC 8859-1 (a.k.a. Latin 1),
diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml
index 45fa0847a8..ec607d6e4c 100644
--- a/lib/stdlib/doc/src/supervisor.xml
+++ b/lib/stdlib/doc/src/supervisor.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2010</year>
+ <year>1996</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -59,7 +59,6 @@
processes are started in order from left to right according to
this list. When the supervisor terminates, it first terminates
its child processes in reversed start order, from right to left.</p>
- <p></p>
<p>A supervisor can have one of the following <em>restart strategies</em>:</p>
<list type="bulleted">
<item>
@@ -83,11 +82,17 @@
supervisor, where all child processes are dynamically added
instances of the same process type, i.e. running the same
code.</p>
- <p>The functions <c>terminate_child/2</c>, <c>delete_child/2</c>
+ <p>The functions <c>delete_child/2</c>
and <c>restart_child/2</c> are invalid for
<c>simple_one_for_one</c> supervisors and will return
<c>{error,simple_one_for_one}</c> if the specified supervisor
uses this restart strategy.</p>
+ <p>The function <c>terminate_child/2</c> can be used for
+ children under <c>simple_one_for_one</c> supervisors by
+ giving the child's <c>pid()</c> as the second argument. If
+ instead the child specification identifier is used,
+ <c>terminate_child/2</c> will return
+ <c>{error,simple_one_for_one}</c>.</p>
</item>
</list>
<p>To prevent a supervisor from getting into an infinite loop of
@@ -144,9 +149,12 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
<p><c>Restart</c> defines when a terminated child process
should be restarted. A <c>permanent</c> child process should
always be restarted, a <c>temporary</c> child process should
- never be restarted and a <c>transient</c> child process
- should be restarted only if it terminates abnormally, i.e.
- with another exit reason than <c>normal</c>.</p>
+ never be restarted (even when the supervisor's restart strategy
+ is <c>rest_for_one</c> or <c>one_for_all</c> and a sibling's
+ death causes the temporary process to be terminated) and a
+ <c>transient</c> child process should be restarted only if
+ it terminates abnormally, i.e. with another exit reason
+ than <c>normal</c>.</p>
</item>
<item>
<p><c>Shutdown</c> defines how a child process should be
@@ -193,51 +201,81 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
</item>
</list>
</section>
+ <datatypes>
+ <datatype>
+ <name name="child"/>
+ </datatype>
+ <datatype>
+ <name name="child_id"/>
+ <desc><p>Not a <c>pid()</c>.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="child_spec"/>
+ </datatype>
+ <datatype>
+ <name name="mfargs"/>
+ <desc><p><c>A</c> (the argument list) has the value
+ <c>undefined</c> if <c>Restart</c> is <c>temporary</c>.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="modules"/>
+ </datatype>
+ <datatype>
+ <name name="restart"/>
+ </datatype>
+ <datatype>
+ <name name="shutdown"/>
+ </datatype>
+ <datatype>
+ <name name="strategy"/>
+ </datatype>
+ <datatype>
+ <name name="sup_ref"/>
+ </datatype>
+ <datatype>
+ <name name="worker"/>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>start_link(Module, Args) -> Result</name>
- <name>start_link(SupName, Module, Args) -> Result</name>
+ <name name="start_link" arity="2"/>
+ <name name="start_link" arity="3"/>
<fsummary>Create a supervisor process.</fsummary>
- <type>
- <v>SupName = {local,Name} | {global,Name}</v>
- <v>&nbsp;Name = atom()</v>
- <v>Module = atom()</v>
- <v>Args = term()</v>
- <v>Result = {ok,Pid} | ignore | {error,Error}</v>
- <v>&nbsp;Pid = pid()</v>
- <v>&nbsp;Error = {already_started,Pid}} | shutdown | term()</v>
- </type>
+ <type name="startlink_ret"/>
+ <type name="startlink_err"/>
+ <type name="sup_name"/>
<desc>
<p>Creates a supervisor process as part of a supervision tree.
The function will, among other things, ensure that
the supervisor is linked to the calling process (its
supervisor).</p>
- <p>The created supervisor process calls <c>Module:init/1</c> to
+ <p>The created supervisor process calls <c><anno>Module</anno>:init/1</c> to
find out about restart strategy, maximum restart frequency
and child processes. To ensure a synchronized start-up
procedure, <c>start_link/2,3</c> does not return until
- <c>Module:init/1</c> has returned and all child processes
+ <c><anno>Module</anno>:init/1</c> has returned and all child processes
have been started.</p>
- <p>If <c>SupName={local,Name}</c> the supervisor is registered
+ <p>If <c><anno>SupName</anno>={local,Name}</c> the supervisor is registered
locally as <c>Name</c> using <c>register/2</c>. If
- <c>SupName={global,Name}</c> the supervisor is registered
+ <c><anno>SupName</anno>={global,Name}</c> the supervisor is registered
globally as <c>Name</c> using <c>global:register_name/2</c>.
If no name is provided, the supervisor is not registered.</p>
- <p><c>Module</c> is the name of the callback module.</p>
- <p><c>Args</c> is an arbitrary term which is passed as
- the argument to <c>Module:init/1</c>.</p>
+ <p><c><anno>Module</anno></c> is the name of the callback module.</p>
+ <p><c><anno>Args</anno></c> is an arbitrary term which is passed as
+ the argument to <c><anno>Module</anno>:init/1</c>.</p>
<p>If the supervisor and its child processes are successfully
created (i.e. if all child process start functions return
<c>{ok,Child}</c>, <c>{ok,Child,Info}</c>, or <c>ignore</c>)
the function returns <c>{ok,Pid}</c>, where <c>Pid</c> is
the pid of the supervisor. If there already exists a process
- with the specified <c>SupName</c> the function returns
+ with the specified <c><anno>SupName</anno></c> the function returns
<c>{error,{already_started,Pid}}</c>, where <c>Pid</c> is
the pid of that process.</p>
- <p>If <c>Module:init/1</c> returns <c>ignore</c>, this function
+ <p>If <c><anno>Module</anno>:init/1</c> returns <c>ignore</c>, this function
returns <c>ignore</c> as well and the supervisor terminates
with reason <c>normal</c>.
- If <c>Module:init/1</c> fails or returns an incorrect value,
+ If <c><anno>Module</anno>:init/1</c> fails or returns an incorrect value,
this function returns <c>{error,Term}</c> where <c>Term</c>
is a term with information about the error, and the supervisor
terminates with reason <c>Term</c>.</p>
@@ -249,21 +287,15 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
</desc>
</func>
<func>
- <name>start_child(SupRef, ChildSpec) -> Result</name>
+ <name name="start_child" arity="2"/>
<fsummary>Dynamically add a child process to a supervisor.</fsummary>
- <type>
- <v>SupRef = Name | {Name,Node} | {global,Name} | pid()</v>
- <v>&nbsp;Name = Node = atom()</v>
- <v>ChildSpec = child_spec() | [term()]</v>
- <v>Result = {ok,Child} | {ok,Child,Info} | {error,Error}</v>
- <v>&nbsp;Child = pid() | undefined</v>
- <v>&nbsp;Info = term()</v>
- <v>&nbsp;Error = already_present | {already_started,Child} | term()</v>
- </type>
+ <type name="child_spec"/>
+ <type name="startchild_ret"/>
+ <type name="startchild_err"/>
<desc>
<p>Dynamically adds a child specification to the supervisor
- <c>SupRef</c> which starts the corresponding child process.</p>
- <p><c>SupRef</c> can be:</p>
+ <c><anno>SupRef</anno></c> which starts the corresponding child process.</p>
+ <p><marker id="SupRef"><c><anno>SupRef</anno></c></marker> can be:</p>
<list type="bulleted">
<item>the pid,</item>
<item><c>Name</c>, if the supervisor is locally registered,</item>
@@ -272,26 +304,26 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
<item><c>{global,Name}</c>, if the supervisor is globally
registered.</item>
</list>
- <p><c>ChildSpec</c> should be a valid child specification
+ <p><c><anno>ChildSpec</anno></c> should be a valid child specification
(unless the supervisor is a <c>simple_one_for_one</c>
supervisor, see below). The child process will be started by
using the start function as defined in the child
specification.</p>
<p>If the case of a <c>simple_one_for_one</c> supervisor,
the child specification defined in <c>Module:init/1</c> will
- be used and <c>ChildSpec</c> should instead be an arbitrary
- list of terms <c>List</c>. The child process will then be
- started by appending <c>List</c> to the existing start
+ be used and <c><anno>ChildSpec</anno></c> should instead be an arbitrary
+ list of terms <c><anno>List</anno></c>. The child process will then be
+ started by appending <c><anno>List</anno></c> to the existing start
function arguments, i.e. by calling
- <c>apply(M, F, A++List)</c> where <c>{M,F,A}</c> is the start
+ <c>apply(M, F, A++<anno>List</anno>)</c> where <c>{M,F,A}</c> is the start
function defined in the child specification.</p>
<p>If there already exists a child specification with
- the specified <c>Id</c>, <c>ChildSpec</c> is discarded and
+ the specified <c><anno>Id</anno></c>, <c><anno>ChildSpec</anno></c> is discarded and
the function returns <c>{error,already_present}</c> or
- <c>{error,{already_started,Child}}</c>, depending on if
+ <c>{error,{already_started,<anno>Child</anno>}}</c>, depending on if
the corresponding child process is running or not.</p>
- <p>If the child process start function returns <c>{ok,Child}</c>
- or <c>{ok,Child,Info}</c>, the child specification and pid is
+ <p>If the child process start function returns <c>{ok,<anno>Child</anno>}</c>
+ or <c>{ok,<anno>Child</anno>,<anno>Info</anno>}</c>, the child specification and pid is
added to the supervisor and the function returns the same
value.</p>
<p>If the child process start function returns <c>ignore</c>,
@@ -306,138 +338,114 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
</desc>
</func>
<func>
- <name>terminate_child(SupRef, Id) -> Result</name>
+ <name name="terminate_child" arity="2"/>
<fsummary>Terminate a child process belonging to a supervisor.</fsummary>
- <type>
- <v>SupRef = Name | {Name,Node} | {global,Name} | pid()</v>
- <v>&nbsp;Name = Node = atom()</v>
- <v>Id = term()</v>
- <v>Result = ok | {error,Error}</v>
- <v>&nbsp;Error = not_found | simple_one_for_one</v>
- </type>
<desc>
- <p>Tells the supervisor <c>SupRef</c> to terminate the child
- process corresponding to the child specification identified
- by <c>Id</c>. The process, if there is one, is terminated but
- the child specification is kept by the supervisor. This means
- that the child process may be later be restarted by
- the supervisor. The child process can also be restarted
- explicitly by calling <c>restart_child/2</c>. Use
- <c>delete_child/2</c> to remove the child specification.</p>
- <p>See <c>start_child/2</c> for a description of
- <c>SupRef</c>.</p>
+ <p>Tells the supervisor <c><anno>SupRef</anno></c> to terminate the given
+ child.</p>
+ <p>If the supervisor is not <c>simple_one_for_one</c>,
+ <c><anno>Id</anno></c> must be the child specification identifier. The
+ process, if there is one, is terminated but the child
+ specification is kept by the supervisor. The child process
+ may later be restarted by the supervisor. The child process
+ can also be restarted explicitly by calling
+ <c>restart_child/2</c>. Use <c>delete_child/2</c> to remove
+ the child specification.</p>
+ <p>If the supervisor is <c>simple_one_for_one</c>, <c><anno>Id</anno></c>
+ must be the child process' <c>pid()</c>. I the specified
+ process is alive, but is not a child of the given
+ supervisor, the function will return
+ <c>{error,not_found}</c>. If the child specification
+ identifier is given instead instead of a <c>pid()</c>, the
+ function will return <c>{error,simple_one_for_one}</c>.</p>
<p>If successful, the function returns <c>ok</c>. If there is
- no child specification with the specified <c>Id</c>,
- the function returns <c>{error,not_found}</c>.</p>
+ no child specification with the specified <c><anno>Id</anno></c>, the
+ function returns <c>{error,not_found}</c>.</p>
+ <p>See <c>start_child/2</c> for a description of
+ <c><anno>SupRef</anno></c>.</p>
</desc>
</func>
<func>
- <name>delete_child(SupRef, Id) -> Result</name>
+ <name name="delete_child" arity="2"/>
<fsummary>Delete a child specification from a supervisor.</fsummary>
- <type>
- <v>SupRef = Name | {Name,Node} | {global,Name} | pid()</v>
- <v>&nbsp;Name = Node = atom()</v>
- <v>Id = term()</v>
- <v>Result = ok | {error,Error}</v>
- <v>&nbsp;Error = running | not_found | simple_one_for_one</v>
- </type>
<desc>
- <p>Tells the supervisor <c>SupRef</c> to delete the child
- specification identified by <c>Id</c>. The corresponding child
+ <p>Tells the supervisor <c><anno>SupRef</anno></c> to delete the child
+ specification identified by <c><anno>Id</anno></c>. The corresponding child
process must not be running, use <c>terminate_child/2</c> to
terminate it.</p>
- <p>See <c>start_child/2</c> for a description of <c>SupRef</c>.</p>
+ <p>See <seealso marker="#SupRef"><c>start_child/2</c></seealso> for a description of
+ <c>SupRef</c>.</p>
<p>If successful, the function returns <c>ok</c>. If the child
- specification identified by <c>Id</c> exists but
+ specification identified by <c><anno>Id</anno></c> exists but
the corresponding child process is running, the function
returns <c>{error,running}</c>. If the child specification
- identified by <c>Id</c> does not exist, the function returns
+ identified by <c><anno>Id</anno></c> does not exist, the function returns
<c>{error,not_found}</c>.</p>
</desc>
</func>
<func>
- <name>restart_child(SupRef, Id) -> Result</name>
+ <name name="restart_child" arity="2"/>
<fsummary>Restart a terminated child process belonging to a supervisor.</fsummary>
- <type>
- <v>SupRef = Name | {Name,Node} | {global,Name} | pid()</v>
- <v>&nbsp;Name = Node = atom()</v>
- <v>Id = term()</v>
- <v>Result = {ok,Child} | {ok,Child,Info} | {error,Error}</v>
- <v>&nbsp;Child = pid() | undefined</v>
- <v>&nbsp;Error = running | not_found | simple_one_for_one | term()</v>
- </type>
<desc>
- <p>Tells the supervisor <c>SupRef</c> to restart a child process
+ <p>Tells the supervisor <c><anno>SupRef</anno></c> to restart a child process
corresponding to the child specification identified by
- <c>Id</c>. The child specification must exist and
+ <c><anno>Id</anno></c>. The child specification must exist and
the corresponding child process must not be running.</p>
- <p>See <c>start_child/2</c> for a description of <c>SupRef</c>.</p>
- <p>If the child specification identified by <c>Id</c> does not
+ <p>See <seealso marker="#SupRef"><c>start_child/2</c></seealso> for a description of
+ <c>SupRef</c>.</p>
+ <p>If the child specification identified by <c><anno>Id</anno></c> does not
exist, the function returns <c>{error,not_found}</c>. If
the child specification exists but the corresponding process
is already running, the function returns
<c>{error,running}</c>.</p>
- <p>If the child process start function returns <c>{ok,Child}</c>
- or <c>{ok,Child,Info}</c>, the pid is added to the supervisor
+ <p>If the child process start function returns <c>{ok,<anno>Child</anno>}</c>
+ or <c>{ok,<anno>Child</anno>,<anno>Info</anno>}</c>, the pid is added to the supervisor
and the function returns the same value.</p>
<p>If the child process start function returns <c>ignore</c>,
the pid remains set to <c>undefined</c> and the function
returns <c>{ok,undefined}</c>.</p>
<p>If the child process start function returns an error tuple or
an erroneous value, or if it fails, the function returns
- <c>{error,Error}</c> where <c>Error</c> is a term containing
+ <c>{error,<anno>Error</anno>}</c> where <c><anno>Error</anno></c> is a term containing
information about the error.</p>
</desc>
</func>
<func>
- <name>which_children(SupRef) -> [{Id,Child,Type,Modules}]</name>
+ <name name="which_children" arity="1"/>
<fsummary>Return information about all children specifications and child processes belonging to a supervisor.</fsummary>
- <type>
- <v>SupRef = Name | {Name,Node} | {global,Name} | pid()</v>
- <v>&nbsp;Name = Node = atom()</v>
- <v>Id = term() | undefined</v>
- <v>Child = pid() | undefined</v>
- <v>Type = worker | supervisor</v>
- <v>Modules = [Module] | dynamic</v>
- <v>&nbsp;Module = atom()</v>
- </type>
<desc>
<p>Returns a newly created list with information about all child
specifications and child processes belonging to
- the supervisor <c>SupRef</c>.</p>
+ the supervisor <c><anno>SupRef</anno></c>.</p>
<p>Note that calling this function when supervising a large
number of children under low memory conditions can cause an
out of memory exception.</p>
- <p>See <c>start_child/2</c> for a description of <c>SupRef</c>.</p>
+ <p>See <seealso marker="#SupRef"><c>start_child/2</c></seealso> for a description of
+ <c>SupRef</c>.</p>
<p>The information given for each child specification/process
is:</p>
<list type="bulleted">
<item>
- <p><c>Id</c> - as defined in the child specification or
+ <p><c><anno>Id</anno></c> - as defined in the child specification or
<c>undefined</c> in the case of a
<c>simple_one_for_one</c> supervisor.</p>
</item>
<item>
- <p><c>Child</c> - the pid of the corresponding child
+ <p><c><anno>Child</anno></c> - the pid of the corresponding child
process, or <c>undefined</c> if there is no such process.</p>
</item>
<item>
- <p><c>Type</c> - as defined in the child specification.</p>
+ <p><c><anno>Type</anno></c> - as defined in the child specification.</p>
</item>
<item>
- <p><c>Modules</c> - as defined in the child specification.</p>
+ <p><c><anno>Modules</anno></c> - as defined in the child specification.</p>
</item>
</list>
</desc>
</func>
<func>
- <name>count_children(SupRef) -> PropListOfCounts</name>
+ <name name="count_children" arity="1"/>
<fsummary>Return counts for the number of childspecs, active children, supervisors and workers.</fsummary>
- <type>
- <v>SupRef = Name | {Name,Node} | {global,Name} | pid()</v>
- <v>&nbsp;Name = Node = atom()</v>
- <v>PropListOfCounts = [{specs, ChildSpecCount}, {active, ActiveProcessCount}, {supervisors, ChildSupervisorCount}, {workers, ChildWorkerCount}]</v>
- </type>
<desc>
<p>Returns a property list (see <c>proplists</c>) containing the
counts for each of the following elements of the supervisor's
@@ -464,17 +472,12 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
</desc>
</func>
<func>
- <name>check_childspecs([ChildSpec]) -> Result</name>
+ <name name="check_childspecs" arity="1"/>
<fsummary>Check if children specifications are syntactically correct.</fsummary>
- <type>
- <v>ChildSpec = child_spec()</v>
- <v>Result = ok | {error,Error}</v>
- <v>&nbsp;Error = term()</v>
- </type>
<desc>
<p>This function takes a list of child specification as argument
and returns <c>ok</c> if all of them are syntactically
- correct, or <c>{error,Error}</c> otherwise.</p>
+ correct, or <c>{error,<anno>Error</anno>}</c> otherwise.</p>
</desc>
</func>
</funcs>
@@ -491,9 +494,9 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
<type>
<v>Args = term()</v>
<v>Result = {ok,{{RestartStrategy,MaxR,MaxT},[ChildSpec]}} | ignore</v>
- <v>&nbsp;RestartStrategy = one_for_all | one_for_one | rest_for_one | simple_one_for_one</v>
- <v>&nbsp;MaxR = MaxT = int()>=0</v>
- <v>&nbsp;ChildSpec = child_spec()</v>
+ <v>&nbsp;RestartStrategy = <seealso marker="#type-strategy">strategy()</seealso></v>
+ <v>&nbsp;MaxR = MaxT = integer()>=0</v>
+ <v>&nbsp;ChildSpec = <seealso marker="#type-child_spec">child_spec()</seealso></v>
</type>
<desc>
<p>Whenever a supervisor is started using
diff --git a/lib/stdlib/doc/src/supervisor_bridge.xml b/lib/stdlib/doc/src/supervisor_bridge.xml
index cbd0d9230b..c1a5e7947f 100644
--- a/lib/stdlib/doc/src/supervisor_bridge.xml
+++ b/lib/stdlib/doc/src/supervisor_bridge.xml
@@ -50,46 +50,37 @@
</description>
<funcs>
<func>
- <name>start_link(Module, Args) -> Result</name>
- <name>start_link(SupBridgeName, Module, Args) -> Result</name>
+ <name name="start_link" arity="2"/>
+ <name name="start_link" arity="3"/>
<fsummary>Create a supervisor bridge process.</fsummary>
- <type>
- <v>SupBridgeName = {local,Name} | {global,Name}</v>
- <v>&nbsp;Name = atom()</v>
- <v>Module = atom()</v>
- <v>Args = term()</v>
- <v>Result = {ok,Pid} | ignore | {error,Error}</v>
- <v>&nbsp;Pid = pid()</v>
- <v>&nbsp;Error = {already_started,Pid} | term()</v>
- </type>
<desc>
<p>Creates a supervisor_bridge process, linked to the calling
- process, which calls <c>Module:init/1</c> to start the subsystem.
+ process, which calls <c><anno>Module</anno>:init/1</c> to start the subsystem.
To ensure a synchronized start-up procedure, this function does
- not return until <c>Module:init/1</c> has returned.</p>
- <p>If <c>SupBridgeName={local,Name}</c> the supervisor_bridge is
- registered locally as <c>Name</c> using <c>register/2</c>.
- If <c>SupBridgeName={global,Name}</c> the supervisor_bridge is
- registered globally as <c>Name</c> using
+ not return until <c><anno>Module</anno>:init/1</c> has returned.</p>
+ <p>If <c><anno>SupBridgeName</anno>={local,<anno>Name</anno>}</c> the supervisor_bridge is
+ registered locally as <c><anno>Name</anno></c> using <c>register/2</c>.
+ If <c><anno>SupBridgeName</anno>={global,<anno>Name</anno>}</c> the supervisor_bridge is
+ registered globally as <c><anno>Name</anno></c> using
<c>global:register_name/2</c>.
If no name is provided, the supervisor_bridge is not registered.
If there already exists a process with the specified
- <c>SupBridgeName</c> the function returns
- <c>{error,{already_started,Pid}}</c>, where <c>Pid</c> is the pid
+ <c><anno>SupBridgeName</anno></c> the function returns
+ <c>{error,{already_started,<anno>Pid</anno>}}</c>, where <c><anno>Pid</anno></c> is the pid
of that process.</p>
- <p><c>Module</c> is the name of the callback module.</p>
- <p><c>Args</c> is an arbitrary term which is passed as the argument
- to <c>Module:init/1</c>.</p>
+ <p><c><anno>Module</anno></c> is the name of the callback module.</p>
+ <p><c><anno>Args</anno></c> is an arbitrary term which is passed as the argument
+ to <c><anno>Module</anno>:init/1</c>.</p>
<p>If the supervisor_bridge and the subsystem are successfully
- started the function returns <c>{ok,Pid}</c>, where <c>Pid</c> is
+ started the function returns <c>{ok,<anno>Pid</anno>}</c>, where <c><anno>Pid</anno></c> is
is the pid of the supervisor_bridge.</p>
- <p>If <c>Module:init/1</c> returns <c>ignore</c>, this function
+ <p>If <c><anno>Module</anno>:init/1</c> returns <c>ignore</c>, this function
returns <c>ignore</c> as well and the supervisor_bridge terminates
with reason <c>normal</c>.
- If <c>Module:init/1</c> fails or returns an error tuple or an
- incorrect value, this function returns <c>{error,Term}</c> where
- <c>Term</c> is a term with information about the error, and
- the supervisor_bridge terminates with reason <c>Term</c>.</p>
+ If <c><anno>Module</anno>:init/1</c> fails or returns an error tuple or an
+ incorrect value, this function returns <c>{error,<anno>Error</anno>r}</c> where
+ <c><anno>Error</anno></c> is a term with information about the error, and
+ the supervisor_bridge terminates with reason <c><anno>Error</anno></c>.</p>
</desc>
</func>
</funcs>
diff --git a/lib/stdlib/doc/src/sys.xml b/lib/stdlib/doc/src/sys.xml
index efa8922a9d..073faf2df2 100644
--- a/lib/stdlib/doc/src/sys.xml
+++ b/lib/stdlib/doc/src/sys.xml
@@ -39,24 +39,12 @@
<p>Functions used for implementation of processes
should also understand system messages such as debugging
messages and code change. These functions must be used to implement the use of system messages for a process; either directly, or through standard behaviours, such as <c>gen_server</c>.</p>
- <p>The following types are used in the functions defined below:</p>
- <list type="bulleted">
- <item>
- <p><c>Name = pid() | atom() | {global, atom()}</c></p>
- </item>
- <item>
- <p><c>Timeout = int() >= 0 | infinity</c></p>
- </item>
- <item>
- <p><c>system_event() = {in, Msg} | {in, Msg, From} | {out, Msg, To} | term()</c></p>
- </item>
- </list>
<p>The default timeout is 5000 ms, unless otherwise specified. The
<c>timeout</c> defines the time period to wait for the process to
respond to a request. If the process does not respond, the
function evaluates <c>exit({timeout, {M, F, A}})</c>.
</p>
- <p>The functions make reference to a debug structure.
+ <p><marker id="dbg_opt"/>The functions make reference to a debug structure.
The debug structure is a list of <c>dbg_opt()</c>.
<c>dbg_opt()</c> is an internal data type used by the
<c>handle_system_msg/6</c> function. No debugging is performed if it is an empty list.
@@ -113,20 +101,31 @@
own system events. It is always up to the process itself
to format these events.</p>
</section>
+ <datatypes>
+ <datatype>
+ <name name="name"/>
+ </datatype>
+ <datatype>
+ <name name="system_event"/>
+ </datatype>
+ <datatype>
+ <name name="dbg_opt"/>
+ <desc><p>See <seealso marker="#dbg_opt">above</seealso>.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="dbg_fun"/>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>log(Name,Flag)</name>
- <name>log(Name,Flag,Timeout) -> ok | {ok, [system_event()]}</name>
+ <name name="log" arity="2"/>
+ <name name="log" arity="3"/>
<fsummary>Log system events in memory</fsummary>
- <type>
- <v>Flag = true | {true, N} | false | get | print</v>
- <v>N = integer() > 0</v>
- </type>
<desc>
<p>Turns the logging of system events On or Off. If On, a
- maximum of <c>N</c> events are kept in the
- debug structure (the default is 10). If <c>Flag</c> is <c>get</c>, a list of all
- logged events is returned. If <c>Flag</c> is <c>print</c>, the
+ maximum of <c><anno>N</anno></c> events are kept in the
+ debug structure (the default is 10). If <c><anno>Flag</anno></c> is <c>get</c>, a list of all
+ logged events is returned. If <c><anno>Flag</anno></c> is <c>print</c>, the
logged events are printed to <c>standard_io</c>. The events are
formatted with a function that is defined by the process that
generated the event (with a call to
@@ -134,13 +133,9 @@
</desc>
</func>
<func>
- <name>log_to_file(Name,Flag)</name>
- <name>log_to_file(Name,Flag,Timeout) -> ok | {error, open_file}</name>
+ <name name="log_to_file" arity="2"/>
+ <name name="log_to_file" arity="3"/>
<fsummary>Log system events to the specified file</fsummary>
- <type>
- <v>Flag = FileName | false</v>
- <v>FileName = string()</v>
- </type>
<desc>
<p>Enables or disables the logging of all system events in textual
format to the file. The events are formatted with a function that is
@@ -149,27 +144,18 @@
</desc>
</func>
<func>
- <name>statistics(Name,Flag)</name>
- <name>statistics(Name,Flag,Timeout) -> ok | {ok, Statistics} </name>
+ <name name="statistics" arity="2"/>
+ <name name="statistics" arity="3"/>
<fsummary>Enable or disable the collections of statistics</fsummary>
- <type>
- <v>Flag = true | false | get</v>
- <v>Statistics = [{start_time, {Date1, Time1}}, {current_time, {Date, Time2}}, {reductions, integer()}, {messages_in, integer()}, {messages_out, integer()}]</v>
- <v>Date1 = Date2 = {Year, Month, Day}</v>
- <v>Time1 = Time2 = {Hour, Min, Sec}</v>
- </type>
<desc>
- <p>Enables or disables the collection of statistics. If <c>Flag</c> is
+ <p>Enables or disables the collection of statistics. If <c><anno>Flag</anno></c> is
<c>get</c>, the statistical collection is returned.</p>
</desc>
</func>
<func>
- <name>trace(Name,Flag)</name>
- <name>trace(Name,Flag,Timeout) -> void()</name>
+ <name name="trace" arity="2"/>
+ <name name="trace" arity="3"/>
<fsummary>Print all system events on <c>standard_io</c></fsummary>
- <type>
- <v>Flag = boolean()</v>
- </type>
<desc>
<p>Prints all system events on <c>standard_io</c>. The events are
formatted with a function that is defined by the process that
@@ -178,8 +164,8 @@
</desc>
</func>
<func>
- <name>no_debug(Name)</name>
- <name>no_debug(Name,Timeout) -> void()</name>
+ <name name="no_debug" arity="1"/>
+ <name name="no_debug" arity="2"/>
<fsummary>Turn off debugging</fsummary>
<desc>
<p>Turns off all debugging for the process. This includes
@@ -188,8 +174,8 @@
</desc>
</func>
<func>
- <name>suspend(Name)</name>
- <name>suspend(Name,Timeout) -> void()</name>
+ <name name="suspend" arity="1"/>
+ <name name="suspend" arity="2"/>
<fsummary>Suspend the process</fsummary>
<desc>
<p>Suspends the process. When the process is suspended, it
@@ -198,49 +184,37 @@
</desc>
</func>
<func>
- <name>resume(Name)</name>
- <name>resume(Name,Timeout) -> void()</name>
+ <name name="resume" arity="1"/>
+ <name name="resume" arity="2"/>
<fsummary>Resume a suspended process</fsummary>
<desc>
<p>Resumes a suspended process.</p>
</desc>
</func>
<func>
- <name>change_code(Name, Module, OldVsn, Extra)</name>
- <name>change_code(Name, Module, OldVsn, Extra, Timeout) -> ok | {error, Reason}</name>
+ <name name="change_code" arity="4"/>
+ <name name="change_code" arity="5"/>
<fsummary>Send the code change system message to the process</fsummary>
- <type>
- <v>OldVsn = undefined | term()</v>
- <v>Module = atom()</v>
- <v>Extra = term()</v>
- </type>
<desc>
<p>Tells the process to change code. The process must be
- suspended to handle this message. The <c>Extra</c> argument is
+ suspended to handle this message. The <c><anno>Extra</anno></c> argument is
reserved for each process to use as its own. The function
- <c>Mod:system_code_change/4</c> is called. <c>OldVsn</c> is
- the old version of the <c>Module</c>.</p>
+ <c><anno>Module</anno>:system_code_change/4</c> is called. <c><anno>OldVsn</anno></c> is
+ the old version of the <c><anno>Module</anno></c>.</p>
</desc>
</func>
<func>
- <name>get_status(Name)</name>
- <name>get_status(Name,Timeout) -> {status, Pid, {module, Mod}, [PDict, SysState, Parent, Dbg, Misc]}</name>
+ <name name="get_status" arity="1"/>
+ <name name="get_status" arity="2"/>
<fsummary>Get the status of the process</fsummary>
- <type>
- <v>PDict = [{Key, Value}]</v>
- <v>SysState = running | suspended</v>
- <v>Parent = pid()</v>
- <v>Dbg = [dbg_opt()]</v>
- <v>Misc = term()</v>
- </type>
<desc>
<p>Gets the status of the process.</p>
- <p>The value of <c>Misc</c> varies for different types of
+ <p>The value of <c><anno>Misc</anno></c> varies for different types of
processes. For example, a <c>gen_server</c> process returns
the callback module's state, and a <c>gen_fsm</c> process
returns information such as its current state name. Callback
modules for <c>gen_server</c> and <c>gen_fsm</c> can also
- customise the value of <c>Misc</c> by exporting
+ customise the value of <c><anno>Misc</anno></c> by exporting
a <c>format_status/2</c> function that contributes
module-specific information;
see <seealso marker="gen_server#Module:format_status/2">gen_server:format_status/2</seealso>
@@ -249,17 +223,9 @@
</desc>
</func>
<func>
- <name>install(Name,{Func,FuncState})</name>
- <name>install(Name,{Func,FuncState},Timeout)</name>
+ <name name="install" arity="2"/>
+ <name name="install" arity="3"/>
<fsummary>Install a debug function in the process</fsummary>
- <type>
- <v>Func = dbg_fun()</v>
- <v>dbg_fun() = fun(FuncState, Event, ProcState) -> done | NewFuncState</v>
- <v>FuncState = term()</v>
- <v>Event = system_event()</v>
- <v>ProcState = term()</v>
- <v>NewFuncState = term()</v>
- </type>
<desc>
<p>This function makes it possible to install other debug
functions than the ones defined above. An example of such a
@@ -267,22 +233,19 @@
special event and performs some action when the event is
generated. This could, for example, be turning on low level tracing.
</p>
- <p><c>Func</c> is called whenever a system event is
+ <p><c><anno>Func</anno></c> is called whenever a system event is
generated. This function should return <c>done</c>, or a new
func state. In the first case, the function is removed. It is removed
if the function fails.</p>
</desc>
</func>
<func>
- <name>remove(Name,Func)</name>
- <name>remove(Name,Func,Timeout) -> void()</name>
+ <name name="remove" arity="2"/>
+ <name name="remove" arity="3"/>
<fsummary>Remove a debug function from the process</fsummary>
- <type>
- <v>Func = dbg_fun()</v>
- </type>
<desc>
<p>Removes a previously installed debug function from the
- process. <c>Func</c> must be the same as previously
+ process. <c><anno>Func</anno></c> must be the same as previously
installed.</p>
</desc>
</func>
@@ -296,86 +259,65 @@
</section>
<funcs>
<func>
- <name>debug_options(Options) -> [dbg_opt()]</name>
+ <name name="debug_options" arity="1"/>
<fsummary>Convert a list of options to a debug structure</fsummary>
- <type>
- <v>Options = [Opt]</v>
- <v>Opt = trace | log | statistics | {log_to_file, FileName} | {install, {Func, FuncState}}</v>
- <v>Func = dbg_fun()</v>
- <v>FuncState = term()</v>
- </type>
<desc>
<p>This function can be used by a process that initiates a debug
structure from a list of options. The values of the
- <c>Opt</c> argument are the same as the corresponding
+ <c><anno>Opt</anno></c> argument are the same as the corresponding
functions.</p>
</desc>
</func>
<func>
- <name>get_debug(Item,Debug,Default) -> term()</name>
+ <name name="get_debug" arity="3"/>
<fsummary>Get the data associated with a debug option</fsummary>
- <type>
- <v>Item = log | statistics</v>
- <v>Debug = [dbg_opt()]</v>
- <v>Default = term()</v>
- </type>
<desc>
- <p>This function gets the data associated with a debug option. <c>Default</c> is returned if the
- <c>Item</c> is not found. Can be
+ <p>This function gets the data associated with a debug option. <c><anno>Default</anno></c> is returned if the
+ <c><anno>Item</anno></c> is not found. Can be
used by the process to retrieve debug data for printing
before it terminates.</p>
</desc>
</func>
<func>
- <name>handle_debug([dbg_opt()],FormFunc,Extra,Event) -> [dbg_opt()]</name>
+ <name name="handle_debug" arity="4"/>
<fsummary>Generate a system event</fsummary>
- <type>
- <v>FormFunc = dbg_fun()</v>
- <v>Extra = term()</v>
- <v>Event = system_event()</v>
- </type>
<desc>
- <p>This function is called by a process when it generates a system event. <c>FormFunc</c> is a formatting function which is called as <c>FormFunc(Device, Event, Extra)</c> in order to print the events, which is necessary if tracing is activated. <c>Extra</c> is any
- extra information which the process needs in the format function, for example the name of the process.</p>
+ <p>This function is called by a process when it generates a
+ system event. <c><anno>FormFunc</anno></c> is a formatting
+ function which is called as <c><anno>FormFunc</anno>(Device,
+ <anno>Event</anno>, <anno>Extra</anno>)</c> in order to print
+ the events, which is necessary if tracing is activated.
+ <c><anno>Extra</anno></c> is any extra information which the
+ process needs in the format function, for example the name
+ of the process.</p>
</desc>
</func>
<func>
- <name>handle_system_msg(Msg,From,Parent,Module,Debug,Misc)</name>
+ <name name="handle_system_msg" arity="6"/>
<fsummary>Take care of system messages</fsummary>
- <type>
- <v>Msg = term()</v>
- <v>From = pid()</v>
- <v>Parent = pid()</v>
- <v>Module = atom()</v>
- <v>Debug = [dbg_opt()]</v>
- <v>Misc = term()</v>
- </type>
<desc>
<p>This function is used by a process module that wishes to take care of system
- messages. The process receives a <c>{system, From, Msg}</c>
- message and passes the <c>Msg</c> and <c>From</c> to this
+ messages. The process receives a <c>{system, <anno>From</anno>, <anno>Msg</anno>}</c>
+ message and passes the <c><anno>Msg</anno></c> and <c><anno>From</anno></c> to this
function.
</p>
<p>This function <em>never</em> returns. It calls the function
- <c>Module:system_continue(Parent, NDebug, Misc)</c> where the
+ <c><anno>Module</anno>:system_continue(<anno>Parent</anno>, NDebug, <anno>Misc</anno>)</c> where the
process continues the execution, or
- <c>Module:system_terminate(Reason, Parent, Debug, Misc)</c> if
- the process should terminate. The <c>Module</c> must export
+ <c><anno>Module</anno>:system_terminate(Reason, <anno>Parent</anno>, <anno>Debug</anno>, <anno>Misc</anno>)</c> if
+ the process should terminate. The <c><anno>Module</anno></c> must export
<c>system_continue/3</c>, <c>system_terminate/4</c>, and
<c>system_code_change/4</c> (see below).
</p>
- <p>The <c>Misc</c> argument can be used to save internal data
+ <p>The <c><anno>Misc</anno></c> argument can be used to save internal data
in a process, for example its state. It is sent to
- <c>Module:system_continue/3</c> or
- <c>Module:system_terminate/4</c></p>
+ <c><anno>Module</anno>:system_continue/3</c> or
+ <c><anno>Module</anno>:system_terminate/4</c></p>
</desc>
</func>
<func>
- <name>print_log(Debug) -> void()</name>
+ <name name="print_log" arity="1"/>
<fsummary>Print the logged events in the debug structure</fsummary>
- <type>
- <v>Debug = [dbg_opt()]</v>
- </type>
<desc>
<p>Prints the logged system events in the debug structure
using <c>FormFunc</c> as defined when the event was
@@ -383,11 +325,11 @@
</desc>
</func>
<func>
- <name>Mod:system_continue(Parent, Debug, Misc)</name>
+ <name>Mod:system_continue(Parent, Debug, Misc) -> none()</name>
<fsummary>Called when the process should continue its execution</fsummary>
<type>
<v>Parent = pid()</v>
- <v>Debug = [dbg_opt()]</v>
+ <v>Debug = [<seealso marker="#type-dbg_opt">dbg_opt()</seealso>]</v>
<v>Misc = term()</v>
</type>
<desc>
@@ -397,12 +339,12 @@
</desc>
</func>
<func>
- <name>Mod:system_terminate(Reason, Parent, Debug, Misc)</name>
+ <name>Mod:system_terminate(Reason, Parent, Debug, Misc) -> none()</name>
<fsummary>Called when the process should terminate</fsummary>
<type>
<v>Reason = term()</v>
<v>Parent = pid()</v>
- <v>Debug = [dbg_opt()]</v>
+ <v>Debug = [<seealso marker="#type-dbg_opt">dbg_opt()</seealso>]</v>
<v>Misc = term()</v>
</type>
<desc>
diff --git a/lib/stdlib/doc/src/timer.xml b/lib/stdlib/doc/src/timer.xml
index cae655f801..0c1e398dc4 100644
--- a/lib/stdlib/doc/src/timer.xml
+++ b/lib/stdlib/doc/src/timer.xml
@@ -49,9 +49,19 @@
as requested.
</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="time"/>
+ <desc><p>Time in milliseconds.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="tref"/>
+ <desc><p>A timer reference.</p></desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>start() -> ok</name>
+ <name name="start" arity="0"/>
<fsummary>Start a global timer server (named <c>timer_server</c>).</fsummary>
<desc>
<p>Starts the timer server. Normally, the server does not need
@@ -62,214 +72,185 @@
</desc>
</func>
<func>
- <name>apply_after(Time, Module, Function, Arguments) -> {ok, Tref} | {error, Reason}</name>
+ <name name="apply_after" arity="4"/>
<fsummary>Apply <c>Module:Function(Arguments)</c>after a specified <c>Time</c>.</fsummary>
- <type>
- <v>Time = integer() in Milliseconds</v>
- <v>Module = Function = atom()</v>
- <v>Arguments = [term()]</v>
- </type>
<desc>
- <p>Evaluates <c>apply(M, F, A)</c> after <c>Time</c> amount of time
- has elapsed. Returns <c>{ok, TRef}</c>, or <c>{error, Reason}</c>.</p>
+ <p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Arguments</anno>)</c> after <c><anno>Time</anno></c> amount of time
+ has elapsed. Returns <c>{ok, <anno>TRef</anno>}</c>, or <c>{error, <anno>Reason</anno>}</c>.</p>
</desc>
</func>
<func>
- <name>send_after(Time, Pid, Message) -> {ok, TRef} | {error,Reason}</name>
- <name>send_after(Time, Message) -> {ok, TRef} | {error,Reason}</name>
+ <name name="send_after" arity="2"/>
+ <name name="send_after" arity="3"/>
<fsummary>Send <c>Message</c>to <c>Pid</c>after a specified <c>Time</c>.</fsummary>
- <type>
- <v>Time = integer() in Milliseconds</v>
- <v>Pid = pid() | atom()</v>
- <v>Message = term()</v>
- <v>Result = {ok, TRef} | {error, Reason}</v>
- </type>
<desc>
- <p></p>
+ <p>
<taglist>
<tag><c>send_after/3</c></tag>
<item>
- <p>Evaluates <c>Pid ! Message</c> after <c>Time</c> amount
- of time has elapsed. (<c>Pid</c> can also be an atom of a
- registered name.) Returns <c>{ok, TRef}</c>, or
- <c>{error, Reason}</c>.</p>
+ <p>Evaluates <c><anno>Pid</anno> ! <anno>Message</anno></c> after <c><anno>Time</anno></c> amount
+ of time has elapsed. (<c><anno>Pid</anno></c> can also be an atom of a
+ registered name.) Returns <c>{ok, <anno>TRef</anno>}</c>, or
+ <c>{error, <anno>Reason</anno>}</c>.</p>
</item>
<tag><c>send_after/2</c></tag>
<item>
- <p>Same as <c>send_after(Time, self(), Message)</c>.</p>
+ <p>Same as <c>send_after(<anno>Time</anno>, self(), <anno>Message</anno>)</c>.</p>
</item>
</taglist>
+ </p>
</desc>
</func>
<func>
- <name>exit_after(Time, Pid, Reason1) -> {ok, TRef} | {error,Reason2}</name>
- <name>exit_after(Time, Reason1) -> {ok, TRef} | {error,Reason2}</name>
- <name>kill_after(Time, Pid)-> {ok, TRef} | {error,Reason2}</name>
- <name>kill_after(Time) -> {ok, TRef} | {error,Reason2}</name>
+ <name name="kill_after" arity="1"/>
+ <name name="kill_after" arity="2"/>
+ <name name="exit_after" arity="2"/>
+ <name name="exit_after" arity="3"/>
<fsummary>Send an exit signal with <c>Reason</c>after a specified <c>Time</c>.</fsummary>
- <type>
- <v>Time = integer() in milliseconds</v>
- <v>Pid = pid() | atom()</v>
- <v>Reason1 = Reason2 = term()</v>
- </type>
<desc>
- <p></p>
+ <p>
<taglist>
<tag><c>exit_after/3</c></tag>
<item>
- <p>Send an exit signal with reason <c>Reason1</c> to Pid
- <c>Pid</c>. Returns <c>{ok, TRef}</c>, or
- <c>{error, Reason2}</c>.</p>
+ <p>Send an exit signal with reason <c><anno>Reason1</anno></c> to Pid
+ <c><anno>Pid</anno></c>. Returns <c>{ok, <anno>TRef</anno>}</c>, or
+ <c>{error, <anno>Reason2</anno>}</c>.</p>
</item>
<tag><c>exit_after/2</c></tag>
<item>
- <p>Same as <c>exit_after(Time, self(), Reason1)</c>. </p>
+ <p>Same as <c>exit_after(<anno>Time</anno>, self(), <anno>Reason1</anno>)</c>. </p>
</item>
<tag><c>kill_after/2</c></tag>
<item>
- <p>Same as <c>exit_after(Time, Pid, kill)</c>. </p>
+ <p>Same as <c>exit_after(<anno>Time</anno>, <anno>Pid</anno>, kill)</c>. </p>
</item>
<tag><c>kill_after/1</c></tag>
<item>
- <p>Same as <c>exit_after(Time, self(), kill)</c>. </p>
+ <p>Same as <c>exit_after(<anno>Time</anno>, self(), kill)</c>. </p>
</item>
</taglist>
+ </p>
</desc>
</func>
<func>
- <name>apply_interval(Time, Module, Function, Arguments) -> {ok, TRef} | {error, Reason}</name>
+ <name name="apply_interval" arity="4"/>
<fsummary>Evaluate <c>Module:Function(Arguments)</c>repeatedly at intervals of <c>Time</c>.</fsummary>
- <type>
- <v>Time = integer() in milliseconds</v>
- <v>Module = Function = atom()</v>
- <v>Arguments = [term()]</v>
- </type>
<desc>
- <p>Evaluates <c>apply(Module, Function, Arguments)</c> repeatedly at
- intervals of <c>Time</c>. Returns <c>{ok, TRef}</c>, or
- <c>{error, Reason}</c>.</p>
+ <p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Arguments</anno>)</c> repeatedly at
+ intervals of <c><anno>Time</anno></c>. Returns <c>{ok, <anno>TRef</anno>}</c>, or
+ <c>{error, <anno>Reason</anno>}</c>.</p>
</desc>
</func>
<func>
- <name>send_interval(Time, Pid, Message) -> {ok, TRef} | {error, Reason}</name>
- <name>send_interval(Time, Message) -> {ok, TRef} | {error, Reason}</name>
+ <name name="send_interval" arity="2"/>
+ <name name="send_interval" arity="3"/>
<fsummary>Send <c>Message</c>repeatedly at intervals of <c>Time</c>.</fsummary>
- <type>
- <v>Time = integer() in milliseconds</v>
- <v>Pid = pid() | atom()</v>
- <v>Message = term()</v>
- <v>Reason = term()</v>
- </type>
<desc>
- <p></p>
+ <p>
<taglist>
<tag><c>send_interval/3</c></tag>
<item>
- <p>Evaluates <c>Pid ! Message</c> repeatedly after <c>Time</c>
- amount of time has elapsed. (<c>Pid</c> can also be an atom of
- a registered name.) Returns <c>{ok, TRef}</c> or
- <c>{error, Reason}</c>.</p>
+ <p>Evaluates <c><anno>Pid</anno> ! <anno>Message</anno></c> repeatedly after <c><anno>Time</anno></c>
+ amount of time has elapsed. (<c><anno>Pid</anno></c> can also be an atom of
+ a registered name.) Returns <c>{ok, <anno>TRef</anno>}</c> or
+ <c>{error, <anno>Reason</anno>}</c>.</p>
</item>
<tag><c>send_interval/2</c></tag>
<item>
- <p>Same as <c>send_interval(Time, self(), Message)</c>.</p>
+ <p>Same as <c>send_interval(<anno>Time</anno>, self(), <anno>Message</anno>)</c>.</p>
</item>
</taglist>
+ </p>
</desc>
</func>
<func>
- <name>cancel(TRef) -> {ok, cancel} | {error, Reason}</name>
+ <name name="cancel" arity="1"/>
<fsummary>Cancel a previously requested timeout identified by <c>TRef</c>.</fsummary>
<desc>
- <p>Cancels a previously requested timeout. <c>TRef</c> is a unique
+ <p>Cancels a previously requested timeout. <c><anno>TRef</anno></c> is a unique
timer reference returned by the timer function in question. Returns
- <c>{ok, cancel}</c>, or <c>{error, Reason}</c> when <c>TRef</c>
+ <c>{ok, cancel}</c>, or <c>{error, <anno>Reason</anno>}</c> when <c><anno>TRef</anno></c>
is not a timer reference.</p>
</desc>
</func>
<func>
- <name>sleep(Time) -> ok</name>
+ <name name="sleep" arity="1"/>
<fsummary>Suspend the calling process for <c>Time</c>amount of milliseconds.</fsummary>
- <type>
- <v>Time = integer() in milliseconds or the atom infinity</v>
- </type>
<desc>
- <p>Suspends the process calling this function for <c>Time</c> amount
+ <p>Suspends the process calling this function for <c><anno>Time</anno></c> amount
of milliseconds and then returns <c>ok</c>, or suspend the process
- forever if <c>Time</c> is the atom <c>infinity</c>. Naturally, this
+ forever if <c><anno>Time</anno></c> is the atom <c>infinity</c>. Naturally, this
function does <em>not</em> return immediately.</p>
</desc>
</func>
<func>
- <name>tc(Module, Function, Arguments) -> {Time, Value}</name>
- <name>tc(Fun, Arguments) -> {Time, Value}</name>
+ <name name="tc" arity="1"/>
+ <name name="tc" arity="2"/>
+ <name name="tc" arity="3"/>
<fsummary>Measure the real time it takes to evaluate <c>apply(Module,
Function, Arguments)</c> or <c>apply(Fun, Arguments)</c></fsummary>
- <type>
- <v>Module = Function = atom()</v>
- <v>Fun = fun()</v>
- <v>Arguments = [term()]</v>
- <v>Time = integer() in microseconds</v>
- <v>Value = term()</v>
- </type>
+ <type_desc variable="Time">In microseconds</type_desc>
<desc>
- <p></p>
+ <p>
<taglist>
<tag><c>tc/3</c></tag>
<item>
- <p>Evaluates <c>apply(Module, Function, Arguments)</c> and measures
- the elapsed real time as reported by <c>now/0</c>.
- Returns <c>{Time, Value}</c>, where
- <c>Time</c> is the elapsed real time in <em>microseconds</em>,
- and <c>Value</c> is what is returned from the apply.</p>
+ <p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>, <anno>Arguments</anno>)</c> and measures
+ the elapsed real time as reported by <c>os:timestamp/0</c>.
+ Returns <c>{<anno>Time</anno>, <anno>Value</anno>}</c>, where
+ <c><anno>Time</anno></c> is the elapsed real time in <em>microseconds</em>,
+ and <c><anno>Value</anno></c> is what is returned from the apply.</p>
</item>
<tag><c>tc/2</c></tag>
<item>
- <p>Evaluates <c>apply(Fun, Arguments)</c>. Otherwise works
+ <p>Evaluates <c>apply(<anno>Fun</anno>, <anno>Arguments</anno>)</c>. Otherwise works
like <c>tc/3</c>.</p>
</item>
+ <tag><c>tc/1</c></tag>
+ <item>
+ <p>Evaluates <c><anno>Fun</anno>()</c>. Otherwise works like <c>tc/2</c>.</p>
+ </item>
+
</taglist>
+ </p>
</desc>
</func>
<func>
- <name>now_diff(T2, T1) -> Tdiff</name>
+ <name name="now_diff" arity="2"/>
<fsummary>Calculate time difference between <c>now/0</c>timestamps</fsummary>
- <type>
- <v>T1 = T2 = {MegaSecs, Secs, MicroSecs}</v>
- <v>Tdiff = MegaSecs = Secs = MicroSecs = integer()</v>
- </type>
+ <type_desc variable="Tdiff">In microseconds</type_desc>
<desc>
- <p>Calculates the time difference <c>Tdiff = T2 - T1</c> in
- <em>microseconds</em>, where <c>T1</c> and <c>T2</c> probably
+ <p>Calculates the time difference <c><anno>Tdiff</anno> = <anno>T2</anno> - <anno>T1</anno></c> in
+ <em>microseconds</em>, where <c><anno>T1</anno></c> and <c><anno>T2</anno></c> probably
are timestamp tuples returned from <c>erlang:now/0</c>.</p>
</desc>
</func>
<func>
- <name>seconds(Seconds) -> Milliseconds</name>
+ <name name="seconds" arity="1"/>
<fsummary>Convert <c>Seconds</c>to <c>Milliseconds</c>.</fsummary>
<desc>
- <p>Returns the number of milliseconds in <c>Seconds</c>.</p>
+ <p>Returns the number of milliseconds in <c><anno>Seconds</anno></c>.</p>
</desc>
</func>
<func>
- <name>minutes(Minutes) -> Milliseconds</name>
+ <name name="minutes" arity="1"/>
<fsummary>Converts <c>Minutes</c>to <c>Milliseconds</c>.</fsummary>
<desc>
- <p>Return the number of milliseconds in <c>Minutes</c>.</p>
+ <p>Return the number of milliseconds in <c><anno>Minutes</anno></c>.</p>
</desc>
</func>
<func>
- <name>hours(Hours) -> Milliseconds</name>
+ <name name="hours" arity="1"/>
<fsummary>Convert <c>Hours</c>to <c>Milliseconds</c>.</fsummary>
<desc>
- <p>Returns the number of milliseconds in <c>Hours</c>.</p>
+ <p>Returns the number of milliseconds in <c><anno>Hours</anno></c>.</p>
</desc>
</func>
<func>
- <name>hms(Hours, Minutes, Seconds) -> Milliseconds</name>
+ <name name="hms" arity="3"/>
<fsummary>Convert <c>Hours</c>+<c>Minutes</c>+<c>Seconds</c>to <c>Milliseconds</c>.</fsummary>
<desc>
- <p>Returns the number of milliseconds in <c>Hours + Minutes + Seconds</c>.</p>
+ <p>Returns the number of milliseconds in <c><anno>Hours</anno> + <anno>Minutes</anno> + <anno>Seconds</anno></c>.</p>
</desc>
</func>
</funcs>
@@ -277,7 +258,6 @@
<section>
<title>Examples</title>
<p>This example illustrates how to print out "Hello World!" in 5 seconds:</p>
- <p></p>
<pre>
1> <input>timer:apply_after(5000, io, format, ["~nHello World!~n", []]).</input>
{ok,TRef}
diff --git a/lib/stdlib/doc/src/unicode.xml b/lib/stdlib/doc/src/unicode.xml
index e3a25a407b..d02763f75c 100644
--- a/lib/stdlib/doc/src/unicode.xml
+++ b/lib/stdlib/doc/src/unicode.xml
@@ -38,50 +38,83 @@
<p>It is recommended to only use external encodings for communication with external entities where this is required. When working inside the Erlang/OTP environment, it is recommended to keep binaries in UTF-8 when representing Unicode characters. Latin1 encoding is supported both for backward compatibility and for communication with external entities not supporting Unicode character sets.</p>
</description>
- <section>
- <title>DATA TYPES</title>
- <marker id="type-charlist"></marker>
- <code type="none">
-unicode_binary() = binary() with characters encoded in UTF-8 coding standard
-unicode_char() = integer() representing valid unicode codepoint
-
-chardata() = charlist() | unicode_binary()
-
-charlist() = [unicode_char() | unicode_binary() | charlist()]
- a unicode_binary is allowed as the tail of the list</code>
-
- <code type="none">
-external_unicode_binary() = binary()
- with characters coded in a user specified Unicode encoding other
- than UTF-8 (UTF-16 or UTF-32)
-
-external_chardata() = external_charlist() | external_unicode_binary()
-
-external_charlist() = [unicode_char() | external_unicode_binary() | external_charlist()]
- an external_unicode_binary is allowed as the tail of the list</code>
-
- <code type="none">
-latin1_binary() = binary() with characters coded in iso-latin-1
-latin1_char() = integer() representing valid latin1 character (0-255)
-
-latin1_chardata() = latin1_charlist() | latin1_binary()
+ <datatypes>
+ <datatype>
+ <name name="encoding"/>
+ </datatype>
+ <datatype>
+ <name name="endian"/>
+ </datatype>
+ <datatype>
+ <name name="unicode_binary"/>
+ <desc>
+ <p>A binary() with characters encoded in the UTF-8 coding standard.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="unicode_char"/>
+ <desc>
+ <p>An integer() representing a valid unicode codepoint.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="chardata"/>
+ </datatype>
+ <datatype>
+ <name name="charlist"/>
+ <desc>
+ <p>A unicode_binary is allowed as the tail of the list.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="external_unicode_binary"/>
+ <desc>
+ <p>A <c>binary()</c> with characters coded in a user specified Unicode
+ encoding other than UTF-8 (UTF-16 or UTF-32).</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="external_chardata"/>
+ </datatype>
+ <datatype>
+ <name name="external_charlist"/>
+ <desc>
+ <p>An <c>external_unicode_binary()</c> is allowed as the tail
+ of the list.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="latin1_binary"/>
+ <desc><p>A <c>binary()</c> with characters coded in iso-latin-1.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="latin1_char"/>
+ <desc><p>An <c>integer()</c> representing valid latin1
+ character (0-255).</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="latin1_chardata"/>
+ </datatype>
+ <datatype>
+ <name name="latin1_charlist"/>
+ <desc><p>A <c>latin1_binary()</c> is allowed as the tail of
+ the list.</p>
+ </desc>
+ </datatype>
+ </datatypes>
-latin1_charlist() = [latin1_char() | latin1_binary() | latin1_charlist()]
- a latin1_binary is allowed as the tail of the list</code>
- </section>
<funcs>
<func>
- <name>bom_to_encoding(Bin) -> {Encoding,Length}</name>
+ <name name="bom_to_encoding" arity="1"/>
<fsummary>Identify UTF byte order marks in a binary.</fsummary>
- <type>
- <v>Bin = binary() of byte_size 4 or more</v>
- <v>Encoding = latin1 | utf8 | {utf16,little} | {utf16,big} | {utf32,little} | {utf32,big}</v>
- <v>Length = int()</v>
- </type>
+ <type name="endian"/>
+ <type_desc variable="Bin">A binary() of byte_size 4 or more.</type_desc>
<desc>
<p>Check for a UTF byte order mark (BOM) in the beginning of a
- binary. If the supplied binary <c>Bin</c> begins with a valid
+ binary. If the supplied binary <c><anno>Bin</anno></c> begins with a valid
byte order mark for either UTF-8, UTF-16 or UTF-32, the function
returns the encoding identified along with the length of the BOM
in bytes.</p>
@@ -90,23 +123,24 @@ latin1_charlist() = [latin1_char() | latin1_binary() | latin1_charlist()]
</desc>
</func>
<func>
- <name>characters_to_list(Data) -> list() | {error, list(), RestData} | {incomplete, list(), binary()} </name>
+ <name name="characters_to_list" arity="1"/>
<fsummary>Convert a collection of characters to list of Unicode characters</fsummary>
- <type>
- <v>Data = latin1_chardata() | chardata() | external_chardata()</v>
- <v>RestData = latin1_chardata() | chardata() | external_chardata()</v>
- </type>
<desc>
- <p>Same as characters_to_list(Data,unicode).</p>
+ <p>Same as characters_to_list(<anno>Data</anno>,unicode).</p>
</desc>
</func>
<func>
- <name>characters_to_list(Data, InEncoding) -> list() | {error, list(), RestData} | {incomplete, list(), binary()} </name>
+ <name>characters_to_list(Data, InEncoding) -> Result</name>
<fsummary>Convert a collection of characters to list of Unicode characters</fsummary>
<type>
- <v>Data = latin1_chardata() | chardata() | external_chardata()</v>
- <v>RestData = latin1_chardata() | chardata() | external_chardata()</v>
- <v>InEncoding = latin1 | unicode | utf8 | utf16 | utf32 | {utf16,little} | {utf16,big} | {utf32,little} | {utf32,big}</v>
+ <v>Data = <seealso marker="#type-latin1_chardata">latin1_chardata()</seealso>
+ | <seealso marker="#type-chardata">chardata()</seealso>
+ | <seealso marker="#type-external_chardata">external_chardata()</seealso></v>
+ <v>Result = list() | {error, list(), RestData} | {incomplete, list(), binary()}</v>
+ <v>RestData = <seealso marker="#type-latin1_chardata">latin1_chardata()</seealso>
+ | <seealso marker="#type-chardata">chardata()</seealso>
+ | <seealso marker="#type-external_chardata">external_chardata()</seealso></v>
+ <v>InEncoding = <seealso marker="#type-encoding">encoding()</seealso></v>
</type>
<desc>
@@ -164,10 +198,16 @@ latin1_charlist() = [latin1_char() | latin1_binary() | latin1_charlist()]
<item>Integers out of range - If <c>InEncoding</c> is
<c>latin1</c>, an error occurs whenever an integer greater
than 255 is found in the lists. If <c>InEncoding</c> is
- of a Unicode type, error occurs whenever an integer greater than
- <c>16#10FFFF</c> (the maximum unicode character) or in the
- range <c>16#D800</c> to <c>16#DFFF</c> (invalid unicode
- range) is found.</item>
+ of a Unicode type, an error occurs whenever an integer
+ <list type="bulleted">
+ <item>greater than <c>16#10FFFF</c>
+ (the maximum unicode character),</item>
+ <item>in the range <c>16#D800</c> to <c>16#DFFF</c>
+ (invalid unicode range)</item>
+ <item>or equal to 16#FFFE or 16#FFFF (non characters)</item>
+ </list>
+ is found.
+ </item>
<item>UTF encoding incorrect - If <c>InEncoding</c> is
one of the UTF types, the bytes in any binaries have to be valid
@@ -228,44 +268,42 @@ latin1_charlist() = [latin1_char() | latin1_binary() | latin1_charlist()]
</desc>
</func>
<func>
- <name>characters_to_binary(Data) -> binary() | {error, binary(), RestData} | {incomplete, binary(), binary()} </name>
- <fsummary>Convert a collection of characters to an UTF-8 binary</fsummary> <type>
- <v>Data = latin1_chardata() | chardata() | external_chardata()</v>
- <v>RestData = latin1_chardata() | chardata() | external_chardata()</v>
- </type>
+ <name name="characters_to_binary" arity="1"/>
+ <fsummary>Convert a collection of characters to an UTF-8 binary</fsummary>
<desc>
<p>Same as characters_to_binary(Data, unicode, unicode).</p>
</desc>
</func>
<func>
- <name>characters_to_binary(Data,InEncoding) -> binary() | {error, binary(), RestData} | {incomplete, binary(), binary()} </name>
- <fsummary>Convert a collection of characters to an UTF-8 binary</fsummary> <type>
- <v>Data = latin1_chardata() | chardata() | external_chardata()</v>
- <v>RestData = latin1_chardata() | chardata() | external_chardata()</v>
- <v>InEncoding = latin1 | unicode | utf8 | utf16 | utf32 | {utf16,little} | {utf16,big} | {utf32,little} | {utf32,big}</v>
+ <name>characters_to_binary(Data,InEncoding) -> Result</name>
+ <fsummary>Convert a collection of characters to an UTF-8 binary</fsummary>
+
+ <type>
+ <v>Data = <seealso marker="#type-latin1_chardata">latin1_chardata()</seealso>
+ | <seealso marker="#type-chardata">chardata()</seealso>
+ | <seealso marker="#type-external_chardata">external_chardata()</seealso></v>
+ <v>Result = binary() | {error, binary(), RestData} | {incomplete, binary(), binary()}</v>
+ <v>RestData = <seealso marker="#type-latin1_chardata">latin1_chardata()</seealso>
+ | <seealso marker="#type-chardata">chardata()</seealso>
+ | <seealso marker="#type-external_chardata">external_chardata()</seealso></v>
+ <v>InEncoding = <seealso marker="#type-encoding">encoding()</seealso></v>
</type>
<desc>
<p>Same as characters_to_binary(Data, InEncoding, unicode).</p>
</desc>
</func>
<func>
- <name>characters_to_binary(Data, InEncoding, OutEncoding) -> binary() | {error, binary(), RestData} | {incomplete, binary(), binary()} </name>
+ <name name="characters_to_binary" arity="3"/>
<fsummary>Convert a collection of characters to an UTF-8 binary</fsummary>
- <type>
- <v>Data = latin1_chardata() | chardata() | external_chardata()</v>
- <v>RestData = latin1_chardata() | chardata() | external_chardata()</v>
- <v>InEncoding = latin1 | unicode | utf8 | utf16 | utf32 | {utf16,little} | {utf16,big} | {utf32,little} | {utf32,big}</v>
- <v>OutEncoding = latin1 | unicode | utf8 | utf16 | utf32| {utf16,little} | {utf16,big} | {utf32,little} | {utf32,big}</v>
- </type>
<desc>
<p>This function behaves as <seealso
marker="#characters_to_list/2">
characters_to_list/2</seealso>, but produces an binary
instead of a unicode list. The
- <c>InEncoding</c> defines how input is to be interpreted if
+ <c><anno>InEncoding</anno></c> defines how input is to be interpreted if
binaries are present in the <c>Data</c>, while
- <c>OutEncoding</c> defines in what format output is to be
+ <c><anno>OutEncoding</anno></c> defines in what format output is to be
generated.</p>
<p>The option <c>unicode</c> is an alias for <c>utf8</c>, as this is the
@@ -285,17 +323,13 @@ latin1_charlist() = [latin1_char() | latin1_binary() | latin1_charlist()]
</desc>
</func>
<func>
- <name>encoding_to_bom(InEncoding) -> Bin</name>
+ <name name="encoding_to_bom" arity="1"/>
<fsummary>Create a binary UTF byte order mark from encoding.</fsummary>
- <type>
- <v>Bin = binary() of byte_size 4 or less</v>
- <v>InEncoding = latin1 | unicode | utf8 | utf16 | utf32 | {utf16,little} | {utf16,big} | {utf32,little} | {utf32,big}</v>
- <v>Length = int()</v>
- </type>
+ <type_desc variable="Bin">A binary() of byte_size 4 or more.</type_desc>
<desc>
<p>Create an UTF byte order mark (BOM) as a binary from the
- supplied <c>InEncoding</c>. The BOM is, if supported at all,
+ supplied <c><anno>InEncoding</anno></c>. The BOM is, if supported at all,
expected to be placed first in UTF encoded files or
messages.</p>
diff --git a/lib/stdlib/doc/src/unicode_usage.xml b/lib/stdlib/doc/src/unicode_usage.xml
index 416df1f02c..0fa7de0a5c 100644
--- a/lib/stdlib/doc/src/unicode_usage.xml
+++ b/lib/stdlib/doc/src/unicode_usage.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1999</year>
- <year>2010</year>
+ <year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -52,7 +52,7 @@
<tag>UCS-4</tag>
<item>Basically the same as UTF-32, but without some Unicode semantics, defined by IEEE and has little use as a separate encoding standard. For all normal (and possibly abnormal) usages, UTF-32 and UCS-4 are interchangeable.</item>
</taglist>
-<p>Certain ranges of characters are left unused and certain ranges are even deemed invalid. The most notable invalid range is 16#D800 - 16#DFFF, as the UTF-16 encoding does not allow for encoding of these numbers. It can be speculated that the UTF-16 encoding standard was, from the beginning, expected to be able to hold all Unicode characters in one 16-bit entity, but then had to be extended, leaving a whole in the Unicode range to cope with backward compatibility.</p>
+<p>Certain ranges of characters are left unused and certain ranges are even deemed invalid. The most notable invalid range is 16#D800 - 16#DFFF, as the UTF-16 encoding does not allow for encoding of these numbers. It can be speculated that the UTF-16 encoding standard was, from the beginning, expected to be able to hold all Unicode characters in one 16-bit entity, but then had to be extended, leaving a hole in the Unicode range to cope with backward compatibility.</p>
<p>Additionally, the codepoint 16#FEFF is used for byte order marks (BOM's) and use of that character is not encouraged in other contexts than that. It actually is valid though, as the character "ZWNBS" (Zero Width Non Breaking Space). BOM's are used to identify encodings and byte order for programs where such parameters are not known in advance. Byte order marks are more seldom used than one could expect, put their use is becoming more widely spread as they provide the means for programs to make educated guesses about the Unicode format of a certain file.</p>
</section>
<section>
diff --git a/lib/stdlib/doc/src/win32reg.xml b/lib/stdlib/doc/src/win32reg.xml
index 28960cd098..99fd7fdeb6 100644
--- a/lib/stdlib/doc/src/win32reg.xml
+++ b/lib/stdlib/doc/src/win32reg.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2009</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -85,14 +85,22 @@ hkdd HKEY_DYN_DATA</pre>
<p>For additional information on the Windows registry consult the Win32
Programmer's Reference.</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="reg_handle"/>
+ <desc><p>As returned by <seealso marker="#open/1">open/1</seealso>.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="name"/>
+ </datatype>
+ <datatype>
+ <name name="value"/>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>change_key(RegHandle, Key) -> ReturnValue</name>
+ <name name="change_key" arity="2"/>
<fsummary>Move to a key in the registry</fsummary>
- <type>
- <v>RegHandle = term()</v>
- <v>Key = string()</v>
- </type>
<desc>
<p>Changes the current key to another key. Works like cd.
The key can be specified as a relative path or as an
@@ -100,12 +108,8 @@ hkdd HKEY_DYN_DATA</pre>
</desc>
</func>
<func>
- <name>change_key_create(RegHandle, Key) -> ReturnValue</name>
+ <name name="change_key_create" arity="2"/>
<fsummary>Move to a key, create it if it is not there</fsummary>
- <type>
- <v>RegHandle = term()</v>
- <v>Key = string()</v>
- </type>
<desc>
<p>Creates a key, or just changes to it, if it is already there. Works
like a combination of <c>mkdir</c> and <c>cd</c>. Calls the Win32 API function
@@ -114,23 +118,16 @@ hkdd HKEY_DYN_DATA</pre>
</desc>
</func>
<func>
- <name>close(RegHandle)-> ReturnValue</name>
+ <name name="close" arity="1"/>
<fsummary>Close the registry.</fsummary>
- <type>
- <v>RegHandle = term()</v>
- </type>
<desc>
- <p>Closes the registry. After that, the <c>RegHandle</c> cannot
+ <p>Closes the registry. After that, the <c><anno>RegHandle</anno></c> cannot
be used.</p>
</desc>
</func>
<func>
- <name>current_key(RegHandle) -> ReturnValue</name>
+ <name name="current_key" arity="1"/>
<fsummary>Return the path to the current key.</fsummary>
- <type>
- <v>RegHandle = term()</v>
- <v>ReturnValue = {ok, string()}</v>
- </type>
<desc>
<p>Returns the path to the current key. This is the equivalent of <c>pwd</c>.</p>
<p>Note that the current key is stored in the driver, and might be
@@ -138,12 +135,8 @@ hkdd HKEY_DYN_DATA</pre>
</desc>
</func>
<func>
- <name>delete_key(RegHandle) -> ReturnValue</name>
+ <name name="delete_key" arity="1"/>
<fsummary>Delete the current key</fsummary>
- <type>
- <v>RegHandle = term()</v>
- <v>ReturnValue = ok | {error, ErrorId}</v>
- </type>
<desc>
<p>Deletes the current key, if it is valid. Calls the Win32 API
function <c>RegDeleteKey()</c>. Note that this call does not change the current key,
@@ -152,12 +145,8 @@ hkdd HKEY_DYN_DATA</pre>
</desc>
</func>
<func>
- <name>delete_value(RegHandle, Name) -> ReturnValue</name>
+ <name name="delete_value" arity="2"/>
<fsummary>Delete the named value on the current key.</fsummary>
- <type>
- <v>RegHandle = term()</v>
- <v>ReturnValue = ok | {error, ErrorId}</v>
- </type>
<desc>
<p>Deletes a named value on the current key. The atom <c>default</c> is
used for the the default value.</p>
@@ -165,12 +154,8 @@ hkdd HKEY_DYN_DATA</pre>
</desc>
</func>
<func>
- <name>expand(String) -> ExpandedString</name>
+ <name name="expand" arity="1"/>
<fsummary>Expand a string with environment variables</fsummary>
- <type>
- <v>String = string()</v>
- <v>ExpandedString = string()</v>
- </type>
<desc>
<p>Expands a string containing environment variables between percent
characters. Anything between two % is taken for a environment
@@ -180,23 +165,15 @@ hkdd HKEY_DYN_DATA</pre>
</desc>
</func>
<func>
- <name>format_error(ErrorId) -> ErrorString</name>
+ <name name="format_error" arity="1"/>
<fsummary>Convert an POSIX errorcode to a string</fsummary>
- <type>
- <v>ErrorId = atom()</v>
- <v>ErrorString = string()</v>
- </type>
<desc>
<p>Convert an POSIX errorcode to a string (by calling <c>erl_posix_msg:message</c>).</p>
</desc>
</func>
<func>
- <name>open(OpenModeList)-> ReturnValue</name>
+ <name name="open" arity="1"/>
<fsummary>Open the registry for reading or writing</fsummary>
- <type>
- <v>OpenModeList = [OpenMode]</v>
- <v>OpenMode = read | write</v>
- </type>
<desc>
<p>Opens the registry for reading or writing. The current key will be the root
(<c>HKEY_CLASSES_ROOT</c>). The <c>read</c> flag in the mode list can be omitted.</p>
@@ -204,12 +181,8 @@ hkdd HKEY_DYN_DATA</pre>
</desc>
</func>
<func>
- <name>set_value(RegHandle, Name, Value) -> ReturnValue</name>
+ <name name="set_value" arity="3"/>
<fsummary>Set value at the current registry key with specified name.</fsummary>
- <type>
- <v>Name = string() | default</v>
- <v>Value = string() | integer() | binary()</v>
- </type>
<desc>
<p>Sets the named (or default) value to value. Calls the Win32
API function <c>RegSetValueEx()</c>. The value can be of three types, and
@@ -221,13 +194,8 @@ hkdd HKEY_DYN_DATA</pre>
</desc>
</func>
<func>
- <name>sub_keys(RegHandle) -> ReturnValue</name>
+ <name name="sub_keys" arity="1"/>
<fsummary>Get subkeys to the current key.</fsummary>
- <type>
- <v>ReturnValue = {ok, SubKeys} | {error, ErrorId}</v>
- <v>SubKeys = [SubKey]</v>
- <v>SubKey = string()</v>
- </type>
<desc>
<p>Returns a list of subkeys to the current key. Calls the Win32
API function <c>EnumRegKeysEx()</c>.</p>
@@ -235,13 +203,8 @@ hkdd HKEY_DYN_DATA</pre>
</desc>
</func>
<func>
- <name>value(RegHandle, Name) -> ReturnValue</name>
+ <name name="value" arity="2"/>
<fsummary>Get the named value on the current key.</fsummary>
- <type>
- <v>Name = string() | default</v>
- <v>ReturnValue = {ok, Value}</v>
- <v>Value = string() | integer() | binary()</v>
- </type>
<desc>
<p>Retrieves the named value (or default) on the current key.
Registry values of type <c>REG_SZ</c>, are returned as strings. Type <c>REG_DWORD</c>
@@ -249,15 +212,8 @@ hkdd HKEY_DYN_DATA</pre>
</desc>
</func>
<func>
- <name>values(RegHandle) -> ReturnValue</name>
+ <name name="values" arity="1"/>
<fsummary>Get all values on the current key.</fsummary>
- <type>
- <v>ReturnValue = {ok, ValuePairs} | {ok, ErrorId}</v>
- <v>ValuePairs = [ValuePair]</v>
- <v>ValuePair = {Name, Value}</v>
- <v>Name = string | default</v>
- <v>Value = string() | integer() | binary()</v>
- </type>
<desc>
<p>Retrieves a list of all values on the current key. The values
have types corresponding to the registry types, see <c>value</c>.
diff --git a/lib/stdlib/doc/src/zip.xml b/lib/stdlib/doc/src/zip.xml
index 529a70a23d..cf0d581352 100644
--- a/lib/stdlib/doc/src/zip.xml
+++ b/lib/stdlib/doc/src/zip.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2006</year><year>2010</year>
+ <year>2006</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -85,67 +85,55 @@
recreated.</p>
</section>
- <section>
- <title>DATA TYPES</title>
- <code type="none">
-zip_file() </code>
- <p>The record <c>zip_file</c> contains the following fields.</p>
- <taglist>
- <tag><c>name = string()</c></tag>
- <item>
- <p>the name of the file</p>
- </item>
- <tag><c>info = file_info()</c></tag>
- <item>
- <p>file info as in
- <seealso marker="erts:file#read_file_info/1">file:read_file_info/1</seealso></p>
- </item>
- <tag><c>comment = string()</c></tag>
- <item>
- <p>the comment for the file in the zip archive</p>
- </item>
- <tag><c>offset = integer()</c></tag>
- <item>
- <p>the offset of the file in the zip archive (used internally)</p>
- </item>
- <tag><c>comp_size = integer()</c></tag>
- <item>
- <p>the compressed size of the file (the uncompressed size is found
- in <c>info</c>)</p>
- </item>
- </taglist>
- <code type="none">zip_comment</code>
- <p>The record <c>zip_comment</c> just contains the archive comment for
- a zip archive</p>
- <taglist>
- <tag><c>comment = string()</c></tag>
- <item>
- <p>the comment for the zip archive</p>
- </item>
- </taglist>
- </section>
+ <datatypes>
+ <datatype>
+ <name name="zip_comment"/>
+ <desc>
+ <p>The record <c>zip_comment</c> just contains the archive comment for
+ a zip archive</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="zip_file"/>
+ <desc>
+ <p>The record <c>zip_file</c> contains the following fields.</p>
+ <taglist>
+ <tag><c>name</c></tag>
+ <item>
+ <p>the name of the file</p>
+ </item>
+ <tag><c>info</c></tag>
+ <item>
+ <p>file info as in
+ <seealso marker="kernel:file#read_file_info/1">file:read_file_info/1</seealso></p>
+ </item>
+ <tag><c>comment</c></tag>
+ <item>
+ <p>the comment for the file in the zip archive</p>
+ </item>
+ <tag><c>offset</c></tag>
+ <item>
+ <p>the offset of the file in the zip archive (used internally)</p>
+ </item>
+ <tag><c>comp_size</c></tag>
+ <item>
+ <p>the compressed size of the file (the uncompressed size is found
+ in <c>info</c>)</p>
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>zip(Name, FileList) -> RetValue</name>
- <name>zip(Name, FileList, Options) -> RetValue</name>
- <name>create(Name, FileList) -> RetValue</name>
- <name>create(Name, FileList, Options) -> RetValue</name>
+ <name name="zip" arity="2"/>
+ <name name="zip" arity="3"/>
+ <name name="create" arity="2"/>
+ <name name="create" arity="3"/>
<fsummary>Create a zip archive with options</fsummary>
- <type>
- <v>Name = filename()</v>
- <v>FileList = [FileSpec]</v>
- <v>FileSpec = filename() | {filename(), binary()} | {filename(), binary(), #file_info{}}</v>
- <v>Options = [Option]</v>
- <v>Option = memory | cooked | verbose | {comment, Comment} | {cwd, CWD} | {compress, What} | {uncompress, What}</v>
- <v>What = all | [Extension] | {add, [Extension]} | {del, [Extension]}</v>
- <v>Extension = string()</v>
- <v>Comment = CWD = string()</v>
- <v>RetValue = {ok, Name} | {ok, {Name, binary()}} | {error, Reason}</v>
- <v>Reason = term()</v>
- </type>
<desc>
<p>The <marker id="zip_2"></marker><c>zip</c> function creates a
- zip archive containing the files specified in <c>FileList</c>.</p>
+ zip archive containing the files specified in <c><anno>FileList</anno></c>.</p>
<p>As synonyms, the functions <c>create/2</c> and <c>create/3</c>
are provided, to make it resemble the <c>erl_tar</c> module.</p>
<p>The file-list is a list of files, with paths relative to the
@@ -161,9 +149,9 @@ zip_file() </code>
<c>.Z</c>, <c>.zip</c>, <c>.zoo</c>, <c>.arc</c>, <c>.lzh</c>,
<c>.arj</c>.</p>
<p>It is possible to override the default behavior and
- explicitly control what types of files should be
- compressed by using the <c>{compress, What}</c> and
- <c>{uncompress, What}</c> options. It is possible to have
+ explicitly control what types of files that should be
+ compressed by using the <c>{compress, <anno>What</anno>}</c> and
+ <c>{uncompress, <anno>What</anno>}</c> options. It is possible to have
several <c>compress</c> and <c>uncompress</c> options. In
order to trigger compression of a file, its extension must
match with the
@@ -191,22 +179,22 @@ zip_file() </code>
<tag><c>memory</c></tag>
<item>
<p>The output will not be to a file, but instead as a tuple
- <c>{FileName, binary()}</c>. The binary will be a full zip
+ <c>{<anno>FileName</anno>, binary()}</c>. The binary will be a full zip
archive with header, and can be extracted with for instance
<c>unzip/2</c>.</p>
</item>
- <tag><c>{comment, Comment}</c></tag>
+ <tag><c>{comment, <anno>Comment</anno>}</c></tag>
<item>
<p>Add a comment to the zip-archive.</p>
</item>
- <tag><c>{cwd, CWD}</c></tag>
+ <tag><c>{cwd, <anno>CWD</anno>}</c></tag>
<item>
<p>Use the given directory as current directory, it will be
prepended to file names when adding them, although it will not
be in the zip-archive. (Acting like a file:set_cwd/1, but
without changing the global cwd property.)</p>
</item>
- <tag><c>{compress, What}</c></tag>
+ <tag><c>{compress, <anno>What</anno>}</c></tag>
<item>
<p>Controls what types of files will be
compressed. It is by default set to <c>all</c>. The
@@ -215,18 +203,18 @@ zip_file() </code>
<tag><c>all</c></tag>
<item><p> means that all files will be compressed (as long
as they pass the <c>uncompress</c> condition).</p></item>
- <tag><c>[Extension]</c></tag>
+ <tag><c>[<anno>Extension</anno>]</c></tag>
<item><p>means that only files with exactly these extensions
will be compressed.</p></item>
- <tag><c>{add,[Extension]}</c></tag>
+ <tag><c>{add,[<anno>Extension</anno>]}</c></tag>
<item><p>adds these extensions to the list of compress
extensions.</p></item>
- <tag><c>{del,[Extension]}</c></tag>
+ <tag><c>{del,[<anno>Extension</anno>]}</c></tag>
<item><p>deletes these extensions from the list of compress
extensions.</p></item>
</taglist>
</item>
- <tag><c>{uncompress, What}</c></tag>
+ <tag><c>{uncompress, <anno>What</anno>}</c></tag>
<item>
<p>Controls what types of files will be uncompressed. It is by
default set to <c>[".Z",".zip",".zoo",".arc",".lzh",".arj"]</c>.
@@ -234,13 +222,13 @@ zip_file() </code>
<taglist>
<tag><c>all</c></tag>
<item><p> means that no files will be compressed.</p></item>
- <tag><c>[Extension]</c></tag>
+ <tag><c>[<anno>Extension</anno>]</c></tag>
<item><p>means that files with these extensions will be
uncompressed.</p></item>
- <tag><c>{add,[Extension]}</c></tag>
+ <tag><c>{add,[<anno>Extension</anno>]}</c></tag>
<item><p>adds these extensions to the list of uncompress
extensions.</p></item>
- <tag><c>{del,[Extension]}</c></tag>
+ <tag><c>{del,[<anno>Extension</anno>]}</c></tag>
<item><p>deletes these extensions from the list of uncompress
extensions.</p></item>
</taglist>
@@ -249,41 +237,27 @@ zip_file() </code>
</desc>
</func>
<func>
- <name>unzip(Archive) -> RetValue</name>
- <name>unzip(Archive, Options) -> RetValue</name>
- <name>extract(Archive) -> RetValue</name>
- <name>extract(Archive, Options) -> RetValue</name>
+ <name name="unzip" arity="1"/>
+ <name name="unzip" arity="2"/>
+ <name name="extract" arity="1"/>
+ <name name="extract" arity="2"/>
<fsummary>Extract files from a zip archive</fsummary>
- <type>
- <v>Archive = filename() | binary()</v>
- <v>Options = [Option]</v>
- <v>Option = {file_list, FileList} | keep_old_files | verbose | memory | {file_filter, FileFilter} | {cwd, CWD}</v>
- <v>FileList = [filename()]</v>
- <v>FileBinList = [{filename(),binary()}]</v>
- <v>FileFilter = fun(ZipFile) -> true | false</v>
- <v>CWD = string()</v>
- <v>ZipFile = zip_file()</v>
- <v>RetValue = {ok,FileList} | {ok,FileBinList} | {error, Reason} | {error, {Name, Reason}}</v>
- <v>Reason = term()</v>
- </type>
<desc>
- <p>The <marker id="unzip_1"></marker>
-<c>unzip/1</c> function extracts
- all files from a zip archive. The
- <marker id="unzip_2"></marker>
-<c>unzip/2</c> function provides options
- to extract some files, and more.</p>
- <p>If the <c>Archive</c> argument is given as a binary,
+ <p>The <marker id="unzip_1"></marker><c>unzip/1</c> function extracts
+ all files from a zip archive.
+ The <marker id="unzip_2"></marker><c>unzip/2</c> function provides
+ options to extract some files, and more.</p>
+ <p>If the <c><anno>Archive</anno></c> argument is given as a binary,
the contents of the binary is assumed to be a zip archive,
otherwise it should be a filename.</p>
<p>The following options are available:</p>
<taglist>
- <tag><c>{file_list, FileList}</c></tag>
+ <tag><c>{file_list, <anno>FileList</anno>}</c></tag>
<item>
<p>By default, all files will be extracted from the zip
- archive. With the <c>{file_list,FileList}</c> option,
+ archive. With the <c>{file_list, <anno>FileList</anno>}</c> option,
the <c>unzip/2</c> function will only extract the files
- whose names are included in <c>FileList</c>. The full
+ whose names are included in <c><anno>FileList</anno></c>. The full
paths, including the names of all sub directories within
the zip archive, must be specified.</p>
</item>
@@ -329,29 +303,29 @@ zip_file() </code>
</desc>
</func>
<func>
- <name>foldl(Fun, Acc0, Archive) -> {ok, Acc1} | {error, Reason}</name>
+ <name name="foldl" arity="3"/>
<fsummary>Fold a function over all files in a zip archive</fsummary>
- <type>
- <v>Fun = fun(FileInArchive, GetInfo, GetBin, AccIn) -> AccOut</v>
- <v>FileInArchive = filename()</v>
- <v>GetInfo = fun() -> #file_info{}</v>
- <v>GetBin = fun() -> binary()</v>
- <v>Acc0 = Acc1 = AccIn = AccOut = term()</v>
- <v>Archive = filename() | {filename(), binary()}</v>
- </type>
<desc>
<p>The <marker id="foldl_3"></marker> <c>foldl/3</c> function
- calls <c>Fun(FileInArchive, GetInfo, GetBin, AccIn)</c> on
- successive files in the <c>Archive</c>, starting with <c>AccIn
- == Acc0</c>. <c>FileInArchive</c> is the name that the file
- has in the archive. <c>GetInfo</c> is a fun that returns info
- about the the file. <c>GetBin</c> returns the contents of the
- file. Both <c>GetInfo</c> and <c>GetBin</c> must be called
- within the <c>Fun</c>. Their behavior is undefined if they are
- called outside the context of the <c>Fun</c>. The <c>Fun</c>
+ calls <c><anno>Fun</anno>(<anno>FileInArchive</anno>, <anno>GetInfo
+ </anno>, <anno>GetBin</anno>, <anno>AccIn</anno>)</c> on
+ successive files in the <c>Archive</c>, starting with
+ <c><anno>AccIn</anno>
+ == <anno>Acc0</anno></c>. <c><anno>FileInArchive</anno></c> is
+ the name that the file
+ has in the archive. <c><anno>GetInfo</anno></c> is a fun that
+ returns info
+ about the the file. <c><anno>GetBin</anno></c> returns the contents
+ of the
+ file. Both <c><anno>GetInfo</anno></c> and <c><anno>GetBin</anno></c>
+ must be called
+ within the <c><anno>Fun</anno></c>. Their behavior is undefined if
+ they are
+ called outside the context of the <c><anno>Fun</anno></c>.
+ The <c><anno>Fun</anno></c>
must return a new accumulator which is passed to the next
call. <c>foldl/3</c> returns the final value of the
- accumulator. <c>Acc0</c> is returned if the archive is
+ accumulator. <c><anno>Acc0</anno></c> is returned if the archive is
empty. It is not necessary to iterate over all files in the
archive. The iteration may be ended prematurely in a
controlled manner by throwing an exception.</p>
@@ -387,26 +361,16 @@ zip_file() </code>
</desc>
</func>
<func>
- <name>list_dir(Archive) -> RetValue</name>
- <name>list_dir(Archive, Options)</name>
- <name>table(Archive) -> RetValue</name>
- <name>table(Archive, Options)</name>
+ <name name="list_dir" arity="1"/>
+ <name name="list_dir" arity="2"/>
+ <name name="table" arity="1" />
+ <name name="table" arity="2"/>
<fsummary>Retrieve the name of all files in a zip archive</fsummary>
- <type>
- <v>Archive = filename() | binary()</v>
- <v>RetValue = {ok, [Comment, Files]} | {error, Reason}</v>
- <v>Comment = zip_comment()</v>
- <v>Files = [zip_file()]</v>
- <v>Options = [Option]</v>
- <v>Option = cooked</v>
- <v>Reason = term()</v>
- </type>
<desc>
- <p>The <marker id="list_dir_1"></marker>
-<c>list_dir/1</c> function retrieves
- the names of all files in the zip archive <c>Archive</c>. The
- <marker id="list_dir_2"></marker>
-<c>list_dir/2</c> function provides options.</p>
+ <p>The <marker id="list_dir_1"></marker><c>list_dir/1</c>
+ function retrieves the names of all files in the zip archive
+ <c><anno>Archive</anno></c>. The <marker id="list_dir_2"></marker>
+ <c>list_dir/2</c> function provides options.</p>
<p>As synonyms, the functions <c>table/2</c> and <c>table/3</c>
are provided, to make it resemble the <c>erl_tar</c> module.</p>
<p>The result value is the tuple <c>{ok, List}</c>, where <c>List</c>
@@ -425,46 +389,30 @@ zip_file() </code>
</desc>
</func>
<func>
- <name>t(Archive)</name>
+ <name name="t" arity="1"/>
<fsummary>Print the name of each file in a zip archive</fsummary>
- <type>
- <v>Archive = filename() | binary() | ZipHandle</v>
- <v>ZipHandle = pid()</v>
- </type>
<desc>
- <p>The <marker id="t_1"></marker>
-<c>t/1</c> function prints the names
- of all files in the zip archive <c>Archive</c> to the Erlang shell.
+ <p>The <marker id="t_1"></marker><c>t/1</c> function prints the names
+ of all files in the zip archive <c><anno>Archive</anno></c> to the Erlang shell.
(Similar to "<c>tar&nbsp;t</c>".)</p>
</desc>
</func>
<func>
- <name>tt(Archive)</name>
+ <name name="tt" arity="1"/>
<fsummary>Print name and information for each file in a zip archive</fsummary>
- <type>
- <v>Archive = filename() | binary()</v>
- </type>
<desc>
- <p>The <marker id="tt_1"></marker>
-<c>tt/1</c> function prints names and
- information about all files in the zip archive <c>Archive</c> to
+ <p>The <marker id="tt_1"></marker><c>tt/1</c> function prints names and
+ information about all files in the zip archive <c><anno>Archive</anno></c> to
the Erlang shell. (Similar to "<c>tar tv</c>".)</p>
</desc>
</func>
<func>
- <name>zip_open(Archive) -> {ok, ZipHandle} | {error, Reason}</name>
- <name>zip_open(Archive, Options) -> {ok, ZipHandle} | {error, Reason}</name>
+ <name name="zip_open" arity="1"/>
+ <name name="zip_open" arity="2"/>
<fsummary>Open an archive and return a handle to it</fsummary>
- <type>
- <v>Archive = filename() | binary()</v>
- <v>Options = [Option]</v>
- <v>Options = cooked | memory | {cwd, CWD}</v>
- <v>CWD = string()</v>
- <v>ZipHandle = pid()</v>
- </type>
<desc>
- <p>The <marker id="zip_open"></marker>
-<c>zip_open</c> function opens a
+ <p>The <marker id="zip_open"></marker><c>zip_open</c> function
+ opens a
zip archive, and reads and saves its directory. This
means that subsequently reading files from the archive will be
faster than unzipping files one at a time with <c>unzip</c>.</p>
@@ -472,32 +420,21 @@ zip_file() </code>
</desc>
</func>
<func>
- <name>zip_list_dir(ZipHandle) -> Result | {error, Reason}</name>
+ <name name="zip_list_dir" arity="1"/>
<fsummary>Return a table of files in open zip archive</fsummary>
- <type>
- <v>Result = [ZipComment, ZipFile...]</v>
- <v>ZipComment = #zip_comment{}</v>
- <v>ZipFile = #zip_file{}</v>
- <v>ZipHandle = pid()</v>
- </type>
<desc>
- <p>The <marker id="zip_list_dir"></marker>
-<c>zip_list_dir/1</c> function
- returns the file list of an open zip archive.</p>
+ <p>The <marker id="zip_list_dir"></marker>
+ <c>zip_list_dir/1</c> function
+ returns the file list of an open zip archive. The first returned
+ element is the zip archive comment.</p>
</desc>
</func>
<func>
- <name>zip_get(ZipHandle) -> {ok, [Result]} | {error, Reason}</name>
- <name>zip_get(FileName, ZipHandle) -> {ok, Result} | {error, Reason}</name>
+ <name name="zip_get" arity="1"/>
+ <name name="zip_get" arity="2"/>
<fsummary>Extract files from an open archive</fsummary>
- <type>
- <v>FileName = filename()</v>
- <v>ZipHandle = pid()</v>
- <v>Result = filename() | {filename(), binary()}</v>
- </type>
<desc>
- <p>The <marker id="zip_get"></marker>
-<c>zip_get</c> function extracts
+ <p>The <marker id="zip_get"></marker><c>zip_get</c> function extracts
one or all files from an open archive.</p>
<p>The files will be unzipped to memory or to file, depending on
the options given to the <c>zip_open</c> function when the
@@ -505,15 +442,11 @@ zip_file() </code>
</desc>
</func>
<func>
- <name>zip_close(ZipHandle) -> ok | {error, einval}</name>
+ <name name="zip_close" arity="1"/>
<fsummary>Close an open archive</fsummary>
- <type>
- <v>ZipHandle = pid()</v>
- </type>
<desc>
- <p>The <marker id="zip_close"></marker>
-<c>zip_close/1</c> function closes
- a zip archive, previously opened with <c>zip_open</c>. All
+ <p>The <marker id="zip_close"></marker><c>zip_close/1</c> function
+ closes a zip archive, previously opened with <c>zip_open</c>. All
resources are closed, and the handle should not be used after
closing.</p>
</desc>
diff --git a/lib/stdlib/include/zip.hrl b/lib/stdlib/include/zip.hrl
index 2b5ddc1dfe..6e3ed9c78a 100644
--- a/lib/stdlib/include/zip.hrl
+++ b/lib/stdlib/include/zip.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
%%
%% The 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,7 +19,7 @@
-record(zip_file, {
name :: string(), % file name
- info :: #file_info{},
+ info :: file:file_info(),
comment :: string(), % zip file comment
offset :: non_neg_integer(), % offset of file's local header in archive
comp_size :: non_neg_integer() % compressed size
diff --git a/lib/stdlib/src/array.erl b/lib/stdlib/src/array.erl
index 83576c9fd3..2f69e2b0a4 100644
--- a/lib/stdlib/src/array.erl
+++ b/lib/stdlib/src/array.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -163,17 +163,17 @@
-type array_indx() :: non_neg_integer().
--type array_opt() :: 'fixed' | non_neg_integer()
- | {'default', term()} | {'fixed', boolean()}
- | {'size', non_neg_integer()}.
+-type array_opt() :: {'fixed', boolean()} | 'fixed'
+ | {'default', Value :: term()}
+ | {'size', N :: non_neg_integer()}
+ | (N :: non_neg_integer()).
-type array_opts() :: array_opt() | [array_opt()].
--type indx_pair() :: {array_indx(), term()}.
+-type indx_pair() :: {Index :: array_indx(), Value :: term()}.
-type indx_pairs() :: [indx_pair()].
%%--------------------------------------------------------------------------
-%% @spec () -> array()
%% @doc Create a new, extendible array with initial size zero.
%% @equiv new([])
%%
@@ -185,7 +185,6 @@
new() ->
new([]).
-%% @spec (Options::term()) -> array()
%% @doc Create a new array according to the given options. By default,
%% the array is extendible and has initial size zero. Array indices
%% start at 0.
@@ -224,12 +223,11 @@ new() ->
%% @see from_list/2
%% @see fix/1
--spec new(array_opts()) -> array().
+-spec new(Options :: array_opts()) -> array().
new(Options) ->
new_0(Options, 0, false).
-%% @spec (Size::integer(), Options::term()) -> array()
%% @doc Create a new array according to the given size and options. If
%% `Size' is not a nonnegative integer, the call fails with reason
%% `badarg'. By default, the array has fixed size. Note that any size
@@ -245,7 +243,7 @@ new(Options) ->
%%
%% @see new/1
--spec new(non_neg_integer(), array_opts()) -> array().
+-spec new(Size :: non_neg_integer(), Options :: array_opts()) -> array().
new(Size, Options) when is_integer(Size), Size >= 0 ->
new_0(Options, Size, true);
@@ -293,13 +291,12 @@ find_max(_I, M) ->
M.
-%% @spec (X::term()) -> boolean()
%% @doc Returns `true' if `X' appears to be an array, otherwise `false'.
%% Note that the check is only shallow; there is no guarantee that `X'
%% is a well-formed array representation even if this function returns
%% `true'.
--spec is_array(term()) -> boolean().
+-spec is_array(X :: term()) -> boolean().
is_array(#array{size = Size, max = Max})
when is_integer(Size), is_integer(Max) ->
@@ -308,25 +305,23 @@ is_array(_) ->
false.
-%% @spec (array()) -> integer()
%% @doc Get the number of entries in the array. Entries are numbered
%% from 0 to `size(Array)-1'; hence, this is also the index of the first
%% entry that is guaranteed to not have been previously set.
%% @see set/3
%% @see sparse_size/1
--spec size(array()) -> non_neg_integer().
+-spec size(Array :: array()) -> non_neg_integer().
size(#array{size = N}) -> N;
size(_) -> erlang:error(badarg).
-%% @spec (array()) -> term()
%% @doc Get the value used for uninitialized entries.
%%
%% @see new/2
--spec default(array()) -> term().
+-spec default(Array :: array()) -> term().
default(#array{default = D}) -> D;
default(_) -> erlang:error(badarg).
@@ -405,23 +400,21 @@ new_test_() ->
-endif.
-%% @spec (array()) -> array()
%% @doc Fix the size of the array. This prevents it from growing
%% automatically upon insertion; see also {@link set/3}.
%% @see relax/1
--spec fix(array()) -> array().
+-spec fix(Array :: array()) -> array().
fix(#array{}=A) ->
A#array{max = 0}.
-%% @spec (array()) -> boolean()
%% @doc Check if the array has fixed size.
%% Returns `true' if the array is fixed, otherwise `false'.
%% @see fix/1
--spec is_fix(array()) -> boolean().
+-spec is_fix(Array :: array()) -> boolean().
is_fix(#array{max = 0}) -> true;
is_fix(#array{}) -> false.
@@ -455,12 +448,11 @@ fix_test_() ->
-endif.
-%% @spec (array()) -> array()
%% @doc Make the array resizable. (Reverses the effects of {@link
%% fix/1}.)
%% @see fix/1
--spec relax(array()) -> array().
+-spec relax(Array :: array()) -> array().
relax(#array{size = N}=A) ->
A#array{max = find_max(N-1, ?LEAFSIZE)}.
@@ -481,12 +473,11 @@ relax_test_() ->
-endif.
-%% @spec (integer(), array()) -> array()
%% @doc Change the size of the array. If `Size' is not a nonnegative
%% integer, the call fails with reason `badarg'. If the given array has
%% fixed size, the resulting array will also have fixed size.
--spec resize(non_neg_integer(), array()) -> array().
+-spec resize(Size :: non_neg_integer(), Array :: array()) -> array().
resize(Size, #array{size = N, max = M, elements = E}=A)
when is_integer(Size), Size >= 0 ->
@@ -510,8 +501,6 @@ resize(_Size, _) ->
erlang:error(badarg).
-%% @spec (array()) -> array()
-
%% @doc Change the size of the array to that reported by {@link
%% sparse_size/1}. If the given array has fixed size, the resulting
%% array will also have fixed size.
@@ -519,7 +508,7 @@ resize(_Size, _) ->
%% @see resize/2
%% @see sparse_size/1
--spec resize(array()) -> array().
+-spec resize(Array :: array()) -> array().
resize(Array) ->
resize(sparse_size(Array), Array).
@@ -559,7 +548,6 @@ resize_test_() ->
-endif.
-%% @spec (integer(), term(), array()) -> array()
%% @doc Set entry `I' of the array to `Value'. If `I' is not a
%% nonnegative integer, or if the array has fixed size and `I' is larger
%% than the maximum index, the call fails with reason `badarg'.
@@ -570,7 +558,7 @@ resize_test_() ->
%% @see get/2
%% @see reset/2
--spec set(array_indx(), term(), array()) -> array().
+-spec set(I :: array_indx(), Value :: term(), Array :: array()) -> array().
set(I, Value, #array{size = N, max = M, default = D, elements = E}=A)
when is_integer(I), I >= 0 ->
@@ -624,7 +612,6 @@ expand(I, _S, X, D) ->
setelement(I+1, ?NEW_LEAF(D), X).
-%% @spec (integer(), array()) -> term()
%% @doc Get the value of entry `I'. If `I' is not a nonnegative
%% integer, or if the array has fixed size and `I' is larger than the
%% maximum index, the call fails with reason `badarg'.
@@ -634,7 +621,7 @@ expand(I, _S, X, D) ->
%% @see set/3
--spec get(array_indx(), array()) -> term().
+-spec get(I :: array_indx(), Array :: array()) -> term().
get(I, #array{size = N, max = M, elements = E, default = D})
when is_integer(I), I >= 0 ->
@@ -660,7 +647,6 @@ get_1(I, E, _D) ->
element(I+1, E).
-%% @spec (integer(), array()) -> array()
%% @doc Reset entry `I' to the default value for the array.
%% If the value of entry `I' is the default value the array will be
%% returned unchanged. Reset will never change size of the array.
@@ -675,7 +661,7 @@ get_1(I, E, _D) ->
%% TODO: a reset_range function
--spec reset(array_indx(), array()) -> array().
+-spec reset(I :: array_indx(), Array :: array()) -> array().
reset(I, #array{size = N, max = M, default = D, elements = E}=A)
when is_integer(I), I >= 0 ->
@@ -756,13 +742,12 @@ set_get_test_() ->
-endif.
-%% @spec (array()) -> list()
%% @doc Converts the array to a list.
%%
%% @see from_list/2
%% @see sparse_to_list/1
--spec to_list(array()) -> list().
+-spec to_list(Array :: array()) -> list().
to_list(#array{size = 0}) ->
[];
@@ -831,12 +816,11 @@ to_list_test_() ->
-endif.
-%% @spec (array()) -> list()
%% @doc Converts the array to a list, skipping default-valued entries.
%%
%% @see to_list/1
--spec sparse_to_list(array()) -> list().
+-spec sparse_to_list(Array :: array()) -> list().
sparse_to_list(#array{size = 0}) ->
[];
@@ -901,15 +885,13 @@ sparse_to_list_test_() ->
-endif.
-%% @spec (list()) -> array()
%% @equiv from_list(List, undefined)
--spec from_list(list()) -> array().
+-spec from_list(List :: list()) -> array().
from_list(List) ->
from_list(List, undefined).
-%% @spec (list(), term()) -> array()
%% @doc Convert a list to an extendible array. `Default' is used as the value
%% for uninitialized entries of the array. If `List' is not a proper list,
%% the call fails with reason `badarg'.
@@ -917,7 +899,7 @@ from_list(List) ->
%% @see new/2
%% @see to_list/1
--spec from_list(list(), term()) -> array().
+-spec from_list(List :: list(), Default :: term()) -> array().
from_list([], Default) ->
new({default,Default});
@@ -1011,13 +993,12 @@ from_list_test_() ->
-endif.
-%% @spec (array()) -> [{Index::integer(), Value::term()}]
%% @doc Convert the array to an ordered list of pairs `{Index, Value}'.
%%
%% @see from_orddict/2
%% @see sparse_to_orddict/1
--spec to_orddict(array()) -> indx_pairs().
+-spec to_orddict(Array :: array()) -> indx_pairs().
to_orddict(#array{size = 0}) ->
[];
@@ -1104,13 +1085,12 @@ to_orddict_test_() ->
-endif.
-%% @spec (array()) -> [{Index::integer(), Value::term()}]
%% @doc Convert the array to an ordered list of pairs `{Index, Value}',
%% skipping default-valued entries.
%%
%% @see to_orddict/1
--spec sparse_to_orddict(array()) -> indx_pairs().
+-spec sparse_to_orddict(Array :: array()) -> indx_pairs().
sparse_to_orddict(#array{size = 0}) ->
[];
@@ -1188,15 +1168,13 @@ sparse_to_orddict_test_() ->
-endif.
-%% @spec (list()) -> array()
%% @equiv from_orddict(Orddict, undefined)
--spec from_orddict(indx_pairs()) -> array().
+-spec from_orddict(Orddict :: indx_pairs()) -> array().
from_orddict(Orddict) ->
from_orddict(Orddict, undefined).
-%% @spec (list(), term()) -> array()
%% @doc Convert an ordered list of pairs `{Index, Value}' to a
%% corresponding extendible array. `Default' is used as the value for
%% uninitialized entries of the array. If `List' is not a proper,
@@ -1206,7 +1184,7 @@ from_orddict(Orddict) ->
%% @see new/2
%% @see to_orddict/1
--spec from_orddict(indx_pairs(), term()) -> array().
+-spec from_orddict(Orddict :: indx_pairs(), Default :: term()) -> array().
from_orddict([], Default) ->
new({default,Default});
@@ -1392,7 +1370,6 @@ from_orddict_test_() ->
-endif.
-%% @spec (Function, array()) -> array()
%% Function = (Index::integer(), Value::term()) -> term()
%% @doc Map the given function onto each element of the array. The
%% elements are visited in order from the lowest index to the highest.
@@ -1402,7 +1379,8 @@ from_orddict_test_() ->
%% @see foldr/3
%% @see sparse_map/2
--spec map(fun((array_indx(), _) -> _), array()) -> array().
+-spec map(Function, Array :: array()) -> array() when
+ Function :: fun((Index :: array_indx(), Value :: _) -> _).
map(Function, Array=#array{size = N, elements = E, default = D})
when is_function(Function, 2) ->
@@ -1485,7 +1463,6 @@ map_test_() ->
-endif.
-%% @spec (Function, array()) -> array()
%% Function = (Index::integer(), Value::term()) -> term()
%% @doc Map the given function onto each element of the array, skipping
%% default-valued entries. The elements are visited in order from the
@@ -1494,7 +1471,8 @@ map_test_() ->
%%
%% @see map/2
--spec sparse_map(fun((array_indx(), _) -> _), array()) -> array().
+-spec sparse_map(Function, Array :: array()) -> array() when
+ Function :: fun((Index :: array_indx(), Value :: _) -> _).
sparse_map(Function, Array=#array{size = N, elements = E, default = D})
when is_function(Function, 2) ->
@@ -1580,9 +1558,6 @@ sparse_map_test_() ->
-endif.
-%% @spec (Function, InitialAcc::term(), array()) -> term()
-%% Function = (Index::integer(), Value::term(), Acc::term()) ->
-%% term()
%% @doc Fold the elements of the array using the given function and
%% initial accumulator value. The elements are visited in order from the
%% lowest index to the highest. If `Function' is not a function, the
@@ -1592,7 +1567,8 @@ sparse_map_test_() ->
%% @see map/2
%% @see sparse_foldl/3
--spec foldl(fun((array_indx(), _, A) -> B), A, array()) -> B.
+-spec foldl(Function, InitialAcc :: A, Array :: array()) -> B when
+ Function :: fun((Index :: array_indx(), Value :: _, Acc :: A) -> B).
foldl(Function, A, #array{size = N, elements = E, default = D})
when is_function(Function, 3) ->
@@ -1656,9 +1632,6 @@ foldl_test_() ->
-endif.
-%% @spec (Function, InitialAcc::term(), array()) -> term()
-%% Function = (Index::integer(), Value::term(), Acc::term()) ->
-%% term()
%% @doc Fold the elements of the array using the given function and
%% initial accumulator value, skipping default-valued entries. The
%% elements are visited in order from the lowest index to the highest.
@@ -1667,7 +1640,8 @@ foldl_test_() ->
%% @see foldl/3
%% @see sparse_foldr/3
--spec sparse_foldl(fun((array_indx(), _, A) -> B), A, array()) -> B.
+-spec sparse_foldl(Function, InitialAcc :: A, Array :: array()) -> B when
+ Function :: fun((Index :: array_indx(), Value :: _, Acc :: A) -> B).
sparse_foldl(Function, A, #array{size = N, elements = E, default = D})
when is_function(Function, 3) ->
@@ -1735,9 +1709,6 @@ sparse_foldl_test_() ->
-endif.
-%% @spec (Function, InitialAcc::term(), array()) -> term()
-%% Function = (Index::integer(), Value::term(), Acc::term()) ->
-%% term()
%% @doc Fold the elements of the array right-to-left using the given
%% function and initial accumulator value. The elements are visited in
%% order from the highest index to the lowest. If `Function' is not a
@@ -1746,7 +1717,8 @@ sparse_foldl_test_() ->
%% @see foldl/3
%% @see map/2
--spec foldr(fun((array_indx(), _, A) -> B), A, array()) -> B.
+-spec foldr(Function, InitialAcc :: A, Array :: array()) -> B when
+ Function :: fun((Index :: array_indx(), Value :: _, Acc :: A) -> B).
foldr(Function, A, #array{size = N, elements = E, default = D})
when is_function(Function, 3) ->
@@ -1815,9 +1787,6 @@ foldr_test_() ->
-endif.
-%% @spec (Function, InitialAcc::term(), array()) -> term()
-%% Function = (Index::integer(), Value::term(), Acc::term()) ->
-%% term()
%% @doc Fold the elements of the array right-to-left using the given
%% function and initial accumulator value, skipping default-valued
%% entries. The elements are visited in order from the highest index to
@@ -1827,7 +1796,8 @@ foldr_test_() ->
%% @see foldr/3
%% @see sparse_foldl/3
--spec sparse_foldr(fun((array_indx(), _, A) -> B), A, array()) -> B.
+-spec sparse_foldr(Function, InitialAcc :: A, Array :: array()) -> B when
+ Function :: fun((Index :: array_indx(), Value :: _, Acc :: A) -> B).
sparse_foldr(Function, A, #array{size = N, elements = E, default = D})
when is_function(Function, 3) ->
@@ -1870,7 +1840,6 @@ sparse_foldr_3(I, T, Ix, A, F, D) ->
end.
-%% @spec (array()) -> integer()
%% @doc Get the number of entries in the array up until the last
%% non-default valued entry. In other words, returns `I+1' if `I' is the
%% last non-default valued entry in the array, or zero if no such entry
@@ -1878,7 +1847,7 @@ sparse_foldr_3(I, T, Ix, A, F, D) ->
%% @see size/1
%% @see resize/1
--spec sparse_size(array()) -> non_neg_integer().
+-spec sparse_size(Array :: array()) -> non_neg_integer().
sparse_size(A) ->
F = fun (I, _V, _A) -> throw({value, I}) end,
diff --git a/lib/stdlib/src/base64.erl b/lib/stdlib/src/base64.erl
index a14a72ac6d..5d800e87b8 100644
--- a/lib/stdlib/src/base64.erl
+++ b/lib/stdlib/src/base64.erl
@@ -38,7 +38,9 @@
%% Description: Encodes a plain ASCII string (or binary) into base64.
%%-------------------------------------------------------------------------
--spec encode_to_string(string() | binary()) -> ascii_string().
+-spec encode_to_string(Data) -> Base64String when
+ Data :: string() | binary(),
+ Base64String :: ascii_string().
encode_to_string(Bin) when is_binary(Bin) ->
encode_to_string(binary_to_list(Bin));
@@ -53,7 +55,9 @@ encode_to_string(List) when is_list(List) ->
%% Description: Encodes a plain ASCII string (or binary) into base64.
%%-------------------------------------------------------------------------
--spec encode(string() | binary()) -> binary().
+-spec encode(Data) -> Base64 when
+ Data :: string() | binary(),
+ Base64 :: binary().
encode(Bin) when is_binary(Bin) ->
encode_binary(Bin);
@@ -102,14 +106,18 @@ encode_binary(Bin) ->
%% whereas decode crashes if an illegal character is found
%%-------------------------------------------------------------------------
--spec decode(string() | binary()) -> binary().
+-spec decode(Base64) -> Data when
+ Base64 :: string() | binary(),
+ Data :: binary().
decode(Bin) when is_binary(Bin) ->
decode_binary(<<>>, Bin);
decode(List) when is_list(List) ->
list_to_binary(decode_l(List)).
--spec mime_decode(string() | binary()) -> binary().
+-spec mime_decode(Base64) -> Data when
+ Base64 :: string() | binary(),
+ Data :: binary().
mime_decode(Bin) when is_binary(Bin) ->
mime_decode_binary(<<>>, Bin);
@@ -139,14 +147,18 @@ mime_decode_l(List) ->
%% whereas decode crashes if an illegal character is found
%%-------------------------------------------------------------------------
--spec decode_to_string(string() | binary()) -> string().
+-spec decode_to_string(Base64) -> DataString when
+ Base64 :: string() | binary(),
+ DataString :: string().
decode_to_string(Bin) when is_binary(Bin) ->
decode_to_string(binary_to_list(Bin));
decode_to_string(List) when is_list(List) ->
decode_l(List).
--spec mime_decode_to_string(string() | binary()) -> string().
+-spec mime_decode_to_string(Base64) -> DataString when
+ Base64 :: string() | binary(),
+ DataString :: string().
mime_decode_to_string(Bin) when is_binary(Bin) ->
mime_decode_to_string(binary_to_list(Bin));
diff --git a/lib/stdlib/src/beam_lib.erl b/lib/stdlib/src/beam_lib.erl
index 74d4ad3da7..e9a5e6831e 100644
--- a/lib/stdlib/src/beam_lib.erl
+++ b/lib/stdlib/src/beam_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -54,13 +54,9 @@
-type beam() :: module() | file:filename() | binary().
-%% XXX: THE FOLLOWING SHOULD BE IMPORTED FROM SOMEWHERE ELSE
--type forms() :: term().
+-type forms() :: [erl_parse:abstract_form()].
--type abst_vsn() :: atom().
--type abst_code() :: {abst_vsn(), forms()} | 'no_abstract_code'.
--type attribute() :: atom().
--type attrvalue() :: term().
+-type abst_code() :: {AbstVersion :: atom(), forms()} | 'no_abstract_code'.
-type dataB() :: binary().
-type index() :: non_neg_integer().
-type label() :: integer().
@@ -74,9 +70,9 @@
| 'atoms'.
-type chunkref() :: chunkname() | chunkid().
--type attrib_entry() :: {attribute(), [attrvalue()]}.
--type compinfo_entry() :: {atom(), term()}.
--type labeled_entry() :: {atom(), arity(), label()}.
+-type attrib_entry() :: {Attribute :: atom(), [AttributeValue :: term()]}.
+-type compinfo_entry() :: {InfoKey :: atom(), term()}.
+-type labeled_entry() :: {Function :: atom(), arity(), label()}.
-type chunkdata() :: {chunkid(), dataB()}
| {'abstract_code', abst_code()}
@@ -85,20 +81,17 @@
| {'exports', [{atom(), arity()}]}
| {'labeled_exports', [labeled_entry()]}
| {'imports', [mfa()]}
- | {'indexed_imports', [{index(), module(), atom(), arity()}]}
+ | {'indexed_imports', [{index(), module(), Function :: atom(), arity()}]}
| {'locals', [{atom(), arity()}]}
| {'labeled_locals', [labeled_entry()]}
| {'atoms', [{integer(), atom()}]}.
--type info_pair() :: {'file', file:filename()}
- | {'binary', binary()}
- | {'module', module()}
- | {'chunks', [{chunkid(), integer(), integer()}]}.
-
%% Error reasons
-type info_rsn() :: {'chunk_too_big', file:filename(),
- chunkid(), integer(), integer()}
- | {'invalid_beam_file', file:filename(), integer()}
+ chunkid(), ChunkSize :: non_neg_integer(),
+ FileSize :: non_neg_integer()}
+ | {'invalid_beam_file', file:filename(),
+ Position :: non_neg_integer()}
| {'invalid_chunk', file:filename(), chunkid()}
| {'missing_chunk', file:filename(), chunkid()}
| {'not_a_beam_file', file:filename()}
@@ -118,20 +111,34 @@
%% Exported functions
%%
--spec info(beam()) -> [info_pair()] | {'error', 'beam_lib', info_rsn()}.
+-spec info(Beam) -> [InfoPair] | {'error', 'beam_lib', info_rsn()} when
+ Beam :: beam(),
+ InfoPair :: {'file', Filename :: file:filename()}
+ | {'binary', Binary :: binary()}
+ | {'module', Module :: module()}
+ | {'chunks', [{ChunkId :: chunkid(),
+ Pos :: non_neg_integer(),
+ Size :: non_neg_integer()}]}.
info(File) ->
read_info(beam_filename(File)).
--spec chunks(beam(), [chunkref()]) ->
- {'ok', {module(), [chunkdata()]}} | {'error', 'beam_lib', chnk_rsn()}.
+-spec chunks(Beam, ChunkRefs) ->
+ {'ok', {module(), [chunkdata()]}} |
+ {'error', 'beam_lib', chnk_rsn()} when
+ Beam :: beam(),
+ ChunkRefs :: [chunkref()].
chunks(File, Chunks) ->
read_chunk_data(File, Chunks).
--spec chunks(beam(), [chunkref()], ['allow_missing_chunks']) ->
- {'ok', {module(), [{chunkref(), chunkdata() | 'missing_chunk'}]}}
- | {'error', 'beam_lib', chnk_rsn()}.
+-spec chunks(Beam, ChunkRefs, Options) ->
+ {'ok', {module(), [ChunkResult]}} |
+ {'error', 'beam_lib', chnk_rsn()} when
+ Beam :: beam(),
+ ChunkRefs :: [chunkref()],
+ Options :: ['allow_missing_chunks'],
+ ChunkResult :: chunkdata() | {ChunkRef :: chunkref(), 'missing_chunk'}.
chunks(File, Chunks, Options) ->
try read_chunk_data(File, Chunks, Options)
@@ -142,49 +149,65 @@ chunks(File, Chunks, Options) ->
all_chunks(File) ->
read_all_chunks(File).
--spec cmp(beam(), beam()) -> 'ok' | {'error', 'beam_lib', cmp_rsn()}.
+-spec cmp(Beam1, Beam2) -> 'ok' | {'error', 'beam_lib', cmp_rsn()} when
+ Beam1 :: beam(),
+ Beam2 :: beam().
cmp(File1, File2) ->
try cmp_files(File1, File2)
catch Error -> Error end.
--spec cmp_dirs(atom() | file:filename(), atom() | file:filename()) ->
- {[file:filename()], [file:filename()],
- [{file:filename(), file:filename()}]}
- | {'error', 'beam_lib', {'not_a_directory', term()} | info_rsn()}.
+-spec cmp_dirs(Dir1, Dir2) ->
+ {Only1, Only2, Different} | {'error', 'beam_lib', Reason} when
+ Dir1 :: atom() | file:filename(),
+ Dir2 :: atom() | file:filename(),
+ Only1 :: [file:filename()],
+ Only2 :: [file:filename()],
+ Different :: [{Filename1 :: file:filename(), Filename2 :: file:filename()}],
+ Reason :: {'not_a_directory', term()} | info_rsn().
cmp_dirs(Dir1, Dir2) ->
catch compare_dirs(Dir1, Dir2).
--spec diff_dirs(atom() | file:filename(), atom() | file:filename()) ->
- 'ok' | {'error', 'beam_lib', {'not_a_directory', term()} | info_rsn()}.
+-spec diff_dirs(Dir1, Dir2) -> 'ok' | {'error', 'beam_lib', Reason} when
+ Dir1 :: atom() | file:filename(),
+ Dir2 :: atom() | file:filename(),
+ Reason :: {'not_a_directory', term()} | info_rsn().
diff_dirs(Dir1, Dir2) ->
catch diff_directories(Dir1, Dir2).
--spec strip(beam()) ->
- {'ok', {module(), beam()}} | {'error', 'beam_lib', info_rsn()}.
+-spec strip(Beam1) ->
+ {'ok', {module(), Beam2}} | {'error', 'beam_lib', info_rsn()} when
+ Beam1 :: beam(),
+ Beam2 :: beam().
strip(FileName) ->
try strip_file(FileName)
catch Error -> Error end.
--spec strip_files([beam()]) ->
- {'ok', [{module(), beam()}]} | {'error', 'beam_lib', info_rsn()}.
+-spec strip_files(Files) ->
+ {'ok', [{module(), Beam}]} | {'error', 'beam_lib', info_rsn()} when
+ Files :: [beam()],
+ Beam :: beam().
strip_files(Files) when is_list(Files) ->
try strip_fils(Files)
catch Error -> Error end.
--spec strip_release(atom() | file:filename()) ->
+-spec strip_release(Dir) ->
{'ok', [{module(), file:filename()}]}
- | {'error', 'beam_lib', {'not_a_directory', term()} | info_rsn()}.
+ | {'error', 'beam_lib', Reason} when
+ Dir :: atom() | file:filename(),
+ Reason :: {'not_a_directory', term()} | info_rsn().
strip_release(Root) ->
catch strip_rel(Root).
--spec version(beam()) ->
- {'ok', {module(), [term()]}} | {'error', 'beam_lib', chnk_rsn()}.
+-spec version(Beam) ->
+ {'ok', {module(), [Version :: term()]}} |
+ {'error', 'beam_lib', chnk_rsn()} when
+ Beam :: beam().
version(File) ->
case catch read_chunk_data(File, [attributes]) of
@@ -195,11 +218,13 @@ version(File) ->
Error
end.
--spec md5(beam()) ->
- {'ok', {module(), binary()}} | {'error', 'beam_lib', chnk_rsn()}.
+-spec md5(Beam) ->
+ {'ok', {module(), MD5}} | {'error', 'beam_lib', chnk_rsn()} when
+ Beam :: beam(),
+ MD5 :: binary().
md5(File) ->
- case catch read_significant_chunks(File) of
+ case catch read_significant_chunks(File, md5_chunks()) of
{ok, {Module, Chunks0}} ->
Chunks = filter_funtab(Chunks0),
{ok, {Module, erlang:md5([C || {_Id, C} <- Chunks])}};
@@ -207,7 +232,8 @@ md5(File) ->
Error
end.
--spec format_error(term()) -> [char() | string()].
+-spec format_error(Reason) -> io_lib:chars() when
+ Reason :: term().
format_error({error, Error}) ->
format_error(Error);
@@ -260,12 +286,15 @@ format_error(E) ->
| {'debug_info', mode(), module(), file:filename()}.
-type crypto_fun() :: fun((crypto_fun_arg()) -> term()).
--spec crypto_key_fun(crypto_fun()) -> 'ok' | {'error', term()}.
+-spec crypto_key_fun(CryptoKeyFun) -> 'ok' | {'error', Reason} when
+ CryptoKeyFun :: crypto_fun(),
+ Reason :: badfun | exists | term().
crypto_key_fun(F) ->
call_crypto_server({crypto_key_fun, F}).
--spec clear_crypto_key_fun() -> 'undefined' | {'ok', term()}.
+-spec clear_crypto_key_fun() -> 'undefined' | {'ok', Result} when
+ Result :: 'undefined' | term().
clear_crypto_key_fun() ->
call_crypto_server(clear_crypto_key_fun).
@@ -366,7 +395,7 @@ strip_fils(Files) ->
%% -> {ok, {Mod, FileName}} | {ok, {Mod, binary()}} | throw(Error)
strip_file(File) ->
- {ok, {Mod, Chunks}} = read_significant_chunks(File),
+ {ok, {Mod, Chunks}} = read_significant_chunks(File, significant_chunks()),
{ok, Stripped0} = build_module(Chunks),
Stripped = compress(Stripped0),
case File of
@@ -424,8 +453,8 @@ is_useless_chunk("CInf") -> true;
is_useless_chunk(_) -> false.
%% -> {ok, {Module, Chunks}} | throw(Error)
-read_significant_chunks(File) ->
- case read_chunk_data(File, significant_chunks(), [allow_missing_chunks]) of
+read_significant_chunks(File, ChunkList) ->
+ case read_chunk_data(File, ChunkList, [allow_missing_chunks]) of
{ok, {Module, Chunks0}} ->
Mandatory = mandatory_chunks(),
Chunks = filter_significant_chunks(Chunks0, Mandatory, File, Module),
@@ -806,12 +835,15 @@ file_error(FileName, {error, Reason}) ->
error(Reason) ->
throw({error, ?MODULE, Reason}).
-
-%% The following chunks are significant when calculating the MD5 for a module,
-%% and also the modules that must be retained when stripping a file.
-%% They are listed in the order that they should be MD5:ed.
+%% The following chunks must be kept when stripping a BEAM file.
significant_chunks() ->
+ ["Line" | md5_chunks()].
+
+%% The following chunks are significant when calculating the MD5
+%% for a module. They are listed in the order that they should be MD5:ed.
+
+md5_chunks() ->
["Atom", "Code", "StrT", "ImpT", "ExpT", "FunT", "LitT"].
%% The following chunks are mandatory in every Beam file.
@@ -864,13 +896,17 @@ call_crypto_server(Req) ->
gen_server:call(?CRYPTO_KEY_SERVER, Req, infinity)
catch
exit:{noproc,_} ->
- start_crypto_server(),
- erlang:yield(),
- call_crypto_server(Req)
+ %% Not started.
+ call_crypto_server_1(Req);
+ exit:{normal,_} ->
+ %% The process finished just as we called it.
+ call_crypto_server_1(Req)
end.
-start_crypto_server() ->
- gen_server:start({local,?CRYPTO_KEY_SERVER}, ?MODULE, [], []).
+call_crypto_server_1(Req) ->
+ gen_server:start({local,?CRYPTO_KEY_SERVER}, ?MODULE, [], []),
+ erlang:yield(),
+ call_crypto_server(Req).
-spec init([]) -> {'ok', #state{}}.
diff --git a/lib/stdlib/src/binary.erl b/lib/stdlib/src/binary.erl
index f6489788b2..cb1e12ae46 100644
--- a/lib/stdlib/src/binary.erl
+++ b/lib/stdlib/src/binary.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
%%
%% The 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,11 +38,28 @@
%% Implemented in this module:
-export([split/2,split/3,replace/3,replace/4]).
+-opaque cp() :: tuple().
+-type part() :: {Start :: non_neg_integer(), Length :: integer()}.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% split
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-spec split(Subject, Pattern) -> Parts when
+ Subject :: binary(),
+ Pattern :: binary() | [binary()] | cp(),
+ Parts :: [binary()].
+
split(H,N) ->
split(H,N,[]).
+
+-spec split(Subject, Pattern, Options) -> Parts when
+ Subject :: binary(),
+ Pattern :: binary() | [binary()] | cp(),
+ Options :: [Option],
+ Option :: {scope, part()} | trim | global,
+ Parts :: [binary()].
+
split(Haystack,Needles,Options) ->
try
{Part,Global,Trim} = get_opts_split(Options,{no,false,false}),
@@ -89,8 +106,26 @@ do_split(H,[{A,B}|T],N,Trim) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% replace
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-spec replace(Subject, Pattern, Replacement) -> Result when
+ Subject :: binary(),
+ Pattern :: binary() | [ binary() ] | cp(),
+ Replacement :: binary(),
+ Result :: binary().
+
replace(H,N,R) ->
replace(H,N,R,[]).
+
+-spec replace(Subject, Pattern, Replacement, Options) -> Result when
+ Subject :: binary(),
+ Pattern :: binary() | [ binary() ] | cp(),
+ Replacement :: binary(),
+ Options :: [Option],
+ Option :: global | {scope, part()} | {insert_replaced, InsPos},
+ InsPos :: OnePos | [ OnePos ],
+ OnePos :: non_neg_integer(),
+ Result :: binary().
+
replace(Haystack,Needles,Replacement,Options) ->
try
true = is_binary(Replacement), % Make badarg instead of function clause
diff --git a/lib/stdlib/src/c.erl b/lib/stdlib/src/c.erl
index 235ea939a8..a920921a5e 100644
--- a/lib/stdlib/src/c.erl
+++ b/lib/stdlib/src/c.erl
@@ -71,11 +71,16 @@ help() ->
%% c(FileName)
%% Compile a file/module.
--spec c(file:name()) -> {'ok', module()} | 'error'.
+-spec c(File) -> {'ok', Module} | 'error' when
+ File :: file:name(),
+ Module :: module().
c(File) -> c(File, []).
--spec c(file:name(), [compile:option()]) -> {'ok', module()} | 'error'.
+-spec c(File, Options) -> {'ok', Module} | 'error' when
+ File :: file:name(),
+ Options :: [compile:option()],
+ Module :: module().
c(File, Opts0) when is_list(Opts0) ->
Opts = [report_errors,report_warnings|Opts0],
@@ -140,7 +145,8 @@ check_load(_, Mod) -> {ok, Mod}.
%% with constant c2 defined, c1=v1 (v1 must be a term!), include dir
%% IDir, outdir ODir.
--spec lc([erl_compile:cmd_line_arg()]) -> 'ok' | 'error'.
+-spec lc(Files) -> 'ok' | 'error' when
+ Files :: [File :: erl_compile:cmd_line_arg()].
lc(Args) ->
case catch split(Args, [], []) of
@@ -205,12 +211,17 @@ make_term(Str) ->
throw(error)
end.
--spec nc(file:name()) -> {'ok', module()} | 'error'.
+-spec nc(File) -> {'ok', Module} | 'error' when
+ File :: file:name(),
+ Module :: module().
nc(File) -> nc(File, []).
--spec nc(file:name(), [compile:option()] | compile:option()) ->
- {'ok', module} | 'error'.
+-spec nc(File, Options) -> {'ok', Module} | 'error' when
+ File :: file:name(),
+ Options :: [Option] | Option,
+ Option:: compile:option(),
+ Module :: module().
nc(File, Opts0) when is_list(Opts0) ->
Opts = Opts0 ++ [report_errors, report_warnings],
@@ -234,14 +245,17 @@ nc(File, Opt) when is_atom(Opt) ->
%% l(Mod)
%% Reload module Mod from file of same name
--spec l(module()) -> code:load_ret().
+-spec l(Module) -> code:load_ret() when
+ Module :: module().
l(Mod) ->
code:purge(Mod),
code:load_file(Mod).
%% Network version of l/1
-%%-spec nl(module()) ->
+-spec nl(Module) -> abcast | error when
+ Module :: module().
+
nl(Mod) ->
case code:get_object_code(Mod) of
{_Module, Bin, Fname} ->
@@ -396,15 +410,20 @@ fetch(Key, Info) ->
false -> 0
end.
--spec pid(non_neg_integer(), non_neg_integer(), non_neg_integer()) -> pid().
+-spec pid(X, Y, Z) -> pid() when
+ X :: non_neg_integer(),
+ Y :: non_neg_integer(),
+ Z :: non_neg_integer().
pid(X, Y, Z) ->
list_to_pid("<" ++ integer_to_list(X) ++ "." ++
integer_to_list(Y) ++ "." ++
integer_to_list(Z) ++ ">").
--spec i(non_neg_integer(), non_neg_integer(), non_neg_integer()) ->
- [{atom(), term()}].
+-spec i(X, Y, Z) -> [{atom(), term()}] when
+ X :: non_neg_integer(),
+ Y :: non_neg_integer(),
+ Z :: non_neg_integer().
i(X, Y, Z) -> pinfo(pid(X, Y, Z)).
@@ -413,7 +432,8 @@ i(X, Y, Z) -> pinfo(pid(X, Y, Z)).
q() ->
init:stop().
--spec bt(pid()) -> 'ok' | 'undefined'.
+-spec bt(Pid) -> 'ok' | 'undefined' when
+ Pid :: pid().
bt(Pid) ->
case catch erlang:process_display(Pid, backtrace) of
@@ -476,7 +496,8 @@ bi(I) ->
%%
%% Short and nice form of module info
%%
--spec m(module()) -> 'ok'.
+-spec m(Module) -> 'ok' when
+ Module :: module().
m(M) ->
L = M:module_info(),
@@ -664,7 +685,8 @@ pwd() ->
ok = io:format("Cannot determine current directory\n")
end.
--spec cd(file:name()) -> 'ok'.
+-spec cd(Dir) -> 'ok' when
+ Dir :: file:name().
cd(Dir) ->
file:set_cwd(Dir),
@@ -679,7 +701,8 @@ cd(Dir) ->
ls() ->
ls(".").
--spec ls(file:name()) -> 'ok'.
+-spec ls(Dir) -> 'ok' when
+ Dir :: file:name().
ls(Dir) ->
case file:list_dir(Dir) of
@@ -729,12 +752,19 @@ w(X) ->
%% memory/[0,1]
%%
--spec memory() -> [{atom(), non_neg_integer()}].
+-spec memory() -> [{Type, Size}] when
+ Type :: atom(),
+ Size :: non_neg_integer().
memory() -> erlang:memory().
--spec memory(atom()) -> non_neg_integer()
- ; ([atom()]) -> [{atom(), non_neg_integer()}].
+-spec memory(Type) -> Size when
+ Type :: atom(),
+ Size :: non_neg_integer()
+ ; (Types) -> [{Type, Size}] when
+ Types :: [Type],
+ Type :: atom(),
+ Size :: non_neg_integer().
memory(TypeSpec) -> erlang:memory(TypeSpec).
@@ -767,7 +797,7 @@ appcall(App, M, F, Args) ->
catch
error:undef ->
case erlang:get_stacktrace() of
- [{M,F,Args}|_] ->
+ [{M,F,Args,_}|_] ->
Arity = length(Args),
io:format("Call to ~w:~w/~w in application ~w failed.\n",
[M,F,Arity,App]);
diff --git a/lib/stdlib/src/calendar.erl b/lib/stdlib/src/calendar.erl
index 33725d999c..0320e0cd0e 100644
--- a/lib/stdlib/src/calendar.erl
+++ b/lib/stdlib/src/calendar.erl
@@ -63,6 +63,8 @@
%% Types
%%----------------------------------------------------------------------
+-export_type([date/0, time/0, datetime/0, datetime1970/0]).
+
-type year() :: non_neg_integer().
-type year1970() :: 1970..10000. % should probably be 1970..
-type month() :: 1..12.
@@ -74,13 +76,11 @@
-type ldom() :: 28 | 29 | 30 | 31. % last day of month
-type weeknum() :: 1..53.
--type t_now() :: {non_neg_integer(),non_neg_integer(),non_neg_integer()}.
-
--type t_date() :: {year(),month(),day()}.
--type t_time() :: {hour(),minute(),second()}.
--type t_datetime() :: {t_date(),t_time()}.
--type t_datetime1970() :: {{year1970(),month(),day()},t_time()}.
--type t_yearweeknum() :: {year(),weeknum()}.
+-type date() :: {year(),month(),day()}.
+-type time() :: {hour(),minute(),second()}.
+-type datetime() :: {date(),time()}.
+-type datetime1970() :: {{year1970(),month(),day()},time()}.
+-type yearweeknum() :: {year(),weeknum()}.
%%----------------------------------------------------------------------
@@ -106,7 +106,11 @@
%% January 1st.
%%
%% df/2 catches the case Year<0
--spec date_to_gregorian_days(year(),month(),day()) -> non_neg_integer().
+-spec date_to_gregorian_days(Year, Month, Day) -> Days when
+ Year :: year(),
+ Month :: month(),
+ Day :: day(),
+ Days :: non_neg_integer().
date_to_gregorian_days(Year, Month, Day) when is_integer(Day), Day > 0 ->
Last = last_day_of_the_month(Year, Month),
if
@@ -114,7 +118,9 @@ date_to_gregorian_days(Year, Month, Day) when is_integer(Day), Day > 0 ->
dy(Year) + dm(Month) + df(Year, Month) + Day - 1
end.
--spec date_to_gregorian_days(t_date()) -> non_neg_integer().
+-spec date_to_gregorian_days(Date) -> Days when
+ Date :: date(),
+ Days :: non_neg_integer().
date_to_gregorian_days({Year, Month, Day}) ->
date_to_gregorian_days(Year, Month, Day).
@@ -124,7 +130,9 @@ date_to_gregorian_days({Year, Month, Day}) ->
%% Computes the total number of seconds starting from year 0,
%% January 1st.
%%
--spec datetime_to_gregorian_seconds(t_datetime()) -> non_neg_integer().
+-spec datetime_to_gregorian_seconds(DateTime) -> Seconds when
+ DateTime :: datetime(),
+ Seconds :: non_neg_integer().
datetime_to_gregorian_seconds({Date, Time}) ->
?SECONDS_PER_DAY*date_to_gregorian_days(Date) +
time_to_seconds(Time).
@@ -135,18 +143,23 @@ datetime_to_gregorian_seconds({Date, Time}) ->
%%
%% Returns: 1 | .. | 7. Monday = 1, Tuesday = 2, ..., Sunday = 7.
%%
--spec day_of_the_week(year(), month(), day()) -> daynum().
+-spec day_of_the_week(Year, Month, Day) -> daynum() when
+ Year :: year(),
+ Month :: month(),
+ Day :: day().
day_of_the_week(Year, Month, Day) ->
(date_to_gregorian_days(Year, Month, Day) + 5) rem 7 + 1.
--spec day_of_the_week(t_date()) -> daynum().
+-spec day_of_the_week(Date) -> daynum() when
+ Date:: date().
day_of_the_week({Year, Month, Day}) ->
day_of_the_week(Year, Month, Day).
%% gregorian_days_to_date(Days) = {Year, Month, Day}
%%
--spec gregorian_days_to_date(non_neg_integer()) -> t_date().
+-spec gregorian_days_to_date(Days) -> date() when
+ Days :: non_neg_integer().
gregorian_days_to_date(Days) ->
{Year, DayOfYear} = day_to_year(Days),
{Month, DayOfMonth} = year_day_to_date(Year, DayOfYear),
@@ -155,7 +168,8 @@ gregorian_days_to_date(Days) ->
%% gregorian_seconds_to_datetime(Secs)
%%
--spec gregorian_seconds_to_datetime(non_neg_integer()) -> t_datetime().
+-spec gregorian_seconds_to_datetime(Seconds) -> datetime() when
+ Seconds :: non_neg_integer().
gregorian_seconds_to_datetime(Secs) when Secs >= 0 ->
Days = Secs div ?SECONDS_PER_DAY,
Rest = Secs rem ?SECONDS_PER_DAY,
@@ -164,7 +178,8 @@ gregorian_seconds_to_datetime(Secs) when Secs >= 0 ->
%% is_leap_year(Year) = true | false
%%
--spec is_leap_year(year()) -> boolean().
+-spec is_leap_year(Year) -> boolean() when
+ Year :: year().
is_leap_year(Y) when is_integer(Y), Y >= 0 ->
is_leap_year1(Y).
@@ -179,7 +194,7 @@ is_leap_year1(_) -> false.
%%
%% Calculates the iso week number for the current date.
%%
--spec iso_week_number() -> t_yearweeknum().
+-spec iso_week_number() -> yearweeknum().
iso_week_number() ->
{Date, _} = local_time(),
iso_week_number(Date).
@@ -188,7 +203,8 @@ iso_week_number() ->
%%
%% Calculates the iso week number for the given date.
%%
--spec iso_week_number(t_date()) -> t_yearweeknum().
+-spec iso_week_number(Date) -> yearweeknum() when
+ Date :: date().
iso_week_number({Year, Month, Day}) ->
D = date_to_gregorian_days({Year, Month, Day}),
W01_1_Year = gregorian_days_of_iso_w01_1(Year),
@@ -216,7 +232,10 @@ iso_week_number({Year, Month, Day}) ->
%%
%% Returns the number of days in a month.
%%
--spec last_day_of_the_month(year(), month()) -> ldom().
+-spec last_day_of_the_month(Year, Month) -> LastDay when
+ Year :: year(),
+ Month :: month(),
+ LastDay :: ldom().
last_day_of_the_month(Y, M) when is_integer(Y), Y >= 0 ->
last_day_of_the_month1(Y, M).
@@ -237,24 +256,28 @@ last_day_of_the_month1(_, M) when is_integer(M), M > 0, M < 13 ->
%% local_time()
%%
%% Returns: {date(), time()}, date() = {Y, M, D}, time() = {H, M, S}.
--spec local_time() -> t_datetime().
+-spec local_time() -> datetime().
local_time() ->
erlang:localtime().
%% local_time_to_universal_time(DateTime)
%%
--spec local_time_to_universal_time(t_datetime1970()) -> t_datetime1970().
+-spec local_time_to_universal_time(DateTime1) -> DateTime2 when
+ DateTime1 :: datetime1970(),
+ DateTime2 :: datetime1970().
local_time_to_universal_time(DateTime) ->
erlang:localtime_to_universaltime(DateTime).
--spec local_time_to_universal_time(t_datetime1970(),
+-spec local_time_to_universal_time(datetime1970(),
'true' | 'false' | 'undefined') ->
- t_datetime1970().
+ datetime1970().
local_time_to_universal_time(DateTime, IsDst) ->
erlang:localtime_to_universaltime(DateTime, IsDst).
--spec local_time_to_universal_time_dst(t_datetime1970()) -> [t_datetime1970()].
+-spec local_time_to_universal_time_dst(DateTime1) -> [DateTime] when
+ DateTime1 :: datetime1970(),
+ DateTime :: datetime1970().
local_time_to_universal_time_dst(DateTime) ->
UtDst = erlang:localtime_to_universaltime(DateTime, true),
Ut = erlang:localtime_to_universaltime(DateTime, false),
@@ -282,12 +305,14 @@ local_time_to_universal_time_dst(DateTime) ->
%% = MilliSec = integer()
%% Returns: {date(), time()}, date() = {Y, M, D}, time() = {H, M, S}.
%%
--spec now_to_datetime(t_now()) -> t_datetime1970().
+-spec now_to_datetime(Now) -> datetime1970() when
+ Now :: erlang:timestamp().
now_to_datetime({MSec, Sec, _uSec}) ->
Sec0 = MSec*1000000 + Sec + ?DAYS_FROM_0_TO_1970*?SECONDS_PER_DAY,
gregorian_seconds_to_datetime(Sec0).
--spec now_to_universal_time(t_now()) -> t_datetime1970().
+-spec now_to_universal_time(Now) -> datetime1970() when
+ Now :: erlang:timestamp().
now_to_universal_time(Now) ->
now_to_datetime(Now).
@@ -296,7 +321,8 @@ now_to_universal_time(Now) ->
%%
%% Args: Now = now()
%%
--spec now_to_local_time(t_now()) -> t_datetime1970().
+-spec now_to_local_time(Now) -> datetime1970() when
+ Now :: erlang:timestamp().
now_to_local_time({MSec, Sec, _uSec}) ->
erlang:universaltime_to_localtime(
now_to_universal_time({MSec, Sec, _uSec})).
@@ -305,7 +331,10 @@ now_to_local_time({MSec, Sec, _uSec}) ->
%% seconds_to_daystime(Secs) = {Days, {Hour, Minute, Second}}
%%
--spec seconds_to_daystime(integer()) -> {integer(), t_time()}.
+-spec seconds_to_daystime(Seconds) -> {Days, Time} when
+ Seconds :: integer(),
+ Days :: integer(),
+ Time :: time().
seconds_to_daystime(Secs) ->
Days0 = Secs div ?SECONDS_PER_DAY,
Secs0 = Secs rem ?SECONDS_PER_DAY,
@@ -323,7 +352,8 @@ seconds_to_daystime(Secs) ->
%% Wraps.
%%
-type secs_per_day() :: 0..?SECONDS_PER_DAY.
--spec seconds_to_time(secs_per_day()) -> t_time().
+-spec seconds_to_time(Seconds) -> time() when
+ Seconds :: secs_per_day().
seconds_to_time(Secs) when Secs >= 0, Secs < ?SECONDS_PER_DAY ->
Secs0 = Secs rem ?SECONDS_PER_DAY,
Hour = Secs0 div ?SECONDS_PER_HOUR,
@@ -340,8 +370,11 @@ seconds_to_time(Secs) when Secs >= 0, Secs < ?SECONDS_PER_DAY ->
%% Date = {Year, Month, Day}, Time = {Hour, Minute, Sec},
%% Year = Month = Day = Hour = Minute = Sec = integer()
%%
--type timediff() :: {integer(), t_time()}.
--spec time_difference(t_datetime(), t_datetime()) -> timediff().
+-spec time_difference(T1, T2) -> {Days, Time} when
+ T1 :: datetime(),
+ T2 :: datetime(),
+ Days :: integer(),
+ Time :: time().
time_difference({{Y1, Mo1, D1}, {H1, Mi1, S1}},
{{Y2, Mo2, D2}, {H2, Mi2, S2}}) ->
Secs = datetime_to_gregorian_seconds({{Y2, Mo2, D2}, {H2, Mi2, S2}}) -
@@ -352,7 +385,8 @@ time_difference({{Y1, Mo1, D1}, {H1, Mi1, S1}},
%%
%% time_to_seconds(Time)
%%
--spec time_to_seconds(t_time()) -> secs_per_day().
+-spec time_to_seconds(Time) -> secs_per_day() when
+ Time :: time().
time_to_seconds({H, M, S}) when is_integer(H), is_integer(M), is_integer(S) ->
H * ?SECONDS_PER_HOUR +
M * ?SECONDS_PER_MINUTE + S.
@@ -361,14 +395,15 @@ time_to_seconds({H, M, S}) when is_integer(H), is_integer(M), is_integer(S) ->
%% universal_time()
%%
%% Returns: {date(), time()}, date() = {Y, M, D}, time() = {H, M, S}.
--spec universal_time() -> t_datetime().
+-spec universal_time() -> datetime().
universal_time() ->
erlang:universaltime().
%% universal_time_to_local_time(DateTime)
%%
--spec universal_time_to_local_time(t_datetime()) -> t_datetime().
+-spec universal_time_to_local_time(DateTime) -> datetime() when
+ DateTime :: datetime1970().
universal_time_to_local_time(DateTime) ->
erlang:universaltime_to_localtime(DateTime).
@@ -376,7 +411,10 @@ universal_time_to_local_time(DateTime) ->
%% valid_date(Year, Month, Day) = true | false
%% valid_date({Year, Month, Day}) = true | false
%%
--spec valid_date(integer(), integer(), integer()) -> boolean().
+-spec valid_date(Year, Month, Day) -> boolean() when
+ Year :: integer(),
+ Month :: integer(),
+ Day :: integer().
valid_date(Y, M, D) when is_integer(Y), is_integer(M), is_integer(D) ->
valid_date1(Y, M, D).
@@ -386,7 +424,8 @@ valid_date1(Y, M, D) when Y >= 0, M > 0, M < 13, D > 0 ->
valid_date1(_, _, _) ->
false.
--spec valid_date({integer(),integer(),integer()}) -> boolean().
+-spec valid_date(Date) -> boolean() when
+ Date :: date().
valid_date({Y, M, D}) ->
valid_date(Y, M, D).
diff --git a/lib/stdlib/src/dets.erl b/lib/stdlib/src/dets.erl
index 6c91f1efb7..c0f9ce34b0 100644
--- a/lib/stdlib/src/dets.erl
+++ b/lib/stdlib/src/dets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -97,10 +97,6 @@
-include("dets.hrl").
--type object() :: tuple().
--type pattern() :: atom() | tuple().
--type tab_name() :: atom() | reference().
-
%%% This is the implementation of the mnesia file storage. Each (non
%%% ram-copy) table is maintained in a corresponding .DAT file. The
%%% dat file is organized as a segmented linear hashlist. The head of
@@ -179,6 +175,21 @@
%%-define(PROFILE(C), C).
-define(PROFILE(C), void).
+-type access() :: 'read' | 'read_write'.
+-type auto_save() :: 'infinity' | non_neg_integer().
+-opaque bindings_cont() :: #dets_cont{}.
+-opaque cont() :: #dets_cont{}.
+-type keypos() :: pos_integer().
+-type match_spec() :: ets:match_spec().
+-type object() :: tuple().
+-type no_slots() :: non_neg_integer() | 'default'.
+-opaque object_cont() :: #dets_cont{}.
+-type pattern() :: atom() | tuple().
+-opaque select_cont() :: #dets_cont{}.
+-type tab_name() :: term().
+-type type() :: 'bag' | 'duplicate_bag' | 'set'.
+-type version() :: 8 | 9 | 'default'.
+
%%% Some further debug code was added in R12B-1 (stdlib-1.15.1):
%%% - there is a new open_file() option 'debug';
%%% - there is a new OS environment variable 'DETS_DEBUG';
@@ -203,9 +214,13 @@ add_user(Pid, Tab, Args) ->
all() ->
dets_server:all().
--type cont() :: #dets_cont{}.
--spec bchunk(tab_name(), 'start' | cont()) ->
- {cont(), binary() | tuple()} | '$end_of_table' | {'error', term()}.
+-spec bchunk(Name, Continuation) ->
+ {Continuation2, Data} | '$end_of_table' | {'error', Reason} when
+ Name :: tab_name(),
+ Continuation :: 'start' | cont(),
+ Continuation2 :: cont(),
+ Data :: binary() | tuple(),
+ Reason :: term().
bchunk(Tab, start) ->
badarg(treq(Tab, {bchunk_init, Tab}), [Tab, start]);
@@ -214,7 +229,9 @@ bchunk(Tab, #dets_cont{what = bchunk, tab = Tab} = State) ->
bchunk(Tab, Term) ->
erlang:error(badarg, [Tab, Term]).
--spec close(tab_name()) -> 'ok' | {'error', term()}.
+-spec close(Name) -> 'ok' | {'error', Reason} when
+ Name :: tab_name(),
+ Reason :: term().
close(Tab) ->
case dets_server:close(Tab) of
@@ -224,12 +241,17 @@ close(Tab) ->
Reply
end.
--spec delete(tab_name(), term()) -> 'ok' | {'error', term()}.
+-spec delete(Name, Key) -> 'ok' | {'error', Reason} when
+ Name :: tab_name(),
+ Key :: term(),
+ Reason :: term().
delete(Tab, Key) ->
badarg(treq(Tab, {delete_key, [Key]}), [Tab, Key]).
--spec delete_all_objects(tab_name()) -> 'ok' | {'error', term()}.
+-spec delete_all_objects(Name) -> 'ok' | {'error', Reason} when
+ Name :: tab_name(),
+ Reason :: term().
delete_all_objects(Tab) ->
case treq(Tab, delete_all_objects) of
@@ -241,7 +263,10 @@ delete_all_objects(Tab) ->
Reply
end.
--spec delete_object(tab_name(), object()) -> 'ok' | {'error', term()}.
+-spec delete_object(Name, Object) -> 'ok' | {'error', Reason} when
+ Name :: tab_name(),
+ Object :: object(),
+ Reason :: term().
delete_object(Tab, O) ->
badarg(treq(Tab, {delete_object, [O]}), [Tab, O]).
@@ -264,23 +289,42 @@ fsck(Fname, Version) ->
end
end.
--spec first(tab_name()) -> term() | '$end_of_table'.
+-spec first(Name) -> Key | '$end_of_table' when
+ Name :: tab_name(),
+ Key :: term().
first(Tab) ->
badarg_exit(treq(Tab, first), [Tab]).
--spec foldr(fun((object(), Acc) -> Acc), Acc, tab_name()) -> Acc | {'error', term()}.
+-spec foldr(Function, Acc0, Name) -> Acc | {'error', Reason} when
+ Name :: tab_name(),
+ Function :: fun((Object :: object(), AccIn) -> AccOut),
+ Acc0 :: term(),
+ Acc :: term(),
+ AccIn :: term(),
+ AccOut :: term(),
+ Reason :: term().
foldr(Fun, Acc, Tab) ->
foldl(Fun, Acc, Tab).
--spec foldl(fun((object(), Acc) -> Acc), Acc, tab_name()) -> Acc | {'error', term()}.
+-spec foldl(Function, Acc0, Name) -> Acc | {'error', Reason} when
+ Name :: tab_name(),
+ Function :: fun((Object :: object(), AccIn) -> AccOut),
+ Acc0 :: term(),
+ Acc :: term(),
+ AccIn :: term(),
+ AccOut :: term(),
+ Reason :: term().
foldl(Fun, Acc, Tab) ->
Ref = make_ref(),
do_traverse(Fun, Acc, Tab, Ref).
--spec from_ets(tab_name(), ets:tab()) -> 'ok' | {'error', term()}.
+-spec from_ets(Name, EtsTab) -> 'ok' | {'error', Reason} when
+ Name :: tab_name(),
+ EtsTab :: ets:tab(),
+ Reason :: term().
from_ets(DTab, ETab) ->
ets:safe_fixtable(ETab, true),
@@ -304,6 +348,15 @@ from_ets_fun(LC, ETab) ->
{L, from_ets_fun(ets:select(C), ETab)}
end.
+-spec info(Name) -> InfoList | 'undefined' when
+ Name :: tab_name(),
+ InfoList :: [InfoTuple],
+ InfoTuple :: {'file_size', non_neg_integer()}
+ | {'filename', file:name()}
+ | {'keypos', keypos()}
+ | {'size', non_neg_integer()}
+ | {'type', type()}.
+
info(Tab) ->
case catch dets_server:get_pid(Tab) of
{'EXIT', _Reason} ->
@@ -312,6 +365,14 @@ info(Tab) ->
undefined(req(Pid, info))
end.
+-spec info(Name, Item) -> Value | 'undefined' when
+ Name :: tab_name(),
+ Item :: 'access' | 'auto_save' | 'bchunk_format'
+ | 'hash' | 'file_size' | 'filename' | 'keypos' | 'memory'
+ | 'no_keys' | 'no_objects' | 'no_slots' | 'owner' | 'ram_file'
+ | 'safe_fixed' | 'size' | 'type' | 'version',
+ Value :: term().
+
info(Tab, owner) ->
case catch dets_server:get_pid(Tab) of
Pid when is_pid(Pid) ->
@@ -334,9 +395,27 @@ info(Tab, Tag) ->
undefined(req(Pid, {info, Tag}))
end.
+-spec init_table(Name, InitFun) -> ok | {'error', Reason} when
+ Name :: tab_name(),
+ InitFun :: fun((Arg) -> Res),
+ Arg :: read | close,
+ Res :: end_of_input | {[object()], InitFun} | {Data, InitFun} | term(),
+ Reason :: term(),
+ Data :: binary() | tuple().
+
init_table(Tab, InitFun) ->
init_table(Tab, InitFun, []).
+-spec init_table(Name, InitFun, Options) -> ok | {'error', Reason} when
+ Name :: tab_name(),
+ InitFun :: fun((Arg) -> Res),
+ Arg :: read | close,
+ Res :: end_of_input | {[object()], InitFun} | {Data, InitFun} | term(),
+ Options :: Option | [Option],
+ Option :: {min_no_slots,no_slots()} | {format,term | bchunk},
+ Reason :: term(),
+ Data :: binary() | tuple().
+
init_table(Tab, InitFun, Options) when is_function(InitFun) ->
case options(Options, [format, min_no_slots]) of
{badarg,_} ->
@@ -350,11 +429,20 @@ init_table(Tab, InitFun, Options) when is_function(InitFun) ->
init_table(Tab, InitFun, Options) ->
erlang:error(badarg, [Tab, InitFun, Options]).
+-spec insert(Name, Objects) -> 'ok' | {'error', Reason} when
+ Name :: tab_name(),
+ Objects :: object() | [object()],
+ Reason :: term().
+
insert(Tab, Objs) when is_list(Objs) ->
badarg(treq(Tab, {insert, Objs}), [Tab, Objs]);
insert(Tab, Obj) ->
badarg(treq(Tab, {insert, [Obj]}), [Tab, Obj]).
+-spec insert_new(Name, Objects) -> boolean() when
+ Name :: tab_name(),
+ Objects :: object() | [object()].
+
insert_new(Tab, Objs) when is_list(Objs) ->
badarg(treq(Tab, {insert_new, Objs}), [Tab, Objs]);
insert_new(Tab, Obj) ->
@@ -366,9 +454,17 @@ internal_close(Pid) ->
internal_open(Pid, Ref, Args) ->
req(Pid, {internal_open, Ref, Args}).
+-spec is_compatible_bchunk_format(Name, BchunkFormat) -> boolean() when
+ Name :: tab_name(),
+ BchunkFormat :: binary().
+
is_compatible_bchunk_format(Tab, Term) ->
badarg(treq(Tab, {is_compatible_bchunk_format, Term}), [Tab, Term]).
+-spec is_dets_file(Filename) -> boolean() | {'error', Reason} when
+ Filename :: file:name(),
+ Reason :: term().
+
is_dets_file(FileName) ->
case catch read_file_header(FileName, read, false) of
{ok, Fd, FH} ->
@@ -382,6 +478,12 @@ is_dets_file(FileName) ->
Other
end.
+-spec lookup(Name, Key) -> Objects | {'error', Reason} when
+ Name :: tab_name(),
+ Key :: term(),
+ Objects :: [object()],
+ Reason :: term().
+
lookup(Tab, Key) ->
badarg(treq(Tab, {lookup_keys, [Key]}), [Tab, Key]).
@@ -394,19 +496,43 @@ lookup_keys(Tab, Keys) ->
erlang:error(badarg, [Tab, Keys])
end.
+-spec match(Name, Pattern) -> [Match] | {'error', Reason} when
+ Name :: tab_name(),
+ Pattern :: pattern(),
+ Match :: [term()],
+ Reason :: term().
+
match(Tab, Pat) ->
badarg(safe_match(Tab, Pat, bindings), [Tab, Pat]).
+-spec match(Name, Pattern, N) ->
+ {[Match], Continuation} | '$end_of_table' | {'error', Reason} when
+ Name :: tab_name(),
+ Pattern :: pattern(),
+ N :: 'default' | non_neg_integer(),
+ Continuation :: bindings_cont(),
+ Match :: [term()],
+ Reason :: term().
+
match(Tab, Pat, N) ->
badarg(init_chunk_match(Tab, Pat, bindings, N), [Tab, Pat, N]).
+-spec match(Continuation) ->
+ {[Match], Continuation2} | '$end_of_table' | {'error', Reason} when
+ Continuation :: bindings_cont(),
+ Continuation2 :: bindings_cont(),
+ Match :: [term()],
+ Reason :: term().
+
match(State) when State#dets_cont.what =:= bindings ->
badarg(chunk_match(State), [State]);
match(Term) ->
erlang:error(badarg, [Term]).
--spec match_delete(tab_name(), pattern()) ->
- non_neg_integer() | 'ok' | {'error', term()}.
+-spec match_delete(Name, Pattern) -> 'ok' | {'error', Reason} when
+ Name :: tab_name(),
+ Pattern :: pattern(),
+ Reason :: term().
match_delete(Tab, Pat) ->
badarg(match_delete(Tab, Pat, delete), [Tab, Pat]).
@@ -434,23 +560,60 @@ do_match_delete(Tab, _Proc, Error, _What, _N) ->
safe_fixtable(Tab, false),
Error.
+-spec match_object(Name, Pattern) -> Objects | {'error', Reason} when
+ Name :: tab_name(),
+ Pattern :: pattern(),
+ Objects :: [object()],
+ Reason :: term().
+
match_object(Tab, Pat) ->
badarg(safe_match(Tab, Pat, object), [Tab, Pat]).
+-spec match_object(Name, Pattern, N) ->
+ {Objects, Continuation} | '$end_of_table' | {'error', Reason} when
+ Name :: tab_name(),
+ Pattern :: pattern(),
+ N :: 'default' | non_neg_integer(),
+ Continuation :: object_cont(),
+ Objects :: [object()],
+ Reason :: term().
+
match_object(Tab, Pat, N) ->
badarg(init_chunk_match(Tab, Pat, object, N), [Tab, Pat, N]).
+-spec match_object(Continuation) ->
+ {Objects, Continuation2} | '$end_of_table' | {'error', Reason} when
+ Continuation :: object_cont(),
+ Continuation2 :: object_cont(),
+ Objects :: [object()],
+ Reason :: term().
+
match_object(State) when State#dets_cont.what =:= object ->
badarg(chunk_match(State), [State]);
match_object(Term) ->
erlang:error(badarg, [Term]).
+-spec member(Name, Key) -> boolean() | {'error', Reason} when
+ Name :: tab_name(),
+ Key :: term(),
+ Reason :: term().
+
member(Tab, Key) ->
badarg(treq(Tab, {member, Key}), [Tab, Key]).
+-spec next(Name, Key1) -> Key2 | '$end_of_table' when
+ Name :: tab_name(),
+ Key1 :: term(),
+ Key2 :: term().
+
next(Tab, Key) ->
badarg_exit(treq(Tab, {next, Key}), [Tab, Key]).
+-spec open_file(Filename) -> {'ok', Reference} | {'error', Reason} when
+ Filename :: file:name(),
+ Reference :: reference(),
+ Reason :: term().
+
%% Assuming that a file already exists, open it with the
%% parameters as already specified in the file itself.
%% Return a ref leading to the file.
@@ -462,6 +625,22 @@ open_file(File) ->
einval(Reply, [File])
end.
+-spec open_file(Name, Args) -> {'ok', Name} | {'error', Reason} when
+ Name :: tab_name(),
+ Args :: [OpenArg],
+ OpenArg :: {'access', access()}
+ | {'auto_save', auto_save()}
+ | {'estimated_no_objects', non_neg_integer()}
+ | {'file', file:name()}
+ | {'max_no_slots', no_slots()}
+ | {'min_no_slots', no_slots()}
+ | {'keypos', keypos()}
+ | {'ram_file', boolean()}
+ | {'repair', boolean() | 'force'}
+ | {'type', type()}
+ | {'version', version()},
+ Reason :: term().
+
open_file(Tab, Args) when is_list(Args) ->
case catch defaults(Tab, Args) of
OpenArgs when is_record(OpenArgs, open_args) ->
@@ -477,12 +656,21 @@ open_file(Tab, Args) when is_list(Args) ->
open_file(Tab, Arg) ->
open_file(Tab, [Arg]).
+-spec pid2name(Pid) -> {'ok', Name} | 'undefined' when
+ Pid :: pid(),
+ Name :: tab_name().
+
pid2name(Pid) ->
dets_server:pid2name(Pid).
remove_user(Pid, From) ->
req(Pid, {close, From}).
+-spec repair_continuation(Continuation, MatchSpec) -> Continuation2 when
+ Continuation :: select_cont(),
+ Continuation2 :: select_cont(),
+ MatchSpec :: match_spec().
+
repair_continuation(#dets_cont{match_program = B}=Cont, MS)
when is_binary(B) ->
case ets:is_compiled_ms(B) of
@@ -496,25 +684,63 @@ repair_continuation(#dets_cont{}=Cont, _MS) ->
repair_continuation(T, MS) ->
erlang:error(badarg, [T, MS]).
+-spec safe_fixtable(Name, Fix) -> 'ok' when
+ Name :: tab_name(),
+ Fix :: boolean().
+
safe_fixtable(Tab, Bool) when Bool; not Bool ->
badarg(treq(Tab, {safe_fixtable, Bool}), [Tab, Bool]);
safe_fixtable(Tab, Term) ->
erlang:error(badarg, [Tab, Term]).
+-spec select(Name, MatchSpec) -> Selection | {'error', Reason} when
+ Name :: tab_name(),
+ MatchSpec :: match_spec(),
+ Selection :: [term()],
+ Reason :: term().
+
select(Tab, Pat) ->
badarg(safe_match(Tab, Pat, select), [Tab, Pat]).
+-spec select(Name, MatchSpec, N) ->
+ {Selection, Continuation} | '$end_of_table' | {'error', Reason} when
+ Name :: tab_name(),
+ MatchSpec :: match_spec(),
+ N :: 'default' | non_neg_integer(),
+ Continuation :: select_cont(),
+ Selection :: [term()],
+ Reason :: term().
+
select(Tab, Pat, N) ->
badarg(init_chunk_match(Tab, Pat, select, N), [Tab, Pat, N]).
+-spec select(Continuation) ->
+ {Selection, Continuation2} | '$end_of_table' | {'error', Reason} when
+ Continuation :: select_cont(),
+ Continuation2 :: select_cont(),
+ Selection :: [term()],
+ Reason :: term().
+
select(State) when State#dets_cont.what =:= select ->
badarg(chunk_match(State), [State]);
select(Term) ->
erlang:error(badarg, [Term]).
+-spec select_delete(Name, MatchSpec) -> N | {'error', Reason} when
+ Name :: tab_name(),
+ MatchSpec :: match_spec(),
+ N :: non_neg_integer(),
+ Reason :: term().
+
select_delete(Tab, Pat) ->
badarg(match_delete(Tab, Pat, select), [Tab, Pat]).
+-spec slot(Name, I) -> '$end_of_table' | Objects | {'error', Reason} when
+ Name :: tab_name(),
+ I :: non_neg_integer(),
+ Objects :: [object()],
+ Reason :: term().
+
slot(Tab, Slot) when is_integer(Slot), Slot >= 0 ->
badarg(treq(Tab, {slot, Slot}), [Tab, Slot]);
slot(Tab, Term) ->
@@ -529,12 +755,29 @@ stop() ->
istart_link(Server) ->
{ok, proc_lib:spawn_link(dets, init, [self(), Server])}.
+-spec sync(Name) -> 'ok' | {'error', Reason} when
+ Name :: tab_name(),
+ Reason :: term().
+
sync(Tab) ->
badarg(treq(Tab, sync), [Tab]).
+-spec table(Name) -> QueryHandle when
+ Name :: tab_name(),
+ QueryHandle :: qlc:query_handle().
+
table(Tab) ->
table(Tab, []).
+-spec table(Name, Options) -> QueryHandle when
+ Name :: tab_name(),
+ Options :: Option | [Option],
+ Option :: {'n_objects', Limit}
+ | {'traverse', TraverseMethod},
+ Limit :: 'default' | pos_integer(),
+ TraverseMethod :: 'first_next' | 'select' | {'select', match_spec()},
+ QueryHandle :: qlc:query_handle().
+
table(Tab, Opts) ->
case options(Opts, [traverse, n_objects]) of
{badarg,_} ->
@@ -612,6 +855,11 @@ table_info(_Tab, _) ->
%% End of table/2.
+-spec to_ets(Name, EtsTab) -> EtsTab | {'error', Reason} when
+ Name :: tab_name(),
+ EtsTab :: ets:tab(),
+ Reason :: term().
+
to_ets(DTab, ETab) ->
case ets:info(ETab, protection) of
undefined ->
@@ -621,6 +869,20 @@ to_ets(DTab, ETab) ->
foldl(Fun, ETab, DTab)
end.
+-spec traverse(Name, Fun) -> Return | {'error', Reason} when
+ Name :: tab_name(),
+ Fun :: fun((Object) -> FunReturn),
+ Object :: object(),
+ FunReturn :: 'continue'
+ | {'continue', Val}
+ | {'done', Value}
+ | OtherValue,
+ Return :: [term()] | OtherValue,
+ Val :: term(),
+ Value :: term(),
+ OtherValue :: term(),
+ Reason :: term().
+
traverse(Tab, Fun) ->
Ref = make_ref(),
TFun =
@@ -638,6 +900,14 @@ traverse(Tab, Fun) ->
end,
do_traverse(TFun, [], Tab, Ref).
+-spec update_counter(Name, Key, Increment) -> Result when
+ Name :: tab_name(),
+ Key :: term(),
+ Increment :: {Pos, Incr} | Incr,
+ Pos :: integer(),
+ Incr :: integer(),
+ Result :: integer().
+
update_counter(Tab, Key, C) ->
badarg(treq(Tab, {update_counter, Key, C}), [Tab, Key, C]).
@@ -1484,17 +1754,6 @@ system_code_change(State, _Module, _OldVsn, _Extra) ->
%%% Internal functions
%%%----------------------------------------------------------------------
-constants(FH, FileName) ->
- Version = FH#fileheader.version,
- if
- Version =< 8 ->
- dets_v8:constants();
- Version =:= 9 ->
- dets_v9:constants();
- true ->
- throw({error, {not_a_dets_file, FileName}})
- end.
-
%% -> {ok, Fd, fileheader()} | throw(Error)
read_file_header(FileName, Access, RamFile) ->
BF = if
@@ -1572,7 +1831,11 @@ do_bchunk_init(Head, Tab) ->
{H2, {error, old_version}};
Parms ->
L = dets_utils:all_allocated(H2),
- C0 = #dets_cont{no_objs = default, bin = <<>>, alloc = L},
+ Bin = if
+ L =:= <<>> -> eof;
+ true -> <<>>
+ end,
+ C0 = #dets_cont{no_objs = default, bin = Bin, alloc = L},
BinParms = term_to_binary(Parms),
{H2, {C0#dets_cont{tab = Tab, proc = self(),what = bchunk},
[BinParms]}}
@@ -2205,10 +2468,23 @@ fopen2(Fname, Tab) ->
%% Fd is not always closed upon error, but exit is soon called.
{ok, Fd, FH} = read_file_header(Fname, Acc, Ram),
Mod = FH#fileheader.mod,
- case Mod:check_file_header(FH, Fd) of
- {error, not_closed} ->
- io:format(user,"dets: file ~p not properly closed, "
- "repairing ...~n", [Fname]),
+ Do = case Mod:check_file_header(FH, Fd) of
+ {ok, Head1, ExtraInfo} ->
+ Head2 = Head1#head{filename = Fname},
+ try {ok, Mod:init_freelist(Head2, ExtraInfo)}
+ catch
+ throw:_ ->
+ {repair, " has bad free lists, repairing ..."}
+ end;
+ {error, not_closed} ->
+ M = " not properly closed, repairing ...",
+ {repair, M};
+ Else ->
+ Else
+ end,
+ case Do of
+ {repair, Mess} ->
+ io:format(user, "dets: file ~p~s~n", [Fname, Mess]),
Version = default,
case fsck(Fd, Tab, Fname, FH, default, default, Version) of
ok ->
@@ -2216,9 +2492,9 @@ fopen2(Fname, Tab) ->
Error ->
throw(Error)
end;
- {ok, Head, ExtraInfo} ->
+ {ok, Head} ->
open_final(Head, Fname, Acc, Ram, ?DEFAULT_CACHE,
- Tab, ExtraInfo, false);
+ Tab, false);
{error, Reason} ->
throw({error, {Reason, Fname}})
end;
@@ -2250,12 +2526,13 @@ fopen_existing_file(Tab, OpenArgs) ->
V9 = (Version =:= 9) or (Version =:= default),
MinF = (MinSlots =:= default) or (MinSlots =:= FH#fileheader.min_no_slots),
MaxF = (MaxSlots =:= default) or (MaxSlots =:= FH#fileheader.max_no_slots),
- Do = case (FH#fileheader.mod):check_file_header(FH, Fd) of
+ Mod = (FH#fileheader.mod),
+ Wh = case Mod:check_file_header(FH, Fd) of
{ok, Head, true} when Rep =:= force, Acc =:= read_write,
FH#fileheader.version =:= 9,
FH#fileheader.no_colls =/= undefined,
MinF, MaxF, V9 ->
- {compact, Head};
+ {compact, Head, true};
{ok, _Head, _Extra} when Rep =:= force, Acc =:= read ->
throw({error, {access_mode, Fname}});
{ok, Head, need_compacting} when Acc =:= read ->
@@ -2285,6 +2562,17 @@ fopen_existing_file(Tab, OpenArgs) ->
{error, Reason} ->
throw({error, {Reason, Fname}})
end,
+ Do = case Wh of
+ {Tag, Hd, Extra} when Tag =:= final; Tag =:= compact ->
+ Hd1 = Hd#head{filename = Fname},
+ try {Tag, Mod:init_freelist(Hd1, Extra)}
+ catch
+ throw:_ ->
+ {repair, " has bad free lists, repairing ..."}
+ end;
+ Else ->
+ Else
+ end,
case Do of
_ when FH#fileheader.type =/= Type ->
throw({error, {type_mismatch, Fname}});
@@ -2293,8 +2581,7 @@ fopen_existing_file(Tab, OpenArgs) ->
{compact, SourceHead} ->
io:format(user, "dets: file ~p is now compacted ...~n", [Fname]),
{ok, NewSourceHead} = open_final(SourceHead, Fname, read, false,
- ?DEFAULT_CACHE, Tab, true,
- Debug),
+ ?DEFAULT_CACHE, Tab, Debug),
case catch compact(NewSourceHead) of
ok ->
erlang:garbage_collect(),
@@ -2314,9 +2601,9 @@ fopen_existing_file(Tab, OpenArgs) ->
Version, OpenArgs);
_ when FH#fileheader.version =/= Version, Version =/= default ->
throw({error, {version_mismatch, Fname}});
- {final, H, EI} ->
+ {final, H} ->
H1 = H#head{auto_save = Auto},
- open_final(H1, Fname, Acc, Ram, CacheSz, Tab, EI, Debug)
+ open_final(H1, Fname, Acc, Ram, CacheSz, Tab, Debug)
end.
do_repair(Fd, Tab, Fname, FH, MinSlots, MaxSlots, Version, OpenArgs) ->
@@ -2330,19 +2617,16 @@ do_repair(Fd, Tab, Fname, FH, MinSlots, MaxSlots, Version, OpenArgs) ->
end.
%% -> {ok, head()} | throw(Error)
-open_final(Head, Fname, Acc, Ram, CacheSz, Tab, ExtraInfo, Debug) ->
+open_final(Head, Fname, Acc, Ram, CacheSz, Tab, Debug) ->
Head1 = Head#head{access = Acc,
ram_file = Ram,
filename = Fname,
name = Tab,
cache = dets_utils:new_cache(CacheSz)},
init_disk_map(Head1#head.version, Tab, Debug),
- Mod = Head#head.mod,
- Mod:cache_segps(Head1#head.fptr, Fname, Head1#head.next),
- Ftab = Mod:init_freelist(Head1, ExtraInfo),
+ (Head1#head.mod):cache_segps(Head1#head.fptr, Fname, Head1#head.next),
check_growth(Head1),
- NewHead = Head1#head{freelists = Ftab},
- {ok, NewHead}.
+ {ok, Head1}.
%% -> {ok, head()} | throw(Error)
fopen_init_file(Tab, OpenArgs) ->
@@ -2869,8 +3153,12 @@ init_scan(Head, NoObjs) ->
check_safe_fixtable(Head),
FreeLists = dets_utils:get_freelists(Head),
Base = Head#head.base,
- {From, To} = dets_utils:find_next_allocated(FreeLists, Base, Base),
- #dets_cont{no_objs = NoObjs, bin = <<>>, alloc = {From, To, <<>>}}.
+ case dets_utils:find_next_allocated(FreeLists, Base, Base) of
+ {From, To} ->
+ #dets_cont{no_objs = NoObjs, bin = <<>>, alloc = {From,To,<<>>}};
+ none ->
+ #dets_cont{no_objs = NoObjs, bin = eof, alloc = <<>>}
+ end.
check_safe_fixtable(Head) ->
case (Head#head.fixed =:= false) andalso
@@ -2971,18 +3259,20 @@ view(FileName) ->
case catch read_file_header(FileName, read, false) of
{ok, Fd, FH} ->
Mod = FH#fileheader.mod,
- case Mod:check_file_header(FH, Fd) of
- {ok, H0, ExtraInfo} ->
- Ftab = Mod:init_freelist(H0, ExtraInfo),
- {_Bump, Base} = constants(FH, FileName),
- H = H0#head{freelists=Ftab, base = Base},
- v_free_list(H),
- Mod:v_segments(H),
- file:close(Fd);
- X ->
- file:close(Fd),
- X
- end;
+ try Mod:check_file_header(FH, Fd) of
+ {ok, H0, ExtraInfo} ->
+ Mod = FH#fileheader.mod,
+ case Mod:check_file_header(FH, Fd) of
+ {ok, H0, ExtraInfo} ->
+ H = Mod:init_freelist(H0, ExtraInfo),
+ v_free_list(H),
+ Mod:v_segments(H),
+ ok;
+ X ->
+ X
+ end
+ after file:close(Fd)
+ end;
X ->
X
end.
diff --git a/lib/stdlib/src/dets.hrl b/lib/stdlib/src/dets.hrl
index fbffc9d008..a3f99357a2 100644
--- a/lib/stdlib/src/dets.hrl
+++ b/lib/stdlib/src/dets.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The 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,6 +92,7 @@
%% Info extracted from the file header.
-record(fileheader, {
freelist,
+ fl_base,
cookie,
closed_properly,
type,
diff --git a/lib/stdlib/src/dets_v8.erl b/lib/stdlib/src/dets_v8.erl
index af36958c1c..3e962a1c8b 100644
--- a/lib/stdlib/src/dets_v8.erl
+++ b/lib/stdlib/src/dets_v8.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The 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,7 +21,7 @@
%% Dets files, implementation part. This module handles versions up to
%% and including 8(c). To be called from dets.erl only.
--export([constants/0, mark_dirty/1, read_file_header/2,
+-export([mark_dirty/1, read_file_header/2,
check_file_header/2, do_perform_save/1, initiate_file/11,
init_freelist/2, fsck_input/4,
bulk_input/3, output_objs/4, write_cache/1, may_grow/3,
@@ -163,7 +163,7 @@
%% The 8(c) version uses a different hashing algorithm, erlang:phash
%% (former versions use erlang:hash).
%% Version 8(b) files are only converted to version 8(c) if repair is
-%% done, so we need compatability with 8(b) for a _long_ time.
+%% done, so we need compatibility with 8(b) for a _long_ time.
%%
%% There are known bugs due to the fact that keys and objects are
%% sometimes compared (==) and sometimes matched (=:=). The version
@@ -196,10 +196,6 @@
%%-define(DEBUGF(X,Y), io:format(X, Y)).
-define(DEBUGF(X,Y), void).
-%% {Bump}
-constants() ->
- {?BUMP, ?BASE}.
-
%% -> ok | throw({NewHead,Error})
mark_dirty(Head) ->
Dirty = [{?CLOSED_PROPERLY_POS, <<?NOT_PROPERLY_CLOSED:32>>}],
@@ -308,8 +304,9 @@ init_freelist(Head, {convert_freelist,_Version}) ->
Pos = Head#head.freelists_p,
case catch prterm(Head, Pos, ?OHDSZ) of
{0, _Sz, Term} ->
- FreeList = lists:reverse(Term),
- dets_utils:init_slots_from_old_file(FreeList, Ftab);
+ FreeList1 = lists:reverse(Term),
+ FreeList = dets_utils:init_slots_from_old_file(FreeList1, Ftab),
+ Head#head{freelists = FreeList, base = ?BASE};
_ ->
throw({error, {bad_freelists, Head#head.filename}})
end;
@@ -318,7 +315,7 @@ init_freelist(Head, _) ->
Pos = Head#head.freelists_p,
case catch prterm(Head, Pos, ?OHDSZ) of
{0, _Sz, Term} ->
- Term;
+ Head#head{freelists = Term, base = ?BASE};
_ ->
throw({error, {bad_freelists, Head#head.filename}})
end.
@@ -331,6 +328,7 @@ read_file_header(Fd, FileName) ->
{ok, EOF} = dets_utils:position_close(Fd, FileName, eof),
{ok, <<FileSize:32>>} = dets_utils:pread_close(Fd, FileName, EOF-4, 4),
FH = #fileheader{freelist = Freelist,
+ fl_base = ?BASE,
cookie = Cookie,
closed_properly = CP,
type = dets_utils:code_to_type(Type2),
@@ -413,7 +411,7 @@ check_file_header(FH, Fd) ->
version = ?FILE_FORMAT_VERSION,
mod = ?MODULE,
bump = ?BUMP,
- base = ?BASE},
+ base = FH#fileheader.fl_base},
{ok, H, ExtraInfo};
Error ->
Error
diff --git a/lib/stdlib/src/dets_v9.erl b/lib/stdlib/src/dets_v9.erl
index 132af01f79..f577b4410f 100644
--- a/lib/stdlib/src/dets_v9.erl
+++ b/lib/stdlib/src/dets_v9.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The 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,7 +21,7 @@
%% Dets files, implementation part. This module handles version 9.
%% To be called from dets.erl only.
--export([constants/0, mark_dirty/1, read_file_header/2,
+-export([mark_dirty/1, read_file_header/2,
check_file_header/2, do_perform_save/1, initiate_file/11,
prep_table_copy/9, init_freelist/2, fsck_input/4,
bulk_input/3, output_objs/4, bchunk_init/2,
@@ -70,6 +70,17 @@
%% 16 MD5-sum for the 44 plus 112 bytes before the MD5-sum.
%% (FreelistsPointer, Cookie and ClosedProperly are not digested.)
%% 128 Reserved for future versions. Initially zeros.
+%% Version 9(d), introduced in R15A, has instead:
+%% 112 28 counters for the buddy system sizes (as for 9(b)).
+%% 16 MD5-sum for the 44 plus 112 bytes before the MD5-sum.
+%% (FreelistsPointer, Cookie and ClosedProperly are not digested.)
+%% 4 Base of the buddy system.
+%% 0 (zero) if the base is equal to ?BASE. Compatible with R14B.
+%% File size at the end of the file is RealFileSize - Base.
+%% The reason for modifying file size is that when a file created
+%% by R15 is read by R14 a repair takes place immediately, which
+%% is acceptable when downgrading.
+%% 124 Reserved for future versions. Initially zeros.
%% ---
%% ------------------ end of file header
%% 4*256 SegmentArray Pointers.
@@ -86,7 +97,7 @@
%% -----------------------------
%% ??? Free lists
%% -----------------------------
-%% 4 File size, in bytes.
+%% 4 File size, in bytes. See 9(d) obove.
%% Before we can find an object we must find the slot where the
%% object resides. Each slot is a (possibly empty) list (or chain) of
@@ -177,14 +188,14 @@
%%% File header
%%%
--define(RESERVED, 128). % Reserved for future use.
+-define(RESERVED, 124). % Reserved for future use.
-define(COLL_CNTRS, (28*4)). % Counters for the buddy system.
-define(MD5SZ, 16).
+-define(FL_BASE, 4).
--define(HEADSZ,
- 56+?COLL_CNTRS+?MD5SZ). % The size of the file header, in bytes,
- % not including the reserved part.
+-define(HEADSZ, 56+?COLL_CNTRS % The size of the file header, in bytes,
+ +?MD5SZ+?FL_BASE). % not including the reserved part.
-define(HEADEND, (?HEADSZ+?RESERVED)).
% End of header and reserved area.
-define(SEGSZ, 512). % Size of a segment, in words. SZOBJP*SEGSZP.
@@ -270,10 +281,6 @@
%%-define(DEBUGF(X,Y), io:format(X, Y)).
-define(DEBUGF(X,Y), void).
-%% {Bump}
-constants() ->
- {?BUMP, ?BASE}.
-
%% -> ok | throw({NewHead,Error})
mark_dirty(Head) ->
Dirty = [{?CLOSED_PROPERLY_POS, <<?NOT_PROPERLY_CLOSED:32>>}],
@@ -356,7 +363,7 @@ init_file(Fd, Tab, Fname, Type, Kp, MinSlots, MaxSlots, Ram, CacheSz,
cache = dets_utils:new_cache(CacheSz),
version = ?FILE_FORMAT_VERSION,
bump = ?BUMP,
- base = ?BASE,
+ base = ?BASE, % to be overwritten
mod = ?MODULE
},
@@ -378,13 +385,20 @@ init_file(Fd, Tab, Fname, Type, Kp, MinSlots, MaxSlots, Ram, CacheSz,
{Head1, Ws1} = init_parts(Head0, 0, no_parts(Next), Zero, []),
NoSegs = no_segs(Next),
- {Head, WsI, WsP} = init_segments(Head1, 0, NoSegs, Zero, [], []),
+ {Head2, WsI, WsP} = init_segments(Head1, 0, NoSegs, Zero, [], []),
Ws2 = if
DoInitSegments -> WsP ++ WsI;
true -> WsP
end,
dets_utils:pwrite(Fd, Fname, [W0 | lists:append(Ws1) ++ Ws2]),
- true = hash_invars(Head),
+ true = hash_invars(Head2),
+ %% The allocations that have been made so far (parts, segments)
+ %% are permanent; the table will never shrink. Therefore the base
+ %% of the Buddy system can be set to the first free object.
+ %% This is used in allocate_all(), see below.
+ {_, Where, _} = dets_utils:alloc(Head2, ?BUMP),
+ NewFtab = dets_utils:init_alloc(Where),
+ Head = Head2#head{freelists = NewFtab, base = Where},
{ok, Head}.
%% Returns a power of two not less than 256.
@@ -451,8 +465,9 @@ read_file_header(Fd, FileName) ->
Version:32, M:32, Next:32, Kp:32,
NoObjects:32, NoKeys:32, MinNoSlots:32, MaxNoSlots:32,
HashMethod:32, N:32, NoCollsB:?COLL_CNTRS/binary,
- MD5:?MD5SZ/binary>> = Bin,
- <<_:12/binary,MD5DigestedPart:(?HEADSZ-?MD5SZ-12)/binary,_/binary>> = Bin,
+ MD5:?MD5SZ/binary, FlBase:32>> = Bin,
+ <<_:12/binary,MD5DigestedPart:(?HEADSZ-?MD5SZ-?FL_BASE-12)/binary,
+ _/binary>> = Bin,
{ok, EOF} = dets_utils:position_close(Fd, FileName, eof),
{ok, <<FileSize:32>>} = dets_utils:pread_close(Fd, FileName, EOF-4, 4),
{CL, <<>>} = lists:foldl(fun(LSz, {Acc,<<NN:32,R/binary>>}) ->
@@ -468,8 +483,12 @@ read_file_header(Fd, FileName) ->
true ->
lists:reverse(CL)
end,
-
+ Base = case FlBase of
+ 0 -> ?BASE;
+ _ -> FlBase
+ end,
FH = #fileheader{freelist = FreeList,
+ fl_base = Base,
cookie = Cookie,
closed_properly = CP,
type = dets_utils:code_to_type(Type2),
@@ -486,7 +505,7 @@ read_file_header(Fd, FileName) ->
read_md5 = MD5,
has_md5 = <<0:?MD5SZ/unit:8>> =/= MD5,
md5 = erlang:md5(MD5DigestedPart),
- trailer = FileSize,
+ trailer = FileSize + FlBase,
eof = EOF,
n = N,
mod = ?MODULE},
@@ -544,7 +563,7 @@ check_file_header(FH, Fd) ->
version = ?FILE_FORMAT_VERSION,
mod = ?MODULE,
bump = ?BUMP,
- base = ?BASE},
+ base = FH#fileheader.fl_base},
{ok, H, ExtraInfo};
Error ->
Error
@@ -1185,41 +1204,25 @@ write_loop(Head, BytesToWrite, Bin) ->
write_loop(Head, BytesToWrite, SmallBin).
%% By allocating bigger objects before smaller ones, holes in the
-%% buddy system memory map are avoided. Unfortunately, the segments
-%% are always allocated first, so if there are objects bigger than a
-%% segment, there is a hole to handle. (Haven't considered placing the
-%% segments among other objects of the same size.)
+%% buddy system memory map are avoided.
allocate_all_objects(Head, SizeT) ->
DTL = lists:reverse(lists:keysort(1, ets:tab2list(SizeT))),
MaxSz = element(1, hd(DTL)),
- SegSize = ?ACTUAL_SEG_SIZE,
- {Head1, HSz, HN, HA} = alloc_hole(MaxSz, Head, SegSize),
- {Head2, NL} = allocate_all(Head1, DTL, []),
+ {Head1, NL} = allocate_all(Head, DTL, []),
%% Find the position that will be the end of the file by allocating
%% a minimal object.
- {_Head, EndOfFile, _} = dets_utils:alloc(Head2, ?BUMP),
- Head3 = free_hole(Head2, HSz, HN, HA),
- NewHead = Head3#head{maxobjsize = max_objsize(Head3#head.no_collections)},
+ {_Head, EndOfFile, _} = dets_utils:alloc(Head1, ?BUMP),
+ NewHead = Head1#head{maxobjsize = max_objsize(Head1#head.no_collections)},
{NewHead, NL, MaxSz, EndOfFile}.
-alloc_hole(LSize, Head, SegSz) when ?POW(LSize-1) > SegSz ->
- Size = ?POW(LSize-1),
- {_, SegAddr, _} = dets_utils:alloc(Head, adjsz(SegSz)),
- {_, Addr, _} = dets_utils:alloc(Head, adjsz(Size)),
- N = (Addr - SegAddr) div SegSz,
- Head1 = dets_utils:alloc_many(Head, SegSz, N, SegAddr),
- {Head1, SegSz, N, SegAddr};
-alloc_hole(_MaxSz, Head, _SegSz) ->
- {Head, 0, 0, 0}.
-
-free_hole(Head, _Size, 0, _Addr) ->
- Head;
-free_hole(Head, Size, N, Addr) ->
- {Head1, _} = dets_utils:free(Head, Addr, adjsz(Size)),
- free_hole(Head1, Size, N-1, Addr+Size).
-
%% One (temporary) file for each buddy size, write all objects of that
%% size to the file.
+%%
+%% Before R15 a "hole" was needed before the first bucket if the size
+%% of the biggest bucket was greater than the size of a segment. The
+%% hole proved to be a problem with almost full tables with huge
+%% buckets. Since R15 the hole is no longer needed due to the fact
+%% that the base of the Buddy system is flexible.
allocate_all(Head, [{?FSCK_SEGMENT,_,Data,_}], L) ->
%% And one file for the segments...
%% Note that space for the array parts and the segments has
@@ -1593,23 +1596,28 @@ do_perform_save(H) ->
H1 = H#head{freelists_p = FreeListsPointer},
{FLW, FLSize} = free_lists_to_file(H1),
FileSize = FreeListsPointer + FLSize + 4,
- ok = dets_utils:write(H1, [FLW | <<FileSize:32>>]),
+ AdjustedFileSize = case H#head.base of
+ ?BASE -> FileSize;
+ Base -> FileSize - Base
+ end,
+ ok = dets_utils:write(H1, [FLW | <<AdjustedFileSize:32>>]),
FileHeader = file_header(H1, FreeListsPointer, ?CLOSED_PROPERLY),
case dets_utils:debug_mode() of
true ->
- TmpHead = H1#head{freelists = init_freelist(H1, true),
- fixed = false},
+ TmpHead0 = init_freelist(H1#head{fixed = false}, true),
+ TmpHead = TmpHead0#head{base = H1#head.base},
case
catch dets_utils:all_allocated_as_list(TmpHead)
=:= dets_utils:all_allocated_as_list(H1)
- of
+ of
true ->
dets_utils:pwrite(H1, [{0, FileHeader}]);
_ ->
+ throw(
dets_utils:corrupt_reason(H1, {failed_to_save_free_lists,
FreeListsPointer,
TmpHead#head.freelists,
- H1#head.freelists})
+ H1#head.freelists}))
end;
false ->
dets_utils:pwrite(H1, [{0, FileHeader}])
@@ -1648,7 +1656,11 @@ file_header(Head, FreeListsPointer, ClosedProperly, NoColls) ->
true -> erlang:md5(DigH);
false -> <<0:?MD5SZ/unit:8>>
end,
- [H1, DigH, MD5 | <<0:?RESERVED/unit:8>>].
+ Base = case Head#head.base of
+ ?BASE -> <<0:32>>;
+ FlBase -> <<FlBase:32>>
+ end,
+ [H1, DigH, MD5, Base | <<0:?RESERVED/unit:8>>].
%% Going through some trouble to avoid creating one single binary for
%% the free lists. If the free lists are huge, binary_to_term and
@@ -1695,8 +1707,8 @@ free_lists_from_file(H, Pos) ->
case catch bin_to_tree([], H, start, FL, -1, []) of
{'EXIT', _} ->
throw({error, {bad_freelists, H#head.filename}});
- Reply ->
- Reply
+ Ftab ->
+ H#head{freelists = Ftab, base = ?BASE}
end.
bin_to_tree(Bin, H, LastPos, Ftab, A0, L) ->
diff --git a/lib/stdlib/src/dict.erl b/lib/stdlib/src/dict.erl
index 7e51141098..2e9eba4bfa 100644
--- a/lib/stdlib/src/dict.erl
+++ b/lib/stdlib/src/dict.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -80,7 +80,9 @@ new() ->
Empty = mk_seg(?seg_size),
#dict{empty=Empty,segs={Empty}}.
--spec is_key(term(), dict()) -> boolean().
+-spec is_key(Key, Dict) -> boolean() when
+ Key :: term(),
+ Dict :: dict().
is_key(Key, D) ->
Slot = get_slot(D, Key),
@@ -91,21 +93,29 @@ find_key(K, [?kv(K,_Val)|_]) -> true;
find_key(K, [_|Bkt]) -> find_key(K, Bkt);
find_key(_, []) -> false.
--spec to_list(dict()) -> [{term(), term()}].
+-spec to_list(Dict) -> List when
+ Dict :: dict(),
+ List :: [{Key :: term(), Value :: term()}].
to_list(D) ->
fold(fun (Key, Val, List) -> [{Key,Val}|List] end, [], D).
--spec from_list([{term(), term()}]) -> dict().
+-spec from_list(List) -> Dict when
+ List :: [{Key :: term(), Value :: term()}],
+ Dict :: dict().
from_list(L) ->
lists:foldl(fun ({K,V}, D) -> store(K, V, D) end, new(), L).
--spec size(dict()) -> non_neg_integer().
+-spec size(Dict) -> non_neg_integer() when
+ Dict :: dict().
size(#dict{size=N}) when is_integer(N), N >= 0 -> N.
--spec fetch(term(), dict()) -> term().
+-spec fetch(Key, Dict) -> Value when
+ Key :: term(),
+ Dict :: dict(),
+ Value :: term().
fetch(Key, D) ->
Slot = get_slot(D, Key),
@@ -119,7 +129,10 @@ fetch_val(K, [?kv(K,Val)|_]) -> Val;
fetch_val(K, [_|Bkt]) -> fetch_val(K, Bkt);
fetch_val(_, []) -> throw(badarg).
--spec find(term(), dict()) -> {'ok', term()} | 'error'.
+-spec find(Key, Dict) -> {'ok', Value} | 'error' when
+ Key :: term(),
+ Dict :: dict(),
+ Value :: term().
find(Key, D) ->
Slot = get_slot(D, Key),
@@ -130,12 +143,17 @@ find_val(K, [?kv(K,Val)|_]) -> {ok,Val};
find_val(K, [_|Bkt]) -> find_val(K, Bkt);
find_val(_, []) -> error.
--spec fetch_keys(dict()) -> [term()].
+-spec fetch_keys(Dict) -> Keys when
+ Dict :: dict(),
+ Keys :: [term()].
fetch_keys(D) ->
fold(fun (Key, _Val, Keys) -> [Key|Keys] end, [], D).
--spec erase(term(), dict()) -> dict().
+-spec erase(Key, Dict1) -> Dict2 when
+ Key :: term(),
+ Dict1 :: dict(),
+ Dict2 :: dict().
%% Erase all elements with key Key.
erase(Key, D0) ->
@@ -150,7 +168,11 @@ erase_key(Key, [E|Bkt0]) ->
{[E|Bkt1],Dc};
erase_key(_, []) -> {[],0}.
--spec store(term(), term(), dict()) -> dict().
+-spec store(Key, Value, Dict1) -> Dict2 when
+ Key :: term(),
+ Value :: term(),
+ Dict1 :: dict(),
+ Dict2 :: dict().
store(Key, Val, D0) ->
Slot = get_slot(D0, Key),
@@ -166,7 +188,11 @@ store_bkt_val(Key, New, [Other|Bkt0]) ->
{[Other|Bkt1],Ic};
store_bkt_val(Key, New, []) -> {[?kv(Key,New)],1}.
--spec append(term(), term(), dict()) -> dict().
+-spec append(Key, Value, Dict1) -> Dict2 when
+ Key :: term(),
+ Value :: term(),
+ Dict1 :: dict(),
+ Dict2 :: dict().
append(Key, Val, D0) ->
Slot = get_slot(D0, Key),
@@ -182,7 +208,11 @@ append_bkt(Key, Val, [Other|Bkt0]) ->
{[Other|Bkt1],Ic};
append_bkt(Key, Val, []) -> {[?kv(Key,[Val])],1}.
--spec append_list(term(), [term()], dict()) -> dict().
+-spec append_list(Key, ValList, Dict1) -> Dict2 when
+ Key :: term(),
+ ValList :: [Value :: term()],
+ Dict1 :: dict(),
+ Dict2 :: dict().
append_list(Key, L, D0) ->
Slot = get_slot(D0, Key),
@@ -252,7 +282,11 @@ app_list_bkt(Key, L, []) -> {[?kv(Key,L)],1}.
%% {Bkt1,Dc} = on_key_bkt(Key, F, Bkt0),
%% {[Other|Bkt1],Dc}.
--spec update(term(), fun((term()) -> term()), dict()) -> dict().
+-spec update(Key, Fun, Dict1) -> Dict2 when
+ Key :: term(),
+ Fun :: fun((Value1 :: term()) -> Value2 :: term()),
+ Dict1 :: dict(),
+ Dict2 :: dict().
update(Key, F, D0) ->
Slot = get_slot(D0, Key),
@@ -271,7 +305,12 @@ update_bkt(Key, F, [Other|Bkt0]) ->
update_bkt(_Key, _F, []) ->
throw(badarg).
--spec update(term(), fun((term()) -> term()), term(), dict()) -> dict().
+-spec update(Key, Fun, Initial, Dict1) -> Dict2 when
+ Key :: term(),
+ Initial :: term(),
+ Fun :: fun((Value1 :: term()) -> Value2 :: term()),
+ Dict1 :: dict(),
+ Dict2 :: dict().
update(Key, F, Init, D0) ->
Slot = get_slot(D0, Key),
@@ -286,7 +325,11 @@ update_bkt(Key, F, I, [Other|Bkt0]) ->
{[Other|Bkt1],Ic};
update_bkt(Key, F, I, []) when is_function(F, 1) -> {[?kv(Key,I)],1}.
--spec update_counter(term(), number(), dict()) -> dict().
+-spec update_counter(Key, Increment, Dict1) -> Dict2 when
+ Key :: term(),
+ Increment :: number(),
+ Dict1 :: dict(),
+ Dict2 :: dict().
update_counter(Key, Incr, D0) when is_number(Incr) ->
Slot = get_slot(D0, Key),
@@ -301,20 +344,38 @@ counter_bkt(Key, I, [Other|Bkt0]) ->
{[Other|Bkt1],Ic};
counter_bkt(Key, I, []) -> {[?kv(Key,I)],1}.
--spec fold(fun((term(), term(), term()) -> term()), term(), dict()) -> term().
+-spec fold(Fun, Acc0, Dict) -> Acc1 when
+ Fun :: fun((Key, Value, AccIn) -> AccOut),
+ Key :: term(),
+ Value :: term(),
+ Acc0 :: term(),
+ Acc1 :: term(),
+ AccIn :: term(),
+ AccOut :: term(),
+ Dict :: dict().
%% Fold function Fun over all "bags" in Table and return Accumulator.
fold(F, Acc, D) -> fold_dict(F, Acc, D).
--spec map(fun((term(), term()) -> term()), dict()) -> dict().
+-spec map(Fun, Dict1) -> Dict2 when
+ Fun :: fun((Key :: term(), Value1 :: term()) -> Value2 :: term()),
+ Dict1 :: dict(),
+ Dict2 :: dict().
map(F, D) -> map_dict(F, D).
--spec filter(fun((term(), term()) -> boolean()), dict()) -> dict().
+-spec filter(Pred, Dict1) -> Dict2 when
+ Pred :: fun((Key :: term(), Value :: term()) -> boolean()),
+ Dict1 :: dict(),
+ Dict2 :: dict().
filter(F, D) -> filter_dict(F, D).
--spec merge(fun((term(), term(), term()) -> term()), dict(), dict()) -> dict().
+-spec merge(Fun, Dict1, Dict2) -> Dict3 when
+ Fun :: fun((Key :: term(), Value1 :: term(), Value2 :: term()) -> Value :: term()),
+ Dict1 :: dict(),
+ Dict2 :: dict(),
+ Dict3 :: dict().
merge(F, D1, D2) when D1#dict.size < D2#dict.size ->
fold_dict(fun (K, V1, D) ->
diff --git a/lib/stdlib/src/digraph.erl b/lib/stdlib/src/digraph.erl
index 5edc868a94..e3f87d2c57 100644
--- a/lib/stdlib/src/digraph.erl
+++ b/lib/stdlib/src/digraph.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,8 @@
-type label() :: term().
-type vertex() :: term().
--type add_edge_err_rsn() :: {'bad_edge', [vertex()]} | {'bad_vertex', vertex()}.
+-type add_edge_err_rsn() :: {'bad_edge', Path :: [vertex()]}
+ | {'bad_vertex', V :: vertex()}.
%%
%% Type is a list of
@@ -70,7 +71,8 @@
new() -> new([]).
--spec new([d_type()]) -> digraph().
+-spec new(Type) -> digraph() when
+ Type :: [d_type()].
new(Type) ->
case check_type(Type, protected, []) of
@@ -113,16 +115,20 @@ set_type([], G) -> G.
%% Data access functions
--spec delete(digraph()) -> 'true'.
+-spec delete(G) -> 'true' when
+ G :: digraph().
delete(G) ->
ets:delete(G#digraph.vtab),
ets:delete(G#digraph.etab),
ets:delete(G#digraph.ntab).
--spec info(digraph()) -> [{'cyclicity', d_cyclicity()} |
- {'memory', non_neg_integer()} |
- {'protection', d_protection()}].
+-spec info(G) -> InfoList when
+ G :: digraph(),
+ InfoList :: [{'cyclicity', Cyclicity :: d_cyclicity()} |
+ {'memory', NoWords :: non_neg_integer()} |
+ {'protection', Protection :: d_protection()}].
+
info(G) ->
VT = G#digraph.vtab,
ET = G#digraph.etab,
@@ -135,32 +141,45 @@ info(G) ->
Memory = ets:info(VT, memory) + ets:info(ET, memory) + ets:info(NT, memory),
[{cyclicity, Cyclicity}, {memory, Memory}, {protection, Protection}].
--spec add_vertex(digraph()) -> vertex().
+-spec add_vertex(G) -> vertex() when
+ G :: digraph().
add_vertex(G) ->
do_add_vertex({new_vertex_id(G), []}, G).
--spec add_vertex(digraph(), vertex()) -> vertex().
+-spec add_vertex(G, V) -> vertex() when
+ G :: digraph(),
+ V :: vertex().
add_vertex(G, V) ->
do_add_vertex({V, []}, G).
--spec add_vertex(digraph(), vertex(), label()) -> vertex().
+-spec add_vertex(G, V, Label) -> vertex() when
+ G :: digraph(),
+ V :: vertex(),
+ Label :: label().
add_vertex(G, V, D) ->
do_add_vertex({V, D}, G).
--spec del_vertex(digraph(), vertex()) -> 'true'.
+-spec del_vertex(G, V) -> 'true' when
+ G :: digraph(),
+ V :: vertex().
del_vertex(G, V) ->
do_del_vertex(V, G).
--spec del_vertices(digraph(), [vertex()]) -> 'true'.
+-spec del_vertices(G, Vertices) -> 'true' when
+ G :: digraph(),
+ Vertices :: [vertex()].
del_vertices(G, Vs) ->
do_del_vertices(Vs, G).
--spec vertex(digraph(), vertex()) -> {vertex(), label()} | 'false'.
+-spec vertex(G, V) -> {V, Label} | 'false' when
+ G :: digraph(),
+ V :: vertex(),
+ Label :: label().
vertex(G, V) ->
case ets:lookup(G#digraph.vtab, V) of
@@ -168,12 +187,15 @@ vertex(G, V) ->
[Vertex] -> Vertex
end.
--spec no_vertices(digraph()) -> non_neg_integer().
+-spec no_vertices(G) -> non_neg_integer() when
+ G :: digraph().
no_vertices(G) ->
ets:info(G#digraph.vtab, size).
--spec vertices(digraph()) -> [vertex()].
+-spec vertices(G) -> Vertices when
+ G :: digraph(),
+ Vertices :: [vertex()].
vertices(G) ->
ets:select(G#digraph.vtab, [{{'$1', '_'}, [], ['$1']}]).
@@ -188,85 +210,125 @@ source_vertices(G) ->
sink_vertices(G) ->
collect_vertices(G, out).
--spec in_degree(digraph(), vertex()) -> non_neg_integer().
+-spec in_degree(G, V) -> non_neg_integer() when
+ G :: digraph(),
+ V :: vertex().
in_degree(G, V) ->
length(ets:lookup(G#digraph.ntab, {in, V})).
--spec in_neighbours(digraph(), vertex()) -> [vertex()].
+-spec in_neighbours(G, V) -> Vertex when
+ G :: digraph(),
+ V :: vertex(),
+ Vertex :: [vertex()].
in_neighbours(G, V) ->
ET = G#digraph.etab,
NT = G#digraph.ntab,
collect_elems(ets:lookup(NT, {in, V}), ET, 2).
--spec in_edges(digraph(), vertex()) -> [edge()].
+-spec in_edges(G, V) -> Edges when
+ G :: digraph(),
+ V :: vertex(),
+ Edges :: [edge()].
in_edges(G, V) ->
ets:select(G#digraph.ntab, [{{{in, V}, '$1'}, [], ['$1']}]).
--spec out_degree(digraph(), vertex()) -> non_neg_integer().
+-spec out_degree(G, V) -> non_neg_integer() when
+ G :: digraph(),
+ V :: vertex().
out_degree(G, V) ->
length(ets:lookup(G#digraph.ntab, {out, V})).
--spec out_neighbours(digraph(), vertex()) -> [vertex()].
+-spec out_neighbours(G, V) -> Vertices when
+ G :: digraph(),
+ V :: vertex(),
+ Vertices :: [vertex()].
out_neighbours(G, V) ->
ET = G#digraph.etab,
NT = G#digraph.ntab,
collect_elems(ets:lookup(NT, {out, V}), ET, 3).
--spec out_edges(digraph(), vertex()) -> [edge()].
+-spec out_edges(G, V) -> Edges when
+ G :: digraph(),
+ V :: vertex(),
+ Edges :: [edge()].
out_edges(G, V) ->
ets:select(G#digraph.ntab, [{{{out, V}, '$1'}, [], ['$1']}]).
--spec add_edge(digraph(), vertex(), vertex()) ->
- edge() | {'error', add_edge_err_rsn()}.
+-spec add_edge(G, V1, V2) -> edge() | {'error', add_edge_err_rsn()} when
+ G :: digraph(),
+ V1 :: vertex(),
+ V2 :: vertex().
add_edge(G, V1, V2) ->
do_add_edge({new_edge_id(G), V1, V2, []}, G).
--spec add_edge(digraph(), vertex(), vertex(), label()) ->
- edge() | {'error', add_edge_err_rsn()}.
+-spec add_edge(G, V1, V2, Label) -> edge() | {'error', add_edge_err_rsn()} when
+ G :: digraph(),
+ V1 :: vertex(),
+ V2 :: vertex(),
+ Label :: label().
add_edge(G, V1, V2, D) ->
do_add_edge({new_edge_id(G), V1, V2, D}, G).
--spec add_edge(digraph(), edge(), vertex(), vertex(), label()) ->
- edge() | {'error', add_edge_err_rsn()}.
+-spec add_edge(G, E, V1, V2, Label) -> edge() | {'error', add_edge_err_rsn()} when
+ G :: digraph(),
+ E :: edge(),
+ V1 :: vertex(),
+ V2 :: vertex(),
+ Label :: label().
add_edge(G, E, V1, V2, D) ->
do_add_edge({E, V1, V2, D}, G).
--spec del_edge(digraph(), edge()) -> 'true'.
+-spec del_edge(G, E) -> 'true' when
+ G :: digraph(),
+ E :: edge().
del_edge(G, E) ->
do_del_edges([E], G).
--spec del_edges(digraph(), [edge()]) -> 'true'.
+-spec del_edges(G, Edges) -> 'true' when
+ G :: digraph(),
+ Edges :: [edge()].
del_edges(G, Es) ->
do_del_edges(Es, G).
--spec no_edges(digraph()) -> non_neg_integer().
+-spec no_edges(G) -> non_neg_integer() when
+ G :: digraph().
no_edges(G) ->
ets:info(G#digraph.etab, size).
--spec edges(digraph()) -> [edge()].
+-spec edges(G) -> Edges when
+ G :: digraph(),
+ Edges :: [edge()].
edges(G) ->
ets:select(G#digraph.etab, [{{'$1', '_', '_', '_'}, [], ['$1']}]).
--spec edges(digraph(), vertex()) -> [edge()].
+-spec edges(G, V) -> Edges when
+ G :: digraph(),
+ V :: vertex(),
+ Edges :: [edge()].
edges(G, V) ->
ets:select(G#digraph.ntab, [{{{out, V},'$1'}, [], ['$1']},
{{{in, V}, '$1'}, [], ['$1']}]).
--spec edge(digraph(), edge()) -> {edge(),vertex(),vertex(),label()} | 'false'.
+-spec edge(G, E) -> {E, V1, V2, Label} | 'false' when
+ G :: digraph(),
+ E :: edge(),
+ V1 :: vertex(),
+ V2 :: vertex(),
+ Label :: label().
edge(G, E) ->
case ets:lookup(G#digraph.etab,E) of
@@ -277,7 +339,7 @@ edge(G, E) ->
%%
%% Generate a "unique" edge identifier (relative to this graph)
%%
--spec new_edge_id(digraph()) -> nonempty_improper_list('$e', non_neg_integer()).
+-spec new_edge_id(digraph()) -> edge().
new_edge_id(G) ->
NT = G#digraph.ntab,
@@ -289,7 +351,7 @@ new_edge_id(G) ->
%%
%% Generate a "unique" vertex identifier (relative to this graph)
%%
--spec new_vertex_id(digraph()) -> nonempty_improper_list('$v', non_neg_integer()).
+-spec new_vertex_id(digraph()) -> vertex().
new_vertex_id(G) ->
NT = G#digraph.ntab,
@@ -444,7 +506,10 @@ acyclic_add_edge(E, V1, V2, Label, G) ->
%% Delete all paths from vertex V1 to vertex V2
%%
--spec del_path(digraph(), vertex(), vertex()) -> 'true'.
+-spec del_path(G, V1, V2) -> 'true' when
+ G :: digraph(),
+ V1 :: vertex(),
+ V2 :: vertex().
del_path(G, V1, V2) ->
case get_path(G, V1, V2) of
@@ -463,7 +528,10 @@ del_path(G, V1, V2) ->
%% been searched.
%%
--spec get_cycle(digraph(), vertex()) -> [vertex(),...] | 'false'.
+-spec get_cycle(G, V) -> Vertices | 'false' when
+ G :: digraph(),
+ V :: vertex(),
+ Vertices :: [vertex(),...].
get_cycle(G, V) ->
case one_path(out_neighbours(G, V), V, [], [V], [V], 2, G, 1) of
@@ -481,7 +549,11 @@ get_cycle(G, V) ->
%% if no path exists false is returned
%%
--spec get_path(digraph(), vertex(), vertex()) -> [vertex(),...] | 'false'.
+-spec get_path(G, V1, V2) -> Vertices | 'false' when
+ G :: digraph(),
+ V1 :: vertex(),
+ V2 :: vertex(),
+ Vertices :: [vertex(),...].
get_path(G, V1, V2) ->
one_path(out_neighbours(G, V1), V2, [], [V1], [V1], 1, G, 1).
@@ -516,7 +588,10 @@ one_path([], _, [], _, _, _, _, _Counter) -> false.
%% Like get_cycle/2, but a cycle of length one is preferred.
%%
--spec get_short_cycle(digraph(), vertex()) -> [vertex(),...] | 'false'.
+-spec get_short_cycle(G, V) -> Vertices | 'false' when
+ G :: digraph(),
+ V :: vertex(),
+ Vertices :: [vertex(),...].
get_short_cycle(G, V) ->
get_short_path(G, V, V).
@@ -526,7 +601,11 @@ get_short_cycle(G, V) ->
%% to find a short path.
%%
--spec get_short_path(digraph(), vertex(), vertex()) -> [vertex(),...] | 'false'.
+-spec get_short_path(G, V1, V2) -> Vertices | 'false' when
+ G :: digraph(),
+ V1 :: vertex(),
+ V2 :: vertex(),
+ Vertices :: [vertex(),...].
get_short_path(G, V1, V2) ->
T = new(),
diff --git a/lib/stdlib/src/digraph_utils.erl b/lib/stdlib/src/digraph_utils.erl
index 080cae4742..e221be15a1 100644
--- a/lib/stdlib/src/digraph_utils.erl
+++ b/lib/stdlib/src/digraph_utils.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
%%
%% The 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,48 +38,66 @@
%% A convenient type alias
%%
--type vertices() :: [digraph:vertex()].
-
%%
%% Exported functions
%%
--spec components(digraph()) -> vertices().
+-spec components(Digraph) -> [Component] when
+ Digraph :: digraph(),
+ Component :: [digraph:vertex()].
components(G) ->
forest(G, fun inout/3).
--spec strong_components(digraph()) -> vertices().
+-spec strong_components(Digraph) -> [StrongComponent] when
+ Digraph :: digraph(),
+ StrongComponent :: [digraph:vertex()].
strong_components(G) ->
forest(G, fun in/3, revpostorder(G)).
--spec cyclic_strong_components(digraph()) -> vertices().
+-spec cyclic_strong_components(Digraph) -> [StrongComponent] when
+ Digraph :: digraph(),
+ StrongComponent :: [digraph:vertex()].
cyclic_strong_components(G) ->
remove_singletons(strong_components(G), G, []).
--spec reachable(vertices(), digraph()) -> vertices().
+-spec reachable(Vertices, Digraph) -> Reachable when
+ Digraph :: digraph(),
+ Vertices :: [digraph:vertex()],
+ Reachable :: [digraph:vertex()].
reachable(Vs, G) when is_list(Vs) ->
lists:append(forest(G, fun out/3, Vs, first)).
--spec reachable_neighbours(vertices(), digraph()) -> vertices().
+-spec reachable_neighbours(Vertices, Digraph) -> Reachable when
+ Digraph :: digraph(),
+ Vertices :: [digraph:vertex()],
+ Reachable :: [digraph:vertex()].
reachable_neighbours(Vs, G) when is_list(Vs) ->
lists:append(forest(G, fun out/3, Vs, not_first)).
--spec reaching(vertices(), digraph()) -> vertices().
+-spec reaching(Vertices, Digraph) -> Reaching when
+ Digraph :: digraph(),
+ Vertices :: [digraph:vertex()],
+ Reaching :: [digraph:vertex()].
reaching(Vs, G) when is_list(Vs) ->
lists:append(forest(G, fun in/3, Vs, first)).
--spec reaching_neighbours(vertices(), digraph()) -> vertices().
+-spec reaching_neighbours(Vertices, Digraph) -> Reaching when
+ Digraph :: digraph(),
+ Vertices :: [digraph:vertex()],
+ Reaching :: [digraph:vertex()].
reaching_neighbours(Vs, G) when is_list(Vs) ->
lists:append(forest(G, fun in/3, Vs, not_first)).
--spec topsort(digraph()) -> vertices() | 'false'.
+-spec topsort(Digraph) -> Vertices | 'false' when
+ Digraph :: digraph(),
+ Vertices :: [digraph:vertex()].
topsort(G) ->
L = revpostorder(G),
@@ -88,12 +106,15 @@ topsort(G) ->
false -> false
end.
--spec is_acyclic(digraph()) -> boolean().
+-spec is_acyclic(Digraph) -> boolean() when
+ Digraph :: digraph().
is_acyclic(G) ->
loop_vertices(G) =:= [] andalso topsort(G) =/= false.
--spec arborescence_root(digraph()) -> 'no' | {'yes', digraph:vertex()}.
+-spec arborescence_root(Digraph) -> 'no' | {'yes', Root} when
+ Digraph :: digraph(),
+ Root :: digraph:vertex().
arborescence_root(G) ->
case digraph:no_edges(G) =:= digraph:no_vertices(G) - 1 of
@@ -114,23 +135,30 @@ arborescence_root(G) ->
no
end.
--spec is_arborescence(digraph()) -> boolean().
+-spec is_arborescence(Digraph) -> boolean() when
+ Digraph :: digraph().
is_arborescence(G) ->
arborescence_root(G) =/= no.
--spec is_tree(digraph()) -> boolean().
+-spec is_tree(Digraph) -> boolean() when
+ Digraph :: digraph().
is_tree(G) ->
(digraph:no_edges(G) =:= digraph:no_vertices(G) - 1)
andalso (length(components(G)) =:= 1).
--spec loop_vertices(digraph()) -> vertices().
+-spec loop_vertices(Digraph) -> Vertices when
+ Digraph :: digraph(),
+ Vertices :: [digraph:vertex()].
loop_vertices(G) ->
[V || V <- digraph:vertices(G), is_reflexive_vertex(V, G)].
--spec subgraph(digraph(), vertices()) -> digraph().
+-spec subgraph(Digraph, Vertices) -> SubGraph when
+ Digraph :: digraph(),
+ Vertices :: [digraph:vertex()],
+ SubGraph :: digraph().
subgraph(G, Vs) ->
try
@@ -140,10 +168,12 @@ subgraph(G, Vs) ->
erlang:error(badarg)
end.
--type option() :: {'type', 'inherit' | [digraph:d_type()]}
- | {'keep_labels', boolean()}.
-
--spec subgraph(digraph(), vertices(), [option()]) -> digraph().
+-spec subgraph(Digraph, Vertices, Options) -> SubGraph when
+ Digraph :: digraph(),
+ SubGraph :: digraph(),
+ Vertices :: [digraph:vertex()],
+ Options :: [{'type', SubgraphType} | {'keep_labels', boolean()}],
+ SubgraphType :: 'inherit' | [digraph:d_type()].
subgraph(G, Vs, Opts) ->
try
@@ -153,7 +183,9 @@ subgraph(G, Vs, Opts) ->
erlang:error(badarg)
end.
--spec condensation(digraph()) -> digraph().
+-spec condensation(Digraph) -> CondensedDigraph when
+ Digraph :: digraph(),
+ CondensedDigraph :: digraph().
condensation(G) ->
SCs = strong_components(G),
@@ -176,12 +208,16 @@ condensation(G) ->
ets:delete(I2C),
SCG.
--spec preorder(digraph()) -> vertices().
+-spec preorder(Digraph) -> Vertices when
+ Digraph :: digraph(),
+ Vertices :: [digraph:vertex()].
preorder(G) ->
lists:reverse(revpreorder(G)).
--spec postorder(digraph()) -> vertices().
+-spec postorder(Digraph) -> Vertices when
+ Digraph :: digraph(),
+ Vertices :: [digraph:vertex()].
postorder(G) ->
lists:reverse(revpostorder(G)).
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index e5ccaddbb4..230a4a0612 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,6 +29,7 @@
%%------------------------------------------------------------------------
-type macros() :: [{atom(), term()}].
+-type epp_handle() :: pid().
%% Epp state record.
-record(epp, {file, %Current file
@@ -61,14 +62,23 @@
%% parse_file(FileName, IncludePath, PreDefMacros)
%% macro_defs(Epp)
--spec open(file:name(), [file:name()]) ->
- {'ok', pid()} | {'error', term()}.
+-spec open(FileName, IncludePath) ->
+ {'ok', Epp} | {'error', ErrorDescriptor} when
+ FileName :: file:name(),
+ IncludePath :: [DirectoryName :: file:name()],
+ Epp :: epp_handle(),
+ ErrorDescriptor :: term().
open(Name, Path) ->
open(Name, Path, []).
--spec open(file:name(), [file:name()], macros()) ->
- {'ok', pid()} | {'error', term()}.
+-spec open(FileName, IncludePath, PredefMacros) ->
+ {'ok', Epp} | {'error', ErrorDescriptor} when
+ FileName :: file:name(),
+ IncludePath :: [DirectoryName :: file:name()],
+ PredefMacros :: macros(),
+ Epp :: epp_handle(),
+ ErrorDescriptor :: term().
open(Name, Path, Pdm) ->
Self = self(),
@@ -80,7 +90,8 @@ open(Name, File, StartLocation, Path, Pdm) ->
Epp = spawn(fun() -> server(Self, Name, File, StartLocation,Path,Pdm) end),
epp_request(Epp).
--spec close(pid()) -> 'ok'.
+-spec close(Epp) -> 'ok' when
+ Epp :: epp_handle().
close(Epp) ->
%% Make sure that close is synchronous as a courtesy to test
@@ -93,6 +104,13 @@ close(Epp) ->
scan_erl_form(Epp) ->
epp_request(Epp, scan_erl_form).
+-spec parse_erl_form(Epp) ->
+ {'ok', AbsForm} | {'eof', Line} | {error, ErrorInfo} when
+ Epp :: epp_handle(),
+ AbsForm :: erl_parse:abstract_form(),
+ Line :: erl_scan:line(),
+ ErrorInfo :: erl_scan:error_info() | erl_parse:error_info().
+
parse_erl_form(Epp) ->
case epp_request(Epp, scan_erl_form) of
{ok,Toks} ->
@@ -107,6 +125,9 @@ macro_defs(Epp) ->
%% format_error(ErrorDescriptor) -> String
%% Return a string describing the error.
+-spec format_error(ErrorDescriptor) -> io_lib:chars() when
+ ErrorDescriptor :: term().
+
format_error(cannot_parse) ->
io_lib:format("cannot parse file, giving up", []);
format_error({bad,W}) ->
@@ -146,6 +167,16 @@ format_error(E) -> file:format_error(E).
%% parse_file(FileName, IncludePath, [PreDefMacro]) ->
%% {ok,[Form]} | {error,OpenError}
+-spec parse_file(FileName, IncludePath, PredefMacros) ->
+ {'ok', [Form]} | {error, OpenError} when
+ FileName :: file:name(),
+ IncludePath :: [DirectoryName :: file:name()],
+ Form :: erl_parse:abstract_form() | {'error', ErrorInfo} | {'eof',Line},
+ PredefMacros :: macros(),
+ Line :: erl_scan:line(),
+ ErrorInfo :: erl_scan:error_info() | erl_parse:error_info(),
+ OpenError :: file:posix() | badarg | system_limit.
+
parse_file(Ifile, Path, Predefs) ->
case open(Ifile, Path, Predefs) of
{ok,Epp} ->
@@ -653,7 +684,7 @@ scan_include_lib([{'(',_Llp},{string,_Lf,NewName0},{')',_Lrp},{dot,_Ld}],
{error,_E1} ->
case catch find_lib_dir(NewName) of
{LibDir, Rest} when is_list(LibDir) ->
- LibName = filename:join([LibDir | Rest]),
+ LibName = fname_join([LibDir | Rest]),
case file:open(LibName, [read]) of
{ok,NewF} ->
ExtraPath = [filename:dirname(LibName)],
@@ -1123,7 +1154,12 @@ expand_var1(NewName) ->
[[$$ | Var] | Rest] = filename:split(NewName),
Value = os:getenv(Var),
true = Value =/= false,
- {ok, filename:join([Value | Rest])}.
+ {ok, fname_join([Value | Rest])}.
+
+fname_join(["." | [_|_]=Rest]) ->
+ fname_join(Rest);
+fname_join(Components) ->
+ filename:join(Components).
%% The line only. (Other tokens may have the column and text as well...)
loc_attr(Line) when is_integer(Line) ->
diff --git a/lib/stdlib/src/erl_compile.erl b/lib/stdlib/src/erl_compile.erl
index abff37e4bc..ff032b129c 100644
--- a/lib/stdlib/src/erl_compile.erl
+++ b/lib/stdlib/src/erl_compile.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -41,7 +41,6 @@ compiler(".idl") -> {ic, compile};
compiler(".asn1") -> {asn1ct, compile_asn1};
compiler(".asn") -> {asn1ct, compile_asn};
compiler(".py") -> {asn1ct, compile_py};
-compiler(".xml") -> {xmerl_scan, process};
compiler(_) -> no.
%% Entry from command line.
diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl
index ea1b179ee5..4f4fa16040 100644
--- a/lib/stdlib/src/erl_eval.erl
+++ b/lib/stdlib/src/erl_eval.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,6 +34,37 @@
-import(lists, [reverse/1,foldl/3,member/2]).
+-export_type([binding_struct/0]).
+
+-type(expression() :: erl_parse:abstract_expr()).
+-type(expressions() :: [erl_parse:abstract_expr()]).
+-type(expression_list() :: [expression()]).
+-type(clauses() :: [erl_parse:abstract_clause()]).
+-type(name() :: term()).
+-type(value() :: term()).
+-type(bindings() :: [{name(), value()}]).
+-type(binding_struct() :: orddict:orddict()).
+
+-type(lfun_value_handler() :: fun((Name :: atom(),
+ Arguments :: [term()]) ->
+ Value :: value())).
+-type(lfun_eval_handler() :: fun((Name :: atom(),
+ Arguments :: expression_list(),
+ Bindings :: binding_struct()) ->
+ {value,
+ Value :: value(),
+ NewBindings :: binding_struct()})).
+-type(local_function_handler() :: {value, lfun_value_handler()}
+ | {eval, lfun_eval_handler()}
+ | none).
+
+-type(func_spec() :: {Module :: module(), Function :: atom()} | function()).
+-type(nlfun_handler() :: fun((FuncSpec :: func_spec(),
+ Arguments :: [term()]) ->
+ term())).
+-type(non_local_function_handler() :: {value, nlfun_handler()}
+ | none).
+
%% exprs(ExpressionSeq, Bindings)
%% exprs(ExpressionSeq, Bindings, LocalFuncHandler)
%% exprs(ExpressionSeq, Bindings, LocalFuncHandler, ExternalFuncHandler)
@@ -45,6 +76,11 @@
%% that there are valid constructs in Expression to be taken care of
%% by a function handler but considerad errors by erl_lint.
+-spec(exprs(Expressions, Bindings) -> {value, Value, NewBindings} when
+ Expressions :: expressions(),
+ Bindings :: binding_struct(),
+ Value :: value(),
+ NewBindings :: binding_struct()).
exprs(Exprs, Bs) ->
case check_command(Exprs, Bs) of
ok ->
@@ -53,9 +89,25 @@ exprs(Exprs, Bs) ->
erlang:raise(error, Error, [{?MODULE,exprs,2}])
end.
+-spec(exprs(Expressions, Bindings, LocalFunctionHandler) ->
+ {value, Value, NewBindings} when
+ Expressions :: expressions(),
+ Bindings :: binding_struct(),
+ LocalFunctionHandler :: local_function_handler(),
+ Value :: value(),
+ NewBindings :: binding_struct()).
exprs(Exprs, Bs, Lf) ->
exprs(Exprs, Bs, Lf, none, none).
+-spec(exprs(Expressions, Bindings, LocalFunctionHandler,
+ NonLocalFunctionHandler) ->
+ {value, Value, NewBindings} when
+ Expressions :: expressions(),
+ Bindings :: binding_struct(),
+ LocalFunctionHandler :: local_function_handler(),
+ NonLocalFunctionHandler :: non_local_function_handler(),
+ Value :: value(),
+ NewBindings :: binding_struct()).
exprs(Exprs, Bs, Lf, Ef) ->
exprs(Exprs, Bs, Lf, Ef, none).
@@ -75,6 +127,11 @@ exprs([E|Es], Bs0, Lf, Ef, RBs) ->
%%
%% Only expr/2 checks the command by calling erl_lint. See exprs/2.
+-spec(expr(Expression, Bindings) -> {value, Value, NewBindings} when
+ Expression :: expression(),
+ Bindings :: binding_struct(),
+ Value :: value(),
+ NewBindings :: binding_struct()).
expr(E, Bs) ->
case check_command([E], Bs) of
ok ->
@@ -83,9 +140,25 @@ expr(E, Bs) ->
erlang:raise(error, Error, [{?MODULE,expr,2}])
end.
+-spec(expr(Expression, Bindings, LocalFunctionHandler) ->
+ {value, Value, NewBindings} when
+ Expression :: expression(),
+ Bindings :: binding_struct(),
+ LocalFunctionHandler :: local_function_handler(),
+ Value :: value(),
+ NewBindings :: binding_struct()).
expr(E, Bs, Lf) ->
expr(E, Bs, Lf, none, none).
+-spec(expr(Expression, Bindings, LocalFunctionHandler,
+ NonLocalFunctionHandler) ->
+ {value, Value, NewBindings} when
+ Expression :: expression(),
+ Bindings :: binding_struct(),
+ LocalFunctionHandler :: local_function_handler(),
+ NonLocalFunctionHandler :: non_local_function_handler(),
+ Value :: value(),
+ NewBindings :: binding_struct()).
expr(E, Bs, Lf, Ef) ->
expr(E, Bs, Lf, Ef, none).
@@ -114,6 +187,16 @@ fun_data(F) when is_function(F) ->
fun_data(_T) ->
false.
+-spec(expr(Expression, Bindings, LocalFunctionHandler,
+ NonLocalFunctionHandler, ReturnFormat) ->
+ {value, Value, NewBindings} | Value when
+ Expression :: expression(),
+ Bindings :: binding_struct(),
+ LocalFunctionHandler :: local_function_handler(),
+ NonLocalFunctionHandler :: non_local_function_handler(),
+ ReturnFormat :: none | value,
+ Value :: value(),
+ NewBindings :: binding_struct()).
expr({var,_,V}, Bs, _Lf, _Ef, RBs) ->
case binding(V, Bs) of
{value,Val} ->
@@ -384,12 +467,9 @@ local_func(Func, As0, Bs0, {value,F}, value) ->
local_func(Func, As0, Bs0, {value,F}, RBs) ->
{As1,Bs1} = expr_list(As0, Bs0, {value,F}),
ret_expr(F(Func, As1), Bs1, RBs);
-local_func(Func, As0, Bs0, {value,F,Eas}, value) ->
- {As1,_Bs1} = expr_list(As0, Bs0, {value,F,Eas}),
- apply(F, [Func,As1|Eas]);
local_func(Func, As0, Bs0, {value,F,Eas}, RBs) ->
- {As1,Bs1} = expr_list(As0, Bs0, {value,F,Eas}),
- ret_expr(apply(F, [Func,As1|Eas]), Bs1, RBs);
+ Fun = fun(Name, Args) -> apply(F, [Name,Args|Eas]) end,
+ local_func(Func, As0, Bs0, {value, Fun}, RBs);
local_func(Func, As, Bs, {eval,F}, RBs) ->
local_func2(F(Func, As, Bs), RBs);
local_func(Func, As, Bs, {eval,F,Eas}, RBs) ->
@@ -541,7 +621,7 @@ eval_generate(Term, _P, _Bs0, _Lf, _Ef, _CompFun, _Acc) ->
erlang:raise(error, {bad_generator,Term}, stacktrace()).
eval_b_generate(<<_/bitstring>>=Bin, P, Bs0, Lf, Ef, CompFun, Acc) ->
- Mfun = fun(L, R, Bs) -> match1(L, R, Bs, Bs0) end,
+ Mfun = match_fun(Bs0),
Efun = fun(Exp, Bs) -> expr(Exp, Bs, Lf, Ef, none) end,
case eval_bits:bin_gen(P, Bin, new_bindings(), Bs0, Mfun, Efun) of
{match, Rest, Bs1} ->
@@ -613,12 +693,33 @@ eval_fun([], As, _Bs, _Lf, _Ef, _RBs) ->
%% expr_list(ExpressionList, Bindings, LocalFuncHandler, ExternalFuncHandler)
%% Evaluate a list of expressions "in parallel" at the same level.
+-spec(expr_list(ExpressionList, Bindings) -> {ValueList, NewBindings} when
+ ExpressionList :: expression_list(),
+ Bindings :: binding_struct(),
+ ValueList :: [value()],
+ NewBindings :: binding_struct()).
expr_list(Es, Bs) ->
expr_list(Es, Bs, none, none).
+-spec(expr_list(ExpressionList, Bindings, LocalFunctionHandler) ->
+ {ValueList, NewBindings} when
+ ExpressionList :: expression_list(),
+ Bindings :: binding_struct(),
+ LocalFunctionHandler :: local_function_handler(),
+ ValueList :: [value()],
+ NewBindings :: binding_struct()).
expr_list(Es, Bs, Lf) ->
expr_list(Es, Bs, Lf, none).
+-spec(expr_list(ExpressionList, Bindings, LocalFunctionHandler,
+ NonLocalFunctionHandler) ->
+ {ValueList, NewBindings} when
+ ExpressionList :: expression_list(),
+ Bindings :: binding_struct(),
+ LocalFunctionHandler :: local_function_handler(),
+ NonLocalFunctionHandler :: non_local_function_handler(),
+ ValueList :: [value()],
+ NewBindings :: binding_struct()).
expr_list(Es, Bs, Lf, Ef) ->
expr_list(Es, [], Bs, Bs, Lf, Ef).
@@ -757,6 +858,15 @@ send_all([], _) -> true.
%% match_clause -> {Body, Bindings} or nomatch
+-spec(match_clause(Clauses, ValueList, Bindings, LocalFunctionHandler) ->
+ {Body, NewBindings} | nomatch when
+ Clauses :: clauses(),
+ ValueList :: [value()],
+ Bindings :: binding_struct(),
+ LocalFunctionHandler :: local_function_handler(),
+ Body :: expression_list(),
+ NewBindings :: binding_struct()).
+
match_clause(Cs, Vs, Bs, Lf) ->
match_clause(Cs, Vs, Bs, Lf, none).
@@ -914,7 +1024,7 @@ match1({tuple,_,_}, _, _Bs, _BBs) ->
throw(nomatch);
match1({bin, _, Fs}, <<_/bitstring>>=B, Bs0, BBs) ->
eval_bits:match_bits(Fs, B, Bs0, BBs,
- fun(L, R, Bs) -> match1(L, R, Bs, BBs) end,
+ match_fun(BBs),
fun(E, Bs) -> expr(E, Bs, none, none, none) end);
match1({bin,_,_}, _, _Bs, _BBs) ->
throw(nomatch);
@@ -943,6 +1053,12 @@ match1({op,Line,Op,L,R}, Term, Bs, BBs) ->
match1(_, _, _Bs, _BBs) ->
throw(invalid).
+match_fun(BBs) ->
+ fun(match, {L,R,Bs}) -> match1(L, R, Bs, BBs);
+ (binding, {Name,Bs}) -> binding(Name, Bs);
+ (add_binding, {Name,Val,Bs}) -> add_binding(Name, Val, Bs)
+ end.
+
match_tuple([E|Es], Tuple, I, Bs0, BBs) ->
{match,Bs} = match1(E, element(I, Tuple), Bs0, BBs),
match_tuple(Es, Tuple, I+1, Bs, BBs);
@@ -973,18 +1089,30 @@ match_list(_, _, _Bs, _BBs) ->
%% add_binding(Name, Value, Bindings)
%% del_binding(Name, Bindings)
+-spec(new_bindings() -> binding_struct()).
new_bindings() -> orddict:new().
+-spec(bindings(BindingStruct :: binding_struct()) -> bindings()).
bindings(Bs) -> orddict:to_list(Bs).
+-spec(binding(Name, BindingStruct) -> {value, value()} | unbound when
+ Name :: name(),
+ BindingStruct :: binding_struct()).
binding(Name, Bs) ->
case orddict:find(Name, Bs) of
{ok,Val} -> {value,Val};
error -> unbound
end.
+-spec(add_binding(Name, Value, BindingStruct) -> binding_struct() when
+ Name :: name(),
+ Value :: value(),
+ BindingStruct :: binding_struct()).
add_binding(Name, Val, Bs) -> orddict:store(Name, Val, Bs).
+-spec(del_binding(Name, BindingStruct) -> binding_struct() when
+ Name :: name(),
+ BindingStruct :: binding_struct()).
del_binding(Name, Bs) -> orddict:erase(Name, Bs).
add_bindings(Bs1, Bs2) ->
diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl
index 61ce41f714..20fd247cea 100644
--- a/lib/stdlib/src/erl_expand_records.erl
+++ b/lib/stdlib/src/erl_expand_records.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The 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,9 +35,13 @@
trecords=sets:new(), % Typed records
uses_types=false, % Are there -spec or -type in the module
strict_ra=[], % strict record accesses
- checked_ra=[] % succesfully accessed records
+ checked_ra=[] % successfully accessed records
}).
+-spec(module(AbsForms, CompileOptions) -> AbsForms when
+ AbsForms :: [erl_parse:abstract_form()],
+ CompileOptions :: [compile:option()]).
+
%% Is is assumed that Fs is a valid list of forms. It should pass
%% erl_lint without errors.
module(Fs0, Opts0) ->
diff --git a/lib/stdlib/src/erl_internal.erl b/lib/stdlib/src/erl_internal.erl
index b30b02a96f..cd3b531d10 100644
--- a/lib/stdlib/src/erl_internal.erl
+++ b/lib/stdlib/src/erl_internal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -54,7 +54,9 @@
%%---------------------------------------------------------------------------
%% Erlang builtin functions allowed in guards.
--spec guard_bif(Name::atom(), Arity::arity()) -> boolean().
+-spec guard_bif(Name, Arity) -> boolean() when
+ Name :: atom(),
+ Arity :: arity().
guard_bif(abs, 1) -> true;
guard_bif(float, 1) -> true;
@@ -92,7 +94,9 @@ guard_bif(binary_part, 3) -> true;
guard_bif(Name, A) when is_atom(Name), is_integer(A) -> false.
%% Erlang type tests.
--spec type_test(Name::atom(), Arity::arity()) -> boolean().
+-spec type_test(Name, Arity) -> boolean() when
+ Name :: atom(),
+ Arity :: arity().
type_test(Name, Arity) ->
new_type_test(Name, Arity) orelse old_type_test(Name, Arity).
@@ -135,7 +139,9 @@ old_type_test(record, 2) -> true;
old_type_test(function, 1) -> true;
old_type_test(Name, A) when is_atom(Name), is_integer(A) -> false.
--spec arith_op(Op::atom(), Arity::arity()) -> boolean().
+-spec arith_op(OpName, Arity) -> boolean() when
+ OpName :: atom(),
+ Arity :: arity().
arith_op('+', 1) -> true;
arith_op('-', 1) -> true;
@@ -153,7 +159,9 @@ arith_op('bsl', 2) -> true;
arith_op('bsr', 2) -> true;
arith_op(Op, A) when is_atom(Op), is_integer(A) -> false.
--spec bool_op(Op::atom(), Arity::arity()) -> boolean().
+-spec bool_op(OpName, Arity) -> boolean() when
+ OpName :: atom(),
+ Arity :: arity().
bool_op('not', 1) -> true;
bool_op('and', 2) -> true;
@@ -161,7 +169,9 @@ bool_op('or', 2) -> true;
bool_op('xor', 2) -> true;
bool_op(Op, A) when is_atom(Op), is_integer(A) -> false.
--spec comp_op(Op::atom(), Arity::arity()) -> boolean().
+-spec comp_op(OpName, Arity) -> boolean() when
+ OpName :: atom(),
+ Arity :: arity().
comp_op('==', 2) -> true;
comp_op('/=', 2) -> true;
@@ -173,18 +183,25 @@ comp_op('=:=', 2) -> true;
comp_op('=/=', 2) -> true;
comp_op(Op, A) when is_atom(Op), is_integer(A) -> false.
--spec list_op(Op::atom(), Arity::arity()) -> boolean().
+-spec list_op(OpName, Arity) -> boolean() when
+ OpName :: atom(),
+ Arity :: arity().
list_op('++', 2) -> true;
list_op('--', 2) -> true;
list_op(Op, A) when is_atom(Op), is_integer(A) -> false.
--spec send_op(Op::atom(), Arity::arity()) -> boolean().
+-spec send_op(OpName, Arity) -> boolean() when
+ OpName :: atom(),
+ Arity :: arity().
send_op('!', 2) -> true;
send_op(Op, A) when is_atom(Op), is_integer(A) -> false.
--spec op_type(atom(), arity()) -> 'arith' | 'bool' | 'comp' | 'list' | 'send'.
+-spec op_type(OpName, Arity) -> Type when
+ OpName :: atom(),
+ Arity :: arity(),
+ Type :: 'arith' | 'bool' | 'comp' | 'list' | 'send'.
op_type('+', 1) -> arith;
op_type('-', 1) -> arith;
@@ -221,7 +238,9 @@ op_type('!', 2) -> send.
bif(erlang, Name, Arity) -> bif(Name, Arity);
bif(M, F, A) when is_atom(M), is_atom(F), is_integer(A) -> false.
--spec bif(Name::atom(), Arity::arity()) -> boolean().
+-spec bif(Name, Arity) -> boolean() when
+ Name :: atom(),
+ Arity::arity().
%% Returns true if erlang:Name/Arity is an auto-imported BIF, false otherwise.
%% Use erlang:is_bultin(Mod, Name, Arity) to find whether a function is a BIF
%% (meaning implemented in C) or not.
@@ -243,8 +262,8 @@ bif(bitsize, 1) -> true;
bif(bit_size, 1) -> true;
bif(bitstring_to_list, 1) -> true;
bif(byte_size, 1) -> true;
+bif(check_old_code, 1) -> true;
bif(check_process_code, 2) -> true;
-bif(concat_binary, 1) -> true;
bif(date, 0) -> true;
bif(delete_module, 1) -> true;
bif(demonitor, 1) -> true;
@@ -386,7 +405,6 @@ old_bif(bit_size, 1) -> true;
old_bif(bitstring_to_list, 1) -> true;
old_bif(byte_size, 1) -> true;
old_bif(check_process_code, 2) -> true;
-old_bif(concat_binary, 1) -> true;
old_bif(date, 0) -> true;
old_bif(delete_module, 1) -> true;
old_bif(disconnect_node, 1) -> true;
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index cfb9f0ca98..78b996d94b 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -123,15 +123,21 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
called= [] :: [{fa(),line()}], %Called functions
usage = #usage{} :: #usage{},
specs = dict:new() :: dict(), %Type specifications
+ callbacks = dict:new() :: dict(), %Callback types
types = dict:new() :: dict(), %Type definitions
exp_types=gb_sets:empty():: gb_set() %Exported types
}).
-type lint_state() :: #lint{}.
+-type error_description() :: term().
+-type error_info() :: {erl_scan:line(), module(), error_description()}.
%% format_error(Error)
%% Return a string describing the error.
+-spec format_error(ErrorDescriptor) -> io_lib:chars() when
+ ErrorDescriptor :: error_description().
+
format_error(undefined_module) ->
"no module definition";
format_error({bad_module_name, M}) ->
@@ -305,8 +311,6 @@ format_error({conflicting_behaviours,{Name,Arity},B,FirstL,FirstB}) ->
format_error({undefined_behaviour_func, {Func,Arity}, Behaviour}) ->
io_lib:format("undefined callback function ~w/~w (behaviour '~w')",
[Func,Arity,Behaviour]);
-format_error({undefined_behaviour_func, {Func,Arity,_Spec}, Behaviour}) ->
- format_error({undefined_behaviour_func, {Func,Arity}, Behaviour});
format_error({undefined_behaviour,Behaviour}) ->
io_lib:format("behaviour ~w undefined", [Behaviour]);
format_error({undefined_behaviour_callbacks,Behaviour}) ->
@@ -315,6 +319,9 @@ format_error({undefined_behaviour_callbacks,Behaviour}) ->
format_error({ill_defined_behaviour_callbacks,Behaviour}) ->
io_lib:format("behaviour ~w callback functions erroneously defined",
[Behaviour]);
+format_error({behaviour_info, {_M,F,A}}) ->
+ io_lib:format("cannot define callback attibute for ~w/~w when "
+ "behaviour_info is defined",[F,A]);
%% --- types and specs ---
format_error({singleton_typevar, Name}) ->
io_lib:format("type variable ~w is only used once (is unbound)", [Name]);
@@ -343,12 +350,16 @@ format_error({type_syntax, Constr}) ->
io_lib:format("bad ~w type", [Constr]);
format_error({redefine_spec, {M, F, A}}) ->
io_lib:format("spec for ~w:~w/~w already defined", [M, F, A]);
+format_error({redefine_callback, {M, F, A}}) ->
+ io_lib:format("callback ~w:~w/~w already defined", [M, F, A]);
format_error({spec_fun_undefined, {M, F, A}}) ->
io_lib:format("spec for undefined function ~w:~w/~w", [M, F, A]);
format_error({missing_spec, {F,A}}) ->
io_lib:format("missing specification for function ~w/~w", [F, A]);
format_error(spec_wrong_arity) ->
"spec has the wrong arity";
+format_error(callback_wrong_arity) ->
+ "callback has the wrong arity";
format_error({imported_predefined_type, Name}) ->
io_lib:format("referring to built-in type ~w as a remote type; "
"please take out the module name", [Name]);
@@ -419,16 +430,39 @@ used_vars(Exprs, BindingsList) ->
%% apply_lambda/2 has been called to shut lint up. N.B. these lists are
%% really all ordsets!
+-spec(module(AbsForms) -> {ok, Warnings} | {error, Errors, Warnings} when
+ AbsForms :: [erl_parse:abstract_form()],
+ Warnings :: [{file:filename(),[ErrorInfo]}],
+ Errors :: [{FileName2 :: file:filename(),[ErrorInfo]}],
+ ErrorInfo :: error_info()).
+
module(Forms) ->
Opts = compiler_options(Forms),
St = forms(Forms, start("nofile", Opts)),
return_status(St).
+-spec(module(AbsForms, FileName) ->
+ {ok, Warnings} | {error, Errors, Warnings} when
+ AbsForms :: [erl_parse:abstract_form()],
+ FileName :: atom() | string(),
+ Warnings :: [{file:filename(),[ErrorInfo]}],
+ Errors :: [{FileName2 :: file:filename(),[ErrorInfo]}],
+ ErrorInfo :: error_info()).
+
module(Forms, FileName) ->
Opts = compiler_options(Forms),
St = forms(Forms, start(FileName, Opts)),
return_status(St).
+-spec(module(AbsForms, FileName, CompileOptions) ->
+ {ok, Warnings} | {error, Errors, Warnings} when
+ AbsForms :: [erl_parse:abstract_form()],
+ FileName :: atom() | string(),
+ CompileOptions :: [compile:option()],
+ Warnings :: [{file:filename(),[ErrorInfo]}],
+ Errors :: [{FileName2 :: file:filename(),[ErrorInfo]}],
+ ErrorInfo :: error_info()).
+
module(Forms, FileName, Opts0) ->
%% We want the options given on the command line to take
%% precedence over options in the module.
@@ -719,6 +753,8 @@ attribute_state({attribute,L,opaque,{TypeName,TypeDef,Args}}, St) ->
type_def(opaque, L, TypeName, TypeDef, Args, St);
attribute_state({attribute,L,spec,{Fun,Types}}, St) ->
spec_decl(L, Fun, Types, St);
+attribute_state({attribute,L,callback,{Fun,Types}}, St) ->
+ callback_decl(L, Fun, Types, St);
attribute_state({attribute,L,on_load,Val}, St) ->
on_load(L, Val, St);
attribute_state({attribute,_L,_Other,_Val}, St) -> % Ignore others
@@ -812,7 +848,8 @@ post_traversal_check(Forms, St0) ->
StB = check_unused_types(Forms, StA),
StC = check_untyped_records(Forms, StB),
StD = check_on_load(StC),
- check_unused_records(Forms, StD).
+ StE = check_unused_records(Forms, StD),
+ check_callback_information(StE).
%% check_behaviour(State0) -> State
%% Check that the behaviour attribute is valid.
@@ -1111,6 +1148,23 @@ check_unused_records(Forms, St0) ->
St0
end.
+check_callback_information(#lint{callbacks = Callbacks,
+ defined = Defined} = State) ->
+ case gb_sets:is_member({behaviour_info,1}, Defined) of
+ false -> State;
+ true ->
+ case dict:size(Callbacks) of
+ 0 -> State;
+ _ ->
+ CallbacksList = dict:to_list(Callbacks),
+ FoldL =
+ fun({Fa,Line},St) ->
+ add_error(Line, {behaviour_info, Fa}, St)
+ end,
+ lists:foldl(FoldL, State, CallbacksList)
+ end
+ end.
+
%% For storing the import list we use the orddict module.
%% We know an empty set is [].
@@ -1877,6 +1931,9 @@ gexpr_list(Es, Vt, St) ->
%% is_guard_test(Expression) -> boolean().
%% Test if a general expression is a guard test.
+-spec is_guard_test(Expr) -> boolean() when
+ Expr :: erl_parse:abstract_expr().
+
is_guard_test(E) ->
is_guard_test2(E, dict:new()).
@@ -2739,6 +2796,20 @@ spec_decl(Line, MFA0, TypeSpecs, St0 = #lint{specs = Specs, module = Mod}) ->
false -> check_specs(TypeSpecs, Arity, St1)
end.
+%% callback_decl(Line, Fun, Types, State) -> State.
+
+callback_decl(Line, MFA0, TypeSpecs,
+ St0 = #lint{callbacks = Callbacks, module = Mod}) ->
+ MFA = case MFA0 of
+ {F, Arity} -> {Mod, F, Arity};
+ {_M, _F, Arity} -> MFA0
+ end,
+ St1 = St0#lint{callbacks = dict:store(MFA, Line, Callbacks)},
+ case dict:is_key(MFA, Callbacks) of
+ true -> add_error(Line, {redefine_callback, MFA}, St1);
+ false -> check_specs(TypeSpecs, Arity, St1)
+ end.
+
check_specs([FunType|Left], Arity, St0) ->
{FunType1, CTypes} =
case FunType of
@@ -3244,6 +3315,8 @@ modify_line1({attribute,L,record,{Name,Fields}}, Mf) ->
{attribute,Mf(L),record,{Name,modify_line1(Fields, Mf)}};
modify_line1({attribute,L,spec,{Fun,Types}}, Mf) ->
{attribute,Mf(L),spec,{Fun,modify_line1(Types, Mf)}};
+modify_line1({attribute,L,callback,{Fun,Types}}, Mf) ->
+ {attribute,Mf(L),callback,{Fun,modify_line1(Types, Mf)}};
modify_line1({attribute,L,type,{TypeName,TypeDef,Args}}, Mf) ->
{attribute,Mf(L),type,{TypeName,modify_line1(TypeDef, Mf),
modify_line1(Args, Mf)}};
diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl
index 15b45d72f4..709bd83e6f 100644
--- a/lib/stdlib/src/erl_parse.yrl
+++ b/lib/stdlib/src/erl_parse.yrl
@@ -62,7 +62,7 @@ char integer float atom string var
'==' '/=' '=<' '<' '>=' '>' '=:=' '=/=' '<='
'<<' '>>'
'!' '=' '::' '..' '...'
-'spec' % helper
+'spec' 'callback' % helper
dot.
Expect 2.
@@ -77,6 +77,7 @@ attribute -> '-' atom attr_val : build_attribute('$2', '$3').
attribute -> '-' atom typed_attr_val : build_typed_attribute('$2','$3').
attribute -> '-' atom '(' typed_attr_val ')' : build_typed_attribute('$2','$4').
attribute -> '-' 'spec' type_spec : build_type_spec('$2', '$3').
+attribute -> '-' 'callback' type_spec : build_type_spec('$2', '$3').
type_spec -> spec_fun type_sigs : {'$1', '$2'}.
type_spec -> '(' spec_fun type_sigs ')' : {'$2', '$3'}.
@@ -511,6 +512,15 @@ Erlang code.
%% of the generated .erl file by the HiPE compiler. Please do not remove.
-compile([{hipe,[{regalloc,linear_scan}]}]).
+-export_type([abstract_clause/0, abstract_expr/0, abstract_form/0,
+ error_info/0]).
+
+-type abstract_clause() :: term().
+-type abstract_expr() :: term().
+-type abstract_form() :: term().
+-type error_description() :: term().
+-type error_info() :: {erl_scan:line(), module(), error_description()}.
+-type token() :: {Tag :: atom(), Line :: erl_scan:line()}.
%% mkop(Op, Arg) -> {op,Line,Op,Arg}.
%% mkop(Left, Op, Right) -> {op,Line,Op,Left,Right}.
@@ -534,11 +544,21 @@ Erlang code.
%% These really suck and are only here until Calle gets multiple
%% entry points working.
+-spec parse_form(Tokens) -> {ok, AbsForm} | {error, ErrorInfo} when
+ Tokens :: [token()],
+ AbsForm :: abstract_form(),
+ ErrorInfo :: error_info().
parse_form([{'-',L1},{atom,L2,spec}|Tokens]) ->
parse([{'-',L1},{'spec',L2}|Tokens]);
+parse_form([{'-',L1},{atom,L2,callback}|Tokens]) ->
+ parse([{'-',L1},{'callback',L2}|Tokens]);
parse_form(Tokens) ->
parse(Tokens).
+-spec parse_exprs(Tokens) -> {ok, ExprList} | {error, ErrorInfo} when
+ Tokens :: [token()],
+ ExprList :: [abstract_expr()],
+ ErrorInfo :: error_info().
parse_exprs(Tokens) ->
case parse([{atom,0,f},{'(',0},{')',0},{'->',0}|Tokens]) of
{ok,{function,_Lf,f,0,[{clause,_Lc,[],[],Exprs}]}} ->
@@ -546,6 +566,10 @@ parse_exprs(Tokens) ->
{error,_} = Err -> Err
end.
+-spec parse_term(Tokens) -> {ok, Term} | {error, ErrorInfo} when
+ Tokens :: [token()],
+ Term :: term(),
+ ErrorInfo :: error_info().
parse_term(Tokens) ->
case parse([{atom,0,f},{'(',0},{')',0},{'->',0}|Tokens]) of
{ok,{function,_Lf,f,0,[{clause,_Lc,[],[],[Expr]}]}} ->
@@ -582,7 +606,8 @@ build_typed_attribute({atom,La,Attr},_) ->
_ -> ret_err(La, "bad attribute")
end.
-build_type_spec({spec,La}, {SpecFun, TypeSpecs}) ->
+build_type_spec({Kind,La}, {SpecFun, TypeSpecs})
+ when (Kind =:= spec) or (Kind =:= callback) ->
NewSpecFun =
case SpecFun of
{atom, _, Fun} ->
@@ -596,7 +621,7 @@ build_type_spec({spec,La}, {SpecFun, TypeSpecs}) ->
%% Old style spec. Allow this for now.
{Mod,Fun,Arity}
end,
- {attribute,La,spec,{NewSpecFun, TypeSpecs}}.
+ {attribute,La,Kind,{NewSpecFun, TypeSpecs}}.
find_arity_from_specs([Spec|_]) ->
%% Use the first spec to find the arity. If all are not the same,
@@ -830,6 +855,7 @@ check_clauses(Cs, Name, Arity) ->
build_try(L,Es,Scs,{Ccs,As}) ->
{'try',L,Es,Scs,Ccs,As}.
+-spec ret_err(_, _) -> no_return().
ret_err(L, S) ->
{location,Location} = get_attribute(L, location),
return_error(Location, S).
@@ -846,10 +872,11 @@ mapl(F, [H|T]) ->
mapl(_, []) ->
[].
-%% normalise(AbsTerm)
-%% abstract(Term)
%% Convert between the abstract form of a term and a term.
+-spec normalise(AbsTerm) -> Data when
+ AbsTerm :: abstract_expr(),
+ Data :: term().
normalise({char,_,C}) -> C;
normalise({integer,_,I}) -> I;
normalise({float,_,F}) -> F;
@@ -887,6 +914,9 @@ normalise_list([H|T]) ->
normalise_list([]) ->
[].
+-spec abstract(Data) -> AbsTerm when
+ Data :: term(),
+ AbsTerm :: abstract_expr().
abstract(T) when is_integer(T) -> {integer,0,T};
abstract(T) when is_float(T) -> {float,0,T};
abstract(T) when is_atom(T) -> {atom,0,T};
@@ -955,13 +985,18 @@ abstract_list([H|T], Line) ->
abstract_list([], _Line) ->
[].
-%% tokens(AbsTerm) -> [Token]
-%% tokens(AbsTerm, More) -> [Token]
%% Generate a list of tokens representing the abstract term.
+-spec tokens(AbsTerm) -> Tokens when
+ AbsTerm :: abstract_expr(),
+ Tokens :: [token()].
tokens(Abs) ->
tokens(Abs, []).
+-spec tokens(AbsTerm, MoreTokens) -> Tokens when
+ AbsTerm :: abstract_expr(),
+ MoreTokens :: [token()],
+ Tokens :: [token()].
tokens({char,L,C}, More) -> [{char,L,C}|More];
tokens({integer,L,N}, More) -> [{integer,L,N}|More];
tokens({float,L,F}, More) -> [{float,L,F}|More];
diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl
index 66c80a45cb..7dc19f2e9b 100644
--- a/lib/stdlib/src/erl_pp.erl
+++ b/lib/stdlib/src/erl_pp.erl
@@ -31,25 +31,53 @@
-define(MAXLINE, 72).
+-type(hook_function() :: none
+ | fun((Expr :: erl_parse:abstract_expr(),
+ CurrentIndentation :: integer(),
+ CurrentPrecedence :: non_neg_integer(),
+ HookFunction :: hook_function()) ->
+ io_lib:chars())).
+
%%%
%%% Exported functions
%%%
+-spec(form(Form) -> io_lib:chars() when
+ Form :: erl_parse:abstract_form()).
+
form(Thing) ->
form(Thing, none).
+-spec(form(Form, HookFunction) -> io_lib:chars() when
+ Form :: erl_parse:abstract_form(),
+ HookFunction :: hook_function()).
+
form(Thing, Hook) ->
frmt(lform(Thing, Hook)).
+-spec(attribute(Attribute) -> io_lib:chars() when
+ Attribute :: erl_parse:abstract_form()).
+
attribute(Thing) ->
attribute(Thing, none).
+-spec(attribute(Attribute, HookFunction) -> io_lib:chars() when
+ Attribute :: erl_parse:abstract_form(),
+ HookFunction :: hook_function()).
+
attribute(Thing, Hook) ->
frmt(lattribute(Thing, Hook)).
+-spec(function(Function) -> io_lib:chars() when
+ Function :: erl_parse:abstract_form()).
+
function(F) ->
function(F, none).
+-spec(function(Function, HookFunction) -> io_lib:chars() when
+ Function :: erl_parse:abstract_form(),
+ HookFunction :: hook_function()).
+
function(F, Hook) ->
frmt(lfunction(F, Hook)).
@@ -59,30 +87,67 @@ rule(R) ->
rule(R, Hook) ->
frmt(lrule(R, Hook)).
+-spec(guard(Guard) -> io_lib:chars() when
+ Guard :: [erl_parse:abstract_expr()]).
+
guard(Gs) ->
guard(Gs, none).
+-spec(guard(Guard, HookFunction) -> io_lib:chars() when
+ Guard :: [erl_parse:abstract_expr()],
+ HookFunction :: hook_function()).
+
guard(Gs, Hook) ->
frmt(lguard(Gs, Hook)).
+-spec(exprs(Expressions) -> io_lib:chars() when
+ Expressions :: [erl_parse:abstract_expr()]).
+
exprs(Es) ->
exprs(Es, 0, none).
+-spec(exprs(Expressions, HookFunction) -> io_lib:chars() when
+ Expressions :: [erl_parse:abstract_expr()],
+ HookFunction :: hook_function()).
+
exprs(Es, Hook) ->
exprs(Es, 0, Hook).
+-spec(exprs(Expressions, Indent, HookFunction) -> io_lib:chars() when
+ Expressions :: [erl_parse:abstract_expr()],
+ Indent :: integer(),
+ HookFunction :: hook_function()).
+
exprs(Es, I, Hook) ->
frmt({seq,[],[],[$,],lexprs(Es, Hook)}, I).
+-spec(expr(Expression) -> io_lib:chars() when
+ Expression :: erl_parse:abstract_expr()).
+
expr(E) ->
frmt(lexpr(E, 0, none)).
+-spec(expr(Expression, HookFunction) -> io_lib:chars() when
+ Expression :: erl_parse:abstract_expr(),
+ HookFunction :: hook_function()).
+
expr(E, Hook) ->
frmt(lexpr(E, 0, Hook)).
+-spec(expr(Expression, Indent, HookFunction) -> io_lib:chars() when
+ Expression :: erl_parse:abstract_expr(),
+ Indent :: integer(),
+ HookFunction :: hook_function()).
+
expr(E, I, Hook) ->
frmt(lexpr(E, 0, Hook), I).
+-spec(expr(Expression, Indent, Precedence, HookFunction) -> io_lib:chars() when
+ Expression :: erl_parse:abstract_expr(),
+ Indent :: integer(),
+ Precedence :: non_neg_integer(),
+ HookFunction :: hook_function()).
+
expr(E, I, P, Hook) ->
frmt(lexpr(E, P, Hook), I).
diff --git a/lib/stdlib/src/erl_scan.erl b/lib/stdlib/src/erl_scan.erl
index 18f64c46d0..10b2ed2e49 100644
--- a/lib/stdlib/src/erl_scan.erl
+++ b/lib/stdlib/src/erl_scan.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -99,7 +99,8 @@
%%----------------------------------------------------------------------------
--spec format_error(Error :: term()) -> string().
+-spec format_error(ErrorDescriptor) -> string() when
+ ErrorDescriptor :: error_description().
format_error({string,Quote,Head}) ->
lists:flatten(["unterminated " ++ string_thing(Quote) ++
" starting with " ++
@@ -112,20 +113,33 @@ format_error({base,Base}) ->
format_error(Other) ->
lists:flatten(io_lib:write(Other)).
--type string_return() :: {'ok', tokens(), location()}
- | {'error', error_info(), location()}.
-
--spec string(String :: string()) -> string_return().
+-spec string(String) -> Return when
+ String :: string(),
+ Return :: {'ok', Tokens :: tokens(), EndLocation}
+ | {'error', ErrorInfo :: error_info(), ErrorLocation},
+ EndLocation :: location(),
+ ErrorLocation :: location().
string(String) ->
string(String, 1, []).
--spec string(String :: string(), StartLocation :: location()) ->
- string_return().
+-spec string(String, StartLocation) -> Return when
+ String :: string(),
+ Return :: {'ok', Tokens :: tokens(), EndLocation}
+ | {'error', ErrorInfo :: error_info(), ErrorLocation},
+ StartLocation :: location(),
+ EndLocation :: location(),
+ ErrorLocation :: location().
string(String, StartLocation) ->
string(String, StartLocation, []).
--spec string(String :: string(), StartLocation :: location(),
- Options :: options()) -> string_return().
+-spec string(String, StartLocation, Options) -> Return when
+ String :: string(),
+ Options :: options(),
+ Return :: {'ok', Tokens :: tokens(), EndLocation}
+ | {'error', ErrorInfo :: error_info(), ErrorLocation},
+ StartLocation :: location(),
+ EndLocation :: location(),
+ ErrorLocation :: location().
string(String, Line, Options) when ?STRING(String), ?ALINE(Line) ->
string1(String, options(Options), Line, no_col, []);
string(String, {Line,Column}, Options) when ?STRING(String),
@@ -136,29 +150,37 @@ string(String, {Line,Column}, Options) when ?STRING(String),
-type char_spec() :: string() | 'eof'.
-type cont_fun() :: fun((char_spec(), #erl_scan{}, line(), column(),
tokens(), any()) -> any()).
--opaque return_cont() :: {string(), column(), tokens(), line(),
- #erl_scan{}, cont_fun(), any()}.
--type cont() :: return_cont() | [].
--type tokens_result() :: {'ok', tokens(), location()}
- | {'eof', location()}
- | {'error', error_info(), location()}.
--type tokens_return() :: {'done', tokens_result(), char_spec()}
- | {'more', return_cont()}.
-
--spec tokens(Cont :: cont(), CharSpec :: char_spec(),
- StartLocation :: location()) -> tokens_return().
+-opaque return_cont() :: {erl_scan_continuation,
+ string(), column(), tokens(), line(),
+ #erl_scan{}, any(), cont_fun()}.
+-type tokens_result() :: {'ok', Tokens :: tokens(), EndLocation :: location()}
+ | {'eof', EndLocation :: location()}
+ | {'error', ErrorInfo :: error_info(),
+ EndLocation :: location()}.
+
+-spec tokens(Continuation, CharSpec, StartLocation) -> Return when
+ Continuation :: return_cont() | [],
+ CharSpec :: char_spec(),
+ StartLocation :: location(),
+ Return :: {'done',Result :: tokens_result(),LeftOverChars :: char_spec()}
+ | {'more', Continuation1 :: return_cont()}.
tokens(Cont, CharSpec, StartLocation) ->
tokens(Cont, CharSpec, StartLocation, []).
--spec tokens(Cont :: cont(), CharSpec :: char_spec(),
- StartLocation :: location(), Options :: options()) ->
- tokens_return().
+-spec tokens(Continuation, CharSpec, StartLocation, Options) -> Return when
+ Continuation :: return_cont() | [],
+ CharSpec :: char_spec(),
+ StartLocation :: location(),
+ Options :: options(),
+ Return :: {'done',Result :: tokens_result(),LeftOverChars :: char_spec()}
+ | {'more', Continuation1 :: return_cont()}.
tokens([], CharSpec, Line, Options) when ?ALINE(Line) ->
tokens1(CharSpec, options(Options), Line, no_col, [], fun scan/6, []);
tokens([], CharSpec, {Line,Column}, Options) when ?ALINE(Line),
?COLUMN(Column) ->
tokens1(CharSpec, options(Options), Line, Column, [], fun scan/6, []);
-tokens({Cs,Col,Toks,Line,St,Any,Fun}, CharSpec, _Loc, _Opts) ->
+tokens({erl_scan_continuation,Cs,Col,Toks,Line,St,Any,Fun},
+ CharSpec, _Loc, _Opts) ->
tokens1(Cs++CharSpec, St, Line, Col, Toks, Fun, Any).
-type attribute_item() :: 'column' | 'length' | 'line'
@@ -172,13 +194,22 @@ tokens({Cs,Col,Toks,Line,St,Any,Fun}, CharSpec, _Loc, _Opts) ->
-type token_info() :: {'category', category()} | {'symbol', symbol()}
| attribute_info().
--spec token_info(token()) -> [token_info()].
+-spec token_info(Token) -> TokenInfo when
+ Token :: token(),
+ TokenInfo :: [TokenInfoTuple :: token_info()].
token_info(Token) ->
Items = [category,column,length,line,symbol,text], % undefined order
token_info(Token, Items).
--spec token_info(token(), token_item()) -> token_info() | 'undefined';
- (token(), [token_item()]) -> [token_info()].
+-spec token_info(Token, TokenItem) -> TokenInfo | 'undefined' when
+ Token :: token(),
+ TokenItem :: token_item(),
+ TokenInfo :: TokenInfoTuple :: token_info();
+ (Token, TokenItems) -> [TokenInfo] when
+ Token :: token(),
+ TokenItems :: [TokenItem],
+ TokenItem :: token_item(),
+ TokenInfo :: [TokenInfoTuple :: token_info()].
token_info(_Token, []) ->
[];
token_info(Token, [Item|Items]) when is_atom(Item) ->
@@ -201,14 +232,23 @@ token_info({_Category,Attrs}, Item) ->
token_info({_Category,Attrs,_Symbol}, Item) ->
attributes_info(Attrs, Item).
--spec attributes_info(attributes()) -> [attribute_info()].
+-spec attributes_info(Attributes) -> AttributesInfo when
+ Attributes :: attributes(),
+ AttributesInfo :: [AttributeInfoTuple :: attribute_info()].
attributes_info(Attributes) ->
Items = [column,length,line,text], % undefined order
attributes_info(Attributes, Items).
--spec attributes_info(attributes(), attribute_item()) ->
- attribute_info() | 'undefined';
- (attributes(), [attribute_item()]) -> [attribute_info()].
+-spec attributes_info(Attributes, AttributeItem) ->
+ AttributeInfo | 'undefined' when
+ Attributes :: attributes(),
+ AttributeItem :: attribute_item(),
+ AttributeInfo :: AttributeInfoTuple :: attribute_info();
+ (Attributes, AttributeItems) -> [AttributeInfo] when
+ Attributes :: attributes(),
+ AttributeItems :: [AttributeItem],
+ AttributeItem :: attribute_item(),
+ AttributeInfo :: [AttributeInfoTuple :: attribute_info()].
attributes_info(_Attrs, []) ->
[];
attributes_info(Attrs, [A|As]) when is_atom(A) ->
@@ -265,9 +305,10 @@ attributes_info(Attrs, text=Item) ->
attributes_info(T1, T2) ->
erlang:error(badarg, [T1,T2]).
--type setlineattr_fun() :: fun((info_line()) -> info_line()).
-
--spec set_attribute('line', attributes(), setlineattr_fun()) -> attributes().
+-spec set_attribute(AttributeItem, Attributes, SetAttributeFun) -> Attributes when
+ AttributeItem :: 'line',
+ Attributes :: attributes(),
+ SetAttributeFun :: fun((info_line()) -> info_line()).
set_attribute(Tag, Attributes, Fun) when ?SETATTRFUN(Fun) ->
set_attr(Tag, Attributes, Fun).
@@ -367,14 +408,19 @@ set_attr(line, {Line,Column}, Fun) when ?ALINE(Line), ?COLUMN(Column) ->
end;
set_attr(line=Tag, Attrs, Fun) when is_list(Attrs) ->
{line,Line} = lists:keyfind(Tag, 1, Attrs),
- lists:keyreplace(Tag, 1, Attrs, {line,Fun(Line)});
+ case lists:keyreplace(Tag, 1, Attrs, {line,Fun(Line)}) of
+ [{line,Ln}] when ?ALINE(Ln) ->
+ Ln;
+ As ->
+ As
+ end;
set_attr(T1, T2, T3) ->
erlang:error(badarg, [T1,T2,T3]).
tokens1(Cs, St, Line, Col, Toks, Fun, Any) when ?STRING(Cs); Cs =:= eof ->
case Fun(Cs, St, Line, Col, Toks, Any) of
{more,{Cs0,Ncol,Ntoks,Nline,Nany,Nfun}} ->
- {more,{Cs0,Ncol,Ntoks,Nline,St,Nany,Nfun}};
+ {more,{erl_scan_continuation,Cs0,Ncol,Ntoks,Nline,St,Nany,Nfun}};
{ok,Toks0,eof,Nline,Ncol} ->
Res = case Toks0 of
[] ->
@@ -1285,7 +1331,7 @@ tabs(8) -> "\t\t\t\t\t\t\t\t";
tabs(9) -> "\t\t\t\t\t\t\t\t\t";
tabs(10) -> "\t\t\t\t\t\t\t\t\t\t".
--spec reserved_word(atom()) -> boolean().
+-spec reserved_word(Atom :: atom()) -> boolean().
reserved_word('after') -> true;
reserved_word('begin') -> true;
reserved_word('case') -> true;
diff --git a/lib/stdlib/src/erl_tar.erl b/lib/stdlib/src/erl_tar.erl
index fd85c7aef5..306834e845 100644
--- a/lib/stdlib/src/erl_tar.erl
+++ b/lib/stdlib/src/erl_tar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -798,30 +798,10 @@ set_extracted_file_info(Name, #tar_header{mode=Mode, mtime=Mtime}) ->
%% Makes all directories leading up to the file.
-make_dirs(Name, Type) ->
- make_dirs1(filename:split(Name), Type).
-
-make_dirs1([Dir, Next|Rest], Type) ->
- case file:read_file_info(Dir) of
- {ok, #file_info{type=directory}} ->
- make_dirs1([filename:join(Dir, Next)|Rest], Type);
- {ok, #file_info{}} ->
- throw({error, enotdir});
- {error, _} ->
- case file:make_dir(Dir) of
- ok ->
- make_dirs1([filename:join(Dir, Next)|Rest], Type);
- {error, Reason} ->
- throw({error, Reason})
- end
- end;
-make_dirs1([_], file) -> ok;
-make_dirs1([Dir], dir) ->
- file:make_dir(Dir);
-make_dirs1([], _) ->
- %% There must be something wrong here. The list was not supposed
- %% to be empty.
- throw({error, enoent}).
+make_dirs(Name, file) ->
+ filelib:ensure_dir(Name);
+make_dirs(Name, dir) ->
+ filelib:ensure_dir(filename:join(Name,"*")).
%% Prints the message on if the verbose option is given (for reading).
diff --git a/lib/stdlib/src/error_logger_tty_h.erl b/lib/stdlib/src/error_logger_tty_h.erl
index 435e57aa0e..fa13fbb2bd 100644
--- a/lib/stdlib/src/error_logger_tty_h.erl
+++ b/lib/stdlib/src/error_logger_tty_h.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,10 +34,12 @@
handle_event/2, handle_call/2, handle_info/2,
terminate/2, code_change/3]).
+-export([write_event/2]).
+
%% This one is used when we takeover from the simple error_logger.
init({[], {error_logger, Buf}}) ->
User = set_group_leader(),
- write_events(Buf),
+ write_events(Buf,io),
{ok, {User, error_logger}};
%% This one is used if someone took over from us, and now wants to
%% go back.
@@ -52,7 +54,7 @@ init([]) ->
handle_event({_Type, GL, _Msg}, State) when node(GL) =/= node() ->
{ok, State};
handle_event(Event, State) ->
- write_event(tag_event(Event)),
+ write_event(tag_event(Event),io),
{ok, State}.
handle_info({'EXIT', User, _Reason}, {User, PrevHandler}) ->
@@ -64,10 +66,10 @@ handle_info({'EXIT', User, _Reason}, {User, PrevHandler}) ->
PrevHandler, go_back}
end;
handle_info({emulator, GL, Chars}, State) when node(GL) == node() ->
- write_event(tag_event({emulator, GL, Chars})),
+ write_event(tag_event({emulator, GL, Chars}),io),
{ok, State};
handle_info({emulator, noproc, Chars}, State) ->
- write_event(tag_event({emulator, noproc, Chars})),
+ write_event(tag_event({emulator, noproc, Chars}),io),
{ok, State};
handle_info(_, State) ->
{ok, State}.
@@ -97,65 +99,65 @@ set_group_leader() ->
tag_event(Event) ->
{erlang:localtime(), Event}.
-write_events(Events) -> write_events1(lists:reverse(Events)).
+write_events(Events,IOMod) -> write_events1(lists:reverse(Events),IOMod).
-write_events1([Event|Es]) ->
- write_event(Event),
- write_events1(Es);
-write_events1([]) ->
+write_events1([Event|Es],IOMod) ->
+ write_event(Event,IOMod),
+ write_events1(Es,IOMod);
+write_events1([],_IOMod) ->
ok.
-write_event({Time, {error, _GL, {Pid, Format, Args}}}) ->
+write_event({Time, {error, _GL, {Pid, Format, Args}}},IOMod) ->
T = write_time(maybe_utc(Time)),
case catch io_lib:format(add_node(Format,Pid), Args) of
S when is_list(S) ->
- format(T ++ S);
+ format(IOMod, T ++ S);
_ ->
F = add_node("ERROR: ~p - ~p~n", Pid),
- format(T ++ F, [Format,Args])
+ format(IOMod, T ++ F, [Format,Args])
end;
-write_event({Time, {emulator, _GL, Chars}}) ->
+write_event({Time, {emulator, _GL, Chars}},IOMod) ->
T = write_time(maybe_utc(Time)),
case catch io_lib:format(Chars, []) of
S when is_list(S) ->
- format(T ++ S);
+ format(IOMod, T ++ S);
_ ->
- format(T ++ "ERROR: ~p ~n", [Chars])
+ format(IOMod, T ++ "ERROR: ~p ~n", [Chars])
end;
-write_event({Time, {info, _GL, {Pid, Info, _}}}) ->
+write_event({Time, {info, _GL, {Pid, Info, _}}},IOMod) ->
T = write_time(maybe_utc(Time)),
- format(T ++ add_node("~p~n",Pid),[Info]);
-write_event({Time, {error_report, _GL, {Pid, std_error, Rep}}}) ->
+ format(IOMod, T ++ add_node("~p~n",Pid),[Info]);
+write_event({Time, {error_report, _GL, {Pid, std_error, Rep}}},IOMod) ->
T = write_time(maybe_utc(Time)),
S = format_report(Rep),
- format(T ++ S ++ add_node("", Pid));
-write_event({Time, {info_report, _GL, {Pid, std_info, Rep}}}) ->
+ format(IOMod, T ++ S ++ add_node("", Pid));
+write_event({Time, {info_report, _GL, {Pid, std_info, Rep}}},IOMod) ->
T = write_time(maybe_utc(Time), "INFO REPORT"),
S = format_report(Rep),
- format(T ++ S ++ add_node("", Pid));
-write_event({Time, {info_msg, _GL, {Pid, Format, Args}}}) ->
+ format(IOMod, T ++ S ++ add_node("", Pid));
+write_event({Time, {info_msg, _GL, {Pid, Format, Args}}},IOMod) ->
T = write_time(maybe_utc(Time), "INFO REPORT"),
case catch io_lib:format(add_node(Format,Pid), Args) of
S when is_list(S) ->
- format(T ++ S);
+ format(IOMod, T ++ S);
_ ->
F = add_node("ERROR: ~p - ~p~n", Pid),
- format(T ++ F, [Format,Args])
+ format(IOMod, T ++ F, [Format,Args])
end;
-write_event({Time, {warning_report, _GL, {Pid, std_warning, Rep}}}) ->
+write_event({Time, {warning_report, _GL, {Pid, std_warning, Rep}}},IOMod) ->
T = write_time(maybe_utc(Time), "WARNING REPORT"),
S = format_report(Rep),
- format(T ++ S ++ add_node("", Pid));
-write_event({Time, {warning_msg, _GL, {Pid, Format, Args}}}) ->
+ format(IOMod, T ++ S ++ add_node("", Pid));
+write_event({Time, {warning_msg, _GL, {Pid, Format, Args}}},IOMod) ->
T = write_time(maybe_utc(Time), "WARNING REPORT"),
case catch io_lib:format(add_node(Format,Pid), Args) of
S when is_list(S) ->
- format(T ++ S);
+ format(IOMod, T ++ S);
_ ->
F = add_node("ERROR: ~p - ~p~n", Pid),
- format(T ++ F, [Format,Args])
+ format(IOMod, T ++ F, [Format,Args])
end;
-write_event({_Time, _Error}) ->
+write_event({_Time, _Error},_IOMod) ->
ok.
maybe_utc(Time) ->
@@ -178,8 +180,9 @@ maybe_utc(Time) ->
Time
end.
-format(String) -> io:format(user, String, []).
-format(String, Args) -> io:format(user, String, Args).
+format(IOMod, String) -> format(IOMod, String, []).
+format(io_lib, String, Args) -> io_lib:format(String, Args);
+format(io, String, Args) -> io:format(user, String, Args).
format_report(Rep) when is_list(Rep) ->
case string_p(Rep) of
diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl
index d67617260e..ad49d89908 100644
--- a/lib/stdlib/src/escript.erl
+++ b/lib/stdlib/src/escript.erl
@@ -62,10 +62,10 @@
-type zip_create_option() :: term().
-type section() ::
shebang
- | {shebang, shebang()}
+ | {shebang, shebang() | default | undefined}
| comment
- | {comment, comment()}
- | {emu_args, emu_args()}
+ | {comment, comment() | default | undefined}
+ | {emu_args, emu_args() | undefined}
| {source, file:filename() | binary()}
| {beam, file:filename() | binary()}
| {archive, file:filename() | binary()}
@@ -866,7 +866,7 @@ hidden_apply(App, M, F, Args) ->
catch
error:undef ->
case erlang:get_stacktrace() of
- [{M,F,Args} | _] ->
+ [{M,F,Args,_} | _] ->
Arity = length(Args),
Text = io_lib:format("Call to ~w:~w/~w in application ~w failed.\n",
[M, F, Arity, App]),
diff --git a/lib/stdlib/src/ets.erl b/lib/stdlib/src/ets.erl
index 6e6e949e2c..afa914a456 100644
--- a/lib/stdlib/src/ets.erl
+++ b/lib/stdlib/src/ets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,7 @@
-export([i/0, i/1, i/2, i/3]).
--export_type([tab/0, tid/0]).
+-export_type([tab/0, tid/0, match_spec/0]).
%%-----------------------------------------------------------------------------
@@ -51,22 +51,9 @@
%% a similar definition is also in erl_types
-opaque tid() :: integer().
--type ext_info() :: 'md5sum' | 'object_count'.
--type protection() :: 'private' | 'protected' | 'public'.
--type type() :: 'bag' | 'duplicate_bag' | 'ordered_set' | 'set'.
-
--type table_info() :: {'name', atom()}
- | {'type', type()}
- | {'protection', protection()}
- | {'named_table', boolean()}
- | {'keypos', non_neg_integer()}
- | {'size', non_neg_integer()}
- | {'extended_info', [ext_info()]}
- | {'version', {non_neg_integer(), non_neg_integer()}}.
-
%% these ones are also defined in erl_bif_types
-type match_pattern() :: atom() | tuple().
--type match_specs() :: [{match_pattern(), [_], [_]}].
+-type match_spec() :: [{match_pattern(), [_], [_]}].
%%-----------------------------------------------------------------------------
@@ -86,6 +73,7 @@
%% insert/2
%% is_compiled_ms/1
%% last/1
+%% member/2
%% next/2
%% prev/2
%% rename/2
@@ -101,11 +89,14 @@
%% select/1
%% select/2
%% select/3
+%% select_count/2
%% select_reverse/1
%% select_reverse/2
%% select_reverse/3
%% select_delete/2
+%% setopts/2
%% update_counter/3
+%% update_element/3
%%
-opaque comp_match_spec() :: any(). %% this one is REALLY opaque
@@ -119,7 +110,9 @@ match_spec_run(List, CompiledMS) ->
| {tab(),integer(),integer(),binary(),list(),integer()}
| {tab(),_,_,integer(),binary(),list(),integer(),integer()}.
--spec repair_continuation(continuation(), match_specs()) -> continuation().
+-spec repair_continuation(Continuation, MatchSpec) -> Continuation when
+ Continuation :: continuation(),
+ MatchSpec :: match_spec().
%% $end_of_table is an allowed continuation in ets...
repair_continuation('$end_of_table', _) ->
@@ -153,7 +146,9 @@ repair_continuation(Untouched = {Table,N1,N2,Bin,L,N3}, MS)
{Table,N1,N2,ets:match_spec_compile(MS),L,N3}
end.
--spec fun2ms(function()) -> match_specs().
+-spec fun2ms(LiteralFun) -> MatchSpec when
+ LiteralFun :: function(),
+ MatchSpec :: match_spec().
fun2ms(ShellFun) when is_function(ShellFun) ->
%% Check that this is really a shell fun...
@@ -177,7 +172,13 @@ fun2ms(ShellFun) when is_function(ShellFun) ->
shell]}})
end.
--spec foldl(fun((_, term()) -> term()), term(), tab()) -> term().
+-spec foldl(Function, Acc0, Tab) -> Acc1 when
+ Function :: fun((Element :: term(), AccIn) -> AccOut),
+ Tab :: tab(),
+ Acc0 :: term(),
+ Acc1 :: term(),
+ AccIn :: term(),
+ AccOut :: term().
foldl(F, Accu, T) ->
ets:safe_fixtable(T, true),
@@ -198,7 +199,13 @@ do_foldl(F, Accu0, Key, T) ->
ets:next(T, Key), T)
end.
--spec foldr(fun((_, term()) -> term()), term(), tab()) -> term().
+-spec foldr(Function, Acc0, Tab) -> Acc1 when
+ Function :: fun((Element :: term(), AccIn) -> AccOut),
+ Tab :: tab(),
+ Acc0 :: term(),
+ Acc1 :: term(),
+ AccIn :: term(),
+ AccOut :: term().
foldr(F, Accu, T) ->
ets:safe_fixtable(T, true),
@@ -219,7 +226,9 @@ do_foldr(F, Accu0, Key, T) ->
ets:prev(T, Key), T)
end.
--spec from_dets(tab(), dets:tab_name()) -> 'true'.
+-spec from_dets(Tab, DetsTab) -> 'true' when
+ Tab :: tab(),
+ DetsTab :: dets:tab_name().
from_dets(EtsTable, DetsTable) ->
case (catch dets:to_ets(DetsTable, EtsTable)) of
@@ -235,7 +244,9 @@ from_dets(EtsTable, DetsTable) ->
erlang:error(Unexpected,[EtsTable,DetsTable])
end.
--spec to_dets(tab(), dets:tab_name()) -> dets:tab_name().
+-spec to_dets(Tab, DetsTab) -> DetsTab when
+ Tab :: tab(),
+ DetsTab :: dets:tab_name().
to_dets(EtsTable, DetsTable) ->
case (catch dets:from_ets(DetsTable, EtsTable)) of
@@ -251,8 +262,11 @@ to_dets(EtsTable, DetsTable) ->
erlang:error(Unexpected,[EtsTable,DetsTable])
end.
--spec test_ms(tuple(), match_specs()) ->
- {'ok', term()} | {'error', [{'warning'|'error', string()}]}.
+-spec test_ms(Tuple, MatchSpec) -> {'ok', Result} | {'error', Errors} when
+ Tuple :: tuple(),
+ MatchSpec :: match_spec(),
+ Result :: term(),
+ Errors :: [{'warning'|'error', string()}].
test_ms(Term, MS) ->
case erlang:match_spec_test(Term, MS, table) of
@@ -262,7 +276,11 @@ test_ms(Term, MS) ->
Error
end.
--spec init_table(tab(), fun(('read' | 'close') -> term())) -> 'true'.
+-spec init_table(Tab, InitFun) -> 'true' when
+ Tab :: tab(),
+ InitFun :: fun((Arg) -> Res),
+ Arg :: 'read' | 'close',
+ Res :: 'end_of_input' | {Objects :: [term()], InitFun} | term().
init_table(Table, Fun) ->
ets:delete_all_objects(Table),
@@ -287,7 +305,9 @@ init_table_sub(Table, [H|T]) ->
ets:insert(Table, H),
init_table_sub(Table, T).
--spec match_delete(tab(), match_pattern()) -> 'true'.
+-spec match_delete(Tab, Pattern) -> 'true' when
+ Tab :: tab(),
+ Pattern :: match_pattern().
match_delete(Table, Pattern) ->
ets:select_delete(Table, [{Pattern,[],[true]}]),
@@ -295,7 +315,9 @@ match_delete(Table, Pattern) ->
%% Produce a list of tuples from a table
--spec tab2list(tab()) -> [tuple()].
+-spec tab2list(Tab) -> [Object] when
+ Tab :: tab(),
+ Object :: tuple().
tab2list(T) ->
ets:match_object(T, '_').
@@ -334,15 +356,21 @@ do_filter(Tab, Key, F, A, Ack) ->
md5sum = false :: boolean()
}).
--type fname() :: string() | atom().
--type t2f_option() :: {'extended_info', [ext_info()]}.
-
--spec tab2file(tab(), fname()) -> 'ok' | {'error', term()}.
+-spec tab2file(Tab, Filename) -> 'ok' | {'error', Reason} when
+ Tab :: tab(),
+ Filename :: file:name(),
+ Reason :: term().
tab2file(Tab, File) ->
tab2file(Tab, File, []).
--spec tab2file(tab(), fname(), [t2f_option()]) -> 'ok' | {'error', term()}.
+-spec tab2file(Tab, Filename, Options) -> 'ok' | {'error', Reason} when
+ Tab :: tab(),
+ Filename :: file:name(),
+ Options :: [Option],
+ Option :: {'extended_info', [ExtInfo]},
+ ExtInfo :: 'md5sum' | 'object_count',
+ Reason :: term().
tab2file(Tab, File, Options) ->
try
@@ -501,14 +529,20 @@ parse_ft_info_options(_,Malformed) ->
%% Opt := {verify,boolean()}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--type f2t_option() :: {'verify', boolean()}.
-
--spec file2tab(fname()) -> {'ok', tab()} | {'error', term()}.
+-spec file2tab(Filename) -> {'ok', Tab} | {'error', Reason} when
+ Filename :: file:name(),
+ Tab :: tab(),
+ Reason :: term().
file2tab(File) ->
file2tab(File, []).
--spec file2tab(fname(), [f2t_option()]) -> {'ok', tab()} | {'error', term()}.
+-spec file2tab(Filename, Options) -> {'ok', Tab} | {'error', Reason} when
+ Filename :: file:name(),
+ Tab :: tab(),
+ Options :: [Option],
+ Option :: {'verify', boolean()},
+ Reason :: term().
file2tab(File, Opts) ->
try
@@ -895,7 +929,22 @@ named_table(false) -> [].
%% information
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec tabfile_info(fname()) -> {'ok', [table_info()]} | {'error', term()}.
+-spec tabfile_info(Filename) -> {'ok', TableInfo} | {'error', Reason} when
+ Filename :: file:name(),
+ TableInfo :: [InfoItem],
+ InfoItem :: {'name', atom()}
+ | {'type', Type}
+ | {'protection', Protection}
+ | {'named_table', boolean()}
+ | {'keypos', non_neg_integer()}
+ | {'size', non_neg_integer()}
+ | {'extended_info', [ExtInfo]}
+ | {'version', {Major :: non_neg_integer(),
+ Minor :: non_neg_integer()}},
+ ExtInfo :: 'md5sum' | 'object_count',
+ Type :: 'bag' | 'duplicate_bag' | 'ordered_set' | 'set',
+ Protection :: 'private' | 'protected' | 'public',
+ Reason :: term().
tabfile_info(File) when is_list(File) ; is_atom(File) ->
try
@@ -932,20 +981,22 @@ tabfile_info(File) when is_list(File) ; is_atom(File) ->
{error,ExReason}
end.
--type qlc__query_handle() :: term(). %% XXX: belongs in 'qlc'
-
--type num_objects() :: 'default' | pos_integer().
--type trav_method() :: 'first_next' | 'last_prev'
- | 'select' | {'select', match_specs()}.
--type table_option() :: {'n_objects', num_objects()}
- | {'traverse', trav_method()}.
-
--spec table(tab()) -> qlc__query_handle().
+-spec table(Tab) -> QueryHandle when
+ Tab :: tab(),
+ QueryHandle :: qlc:query_handle().
table(Tab) ->
table(Tab, []).
--spec table(tab(), table_option() | [table_option()]) -> qlc__query_handle().
+-spec table(Tab, Options) -> QueryHandle when
+ Tab :: tab(),
+ QueryHandle :: qlc:query_handle(),
+ Options :: [Option] | Option,
+ Option :: {'n_objects', NObjects}
+ | {'traverse', TraverseMethod},
+ NObjects :: 'default' | pos_integer(),
+ TraverseMethod :: 'first_next' | 'last_prev'
+ | 'select' | {'select', MatchSpec :: match_spec()}.
table(Tab, Opts) ->
case options(Opts, [traverse, n_objects]) of
@@ -1135,7 +1186,8 @@ to_string(X) ->
lists:flatten(io_lib:format("~p", [X])).
%% view a specific table
--spec i(tab()) -> 'ok'.
+-spec i(Tab) -> 'ok' when
+ Tab :: tab().
i(Tab) ->
i(Tab, 40).
diff --git a/lib/stdlib/src/eval_bits.erl b/lib/stdlib/src/eval_bits.erl
index 2cbd6cdae7..f40904df1c 100644
--- a/lib/stdlib/src/eval_bits.erl
+++ b/lib/stdlib/src/eval_bits.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
%%
%% The 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,15 +31,16 @@
%% @type evalfun(). A closure which evaluates an expression given an
%% environment
%%
-%% @type matchfun(). A closure which performs a match given a value, a
-%% pattern and an environment
+%% @type matchfun(). A closure which depending on its first argument
+%% can perform a match (given a value, a pattern and an environment),
+%% lookup a variable in the bindings, or add a new binding
%%
-%% @type field() represents a field in a "bin"
+%% @type field(). Represents a field in a "bin".
%%% Part 1: expression evaluation (binary construction)
%% @spec expr_grp(Fields::[field()], Bindings::bindings(),
-%% EvalFun::evalfun()) ->
+%% EvalFun::evalfun(), term(), term()) ->
%% {value, binary(), bindings()}
%%
%% @doc Returns a tuple with {value,Bin,Bs} where Bin is the binary
@@ -144,7 +145,8 @@ eval_exp_field(Val, Size, Unit, binary, _, _) ->
bin_gen({bin,_,Fs}, Bin, Bs0, BBs0, Mfun, Efun) ->
bin_gen(Fs, Bin, Bs0, BBs0, Mfun, Efun, true).
-bin_gen([F|Fs], Bin, Bs0, BBs0, Mfun, Efun, Flag) ->
+bin_gen([F|Fs], Bin, Bs0, BBs0, Mfun, Efun, Flag)
+ when is_function(Mfun, 2), is_function(Efun, 2) ->
case bin_gen_field(F, Bin, Bs0, BBs0, Mfun, Efun) of
{match,Bs,BBs,Rest} ->
bin_gen(Fs, Rest, Bs, BBs, Mfun, Efun, Flag);
@@ -175,14 +177,14 @@ bin_gen_field({bin_element,Line,VE,Size0,Options0},
{Size1, [Type,{unit,Unit},Sign,Endian]} =
make_bit_type(Line, Size0, Options0),
V = erl_eval:partial_eval(VE),
- match_check_size(Size1, BBs0),
+ match_check_size(Mfun, Size1, BBs0),
{value, Size, _BBs} = Efun(Size1, BBs0),
case catch get_value(Bin, Type, Size, Unit, Sign, Endian) of
{Val,<<_/bitstring>>=Rest} ->
NewV = coerce_to_float(V, Type),
- case catch Mfun(NewV, Val, Bs0) of
+ case catch Mfun(match, {NewV,Val,Bs0}) of
{match,Bs} ->
- BBs = add_bin_binding(NewV, Bs, BBs0),
+ BBs = add_bin_binding(Mfun, NewV, Bs, BBs0),
{match,Bs,BBs,Rest};
_ ->
{nomatch,Rest}
@@ -192,9 +194,9 @@ bin_gen_field({bin_element,Line,VE,Size0,Options0},
end.
%%% Part 3: binary pattern matching
-%% @spec match_bits(Fields::[field()], Bin::binary()
+%% @spec match_bits(Fields::[field()], Bin::binary(),
%% GlobalEnv::bindings(), LocalEnv::bindings(),
-%% MatchFun::matchfun(),EvalFun::evalfun()) ->
+%% MatchFun::matchfun(),EvalFun::evalfun(), term()) ->
%% {match, bindings()}
%% @doc Used to perform matching. If the match succeeds a new
%% environment is returned. If the match have some syntactic or
@@ -205,7 +207,8 @@ bin_gen_field({bin_element,Line,VE,Size0,Options0},
match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun, _) ->
match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun).
-match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun) ->
+match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun)
+ when is_function(Mfun, 2), is_function(Efun, 2) ->
case catch match_bits_1(Fs, Bin, Bs0, BBs, Mfun, Efun) of
{match,Bs} -> {match,Bs};
invalid -> throw(invalid);
@@ -230,12 +233,12 @@ match_field_1({bin_element,Line,VE,Size0,Options0},
make_bit_type(Line, Size0, Options0),
V = erl_eval:partial_eval(VE),
Size2 = erl_eval:partial_eval(Size1),
- match_check_size(Size2, BBs0),
+ match_check_size(Mfun, Size2, BBs0),
{value, Size, _BBs} = Efun(Size2, BBs0),
{Val,Rest} = get_value(Bin, Type, Size, Unit, Sign, Endian),
NewV = coerce_to_float(V, Type),
- {match,Bs} = Mfun(NewV, Val, Bs0),
- BBs = add_bin_binding(NewV, Bs, BBs0),
+ {match,Bs} = Mfun(match, {NewV,Val,Bs0}),
+ BBs = add_bin_binding(Mfun, NewV, Bs, BBs0),
{Bs,BBs,Rest}.
%% Almost identical to the one in sys_pre_expand.
@@ -249,12 +252,12 @@ coerce_to_float({integer,L,I}=E, float) ->
coerce_to_float(E, _Type) ->
E.
-add_bin_binding({var,_,'_'}, _Bs, BBs) ->
+add_bin_binding(_, {var,_,'_'}, _Bs, BBs) ->
BBs;
-add_bin_binding({var,_,Name}, Bs, BBs) ->
- {value,Value} = erl_eval:binding(Name, Bs),
- erl_eval:add_binding(Name, Value, BBs);
-add_bin_binding(_, _Bs, BBs) ->
+add_bin_binding(Mfun, {var,_,Name}, Bs, BBs) ->
+ {value,Value} = Mfun(binding, {Name,Bs}),
+ Mfun(add_binding, {Name,Value,BBs});
+add_bin_binding(_, _, _Bs, BBs) ->
BBs.
get_value(Bin, integer, Size, Unit, Sign, Endian) ->
@@ -327,20 +330,20 @@ make_bit_type(_Line, Size, Type0) -> %Size evaluates to an integer or 'all'
{error,Reason} -> error(Reason)
end.
-match_check_size({var,_,V}, Bs) ->
- case erl_eval:binding(V, Bs) of
+match_check_size(Mfun, {var,_,V}, Bs) ->
+ case Mfun(binding, {V,Bs}) of
{value,_} -> ok;
unbound -> throw(invalid) % or, rather, error({unbound,V})
end;
-match_check_size({atom,_,all}, _Bs) ->
+match_check_size(_, {atom,_,all}, _Bs) ->
ok;
-match_check_size({atom,_,undefined}, _Bs) ->
+match_check_size(_, {atom,_,undefined}, _Bs) ->
ok;
-match_check_size({integer,_,_}, _Bs) ->
+match_check_size(_, {integer,_,_}, _Bs) ->
ok;
-match_check_size({value,_,_}, _Bs) ->
+match_check_size(_, {value,_,_}, _Bs) ->
ok; %From the debugger.
-match_check_size(_, _Bs) ->
+match_check_size(_, _, _Bs) ->
throw(invalid).
%% error(Reason) -> exception thrown
diff --git a/lib/stdlib/src/file_sorter.erl b/lib/stdlib/src/file_sorter.erl
index 2a5b08b581..3f31852afc 100644
--- a/lib/stdlib/src/file_sorter.erl
+++ b/lib/stdlib/src/file_sorter.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The 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,12 +50,68 @@
%%% Exported functions
%%%
+-export_type([reason/0]).
+
+-type(file_name() :: file:name()).
+-type(file_names() :: [file:name()]).
+-type(i_command() :: read | close).
+-type(i_reply() :: end_of_input | {end_of_input, value()}
+ | {[object()], infun()} | input_reply()).
+-type(infun() :: fun((i_command()) -> i_reply())).
+-type(input() :: file_names() | infun()).
+-type(input_reply() :: term()).
+-type(o_command() :: {value, value()} | [object()] | close).
+-type(o_reply() :: outfun() | output_reply()).
+-type(object() :: term() | binary()).
+-type(outfun() :: fun((o_command()) -> o_reply())).
+-type(output() :: file_name() | outfun()).
+-type(output_reply() :: term()).
+-type(value() :: term()).
+
+-type(options() :: [option()] | option()).
+-type(option() :: {compressed, boolean()}
+ | {header, header_length()}
+ | {format, format()}
+ | {no_files, no_files()}
+ | {order, order()}
+ | {size, size()}
+ | {tmpdir, tmp_directory()}
+ | {unique, boolean()}).
+-type(format() :: binary_term | term | binary | format_fun()).
+-type(format_fun() :: fun((binary()) -> term())).
+-type(header_length() :: pos_integer()).
+-type(key_pos() :: pos_integer() | [pos_integer()]).
+-type(no_files() :: pos_integer()). % > 1
+-type(order() :: ascending | descending | order_fun()).
+-type(order_fun() :: fun((term(), term()) -> boolean())).
+-type(size() :: non_neg_integer()).
+-type(tmp_directory() :: [] | file:name()).
+
+-type(reason() :: bad_object
+ | {bad_object, file_name()}
+ | {bad_term, file_name()}
+ | {file_error, file_name(),
+ file:posix() | badarg | system_limit}
+ | {premature_eof, file_name()}).
+
+-spec(sort(FileName) -> Reply when
+ FileName :: file_name(),
+ Reply :: ok | {error, reason()} | input_reply() | output_reply()).
sort(FileName) ->
sort([FileName], FileName).
+-spec(sort(Input, Output) -> Reply when
+ Input :: input(),
+ Output :: output(),
+ Reply :: ok | {error, reason()} | input_reply() | output_reply()).
sort(Input, Output) ->
sort(Input, Output, []).
+-spec(sort(Input, Output, Options) -> Reply when
+ Input :: input(),
+ Output :: output(),
+ Options :: options(),
+ Reply :: ok | {error, reason()} | input_reply() | output_reply()).
sort(Input0, Output0, Options) ->
case {is_input(Input0), maybe_output(Output0), options(Options)} of
{{true,Input}, {true,Output}, #opts{}=Opts} ->
@@ -64,12 +120,27 @@ sort(Input0, Output0, Options) ->
badarg(culprit(tuple_to_list(T)), [Input0, Output0, Options])
end.
+-spec(keysort(KeyPos, FileName) -> Reply when
+ KeyPos :: key_pos(),
+ FileName :: file_name(),
+ Reply :: ok | {error, reason()} | input_reply() | output_reply()).
keysort(KeyPos, FileName) ->
keysort(KeyPos, [FileName], FileName).
+-spec(keysort(KeyPos, Input, Output) -> Reply when
+ KeyPos :: key_pos(),
+ Input :: input(),
+ Output :: output(),
+ Reply :: ok | {error, reason()} | input_reply() | output_reply()).
keysort(KeyPos, Input, Output) ->
keysort(KeyPos, Input, Output, []).
+-spec(keysort(KeyPos, Input, Output, Options) -> Reply when
+ KeyPos :: key_pos(),
+ Input :: input(),
+ Output :: output(),
+ Options :: options(),
+ Reply :: ok | {error, reason()} | input_reply() | output_reply()).
keysort(KeyPos, Input0, Output0, Options) ->
R = case {is_keypos(KeyPos), is_input(Input0),
maybe_output(Output0), options(Options)} of
@@ -89,9 +160,18 @@ keysort(KeyPos, Input0, Output0, Options) ->
badarg(culprit(O), [KeyPos, Input0, Output0, Options])
end.
+-spec(merge(FileNames, Output) -> Reply when
+ FileNames :: file_names(),
+ Output :: output(),
+ Reply :: ok | {error, reason()} | output_reply()).
merge(Files, Output) ->
merge(Files, Output, []).
+-spec(merge(FileNames, Output, Options) -> Reply when
+ FileNames :: file_names(),
+ Output :: output(),
+ Options :: options(),
+ Reply :: ok | {error, reason()} | output_reply()).
merge(Files0, Output0, Options) ->
case {is_files(Files0), maybe_output(Output0), options(Options)} of
%% size not used
@@ -101,9 +181,20 @@ merge(Files0, Output0, Options) ->
badarg(culprit(tuple_to_list(T)), [Files0, Output0, Options])
end.
+-spec(keymerge(KeyPos, FileNames, Output) -> Reply when
+ KeyPos :: key_pos(),
+ FileNames :: file_names(),
+ Output :: output(),
+ Reply :: ok | {error, reason()} | output_reply()).
keymerge(KeyPos, Files, Output) ->
keymerge(KeyPos, Files, Output, []).
+-spec(keymerge(KeyPos, FileNames, Output, Options) -> Reply when
+ KeyPos :: key_pos(),
+ FileNames :: file_names(),
+ Output :: output(),
+ Options :: options(),
+ Reply :: ok | {error, reason()} | output_reply()).
keymerge(KeyPos, Files0, Output0, Options) ->
R = case {is_keypos(KeyPos), is_files(Files0),
maybe_output(Output0), options(Options)} of
@@ -123,9 +214,21 @@ keymerge(KeyPos, Files0, Output0, Options) ->
badarg(culprit(O), [KeyPos, Files0, Output0, Options])
end.
+-spec(check(FileName) -> Reply when
+ FileName :: file_name(),
+ Reply :: {ok, [Result]} | {error, reason()},
+ Result :: {FileName, TermPosition, term()},
+ TermPosition :: pos_integer()).
check(FileName) ->
check([FileName], []).
+-spec(check(FileNames, Options) -> Reply when
+ FileNames :: file_names(),
+ Options :: options(),
+ Reply :: {ok, [Result]} | {error, reason()},
+ Result :: {FileName, TermPosition, term()},
+ FileName :: file_name(),
+ TermPosition :: pos_integer()).
check(Files0, Options) ->
case {is_files(Files0), options(Options)} of
{{true,Files}, #opts{}=Opts} ->
@@ -134,9 +237,23 @@ check(Files0, Options) ->
badarg(culprit(tuple_to_list(T)), [Files0, Options])
end.
+-spec(keycheck(KeyPos, FileName) -> Reply when
+ KeyPos :: key_pos(),
+ FileName :: file_name(),
+ Reply :: {ok, [Result]} | {error, reason()},
+ Result :: {FileName, TermPosition, term()},
+ TermPosition :: pos_integer()).
keycheck(KeyPos, FileName) ->
keycheck(KeyPos, [FileName], []).
+-spec(keycheck(KeyPos, FileNames, Options) -> Reply when
+ KeyPos :: key_pos(),
+ FileNames :: file_names(),
+ Options :: options(),
+ Reply :: {ok, [Result]} | {error, reason()},
+ Result :: {FileName, TermPosition, term()},
+ FileName :: file_name(),
+ TermPosition :: pos_integer()).
keycheck(KeyPos, Files0, Options) ->
R = case {is_keypos(KeyPos), is_files(Files0), options(Options)} of
{_, _, #opts{format = binary}} ->
diff --git a/lib/stdlib/src/filelib.erl b/lib/stdlib/src/filelib.erl
index c845b61204..d532cea187 100644
--- a/lib/stdlib/src/filelib.erl
+++ b/lib/stdlib/src/filelib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The 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,13 +40,19 @@
erlang:error(UnUsUalVaRiAbLeNaMe)
end).
+-type filename() :: file:name().
+-type dirname() :: filename().
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec wildcard(file:name()) -> [file:filename()].
+-spec wildcard(Wildcard) -> [file:filename()] when
+ Wildcard :: filename() | dirname().
wildcard(Pattern) when is_list(Pattern) ->
?HANDLE_ERROR(do_wildcard(Pattern, file)).
--spec wildcard(file:name(), file:name() | atom()) -> [file:filename()].
+-spec wildcard(Wildcard, Cwd) -> [file:filename()] when
+ Wildcard :: filename() | dirname(),
+ Cwd :: dirname().
wildcard(Pattern, Cwd) when is_list(Pattern), (is_list(Cwd) or is_binary(Cwd)) ->
?HANDLE_ERROR(do_wildcard(Pattern, Cwd, file));
wildcard(Pattern, Mod) when is_list(Pattern), is_atom(Mod) ->
@@ -57,7 +63,8 @@ wildcard(Pattern, Cwd, Mod)
when is_list(Pattern), (is_list(Cwd) or is_binary(Cwd)), is_atom(Mod) ->
?HANDLE_ERROR(do_wildcard(Pattern, Cwd, Mod)).
--spec is_dir(file:name()) -> boolean().
+-spec is_dir(Name) -> boolean() when
+ Name :: filename() | dirname().
is_dir(Dir) ->
do_is_dir(Dir, file).
@@ -65,7 +72,8 @@ is_dir(Dir) ->
is_dir(Dir, Mod) when is_atom(Mod) ->
do_is_dir(Dir, Mod).
--spec is_file(file:name()) -> boolean().
+-spec is_file(Name) -> boolean() when
+ Name :: filename() | dirname().
is_file(File) ->
do_is_file(File, file).
@@ -73,7 +81,8 @@ is_file(File) ->
is_file(File, Mod) when is_atom(Mod) ->
do_is_file(File, Mod).
--spec is_regular(file:name()) -> boolean().
+-spec is_regular(Name) -> boolean() when
+ Name :: filename().
is_regular(File) ->
do_is_regular(File, file).
@@ -81,7 +90,13 @@ is_regular(File) ->
is_regular(File, Mod) when is_atom(Mod) ->
do_is_regular(File, Mod).
--spec fold_files(file:name(), string(), boolean(), fun((_,_) -> _), _) -> _.
+-spec fold_files(Dir, RegExp, Recursive, Fun, AccIn) -> AccOut when
+ Dir :: dirname(),
+ RegExp :: string(),
+ Recursive :: boolean(),
+ Fun :: fun((F :: file:filename(), AccIn) -> AccOut),
+ AccIn :: term(),
+ AccOut :: term().
fold_files(Dir, RegExp, Recursive, Fun, Acc) ->
do_fold_files(Dir, RegExp, Recursive, Fun, Acc, file).
@@ -89,7 +104,8 @@ fold_files(Dir, RegExp, Recursive, Fun, Acc) ->
fold_files(Dir, RegExp, Recursive, Fun, Acc, Mod) when is_atom(Mod) ->
do_fold_files(Dir, RegExp, Recursive, Fun, Acc, Mod).
--spec last_modified(file:name()) -> file:date_time() | 0.
+-spec last_modified(Name) -> file:date_time() | 0 when
+ Name :: filename() | dirname().
last_modified(File) ->
do_last_modified(File, file).
@@ -97,7 +113,8 @@ last_modified(File) ->
last_modified(File, Mod) when is_atom(Mod) ->
do_last_modified(File, Mod).
--spec file_size(file:name()) -> non_neg_integer().
+-spec file_size(Filename) -> non_neg_integer() when
+ Filename :: filename().
file_size(File) ->
do_file_size(File, file).
@@ -237,7 +254,9 @@ do_file_size(File, Mod) ->
%% +type X = filename() | dirname()
%% ensures that the directory name required to create D exists
--spec ensure_dir(file:name()) -> 'ok' | {'error', file:posix()}.
+-spec ensure_dir(Name) -> 'ok' | {'error', Reason} when
+ Name :: filename() | dirname(),
+ Reason :: file:posix().
ensure_dir("/") ->
ok;
ensure_dir(F) ->
diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl
index 24abf1e977..1cb9e4a25e 100644
--- a/lib/stdlib/src/filename.erl
+++ b/lib/stdlib/src/filename.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The 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,12 +61,15 @@
%% (for WIN32): absname("/") -> "D:/"
--spec absname(file:name()) -> file:filename().
+-spec absname(Filename) -> file:filename() when
+ Filename :: file:name().
absname(Name) ->
{ok, Cwd} = file:get_cwd(),
absname(Name, Cwd).
--spec absname(file:name(), file:filename()) -> file:filename().
+-spec absname(Filename, Dir) -> file:filename() when
+ Filename :: file:name(),
+ Dir :: file:filename().
absname(Name, AbsBase) when is_binary(Name), is_list(AbsBase) ->
absname(Name,filename_string_to_binary(AbsBase));
absname(Name, AbsBase) when is_list(Name), is_binary(AbsBase) ->
@@ -119,7 +122,9 @@ absname_vr([[X, $:]|Name], _, _AbsBase) ->
%% This is just a join/2, but assumes that
%% AbsBase must be absolute and Name must be relative.
--spec absname_join(file:filename(), file:name()) -> file:filename().
+-spec absname_join(Dir, Filename) -> file:filename() when
+ Dir :: file:filename(),
+ Filename :: file:name().
absname_join(AbsBase, Name) ->
join(AbsBase, flatten(Name)).
@@ -131,7 +136,8 @@ absname_join(AbsBase, Name) ->
%% basename("/usr/foo/") -> "foo" (trailing slashes ignored)
%% basename("/") -> []
--spec basename(file:name()) -> file:filename().
+-spec basename(Filename) -> file:filename() when
+ Filename :: file:name().
basename(Name) when is_binary(Name) ->
case os:type() of
{win32,_} ->
@@ -192,7 +198,9 @@ skip_prefix(Name, _) ->
%% rootname(basename("xxx.jam")) -> "xxx"
%% rootname(basename("xxx.erl")) -> "xxx"
--spec basename(file:name(), file:name()) -> file:filename().
+-spec basename(Filename, Ext) -> file:filename() when
+ Filename :: file:name(),
+ Ext :: file:name().
basename(Name, Ext) when is_binary(Name), is_list(Ext) ->
basename(Name,filename_string_to_binary(Ext));
basename(Name, Ext) when is_list(Name), is_binary(Ext) ->
@@ -240,7 +248,8 @@ basename([], _Ext, Tail, _DrvSep2) ->
%% Example: dirname("/usr/src/kalle.erl") -> "/usr/src",
%% dirname("kalle.erl") -> "."
--spec dirname(file:name()) -> file:filename().
+-spec dirname(Filename) -> file:filename() when
+ Filename :: file:name().
dirname(Name) when is_binary(Name) ->
{Dsep,Drivesep} = separators(),
SList = case Dsep of
@@ -332,7 +341,8 @@ dirjoin1([H|T],Acc,Sep) ->
%%
%% On Windows: fn:dirname("\\usr\\src/kalle.erl") -> "/usr/src"
--spec extension(file:name()) -> file:filename().
+-spec extension(Filename) -> file:filename() when
+ Filename :: file:name().
extension(Name) when is_binary(Name) ->
{Dsep,_} = separators(),
SList = case Dsep of
@@ -374,7 +384,8 @@ extension([], Result, _OsType) ->
%% Joins a list of filenames with directory separators.
--spec join([file:filename()]) -> file:filename().
+-spec join(Components) -> file:filename() when
+ Components :: [file:filename()].
join([Name1, Name2|Rest]) ->
join([join(Name1, Name2)|Rest]);
join([Name]) when is_list(Name) ->
@@ -386,7 +397,9 @@ join([Name]) when is_atom(Name) ->
%% Joins two filenames with directory separators.
--spec join(file:filename(), file:filename()) -> file:filename().
+-spec join(Name1, Name2) -> file:filename() when
+ Name1 :: file:filename(),
+ Name2 :: file:filename().
join(Name1, Name2) when is_list(Name1), is_list(Name2) ->
OsType = major_os_type(),
case pathtype(Name2) of
@@ -494,7 +507,8 @@ append(Dir, Name) ->
%% current working volume. (Windows only)
%% Example: a:bar.erl, /temp/foo.erl
--spec pathtype(file:name()) -> 'absolute' | 'relative' | 'volumerelative'.
+-spec pathtype(Path) -> 'absolute' | 'relative' | 'volumerelative' when
+ Path :: file:name().
pathtype(Atom) when is_atom(Atom) ->
pathtype(atom_to_list(Atom));
pathtype(Name) when is_list(Name) or is_binary(Name) ->
@@ -547,7 +561,8 @@ win32_pathtype(_) -> relative.
%% Examples: rootname("/jam.src/kalle") -> "/jam.src/kalle"
%% rootname("/jam.src/foo.erl") -> "/jam.src/foo"
--spec rootname(file:name()) -> file:filename().
+-spec rootname(Filename) -> file:filename() when
+ Filename :: file:name().
rootname(Name) when is_binary(Name) ->
list_to_binary(rootname(binary_to_list(Name))); % No need to handle unicode, . is < 128
rootname(Name0) ->
@@ -576,7 +591,9 @@ rootname([], Root, _Ext, _OsType) ->
%% Examples: rootname("/jam.src/kalle.jam", ".erl") -> "/jam.src/kalle.jam"
%% rootname("/jam.src/foo.erl", ".erl") -> "/jam.src/foo"
--spec rootname(file:name(), file:name()) -> file:filename().
+-spec rootname(Filename, Ext) -> file:filename() when
+ Filename :: file:name(),
+ Ext :: file:name().
rootname(Name, Ext) when is_binary(Name), is_binary(Ext) ->
list_to_binary(rootname(binary_to_list(Name),binary_to_list(Ext)));
rootname(Name, Ext) when is_binary(Name) ->
@@ -602,7 +619,9 @@ rootname2([Char|Rest], Ext, Result) when is_integer(Char) ->
%% split("foo/bar") -> ["foo", "bar"]
%% split("a:\\msdev\\include") -> ["a:/", "msdev", "include"]
--spec split(file:name()) -> [file:filename()].
+-spec split(Filename) -> Components when
+ Filename :: file:name(),
+ Components :: [file:filename()].
split(Name) when is_binary(Name) ->
case os:type() of
{win32, _} -> win32_splitb(Name);
@@ -695,7 +714,8 @@ split([], Comp, Components, OsType) ->
%% will be converted to backslashes. On all platforms, the
%% name will be normalized as done by join/1.
--spec nativename(file:filename()) -> file:filename().
+-spec nativename(Path) -> file:filename() when
+ Path :: file:filename().
nativename(Name0) ->
Name = join([Name0]), %Normalize.
case os:type() of
@@ -747,12 +767,17 @@ separators() ->
%% The paths in the {outdir, Path} and {i, Path} options are guaranteed
%% to be absolute.
--type rule() :: {string(), string()}.
--type ecode() :: 'non_existing' | 'preloaded' | 'interpreted'.
--type option() :: {'i', string()} | {'outdir', string()} | {'d', atom()}.
-
--spec find_src(atom() | string()) ->
- {string(), [option()]} | {'error', {ecode(), atom()}}.
+-spec find_src(Beam) -> {SourceFile, Options}
+ | {error, {ErrorReason, Module}} when
+ Beam :: Module | Filename,
+ Filename :: atom() | string(),
+ Module :: module(),
+ SourceFile :: string(),
+ Options :: [Option],
+ Option :: {'i', Path :: string()}
+ | {'outdir', Path :: string()}
+ | {'d', atom()},
+ ErrorReason :: 'non_existing' | 'preloaded' | 'interpreted'.
find_src(Mod) ->
Default = [{"", ""}, {"ebin", "src"}, {"ebin", "esrc"}],
Rules =
@@ -763,8 +788,18 @@ find_src(Mod) ->
end,
find_src(Mod, Rules).
--spec find_src(atom() | string(), [rule()]) ->
- {string(), [option()]} | {'error', {ecode(), atom()}}.
+-spec find_src(Beam, Rules) -> {SourceFile, Options}
+ | {error, {ErrorReason, Module}} when
+ Beam :: Module | Filename,
+ Filename :: atom() | string(),
+ Rules :: [{BinSuffix :: string(), SourceSuffix :: string()}],
+ Module :: module(),
+ SourceFile :: string(),
+ Options :: [Option],
+ Option :: {'i', Path :: string()}
+ | {'outdir', Path :: string()}
+ | {'d', atom()},
+ ErrorReason :: 'non_existing' | 'preloaded' | 'interpreted'.
find_src(Mod, Rules) when is_atom(Mod) ->
find_src(atom_to_list(Mod), Rules);
find_src(File0, Rules) when is_list(File0) ->
@@ -890,7 +925,8 @@ major_os_type() ->
%% flatten(List)
%% Flatten a list, also accepting atoms.
--spec flatten(file:name()) -> file:filename().
+-spec flatten(Filename) -> file:filename() when
+ Filename :: file:name().
flatten(Bin) when is_binary(Bin) ->
Bin;
flatten(List) ->
diff --git a/lib/stdlib/src/gb_sets.erl b/lib/stdlib/src/gb_sets.erl
index fc5beb28b0..91d21d869c 100644
--- a/lib/stdlib/src/gb_sets.erl
+++ b/lib/stdlib/src/gb_sets.erl
@@ -197,6 +197,7 @@
%% Some types.
-type gb_set_node() :: 'nil' | {term(), _, _}.
+-opaque iter() :: [gb_set_node()].
%% A declaration equivalent to the following is currently hard-coded
%% in erl_types.erl
@@ -205,38 +206,47 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec empty() -> gb_set().
+-spec empty() -> Set when
+ Set :: gb_set().
empty() ->
{0, nil}.
--spec new() -> gb_set().
+-spec new() -> Set when
+ Set :: gb_set().
new() -> empty().
--spec is_empty(gb_set()) -> boolean().
+-spec is_empty(Set) -> boolean() when
+ Set :: gb_set().
is_empty({0, nil}) ->
true;
is_empty(_) ->
false.
--spec size(gb_set()) -> non_neg_integer().
+-spec size(Set) -> non_neg_integer() when
+ Set :: gb_set().
size({Size, _}) ->
Size.
--spec singleton(term()) -> gb_set().
+-spec singleton(Element) -> gb_set() when
+ Element :: term().
singleton(Key) ->
{1, {Key, nil, nil}}.
--spec is_element(term(), gb_set()) -> boolean().
+-spec is_element(Element, Set) -> boolean() when
+ Element :: term(),
+ Set :: gb_set().
is_element(Key, S) ->
is_member(Key, S).
--spec is_member(term(), gb_set()) -> boolean().
+-spec is_member(Element, Set) -> boolean() when
+ Element :: term(),
+ Set :: gb_set().
is_member(Key, {_, T}) ->
is_member_1(Key, T).
@@ -250,7 +260,10 @@ is_member_1(_, {_, _, _}) ->
is_member_1(_, nil) ->
false.
--spec insert(term(), gb_set()) -> gb_set().
+-spec insert(Element, Set1) -> Set2 when
+ Element :: term(),
+ Set1 :: gb_set(),
+ Set2 :: gb_set().
insert(Key, {S, T}) ->
S1 = S + 1,
@@ -306,7 +319,9 @@ count({_, Sm, Bi}) ->
count(nil) ->
{1, 0}.
--spec balance(gb_set()) -> gb_set().
+-spec balance(Set1) -> Set2 when
+ Set1 :: gb_set(),
+ Set2 :: gb_set().
balance({S, T}) ->
{S, balance(T, S)}.
@@ -331,12 +346,18 @@ balance_list_1([Key | L], 1) ->
balance_list_1(L, 0) ->
{nil, L}.
--spec add_element(term(), gb_set()) -> gb_set().
+-spec add_element(Element, Set1) -> Set2 when
+ Element :: term(),
+ Set1 :: gb_set(),
+ Set2 :: gb_set().
add_element(X, S) ->
add(X, S).
--spec add(term(), gb_set()) -> gb_set().
+-spec add(Element, Set1) -> Set2 when
+ Element :: term(),
+ Set1 :: gb_set(),
+ Set2 :: gb_set().
add(X, S) ->
case is_member(X, S) of
@@ -346,23 +367,33 @@ add(X, S) ->
insert(X, S)
end.
--spec from_list([term()]) -> gb_set().
+-spec from_list(List) -> Set when
+ List :: [term()],
+ Set :: gb_set().
from_list(L) ->
from_ordset(ordsets:from_list(L)).
--spec from_ordset([term()]) -> gb_set().
+-spec from_ordset(List) -> Set when
+ List :: [term()],
+ Set :: gb_set().
from_ordset(L) ->
S = length(L),
{S, balance_list(L, S)}.
--spec del_element(term(), gb_set()) -> gb_set().
+-spec del_element(Element, Set1) -> Set2 when
+ Element :: term(),
+ Set1 :: gb_set(),
+ Set2 :: gb_set().
del_element(Key, S) ->
delete_any(Key, S).
--spec delete_any(term(), gb_set()) -> gb_set().
+-spec delete_any(Element, Set1) -> Set2 when
+ Element :: term(),
+ Set1 :: gb_set(),
+ Set2 :: gb_set().
delete_any(Key, S) ->
case is_member(Key, S) of
@@ -372,7 +403,10 @@ delete_any(Key, S) ->
S
end.
--spec delete(term(), gb_set()) -> gb_set().
+-spec delete(Element, Set1) -> Set2 when
+ Element :: term(),
+ Set1 :: gb_set(),
+ Set2 :: gb_set().
delete(Key, {S, T}) ->
{S - 1, delete_1(Key, T)}.
@@ -394,7 +428,10 @@ merge(Smaller, Larger) ->
{Key, Larger1} = take_smallest1(Larger),
{Key, Smaller, Larger1}.
--spec take_smallest(gb_set()) -> {term(), gb_set()}.
+-spec take_smallest(Set1) -> {Element, Set2} when
+ Set1 :: gb_set(),
+ Set2 :: gb_set(),
+ Element :: term().
take_smallest({S, T}) ->
{Key, Larger} = take_smallest1(T),
@@ -406,7 +443,8 @@ take_smallest1({Key, Smaller, Larger}) ->
{Key1, Smaller1} = take_smallest1(Smaller),
{Key1, {Key, Smaller1, Larger}}.
--spec smallest(gb_set()) -> term().
+-spec smallest(Set) -> term() when
+ Set :: gb_set().
smallest({_, T}) ->
smallest_1(T).
@@ -416,7 +454,10 @@ smallest_1({Key, nil, _Larger}) ->
smallest_1({_Key, Smaller, _Larger}) ->
smallest_1(Smaller).
--spec take_largest(gb_set()) -> {term(), gb_set()}.
+-spec take_largest(Set1) -> {Element, Set2} when
+ Set1 :: gb_set(),
+ Set2 :: gb_set(),
+ Element :: term().
take_largest({S, T}) ->
{Key, Smaller} = take_largest1(T),
@@ -428,7 +469,8 @@ take_largest1({Key, Smaller, Larger}) ->
{Key1, Larger1} = take_largest1(Larger),
{Key1, {Key, Smaller, Larger1}}.
--spec largest(gb_set()) -> term().
+-spec largest(Set) -> term() when
+ Set :: gb_set().
largest({_, T}) ->
largest_1(T).
@@ -438,7 +480,9 @@ largest_1({Key, _Smaller, nil}) ->
largest_1({_Key, _Smaller, Larger}) ->
largest_1(Larger).
--spec to_list(gb_set()) -> [term()].
+-spec to_list(Set) -> List when
+ Set :: gb_set(),
+ List :: [term()].
to_list({_, T}) ->
to_list(T, []).
@@ -449,7 +493,9 @@ to_list({Key, Small, Big}, L) ->
to_list(Small, [Key | to_list(Big, L)]);
to_list(nil, L) -> L.
--spec iterator(gb_set()) -> [term()].
+-spec iterator(Set) -> Iter when
+ Set :: gb_set(),
+ Iter :: iter().
iterator({_, T}) ->
iterator(T, []).
@@ -464,7 +510,10 @@ iterator({_, L, _} = T, As) ->
iterator(nil, As) ->
As.
--spec next([term()]) -> {term(), [term()]} | 'none'.
+-spec next(Iter1) -> {Element, Iter2} | 'none' when
+ Iter1 :: iter(),
+ Iter2 :: iter(),
+ Element :: term().
next([{X, _, T} | As]) ->
{X, iterator(T, As)};
@@ -494,7 +543,10 @@ next([]) ->
%% traversing the elements can be devised, but they all have higher
%% overhead.
--spec union(gb_set(), gb_set()) -> gb_set().
+-spec union(Set1, Set2) -> Set3 when
+ Set1 :: gb_set(),
+ Set2 :: gb_set(),
+ Set3 :: gb_set().
union({N1, T1}, {N2, T2}) when N2 < N1 ->
union(to_list_1(T2), N2, T1, N1);
@@ -596,7 +648,9 @@ balance_revlist_1([Key | L], 1) ->
balance_revlist_1(L, 0) ->
{nil, L}.
--spec union([gb_set()]) -> gb_set().
+-spec union(SetList) -> Set when
+ SetList :: [gb_set(),...],
+ Set :: gb_set().
union([S | Ss]) ->
union_list(S, Ss);
@@ -609,7 +663,10 @@ union_list(S, []) -> S.
%% The rest is modelled on the above.
--spec intersection(gb_set(), gb_set()) -> gb_set().
+-spec intersection(Set1, Set2) -> Set3 when
+ Set1 :: gb_set(),
+ Set2 :: gb_set(),
+ Set3 :: gb_set().
intersection({N1, T1}, {N2, T2}) when N2 < N1 ->
intersection(to_list_1(T2), N2, T1, N1);
@@ -657,7 +714,9 @@ intersection_2([], _, As, S) ->
intersection_2(_, [], As, S) ->
{S, balance_revlist(As, S)}.
--spec intersection([gb_set(),...]) -> gb_set().
+-spec intersection(SetList) -> Set when
+ SetList :: [gb_set(),...],
+ Set :: gb_set().
intersection([S | Ss]) ->
intersection_list(S, Ss).
@@ -666,7 +725,9 @@ intersection_list(S, [S1 | Ss]) ->
intersection_list(intersection(S, S1), Ss);
intersection_list(S, []) -> S.
--spec is_disjoint(gb_set(), gb_set()) -> boolean().
+-spec is_disjoint(Set1, Set2) -> boolean() when
+ Set1 :: gb_set(),
+ Set2 :: gb_set().
is_disjoint({N1, T1}, {N2, T2}) when N1 < N2 ->
is_disjoint_1(T1, T2);
@@ -694,12 +755,18 @@ is_disjoint_1(_, nil) ->
%% the sets. Therefore, we always build a new tree, and thus we need to
%% traverse the whole element list of the left operand.
--spec subtract(gb_set(), gb_set()) -> gb_set().
+-spec subtract(Set1, Set2) -> Set3 when
+ Set1 :: gb_set(),
+ Set2 :: gb_set(),
+ Set3 :: gb_set().
subtract(S1, S2) ->
difference(S1, S2).
--spec difference(gb_set(), gb_set()) -> gb_set().
+-spec difference(Set1, Set2) -> Set3 when
+ Set1 :: gb_set(),
+ Set2 :: gb_set(),
+ Set3 :: gb_set().
difference({N1, T1}, {N2, T2}) ->
difference(to_list_1(T1), N1, T2, N2).
@@ -747,7 +814,9 @@ difference_2(Xs, [], As, S) ->
%% Subset testing is much the same thing as set difference, but
%% without the construction of a new set.
--spec is_subset(gb_set(), gb_set()) -> boolean().
+-spec is_subset(Set1, Set2) -> boolean() when
+ Set1 :: gb_set(),
+ Set2 :: gb_set().
is_subset({N1, T1}, {N2, T2}) ->
is_subset(to_list_1(T1), N1, T2, N2).
@@ -788,18 +857,28 @@ is_subset_2(_, []) ->
%% For compatibility with `sets':
--spec is_set(term()) -> boolean().
+-spec is_set(Term) -> boolean() when
+ Term :: term().
is_set({0, nil}) -> true;
is_set({N, {_, _, _}}) when is_integer(N), N >= 0 -> true;
is_set(_) -> false.
--spec filter(fun((term()) -> boolean()), gb_set()) -> gb_set().
+-spec filter(Pred, Set1) -> Set2 when
+ Pred :: fun((E :: term()) -> boolean()),
+ Set1 :: gb_set(),
+ Set2 :: gb_set().
filter(F, S) ->
from_ordset([X || X <- to_list(S), F(X)]).
--spec fold(fun((term(), term()) -> term()), term(), gb_set()) -> term().
+-spec fold(Function, Acc0, Set) -> Acc1 when
+ Function :: fun((E :: term(), AccIn) -> AccOut),
+ Acc0 :: term(),
+ Acc1 :: term(),
+ AccIn :: term(),
+ AccOut :: term(),
+ Set :: gb_set().
fold(F, A, {_, T}) when is_function(F, 2) ->
fold_1(F, A, T).
diff --git a/lib/stdlib/src/gb_trees.erl b/lib/stdlib/src/gb_trees.erl
index d37786a100..6ad861ff5b 100644
--- a/lib/stdlib/src/gb_trees.erl
+++ b/lib/stdlib/src/gb_trees.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -153,6 +153,7 @@
%% Some types.
-type gb_tree_node() :: 'nil' | {_, _, _, _}.
+-opaque iter() :: [gb_tree_node()].
%% A declaration equivalent to the following is currently hard-coded
%% in erl_types.erl
@@ -166,21 +167,26 @@
empty() ->
{0, nil}.
--spec is_empty(gb_tree()) -> boolean().
+-spec is_empty(Tree) -> boolean() when
+ Tree :: gb_tree().
is_empty({0, nil}) ->
true;
is_empty(_) ->
false.
--spec size(gb_tree()) -> non_neg_integer().
+-spec size(Tree) -> non_neg_integer() when
+ Tree :: gb_tree().
size({Size, _}) when is_integer(Size), Size >= 0 ->
Size.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec lookup(term(), gb_tree()) -> 'none' | {'value', term()}.
+-spec lookup(Key, Tree) -> 'none' | {'value', Val} when
+ Key :: term(),
+ Val :: term(),
+ Tree :: gb_tree().
lookup(Key, {_, T}) ->
lookup_1(Key, T).
@@ -205,7 +211,9 @@ lookup_1(_, nil) ->
%% This is a specialized version of `lookup'.
--spec is_defined(term(), gb_tree()) -> boolean().
+-spec is_defined(Key, Tree) -> boolean() when
+ Key :: term(),
+ Tree :: gb_tree().
is_defined(Key, {_, T}) ->
is_defined_1(Key, T).
@@ -223,7 +231,10 @@ is_defined_1(_, nil) ->
%% This is a specialized version of `lookup'.
--spec get(term(), gb_tree()) -> term().
+-spec get(Key, Tree) -> Val when
+ Key :: term(),
+ Tree :: gb_tree(),
+ Val :: term().
get(Key, {_, T}) ->
get_1(Key, T).
@@ -237,7 +248,11 @@ get_1(_, {_, Value, _, _}) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec update(term(), term(), gb_tree()) -> gb_tree().
+-spec update(Key, Val, Tree1) -> Tree2 when
+ Key :: term(),
+ Val :: term(),
+ Tree1 :: gb_tree(),
+ Tree2 :: gb_tree().
update(Key, Val, {S, T}) ->
T1 = update_1(Key, Val, T),
@@ -254,7 +269,11 @@ update_1(Key, Value, {_, _, Smaller, Bigger}) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec insert(term(), term(), gb_tree()) -> gb_tree().
+-spec insert(Key, Val, Tree1) -> Tree2 when
+ Key :: term(),
+ Val :: term(),
+ Tree1 :: gb_tree(),
+ Tree2 :: gb_tree().
insert(Key, Val, {S, T}) when is_integer(S) ->
S1 = S+1,
@@ -303,7 +322,11 @@ insert_1(Key, _, _, _) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec enter(term(), term(), gb_tree()) -> gb_tree().
+-spec enter(Key, Val, Tree1) -> Tree2 when
+ Key :: term(),
+ Val :: term(),
+ Tree1 :: gb_tree(),
+ Tree2 :: gb_tree().
enter(Key, Val, T) ->
case is_defined(Key, T) of
@@ -326,7 +349,9 @@ count(nil) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec balance(gb_tree()) -> gb_tree().
+-spec balance(Tree1) -> Tree2 when
+ Tree1 :: gb_tree(),
+ Tree2 :: gb_tree().
balance({S, T}) ->
{S, balance(T, S)}.
@@ -351,7 +376,9 @@ balance_list_1([{Key, Val} | L], 1) ->
balance_list_1(L, 0) ->
{nil, L}.
--spec from_orddict([{_,_}]) -> gb_tree().
+-spec from_orddict(List) -> Tree when
+ List :: [{Key :: term(), Val :: term()}],
+ Tree :: gb_tree().
from_orddict(L) ->
S = length(L),
@@ -359,7 +386,10 @@ from_orddict(L) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec delete_any(term(), gb_tree()) -> gb_tree().
+-spec delete_any(Key, Tree1) -> Tree2 when
+ Key :: term(),
+ Tree1 :: gb_tree(),
+ Tree2 :: gb_tree().
delete_any(Key, T) ->
case is_defined(Key, T) of
@@ -371,7 +401,10 @@ delete_any(Key, T) ->
%%% delete. Assumes that key is present.
--spec delete(term(), gb_tree()) -> gb_tree().
+-spec delete(Key, Tree1) -> Tree2 when
+ Key :: term(),
+ Tree1 :: gb_tree(),
+ Tree2 :: gb_tree().
delete(Key, {S, T}) when is_integer(S), S >= 0 ->
{S - 1, delete_1(Key, T)}.
@@ -397,7 +430,11 @@ merge(Smaller, Larger) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec take_smallest(gb_tree()) -> {term(), term(), gb_tree()}.
+-spec take_smallest(Tree1) -> {Key, Val, Tree2} when
+ Tree1 :: gb_tree(),
+ Tree2 :: gb_tree(),
+ Key :: term(),
+ Val :: term().
take_smallest({Size, Tree}) when is_integer(Size), Size >= 0 ->
{Key, Value, Larger} = take_smallest1(Tree),
@@ -409,7 +446,10 @@ take_smallest1({Key, Value, Smaller, Larger}) ->
{Key1, Value1, Smaller1} = take_smallest1(Smaller),
{Key1, Value1, {Key, Value, Smaller1, Larger}}.
--spec smallest(gb_tree()) -> {term(), term()}.
+-spec smallest(Tree) -> {Key, Val} when
+ Tree :: gb_tree(),
+ Key :: term(),
+ Val :: term().
smallest({_, Tree}) ->
smallest_1(Tree).
@@ -419,7 +459,11 @@ smallest_1({Key, Value, nil, _Larger}) ->
smallest_1({_Key, _Value, Smaller, _Larger}) ->
smallest_1(Smaller).
--spec take_largest(gb_tree()) -> {term(), term(), gb_tree()}.
+-spec take_largest(Tree1) -> {Key, Val, Tree2} when
+ Tree1 :: gb_tree(),
+ Tree2 :: gb_tree(),
+ Key :: term(),
+ Val :: term().
take_largest({Size, Tree}) when is_integer(Size), Size >= 0 ->
{Key, Value, Smaller} = take_largest1(Tree),
@@ -431,7 +475,10 @@ take_largest1({Key, Value, Smaller, Larger}) ->
{Key1, Value1, Larger1} = take_largest1(Larger),
{Key1, Value1, {Key, Value, Smaller, Larger1}}.
--spec largest(gb_tree()) -> {term(), term()}.
+-spec largest(Tree) -> {Key, Val} when
+ Tree :: gb_tree(),
+ Key :: term(),
+ Val :: term().
largest({_, Tree}) ->
largest_1(Tree).
@@ -443,7 +490,10 @@ largest_1({_Key, _Value, _Smaller, Larger}) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec to_list(gb_tree()) -> [{term(), term()}].
+-spec to_list(Tree) -> [{Key, Val}] when
+ Tree :: gb_tree(),
+ Key :: term(),
+ Val :: term().
to_list({_, T}) ->
to_list(T, []).
@@ -456,7 +506,9 @@ to_list(nil, L) -> L.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec keys(gb_tree()) -> [term()].
+-spec keys(Tree) -> [Key] when
+ Tree :: gb_tree(),
+ Key :: term().
keys({_, T}) ->
keys(T, []).
@@ -467,7 +519,9 @@ keys(nil, L) -> L.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec values(gb_tree()) -> [term()].
+-spec values(Tree) -> [Val] when
+ Tree :: gb_tree(),
+ Val :: term().
values({_, T}) ->
values(T, []).
@@ -478,7 +532,9 @@ values(nil, L) -> L.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec iterator(gb_tree()) -> [gb_tree_node()].
+-spec iterator(Tree) -> Iter when
+ Tree :: gb_tree(),
+ Iter :: iter().
iterator({_, T}) ->
iterator_1(T).
@@ -496,7 +552,11 @@ iterator({_, _, L, _} = T, As) ->
iterator(nil, As) ->
As.
--spec next([gb_tree_node()]) -> 'none' | {term(), term(), [gb_tree_node()]}.
+-spec next(Iter1) -> 'none' | {Key, Val, Iter2} when
+ Iter1 :: iter(),
+ Iter2 :: iter(),
+ Key :: term(),
+ Val :: term().
next([{X, V, _, T} | As]) ->
{X, V, iterator(T, As)};
@@ -505,7 +565,10 @@ next([]) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec map(fun((term(), term()) -> term()), gb_tree()) -> gb_tree().
+-spec map(Function, Tree1) -> Tree2 when
+ Function :: fun((K :: term(), V1 :: term()) -> V2 :: term()),
+ Tree1 :: gb_tree(),
+ Tree2 :: gb_tree().
map(F, {Size, Tree}) when is_function(F, 2) ->
{Size, map_1(F, Tree)}.
diff --git a/lib/stdlib/src/gen.erl b/lib/stdlib/src/gen.erl
index 43df6f621d..574146b1cd 100644
--- a/lib/stdlib/src/gen.erl
+++ b/lib/stdlib/src/gen.erl
@@ -29,6 +29,8 @@
-export([init_it/6, init_it/7]).
+-export([format_status_header/2]).
+
-define(default_timeout, 5000).
%%-----------------------------------------------------------------
@@ -315,3 +317,10 @@ debug_options(Opts) ->
{ok, Options} -> sys:debug_options(Options);
_ -> []
end.
+
+format_status_header(TagLine, Pid) when is_pid(Pid) ->
+ lists:concat([TagLine, " ", pid_to_list(Pid)]);
+format_status_header(TagLine, RegName) when is_atom(RegName) ->
+ lists:concat([TagLine, " ", RegName]);
+format_status_header(TagLine, Name) ->
+ {TagLine, Name}.
diff --git a/lib/stdlib/src/gen_event.erl b/lib/stdlib/src/gen_event.erl
index b1e9e3a02f..9879b76391 100644
--- a/lib/stdlib/src/gen_event.erl
+++ b/lib/stdlib/src/gen_event.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -36,14 +36,15 @@
add_handler/3, add_sup_handler/3, delete_handler/3, swap_handler/3,
swap_sup_handler/3, which_handlers/1, call/3, call/4, wake_hib/4]).
--export([behaviour_info/1]).
-
-export([init_it/6,
system_continue/3,
system_terminate/4,
system_code_change/4,
format_status/2]).
+-export_type([handler/0, handler_args/0, add_handler_ret/0,
+ del_handler_ret/0]).
+
-import(error_logger, [error_msg/2]).
-define(reply(X), From ! {element(2,Tag), X}).
@@ -57,14 +58,6 @@
%%% API
%%%=========================================================================
--spec behaviour_info(atom()) -> 'undefined' | [{atom(), arity()}].
-
-behaviour_info(callbacks) ->
- [{init,1},{handle_event,2},{handle_call,2},{handle_info,2},
- {terminate,2},{code_change,3}];
-behaviour_info(_Other) ->
- undefined.
-
%% gen_event:start(Handler) -> {ok, Pid} | {error, What}
%% gen_event:add_handler(Handler, Mod, Args) -> ok | Other
%% gen_event:notify(Handler, Event) -> ok
@@ -75,45 +68,44 @@ behaviour_info(_Other) ->
%% gen_event:which_handler(Handler) -> [Mod]
%% gen_event:stop(Handler) -> ok
-
-%% handlers must export
-%% Mod:init(Args) -> {ok, State} | Other
-%% Mod:handle_event(Event, State) ->
-%% {ok, State'} | remove_handler | {swap_handler,Args1,State1,Mod2,Args2}
-%% Mod:handle_info(Info, State) ->
-%% {ok, State'} | remove_handler | {swap_handler,Args1,State1,Mod2,Args2}
-%% Mod:handle_call(Query, State) ->
-%% {ok, Reply, State'} | {remove_handler, Reply} |
-%% {swap_handler, Reply, Args1,State1,Mod2,Args2}
-%% Mod:terminate(Args, State) -> Val
-
-
-%% add_handler(H, Mod, Args) -> ok | Other
-%% Mod:init(Args) -> {ok, State} | Other
-
-%% delete_handler(H, Mod, Args) -> Val
-%% Mod:terminate(Args, State) -> Val
-
-%% notify(H, Event)
-%% Mod:handle_event(Event, State) ->
-%% {ok, State1}
-%% remove_handler
-%% Mod:terminate(remove_handler, State) is called
-%% the return value is ignored
-%% {swap_handler, Args1, State1, Mod2, Args2}
-%% State2 = Mod:terminate(Args1, State1) is called
-%% the return value is chained into the new module and
-%% Mod2:init({Args2, State2}) is called
-%% Other
-%% Mod:terminate({error, Other}, State) is called
-%% The return value is ignored
-%% call(H, Mod, Query) -> Val
-%% call(H, Mod, Query, Timeout) -> Val
-%% Mod:handle_call(Query, State) -> as above
+-callback init(InitArgs :: term()) ->
+ {ok, State :: term()} |
+ {ok, State :: term(), hibernate}.
+-callback handle_event(Event :: term(), State :: term()) ->
+ {ok, NewState :: term()} |
+ {ok, NewState :: term(), hibernate} |
+ {swap_handler, Args1 :: term(), NewState :: term(),
+ Handler2 :: (atom() | {atom(), Id :: term()}), Args2 :: term()} |
+ remove_handler.
+-callback handle_call(Request :: term(), State :: term()) ->
+ {ok, Reply :: term(), NewState :: term()} |
+ {ok, Reply :: term(), NewState :: term(), hibernate} |
+ {swap_handler, Reply :: term(), Args1 :: term(), NewState :: term(),
+ Handler2 :: (atom() | {atom(), Id :: term()}), Args2 :: term()} |
+ {remove_handler, Reply :: term()}.
+-callback handle_info(Info :: term(), State :: term()) ->
+ {ok, NewState :: term()} |
+ {ok, NewState :: term(), hibernate} |
+ {swap_handler, Args1 :: term(), NewState :: term(),
+ Handler2 :: (atom() | {atom(), Id :: term()}), Args2 :: term()} |
+ remove_handler.
+-callback terminate(Args :: (term() | {stop, Reason :: term()} |
+ stop | remove_handler |
+ {error, {'EXIT', Reason :: term()}} |
+ {error, term()}),
+ State :: term()) ->
+ term().
+-callback code_change(OldVsn :: (term() | {down, term()}),
+ State :: term(), Extra :: term()) ->
+ {ok, NewState :: term()}.
%%---------------------------------------------------------------------------
--type handler() :: atom() | {atom(), term()}.
+-type handler() :: atom() | {atom(), term()}.
+-type handler_args() :: term().
+-type add_handler_ret() :: ok | term() | {'EXIT',term()}.
+-type del_handler_ret() :: ok | term() | {'EXIT',term()}.
+
-type emgr_name() :: {'local', atom()} | {'global', atom()}.
-type emgr_ref() :: atom() | {atom(), atom()} | {'global', atom()} | pid().
-type start_ret() :: {'ok', pid()} | {'error', term()}.
@@ -660,16 +652,16 @@ report_error(_Handler, {swapped,_,_}, _, _, _) -> ok;
report_error(Handler, Reason, State, LastIn, SName) ->
Reason1 =
case Reason of
- {'EXIT',{undef,[{M,F,A}|MFAs]}} ->
+ {'EXIT',{undef,[{M,F,A,L}|MFAs]}} ->
case code:is_loaded(M) of
false ->
- {'module could not be loaded',[{M,F,A}|MFAs]};
+ {'module could not be loaded',[{M,F,A,L}|MFAs]};
_ ->
case erlang:function_exported(M, F, length(A)) of
true ->
- {undef,[{M,F,A}|MFAs]};
+ {undef,[{M,F,A,L}|MFAs]};
false ->
- {'function not exported',[{M,F,A}|MFAs]}
+ {'function not exported',[{M,F,A,L}|MFAs]}
end
end;
{'EXIT',Why} ->
@@ -724,7 +716,8 @@ get_modules(MSL) ->
%%-----------------------------------------------------------------
format_status(Opt, StatusData) ->
[PDict, SysState, Parent, _Debug, [ServerName, MSL, _Hib]] = StatusData,
- Header = lists:concat(["Status for event handler ", ServerName]),
+ Header = gen:format_status_header("Status for event handler",
+ ServerName),
FmtMSL = [case erlang:function_exported(Mod, format_status, 2) of
true ->
Args = [PDict, State],
diff --git a/lib/stdlib/src/gen_fsm.erl b/lib/stdlib/src/gen_fsm.erl
index 7d9960b912..3db8c9f4f2 100644
--- a/lib/stdlib/src/gen_fsm.erl
+++ b/lib/stdlib/src/gen_fsm.erl
@@ -113,8 +113,6 @@
start_timer/2,send_event_after/2,cancel_timer/1,
enter_loop/4, enter_loop/5, enter_loop/6, wake_hib/6]).
--export([behaviour_info/1]).
-
%% Internal exports
-export([init_it/6,
system_continue/3,
@@ -128,13 +126,38 @@
%%% Interface functions.
%%% ---------------------------------------------------
--spec behaviour_info(atom()) -> 'undefined' | [{atom(), arity()}].
-
-behaviour_info(callbacks) ->
- [{init,1},{handle_event,3},{handle_sync_event,4},{handle_info,3},
- {terminate,3},{code_change,4}];
-behaviour_info(_Other) ->
- undefined.
+-callback init(Args :: term()) ->
+ {ok, StateName :: atom(), StateData :: term()} |
+ {ok, StateName :: atom(), StateData :: term(), timeout() | hibernate} |
+ {stop, Reason :: term()} | ignore.
+-callback handle_event(Event :: term(), StateName :: atom(),
+ StateData :: term()) ->
+ {next_state, NextStateName :: atom(), NewStateData :: term()} |
+ {next_state, NextStateName :: atom(), NewStateData :: term(),
+ timeout() | hibernate} |
+ {stop, Reason :: term(), NewStateData :: term()}.
+-callback handle_sync_event(Event :: term(), From :: {pid(), Tag :: term()},
+ StateName :: atom(), StateData :: term()) ->
+ {reply, Reply :: term(), NextStateName :: atom(), NewStateData :: term()} |
+ {reply, Reply :: term(), NextStateName :: atom(), NewStateData :: term(),
+ timeout() | hibernate} |
+ {next_state, NextStateName :: atom(), NewStateData :: term()} |
+ {next_state, NextStateName :: atom(), NewStateData :: term(),
+ timeout() | hibernate} |
+ {stop, Reason :: term(), Reply :: term(), NewStateData :: term()} |
+ {stop, Reason :: term(), NewStateData :: term()}.
+-callback handle_info(Info :: term(), StateName :: atom(),
+ StateData :: term()) ->
+ {next_state, NextStateName :: atom(), NewStateData :: term()} |
+ {next_state, NextStateName :: atom(), NewStateData :: term(),
+ timeout() | hibernate} |
+ {stop, Reason :: normal | term(), NewStateData :: term()}.
+-callback terminate(Reason :: normal | shutdown | {shutdown, term()}
+ | term(), StateName :: atom(), StateData :: term()) ->
+ term().
+-callback code_change(OldVsn :: term() | {down, term()}, StateName :: atom(),
+ StateData :: term(), Extra :: term()) ->
+ {ok, NextStateName :: atom(), NewStateData :: term()}.
%%% ---------------------------------------------------
%%% Starts a generic state machine.
@@ -561,16 +584,16 @@ terminate(Reason, Name, Msg, Mod, StateName, StateData, Debug) ->
error_info(Reason, Name, Msg, StateName, StateData, Debug) ->
Reason1 =
case Reason of
- {undef,[{M,F,A}|MFAs]} ->
+ {undef,[{M,F,A,L}|MFAs]} ->
case code:is_loaded(M) of
false ->
- {'module could not be loaded',[{M,F,A}|MFAs]};
+ {'module could not be loaded',[{M,F,A,L}|MFAs]};
_ ->
case erlang:function_exported(M, F, length(A)) of
true ->
Reason;
false ->
- {'function not exported',[{M,F,A}|MFAs]}
+ {'function not exported',[{M,F,A,L}|MFAs]}
end
end;
_ ->
@@ -614,15 +637,8 @@ get_msg(Msg) -> Msg.
format_status(Opt, StatusData) ->
[PDict, SysState, Parent, Debug, [Name, StateName, StateData, Mod, _Time]] =
StatusData,
- StatusHdr = "Status for state machine",
- Header = if
- is_pid(Name) ->
- lists:concat([StatusHdr, " ", pid_to_list(Name)]);
- is_atom(Name); is_list(Name) ->
- lists:concat([StatusHdr, " ", Name]);
- true ->
- {StatusHdr, Name}
- end,
+ Header = gen:format_status_header("Status for state machine",
+ Name),
Log = sys:get_debug(log, Debug, []),
DefaultStatus = [{data, [{"StateData", StateData}]}],
Specfic =
diff --git a/lib/stdlib/src/gen_server.erl b/lib/stdlib/src/gen_server.erl
index ac81df9cab..dd0ef74f30 100644
--- a/lib/stdlib/src/gen_server.erl
+++ b/lib/stdlib/src/gen_server.erl
@@ -94,8 +94,6 @@
multi_call/2, multi_call/3, multi_call/4,
enter_loop/3, enter_loop/4, enter_loop/5, wake_hib/5]).
--export([behaviour_info/1]).
-
%% System exports
-export([system_continue/3,
system_terminate/4,
@@ -111,13 +109,32 @@
%%% API
%%%=========================================================================
--spec behaviour_info(atom()) -> 'undefined' | [{atom(), arity()}].
-
-behaviour_info(callbacks) ->
- [{init,1},{handle_call,3},{handle_cast,2},{handle_info,2},
- {terminate,2},{code_change,3}];
-behaviour_info(_Other) ->
- undefined.
+-callback init(Args :: term()) ->
+ {ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} |
+ {stop, Reason :: term()} | ignore.
+-callback handle_call(Request :: term(), From :: {pid(), Tag :: term()},
+ State :: term()) ->
+ {reply, Reply :: term(), NewState :: term()} |
+ {reply, Reply :: term(), NewState :: term(), timeout() | hibernate} |
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), timeout() | hibernate} |
+ {stop, Reason :: term(), Reply :: term(), NewState :: term()} |
+ {stop, Reason :: term(), NewState :: term()}.
+-callback handle_cast(Request :: term(), State :: term()) ->
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), timeout() | hibernate} |
+ {stop, Reason :: term(), NewState :: term()}.
+-callback handle_info(Info :: timeout() | term(), State :: term()) ->
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), timeout() | hibernate} |
+ {stop, Reason :: term(), NewState :: term()}.
+-callback terminate(Reason :: (normal | shutdown | {shutdown, term()} |
+ term()),
+ State :: term()) ->
+ term().
+-callback code_change(OldVsn :: (term() | {down, term()}), State :: term(),
+ Extra :: term()) ->
+ {ok, NewState :: term()}.
%%% -----------------------------------------------------------------
%%% Starts a generic server.
@@ -729,16 +746,16 @@ error_info(_Reason, application_controller, _Msg, _State, _Debug) ->
error_info(Reason, Name, Msg, State, Debug) ->
Reason1 =
case Reason of
- {undef,[{M,F,A}|MFAs]} ->
+ {undef,[{M,F,A,L}|MFAs]} ->
case code:is_loaded(M) of
false ->
- {'module could not be loaded',[{M,F,A}|MFAs]};
+ {'module could not be loaded',[{M,F,A,L}|MFAs]};
_ ->
case erlang:function_exported(M, F, length(A)) of
true ->
Reason;
false ->
- {'function not exported',[{M,F,A}|MFAs]}
+ {'function not exported',[{M,F,A,L}|MFAs]}
end
end;
_ ->
@@ -840,15 +857,8 @@ name_to_pid(Name) ->
%%-----------------------------------------------------------------
format_status(Opt, StatusData) ->
[PDict, SysState, Parent, Debug, [Name, State, Mod, _Time]] = StatusData,
- StatusHdr = "Status for generic server",
- Header = if
- is_pid(Name) ->
- lists:concat([StatusHdr, " ", pid_to_list(Name)]);
- is_atom(Name); is_list(Name) ->
- lists:concat([StatusHdr, " ", Name]);
- true ->
- {StatusHdr, Name}
- end,
+ Header = gen:format_status_header("Status for generic server",
+ Name),
Log = sys:get_debug(log, Debug, []),
DefaultStatus = [{data, [{"State", State}]}],
Specfic =
diff --git a/lib/stdlib/src/io.erl b/lib/stdlib/src/io.erl
index 6aeb076a0b..9f65bbfa3a 100644
--- a/lib/stdlib/src/io.erl
+++ b/lib/stdlib/src/io.erl
@@ -41,6 +41,7 @@
-type error_description() :: term(). % Whatever the io-server sends.
-type request_error() :: {'error',error_description()}.
+
%% XXX: Some uses of line() in this file may need to read erl_scan:location()
-type line() :: pos_integer().
@@ -66,12 +67,15 @@ o_request(Io, Request, Func) ->
end.
%% Put chars takes mixed *unicode* list from R13 onwards.
--spec put_chars(iodata()) -> 'ok'.
+-spec put_chars(CharData) -> 'ok' when
+ CharData :: unicode:chardata().
put_chars(Chars) ->
put_chars(default_output(), Chars).
--spec put_chars(device(), iodata()) -> 'ok'.
+-spec put_chars(IoDevice, IoData) -> 'ok' when
+ IoDevice :: device(),
+ IoData :: unicode:chardata().
put_chars(Io, Chars) ->
o_request(Io, {put_chars,unicode,Chars}, put_chars).
@@ -81,7 +85,8 @@ put_chars(Io, Chars) ->
nl() ->
nl(default_output()).
--spec nl(device()) -> 'ok'.
+-spec nl(IoDevice) -> 'ok' when
+ IoDevice :: device().
nl(Io) ->
% o_request(Io, {put_chars,io_lib:nl()}).
@@ -92,7 +97,8 @@ nl(Io) ->
columns() ->
columns(default_output()).
--spec columns(device()) -> {'ok', pos_integer()} | {'error', 'enotsup'}.
+-spec columns(IoDevice) -> {'ok', pos_integer()} | {'error', 'enotsup'} when
+ IoDevice :: device().
columns(Io) ->
case request(Io, {get_geometry,columns}) of
@@ -107,7 +113,8 @@ columns(Io) ->
rows() ->
rows(default_output()).
--spec rows(device()) -> {'ok', pos_integer()} | {'error', 'enotsup'}.
+-spec rows(IoDevice) -> {'ok', pos_integer()} | {'error', 'enotsup'} when
+ IoDevice :: device().
rows(Io) ->
case request(Io,{get_geometry,rows}) of
@@ -117,22 +124,36 @@ rows(Io) ->
{error,enotsup}
end.
--spec get_chars(prompt(), non_neg_integer()) -> iodata() | 'eof'.
+-spec get_chars(Prompt, Count) -> Data | 'eof' when
+ Prompt :: prompt(),
+ Count :: non_neg_integer(),
+ Data :: [unicode:unicode_char()] | unicode:unicode_binary().
get_chars(Prompt, N) ->
get_chars(default_input(), Prompt, N).
--spec get_chars(device(), prompt(), non_neg_integer()) -> iodata() | 'eof'.
+-spec get_chars(IoDevice, Prompt, Count) -> Data | 'eof' | {error, Reason} when
+ IoDevice :: device(),
+ Prompt :: prompt(),
+ Count :: non_neg_integer(),
+ Reason :: term(),
+ Data :: [unicode:unicode_char()] | unicode:unicode_binary().
get_chars(Io, Prompt, N) when is_integer(N), N >= 0 ->
request(Io, {get_chars,unicode,Prompt,N}).
--spec get_line(prompt()) -> iodata() | 'eof' | {'error', term()}.
+-spec get_line(Prompt) -> Data | 'eof' | {'error', Reason} when
+ Prompt :: prompt(),
+ Reason :: term(),
+ Data :: [unicode:unicode_char()] | unicode:unicode_binary().
get_line(Prompt) ->
get_line(default_input(), Prompt).
--spec get_line(device(), prompt()) -> iodata() | 'eof' | {'error', term()}.
+-spec get_line(IoDevice, Prompt) -> Data | 'eof' | {'error', term()} when
+ IoDevice :: device(),
+ Prompt :: prompt(),
+ Data :: [unicode:unicode_char()] | unicode:unicode_binary().
get_line(Io, Prompt) ->
request(Io, {get_line,unicode,Prompt}).
@@ -156,46 +177,62 @@ get_password(Io) ->
getopts() ->
getopts(default_input()).
--spec getopts(device()) -> [opt_pair()].
+-spec getopts(IoDevice) -> [opt_pair()] when
+ IoDevice :: device().
getopts(Io) ->
request(Io, getopts).
-type setopt() :: 'binary' | 'list' | opt_pair().
--spec setopts([setopt()]) -> 'ok' | {'error', term()}.
+-spec setopts(Opts) -> 'ok' | {'error', Reason} when
+ Opts :: [setopt()],
+ Reason :: term().
setopts(Opts) ->
setopts(default_input(), Opts).
--spec setopts(device(), [setopt()]) -> 'ok' | {'error', term()}.
+-spec setopts(IoDevice, Opts) -> 'ok' | {'error', Reason} when
+ IoDevice :: device(),
+ Opts :: [setopt()],
+ Reason :: term().
setopts(Io, Opts) ->
request(Io, {setopts, Opts}).
%% Writing and reading Erlang terms.
--spec write(term()) -> 'ok'.
+-spec write(Term) -> 'ok' when
+ Term :: term().
write(Term) ->
write(default_output(), Term).
--spec write(device(), term()) -> 'ok'.
+-spec write(IoDevice, Term) -> 'ok' when
+ IoDevice :: device(),
+ Term :: term().
write(Io, Term) ->
o_request(Io, {write,Term}, write).
--spec read(prompt()) ->
- {'ok', term()} | 'eof' | {'error', erl_scan:error_info()}.
+-spec read(Prompt) -> Result when
+ Prompt :: prompt(),
+ Result :: {'ok', Term :: term()}
+ | 'eof'
+ | {'error', ErrorInfo :: erl_scan:error_info()}.
% Read does not use get_until as erl_scan does not work with unicode
% XXX:PaN fixme?
read(Prompt) ->
read(default_input(), Prompt).
--spec read(device(), prompt()) ->
- {'ok', term()} | 'eof' | {'error', erl_scan:error_info()}.
+-spec read(IoDevice, Prompt) -> Result when
+ IoDevice :: device(),
+ Prompt :: prompt(),
+ Result :: {'ok', Term :: term()}
+ | 'eof'
+ | {'error', ErrorInfo :: erl_scan:error_info()}.
read(Io, Prompt) ->
case request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[1]}) of
@@ -211,9 +248,13 @@ read(Io, Prompt) ->
Other
end.
--spec read(device(), prompt(), line()) ->
- {'ok', term(), line()} | {'eof', line()} |
- {'error', erl_scan:error_info(), line()}.
+-spec read(IoDevice, Prompt, StartLine) -> Result when
+ IoDevice :: device(),
+ Prompt :: prompt(),
+ StartLine :: line(),
+ Result :: {'ok', Term :: term(), EndLine :: line()}
+ | {'eof', EndLine :: line()}
+ | {'error', ErrorInfo :: erl_scan:error_info(), ErrorLine :: line()}.
read(Io, Prompt, StartLine) when is_integer(StartLine) ->
case request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[StartLine]}) of
@@ -239,28 +280,40 @@ conv_reason(_, _Reason) -> badarg.
-type format() :: atom() | string() | binary().
--spec fwrite(format()) -> 'ok'.
+-spec fwrite(Format) -> 'ok' when
+ Format :: format().
fwrite(Format) ->
format(Format).
--spec fwrite(format(), [term()]) -> 'ok'.
+-spec fwrite(Format, Data) -> 'ok' when
+ Format :: format(),
+ Data :: [term()].
fwrite(Format, Args) ->
format(Format, Args).
--spec fwrite(device(), format(), [term()]) -> 'ok'.
+-spec fwrite(IoDevice, Format, Data) -> 'ok' when
+ IoDevice :: device(),
+ Format :: format(),
+ Data :: [term()].
fwrite(Io, Format, Args) ->
format(Io, Format, Args).
--spec fread(prompt(), format()) -> {'ok', [term()]} | 'eof' | {'error',term()}.
+-spec fread(Prompt, Format) -> Result when
+ Prompt :: prompt(),
+ Format :: format(),
+ Result :: {'ok', Terms :: [term()]} | 'eof' | {'error', What :: term()}.
fread(Prompt, Format) ->
fread(default_input(), Prompt, Format).
--spec fread(device(), prompt(), format()) ->
- {'ok', [term()]} | 'eof' | {'error',term()}.
+-spec fread(IoDevice, Prompt, Format) -> Result when
+ IoDevice :: device(),
+ Prompt :: prompt(),
+ Format :: format(),
+ Result :: {'ok', Terms :: [term()]} | 'eof' | {'error', What :: term()}.
fread(Io, Prompt, Format) ->
case request(Io, {fread,Prompt,Format}) of
@@ -270,73 +323,104 @@ fread(Io, Prompt, Format) ->
Other
end.
--spec format(format()) -> 'ok'.
+-spec format(Format) -> 'ok' when
+ Format :: format().
format(Format) ->
format(Format, []).
--spec format(format(), [term()]) -> 'ok'.
+-spec format(Format, Data) -> 'ok' when
+ Format :: format(),
+ Data :: [term()].
format(Format, Args) ->
format(default_output(), Format, Args).
--spec format(device(), format(), [term()]) -> 'ok'.
+-spec format(IoDevice, Format, Data) -> 'ok' when
+ IoDevice :: device(),
+ Format :: format(),
+ Data :: [term()].
format(Io, Format, Args) ->
o_request(Io, {format,Format,Args}, format).
%% Scanning Erlang code.
--spec scan_erl_exprs(prompt()) -> erl_scan:tokens_result() | request_error().
+-spec scan_erl_exprs(Prompt) -> Result when
+ Prompt :: prompt(),
+ Result :: erl_scan:tokens_result() | request_error().
scan_erl_exprs(Prompt) ->
scan_erl_exprs(default_input(), Prompt, 1).
--spec scan_erl_exprs(device(), prompt()) -> erl_scan:tokens_result() | request_error().
+-spec scan_erl_exprs(Device, Prompt) -> Result when
+ Device :: device(),
+ Prompt :: prompt(),
+ Result :: erl_scan:tokens_result() | request_error().
scan_erl_exprs(Io, Prompt) ->
scan_erl_exprs(Io, Prompt, 1).
--spec scan_erl_exprs(device(), prompt(), line()) -> erl_scan:tokens_result() | request_error().
+-spec scan_erl_exprs(Device, Prompt, StartLine) -> Result when
+ Device :: device(),
+ Prompt :: prompt(),
+ StartLine :: line(),
+ Result :: erl_scan:tokens_result() | request_error().
scan_erl_exprs(Io, Prompt, Pos0) ->
request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[Pos0]}).
--spec scan_erl_form(prompt()) -> erl_scan:tokens_result() | request_error().
+-spec scan_erl_form(Prompt) -> Result when
+ Prompt :: prompt(),
+ Result :: erl_scan:tokens_result() | request_error().
scan_erl_form(Prompt) ->
scan_erl_form(default_input(), Prompt, 1).
--spec scan_erl_form(device(), prompt()) -> erl_scan:tokens_result() | request_error().
+-spec scan_erl_form(IoDevice, Prompt) -> Result when
+ IoDevice :: device(),
+ Prompt :: prompt(),
+ Result :: erl_scan:tokens_result() | request_error().
scan_erl_form(Io, Prompt) ->
scan_erl_form(Io, Prompt, 1).
--spec scan_erl_form(device(), prompt(), line()) -> erl_scan:tokens_result() | request_error().
+-spec scan_erl_form(IoDevice, Prompt, StartLine) -> Result when
+ IoDevice :: device(),
+ Prompt :: prompt(),
+ StartLine :: line(),
+ Result :: erl_scan:tokens_result() | request_error().
scan_erl_form(Io, Prompt, Pos0) ->
request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[Pos0]}).
%% Parsing Erlang code.
--type erl_parse_expr_list() :: [_]. %% XXX: should be imported from erl_parse
-
--type parse_ret() :: {'ok', erl_parse_expr_list(), line()}
- | {'eof', line()}
- | {'error', erl_scan:error_info(), line()}
+-type parse_ret() :: {'ok', ExprList :: erl_parse:abstract_expr(), EndLine :: line()}
+ | {'eof', EndLine :: line()}
+ | {'error', ErrorInfo :: erl_scan:error_info(), ErrorLine :: line()}
| request_error().
--spec parse_erl_exprs(prompt()) -> parse_ret().
+-spec parse_erl_exprs(Prompt) -> Result when
+ Prompt :: prompt(),
+ Result :: parse_ret().
parse_erl_exprs(Prompt) ->
parse_erl_exprs(default_input(), Prompt, 1).
--spec parse_erl_exprs(device(), prompt()) -> parse_ret().
+-spec parse_erl_exprs(IoDevice, Prompt) -> Result when
+ IoDevice :: device(),
+ Prompt :: prompt(),
+ Result :: parse_ret().
parse_erl_exprs(Io, Prompt) ->
parse_erl_exprs(Io, Prompt, 1).
--spec parse_erl_exprs(device(), prompt(), line()) -> parse_ret().
+-spec parse_erl_exprs(IoDevice, Prompt, StartLine) -> Result when
+ IoDevice :: device(),
+ Prompt :: prompt(),
+ StartLine :: line(),
+ Result :: parse_ret().
parse_erl_exprs(Io, Prompt, Pos0) ->
case request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[Pos0]}) of
@@ -349,24 +433,31 @@ parse_erl_exprs(Io, Prompt, Pos0) ->
Other
end.
--type erl_parse_absform() :: _. %% XXX: should be imported from erl_parse
-
--type parse_form_ret() :: {'ok', erl_parse_absform(), line()}
- | {'eof', line()}
- | {'error', erl_scan:error_info(), line()}
+-type parse_form_ret() :: {'ok', AbsForm :: erl_parse:abstract_form(), EndLine :: line()}
+ | {'eof', EndLine :: line()}
+ | {'error', ErrorInfo :: erl_scan:error_info(), ErrorLine :: line()}
| request_error().
--spec parse_erl_form(prompt()) -> parse_form_ret().
+-spec parse_erl_form(Prompt) -> Result when
+ Prompt :: prompt(),
+ Result :: parse_form_ret().
parse_erl_form(Prompt) ->
parse_erl_form(default_input(), Prompt, 1).
--spec parse_erl_form(device(), prompt()) -> parse_form_ret().
+-spec parse_erl_form(IoDevice, Prompt) -> Result when
+ IoDevice :: device(),
+ Prompt :: prompt(),
+ Result :: parse_form_ret().
parse_erl_form(Io, Prompt) ->
parse_erl_form(Io, Prompt, 1).
--spec parse_erl_form(device(), prompt(), line()) -> parse_form_ret().
+-spec parse_erl_form(IoDevice, Prompt, StartLine) -> Result when
+ IoDevice :: device(),
+ Prompt :: prompt(),
+ StartLine :: line(),
+ Result :: parse_form_ret().
parse_erl_form(Io, Prompt, Pos0) ->
case request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[Pos0]}) of
diff --git a/lib/stdlib/src/io_lib.erl b/lib/stdlib/src/io_lib.erl
index 4ca9d079b7..0252cdf742 100644
--- a/lib/stdlib/src/io_lib.erl
+++ b/lib/stdlib/src/io_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,35 +75,57 @@
collect_line/2, collect_line/3, collect_line/4,
get_until/3, get_until/4]).
--export_type([chars/0]).
+-export_type([chars/0, continuation/0]).
%%----------------------------------------------------------------------
- %% XXX: overapproximates a deep list of (unicode) characters
--type chars() :: [_].
+-type chars() :: [char() | chars()].
-type depth() :: -1 | non_neg_integer().
+-opaque continuation() :: {_, _, _, _}. % XXX: refine
+
%%----------------------------------------------------------------------
%% Interface calls to sub-modules.
--spec fwrite(io:format(), [term()]) -> chars().
+-spec fwrite(Format, Data) -> chars() | UnicodeList when
+ Format :: io:format(),
+ Data :: [term()],
+ UnicodeList :: [unicode:unicode_char()],
+ Data :: [term()].
fwrite(Format, Args) ->
format(Format, Args).
--spec fread(string(), string()) -> io_lib_fread:fread_2_ret().
+-spec fread(Format, String) -> Result when
+ Format :: string(),
+ String :: string(),
+ Result :: {'ok', InputList :: [term()], LeftOverChars :: string()}
+ | {'more', RestFormat :: string(),
+ Nchars :: non_neg_integer(),
+ InputStack :: chars()}
+ | {'error', What :: term()}.
fread(Chars, Format) ->
io_lib_fread:fread(Chars, Format).
--spec fread(io_lib_fread:continuation(), string(), string()) ->
- io_lib_fread:fread_3_ret().
+-spec fread(Continuation, CharSpec, Format) -> Return when
+ Continuation :: continuation() | [],
+ CharSpec :: string() | eof,
+ Format :: string(),
+ Return :: {'more', Continuation1 :: continuation()}
+ | {'done', Result, LeftOverChars :: string()},
+ Result :: {'ok', InputList :: [term()]}
+ | 'eof'
+ | {'error', What :: term()}.
fread(Cont, Chars, Format) ->
io_lib_fread:fread(Cont, Chars, Format).
--spec format(io:format(), [term()]) -> chars().
+-spec format(Format, Data) -> chars() | UnicodeList when
+ Format :: io:format(),
+ Data :: [term()],
+ UnicodeList :: [unicode:unicode_char()].
format(Format, Args) ->
case catch io_lib_format:fwrite(Format, Args) of
@@ -113,17 +135,24 @@ format(Format, Args) ->
Other
end.
--spec print(term()) -> chars().
+-spec print(Term) -> chars() when
+ Term :: term().
print(Term) ->
io_lib_pretty:print(Term).
--spec print(term(), non_neg_integer(), non_neg_integer(), depth()) -> chars().
+-spec print(Term, Column, LineLength, Depth) -> chars() when
+ Term :: term(),
+ Column :: non_neg_integer(),
+ LineLength :: non_neg_integer(),
+ Depth :: depth().
print(Term, Column, LineLength, Depth) ->
io_lib_pretty:print(Term, Column, LineLength, Depth).
--spec indentation(string(), integer()) -> integer().
+-spec indentation(String, StartIndent) -> integer() when
+ String :: string(),
+ StartIndent :: integer().
indentation(Chars, Current) ->
io_lib_format:indentation(Chars, Current).
@@ -158,7 +187,8 @@ format_prompt(Format, Args) ->
%% Return a (non-flattened) list of characters giving a printed
%% representation of the term. write/3 is for backward compatibility.
--spec write(term()) -> chars().
+-spec write(Term) -> chars() when
+ Term :: term().
write(Term) -> write(Term, -1).
@@ -169,7 +199,9 @@ write(Term, D, true) ->
write(Term, D, false) ->
write(Term, D).
--spec write(term(), depth()) -> chars().
+-spec write(Term, Depth) -> chars() when
+ Term :: term(),
+ Depth :: depth().
write(_Term, 0) -> "...";
write(Term, _D) when is_integer(Term) -> integer_to_list(Term);
@@ -234,7 +266,8 @@ write_binary_body(B, _D) ->
%% write_atom(Atom) -> [Char]
%% Generate the list of characters needed to print an atom.
--spec write_atom(atom()) -> chars().
+-spec write_atom(Atom) -> chars() when
+ Atom :: atom().
write_atom(Atom) ->
Chars = atom_to_list(Atom),
@@ -283,7 +316,8 @@ name_char(_) -> false.
%% write_string([Char]) -> [Char]
%% Generate the list of characters needed to print a string.
--spec write_string(string()) -> chars().
+-spec write_string(String) -> chars() when
+ String :: string().
write_string(S) ->
write_string(S, $"). %"
@@ -330,7 +364,8 @@ string_char(_,C, _, Tail) when C < $\240-> %Other control characters.
%% Generate the list of characters needed to print a character constant.
%% Must special case SPACE, $\s, here.
--spec write_char(char()) -> chars().
+-spec write_char(Char) -> chars() when
+ Char :: char().
write_char($\s) -> "$\\s"; %Must special case this.
write_char(C) when is_integer(C), C >= $\000, C =< $\377 ->
@@ -346,7 +381,8 @@ write_unicode_char(Uni) ->
%% Return true if CharList is a (possibly deep) list of characters, else
%% false.
--spec char_list(term()) -> boolean().
+-spec char_list(Term) -> boolean() when
+ Term :: term().
char_list([C|Cs]) when is_integer(C), C >= $\000, C =< $\377 ->
char_list(Cs);
@@ -362,7 +398,8 @@ unicode_char_list([C|Cs]) when is_integer(C), C >= 0, C < 16#D800;
unicode_char_list([]) -> true;
unicode_char_list(_) -> false. %Everything else is false
--spec deep_char_list(term()) -> boolean().
+-spec deep_char_list(Term) -> boolean() when
+ Term :: term().
deep_char_list(Cs) ->
deep_char_list(Cs, []).
@@ -399,7 +436,8 @@ deep_unicode_char_list(_, _More) -> %Everything else is false
%% Return true if CharList is a list of printable characters, else
%% false.
--spec printable_list(term()) -> boolean().
+-spec printable_list(Term) -> boolean() when
+ Term :: term().
printable_list([C|Cs]) when is_integer(C), C >= $\040, C =< $\176 ->
printable_list(Cs);
diff --git a/lib/stdlib/src/io_lib_fread.erl b/lib/stdlib/src/io_lib_fread.erl
index 33553692bc..ded1346097 100644
--- a/lib/stdlib/src/io_lib_fread.erl
+++ b/lib/stdlib/src/io_lib_fread.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,27 +22,11 @@
-export([fread/2,fread/3]).
--export_type([continuation/0, fread_2_ret/0, fread_3_ret/0]).
-
-import(lists, [reverse/1,reverse/2]).
-%%-----------------------------------------------------------------------
-%% Local types
-%%-----------------------------------------------------------------------
-
--type done_arg2() :: {'ok', io_lib:chars()} | 'eof' | {'error', term()}.
-
-%%-----------------------------------------------------------------------
-%% Types also used in other files
-%%-----------------------------------------------------------------------
-
--type continuation() :: [] | {_, _, _, _}. % XXX: refine
-
--type fread_2_ret() :: {'ok', io_lib:chars(), string()}
- | {'more', string(), non_neg_integer(), io_lib:chars()}
- | {'error', term()}.
--type fread_3_ret() :: {'more', continuation()}
- | {'done', done_arg2(), string()}.
+-define(is_whitespace(C),
+ ((C) =:= $\s orelse (C) =:= $\t
+ orelse (C) =:= $\r orelse (C) =:= $\n)).
%%-----------------------------------------------------------------------
@@ -51,7 +35,15 @@
%% repeatedly collects lines and calls fread/2 to format the input until
%% all the format string has been used. And it counts the characters.
--spec fread(io_lib_fread:continuation(), string(), string()) -> fread_3_ret().
+-spec fread(Continuation, String, Format) -> Return when
+ Continuation :: io_lib:continuation() | [],
+ String :: string(),
+ Format :: string(),
+ Return :: {'more', Continuation1 :: io_lib:continuation()}
+ | {'done', Result, LeftOverChars :: string()},
+ Result :: {'ok', InputList :: io_lib:chars()}
+ | 'eof'
+ | {'error', What :: term()}.
fread([], Chars, Format) ->
%%io:format("FREAD: ~w `~s'~n", [Format,Chars]),
@@ -106,36 +98,39 @@ fread_line(Format0, Line, N0, Results0, More, Newline) ->
%% WHITE Skip white space
%% X Literal X
--spec fread(string(), string()) -> fread_2_ret().
+-spec fread(Format, String) -> Result when
+ Format :: string(),
+ String :: string(),
+ Result :: {'ok', InputList :: io_lib:chars(), LeftOverChars :: string()}
+ | {'more', RestFormat :: string(),
+ Nchars :: non_neg_integer(),
+ InputStack :: io_lib:chars()}
+ | {'error', What :: term()}.
fread(Format, Line) ->
fread(Format, Line, 0, []).
-fread([$~|Format0], Line, N, Results) ->
+fread([$~|Format0]=AllFormat, Line, N, Results) ->
{Format,F,Sup,Unicode} = fread_field(Format0),
- fread1(Format, F, Sup, Unicode, Line, N, Results, Format0);
-fread([$\s|Format], Line, N, Results) ->
- fread_skip_white(Format, Line, N, Results);
-fread([$\t|Format], Line, N, Results) ->
- fread_skip_white(Format, Line, N, Results);
-fread([$\r|Format], Line, N, Results) ->
- fread_skip_white(Format, Line, N, Results);
-fread([$\n|Format], Line, N, Results) ->
+ fread1(Format, F, Sup, Unicode, Line, N, Results, AllFormat);
+fread([C|Format], Line, N, Results) when ?is_whitespace(C) ->
fread_skip_white(Format, Line, N, Results);
fread([C|Format], [C|Line], N, Results) ->
fread(Format, Line, N+1, Results);
fread([_F|_Format], [_C|_Line], _N, _Results) ->
fread_error(input);
+fread([_|_]=Format, [], N, Results) ->
+ {more,Format,N,Results};
+fread([_|_], eof, 0, []) ->
+ %% This is at start of input so no error.
+ eof;
+fread([_|_], eof, _N, _Results) ->
+ %% This is an error as there is no more input.
+ fread_error(input);
fread([], Line, _N, Results) ->
{ok,reverse(Results),Line}.
-fread_skip_white(Format, [$\s|Line], N, Results) ->
- fread_skip_white(Format, Line, N+1, Results);
-fread_skip_white(Format, [$\t|Line], N, Results) ->
- fread_skip_white(Format, Line, N+1, Results);
-fread_skip_white(Format, [$\r|Line], N, Results) ->
- fread_skip_white(Format, Line, N+1, Results);
-fread_skip_white(Format, [$\n|Line], N, Results) ->
+fread_skip_white(Format, [C|Line], N, Results) when ?is_whitespace(C) ->
fread_skip_white(Format, Line, N+1, Results);
fread_skip_white(Format, Line, N, Results) ->
fread(Format, Line, N, Results).
@@ -171,9 +166,9 @@ fread1([$l|Format], _F, Sup, _U, Line, N, Res, _AllFormat) ->
fread(Format, Line, N, fread_result(Sup, N, Res));
fread1(_Format, _F, _Sup, _U, [], N, Res, AllFormat) ->
%% Need more input here.
- {more,[$~|AllFormat],N,Res};
-fread1(_Format, _F, _Sup, _U, eof, _N, [], _AllFormat) ->
- %% This is at start of format string so no error.
+ {more,AllFormat,N,Res};
+fread1(_Format, _F, _Sup, _U, eof, 0, [], _AllFormat) ->
+ %% This is at start of input so no error.
eof;
fread1(_Format, _F, _Sup, _U, eof, _N, _Res, _AllFormat) ->
%% This is an error as there is no more input.
@@ -391,26 +386,16 @@ fread_string_cs(Line0, N0, true) ->
%% fread_digits(Line, N, Base, Characters)
%% Read segments of things, return "thing" characters in reverse order.
-fread_skip_white([$\s|Line]) -> fread_skip_white(Line);
-fread_skip_white([$\t|Line]) -> fread_skip_white(Line);
-fread_skip_white([$\r|Line]) -> fread_skip_white(Line);
-fread_skip_white([$\n|Line]) -> fread_skip_white(Line);
+fread_skip_white([C|Line]) when ?is_whitespace(C) ->
+ fread_skip_white(Line);
fread_skip_white(Line) -> Line.
-fread_skip_white([$\s|Line], N) ->
- fread_skip_white(Line, N+1);
-fread_skip_white([$\t|Line], N) ->
- fread_skip_white(Line, N+1);
-fread_skip_white([$\r|Line], N) ->
- fread_skip_white(Line, N+1);
-fread_skip_white([$\n|Line], N) ->
+fread_skip_white([C|Line], N) when ?is_whitespace(C) ->
fread_skip_white(Line, N+1);
fread_skip_white(Line, N) -> {Line,N}.
-fread_skip_latin1_nonwhite([$\s|Line], N, Cs) -> {[$\s|Line],N,Cs};
-fread_skip_latin1_nonwhite([$\t|Line], N, Cs) -> {[$\t|Line],N,Cs};
-fread_skip_latin1_nonwhite([$\r|Line], N, Cs) -> {[$\r|Line],N,Cs};
-fread_skip_latin1_nonwhite([$\n|Line], N, Cs) -> {[$\n|Line],N,Cs};
+fread_skip_latin1_nonwhite([C|Line], N, Cs) when ?is_whitespace(C) ->
+ {[C|Line],N,Cs};
fread_skip_latin1_nonwhite([C|Line], N, []) when C > 255 ->
{[C|Line],N,error};
fread_skip_latin1_nonwhite([C|Line], N, Cs) when C > 255 ->
@@ -419,10 +404,8 @@ fread_skip_latin1_nonwhite([C|Line], N, Cs) ->
fread_skip_latin1_nonwhite(Line, N+1, [C|Cs]);
fread_skip_latin1_nonwhite([], N, Cs) -> {[],N,Cs}.
-fread_skip_nonwhite([$\s|Line], N, Cs) -> {[$\s|Line],N,Cs};
-fread_skip_nonwhite([$\t|Line], N, Cs) -> {[$\t|Line],N,Cs};
-fread_skip_nonwhite([$\r|Line], N, Cs) -> {[$\r|Line],N,Cs};
-fread_skip_nonwhite([$\n|Line], N, Cs) -> {[$\n|Line],N,Cs};
+fread_skip_nonwhite([C|Line], N, Cs) when ?is_whitespace(C) ->
+ {[C|Line],N,Cs};
fread_skip_nonwhite([C|Line], N, Cs) ->
fread_skip_nonwhite(Line, N+1, [C|Cs]);
fread_skip_nonwhite([], N, Cs) -> {[],N,Cs}.
diff --git a/lib/stdlib/src/lib.erl b/lib/stdlib/src/lib.erl
index b2cfb00de9..314fd60903 100644
--- a/lib/stdlib/src/lib.erl
+++ b/lib/stdlib/src/lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,7 +38,9 @@ flush_receive() ->
%%
%% Functions for doing standard system format i/o.
%%
--spec error_message(atom() | string() | binary(), [term()]) -> 'ok'.
+-spec error_message(Format, Args) -> 'ok' when
+ Format :: io:format(),
+ Args :: [term()].
error_message(Format, Args) ->
io:format(<<"** ~s **\n">>, [io_lib:format(Format, Args)]).
@@ -55,17 +57,23 @@ progname() ->
no_prog_name
end.
--spec nonl(string()) -> string().
+-spec nonl(String1) -> String2 when
+ String1 :: string(),
+ String2 :: string().
nonl([10]) -> [];
nonl([]) -> [];
nonl([H|T]) -> [H|nonl(T)].
--spec send(pid() | atom() | {atom(), node()}, term()) -> term().
+-spec send(To, Msg) -> Msg when
+ To :: pid() | atom() | {atom(), node()},
+ Msg :: term().
send(To, Msg) -> To ! Msg.
--spec sendw(pid() | atom() | {atom(), node()}, term()) -> term().
+-spec sendw(To, Msg) -> Msg when
+ To :: pid() | atom() | {atom(), node()},
+ Msg :: term().
sendw(To, Msg) ->
To ! {self(), Msg},
@@ -89,7 +97,7 @@ eval_str(Str) when is_list(Str) ->
true ->
case erl_parse:parse_exprs(Toks) of
{ok, Exprs} ->
- case catch erl_eval:exprs(Exprs, []) of
+ case catch erl_eval:exprs(Exprs, erl_eval:new_bindings()) of
{value, Val, _} ->
{ok, Val};
Other ->
@@ -165,12 +173,12 @@ format_fun(Fun) when is_function(Fun) ->
analyze_exception(error, Term, Stack) ->
case {is_stacktrace(Stack), Stack, Term} of
- {true, [{_M,_F,As}=MFA|MFAs], function_clause} when is_list(As) ->
- {Term,[MFA],MFAs};
- {true, [{shell,F,A}], function_clause} when is_integer(A) ->
+ {true, [{_,_,As,_}=MFAL|MFAs], function_clause} when is_list(As) ->
+ {Term,[MFAL],MFAs};
+ {true, [{shell,F,A,_}], function_clause} when is_integer(A) ->
{Term, [{F,A}], []};
- {true, [{_M,_F,_AorAs}=MFA|MFAs], undef} ->
- {Term,[MFA],MFAs};
+ {true, [{_,_,_,_}=MFAL|MFAs], undef} ->
+ {Term,[MFAL],MFAs};
{true, _, _} ->
{Term,[],Stack};
{false, _, _} ->
@@ -186,9 +194,11 @@ analyze_exception(_Class, Term, Stack) ->
is_stacktrace([]) ->
true;
-is_stacktrace([{M,F,A}|Fs]) when is_atom(M), is_atom(F), is_integer(A) ->
+is_stacktrace([{M,F,A,I}|Fs])
+ when is_atom(M), is_atom(F), is_integer(A), is_list(I) ->
is_stacktrace(Fs);
-is_stacktrace([{M,F,As}|Fs]) when is_atom(M), is_atom(F), length(As) >= 0 ->
+is_stacktrace([{M,F,As,I}|Fs])
+ when is_atom(M), is_atom(F), length(As) >= 0, is_list(I) ->
is_stacktrace(Fs);
is_stacktrace(_) ->
false.
@@ -217,9 +227,9 @@ explain_reason(function_clause, error, [{F,A}], _PF, _S) ->
%% Shell commands
FAs = io_lib:fwrite(<<"~w/~w">>, [F, A]),
[<<"no function clause matching call to ">> | FAs];
-explain_reason(function_clause, error=Cl, [{M,F,As}], PF, S) ->
+explain_reason(function_clause, error=Cl, [{M,F,As,Loc}], PF, S) ->
Str = <<"no function clause matching ">>,
- format_errstr_call(Str, Cl, {M,F}, As, PF, S);
+ [format_errstr_call(Str, Cl, {M,F}, As, PF, S),$\s|location(Loc)];
explain_reason(if_clause, error, [], _PF, _S) ->
<<"no true branch found when evaluating an if expression">>;
explain_reason(noproc, error, [], _PF, _S) ->
@@ -234,11 +244,11 @@ explain_reason({try_clause,V}, error=Cl, [], PF, S) ->
%% "there is no try clause with a true guard sequence and a
%% pattern matching..."
format_value(V, <<"no try clause matching ">>, Cl, PF, S);
-explain_reason(undef, error, [{M,F,A}], _PF, _S) ->
+explain_reason(undef, error, [{M,F,A,_}], _PF, _S) ->
%% Only the arity is displayed, not the arguments, if there are any.
io_lib:fwrite(<<"undefined function ~s">>,
[mfa_to_string(M, F, n_args(A))]);
-explain_reason({shell_undef,F,A}, error, [], _PF, _S) ->
+explain_reason({shell_undef,F,A,_}, error, [], _PF, _S) ->
%% Give nicer reports for undefined shell functions
%% (but not when the user actively calls shell_default:F(...)).
io_lib:fwrite(<<"undefined shell command ~s/~w">>, [F, n_args(A)]);
@@ -284,17 +294,19 @@ argss(I) ->
io_lib:fwrite(<<"~w arguments">>, [I]).
format_stacktrace1(S0, Stack0, PF, SF) ->
- Stack1 = lists:dropwhile(fun({M,F,A}) -> SF(M, F, A)
+ Stack1 = lists:dropwhile(fun({M,F,A,_}) -> SF(M, F, A)
end, lists:reverse(Stack0)),
S = [" " | S0],
Stack = lists:reverse(Stack1),
format_stacktrace2(S, Stack, 1, PF).
-format_stacktrace2(S, [{M,F,A}|Fs], N, PF) when is_integer(A) ->
- [io_lib:fwrite(<<"~s~s ~s">>,
- [sep(N, S), origin(N, M, F, A), mfa_to_string(M, F, A)])
+format_stacktrace2(S, [{M,F,A,L}|Fs], N, PF) when is_integer(A) ->
+ [io_lib:fwrite(<<"~s~s ~s ~s">>,
+ [sep(N, S), origin(N, M, F, A),
+ mfa_to_string(M, F, A),
+ location(L)])
| format_stacktrace2(S, Fs, N + 1, PF)];
-format_stacktrace2(S, [{M,F,As}|Fs], N, PF) when is_list(As) ->
+format_stacktrace2(S, [{M,F,As,_}|Fs], N, PF) when is_list(As) ->
A = length(As),
CalledAs = [S,<<" called as ">>],
C = format_call("", CalledAs, {M,F}, As, PF),
@@ -305,6 +317,16 @@ format_stacktrace2(S, [{M,F,As}|Fs], N, PF) when is_list(As) ->
format_stacktrace2(_S, [], _N, _PF) ->
"".
+location(L) ->
+ File = proplists:get_value(file, L),
+ Line = proplists:get_value(line, L),
+ if
+ File =/= undefined, Line =/= undefined ->
+ io_lib:format("(~s, line ~w)", [File, Line]);
+ true ->
+ ""
+ end.
+
sep(1, S) -> S;
sep(_, S) -> [$\n | S].
diff --git a/lib/stdlib/src/lists.erl b/lib/stdlib/src/lists.erl
index c669c1f7c1..e73c087753 100644
--- a/lib/stdlib/src/lists.erl
+++ b/lib/stdlib/src/lists.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -54,13 +54,21 @@
%% append(X, Y) appends lists X and Y
--spec append([T], [T]) -> [T].
+-spec append(List1, List2) -> List3 when
+ List1 :: [T],
+ List2 :: [T],
+ List3 :: [T],
+ T :: term().
append(L1, L2) -> L1 ++ L2.
%% append(L) appends the list of lists L
--spec append([[T]]) -> [T].
+-spec append(ListOfLists) -> List1 when
+ ListOfLists :: [List],
+ List :: [T],
+ List1 :: [T],
+ T :: term().
append([E]) -> E;
append([H|T]) -> H ++ append(T);
@@ -68,13 +76,20 @@ append([]) -> [].
%% subtract(List1, List2) subtract elements in List2 form List1.
--spec subtract([T], [T]) -> [T].
+-spec subtract(List1, List2) -> List3 when
+ List1 :: [T],
+ List2 :: [T],
+ List3 :: [T],
+ T :: term().
subtract(L1, L2) -> L1 -- L2.
%% reverse(L) reverse all elements in the list L. Is now a BIF!
--spec reverse([T]) -> [T].
+-spec reverse(List1) -> List2 when
+ List1 :: [T],
+ List2 :: [T],
+ T :: term().
reverse([] = L) ->
L;
@@ -93,13 +108,21 @@ reverse([A, B | L]) ->
%% nth(N, L) returns the N`th element of the list L
%% nthtail(N, L) returns the N`th tail of the list L
--spec nth(pos_integer(), [T,...]) -> T.
+-spec nth(N, List) -> Elem when
+ N :: pos_integer(),
+ List :: [T,...],
+ Elem :: T,
+ T :: term().
nth(1, [H|_]) -> H;
nth(N, [_|T]) when N > 1 ->
nth(N - 1, T).
--spec nthtail(non_neg_integer(), [T,...]) -> [T].
+-spec nthtail(N, List) -> Tail when
+ N :: non_neg_integer(),
+ List :: [T,...],
+ Tail :: [T],
+ T :: term().
nthtail(1, [_|T]) -> T;
nthtail(N, [_|T]) when N > 1 ->
@@ -108,7 +131,10 @@ nthtail(0, L) when is_list(L) -> L.
%% prefix(Prefix, List) -> (true | false)
--spec prefix([T], [T]) -> boolean().
+-spec prefix(List1, List2) -> boolean() when
+ List1 :: [T],
+ List2 :: [T],
+ T :: term().
prefix([X|PreTail], [X|Tail]) ->
prefix(PreTail, Tail);
@@ -117,7 +143,10 @@ prefix([_|_], List) when is_list(List) -> false.
%% suffix(Suffix, List) -> (true | false)
--spec suffix([T], [T]) -> boolean().
+-spec suffix(List1, List2) -> boolean() when
+ List1 :: [T],
+ List2 :: [T],
+ T :: term().
suffix(Suffix, List) ->
Delta = length(List) - length(Suffix),
@@ -125,7 +154,10 @@ suffix(Suffix, List) ->
%% last(List) returns the last element in a list.
--spec last([T,...]) -> T.
+-spec last(List) -> Last when
+ List :: [T,...],
+ Last :: T,
+ T :: term().
last([E|Es]) -> last(E, Es).
@@ -137,7 +169,10 @@ last(E, []) -> E.
%% returns the sequence Min..Max
%% Min <= Max and Min and Max must be integers
--spec seq(integer(), integer()) -> [integer()].
+-spec seq(From, To) -> Seq when
+ From :: integer(),
+ To :: integer(),
+ Seq :: [integer()].
seq(First, Last)
when is_integer(First), is_integer(Last), First-1 =< Last ->
@@ -152,7 +187,11 @@ seq_loop(1, X, L) ->
seq_loop(0, _, L) ->
L.
--spec seq(integer(), integer(), integer()) -> [integer()].
+-spec seq(From, To, Incr) -> Seq when
+ From :: integer(),
+ To :: integer(),
+ Incr :: integer(),
+ Seq :: [integer()].
seq(First, Last, Inc)
when is_integer(First), is_integer(Last), is_integer(Inc) ->
@@ -178,7 +217,8 @@ seq_loop(0, _, _, L) ->
%% sum(L) returns the sum of the elements in L
--spec sum([number()]) -> number().
+-spec sum(List) -> number() when
+ List :: [number()].
sum(L) -> sum(L, 0).
@@ -188,7 +228,11 @@ sum([], Sum) -> Sum.
%% duplicate(N, X) -> [X,X,X,.....,X] (N times)
%% return N copies of X
--spec duplicate(non_neg_integer(), T) -> [T].
+-spec duplicate(N, Elem) -> List when
+ N :: non_neg_integer(),
+ Elem :: T,
+ List :: [T],
+ T :: term().
duplicate(N, X) when is_integer(N), N >= 0 -> duplicate(N, X, []).
@@ -197,7 +241,10 @@ duplicate(N, X, L) -> duplicate(N-1, X, [X|L]).
%% min(L) -> returns the minimum element of the list L
--spec min([T,...]) -> T.
+-spec min(List) -> Min when
+ List :: [T,...],
+ Min :: T,
+ T :: term().
min([H|T]) -> min(T, H).
@@ -207,7 +254,10 @@ min([], Min) -> Min.
%% max(L) -> returns the maximum element of the list L
--spec max([T,...]) -> T.
+-spec max(List) -> Max when
+ List :: [T,...],
+ Max :: T,
+ T :: term().
max([H|T]) -> max(T, H).
@@ -218,12 +268,21 @@ max([], Max) -> Max.
%% sublist(List, Start, Length)
%% Returns the sub-list starting at Start of length Length.
--spec sublist([T], pos_integer(), non_neg_integer()) -> [T].
+-spec sublist(List1, Start, Len) -> List2 when
+ List1 :: [T],
+ List2 :: [T],
+ Start :: pos_integer(),
+ Len :: non_neg_integer(),
+ T :: term().
sublist(List, S, L) when is_integer(L), L >= 0 ->
sublist(nthtail(S-1, List), L).
--spec sublist([T], non_neg_integer()) -> [T].
+-spec sublist(List1, Len) -> List2 when
+ List1 :: [T],
+ List2 :: [T],
+ Len :: non_neg_integer(),
+ T :: term().
sublist(List, L) when is_integer(L), is_list(List) ->
sublist_2(List, L).
@@ -238,7 +297,11 @@ sublist_2(List, L) when is_list(List), L > 0 ->
%% delete(Item, List) -> List'
%% Delete the first occurrence of Item from the list L.
--spec delete(T, [T]) -> [T].
+-spec delete(Elem, List1) -> List2 when
+ Elem :: T,
+ List1 :: [T],
+ List2 :: [T],
+ T :: term().
delete(Item, [Item|Rest]) -> Rest;
delete(Item, [H|Rest]) ->
@@ -248,7 +311,12 @@ delete(_, []) -> [].
%% Return [{X0, Y0}, {X1, Y1}, ..., {Xn, Yn}] for lists [X0, X1, ...,
%% Xn] and [Y0, Y1, ..., Yn].
--spec zip([A], [B]) -> [{A, B}].
+-spec zip(List1, List2) -> List3 when
+ List1 :: [A],
+ List2 :: [B],
+ List3 :: [{A, B}],
+ A :: term(),
+ B :: term().
zip([X | Xs], [Y | Ys]) -> [{X, Y} | zip(Xs, Ys)];
zip([], []) -> [].
@@ -256,7 +324,12 @@ zip([], []) -> [].
%% Return {[X0, X1, ..., Xn], [Y0, Y1, ..., Yn]}, for a list [{X0, Y0},
%% {X1, Y1}, ..., {Xn, Yn}].
--spec unzip([{A, B}]) -> {[A], [B]}.
+-spec unzip(List1) -> {List2, List3} when
+ List1 :: [{A, B}],
+ List2 :: [A],
+ List3 :: [B],
+ A :: term(),
+ B :: term().
unzip(Ts) -> unzip(Ts, [], []).
@@ -266,7 +339,14 @@ unzip([], Xs, Ys) -> {reverse(Xs), reverse(Ys)}.
%% Return [{X0, Y0, Z0}, {X1, Y1, Z1}, ..., {Xn, Yn, Zn}] for lists [X0,
%% X1, ..., Xn], [Y0, Y1, ..., Yn] and [Z0, Z1, ..., Zn].
--spec zip3([A], [B], [C]) -> [{A, B, C}].
+-spec zip3(List1, List2, List3) -> List4 when
+ List1 :: [A],
+ List2 :: [B],
+ List3 :: [C],
+ List4 :: [{A, B, C}],
+ A :: term(),
+ B :: term(),
+ C :: term().
zip3([X | Xs], [Y | Ys], [Z | Zs]) -> [{X, Y, Z} | zip3(Xs, Ys, Zs)];
zip3([], [], []) -> [].
@@ -274,7 +354,14 @@ zip3([], [], []) -> [].
%% Return {[X0, X1, ..., Xn], [Y0, Y1, ..., Yn], [Z0, Z1, ..., Zn]}, for
%% a list [{X0, Y0, Z0}, {X1, Y1, Z1}, ..., {Xn, Yn, Zn}].
--spec unzip3([{A, B, C}]) -> {[A], [B], [C]}.
+-spec unzip3(List1) -> {List2, List3, List4} when
+ List1 :: [{A, B, C}],
+ List2 :: [A],
+ List3 :: [B],
+ List4 :: [C],
+ A :: term(),
+ B :: term(),
+ C :: term().
unzip3(Ts) -> unzip3(Ts, [], [], []).
@@ -286,7 +373,14 @@ unzip3([], Xs, Ys, Zs) ->
%% Return [F(X0, Y0), F(X1, Y1), ..., F(Xn, Yn)] for lists [X0, X1, ...,
%% Xn] and [Y0, Y1, ..., Yn].
--spec zipwith(fun((X, Y) -> R), [X], [Y]) -> [R].
+-spec zipwith(Combine, List1, List2) -> List3 when
+ Combine :: fun((X, Y) -> T),
+ List1 :: [X],
+ List2 :: [Y],
+ List3 :: [T],
+ X :: term(),
+ Y :: term(),
+ T :: term().
zipwith(F, [X | Xs], [Y | Ys]) -> [F(X, Y) | zipwith(F, Xs, Ys)];
zipwith(F, [], []) when is_function(F, 2) -> [].
@@ -294,7 +388,16 @@ zipwith(F, [], []) when is_function(F, 2) -> [].
%% Return [F(X0, Y0, Z0), F(X1, Y1, Z1), ..., F(Xn, Yn, Zn)] for lists
%% [X0, X1, ..., Xn], [Y0, Y1, ..., Yn] and [Z0, Z1, ..., Zn].
--spec zipwith3(fun((X, Y, Z) -> R), [X], [Y], [Z]) -> [R].
+-spec zipwith3(Combine, List1, List2, List3) -> List4 when
+ Combine :: fun((X, Y, Z) -> T),
+ List1 :: [X],
+ List2 :: [Y],
+ List3 :: [Z],
+ List4 :: [T],
+ X :: term(),
+ Y :: term(),
+ Z :: term(),
+ T :: term().
zipwith3(F, [X | Xs], [Y | Ys], [Z | Zs]) ->
[F(X, Y, Z) | zipwith3(F, Xs, Ys, Zs)];
@@ -303,7 +406,10 @@ zipwith3(F, [], [], []) when is_function(F, 3) -> [].
%% sort(List) -> L
%% sorts the list L
--spec sort([T]) -> [T].
+-spec sort(List1) -> List2 when
+ List1 :: [T],
+ List2 :: [T],
+ T :: term().
sort([X, Y | L] = L0) when X =< Y ->
case L of
@@ -350,7 +456,11 @@ sort_1(X, [], R) ->
%% merge(List) -> L
%% merges a list of sorted lists
--spec merge([[T]]) -> [T].
+-spec merge(ListOfLists) -> List1 when
+ ListOfLists :: [List],
+ List :: [T],
+ List1 :: [T],
+ T :: term().
merge(L) ->
mergel(L, []).
@@ -358,7 +468,14 @@ merge(L) ->
%% merge3(X, Y, Z) -> L
%% merges three sorted lists X, Y and Z
--spec merge3([X], [Y], [Z]) -> [(X | Y | Z)].
+-spec merge3(List1, List2, List3) -> List4 when
+ List1 :: [X],
+ List2 :: [Y],
+ List3 :: [Z],
+ List4 :: [(X | Y | Z)],
+ X :: term(),
+ Y :: term(),
+ Z :: term().
merge3(L1, [], L3) ->
merge(L1, L3);
@@ -382,7 +499,12 @@ rmerge3(L1, [H2 | T2], [H3 | T3]) ->
%% merge(X, Y) -> L
%% merges two sorted lists X and Y
--spec merge([X], [Y]) -> [(X | Y)].
+-spec merge(List1, List2) -> List3 when
+ List1 :: [X],
+ List2 :: [Y],
+ List3 :: [(X | Y)],
+ X :: term(),
+ Y :: term().
merge(T1, []) ->
T1;
@@ -405,8 +527,9 @@ rmerge(T1, [H2 | T2]) ->
%% in L - the elements in L can be atoms, numbers of strings.
%% Returns a list of characters.
--type concat_thing() :: atom() | integer() | float() | string().
--spec concat([concat_thing()]) -> string().
+-spec concat(Things) -> string() when
+ Things :: [Thing],
+ Thing :: atom() | integer() | float() | string().
concat(List) ->
flatmap(fun thing_to_list/1, List).
@@ -420,12 +543,17 @@ 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([term()]) -> [term()].
+-spec flatten(DeepList) -> List when
+ DeepList :: [term() | DeepList],
+ List :: [term()].
flatten(List) when is_list(List) ->
do_flatten(List, []).
--spec flatten([term()], [term()]) -> [term()].
+-spec flatten(DeepList, Tail) -> List when
+ DeepList :: [term() | DeepList],
+ Tail :: [term()],
+ List :: [term()].
flatten(List, Tail) when is_list(List), is_list(Tail) ->
do_flatten(List, Tail).
@@ -440,7 +568,8 @@ do_flatten([], Tail) ->
%% flatlength(List)
%% Calculate the length of a list of lists.
--spec flatlength([term()]) -> non_neg_integer().
+-spec flatlength(DeepList) -> non_neg_integer() when
+ DeepList :: [term() | DeepList].
flatlength(List) ->
flatlength(List, 0).
@@ -481,7 +610,12 @@ flatlength([], L) -> L.
% keysearch3(Key, N, T);
%keysearch3(Key, N, []) -> false.
--spec keydelete(term(), pos_integer(), [T]) -> [T] when T :: tuple().
+-spec keydelete(Key, N, TupleList1) -> TupleList2 when
+ Key :: term(),
+ N :: pos_integer(),
+ TupleList1 :: [Tuple],
+ TupleList2 :: [Tuple],
+ Tuple :: tuple().
keydelete(K, N, L) when is_integer(N), N > 0 ->
keydelete3(K, N, L).
@@ -491,7 +625,13 @@ keydelete3(Key, N, [H|T]) ->
[H|keydelete3(Key, N, T)];
keydelete3(_, _, []) -> [].
--spec keyreplace(term(), pos_integer(), [tuple()], tuple()) -> [tuple()].
+-spec keyreplace(Key, N, TupleList1, NewTuple) -> TupleList2 when
+ Key :: term(),
+ N :: pos_integer(),
+ TupleList1 :: [Tuple],
+ TupleList2 :: [Tuple],
+ NewTuple :: Tuple,
+ Tuple :: tuple().
keyreplace(K, N, L, New) when is_integer(N), N > 0, is_tuple(New) ->
keyreplace3(K, N, L, New).
@@ -502,8 +642,12 @@ keyreplace3(Key, Pos, [H|T], New) ->
[H|keyreplace3(Key, Pos, T, New)];
keyreplace3(_, _, [], _) -> [].
--spec keytake(term(), pos_integer(), [tuple()]) ->
- {'value', tuple(), [tuple()]} | 'false'.
+-spec keytake(Key, N, TupleList1) -> {value, Tuple, TupleList2} | false when
+ Key :: term(),
+ N :: pos_integer(),
+ TupleList1 :: [tuple()],
+ TupleList2 :: [tuple()],
+ Tuple :: tuple().
keytake(Key, N, L) when is_integer(N), N > 0 ->
keytake(Key, N, L, []).
@@ -514,7 +658,13 @@ keytake(Key, N, [H|T], L) ->
keytake(Key, N, T, [H|L]);
keytake(_K, _N, [], _L) -> false.
--spec keystore(term(), pos_integer(), [tuple()], tuple()) -> [tuple(),...].
+-spec keystore(Key, N, TupleList1, NewTuple) -> TupleList2 when
+ Key :: term(),
+ N :: pos_integer(),
+ TupleList1 :: [Tuple],
+ TupleList2 :: [Tuple, ...],
+ NewTuple :: Tuple,
+ Tuple :: tuple().
keystore(K, N, L, New) when is_integer(N), N > 0, is_tuple(New) ->
keystore2(K, N, L, New).
@@ -526,7 +676,11 @@ keystore2(Key, N, [H|T], New) ->
keystore2(_Key, _N, [], New) ->
[New].
--spec keysort(pos_integer(), [T]) -> [T] when T :: tuple().
+-spec keysort(N, TupleList1) -> TupleList2 when
+ N :: pos_integer(),
+ TupleList1 :: [Tuple],
+ TupleList2 :: [Tuple],
+ Tuple :: tuple().
keysort(I, L) when is_integer(I), I > 0 ->
case L of
@@ -583,8 +737,14 @@ keysort_1(I, X, EX, [Y | L], R) ->
keysort_1(_I, X, _EX, [], R) ->
lists:reverse(R, [X]).
--spec keymerge(pos_integer(), [X], [Y]) ->
- [R] when X :: tuple(), Y :: tuple(), R :: tuple().
+-spec keymerge(N, TupleList1, TupleList2) -> TupleList3 when
+ N :: pos_integer(),
+ TupleList1 :: [T1],
+ TupleList2 :: [T2],
+ TupleList3 :: [(T1 | T2)],
+ T1 :: Tuple,
+ T2 :: Tuple,
+ Tuple :: tuple().
keymerge(Index, T1, L2) when is_integer(Index), Index > 0 ->
case L2 of
@@ -611,7 +771,11 @@ rkeymerge(Index, T1, L2) when is_integer(Index), Index > 0 ->
lists:reverse(M, [])
end.
--spec ukeysort(pos_integer(), [T]) -> [T] when T :: tuple().
+-spec ukeysort(N, TupleList1) -> TupleList2 when
+ N :: pos_integer(),
+ TupleList1 :: [Tuple],
+ TupleList2 :: [Tuple],
+ Tuple :: tuple().
ukeysort(I, L) when is_integer(I), I > 0 ->
case L of
@@ -676,8 +840,14 @@ ukeysort_1(I, X, EX, [Y | L]) ->
ukeysort_1(_I, X, _EX, []) ->
[X].
--spec ukeymerge(pos_integer(), [X], [Y]) ->
- [(X | Y)] when X :: tuple(), Y :: tuple().
+-spec ukeymerge(N, TupleList1, TupleList2) -> TupleList3 when
+ N :: pos_integer(),
+ TupleList1 :: [T1],
+ TupleList2 :: [T2],
+ TupleList3 :: [(T1 | T2)],
+ T1 :: Tuple,
+ T2 :: Tuple,
+ Tuple :: tuple().
ukeymerge(Index, L1, T2) when is_integer(Index), Index > 0 ->
case L1 of
@@ -704,7 +874,12 @@ rukeymerge(Index, T1, L2) when is_integer(Index), Index > 0 ->
lists:reverse(M, [])
end.
--spec keymap(fun((term()) -> term()), pos_integer(), [tuple()]) -> [tuple()].
+-spec keymap(Fun, N, TupleList1) -> TupleList2 when
+ Fun :: fun((Term1 :: term()) -> Term2 :: term()),
+ N :: pos_integer(),
+ TupleList1 :: [Tuple],
+ TupleList2 :: [Tuple],
+ Tuple :: tuple().
keymap(Fun, Index, [Tup|Tail]) ->
[setelement(Index, Tup, Fun(element(Index, Tup)))|keymap(Fun, Index, Tail)];
@@ -713,7 +888,11 @@ keymap(Fun, Index, []) when is_integer(Index), Index >= 1,
%%% Suggestion from OTP-2948: sort and merge with Fun.
--spec sort(fun((T, T) -> boolean()), [T]) -> [T].
+-spec sort(Fun, List1) -> List2 when
+ Fun :: fun((A :: T, B :: T) -> boolean()),
+ List1 :: [T],
+ List2 :: [T],
+ T :: term().
sort(Fun, []) when is_function(Fun, 2) ->
[];
@@ -727,7 +906,13 @@ sort(Fun, [X, Y | T]) ->
fsplit_2(Y, X, Fun, T, [], [])
end.
--spec merge(fun((X, Y) -> boolean()), [X], [Y]) -> [(X | Y)].
+-spec merge(Fun, List1, List2) -> List3 when
+ Fun :: fun((A, B) -> boolean()),
+ List1 :: [A],
+ List2 :: [B],
+ List3 :: [(A | B)],
+ A :: term(),
+ B :: term().
merge(Fun, T1, [H2 | T2]) when is_function(Fun, 2) ->
lists:reverse(fmerge2_1(T1, H2, Fun, T2, []), []);
@@ -743,7 +928,11 @@ rmerge(Fun, T1, [H2 | T2]) when is_function(Fun, 2) ->
rmerge(Fun, T1, []) when is_function(Fun, 2) ->
T1.
--spec usort(fun((T, T) -> boolean()), [T]) -> [T].
+-spec usort(Fun, List1) -> List2 when
+ Fun :: fun((T, T) -> boolean()),
+ List1 :: [T],
+ List2 :: [T],
+ T :: term().
usort(Fun, [_] = L) when is_function(Fun, 2) ->
L;
@@ -770,7 +959,13 @@ usort_1(Fun, X, [Y | L]) ->
ufsplit_2(Y, L, Fun, [X])
end.
--spec umerge(fun((X, Y) -> boolean()), [X], [Y]) -> [(X | Y)].
+-spec umerge(Fun, List1, List2) -> List3 when
+ Fun :: fun((A, B) -> boolean()),
+ List1 :: [A],
+ List2 :: [B],
+ List3 :: [(A | B)],
+ A :: term(),
+ B :: term().
umerge(Fun, [], T2) when is_function(Fun, 2) ->
T2;
@@ -789,7 +984,10 @@ rumerge(Fun, T1, [H2 | T2]) when is_function(Fun, 2) ->
%% usort(List) -> L
%% sorts the list L, removes duplicates
--spec usort([T]) -> [T].
+-spec usort(List1) -> List2 when
+ List1 :: [T],
+ List2 :: [T],
+ T :: term().
usort([X, Y | L] = L0) when X < Y ->
case L of
@@ -844,7 +1042,11 @@ usort_1(X, []) ->
%% umerge(List) -> L
%% merges a list of sorted lists without duplicates, removes duplicates
--spec umerge([[T]]) -> [T].
+-spec umerge(ListOfLists) -> List1 when
+ ListOfLists :: [List],
+ List :: [T],
+ List1 :: [T],
+ T :: term().
umerge(L) ->
umergel(L).
@@ -853,7 +1055,14 @@ umerge(L) ->
%% merges three sorted lists X, Y and Z without duplicates,
%% removes duplicates
--spec umerge3([X], [Y], [Z]) -> [(X | Y | Z)].
+-spec umerge3(List1, List2, List3) -> List4 when
+ List1 :: [X],
+ List2 :: [Y],
+ List3 :: [Z],
+ List4 :: [(X | Y | Z)],
+ X :: term(),
+ Y :: term(),
+ Z :: term().
umerge3(L1, [], L3) ->
umerge(L1, L3);
@@ -878,7 +1087,12 @@ rumerge3(L1, [H2 | T2], [H3 | T3]) ->
%% umerge(X, Y) -> L
%% merges two sorted lists X and Y without duplicates, removes duplicates
--spec umerge([X], [Y]) -> [(X | Y)].
+-spec umerge(List1, List2) -> List3 when
+ List1 :: [X],
+ List2 :: [Y],
+ List3 :: [(X | Y)],
+ X :: term(),
+ Y :: term().
umerge([], T2) ->
T2;
@@ -924,7 +1138,10 @@ rumerge(T1, [H2 | T2]) ->
%% There are also versions with an extra argument, ExtraArgs, which is a
%% list of extra arguments to each call.
--spec all(fun((T) -> boolean()), [T]) -> boolean().
+-spec all(Pred, List) -> boolean() when
+ Pred :: fun((Elem :: T) -> boolean()),
+ List :: [T],
+ T :: term().
all(Pred, [Hd|Tail]) ->
case Pred(Hd) of
@@ -933,7 +1150,10 @@ all(Pred, [Hd|Tail]) ->
end;
all(Pred, []) when is_function(Pred, 1) -> true.
--spec any(fun((T) -> boolean()), [T]) -> boolean().
+-spec any(Pred, List) -> boolean() when
+ Pred :: fun((Elem :: T) -> boolean()),
+ List :: [T],
+ T :: term().
any(Pred, [Hd|Tail]) ->
case Pred(Hd) of
@@ -942,31 +1162,59 @@ any(Pred, [Hd|Tail]) ->
end;
any(Pred, []) when is_function(Pred, 1) -> false.
--spec map(fun((D) -> R), [D]) -> [R].
+-spec map(Fun, List1) -> List2 when
+ Fun :: fun((A) -> B),
+ List1 :: [A],
+ List2 :: [B],
+ A :: term(),
+ B :: term().
map(F, [H|T]) ->
[F(H)|map(F, T)];
map(F, []) when is_function(F, 1) -> [].
--spec flatmap(fun((D) -> [R]), [D]) -> [R].
+-spec flatmap(Fun, List1) -> List2 when
+ Fun :: fun((A) -> [B]),
+ List1 :: [A],
+ List2 :: [B],
+ A :: term(),
+ B :: term().
flatmap(F, [Hd|Tail]) ->
F(Hd) ++ flatmap(F, Tail);
flatmap(F, []) when is_function(F, 1) -> [].
--spec foldl(fun((T, term()) -> term()), term(), [T]) -> term().
+-spec foldl(Fun, Acc0, List) -> Acc1 when
+ Fun :: fun((Elem :: T, AccIn) -> AccOut),
+ Acc0 :: term(),
+ Acc1 :: term(),
+ AccIn :: term(),
+ AccOut :: term(),
+ List :: [T],
+ 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, term()) -> term()), term(), [T]) -> term().
+-spec foldr(Fun, Acc0, List) -> Acc1 when
+ Fun :: fun((Elem :: T, AccIn) -> AccOut),
+ Acc0 :: term(),
+ Acc1 :: term(),
+ AccIn :: term(),
+ AccOut :: term(),
+ List :: [T],
+ T :: term().
foldr(F, Accu, [Hd|Tail]) ->
F(Hd, foldr(F, Accu, Tail));
foldr(F, Accu, []) when is_function(F, 2) -> Accu.
--spec filter(Pred :: fun((T) -> boolean()), List :: [T]) -> [T].
+-spec filter(Pred, List1) -> List2 when
+ Pred :: fun((Elem :: T) -> boolean()),
+ List1 :: [T],
+ List2 :: [T],
+ T :: term().
filter(Pred, List) when is_function(Pred, 1) ->
[ E || E <- List, Pred(E) ].
@@ -974,7 +1222,12 @@ filter(Pred, List) when is_function(Pred, 1) ->
%% Equivalent to {filter(F, L), filter(NotF, L)}, if NotF = 'fun(X) ->
%% not F(X) end'.
--spec partition(Pred :: fun((T) -> boolean()), List :: [T]) -> {[T], [T]}.
+-spec partition(Pred, List) -> {Satisfying, NotSatisfying} when
+ Pred :: fun((Elem :: T) -> boolean()),
+ List :: [T],
+ Satisfying :: [T],
+ NotSatisfying :: [T],
+ T :: term().
partition(Pred, L) ->
partition(Pred, L, [], []).
@@ -1000,14 +1253,26 @@ zf(F, [Hd|Tail]) ->
end;
zf(F, []) when is_function(F, 1) -> [].
--spec foreach(F :: fun((T) -> term()), List :: [T]) -> 'ok'.
+-spec foreach(Fun, List) -> ok when
+ Fun :: fun((Elem :: T) -> term()),
+ List :: [T],
+ T :: term().
foreach(F, [Hd|Tail]) ->
F(Hd),
foreach(F, Tail);
foreach(F, []) when is_function(F, 1) -> ok.
--spec mapfoldl(fun((A, term()) -> {B, term()}), term(), [A]) -> {[B], term()}.
+-spec mapfoldl(Fun, Acc0, List1) -> {List2, Acc1} when
+ Fun :: fun((A, AccIn) -> {B, AccOut}),
+ Acc0 :: term(),
+ Acc1 :: term(),
+ AccIn :: term(),
+ AccOut :: term(),
+ List1 :: [A],
+ List2 :: [B],
+ A :: term(),
+ B :: term().
mapfoldl(F, Accu0, [Hd|Tail]) ->
{R,Accu1} = F(Hd, Accu0),
@@ -1015,7 +1280,16 @@ mapfoldl(F, Accu0, [Hd|Tail]) ->
{[R|Rs],Accu2};
mapfoldl(F, Accu, []) when is_function(F, 2) -> {[],Accu}.
--spec mapfoldr(fun((A, term()) -> {B, term()}), term(), [A]) -> {[B], term()}.
+-spec mapfoldr(Fun, Acc0, List1) -> {List2, Acc1} when
+ Fun :: fun((A, AccIn) -> {B, AccOut}),
+ Acc0 :: term(),
+ Acc1 :: term(),
+ AccIn :: term(),
+ AccOut :: term(),
+ List1 :: [A],
+ List2 :: [B],
+ A :: term(),
+ B :: term().
mapfoldr(F, Accu0, [Hd|Tail]) ->
{Rs,Accu1} = mapfoldr(F, Accu0, Tail),
@@ -1023,7 +1297,11 @@ mapfoldr(F, Accu0, [Hd|Tail]) ->
{[R|Rs],Accu2};
mapfoldr(F, Accu, []) when is_function(F, 2) -> {[],Accu}.
--spec takewhile(fun((T) -> boolean()), [T]) -> [T].
+-spec takewhile(Pred, List1) -> List2 when
+ Pred :: fun((Elem :: T) -> boolean()),
+ List1 :: [T],
+ List2 :: [T],
+ T :: term().
takewhile(Pred, [Hd|Tail]) ->
case Pred(Hd) of
@@ -1032,7 +1310,11 @@ takewhile(Pred, [Hd|Tail]) ->
end;
takewhile(Pred, []) when is_function(Pred, 1) -> [].
--spec dropwhile(fun((T) -> boolean()), [T]) -> [T].
+-spec dropwhile(Pred, List1) -> List2 when
+ Pred :: fun((Elem :: T) -> boolean()),
+ List1 :: [T],
+ List2 :: [T],
+ T :: term().
dropwhile(Pred, [Hd|Tail]=Rest) ->
case Pred(Hd) of
@@ -1041,7 +1323,12 @@ dropwhile(Pred, [Hd|Tail]=Rest) ->
end;
dropwhile(Pred, []) when is_function(Pred, 1) -> [].
--spec splitwith(fun((T) -> boolean()), [T]) -> {[T], [T]}.
+-spec splitwith(Pred, List) -> {List1, List2} when
+ Pred :: fun((T) -> boolean()),
+ List :: [T],
+ List1 :: [T],
+ List2 :: [T],
+ T :: term().
splitwith(Pred, List) when is_function(Pred, 1) ->
splitwith(Pred, List, []).
@@ -1054,7 +1341,12 @@ splitwith(Pred, [Hd|Tail], Taken) ->
splitwith(Pred, [], Taken) when is_function(Pred, 1) ->
{reverse(Taken),[]}.
--spec split(non_neg_integer(), [T]) -> {[T], [T]}.
+-spec split(N, List1) -> {List2, List3} when
+ N :: non_neg_integer(),
+ List1 :: [T],
+ List2 :: [T],
+ List3 :: [T],
+ T :: term().
split(N, List) when is_integer(N), N >= 0, is_list(List) ->
case split(N, List, []) of
diff --git a/lib/stdlib/src/log_mf_h.erl b/lib/stdlib/src/log_mf_h.erl
index 5fa5360fa1..f7f128dac7 100644
--- a/lib/stdlib/src/log_mf_h.erl
+++ b/lib/stdlib/src/log_mf_h.erl
@@ -27,14 +27,13 @@
%%-----------------------------------------------------------------
--type dir() :: file:filename().
-type b() :: non_neg_integer().
-type f() :: 1..255.
-type pred() :: fun((term()) -> boolean()).
%%-----------------------------------------------------------------
--record(state, {dir :: dir(),
+-record(state, {dir :: file:filename(),
maxB :: b(),
maxF :: f(),
curB :: b(),
@@ -67,11 +66,23 @@
%% EventMgr = pid() | atom().
%%-----------------------------------------------------------------
--spec init(dir(), b(), f()) -> {dir(), b(), f(), pred()}.
+-opaque args() :: {file:filename(), b(), f(), pred()}.
+
+
+-spec init(Dir, MaxBytes, MaxFiles) -> Args when
+ Dir :: file:filename(),
+ MaxBytes :: non_neg_integer(), % b()
+ MaxFiles :: 1..255, % f()
+ Args :: args().
init(Dir, MaxB, MaxF) -> init(Dir, MaxB, MaxF, fun(_) -> true end).
--spec init(dir(), b(), f(), pred()) -> {dir(), b(), f(), pred()}.
+-spec init(Dir, MaxBytes, MaxFiles, Pred) -> Args when
+ Dir :: file:filename(),
+ MaxBytes :: non_neg_integer(), % b()
+ MaxFiles :: 1..255, % f()
+ Pred :: fun((Event :: term()) -> boolean()), % pred()
+ Args :: args().
init(Dir, MaxB, MaxF, Pred) -> {Dir, MaxB, MaxF, Pred}.
@@ -79,7 +90,7 @@ init(Dir, MaxB, MaxF, Pred) -> {Dir, MaxB, MaxF, Pred}.
%% Call-back functions from gen_event
%%-----------------------------------------------------------------
--spec init({dir(), b(), f(), pred()}) -> {'ok', #state{}} | {'error', term()}.
+-spec init({file:filename(), non_neg_integer(), f(), pred()}) -> {'ok', #state{}} | {'error', term()}.
init({Dir, MaxB, MaxF, Pred}) when is_integer(MaxF), MaxF > 0, MaxF < 256 ->
First =
diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl
index b565eb20f4..48e22e53fa 100644
--- a/lib/stdlib/src/ms_transform.erl
+++ b/lib/stdlib/src/ms_transform.erl
@@ -66,6 +66,11 @@
%%
%% Called by compiler or ets/dbg:fun2ms when errors/warnings occur
%%
+
+-spec(format_error(Error) -> Chars when
+ Error :: {error, module(), term()},
+ Chars :: io_lib:chars()).
+
format_error({?WARN_SHADOW_VAR,Name}) ->
lists:flatten(
io_lib:format("variable ~p shadowed in ms_transform fun head",
@@ -186,6 +191,12 @@ format_error(Else) ->
%%
%% Called when translating in shell
%%
+
+-spec transform_from_shell(Dialect, Clauses, BoundEnvironment) -> term() when
+ Dialect :: ets | dbg,
+ Clauses :: [erl_parse:abstract_clause()],
+ BoundEnvironment :: erl_eval:binding_struct().
+
transform_from_shell(Dialect, Clauses, BoundEnvironment) ->
SaveFilename = setup_filename(),
case catch ms_clause_list(1,Clauses,Dialect,gb_sets:new()) of
@@ -211,6 +222,11 @@ transform_from_shell(Dialect, Clauses, BoundEnvironment) ->
%%
%% Called when translating during compiling
%%
+
+-spec parse_transform(Forms, Options) -> Forms when
+ Forms :: [erl_parse:abstract_form()],
+ Options :: term().
+
parse_transform(Forms, _Options) ->
SaveFilename = setup_filename(),
%io:format("Forms: ~p~n",[Forms]),
diff --git a/lib/stdlib/src/orddict.erl b/lib/stdlib/src/orddict.erl
index 4e30c9eefd..45d3c84b3e 100644
--- a/lib/stdlib/src/orddict.erl
+++ b/lib/stdlib/src/orddict.erl
@@ -25,9 +25,11 @@
-export([store/3,append/3,append_list/3,update/3,update/4,update_counter/3]).
-export([fold/3,map/2,filter/2,merge/3]).
+-export_type([orddict/0]).
+
%%---------------------------------------------------------------------------
--type orddict() :: [{term(), term()}].
+-type orddict() :: [{Key :: term(), Value :: term()}].
%%---------------------------------------------------------------------------
@@ -35,45 +37,63 @@
new() -> [].
--spec is_key(Key::term(), Dictionary::orddict()) -> boolean().
+-spec is_key(Key, Orddict) -> boolean() when
+ Key :: term(),
+ Orddict :: orddict().
is_key(Key, [{K,_}|_]) when Key < K -> false;
is_key(Key, [{K,_}|Dict]) when Key > K -> is_key(Key, Dict);
is_key(_Key, [{_K,_Val}|_]) -> true; %Key == K
is_key(_, []) -> false.
--spec to_list(orddict()) -> [{term(), term()}].
+-spec to_list(Orddict) -> List when
+ Orddict :: orddict(),
+ List :: [{Key :: term(), Value :: term()}].
to_list(Dict) -> Dict.
--spec from_list([{term(), term()}]) -> orddict().
+-spec from_list(List) -> Orddict when
+ List :: [{Key :: term(), Value :: term()}],
+ Orddict :: orddict().
from_list(Pairs) ->
lists:foldl(fun ({K,V}, D) -> store(K, V, D) end, [], Pairs).
--spec size(orddict()) -> non_neg_integer().
+-spec size(Orddict) -> non_neg_integer() when
+ Orddict :: orddict().
size(D) -> length(D).
--spec fetch(Key::term(), Dictionary::orddict()) -> term().
+-spec fetch(Key, Orddict) -> Value when
+ Key :: term(),
+ Value :: term(),
+ Orddict :: orddict().
fetch(Key, [{K,_}|D]) when Key > K -> fetch(Key, D);
fetch(Key, [{K,Value}|_]) when Key == K -> Value.
--spec find(Key::term(), Dictionary::orddict()) -> {'ok', term()} | 'error'.
+-spec find(Key, Orddict) -> {'ok', Value} | 'error' when
+ Key :: term(),
+ Orddict :: orddict(),
+ Value :: term().
find(Key, [{K,_}|_]) when Key < K -> error;
find(Key, [{K,_}|D]) when Key > K -> find(Key, D);
find(_Key, [{_K,Value}|_]) -> {ok,Value}; %Key == K
find(_, []) -> error.
--spec fetch_keys(Dictionary::orddict()) -> [term()].
+-spec fetch_keys(Orddict) -> Keys when
+ Orddict :: orddict(),
+ Keys :: [term()].
fetch_keys([{Key,_}|Dict]) ->
[Key|fetch_keys(Dict)];
fetch_keys([]) -> [].
--spec erase(Key::term(), Dictionary::orddict()) -> orddict().
+-spec erase(Key, Orddict1) -> Orddict2 when
+ Key :: term(),
+ Orddict1 :: orddict(),
+ Orddict2 :: orddict().
erase(Key, [{K,_}=E|Dict]) when Key < K -> [E|Dict];
erase(Key, [{K,_}=E|Dict]) when Key > K ->
@@ -81,7 +101,11 @@ erase(Key, [{K,_}=E|Dict]) when Key > K ->
erase(_Key, [{_K,_Val}|Dict]) -> Dict; %Key == K
erase(_, []) -> [].
--spec store(Key::term(), Value::term(), Dictionary::orddict()) -> orddict().
+-spec store(Key, Value, Orddict1) -> Orddict2 when
+ Key :: term(),
+ Value :: term(),
+ Orddict1 :: orddict(),
+ Orddict2 :: orddict().
store(Key, New, [{K,_}=E|Dict]) when Key < K ->
[{Key,New},E|Dict];
@@ -91,7 +115,11 @@ store(Key, New, [{_K,_Old}|Dict]) -> %Key == K
[{Key,New}|Dict];
store(Key, New, []) -> [{Key,New}].
--spec append(Key::term(), Value::term(), Dictionary::orddict()) -> orddict().
+-spec append(Key, Value, Orddict1) -> Orddict2 when
+ Key :: term(),
+ Value :: term(),
+ Orddict1 :: orddict(),
+ Orddict2 :: orddict().
append(Key, New, [{K,_}=E|Dict]) when Key < K ->
[{Key,[New]},E|Dict];
@@ -101,7 +129,11 @@ append(Key, New, [{_K,Old}|Dict]) -> %Key == K
[{Key,Old ++ [New]}|Dict];
append(Key, New, []) -> [{Key,[New]}].
--spec append_list(Key::term(), ValueList::[term()], orddict()) -> orddict().
+-spec append_list(Key, ValList, Orddict1) -> Orddict2 when
+ Key :: term(),
+ ValList :: [Value :: term()],
+ Orddict1 :: orddict(),
+ Orddict2 :: orddict().
append_list(Key, NewList, [{K,_}=E|Dict]) when Key < K ->
[{Key,NewList},E|Dict];
@@ -112,14 +144,23 @@ append_list(Key, NewList, [{_K,Old}|Dict]) -> %Key == K
append_list(Key, NewList, []) ->
[{Key,NewList}].
--spec update(Key::term(), Fun::fun((term()) -> term()), orddict()) -> orddict().
+-spec update(Key, Fun, Orddict1) -> Orddict2 when
+ Key :: term(),
+ Fun :: fun((Value1 :: term()) -> Value2 :: term()),
+ Orddict1 :: orddict(),
+ Orddict2 :: orddict().
update(Key, Fun, [{K,_}=E|Dict]) when Key > K ->
[E|update(Key, Fun, Dict)];
update(Key, Fun, [{K,Val}|Dict]) when Key == K ->
[{Key,Fun(Val)}|Dict].
--spec update(term(), fun((term()) -> term()), term(), orddict()) -> orddict().
+-spec update(Key, Fun, Initial, Orddict1) -> Orddict2 when
+ Key :: term(),
+ Initial :: term(),
+ Fun :: fun((Value1 :: term()) -> Value2 :: term()),
+ Orddict1 :: orddict(),
+ Orddict2 :: orddict().
update(Key, _, Init, [{K,_}=E|Dict]) when Key < K ->
[{Key,Init},E|Dict];
@@ -129,7 +170,11 @@ update(Key, Fun, _Init, [{_K,Val}|Dict]) -> %Key == K
[{Key,Fun(Val)}|Dict];
update(Key, _, Init, []) -> [{Key,Init}].
--spec update_counter(Key::term(), Incr::number(), orddict()) -> orddict().
+-spec update_counter(Key, Increment, Orddict1) -> Orddict2 when
+ Key :: term(),
+ Increment :: number(),
+ Orddict1 :: orddict(),
+ Orddict2 :: orddict().
update_counter(Key, Incr, [{K,_}=E|Dict]) when Key < K ->
[{Key,Incr},E|Dict];
@@ -139,19 +184,29 @@ update_counter(Key, Incr, [{_K,Val}|Dict]) -> %Key == K
[{Key,Val+Incr}|Dict];
update_counter(Key, Incr, []) -> [{Key,Incr}].
--spec fold(fun((term(),term(),term()) -> term()), term(), orddict()) -> term().
+-spec fold(Fun, Acc0, Orddict) -> Acc1 when
+ Fun :: fun((Key :: term(), Value :: term(), AccIn :: term()) -> AccOut :: term()),
+ Acc0 :: term(),
+ Acc1 :: term(),
+ Orddict :: orddict().
fold(F, Acc, [{Key,Val}|D]) ->
fold(F, F(Key, Val, Acc), D);
fold(F, Acc, []) when is_function(F, 3) -> Acc.
--spec map(fun((term(), term()) -> term()), orddict()) -> orddict().
+-spec map(Fun, Orddict1) -> Orddict2 when
+ Fun :: fun((Key :: term(), Value1 :: term()) -> Value2 :: term()),
+ Orddict1 :: orddict(),
+ Orddict2 :: orddict().
map(F, [{Key,Val}|D]) ->
[{Key,F(Key, Val)}|map(F, D)];
map(F, []) when is_function(F, 2) -> [].
--spec filter(fun((term(), term()) -> boolean()), orddict()) -> orddict().
+-spec filter(Pred, Orddict1) -> Orddict2 when
+ Pred :: fun((Key :: term(), Value :: term()) -> boolean()),
+ Orddict1 :: orddict(),
+ Orddict2 :: orddict().
filter(F, [{Key,Val}=E|D]) ->
case F(Key, Val) of
@@ -160,8 +215,11 @@ filter(F, [{Key,Val}=E|D]) ->
end;
filter(F, []) when is_function(F, 2) -> [].
--spec merge(fun((term(), term(), term()) -> term()), orddict(), orddict()) ->
- orddict().
+-spec merge(Fun, Orddict1, Orddict2) -> Orddict3 when
+ Fun :: fun((Key :: term(), Value1 :: term(), Value2 :: term()) -> Value :: term()),
+ Orddict1 :: orddict(),
+ Orddict2 :: orddict(),
+ Orddict3 :: orddict().
merge(F, [{K1,_}=E1|D1], [{K2,_}=E2|D2]) when K1 < K2 ->
[E1|merge(F, D1, [E2|D2])];
diff --git a/lib/stdlib/src/ordsets.erl b/lib/stdlib/src/ordsets.erl
index 5a1c260703..4a8b1275b2 100644
--- a/lib/stdlib/src/ordsets.erl
+++ b/lib/stdlib/src/ordsets.erl
@@ -40,7 +40,8 @@ new() -> [].
%% is_set(Term) -> boolean().
%% Return 'true' if Set is an ordered set of elements, else 'false'.
--spec is_set(term()) -> boolean().
+-spec is_set(Ordset) -> boolean() when
+ Ordset :: term().
is_set([E|Es]) -> is_set(Es, E);
is_set([]) -> true;
@@ -54,21 +55,26 @@ is_set([], _) -> true.
%% size(OrdSet) -> int().
%% Return the number of elements in OrdSet.
--spec size(ordset(_)) -> non_neg_integer().
+-spec size(Ordset) -> non_neg_integer() when
+ Ordset :: ordset(_).
size(S) -> length(S).
%% to_list(OrdSet) -> [Elem].
%% Return the elements in OrdSet as a list.
--spec to_list(ordset(T)) -> [T].
+-spec to_list(Ordset) -> List when
+ Ordset :: ordset(T),
+ List :: [T].
to_list(S) -> S.
%% from_list([Elem]) -> Set.
%% Build an ordered set from the elements in List.
--spec from_list([T]) -> ordset(T).
+-spec from_list(List) -> Ordset when
+ List :: [T],
+ Ordset :: ordset(T).
from_list(L) ->
lists:usort(L).
@@ -76,7 +82,9 @@ from_list(L) ->
%% is_element(Element, OrdSet) -> boolean().
%% Return 'true' if Element is an element of OrdSet, else 'false'.
--spec is_element(term(), ordset(_)) -> boolean().
+-spec is_element(Element, Ordset) -> boolean() when
+ Element :: term(),
+ Ordset :: ordset(_).
is_element(E, [H|Es]) when E > H -> is_element(E, Es);
is_element(E, [H|_]) when E < H -> false;
@@ -86,7 +94,12 @@ is_element(_, []) -> false.
%% add_element(Element, OrdSet) -> OrdSet.
%% Return OrdSet with Element inserted in it.
--spec add_element(E, ordset(T)) -> [T | E,...].
+-spec add_element(Element, Ordset1) -> Ordset2 when
+ Element :: E,
+ Ordset1 :: ordset(T),
+ Ordset2 :: ordset(T | E).
+
+%-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];
@@ -96,7 +109,10 @@ add_element(E, []) -> [E].
%% del_element(Element, OrdSet) -> OrdSet.
%% Return OrdSet but with Element removed.
--spec del_element(term(), ordset(T)) -> ordset(T).
+-spec del_element(Element, Ordset1) -> Ordset2 when
+ Element :: term(),
+ Ordset1 :: ordset(T),
+ Ordset2 :: ordset(T).
del_element(E, [H|Es]) when E > H -> [H|del_element(E, Es)];
del_element(E, [H|_]=Set) when E < H -> Set;
@@ -106,7 +122,10 @@ del_element(_, []) -> [].
%% union(OrdSet1, OrdSet2) -> OrdSet
%% Return the union of OrdSet1 and OrdSet2.
--spec union(ordset(T1), ordset(T2)) -> ordset(T1 | T2).
+-spec union(Ordset1, Ordset2) -> Ordset3 when
+ Ordset1 :: ordset(T1),
+ Ordset2 :: ordset(T2),
+ Ordset3 :: ordset(T1 | T2).
union([E1|Es1], [E2|_]=Set2) when E1 < E2 ->
[E1|union(Es1, Set2)];
@@ -120,7 +139,9 @@ union(Es1, []) -> Es1.
%% union([OrdSet]) -> OrdSet
%% Return the union of the list of ordered sets.
--spec union([ordset(T)]) -> ordset(T).
+-spec union(OrdsetList) -> Ordset when
+ OrdsetList :: [ordset(T)],
+ Ordset :: ordset(T).
union([S1,S2|Ss]) ->
union1(union(S1, S2), Ss);
@@ -133,7 +154,10 @@ union1(S1, []) -> S1.
%% intersection(OrdSet1, OrdSet2) -> OrdSet.
%% Return the intersection of OrdSet1 and OrdSet2.
--spec intersection(ordset(_), ordset(_)) -> ordset(_).
+-spec intersection(Ordset1, Ordset2) -> Ordset3 when
+ Ordset1 :: ordset(_),
+ Ordset2 :: ordset(_),
+ Ordset3 :: ordset(_).
intersection([E1|Es1], [E2|_]=Set2) when E1 < E2 ->
intersection(Es1, Set2);
@@ -149,7 +173,9 @@ intersection(_, []) ->
%% intersection([OrdSet]) -> OrdSet.
%% Return the intersection of the list of ordered sets.
--spec intersection([ordset(_),...]) -> ordset(_).
+-spec intersection(OrdsetList) -> Ordset when
+ OrdsetList :: [ordset(_),...],
+ Ordset :: ordset(_).
intersection([S1,S2|Ss]) ->
intersection1(intersection(S1, S2), Ss);
@@ -162,7 +188,9 @@ intersection1(S1, []) -> S1.
%% is_disjoint(OrdSet1, OrdSet2) -> boolean().
%% Check whether OrdSet1 and OrdSet2 are disjoint.
--spec is_disjoint(ordset(_), ordset(_)) -> boolean().
+-spec is_disjoint(Ordset1, Ordset2) -> boolean() when
+ Ordset1 :: ordset(_),
+ Ordset2 :: ordset(_).
is_disjoint([E1|Es1], [E2|_]=Set2) when E1 < E2 ->
is_disjoint(Es1, Set2);
@@ -179,7 +207,10 @@ is_disjoint(_, []) ->
%% Return all and only the elements of OrdSet1 which are not also in
%% OrdSet2.
--spec subtract(ordset(_), ordset(_)) -> ordset(_).
+-spec subtract(Ordset1, Ordset2) -> Ordset3 when
+ Ordset1 :: ordset(_),
+ Ordset2 :: ordset(_),
+ Ordset3 :: ordset(_).
subtract([E1|Es1], [E2|_]=Set2) when E1 < E2 ->
[E1|subtract(Es1, Set2)];
@@ -194,7 +225,9 @@ subtract(Es1, []) -> Es1.
%% Return 'true' when every element of OrdSet1 is also a member of
%% OrdSet2, else 'false'.
--spec is_subset(ordset(_), ordset(_)) -> boolean().
+-spec is_subset(Ordset1, Ordset2) -> boolean() when
+ Ordset1 :: ordset(_),
+ Ordset2 :: ordset(_).
is_subset([E1|_], [E2|_]) when E1 < E2 -> %E1 not in Set2
false;
@@ -208,7 +241,11 @@ is_subset(_, []) -> false.
%% fold(Fun, Accumulator, OrdSet) -> Accumulator.
%% Fold function Fun over all elements in OrdSet and return Accumulator.
--spec fold(fun((T, term()) -> term()), term(), ordset(T)) -> term().
+-spec fold(Function, Acc0, Ordset) -> Acc1 when
+ Function :: fun((Element :: T, AccIn :: term()) -> AccOut :: term()),
+ Ordset :: ordset(T),
+ Acc0 :: term(),
+ Acc1 :: term().
fold(F, Acc, Set) ->
lists:foldl(F, Acc, Set).
@@ -216,7 +253,10 @@ fold(F, Acc, Set) ->
%% filter(Fun, OrdSet) -> OrdSet.
%% Filter OrdSet with Fun.
--spec filter(fun((T) -> boolean()), ordset(T)) -> ordset(T).
+-spec filter(Pred, Ordset1) -> Ordset2 when
+ Pred :: fun((Element :: T) -> boolean()),
+ Ordset1 :: ordset(T),
+ Ordset2 :: 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 5c52dfcbf0..c1285dab60 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -180,6 +180,9 @@ obsolete_1(calendar, local_time_to_universal_time, 1) ->
obsolete_1(rpc, safe_multi_server_call, A) when A =:= 2; A =:= 3 ->
{deprecated, {rpc, multi_server_call, A}};
+
+%% *** SNMP ***
+
obsolete_1(snmp, N, A) ->
case is_snmp_agent_function(N, A) of
false ->
@@ -189,9 +192,100 @@ obsolete_1(snmp, N, A) ->
integer_to_list(A)++" instead"}
end;
+obsolete_1(snmpm, agent_info, 3) ->
+ {deprecated, {snmpm, agent_info, 2}, "R16B"};
+obsolete_1(snmpm, update_agent_info, 5) ->
+ {deprecated, {snmpm, update_agent_info, 4}, "R16B"};
+obsolete_1(snmpm, g, 3) ->
+ {deprecated, {snmpm, sync_get, 3}, "R16B"};
+obsolete_1(snmpm, g, 4) ->
+ {deprecated, {snmpm, sync_get, [3,4]}, "R16B"};
+obsolete_1(snmpm, g, 5) ->
+ {deprecated, {snmpm, sync_get, [4,5]}, "R16B"};
+obsolete_1(snmpm, g, 6) ->
+ {deprecated, {snmpm, sync_get, [5,6]}, "R16B"};
+obsolete_1(snmpm, g, 7) ->
+ {deprecated, {snmpm, sync_get, 6}, "R16B"};
+obsolete_1(snmpm, ag, 3) ->
+ {deprecated, {snmpm, async_get, 3}, "R16B"};
+obsolete_1(snmpm, ag, 4) ->
+ {deprecated, {snmpm, async_get, [3,4]}, "R16B"};
+obsolete_1(snmpm, ag, 5) ->
+ {deprecated, {snmpm, async_get, [4,5]}, "R16B"};
+obsolete_1(snmpm, ag, 6) ->
+ {deprecated, {snmpm, async_get, [5,6]}, "R16B"};
+obsolete_1(snmpm, ag, 7) ->
+ {deprecated, {snmpm, async_get, 6}, "R16B"};
+obsolete_1(snmpm, gn, 3) ->
+ {deprecated, {snmpm, sync_get_next, 3}, "R16B"};
+obsolete_1(snmpm, gn, 4) ->
+ {deprecated, {snmpm, sync_get_next, [3,4]}, "R16B"};
+obsolete_1(snmpm, gn, 5) ->
+ {deprecated, {snmpm, sync_get_next, [4,5]}, "R16B"};
+obsolete_1(snmpm, gn, 6) ->
+ {deprecated, {snmpm, sync_get_next, [5,6]}, "R16B"};
+obsolete_1(snmpm, gn, 7) ->
+ {deprecated, {snmpm, sync_get_next, 6}, "R16B"};
+obsolete_1(snmpm, agn, 3) ->
+ {deprecated, {snmpm, async_get_next, 3}, "R16B"};
+obsolete_1(snmpm, agn, 4) ->
+ {deprecated, {snmpm, async_get_next, [3,4]}, "R16B"};
+obsolete_1(snmpm, agn, 5) ->
+ {deprecated, {snmpm, async_get_next, [4,5]}, "R16B"};
+obsolete_1(snmpm, agn, 6) ->
+ {deprecated, {snmpm, async_get_next, [5,6]}, "R16B"};
+obsolete_1(snmpm, agn, 7) ->
+ {deprecated, {snmpm, async_get_next, 6}, "R16B"};
+obsolete_1(snmpm, s, 3) ->
+ {deprecated, {snmpm, sync_set, 3}, "R16B"};
+obsolete_1(snmpm, s, 4) ->
+ {deprecated, {snmpm, sync_set, [3,4]}, "R16B"};
+obsolete_1(snmpm, s, 5) ->
+ {deprecated, {snmpm, sync_set, [4,5]}, "R16B"};
+obsolete_1(snmpm, s, 6) ->
+ {deprecated, {snmpm, sync_set, [5,6]}, "R16B"};
+obsolete_1(snmpm, s, 7) ->
+ {deprecated, {snmpm, sync_set, 6}, "R16B"};
+obsolete_1(snmpm, as, 3) ->
+ {deprecated, {snmpm, async_set, 3}, "R16B"};
+obsolete_1(snmpm, as, 4) ->
+ {deprecated, {snmpm, async_set, [3,4]}, "R16B"};
+obsolete_1(snmpm, as, 5) ->
+ {deprecated, {snmpm, async_set, [4,5]}, "R16B"};
+obsolete_1(snmpm, as, 6) ->
+ {deprecated, {snmpm, async_set, [5,6]}, "R16B"};
+obsolete_1(snmpm, as, 7) ->
+ {deprecated, {snmpm, async_set, 6}, "R16B"};
+obsolete_1(snmpm, gb, 5) ->
+ {deprecated, {snmpm, sync_get_bulk, 5}, "R16B"};
+obsolete_1(snmpm, gb, 6) ->
+ {deprecated, {snmpm, sync_get_bulk, [5,6]}, "R16B"};
+obsolete_1(snmpm, gb, 7) ->
+ {deprecated, {snmpm, sync_get_bulk, [6,7]}, "R16B"};
+obsolete_1(snmpm, gb, 8) ->
+ {deprecated, {snmpm, sync_get_bulk, [7,8]}, "R16B"};
+obsolete_1(snmpm, gb, 9) ->
+ {deprecated, {snmpm, sync_get_bulk, 8}, "R16B"};
+obsolete_1(snmpm, agb, 5) ->
+ {deprecated, {snmpm, async_get_bulk, 5}, "R16B"};
+obsolete_1(snmpm, agb, 6) ->
+ {deprecated, {snmpm, async_get_bulk, [5,6]}, "R16B"};
+obsolete_1(snmpm, agb, 7) ->
+ {deprecated, {snmpm, async_get_bulk, [6,7]}, "R16B"};
+obsolete_1(snmpm, agb, 8) ->
+ {deprecated, {snmpm, async_get_bulk, [7,8]}, "R16B"};
+obsolete_1(snmpm, agb, 9) ->
+ {deprecated, {snmpm, async_get_bulk, 8}, "R16B"};
+
+
+%% *** MEGACO ***
+
obsolete_1(megaco, format_versions, 1) ->
{deprecated, "Deprecated; use megaco:print_version_info/0,1 instead"};
+
+%% *** OS-MON-MIB ***
+
obsolete_1(os_mon_mib, init, 1) ->
{deprecated, {os_mon_mib, load, 1}};
obsolete_1(os_mon_mib, stop, 1) ->
@@ -236,22 +330,22 @@ obsolete_1(erlang, fault, 2) ->
obsolete_1(file, rawopen, 2) ->
{removed, "deprecated (will be removed in R13B); use file:open/2 with the raw option"};
-obsolete_1(http, request, 1) -> {deprecated,{httpc,request,1},"R15B"};
-obsolete_1(http, request, 2) -> {deprecated,{httpc,request,2},"R15B"};
-obsolete_1(http, request, 4) -> {deprecated,{httpc,request,4},"R15B"};
-obsolete_1(http, request, 5) -> {deprecated,{httpc,request,5},"R15B"};
-obsolete_1(http, cancel_request, 1) -> {deprecated,{httpc,cancel_request,1},"R15B"};
-obsolete_1(http, cancel_request, 2) -> {deprecated,{httpc,cancel_request,2},"R15B"};
-obsolete_1(http, set_option, 2) -> {deprecated,{httpc,set_option,2},"R15B"};
-obsolete_1(http, set_option, 3) -> {deprecated,{httpc,set_option,3},"R15B"};
-obsolete_1(http, set_options, 1) -> {deprecated,{httpc,set_options,1},"R15B"};
-obsolete_1(http, set_options, 2) -> {deprecated,{httpc,set_options,2},"R15B"};
-obsolete_1(http, verify_cookies, 2) -> {deprecated,{httpc,verify_cookies,2},"R15B"};
-obsolete_1(http, verify_cookies, 3) -> {deprecated,{httpc,verify_cookies,3},"R15B"};
-obsolete_1(http, cookie_header, 1) -> {deprecated,{httpc,cookie_header,1},"R15B"};
-obsolete_1(http, cookie_header, 2) -> {deprecated,{httpc,cookie_header,2},"R15B"};
-obsolete_1(http, stream_next, 1) -> {deprecated,{httpc,stream_next,1},"R15B"};
-obsolete_1(http, default_profile, 0) -> {deprecated,{httpc,default_profile,0},"R15B"};
+obsolete_1(http, request, 1) -> {removed,{httpc,request,1},"R15B"};
+obsolete_1(http, request, 2) -> {removed,{httpc,request,2},"R15B"};
+obsolete_1(http, request, 4) -> {removed,{httpc,request,4},"R15B"};
+obsolete_1(http, request, 5) -> {removed,{httpc,request,5},"R15B"};
+obsolete_1(http, cancel_request, 1) -> {removed,{httpc,cancel_request,1},"R15B"};
+obsolete_1(http, cancel_request, 2) -> {removed,{httpc,cancel_request,2},"R15B"};
+obsolete_1(http, set_option, 2) -> {removed,{httpc,set_option,2},"R15B"};
+obsolete_1(http, set_option, 3) -> {removed,{httpc,set_option,3},"R15B"};
+obsolete_1(http, set_options, 1) -> {removed,{httpc,set_options,1},"R15B"};
+obsolete_1(http, set_options, 2) -> {removed,{httpc,set_options,2},"R15B"};
+obsolete_1(http, verify_cookies, 2) -> {removed,{httpc,store_cookies,2},"R15B"};
+obsolete_1(http, verify_cookies, 3) -> {removed,{httpc,store_cookies,3},"R15B"};
+obsolete_1(http, cookie_header, 1) -> {removed,{httpc,cookie_header,1},"R15B"};
+obsolete_1(http, cookie_header, 2) -> {removed,{httpc,cookie_header,2},"R15B"};
+obsolete_1(http, stream_next, 1) -> {removed,{httpc,stream_next,1},"R15B"};
+obsolete_1(http, default_profile, 0) -> {removed,{httpc,default_profile,0},"R15B"};
obsolete_1(httpd, start, 0) -> {removed,{inets,start,[2,3]},"R14B"};
obsolete_1(httpd, start, 1) -> {removed,{inets,start,[2,3]},"R14B"};
@@ -355,7 +449,7 @@ obsolete_1(ssl_pkix, decode_cert, A) when A =:= 1; A =:= 2 ->
%% Added in R13B04.
obsolete_1(erlang, concat_binary, 1) ->
- {deprecated,{erlang,list_to_binary,1},"R15B"};
+ {removed,{erlang,list_to_binary,1},"R15B"};
%% Added in R14A.
obsolete_1(ssl, peercert, 2) ->
@@ -367,6 +461,18 @@ obsolete_1(public_key, pem_to_der, 1) ->
obsolete_1(public_key, decode_private_key, A) when A =:= 1; A =:= 2 ->
{deprecated,{public_key,pem_entry_decode,1},"R15A"};
+%% Added in R14B03.
+obsolete_1(docb_gen, _, _) ->
+ {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"};
+obsolete_1(docb_transform, _, _) ->
+ {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"};
+obsolete_1(docb_xml_check, _, _) ->
+ {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"};
+
+%% Added in R15B
+obsolete_1(asn1rt, F, _) when F == load_driver; F == unload_driver ->
+ {deprecated,"deprecated (will be removed in R16A); has no effect as drivers are no longer used."};
+
obsolete_1(_, _, _) ->
no.
diff --git a/lib/stdlib/src/pg.erl b/lib/stdlib/src/pg.erl
index 503654e706..ee177e4e0b 100644
--- a/lib/stdlib/src/pg.erl
+++ b/lib/stdlib/src/pg.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,9 @@
%% Create a brand new empty process group with the master residing
%% at the local node
--spec create(term()) -> 'ok' | {'error', term()}.
+-spec create(PgName) -> 'ok' | {'error', Reason} when
+ PgName :: term(),
+ Reason :: 'already_created' | term().
create(PgName) ->
catch begin check(PgName),
@@ -46,7 +48,10 @@ create(PgName) ->
%% Create a brand new empty process group with the master
%% residing at Node
--spec create(term(), node()) -> 'ok' | {'error', term()}.
+-spec create(PgName, Node) -> 'ok' | {'error', Reason} when
+ PgName :: term(),
+ Node :: node(),
+ Reason :: 'already_created' | term().
create(PgName, Node) ->
catch begin check(PgName),
@@ -66,7 +71,10 @@ standby(_PgName, _Node) ->
%% Tell process group PgName that Pid is a new member of the group
%% synchronously return a list of all old members in the group
--spec join(atom(), pid()) -> [pid()].
+-spec join(PgName, Pid) -> Members when
+ PgName :: term(),
+ Pid :: pid(),
+ Members :: [pid()].
join(PgName, Pid) when is_atom(PgName) ->
global:send(PgName, {join,self(),Pid}),
@@ -77,7 +85,9 @@ join(PgName, Pid) when is_atom(PgName) ->
%% Multi cast Mess to all members in the group
--spec send(atom() | pid(), term()) -> 'ok'.
+-spec send(PgName, Msg) -> 'ok' when
+ PgName :: term(),
+ Msg :: term().
send(PgName, Mess) when is_atom(PgName) ->
global:send(PgName, {send, self(), Mess}),
@@ -89,7 +99,9 @@ send(Pg, Mess) when is_pid(Pg) ->
%% multi cast a message to all members in the group but ourselves
%% If we are a member
--spec esend(atom() | pid(), term()) -> 'ok'.
+-spec esend(PgName, Msg) -> 'ok' when
+ PgName :: term(),
+ Msg :: term().
esend(PgName, Mess) when is_atom(PgName) ->
global:send(PgName, {esend,self(),Mess}),
@@ -100,7 +112,9 @@ esend(Pg, Mess) when is_pid(Pg) ->
%% Return the members of the group
--spec members(atom() | pid()) -> [pid()].
+-spec members(PgName) -> Members when
+ PgName :: term(),
+ Members :: [pid()].
members(PgName) when is_atom(PgName) ->
global:send(PgName, {self() ,members}),
diff --git a/lib/stdlib/src/pool.erl b/lib/stdlib/src/pool.erl
index 7f5f23e26d..a5eb191ab2 100644
--- a/lib/stdlib/src/pool.erl
+++ b/lib/stdlib/src/pool.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -52,11 +52,16 @@
%% Start up using the .hosts.erlang file
--spec start(atom()) -> [node()].
+-spec start(Name) -> Nodes when
+ Name :: atom(),
+ Nodes :: [node()].
start(Name) ->
start(Name,[]).
--spec start(atom(), string()) -> [node()].
+-spec start(Name, Args) -> Nodes when
+ Name :: atom(),
+ Args :: string(),
+ Nodes :: [node()].
start(Name, Args) when is_atom(Name) ->
gen_server:start({global, pool_master}, pool, [], []),
Hosts = net_adm:host_file(),
@@ -71,7 +76,8 @@ start(Name, Args) when is_atom(Name) ->
get_nodes() ->
get_elements(2, get_nodes_and_load()).
--spec attach(node()) -> 'already_attached' | 'attached'.
+-spec attach(Node) -> 'already_attached' | 'attached' when
+ Node :: node().
attach(Node) ->
gen_server:call({global, pool_master}, {attach, Node}).
@@ -82,11 +88,17 @@ get_nodes_and_load() ->
get_node() ->
gen_server:call({global, pool_master}, get_node).
--spec pspawn(module(), atom(), [term()]) -> pid().
+-spec pspawn(Mod, Fun, Args) -> pid() when
+ Mod :: module(),
+ Fun :: atom(),
+ Args :: [term()].
pspawn(M, F, A) ->
gen_server:call({global, pool_master}, {spawn, group_leader(), M, F, A}).
--spec pspawn_link(module(), atom(), [term()]) -> pid().
+-spec pspawn_link(Mod, Fun, Args) -> pid() when
+ Mod :: module(),
+ Fun :: atom(),
+ Args :: [term()].
pspawn_link(M, F, A) ->
P = pspawn(M, F, A),
link(P),
@@ -95,6 +107,9 @@ pspawn_link(M, F, A) ->
start_nodes([], _, _) -> [];
start_nodes([Host|Tail], Name, Args) ->
case slave:start(Host, Name, Args) of
+ {error, {already_running, Node}} ->
+ io:format("Can't start node on host ~w due to ~w~n",[Host, {already_running, Node}]),
+ [Node | start_nodes(Tail, Name, Args)];
{error, R} ->
io:format("Can't start node on host ~w due to ~w~n",[Host, R]),
start_nodes(Tail, Name, Args);
diff --git a/lib/stdlib/src/proc_lib.erl b/lib/stdlib/src/proc_lib.erl
index 4fb64a3353..02bcbb5a60 100644
--- a/lib/stdlib/src/proc_lib.erl
+++ b/lib/stdlib/src/proc_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,77 +40,108 @@
-type priority_level() :: 'high' | 'low' | 'max' | 'normal'.
-type spawn_option() :: 'link'
+ | 'monitor'
| {'priority', priority_level()}
| {'min_heap_size', non_neg_integer()}
+ | {'min_bin_vheap_size', non_neg_integer()}
| {'fullsweep_after', non_neg_integer()}.
--type dict_or_pid() :: pid() | [_] | {integer(), integer(), integer()}.
+-type dict_or_pid() :: pid()
+ | (ProcInfo :: [_])
+ | {X :: integer(), Y :: integer(), Z :: integer()}.
%%-----------------------------------------------------------------------------
--spec spawn(function()) -> pid().
+-spec spawn(Fun) -> pid() when
+ Fun :: function().
spawn(F) when is_function(F) ->
Parent = get_my_name(),
Ancestors = get_ancestors(),
erlang:spawn(?MODULE, init_p, [Parent,Ancestors,F]).
--spec spawn(atom(), atom(), [term()]) -> pid().
+-spec spawn(Module, Function, Args) -> pid() when
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()].
spawn(M,F,A) when is_atom(M), is_atom(F), is_list(A) ->
Parent = get_my_name(),
Ancestors = get_ancestors(),
erlang:spawn(?MODULE, init_p, [Parent,Ancestors,M,F,A]).
--spec spawn_link(function()) -> pid().
+-spec spawn_link(Fun) -> pid() when
+ Fun :: function().
spawn_link(F) when is_function(F) ->
Parent = get_my_name(),
Ancestors = get_ancestors(),
erlang:spawn_link(?MODULE, init_p, [Parent,Ancestors,F]).
--spec spawn_link(atom(), atom(), [term()]) -> pid().
+-spec spawn_link(Module, Function, Args) -> pid() when
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()].
spawn_link(M,F,A) when is_atom(M), is_atom(F), is_list(A) ->
Parent = get_my_name(),
Ancestors = get_ancestors(),
erlang:spawn_link(?MODULE, init_p, [Parent,Ancestors,M,F,A]).
--spec spawn(node(), function()) -> pid().
+-spec spawn(Node, Fun) -> pid() when
+ Node :: node(),
+ Fun :: function().
spawn(Node, F) when is_function(F) ->
Parent = get_my_name(),
Ancestors = get_ancestors(),
erlang:spawn(Node, ?MODULE, init_p, [Parent,Ancestors,F]).
--spec spawn(node(), atom(), atom(), [term()]) -> pid().
+-spec spawn(Node, Module, Function, Args) -> pid() when
+ Node :: node(),
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()].
+
spawn(Node, M, F, A) when is_atom(M), is_atom(F), is_list(A) ->
Parent = get_my_name(),
Ancestors = get_ancestors(),
erlang:spawn(Node, ?MODULE, init_p, [Parent,Ancestors,M,F,A]).
--spec spawn_link(node(), function()) -> pid().
+-spec spawn_link(Node, Fun) -> pid() when
+ Node :: node(),
+ Fun :: function().
spawn_link(Node, F) when is_function(F) ->
Parent = get_my_name(),
Ancestors = get_ancestors(),
erlang:spawn_link(Node, ?MODULE, init_p, [Parent,Ancestors,F]).
--spec spawn_link(node(), atom(), atom(), [term()]) -> pid().
+-spec spawn_link(Node, Module, Function, Args) -> pid() when
+ Node :: node(),
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()].
spawn_link(Node, M, F, A) when is_atom(M), is_atom(F), is_list(A) ->
Parent = get_my_name(),
Ancestors = get_ancestors(),
erlang:spawn_link(Node, ?MODULE, init_p, [Parent,Ancestors,M,F,A]).
--spec spawn_opt(function(), [spawn_option()]) -> pid().
+-spec spawn_opt(Fun, SpawnOpts) -> pid() when
+ Fun :: function(),
+ SpawnOpts :: [spawn_option()].
+
spawn_opt(F, Opts) when is_function(F) ->
Parent = get_my_name(),
Ancestors = get_ancestors(),
check_for_monitor(Opts),
erlang:spawn_opt(?MODULE, init_p, [Parent,Ancestors,F],Opts).
--spec spawn_opt(node(), function(), [spawn_option()]) -> pid().
+-spec spawn_opt(Node, Function, SpawnOpts) -> pid() when
+ Node :: node(),
+ Function :: function(),
+ SpawnOpts :: [spawn_option()].
spawn_opt(Node, F, Opts) when is_function(F) ->
Parent = get_my_name(),
@@ -118,7 +149,11 @@ spawn_opt(Node, F, Opts) when is_function(F) ->
check_for_monitor(Opts),
erlang:spawn_opt(Node, ?MODULE, init_p, [Parent,Ancestors,F], Opts).
--spec spawn_opt(atom(), atom(), [term()], [spawn_option()]) -> pid().
+-spec spawn_opt(Module, Function, Args, SpawnOpts) -> pid() when
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ SpawnOpts :: [spawn_option()].
spawn_opt(M, F, A, Opts) when is_atom(M), is_atom(F), is_list(A) ->
Parent = get_my_name(),
@@ -126,7 +161,12 @@ spawn_opt(M, F, A, Opts) when is_atom(M), is_atom(F), is_list(A) ->
check_for_monitor(Opts),
erlang:spawn_opt(?MODULE, init_p, [Parent,Ancestors,M,F,A], Opts).
--spec spawn_opt(node(), atom(), atom(), [term()], [spawn_option()]) -> pid().
+-spec spawn_opt(Node, Module, Function, Args, SpawnOpts) -> pid() when
+ Node :: node(),
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ SpawnOpts :: [spawn_option()].
spawn_opt(Node, M, F, A, Opts) when is_atom(M), is_atom(F), is_list(A) ->
Parent = get_my_name(),
@@ -144,7 +184,10 @@ check_for_monitor(SpawnOpts) ->
false
end.
--spec hibernate(module(), atom(), [term()]) -> no_return().
+-spec hibernate(Module, Function, Args) -> no_return() when
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()].
hibernate(M, F, A) when is_atom(M), is_atom(F), is_list(A) ->
erlang:hibernate(?MODULE, wake_up, [M, F, A]).
@@ -210,35 +253,65 @@ exit_p(Class, Reason) ->
exit(Reason)
end.
--spec start(atom(), atom(), [term()]) -> term().
+-spec start(Module, Function, Args) -> Ret when
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Ret :: term() | {error, Reason :: term()}.
start(M, F, A) when is_atom(M), is_atom(F), is_list(A) ->
start(M, F, A, infinity).
--spec start(atom(), atom(), [term()], timeout()) -> term().
+-spec start(Module, Function, Args, Time) -> Ret when
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Time :: timeout(),
+ Ret :: term() | {error, Reason :: term()}.
start(M, F, A, Timeout) when is_atom(M), is_atom(F), is_list(A) ->
Pid = ?MODULE:spawn(M, F, A),
sync_wait(Pid, Timeout).
--spec start(atom(), atom(), [term()], timeout(), [spawn_option()]) -> term().
+-spec start(Module, Function, Args, Time, SpawnOpts) -> Ret when
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Time :: timeout(),
+ SpawnOpts :: [spawn_option()],
+ Ret :: term() | {error, Reason :: term()}.
start(M, F, A, Timeout, SpawnOpts) when is_atom(M), is_atom(F), is_list(A) ->
Pid = ?MODULE:spawn_opt(M, F, A, SpawnOpts),
sync_wait(Pid, Timeout).
--spec start_link(atom(), atom(), [term()]) -> term().
+-spec start_link(Module, Function, Args) -> Ret when
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Ret :: term() | {error, Reason :: term()}.
start_link(M, F, A) when is_atom(M), is_atom(F), is_list(A) ->
start_link(M, F, A, infinity).
--spec start_link(atom(), atom(), [term()], timeout()) -> term().
+-spec start_link(Module, Function, Args, Time) -> Ret when
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Time :: timeout(),
+ Ret :: term() | {error, Reason :: term()}.
start_link(M, F, A, Timeout) when is_atom(M), is_atom(F), is_list(A) ->
Pid = ?MODULE:spawn_link(M, F, A),
sync_wait(Pid, Timeout).
--spec start_link(atom(),atom(),[term()],timeout(),[spawn_option()]) -> term().
+-spec start_link(Module, Function, Args, Time, SpawnOpts) -> Ret when
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Time :: timeout(),
+ SpawnOpts :: [spawn_option()],
+ Ret :: term() | {error, Reason :: term()}.
start_link(M,F,A,Timeout,SpawnOpts) when is_atom(M), is_atom(F), is_list(A) ->
Pid = ?MODULE:spawn_opt(M, F, A, ensure_link(SpawnOpts)),
@@ -267,13 +340,17 @@ flush(Pid) ->
true
end.
--spec init_ack(pid(), term()) -> 'ok'.
+-spec init_ack(Parent, Ret) -> 'ok' when
+ Parent :: pid(),
+ Ret :: term().
init_ack(Parent, Return) ->
Parent ! {ack, self(), Return},
ok.
--spec init_ack(term()) -> 'ok'.
+-spec init_ack(Ret) -> 'ok' when
+ Ret :: term().
+
init_ack(Return) ->
[Parent|_] = get('$ancestors'),
init_ack(Parent, Return).
@@ -282,7 +359,11 @@ init_ack(Return) ->
%% Fetch the initial call of a proc_lib spawned process.
%% -----------------------------------------------------
--spec initial_call(dict_or_pid()) -> {atom(), atom(), [atom()]} | 'false'.
+-spec initial_call(Process) -> {Module, Function, Args} | 'false' when
+ Process :: dict_or_pid(),
+ Module :: module(),
+ Function :: atom(),
+ Args :: [atom()].
initial_call(DictOrPid) ->
case raw_initial_call(DictOrPid) of
@@ -305,7 +386,11 @@ make_dummy_args(N, Acc) ->
%% This function is typically called from c:i() and c:regs().
%% -----------------------------------------------------
--spec translate_initial_call(dict_or_pid()) -> mfa().
+-spec translate_initial_call(Process) -> {Module, Function, Arity} when
+ Process :: dict_or_pid(),
+ Module :: module(),
+ Function :: atom(),
+ Arity :: byte().
translate_initial_call(DictOrPid) ->
case raw_initial_call(DictOrPid) of
@@ -577,7 +662,8 @@ check(Res) -> Res.
%%% Format (and write) a generated crash info structure.
%%% -----------------------------------------------------------
--spec format([term()]) -> string().
+-spec format(CrashReport) -> string() when
+ CrashReport :: [term()].
format([OwnReport,LinkReport]) ->
OwnFormat = format_report(OwnReport),
diff --git a/lib/stdlib/src/proplists.erl b/lib/stdlib/src/proplists.erl
index 6a45e0f868..e3eda5d932 100644
--- a/lib/stdlib/src/proplists.erl
+++ b/lib/stdlib/src/proplists.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%%
%% The 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 @@
%% overriding the default settings, object properties, annotations,
%% etc.</p>
%%
-%% @type property() = atom() | tuple()
+%% % @type property() = atom() | tuple()
-module(proplists).
@@ -49,18 +49,13 @@
%% ---------------------------------------------------------------------
--export_type([property/0]).
+-export_type([property/0, proplist/0]).
-type property() :: atom() | tuple().
-
--type aliases() :: [{any(), any()}].
--type negations() :: [{any(), any()}].
--type expansions() :: [{property(), [any()]}].
+-type proplist() :: [property()].
%% ---------------------------------------------------------------------
-%% @spec property(P::property()) -> property()
-%%
%% @doc Creates a normal form (minimal) representation of a property. If
%% <code>P</code> is <code>{Key, true}</code> where <code>Key</code> is
%% an atom, this returns <code>Key</code>, otherwise the whole term
@@ -68,7 +63,8 @@
%%
%% @see property/2
--spec property(property()) -> property().
+-spec property(Property) -> Property when
+ Property :: property().
property({Key, true}) when is_atom(Key) ->
Key;
@@ -76,8 +72,6 @@ property(Property) ->
Property.
-%% @spec property(Key::term(), Value::term()) -> property()
-%%
%% @doc Creates a normal form (minimal) representation of a simple
%% key/value property. Returns <code>Key</code> if <code>Value</code> is
%% <code>true</code> and <code>Key</code> is an atom, otherwise a tuple
@@ -85,7 +79,10 @@ property(Property) ->
%%
%% @see property/1
--spec property(Key::term(), Value::term()) -> atom() | {term(), term()}.
+-spec property(Key, Value) -> Property when
+ Key :: term(),
+ Value :: term(),
+ Property :: atom() | {term(), term()}.
property(Key, true) when is_atom(Key) ->
Key;
@@ -95,14 +92,13 @@ property(Key, Value) ->
%% ---------------------------------------------------------------------
-%% @spec unfold(List::[term()]) -> [term()]
-%%
%% @doc Unfolds all occurences of atoms in <code>List</code> to tuples
%% <code>{Atom, true}</code>.
%%
%% @see compact/1
--spec unfold(List::[term()]) -> [term()].
+-spec unfold(List) -> List when
+ List :: [term()].
unfold([P | Ps]) ->
if is_atom(P) ->
@@ -113,15 +109,14 @@ unfold([P | Ps]) ->
unfold([]) ->
[].
-%% @spec compact(List::[term()]) -> [term()]
-%%
%% @doc Minimizes the representation of all entries in the list. This is
%% equivalent to <code>[property(P) || P &lt;- List]</code>.
%%
%% @see unfold/1
%% @see property/1
--spec compact(List::[property()]) -> [property()].
+-spec compact(List) -> List when
+ List :: [property()].
compact(List) ->
[property(P) || P <- List].
@@ -129,8 +124,6 @@ compact(List) ->
%% ---------------------------------------------------------------------
-%% @spec lookup(Key::term(), List::[term()]) -> none | tuple()
-%%
%% @doc Returns the first entry associated with <code>Key</code> in
%% <code>List</code>, if one exists, otherwise returns
%% <code>none</code>. For an atom <code>A</code> in the list, the tuple
@@ -140,7 +133,9 @@ compact(List) ->
%% @see get_value/2
%% @see get_bool/2
--spec lookup(Key::term(), List::[term()]) -> 'none' | tuple().
+-spec lookup(Key, List) -> 'none' | tuple() when
+ Key :: term(),
+ List :: [term()].
lookup(Key, [P | Ps]) ->
if is_atom(P), P =:= Key ->
@@ -154,15 +149,15 @@ lookup(Key, [P | Ps]) ->
lookup(_Key, []) ->
none.
-%% @spec lookup_all(Key::term(), List::[term()]) -> [tuple()]
-%%
%% @doc Returns the list of all entries associated with <code>Key</code>
%% in <code>List</code>. If no such entry exists, the result is the
%% empty list.
%%
%% @see lookup/2
--spec lookup_all(Key::term(), List::[term()]) -> [tuple()].
+-spec lookup_all(Key, List) -> [tuple()] when
+ Key :: term(),
+ List :: [term()].
lookup_all(Key, [P | Ps]) ->
if is_atom(P), P =:= Key ->
@@ -178,13 +173,13 @@ lookup_all(_Key, []) ->
%% ---------------------------------------------------------------------
-%% @spec is_defined(Key::term(), List::[term()]) -> boolean()
-%%
%% @doc Returns <code>true</code> if <code>List</code> contains at least
%% one entry associated with <code>Key</code>, otherwise
%% <code>false</code> is returned.
--spec is_defined(Key::term(), List::[term()]) -> boolean().
+-spec is_defined(Key, List) -> boolean() when
+ Key :: term(),
+ List :: [term()].
is_defined(Key, [P | Ps]) ->
if is_atom(P), P =:= Key ->
@@ -200,17 +195,15 @@ is_defined(_Key, []) ->
%% ---------------------------------------------------------------------
-%% @spec get_value(Key::term(), List::[term()]) -> term()
%% @equiv get_value(Key, List, undefined)
--spec get_value(Key::term(), List::[term()]) -> term().
+-spec get_value(Key, List) -> term() when
+ Key :: term(),
+ List :: List::[term()].
get_value(Key, List) ->
get_value(Key, List, undefined).
-%% @spec get_value(Key::term(), List::[term()], Default::term()) ->
-%% term()
-%%
%% @doc Returns the value of a simple key/value property in
%% <code>List</code>. If <code>lookup(Key, List)</code> would yield
%% <code>{Key, Value}</code>, this function returns the corresponding
@@ -221,7 +214,10 @@ get_value(Key, List) ->
%% @see get_all_values/2
%% @see get_bool/2
--spec get_value(Key::term(), List::[term()], Default::term()) -> term().
+-spec get_value(Key, List, Default) -> term() when
+ Key :: term(),
+ List :: [term()],
+ Default :: term().
get_value(Key, [P | Ps], Default) ->
if is_atom(P), P =:= Key ->
@@ -240,8 +236,6 @@ get_value(Key, [P | Ps], Default) ->
get_value(_Key, [], Default) ->
Default.
-%% @spec get_all_values(Key, List) -> [term()]
-%%
%% @doc Similar to <code>get_value/2</code>, but returns the list of
%% values for <em>all</em> entries <code>{Key, Value}</code> in
%% <code>List</code>. If no such entry exists, the result is the empty
@@ -249,7 +243,9 @@ get_value(_Key, [], Default) ->
%%
%% @see get_value/2
--spec get_all_values(Key::term(), List::[term()]) -> [term()].
+-spec get_all_values(Key, List) -> [term()] when
+ Key :: term(),
+ List :: [term()].
get_all_values(Key, [P | Ps]) ->
if is_atom(P), P =:= Key ->
@@ -267,8 +263,6 @@ get_all_values(Key, [P | Ps]) ->
get_all_values(_Key, []) ->
[].
-%% @spec append_values(Key::term(), List::[term()]) -> [term()]
-%%
%% @doc Similar to <code>get_all_values/2</code>, but each value is
%% wrapped in a list unless it is already itself a list, and the
%% resulting list of lists is concatenated. This is often useful for
@@ -278,7 +272,9 @@ get_all_values(_Key, []) ->
%%
%% @see get_all_values/2
--spec append_values(Key::term(), List::[term()]) -> [term()].
+-spec append_values(Key, List) -> List when
+ Key :: term(),
+ List :: [term()].
append_values(Key, [P | Ps]) ->
if is_atom(P), P =:= Key ->
@@ -301,8 +297,6 @@ append_values(_Key, []) ->
%% ---------------------------------------------------------------------
-%% @spec get_bool(Key::term(), List::[term()]) -> boolean()
-%%
%% @doc Returns the value of a boolean key/value option. If
%% <code>lookup(Key, List)</code> would yield <code>{Key, true}</code>,
%% this function returns <code>true</code>; otherwise <code>false</code>
@@ -311,7 +305,9 @@ append_values(_Key, []) ->
%% @see lookup/2
%% @see get_value/2
--spec get_bool(Key::term(), List::[term()]) -> boolean().
+-spec get_bool(Key, List) -> boolean() when
+ Key :: term(),
+ List :: [term()].
get_bool(Key, [P | Ps]) ->
if is_atom(P), P =:= Key ->
@@ -333,12 +329,11 @@ get_bool(_Key, []) ->
%% ---------------------------------------------------------------------
-%% @spec get_keys(List::[term()]) -> [term()]
-%%
%% @doc Returns an unordered list of the keys used in <code>List</code>,
%% not containing duplicates.
--spec get_keys(List::[term()]) -> [term()].
+-spec get_keys(List) -> [term()] when
+ List :: [term()].
get_keys(Ps) ->
sets:to_list(get_keys(Ps, sets:new())).
@@ -357,12 +352,12 @@ get_keys([], Keys) ->
%% ---------------------------------------------------------------------
-%% @spec delete(Key::term(), List::[term()]) -> [term()]
-%%
%% @doc Deletes all entries associated with <code>Key</code> from
%% <code>List</code>.
--spec delete(Key::term(), List::[term()]) -> [term()].
+-spec delete(Key, List) -> List when
+ Key :: term(),
+ List::[term()].
delete(Key, [P | Ps]) ->
if is_atom(P), P =:= Key ->
@@ -378,11 +373,6 @@ delete(_, []) ->
%% ---------------------------------------------------------------------
-%% @spec substitute_aliases(Aliases, List::[term()]) -> [term()]
-%%
-%% Aliases = [{Key, Key}]
-%% Key = term()
-%%
%% @doc Substitutes keys of properties. For each entry in
%% <code>List</code>, if it is associated with some key <code>K1</code>
%% such that <code>{K1, K2}</code> occurs in <code>Aliases</code>, the
@@ -398,7 +388,10 @@ delete(_, []) ->
%% @see substitute_negations/2
%% @see normalize/2
--spec substitute_aliases(aliases(), List::[term()]) -> [term()].
+-spec substitute_aliases(Aliases, List) -> List when
+ Aliases :: [{Key, Key}],
+ Key :: term(),
+ List::[term()].
substitute_aliases(As, Props) ->
[substitute_aliases_1(As, P) || P <- Props].
@@ -417,11 +410,6 @@ substitute_aliases_1([], P) ->
%% ---------------------------------------------------------------------
-%% @spec substitute_negations(Negations, List::[term()]) -> [term()]
-%%
-%% Negations = [{Key, Key}]
-%% Key = term()
-%%
%% @doc Substitutes keys of boolean-valued properties and simultaneously
%% negates their values. For each entry in <code>List</code>, if it is
%% associated with some key <code>K1</code> such that <code>{K1,
@@ -443,7 +431,10 @@ substitute_aliases_1([], P) ->
%% @see substitute_aliases/2
%% @see normalize/2
--spec substitute_negations(negations(), List::[term()]) -> [term()].
+-spec substitute_negations(Negations, List) -> List when
+ Negations :: [{Key, Key}],
+ Key :: term(),
+ List :: [term()].
substitute_negations(As, Props) ->
[substitute_negations_1(As, P) || P <- Props].
@@ -472,10 +463,6 @@ substitute_negations_1([], P) ->
%% ---------------------------------------------------------------------
-%% @spec expand(Expansions, List::[term()]) -> [term()]
-%%
-%% Expansions = [{property(), [term()]}]
-%%
%% @doc Expands particular properties to corresponding sets of
%% properties (or other terms). For each pair <code>{Property,
%% Expansion}</code> in <code>Expansions</code>, if <code>E</code> is
@@ -510,7 +497,9 @@ substitute_negations_1([], P) ->
%%
%% @see normalize/2
--spec expand(Expansions::expansions(), [term()]) -> [term()].
+-spec expand(Expansions, List) -> List when
+ Expansions :: [{Property :: property(), Expansion :: [term()]}],
+ List :: [term()].
expand(Es, Ps) when is_list(Ps) ->
Es1 = [{property(P), V} || {P, V} <- Es],
@@ -589,15 +578,6 @@ flatten([]) ->
%% ---------------------------------------------------------------------
-%% @spec normalize(List::[term()], Stages::[Operation]) -> [term()]
-%%
-%% Operation = {aliases, Aliases} | {negations, Negations}
-%% | {expand, Expansions}
-%% Aliases = [{Key, Key}]
-%% Negations = [{Key, Key}]
-%% Key = term()
-%% Expansions = [{property(), [term()]}]
-%%
%% @doc Passes <code>List</code> through a sequence of
%% substitution/expansion stages. For an <code>aliases</code> operation,
%% the function <code>substitute_aliases/2</code> is applied using the
@@ -619,11 +599,15 @@ flatten([]) ->
%% @see expand/2
%% @see compact/1
--type operation() :: {'aliases', aliases()}
- | {'negations', negations()}
- | {'expand', expansions()}.
-
--spec normalize(List::[term()], Stages::[operation()]) -> [term()].
+-spec normalize(List, Stages) -> List when
+ List :: [term()],
+ Stages :: [Operation],
+ Operation :: {'aliases', Aliases}
+ | {'negations', Negations}
+ | {'expand', Expansions},
+ Aliases :: [{Key, Key}],
+ Negations :: [{Key, Key}],
+ Expansions :: [{Property :: property(), Expansion :: [term()]}].
normalize(L, [{aliases, As} | Xs]) ->
normalize(substitute_aliases(As, L), Xs);
@@ -636,10 +620,6 @@ normalize(L, []) ->
%% ---------------------------------------------------------------------
-%% @spec split(List::[term()], Keys::[term()]) -> {Lists, Rest}
-%% Lists = [[term()]]
-%% Rest = [term()]
-%%
%% @doc Partitions <code>List</code> into a list of sublists and a
%% remainder. <code>Lists</code> contains one sublist for each key in
%% <code>Keys</code>, in the corresponding order. The relative order of
@@ -654,7 +634,11 @@ normalize(L, []) ->
%% {[[a], [{b, 5}, b],[{c, 2}, {c, 3, 4}]], [{e, 1}, d]}</pre>
%% </p>
--spec split(List::[term()], Keys::[term()]) -> {[[term()]], [term()]}.
+-spec split(List, Keys) -> {Lists, Rest} when
+ List :: [term()],
+ Keys :: [term()],
+ Lists :: [[term()]],
+ Rest :: [term()].
split(List, Keys) ->
{Store, Rest} = split(List, dict:from_list([{K, []} || K <- Keys]), []),
diff --git a/lib/stdlib/src/qlc.erl b/lib/stdlib/src/qlc.erl
index bc6944e520..f5e180b4bd 100644
--- a/lib/stdlib/src/qlc.erl
+++ b/lib/stdlib/src/qlc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -60,7 +60,7 @@
-record(qlc_table, % qlc:table/2
{trav_fun, % traverse fun
- trav_MS, % bool(); true iff traverse fun takes a match spec
+ trav_MS, % boolean(); true iff traverse fun takes a match spec
pre_fun,
post_fun,
info_fun,
@@ -110,12 +110,12 @@
-record(qlc_cursor, {c}).
-record(qlc_opt,
- {unique = false, % bool()
- cache = false, % bool() | list (true~ets, false~no)
+ {unique = false, % boolean()
+ cache = false, % boolean() | list (true~ets, false~no)
max_lookup = -1, % int() >= 0 | -1 (represents infinity)
join = any, % any | nested_loop | merge | lookup
tmpdir = "", % global tmpdir
- lookup = any, % any | bool()
+ lookup = any, % any | boolean()
max_list = ?MAX_LIST_SIZE, % int() >= 0
tmpdir_usage = allowed % allowed | not_allowed
% | warning_msg | error_msg | info_msg
@@ -123,7 +123,9 @@
-record(setup, {parent}).
--define(THROWN_ERROR, {?MODULE, throw_error, _}).
+-define(THROWN_ERROR, {?MODULE, throw_error, _, _}).
+
+-export_type([query_handle/0]).
%%% A query handle is a tuple {qlc_handle, Handle} where Handle is one
%%% of #qlc_append, #qlc_table, #qlc_sort, and #qlc_lc.
@@ -144,6 +146,35 @@ get_handle(_) ->
%%% Exported functions
%%%
+-type(query_list_comprehension() :: term()).
+-opaque(query_cursor() :: {qlc_cursor, term()}).
+-opaque(query_handle() :: {qlc_handle, term()}).
+-type(query_handle_or_list() :: query_handle() | list()).
+-type(answers() :: [answer()]).
+-type(answer() :: term()).
+-type(abstract_expr() :: erl_parse:abstract_expr()).
+-type(match_expression() :: ets:match_spec()).
+-type(spawn_options() :: default | [proc_lib:spawn_option()]).
+-type(sort_options() :: [sort_option()] | sort_option()).
+-type(sort_option() :: {compressed, boolean()}
+ | {no_files, no_files()}
+ | {order, order()}
+ | {size, pos_integer()}
+ | {tmpdir, tmp_directory()}
+ | {unique, boolean()}).
+-type(order() :: ascending | descending | order_fun()).
+-type(order_fun() :: fun((term(), term()) -> boolean())).
+-type(tmp_directory() :: [] | file:name()).
+-type(no_files() :: pos_integer()). % > 1
+-type(key_pos() :: pos_integer() | [pos_integer()]).
+-type(max_list_size() :: non_neg_integer()).
+-type(cache() :: ets | list | no).
+-type(tmp_file_usage() :: allowed | not_allowed | info_msg
+ | warning_msg | error_msg).
+
+-spec(append(QHL) -> QH when
+ QHL :: [query_handle_or_list()],
+ QH :: query_handle()).
append(QHs) ->
Hs = [case get_handle(QH) of
badarg -> erlang:error(badarg, [QHs]);
@@ -151,6 +182,10 @@ append(QHs) ->
end || QH <- QHs],
#qlc_handle{h = #qlc_append{hl = Hs}}.
+-spec(append(QH1, QH2) -> QH3 when
+ QH1 :: query_handle_or_list(),
+ QH2 :: query_handle_or_list(),
+ QH3 :: query_handle()).
append(QH1, QH2) ->
Hs = [case get_handle(QH) of
badarg -> erlang:error(badarg, [QH1, QH2]);
@@ -158,9 +193,22 @@ append(QH1, QH2) ->
end || QH <- [QH1, QH2]],
#qlc_handle{h = #qlc_append{hl = Hs}}.
+-spec(cursor(QH) -> Cursor when
+ QH :: query_handle_or_list(),
+ Cursor :: query_cursor()).
cursor(QH) ->
cursor(QH, []).
+-spec(cursor(QH, Options) -> Cursor when
+ QH :: query_handle_or_list(),
+ Options :: [Option] | Option,
+ Option :: {cache_all, cache()} | cache_all
+ | {max_list_size, max_list_size()}
+ | {spawn_options, spawn_options()}
+ | {tmpdir_usage, tmp_file_usage()}
+ | {tmpdir, tmp_directory()}
+ | {unique_all, boolean()} | unique_all,
+ Cursor :: query_cursor()).
cursor(QH, Options) ->
case {options(Options, [unique_all, cache_all, tmpdir,
spawn_options, max_list_size,
@@ -179,6 +227,8 @@ cursor(QH, Options) ->
end
end.
+-spec(delete_cursor(QueryCursor) -> ok when
+ QueryCursor :: query_cursor()).
delete_cursor(#qlc_cursor{c = {_, Owner}}=C) when Owner =/= self() ->
erlang:error(not_cursor_owner, [C]);
delete_cursor(#qlc_cursor{c = {Pid, _}}) ->
@@ -186,15 +236,47 @@ delete_cursor(#qlc_cursor{c = {Pid, _}}) ->
delete_cursor(T) ->
erlang:error(badarg, [T]).
+-spec(e(QH) -> Answers | Error when
+ QH :: query_handle_or_list(),
+ Answers :: answers(),
+ Error :: {error, module(), Reason},
+ Reason :: file_sorter:reason()).
e(QH) ->
eval(QH, []).
+-spec(e(QH, Options) -> Answers | Error when
+ QH :: query_handle_or_list(),
+ Options :: [Option] | Option,
+ Option :: {cache_all, cache()} | cache_all
+ | {max_list_size, max_list_size()}
+ | {tmpdir_usage, tmp_file_usage()}
+ | {tmpdir, tmp_directory()}
+ | {unique_all, boolean()} | unique_all,
+ Answers :: answers(),
+ Error :: {error, module(), Reason},
+ Reason :: file_sorter:reason()).
e(QH, Options) ->
eval(QH, Options).
+-spec(eval(QH) -> Answers | Error when
+ QH :: query_handle_or_list(),
+ Answers :: answers(),
+ Error :: {error, module(), Reason},
+ Reason :: file_sorter:reason()).
eval(QH) ->
eval(QH, []).
+-spec(eval(QH, Options) -> Answers | Error when
+ QH :: query_handle_or_list(),
+ Answers :: answers(),
+ Options :: [Option] | Option,
+ Option :: {cache_all, cache()} | cache_all
+ | {max_list_size, max_list_size()}
+ | {tmpdir_usage, tmp_file_usage()}
+ | {tmpdir, tmp_directory()}
+ | {unique_all, boolean()} | unique_all,
+ Error :: {error, module(), Reason},
+ Reason :: file_sorter:reason()).
eval(QH, Options) ->
case {options(Options, [unique_all, cache_all, tmpdir, max_list_size,
tmpdir_usage]),
@@ -226,9 +308,35 @@ eval(QH, Options) ->
end
end.
+-spec(fold(Function, Acc0, QH) ->
+ Acc1 | Error when
+ QH :: query_handle_or_list(),
+ Function :: fun((answer(), AccIn) -> AccOut),
+ Acc0 :: term(),
+ Acc1 :: term(),
+ AccIn :: term(),
+ AccOut :: term(),
+ Error :: {error, module(), Reason},
+ Reason :: file_sorter:reason()).
fold(Fun, Acc0, QH) ->
fold(Fun, Acc0, QH, []).
+-spec(fold(Function, Acc0, QH, Options) ->
+ Acc1 | Error when
+ QH :: query_handle_or_list(),
+ Function :: fun((answer(), AccIn) -> AccOut),
+ Acc0 :: term(),
+ Acc1 :: term(),
+ AccIn :: term(),
+ AccOut :: term(),
+ Options :: [Option] | Option,
+ Option :: {cache_all, cache()} | cache_all
+ | {max_list_size, max_list_size()}
+ | {tmpdir_usage, tmp_file_usage()}
+ | {tmpdir, tmp_directory()}
+ | {unique_all, boolean()} | unique_all,
+ Error :: {error, module(), Reason},
+ Reason :: file_sorter:reason()).
fold(Fun, Acc0, QH, Options) ->
case {options(Options, [unique_all, cache_all, tmpdir, max_list_size,
tmpdir_usage]),
@@ -258,6 +366,9 @@ fold(Fun, Acc0, QH, Options) ->
end
end.
+-spec(format_error(Error) -> Chars when
+ Error :: {error, module(), term()},
+ Chars :: io_lib:chars()).
format_error(not_a_query_list_comprehension) ->
io_lib:format("argument is not a query list comprehension", []);
format_error({used_generator_variable, V}) ->
@@ -295,9 +406,29 @@ format_error({error, Module, Reason}) ->
format_error(E) ->
io_lib:format("~p~n", [E]).
+-spec(info(QH) -> Info when
+ QH :: query_handle_or_list(),
+ Info :: abstract_expr() | string()).
info(QH) ->
info(QH, []).
+-spec(info(QH, Options) -> Info when
+ QH :: query_handle_or_list(),
+ Options :: [Option] | Option,
+ Option :: EvalOption | ReturnOption,
+ EvalOption :: {cache_all, cache()} | cache_all
+ | {max_list_size, max_list_size()}
+ | {tmpdir_usage, tmp_file_usage()}
+ | {tmpdir, tmp_directory()}
+ | {unique_all, boolean()} | unique_all,
+ ReturnOption :: {depth, Depth}
+ | {flat, boolean()}
+ | {format, Format}
+ | {n_elements, NElements},
+ Depth :: infinity | non_neg_integer(),
+ Format :: abstract_code | string,
+ NElements :: infinity | pos_integer(),
+ Info :: abstract_expr() | string()).
info(QH, Options) ->
case {options(Options, [unique_all, cache_all, flat, format, n_elements,
depth, tmpdir, max_list_size, tmpdir_usage]),
@@ -333,9 +464,18 @@ info(QH, Options) ->
end
end.
+-spec(keysort(KeyPos, QH1) -> QH2 when
+ KeyPos :: key_pos(),
+ QH1 :: query_handle_or_list(),
+ QH2 :: query_handle()).
keysort(KeyPos, QH) ->
keysort(KeyPos, QH, []).
+-spec(keysort(KeyPos, QH1, SortOptions) -> QH2 when
+ KeyPos :: key_pos(),
+ SortOptions :: sort_options(),
+ QH1 :: query_handle_or_list(),
+ QH2 :: query_handle()).
keysort(KeyPos, QH, Options) ->
case {is_keypos(KeyPos),
options(Options, [tmpdir, order, unique, compressed,
@@ -354,9 +494,22 @@ keysort(KeyPos, QH, Options) ->
-define(DEFAULT_NUM_OF_ANSWERS, 10).
+-spec(next_answers(QueryCursor) ->
+ Answers | Error when
+ QueryCursor :: query_cursor(),
+ Answers :: answers(),
+ Error :: {error, module(), Reason},
+ Reason :: file_sorter:reason()).
next_answers(C) ->
next_answers(C, ?DEFAULT_NUM_OF_ANSWERS).
+-spec(next_answers(QueryCursor, NumberOfAnswers) ->
+ Answers | Error when
+ QueryCursor :: query_cursor(),
+ Answers :: answers(),
+ NumberOfAnswers :: all_remaining | pos_integer(),
+ Error :: {error, module(), Reason},
+ Reason :: file_sorter:reason()).
next_answers(#qlc_cursor{c = {_, Owner}}=C,
NumOfAnswers) when Owner =/= self() ->
erlang:error(not_cursor_owner, [C, NumOfAnswers]);
@@ -370,14 +523,35 @@ next_answers(#qlc_cursor{c = {Pid, _}}=C, NumOfAnswers) ->
next_answers(T1, T2) ->
erlang:error(badarg, [T1, T2]).
+-spec(parse_transform(Forms, Options) -> Forms2 when
+ Forms :: [erl_parse:abstract_form()],
+ Forms2 :: [erl_parse:abstract_form()],
+ Options :: [Option],
+ Option :: type_checker | compile:option()).
+
parse_transform(Forms, Options) ->
qlc_pt:parse_transform(Forms, Options).
%% The funcspecs qlc:q/1 and qlc:q/2 are known by erl_eval.erl and
%% erl_lint.erl.
+-spec(q(QLC) -> QH when
+ QLC :: query_list_comprehension(),
+ QH :: query_handle()).
q(QLC_lc) ->
q(QLC_lc, []).
+-spec(q(QLC, Options) -> QH when
+ QH :: query_handle(),
+ Options :: [Option] | Option,
+ Option :: {max_lookup, MaxLookup}
+ | {cache, cache()} | cache
+ | {join, Join}
+ | {lookup, Lookup}
+ | {unique, boolean()} | unique,
+ MaxLookup :: non_neg_integer() | infinity,
+ Join :: any | lookup | merge | nested_loop,
+ Lookup :: boolean() | any,
+ QLC :: query_list_comprehension()).
q(#qlc_lc{}=QLC_lc, Options) ->
case options(Options, [unique, cache, max_lookup, join, lookup]) of
[Unique, Cache, Max, Join, Lookup] ->
@@ -390,9 +564,16 @@ q(#qlc_lc{}=QLC_lc, Options) ->
q(T1, T2) ->
erlang:error(badarg, [T1, T2]).
+-spec(sort(QH1) -> QH2 when
+ QH1 :: query_handle_or_list(),
+ QH2 :: query_handle()).
sort(QH) ->
sort(QH, []).
+-spec(sort(QH1, SortOptions) -> QH2 when
+ SortOptions :: sort_options(),
+ QH1 :: query_handle_or_list(),
+ QH2 :: query_handle()).
sort(QH, Options) ->
case {options(Options, [tmpdir, order, unique, compressed,
size, no_files]), get_handle(QH)} of
@@ -406,14 +587,47 @@ sort(QH, Options) ->
end.
%% Note that the generated code is evaluated by (the slow) erl_eval.
+-spec(string_to_handle(QueryString) -> QH | Error when
+ QueryString :: string(),
+ QH :: query_handle(),
+ Error :: {error, module(), Reason},
+ Reason :: erl_parse:error_info() | erl_scan:error_info()).
string_to_handle(Str) ->
string_to_handle(Str, []).
+-spec(string_to_handle(QueryString, Options) -> QH | Error when
+ QueryString :: string(),
+ Options :: [Option] | Option,
+ Option :: {max_lookup, MaxLookup}
+ | {cache, cache()} | cache
+ | {join, Join}
+ | {lookup, Lookup}
+ | {unique, boolean()} | unique,
+ MaxLookup :: non_neg_integer() | infinity,
+ Join :: any | lookup | merge | nested_loop,
+ Lookup :: boolean() | any,
+ QH :: query_handle(),
+ Error :: {error, module(), Reason},
+ Reason :: erl_parse:error_info() | erl_scan:error_info()).
string_to_handle(Str, Options) ->
- string_to_handle(Str, Options, []).
-
-string_to_handle(Str, Options, Bindings) when is_list(Str),
- is_list(Bindings) ->
+ string_to_handle(Str, Options, erl_eval:new_bindings()).
+
+-spec(string_to_handle(QueryString, Options, Bindings) -> QH | Error when
+ QueryString :: string(),
+ Options :: [Option] | Option,
+ Option :: {max_lookup, MaxLookup}
+ | {cache, cache()} | cache
+ | {join, Join}
+ | {lookup, Lookup}
+ | {unique, boolean()} | unique,
+ MaxLookup :: non_neg_integer() | infinity,
+ Join :: any | lookup | merge | nested_loop,
+ Lookup :: boolean() | any,
+ Bindings :: erl_eval:binding_struct(),
+ QH :: query_handle(),
+ Error :: {error, module(), Reason},
+ Reason :: erl_parse:error_info() | erl_scan:error_info()).
+string_to_handle(Str, Options, Bindings) when is_list(Str) ->
case options(Options, [unique, cache, max_lookup, join, lookup]) of
badarg ->
erlang:error(badarg, [Str, Options, Bindings]);
@@ -447,6 +661,51 @@ string_to_handle(Str, Options, Bindings) when is_list(Str),
string_to_handle(T1, T2, T3) ->
erlang:error(badarg, [T1, T2, T3]).
+-spec(table(TraverseFun, Options) -> QH when
+ TraverseFun :: TraverseFun0 | TraverseFun1,
+ TraverseFun0 :: fun(() -> TraverseResult),
+ TraverseFun1 :: fun((match_expression()) -> TraverseResult),
+ TraverseResult :: Objects | term(),
+ Objects :: [] | [term() | ObjectList],
+ ObjectList :: TraverseFun0 | Objects,
+ Options :: [Option] | Option,
+ Option :: {format_fun, FormatFun}
+ | {info_fun, InfoFun}
+ | {lookup_fun, LookupFun}
+ | {parent_fun, ParentFun}
+ | {post_fun, PostFun}
+ | {pre_fun, PreFun}
+ | {key_equality, KeyComparison},
+ FormatFun :: undefined | fun((SelectedObjects) -> FormatedTable),
+ SelectedObjects :: all
+ | {all, NElements, DepthFun}
+ | {match_spec, match_expression()}
+ | {lookup, Position, Keys}
+ | {lookup, Position, Keys, NElements, DepthFun},
+ NElements :: infinity | pos_integer(),
+ DepthFun :: fun((term()) -> term()),
+ FormatedTable :: {Mod, Fun, Args}
+ | abstract_expr()
+ | string(),
+ InfoFun :: undefined | fun((InfoTag) -> InfoValue),
+ InfoTag :: indices | is_unique_objects | keypos | num_of_objects,
+ InfoValue :: undefined | term(),
+ LookupFun :: undefined | fun((Position, Keys) -> LookupResult),
+ LookupResult :: [term()] | term(),
+ ParentFun :: undefined | fun(() -> ParentFunValue),
+ PostFun :: undefined | fun(() -> term()),
+ PreFun :: undefined | fun((PreArgs) -> term()),
+ PreArgs :: [PreArg],
+ PreArg :: {parent_value, ParentFunValue} | {stop_fun, StopFun},
+ ParentFunValue :: undefined | term(),
+ StopFun :: undefined | fun(() -> term()),
+ KeyComparison :: '=:=' | '==',
+ Position :: pos_integer(),
+ Keys :: [term()],
+ Mod :: atom(),
+ Fun :: atom(),
+ Args :: [term()],
+ QH :: query_handle()).
table(TraverseFun, Options) when is_function(TraverseFun) ->
case {is_function(TraverseFun, 0),
IsFun1 = is_function(TraverseFun, 1)} of
@@ -472,6 +731,11 @@ table(TraverseFun, Options) when is_function(TraverseFun) ->
table(T1, T2) ->
erlang:error(badarg, [T1, T2]).
+-spec(transform_from_evaluator(LC, Bs) -> Expr when
+ LC :: abstract_expr(),
+ Expr :: abstract_expr(),
+ Bs :: erl_eval:binding_struct()).
+
transform_from_evaluator(LC, Bs0) ->
qlc_pt:transform_from_evaluator(LC, Bs0).
@@ -722,8 +986,8 @@ listify(T) ->
%% Optimizations to be carried out.
-record(optz,
- {unique = false, % bool()
- cache = false, % bool() | list
+ {unique = false, % boolean()
+ cache = false, % boolean() | list
join_option = any, % constraint set by the 'join' option
fast_join = no, % no | #qlc_join. 'no' means nested loop.
opt % #qlc_opt
@@ -756,8 +1020,8 @@ listify(T) ->
lu_skip_quals = [], % qualifiers to skip due to lookup
join = {[],[]}, % {Lookup, Merge}
n_objs = undefined, % for join (not used yet)
- is_unique_objects = false, % bool()
- is_cached = false % bool() (true means 'ets' or 'list')
+ is_unique_objects = false, % boolean()
+ is_cached = false % boolean() (true means 'ets' or 'list')
}).
%%% Cursor process functions.
@@ -1143,20 +1407,20 @@ monitor_request(Pid, Req) ->
%% QueryDesc = {qlc, TemplateDesc, [QualDesc], [QueryOpt]}
%% | {table, TableDesc}
%% | {append, [QueryDesc]}
-%% | {sort, QueryDesc, [SortOption]}
-%% | {keysort, KeyPos, QueryDesc, [SortOption]}
+%% | {sort, QueryDesc, [sort_option()]}
+%% | {keysort, key_pos(), QueryDesc, [sort_option()]}
%% | {list, list()}
-%% | {list, QueryDesc, MatchExpression}
+%% | {list, QueryDesc, match_expression()}
%% TableDesc = {Mod, Fun, Args}
-%% | AbstractExpression
-%% | character_list()
+%% | erl_parse:abstract_expr()
+%% | string()
%% Mod = module()
%% Fun = atom()
%% Args = [term()]
%% QualDesc = FilterDesc
%% | {generate, PatternDesc, QueryDesc}
-%% QueryOpt = {cache, bool()} | cache
-%% | {unique, bool()} | unique
+%% QueryOpt = {cache, boolean()} | cache
+%% | {unique, boolean()} | unique
%% FilterDesc = PatternDesc = TemplateDesc = binary()
le_info(#prepared{qh = #simple_qlc{le = LE, p = P, line = L, optz = Optz}},
@@ -3437,7 +3701,8 @@ lookup_join(F1, C1, LuF, C2, Rev) ->
maybe_error_logger(allowed, _) ->
ok;
maybe_error_logger(Name, Why) ->
- [_, _, {?MODULE,maybe_error_logger,_} | Stacktrace] = expand_stacktrace(),
+ [_, _, {?MODULE,maybe_error_logger,_,_} | Stacktrace] =
+ expand_stacktrace(),
Trimmer = fun(M, _F, _A) -> M =:= erl_eval end,
Formater = fun(Term, I) -> io_lib:print(Term, I, 80, -1) end,
X = lib:format_stacktrace(1, Stacktrace, Trimmer, Formater),
@@ -3456,7 +3721,7 @@ expand_stacktrace() ->
expand_stacktrace(D) ->
_ = erlang:system_flag(backtrace_depth, D),
{'EXIT', {foo, Stacktrace}} = (catch erlang:error(foo)),
- L = lists:takewhile(fun({M,_,_}) -> M =/= ?MODULE
+ L = lists:takewhile(fun({M,_,_,_}) -> M =/= ?MODULE
end, lists:reverse(Stacktrace)),
if
length(L) < 3 andalso length(Stacktrace) =:= D ->
diff --git a/lib/stdlib/src/qlc_pt.erl b/lib/stdlib/src/qlc_pt.erl
index 24378a0698..21504d707b 100644
--- a/lib/stdlib/src/qlc_pt.erl
+++ b/lib/stdlib/src/qlc_pt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -63,6 +63,12 @@
%%% Exported functions
%%%
+-spec(parse_transform(Forms, Options) -> Forms2 when
+ Forms :: [erl_parse:abstract_form()],
+ Forms2 :: [erl_parse:abstract_form()],
+ Options :: [Option],
+ Option :: type_checker | compile:option()).
+
parse_transform(Forms, Options) ->
?DEBUG("qlc Parse Transform~n", []),
State = #state{imp = is_qlc_q_imported(Forms),
@@ -96,10 +102,20 @@ parse_transform(Forms, Options) ->
end
end.
+-spec(transform_from_evaluator(LC, Bs) -> Expr when
+ LC :: erl_parse:abstract_expr(),
+ Expr :: erl_parse:abstract_expr(),
+ Bs :: erl_eval:binding_struct()).
+
transform_from_evaluator(LC, Bindings) ->
?DEBUG("qlc Parse Transform (Evaluator Version)~n", []),
transform_expression(LC, Bindings, false).
+-spec(transform_expression(LC, Bs) -> Expr when
+ LC :: erl_parse:abstract_expr(),
+ Expr :: erl_parse:abstract_expr(),
+ Bs :: erl_eval:binding_struct()).
+
transform_expression(LC, Bindings) ->
transform_expression(LC, Bindings, true).
diff --git a/lib/stdlib/src/queue.erl b/lib/stdlib/src/queue.erl
index c09079e8d2..afe917b151 100644
--- a/lib/stdlib/src/queue.erl
+++ b/lib/stdlib/src/queue.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -56,14 +56,14 @@
new() -> {[],[]}. %{RearList,FrontList}
%% O(1)
--spec is_queue(term()) -> boolean().
+-spec is_queue(Term :: term()) -> boolean().
is_queue({R,F}) when is_list(R), is_list(F) ->
true;
is_queue(_) ->
false.
%% O(1)
--spec is_empty(queue()) -> boolean().
+-spec is_empty(Q :: queue()) -> boolean().
is_empty({[],[]}) ->
true;
is_empty({In,Out}) when is_list(In), is_list(Out) ->
@@ -72,14 +72,14 @@ is_empty(Q) ->
erlang:error(badarg, [Q]).
%% O(len(Q))
--spec len(queue()) -> non_neg_integer().
+-spec len(Q :: queue()) -> non_neg_integer().
len({R,F}) when is_list(R), is_list(F) ->
length(R)+length(F);
len(Q) ->
erlang:error(badarg, [Q]).
%% O(len(Q))
--spec to_list(queue()) -> list().
+-spec to_list(Q :: queue()) -> list().
to_list({In,Out}) when is_list(In), is_list(Out) ->
Out++lists:reverse(In, []);
to_list(Q) ->
@@ -88,7 +88,7 @@ to_list(Q) ->
%% Create queue from list
%%
%% O(length(L))
--spec from_list(list()) -> queue().
+-spec from_list(L :: list()) -> queue().
from_list(L) when is_list(L) ->
f2r(L);
from_list(L) ->
@@ -97,7 +97,7 @@ from_list(L) ->
%% Return true or false depending on if element is in queue
%%
%% O(length(Q)) worst case
--spec member(term(), queue()) -> boolean().
+-spec member(Item :: term(), Q :: queue()) -> boolean().
member(X, {R,F}) when is_list(R), is_list(F) ->
lists:member(X, R) orelse lists:member(X, F);
member(X, Q) ->
@@ -110,7 +110,7 @@ member(X, Q) ->
%% Put at least one element in each list, if it is cheap
%%
%% O(1)
--spec in(term(), queue()) -> queue().
+-spec in(Item :: term(), Q1 :: queue()) -> Q2 :: queue().
in(X, {[_]=In,[]}) ->
{[X], In};
in(X, {In,Out}) when is_list(In), is_list(Out) ->
@@ -122,7 +122,7 @@ in(X, Q) ->
%% Put at least one element in each list, if it is cheap
%%
%% O(1)
--spec in_r(term(), queue()) -> queue().
+-spec in_r(Item :: term(), Q1 :: queue()) -> Q2 :: queue().
in_r(X, {[],[_]=F}) ->
{F,[X]};
in_r(X, {R,F}) when is_list(R), is_list(F) ->
@@ -133,7 +133,9 @@ in_r(X, Q) ->
%% Take from head/front
%%
%% O(1) amortized, O(len(Q)) worst case
--spec out(queue()) -> {'empty' | {'value',term()}, queue()}.
+-spec out(Q1 :: queue()) ->
+ {{value, Item :: term()}, Q2 :: queue()} |
+ {empty, Q1 :: queue()}.
out({[],[]}=Q) ->
{empty,Q};
out({[V],[]}) ->
@@ -151,7 +153,9 @@ out(Q) ->
%% Take from tail/rear
%%
%% O(1) amortized, O(len(Q)) worst case
--spec out_r(queue()) -> {'empty' | {'value',term()}, queue()}.
+-spec out_r(Q1 :: queue()) ->
+ {{value, Item :: term()}, Q2 :: queue()} |
+ {empty, Q1 :: queue()}.
out_r({[],[]}=Q) ->
{empty,Q};
out_r({[],[V]}) ->
@@ -172,7 +176,7 @@ out_r(Q) ->
%% Return the first element in the queue
%%
%% O(1) since the queue is supposed to be well formed
--spec get(queue()) -> term().
+-spec get(Q :: queue()) -> Item :: term().
get({[],[]}=Q) ->
erlang:error(empty, [Q]);
get({R,F}) when is_list(R), is_list(F) ->
@@ -191,7 +195,7 @@ get([_|R], []) -> % malformed queue -> O(len(Q))
%% Return the last element in the queue
%%
%% O(1) since the queue is supposed to be well formed
--spec get_r(queue()) -> term().
+-spec get_r(Q :: queue()) -> Item :: term().
get_r({[],[]}=Q) ->
erlang:error(empty, [Q]);
get_r({[H|_],F}) when is_list(F) ->
@@ -206,7 +210,7 @@ get_r(Q) ->
%% Return the first element in the queue
%%
%% O(1) since the queue is supposed to be well formed
--spec peek(queue()) -> 'empty' | {'value',term()}.
+-spec peek(Q :: queue()) -> empty | {value,Item :: term()}.
peek({[],[]}) ->
empty;
peek({R,[H|_]}) when is_list(R) ->
@@ -221,7 +225,7 @@ peek(Q) ->
%% Return the last element in the queue
%%
%% O(1) since the queue is supposed to be well formed
--spec peek_r(queue()) -> 'empty' | {'value',term()}.
+-spec peek_r(Q :: queue()) -> empty | {value,Item :: term()}.
peek_r({[],[]}) ->
empty;
peek_r({[H|_],F}) when is_list(F) ->
@@ -236,7 +240,7 @@ peek_r(Q) ->
%% Remove the first element and return resulting queue
%%
%% O(1) amortized
--spec drop(queue()) -> queue().
+-spec drop(Q1 :: queue()) -> Q2 :: queue().
drop({[],[]}=Q) ->
erlang:error(empty, [Q]);
drop({[_],[]}) ->
@@ -254,7 +258,7 @@ drop(Q) ->
%% Remove the last element and return resulting queue
%%
%% O(1) amortized
--spec drop_r(queue()) -> queue().
+-spec drop_r(Q1 :: queue()) -> Q2 :: queue().
drop_r({[],[]}=Q) ->
erlang:error(empty, [Q]);
drop_r({[],[_]}) ->
@@ -275,7 +279,7 @@ drop_r(Q) ->
%% Return reversed queue
%%
%% O(1)
--spec reverse(queue()) -> queue().
+-spec reverse(Q1 :: queue()) -> Q2 :: queue().
reverse({R,F}) when is_list(R), is_list(F) ->
{F,R};
reverse(Q) ->
@@ -285,7 +289,7 @@ reverse(Q) ->
%%
%% Q2 empty: O(1)
%% else: O(len(Q1))
--spec join(queue(), queue()) -> queue().
+-spec join(Q1 :: queue(), Q2 :: queue()) -> Q3 :: queue().
join({R,F}=Q, {[],[]}) when is_list(R), is_list(F) ->
Q;
join({[],[]}, {R,F}=Q) when is_list(R), is_list(F) ->
@@ -299,7 +303,8 @@ join(Q1, Q2) ->
%%
%% N = 0..len(Q)
%% O(max(N, len(Q)))
--spec split(non_neg_integer(), queue()) -> {queue(),queue()}.
+-spec split(N :: non_neg_integer(), Q1 :: queue()) ->
+ {Q2 :: queue(),Q3 :: queue()}.
split(0, {R,F}=Q) when is_list(R), is_list(F) ->
{{[],[]},Q};
split(N, {R,F}=Q) when is_integer(N), N >= 1, is_list(R), is_list(F) ->
@@ -340,7 +345,8 @@ split_r1_to_f2(N, [X|R1], F1, R2, F2) ->
%%
%% Fun(_) -> List: O(length(List) * len(Q))
%% else: O(len(Q)
--spec filter(fun((term()) -> boolean() | list()), queue()) -> queue().
+-spec filter(Fun, Q1 :: queue()) -> Q2 :: queue() when
+ Fun :: fun((Item :: term()) -> boolean() | list()).
filter(Fun, {R0,F0}) when is_function(Fun, 1), is_list(R0), is_list(F0) ->
F = filter_f(Fun, F0),
R = filter_r(Fun, R0),
@@ -416,7 +422,7 @@ filter_r(Fun, [X|R0]) ->
%% Cons to head
%%
--spec cons(term(), queue()) -> queue().
+-spec cons(Item :: term(), Q1 :: queue()) -> Q2 :: queue().
cons(X, Q) ->
in_r(X, Q).
@@ -425,7 +431,7 @@ cons(X, Q) ->
%% Return the first element in the queue
%%
%% O(1) since the queue is supposed to be well formed
--spec head(queue()) -> term().
+-spec head(Q :: queue()) -> Item :: term().
head({[],[]}=Q) ->
erlang:error(empty, [Q]);
head({R,F}) when is_list(R), is_list(F) ->
@@ -435,7 +441,7 @@ head(Q) ->
%% Remove head element and return resulting queue
%%
--spec tail(queue()) -> queue().
+-spec tail(Q1 :: queue()) -> Q2 :: queue().
tail(Q) ->
drop(Q).
@@ -443,22 +449,22 @@ tail(Q) ->
%% Cons to tail
%%
--spec snoc(queue(), term()) -> queue().
+-spec snoc(Q1 :: queue(), Item :: term()) -> Q2 :: queue().
snoc(Q, X) ->
in(X, Q).
%% Return last element
--spec daeh(queue()) -> term().
+-spec daeh(Q :: queue()) -> Item :: term().
daeh(Q) -> get_r(Q).
--spec last(queue()) -> term().
+-spec last(Q :: queue()) -> Item :: term().
last(Q) -> get_r(Q).
%% Remove last element and return resulting queue
--spec liat(queue()) -> queue().
+-spec liat(Q1 :: queue()) -> Q2 :: queue().
liat(Q) -> drop_r(Q).
--spec lait(queue()) -> queue().
+-spec lait(Q1 :: queue()) -> Q2 :: queue().
lait(Q) -> drop_r(Q). %% Oops, mis-spelled 'tail' reversed. Forget this one.
--spec init(queue()) -> queue().
+-spec init(Q1 :: queue()) -> Q2 :: queue().
init(Q) -> drop_r(Q).
%%--------------------------------------------------------------------------
diff --git a/lib/stdlib/src/random.erl b/lib/stdlib/src/random.erl
index 606edbb1fb..d7b51a151c 100644
--- a/lib/stdlib/src/random.erl
+++ b/lib/stdlib/src/random.erl
@@ -57,7 +57,10 @@ seed() ->
%% seed({A1, A2, A3})
%% Seed random number generation
--spec seed({integer(), integer(), integer()}) -> 'undefined' | ran().
+-spec seed({A1, A2, A3}) -> 'undefined' | ran() when
+ A1 :: integer(),
+ A2 :: integer(),
+ A3 :: integer().
seed({A1, A2, A3}) ->
seed(A1, A2, A3).
@@ -65,7 +68,10 @@ seed({A1, A2, A3}) ->
%% seed(A1, A2, A3)
%% Seed random number generation
--spec seed(integer(), integer(), integer()) -> 'undefined' | ran().
+-spec seed(A1, A2, A3) -> 'undefined' | ran() when
+ A1 :: integer(),
+ A2 :: integer(),
+ A3 :: integer().
seed(A1, A2, A3) ->
seed_put({(abs(A1) rem (?PRIME1-1)) + 1, % Avoid seed numbers that are
@@ -99,7 +105,8 @@ uniform() ->
%% Given an integer N >= 1, uniform(N) returns a random integer
%% between 1 and N.
--spec uniform(pos_integer()) -> pos_integer().
+-spec uniform(N) -> pos_integer() when
+ N :: pos_integer().
uniform(N) when is_integer(N), N >= 1 ->
trunc(uniform() * N) + 1.
@@ -110,7 +117,9 @@ uniform(N) when is_integer(N), N >= 1 ->
%% uniform_s(State) -> {F, NewState}
%% Returns a random float between 0 and 1.
--spec uniform_s(ran()) -> {float(), ran()}.
+-spec uniform_s(State0) -> {float(), State1} when
+ State0 :: ran(),
+ State1 :: ran().
uniform_s({A1, A2, A3}) ->
B1 = (A1*171) rem ?PRIME1,
@@ -123,7 +132,10 @@ uniform_s({A1, A2, A3}) ->
%% Given an integer N >= 1, uniform(N) returns a random integer
%% between 1 and N.
--spec uniform_s(pos_integer(), ran()) -> {integer(), ran()}.
+-spec uniform_s(N, State0) -> {integer(), State1} when
+ N :: pos_integer(),
+ State0 :: ran(),
+ State1 :: ran().
uniform_s(N, State0) when is_integer(N), N >= 1 ->
{F, State1} = uniform_s(State0),
diff --git a/lib/stdlib/src/re.erl b/lib/stdlib/src/re.erl
index e2cc9f57ce..99bcbd722e 100644
--- a/lib/stdlib/src/re.erl
+++ b/lib/stdlib/src/re.erl
@@ -19,15 +19,46 @@
-module(re).
-export([grun/3,urun/3,ucompile/2,replace/3,replace/4,split/2,split/3]).
+%-opaque mp() :: {re_pattern, _, _, _}.
+-type mp() :: {re_pattern, _, _, _}.
+
+-type nl_spec() :: cr | crlf | lf | anycrlf | any.
+
+-type compile_option() :: unicode | anchored | caseless | dollar_endonly
+ | dotall | extended | firstline | multiline
+ | no_auto_capture | dupnames | ungreedy
+ | {newline, nl_spec()}| bsr_anycrlf
+ | bsr_unicode.
+
%% Emulator builtins in this module:
%% re:compile/1
%% re:compile/2
%% re:run/2
%% re:run/3
+-spec split(Subject, RE) -> SplitList when
+ Subject :: iodata() | unicode:charlist(),
+ RE :: mp() | iodata(),
+ SplitList :: [iodata() | unicode:charlist()].
+
split(Subject,RE) ->
split(Subject,RE,[]).
+-spec split(Subject, RE, Options) -> SplitList when
+ Subject :: iodata() | unicode:charlist(),
+ RE :: mp() | iodata() | unicode:charlist(),
+ Options :: [ Option ],
+ Option :: anchored | global | notbol | noteol | notempty
+ | {offset, non_neg_integer()} | {newline, nl_spec()}
+ | bsr_anycrlf | bsr_unicode | {return, ReturnType}
+ | {parts, NumParts} | group | trim | CompileOpt,
+ NumParts :: non_neg_integer() | infinity,
+ ReturnType :: iodata | list | binary,
+ CompileOpt :: compile_option(),
+ SplitList :: [RetData] | [GroupedRetData],
+ GroupedRetData :: [RetData],
+ RetData :: iodata() | unicode:charlist() | binary() | list().
+
split(Subject,RE,Options) ->
try
{NewOpt,Convert,Unicode,Limit,Strip,Group} =
@@ -197,10 +228,26 @@ compile_split(Pat,Options0) when not is_tuple(Pat) ->
compile_split(_,_) ->
throw(badre).
+-spec replace(Subject, RE, Replacement) -> iodata() | unicode:charlist() when
+ Subject :: iodata() | unicode:charlist(),
+ RE :: mp() | iodata(),
+ Replacement :: iodata() | unicode:charlist().
replace(Subject,RE,Replacement) ->
replace(Subject,RE,Replacement,[]).
+-spec replace(Subject, RE, Replacement, Options) -> iodata() | unicode:charlist() when
+ Subject :: iodata() | unicode:charlist(),
+ RE :: mp() | iodata() | unicode:charlist(),
+ Replacement :: iodata() | unicode:charlist(),
+ Options :: [Option],
+ Option :: anchored | global | notbol | noteol | notempty
+ | {offset, non_neg_integer()} | {newline, NLSpec} | bsr_anycrlf
+ | bsr_unicode | {return, ReturnType} | CompileOpt,
+ ReturnType :: iodata | list | binary,
+ CompileOpt :: compile_option(),
+ NLSpec :: cr | crlf | lf | anycrlf | any.
+
replace(Subject,RE,Replacement,Options) ->
try
{NewOpt,Convert,Unicode} =
@@ -526,10 +573,10 @@ ucompile(RE,Options) ->
re:compile(unicode:characters_to_binary(RE,unicode),Options)
catch
error:AnyError ->
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,Loc}|Rest]}} =
(catch erlang:error(new_stacktrace,
[RE,Options])),
- erlang:raise(error,AnyError,[{Mod,compile,L}|Rest])
+ erlang:raise(error,AnyError,[{Mod,compile,L,Loc}|Rest])
end.
@@ -538,10 +585,10 @@ urun(Subject,RE,Options) ->
urun2(Subject,RE,Options)
catch
error:AnyError ->
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,Loc}|Rest]}} =
(catch erlang:error(new_stacktrace,
[Subject,RE,Options])),
- erlang:raise(error,AnyError,[{Mod,run,L}|Rest])
+ erlang:raise(error,AnyError,[{Mod,run,L,Loc}|Rest])
end.
urun2(Subject0,RE0,Options0) ->
@@ -578,20 +625,20 @@ grun(Subject,RE,{Options,NeedClean}) ->
grun2(Subject,RE,{Options,NeedClean})
catch
error:AnyError ->
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,Loc}|Rest]}} =
(catch erlang:error(new_stacktrace,
[Subject,RE,Options])),
- erlang:raise(error,AnyError,[{Mod,run,L}|Rest])
+ erlang:raise(error,AnyError,[{Mod,run,L,Loc}|Rest])
end;
grun(Subject,RE,{Options,NeedClean,OrigRE}) ->
try
grun2(Subject,RE,{Options,NeedClean})
catch
error:AnyError ->
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,Loc}|Rest]}} =
(catch erlang:error(new_stacktrace,
[Subject,OrigRE,Options])),
- erlang:raise(error,AnyError,[{Mod,run,L}|Rest])
+ erlang:raise(error,AnyError,[{Mod,run,L,Loc}|Rest])
end.
grun2(Subject,RE,{Options,NeedClean}) ->
diff --git a/lib/stdlib/src/regexp.erl b/lib/stdlib/src/regexp.erl
index 8f5994bbee..65f9ca247d 100644
--- a/lib/stdlib/src/regexp.erl
+++ b/lib/stdlib/src/regexp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,9 @@
-import(string, [substr/2,substr/3]).
-import(lists, [reverse/1]).
+-type errordesc() :: term().
+-opaque regexp() :: term().
+
%% -type matchres() = {match,Start,Length} | nomatch | {error,E}.
%% -type subres() = {ok,RepString,RepCount} | {error,E}.
%% -type splitres() = {ok,[SubString]} | {error,E}.
@@ -287,6 +290,10 @@ re_apply_or(R1, nomatch) -> R1.
%% Convert a sh style regexp into a full AWK one. The main difficulty is
%% getting character sets right as the conventions are different.
+-spec sh_to_awk(ShRegExp) -> AwkRegExp when
+ ShRegExp :: string(),
+ AwkRegExp :: string().
+
sh_to_awk(Sh) -> "^(" ++ sh_to_awk_1(Sh). %Fix the beginning
sh_to_awk_1([$*|Sh]) -> %This matches any string
@@ -336,6 +343,12 @@ special_char(_C) -> false.
%% parse(RegExp) -> {ok,RE} | {error,E}.
%% Parse the regexp described in the string RegExp.
+-spec parse(RegExp) -> ParseRes when
+ RegExp :: string(),
+ ParseRes :: {ok, RE} | {error, Error},
+ RE :: regexp(),
+ Error :: errordesc().
+
parse(S) ->
case catch reg(S) of
{R,[]} -> {ok,R};
@@ -345,6 +358,10 @@ parse(S) ->
%% format_error(Error) -> String.
+-spec format_error(ErrorDescriptor) -> Chars when
+ ErrorDescriptor :: errordesc(),
+ Chars :: io_lib:chars().
+
format_error({illegal,What}) -> ["illegal character `",What,"'"];
format_error({unterminated,What}) -> ["unterminated `",What,"'"];
format_error({char_class,What}) ->
@@ -353,6 +370,14 @@ format_error({char_class,What}) ->
%% -type match(String, RegExp) -> matchres().
%% Find the longest match of RegExp in String.
+-spec match(String, RegExp) -> MatchRes when
+ String :: string(),
+ RegExp :: string() | regexp(),
+ MatchRes :: {match, Start, Length} | nomatch | {error, Error},
+ Start :: pos_integer(),
+ Length :: pos_integer(),
+ Error :: errordesc().
+
match(S, RegExp) when is_list(RegExp) ->
case parse(RegExp) of
{ok,RE} -> match(S, RE);
@@ -378,6 +403,14 @@ match(RE, S, St, Pos, L) ->
%% -type first_match(String, RegExp) -> matchres().
%% Find the first match of RegExp in String.
+-spec first_match(String, RegExp) -> MatchRes when
+ String :: string(),
+ RegExp :: string() | regexp(),
+ MatchRes :: {match, Start, Length} | nomatch | {error, Error},
+ Start :: pos_integer(),
+ Length :: pos_integer(),
+ Error :: errordesc().
+
first_match(S, RegExp) when is_list(RegExp) ->
case parse(RegExp) of
{ok,RE} -> first_match(S, RE);
@@ -400,6 +433,15 @@ first_match(_RE, [], _St) -> nomatch.
%% -type matches(String, RegExp) -> {match,[{Start,Length}]} | {error,E}.
%% Return the all the non-overlapping matches of RegExp in String.
+-spec matches(String, RegExp) -> MatchRes when
+ String :: string(),
+ RegExp :: string() | regexp(),
+ MatchRes :: {match, Matches} | {error, Error},
+ Matches :: [{Start, Length}],
+ Start :: pos_integer(),
+ Length :: pos_integer(),
+ Error :: errordesc().
+
matches(S, RegExp) when is_list(RegExp) ->
case parse(RegExp) of
{ok,RE} -> matches(S, RE);
@@ -420,6 +462,15 @@ matches(S, RE, St) ->
%% the string Replace in String. Accept pre-parsed regular
%% expressions.
+-spec sub(String, RegExp, New) -> SubRes when
+ String :: string(),
+ RegExp :: string() | regexp(),
+ New :: string(),
+ NewString :: string(),
+ SubRes :: {ok, NewString, RepCount} | {error, Error},
+ RepCount :: 0 | 1,
+ Error :: errordesc().
+
sub(String, RegExp, Rep) when is_list(RegExp) ->
case parse(RegExp) of
{ok,RE} -> sub(String, RE, Rep);
@@ -449,6 +500,15 @@ sub_repl([], _M, Rest) -> Rest.
%% Substitute every match of the regular expression RegExp with the
%% string New in String. Accept pre-parsed regular expressions.
+-spec gsub(String, RegExp, New) -> SubRes when
+ String :: string(),
+ RegExp :: string() | regexp(),
+ New :: string(),
+ NewString :: string(),
+ SubRes :: {ok, NewString, RepCount} | {error, Error},
+ RepCount :: non_neg_integer(),
+ Error :: errordesc().
+
gsub(String, RegExp, Rep) when is_list(RegExp) ->
case parse(RegExp) of
{ok,RE} -> gsub(String, RE, Rep);
@@ -462,6 +522,13 @@ gsub(String, RE, Rep) ->
%% Split a string into substrings where the RegExp describes the
%% field seperator. The RegExp " " is specially treated.
+-spec split(String, RegExp) -> SplitRes when
+ String :: string(),
+ RegExp :: string() | regexp(),
+ SplitRes :: {ok, FieldList} | {error, Error},
+ FieldList :: [string()],
+ Error :: errordesc().
+
split(String, " ") -> %This is really special
{ok,RE} = parse("[ \t]+"),
case split_apply(String, RE, true) of
diff --git a/lib/stdlib/src/sets.erl b/lib/stdlib/src/sets.erl
index bcddca2567..3fd6c81e5f 100644
--- a/lib/stdlib/src/sets.erl
+++ b/lib/stdlib/src/sets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
%%
%% The 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,30 +84,38 @@ new() ->
%% is_set(Set) -> boolean().
%% Return 'true' if Set is a set of elements, else 'false'.
--spec is_set(term()) -> boolean().
+-spec is_set(Set) -> boolean() when
+ Set :: term().
is_set(#set{}) -> true;
is_set(_) -> false.
%% size(Set) -> int().
%% Return the number of elements in Set.
--spec size(set()) -> non_neg_integer().
+-spec size(Set) -> non_neg_integer() when
+ Set :: set().
size(S) -> S#set.size.
%% to_list(Set) -> [Elem].
%% Return the elements in Set as a list.
--spec to_list(set()) -> [term()].
+-spec to_list(Set) -> List when
+ Set :: set(),
+ List :: [term()].
to_list(S) ->
fold(fun (Elem, List) -> [Elem|List] end, [], S).
%% from_list([Elem]) -> Set.
%% Build a set from the elements in List.
--spec from_list([term()]) -> set().
+-spec from_list(List) -> Set when
+ List :: [term()],
+ Set :: set().
from_list(L) ->
lists:foldl(fun (E, S) -> add_element(E, S) end, new(), L).
%% is_element(Element, Set) -> boolean().
%% Return 'true' if Element is an element of Set, else 'false'.
--spec is_element(term(), set()) -> boolean().
+-spec is_element(Element, Set) -> boolean() when
+ Element :: term(),
+ Set :: set().
is_element(E, S) ->
Slot = get_slot(S, E),
Bkt = get_bucket(S, Slot),
@@ -115,7 +123,10 @@ is_element(E, S) ->
%% add_element(Element, Set) -> Set.
%% Return Set with Element inserted in it.
--spec add_element(term(), set()) -> set().
+-spec add_element(Element, Set1) -> Set2 when
+ Element :: term(),
+ Set1 :: set(),
+ Set2 :: set().
add_element(E, S0) ->
Slot = get_slot(S0, E),
{S1,Ic} = on_bucket(fun (B0) -> add_bkt_el(E, B0, B0) end, S0, Slot),
@@ -129,7 +140,10 @@ add_bkt_el(E, [], Bkt) -> {[E|Bkt],1}.
%% del_element(Element, Set) -> Set.
%% Return Set but with Element removed.
--spec del_element(term(), set()) -> set().
+-spec del_element(Element, Set1) -> Set2 when
+ Element :: term(),
+ Set1 :: set(),
+ Set2 :: set().
del_element(E, S0) ->
Slot = get_slot(S0, E),
{S1,Dc} = on_bucket(fun (B0) -> del_bkt_el(E, B0) end, S0, Slot),
@@ -144,7 +158,10 @@ del_bkt_el(_, []) -> {[],0}.
%% union(Set1, Set2) -> Set
%% Return the union of Set1 and Set2.
--spec union(set(), set()) -> set().
+-spec union(Set1, Set2) -> Set3 when
+ Set1 :: set(),
+ Set2 :: set(),
+ Set3 :: set().
union(S1, S2) when S1#set.size < S2#set.size ->
fold(fun (E, S) -> add_element(E, S) end, S2, S1);
union(S1, S2) ->
@@ -152,7 +169,9 @@ union(S1, S2) ->
%% union([Set]) -> Set
%% Return the union of the list of sets.
--spec union([set()]) -> set().
+-spec union(SetList) -> Set when
+ SetList :: [set()],
+ Set :: set().
union([S1,S2|Ss]) ->
union1(union(S1, S2), Ss);
union([S]) -> S;
@@ -165,7 +184,10 @@ union1(S1, []) -> S1.
%% intersection(Set1, Set2) -> Set.
%% Return the intersection of Set1 and Set2.
--spec intersection(set(), set()) -> set().
+-spec intersection(Set1, Set2) -> Set3 when
+ Set1 :: set(),
+ Set2 :: set(),
+ Set3 :: set().
intersection(S1, S2) when S1#set.size < S2#set.size ->
filter(fun (E) -> is_element(E, S2) end, S1);
intersection(S1, S2) ->
@@ -173,7 +195,9 @@ intersection(S1, S2) ->
%% intersection([Set]) -> Set.
%% Return the intersection of the list of sets.
--spec intersection([set(),...]) -> set().
+-spec intersection(SetList) -> Set when
+ SetList :: [set(),...],
+ Set :: set().
intersection([S1,S2|Ss]) ->
intersection1(intersection(S1, S2), Ss);
intersection([S]) -> S.
@@ -185,7 +209,9 @@ intersection1(S1, []) -> S1.
%% is_disjoint(Set1, Set2) -> boolean().
%% Check whether Set1 and Set2 are disjoint.
--spec is_disjoint(set(), set()) -> boolean().
+-spec is_disjoint(Set1, Set2) -> boolean() when
+ Set1 :: set(),
+ Set2 :: set().
is_disjoint(S1, S2) when S1#set.size < S2#set.size ->
fold(fun (_, false) -> false;
(E, true) -> not is_element(E, S2)
@@ -198,25 +224,39 @@ is_disjoint(S1, S2) ->
%% subtract(Set1, Set2) -> Set.
%% Return all and only the elements of Set1 which are not also in
%% Set2.
--spec subtract(set(), set()) -> set().
+-spec subtract(Set1, Set2) -> Set3 when
+ Set1 :: set(),
+ Set2 :: set(),
+ Set3 :: set().
subtract(S1, S2) ->
filter(fun (E) -> not is_element(E, S2) end, S1).
%% is_subset(Set1, Set2) -> boolean().
%% Return 'true' when every element of Set1 is also a member of
%% Set2, else 'false'.
--spec is_subset(set(), set()) -> boolean().
+-spec is_subset(Set1, Set2) -> boolean() when
+ Set1 :: set(),
+ Set2 :: set().
is_subset(S1, S2) ->
fold(fun (E, Sub) -> Sub andalso is_element(E, S2) end, true, S1).
%% fold(Fun, Accumulator, Set) -> Accumulator.
%% Fold function Fun over all elements in Set and return Accumulator.
--spec fold(fun((_,_) -> _), T, set()) -> T.
+-spec fold(Function, Acc0, Set) -> Acc1 when
+ Function :: fun((E :: term(),AccIn) -> AccOut),
+ Set :: set(),
+ Acc0 :: T,
+ Acc1 :: T,
+ AccIn :: T,
+ AccOut :: T.
fold(F, Acc, D) -> fold_set(F, Acc, D).
%% filter(Fun, Set) -> Set.
%% Filter Set with Fun.
--spec filter(fun((_) -> boolean()), set()) -> set().
+-spec filter(Pred, Set1) -> Set2 when
+ Pred :: fun((E :: term()) -> boolean()),
+ Set1 :: set(),
+ Set2 :: set().
filter(F, D) -> filter_set(F, D).
%% get_slot(Hashdb, Key) -> Slot.
diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl
index ebb221c151..964697cae6 100644
--- a/lib/stdlib/src/shell.erl
+++ b/lib/stdlib/src/shell.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -115,7 +115,9 @@ whereis_evaluator(Shell) ->
%% Call this function to start a user restricted shell
%% from a normal shell session.
--spec start_restricted(module()) -> {'error', code:load_error_rsn()}.
+-spec start_restricted(Module) -> {'error', Reason} when
+ Module :: module(),
+ Reason :: code:load_error_rsn().
start_restricted(RShMod) when is_atom(RShMod) ->
case code:ensure_loaded(RShMod) of
@@ -465,7 +467,7 @@ getc(N) ->
{get({command,N}), get({result,N}), N}.
get_cmd(Num, C) ->
- case catch erl_eval:expr(Num, []) of
+ case catch erl_eval:expr(Num, erl_eval:new_bindings()) of
{value,N,_} when N < 0 -> getc(C+N);
{value,N,_} -> getc(N);
_Other -> {undefined,undefined,undefined}
@@ -1086,7 +1088,7 @@ shell_default(F,As,Bs) ->
end.
shell_undef(F,A) ->
- erlang:error({shell_undef,F,A}).
+ erlang:error({shell_undef,F,A,[]}).
local_func_handler(Shell, RT, Ef) ->
H = fun(Lf) ->
@@ -1184,6 +1186,8 @@ expr(E, Bs, Lf, Ef) ->
expr_list(Es, Bs, Lf, Ef) ->
erl_eval:expr_list(Es, strip_bindings(Bs), Lf, Ef).
+-spec strip_bindings(erl_eval:binding_struct()) -> erl_eval:binding_struct().
+
strip_bindings(Bs) ->
Bs -- [B || {{module,_},_}=B <- Bs].
@@ -1468,23 +1472,26 @@ set_env(App, Name, Val, Default) ->
application_controller:set_env(App, Name, Val),
Prev.
--spec history(non_neg_integer()) -> non_neg_integer().
+-spec history(N) -> non_neg_integer() when
+ N :: non_neg_integer().
history(L) when is_integer(L), L >= 0 ->
set_env(stdlib, shell_history_length, L, ?DEF_HISTORY).
--spec results(non_neg_integer()) -> non_neg_integer().
+-spec results(N) -> non_neg_integer() when
+ N :: non_neg_integer().
results(L) when is_integer(L), L >= 0 ->
set_env(stdlib, shell_saved_results, L, ?DEF_RESULTS).
--spec catch_exception(boolean()) -> boolean().
+-spec catch_exception(Bool) -> Bool when
+ Bool :: boolean().
catch_exception(Bool) ->
set_env(stdlib, shell_catch_exception, Bool, ?DEF_CATCH_EXCEPTION).
--type prompt_func() :: 'default' | {module(),atom()}.
--spec prompt_func(prompt_func()) -> prompt_func().
+-spec prompt_func(PromptFunc) -> PromptFunc when
+ PromptFunc :: 'default' | {module(),atom()}.
prompt_func(String) ->
set_env(stdlib, shell_prompt_func, String, ?DEF_PROMPT_FUNC).
diff --git a/lib/stdlib/src/slave.erl b/lib/stdlib/src/slave.erl
index 196b659938..de0179da59 100644
--- a/lib/stdlib/src/slave.erl
+++ b/lib/stdlib/src/slave.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -54,6 +54,10 @@ pseudo([Master | ServerList]) ->
pseudo(_) ->
error_msg("No master node given to slave:pseudo/1~n",[]).
+-spec pseudo(Master, ServerList) -> ok when
+ Master :: node(),
+ ServerList :: [atom()].
+
pseudo(_, []) -> ok;
pseudo(Master, [S|Tail]) ->
start_pseudo(S, whereis(S), Master),
@@ -68,6 +72,9 @@ start_pseudo(_,_,_) -> ok. %% It's already there
%% This relay can be used to relay all messages directed to a process.
+-spec relay(Pid) -> no_return() when
+ Pid :: pid().
+
relay({badrpc,Reason}) ->
error_msg(" ** exiting relay server ~w :~w **~n", [self(),Reason]),
exit(Reason);
@@ -120,25 +127,61 @@ relay1(Pid) ->
%% {error, no_rsh} |
%% {error, {already_running, Name@Host}}
+-spec start(Host) -> {ok, Node} | {error, Reason} when
+ Host :: atom(),
+ Node :: node(),
+ Reason :: timeout | no_rsh | {already_running, Node}.
+
start(Host) ->
L = atom_to_list(node()),
Name = upto($@, L),
- start(Host, Name).
+ start(Host, Name, [], no_link).
+
+-spec start(Host, Name) -> {ok, Node} | {error, Reason} when
+ Host :: atom(),
+ Name :: atom(),
+ Node :: node(),
+ Reason :: timeout | no_rsh | {already_running, Node}.
start(Host, Name) ->
start(Host, Name, []).
+-spec start(Host, Name, Args) -> {ok, Node} | {error, Reason} when
+ Host :: atom(),
+ Name :: atom(),
+ Args :: string(),
+ Node :: node(),
+ Reason :: timeout | no_rsh | {already_running, Node}.
+
start(Host, Name, Args) ->
start(Host, Name, Args, no_link).
+-spec start_link(Host) -> {ok, Node} | {error, Reason} when
+ Host :: atom(),
+ Node :: node(),
+ Reason :: timeout | no_rsh | {already_running, Node}.
+
start_link(Host) ->
L = atom_to_list(node()),
Name = upto($@, L),
- start_link(Host, Name).
+ start(Host, Name, [], self()).
+
+-spec start_link(Host, Name) -> {ok, Node} | {error, Reason} when
+ Host :: atom(),
+ Name :: atom(),
+ Node :: node(),
+ Reason :: timeout | no_rsh | {already_running, Node}.
start_link(Host, Name) ->
start_link(Host, Name, []).
+-spec start_link(Host, Name, Args) -> {ok, Node} | {error, Reason} when
+ Host :: atom(),
+ Name :: atom(),
+ Args :: string(),
+ Node :: node(),
+ Reason :: timeout | no_rsh | {already_running, Node}.
+
start_link(Host, Name, Args) ->
start(Host, Name, Args, self()).
@@ -163,6 +206,9 @@ start(Host0, Name, Args, LinkTo, Prog) ->
%% Stops a running node.
+-spec stop(Node) -> ok when
+ Node :: node().
+
stop(Node) ->
% io:format("stop(~p)~n", [Node]),
rpc:call(Node, erlang, halt, []),
diff --git a/lib/stdlib/src/sofs.erl b/lib/stdlib/src/sofs.erl
index a83f803330..34eb224647 100644
--- a/lib/stdlib/src/sofs.erl
+++ b/lib/stdlib/src/sofs.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, 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(sofs).
@@ -40,11 +40,11 @@
substitution/2, projection/2, partition/1, partition/2,
partition/3, multiple_relative_product/2, join/4]).
--export([family_to_relation/1, family_specification/2,
+-export([family_to_relation/1, family_specification/2,
union_of_family/1, intersection_of_family/1,
family_union/1, family_intersection/1,
family_domain/1, family_range/1, family_field/1,
- family_union/2, family_intersection/2, family_difference/2,
+ family_union/2, family_intersection/2, family_difference/2,
partition_family/2, family_projection/2]).
-export([family_to_digraph/1, family_to_digraph/2,
@@ -64,9 +64,9 @@
-compile({inline, [{external_fun,1},{element_type,1}]}).
--compile({inline,
+-compile({inline,
[{unify_types,2}, {match_types,2},
- {test_rel,3}, {symdiff,3},
+ {test_rel,3}, {symdiff,3},
{subst,3}]}).
-compile({inline, [{fam_binop,3}]}).
@@ -80,13 +80,14 @@
-define(TAG, 'Set').
-define(ORDTAG, 'OrdSet').
--record(?TAG, {data = [], type = type}).
--record(?ORDTAG, {orddata = {}, ordtype = type}).
+-record(?TAG, {data = [] :: list(), type = type :: term()}).
+-record(?ORDTAG, {orddata = {} :: tuple() | atom(),
+ ordtype = type :: term()}).
-define(LIST(S), (S)#?TAG.data).
-define(TYPE(S), (S)#?TAG.type).
-%%-define(SET(L, T),
-%% case is_type(T) of
+%%-define(SET(L, T),
+%% case is_type(T) of
%% true -> #?TAG{data = L, type = T};
%% false -> erlang:error(badtype, [T])
%% end
@@ -113,14 +114,40 @@
-define(IS_SET_OF(X), is_list(X)).
-define(FAMILY(X, Y), ?BINREL(X, ?SET_OF(Y))).
+-export_type([anyset/0, binary_relation/0, external_set/0, a_function/0,
+ family/0, relation/0, set_of_sets/0, set_fun/0, spec_fun/0,
+ type/0]).
+-export_type([ordset/0, a_set/0]).
+
+-type(anyset() :: ordset() | a_set()).
+-type(binary_relation() :: relation()).
+-type(external_set() :: term()).
+-type(a_function() :: relation()).
+-type(family() :: a_function()).
+-opaque(ordset() :: #?ORDTAG{}).
+-type(relation() :: a_set()).
+-opaque(a_set() :: #?TAG{}).
+-type(set_of_sets() :: a_set()).
+-type(set_fun() :: pos_integer()
+ | {external, fun((external_set()) -> external_set())}
+ | fun((anyset()) -> anyset())).
+-type(spec_fun() :: {external, fun((external_set()) -> boolean())}
+ | fun((anyset()) -> boolean())).
+-type(type() :: term()).
+
+-type(tuple_of(_T) :: tuple()).
+
%%
%% Exported functions
%%
-%%%
+%%%
%%% Create sets
-%%%
+%%%
+-spec(from_term(Term) -> AnySet when
+ AnySet :: anyset(),
+ Term :: term()).
from_term(T) ->
Type = case T of
_ when is_list(T) -> [?ANYTYPE];
@@ -133,6 +160,10 @@ from_term(T) ->
Set
end.
+-spec(from_term(Term, Type) -> AnySet when
+ AnySet :: anyset(),
+ Term :: term(),
+ Type :: type()).
from_term(L, T) ->
case is_type(T) of
true ->
@@ -146,14 +177,23 @@ from_term(L, T) ->
erlang:error(badarg, [L, T])
end.
+-spec(from_external(ExternalSet, Type) -> AnySet when
+ ExternalSet :: external_set(),
+ AnySet :: anyset(),
+ Type :: type()).
from_external(L, ?SET_OF(Type)) ->
?SET(L, Type);
from_external(T, Type) ->
?ORDSET(T, Type).
+-spec(empty_set() -> Set when
+ Set :: a_set()).
empty_set() ->
?SET([], ?ANYTYPE).
+-spec(is_type(Term) -> Bool when
+ Bool :: boolean(),
+ Term :: term()).
is_type(Atom) when ?IS_ATOM_TYPE(Atom), Atom =/= ?ANYTYPE ->
true;
is_type(?SET_OF(T)) ->
@@ -163,19 +203,26 @@ is_type(T) when tuple_size(T) > 0 ->
is_type(_T) ->
false.
+-spec(set(Terms) -> Set when
+ Set :: a_set(),
+ Terms :: [term()]).
set(L) ->
case catch usort(L) of
{'EXIT', _} ->
erlang:error(badarg, [L]);
- SL ->
+ SL ->
?SET(SL, ?ATOM_TYPE)
end.
+-spec(set(Terms, Type) -> Set when
+ Set :: a_set(),
+ Terms :: [term()],
+ Type :: type()).
set(L, ?SET_OF(Type) = T) when ?IS_ATOM_TYPE(Type), Type =/= ?ANYTYPE ->
case catch usort(L) of
{'EXIT', _} ->
erlang:error(badarg, [L, T]);
- SL ->
+ SL ->
?SET(SL, Type)
end;
set(L, ?SET_OF(_) = T) ->
@@ -188,6 +235,12 @@ set(L, ?SET_OF(_) = T) ->
set(L, T) ->
erlang:error(badarg, [L, T]).
+-spec(from_sets(ListOfSets) -> Set when
+ Set :: a_set(),
+ ListOfSets :: [anyset()];
+ (TupleOfSets) -> Ordset when
+ Ordset :: ordset(),
+ TupleOfSets :: tuple_of(anyset())).
from_sets(Ss) when is_list(Ss) ->
case set_of_sets(Ss, [], ?ANYTYPE) of
{error, Error} ->
@@ -205,6 +258,9 @@ from_sets(Tuple) when is_tuple(Tuple) ->
from_sets(T) ->
erlang:error(badarg, [T]).
+-spec(relation(Tuples) -> Relation when
+ Relation :: relation(),
+ Tuples :: [tuple()]).
relation([]) ->
?SET([], ?BINREL(?ATOM_TYPE, ?ATOM_TYPE));
relation(Ts = [T | _]) when is_tuple(T) ->
@@ -217,6 +273,11 @@ relation(Ts = [T | _]) when is_tuple(T) ->
relation(E) ->
erlang:error(badarg, [E]).
+-spec(relation(Tuples, Type) -> Relation when
+ N :: integer(),
+ Type :: N | type(),
+ Relation :: relation(),
+ Tuples :: [tuple()]).
relation(Ts, TS) ->
case catch rel(Ts, TS) of
{'EXIT', _} ->
@@ -225,6 +286,9 @@ relation(Ts, TS) ->
Set
end.
+-spec(a_function(Tuples) -> Function when
+ Function :: a_function(),
+ Tuples :: [tuple()]).
a_function(Ts) ->
case catch func(Ts, ?BINREL(?ATOM_TYPE, ?ATOM_TYPE)) of
{'EXIT', _} ->
@@ -235,6 +299,10 @@ a_function(Ts) ->
Set
end.
+-spec(a_function(Tuples, Type) -> Function when
+ Function :: a_function(),
+ Tuples :: [tuple()],
+ Type :: type()).
a_function(Ts, T) ->
case catch a_func(Ts, T) of
{'EXIT', _} ->
@@ -245,6 +313,9 @@ a_function(Ts, T) ->
Set
end.
+-spec(family(Tuples) -> Family when
+ Family :: family(),
+ Tuples :: [tuple()]).
family(Ts) ->
case catch fam2(Ts, ?FAMILY(?ATOM_TYPE, ?ATOM_TYPE)) of
{'EXIT', _} ->
@@ -255,6 +326,10 @@ family(Ts) ->
Set
end.
+-spec(family(Tuples, Type) -> Family when
+ Family :: family(),
+ Tuples :: [tuple()],
+ Type :: type()).
family(Ts, T) ->
case catch fam(Ts, T) of
{'EXIT', _} ->
@@ -265,20 +340,30 @@ family(Ts, T) ->
Set
end.
-%%%
+%%%
%%% Functions on sets.
-%%%
+%%%
+-spec(to_external(AnySet) -> ExternalSet when
+ ExternalSet :: external_set(),
+ AnySet :: anyset()).
to_external(S) when ?IS_SET(S) ->
?LIST(S);
to_external(S) when ?IS_ORDSET(S) ->
?ORDDATA(S).
+-spec(type(AnySet) -> Type when
+ AnySet :: anyset(),
+ Type :: type()).
type(S) when ?IS_SET(S) ->
?SET_OF(?TYPE(S));
type(S) when ?IS_ORDSET(S) ->
?ORDTYPE(S).
+-spec(to_sets(ASet) -> Sets when
+ ASet :: a_set() | ordset(),
+ Sets :: tuple_of(AnySet) | [AnySet],
+ AnySet :: anyset()).
to_sets(S) when ?IS_SET(S) ->
case ?TYPE(S) of
?SET_OF(Type) -> list_of_sets(?LIST(S), Type, []);
@@ -289,6 +374,9 @@ to_sets(S) when ?IS_ORDSET(S), is_tuple(?ORDTYPE(S)) ->
to_sets(S) when ?IS_ORDSET(S) ->
erlang:error(badarg, [S]).
+-spec(no_elements(ASet) -> NoElements when
+ ASet :: a_set() | ordset(),
+ NoElements :: non_neg_integer()).
no_elements(S) when ?IS_SET(S) ->
length(?LIST(S));
no_elements(S) when ?IS_ORDSET(S), is_tuple(?ORDTYPE(S)) ->
@@ -296,6 +384,10 @@ no_elements(S) when ?IS_ORDSET(S), is_tuple(?ORDTYPE(S)) ->
no_elements(S) when ?IS_ORDSET(S) ->
erlang:error(badarg, [S]).
+-spec(specification(Fun, Set1) -> Set2 when
+ Fun :: spec_fun(),
+ Set1 :: a_set(),
+ Set2 :: a_set()).
specification(Fun, S) when ?IS_SET(S) ->
Type = ?TYPE(S),
R = case external_fun(Fun) of
@@ -311,36 +403,62 @@ specification(Fun, S) when ?IS_SET(S) ->
erlang:error(Bad, [Fun, S])
end.
+-spec(union(Set1, Set2) -> Set3 when
+ Set1 :: a_set(),
+ Set2 :: a_set(),
+ Set3 :: a_set()).
union(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) ->
case unify_types(?TYPE(S1), ?TYPE(S2)) of
[] -> erlang:error(type_mismatch, [S1, S2]);
Type -> ?SET(umerge(?LIST(S1), ?LIST(S2)), Type)
end.
+-spec(intersection(Set1, Set2) -> Set3 when
+ Set1 :: a_set(),
+ Set2 :: a_set(),
+ Set3 :: a_set()).
intersection(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) ->
case unify_types(?TYPE(S1), ?TYPE(S2)) of
[] -> erlang:error(type_mismatch, [S1, S2]);
Type -> ?SET(intersection(?LIST(S1), ?LIST(S2), []), Type)
end.
+-spec(difference(Set1, Set2) -> Set3 when
+ Set1 :: a_set(),
+ Set2 :: a_set(),
+ Set3 :: a_set()).
difference(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) ->
case unify_types(?TYPE(S1), ?TYPE(S2)) of
[] -> erlang:error(type_mismatch, [S1, S2]);
Type -> ?SET(difference(?LIST(S1), ?LIST(S2), []), Type)
end.
+-spec(symdiff(Set1, Set2) -> Set3 when
+ Set1 :: a_set(),
+ Set2 :: a_set(),
+ Set3 :: a_set()).
symdiff(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) ->
case unify_types(?TYPE(S1), ?TYPE(S2)) of
[] -> erlang:error(type_mismatch, [S1, S2]);
Type -> ?SET(symdiff(?LIST(S1), ?LIST(S2), []), Type)
end.
+-spec(symmetric_partition(Set1, Set2) -> {Set3, Set4, Set5} when
+ Set1 :: a_set(),
+ Set2 :: a_set(),
+ Set3 :: a_set(),
+ Set4 :: a_set(),
+ Set5 :: a_set()).
symmetric_partition(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) ->
case unify_types(?TYPE(S1), ?TYPE(S2)) of
[] -> erlang:error(type_mismatch, [S1, S2]);
Type -> sympart(?LIST(S1), ?LIST(S2), [], [], [], Type)
end.
+-spec(product(Set1, Set2) -> BinRel when
+ BinRel :: binary_relation(),
+ Set1 :: a_set(),
+ Set2 :: a_set()).
product(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) ->
if
?TYPE(S1) =:= ?ANYTYPE -> S1;
@@ -351,6 +469,9 @@ product(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) ->
?SET(relprod(map(F, ?LIST(S1)), map(F, ?LIST(S2))), T)
end.
+-spec(product(TupleOfSets) -> Relation when
+ Relation :: relation(),
+ TupleOfSets :: tuple_of(a_set())).
product({S1, S2}) ->
product(S1, S2);
product(T) when is_tuple(T) ->
@@ -365,11 +486,15 @@ product(T) when is_tuple(T) ->
case member([], L) of
true ->
empty_set();
- false ->
+ false ->
?SET(reverse(prod(L, [], [])), Type)
end
end.
+-spec(constant_function(Set, AnySet) -> Function when
+ AnySet :: anyset(),
+ Function :: a_function(),
+ Set :: a_set()).
constant_function(S, E) when ?IS_SET(S) ->
case {?TYPE(S), is_sofs_set(E)} of
{?ANYTYPE, true} -> S;
@@ -381,6 +506,10 @@ constant_function(S, E) when ?IS_SET(S) ->
constant_function(S, E) when ?IS_ORDSET(S) ->
erlang:error(badarg, [S, E]).
+-spec(is_equal(AnySet1, AnySet2) -> Bool when
+ AnySet1 :: anyset(),
+ AnySet2 :: anyset(),
+ Bool :: boolean()).
is_equal(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) ->
case match_types(?TYPE(S1), ?TYPE(S2)) of
true -> ?LIST(S1) == ?LIST(S2);
@@ -396,12 +525,19 @@ is_equal(S1, S2) when ?IS_SET(S1), ?IS_ORDSET(S2) ->
is_equal(S1, S2) when ?IS_ORDSET(S1), ?IS_SET(S2) ->
erlang:error(type_mismatch, [S1, S2]).
+-spec(is_subset(Set1, Set2) -> Bool when
+ Bool :: boolean(),
+ Set1 :: a_set(),
+ Set2 :: a_set()).
is_subset(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) ->
case match_types(?TYPE(S1), ?TYPE(S2)) of
true -> subset(?LIST(S1), ?LIST(S2));
false -> erlang:error(type_mismatch, [S1, S2])
end.
+-spec(is_sofs_set(Term) -> Bool when
+ Bool :: boolean(),
+ Term :: term()).
is_sofs_set(S) when ?IS_SET(S) ->
true;
is_sofs_set(S) when ?IS_ORDSET(S) ->
@@ -409,16 +545,26 @@ is_sofs_set(S) when ?IS_ORDSET(S) ->
is_sofs_set(_S) ->
false.
+-spec(is_set(AnySet) -> Bool when
+ AnySet :: anyset(),
+ Bool :: boolean()).
is_set(S) when ?IS_SET(S) ->
true;
is_set(S) when ?IS_ORDSET(S) ->
false.
-is_empty_set(S) when ?IS_SET(S) ->
+-spec(is_empty_set(AnySet) -> Bool when
+ AnySet :: anyset(),
+ Bool :: boolean()).
+is_empty_set(S) when ?IS_SET(S) ->
?LIST(S) =:= [];
is_empty_set(S) when ?IS_ORDSET(S) ->
false.
+-spec(is_disjoint(Set1, Set2) -> Bool when
+ Bool :: boolean(),
+ Set1 :: a_set(),
+ Set2 :: a_set()).
is_disjoint(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) ->
case match_types(?TYPE(S1), ?TYPE(S2)) of
true ->
@@ -433,6 +579,9 @@ is_disjoint(S1, S2) when ?IS_SET(S1), ?IS_SET(S2) ->
%%% Functions on set-of-sets.
%%%
+-spec(union(SetOfSets) -> Set when
+ Set :: a_set(),
+ SetOfSets :: set_of_sets()).
union(Sets) when ?IS_SET(Sets) ->
case ?TYPE(Sets) of
?SET_OF(Type) -> ?SET(lunion(?LIST(Sets)), Type);
@@ -440,6 +589,9 @@ union(Sets) when ?IS_SET(Sets) ->
_ -> erlang:error(badarg, [Sets])
end.
+-spec(intersection(SetOfSets) -> Set when
+ Set :: a_set(),
+ SetOfSets :: set_of_sets()).
intersection(Sets) when ?IS_SET(Sets) ->
case ?LIST(Sets) of
[] -> erlang:error(badarg, [Sets]);
@@ -451,32 +603,41 @@ intersection(Sets) when ?IS_SET(Sets) ->
end
end.
+-spec(canonical_relation(SetOfSets) -> BinRel when
+ BinRel :: binary_relation(),
+ SetOfSets :: set_of_sets()).
canonical_relation(Sets) when ?IS_SET(Sets) ->
ST = ?TYPE(Sets),
case ST of
?SET_OF(?ANYTYPE) -> empty_set();
- ?SET_OF(Type) ->
+ ?SET_OF(Type) ->
?SET(can_rel(?LIST(Sets), []), ?BINREL(Type, ST));
?ANYTYPE -> Sets;
_ -> erlang:error(badarg, [Sets])
end.
-%%%
+%%%
%%% Functions on binary relations only.
-%%%
+%%%
rel2fam(R) ->
relation_to_family(R).
+-spec(relation_to_family(BinRel) -> Family when
+ Family :: family(),
+ BinRel :: binary_relation()).
%% Inlined.
relation_to_family(R) when ?IS_SET(R) ->
case ?TYPE(R) of
- ?BINREL(DT, RT) ->
+ ?BINREL(DT, RT) ->
?SET(rel2family(?LIST(R)), ?FAMILY(DT, RT));
?ANYTYPE -> R;
_Else -> erlang:error(badarg, [R])
end.
+-spec(domain(BinRel) -> Set when
+ BinRel :: binary_relation(),
+ Set :: a_set()).
domain(R) when ?IS_SET(R) ->
case ?TYPE(R) of
?BINREL(DT, _) -> ?SET(dom(?LIST(R)), DT);
@@ -484,6 +645,9 @@ domain(R) when ?IS_SET(R) ->
_Else -> erlang:error(badarg, [R])
end.
+-spec(range(BinRel) -> Set when
+ BinRel :: binary_relation(),
+ Set :: a_set()).
range(R) when ?IS_SET(R) ->
case ?TYPE(R) of
?BINREL(_, RT) -> ?SET(ran(?LIST(R), []), RT);
@@ -491,35 +655,63 @@ range(R) when ?IS_SET(R) ->
_ -> erlang:error(badarg, [R])
end.
+-spec(field(BinRel) -> Set when
+ BinRel :: binary_relation(),
+ Set :: a_set()).
%% In "Introduction to LOGIC", Suppes defines the field of a binary
%% relation to be the union of the domain and the range (or
%% counterdomain).
field(R) ->
union(domain(R), range(R)).
+-spec(relative_product(ListOfBinRels) -> BinRel2 when
+ ListOfBinRels :: [BinRel, ...],
+ BinRel :: binary_relation(),
+ BinRel2 :: binary_relation()).
+%% The following clause is kept for backward compatibility.
+%% The list is due to Dialyzer's specs.
relative_product(RT) when is_tuple(RT) ->
- case relprod_n(RT, foo, false, false) of
- {error, Reason} ->
- erlang:error(Reason, [RT]);
+ relative_product(tuple_to_list(RT));
+relative_product(RL) when is_list(RL) ->
+ case relprod_n(RL, foo, false, false) of
+ {error, Reason} ->
+ erlang:error(Reason, [RL]);
Reply ->
Reply
end.
+-spec(relative_product(ListOfBinRels, BinRel1) -> BinRel2 when
+ ListOfBinRels :: [BinRel, ...],
+ BinRel :: binary_relation(),
+ BinRel1 :: binary_relation(),
+ BinRel2 :: binary_relation();
+ (BinRel1, BinRel2) -> BinRel3 when
+ BinRel1 :: binary_relation(),
+ BinRel2 :: binary_relation(),
+ BinRel3 :: binary_relation()).
relative_product(R1, R2) when ?IS_SET(R1), ?IS_SET(R2) ->
relative_product1(converse(R1), R2);
+%% The following clause is kept for backward compatibility.
+%% The list is due to Dialyzer's specs.
relative_product(RT, R) when is_tuple(RT), ?IS_SET(R) ->
+ relative_product(tuple_to_list(RT), R);
+relative_product(RL, R) when is_list(RL), ?IS_SET(R) ->
EmptyR = case ?TYPE(R) of
?BINREL(_, _) -> ?LIST(R) =:= [];
?ANYTYPE -> true;
- _ -> erlang:error(badarg, [RT, R])
+ _ -> erlang:error(badarg, [RL, R])
end,
- case relprod_n(RT, R, EmptyR, true) of
- {error, Reason} ->
- erlang:error(Reason, [RT, R]);
+ case relprod_n(RL, R, EmptyR, true) of
+ {error, Reason} ->
+ erlang:error(Reason, [RL, R]);
Reply ->
Reply
end.
+-spec(relative_product1(BinRel1, BinRel2) -> BinRel3 when
+ BinRel1 :: binary_relation(),
+ BinRel2 :: binary_relation(),
+ BinRel3 :: binary_relation()).
relative_product1(R1, R2) when ?IS_SET(R1), ?IS_SET(R2) ->
{DTR1, RTR1} = case ?TYPE(R1) of
?BINREL(_, _) = R1T -> R1T;
@@ -538,16 +730,23 @@ relative_product1(R1, R2) when ?IS_SET(R1), ?IS_SET(R2) ->
false -> erlang:error(type_mismatch, [R1, R2])
end.
+-spec(converse(BinRel1) -> BinRel2 when
+ BinRel1 :: binary_relation(),
+ BinRel2 :: binary_relation()).
converse(R) when ?IS_SET(R) ->
case ?TYPE(R) of
?BINREL(DT, RT) -> ?SET(converse(?LIST(R), []), ?BINREL(RT, DT));
?ANYTYPE -> R;
_ -> erlang:error(badarg, [R])
end.
-
+
+-spec(image(BinRel, Set1) -> Set2 when
+ BinRel :: binary_relation(),
+ Set1 :: a_set(),
+ Set2 :: a_set()).
image(R, S) when ?IS_SET(R), ?IS_SET(S) ->
case ?TYPE(R) of
- ?BINREL(DT, RT) ->
+ ?BINREL(DT, RT) ->
case match_types(DT, ?TYPE(S)) of
true ->
?SET(usort(restrict(?LIST(S), ?LIST(R))), RT);
@@ -558,9 +757,13 @@ image(R, S) when ?IS_SET(R), ?IS_SET(S) ->
_ -> erlang:error(badarg, [R, S])
end.
+-spec(inverse_image(BinRel, Set1) -> Set2 when
+ BinRel :: binary_relation(),
+ Set1 :: a_set(),
+ Set2 :: a_set()).
inverse_image(R, S) when ?IS_SET(R), ?IS_SET(S) ->
case ?TYPE(R) of
- ?BINREL(DT, RT) ->
+ ?BINREL(DT, RT) ->
case match_types(RT, ?TYPE(S)) of
true ->
NL = restrict(?LIST(S), converse(?LIST(R), [])),
@@ -572,17 +775,23 @@ inverse_image(R, S) when ?IS_SET(R), ?IS_SET(S) ->
_ -> erlang:error(badarg, [R, S])
end.
+-spec(strict_relation(BinRel1) -> BinRel2 when
+ BinRel1 :: binary_relation(),
+ BinRel2 :: binary_relation()).
strict_relation(R) when ?IS_SET(R) ->
case ?TYPE(R) of
- Type = ?BINREL(_, _) ->
+ Type = ?BINREL(_, _) ->
?SET(strict(?LIST(R), []), Type);
?ANYTYPE -> R;
_ -> erlang:error(badarg, [R])
end.
-
+
+-spec(weak_relation(BinRel1) -> BinRel2 when
+ BinRel1 :: binary_relation(),
+ BinRel2 :: binary_relation()).
weak_relation(R) when ?IS_SET(R) ->
case ?TYPE(R) of
- ?BINREL(DT, RT) ->
+ ?BINREL(DT, RT) ->
case unify_types(DT, RT) of
[] ->
erlang:error(badarg, [R]);
@@ -592,7 +801,12 @@ weak_relation(R) when ?IS_SET(R) ->
?ANYTYPE -> R;
_ -> erlang:error(badarg, [R])
end.
-
+
+-spec(extension(BinRel1, Set, AnySet) -> BinRel2 when
+ AnySet :: anyset(),
+ BinRel1 :: binary_relation(),
+ BinRel2 :: binary_relation(),
+ Set :: a_set()).
extension(R, S, E) when ?IS_SET(R), ?IS_SET(S) ->
case {?TYPE(R), ?TYPE(S), is_sofs_set(E)} of
{T=?BINREL(DT, RT), ST, true} ->
@@ -621,9 +835,12 @@ extension(R, S, E) when ?IS_SET(R), ?IS_SET(S) ->
erlang:error(badarg, [R, S, E])
end.
+-spec(is_a_function(BinRel) -> Bool when
+ Bool :: boolean(),
+ BinRel :: binary_relation()).
is_a_function(R) when ?IS_SET(R) ->
case ?TYPE(R) of
- ?BINREL(_, _) ->
+ ?BINREL(_, _) ->
case ?LIST(R) of
[] -> true;
[{V,_} | Es] -> is_a_func(Es, V)
@@ -632,16 +849,28 @@ is_a_function(R) when ?IS_SET(R) ->
_ -> erlang:error(badarg, [R])
end.
+-spec(restriction(BinRel1, Set) -> BinRel2 when
+ BinRel1 :: binary_relation(),
+ BinRel2 :: binary_relation(),
+ Set :: a_set()).
restriction(Relation, Set) ->
restriction(1, Relation, Set).
+-spec(drestriction(BinRel1, Set) -> BinRel2 when
+ BinRel1 :: binary_relation(),
+ BinRel2 :: binary_relation(),
+ Set :: a_set()).
drestriction(Relation, Set) ->
drestriction(1, Relation, Set).
-%%%
+%%%
%%% Functions on functions only.
-%%%
+%%%
+-spec(composite(Function1, Function2) -> Function3 when
+ Function1 :: a_function(),
+ Function2 :: a_function(),
+ Function3 :: a_function()).
composite(Fn1, Fn2) when ?IS_SET(Fn1), ?IS_SET(Fn2) ->
?BINREL(DTF1, RTF1) = case ?TYPE(Fn1)of
?BINREL(_, _) = F1T -> F1T;
@@ -656,7 +885,7 @@ composite(Fn1, Fn2) when ?IS_SET(Fn1), ?IS_SET(Fn2) ->
case match_types(RTF1, DTF2) of
true when DTF1 =:= ?ANYTYPE -> Fn1;
true when DTF2 =:= ?ANYTYPE -> Fn2;
- true ->
+ true ->
case comp(?LIST(Fn1), ?LIST(Fn2)) of
SL when is_list(SL) ->
?SET(sort(SL), ?BINREL(DTF1, RTF2));
@@ -666,9 +895,12 @@ composite(Fn1, Fn2) when ?IS_SET(Fn1), ?IS_SET(Fn2) ->
false -> erlang:error(type_mismatch, [Fn1, Fn2])
end.
+-spec(inverse(Function1) -> Function2 when
+ Function1 :: a_function(),
+ Function2 :: a_function()).
inverse(Fn) when ?IS_SET(Fn) ->
case ?TYPE(Fn) of
- ?BINREL(DT, RT) ->
+ ?BINREL(DT, RT) ->
case inverse1(?LIST(Fn)) of
SL when is_list(SL) ->
?SET(SL, ?BINREL(RT, DT));
@@ -678,11 +910,16 @@ inverse(Fn) when ?IS_SET(Fn) ->
?ANYTYPE -> Fn;
_ -> erlang:error(badarg, [Fn])
end.
-
-%%%
+
+%%%
%%% Functions on relations (binary or other).
-%%%
+%%%
+-spec(restriction(SetFun, Set1, Set2) -> Set3 when
+ SetFun :: set_fun(),
+ Set1 :: a_set(),
+ Set2 :: a_set(),
+ Set3 :: a_set()).
%% Equivalent to range(restriction(inverse(substitution(Fun, S1)), S2)).
restriction(I, R, S) when is_integer(I), ?IS_SET(R), ?IS_SET(S) ->
RT = ?TYPE(R),
@@ -747,6 +984,11 @@ restriction(SetFun, S1, S2) when ?IS_SET(S1), ?IS_SET(S2) ->
end
end.
+-spec(drestriction(SetFun, Set1, Set2) -> Set3 when
+ SetFun :: set_fun(),
+ Set1 :: a_set(),
+ Set2 :: a_set(),
+ Set3 :: a_set()).
drestriction(I, R, S) when is_integer(I), ?IS_SET(R), ?IS_SET(S) ->
RT = ?TYPE(R),
ST = ?TYPE(S),
@@ -812,6 +1054,10 @@ drestriction(SetFun, S1, S2) when ?IS_SET(S1), ?IS_SET(S2) ->
end
end.
+-spec(projection(SetFun, Set1) -> Set2 when
+ SetFun :: set_fun(),
+ Set1 :: a_set(),
+ Set2 :: a_set()).
projection(I, Set) when is_integer(I), ?IS_SET(Set) ->
Type = ?TYPE(Set),
case check_for_sort(Type, I) of
@@ -827,6 +1073,10 @@ projection(I, Set) when is_integer(I), ?IS_SET(Set) ->
projection(Fun, Set) ->
range(substitution(Fun, Set)).
+-spec(substitution(SetFun, Set1) -> Set2 when
+ SetFun :: set_fun(),
+ Set1 :: a_set(),
+ Set2 :: a_set()).
substitution(I, Set) when is_integer(I), ?IS_SET(Set) ->
Type = ?TYPE(Set),
case check_for_sort(Type, I) of
@@ -867,11 +1117,18 @@ substitution(SetFun, Set) when ?IS_SET(Set) ->
end
end.
+-spec(partition(SetOfSets) -> Partition when
+ SetOfSets :: set_of_sets(),
+ Partition :: a_set()).
partition(Sets) ->
F1 = relation_to_family(canonical_relation(Sets)),
F2 = relation_to_family(converse(F1)),
range(F2).
+-spec(partition(SetFun, Set) -> Partition when
+ SetFun :: set_fun(),
+ Partition :: a_set(),
+ Set :: a_set()).
partition(I, Set) when is_integer(I), ?IS_SET(Set) ->
Type = ?TYPE(Set),
case check_for_sort(Type, I) of
@@ -887,6 +1144,12 @@ partition(I, Set) when is_integer(I), ?IS_SET(Set) ->
partition(Fun, Set) ->
range(partition_family(Fun, Set)).
+-spec(partition(SetFun, Set1, Set2) -> {Set3, Set4} when
+ SetFun :: set_fun(),
+ Set1 :: a_set(),
+ Set2 :: a_set(),
+ Set3 :: a_set(),
+ Set4 :: a_set()).
partition(I, R, S) when is_integer(I), ?IS_SET(R), ?IS_SET(S) ->
RT = ?TYPE(R),
ST = ?TYPE(S),
@@ -954,21 +1217,32 @@ partition(SetFun, S1, S2) when ?IS_SET(S1), ?IS_SET(S2) ->
end
end.
+-spec(multiple_relative_product(TupleOfBinRels, BinRel1) -> BinRel2 when
+ TupleOfBinRels :: tuple_of(BinRel),
+ BinRel :: binary_relation(),
+ BinRel1 :: binary_relation(),
+ BinRel2 :: binary_relation()).
multiple_relative_product(T, R) when is_tuple(T), ?IS_SET(R) ->
case test_rel(R, tuple_size(T), eq) of
true when ?TYPE(R) =:= ?ANYTYPE ->
empty_set();
- true ->
+ true ->
MProd = mul_relprod(tuple_to_list(T), 1, R),
- relative_product(list_to_tuple(MProd));
- false ->
+ relative_product(MProd);
+ false ->
erlang:error(badarg, [T, R])
end.
-join(R1, I1, R2, I2)
+-spec(join(Relation1, I, Relation2, J) -> Relation3 when
+ Relation1 :: relation(),
+ Relation2 :: relation(),
+ Relation3 :: relation(),
+ I :: pos_integer(),
+ J :: pos_integer()).
+join(R1, I1, R2, I2)
when ?IS_SET(R1), ?IS_SET(R2), is_integer(I1), is_integer(I2) ->
case test_rel(R1, I1, lte) and test_rel(R2, I2, lte) of
- false ->
+ false ->
erlang:error(badarg, [R1, I1, R2, I2]);
true when ?TYPE(R1) =:= ?ANYTYPE -> R1;
true when ?TYPE(R2) =:= ?ANYTYPE -> R2;
@@ -980,8 +1254,8 @@ join(R1, I1, R2, I2)
true ->
fun({X,Y}) -> join_element(X, Y) end;
false ->
- fun({X,Y}) ->
- list_to_tuple(join_element(X, Y, I2))
+ fun({X,Y}) ->
+ list_to_tuple(join_element(X, Y, I2))
end
end,
?SET(replace(T, F, []), F({?TYPE(R1), ?TYPE(R2)}))
@@ -1001,9 +1275,15 @@ test_rel(R, I, C) ->
%%% Family functions
%%%
+-spec(fam2rel(Family) -> BinRel when
+ Family :: family(),
+ BinRel :: binary_relation()).
fam2rel(F) ->
family_to_relation(F).
+-spec(family_to_relation(Family) -> BinRel when
+ Family :: family(),
+ BinRel :: binary_relation()).
%% Inlined.
family_to_relation(F) when ?IS_SET(F) ->
case ?TYPE(F) of
@@ -1013,6 +1293,10 @@ family_to_relation(F) when ?IS_SET(F) ->
_ -> erlang:error(badarg, [F])
end.
+-spec(family_specification(Fun, Family1) -> Family2 when
+ Fun :: spec_fun(),
+ Family1 :: family(),
+ Family2 :: family()).
family_specification(Fun, F) when ?IS_SET(F) ->
case ?TYPE(F) of
?FAMILY(_DT, Type) = FType ->
@@ -1032,6 +1316,9 @@ family_specification(Fun, F) when ?IS_SET(F) ->
_ -> erlang:error(badarg, [Fun, F])
end.
+-spec(union_of_family(Family) -> Set when
+ Family :: family(),
+ Set :: a_set()).
union_of_family(F) when ?IS_SET(F) ->
case ?TYPE(F) of
?FAMILY(_DT, Type) ->
@@ -1040,6 +1327,9 @@ union_of_family(F) when ?IS_SET(F) ->
_ -> erlang:error(badarg, [F])
end.
+-spec(intersection_of_family(Family) -> Set when
+ Family :: family(),
+ Set :: a_set()).
intersection_of_family(F) when ?IS_SET(F) ->
case ?TYPE(F) of
?FAMILY(_DT, Type) ->
@@ -1052,6 +1342,9 @@ intersection_of_family(F) when ?IS_SET(F) ->
_ -> erlang:error(badarg, [F])
end.
+-spec(family_union(Family1) -> Family2 when
+ Family1 :: family(),
+ Family2 :: family()).
family_union(F) when ?IS_SET(F) ->
case ?TYPE(F) of
?FAMILY(DT, ?SET_OF(Type)) ->
@@ -1060,6 +1353,9 @@ family_union(F) when ?IS_SET(F) ->
_ -> erlang:error(badarg, [F])
end.
+-spec(family_intersection(Family1) -> Family2 when
+ Family1 :: family(),
+ Family2 :: family()).
family_intersection(F) when ?IS_SET(F) ->
case ?TYPE(F) of
?FAMILY(DT, ?SET_OF(Type)) ->
@@ -1073,6 +1369,9 @@ family_intersection(F) when ?IS_SET(F) ->
_ -> erlang:error(badarg, [F])
end.
+-spec(family_domain(Family1) -> Family2 when
+ Family1 :: family(),
+ Family2 :: family()).
family_domain(F) when ?IS_SET(F) ->
case ?TYPE(F) of
?FAMILY(FDT, ?BINREL(DT, _)) ->
@@ -1082,6 +1381,9 @@ family_domain(F) when ?IS_SET(F) ->
_ -> erlang:error(badarg, [F])
end.
+-spec(family_range(Family1) -> Family2 when
+ Family1 :: family(),
+ Family2 :: family()).
family_range(F) when ?IS_SET(F) ->
case ?TYPE(F) of
?FAMILY(DT, ?BINREL(_, RT)) ->
@@ -1091,15 +1393,30 @@ family_range(F) when ?IS_SET(F) ->
_ -> erlang:error(badarg, [F])
end.
+-spec(family_field(Family1) -> Family2 when
+ Family1 :: family(),
+ Family2 :: family()).
family_field(F) ->
family_union(family_domain(F), family_range(F)).
+-spec(family_union(Family1, Family2) -> Family3 when
+ Family1 :: family(),
+ Family2 :: family(),
+ Family3 :: family()).
family_union(F1, F2) ->
fam_binop(F1, F2, fun fam_union/3).
+-spec(family_intersection(Family1, Family2) -> Family3 when
+ Family1 :: family(),
+ Family2 :: family(),
+ Family3 :: family()).
family_intersection(F1, F2) ->
fam_binop(F1, F2, fun fam_intersect/3).
+-spec(family_difference(Family1, Family2) -> Family3 when
+ Family1 :: family(),
+ Family2 :: family(),
+ Family3 :: family()).
family_difference(F1, F2) ->
fam_binop(F1, F2, fun fam_difference/3).
@@ -1108,13 +1425,17 @@ fam_binop(F1, F2, FF) when ?IS_SET(F1), ?IS_SET(F2) ->
case unify_types(?TYPE(F1), ?TYPE(F2)) of
[] ->
erlang:error(type_mismatch, [F1, F2]);
- ?ANYTYPE ->
+ ?ANYTYPE ->
F1;
- Type = ?FAMILY(_, _) ->
+ Type = ?FAMILY(_, _) ->
?SET(FF(?LIST(F1), ?LIST(F2), []), Type);
_ -> erlang:error(badarg, [F1, F2])
end.
+-spec(partition_family(SetFun, Set) -> Family when
+ Family :: family(),
+ SetFun :: set_fun(),
+ Set :: a_set()).
partition_family(I, Set) when is_integer(I), ?IS_SET(Set) ->
Type = ?TYPE(Set),
case check_for_sort(Type, I) of
@@ -1159,8 +1480,12 @@ partition_family(SetFun, Set) when ?IS_SET(Set) ->
end
end.
+-spec(family_projection(SetFun, Family1) -> Family2 when
+ SetFun :: set_fun(),
+ Family1 :: family(),
+ Family2 :: family()).
family_projection(SetFun, F) when ?IS_SET(F) ->
- case ?TYPE(F) of
+ case ?TYPE(F) of
?FAMILY(_, _) when [] =:= ?LIST(F) ->
empty_set();
?FAMILY(DT, Type) ->
@@ -1172,7 +1497,7 @@ family_projection(SetFun, F) when ?IS_SET(F) ->
Bad ->
erlang:error(Bad, [SetFun, F])
end;
- _ ->
+ _ ->
erlang:error(badarg, [SetFun, F])
end;
?ANYTYPE -> F;
@@ -1183,6 +1508,9 @@ family_projection(SetFun, F) when ?IS_SET(F) ->
%%% Digraph functions
%%%
+-spec(family_to_digraph(Family) -> Graph when
+ Graph :: digraph(),
+ Family :: family()).
family_to_digraph(F) when ?IS_SET(F) ->
case ?TYPE(F) of
?FAMILY(_, _) -> fam2digraph(F, digraph:new());
@@ -1190,6 +1518,10 @@ family_to_digraph(F) when ?IS_SET(F) ->
_Else -> erlang:error(badarg, [F])
end.
+-spec(family_to_digraph(Family, GraphType) -> Graph when
+ Graph :: digraph(),
+ Family :: family(),
+ GraphType :: [digraph:d_type()]).
family_to_digraph(F, Type) when ?IS_SET(F) ->
case ?TYPE(F) of
?FAMILY(_, _) -> ok;
@@ -1208,12 +1540,19 @@ family_to_digraph(F, Type) when ?IS_SET(F) ->
error:badarg -> erlang:error(badarg, [F, Type])
end.
+-spec(digraph_to_family(Graph) -> Family when
+ Graph :: digraph(),
+ Family :: family()).
digraph_to_family(G) ->
case catch digraph_family(G) of
{'EXIT', _} -> erlang:error(badarg, [G]);
L -> ?SET(L, ?FAMILY(?ATOM_TYPE, ?ATOM_TYPE))
end.
+-spec(digraph_to_family(Graph, Type) -> Family when
+ Graph :: digraph(),
+ Family :: family(),
+ Type :: type()).
digraph_to_family(G, T) ->
case {is_type(T), T} of
{true, ?SET_OF(?FAMILY(_,_) = Type)} ->
@@ -1284,7 +1623,7 @@ rel(Ts, [Type]) ->
end;
rel(Ts, Sz) ->
rel(Ts, Sz, erlang:make_tuple(Sz, ?ATOM_TYPE)).
-
+
atoms_only(Type, I) when ?IS_ATOM_TYPE(?REL_TYPE(I, Type)) ->
atoms_only(Type, I+1);
atoms_only(Type, I) when I > tuple_size(Type), ?IS_RELATION(Type) ->
@@ -1312,7 +1651,7 @@ rel_type([], SL, Type) when ?IS_RELATION(Type) ->
%% Inlined.
a_func(Ts, T) ->
case {T, is_type(T)} of
- {[?BINREL(DT, RT) = Type], true} when ?IS_ATOM_TYPE(DT),
+ {[?BINREL(DT, RT) = Type], true} when ?IS_ATOM_TYPE(DT),
?IS_ATOM_TYPE(RT) ->
func(Ts, Type);
{[Type], true} ->
@@ -1333,16 +1672,16 @@ func([], _X0, L, Type) ->
%% Inlined.
fam(Ts, T) ->
case {T, is_type(T)} of
- {[?FAMILY(DT, RT) = Type], true} when ?IS_ATOM_TYPE(DT),
+ {[?FAMILY(DT, RT) = Type], true} when ?IS_ATOM_TYPE(DT),
?IS_ATOM_TYPE(RT) ->
fam2(Ts, Type);
{[Type], true} ->
func_type(Ts, [], Type, fun(?FAMILY(_,_)) -> true end)
end.
-fam2([], Type) ->
+fam2([], Type) ->
?SET([], Type);
-fam2(Ts, Type) ->
+fam2(Ts, Type) ->
fam2(sort(Ts), Ts, [], Type).
fam2([{I,L} | T], I0, SL, Type) when I /= I0 ->
@@ -1383,7 +1722,7 @@ setify(E, Type0) ->
{Type, OrdSet} = make_element(E, Type0, Type0),
?ORDSET(OrdSet, Type).
-is_no_lists(T) when is_tuple(T) ->
+is_no_lists(T) when is_tuple(T) ->
Sz = tuple_size(T),
is_no_lists(T, Sz, Sz, []).
@@ -1404,7 +1743,7 @@ create([], T, _T0, L) ->
make_element(C, ?ANYTYPE, _T0) ->
make_element(C);
-make_element(C, Atom, ?ANYTYPE) when ?IS_ATOM_TYPE(Atom),
+make_element(C, Atom, ?ANYTYPE) when ?IS_ATOM_TYPE(Atom),
not is_list(C), not is_tuple(C) ->
{Atom, C};
make_element(C, Atom, Atom) when ?IS_ATOM_TYPE(Atom) ->
@@ -1585,12 +1924,12 @@ sympart([H1 | T1], [H2 | T2], L1, L12, L2, T) when H1 == H2 ->
sympart([H1 | T1], [H2 | T2], L1, L12, L2, T) ->
sympart2(T1, T2, L1, L12, [H2 | L2], T, H1);
sympart(S1, [], L1, L12, L2, T) ->
- {?SET(reverse(L1, S1), T),
- ?SET(reverse(L12), T),
+ {?SET(reverse(L1, S1), T),
+ ?SET(reverse(L12), T),
?SET(reverse(L2), T)};
sympart(_, S2, L1, L12, L2, T) ->
- {?SET(reverse(L1), T),
- ?SET(reverse(L12), T),
+ {?SET(reverse(L1), T),
+ ?SET(reverse(L12), T),
?SET(reverse(L2, S2), T)}.
sympart1([H1 | T1], T2, L1, L12, L2, T, H2) when H1 < H2 ->
@@ -1600,8 +1939,8 @@ sympart1([H1 | T1], T2, L1, L12, L2, T, H2) when H1 == H2 ->
sympart1([H1 | T1], T2, L1, L12, L2, T, H2) ->
sympart2(T1, T2, L1, L12, [H2 | L2], T, H1);
sympart1(_, T2, L1, L12, L2, T, H2) ->
- {?SET(reverse(L1), T),
- ?SET(reverse(L12), T),
+ {?SET(reverse(L1), T),
+ ?SET(reverse(L12), T),
?SET(reverse(L2, [H2 | T2]), T)}.
sympart2(T1, [H2 | T2], L1, L12, L2, T, H1) when H1 > H2 ->
@@ -1611,8 +1950,8 @@ sympart2(T1, [H2 | T2], L1, L12, L2, T, H1) when H1 == H2 ->
sympart2(T1, [H2 | T2], L1, L12, L2, T, H1) ->
sympart1(T1, T2, [H1 | L1], L12, L2, T, H2);
sympart2(T1, _, L1, L12, L2, T, H1) ->
- {?SET(reverse(L1, [H1 | T1]), T),
- ?SET(reverse(L12), T),
+ {?SET(reverse(L1, [H1 | T1]), T),
+ ?SET(reverse(L12), T),
?SET(reverse(L2), T)}.
prod([[E | Es] | Xs], T, L) ->
@@ -1660,7 +1999,7 @@ lunion([[] | Ls]) ->
lunion(Ls);
lunion([S | Ss]) ->
umerge(lunion(Ss, last(S), [S], []));
-lunion([]) ->
+lunion([]) ->
[].
lunion([[E] = S | Ss], Last, SL, Ls) when E > Last -> % optimization
@@ -1669,7 +2008,7 @@ lunion([S | Ss], Last, SL, Ls) when hd(S) > Last ->
lunion(Ss, last(S), [S | SL], Ls);
lunion([S | Ss], _Last, SL, Ls) ->
lunion(Ss, last(S), [S], [append(reverse(SL)) | Ls]);
-lunion([], _Last, SL, Ls) ->
+lunion([], _Last, SL, Ls) ->
[append(reverse(SL)) | Ls].
%% The empty list is always the first list, if present.
@@ -1752,18 +2091,17 @@ relprod(B0, Bx0, By0, A0, L, Ax, [{Bx,By} | B], Ay) when Ay == Bx ->
relprod(B0, Bx0, By0, A0, L, _Ax, _B, _Ay) ->
relprod2(B0, Bx0, By0, A0, L).
-relprod_n({}, _R, _EmptyG, _IsR) ->
+relprod_n([], _R, _EmptyG, _IsR) ->
{error, badarg};
-relprod_n(RT, R, EmptyR, IsR) ->
- RL = tuple_to_list(RT),
+relprod_n(RL, R, EmptyR, IsR) ->
case domain_type(RL, ?ANYTYPE) of
- Error = {error, _Reason} ->
+ Error = {error, _Reason} ->
Error;
DType ->
Empty = any(fun is_empty_set/1, RL) or EmptyR,
RType = range_type(RL, []),
Type = ?BINREL(DType, RType),
- Prod =
+ Prod =
case Empty of
true when DType =:= ?ANYTYPE; RType =:= ?ANYTYPE ->
empty_set();
@@ -1771,7 +2109,7 @@ relprod_n(RT, R, EmptyR, IsR) ->
?SET([], Type);
false ->
TL = ?LIST((relprod_n(RL))),
- Sz = tuple_size(RT),
+ Sz = length(RL),
Fun = fun({X,A}) -> {X, flat(Sz, A, [])} end,
?SET(map(Fun, TL), Type)
end,
@@ -1799,12 +2137,12 @@ flat(N, {T,A}, L) ->
domain_type([T | Ts], T0) when ?IS_SET(T) ->
case ?TYPE(T) of
- ?BINREL(DT, _RT) ->
+ ?BINREL(DT, _RT) ->
case unify_types(DT, T0) of
[] -> {error, type_mismatch};
T1 -> domain_type(Ts, T1)
end;
- ?ANYTYPE ->
+ ?ANYTYPE ->
domain_type(Ts, T0);
_ -> {error, badarg}
end;
@@ -1813,12 +2151,12 @@ domain_type([], T0) ->
range_type([T | Ts], L) ->
case ?TYPE(T) of
- ?BINREL(_DT, RT) ->
+ ?BINREL(_DT, RT) ->
range_type(Ts, [RT | L]);
- ?ANYTYPE ->
+ ?ANYTYPE ->
?ANYTYPE
end;
-range_type([], L) ->
+range_type([], L) ->
list_to_tuple(reverse(L)).
converse([{A,B} | X], L) ->
@@ -1861,7 +2199,7 @@ weak1([E={X,_Y} | Es], Ys, L, X0) when X == X0 -> % when X < Y
weak1(Es, Ys, L, X) ->
weak(Es, Ys, [{X,X} | L]).
-weak2([E={X,_Y} | Es], Ys, L, X0) when X == X0 -> % when X < _Y
+weak2([E={X,_Y} | Es], Ys, L, X0) when X == X0 -> % when X < _Y
weak2(Es, Ys, [E | L], X);
weak2(Es, Ys, L, _X) ->
weak(Es, Ys, L).
@@ -1910,7 +2248,7 @@ restrict_n(I, [T | Ts], Key, Keys, L) ->
end;
restrict_n(_I, _Ts, _Key, _Keys, L) ->
L.
-
+
restrict_n(I, K, Ts, [Key | Keys], L, E) when K > Key ->
restrict_n(I, K, Ts, Keys, L, E);
restrict_n(I, K, Ts, [Key | Keys], L, E) when K == Key ->
@@ -1933,7 +2271,7 @@ restrict([{K,E} | Ts], _Key, Keys, L) ->
restrict(Ts, K, Keys, L, E);
restrict(_Ts, _Key, _Keys, L) ->
L.
-
+
restrict(Ts, K, [Key | Keys], L, E) when K > Key ->
restrict(Ts, K, Keys, L, E);
restrict(Ts, K, [Key | Keys], L, E) when K == Key ->
@@ -1956,7 +2294,7 @@ diff_restrict_n(I, _Ts, _Key, _Keys, L) when I =:= 1 ->
reverse(L);
diff_restrict_n(_I, _Ts, _Key, _Keys, L) ->
sort(L).
-
+
diff_restrict_n(I, K, Ts, [Key | Keys], L, T) when K > Key ->
diff_restrict_n(I, K, Ts, Keys, L, T);
diff_restrict_n(I, K, Ts, [Key | Keys], L, _T) when K == Key ->
@@ -1981,7 +2319,7 @@ diff_restrict([{K,E} | Ts], _Key, Keys, L) ->
diff_restrict(Ts, K, Keys, L, E);
diff_restrict(_Ts, _Key, _Keys, L) ->
L.
-
+
diff_restrict(Ts, K, [Key | Keys], L, E) when K > Key ->
diff_restrict(Ts, K, Keys, L, E);
diff_restrict(Ts, K, [Key | Keys], L, _E) when K == Key ->
@@ -2041,7 +2379,7 @@ external_fun({external, Function}) when is_atom(Function) ->
false;
external_fun({external, Fun}) ->
Fun;
-external_fun(_) ->
+external_fun(_) ->
false.
%% Inlined.
@@ -2121,7 +2459,7 @@ partition3_n(I, _Ts, _Key, _Keys, L1, L2) when I =:= 1 ->
[reverse(L1) | reverse(L2)];
partition3_n(_I, _Ts, _Key, _Keys, L1, L2) ->
[sort(L1) | sort(L2)].
-
+
partition3_n(I, K, Ts, [Key | Keys], L1, L2, T) when K > Key ->
partition3_n(I, K, Ts, Keys, L1, L2, T);
partition3_n(I, K, Ts, [Key | Keys], L1, L2, T) when K == Key ->
@@ -2146,7 +2484,7 @@ partition3([{K,E} | Ts], _Key, Keys, L1, L2) ->
partition3(Ts, K, Keys, L1, L2, E);
partition3(_Ts, _Key, _Keys, L1, L2) ->
[L1 | L2].
-
+
partition3(Ts, K, [Key | Keys], L1, L2, E) when K > Key ->
partition3(Ts, K, Keys, L1, L2, E);
partition3(Ts, K, [Key | Keys], L1, L2, E) when K == Key ->
@@ -2192,7 +2530,7 @@ join_element(E1, E2, I2) ->
join_element2([B | Bs], C, I2) when C =/= I2 ->
[B | join_element2(Bs, C+1, I2)];
-join_element2([_ | Bs], _C, _I2) ->
+join_element2([_ | Bs], _C, _I2) ->
Bs.
family2rel([{X,S} | F], L) ->
@@ -2297,7 +2635,7 @@ check_function([{X,_} | XL], R) ->
check_function(X, XL, R);
check_function([], R) ->
R.
-
+
check_function(X0, [{X,_} | XL], R) when X0 /= X ->
check_function(X, XL, R);
check_function(X0, [{X,_} | _XL], _R) when X0 == X ->
@@ -2371,14 +2709,14 @@ term2set(T, Type) ->
?ORDSET(T, Type).
fam2digraph(F, G) ->
- Fun = fun({From, ToL}) ->
+ Fun = fun({From, ToL}) ->
digraph:add_vertex(G, From),
Fun2 = fun(To) ->
digraph:add_vertex(G, To),
case digraph:add_edge(G, From, To) of
- {error, {bad_edge, _}} ->
+ {error, {bad_edge, _}} ->
throw({error, cyclic});
- _ ->
+ _ ->
true
end
end,
@@ -2397,7 +2735,7 @@ digraph_fam([V | Vs], V0, G, L) when V /= V0 ->
digraph_fam([], _V0, _G, L) ->
reverse(L).
-%% -> bool()
+%% -> boolean()
check_fun(T, F, FunT) ->
true = is_type(FunT),
{NT, _MaxI} = number_tuples(T, 1),
@@ -2424,7 +2762,7 @@ check_for_sort(T, _I) when T =:= ?ANYTYPE ->
check_for_sort(T, I) when ?IS_RELATION(T), I =< ?REL_ARITY(T), I >= 1 ->
I > 1;
check_for_sort(_T, _I) ->
- error.
+ error.
inverse_substitution(L, Fun, Sort) ->
%% One easily sees that the inverse of the tuples created by
@@ -2477,11 +2815,11 @@ match_types(Type1, Type2) -> match_types1(Type1, Type2).
match_types1(Atom, Atom) when ?IS_ATOM_TYPE(Atom) ->
true;
-match_types1(?ANYTYPE, _) ->
+match_types1(?ANYTYPE, _) ->
true;
-match_types1(_, ?ANYTYPE) ->
+match_types1(_, ?ANYTYPE) ->
true;
-match_types1(?SET_OF(Type1), ?SET_OF(Type2)) ->
+match_types1(?SET_OF(Type1), ?SET_OF(Type2)) ->
match_types1(Type1, Type2);
match_types1(T1, T2) when tuple_size(T1) =:= tuple_size(T2) ->
match_typesl(tuple_size(T1), T1, T2);
diff --git a/lib/stdlib/src/string.erl b/lib/stdlib/src/string.erl
index 264348180f..30eac4f07d 100644
--- a/lib/stdlib/src/string.erl
+++ b/lib/stdlib/src/string.erl
@@ -29,23 +29,23 @@
%%---------------------------------------------------------------------------
--type direction() :: 'left' | 'right' | 'both'.
-
-%%---------------------------------------------------------------------------
-
%% Robert's bit
%% len(String)
%% Return the length of a string.
--spec len(string()) -> non_neg_integer().
+-spec len(String) -> Length when
+ String :: string(),
+ Length :: non_neg_integer().
len(S) -> length(S).
%% equal(String1, String2)
%% Test if 2 strings are equal.
--spec equal(string(), string()) -> boolean().
+-spec equal(String1, String2) -> boolean() when
+ String1 :: string(),
+ String2 :: string().
equal(S, S) -> true;
equal(_, _) -> false.
@@ -53,7 +53,10 @@ equal(_, _) -> false.
%% concat(String1, String2)
%% Concatenate 2 strings.
--spec concat(string(), string()) -> string().
+-spec concat(String1, String2) -> String3 when
+ String1 :: string(),
+ String2 :: string(),
+ String3 :: string().
concat(S1, S2) -> S1 ++ S2.
@@ -61,7 +64,10 @@ concat(S1, S2) -> S1 ++ S2.
%% rchr(String, Char)
%% Return the first/last index of the character in a string.
--spec chr(string(), char()) -> non_neg_integer().
+-spec chr(String, Character) -> Index when
+ String :: string(),
+ Character :: char(),
+ Index :: non_neg_integer().
chr(S, C) when is_integer(C) -> chr(S, C, 1).
@@ -69,7 +75,10 @@ chr([C|_Cs], C, I) -> I;
chr([_|Cs], C, I) -> chr(Cs, C, I+1);
chr([], _C, _I) -> 0.
--spec rchr(string(), char()) -> non_neg_integer().
+-spec rchr(String, Character) -> Index when
+ String :: string(),
+ Character :: char(),
+ Index :: non_neg_integer().
rchr(S, C) when is_integer(C) -> rchr(S, C, 1, 0).
@@ -85,7 +94,10 @@ rchr([], _C, _I, L) -> L.
%% Return the first/last index of the sub-string in a string.
%% index/2 is kept for backwards compatibility.
--spec str(string(), string()) -> non_neg_integer().
+-spec str(String, SubString) -> Index when
+ String :: string(),
+ SubString :: string(),
+ Index :: non_neg_integer().
str(S, Sub) when is_list(Sub) -> str(S, Sub, 1).
@@ -97,7 +109,10 @@ str([C|S], [C|Sub], I) ->
str([_|S], Sub, I) -> str(S, Sub, I+1);
str([], _Sub, _I) -> 0.
--spec rstr(string(), string()) -> non_neg_integer().
+-spec rstr(String, SubString) -> Index when
+ String :: string(),
+ SubString :: string(),
+ Index :: non_neg_integer().
rstr(S, Sub) when is_list(Sub) -> rstr(S, Sub, 1, 0).
@@ -116,7 +131,10 @@ prefix(Pre, String) when is_list(Pre), is_list(String) -> false.
%% span(String, Chars) -> Length.
%% cspan(String, Chars) -> Length.
--spec span(string(), string()) -> non_neg_integer().
+-spec span(String, Chars) -> Length when
+ String :: string(),
+ Chars :: string(),
+ Length :: non_neg_integer().
span(S, Cs) when is_list(Cs) -> span(S, Cs, 0).
@@ -127,7 +145,10 @@ span([C|S], Cs, I) ->
end;
span([], _Cs, I) -> I.
--spec cspan(string(), string()) -> non_neg_integer().
+-spec cspan(String, Chars) -> Length when
+ String :: string(),
+ Chars :: string(),
+ Length :: non_neg_integer().
cspan(S, Cs) when is_list(Cs) -> cspan(S, Cs, 0).
@@ -142,14 +163,21 @@ cspan([], _Cs, I) -> I.
%% substr(String, Start, Length)
%% Extract a sub-string from String.
--spec substr(string(), pos_integer()) -> string().
+-spec substr(String, Start) -> SubString when
+ String :: string(),
+ SubString :: string(),
+ Start :: pos_integer().
substr(String, 1) when is_list(String) ->
String;
substr(String, S) when is_integer(S), S > 1 ->
substr2(String, S).
--spec substr(string(), pos_integer(), non_neg_integer()) -> string().
+-spec substr(String, Start, Length) -> SubString when
+ String :: string(),
+ SubString :: string(),
+ Start :: pos_integer(),
+ Length :: non_neg_integer().
substr(String, S, L) when is_integer(S), S >= 1, is_integer(L), L >= 0 ->
substr1(substr2(String, S), L).
@@ -163,7 +191,10 @@ substr2([_|String], S) -> substr2(String, S-1).
%% tokens(String, Seperators).
%% Return a list of tokens seperated by characters in Seperators.
--spec tokens(string(), string()) -> [[char(),...]].
+-spec tokens(String, SeparatorList) -> Tokens when
+ String :: string(),
+ SeparatorList :: string(),
+ Tokens :: [Token :: nonempty_string()].
tokens(S, Seps) ->
tokens1(S, Seps, []).
@@ -184,11 +215,18 @@ tokens2([C|S], Seps, Toks, Cs) ->
tokens2([], _Seps, Toks, Cs) ->
reverse([reverse(Cs)|Toks]).
--spec chars(char(), non_neg_integer()) -> string().
+-spec chars(Character, Number) -> String when
+ Character :: char(),
+ Number :: non_neg_integer(),
+ String :: string().
chars(C, N) -> chars(C, N, []).
--spec chars(char(), non_neg_integer(), string()) -> string().
+-spec chars(Character, Number, Tail) -> String when
+ Character :: char(),
+ Number :: non_neg_integer(),
+ Tail :: string(),
+ String :: string().
chars(C, N, Tail) when N > 0 ->
chars(C, N-1, [C|Tail]);
@@ -199,7 +237,10 @@ chars(C, 0, Tail) when is_integer(C) ->
%%% COPIES %%%
--spec copies(string(), non_neg_integer()) -> string().
+-spec copies(String, Number) -> Copies when
+ String :: string(),
+ Copies :: string(),
+ Number :: non_neg_integer().
copies(CharList, Num) when is_list(CharList), is_integer(Num), Num >= 0 ->
copies(CharList, Num, []).
@@ -211,11 +252,16 @@ copies(CharList, Num, R) ->
%%% WORDS %%%
--spec words(string()) -> pos_integer().
+-spec words(String) -> Count when
+ String :: string(),
+ Count :: pos_integer().
words(String) -> words(String, $\s).
--spec words(string(), char()) -> pos_integer().
+-spec words(String, Character) -> Count when
+ String :: string(),
+ Character :: char(),
+ Count :: pos_integer().
words(String, Char) when is_integer(Char) ->
w_count(strip(String, both, Char), Char, 0).
@@ -226,11 +272,18 @@ w_count([_H|T], Char, Num) -> w_count(T, Char, Num).
%%% SUB_WORDS %%%
--spec sub_word(string(), integer()) -> string().
+-spec sub_word(String, Number) -> Word when
+ String :: string(),
+ Word :: string(),
+ Number :: integer().
sub_word(String, Index) -> sub_word(String, Index, $\s).
--spec sub_word(string(), integer(), char()) -> string().
+-spec sub_word(String, Number, Character) -> Word when
+ String :: string(),
+ Word :: string(),
+ Number :: integer(),
+ Character :: char().
sub_word(String, Index, Char) when is_integer(Index), is_integer(Char) ->
case words(String, Char) of
@@ -254,14 +307,21 @@ s_word([_|T],Stop,Char,Index,Res) when Index < Stop ->
strip(String) -> strip(String, both).
--spec strip(string(), direction()) -> string().
+-spec strip(String, Direction) -> Stripped when
+ String :: string(),
+ Stripped :: string(),
+ Direction :: left | right | both.
strip(String, left) -> strip_left(String, $\s);
strip(String, right) -> strip_right(String, $\s);
strip(String, both) ->
strip_right(strip_left(String, $\s), $\s).
--spec strip(string(), direction(), char()) -> string().
+-spec strip(String, Direction, Character) -> Stripped when
+ String :: string(),
+ Stripped :: string(),
+ Direction :: left | right | both,
+ Character :: char().
strip(String, right, Char) -> strip_right(String, Char);
strip(String, left, Char) -> strip_left(String, Char);
@@ -285,11 +345,18 @@ strip_right([], Sc) when is_integer(Sc) ->
%%% LEFT %%%
--spec left(string(), non_neg_integer()) -> string().
+-spec left(String, Number) -> Left when
+ String :: string(),
+ Left :: string(),
+ Number :: non_neg_integer().
left(String, Len) when is_integer(Len) -> left(String, Len, $\s).
--spec left(string(), non_neg_integer(), char()) -> string().
+-spec left(String, Number, Character) -> Left when
+ String :: string(),
+ Left :: string(),
+ Number :: non_neg_integer(),
+ Character :: char().
left(String, Len, Char) when is_integer(Char) ->
Slen = length(String),
@@ -303,11 +370,18 @@ l_pad(String, Num, Char) -> String ++ chars(Char, Num).
%%% RIGHT %%%
--spec right(string(), non_neg_integer()) -> string().
+-spec right(String, Number) -> Right when
+ String :: string(),
+ Right :: string(),
+ Number :: non_neg_integer().
right(String, Len) when is_integer(Len) -> right(String, Len, $\s).
--spec right(string(), non_neg_integer(), char()) -> string().
+-spec right(String, Number, Character) -> Right when
+ String :: string(),
+ Right :: string(),
+ Number :: non_neg_integer(),
+ Character :: char().
right(String, Len, Char) when is_integer(Char) ->
Slen = length(String),
@@ -321,11 +395,18 @@ r_pad(String, Num, Char) -> chars(Char, Num, String).
%%% CENTRE %%%
--spec centre(string(), non_neg_integer()) -> string().
+-spec centre(String, Number) -> Centered when
+ String :: string(),
+ Centered :: string(),
+ Number :: non_neg_integer().
centre(String, Len) when is_integer(Len) -> centre(String, Len, $\s).
--spec centre(string(), non_neg_integer(), char()) -> string().
+-spec centre(String, Number, Character) -> Centered when
+ String :: string(),
+ Centered :: string(),
+ Number :: non_neg_integer(),
+ Character :: char().
centre(String, 0, Char) when is_list(String), is_integer(Char) ->
[]; % Strange cases to centre string
@@ -341,11 +422,18 @@ centre(String, Len, Char) when is_integer(Char) ->
%%% SUB_STRING %%%
--spec sub_string(string(), pos_integer()) -> string().
+-spec sub_string(String, Start) -> SubString when
+ String :: string(),
+ SubString :: string(),
+ Start :: pos_integer().
sub_string(String, Start) -> substr(String, Start).
--spec sub_string(string(), pos_integer(), pos_integer()) -> string().
+-spec sub_string(String, Start, Stop) -> SubString when
+ String :: string(),
+ SubString :: string(),
+ Start :: pos_integer(),
+ Stop :: pos_integer().
sub_string(String, Start, Stop) -> substr(String, Start, Stop - Start + 1).
@@ -370,23 +458,34 @@ to_upper_char(C) when is_integer(C), 16#F8 =< C, C =< 16#FE ->
to_upper_char(C) ->
C.
--spec to_lower(string()) -> string()
- ; (char()) -> char().
+-spec to_lower(String) -> Result when
+ String :: string(),
+ Result :: string()
+ ; (Char) -> CharResult when
+ Char :: char(),
+ CharResult :: char().
to_lower(S) when is_list(S) ->
[to_lower_char(C) || C <- S];
to_lower(C) when is_integer(C) ->
to_lower_char(C).
--spec to_upper(string()) -> string()
- ; (char()) -> char().
+-spec to_upper(String) -> Result when
+ String :: string(),
+ Result :: string()
+ ; (Char) -> CharResult when
+ Char :: char(),
+ CharResult :: char().
to_upper(S) when is_list(S) ->
[to_upper_char(C) || C <- S];
to_upper(C) when is_integer(C) ->
to_upper_char(C).
--spec join([string()], string()) -> string().
+-spec join(StringList, Separator) -> String when
+ StringList :: [string()],
+ Separator :: string(),
+ String :: string().
join([], Sep) when is_list(Sep) ->
[];
diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl
index 3c5800effa..9da0d52f8c 100644
--- a/lib/stdlib/src/supervisor.erl
+++ b/lib/stdlib/src/supervisor.erl
@@ -27,27 +27,34 @@
which_children/1, count_children/1,
check_childspecs/1]).
--export([behaviour_info/1]).
-
%% Internal exports
-export([init/1, handle_call/3, handle_info/2, terminate/2, code_change/3]).
-export([handle_cast/2]).
%%--------------------------------------------------------------------------
--export_type([child_spec/0, del_err/0, startchild_ret/0, strategy/0]).
+-export_type([child_spec/0, startchild_ret/0, strategy/0]).
%%--------------------------------------------------------------------------
--type child_id() :: pid() | 'undefined'.
--type mfargs() :: {module(), atom(), [term()] | undefined}.
+-type child() :: pid() | 'undefined'.
+-type child_id() :: term().
+-type mfargs() :: {M :: module(), F :: atom(), A :: [term()] | undefined}.
-type modules() :: [module()] | 'dynamic'.
-type restart() :: 'permanent' | 'transient' | 'temporary'.
-type shutdown() :: 'brutal_kill' | timeout().
-type worker() :: 'worker' | 'supervisor'.
--type sup_name() :: {'local', atom()} | {'global', atom()}.
--type sup_ref() :: atom() | {atom(), atom()} | {'global', atom()} | pid().
--type child_spec() :: {term(),mfargs(),restart(),shutdown(),worker(),modules()}.
+-type sup_name() :: {'local', Name :: atom()} | {'global', Name :: atom()}.
+-type sup_ref() :: (Name :: atom())
+ | {Name :: atom(), Node :: node()}
+ | {'global', Name :: atom()}
+ | pid().
+-type child_spec() :: {Id :: child_id(),
+ StartFunc :: mfargs(),
+ Restart :: restart(),
+ Shutdown :: shutdown(),
+ Type :: worker(),
+ Modules :: modules()}.
-type strategy() :: 'one_for_all' | 'one_for_one'
| 'rest_for_one' | 'simple_one_for_one'.
@@ -55,21 +62,23 @@
%%--------------------------------------------------------------------------
-record(child, {% pid is undefined when child is not running
- pid = undefined :: child_id(),
+ pid = undefined :: child(),
name,
mfargs :: mfargs(),
restart_type :: restart(),
shutdown :: shutdown(),
child_type :: worker(),
modules = [] :: modules()}).
--type child() :: #child{}.
+-type child_rec() :: #child{}.
-define(DICT, dict).
+-define(SETS, sets).
+-define(SET, set).
-record(state, {name,
strategy :: strategy(),
- children = [] :: [child()],
- dynamics :: ?DICT() | list(),
+ children = [] :: [child_rec()],
+ dynamics :: ?DICT() | ?SET(),
intensity :: non_neg_integer(),
period :: pos_integer(),
restarts = [],
@@ -79,14 +88,12 @@
-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) ->
- undefined.
+-callback init(Args :: term()) ->
+ {ok, {{RestartStrategy :: strategy(),
+ MaxR :: non_neg_integer(),
+ MaxT :: non_neg_integer()},
+ [ChildSpec :: child_spec()]}}
+ | ignore.
%%% ---------------------------------------------------
%%% This is a general process supervisor built upon gen_server.erl.
@@ -97,11 +104,16 @@ behaviour_info(_Other) ->
-type startlink_err() :: {'already_started', pid()} | 'shutdown' | term().
-type startlink_ret() :: {'ok', pid()} | 'ignore' | {'error', startlink_err()}.
--spec start_link(module(), term()) -> startlink_ret().
+-spec start_link(Module, Args) -> startlink_ret() when
+ Module :: module(),
+ Args :: term().
start_link(Mod, Args) ->
gen_server:start_link(supervisor, {self, Mod, Args}, []).
--spec start_link(sup_name(), module(), term()) -> startlink_ret().
+-spec start_link(SupName, Module, Args) -> startlink_ret() when
+ SupName :: sup_name(),
+ Module :: module(),
+ Args :: term().
start_link(SupName, Mod, Args) ->
gen_server:start_link(SupName, supervisor, {SupName, Mod, Args}, []).
@@ -109,24 +121,33 @@ start_link(SupName, Mod, Args) ->
%%% Interface functions.
%%% ---------------------------------------------------
--type info() :: term().
-type startchild_err() :: 'already_present'
- | {'already_started', child_id()} | term().
--type startchild_ret() :: {'ok', child_id()} | {'ok', child_id(), info()}
+ | {'already_started', Child :: child()} | term().
+-type startchild_ret() :: {'ok', Child :: child()}
+ | {'ok', Child :: child(), Info :: term()}
| {'error', startchild_err()}.
--spec start_child(sup_ref(), child_spec() | [term()]) -> startchild_ret().
+-spec start_child(SupRef, ChildSpec) -> startchild_ret() when
+ SupRef :: sup_ref(),
+ ChildSpec :: child_spec() | (List :: [term()]).
start_child(Supervisor, ChildSpec) ->
call(Supervisor, {start_child, ChildSpec}).
--type restart_err() :: 'running' | 'not_found' | 'simple_one_for_one' | term().
--spec restart_child(sup_ref(), term()) ->
- {'ok', child_id()} | {'ok', child_id(), info()} | {'error', restart_err()}.
+-spec restart_child(SupRef, Id) -> Result when
+ SupRef :: sup_ref(),
+ Id :: child_id(),
+ Result :: {'ok', Child :: child()}
+ | {'ok', Child :: child(), Info :: term()}
+ | {'error', Error},
+ Error :: 'running' | 'not_found' | 'simple_one_for_one' | term().
restart_child(Supervisor, Name) ->
call(Supervisor, {restart_child, Name}).
--type del_err() :: 'running' | 'not_found' | 'simple_one_for_one'.
--spec delete_child(sup_ref(), term()) -> 'ok' | {'error', del_err()}.
+-spec delete_child(SupRef, Id) -> Result when
+ SupRef :: sup_ref(),
+ Id :: child_id(),
+ Result :: 'ok' | {'error', Error},
+ Error :: 'running' | 'not_found' | 'simple_one_for_one'.
delete_child(Supervisor, Name) ->
call(Supervisor, {delete_child, Name}).
@@ -137,22 +158,39 @@ delete_child(Supervisor, Name) ->
%% way (maybe killed).
%%-----------------------------------------------------------------
--type term_err() :: 'not_found' | 'simple_one_for_one'.
--spec terminate_child(sup_ref(), term()) -> 'ok' | {'error', term_err()}.
+-spec terminate_child(SupRef, Id) -> Result when
+ SupRef :: sup_ref(),
+ Id :: pid() | child_id(),
+ Result :: 'ok' | {'error', Error},
+ Error :: 'not_found' | 'simple_one_for_one'.
terminate_child(Supervisor, Name) ->
call(Supervisor, {terminate_child, Name}).
--spec which_children(sup_ref()) -> [{term(), child_id(), worker(), modules()}].
+-spec which_children(SupRef) -> [{Id,Child,Type,Modules}] when
+ SupRef :: sup_ref(),
+ Id :: child_id() | undefined,
+ Child :: child(),
+ Type :: worker(),
+ Modules :: modules().
which_children(Supervisor) ->
call(Supervisor, which_children).
+-spec count_children(SupRef) -> PropListOfCounts when
+ SupRef :: sup_ref(),
+ PropListOfCounts :: [Count],
+ Count :: {specs, ChildSpecCount :: non_neg_integer()}
+ | {active, ActiveProcessCount :: non_neg_integer()}
+ | {supervisors, ChildSupervisorCount :: non_neg_integer()}
+ |{workers, ChildWorkerCount :: non_neg_integer()}.
count_children(Supervisor) ->
call(Supervisor, count_children).
call(Supervisor, Req) ->
gen_server:call(Supervisor, Req, infinity).
--spec check_childspecs([child_spec()]) -> 'ok' | {'error', term()}.
+-spec check_childspecs(ChildSpecs) -> Result when
+ ChildSpecs :: [child_spec()],
+ Result :: 'ok' | {'error', Error :: term()}.
check_childspecs(ChildSpecs) when is_list(ChildSpecs) ->
case check_startspec(ChildSpecs) of
{ok, _} -> ok;
@@ -220,12 +258,12 @@ init_dynamic(_State, StartSpec) ->
%%-----------------------------------------------------------------
%% Func: start_children/2
-%% Args: Children = [child()] in start order
+%% Args: Children = [child_rec()] in start order
%% SupName = {local, atom()} | {global, atom()} | {pid(), Mod}
%% Purpose: Start all children. The new list contains #child's
%% with pids.
%% Returns: {ok, NChildren} | {error, NChildren}
-%% NChildren = [child()] in termination order (reversed
+%% NChildren = [child_rec()] in termination order (reversed
%% start order)
%%-----------------------------------------------------------------
start_children(Children, SupName) -> start_children(Children, [], SupName).
@@ -297,8 +335,26 @@ handle_call({start_child, EArgs}, _From, State) when ?is_simple(State) ->
{reply, What, State}
end;
-%%% The requests terminate_child, delete_child and restart_child are
-%%% invalid for simple_one_for_one supervisors.
+%% terminate_child for simple_one_for_one can only be done with pid
+handle_call({terminate_child, Name}, _From, State) when not is_pid(Name),
+ ?is_simple(State) ->
+ {reply, {error, simple_one_for_one}, State};
+
+handle_call({terminate_child, Name}, _From, State) ->
+ case get_child(Name, State, ?is_simple(State)) of
+ {value, Child} ->
+ case do_terminate(Child, State#state.name) of
+ #child{restart_type=RT} when RT=:=temporary; ?is_simple(State) ->
+ {reply, ok, state_del_child(Child, State)};
+ NChild ->
+ {reply, ok, replace_child(NChild, State)}
+ end;
+ false ->
+ {reply, {error, not_found}, State}
+ end;
+
+%%% The requests delete_child and restart_child are invalid for
+%%% simple_one_for_one supervisors.
handle_call({_Req, _Data}, _From, State) when ?is_simple(State) ->
{reply, {error, simple_one_for_one}, State};
@@ -341,21 +397,12 @@ handle_call({delete_child, Name}, _From, State) ->
{reply, {error, not_found}, State}
end;
-handle_call({terminate_child, Name}, _From, State) ->
- case get_child(Name, State) of
- {value, Child} ->
- NChild = do_terminate(Child, State#state.name),
- {reply, ok, replace_child(NChild, State)};
- _ ->
- {reply, {error, not_found}, State}
- end;
-
handle_call(which_children, _From, #state{children = [#child{restart_type = temporary,
child_type = CT,
modules = Mods}]} =
State) when ?is_simple(State) ->
- Reply = lists:map(fun(Pid) -> {undefined, Pid, CT, Mods} end, dynamics_db(temporary,
- State#state.dynamics)),
+ Reply = lists:map(fun(Pid) -> {undefined, Pid, CT, Mods} end,
+ ?SETS:to_list(dynamics_db(temporary, State#state.dynamics))),
{reply, Reply, State};
handle_call(which_children, _From, #state{children = [#child{restart_type = RType,
@@ -380,7 +427,7 @@ handle_call(count_children, _From, #state{children = [#child{restart_type = temp
child_type = CT}]} = State)
when ?is_simple(State) ->
{Active, Count} =
- lists:foldl(fun(Pid, {Alive, Tot}) ->
+ ?SETS:fold(fun(Pid, {Alive, Tot}) ->
if is_pid(Pid) -> {Alive+1, Tot +1};
true -> {Alive, Tot + 1} end
end, {0, 0}, dynamics_db(temporary, State#state.dynamics)),
@@ -610,6 +657,9 @@ do_restart(_, normal, Child, State) ->
do_restart(_, shutdown, Child, State) ->
NState = state_del_child(Child, State),
{ok, NState};
+do_restart(_, {shutdown, _Term}, Child, State) ->
+ NState = state_del_child(Child, State),
+ {ok, NState};
do_restart(transient, Reason, Child, State) ->
report_error(child_terminated, Reason, Child, State#state.name),
restart(Child, State);
@@ -676,14 +726,21 @@ restart(one_for_all, Child, State) ->
%%-----------------------------------------------------------------
%% Func: terminate_children/2
-%% Args: Children = [child()] in termination order
+%% Args: Children = [child_rec()] in termination order
%% SupName = {local, atom()} | {global, atom()} | {pid(),Mod}
-%% Returns: NChildren = [child()] in
+%% Returns: NChildren = [child_rec()] in
%% startup order (reversed termination order)
%%-----------------------------------------------------------------
terminate_children(Children, SupName) ->
terminate_children(Children, SupName, []).
+%% Temporary children should not be restarted and thus should
+%% be skipped when building the list of terminated children, although
+%% we do want them to be shut down as many functions from this module
+%% use this function to just clear everything.
+terminate_children([Child = #child{restart_type=temporary} | Children], SupName, Res) ->
+ do_terminate(Child, SupName),
+ terminate_children(Children, SupName, Res);
terminate_children([Child | Children], SupName, Res) ->
NChild = do_terminate(Child, SupName),
terminate_children(Children, SupName, [NChild | Res]);
@@ -791,24 +848,27 @@ save_child(Child, #state{children = Children} = State) ->
State#state{children = [Child |Children]}.
save_dynamic_child(temporary, Pid, _, #state{dynamics = Dynamics} = State) ->
- State#state{dynamics = [Pid | dynamics_db(temporary, Dynamics)]};
+ State#state{dynamics = ?SETS:add_element(Pid, dynamics_db(temporary, Dynamics))};
save_dynamic_child(RestartType, Pid, Args, #state{dynamics = Dynamics} = State) ->
State#state{dynamics = ?DICT:store(Pid, Args, dynamics_db(RestartType, Dynamics))}.
dynamics_db(temporary, undefined) ->
- [];
+ ?SETS:new();
dynamics_db(_, undefined) ->
?DICT:new();
dynamics_db(_,Dynamics) ->
Dynamics.
-dynamic_child_args(_, Dynamics) when is_list(Dynamics)->
- {ok, undefined};
dynamic_child_args(Pid, Dynamics) ->
- ?DICT:find(Pid, Dynamics).
+ case ?SETS:is_set(Dynamics) of
+ true ->
+ {ok, undefined};
+ false ->
+ ?DICT:find(Pid, Dynamics)
+ end.
state_del_child(#child{pid = Pid, restart_type = temporary}, State) when ?is_simple(State) ->
- NDynamics = lists:delete(Pid, dynamics_db(temporary, State#state.dynamics)),
+ NDynamics = ?SETS:del_element(Pid, dynamics_db(temporary, State#state.dynamics)),
State#state{dynamics = NDynamics};
state_del_child(#child{pid = Pid, restart_type = RType}, State) when ?is_simple(State) ->
NDynamics = ?DICT:erase(Pid, dynamics_db(RType, State#state.dynamics)),
@@ -817,8 +877,12 @@ state_del_child(Child, State) ->
NChildren = del_child(Child#child.name, State#state.children),
State#state{children = NChildren}.
+del_child(Name, [Ch|Chs]) when Ch#child.name =:= Name, Ch#child.restart_type =:= temporary ->
+ Chs;
del_child(Name, [Ch|Chs]) when Ch#child.name =:= Name ->
[Ch#child{pid = undefined} | Chs];
+del_child(Pid, [Ch|Chs]) when Ch#child.pid =:= Pid, Ch#child.restart_type =:= temporary ->
+ Chs;
del_child(Pid, [Ch|Chs]) when Ch#child.pid =:= Pid ->
[Ch#child{pid = undefined} | Chs];
del_child(Name, [Ch|Chs]) ->
@@ -841,7 +905,31 @@ split_child(_, [], After) ->
{lists:reverse(After), []}.
get_child(Name, State) ->
+ get_child(Name, State, false).
+get_child(Pid, State, AllowPid) when AllowPid, is_pid(Pid) ->
+ get_dynamic_child(Pid, State);
+get_child(Name, State, _) ->
lists:keysearch(Name, #child.name, State#state.children).
+
+get_dynamic_child(Pid, #state{children=[Child], dynamics=Dynamics}) ->
+ case is_dynamic_pid(Pid, dynamics_db(Child#child.restart_type, Dynamics)) of
+ true ->
+ {value, Child#child{pid=Pid}};
+ false ->
+ case erlang:is_process_alive(Pid) of
+ true -> false;
+ false -> {value, Child}
+ end
+ end.
+
+is_dynamic_pid(Pid, Dynamics) ->
+ case ?SETS:is_set(Dynamics) of
+ true ->
+ ?SETS:is_element(Pid, Dynamics);
+ false ->
+ ?DICT:is_key(Pid, Dynamics)
+ end.
+
replace_child(Child, State) ->
Chs = do_replace_child(Child, State#state.children),
State#state{children = Chs}.
@@ -916,7 +1004,7 @@ supname(N, _) -> N.
%%% Shutdown = integer() | infinity | brutal_kill
%%% ChildType = supervisor | worker
%%% Modules = [atom()] | dynamic
-%%% Returns: {ok, [child()]} | Error
+%%% Returns: {ok, [child_rec()]} | Error
%%% ------------------------------------------------------
check_startspec(Children) -> check_startspec(Children, []).
diff --git a/lib/stdlib/src/supervisor_bridge.erl b/lib/stdlib/src/supervisor_bridge.erl
index 3d2bd2c9a5..e8405ab9a4 100644
--- a/lib/stdlib/src/supervisor_bridge.erl
+++ b/lib/stdlib/src/supervisor_bridge.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,15 +22,14 @@
%% External exports
-export([start_link/2, start_link/3]).
--export([behaviour_info/1]).
%% Internal exports
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]).
-export([code_change/3]).
-behaviour_info(callbacks) ->
- [{init,1},{terminate,2}];
-behaviour_info(_Other) ->
- undefined.
+-callback init(Args :: term()) ->
+ {ok, Pid :: pid(), State :: term()} | ignore | {error, Error :: term()}.
+-callback terminate(Reason :: (shutdown | term()), State :: term()) ->
+ Ignored :: term().
%%%-----------------------------------------------------------------
%%% This is a rewrite of supervisor_bridge from BS.3.
@@ -49,9 +48,25 @@ behaviour_info(_Other) ->
%%%-----------------------------------------------------------------
-record(state, {mod, pid, child_state, name}).
+-spec start_link(Module, Args) -> Result when
+ Module :: module(),
+ Args :: term(),
+ Result :: {ok, Pid} | ignore | {error, Error},
+ Error :: {already_started, Pid} | term(),
+ Pid :: pid().
+
start_link(Mod, StartArgs) ->
gen_server:start_link(supervisor_bridge, [Mod, StartArgs, self], []).
+-spec start_link(SupBridgeName, Module, Args) -> Result when
+ SupBridgeName :: {local, Name} | {global, Name},
+ Name :: atom(),
+ Module :: module(),
+ Args :: term(),
+ Result :: {ok, Pid} | ignore | {error, Error},
+ Error :: {already_started, Pid} | term(),
+ Pid :: pid().
+
start_link(Name, Mod, StartArgs) ->
gen_server:start_link(Name, supervisor_bridge, [Mod, StartArgs, Name], []).
diff --git a/lib/stdlib/src/sys.erl b/lib/stdlib/src/sys.erl
index 12209c16d7..f34201604c 100644
--- a/lib/stdlib/src/sys.erl
+++ b/lib/stdlib/src/sys.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,22 +33,74 @@
%%-----------------------------------------------------------------
-type name() :: pid() | atom() | {'global', atom()}.
--type system_event() :: {'in', _Msg} | {'in', _Msg, _From} | {'out', _Msg, _To}.
+-type system_event() :: {'in', Msg :: _}
+ | {'in', Msg :: _, From :: _}
+ | {'out', Msg :: _, To :: _}
+ | term().
+-opaque dbg_opt() :: list().
+-type dbg_fun() :: fun((FuncState :: _,
+ Event :: system_event(),
+ ProcState :: _) -> 'done' | (NewFuncState :: _)).
%%-----------------------------------------------------------------
%% System messages
%%-----------------------------------------------------------------
+-spec suspend(Name) -> Void when
+ Name :: name(),
+ Void :: term().
suspend(Name) -> send_system_msg(Name, suspend).
+-spec suspend(Name, Timeout) -> Void when
+ Name :: name(),
+ Timeout :: timeout(),
+ Void :: term().
suspend(Name, Timeout) -> send_system_msg(Name, suspend, Timeout).
+-spec resume(Name) -> Void when
+ Name :: name(),
+ Void :: term().
resume(Name) -> send_system_msg(Name, resume).
+-spec resume(Name, Timeout) -> Void when
+ Name :: name(),
+ Timeout :: timeout(),
+ Void :: term().
resume(Name, Timeout) -> send_system_msg(Name, resume, Timeout).
+-spec get_status(Name) -> Status when
+ Name :: name(),
+ Status :: {status, Pid :: pid(), {module, Module :: module()}, [SItem]},
+ SItem :: (PDict :: [{Key :: term(), Value :: term()}])
+ | (SysState :: 'running' | 'suspended')
+ | (Parent :: pid())
+ | (Dbg :: dbg_opt())
+ | (Misc :: term()).
get_status(Name) -> send_system_msg(Name, get_status).
+-spec get_status(Name, Timeout) -> Status when
+ Name :: name(),
+ Timeout :: timeout(),
+ Status :: {status, Pid :: pid(), {module, Module :: module()}, [SItem]},
+ SItem :: (PDict :: [{Key :: term(), Value :: term()}])
+ | (SysState :: 'running' | 'suspended')
+ | (Parent :: pid())
+ | (Dbg :: dbg_opt())
+ | (Misc :: term()).
get_status(Name, Timeout) -> send_system_msg(Name, get_status, Timeout).
+-spec change_code(Name, Module, OldVsn, Extra) -> 'ok' | {error, Reason} when
+ Name :: name(),
+ Module :: module(),
+ OldVsn :: 'undefined' | term(),
+ Extra :: term(),
+ Reason :: term().
change_code(Name, Mod, Vsn, Extra) ->
send_system_msg(Name, {change_code, Mod, Vsn, Extra}).
+-spec change_code(Name, Module, OldVsn, Extra, Timeout) ->
+ 'ok' | {error, Reason} when
+ Name :: name(),
+ Module :: module(),
+ OldVsn :: 'undefined' | term(),
+ Extra :: term(),
+ Timeout :: timeout(),
+ Reason :: term().
change_code(Name, Mod, Vsn, Extra, Timeout) ->
send_system_msg(Name, {change_code, Mod, Vsn, Extra}, Timeout).
@@ -56,52 +108,116 @@ change_code(Name, Mod, Vsn, Extra, Timeout) ->
%% Debug commands
%%-----------------------------------------------------------------
--type log_flag() :: 'true' | {'true',pos_integer()} | 'false' | 'get' | 'print'.
-
--spec log(name(), log_flag()) -> 'ok' | {'ok', [system_event()]}.
+-spec log(Name, Flag) -> 'ok' | {'ok', [system_event()]} when
+ Name :: name(),
+ Flag :: 'true' |
+ {'true', N :: pos_integer()}
+ | 'false' | 'get' | 'print'.
log(Name, Flag) ->
send_system_msg(Name, {debug, {log, Flag}}).
--spec log(name(), log_flag(), timeout()) -> 'ok' | {'ok', [system_event()]}.
+-spec log(Name, Flag, Timeout) -> 'ok' | {'ok', [system_event()]} when
+ Name :: name(),
+ Flag :: 'true' |
+ {'true', N :: pos_integer()}
+ | 'false' | 'get' | 'print',
+ Timeout :: timeout().
log(Name, Flag, Timeout) ->
send_system_msg(Name, {debug, {log, Flag}}, Timeout).
--spec trace(name(), boolean()) -> 'ok'.
+-spec trace(Name, Flag) -> 'ok' when
+ Name :: name(),
+ Flag :: boolean().
trace(Name, Flag) ->
send_system_msg(Name, {debug, {trace, Flag}}).
--spec trace(name(), boolean(), timeout()) -> 'ok'.
+-spec trace(Name, Flag, Timeout) -> 'ok' when
+ Name :: name(),
+ Flag :: boolean(),
+ Timeout :: timeout().
trace(Name, Flag, Timeout) ->
send_system_msg(Name, {debug, {trace, Flag}}, Timeout).
--type l2f_fname() :: string() | 'false'.
-
--spec log_to_file(name(), l2f_fname()) -> 'ok' | {'error','open_file'}.
+-spec log_to_file(Name, Flag) -> 'ok' | {'error','open_file'} when
+ Name :: name(),
+ Flag :: (FileName :: string()) | 'false'.
log_to_file(Name, FileName) ->
send_system_msg(Name, {debug, {log_to_file, FileName}}).
--spec log_to_file(name(), l2f_fname(), timeout()) -> 'ok' | {'error','open_file'}.
+-spec log_to_file(Name, Flag, Timeout) -> 'ok' | {'error','open_file'} when
+ Name :: name(),
+ Flag :: (FileName :: string()) | 'false',
+ Timeout :: timeout().
log_to_file(Name, FileName, Timeout) ->
send_system_msg(Name, {debug, {log_to_file, FileName}}, Timeout).
+-spec statistics(Name, Flag) -> 'ok' | {'ok', Statistics} when
+ Name :: name(),
+ Flag :: 'true' | 'false' | 'get',
+ Statistics :: [StatisticsTuple] | no_statistics,
+ StatisticsTuple :: {'start_time', DateTime1}
+ | {'current_time', DateTime2}
+ | {'reductions', non_neg_integer()}
+ | {'messages_in', non_neg_integer()}
+ | {'messages_out', non_neg_integer()},
+ DateTime1 :: file:date_time(),
+ DateTime2 :: file:date_time().
statistics(Name, Flag) ->
send_system_msg(Name, {debug, {statistics, Flag}}).
+
+-spec statistics(Name, Flag, Timeout) -> 'ok' | {'ok', Statistics} when
+ Name :: name(),
+ Flag :: 'true' | 'false' | 'get',
+ Statistics :: [StatisticsTuple] | no_statistics,
+ StatisticsTuple :: {'start_time', DateTime1}
+ | {'current_time', DateTime2}
+ | {'reductions', non_neg_integer()}
+ | {'messages_in', non_neg_integer()}
+ | {'messages_out', non_neg_integer()},
+ DateTime1 :: file:date_time(),
+ DateTime2 :: file:date_time(),
+ Timeout :: timeout().
statistics(Name, Flag, Timeout) ->
send_system_msg(Name, {debug, {statistics, Flag}}, Timeout).
--spec no_debug(name()) -> 'ok'.
+-spec no_debug(Name) -> 'ok' when
+ Name :: name().
no_debug(Name) -> send_system_msg(Name, {debug, no_debug}).
--spec no_debug(name(), timeout()) -> 'ok'.
+-spec no_debug(Name, Timeout) -> 'ok' when
+ Name :: name(),
+ Timeout :: timeout().
no_debug(Name, Timeout) -> send_system_msg(Name, {debug, no_debug}, Timeout).
+-spec install(Name, FuncSpec) -> Void when
+ Name :: name(),
+ FuncSpec :: {Func, FuncState},
+ Func :: dbg_fun(),
+ FuncState :: term(),
+ Void :: term().
install(Name, {Func, FuncState}) ->
send_system_msg(Name, {debug, {install, {Func, FuncState}}}).
+-spec install(Name, FuncSpec, Timeout) -> Void when
+ Name :: name(),
+ FuncSpec :: {Func, FuncState},
+ Func :: dbg_fun(),
+ FuncState :: term(),
+ Timeout :: timeout(),
+ Void :: term().
install(Name, {Func, FuncState}, Timeout) ->
send_system_msg(Name, {debug, {install, {Func, FuncState}}}, Timeout).
+-spec remove(Name, Func) -> Void when
+ Name :: name(),
+ Func :: dbg_fun(),
+ Void :: term().
remove(Name, Func) ->
send_system_msg(Name, {debug, {remove, Func}}).
+-spec remove(Name, Func, Timeout) -> Void when
+ Name :: name(),
+ Func :: dbg_fun(),
+ Timeout :: timeout(),
+ Void :: term().
remove(Name, Func, Timeout) ->
send_system_msg(Name, {debug, {remove, Func}}, Timeout).
@@ -150,6 +266,14 @@ mfa(Name, Req, Timeout) ->
%% The Module must export system_continue/3, system_terminate/4
%% and format_status/2 for status information.
%%-----------------------------------------------------------------
+-spec handle_system_msg(Msg, From, Parent, Module, Debug, Misc) -> Void when
+ Msg :: term(),
+ From :: {pid(), Tag :: _},
+ Parent :: pid(),
+ Module :: module(),
+ Debug :: [dbg_opt()],
+ Misc :: term(),
+ Void :: term().
handle_system_msg(Msg, From, Parent, Module, Debug, Misc) ->
handle_system_msg(running, Msg, From, Parent, Module, Debug, Misc, false).
@@ -176,6 +300,11 @@ handle_system_msg(SysState, Msg, From, Parent, Mod, Debug, Misc, Hib) ->
%% Func is a formatting function, called as Func(Device, Event).
%% Returns: [debug_opts()]
%%-----------------------------------------------------------------
+-spec handle_debug(Debug, FormFunc, Extra, Event) -> [dbg_opt()] when
+ Debug :: [dbg_opt()],
+ FormFunc :: dbg_fun(),
+ Extra :: term(),
+ Event :: system_event().
handle_debug([{trace, true} | T], FormFunc, State, Event) ->
print_event({Event, State, FormFunc}),
[{trace, true} | handle_debug(T, FormFunc, State, Event)];
@@ -341,24 +470,36 @@ trim(N, LogData) ->
%% Debug structure manipulating functions
%%-----------------------------------------------------------------
install_debug(Item, Data, Debug) ->
- case get_debug(Item, Debug, undefined) of
+ case get_debug2(Item, Debug, undefined) of
undefined -> [{Item, Data} | Debug];
_ -> Debug
end.
remove_debug(Item, Debug) -> lists:keydelete(Item, 1, Debug).
+
+-spec get_debug(Item, Debug, Default) -> term() when
+ Item :: 'log' | 'statistics',
+ Debug :: [dbg_opt()],
+ Default :: term().
get_debug(Item, Debug, Default) ->
+ get_debug2(Item, Debug, Default).
+
+%% Workaround: accepts more Item types than get_debug/3.
+get_debug2(Item, Debug, Default) ->
case lists:keysearch(Item, 1, Debug) of
{value, {Item, Data}} -> Data;
_ -> Default
end.
+-spec print_log(Debug) -> Void when
+ Debug :: [dbg_opt()],
+ Void :: term().
print_log(Debug) ->
{_N, Logs} = get_debug(log, Debug, {0, []}),
lists:foreach(fun print_event/1,
lists:reverse(Logs)).
close_log_file(Debug) ->
- case get_debug(log_to_file, Debug, []) of
+ case get_debug2(log_to_file, Debug, []) of
[] ->
Debug;
Fd ->
@@ -375,6 +516,15 @@ close_log_file(Debug) ->
%% system messages.
%% Returns: [debug_opts()]
%%-----------------------------------------------------------------
+
+-spec debug_options(Options) -> [dbg_opt()] when
+ Options :: [Opt],
+ Opt :: 'trace' | 'log' | 'statistics' | {'log_to_file', FileName}
+ | {'install', FuncSpec},
+ FileName :: file:name(),
+ FuncSpec :: {Func, FuncState},
+ Func :: dbg_fun(),
+ FuncState :: term().
debug_options(Options) ->
debug_options(Options, []).
debug_options([trace | T], Debug) ->
diff --git a/lib/stdlib/src/timer.erl b/lib/stdlib/src/timer.erl
index b456c5d6c1..689e42051f 100644
--- a/lib/stdlib/src/timer.erl
+++ b/lib/stdlib/src/timer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,7 +22,7 @@
send_after/3, send_after/2,
exit_after/3, exit_after/2, kill_after/2, kill_after/1,
apply_interval/4, send_interval/3, send_interval/2,
- cancel/1, sleep/1, tc/2, tc/3, now_diff/2,
+ cancel/1, sleep/1, tc/1, tc/2, tc/3, now_diff/2,
seconds/1, minutes/1, hours/1, hms/3]).
-export([start_link/0, start/0,
@@ -46,103 +46,189 @@
%%
-opaque tref() :: {integer(), reference()}.
-type time() :: non_neg_integer().
--type timestamp() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}.
%%
%% Interface functions
%%
--spec apply_after(time(), atom(), atom(), [term()]) -> {'ok', tref()} | {'error', term()}.
+-spec apply_after(Time, Module, Function, Arguments) ->
+ {'ok', TRef} | {'error', Reason} when
+ Time :: time(),
+ Module :: module(),
+ Function :: atom(),
+ Arguments :: [term()],
+ TRef :: tref(),
+ Reason :: term().
+
apply_after(Time, M, F, A) ->
req(apply_after, {Time, {M, F, A}}).
--spec send_after(time(), pid() | atom(), term()) -> {'ok', tref()} | {'error', term()}.
+-spec send_after(Time, Pid, Message) -> {'ok', TRef} | {'error', Reason} when
+ Time :: time(),
+ Pid :: pid() | (RegName :: atom()),
+ Message :: term(),
+ TRef :: tref(),
+ Reason :: term().
send_after(Time, Pid, Message) ->
req(apply_after, {Time, {?MODULE, send, [Pid, Message]}}).
--spec send_after(time(), term()) -> {'ok', tref()} | {'error', term()}.
+-spec send_after(Time, Message) -> {'ok', TRef} | {'error', Reason} when
+ Time :: time(),
+ Message :: term(),
+ TRef :: tref(),
+ Reason :: term().
send_after(Time, Message) ->
send_after(Time, self(), Message).
--spec exit_after(time(), pid() | atom(), term()) -> {'ok', tref()} | {'error', term()}.
+-spec exit_after(Time, Pid, Reason1) -> {'ok', TRef} | {'error', Reason2} when
+ Time :: time(),
+ Pid :: pid() | (RegName :: atom()),
+ TRef :: tref(),
+ Reason1 :: term(),
+ Reason2 :: term().
exit_after(Time, Pid, Reason) ->
req(apply_after, {Time, {erlang, exit, [Pid, Reason]}}).
--spec exit_after(time(), term()) -> {'ok', tref()} | {'error', term()}.
+-spec exit_after(Time, Reason1) -> {'ok', TRef} | {'error', Reason2} when
+ Time :: time(),
+ TRef :: tref(),
+ Reason1 :: term(),
+ Reason2 :: term().
exit_after(Time, Reason) ->
exit_after(Time, self(), Reason).
--spec kill_after(time(), pid() | atom()) -> {'ok', tref()} | {'error', term()}.
+-spec kill_after(Time, Pid) -> {'ok', TRef} | {'error', Reason2} when
+ Time :: time(),
+ Pid :: pid() | (RegName :: atom()),
+ TRef :: tref(),
+ Reason2 :: term().
kill_after(Time, Pid) ->
exit_after(Time, Pid, kill).
--spec kill_after(time()) -> {'ok', tref()} | {'error', term()}.
+-spec kill_after(Time) -> {'ok', TRef} | {'error', Reason2} when
+ Time :: time(),
+ TRef :: tref(),
+ Reason2 :: term().
kill_after(Time) ->
exit_after(Time, self(), kill).
--spec apply_interval(time(), atom(), atom(), [term()]) -> {'ok', tref()} | {'error', term()}.
+-spec apply_interval(Time, Module, Function, Arguments) ->
+ {'ok', TRef} | {'error', Reason} when
+ Time :: time(),
+ Module :: module(),
+ Function :: atom(),
+ Arguments :: [term()],
+ TRef :: tref(),
+ Reason :: term().
apply_interval(Time, M, F, A) ->
req(apply_interval, {Time, self(), {M, F, A}}).
--spec send_interval(time(), pid() | atom(), term()) -> {'ok', tref()} | {'error', term()}.
+-spec send_interval(Time, Pid, Message) ->
+ {'ok', TRef} | {'error', Reason} when
+ Time :: time(),
+ Pid :: pid() | (RegName :: atom()),
+ Message :: term(),
+ TRef :: tref(),
+ Reason :: term().
send_interval(Time, Pid, Message) ->
req(apply_interval, {Time, Pid, {?MODULE, send, [Pid, Message]}}).
--spec send_interval(time(), term()) -> {'ok', tref()} | {'error', term()}.
+-spec send_interval(Time, Message) -> {'ok', TRef} | {'error', Reason} when
+ Time :: time(),
+ Message :: term(),
+ TRef :: tref(),
+ Reason :: term().
send_interval(Time, Message) ->
send_interval(Time, self(), Message).
--spec cancel(tref()) -> {'ok', 'cancel'} | {'error', term()}.
+-spec cancel(TRef) -> {'ok', 'cancel'} | {'error', Reason} when
+ TRef :: tref(),
+ Reason :: term().
cancel(BRef) ->
req(cancel, BRef).
--spec sleep(timeout()) -> 'ok'.
+-spec sleep(Time) -> 'ok' when
+ Time :: timeout().
sleep(T) ->
receive
after T -> ok
end.
+%%
+%% Measure the execution time (in microseconds) for Fun().
+%%
+-spec tc(Fun) -> {Time, Value} when
+ Fun :: function(),
+ Time :: integer(),
+ Value :: term().
+tc(F) ->
+ Before = os:timestamp(),
+ Val = F(),
+ After = os:timestamp(),
+ {now_diff(After, Before), Val}.
%%
%% Measure the execution time (in microseconds) for Fun(Args).
%%
--spec tc(function(), [_]) -> {time(), term()}.
+-spec tc(Fun, Arguments) -> {Time, Value} when
+ Fun :: function(),
+ Arguments :: [term()],
+ Time :: integer(),
+ Value :: term().
tc(F, A) ->
- Before = erlang:now(),
- Val = (catch apply(F, A)),
- After = erlang:now(),
+ Before = os:timestamp(),
+ Val = apply(F, A),
+ After = os:timestamp(),
{now_diff(After, Before), Val}.
%%
%% Measure the execution time (in microseconds) for an MFA.
%%
--spec tc(atom(), atom(), [term()]) -> {time(), term()}.
+-spec tc(Module, Function, Arguments) -> {Time, Value} when
+ Module :: module(),
+ Function :: atom(),
+ Arguments :: [term()],
+ Time :: integer(),
+ Value :: term().
tc(M, F, A) ->
- Before = erlang:now(),
- Val = (catch apply(M, F, A)),
- After = erlang:now(),
+ Before = os:timestamp(),
+ Val = apply(M, F, A),
+ After = os:timestamp(),
{now_diff(After, Before), Val}.
%%
%% Calculate the time difference (in microseconds) of two
%% erlang:now() timestamps, T2-T1.
%%
--spec now_diff(timestamp(), timestamp()) -> integer().
+-spec now_diff(T2, T1) -> Tdiff when
+ T1 :: erlang:timestamp(),
+ T2 :: erlang:timestamp(),
+ Tdiff :: integer().
now_diff({A2, B2, C2}, {A1, B1, C1}) ->
((A2-A1)*1000000 + B2-B1)*1000000 + C2-C1.
%%
%% Convert seconds, minutes etc. to milliseconds.
%%
--spec seconds(non_neg_integer()) -> non_neg_integer().
+-spec seconds(Seconds) -> MilliSeconds when
+ Seconds :: non_neg_integer(),
+ MilliSeconds :: non_neg_integer().
seconds(Seconds) ->
1000*Seconds.
--spec minutes(non_neg_integer()) -> non_neg_integer().
+-spec minutes(Minutes) -> MilliSeconds when
+ Minutes :: non_neg_integer(),
+ MilliSeconds :: non_neg_integer().
minutes(Minutes) ->
1000*60*Minutes.
--spec hours(non_neg_integer()) -> non_neg_integer().
+-spec hours(Hours) -> MilliSeconds when
+ Hours :: non_neg_integer(),
+ MilliSeconds :: non_neg_integer().
hours(Hours) ->
1000*60*60*Hours.
--spec hms(non_neg_integer(), non_neg_integer(), non_neg_integer()) -> non_neg_integer().
+-spec hms(Hours, Minutes, Seconds) -> MilliSeconds when
+ Hours :: non_neg_integer(),
+ Minutes :: non_neg_integer(),
+ Seconds :: non_neg_integer(),
+ MilliSeconds :: non_neg_integer().
hms(H, M, S) ->
hours(H) + minutes(M) + seconds(S).
diff --git a/lib/stdlib/src/unicode.erl b/lib/stdlib/src/unicode.erl
index 12bc60623d..e9b90befe6 100644
--- a/lib/stdlib/src/unicode.erl
+++ b/lib/stdlib/src/unicode.erl
@@ -30,12 +30,34 @@
characters_to_binary/3,
bom_to_encoding/1, encoding_to_bom/1]).
--export_type([encoding/0]).
+-export_type([chardata/0, charlist/0, encoding/0, external_chardata/0,
+ external_charlist/0, latin1_chardata/0,
+ latin1_charlist/0, unicode_binary/0, unicode_char/0]).
-type encoding() :: 'latin1' | 'unicode' | 'utf8'
| 'utf16' | {'utf16', endian()}
| 'utf32' | {'utf32', endian()}.
-type endian() :: 'big' | 'little'.
+-type unicode_binary() :: binary().
+-type unicode_char() :: non_neg_integer().
+-type charlist() :: [unicode_char() | unicode_binary() | charlist()].
+-type chardata() :: charlist() | unicode_binary().
+-type external_unicode_binary() :: binary().
+-type external_chardata() :: external_charlist() | external_unicode_binary().
+-type external_charlist() :: [unicode_char() | external_unicode_binary()
+ | external_charlist()].
+-type latin1_binary() :: binary().
+-type latin1_char() :: byte().
+-type latin1_chardata() :: latin1_charlist() | latin1_binary().
+-type latin1_charlist() :: [latin1_char() | latin1_binary()
+ | latin1_charlist()].
+
+-spec characters_to_list(Data) -> Result when
+ Data :: latin1_chardata() | chardata() | external_chardata(),
+ Result :: list()
+ | {error, list(), RestData}
+ | {incomplete, list(), binary()},
+ RestData :: latin1_chardata() | chardata() | external_chardata().
characters_to_list(ML) ->
unicode:characters_to_list(ML,unicode).
@@ -51,7 +73,7 @@ characters_to_list_int(ML, Encoding) ->
_ ->
badarg
end,
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,_}|Rest]}} =
(catch erlang:error(new_stacktrace,
[ML,Encoding])),
erlang:raise(error,TheError,[{Mod,characters_to_list,L}|Rest])
@@ -69,6 +91,13 @@ do_characters_to_list(ML, Encoding) ->
end.
+-spec characters_to_binary(Data) -> Result when
+ Data :: latin1_chardata() | chardata() | external_chardata(),
+ Result :: binary()
+ | {error, binary(), RestData}
+ | {incomplete, binary(), binary()},
+ RestData :: latin1_chardata() | chardata() | external_chardata().
+
characters_to_binary(ML) ->
try
unicode:characters_to_binary(ML,unicode)
@@ -80,7 +109,7 @@ characters_to_binary(ML) ->
_ ->
badarg
end,
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,_}|Rest]}} =
(catch erlang:error(new_stacktrace,
[ML])),
erlang:raise(error,TheError,[{Mod,characters_to_binary,L}|Rest])
@@ -98,12 +127,21 @@ characters_to_binary_int(ML,InEncoding) ->
_ ->
badarg
end,
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,_}|Rest]}} =
(catch erlang:error(new_stacktrace,
[ML,InEncoding])),
erlang:raise(error,TheError,[{Mod,characters_to_binary,L}|Rest])
end.
+-spec characters_to_binary(Data, InEncoding, OutEncoding) -> Result when
+ Data :: latin1_chardata() | chardata() | external_chardata(),
+ InEncoding :: encoding(),
+ OutEncoding :: encoding(),
+ Result :: binary()
+ | {error, binary(), RestData}
+ | {incomplete, binary(), binary()},
+ RestData :: latin1_chardata() | chardata() | external_chardata().
+
characters_to_binary(ML, latin1, latin1) when is_binary(ML) ->
ML;
characters_to_binary(ML, latin1, Uni) when is_binary(ML) and ((Uni =:= utf8) or (Uni =:= unicode)) ->
@@ -121,7 +159,7 @@ characters_to_binary(ML, latin1, Uni) when is_binary(ML) and ((Uni =:= utf8) or
_ ->
badarg
end,
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,_}|Rest]}} =
(catch erlang:error(new_stacktrace,
[ML,latin1,Uni])),
erlang:raise(error,TheError,
@@ -143,7 +181,7 @@ characters_to_binary(ML,Uni,latin1) when is_binary(ML) and ((Uni =:= utf8) or
_ ->
badarg
end,
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,_}|Rest]}} =
(catch erlang:error(new_stacktrace,
[ML,Uni,latin1])),
erlang:raise(error,TheError,
@@ -162,7 +200,7 @@ characters_to_binary(ML, InEncoding, OutEncoding) ->
_ ->
badarg
end,
- {'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
+ {'EXIT',{new_stacktrace,[{Mod,_,L,_}|Rest]}} =
(catch erlang:error(new_stacktrace,
[ML,InEncoding,OutEncoding])),
erlang:raise(error,TheError,[{Mod,characters_to_binary,L}|Rest])
@@ -215,6 +253,13 @@ characters_to_binary_int(ML, InEncoding, OutEncoding) ->
Res
end.
+-spec bom_to_encoding(Bin) -> {Encoding, Length} when
+ Bin :: binary(),
+ Encoding :: 'latin1' | 'utf8'
+ | {'utf16', endian()}
+ | {'utf32', endian()},
+ Length :: non_neg_integer().
+
bom_to_encoding(<<239,187,191,_/binary>>) ->
{utf8,3};
bom_to_encoding(<<0,0,254,255,_/binary>>) ->
@@ -228,6 +273,10 @@ bom_to_encoding(<<255,254,_/binary>>) ->
bom_to_encoding(Bin) when is_binary(Bin) ->
{latin1,0}.
+-spec encoding_to_bom(InEncoding) -> Bin when
+ Bin :: binary(),
+ InEncoding :: encoding().
+
encoding_to_bom(unicode) ->
<<239,187,191>>;
encoding_to_bom(utf8) ->
diff --git a/lib/stdlib/src/win32reg.erl b/lib/stdlib/src/win32reg.erl
index ee0d17bc94..598e77ffdc 100644
--- a/lib/stdlib/src/win32reg.erl
+++ b/lib/stdlib/src/win32reg.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -52,14 +52,17 @@
-define(reg_dword, 4).
%% Basic types internal to this file.
--type open_mode() :: 'read' | 'write'.
--type reg_handle() :: {'win32reg',port()}.
+-opaque reg_handle() :: {'win32reg',port()}.
-type name() :: string() | 'default'.
-type value() :: string() | integer() | binary().
%%% Exported functions.
--spec open([open_mode()]) -> {'ok', reg_handle()} | {'error', 'enotsup'}.
+-spec open(OpenModeList) -> ReturnValue when
+ OpenModeList :: [OpenMode],
+ OpenMode :: 'read' | 'write',
+ ReturnValue :: {'ok', RegHandle} | {'error', ErrorId :: 'enotsup'},
+ RegHandle :: reg_handle().
open(Modes) ->
case os:type() of
@@ -75,14 +78,17 @@ open(Modes) ->
{error, enotsup}
end.
--spec close(reg_handle()) -> 'ok'.
+-spec close(RegHandle) -> 'ok' when
+ RegHandle :: reg_handle().
close({win32reg, Reg}) when is_port(Reg) ->
unlink(Reg),
exit(Reg, die),
ok.
--spec current_key(reg_handle()) -> {'ok', string()}.
+-spec current_key(RegHandle) -> ReturnValue when
+ RegHandle :: reg_handle(),
+ ReturnValue :: {'ok', string()}.
current_key({win32reg, Reg}) when is_port(Reg) ->
Cmd = [?cmd_get_current],
@@ -94,12 +100,18 @@ current_key({win32reg, Reg}) when is_port(Reg) ->
_ -> Root ++ [$\\|Name]
end}.
--spec change_key(reg_handle(), string()) -> 'ok' | {'error', atom()}.
+-spec change_key(RegHandle, Key) -> ReturnValue when
+ RegHandle :: reg_handle(),
+ Key :: string(),
+ ReturnValue :: 'ok' | {'error', ErrorId :: atom()}.
change_key({win32reg, Reg}, Key) when is_port(Reg) ->
change_key(Reg, ?cmd_open_key, Key).
--spec change_key_create(reg_handle(), string()) -> 'ok' | {'error', atom()}.
+-spec change_key_create(RegHandle, Key) -> ReturnValue when
+ RegHandle :: reg_handle(),
+ Key :: string(),
+ ReturnValue :: 'ok' | {'error', ErrorId :: atom()}.
change_key_create({win32reg, Reg}, Key) when is_port(Reg) ->
change_key(Reg, ?cmd_create_key, Key).
@@ -113,21 +125,30 @@ change_key(Reg, Cmd, Key) ->
{error, Reason}
end.
--spec sub_keys(reg_handle()) -> {'ok', [string()]} | {'error', atom()}.
+-spec sub_keys(RegHandle) -> ReturnValue when
+ RegHandle :: reg_handle(),
+ ReturnValue :: {'ok', [SubKey]} | {'error', ErrorId :: atom()},
+ SubKey :: string().
sub_keys({win32reg, Reg}) when is_port(Reg) ->
Cmd = [?cmd_get_all_subkeys],
Reg ! {self(), {command, Cmd}},
collect_keys(Reg, []).
--spec delete_key(reg_handle()) -> 'ok' | {'error', atom()}.
+-spec delete_key(RegHandle) -> ReturnValue when
+ RegHandle :: reg_handle(),
+ ReturnValue :: 'ok' | {'error', ErrorId :: atom()}.
delete_key({win32reg, Reg}) when is_port(Reg) ->
Cmd = [?cmd_delete_key],
Reg ! {self(), {command, Cmd}},
get_result(Reg).
--spec set_value(reg_handle(), name(), value()) -> 'ok' | {'error', atom()}.
+-spec set_value(RegHandle, Name, Value) -> ReturnValue when
+ RegHandle :: reg_handle(),
+ Name :: name(),
+ Value :: value(),
+ ReturnValue :: 'ok' | {'error', ErrorId :: atom()}.
set_value({win32reg, Reg}, Name0, Value) when is_port(Reg) ->
Name =
@@ -140,7 +161,10 @@ set_value({win32reg, Reg}, Name0, Value) when is_port(Reg) ->
Reg ! {self(), {command, Cmd}},
get_result(Reg).
--spec value(reg_handle(), name()) -> {'ok', value()} | {'error', atom()}.
+-spec value(RegHandle, Name) -> ReturnValue when
+ RegHandle :: reg_handle(),
+ Name :: name(),
+ ReturnValue :: {'ok', Value :: value()} | {'error', ErrorId :: atom()}.
value({win32reg, Reg}, Name) when is_port(Reg) ->
Cmd = [?cmd_get_value, Name, 0],
@@ -152,14 +176,20 @@ value({win32reg, Reg}, Name) when is_port(Reg) ->
{error, Reason}
end.
--spec values(reg_handle()) -> {'ok', [{name(), value()}]} | {'error', atom()}.
+-spec values(RegHandle) -> ReturnValue when
+ RegHandle :: reg_handle(),
+ ReturnValue :: {'ok', [ValuePair]} | {'error', ErrorId :: atom()},
+ ValuePair :: {Name :: name(), Value :: value()}.
values({win32reg, Reg}) when is_port(Reg) ->
Cmd = [?cmd_get_all_values],
Reg ! {self(), {command, Cmd}},
collect_values(Reg, []).
--spec delete_value(reg_handle(), name()) -> 'ok' | {'error', atom()}.
+-spec delete_value(RegHandle, Name) -> ReturnValue when
+ RegHandle :: reg_handle(),
+ Name :: name(),
+ ReturnValue :: 'ok' | {'error', ErrorId :: atom()}.
delete_value({win32reg, Reg}, Name0) when is_port(Reg) ->
Name =
@@ -171,7 +201,9 @@ delete_value({win32reg, Reg}, Name0) when is_port(Reg) ->
Reg ! {self(), {command, Cmd}},
get_result(Reg).
--spec expand(string()) -> string().
+-spec expand(String) -> ExpandedString when
+ String :: string(),
+ ExpandedString :: string().
expand(Value) ->
expand(Value, [], []).
@@ -195,7 +227,9 @@ expand([C|Rest], Env, Result) ->
expand([], [], Result) ->
lists:reverse(Result).
--spec format_error(atom()) -> string().
+-spec format_error(ErrorId) -> ErrorString when
+ ErrorId :: atom(),
+ ErrorString :: string().
format_error(ErrorId) ->
erl_posix_msg:message(ErrorId).
@@ -203,7 +237,7 @@ format_error(ErrorId) ->
%%% Implementation.
-spec collect_values(port(), [{name(), value()}]) ->
- {'ok', [{name(), value()}]} | {'error', atom()}.
+ {'ok', [{name(), value()}]} | {'error', ErrorId :: atom()}.
collect_values(P, Result) ->
case get_result(P) of
@@ -215,7 +249,7 @@ collect_values(P, Result) ->
{error, Reason}
end.
--spec collect_keys(port(), string()) -> {'ok', [string()]} | {'error', atom()}.
+-spec collect_keys(port(), string()) -> {'ok', [string()]} | {'error', ErrorId :: atom()}.
collect_keys(P, Result) ->
case get_result(P) of
diff --git a/lib/stdlib/src/zip.erl b/lib/stdlib/src/zip.erl
index d41aeefa59..c82c8159b6 100644
--- a/lib/stdlib/src/zip.erl
+++ b/lib/stdlib/src/zip.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -203,6 +203,9 @@
zip_comment_length}).
+-type zip_file() :: #zip_file{}.
+-type zip_comment() :: #zip_comment{}.
+
%% Open a zip archive with options
%%
@@ -220,7 +223,7 @@ openzip_open(F, Options) ->
do_openzip_open(F, Options) ->
Opts = get_openzip_options(Options),
#openzip_opts{output = Output, open_opts = OpO, cwd = CWD} = Opts,
- Input = get_zip_input(F),
+ Input = get_input(F),
In0 = Input({open, F, OpO -- [write]}, []),
{[#zip_comment{comment = C} | Files], In1} =
get_central_dir(In0, fun raw_file_info_etc/5, Input),
@@ -323,8 +326,33 @@ openzip_close(_) ->
%% Accepted options:
%% verbose, cooked, file_list, keep_old_files, file_filter, memory
+-spec(unzip(Archive) -> RetValue when
+ Archive :: file:name() | binary(),
+ RetValue :: {ok, FileList}
+ | {ok, FileBinList}
+ | {error, Reason :: term()}
+ | {error, {Name :: file:name(), Reason :: term()}},
+ FileList :: [file:name()],
+ FileBinList :: [{file:name(),binary()}]).
+
unzip(F) -> unzip(F, []).
+-spec(unzip(Archive, Options) -> RetValue when
+ Archive :: file:name() | binary(),
+ Options :: [Option],
+ Option :: {file_list, FileList}
+ | keep_old_files | verbose | memory |
+ {file_filter, FileFilter} | {cwd, CWD},
+ FileList :: [file:name()],
+ FileBinList :: [{file:name(),binary()}],
+ FileFilter :: fun((ZipFile) -> boolean()),
+ CWD :: string(),
+ ZipFile :: zip_file(),
+ RetValue :: {ok, FileList}
+ | {ok, FileBinList}
+ | {error, Reason :: term()}
+ | {error, {Name :: file:name(), Reason :: term()}}).
+
unzip(F, Options) ->
case ?CATCH do_unzip(F, Options) of
{ok, R} -> {ok, R};
@@ -345,6 +373,18 @@ do_unzip(F, Options) ->
{ok, Files}.
%% Iterate over all files in a zip archive
+-spec(foldl(Fun, Acc0, Archive) -> {ok, Acc1} | {error, Reason} when
+ Fun :: fun((FileInArchive, GetInfo, GetBin, AccIn) -> AccOut),
+ FileInArchive :: file:name(),
+ GetInfo :: fun(() -> file:file_info()),
+ GetBin :: fun(() -> binary()),
+ Acc0 :: term(),
+ Acc1 :: term(),
+ AccIn :: term(),
+ AccOut :: term(),
+ Archive :: file:name() | {file:name(), binary()},
+ Reason :: term()).
+
foldl(Fun, Acc0, Archive) when is_function(Fun, 4) ->
ZipFun =
fun({Name, GetInfo, GetBin}, A) ->
@@ -368,8 +408,33 @@ foldl(_,_, _) ->
%% Accepted options:
%% verbose, cooked, memory, comment
+-spec(zip(Name, FileList) -> RetValue when
+ Name :: file:name(),
+ FileList :: [FileSpec],
+ FileSpec :: file:name() | {file:name(), binary()}
+ | {file:name(), binary(), file:file_info()},
+ RetValue :: {ok, FileName :: file:name()}
+ | {ok, {FileName :: file:name(), binary()}}
+ | {error, Reason :: term()}).
+
zip(F, Files) -> zip(F, Files, []).
+-spec(zip(Name, FileList, Options) -> RetValue when
+ Name :: file:name(),
+ FileList :: [FileSpec],
+ FileSpec :: file:name() | {file:name(), binary()}
+ | {file:name(), binary(), file:file_info()},
+ Options :: [Option],
+ Option :: memory | cooked | verbose | {comment, Comment}
+ | {cwd, CWD} | {compress, What} | {uncompress, What},
+ What :: all | [Extension] | {add, [Extension]} | {del, [Extension]},
+ Extension :: string(),
+ Comment :: string(),
+ CWD :: string(),
+ RetValue :: {ok, FileName :: file:name()}
+ | {ok, {FileName :: file:name(), binary()}}
+ | {error, Reason :: term()}).
+
zip(F, Files, Options) ->
case ?CATCH do_zip(F, Files, Options) of
{ok, R} -> {ok, R};
@@ -392,8 +457,20 @@ do_zip(F, Files, Options) ->
%% Accepted options:
%% cooked, file_filter, file_output (latter 2 undocumented)
+-spec(list_dir(Archive) -> RetValue when
+ Archive :: file:name() | binary(),
+ RetValue :: {ok, CommentAndFiles} | {error, Reason :: term()},
+ CommentAndFiles :: [zip_comment() | zip_file()]).
+
list_dir(F) -> list_dir(F, []).
+-spec(list_dir(Archive, Options) -> RetValue when
+ Archive :: file:name() | binary(),
+ RetValue :: {ok, CommentAndFiles} | {error, Reason :: term()},
+ CommentAndFiles :: [zip_comment() | zip_file()],
+ Options :: [Option],
+ Option :: cooked).
+
list_dir(F, Options) ->
case ?CATCH do_list_dir(F, Options) of
{ok, R} -> {ok, R};
@@ -411,6 +488,10 @@ do_list_dir(F, Options) ->
%% Print zip directory in short form
+-spec(t(Archive) -> ok when
+ Archive :: file:name() | binary() | ZipHandle,
+ ZipHandle :: pid()).
+
t(F) when is_pid(F) -> zip_t(F);
t(F) when is_record(F, openzip) -> openzip_t(F);
t(F) -> t(F, fun raw_short_print_info_etc/5).
@@ -431,6 +512,10 @@ do_t(F, RawPrint) ->
%% Print zip directory in long form (like ls -l)
+-spec(tt(Archive) -> ok when
+ Archive :: file:name() | binary() | ZipHandle,
+ ZipHandle :: pid()).
+
tt(F) when is_pid(F) -> zip_tt(F);
tt(F) when is_record(F, openzip) -> openzip_tt(F);
tt(F) -> t(F, fun raw_long_print_info_etc/5).
@@ -605,11 +690,78 @@ get_list_dir_options(F, Options) ->
get_list_dir_opt(Options, Opts).
%% aliases for erl_tar compatibility
+-spec(table(Archive) -> RetValue when
+ Archive :: file:name() | binary(),
+ RetValue :: {ok, CommentAndFiles} | {error, Reason :: term()},
+ CommentAndFiles :: [zip_comment() | zip_file()]).
+
table(F) -> list_dir(F).
+
+-spec(table(Archive, Options) -> RetValue when
+ Archive :: file:name() | binary(),
+ RetValue :: {ok, CommentAndFiles} | {error, Reason :: term()},
+ CommentAndFiles :: [zip_comment() | zip_file()],
+
+ Options :: [Option],
+ Option :: cooked).
+
table(F, O) -> list_dir(F, O).
+
+-spec(create(Name, FileList) -> RetValue when
+ Name :: file:name(),
+ FileList :: [FileSpec],
+ FileSpec :: file:name() | {file:name(), binary()}
+ | {file:name(), binary(), file:file_info()},
+ RetValue :: {ok, FileName :: file:name()}
+ | {ok, {FileName :: file:name(), binary()}}
+ | {error, Reason :: term()}).
+
create(F, Fs) -> zip(F, Fs).
+
+-spec(create(Name, FileList, Options) -> RetValue when
+ Name :: file:name(),
+ FileList :: [FileSpec],
+ FileSpec :: file:name() | {file:name(), binary()}
+ | {file:name(), binary(), file:file_info()},
+ Options :: [Option],
+ Option :: memory | cooked | verbose | {comment, Comment}
+ | {cwd, CWD} | {compress, What} | {uncompress, What},
+ What :: all | [Extension] | {add, [Extension]} | {del, [Extension]},
+ Extension :: string(),
+ Comment :: string(),
+ CWD :: string(),
+ RetValue :: {ok, FileName :: file:name()}
+ | {ok, {FileName :: file:name(), binary()}}
+ | {error, Reason :: term()}).
create(F, Fs, O) -> zip(F, Fs, O).
+
+-spec(extract(Archive) -> RetValue when
+ Archive :: file:name() | binary(),
+ RetValue :: {ok, FileList}
+ | {ok, FileBinList}
+ | {error, Reason :: term()}
+ | {error, {Name :: file:name(), Reason :: term()}},
+ FileList :: [file:name()],
+ FileBinList :: [{file:name(),binary()}]).
+
extract(F) -> unzip(F).
+
+-spec(extract(Archive, Options) -> RetValue when
+ Archive :: file:name() | binary(),
+ Options :: [Option],
+ Option :: {file_list, FileList}
+ | keep_old_files | verbose | memory |
+ {file_filter, FileFilter} | {cwd, CWD},
+ FileList :: [file:name()],
+ FileBinList :: [{file:name(),binary()}],
+ FileFilter :: fun((ZipFile) -> boolean()),
+ CWD :: string(),
+ ZipFile :: zip_file(),
+ RetValue :: {ok, FileList}
+ | {ok, FileBinList}
+ | {error, Reason :: term()}
+ | {error, {Name :: file:name(), Reason :: term()}}).
+
extract(F, O) -> unzip(F, O).
@@ -990,21 +1142,52 @@ server_loop(OpenZip) ->
{error, bad_msg}
end.
+-spec(zip_open(Archive) -> {ok, ZipHandle} | {error, Reason} when
+ Archive :: file:name() | binary(),
+ ZipHandle :: pid(),
+ Reason :: term()).
+
zip_open(Archive) -> zip_open(Archive, []).
+-spec(zip_open(Archive, Options) -> {ok, ZipHandle} | {error, Reason} when
+ Archive :: file:name() | binary(),
+ ZipHandle :: pid(),
+ Options :: [Option],
+ Option :: cooked | memory | {cwd, CWD :: string()},
+ Reason :: term()).
+
zip_open(Archive, Options) ->
Pid = spawn(fun() -> server_loop(not_open) end),
request(self(), Pid, {open, Archive, Options}).
+-spec(zip_get(ZipHandle) -> {ok, [Result]} | {error, Reason} when
+ ZipHandle :: pid(),
+ Result :: file:name() | {file:name(), binary()},
+ Reason :: term()).
+
zip_get(Pid) when is_pid(Pid) ->
request(self(), Pid, get).
+-spec(zip_close(ZipHandle) -> ok | {error, einval} when
+ ZipHandle :: pid()).
+
zip_close(Pid) when is_pid(Pid) ->
request(self(), Pid, close).
+-spec(zip_get(FileName, ZipHandle) -> {ok, Result} | {error, Reason} when
+ FileName :: file:name(),
+ ZipHandle :: pid(),
+ Result :: file:name() | {file:name(), binary()},
+ Reason :: term()).
+
zip_get(FileName, Pid) when is_pid(Pid) ->
request(self(), Pid, {get, FileName}).
+-spec(zip_list_dir(ZipHandle) -> {ok, Result} | {error, Reason} when
+ Result :: [zip_comment() | zip_file()],
+ ZipHandle :: pid(),
+ Reason :: term()).
+
zip_list_dir(Pid) when is_pid(Pid) ->
request(self(), Pid, list_dir).
diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile
index 3dd0a91870..5502c69fa5 100644
--- a/lib/stdlib/test/Makefile
+++ b/lib/stdlib/test/Makefile
@@ -135,7 +135,7 @@ release_tests_spec: make_emakefile
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) stdlib.spec $(EMAKEFILE) \
$(ERL_FILES) $(COVERFILE) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/stdlib/test/beam_lib_SUITE.erl b/lib/stdlib/test/beam_lib_SUITE.erl
index 4ccc863795..5df19ca7f1 100644
--- a/lib/stdlib/test/beam_lib_SUITE.erl
+++ b/lib/stdlib/test/beam_lib_SUITE.erl
@@ -181,7 +181,8 @@ error(Conf) when is_list(Conf) ->
?line verify(not_a_beam_file, beam_lib:info(<<"short">>)),
?line {Binary1, _} = split_binary(Binary, byte_size(Binary)-10),
- ?line verify(chunk_too_big, beam_lib:chunks(Binary1, ["Abst"])),
+ LastChunk = last_chunk(Binary),
+ ?line verify(chunk_too_big, beam_lib:chunks(Binary1, [LastChunk])),
?line Chunks = chunk_info(Binary),
?line {value, {_, AbstractStart, _}} = lists:keysearch("Abst", 1, Chunks),
?line {Binary2, _} = split_binary(Binary, AbstractStart),
@@ -205,6 +206,12 @@ error(Conf) when is_list(Conf) ->
?line file:delete(ACopy),
ok.
+last_chunk(Bin) ->
+ L = beam_lib:info(Bin),
+ {chunks,Chunks} = lists:keyfind(chunks, 1, L),
+ {Last,_,_} = lists:last(Chunks),
+ Last.
+
do_error(BeamFile, ACopy) ->
% evil tests
?line Chunks = chunk_info(BeamFile),
@@ -242,8 +249,8 @@ cmp(doc) -> ["Compare contents of BEAM files and directories"];
cmp(Conf) when is_list(Conf) ->
?line PrivDir = ?privdir,
- ?line Dir1 = filename:join(PrivDir, dir1),
- ?line Dir2 = filename:join(PrivDir, dir2),
+ ?line Dir1 = filename:join(PrivDir, "dir1"),
+ ?line Dir2 = filename:join(PrivDir, "dir2"),
ok = file:make_dir(Dir1),
ok = file:make_dir(Dir2),
@@ -292,8 +299,8 @@ cmp_literals(doc) -> ["Compare contents of BEAM files having literals"];
cmp_literals(Conf) when is_list(Conf) ->
?line PrivDir = ?privdir,
- ?line Dir1 = filename:join(PrivDir, dir1),
- ?line Dir2 = filename:join(PrivDir, dir2),
+ ?line Dir1 = filename:join(PrivDir, "dir1"),
+ ?line Dir2 = filename:join(PrivDir, "dir2"),
ok = file:make_dir(Dir1),
ok = file:make_dir(Dir2),
@@ -330,6 +337,7 @@ strip(Conf) when is_list(Conf) ->
?line {Source2D1, BeamFile2D1} = make_beam(PrivDir, simple2, concat),
?line {Source3D1, BeamFile3D1} = make_beam(PrivDir, make_fun, make_fun),
?line {Source4D1, BeamFile4D1} = make_beam(PrivDir, constant, constant),
+ ?line {Source5D1, BeamFile5D1} = make_beam(PrivDir, lines, lines),
?line NoOfTables = length(ets:all()),
?line P0 = pps(),
@@ -360,13 +368,25 @@ strip(Conf) when is_list(Conf) ->
?line {module, make_fun} = code:load_abs(filename:rootname(BeamFile3D1)),
?line {module, constant} = code:load_abs(filename:rootname(BeamFile4D1)),
+ %% check that line number information is still present after stripping
+ ?line {module, lines} = code:load_abs(filename:rootname(BeamFile5D1)),
+ ?line {'EXIT',{badarith,[{lines,t,1,Info}|_]}} =
+ (catch lines:t(atom)),
+ ?line true = code:delete(lines),
+ ?line false = code:purge(lines),
+ ?line {ok, {lines,BeamFile5D1}} = beam_lib:strip(BeamFile5D1),
+ ?line {module, lines} = code:load_abs(filename:rootname(BeamFile5D1)),
+ ?line {'EXIT',{badarith,[{lines,t,1,Info}|_]}} =
+ (catch lines:t(atom)),
+
?line true = (P0 == pps()),
?line NoOfTables = length(ets:all()),
?line delete_files([SourceD1, BeamFileD1,
Source2D1, BeamFile2D1,
Source3D1, BeamFile3D1,
- Source4D1, BeamFile4D1]),
+ Source4D1, BeamFile4D1,
+ Source5D1, BeamFile5D1]),
ok.
@@ -381,7 +401,7 @@ otp_6711(Conf) when is_list(Conf) ->
(catch {a, beam_lib:strip_files([3])}),
?line PrivDir = ?privdir,
- ?line Dir = filename:join(PrivDir, dir),
+ ?line Dir = filename:join(PrivDir, "dir"),
?line Lib = filename:join(Dir, "lib"),
?line App = filename:join(Lib, "app"),
?line EBin = filename:join(App, "ebin"),
@@ -417,8 +437,8 @@ building(doc) -> "Testing building of BEAM files.";
building(Conf) when is_list(Conf) ->
?line PrivDir = ?privdir,
- ?line Dir1 = filename:join(PrivDir, b_dir1),
- ?line Dir2 = filename:join(PrivDir, b_dir2),
+ ?line Dir1 = filename:join(PrivDir, "b_dir1"),
+ ?line Dir2 = filename:join(PrivDir, "b_dir2"),
ok = file:make_dir(Dir1),
ok = file:make_dir(Dir2),
@@ -571,8 +591,18 @@ do_encrypted_abstr(Beam, Key) ->
?line {ok,{simple,[{"Abst",Abst}]}} = beam_lib:chunks(Beam, ["Abst"]),
?line {ok,cleared} = beam_lib:clear_crypto_key_fun(),
+
+ %% Try to force a stop/start race.
+ ?line start_stop_race(10000),
+
ok.
+start_stop_race(0) ->
+ ok;
+start_stop_race(N) ->
+ {error,_} = beam_lib:crypto_key_fun(bad_fun),
+ undefined = beam_lib:clear_crypto_key_fun(),
+ start_stop_race(N-1).
bad_fun(F) ->
{error,E} = beam_lib:crypto_key_fun(F),
@@ -688,7 +718,7 @@ chunk_info(File) ->
Chunks.
make_beam(Dir, Module, F) ->
- ?line FileBase = filename:join(Dir, Module),
+ ?line FileBase = filename:join(Dir, atom_to_list(Module)),
?line Source = FileBase ++ ".erl",
?line BeamFile = FileBase ++ ".beam",
?line simple_file(Source, Module, F),
@@ -773,6 +803,12 @@ simple_file(File, Module, constant2) ->
"t(A) -> "
" {a,b,[2,3],x,y}. "]),
ok = file:write_file(File, B);
+simple_file(File, Module, lines) ->
+ B = list_to_binary(["-module(", atom_to_list(Module), ").\n"
+ "-export([t/1]).\n"
+ "t(A) ->\n"
+ " A+1.\n"]),
+ ok = file:write_file(File, B);
simple_file(File, Module, F) ->
B = list_to_binary(["-module(", atom_to_list(Module), "). "
"-export([t/0]). "
diff --git a/lib/stdlib/test/dets_SUITE.erl b/lib/stdlib/test/dets_SUITE.erl
index 9fcc9e6aaf..63767aeda6 100644
--- a/lib/stdlib/test/dets_SUITE.erl
+++ b/lib/stdlib/test/dets_SUITE.erl
@@ -34,6 +34,8 @@
-define(datadir(Conf), ?config(data_dir, Conf)).
-endif.
+-compile(r13). % OTP-9607
+
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
not_run/1, newly_started/1, basic_v8/1, basic_v9/1,
@@ -53,7 +55,7 @@
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_8856/1, otp_8898/1, otp_8899/1, otp_8903/1,
- otp_8923/1]).
+ otp_8923/1, otp_9282/1, otp_9607/1]).
-export([dets_dirty_loop/0]).
@@ -112,7 +114,7 @@ all() ->
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_8856, otp_8898,
- otp_8899, otp_8903, otp_8923]
+ otp_8899, otp_8903, otp_8923, otp_9282, otp_9607]
end.
groups() ->
@@ -554,7 +556,11 @@ dets_dirty_loop() ->
{From, [write, Name, Value]} ->
Ret = dets:insert(Name, Value),
From ! {self(), Ret},
- dets_dirty_loop()
+ dets_dirty_loop();
+ {From, [close, Name]} ->
+ Ret = dets:close(Name),
+ From ! {self(), Ret},
+ dets_dirty_loop()
end.
@@ -1516,7 +1522,7 @@ repair(Config, V) ->
if
V =:= 8 ->
%% first estimated number of objects is wrong, repair once more
- ?line {ok, Fd} = file:open(Fname, read_write),
+ ?line {ok, Fd} = file:open(Fname, [read,write]),
NoPos = HeadSize - 8, % no_objects
?line file:pwrite(Fd, NoPos, <<0:32>>), % NoItems
ok = file:close(Fd),
@@ -1568,8 +1574,10 @@ repair(Config, V) ->
?line FileSize = dets:info(TabRef, memory),
?line ok = dets:close(TabRef),
crash(Fname, FileSize+20),
- ?line {error, {bad_freelists, Fname}} =
+ %% Used to return bad_freelists, but that changed in OTP-9622
+ ?line {ok, TabRef} =
dets:open_file(TabRef, [{file,Fname},{version,V}]),
+ ?line ok = dets:close(TabRef),
?line file:delete(Fname),
%% File not closed, opening with read and read_write access tried.
@@ -1857,9 +1865,9 @@ fixtable(Config, Version) when is_list(Config) ->
?line {ok, _} = dets:open_file(T, Args),
%% badarg
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} =
(catch dets:safe_fixtable(no_table,true)),
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[T,undefined]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,safe_fixtable,[T,undefined],_}|_]}} =
(catch dets:safe_fixtable(T,undefined)),
%% The table is not allowed to grow while the elements are inserted:
@@ -1940,21 +1948,21 @@ match(Config, Version) ->
%% match, badarg
MSpec = [{'_',[],['$_']}],
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} =
(catch dets:match(no_table, '_')),
- ?line {'EXIT', {badarg, [{dets,match,[T,'_',not_a_number]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,match,[T,'_',not_a_number],_}|_]}} =
(catch dets:match(T, '_', not_a_number)),
?line {EC1, _} = dets:select(T, MSpec, 1),
- ?line {'EXIT', {badarg, [{dets,match,[EC1]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,match,[EC1],_}|_]}} =
(catch dets:match(EC1)),
%% match_object, badarg
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} =
(catch dets:match_object(no_table, '_')),
- ?line {'EXIT', {badarg, [{dets,match_object,[T,'_',not_a_number]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,match_object,[T,'_',not_a_number],_}|_]}} =
(catch dets:match_object(T, '_', not_a_number)),
?line {EC2, _} = dets:select(T, MSpec, 1),
- ?line {'EXIT', {badarg, [{dets,match_object,[EC2]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,match_object,[EC2],_}|_]}} =
(catch dets:match_object(EC2)),
dets:safe_fixtable(T, true),
@@ -2118,16 +2126,16 @@ select(Config, Version) ->
%% badarg
MSpec = [{'_',[],['$_']}],
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} =
(catch dets:select(no_table, MSpec)),
- ?line {'EXIT', {badarg, [{dets,select,[T,<<17>>]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,select,[T,<<17>>],_}|_]}} =
(catch dets:select(T, <<17>>)),
- ?line {'EXIT', {badarg, [{dets,select,[T,[]]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,select,[T,[]],_}|_]}} =
(catch dets:select(T, [])),
- ?line {'EXIT', {badarg, [{dets,select,[T,MSpec,not_a_number]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,select,[T,MSpec,not_a_number],_}|_]}} =
(catch dets:select(T, MSpec, not_a_number)),
?line {EC, _} = dets:match(T, '_', 1),
- ?line {'EXIT', {badarg, [{dets,select,[EC]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,select,[EC],_}|_]}} =
(catch dets:select(EC)),
AllSpec = [{'_',[],['$_']}],
@@ -2210,7 +2218,7 @@ update_counter(Config) when is_list(Config) ->
?line file:delete(Fname),
P0 = pps(),
- ?line {'EXIT', {badarg, [{dets,update_counter,[no_table,1,1]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,update_counter,[no_table,1,1],_}|_]}} =
(catch dets:update_counter(no_table, 1, 1)),
Args = [{file,Fname},{keypos,2}],
@@ -2254,65 +2262,66 @@ badarg(Config) when is_list(Config) ->
%% badargs are tested in match, select and fixtable too.
%% open
- ?line {'EXIT', {badarg, [{dets,open_file,[{a,tuple},[]]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,open_file,[{a,tuple},[]],_}|_]}} =
(catch dets:open_file({a,tuple},[])),
- ?line {'EXIT', {badarg, [{dets,open_file,[{a,tuple}]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,open_file,[{a,tuple}],_}|_]}} =
(catch dets:open_file({a,tuple})),
- ?line {'EXIT', {badarg, [{dets,open_file,[file,[foo]]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,open_file,[file,[foo]],_}|_]}} =
(catch dets:open_file(file,[foo])),
- ?line {'EXIT', {badarg,[{dets,open_file,[{hej,san},[{type,set}|3]]}|_]}} =
+ ?line {'EXIT', {badarg,[{dets,open_file,
+ [{hej,san},[{type,set}|3]],_}|_]}} =
(catch dets:open_file({hej,san},[{type,set}|3])),
%% insert
- ?line {'EXIT', {badarg, [{dets,insert,[no_table,{1,2}]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,insert,[no_table,{1,2}],_}|_]}} =
(catch dets:insert(no_table, {1,2})),
- ?line {'EXIT', {badarg, [{dets,insert,[no_table,[{1,2}]]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,insert,[no_table,[{1,2}]],_}|_]}} =
(catch dets:insert(no_table, [{1,2}])),
- ?line {'EXIT', {badarg, [{dets,insert,[T,{1,2}]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,insert,[T,{1,2}],_}|_]}} =
(catch dets:insert(T, {1,2})),
- ?line {'EXIT', {badarg, [{dets,insert,[T,[{1,2}]]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,insert,[T,[{1,2}]],_}|_]}} =
(catch dets:insert(T, [{1,2}])),
- ?line {'EXIT', {badarg, [{dets,insert,[T,[{1,2,3}|3]]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,insert,[T,[{1,2,3}|3]],_}|_]}} =
(catch dets:insert(T, [{1,2,3} | 3])),
%% lookup{_keys}
- ?line {'EXIT', {badarg, [{dets,lookup_keys,[badarg,[]]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,lookup_keys,[badarg,[]],_}|_]}} =
(catch dets:lookup_keys(T, [])),
- ?line {'EXIT', {badarg, [{dets,lookup,[no_table,1]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,lookup,[no_table,1],_}|_]}} =
(catch dets:lookup(no_table, 1)),
- ?line {'EXIT', {badarg, [{dets,lookup_keys,[T,[1|2]]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,lookup_keys,[T,[1|2]],_}|_]}} =
(catch dets:lookup_keys(T, [1 | 2])),
%% member
- ?line {'EXIT', {badarg, [{dets,member,[no_table,1]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,member,[no_table,1],_}|_]}} =
(catch dets:member(no_table, 1)),
%% sync
- ?line {'EXIT', {badarg, [{dets,sync,[no_table]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,sync,[no_table],_}|_]}} =
(catch dets:sync(no_table)),
%% delete{_keys}
- ?line {'EXIT', {badarg, [{dets,delete,[no_table,1]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,delete,[no_table,1],_}|_]}} =
(catch dets:delete(no_table, 1)),
%% delete_object
- ?line {'EXIT', {badarg, [{dets,delete_object,[no_table,{1,2,3}]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,delete_object,[no_table,{1,2,3}],_}|_]}} =
(catch dets:delete_object(no_table, {1,2,3})),
- ?line {'EXIT', {badarg, [{dets,delete_object,[T,{1,2}]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,delete_object,[T,{1,2}],_}|_]}} =
(catch dets:delete_object(T, {1,2})),
- ?line {'EXIT', {badarg, [{dets,delete_object,[no_table,[{1,2,3}]]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,delete_object,[no_table,[{1,2,3}]],_}|_]}} =
(catch dets:delete_object(no_table, [{1,2,3}])),
- ?line {'EXIT', {badarg, [{dets,delete_object,[T,[{1,2}]]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,delete_object,[T,[{1,2}]],_}|_]}} =
(catch dets:delete_object(T, [{1,2}])),
- ?line {'EXIT', {badarg, [{dets,delete_object,[T,[{1,2,3}|3]]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,delete_object,[T,[{1,2,3}|3]],_}|_]}} =
(catch dets:delete_object(T, [{1,2,3} | 3])),
%% first,next,slot
- ?line {'EXIT', {badarg, [{dets,first,[no_table]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,first,[no_table],_}|_]}} =
(catch dets:first(no_table)),
- ?line {'EXIT', {badarg, [{dets,next,[no_table,1]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,next,[no_table,1],_}|_]}} =
(catch dets:next(no_table, 1)),
- ?line {'EXIT', {badarg, [{dets,slot,[no_table,0]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,slot,[no_table,0],_}|_]}} =
(catch dets:slot(no_table, 0)),
%% info
@@ -2321,26 +2330,26 @@ badarg(Config) when is_list(Config) ->
?line undefined = dets:info(T, foo),
%% match_delete
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} =
(catch dets:match_delete(no_table, '_')),
%% delete_all_objects
- ?line {'EXIT', {badarg, [{dets,delete_all_objects,[no_table]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,delete_all_objects,[no_table],_}|_]}} =
(catch dets:delete_all_objects(no_table)),
%% select_delete
MSpec = [{'_',[],['$_']}],
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} =
(catch dets:select_delete(no_table, MSpec)),
- ?line {'EXIT', {badarg, [{dets,select_delete,[T, <<17>>]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,select_delete,[T, <<17>>],_}|_]}} =
(catch dets:select_delete(T, <<17>>)),
%% traverse, fold
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} =
(catch dets:traverse(no_table, fun(_) -> continue end)),
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} =
(catch dets:foldl(fun(_, A) -> A end, [], no_table)),
- ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true]}|_]}} =
+ ?line {'EXIT', {badarg, [{dets,safe_fixtable,[no_table,true],_}|_]}} =
(catch dets:foldr(fun(_, A) -> A end, [], no_table)),
%% close
@@ -2349,14 +2358,14 @@ badarg(Config) when is_list(Config) ->
?line {error, not_owner} = dets:close(T),
%% init_table
- ?line {'EXIT', {badarg,[{dets,init_table,[no_table,_,[]]}|_]}} =
+ ?line {'EXIT', {badarg,[{dets,init_table,[no_table,_,[]],_}|_]}} =
(catch dets:init_table(no_table, fun(X) -> X end)),
- ?line {'EXIT', {badarg,[{dets,init_table,[no_table,_,[]]}|_]}} =
+ ?line {'EXIT', {badarg,[{dets,init_table,[no_table,_,[]],_}|_]}} =
(catch dets:init_table(no_table, fun(X) -> X end, [])),
%% from_ets
Ets = ets:new(ets,[]),
- ?line {'EXIT', {badarg,[{dets,from_ets,[no_table,_]}|_]}} =
+ ?line {'EXIT', {badarg,[{dets,from_ets,[no_table,_],_}|_]}} =
(catch dets:from_ets(no_table, Ets)),
ets:delete(Ets),
@@ -3247,7 +3256,7 @@ otp_5402(suite) ->
[];
otp_5402(Config) when is_list(Config) ->
Tab = otp_5402,
- ?line File = filename:join([cannot, write, this, file]),
+ ?line File = filename:join(["cannot", "write", "this", "file"]),
%% close
?line{ok, T} = dets:open_file(Tab, [{ram_file,true},
@@ -3857,15 +3866,118 @@ otp_8923(Config) when is_list(Config) ->
file:delete(File),
ok.
+otp_9282(doc) ->
+ ["OTP-9282. The name of a table can be an arbitrary term"];
+otp_9282(suite) ->
+ [];
+otp_9282(Config) when is_list(Config) ->
+ some_calls(make_ref(), Config),
+ some_calls({a,typical,name}, Config),
+ some_calls(fun() -> a_funny_name end, Config),
+ ok.
+
+some_calls(Tab, Config) ->
+ File = filename(ref, Config),
+ ?line {ok,T} = dets:open_file(Tab, [{file,File}]),
+ ?line T = Tab,
+ ?line false = dets:info(T, safe_fixed),
+ ?line File = dets:info(T, filename),
+ ?line ok = dets:insert(Tab, [{3,0}]),
+ ?line [{3,0}] = dets:lookup(Tab, 3),
+ ?line [{3,0}] = dets:traverse(Tab, fun(X) -> {continue, X} end),
+ ?line ok = dets:close(T),
+ file:delete(File).
+
+otp_9607(doc) ->
+ ["OTP-9607. Test downgrading the slightly changed format."];
+otp_9607(suite) ->
+ [];
+otp_9607(Config) when is_list(Config) ->
+ %% Note: the bug is about almost full tables. The fix of that
+ %% problem is *not* tested here.
+ Version = r13b,
+ case ?t:is_release_available(atom_to_list(Version)) of
+ true ->
+ T = otp_9607,
+ File = filename(T, Config),
+ Key = a,
+ Value = 1,
+ Args = [{file,File}],
+ ?line {ok, T} = dets:open_file(T, Args),
+ ?line ok = dets:insert(T, {Key, Value}),
+ ?line ok = dets:close(T),
+
+ ?line Call = fun(P, A) ->
+ P ! {self(), A},
+ receive
+ {P, Ans} ->
+ Ans
+ after 5000 ->
+ exit(other_process_dead)
+ end
+ end,
+ %% Create a file on the modified format, read the file
+ %% with an emulator that doesn't know about the modified
+ %% format.
+ ?line {ok, Node} = start_node_rel(Version, Version, slave),
+ ?line Pid = rpc:call(Node, erlang, spawn,
+ [?MODULE, dets_dirty_loop, []]),
+ ?line {error,{needs_repair, File}} =
+ Call(Pid, [open, T, Args++[{repair,false}]]),
+ io:format("Expect repair:~n"),
+ ?line {ok, T} = Call(Pid, [open, T, Args]),
+ ?line [{Key,Value}] = Call(Pid, [read, T, Key]),
+ ?line ok = Call(Pid, [close, T]),
+ file:delete(File),
+
+ %% Create a file on the unmodified format. Modify the file
+ %% using an emulator that must not turn the file into the
+ %% modified format. Read the file and make sure it is not
+ %% repaired.
+ ?line {ok, T} = Call(Pid, [open, T, Args]),
+ ?line ok = Call(Pid, [write, T, {Key,Value}]),
+ ?line [{Key,Value}] = Call(Pid, [read, T, Key]),
+ ?line ok = Call(Pid, [close, T]),
+
+ Key2 = b,
+ Value2 = 2,
+
+ ?line {ok, T} = dets:open_file(T, Args),
+ ?line [{Key,Value}] = dets:lookup(T, Key),
+ ?line ok = dets:insert(T, {Key2,Value2}),
+ ?line ok = dets:close(T),
+
+ ?line {ok, T} = Call(Pid, [open, T, Args++[{repair,false}]]),
+ ?line [{Key2,Value2}] = Call(Pid, [read, T, Key2]),
+ ?line ok = Call(Pid, [close, T]),
+
+ ?t:stop_node(Node),
+ file:delete(File),
+ ok;
+ false ->
+ {skipped, "No support for old node"}
+ end.
+
+
+
%%
%% Parts common to several test cases
%%
+start_node_rel(Name, Rel, How) ->
+ Release = [{release, atom_to_list(Rel)}],
+ ?line Pa = filename:dirname(code:which(?MODULE)),
+ ?line test_server:start_node(Name, How,
+ [{args,
+ " -kernel net_setuptime 100 "
+ " -pa " ++ Pa},
+ {erl, Release}]).
+
crash(File, Where) ->
crash(File, Where, 10).
crash(File, Where, What) when is_integer(What) ->
- ?line {ok, Fd} = file:open(File, read_write),
+ ?line {ok, Fd} = file:open(File, [read,write]),
?line file:position(Fd, Where),
?line ok = file:write(Fd, [What]),
?line ok = file:close(Fd).
@@ -4009,7 +4121,7 @@ writable(Fname) ->
?line file:write_file_info(Fname, Info#file_info{mode = Mode}).
truncate(File, Where) ->
- ?line {ok, Fd} = file:open(File, read_write),
+ ?line {ok, Fd} = file:open(File, [read,write]),
?line file:position(Fd, Where),
?line ok = file:truncate(Fd),
?line ok = file:close(Fd).
diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl
index 9b024a5b49..57f3f4eddb 100644
--- a/lib/stdlib/test/epp_SUITE.erl
+++ b/lib/stdlib/test/epp_SUITE.erl
@@ -1280,7 +1280,7 @@ eval_tests(Config, Fun, Tests) ->
check_test(Config, Test) ->
- Filename = 'epp_test.erl',
+ Filename = "epp_test.erl",
?line PrivDir = ?config(priv_dir, Config),
?line File = filename:join(PrivDir, Filename),
?line ok = file:write_file(File, Test),
@@ -1293,7 +1293,7 @@ check_test(Config, Test) ->
compile_test(Config, Test0) ->
Test = [<<"-module(epp_test). -compile(export_all). ">>, Test0],
- Filename = 'epp_test.erl',
+ Filename = "epp_test.erl",
?line PrivDir = ?config(priv_dir, Config),
?line File = filename:join(PrivDir, Filename),
?line ok = file:write_file(File, Test),
diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl
index 4b59cee99e..784c7cb86e 100644
--- a/lib/stdlib/test/erl_eval_SUITE.erl
+++ b/lib/stdlib/test/erl_eval_SUITE.erl
@@ -1189,7 +1189,7 @@ 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()}),
+ {As,Bs} = erl_eval:expr_list(As0, Bs0, lfh()),
case erlang:function_exported(?MODULE, F, length(As)) of
true ->
{value,apply(?MODULE, F, As),Bs};
@@ -1199,7 +1199,7 @@ local_func(F, As0, Bs0) when is_atom(F) ->
lfh_value_extra() ->
%% Not documented.
- {value, fun(F, As) -> local_func_value(F, As) end, []}.
+ {value, fun(F, As, a1, a2) -> local_func_value(F, As) end, [a1, a2]}.
lfh_value() ->
{value, fun(F, As) -> local_func_value(F, As) end}.
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index f980d52e4e..9041adbe5c 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -2981,7 +2981,7 @@ run_test(Conf, Test0, Warnings0) ->
run_test2(Conf, Test, Warnings0).
run_test2(Conf, Test, Warnings0) ->
- Filename = 'lint_test.erl',
+ Filename = "lint_test.erl",
DataDir = ?privdir,
File = filename:join(DataDir, Filename),
Opts = case Warnings0 of
diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl
index bc811355ab..280c95b1aa 100644
--- a/lib/stdlib/test/erl_pp_SUITE.erl
+++ b/lib/stdlib/test/erl_pp_SUITE.erl
@@ -1161,7 +1161,7 @@ parse_forms2(String, Cont0, Line, Forms) ->
{done, {ok, Tokens, EndLine}, Chars} ->
{ok, Form} = erl_parse:parse_form(Tokens),
parse_forms2(Chars, [], EndLine, [Form | Forms]);
- {more, Cont} when element(3, Cont) =:= [] ->
+ {more, Cont} when element(4, Cont) =:= [] ->
%% extra spaces after forms...
parse_forms2([], Cont, Line, Forms);
{more, Cont} ->
diff --git a/lib/stdlib/test/erl_scan_SUITE.erl b/lib/stdlib/test/erl_scan_SUITE.erl
index 31a4f94294..4298b2c701 100644
--- a/lib/stdlib/test/erl_scan_SUITE.erl
+++ b/lib/stdlib/test/erl_scan_SUITE.erl
@@ -737,6 +737,10 @@ set_attribute() ->
(catch {foo, erl_scan:set_attribute(line, [], F2)}), % type error
?line {'EXIT',{badarg,_}} =
(catch {foo, erl_scan:set_attribute(column, [], F2)}), % type error
+
+ %% OTP-9412
+ ?line 8 = erl_scan:set_attribute(line, [{line,{nos,'X',8}}],
+ fun({nos,_V,VL}) -> VL end),
ok.
column_errors() ->
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index 9d348b5f1a..e048764a55 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -72,6 +72,7 @@
exit_many_many_tables_owner/1]).
-export([write_concurrency/1, heir/1, give_away/1, setopts/1]).
-export([bad_table/1, types/1]).
+-export([otp_9423/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
%% Convenience for manual testing
@@ -143,7 +144,8 @@ all() ->
otp_8166, exit_large_table_owner,
exit_many_large_table_owner, exit_many_tables_owner,
exit_many_many_tables_owner, write_concurrency, heir,
- give_away, setopts, bad_table, types].
+ give_away, setopts, bad_table, types,
+ otp_9423].
groups() ->
[{new, [],
@@ -793,16 +795,16 @@ t_ets_dets(Config, Opts) ->
?line true = ets:from_dets(ETab,DTab),
?line 3000 = ets:info(ETab,size),
?line ets:delete(ETab),
- ?line {'EXIT',{badarg,[{ets,to_dets,[ETab,DTab]}|_]}} =
+ ?line {'EXIT',{badarg,[{ets,to_dets,[ETab,DTab],_}|_]}} =
(catch ets:to_dets(ETab,DTab)),
- ?line {'EXIT',{badarg,[{ets,from_dets,[ETab,DTab]}|_]}} =
+ ?line {'EXIT',{badarg,[{ets,from_dets,[ETab,DTab],_}|_]}} =
(catch ets:from_dets(ETab,DTab)),
?line ETab2 = ets_new(x,Opts),
?line filltabint(ETab2,3000),
?line dets:close(DTab),
- ?line {'EXIT',{badarg,[{ets,to_dets,[ETab2,DTab]}|_]}} =
+ ?line {'EXIT',{badarg,[{ets,to_dets,[ETab2,DTab],_}|_]}} =
(catch ets:to_dets(ETab2,DTab)),
- ?line {'EXIT',{badarg,[{ets,from_dets,[ETab2,DTab]}|_]}} =
+ ?line {'EXIT',{badarg,[{ets,from_dets,[ETab2,DTab],_}|_]}} =
(catch ets:from_dets(ETab2,DTab)),
?line ets:delete(ETab2),
?line (catch file:delete(Fname)),
@@ -817,6 +819,14 @@ t_delete_all_objects(Config) when is_list(Config) ->
repeat_for_opts(t_delete_all_objects_do),
?line verify_etsmem(EtsMem).
+get_kept_objects(T) ->
+ case ets:info(T,stats) of
+ false ->
+ 0;
+ {_,_,_,_,_,_,KO} ->
+ KO
+ end.
+
t_delete_all_objects_do(Opts) ->
?line T=ets_new(x,Opts),
?line filltabint(T,4000),
@@ -826,10 +836,10 @@ t_delete_all_objects_do(Opts) ->
?line true = ets:delete_all_objects(T),
?line '$end_of_table' = ets:next(T,O),
?line 0 = ets:info(T,size),
- ?line 4000 = ets:info(T,kept_objects),
+ ?line 4000 = get_kept_objects(T),
?line ets:safe_fixtable(T,false),
?line 0 = ets:info(T,size),
- ?line 0 = ets:info(T,kept_objects),
+ ?line 0 = get_kept_objects(T),
?line filltabint(T,4000),
?line 4000 = ets:info(T,size),
?line true = ets:delete_all_objects(T),
@@ -859,10 +869,10 @@ t_delete_object_do(Opts) ->
?line ets:delete_object(T,{First, integer_to_list(First)}),
?line Next = ets:next(T,First),
?line 3999 = ets:info(T,size),
- ?line 1 = ets:info(T,kept_objects),
+ ?line 1 = get_kept_objects(T),
?line ets:safe_fixtable(T,false),
?line 3999 = ets:info(T,size),
- ?line 0 = ets:info(T,kept_objects),
+ ?line 0 = get_kept_objects(T),
?line ets:delete(T),
?line T1 = ets_new(x,[ordered_set | Opts]),
?line filltabint(T1,4000),
@@ -2642,7 +2652,7 @@ maybe_sort(L) when is_list(L) ->
%maybe_sort({'EXIT',{Reason, [{Module, Function, _}|_]}}) ->
% {'EXIT',{Reason, [{Module, Function, '_'}]}};
maybe_sort({'EXIT',{Reason, List}}) when is_list(List) ->
- {'EXIT',{Reason, lists:map(fun({Module, Function, _}) ->
+ {'EXIT',{Reason, lists:map(fun({Module, Function, _, _}) ->
{Module, Function, '_'}
end,
List)}};
@@ -2715,7 +2725,8 @@ ordered_do(Opts) ->
9,10,11,12,
1,2,3,4,
17,18,19,20,
- 13,14,15,16
+ 13,14,15,16,
+ 1 bsl 33
],
?line lists:foreach(fun(X) ->
ets:insert(T,{X,integer_to_list(X)})
@@ -2730,13 +2741,14 @@ ordered_do(Opts) ->
?line S2 = L2,
?line [{1,"1"}] = ets:slot(T,0),
?line [{28,"28"}] = ets:slot(T,27),
+ ?line [{1 bsl 33,_}] = ets:slot(T,28),
?line 27 = ets:prev(T,28),
?line [{7,"7"}] = ets:slot(T,6),
- ?line '$end_of_table' = ets:next(T,28),
+ ?line '$end_of_table' = ets:next(T,1 bsl 33),
?line [{12,"12"}] = ets:slot(T,11),
- ?line '$end_of_table' = ets:slot(T,28),
+ ?line '$end_of_table' = ets:slot(T,29),
?line [{1,"1"}] = ets:slot(T,0),
- ?line 28 = ets:prev(T,29),
+ ?line 28 = ets:prev(T,1 bsl 33),
?line 1 = ets:next(T,0),
?line pick_all_forward(T),
?line [{7,"7"}] = ets:slot(T,6),
@@ -4967,7 +4979,7 @@ grow_pseudo_deleted_do(Type) ->
[true]}]),
Left = Mult*(Mod-1),
?line Left = ets:info(T,size),
- ?line Mult = ets:info(T,kept_objects),
+ ?line Mult = get_kept_objects(T),
filltabstr(T,Mult),
spawn_opt(fun()-> ?line true = ets:info(T,fixed),
Self ! start,
@@ -4981,7 +4993,7 @@ grow_pseudo_deleted_do(Type) ->
?line true = ets:safe_fixtable(T,false),
io:format("Unfix table done. ~p nitems=~p\n",[now(),ets:info(T,size)]),
?line false = ets:info(T,fixed),
- ?line 0 = ets:info(T,kept_objects),
+ ?line 0 = get_kept_objects(T),
?line done = receive_any(),
%%verify_table_load(T), % may fail if concurrency is poor (genny)
ets:delete(T),
@@ -5008,7 +5020,7 @@ shrink_pseudo_deleted_do(Type) ->
[{'>', '$1', Half}],
[true]}]),
?line Half = ets:info(T,size),
- ?line Half = ets:info(T,kept_objects),
+ ?line Half = get_kept_objects(T),
spawn_opt(fun()-> ?line true = ets:info(T,fixed),
Self ! start,
io:format("Starting to delete... ~p\n",[now()]),
@@ -5021,7 +5033,7 @@ shrink_pseudo_deleted_do(Type) ->
?line true = ets:safe_fixtable(T,false),
io:format("Unfix table done. ~p nitems=~p\n",[now(),ets:info(T,size)]),
?line false = ets:info(T,fixed),
- ?line 0 = ets:info(T,kept_objects),
+ ?line 0 = get_kept_objects(T),
?line done = receive_any(),
%%verify_table_load(T), % may fail if concurrency is poor (genny)
ets:delete(T),
@@ -5137,7 +5149,7 @@ smp_fixed_delete_do() ->
?line 0 = ets:info(T,size),
?line true = ets:info(T,fixed),
?line Buckets = num_of_buckets(T),
- ?line NumOfObjs = ets:info(T,kept_objects),
+ ?line NumOfObjs = get_kept_objects(T),
ets:safe_fixtable(T,false),
%% Will fail as unfix does not shrink the table:
%%?line Mem = ets:info(T,memory),
@@ -5169,7 +5181,7 @@ smp_unfix_fix_do() ->
Left = NumOfObjs - Deleted,
?line Left = ets:info(T,size),
?line true = ets:info(T,fixed),
- ?line Deleted = ets:info(T,kept_objects),
+ ?line Deleted = get_kept_objects(T),
{Child, Mref} =
spawn_opt(fun()-> ?line true = ets:info(T,fixed),
@@ -5186,7 +5198,7 @@ smp_unfix_fix_do() ->
end,
Deleted),
?line 0 = ets:info(T,size),
- ?line true = ets:info(T,kept_objects) >= Left,
+ ?line true = get_kept_objects(T) >= Left,
?line done = receive_any()
end,
[link, monitor, {scheduler,2}]),
@@ -5199,7 +5211,7 @@ smp_unfix_fix_do() ->
Child ! done,
{'DOWN', Mref, process, Child, normal} = receive_any(),
?line false = ets:info(T,fixed),
- ?line 0 = ets:info(T,kept_objects),
+ ?line 0 = get_kept_objects(T),
%%verify_table_load(T),
ets:delete(T),
process_flag(scheduler,0).
@@ -5237,7 +5249,7 @@ otp_8166_do(WC) ->
ZombieCrPid ! quit,
{'DOWN', ZombieCrMref, process, ZombieCrPid, normal} = receive_any(),
?line false = ets:info(T,fixed),
- ?line 0 = ets:info(T,kept_objects),
+ ?line 0 = get_kept_objects(T),
%%verify_table_load(T),
ets:delete(T),
process_flag(scheduler,0).
@@ -5304,7 +5316,7 @@ otp_8166_zombie_creator(T,Deleted) ->
verify_table_load(T) ->
?line Stats = ets:info(T,stats),
- ?line {Buckets,AvgLen,StdDev,ExpSD,_MinLen,_MaxLen} = Stats,
+ ?line {Buckets,AvgLen,StdDev,ExpSD,_MinLen,_MaxLen,_} = Stats,
?line ok = if
AvgLen > 7 ->
io:format("Table overloaded: Stats=~p\n~p\n",
@@ -5420,7 +5432,39 @@ types_do(Opts) ->
?line verify_etsmem(EtsMem).
-
+otp_9423(doc) -> ["vm-deadlock caused by race between ets:delete and others on write_concurrency table"];
+otp_9423(Config) when is_list(Config) ->
+ InitF = fun(_) -> {0,0} end,
+ ExecF = fun({S,F}) ->
+ receive
+ stop ->
+ io:format("~p got stop\n", [self()]),
+ [end_of_work | {"Succeded=",S,"Failed=",F}]
+ after 0 ->
+ %%io:format("~p (~p) doing lookup\n", [self(), {S,F}]),
+ try ets:lookup(otp_9423, key) of
+ [] -> {S+1,F}
+ catch
+ error:badarg -> {S,F+1}
+ end
+ end
+ end,
+ FiniF = fun(R) -> R end,
+ case run_workers(InitF, ExecF, FiniF, infinite, 1) of
+ Pids when is_list(Pids) ->
+ %%[P ! start || P <- Pids],
+ repeat(fun() -> ets:new(otp_9423, [named_table, public, {write_concurrency,true}]),
+ ets:delete(otp_9423)
+ end, 10000),
+ [P ! stop || P <- Pids],
+ wait_pids(Pids),
+ ok;
+
+ Skipped -> Skipped
+ end.
+
+
+
%
% Utility functions:
@@ -5434,21 +5478,30 @@ add_lists([E1|T1], [E2|T2], Acc) ->
add_lists(T1, T2, [E1+E2 | Acc]).
run_workers(InitF,ExecF,FiniF,Laps) ->
+ run_workers(InitF,ExecF,FiniF,Laps, 0).
+run_workers(InitF,ExecF,FiniF,Laps, Exclude) ->
case erlang:system_info(smp_support) of
true ->
- run_workers_do(InitF,ExecF,FiniF,Laps);
+ run_workers_do(InitF,ExecF,FiniF,Laps, Exclude);
false ->
{skipped,"No smp support"}
end.
-
+
run_workers_do(InitF,ExecF,FiniF,Laps) ->
- NumOfProcs = erlang:system_info(schedulers),
+ run_workers_do(InitF,ExecF,FiniF,Laps, 0).
+run_workers_do(InitF,ExecF,FiniF,Laps, Exclude) ->
+ ?line NumOfProcs = case erlang:system_info(schedulers) of
+ N when (N > Exclude) -> N - Exclude
+ end,
io:format("smp starting ~p workers\n",[NumOfProcs]),
Seeds = [{ProcN,random:uniform(9999)} || ProcN <- lists:seq(1,NumOfProcs)],
Parent = self(),
Pids = [spawn_link(fun()-> worker(Seed,InitF,ExecF,FiniF,Laps,Parent,NumOfProcs) end)
|| Seed <- Seeds],
- wait_pids(Pids).
+ case Laps of
+ infinite -> Pids;
+ _ -> wait_pids(Pids)
+ end.
worker({ProcN,Seed}, InitF, ExecF, FiniF, Laps, Parent, NumOfProcs) ->
io:format("smp worker ~p, seed=~p~n",[self(),Seed]),
@@ -5463,6 +5516,8 @@ worker_loop(0, _, State) ->
State;
worker_loop(_, _, [end_of_work|State]) ->
State;
+worker_loop(infinite, ExecF, State) ->
+ worker_loop(infinite,ExecF,ExecF(State));
worker_loop(N, ExecF, State) ->
worker_loop(N-1,ExecF,ExecF(State)).
@@ -5517,20 +5572,21 @@ etsmem() ->
case erlang:system_info({allocator,ets_alloc}) of
false -> undefined;
MemInfo ->
- MSBCS = lists:foldl(
- fun ({instance, _, L}, Acc) ->
- {value,{_,MBCS}} = lists:keysearch(mbcs, 1, L),
- {value,{_,SBCS}} = lists:keysearch(sbcs, 1, L),
- [MBCS,SBCS | Acc]
- end,
- [],
- MemInfo),
+ CS = lists:foldl(
+ fun ({instance, _, L}, Acc) ->
+ {value,{_,SBMBCS}} = lists:keysearch(sbmbcs, 1, L),
+ {value,{_,MBCS}} = lists:keysearch(mbcs, 1, L),
+ {value,{_,SBCS}} = lists:keysearch(sbcs, 1, L),
+ [SBMBCS,MBCS,SBCS | Acc]
+ end,
+ [],
+ MemInfo),
lists:foldl(
fun(L, {Bl0,BlSz0}) ->
{value,{_,Bl,_,_}} = lists:keysearch(blocks, 1, L),
{value,{_,BlSz,_,_}} = lists:keysearch(blocks_size, 1, L),
{Bl0+Bl,BlSz0+BlSz}
- end, {0,0}, MSBCS)
+ end, {0,0}, CS)
end},
{Mem,AllTabs}.
@@ -5872,7 +5928,7 @@ very_big_num(0, Result) ->
?line Result.
make_port() ->
- ?line open_port({spawn, efile}, [eof]).
+ ?line open_port({spawn, "efile"}, [eof]).
make_pid() ->
?line spawn_link(?MODULE, sleeper, []).
diff --git a/lib/stdlib/test/file_sorter_SUITE.erl b/lib/stdlib/test/file_sorter_SUITE.erl
index 80d4ea5fdc..74c08912be 100644
--- a/lib/stdlib/test/file_sorter_SUITE.erl
+++ b/lib/stdlib/test/file_sorter_SUITE.erl
@@ -89,7 +89,7 @@ basic(suite) ->
basic(Config) when is_list(Config) ->
Fmt = binary,
Arg = {format,Fmt},
- Foo = outfile(foo, Config),
+ Foo = outfile("foo", Config),
P0 = pps(),
?line F1s = [F1] = to_files([[]], Fmt, Config),
@@ -455,7 +455,7 @@ inout(suite) ->
[];
inout(Config) when is_list(Config) ->
BTF = {format, binary_term},
- Foo = outfile(foo, Config),
+ Foo = outfile("foo", Config),
%% Input is fun.
End = fun(read) -> end_of_input end,
@@ -522,7 +522,7 @@ many(doc) ->
many(suite) ->
[];
many(Config) when is_list(Config) ->
- Foo = outfile(foo, Config),
+ Foo = outfile("foo", Config),
PrivDir = ?privdir(Config),
P0 = pps(),
@@ -587,7 +587,7 @@ misc(suite) ->
[];
misc(Config) when is_list(Config) ->
BTF = {format, binary_term},
- Foo = outfile(foo, Config),
+ Foo = outfile("foo", Config),
FFoo = filename:absname(Foo),
P0 = pps(),
@@ -704,7 +704,7 @@ misc(Config) when is_list(Config) ->
sort(Fmt, XArgs, Config) ->
Args = make_args(Fmt, [{size,5} | XArgs]),
TmpArgs = [{tmpdir,?privdir(Config)} | Args],
- Foo = outfile(foo, Config),
+ Foo = outfile("foo", Config),
%% Input is a fun. Output is a fun.
?line [] = file_sorter:sort(input([], 2, Fmt), output([], Fmt), Args),
@@ -777,7 +777,7 @@ sort(Fmt, XArgs, Config) ->
keysort(Fmt, XArgs, Config) ->
Args = make_args(Fmt, [{size,50}, {no_files, 2} | XArgs]),
TmpArgs = Args ++ [{tmpdir,?privdir(Config)}],
- Foo = outfile(foo, Config),
+ Foo = outfile("foo", Config),
%% Input is files. Output is a file.
?line ok = file_sorter:keysort(2, [], Foo, Args),
@@ -836,7 +836,7 @@ keysort(Fmt, XArgs, Config) ->
merge(Fmt, XArgs, Config) ->
Args = make_args(Fmt, [{size,5} | XArgs]),
- Foo = outfile(foo, Config),
+ Foo = outfile("foo", Config),
%% Input is a file. Output is a fun.
?line [] = file_sorter:merge([], output([], Fmt), Args),
@@ -873,7 +873,7 @@ merge(Fmt, XArgs, Config) ->
keymerge(Fmt, XArgs, Config) ->
Args = make_args(Fmt, [{size,50}, {no_files, 2} | XArgs]),
- Foo = outfile(foo, Config),
+ Foo = outfile("foo", Config),
%% Input is files. Output is a file.
?line ok = file_sorter:keymerge(2, [], Foo, Args),
diff --git a/lib/stdlib/test/filelib_SUITE.erl b/lib/stdlib/test/filelib_SUITE.erl
index a355097fe2..1de639a166 100644
--- a/lib/stdlib/test/filelib_SUITE.erl
+++ b/lib/stdlib/test/filelib_SUITE.erl
@@ -97,11 +97,12 @@ wildcard_errors(Config) when is_list(Config) ->
wcc(Wc, Error) ->
{'EXIT',{{badpattern,Error},
- [{filelib,compile_wildcard,1}|_]}} = (catch filelib:compile_wildcard(Wc)),
+ [{filelib,compile_wildcard,1,_}|_]}} =
+ (catch filelib:compile_wildcard(Wc)),
{'EXIT',{{badpattern,Error},
- [{filelib,wildcard,1}|_]}} = (catch filelib:wildcard(Wc)),
+ [{filelib,wildcard,1,_}|_]}} = (catch filelib:wildcard(Wc)),
{'EXIT',{{badpattern,Error},
- [{filelib,wildcard,2}|_]}} = (catch filelib:wildcard(Wc, ".")).
+ [{filelib,wildcard,2,_}|_]}} = (catch filelib:wildcard(Wc, ".")).
do_wildcard_1(Dir, Wcf0) ->
do_wildcard_2(Dir, Wcf0),
@@ -243,7 +244,7 @@ otp_5960(doc) ->
["Test that filelib:ensure_dir/1 returns ok or {error,Reason}"];
otp_5960(Config) when is_list(Config) ->
?line PrivDir = ?config(priv_dir, Config),
- ?line Dir = filename:join(PrivDir, otp_5960_dir),
+ ?line Dir = filename:join(PrivDir, "otp_5960_dir"),
?line Name1 = filename:join(Dir, name1),
?line Name2 = filename:join(Dir, name2),
?line ok = filelib:ensure_dir(Name1), % parent is created
@@ -268,7 +269,7 @@ otp_5960(Config) when is_list(Config) ->
ensure_dir_eexist(Config) when is_list(Config) ->
?line PrivDir = ?config(priv_dir, Config),
- ?line Dir = filename:join(PrivDir, ensure_dir_eexist),
+ ?line Dir = filename:join(PrivDir, "ensure_dir_eexist"),
?line Name = filename:join(Dir, "same_name_as_file_and_dir"),
?line ok = filelib:ensure_dir(Name),
?line ok = file:write_file(Name, <<"some string\n">>),
diff --git a/lib/stdlib/test/gen_event_SUITE.erl b/lib/stdlib/test/gen_event_SUITE.erl
index 9e3e717e7d..b3a7edc140 100644
--- a/lib/stdlib/test/gen_event_SUITE.erl
+++ b/lib/stdlib/test/gen_event_SUITE.erl
@@ -25,13 +25,14 @@
-export([start/1, add_handler/1, add_sup_handler/1,
delete_handler/1, swap_handler/1, swap_sup_handler/1,
notify/1, sync_notify/1, call/1, info/1, hibernate/1,
- call_format_status/1, error_format_status/1]).
+ call_format_status/1, call_format_status_anon/1,
+ error_format_status/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[start, {group, test_all}, hibernate,
- call_format_status, error_format_status].
+ call_format_status, call_format_status_anon, error_format_status].
groups() ->
[{test_all, [],
@@ -888,6 +889,22 @@ call_format_status(Config) when is_list(Config) ->
?line {"Installed handlers", [{_,dummy1_h,_,FmtState,_}]} = HandlerInfo2,
ok.
+call_format_status_anon(suite) ->
+ [];
+call_format_status_anon(doc) ->
+ ["Test that sys:get_status/1,2 calls format_status/2 for anonymous gen_event processes"];
+call_format_status_anon(Config) when is_list(Config) ->
+ ?line {ok, Pid} = gen_event:start(),
+ %% The 'Name' of the gen_event process will be a pid() here, so
+ %% the next line will crash if format_status can't string-ify pids.
+ ?line Status1 = sys:get_status(Pid),
+ ?line ok = gen_event:stop(Pid),
+ Header = "Status for event handler " ++ pid_to_list(Pid),
+ ?line {status, Pid, _, [_, _, Pid, [], Data1]} = Status1,
+ ?line Header = proplists:get_value(header, Data1),
+ ok.
+
+
error_format_status(suite) ->
[];
error_format_status(doc) ->
diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl
index 54a98985cd..bb02a879c2 100644
--- a/lib/stdlib/test/io_SUITE.erl
+++ b/lib/stdlib/test/io_SUITE.erl
@@ -27,7 +27,7 @@
otp_6282/1, otp_6354/1, otp_6495/1, otp_6517/1, otp_6502/1,
manpage/1, otp_6708/1, otp_7084/1, otp_7421/1,
io_lib_collect_line_3_wb/1, cr_whitespace_in_string/1,
- io_fread_newlines/1, otp_8989/1]).
+ io_fread_newlines/1, otp_8989/1, io_lib_fread_literal/1]).
%-define(debug, true).
@@ -62,7 +62,7 @@ all() ->
otp_6282, otp_6354, otp_6495, otp_6517, otp_6502,
manpage, otp_6708, otp_7084, otp_7421,
io_lib_collect_line_3_wb, cr_whitespace_in_string,
- io_fread_newlines, otp_8989].
+ io_fread_newlines, otp_8989, io_lib_fread_literal].
groups() ->
[].
@@ -1995,3 +1995,29 @@ otp_8989(Suite) when is_list(Suite) ->
?line "Hel " = fmt("~-4.*s", [3,Hello]),
?line "Hel " = fmt("~*.*s", [-4,3,Hello]),
ok.
+
+io_lib_fread_literal(doc) ->
+ "OTP-9439 io_lib:fread bug for literate at end";
+io_lib_fread_literal(Suite) when is_list(Suite) ->
+ ?line {more,"~d",0,""} = io_lib:fread("~d", ""),
+ ?line {error,{fread,integer}} = io_lib:fread("~d", " "),
+ ?line {more,"~d",1,""} = io_lib:fread(" ~d", " "),
+ ?line {ok,[17],"X"} = io_lib:fread(" ~d", " 17X"),
+ %%
+ ?line {more,"d",0,""} = io_lib:fread("d", ""),
+ ?line {error,{fread,input}} = io_lib:fread("d", " "),
+ ?line {more,"d",1,""} = io_lib:fread(" d", " "),
+ ?line {ok,[],"X"} = io_lib:fread(" d", " dX"),
+ %%
+ ?line {done,eof,_} = io_lib:fread([], eof, "~d"),
+ ?line {done,eof,_} = io_lib:fread([], eof, " ~d"),
+ ?line {more,C1} = io_lib:fread([], " \n", " ~d"),
+ ?line {done,{error,{fread,input}},_} = io_lib:fread(C1, eof, " ~d"),
+ ?line {done,{ok,[18]},""} = io_lib:fread(C1, "18\n", " ~d"),
+ %%
+ ?line {done,eof,_} = io_lib:fread([], eof, "d"),
+ ?line {done,eof,_} = io_lib:fread([], eof, " d"),
+ ?line {more,C2} = io_lib:fread([], " \n", " d"),
+ ?line {done,{error,{fread,input}},_} = io_lib:fread(C2, eof, " d"),
+ ?line {done,{ok,[]},[]} = io_lib:fread(C2, "d\n", " d"),
+ ok.
diff --git a/lib/stdlib/test/proc_lib_SUITE.erl b/lib/stdlib/test/proc_lib_SUITE.erl
index 1565aa9bba..c95089117c 100644
--- a/lib/stdlib/test/proc_lib_SUITE.erl
+++ b/lib/stdlib/test/proc_lib_SUITE.erl
@@ -328,7 +328,7 @@ otp_6345(doc) ->
["'monitor' spawn_opt option"];
otp_6345(Config) when is_list(Config) ->
Opts = [link,monitor],
- {'EXIT', {badarg,[{proc_lib,check_for_monitor,_}|_Stack]}} =
+ {'EXIT', {badarg,[{proc_lib,check_for_monitor,_,_}|_Stack]}} =
(catch proc_lib:start(?MODULE, otp_6345_init, [self()],
1000, Opts)),
ok.
diff --git a/lib/stdlib/test/re_SUITE.erl b/lib/stdlib/test/re_SUITE.erl
index c4817c0d38..3b2e637c84 100644
--- a/lib/stdlib/test/re_SUITE.erl
+++ b/lib/stdlib/test/re_SUITE.erl
@@ -454,115 +454,115 @@ error_handling(Config) when is_list(Config) ->
% The malformed precomiled RE is detected after
% the trap to re:grun from grun, in the grun function clause
% that handles precompiled expressions
- ?line {'EXIT',{badarg,[{re,run,["apa",{1,2,3,4},[global]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,run,["apa",{1,2,3,4},[global]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:run("apa",{1,2,3,4},[global])),
% An invalid capture list will also cause a badarg late,
% but with a non pre compiled RE, the exception should be thrown by the
% grun function clause that handles RE's compiled implicitly by
% the run/3 BIF before trapping.
- ?line {'EXIT',{badarg,[{re,run,["apa","p",[{capture,[1,{a}]},global]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,run,["apa","p",[{capture,[1,{a}]},global]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:run("apa","p",[{capture,[1,{a}]},global])),
% And so the case of a precompiled expression together with
% a compile-option (binary and list subject):
?line {ok,RE} = re:compile("(p)"),
?line {match,[[{1,1},{1,1}]]} = re:run(<<"apa">>,RE,[global]),
?line {match,[[{1,1},{1,1}]]} = re:run("apa",RE,[global]),
- {'EXIT',{badarg,[{re,run,
- [<<"apa">>,
- {re_pattern,1,0,_},
- [global,unicode]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,run,
+ [<<"apa">>,
+ {re_pattern,1,0,_},
+ [global,unicode]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:run(<<"apa">>,RE,[global,unicode])),
- {'EXIT',{badarg,[{re,run,
- ["apa",
- {re_pattern,1,0,_},
- [global,unicode]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,run,
+ ["apa",
+ {re_pattern,1,0,_},
+ [global,unicode]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:run("apa",RE,[global,unicode])),
?line {'EXIT',{badarg,_}} = (catch re:run("apa","(p",[])),
?line {'EXIT',{badarg,_}} = (catch re:run("apa","(p",[global])),
% The replace errors:
- ?line {'EXIT',{badarg,[{re,replace,["apa",{1,2,3,4},"X",[]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,replace,["apa",{1,2,3,4},"X",[]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:replace("apa",{1,2,3,4},"X",[])),
- ?line {'EXIT',{badarg,[{re,replace,["apa",{1,2,3,4},"X",[global]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,replace,["apa",{1,2,3,4},"X",[global]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:replace("apa",{1,2,3,4},"X",[global])),
?line {'EXIT',{badarg,[{re,replace,
["apa",
{re_pattern,1,0,_},
"X",
- [unicode]]},
- {?MODULE, error_handling,1} | _]}} =
+ [unicode]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:replace("apa",RE,"X",[unicode])),
?line <<"aXa">> = iolist_to_binary(re:replace("apa","p","X",[])),
?line {'EXIT',{badarg,[{re,replace,
- ["apa","p","X",[{capture,all,binary}]]},
- {?MODULE, error_handling,1} | _]}} =
+ ["apa","p","X",[{capture,all,binary}]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch iolist_to_binary(re:replace("apa","p","X",
[{capture,all,binary}]))),
?line {'EXIT',{badarg,[{re,replace,
- ["apa","p","X",[{capture,all}]]},
- {?MODULE, error_handling,1} | _]}} =
+ ["apa","p","X",[{capture,all}]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch iolist_to_binary(re:replace("apa","p","X",
[{capture,all}]))),
?line {'EXIT',{badarg,[{re,replace,
- ["apa","p","X",[{return,banana}]]},
- {?MODULE, error_handling,1} | _]}} =
+ ["apa","p","X",[{return,banana}]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch iolist_to_binary(re:replace("apa","p","X",
[{return,banana}]))),
?line {'EXIT',{badarg,_}} = (catch re:replace("apa","(p","X",[])),
% Badarg, not compile error.
?line {'EXIT',{badarg,[{re,replace,
- ["apa","(p","X",[{return,banana}]]},
- {?MODULE, error_handling,1} | _]}} =
+ ["apa","(p","X",[{return,banana}]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch iolist_to_binary(re:replace("apa","(p","X",
[{return,banana}]))),
% And the split errors:
?line [<<"a">>,<<"a">>] = (catch re:split("apa","p",[])),
?line [<<"a">>,<<"p">>,<<"a">>] = (catch re:split("apa",RE,[])),
- ?line {'EXIT',{badarg,[{re,split,["apa","p",[global]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,split,["apa","p",[global]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:split("apa","p",[global])),
- ?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all}]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all}]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:split("apa","p",[{capture,all}])),
- ?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all,binary}]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all,binary}]],_},
+ {?MODULE, error_handling,1,_} | _]}} =
(catch re:split("apa","p",[{capture,all,binary}])),
- ?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:split("apa",{1,2,3,4})),
- ?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]]},
- {?MODULE, error_handling,1} | _]}} =
+ ?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:split("apa",{1,2,3,4},[])),
?line {'EXIT',{badarg,[{re,split,
["apa",
RE,
- [unicode]]},
- {?MODULE, error_handling,1} | _]}} =
+ [unicode]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:split("apa",RE,[unicode])),
?line {'EXIT',{badarg,[{re,split,
["apa",
RE,
- [{return,banana}]]},
- {?MODULE, error_handling,1} | _]}} =
+ [{return,banana}]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:split("apa",RE,[{return,banana}])),
?line {'EXIT',{badarg,[{re,split,
["apa",
RE,
- [banana]]},
- {?MODULE, error_handling,1} | _]}} =
+ [banana]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:split("apa",RE,[banana])),
?line {'EXIT',{badarg,_}} = (catch re:split("apa","(p")),
%Exception on bad argument, not compilation error
?line {'EXIT',{badarg,[{re,split,
["apa",
"(p",
- [banana]]},
- {?MODULE, error_handling,1} | _]}} =
+ [banana]],_},
+ {?MODULE,error_handling,1,_} | _]}} =
(catch re:split("apa","(p",[banana])),
?t:timetrap_cancel(Dog),
ok.
diff --git a/lib/stdlib/test/shell_SUITE.erl b/lib/stdlib/test/shell_SUITE.erl
index 8273377ba1..b6019b86f0 100644
--- a/lib/stdlib/test/shell_SUITE.erl
+++ b/lib/stdlib/test/shell_SUITE.erl
@@ -2388,12 +2388,12 @@ otp_6554(Config) when is_list(Config) ->
comm_err(<<"V = lists:seq(1, 20), case V of a -> ok end.">>),
?line "exception error: no function clause matching" =
comm_err(<<"fun(P) when is_pid(P) -> true end(a).">>),
- ?line "exception error: {function_clause,[{erl_eval,do_apply,[unproper|list]}"++_ =
+ ?line "exception error: {function_clause," =
comm_err(<<"erlang:error(function_clause, [unproper | list]).">>),
?line "exception error: function_clause" =
comm_err(<<"erlang:error(function_clause, 4).">>),
%% Cheating:
- ?line "exception error: no function clause matching erl_eval:do_apply(4)" =
+ ?line "exception error: no function clause matching erl_eval:do_apply(4)" ++ _ =
comm_err(<<"erlang:error(function_clause, [4]).">>),
?line "exception error: no function clause matching" ++ _ =
comm_err(<<"fun(a, b, c, d) -> foo end"
@@ -2406,7 +2406,7 @@ otp_6554(Config) when is_list(Config) ->
comm_err(<<"fun(P, q) when is_pid(P) -> true end(a, b).">>),
?line "exception error: no function clause matching lists:reverse(" ++ _ =
comm_err(<<"F=fun() -> hello end, lists:reverse(F).">>),
- ?line "exception error: no function clause matching lists:reverse(34)" =
+ ?line "exception error: no function clause matching lists:reverse(34) (lists.erl, line " ++ _ =
comm_err(<<"lists:reverse(34).">>),
?line "exception error: no true branch found when evaluating an if expression" =
comm_err(<<"if length([a,b]) > 17 -> a end.">>),
diff --git a/lib/stdlib/test/sofs_SUITE.erl b/lib/stdlib/test/sofs_SUITE.erl
index 01de1f0600..73b282149a 100644
--- a/lib/stdlib/test/sofs_SUITE.erl
+++ b/lib/stdlib/test/sofs_SUITE.erl
@@ -1602,19 +1602,15 @@ relative_product_2(Conf) when is_list(Conf) ->
from_term([{{a},b}])}, ER)),
?line {'EXIT', {badarg, _}} = (catch relative_product({}, ER)),
- ?line eval(relative_product({relation([{a,b}])},
- from_term([],[{{atom},atom}])),
- ER),
- ?line eval(relative_product({relation([{a,b}]),relation([{a,1}])},
- from_term([{{b,1},{tjo,hej,sa}}])),
- from_term([{a,{tjo,hej,sa}}])),
- ?line eval(relative_product({relation([{a,b}]), ER},
- from_term([{{a,b},b}])),
- ER),
- ?line eval(relative_product({relation([{a,b},{c,a}]),
- relation([{a,1},{a,2}])},
- from_term([{{b,1},b1},{{b,2},b2}])),
- relation([{a,b1},{a,b2}])),
+ ?line relprod2({relation([{a,b}])}, from_term([],[{{atom},atom}]), ER),
+ ?line relprod2({relation([{a,b}]),relation([{a,1}])},
+ from_term([{{b,1},{tjo,hej,sa}}]),
+ from_term([{a,{tjo,hej,sa}}])),
+ ?line relprod2({relation([{a,b}]), ER}, from_term([{{a,b},b}]), ER),
+ ?line relprod2({relation([{a,b},{c,a}]),
+ relation([{a,1},{a,2}])},
+ from_term([{{b,1},b1},{{b,2},b2}]),
+ relation([{a,b1},{a,b2}])),
?line eval(relative_product({relation([{a,b}]), ER}),
from_term([],[{atom,{atom,atom}}])),
?line eval(relative_product({from_term([{{a,[a,b]},[a]}]),
@@ -1622,6 +1618,11 @@ relative_product_2(Conf) when is_list(Conf) ->
from_term([{{a,[a,b]},{[a],[[a,b]]}}])),
ok.
+relprod2(A1T, A2, R) ->
+ %% A tuple as first argument is the old interface:
+ eval(relative_product(A1T, A2), R),
+ eval(relative_product(tuple_to_list(A1T), A2), R).
+
product_1(suite) -> [];
product_1(doc) -> [""];
product_1(Conf) when is_list(Conf) ->
@@ -1878,11 +1879,11 @@ digraph(Conf) when is_list(Conf) ->
?line {'EXIT', {badarg, _}} =
(catch family_to_digraph(set([a]))),
- ?line {'EXIT', {badarg, [{sofs,family_to_digraph,[_,_]}|_]}} =
+ ?line {'EXIT', {badarg, [{sofs,family_to_digraph,[_,_],_}|_]}} =
(catch family_to_digraph(set([a]), [foo])),
- ?line {'EXIT', {badarg, [{sofs,family_to_digraph,[_,_]}|_]}} =
+ ?line {'EXIT', {badarg, [{sofs,family_to_digraph,[_,_],_}|_]}} =
(catch family_to_digraph(F, [foo])),
- ?line {'EXIT', {cyclic, [{sofs,family_to_digraph,[_,_]}|_]}} =
+ ?line {'EXIT', {cyclic, [{sofs,family_to_digraph,[_,_],_}|_]}} =
(catch family_to_digraph(family([{a,[a]}]),[acyclic])),
?line G1 = family_to_digraph(E),
diff --git a/lib/stdlib/test/string_SUITE.erl b/lib/stdlib/test/string_SUITE.erl
index 1dcd4be21e..6969c095a0 100644
--- a/lib/stdlib/test/string_SUITE.erl
+++ b/lib/stdlib/test/string_SUITE.erl
@@ -273,9 +273,9 @@ words(Config) when is_list(Config) ->
?line 2 = string:words("2.35", $.),
?line 100 = string:words(string:copies(". ", 100)),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:chars(hej)),
+ ?line {'EXIT',_} = (catch string:chars(hej, 1)),
%% invalid arg type
- ?line {'EXIT',_} = (catch string:chars("hej", " ")),
+ ?line {'EXIT',_} = (catch string:chars("hej", 1, " ")),
ok.
diff --git a/lib/stdlib/test/supervisor_1.erl b/lib/stdlib/test/supervisor_1.erl
index 3198be0fed..f819594c46 100644
--- a/lib/stdlib/test/supervisor_1.erl
+++ b/lib/stdlib/test/supervisor_1.erl
@@ -62,6 +62,12 @@ handle_info(die, State) ->
handle_info(stop, State) ->
{stop, normal, State};
+handle_info({'EXIT',_,shutdown}, State) ->
+ {stop, shutdown, State};
+
+handle_info({'EXIT',_,{shutdown,Term}}, State) ->
+ {stop, {shutdown,Term}, State};
+
handle_info({sleep, Time}, State) ->
io:format("FOO: ~p~n", [Time]),
timer:sleep(Time),
diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl
index 6e927da2ab..2aa3131aeb 100644
--- a/lib/stdlib/test/supervisor_SUITE.erl
+++ b/lib/stdlib/test/supervisor_SUITE.erl
@@ -20,45 +20,50 @@
-module(supervisor_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
+-define(TIMEOUT, 1000).
%% Testserver specific export
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2, init_per_testcase/2,
end_per_testcase/2]).
-%% Indirect spawn export
--export([init/1]).
+%% Internal export
+-export([init/1, terminate_all_children/1]).
%% API tests
-export([ sup_start_normal/1, sup_start_ignore_init/1,
- sup_start_ignore_child/1, sup_start_error_return/1,
- sup_start_fail/1, sup_stop_infinity/1,
- sup_stop_timeout/1, sup_stop_brutal_kill/1, child_adm/1,
- child_adm_simple/1, child_specs/1, extra_return/1]).
+ sup_start_ignore_child/1, sup_start_error_return/1,
+ sup_start_fail/1, sup_stop_infinity/1,
+ sup_stop_timeout/1, sup_stop_brutal_kill/1, child_adm/1,
+ child_adm_simple/1, child_specs/1, extra_return/1]).
%% Tests concept permanent, transient and temporary
-export([ permanent_normal/1, transient_normal/1,
- temporary_normal/1,
- permanent_abnormal/1, transient_abnormal/1,
- temporary_abnormal/1]).
+ temporary_normal/1,
+ permanent_shutdown/1, transient_shutdown/1,
+ temporary_shutdown/1,
+ permanent_abnormal/1, transient_abnormal/1,
+ temporary_abnormal/1, temporary_bystander/1]).
%% Restart strategy tests
-export([ one_for_one/1,
- one_for_one_escalation/1, one_for_all/1,
- one_for_all_escalation/1,
- simple_one_for_one/1, simple_one_for_one_escalation/1,
- rest_for_one/1, rest_for_one_escalation/1,
- simple_one_for_one_extra/1]).
+ one_for_one_escalation/1, one_for_all/1,
+ one_for_all_escalation/1,
+ simple_one_for_one/1, simple_one_for_one_escalation/1,
+ rest_for_one/1, rest_for_one_escalation/1,
+ simple_one_for_one_extra/1]).
%% Misc tests
-export([child_unlink/1, tree/1, count_children_memory/1,
- do_not_save_start_parameters_for_temporary_children/1]).
+ do_not_save_start_parameters_for_temporary_children/1,
+ do_not_save_child_specs_for_temporary_children/1,
+ simple_one_for_one_scale_many_temporary_children/1]).
-%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]}].
all() ->
[{group, sup_start}, {group, sup_stop}, child_adm,
@@ -68,8 +73,11 @@ all() ->
{group, restart_simple_one_for_one},
{group, restart_rest_for_one},
{group, normal_termination},
+ {group, shutdown_termination},
{group, abnormal_termination}, child_unlink, tree,
- count_children_memory, do_not_save_start_parameters_for_temporary_children].
+ count_children_memory, do_not_save_start_parameters_for_temporary_children,
+ do_not_save_child_specs_for_temporary_children,
+ simple_one_for_one_scale_many_temporary_children, temporary_bystander].
groups() ->
[{sup_start, [],
@@ -81,6 +89,8 @@ groups() ->
sup_stop_brutal_kill]},
{normal_termination, [],
[permanent_normal, transient_normal, temporary_normal]},
+ {shutdown_termination, [],
+ [permanent_shutdown, transient_shutdown, temporary_shutdown]},
{abnormal_termination, [],
[permanent_abnormal, transient_abnormal,
temporary_abnormal]},
@@ -94,8 +104,10 @@ groups() ->
{restart_rest_for_one, [],
[rest_for_one, rest_for_one_escalation]}].
-init_per_suite(Config) ->
- Config.
+init_per_suite(Config0) ->
+ Config = lists:keydelete(watchdog, 1, Config0),
+ Dog = test_server:timetrap(?TIMEOUT),
+ [{watchdog, Dog} | Config].
end_per_suite(_Config) ->
ok.
@@ -107,19 +119,19 @@ end_per_group(_GroupName, Config) ->
Config.
init_per_testcase(count_children_memory, Config) ->
- MemoryState = erlang:system_info(allocator),
- case count_children_allocator_test(MemoryState) of
- true -> Config;
- false ->
+ try erlang:memory() of
+ _ -> Config
+ catch error:notsup ->
{skip, "+Meamin used during test; erlang:memory/1 not available"}
end;
init_per_testcase(_Case, Config) ->
+ erlang:display(_Case),
Config.
end_per_testcase(_Case, _Config) ->
ok.
-start(InitResult) ->
+start_link(InitResult) ->
supervisor:start_link({local, sup_test}, ?MODULE, InitResult).
%% Simulate different supervisors callback.
@@ -136,145 +148,87 @@ get_child_counts(Supervisor) ->
proplists:get_value(supervisors, Counts),
proplists:get_value(workers, Counts)].
-%-------------------------------------------------------------------------
-% Test cases starts here.
-%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
+%% Test cases starts here.
+%%-------------------------------------------------------------------------
sup_start_normal(doc) ->
["Tests that the supervisor process starts correctly and that it "
- "can be terminated gracefully."];
+ "can be terminated gracefully."];
sup_start_normal(suite) -> [];
sup_start_normal(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ?line {ok, Pid} = start({ok, {{one_for_one, 2, 3600}, []}}),
- ?line exit(Pid, shutdown),
- receive
- {'EXIT', Pid, shutdown} ->
- ok;
- {'EXIT', Pid, Else} ->
- ?line test_server:fail({bad_exit_reason, Else})
- after
- 2000 ->
- ?line test_server:fail(no_exit_reason)
- end,
- ok.
-%-------------------------------------------------------------------------
+ {ok, Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
+ terminate(Pid, shutdown).
+
+%%-------------------------------------------------------------------------
sup_start_ignore_init(doc) ->
["Tests what happens if init-callback returns ignore"];
sup_start_ignore_init(suite) -> [];
sup_start_ignore_init(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ?line ignore = start(ignore),
-
- receive
- {'EXIT', _Pid, normal} ->
- ok;
- {'EXIT', _Pid, Else} ->
- ?line test_server:fail({bad_exit_reason, Else})
- after
- 2000 ->
- ?line test_server:fail(no_exit_reason)
- end,
- ok.
+ ignore = start_link(ignore),
+ check_exit_reason(normal).
-
-%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
sup_start_ignore_child(doc) ->
["Tests what happens if init-callback returns ignore"];
sup_start_ignore_child(suite) -> [];
sup_start_ignore_child(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ?line {ok, _Pid} = start({ok, {{one_for_one, 2, 3600}, []}}),
+ {ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
Child1 = {child1, {supervisor_1, start_child, [ignore]},
permanent, 1000, worker, []},
Child2 = {child2, {supervisor_1, start_child, []}, permanent,
1000, worker, []},
-
- ?line {ok, undefined} = supervisor:start_child(sup_test, Child1),
- ?line {ok, CPid2} = supervisor:start_child(sup_test, Child2),
- ?line [{child2, CPid2, worker, []},{child1, undefined, worker, []}]
- = supervisor:which_children(sup_test),
- ?line [2,1,0,2] = get_child_counts(sup_test),
+ {ok, undefined} = supervisor:start_child(sup_test, Child1),
+ {ok, CPid2} = supervisor:start_child(sup_test, Child2),
- ok.
+ [{child2, CPid2, worker, []},{child1, undefined, worker, []}]
+ = supervisor:which_children(sup_test),
+ [2,1,0,2] = get_child_counts(sup_test).
-%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
sup_start_error_return(doc) ->
["Tests what happens if init-callback returns a invalid value"];
sup_start_error_return(suite) -> [];
sup_start_error_return(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ?line {error, Term} = start(invalid),
+ {error, Term} = start_link(invalid),
+ check_exit_reason(Term).
- receive
- {'EXIT', _Pid, Term} ->
- ok;
- {'EXIT', _Pid, Else} ->
- ?line test_server:fail({bad_exit_reason, Else})
- after
- 2000 ->
- ?line test_server:fail(no_exit_reason)
- end,
- ok.
-
-%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
sup_start_fail(doc) ->
["Tests what happens if init-callback fails"];
sup_start_fail(suite) -> [];
sup_start_fail(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ?line {error, Term} = start(fail),
+ {error, Term} = start_link(fail),
+ check_exit_reason(Term).
- receive
- {'EXIT', _Pid, Term} ->
- ok;
- {'EXIT', _Pid, Else} ->
- ?line test_server:fail({bad_exit_reason, Else})
- after
- 2000 ->
- ?line test_server:fail(no_exit_reason)
- end,
- ok.
-%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
sup_stop_infinity(doc) ->
["See sup_stop/1 when Shutdown = infinity, this walue is only allowed "
- "for children of type supervisor"];
+ "for children of type supervisor"];
sup_stop_infinity(suite) -> [];
sup_stop_infinity(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ?line {ok, Pid} = start({ok, {{one_for_one, 2, 3600}, []}}),
+ {ok, Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
Child1 = {child1, {supervisor_1, start_child, []},
permanent, infinity, supervisor, []},
Child2 = {child2, {supervisor_1, start_child, []}, permanent,
- infinity, worker, []},
- ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+ infinity, worker, []},
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
link(CPid1),
- ?line {error, {invalid_shutdown,infinity}} =
- supervisor:start_child(sup_test, Child2),
+ {error, {invalid_shutdown,infinity}} =
+ supervisor:start_child(sup_test, Child2),
- ?line exit(Pid, shutdown),
+ terminate(Pid, shutdown),
+ check_exit_reason(CPid1, shutdown).
- receive
- {'EXIT', Pid, shutdown} ->
- ok;
- {'EXIT', Pid, Else} ->
- ?line test_server:fail({bad_exit_reason, Else})
- after
- 5000 ->
- ?line test_server:fail(no_exit_reason)
- end,
- receive
- {'EXIT', CPid1, shutdown} -> ok;
- {'EXIT', CPid1, Reason} ->
- ?line test_server:fail({bad_exit_reason, Reason})
- after
- 2000 -> ?line test_server:fail(no_exit_reason)
- end,
- ok.
-
-%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
sup_stop_timeout(doc) ->
["See sup_stop/1 when Shutdown = 1000"];
@@ -282,93 +236,47 @@ sup_stop_timeout(suite) -> [];
sup_stop_timeout(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ?line {ok, Pid} = start({ok, {{one_for_one, 2, 3600}, []}}),
+ {ok, Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
Child1 = {child1, {supervisor_1, start_child, []},
permanent, 1000, worker, []},
Child2 = {child2, {supervisor_1, start_child, []}, permanent,
1000, worker, []},
- ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
link(CPid1),
- ?line {ok, CPid2} = supervisor:start_child(sup_test, Child2),
+ {ok, CPid2} = supervisor:start_child(sup_test, Child2),
link(CPid2),
-
+
CPid2 ! {sleep, 200000},
- ?line exit(Pid, shutdown),
+ terminate(Pid, shutdown),
- receive
- {'EXIT', Pid, shutdown} ->
- ok;
- {'EXIT', Pid, Else} ->
- ?line test_server:fail({bad_exit_reason, Else})
- after
- 5000 ->
- ?line test_server:fail(no_exit_reason)
- end,
+ check_exit_reason(CPid1, shutdown),
+ check_exit_reason(CPid2, killed).
- receive
- {'EXIT', CPid1, shutdown} -> ok;
- {'EXIT', CPid1, Reason} ->
- ?line test_server:fail({bad_exit_reason,Reason})
- after
- 2000 -> ?line test_server:fail(no_exit_reason)
- end,
-
- receive
- {'EXIT', CPid2, killed} -> ok;
- {'EXIT', CPid2, Reason2} ->
- ?line test_server:fail({bad_exit_reason, Reason2})
- after
- 2000 -> ?line test_server:fail(no_exit_reason)
- end,
- ok.
-%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
sup_stop_brutal_kill(doc) ->
["See sup_stop/1 when Shutdown = brutal_kill"];
sup_stop_brutal_kill(suite) -> [];
sup_stop_brutal_kill(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ?line {ok, Pid} = start({ok, {{one_for_one, 2, 3600}, []}}),
+ {ok, Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
Child1 = {child1, {supervisor_1, start_child, []},
permanent, 1000, worker, []},
Child2 = {child2, {supervisor_1, start_child, []}, permanent,
brutal_kill, worker, []},
- ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
link(CPid1),
- ?line {ok, CPid2} = supervisor:start_child(sup_test, Child2),
+ {ok, CPid2} = supervisor:start_child(sup_test, Child2),
link(CPid2),
- ?line exit(Pid, shutdown),
+ terminate(Pid, shutdown),
- receive
- {'EXIT', Pid, shutdown} ->
- ok;
- {'EXIT', Pid, Else} ->
- ?line test_server:fail({bad_exit_reason, Else})
- after
- 5000 ->
- ?line test_server:fail(no_exit_reason)
- end,
+ check_exit_reason(CPid1, shutdown),
+ check_exit_reason(CPid2, killed).
- receive
- {'EXIT', CPid1, shutdown} -> ok;
- {'EXIT', CPid1, Reason} ->
- ?line test_server:fail({bad_exit_reason, Reason})
- after
- 2000 -> ?line test_server:fail(no_exit_reason)
- end,
- receive
- {'EXIT', CPid2, killed} -> ok;
- {'EXIT', CPid2, Reason2} ->
- ?line test_server:fail({bad_exit_reason, Reason2})
- after
- 2000 -> ?line test_server:fail(no_exit_reason)
- end,
- ok.
-
-%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
extra_return(doc) ->
["The start function provided to start a child may "
"return {ok, Pid} or {ok, Pid, Info}, if it returns "
@@ -382,46 +290,40 @@ extra_return(Config) when is_list(Config) ->
Child = {child1, {supervisor_1, start_child, [extra_return]},
permanent, 1000,
worker, []},
- ?line {ok, _Pid} = start({ok, {{one_for_one, 2, 3600}, [Child]}}),
- ?line [{child1, CPid, worker, []}] = supervisor:which_children(sup_test),
+ {ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, [Child]}}),
+ [{child1, CPid, worker, []}] = supervisor:which_children(sup_test),
link(CPid),
- ?line {error, not_found} = supervisor:terminate_child(sup_test, hej),
- ?line {error, not_found} = supervisor:delete_child(sup_test, hej),
- ?line {error, not_found} = supervisor:restart_child(sup_test, hej),
- ?line {error, running} = supervisor:delete_child(sup_test, child1),
- ?line {error, running} = supervisor:restart_child(sup_test, child1),
- ?line [{child1, CPid, worker, []}] = supervisor:which_children(sup_test),
- ?line [1,1,0,1] = get_child_counts(sup_test),
-
- ?line ok = supervisor:terminate_child(sup_test, child1),
- receive
- {'EXIT', CPid, shutdown} -> ok;
- {'EXIT', CPid, Reason} ->
- ?line test_server:fail({bad_reason, Reason})
- after 1000 ->
- ?line test_server:fail(no_child_termination)
- end,
- ?line [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test),
- ?line [1,0,0,1] = get_child_counts(sup_test),
-
- ?line {ok, CPid2,extra_return} =
+ {error, not_found} = supervisor:terminate_child(sup_test, hej),
+ {error, not_found} = supervisor:delete_child(sup_test, hej),
+ {error, not_found} = supervisor:restart_child(sup_test, hej),
+ {error, running} = supervisor:delete_child(sup_test, child1),
+ {error, running} = supervisor:restart_child(sup_test, child1),
+ [{child1, CPid, worker, []}] = supervisor:which_children(sup_test),
+ [1,1,0,1] = get_child_counts(sup_test),
+
+ ok = supervisor:terminate_child(sup_test, child1),
+ check_exit_reason(CPid, shutdown),
+ [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test),
+ [1,0,0,1] = get_child_counts(sup_test),
+
+ {ok, CPid2,extra_return} =
supervisor:restart_child(sup_test, child1),
- ?line [{child1, CPid2, worker, []}] = supervisor:which_children(sup_test),
- ?line [1,1,0,1] = get_child_counts(sup_test),
+ [{child1, CPid2, worker, []}] = supervisor:which_children(sup_test),
+ [1,1,0,1] = get_child_counts(sup_test),
- ?line ok = supervisor:terminate_child(sup_test, child1),
- ?line ok = supervisor:terminate_child(sup_test, child1),
- ?line ok = supervisor:delete_child(sup_test, child1),
- ?line {error, not_found} = supervisor:restart_child(sup_test, child1),
- ?line [] = supervisor:which_children(sup_test),
- ?line [0,0,0,0] = get_child_counts(sup_test),
+ ok = supervisor:terminate_child(sup_test, child1),
+ ok = supervisor:terminate_child(sup_test, child1),
+ ok = supervisor:delete_child(sup_test, child1),
+ {error, not_found} = supervisor:restart_child(sup_test, child1),
+ [] = supervisor:which_children(sup_test),
+ [0,0,0,0] = get_child_counts(sup_test),
- ?line {ok, CPid3, extra_return} = supervisor:start_child(sup_test, Child),
- ?line [{child1, CPid3, worker, []}] = supervisor:which_children(sup_test),
- ?line [1,1,0,1] = get_child_counts(sup_test),
+ {ok, CPid3, extra_return} = supervisor:start_child(sup_test, Child),
+ [{child1, CPid3, worker, []}] = supervisor:which_children(sup_test),
+ [1,1,0,1] = get_child_counts(sup_test),
ok.
-%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
child_adm(doc)->
["Test API functions start_child/2, terminate_child/2, delete_child/2 "
"restart_child/2, which_children/1, count_children/1. Only correct "
@@ -432,116 +334,124 @@ child_adm(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Child = {child1, {supervisor_1, start_child, []}, permanent, 1000,
worker, []},
- ?line {ok, _Pid} = start({ok, {{one_for_one, 2, 3600}, [Child]}}),
- ?line [{child1, CPid, worker, []}] = supervisor:which_children(sup_test),
- ?line [1,1,0,1] = get_child_counts(sup_test),
+ {ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, [Child]}}),
+ [{child1, CPid, worker, []}] = supervisor:which_children(sup_test),
+ [1,1,0,1] = get_child_counts(sup_test),
link(CPid),
%% Start of an already runnig process
- ?line {error,{already_started, CPid}} =
+ {error,{already_started, CPid}} =
supervisor:start_child(sup_test, Child),
-
+
%% Termination
- ?line {error, not_found} = supervisor:terminate_child(sup_test, hej),
- ?line {'EXIT',{noproc,{gen_server,call, _}}} =
+ {error, not_found} = supervisor:terminate_child(sup_test, hej),
+ {'EXIT',{noproc,{gen_server,call, _}}} =
(catch supervisor:terminate_child(foo, child1)),
- ?line ok = supervisor:terminate_child(sup_test, child1),
- receive
- {'EXIT', CPid, shutdown} -> ok;
- {'EXIT', CPid, Reason} ->
- ?line test_server:fail({bad_reason, Reason})
- after 1000 ->
- ?line test_server:fail(no_child_termination)
- end,
- ?line [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test),
- ?line [1,0,0,1] = get_child_counts(sup_test),
+ ok = supervisor:terminate_child(sup_test, child1),
+ check_exit_reason(CPid, shutdown),
+ [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test),
+ [1,0,0,1] = get_child_counts(sup_test),
%% Like deleting something that does not exist, it will succeed!
- ?line ok = supervisor:terminate_child(sup_test, child1),
+ ok = supervisor:terminate_child(sup_test, child1),
%% Start of already existing but not running process
- ?line {error,already_present} =
- supervisor:start_child(sup_test, Child),
+ {error,already_present} = supervisor:start_child(sup_test, Child),
%% Restart
- ?line {ok, CPid2} = supervisor:restart_child(sup_test, child1),
- ?line [{child1, CPid2, worker, []}] = supervisor:which_children(sup_test),
- ?line [1,1,0,1] = get_child_counts(sup_test),
- ?line {error, running} = supervisor:restart_child(sup_test, child1),
- ?line {error, not_found} = supervisor:restart_child(sup_test, child2),
-
+ {ok, CPid2} = supervisor:restart_child(sup_test, child1),
+ [{child1, CPid2, worker, []}] = supervisor:which_children(sup_test),
+ [1,1,0,1] = get_child_counts(sup_test),
+ {error, running} = supervisor:restart_child(sup_test, child1),
+ {error, not_found} = supervisor:restart_child(sup_test, child2),
+
%% Deletion
- ?line {error, running} = supervisor:delete_child(sup_test, child1),
- ?line {error, not_found} = supervisor:delete_child(sup_test, hej),
- ?line {'EXIT',{noproc,{gen_server,call, _}}} =
+ {error, running} = supervisor:delete_child(sup_test, child1),
+ {error, not_found} = supervisor:delete_child(sup_test, hej),
+ {'EXIT',{noproc,{gen_server,call, _}}} =
(catch supervisor:delete_child(foo, child1)),
- ?line ok = supervisor:terminate_child(sup_test, child1),
- ?line ok = supervisor:delete_child(sup_test, child1),
- ?line {error, not_found} = supervisor:restart_child(sup_test, child1),
- ?line [] = supervisor:which_children(sup_test),
- ?line [0,0,0,0] = get_child_counts(sup_test),
-
+ ok = supervisor:terminate_child(sup_test, child1),
+ ok = supervisor:delete_child(sup_test, child1),
+ {error, not_found} = supervisor:restart_child(sup_test, child1),
+ [] = supervisor:which_children(sup_test),
+ [0,0,0,0] = get_child_counts(sup_test),
+
%% Start
- ?line {'EXIT',{noproc,{gen_server,call, _}}} =
+ {'EXIT',{noproc,{gen_server,call, _}}} =
(catch supervisor:start_child(foo, Child)),
- ?line {ok, CPid3} = supervisor:start_child(sup_test, Child),
- ?line [{child1, CPid3, worker, []}] = supervisor:which_children(sup_test),
- ?line [1,1,0,1] = get_child_counts(sup_test),
+ {ok, CPid3} = supervisor:start_child(sup_test, Child),
+ [{child1, CPid3, worker, []}] = supervisor:which_children(sup_test),
+ [1,1,0,1] = get_child_counts(sup_test),
- ?line {'EXIT',{noproc,{gen_server,call,[foo,which_children,infinity]}}}
+ %% Terminate with Pid not allowed when not simple_one_for_one
+ {error,not_found} = supervisor:terminate_child(sup_test, CPid3),
+ [{child1, CPid3, worker, []}] = supervisor:which_children(sup_test),
+ [1,1,0,1] = get_child_counts(sup_test),
+
+ {'EXIT',{noproc,{gen_server,call,[foo,which_children,infinity]}}}
= (catch supervisor:which_children(foo)),
- ?line {'EXIT',{noproc,{gen_server,call,[foo,count_children,infinity]}}}
+ {'EXIT',{noproc,{gen_server,call,[foo,count_children,infinity]}}}
= (catch supervisor:count_children(foo)),
ok.
-%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
child_adm_simple(doc) ->
["The API functions terminate_child/2, delete_child/2 "
"restart_child/2 are not valid for a simple_one_for_one supervisor "
- "check that the correct error message is returned."];
+ "check that the correct error message is returned."];
child_adm_simple(suite) -> [];
child_adm_simple(Config) when is_list(Config) ->
Child = {child, {supervisor_1, start_child, []}, permanent, 1000,
worker, []},
- ?line {ok, _Pid} = start({ok, {{simple_one_for_one, 2, 3600}, [Child]}}),
+ {ok, _Pid} = start_link({ok, {{simple_one_for_one, 2, 3600}, [Child]}}),
%% In simple_one_for_one all children are added dynamically
- ?line [] = supervisor:which_children(sup_test),
- ?line [1,0,0,0] = get_child_counts(sup_test),
-
+ [] = supervisor:which_children(sup_test),
+ [1,0,0,0] = get_child_counts(sup_test),
+
%% Start
- ?line {'EXIT',{noproc,{gen_server,call, _}}} =
+ {'EXIT',{noproc,{gen_server,call, _}}} =
(catch supervisor:start_child(foo, [])),
- ?line {ok, CPid1} = supervisor:start_child(sup_test, []),
- ?line [{undefined, CPid1, worker, []}] =
+ {ok, CPid1} = supervisor:start_child(sup_test, []),
+ [{undefined, CPid1, worker, []}] =
supervisor:which_children(sup_test),
- ?line [1,1,0,1] = get_child_counts(sup_test),
-
- ?line {ok, CPid2} = supervisor:start_child(sup_test, []),
- ?line Children = supervisor:which_children(sup_test),
- ?line 2 = length(Children),
- ?line true = lists:member({undefined, CPid2, worker, []}, Children),
- ?line true = lists:member({undefined, CPid1, worker, []}, Children),
- ?line [1,2,0,2] = get_child_counts(sup_test),
+ [1,1,0,1] = get_child_counts(sup_test),
+
+ {ok, CPid2} = supervisor:start_child(sup_test, []),
+ Children = supervisor:which_children(sup_test),
+ 2 = length(Children),
+ true = lists:member({undefined, CPid2, worker, []}, Children),
+ true = lists:member({undefined, CPid1, worker, []}, Children),
+ [1,2,0,2] = get_child_counts(sup_test),
%% Termination
- ?line {error, simple_one_for_one} =
- supervisor:terminate_child(sup_test, child1),
+ {error, simple_one_for_one} = supervisor:terminate_child(sup_test, child1),
+ [1,2,0,2] = get_child_counts(sup_test),
+ ok = supervisor:terminate_child(sup_test,CPid1),
+ [_] = supervisor:which_children(sup_test),
+ [1,1,0,1] = get_child_counts(sup_test),
+ false = erlang:is_process_alive(CPid1),
+ %% Terminate non-existing proccess is ok
+ ok = supervisor:terminate_child(sup_test,CPid1),
+ [_] = supervisor:which_children(sup_test),
+ [1,1,0,1] = get_child_counts(sup_test),
+ %% Terminate pid which is not a child of this supervisor is not ok
+ NoChildPid = spawn_link(fun() -> receive after infinity -> ok end end),
+ {error, not_found} = supervisor:terminate_child(sup_test, NoChildPid),
+ true = erlang:is_process_alive(NoChildPid),
%% Restart
- ?line {error, simple_one_for_one} =
- supervisor:restart_child(sup_test, child1),
-
+ {error, simple_one_for_one} = supervisor:restart_child(sup_test, child1),
+
%% Deletion
- ?line {error, simple_one_for_one} =
- supervisor:delete_child(sup_test, child1),
+ {error, simple_one_for_one} = supervisor:delete_child(sup_test, child1),
ok.
-
-%-------------------------------------------------------------------------
+
+%%-------------------------------------------------------------------------
child_specs(doc) ->
["Tests child specs, invalid formats should be rejected."];
child_specs(suite) -> [];
child_specs(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ?line {ok, _Pid} = start({ok, {{one_for_one, 2, 3600}, []}}),
- ?line {error, _} = supervisor:start_child(sup_test, hej),
+ {ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
+ {error, _} = supervisor:start_child(sup_test, hej),
%% Bad child specs
B1 = {child, mfa, permanent, 1000, worker, []},
@@ -551,7 +461,7 @@ child_specs(Config) when is_list(Config) ->
B5 = {child, {m,f,[a]}, permanent, infinity, worker, []},
B6 = {child, {m,f,[a]}, permanent, 1000, worker, dy},
B7 = {child, {m,f,[a]}, permanent, 1000, worker, [1,2,3]},
-
+
%% Correct child specs!
%% <Modules> (last parameter in a child spec) can be [] as we do
%% not test code upgrade here.
@@ -560,327 +470,373 @@ child_specs(Config) when is_list(Config) ->
C3 = {child, {m,f,[a]}, temporary, 1000, worker, dynamic},
C4 = {child, {m,f,[a]}, transient, 1000, worker, [m]},
- ?line {error, {invalid_mfa,mfa}} = supervisor:start_child(sup_test, B1),
- ?line {error, {invalid_restart_type, prmanent}} =
+ {error, {invalid_mfa,mfa}} = supervisor:start_child(sup_test, B1),
+ {error, {invalid_restart_type, prmanent}} =
supervisor:start_child(sup_test, B2),
- ?line {error, {invalid_shutdown,-10}}
- = supervisor:start_child(sup_test, B3),
- ?line {error, {invalid_child_type,wrker}}
+ {error, {invalid_shutdown,-10}}
+ = supervisor:start_child(sup_test, B3),
+ {error, {invalid_child_type,wrker}}
= supervisor:start_child(sup_test, B4),
- ?line {error, _} = supervisor:start_child(sup_test, B5),
- ?line {error, {invalid_modules,dy}}
+ {error, _} = supervisor:start_child(sup_test, B5),
+ {error, {invalid_modules,dy}}
= supervisor:start_child(sup_test, B6),
-
- ?line {error, {invalid_mfa,mfa}} = supervisor:check_childspecs([B1]),
- ?line {error, {invalid_restart_type,prmanent}} =
+
+ {error, {invalid_mfa,mfa}} = supervisor:check_childspecs([B1]),
+ {error, {invalid_restart_type,prmanent}} =
supervisor:check_childspecs([B2]),
- ?line {error, {invalid_shutdown,-10}} = supervisor:check_childspecs([B3]),
- ?line {error, {invalid_child_type,wrker}}
+ {error, {invalid_shutdown,-10}} = supervisor:check_childspecs([B3]),
+ {error, {invalid_child_type,wrker}}
= supervisor:check_childspecs([B4]),
- ?line {error, _} = supervisor:check_childspecs([B5]),
- ?line {error, {invalid_modules,dy}} = supervisor:check_childspecs([B6]),
- ?line {error, {invalid_module, 1}} =
+ {error, _} = supervisor:check_childspecs([B5]),
+ {error, {invalid_modules,dy}} = supervisor:check_childspecs([B6]),
+ {error, {invalid_module, 1}} =
supervisor:check_childspecs([B7]),
- ?line ok = supervisor:check_childspecs([C1]),
- ?line ok = supervisor:check_childspecs([C2]),
- ?line ok = supervisor:check_childspecs([C3]),
- ?line ok = supervisor:check_childspecs([C4]),
+ ok = supervisor:check_childspecs([C1]),
+ ok = supervisor:check_childspecs([C2]),
+ ok = supervisor:check_childspecs([C3]),
+ ok = supervisor:check_childspecs([C4]),
ok.
-%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
permanent_normal(doc) ->
["A permanent child should always be restarted"];
permanent_normal(suite) -> [];
permanent_normal(Config) when is_list(Config) ->
- ?line {ok, _SupPid} = start({ok, {{one_for_one, 2, 3600}, []}}),
+ {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000,
worker, []},
-
- ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1),
-
- CPid1 ! stop,
- test_server:sleep(100),
- ?line [{child1, Pid ,worker,[]}] = supervisor:which_children(sup_test),
+
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+
+ terminate(SupPid, CPid1, child1, normal),
+
+ [{child1, Pid ,worker,[]}] = supervisor:which_children(sup_test),
case is_pid(Pid) of
true ->
ok;
false ->
- ?line test_server:fail({permanent_child_not_restarted, Child1})
+ test_server:fail({permanent_child_not_restarted, Child1})
end,
- ?line [1,1,0,1] = get_child_counts(sup_test),
+ [1,1,0,1] = get_child_counts(sup_test).
- ok.
-%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
transient_normal(doc) ->
["A transient child should not be restarted if it exits with "
"reason normal"];
transient_normal(suite) -> [];
transient_normal(Config) when is_list(Config) ->
- ?line {ok, _SupPid} = start({ok, {{one_for_one, 2, 3600}, []}}),
+ {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
Child1 = {child1, {supervisor_1, start_child, []}, transient, 1000,
worker, []},
-
- ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1),
-
- CPid1 ! stop,
- test_server:sleep(100),
-
- ?line [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test),
- ?line [1,0,0,1] = get_child_counts(sup_test),
- ok.
-%-------------------------------------------------------------------------
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+
+ terminate(SupPid, CPid1, child1, normal),
+
+ [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test),
+ [1,0,0,1] = get_child_counts(sup_test).
+
+%%-------------------------------------------------------------------------
temporary_normal(doc) ->
["A temporary process should never be restarted"];
temporary_normal(suite) -> [];
temporary_normal(Config) when is_list(Config) ->
- ?line {ok, _SupPid} = start({ok, {{one_for_one, 2, 3600}, []}}),
+ {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
Child1 = {child1, {supervisor_1, start_child, []}, temporary, 1000,
worker, []},
-
- ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1),
-
- CPid1 ! stop,
- test_server:sleep(100),
-
- ?line [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test),
- ?line [1,0,0,1] = get_child_counts(sup_test),
- ok.
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+
+ terminate(SupPid, CPid1, child1, normal),
+
+ [] = supervisor:which_children(sup_test),
+ [0,0,0,0] = get_child_counts(sup_test).
+
+%%-------------------------------------------------------------------------
+permanent_shutdown(doc) ->
+ ["A permanent child should always be restarted"];
+permanent_shutdown(suite) -> [];
+permanent_shutdown(Config) when is_list(Config) ->
+ {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
+ Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000,
+ worker, []},
+
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
-%-------------------------------------------------------------------------
+ terminate(SupPid, CPid1, child1, shutdown),
+
+ [{child1, CPid2 ,worker,[]}] = supervisor:which_children(sup_test),
+ case is_pid(CPid2) of
+ true ->
+ ok;
+ false ->
+ test_server:fail({permanent_child_not_restarted, Child1})
+ end,
+ [1,1,0,1] = get_child_counts(sup_test),
+
+ terminate(SupPid, CPid2, child1, {shutdown, some_info}),
+
+ [{child1, CPid3 ,worker,[]}] = supervisor:which_children(sup_test),
+ case is_pid(CPid3) of
+ true ->
+ ok;
+ false ->
+ test_server:fail({permanent_child_not_restarted, Child1})
+ end,
+
+ [1,1,0,1] = get_child_counts(sup_test).
+
+%%-------------------------------------------------------------------------
+transient_shutdown(doc) ->
+ ["A transient child should not be restarted if it exits with "
+ "reason shutdown or {shutdown,Term}"];
+transient_shutdown(suite) -> [];
+transient_shutdown(Config) when is_list(Config) ->
+ {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
+ Child1 = {child1, {supervisor_1, start_child, []}, transient, 1000,
+ worker, []},
+
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+
+ terminate(SupPid, CPid1, child1, shutdown),
+
+ [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test),
+ [1,0,0,1] = get_child_counts(sup_test),
+
+ {ok, CPid2} = supervisor:restart_child(sup_test, child1),
+
+ terminate(SupPid, CPid2, child1, {shutdown, some_info}),
+
+ [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test),
+ [1,0,0,1] = get_child_counts(sup_test).
+
+%%-------------------------------------------------------------------------
+temporary_shutdown(doc) ->
+ ["A temporary process should never be restarted"];
+temporary_shutdown(suite) -> [];
+temporary_shutdown(Config) when is_list(Config) ->
+ {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
+ Child1 = {child1, {supervisor_1, start_child, []}, temporary, 1000,
+ worker, []},
+
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+
+ terminate(SupPid, CPid1, child1, shutdown),
+
+ [] = supervisor:which_children(sup_test),
+ [0,0,0,0] = get_child_counts(sup_test),
+
+ {ok, CPid2} = supervisor:start_child(sup_test, Child1),
+
+ terminate(SupPid, CPid2, child1, {shutdown, some_info}),
+
+ [] = supervisor:which_children(sup_test),
+ [0,0,0,0] = get_child_counts(sup_test).
+
+%%-------------------------------------------------------------------------
permanent_abnormal(doc) ->
["A permanent child should always be restarted"];
permanent_abnormal(suite) -> [];
permanent_abnormal(Config) when is_list(Config) ->
- ?line {ok, _SupPid} = start({ok, {{one_for_one, 2, 3600}, []}}),
+ {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000,
worker, []},
-
- ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1),
-
- CPid1 ! die,
- test_server:sleep(100),
- ?line [{child1, Pid ,worker,[]}] = supervisor:which_children(sup_test),
+
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+ terminate(SupPid, CPid1, child1, abnormal),
+
+ [{child1, Pid ,worker,[]}] = supervisor:which_children(sup_test),
case is_pid(Pid) of
true ->
ok;
false ->
- ?line test_server:fail({permanent_child_not_restarted, Child1})
+ test_server:fail({permanent_child_not_restarted, Child1})
end,
- ?line [1,1,0,1] = get_child_counts(sup_test),
+ [1,1,0,1] = get_child_counts(sup_test).
- ok.
-%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
transient_abnormal(doc) ->
["A transient child should be restarted if it exits with "
"reason abnormal"];
transient_abnormal(suite) -> [];
transient_abnormal(Config) when is_list(Config) ->
- ?line {ok, _SupPid} = start({ok, {{one_for_one, 2, 3600}, []}}),
+ {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
Child1 = {child1, {supervisor_1, start_child, []}, transient, 1000,
worker, []},
-
- ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1),
-
- CPid1 ! die,
- test_server:sleep(100),
-
- ?line [{child1, Pid ,worker,[]}] = supervisor:which_children(sup_test),
+
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+ terminate(SupPid, CPid1, child1, abnormal),
+
+ [{child1, Pid ,worker,[]}] = supervisor:which_children(sup_test),
case is_pid(Pid) of
true ->
ok;
false ->
- ?line test_server:fail({transient_child_not_restarted, Child1})
+ test_server:fail({transient_child_not_restarted, Child1})
end,
- ?line [1,1,0,1] = get_child_counts(sup_test),
+ [1,1,0,1] = get_child_counts(sup_test).
- ok.
-%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
temporary_abnormal(doc) ->
["A temporary process should never be restarted"];
temporary_abnormal(suite) -> [];
temporary_abnormal(Config) when is_list(Config) ->
- ?line {ok, _SupPid} = start({ok, {{one_for_one, 2, 3600}, []}}),
+ {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
Child1 = {child1, {supervisor_1, start_child, []}, temporary, 1000,
worker, []},
-
- ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1),
-
- CPid1 ! die,
- test_server:sleep(100),
-
- ?line [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test),
- ?line [1,0,0,1] = get_child_counts(sup_test),
- ok.
-%-------------------------------------------------------------------------
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+ terminate(SupPid, CPid1, child1, abnormal),
+
+ [] = supervisor:which_children(sup_test),
+ [0,0,0,0] = get_child_counts(sup_test).
+
+%%-------------------------------------------------------------------------
+temporary_bystander(doc) ->
+ ["A temporary process killed as part of a rest_for_one or one_for_all "
+ "restart strategy should not be restarted given its args are not "
+ " saved. Otherwise the supervisor hits its limit and crashes."];
+temporary_bystander(suite) -> [];
+temporary_bystander(_Config) ->
+ Child1 = {child1, {supervisor_1, start_child, []}, permanent, 100,
+ worker, []},
+ Child2 = {child2, {supervisor_1, start_child, []}, temporary, 100,
+ worker, []},
+ {ok, SupPid1} = supervisor:start_link(?MODULE, {ok, {{one_for_all, 2, 300}, []}}),
+ {ok, SupPid2} = supervisor:start_link(?MODULE, {ok, {{rest_for_one, 2, 300}, []}}),
+ unlink(SupPid1), % otherwise we crash with it
+ unlink(SupPid2), % otherwise we crash with it
+ {ok, CPid1} = supervisor:start_child(SupPid1, Child1),
+ {ok, _CPid2} = supervisor:start_child(SupPid1, Child2),
+ {ok, CPid3} = supervisor:start_child(SupPid2, Child1),
+ {ok, _CPid4} = supervisor:start_child(SupPid2, Child2),
+ terminate(SupPid1, CPid1, child1, normal),
+ terminate(SupPid2, CPid3, child1, normal),
+ timer:sleep(350),
+ catch link(SupPid1),
+ catch link(SupPid2),
+ %% The supervisor would die attempting to restart child2
+ true = erlang:is_process_alive(SupPid1),
+ true = erlang:is_process_alive(SupPid2),
+ %% Child2 has not been restarted
+ [{child1, _, _, _}] = supervisor:which_children(SupPid1),
+ [{child1, _, _, _}] = supervisor:which_children(SupPid2).
+
+%%-------------------------------------------------------------------------
one_for_one(doc) ->
["Test the one_for_one base case."];
one_for_one(suite) -> [];
one_for_one(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000,
- worker, []},
+ worker, []},
Child2 = {child2, {supervisor_1, start_child, []}, permanent, 1000,
- worker, []},
- ?line {ok, Pid} = start({ok, {{one_for_one, 2, 3600}, []}}),
- ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1),
- link(CPid1),
- ?line {ok, CPid2} = supervisor:start_child(sup_test, Child2),
- link(CPid2),
- CPid1 ! die,
- receive
- {'EXIT', CPid1, died} -> ok;
- {'EXIT', CPid1, Reason} ->
- ?line test_server:fail({bad_exit_reason, Reason})
- end,
- test_server:sleep(100),
+ worker, []},
+ {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+ {ok, CPid2} = supervisor:start_child(sup_test, Child2),
+
+ terminate(SupPid, CPid1, child1, abnormal),
Children = supervisor:which_children(sup_test),
if length(Children) == 2 ->
case lists:keysearch(CPid2, 2, Children) of
{value, _} -> ok;
- _ -> ?line test_server:fail(bad_child)
+ _ -> test_server:fail(bad_child)
end;
- true -> ?line test_server:fail({bad_child_list, Children})
+ true -> test_server:fail({bad_child_list, Children})
end,
- ?line [2,2,0,2] = get_child_counts(sup_test),
-
+ [2,2,0,2] = get_child_counts(sup_test),
+
%% Test restart frequency property
- CPid2 ! die,
- receive
- {'EXIT', CPid2, _} -> ok
- end,
- test_server:sleep(100),
- [{_, Pid4, _, _}|_] = supervisor:which_children(sup_test),
- Pid4 ! die,
- receive
- {'EXIT', Pid, _} -> ok
- after 3000 -> ?line test_server:fail(restart_failed)
- end,
- ok.
-%-------------------------------------------------------------------------
+ terminate(SupPid, CPid2, child2, abnormal),
+
+ [{Id4, Pid4, _, _}|_] = supervisor:which_children(sup_test),
+ terminate(SupPid, Pid4, Id4, abnormal),
+ check_exit([SupPid]).
+
+%%-------------------------------------------------------------------------
one_for_one_escalation(doc) ->
["Test restart escalation on a one_for_one supervisor."];
one_for_one_escalation(suite) -> [];
one_for_one_escalation(Config) when is_list(Config) ->
process_flag(trap_exit, true),
+
Child1 = {child1, {supervisor_1, start_child, [error]},
permanent, 1000,
- worker, []},
+ worker, []},
Child2 = {child2, {supervisor_1, start_child, []}, permanent, 1000,
- worker, []},
- ?line {ok, Pid} = start({ok, {{one_for_one, 4, 3600}, []}}),
- ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1),
- link(CPid1),
- ?line {ok, CPid2} = supervisor:start_child(sup_test, Child2),
+ worker, []},
+
+ {ok, SupPid} = start_link({ok, {{one_for_one, 4, 3600}, []}}),
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+ {ok, CPid2} = supervisor:start_child(sup_test, Child2),
link(CPid2),
- CPid1 ! die,
- receive
- {'EXIT', CPid1, died} -> ok;
- {'EXIT', CPid1, Reason} ->
- ?line test_server:fail({bad_exit_reason, Reason})
- end,
- receive
- {'EXIT', Pid, _} -> ok
- after
- 2000 -> ?line test_server:fail(supervisor_alive)
- end,
- receive
- {'EXIT', CPid2, _} -> ok
- after
- 4000 -> ?line test_server:fail(all_not_terminated)
- end,
- ok.
-%-------------------------------------------------------------------------
+
+ terminate(SupPid, CPid1, child1, abnormal),
+ check_exit([SupPid, CPid2]).
+
+
+%%-------------------------------------------------------------------------
one_for_all(doc) ->
["Test the one_for_all base case."];
one_for_all(suite) -> [];
one_for_all(Config) when is_list(Config) ->
process_flag(trap_exit, true),
+
Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000,
worker, []},
Child2 = {child2, {supervisor_1, start_child, []}, permanent, 1000,
worker, []},
- ?line {ok, Pid} = start({ok, {{one_for_all, 2, 3600}, []}}),
- ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1),
- link(CPid1),
- ?line {ok, CPid2} = supervisor:start_child(sup_test, Child2),
+ {ok, SupPid} = start_link({ok, {{one_for_all, 2, 3600}, []}}),
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+ {ok, CPid2} = supervisor:start_child(sup_test, Child2),
link(CPid2),
- CPid1 ! die,
- receive
- {'EXIT', CPid1, died} -> ok;
- {'EXIT', CPid1, Reason} ->
- ?line test_server:fail({bad_exit_reason, Reason})
- end,
- receive
- {'EXIT', CPid2, _} -> ok
- end,
- test_server:sleep(100),
+
+ terminate(SupPid, CPid1, child1, abnormal),
+ check_exit([CPid2]),
+
Children = supervisor:which_children(sup_test),
if length(Children) == 2 -> ok;
- true -> ?line test_server:fail({bad_child_list, Children})
+ true ->
+ test_server:fail({bad_child_list, Children})
end,
+
%% Test that no old children is still alive
- SCh = lists:map(fun({_,P,_,_}) -> P end, Children),
- case lists:member(CPid1, SCh) of
- true -> ?line test_server:fail(bad_child);
- false -> ok
- end,
- case lists:member(CPid2, SCh) of
- true -> ?line test_server:fail(bad_child);
- false -> ok
- end,
- ?line [2,2,0,2] = get_child_counts(sup_test),
+ not_in_child_list([CPid1, CPid2], lists:map(fun({_,P,_,_}) -> P end, Children)),
+
+ [2,2,0,2] = get_child_counts(sup_test),
%%% Test restart frequency property
- [{_, Pid3, _, _}|_] = supervisor:which_children(sup_test),
- Pid3 ! die,
- test_server:sleep(100),
- [{_, Pid4, _, _}|_] = supervisor:which_children(sup_test),
- Pid4 ! die,
- receive
- {'EXIT', Pid, _} -> ok
- after 3000 -> ?line test_server:fail(restart_failed)
- end,
- exit(Pid, shutdown).
+ [{Id3, Pid3, _, _}|_] = supervisor:which_children(sup_test),
+ terminate(SupPid, Pid3, Id3, abnormal),
+ [{Id4, Pid4, _, _}|_] = supervisor:which_children(sup_test),
+ terminate(SupPid, Pid4, Id4, abnormal),
+ check_exit([SupPid]).
+
-%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
one_for_all_escalation(doc) ->
["Test restart escalation on a one_for_all supervisor."];
one_for_all_escalation(suite) -> [];
one_for_all_escalation(Config) when is_list(Config) ->
process_flag(trap_exit, true),
+
Child1 = {child1, {supervisor_1, start_child, []}, permanent, 1000,
worker, []},
Child2 = {child2, {supervisor_1, start_child, [error]},
permanent, 1000,
worker, []},
- ?line {ok, Pid} = start({ok, {{one_for_all, 4, 3600}, []}}),
- ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1),
- link(CPid1),
- ?line {ok, CPid2} = supervisor:start_child(sup_test, Child2),
+ {ok, SupPid} = start_link({ok, {{one_for_all, 4, 3600}, []}}),
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+ {ok, CPid2} = supervisor:start_child(sup_test, Child2),
link(CPid2),
- CPid1 ! die,
- receive
- {'EXIT', CPid1, died} -> ok;
- {'EXIT', CPid1, Reason} ->
- ?line test_server:fail({bad_exit_reason, Reason})
- end,
- receive
- {'EXIT', CPid2, _} -> ok
- after
- 2000 -> ?line test_server:fail(all_not_terminated)
- end,
- receive
- {'EXIT', Pid, _} -> ok
- after
- 4000 -> ?line test_server:fail(supervisor_alive)
- end,
- ok.
-%-------------------------------------------------------------------------
+ terminate(SupPid, CPid1, child1, abnormal),
+ check_exit([CPid2, SupPid]).
+
+
+%%-------------------------------------------------------------------------
simple_one_for_one(doc) ->
["Test the simple_one_for_one base case."];
simple_one_for_one(suite) -> [];
@@ -888,42 +844,31 @@ simple_one_for_one(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Child = {child, {supervisor_1, start_child, []}, permanent, 1000,
worker, []},
- ?line {ok, Pid} = start({ok, {{simple_one_for_one, 2, 3600}, [Child]}}),
- ?line {ok, CPid1} = supervisor:start_child(sup_test, []),
- link(CPid1),
- ?line {ok, CPid2} = supervisor:start_child(sup_test, []),
- link(CPid2),
- CPid1 ! die,
- receive
- {'EXIT', CPid1, died} -> ok;
- {'EXIT', CPid1, Reason} ->
- ?line test_server:fail({bad_exit_reason, Reason})
- end,
- test_server:sleep(100),
+ {ok, SupPid} = start_link({ok, {{simple_one_for_one, 2, 3600}, [Child]}}),
+ {ok, CPid1} = supervisor:start_child(sup_test, []),
+ {ok, CPid2} = supervisor:start_child(sup_test, []),
+
+ terminate(SupPid, CPid1, child1, abnormal),
+
Children = supervisor:which_children(sup_test),
if length(Children) == 2 ->
case lists:keysearch(CPid2, 2, Children) of
{value, _} -> ok;
- _ -> ?line test_server:fail(bad_child)
+ _ -> test_server:fail(bad_child)
end;
- true -> ?line test_server:fail({bad_child_list, Children})
+ true -> test_server:fail({bad_child_list, Children})
end,
- ?line [1,2,0,2] = get_child_counts(sup_test),
+ [1,2,0,2] = get_child_counts(sup_test),
%% Test restart frequency property
- CPid2 ! die,
- receive
- {'EXIT', CPid2, _} -> ok
- end,
- test_server:sleep(100),
- [{_, Pid4, _, _}|_] = supervisor:which_children(sup_test),
- Pid4 ! die,
- receive
- {'EXIT', Pid, _} -> ok
- after 3000 -> ?line test_server:fail(restart_failed)
- end,
- ok.
-%-------------------------------------------------------------------------
+ terminate(SupPid, CPid2, child2, abnormal),
+
+ [{Id4, Pid4, _, _}|_] = supervisor:which_children(sup_test),
+
+ terminate(SupPid, Pid4, Id4, abnormal),
+ check_exit([SupPid]).
+
+%%-------------------------------------------------------------------------
simple_one_for_one_extra(doc) ->
["Tests automatic restart of children "
"who's start function return extra info."];
@@ -932,41 +877,26 @@ simple_one_for_one_extra(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Child = {child, {supervisor_1, start_child, [extra_info]},
permanent, 1000, worker, []},
- ?line {ok, Pid} = start({ok, {{simple_one_for_one, 2, 3600}, [Child]}}),
- ?line {ok, CPid1, extra_info} = supervisor:start_child(sup_test, []),
- link(CPid1),
- ?line {ok, CPid2, extra_info} = supervisor:start_child(sup_test, []),
+ {ok, SupPid} = start_link({ok, {{simple_one_for_one, 2, 3600}, [Child]}}),
+ {ok, CPid1, extra_info} = supervisor:start_child(sup_test, []),
+ {ok, CPid2, extra_info} = supervisor:start_child(sup_test, []),
link(CPid2),
- CPid1 ! die,
- receive
- {'EXIT', CPid1, died} -> ok;
- {'EXIT', CPid1, Reason} ->
- ?line test_server:fail({bad_exit_reason, Reason})
- end,
- test_server:sleep(100),
+ terminate(SupPid, CPid1, child1, abnormal),
Children = supervisor:which_children(sup_test),
if length(Children) == 2 ->
case lists:keysearch(CPid2, 2, Children) of
{value, _} -> ok;
- _ -> ?line test_server:fail(bad_child)
+ _ -> test_server:fail(bad_child)
end;
- true -> ?line test_server:fail({bad_child_list, Children})
+ true -> test_server:fail({bad_child_list, Children})
end,
- ?line [1,2,0,2] = get_child_counts(sup_test),
+ [1,2,0,2] = get_child_counts(sup_test),
+ terminate(SupPid, CPid2, child2, abnormal),
+ [{Id4, Pid4, _, _}|_] = supervisor:which_children(sup_test),
+ terminate(SupPid, Pid4, Id4, abnormal),
+ check_exit([SupPid]).
- CPid2 ! die,
- receive
- {'EXIT', CPid2, _} -> ok
- end,
- test_server:sleep(100),
- [{_, Pid4, _, _}|_] = supervisor:which_children(sup_test),
- Pid4 ! die,
- receive
- {'EXIT', Pid, _} -> ok
- after 3000 -> ?line test_server:fail(restart_failed)
- end,
- ok.
-%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
simple_one_for_one_escalation(doc) ->
["Test restart escalation on a simple_one_for_one supervisor."];
simple_one_for_one_escalation(suite) -> [];
@@ -974,29 +904,16 @@ simple_one_for_one_escalation(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Child = {child, {supervisor_1, start_child, []}, permanent, 1000,
worker, []},
- ?line {ok, Pid} = start({ok, {{simple_one_for_one, 4, 3600}, [Child]}}),
- ?line {ok, CPid1} = supervisor:start_child(sup_test, [error]),
+ {ok, SupPid} = start_link({ok, {{simple_one_for_one, 4, 3600}, [Child]}}),
+ {ok, CPid1} = supervisor:start_child(sup_test, [error]),
link(CPid1),
- ?line {ok, CPid2} = supervisor:start_child(sup_test, []),
+ {ok, CPid2} = supervisor:start_child(sup_test, []),
link(CPid2),
- CPid1 ! die,
- receive
- {'EXIT', CPid1, died} -> ok;
- {'EXIT', CPid1, Reason} ->
- ?line test_server:fail({bad_exit_reason, Reason})
- end,
- receive
- {'EXIT', Pid, _} -> ok
- after
- 2000 -> ?line test_server:fail(supervisor_alive)
- end,
- receive
- {'EXIT', CPid2, _} -> ok
- after
- 2000 -> ?line test_server:fail(all_not_terminated)
- end,
- ok.
-%-------------------------------------------------------------------------
+
+ terminate(SupPid, CPid1, child, abnormal),
+ check_exit([SupPid, CPid2]).
+
+%%-------------------------------------------------------------------------
rest_for_one(doc) ->
["Test the rest_for_one base case."];
rest_for_one(suite) -> [];
@@ -1008,70 +925,45 @@ rest_for_one(Config) when is_list(Config) ->
worker, []},
Child3 = {child3, {supervisor_1, start_child, []}, permanent, 1000,
worker, []},
- ?line {ok, Pid} = start({ok, {{rest_for_one, 2, 3600}, []}}),
- ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+ {ok, SupPid} = start_link({ok, {{rest_for_one, 2, 3600}, []}}),
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
link(CPid1),
- ?line {ok, CPid2} = supervisor:start_child(sup_test, Child2),
- link(CPid2),
- ?line {ok, CPid3} = supervisor:start_child(sup_test, Child3),
+ {ok, CPid2} = supervisor:start_child(sup_test, Child2),
+ {ok, CPid3} = supervisor:start_child(sup_test, Child3),
link(CPid3),
- ?line [3,3,0,3] = get_child_counts(sup_test),
+ [3,3,0,3] = get_child_counts(sup_test),
+
+ terminate(SupPid, CPid2, child2, abnormal),
- CPid2 ! die,
- receive
- {'EXIT', CPid2, died} -> ok;
- {'EXIT', CPid2, Reason} ->
- ?line test_server:fail({bad_exit_reason, Reason})
- after 2000 ->
- ?line test_server:fail(no_exit)
- end,
%% Check that Cpid3 did die
- receive
- {'EXIT', CPid3, _} -> ok
- after 2000 ->
- ?line test_server:fail(no_exit)
- end,
- %% Check that Cpid1 didn't die
- receive
- {'EXIT', CPid1, _} ->
- ?line test_server:fail(bad_exit)
- after
- 100 -> ok
- end,
+ check_exit([CPid3]),
+
Children = supervisor:which_children(sup_test),
- if length(Children) == 3 -> ok;
- true -> ?line test_server:fail({bad_child_list, Children})
+ is_in_child_list([CPid1], Children),
+
+ if length(Children) == 3 ->
+ ok;
+ true ->
+ test_server:fail({bad_child_list, Children})
end,
- ?line [3,3,0,3] = get_child_counts(sup_test),
+ [3,3,0,3] = get_child_counts(sup_test),
%% Test that no old children is still alive
- SCh = lists:map(fun({_,P,_,_}) -> P end, Children),
- case lists:member(CPid1, SCh) of
- true -> ok;
- false -> ?line test_server:fail(bad_child)
- end,
- case lists:member(CPid2, SCh) of
- true -> ?line test_server:fail(bad_child);
- false -> ok
- end,
- case lists:member(CPid3, SCh) of
- true -> ?line test_server:fail(bad_child);
- false -> ok
- end,
-
+ Pids = lists:map(fun({_,P,_,_}) -> P end, Children),
+ not_in_child_list([CPid2, CPid3], Pids),
+ in_child_list([CPid1], Pids),
+
%% Test restart frequency property
[{child3, Pid3, _, _}|_] = supervisor:which_children(sup_test),
- Pid3 ! die,
- test_server:sleep(100),
+
+ terminate(SupPid, Pid3, child3, abnormal),
+
[_,{child2, Pid4, _, _}|_] = supervisor:which_children(sup_test),
- Pid4 ! die,
- receive
- {'EXIT', Pid, _} -> ok
- after 3000 -> ?line test_server:fail(restart_failed)
- end,
- exit(Pid, shutdown).
-%-------------------------------------------------------------------------
+ terminate(SupPid, Pid4, child2, abnormal),
+ check_exit([SupPid]).
+
+%%-------------------------------------------------------------------------
rest_for_one_escalation(doc) ->
["Test restart escalation on a rest_for_one supervisor."];
rest_for_one_escalation(suite) -> [];
@@ -1082,42 +974,29 @@ rest_for_one_escalation(Config) when is_list(Config) ->
Child2 = {child2, {supervisor_1, start_child, [error]},
permanent, 1000,
worker, []},
- ?line {ok, Pid} = start({ok, {{rest_for_one, 4, 3600}, []}}),
- ?line {ok, CPid1} = supervisor:start_child(sup_test, Child1),
- link(CPid1),
- ?line {ok, CPid2} = supervisor:start_child(sup_test, Child2),
+ {ok, SupPid} = start_link({ok, {{rest_for_one, 4, 3600}, []}}),
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+ {ok, CPid2} = supervisor:start_child(sup_test, Child2),
link(CPid2),
- CPid1 ! die,
- receive
- {'EXIT', CPid1, died} -> ok;
- {'EXIT', CPid1, Reason} ->
- ?line test_server:fail({bad_exit_reason, Reason})
- end,
- receive
- {'EXIT', CPid2, _} -> ok
- after
- 2000 -> ?line test_server:fail(not_terminated)
- end,
- receive
- {'EXIT', Pid, _} -> ok
- after
- 4000 -> ?line test_server:fail(supervisor_alive)
- end,
- ok.
-%-------------------------------------------------------------------------
-child_unlink(doc)-> ["Test that the supervisor does not hang forever if "
- "the child unliks and then is terminated by the supervisor."];
-child_unlink(suite) -> [];
+ terminate(SupPid, CPid1, child1, abnormal),
+ check_exit([CPid2, SupPid]).
+
+%%-------------------------------------------------------------------------
+child_unlink(doc)->
+ ["Test that the supervisor does not hang forever if "
+ "the child unliks and then is terminated by the supervisor."];
+child_unlink(suite) ->
+ [];
child_unlink(Config) when is_list(Config) ->
-
- ?line {ok, SupPid} = start({ok, {{one_for_one, 2, 3600}, []}}),
-
+
+ {ok, SupPid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
+
Child = {naughty_child, {naughty_child,
start_link, [SupPid]}, permanent,
1000, worker, [supervisor_SUITE]},
-
- ?line {ok, _ChildPid} = supervisor:start_child(sup_test, Child),
+
+ {ok, _ChildPid} = supervisor:start_child(sup_test, Child),
Pid = spawn(supervisor, terminate_child, [SupPid, naughty_child]),
@@ -1130,17 +1009,16 @@ child_unlink(Config) when is_list(Config) ->
ok;
_ ->
exit(Pid, kill),
- ?line test_server:fail(supervisor_hangs)
+ test_server:fail(supervisor_hangs)
end.
-%-------------------------------------------------------------------------
-
+%%-------------------------------------------------------------------------
tree(doc) ->
["Test a basic supervison tree."];
tree(suite) ->
[];
tree(Config) when is_list(Config) ->
process_flag(trap_exit, true),
-
+
Child1 = {child1, {supervisor_1, start_child, []},
permanent, 1000,
worker, []},
@@ -1166,109 +1044,54 @@ tree(Config) when is_list(Config) ->
supervisor, []},
%% Top supervisor
- ?line {ok, Pid} = start({ok, {{one_for_all, 4, 3600}, []}}),
-
+ {ok, SupPid} = start_link({ok, {{one_for_all, 4, 3600}, []}}),
+
%% Child supervisors
- ?line {ok, Sup1} = supervisor:start_child(Pid, ChildSup1),
- ?line {ok, Sup2} = supervisor:start_child(Pid, ChildSup2),
- ?line [2,2,2,0] = get_child_counts(Pid),
-
+ {ok, Sup1} = supervisor:start_child(SupPid, ChildSup1),
+ {ok, Sup2} = supervisor:start_child(SupPid, ChildSup2),
+ [2,2,2,0] = get_child_counts(SupPid),
+
%% Workers
- ?line [{_, CPid2, _, _},{_, CPid1, _, _}] =
+ [{_, CPid2, _, _},{_, CPid1, _, _}] =
supervisor:which_children(Sup1),
- ?line [2,2,0,2] = get_child_counts(Sup1),
- ?line [0,0,0,0] = get_child_counts(Sup2),
-
+ [2,2,0,2] = get_child_counts(Sup1),
+ [0,0,0,0] = get_child_counts(Sup2),
+
%% Dynamic children
- ?line {ok, CPid3} = supervisor:start_child(Sup2, Child3),
- ?line {ok, CPid4} = supervisor:start_child(Sup2, Child4),
- ?line [2,2,0,2] = get_child_counts(Sup1),
- ?line [2,2,0,2] = get_child_counts(Sup2),
-
- link(Sup1),
- link(Sup2),
- link(CPid1),
- link(CPid2),
- link(CPid3),
- link(CPid4),
-
+ {ok, CPid3} = supervisor:start_child(Sup2, Child3),
+ {ok, CPid4} = supervisor:start_child(Sup2, Child4),
+ [2,2,0,2] = get_child_counts(Sup1),
+ [2,2,0,2] = get_child_counts(Sup2),
+
%% Test that the only the process that dies is restarted
- CPid4 ! die,
-
- receive
- {'EXIT', CPid4, _} -> ?line ok
- after 10000 ->
- ?line test_server:fail(child_was_not_killed)
- end,
-
- test_server:sleep(100),
-
- ?line [{_, CPid2, _, _},{_, CPid1, _, _}] =
+ terminate(Sup2, CPid4, child4, abnormal),
+
+ [{_, CPid2, _, _},{_, CPid1, _, _}] =
supervisor:which_children(Sup1),
- ?line [2,2,0,2] = get_child_counts(Sup1),
-
- ?line [{_, NewCPid4, _, _},{_, CPid3, _, _}] =
+ [2,2,0,2] = get_child_counts(Sup1),
+
+ [{_, NewCPid4, _, _},{_, CPid3, _, _}] =
supervisor:which_children(Sup2),
- ?line [2,2,0,2] = get_child_counts(Sup2),
-
- link(NewCPid4),
+ [2,2,0,2] = get_child_counts(Sup2),
+
+ false = NewCPid4 == CPid4,
%% Test that supervisor tree is restarted, but not dynamic children.
- CPid3 ! die,
+ terminate(Sup2, CPid3, child3, abnormal),
- receive
- {'EXIT', CPid3, died} -> ?line ok;
- {'EXIT', CPid3, Reason} ->
- ?line test_server:fail({bad_exit_reason, Reason})
- after 1000 ->
- ?line test_server:fail(child_was_not_killed)
- end,
+ timer:sleep(1000),
- test_server:sleep(1000),
+ [{supchild2, NewSup2, _, _},{supchild1, NewSup1, _, _}] =
+ supervisor:which_children(SupPid),
+ [2,2,2,0] = get_child_counts(SupPid),
- receive
- {'EXIT', NewCPid4, _} -> ?line ok
- after 1000 ->
- ?line test_server:fail(child_was_not_killed)
- end,
-
- receive
- {'EXIT', Sup2, _} -> ?line ok
- after 1000 ->
- ?line test_server:fail(child_was_not_killed)
- end,
-
- receive
- {'EXIT', CPid1, _} -> ?line ok
- after 1000 ->
- ?line test_server:fail(child_was_not_killed)
- end,
-
- receive
- {'EXIT', CPid2, _} -> ?line ok
- after 1000 ->
- ?line test_server:fail(child_was_not_killed)
- end,
-
- receive
- {'EXIT', Sup1, _} -> ?line ok
- after 1000 ->
- ?line test_server:fail(child_was_not_killed)
- end,
-
- ?line [{supchild2, NewSup2, _, _},{supchild1, NewSup1, _, _}] =
- supervisor:which_children(Pid),
- ?line [2,2,2,0] = get_child_counts(Pid),
-
- ?line [{child2, _, _, _},{child1, _, _, _}] =
+ [{child2, _, _, _},{child1, _, _, _}] =
supervisor:which_children(NewSup1),
- ?line [2,2,0,2] = get_child_counts(NewSup1),
+ [2,2,0,2] = get_child_counts(NewSup1),
- ?line [] = supervisor:which_children(NewSup2),
- ?line [0,0,0,0] = get_child_counts(NewSup2),
-
- ok.
-%-------------------------------------------------------------------------
+ [] = supervisor:which_children(NewSup2),
+ [0,0,0,0] = get_child_counts(NewSup2).
+%%-------------------------------------------------------------------------
count_children_memory(doc) ->
["Test that count_children does not eat memory."];
count_children_memory(suite) ->
@@ -1277,7 +1100,7 @@ count_children_memory(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Child = {child, {supervisor_1, start_child, []}, temporary, 1000,
worker, []},
- ?line {ok, _Pid} = start({ok, {{simple_one_for_one, 2, 3600}, [Child]}}),
+ {ok, SupPid} = start_link({ok, {{simple_one_for_one, 2, 3600}, [Child]}}),
[supervisor:start_child(sup_test, []) || _Ignore <- lists:seq(1,1000)],
garbage_collect(),
@@ -1301,12 +1124,12 @@ count_children_memory(Config) when is_list(Config) ->
ChildCount3 = get_child_counts(sup_test),
Size7 = erlang:memory(processes_used),
- ?line 1000 = length(Children),
- ?line [1,1000,0,1000] = ChildCount,
- ?line 2000 = length(Children2),
- ?line [1,2000,0,2000] = ChildCount2,
- ?line Children3 = Children2,
- ?line ChildCount3 = ChildCount2,
+ 1000 = length(Children),
+ [1,1000,0,1000] = ChildCount,
+ 2000 = length(Children2),
+ [1,2000,0,2000] = ChildCount2,
+ Children3 = Children2,
+ ChildCount3 = ChildCount2,
%% count_children consumes memory using an accumulator function,
%% but the space can be reclaimed incrementally,
@@ -1314,29 +1137,18 @@ count_children_memory(Config) when is_list(Config) ->
case (Size5 =< Size4) of
true -> ok;
false ->
- ?line test_server:fail({count_children, used_more_memory})
+ test_server:fail({count_children, used_more_memory})
end,
case Size7 =< Size6 of
true -> ok;
false ->
- ?line test_server:fail({count_children, used_more_memory})
+ test_server:fail({count_children, used_more_memory})
end,
- [exit(Pid, kill) || {undefined, Pid, worker, _Modules} <- Children3],
- test_server:sleep(100),
- ?line [1,0,0,0] = get_child_counts(sup_test),
- ok.
-count_children_allocator_test(MemoryState) ->
- Allocators = [temp_alloc, eheap_alloc, binary_alloc, ets_alloc,
- driver_alloc, sl_alloc, ll_alloc, fix_alloc, std_alloc,
- sys_alloc],
- MemoryStateList = element(4, MemoryState),
- AllocTypes = [lists:keyfind(Alloc, 1, MemoryStateList)
- || Alloc <- Allocators],
- AllocStates = [lists:keyfind(e, 1, AllocValue)
- || {_Type, AllocValue} <- AllocTypes],
- lists:all(fun(State) -> State == {e, true} end, AllocStates).
-%-------------------------------------------------------------------------
+ [terminate(SupPid, Pid, child, kill) || {undefined, Pid, worker, _Modules} <- Children3],
+ [1,0,0,0] = get_child_counts(sup_test).
+
+%%-------------------------------------------------------------------------
do_not_save_start_parameters_for_temporary_children(doc) ->
["Temporary children shall not be restarted so they should not "
"save start parameters, as it potentially can "
@@ -1350,6 +1162,44 @@ do_not_save_start_parameters_for_temporary_children(Config) when is_list(Config)
dont_save_start_parameters_for_temporary_children(rest_for_one),
dont_save_start_parameters_for_temporary_children(simple_one_for_one).
+start_children(_,_, 0) ->
+ ok;
+start_children(Sup, Args, N) ->
+ Spec = child_spec(Args, N),
+ {ok, _, _} = supervisor:start_child(Sup, Spec),
+ start_children(Sup, Args, N-1).
+
+child_spec([_|_] = SimpleOneForOneArgs, _) ->
+ SimpleOneForOneArgs;
+child_spec({Name, MFA, RestartType, Shutdown, Type, Modules}, N) ->
+ NewName = list_to_atom((atom_to_list(Name) ++ integer_to_list(N))),
+ {NewName, MFA, RestartType, Shutdown, Type, Modules}.
+
+%%-------------------------------------------------------------------------
+do_not_save_child_specs_for_temporary_children(doc) ->
+ ["Temporary children shall not be restarted so supervisors should "
+ "not save their spec when they terminate"];
+do_not_save_child_specs_for_temporary_children(suite) ->
+ [];
+do_not_save_child_specs_for_temporary_children(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ dont_save_child_specs_for_temporary_children(one_for_all, kill),
+ dont_save_child_specs_for_temporary_children(one_for_one, kill),
+ dont_save_child_specs_for_temporary_children(rest_for_one, kill),
+
+ dont_save_child_specs_for_temporary_children(one_for_all, normal),
+ dont_save_child_specs_for_temporary_children(one_for_one, normal),
+ dont_save_child_specs_for_temporary_children(rest_for_one, normal),
+
+ dont_save_child_specs_for_temporary_children(one_for_all, abnormal),
+ dont_save_child_specs_for_temporary_children(one_for_one, abnormal),
+ dont_save_child_specs_for_temporary_children(rest_for_one, abnormal),
+
+ dont_save_child_specs_for_temporary_children(one_for_all, supervisor),
+ dont_save_child_specs_for_temporary_children(one_for_one, supervisor),
+ dont_save_child_specs_for_temporary_children(rest_for_one, supervisor).
+
+%%-------------------------------------------------------------------------
dont_save_start_parameters_for_temporary_children(simple_one_for_one = Type) ->
Permanent = {child, {supervisor_1, start_child, []},
permanent, 1000, worker, []},
@@ -1373,9 +1223,9 @@ dont_save_start_parameters_for_temporary_children(simple_one_for_one = Type) ->
true = (Mem3 < Mem1) and (Mem3 < Mem2),
- exit(Sup1, shutdown),
- exit(Sup2, shutdown),
- exit(Sup3, shutdown);
+ terminate(Sup1, shutdown),
+ terminate(Sup2, shutdown),
+ terminate(Sup3, shutdown);
dont_save_start_parameters_for_temporary_children(Type) ->
{ok, Sup1} = supervisor:start_link(?MODULE, {ok, {{Type, 2, 3600}, []}}),
@@ -1401,19 +1251,187 @@ dont_save_start_parameters_for_temporary_children(Type) ->
true = (Mem3 < Mem1) and (Mem3 < Mem2),
- exit(Sup1, shutdown),
- exit(Sup2, shutdown),
- exit(Sup3, shutdown).
+ terminate(Sup1, shutdown),
+ terminate(Sup2, shutdown),
+ terminate(Sup3, shutdown).
-start_children(_,_, 0) ->
+dont_save_child_specs_for_temporary_children(Type, TerminateHow)->
+ {ok, Sup} =
+ supervisor:start_link(?MODULE, {ok, {{Type, 2, 3600}, []}}),
+
+ Permanent = {child1, {supervisor_1, start_child, []},
+ permanent, 1000, worker, []},
+ Transient = {child2, {supervisor_1, start_child, []},
+ transient, 1000, worker, []},
+ Temporary = {child3, {supervisor_1, start_child, []},
+ temporary, 1000, worker, []},
+
+ permanent_child_spec_saved(Permanent, Sup, TerminateHow),
+
+ transient_child_spec_saved(Transient, Sup, TerminateHow),
+
+ temporary_child_spec_not_saved(Temporary, Sup, TerminateHow),
+
+ terminate(Sup, shutdown).
+
+permanent_child_spec_saved(ChildSpec, Sup, supervisor = TerminateHow) ->
+ already_present(Sup, ChildSpec, TerminateHow);
+
+permanent_child_spec_saved(ChildSpec, Sup, TerminateHow) ->
+ restarted(Sup, ChildSpec, TerminateHow).
+
+transient_child_spec_saved(ChildSpec, Sup, supervisor = TerminateHow) ->
+ already_present(Sup, ChildSpec, TerminateHow);
+
+transient_child_spec_saved(ChildSpec, Sup, normal = TerminateHow) ->
+ already_present(Sup, ChildSpec, TerminateHow);
+
+transient_child_spec_saved(ChildSpec, Sup, TerminateHow) ->
+ restarted(Sup, ChildSpec, TerminateHow).
+
+temporary_child_spec_not_saved({Id, _,_,_,_,_} = ChildSpec, Sup, TerminateHow) ->
+ {ok, Pid} = supervisor:start_child(Sup, ChildSpec),
+ terminate(Sup, Pid, Id, TerminateHow),
+ {ok, _} = supervisor:start_child(Sup, ChildSpec).
+
+already_present(Sup, {Id,_,_,_,_,_} = ChildSpec, TerminateHow) ->
+ {ok, Pid} = supervisor:start_child(Sup, ChildSpec),
+ terminate(Sup, Pid, Id, TerminateHow),
+ {error, already_present} = supervisor:start_child(Sup, ChildSpec),
+ {ok, _} = supervisor:restart_child(Sup, Id).
+
+restarted(Sup, {Id,_,_,_,_,_} = ChildSpec, TerminateHow) ->
+ {ok, Pid} = supervisor:start_child(Sup, ChildSpec),
+ terminate(Sup, Pid, Id, TerminateHow),
+ %% Permanent processes will be restarted by the supervisor
+ %% when not terminated by api
+ {error, {already_started, _}} = supervisor:start_child(Sup, ChildSpec).
+
+
+%%-------------------------------------------------------------------------
+%% OTP-9242: Pids for dynamic temporary children were saved as a list,
+%% which caused bad scaling when adding/deleting many processes.
+simple_one_for_one_scale_many_temporary_children(_Config) ->
+ process_flag(trap_exit, true),
+ Child = {child, {supervisor_1, start_child, []}, temporary, 1000,
+ worker, []},
+ {ok, _SupPid} = start_link({ok, {{simple_one_for_one, 2, 3600}, [Child]}}),
+
+ C1 = [begin
+ {ok,P} = supervisor:start_child(sup_test,[]),
+ P
+ end || _<- lists:seq(1,1000)],
+ {T1,done} = timer:tc(?MODULE,terminate_all_children,[C1]),
+
+ C2 = [begin
+ {ok,P} = supervisor:start_child(sup_test,[]),
+ P
+ end || _<- lists:seq(1,10000)],
+ {T2,done} = timer:tc(?MODULE,terminate_all_children,[C2]),
+
+ Scaling = T2 div T1,
+ if Scaling > 20 ->
+ %% The scaling shoul be linear (i.e.10, really), but we
+ %% give some extra here to avoid failing the test
+ %% unecessarily.
+ ?t:fail({bad_scaling,Scaling});
+ true ->
+ ok
+ end.
+
+
+terminate_all_children([C|Cs]) ->
+ ok = supervisor:terminate_child(sup_test,C),
+ terminate_all_children(Cs);
+terminate_all_children([]) ->
+ done.
+
+
+
+%%-------------------------------------------------------------------------
+terminate(Pid, Reason) when Reason =/= supervisor ->
+ terminate(dummy, Pid, dummy, Reason).
+
+terminate(Sup, _, ChildId, supervisor) ->
+ ok = supervisor:terminate_child(Sup, ChildId);
+terminate(_, ChildPid, _, kill) ->
+ Ref = erlang:monitor(process, ChildPid),
+ exit(ChildPid, kill),
+ receive
+ {'DOWN', Ref, process, ChildPid, killed} ->
+ ok
+ end;
+terminate(_, ChildPid, _, shutdown) ->
+ Ref = erlang:monitor(process, ChildPid),
+ exit(ChildPid, shutdown),
+ receive
+ {'DOWN', Ref, process, ChildPid, shutdown} ->
+ ok
+ end;
+terminate(_, ChildPid, _, {shutdown, Term}) ->
+ Ref = erlang:monitor(process, ChildPid),
+ exit(ChildPid, {shutdown, Term}),
+ receive
+ {'DOWN', Ref, process, ChildPid, {shutdown, Term}} ->
+ ok
+ end;
+terminate(_, ChildPid, _, normal) ->
+ Ref = erlang:monitor(process, ChildPid),
+ ChildPid ! stop,
+ receive
+ {'DOWN', Ref, process, ChildPid, normal} ->
+ ok
+ end;
+terminate(_, ChildPid, _,abnormal) ->
+ Ref = erlang:monitor(process, ChildPid),
+ ChildPid ! die,
+ receive
+ {'DOWN', Ref, process, ChildPid, died} ->
+ ok
+ end.
+
+in_child_list([], _) ->
+ true;
+in_child_list([Pid | Rest], Pids) ->
+ case is_in_child_list(Pid, Pids) of
+ true ->
+ in_child_list(Rest, Pids);
+ false ->
+ test_server:fail(child_should_be_alive)
+ end.
+not_in_child_list([], _) ->
+ true;
+not_in_child_list([Pid | Rest], Pids) ->
+ case is_in_child_list(Pid, Pids) of
+ true ->
+ test_server:fail(child_should_not_be_alive);
+ false ->
+ not_in_child_list(Rest, Pids)
+ end.
+
+is_in_child_list(Pid, ChildPids) ->
+ lists:member(Pid, ChildPids).
+
+check_exit([]) ->
ok;
-start_children(Sup, Args, N) ->
- Spec = child_spec(Args, N),
- {ok, _, _} = supervisor:start_child(Sup, Spec),
- start_children(Sup, Args, N-1).
+check_exit([Pid | Pids]) ->
+ receive
+ {'EXIT', Pid, _} ->
+ check_exit(Pids)
+ end.
-child_spec([_|_] = SimpleOneForOneArgs, _) ->
- SimpleOneForOneArgs;
-child_spec({Name, MFA, RestartType, Shutdown, Type, Modules}, N) ->
- NewName = list_to_atom((atom_to_list(Name) ++ integer_to_list(N))),
- {NewName, MFA, RestartType, Shutdown, Type, Modules}.
+check_exit_reason(Reason) ->
+ receive
+ {'EXIT', _, Reason} ->
+ ok;
+ {'EXIT', _, Else} ->
+ test_server:fail({bad_exit_reason, Else})
+ end.
+
+check_exit_reason(Pid, Reason) ->
+ receive
+ {'EXIT', Pid, Reason} ->
+ ok;
+ {'EXIT', Pid, Else} ->
+ test_server:fail({bad_exit_reason, Else})
+ end.
diff --git a/lib/stdlib/test/supervisor_bridge_SUITE.erl b/lib/stdlib/test/supervisor_bridge_SUITE.erl
index f2dbad0b3b..c4d696564d 100644
--- a/lib/stdlib/test/supervisor_bridge_SUITE.erl
+++ b/lib/stdlib/test/supervisor_bridge_SUITE.erl
@@ -158,7 +158,7 @@ internal_loop(State) ->
terminate(Reason,{Parent,Worker}) ->
%% This func knows about supervisor_bridge
io:format("Terminating bridge...\n"),
- exit(kill,Worker),
+ exit(Worker,kill),
Parent ! {dying,Reason},
anything.
diff --git a/lib/stdlib/test/sys_SUITE.erl b/lib/stdlib/test/sys_SUITE.erl
index 72b089aa3f..fe039e8bcc 100644
--- a/lib/stdlib/test/sys_SUITE.erl
+++ b/lib/stdlib/test/sys_SUITE.erl
@@ -71,7 +71,7 @@ log_to_file(Config) when is_list(Config) ->
?line ok = sys:log_to_file(?server,TempName),
?line {ok,-44} = public_call(44),
?line ok = sys:log_to_file(?server,false),
- ?line {ok,Fd} = file:open(TempName,read),
+ ?line {ok,Fd} = file:open(TempName,[read]),
?line Msg1 = io:get_line(Fd,''),
?line Msg2 = io:get_line(Fd,''),
?line file:close(Fd),
diff --git a/lib/stdlib/test/tar_SUITE.erl b/lib/stdlib/test/tar_SUITE.erl
index e32704ca65..9ad3936928 100644
--- a/lib/stdlib/test/tar_SUITE.erl
+++ b/lib/stdlib/test/tar_SUITE.erl
@@ -65,7 +65,7 @@ borderline(Config) when is_list(Config) ->
?line {ok, Cwd} = file:get_cwd(),
?line RootDir = ?config(priv_dir, Config),
- ?line TempDir = remove_prefix(Cwd++"/", filename:join(RootDir, borderline)),
+ ?line TempDir = remove_prefix(Cwd++"/", filename:join(RootDir, "borderline")),
?line ok = file:make_dir(TempDir),
?line Record = 512,
@@ -283,17 +283,16 @@ long_names(doc) ->
long_names(Config) when is_list(Config) ->
?line DataDir = ?config(data_dir, Config),
?line Long = filename:join(DataDir, "long_names.tar"),
+ run_in_short_tempdir(Config,
+ fun() -> do_long_names(Long) end).
+do_long_names(Long) ->
%% Try table/2 and extract/2.
?line case erl_tar:table(Long, [verbose]) of
{ok,List} when is_list(List) ->
?line io:format("~p\n", [List])
end,
-
- %% To avoid getting too long paths for Windows to handle, extract into
- %% the current directory (which is the test_server directory). Its path
- %% is quite a bit shorter than the path to priv_dir.
?line {ok,Cwd} = file:get_cwd(),
?line ok = erl_tar:extract(Long),
?line Base = filename:join([Cwd, "original_software", "written_by",
@@ -312,29 +311,28 @@ long_names(Config) when is_list(Config) ->
?line "Here"++_ = binary_to_list(First),
?line "And"++_ = binary_to_list(Second),
- %% Clean up.
- ?line delete_files([filename:join(Cwd, "original_software"),EmptyDir]),
-
ok.
create_long_names(doc) ->
["Creates a tar file from a deep directory structure (filenames are ",
"longer than 100 characters)."];
create_long_names(Config) when is_list(Config) ->
- ?line PrivDir = ?config(priv_dir, Config),
- ?line ok = file:set_cwd(PrivDir),
- Dirs = [aslfjkshjkhliuf,
- asdhjfehnbfsky,
- sahajfskdfhsz,
- asldfkdlfy4y8rchg,
- f7nafhjgffagkhsfkhsjk,
- dfjasldkfjsdkfjashbv],
+ run_in_short_tempdir(Config, fun create_long_names/0).
+
+create_long_names() ->
+ ?line {ok,Dir} = file:get_cwd(),
+ Dirs = ["aslfjkshjkhliuf",
+ "asdhjfehnbfsky",
+ "sahajfskdfhsz",
+ "asldfkdlfy4y8rchg",
+ "f7nafhjgffagkhsfkhsjk",
+ "dfjasldkfjsdkfjashbv"],
?line DeepDir = make_dirs(Dirs, []),
?line AFile = filename:join(DeepDir, "a_file"),
?line Hello = "hello, world\n",
?line ok = file:write_file(AFile, Hello),
- ?line TarName = filename:join(PrivDir, "my_tar_with_long_names.tar"),
+ ?line TarName = filename:join(Dir, "my_tar_with_long_names.tar"),
?line ok = erl_tar:create(TarName, [AFile]),
%% Print contents.
@@ -347,9 +345,6 @@ create_long_names(Config) when is_list(Config) ->
?line {ok, Bin} = file:read_file(filename:join(ExtractDir, AFile)),
?line Hello = binary_to_list(Bin),
- %% Clean up.
- ?line delete_files([ExtractDir,TarName,hd(Dirs)]),
-
ok.
make_dirs([Dir|Rest], []) ->
@@ -487,7 +482,7 @@ extract_from_binary_compressed(Config) when is_list(Config) ->
%% Trying extracting from a binary.
?line ok = erl_tar:extract({binary,Bin}, [compressed,{cwd,ExtractDir}]),
- ?line {ok,List} = file:list_dir(filename:join(ExtractDir, ddll_SUITE_data)),
+ ?line {ok,List} = file:list_dir(filename:join(ExtractDir, "ddll_SUITE_data")),
?line io:format("~p\n", [List]),
?line 19 = length(List),
@@ -676,7 +671,7 @@ cooked_compressed(Config) when is_list(Config) ->
end, List),
%% Clean up.
- ?line delete_files([filename:join(PrivDir, ddll_SUITE_data)]),
+ ?line delete_files([filename:join(PrivDir, "ddll_SUITE_data")]),
ok.
memory(doc) ->
@@ -734,3 +729,42 @@ delete_files([Item|Rest]) ->
end,
delete_files(Rest).
+%% Move to a temporary directory with as short name as possible and
+%% execute Fun. Remove the directory and any files in it afterwards.
+%% This is necessary because pathnames on Windows may be limited to
+%% 260 characters.
+run_in_short_tempdir(Config, Fun) ->
+ {ok,Cwd} = file:get_cwd(),
+ PrivDir0 = ?config(priv_dir, Config),
+
+ %% Normalize name to make sure that there is no slash at the end.
+ PrivDir = filename:absname(PrivDir0),
+
+ %% We need a base directory with a much shorter pathname than
+ %% priv_dir. We KNOW that priv_dir is located four levels below
+ %% the directory that common_test puts the ct_run.* directories
+ %% in. That fact is not documented, but an usually reliable source
+ %% assured me that the directory structure is unlikely to change
+ %% in future versions of common_test because of backward
+ %% compatibility (tools developed by users of common_test depend
+ %% on the current directory layout).
+ Base = lists:foldl(fun(_, D) ->
+ filename:dirname(D)
+ end, PrivDir, [1,2,3,4]),
+
+ Dir = make_temp_dir(Base, 0),
+ ok = file:set_cwd(Dir),
+ io:format("Running test in ~s\n", [Dir]),
+ try
+ Fun()
+ after
+ file:set_cwd(Cwd),
+ delete_files([Dir])
+ end.
+
+make_temp_dir(Base, I) ->
+ Name = filename:join(Base, integer_to_list(I, 36)),
+ case file:make_dir(Name) of
+ ok -> Name;
+ {error,eexist} -> make_temp_dir(Base, I+1)
+ end.
diff --git a/lib/stdlib/test/timer_simple_SUITE.erl b/lib/stdlib/test/timer_simple_SUITE.erl
index 852afa1a4d..dc751aad16 100644
--- a/lib/stdlib/test/timer_simple_SUITE.erl
+++ b/lib/stdlib/test/timer_simple_SUITE.erl
@@ -229,7 +229,7 @@ cancel2(Config) when is_list(Config) ->
tc(doc) -> "Test sleep/1 and tc/3.";
tc(suite) -> [];
tc(Config) when is_list(Config) ->
- % This should both sleep and tc/3
+ %% This should test both sleep and tc/3
?line {Res1, ok} = timer:tc(timer, sleep, [500]),
?line ok = if
Res1 < 500*1000 -> {too_early, Res1}; % Too early
@@ -237,13 +237,40 @@ tc(Config) when is_list(Config) ->
true -> ok
end,
- % This should both sleep and tc/2
+ %% tc/2
?line {Res2, ok} = timer:tc(fun(T) -> timer:sleep(T) end, [500]),
?line ok = if
Res2 < 500*1000 -> {too_early, Res2}; % Too early
Res2 > 800*1000 -> {too_late, Res2}; % Too much time
true -> ok
end,
+
+ %% tc/1
+ ?line {Res3, ok} = timer:tc(fun() -> timer:sleep(500) end),
+ ?line ok = if
+ Res3 < 500*1000 -> {too_early, Res3}; % Too early
+ Res3 > 800*1000 -> {too_late, Res3}; % Too much time
+ true -> ok
+ end,
+
+ %% Check that timer:tc don't catch errors
+ ?line ok = try timer:tc(erlang, exit, [foo])
+ catch exit:foo -> ok
+ end,
+
+ ?line ok = try timer:tc(fun(Reason) -> 1 = Reason end, [foo])
+ catch error:{badmatch,_} -> ok
+ end,
+
+ ?line ok = try timer:tc(fun() -> throw(foo) end)
+ catch foo -> ok
+ end,
+
+ %% Check that return values are propageted
+ Self = self(),
+ ?line {_, Self} = timer:tc(erlang, self, []),
+ ?line {_, Self} = timer:tc(fun(P) -> P end, [self()]),
+ ?line {_, Self} = timer:tc(fun() -> self() end),
?line Sec = timer:seconds(4),
?line Min = timer:minutes(4),
diff --git a/lib/stdlib/test/zip_SUITE.erl b/lib/stdlib/test/zip_SUITE.erl
index d5f2cd52d4..7233c061ef 100644
--- a/lib/stdlib/test/zip_SUITE.erl
+++ b/lib/stdlib/test/zip_SUITE.erl
@@ -375,7 +375,8 @@ zip_options(Config) when is_list(Config) ->
ok = file:set_cwd(?config(data_dir, Config)),
%% Create a zip archive
- {ok, Zip} = zip:zip("filename_not_used.zip", Names, [memory, {cwd, PrivDir}]),
+ {ok, {_,Zip}} =
+ zip:zip("filename_not_used.zip", Names, [memory, {cwd, PrivDir}]),
%% Open archive
{ok, ZipSrv} = zip:zip_open(Zip, [memory]),
diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk
index c0956030cf..2f0ecd3863 100644
--- a/lib/stdlib/vsn.mk
+++ b/lib/stdlib/vsn.mk
@@ -1 +1 @@
-STDLIB_VSN = 1.17.4
+STDLIB_VSN = 1.18
diff --git a/lib/syntax_tools/doc/src/notes.xml b/lib/syntax_tools/doc/src/notes.xml
index 3f5eb7231e..5948f7ada3 100644
--- a/lib/syntax_tools/doc/src/notes.xml
+++ b/lib/syntax_tools/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2007</year><year>2010</year>
+ <year>2007</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,25 @@
<p>This document describes the changes made to the Syntax_Tools
application.</p>
+<section><title>Syntax_Tools 1.6.7.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> In a file containing declarations and comments
+ without any empty lines between them, the
+ <c>recomment_forms()</c> function would associate a
+ multi-line comment with the declaration above it rather
+ than the one following it. (Thanks to Richard Carlsson
+ and Kostis Sagonas.) </p>
+ <p>
+ Own Id: OTP-9180</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Syntax_Tools 1.6.7</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/syntax_tools/src/erl_recomment.erl b/lib/syntax_tools/src/erl_recomment.erl
index 919e9cfc5d..fc7c515700 100644
--- a/lib/syntax_tools/src/erl_recomment.erl
+++ b/lib/syntax_tools/src/erl_recomment.erl
@@ -163,7 +163,7 @@ recomment_forms_2(C, [N | Ns] = Nodes, Insert) ->
Trailing =
case Ns of
[] -> true;
- [Next | _] -> L < node_min(Next) - 2
+ [Next | _] -> L + Delta < node_min(Next) - 2
end,
if L > Max + 1 ; L =:= Max + 1, not Trailing ->
[N | recomment_forms_2(C, Ns, Insert)];
diff --git a/lib/syntax_tools/test/Makefile b/lib/syntax_tools/test/Makefile
index e793dec566..3e31bdbd50 100644
--- a/lib/syntax_tools/test/Makefile
+++ b/lib/syntax_tools/test/Makefile
@@ -60,6 +60,6 @@ release_tests_spec: make_emakefile
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(RELSYSDIR)
$(INSTALL_DATA) syntax_tools.spec syntax_tools.cover $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
release_docs_spec:
diff --git a/lib/syntax_tools/vsn.mk b/lib/syntax_tools/vsn.mk
index 2e23f6aef9..cc7ea944f9 100644
--- a/lib/syntax_tools/vsn.mk
+++ b/lib/syntax_tools/vsn.mk
@@ -1 +1 @@
-SYNTAX_TOOLS_VSN = 1.6.7
+SYNTAX_TOOLS_VSN = 1.6.7.1
diff --git a/lib/test_server/doc/src/notes.xml b/lib/test_server/doc/src/notes.xml
index 9c62b0fcf6..beeff55ffe 100644
--- a/lib/test_server/doc/src/notes.xml
+++ b/lib/test_server/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,209 @@
<file>notes.xml</file>
</header>
+<section><title>Test_Server 3.4.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ An error in how comments are colored in the test suite
+ overview html log file has been corrected. As result, a
+ new framework callback function, format_comment/1, has
+ been introduced.</p>
+ <p>
+ Own Id: OTP-9237</p>
+ </item>
+ <item>
+ <p>
+ Test Server did not release SASL TTY handlers
+ (sasl_report_tty_h and error_logger_tty_h) properly after
+ each test run. This error has been fixed.</p>
+ <p>
+ Own Id: OTP-9311</p>
+ </item>
+ <item>
+ <p>
+ Automatically generated init- and end-configuration
+ functions for test case groups caused incorrect execution
+ order of test cases. This has been corrected.</p>
+ <p>
+ Own Id: OTP-9369</p>
+ </item>
+ <item>
+ <p>
+ If ct:log/2 was called with bad arguments, this could
+ cause the Common Test IO handling process to crash. This
+ fault has been corrected.</p>
+ <p>
+ Own Id: OTP-9371 Aux Id: OTP-8933 </p>
+ </item>
+ <item>
+ <p>
+ A bug has been fixed that made Test Server call the
+ end_tc/3 framework function with an incorrect module name
+ as first argument.</p>
+ <p>
+ Own Id: OTP-9379 Aux Id: seq11863 </p>
+ </item>
+ <item>
+ <p>
+ If end_per_testcase caused a timetrap timeout, the actual
+ test case status was discarded and the test case logged
+ as successful (even if the case had actually failed
+ before the call to end_per_testcase). This fault has been
+ fixed.</p>
+ <p>
+ Own Id: OTP-9397</p>
+ </item>
+ <item>
+ <p>
+ If a timetrap timeout occured during execution of of a
+ function in a lib module (i.e. a function called directly
+ or indirectly from a test case), the Suite argument in
+ the end_tc/3 framework callback function would not
+ correctly contain the name of the test suite, but the lib
+ module. (This would only happen if the lib module was
+ compiled with ct.hrl included). This error has been
+ solved.</p>
+ <p>
+ Own Id: OTP-9398</p>
+ </item>
+ <item>
+ <p>
+ Add a proplist() type</p>
+ <p>
+ Recently I was adding specs to an API and found that
+ there is no canonical proplist() type defined. (Thanks to
+ Ryan Zezeski)</p>
+ <p>
+ Own Id: OTP-9499</p>
+ </item>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ <item>
+ <p>
+ If a test suite would start with a test case group
+ defined without the init_per_group/2 and end_per_group/2
+ function, init_per_suite/1 would not execute initially
+ and logging of the test run would fail. This error has
+ been fixed.</p>
+ <p>
+ Own Id: OTP-9584</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A new option, 'logopts', has been introduced, to make it
+ possible to modify some aspects of the logging behaviour
+ in Common Test (or Test Server). For example, whenever an
+ io printout is made, test_server adds newline (\n) to the
+ end of the output string. This may not always be a
+ preferred action and can therefore be disabled by means
+ of "ct_run ... -logopts no_nl" (or ct:run_test([...,
+ {logopts,[no_nl]}])). A new framework callback function,
+ get_logopts/0, has been introduced (see the ct_framework
+ module for details).</p>
+ <p>
+ Own Id: OTP-9372 Aux Id: OTP-9396 </p>
+ </item>
+ <item>
+ <p>
+ A new option, 'logopts', has been introduced, to make it
+ possible to modify some aspects of the logging behaviour
+ in Common Test (or Test Server). For example, if the html
+ version of the test suite source code should not be
+ generated during the test run (and consequently be
+ unavailable in the log file system), the feature may be
+ disabled by means of "ct_run ... -logopts no_src" (or
+ ct:run_test([..., {logopts,[no_src]}])). A new framework
+ callback function, get_logopts/0, has been introduced
+ (see the ct_framework module for details).</p>
+ <p>
+ Own Id: OTP-9396 Aux Id: seq11869, OTP-9372 </p>
+ </item>
+ <item>
+ <p>
+ It is now possible to use a tuple {M,F,A}, or a fun, as
+ timetrap specification in the suite info function or test
+ case info functions. The function must return a valid
+ timeout value, as documented in the common_test man page
+ and in the User's Guide.</p>
+ <p>
+ Own Id: OTP-9501 Aux Id: seq11894 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Test_Server 3.4.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ It was previously not possible to use timetrap value
+ 'infinity' with ct:timetrap/1. This has been fixed.</p>
+ <p>
+ Own Id: OTP-9159</p>
+ </item>
+ <item>
+ <p>
+ A bug that made it impossible to cancel the previous
+ timetrap when calling ct:timetrap/1 has been corrected.</p>
+ <p>
+ Own Id: OTP-9233 Aux Id: OTP-9159 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ When running tests with auto-compilation disabled, Common
+ Test could only display the test suite source code on
+ html format in the test case log if the source file was
+ located in the same directory as the pre-compiled suite.
+ This has been modified so that Common Test now tries to
+ locate the source file by means of the test suite module
+ info (Suite:module_info/1). As a result, a suite may now
+ be compiled to a different output directory (e.g.
+ $MYTEST/bin) than the source code directory (e.g.
+ $MYTEST/src), without the source-code-to-html generation
+ being affected.</p>
+ <p>
+ Own Id: OTP-9138</p>
+ </item>
+ <item>
+ <p>
+ It is now possible to return a tuple {fail,Reason} from
+ init_per_testcase/2. The result is that the associated
+ test case gets logged as failed without ever executing.</p>
+ <p>
+ Own Id: OTP-9160 Aux Id: seq11502 </p>
+ </item>
+ <item>
+ <p>
+ Added DragonflyBSD check in test_server configure.</p>
+ <p>
+ Own Id: OTP-9249</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Test_Server 3.4.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/test_server/doc/src/ts.xml b/lib/test_server/doc/src/ts.xml
index 496ad3667a..f9b48d8372 100644
--- a/lib/test_server/doc/src/ts.xml
+++ b/lib/test_server/doc/src/ts.xml
@@ -77,7 +77,7 @@
</p>
<p><c>ts:install/0</c> is used if the target platform is the
same as the controller host, i.e. if you run on "local target"
- and no options are needed. Then running <c>ts:install/0</c><c>ts</c>
+ and no options are needed. Then running <c>ts:install/0</c> <c>ts</c>
will run an autoconf script for your current
environment and set up the necessary variables needed by the
test suites.
diff --git a/lib/test_server/include/test_server.hrl b/lib/test_server/include/test_server.hrl
index 4b96d84ace..36e7e1f83d 100644
--- a/lib/test_server/include/test_server.hrl
+++ b/lib/test_server/include/test_server.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The 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,11 +20,10 @@
-ifdef(line_trace).
-line_trace(true).
-define(line,
- put(test_server_loc,{?MODULE,?LINE}),
io:format(lists:concat([?MODULE,",",integer_to_list(?LINE),": ~p"]),
[erlang:now()]),).
-else.
--define(line,put(test_server_loc,{?MODULE,?LINE}),).
+-define(line,).
-endif.
-define(t,test_server).
-define(config,test_server:lookup_config).
diff --git a/lib/test_server/include/test_server_line.hrl b/lib/test_server/include/test_server_line.hrl
index 60ef860883..3c309d3ee5 100644
--- a/lib/test_server/include/test_server_line.hrl
+++ b/lib/test_server/include/test_server_line.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -16,5 +16,4 @@
%%
%% %CopyrightEnd%
%%
--compile({parse_transform,test_server_line}).
diff --git a/lib/test_server/src/Makefile b/lib/test_server/src/Makefile
index 63a585d526..4bc51873c2 100644
--- a/lib/test_server/src/Makefile
+++ b/lib/test_server/src/Makefile
@@ -43,7 +43,6 @@ MODULES= test_server_ctrl \
test_server_node \
test_server \
test_server_sup \
- test_server_line \
test_server_h \
erl2html2 \
vxworks_client
diff --git a/lib/test_server/src/configure.in b/lib/test_server/src/configure.in
index 2bbbc18966..097853bcfc 100644
--- a/lib/test_server/src/configure.in
+++ b/lib/test_server/src/configure.in
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script for Erlang.
dnl
dnl %CopyrightBegin%
dnl
-dnl Copyright Ericsson AB 1997-2009. All Rights Reserved.
+dnl Copyright Ericsson AB 1997-2011. All Rights Reserved.
dnl
dnl The contents of this file are subject to the Erlang Public License,
dnl Version 1.1, (the "License"); you may not use this file except in
@@ -136,7 +136,7 @@ case $system in
fi
SHLIB_EXTRACT_ALL=""
;;
- NetBSD-*|FreeBSD-*|OpenBSD-*)
+ NetBSD-*|FreeBSD-*|OpenBSD-*|DragonFly*)
# Not available on all versions: check for include file.
AC_CHECK_HEADER(dlfcn.h, [
SHLIB_CFLAGS="-fpic"
diff --git a/lib/test_server/src/test_server.app.src b/lib/test_server/src/test_server.app.src
index af2d4dc2cb..7e87583a7b 100644
--- a/lib/test_server/src/test_server.app.src
+++ b/lib/test_server/src/test_server.app.src
@@ -24,7 +24,6 @@
test_server_ctrl,
test_server,
test_server_h,
- test_server_line,
test_server_node,
test_server_sup
]},
diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl
index 7f0011bd68..49f97686a0 100644
--- a/lib/test_server/src/test_server.erl
+++ b/lib/test_server/src/test_server.erl
@@ -36,7 +36,7 @@
-export([capture_start/0,capture_stop/0,capture_get/0]).
-export([messages_get/0]).
-export([hours/1,minutes/1,seconds/1,sleep/1,adjusted_sleep/1,timecall/3]).
--export([timetrap_scale_factor/0,timetrap/1,timetrap_cancel/1]).
+-export([timetrap_scale_factor/0,timetrap/1,timetrap_cancel/1,timetrap_cancel/0]).
-export([m_out_of_n/3,do_times/4,do_times/2]).
-export([call_crash/3,call_crash/4,call_crash/5]).
-export([temp_name/1]).
@@ -612,6 +612,7 @@ do_run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData) ->
print(minor, "Current directory is ~p\n", [Cwd]),
print_timestamp(minor,"Started at "),
TCCallback = get(test_server_testcase_callback),
+ LogOpts = get(test_server_logopts),
Ref = make_ref(),
OldGLeader = group_leader(),
%% Set ourself to group leader for the spawned process
@@ -621,7 +622,7 @@ do_run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData) ->
fun() ->
run_test_case_eval(Mod, Func, Args, Name, Ref,
RunInit, TimetrapData,
- TCCallback)
+ LogOpts, TCCallback)
end),
group_leader(OldGLeader, self()),
put(test_server_detected_fail, []),
@@ -733,15 +734,23 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
print(Detail,Format,Args),
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
{comment,NewComment} ->
+ NewComment1 = test_server_ctrl:to_string(NewComment),
+ NewComment2 = test_server_sup:framework_call(format_comment,
+ [NewComment1],
+ NewComment1),
Terminate1 =
case Terminate of
{true,{Time,Value,Loc,Opts,_OldComment}} ->
- {true,{Time,Value,mod_loc(Loc),Opts,NewComment}};
+ {true,{Time,Value,mod_loc(Loc),Opts,NewComment2}};
Other ->
Other
end,
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate1,NewComment,CurrConf);
- {set_curr_conf,NewCurrConf} ->
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate1,NewComment2,CurrConf);
+ {read_comment,From} ->
+ From ! {self(),read_comment,Comment},
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
+ {set_curr_conf,From,NewCurrConf} ->
+ From ! {self(),set_curr_conf,ok},
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,NewCurrConf);
{'EXIT',Pid,{Ref,Time,Value,Loc,Opts}} ->
RetVal = {Time/1000000,Value,mod_loc(Loc),Opts,Comment},
@@ -753,13 +762,12 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
case mod_loc(Loc) of
{FwMod,FwFunc,framework} ->
%% timout during framework call
- spawn_fw_call(FwMod,FwFunc,Pid,
+ spawn_fw_call(FwMod,FwFunc,CurrConf,Pid,
{framework_error,{timetrap,TVal}},
unknown,self(),Comment),
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,
Comment,undefined);
Loc1 ->
- {Mod,Func} = get_mf(Loc1),
%% call end_per_testcase on a separate process,
%% only so that the user has a chance to clean up
%% after init_per_testcase, even after a timetrap timeout
@@ -775,11 +783,13 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
TVal),
{EndConfPid,{Mod,Func},Conf};
_ ->
+ {Mod,Func} = get_mf(Loc1),
%% The framework functions mustn't execute on this
%% group leader process or io will cause deadlock,
%% so we spawn a dedicated process for the operation
%% and let the group leader go back to handle io.
- spawn_fw_call(Mod,Func,Pid,{timetrap_timeout,TVal},
+ spawn_fw_call(Mod,Func,CurrConf,Pid,
+ {timetrap_timeout,TVal},
Loc1,self(),Comment),
undefined
end,
@@ -790,12 +800,13 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
case mod_loc(Loc) of
{FwMod,FwFunc,framework} ->
%% timout during framework call
- spawn_fw_call(FwMod,FwFunc,Pid,
+ spawn_fw_call(FwMod,FwFunc,CurrConf,Pid,
{framework_error,{timetrap,TVal}},
unknown,self(),Comment);
Loc1 ->
{Mod,_Func} = get_mf(Loc1),
- spawn_fw_call(Mod,InitOrEnd,Pid,{timetrap_timeout,TVal},
+ spawn_fw_call(Mod,InitOrEnd,CurrConf,Pid,
+ {timetrap_timeout,TVal},
Loc1,self(),Comment)
end,
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
@@ -804,13 +815,12 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
case mod_loc(AbortLoc) of
{FwMod,FwFunc,framework} ->
%% abort during framework call
- spawn_fw_call(FwMod,FwFunc,Pid,
+ spawn_fw_call(FwMod,FwFunc,CurrConf,Pid,
{framework_error,ErrorMsg},
unknown,self(),Comment),
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,
Comment,undefined);
Loc1 ->
- {Mod,Func} = get_mf(Loc1),
%% call end_per_testcase on a separate process, only so
%% that the user has a chance to clean up after init_per_testcase,
%% even after abortion
@@ -828,7 +838,8 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
TVal),
{EndConfPid,{Mod,Func},Conf};
_ ->
- spawn_fw_call(Mod,Func,Pid,ErrorMsg,
+ {Mod,Func} = get_mf(Loc1),
+ spawn_fw_call(Mod,Func,CurrConf,Pid,ErrorMsg,
Loc1,self(),Comment),
undefined
end,
@@ -839,17 +850,18 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
%% result of an exit(TestCase,kill) call, which is the
%% only way to abort a testcase process that traps exits
%% (see abort_current_testcase)
- spawn_fw_call(undefined,undefined,Pid,testcase_aborted_or_killed,
+ spawn_fw_call(undefined,undefined,CurrConf,Pid,
+ testcase_aborted_or_killed,
unknown,self(),Comment),
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
{fw_error,{FwMod,FwFunc,FwError}} ->
- spawn_fw_call(FwMod,FwFunc,Pid,{framework_error,FwError},
+ spawn_fw_call(FwMod,FwFunc,CurrConf,Pid,{framework_error,FwError},
unknown,self(),Comment),
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
_Other ->
%% the testcase has terminated because of Reason (e.g. an exit
%% because a linked process failed)
- spawn_fw_call(undefined,undefined,Pid,Reason,
+ spawn_fw_call(undefined,undefined,CurrConf,Pid,Reason,
unknown,self(),Comment),
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf)
end;
@@ -857,7 +869,7 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
case CurrConf of
{EndConfPid,{Mod,Func},_Conf} ->
{_Mod,_Func,TCPid,TCExitReason,Loc} = Data,
- spawn_fw_call(Mod,Func,TCPid,TCExitReason,Loc,self(),Comment),
+ spawn_fw_call(Mod,Func,CurrConf,TCPid,TCExitReason,Loc,self(),Comment),
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,undefined);
_ ->
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf)
@@ -928,7 +940,7 @@ call_end_conf(Mod,Func,TCPid,TCExitReason,Loc,Conf,TVal) ->
ok
end,
Supervisor ! {self(),end_conf}
- end,
+ end,
Pid = spawn_link(EndConfApply),
receive
{Pid,end_conf} ->
@@ -941,50 +953,72 @@ call_end_conf(Mod,Func,TCPid,TCExitReason,Loc,Conf,TVal) ->
end,
spawn_link(EndConfProc).
-spawn_fw_call(Mod,{init_per_testcase,Func},Pid,{timetrap_timeout,TVal}=Why,
+spawn_fw_call(Mod,{init_per_testcase,Func},_,Pid,{timetrap_timeout,TVal}=Why,
Loc,SendTo,Comment) ->
FwCall =
fun() ->
- Skip = {skip,{failed,{Mod,init_per_testcase,Why}}},
- %% if init_per_testcase fails, the test case
- %% should be skipped
- case catch do_end_tc_call(Mod,Func,{Pid,Skip,[[]]},Why) of
- {'EXIT',FwEndTCErr} ->
- exit({fw_notify_done,end_tc,FwEndTCErr});
- _ ->
- ok
- end,
- %% finished, report back
- SendTo ! {self(),fw_notify_done,
- {TVal/1000,Skip,Loc,[],Comment}}
+ Skip = {skip,{failed,{Mod,init_per_testcase,Why}}},
+ %% if init_per_testcase fails, the test case
+ %% should be skipped
+ case catch do_end_tc_call(Mod,Func, Loc, {Pid,Skip,[[]]}, Why) of
+ {'EXIT',FwEndTCErr} ->
+ exit({fw_notify_done,end_tc,FwEndTCErr});
+ _ ->
+ ok
+ end,
+ %% finished, report back
+ SendTo ! {self(),fw_notify_done,
+ {TVal/1000,Skip,Loc,[],Comment}}
end,
spawn_link(FwCall);
-spawn_fw_call(Mod,{end_per_testcase,Func},Pid,{timetrap_timeout,TVal}=Why,
- Loc,SendTo,_Comment) ->
+spawn_fw_call(Mod,{end_per_testcase,Func},EndConf,Pid,
+ {timetrap_timeout,TVal}=Why,_Loc,SendTo,Comment) ->
+ %%! This is a temporary fix that keeps Test Server alive during
+ %%! execution of a parallel test case group, when sometimes
+ %%! this clause gets called with EndConf == undefined. See OTP-9594
+ %%! for more info.
+ EndConf1 = if EndConf == undefined ->
+ [{tc_status,{failed,{Mod,end_per_testcase,Why}}}];
+ true ->
+ EndConf
+ end,
FwCall =
fun() ->
- Conf = [{tc_status,ok}],
- %% if end_per_testcase fails, the test case should be
- %% reported successful with a warning printed as comment
- case catch do_end_tc_call(Mod,Func,{Pid,
- {failed,{Mod,end_per_testcase,Why}},
- [Conf]}, Why) of
- {'EXIT',FwEndTCErr} ->
- exit({fw_notify_done,end_tc,FwEndTCErr});
- _ ->
- ok
- end,
- %% finished, report back
- SendTo ! {self(),fw_notify_done,
- {TVal/1000,{error,{Mod,end_per_testcase,Why}},Loc,[],
- ["<font color=\"red\">"
- "WARNING: end_per_testcase timed out!"
- "</font>"]}}
+ {RetVal,Report} =
+ case proplists:get_value(tc_status, EndConf1) of
+ undefined ->
+ E = {failed,{Mod,end_per_testcase,Why}},
+ {E,E};
+ E = {failed,Reason} ->
+ {E,{error,Reason}};
+ Result ->
+ E = {failed,{Mod,end_per_testcase,Why}},
+ {Result,E}
+ end,
+ FailLoc = proplists:get_value(tc_fail_loc, EndConf1),
+ case catch do_end_tc_call(Mod,Func, FailLoc,
+ {Pid,Report,[EndConf1]}, Why) of
+ {'EXIT',FwEndTCErr} ->
+ exit({fw_notify_done,end_tc,FwEndTCErr});
+ _ ->
+ ok
+ end,
+ %% if end_per_testcase fails a warning should be
+ %% printed as comment
+ Comment1 = if Comment == "" -> "";
+ true -> Comment ++ "<br>"
+ end,
+ %% finished, report back
+ SendTo ! {self(),fw_notify_done,
+ {TVal/1000,RetVal,FailLoc,[],
+ [Comment1,"<font color=\"red\">"
+ "WARNING: end_per_testcase timed out!"
+ "</font>"]}}
end,
spawn_link(FwCall);
-spawn_fw_call(FwMod,FwFunc,_Pid,{framework_error,FwError},_,SendTo,_Comment) ->
+spawn_fw_call(FwMod,FwFunc,_,_Pid,{framework_error,FwError},_,SendTo,_Comment) ->
FwCall =
fun() ->
test_server_sup:framework_call(report, [framework_error,
@@ -999,7 +1033,7 @@ spawn_fw_call(FwMod,FwFunc,_Pid,{framework_error,FwError},_,SendTo,_Comment) ->
end,
spawn_link(FwCall);
-spawn_fw_call(Mod,Func,Pid,Error,Loc,SendTo,Comment) ->
+spawn_fw_call(Mod,Func,_,Pid,Error,Loc,SendTo,Comment) ->
FwCall =
fun() ->
case catch fw_error_notify(Mod,Func,[],
@@ -1011,7 +1045,8 @@ spawn_fw_call(Mod,Func,Pid,Error,Loc,SendTo,Comment) ->
ok
end,
Conf = [{tc_status,{failed,timetrap_timeout}}],
- case catch do_end_tc_call(Mod,Func,{Pid,Error,[Conf]},Error) of
+ case catch do_end_tc_call(Mod,Func, Loc,
+ {Pid,Error,[Conf]},Error) of
{'EXIT',FwEndTCErr} ->
exit({fw_notify_done,end_tc,FwEndTCErr});
_ ->
@@ -1072,32 +1107,36 @@ job_proxy_msgloop() ->
%% or sends a message {failed, File, Line} to it's group_leader
run_test_case_eval(Mod, Func, Args0, Name, Ref, RunInit,
- TimetrapData, TCCallback) ->
- put(test_server_multiply_timetraps,TimetrapData),
+ TimetrapData, LogOpts, TCCallback) ->
+ put(test_server_multiply_timetraps, TimetrapData),
+ put(test_server_logopts, LogOpts),
{{Time,Value},Loc,Opts} =
case test_server_sup:framework_call(init_tc,[?pl2a(Mod),Func,Args0],
- {ok, Args0}) of
+ {ok,Args0}) of
{ok,Args} ->
run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback);
Error = {error,_Reason} ->
- NewResult = do_end_tc_call(Mod,Func,{Error,Args0},
+ Where = {Mod,Func},
+ NewResult = do_end_tc_call(Mod,Func, Where, {Error,Args0},
{skip,{failed,Error}}),
- {{0,NewResult},{Mod,Func},[]};
+ {{0,NewResult},Where,[]};
{fail,Reason} ->
- [Conf] = Args0,
- Conf1 = [{tc_status,{failed,Reason}} | Conf],
+ Conf = [{tc_status,{failed,Reason}} | hd(Args0)],
+ Where = {Mod,Func},
fw_error_notify(Mod, Func, Conf, Reason),
- NewResult = do_end_tc_call(Mod,Func, {{error,Reason},[Conf1]},
- {fail, Reason}),
- {{0,NewResult},{Mod,Func},[]};
+ NewResult = do_end_tc_call(Mod,Func, Where, {{error,Reason},[Conf]},
+ {fail,Reason}),
+ {{0,NewResult},Where,[]};
Skip = {skip,_Reason} ->
- NewResult = do_end_tc_call(Mod,Func,{Skip,Args0},Skip),
- {{0,NewResult},{Mod,Func},[]};
+ Where = {Mod,Func},
+ NewResult = do_end_tc_call(Mod,Func, Where, {Skip,Args0}, Skip),
+ {{0,NewResult},Where,[]};
{auto_skip,Reason} ->
- NewResult = do_end_tc_call(Mod, Func, {{skip,Reason},Args0},
- {skip, {fw_auto_skip,Reason}}),
- {{0,NewResult},{Mod,Func},[]}
+ Where = {Mod,Func},
+ NewResult = do_end_tc_call(Mod,Func, Where, {{skip,Reason},Args0},
+ {skip,{fw_auto_skip,Reason}}),
+ {{0,NewResult},Where,[]}
end,
exit({Ref,Time,Value,Loc,Opts}).
@@ -1111,59 +1150,81 @@ run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) ->
Skip = {skip,Reason} ->
Line = get_loc(),
Conf = [{tc_status,{skipped,Reason}}],
- NewRes = do_end_tc_call(Mod,Func,{Skip,[Conf]}, Skip),
+ NewRes = do_end_tc_call(Mod,Func, Line, {Skip,[Conf]}, Skip),
{{0,NewRes},Line,[]};
{skip_and_save,Reason,SaveCfg} ->
Line = get_loc(),
Conf = [{tc_status,{skipped,Reason}},{save_config,SaveCfg}],
- NewRes = do_end_tc_call(Mod, Func, {{skip, Reason}, [Conf]},
- {skip, Reason}),
+ NewRes = do_end_tc_call(Mod,Func, Line, {{skip,Reason},[Conf]},
+ {skip,Reason}),
{{0,NewRes},Line,[]};
+ FailTC = {fail,Reason} -> % user fails the testcase
+ EndConf = [{tc_status,{failed,Reason}} | hd(Args)],
+ fw_error_notify(Mod, Func, EndConf, Reason),
+ NewRes = do_end_tc_call(Mod,Func, {Mod,Func},
+ {{error,Reason},[EndConf]},
+ FailTC),
+ {{0,NewRes},{Mod,Func},[]};
{ok,NewConf} ->
put(test_server_init_or_end_conf,undefined),
%% call user callback function if defined
NewConf1 = user_callback(TCCallback, Mod, Func, init, NewConf),
%% save current state in controller loop
- group_leader() ! {set_curr_conf,{{Mod,Func},NewConf1}},
+ sync_send(group_leader(),set_curr_conf,{{Mod,Func},NewConf1},
+ 5000, fun() -> exit(no_answer_from_group_leader) end),
put(test_server_loc, {Mod,Func}),
%% execute the test case
{{T,Return},Loc} = {ts_tc(Mod, Func, [NewConf1]),get_loc()},
{EndConf,TSReturn,FWReturn} =
case Return of
{E,TCError} when E=='EXIT' ; E==failed ->
+ ModLoc = mod_loc(Loc),
fw_error_notify(Mod, Func, NewConf1,
- TCError, mod_loc(Loc)),
- {[{tc_status,{failed,TCError}}|NewConf1],
+ TCError, ModLoc),
+ {[{tc_status,{failed,TCError}},
+ {tc_fail_loc,ModLoc}|NewConf1],
Return,{error,TCError}};
SaveCfg={save_config,_} ->
{[{tc_status,ok},SaveCfg|NewConf1],Return,ok};
{skip_and_save,Why,SaveCfg} ->
Skip = {skip,Why},
- {[{tc_status,{skipped,Why}},{save_config,SaveCfg}|NewConf1],
+ {[{tc_status,{skipped,Why}},
+ {save_config,SaveCfg}|NewConf1],
Skip,Skip};
{skip,Why} ->
{[{tc_status,{skipped,Why}}|NewConf1],Return,Return};
_ ->
{[{tc_status,ok}|NewConf1],Return,ok}
end,
- %% clear current state in controller loop
- group_leader() ! {set_curr_conf,undefined},
%% call user callback function if defined
EndConf1 = user_callback(TCCallback, Mod, Func, 'end', EndConf),
+ %% update current state in controller loop
+ sync_send(group_leader(),set_curr_conf,EndConf1,
+ 5000, fun() -> exit(no_answer_from_group_leader) end),
{FWReturn1,TSReturn1,EndConf2} =
case end_per_testcase(Mod, Func, EndConf1) of
SaveCfg1={save_config,_} ->
- {FWReturn,TSReturn,[SaveCfg1|lists:keydelete(save_config, 1, EndConf1)]};
- {fail,ReasonToFail} -> % user has failed the testcase
+ {FWReturn,TSReturn,[SaveCfg1|lists:keydelete(save_config,1,
+ EndConf1)]};
+ {fail,ReasonToFail} ->
+ %% user has failed the testcase
fw_error_notify(Mod, Func, EndConf1, ReasonToFail),
{{error,ReasonToFail},{failed,ReasonToFail},EndConf1};
- {failed,{_,end_per_testcase,_}} = Failure -> % unexpected termination
+ {failed,{_,end_per_testcase,_}} = Failure when FWReturn == ok ->
+ %% unexpected termination in end_per_testcase
+ %% report this as the result to the framework
{Failure,TSReturn,EndConf1};
_ ->
+ %% test case result should be reported to framework
+ %% no matter the status of end_per_testcase
{FWReturn,TSReturn,EndConf1}
end,
+ %% clear current state in controller loop
+ sync_send(group_leader(),set_curr_conf,undefined,
+ 5000, fun() -> exit(no_answer_from_group_leader) end),
put(test_server_init_or_end_conf,undefined),
- case do_end_tc_call(Mod, Func, {FWReturn1,[EndConf2]}, TSReturn1) of
+ case do_end_tc_call(Mod,Func, Loc,
+ {FWReturn1,[EndConf2]}, TSReturn1) of
{failed,Reason} = NewReturn ->
fw_error_notify(Mod,Func,EndConf2, Reason),
{{T,NewReturn},{Mod,Func},[]};
@@ -1187,19 +1248,43 @@ run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) ->
%% call user callback function if defined
Return1 = user_callback(TCCallback, Mod, Func, 'end', Return),
{Return2,Opts} = process_return_val([Return1], Mod, Func,
- Args1, Loc, Return1),
+ Args1, {Mod,Func}, Return1),
{{T,Return2},Loc,Opts}
end.
-do_end_tc_call(M,F,Res,Return) ->
+do_end_tc_call(M,F, Loc, Res, Return) ->
+ FwMod = os:getenv("TEST_SERVER_FRAMEWORK"),
+ {Mod,Func} =
+ if FwMod == M ; FwMod == "undefined"; FwMod == false ->
+ {M,F};
+ is_list(Loc) and (length(Loc)>1) ->
+ %% If failure in other module (M) than suite, try locate
+ %% suite name in Loc list and call end_tc with Suite:TestCase
+ %% instead of M:F.
+ GetSuite = fun(S,TC) ->
+ case lists:reverse(atom_to_list(S)) of
+ [$E,$T,$I,$U,$S,$_|_] -> [{S,TC}];
+ _ -> []
+ end
+ end,
+ case lists:flatmap(fun({S,TC,_}) -> GetSuite(S,TC);
+ ({{S,TC},_}) -> GetSuite(S,TC);
+ ({S,TC}) -> GetSuite(S,TC);
+ (_) -> []
+ end, Loc) of
+ [] ->
+ {M,F};
+ [FoundSuite|_] ->
+ FoundSuite
+ end;
+ true ->
+ {M,F}
+ end,
+
Ref = make_ref(),
- case test_server_sup:framework_call(
- end_tc, [?pl2a(M),F,Res], Ref) of
- {fail,FWReason} ->
- {failed,FWReason};
- Ref ->
+ if FwMod == "ct_framework" ; FwMod == "undefined"; FwMod == false ->
case test_server_sup:framework_call(
- end_tc, [?pl2a(M),F,Res, Return], ok) of
+ end_tc, [?pl2a(Mod),Func,Res, Return], ok) of
{fail,FWReason} ->
{failed,FWReason};
ok ->
@@ -1212,8 +1297,14 @@ do_end_tc_call(M,F,Res,Return) ->
NewReturn ->
NewReturn
end;
- _ ->
- Return
+ true ->
+ case test_server_sup:framework_call(FwMod, end_tc,
+ [?pl2a(Mod),Func,Res], Ref) of
+ {fail,FWReason} ->
+ {failed,FWReason};
+ _Else ->
+ Return
+ end
end.
%% the return value is a list and we have to check if it contains
@@ -1231,7 +1322,7 @@ 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
- case do_end_tc_call(M,F,{ok,A}, Return) of
+ case do_end_tc_call(M, F, Loc, {ok,A}, Return) of
{failed, FWReason} = Failed ->
fw_error_notify(M,F,A, FWReason),
{Failed, []};
@@ -1248,8 +1339,9 @@ process_return_val1([Failed={E,TCError}|_], M,F,A=[Args], Loc, _, SaveOpts)
when E=='EXIT';
E==failed ->
fw_error_notify(M,F,A, TCError, mod_loc(Loc)),
- case do_end_tc_call(M,F,{{error,TCError},
- [[{tc_status,{failed,TCError}}|Args]]}, Failed) of
+ case do_end_tc_call(M,F, Loc, {{error,TCError},
+ [[{tc_status,{failed,TCError}}|Args]]},
+ Failed) of
{failed,FWReason} ->
{{failed,FWReason},SaveOpts};
NewReturn ->
@@ -1266,8 +1358,8 @@ process_return_val1([RetVal={Tag,_}|Opts], M,F,A, Loc, _, SaveOpts) when Tag==sk
process_return_val1(Opts, M,F,A, Loc, RetVal, SaveOpts);
process_return_val1([_|Opts], M,F,A, Loc, Final, SaveOpts) ->
process_return_val1(Opts, M,F,A, Loc, Final, SaveOpts);
-process_return_val1([], M,F,A, _Loc, Final, SaveOpts) ->
- case do_end_tc_call(M,F,{Final,A}, Final) of
+process_return_val1([], M,F,A, Loc, Final, SaveOpts) ->
+ case do_end_tc_call(M,F, Loc, {Final,A}, Final) of
{failed,FWReason} ->
{{failed,FWReason},SaveOpts};
NewReturn ->
@@ -1296,55 +1388,62 @@ init_per_testcase(Mod, Func, Args) ->
false -> code:load_file(Mod);
_ -> ok
end,
-%% init_per_testcase defined, returns new configuration
- case erlang:function_exported(Mod,init_per_testcase,2) of
+ case erlang:function_exported(Mod, init_per_testcase, 2) of
true ->
- case catch my_apply(Mod, init_per_testcase, [Func|Args]) of
- {'$test_server_ok',{Skip,Reason}} when Skip==skip;
- Skip==skipped ->
- {skip,Reason};
- {'$test_server_ok',Res={skip_and_save,_,_}} ->
- Res;
- {'$test_server_ok',NewConf} when is_list(NewConf) ->
- case lists:filter(fun(T) when is_tuple(T) -> false;
- (_) -> true end, NewConf) of
- [] ->
- {ok,NewConf};
- Bad ->
- group_leader() ! {printout,12,
- "ERROR! init_per_testcase has returned "
- "bad elements in Config: ~p\n",[Bad]},
- {skip,{failed,{Mod,init_per_testcase,bad_return}}}
- end;
- {'$test_server_ok',_Other} ->
- group_leader() ! {printout,12,
- "ERROR! init_per_testcase did not return "
- "a Config list.\n",[]},
- {skip,{failed,{Mod,init_per_testcase,bad_return}}};
- {'EXIT',Reason} ->
- Line = get_loc(),
- FormattedLoc = test_server_sup:format_loc(mod_loc(Line)),
- group_leader() ! {printout,12,
- "ERROR! init_per_testcase crashed!\n"
- "\tLocation: ~s\n\tReason: ~p\n",
- [FormattedLoc,Reason]},
- {skip,{failed,{Mod,init_per_testcase,Reason}}};
- Other ->
- Line = get_loc(),
- FormattedLoc = test_server_sup:format_loc(mod_loc(Line)),
- group_leader() ! {printout,12,
- "ERROR! init_per_testcase thrown!\n"
- "\tLocation: ~s\n\tReason: ~p\n",
- [FormattedLoc, Other]},
- {skip,{failed,{Mod,init_per_testcase,Other}}}
- end;
+ do_init_per_testcase(Mod, [Func|Args]);
false ->
-%% Optional init_per_testcase not defined
-%% keep quiet.
+ %% Optional init_per_testcase is not defined -- keep quiet.
[Config] = Args,
{ok, Config}
end.
+do_init_per_testcase(Mod, Args) ->
+ try apply(Mod, init_per_testcase, Args) of
+ {Skip,Reason} when Skip =:= skip; Skip =:= skipped ->
+ {skip,Reason};
+ {skip_and_save,_,_}=Res ->
+ Res;
+ NewConf when is_list(NewConf) ->
+ case lists:filter(fun(T) when is_tuple(T) -> false;
+ (_) -> true end, NewConf) of
+ [] ->
+ {ok,NewConf};
+ Bad ->
+ group_leader() ! {printout,12,
+ "ERROR! init_per_testcase has returned "
+ "bad elements in Config: ~p\n",[Bad]},
+ {skip,{failed,{Mod,init_per_testcase,bad_return}}}
+ end;
+ {fail,_Reason}=Res ->
+ Res;
+ _Other ->
+ group_leader() ! {printout,12,
+ "ERROR! init_per_testcase did not return "
+ "a Config list.\n",[]},
+ {skip,{failed,{Mod,init_per_testcase,bad_return}}}
+ catch
+ throw:Other ->
+ set_loc(erlang:get_stacktrace()),
+ Line = get_loc(),
+ FormattedLoc = test_server_sup:format_loc(mod_loc(Line)),
+ group_leader() ! {printout,12,
+ "ERROR! init_per_testcase thrown!\n"
+ "\tLocation: ~s\n\tReason: ~p\n",
+ [FormattedLoc, Other]},
+ {skip,{failed,{Mod,init_per_testcase,Other}}};
+ _:Reason0 ->
+ Stk = erlang:get_stacktrace(),
+ Reason = {Reason0,Stk},
+ set_loc(Stk),
+ Line = get_loc(),
+ FormattedLoc = test_server_sup:format_loc(mod_loc(Line)),
+ group_leader() ! {printout,12,
+ "ERROR! init_per_testcase crashed!\n"
+ "\tLocation: ~s\n\tReason: ~p\n",
+ [FormattedLoc,Reason]},
+ {skip,{failed,{Mod,init_per_testcase,Reason}}}
+ end.
+
end_per_testcase(Mod, Func, Conf) ->
case erlang:function_exported(Mod,end_per_testcase,2) of
true ->
@@ -1362,57 +1461,87 @@ end_per_testcase(Mod, Func, Conf) ->
do_end_per_testcase(Mod,EndFunc,Func,Conf) ->
put(test_server_init_or_end_conf,{EndFunc,Func}),
put(test_server_loc, {Mod,{EndFunc,Func}}),
- case catch my_apply(Mod, EndFunc, [Func,Conf]) of
- {'$test_server_ok',SaveCfg={save_config,_}} ->
+ try Mod:EndFunc(Func, Conf) of
+ {save_config,_}=SaveCfg ->
SaveCfg;
- {'$test_server_ok',{fail,_}=Fail} ->
+ {fail,_}=Fail ->
Fail;
- {'$test_server_ok',_} ->
- ok;
- {'EXIT',Reason} = Why ->
- comment(io_lib:format("<font color=\"red\">"
- "WARNING: ~w crashed!"
- "</font>\n",[EndFunc])),
+ _ ->
+ ok
+ catch
+ throw:Other ->
+ Comment0 = case read_comment() of
+ "" -> "";
+ Cmt -> Cmt ++ "<br>"
+ end,
+ set_loc(erlang:get_stacktrace()),
+ comment(io_lib:format("~s<font color=\"red\">"
+ "WARNING: ~w thrown!"
+ "</font>\n",[Comment0,EndFunc])),
group_leader() ! {printout,12,
- "WARNING: ~w crashed!\n"
+ "WARNING: ~w thrown!\n"
"Reason: ~p\n"
"Line: ~s\n",
- [EndFunc, Reason,
+ [EndFunc, Other,
test_server_sup:format_loc(
mod_loc(get_loc()))]},
- {failed,{Mod,end_per_testcase,Why}};
- Other ->
- comment(io_lib:format("<font color=\"red\">"
- "WARNING: ~w thrown!"
- "</font>\n",[EndFunc])),
+ {failed,{Mod,end_per_testcase,Other}};
+ Class:Reason ->
+ Stk = erlang:get_stacktrace(),
+ set_loc(Stk),
+ Why = case Class of
+ exit -> {'EXIT',Reason};
+ error -> {'EXIT',{Reason,Stk}}
+ end,
+ Comment0 = case read_comment() of
+ "" -> "";
+ Cmt -> Cmt ++ "<br>"
+ end,
+ comment(io_lib:format("~s<font color=\"red\">"
+ "WARNING: ~w crashed!"
+ "</font>\n",[Comment0,EndFunc])),
group_leader() ! {printout,12,
- "WARNING: ~w thrown!\n"
+ "WARNING: ~w crashed!\n"
"Reason: ~p\n"
"Line: ~s\n",
- [EndFunc, Other,
+ [EndFunc, Reason,
test_server_sup:format_loc(
mod_loc(get_loc()))]},
- {failed,{Mod,end_per_testcase,Other}}
+ {failed,{Mod,end_per_testcase,Why}}
end.
get_loc() ->
- case catch test_server_line:get_lines() of
- [] ->
- get(test_server_loc);
- {'EXIT',_} ->
- get(test_server_loc);
- Loc ->
- Loc
- end.
+ get(test_server_loc).
get_loc(Pid) ->
- {dictionary,Dict} = process_info(Pid, dictionary),
- lists:foreach(fun({Key,Val}) -> put(Key,Val) end,Dict),
+ [{current_stacktrace,Stk0},{dictionary,Dict}] =
+ process_info(Pid, [current_stacktrace,dictionary]),
+ lists:foreach(fun({Key,Val}) -> put(Key, Val) end, Dict),
+ Stk = [rewrite_loc_item(Loc) || Loc <- Stk0],
+ put(test_server_loc, Stk),
get_loc().
-get_mf([{M,F,_}|_]) -> {M,F};
-get_mf([{M,F}|_]) -> {M,F};
-get_mf(_) -> {undefined,undefined}.
+%% find the latest known Suite:Testcase
+get_mf(MFs) ->
+ get_mf(MFs, {undefined,undefined}).
+
+get_mf([MF|MFs], Found) when is_tuple(MF) ->
+ ModFunc = {Mod,_} = case MF of
+ {M,F,_} -> {M,F};
+ MF -> MF
+ end,
+ case is_suite(Mod) of
+ true -> ModFunc;
+ false -> get_mf(MFs, ModFunc)
+ end;
+get_mf(_, Found) ->
+ Found.
+
+is_suite(Mod) ->
+ case lists:reverse(atom_to_list(Mod)) of
+ "ETIUS" ++ _ -> true;
+ _ -> false
+ end.
mod_loc(Loc) ->
%% handle diff line num versions
@@ -1485,16 +1614,22 @@ lookup_config(Key,Config) ->
%% timer:tc/3
ts_tc(M, F, A) ->
Before = erlang:now(),
- Val = (catch my_apply(M, F, A)),
+ Result = try
+ apply(M, F, A)
+ catch
+ Type:Reason ->
+ Stk = erlang:get_stacktrace(),
+ set_loc(Stk),
+ case Type of
+ throw ->
+ {failed,{thrown,Reason}};
+ error ->
+ {'EXIT',{Reason,Stk}};
+ exit ->
+ {'EXIT',Reason}
+ end
+ end,
After = erlang:now(),
- Result = case Val of
- {'$test_server_ok', R} ->
- R; % test case ok
- {'EXIT',_Reason} = R ->
- R; % test case crashed
- Other ->
- {failed, {thrown,Other}} % test case was thrown
- end,
Elapsed =
(element(1,After)*1000000000000
+element(2,After)*1000000+element(3,After)) -
@@ -1502,8 +1637,12 @@ ts_tc(M, F, A) ->
+element(2,Before)*1000000+element(3,Before)),
{Elapsed, Result}.
-my_apply(M, F, A) ->
- {'$test_server_ok',apply(M, F, A)}.
+set_loc(Stk) ->
+ Loc = [rewrite_loc_item(I) || {_,_,_,_}=I <- Stk],
+ put(test_server_loc, Loc).
+
+rewrite_loc_item({M,F,_,Loc}) ->
+ {M,F,proplists:get_value(line, Loc, 0)}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1666,7 +1805,16 @@ adjusted_sleep(MSecs) ->
%% to read when using this function, rather than exit directly.
fail(Reason) ->
comment(cast_to_list(Reason)),
- exit({suite_failed,Reason}).
+ try
+ exit({suite_failed,Reason})
+ catch
+ Class:R ->
+ case erlang:get_stacktrace() of
+ [{?MODULE,fail,1,_}|Stk] -> ok;
+ Stk -> ok
+ end,
+ erlang:raise(Class, R, Stk)
+ end.
cast_to_list(X) when is_list(X) -> X;
cast_to_list(X) when is_atom(X) -> atom_to_list(X);
@@ -1680,7 +1828,16 @@ cast_to_list(X) -> lists:flatten(io_lib:format("~p", [X])).
%% Immediately calls exit. Included because test suites are easier
%% to read when using this function, rather than exit directly.
fail() ->
- exit(suite_failed).
+ try
+ exit(suite_failed)
+ catch
+ Class:R ->
+ case erlang:get_stacktrace() of
+ [{?MODULE,fail,0,_}|Stk] -> ok;
+ Stk -> ok
+ end,
+ erlang:raise(Class, R, Stk)
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% break(Comment) -> ok
@@ -1690,7 +1847,7 @@ fail() ->
break(Comment) ->
case erase(test_server_timetraps) of
undefined -> ok;
- List -> lists:foreach(fun(Ref) -> timetrap_cancel(Ref) end,List)
+ List -> lists:foreach(fun({Ref,_}) -> timetrap_cancel(Ref) end, List)
end,
io:format(user,
"\n\n\n--- SEMIAUTOMATIC TESTING ---"
@@ -1771,14 +1928,16 @@ timetrap(Timeout0) ->
{undefined,false} -> timetrap1(Timeout, false);
{undefined,_} -> timetrap1(Timeout, true);
{infinity,_} -> infinity;
+ {_Int,_Scale} when Timeout == infinity -> infinity;
{Int,Scale} -> timetrap1(Timeout*Int, Scale)
end.
timetrap1(Timeout, Scale) ->
- Ref = spawn_link(test_server_sup,timetrap,[Timeout,Scale,self()]),
+ TCPid = self(),
+ Ref = spawn_link(test_server_sup,timetrap,[Timeout,Scale,TCPid]),
case get(test_server_timetraps) of
- undefined -> put(test_server_timetraps,[Ref]);
- List -> put(test_server_timetraps,[Ref|List])
+ undefined -> put(test_server_timetraps,[{Ref,TCPid}]);
+ List -> put(test_server_timetraps,[{Ref,TCPid}|List])
end,
Ref.
@@ -1791,14 +1950,16 @@ ensure_timetrap(Config) ->
undefined -> ok;
Garbage ->
erase(test_server_default_timetrap),
- format("=== WARNING: garbage in test_server_default_timetrap: ~p~n",
+ format("=== WARNING: garbage in "
+ "test_server_default_timetrap: ~p~n",
[Garbage])
end,
DTmo = case lists:keysearch(default_timeout,1,Config) of
{value,{default_timeout,Tmo}} -> Tmo;
_ -> ?DEFAULT_TIMETRAP_SECS
end,
- format("=== test_server setting default timetrap of ~p seconds~n",
+ format("=== test_server setting default "
+ "timetrap of ~p seconds~n",
[DTmo]),
put(test_server_default_timetrap, timetrap(seconds(DTmo)))
end.
@@ -1810,11 +1971,13 @@ cancel_default_timetrap() ->
TimeTrap when is_pid(TimeTrap) ->
timetrap_cancel(TimeTrap),
erase(test_server_default_timetrap),
- format("=== test_server canceled default timetrap since another timetrap was set~n"),
+ format("=== test_server canceled default timetrap "
+ "since another timetrap was set~n"),
ok;
Garbage ->
erase(test_server_default_timetrap),
- format("=== WARNING: garbage in test_server_default_timetrap: ~p~n",
+ format("=== WARNING: garbage in "
+ "test_server_default_timetrap: ~p~n",
[Garbage]),
error
end.
@@ -1826,10 +1989,54 @@ time_ms({seconds,N}) -> seconds(N);
time_ms({Other,_N}) ->
format("=== ERROR: Invalid time specification: ~p. "
"Should be seconds, minutes, or hours.~n", [Other]),
- exit({invalid_time_spec,Other});
+ exit({invalid_time_format,Other});
time_ms(Ms) when is_integer(Ms) -> Ms;
-time_ms(Other) -> exit({invalid_time_spec,Other}).
+time_ms(infinity) -> infinity;
+time_ms(Fun) when is_function(Fun) ->
+ time_ms_apply(Fun);
+time_ms({M,F,A}=MFA) when is_atom(M), is_atom(F), is_list(A) ->
+ time_ms_apply(MFA);
+time_ms(Other) -> exit({invalid_time_format,Other}).
+
+time_ms_apply(Func) ->
+ time_ms_apply(Func, [5000,30000,60000,infinity]).
+
+time_ms_apply(Func, TOs) ->
+ Apply = fun() ->
+ case Func of
+ {M,F,A} ->
+ exit({self(),apply(M, F, A)});
+ Fun ->
+ exit({self(),Fun()})
+ end
+ end,
+ Pid = spawn(Apply),
+ Ref = monitor(process, Pid),
+ time_ms_wait(Func, Pid, Ref, TOs).
+time_ms_wait(Func, Pid, Ref, [TO|TOs]) ->
+ receive
+ {'DOWN',Ref,process,Pid,{Pid,Result}} ->
+ time_ms_check(Result);
+ {'DOWN',Ref,process,Pid,Error} ->
+ exit({timetrap_error,Error})
+ after
+ TO ->
+ format("=== WARNING: No return from timetrap function ~p~n", [Func]),
+ time_ms_wait(Func, Pid, Ref, TOs)
+ end;
+%% this clause will never execute if 'infinity' is in TOs list, that's ok!
+time_ms_wait(Func, Pid, Ref, []) ->
+ demonitor(Ref),
+ exit(Pid, kill),
+ exit({timetrap_error,{no_return_from_timetrap_function,Func}}).
+
+time_ms_check(MFA = {M,F,A}) when is_atom(M), is_atom(F), is_list(A) ->
+ exit({invalid_time_format,MFA});
+time_ms_check(Fun) when is_function(Fun) ->
+ exit({invalid_time_format,Fun});
+time_ms_check(Other) ->
+ time_ms(Other).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% timetrap_cancel(Handle) -> ok
@@ -1841,11 +2048,29 @@ timetrap_cancel(infinity) ->
timetrap_cancel(Handle) ->
case get(test_server_timetraps) of
undefined -> ok;
- [Handle] -> erase(test_server_timetraps);
- List -> put(test_server_timetraps,lists:delete(Handle,List))
+ [{Handle,_}] -> erase(test_server_timetraps);
+ Timers -> put(test_server_timetraps,
+ lists:keydelete(Handle, 1, Timers))
end,
test_server_sup:timetrap_cancel(Handle).
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% timetrap_cancel() -> ok
+%%
+%% Cancels timetrap for current test case.
+timetrap_cancel() ->
+ case get(test_server_timetraps) of
+ undefined ->
+ ok;
+ Timers ->
+ case lists:keysearch(self(), 2, Timers) of
+ {value,{Handle,_}} ->
+ timetrap_cancel(Handle);
+ _ ->
+ ok
+ end
+ end.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% hours(N) -> Milliseconds
%% minutes(N) -> Milliseconds
@@ -1859,6 +2084,19 @@ hours(N) -> trunc(N * 1000 * 60 * 60).
minutes(N) -> trunc(N * 1000 * 60).
seconds(N) -> trunc(N * 1000).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% sync_send(Pid,Tag,Msg,Timeout,DoAfter) -> Result
+%%
+sync_send(Pid,Tag,Msg,Timeout,DoAfter) ->
+ Pid ! {Tag,self(),Msg},
+ receive
+ {Pid,Tag,Result} ->
+ Result
+ after Timeout ->
+ DoAfter()
+ end.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% timecall(M,F,A) -> {Time,Val}
%% Time = float()
@@ -2245,6 +2483,21 @@ comment(String) ->
group_leader() ! {comment,String},
ok.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% read_comment() -> string()
+%%
+%% Read the current comment string stored in
+%% state during test case execution.
+read_comment() ->
+ MsgLooper = group_leader(),
+ MsgLooper ! {read_comment,self()},
+ receive
+ {MsgLooper,read_comment,Comment} ->
+ Comment
+ after
+ 5000 ->
+ ""
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% os_type() -> OsType
diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl
index 30d7314058..4fad86d16d 100644
--- a/lib/test_server/src/test_server_ctrl.erl
+++ b/lib/test_server/src/test_server_ctrl.erl
@@ -173,7 +173,7 @@
%%% TEST_SERVER INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-export([output/2, print/2, print/3, print_timestamp/2]).
-export([start_node/3, stop_node/1, wait_for_node/1, is_release_available/1]).
--export([format/1, format/2, format/3]).
+-export([format/1, format/2, format/3, to_string/1]).
-export([get_target_info/0]).
-export([get_hosts/0]).
-export([get_target_os_type/0]).
@@ -1297,6 +1297,7 @@ terminate(_Reason, State) ->
end,
kill_all_jobs(State#state.jobs),
test_server_node:stop(State#state.target_info),
+ test_server_h:restore(),
ok.
kill_all_jobs([{_Name,JobPid}|Jobs]) ->
@@ -1349,6 +1350,10 @@ init_tester(Mod, Func, Args, Dir, Name, {SumLev,MajLev,MinLev},
put(test_server_minor_level, MinLev),
put(test_server_random_seed, proplists:get_value(random_seed, ExtraTools)),
put(test_server_testcase_callback, TCCallback),
+ %% before first print, read and set logging options
+ LogOpts = test_server_sup:framework_call(get_logopts, [], []),
+ put(test_server_logopts, LogOpts),
+ put(test_server_log_nl, not lists:member(no_nl, LogOpts)),
StartedExtraTools = start_extra_tools(ExtraTools),
{TimeMy,Result} = ts_tc(Mod, Func, Args),
put(test_server_common_io_handler, undefined),
@@ -1664,6 +1669,11 @@ do_test_cases(TopCases, SkipCases,
Config, TimetrapData) when is_list(TopCases),
is_tuple(TimetrapData) ->
start_log_file(),
+ FwMod =
+ case os:getenv("TEST_SERVER_FRAMEWORK") of
+ FW when FW =:= false; FW =:= "undefined" -> ?MODULE;
+ FW -> list_to_atom(FW)
+ end,
case collect_all_cases(TopCases, SkipCases) of
{error,Why} ->
print(1, "Error starting: ~p", [Why]),
@@ -1676,11 +1686,11 @@ do_test_cases(TopCases, SkipCases,
put(test_server_cases, N),
put(test_server_case_num, 0),
TestSpec =
- add_init_and_end_per_suite(TestSpec0, undefined, undefined),
-
+ add_init_and_end_per_suite(TestSpec0, undefined, undefined, FwMod),
TI = get_target_info(),
- print(1, "Starting test~s", [print_if_known(N, {", ~w test cases",[N]},
- {" (with repeated test cases)",[]})]),
+ print(1, "Starting test~s",
+ [print_if_known(N, {", ~w test cases",[N]},
+ {" (with repeated test cases)",[]})]),
Test = get(test_server_name),
test_server_sup:framework_call(report, [tests_start,{Test,N}]),
@@ -1709,13 +1719,12 @@ do_test_cases(TopCases, SkipCases,
print(html, "<br>Used Erlang ~s in <tt>~s</tt>.\n",
[erlang:system_info(version), code:root_dir()]),
- case os:getenv("TEST_SERVER_FRAMEWORK") of
- FW when FW =:= false; FW =:= "undefined" ->
+ if FwMod == ?MODULE ->
print(html, "<p>Target:<br>\n"),
print_who(TI#target_info.host, TI#target_info.username),
print(html, "<br>Used Erlang ~s in <tt>~s</tt>.\n",
[TI#target_info.version, TI#target_info.root_dir]);
- _ ->
+ true ->
case test_server_sup:framework_call(target_info, []) of
TargetInfo when is_list(TargetInfo),
length(TargetInfo) > 0 ->
@@ -1812,6 +1821,9 @@ start_log_file() ->
ok = file:make_dir(PrivDir),
put(test_server_priv_dir,PrivDir++"/"),
print_timestamp(13,"Suite started at "),
+
+ LogInfo = [{topdir,Dir},{rundir,lists:flatten(TestDir)}],
+ test_server_sup:framework_call(report, [loginfo,LogInfo]),
ok.
make_html_link(LinkName, Target, Explanation) ->
@@ -1881,11 +1893,12 @@ start_minor_log_file1(Mod, Func, LogDir, AbsName) ->
[]),
SrcListing = downcase(cast_to_list(Mod)) ++ ?src_listing_ext,
- case filelib:is_file(filename:join(LogDir, SrcListing)) of
- true ->
+ case {filelib:is_file(filename:join(LogDir, SrcListing)),
+ lists:member(no_src, get(test_server_logopts))} of
+ {true,false} ->
print(Lev, "<a href=\"~s#~s\">source code for ~p:~p/1</a>\n",
[SrcListing,Func,Mod,Func]);
- false -> ok
+ _ -> ok
end,
io:fwrite(Fd, "<pre>\n", []),
@@ -1925,7 +1938,6 @@ html_convert_modules(TestSpec, _Config) ->
copy_html_files(get(test_server_dir), get(test_server_log_dir_base)).
%% Retrieve a list of modules out of the test spec.
-
html_isolate_modules(List) -> html_isolate_modules(List, sets:new()).
html_isolate_modules([], Set) -> sets:to_list(Set);
@@ -1939,37 +1951,56 @@ html_isolate_modules([{Mod,_Case,_Args}|Cases], Set) ->
html_isolate_modules(Cases, sets:add_element(Mod, Set)).
%% Given a list of modules, convert each module's source code to HTML.
-
html_convert_modules([Mod|Mods]) ->
case code:which(Mod) of
Path when is_list(Path) ->
SrcFile = filename:rootname(Path) ++ ".erl",
- DestDir = get(test_server_dir),
- Name = atom_to_list(Mod),
- DestFile = filename:join(DestDir, downcase(Name) ++ ?src_listing_ext),
- html_possibly_convert(SrcFile, DestFile),
- html_convert_modules(Mods);
- _Other -> ok
+ FoundSrcFile =
+ case file:read_file_info(SrcFile) of
+ {ok,SInfo} ->
+ {SrcFile,SInfo};
+ {error,_} ->
+ ModInfo = Mod:module_info(compile),
+ case proplists:get_value(source, ModInfo) of
+ undefined ->
+ undefined;
+ OtherSrcFile ->
+ case file:read_file_info(OtherSrcFile) of
+ {ok,SInfo} ->
+ {OtherSrcFile,SInfo};
+ {error,_} ->
+ undefined
+ end
+ end
+ end,
+ case FoundSrcFile of
+ undefined ->
+ html_convert_modules(Mods);
+ {SrcFile1,SrcFileInfo} ->
+ DestDir = get(test_server_dir),
+ Name = atom_to_list(Mod),
+ DestFile = filename:join(DestDir,
+ downcase(Name)++?src_listing_ext),
+ html_possibly_convert(SrcFile1, SrcFileInfo, DestFile),
+ html_convert_modules(Mods)
+ end;
+ _Other ->
+ html_convert_modules(Mods)
end;
html_convert_modules([]) -> ok.
%% Convert source code to HTML if possible and needed.
-
-html_possibly_convert(Src, Dest) ->
- case file:read_file_info(Src) of
- {ok,SInfo} ->
- case file:read_file_info(Dest) of
- {error,_Reason} -> % no dest file
- erl2html2:convert(Src, Dest);
- {ok,DInfo} when DInfo#file_info.mtime < SInfo#file_info.mtime ->
- erl2html2:convert(Src, Dest);
- {ok,_DInfo} -> ok % dest file up to date
- end;
- {error,_Reason} -> ok % no source code found
+html_possibly_convert(Src, SrcInfo, Dest) ->
+ case file:read_file_info(Dest) of
+ {error,_Reason} -> % no dest file
+ erl2html2:convert(Src, Dest);
+ {ok,DestInfo} when DestInfo#file_info.mtime < SrcInfo#file_info.mtime ->
+ erl2html2:convert(Src, Dest);
+ {ok,_DestInfo} ->
+ ok % dest file up to date
end.
%% Copy all HTML files in InDir to OutDir.
-
copy_html_files(InDir, OutDir) ->
Files = filelib:wildcard(filename:join(InDir, "*" ++ ?src_listing_ext)),
lists:foreach(fun (Src) -> copy_html_file(Src, OutDir) end, Files).
@@ -1984,54 +2015,69 @@ copy_html_file(Src, DestDir) ->
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% add_init_and_end_per_suite(TestSpec, Mod, Ref) -> NewTestSpec
+%% add_init_and_end_per_suite(TestSpec, Mod, Ref, FwMod) -> NewTestSpec
%%
%% Expands TestSpec with an initial init_per_suite, and a final
%% end_per_suite element, per each discovered suite in the list.
-add_init_and_end_per_suite([{make,_,_}=Case|Cases], LastMod, LastRef) ->
- [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef)];
-add_init_and_end_per_suite([{skip_case,{{Mod,all},_}}=Case|Cases], LastMod, LastRef)
- when Mod =/= LastMod ->
+add_init_and_end_per_suite([{make,_,_}=Case|Cases], LastMod, LastRef, FwMod) ->
+ [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)];
+add_init_and_end_per_suite([{skip_case,{{Mod,all},_}}=Case|Cases], LastMod,
+ LastRef, FwMod) when Mod =/= LastMod ->
{PreCases, NextMod, NextRef} =
do_add_end_per_suite_and_skip(LastMod, LastRef, Mod),
- PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef)];
-add_init_and_end_per_suite([{skip_case,{{Mod,_},_}}=Case|Cases], LastMod, LastRef)
- when Mod =/= LastMod ->
+ PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)];
+add_init_and_end_per_suite([{skip_case,{{Mod,_},_}}=Case|Cases], LastMod,
+ LastRef, FwMod) when Mod =/= LastMod ->
{PreCases, NextMod, NextRef} =
do_add_init_and_end_per_suite(LastMod, LastRef, Mod),
- PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef)];
-add_init_and_end_per_suite([{skip_case,{conf,_,{Mod,_},_}}=Case|Cases], LastMod, LastRef)
- when Mod =/= LastMod ->
+ PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)];
+add_init_and_end_per_suite([{skip_case,{conf,_,{Mod,_},_}}=Case|Cases], LastMod,
+ LastRef, FwMod) when Mod =/= LastMod ->
{PreCases, NextMod, NextRef} =
do_add_init_and_end_per_suite(LastMod, LastRef, Mod),
- PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef)];
-add_init_and_end_per_suite([{skip_case,_}=Case|Cases], LastMod, LastRef) ->
- [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef)];
-add_init_and_end_per_suite([{conf,_,_,{Mod,_}}=Case|Cases], LastMod, LastRef)
- when Mod =/= LastMod ->
+ PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)];
+add_init_and_end_per_suite([{skip_case,_}=Case|Cases], LastMod, LastRef, FwMod) ->
+ [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)];
+add_init_and_end_per_suite([{conf,Ref,Props,{FwMod,Func}}=Case|Cases], LastMod,
+ LastRef, FwMod) ->
+ %% if Mod == FwMod, this conf test is (probably) a test case group where
+ %% the init- and end-functions are missing in the suite, and if so,
+ %% the suite name should be stored as {suite,Suite} in Props
+ case proplists:get_value(suite, Props) of
+ Suite when Suite =/= undefined, Suite =/= LastMod ->
+ {PreCases, NextMod, NextRef} =
+ do_add_init_and_end_per_suite(LastMod, LastRef, Suite),
+ Case1 = {conf,Ref,proplists:delete(suite,Props),{FwMod,Func}},
+ PreCases ++ [Case1|add_init_and_end_per_suite(Cases, NextMod,
+ NextRef, FwMod)];
+ _ ->
+ [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)]
+ end;
+add_init_and_end_per_suite([{conf,_,_,{Mod,_}}=Case|Cases], LastMod,
+ LastRef, FwMod) when Mod =/= LastMod, Mod =/= FwMod ->
{PreCases, NextMod, NextRef} =
do_add_init_and_end_per_suite(LastMod, LastRef, Mod),
- PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef)];
-add_init_and_end_per_suite([{conf,_,_,_}=Case|Cases], LastMod, LastRef) ->
- [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef)];
-add_init_and_end_per_suite([{Mod,_}=Case|Cases], LastMod, LastRef)
- when Mod =/= LastMod ->
+ PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)];
+add_init_and_end_per_suite([{conf,_,_,_}=Case|Cases], LastMod, LastRef, FwMod) ->
+ [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)];
+add_init_and_end_per_suite([{Mod,_}=Case|Cases], LastMod, LastRef, FwMod)
+ when Mod =/= LastMod, Mod =/= FwMod ->
{PreCases, NextMod, NextRef} =
do_add_init_and_end_per_suite(LastMod, LastRef, Mod),
- PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef)];
-add_init_and_end_per_suite([{Mod,_,_}=Case|Cases], LastMod, LastRef)
- when Mod =/= LastMod ->
+ PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)];
+add_init_and_end_per_suite([{Mod,_,_}=Case|Cases], LastMod, LastRef, FwMod)
+ when Mod =/= LastMod, Mod =/= FwMod ->
{PreCases, NextMod, NextRef} =
do_add_init_and_end_per_suite(LastMod, LastRef, Mod),
- PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef)];
-add_init_and_end_per_suite([Case|Cases], LastMod, LastRef)->
- [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef)];
-add_init_and_end_per_suite([], _LastMod, undefined) ->
+ PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)];
+add_init_and_end_per_suite([Case|Cases], LastMod, LastRef, FwMod)->
+ [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)];
+add_init_and_end_per_suite([], _LastMod, undefined, _FwMod) ->
[];
-add_init_and_end_per_suite([], _LastMod, skipped_suite) ->
+add_init_and_end_per_suite([], _LastMod, skipped_suite, _FwMod) ->
[];
-add_init_and_end_per_suite([], LastMod, LastRef) ->
+add_init_and_end_per_suite([], LastMod, LastRef, _FwMod) ->
[{conf,LastRef,[],{LastMod,end_per_suite}}].
do_add_init_and_end_per_suite(LastMod, LastRef, Mod) ->
@@ -2080,7 +2126,12 @@ run_test_cases(TestSpec, Config, TimetrapData) ->
maybe_open_job_sock(),
- html_convert_modules(TestSpec, Config),
+ case lists:member(no_src, get(test_server_logopts)) of
+ true ->
+ ok;
+ false ->
+ html_convert_modules(TestSpec, Config)
+ end,
run_test_cases_loop(TestSpec, [Config], TimetrapData, [], []),
@@ -2289,7 +2340,8 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases],
handle_test_case_io_and_status(),
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}]),
+ test_server_sup:framework_call(report, [tc_auto_skip,
+ {?pl2a(Mod),Func,Comment}]),
run_test_cases_loop(Cases, Config, TimetrapData, ParentMode,
delete_status(Ref, Status));
_ ->
@@ -2297,7 +2349,8 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases],
%% parallel group (io buffering is active)
wait_for_cases(Ref),
{Mod,Func} = skip_case(auto, Ref, 0, Case, Comment, true, SkipMode),
- test_server_sup:framework_call(report, [tc_auto_skip,{?pl2a(Mod),Func,Comment}]),
+ test_server_sup:framework_call(report, [tc_auto_skip,
+ {?pl2a(Mod),Func,Comment}]),
case CurrIOHandler of
{Ref,_} ->
%% current_io_handler was set by start conf of this
@@ -3938,8 +3991,11 @@ progress(ok, _CaseNum, Mod, Func, _Loc, RetVal, Time,
case RetVal of
{comment,RetComment} ->
String = to_string(RetComment),
+ HtmlCmt = test_server_sup:framework_call(format_comment,
+ [String],
+ String),
print(major, "=result ok: ~s", [String]),
- "<td>" ++ String ++ "</td>";
+ "<td>" ++ HtmlCmt ++ "</td>";
_ ->
print(major, "=result ok", []),
case Comment0 of
@@ -4324,14 +4380,18 @@ output_to_fd(Fd, [$=|Msg], internal) ->
io:put_chars(Fd, [$=]),
io:put_chars(Fd, Msg),
io:put_chars(Fd, "\n");
+
output_to_fd(Fd, Msg, internal) ->
io:put_chars(Fd, [$=,$=,$=,$ ]),
io:put_chars(Fd, Msg),
io:put_chars(Fd, "\n");
+
output_to_fd(Fd, Msg, _Sender) ->
io:put_chars(Fd, Msg),
- io:put_chars(Fd, "\n").
-
+ case get(test_server_log_nl) of
+ false -> ok;
+ _ -> io:put_chars(Fd, "\n")
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% timestamp_filename_get(Leader) -> string()
@@ -4644,7 +4704,7 @@ collect_case_invoke(Mod, Case, MFA, St) ->
collect_subcases(Mod, Case, MFA, St, Suite)
end;
_ ->
- Suite = test_server_sup:framework_call(get_suite, [?pl2a(Mod),Case],[]),
+ Suite = test_server_sup:framework_call(get_suite, [?pl2a(Mod),Case], []),
collect_subcases(Mod, Case, MFA, St, Suite)
end.
@@ -4653,13 +4713,13 @@ collect_subcases(Mod, Case, MFA, St, Suite) ->
[] when Case == all -> {ok,[],St};
[] when element(1, Case) == conf -> {ok,[],St};
[] -> {ok,[MFA],St};
-%%%! --- START Kept for backwards compatibilty ---
+%%%! --- START Kept for backwards compatibility ---
%%%! Requirements are not used
{req,ReqList} ->
collect_case_deny(Mod, Case, MFA, ReqList, [], St);
{req,ReqList,SubCases} ->
collect_case_deny(Mod, Case, MFA, ReqList, SubCases, St);
-%%%! --- END Kept for backwards compatibilty ---
+%%%! --- END Kept for backwards compatibility ---
{Skip,Reason} when Skip==skip; Skip==skipped ->
{ok,[{skip_case,{MFA,Reason}}],St};
{error,Reason} ->
diff --git a/lib/test_server/src/test_server_line.erl b/lib/test_server/src/test_server_line.erl
deleted file mode 100644
index 848a9c23dd..0000000000
--- a/lib/test_server/src/test_server_line.erl
+++ /dev/null
@@ -1,387 +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(test_server_line).
-
-%% User interface
--export([get_lines/0]).
--export([clear/0]).
-
-%% Parse transform functions
--export([parse_transform/2]).
--export(['$test_server_line'/3]).
--export(['$test_server_lineQ'/3]).
--export([trace_line/3]).
-
--define(TEST_SERVER_LINE_SIZE, 10).
-%-define(STORAGE_FUNCTION, '$test_server_line').
--define(STORAGE_FUNCTION, '$test_server_lineQ').
-
--include("test_server.hrl").
-
--record(vars, {module, % atom() Module name
- function, % atom() Function name
- arity, % int() Function arity
- lines, % [int()] seen lines
- is_guard=false, % boolean()
- no_lines=[], % [{atom(),integer()}]
- % Functions to exclude
- line_trace=false
- }).
-
-
-
-
-%% Process dictionary littering variant
-%%
-
-'$test_server_line'(Mod, Func, Line) ->
- {Prev,Next} =
- case get('$test_server_line') of
- I when is_integer(I) ->
- if 1 =< I, I < ?TEST_SERVER_LINE_SIZE -> {I,I+1};
- true -> {?TEST_SERVER_LINE_SIZE,1}
- end;
- _ -> {?TEST_SERVER_LINE_SIZE,1}
- end,
- PrevTag = {'$test_server_line',Prev},
- case get(PrevTag) of
- {Mod,Func,_} -> put(PrevTag, {Mod,Func,Line});
- _ ->
- put({'$test_server_line',Next}, {Mod,Func,Line}),
- put('$test_server_line', Next)
- end, ok.
-
-test_server_line_get() ->
- case get('$test_server_line') of
- I when is_integer(I), 1 =< I, I =< ?TEST_SERVER_LINE_SIZE ->
- test_server_line_get_1(?TEST_SERVER_LINE_SIZE, I, []);
- _ -> []
- end.
-
-test_server_line_get_1(0, _I, R) ->
- R;
-test_server_line_get_1(Cnt, I, R) ->
- J = if I < ?TEST_SERVER_LINE_SIZE -> I+1;
- true -> 1 end,
- case get({'$test_server_line',J}) of
- undefined ->
- %% Less than ?TEST_SERVER_LINE_SIZE number of lines stored
- %% Start from line 1 and stop at actutual number of lines
- case get({'$test_server_line',1}) of
- undefined -> R; % no lines at all stored
- E -> test_server_line_get_1(I-1,1,[E|R])
- end;
- E ->
- test_server_line_get_1(Cnt-1, J, [E|R])
- end.
-
-test_server_line_clear() ->
- Is = lists:seq(1,?TEST_SERVER_LINE_SIZE),
- lists:foreach(fun (I) -> erase({'$test_server_line',I}) end, Is),
- erase('$test_server_line'),
- ok.
-
-
-%% Queue variant, uses just one process dictionary entry
-%%
-
-'$test_server_lineQ'(Mod, Func, Line) ->
- case get('$test_server_lineQ') of
- {I,Q} when is_integer(I), 1 =< I, I =< ?TEST_SERVER_LINE_SIZE ->
- case queue:head(Q) of
- {Mod,Func,_} ->
- %% Replace queue head
- put('$test_server_lineQ',
- {I,queue:cons({Mod,Func,Line}, queue:tail(Q))});
- _ when I < ?TEST_SERVER_LINE_SIZE ->
- put('$test_server_lineQ',
- {I+1,queue:cons({Mod,Func,Line}, Q)});
- _ ->
- %% Waste last in queue
- put('$test_server_lineQ',
- {I,queue:cons({Mod,Func,Line}, queue:lait(Q))})
- end;
- _ ->
- Q = queue:new(),
- put('$test_server_lineQ', {1,queue:cons({Mod,Func,Line}, Q)})
- end, ok.
-
-%test_server_lineQ_get() ->
-% case get('$test_server_lineQ') of
-% {I,Q} when integer(I), 1 =< I, I =< ?TEST_SERVER_LINE_SIZE ->
-% queue:to_list(Q);
-% _ -> []
-% end.
-
-test_server_lineQ_clear() ->
- erase('$test_server_lineQ'),
- ok.
-
-
-%% Get line - check if queue or dictionary is used, then get the lines
-%%
-
-get_lines() ->
- case get('$test_server_lineQ') of
- {I,Q} when is_integer(I), 1 =< I, I =< ?TEST_SERVER_LINE_SIZE ->
- queue:to_list(Q);
- _ ->
- test_server_line_get()
- end.
-
-%% Clear all dictionary entries
-%%
-clear() ->
- test_server_line_clear(),
- test_server_lineQ_clear().
-
-
-trace_line(Mod,Func,Line) ->
- io:format(lists:concat([Mod,":",Func,",",integer_to_list(Line),": ~p"]),
- [erlang:now()]).
-
-
-%%%=================================================================
-%%%========= **** PARSE TRANSFORM **** ========================
-%%%=================================================================
-parse_transform(Forms, _Options) ->
- transform(Forms, _Options).
-
-%% forms(Fs) -> lists:map(fun (F) -> form(F) end, Fs).
-
-transform(Forms, _Options)->
- Vars0 = #vars{},
- {ok, MungedForms, _Vars} = transform(Forms, [], Vars0),
- MungedForms.
-
-
-transform([Form|Forms], MungedForms, Vars) ->
- case munge(Form, Vars) of
- ignore ->
- transform(Forms, MungedForms, Vars);
- {MungedForm, Vars2} ->
- transform(Forms, [MungedForm|MungedForms], Vars2)
- end;
-transform([], MungedForms, Vars) ->
- {ok, lists:reverse(MungedForms), Vars}.
-
-%% This code traverses the abstract code, stored as the abstract_code
-%% chunk in the BEAM file, as described in absform(3) for Erlang/OTP R8B
-%% (Vsn=abstract_v2).
-%% The abstract format after preprocessing differs slightly from the abstract
-%% format given eg using epp:parse_form, this has been noted in comments.
-munge(Form={attribute,_,module,Module}, Vars) ->
- Vars2 = Vars#vars{module=Module},
- {Form, Vars2};
-
-munge(Form={attribute,_,no_lines,Funcs}, Vars) ->
- Vars2 = Vars#vars{no_lines=Funcs},
- {Form, Vars2};
-
-munge(Form={attribute,_,line_trace,_}, Vars) ->
- Vars2 = Vars#vars{line_trace=true},
- {Form, Vars2};
-
-munge({function,0,module_info,_Arity,_Clauses}, _Vars) ->
- ignore; % module_info will be added again when the forms are recompiled
-munge(Form = {function,Line,Function,Arity,Clauses}, Vars) ->
- case lists:member({Function,Arity},Vars#vars.no_lines) of
- true ->
- %% Line numbers in this function shall not be stored
- {Form,Vars};
- false ->
- Vars2 = Vars#vars{function=Function,
- arity=Arity,
- lines=[]},
- {MungedClauses, Vars3} = munge_clauses(Clauses, Vars2, []),
- {{function,Line,Function,Arity,MungedClauses}, Vars3}
- end;
-munge(Form, Vars) -> % attributes
- {Form, Vars}.
-
-munge_clauses([{clause,Line,Pattern,Guards,Body}|Clauses], Vars, MClauses) ->
- {MungedGuards, _Vars} = munge_exprs(Guards, Vars#vars{is_guard=true},[]),
- {MungedBody, Vars2} = munge_body(Body, Vars, []),
- munge_clauses(Clauses, Vars2,
- [{clause,Line,Pattern,MungedGuards,MungedBody}|
- MClauses]);
-munge_clauses([], Vars, MungedClauses) ->
- {lists:reverse(MungedClauses), Vars}.
-
-munge_body([Expr|Body], Vars, MungedBody) ->
- %% Here is the place to add a call to storage function!
- Line = element(2, Expr),
- Lines = Vars#vars.lines,
- case lists:member(Line,Lines) of
- true -> % already a bump at this line!
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- munge_body(Body, Vars2, [MungedExpr|MungedBody]);
- false ->
- Bump = {call, 0, {remote,0,
- {atom,0,?MODULE},
- {atom,0,?STORAGE_FUNCTION}},
- [{atom,0,Vars#vars.module},
- {atom, 0, Vars#vars.function},
- {integer, 0, Line}]},
- Lines2 = [Line|Lines],
-
- {MungedExpr, Vars2} = munge_expr(Expr, Vars#vars{lines=Lines2}),
- MungedBody2 =
- if Vars#vars.line_trace ->
- LineTrace = {call, 0, {remote,0,
- {atom,0,?MODULE},
- {atom,0,trace_line}},
- [{atom,0,Vars#vars.module},
- {atom, 0, Vars#vars.function},
- {integer, 0, Line}]},
- [MungedExpr,LineTrace,Bump|MungedBody];
- true ->
- [MungedExpr,Bump|MungedBody]
- end,
- munge_body(Body, Vars2, MungedBody2)
- end;
-munge_body([], Vars, MungedBody) ->
- {lists:reverse(MungedBody), Vars}.
-
-munge_expr({match,Line,ExprL,ExprR}, Vars) ->
- {MungedExprL, Vars2} = munge_expr(ExprL, Vars),
- {MungedExprR, Vars3} = munge_expr(ExprR, Vars2),
- {{match,Line,MungedExprL,MungedExprR}, Vars3};
-munge_expr({tuple,Line,Exprs}, Vars) ->
- {MungedExprs, Vars2} = munge_exprs(Exprs, Vars, []),
- {{tuple,Line,MungedExprs}, Vars2};
-munge_expr({record,Line,Expr,Exprs}, Vars) ->
- %% Only for Vsn=raw_abstract_v1
- {MungedExprName, Vars2} = munge_expr(Expr, Vars),
- {MungedExprFields, Vars3} = munge_exprs(Exprs, Vars2, []),
- {{record,Line,MungedExprName,MungedExprFields}, Vars3};
-munge_expr({record_field,Line,ExprL,ExprR}, Vars) ->
- %% Only for Vsn=raw_abstract_v1
- {MungedExprL, Vars2} = munge_expr(ExprL, Vars),
- {MungedExprR, Vars3} = munge_expr(ExprR, Vars2),
- {{record_field,Line,MungedExprL,MungedExprR}, Vars3};
-munge_expr({cons,Line,ExprH,ExprT}, Vars) ->
- {MungedExprH, Vars2} = munge_expr(ExprH, Vars),
- {MungedExprT, Vars3} = munge_expr(ExprT, Vars2),
- {{cons,Line,MungedExprH,MungedExprT}, Vars3};
-munge_expr({op,Line,Op,ExprL,ExprR}, Vars) ->
- {MungedExprL, Vars2} = munge_expr(ExprL, Vars),
- {MungedExprR, Vars3} = munge_expr(ExprR, Vars2),
- {{op,Line,Op,MungedExprL,MungedExprR}, Vars3};
-munge_expr({op,Line,Op,Expr}, Vars) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- {{op,Line,Op,MungedExpr}, Vars2};
-munge_expr({'catch',Line,Expr}, Vars) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- {{'catch',Line,MungedExpr}, Vars2};
-munge_expr({call,Line1,{remote,Line2,ExprM,ExprF},Exprs},
- Vars) when Vars#vars.is_guard==false->
- {MungedExprM, Vars2} = munge_expr(ExprM, Vars),
- {MungedExprF, Vars3} = munge_expr(ExprF, Vars2),
- {MungedExprs, Vars4} = munge_exprs(Exprs, Vars3, []),
- {{call,Line1,{remote,Line2,MungedExprM,MungedExprF},MungedExprs}, Vars4};
-munge_expr({call,Line1,{remote,_Line2,_ExprM,ExprF},Exprs},
- Vars) when Vars#vars.is_guard==true ->
- %% Difference in abstract format after preprocessing: BIF calls in guards
- %% are translated to {remote,...} (which is not allowed as source form)
- %% NOT NECESSARY FOR Vsn=raw_abstract_v1
- munge_expr({call,Line1,ExprF,Exprs}, Vars);
-munge_expr({call,Line,Expr,Exprs}, Vars) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- {MungedExprs, Vars3} = munge_exprs(Exprs, Vars2, []),
- {{call,Line,MungedExpr,MungedExprs}, Vars3};
-munge_expr({lc,Line,Expr,LC}, Vars) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- {MungedLC, Vars3} = munge_lc(LC, Vars2, []),
- {{lc,Line,MungedExpr,MungedLC}, Vars3};
-munge_expr({block,Line,Body}, Vars) ->
- {MungedBody, Vars2} = munge_body(Body, Vars, []),
- {{block,Line,MungedBody}, Vars2};
-munge_expr({'if',Line,Clauses}, Vars) ->
- {MungedClauses,Vars2} = munge_clauses(Clauses, Vars, []),
- {{'if',Line,MungedClauses}, Vars2};
-munge_expr({'case',Line,Expr,Clauses}, Vars) ->
- {MungedExpr,Vars2} = munge_expr(Expr,Vars),
- {MungedClauses,Vars3} = munge_clauses(Clauses, Vars2, []),
- {{'case',Line,MungedExpr,MungedClauses}, Vars3};
-munge_expr({'receive',Line,Clauses}, Vars) ->
- {MungedClauses,Vars2} = munge_clauses(Clauses, Vars, []),
- {{'receive',Line,MungedClauses}, Vars2};
-munge_expr({'receive',Line,Clauses,Expr,Body}, Vars) ->
- {MungedClauses,Vars2} = munge_clauses(Clauses, Vars, []),
- {MungedExpr, Vars3} = munge_expr(Expr, Vars2),
- {MungedBody, Vars4} = munge_body(Body, Vars3, []),
- {{'receive',Line,MungedClauses,MungedExpr,MungedBody}, Vars4};
-munge_expr({'try',Line,Exprs,Clauses,CatchClauses,After}, Vars) ->
- {MungedExprs, Vars1} = munge_exprs(Exprs, Vars, []),
- {MungedClauses, Vars2} = munge_clauses(Clauses, Vars1, []),
- {MungedCatchClauses, Vars3} = munge_clauses(CatchClauses, Vars2, []),
- {MungedAfter, Vars4} = munge_body(After, Vars3, []),
- {{'try',Line,MungedExprs,MungedClauses,MungedCatchClauses,MungedAfter},
- Vars4};
-%% Difference in abstract format after preprocessing: Funs get an extra
-%% element Extra.
-%% NOT NECESSARY FOR Vsn=raw_abstract_v1
-munge_expr({'fun',Line,{function,Name,Arity},_Extra}, Vars) ->
- {{'fun',Line,{function,Name,Arity}}, Vars};
-munge_expr({'fun',Line,{clauses,Clauses},_Extra}, Vars) ->
- {MungedClauses,Vars2}=munge_clauses(Clauses, Vars, []),
- {{'fun',Line,{clauses,MungedClauses}}, Vars2};
-munge_expr({'fun',Line,{clauses,Clauses}}, Vars) ->
- %% Only for Vsn=raw_abstract_v1
- {MungedClauses,Vars2}=munge_clauses(Clauses, Vars, []),
- {{'fun',Line,{clauses,MungedClauses}}, Vars2};
-munge_expr({bc,Line,Expr,LC}, Vars) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- {MungedLC, Vars3} = munge_lc(LC, Vars2, []),
- {{bc,Line,MungedExpr,MungedLC}, Vars3};
-munge_expr(Form, Vars) -> % var|char|integer|float|string|atom|nil|bin|eof
- {Form, Vars}.
-
-munge_exprs([Expr|Exprs], Vars, MungedExprs) when Vars#vars.is_guard==true,
- is_list(Expr) ->
- {MungedExpr, _Vars} = munge_exprs(Expr, Vars, []),
- munge_exprs(Exprs, Vars, [MungedExpr|MungedExprs]);
-munge_exprs([Expr|Exprs], Vars, MungedExprs) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- munge_exprs(Exprs, Vars2, [MungedExpr|MungedExprs]);
-munge_exprs([], Vars, MungedExprs) ->
- {lists:reverse(MungedExprs), Vars}.
-
-munge_lc([{generate,Line,Pattern,Expr}|LC], Vars, MungedLC) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- munge_lc(LC, Vars2, [{generate,Line,Pattern,MungedExpr}|MungedLC]);
-munge_lc([{b_generate,Line,Pattern,Expr}|LC], Vars, MungedLC) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- munge_lc(LC, Vars2, [{b_generate,Line,Pattern,MungedExpr}|MungedLC]);
-munge_lc([Expr|LC], Vars, MungedLC) ->
- {MungedExpr, Vars2} = munge_expr(Expr, Vars),
- munge_lc(LC, Vars2, [MungedExpr|MungedLC]);
-munge_lc([], Vars, MungedLC) ->
- {lists:reverse(MungedLC), Vars}.
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/test_server/src/test_server_sup.erl b/lib/test_server/src/test_server_sup.erl
index 1a614d74d5..875f45eea6 100644
--- a/lib/test_server/src/test_server_sup.erl
+++ b/lib/test_server/src/test_server_sup.erl
@@ -26,7 +26,7 @@
cleanup_crash_dumps/0, crash_dump_dir/0, tar_crash_dumps/0,
get_username/0, get_os_family/0,
hostatom/0, hostatom/1, hoststr/0, hoststr/1,
- framework_call/2,framework_call/3,
+ framework_call/2,framework_call/3,framework_call/4,
format_loc/1, package_str/1, package_atom/1,
call_trace/1]).
-include("test_server_internal.hrl").
@@ -51,18 +51,19 @@ timetrap(Timeout0, Scale, Pid) ->
Timeout = if not Scale -> Timeout0;
true -> test_server:timetrap_scale_factor() * Timeout0
end,
+ TruncTO = trunc(Timeout),
receive
- after trunc(Timeout) ->
- Line = test_server:get_loc(Pid),
+ after TruncTO ->
+ MFLs = test_server:get_loc(Pid),
Mon = erlang:monitor(process, Pid),
Trap =
case get(test_server_init_or_end_conf) of
undefined ->
- {timetrap_timeout,trunc(Timeout),Line};
+ {timetrap_timeout,TruncTO,MFLs};
InitOrEnd ->
- {timetrap_timeout,trunc(Timeout),Line,InitOrEnd}
+ {timetrap_timeout,TruncTO,MFLs,InitOrEnd}
end,
- exit(Pid,Trap),
+ exit(Pid, Trap),
receive
{'DOWN', Mon, process, Pid, _} ->
ok
@@ -83,13 +84,13 @@ timetrap(Timeout0, Scale, Pid) ->
%% Handle = term()
%%
%% Cancels a time trap.
-
timetrap_cancel(Handle) ->
unlink(Handle),
MonRef = erlang:monitor(process, Handle),
exit(Handle, kill),
receive {'DOWN',MonRef,_,_,_} -> ok after 2000 -> ok end.
+
capture_get(Msgs) ->
receive
{captured,Msg} ->
@@ -540,8 +541,9 @@ format_loc({Mod,Func}) when is_atom(Func) ->
format_loc({Mod,Line}) when is_integer(Line) ->
%% ?line macro is used
ModStr = package_str(Mod),
- case lists:reverse(ModStr) of
- [$E,$T,$I,$U,$S,$_|_] ->
+ case {lists:member(no_src, get(test_server_logopts)),
+ lists:reverse(ModStr)} of
+ {false,[$E,$T,$I,$U,$S,$_|_]} ->
io_lib:format("{~s,<a href=\"~s~s#~w\">~w</a>}",
[ModStr,downcase(ModStr),?src_listing_ext,
round_to_10(Line),Line]);
@@ -557,8 +559,9 @@ format_loc1([{Mod,Func,Line}|Rest]) ->
[" ",format_loc1({Mod,Func,Line}),",\n"|format_loc1(Rest)];
format_loc1({Mod,Func,Line}) ->
ModStr = package_str(Mod),
- case lists:reverse(ModStr) of
- [$E,$T,$I,$U,$S,$_|_] ->
+ case {lists:member(no_src, get(test_server_logopts)),
+ lists:reverse(ModStr)} of
+ {false,[$E,$T,$I,$U,$S,$_|_]} ->
io_lib:format("{~s,~w,<a href=\"~s~s#~w\">~w</a>}",
[ModStr,Func,downcase(ModStr),?src_listing_ext,
round_to_10(Line),Line]);
diff --git a/lib/test_server/src/ts.config b/lib/test_server/src/ts.config
index f021f5958b..cf3d269616 100644
--- a/lib/test_server/src/ts.config
+++ b/lib/test_server/src/ts.config
@@ -12,7 +12,7 @@
% "10.10.0.1", %IP string
% {10,10,0,1}, %IP tuple
% ["my_ip4_host"], %Any aliases
-% "::ffff:10.10.0.1", %IPv6 string (compatibilty addr)
+% "::ffff:10.10.0.1", %IPv6 string (compatibility addr)
% {0,0,0,0,0,65535,2570,1} %IPv6 tuple
% }}.
diff --git a/lib/test_server/src/ts_erl_config.erl b/lib/test_server/src/ts_erl_config.erl
index 640c8ddc9f..3b41f90d55 100644
--- a/lib/test_server/src/ts_erl_config.erl
+++ b/lib/test_server/src/ts_erl_config.erl
@@ -222,7 +222,6 @@ erl_interface(Vars,OsType) ->
end,
CrossCompile = case OsType of
vxworks -> "true";
- ose -> "true";
_ -> "false"
end,
[{erl_interface_libpath, filename:nativename(LibPath)},
@@ -329,8 +328,6 @@ sock_libraries({win32, _}) ->
sock_libraries({unix, _}) ->
""; % Included in general libraries if needed.
sock_libraries(vxworks) ->
- "";
-sock_libraries(ose) ->
"".
link_library(LibName,{win32, _}) ->
@@ -339,8 +336,6 @@ link_library(LibName,{unix, _}) ->
"lib" ++ LibName ++ ".a";
link_library(LibName,vxworks) ->
"lib" ++ LibName ++ ".a";
-link_library(_LibName,ose) ->
- "";
link_library(_LibName,_Other) ->
exit({link_library, not_supported}).
diff --git a/lib/test_server/src/ts_install.erl b/lib/test_server/src/ts_install.erl
index 2ddffccf5b..9703478f20 100644
--- a/lib/test_server/src/ts_install.erl
+++ b/lib/test_server/src/ts_install.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The 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,7 @@
-export([install/2, platform_id/1]).
-include("ts.hrl").
+-include_lib("kernel/include/file.hrl").
install(install_local, Options) ->
install(os:type(), Options);
@@ -150,11 +151,17 @@ add_vars(Vars0, Opts0) ->
end,
{PlatformId, PlatformLabel, PlatformFilename, Version} =
platform([{longnames, LongNames}|Vars0]),
+ NetDir = lists:concat(["/net", hostname()]),
+ Mounted = case file:read_file_info(NetDir) of
+ {ok, #file_info{type = directory}} -> NetDir;
+ _ -> ""
+ end,
{Opts, [{longnames, LongNames},
{platform_id, PlatformId},
{platform_filename, PlatformFilename},
{rsh_name, get_rsh_name()},
{platform_label, PlatformLabel},
+ {ts_net_dir, Mounted},
{erl_flags, []},
{erl_release, Version},
{ts_testcase_callback, get_testcase_callback()} | Vars0]}.
diff --git a/lib/test_server/src/ts_install_cth.erl b/lib/test_server/src/ts_install_cth.erl
index c5444a342f..a41916fd0a 100644
--- a/lib/test_server/src/ts_install_cth.erl
+++ b/lib/test_server/src/ts_install_cth.erl
@@ -49,8 +49,7 @@
-include_lib("kernel/include/file.hrl").
--type proplist() :: list({atom(),term()}).
--type config() :: proplist().
+-type config() :: proplists:proplist().
-type reason() :: term().
-type skip_or_fail() :: {skip, reason()} |
{auto_skip, reason()} |
@@ -65,19 +64,19 @@ id(_Opts) ->
?MODULE.
%% @doc Always called before any other callback function.
--spec init(Id :: term(), Opts :: proplist()) ->
- State :: #state{}.
+-spec init(Id :: term(), Opts :: proplists:proplist()) ->
+ {ok, State :: #state{}}.
init(_Id, Opts) ->
Nodenames = proplists:get_value(nodenames, Opts, 0),
Nodes = proplists:get_value(nodes, Opts, 0),
TSConfDir = proplists:get_value(ts_conf_dir, Opts),
TargetSystem = proplists:get_value(target_system, Opts, install_local),
InstallOpts = proplists:get_value(install_opts, Opts, []),
- #state{ nodenames = Nodenames,
- nodes = Nodes,
- ts_conf_dir = TSConfDir,
- target_system = TargetSystem,
- install_opts = InstallOpts }.
+ {ok, #state{ nodenames = Nodenames,
+ nodes = Nodes,
+ ts_conf_dir = TSConfDir,
+ target_system = TargetSystem,
+ install_opts = InstallOpts } }.
%% @doc Called before init_per_suite is called.
-spec pre_init_per_suite(Suite :: atom(),
diff --git a/lib/test_server/src/ts_run.erl b/lib/test_server/src/ts_run.erl
index 067961a216..885a3c9b96 100644
--- a/lib/test_server/src/ts_run.erl
+++ b/lib/test_server/src/ts_run.erl
@@ -212,6 +212,12 @@ make_command(Vars, Spec, State) ->
false ->
ok
end,
+
+ %% If Common Test specific variables are needed, add them here
+ %% on form: "{key1,value1}" "{key2,value2}" ...
+ NetDir = ts_lib:var(ts_net_dir, Vars),
+ TestVars = [ "\"{net_dir,\\\"",NetDir,"\\\"}\"" ],
+
%% NOTE: Do not use ' in these commands as it wont work on windows
Cmd = [Erl, Naming, "test_server"
" -rsh ", ts_lib:var(rsh_name, Vars),
@@ -224,6 +230,7 @@ make_command(Vars, Spec, State) ->
%% " -test_server_format_exception false",
" -boot start_sasl -sasl errlog_type error",
" -pz ",Cwd,
+ " -ct_test_vars ",TestVars,
" -eval \"file:set_cwd(\\\"",TestDir,"\\\")\" "
" -eval \"ct:run_test(",
backslashify(lists:flatten(State#state.test_server_args)),")\""
@@ -358,6 +365,14 @@ make_common_test_args(Args0, Options, _Vars) ->
[{logdir,"../test_server"}]
end,
+ TimeTrap = case test_server:timetrap_scale_factor() of
+ 1 ->
+ [];
+ Scale ->
+ [{multiply_timetraps, Scale},
+ {scale_timetraps, true}]
+ end,
+
ConfigPath = case {os:getenv("TEST_CONFIG_PATH"),
lists:keysearch(config, 1, Options)} of
{false,{value, {config, Path}}} ->
@@ -369,9 +384,8 @@ make_common_test_args(Args0, Options, _Vars) ->
end,
ConfigFiles = [{config,[filename:join(ConfigPath,File)
|| File <- get_config_files()]}],
-
io_lib:format("~100000p",[Args0++Trace++Cover++Logdir++
- ConfigFiles++Options]).
+ ConfigFiles++Options++TimeTrap]).
to_list(X) when is_atom(X) ->
atom_to_list(X);
diff --git a/lib/test_server/test/Makefile b/lib/test_server/test/Makefile
index 34c55c595d..198440bb17 100644
--- a/lib/test_server/test/Makefile
+++ b/lib/test_server/test/Makefile
@@ -85,8 +85,8 @@ release_spec: opt
release_tests_spec: make_emakefile
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(COVERFILE) $(RELSYSDIR)
- $(INSTALL_DATA) test_server.spec test_server.cover $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ $(INSTALL_DATA) test_server_test_lib.hrl test_server.spec test_server.cover $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/test_server/test/test_server_SUITE.erl b/lib/test_server/test/test_server_SUITE.erl
index 4c344717f0..a8532b08ab 100644
--- a/lib/test_server/test/test_server_SUITE.erl
+++ b/lib/test_server/test/test_server_SUITE.erl
@@ -119,6 +119,11 @@ test_server_conf02_SUITE(Config) ->
run_test_server_tests(SuiteName, NCases, NFail, NExpected, NSucc,
NUsrSkip, NAutoSkip,
NActualSkip, NActualFail, NActualSucc, Config) ->
+
+ ct:log("See test case log files under:~n~p~n",
+ [filename:join([proplists:get_value(priv_dir, Config),
+ SuiteName++".logs"])]),
+
Node = proplists:get_value(node, Config),
{ok,_Pid} = rpc:call(Node,test_server_ctrl, start, []),
rpc:call(Node,
@@ -132,6 +137,7 @@ run_test_server_tests(SuiteName, NCases, NFail, NExpected, NSucc,
end),
rpc:call(Node,test_server_ctrl, stop, []),
+
{ok,#suite{ n_cases = NCases,
n_cases_failed = NFail,
n_cases_expected = NExpected,
diff --git a/lib/test_server/vsn.mk b/lib/test_server/vsn.mk
index b7c0987845..563c1b6db6 100644
--- a/lib/test_server/vsn.mk
+++ b/lib/test_server/vsn.mk
@@ -1,2 +1,2 @@
-TEST_SERVER_VSN = 3.4.3
+TEST_SERVER_VSN = 3.4.5
diff --git a/lib/toolbar/doc/src/notes.xml b/lib/toolbar/doc/src/notes.xml
index e2a3c22684..ffca2c5fbf 100644
--- a/lib/toolbar/doc/src/notes.xml
+++ b/lib/toolbar/doc/src/notes.xml
@@ -31,6 +31,22 @@
<p>This document describes the changes made to the Toolbar
application.</p>
+<section><title>Toolbar 1.4.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improve spelling throughout documentation, code comments
+ and error messages</p>
+ <p>
+ Own Id: OTP-9555</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Toolbar 1.4.1</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/toolbar/src/toolbar_toolconfig.erl b/lib/toolbar/src/toolbar_toolconfig.erl
index 7d8f2b4d21..6dccb7ba72 100644
--- a/lib/toolbar/src/toolbar_toolconfig.erl
+++ b/lib/toolbar/src/toolbar_toolconfig.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -126,7 +126,7 @@ loop(S,Window) ->
show_info(Window,Info),
move_focus(Window,file);
- %% Erronous version number -- Notify user
+ %% Erroneous version number -- Notify user
{error,version} ->
Win = Window#tfwindow.window,
tool_utils:notify(Win,[FileName,
@@ -136,7 +136,7 @@ loop(S,Window) ->
_Error ->
Win = Window#tfwindow.window,
tool_utils:notify(Win,[FileName,
- "File is on erronous format"])
+ "File is in erroneous format"])
end;
%% The file can not be read, show default values
diff --git a/lib/toolbar/vsn.mk b/lib/toolbar/vsn.mk
index 47d18e29f0..105303d785 100644
--- a/lib/toolbar/vsn.mk
+++ b/lib/toolbar/vsn.mk
@@ -1,4 +1,4 @@
-TOOLBAR_VSN = 1.4.1
+TOOLBAR_VSN = 1.4.2
diff --git a/lib/tools/c_src/Makefile.in b/lib/tools/c_src/Makefile.in
index 65a7f5f424..6921193154 100644
--- a/lib/tools/c_src/Makefile.in
+++ b/lib/tools/c_src/Makefile.in
@@ -142,7 +142,9 @@ EMEM_OBJS = $(addprefix $(EMEM_OBJ_DIR)/,$(notdir $(EMEM_SRCS:.c=.o)))
# Misc targets
#
-all: $(CREATE_DIRS) erts_lib $(PROGS) $(DRIVERS)
+_create_dirs := $(shell mkdir -p $(CREATE_DIRS))
+
+all: erts_lib $(PROGS) $(DRIVERS)
erts_lib:
cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE)
@@ -158,13 +160,6 @@ clean:
.PHONY: all erts_lib docs clean
#
-# Make dir targets
-#
-
-$(CREATE_DIRS):
- $(MKDIR) -p $@
-
-#
# Object targets
#
diff --git a/lib/tools/doc/src/instrument.xml b/lib/tools/doc/src/instrument.xml
index 12877994de..b7e48ea306 100644
--- a/lib/tools/doc/src/instrument.xml
+++ b/lib/tools/doc/src/instrument.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1998</year><year>2009</year>
+ <year>1998</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -342,7 +342,7 @@
<p>Stores the current memory allocation map on the file
<c>File</c>. Returns <c>true</c> if the emulator has been
started with the "<c>+Mim true</c>" command-line argument, and
- the map was successfuly stored; otherwise, <c>false</c>. The
+ the map was successfully stored; otherwise, <c>false</c>. The
contents of the file can later be read using
<seealso marker="#read_memory_data/1">read_memory_data/1</seealso>.
<em>NOTE:</em><c>store_memory_data/0</c> blocks execution of
@@ -360,7 +360,7 @@
<p>Stores the current memory status on the file
<c>File</c>. Returns <c>true</c> if the emulator has been
started with the "<c>+Mis true</c>", or "<c>+Mim true</c>"
- command-line arguments, and the data was successfuly stored;
+ command-line arguments, and the data was successfully stored;
otherwise, <c>false</c>. The contents of the file can later be
read using
<seealso marker="#read_memory_status/1">read_memory_status/1</seealso>.</p>
diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml
index 118800e44a..17506fb6e2 100644
--- a/lib/tools/doc/src/notes.xml
+++ b/lib/tools/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,6 +30,111 @@
</header>
<p>This document describes the changes made to the Tools application.</p>
+<section><title>Tools 2.6.6.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Teach the emacs mode to compile yecc and leex files</p>
+ <p>
+ If visiting a .yrl or .xrl file in emacs with
+ erlang-mode, then the `erlang-compile' function (normally
+ bound to C-c C-k), now knows how to compile yecc and leex
+ files, and then, if that compilation succeeds, also
+ compiles the resulting .erl files.</p>
+ <p>
+ Also introduce a `erlang-compile-command-function-alist'
+ to make it possible to hook in other functions for
+ computing compilation commands/expressions, depending on
+ file name. (Thanks to Tomas Abrahamsson )</p>
+ <p>
+ Own Id: OTP-9503</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Bugs in xref(3) have been fixed. (Thanks to Matthias
+ Lang.) </p>
+ <p>
+ Own Id: OTP-9416</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Tools 2.6.6.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Change make:files to behave more like erlc</p>
+ <p>
+ This change removes the unnecessary checks on the files
+ when make:files is called and allows the error checking
+ to be done in compile:file, where the error messages are
+ produced. It does not affect the return value.</p>
+ <p>
+ (Thanks to Sam bobroff)</p>
+ <p>
+ Own Id: OTP-9179</p>
+ </item>
+ <item>
+ <p>
+ add user specified compiler options on form reloading</p>
+ <p>
+ In order to be able to test non-exported functions from
+ another (test) module it is necessary to compile the
+ specific module (at least during the test phase) with the
+ export_all compiler option. This allows complete
+ separation of testing and productive code. At the moment
+ it is not possible to combine this with a test code
+ coverage using the cover module. The problem is that when
+ cover compiling a module using cover:compile_* the code
+ is reloaded into the emulator omitting/filtering the
+ passed user options. In my example above the export_all
+ option would be removed and the non-exported functions
+ cannot be called any more. (Thanks to Tobias Schlager)</p>
+ <p>
+ Own Id: OTP-9204</p>
+ </item>
+ <item>
+ <p>
+ Inhibit electric newline after "-&gt;" when inside a type
+ spec</p>
+ <p>
+ The Erlang mode for Emacs inserts a newline after every
+ "-&gt;", which saves you one keystroke when writing a
+ function, but that is inappropriate when writing a type
+ spec, as you'd normally keep the spec on one line. This
+ change inhibits the automatic insertion when the current
+ line starts with "-spec" or "-type".(Thanks to Magnus
+ Henoch)</p>
+ <p>
+ Own Id: OTP-9255</p>
+ </item>
+ <item>
+ <p>
+ Add a check logic to prevent file descriptor leak</p>
+ <p>
+ cover module handle files as raw in export and import.
+ Assert counts of ports are the same at the beginning and
+ at the end of the test case.(Thanks to Shunichi
+ Shinohara)</p>
+ <p>
+ Own Id: OTP-9300</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Tools 2.6.6.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/tools/doc/src/xref.xml b/lib/tools/doc/src/xref.xml
index 75ffa25311..17de66bb22 100644
--- a/lib/tools/doc/src/xref.xml
+++ b/lib/tools/doc/src/xref.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2010</year>
+ <year>2000</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -1465,8 +1465,8 @@ Evaluates a predefined analysis.
<name>start(NameOrOptions) -> Return</name>
<fsummary>Create an Xref server.</fsummary>
<type>
- <v>Name = atom()()</v>
- <v>XrefOrOptions = Xref | Options</v>
+ <v>NameOrOptions = Name | Options</v>
+ <v>Name = atom()</v>
<v>Options = [Option] | Option</v>
<v>Option = {xref_mode, mode()} | term()</v>
<v>Return = {ok, pid()} | {error, {already_started, pid()}}</v>
@@ -1483,7 +1483,7 @@ Evaluates a predefined analysis.
<name>start(Name, Options) -> Return</name>
<fsummary>Create an Xref server.</fsummary>
<type>
- <v>Name = atom()()</v>
+ <v>Name = atom()</v>
<v>Options = [Option] | Option</v>
<v>Option = {xref_mode, mode()} | term()</v>
<v>Return = {ok, pid()} | {error, {already_started, pid()}}</v>
diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el
index e1c0d31371..bc7a190fb4 100644
--- a/lib/tools/emacs/erlang.el
+++ b/lib/tools/emacs/erlang.el
@@ -386,7 +386,8 @@ then no prototype is inserted.
The test is performed by the function `erlang-test-criteria-list'.")
(defvar erlang-electric-arrow-criteria
- '(erlang-next-lines-empty-p
+ '(erlang-stop-when-in-type-spec
+ erlang-next-lines-empty-p
erlang-at-end-of-function-p)
"*List of functions controlling the arrow aspect of `erlang-electric-gt'.
The functions in this list are called, in order, whenever a `>'
@@ -522,6 +523,32 @@ This is an elisp list of options. Each option can be either:
- a string
Example: '(bin_opt_info (i . \"/path1/include\") (i . \"/path2/include\"))")
+(defvar erlang-compile-command-function-alist
+ '((".erl\\'" . inferior-erlang-compute-erl-compile-command)
+ (".xrl\\'" . inferior-erlang-compute-leex-compile-command)
+ (".yrl\\'" . inferior-erlang-compute-yecc-compile-command)
+ ("." . inferior-erlang-compute-erl-compile-command))
+ "*Alist of filename patterns vs corresponding compilation functions.
+Each element looks like (REGEXP . FUNCTION). Compiling a file whose name
+matches REGEXP specifies FUNCTION to use to compute the compilation
+command. The FUNCTION will be called with two arguments: module name and
+default compilation options, like output directory. The FUNCTION
+is expected to return a string.")
+
+(defvar erlang-leex-compile-opts '()
+ "*Options to pass to leex when compiling xrl files.
+This is an elisp list of options. Each option can be either:
+- an atom
+- a dotted pair
+- a string")
+
+(defvar erlang-yecc-compile-opts '()
+ "*Options to pass to yecc when compiling yrl files.
+This is an elisp list of options. Each option can be either:
+- an atom
+- a dotted pair
+- a string")
+
(eval-and-compile
(defvar erlang-regexp-modern-p
(if (> erlang-emacs-major-version 21) t nil)
@@ -1198,7 +1225,7 @@ Lock syntax table. The effect is that `apply' in the atom
`( (char-after (1- (or ,pos (point)))))))
;; defvar some obsolete variables, which we still support for
-;; backwardscompatibility reasons.
+;; backwards compatibility reasons.
(eval-when-compile
(defvar comment-indent-hook)
(defvar dabbrev-case-fold-search)
@@ -4045,6 +4072,16 @@ This function is designed to be a member of a criteria list."
nil)))
+(defun erlang-stop-when-in-type-spec ()
+ "Return `stop' when in a type spec line.
+
+This function is designed to be a member of a criteria list."
+ (save-excursion
+ (beginning-of-line)
+ (when (save-match-data (looking-at "-\\(spec\\|type\\)"))
+ 'stop)))
+
+
(defun erlang-next-lines-empty-p ()
"Return non-nil if next lines are empty.
@@ -5265,6 +5302,22 @@ unless the optional NO-DISPLAY is non-nil."
(file-name-as-directory buffer-dir))))
(defun inferior-erlang-compute-compile-command (module-name opts)
+ (let ((ccfn erlang-compile-command-function-alist)
+ (res (inferior-erlang-compute-erl-compile-command module-name opts))
+ ccfn-entry
+ done)
+ (if (not (null (buffer-file-name)))
+ (while (and (not done) (not (null ccfn)))
+ (setq ccfn-entry (car ccfn))
+ (setq ccfn (cdr ccfn))
+ (if (string-match (car ccfn-entry) (buffer-file-name))
+ (let ((c-fn (cdr ccfn-entry)))
+ (setq done t)
+ (if (not (null c-fn))
+ (setq result (funcall c-fn module-name opts)))))))
+ result))
+
+(defun inferior-erlang-compute-erl-compile-command (module-name opts)
(let* ((out-dir-opt (assoc 'outdir opts))
(out-dir (cdr out-dir-opt)))
(if erlang-compile-use-outdir
@@ -5288,6 +5341,48 @@ unless the optional NO-DISPLAY is non-nil."
(remq out-dir-opt opts))
tmpvar tmpvar tmpvar2)))))
+(defun inferior-erlang-compute-leex-compile-command (module-name opts)
+ (let ((file-name (buffer-file-name))
+ (erl-compile-expr (inferior-erlang-remove-any-trailing-dot
+ (inferior-erlang-compute-erl-compile-command
+ module-name opts))))
+ (format (concat "f(LErr1__), f(LErr2__), "
+ "case case leex:file(\"%s\", [%s]) of"
+ " ok -> ok;"
+ " {ok,_} -> ok;"
+ " {ok,_,_} -> ok;"
+ " LErr1__ -> LErr1__ "
+ "end of"
+ " ok -> %s;"
+ " LErr2__ -> LErr2__ "
+ "end.")
+ file-name
+ (inferior-erlang-format-comma-opts erlang-leex-compile-opts)
+ erl-compile-expr)))
+
+(defun inferior-erlang-compute-yecc-compile-command (module-name opts)
+ (let ((file-name (buffer-file-name))
+ (erl-compile-expr (inferior-erlang-remove-any-trailing-dot
+ (inferior-erlang-compute-erl-compile-command
+ module-name opts))))
+ (format (concat "f(YErr1__), f(YErr2__), "
+ "case case yecc:file(\"%s\", [%s]) of"
+ " {ok,_} -> ok;"
+ " {ok,_,_} -> ok;"
+ " YErr1__ -> YErr1__ "
+ "end of"
+ " ok -> %s;"
+ " YErr2__ -> YErr2__ "
+ "end.")
+ file-name
+ (inferior-erlang-format-comma-opts erlang-yecc-compile-opts)
+ erl-compile-expr)))
+
+(defun inferior-erlang-remove-any-trailing-dot (str)
+ (if (string= (substring str -1) ".")
+ (substring str 0 (1- (length str)))
+ str))
+
(defun inferior-erlang-format-comma-opts (opts)
(if (null opts)
""
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index 230f0e9428..fb9744d759 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -55,14 +55,14 @@
%% compiled module. This is necessary so that the code can be loaded
%% on remote nodes that are started after the compilation.
%%
-%% PARELLALISM
+%% PARALLELISM
%% To take advantage of SMP when doing the cover analysis both the data
%% collection and analysis has been parallelized. One process is spawned for
%% each node when collecting data, and on the remote node when collecting data
%% one process is spawned per module.
%%
%% When analyzing data it is possible to issue multiple analyse(_to_file)/X
-%% calls at once. They are however all calls (for backwardscompatability
+%% calls at once. They are however all calls (for backwards compatibility
%% reasons) so the user of cover will have to spawn several processes to to the
%% calls ( or use async_analyse_to_file ).
%%
@@ -253,6 +253,7 @@ compile_modules(Files,Options) ->
{i, Dir} when is_list(Dir) -> true;
{d, _Macro} -> true;
{d, _Macro, _Value} -> true;
+ export_all -> true;
_ -> false
end
end,
@@ -625,7 +626,7 @@ main_process_loop(State) ->
case get_beam_file(Module,BeamFile0,Compiled0) of
{ok,BeamFile} ->
{Reply,Compiled} =
- case do_compile_beam(Module,BeamFile) of
+ case do_compile_beam(Module,BeamFile,[]) of
{ok, Module} ->
remote_load_compiled(State#main_state.nodes,
[{Module,BeamFile}]),
@@ -661,6 +662,7 @@ main_process_loop(State) ->
Imported = do_import_to_table(Fd,File,
State#main_state.imported),
reply(From, ok),
+ file:close(Fd),
main_process_loop(State#main_state{imported=Imported});
{error,Reason} ->
reply(From, {error, {cant_open_file,File,Reason}}),
@@ -1258,13 +1260,13 @@ do_compile(File, UserOptions) ->
Options = [debug_info,binary,report_errors,report_warnings] ++ UserOptions,
case compile:file(File, Options) of
{ok, Module, Binary} ->
- do_compile_beam(Module,Binary);
+ do_compile_beam(Module,Binary,UserOptions);
error ->
error
end.
%% Beam is a binary or a .beam file name
-do_compile_beam(Module,Beam) ->
+do_compile_beam(Module,Beam,UserOptions) ->
%% Clear database
do_clear(Module),
@@ -1284,7 +1286,7 @@ do_compile_beam(Module,Beam) ->
%% Compile and load the result
%% It's necessary to check the result of loading since it may
%% fail, for example if Module resides in a sticky directory
- {ok, Module, Binary} = compile:forms(Forms, []),
+ {ok, Module, Binary} = compile:forms(Forms, UserOptions),
case code:load_binary(Module, ?TAG, Binary) of
{module, Module} ->
diff --git a/lib/tools/src/make.erl b/lib/tools/src/make.erl
index 77c354651b..5cc8d47faa 100644
--- a/lib/tools/src/make.erl
+++ b/lib/tools/src/make.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -222,12 +222,7 @@ recompilep(File, NoExec, Load, Opts) ->
recompilep1(File, NoExec, Load, Opts, ObjFile) ->
{ok, Erl} = file:read_file_info(lists:append(File, ".erl")),
{ok, Obj} = file:read_file_info(ObjFile),
- case {readable(Erl), writable(Obj)} of
- {true, true} ->
- recompilep1(Erl, Obj, File, NoExec, Load, Opts);
- _ ->
- error
- end.
+ recompilep1(Erl, Obj, File, NoExec, Load, Opts).
recompilep1(#file_info{mtime=Te},
#file_info{mtime=To}, File, NoExec, Load, Opts) when Te>To ->
@@ -277,14 +272,6 @@ exists(File) ->
false
end.
-readable(#file_info{access=read_write}) -> true;
-readable(#file_info{access=read}) -> true;
-readable(_) -> false.
-
-writable(#file_info{access=read_write}) -> true;
-writable(#file_info{access=write}) -> true;
-writable(_) -> false.
-
coerce_2_list(X) when is_atom(X) ->
atom_to_list(X);
coerce_2_list(X) ->
diff --git a/lib/tools/test/Makefile b/lib/tools/test/Makefile
index 63f96520fd..8019b7269f 100644
--- a/lib/tools/test/Makefile
+++ b/lib/tools/test/Makefile
@@ -87,7 +87,7 @@ release_tests_spec: make_emakefile
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(SPEC_FILES) $(COVER_FILE) $(EMAKEFILE) \
$(ERL_FILES) $(RELSYSDIR)
- chmod -f -R u+w $(RELSYSDIR)
+ chmod -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
release_docs_spec:
diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl
index b5c8e8a1b7..fe7f92de78 100644
--- a/lib/tools/test/cover_SUITE.erl
+++ b/lib/tools/test/cover_SUITE.erl
@@ -395,6 +395,7 @@ export_import(suite) -> [];
export_import(Config) when is_list(Config) ->
?line DataDir = ?config(data_dir, Config),
?line ok = file:set_cwd(DataDir),
+ ?line PortCount = length(erlang:ports()),
%% Export one module
?line {ok,f} = cover:compile(f),
@@ -484,6 +485,9 @@ export_import(Config) when is_list(Config) ->
?line ?t:capture_stop(),
?line check_f_calls(1,0),
+ %% Check no raw files are left open
+ ?line PortCount = length(erlang:ports()),
+
%% Cleanup
?line ok = cover:stop(),
?line Files = lsfiles(),
diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk
index 83027cfaa6..2d63a33554 100644
--- a/lib/tools/vsn.mk
+++ b/lib/tools/vsn.mk
@@ -1 +1 @@
-TOOLS_VSN = 2.6.6.3
+TOOLS_VSN = 2.6.6.5
diff --git a/lib/tv/doc/src/notes.xml b/lib/tv/doc/src/notes.xml
index 388bb82c91..77a6a43d51 100644
--- a/lib/tv/doc/src/notes.xml
+++ b/lib/tv/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,6 +30,30 @@
</header>
<p>This document describes the changes made to the TV application.</p>
+<section><title>TV 2.1.4.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ tv: Allow table viewer to display refs, ports and small
+ binaries</p>
+ <p>
+ Table viewer displayed #Port, #Ref, or #Bin as place
+ holders for their respective object types in ets and
+ mnesia tables. This can make table viewer difficult to
+ use when viewing tables containing those data types. It
+ doesn't make sense to render large binaries so #Bin will
+ still be used for binaries that exceed 100 bytes. (Thanks
+ to Blaine whittle)</p>
+ <p>
+ Own Id: OTP-9153</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>TV 2.1.4.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/tv/src/tv_main.erl b/lib/tv/src/tv_main.erl
index 2f743c2397..283ba4c967 100644
--- a/lib/tv/src/tv_main.erl
+++ b/lib/tv/src/tv_main.erl
@@ -312,7 +312,7 @@ analyze_error(Cause, Node, Table) ->
handle_error(mnesia_not_started, Node, Table);
{badrpc, {'EXIT', {aborted, {node_not_running,_ErrNode}}}} ->
handle_error(mnesia_not_started, Node, Table);
- {'EXIT', {undef, {mnesia,_Fcn,_Args}}} ->
+ {'EXIT', {undef, {mnesia,_Fcn,_Args,_}}} ->
handle_error(mnesia_not_started, Node, Table);
{'EXIT', Reason} ->
diff --git a/lib/tv/src/tv_mnesia_rpc.erl b/lib/tv/src/tv_mnesia_rpc.erl
index a2385714ec..4a75994145 100644
--- a/lib/tv/src/tv_mnesia_rpc.erl
+++ b/lib/tv/src/tv_mnesia_rpc.erl
@@ -87,6 +87,8 @@ chk(Result) ->
throw(mnesia_not_started);
{badrpc, _Reason} ->
throw(mnesia_not_started);
+ {'EXIT', {undef, {mnesia,_Fcn,_Args,_}}} ->
+ throw(mnesia_not_started);
{'EXIT', {undef, {mnesia,_Fcn,_Args}}} ->
throw(mnesia_not_started);
diff --git a/lib/tv/vsn.mk b/lib/tv/vsn.mk
index 958aa0ea42..43e3d2ebce 100644
--- a/lib/tv/vsn.mk
+++ b/lib/tv/vsn.mk
@@ -1 +1 @@
-TV_VSN = 2.1.4.6
+TV_VSN = 2.1.4.7
diff --git a/lib/typer/src/typer.erl b/lib/typer/src/typer.erl
index fc8caa4f21..f2a70f49b7 100644
--- a/lib/typer/src/typer.erl
+++ b/lib/typer/src/typer.erl
@@ -466,14 +466,20 @@ write_typed_file(File, Info) ->
case file:make_dir(TyperAnnDir) of
{error, Reason} ->
case Reason of
- eexist -> %% TypEr dir exists; remove old typer files
- ok = file:delete(NewFileName),
+ eexist -> %% TypEr dir exists; remove old typer files if they exist
+ case file:delete(NewFileName) of
+ ok -> ok;
+ {error, enoent} -> ok;
+ {error, _} ->
+ Msg = io_lib:format("Error in deleting file ~s\n", [NewFileName]),
+ fatal_error(Msg)
+ end,
write_typed_file(File, Info, NewFileName);
enospc ->
Msg = io_lib:format("Not enough space in ~p\n", [Dir]),
fatal_error(Msg);
eacces ->
- Msg = io:format("No write permission in ~p\n", [Dir]),
+ Msg = io_lib:format("No write permission in ~p\n", [Dir]),
fatal_error(Msg);
_ ->
Msg = io_lib:format("Unhandled error ~s when writing ~p\n",
@@ -539,7 +545,7 @@ get_type_string(F, A, Info, Mode) ->
case {Mode, Type} of
{file, {contract, _}} -> "";
_ ->
- Prefix = lists:concat(["-spec ", F]),
+ Prefix = lists:concat(["-spec ", erl_types:atom_to_string(F)]),
lists:concat([Prefix, TypeStr, "."])
end;
true ->
@@ -628,6 +634,8 @@ cl(["-T"|Opts]) ->
cl(["-r"|Opts]) ->
{Files, RestOpts} = dialyzer_cl_parse:collect_args(Opts),
{{files_r, Files}, RestOpts};
+cl(["-pa",Dir|Opts]) -> {{pa,Dir}, Opts};
+cl(["-pz",Dir|Opts]) -> {{pz,Dir}, Opts};
cl(["-"++H|_]) -> fatal_error("unknown option -"++H);
cl(Opts) ->
{Files, RestOpts} = dialyzer_cl_parse:collect_args(Opts),
@@ -672,7 +680,13 @@ analyze_result({plt, Plt}, Args, Analysis) ->
analyze_result(show_succ, Args, Analysis) ->
{Args, Analysis#analysis{show_succ = true}};
analyze_result(no_spec, Args, Analysis) ->
- {Args, Analysis#analysis{no_spec = true}}.
+ {Args, Analysis#analysis{no_spec = true}};
+analyze_result({pa, Dir}, Args, Analysis) ->
+ code:add_patha(Dir),
+ {Args, Analysis};
+analyze_result({pz, Dir}, Args, Analysis) ->
+ code:add_pathz(Dir),
+ {Args, Analysis}.
%%--------------------------------------------------------------------
%% File processing.
@@ -1009,7 +1023,8 @@ version_message() ->
help_message() ->
S = <<" Usage: typer [--help] [--version] [--plt PLT] [--edoc]
[--show | --show-exported | --annotate | --annotate-inc-files]
- [-Ddefine]* [-I include_dir]* [-T application]* [-r] file*
+ [-Ddefine]* [-I include_dir]* [-pa dir]* [-pz dir]*
+ [-T application]* [-r] file*
Options:
-r dir*
@@ -1039,6 +1054,10 @@ help_message() ->
-I include_dir
pass the include_dir to TypEr
(The syntax of includes is the same as that used by \"erlc\".)
+ -pa dir
+ -pz dir
+ Set code path options to TypEr
+ (This is useful for files that use parse tranforms.)
--version (or -v)
prints the Typer version and exits
--help (or -h)
diff --git a/lib/typer/vsn.mk b/lib/typer/vsn.mk
index 51561939ac..9e73aed286 100644
--- a/lib/typer/vsn.mk
+++ b/lib/typer/vsn.mk
@@ -1 +1 @@
-TYPER_VSN = 0.9
+TYPER_VSN = 0.9.2
diff --git a/lib/webtool/doc/src/notes.xml b/lib/webtool/doc/src/notes.xml
index 5179f37db2..c58a440937 100644
--- a/lib/webtool/doc/src/notes.xml
+++ b/lib/webtool/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,38 @@
<p>This document describes the changes made to the Webtool
application.</p>
+<section><title>WebTool 0.8.9</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Do not install *.bat files on non-win32 machines (Thanks
+ to Hans Ulrich Niedermann)</p>
+ <p>
+ Own Id: OTP-9515</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>WebTool 0.8.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Various small documentation fixes (Thanks to Bernard
+ Duggan)</p>
+ <p>
+ Own Id: OTP-9172</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>WebTool 0.8.7</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/webtool/doc/src/webtool_chapter.xml b/lib/webtool/doc/src/webtool_chapter.xml
index f72a255b0a..77fcaebb4b 100644
--- a/lib/webtool/doc/src/webtool_chapter.xml
+++ b/lib/webtool/doc/src/webtool_chapter.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2001</year><year>2009</year>
+ <year>2001</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -151,7 +151,7 @@
http://Servername:Port/ErlScriptAlias/Mod/Func<?QueryString> ]]></code>
<p>An <c>alias</c> parameter in the configuration function can be
an ErlScriptAlias as used in the above URL. The definition of
- an ErlScripAlias shall be like this:</p>
+ an ErlScriptAlias shall be like this:</p>
<p><c>{alias,{erl_alias,Path,[Modules]}}</c>, e.g.</p>
<p><c>{alias,{erl_alias,"/testtool",[helloworld]}}</c></p>
<p>The following URL will then cause a call to the function
@@ -184,7 +184,7 @@ http://Servername:Port/ErlScriptAlias/Mod/Func<?QueryString> ]]></code>
directory <c>/usr/local/otp/lib/myapp-1.0/priv</c>:</p>
<p><c>{alias,{"/mytool_home","/usr/local/otp/lib/myapp-1.0/priv"}}</c></p>
<p>See the INETS documentation, especially the module
- <c>mod_esi</c>, for a more in depht coverage of Erl Scheme.</p>
+ <c>mod_esi</c>, for a more in depth coverage of the Erl Scheme.</p>
</section>
<section>
diff --git a/lib/webtool/priv/Makefile b/lib/webtool/priv/Makefile
index 56ab772c45..6e1c6606fe 100644
--- a/lib/webtool/priv/Makefile
+++ b/lib/webtool/priv/Makefile
@@ -39,8 +39,12 @@ HTDOCS_FILES = root/doc/index.html \
root/doc/tool_management.html \
root/doc/start_info.html
-SCRIPTS = bin/start_webtool \
- bin/start_webtool.bat
+ifeq ($(findstring win32,$(TARGET)),win32)
+WIN32_SCRIPTS= bin/start_webtool.bat
+else
+WIN32_SCRIPTS=
+endif
+SCRIPTS = bin/start_webtool $(WIN32_SCRIPTS)
# ----------------------------------------------------
# FLAGS
diff --git a/lib/webtool/vsn.mk b/lib/webtool/vsn.mk
index 6b76883330..2643be866e 100644
--- a/lib/webtool/vsn.mk
+++ b/lib/webtool/vsn.mk
@@ -1 +1 @@
-WEBTOOL_VSN=0.8.7
+WEBTOOL_VSN=0.8.9
diff --git a/lib/wx/api_gen/gen_util.erl b/lib/wx/api_gen/gen_util.erl
index b53f817ce0..df5b4c3405 100644
--- a/lib/wx/api_gen/gen_util.erl
+++ b/lib/wx/api_gen/gen_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The 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,23 +43,27 @@ strip_name(String,[]) -> String.
get_hook(_Type, undefined) -> ignore;
get_hook(Type, List) -> proplists:get_value(Type, List, ignore).
-
+
+get_taylor_made(Str, Name) ->
+ re:run(Str, "<<"++Name++"(.*)"++Name++">>",
+ [dotall, {capture, all_but_first, list}]).
+
open_write(File) ->
%% io:format("Generating ~s~n",[File]),
{ok, Fd} = file:open(File++".temp", [write]),
put(current_file, {Fd,File}).
-
+
close() ->
case get(current_file) of
- undefined ->
+ undefined ->
ok;
{closed, File} ->
io:format("Closing twice ~s~n",[File]);
{Fd,File} ->
file:close(Fd),
case os:cmd("diff " ++ File ++ " " ++ File ++ ".temp" ++ "| head -30") of
- [] ->
+ [] ->
ok = file:delete(File ++ ".temp"),
%% So that make understands that we have made this
%% case os:getenv("CLEARCASE_ROOT") of
@@ -71,11 +75,11 @@ close() ->
case check_diff(Diff) of
copyright -> %% We ignore copyright changes only
ok = file:delete(File ++ ".temp");
- _ ->
+ _ ->
io:format("Diff in ~s~n~s ~n", [File, Diff]),
case file:rename(File ++ ".temp", File) of
ok -> ok;
- _ ->
+ _ ->
io:format("***** Failed to save file ~p ~n",[File])
end
end
@@ -85,9 +89,9 @@ close() ->
check_diff(Diff) ->
- try
+ try
[_,D1,_,D2|Tail] = re:split(Diff, "\n"),
- case Tail of
+ case Tail of
[] -> ok;
[<<>>] -> ok;
_ -> throw(diff)
@@ -117,29 +121,29 @@ args(Fun, Limit, List, Max) ->
args(Fun, Limit, List, Max, 0).
args(_Fun, _Limit, [], _Max, _) -> ""; %% No args
-args(Fun, _Limit, [Last], _Max, _Pos) ->
- case Fun(Last) of
+args(Fun, _Limit, [Last], _Max, _Pos) ->
+ case Fun(Last) of
skip -> ""; %% FIXME bug if last skips
Str -> Str
end;
args(Fun, Limit, [H|R], Max, Pos) ->
- case Fun(H) of
+ case Fun(H) of
skip -> args(Fun,Limit,R, Max, Pos);
- Str ->
- {NL, NewPos} =
+ Str ->
+ {NL, NewPos} =
case length(Str) + Pos of
Curr when Curr > Max ->
{"\n ", 0};
- Curr ->
+ Curr ->
{"", Curr}
end,
- case args(Fun,Limit,R, Max, NewPos) of
+ case args(Fun,Limit,R, Max, NewPos) of
"" -> Str;
End -> Str ++ Limit ++ NL ++ End
end
end.
-
+
tokens(S) ->
@@ -167,11 +171,11 @@ replace_and_remove([E|R], Acc) when is_list(E) -> %% Keep everything that is a w
replace_and_remove(R, [E|Acc]);
replace_and_remove([$\n | R], Acc) -> %% It is semi line oriented so keep eol
replace_and_remove(R, [eol|Acc]);
-replace_and_remove([$( | R], Acc) ->
+replace_and_remove([$( | R], Acc) ->
replace_and_remove(R, ["("|Acc]);
replace_and_remove([$) | R], Acc) ->
replace_and_remove(R, [")"|Acc]);
-replace_and_remove([${ | R], Acc) ->
+replace_and_remove([${ | R], Acc) ->
replace_and_remove(R, ["{"|Acc]);
replace_and_remove([$} | R], Acc) ->
replace_and_remove(R, ["}"|Acc]);
@@ -187,7 +191,7 @@ replace_and_remove([$, | R], Acc) ->
replace_and_remove(R, [cont|Acc]);
replace_and_remove([$; | R], Acc) ->
replace_and_remove(R, [eoe|Acc]);
-replace_and_remove([$@ | R], Acc) ->
+replace_and_remove([$@ | R], Acc) ->
replace_and_remove(R, [directive|Acc]);
replace_and_remove([_E|R], Acc) -> %% Ignore everthing else
@@ -213,7 +217,7 @@ erl_copyright() ->
w("%%~n",[]),
w("%% %CopyrightBegin%~n",[]),
w("%%~n",[]),
- w("%% Copyright Ericsson AB ~p-2010. All Rights Reserved.~n",
+ w("%% Copyright Ericsson AB ~p-2011. All Rights Reserved.~n",
[StartYear]),
w("%%~n",[]),
w("%% The contents of this file are subject to the Erlang Public License,~n",[]),
@@ -229,11 +233,11 @@ erl_copyright() ->
w("%%~n",[]),
w("%% %CopyrightEnd%~n",[]).
-c_copyright() ->
+c_copyright() ->
w("/*~n",[]),
w(" * %CopyrightBegin%~n",[]),
w(" *~n",[]),
- w(" * Copyright Ericsson AB 2008-2010. All Rights Reserved.~n",[]),
+ w(" * Copyright Ericsson AB 2008-2011. All Rights Reserved.~n",[]),
w(" *~n",[]),
w(" * The contents of this file are subject to the Erlang Public License,~n",[]),
w(" * Version 1.1, (the \"License\"); you may not use this file except in~n",[]),
diff --git a/lib/wx/api_gen/gl_gen.erl b/lib/wx/api_gen/gl_gen.erl
index 374e0bd12b..8998d341e7 100644
--- a/lib/wx/api_gen/gl_gen.erl
+++ b/lib/wx/api_gen/gl_gen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -44,7 +44,7 @@ devcode() -> spawn(fun() -> safe(fun gen_code/0,false) end).
safe(What, QuitOnErr) ->
try
What(),
- io:format("Completed succesfully~n~n", []),
+ io:format("Completed successfully~n~n", []),
QuitOnErr andalso gen_util:halt(0)
catch Err:Reason ->
io:format("Error ~p: ~p:~p~n ~p~n",
diff --git a/lib/wx/api_gen/wx_extra/wxListCtrl.c_src b/lib/wx/api_gen/wx_extra/wxListCtrl.c_src
index cd3074e481..54d6fafd01 100644
--- a/lib/wx/api_gen/wx_extra/wxListCtrl.c_src
+++ b/lib/wx/api_gen/wx_extra/wxListCtrl.c_src
@@ -1,3 +1,161 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+
+<<wxListCtrl_class
+class EwxListCtrl : public wxListCtrl {
+ public: ~EwxListCtrl();
+ EwxListCtrl(wxWindow * parent,wxWindowID winid,const wxPoint& pos,const wxSize& size,long style,const wxValidator& validator) : wxListCtrl(parent,winid,pos,size,style,validator) {};
+ EwxListCtrl() : wxListCtrl() {};
+
+ int onGetItemText;
+ int onGetItemAttr;
+ int onGetItemColumnImage;
+ ErlDrvPort port;
+
+ private:
+ virtual wxString OnGetItemText(long item, long col) const;
+ virtual wxListItemAttr* OnGetItemAttr(long item) const;
+ virtual int OnGetItemImage(long item) const;
+ virtual int OnGetItemColumnImage(long item, long column) const;
+};
+wxListCtrl_class>>
+
+<<wxListCtrl_new_0
+case ~s: { // wxListCtrl::wxListCtrl
+ wxListCtrl * Result = new EwxListCtrl();
+ newPtr((void *) Result, 0, memenv);
+ rt.addRef(getRef((void *)Result,memenv), "wxListCtrl");
+ break;
+}
+wxListCtrl_new_0>>
+
+<<wxListCtrl_new_2
+case ~s: { // wxListCtrl::wxListCtrl
+ wxWindowID winid=wxID_ANY;
+ wxPoint pos= wxDefaultPosition;
+ wxSize size= wxDefaultSize;
+ long style=wxLC_ICON;
+ const wxValidator * validator= &wxDefaultValidator;
+ wxWindow *parent = (wxWindow *) getPtr(bp,memenv); bp += 4;
+ int onGetItemText = 0, onGetItemAttr = 0, onGetItemColumnImage = 0;
+
+ bp += 4; /* Align */
+ while( * (int*) bp) { switch (* (int*) bp) {
+ case 1: {bp += 4;
+ winid = (wxWindowID)*(int *) bp; bp += 4;
+ } break;
+ case 2: {bp += 4;
+ int * posX = (int *) bp; bp += 4;
+ int * posY = (int *) bp; bp += 4;
+ pos = wxPoint(*posX,*posY);
+ bp += 4; /* Align */
+ } break;
+ case 3: {bp += 4;
+ int * sizeW = (int *) bp; bp += 4;
+ int * sizeH = (int *) bp; bp += 4;
+ size = wxSize(*sizeW,*sizeH);
+ bp += 4; /* Align */
+ } break;
+ case 4: {bp += 4;
+ style = (long)*(int *) bp; bp += 4;
+ } break;
+ case 5: {bp += 4;
+validator = (wxValidator *) getPtr(bp,memenv); bp += 4;
+ } break;
+ case 6: {bp += 4;
+ onGetItemText = *(int *) bp; bp += 4;
+ } break;
+ case 7: {bp += 4;
+ onGetItemAttr = *(int *) bp; bp += 4;
+ } break;
+ case 8: {bp += 4;
+ onGetItemColumnImage = *(int *) bp; bp += 4;
+ } break;
+ }};
+ EwxListCtrl * Result = new EwxListCtrl(parent,winid,pos,size,style,*validator);
+ Result->onGetItemText = onGetItemText;
+ Result->onGetItemAttr = onGetItemAttr;
+ Result->onGetItemColumnImage = onGetItemColumnImage;
+ Result->port = Ecmd.port;
+ newPtr((void *) Result, 0, memenv);
+ rt.addRef(getRef((void *)Result,memenv), "wxListCtrl");
+ break;
+}
+wxListCtrl_new_2>>
+
+<<Create
+case ~s: { // wxListCtrl::Create
+ wxWindowID winid=wxID_ANY;
+ wxPoint pos= wxDefaultPosition;
+ wxSize size= wxDefaultSize;
+ long style=wxLC_ICON;
+ const wxValidator * validator= &wxDefaultValidator;
+ EwxListCtrl *This = (EwxListCtrl *) getPtr(bp,memenv); bp += 4;
+ wxWindow *parent = (wxWindow *) getPtr(bp,memenv); bp += 4;
+ int onGetItemText = 0, onGetItemAttr = 0, onGetItemColumnImage = 0;
+
+ bp += 4; /* Align */
+ while( * (int*) bp) { switch (* (int*) bp) {
+ case 1: {bp += 4;
+ winid = (wxWindowID)*(int *) bp; bp += 4;
+ } break;
+ case 2: {bp += 4;
+ int * posX = (int *) bp; bp += 4;
+ int * posY = (int *) bp; bp += 4;
+ pos = wxPoint(*posX,*posY);
+ bp += 4; /* Align */
+ } break;
+ case 3: {bp += 4;
+ int * sizeW = (int *) bp; bp += 4;
+ int * sizeH = (int *) bp; bp += 4;
+ size = wxSize(*sizeW,*sizeH);
+ bp += 4; /* Align */
+ } break;
+ case 4: {bp += 4;
+ style = (long)*(int *) bp; bp += 4;
+ } break;
+ case 5: {bp += 4;
+validator = (wxValidator *) getPtr(bp,memenv); bp += 4;
+ } break;
+ case 6: {bp += 4;
+ onGetItemText = *(int *) bp; bp += 4;
+ } break;
+ case 7: {bp += 4;
+ onGetItemAttr = *(int *) bp; bp += 4;
+ } break;
+ case 8: {bp += 4;
+ onGetItemColumnImage = *(int *) bp; bp += 4;
+ } break;
+ }};
+ if(!This) throw wxe_badarg(0);
+ bool Result = This->Create(parent,winid,pos,size,style,*validator);
+ This->onGetItemText = onGetItemText;
+ This->onGetItemAttr = onGetItemAttr;
+ This->onGetItemColumnImage = onGetItemColumnImage;
+ This->port = Ecmd.port;
+
+ rt.addBool(Result);
+ break;
+}
+Create>>
+
<<SortItems
case ~s: { // wxListCtrl::SortItems taylormade
wxListCtrl *This = (wxListCtrl *) getPtr(bp,memenv); bp += 4;
@@ -22,3 +180,6 @@ case ~s: { // wxListCtrl::SortItems taylormade
break;
}
SortItems>>
+
+
+
diff --git a/lib/wx/api_gen/wx_extra/wxListCtrl.erl b/lib/wx/api_gen/wx_extra/wxListCtrl.erl
index e6470182cb..99255bc53f 100644
--- a/lib/wx/api_gen/wx_extra/wxListCtrl.erl
+++ b/lib/wx/api_gen/wx_extra/wxListCtrl.erl
@@ -1,32 +1,33 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
+
<<EXPORT:SortItems sortItems/2 SortItems:EXPORT>>
<<SortItems
%% @spec (This::wxListCtrl(), SortCallBack::function()) -> boolean()
%% @doc Sort the items in the list control<br />
-%% <pre>SortCalBack(Item1,Item2) -> integer()</pre>
+%% <pre>SortCallBack(Item1,Item2) -> integer()</pre>
%% <br /> SortCallBack receives the client data associated with two items
%% to compare, and should return 0 if the items are equal, a negative
%% value if the first item is less than the second one and a positive
%% value if the first item is greater than the second one.
-%% <br /> NOTE: The callback may not call other processes.
+%% <br /> NOTE: The callback may not call other (wx) processes.
sortItems(#wx_ref{type=ThisT,ref=ThisRef}, SortCallBack)
when is_function(SortCallBack, 2) ->
?CLASS(ThisT,wxListCtrl),
@@ -37,3 +38,100 @@ sortItems(#wx_ref{type=ThisT,ref=ThisRef}, SortCallBack)
SortId = wxe_util:get_cbId(Sort),
wxe_util:call(~s, <<ThisRef:32/?UI,SortId:32/?UI>>).
SortItems>>
+
+<<EXPORT:wxListCtrl new/0, new/1, new/2 wxListCtrl:EXPORT>>
+
+<<wxListCtrl_new_0
+%% @spec () -> wxListCtrl()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlwxlistctrl">external documentation</a>.
+new() ->
+ wxe_util:construct(~s, <<>>).
+wxListCtrl_new_0>>
+
+<<wxListCtrl_new_2
+%% @spec (Parent::wxWindow:wxWindow()) -> wxListCtrl()
+%% @equiv new(Parent, [])
+new(Parent)
+ when is_record(Parent, wx_ref) ->
+ new(Parent, []).
+
+%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxListCtrl()
+%% Option = {winid, integer()} |
+%% {pos, {X::integer(),Y::integer()}} |
+%% {size, {W::integer(),H::integer()}} |
+%% {style, integer()} |
+%% {validator, wx:wx()} |
+%% {onGetItemText, OnGetItemText} |
+%% {onGetItemAttr, OnGetItemAttr} |
+%% {onGetItemColumnImage, OnGetItemColumnImage}
+%%
+%% OnGetItemText = (This, Item, Column) -> wxString()
+%% OnGetItemAttr = (This, Item) -> wxListItemAttr()
+%% OnGetItemColumnImage = (This, Item, Column) -> integer()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlwxlistctrl">external documentation</a>.
+
+new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
+ when is_list(Options)->
+ ?CLASS(ParentT,wxWindow),
+ MOpts = fun({winid, Winid}, Acc) -> [<<1:32/?UI,Winid:32/?UI>>|Acc];
+ ({pos, {PosX,PosY}}, Acc) -> [<<2:32/?UI,PosX:32/?UI,PosY:32/?UI,0:32>>|Acc];
+ ({size, {SizeW,SizeH}}, Acc) -> [<<3:32/?UI,SizeW:32/?UI,SizeH:32/?UI,0:32>>|Acc];
+ ({style, Style}, Acc) -> [<<4:32/?UI,Style:32/?UI>>|Acc];
+ ({validator, #wx_ref{type=ValidatorT,ref=ValidatorRef}}, Acc) ->
+ ?CLASS(ValidatorT,wx),[<<5:32/?UI,ValidatorRef:32/?UI>>|Acc];
+ ({onGetItemText, F}, Acc) when is_function(F) ->
+ Fun = fun([This,Item,Col]) -> unicode:characters_to_binary([F(This,Item,Col),0]) end,
+ [<<6:32/?UI,(wxe_util:get_cbId(Fun)):32/?UI>>|Acc];
+ ({onGetItemAttr, F}, Acc) when is_function(F) ->
+ Fun = fun([This,Item]) ->
+ #wx_ref{type=wxListItemAttr,ref=ThisRef} = F(This,Item),
+ <<ThisRef:32/?UI>>
+ end,
+ [<<7:32/?UI,(wxe_util:get_cbId(Fun)):32/?UI>>|Acc];
+ ({onGetItemColumnImage, F}, Acc) when is_function(F) ->
+ Fun = fun([This,Item, Col]) -> <<(F(This,Item,Col)):32/?I>> end,
+ [<<8:32/?UI,(wxe_util:get_cbId(Fun)):32/?UI>>|Acc];
+ (BadOpt, _) -> erlang:error({badoption, BadOpt}) end,
+ BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)),
+ wxe_util:construct(~s, <<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
+
+wxListCtrl_new_2>>
+
+<<EXPORT:Create create/2, create/3 Create:EXPORT>>
+
+<<Create
+%% @spec (This::wxListCtrl(), Parent::wxWindow:wxWindow()) -> bool()
+%% @equiv create(This,Parent, [])
+create(This,Parent)
+ when is_record(This, wx_ref),is_record(Parent, wx_ref) ->
+ create(This,Parent, []).
+
+%% @spec (This::wxListCtrl(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
+%% Option = {winid, integer()} |
+%% {pos, {X::integer(),Y::integer()}} |
+%% {size, {W::integer(),H::integer()}} |
+%% {style, integer()} |
+%% {validator, wx:wx()} |
+%% {onGetItemText, OnGetItemText} |
+%% {onGetItemAttr, OnGetItemAttr} |
+%% {onGetItemColumnImage, OnGetItemColumnImage}
+%%
+%% OnGetItemText = (This, Item, Column) -> wxString()
+%% OnGetItemAttr = (This, Item) -> wxListItemAttr()
+%% OnGetItemColumnImage = (This, Item, Column) -> integer()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlcreate">external documentation</a>.
+create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
+ when is_list(Options) ->
+ ?CLASS(ThisT,wxListCtrl),
+ ?CLASS(ParentT,wxWindow),
+ MOpts = fun({winid, Winid}, Acc) -> [<<1:32/?UI,Winid:32/?UI>>|Acc];
+ ({pos, {PosX,PosY}}, Acc) -> [<<2:32/?UI,PosX:32/?UI,PosY:32/?UI,0:32>>|Acc];
+ ({size, {SizeW,SizeH}}, Acc) -> [<<3:32/?UI,SizeW:32/?UI,SizeH:32/?UI,0:32>>|Acc];
+ ({style, Style}, Acc) -> [<<4:32/?UI,Style:32/?UI>>|Acc];
+ ({validator, #wx_ref{type=ValidatorT,ref=ValidatorRef}}, Acc) -> ?CLASS(ValidatorT,wx),[<<5:32/?UI,ValidatorRef:32/?UI>>|Acc];
+ (BadOpt, _) -> erlang:error({badoption, BadOpt}) end,
+ BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)),
+ wxe_util:call(~s,
+ <<ThisRef:32/?UI,ParentRef:32/?UI, BinOpt/binary>>).
+
+Create>>
diff --git a/lib/wx/api_gen/wx_gen.erl b/lib/wx/api_gen/wx_gen.erl
index 2f20c42a5d..209de48496 100644
--- a/lib/wx/api_gen/wx_gen.erl
+++ b/lib/wx/api_gen/wx_gen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The 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,6 +30,12 @@
-compile(export_all).
+-define(DBGCF(Class, Func, Format, Args),
+ case {get(current_class), get(current_func)} of
+ {Class, Func} -> io:format("~p:~p: " ++ Format, [?MODULE,?LINE] ++ Args);
+ _ -> ok
+ end).
+
code() -> safe(fun gen_code/0,true).
xml() -> safe(fun gen_xml/0,true).
@@ -38,7 +44,7 @@ devcode() -> erase(),safe(fun gen_code/0,false).
safe(What, QuitOnErr) ->
try
What(),
- io:format("Completed succesfully~n~n", []),
+ io:format("Completed successfully~n~n", []),
QuitOnErr andalso gen_util:halt(0)
catch Err:Reason ->
io:format("Error in ~p ~p~n", [get(current_class),get(current_func)]),
@@ -957,17 +963,17 @@ erl_skip_opt(All=[Ms=[{_,{Len,_,_},_}|_]|R],Acc1=[{_,{N,_,_},_}|_], Acc2) ->
end;
erl_skip_opt([],Acc1,Acc2) -> [strip_ti(Acc1)|Acc2].
-erl_skip_opt2([F={_,{N,In,_},M=#method{where=Where}}|Ms],Acc1,Acc2,Check) ->
+erl_skip_opt2([F={_,{N,In,_},M=#method{where=Where}}|Ms],Acc1,Acc2,Check) ->
case N > 0 andalso lists:last(In) =:= opt_list of
- true when Where =/= merged_c, Where =/= taylormade ->
- case Check of
- [] ->
+ true when Where =/= merged_c, Where =/= taylormade ->
+ case Check of
+ [] ->
erl_skip_opt2(Ms,[F|Acc1],[M#method{where=erl_no_opt}|Acc2],[]);
- _ ->
+ _ ->
Skipped = reverse(tl(reverse(In))),
T = fun({_,{_,Args,_},_}) -> true =:= types_differ(Skipped,Args) end,
case lists:all(T, Check) of
- true ->
+ true ->
erl_skip_opt2(Ms,[F|Acc1],
[M#method{where=erl_no_opt}|Acc2],
Check);
@@ -976,7 +982,7 @@ erl_skip_opt2([F={_,{N,In,_},M=#method{where=Where}}|Ms],Acc1,Acc2,Check) ->
end
end;
_ ->
- erl_skip_opt2(Ms,[F|Acc1],Acc2,[])
+ erl_skip_opt2(Ms,[F|Acc1],Acc2,Check)
end;
erl_skip_opt2([],Acc1,Acc2,_) -> {Acc1,Acc2}.
@@ -1025,7 +1031,6 @@ types_differ([{class,C1}|R1], [{class,C2}|R2]) ->
true ->
true;
false ->
-%% _ ->
{class,C1,C2};
{class,C1,C2} ->
{class,C1,C2};
diff --git a/lib/wx/api_gen/wx_gen_cpp.erl b/lib/wx/api_gen/wx_gen_cpp.erl
index 4b33068d8f..4632fdbffe 100644
--- a/lib/wx/api_gen/wx_gen_cpp.erl
+++ b/lib/wx/api_gen/wx_gen_cpp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The 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,7 +19,7 @@
%%%-------------------------------------------------------------------
%%% File : wx_gen_cpp.erl
%%% Author : Dan Gudmundsson <[email protected]>
-%%% Description :
+%%% Description :
%%%
%%% Created : 19 Feb 2007 by Dan Gudmundsson <[email protected]>
%%%-------------------------------------------------------------------
@@ -35,7 +35,7 @@
args/3, strip_name/2]).
-import(wx_gen, [next_id/1]).
-gen(Defs) ->
+gen(Defs) ->
open_write("../c_src/gen/wxe_derived_dest.h"),
c_copyright(),
w("~n/***** This file is generated do not edit ****/~n~n", []),
@@ -49,48 +49,26 @@ gen(Defs) ->
open_write("../c_src/gen/wxe_macros.h"),
c_copyright(),
- gen_macros(),
+ gen_macros(),
close(),
open_write("../c_src/gen/wxe_init.cpp"),
c_copyright(),
build_enums(),
close(),
-
+
build_events(),
Res.
-
+
gen_derived_dest(Defs) ->
[gen_derived_dest_2(Class) || Class <- Defs],
-
- UglySkipList = ["wxCaret", "wxCalendarDateAttr",
- "wxFileDataObject", "wxTextDataObject", "wxBitmapDataObject"
- ],
-
- ?WTC("gen_derived_dest"),
- w("void WxeApp::delete_object(void *ptr, wxeRefData *refd) {~n", []),
- w(" switch(refd->type) {~n", []),
- Case = fun(#class{name=Class, id=Id, abstract=IsAbs, parent=P}) when P /= "static" ->
- UglyWorkaround = lists:member(Class, UglySkipList),
- case hd(reverse(wx_gen_erl:parents(Class))) of
- root when IsAbs == false, UglyWorkaround == false ->
- w(" case ~p: delete (~s *) ptr; break;~n", [Id, Class]);
- root when IsAbs == false, UglyWorkaround == true ->
- w(" case ~p: /* delete (~s *) ptr;"
- "These objects must be deleted by owner object */ "
- "break;~n", [Id, Class]);
- _ -> ok
- end;
- (_) -> ok
- end,
- [Case(Class) || Class <- Defs],
- w(" default: delete (wxObject *) ptr;~n", []),
- w("}}~n~n", []).
+ ok.
gen_derived_dest_2(C=#class{name=Class}) ->
- case is_derived(C) of
- true ->
- ?WTC("gen_derived_dest_2"),
+ ?WTC("gen_derived_dest_2"),
+ Derived = is_derived(C),
+ TaylorMade = taylormade_class(C),
+ if Derived andalso (TaylorMade =:= false) ->
w("class E~s : public ~s {~n",[Class,Class]),
case Class of
"wxGLCanvas" -> %% Special for cleaning up gl context
@@ -101,15 +79,32 @@ gen_derived_dest_2(C=#class{name=Class}) ->
end,
gen_constructors(C),
w("};~n~n", []);
- false ->
+ TaylorMade /= false ->
+ w("~s~n", [TaylorMade]);
+ true ->
ignore
end.
+taylormade_class(#class{name=CName, methods=Ms}) ->
+ TaylorMade = lists:any(fun([#method{where=taylormade}|_]) -> true;
+ (_) -> false
+ end, Ms),
+ case TaylorMade of
+ false -> false;
+ true ->
+ {ok, Bin} = file:read_file(filename:join([wx_extra, CName ++".c_src"])),
+ Src = binary_to_list(Bin),
+ case gen_util:get_taylor_made(Src, CName ++ "_class") of
+ nomatch -> false;
+ {match, [Str0]} -> Str0
+ end
+ end.
+
gen_constructors(#class{name=Class, methods=Ms0}) ->
Ms = lists:append(Ms0),
Cs = lists:filter(fun(#method{method_type=MT}) -> MT =:= constructor end, Ms),
[gen_constructor(Class, Const) || Const <- Cs].
-
+
gen_constructor(_Class, #method{where=merged_c}) -> ok;
gen_constructor(_Class, #method{where=erl_no_opt}) -> ok;
gen_constructor(Class, _M=#method{params=Ps}) ->
@@ -119,7 +114,7 @@ gen_constructor(Class, _M=#method{params=Ps}) ->
HaveMergedType = fun(#param{type={merged,_,_,_,_,_,_}}) -> true; (_) -> false end,
?WTC("gen_constructor"),
case lists:any(HaveMergedType, Ps) of
- false ->
+ false ->
w(" E~s(~s) : ~s(~s) {};~n",
[Class,args(Gen1,",",Ps),Class,args(CallA,",",Ps)]);
true ->
@@ -141,9 +136,9 @@ gen_type(#type{name=Type, ref=undefined, single=array, mod=Mod},_) ->
mods(Mod) ++ to_string(Type) ++ " * ";
gen_type(#type{name=Type, ref=undefined, mod=Mod},_) ->
mods(Mod) ++ to_string(Type) ++ " ";
-gen_type({merged, _, T1, _,_, _T2,_}, 1) ->
+gen_type({merged, _, T1, _,_, _T2,_}, 1) ->
gen_type(T1,error);
-gen_type({merged, _, _T1,_, _, T2,_}, 2) ->
+gen_type({merged, _, _T1,_, _, T2,_}, 2) ->
gen_type(T2,error).
gen_funcs(Defs) ->
@@ -168,7 +163,7 @@ gen_funcs(Defs) ->
%% w(" case WXE_REMOVE_PORT:~n", []),
%% w(" { destroyMemEnv(Ecmd.port); } break;~n", []),
w(" case DESTROY_OBJECT: {~n"),
- w(" wxObject *This = (wxObject *) getPtr(bp,memenv); "),
+ w(" wxObject *This = (wxObject *) getPtr(bp,memenv); "),
w(" if(This) {"),
w(" ((WxeApp *) wxTheApp)->clearPtr((void *) This);~n"),
w(" delete This; }~n } break;~n"),
@@ -203,16 +198,39 @@ gen_funcs(Defs) ->
w(" error.addTupleCount(2);~n"),
w(" error.addTupleCount(3);~n"),
w(" error.send();~n"),
- w("}} /* The End */~n"),
+ w("}} /* The End */~n~n~n"),
+
+ UglySkipList = ["wxCaret", "wxCalendarDateAttr",
+ "wxFileDataObject", "wxTextDataObject", "wxBitmapDataObject"
+ ],
+
+ w("void WxeApp::delete_object(void *ptr, wxeRefData *refd) {~n", []),
+ w(" switch(refd->type) {~n", []),
+ Case = fun(#class{name=Class, id=Id, abstract=IsAbs, parent=P}) when P /= "static" ->
+ UglyWorkaround = lists:member(Class, UglySkipList),
+ case hd(reverse(wx_gen_erl:parents(Class))) of
+ root when IsAbs == false, UglyWorkaround == false ->
+ w(" case ~p: delete (~s *) ptr; break;~n", [Id, Class]);
+ root when IsAbs == false, UglyWorkaround == true ->
+ w(" case ~p: /* delete (~s *) ptr;"
+ "These objects must be deleted by owner object */ "
+ "break;~n", [Id, Class]);
+ _ -> ok
+ end;
+ (_) -> ok
+ end,
+ [Case(Class) || Class <- Defs],
+ w(" default: delete (wxObject *) ptr;~n", []),
+ w("}}~n~n", []),
Res.
-
+
gen_class(C=#class{name=Name,methods=Ms,options=Opts}) ->
put(current_class, Name),
- NewMs =
+ NewMs =
case lists:member(taylormade, Opts) of
true ->
{ok, Bin} = file:read_file(filename:join([wx_extra,Name++".c_src"])),
- ?WTC("gen_class"),
+ ?WTC("gen_class"),
w("~s~n", [binary_to_list(Bin)]),
Ms;
false ->
@@ -220,13 +238,13 @@ gen_class(C=#class{name=Name,methods=Ms,options=Opts}) ->
{value, {ifdef, What}} ->
w("#if ~p~n",[What]),
Methods = lists:flatten(Ms),
- MsR = [gen_method(Name,M) ||
+ MsR = [gen_method(Name,M) ||
M <- lists:keysort(#method.id, Methods)],
w("#endif // ~p~n",[What]),
MsR;
false ->
Methods = lists:flatten(Ms),
- [gen_method(Name,M) ||
+ [gen_method(Name,M) ||
M <- lists:keysort(#method.id, Methods)]
end
end,
@@ -234,15 +252,19 @@ gen_class(C=#class{name=Name,methods=Ms,options=Opts}) ->
C#class{methods=NewMs}.
gen_method(_CName, M=#method{where=erl_no_opt}) -> M;
-gen_method(CName, M=#method{where=taylormade, name=Name, id=Id}) ->
+gen_method(CName, M=#method{where=taylormade, name=Name, id=Id}) ->
{ok, Bin} = file:read_file(filename:join([wx_extra, CName ++".c_src"])),
- Str0 = binary_to_list(Bin),
+ Src = binary_to_list(Bin),
%% io:format("C++ Class ~p ~p~n", [CName, Name]),
-
- {match, [Str1]} = re:run(Str0, "<<"++Name++"(.*)"++Name++">>",
- [dotall, {capture, all_but_first, list}]),
+ Str = case gen_util:get_taylor_made(Src, Name) of
+ nomatch ->
+ {match, [Str0]} = gen_util:get_taylor_made(Src, wx_gen_erl:get_unique_name(Id)),
+ Str0;
+ {match, [Str0]} ->
+ Str0
+ end,
?WTC("gen_method"),
- w(Str1, [wx_gen_erl:get_unique_name(Id)]),
+ w(Str, [wx_gen_erl:get_unique_name(Id)]),
M;
gen_method(CName, M=#method{name=N,params=[Ps],method_type=destructor,id=MethodId}) ->
case hd(reverse(wx_gen_erl:parents(CName))) of
@@ -253,7 +275,7 @@ gen_method(CName, M=#method{name=N,params=[Ps],method_type=destructor,id=MethodI
w(" if(This) {", []),
w(" ((WxeApp *) wxTheApp)->clearPtr((void *) This);~n", []),
w(" delete This;}~n", []),
- free_args(),
+ free_args(),
w(" break;~n}~n", []);
object -> %% Use default
ignore
@@ -266,7 +288,7 @@ gen_method(CName, M=#method{name=N,params=Ps0,type=T,method_type=MT,id=MethodId
w("case ~s: { // ~s::~s~n", [wx_gen_erl:get_unique_name(MethodId),CName,N]),
Ps1 = declare_variables(void, Ps0),
{Ps2,Align} = decode_arguments(Ps1),
- Opts = [Opt || Opt = #param{def=Def,in=In,where=Where} <- Ps2,
+ Opts = [Opt || Opt = #param{def=Def,in=In,where=Where} <- Ps2,
Def =/= none, In =/= false, Where =/= c],
decode_options(Opts, Align),
case gen_util:get_hook(c, M#method.pre_hook) of
@@ -292,7 +314,7 @@ declare_variables(T, Ps) ->
declare_var(P = #param{where=erl}) -> P;
declare_var(P = #param{where=this}) -> P;
-declare_var(P = #param{name=Name,def=Def,type=Type,in=true}) when Def =/= none ->
+declare_var(P = #param{name=Name,def=Def,type=Type,in=true}) when Def =/= none ->
declare_type(Name, true, Def, Type),
P;
declare_var(P = #param{in=In}) when In =/= false -> P;
@@ -304,7 +326,7 @@ declare_type(N,false,_,#type{name="wxArrayInt"}) ->
w(" wxArrayInt ~s;~n", [N]);
declare_type(N,false,_,#type{name="wxArrayString"}) ->
w(" wxArrayString ~s;~n", [N]);
-declare_type(N,false,_,#type{base=Base,single=true,name=Type,by_val=false,mod=Mod})
+declare_type(N,false,_,#type{base=Base,single=true,name=Type,by_val=false,mod=Mod})
when Base =:= int; Base =:= long; Base =:= float; Base =:= double ->
w(" ~s~s ~s;~n", [mods(Mod),Type,N]);
declare_type(N,false,_,#type{base={enum,_},single=true,name=Type,by_val=false,mod=Mod}) ->
@@ -315,7 +337,7 @@ declare_type(N,false,_,#type{name="wxDateTime"}) ->
w(" wxDateTime ~s;~n", [N]);
declare_type(N,false,_,#type{name=Type, base=int64, ref=reference}) ->
w(" ~s ~s;~n", [Type,N]);
-declare_type(N,true,Def,#type{base=Base,single=true,name=Type,by_val=true})
+declare_type(N,true,Def,#type{base=Base,single=true,name=Type,by_val=true})
when Base =:= int; Base =:= long; Base =:= float; Base =:= double; Base =:= bool ->
w(" ~s ~s=~s;~n", [Type,N,Def]);
declare_type(N,true,Def,#type{base={comp,_,_},single=true,name=Type,mod=Mod,ref={pointer,1}}) ->
@@ -328,7 +350,7 @@ declare_type(N,true,Def,#type{base={class,_},single=true,name=Type,ref={pointer,
w(" ~s~s * ~s=~s;~n", [mods(Mod),Type,N,Def]);
declare_type(N,true,Def,#type{base={class,_},single=true,name=Type,ref=reference,mod=Mod}) ->
w(" ~s~s * ~s= &~s;~n", [mods(Mod),Type,N,Def]);
-declare_type(N,true,Def,#type{base=Base,single=true,name=Type,by_val=false,ref={pointer,1}})
+declare_type(N,true,Def,#type{base=Base,single=true,name=Type,by_val=false,ref={pointer,1}})
when Base =:= int; Base =:= long; Base =:= float; Base =:= double; Base =:= bool ->
w(" ~s *~s=~s;~n", [Type,N,Def]);
declare_type(N,true,Def,#type{single=true,name="wxArtClient"}) ->
@@ -345,7 +367,7 @@ declare_type(N,true,Def,#type{name=Type, ref={pointer,2}}) ->
%% xxxx
w(" ~s ** ~s = ~s;~n", [Type,N,Def]);
declare_type(N,true,Def,#type{name=Type, single=array, ref={pointer,1}}) ->
- w(" int * ~sLen = 0;~n", [N]),
+ w(" int * ~sLen = 0;~n", [N]),
w(" ~s * ~s = ~s;~n", [Type,N,Def]);
declare_type(N,true,"",#type{name="wxArrayString", single=array, ref=reference}) ->
w(" wxArrayString ~s;~n", [N]);
@@ -363,12 +385,12 @@ decode_options(Opts, Align) ->
decode_opt(#param{name=Name,type=Type}, N) ->
w(" case ~p: {bp += 4;~n", [N]),
- Align = decode_arg(Name,Type,opt,1),
+ Align = decode_arg(Name,Type,opt,1),
align(Align, 64),
w(" } break;~n", []),
N+1.
-decode_arguments(Ps0) ->
+decode_arguments(Ps0) ->
lists:mapfoldl(fun decode_arg/2,0,Ps0).
store_free(N) ->
@@ -380,7 +402,7 @@ store_free(N) ->
free_args() ->
case get(free_args) of
undefined -> ignore;
- List ->
+ List ->
erase(free_args),
[w(" driver_free(~s);~n", [Arg]) || Arg <- List]
end.
@@ -388,7 +410,7 @@ free_args() ->
decode_arg(P = #param{where=erl},A) -> {P,A};
decode_arg(P = #param{where=c},A) -> {P,A};
decode_arg(P = #param{in=false},A) -> {P,A};
-decode_arg(P = #param{def=Def},A) when Def =/= none -> {P,A};
+decode_arg(P = #param{def=Def},A) when Def =/= none -> {P,A};
decode_arg(P = #param{name=Name,type=Type},A0) ->
A = decode_arg(Name, Type, arg, A0),
{P, A}.
@@ -426,22 +448,22 @@ decode_arg(N,#type{base=float,single=true,name=Type},arg,A0) ->
align(A0,32);
decode_arg(N,#type{base=double,single=true,name=Type},Arg,A0) ->
A = align(A0,64),
- case Arg of
+ case Arg of
arg -> w(" ~s * ~s = (~s *) bp; bp += 8;~n", [Type,N,Type]);
opt -> w(" ~s = * (~s *) bp; bp += 8;~n", [N,Type])
end,
A;
decode_arg(N,#type{base=bool,single=true,name=Type},Arg,A0) ->
- case Arg of
+ case Arg of
arg -> w(" bool * ~s = (~s *) bp; bp += 4;~n", [N,Type]);
opt -> w(" ~s = *(~s *) bp; bp += 4;~n", [N,Type])
end,
align(A0,32);
decode_arg(N,#type{base={enum,Type},single=true},Arg,A0) ->
- wa(" ~s ", [enum_type(Type)], "~s = *(~s *) bp; bp += 4;;~n",[N, enum_type(Type)], Arg),
+ wa(" ~s ", [enum_type(Type)], "~s = *(~s *) bp; bp += 4;;~n",[N, enum_type(Type)], Arg),
align(A0,32);
decode_arg(N,#type{base={comp,"wxDateTime",List},single=true,name=Type,ref=Ref},Arg,A0) ->
- Decl = fun({int,Spec}) ->
+ Decl = fun({int,Spec}) ->
w(" int * ~s~s = (int *) bp; bp += 4;~n", [N,Spec])
end,
align(A0,32),
@@ -452,15 +474,15 @@ decode_arg(N,#type{base={comp,"wxDateTime",List},single=true,name=Type,ref=Ref},
end,
case Arg of
arg -> w(" ~s ~s = ~s(~s);~n", [Type,N,Type,args(Name, ",", List)]);
- opt when Ref =:= {pointer,1} ->
- w(" ~sTmp = ~s(~s); ~s = & ~sTmp;~n",
+ opt when Ref =:= {pointer,1} ->
+ w(" ~sTmp = ~s(~s); ~s = & ~sTmp;~n",
[N,Type,args(Name, ",", List), N,N]);
opt ->
w(" ~s = ~s(~s);~n", [N,Type,args(Name, ",", List)])
end,
(A0+length(List)) rem 2;
decode_arg(N,#type{base={comp,_,List},single=true,name=Type,ref=Ref},Arg,A0) ->
- Decl = fun({int,Spec}) ->
+ Decl = fun({int,Spec}) ->
w(" int * ~s~s = (int *) bp; bp += 4;~n", [N,Spec]);
({double, Spec}) ->
w(" wxDouble * ~s~s = (wxDouble *) bp; bp += 8;~n", [N,Spec])
@@ -473,8 +495,8 @@ decode_arg(N,#type{base={comp,_,List},single=true,name=Type,ref=Ref},Arg,A0) ->
Name = fun({_,Spec}) -> "*"++N++Spec end,
case Arg of
arg -> w(" ~s ~s = ~s(~s);~n", [Type,N,Type,args(Name, ",", List)]);
- opt when Ref =:= {pointer,1} ->
- w(" ~sTmp = ~s(~s); ~s = & ~sTmp;~n",
+ opt when Ref =:= {pointer,1} ->
+ w(" ~sTmp = ~s(~s); ~s = & ~sTmp;~n",
[N,Type,args(Name, ",", List), N,N]);
opt ->
w(" ~s = ~s(~s);~n", [N,Type,args(Name, ",", List)])
@@ -483,7 +505,7 @@ decode_arg(N,#type{base={comp,_,List},single=true,name=Type,ref=Ref},Arg,A0) ->
{int, _} -> (A0+length(List)) rem 2;
{double, _} -> 0
end;
-
+
decode_arg(N,#type{name=Class="wxTreeItemId",single=true},Arg,A0) ->
A = align(A0,64),
wa(" ~s ",[Class],"~s = wxTreeItemId((void *) *(wxUint64 *) bp); bp += 8;~n",[N],Arg),
@@ -492,7 +514,7 @@ decode_arg(N,#type{name=Class="wxTreeItemIdValue",single=true},Arg,A0) ->
A = align(A0,64),
wa(" ~s ",[Class],"~s = (~s) * (wxUint64 *) bp; bp += 8;~n",[N,Class],Arg),
A;
-decode_arg(N,#type{name="wxChar", single=S},Arg,A0)
+decode_arg(N,#type{name="wxChar", single=S},Arg,A0)
when S =/= true ->
w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
wa(" wxString", []," ~s = wxString(bp, wxConvUTF8);~n", [N],Arg),
@@ -501,7 +523,7 @@ decode_arg(N,#type{name="wxChar", single=S},Arg,A0)
decode_arg(N,#type{base=string, name="wxFileName"},Arg,A0) ->
w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
wa(" wxString", []," ~sStr = wxString(bp, wxConvUTF8);~n", [N],Arg),
- w(" bp += *~sLen+((8-((~p+ *~sLen) & 7)) & 7);~n", [N,4*((A0+1) rem 2),N]),
+ w(" bp += *~sLen+((8-((~p+ *~sLen) & 7)) & 7);~n", [N,4*((A0+1) rem 2),N]),
w(" wxFileName ~s = wxFileName(~sStr);~n",[N,N]),
0;
decode_arg(N,#type{base=string},Arg,A0) ->
@@ -541,7 +563,7 @@ decode_arg(N,#type{name="wxArrayDouble"},arg,A0) ->
decode_arg(_N,#type{base=eventType},_Arg,A0) ->
%% w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
%% case Arg of
-%% arg ->
+%% arg ->
%% w(" int ~s = wxeEventTypeFromAtom(bp);bp += *~sLen;~n",[N,N]),
%% w(" char *class_name = bp;~n", []),
%% w(" wxeCallbackData * Evt_cb = new wxeCallbackData(Ecmd.caller,This,class_name);~n",
@@ -551,7 +573,7 @@ decode_arg(_N,#type{base=eventType},_Arg,A0) ->
decode_arg(N,#type{name=Type,base=binary,mod=Mod0},Arg,A0) ->
Mod = mods([M || M <- Mod0]),
case Arg of
- arg ->
+ arg ->
w(" ~s~s * ~s = (~s~s*) Ecmd.bin[~p]->base;~n",
[Mod,Type,N,Mod,Type, next_id(bin_count)]);
opt ->
@@ -564,10 +586,10 @@ decode_arg(N,#type{base={term,"wxTreeItemData"},mod=Mod0},Arg,A0) ->
Type = "wxETreeItemData",
BinCnt = next_id(bin_count),
case Arg of
- arg ->
+ arg ->
w(" ~s~s * ~s = new ~s(Ecmd.bin[~p]->size, Ecmd.bin[~p]->base);~n",
[Mod,Type,N,Type,BinCnt,BinCnt]);
- opt ->
+ opt ->
w(" ~s = new ~s(Ecmd.bin[~p]->size, Ecmd.bin[~p]->base);~n",
[N,Type,BinCnt,BinCnt])
end,
@@ -576,10 +598,10 @@ decode_arg(N,#type{name=Type,base={term,_},mod=Mod0},Arg,A0) ->
Mod = mods([M || M <- Mod0]),
BinCnt = next_id(bin_count),
case Arg of
- arg ->
+ arg ->
w(" ~s~s * ~s = new ~s(Ecmd.bin[~p]);~n",
[Mod,Type,N,Type,BinCnt]);
- opt ->
+ opt ->
w(" ~s = new ~s(Ecmd.bin[~p]);~n",
[N,Type,BinCnt])
end,
@@ -588,17 +610,17 @@ decode_arg(N,#type{single=array,base=int},Arg,A0) ->
case Arg of
arg ->
w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
- w(" int * ~s = (int *) bp; bp += *~sLen*4+((~p+ *~sLen)%2 )*4;~n",
+ w(" int * ~s = (int *) bp; bp += *~sLen*4+((~p+ *~sLen)%2 )*4;~n",
[N,N,(A0+1) rem 2,N]);
- opt ->
+ opt ->
w(" ~sLen = (int *) bp; bp += 4;~n", [N]),
- w(" ~s = (int *) bp; bp += *~sLen*4+((~p+ *~sLen)%2 )*4;~n",
+ w(" ~s = (int *) bp; bp += *~sLen*4+((~p+ *~sLen)%2 )*4;~n",
[N,N,(A0+1) rem 2,N])
end,
0;
decode_arg(N,#type{by_val=true,single=array,base={comp,Class="wxPoint",_}},arg,A0) ->
- w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
- w(" ~s *~s;~n",[Class,N]),
+ w(" int * ~sLen = (int *) bp; bp += 4;~n", [N]),
+ w(" ~s *~s;~n",[Class,N]),
w(" ~s = (~s *) driver_alloc(sizeof(~s) * *~sLen);~n",[N,Class,Class,N]),
store_free(N),
w(" for(int i=0; i < *~sLen; i++) {~n", [N]),
@@ -629,13 +651,13 @@ decode_arg(Name,T, Arg,_A) ->
align(0, 32) -> 1;
align(1, 32) -> 0;
align(0, 64) -> 0;
-align(1, 64) ->
+align(1, 64) ->
w(" bp += 4; /* Align */~n"),
0;
align(N,Sz) ->
align(N rem 2, Sz).
-call_wx(_N,{constructor,_},#type{base={class,RClass}},Ps) ->
+call_wx(_N,{constructor,_},#type{base={class,RClass}},Ps) ->
#class{id=Id} = ClassDef = get({class,RClass}),
Class = case is_derived(ClassDef) of
true -> "E" ++ RClass;
@@ -648,8 +670,8 @@ call_wx(_N,{constructor,_},#type{base={class,RClass}},Ps) ->
case is_dialog(RClass) of
true -> 2; %% Dialogs must be closed first event before windows
false -> 0
- end;
- false ->
+ end;
+ false ->
case hd(reverse(wx_gen_erl:parents(RClass))) of
root -> Id;
_ -> 1
@@ -682,10 +704,10 @@ call_wx(N,{static,Class},Type,Ps) ->
return_res(void) -> {"", ""};
return_res(Type = #type{mod=Mod}) ->
case lists:member(const, Mod) of
- true ->
- {Beg, End} = return_res1(Type),
+ true ->
+ {Beg, End} = return_res1(Type),
{"const " ++ Beg, End};
- _ ->
+ _ ->
return_res1(Type)
end.
@@ -695,8 +717,8 @@ return_res1(#type{name=Type,ref={pointer,_}}) ->
{Type ++ " * Result = (" ++ Type ++ "*)", ""};
return_res1(#type{name=Type,single=true,ref=reference}) ->
{Type ++ " * Result = &", ""};
-return_res1(#type{name=Type,single=true,by_val=true})
- when is_atom(Type) ->
+return_res1(#type{name=Type,single=true,by_val=true})
+ when is_atom(Type) ->
{atom_to_list(Type) ++ " Result = ", ""};
return_res1(#type{name=Type="wxArrayInt"}) ->
{Type ++ " Result = ", ""};
@@ -705,19 +727,19 @@ return_res1(#type{name=Type,base={class,_},single=list,ref=reference}) ->
return_res1(#type{name=Type,base={comp,_,_},single=array,by_val=true}) ->
{Type ++ " Result = ", ""};
return_res1(#type{name=Type,single=true,by_val=true, base={class, _}}) ->
- %% Memory leak !!!!!! XXXX BUGBUG FIXME or doument!!
- case Type of
+ %% Memory leak !!!!!! XXXX BUGBUG FIXME or doument!!
+ case Type of
"wxImage" -> ok;
"wxFont" -> ok;
"wxBitmap" -> ok;
"wxIcon" -> ok;
"wxGraphics" ++ _ -> ok;
_ ->
- io:format("~s::~s Building return value of temp ~s~n",
+ io:format("~s::~s Building return value of temp ~s~n",
[get(current_class),get(current_func),Type])
end,
%% #class{id=Id} = get({class,Type}),
- {Type ++ " * Result = new " ++ Type ++ "(", "); newPtr((void *) Result,"
+ {Type ++ " * Result = new " ++ Type ++ "(", "); newPtr((void *) Result,"
++ "3, memenv);"};
return_res1(#type{base={enum,_Type},single=true,by_val=true}) ->
{"int Result = " , ""};
@@ -730,7 +752,7 @@ return_res1(#type{name=Type,single=true,by_val=true}) ->
filter(Ps) ->
lists:filter(fun filter_arg/1, Ps).
-filter_arg(#param{where=erl}) -> false;
+filter_arg(#param{where=erl}) -> false;
filter_arg(#param{where=this}) -> false;
filter_arg(#param{}) -> true.
%%filter_arg(#param{def=Def, in=In}) -> Def =:= none orelse In =:= false.
@@ -739,20 +761,20 @@ filter_arg(#param{}) -> true.
call_arg(#param{where=c, alt={length,Alt}}) when is_list(Alt) ->
"*" ++ Alt ++ "Len";
call_arg(#param{where=c, alt={size,Id}}) when is_integer(Id) ->
- %% It's a binary
+ %% It's a binary
"Ecmd.bin["++ integer_to_list(Id) ++ "]->size";
-call_arg(#param{name=N,def=Def,type=#type{name=Type,by_val=true,single=true,base=Base}})
- when Base =:= int; Base =:= long; Base =:= float; Base =:= double; Base =:= bool ->
+call_arg(#param{name=N,def=Def,type=#type{name=Type,by_val=true,single=true,base=Base}})
+ when Base =:= int; Base =:= long; Base =:= float; Base =:= double; Base =:= bool ->
case Def of
none -> "(" ++ to_string(Type) ++ ") *" ++ N;
_ -> N
end;
-call_arg(#param{name=N,type=#type{base={enum,Type}, by_val=true,single=true}}) ->
+call_arg(#param{name=N,type=#type{base={enum,Type}, by_val=true,single=true}}) ->
"(" ++ enum_type(Type) ++") " ++ N;
call_arg(#param{name=N,type=#type{base={class,_},by_val=true,single=true}}) -> "*" ++ N;
call_arg(#param{name=N,type=#type{base={class,_},ref=reference,single=true}}) -> "*" ++ N;
-call_arg(#param{name=N,type=#type{base=eventType}}) ->
+call_arg(#param{name=N,type=#type{base=eventType}}) ->
N ++ ", (wxObjectEventFunction)(wxEventFunction) &WxeApp::handle_evt, Evt_cb, this";
call_arg(#param{name=N,type=#type{by_val=true, single=_False}}) -> N;
call_arg(#param{name=N,def=Def,type=#type{by_val=false, ref={pointer,2}}})
@@ -760,20 +782,20 @@ call_arg(#param{name=N,def=Def,type=#type{by_val=false, ref={pointer,2}}})
call_arg(#param{name=N,type=#type{by_val=false, ref={pointer,2}}}) -> "&" ++ N;
call_arg(#param{name=N,in=false,type=#type{ref=reference, single=true}}) -> N;
call_arg(#param{name=N,in=false,type=#type{by_val=false, single=true}}) -> "&" ++ N;
-call_arg(#param{name=N,def=Def,type=#type{base={comp,_,_},ref={pointer,1},single=true}})
+call_arg(#param{name=N,def=Def,type=#type{base={comp,_,_},ref={pointer,1},single=true}})
when Def =:= none ->
"&" ++N;
call_arg(#param{name=N,type=#type{by_val=false}}) -> N;
call_arg(#param{name=N,type={merged,_,#type{base={class,_},single=true,
by_val=ByVal,
- ref=Ref},_,_,_,_}})
- when ByVal =:= true; Ref =:= reference ->
+ ref=Ref},_,_,_,_}})
+ when ByVal =:= true; Ref =:= reference ->
"*" ++ N;
-call_arg(#param{def=Def, type=void}) when Def =/= none -> Def;
+call_arg(#param{def=Def, type=void}) when Def =/= none -> Def;
call_arg(#param{name=N,type=#type{base={ref,_},by_val=true,single=true}}) -> N;
call_arg(#param{name=N,type={merged,_,_,_,_,_,_}}) -> N.
-%% call_arg(#param{name=N,type=#type{base=Tuple,ref=reference}})
+%% call_arg(#param{name=N,type=#type{base=Tuple,ref=reference}})
%% when is_tuple(Tuple) -> "&" ++ N;
to_string(Type) when is_atom(Type) -> atom_to_list(Type);
@@ -781,19 +803,19 @@ to_string(Type) when is_list(Type) -> Type.
virtual_dest(#class{abstract=true, parent="root"}) -> false;
virtual_dest(#class{abstract=true, parent="object"}) -> true;
-virtual_dest(#class{abstract=true, parent=Parent}) ->
+virtual_dest(#class{abstract=true, parent=Parent}) ->
virtual_dest(get({class,Parent}));
virtual_dest(#class{methods=Ms, parent=Parent}) ->
case lists:keysearch(destructor,#method.method_type, lists:append(Ms)) of
{value, #method{method_type=destructor, virtual=Virtual}} ->
case Virtual of
- undefined ->
+ undefined ->
case get({class,Parent}) of
- undefined ->
+ undefined ->
case Parent of
- "object" ->
+ "object" ->
true;
- "root" ->
+ "root" ->
false;
_ ->
io:format("Error: ~p~n",[Parent]),
@@ -802,10 +824,10 @@ virtual_dest(#class{methods=Ms, parent=Parent}) ->
PClass ->
virtual_dest(PClass)
end;
- _ ->
+ _ ->
Virtual
end;
- false ->
+ false ->
false
end.
@@ -819,24 +841,24 @@ is_derived(#class{abstract=true}) -> false;
is_derived(C = #class{}) -> virtual_dest(C).
is_window(Class) ->
- lists:member("wxWindow", wx_gen_erl:parents(Class)).
+ lists:member("wxWindow", wx_gen_erl:parents(Class)).
is_dialog(Class) ->
lists:member("wxDialog", wx_gen_erl:parents(Class)).
-
+
build_return_vals(Type,Ps) ->
HaveType = case Type of void -> 0; _ -> 1 end,
NoOut = lists:sum([1 || #param{in=In} <- Ps, In =/= true]) + HaveType,
OutTupSz = if NoOut > 1 -> NoOut; true -> 0 end,
-
+
build_ret_types(Type,Ps),
- if
+ if
OutTupSz > 1 -> w(" rt.addTupleCount(~p);~n",[OutTupSz]);
true -> ignore
- end,
+ end,
Ps.
-build_ret_types(void,Ps) ->
+build_ret_types(void,Ps) ->
Calc = fun(#param{name=N,in=False,type=T}, Free) when False =/= true ->
case build_ret(N, False, T) of
ok -> Free;
@@ -845,7 +867,7 @@ build_ret_types(void,Ps) ->
(_, Free) -> Free
end,
lists:foldl(Calc, [], Ps);
-build_ret_types(Type,Ps) ->
+build_ret_types(Type,Ps) ->
Free = case build_ret("Result", out, Type) of
ok -> [];
FreeStr -> [FreeStr]
@@ -854,8 +876,8 @@ build_ret_types(Type,Ps) ->
case build_ret(N, False, T) of
ok -> FreeAcc;
FreeMe -> [FreeMe|FreeAcc]
- end;
- (_, FreeAcc) -> FreeAcc
+ end;
+ (_, FreeAcc) -> FreeAcc
end,
lists:foldl(Calc, Free, Ps).
@@ -898,17 +920,17 @@ build_ret(Name,_,#type{name="wxArrayInt"}) ->
build_ret(Name,_,#type{base={comp,_,_},single=array}) ->
w(" for(unsigned int i=0; i < ~s.GetCount(); i++) {~n", [Name]),
w(" rt.add(~s[i]);~n }~n",[Name]),
- w(" rt.endList(~s.GetCount());~n",[Name]);
+ w(" rt.endList(~s.GetCount());~n",[Name]);
build_ret(Name,_,#type{name=List,single=list,base={class,Class}}) ->
w(" int i=0;~n"),
w(" for(~s::const_iterator it = ~s.begin(); it != ~s.end(); ++it) {~n",
[List, Name, Name]),
w(" ~s * ~sTmp = *it;~n", [Class,Name]),
w(" rt.addRef(getRef((void *)~sTmp,memenv), \"~s\"); i++;}~n",[Name,Class]),
- w(" rt.endList(~s.GetCount());~n",[Name]);
-
+ w(" rt.endList(~s.GetCount());~n",[Name]);
+
build_ret(Name,_,#type{name="wxArrayTreeItemIds"}) ->
- w(" for(unsigned int i=0; i < ~s.GetCount(); i++) {~n", [Name]),
+ w(" for(unsigned int i=0; i < ~s.GetCount(); i++) {~n", [Name]),
w(" rt.add((wxUIntPtr *)~s[i].m_pItem);}~n",[Name]),
w(" rt.endList(~s.GetCount());~n",[Name]);
@@ -923,10 +945,10 @@ build_ret(Name,_,#type{name="wxArrayString", single=array}) ->
w(" rt.add(~s);~n", [Name]);
build_ret(Name,In,T) ->
?error({nyi, Name,In, T}).
-
+
mods([const|R]) -> "const " ++ mods(R);
mods([unsigned|R]) -> "unsigned " ++ mods(R);
-mods([]) -> "".
+mods([]) -> "".
build_enums() ->
Tree = get(consts),
@@ -935,13 +957,13 @@ build_enums() ->
w("#include \"../wxe_impl.h\"~n"),
w("#include \"wxe_macros.h\"~n"),
w("#include \"../wxe_return.h\"~n"),
- w("void WxeApp::init_nonconsts(wxeMemEnv *memenv, ErlDrvTermData caller) {~n"),
+ w("void WxeApp::init_nonconsts(wxeMemEnv *memenv, ErlDrvTermData caller) {~n"),
NotConsts = [NC || NC = #const{is_const=false} <- gb_trees:values(Tree)],
Size = length(NotConsts),
GVars = get(gvars),
GSize = length(GVars),
w(" wxeReturn rt = wxeReturn(WXE_DRV_PORT, caller);~n"),
- w(" rt.addAtom((char*)\"wx_consts\");~n"),
+ w(" rt.addAtom((char*)\"wx_consts\");~n"),
[build_enum(NConst) || NConst <- lists:keysort(#const.val, NotConsts)],
_Cnt = foldl(fun(Gvar, I) -> build_gvar(Gvar,I) end, 0, lists:sort(GVars)),
w(" rt.endList(~p);~n", [Size+GSize]),
@@ -968,9 +990,9 @@ build_gvar({Name, Class, _Id}, Cnt) ->
Cnt+1.
gen_macros() ->
- w("#include <wx/caret.h>~n"), %% Arrg wxw forgot?? some files
- w("#include <wx/tooltip.h>~n"),
- w("#include <wx/gbsizer.h>~n"),
+ w("#include <wx/caret.h>~n"), %% Arrg wxw forgot?? some files
+ w("#include <wx/tooltip.h>~n"),
+ w("#include <wx/gbsizer.h>~n"),
w("#include <wx/splash.h>~n"),
w("#include <wx/grid.h>~n"),
w("#include <wx/image.h>~n"),
@@ -995,15 +1017,15 @@ gen_macros() ->
w("#include <wx/stc/stc.h>~n"),
w("#include <wx/minifram.h>~n"),
w("#include <wx/sashwin.h>~n"),
- w("#include <wx/laywin.h>~n"),
- w("#include <wx/graphics.h>~n"),
- w("#include <wx/aui/aui.h>~n"),
- w("#include <wx/datectrl.h>~n"),
- w("#include <wx/filepicker.h>~n"),
- w("#include <wx/fontpicker.h>~n"),
- w("#include <wx/clrpicker.h>~n"),
- w("#include <wx/statline.h>~n"),
- w("#include <wx/clipbrd.h>~n"),
+ w("#include <wx/laywin.h>~n"),
+ w("#include <wx/graphics.h>~n"),
+ w("#include <wx/aui/aui.h>~n"),
+ w("#include <wx/datectrl.h>~n"),
+ w("#include <wx/filepicker.h>~n"),
+ w("#include <wx/fontpicker.h>~n"),
+ w("#include <wx/clrpicker.h>~n"),
+ w("#include <wx/statline.h>~n"),
+ w("#include <wx/clipbrd.h>~n"),
w("#include <wx/splitter.h>~n"),
w("#include <wx/choicebk.h>~n"),
w("#include <wx/toolbook.h>~n"),
@@ -1012,14 +1034,14 @@ gen_macros() ->
w("#include <wx/html/htmlwin.h>~n"),
w("#include <wx/html/htmlcell.h>~n"),
w("#include <wx/filename.h>~n"),
-
+
w("~n~n", []),
w("#ifndef wxICON_DEFAULT_BITMAP_TYPE~n",[]),
w(" #define wxICON_DEFAULT_BITMAP_TYPE wxBITMAP_TYPE_ICO_RESOURCE~n",[]),
w("#endif~n", []),
w("~n~n", []),
- [w("#define ~s_~s ~p~n", [Class,Name,Id]) ||
+ [w("#define ~s_~s ~p~n", [Class,Name,Id]) ||
{Class,Name,_,Id} <- wx_gen_erl:get_unique_names()],
w("~n~n").
@@ -1032,29 +1054,29 @@ build_events() ->
w("#include \"wxe_macros.h\"~n"),
w("#include \"../wxe_events.h\"~n~n"),
w("#include \"../wxe_return.h\"~n~n"),
-
+
w("wxeEtype::wxeEtype(const char *name, int Id) {eName = name;cID = Id;}~n~n"),
w("WX_DECLARE_HASH_MAP(int, wxeEtype*, wxIntegerHash, wxIntegerEqual, wxeETmap );~n~n"),
-
+
w("wxeETmap etmap;~n~n"),
-
+
w(
"int wxeEventTypeFromAtom(char *etype_atom) {
wxeETmap::iterator it;
for(it = etmap.begin(); it != etmap.end(); ++it) {
wxeEtype * value = it->second;
- if(strcmp(value->eName, etype_atom) == 0) {
- if(it->first > wxEVT_USER_FIRST) {
+ if(strcmp(value->eName, etype_atom) == 0) {
+ if(it->first > wxEVT_USER_FIRST) {
return it->first - wxEVT_USER_FIRST;
} else {
return it->first;
}
}
- }
- return -1;
+ }
+ return -1;
}
-"),
+"),
Evs0 = [C || {_,C=#class{event=Evs}} <- get(), Evs =/= false],
Evs = lists:keysort(#class.id, Evs0),
@@ -1067,7 +1089,7 @@ initEventTable(Evs) ->
w(" struct { ",[]),
w("int ev_type; int class_id; const char * ev_name;} event_types[] =~n {~n",[]),
- lists:foreach(fun(Ev) -> init_event_classes(Ev) end,
+ lists:foreach(fun(Ev) -> init_event_classes(Ev) end,
[#class{id=0,event=[wxEVT_NULL]}|Evs]),
w(" {-1, 0, ""}~n };~n",[]),
w(" for(int i=0; event_types[i].ev_type != -1; i++) {~n",[]),
@@ -1085,7 +1107,7 @@ initEventTable(Evs) ->
" }~n"
" }~n", []),
w("}~n~n").
-
+
init_event_classes(#class{event=ETs, id=Id}) ->
F = fun({Eev, Cev, OtherClass}) ->
w(" {~w + wxEVT_USER_FIRST, ~w, ~p},~n",
@@ -1105,7 +1127,7 @@ find_id(OtherClass) ->
Class = get({class,atom_to_list(OtherClass)}),
%%{value, Class} = lists:keysearch(atom_to_list(OtherClass), #class.name, All),
Class#class.id.
-
+
encode_events(Evs) ->
?WTC("encode_events"),
w("void wxeEvtListener::forward(wxEvent& event)~n"
@@ -1132,7 +1154,7 @@ encode_events(Evs) ->
" wxeMemEnv *memenv = app->getMemEnv(port);~n"
" if(!memenv) return 0;~n~n"
" wxeReturn rt = wxeReturn(port, cb->listener);~n"),
-
+
w("~n rt.addAtom((char*)\"wx\");~n"
" rt.addInt((int) event->GetId());~n"
" rt.addRef(getRef((void *)(cb->obj), memenv), cb->class_name);~n"
@@ -1155,15 +1177,15 @@ encode_events(Evs) ->
w(" app->clearPtr((void *) event);~n"),
w(" } else {~n"),
w(" send_res = rt.send();~n"),
- w(" if(cb->skip) event->Skip();~n"),
+ w(" if(cb->skip) event->Skip();~n"),
w(" };~n"),
w(" return send_res;~n"),
w(" }~n").
encode_event(C = #class{name=Class, id=Id, options=Opts}) ->
?WTC("encode_event"),
- case proplists:get_value("mixed_event", Opts) of
- undefined ->
+ case proplists:get_value("mixed_event", Opts) of
+ undefined ->
w("case ~p: {// ~s~n", [Id,Class]),
encode_event2(C),
ok;
@@ -1189,10 +1211,10 @@ encode_event2(Class = #class{name=Name}) ->
build_event_attrs(ClassRec = #class{name=Class}) ->
Attrs0 = wx_gen_erl:filter_attrs(ClassRec),
- Rename =
- fun(Att = #param{name=Name,prot=public,acc=undefined}, {All,Use}) ->
+ Rename =
+ fun(Att = #param{name=Name,prot=public,acc=undefined}, {All,Use}) ->
{[Att#param{name= "ev->" ++ Name}|All],Use};
- (Att = #param{acc=Acc}, {All,_}) ->
+ (Att = #param{acc=Acc}, {All,_}) ->
{[Att#param{name= "ev->" ++ Acc}|All], true}
end,
case foldr(Rename,{[],false},Attrs0) of
@@ -1202,9 +1224,9 @@ build_event_attrs(ClassRec = #class{name=Class}) ->
%% Attrs;
{Attrs,_} ->
w(" ~s * ev = (~s *) event;~n",[Class,Class]),
- FixClass =
+ FixClass =
fun(P=#param{name=N,acc=Acc,type=#type{single=Single,by_val=ByVal,
- base={class,C}}})
+ base={class,C}}})
when Acc =/= undefined ->
Var = var_name(N),
if Single, ByVal ->
@@ -1215,17 +1237,17 @@ build_event_attrs(ClassRec = #class{name=Class}) ->
end,
P#param{name=Var};
(P) -> P
- end,
+ end,
lists:map(FixClass, Attrs)
end.
-var_name("ev->" ++ Name0) ->
+var_name("ev->" ++ Name0) ->
case reverse(Name0) of
")(" ++ Name -> reverse(Name);
_ -> Name0
end;
var_name(Name) -> Name.
-
+
enum_name({Class,Type}) ->
uppercase_all(Class ++ "_" ++ Type);
enum_name(Type) ->
diff --git a/lib/wx/api_gen/wx_gen_erl.erl b/lib/wx/api_gen/wx_gen_erl.erl
index e1201ab0d4..e882ae87ca 100644
--- a/lib/wx/api_gen/wx_gen_erl.erl
+++ b/lib/wx/api_gen/wx_gen_erl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The 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,7 +19,7 @@
%%%-------------------------------------------------------------------
%%% File : wx_gen_erl.erl
%%% Author : Dan Gudmundsson <[email protected]>
-%%% Description :
+%%% Description :
%%%
%%% Created : 25 Jan 2007 by Dan Gudmundsson <[email protected]>
%%%-------------------------------------------------------------------
@@ -32,7 +32,7 @@
-import(lists, [foldl/3,foldr/3,reverse/1, keysearch/3, map/2, filter/2]).
-import(gen_util, [lowercase/1, lowercase_all/1, uppercase/1, uppercase_all/1,
- open_write/1, close/0, erl_copyright/0, w/2,
+ open_write/1, close/0, erl_copyright/0, w/2,
args/3, args/4, strip_name/2]).
gen(Defs) ->
@@ -42,9 +42,9 @@ gen(Defs) ->
gen_enums_ints(),
[gen_class(Class) || Class <- Defs],
gen_funcnames().
-
+
gen_class(Class) ->
- try
+ try
gen_class1(Class)
catch throw:skipped ->
Class
@@ -52,10 +52,10 @@ gen_class(Class) ->
gen_class1(C=#class{name=Name,parent="static",methods=Ms,options=_Opts}) ->
open_write("../src/gen/wx_misc.erl"),
- put(current_class, Name),
+ put(current_class, Name),
erl_copyright(),
w("", []),
- w("%% This file is generated DO NOT EDIT~n~n", []),
+ w("%% This file is generated DO NOT EDIT~n~n", []),
w("%% @doc See external documentation: "
"<a href=\"http://www.wxwidgets.org/manuals/stable/wx_miscellany.html\">Misc</a>.\n\n",[]),
@@ -67,8 +67,8 @@ gen_class1(C=#class{name=Name,parent="static",methods=Ms,options=_Opts}) ->
Exp = fun(M) -> gen_export(C,M) end,
ExportList = lists:usort(lists:append(lists:map(Exp,reverse(Ms)))),
w("-export([~s]).~n~n", [args(fun(EF) -> EF end, ",", ExportList, 60)]),
-
-
+
+
Gen = fun(M) -> gen_method(Name,M) end,
NewMs = lists:map(Gen,reverse(Ms)),
close(),
@@ -79,13 +79,13 @@ gen_class1(C=#class{name=Name,parent=Parent,methods=Ms,options=Opts}) ->
case Opts of
["ignore"] -> throw(skipped);
_ -> ok
- end,
+ end,
open_write("../src/gen/"++Name++".erl"),
- put(current_class, Name),
+ put(current_class, Name),
erl_copyright(),
w("", []),
- w("%% This file is generated DO NOT EDIT~n~n", []),
-
+ w("%% This file is generated DO NOT EDIT~n~n", []),
+
case lists:member(taylormade, Opts) of
true ->
{ok, Bin} = file:read_file(filename:join([wx_extra, Name++".erl"])),
@@ -95,33 +95,33 @@ gen_class1(C=#class{name=Name,parent=Parent,methods=Ms,options=Opts}) ->
w("%% @doc See external documentation: "
"<a href=\"http://www.wxwidgets.org/manuals/stable/wx_~s.html\">~s</a>.\n",
[lowercase_all(Name), Name]),
-
+
case C#class.doc of
undefined -> ignore;
Str -> w("%%~n%% ~s~n~n%%~n", [Str])
end,
-
+
case C#class.event of
false -> ignore;
Evs ->
EvTypes = [event_type_name(Ev) || Ev <- Evs],
EvStr = args(fun(Ev) -> "<em>"++Ev++"</em>" end, ", ", EvTypes),
-
+
w("%% <dl><dt>Use {@link wxEvtHandler:connect/3.} with EventType:</dt>~n",[]),
w("%% <dd>~s</dd></dl>~n", [EvStr]),
- w("%% See also the message variant {@link wxEvtHandler:~s(). #~s{}} event record type.~n",
+ w("%% See also the message variant {@link wxEvtHandler:~s(). #~s{}} event record type.~n",
[event_rec_name(Name),event_rec_name(Name)]),
w("%%~n",[]),
ok
end,
-
+
Parents = parents(Parent),
case [P || P <- Parents, P =/= root, P =/= object] of
[] -> ignore;
- Ps ->
+ Ps ->
w("%% <p>This class is derived (and can use functions) from:~n", []),
[w("%% <br />{@link ~s}~n", [P]) || P <- Ps],
- w("%% </p>~n",[])
+ w("%% </p>~n",[])
end,
w("%% @type ~s(). An object reference, The representation is internal~n",[Name]),
w("%% and can be changed without notice. It can't be used for comparsion~n", []),
@@ -137,17 +137,17 @@ gen_class1(C=#class{name=Name,parent=Parent,methods=Ms,options=Opts}) ->
Done0 = ["Destroy", "New", "Create", "destroy", "new", "create"],
Done = gb_sets:from_list(Done0 ++ [M|| #method{name=M} <- lists:append(Ms)]),
{_, InExported} = gen_inherited(Parents, Done, []),
- w("-export([~s]).~n~n", [args(fun(EF) -> EF end, ",",
- lists:usort(["parent_class/1"|InExported]),
+ w("-export([~s]).~n~n", [args(fun(EF) -> EF end, ",",
+ lists:usort(["parent_class/1"|InExported]),
60)]),
-
+
w("%% @hidden~n", []),
parents_check(Parents),
-
+
Gen = fun(M) -> gen_method(Name,M) end,
NewMs = lists:map(Gen,reverse(Ms)),
- gen_dest(C, Ms),
-
+ gen_dest(C, Ms),
+
gen_inherited(Parents, Done, true)
end,
@@ -203,26 +203,26 @@ gen_export(#class{name=Class,abstract=Abs},Ms0) ->
[] -> [];
[M=#method{where=taylormade}|_] ->
[taylormade_export(Class, M)];
- Ms ->
+ Ms ->
GetF = fun(#method{method_type=constructor,where=W,params=Ps}) ->
{Args,Opts} = split_optional(Ps),
- OptLen = case Opts of
- [] -> 0;
+ OptLen = case Opts of
+ [] -> 0;
_ when W =:= erl_no_opt -> 0;
- _ -> 1
+ _ -> 1
end,
"new/" ++ integer_to_list(length(Args)+OptLen);
(#method{method_type=destructor}) ->
- case Abs of
- true -> [];
+ case Abs of
+ true -> [];
_ -> "destroy/1"
end;
(#method{name=N,alias=A,where=W, params=Ps}) ->
{Args,Opts} = split_optional(Ps),
- OptLen = case Opts of
- [] -> 0;
+ OptLen = case Opts of
+ [] -> 0;
_ when W =:= erl_no_opt -> 0;
- _ -> 1
+ _ -> 1
end,
erl_func_name(N,A) ++ "/" ++ integer_to_list(length(Args) + OptLen)
end,
@@ -235,10 +235,10 @@ gen_method(Class,Ms0) ->
Res = filter(RemoveC, Ms0),
case Res of
[] -> Ms0;
- [M=#method{where=taylormade}|_] ->
- taylormade_func(Class, M),
+ [#method{where=taylormade}|_] ->
+ taylormade_func(Class, Res),
Ms0;
- Ms ->
+ Ms ->
gen_doc(Class,Ms),
gen_method1(Ms),
Ms0
@@ -279,22 +279,22 @@ gen_method2(M=#method{name=N,alias=A,params=Ps,type=T,method_type=MT,id=MethodId
ignore -> skip;
_ -> w(" _Result =", [])
end,
-
+
case have_return_vals(T, Ps) of
_ when MT =:= constructor ->
w(" wxe_util:construct(~s,~n <<~s~s>>)", [MId, MArgs,MOpts]);
true ->
w(" wxe_util:call(~s,~n <<~s~s>>)", [MId, MArgs,MOpts]);
- false ->
+ false ->
w(" wxe_util:cast(~s,~n <<~s~s>>)", [MId, MArgs,MOpts])
end,
case gen_util:get_hook(erl, M#method.post_hook) of
ignore -> skip;
- Post ->
+ Post ->
w(",~n ~s~n", [Post]),
w(" _Result", [])
end,
-
+
erase(current_func),
M.
@@ -306,9 +306,9 @@ gen_dest(#class{name=CName,abstract=Abs}, Ms) ->
case lists:keysearch(destructor,#method.method_type, lists:append(Ms)) of
{value, #method{method_type=destructor, id=Id}} ->
case hd(reverse(parents(CName))) of
- object ->
+ object ->
gen_dest2(CName, object);
- root ->
+ root ->
gen_dest2(CName, Id)
end;
false ->
@@ -320,7 +320,7 @@ gen_dest2(Class, Id) ->
w("%% @spec (This::~s()) -> ok~n", [Class]),
w("%% @doc Destroys this object, do not use object again~n", []),
w("destroy(Obj=#wx_ref{type=Type}) ->~n", []),
- w(" ?CLASS(Type,~s),~n",[Class]),
+ w(" ?CLASS(Type,~s),~n",[Class]),
case Id of
object ->
w(" wxe_util:destroy(?DESTROY_OBJECT,Obj),~n ok.~n", []);
@@ -341,14 +341,14 @@ gen_inherited([Parent|Ps], Done0, Exported0) ->
gen_inherited(Ps, gb_sets:union(Done,Done0), Exported).
gen_inherited_ms([[#method{name=Name,alias=A,params=Ps0,where=W,method_type=MT}|_]|R],
- Class,Skip,Done, Exported)
- when W =/= merged_c ->
+ Class,Skip,Done, Exported)
+ when W =/= merged_c ->
case gb_sets:is_member(Name,Skip) of
false when MT =:= member, Exported =:= true ->
Ps = [patch_param(P,all) || P <- Ps0],
Opts = if W =:= erl_no_opt -> [];
- true ->
- [Opt || Opt = #param{def=Def,in=In, where=Where} <- Ps,
+ true ->
+ [Opt || Opt = #param{def=Def,in=In, where=Where} <- Ps,
Def =/= none, In =/= false, Where =/= c]
end,
w("%% @hidden~n", []),
@@ -359,10 +359,10 @@ gen_inherited_ms([[#method{name=Name,alias=A,params=Ps0,where=W,method_type=MT}|
gen_inherited_ms(R,Class, Skip, gb_sets:add(Name,Done), Exported);
false when MT =:= member, is_list(Exported) ->
{Args,Opts} = split_optional(Ps0),
- OptLen = case Opts of
- [] -> 0;
+ OptLen = case Opts of
+ [] -> 0;
_ when W =:= erl_no_opt -> 0;
- _ -> 1
+ _ -> 1
end,
Export = erl_func_name(Name,A) ++ "/" ++ integer_to_list(length(Args) + OptLen),
gen_inherited_ms(R,Class,Skip, gb_sets:add(Name,Done), [Export|Exported]);
@@ -374,17 +374,21 @@ gen_inherited_ms([[_|Check]|R],Class,Skip, Done0,Exp) ->
gen_inherited_ms([[]|R],Class,Skip,Done0,Exp) ->
gen_inherited_ms(R,Class,Skip,Done0,Exp);
gen_inherited_ms([], _, _Skip, Done,Exp) -> {Done,Exp}.
-
+
%%%%%%%%%%%%%%%
-taylormade_func(Class, #method{name=Name, id=Id}) ->
+taylormade_func(Class, [#method{name=Name, id=Id}|_]) ->
{ok, Bin} = file:read_file(filename:join([wx_extra, Class ++".erl"])),
- Str0 = binary_to_list(Bin),
- {match, [Str1]} = re:run(Str0, "<<"++Name++"(.*)"++Name++">>",
- [dotall, {capture, all_but_first, list}]),
-
- w(Str1, ["?" ++ get_unique_name(Id)]),
+ Src = binary_to_list(Bin),
+ Str = case gen_util:get_taylor_made(Src, Name) of
+ nomatch ->
+ {match, [Str0]} = gen_util:get_taylor_made(Src, get_unique_name(Id)),
+ Str0;
+ {match, [Str0]} ->
+ Str0
+ end,
+ w(Str, ["?" ++ get_unique_name(Id)]),
ok.
taylormade_export(Class, #method{name=Name}) ->
@@ -398,12 +402,12 @@ taylormade_export(Class, #method{name=Name}) ->
arg_type_tests([P|Ps], Mid0) ->
case arg_type_test(P,"\n",Mid0) of
- Mid0 ->
+ Mid0 ->
arg_type_tests(Ps, Mid0);
Mid -> %% Already checked the other args
Mid
end;
-arg_type_tests([],Mid) -> Mid.
+arg_type_tests([],Mid) -> Mid.
arg_type_test(#param{where=c}, _, Acc) ->
Acc;
@@ -412,7 +416,7 @@ arg_type_test(#param{name=Name0,in=In,type=#type{base={class,T},single=true},def
Name = erl_arg_name(Name0),
w(" ?CLASS(~sT,~s),~s", [Name,T,EOS]),
Acc;
-arg_type_test(#param{name=Name0,in=In,type=#type{base={class,T}}, def=none},EOS,Acc)
+arg_type_test(#param{name=Name0,in=In,type=#type{base={class,T}}, def=none},EOS,Acc)
when In =/= false ->
Name = erl_arg_name(Name0),
w(" [?CLASS(~sT,~s) || #wx_ref{type=~sT} <- ~s],~s", [Name,T,Name,Name,EOS]),
@@ -420,35 +424,35 @@ arg_type_test(#param{name=Name0,in=In,type=#type{base={class,T}}, def=none},EOS,
arg_type_test(#param{name=Name0,def=none,in=In,
type={merged,
M1, #type{base={class,T1},single=true},Ps1,
- M2, #type{base={class,T2},single=true},Ps2}}, EOS, _Acc)
+ M2, #type{base={class,T2},single=true},Ps2}}, EOS, _Acc)
when In =/= false ->
Name = erl_arg_name(Name0),
Opname = Name++"OP",
w(" ~s = case ?CLASS_T(~sT,~s) of~n true ->\n ", [Opname,Name,T1]),
- lists:foreach(fun(Param) -> arg_type_test(Param,"\n ", ignore) end,
+ lists:foreach(fun(Param) -> arg_type_test(Param,"\n ", ignore) end,
element(1,split_optional(Ps1))),
w("?~s;~n",[get_unique_name(M1)]),
w(" _ -> ?CLASS(~sT,~s),\n ",[Name,T2]),
{Ps21,_} = split_optional(patchArgName(Ps2,Ps1)),
- lists:foreach(fun(Param) -> arg_type_test(Param,"\n ", ignore) end,
+ lists:foreach(fun(Param) -> arg_type_test(Param,"\n ", ignore) end,
Ps21),
w("?~s\n end,~s",[get_unique_name(M2),EOS]),
Opname;
-arg_type_test(#param{name=Name0, type=#type{base=eventType}}, EOS, Acc) ->
+arg_type_test(#param{name=Name0, type=#type{base=eventType}}, EOS, Acc) ->
Name = erl_arg_name(Name0),
w(" ~sBin = list_to_binary([atom_to_list(~s)|[0]]),~s", [Name,Name,EOS]),
w(" ThisTypeBin = list_to_binary([atom_to_list(ThisT)|[0]]),~s", [EOS]),
Acc;
-arg_type_test(#param{name=Name0,def=none,type=#type{base={term,_}}}, EOS, Acc) ->
+arg_type_test(#param{name=Name0,def=none,type=#type{base={term,_}}}, EOS, Acc) ->
Name = erl_arg_name(Name0),
w(" wxe_util:send_bin(term_to_binary(~s)),~s", [Name,EOS]),
Acc;
-arg_type_test(#param{name=Name0,type=#type{base=binary}},EOS,Acc) ->
+arg_type_test(#param{name=Name0,type=#type{base=binary}},EOS,Acc) ->
Name = erl_arg_name(Name0),
w(" wxe_util:send_bin(~s),~s", [Name,EOS]),
Acc;
-arg_type_test(#param{name=Name0,type=#type{name=Type,base=Base,single=Single}},EOS,Acc) ->
- if
+arg_type_test(#param{name=Name0,type=#type{name=Type,base=Base,single=Single}},EOS,Acc) ->
+ if
Type =:= "wxArtClient", Single =:= true ->
Name = erl_arg_name(Name0),
w(" ~s_UC = unicode:characters_to_binary([~s, $_, $C,0]),~s",
@@ -458,11 +462,11 @@ arg_type_test(#param{name=Name0,type=#type{name=Type,base=Base,single=Single}},E
w(" ~s_UC = unicode:characters_to_binary([~s,0]),~s", [Name,Name,EOS]);
Type =:= "wxArrayString" ->
Name = erl_arg_name(Name0),
- w(" ~s_UCA = [unicode:characters_to_binary([~sTemp,0]) || ~s",
+ w(" ~s_UCA = [unicode:characters_to_binary([~sTemp,0]) || ~s",
[Name,Name, EOS]),
w(" ~sTemp <- ~s],~s", [Name,Name,EOS]);
true -> %% Not a string
- ignore
+ ignore
end,
Acc;
arg_type_test(_,_,Acc) -> Acc.
@@ -476,10 +480,10 @@ have_return_vals(void, Ps) ->
have_return_vals(#type{}, _) -> true.
gen_function_clause(Name0,MT,Ps,Optional,Variant) ->
- PArg = fun(Arg) ->
+ PArg = fun(Arg) ->
case lists:member(name_only, Variant) of
true -> func_arg_name(Arg);
- false ->
+ false ->
case lists:member(name_type, Variant) of
true ->
Name = func_arg_name(Arg),
@@ -495,17 +499,17 @@ gen_function_clause(Name0,MT,Ps,Optional,Variant) ->
Args = args(PArg, ",", Ps),
Name = case MT of constructor -> "new"; _ -> Name0 end,
w("~s(~s",[Name,Args]),
- Opts = case Optional of
+ Opts = case Optional of
[] -> "";
empty_list when Args =:= [] -> "[]";
empty_list -> ", []";
_ when Args =:= [] -> "Options";
- _ -> ", Options"
+ _ -> ", Options"
end,
w("~s)", [Opts]),
case lists:member(no_guards, Variant) of
true -> ok;
- false ->
+ false ->
Guards = args(fun guard_test/1, ",", Ps),
if
Guards =:= [], Opts =:= "" -> w(" ->~n", []);
@@ -517,10 +521,10 @@ gen_function_clause(Name0,MT,Ps,Optional,Variant) ->
split_optional(Ps) ->
split_optional(Ps, [], []).
-split_optional([P=#param{def=Def,in=In, where=Where}|Ps], Standard, Opts)
+split_optional([P=#param{def=Def,in=In, where=Where}|Ps], Standard, Opts)
when Def =/= none, In =/= false, Where =/= c ->
split_optional(Ps, Standard, [P|Opts]);
-split_optional([P=#param{def=Def,in=In, where=Where}|Ps], Standard, Opts)
+split_optional([P=#param{def=Def,in=In, where=Where}|Ps], Standard, Opts)
when Def =:= none, In =/= false, Where =/= c ->
split_optional(Ps, [P|Standard], Opts);
split_optional([_|Ps], Standard, Opts) ->
@@ -532,24 +536,24 @@ patch_param(P=#param{type=#type{base=Tuple}}, all) when is_tuple(Tuple) ->
P#param{type={class,ignore}};
patch_param(P=#param{type={merged,_,_,_,_,_,_}}, _) ->
P#param{type={class,ignore}};
-patch_param(P=#param{type=#type{base={class,_}}},_) ->
+patch_param(P=#param{type=#type{base={class,_}}},_) ->
P#param{type={class,ignore}};
-patch_param(P=#param{type=#type{base={ref,_}}},_) ->
+patch_param(P=#param{type=#type{base={ref,_}}},_) ->
P#param{type={class,ignore}};
patch_param(P,_) -> P.
func_arg_name(#param{def=Def}) when Def =/= none -> skip;
func_arg_name(#param{in=false}) -> skip;
func_arg_name(#param{where=c}) -> skip;
-func_arg_name(#param{name=Name}) ->
+func_arg_name(#param{name=Name}) ->
erl_arg_name(Name).
func_arg(#param{def=Def}) when Def =/= none -> skip;
func_arg(#param{in=false}) -> skip;
func_arg(#param{where=c}) -> skip;
-func_arg(#param{name=Name,type=#type{base=string}}) ->
+func_arg(#param{name=Name,type=#type{base=string}}) ->
erl_arg_name(Name);
-func_arg(#param{name=Name,type=#type{name="wxArrayString"}}) ->
+func_arg(#param{name=Name,type=#type{name="wxArrayString"}}) ->
erl_arg_name(Name);
func_arg(#param{name=Name0,type=#type{base={class,_CN}, single=true}}) ->
Name = erl_arg_name(Name0),
@@ -570,7 +574,7 @@ func_arg(#param{name=Name,type=#type{base={comp,"wxDateTime",_Tup}, single=true}
func_arg(#param{name=Name,type=#type{name="wxArtClient", single=true}}) ->
erl_arg_name(Name);
func_arg(#param{name=Name,type=#type{base={comp,_,Tup}, single=true}}) ->
- N = erl_arg_name(Name),
+ N = erl_arg_name(Name),
Doc = fun({_,V}) -> erl_arg_name(N)++V end,
"{" ++ args(Doc, ",", Tup) ++ "}";
func_arg(#param{name=Name}) ->
@@ -587,7 +591,7 @@ guard_test(#param{name=N, type=#type{name="wxArtClient"}}) ->
"is_list(" ++ erl_arg_name(N) ++")";
guard_test(#param{name=N, type=#type{name="wxArrayString"}}) ->
"is_list(" ++ erl_arg_name(N) ++")";
-guard_test(#param{name=Name,type=#type{single=Single}})
+guard_test(#param{name=Name,type=#type{single=Single}})
when Single =/= true->
"is_list(" ++ erl_arg_name(Name) ++ ")";
guard_test(#param{name=N,type=#type{base=int}}) ->
@@ -637,42 +641,42 @@ gen_doc(_Class,[#method{name=N,alias=A,params=Ps,type=T,where=erl_no_opt,method_
gen_function_clause(erl_func_name(N,A),MT,Ps,empty_list,[no_guards,name_only]);
gen_doc(Class,[#method{name=N,params=Ps,type=T}])->
{_, Optional} = split_optional(Ps),
- NonDef = [Arg || Arg = #param{def=Def,in=In, where=Where} <- Ps,
+ NonDef = [Arg || Arg = #param{def=Def,in=In, where=Where} <- Ps,
Def =:= none, In =/= false, Where =/= c],
OptsType = case Optional of
[] -> "";
_ when NonDef =:= [] -> "[Option]";
- _ -> ", [Option]"
+ _ -> ", [Option]"
end,
w("%% @spec (~s~s) -> ~s~n",
[doc_arg_types(Ps),OptsType,doc_return_types(T,Ps)]),
doc_optional(Optional, normal),
- DocEnum = doc_enum(T,Ps, normal),
+ DocEnum = doc_enum(T,Ps, normal),
case Class of
"utils" ->
w("%% @doc See <a href=\"http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#~s\">"
- "external documentation</a>.~n",
+ "external documentation</a>.~n",
[lowercase_all(N)]);
_ ->
w("%% @doc See <a href=\"http://www.wxwidgets.org/manuals/stable/wx_~s.html#~s~s\">"
- "external documentation</a>.~n",
+ "external documentation</a>.~n",
[lowercase_all(Class),lowercase_all(Class),lowercase_all(N)])
end,
doc_enum_desc(DocEnum);
gen_doc(Class, Cs = [#method{name=N, alias=A,method_type=MT}|_]) ->
- GetRet = fun(#method{params=Ps,type=T}) ->
+ GetRet = fun(#method{params=Ps,type=T}) ->
doc_return_types(T,Ps)
end,
- GetArgs = fun(#method{params=Ps, where=Where}) ->
+ GetArgs = fun(#method{params=Ps, where=Where}) ->
Opt = case Where of
erl_no_opt -> [];
- _ ->
+ _ ->
case split_optional(Ps) of
{_, []} -> [];
_ -> ["[Option]"]
end
end,
- [doc_arg_type(P) ||
+ [doc_arg_type(P) ||
P=#param{in=In,def=none,where=W} <- Ps,
In =/= false, W =/= c] ++ Opt
end,
@@ -682,16 +686,16 @@ gen_doc(Class, Cs = [#method{name=N, alias=A,method_type=MT}|_]) ->
case Class of
"utils" ->
w("%% @doc See <a href=\"http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#~s\">"
- "external documentation</a>.~n",
+ "external documentation</a>.~n",
[lowercase_all(N)]);
_ ->
w("%% @doc See <a href=\"http://www.wxwidgets.org/manuals/stable/wx_~s.html#~s~s\">"
- "external documentation</a>.~n",
+ "external documentation</a>.~n",
[lowercase_all(Class),lowercase_all(Class),lowercase_all(N)])
end,
Name = case MT of constructor -> "new"; _ -> erl_func_name(N,A) end,
w("%% <br /> Alternatives:~n",[]),
- [gen_doc2(Name, Clause) || Clause <- Cs],
+ [gen_doc2(Name, Clause) || Clause <- Cs],
ok.
gen_doc2(Name,#method{params=Ps,where=erl_no_opt,method_type=MT}) ->
@@ -704,11 +708,11 @@ gen_doc2(Name,#method{params=Ps,type=T}) ->
OptsType = case Optional of
[] -> "";
_ when NonDef =:= [] -> "[Option]";
- _ -> ", [Option]"
+ _ -> ", [Option]"
end,
w("%% <p><c>~n",[]),
w("%% ~s(~s~s) -> ~s </c>~n",
- [Name,doc_arg_types(Ps),OptsType,doc_return_types(T,Ps)]),
+ [Name,doc_arg_types(Ps),OptsType,doc_return_types(T,Ps)]),
doc_optional(Optional, xhtml),
DocEnum = doc_enum(T,Ps, xhtml),
doc_enum_desc(DocEnum),
@@ -717,7 +721,7 @@ gen_doc2(Name,#method{params=Ps,type=T}) ->
doc_arg(ArgList) ->
case all_eq(ArgList) of
true -> hd(ArgList);
- false ->
+ false ->
Get = fun(Str) ->
[_Name|Types] = string:tokens(Str, ":"),
case Types of
@@ -734,12 +738,12 @@ doc_arg(ArgList) ->
doc_ret(ArgList) ->
case all_eq(ArgList) of
true -> hd(ArgList);
- false ->
+ false ->
args(fun(A) -> A end, "|", ArgList)
end.
unique([], U) -> reverse(U);
-unique([H|R], U) ->
+unique([H|R], U) ->
case lists:member(H,U) of
false -> unique(R,[H|U]);
true -> unique(R,U)
@@ -756,7 +760,7 @@ zip(List) ->
zip([[F|L1]|List], Rest, AccL, Acc) ->
zip(List, [L1|Rest], [F|AccL], Acc);
-zip(Empty, Rest, AccL, Acc) ->
+zip(Empty, Rest, AccL, Acc) ->
true = empty(Empty),
case empty(Rest) andalso empty(AccL) of
true -> reverse(Acc);
@@ -779,7 +783,7 @@ doc_arg_type(_) -> skip.
doc_arg_type2(T=#type{single=Single}) when Single =:= array; Single =:= list ->
"[" ++ doc_arg_type3(T) ++ "]";
-doc_arg_type2(T) ->
+doc_arg_type2(T) ->
doc_arg_type3(T).
doc_arg_type3(#type{base=string}) -> "string()";
@@ -799,8 +803,8 @@ doc_arg_type3(#type{base={binary,_}}) -> "binary()";
doc_arg_type3(#type{base=eventType}) -> "atom()";
doc_arg_type3(#type{base={ref,N}}) -> N++"()";
doc_arg_type3(#type{base={term,_N}}) -> "term()";
-doc_arg_type3(T=#type{base={class,N}}) ->
- check_class(T),
+doc_arg_type3(T=#type{base={class,N}}) ->
+ check_class(T),
case get(current_class) of
N -> N ++ "()";
_ -> N++":" ++ N++"()"
@@ -809,7 +813,7 @@ doc_arg_type3({merged,_,T1=#type{base={class,N1}},_,_,T2=#type{base={class,N2}},
check_class(T1),
check_class(T2),
Curr = get(current_class),
- if
+ if
N1 =:= Curr, N2 =:= Curr -> N1++"() | "++ N2++"()";
N1 =:= Curr -> N1++"() | "++ N2++":" ++ N2++"()";
N2 =:= Curr -> N1++":" ++ N1++"() | "++ N2++"()";
@@ -824,7 +828,7 @@ doc_arg_type3(#type{base={comp,_,{record,Name}}}) ->
"wx:" ++ atom_to_list(Name) ++ "()";
doc_arg_type3(#type{base={comp,_,Tup}}) ->
Doc = fun({int,V}) -> V ++ "::integer()";
- ({double,V}) -> V ++ "::float()"
+ ({double,V}) -> V ++ "::float()"
end,
"{" ++ args(Doc, ",", Tup) ++ "}";
doc_arg_type3(T) -> ?error({unknown_type,T}).
@@ -834,7 +838,7 @@ doc_return_types(T, Ps) ->
doc_return_types2(void, []) -> "ok";
doc_return_types2(void, [#param{type=T}]) -> doc_arg_type2(T);
doc_return_types2(T, []) -> doc_arg_type2(T);
-doc_return_types2(void, Ps) ->
+doc_return_types2(void, Ps) ->
"{" ++ args(fun doc_arg_type/1,",",Ps) ++ "}";
doc_return_types2(T, Ps) ->
"{" ++ doc_arg_type2(T) ++ "," ++ args(fun doc_arg_type/1,",",Ps) ++ "}".
@@ -887,7 +891,7 @@ check_name(Name) -> Name.
marshal_opts([], _,_) -> ""; %% No opts skip this!
marshal_opts(Opts, Align, Args) ->
- w(" MOpts = fun", []),
+ w(" MOpts = fun", []),
marshal_opts1(Opts,1),
w(";~n (BadOpt, _) -> erlang:error({badoption, BadOpt}) end,~n", []),
w(" BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)),~n", []),
@@ -896,7 +900,7 @@ marshal_opts(Opts, Align, Args) ->
[] -> Str; % All Args are optional
_ -> ", " ++ Str
end.
-
+
marshal_opts1([P],N) ->
marshal_opt(P,N);
marshal_opts1([P|R],N) ->
@@ -909,15 +913,15 @@ marshal_opt(P0=#param{name=Name,type=Type},N) ->
{Arg,Align} = marshal_arg(Type,erl_arg_name(Name),1),
AStr = if Align =:= 0 -> "";
Align =:= 1 -> ",0:32"
- end,
- w("({~s, ~s}, Acc) -> ", [erl_option_name(Name), func_arg(P)]),
+ end,
+ w("({~s, ~s}, Acc) -> ", [erl_option_name(Name), func_arg(P)]),
arg_type_test(P,"",[]),
case Arg of
- skip ->
+ skip ->
w("[<<~p:32/?UI~s>>|Acc]", [N, AStr]);
- _ ->
+ _ ->
w("[<<~p:32/?UI,~s~s>>|Acc]", [N, Arg,AStr])
- end.
+ end.
marshal_args(Ps) ->
marshal_args(Ps, [], 0).
@@ -957,23 +961,23 @@ marshal_arg(#type{single=true,base={enum,_Enum}}, Name, Align) ->
marshal_arg(#type{single=true,base=bool}, Name, Align) ->
align(32, Align, "(wxe_util:from_bool(" ++ Name ++ ")):32/?UI");
-marshal_arg(#type{name="wxChar", single=Single}, Name, Align0)
+marshal_arg(#type{name="wxChar", single=Single}, Name, Align0)
when Single =/= true ->
- {Str,Align} =
+ {Str,Align} =
align(32,Align0, "(byte_size("++Name++"_UC)):32/?UI,(" ++ Name ++ "_UC)/binary"),
MsgSize = "(" ++ integer_to_list(Align*4)++"+byte_size("++Name++"_UC))",
{Str++", 0:(((8- (" ++ MsgSize ++" band 16#7)) band 16#7))/unit:8",0};
marshal_arg(#type{base=string}, Name, Align0) ->
- {Str,Align} =
+ {Str,Align} =
align(32,Align0, "(byte_size("++Name++"_UC)):32/?UI,(" ++ Name ++ "_UC)/binary"),
MsgSize = "(" ++ integer_to_list(Align*4)++"+byte_size("++Name++"_UC))",
{Str++", 0:(((8- (" ++ MsgSize ++" band 16#7)) band 16#7))/unit:8",0};
marshal_arg(#type{name="wxArrayString"}, Name, Align0) ->
- InnerBin = "<<(byte_size(UC_Str)):32/?UI, UC_Str/binary>>",
+ InnerBin = "<<(byte_size(UC_Str)):32/?UI, UC_Str/binary>>",
Outer = "(<< " ++ InnerBin ++ "|| UC_Str <- "++ Name ++"_UCA>>)/binary",
Str0 = "(length("++Name++"_UCA)):32/?UI, " ++ Outer,
{Str,Align} = align(32,Align0,Str0),
- MsgSize = "("++integer_to_list(Align*4) ++
+ MsgSize = "("++integer_to_list(Align*4) ++
" + lists:sum([byte_size(S)+4||S<-" ++ Name ++"_UCA]))",
AStr = ", 0:(((8- (" ++ MsgSize ++" band 16#7)) band 16#7))/unit:8",
{Str ++ AStr, 0};
@@ -997,15 +1001,15 @@ marshal_arg(#type{base={term,_}}, _Name, Align0) ->
{skip,Align0};
marshal_arg(#type{base=binary}, _Name, Align0) ->
{skip,Align0};
-marshal_arg(#type{base=Base, single=Single}, Name, Align0)
+marshal_arg(#type{base=Base, single=Single}, Name, Align0)
when Single =/= true ->
- case Base of
- int ->
+ case Base of
+ int ->
Str0 = "(length("++Name++")):32/?UI,\n"
" (<< <<C:32/?I>> || C <- "++Name++">>)/binary",
{Str,Align} = align(32,Align0, Str0),
{Str ++ ", 0:((("++integer_to_list(Align)++"+length("++Name++ ")) rem 2)*32)", 0};
- {ObjRef,_} when ObjRef =:= class; ObjRef =:= ref ->
+ {ObjRef,_} when ObjRef =:= class; ObjRef =:= ref ->
Str0 = "(length("++Name++")):32/?UI,",
Str1 = "\n (<< <<(C#wx_ref.ref):32/?UI>> || C <- "++Name++">>)/binary",
{Str2,Align} = align(32, Align0, Str1),
@@ -1033,7 +1037,7 @@ align(64, 0, Str) -> {Str, 0};
align(64, 1, Str) -> {"0:32," ++ Str,0};
align(Sz, W, Str) -> align(Sz, W rem 2, Str).
-enum_name(Name) ->
+enum_name(Name) ->
case string:tokens(Name, ":") of
[Name] -> Name;
[C,N] -> C ++ "_" ++ N
@@ -1053,10 +1057,10 @@ gen_enums_ints() ->
" }).~n", []),
w("~n%% Hardcoded Defines~n", []),
Enums = [E || {{enum,_},E = #enum{as_atom=false}} <- get()],
- w("-define(wxDefaultSize, {-1,-1}).~n", []),
- w("-define(wxDefaultPosition, {-1,-1}).~n", []),
+ w("-define(wxDefaultSize, {-1,-1}).~n", []),
+ w("-define(wxDefaultPosition, {-1,-1}).~n", []),
w("~n%% Global Variables~n", []),
- [w("-define(~s, wxe_util:get_const(~s)).~n", [Gvar, Gvar]) ||
+ [w("-define(~s, wxe_util:get_const(~s)).~n", [Gvar, Gvar]) ||
{Gvar,_,_Id} <- get(gvars)],
w("~n%% Enum and defines~n", []),
foldl(fun(Enum= #enum{vals=Vals}, Done) when Vals =/= [] ->
@@ -1076,7 +1080,7 @@ build_enum_ints(#enum{from=From, vals=Vals},Done) ->
{_File, Class, Name} ->
w("% From class ~s::~s~n",[Class, Name])
end,
-
+
Format = fun(#const{name="wxEVT_" ++ _}) ->
ignore; %% Ignore event macros they are not valid in our event model
(#const{name=Name,val=Value,is_const=true}) when is_integer(Value) ->
@@ -1100,12 +1104,12 @@ build_enum_ints(#enum{from=From, vals=Vals},Done) ->
Consts = get(consts),
Write = fun({Name,_What}, Skip) ->
case gb_sets:is_member(Name,Skip) of
- true ->
+ true ->
Skip;
false ->
case gb_trees:lookup(Name, Consts) of
{value, Const} ->
- Format(Const),
+ Format(Const),
gb_sets:add(Name,Skip);
none -> Skip
end
@@ -1119,8 +1123,8 @@ gen_event_recs() ->
w("", []),
w("%% This file is generated DO NOT EDIT~n~n", []),
w("%% All event messages are encapsulated in a wx record~n"
- "%% they contain the widget id and a specialized event record.~n"
- "%% Each event record may be sent for one or more event types.~n"
+ "%% they contain the widget id and a specialized event record.~n"
+ "%% Each event record may be sent for one or more event types.~n"
"%% The mapping to wxWidgets is one record per class.~n~n",[]),
w("%% @type wx() = #wx{id=integer(), obj=wx:wxObject(), userData=term(), event=Rec}. Rec is a event record.~n",[]),
w("-record(wx, {id, %% Integer Identity of object.~n"
@@ -1130,7 +1134,7 @@ gen_event_recs() ->
w("%% Here comes the definitions of all event records.~n"
"%% they contain the event type and possible some extra information.~n~n",[]),
Types = [build_event_rec(C) || {_,C=#class{event=Evs}} <- get(), Evs =/= false],
- w("%% @type wxEventType() = ~s.~n",
+ w("%% @type wxEventType() = ~s.~n",
[args(fun(Ev) -> Ev end, " | ", lists:sort(lists:append(Types)))]),
%% close(), closed in gen_enums_ints
ok.
@@ -1145,22 +1149,22 @@ find_inherited_attr(Param = {PName,_}, Name) ->
end.
filter_attrs(#class{name=Name, parent=Parent,attributes=Attrs}) ->
- Attr1 = lists:foldl(fun(#param{acc=skip},Acc) -> Acc;
+ Attr1 = lists:foldl(fun(#param{acc=skip},Acc) -> Acc;
(P=#param{prot=public},Acc) -> [P|Acc];
- (#param{acc=undefined},Acc) -> Acc;
+ (#param{acc=undefined},Acc) -> Acc;
({inherited, PName},Acc) ->
case find_inherited_attr(PName, Parent) of
- undefined ->
+ undefined ->
io:format("~p:~p: Missing Event Attr ~p in ~p~n",
[?MODULE,?LINE, PName, Name]),
Acc;
- P ->
+ P ->
[P|Acc]
end;
(P, Acc) -> [P|Acc]
end, [], Attrs),
lists:reverse(Attr1).
-
+
build_event_rec(Class=#class{name=Name, event=Evs}) ->
EvTypes = [event_type_name(Ev) || Ev <- Evs],
Str = args(fun(Ev) -> "<em>"++Ev++"</em>" end, ", ", EvTypes),
@@ -1168,26 +1172,26 @@ build_event_rec(Class=#class{name=Name, event=Evs}) ->
Rec = event_rec_name(Name),
GetName = fun(#param{name=N}) ->event_attr_name(N) end,
GetType = fun(#param{name=N,type=T}) ->
- event_attr_name(N) ++ "=" ++ doc_arg_type2(T)
+ event_attr_name(N) ++ "=" ++ doc_arg_type2(T)
end,
case Attr =:= [] of
- true ->
+ true ->
w("%% @type ~s() = #~s{type=wxEventType()}.~n", [Rec,Rec]),
w("%% <dl><dt>EventType:</dt> <dd>~s</dd></dl>~n",[Str]),
-%% case is_command_event(Name) of
+%% case is_command_event(Name) of
%% true -> w("%% This event skips other event handlers.~n",[]);
%% false -> w("%% This event will be handled by other handlers~n",[])
%% end,
w("%% Callback event: {@link ~s}~n", [Name]),
w("-record(~s, {type}).~n~n", [Rec]);
false ->
- w("%% @type ~s() = #~s{type=wxEventType(),~s}.~n",
+ w("%% @type ~s() = #~s{type=wxEventType(),~s}.~n",
[Rec,Rec,args(GetType,",",Attr)]),
w("%% <dl><dt>EventType:</dt> <dd>~s</dd></dl>~n",[Str]),
-%% case is_command_event(Name) of
+%% case is_command_event(Name) of
%% true -> w("%% This event skips other event handlers.~n",[]);
%% false -> w("%% This event will be handled by other handlers~n",[])
-%% end,
+%% end,
w("%% Callback event: {@link ~s}~n", [Name]),
w("-record(~s,{type, ~s}).~n~n", [Rec,args(GetName,",",Attr)])
end,
@@ -1198,7 +1202,7 @@ is_command_event(Name) ->
true -> true;
false -> false
end.
-
+
event_rec_name(Name0 = "wx" ++ _) ->
"tnevE" ++ Name1 = reverse(Name0),
reverse(Name1).
@@ -1215,7 +1219,7 @@ event_attr_name(Attr) ->
lowercase(Attr).
-gen_funcnames() ->
+gen_funcnames() ->
open_write("../src/gen/wxe_debug.hrl"),
erl_copyright(),
w("%% This file is generated DO NOT EDIT~n~n", []),
@@ -1257,7 +1261,7 @@ unique_names(Ms0, Class) ->
Ms = split_list(fun(#method{name=N}, M) -> {N =:= M, N} end, undefined, Ms2),
unique_names2(Ms,Class).
%% by Names
-unique_names2([[#method{id=Id, name=Method,alias=Alias, max_arity=A}]|Ms], Class) ->
+unique_names2([[#method{id=Id, name=Method,alias=Alias, max_arity=A}]|Ms], Class) ->
[{Class,uname(alias(Method,Alias),Class),A,Id} | unique_names2(Ms,Class)];
unique_names2([Ms0|RMs], Class) ->
Split = fun(#method{max_arity=A}, P) -> {A =:= P, A} end,
@@ -1278,11 +1282,11 @@ unique_names4([], _, _Class) -> [].
alias(Method, undefined) -> Method;
alias(_, Alias) -> Alias.
-
+
uname(Class,Class) -> "new";
uname([$~ | _], _ ) -> "destruct";
uname(Name, _) -> Name.
-
+
split_list(F, Keep, List) ->
split_list(F, Keep, List, []).
@@ -1297,5 +1301,5 @@ split_list(F, Keep, [M|Ms], Acc) ->
end;
split_list(_, _, [], []) -> [];
split_list(_, _, [], Acc) -> [lists:reverse(Acc)].
-
+
diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf
index aec8a4944a..8ee4451057 100644
--- a/lib/wx/api_gen/wxapi.conf
+++ b/lib/wx/api_gen/wxapi.conf
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -756,7 +756,9 @@
'SetFirstItem']}.
{class, wxListCtrl, wxControl, [],
- ['wxListCtrl','~wxListCtrl','Arrange','AssignImageList','ClearAll','Create',
+ [{'wxListCtrl', [{where, taylormade}]},
+ '~wxListCtrl','Arrange','AssignImageList','ClearAll',
+ {'Create',[{where, taylormade}]},
'DeleteAllItems','DeleteColumn','DeleteItem',
{'EditLabel',[{"textControlClass",nowhere}]},
'EnsureVisible',
@@ -788,6 +790,13 @@
'SetFont','SetId','SetImage','SetMask','SetState',
'SetStateMask','SetText','SetTextColour','SetWidth']}.
+{class, wxListItemAttr, root, [],
+ ['wxListItemAttr','~wxListItemAttr',
+ 'GetBackgroundColour', 'GetFont',
+ 'GetTextColour', 'HasBackgroundColour', 'HasFont',
+ 'HasTextColour', 'SetBackgroundColour', 'SetFont', 'SetTextColour'
+ ]}.
+
{class, wxImageList, object, [{skip, [{'Create',1}]}], %% No create/0 on windows
['wxImageList','~wxImageList','Add','Create','Draw','GetBitmap','GetIcon','GetImageCount',
'GetSize','Remove','RemoveAll','Replace']}.
diff --git a/lib/wx/c_src/egl_impl.cpp b/lib/wx/c_src/egl_impl.cpp
index e2dbbb73c4..6d873abc44 100644
--- a/lib/wx/c_src/egl_impl.cpp
+++ b/lib/wx/c_src/egl_impl.cpp
@@ -1,20 +1,20 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 2010. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 2011. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
- * %CopyrightEnd%
+ *
+ * %CopyrightEnd%
*/
#include <stdio.h>
@@ -35,8 +35,8 @@ void init_tess();
void exit_tess();
int load_gl_functions();
-/* ****************************************************************************
- * OPENGL INITIALIZATION
+/* ****************************************************************************
+ * OPENGL INITIALIZATION
*****************************************************************************/
int egl_initiated = 0;
@@ -51,7 +51,7 @@ void * dlsym(HMODULE Lib, const char *func) {
void * funcp;
if((funcp = (void *) GetProcAddress(Lib, func)))
return funcp;
- else
+ else
return (void *) wglGetProcAddress(func);
}
@@ -73,14 +73,14 @@ typedef char DL_CHAR;
# define OPENGL_LIB "libGL.so"
# define OPENGLU_LIB "libGLU.so"
# endif
-#endif
+#endif
extern "C" {
-DRIVER_INIT(EGL_DRIVER) {
+DRIVER_INIT(EGL_DRIVER) {
return NULL;
}
}
-int egl_init_opengl(void *erlCallbacks)
+int egl_init_opengl(void *erlCallbacks)
{
#ifdef _WIN32
driver_init((TWinDynDriverCallbacks *) erlCallbacks);
@@ -95,7 +95,7 @@ int egl_init_opengl(void *erlCallbacks)
}
int load_gl_functions() {
- DL_CHAR * DLName = OPENGL_LIB;
+ DL_CHAR * DLName = (DL_CHAR *) OPENGL_LIB;
DL_LIB_P LIBhandle = dlopen(DLName, RTLD_LAZY);
//fprintf(stderr, "Loading GL: %s\r\n", (const char*)DLName);
void * func = NULL;
@@ -127,13 +127,13 @@ int load_gl_functions() {
fprintf(stderr, "Could NOT load OpenGL library: %s\r\n", DLName);
};
- DLName = OPENGLU_LIB;
+ DLName = (DL_CHAR *) OPENGLU_LIB;
LIBhandle = dlopen(DLName, RTLD_LAZY);
// fprintf(stderr, "Loading GLU: %s\r\n", (const char*)DLName);
func = NULL;
if(LIBhandle) {
- for(i=0; glu_fns[i].name != NULL; i++) {
+ for(i=0; glu_fns[i].name != NULL; i++) {
if((func = dlsym(LIBhandle, glu_fns[i].name))) {
* (void **) (glu_fns[i].func) = func;
} else {
@@ -201,7 +201,7 @@ egl_ogla_error(GLenum errorCode)
void CALLBACK
egl_ogla_combine(GLdouble coords[3],
void* vertex_data[4],
- GLfloat w[4],
+ GLfloat w[4],
void **dataOut)
{
GLdouble* vertex = tess_alloc_vertex;
@@ -226,7 +226,7 @@ egl_ogla_combine(GLdouble coords[3],
*dataOut = vertex;
}
-void init_tess()
+void init_tess()
{
tess = gluNewTess();
@@ -237,7 +237,7 @@ void init_tess()
}
-void exit_tess()
+void exit_tess()
{
gluDeleteTess(tess);
}
@@ -251,22 +251,22 @@ int erl_tess_impl(char* buff, ErlDrvPort port, ErlDrvTermData caller)
int num_vertices;
GLdouble *n;
int n_pos, AP, res;
-
+
num_vertices = * (int *) buff; buff += 8; /* Align */
n = (double *) buff; buff += 8*3;
- bin = driver_alloc_binary(num_vertices*6*sizeof(GLdouble));
+ bin = driver_alloc_binary(num_vertices*6*sizeof(GLdouble));
new_vertices = tess_coords = (double *) bin->orig_bytes;
memcpy(tess_coords,buff,num_vertices*3*sizeof(GLdouble));
tess_alloc_vertex = tess_coords + num_vertices*3;
#if 0
fprintf(stderr, "n=%d\r\n", num_vertices);
-#endif
+#endif
vertices = (int *) driver_alloc(sizeof(int) * 16*num_vertices);
-
+
tess_vertices = vertices;
-
+
gluTessNormal(tess, n[0], n[1], n[2]);
gluTessBeginPolygon(tess, 0);
gluTessBeginContour(tess);
@@ -275,9 +275,9 @@ int erl_tess_impl(char* buff, ErlDrvPort port, ErlDrvTermData caller)
}
gluTessEndContour(tess);
gluTessEndPolygon(tess);
-
- n_pos = (tess_vertices - vertices);
-
+
+ n_pos = (tess_vertices - vertices);
+
AP = 0; ErlDrvTermData *rt;
rt = (ErlDrvTermData *) driver_alloc(sizeof(ErlDrvTermData) * (13+n_pos*2));
rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");
@@ -287,12 +287,12 @@ int erl_tess_impl(char* buff, ErlDrvPort port, ErlDrvTermData caller)
};
rt[AP++] = ERL_DRV_NIL; rt[AP++] = ERL_DRV_LIST; rt[AP++] = n_pos+1;
- rt[AP++] = ERL_DRV_BINARY; rt[AP++] = (ErlDrvTermData) bin;
+ rt[AP++] = ERL_DRV_BINARY; rt[AP++] = (ErlDrvTermData) bin;
rt[AP++] = (tess_alloc_vertex-new_vertices)*sizeof(GLdouble); rt[AP++] = 0;
-
+
rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2; // Return tuple {list, Bin}
rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2; // Result tuple
-
+
res = driver_send_term(port,caller,rt,AP);
/* fprintf(stderr, "List %d: %d %d %d \r\n", */
/* res, */
diff --git a/lib/wx/c_src/gen/wxe_derived_dest.h b/lib/wx/c_src/gen/wxe_derived_dest.h
index ad46a98c90..4e4aea098d 100644
--- a/lib/wx/c_src/gen/wxe_derived_dest.h
+++ b/lib/wx/c_src/gen/wxe_derived_dest.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -362,10 +362,22 @@ class EwxListBox : public wxListBox {
EwxListBox() : wxListBox() {};
};
+
class EwxListCtrl : public wxListCtrl {
- public: ~EwxListCtrl() {((WxeApp *)wxTheApp)->clearPtr(this);};
+ public: ~EwxListCtrl();
EwxListCtrl(wxWindow * parent,wxWindowID winid,const wxPoint& pos,const wxSize& size,long style,const wxValidator& validator) : wxListCtrl(parent,winid,pos,size,style,validator) {};
EwxListCtrl() : wxListCtrl() {};
+
+ int onGetItemText;
+ int onGetItemAttr;
+ int onGetItemColumnImage;
+ ErlDrvPort port;
+
+ private:
+ virtual wxString OnGetItemText(long item, long col) const;
+ virtual wxListItemAttr* OnGetItemAttr(long item) const;
+ virtual int OnGetItemImage(long item) const;
+ virtual int OnGetItemColumnImage(long item, long column) const;
};
class EwxListItem : public wxListItem {
@@ -715,28 +727,3 @@ class EwxHtmlWindow : public wxHtmlWindow {
EwxHtmlWindow() : wxHtmlWindow() {};
};
-void WxeApp::delete_object(void *ptr, wxeRefData *refd) {
- switch(refd->type) {
- case 24: delete (wxGridCellBoolRenderer *) ptr; break;
- case 25: delete (wxGridCellBoolEditor *) ptr; break;
- case 26: delete (wxGridCellFloatRenderer *) ptr; break;
- case 27: delete (wxGridCellFloatEditor *) ptr; break;
- case 28: delete (wxGridCellStringRenderer *) ptr; break;
- case 29: delete (wxGridCellTextEditor *) ptr; break;
- case 30: delete (wxGridCellChoiceEditor *) ptr; break;
- case 31: delete (wxGridCellNumberRenderer *) ptr; break;
- case 32: delete (wxGridCellNumberEditor *) ptr; break;
- case 61: delete (wxIconBundle *) ptr; break;
- case 69: delete (wxAcceleratorEntry *) ptr; break;
- case 70: /* delete (wxCaret *) ptr;These objects must be deleted by owner object */ break;
- case 72: delete (wxSizerFlags *) ptr; break;
- case 88: /* delete (wxCalendarDateAttr *) ptr;These objects must be deleted by owner object */ break;
- case 102: delete (wxTextAttr *) ptr; break;
- case 154: delete (wxAuiPaneInfo *) ptr; break;
- 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 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 692eef858c..b9769318af 100644
--- a/lib/wx/c_src/gen/wxe_events.cpp
+++ b/lib/wx/c_src/gen/wxe_events.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2011. All Rights Reserved.
*
* The 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,15 +37,15 @@ int wxeEventTypeFromAtom(char *etype_atom) {
wxeETmap::iterator it;
for(it = etmap.begin(); it != etmap.end(); ++it) {
wxeEtype * value = it->second;
- if(strcmp(value->eName, etype_atom) == 0) {
- if(it->first > wxEVT_USER_FIRST) {
+ if(strcmp(value->eName, etype_atom) == 0) {
+ if(it->first > wxEVT_USER_FIRST) {
return it->first - wxEVT_USER_FIRST;
} else {
return it->first;
}
}
- }
- return -1;
+ }
+ return -1;
}
void initEventTable()
@@ -53,254 +53,254 @@ void initEventTable()
struct { int ev_type; int class_id; const char * ev_name;} event_types[] =
{
{wxEVT_NULL, 0, "null"},
- {wxEVT_COMMAND_BUTTON_CLICKED, 163, "command_button_clicked"},
- {wxEVT_COMMAND_CHECKBOX_CLICKED, 163, "command_checkbox_clicked"},
- {wxEVT_COMMAND_CHOICE_SELECTED, 163, "command_choice_selected"},
- {wxEVT_COMMAND_LISTBOX_SELECTED, 163, "command_listbox_selected"},
- {wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, 163, "command_listbox_doubleclicked"},
- {wxEVT_COMMAND_TEXT_UPDATED, 163, "command_text_updated"},
- {wxEVT_COMMAND_TEXT_ENTER, 163, "command_text_enter"},
- {wxEVT_COMMAND_MENU_SELECTED, 163, "command_menu_selected"},
- {wxEVT_COMMAND_SLIDER_UPDATED, 163, "command_slider_updated"},
- {wxEVT_COMMAND_RADIOBOX_SELECTED, 163, "command_radiobox_selected"},
- {wxEVT_COMMAND_RADIOBUTTON_SELECTED, 163, "command_radiobutton_selected"},
- {wxEVT_COMMAND_SCROLLBAR_UPDATED, 163, "command_scrollbar_updated"},
- {wxEVT_COMMAND_VLBOX_SELECTED, 163, "command_vlbox_selected"},
- {wxEVT_COMMAND_COMBOBOX_SELECTED, 163, "command_combobox_selected"},
- {wxEVT_COMMAND_TOOL_RCLICKED, 163, "command_tool_rclicked"},
- {wxEVT_COMMAND_TOOL_ENTER, 163, "command_tool_enter"},
- {wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, 163, "command_checklistbox_toggled"},
- {wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, 163, "command_togglebutton_clicked"},
- {wxEVT_COMMAND_LEFT_CLICK, 163, "command_left_click"},
- {wxEVT_COMMAND_LEFT_DCLICK, 163, "command_left_dclick"},
- {wxEVT_COMMAND_RIGHT_CLICK, 163, "command_right_click"},
- {wxEVT_COMMAND_SET_FOCUS, 163, "command_set_focus"},
- {wxEVT_COMMAND_KILL_FOCUS, 163, "command_kill_focus"},
- {wxEVT_COMMAND_ENTER, 163, "command_enter"},
- {wxEVT_SCROLL_TOP, 164, "scroll_top"},
- {wxEVT_SCROLL_BOTTOM, 164, "scroll_bottom"},
- {wxEVT_SCROLL_LINEUP, 164, "scroll_lineup"},
- {wxEVT_SCROLL_LINEDOWN, 164, "scroll_linedown"},
- {wxEVT_SCROLL_PAGEUP, 164, "scroll_pageup"},
- {wxEVT_SCROLL_PAGEDOWN, 164, "scroll_pagedown"},
- {wxEVT_SCROLL_THUMBTRACK, 164, "scroll_thumbtrack"},
- {wxEVT_SCROLL_THUMBRELEASE, 164, "scroll_thumbrelease"},
- {wxEVT_SCROLL_CHANGED, 164, "scroll_changed"},
- {wxEVT_SCROLLWIN_TOP, 165, "scrollwin_top"},
- {wxEVT_SCROLLWIN_BOTTOM, 165, "scrollwin_bottom"},
- {wxEVT_SCROLLWIN_LINEUP, 165, "scrollwin_lineup"},
- {wxEVT_SCROLLWIN_LINEDOWN, 165, "scrollwin_linedown"},
- {wxEVT_SCROLLWIN_PAGEUP, 165, "scrollwin_pageup"},
- {wxEVT_SCROLLWIN_PAGEDOWN, 165, "scrollwin_pagedown"},
- {wxEVT_SCROLLWIN_THUMBTRACK, 165, "scrollwin_thumbtrack"},
- {wxEVT_SCROLLWIN_THUMBRELEASE, 165, "scrollwin_thumbrelease"},
- {wxEVT_LEFT_DOWN, 166, "left_down"},
- {wxEVT_LEFT_UP, 166, "left_up"},
- {wxEVT_MIDDLE_DOWN, 166, "middle_down"},
- {wxEVT_MIDDLE_UP, 166, "middle_up"},
- {wxEVT_RIGHT_DOWN, 166, "right_down"},
- {wxEVT_RIGHT_UP, 166, "right_up"},
- {wxEVT_MOTION, 166, "motion"},
- {wxEVT_ENTER_WINDOW, 166, "enter_window"},
- {wxEVT_LEAVE_WINDOW, 166, "leave_window"},
- {wxEVT_LEFT_DCLICK, 166, "left_dclick"},
- {wxEVT_MIDDLE_DCLICK, 166, "middle_dclick"},
- {wxEVT_RIGHT_DCLICK, 166, "right_dclick"},
- {wxEVT_MOUSEWHEEL, 166, "mousewheel"},
- {wxEVT_NC_LEFT_DOWN, 166, "nc_left_down"},
- {wxEVT_NC_LEFT_UP, 166, "nc_left_up"},
- {wxEVT_NC_MIDDLE_DOWN, 166, "nc_middle_down"},
- {wxEVT_NC_MIDDLE_UP, 166, "nc_middle_up"},
- {wxEVT_NC_RIGHT_DOWN, 166, "nc_right_down"},
- {wxEVT_NC_RIGHT_UP, 166, "nc_right_up"},
- {wxEVT_NC_MOTION, 166, "nc_motion"},
- {wxEVT_NC_ENTER_WINDOW, 166, "nc_enter_window"},
- {wxEVT_NC_LEAVE_WINDOW, 166, "nc_leave_window"},
- {wxEVT_NC_LEFT_DCLICK, 166, "nc_left_dclick"},
- {wxEVT_NC_MIDDLE_DCLICK, 166, "nc_middle_dclick"},
- {wxEVT_NC_RIGHT_DCLICK, 166, "nc_right_dclick"},
- {wxEVT_SET_CURSOR, 167, "set_cursor"},
- {wxEVT_CHAR, 168, "char"},
- {wxEVT_CHAR_HOOK, 168, "char_hook"},
- {wxEVT_KEY_DOWN, 168, "key_down"},
- {wxEVT_KEY_UP, 168, "key_up"},
- {wxEVT_SIZE, 169, "size"},
- {wxEVT_MOVE, 170, "move"},
- {wxEVT_PAINT, 171, "paint"},
- {wxEVT_PAINT_ICON, 171, "paint_icon"},
- {wxEVT_NC_PAINT, 172, "nc_paint"},
- {wxEVT_ERASE_BACKGROUND, 173, "erase_background"},
- {wxEVT_SET_FOCUS, 174, "set_focus"},
- {wxEVT_KILL_FOCUS, 174, "kill_focus"},
- {wxEVT_CHILD_FOCUS, 175, "child_focus"},
- {wxEVT_MENU_OPEN, 176, "menu_open"},
- {wxEVT_MENU_CLOSE, 176, "menu_close"},
- {wxEVT_MENU_HIGHLIGHT, 176, "menu_highlight"},
- {wxEVT_CLOSE_WINDOW, 177, "close_window"},
- {wxEVT_END_SESSION, 177, "end_session"},
- {wxEVT_QUERY_END_SESSION, 177, "query_end_session"},
- {wxEVT_SHOW, 178, "show"},
- {wxEVT_ICONIZE, 179, "iconize"},
- {wxEVT_MAXIMIZE, 180, "maximize"},
- {wxEVT_JOY_BUTTON_DOWN, 181, "joy_button_down"},
- {wxEVT_JOY_BUTTON_UP, 181, "joy_button_up"},
- {wxEVT_JOY_MOVE, 181, "joy_move"},
- {wxEVT_JOY_ZMOVE, 181, "joy_zmove"},
- {wxEVT_UPDATE_UI, 182, "update_ui"},
- {wxEVT_SYS_COLOUR_CHANGED, 183, "sys_colour_changed"},
- {wxEVT_MOUSE_CAPTURE_CHANGED, 184, "mouse_capture_changed"},
- {wxEVT_DISPLAY_CHANGED, 185, "display_changed"},
- {wxEVT_PALETTE_CHANGED, 186, "palette_changed"},
- {wxEVT_QUERY_NEW_PALETTE, 187, "query_new_palette"},
- {wxEVT_NAVIGATION_KEY, 188, "navigation_key"},
- {wxEVT_CREATE, 189, "create"},
- {wxEVT_DESTROY, 190, "destroy"},
- {wxEVT_HELP, 191, "help"},
- {wxEVT_DETAILED_HELP, 191, "detailed_help"},
- {wxEVT_CONTEXT_MENU, 192, "context_menu"},
- {wxEVT_IDLE, 193, "idle"},
- {wxEVT_GRID_CELL_LEFT_CLICK, 194, "grid_cell_left_click"},
- {wxEVT_GRID_CELL_RIGHT_CLICK, 194, "grid_cell_right_click"},
- {wxEVT_GRID_CELL_LEFT_DCLICK, 194, "grid_cell_left_dclick"},
- {wxEVT_GRID_CELL_RIGHT_DCLICK, 194, "grid_cell_right_dclick"},
- {wxEVT_GRID_LABEL_LEFT_CLICK, 194, "grid_label_left_click"},
- {wxEVT_GRID_LABEL_RIGHT_CLICK, 194, "grid_label_right_click"},
- {wxEVT_GRID_LABEL_LEFT_DCLICK, 194, "grid_label_left_dclick"},
- {wxEVT_GRID_LABEL_RIGHT_DCLICK, 194, "grid_label_right_dclick"},
- {wxEVT_GRID_ROW_SIZE, 194, "grid_row_size"},
- {wxEVT_GRID_COL_SIZE, 194, "grid_col_size"},
- {wxEVT_GRID_RANGE_SELECT, 194, "grid_range_select"},
- {wxEVT_GRID_CELL_CHANGE, 194, "grid_cell_change"},
- {wxEVT_GRID_SELECT_CELL, 194, "grid_select_cell"},
- {wxEVT_GRID_EDITOR_SHOWN, 194, "grid_editor_shown"},
- {wxEVT_GRID_EDITOR_HIDDEN, 194, "grid_editor_hidden"},
- {wxEVT_GRID_EDITOR_CREATED, 194, "grid_editor_created"},
- {wxEVT_GRID_CELL_BEGIN_DRAG, 194, "grid_cell_begin_drag"},
- {wxEVT_SASH_DRAGGED, 196, "sash_dragged"},
- {wxEVT_COMMAND_LIST_BEGIN_DRAG, 197, "command_list_begin_drag"},
- {wxEVT_COMMAND_LIST_BEGIN_RDRAG, 197, "command_list_begin_rdrag"},
- {wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, 197, "command_list_begin_label_edit"},
- {wxEVT_COMMAND_LIST_END_LABEL_EDIT, 197, "command_list_end_label_edit"},
- {wxEVT_COMMAND_LIST_DELETE_ITEM, 197, "command_list_delete_item"},
- {wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, 197, "command_list_delete_all_items"},
- {wxEVT_COMMAND_LIST_KEY_DOWN, 197, "command_list_key_down"},
- {wxEVT_COMMAND_LIST_INSERT_ITEM, 197, "command_list_insert_item"},
- {wxEVT_COMMAND_LIST_COL_CLICK, 197, "command_list_col_click"},
- {wxEVT_COMMAND_LIST_COL_RIGHT_CLICK, 197, "command_list_col_right_click"},
- {wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, 197, "command_list_col_begin_drag"},
- {wxEVT_COMMAND_LIST_COL_DRAGGING, 197, "command_list_col_dragging"},
- {wxEVT_COMMAND_LIST_COL_END_DRAG, 197, "command_list_col_end_drag"},
- {wxEVT_COMMAND_LIST_ITEM_SELECTED, 197, "command_list_item_selected"},
- {wxEVT_COMMAND_LIST_ITEM_DESELECTED, 197, "command_list_item_deselected"},
- {wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, 197, "command_list_item_right_click"},
- {wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK, 197, "command_list_item_middle_click"},
- {wxEVT_COMMAND_LIST_ITEM_ACTIVATED, 197, "command_list_item_activated"},
- {wxEVT_COMMAND_LIST_ITEM_FOCUSED, 197, "command_list_item_focused"},
- {wxEVT_COMMAND_LIST_CACHE_HINT, 197, "command_list_cache_hint"},
- {wxEVT_DATE_CHANGED, 198, "date_changed"},
- {wxEVT_CALENDAR_SEL_CHANGED, 199, "calendar_sel_changed"},
- {wxEVT_CALENDAR_DAY_CHANGED, 199, "calendar_day_changed"},
- {wxEVT_CALENDAR_MONTH_CHANGED, 199, "calendar_month_changed"},
- {wxEVT_CALENDAR_YEAR_CHANGED, 199, "calendar_year_changed"},
- {wxEVT_CALENDAR_DOUBLECLICKED, 199, "calendar_doubleclicked"},
- {wxEVT_CALENDAR_WEEKDAY_CLICKED, 199, "calendar_weekday_clicked"},
- {wxEVT_COMMAND_FILEPICKER_CHANGED, 200, "command_filepicker_changed"},
- {wxEVT_COMMAND_DIRPICKER_CHANGED, 200, "command_dirpicker_changed"},
- {wxEVT_COMMAND_COLOURPICKER_CHANGED, 201, "command_colourpicker_changed"},
- {wxEVT_COMMAND_FONTPICKER_CHANGED, 202, "command_fontpicker_changed"},
- {wxEVT_STC_CHANGE, 203, "stc_change"},
- {wxEVT_STC_STYLENEEDED, 203, "stc_styleneeded"},
- {wxEVT_STC_CHARADDED, 203, "stc_charadded"},
- {wxEVT_STC_SAVEPOINTREACHED, 203, "stc_savepointreached"},
- {wxEVT_STC_SAVEPOINTLEFT, 203, "stc_savepointleft"},
- {wxEVT_STC_ROMODIFYATTEMPT, 203, "stc_romodifyattempt"},
- {wxEVT_STC_KEY, 203, "stc_key"},
- {wxEVT_STC_DOUBLECLICK, 203, "stc_doubleclick"},
- {wxEVT_STC_UPDATEUI, 203, "stc_updateui"},
- {wxEVT_STC_MODIFIED, 203, "stc_modified"},
- {wxEVT_STC_MACRORECORD, 203, "stc_macrorecord"},
- {wxEVT_STC_MARGINCLICK, 203, "stc_marginclick"},
- {wxEVT_STC_NEEDSHOWN, 203, "stc_needshown"},
- {wxEVT_STC_PAINTED, 203, "stc_painted"},
- {wxEVT_STC_USERLISTSELECTION, 203, "stc_userlistselection"},
- {wxEVT_STC_URIDROPPED, 203, "stc_uridropped"},
- {wxEVT_STC_DWELLSTART, 203, "stc_dwellstart"},
- {wxEVT_STC_DWELLEND, 203, "stc_dwellend"},
- {wxEVT_STC_START_DRAG, 203, "stc_start_drag"},
- {wxEVT_STC_DRAG_OVER, 203, "stc_drag_over"},
- {wxEVT_STC_DO_DROP, 203, "stc_do_drop"},
- {wxEVT_STC_ZOOM, 203, "stc_zoom"},
- {wxEVT_STC_HOTSPOT_CLICK, 203, "stc_hotspot_click"},
- {wxEVT_STC_HOTSPOT_DCLICK, 203, "stc_hotspot_dclick"},
- {wxEVT_STC_CALLTIP_CLICK, 203, "stc_calltip_click"},
- {wxEVT_STC_AUTOCOMP_SELECTION, 203, "stc_autocomp_selection"},
- {wxEVT_COMMAND_TREE_BEGIN_DRAG, 208, "command_tree_begin_drag"},
- {wxEVT_COMMAND_TREE_BEGIN_RDRAG, 208, "command_tree_begin_rdrag"},
- {wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, 208, "command_tree_begin_label_edit"},
- {wxEVT_COMMAND_TREE_END_LABEL_EDIT, 208, "command_tree_end_label_edit"},
- {wxEVT_COMMAND_TREE_DELETE_ITEM, 208, "command_tree_delete_item"},
- {wxEVT_COMMAND_TREE_GET_INFO, 208, "command_tree_get_info"},
- {wxEVT_COMMAND_TREE_SET_INFO, 208, "command_tree_set_info"},
- {wxEVT_COMMAND_TREE_ITEM_EXPANDED, 208, "command_tree_item_expanded"},
- {wxEVT_COMMAND_TREE_ITEM_EXPANDING, 208, "command_tree_item_expanding"},
- {wxEVT_COMMAND_TREE_ITEM_COLLAPSED, 208, "command_tree_item_collapsed"},
- {wxEVT_COMMAND_TREE_ITEM_COLLAPSING, 208, "command_tree_item_collapsing"},
- {wxEVT_COMMAND_TREE_SEL_CHANGED, 208, "command_tree_sel_changed"},
- {wxEVT_COMMAND_TREE_SEL_CHANGING, 208, "command_tree_sel_changing"},
- {wxEVT_COMMAND_TREE_KEY_DOWN, 208, "command_tree_key_down"},
- {wxEVT_COMMAND_TREE_ITEM_ACTIVATED, 208, "command_tree_item_activated"},
- {wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, 208, "command_tree_item_right_click"},
- {wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK, 208, "command_tree_item_middle_click"},
- {wxEVT_COMMAND_TREE_END_DRAG, 208, "command_tree_end_drag"},
- {wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK, 208, "command_tree_state_image_click"},
- {wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP, 208, "command_tree_item_gettooltip"},
- {wxEVT_COMMAND_TREE_ITEM_MENU, 208, "command_tree_item_menu"},
- {wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, 209, "command_notebook_page_changed"},
- {wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, 209, "command_notebook_page_changing"},
- {wxEVT_COMMAND_SPINCTRL_UPDATED, 215, "command_spinctrl_updated"},
- {wxEVT_SCROLL_LINEUP + wxEVT_USER_FIRST, 164, "spin_up"},
- {wxEVT_SCROLL_LINEDOWN + wxEVT_USER_FIRST, 164, "spin_down"},
- {wxEVT_SCROLL_THUMBTRACK + wxEVT_USER_FIRST, 164, "spin"},
- {wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED, 217, "command_splitter_sash_pos_changed"},
- {wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING, 217, "command_splitter_sash_pos_changing"},
- {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, 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"},
+ {wxEVT_COMMAND_BUTTON_CLICKED, 164, "command_button_clicked"},
+ {wxEVT_COMMAND_CHECKBOX_CLICKED, 164, "command_checkbox_clicked"},
+ {wxEVT_COMMAND_CHOICE_SELECTED, 164, "command_choice_selected"},
+ {wxEVT_COMMAND_LISTBOX_SELECTED, 164, "command_listbox_selected"},
+ {wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, 164, "command_listbox_doubleclicked"},
+ {wxEVT_COMMAND_TEXT_UPDATED, 164, "command_text_updated"},
+ {wxEVT_COMMAND_TEXT_ENTER, 164, "command_text_enter"},
+ {wxEVT_COMMAND_MENU_SELECTED, 164, "command_menu_selected"},
+ {wxEVT_COMMAND_SLIDER_UPDATED, 164, "command_slider_updated"},
+ {wxEVT_COMMAND_RADIOBOX_SELECTED, 164, "command_radiobox_selected"},
+ {wxEVT_COMMAND_RADIOBUTTON_SELECTED, 164, "command_radiobutton_selected"},
+ {wxEVT_COMMAND_SCROLLBAR_UPDATED, 164, "command_scrollbar_updated"},
+ {wxEVT_COMMAND_VLBOX_SELECTED, 164, "command_vlbox_selected"},
+ {wxEVT_COMMAND_COMBOBOX_SELECTED, 164, "command_combobox_selected"},
+ {wxEVT_COMMAND_TOOL_RCLICKED, 164, "command_tool_rclicked"},
+ {wxEVT_COMMAND_TOOL_ENTER, 164, "command_tool_enter"},
+ {wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, 164, "command_checklistbox_toggled"},
+ {wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, 164, "command_togglebutton_clicked"},
+ {wxEVT_COMMAND_LEFT_CLICK, 164, "command_left_click"},
+ {wxEVT_COMMAND_LEFT_DCLICK, 164, "command_left_dclick"},
+ {wxEVT_COMMAND_RIGHT_CLICK, 164, "command_right_click"},
+ {wxEVT_COMMAND_SET_FOCUS, 164, "command_set_focus"},
+ {wxEVT_COMMAND_KILL_FOCUS, 164, "command_kill_focus"},
+ {wxEVT_COMMAND_ENTER, 164, "command_enter"},
+ {wxEVT_SCROLL_TOP, 165, "scroll_top"},
+ {wxEVT_SCROLL_BOTTOM, 165, "scroll_bottom"},
+ {wxEVT_SCROLL_LINEUP, 165, "scroll_lineup"},
+ {wxEVT_SCROLL_LINEDOWN, 165, "scroll_linedown"},
+ {wxEVT_SCROLL_PAGEUP, 165, "scroll_pageup"},
+ {wxEVT_SCROLL_PAGEDOWN, 165, "scroll_pagedown"},
+ {wxEVT_SCROLL_THUMBTRACK, 165, "scroll_thumbtrack"},
+ {wxEVT_SCROLL_THUMBRELEASE, 165, "scroll_thumbrelease"},
+ {wxEVT_SCROLL_CHANGED, 165, "scroll_changed"},
+ {wxEVT_SCROLLWIN_TOP, 166, "scrollwin_top"},
+ {wxEVT_SCROLLWIN_BOTTOM, 166, "scrollwin_bottom"},
+ {wxEVT_SCROLLWIN_LINEUP, 166, "scrollwin_lineup"},
+ {wxEVT_SCROLLWIN_LINEDOWN, 166, "scrollwin_linedown"},
+ {wxEVT_SCROLLWIN_PAGEUP, 166, "scrollwin_pageup"},
+ {wxEVT_SCROLLWIN_PAGEDOWN, 166, "scrollwin_pagedown"},
+ {wxEVT_SCROLLWIN_THUMBTRACK, 166, "scrollwin_thumbtrack"},
+ {wxEVT_SCROLLWIN_THUMBRELEASE, 166, "scrollwin_thumbrelease"},
+ {wxEVT_LEFT_DOWN, 167, "left_down"},
+ {wxEVT_LEFT_UP, 167, "left_up"},
+ {wxEVT_MIDDLE_DOWN, 167, "middle_down"},
+ {wxEVT_MIDDLE_UP, 167, "middle_up"},
+ {wxEVT_RIGHT_DOWN, 167, "right_down"},
+ {wxEVT_RIGHT_UP, 167, "right_up"},
+ {wxEVT_MOTION, 167, "motion"},
+ {wxEVT_ENTER_WINDOW, 167, "enter_window"},
+ {wxEVT_LEAVE_WINDOW, 167, "leave_window"},
+ {wxEVT_LEFT_DCLICK, 167, "left_dclick"},
+ {wxEVT_MIDDLE_DCLICK, 167, "middle_dclick"},
+ {wxEVT_RIGHT_DCLICK, 167, "right_dclick"},
+ {wxEVT_MOUSEWHEEL, 167, "mousewheel"},
+ {wxEVT_NC_LEFT_DOWN, 167, "nc_left_down"},
+ {wxEVT_NC_LEFT_UP, 167, "nc_left_up"},
+ {wxEVT_NC_MIDDLE_DOWN, 167, "nc_middle_down"},
+ {wxEVT_NC_MIDDLE_UP, 167, "nc_middle_up"},
+ {wxEVT_NC_RIGHT_DOWN, 167, "nc_right_down"},
+ {wxEVT_NC_RIGHT_UP, 167, "nc_right_up"},
+ {wxEVT_NC_MOTION, 167, "nc_motion"},
+ {wxEVT_NC_ENTER_WINDOW, 167, "nc_enter_window"},
+ {wxEVT_NC_LEAVE_WINDOW, 167, "nc_leave_window"},
+ {wxEVT_NC_LEFT_DCLICK, 167, "nc_left_dclick"},
+ {wxEVT_NC_MIDDLE_DCLICK, 167, "nc_middle_dclick"},
+ {wxEVT_NC_RIGHT_DCLICK, 167, "nc_right_dclick"},
+ {wxEVT_SET_CURSOR, 168, "set_cursor"},
+ {wxEVT_CHAR, 169, "char"},
+ {wxEVT_CHAR_HOOK, 169, "char_hook"},
+ {wxEVT_KEY_DOWN, 169, "key_down"},
+ {wxEVT_KEY_UP, 169, "key_up"},
+ {wxEVT_SIZE, 170, "size"},
+ {wxEVT_MOVE, 171, "move"},
+ {wxEVT_PAINT, 172, "paint"},
+ {wxEVT_PAINT_ICON, 172, "paint_icon"},
+ {wxEVT_NC_PAINT, 173, "nc_paint"},
+ {wxEVT_ERASE_BACKGROUND, 174, "erase_background"},
+ {wxEVT_SET_FOCUS, 175, "set_focus"},
+ {wxEVT_KILL_FOCUS, 175, "kill_focus"},
+ {wxEVT_CHILD_FOCUS, 176, "child_focus"},
+ {wxEVT_MENU_OPEN, 177, "menu_open"},
+ {wxEVT_MENU_CLOSE, 177, "menu_close"},
+ {wxEVT_MENU_HIGHLIGHT, 177, "menu_highlight"},
+ {wxEVT_CLOSE_WINDOW, 178, "close_window"},
+ {wxEVT_END_SESSION, 178, "end_session"},
+ {wxEVT_QUERY_END_SESSION, 178, "query_end_session"},
+ {wxEVT_SHOW, 179, "show"},
+ {wxEVT_ICONIZE, 180, "iconize"},
+ {wxEVT_MAXIMIZE, 181, "maximize"},
+ {wxEVT_JOY_BUTTON_DOWN, 182, "joy_button_down"},
+ {wxEVT_JOY_BUTTON_UP, 182, "joy_button_up"},
+ {wxEVT_JOY_MOVE, 182, "joy_move"},
+ {wxEVT_JOY_ZMOVE, 182, "joy_zmove"},
+ {wxEVT_UPDATE_UI, 183, "update_ui"},
+ {wxEVT_SYS_COLOUR_CHANGED, 184, "sys_colour_changed"},
+ {wxEVT_MOUSE_CAPTURE_CHANGED, 185, "mouse_capture_changed"},
+ {wxEVT_DISPLAY_CHANGED, 186, "display_changed"},
+ {wxEVT_PALETTE_CHANGED, 187, "palette_changed"},
+ {wxEVT_QUERY_NEW_PALETTE, 188, "query_new_palette"},
+ {wxEVT_NAVIGATION_KEY, 189, "navigation_key"},
+ {wxEVT_CREATE, 190, "create"},
+ {wxEVT_DESTROY, 191, "destroy"},
+ {wxEVT_HELP, 192, "help"},
+ {wxEVT_DETAILED_HELP, 192, "detailed_help"},
+ {wxEVT_CONTEXT_MENU, 193, "context_menu"},
+ {wxEVT_IDLE, 194, "idle"},
+ {wxEVT_GRID_CELL_LEFT_CLICK, 195, "grid_cell_left_click"},
+ {wxEVT_GRID_CELL_RIGHT_CLICK, 195, "grid_cell_right_click"},
+ {wxEVT_GRID_CELL_LEFT_DCLICK, 195, "grid_cell_left_dclick"},
+ {wxEVT_GRID_CELL_RIGHT_DCLICK, 195, "grid_cell_right_dclick"},
+ {wxEVT_GRID_LABEL_LEFT_CLICK, 195, "grid_label_left_click"},
+ {wxEVT_GRID_LABEL_RIGHT_CLICK, 195, "grid_label_right_click"},
+ {wxEVT_GRID_LABEL_LEFT_DCLICK, 195, "grid_label_left_dclick"},
+ {wxEVT_GRID_LABEL_RIGHT_DCLICK, 195, "grid_label_right_dclick"},
+ {wxEVT_GRID_ROW_SIZE, 195, "grid_row_size"},
+ {wxEVT_GRID_COL_SIZE, 195, "grid_col_size"},
+ {wxEVT_GRID_RANGE_SELECT, 195, "grid_range_select"},
+ {wxEVT_GRID_CELL_CHANGE, 195, "grid_cell_change"},
+ {wxEVT_GRID_SELECT_CELL, 195, "grid_select_cell"},
+ {wxEVT_GRID_EDITOR_SHOWN, 195, "grid_editor_shown"},
+ {wxEVT_GRID_EDITOR_HIDDEN, 195, "grid_editor_hidden"},
+ {wxEVT_GRID_EDITOR_CREATED, 195, "grid_editor_created"},
+ {wxEVT_GRID_CELL_BEGIN_DRAG, 195, "grid_cell_begin_drag"},
+ {wxEVT_SASH_DRAGGED, 197, "sash_dragged"},
+ {wxEVT_COMMAND_LIST_BEGIN_DRAG, 198, "command_list_begin_drag"},
+ {wxEVT_COMMAND_LIST_BEGIN_RDRAG, 198, "command_list_begin_rdrag"},
+ {wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, 198, "command_list_begin_label_edit"},
+ {wxEVT_COMMAND_LIST_END_LABEL_EDIT, 198, "command_list_end_label_edit"},
+ {wxEVT_COMMAND_LIST_DELETE_ITEM, 198, "command_list_delete_item"},
+ {wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, 198, "command_list_delete_all_items"},
+ {wxEVT_COMMAND_LIST_KEY_DOWN, 198, "command_list_key_down"},
+ {wxEVT_COMMAND_LIST_INSERT_ITEM, 198, "command_list_insert_item"},
+ {wxEVT_COMMAND_LIST_COL_CLICK, 198, "command_list_col_click"},
+ {wxEVT_COMMAND_LIST_COL_RIGHT_CLICK, 198, "command_list_col_right_click"},
+ {wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, 198, "command_list_col_begin_drag"},
+ {wxEVT_COMMAND_LIST_COL_DRAGGING, 198, "command_list_col_dragging"},
+ {wxEVT_COMMAND_LIST_COL_END_DRAG, 198, "command_list_col_end_drag"},
+ {wxEVT_COMMAND_LIST_ITEM_SELECTED, 198, "command_list_item_selected"},
+ {wxEVT_COMMAND_LIST_ITEM_DESELECTED, 198, "command_list_item_deselected"},
+ {wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, 198, "command_list_item_right_click"},
+ {wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK, 198, "command_list_item_middle_click"},
+ {wxEVT_COMMAND_LIST_ITEM_ACTIVATED, 198, "command_list_item_activated"},
+ {wxEVT_COMMAND_LIST_ITEM_FOCUSED, 198, "command_list_item_focused"},
+ {wxEVT_COMMAND_LIST_CACHE_HINT, 198, "command_list_cache_hint"},
+ {wxEVT_DATE_CHANGED, 199, "date_changed"},
+ {wxEVT_CALENDAR_SEL_CHANGED, 200, "calendar_sel_changed"},
+ {wxEVT_CALENDAR_DAY_CHANGED, 200, "calendar_day_changed"},
+ {wxEVT_CALENDAR_MONTH_CHANGED, 200, "calendar_month_changed"},
+ {wxEVT_CALENDAR_YEAR_CHANGED, 200, "calendar_year_changed"},
+ {wxEVT_CALENDAR_DOUBLECLICKED, 200, "calendar_doubleclicked"},
+ {wxEVT_CALENDAR_WEEKDAY_CLICKED, 200, "calendar_weekday_clicked"},
+ {wxEVT_COMMAND_FILEPICKER_CHANGED, 201, "command_filepicker_changed"},
+ {wxEVT_COMMAND_DIRPICKER_CHANGED, 201, "command_dirpicker_changed"},
+ {wxEVT_COMMAND_COLOURPICKER_CHANGED, 202, "command_colourpicker_changed"},
+ {wxEVT_COMMAND_FONTPICKER_CHANGED, 203, "command_fontpicker_changed"},
+ {wxEVT_STC_CHANGE, 204, "stc_change"},
+ {wxEVT_STC_STYLENEEDED, 204, "stc_styleneeded"},
+ {wxEVT_STC_CHARADDED, 204, "stc_charadded"},
+ {wxEVT_STC_SAVEPOINTREACHED, 204, "stc_savepointreached"},
+ {wxEVT_STC_SAVEPOINTLEFT, 204, "stc_savepointleft"},
+ {wxEVT_STC_ROMODIFYATTEMPT, 204, "stc_romodifyattempt"},
+ {wxEVT_STC_KEY, 204, "stc_key"},
+ {wxEVT_STC_DOUBLECLICK, 204, "stc_doubleclick"},
+ {wxEVT_STC_UPDATEUI, 204, "stc_updateui"},
+ {wxEVT_STC_MODIFIED, 204, "stc_modified"},
+ {wxEVT_STC_MACRORECORD, 204, "stc_macrorecord"},
+ {wxEVT_STC_MARGINCLICK, 204, "stc_marginclick"},
+ {wxEVT_STC_NEEDSHOWN, 204, "stc_needshown"},
+ {wxEVT_STC_PAINTED, 204, "stc_painted"},
+ {wxEVT_STC_USERLISTSELECTION, 204, "stc_userlistselection"},
+ {wxEVT_STC_URIDROPPED, 204, "stc_uridropped"},
+ {wxEVT_STC_DWELLSTART, 204, "stc_dwellstart"},
+ {wxEVT_STC_DWELLEND, 204, "stc_dwellend"},
+ {wxEVT_STC_START_DRAG, 204, "stc_start_drag"},
+ {wxEVT_STC_DRAG_OVER, 204, "stc_drag_over"},
+ {wxEVT_STC_DO_DROP, 204, "stc_do_drop"},
+ {wxEVT_STC_ZOOM, 204, "stc_zoom"},
+ {wxEVT_STC_HOTSPOT_CLICK, 204, "stc_hotspot_click"},
+ {wxEVT_STC_HOTSPOT_DCLICK, 204, "stc_hotspot_dclick"},
+ {wxEVT_STC_CALLTIP_CLICK, 204, "stc_calltip_click"},
+ {wxEVT_STC_AUTOCOMP_SELECTION, 204, "stc_autocomp_selection"},
+ {wxEVT_COMMAND_TREE_BEGIN_DRAG, 209, "command_tree_begin_drag"},
+ {wxEVT_COMMAND_TREE_BEGIN_RDRAG, 209, "command_tree_begin_rdrag"},
+ {wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, 209, "command_tree_begin_label_edit"},
+ {wxEVT_COMMAND_TREE_END_LABEL_EDIT, 209, "command_tree_end_label_edit"},
+ {wxEVT_COMMAND_TREE_DELETE_ITEM, 209, "command_tree_delete_item"},
+ {wxEVT_COMMAND_TREE_GET_INFO, 209, "command_tree_get_info"},
+ {wxEVT_COMMAND_TREE_SET_INFO, 209, "command_tree_set_info"},
+ {wxEVT_COMMAND_TREE_ITEM_EXPANDED, 209, "command_tree_item_expanded"},
+ {wxEVT_COMMAND_TREE_ITEM_EXPANDING, 209, "command_tree_item_expanding"},
+ {wxEVT_COMMAND_TREE_ITEM_COLLAPSED, 209, "command_tree_item_collapsed"},
+ {wxEVT_COMMAND_TREE_ITEM_COLLAPSING, 209, "command_tree_item_collapsing"},
+ {wxEVT_COMMAND_TREE_SEL_CHANGED, 209, "command_tree_sel_changed"},
+ {wxEVT_COMMAND_TREE_SEL_CHANGING, 209, "command_tree_sel_changing"},
+ {wxEVT_COMMAND_TREE_KEY_DOWN, 209, "command_tree_key_down"},
+ {wxEVT_COMMAND_TREE_ITEM_ACTIVATED, 209, "command_tree_item_activated"},
+ {wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, 209, "command_tree_item_right_click"},
+ {wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK, 209, "command_tree_item_middle_click"},
+ {wxEVT_COMMAND_TREE_END_DRAG, 209, "command_tree_end_drag"},
+ {wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK, 209, "command_tree_state_image_click"},
+ {wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP, 209, "command_tree_item_gettooltip"},
+ {wxEVT_COMMAND_TREE_ITEM_MENU, 209, "command_tree_item_menu"},
+ {wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, 210, "command_notebook_page_changed"},
+ {wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, 210, "command_notebook_page_changing"},
+ {wxEVT_COMMAND_SPINCTRL_UPDATED, 216, "command_spinctrl_updated"},
+ {wxEVT_SCROLL_LINEUP + wxEVT_USER_FIRST, 165, "spin_up"},
+ {wxEVT_SCROLL_LINEDOWN + wxEVT_USER_FIRST, 165, "spin_down"},
+ {wxEVT_SCROLL_THUMBTRACK + wxEVT_USER_FIRST, 165, "spin"},
+ {wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED, 218, "command_splitter_sash_pos_changed"},
+ {wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING, 218, "command_splitter_sash_pos_changing"},
+ {wxEVT_COMMAND_SPLITTER_DOUBLECLICKED, 218, "command_splitter_doubleclicked"},
+ {wxEVT_COMMAND_SPLITTER_UNSPLIT, 218, "command_splitter_unsplit"},
+ {wxEVT_COMMAND_HTML_LINK_CLICKED, 220, "command_html_link_clicked"},
+ {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, 222, "command_auinotebook_page_close"},
+ {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, 222, "command_auinotebook_page_changed"},
+ {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, 222, "command_auinotebook_page_changing"},
+ {wxEVT_COMMAND_AUINOTEBOOK_BUTTON, 222, "command_auinotebook_button"},
+ {wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, 222, "command_auinotebook_begin_drag"},
+ {wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, 222, "command_auinotebook_end_drag"},
+ {wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, 222, "command_auinotebook_drag_motion"},
+ {wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, 222, "command_auinotebook_allow_dnd"},
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, 221, "command_auinotebook_tab_middle_down"},
+ {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, 222, "command_auinotebook_tab_middle_down"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, 221, "command_auinotebook_tab_middle_up"},
+ {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, 222, "command_auinotebook_tab_middle_up"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, 221, "command_auinotebook_tab_right_down"},
+ {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, 222, "command_auinotebook_tab_right_down"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, 221, "command_auinotebook_tab_right_up"},
+ {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, 222, "command_auinotebook_tab_right_up"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, 221, "command_auinotebook_page_closed"},
+ {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, 222, "command_auinotebook_page_closed"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, 221, "command_auinotebook_drag_done"},
+ {wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, 222, "command_auinotebook_drag_done"},
#endif
#if wxCHECK_VERSION(2,8,5)
- {wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, 221, "command_auinotebook_bg_dclick"},
+ {wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, 222, "command_auinotebook_bg_dclick"},
#endif
- {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"},
+ {wxEVT_AUI_PANE_BUTTON, 223, "aui_pane_button"},
+ {wxEVT_AUI_PANE_CLOSE, 223, "aui_pane_close"},
+ {wxEVT_AUI_PANE_MAXIMIZE, 223, "aui_pane_maximize"},
+ {wxEVT_AUI_PANE_RESTORE, 223, "aui_pane_restore"},
+ {wxEVT_AUI_RENDER, 223, "aui_render"},
+ {wxEVT_AUI_FIND_MANAGER, 223, "aui_find_manager"},
{-1, 0, }
};
for(int i=0; event_types[i].ev_type != -1; i++) {
@@ -353,7 +353,7 @@ bool sendevent(wxEvent *event, ErlDrvPort port)
rt.addRef(getRef((void *)(cb->obj), memenv), cb->class_name);
rt.addExt2Term(cb->user_data);
switch(Etype->cID) {
-case 163: {// wxCommandEvent
+case 164: {// wxCommandEvent
wxCommandEvent * ev = (wxCommandEvent *) event;
evClass = (char*)"wxCommandEvent";
rt.addAtom((char*)"wxCommand");
@@ -364,7 +364,7 @@ case 163: {// wxCommandEvent
rt.addTupleCount(5);
break;
}
-case 164: {// wxScrollEvent or wxSpinEvent
+case 165: {// wxScrollEvent or wxSpinEvent
if(event->IsKindOf(CLASSINFO(wxScrollEvent))) {
wxScrollEvent * ev = (wxScrollEvent *) event;
evClass = (char*)"wxScrollEvent";
@@ -384,14 +384,14 @@ case 164: {// wxScrollEvent or wxSpinEvent
}
break;
}
-case 165: {// wxScrollWinEvent
+case 166: {// wxScrollWinEvent
evClass = (char*)"wxScrollWinEvent";
rt.addAtom((char*)"wxScrollWin");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 166: {// wxMouseEvent
+case 167: {// wxMouseEvent
wxMouseEvent * ev = (wxMouseEvent *) event;
evClass = (char*)"wxMouseEvent";
rt.addAtom((char*)"wxMouse");
@@ -411,14 +411,14 @@ case 166: {// wxMouseEvent
rt.addTupleCount(14);
break;
}
-case 167: {// wxSetCursorEvent
+case 168: {// wxSetCursorEvent
evClass = (char*)"wxSetCursorEvent";
rt.addAtom((char*)"wxSetCursor");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 168: {// wxKeyEvent
+case 169: {// wxKeyEvent
wxKeyEvent * ev = (wxKeyEvent *) event;
evClass = (char*)"wxKeyEvent";
rt.addAtom((char*)"wxKey");
@@ -437,7 +437,7 @@ case 168: {// wxKeyEvent
rt.addTupleCount(13);
break;
}
-case 169: {// wxSizeEvent
+case 170: {// wxSizeEvent
wxSizeEvent * ev = (wxSizeEvent *) event;
evClass = (char*)"wxSizeEvent";
rt.addAtom((char*)"wxSize");
@@ -447,28 +447,28 @@ case 169: {// wxSizeEvent
rt.addTupleCount(4);
break;
}
-case 170: {// wxMoveEvent
+case 171: {// wxMoveEvent
evClass = (char*)"wxMoveEvent";
rt.addAtom((char*)"wxMove");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 171: {// wxPaintEvent
+case 172: {// wxPaintEvent
evClass = (char*)"wxPaintEvent";
rt.addAtom((char*)"wxPaint");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 172: {// wxNcPaintEvent
+case 173: {// wxNcPaintEvent
evClass = (char*)"wxNcPaintEvent";
rt.addAtom((char*)"wxNcPaint");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 173: {// wxEraseEvent
+case 174: {// wxEraseEvent
wxEraseEvent * ev = (wxEraseEvent *) event;
wxDC * GetDC = ev->GetDC();
evClass = (char*)"wxEraseEvent";
@@ -478,105 +478,105 @@ case 173: {// wxEraseEvent
rt.addTupleCount(3);
break;
}
-case 174: {// wxFocusEvent
+case 175: {// wxFocusEvent
evClass = (char*)"wxFocusEvent";
rt.addAtom((char*)"wxFocus");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 175: {// wxChildFocusEvent
+case 176: {// wxChildFocusEvent
evClass = (char*)"wxChildFocusEvent";
rt.addAtom((char*)"wxChildFocus");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 176: {// wxMenuEvent
+case 177: {// wxMenuEvent
evClass = (char*)"wxMenuEvent";
rt.addAtom((char*)"wxMenu");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 177: {// wxCloseEvent
+case 178: {// wxCloseEvent
evClass = (char*)"wxCloseEvent";
rt.addAtom((char*)"wxClose");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 178: {// wxShowEvent
+case 179: {// wxShowEvent
evClass = (char*)"wxShowEvent";
rt.addAtom((char*)"wxShow");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 179: {// wxIconizeEvent
+case 180: {// wxIconizeEvent
evClass = (char*)"wxIconizeEvent";
rt.addAtom((char*)"wxIconize");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 180: {// wxMaximizeEvent
+case 181: {// wxMaximizeEvent
evClass = (char*)"wxMaximizeEvent";
rt.addAtom((char*)"wxMaximize");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 181: {// wxJoystickEvent
+case 182: {// wxJoystickEvent
evClass = (char*)"wxJoystickEvent";
rt.addAtom((char*)"wxJoystick");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 182: {// wxUpdateUIEvent
+case 183: {// wxUpdateUIEvent
evClass = (char*)"wxUpdateUIEvent";
rt.addAtom((char*)"wxUpdateUI");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 183: {// wxSysColourChangedEvent
+case 184: {// wxSysColourChangedEvent
evClass = (char*)"wxSysColourChangedEvent";
rt.addAtom((char*)"wxSysColourChanged");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 184: {// wxMouseCaptureChangedEvent
+case 185: {// wxMouseCaptureChangedEvent
evClass = (char*)"wxMouseCaptureChangedEvent";
rt.addAtom((char*)"wxMouseCaptureChanged");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 185: {// wxDisplayChangedEvent
+case 186: {// wxDisplayChangedEvent
evClass = (char*)"wxDisplayChangedEvent";
rt.addAtom((char*)"wxDisplayChanged");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 186: {// wxPaletteChangedEvent
+case 187: {// wxPaletteChangedEvent
evClass = (char*)"wxPaletteChangedEvent";
rt.addAtom((char*)"wxPaletteChanged");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 187: {// wxQueryNewPaletteEvent
+case 188: {// wxQueryNewPaletteEvent
evClass = (char*)"wxQueryNewPaletteEvent";
rt.addAtom((char*)"wxQueryNewPalette");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 188: {// wxNavigationKeyEvent
+case 189: {// wxNavigationKeyEvent
wxNavigationKeyEvent * ev = (wxNavigationKeyEvent *) event;
evClass = (char*)"wxNavigationKeyEvent";
rt.addAtom((char*)"wxNavigationKey");
@@ -586,42 +586,42 @@ case 188: {// wxNavigationKeyEvent
rt.addTupleCount(4);
break;
}
-case 189: {// wxWindowCreateEvent
+case 190: {// wxWindowCreateEvent
evClass = (char*)"wxWindowCreateEvent";
rt.addAtom((char*)"wxWindowCreate");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 190: {// wxWindowDestroyEvent
+case 191: {// wxWindowDestroyEvent
evClass = (char*)"wxWindowDestroyEvent";
rt.addAtom((char*)"wxWindowDestroy");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 191: {// wxHelpEvent
+case 192: {// wxHelpEvent
evClass = (char*)"wxHelpEvent";
rt.addAtom((char*)"wxHelp");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 192: {// wxContextMenuEvent
+case 193: {// wxContextMenuEvent
evClass = (char*)"wxContextMenuEvent";
rt.addAtom((char*)"wxContextMenu");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 193: {// wxIdleEvent
+case 194: {// wxIdleEvent
evClass = (char*)"wxIdleEvent";
rt.addAtom((char*)"wxIdle");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 194: {// wxGridEvent
+case 195: {// wxGridEvent
wxGridEvent * ev = (wxGridEvent *) event;
evClass = (char*)"wxGridEvent";
rt.addAtom((char*)"wxGrid");
@@ -638,7 +638,7 @@ case 194: {// wxGridEvent
rt.addTupleCount(11);
break;
}
-case 196: {// wxSashEvent
+case 197: {// wxSashEvent
wxSashEvent * ev = (wxSashEvent *) event;
evClass = (char*)"wxSashEvent";
rt.addAtom((char*)"wxSash");
@@ -649,7 +649,7 @@ case 196: {// wxSashEvent
rt.addTupleCount(5);
break;
}
-case 197: {// wxListEvent
+case 198: {// wxListEvent
wxListEvent * ev = (wxListEvent *) event;
evClass = (char*)"wxListEvent";
rt.addAtom((char*)"wxList");
@@ -662,7 +662,7 @@ case 197: {// wxListEvent
rt.addTupleCount(7);
break;
}
-case 198: {// wxDateEvent
+case 199: {// wxDateEvent
wxDateEvent * ev = (wxDateEvent *) event;
evClass = (char*)"wxDateEvent";
rt.addAtom((char*)"wxDate");
@@ -671,14 +671,14 @@ case 198: {// wxDateEvent
rt.addTupleCount(3);
break;
}
-case 199: {// wxCalendarEvent
+case 200: {// wxCalendarEvent
evClass = (char*)"wxCalendarEvent";
rt.addAtom((char*)"wxCalendar");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 200: {// wxFileDirPickerEvent
+case 201: {// wxFileDirPickerEvent
wxFileDirPickerEvent * ev = (wxFileDirPickerEvent *) event;
evClass = (char*)"wxFileDirPickerEvent";
rt.addAtom((char*)"wxFileDirPicker");
@@ -687,7 +687,7 @@ case 200: {// wxFileDirPickerEvent
rt.addTupleCount(3);
break;
}
-case 201: {// wxColourPickerEvent
+case 202: {// wxColourPickerEvent
wxColourPickerEvent * ev = (wxColourPickerEvent *) event;
evClass = (char*)"wxColourPickerEvent";
rt.addAtom((char*)"wxColourPicker");
@@ -696,7 +696,7 @@ case 201: {// wxColourPickerEvent
rt.addTupleCount(3);
break;
}
-case 202: {// wxFontPickerEvent
+case 203: {// wxFontPickerEvent
wxFontPickerEvent * ev = (wxFontPickerEvent *) event;
wxFont * GetFont = new wxFont(ev->GetFont());
app->newPtr((void *) GetFont,3, memenv);
@@ -707,7 +707,7 @@ case 202: {// wxFontPickerEvent
rt.addTupleCount(3);
break;
}
-case 203: {// wxStyledTextEvent
+case 204: {// wxStyledTextEvent
wxStyledTextEvent * ev = (wxStyledTextEvent *) event;
evClass = (char*)"wxStyledTextEvent";
rt.addAtom((char*)"wxStyledText");
@@ -735,7 +735,7 @@ case 203: {// wxStyledTextEvent
rt.addTupleCount(22);
break;
}
-case 208: {// wxTreeEvent
+case 209: {// wxTreeEvent
wxTreeEvent * ev = (wxTreeEvent *) event;
evClass = (char*)"wxTreeEvent";
rt.addAtom((char*)"wxTree");
@@ -746,14 +746,14 @@ case 208: {// wxTreeEvent
rt.addTupleCount(5);
break;
}
-case 209: {// wxNotebookEvent
+case 210: {// wxNotebookEvent
evClass = (char*)"wxNotebookEvent";
rt.addAtom((char*)"wxNotebook");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 215: {// wxSpinEvent
+case 216: {// wxSpinEvent
wxSpinEvent * ev = (wxSpinEvent *) event;
evClass = (char*)"wxSpinEvent";
rt.addAtom((char*)"wxSpin");
@@ -762,14 +762,14 @@ case 215: {// wxSpinEvent
rt.addTupleCount(3);
break;
}
-case 217: {// wxSplitterEvent
+case 218: {// wxSplitterEvent
evClass = (char*)"wxSplitterEvent";
rt.addAtom((char*)"wxSplitter");
rt.addAtom(Etype->eName);
rt.addTupleCount(2);
break;
}
-case 219: {// wxHtmlLinkEvent
+case 220: {// wxHtmlLinkEvent
wxHtmlLinkEvent * ev = (wxHtmlLinkEvent *) event;
evClass = (char*)"wxHtmlLinkEvent";
rt.addAtom((char*)"wxHtmlLink");
@@ -778,7 +778,7 @@ case 219: {// wxHtmlLinkEvent
rt.addTupleCount(3);
break;
}
-case 221: {// wxAuiNotebookEvent
+case 222: {// wxAuiNotebookEvent
wxAuiNotebookEvent * ev = (wxAuiNotebookEvent *) event;
wxAuiNotebook * GetDragSource = ev->GetDragSource();
evClass = (char*)"wxAuiNotebookEvent";
@@ -790,7 +790,7 @@ case 221: {// wxAuiNotebookEvent
rt.addTupleCount(5);
break;
}
-case 222: {// wxAuiManagerEvent
+case 223: {// 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 479d7679a4..afef2990b4 100644
--- a/lib/wx/c_src/gen/wxe_funcs.cpp
+++ b/lib/wx/c_src/gen/wxe_funcs.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -4486,7 +4486,7 @@ case wxGridCellBoolEditor_IsTrueValue: { // wxGridCellBoolEditor::IsTrueValue
break;
}
case wxGridCellBoolEditor_UseStringValues: { // wxGridCellBoolEditor::UseStringValues
- wxString valueTrue= _T("1");
+ wxString valueTrue= wxT("1");
wxString valueFalse= wxEmptyString;
while( * (int*) bp) { switch (* (int*) bp) {
case 1: {bp += 4;
@@ -15143,12 +15143,14 @@ case wxListBox_SetFirstItem_1_1: { // wxListBox::SetFirstItem
This->SetFirstItem(s);
break;
}
+
case wxListCtrl_new_0: { // wxListCtrl::wxListCtrl
wxListCtrl * Result = new EwxListCtrl();
newPtr((void *) Result, 0, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxListCtrl");
break;
}
+
case wxListCtrl_new_2: { // wxListCtrl::wxListCtrl
wxWindowID winid=wxID_ANY;
wxPoint pos= wxDefaultPosition;
@@ -15156,6 +15158,8 @@ case wxListCtrl_new_2: { // wxListCtrl::wxListCtrl
long style=wxLC_ICON;
const wxValidator * validator= &wxDefaultValidator;
wxWindow *parent = (wxWindow *) getPtr(bp,memenv); bp += 4;
+ int onGetItemText = 0, onGetItemAttr = 0, onGetItemColumnImage = 0;
+
bp += 4; /* Align */
while( * (int*) bp) { switch (* (int*) bp) {
case 1: {bp += 4;
@@ -15179,8 +15183,21 @@ case wxListCtrl_new_2: { // wxListCtrl::wxListCtrl
case 5: {bp += 4;
validator = (wxValidator *) getPtr(bp,memenv); bp += 4;
} break;
+ case 6: {bp += 4;
+ onGetItemText = *(int *) bp; bp += 4;
+ } break;
+ case 7: {bp += 4;
+ onGetItemAttr = *(int *) bp; bp += 4;
+ } break;
+ case 8: {bp += 4;
+ onGetItemColumnImage = *(int *) bp; bp += 4;
+ } break;
}};
- wxListCtrl * Result = new EwxListCtrl(parent,winid,pos,size,style,*validator);
+ EwxListCtrl * Result = new EwxListCtrl(parent,winid,pos,size,style,*validator);
+ Result->onGetItemText = onGetItemText;
+ Result->onGetItemAttr = onGetItemAttr;
+ Result->onGetItemColumnImage = onGetItemColumnImage;
+ Result->port = Ecmd.port;
newPtr((void *) Result, 0, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxListCtrl");
break;
@@ -15213,14 +15230,18 @@ case wxListCtrl_ClearAll: { // wxListCtrl::ClearAll
This->ClearAll();
break;
}
+
case wxListCtrl_Create: { // wxListCtrl::Create
wxWindowID winid=wxID_ANY;
wxPoint pos= wxDefaultPosition;
wxSize size= wxDefaultSize;
long style=wxLC_ICON;
const wxValidator * validator= &wxDefaultValidator;
- wxListCtrl *This = (wxListCtrl *) getPtr(bp,memenv); bp += 4;
+ EwxListCtrl *This = (EwxListCtrl *) getPtr(bp,memenv); bp += 4;
wxWindow *parent = (wxWindow *) getPtr(bp,memenv); bp += 4;
+ int onGetItemText = 0, onGetItemAttr = 0, onGetItemColumnImage = 0;
+
+ bp += 4; /* Align */
while( * (int*) bp) { switch (* (int*) bp) {
case 1: {bp += 4;
winid = (wxWindowID)*(int *) bp; bp += 4;
@@ -15243,9 +15264,23 @@ case wxListCtrl_Create: { // wxListCtrl::Create
case 5: {bp += 4;
validator = (wxValidator *) getPtr(bp,memenv); bp += 4;
} break;
+ case 6: {bp += 4;
+ onGetItemText = *(int *) bp; bp += 4;
+ } break;
+ case 7: {bp += 4;
+ onGetItemAttr = *(int *) bp; bp += 4;
+ } break;
+ case 8: {bp += 4;
+ onGetItemColumnImage = *(int *) bp; bp += 4;
+ } break;
}};
if(!This) throw wxe_badarg(0);
bool Result = This->Create(parent,winid,pos,size,style,*validator);
+ This->onGetItemText = onGetItemText;
+ This->onGetItemAttr = onGetItemAttr;
+ This->onGetItemColumnImage = onGetItemColumnImage;
+ This->port = Ecmd.port;
+
rt.addBool(Result);
break;
}
@@ -16095,6 +16130,106 @@ case wxListItem_SetWidth: { // wxListItem::SetWidth
This->SetWidth((int) *width);
break;
}
+case wxListItemAttr_new_0: { // wxListItemAttr::wxListItemAttr
+ wxListItemAttr * Result = new wxListItemAttr();
+ newPtr((void *) Result, 101, memenv);
+ rt.addRef(getRef((void *)Result,memenv), "wxListItemAttr");
+ break;
+}
+case wxListItemAttr_new_3: { // wxListItemAttr::wxListItemAttr
+ int * colTextR = (int *) bp; bp += 4;
+ int * colTextG = (int *) bp; bp += 4;
+ int * colTextB = (int *) bp; bp += 4;
+ int * colTextA = (int *) bp; bp += 4;
+ wxColour colText = wxColour(*colTextR,*colTextG,*colTextB,*colTextA);
+ int * colBackR = (int *) bp; bp += 4;
+ int * colBackG = (int *) bp; bp += 4;
+ int * colBackB = (int *) bp; bp += 4;
+ int * colBackA = (int *) bp; bp += 4;
+ wxColour colBack = wxColour(*colBackR,*colBackG,*colBackB,*colBackA);
+ wxFont *font = (wxFont *) getPtr(bp,memenv); bp += 4;
+ wxListItemAttr * Result = new wxListItemAttr(colText,colBack,*font);
+ newPtr((void *) Result, 101, memenv);
+ rt.addRef(getRef((void *)Result,memenv), "wxListItemAttr");
+ break;
+}
+case wxListItemAttr_GetBackgroundColour: { // wxListItemAttr::GetBackgroundColour
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ const wxColour * Result = &This->GetBackgroundColour();
+ rt.add((*Result));
+ break;
+}
+case wxListItemAttr_GetFont: { // wxListItemAttr::GetFont
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ const wxFont * Result = &This->GetFont();
+ rt.addRef(getRef((void *)Result,memenv), "wxFont");
+ break;
+}
+case wxListItemAttr_GetTextColour: { // wxListItemAttr::GetTextColour
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ const wxColour * Result = &This->GetTextColour();
+ rt.add((*Result));
+ break;
+}
+case wxListItemAttr_HasBackgroundColour: { // wxListItemAttr::HasBackgroundColour
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ bool Result = This->HasBackgroundColour();
+ rt.addBool(Result);
+ break;
+}
+case wxListItemAttr_HasFont: { // wxListItemAttr::HasFont
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ bool Result = This->HasFont();
+ rt.addBool(Result);
+ break;
+}
+case wxListItemAttr_HasTextColour: { // wxListItemAttr::HasTextColour
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ bool Result = This->HasTextColour();
+ rt.addBool(Result);
+ break;
+}
+case wxListItemAttr_SetBackgroundColour: { // wxListItemAttr::SetBackgroundColour
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ int * colBackR = (int *) bp; bp += 4;
+ int * colBackG = (int *) bp; bp += 4;
+ int * colBackB = (int *) bp; bp += 4;
+ int * colBackA = (int *) bp; bp += 4;
+ wxColour colBack = wxColour(*colBackR,*colBackG,*colBackB,*colBackA);
+ if(!This) throw wxe_badarg(0);
+ This->SetBackgroundColour(colBack);
+ break;
+}
+case wxListItemAttr_SetFont: { // wxListItemAttr::SetFont
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ wxFont *font = (wxFont *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+ This->SetFont(*font);
+ break;
+}
+case wxListItemAttr_SetTextColour: { // wxListItemAttr::SetTextColour
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ int * colTextR = (int *) bp; bp += 4;
+ int * colTextG = (int *) bp; bp += 4;
+ int * colTextB = (int *) bp; bp += 4;
+ int * colTextA = (int *) bp; bp += 4;
+ wxColour colText = wxColour(*colTextR,*colTextG,*colTextB,*colTextA);
+ if(!This) throw wxe_badarg(0);
+ This->SetTextColour(colText);
+ break;
+}
+case wxListItemAttr_destroy: { // wxListItemAttr::destroy
+ wxListItemAttr *This = (wxListItemAttr *) getPtr(bp,memenv); bp += 4;
+ if(This) { ((WxeApp *) wxTheApp)->clearPtr((void *) This);
+ delete This;}
+ break;
+}
case wxImageList_new_0: { // wxImageList::wxImageList
wxImageList * Result = new EwxImageList();
newPtr((void *) Result, 1, memenv);
@@ -16263,7 +16398,7 @@ case wxImageList_Replace_3: { // wxImageList::Replace
}
case wxTextAttr_new_0: { // wxTextAttr::wxTextAttr
wxTextAttr * Result = new wxTextAttr();
- newPtr((void *) Result, 102, memenv);
+ newPtr((void *) Result, 103, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxTextAttr");
break;
}
@@ -16293,7 +16428,7 @@ alignment = *(wxTextAttrAlignment *) bp; bp += 4;;
} break;
}};
wxTextAttr * Result = new wxTextAttr(colText,colBack,*font,(wxTextAttrAlignment) alignment);
- newPtr((void *) Result, 102, memenv);
+ newPtr((void *) Result, 103, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxTextAttr");
break;
}
@@ -22711,7 +22846,7 @@ case wxPreviewFrame_new: { // wxPreviewFrame::wxPreviewFrame
wxString title= wxT("Print Preview");
wxPoint pos= wxDefaultPosition;
wxSize size= wxDefaultSize;
- long style=wxDEFAULT_FRAME_STYLE;
+ long style=wxDEFAULT_FRAME_STYLE|wxFRAME_FLOAT_ON_PARENT;
wxPrintPreview *preview = (wxPrintPreview *) getPtr(bp,memenv); bp += 4;
wxWindow *parent = (wxWindow *) getPtr(bp,memenv); bp += 4;
while( * (int*) bp) { switch (* (int*) bp) {
@@ -23742,14 +23877,14 @@ case wxAuiManager_Update: { // wxAuiManager::Update
#if wxUSE_AUI
case wxAuiPaneInfo_new_0: { // wxAuiPaneInfo::wxAuiPaneInfo
wxAuiPaneInfo * Result = new wxAuiPaneInfo();
- newPtr((void *) Result, 154, memenv);
+ newPtr((void *) Result, 155, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxAuiPaneInfo");
break;
}
case wxAuiPaneInfo_new_1: { // wxAuiPaneInfo::wxAuiPaneInfo
wxAuiPaneInfo *c = (wxAuiPaneInfo *) getPtr(bp,memenv); bp += 4;
wxAuiPaneInfo * Result = new wxAuiPaneInfo(*c);
- newPtr((void *) Result, 154, memenv);
+ newPtr((void *) Result, 155, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxAuiPaneInfo");
break;
}
@@ -30292,7 +30427,7 @@ case wxNotebookEvent_SetSelection: { // wxNotebookEvent::SetSelection
}
case wxFileDataObject_new: { // wxFileDataObject::wxFileDataObject
wxFileDataObject * Result = new wxFileDataObject();
- newPtr((void *) Result, 211, memenv);
+ newPtr((void *) Result, 212, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxFileDataObject");
break;
}
@@ -30328,7 +30463,7 @@ case wxTextDataObject_new: { // wxTextDataObject::wxTextDataObject
} break;
}};
wxTextDataObject * Result = new wxTextDataObject(text);
- newPtr((void *) Result, 212, memenv);
+ newPtr((void *) Result, 213, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxTextDataObject");
break;
}
@@ -30364,7 +30499,7 @@ case wxTextDataObject_destroy: { // wxTextDataObject::destroy
case wxBitmapDataObject_new_1_1: { // wxBitmapDataObject::wxBitmapDataObject
wxBitmap *bitmap = (wxBitmap *) getPtr(bp,memenv); bp += 4;
wxBitmapDataObject * Result = new wxBitmapDataObject(*bitmap);
- newPtr((void *) Result, 213, memenv);
+ newPtr((void *) Result, 214, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxBitmapDataObject");
break;
}
@@ -30376,7 +30511,7 @@ bitmap = (wxBitmap *) getPtr(bp,memenv); bp += 4;
} break;
}};
wxBitmapDataObject * Result = new wxBitmapDataObject(*bitmap);
- newPtr((void *) Result, 213, memenv);
+ newPtr((void *) Result, 214, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxBitmapDataObject");
break;
}
@@ -31159,7 +31294,7 @@ case wxAuiManagerEvent_CanVeto: { // wxAuiManagerEvent::CanVeto
}
case wxLogNull_new: { // wxLogNull::wxLogNull
wxLogNull * Result = new wxLogNull();
- newPtr((void *) Result, 223, memenv);
+ newPtr((void *) Result, 224, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxLogNull");
break;
}
@@ -31188,3 +31323,31 @@ case wxLogNull_destroy: { // wxLogNull::destroy
error.addTupleCount(3);
error.send();
}} /* The End */
+
+
+void WxeApp::delete_object(void *ptr, wxeRefData *refd) {
+ switch(refd->type) {
+ case 24: delete (wxGridCellBoolRenderer *) ptr; break;
+ case 25: delete (wxGridCellBoolEditor *) ptr; break;
+ case 26: delete (wxGridCellFloatRenderer *) ptr; break;
+ case 27: delete (wxGridCellFloatEditor *) ptr; break;
+ case 28: delete (wxGridCellStringRenderer *) ptr; break;
+ case 29: delete (wxGridCellTextEditor *) ptr; break;
+ case 30: delete (wxGridCellChoiceEditor *) ptr; break;
+ case 31: delete (wxGridCellNumberRenderer *) ptr; break;
+ case 32: delete (wxGridCellNumberEditor *) ptr; break;
+ case 61: delete (wxIconBundle *) ptr; break;
+ case 69: delete (wxAcceleratorEntry *) ptr; break;
+ case 70: /* delete (wxCaret *) ptr;These objects must be deleted by owner object */ break;
+ case 72: delete (wxSizerFlags *) ptr; break;
+ case 88: /* delete (wxCalendarDateAttr *) ptr;These objects must be deleted by owner object */ break;
+ case 101: delete (wxListItemAttr *) ptr; break;
+ case 103: delete (wxTextAttr *) ptr; break;
+ case 155: delete (wxAuiPaneInfo *) ptr; break;
+ case 212: /* delete (wxFileDataObject *) ptr;These objects must be deleted by owner object */ break;
+ case 213: /* delete (wxTextDataObject *) ptr;These objects must be deleted by owner object */ break;
+ case 214: /* delete (wxBitmapDataObject *) ptr;These objects must be deleted by owner object */ break;
+ case 224: delete (wxLogNull *) ptr; break;
+ default: delete (wxObject *) ptr;
+}}
+
diff --git a/lib/wx/c_src/gen/wxe_init.cpp b/lib/wx/c_src/gen/wxe_init.cpp
index bab3261be4..a75298392b 100644
--- a/lib/wx/c_src/gen/wxe_init.cpp
+++ b/lib/wx/c_src/gen/wxe_init.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/wx/c_src/gen/wxe_macros.h b/lib/wx/c_src/gen/wxe_macros.h
index 4fb76f960b..be0481564f 100644
--- a/lib/wx/c_src/gen/wxe_macros.h
+++ b/lib/wx/c_src/gen/wxe_macros.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -1648,1683 +1648,1695 @@
#define wxListItem_SetText 1754
#define wxListItem_SetTextColour 1755
#define wxListItem_SetWidth 1756
-#define wxImageList_new_0 1757
-#define wxImageList_new_3 1758
-#define wxImageList_Add_1 1759
-#define wxImageList_Add_2_0 1760
-#define wxImageList_Add_2_1 1761
-#define wxImageList_Create 1762
-#define wxImageList_Draw 1764
-#define wxImageList_GetBitmap 1765
-#define wxImageList_GetIcon 1766
-#define wxImageList_GetImageCount 1767
-#define wxImageList_GetSize 1768
-#define wxImageList_Remove 1769
-#define wxImageList_RemoveAll 1770
-#define wxImageList_Replace_2 1771
-#define wxImageList_Replace_3 1772
-#define wxImageList_destroy 1773
-#define wxTextAttr_new_0 1774
-#define wxTextAttr_new_2 1775
-#define wxTextAttr_GetAlignment 1776
-#define wxTextAttr_GetBackgroundColour 1777
-#define wxTextAttr_GetFont 1778
-#define wxTextAttr_GetLeftIndent 1779
-#define wxTextAttr_GetLeftSubIndent 1780
-#define wxTextAttr_GetRightIndent 1781
-#define wxTextAttr_GetTabs 1782
-#define wxTextAttr_GetTextColour 1783
-#define wxTextAttr_HasBackgroundColour 1784
-#define wxTextAttr_HasFont 1785
-#define wxTextAttr_HasTextColour 1786
-#define wxTextAttr_GetFlags 1787
-#define wxTextAttr_IsDefault 1788
-#define wxTextAttr_SetAlignment 1789
-#define wxTextAttr_SetBackgroundColour 1790
-#define wxTextAttr_SetFlags 1791
-#define wxTextAttr_SetFont 1792
-#define wxTextAttr_SetLeftIndent 1793
-#define wxTextAttr_SetRightIndent 1794
-#define wxTextAttr_SetTabs 1795
-#define wxTextAttr_SetTextColour 1796
-#define wxTextAttr_destroy 1797
-#define wxTextCtrl_new_3 1799
-#define wxTextCtrl_new_0 1800
-#define wxTextCtrl_destruct 1802
-#define wxTextCtrl_AppendText 1803
-#define wxTextCtrl_CanCopy 1804
-#define wxTextCtrl_CanCut 1805
-#define wxTextCtrl_CanPaste 1806
-#define wxTextCtrl_CanRedo 1807
-#define wxTextCtrl_CanUndo 1808
-#define wxTextCtrl_Clear 1809
-#define wxTextCtrl_Copy 1810
-#define wxTextCtrl_Create 1811
-#define wxTextCtrl_Cut 1812
-#define wxTextCtrl_DiscardEdits 1813
-#define wxTextCtrl_EmulateKeyPress 1814
-#define wxTextCtrl_GetDefaultStyle 1815
-#define wxTextCtrl_GetInsertionPoint 1816
-#define wxTextCtrl_GetLastPosition 1817
-#define wxTextCtrl_GetLineLength 1818
-#define wxTextCtrl_GetLineText 1819
-#define wxTextCtrl_GetNumberOfLines 1820
-#define wxTextCtrl_GetRange 1821
-#define wxTextCtrl_GetSelection 1822
-#define wxTextCtrl_GetStringSelection 1823
-#define wxTextCtrl_GetStyle 1824
-#define wxTextCtrl_GetValue 1825
-#define wxTextCtrl_IsEditable 1826
-#define wxTextCtrl_IsModified 1827
-#define wxTextCtrl_IsMultiLine 1828
-#define wxTextCtrl_IsSingleLine 1829
-#define wxTextCtrl_LoadFile 1830
-#define wxTextCtrl_MarkDirty 1831
-#define wxTextCtrl_Paste 1832
-#define wxTextCtrl_PositionToXY 1833
-#define wxTextCtrl_Redo 1834
-#define wxTextCtrl_Remove 1835
-#define wxTextCtrl_Replace 1836
-#define wxTextCtrl_SaveFile 1837
-#define wxTextCtrl_SetDefaultStyle 1838
-#define wxTextCtrl_SetEditable 1839
-#define wxTextCtrl_SetInsertionPoint 1840
-#define wxTextCtrl_SetInsertionPointEnd 1841
-#define wxTextCtrl_SetMaxLength 1843
-#define wxTextCtrl_SetSelection 1844
-#define wxTextCtrl_SetStyle 1845
-#define wxTextCtrl_SetValue 1846
-#define wxTextCtrl_ShowPosition 1847
-#define wxTextCtrl_Undo 1848
-#define wxTextCtrl_WriteText 1849
-#define wxTextCtrl_XYToPosition 1850
-#define wxNotebook_new_0 1853
-#define wxNotebook_new_3 1854
-#define wxNotebook_destruct 1855
-#define wxNotebook_AddPage 1856
-#define wxNotebook_AdvanceSelection 1857
-#define wxNotebook_AssignImageList 1858
-#define wxNotebook_Create 1859
-#define wxNotebook_DeleteAllPages 1860
-#define wxNotebook_DeletePage 1861
-#define wxNotebook_RemovePage 1862
-#define wxNotebook_GetCurrentPage 1863
-#define wxNotebook_GetImageList 1864
-#define wxNotebook_GetPage 1866
-#define wxNotebook_GetPageCount 1867
-#define wxNotebook_GetPageImage 1868
-#define wxNotebook_GetPageText 1869
-#define wxNotebook_GetRowCount 1870
-#define wxNotebook_GetSelection 1871
-#define wxNotebook_GetThemeBackgroundColour 1872
-#define wxNotebook_HitTest 1874
-#define wxNotebook_InsertPage 1876
-#define wxNotebook_SetImageList 1877
-#define wxNotebook_SetPadding 1878
-#define wxNotebook_SetPageSize 1879
-#define wxNotebook_SetPageImage 1880
-#define wxNotebook_SetPageText 1881
-#define wxNotebook_SetSelection 1882
-#define wxNotebook_ChangeSelection 1883
-#define wxChoicebook_new_0 1884
-#define wxChoicebook_new_3 1885
-#define wxChoicebook_AddPage 1886
-#define wxChoicebook_AdvanceSelection 1887
-#define wxChoicebook_AssignImageList 1888
-#define wxChoicebook_Create 1889
-#define wxChoicebook_DeleteAllPages 1890
-#define wxChoicebook_DeletePage 1891
-#define wxChoicebook_RemovePage 1892
-#define wxChoicebook_GetCurrentPage 1893
-#define wxChoicebook_GetImageList 1894
-#define wxChoicebook_GetPage 1896
-#define wxChoicebook_GetPageCount 1897
-#define wxChoicebook_GetPageImage 1898
-#define wxChoicebook_GetPageText 1899
-#define wxChoicebook_GetSelection 1900
-#define wxChoicebook_HitTest 1901
-#define wxChoicebook_InsertPage 1902
-#define wxChoicebook_SetImageList 1903
-#define wxChoicebook_SetPageSize 1904
-#define wxChoicebook_SetPageImage 1905
-#define wxChoicebook_SetPageText 1906
-#define wxChoicebook_SetSelection 1907
-#define wxChoicebook_ChangeSelection 1908
-#define wxChoicebook_destroy 1909
-#define wxToolbook_new_0 1910
-#define wxToolbook_new_3 1911
-#define wxToolbook_AddPage 1912
-#define wxToolbook_AdvanceSelection 1913
-#define wxToolbook_AssignImageList 1914
-#define wxToolbook_Create 1915
-#define wxToolbook_DeleteAllPages 1916
-#define wxToolbook_DeletePage 1917
-#define wxToolbook_RemovePage 1918
-#define wxToolbook_GetCurrentPage 1919
-#define wxToolbook_GetImageList 1920
-#define wxToolbook_GetPage 1922
-#define wxToolbook_GetPageCount 1923
-#define wxToolbook_GetPageImage 1924
-#define wxToolbook_GetPageText 1925
-#define wxToolbook_GetSelection 1926
-#define wxToolbook_HitTest 1928
-#define wxToolbook_InsertPage 1929
-#define wxToolbook_SetImageList 1930
-#define wxToolbook_SetPageSize 1931
-#define wxToolbook_SetPageImage 1932
-#define wxToolbook_SetPageText 1933
-#define wxToolbook_SetSelection 1934
-#define wxToolbook_ChangeSelection 1935
-#define wxToolbook_destroy 1936
-#define wxListbook_new_0 1937
-#define wxListbook_new_3 1938
-#define wxListbook_AddPage 1939
-#define wxListbook_AdvanceSelection 1940
-#define wxListbook_AssignImageList 1941
-#define wxListbook_Create 1942
-#define wxListbook_DeleteAllPages 1943
-#define wxListbook_DeletePage 1944
-#define wxListbook_RemovePage 1945
-#define wxListbook_GetCurrentPage 1946
-#define wxListbook_GetImageList 1947
-#define wxListbook_GetPage 1949
-#define wxListbook_GetPageCount 1950
-#define wxListbook_GetPageImage 1951
-#define wxListbook_GetPageText 1952
-#define wxListbook_GetSelection 1953
-#define wxListbook_HitTest 1955
-#define wxListbook_InsertPage 1956
-#define wxListbook_SetImageList 1957
-#define wxListbook_SetPageSize 1958
-#define wxListbook_SetPageImage 1959
-#define wxListbook_SetPageText 1960
-#define wxListbook_SetSelection 1961
-#define wxListbook_ChangeSelection 1962
-#define wxListbook_destroy 1963
-#define wxTreebook_new_0 1964
-#define wxTreebook_new_3 1965
-#define wxTreebook_AddPage 1966
-#define wxTreebook_AdvanceSelection 1967
-#define wxTreebook_AssignImageList 1968
-#define wxTreebook_Create 1969
-#define wxTreebook_DeleteAllPages 1970
-#define wxTreebook_DeletePage 1971
-#define wxTreebook_RemovePage 1972
-#define wxTreebook_GetCurrentPage 1973
-#define wxTreebook_GetImageList 1974
-#define wxTreebook_GetPage 1976
-#define wxTreebook_GetPageCount 1977
-#define wxTreebook_GetPageImage 1978
-#define wxTreebook_GetPageText 1979
-#define wxTreebook_GetSelection 1980
-#define wxTreebook_ExpandNode 1981
-#define wxTreebook_IsNodeExpanded 1982
-#define wxTreebook_HitTest 1984
-#define wxTreebook_InsertPage 1985
-#define wxTreebook_InsertSubPage 1986
-#define wxTreebook_SetImageList 1987
-#define wxTreebook_SetPageSize 1988
-#define wxTreebook_SetPageImage 1989
-#define wxTreebook_SetPageText 1990
-#define wxTreebook_SetSelection 1991
-#define wxTreebook_ChangeSelection 1992
-#define wxTreebook_destroy 1993
-#define wxTreeCtrl_new_2 1996
-#define wxTreeCtrl_new_0 1997
-#define wxTreeCtrl_destruct 1999
-#define wxTreeCtrl_AddRoot 2000
-#define wxTreeCtrl_AppendItem 2001
-#define wxTreeCtrl_AssignImageList 2002
-#define wxTreeCtrl_AssignStateImageList 2003
-#define wxTreeCtrl_Collapse 2004
-#define wxTreeCtrl_CollapseAndReset 2005
-#define wxTreeCtrl_Create 2006
-#define wxTreeCtrl_Delete 2007
-#define wxTreeCtrl_DeleteAllItems 2008
-#define wxTreeCtrl_DeleteChildren 2009
-#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
+#define wxListItemAttr_new_0 1757
+#define wxListItemAttr_new_3 1758
+#define wxListItemAttr_GetBackgroundColour 1759
+#define wxListItemAttr_GetFont 1760
+#define wxListItemAttr_GetTextColour 1761
+#define wxListItemAttr_HasBackgroundColour 1762
+#define wxListItemAttr_HasFont 1763
+#define wxListItemAttr_HasTextColour 1764
+#define wxListItemAttr_SetBackgroundColour 1765
+#define wxListItemAttr_SetFont 1766
+#define wxListItemAttr_SetTextColour 1767
+#define wxListItemAttr_destroy 1768
+#define wxImageList_new_0 1769
+#define wxImageList_new_3 1770
+#define wxImageList_Add_1 1771
+#define wxImageList_Add_2_0 1772
+#define wxImageList_Add_2_1 1773
+#define wxImageList_Create 1774
+#define wxImageList_Draw 1776
+#define wxImageList_GetBitmap 1777
+#define wxImageList_GetIcon 1778
+#define wxImageList_GetImageCount 1779
+#define wxImageList_GetSize 1780
+#define wxImageList_Remove 1781
+#define wxImageList_RemoveAll 1782
+#define wxImageList_Replace_2 1783
+#define wxImageList_Replace_3 1784
+#define wxImageList_destroy 1785
+#define wxTextAttr_new_0 1786
+#define wxTextAttr_new_2 1787
+#define wxTextAttr_GetAlignment 1788
+#define wxTextAttr_GetBackgroundColour 1789
+#define wxTextAttr_GetFont 1790
+#define wxTextAttr_GetLeftIndent 1791
+#define wxTextAttr_GetLeftSubIndent 1792
+#define wxTextAttr_GetRightIndent 1793
+#define wxTextAttr_GetTabs 1794
+#define wxTextAttr_GetTextColour 1795
+#define wxTextAttr_HasBackgroundColour 1796
+#define wxTextAttr_HasFont 1797
+#define wxTextAttr_HasTextColour 1798
+#define wxTextAttr_GetFlags 1799
+#define wxTextAttr_IsDefault 1800
+#define wxTextAttr_SetAlignment 1801
+#define wxTextAttr_SetBackgroundColour 1802
+#define wxTextAttr_SetFlags 1803
+#define wxTextAttr_SetFont 1804
+#define wxTextAttr_SetLeftIndent 1805
+#define wxTextAttr_SetRightIndent 1806
+#define wxTextAttr_SetTabs 1807
+#define wxTextAttr_SetTextColour 1808
+#define wxTextAttr_destroy 1809
+#define wxTextCtrl_new_3 1811
+#define wxTextCtrl_new_0 1812
+#define wxTextCtrl_destruct 1814
+#define wxTextCtrl_AppendText 1815
+#define wxTextCtrl_CanCopy 1816
+#define wxTextCtrl_CanCut 1817
+#define wxTextCtrl_CanPaste 1818
+#define wxTextCtrl_CanRedo 1819
+#define wxTextCtrl_CanUndo 1820
+#define wxTextCtrl_Clear 1821
+#define wxTextCtrl_Copy 1822
+#define wxTextCtrl_Create 1823
+#define wxTextCtrl_Cut 1824
+#define wxTextCtrl_DiscardEdits 1825
+#define wxTextCtrl_EmulateKeyPress 1826
+#define wxTextCtrl_GetDefaultStyle 1827
+#define wxTextCtrl_GetInsertionPoint 1828
+#define wxTextCtrl_GetLastPosition 1829
+#define wxTextCtrl_GetLineLength 1830
+#define wxTextCtrl_GetLineText 1831
+#define wxTextCtrl_GetNumberOfLines 1832
+#define wxTextCtrl_GetRange 1833
+#define wxTextCtrl_GetSelection 1834
+#define wxTextCtrl_GetStringSelection 1835
+#define wxTextCtrl_GetStyle 1836
+#define wxTextCtrl_GetValue 1837
+#define wxTextCtrl_IsEditable 1838
+#define wxTextCtrl_IsModified 1839
+#define wxTextCtrl_IsMultiLine 1840
+#define wxTextCtrl_IsSingleLine 1841
+#define wxTextCtrl_LoadFile 1842
+#define wxTextCtrl_MarkDirty 1843
+#define wxTextCtrl_Paste 1844
+#define wxTextCtrl_PositionToXY 1845
+#define wxTextCtrl_Redo 1846
+#define wxTextCtrl_Remove 1847
+#define wxTextCtrl_Replace 1848
+#define wxTextCtrl_SaveFile 1849
+#define wxTextCtrl_SetDefaultStyle 1850
+#define wxTextCtrl_SetEditable 1851
+#define wxTextCtrl_SetInsertionPoint 1852
+#define wxTextCtrl_SetInsertionPointEnd 1853
+#define wxTextCtrl_SetMaxLength 1855
+#define wxTextCtrl_SetSelection 1856
+#define wxTextCtrl_SetStyle 1857
+#define wxTextCtrl_SetValue 1858
+#define wxTextCtrl_ShowPosition 1859
+#define wxTextCtrl_Undo 1860
+#define wxTextCtrl_WriteText 1861
+#define wxTextCtrl_XYToPosition 1862
+#define wxNotebook_new_0 1865
+#define wxNotebook_new_3 1866
+#define wxNotebook_destruct 1867
+#define wxNotebook_AddPage 1868
+#define wxNotebook_AdvanceSelection 1869
+#define wxNotebook_AssignImageList 1870
+#define wxNotebook_Create 1871
+#define wxNotebook_DeleteAllPages 1872
+#define wxNotebook_DeletePage 1873
+#define wxNotebook_RemovePage 1874
+#define wxNotebook_GetCurrentPage 1875
+#define wxNotebook_GetImageList 1876
+#define wxNotebook_GetPage 1878
+#define wxNotebook_GetPageCount 1879
+#define wxNotebook_GetPageImage 1880
+#define wxNotebook_GetPageText 1881
+#define wxNotebook_GetRowCount 1882
+#define wxNotebook_GetSelection 1883
+#define wxNotebook_GetThemeBackgroundColour 1884
+#define wxNotebook_HitTest 1886
+#define wxNotebook_InsertPage 1888
+#define wxNotebook_SetImageList 1889
+#define wxNotebook_SetPadding 1890
+#define wxNotebook_SetPageSize 1891
+#define wxNotebook_SetPageImage 1892
+#define wxNotebook_SetPageText 1893
+#define wxNotebook_SetSelection 1894
+#define wxNotebook_ChangeSelection 1895
+#define wxChoicebook_new_0 1896
+#define wxChoicebook_new_3 1897
+#define wxChoicebook_AddPage 1898
+#define wxChoicebook_AdvanceSelection 1899
+#define wxChoicebook_AssignImageList 1900
+#define wxChoicebook_Create 1901
+#define wxChoicebook_DeleteAllPages 1902
+#define wxChoicebook_DeletePage 1903
+#define wxChoicebook_RemovePage 1904
+#define wxChoicebook_GetCurrentPage 1905
+#define wxChoicebook_GetImageList 1906
+#define wxChoicebook_GetPage 1908
+#define wxChoicebook_GetPageCount 1909
+#define wxChoicebook_GetPageImage 1910
+#define wxChoicebook_GetPageText 1911
+#define wxChoicebook_GetSelection 1912
+#define wxChoicebook_HitTest 1913
+#define wxChoicebook_InsertPage 1914
+#define wxChoicebook_SetImageList 1915
+#define wxChoicebook_SetPageSize 1916
+#define wxChoicebook_SetPageImage 1917
+#define wxChoicebook_SetPageText 1918
+#define wxChoicebook_SetSelection 1919
+#define wxChoicebook_ChangeSelection 1920
+#define wxChoicebook_destroy 1921
+#define wxToolbook_new_0 1922
+#define wxToolbook_new_3 1923
+#define wxToolbook_AddPage 1924
+#define wxToolbook_AdvanceSelection 1925
+#define wxToolbook_AssignImageList 1926
+#define wxToolbook_Create 1927
+#define wxToolbook_DeleteAllPages 1928
+#define wxToolbook_DeletePage 1929
+#define wxToolbook_RemovePage 1930
+#define wxToolbook_GetCurrentPage 1931
+#define wxToolbook_GetImageList 1932
+#define wxToolbook_GetPage 1934
+#define wxToolbook_GetPageCount 1935
+#define wxToolbook_GetPageImage 1936
+#define wxToolbook_GetPageText 1937
+#define wxToolbook_GetSelection 1938
+#define wxToolbook_HitTest 1940
+#define wxToolbook_InsertPage 1941
+#define wxToolbook_SetImageList 1942
+#define wxToolbook_SetPageSize 1943
+#define wxToolbook_SetPageImage 1944
+#define wxToolbook_SetPageText 1945
+#define wxToolbook_SetSelection 1946
+#define wxToolbook_ChangeSelection 1947
+#define wxToolbook_destroy 1948
+#define wxListbook_new_0 1949
+#define wxListbook_new_3 1950
+#define wxListbook_AddPage 1951
+#define wxListbook_AdvanceSelection 1952
+#define wxListbook_AssignImageList 1953
+#define wxListbook_Create 1954
+#define wxListbook_DeleteAllPages 1955
+#define wxListbook_DeletePage 1956
+#define wxListbook_RemovePage 1957
+#define wxListbook_GetCurrentPage 1958
+#define wxListbook_GetImageList 1959
+#define wxListbook_GetPage 1961
+#define wxListbook_GetPageCount 1962
+#define wxListbook_GetPageImage 1963
+#define wxListbook_GetPageText 1964
+#define wxListbook_GetSelection 1965
+#define wxListbook_HitTest 1967
+#define wxListbook_InsertPage 1968
+#define wxListbook_SetImageList 1969
+#define wxListbook_SetPageSize 1970
+#define wxListbook_SetPageImage 1971
+#define wxListbook_SetPageText 1972
+#define wxListbook_SetSelection 1973
+#define wxListbook_ChangeSelection 1974
+#define wxListbook_destroy 1975
+#define wxTreebook_new_0 1976
+#define wxTreebook_new_3 1977
+#define wxTreebook_AddPage 1978
+#define wxTreebook_AdvanceSelection 1979
+#define wxTreebook_AssignImageList 1980
+#define wxTreebook_Create 1981
+#define wxTreebook_DeleteAllPages 1982
+#define wxTreebook_DeletePage 1983
+#define wxTreebook_RemovePage 1984
+#define wxTreebook_GetCurrentPage 1985
+#define wxTreebook_GetImageList 1986
+#define wxTreebook_GetPage 1988
+#define wxTreebook_GetPageCount 1989
+#define wxTreebook_GetPageImage 1990
+#define wxTreebook_GetPageText 1991
+#define wxTreebook_GetSelection 1992
+#define wxTreebook_ExpandNode 1993
+#define wxTreebook_IsNodeExpanded 1994
+#define wxTreebook_HitTest 1996
+#define wxTreebook_InsertPage 1997
+#define wxTreebook_InsertSubPage 1998
+#define wxTreebook_SetImageList 1999
+#define wxTreebook_SetPageSize 2000
+#define wxTreebook_SetPageImage 2001
+#define wxTreebook_SetPageText 2002
+#define wxTreebook_SetSelection 2003
+#define wxTreebook_ChangeSelection 2004
+#define wxTreebook_destroy 2005
+#define wxTreeCtrl_new_2 2008
+#define wxTreeCtrl_new_0 2009
+#define wxTreeCtrl_destruct 2011
+#define wxTreeCtrl_AddRoot 2012
+#define wxTreeCtrl_AppendItem 2013
+#define wxTreeCtrl_AssignImageList 2014
+#define wxTreeCtrl_AssignStateImageList 2015
+#define wxTreeCtrl_Collapse 2016
+#define wxTreeCtrl_CollapseAndReset 2017
+#define wxTreeCtrl_Create 2018
+#define wxTreeCtrl_Delete 2019
+#define wxTreeCtrl_DeleteAllItems 2020
+#define wxTreeCtrl_DeleteChildren 2021
+#define wxTreeCtrl_EditLabel 2022
+#define wxTreeCtrl_EnsureVisible 2023
+#define wxTreeCtrl_Expand 2024
+#define wxTreeCtrl_GetBoundingRect 2025
+#define wxTreeCtrl_GetChildrenCount 2027
+#define wxTreeCtrl_GetCount 2028
+#define wxTreeCtrl_GetEditControl 2029
+#define wxTreeCtrl_GetFirstChild 2030
+#define wxTreeCtrl_GetNextChild 2031
+#define wxTreeCtrl_GetFirstVisibleItem 2032
+#define wxTreeCtrl_GetImageList 2033
+#define wxTreeCtrl_GetIndent 2034
+#define wxTreeCtrl_GetItemBackgroundColour 2035
+#define wxTreeCtrl_GetItemData 2036
+#define wxTreeCtrl_GetItemFont 2037
+#define wxTreeCtrl_GetItemImage_1 2038
+#define wxTreeCtrl_GetItemImage_2 2039
+#define wxTreeCtrl_GetItemText 2040
+#define wxTreeCtrl_GetItemTextColour 2041
+#define wxTreeCtrl_GetLastChild 2042
+#define wxTreeCtrl_GetNextSibling 2043
+#define wxTreeCtrl_GetNextVisible 2044
+#define wxTreeCtrl_GetItemParent 2045
+#define wxTreeCtrl_GetPrevSibling 2046
+#define wxTreeCtrl_GetPrevVisible 2047
+#define wxTreeCtrl_GetRootItem 2048
+#define wxTreeCtrl_GetSelection 2049
+#define wxTreeCtrl_GetSelections 2050
+#define wxTreeCtrl_GetStateImageList 2051
+#define wxTreeCtrl_HitTest 2052
+#define wxTreeCtrl_InsertItem 2054
+#define wxTreeCtrl_IsBold 2055
+#define wxTreeCtrl_IsExpanded 2056
+#define wxTreeCtrl_IsSelected 2057
+#define wxTreeCtrl_IsVisible 2058
+#define wxTreeCtrl_ItemHasChildren 2059
+#define wxTreeCtrl_PrependItem 2060
+#define wxTreeCtrl_ScrollTo 2061
+#define wxTreeCtrl_SelectItem_1 2062
+#define wxTreeCtrl_SelectItem_2 2063
+#define wxTreeCtrl_SetIndent 2064
+#define wxTreeCtrl_SetImageList 2065
+#define wxTreeCtrl_SetItemBackgroundColour 2066
+#define wxTreeCtrl_SetItemBold 2067
+#define wxTreeCtrl_SetItemData 2068
+#define wxTreeCtrl_SetItemDropHighlight 2069
+#define wxTreeCtrl_SetItemFont 2070
+#define wxTreeCtrl_SetItemHasChildren 2071
+#define wxTreeCtrl_SetItemImage_2 2072
+#define wxTreeCtrl_SetItemImage_3 2073
+#define wxTreeCtrl_SetItemText 2074
+#define wxTreeCtrl_SetItemTextColour 2075
+#define wxTreeCtrl_SetStateImageList 2076
+#define wxTreeCtrl_SetWindowStyle 2077
+#define wxTreeCtrl_SortChildren 2078
+#define wxTreeCtrl_Toggle 2079
+#define wxTreeCtrl_ToggleItemSelection 2080
+#define wxTreeCtrl_Unselect 2081
+#define wxTreeCtrl_UnselectAll 2082
+#define wxTreeCtrl_UnselectItem 2083
+#define wxScrollBar_new_0 2084
+#define wxScrollBar_new_3 2085
+#define wxScrollBar_destruct 2086
+#define wxScrollBar_Create 2087
+#define wxScrollBar_GetRange 2088
+#define wxScrollBar_GetPageSize 2089
+#define wxScrollBar_GetThumbPosition 2090
+#define wxScrollBar_GetThumbSize 2091
+#define wxScrollBar_SetThumbPosition 2092
+#define wxScrollBar_SetScrollbar 2093
+#define wxSpinButton_new_2 2095
+#define wxSpinButton_new_0 2096
+#define wxSpinButton_Create 2097
+#define wxSpinButton_GetMax 2098
+#define wxSpinButton_GetMin 2099
+#define wxSpinButton_GetValue 2100
+#define wxSpinButton_SetRange 2101
+#define wxSpinButton_SetValue 2102
+#define wxSpinButton_destroy 2103
+#define wxSpinCtrl_new_0 2104
+#define wxSpinCtrl_new_2 2105
+#define wxSpinCtrl_Create 2107
+#define wxSpinCtrl_SetValue_1_1 2110
+#define wxSpinCtrl_SetValue_1_0 2111
+#define wxSpinCtrl_GetValue 2113
+#define wxSpinCtrl_SetRange 2115
+#define wxSpinCtrl_SetSelection 2116
+#define wxSpinCtrl_GetMin 2118
+#define wxSpinCtrl_GetMax 2120
+#define wxSpinCtrl_destroy 2121
+#define wxStaticText_new_0 2122
+#define wxStaticText_new_4 2123
+#define wxStaticText_Create 2124
+#define wxStaticText_GetLabel 2125
+#define wxStaticText_SetLabel 2126
+#define wxStaticText_Wrap 2127
+#define wxStaticText_destroy 2128
+#define wxStaticBitmap_new_0 2129
+#define wxStaticBitmap_new_4 2130
+#define wxStaticBitmap_Create 2131
+#define wxStaticBitmap_GetBitmap 2132
+#define wxStaticBitmap_SetBitmap 2133
+#define wxStaticBitmap_destroy 2134
+#define wxRadioBox_new 2135
+#define wxRadioBox_destruct 2137
+#define wxRadioBox_Create 2138
+#define wxRadioBox_Enable_2 2139
+#define wxRadioBox_Enable_1 2140
+#define wxRadioBox_GetSelection 2141
+#define wxRadioBox_GetString 2142
+#define wxRadioBox_SetSelection 2143
+#define wxRadioBox_Show_2 2144
+#define wxRadioBox_Show_1 2145
+#define wxRadioBox_GetColumnCount 2146
+#define wxRadioBox_GetItemHelpText 2147
+#define wxRadioBox_GetItemToolTip 2148
+#define wxRadioBox_GetItemFromPoint 2150
+#define wxRadioBox_GetRowCount 2151
+#define wxRadioBox_IsItemEnabled 2152
+#define wxRadioBox_IsItemShown 2153
+#define wxRadioBox_SetItemHelpText 2154
+#define wxRadioBox_SetItemToolTip 2155
+#define wxRadioButton_new_0 2156
+#define wxRadioButton_new_4 2157
+#define wxRadioButton_Create 2158
+#define wxRadioButton_GetValue 2159
+#define wxRadioButton_SetValue 2160
+#define wxRadioButton_destroy 2161
+#define wxSlider_new_6 2163
+#define wxSlider_new_0 2164
+#define wxSlider_Create 2165
+#define wxSlider_GetLineSize 2166
+#define wxSlider_GetMax 2167
+#define wxSlider_GetMin 2168
+#define wxSlider_GetPageSize 2169
+#define wxSlider_GetThumbLength 2170
+#define wxSlider_GetValue 2171
+#define wxSlider_SetLineSize 2172
+#define wxSlider_SetPageSize 2173
+#define wxSlider_SetRange 2174
+#define wxSlider_SetThumbLength 2175
+#define wxSlider_SetValue 2176
+#define wxSlider_destroy 2177
+#define wxDialog_new_4 2179
+#define wxDialog_new_0 2180
+#define wxDialog_destruct 2182
+#define wxDialog_Create 2183
+#define wxDialog_CreateButtonSizer 2184
+#define wxDialog_CreateStdDialogButtonSizer 2185
+#define wxDialog_EndModal 2186
+#define wxDialog_GetAffirmativeId 2187
+#define wxDialog_GetReturnCode 2188
+#define wxDialog_IsModal 2189
+#define wxDialog_SetAffirmativeId 2190
+#define wxDialog_SetReturnCode 2191
+#define wxDialog_Show 2192
+#define wxDialog_ShowModal 2193
+#define wxColourDialog_new_0 2194
+#define wxColourDialog_new_2 2195
+#define wxColourDialog_destruct 2196
+#define wxColourDialog_Create 2197
+#define wxColourDialog_GetColourData 2198
+#define wxColourData_new_0 2199
+#define wxColourData_new_1 2200
+#define wxColourData_destruct 2201
+#define wxColourData_GetChooseFull 2202
+#define wxColourData_GetColour 2203
+#define wxColourData_GetCustomColour 2205
+#define wxColourData_SetChooseFull 2206
+#define wxColourData_SetColour 2207
+#define wxColourData_SetCustomColour 2208
+#define wxPalette_new_0 2209
+#define wxPalette_new_4 2210
+#define wxPalette_destruct 2212
+#define wxPalette_Create 2213
+#define wxPalette_GetColoursCount 2214
+#define wxPalette_GetPixel 2215
+#define wxPalette_GetRGB 2216
+#define wxPalette_IsOk 2217
+#define wxDirDialog_new 2221
+#define wxDirDialog_destruct 2222
+#define wxDirDialog_GetPath 2223
+#define wxDirDialog_GetMessage 2224
+#define wxDirDialog_SetMessage 2225
+#define wxDirDialog_SetPath 2226
+#define wxFileDialog_new 2230
+#define wxFileDialog_destruct 2231
+#define wxFileDialog_GetDirectory 2232
+#define wxFileDialog_GetFilename 2233
+#define wxFileDialog_GetFilenames 2234
+#define wxFileDialog_GetFilterIndex 2235
+#define wxFileDialog_GetMessage 2236
+#define wxFileDialog_GetPath 2237
+#define wxFileDialog_GetPaths 2238
+#define wxFileDialog_GetWildcard 2239
+#define wxFileDialog_SetDirectory 2240
+#define wxFileDialog_SetFilename 2241
+#define wxFileDialog_SetFilterIndex 2242
+#define wxFileDialog_SetMessage 2243
+#define wxFileDialog_SetPath 2244
+#define wxFileDialog_SetWildcard 2245
+#define wxPickerBase_SetInternalMargin 2246
+#define wxPickerBase_GetInternalMargin 2247
+#define wxPickerBase_SetTextCtrlProportion 2248
+#define wxPickerBase_SetPickerCtrlProportion 2249
+#define wxPickerBase_GetTextCtrlProportion 2250
+#define wxPickerBase_GetPickerCtrlProportion 2251
+#define wxPickerBase_HasTextCtrl 2252
+#define wxPickerBase_GetTextCtrl 2253
+#define wxPickerBase_IsTextCtrlGrowable 2254
+#define wxPickerBase_SetPickerCtrlGrowable 2255
+#define wxPickerBase_SetTextCtrlGrowable 2256
+#define wxPickerBase_IsPickerCtrlGrowable 2257
+#define wxFilePickerCtrl_new_0 2258
+#define wxFilePickerCtrl_new_3 2259
+#define wxFilePickerCtrl_Create 2260
+#define wxFilePickerCtrl_GetPath 2261
+#define wxFilePickerCtrl_SetPath 2262
+#define wxFilePickerCtrl_destroy 2263
+#define wxDirPickerCtrl_new_0 2264
+#define wxDirPickerCtrl_new_3 2265
+#define wxDirPickerCtrl_Create 2266
+#define wxDirPickerCtrl_GetPath 2267
+#define wxDirPickerCtrl_SetPath 2268
+#define wxDirPickerCtrl_destroy 2269
+#define wxColourPickerCtrl_new_0 2270
+#define wxColourPickerCtrl_new_3 2271
+#define wxColourPickerCtrl_Create 2272
+#define wxColourPickerCtrl_GetColour 2273
+#define wxColourPickerCtrl_SetColour_1_1 2274
+#define wxColourPickerCtrl_SetColour_1_0 2275
+#define wxColourPickerCtrl_destroy 2276
+#define wxDatePickerCtrl_new_0 2277
+#define wxDatePickerCtrl_new_3 2278
+#define wxDatePickerCtrl_GetRange 2279
+#define wxDatePickerCtrl_GetValue 2280
+#define wxDatePickerCtrl_SetRange 2281
+#define wxDatePickerCtrl_SetValue 2282
+#define wxDatePickerCtrl_destroy 2283
+#define wxFontPickerCtrl_new_0 2284
+#define wxFontPickerCtrl_new_3 2285
+#define wxFontPickerCtrl_Create 2286
+#define wxFontPickerCtrl_GetSelectedFont 2287
+#define wxFontPickerCtrl_SetSelectedFont 2288
+#define wxFontPickerCtrl_GetMaxPointSize 2289
+#define wxFontPickerCtrl_SetMaxPointSize 2290
+#define wxFontPickerCtrl_destroy 2291
+#define wxFindReplaceDialog_new_0 2294
+#define wxFindReplaceDialog_new_4 2295
+#define wxFindReplaceDialog_destruct 2296
+#define wxFindReplaceDialog_Create 2297
+#define wxFindReplaceDialog_GetData 2298
+#define wxFindReplaceData_new_0 2299
+#define wxFindReplaceData_new_1 2300
+#define wxFindReplaceData_GetFindString 2301
+#define wxFindReplaceData_GetReplaceString 2302
+#define wxFindReplaceData_GetFlags 2303
+#define wxFindReplaceData_SetFlags 2304
+#define wxFindReplaceData_SetFindString 2305
+#define wxFindReplaceData_SetReplaceString 2306
+#define wxFindReplaceData_destroy 2307
+#define wxMultiChoiceDialog_new_0 2308
+#define wxMultiChoiceDialog_new_5 2310
+#define wxMultiChoiceDialog_GetSelections 2311
+#define wxMultiChoiceDialog_SetSelections 2312
+#define wxMultiChoiceDialog_destroy 2313
+#define wxSingleChoiceDialog_new_0 2314
+#define wxSingleChoiceDialog_new_5 2316
+#define wxSingleChoiceDialog_GetSelection 2317
+#define wxSingleChoiceDialog_GetStringSelection 2318
+#define wxSingleChoiceDialog_SetSelection 2319
+#define wxSingleChoiceDialog_destroy 2320
+#define wxTextEntryDialog_new 2321
+#define wxTextEntryDialog_GetValue 2322
+#define wxTextEntryDialog_SetValue 2323
+#define wxTextEntryDialog_destroy 2324
+#define wxPasswordEntryDialog_new 2325
+#define wxPasswordEntryDialog_destroy 2326
+#define wxFontData_new_0 2327
+#define wxFontData_new_1 2328
+#define wxFontData_destruct 2329
+#define wxFontData_EnableEffects 2330
+#define wxFontData_GetAllowSymbols 2331
+#define wxFontData_GetColour 2332
+#define wxFontData_GetChosenFont 2333
+#define wxFontData_GetEnableEffects 2334
+#define wxFontData_GetInitialFont 2335
+#define wxFontData_GetShowHelp 2336
+#define wxFontData_SetAllowSymbols 2337
+#define wxFontData_SetChosenFont 2338
+#define wxFontData_SetColour 2339
+#define wxFontData_SetInitialFont 2340
+#define wxFontData_SetRange 2341
+#define wxFontData_SetShowHelp 2342
+#define wxFontDialog_new_0 2346
+#define wxFontDialog_new_2 2348
+#define wxFontDialog_Create 2350
+#define wxFontDialog_GetFontData 2351
+#define wxFontDialog_destroy 2353
+#define wxProgressDialog_new 2354
+#define wxProgressDialog_destruct 2355
+#define wxProgressDialog_Resume 2356
+#define wxProgressDialog_Update_2 2357
+#define wxProgressDialog_Update_0 2358
+#define wxMessageDialog_new 2359
+#define wxMessageDialog_destruct 2360
+#define wxPageSetupDialog_new 2361
+#define wxPageSetupDialog_destruct 2362
+#define wxPageSetupDialog_GetPageSetupData 2363
+#define wxPageSetupDialog_ShowModal 2364
+#define wxPageSetupDialogData_new_0 2365
+#define wxPageSetupDialogData_new_1_0 2366
+#define wxPageSetupDialogData_new_1_1 2367
+#define wxPageSetupDialogData_destruct 2368
+#define wxPageSetupDialogData_EnableHelp 2369
+#define wxPageSetupDialogData_EnableMargins 2370
+#define wxPageSetupDialogData_EnableOrientation 2371
+#define wxPageSetupDialogData_EnablePaper 2372
+#define wxPageSetupDialogData_EnablePrinter 2373
+#define wxPageSetupDialogData_GetDefaultMinMargins 2374
+#define wxPageSetupDialogData_GetEnableMargins 2375
+#define wxPageSetupDialogData_GetEnableOrientation 2376
+#define wxPageSetupDialogData_GetEnablePaper 2377
+#define wxPageSetupDialogData_GetEnablePrinter 2378
+#define wxPageSetupDialogData_GetEnableHelp 2379
+#define wxPageSetupDialogData_GetDefaultInfo 2380
+#define wxPageSetupDialogData_GetMarginTopLeft 2381
+#define wxPageSetupDialogData_GetMarginBottomRight 2382
+#define wxPageSetupDialogData_GetMinMarginTopLeft 2383
+#define wxPageSetupDialogData_GetMinMarginBottomRight 2384
+#define wxPageSetupDialogData_GetPaperId 2385
+#define wxPageSetupDialogData_GetPaperSize 2386
+#define wxPageSetupDialogData_GetPrintData 2388
+#define wxPageSetupDialogData_IsOk 2389
+#define wxPageSetupDialogData_SetDefaultInfo 2390
+#define wxPageSetupDialogData_SetDefaultMinMargins 2391
+#define wxPageSetupDialogData_SetMarginTopLeft 2392
+#define wxPageSetupDialogData_SetMarginBottomRight 2393
+#define wxPageSetupDialogData_SetMinMarginTopLeft 2394
+#define wxPageSetupDialogData_SetMinMarginBottomRight 2395
+#define wxPageSetupDialogData_SetPaperId 2396
+#define wxPageSetupDialogData_SetPaperSize_1_1 2397
+#define wxPageSetupDialogData_SetPaperSize_1_0 2398
+#define wxPageSetupDialogData_SetPrintData 2399
+#define wxPrintDialog_new_2_0 2400
+#define wxPrintDialog_new_2_1 2401
+#define wxPrintDialog_destruct 2402
+#define wxPrintDialog_GetPrintDialogData 2403
+#define wxPrintDialog_GetPrintDC 2404
+#define wxPrintDialogData_new_0 2405
+#define wxPrintDialogData_new_1_1 2406
+#define wxPrintDialogData_new_1_0 2407
+#define wxPrintDialogData_destruct 2408
+#define wxPrintDialogData_EnableHelp 2409
+#define wxPrintDialogData_EnablePageNumbers 2410
+#define wxPrintDialogData_EnablePrintToFile 2411
+#define wxPrintDialogData_EnableSelection 2412
+#define wxPrintDialogData_GetAllPages 2413
+#define wxPrintDialogData_GetCollate 2414
+#define wxPrintDialogData_GetFromPage 2415
+#define wxPrintDialogData_GetMaxPage 2416
+#define wxPrintDialogData_GetMinPage 2417
+#define wxPrintDialogData_GetNoCopies 2418
+#define wxPrintDialogData_GetPrintData 2419
+#define wxPrintDialogData_GetPrintToFile 2420
+#define wxPrintDialogData_GetSelection 2421
+#define wxPrintDialogData_GetToPage 2422
+#define wxPrintDialogData_IsOk 2423
+#define wxPrintDialogData_SetCollate 2424
+#define wxPrintDialogData_SetFromPage 2425
+#define wxPrintDialogData_SetMaxPage 2426
+#define wxPrintDialogData_SetMinPage 2427
+#define wxPrintDialogData_SetNoCopies 2428
+#define wxPrintDialogData_SetPrintData 2429
+#define wxPrintDialogData_SetPrintToFile 2430
+#define wxPrintDialogData_SetSelection 2431
+#define wxPrintDialogData_SetToPage 2432
+#define wxPrintData_new_0 2433
+#define wxPrintData_new_1 2434
+#define wxPrintData_destruct 2435
+#define wxPrintData_GetCollate 2436
+#define wxPrintData_GetBin 2437
+#define wxPrintData_GetColour 2438
+#define wxPrintData_GetDuplex 2439
+#define wxPrintData_GetNoCopies 2440
+#define wxPrintData_GetOrientation 2441
+#define wxPrintData_GetPaperId 2442
+#define wxPrintData_GetPrinterName 2443
+#define wxPrintData_GetQuality 2444
+#define wxPrintData_IsOk 2445
+#define wxPrintData_SetBin 2446
+#define wxPrintData_SetCollate 2447
+#define wxPrintData_SetColour 2448
+#define wxPrintData_SetDuplex 2449
+#define wxPrintData_SetNoCopies 2450
+#define wxPrintData_SetOrientation 2451
+#define wxPrintData_SetPaperId 2452
+#define wxPrintData_SetPrinterName 2453
+#define wxPrintData_SetQuality 2454
+#define wxPrintPreview_new_2 2457
+#define wxPrintPreview_new_3 2458
+#define wxPrintPreview_destruct 2460
+#define wxPrintPreview_GetCanvas 2461
+#define wxPrintPreview_GetCurrentPage 2462
+#define wxPrintPreview_GetFrame 2463
+#define wxPrintPreview_GetMaxPage 2464
+#define wxPrintPreview_GetMinPage 2465
+#define wxPrintPreview_GetPrintout 2466
+#define wxPrintPreview_GetPrintoutForPrinting 2467
+#define wxPrintPreview_IsOk 2468
+#define wxPrintPreview_PaintPage 2469
+#define wxPrintPreview_Print 2470
+#define wxPrintPreview_RenderPage 2471
+#define wxPrintPreview_SetCanvas 2472
+#define wxPrintPreview_SetCurrentPage 2473
+#define wxPrintPreview_SetFrame 2474
+#define wxPrintPreview_SetPrintout 2475
+#define wxPrintPreview_SetZoom 2476
+#define wxPreviewFrame_new 2477
+#define wxPreviewFrame_destruct 2478
+#define wxPreviewFrame_CreateControlBar 2479
+#define wxPreviewFrame_CreateCanvas 2480
+#define wxPreviewFrame_Initialize 2481
+#define wxPreviewFrame_OnCloseWindow 2482
+#define wxPreviewControlBar_new 2483
+#define wxPreviewControlBar_destruct 2484
+#define wxPreviewControlBar_CreateButtons 2485
+#define wxPreviewControlBar_GetPrintPreview 2486
+#define wxPreviewControlBar_GetZoomControl 2487
+#define wxPreviewControlBar_SetZoomControl 2488
+#define wxPrinter_new 2490
+#define wxPrinter_CreateAbortWindow 2491
+#define wxPrinter_GetAbort 2492
+#define wxPrinter_GetLastError 2493
+#define wxPrinter_GetPrintDialogData 2494
+#define wxPrinter_Print 2495
+#define wxPrinter_PrintDialog 2496
+#define wxPrinter_ReportError 2497
+#define wxPrinter_Setup 2498
+#define wxPrinter_destroy 2499
+#define wxXmlResource_new_1 2500
+#define wxXmlResource_new_2 2501
+#define wxXmlResource_destruct 2502
+#define wxXmlResource_AttachUnknownControl 2503
+#define wxXmlResource_ClearHandlers 2504
+#define wxXmlResource_CompareVersion 2505
+#define wxXmlResource_Get 2506
+#define wxXmlResource_GetFlags 2507
+#define wxXmlResource_GetVersion 2508
+#define wxXmlResource_GetXRCID 2509
+#define wxXmlResource_InitAllHandlers 2510
+#define wxXmlResource_Load 2511
+#define wxXmlResource_LoadBitmap 2512
+#define wxXmlResource_LoadDialog_2 2513
+#define wxXmlResource_LoadDialog_3 2514
+#define wxXmlResource_LoadFrame_2 2515
+#define wxXmlResource_LoadFrame_3 2516
+#define wxXmlResource_LoadIcon 2517
+#define wxXmlResource_LoadMenu 2518
+#define wxXmlResource_LoadMenuBar_2 2519
+#define wxXmlResource_LoadMenuBar_1 2520
+#define wxXmlResource_LoadPanel_2 2521
+#define wxXmlResource_LoadPanel_3 2522
+#define wxXmlResource_LoadToolBar 2523
+#define wxXmlResource_Set 2524
+#define wxXmlResource_SetFlags 2525
+#define wxXmlResource_Unload 2526
+#define wxXmlResource_xrcctrl 2527
+#define wxHtmlEasyPrinting_new 2528
+#define wxHtmlEasyPrinting_destruct 2529
+#define wxHtmlEasyPrinting_GetPrintData 2530
+#define wxHtmlEasyPrinting_GetPageSetupData 2531
+#define wxHtmlEasyPrinting_PreviewFile 2532
+#define wxHtmlEasyPrinting_PreviewText 2533
+#define wxHtmlEasyPrinting_PrintFile 2534
+#define wxHtmlEasyPrinting_PrintText 2535
+#define wxHtmlEasyPrinting_PageSetup 2536
+#define wxHtmlEasyPrinting_SetFonts 2537
+#define wxHtmlEasyPrinting_SetHeader 2538
+#define wxHtmlEasyPrinting_SetFooter 2539
+#define wxGLCanvas_new_2 2541
+#define wxGLCanvas_new_3_1 2542
+#define wxGLCanvas_new_3_0 2543
+#define wxGLCanvas_GetContext 2544
+#define wxGLCanvas_SetCurrent 2546
+#define wxGLCanvas_SwapBuffers 2547
+#define wxGLCanvas_destroy 2548
+#define wxAuiManager_new 2549
+#define wxAuiManager_destruct 2550
+#define wxAuiManager_AddPane_2_1 2551
+#define wxAuiManager_AddPane_3 2552
+#define wxAuiManager_AddPane_2_0 2553
+#define wxAuiManager_DetachPane 2554
+#define wxAuiManager_GetAllPanes 2555
+#define wxAuiManager_GetArtProvider 2556
+#define wxAuiManager_GetDockSizeConstraint 2557
+#define wxAuiManager_GetFlags 2558
+#define wxAuiManager_GetManagedWindow 2559
+#define wxAuiManager_GetManager 2560
+#define wxAuiManager_GetPane_1_1 2561
+#define wxAuiManager_GetPane_1_0 2562
+#define wxAuiManager_HideHint 2563
+#define wxAuiManager_InsertPane 2564
+#define wxAuiManager_LoadPaneInfo 2565
+#define wxAuiManager_LoadPerspective 2566
+#define wxAuiManager_SavePaneInfo 2567
+#define wxAuiManager_SavePerspective 2568
+#define wxAuiManager_SetArtProvider 2569
+#define wxAuiManager_SetDockSizeConstraint 2570
+#define wxAuiManager_SetFlags 2571
+#define wxAuiManager_SetManagedWindow 2572
+#define wxAuiManager_ShowHint 2573
+#define wxAuiManager_UnInit 2574
+#define wxAuiManager_Update 2575
+#define wxAuiPaneInfo_new_0 2576
+#define wxAuiPaneInfo_new_1 2577
+#define wxAuiPaneInfo_destruct 2578
+#define wxAuiPaneInfo_BestSize_1 2579
+#define wxAuiPaneInfo_BestSize_2 2580
+#define wxAuiPaneInfo_Bottom 2581
+#define wxAuiPaneInfo_BottomDockable 2582
+#define wxAuiPaneInfo_Caption 2583
+#define wxAuiPaneInfo_CaptionVisible 2584
+#define wxAuiPaneInfo_Centre 2585
+#define wxAuiPaneInfo_CentrePane 2586
+#define wxAuiPaneInfo_CloseButton 2587
+#define wxAuiPaneInfo_DefaultPane 2588
+#define wxAuiPaneInfo_DestroyOnClose 2589
+#define wxAuiPaneInfo_Direction 2590
+#define wxAuiPaneInfo_Dock 2591
+#define wxAuiPaneInfo_Dockable 2592
+#define wxAuiPaneInfo_Fixed 2593
+#define wxAuiPaneInfo_Float 2594
+#define wxAuiPaneInfo_Floatable 2595
+#define wxAuiPaneInfo_FloatingPosition_1 2596
+#define wxAuiPaneInfo_FloatingPosition_2 2597
+#define wxAuiPaneInfo_FloatingSize_1 2598
+#define wxAuiPaneInfo_FloatingSize_2 2599
+#define wxAuiPaneInfo_Gripper 2600
+#define wxAuiPaneInfo_GripperTop 2601
+#define wxAuiPaneInfo_HasBorder 2602
+#define wxAuiPaneInfo_HasCaption 2603
+#define wxAuiPaneInfo_HasCloseButton 2604
+#define wxAuiPaneInfo_HasFlag 2605
+#define wxAuiPaneInfo_HasGripper 2606
+#define wxAuiPaneInfo_HasGripperTop 2607
+#define wxAuiPaneInfo_HasMaximizeButton 2608
+#define wxAuiPaneInfo_HasMinimizeButton 2609
+#define wxAuiPaneInfo_HasPinButton 2610
+#define wxAuiPaneInfo_Hide 2611
+#define wxAuiPaneInfo_IsBottomDockable 2612
+#define wxAuiPaneInfo_IsDocked 2613
+#define wxAuiPaneInfo_IsFixed 2614
+#define wxAuiPaneInfo_IsFloatable 2615
+#define wxAuiPaneInfo_IsFloating 2616
+#define wxAuiPaneInfo_IsLeftDockable 2617
+#define wxAuiPaneInfo_IsMovable 2618
+#define wxAuiPaneInfo_IsOk 2619
+#define wxAuiPaneInfo_IsResizable 2620
+#define wxAuiPaneInfo_IsRightDockable 2621
+#define wxAuiPaneInfo_IsShown 2622
+#define wxAuiPaneInfo_IsToolbar 2623
+#define wxAuiPaneInfo_IsTopDockable 2624
+#define wxAuiPaneInfo_Layer 2625
+#define wxAuiPaneInfo_Left 2626
+#define wxAuiPaneInfo_LeftDockable 2627
+#define wxAuiPaneInfo_MaxSize_1 2628
+#define wxAuiPaneInfo_MaxSize_2 2629
+#define wxAuiPaneInfo_MaximizeButton 2630
+#define wxAuiPaneInfo_MinSize_1 2631
+#define wxAuiPaneInfo_MinSize_2 2632
+#define wxAuiPaneInfo_MinimizeButton 2633
+#define wxAuiPaneInfo_Movable 2634
+#define wxAuiPaneInfo_Name 2635
+#define wxAuiPaneInfo_PaneBorder 2636
+#define wxAuiPaneInfo_PinButton 2637
+#define wxAuiPaneInfo_Position 2638
+#define wxAuiPaneInfo_Resizable 2639
+#define wxAuiPaneInfo_Right 2640
+#define wxAuiPaneInfo_RightDockable 2641
+#define wxAuiPaneInfo_Row 2642
+#define wxAuiPaneInfo_SafeSet 2643
+#define wxAuiPaneInfo_SetFlag 2644
+#define wxAuiPaneInfo_Show 2645
+#define wxAuiPaneInfo_ToolbarPane 2646
+#define wxAuiPaneInfo_Top 2647
+#define wxAuiPaneInfo_TopDockable 2648
+#define wxAuiPaneInfo_Window 2649
+#define wxAuiNotebook_new_0 2650
+#define wxAuiNotebook_new_2 2651
+#define wxAuiNotebook_AddPage 2652
+#define wxAuiNotebook_Create 2653
+#define wxAuiNotebook_DeletePage 2654
+#define wxAuiNotebook_GetArtProvider 2655
+#define wxAuiNotebook_GetPage 2656
+#define wxAuiNotebook_GetPageBitmap 2657
+#define wxAuiNotebook_GetPageCount 2658
+#define wxAuiNotebook_GetPageIndex 2659
+#define wxAuiNotebook_GetPageText 2660
+#define wxAuiNotebook_GetSelection 2661
+#define wxAuiNotebook_InsertPage 2662
+#define wxAuiNotebook_RemovePage 2663
+#define wxAuiNotebook_SetArtProvider 2664
+#define wxAuiNotebook_SetFont 2665
+#define wxAuiNotebook_SetPageBitmap 2666
+#define wxAuiNotebook_SetPageText 2667
+#define wxAuiNotebook_SetSelection 2668
+#define wxAuiNotebook_SetTabCtrlHeight 2669
+#define wxAuiNotebook_SetUniformBitmapSize 2670
+#define wxAuiNotebook_destroy 2671
+#define wxMDIParentFrame_new_0 2672
+#define wxMDIParentFrame_new_4 2673
+#define wxMDIParentFrame_destruct 2674
+#define wxMDIParentFrame_ActivateNext 2675
+#define wxMDIParentFrame_ActivatePrevious 2676
+#define wxMDIParentFrame_ArrangeIcons 2677
+#define wxMDIParentFrame_Cascade 2678
+#define wxMDIParentFrame_Create 2679
+#define wxMDIParentFrame_GetActiveChild 2680
+#define wxMDIParentFrame_GetClientWindow 2681
+#define wxMDIParentFrame_Tile 2682
+#define wxMDIChildFrame_new_0 2683
+#define wxMDIChildFrame_new_4 2684
+#define wxMDIChildFrame_destruct 2685
+#define wxMDIChildFrame_Activate 2686
+#define wxMDIChildFrame_Create 2687
+#define wxMDIChildFrame_Maximize 2688
+#define wxMDIChildFrame_Restore 2689
+#define wxMDIClientWindow_new_0 2690
+#define wxMDIClientWindow_new_2 2691
+#define wxMDIClientWindow_destruct 2692
+#define wxMDIClientWindow_CreateClient 2693
+#define wxLayoutAlgorithm_new 2694
+#define wxLayoutAlgorithm_LayoutFrame 2695
+#define wxLayoutAlgorithm_LayoutMDIFrame 2696
+#define wxLayoutAlgorithm_LayoutWindow 2697
+#define wxLayoutAlgorithm_destroy 2698
+#define wxEvent_GetId 2699
+#define wxEvent_GetSkipped 2700
+#define wxEvent_GetTimestamp 2701
+#define wxEvent_IsCommandEvent 2702
+#define wxEvent_ResumePropagation 2703
+#define wxEvent_ShouldPropagate 2704
+#define wxEvent_Skip 2705
+#define wxEvent_StopPropagation 2706
+#define wxCommandEvent_getClientData 2707
+#define wxCommandEvent_GetExtraLong 2708
+#define wxCommandEvent_GetInt 2709
+#define wxCommandEvent_GetSelection 2710
+#define wxCommandEvent_GetString 2711
+#define wxCommandEvent_IsChecked 2712
+#define wxCommandEvent_IsSelection 2713
+#define wxCommandEvent_SetInt 2714
+#define wxCommandEvent_SetString 2715
+#define wxScrollEvent_GetOrientation 2716
+#define wxScrollEvent_GetPosition 2717
+#define wxScrollWinEvent_GetOrientation 2718
+#define wxScrollWinEvent_GetPosition 2719
+#define wxMouseEvent_AltDown 2720
+#define wxMouseEvent_Button 2721
+#define wxMouseEvent_ButtonDClick 2722
+#define wxMouseEvent_ButtonDown 2723
+#define wxMouseEvent_ButtonUp 2724
+#define wxMouseEvent_CmdDown 2725
+#define wxMouseEvent_ControlDown 2726
+#define wxMouseEvent_Dragging 2727
+#define wxMouseEvent_Entering 2728
+#define wxMouseEvent_GetButton 2729
+#define wxMouseEvent_GetPosition 2732
+#define wxMouseEvent_GetLogicalPosition 2733
+#define wxMouseEvent_GetLinesPerAction 2734
+#define wxMouseEvent_GetWheelRotation 2735
+#define wxMouseEvent_GetWheelDelta 2736
+#define wxMouseEvent_GetX 2737
+#define wxMouseEvent_GetY 2738
+#define wxMouseEvent_IsButton 2739
+#define wxMouseEvent_IsPageScroll 2740
+#define wxMouseEvent_Leaving 2741
+#define wxMouseEvent_LeftDClick 2742
+#define wxMouseEvent_LeftDown 2743
+#define wxMouseEvent_LeftIsDown 2744
+#define wxMouseEvent_LeftUp 2745
+#define wxMouseEvent_MetaDown 2746
+#define wxMouseEvent_MiddleDClick 2747
+#define wxMouseEvent_MiddleDown 2748
+#define wxMouseEvent_MiddleIsDown 2749
+#define wxMouseEvent_MiddleUp 2750
+#define wxMouseEvent_Moving 2751
+#define wxMouseEvent_RightDClick 2752
+#define wxMouseEvent_RightDown 2753
+#define wxMouseEvent_RightIsDown 2754
+#define wxMouseEvent_RightUp 2755
+#define wxMouseEvent_ShiftDown 2756
+#define wxSetCursorEvent_GetCursor 2757
+#define wxSetCursorEvent_GetX 2758
+#define wxSetCursorEvent_GetY 2759
+#define wxSetCursorEvent_HasCursor 2760
+#define wxSetCursorEvent_SetCursor 2761
+#define wxKeyEvent_AltDown 2762
+#define wxKeyEvent_CmdDown 2763
+#define wxKeyEvent_ControlDown 2764
+#define wxKeyEvent_GetKeyCode 2765
+#define wxKeyEvent_GetModifiers 2766
+#define wxKeyEvent_GetPosition 2769
+#define wxKeyEvent_GetRawKeyCode 2770
+#define wxKeyEvent_GetRawKeyFlags 2771
+#define wxKeyEvent_GetUnicodeKey 2772
+#define wxKeyEvent_GetX 2773
+#define wxKeyEvent_GetY 2774
+#define wxKeyEvent_HasModifiers 2775
+#define wxKeyEvent_MetaDown 2776
+#define wxKeyEvent_ShiftDown 2777
+#define wxSizeEvent_GetSize 2778
+#define wxMoveEvent_GetPosition 2779
+#define wxEraseEvent_GetDC 2780
+#define wxFocusEvent_GetWindow 2781
+#define wxChildFocusEvent_GetWindow 2782
+#define wxMenuEvent_GetMenu 2783
+#define wxMenuEvent_GetMenuId 2784
+#define wxMenuEvent_IsPopup 2785
+#define wxCloseEvent_CanVeto 2786
+#define wxCloseEvent_GetLoggingOff 2787
+#define wxCloseEvent_SetCanVeto 2788
+#define wxCloseEvent_SetLoggingOff 2789
+#define wxCloseEvent_Veto 2790
+#define wxShowEvent_SetShow 2791
+#define wxShowEvent_GetShow 2792
+#define wxIconizeEvent_Iconized 2793
+#define wxJoystickEvent_ButtonDown 2794
+#define wxJoystickEvent_ButtonIsDown 2795
+#define wxJoystickEvent_ButtonUp 2796
+#define wxJoystickEvent_GetButtonChange 2797
+#define wxJoystickEvent_GetButtonState 2798
+#define wxJoystickEvent_GetJoystick 2799
+#define wxJoystickEvent_GetPosition 2800
+#define wxJoystickEvent_GetZPosition 2801
+#define wxJoystickEvent_IsButton 2802
+#define wxJoystickEvent_IsMove 2803
+#define wxJoystickEvent_IsZMove 2804
+#define wxUpdateUIEvent_CanUpdate 2805
+#define wxUpdateUIEvent_Check 2806
+#define wxUpdateUIEvent_Enable 2807
+#define wxUpdateUIEvent_Show 2808
+#define wxUpdateUIEvent_GetChecked 2809
+#define wxUpdateUIEvent_GetEnabled 2810
+#define wxUpdateUIEvent_GetShown 2811
+#define wxUpdateUIEvent_GetSetChecked 2812
+#define wxUpdateUIEvent_GetSetEnabled 2813
+#define wxUpdateUIEvent_GetSetShown 2814
+#define wxUpdateUIEvent_GetSetText 2815
+#define wxUpdateUIEvent_GetText 2816
+#define wxUpdateUIEvent_GetMode 2817
+#define wxUpdateUIEvent_GetUpdateInterval 2818
+#define wxUpdateUIEvent_ResetUpdateTime 2819
+#define wxUpdateUIEvent_SetMode 2820
+#define wxUpdateUIEvent_SetText 2821
+#define wxUpdateUIEvent_SetUpdateInterval 2822
+#define wxMouseCaptureChangedEvent_GetCapturedWindow 2823
+#define wxPaletteChangedEvent_SetChangedWindow 2824
+#define wxPaletteChangedEvent_GetChangedWindow 2825
+#define wxQueryNewPaletteEvent_SetPaletteRealized 2826
+#define wxQueryNewPaletteEvent_GetPaletteRealized 2827
+#define wxNavigationKeyEvent_GetDirection 2828
+#define wxNavigationKeyEvent_SetDirection 2829
+#define wxNavigationKeyEvent_IsWindowChange 2830
+#define wxNavigationKeyEvent_SetWindowChange 2831
+#define wxNavigationKeyEvent_IsFromTab 2832
+#define wxNavigationKeyEvent_SetFromTab 2833
+#define wxNavigationKeyEvent_GetCurrentFocus 2834
+#define wxNavigationKeyEvent_SetCurrentFocus 2835
+#define wxHelpEvent_GetOrigin 2836
+#define wxHelpEvent_GetPosition 2837
+#define wxHelpEvent_SetOrigin 2838
+#define wxHelpEvent_SetPosition 2839
+#define wxContextMenuEvent_GetPosition 2840
+#define wxContextMenuEvent_SetPosition 2841
+#define wxIdleEvent_CanSend 2842
+#define wxIdleEvent_GetMode 2843
+#define wxIdleEvent_RequestMore 2844
+#define wxIdleEvent_MoreRequested 2845
+#define wxIdleEvent_SetMode 2846
+#define wxGridEvent_AltDown 2847
+#define wxGridEvent_ControlDown 2848
+#define wxGridEvent_GetCol 2849
+#define wxGridEvent_GetPosition 2850
+#define wxGridEvent_GetRow 2851
+#define wxGridEvent_MetaDown 2852
+#define wxGridEvent_Selecting 2853
+#define wxGridEvent_ShiftDown 2854
+#define wxNotifyEvent_Allow 2855
+#define wxNotifyEvent_IsAllowed 2856
+#define wxNotifyEvent_Veto 2857
+#define wxSashEvent_GetEdge 2858
+#define wxSashEvent_GetDragRect 2859
+#define wxSashEvent_GetDragStatus 2860
+#define wxListEvent_GetCacheFrom 2861
+#define wxListEvent_GetCacheTo 2862
+#define wxListEvent_GetKeyCode 2863
+#define wxListEvent_GetIndex 2864
+#define wxListEvent_GetColumn 2865
+#define wxListEvent_GetPoint 2866
+#define wxListEvent_GetLabel 2867
+#define wxListEvent_GetText 2868
+#define wxListEvent_GetImage 2869
+#define wxListEvent_GetData 2870
+#define wxListEvent_GetMask 2871
+#define wxListEvent_GetItem 2872
+#define wxListEvent_IsEditCancelled 2873
+#define wxDateEvent_GetDate 2874
+#define wxCalendarEvent_GetWeekDay 2875
+#define wxFileDirPickerEvent_GetPath 2876
+#define wxColourPickerEvent_GetColour 2877
+#define wxFontPickerEvent_GetFont 2878
+#define wxStyledTextEvent_GetPosition 2879
+#define wxStyledTextEvent_GetKey 2880
+#define wxStyledTextEvent_GetModifiers 2881
+#define wxStyledTextEvent_GetModificationType 2882
+#define wxStyledTextEvent_GetText 2883
+#define wxStyledTextEvent_GetLength 2884
+#define wxStyledTextEvent_GetLinesAdded 2885
+#define wxStyledTextEvent_GetLine 2886
+#define wxStyledTextEvent_GetFoldLevelNow 2887
+#define wxStyledTextEvent_GetFoldLevelPrev 2888
+#define wxStyledTextEvent_GetMargin 2889
+#define wxStyledTextEvent_GetMessage 2890
+#define wxStyledTextEvent_GetWParam 2891
+#define wxStyledTextEvent_GetLParam 2892
+#define wxStyledTextEvent_GetListType 2893
+#define wxStyledTextEvent_GetX 2894
+#define wxStyledTextEvent_GetY 2895
+#define wxStyledTextEvent_GetDragText 2896
+#define wxStyledTextEvent_GetDragAllowMove 2897
+#define wxStyledTextEvent_GetDragResult 2898
+#define wxStyledTextEvent_GetShift 2899
+#define wxStyledTextEvent_GetControl 2900
+#define wxStyledTextEvent_GetAlt 2901
+#define utils_wxGetKeyState 2902
+#define utils_wxGetMousePosition 2903
+#define utils_wxGetMouseState 2904
+#define utils_wxSetDetectableAutoRepeat 2905
+#define utils_wxBell 2906
+#define utils_wxFindMenuItemId 2907
+#define utils_wxGenericFindWindowAtPoint 2908
+#define utils_wxFindWindowAtPoint 2909
+#define utils_wxBeginBusyCursor 2910
+#define utils_wxEndBusyCursor 2911
+#define utils_wxIsBusy 2912
+#define utils_wxShutdown 2913
+#define utils_wxShell 2914
+#define utils_wxLaunchDefaultBrowser 2915
+#define utils_wxGetEmailAddress 2916
+#define utils_wxGetUserId 2917
+#define utils_wxGetHomeDir 2918
+#define utils_wxNewId 2919
+#define utils_wxRegisterId 2920
+#define utils_wxGetCurrentId 2921
+#define utils_wxGetOsDescription 2922
+#define utils_wxIsPlatformLittleEndian 2923
+#define utils_wxIsPlatform64Bit 2924
+#define wxPrintout_new 2925
+#define wxPrintout_destruct 2926
+#define wxPrintout_GetDC 2927
+#define wxPrintout_GetPageSizeMM 2928
+#define wxPrintout_GetPageSizePixels 2929
+#define wxPrintout_GetPaperRectPixels 2930
+#define wxPrintout_GetPPIPrinter 2931
+#define wxPrintout_GetPPIScreen 2932
+#define wxPrintout_GetTitle 2933
+#define wxPrintout_IsPreview 2934
+#define wxPrintout_FitThisSizeToPaper 2935
+#define wxPrintout_FitThisSizeToPage 2936
+#define wxPrintout_FitThisSizeToPageMargins 2937
+#define wxPrintout_MapScreenSizeToPaper 2938
+#define wxPrintout_MapScreenSizeToPage 2939
+#define wxPrintout_MapScreenSizeToPageMargins 2940
+#define wxPrintout_MapScreenSizeToDevice 2941
+#define wxPrintout_GetLogicalPaperRect 2942
+#define wxPrintout_GetLogicalPageRect 2943
+#define wxPrintout_GetLogicalPageMarginsRect 2944
+#define wxPrintout_SetLogicalOrigin 2945
+#define wxPrintout_OffsetLogicalOrigin 2946
+#define wxStyledTextCtrl_new_2 2947
+#define wxStyledTextCtrl_new_0 2948
+#define wxStyledTextCtrl_destruct 2949
+#define wxStyledTextCtrl_Create 2950
+#define wxStyledTextCtrl_AddText 2951
+#define wxStyledTextCtrl_AddStyledText 2952
+#define wxStyledTextCtrl_InsertText 2953
+#define wxStyledTextCtrl_ClearAll 2954
+#define wxStyledTextCtrl_ClearDocumentStyle 2955
+#define wxStyledTextCtrl_GetLength 2956
+#define wxStyledTextCtrl_GetCharAt 2957
+#define wxStyledTextCtrl_GetCurrentPos 2958
+#define wxStyledTextCtrl_GetAnchor 2959
+#define wxStyledTextCtrl_GetStyleAt 2960
+#define wxStyledTextCtrl_Redo 2961
+#define wxStyledTextCtrl_SetUndoCollection 2962
+#define wxStyledTextCtrl_SelectAll 2963
+#define wxStyledTextCtrl_SetSavePoint 2964
+#define wxStyledTextCtrl_GetStyledText 2965
+#define wxStyledTextCtrl_CanRedo 2966
+#define wxStyledTextCtrl_MarkerLineFromHandle 2967
+#define wxStyledTextCtrl_MarkerDeleteHandle 2968
+#define wxStyledTextCtrl_GetUndoCollection 2969
+#define wxStyledTextCtrl_GetViewWhiteSpace 2970
+#define wxStyledTextCtrl_SetViewWhiteSpace 2971
+#define wxStyledTextCtrl_PositionFromPoint 2972
+#define wxStyledTextCtrl_PositionFromPointClose 2973
+#define wxStyledTextCtrl_GotoLine 2974
+#define wxStyledTextCtrl_GotoPos 2975
+#define wxStyledTextCtrl_SetAnchor 2976
+#define wxStyledTextCtrl_GetCurLine 2977
+#define wxStyledTextCtrl_GetEndStyled 2978
+#define wxStyledTextCtrl_ConvertEOLs 2979
+#define wxStyledTextCtrl_GetEOLMode 2980
+#define wxStyledTextCtrl_SetEOLMode 2981
+#define wxStyledTextCtrl_StartStyling 2982
+#define wxStyledTextCtrl_SetStyling 2983
+#define wxStyledTextCtrl_GetBufferedDraw 2984
+#define wxStyledTextCtrl_SetBufferedDraw 2985
+#define wxStyledTextCtrl_SetTabWidth 2986
+#define wxStyledTextCtrl_GetTabWidth 2987
+#define wxStyledTextCtrl_SetCodePage 2988
+#define wxStyledTextCtrl_MarkerDefine 2989
+#define wxStyledTextCtrl_MarkerSetForeground 2990
+#define wxStyledTextCtrl_MarkerSetBackground 2991
+#define wxStyledTextCtrl_MarkerAdd 2992
+#define wxStyledTextCtrl_MarkerDelete 2993
+#define wxStyledTextCtrl_MarkerDeleteAll 2994
+#define wxStyledTextCtrl_MarkerGet 2995
+#define wxStyledTextCtrl_MarkerNext 2996
+#define wxStyledTextCtrl_MarkerPrevious 2997
+#define wxStyledTextCtrl_MarkerDefineBitmap 2998
+#define wxStyledTextCtrl_MarkerAddSet 2999
+#define wxStyledTextCtrl_MarkerSetAlpha 3000
+#define wxStyledTextCtrl_SetMarginType 3001
+#define wxStyledTextCtrl_GetMarginType 3002
+#define wxStyledTextCtrl_SetMarginWidth 3003
+#define wxStyledTextCtrl_GetMarginWidth 3004
+#define wxStyledTextCtrl_SetMarginMask 3005
+#define wxStyledTextCtrl_GetMarginMask 3006
+#define wxStyledTextCtrl_SetMarginSensitive 3007
+#define wxStyledTextCtrl_GetMarginSensitive 3008
+#define wxStyledTextCtrl_StyleClearAll 3009
+#define wxStyledTextCtrl_StyleSetForeground 3010
+#define wxStyledTextCtrl_StyleSetBackground 3011
+#define wxStyledTextCtrl_StyleSetBold 3012
+#define wxStyledTextCtrl_StyleSetItalic 3013
+#define wxStyledTextCtrl_StyleSetSize 3014
+#define wxStyledTextCtrl_StyleSetFaceName 3015
+#define wxStyledTextCtrl_StyleSetEOLFilled 3016
+#define wxStyledTextCtrl_StyleResetDefault 3017
+#define wxStyledTextCtrl_StyleSetUnderline 3018
+#define wxStyledTextCtrl_StyleSetCase 3019
+#define wxStyledTextCtrl_StyleSetHotSpot 3020
+#define wxStyledTextCtrl_SetSelForeground 3021
+#define wxStyledTextCtrl_SetSelBackground 3022
+#define wxStyledTextCtrl_GetSelAlpha 3023
+#define wxStyledTextCtrl_SetSelAlpha 3024
+#define wxStyledTextCtrl_SetCaretForeground 3025
+#define wxStyledTextCtrl_CmdKeyAssign 3026
+#define wxStyledTextCtrl_CmdKeyClear 3027
+#define wxStyledTextCtrl_CmdKeyClearAll 3028
+#define wxStyledTextCtrl_SetStyleBytes 3029
+#define wxStyledTextCtrl_StyleSetVisible 3030
+#define wxStyledTextCtrl_GetCaretPeriod 3031
+#define wxStyledTextCtrl_SetCaretPeriod 3032
+#define wxStyledTextCtrl_SetWordChars 3033
+#define wxStyledTextCtrl_BeginUndoAction 3034
+#define wxStyledTextCtrl_EndUndoAction 3035
+#define wxStyledTextCtrl_IndicatorSetStyle 3036
+#define wxStyledTextCtrl_IndicatorGetStyle 3037
+#define wxStyledTextCtrl_IndicatorSetForeground 3038
+#define wxStyledTextCtrl_IndicatorGetForeground 3039
+#define wxStyledTextCtrl_SetWhitespaceForeground 3040
+#define wxStyledTextCtrl_SetWhitespaceBackground 3041
+#define wxStyledTextCtrl_GetStyleBits 3042
+#define wxStyledTextCtrl_SetLineState 3043
+#define wxStyledTextCtrl_GetLineState 3044
+#define wxStyledTextCtrl_GetMaxLineState 3045
+#define wxStyledTextCtrl_GetCaretLineVisible 3046
+#define wxStyledTextCtrl_SetCaretLineVisible 3047
+#define wxStyledTextCtrl_GetCaretLineBackground 3048
+#define wxStyledTextCtrl_SetCaretLineBackground 3049
+#define wxStyledTextCtrl_AutoCompShow 3050
+#define wxStyledTextCtrl_AutoCompCancel 3051
+#define wxStyledTextCtrl_AutoCompActive 3052
+#define wxStyledTextCtrl_AutoCompPosStart 3053
+#define wxStyledTextCtrl_AutoCompComplete 3054
+#define wxStyledTextCtrl_AutoCompStops 3055
+#define wxStyledTextCtrl_AutoCompSetSeparator 3056
+#define wxStyledTextCtrl_AutoCompGetSeparator 3057
+#define wxStyledTextCtrl_AutoCompSelect 3058
+#define wxStyledTextCtrl_AutoCompSetCancelAtStart 3059
+#define wxStyledTextCtrl_AutoCompGetCancelAtStart 3060
+#define wxStyledTextCtrl_AutoCompSetFillUps 3061
+#define wxStyledTextCtrl_AutoCompSetChooseSingle 3062
+#define wxStyledTextCtrl_AutoCompGetChooseSingle 3063
+#define wxStyledTextCtrl_AutoCompSetIgnoreCase 3064
+#define wxStyledTextCtrl_AutoCompGetIgnoreCase 3065
+#define wxStyledTextCtrl_UserListShow 3066
+#define wxStyledTextCtrl_AutoCompSetAutoHide 3067
+#define wxStyledTextCtrl_AutoCompGetAutoHide 3068
+#define wxStyledTextCtrl_AutoCompSetDropRestOfWord 3069
+#define wxStyledTextCtrl_AutoCompGetDropRestOfWord 3070
+#define wxStyledTextCtrl_RegisterImage 3071
+#define wxStyledTextCtrl_ClearRegisteredImages 3072
+#define wxStyledTextCtrl_AutoCompGetTypeSeparator 3073
+#define wxStyledTextCtrl_AutoCompSetTypeSeparator 3074
+#define wxStyledTextCtrl_AutoCompSetMaxWidth 3075
+#define wxStyledTextCtrl_AutoCompGetMaxWidth 3076
+#define wxStyledTextCtrl_AutoCompSetMaxHeight 3077
+#define wxStyledTextCtrl_AutoCompGetMaxHeight 3078
+#define wxStyledTextCtrl_SetIndent 3079
+#define wxStyledTextCtrl_GetIndent 3080
+#define wxStyledTextCtrl_SetUseTabs 3081
+#define wxStyledTextCtrl_GetUseTabs 3082
+#define wxStyledTextCtrl_SetLineIndentation 3083
+#define wxStyledTextCtrl_GetLineIndentation 3084
+#define wxStyledTextCtrl_GetLineIndentPosition 3085
+#define wxStyledTextCtrl_GetColumn 3086
+#define wxStyledTextCtrl_SetUseHorizontalScrollBar 3087
+#define wxStyledTextCtrl_GetUseHorizontalScrollBar 3088
+#define wxStyledTextCtrl_SetIndentationGuides 3089
+#define wxStyledTextCtrl_GetIndentationGuides 3090
+#define wxStyledTextCtrl_SetHighlightGuide 3091
+#define wxStyledTextCtrl_GetHighlightGuide 3092
+#define wxStyledTextCtrl_GetLineEndPosition 3093
+#define wxStyledTextCtrl_GetCodePage 3094
+#define wxStyledTextCtrl_GetCaretForeground 3095
+#define wxStyledTextCtrl_GetReadOnly 3096
+#define wxStyledTextCtrl_SetCurrentPos 3097
+#define wxStyledTextCtrl_SetSelectionStart 3098
+#define wxStyledTextCtrl_GetSelectionStart 3099
+#define wxStyledTextCtrl_SetSelectionEnd 3100
+#define wxStyledTextCtrl_GetSelectionEnd 3101
+#define wxStyledTextCtrl_SetPrintMagnification 3102
+#define wxStyledTextCtrl_GetPrintMagnification 3103
+#define wxStyledTextCtrl_SetPrintColourMode 3104
+#define wxStyledTextCtrl_GetPrintColourMode 3105
+#define wxStyledTextCtrl_FindText 3106
+#define wxStyledTextCtrl_FormatRange 3107
+#define wxStyledTextCtrl_GetFirstVisibleLine 3108
+#define wxStyledTextCtrl_GetLine 3109
+#define wxStyledTextCtrl_GetLineCount 3110
+#define wxStyledTextCtrl_SetMarginLeft 3111
+#define wxStyledTextCtrl_GetMarginLeft 3112
+#define wxStyledTextCtrl_SetMarginRight 3113
+#define wxStyledTextCtrl_GetMarginRight 3114
+#define wxStyledTextCtrl_GetModify 3115
+#define wxStyledTextCtrl_SetSelection 3116
+#define wxStyledTextCtrl_GetSelectedText 3117
+#define wxStyledTextCtrl_GetTextRange 3118
+#define wxStyledTextCtrl_HideSelection 3119
+#define wxStyledTextCtrl_LineFromPosition 3120
+#define wxStyledTextCtrl_PositionFromLine 3121
+#define wxStyledTextCtrl_LineScroll 3122
+#define wxStyledTextCtrl_EnsureCaretVisible 3123
+#define wxStyledTextCtrl_ReplaceSelection 3124
+#define wxStyledTextCtrl_SetReadOnly 3125
+#define wxStyledTextCtrl_CanPaste 3126
+#define wxStyledTextCtrl_CanUndo 3127
+#define wxStyledTextCtrl_EmptyUndoBuffer 3128
+#define wxStyledTextCtrl_Undo 3129
+#define wxStyledTextCtrl_Cut 3130
+#define wxStyledTextCtrl_Copy 3131
+#define wxStyledTextCtrl_Paste 3132
+#define wxStyledTextCtrl_Clear 3133
+#define wxStyledTextCtrl_SetText 3134
+#define wxStyledTextCtrl_GetText 3135
+#define wxStyledTextCtrl_GetTextLength 3136
+#define wxStyledTextCtrl_GetOvertype 3137
+#define wxStyledTextCtrl_SetCaretWidth 3138
+#define wxStyledTextCtrl_GetCaretWidth 3139
+#define wxStyledTextCtrl_SetTargetStart 3140
+#define wxStyledTextCtrl_GetTargetStart 3141
+#define wxStyledTextCtrl_SetTargetEnd 3142
+#define wxStyledTextCtrl_GetTargetEnd 3143
+#define wxStyledTextCtrl_ReplaceTarget 3144
+#define wxStyledTextCtrl_SearchInTarget 3145
+#define wxStyledTextCtrl_SetSearchFlags 3146
+#define wxStyledTextCtrl_GetSearchFlags 3147
+#define wxStyledTextCtrl_CallTipShow 3148
+#define wxStyledTextCtrl_CallTipCancel 3149
+#define wxStyledTextCtrl_CallTipActive 3150
+#define wxStyledTextCtrl_CallTipPosAtStart 3151
+#define wxStyledTextCtrl_CallTipSetHighlight 3152
+#define wxStyledTextCtrl_CallTipSetBackground 3153
+#define wxStyledTextCtrl_CallTipSetForeground 3154
+#define wxStyledTextCtrl_CallTipSetForegroundHighlight 3155
+#define wxStyledTextCtrl_CallTipUseStyle 3156
+#define wxStyledTextCtrl_VisibleFromDocLine 3157
+#define wxStyledTextCtrl_DocLineFromVisible 3158
+#define wxStyledTextCtrl_WrapCount 3159
+#define wxStyledTextCtrl_SetFoldLevel 3160
+#define wxStyledTextCtrl_GetFoldLevel 3161
+#define wxStyledTextCtrl_GetLastChild 3162
+#define wxStyledTextCtrl_GetFoldParent 3163
+#define wxStyledTextCtrl_ShowLines 3164
+#define wxStyledTextCtrl_HideLines 3165
+#define wxStyledTextCtrl_GetLineVisible 3166
+#define wxStyledTextCtrl_SetFoldExpanded 3167
+#define wxStyledTextCtrl_GetFoldExpanded 3168
+#define wxStyledTextCtrl_ToggleFold 3169
+#define wxStyledTextCtrl_EnsureVisible 3170
+#define wxStyledTextCtrl_SetFoldFlags 3171
+#define wxStyledTextCtrl_EnsureVisibleEnforcePolicy 3172
+#define wxStyledTextCtrl_SetTabIndents 3173
+#define wxStyledTextCtrl_GetTabIndents 3174
+#define wxStyledTextCtrl_SetBackSpaceUnIndents 3175
+#define wxStyledTextCtrl_GetBackSpaceUnIndents 3176
+#define wxStyledTextCtrl_SetMouseDwellTime 3177
+#define wxStyledTextCtrl_GetMouseDwellTime 3178
+#define wxStyledTextCtrl_WordStartPosition 3179
+#define wxStyledTextCtrl_WordEndPosition 3180
+#define wxStyledTextCtrl_SetWrapMode 3181
+#define wxStyledTextCtrl_GetWrapMode 3182
+#define wxStyledTextCtrl_SetWrapVisualFlags 3183
+#define wxStyledTextCtrl_GetWrapVisualFlags 3184
+#define wxStyledTextCtrl_SetWrapVisualFlagsLocation 3185
+#define wxStyledTextCtrl_GetWrapVisualFlagsLocation 3186
+#define wxStyledTextCtrl_SetWrapStartIndent 3187
+#define wxStyledTextCtrl_GetWrapStartIndent 3188
+#define wxStyledTextCtrl_SetLayoutCache 3189
+#define wxStyledTextCtrl_GetLayoutCache 3190
+#define wxStyledTextCtrl_SetScrollWidth 3191
+#define wxStyledTextCtrl_GetScrollWidth 3192
+#define wxStyledTextCtrl_TextWidth 3193
+#define wxStyledTextCtrl_GetEndAtLastLine 3194
+#define wxStyledTextCtrl_TextHeight 3195
+#define wxStyledTextCtrl_SetUseVerticalScrollBar 3196
+#define wxStyledTextCtrl_GetUseVerticalScrollBar 3197
+#define wxStyledTextCtrl_AppendText 3198
+#define wxStyledTextCtrl_GetTwoPhaseDraw 3199
+#define wxStyledTextCtrl_SetTwoPhaseDraw 3200
+#define wxStyledTextCtrl_TargetFromSelection 3201
+#define wxStyledTextCtrl_LinesJoin 3202
+#define wxStyledTextCtrl_LinesSplit 3203
+#define wxStyledTextCtrl_SetFoldMarginColour 3204
+#define wxStyledTextCtrl_SetFoldMarginHiColour 3205
+#define wxStyledTextCtrl_LineDown 3206
+#define wxStyledTextCtrl_LineDownExtend 3207
+#define wxStyledTextCtrl_LineUp 3208
+#define wxStyledTextCtrl_LineUpExtend 3209
+#define wxStyledTextCtrl_CharLeft 3210
+#define wxStyledTextCtrl_CharLeftExtend 3211
+#define wxStyledTextCtrl_CharRight 3212
+#define wxStyledTextCtrl_CharRightExtend 3213
+#define wxStyledTextCtrl_WordLeft 3214
+#define wxStyledTextCtrl_WordLeftExtend 3215
+#define wxStyledTextCtrl_WordRight 3216
+#define wxStyledTextCtrl_WordRightExtend 3217
+#define wxStyledTextCtrl_Home 3218
+#define wxStyledTextCtrl_HomeExtend 3219
+#define wxStyledTextCtrl_LineEnd 3220
+#define wxStyledTextCtrl_LineEndExtend 3221
+#define wxStyledTextCtrl_DocumentStart 3222
+#define wxStyledTextCtrl_DocumentStartExtend 3223
+#define wxStyledTextCtrl_DocumentEnd 3224
+#define wxStyledTextCtrl_DocumentEndExtend 3225
+#define wxStyledTextCtrl_PageUp 3226
+#define wxStyledTextCtrl_PageUpExtend 3227
+#define wxStyledTextCtrl_PageDown 3228
+#define wxStyledTextCtrl_PageDownExtend 3229
+#define wxStyledTextCtrl_EditToggleOvertype 3230
+#define wxStyledTextCtrl_Cancel 3231
+#define wxStyledTextCtrl_DeleteBack 3232
+#define wxStyledTextCtrl_Tab 3233
+#define wxStyledTextCtrl_BackTab 3234
+#define wxStyledTextCtrl_NewLine 3235
+#define wxStyledTextCtrl_FormFeed 3236
+#define wxStyledTextCtrl_VCHome 3237
+#define wxStyledTextCtrl_VCHomeExtend 3238
+#define wxStyledTextCtrl_ZoomIn 3239
+#define wxStyledTextCtrl_ZoomOut 3240
+#define wxStyledTextCtrl_DelWordLeft 3241
+#define wxStyledTextCtrl_DelWordRight 3242
+#define wxStyledTextCtrl_LineCut 3243
+#define wxStyledTextCtrl_LineDelete 3244
+#define wxStyledTextCtrl_LineTranspose 3245
+#define wxStyledTextCtrl_LineDuplicate 3246
+#define wxStyledTextCtrl_LowerCase 3247
+#define wxStyledTextCtrl_UpperCase 3248
+#define wxStyledTextCtrl_LineScrollDown 3249
+#define wxStyledTextCtrl_LineScrollUp 3250
+#define wxStyledTextCtrl_DeleteBackNotLine 3251
+#define wxStyledTextCtrl_HomeDisplay 3252
+#define wxStyledTextCtrl_HomeDisplayExtend 3253
+#define wxStyledTextCtrl_LineEndDisplay 3254
+#define wxStyledTextCtrl_LineEndDisplayExtend 3255
+#define wxStyledTextCtrl_HomeWrapExtend 3256
+#define wxStyledTextCtrl_LineEndWrap 3257
+#define wxStyledTextCtrl_LineEndWrapExtend 3258
+#define wxStyledTextCtrl_VCHomeWrap 3259
+#define wxStyledTextCtrl_VCHomeWrapExtend 3260
+#define wxStyledTextCtrl_LineCopy 3261
+#define wxStyledTextCtrl_MoveCaretInsideView 3262
+#define wxStyledTextCtrl_LineLength 3263
+#define wxStyledTextCtrl_BraceHighlight 3264
+#define wxStyledTextCtrl_BraceBadLight 3265
+#define wxStyledTextCtrl_BraceMatch 3266
+#define wxStyledTextCtrl_GetViewEOL 3267
+#define wxStyledTextCtrl_SetViewEOL 3268
+#define wxStyledTextCtrl_SetModEventMask 3269
+#define wxStyledTextCtrl_GetEdgeColumn 3270
+#define wxStyledTextCtrl_SetEdgeColumn 3271
+#define wxStyledTextCtrl_GetEdgeMode 3272
+#define wxStyledTextCtrl_GetEdgeColour 3273
+#define wxStyledTextCtrl_SetEdgeColour 3274
+#define wxStyledTextCtrl_SearchAnchor 3275
+#define wxStyledTextCtrl_SearchNext 3276
+#define wxStyledTextCtrl_SearchPrev 3277
+#define wxStyledTextCtrl_LinesOnScreen 3278
+#define wxStyledTextCtrl_UsePopUp 3279
+#define wxStyledTextCtrl_SelectionIsRectangle 3280
+#define wxStyledTextCtrl_SetZoom 3281
+#define wxStyledTextCtrl_GetZoom 3282
+#define wxStyledTextCtrl_GetModEventMask 3283
+#define wxStyledTextCtrl_SetSTCFocus 3284
+#define wxStyledTextCtrl_GetSTCFocus 3285
+#define wxStyledTextCtrl_SetStatus 3286
+#define wxStyledTextCtrl_GetStatus 3287
+#define wxStyledTextCtrl_SetMouseDownCaptures 3288
+#define wxStyledTextCtrl_GetMouseDownCaptures 3289
+#define wxStyledTextCtrl_SetSTCCursor 3290
+#define wxStyledTextCtrl_GetSTCCursor 3291
+#define wxStyledTextCtrl_SetControlCharSymbol 3292
+#define wxStyledTextCtrl_GetControlCharSymbol 3293
+#define wxStyledTextCtrl_WordPartLeft 3294
+#define wxStyledTextCtrl_WordPartLeftExtend 3295
+#define wxStyledTextCtrl_WordPartRight 3296
+#define wxStyledTextCtrl_WordPartRightExtend 3297
+#define wxStyledTextCtrl_SetVisiblePolicy 3298
+#define wxStyledTextCtrl_DelLineLeft 3299
+#define wxStyledTextCtrl_DelLineRight 3300
+#define wxStyledTextCtrl_GetXOffset 3301
+#define wxStyledTextCtrl_ChooseCaretX 3302
+#define wxStyledTextCtrl_SetXCaretPolicy 3303
+#define wxStyledTextCtrl_SetYCaretPolicy 3304
+#define wxStyledTextCtrl_GetPrintWrapMode 3305
+#define wxStyledTextCtrl_SetHotspotActiveForeground 3306
+#define wxStyledTextCtrl_SetHotspotActiveBackground 3307
+#define wxStyledTextCtrl_SetHotspotActiveUnderline 3308
+#define wxStyledTextCtrl_SetHotspotSingleLine 3309
+#define wxStyledTextCtrl_ParaDownExtend 3310
+#define wxStyledTextCtrl_ParaUp 3311
+#define wxStyledTextCtrl_ParaUpExtend 3312
+#define wxStyledTextCtrl_PositionBefore 3313
+#define wxStyledTextCtrl_PositionAfter 3314
+#define wxStyledTextCtrl_CopyRange 3315
+#define wxStyledTextCtrl_CopyText 3316
+#define wxStyledTextCtrl_SetSelectionMode 3317
+#define wxStyledTextCtrl_GetSelectionMode 3318
+#define wxStyledTextCtrl_LineDownRectExtend 3319
+#define wxStyledTextCtrl_LineUpRectExtend 3320
+#define wxStyledTextCtrl_CharLeftRectExtend 3321
+#define wxStyledTextCtrl_CharRightRectExtend 3322
+#define wxStyledTextCtrl_HomeRectExtend 3323
+#define wxStyledTextCtrl_VCHomeRectExtend 3324
+#define wxStyledTextCtrl_LineEndRectExtend 3325
+#define wxStyledTextCtrl_PageUpRectExtend 3326
+#define wxStyledTextCtrl_PageDownRectExtend 3327
+#define wxStyledTextCtrl_StutteredPageUp 3328
+#define wxStyledTextCtrl_StutteredPageUpExtend 3329
+#define wxStyledTextCtrl_StutteredPageDown 3330
+#define wxStyledTextCtrl_StutteredPageDownExtend 3331
+#define wxStyledTextCtrl_WordLeftEnd 3332
+#define wxStyledTextCtrl_WordLeftEndExtend 3333
+#define wxStyledTextCtrl_WordRightEnd 3334
+#define wxStyledTextCtrl_WordRightEndExtend 3335
+#define wxStyledTextCtrl_SetWhitespaceChars 3336
+#define wxStyledTextCtrl_SetCharsDefault 3337
+#define wxStyledTextCtrl_AutoCompGetCurrent 3338
+#define wxStyledTextCtrl_Allocate 3339
+#define wxStyledTextCtrl_FindColumn 3340
+#define wxStyledTextCtrl_GetCaretSticky 3341
+#define wxStyledTextCtrl_SetCaretSticky 3342
+#define wxStyledTextCtrl_ToggleCaretSticky 3343
+#define wxStyledTextCtrl_SetPasteConvertEndings 3344
+#define wxStyledTextCtrl_GetPasteConvertEndings 3345
+#define wxStyledTextCtrl_SelectionDuplicate 3346
+#define wxStyledTextCtrl_SetCaretLineBackAlpha 3347
+#define wxStyledTextCtrl_GetCaretLineBackAlpha 3348
+#define wxStyledTextCtrl_StartRecord 3349
+#define wxStyledTextCtrl_StopRecord 3350
+#define wxStyledTextCtrl_SetLexer 3351
+#define wxStyledTextCtrl_GetLexer 3352
+#define wxStyledTextCtrl_Colourise 3353
+#define wxStyledTextCtrl_SetProperty 3354
+#define wxStyledTextCtrl_SetKeyWords 3355
+#define wxStyledTextCtrl_SetLexerLanguage 3356
+#define wxStyledTextCtrl_GetProperty 3357
+#define wxStyledTextCtrl_GetStyleBitsNeeded 3358
+#define wxStyledTextCtrl_GetCurrentLine 3359
+#define wxStyledTextCtrl_StyleSetSpec 3360
+#define wxStyledTextCtrl_StyleSetFont 3361
+#define wxStyledTextCtrl_StyleSetFontAttr 3362
+#define wxStyledTextCtrl_StyleSetCharacterSet 3363
+#define wxStyledTextCtrl_StyleSetFontEncoding 3364
+#define wxStyledTextCtrl_CmdKeyExecute 3365
+#define wxStyledTextCtrl_SetMargins 3366
+#define wxStyledTextCtrl_GetSelection 3367
+#define wxStyledTextCtrl_PointFromPosition 3368
+#define wxStyledTextCtrl_ScrollToLine 3369
+#define wxStyledTextCtrl_ScrollToColumn 3370
+#define wxStyledTextCtrl_SendMsg 3371
+#define wxStyledTextCtrl_SetVScrollBar 3372
+#define wxStyledTextCtrl_SetHScrollBar 3373
+#define wxStyledTextCtrl_GetLastKeydownProcessed 3374
+#define wxStyledTextCtrl_SetLastKeydownProcessed 3375
+#define wxStyledTextCtrl_SaveFile 3376
+#define wxStyledTextCtrl_LoadFile 3377
+#define wxStyledTextCtrl_DoDragOver 3378
+#define wxStyledTextCtrl_DoDropText 3379
+#define wxStyledTextCtrl_GetUseAntiAliasing 3380
+#define wxStyledTextCtrl_AddTextRaw 3381
+#define wxStyledTextCtrl_InsertTextRaw 3382
+#define wxStyledTextCtrl_GetCurLineRaw 3383
+#define wxStyledTextCtrl_GetLineRaw 3384
+#define wxStyledTextCtrl_GetSelectedTextRaw 3385
+#define wxStyledTextCtrl_GetTextRangeRaw 3386
+#define wxStyledTextCtrl_SetTextRaw 3387
+#define wxStyledTextCtrl_GetTextRaw 3388
+#define wxStyledTextCtrl_AppendTextRaw 3389
+#define wxArtProvider_GetBitmap 3390
+#define wxArtProvider_GetIcon 3391
+#define wxTreeEvent_GetKeyCode 3392
+#define wxTreeEvent_GetItem 3393
+#define wxTreeEvent_GetKeyEvent 3394
+#define wxTreeEvent_GetLabel 3395
+#define wxTreeEvent_GetOldItem 3396
+#define wxTreeEvent_GetPoint 3397
+#define wxTreeEvent_IsEditCancelled 3398
+#define wxTreeEvent_SetToolTip 3399
+#define wxNotebookEvent_GetOldSelection 3400
+#define wxNotebookEvent_GetSelection 3401
+#define wxNotebookEvent_SetOldSelection 3402
+#define wxNotebookEvent_SetSelection 3403
+#define wxFileDataObject_new 3404
+#define wxFileDataObject_AddFile 3405
+#define wxFileDataObject_GetFilenames 3406
+#define wxFileDataObject_destroy 3407
+#define wxTextDataObject_new 3408
+#define wxTextDataObject_GetTextLength 3409
+#define wxTextDataObject_GetText 3410
+#define wxTextDataObject_SetText 3411
+#define wxTextDataObject_destroy 3412
+#define wxBitmapDataObject_new_1_1 3413
+#define wxBitmapDataObject_new_1_0 3414
+#define wxBitmapDataObject_GetBitmap 3415
+#define wxBitmapDataObject_SetBitmap 3416
+#define wxBitmapDataObject_destroy 3417
+#define wxClipboard_new 3419
+#define wxClipboard_destruct 3420
+#define wxClipboard_AddData 3421
+#define wxClipboard_Clear 3422
+#define wxClipboard_Close 3423
+#define wxClipboard_Flush 3424
+#define wxClipboard_GetData 3425
+#define wxClipboard_IsOpened 3426
+#define wxClipboard_Open 3427
+#define wxClipboard_SetData 3428
+#define wxClipboard_UsePrimarySelection 3430
+#define wxClipboard_IsSupported 3431
+#define wxClipboard_Get 3432
+#define wxSpinEvent_GetPosition 3433
+#define wxSpinEvent_SetPosition 3434
+#define wxSplitterWindow_new_0 3435
+#define wxSplitterWindow_new_2 3436
+#define wxSplitterWindow_destruct 3437
+#define wxSplitterWindow_Create 3438
+#define wxSplitterWindow_GetMinimumPaneSize 3439
+#define wxSplitterWindow_GetSashGravity 3440
+#define wxSplitterWindow_GetSashPosition 3441
+#define wxSplitterWindow_GetSplitMode 3442
+#define wxSplitterWindow_GetWindow1 3443
+#define wxSplitterWindow_GetWindow2 3444
+#define wxSplitterWindow_Initialize 3445
+#define wxSplitterWindow_IsSplit 3446
+#define wxSplitterWindow_ReplaceWindow 3447
+#define wxSplitterWindow_SetSashGravity 3448
+#define wxSplitterWindow_SetSashPosition 3449
+#define wxSplitterWindow_SetSashSize 3450
+#define wxSplitterWindow_SetMinimumPaneSize 3451
+#define wxSplitterWindow_SetSplitMode 3452
+#define wxSplitterWindow_SplitHorizontally 3453
+#define wxSplitterWindow_SplitVertically 3454
+#define wxSplitterWindow_Unsplit 3455
+#define wxSplitterWindow_UpdateSize 3456
+#define wxSplitterEvent_GetSashPosition 3457
+#define wxSplitterEvent_GetX 3458
+#define wxSplitterEvent_GetY 3459
+#define wxSplitterEvent_GetWindowBeingRemoved 3460
+#define wxSplitterEvent_SetSashPosition 3461
+#define wxHtmlWindow_new_0 3462
+#define wxHtmlWindow_new_2 3463
+#define wxHtmlWindow_AppendToPage 3464
+#define wxHtmlWindow_GetOpenedAnchor 3465
+#define wxHtmlWindow_GetOpenedPage 3466
+#define wxHtmlWindow_GetOpenedPageTitle 3467
+#define wxHtmlWindow_GetRelatedFrame 3468
+#define wxHtmlWindow_HistoryBack 3469
+#define wxHtmlWindow_HistoryCanBack 3470
+#define wxHtmlWindow_HistoryCanForward 3471
+#define wxHtmlWindow_HistoryClear 3472
+#define wxHtmlWindow_HistoryForward 3473
+#define wxHtmlWindow_LoadFile 3474
+#define wxHtmlWindow_LoadPage 3475
+#define wxHtmlWindow_SelectAll 3476
+#define wxHtmlWindow_SelectionToText 3477
+#define wxHtmlWindow_SelectLine 3478
+#define wxHtmlWindow_SelectWord 3479
+#define wxHtmlWindow_SetBorders 3480
+#define wxHtmlWindow_SetFonts 3481
+#define wxHtmlWindow_SetPage 3482
+#define wxHtmlWindow_SetRelatedFrame 3483
+#define wxHtmlWindow_SetRelatedStatusBar 3484
+#define wxHtmlWindow_ToText 3485
+#define wxHtmlWindow_destroy 3486
+#define wxHtmlLinkEvent_GetLinkInfo 3487
+#define wxSystemSettings_GetColour 3488
+#define wxSystemSettings_GetFont 3489
+#define wxSystemSettings_GetMetric 3490
+#define wxSystemSettings_GetScreenType 3491
+#define wxAuiNotebookEvent_SetSelection 3492
+#define wxAuiNotebookEvent_GetSelection 3493
+#define wxAuiNotebookEvent_SetOldSelection 3494
+#define wxAuiNotebookEvent_GetOldSelection 3495
+#define wxAuiNotebookEvent_SetDragSource 3496
+#define wxAuiNotebookEvent_GetDragSource 3497
+#define wxAuiManagerEvent_SetManager 3498
+#define wxAuiManagerEvent_GetManager 3499
+#define wxAuiManagerEvent_SetPane 3500
+#define wxAuiManagerEvent_GetPane 3501
+#define wxAuiManagerEvent_SetButton 3502
+#define wxAuiManagerEvent_GetButton 3503
+#define wxAuiManagerEvent_SetDC 3504
+#define wxAuiManagerEvent_GetDC 3505
+#define wxAuiManagerEvent_Veto 3506
+#define wxAuiManagerEvent_GetVeto 3507
+#define wxAuiManagerEvent_SetCanVeto 3508
+#define wxAuiManagerEvent_CanVeto 3509
+#define wxLogNull_new 3510
+#define wxLogNull_destroy 3511
diff --git a/lib/wx/c_src/wxePrintout.cpp b/lib/wx/c_src/wxePrintout.cpp
index ea1c76edcc..90959df379 100644
--- a/lib/wx/c_src/wxePrintout.cpp
+++ b/lib/wx/c_src/wxePrintout.cpp
@@ -1,41 +1,62 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 2008-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 2008-2011. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
- * %CopyrightEnd%
+ *
+ * %CopyrightEnd%
*/
#include <wx/wx.h>
#include "wxe_impl.h"
#include "wxe_return.h"
+#include "gen/wxe_macros.h"
+#include "gen/wxe_derived_dest.h"
/* *****************************************************************/
/* Special Class impls */
+#define INVOKE_CALLBACK_INIT(port, callback, class_str) \
+ { \
+ wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port); \
+ wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false); \
+ rt.addInt(callback); \
+ rt.addRef(((WxeApp *) wxTheApp)->getRef((void *)this, memenv), class_str);
+
+#define INVOKE_CALLBACK_END(port, args) \
+ rt.endList(1 + (args)); \
+ rt.addAtom("_wx_invoke_cb_"); \
+ rt.addTupleCount(3); \
+ rt.send(); \
+ handle_event_callback(port, memenv->owner); \
+ }
+
+#define INVOKE_CALLBACK(port, callback, class_str) \
+ INVOKE_CALLBACK_INIT(port, callback, class_str); \
+ INVOKE_CALLBACK_END(port, 0)
+/* *****************************************************************/
/* Printing special */
wxEPrintout::~wxEPrintout() {
- clear_cb(onPrintPage);
- clear_cb(onPreparePrinting);
- clear_cb(onBeginPrinting);
- clear_cb(onEndPrinting);
- clear_cb(onBeginDocument);
- clear_cb(onEndDocument);
- clear_cb(hasPage);
- clear_cb(getPageInfo);
+ clear_cb(port, onPrintPage);
+ clear_cb(port, onPreparePrinting);
+ clear_cb(port, onBeginPrinting);
+ clear_cb(port, onEndPrinting);
+ clear_cb(port, onBeginDocument);
+ clear_cb(port, onEndDocument);
+ clear_cb(port, hasPage);
+ clear_cb(port, getPageInfo);
((WxeApp *)wxTheApp)->clearPtr(this);
}
@@ -43,73 +64,44 @@ wxEPrintout::~wxEPrintout() {
bool wxEPrintout::OnBeginDocument(int startPage, int endPage)
{
if(onBeginDocument) {
- wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
- char * bp = ((WxeApp *) wxTheApp)->cb_buff;
-
- wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
- rt.addInt(onBeginDocument);
- rt.addRef(((WxeApp *) wxTheApp)->getRef((void *)this, memenv), "wxPrintout");
+ INVOKE_CALLBACK_INIT(port, onBeginDocument, "wxPrintout");
rt.addInt(startPage);
rt.addInt(endPage);
- rt.endList(3);
- rt.addAtom("_wx_invoke_cb_");
- rt.addTupleCount(3);
- rt.send();
- handle_callback_batch(port);
- return *(int*) bp;
- } else {
- return wxPrintout::OnBeginDocument(startPage,endPage);
- }
+ INVOKE_CALLBACK_END(port, 2);
+ if(((WxeApp *) wxTheApp)->cb_buff) {
+ int res = * (int*) ((WxeApp *) wxTheApp)->cb_buff;
+ driver_free(((WxeApp *) wxTheApp)->cb_buff);
+ ((WxeApp *) wxTheApp)->cb_buff = NULL;
+ return res;
+ }
+ }
+ return wxPrintout::OnBeginDocument(startPage,endPage);
}
-void wxEPrintout::OnEndDocument()
+void wxEPrintout::OnEndDocument()
{
if(onEndDocument) {
- wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
- wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
- rt.addInt(onEndDocument);
- rt.addRef(((WxeApp *) wxTheApp)->getRef((void *)this, memenv), "wxPrintout");
- rt.endList(1);
- rt.addAtom("_wx_invoke_cb_");
- rt.addTupleCount(3);
- rt.send();
- handle_callback_batch(port);
+ INVOKE_CALLBACK(port, onEndDocument, "wxPrintout");
} else {
wxPrintout::OnEndDocument();
- }
+ }
}
-void wxEPrintout::OnBeginPrinting()
+void wxEPrintout::OnBeginPrinting()
{
if(onBeginPrinting) {
- wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
- wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
- rt.addInt(onBeginPrinting);
- rt.addRef(((WxeApp *) wxTheApp)->getRef((void *)this, memenv), "wxPrintout");
- rt.endList(1);
- rt.addAtom("_wx_invoke_cb_");
- rt.addTupleCount(3);
- rt.send();
- handle_callback_batch(port);
+ INVOKE_CALLBACK(port, onBeginPrinting, "wxPrintout");
} else {
wxPrintout::OnBeginPrinting();
- }
+ }
}
-void wxEPrintout::OnEndPrinting()
+void wxEPrintout::OnEndPrinting()
{
if(onEndPrinting) {
- wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
- wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
- rt.addInt(onEndPrinting);
- rt.addRef(((WxeApp *) wxTheApp)->getRef((void *)this, memenv), "wxPrintout");
- rt.endList(1);
- rt.addAtom("_wx_invoke_cb_");
- rt.addTupleCount(3);
- rt.send();
- handle_callback_batch(port);
+ INVOKE_CALLBACK(port, onEndPrinting, "wxPrintout");
} else {
wxPrintout::OnEndPrinting();
}
@@ -119,92 +111,133 @@ void wxEPrintout::OnPreparePrinting()
{
if(onPreparePrinting) {
- wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
- wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
- rt.addInt(onPreparePrinting);
- rt.addRef(((WxeApp *) wxTheApp)->getRef((void *)this, memenv), "wxPrintout");
- rt.endList(1);
- rt.addAtom("_wx_invoke_cb_");
- rt.addTupleCount(3);
- rt.send();
- handle_callback_batch(port);
+ INVOKE_CALLBACK(port, onPreparePrinting, "wxPrintout");
} else {
wxPrintout::OnPreparePrinting();
- }
+ }
}
-bool wxEPrintout::HasPage(int page)
+bool wxEPrintout::HasPage(int page)
{
if(hasPage) {
- wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
- wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
- rt.addInt(hasPage);
- rt.addRef(((WxeApp *) wxTheApp)->getRef((void *)this, memenv), "wxPrintout");
+ INVOKE_CALLBACK_INIT(port, hasPage, "wxPrintout");
rt.addInt(page);
- rt.endList(2);
- rt.addAtom("_wx_invoke_cb_");
- rt.addTupleCount(3);
- rt.send();
- char * bp = ((WxeApp *) wxTheApp)->cb_buff;
- handle_callback_batch(port);
- return *(int*) bp;
- } else {
- return wxPrintout::HasPage(page);
- }
+ INVOKE_CALLBACK_END(port, 1);
+ if(((WxeApp *) wxTheApp)->cb_buff) {
+ int res = * (int*) ((WxeApp *) wxTheApp)->cb_buff;
+ driver_free(((WxeApp *) wxTheApp)->cb_buff);
+ ((WxeApp *) wxTheApp)->cb_buff = NULL;
+ return res;
+ }
+ }
+ return wxPrintout::HasPage(page);
}
bool wxEPrintout::OnPrintPage(int page)
{
- wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
- wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
- rt.addInt(onPrintPage);
- rt.addRef(((WxeApp *) wxTheApp)->getRef((void *)this, memenv), "wxPrintout");
+ INVOKE_CALLBACK_INIT(port, onPrintPage, "wxPrintout");
rt.addInt(page);
- rt.endList(2);
- rt.addAtom("_wx_invoke_cb_");
- rt.addTupleCount(3);
- rt.send();
- handle_callback_batch(port);
- //fprintf(stderr,"%d ", __LINE__);handle_callback_batch(port); fprintf(stderr,"%d\r\n", __LINE__);
- char * bp = ((WxeApp *) wxTheApp)->cb_buff;
- return *(int*) bp;
+ INVOKE_CALLBACK_END(port, 1);
+ if(((WxeApp *) wxTheApp)->cb_buff) {
+ int res = * (int*) ((WxeApp *) wxTheApp)->cb_buff;
+ driver_free(((WxeApp *) wxTheApp)->cb_buff);
+ ((WxeApp *) wxTheApp)->cb_buff = NULL;
+ return res;
+ }
+ return FALSE;
}
-
+
void wxEPrintout::GetPageInfo(int *minPage, int *maxPage, int *pageFrom, int *pageTo)
{
if(getPageInfo) {
- wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
- wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
- rt.addInt(getPageInfo);
- rt.addRef(((WxeApp *) wxTheApp)->getRef((void *)this, memenv), "wxPrintout");
- rt.endList(1);
- rt.addAtom("_wx_invoke_cb_");
- rt.addTupleCount(3);
- rt.send();
- handle_callback_batch(port);
- //fprintf(stderr,"%d ", __LINE__);handle_callback_batch(port); fprintf(stderr,"%d\r\n", __LINE__);
+ INVOKE_CALLBACK(port, getPageInfo, "wxPrintout");
+ if(((WxeApp *) wxTheApp)->cb_buff) {
+ char * bp = ((WxeApp *) wxTheApp)->cb_buff;
+ *minPage = *(int *) bp; bp += 4;
+ *maxPage = *(int *) bp; bp += 4;
+ *pageFrom = *(int *) bp; bp += 4;
+ *pageTo = *(int *) bp; bp += 4;
+ driver_free(((WxeApp *) wxTheApp)->cb_buff);
+ ((WxeApp *) wxTheApp)->cb_buff = NULL;
+ }
+ }
+ wxPrintout::GetPageInfo(minPage, maxPage, pageFrom, pageTo);
+}
+
+/* *****************************************************************/
+// ListCtrl with callbacks for VIRTUAL_TABLES
+
+wxString EwxListCtrl::OnGetItemText(long item, long col) const {
+ if(onGetItemText) {
+ INVOKE_CALLBACK_INIT(port, onGetItemText, "wxListCtrl");
+ rt.addInt(item);
+ rt.addInt(col);
+ INVOKE_CALLBACK_END(port, 2);
+ if(((WxeApp *) wxTheApp)->cb_buff) {
+ char * bp = ((WxeApp *) wxTheApp)->cb_buff;
+ wxString str = wxString(bp, wxConvUTF8);
+ driver_free(((WxeApp *) wxTheApp)->cb_buff);
+ ((WxeApp *) wxTheApp)->cb_buff = NULL;
+ return str;
+ }
+ }
+ return wxT("OnGetItemText not correctly defined");
+}
+wxListItemAttr* EwxListCtrl::OnGetItemAttr(long item) const {
+ if(onGetItemAttr) {
+ INVOKE_CALLBACK_INIT(port, onGetItemAttr, "wxListCtrl");
+ rt.addInt(item);
+ INVOKE_CALLBACK_END(port, 1);
char * bp = ((WxeApp *) wxTheApp)->cb_buff;
- *minPage = *(int *) bp; bp += 4;
- *maxPage = *(int *) bp; bp += 4;
- *pageFrom = *(int *) bp; bp += 4;
- *pageTo = *(int *) bp; bp += 4;
- } else {
- wxPrintout::GetPageInfo(minPage, maxPage, pageFrom, pageTo);
+ wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
+ if(bp) {
+ wxListItemAttr * result = (wxListItemAttr *)((WxeApp *) wxTheApp)->getPtr(bp, memenv);
+ driver_free(((WxeApp *) wxTheApp)->cb_buff);
+ ((WxeApp *) wxTheApp)->cb_buff = NULL;
+ return result;
+ }
}
+ return NULL;
+}
+
+int EwxListCtrl::OnGetItemImage(long item) const {
+ return OnGetItemColumnImage(item, 0);
}
-void wxEPrintout::clear_cb(int callback)
+int EwxListCtrl::OnGetItemColumnImage(long item, long col) const {
+ if(onGetItemColumnImage) {
+ INVOKE_CALLBACK_INIT(port, onGetItemColumnImage, "wxListCtrl");
+ rt.addInt(item);
+ rt.addInt(col);
+ INVOKE_CALLBACK_END(port, 2);
+ if(((WxeApp *) wxTheApp)->cb_buff) {
+ int res = * (int*) ((WxeApp *) wxTheApp)->cb_buff;
+ driver_free(((WxeApp *) wxTheApp)->cb_buff);
+ ((WxeApp *) wxTheApp)->cb_buff = NULL;
+ return res;
+ }
+ }
+ return -1;
+}
+
+EwxListCtrl::~EwxListCtrl() {
+ clear_cb(port, onGetItemText);
+ clear_cb(port, onGetItemAttr);
+ clear_cb(port, onGetItemColumnImage);
+ ((WxeApp *)wxTheApp)->clearPtr(this);
+}
+// tools
+
+void clear_cb(ErlDrvPort port, int callback)
{
if(callback > 0) {
wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(port);
wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
- // NOTE: Remove this later when changing from funs to gen_server
rt.addAtom("wx_delete_cb");
rt.addInt(callback);
rt.addTupleCount(2);
rt.send();
}
}
-
diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp
index 365fb691a1..e430fbc7a2 100644
--- a/lib/wx/c_src/wxe_impl.cpp
+++ b/lib/wx/c_src/wxe_impl.cpp
@@ -14,7 +14,7 @@
* the License for the specific language governing rights and limitations
* under the License.
*
- * %CopyrightEnd%
+ * %CopyrightEnd%
*/
#include <stdio.h>
@@ -49,7 +49,7 @@ DEFINE_EVENT_TYPE(wxeEVT_META_COMMAND)
#define WXE_NORMAL 0
#define WXE_CALLBACK 1
-#define WXE_STORED 2
+#define WXE_STORED 2
ErlDrvTid wxe_thread;
@@ -67,7 +67,7 @@ wxList * wxe_batch_cb_saved = NULL;
ErlDrvTermData wxe_batch_caller = 0;
ErlDrvTermData init_caller = 0;
-// extern opengl
+// extern opengl
void gl_dispatch(int op, char *bp, ErlDrvTermData caller, WXEBinRef *bins[]);
@@ -99,7 +99,7 @@ void *wxe_main_loop(void * );
* START AND STOP of driver thread
* ************************************************************/
-int load_native_gui()
+int load_native_gui()
{
return 1;
}
@@ -112,7 +112,7 @@ int start_native_gui(wxe_data *sd)
wxe_batch_locker_m = erl_drv_mutex_create((char *)"wxe_batch_locker_m");
wxe_batch_locker_c = erl_drv_cond_create((char *)"wxe_batch_locker_c");
- init_caller = driver_connected(sd->port);
+ init_caller = driver_connected(sd->port);
#ifdef __DARWIN__
res = erl_drv_steal_main_thread((char *)"wxwidgets",
@@ -152,9 +152,9 @@ void stop_native_gui(wxe_data *sd)
erl_drv_cond_destroy(wxe_batch_locker_c);
}
-void unload_native_gui()
+void unload_native_gui()
{
-
+
}
/* ************************************************************
@@ -162,13 +162,13 @@ void unload_native_gui()
* Called by emulator thread
* ************************************************************/
-void push_command(int op,char * buf,int len, wxe_data *sd)
-{
+void push_command(int op,char * buf,int len, wxe_data *sd)
+{
// fprintf(stderr, "Op %d %d\r\n", op, (int) driver_caller(sd->port)),fflush(stderr);
wxeCommand *Cmd = new wxeCommand(op, buf, len, sd);
erl_drv_mutex_lock(wxe_batch_locker_m);
wxe_batch->Append(Cmd);
-
+
if(wxe_batch_caller > 0) {
// wx-thread is waiting on batch end in cond_wait
erl_drv_cond_signal(wxe_batch_locker_c);
@@ -179,11 +179,11 @@ void push_command(int op,char * buf,int len, wxe_data *sd)
}
erl_drv_cond_signal(wxe_batch_locker_c);
wxWakeUpIdle();
- }
+ }
erl_drv_mutex_unlock(wxe_batch_locker_m);
}
-void meta_command(int what, wxe_data *sd) {
+void meta_command(int what, wxe_data *sd) {
if(what == PING_PORT) {
erl_drv_mutex_lock(wxe_batch_locker_m);
if(wxe_batch_caller > 0) {
@@ -203,17 +203,17 @@ void meta_command(int what, wxe_data *sd) {
}
/* ************************************************************
- * wxWidgets Thread
+ * wxWidgets Thread
* ************************************************************/
void *wxe_main_loop(void *vpdl)
{
- int result;
+ int result;
int argc = 1;
char * temp = (char *) "Erlang";
char * argv[] = {temp,NULL};
ErlDrvPDL pdl = (ErlDrvPDL) vpdl;
-
+
driver_pdl_inc_refc(pdl);
// ErlDrvSysInfo einfo;
@@ -223,7 +223,7 @@ void *wxe_main_loop(void *vpdl)
#ifndef _WIN32
erts_thread_disable_fpe();
#endif
-
+
result = wxEntry(argc, argv);
// fprintf(stderr, "WXWidgets quits main loop %d \r\n", result);
if(result >= 0 && wxe_status == WXE_INITIATED) {
@@ -240,17 +240,17 @@ void *wxe_main_loop(void *vpdl)
erl_drv_cond_signal(wxe_status_c);
erl_drv_mutex_unlock(wxe_status_m);
driver_pdl_dec_refc(pdl);
- return NULL;
+ return NULL;
}
}
wxFrame * dummy_window;
void create_dummy_window() {
- dummy_window = new wxFrame(NULL,-1, wxT("wx driver"),
- wxDefaultPosition, wxSize(5,5),
+ dummy_window = new wxFrame(NULL,-1, wxT("wx driver"),
+ wxDefaultPosition, wxSize(5,5),
wxFRAME_NO_TASKBAR);
- dummy_window->Connect(wxID_ANY, wxEVT_CLOSE_WINDOW,
+ dummy_window->Connect(wxID_ANY, wxEVT_CLOSE_WINDOW,
(wxObjectEventFunction) (wxEventFunction) &WxeApp::dummy_close);
}
@@ -262,7 +262,7 @@ void WxeApp::dummy_close(wxEvent& Ev) {
create_dummy_window();
}
-// Init wx-widgets thread
+// Init wx-widgets thread
bool WxeApp::OnInit()
{
wxe_ps_init();
@@ -270,16 +270,17 @@ bool WxeApp::OnInit()
global_me = new wxeMemEnv();
wxe_batch = new wxList;
wxe_batch_cb_saved = new wxList;
+ cb_buff = NULL;
wxIdleEvent::SetMode(wxIDLE_PROCESS_SPECIFIED);
- this->Connect(wxID_ANY, wxEVT_IDLE,
+ this->Connect(wxID_ANY, wxEVT_IDLE,
(wxObjectEventFunction) (wxEventFunction) &WxeApp::idle);
- this->Connect(CREATE_PORT, wxeEVT_META_COMMAND,
+ this->Connect(CREATE_PORT, wxeEVT_META_COMMAND,
(wxObjectEventFunction) (wxEventFunction) &WxeApp::newMemEnv);
- this->Connect(DELETE_PORT, wxeEVT_META_COMMAND,
+ this->Connect(DELETE_PORT, wxeEVT_META_COMMAND,
(wxObjectEventFunction) (wxEventFunction) &WxeApp::destroyMemEnv);
- this->Connect(WXE_SHUTDOWN, wxeEVT_META_COMMAND,
+ this->Connect(WXE_SHUTDOWN, wxeEVT_META_COMMAND,
(wxObjectEventFunction) (wxEventFunction) &WxeApp::shutdown);
// fprintf(stderr, "Size void* %d: long %d long long %d int64 %d \r\n",
@@ -287,9 +288,9 @@ bool WxeApp::OnInit()
initEventTable();
wxInitAllImageHandlers();
- /* Create a dummy window so wxWidgets don't automagicly quits the main loop
+ /* Create a dummy window so wxWidgets don't automagicly quits the main loop
after the last window */
- create_dummy_window();
+ create_dummy_window();
init_nonconsts(global_me, init_caller);
erl_drv_mutex_lock(wxe_status_m);
@@ -308,19 +309,19 @@ void send_msg(const char * type, wxString * msg) {
wxeReturn rt = wxeReturn(WXE_DRV_PORT, init_caller);
rt.addAtom((char *) "wxe_driver");
rt.addAtom((char *) type);
- rt.add(msg);
+ rt.add(msg);
rt.addTupleCount(3);
rt.send();
}
/* ************************************************************
- * Erlang Command execution *
+ * Erlang Command execution *
* ************************************************************/
-/* Callback from printer and event callbacks */
+/* Callback from printer and event callbacks */
void pre_callback()
{
- // no-op
+ // no-op
}
void handle_event_callback(ErlDrvPort port, ErlDrvTermData process)
@@ -330,29 +331,19 @@ void handle_event_callback(ErlDrvPort port, ErlDrvTermData process)
driver_monitor_process(port, process, &monitor);
// Should we be able to handle commands when recursing? probably
erl_drv_mutex_lock(wxe_batch_locker_m);
- //fprintf(stderr, "\r\nCB Start ");fflush(stderr);
+ // fprintf(stderr, "\r\nCB EV Start ");fflush(stderr);
app->dispatch_cb(wxe_batch, wxe_batch_cb_saved, process);
- //fprintf(stderr, ".. done \r\n");fflush(stderr);
+ // fprintf(stderr, ".. done \r\n");fflush(stderr);
wxe_batch_caller = 0;
erl_drv_mutex_unlock(wxe_batch_locker_m);
driver_demonitor_process(port, &monitor);
}
-void handle_callback_batch(ErlDrvPort port)
-{
- WxeApp * app = (WxeApp *) wxTheApp;
- // Should we be able to handle commands when recursing? probably
- erl_drv_mutex_lock(wxe_batch_locker_m);
- app->dispatch(wxe_batch, 0, WXE_CALLBACK);
- wxe_batch_caller = 0;
- erl_drv_mutex_unlock(wxe_batch_locker_m);
-}
-
// Called by wx thread
void WxeApp::idle(wxIdleEvent& event) {
dispatch_cmds();
}
-
+
void WxeApp::dispatch_cmds() {
erl_drv_mutex_lock(wxe_batch_locker_m);
int level = dispatch(wxe_batch_cb_saved, 0, WXE_STORED);
@@ -361,14 +352,14 @@ void WxeApp::dispatch_cmds() {
erl_drv_mutex_unlock(wxe_batch_locker_m);
}
-// Should have erl_drv_mutex_lock(wxe_batch_locker_m);
-// when entering this function and it should be released
+// Should have erl_drv_mutex_lock(wxe_batch_locker_m);
+// when entering this function and it should be released
// afterwards
-int WxeApp::dispatch(wxList * batch, int blevel, int list_type)
+int WxeApp::dispatch(wxList * batch, int blevel, int list_type)
{
int ping = 0;
// erl_drv_mutex_lock(wxe_batch_locker_m); must be locked already
- while(true)
+ while(true)
{
if (batch->size() > 0) {
for( wxList::compatibility_iterator node = batch->GetFirst();
@@ -385,19 +376,22 @@ int WxeApp::dispatch(wxList * batch, int blevel, int list_type)
{blevel++; }
break;
case WXE_DEBUG_PING:
- // When in debugger we don't want to hang waiting for a BATCH_END
+ // When in debugger we don't want to hang waiting for a BATCH_END
// that never comes, because a breakpoint have hit.
ping++;
- if(ping > 2)
+ if(ping > 2)
blevel = 0;
break;
case WXE_CB_RETURN:
// erl_drv_mutex_unlock(wxe_batch_locker_m); should be called after
// whatever cleaning is necessary
- memcpy(cb_buff, event->buffer, event->len);
+ if(event->len > 0) {
+ cb_buff = (char *) driver_alloc(event->len);
+ memcpy(cb_buff, event->buffer, event->len);
+ }
return blevel;
default:
- erl_drv_mutex_unlock(wxe_batch_locker_m);
+ erl_drv_mutex_unlock(wxe_batch_locker_m);
if(event->op < OPENGL_START) {
// fprintf(stderr, " c %d (%d) \r\n", event->op, blevel);
wxe_dispatch(*event);
@@ -436,10 +430,10 @@ void WxeApp::dispatch_cb(wxList * batch, wxList * temp, ErlDrvTermData process)
wxeCommand *event = (wxeCommand *)node->GetData();
wxeMemEnv *memenv = getMemEnv(event->port);
batch->Erase(node);
- if(event->caller == process || // Callbacks from CB process only
+ 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.
- (memenv && event->caller == memenv->owner))
+ (memenv && event->caller == memenv->owner))
{
switch(event->op) {
case WXE_BATCH_END:
@@ -447,7 +441,10 @@ void WxeApp::dispatch_cb(wxList * batch, wxList * temp, ErlDrvTermData process)
case WXE_DEBUG_PING:
break;
case WXE_CB_RETURN:
- memcpy(cb_buff, event->buffer, event->len);
+ if(event->len > 0) {
+ cb_buff = (char *) driver_alloc(event->len);
+ memcpy(cb_buff, event->buffer, event->len);
+ }
callback_returned = 1;
return;
case WXE_CB_START:
@@ -464,12 +461,12 @@ void WxeApp::dispatch_cb(wxList * batch, wxList * temp, ErlDrvTermData process)
}
erl_drv_mutex_lock(wxe_batch_locker_m);
break;
- if(callback_returned)
+ if(callback_returned)
return;
}
delete event;
} else {
- // fprintf(stderr, " sav %d \r\n", event->op);
+ // fprintf(stderr, " save %d \r\n", event->op);
temp->Append(event);
}
}
@@ -494,13 +491,13 @@ void WxeApp::newMemEnv(wxeMetaCommand& Ecmd) {
driver_pdl_inc_refc(Ecmd.pdl);
for(int i = 0; i < global_me->next; i++) {
- memenv->ref2ptr[i] = global_me->ref2ptr[i];
+ memenv->ref2ptr[i] = global_me->ref2ptr[i];
}
memenv->next = global_me->next;
refmap[(ErlDrvTermData) Ecmd.port] = memenv;
memenv->owner = Ecmd.caller;
- ErlDrvTermData rt[] = {ERL_DRV_ATOM, driver_mk_atom((char *)"wx_port_initiated")};
+ ErlDrvTermData rt[] = {ERL_DRV_ATOM, driver_mk_atom((char *)"wx_port_initiated")};
driver_send_term(WXE_DRV_PORT,Ecmd.caller,rt,2);
}
@@ -519,13 +516,13 @@ void WxeApp::destroyMemEnv(wxeMetaCommand& Ecmd) {
// pre-pass delete all dialogs first since they might crash erlang otherwise
for(int i=1; i < memenv->next; i++) {
wxObject * ptr = (wxObject *) memenv->ref2ptr[i];
- if(ptr) {
+ if(ptr) {
ptrMap::iterator it = ptr2ref.find(ptr);
if(it != ptr2ref.end()) {
wxeRefData *refd = it->second;
if(refd->alloc_in_erl) {
if(refd->type == 2) {
- wxDialog *win = (wxDialog *) ptr;
+ wxDialog *win = (wxDialog *) ptr;
if(win->IsModal()) {
win->EndModal(-1);
}
@@ -535,25 +532,25 @@ void WxeApp::destroyMemEnv(wxeMetaCommand& Ecmd) {
if(parentRef == ptr2ref.end()) {
// The parent is already dead delete the parent ref
win->SetParent(NULL);
- }
+ }
}
delete win;
- }
+ }
}
}
}
}
- // First pass, delete all top parents/windows of all linked objects
+ // First pass, delete all top parents/windows of all linked objects
// fprintf(stderr, "close port %x\r\n", Ecmd.port);fflush(stderr);
for(int i=1; i < memenv->next; i++) {
void * ptr = memenv->ref2ptr[i];
- if(ptr) {
+ if(ptr) {
ptrMap::iterator it = ptr2ref.find(ptr);
if(it != ptr2ref.end()) {
wxeRefData *refd = it->second;
if(refd->alloc_in_erl && refd->type == 0) {
- parent = (wxWindow *) ptr;
+ parent = (wxWindow *) ptr;
// fprintf(stderr, "window %x %d\r\n", (int) parent, refd->ref);
while(parent->GetParent()) {
parent = parent->GetParent();
@@ -573,7 +570,7 @@ void WxeApp::destroyMemEnv(wxeMetaCommand& Ecmd) {
// everything linked from windows should now be deleted
for(int i=1; i < memenv->next; i++) {
void * ptr = memenv->ref2ptr[i];
- if(ptr) {
+ if(ptr) {
ptrMap::iterator it = ptr2ref.find(ptr);
if(it != ptr2ref.end()) {
wxeRefData *refd = it->second;
@@ -585,33 +582,33 @@ void WxeApp::destroyMemEnv(wxeMetaCommand& Ecmd) {
wxString msg;
if((refd->type == 0)) { // Maybe also class 1
wxClassInfo *cinfo = ((wxObject *)ptr)->GetClassInfo();
- msg.Printf(wxT("Memory leak: {wx_ref, %d, %s}"),
+ msg.Printf(wxT("Memory leak: {wx_ref, %d, %s}"),
refd->ref, cinfo->GetClassName());
send_msg("error", &msg);
} else {
delete_object(ptr, refd);
}
- if(type == 0 || type > 3) {
- // Delete refs for leaks and non overridden allocs
+ if(type == 0 || type > 2) {
+ // Delete refs for leaks and non overridden allocs
delete refd;
ptr2ref.erase(it);
} // overridden allocs deletes meta-data in clearPtr
} else { // Not alloced in erl just delete references
if(refd->ref >= global_me->next) { // if it is not part of global ptrs
- delete refd;
+ delete refd;
ptr2ref.erase(it);
}
}
}
}
- }
- // Assert ?
-// for(ptrMap::iterator it = ptr2ref.begin(); it != ptr2ref.end(); it++) {
-// wxeRefData *refd = it->second;
-// if(refd->ref >= global_me->next)
-// fprintf(stderr, "L %d %d\r\n", refd->ref, refd->alloc_in_erl);
-// }
-// fflush(stderr);
+ }
+// // Assert ?
+// for(ptrMap::iterator it = ptr2ref.begin(); it != ptr2ref.end(); it++) {
+// wxeRefData *refd = it->second;
+// if(refd->ref >= global_me->next)
+// fprintf(stderr, "L %d %d %d\r\n", refd->ref, refd->type, refd->alloc_in_erl);
+// }
+// fflush(stderr);
delete memenv;
driver_pdl_dec_refc(Ecmd.pdl);
refmap.erase((ErlDrvTermData) Ecmd.port);
@@ -624,7 +621,7 @@ wxeMemEnv * WxeApp::getMemEnv(ErlDrvPort port) {
int WxeApp::newPtr(void * ptr, int type, wxeMemEnv *memenv) {
int ref;
intList free = memenv->free;
-
+
if(free.IsEmpty()) {
ref = memenv->next++;
} else {
@@ -632,8 +629,8 @@ int WxeApp::newPtr(void * ptr, int type, wxeMemEnv *memenv) {
};
if(ref >= memenv->max) {
memenv->max *= 2;
- memenv->ref2ptr =
- (void **) driver_realloc(memenv->ref2ptr,memenv->max * sizeof(void*));
+ memenv->ref2ptr =
+ (void **) driver_realloc(memenv->ref2ptr,memenv->max * sizeof(void*));
}
memenv->ref2ptr[ref] = ptr;
@@ -653,12 +650,12 @@ int WxeApp::getRef(void * ptr, wxeMemEnv *memenv) {
ptrMap::iterator it = ptr2ref.find(ptr);
if(it != ptr2ref.end()) {
wxeRefData *refd = it->second;
- if(refd->memenv == memenv) {
+ if(refd->memenv == memenv || refd->memenv == global_me) {
// Found it return
return refd->ref;
} // else
// Old reference to deleted object, release old and recreate in current memenv.
- clearPtr(ptr);
+ ptr2ref.erase(it);
}
int ref;
intList free = memenv->free;
@@ -687,7 +684,7 @@ void WxeApp::clearPtr(void * ptr) {
if(it != ptr2ref.end()) {
wxeRefData *refd = it->second;
intList free = refd->memenv->free;
- int ref = refd->ref;
+ int ref = refd->ref;
refd->memenv->ref2ptr[ref] = NULL;
free.Append(ref);
@@ -696,7 +693,7 @@ void WxeApp::clearPtr(void * ptr) {
msg.Printf(wxT("Deleting {wx_ref, %d, unknown} at %p "), ref, ptr);
send_msg("debug", &msg);
}
-
+
if(((int) refd->pid) != -1) {
// Send terminate pid to owner
wxeReturn rt = wxeReturn(WXE_DRV_PORT,refd->memenv->owner, false);
@@ -709,30 +706,30 @@ void WxeApp::clearPtr(void * ptr) {
if(refd->type == 1 && ((wxObject*)ptr)->IsKindOf(CLASSINFO(wxSizer))) {
wxSizerItemList list = ((wxSizer*)ptr)->GetChildren();
for(wxSizerItemList::compatibility_iterator node = list.GetFirst();
- node; node = node->GetNext()) {
+ node; node = node->GetNext()) {
wxSizerItem *item = node->GetData();
wxObject *content=NULL;
- if((content = item->GetWindow()))
+ if((content = item->GetWindow()))
if(ptr2ref.end() == ptr2ref.find(content)) {
wxString msg;
wxClassInfo *cinfo = ((wxObject *)ptr)->GetClassInfo();
msg.Printf(wxT("Double usage detected of window at %p in sizer {wx_ref, %d, %s}"),
content, ref, cinfo->GetClassName());
send_msg("error", &msg);
- ((wxSizer*)ptr)->Detach((wxWindow*)content);
+ ((wxSizer*)ptr)->Detach((wxWindow*)content);
}
- if((content = item->GetSizer()))
+ if((content = item->GetSizer()))
if(ptr2ref.end() == ptr2ref.find(content)) {
wxString msg;
wxClassInfo *cinfo = ((wxObject *)ptr)->GetClassInfo();
msg.Printf(wxT("Double usage detected of sizer at %p in sizer {wx_ref, %d, %s}"),
content, ref, cinfo->GetClassName());
send_msg("error", &msg);
- ((wxSizer*)ptr)->Detach((wxSizer*)content);
+ ((wxSizer*)ptr)->Detach((wxSizer*)content);
}
}
}
-
+
delete refd;
ptr2ref.erase(it);
}
@@ -753,7 +750,7 @@ void * WxeApp::getPtr(char * bp, wxeMemEnv *memenv) {
void WxeApp::registerPid(char * bp, ErlDrvTermData pid, wxeMemEnv * memenv) {
int index = *(int *) bp;
- if(!memenv)
+ if(!memenv)
throw wxe_badarg(index);
void * temp = memenv->ref2ptr[index];
if((index < memenv->next) && ((index == 0) || (temp > NULL))) {
@@ -773,14 +770,14 @@ void WxeApp::registerPid(char * bp, ErlDrvTermData pid, wxeMemEnv * memenv) {
* Misc utility classes
* ************************************************************/
-/* ****************************************************************************
- * Memory handling
+/* ****************************************************************************
+ * Memory handling
* ****************************************************************************/
wxeMemEnv::wxeMemEnv() {
- ref2ptr = (void **) driver_alloc(128*sizeof(void *));
+ ref2ptr = (void **) driver_alloc(128*sizeof(void *));
ref2ptr[0] = NULL;
- next = 1;
+ next = 1;
max = 128;
}
@@ -788,12 +785,12 @@ wxeMemEnv::~wxeMemEnv() {
driver_free(ref2ptr);
}
-/* ****************************************************************************
+/* ****************************************************************************
* Erlang Commands (don't need to be derived of wxEvent anymore should
* be re-written to own class struct)
* ****************************************************************************/
-wxeCommand::wxeCommand(int fc,char * cbuf,int buflen, wxe_data *sd)
+wxeCommand::wxeCommand(int fc,char * cbuf,int buflen, wxe_data *sd)
: wxObject()
{
WXEBinRef *temp, *start, *prev;
@@ -809,12 +806,12 @@ wxeCommand::wxeCommand(int fc,char * cbuf,int buflen, wxe_data *sd)
if(cbuf) {
buffer = (char *) driver_alloc(len);
memcpy((void *) buffer, (void *) cbuf, len);;
-
+
temp = sd->bin;
-
+
prev = NULL;
start = temp;
-
+
while(temp) {
if(caller == temp->from) {
bin[n++] = temp;
@@ -839,7 +836,7 @@ wxeCommand::~wxeCommand() {
int n = 0;
if(buffer) {
while(bin[n]) {
- if(bin[n]->bin)
+ if(bin[n]->bin)
driver_free_binary(bin[n]->bin);
driver_free(bin[n++]);
}
@@ -847,26 +844,26 @@ wxeCommand::~wxeCommand() {
}
}
-/* ****************************************************************************
- * TreeItemData
+/* ****************************************************************************
+ * TreeItemData
* ****************************************************************************/
-wxETreeItemData::wxETreeItemData(int sz, char * data) {
+wxETreeItemData::wxETreeItemData(int sz, char * data) {
size = sz;
bin = (char *) driver_alloc(sz);
memcpy(bin, data, sz);
}
-wxETreeItemData::~wxETreeItemData()
+wxETreeItemData::~wxETreeItemData()
{
driver_free(bin);
}
-/* ****************************************************************************
+/* ****************************************************************************
* CallbackData *
* ****************************************************************************/
-wxeCallbackData::wxeCallbackData(ErlDrvTermData caller,void * req, char *req_type,
+wxeCallbackData::wxeCallbackData(ErlDrvTermData caller,void * req, char *req_type,
int funcb, int skip_ev, wxeErlTerm * userData)
: wxObject()
{
@@ -893,8 +890,6 @@ int wxCALLBACK wxEListCtrlCompare(long item1, long item2, long callbackInfoPtr)
{
callbackInfo * cb = (callbackInfo *)callbackInfoPtr;
wxeMemEnv * memenv = ((WxeApp *) wxTheApp)->getMemEnv(cb->port);
- char * bp = ((WxeApp *) wxTheApp)->cb_buff;
-
wxeReturn rt = wxeReturn(WXE_DRV_PORT, memenv->owner, false);
rt.addInt(cb->callbackID);
rt.addInt(item1);
@@ -903,6 +898,13 @@ int wxCALLBACK wxEListCtrlCompare(long item1, long item2, long callbackInfoPtr)
rt.addAtom("_wx_invoke_cb_");
rt.addTupleCount(3);
rt.send();
- handle_callback_batch(cb->port);
- return *(int*) bp;
+ handle_event_callback(cb->port, memenv->owner);
+
+ if(((WxeApp *) wxTheApp)->cb_buff) {
+ int res = * (int*) ((WxeApp *) wxTheApp)->cb_buff;
+ driver_free(((WxeApp *) wxTheApp)->cb_buff);
+ ((WxeApp *) wxTheApp)->cb_buff = NULL;
+ return res;
+ }
+ return 0;
}
diff --git a/lib/wx/c_src/wxe_impl.h b/lib/wx/c_src/wxe_impl.h
index 39c02f8c1a..ee31068d5d 100644
--- a/lib/wx/c_src/wxe_impl.h
+++ b/lib/wx/c_src/wxe_impl.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2010. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2011. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -178,7 +178,8 @@ public:
wxeMemEnv * global_me;
// Temp container for callbacks
- char cb_buff[256];
+ char *cb_buff;
+ int cb_len;
};
class wxETreeItemData : public wxTreeItemData
@@ -194,7 +195,6 @@ class wxETreeItemData : public wxTreeItemData
bool sendevent(wxEvent * event, ErlDrvPort port);
void pre_callback();
-void handle_callback_batch(ErlDrvPort port); // For wxePrintout
void handle_event_callback(ErlDrvPort port, ErlDrvTermData process);
void activateGL(ErlDrvTermData caller);
@@ -232,8 +232,6 @@ class wxEPrintout : public wxPrintout
bool OnPrintPage(int page);
void GetPageInfo(int *minPage, int *maxPage, int *pageFrom, int *pageTo);
- void clear_cb(int callback);
-
int onPrintPage;
int onPreparePrinting;
int onBeginPrinting;
@@ -246,6 +244,9 @@ class wxEPrintout : public wxPrintout
ErlDrvPort port;
};
+void clear_cb(ErlDrvPort port, int callback);
+
+
// Implementation of wxListCtrlCompare
struct callbackInfo {
ErlDrvPort port;
diff --git a/lib/wx/doc/src/notes.xml b/lib/wx/doc/src/notes.xml
index 3d27cf671b..7bd8d18592 100644
--- a/lib/wx/doc/src/notes.xml
+++ b/lib/wx/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2009</year><year>2010</year>
+ <year>2009</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,55 @@
<p>This document describes the changes made to the wxErlang
application.</p>
+<section><title>Wx 0.99</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ wx: fix obsolete guard warning (list/1) (Thanks to Tuncer
+ Ayaz)</p>
+ <p>
+ Own Id: OTP-9513</p>
+ </item>
+ <item>
+ <p> XML files have been corrected. </p>
+ <p>
+ Own Id: OTP-9550 Aux Id: OTP-9541 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Support virtual tables in wxListCtrl.</p>
+ <p>
+ Own Id: OTP-9415</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Wx 0.98.10</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed wx app files on mac and solaris. Thanks Jachym
+ Holecek and Joe Williams.</p>
+ <p>
+ Own Id: OTP-9324</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Wx 0.98.9</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/wx/examples/demo/ex_listCtrl.erl b/lib/wx/examples/demo/ex_listCtrl.erl
index c574c7247a..3faec4e229 100644
--- a/lib/wx/examples/demo/ex_listCtrl.erl
+++ b/lib/wx/examples/demo/ex_listCtrl.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, 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(ex_listCtrl).
@@ -25,7 +25,7 @@
-export([start/1, init/1, terminate/2, code_change/3,
handle_info/2, handle_call/3, handle_event/2]).
--record(state,
+-record(state,
{
parent,
config,
@@ -40,11 +40,11 @@ init(Config) ->
wx:batch(fun() -> do_init(Config) end).
do_init(Config) ->
- Parent = proplists:get_value(parent, Config),
+ Parent = proplists:get_value(parent, Config),
Panel = wxPanel:new(Parent, []),
%% Setup sizers
- MainSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ MainSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
[{label, "wxListCtrl"}]),
Notebook = wxNotebook:new(Panel, 1, [{style, ?wxBK_DEFAULT}]),
@@ -81,14 +81,46 @@ do_init(Config) ->
wxListCtrl:setItemBackgroundColour(ListCtrl3,3,?wxGREEN),
wxListCtrl:setItemBackgroundColour(ListCtrl3,0,?wxCYAN),
+ IA = wxListItemAttr:new(),
+ wxListItemAttr:setTextColour(IA, {190, 25, 25}),
+ LC4Opts = [{style, ?wxLC_REPORT bor ?wxLC_VIRTUAL},
+ {onGetItemText, fun(_This, Item, 0) ->
+ "Row " ++ integer_to_list(Item);
+ (_, Item, 1) when Item rem 5 == 0 ->
+ "Column 2";
+ (_, _, _) -> ""
+ end},
+ {onGetItemAttr, fun(_This, Item) when Item rem 3 == 0 ->
+ IA;
+ (_This, _Item) ->
+ wx:typeCast(wx:null(), wxListItemAttr)
+ end},
+ {onGetItemColumnImage, fun(_This, Item, 1) ->
+ Item rem 4;
+ (_, _, _) ->
+ -1
+ end}
+ ],
+ ListCtrl4 = wxListCtrl:new(Notebook, LC4Opts),
+ wxListCtrl:setImageList(ListCtrl4, IL, ?wxIMAGE_LIST_SMALL),
+
+ wxListCtrl:insertColumn(ListCtrl4, 0, "Column 1"),
+ wxListCtrl:insertColumn(ListCtrl4, 1, "Column 2"),
+ wxListCtrl:setColumnWidth(ListCtrl4, 0, 200),
+ wxListCtrl:setColumnWidth(ListCtrl4, 1, 200),
+ wxListCtrl:setItemCount(ListCtrl4, 1000000),
+
+
wxListCtrl:connect(ListCtrl1, command_list_item_selected, []),
wxListCtrl:connect(ListCtrl2, command_list_item_selected, []),
wxListCtrl:connect(ListCtrl3, command_list_item_selected, []),
+ wxListCtrl:connect(ListCtrl4, command_list_item_selected, []),
%% Add to sizers
wxNotebook:addPage(Notebook, ListCtrl1, "List", []),
wxNotebook:addPage(Notebook, ListCtrl2, "Report", []),
wxNotebook:addPage(Notebook, ListCtrl3, "Colored multiselect", []),
+ wxNotebook:addPage(Notebook, ListCtrl4, "Virtual Report", []),
wxSizer:add(MainSizer, Notebook, [{proportion, 1},
{flag, ?wxEXPAND}]),
@@ -145,4 +177,4 @@ create_list_ctrl(Win, Options) ->
ListCtrl.
-
+
diff --git a/lib/wx/include/gl.hrl b/lib/wx/include/gl.hrl
index 52f2635af9..54eb551285 100644
--- a/lib/wx/include/gl.hrl
+++ b/lib/wx/include/gl.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The 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,32 +21,22 @@
%% This file is generated DO NOT EDIT
-define(GL_VERSION_1_1, 1).
--define(GL_CURRENT_BIT, 16#1).
--define(GL_POINT_BIT, 16#2).
--define(GL_LINE_BIT, 16#4).
--define(GL_POLYGON_BIT, 16#8).
--define(GL_POLYGON_STIPPLE_BIT, 16#10).
--define(GL_PIXEL_MODE_BIT, 16#20).
--define(GL_LIGHTING_BIT, 16#40).
--define(GL_FOG_BIT, 16#80).
--define(GL_DEPTH_BUFFER_BIT, 16#100).
--define(GL_ACCUM_BUFFER_BIT, 16#200).
--define(GL_STENCIL_BUFFER_BIT, 16#400).
--define(GL_VIEWPORT_BIT, 16#800).
--define(GL_TRANSFORM_BIT, 16#1000).
--define(GL_ENABLE_BIT, 16#2000).
--define(GL_COLOR_BUFFER_BIT, 16#4000).
--define(GL_HINT_BIT, 16#8000).
--define(GL_EVAL_BIT, 16#10000).
--define(GL_LIST_BIT, 16#20000).
--define(GL_TEXTURE_BIT, 16#40000).
--define(GL_SCISSOR_BIT, 16#80000).
--define(GL_ALL_ATTRIB_BITS, 16#FFFFFFFF).
--define(GL_CLIENT_PIXEL_STORE_BIT, 16#1).
--define(GL_CLIENT_VERTEX_ARRAY_BIT, 16#2).
--define(GL_CLIENT_ALL_ATTRIB_BITS, 16#FFFFFFFF).
--define(GL_FALSE, 0).
--define(GL_TRUE, 1).
+-define(GL_VERSION_1_2, 1).
+-define(GL_VERSION_1_3, 1).
+-define(GL_ARB_imaging, 1).
+-define(GL_FALSE, 16#0).
+-define(GL_TRUE, 16#1).
+-define(GL_BYTE, 16#1400).
+-define(GL_UNSIGNED_BYTE, 16#1401).
+-define(GL_SHORT, 16#1402).
+-define(GL_UNSIGNED_SHORT, 16#1403).
+-define(GL_INT, 16#1404).
+-define(GL_UNSIGNED_INT, 16#1405).
+-define(GL_FLOAT, 16#1406).
+-define(GL_2_BYTES, 16#1407).
+-define(GL_3_BYTES, 16#1408).
+-define(GL_4_BYTES, 16#1409).
+-define(GL_DOUBLE, 16#140A).
-define(GL_POINTS, 16#0).
-define(GL_LINES, 16#1).
-define(GL_LINE_LOOP, 16#2).
@@ -57,11 +47,85 @@
-define(GL_QUADS, 16#7).
-define(GL_QUAD_STRIP, 16#8).
-define(GL_POLYGON, 16#9).
--define(GL_ACCUM, 16#100).
--define(GL_LOAD, 16#101).
--define(GL_RETURN, 16#102).
--define(GL_MULT, 16#103).
--define(GL_ADD, 16#104).
+-define(GL_VERTEX_ARRAY, 16#8074).
+-define(GL_NORMAL_ARRAY, 16#8075).
+-define(GL_COLOR_ARRAY, 16#8076).
+-define(GL_INDEX_ARRAY, 16#8077).
+-define(GL_TEXTURE_COORD_ARRAY, 16#8078).
+-define(GL_EDGE_FLAG_ARRAY, 16#8079).
+-define(GL_VERTEX_ARRAY_SIZE, 16#807A).
+-define(GL_VERTEX_ARRAY_TYPE, 16#807B).
+-define(GL_VERTEX_ARRAY_STRIDE, 16#807C).
+-define(GL_NORMAL_ARRAY_TYPE, 16#807E).
+-define(GL_NORMAL_ARRAY_STRIDE, 16#807F).
+-define(GL_COLOR_ARRAY_SIZE, 16#8081).
+-define(GL_COLOR_ARRAY_TYPE, 16#8082).
+-define(GL_COLOR_ARRAY_STRIDE, 16#8083).
+-define(GL_INDEX_ARRAY_TYPE, 16#8085).
+-define(GL_INDEX_ARRAY_STRIDE, 16#8086).
+-define(GL_TEXTURE_COORD_ARRAY_SIZE, 16#8088).
+-define(GL_TEXTURE_COORD_ARRAY_TYPE, 16#8089).
+-define(GL_TEXTURE_COORD_ARRAY_STRIDE, 16#808A).
+-define(GL_EDGE_FLAG_ARRAY_STRIDE, 16#808C).
+-define(GL_VERTEX_ARRAY_POINTER, 16#808E).
+-define(GL_NORMAL_ARRAY_POINTER, 16#808F).
+-define(GL_COLOR_ARRAY_POINTER, 16#8090).
+-define(GL_INDEX_ARRAY_POINTER, 16#8091).
+-define(GL_TEXTURE_COORD_ARRAY_POINTER, 16#8092).
+-define(GL_EDGE_FLAG_ARRAY_POINTER, 16#8093).
+-define(GL_V2F, 16#2A20).
+-define(GL_V3F, 16#2A21).
+-define(GL_C4UB_V2F, 16#2A22).
+-define(GL_C4UB_V3F, 16#2A23).
+-define(GL_C3F_V3F, 16#2A24).
+-define(GL_N3F_V3F, 16#2A25).
+-define(GL_C4F_N3F_V3F, 16#2A26).
+-define(GL_T2F_V3F, 16#2A27).
+-define(GL_T4F_V4F, 16#2A28).
+-define(GL_T2F_C4UB_V3F, 16#2A29).
+-define(GL_T2F_C3F_V3F, 16#2A2A).
+-define(GL_T2F_N3F_V3F, 16#2A2B).
+-define(GL_T2F_C4F_N3F_V3F, 16#2A2C).
+-define(GL_T4F_C4F_N3F_V4F, 16#2A2D).
+-define(GL_MATRIX_MODE, 16#BA0).
+-define(GL_MODELVIEW, 16#1700).
+-define(GL_PROJECTION, 16#1701).
+-define(GL_TEXTURE, 16#1702).
+-define(GL_POINT_SMOOTH, 16#B10).
+-define(GL_POINT_SIZE, 16#B11).
+-define(GL_POINT_SIZE_GRANULARITY, 16#B13).
+-define(GL_POINT_SIZE_RANGE, 16#B12).
+-define(GL_LINE_SMOOTH, 16#B20).
+-define(GL_LINE_STIPPLE, 16#B24).
+-define(GL_LINE_STIPPLE_PATTERN, 16#B25).
+-define(GL_LINE_STIPPLE_REPEAT, 16#B26).
+-define(GL_LINE_WIDTH, 16#B21).
+-define(GL_LINE_WIDTH_GRANULARITY, 16#B23).
+-define(GL_LINE_WIDTH_RANGE, 16#B22).
+-define(GL_POINT, 16#1B00).
+-define(GL_LINE, 16#1B01).
+-define(GL_FILL, 16#1B02).
+-define(GL_CW, 16#900).
+-define(GL_CCW, 16#901).
+-define(GL_FRONT, 16#404).
+-define(GL_BACK, 16#405).
+-define(GL_POLYGON_MODE, 16#B40).
+-define(GL_POLYGON_SMOOTH, 16#B41).
+-define(GL_POLYGON_STIPPLE, 16#B42).
+-define(GL_EDGE_FLAG, 16#B43).
+-define(GL_CULL_FACE, 16#B44).
+-define(GL_CULL_FACE_MODE, 16#B45).
+-define(GL_FRONT_FACE, 16#B46).
+-define(GL_POLYGON_OFFSET_FACTOR, 16#8038).
+-define(GL_POLYGON_OFFSET_UNITS, 16#2A00).
+-define(GL_POLYGON_OFFSET_POINT, 16#2A01).
+-define(GL_POLYGON_OFFSET_LINE, 16#2A02).
+-define(GL_POLYGON_OFFSET_FILL, 16#8037).
+-define(GL_COMPILE, 16#1300).
+-define(GL_COMPILE_AND_EXECUTE, 16#1301).
+-define(GL_LIST_BASE, 16#B32).
+-define(GL_LIST_INDEX, 16#B33).
+-define(GL_LIST_MODE, 16#B30).
-define(GL_NEVER, 16#200).
-define(GL_LESS, 16#201).
-define(GL_EQUAL, 16#202).
@@ -70,8 +134,71 @@
-define(GL_NOTEQUAL, 16#205).
-define(GL_GEQUAL, 16#206).
-define(GL_ALWAYS, 16#207).
--define(GL_ZERO, 0).
--define(GL_ONE, 1).
+-define(GL_DEPTH_TEST, 16#B71).
+-define(GL_DEPTH_BITS, 16#D56).
+-define(GL_DEPTH_CLEAR_VALUE, 16#B73).
+-define(GL_DEPTH_FUNC, 16#B74).
+-define(GL_DEPTH_RANGE, 16#B70).
+-define(GL_DEPTH_WRITEMASK, 16#B72).
+-define(GL_DEPTH_COMPONENT, 16#1902).
+-define(GL_LIGHTING, 16#B50).
+-define(GL_LIGHT0, 16#4000).
+-define(GL_LIGHT1, 16#4001).
+-define(GL_LIGHT2, 16#4002).
+-define(GL_LIGHT3, 16#4003).
+-define(GL_LIGHT4, 16#4004).
+-define(GL_LIGHT5, 16#4005).
+-define(GL_LIGHT6, 16#4006).
+-define(GL_LIGHT7, 16#4007).
+-define(GL_SPOT_EXPONENT, 16#1205).
+-define(GL_SPOT_CUTOFF, 16#1206).
+-define(GL_CONSTANT_ATTENUATION, 16#1207).
+-define(GL_LINEAR_ATTENUATION, 16#1208).
+-define(GL_QUADRATIC_ATTENUATION, 16#1209).
+-define(GL_AMBIENT, 16#1200).
+-define(GL_DIFFUSE, 16#1201).
+-define(GL_SPECULAR, 16#1202).
+-define(GL_SHININESS, 16#1601).
+-define(GL_EMISSION, 16#1600).
+-define(GL_POSITION, 16#1203).
+-define(GL_SPOT_DIRECTION, 16#1204).
+-define(GL_AMBIENT_AND_DIFFUSE, 16#1602).
+-define(GL_COLOR_INDEXES, 16#1603).
+-define(GL_LIGHT_MODEL_TWO_SIDE, 16#B52).
+-define(GL_LIGHT_MODEL_LOCAL_VIEWER, 16#B51).
+-define(GL_LIGHT_MODEL_AMBIENT, 16#B53).
+-define(GL_FRONT_AND_BACK, 16#408).
+-define(GL_SHADE_MODEL, 16#B54).
+-define(GL_FLAT, 16#1D00).
+-define(GL_SMOOTH, 16#1D01).
+-define(GL_COLOR_MATERIAL, 16#B57).
+-define(GL_COLOR_MATERIAL_FACE, 16#B55).
+-define(GL_COLOR_MATERIAL_PARAMETER, 16#B56).
+-define(GL_NORMALIZE, 16#BA1).
+-define(GL_CLIP_PLANE0, 16#3000).
+-define(GL_CLIP_PLANE1, 16#3001).
+-define(GL_CLIP_PLANE2, 16#3002).
+-define(GL_CLIP_PLANE3, 16#3003).
+-define(GL_CLIP_PLANE4, 16#3004).
+-define(GL_CLIP_PLANE5, 16#3005).
+-define(GL_ACCUM_RED_BITS, 16#D58).
+-define(GL_ACCUM_GREEN_BITS, 16#D59).
+-define(GL_ACCUM_BLUE_BITS, 16#D5A).
+-define(GL_ACCUM_ALPHA_BITS, 16#D5B).
+-define(GL_ACCUM_CLEAR_VALUE, 16#B80).
+-define(GL_ACCUM, 16#100).
+-define(GL_ADD, 16#104).
+-define(GL_LOAD, 16#101).
+-define(GL_MULT, 16#103).
+-define(GL_RETURN, 16#102).
+-define(GL_ALPHA_TEST, 16#BC0).
+-define(GL_ALPHA_TEST_REF, 16#BC2).
+-define(GL_ALPHA_TEST_FUNC, 16#BC1).
+-define(GL_BLEND, 16#BE2).
+-define(GL_BLEND_SRC, 16#BE1).
+-define(GL_BLEND_DST, 16#BE0).
+-define(GL_ZERO, 16#0).
+-define(GL_ONE, 16#1).
-define(GL_SRC_COLOR, 16#300).
-define(GL_ONE_MINUS_SRC_COLOR, 16#301).
-define(GL_SRC_ALPHA, 16#302).
@@ -81,121 +208,58 @@
-define(GL_DST_COLOR, 16#306).
-define(GL_ONE_MINUS_DST_COLOR, 16#307).
-define(GL_SRC_ALPHA_SATURATE, 16#308).
--define(GL_NONE, 0).
--define(GL_FRONT_LEFT, 16#400).
--define(GL_FRONT_RIGHT, 16#401).
--define(GL_BACK_LEFT, 16#402).
--define(GL_BACK_RIGHT, 16#403).
--define(GL_FRONT, 16#404).
--define(GL_BACK, 16#405).
--define(GL_LEFT, 16#406).
--define(GL_RIGHT, 16#407).
--define(GL_FRONT_AND_BACK, 16#408).
--define(GL_AUX0, 16#409).
--define(GL_AUX1, 16#40A).
--define(GL_AUX2, 16#40B).
--define(GL_AUX3, 16#40C).
--define(GL_NO_ERROR, 0).
--define(GL_INVALID_ENUM, 16#500).
--define(GL_INVALID_VALUE, 16#501).
--define(GL_INVALID_OPERATION, 16#502).
--define(GL_STACK_OVERFLOW, 16#503).
--define(GL_STACK_UNDERFLOW, 16#504).
--define(GL_OUT_OF_MEMORY, 16#505).
--define(GL_TABLE_TOO_LARGE, 16#8031).
+-define(GL_FEEDBACK, 16#1C01).
+-define(GL_RENDER, 16#1C00).
+-define(GL_SELECT, 16#1C02).
-define(GL_2D, 16#600).
-define(GL_3D, 16#601).
-define(GL_3D_COLOR, 16#602).
-define(GL_3D_COLOR_TEXTURE, 16#603).
-define(GL_4D_COLOR_TEXTURE, 16#604).
--define(GL_PASS_THROUGH_TOKEN, 16#700).
-define(GL_POINT_TOKEN, 16#701).
-define(GL_LINE_TOKEN, 16#702).
+-define(GL_LINE_RESET_TOKEN, 16#707).
-define(GL_POLYGON_TOKEN, 16#703).
-define(GL_BITMAP_TOKEN, 16#704).
-define(GL_DRAW_PIXEL_TOKEN, 16#705).
-define(GL_COPY_PIXEL_TOKEN, 16#706).
--define(GL_LINE_RESET_TOKEN, 16#707).
--define(GL_EXP, 16#800).
--define(GL_EXP2, 16#801).
--define(GL_CW, 16#900).
--define(GL_CCW, 16#901).
--define(GL_COEFF, 16#A00).
--define(GL_ORDER, 16#A01).
--define(GL_DOMAIN, 16#A02).
--define(GL_PIXEL_MAP_I_TO_I, 16#C70).
--define(GL_PIXEL_MAP_S_TO_S, 16#C71).
--define(GL_PIXEL_MAP_I_TO_R, 16#C72).
--define(GL_PIXEL_MAP_I_TO_G, 16#C73).
--define(GL_PIXEL_MAP_I_TO_B, 16#C74).
--define(GL_PIXEL_MAP_I_TO_A, 16#C75).
--define(GL_PIXEL_MAP_R_TO_R, 16#C76).
--define(GL_PIXEL_MAP_G_TO_G, 16#C77).
--define(GL_PIXEL_MAP_B_TO_B, 16#C78).
--define(GL_PIXEL_MAP_A_TO_A, 16#C79).
--define(GL_VERTEX_ARRAY_POINTER, 16#808E).
--define(GL_NORMAL_ARRAY_POINTER, 16#808F).
--define(GL_COLOR_ARRAY_POINTER, 16#8090).
--define(GL_INDEX_ARRAY_POINTER, 16#8091).
--define(GL_TEXTURE_COORD_ARRAY_POINTER, 16#8092).
--define(GL_EDGE_FLAG_ARRAY_POINTER, 16#8093).
--define(GL_CURRENT_COLOR, 16#B00).
--define(GL_CURRENT_INDEX, 16#B01).
--define(GL_CURRENT_NORMAL, 16#B02).
--define(GL_CURRENT_TEXTURE_COORDS, 16#B03).
--define(GL_CURRENT_RASTER_COLOR, 16#B04).
--define(GL_CURRENT_RASTER_INDEX, 16#B05).
--define(GL_CURRENT_RASTER_TEXTURE_COORDS, 16#B06).
--define(GL_CURRENT_RASTER_POSITION, 16#B07).
--define(GL_CURRENT_RASTER_POSITION_VALID, 16#B08).
--define(GL_CURRENT_RASTER_DISTANCE, 16#B09).
--define(GL_POINT_SMOOTH, 16#B10).
--define(GL_POINT_SIZE, 16#B11).
--define(GL_SMOOTH_POINT_SIZE_RANGE, 16#B12).
--define(GL_SMOOTH_POINT_SIZE_GRANULARITY, 16#B13).
--define(GL_POINT_SIZE_RANGE, ?GL_SMOOTH_POINT_SIZE_RANGE).
--define(GL_POINT_SIZE_GRANULARITY, ?GL_SMOOTH_POINT_SIZE_GRANULARITY).
--define(GL_LINE_SMOOTH, 16#B20).
--define(GL_LINE_WIDTH, 16#B21).
--define(GL_SMOOTH_LINE_WIDTH_RANGE, 16#B22).
--define(GL_SMOOTH_LINE_WIDTH_GRANULARITY, 16#B23).
--define(GL_LINE_WIDTH_RANGE, ?GL_SMOOTH_LINE_WIDTH_RANGE).
--define(GL_LINE_WIDTH_GRANULARITY, ?GL_SMOOTH_LINE_WIDTH_GRANULARITY).
--define(GL_LINE_STIPPLE, 16#B24).
--define(GL_LINE_STIPPLE_PATTERN, 16#B25).
--define(GL_LINE_STIPPLE_REPEAT, 16#B26).
--define(GL_LIST_MODE, 16#B30).
--define(GL_MAX_LIST_NESTING, 16#B31).
--define(GL_LIST_BASE, 16#B32).
--define(GL_LIST_INDEX, 16#B33).
--define(GL_POLYGON_MODE, 16#B40).
--define(GL_POLYGON_SMOOTH, 16#B41).
--define(GL_POLYGON_STIPPLE, 16#B42).
--define(GL_EDGE_FLAG, 16#B43).
--define(GL_CULL_FACE, 16#B44).
--define(GL_CULL_FACE_MODE, 16#B45).
--define(GL_FRONT_FACE, 16#B46).
--define(GL_LIGHTING, 16#B50).
--define(GL_LIGHT_MODEL_LOCAL_VIEWER, 16#B51).
--define(GL_LIGHT_MODEL_TWO_SIDE, 16#B52).
--define(GL_LIGHT_MODEL_AMBIENT, 16#B53).
--define(GL_SHADE_MODEL, 16#B54).
--define(GL_COLOR_MATERIAL_FACE, 16#B55).
--define(GL_COLOR_MATERIAL_PARAMETER, 16#B56).
--define(GL_COLOR_MATERIAL, 16#B57).
+-define(GL_PASS_THROUGH_TOKEN, 16#700).
+-define(GL_FEEDBACK_BUFFER_POINTER, 16#DF0).
+-define(GL_FEEDBACK_BUFFER_SIZE, 16#DF1).
+-define(GL_FEEDBACK_BUFFER_TYPE, 16#DF2).
+-define(GL_SELECTION_BUFFER_POINTER, 16#DF3).
+-define(GL_SELECTION_BUFFER_SIZE, 16#DF4).
-define(GL_FOG, 16#B60).
--define(GL_FOG_INDEX, 16#B61).
+-define(GL_FOG_MODE, 16#B65).
-define(GL_FOG_DENSITY, 16#B62).
+-define(GL_FOG_COLOR, 16#B66).
+-define(GL_FOG_INDEX, 16#B61).
-define(GL_FOG_START, 16#B63).
-define(GL_FOG_END, 16#B64).
--define(GL_FOG_MODE, 16#B65).
--define(GL_FOG_COLOR, 16#B66).
--define(GL_DEPTH_RANGE, 16#B70).
--define(GL_DEPTH_TEST, 16#B71).
--define(GL_DEPTH_WRITEMASK, 16#B72).
--define(GL_DEPTH_CLEAR_VALUE, 16#B73).
--define(GL_DEPTH_FUNC, 16#B74).
--define(GL_ACCUM_CLEAR_VALUE, 16#B80).
+-define(GL_LINEAR, 16#2601).
+-define(GL_EXP, 16#800).
+-define(GL_EXP2, 16#801).
+-define(GL_LOGIC_OP, 16#BF1).
+-define(GL_INDEX_LOGIC_OP, 16#BF1).
+-define(GL_COLOR_LOGIC_OP, 16#BF2).
+-define(GL_LOGIC_OP_MODE, 16#BF0).
+-define(GL_CLEAR, 16#1500).
+-define(GL_SET, 16#150F).
+-define(GL_COPY, 16#1503).
+-define(GL_COPY_INVERTED, 16#150C).
+-define(GL_NOOP, 16#1505).
+-define(GL_INVERT, 16#150A).
+-define(GL_AND, 16#1501).
+-define(GL_NAND, 16#150E).
+-define(GL_OR, 16#1507).
+-define(GL_NOR, 16#1508).
+-define(GL_XOR, 16#1506).
+-define(GL_EQUIV, 16#1509).
+-define(GL_AND_REVERSE, 16#1502).
+-define(GL_AND_INVERTED, 16#1504).
+-define(GL_OR_REVERSE, 16#150B).
+-define(GL_OR_INVERTED, 16#150D).
+-define(GL_STENCIL_BITS, 16#D57).
-define(GL_STENCIL_TEST, 16#B90).
-define(GL_STENCIL_CLEAR_VALUE, 16#B91).
-define(GL_STENCIL_FUNC, 16#B92).
@@ -205,89 +269,48 @@
-define(GL_STENCIL_PASS_DEPTH_PASS, 16#B96).
-define(GL_STENCIL_REF, 16#B97).
-define(GL_STENCIL_WRITEMASK, 16#B98).
--define(GL_MATRIX_MODE, 16#BA0).
--define(GL_NORMALIZE, 16#BA1).
--define(GL_VIEWPORT, 16#BA2).
--define(GL_MODELVIEW_STACK_DEPTH, 16#BA3).
--define(GL_PROJECTION_STACK_DEPTH, 16#BA4).
--define(GL_TEXTURE_STACK_DEPTH, 16#BA5).
--define(GL_MODELVIEW_MATRIX, 16#BA6).
--define(GL_PROJECTION_MATRIX, 16#BA7).
--define(GL_TEXTURE_MATRIX, 16#BA8).
--define(GL_ATTRIB_STACK_DEPTH, 16#BB0).
--define(GL_CLIENT_ATTRIB_STACK_DEPTH, 16#BB1).
--define(GL_ALPHA_TEST, 16#BC0).
--define(GL_ALPHA_TEST_FUNC, 16#BC1).
--define(GL_ALPHA_TEST_REF, 16#BC2).
--define(GL_DITHER, 16#BD0).
--define(GL_BLEND_DST, 16#BE0).
--define(GL_BLEND_SRC, 16#BE1).
--define(GL_BLEND, 16#BE2).
--define(GL_LOGIC_OP_MODE, 16#BF0).
--define(GL_INDEX_LOGIC_OP, 16#BF1).
--define(GL_LOGIC_OP, ?GL_INDEX_LOGIC_OP).
--define(GL_COLOR_LOGIC_OP, 16#BF2).
+-define(GL_STENCIL_INDEX, 16#1901).
+-define(GL_KEEP, 16#1E00).
+-define(GL_REPLACE, 16#1E01).
+-define(GL_INCR, 16#1E02).
+-define(GL_DECR, 16#1E03).
+-define(GL_NONE, 16#0).
+-define(GL_LEFT, 16#406).
+-define(GL_RIGHT, 16#407).
+-define(GL_FRONT_LEFT, 16#400).
+-define(GL_FRONT_RIGHT, 16#401).
+-define(GL_BACK_LEFT, 16#402).
+-define(GL_BACK_RIGHT, 16#403).
+-define(GL_AUX0, 16#409).
+-define(GL_AUX1, 16#40A).
+-define(GL_AUX2, 16#40B).
+-define(GL_AUX3, 16#40C).
+-define(GL_COLOR_INDEX, 16#1900).
+-define(GL_RED, 16#1903).
+-define(GL_GREEN, 16#1904).
+-define(GL_BLUE, 16#1905).
+-define(GL_ALPHA, 16#1906).
+-define(GL_LUMINANCE, 16#1909).
+-define(GL_LUMINANCE_ALPHA, 16#190A).
+-define(GL_ALPHA_BITS, 16#D55).
+-define(GL_RED_BITS, 16#D52).
+-define(GL_GREEN_BITS, 16#D53).
+-define(GL_BLUE_BITS, 16#D54).
+-define(GL_INDEX_BITS, 16#D51).
+-define(GL_SUBPIXEL_BITS, 16#D50).
-define(GL_AUX_BUFFERS, 16#C00).
--define(GL_DRAW_BUFFER, 16#C01).
-define(GL_READ_BUFFER, 16#C02).
--define(GL_SCISSOR_BOX, 16#C10).
--define(GL_SCISSOR_TEST, 16#C11).
--define(GL_INDEX_CLEAR_VALUE, 16#C20).
--define(GL_INDEX_WRITEMASK, 16#C21).
--define(GL_COLOR_CLEAR_VALUE, 16#C22).
--define(GL_COLOR_WRITEMASK, 16#C23).
--define(GL_INDEX_MODE, 16#C30).
--define(GL_RGBA_MODE, 16#C31).
+-define(GL_DRAW_BUFFER, 16#C01).
-define(GL_DOUBLEBUFFER, 16#C32).
-define(GL_STEREO, 16#C33).
--define(GL_RENDER_MODE, 16#C40).
--define(GL_PERSPECTIVE_CORRECTION_HINT, 16#C50).
--define(GL_POINT_SMOOTH_HINT, 16#C51).
--define(GL_LINE_SMOOTH_HINT, 16#C52).
--define(GL_POLYGON_SMOOTH_HINT, 16#C53).
--define(GL_FOG_HINT, 16#C54).
--define(GL_TEXTURE_GEN_S, 16#C60).
--define(GL_TEXTURE_GEN_T, 16#C61).
--define(GL_TEXTURE_GEN_R, 16#C62).
--define(GL_TEXTURE_GEN_Q, 16#C63).
--define(GL_PIXEL_MAP_I_TO_I_SIZE, 16#CB0).
--define(GL_PIXEL_MAP_S_TO_S_SIZE, 16#CB1).
--define(GL_PIXEL_MAP_I_TO_R_SIZE, 16#CB2).
--define(GL_PIXEL_MAP_I_TO_G_SIZE, 16#CB3).
--define(GL_PIXEL_MAP_I_TO_B_SIZE, 16#CB4).
--define(GL_PIXEL_MAP_I_TO_A_SIZE, 16#CB5).
--define(GL_PIXEL_MAP_R_TO_R_SIZE, 16#CB6).
--define(GL_PIXEL_MAP_G_TO_G_SIZE, 16#CB7).
--define(GL_PIXEL_MAP_B_TO_B_SIZE, 16#CB8).
--define(GL_PIXEL_MAP_A_TO_A_SIZE, 16#CB9).
--define(GL_UNPACK_SWAP_BYTES, 16#CF0).
--define(GL_UNPACK_LSB_FIRST, 16#CF1).
--define(GL_UNPACK_ROW_LENGTH, 16#CF2).
--define(GL_UNPACK_SKIP_ROWS, 16#CF3).
--define(GL_UNPACK_SKIP_PIXELS, 16#CF4).
--define(GL_UNPACK_ALIGNMENT, 16#CF5).
--define(GL_PACK_SWAP_BYTES, 16#D00).
--define(GL_PACK_LSB_FIRST, 16#D01).
--define(GL_PACK_ROW_LENGTH, 16#D02).
--define(GL_PACK_SKIP_ROWS, 16#D03).
--define(GL_PACK_SKIP_PIXELS, 16#D04).
--define(GL_PACK_ALIGNMENT, 16#D05).
--define(GL_MAP_COLOR, 16#D10).
--define(GL_MAP_STENCIL, 16#D11).
--define(GL_INDEX_SHIFT, 16#D12).
--define(GL_INDEX_OFFSET, 16#D13).
--define(GL_RED_SCALE, 16#D14).
--define(GL_RED_BIAS, 16#D15).
--define(GL_ZOOM_X, 16#D16).
--define(GL_ZOOM_Y, 16#D17).
--define(GL_GREEN_SCALE, 16#D18).
--define(GL_GREEN_BIAS, 16#D19).
--define(GL_BLUE_SCALE, 16#D1A).
--define(GL_BLUE_BIAS, 16#D1B).
--define(GL_ALPHA_SCALE, 16#D1C).
--define(GL_ALPHA_BIAS, 16#D1D).
--define(GL_DEPTH_SCALE, 16#D1E).
--define(GL_DEPTH_BIAS, 16#D1F).
+-define(GL_BITMAP, 16#1A00).
+-define(GL_COLOR, 16#1800).
+-define(GL_DEPTH, 16#1801).
+-define(GL_STENCIL, 16#1802).
+-define(GL_DITHER, 16#BD0).
+-define(GL_RGB, 16#1907).
+-define(GL_RGBA, 16#1908).
+-define(GL_MAX_LIST_NESTING, 16#B31).
-define(GL_MAX_EVAL_ORDER, 16#D30).
-define(GL_MAX_LIGHTS, 16#D31).
-define(GL_MAX_CLIP_PLANES, 16#D32).
@@ -300,19 +323,33 @@
-define(GL_MAX_TEXTURE_STACK_DEPTH, 16#D39).
-define(GL_MAX_VIEWPORT_DIMS, 16#D3A).
-define(GL_MAX_CLIENT_ATTRIB_STACK_DEPTH, 16#D3B).
--define(GL_SUBPIXEL_BITS, 16#D50).
--define(GL_INDEX_BITS, 16#D51).
--define(GL_RED_BITS, 16#D52).
--define(GL_GREEN_BITS, 16#D53).
--define(GL_BLUE_BITS, 16#D54).
--define(GL_ALPHA_BITS, 16#D55).
--define(GL_DEPTH_BITS, 16#D56).
--define(GL_STENCIL_BITS, 16#D57).
--define(GL_ACCUM_RED_BITS, 16#D58).
--define(GL_ACCUM_GREEN_BITS, 16#D59).
--define(GL_ACCUM_BLUE_BITS, 16#D5A).
--define(GL_ACCUM_ALPHA_BITS, 16#D5B).
+-define(GL_ATTRIB_STACK_DEPTH, 16#BB0).
+-define(GL_CLIENT_ATTRIB_STACK_DEPTH, 16#BB1).
+-define(GL_COLOR_CLEAR_VALUE, 16#C22).
+-define(GL_COLOR_WRITEMASK, 16#C23).
+-define(GL_CURRENT_INDEX, 16#B01).
+-define(GL_CURRENT_COLOR, 16#B00).
+-define(GL_CURRENT_NORMAL, 16#B02).
+-define(GL_CURRENT_RASTER_COLOR, 16#B04).
+-define(GL_CURRENT_RASTER_DISTANCE, 16#B09).
+-define(GL_CURRENT_RASTER_INDEX, 16#B05).
+-define(GL_CURRENT_RASTER_POSITION, 16#B07).
+-define(GL_CURRENT_RASTER_TEXTURE_COORDS, 16#B06).
+-define(GL_CURRENT_RASTER_POSITION_VALID, 16#B08).
+-define(GL_CURRENT_TEXTURE_COORDS, 16#B03).
+-define(GL_INDEX_CLEAR_VALUE, 16#C20).
+-define(GL_INDEX_MODE, 16#C30).
+-define(GL_INDEX_WRITEMASK, 16#C21).
+-define(GL_MODELVIEW_MATRIX, 16#BA6).
+-define(GL_MODELVIEW_STACK_DEPTH, 16#BA3).
-define(GL_NAME_STACK_DEPTH, 16#D70).
+-define(GL_PROJECTION_MATRIX, 16#BA7).
+-define(GL_PROJECTION_STACK_DEPTH, 16#BA4).
+-define(GL_RENDER_MODE, 16#C40).
+-define(GL_RGBA_MODE, 16#C31).
+-define(GL_TEXTURE_MATRIX, 16#BA8).
+-define(GL_TEXTURE_STACK_DEPTH, 16#BA5).
+-define(GL_VIEWPORT, 16#BA2).
-define(GL_AUTO_NORMAL, 16#D80).
-define(GL_MAP1_COLOR_4, 16#D90).
-define(GL_MAP1_INDEX, 16#D91).
@@ -336,166 +373,149 @@
-define(GL_MAP1_GRID_SEGMENTS, 16#DD1).
-define(GL_MAP2_GRID_DOMAIN, 16#DD2).
-define(GL_MAP2_GRID_SEGMENTS, 16#DD3).
+-define(GL_COEFF, 16#A00).
+-define(GL_ORDER, 16#A01).
+-define(GL_DOMAIN, 16#A02).
+-define(GL_PERSPECTIVE_CORRECTION_HINT, 16#C50).
+-define(GL_POINT_SMOOTH_HINT, 16#C51).
+-define(GL_LINE_SMOOTH_HINT, 16#C52).
+-define(GL_POLYGON_SMOOTH_HINT, 16#C53).
+-define(GL_FOG_HINT, 16#C54).
+-define(GL_DONT_CARE, 16#1100).
+-define(GL_FASTEST, 16#1101).
+-define(GL_NICEST, 16#1102).
+-define(GL_SCISSOR_BOX, 16#C10).
+-define(GL_SCISSOR_TEST, 16#C11).
+-define(GL_MAP_COLOR, 16#D10).
+-define(GL_MAP_STENCIL, 16#D11).
+-define(GL_INDEX_SHIFT, 16#D12).
+-define(GL_INDEX_OFFSET, 16#D13).
+-define(GL_RED_SCALE, 16#D14).
+-define(GL_RED_BIAS, 16#D15).
+-define(GL_GREEN_SCALE, 16#D18).
+-define(GL_GREEN_BIAS, 16#D19).
+-define(GL_BLUE_SCALE, 16#D1A).
+-define(GL_BLUE_BIAS, 16#D1B).
+-define(GL_ALPHA_SCALE, 16#D1C).
+-define(GL_ALPHA_BIAS, 16#D1D).
+-define(GL_DEPTH_SCALE, 16#D1E).
+-define(GL_DEPTH_BIAS, 16#D1F).
+-define(GL_PIXEL_MAP_S_TO_S_SIZE, 16#CB1).
+-define(GL_PIXEL_MAP_I_TO_I_SIZE, 16#CB0).
+-define(GL_PIXEL_MAP_I_TO_R_SIZE, 16#CB2).
+-define(GL_PIXEL_MAP_I_TO_G_SIZE, 16#CB3).
+-define(GL_PIXEL_MAP_I_TO_B_SIZE, 16#CB4).
+-define(GL_PIXEL_MAP_I_TO_A_SIZE, 16#CB5).
+-define(GL_PIXEL_MAP_R_TO_R_SIZE, 16#CB6).
+-define(GL_PIXEL_MAP_G_TO_G_SIZE, 16#CB7).
+-define(GL_PIXEL_MAP_B_TO_B_SIZE, 16#CB8).
+-define(GL_PIXEL_MAP_A_TO_A_SIZE, 16#CB9).
+-define(GL_PIXEL_MAP_S_TO_S, 16#C71).
+-define(GL_PIXEL_MAP_I_TO_I, 16#C70).
+-define(GL_PIXEL_MAP_I_TO_R, 16#C72).
+-define(GL_PIXEL_MAP_I_TO_G, 16#C73).
+-define(GL_PIXEL_MAP_I_TO_B, 16#C74).
+-define(GL_PIXEL_MAP_I_TO_A, 16#C75).
+-define(GL_PIXEL_MAP_R_TO_R, 16#C76).
+-define(GL_PIXEL_MAP_G_TO_G, 16#C77).
+-define(GL_PIXEL_MAP_B_TO_B, 16#C78).
+-define(GL_PIXEL_MAP_A_TO_A, 16#C79).
+-define(GL_PACK_ALIGNMENT, 16#D05).
+-define(GL_PACK_LSB_FIRST, 16#D01).
+-define(GL_PACK_ROW_LENGTH, 16#D02).
+-define(GL_PACK_SKIP_PIXELS, 16#D04).
+-define(GL_PACK_SKIP_ROWS, 16#D03).
+-define(GL_PACK_SWAP_BYTES, 16#D00).
+-define(GL_UNPACK_ALIGNMENT, 16#CF5).
+-define(GL_UNPACK_LSB_FIRST, 16#CF1).
+-define(GL_UNPACK_ROW_LENGTH, 16#CF2).
+-define(GL_UNPACK_SKIP_PIXELS, 16#CF4).
+-define(GL_UNPACK_SKIP_ROWS, 16#CF3).
+-define(GL_UNPACK_SWAP_BYTES, 16#CF0).
+-define(GL_ZOOM_X, 16#D16).
+-define(GL_ZOOM_Y, 16#D17).
+-define(GL_TEXTURE_ENV, 16#2300).
+-define(GL_TEXTURE_ENV_MODE, 16#2200).
-define(GL_TEXTURE_1D, 16#DE0).
-define(GL_TEXTURE_2D, 16#DE1).
--define(GL_FEEDBACK_BUFFER_POINTER, 16#DF0).
--define(GL_FEEDBACK_BUFFER_SIZE, 16#DF1).
--define(GL_FEEDBACK_BUFFER_TYPE, 16#DF2).
--define(GL_SELECTION_BUFFER_POINTER, 16#DF3).
--define(GL_SELECTION_BUFFER_SIZE, 16#DF4).
--define(GL_POLYGON_OFFSET_UNITS, 16#2A00).
--define(GL_POLYGON_OFFSET_POINT, 16#2A01).
--define(GL_POLYGON_OFFSET_LINE, 16#2A02).
--define(GL_POLYGON_OFFSET_FILL, 16#8037).
--define(GL_POLYGON_OFFSET_FACTOR, 16#8038).
--define(GL_TEXTURE_BINDING_1D, 16#8068).
--define(GL_TEXTURE_BINDING_2D, 16#8069).
--define(GL_TEXTURE_BINDING_3D, 16#806A).
--define(GL_VERTEX_ARRAY, 16#8074).
--define(GL_NORMAL_ARRAY, 16#8075).
--define(GL_COLOR_ARRAY, 16#8076).
--define(GL_INDEX_ARRAY, 16#8077).
--define(GL_TEXTURE_COORD_ARRAY, 16#8078).
--define(GL_EDGE_FLAG_ARRAY, 16#8079).
--define(GL_VERTEX_ARRAY_SIZE, 16#807A).
--define(GL_VERTEX_ARRAY_TYPE, 16#807B).
--define(GL_VERTEX_ARRAY_STRIDE, 16#807C).
--define(GL_NORMAL_ARRAY_TYPE, 16#807E).
--define(GL_NORMAL_ARRAY_STRIDE, 16#807F).
--define(GL_COLOR_ARRAY_SIZE, 16#8081).
--define(GL_COLOR_ARRAY_TYPE, 16#8082).
--define(GL_COLOR_ARRAY_STRIDE, 16#8083).
--define(GL_INDEX_ARRAY_TYPE, 16#8085).
--define(GL_INDEX_ARRAY_STRIDE, 16#8086).
--define(GL_TEXTURE_COORD_ARRAY_SIZE, 16#8088).
--define(GL_TEXTURE_COORD_ARRAY_TYPE, 16#8089).
--define(GL_TEXTURE_COORD_ARRAY_STRIDE, 16#808A).
--define(GL_EDGE_FLAG_ARRAY_STRIDE, 16#808C).
+-define(GL_TEXTURE_WRAP_S, 16#2802).
+-define(GL_TEXTURE_WRAP_T, 16#2803).
+-define(GL_TEXTURE_MAG_FILTER, 16#2800).
+-define(GL_TEXTURE_MIN_FILTER, 16#2801).
+-define(GL_TEXTURE_ENV_COLOR, 16#2201).
+-define(GL_TEXTURE_GEN_S, 16#C60).
+-define(GL_TEXTURE_GEN_T, 16#C61).
+-define(GL_TEXTURE_GEN_MODE, 16#2500).
+-define(GL_TEXTURE_BORDER_COLOR, 16#1004).
-define(GL_TEXTURE_WIDTH, 16#1000).
-define(GL_TEXTURE_HEIGHT, 16#1001).
--define(GL_TEXTURE_INTERNAL_FORMAT, 16#1003).
--define(GL_TEXTURE_COMPONENTS, ?GL_TEXTURE_INTERNAL_FORMAT).
--define(GL_TEXTURE_BORDER_COLOR, 16#1004).
-define(GL_TEXTURE_BORDER, 16#1005).
+-define(GL_TEXTURE_COMPONENTS, 16#1003).
-define(GL_TEXTURE_RED_SIZE, 16#805C).
-define(GL_TEXTURE_GREEN_SIZE, 16#805D).
-define(GL_TEXTURE_BLUE_SIZE, 16#805E).
-define(GL_TEXTURE_ALPHA_SIZE, 16#805F).
-define(GL_TEXTURE_LUMINANCE_SIZE, 16#8060).
-define(GL_TEXTURE_INTENSITY_SIZE, 16#8061).
--define(GL_TEXTURE_PRIORITY, 16#8066).
--define(GL_TEXTURE_RESIDENT, 16#8067).
--define(GL_DONT_CARE, 16#1100).
--define(GL_FASTEST, 16#1101).
--define(GL_NICEST, 16#1102).
--define(GL_AMBIENT, 16#1200).
--define(GL_DIFFUSE, 16#1201).
--define(GL_SPECULAR, 16#1202).
--define(GL_POSITION, 16#1203).
--define(GL_SPOT_DIRECTION, 16#1204).
--define(GL_SPOT_EXPONENT, 16#1205).
--define(GL_SPOT_CUTOFF, 16#1206).
--define(GL_CONSTANT_ATTENUATION, 16#1207).
--define(GL_LINEAR_ATTENUATION, 16#1208).
--define(GL_QUADRATIC_ATTENUATION, 16#1209).
--define(GL_COMPILE, 16#1300).
--define(GL_COMPILE_AND_EXECUTE, 16#1301).
--define(GL_BYTE, 16#1400).
--define(GL_UNSIGNED_BYTE, 16#1401).
--define(GL_SHORT, 16#1402).
--define(GL_UNSIGNED_SHORT, 16#1403).
--define(GL_INT, 16#1404).
--define(GL_UNSIGNED_INT, 16#1405).
--define(GL_FLOAT, 16#1406).
--define(GL_2_BYTES, 16#1407).
--define(GL_3_BYTES, 16#1408).
--define(GL_4_BYTES, 16#1409).
--define(GL_DOUBLE, 16#140A).
--define(GL_DOUBLE_EXT, 16#140A).
--define(GL_CLEAR, 16#1500).
--define(GL_AND, 16#1501).
--define(GL_AND_REVERSE, 16#1502).
--define(GL_COPY, 16#1503).
--define(GL_AND_INVERTED, 16#1504).
--define(GL_NOOP, 16#1505).
--define(GL_XOR, 16#1506).
--define(GL_OR, 16#1507).
--define(GL_NOR, 16#1508).
--define(GL_EQUIV, 16#1509).
--define(GL_INVERT, 16#150A).
--define(GL_OR_REVERSE, 16#150B).
--define(GL_COPY_INVERTED, 16#150C).
--define(GL_OR_INVERTED, 16#150D).
--define(GL_NAND, 16#150E).
--define(GL_SET, 16#150F).
--define(GL_EMISSION, 16#1600).
--define(GL_SHININESS, 16#1601).
--define(GL_AMBIENT_AND_DIFFUSE, 16#1602).
--define(GL_COLOR_INDEXES, 16#1603).
--define(GL_MODELVIEW, 16#1700).
--define(GL_PROJECTION, 16#1701).
--define(GL_TEXTURE, 16#1702).
--define(GL_COLOR, 16#1800).
--define(GL_DEPTH, 16#1801).
--define(GL_STENCIL, 16#1802).
--define(GL_COLOR_INDEX, 16#1900).
--define(GL_STENCIL_INDEX, 16#1901).
--define(GL_DEPTH_COMPONENT, 16#1902).
--define(GL_RED, 16#1903).
--define(GL_GREEN, 16#1904).
--define(GL_BLUE, 16#1905).
--define(GL_ALPHA, 16#1906).
--define(GL_RGB, 16#1907).
--define(GL_RGBA, 16#1908).
--define(GL_LUMINANCE, 16#1909).
--define(GL_LUMINANCE_ALPHA, 16#190A).
--define(GL_BITMAP, 16#1A00).
--define(GL_POINT, 16#1B00).
--define(GL_LINE, 16#1B01).
--define(GL_FILL, 16#1B02).
--define(GL_RENDER, 16#1C00).
--define(GL_FEEDBACK, 16#1C01).
--define(GL_SELECT, 16#1C02).
--define(GL_FLAT, 16#1D00).
--define(GL_SMOOTH, 16#1D01).
--define(GL_KEEP, 16#1E00).
--define(GL_REPLACE, 16#1E01).
--define(GL_INCR, 16#1E02).
--define(GL_DECR, 16#1E03).
--define(GL_VENDOR, 16#1F00).
--define(GL_RENDERER, 16#1F01).
--define(GL_VERSION, 16#1F02).
--define(GL_EXTENSIONS, 16#1F03).
--define(GL_S, 16#2000).
--define(GL_T, 16#2001).
--define(GL_R, 16#2002).
--define(GL_Q, 16#2003).
--define(GL_MODULATE, 16#2100).
--define(GL_DECAL, 16#2101).
--define(GL_TEXTURE_ENV_MODE, 16#2200).
--define(GL_TEXTURE_ENV_COLOR, 16#2201).
--define(GL_TEXTURE_ENV, 16#2300).
--define(GL_EYE_LINEAR, 16#2400).
+-define(GL_NEAREST_MIPMAP_NEAREST, 16#2700).
+-define(GL_NEAREST_MIPMAP_LINEAR, 16#2702).
+-define(GL_LINEAR_MIPMAP_NEAREST, 16#2701).
+-define(GL_LINEAR_MIPMAP_LINEAR, 16#2703).
-define(GL_OBJECT_LINEAR, 16#2401).
--define(GL_SPHERE_MAP, 16#2402).
--define(GL_TEXTURE_GEN_MODE, 16#2500).
-define(GL_OBJECT_PLANE, 16#2501).
+-define(GL_EYE_LINEAR, 16#2400).
-define(GL_EYE_PLANE, 16#2502).
+-define(GL_SPHERE_MAP, 16#2402).
+-define(GL_DECAL, 16#2101).
+-define(GL_MODULATE, 16#2100).
-define(GL_NEAREST, 16#2600).
--define(GL_LINEAR, 16#2601).
--define(GL_NEAREST_MIPMAP_NEAREST, 16#2700).
--define(GL_LINEAR_MIPMAP_NEAREST, 16#2701).
--define(GL_NEAREST_MIPMAP_LINEAR, 16#2702).
--define(GL_LINEAR_MIPMAP_LINEAR, 16#2703).
--define(GL_TEXTURE_MAG_FILTER, 16#2800).
--define(GL_TEXTURE_MIN_FILTER, 16#2801).
--define(GL_TEXTURE_WRAP_S, 16#2802).
--define(GL_TEXTURE_WRAP_T, 16#2803).
+-define(GL_REPEAT, 16#2901).
+-define(GL_CLAMP, 16#2900).
+-define(GL_S, 16#2000).
+-define(GL_T, 16#2001).
+-define(GL_R, 16#2002).
+-define(GL_Q, 16#2003).
+-define(GL_TEXTURE_GEN_R, 16#C62).
+-define(GL_TEXTURE_GEN_Q, 16#C63).
+-define(GL_VENDOR, 16#1F00).
+-define(GL_RENDERER, 16#1F01).
+-define(GL_VERSION, 16#1F02).
+-define(GL_EXTENSIONS, 16#1F03).
+-define(GL_NO_ERROR, 16#0).
+-define(GL_INVALID_ENUM, 16#500).
+-define(GL_INVALID_VALUE, 16#501).
+-define(GL_INVALID_OPERATION, 16#502).
+-define(GL_STACK_OVERFLOW, 16#503).
+-define(GL_STACK_UNDERFLOW, 16#504).
+-define(GL_OUT_OF_MEMORY, 16#505).
+-define(GL_CURRENT_BIT, 16#1).
+-define(GL_POINT_BIT, 16#2).
+-define(GL_LINE_BIT, 16#4).
+-define(GL_POLYGON_BIT, 16#8).
+-define(GL_POLYGON_STIPPLE_BIT, 16#10).
+-define(GL_PIXEL_MODE_BIT, 16#20).
+-define(GL_LIGHTING_BIT, 16#40).
+-define(GL_FOG_BIT, 16#80).
+-define(GL_DEPTH_BUFFER_BIT, 16#100).
+-define(GL_ACCUM_BUFFER_BIT, 16#200).
+-define(GL_STENCIL_BUFFER_BIT, 16#400).
+-define(GL_VIEWPORT_BIT, 16#800).
+-define(GL_TRANSFORM_BIT, 16#1000).
+-define(GL_ENABLE_BIT, 16#2000).
+-define(GL_COLOR_BUFFER_BIT, 16#4000).
+-define(GL_HINT_BIT, 16#8000).
+-define(GL_EVAL_BIT, 16#10000).
+-define(GL_LIST_BIT, 16#20000).
+-define(GL_TEXTURE_BIT, 16#40000).
+-define(GL_SCISSOR_BIT, 16#80000).
+-define(GL_ALL_ATTRIB_BITS, 16#FFFFF).
-define(GL_PROXY_TEXTURE_1D, 16#8063).
-define(GL_PROXY_TEXTURE_2D, 16#8064).
--define(GL_CLAMP, 16#2900).
--define(GL_REPEAT, 16#2901).
--define(GL_R3_G3_B2, 16#2A10).
+-define(GL_TEXTURE_PRIORITY, 16#8066).
+-define(GL_TEXTURE_RESIDENT, 16#8067).
+-define(GL_TEXTURE_BINDING_1D, 16#8068).
+-define(GL_TEXTURE_BINDING_2D, 16#8069).
+-define(GL_TEXTURE_INTERNAL_FORMAT, 16#1003).
-define(GL_ALPHA4, 16#803B).
-define(GL_ALPHA8, 16#803C).
-define(GL_ALPHA12, 16#803D).
@@ -515,6 +535,7 @@
-define(GL_INTENSITY8, 16#804B).
-define(GL_INTENSITY12, 16#804C).
-define(GL_INTENSITY16, 16#804D).
+-define(GL_R3_G3_B2, 16#2A10).
-define(GL_RGB4, 16#804F).
-define(GL_RGB5, 16#8050).
-define(GL_RGB8, 16#8051).
@@ -528,51 +549,14 @@
-define(GL_RGB10_A2, 16#8059).
-define(GL_RGBA12, 16#805A).
-define(GL_RGBA16, 16#805B).
--define(GL_V2F, 16#2A20).
--define(GL_V3F, 16#2A21).
--define(GL_C4UB_V2F, 16#2A22).
--define(GL_C4UB_V3F, 16#2A23).
--define(GL_C3F_V3F, 16#2A24).
--define(GL_N3F_V3F, 16#2A25).
--define(GL_C4F_N3F_V3F, 16#2A26).
--define(GL_T2F_V3F, 16#2A27).
--define(GL_T4F_V4F, 16#2A28).
--define(GL_T2F_C4UB_V3F, 16#2A29).
--define(GL_T2F_C3F_V3F, 16#2A2A).
--define(GL_T2F_N3F_V3F, 16#2A2B).
--define(GL_T2F_C4F_N3F_V3F, 16#2A2C).
--define(GL_T4F_C4F_N3F_V4F, 16#2A2D).
--define(GL_CLIP_PLANE0, 16#3000).
--define(GL_CLIP_PLANE1, 16#3001).
--define(GL_CLIP_PLANE2, 16#3002).
--define(GL_CLIP_PLANE3, 16#3003).
--define(GL_CLIP_PLANE4, 16#3004).
--define(GL_CLIP_PLANE5, 16#3005).
--define(GL_LIGHT0, 16#4000).
--define(GL_LIGHT1, 16#4001).
--define(GL_LIGHT2, 16#4002).
--define(GL_LIGHT3, 16#4003).
--define(GL_LIGHT4, 16#4004).
--define(GL_LIGHT5, 16#4005).
--define(GL_LIGHT6, 16#4006).
--define(GL_LIGHT7, 16#4007).
--define(GL_ABGR_EXT, 16#8000).
--define(GL_FUNC_SUBTRACT_EXT, 16#800A).
--define(GL_FUNC_REVERSE_SUBTRACT_EXT, 16#800B).
--define(GL_UNSIGNED_BYTE_3_3_2_EXT, 16#8032).
--define(GL_UNSIGNED_SHORT_4_4_4_4_EXT, 16#8033).
--define(GL_UNSIGNED_SHORT_5_5_5_1_EXT, 16#8034).
--define(GL_UNSIGNED_INT_8_8_8_8_EXT, 16#8035).
--define(GL_UNSIGNED_INT_10_10_10_2_EXT, 16#8036).
--define(GL_PACK_SKIP_IMAGES, 16#806B).
--define(GL_PACK_IMAGE_HEIGHT, 16#806C).
--define(GL_UNPACK_SKIP_IMAGES, 16#806D).
--define(GL_UNPACK_IMAGE_HEIGHT, 16#806E).
--define(GL_TEXTURE_3D, 16#806F).
--define(GL_PROXY_TEXTURE_3D, 16#8070).
--define(GL_TEXTURE_DEPTH, 16#8071).
--define(GL_TEXTURE_WRAP_R, 16#8072).
--define(GL_MAX_3D_TEXTURE_SIZE, 16#8073).
+-define(GL_CLIENT_PIXEL_STORE_BIT, 16#1).
+-define(GL_CLIENT_VERTEX_ARRAY_BIT, 16#2).
+-define(GL_ALL_CLIENT_ATTRIB_BITS, 16#FFFFFFFF).
+-define(GL_CLIENT_ALL_ATTRIB_BITS, 16#FFFFFFFF).
+-define(GL_RESCALE_NORMAL, 16#803A).
+-define(GL_CLAMP_TO_EDGE, 16#812F).
+-define(GL_MAX_ELEMENTS_VERTICES, 16#80E8).
+-define(GL_MAX_ELEMENTS_INDICES, 16#80E9).
-define(GL_BGR, 16#80E0).
-define(GL_BGRA, 16#80E1).
-define(GL_UNSIGNED_BYTE_3_3_2, 16#8032).
@@ -587,22 +571,104 @@
-define(GL_UNSIGNED_INT_8_8_8_8_REV, 16#8367).
-define(GL_UNSIGNED_INT_10_10_10_2, 16#8036).
-define(GL_UNSIGNED_INT_2_10_10_10_REV, 16#8368).
--define(GL_RESCALE_NORMAL, 16#803A).
-define(GL_LIGHT_MODEL_COLOR_CONTROL, 16#81F8).
-define(GL_SINGLE_COLOR, 16#81F9).
-define(GL_SEPARATE_SPECULAR_COLOR, 16#81FA).
--define(GL_CLAMP_TO_EDGE, 16#812F).
-define(GL_TEXTURE_MIN_LOD, 16#813A).
-define(GL_TEXTURE_MAX_LOD, 16#813B).
-define(GL_TEXTURE_BASE_LEVEL, 16#813C).
-define(GL_TEXTURE_MAX_LEVEL, 16#813D).
--define(GL_MAX_ELEMENTS_VERTICES, 16#80E8).
--define(GL_MAX_ELEMENTS_INDICES, 16#80E9).
+-define(GL_SMOOTH_POINT_SIZE_RANGE, 16#B12).
+-define(GL_SMOOTH_POINT_SIZE_GRANULARITY, 16#B13).
+-define(GL_SMOOTH_LINE_WIDTH_RANGE, 16#B22).
+-define(GL_SMOOTH_LINE_WIDTH_GRANULARITY, 16#B23).
-define(GL_ALIASED_POINT_SIZE_RANGE, 16#846D).
-define(GL_ALIASED_LINE_WIDTH_RANGE, 16#846E).
--define(GL_ACTIVE_TEXTURE, 16#84E0).
--define(GL_CLIENT_ACTIVE_TEXTURE, 16#84E1).
--define(GL_MAX_TEXTURE_UNITS, 16#84E2).
+-define(GL_PACK_SKIP_IMAGES, 16#806B).
+-define(GL_PACK_IMAGE_HEIGHT, 16#806C).
+-define(GL_UNPACK_SKIP_IMAGES, 16#806D).
+-define(GL_UNPACK_IMAGE_HEIGHT, 16#806E).
+-define(GL_TEXTURE_3D, 16#806F).
+-define(GL_PROXY_TEXTURE_3D, 16#8070).
+-define(GL_TEXTURE_DEPTH, 16#8071).
+-define(GL_TEXTURE_WRAP_R, 16#8072).
+-define(GL_MAX_3D_TEXTURE_SIZE, 16#8073).
+-define(GL_TEXTURE_BINDING_3D, 16#806A).
+-define(GL_CONSTANT_COLOR, 16#8001).
+-define(GL_ONE_MINUS_CONSTANT_COLOR, 16#8002).
+-define(GL_CONSTANT_ALPHA, 16#8003).
+-define(GL_ONE_MINUS_CONSTANT_ALPHA, 16#8004).
+-define(GL_COLOR_TABLE, 16#80D0).
+-define(GL_POST_CONVOLUTION_COLOR_TABLE, 16#80D1).
+-define(GL_POST_COLOR_MATRIX_COLOR_TABLE, 16#80D2).
+-define(GL_PROXY_COLOR_TABLE, 16#80D3).
+-define(GL_PROXY_POST_CONVOLUTION_COLOR_TABLE, 16#80D4).
+-define(GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE, 16#80D5).
+-define(GL_COLOR_TABLE_SCALE, 16#80D6).
+-define(GL_COLOR_TABLE_BIAS, 16#80D7).
+-define(GL_COLOR_TABLE_FORMAT, 16#80D8).
+-define(GL_COLOR_TABLE_WIDTH, 16#80D9).
+-define(GL_COLOR_TABLE_RED_SIZE, 16#80DA).
+-define(GL_COLOR_TABLE_GREEN_SIZE, 16#80DB).
+-define(GL_COLOR_TABLE_BLUE_SIZE, 16#80DC).
+-define(GL_COLOR_TABLE_ALPHA_SIZE, 16#80DD).
+-define(GL_COLOR_TABLE_LUMINANCE_SIZE, 16#80DE).
+-define(GL_COLOR_TABLE_INTENSITY_SIZE, 16#80DF).
+-define(GL_CONVOLUTION_1D, 16#8010).
+-define(GL_CONVOLUTION_2D, 16#8011).
+-define(GL_SEPARABLE_2D, 16#8012).
+-define(GL_CONVOLUTION_BORDER_MODE, 16#8013).
+-define(GL_CONVOLUTION_FILTER_SCALE, 16#8014).
+-define(GL_CONVOLUTION_FILTER_BIAS, 16#8015).
+-define(GL_REDUCE, 16#8016).
+-define(GL_CONVOLUTION_FORMAT, 16#8017).
+-define(GL_CONVOLUTION_WIDTH, 16#8018).
+-define(GL_CONVOLUTION_HEIGHT, 16#8019).
+-define(GL_MAX_CONVOLUTION_WIDTH, 16#801A).
+-define(GL_MAX_CONVOLUTION_HEIGHT, 16#801B).
+-define(GL_POST_CONVOLUTION_RED_SCALE, 16#801C).
+-define(GL_POST_CONVOLUTION_GREEN_SCALE, 16#801D).
+-define(GL_POST_CONVOLUTION_BLUE_SCALE, 16#801E).
+-define(GL_POST_CONVOLUTION_ALPHA_SCALE, 16#801F).
+-define(GL_POST_CONVOLUTION_RED_BIAS, 16#8020).
+-define(GL_POST_CONVOLUTION_GREEN_BIAS, 16#8021).
+-define(GL_POST_CONVOLUTION_BLUE_BIAS, 16#8022).
+-define(GL_POST_CONVOLUTION_ALPHA_BIAS, 16#8023).
+-define(GL_CONSTANT_BORDER, 16#8151).
+-define(GL_REPLICATE_BORDER, 16#8153).
+-define(GL_CONVOLUTION_BORDER_COLOR, 16#8154).
+-define(GL_COLOR_MATRIX, 16#80B1).
+-define(GL_COLOR_MATRIX_STACK_DEPTH, 16#80B2).
+-define(GL_MAX_COLOR_MATRIX_STACK_DEPTH, 16#80B3).
+-define(GL_POST_COLOR_MATRIX_RED_SCALE, 16#80B4).
+-define(GL_POST_COLOR_MATRIX_GREEN_SCALE, 16#80B5).
+-define(GL_POST_COLOR_MATRIX_BLUE_SCALE, 16#80B6).
+-define(GL_POST_COLOR_MATRIX_ALPHA_SCALE, 16#80B7).
+-define(GL_POST_COLOR_MATRIX_RED_BIAS, 16#80B8).
+-define(GL_POST_COLOR_MATRIX_GREEN_BIAS, 16#80B9).
+-define(GL_POST_COLOR_MATRIX_BLUE_BIAS, 16#80BA).
+-define(GL_POST_COLOR_MATRIX_ALPHA_BIAS, 16#80BB).
+-define(GL_HISTOGRAM, 16#8024).
+-define(GL_PROXY_HISTOGRAM, 16#8025).
+-define(GL_HISTOGRAM_WIDTH, 16#8026).
+-define(GL_HISTOGRAM_FORMAT, 16#8027).
+-define(GL_HISTOGRAM_RED_SIZE, 16#8028).
+-define(GL_HISTOGRAM_GREEN_SIZE, 16#8029).
+-define(GL_HISTOGRAM_BLUE_SIZE, 16#802A).
+-define(GL_HISTOGRAM_ALPHA_SIZE, 16#802B).
+-define(GL_HISTOGRAM_LUMINANCE_SIZE, 16#802C).
+-define(GL_HISTOGRAM_SINK, 16#802D).
+-define(GL_MINMAX, 16#802E).
+-define(GL_MINMAX_FORMAT, 16#802F).
+-define(GL_MINMAX_SINK, 16#8030).
+-define(GL_TABLE_TOO_LARGE, 16#8031).
+-define(GL_BLEND_EQUATION, 16#8009).
+-define(GL_MIN, 16#8007).
+-define(GL_MAX, 16#8008).
+-define(GL_FUNC_ADD, 16#8006).
+-define(GL_FUNC_SUBTRACT, 16#800A).
+-define(GL_FUNC_REVERSE_SUBTRACT, 16#800B).
+-define(GL_BLEND_COLOR, 16#8005).
-define(GL_TEXTURE0, 16#84C0).
-define(GL_TEXTURE1, 16#84C1).
-define(GL_TEXTURE2, 16#84C2).
@@ -635,6 +701,9 @@
-define(GL_TEXTURE29, 16#84DD).
-define(GL_TEXTURE30, 16#84DE).
-define(GL_TEXTURE31, 16#84DF).
+-define(GL_ACTIVE_TEXTURE, 16#84E0).
+-define(GL_CLIENT_ACTIVE_TEXTURE, 16#84E1).
+-define(GL_MAX_TEXTURE_UNITS, 16#84E2).
-define(GL_NORMAL_MAP, 16#8511).
-define(GL_REFLECTION_MAP, 16#8512).
-define(GL_TEXTURE_CUBE_MAP, 16#8513).
@@ -647,32 +716,6 @@
-define(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 16#851A).
-define(GL_PROXY_TEXTURE_CUBE_MAP, 16#851B).
-define(GL_MAX_CUBE_MAP_TEXTURE_SIZE, 16#851C).
--define(GL_COMBINE, 16#8570).
--define(GL_COMBINE_RGB, 16#8571).
--define(GL_COMBINE_ALPHA, 16#8572).
--define(GL_RGB_SCALE, 16#8573).
--define(GL_ADD_SIGNED, 16#8574).
--define(GL_INTERPOLATE, 16#8575).
--define(GL_CONSTANT, 16#8576).
--define(GL_PRIMARY_COLOR, 16#8577).
--define(GL_PREVIOUS, 16#8578).
--define(GL_SOURCE0_RGB, 16#8580).
--define(GL_SOURCE1_RGB, 16#8581).
--define(GL_SOURCE2_RGB, 16#8582).
--define(GL_SOURCE0_ALPHA, 16#8588).
--define(GL_SOURCE1_ALPHA, 16#8589).
--define(GL_SOURCE2_ALPHA, 16#858A).
--define(GL_OPERAND0_RGB, 16#8590).
--define(GL_OPERAND1_RGB, 16#8591).
--define(GL_OPERAND2_RGB, 16#8592).
--define(GL_OPERAND0_ALPHA, 16#8598).
--define(GL_OPERAND1_ALPHA, 16#8599).
--define(GL_OPERAND2_ALPHA, 16#859A).
--define(GL_SUBTRACT, 16#84E7).
--define(GL_TRANSPOSE_MODELVIEW_MATRIX, 16#84E3).
--define(GL_TRANSPOSE_PROJECTION_MATRIX, 16#84E4).
--define(GL_TRANSPOSE_TEXTURE_MATRIX, 16#84E5).
--define(GL_TRANSPOSE_COLOR_MATRIX, 16#84E6).
-define(GL_COMPRESSED_ALPHA, 16#84E9).
-define(GL_COMPRESSED_LUMINANCE, 16#84EA).
-define(GL_COMPRESSED_LUMINANCE_ALPHA, 16#84EB).
@@ -684,9 +727,6 @@
-define(GL_TEXTURE_COMPRESSED, 16#86A1).
-define(GL_NUM_COMPRESSED_TEXTURE_FORMATS, 16#86A2).
-define(GL_COMPRESSED_TEXTURE_FORMATS, 16#86A3).
--define(GL_DOT3_RGB, 16#86AE).
--define(GL_DOT3_RGBA, 16#86AF).
--define(GL_CLAMP_TO_BORDER, 16#812D).
-define(GL_MULTISAMPLE, 16#809D).
-define(GL_SAMPLE_ALPHA_TO_COVERAGE, 16#809E).
-define(GL_SAMPLE_ALPHA_TO_ONE, 16#809F).
@@ -696,57 +736,120 @@
-define(GL_SAMPLE_COVERAGE_VALUE, 16#80AA).
-define(GL_SAMPLE_COVERAGE_INVERT, 16#80AB).
-define(GL_MULTISAMPLE_BIT, 16#20000000).
--define(GL_VERTEX_ARRAY_EXT, 16#8074).
--define(GL_NORMAL_ARRAY_EXT, 16#8075).
--define(GL_COLOR_ARRAY_EXT, 16#8076).
--define(GL_INDEX_ARRAY_EXT, 16#8077).
--define(GL_TEXTURE_COORD_ARRAY_EXT, 16#8078).
--define(GL_EDGE_FLAG_ARRAY_EXT, 16#8079).
--define(GL_VERTEX_ARRAY_SIZE_EXT, 16#807A).
--define(GL_VERTEX_ARRAY_TYPE_EXT, 16#807B).
--define(GL_VERTEX_ARRAY_STRIDE_EXT, 16#807C).
--define(GL_VERTEX_ARRAY_COUNT_EXT, 16#807D).
--define(GL_NORMAL_ARRAY_TYPE_EXT, 16#807E).
--define(GL_NORMAL_ARRAY_STRIDE_EXT, 16#807F).
--define(GL_NORMAL_ARRAY_COUNT_EXT, 16#8080).
--define(GL_COLOR_ARRAY_SIZE_EXT, 16#8081).
--define(GL_COLOR_ARRAY_TYPE_EXT, 16#8082).
--define(GL_COLOR_ARRAY_STRIDE_EXT, 16#8083).
--define(GL_COLOR_ARRAY_COUNT_EXT, 16#8084).
--define(GL_INDEX_ARRAY_TYPE_EXT, 16#8085).
--define(GL_INDEX_ARRAY_STRIDE_EXT, 16#8086).
--define(GL_INDEX_ARRAY_COUNT_EXT, 16#8087).
--define(GL_TEXTURE_COORD_ARRAY_SIZE_EXT, 16#8088).
--define(GL_TEXTURE_COORD_ARRAY_TYPE_EXT, 16#8089).
--define(GL_TEXTURE_COORD_ARRAY_STRIDE_EXT, 16#808A).
--define(GL_TEXTURE_COORD_ARRAY_COUNT_EXT, 16#808B).
--define(GL_EDGE_FLAG_ARRAY_STRIDE_EXT, 16#808C).
--define(GL_EDGE_FLAG_ARRAY_COUNT_EXT, 16#808D).
--define(GL_VERTEX_ARRAY_POINTER_EXT, 16#808E).
--define(GL_NORMAL_ARRAY_POINTER_EXT, 16#808F).
--define(GL_COLOR_ARRAY_POINTER_EXT, 16#8090).
--define(GL_INDEX_ARRAY_POINTER_EXT, 16#8091).
--define(GL_TEXTURE_COORD_ARRAY_POINTER_EXT, 16#8092).
--define(GL_EDGE_FLAG_ARRAY_POINTER_EXT, 16#8093).
--define(GL_TEXTURE_MIN_LOD_SGIS, 16#813A).
--define(GL_TEXTURE_MAX_LOD_SGIS, 16#813B).
--define(GL_TEXTURE_BASE_LEVEL_SGIS, 16#813C).
--define(GL_TEXTURE_MAX_LEVEL_SGIS, 16#813D).
--define(GL_SHARED_TEXTURE_PALETTE_EXT, 16#81FB).
--define(GL_RESCALE_NORMAL_EXT, 16#803A).
--define(GL_TEXTURE_COMPARE_SGIX, 16#819A).
--define(GL_TEXTURE_COMPARE_OPERATOR_SGIX, 16#819B).
--define(GL_TEXTURE_LEQUAL_R_SGIX, 16#819C).
--define(GL_TEXTURE_GEQUAL_R_SGIX, 16#819D).
--define(GL_DEPTH_COMPONENT16_SGIX, 16#81A5).
--define(GL_DEPTH_COMPONENT24_SGIX, 16#81A6).
--define(GL_DEPTH_COMPONENT32_SGIX, 16#81A7).
--define(GL_GENERATE_MIPMAP_SGIS, 16#8191).
--define(GL_GENERATE_MIPMAP_HINT_SGIS, 16#8192).
+-define(GL_TRANSPOSE_MODELVIEW_MATRIX, 16#84E3).
+-define(GL_TRANSPOSE_PROJECTION_MATRIX, 16#84E4).
+-define(GL_TRANSPOSE_TEXTURE_MATRIX, 16#84E5).
+-define(GL_TRANSPOSE_COLOR_MATRIX, 16#84E6).
+-define(GL_COMBINE, 16#8570).
+-define(GL_COMBINE_RGB, 16#8571).
+-define(GL_COMBINE_ALPHA, 16#8572).
+-define(GL_SOURCE0_RGB, 16#8580).
+-define(GL_SOURCE1_RGB, 16#8581).
+-define(GL_SOURCE2_RGB, 16#8582).
+-define(GL_SOURCE0_ALPHA, 16#8588).
+-define(GL_SOURCE1_ALPHA, 16#8589).
+-define(GL_SOURCE2_ALPHA, 16#858A).
+-define(GL_OPERAND0_RGB, 16#8590).
+-define(GL_OPERAND1_RGB, 16#8591).
+-define(GL_OPERAND2_RGB, 16#8592).
+-define(GL_OPERAND0_ALPHA, 16#8598).
+-define(GL_OPERAND1_ALPHA, 16#8599).
+-define(GL_OPERAND2_ALPHA, 16#859A).
+-define(GL_RGB_SCALE, 16#8573).
+-define(GL_ADD_SIGNED, 16#8574).
+-define(GL_INTERPOLATE, 16#8575).
+-define(GL_SUBTRACT, 16#84E7).
+-define(GL_CONSTANT, 16#8576).
+-define(GL_PRIMARY_COLOR, 16#8577).
+-define(GL_PREVIOUS, 16#8578).
+-define(GL_DOT3_RGB, 16#86AE).
+-define(GL_DOT3_RGBA, 16#86AF).
+-define(GL_CLAMP_TO_BORDER, 16#812D).
+-define(GL_ARB_multitexture, 1).
+-define(GL_TEXTURE0_ARB, 16#84C0).
+-define(GL_TEXTURE1_ARB, 16#84C1).
+-define(GL_TEXTURE2_ARB, 16#84C2).
+-define(GL_TEXTURE3_ARB, 16#84C3).
+-define(GL_TEXTURE4_ARB, 16#84C4).
+-define(GL_TEXTURE5_ARB, 16#84C5).
+-define(GL_TEXTURE6_ARB, 16#84C6).
+-define(GL_TEXTURE7_ARB, 16#84C7).
+-define(GL_TEXTURE8_ARB, 16#84C8).
+-define(GL_TEXTURE9_ARB, 16#84C9).
+-define(GL_TEXTURE10_ARB, 16#84CA).
+-define(GL_TEXTURE11_ARB, 16#84CB).
+-define(GL_TEXTURE12_ARB, 16#84CC).
+-define(GL_TEXTURE13_ARB, 16#84CD).
+-define(GL_TEXTURE14_ARB, 16#84CE).
+-define(GL_TEXTURE15_ARB, 16#84CF).
+-define(GL_TEXTURE16_ARB, 16#84D0).
+-define(GL_TEXTURE17_ARB, 16#84D1).
+-define(GL_TEXTURE18_ARB, 16#84D2).
+-define(GL_TEXTURE19_ARB, 16#84D3).
+-define(GL_TEXTURE20_ARB, 16#84D4).
+-define(GL_TEXTURE21_ARB, 16#84D5).
+-define(GL_TEXTURE22_ARB, 16#84D6).
+-define(GL_TEXTURE23_ARB, 16#84D7).
+-define(GL_TEXTURE24_ARB, 16#84D8).
+-define(GL_TEXTURE25_ARB, 16#84D9).
+-define(GL_TEXTURE26_ARB, 16#84DA).
+-define(GL_TEXTURE27_ARB, 16#84DB).
+-define(GL_TEXTURE28_ARB, 16#84DC).
+-define(GL_TEXTURE29_ARB, 16#84DD).
+-define(GL_TEXTURE30_ARB, 16#84DE).
+-define(GL_TEXTURE31_ARB, 16#84DF).
+-define(GL_ACTIVE_TEXTURE_ARB, 16#84E0).
+-define(GL_CLIENT_ACTIVE_TEXTURE_ARB, 16#84E1).
+-define(GL_MAX_TEXTURE_UNITS_ARB, 16#84E2).
+-define(GL_MESA_packed_depth_stencil, 1).
+-define(GL_DEPTH_STENCIL_MESA, 16#8750).
+-define(GL_UNSIGNED_INT_24_8_MESA, 16#8751).
+-define(GL_UNSIGNED_INT_8_24_REV_MESA, 16#8752).
+-define(GL_UNSIGNED_SHORT_15_1_MESA, 16#8753).
+-define(GL_UNSIGNED_SHORT_1_15_REV_MESA, 16#8754).
+-define(GL_MESA_program_debug, 1).
+-define(GL_FRAGMENT_PROGRAM_POSITION_MESA, 16#8BB0).
+-define(GL_FRAGMENT_PROGRAM_CALLBACK_MESA, 16#8BB1).
+-define(GL_FRAGMENT_PROGRAM_CALLBACK_FUNC_MESA, 16#8BB2).
+-define(GL_FRAGMENT_PROGRAM_CALLBACK_DATA_MESA, 16#8BB3).
+-define(GL_VERTEX_PROGRAM_POSITION_MESA, 16#8BB4).
+-define(GL_VERTEX_PROGRAM_CALLBACK_MESA, 16#8BB5).
+-define(GL_VERTEX_PROGRAM_CALLBACK_FUNC_MESA, 16#8BB6).
+-define(GL_VERTEX_PROGRAM_CALLBACK_DATA_MESA, 16#8BB7).
+-define(GL_MESA_texture_array, 1).
+-define(GL_TEXTURE_1D_ARRAY_EXT, 16#8C18).
+-define(GL_PROXY_TEXTURE_1D_ARRAY_EXT, 16#8C19).
+-define(GL_TEXTURE_2D_ARRAY_EXT, 16#8C1A).
+-define(GL_PROXY_TEXTURE_2D_ARRAY_EXT, 16#8C1B).
+-define(GL_TEXTURE_BINDING_1D_ARRAY_EXT, 16#8C1C).
+-define(GL_TEXTURE_BINDING_2D_ARRAY_EXT, 16#8C1D).
+-define(GL_MAX_ARRAY_TEXTURE_LAYERS_EXT, 16#88FF).
+-define(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT, 16#8CD4).
+-define(GL_ATI_blend_equation_separate, 1).
+-define(GL_ALPHA_BLEND_EQUATION_ATI, 16#883D).
+-define(GL_OES_EGL_image, 1).
+-define(GL_GLEXT_VERSION, 66).
+-define(GL_BLEND_DST_RGB, 16#80C8).
+-define(GL_BLEND_SRC_RGB, 16#80C9).
+-define(GL_BLEND_DST_ALPHA, 16#80CA).
+-define(GL_BLEND_SRC_ALPHA, 16#80CB).
+-define(GL_POINT_FADE_THRESHOLD_SIZE, 16#8128).
+-define(GL_DEPTH_COMPONENT16, 16#81A5).
+-define(GL_DEPTH_COMPONENT24, 16#81A6).
+-define(GL_DEPTH_COMPONENT32, 16#81A7).
+-define(GL_MIRRORED_REPEAT, 16#8370).
+-define(GL_MAX_TEXTURE_LOD_BIAS, 16#84FD).
+-define(GL_TEXTURE_LOD_BIAS, 16#8501).
+-define(GL_INCR_WRAP, 16#8507).
+-define(GL_DECR_WRAP, 16#8508).
+-define(GL_TEXTURE_DEPTH_SIZE, 16#884A).
+-define(GL_TEXTURE_COMPARE_MODE, 16#884C).
+-define(GL_TEXTURE_COMPARE_FUNC, 16#884D).
-define(GL_POINT_SIZE_MIN, 16#8126).
-define(GL_POINT_SIZE_MAX, 16#8127).
--define(GL_POINT_FADE_THRESHOLD_SIZE, 16#8128).
-define(GL_POINT_DISTANCE_ATTENUATION, 16#8129).
+-define(GL_GENERATE_MIPMAP, 16#8191).
+-define(GL_GENERATE_MIPMAP_HINT, 16#8192).
-define(GL_FOG_COORDINATE_SOURCE, 16#8450).
-define(GL_FOG_COORDINATE, 16#8451).
-define(GL_FRAGMENT_DEPTH, 16#8452).
@@ -762,101 +865,9 @@
-define(GL_SECONDARY_COLOR_ARRAY_STRIDE, 16#845C).
-define(GL_SECONDARY_COLOR_ARRAY_POINTER, 16#845D).
-define(GL_SECONDARY_COLOR_ARRAY, 16#845E).
--define(GL_INCR_WRAP, 16#8507).
--define(GL_DECR_WRAP, 16#8508).
--define(GL_MAX_TEXTURE_LOD_BIAS, 16#84FD).
-define(GL_TEXTURE_FILTER_CONTROL, 16#8500).
--define(GL_TEXTURE_LOD_BIAS, 16#8501).
--define(GL_GENERATE_MIPMAP, 16#8191).
--define(GL_GENERATE_MIPMAP_HINT, 16#8192).
--define(GL_BLEND_DST_RGB, 16#80C8).
--define(GL_BLEND_SRC_RGB, 16#80C9).
--define(GL_BLEND_DST_ALPHA, 16#80CA).
--define(GL_BLEND_SRC_ALPHA, 16#80CB).
--define(GL_MIRRORED_REPEAT, 16#8370).
--define(GL_DEPTH_COMPONENT16, 16#81A5).
--define(GL_DEPTH_COMPONENT24, 16#81A6).
--define(GL_DEPTH_COMPONENT32, 16#81A7).
--define(GL_TEXTURE_DEPTH_SIZE, 16#884A).
-define(GL_DEPTH_TEXTURE_MODE, 16#884B).
--define(GL_TEXTURE_COMPARE_MODE, 16#884C).
--define(GL_TEXTURE_COMPARE_FUNC, 16#884D).
-define(GL_COMPARE_R_TO_TEXTURE, 16#884E).
--define(GL_GLEXT_VERSION, 65).
--define(GL_CONSTANT_COLOR, 16#8001).
--define(GL_ONE_MINUS_CONSTANT_COLOR, 16#8002).
--define(GL_CONSTANT_ALPHA, 16#8003).
--define(GL_ONE_MINUS_CONSTANT_ALPHA, 16#8004).
--define(GL_BLEND_COLOR, 16#8005).
--define(GL_FUNC_ADD, 16#8006).
--define(GL_MIN, 16#8007).
--define(GL_MAX, 16#8008).
--define(GL_BLEND_EQUATION, 16#8009).
--define(GL_FUNC_SUBTRACT, 16#800A).
--define(GL_FUNC_REVERSE_SUBTRACT, 16#800B).
--define(GL_CONVOLUTION_1D, 16#8010).
--define(GL_CONVOLUTION_2D, 16#8011).
--define(GL_SEPARABLE_2D, 16#8012).
--define(GL_CONVOLUTION_BORDER_MODE, 16#8013).
--define(GL_CONVOLUTION_FILTER_SCALE, 16#8014).
--define(GL_CONVOLUTION_FILTER_BIAS, 16#8015).
--define(GL_REDUCE, 16#8016).
--define(GL_CONVOLUTION_FORMAT, 16#8017).
--define(GL_CONVOLUTION_WIDTH, 16#8018).
--define(GL_CONVOLUTION_HEIGHT, 16#8019).
--define(GL_MAX_CONVOLUTION_WIDTH, 16#801A).
--define(GL_MAX_CONVOLUTION_HEIGHT, 16#801B).
--define(GL_POST_CONVOLUTION_RED_SCALE, 16#801C).
--define(GL_POST_CONVOLUTION_GREEN_SCALE, 16#801D).
--define(GL_POST_CONVOLUTION_BLUE_SCALE, 16#801E).
--define(GL_POST_CONVOLUTION_ALPHA_SCALE, 16#801F).
--define(GL_POST_CONVOLUTION_RED_BIAS, 16#8020).
--define(GL_POST_CONVOLUTION_GREEN_BIAS, 16#8021).
--define(GL_POST_CONVOLUTION_BLUE_BIAS, 16#8022).
--define(GL_POST_CONVOLUTION_ALPHA_BIAS, 16#8023).
--define(GL_HISTOGRAM, 16#8024).
--define(GL_PROXY_HISTOGRAM, 16#8025).
--define(GL_HISTOGRAM_WIDTH, 16#8026).
--define(GL_HISTOGRAM_FORMAT, 16#8027).
--define(GL_HISTOGRAM_RED_SIZE, 16#8028).
--define(GL_HISTOGRAM_GREEN_SIZE, 16#8029).
--define(GL_HISTOGRAM_BLUE_SIZE, 16#802A).
--define(GL_HISTOGRAM_ALPHA_SIZE, 16#802B).
--define(GL_HISTOGRAM_LUMINANCE_SIZE, 16#802C).
--define(GL_HISTOGRAM_SINK, 16#802D).
--define(GL_MINMAX, 16#802E).
--define(GL_MINMAX_FORMAT, 16#802F).
--define(GL_MINMAX_SINK, 16#8030).
--define(GL_COLOR_MATRIX, 16#80B1).
--define(GL_COLOR_MATRIX_STACK_DEPTH, 16#80B2).
--define(GL_MAX_COLOR_MATRIX_STACK_DEPTH, 16#80B3).
--define(GL_POST_COLOR_MATRIX_RED_SCALE, 16#80B4).
--define(GL_POST_COLOR_MATRIX_GREEN_SCALE, 16#80B5).
--define(GL_POST_COLOR_MATRIX_BLUE_SCALE, 16#80B6).
--define(GL_POST_COLOR_MATRIX_ALPHA_SCALE, 16#80B7).
--define(GL_POST_COLOR_MATRIX_RED_BIAS, 16#80B8).
--define(GL_POST_COLOR_MATRIX_GREEN_BIAS, 16#80B9).
--define(GL_POST_COLOR_MATRIX_BLUE_BIAS, 16#80BA).
--define(GL_POST_COLOR_MATRIX_ALPHA_BIAS, 16#80BB).
--define(GL_COLOR_TABLE, 16#80D0).
--define(GL_POST_CONVOLUTION_COLOR_TABLE, 16#80D1).
--define(GL_POST_COLOR_MATRIX_COLOR_TABLE, 16#80D2).
--define(GL_PROXY_COLOR_TABLE, 16#80D3).
--define(GL_PROXY_POST_CONVOLUTION_COLOR_TABLE, 16#80D4).
--define(GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE, 16#80D5).
--define(GL_COLOR_TABLE_SCALE, 16#80D6).
--define(GL_COLOR_TABLE_BIAS, 16#80D7).
--define(GL_COLOR_TABLE_FORMAT, 16#80D8).
--define(GL_COLOR_TABLE_WIDTH, 16#80D9).
--define(GL_COLOR_TABLE_RED_SIZE, 16#80DA).
--define(GL_COLOR_TABLE_GREEN_SIZE, 16#80DB).
--define(GL_COLOR_TABLE_BLUE_SIZE, 16#80DC).
--define(GL_COLOR_TABLE_ALPHA_SIZE, 16#80DD).
--define(GL_COLOR_TABLE_LUMINANCE_SIZE, 16#80DE).
--define(GL_COLOR_TABLE_INTENSITY_SIZE, 16#80DF).
--define(GL_CONSTANT_BORDER, 16#8151).
--define(GL_REPLICATE_BORDER, 16#8153).
--define(GL_CONVOLUTION_BORDER_COLOR, 16#8154).
-define(GL_BUFFER_SIZE, 16#8764).
-define(GL_BUFFER_USAGE, 16#8765).
-define(GL_QUERY_COUNTER_BITS, 16#8864).
@@ -1184,41 +1195,6 @@
-define(GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW, 16#900D).
-define(GL_INT_SAMPLER_CUBE_MAP_ARRAY, 16#900E).
-define(GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY, 16#900F).
--define(GL_TEXTURE0_ARB, 16#84C0).
--define(GL_TEXTURE1_ARB, 16#84C1).
--define(GL_TEXTURE2_ARB, 16#84C2).
--define(GL_TEXTURE3_ARB, 16#84C3).
--define(GL_TEXTURE4_ARB, 16#84C4).
--define(GL_TEXTURE5_ARB, 16#84C5).
--define(GL_TEXTURE6_ARB, 16#84C6).
--define(GL_TEXTURE7_ARB, 16#84C7).
--define(GL_TEXTURE8_ARB, 16#84C8).
--define(GL_TEXTURE9_ARB, 16#84C9).
--define(GL_TEXTURE10_ARB, 16#84CA).
--define(GL_TEXTURE11_ARB, 16#84CB).
--define(GL_TEXTURE12_ARB, 16#84CC).
--define(GL_TEXTURE13_ARB, 16#84CD).
--define(GL_TEXTURE14_ARB, 16#84CE).
--define(GL_TEXTURE15_ARB, 16#84CF).
--define(GL_TEXTURE16_ARB, 16#84D0).
--define(GL_TEXTURE17_ARB, 16#84D1).
--define(GL_TEXTURE18_ARB, 16#84D2).
--define(GL_TEXTURE19_ARB, 16#84D3).
--define(GL_TEXTURE20_ARB, 16#84D4).
--define(GL_TEXTURE21_ARB, 16#84D5).
--define(GL_TEXTURE22_ARB, 16#84D6).
--define(GL_TEXTURE23_ARB, 16#84D7).
--define(GL_TEXTURE24_ARB, 16#84D8).
--define(GL_TEXTURE25_ARB, 16#84D9).
--define(GL_TEXTURE26_ARB, 16#84DA).
--define(GL_TEXTURE27_ARB, 16#84DB).
--define(GL_TEXTURE28_ARB, 16#84DC).
--define(GL_TEXTURE29_ARB, 16#84DD).
--define(GL_TEXTURE30_ARB, 16#84DE).
--define(GL_TEXTURE31_ARB, 16#84DF).
--define(GL_ACTIVE_TEXTURE_ARB, 16#84E0).
--define(GL_CLIENT_ACTIVE_TEXTURE_ARB, 16#84E1).
--define(GL_MAX_TEXTURE_UNITS_ARB, 16#84E2).
-define(GL_TRANSPOSE_MODELVIEW_MATRIX_ARB, 16#84E3).
-define(GL_TRANSPOSE_PROJECTION_MATRIX_ARB, 16#84E4).
-define(GL_TRANSPOSE_TEXTURE_MATRIX_ARB, 16#84E5).
@@ -1956,6 +1932,7 @@
-define(GL_UNKNOWN_CONTEXT_RESET_ARB, 16#8255).
-define(GL_RESET_NOTIFICATION_STRATEGY_ARB, 16#8256).
-define(GL_NO_RESET_NOTIFICATION_ARB, 16#8261).
+-define(GL_ABGR_EXT, 16#8000).
-define(GL_CONSTANT_COLOR_EXT, 16#8001).
-define(GL_ONE_MINUS_CONSTANT_COLOR_EXT, 16#8002).
-define(GL_CONSTANT_ALPHA_EXT, 16#8003).
@@ -2118,6 +2095,15 @@
-define(GL_LINEAR_SHARPEN_ALPHA_SGIS, 16#80AE).
-define(GL_LINEAR_SHARPEN_COLOR_SGIS, 16#80AF).
-define(GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS, 16#80B0).
+-define(GL_UNSIGNED_BYTE_3_3_2_EXT, 16#8032).
+-define(GL_UNSIGNED_SHORT_4_4_4_4_EXT, 16#8033).
+-define(GL_UNSIGNED_SHORT_5_5_5_1_EXT, 16#8034).
+-define(GL_UNSIGNED_INT_8_8_8_8_EXT, 16#8035).
+-define(GL_UNSIGNED_INT_10_10_10_2_EXT, 16#8036).
+-define(GL_TEXTURE_MIN_LOD_SGIS, 16#813A).
+-define(GL_TEXTURE_MAX_LOD_SGIS, 16#813B).
+-define(GL_TEXTURE_BASE_LEVEL_SGIS, 16#813C).
+-define(GL_TEXTURE_MAX_LEVEL_SGIS, 16#813D).
-define(GL_MULTISAMPLE_SGIS, 16#809D).
-define(GL_SAMPLE_ALPHA_TO_MASK_SGIS, 16#809E).
-define(GL_SAMPLE_ALPHA_TO_ONE_SGIS, 16#809F).
@@ -2134,6 +2120,41 @@
-define(GL_SAMPLE_MASK_VALUE_SGIS, 16#80AA).
-define(GL_SAMPLE_MASK_INVERT_SGIS, 16#80AB).
-define(GL_SAMPLE_PATTERN_SGIS, 16#80AC).
+-define(GL_RESCALE_NORMAL_EXT, 16#803A).
+-define(GL_VERTEX_ARRAY_EXT, 16#8074).
+-define(GL_NORMAL_ARRAY_EXT, 16#8075).
+-define(GL_COLOR_ARRAY_EXT, 16#8076).
+-define(GL_INDEX_ARRAY_EXT, 16#8077).
+-define(GL_TEXTURE_COORD_ARRAY_EXT, 16#8078).
+-define(GL_EDGE_FLAG_ARRAY_EXT, 16#8079).
+-define(GL_VERTEX_ARRAY_SIZE_EXT, 16#807A).
+-define(GL_VERTEX_ARRAY_TYPE_EXT, 16#807B).
+-define(GL_VERTEX_ARRAY_STRIDE_EXT, 16#807C).
+-define(GL_VERTEX_ARRAY_COUNT_EXT, 16#807D).
+-define(GL_NORMAL_ARRAY_TYPE_EXT, 16#807E).
+-define(GL_NORMAL_ARRAY_STRIDE_EXT, 16#807F).
+-define(GL_NORMAL_ARRAY_COUNT_EXT, 16#8080).
+-define(GL_COLOR_ARRAY_SIZE_EXT, 16#8081).
+-define(GL_COLOR_ARRAY_TYPE_EXT, 16#8082).
+-define(GL_COLOR_ARRAY_STRIDE_EXT, 16#8083).
+-define(GL_COLOR_ARRAY_COUNT_EXT, 16#8084).
+-define(GL_INDEX_ARRAY_TYPE_EXT, 16#8085).
+-define(GL_INDEX_ARRAY_STRIDE_EXT, 16#8086).
+-define(GL_INDEX_ARRAY_COUNT_EXT, 16#8087).
+-define(GL_TEXTURE_COORD_ARRAY_SIZE_EXT, 16#8088).
+-define(GL_TEXTURE_COORD_ARRAY_TYPE_EXT, 16#8089).
+-define(GL_TEXTURE_COORD_ARRAY_STRIDE_EXT, 16#808A).
+-define(GL_TEXTURE_COORD_ARRAY_COUNT_EXT, 16#808B).
+-define(GL_EDGE_FLAG_ARRAY_STRIDE_EXT, 16#808C).
+-define(GL_EDGE_FLAG_ARRAY_COUNT_EXT, 16#808D).
+-define(GL_VERTEX_ARRAY_POINTER_EXT, 16#808E).
+-define(GL_NORMAL_ARRAY_POINTER_EXT, 16#808F).
+-define(GL_COLOR_ARRAY_POINTER_EXT, 16#8090).
+-define(GL_INDEX_ARRAY_POINTER_EXT, 16#8091).
+-define(GL_TEXTURE_COORD_ARRAY_POINTER_EXT, 16#8092).
+-define(GL_EDGE_FLAG_ARRAY_POINTER_EXT, 16#8093).
+-define(GL_GENERATE_MIPMAP_SGIS, 16#8191).
+-define(GL_GENERATE_MIPMAP_HINT_SGIS, 16#8192).
-define(GL_LINEAR_CLIPMAP_LINEAR_SGIX, 16#8170).
-define(GL_TEXTURE_CLIPMAP_CENTER_SGIX, 16#8171).
-define(GL_TEXTURE_CLIPMAP_FRAME_SGIX, 16#8172).
@@ -2146,12 +2167,18 @@
-define(GL_NEAREST_CLIPMAP_NEAREST_SGIX, 16#844D).
-define(GL_NEAREST_CLIPMAP_LINEAR_SGIX, 16#844E).
-define(GL_LINEAR_CLIPMAP_NEAREST_SGIX, 16#844F).
+-define(GL_TEXTURE_COMPARE_SGIX, 16#819A).
+-define(GL_TEXTURE_COMPARE_OPERATOR_SGIX, 16#819B).
+-define(GL_TEXTURE_LEQUAL_R_SGIX, 16#819C).
+-define(GL_TEXTURE_GEQUAL_R_SGIX, 16#819D).
-define(GL_CLAMP_TO_EDGE_SGIS, 16#812F).
-define(GL_CLAMP_TO_BORDER_SGIS, 16#812D).
-define(GL_FUNC_ADD_EXT, 16#8006).
-define(GL_MIN_EXT, 16#8007).
-define(GL_MAX_EXT, 16#8008).
-define(GL_BLEND_EQUATION_EXT, 16#8009).
+-define(GL_FUNC_SUBTRACT_EXT, 16#800A).
+-define(GL_FUNC_REVERSE_SUBTRACT_EXT, 16#800B).
-define(GL_INTERLACE_SGIX, 16#8094).
-define(GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX, 16#813E).
-define(GL_PIXEL_TILE_CACHE_INCREMENT_SGIX, 16#813F).
@@ -2216,6 +2243,9 @@
-define(GL_MAX_DEFORMATION_ORDER_SGIX, 16#8197).
-define(GL_REFERENCE_PLANE_SGIX, 16#817D).
-define(GL_REFERENCE_PLANE_EQUATION_SGIX, 16#817E).
+-define(GL_DEPTH_COMPONENT16_SGIX, 16#81A5).
+-define(GL_DEPTH_COMPONENT24_SGIX, 16#81A6).
+-define(GL_DEPTH_COMPONENT32_SGIX, 16#81A7).
-define(GL_FOG_FUNC_SGIS, 16#812A).
-define(GL_FOG_FUNC_POINTS_SGIS, 16#812B).
-define(GL_MAX_FOG_FUNC_POINTS_SGIS, 16#812C).
@@ -2393,6 +2423,7 @@
-define(GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT, 16#8336).
-define(GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT, 16#8337).
-define(GL_PIXEL_TRANSFORM_2D_MATRIX_EXT, 16#8338).
+-define(GL_SHARED_TEXTURE_PALETTE_EXT, 16#81FB).
-define(GL_LIGHT_MODEL_COLOR_CONTROL_EXT, 16#81F8).
-define(GL_SINGLE_COLOR_EXT, 16#81F9).
-define(GL_SEPARATE_SPECULAR_COLOR_EXT, 16#81FA).
@@ -3387,7 +3418,6 @@
-define(GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT, 16#8DA7).
-define(GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT, 16#8DA8).
-define(GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT, 16#8DA9).
--define(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT, 16#8CD4).
-define(GL_PROGRAM_POINT_SIZE_EXT, 16#8642).
-define(GL_GEOMETRY_SHADER_EXT, 16#8DD9).
-define(GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT, 16#8DDD).
@@ -3425,13 +3455,6 @@
-define(GL_R11F_G11F_B10F_EXT, 16#8C3A).
-define(GL_UNSIGNED_INT_10F_11F_11F_REV_EXT, 16#8C3B).
-define(GL_RGBA_SIGNED_COMPONENTS_EXT, 16#8C3C).
--define(GL_TEXTURE_1D_ARRAY_EXT, 16#8C18).
--define(GL_PROXY_TEXTURE_1D_ARRAY_EXT, 16#8C19).
--define(GL_TEXTURE_2D_ARRAY_EXT, 16#8C1A).
--define(GL_PROXY_TEXTURE_2D_ARRAY_EXT, 16#8C1B).
--define(GL_TEXTURE_BINDING_1D_ARRAY_EXT, 16#8C1C).
--define(GL_TEXTURE_BINDING_2D_ARRAY_EXT, 16#8C1D).
--define(GL_MAX_ARRAY_TEXTURE_LAYERS_EXT, 16#88FF).
-define(GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT, 16#884E).
-define(GL_TEXTURE_BUFFER_EXT, 16#8C2A).
-define(GL_MAX_TEXTURE_BUFFER_SIZE_EXT, 16#8C2B).
@@ -3857,396 +3880,5 @@
-define(GL_SURFACE_REGISTERED_NV, 16#86FD).
-define(GL_SURFACE_MAPPED_NV, 16#8700).
-define(GL_WRITE_DISCARD_NV, 16#88BE).
--define(GL_VERSION_1_2, 1).
--define(GL_VERSION_1_2_DEPRECATED, 1).
--define(GL_VERSION_1_3, 1).
--define(GL_VERSION_1_3_DEPRECATED, 1).
--define(GL_VERSION_1_4, 1).
--define(GL_VERSION_1_4_DEPRECATED, 1).
--define(GL_VERSION_1_5, 1).
--define(GL_VERSION_2_0, 1).
--define(GL_VERSION_2_1, 1).
--define(GL_VERSION_3_0, 1).
--define(GL_VERSION_3_1, 1).
--define(GL_VERSION_3_2, 1).
--define(GL_VERSION_3_3, 1).
--define(GL_VERSION_4_0, 1).
--define(GL_VERSION_4_1, 1).
--define(GL_ARB_multitexture, 1).
--define(GL_ARB_transpose_matrix, 1).
--define(GL_ARB_multisample, 1).
--define(GL_ARB_texture_env_add, 1).
--define(GL_ARB_texture_cube_map, 1).
--define(GL_ARB_texture_compression, 1).
--define(GL_ARB_texture_border_clamp, 1).
--define(GL_ARB_point_parameters, 1).
--define(GL_ARB_vertex_blend, 1).
--define(GL_ARB_matrix_palette, 1).
--define(GL_ARB_texture_env_combine, 1).
--define(GL_ARB_texture_env_crossbar, 1).
--define(GL_ARB_texture_env_dot3, 1).
--define(GL_ARB_texture_mirrored_repeat, 1).
--define(GL_ARB_depth_texture, 1).
--define(GL_ARB_shadow, 1).
--define(GL_ARB_shadow_ambient, 1).
--define(GL_ARB_window_pos, 1).
--define(GL_ARB_vertex_program, 1).
--define(GL_ARB_fragment_program, 1).
--define(GL_ARB_vertex_buffer_object, 1).
--define(GL_ARB_occlusion_query, 1).
--define(GL_ARB_shader_objects, 1).
--define(GL_ARB_vertex_shader, 1).
--define(GL_ARB_fragment_shader, 1).
--define(GL_ARB_shading_language_100, 1).
--define(GL_ARB_texture_non_power_of_two, 1).
--define(GL_ARB_point_sprite, 1).
--define(GL_ARB_fragment_program_shadow, 1).
--define(GL_ARB_draw_buffers, 1).
--define(GL_ARB_texture_rectangle, 1).
--define(GL_ARB_color_buffer_float, 1).
--define(GL_ARB_half_float_pixel, 1).
--define(GL_ARB_texture_float, 1).
--define(GL_ARB_pixel_buffer_object, 1).
--define(GL_ARB_depth_buffer_float, 1).
--define(GL_ARB_draw_instanced, 1).
--define(GL_ARB_framebuffer_object, 1).
--define(GL_ARB_framebuffer_sRGB, 1).
--define(GL_ARB_geometry_shader4, 1).
--define(GL_ARB_half_float_vertex, 1).
--define(GL_ARB_instanced_arrays, 1).
--define(GL_ARB_map_buffer_range, 1).
--define(GL_ARB_texture_buffer_object, 1).
--define(GL_ARB_texture_compression_rgtc, 1).
--define(GL_ARB_texture_rg, 1).
--define(GL_ARB_vertex_array_object, 1).
--define(GL_ARB_uniform_buffer_object, 1).
--define(GL_ARB_compatibility, 1).
--define(GL_ARB_copy_buffer, 1).
--define(GL_ARB_shader_texture_lod, 1).
--define(GL_ARB_depth_clamp, 1).
--define(GL_ARB_draw_elements_base_vertex, 1).
--define(GL_ARB_fragment_coord_conventions, 1).
--define(GL_ARB_provoking_vertex, 1).
--define(GL_ARB_seamless_cube_map, 1).
--define(GL_ARB_sync, 1).
--define(GL_ARB_texture_multisample, 1).
--define(GL_ARB_vertex_array_bgra, 1).
--define(GL_ARB_draw_buffers_blend, 1).
--define(GL_ARB_sample_shading, 1).
--define(GL_ARB_texture_cube_map_array, 1).
--define(GL_ARB_texture_gather, 1).
--define(GL_ARB_texture_query_lod, 1).
--define(GL_ARB_shading_language_include, 1).
--define(GL_ARB_texture_compression_bptc, 1).
--define(GL_ARB_blend_func_extended, 1).
--define(GL_ARB_explicit_attrib_location, 1).
--define(GL_ARB_occlusion_query2, 1).
--define(GL_ARB_sampler_objects, 1).
--define(GL_ARB_texture_rgb10_a2ui, 1).
--define(GL_ARB_texture_swizzle, 1).
--define(GL_ARB_timer_query, 1).
--define(GL_ARB_vertex_type_2_10_10_10_rev, 1).
--define(GL_ARB_draw_indirect, 1).
--define(GL_ARB_gpu_shader5, 1).
--define(GL_ARB_gpu_shader_fp64, 1).
--define(GL_ARB_shader_subroutine, 1).
--define(GL_ARB_tessellation_shader, 1).
--define(GL_ARB_texture_buffer_object_rgb32, 1).
--define(GL_ARB_transform_feedback2, 1).
--define(GL_ARB_transform_feedback3, 1).
--define(GL_ARB_ES2_compatibility, 1).
--define(GL_ARB_get_program_binary, 1).
--define(GL_ARB_separate_shader_objects, 1).
--define(GL_ARB_vertex_attrib_64bit, 1).
--define(GL_ARB_viewport_array, 1).
--define(GL_ARB_cl_event, 1).
--define(GL_ARB_debug_output, 1).
--define(GL_ARB_robustness, 1).
--define(GL_ARB_shader_stencil_export, 1).
--define(GL_EXT_abgr, 1).
--define(GL_EXT_blend_color, 1).
--define(GL_EXT_polygon_offset, 1).
--define(GL_EXT_texture, 1).
--define(GL_EXT_texture3D, 1).
--define(GL_SGIS_texture_filter4, 1).
--define(GL_EXT_subtexture, 1).
--define(GL_EXT_copy_texture, 1).
--define(GL_EXT_histogram, 1).
--define(GL_EXT_convolution, 1).
--define(GL_SGI_color_matrix, 1).
--define(GL_SGI_color_table, 1).
--define(GL_SGIX_pixel_texture, 1).
--define(GL_SGIS_pixel_texture, 1).
--define(GL_SGIS_texture4D, 1).
--define(GL_SGI_texture_color_table, 1).
--define(GL_EXT_cmyka, 1).
--define(GL_EXT_texture_object, 1).
--define(GL_SGIS_detail_texture, 1).
--define(GL_SGIS_sharpen_texture, 1).
--define(GL_EXT_packed_pixels, 1).
--define(GL_SGIS_texture_lod, 1).
--define(GL_SGIS_multisample, 1).
--define(GL_EXT_rescale_normal, 1).
--define(GL_EXT_vertex_array, 1).
--define(GL_EXT_misc_attribute, 1).
--define(GL_SGIS_generate_mipmap, 1).
--define(GL_SGIX_clipmap, 1).
--define(GL_SGIX_shadow, 1).
--define(GL_SGIS_texture_edge_clamp, 1).
--define(GL_SGIS_texture_border_clamp, 1).
--define(GL_EXT_blend_minmax, 1).
--define(GL_EXT_blend_subtract, 1).
--define(GL_EXT_blend_logic_op, 1).
--define(GL_SGIX_interlace, 1).
--define(GL_SGIX_pixel_tiles, 1).
--define(GL_SGIX_texture_select, 1).
--define(GL_SGIX_sprite, 1).
--define(GL_SGIX_texture_multi_buffer, 1).
--define(GL_EXT_point_parameters, 1).
--define(GL_SGIS_point_parameters, 1).
--define(GL_SGIX_instruments, 1).
--define(GL_SGIX_texture_scale_bias, 1).
--define(GL_SGIX_framezoom, 1).
--define(GL_SGIX_tag_sample_buffer, 1).
--define(GL_SGIX_polynomial_ffd, 1).
--define(GL_SGIX_reference_plane, 1).
--define(GL_SGIX_flush_raster, 1).
--define(GL_SGIX_depth_texture, 1).
--define(GL_SGIS_fog_function, 1).
--define(GL_SGIX_fog_offset, 1).
--define(GL_HP_image_transform, 1).
--define(GL_HP_convolution_border_modes, 1).
--define(GL_SGIX_texture_add_env, 1).
--define(GL_EXT_color_subtable, 1).
--define(GL_PGI_vertex_hints, 1).
--define(GL_PGI_misc_hints, 1).
--define(GL_EXT_paletted_texture, 1).
--define(GL_EXT_clip_volume_hint, 1).
--define(GL_SGIX_list_priority, 1).
--define(GL_SGIX_ir_instrument1, 1).
--define(GL_SGIX_calligraphic_fragment, 1).
--define(GL_SGIX_texture_lod_bias, 1).
--define(GL_SGIX_shadow_ambient, 1).
--define(GL_EXT_index_texture, 1).
--define(GL_EXT_index_material, 1).
--define(GL_EXT_index_func, 1).
--define(GL_EXT_index_array_formats, 1).
--define(GL_EXT_compiled_vertex_array, 1).
--define(GL_EXT_cull_vertex, 1).
--define(GL_SGIX_ycrcb, 1).
--define(GL_SGIX_fragment_lighting, 1).
--define(GL_IBM_rasterpos_clip, 1).
--define(GL_HP_texture_lighting, 1).
--define(GL_EXT_draw_range_elements, 1).
--define(GL_WIN_phong_shading, 1).
--define(GL_WIN_specular_fog, 1).
--define(GL_EXT_light_texture, 1).
--define(GL_SGIX_blend_alpha_minmax, 1).
--define(GL_EXT_bgra, 1).
--define(GL_SGIX_async, 1).
--define(GL_SGIX_async_pixel, 1).
--define(GL_SGIX_async_histogram, 1).
--define(GL_INTEL_parallel_arrays, 1).
--define(GL_HP_occlusion_test, 1).
--define(GL_EXT_pixel_transform, 1).
--define(GL_EXT_pixel_transform_color_table, 1).
--define(GL_EXT_shared_texture_palette, 1).
--define(GL_EXT_separate_specular_color, 1).
--define(GL_EXT_secondary_color, 1).
--define(GL_EXT_texture_perturb_normal, 1).
--define(GL_EXT_multi_draw_arrays, 1).
--define(GL_EXT_fog_coord, 1).
--define(GL_REND_screen_coordinates, 1).
--define(GL_EXT_coordinate_frame, 1).
--define(GL_EXT_texture_env_combine, 1).
--define(GL_APPLE_specular_vector, 1).
--define(GL_APPLE_transform_hint, 1).
--define(GL_SGIX_fog_scale, 1).
--define(GL_SUNX_constant_data, 1).
--define(GL_SUN_global_alpha, 1).
--define(GL_SUN_triangle_list, 1).
--define(GL_SUN_vertex, 1).
--define(GL_EXT_blend_func_separate, 1).
--define(GL_INGR_blend_func_separate, 1).
--define(GL_INGR_color_clamp, 1).
--define(GL_INGR_interlace_read, 1).
--define(GL_EXT_stencil_wrap, 1).
--define(GL_EXT_422_pixels, 1).
--define(GL_NV_texgen_reflection, 1).
--define(GL_SUN_convolution_border_modes, 1).
--define(GL_EXT_texture_env_add, 1).
--define(GL_EXT_texture_lod_bias, 1).
--define(GL_EXT_texture_filter_anisotropic, 1).
--define(GL_EXT_vertex_weighting, 1).
--define(GL_NV_light_max_exponent, 1).
--define(GL_NV_vertex_array_range, 1).
--define(GL_NV_register_combiners, 1).
--define(GL_NV_fog_distance, 1).
--define(GL_NV_texgen_emboss, 1).
--define(GL_NV_blend_square, 1).
--define(GL_NV_texture_env_combine4, 1).
--define(GL_MESA_resize_buffers, 1).
--define(GL_MESA_window_pos, 1).
--define(GL_IBM_cull_vertex, 1).
--define(GL_IBM_multimode_draw_arrays, 1).
--define(GL_IBM_vertex_array_lists, 1).
--define(GL_SGIX_subsample, 1).
--define(GL_SGIX_ycrcba, 1).
--define(GL_SGIX_ycrcb_subsample, 1).
--define(GL_SGIX_depth_pass_instrument, 1).
--define(GL_3DFX_texture_compression_FXT1, 1).
--define(GL_3DFX_multisample, 1).
--define(GL_3DFX_tbuffer, 1).
--define(GL_EXT_multisample, 1).
--define(GL_SGIX_vertex_preclip, 1).
--define(GL_SGIX_convolution_accuracy, 1).
--define(GL_SGIX_resample, 1).
--define(GL_SGIS_point_line_texgen, 1).
--define(GL_SGIS_texture_color_mask, 1).
--define(GL_SGIX_igloo_interface, 1).
--define(GL_EXT_texture_env_dot3, 1).
--define(GL_ATI_texture_mirror_once, 1).
--define(GL_NV_fence, 1).
--define(GL_NV_evaluators, 1).
--define(GL_NV_packed_depth_stencil, 1).
--define(GL_NV_register_combiners2, 1).
--define(GL_NV_texture_compression_vtc, 1).
--define(GL_NV_texture_rectangle, 1).
--define(GL_NV_texture_shader, 1).
--define(GL_NV_texture_shader2, 1).
--define(GL_NV_vertex_array_range2, 1).
--define(GL_NV_vertex_program, 1).
--define(GL_SGIX_texture_coordinate_clamp, 1).
--define(GL_SGIX_scalebias_hint, 1).
--define(GL_OML_interlace, 1).
--define(GL_OML_subsample, 1).
--define(GL_OML_resample, 1).
--define(GL_NV_copy_depth_to_color, 1).
--define(GL_ATI_envmap_bumpmap, 1).
--define(GL_ATI_fragment_shader, 1).
--define(GL_ATI_pn_triangles, 1).
--define(GL_ATI_vertex_array_object, 1).
--define(GL_EXT_vertex_shader, 1).
--define(GL_ATI_vertex_streams, 1).
--define(GL_ATI_element_array, 1).
--define(GL_SUN_mesh_array, 1).
--define(GL_SUN_slice_accum, 1).
--define(GL_NV_multisample_filter_hint, 1).
--define(GL_NV_depth_clamp, 1).
--define(GL_NV_occlusion_query, 1).
--define(GL_NV_point_sprite, 1).
--define(GL_NV_texture_shader3, 1).
--define(GL_NV_vertex_program1_1, 1).
--define(GL_EXT_shadow_funcs, 1).
--define(GL_EXT_stencil_two_side, 1).
--define(GL_ATI_text_fragment_shader, 1).
--define(GL_APPLE_client_storage, 1).
--define(GL_APPLE_element_array, 1).
--define(GL_APPLE_fence, 1).
--define(GL_APPLE_vertex_array_object, 1).
--define(GL_APPLE_vertex_array_range, 1).
--define(GL_APPLE_ycbcr_422, 1).
--define(GL_S3_s3tc, 1).
--define(GL_ATI_draw_buffers, 1).
--define(GL_ATI_pixel_format_float, 1).
--define(GL_ATI_texture_env_combine3, 1).
--define(GL_ATI_texture_float, 1).
--define(GL_NV_float_buffer, 1).
--define(GL_NV_fragment_program, 1).
--define(GL_NV_half_float, 1).
--define(GL_NV_pixel_data_range, 1).
--define(GL_NV_primitive_restart, 1).
--define(GL_NV_texture_expand_normal, 1).
--define(GL_NV_vertex_program2, 1).
--define(GL_ATI_map_object_buffer, 1).
--define(GL_ATI_separate_stencil, 1).
--define(GL_ATI_vertex_attrib_array_object, 1).
--define(GL_OES_read_format, 1).
--define(GL_EXT_depth_bounds_test, 1).
--define(GL_EXT_texture_mirror_clamp, 1).
--define(GL_EXT_blend_equation_separate, 1).
--define(GL_MESA_pack_invert, 1).
--define(GL_MESA_ycbcr_texture, 1).
--define(GL_EXT_pixel_buffer_object, 1).
--define(GL_NV_fragment_program_option, 1).
--define(GL_NV_fragment_program2, 1).
--define(GL_NV_vertex_program2_option, 1).
--define(GL_NV_vertex_program3, 1).
--define(GL_EXT_framebuffer_object, 1).
--define(GL_GREMEDY_string_marker, 1).
--define(GL_EXT_packed_depth_stencil, 1).
--define(GL_EXT_stencil_clear_tag, 1).
--define(GL_EXT_texture_sRGB, 1).
--define(GL_EXT_framebuffer_blit, 1).
--define(GL_EXT_framebuffer_multisample, 1).
--define(GL_MESAX_texture_stack, 1).
--define(GL_EXT_timer_query, 1).
--define(GL_EXT_gpu_program_parameters, 1).
--define(GL_APPLE_flush_buffer_range, 1).
--define(GL_NV_gpu_program4, 1).
--define(GL_NV_geometry_program4, 1).
--define(GL_EXT_geometry_shader4, 1).
--define(GL_NV_vertex_program4, 1).
--define(GL_EXT_gpu_shader4, 1).
--define(GL_EXT_draw_instanced, 1).
--define(GL_EXT_packed_float, 1).
--define(GL_EXT_texture_array, 1).
--define(GL_EXT_texture_buffer_object, 1).
--define(GL_EXT_texture_compression_latc, 1).
--define(GL_EXT_texture_compression_rgtc, 1).
--define(GL_EXT_texture_shared_exponent, 1).
--define(GL_NV_depth_buffer_float, 1).
--define(GL_NV_fragment_program4, 1).
--define(GL_NV_framebuffer_multisample_coverage, 1).
--define(GL_EXT_framebuffer_sRGB, 1).
--define(GL_NV_geometry_shader4, 1).
--define(GL_NV_parameter_buffer_object, 1).
--define(GL_EXT_draw_buffers2, 1).
--define(GL_NV_transform_feedback, 1).
--define(GL_EXT_bindable_uniform, 1).
--define(GL_EXT_texture_integer, 1).
--define(GL_GREMEDY_frame_terminator, 1).
--define(GL_NV_conditional_render, 1).
--define(GL_NV_present_video, 1).
--define(GL_EXT_transform_feedback, 1).
--define(GL_EXT_direct_state_access, 1).
--define(GL_EXT_vertex_array_bgra, 1).
--define(GL_EXT_texture_swizzle, 1).
--define(GL_NV_explicit_multisample, 1).
--define(GL_NV_transform_feedback2, 1).
--define(GL_ATI_meminfo, 1).
--define(GL_AMD_performance_monitor, 1).
--define(GL_AMD_texture_texture4, 1).
--define(GL_AMD_vertex_shader_tesselator, 1).
--define(GL_EXT_provoking_vertex, 1).
--define(GL_EXT_texture_snorm, 1).
--define(GL_AMD_draw_buffers_blend, 1).
--define(GL_APPLE_texture_range, 1).
--define(GL_APPLE_float_pixels, 1).
--define(GL_APPLE_vertex_program_evaluators, 1).
--define(GL_APPLE_aux_depth_stencil, 1).
--define(GL_APPLE_object_purgeable, 1).
--define(GL_APPLE_row_bytes, 1).
--define(GL_APPLE_rgb_422, 1).
--define(GL_NV_video_capture, 1).
--define(GL_NV_copy_image, 1).
--define(GL_EXT_separate_shader_objects, 1).
--define(GL_NV_parameter_buffer_object2, 1).
--define(GL_NV_shader_buffer_load, 1).
--define(GL_NV_vertex_buffer_unified_memory, 1).
--define(GL_NV_texture_barrier, 1).
--define(GL_AMD_shader_stencil_export, 1).
--define(GL_AMD_seamless_cubemap_per_texture, 1).
--define(GL_AMD_conservative_depth, 1).
--define(GL_EXT_shader_image_load_store, 1).
--define(GL_EXT_vertex_attrib_64bit, 1).
--define(GL_NV_gpu_program5, 1).
--define(GL_NV_gpu_shader5, 1).
--define(GL_NV_shader_buffer_store, 1).
--define(GL_NV_tessellation_program5, 1).
--define(GL_NV_vertex_attrib_integer_64bit, 1).
--define(GL_NV_multisample_coverage, 1).
--define(GL_AMD_name_gen_delete, 1).
--define(GL_AMD_debug_output, 1).
--define(GL_NV_vdpau_interop, 1).
--define(GL_AMD_transform_feedback3_lines_triangles, 1).
+-define(GL_DEPTH_CLAMP_NEAR_AMD, 16#901E).
+-define(GL_DEPTH_CLAMP_FAR_AMD, 16#901F).
diff --git a/lib/wx/src/Makefile b/lib/wx/src/Makefile
index 3cc668375f..46bc06271c 100644
--- a/lib/wx/src/Makefile
+++ b/lib/wx/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2010. All Rights Reserved.
+# Copyright Ericsson AB 2008-2011. All Rights Reserved.
#
# The 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,8 +29,7 @@ ERL_COMPILE_FLAGS += -I$(ERLINC) +warn_unused_vars
ARCHIVE = wx-$(VSN).ez
-ErlMods = \
- wx \
+ErlMods = wx \
wx_object \
wxe_master \
wxe_server \
@@ -44,7 +43,7 @@ GEN_FILES = $(wildcard gen/wx*.erl) \
gen/glu.erl \
gen/gl.erl
-GEN_MODS = $(GEN_FILES:gen/%.erl= %,\n )
+GEN_MODS = $(GEN_FILES:gen/%.erl=%,)
GEN_HRL = \
$(EGEN)/wxe_debug.hrl \
diff --git a/lib/wx/src/gen/wxBoxSizer.erl b/lib/wx/src/gen/wxBoxSizer.erl
index 1d5b1cf2fa..e6287945a9 100644
--- a/lib/wx/src/gen/wxBoxSizer.erl
+++ b/lib/wx/src/gen/wxBoxSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -102,7 +102,7 @@ prepend(This,Width,Height, Options) -> wxSizer:prepend(This,Width,Height, Option
%% @hidden
prepend(This,Width,Height) -> wxSizer:prepend(This,Width,Height).
%% @hidden
-prepend(This,Window) -> wxSizer:prepend(This,Window).
+prepend(This,Item) -> wxSizer:prepend(This,Item).
%% @hidden
layout(This) -> wxSizer:layout(This).
%% @hidden
@@ -118,7 +118,7 @@ insert(This,Index,Width,Height, Options) -> wxSizer:insert(This,Index,Width,Heig
%% @hidden
insert(This,Index,Width,Height) -> wxSizer:insert(This,Index,Width,Height).
%% @hidden
-insert(This,Index,Window) -> wxSizer:insert(This,Index,Window).
+insert(This,Index,Item) -> wxSizer:insert(This,Index,Item).
%% @hidden
hide(This,Window, Options) -> wxSizer:hide(This,Window, Options).
%% @hidden
diff --git a/lib/wx/src/gen/wxFlexGridSizer.erl b/lib/wx/src/gen/wxFlexGridSizer.erl
index 9471cc8a01..910cc78894 100644
--- a/lib/wx/src/gen/wxFlexGridSizer.erl
+++ b/lib/wx/src/gen/wxFlexGridSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -222,7 +222,7 @@ prepend(This,Width,Height, Options) -> wxSizer:prepend(This,Width,Height, Option
%% @hidden
prepend(This,Width,Height) -> wxSizer:prepend(This,Width,Height).
%% @hidden
-prepend(This,Window) -> wxSizer:prepend(This,Window).
+prepend(This,Item) -> wxSizer:prepend(This,Item).
%% @hidden
layout(This) -> wxSizer:layout(This).
%% @hidden
@@ -238,7 +238,7 @@ insert(This,Index,Width,Height, Options) -> wxSizer:insert(This,Index,Width,Heig
%% @hidden
insert(This,Index,Width,Height) -> wxSizer:insert(This,Index,Width,Height).
%% @hidden
-insert(This,Index,Window) -> wxSizer:insert(This,Index,Window).
+insert(This,Index,Item) -> wxSizer:insert(This,Index,Item).
%% @hidden
hide(This,Window, Options) -> wxSizer:hide(This,Window, Options).
%% @hidden
diff --git a/lib/wx/src/gen/wxGridBagSizer.erl b/lib/wx/src/gen/wxGridBagSizer.erl
index d8cc210d3b..cfc182cf89 100644
--- a/lib/wx/src/gen/wxGridBagSizer.erl
+++ b/lib/wx/src/gen/wxGridBagSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -474,7 +474,7 @@ prepend(This,Width,Height, Options) -> wxSizer:prepend(This,Width,Height, Option
%% @hidden
prepend(This,Width,Height) -> wxSizer:prepend(This,Width,Height).
%% @hidden
-prepend(This,Window) -> wxSizer:prepend(This,Window).
+prepend(This,Item) -> wxSizer:prepend(This,Item).
%% @hidden
layout(This) -> wxSizer:layout(This).
%% @hidden
@@ -490,7 +490,7 @@ insert(This,Index,Width,Height, Options) -> wxSizer:insert(This,Index,Width,Heig
%% @hidden
insert(This,Index,Width,Height) -> wxSizer:insert(This,Index,Width,Height).
%% @hidden
-insert(This,Index,Window) -> wxSizer:insert(This,Index,Window).
+insert(This,Index,Item) -> wxSizer:insert(This,Index,Item).
%% @hidden
hide(This,Window, Options) -> wxSizer:hide(This,Window, Options).
%% @hidden
diff --git a/lib/wx/src/gen/wxGridSizer.erl b/lib/wx/src/gen/wxGridSizer.erl
index 7b62774347..fd8580c70d 100644
--- a/lib/wx/src/gen/wxGridSizer.erl
+++ b/lib/wx/src/gen/wxGridSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -174,7 +174,7 @@ prepend(This,Width,Height, Options) -> wxSizer:prepend(This,Width,Height, Option
%% @hidden
prepend(This,Width,Height) -> wxSizer:prepend(This,Width,Height).
%% @hidden
-prepend(This,Window) -> wxSizer:prepend(This,Window).
+prepend(This,Item) -> wxSizer:prepend(This,Item).
%% @hidden
layout(This) -> wxSizer:layout(This).
%% @hidden
@@ -190,7 +190,7 @@ insert(This,Index,Width,Height, Options) -> wxSizer:insert(This,Index,Width,Heig
%% @hidden
insert(This,Index,Width,Height) -> wxSizer:insert(This,Index,Width,Height).
%% @hidden
-insert(This,Index,Window) -> wxSizer:insert(This,Index,Window).
+insert(This,Index,Item) -> wxSizer:insert(This,Index,Item).
%% @hidden
hide(This,Window, Options) -> wxSizer:hide(This,Window, Options).
%% @hidden
diff --git a/lib/wx/src/gen/wxListCtrl.erl b/lib/wx/src/gen/wxListCtrl.erl
index 9c4ba1e5a3..5799206b87 100644
--- a/lib/wx/src/gen/wxListCtrl.erl
+++ b/lib/wx/src/gen/wxListCtrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The 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,17 +29,17 @@
-module(wxListCtrl).
-include("wxe.hrl").
--export([ sortItems/2 ,arrange/1,arrange/2,assignImageList/3,clearAll/1,create/2,
- create/3,deleteAllItems/1,deleteColumn/2,deleteItem/2,destroy/1,editLabel/2,
- ensureVisible/2,findItem/3,findItem/4,getColumn/3,getColumnCount/1,
- getColumnWidth/2,getCountPerPage/1,getEditControl/1,getImageList/2,
- getItem/2,getItemBackgroundColour/2,getItemCount/1,getItemData/2,
- getItemFont/2,getItemPosition/3,getItemRect/3,getItemRect/4,getItemSpacing/1,
- getItemState/3,getItemText/2,getItemTextColour/2,getNextItem/2,getNextItem/3,
- getSelectedItemCount/1,getTextColour/1,getTopItem/1,getViewRect/1,
- hitTest/2,insertColumn/3,insertColumn/4,insertItem/2,insertItem/3,
- insertItem/4,new/0,new/1,new/2,refreshItem/2,refreshItems/3,scrollList/3,
- setBackgroundColour/2,setColumn/3,setColumnWidth/3,setImageList/3,
+-export([ create/2, create/3 , new/0, new/1, new/2 , sortItems/2 ,arrange/1,
+ arrange/2,assignImageList/3,clearAll/1,deleteAllItems/1,deleteColumn/2,
+ deleteItem/2,destroy/1,editLabel/2,ensureVisible/2,findItem/3,findItem/4,
+ getColumn/3,getColumnCount/1,getColumnWidth/2,getCountPerPage/1,getEditControl/1,
+ getImageList/2,getItem/2,getItemBackgroundColour/2,getItemCount/1,
+ getItemData/2,getItemFont/2,getItemPosition/3,getItemRect/3,getItemRect/4,
+ getItemSpacing/1,getItemState/3,getItemText/2,getItemTextColour/2,
+ getNextItem/2,getNextItem/3,getSelectedItemCount/1,getTextColour/1,
+ getTopItem/1,getViewRect/1,hitTest/2,insertColumn/3,insertColumn/4,
+ insertItem/2,insertItem/3,insertItem/4,refreshItem/2,refreshItems/3,
+ scrollList/3,setBackgroundColour/2,setColumn/3,setColumnWidth/3,setImageList/3,
setItem/2,setItem/4,setItem/5,setItemBackgroundColour/3,setItemColumnImage/4,
setItemCount/2,setItemData/3,setItemFont/3,setItemImage/3,setItemImage/4,
setItemPosition/3,setItemState/4,setItemText/3,setItemTextColour/3,
@@ -89,11 +89,11 @@ parent_class(wxWindow) -> true;
parent_class(wxEvtHandler) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+
%% @spec () -> wxListCtrl()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlwxlistctrl">external documentation</a>.
new() ->
- wxe_util:construct(?wxListCtrl_new_0,
- <<>>).
+ wxe_util:construct(?wxListCtrl_new_0, <<>>).
%% @spec (Parent::wxWindow:wxWindow()) -> wxListCtrl()
%% @equiv new(Parent, [])
@@ -102,20 +102,44 @@ new(Parent)
new(Parent, []).
%% @spec (Parent::wxWindow:wxWindow(), [Option]) -> wxListCtrl()
-%% Option = {winid, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {winid, integer()} |
+%% {pos, {X::integer(),Y::integer()}} |
+%% {size, {W::integer(),H::integer()}} |
+%% {style, integer()} |
+%% {validator, wx:wx()} |
+%% {onGetItemText, OnGetItemText} |
+%% {onGetItemAttr, OnGetItemAttr} |
+%% {onGetItemColumnImage, OnGetItemColumnImage}
+%%
+%% OnGetItemText = (This, Item, Column) -> wxString()
+%% OnGetItemAttr = (This, Item) -> wxListItemAttr()
+%% OnGetItemColumnImage = (This, Item, Column) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlwxlistctrl">external documentation</a>.
+
new(#wx_ref{type=ParentT,ref=ParentRef}, Options)
- when is_list(Options) ->
- ?CLASS(ParentT,wxWindow),
- MOpts = fun({winid, Winid}, Acc) -> [<<1:32/?UI,Winid:32/?UI>>|Acc];
- ({pos, {PosX,PosY}}, Acc) -> [<<2:32/?UI,PosX:32/?UI,PosY:32/?UI,0:32>>|Acc];
- ({size, {SizeW,SizeH}}, Acc) -> [<<3:32/?UI,SizeW:32/?UI,SizeH:32/?UI,0:32>>|Acc];
- ({style, Style}, Acc) -> [<<4:32/?UI,Style:32/?UI>>|Acc];
- ({validator, #wx_ref{type=ValidatorT,ref=ValidatorRef}}, Acc) -> ?CLASS(ValidatorT,wx),[<<5:32/?UI,ValidatorRef:32/?UI>>|Acc];
- (BadOpt, _) -> erlang:error({badoption, BadOpt}) end,
- BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)),
- wxe_util:construct(?wxListCtrl_new_2,
- <<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
+ when is_list(Options)->
+ ?CLASS(ParentT,wxWindow),
+ MOpts = fun({winid, Winid}, Acc) -> [<<1:32/?UI,Winid:32/?UI>>|Acc];
+ ({pos, {PosX,PosY}}, Acc) -> [<<2:32/?UI,PosX:32/?UI,PosY:32/?UI,0:32>>|Acc];
+ ({size, {SizeW,SizeH}}, Acc) -> [<<3:32/?UI,SizeW:32/?UI,SizeH:32/?UI,0:32>>|Acc];
+ ({style, Style}, Acc) -> [<<4:32/?UI,Style:32/?UI>>|Acc];
+ ({validator, #wx_ref{type=ValidatorT,ref=ValidatorRef}}, Acc) ->
+ ?CLASS(ValidatorT,wx),[<<5:32/?UI,ValidatorRef:32/?UI>>|Acc];
+ ({onGetItemText, F}, Acc) when is_function(F) ->
+ Fun = fun([This,Item,Col]) -> unicode:characters_to_binary([F(This,Item,Col),0]) end,
+ [<<6:32/?UI,(wxe_util:get_cbId(Fun)):32/?UI>>|Acc];
+ ({onGetItemAttr, F}, Acc) when is_function(F) ->
+ Fun = fun([This,Item]) ->
+ #wx_ref{type=wxListItemAttr,ref=ThisRef} = F(This,Item),
+ <<ThisRef:32/?UI>>
+ end,
+ [<<7:32/?UI,(wxe_util:get_cbId(Fun)):32/?UI>>|Acc];
+ ({onGetItemColumnImage, F}, Acc) when is_function(F) ->
+ Fun = fun([This,Item, Col]) -> <<(F(This,Item,Col)):32/?I>> end,
+ [<<8:32/?UI,(wxe_util:get_cbId(Fun)):32/?UI>>|Acc];
+ (BadOpt, _) -> erlang:error({badoption, BadOpt}) end,
+ BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)),
+ wxe_util:construct(?wxListCtrl_new_2, <<ParentRef:32/?UI, 0:32,BinOpt/binary>>).
%% @spec (This::wxListCtrl()) -> bool()
%% @equiv arrange(This, [])
@@ -151,6 +175,7 @@ clearAll(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:cast(?wxListCtrl_ClearAll,
<<ThisRef:32/?UI>>).
+
%% @spec (This::wxListCtrl(), Parent::wxWindow:wxWindow()) -> bool()
%% @equiv create(This,Parent, [])
create(This,Parent)
@@ -158,7 +183,18 @@ create(This,Parent)
create(This,Parent, []).
%% @spec (This::wxListCtrl(), Parent::wxWindow:wxWindow(), [Option]) -> bool()
-%% Option = {winid, integer()} | {pos, {X::integer(),Y::integer()}} | {size, {W::integer(),H::integer()}} | {style, integer()} | {validator, wx:wx()}
+%% Option = {winid, integer()} |
+%% {pos, {X::integer(),Y::integer()}} |
+%% {size, {W::integer(),H::integer()}} |
+%% {style, integer()} |
+%% {validator, wx:wx()} |
+%% {onGetItemText, OnGetItemText} |
+%% {onGetItemAttr, OnGetItemAttr} |
+%% {onGetItemColumnImage, OnGetItemColumnImage}
+%%
+%% OnGetItemText = (This, Item, Column) -> wxString()
+%% OnGetItemAttr = (This, Item) -> wxListItemAttr()
+%% OnGetItemColumnImage = (This, Item, Column) -> integer()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistctrl.html#wxlistctrlcreate">external documentation</a>.
create(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ParentT,ref=ParentRef}, Options)
when is_list(Options) ->
@@ -726,12 +762,12 @@ setWindowStyleFlag(#wx_ref{type=ThisT,ref=ThisRef},Style)
%% @spec (This::wxListCtrl(), SortCallBack::function()) -> boolean()
%% @doc Sort the items in the list control<br />
-%% <pre>SortCalBack(Item1,Item2) -> integer()</pre>
+%% <pre>SortCallBack(Item1,Item2) -> integer()</pre>
%% <br /> SortCallBack receives the client data associated with two items
%% to compare, and should return 0 if the items are equal, a negative
%% value if the first item is less than the second one and a positive
%% value if the first item is greater than the second one.
-%% <br /> NOTE: The callback may not call other processes.
+%% <br /> NOTE: The callback may not call other (wx) processes.
sortItems(#wx_ref{type=ThisT,ref=ThisRef}, SortCallBack)
when is_function(SortCallBack, 2) ->
?CLASS(ThisT,wxListCtrl),
diff --git a/lib/wx/src/gen/wxListItemAttr.erl b/lib/wx/src/gen/wxListItemAttr.erl
new file mode 100644
index 0000000000..1a43c71854
--- /dev/null
+++ b/lib/wx/src/gen/wxListItemAttr.erl
@@ -0,0 +1,122 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 is generated DO NOT EDIT
+
+%% @doc See external documentation: <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html">wxListItemAttr</a>.
+%% @type wxListItemAttr(). An object reference, The representation is internal
+%% and can be changed without notice. It can't be used for comparsion
+%% stored on disc or distributed for use on other nodes.
+
+-module(wxListItemAttr).
+-include("wxe.hrl").
+-export([destroy/1,getBackgroundColour/1,getFont/1,getTextColour/1,hasBackgroundColour/1,
+ hasFont/1,hasTextColour/1,new/0,new/3,setBackgroundColour/2,setFont/2,
+ setTextColour/2]).
+
+%% inherited exports
+-export([parent_class/1]).
+
+%% @hidden
+parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
+
+%% @spec () -> wxListItemAttr()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrwxlistitemattr">external documentation</a>.
+new() ->
+ wxe_util:construct(?wxListItemAttr_new_0,
+ <<>>).
+
+%% @spec (ColText::wx:colour(), ColBack::wx:colour(), Font::wxFont:wxFont()) -> wxListItemAttr()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrwxlistitemattr">external documentation</a>.
+new(ColText,ColBack,#wx_ref{type=FontT,ref=FontRef})
+ when tuple_size(ColText) =:= 3; tuple_size(ColText) =:= 4,tuple_size(ColBack) =:= 3; tuple_size(ColBack) =:= 4 ->
+ ?CLASS(FontT,wxFont),
+ wxe_util:construct(?wxListItemAttr_new_3,
+ <<(wxe_util:colour_bin(ColText)):16/binary,(wxe_util:colour_bin(ColBack)):16/binary,FontRef:32/?UI>>).
+
+%% @spec (This::wxListItemAttr()) -> wx:colour()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrgetbackgroundcolour">external documentation</a>.
+getBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxListItemAttr),
+ wxe_util:call(?wxListItemAttr_GetBackgroundColour,
+ <<ThisRef:32/?UI>>).
+
+%% @spec (This::wxListItemAttr()) -> wxFont:wxFont()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrgetfont">external documentation</a>.
+getFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxListItemAttr),
+ wxe_util:call(?wxListItemAttr_GetFont,
+ <<ThisRef:32/?UI>>).
+
+%% @spec (This::wxListItemAttr()) -> wx:colour()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrgettextcolour">external documentation</a>.
+getTextColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxListItemAttr),
+ wxe_util:call(?wxListItemAttr_GetTextColour,
+ <<ThisRef:32/?UI>>).
+
+%% @spec (This::wxListItemAttr()) -> bool()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrhasbackgroundcolour">external documentation</a>.
+hasBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxListItemAttr),
+ wxe_util:call(?wxListItemAttr_HasBackgroundColour,
+ <<ThisRef:32/?UI>>).
+
+%% @spec (This::wxListItemAttr()) -> bool()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrhasfont">external documentation</a>.
+hasFont(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxListItemAttr),
+ wxe_util:call(?wxListItemAttr_HasFont,
+ <<ThisRef:32/?UI>>).
+
+%% @spec (This::wxListItemAttr()) -> bool()
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrhastextcolour">external documentation</a>.
+hasTextColour(#wx_ref{type=ThisT,ref=ThisRef}) ->
+ ?CLASS(ThisT,wxListItemAttr),
+ wxe_util:call(?wxListItemAttr_HasTextColour,
+ <<ThisRef:32/?UI>>).
+
+%% @spec (This::wxListItemAttr(), ColBack::wx:colour()) -> ok
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrsetbackgroundcolour">external documentation</a>.
+setBackgroundColour(#wx_ref{type=ThisT,ref=ThisRef},ColBack)
+ when tuple_size(ColBack) =:= 3; tuple_size(ColBack) =:= 4 ->
+ ?CLASS(ThisT,wxListItemAttr),
+ wxe_util:cast(?wxListItemAttr_SetBackgroundColour,
+ <<ThisRef:32/?UI,(wxe_util:colour_bin(ColBack)):16/binary>>).
+
+%% @spec (This::wxListItemAttr(), Font::wxFont:wxFont()) -> ok
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrsetfont">external documentation</a>.
+setFont(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=FontT,ref=FontRef}) ->
+ ?CLASS(ThisT,wxListItemAttr),
+ ?CLASS(FontT,wxFont),
+ wxe_util:cast(?wxListItemAttr_SetFont,
+ <<ThisRef:32/?UI,FontRef:32/?UI>>).
+
+%% @spec (This::wxListItemAttr(), ColText::wx:colour()) -> ok
+%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxlistitemattr.html#wxlistitemattrsettextcolour">external documentation</a>.
+setTextColour(#wx_ref{type=ThisT,ref=ThisRef},ColText)
+ when tuple_size(ColText) =:= 3; tuple_size(ColText) =:= 4 ->
+ ?CLASS(ThisT,wxListItemAttr),
+ wxe_util:cast(?wxListItemAttr_SetTextColour,
+ <<ThisRef:32/?UI,(wxe_util:colour_bin(ColText)):16/binary>>).
+
+%% @spec (This::wxListItemAttr()) -> ok
+%% @doc Destroys this object, do not use object again
+destroy(Obj=#wx_ref{type=Type}) ->
+ ?CLASS(Type,wxListItemAttr),
+ wxe_util:destroy(?wxListItemAttr_destroy,Obj),
+ ok.
diff --git a/lib/wx/src/gen/wxRegion.erl b/lib/wx/src/gen/wxRegion.erl
index 0ceba1d203..4e8d98a54f 100644
--- a/lib/wx/src/gen/wxRegion.erl
+++ b/lib/wx/src/gen/wxRegion.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -48,7 +48,7 @@ new() ->
%% new(Bmp::wxBitmap:wxBitmap()) -> wxRegion() </c>
%% </p>
%% <p><c>
-%% new(Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> wxRegion() </c>
+%% new(Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> wxRegion() </c>
%% </p>
new(#wx_ref{type=BmpT,ref=BmpRef}) ->
?CLASS(BmpT,wxBitmap),
diff --git a/lib/wx/src/gen/wxSizer.erl b/lib/wx/src/gen/wxSizer.erl
index 716b2224b5..e9b83a7333 100644
--- a/lib/wx/src/gen/wxSizer.erl
+++ b/lib/wx/src/gen/wxSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -298,18 +298,8 @@ hide(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=WindowT,ref=WindowRef}, Option
wxe_util:call(WindowOP,
<<ThisRef:32/?UI,WindowRef:32/?UI, BinOpt/binary>>).
-%% @spec (This::wxSizer(),Index::integer(),X::term()) -> wxSizerItem:wxSizerItem()
+%% @spec (This::wxSizer(), Index::integer(), Item::wxSizerItem:wxSizerItem()) -> wxSizerItem:wxSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerinsert">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% insert(This::wxSizer(), Index::integer(), Window::wxWindow:wxWindow() | wxSizer()) -> insert(This,Index,Window, []) </c></p>
-%% <p><c>
-%% insert(This::wxSizer(), Index::integer(), Item::wxSizerItem:wxSizerItem()) -> wxSizerItem:wxSizerItem() </c>
-%% </p>
-
-insert(This,Index,Window)
- when is_record(This, wx_ref),is_integer(Index),is_record(Window, wx_ref) ->
- insert(This,Index,Window, []);
insert(#wx_ref{type=ThisT,ref=ThisRef},Index,#wx_ref{type=ItemT,ref=ItemRef})
when is_integer(Index) ->
?CLASS(ThisT,wxSizer),
@@ -437,18 +427,8 @@ layout(#wx_ref{type=ThisT,ref=ThisRef}) ->
wxe_util:cast(?wxSizer_Layout,
<<ThisRef:32/?UI>>).
-%% @spec (This::wxSizer(),X::term()) -> wxSizerItem:wxSizerItem()
+%% @spec (This::wxSizer(), Item::wxSizerItem:wxSizerItem()) -> wxSizerItem:wxSizerItem()
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxsizer.html#wxsizerprepend">external documentation</a>.
-%% <br /> Alternatives:
-%% <p><c>
-%% prepend(This::wxSizer(), Window::wxWindow:wxWindow() | wxSizer()) -> prepend(This,Window, []) </c></p>
-%% <p><c>
-%% prepend(This::wxSizer(), Item::wxSizerItem:wxSizerItem()) -> wxSizerItem:wxSizerItem() </c>
-%% </p>
-
-prepend(This,Window)
- when is_record(This, wx_ref),is_record(Window, wx_ref) ->
- prepend(This,Window, []);
prepend(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=ItemT,ref=ItemRef}) ->
?CLASS(ThisT,wxSizer),
?CLASS(ItemT,wxSizerItem),
diff --git a/lib/wx/src/gen/wxStaticBoxSizer.erl b/lib/wx/src/gen/wxStaticBoxSizer.erl
index 5f346b7a1e..2cf9f64325 100644
--- a/lib/wx/src/gen/wxStaticBoxSizer.erl
+++ b/lib/wx/src/gen/wxStaticBoxSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -130,7 +130,7 @@ prepend(This,Width,Height, Options) -> wxSizer:prepend(This,Width,Height, Option
%% @hidden
prepend(This,Width,Height) -> wxSizer:prepend(This,Width,Height).
%% @hidden
-prepend(This,Window) -> wxSizer:prepend(This,Window).
+prepend(This,Item) -> wxSizer:prepend(This,Item).
%% @hidden
layout(This) -> wxSizer:layout(This).
%% @hidden
@@ -146,7 +146,7 @@ insert(This,Index,Width,Height, Options) -> wxSizer:insert(This,Index,Width,Heig
%% @hidden
insert(This,Index,Width,Height) -> wxSizer:insert(This,Index,Width,Height).
%% @hidden
-insert(This,Index,Window) -> wxSizer:insert(This,Index,Window).
+insert(This,Index,Item) -> wxSizer:insert(This,Index,Item).
%% @hidden
hide(This,Window, Options) -> wxSizer:hide(This,Window, Options).
%% @hidden
diff --git a/lib/wx/src/gen/wxStdDialogButtonSizer.erl b/lib/wx/src/gen/wxStdDialogButtonSizer.erl
index b0052ca2e1..3d31907275 100644
--- a/lib/wx/src/gen/wxStdDialogButtonSizer.erl
+++ b/lib/wx/src/gen/wxStdDialogButtonSizer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -139,7 +139,7 @@ prepend(This,Width,Height, Options) -> wxSizer:prepend(This,Width,Height, Option
%% @hidden
prepend(This,Width,Height) -> wxSizer:prepend(This,Width,Height).
%% @hidden
-prepend(This,Window) -> wxSizer:prepend(This,Window).
+prepend(This,Item) -> wxSizer:prepend(This,Item).
%% @hidden
layout(This) -> wxSizer:layout(This).
%% @hidden
@@ -155,7 +155,7 @@ insert(This,Index,Width,Height, Options) -> wxSizer:insert(This,Index,Width,Heig
%% @hidden
insert(This,Index,Width,Height) -> wxSizer:insert(This,Index,Width,Height).
%% @hidden
-insert(This,Index,Window) -> wxSizer:insert(This,Index,Window).
+insert(This,Index,Item) -> wxSizer:insert(This,Index,Item).
%% @hidden
hide(This,Window, Options) -> wxSizer:hide(This,Window, Options).
%% @hidden
diff --git a/lib/wx/src/gen/wxWindow.erl b/lib/wx/src/gen/wxWindow.erl
index 33665a0ad6..031314bfe2 100644
--- a/lib/wx/src/gen/wxWindow.erl
+++ b/lib/wx/src/gen/wxWindow.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1144,10 +1144,10 @@ setCaret(#wx_ref{type=ThisT,ref=ThisRef},#wx_ref{type=CaretT,ref=CaretRef}) ->
%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxwindow.html#wxwindowsetclientsize">external documentation</a>.
%% <br /> Alternatives:
%% <p><c>
-%% setClientSize(This::wxWindow(), Size::{W::integer(),H::integer()}) -> ok </c>
+%% setClientSize(This::wxWindow(), Size::{W::integer(), H::integer()}) -> ok </c>
%% </p>
%% <p><c>
-%% setClientSize(This::wxWindow(), Rect::{X::integer(),Y::integer(),W::integer(),H::integer()}) -> ok </c>
+%% setClientSize(This::wxWindow(), Rect::{X::integer(), Y::integer(), W::integer(), H::integer()}) -> ok </c>
%% </p>
setClientSize(#wx_ref{type=ThisT,ref=ThisRef},{SizeW,SizeH})
when is_integer(SizeW),is_integer(SizeH) ->
diff --git a/lib/wx/src/gen/wxe_debug.hrl b/lib/wx/src/gen/wxe_debug.hrl
index 3edfa73599..960f67a1f6 100644
--- a/lib/wx/src/gen/wxe_debug.hrl
+++ b/lib/wx/src/gen/wxe_debug.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1603,1684 +1603,1696 @@ wxdebug_table() ->
{1754, {wxListItem, setText, 1}},
{1755, {wxListItem, setTextColour, 1}},
{1756, {wxListItem, setWidth, 1}},
- {1757, {wxImageList, new_0, 0}},
- {1758, {wxImageList, new_3, 3}},
- {1759, {wxImageList, add_1, 1}},
- {1760, {wxImageList, add_2_0, 2}},
- {1761, {wxImageList, add_2_1, 2}},
- {1762, {wxImageList, create, 3}},
- {1764, {wxImageList, draw, 5}},
- {1765, {wxImageList, getBitmap, 1}},
- {1766, {wxImageList, getIcon, 1}},
- {1767, {wxImageList, getImageCount, 0}},
- {1768, {wxImageList, getSize, 3}},
- {1769, {wxImageList, remove, 1}},
- {1770, {wxImageList, removeAll, 0}},
- {1771, {wxImageList, replace_2, 2}},
- {1772, {wxImageList, replace_3, 3}},
- {1773, {wxImageList, 'Destroy', undefined}},
- {1774, {wxTextAttr, new_0, 0}},
- {1775, {wxTextAttr, new_2, 2}},
- {1776, {wxTextAttr, getAlignment, 0}},
- {1777, {wxTextAttr, getBackgroundColour, 0}},
- {1778, {wxTextAttr, getFont, 0}},
- {1779, {wxTextAttr, getLeftIndent, 0}},
- {1780, {wxTextAttr, getLeftSubIndent, 0}},
- {1781, {wxTextAttr, getRightIndent, 0}},
- {1782, {wxTextAttr, getTabs, 0}},
- {1783, {wxTextAttr, getTextColour, 0}},
- {1784, {wxTextAttr, hasBackgroundColour, 0}},
- {1785, {wxTextAttr, hasFont, 0}},
- {1786, {wxTextAttr, hasTextColour, 0}},
- {1787, {wxTextAttr, getFlags, 0}},
- {1788, {wxTextAttr, isDefault, 0}},
- {1789, {wxTextAttr, setAlignment, 1}},
- {1790, {wxTextAttr, setBackgroundColour, 1}},
- {1791, {wxTextAttr, setFlags, 1}},
- {1792, {wxTextAttr, setFont, 2}},
- {1793, {wxTextAttr, setLeftIndent, 2}},
- {1794, {wxTextAttr, setRightIndent, 1}},
- {1795, {wxTextAttr, setTabs, 1}},
- {1796, {wxTextAttr, setTextColour, 1}},
- {1797, {wxTextAttr, 'Destroy', undefined}},
- {1799, {wxTextCtrl, new_3, 3}},
- {1800, {wxTextCtrl, new_0, 0}},
- {1802, {wxTextCtrl, destruct, 0}},
- {1803, {wxTextCtrl, appendText, 1}},
- {1804, {wxTextCtrl, canCopy, 0}},
- {1805, {wxTextCtrl, canCut, 0}},
- {1806, {wxTextCtrl, canPaste, 0}},
- {1807, {wxTextCtrl, canRedo, 0}},
- {1808, {wxTextCtrl, canUndo, 0}},
- {1809, {wxTextCtrl, clear, 0}},
- {1810, {wxTextCtrl, copy, 0}},
- {1811, {wxTextCtrl, create, 3}},
- {1812, {wxTextCtrl, cut, 0}},
- {1813, {wxTextCtrl, discardEdits, 0}},
- {1814, {wxTextCtrl, emulateKeyPress, 1}},
- {1815, {wxTextCtrl, getDefaultStyle, 0}},
- {1816, {wxTextCtrl, getInsertionPoint, 0}},
- {1817, {wxTextCtrl, getLastPosition, 0}},
- {1818, {wxTextCtrl, getLineLength, 1}},
- {1819, {wxTextCtrl, getLineText, 1}},
- {1820, {wxTextCtrl, getNumberOfLines, 0}},
- {1821, {wxTextCtrl, getRange, 2}},
- {1822, {wxTextCtrl, getSelection, 2}},
- {1823, {wxTextCtrl, getStringSelection, 0}},
- {1824, {wxTextCtrl, getStyle, 2}},
- {1825, {wxTextCtrl, getValue, 0}},
- {1826, {wxTextCtrl, isEditable, 0}},
- {1827, {wxTextCtrl, isModified, 0}},
- {1828, {wxTextCtrl, isMultiLine, 0}},
- {1829, {wxTextCtrl, isSingleLine, 0}},
- {1830, {wxTextCtrl, loadFile, 2}},
- {1831, {wxTextCtrl, markDirty, 0}},
- {1832, {wxTextCtrl, paste, 0}},
- {1833, {wxTextCtrl, positionToXY, 3}},
- {1834, {wxTextCtrl, redo, 0}},
- {1835, {wxTextCtrl, remove, 2}},
- {1836, {wxTextCtrl, replace, 3}},
- {1837, {wxTextCtrl, saveFile, 1}},
- {1838, {wxTextCtrl, setDefaultStyle, 1}},
- {1839, {wxTextCtrl, setEditable, 1}},
- {1840, {wxTextCtrl, setInsertionPoint, 1}},
- {1841, {wxTextCtrl, setInsertionPointEnd, 0}},
- {1843, {wxTextCtrl, setMaxLength, 1}},
- {1844, {wxTextCtrl, setSelection, 2}},
- {1845, {wxTextCtrl, setStyle, 3}},
- {1846, {wxTextCtrl, setValue, 1}},
- {1847, {wxTextCtrl, showPosition, 1}},
- {1848, {wxTextCtrl, undo, 0}},
- {1849, {wxTextCtrl, writeText, 1}},
- {1850, {wxTextCtrl, xYToPosition, 2}},
- {1853, {wxNotebook, new_0, 0}},
- {1854, {wxNotebook, new_3, 3}},
- {1855, {wxNotebook, destruct, 0}},
- {1856, {wxNotebook, addPage, 3}},
- {1857, {wxNotebook, advanceSelection, 1}},
- {1858, {wxNotebook, assignImageList, 1}},
- {1859, {wxNotebook, create, 3}},
- {1860, {wxNotebook, deleteAllPages, 0}},
- {1861, {wxNotebook, deletePage, 1}},
- {1862, {wxNotebook, removePage, 1}},
- {1863, {wxNotebook, getCurrentPage, 0}},
- {1864, {wxNotebook, getImageList, 0}},
- {1866, {wxNotebook, getPage, 1}},
- {1867, {wxNotebook, getPageCount, 0}},
- {1868, {wxNotebook, getPageImage, 1}},
- {1869, {wxNotebook, getPageText, 1}},
- {1870, {wxNotebook, getRowCount, 0}},
- {1871, {wxNotebook, getSelection, 0}},
- {1872, {wxNotebook, getThemeBackgroundColour, 0}},
- {1874, {wxNotebook, hitTest, 2}},
- {1876, {wxNotebook, insertPage, 4}},
- {1877, {wxNotebook, setImageList, 1}},
- {1878, {wxNotebook, setPadding, 1}},
- {1879, {wxNotebook, setPageSize, 1}},
- {1880, {wxNotebook, setPageImage, 2}},
- {1881, {wxNotebook, setPageText, 2}},
- {1882, {wxNotebook, setSelection, 1}},
- {1883, {wxNotebook, changeSelection, 1}},
- {1884, {wxChoicebook, new_0, 0}},
- {1885, {wxChoicebook, new_3, 3}},
- {1886, {wxChoicebook, addPage, 3}},
- {1887, {wxChoicebook, advanceSelection, 1}},
- {1888, {wxChoicebook, assignImageList, 1}},
- {1889, {wxChoicebook, create, 3}},
- {1890, {wxChoicebook, deleteAllPages, 0}},
- {1891, {wxChoicebook, deletePage, 1}},
- {1892, {wxChoicebook, removePage, 1}},
- {1893, {wxChoicebook, getCurrentPage, 0}},
- {1894, {wxChoicebook, getImageList, 0}},
- {1896, {wxChoicebook, getPage, 1}},
- {1897, {wxChoicebook, getPageCount, 0}},
- {1898, {wxChoicebook, getPageImage, 1}},
- {1899, {wxChoicebook, getPageText, 1}},
- {1900, {wxChoicebook, getSelection, 0}},
- {1901, {wxChoicebook, hitTest, 2}},
- {1902, {wxChoicebook, insertPage, 4}},
- {1903, {wxChoicebook, setImageList, 1}},
- {1904, {wxChoicebook, setPageSize, 1}},
- {1905, {wxChoicebook, setPageImage, 2}},
- {1906, {wxChoicebook, setPageText, 2}},
- {1907, {wxChoicebook, setSelection, 1}},
- {1908, {wxChoicebook, changeSelection, 1}},
- {1909, {wxChoicebook, 'Destroy', undefined}},
- {1910, {wxToolbook, new_0, 0}},
- {1911, {wxToolbook, new_3, 3}},
- {1912, {wxToolbook, addPage, 3}},
- {1913, {wxToolbook, advanceSelection, 1}},
- {1914, {wxToolbook, assignImageList, 1}},
- {1915, {wxToolbook, create, 3}},
- {1916, {wxToolbook, deleteAllPages, 0}},
- {1917, {wxToolbook, deletePage, 1}},
- {1918, {wxToolbook, removePage, 1}},
- {1919, {wxToolbook, getCurrentPage, 0}},
- {1920, {wxToolbook, getImageList, 0}},
- {1922, {wxToolbook, getPage, 1}},
- {1923, {wxToolbook, getPageCount, 0}},
- {1924, {wxToolbook, getPageImage, 1}},
- {1925, {wxToolbook, getPageText, 1}},
- {1926, {wxToolbook, getSelection, 0}},
- {1928, {wxToolbook, hitTest, 2}},
- {1929, {wxToolbook, insertPage, 4}},
- {1930, {wxToolbook, setImageList, 1}},
- {1931, {wxToolbook, setPageSize, 1}},
- {1932, {wxToolbook, setPageImage, 2}},
- {1933, {wxToolbook, setPageText, 2}},
- {1934, {wxToolbook, setSelection, 1}},
- {1935, {wxToolbook, changeSelection, 1}},
- {1936, {wxToolbook, 'Destroy', undefined}},
- {1937, {wxListbook, new_0, 0}},
- {1938, {wxListbook, new_3, 3}},
- {1939, {wxListbook, addPage, 3}},
- {1940, {wxListbook, advanceSelection, 1}},
- {1941, {wxListbook, assignImageList, 1}},
- {1942, {wxListbook, create, 3}},
- {1943, {wxListbook, deleteAllPages, 0}},
- {1944, {wxListbook, deletePage, 1}},
- {1945, {wxListbook, removePage, 1}},
- {1946, {wxListbook, getCurrentPage, 0}},
- {1947, {wxListbook, getImageList, 0}},
- {1949, {wxListbook, getPage, 1}},
- {1950, {wxListbook, getPageCount, 0}},
- {1951, {wxListbook, getPageImage, 1}},
- {1952, {wxListbook, getPageText, 1}},
- {1953, {wxListbook, getSelection, 0}},
- {1955, {wxListbook, hitTest, 2}},
- {1956, {wxListbook, insertPage, 4}},
- {1957, {wxListbook, setImageList, 1}},
- {1958, {wxListbook, setPageSize, 1}},
- {1959, {wxListbook, setPageImage, 2}},
- {1960, {wxListbook, setPageText, 2}},
- {1961, {wxListbook, setSelection, 1}},
- {1962, {wxListbook, changeSelection, 1}},
- {1963, {wxListbook, 'Destroy', undefined}},
- {1964, {wxTreebook, new_0, 0}},
- {1965, {wxTreebook, new_3, 3}},
- {1966, {wxTreebook, addPage, 3}},
- {1967, {wxTreebook, advanceSelection, 1}},
- {1968, {wxTreebook, assignImageList, 1}},
- {1969, {wxTreebook, create, 3}},
- {1970, {wxTreebook, deleteAllPages, 0}},
- {1971, {wxTreebook, deletePage, 1}},
- {1972, {wxTreebook, removePage, 1}},
- {1973, {wxTreebook, getCurrentPage, 0}},
- {1974, {wxTreebook, getImageList, 0}},
- {1976, {wxTreebook, getPage, 1}},
- {1977, {wxTreebook, getPageCount, 0}},
- {1978, {wxTreebook, getPageImage, 1}},
- {1979, {wxTreebook, getPageText, 1}},
- {1980, {wxTreebook, getSelection, 0}},
- {1981, {wxTreebook, expandNode, 2}},
- {1982, {wxTreebook, isNodeExpanded, 1}},
- {1984, {wxTreebook, hitTest, 2}},
- {1985, {wxTreebook, insertPage, 4}},
- {1986, {wxTreebook, insertSubPage, 4}},
- {1987, {wxTreebook, setImageList, 1}},
- {1988, {wxTreebook, setPageSize, 1}},
- {1989, {wxTreebook, setPageImage, 2}},
- {1990, {wxTreebook, setPageText, 2}},
- {1991, {wxTreebook, setSelection, 1}},
- {1992, {wxTreebook, changeSelection, 1}},
- {1993, {wxTreebook, 'Destroy', undefined}},
- {1996, {wxTreeCtrl, new_2, 2}},
- {1997, {wxTreeCtrl, new_0, 0}},
- {1999, {wxTreeCtrl, destruct, 0}},
- {2000, {wxTreeCtrl, addRoot, 2}},
- {2001, {wxTreeCtrl, appendItem, 3}},
- {2002, {wxTreeCtrl, assignImageList, 1}},
- {2003, {wxTreeCtrl, assignStateImageList, 1}},
- {2004, {wxTreeCtrl, collapse, 1}},
- {2005, {wxTreeCtrl, collapseAndReset, 1}},
- {2006, {wxTreeCtrl, create, 2}},
- {2007, {wxTreeCtrl, delete, 1}},
- {2008, {wxTreeCtrl, deleteAllItems, 0}},
- {2009, {wxTreeCtrl, deleteChildren, 1}},
- {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}},
+ {1757, {wxListItemAttr, new_0, 0}},
+ {1758, {wxListItemAttr, new_3, 3}},
+ {1759, {wxListItemAttr, getBackgroundColour, 0}},
+ {1760, {wxListItemAttr, getFont, 0}},
+ {1761, {wxListItemAttr, getTextColour, 0}},
+ {1762, {wxListItemAttr, hasBackgroundColour, 0}},
+ {1763, {wxListItemAttr, hasFont, 0}},
+ {1764, {wxListItemAttr, hasTextColour, 0}},
+ {1765, {wxListItemAttr, setBackgroundColour, 1}},
+ {1766, {wxListItemAttr, setFont, 1}},
+ {1767, {wxListItemAttr, setTextColour, 1}},
+ {1768, {wxListItemAttr, 'Destroy', undefined}},
+ {1769, {wxImageList, new_0, 0}},
+ {1770, {wxImageList, new_3, 3}},
+ {1771, {wxImageList, add_1, 1}},
+ {1772, {wxImageList, add_2_0, 2}},
+ {1773, {wxImageList, add_2_1, 2}},
+ {1774, {wxImageList, create, 3}},
+ {1776, {wxImageList, draw, 5}},
+ {1777, {wxImageList, getBitmap, 1}},
+ {1778, {wxImageList, getIcon, 1}},
+ {1779, {wxImageList, getImageCount, 0}},
+ {1780, {wxImageList, getSize, 3}},
+ {1781, {wxImageList, remove, 1}},
+ {1782, {wxImageList, removeAll, 0}},
+ {1783, {wxImageList, replace_2, 2}},
+ {1784, {wxImageList, replace_3, 3}},
+ {1785, {wxImageList, 'Destroy', undefined}},
+ {1786, {wxTextAttr, new_0, 0}},
+ {1787, {wxTextAttr, new_2, 2}},
+ {1788, {wxTextAttr, getAlignment, 0}},
+ {1789, {wxTextAttr, getBackgroundColour, 0}},
+ {1790, {wxTextAttr, getFont, 0}},
+ {1791, {wxTextAttr, getLeftIndent, 0}},
+ {1792, {wxTextAttr, getLeftSubIndent, 0}},
+ {1793, {wxTextAttr, getRightIndent, 0}},
+ {1794, {wxTextAttr, getTabs, 0}},
+ {1795, {wxTextAttr, getTextColour, 0}},
+ {1796, {wxTextAttr, hasBackgroundColour, 0}},
+ {1797, {wxTextAttr, hasFont, 0}},
+ {1798, {wxTextAttr, hasTextColour, 0}},
+ {1799, {wxTextAttr, getFlags, 0}},
+ {1800, {wxTextAttr, isDefault, 0}},
+ {1801, {wxTextAttr, setAlignment, 1}},
+ {1802, {wxTextAttr, setBackgroundColour, 1}},
+ {1803, {wxTextAttr, setFlags, 1}},
+ {1804, {wxTextAttr, setFont, 2}},
+ {1805, {wxTextAttr, setLeftIndent, 2}},
+ {1806, {wxTextAttr, setRightIndent, 1}},
+ {1807, {wxTextAttr, setTabs, 1}},
+ {1808, {wxTextAttr, setTextColour, 1}},
+ {1809, {wxTextAttr, 'Destroy', undefined}},
+ {1811, {wxTextCtrl, new_3, 3}},
+ {1812, {wxTextCtrl, new_0, 0}},
+ {1814, {wxTextCtrl, destruct, 0}},
+ {1815, {wxTextCtrl, appendText, 1}},
+ {1816, {wxTextCtrl, canCopy, 0}},
+ {1817, {wxTextCtrl, canCut, 0}},
+ {1818, {wxTextCtrl, canPaste, 0}},
+ {1819, {wxTextCtrl, canRedo, 0}},
+ {1820, {wxTextCtrl, canUndo, 0}},
+ {1821, {wxTextCtrl, clear, 0}},
+ {1822, {wxTextCtrl, copy, 0}},
+ {1823, {wxTextCtrl, create, 3}},
+ {1824, {wxTextCtrl, cut, 0}},
+ {1825, {wxTextCtrl, discardEdits, 0}},
+ {1826, {wxTextCtrl, emulateKeyPress, 1}},
+ {1827, {wxTextCtrl, getDefaultStyle, 0}},
+ {1828, {wxTextCtrl, getInsertionPoint, 0}},
+ {1829, {wxTextCtrl, getLastPosition, 0}},
+ {1830, {wxTextCtrl, getLineLength, 1}},
+ {1831, {wxTextCtrl, getLineText, 1}},
+ {1832, {wxTextCtrl, getNumberOfLines, 0}},
+ {1833, {wxTextCtrl, getRange, 2}},
+ {1834, {wxTextCtrl, getSelection, 2}},
+ {1835, {wxTextCtrl, getStringSelection, 0}},
+ {1836, {wxTextCtrl, getStyle, 2}},
+ {1837, {wxTextCtrl, getValue, 0}},
+ {1838, {wxTextCtrl, isEditable, 0}},
+ {1839, {wxTextCtrl, isModified, 0}},
+ {1840, {wxTextCtrl, isMultiLine, 0}},
+ {1841, {wxTextCtrl, isSingleLine, 0}},
+ {1842, {wxTextCtrl, loadFile, 2}},
+ {1843, {wxTextCtrl, markDirty, 0}},
+ {1844, {wxTextCtrl, paste, 0}},
+ {1845, {wxTextCtrl, positionToXY, 3}},
+ {1846, {wxTextCtrl, redo, 0}},
+ {1847, {wxTextCtrl, remove, 2}},
+ {1848, {wxTextCtrl, replace, 3}},
+ {1849, {wxTextCtrl, saveFile, 1}},
+ {1850, {wxTextCtrl, setDefaultStyle, 1}},
+ {1851, {wxTextCtrl, setEditable, 1}},
+ {1852, {wxTextCtrl, setInsertionPoint, 1}},
+ {1853, {wxTextCtrl, setInsertionPointEnd, 0}},
+ {1855, {wxTextCtrl, setMaxLength, 1}},
+ {1856, {wxTextCtrl, setSelection, 2}},
+ {1857, {wxTextCtrl, setStyle, 3}},
+ {1858, {wxTextCtrl, setValue, 1}},
+ {1859, {wxTextCtrl, showPosition, 1}},
+ {1860, {wxTextCtrl, undo, 0}},
+ {1861, {wxTextCtrl, writeText, 1}},
+ {1862, {wxTextCtrl, xYToPosition, 2}},
+ {1865, {wxNotebook, new_0, 0}},
+ {1866, {wxNotebook, new_3, 3}},
+ {1867, {wxNotebook, destruct, 0}},
+ {1868, {wxNotebook, addPage, 3}},
+ {1869, {wxNotebook, advanceSelection, 1}},
+ {1870, {wxNotebook, assignImageList, 1}},
+ {1871, {wxNotebook, create, 3}},
+ {1872, {wxNotebook, deleteAllPages, 0}},
+ {1873, {wxNotebook, deletePage, 1}},
+ {1874, {wxNotebook, removePage, 1}},
+ {1875, {wxNotebook, getCurrentPage, 0}},
+ {1876, {wxNotebook, getImageList, 0}},
+ {1878, {wxNotebook, getPage, 1}},
+ {1879, {wxNotebook, getPageCount, 0}},
+ {1880, {wxNotebook, getPageImage, 1}},
+ {1881, {wxNotebook, getPageText, 1}},
+ {1882, {wxNotebook, getRowCount, 0}},
+ {1883, {wxNotebook, getSelection, 0}},
+ {1884, {wxNotebook, getThemeBackgroundColour, 0}},
+ {1886, {wxNotebook, hitTest, 2}},
+ {1888, {wxNotebook, insertPage, 4}},
+ {1889, {wxNotebook, setImageList, 1}},
+ {1890, {wxNotebook, setPadding, 1}},
+ {1891, {wxNotebook, setPageSize, 1}},
+ {1892, {wxNotebook, setPageImage, 2}},
+ {1893, {wxNotebook, setPageText, 2}},
+ {1894, {wxNotebook, setSelection, 1}},
+ {1895, {wxNotebook, changeSelection, 1}},
+ {1896, {wxChoicebook, new_0, 0}},
+ {1897, {wxChoicebook, new_3, 3}},
+ {1898, {wxChoicebook, addPage, 3}},
+ {1899, {wxChoicebook, advanceSelection, 1}},
+ {1900, {wxChoicebook, assignImageList, 1}},
+ {1901, {wxChoicebook, create, 3}},
+ {1902, {wxChoicebook, deleteAllPages, 0}},
+ {1903, {wxChoicebook, deletePage, 1}},
+ {1904, {wxChoicebook, removePage, 1}},
+ {1905, {wxChoicebook, getCurrentPage, 0}},
+ {1906, {wxChoicebook, getImageList, 0}},
+ {1908, {wxChoicebook, getPage, 1}},
+ {1909, {wxChoicebook, getPageCount, 0}},
+ {1910, {wxChoicebook, getPageImage, 1}},
+ {1911, {wxChoicebook, getPageText, 1}},
+ {1912, {wxChoicebook, getSelection, 0}},
+ {1913, {wxChoicebook, hitTest, 2}},
+ {1914, {wxChoicebook, insertPage, 4}},
+ {1915, {wxChoicebook, setImageList, 1}},
+ {1916, {wxChoicebook, setPageSize, 1}},
+ {1917, {wxChoicebook, setPageImage, 2}},
+ {1918, {wxChoicebook, setPageText, 2}},
+ {1919, {wxChoicebook, setSelection, 1}},
+ {1920, {wxChoicebook, changeSelection, 1}},
+ {1921, {wxChoicebook, 'Destroy', undefined}},
+ {1922, {wxToolbook, new_0, 0}},
+ {1923, {wxToolbook, new_3, 3}},
+ {1924, {wxToolbook, addPage, 3}},
+ {1925, {wxToolbook, advanceSelection, 1}},
+ {1926, {wxToolbook, assignImageList, 1}},
+ {1927, {wxToolbook, create, 3}},
+ {1928, {wxToolbook, deleteAllPages, 0}},
+ {1929, {wxToolbook, deletePage, 1}},
+ {1930, {wxToolbook, removePage, 1}},
+ {1931, {wxToolbook, getCurrentPage, 0}},
+ {1932, {wxToolbook, getImageList, 0}},
+ {1934, {wxToolbook, getPage, 1}},
+ {1935, {wxToolbook, getPageCount, 0}},
+ {1936, {wxToolbook, getPageImage, 1}},
+ {1937, {wxToolbook, getPageText, 1}},
+ {1938, {wxToolbook, getSelection, 0}},
+ {1940, {wxToolbook, hitTest, 2}},
+ {1941, {wxToolbook, insertPage, 4}},
+ {1942, {wxToolbook, setImageList, 1}},
+ {1943, {wxToolbook, setPageSize, 1}},
+ {1944, {wxToolbook, setPageImage, 2}},
+ {1945, {wxToolbook, setPageText, 2}},
+ {1946, {wxToolbook, setSelection, 1}},
+ {1947, {wxToolbook, changeSelection, 1}},
+ {1948, {wxToolbook, 'Destroy', undefined}},
+ {1949, {wxListbook, new_0, 0}},
+ {1950, {wxListbook, new_3, 3}},
+ {1951, {wxListbook, addPage, 3}},
+ {1952, {wxListbook, advanceSelection, 1}},
+ {1953, {wxListbook, assignImageList, 1}},
+ {1954, {wxListbook, create, 3}},
+ {1955, {wxListbook, deleteAllPages, 0}},
+ {1956, {wxListbook, deletePage, 1}},
+ {1957, {wxListbook, removePage, 1}},
+ {1958, {wxListbook, getCurrentPage, 0}},
+ {1959, {wxListbook, getImageList, 0}},
+ {1961, {wxListbook, getPage, 1}},
+ {1962, {wxListbook, getPageCount, 0}},
+ {1963, {wxListbook, getPageImage, 1}},
+ {1964, {wxListbook, getPageText, 1}},
+ {1965, {wxListbook, getSelection, 0}},
+ {1967, {wxListbook, hitTest, 2}},
+ {1968, {wxListbook, insertPage, 4}},
+ {1969, {wxListbook, setImageList, 1}},
+ {1970, {wxListbook, setPageSize, 1}},
+ {1971, {wxListbook, setPageImage, 2}},
+ {1972, {wxListbook, setPageText, 2}},
+ {1973, {wxListbook, setSelection, 1}},
+ {1974, {wxListbook, changeSelection, 1}},
+ {1975, {wxListbook, 'Destroy', undefined}},
+ {1976, {wxTreebook, new_0, 0}},
+ {1977, {wxTreebook, new_3, 3}},
+ {1978, {wxTreebook, addPage, 3}},
+ {1979, {wxTreebook, advanceSelection, 1}},
+ {1980, {wxTreebook, assignImageList, 1}},
+ {1981, {wxTreebook, create, 3}},
+ {1982, {wxTreebook, deleteAllPages, 0}},
+ {1983, {wxTreebook, deletePage, 1}},
+ {1984, {wxTreebook, removePage, 1}},
+ {1985, {wxTreebook, getCurrentPage, 0}},
+ {1986, {wxTreebook, getImageList, 0}},
+ {1988, {wxTreebook, getPage, 1}},
+ {1989, {wxTreebook, getPageCount, 0}},
+ {1990, {wxTreebook, getPageImage, 1}},
+ {1991, {wxTreebook, getPageText, 1}},
+ {1992, {wxTreebook, getSelection, 0}},
+ {1993, {wxTreebook, expandNode, 2}},
+ {1994, {wxTreebook, isNodeExpanded, 1}},
+ {1996, {wxTreebook, hitTest, 2}},
+ {1997, {wxTreebook, insertPage, 4}},
+ {1998, {wxTreebook, insertSubPage, 4}},
+ {1999, {wxTreebook, setImageList, 1}},
+ {2000, {wxTreebook, setPageSize, 1}},
+ {2001, {wxTreebook, setPageImage, 2}},
+ {2002, {wxTreebook, setPageText, 2}},
+ {2003, {wxTreebook, setSelection, 1}},
+ {2004, {wxTreebook, changeSelection, 1}},
+ {2005, {wxTreebook, 'Destroy', undefined}},
+ {2008, {wxTreeCtrl, new_2, 2}},
+ {2009, {wxTreeCtrl, new_0, 0}},
+ {2011, {wxTreeCtrl, destruct, 0}},
+ {2012, {wxTreeCtrl, addRoot, 2}},
+ {2013, {wxTreeCtrl, appendItem, 3}},
+ {2014, {wxTreeCtrl, assignImageList, 1}},
+ {2015, {wxTreeCtrl, assignStateImageList, 1}},
+ {2016, {wxTreeCtrl, collapse, 1}},
+ {2017, {wxTreeCtrl, collapseAndReset, 1}},
+ {2018, {wxTreeCtrl, create, 2}},
+ {2019, {wxTreeCtrl, delete, 1}},
+ {2020, {wxTreeCtrl, deleteAllItems, 0}},
+ {2021, {wxTreeCtrl, deleteChildren, 1}},
+ {2022, {wxTreeCtrl, editLabel, 1}},
+ {2023, {wxTreeCtrl, ensureVisible, 1}},
+ {2024, {wxTreeCtrl, expand, 1}},
+ {2025, {wxTreeCtrl, getBoundingRect, 3}},
+ {2027, {wxTreeCtrl, getChildrenCount, 2}},
+ {2028, {wxTreeCtrl, getCount, 0}},
+ {2029, {wxTreeCtrl, getEditControl, 0}},
+ {2030, {wxTreeCtrl, getFirstChild, 2}},
+ {2031, {wxTreeCtrl, getNextChild, 2}},
+ {2032, {wxTreeCtrl, getFirstVisibleItem, 0}},
+ {2033, {wxTreeCtrl, getImageList, 0}},
+ {2034, {wxTreeCtrl, getIndent, 0}},
+ {2035, {wxTreeCtrl, getItemBackgroundColour, 1}},
+ {2036, {wxTreeCtrl, getItemData, 1}},
+ {2037, {wxTreeCtrl, getItemFont, 1}},
+ {2038, {wxTreeCtrl, getItemImage_1, 1}},
+ {2039, {wxTreeCtrl, getItemImage_2, 2}},
+ {2040, {wxTreeCtrl, getItemText, 1}},
+ {2041, {wxTreeCtrl, getItemTextColour, 1}},
+ {2042, {wxTreeCtrl, getLastChild, 1}},
+ {2043, {wxTreeCtrl, getNextSibling, 1}},
+ {2044, {wxTreeCtrl, getNextVisible, 1}},
+ {2045, {wxTreeCtrl, getItemParent, 1}},
+ {2046, {wxTreeCtrl, getPrevSibling, 1}},
+ {2047, {wxTreeCtrl, getPrevVisible, 1}},
+ {2048, {wxTreeCtrl, getRootItem, 0}},
+ {2049, {wxTreeCtrl, getSelection, 0}},
+ {2050, {wxTreeCtrl, getSelections, 1}},
+ {2051, {wxTreeCtrl, getStateImageList, 0}},
+ {2052, {wxTreeCtrl, hitTest, 1}},
+ {2054, {wxTreeCtrl, insertItem, 4}},
+ {2055, {wxTreeCtrl, isBold, 1}},
+ {2056, {wxTreeCtrl, isExpanded, 1}},
+ {2057, {wxTreeCtrl, isSelected, 1}},
+ {2058, {wxTreeCtrl, isVisible, 1}},
+ {2059, {wxTreeCtrl, itemHasChildren, 1}},
+ {2060, {wxTreeCtrl, prependItem, 3}},
+ {2061, {wxTreeCtrl, scrollTo, 1}},
+ {2062, {wxTreeCtrl, selectItem_1, 1}},
+ {2063, {wxTreeCtrl, selectItem_2, 2}},
+ {2064, {wxTreeCtrl, setIndent, 1}},
+ {2065, {wxTreeCtrl, setImageList, 1}},
+ {2066, {wxTreeCtrl, setItemBackgroundColour, 2}},
+ {2067, {wxTreeCtrl, setItemBold, 2}},
+ {2068, {wxTreeCtrl, setItemData, 2}},
+ {2069, {wxTreeCtrl, setItemDropHighlight, 2}},
+ {2070, {wxTreeCtrl, setItemFont, 2}},
+ {2071, {wxTreeCtrl, setItemHasChildren, 2}},
+ {2072, {wxTreeCtrl, setItemImage_2, 2}},
+ {2073, {wxTreeCtrl, setItemImage_3, 3}},
+ {2074, {wxTreeCtrl, setItemText, 2}},
+ {2075, {wxTreeCtrl, setItemTextColour, 2}},
+ {2076, {wxTreeCtrl, setStateImageList, 1}},
+ {2077, {wxTreeCtrl, setWindowStyle, 1}},
+ {2078, {wxTreeCtrl, sortChildren, 1}},
+ {2079, {wxTreeCtrl, toggle, 1}},
+ {2080, {wxTreeCtrl, toggleItemSelection, 1}},
+ {2081, {wxTreeCtrl, unselect, 0}},
+ {2082, {wxTreeCtrl, unselectAll, 0}},
+ {2083, {wxTreeCtrl, unselectItem, 1}},
+ {2084, {wxScrollBar, new_0, 0}},
+ {2085, {wxScrollBar, new_3, 3}},
+ {2086, {wxScrollBar, destruct, 0}},
+ {2087, {wxScrollBar, create, 3}},
+ {2088, {wxScrollBar, getRange, 0}},
+ {2089, {wxScrollBar, getPageSize, 0}},
+ {2090, {wxScrollBar, getThumbPosition, 0}},
+ {2091, {wxScrollBar, getThumbSize, 0}},
+ {2092, {wxScrollBar, setThumbPosition, 1}},
+ {2093, {wxScrollBar, setScrollbar, 5}},
+ {2095, {wxSpinButton, new_2, 2}},
+ {2096, {wxSpinButton, new_0, 0}},
+ {2097, {wxSpinButton, create, 2}},
+ {2098, {wxSpinButton, getMax, 0}},
+ {2099, {wxSpinButton, getMin, 0}},
+ {2100, {wxSpinButton, getValue, 0}},
+ {2101, {wxSpinButton, setRange, 2}},
+ {2102, {wxSpinButton, setValue, 1}},
+ {2103, {wxSpinButton, 'Destroy', undefined}},
+ {2104, {wxSpinCtrl, new_0, 0}},
+ {2105, {wxSpinCtrl, new_2, 2}},
+ {2107, {wxSpinCtrl, create, 2}},
+ {2110, {wxSpinCtrl, setValue_1_1, 1}},
+ {2111, {wxSpinCtrl, setValue_1_0, 1}},
+ {2113, {wxSpinCtrl, getValue, 0}},
+ {2115, {wxSpinCtrl, setRange, 2}},
+ {2116, {wxSpinCtrl, setSelection, 2}},
+ {2118, {wxSpinCtrl, getMin, 0}},
+ {2120, {wxSpinCtrl, getMax, 0}},
+ {2121, {wxSpinCtrl, 'Destroy', undefined}},
+ {2122, {wxStaticText, new_0, 0}},
+ {2123, {wxStaticText, new_4, 4}},
+ {2124, {wxStaticText, create, 4}},
+ {2125, {wxStaticText, getLabel, 0}},
+ {2126, {wxStaticText, setLabel, 1}},
+ {2127, {wxStaticText, wrap, 1}},
+ {2128, {wxStaticText, 'Destroy', undefined}},
+ {2129, {wxStaticBitmap, new_0, 0}},
+ {2130, {wxStaticBitmap, new_4, 4}},
+ {2131, {wxStaticBitmap, create, 4}},
+ {2132, {wxStaticBitmap, getBitmap, 0}},
+ {2133, {wxStaticBitmap, setBitmap, 1}},
+ {2134, {wxStaticBitmap, 'Destroy', undefined}},
+ {2135, {wxRadioBox, new, 7}},
+ {2137, {wxRadioBox, destruct, 0}},
+ {2138, {wxRadioBox, create, 7}},
+ {2139, {wxRadioBox, enable_2, 2}},
+ {2140, {wxRadioBox, enable_1, 1}},
+ {2141, {wxRadioBox, getSelection, 0}},
+ {2142, {wxRadioBox, getString, 1}},
+ {2143, {wxRadioBox, setSelection, 1}},
+ {2144, {wxRadioBox, show_2, 2}},
+ {2145, {wxRadioBox, show_1, 1}},
+ {2146, {wxRadioBox, getColumnCount, 0}},
+ {2147, {wxRadioBox, getItemHelpText, 1}},
+ {2148, {wxRadioBox, getItemToolTip, 1}},
+ {2150, {wxRadioBox, getItemFromPoint, 1}},
+ {2151, {wxRadioBox, getRowCount, 0}},
+ {2152, {wxRadioBox, isItemEnabled, 1}},
+ {2153, {wxRadioBox, isItemShown, 1}},
+ {2154, {wxRadioBox, setItemHelpText, 2}},
+ {2155, {wxRadioBox, setItemToolTip, 2}},
+ {2156, {wxRadioButton, new_0, 0}},
+ {2157, {wxRadioButton, new_4, 4}},
+ {2158, {wxRadioButton, create, 4}},
+ {2159, {wxRadioButton, getValue, 0}},
+ {2160, {wxRadioButton, setValue, 1}},
+ {2161, {wxRadioButton, 'Destroy', undefined}},
+ {2163, {wxSlider, new_6, 6}},
+ {2164, {wxSlider, new_0, 0}},
+ {2165, {wxSlider, create, 6}},
+ {2166, {wxSlider, getLineSize, 0}},
+ {2167, {wxSlider, getMax, 0}},
+ {2168, {wxSlider, getMin, 0}},
+ {2169, {wxSlider, getPageSize, 0}},
+ {2170, {wxSlider, getThumbLength, 0}},
+ {2171, {wxSlider, getValue, 0}},
+ {2172, {wxSlider, setLineSize, 1}},
+ {2173, {wxSlider, setPageSize, 1}},
+ {2174, {wxSlider, setRange, 2}},
+ {2175, {wxSlider, setThumbLength, 1}},
+ {2176, {wxSlider, setValue, 1}},
+ {2177, {wxSlider, 'Destroy', undefined}},
+ {2179, {wxDialog, new_4, 4}},
+ {2180, {wxDialog, new_0, 0}},
+ {2182, {wxDialog, destruct, 0}},
+ {2183, {wxDialog, create, 4}},
+ {2184, {wxDialog, createButtonSizer, 1}},
+ {2185, {wxDialog, createStdDialogButtonSizer, 1}},
+ {2186, {wxDialog, endModal, 1}},
+ {2187, {wxDialog, getAffirmativeId, 0}},
+ {2188, {wxDialog, getReturnCode, 0}},
+ {2189, {wxDialog, isModal, 0}},
+ {2190, {wxDialog, setAffirmativeId, 1}},
+ {2191, {wxDialog, setReturnCode, 1}},
+ {2192, {wxDialog, show, 1}},
+ {2193, {wxDialog, showModal, 0}},
+ {2194, {wxColourDialog, new_0, 0}},
+ {2195, {wxColourDialog, new_2, 2}},
+ {2196, {wxColourDialog, destruct, 0}},
+ {2197, {wxColourDialog, create, 2}},
+ {2198, {wxColourDialog, getColourData, 0}},
+ {2199, {wxColourData, new_0, 0}},
+ {2200, {wxColourData, new_1, 1}},
+ {2201, {wxColourData, destruct, 0}},
+ {2202, {wxColourData, getChooseFull, 0}},
+ {2203, {wxColourData, getColour, 0}},
+ {2205, {wxColourData, getCustomColour, 1}},
+ {2206, {wxColourData, setChooseFull, 1}},
+ {2207, {wxColourData, setColour, 1}},
+ {2208, {wxColourData, setCustomColour, 2}},
+ {2209, {wxPalette, new_0, 0}},
+ {2210, {wxPalette, new_4, 4}},
+ {2212, {wxPalette, destruct, 0}},
+ {2213, {wxPalette, create, 4}},
+ {2214, {wxPalette, getColoursCount, 0}},
+ {2215, {wxPalette, getPixel, 3}},
+ {2216, {wxPalette, getRGB, 4}},
+ {2217, {wxPalette, isOk, 0}},
+ {2221, {wxDirDialog, new, 2}},
+ {2222, {wxDirDialog, destruct, 0}},
+ {2223, {wxDirDialog, getPath, 0}},
+ {2224, {wxDirDialog, getMessage, 0}},
+ {2225, {wxDirDialog, setMessage, 1}},
+ {2226, {wxDirDialog, setPath, 1}},
+ {2230, {wxFileDialog, new, 2}},
+ {2231, {wxFileDialog, destruct, 0}},
+ {2232, {wxFileDialog, getDirectory, 0}},
+ {2233, {wxFileDialog, getFilename, 0}},
+ {2234, {wxFileDialog, getFilenames, 1}},
+ {2235, {wxFileDialog, getFilterIndex, 0}},
+ {2236, {wxFileDialog, getMessage, 0}},
+ {2237, {wxFileDialog, getPath, 0}},
+ {2238, {wxFileDialog, getPaths, 1}},
+ {2239, {wxFileDialog, getWildcard, 0}},
+ {2240, {wxFileDialog, setDirectory, 1}},
+ {2241, {wxFileDialog, setFilename, 1}},
+ {2242, {wxFileDialog, setFilterIndex, 1}},
+ {2243, {wxFileDialog, setMessage, 1}},
+ {2244, {wxFileDialog, setPath, 1}},
+ {2245, {wxFileDialog, setWildcard, 1}},
+ {2246, {wxPickerBase, setInternalMargin, 1}},
+ {2247, {wxPickerBase, getInternalMargin, 0}},
+ {2248, {wxPickerBase, setTextCtrlProportion, 1}},
+ {2249, {wxPickerBase, setPickerCtrlProportion, 1}},
+ {2250, {wxPickerBase, getTextCtrlProportion, 0}},
+ {2251, {wxPickerBase, getPickerCtrlProportion, 0}},
+ {2252, {wxPickerBase, hasTextCtrl, 0}},
+ {2253, {wxPickerBase, getTextCtrl, 0}},
+ {2254, {wxPickerBase, isTextCtrlGrowable, 0}},
+ {2255, {wxPickerBase, setPickerCtrlGrowable, 1}},
+ {2256, {wxPickerBase, setTextCtrlGrowable, 1}},
+ {2257, {wxPickerBase, isPickerCtrlGrowable, 0}},
+ {2258, {wxFilePickerCtrl, new_0, 0}},
+ {2259, {wxFilePickerCtrl, new_3, 3}},
+ {2260, {wxFilePickerCtrl, create, 3}},
+ {2261, {wxFilePickerCtrl, getPath, 0}},
+ {2262, {wxFilePickerCtrl, setPath, 1}},
+ {2263, {wxFilePickerCtrl, 'Destroy', undefined}},
+ {2264, {wxDirPickerCtrl, new_0, 0}},
+ {2265, {wxDirPickerCtrl, new_3, 3}},
+ {2266, {wxDirPickerCtrl, create, 3}},
+ {2267, {wxDirPickerCtrl, getPath, 0}},
+ {2268, {wxDirPickerCtrl, setPath, 1}},
+ {2269, {wxDirPickerCtrl, 'Destroy', undefined}},
+ {2270, {wxColourPickerCtrl, new_0, 0}},
+ {2271, {wxColourPickerCtrl, new_3, 3}},
+ {2272, {wxColourPickerCtrl, create, 3}},
+ {2273, {wxColourPickerCtrl, getColour, 0}},
+ {2274, {wxColourPickerCtrl, setColour_1_1, 1}},
+ {2275, {wxColourPickerCtrl, setColour_1_0, 1}},
+ {2276, {wxColourPickerCtrl, 'Destroy', undefined}},
+ {2277, {wxDatePickerCtrl, new_0, 0}},
+ {2278, {wxDatePickerCtrl, new_3, 3}},
+ {2279, {wxDatePickerCtrl, getRange, 2}},
+ {2280, {wxDatePickerCtrl, getValue, 0}},
+ {2281, {wxDatePickerCtrl, setRange, 2}},
+ {2282, {wxDatePickerCtrl, setValue, 1}},
+ {2283, {wxDatePickerCtrl, 'Destroy', undefined}},
+ {2284, {wxFontPickerCtrl, new_0, 0}},
+ {2285, {wxFontPickerCtrl, new_3, 3}},
+ {2286, {wxFontPickerCtrl, create, 3}},
+ {2287, {wxFontPickerCtrl, getSelectedFont, 0}},
+ {2288, {wxFontPickerCtrl, setSelectedFont, 1}},
+ {2289, {wxFontPickerCtrl, getMaxPointSize, 0}},
+ {2290, {wxFontPickerCtrl, setMaxPointSize, 1}},
+ {2291, {wxFontPickerCtrl, 'Destroy', undefined}},
+ {2294, {wxFindReplaceDialog, new_0, 0}},
+ {2295, {wxFindReplaceDialog, new_4, 4}},
+ {2296, {wxFindReplaceDialog, destruct, 0}},
+ {2297, {wxFindReplaceDialog, create, 4}},
+ {2298, {wxFindReplaceDialog, getData, 0}},
+ {2299, {wxFindReplaceData, new_0, 0}},
+ {2300, {wxFindReplaceData, new_1, 1}},
+ {2301, {wxFindReplaceData, getFindString, 0}},
+ {2302, {wxFindReplaceData, getReplaceString, 0}},
+ {2303, {wxFindReplaceData, getFlags, 0}},
+ {2304, {wxFindReplaceData, setFlags, 1}},
+ {2305, {wxFindReplaceData, setFindString, 1}},
+ {2306, {wxFindReplaceData, setReplaceString, 1}},
+ {2307, {wxFindReplaceData, 'Destroy', undefined}},
+ {2308, {wxMultiChoiceDialog, new_0, 0}},
+ {2310, {wxMultiChoiceDialog, new_5, 5}},
+ {2311, {wxMultiChoiceDialog, getSelections, 0}},
+ {2312, {wxMultiChoiceDialog, setSelections, 1}},
+ {2313, {wxMultiChoiceDialog, 'Destroy', undefined}},
+ {2314, {wxSingleChoiceDialog, new_0, 0}},
+ {2316, {wxSingleChoiceDialog, new_5, 5}},
+ {2317, {wxSingleChoiceDialog, getSelection, 0}},
+ {2318, {wxSingleChoiceDialog, getStringSelection, 0}},
+ {2319, {wxSingleChoiceDialog, setSelection, 1}},
+ {2320, {wxSingleChoiceDialog, 'Destroy', undefined}},
+ {2321, {wxTextEntryDialog, new, 3}},
+ {2322, {wxTextEntryDialog, getValue, 0}},
+ {2323, {wxTextEntryDialog, setValue, 1}},
+ {2324, {wxTextEntryDialog, 'Destroy', undefined}},
+ {2325, {wxPasswordEntryDialog, new, 3}},
+ {2326, {wxPasswordEntryDialog, 'Destroy', undefined}},
+ {2327, {wxFontData, new_0, 0}},
+ {2328, {wxFontData, new_1, 1}},
+ {2329, {wxFontData, destruct, 0}},
+ {2330, {wxFontData, enableEffects, 1}},
+ {2331, {wxFontData, getAllowSymbols, 0}},
+ {2332, {wxFontData, getColour, 0}},
+ {2333, {wxFontData, getChosenFont, 0}},
+ {2334, {wxFontData, getEnableEffects, 0}},
+ {2335, {wxFontData, getInitialFont, 0}},
+ {2336, {wxFontData, getShowHelp, 0}},
+ {2337, {wxFontData, setAllowSymbols, 1}},
+ {2338, {wxFontData, setChosenFont, 1}},
+ {2339, {wxFontData, setColour, 1}},
+ {2340, {wxFontData, setInitialFont, 1}},
+ {2341, {wxFontData, setRange, 2}},
+ {2342, {wxFontData, setShowHelp, 1}},
+ {2346, {wxFontDialog, new_0, 0}},
+ {2348, {wxFontDialog, new_2, 2}},
+ {2350, {wxFontDialog, create, 2}},
+ {2351, {wxFontDialog, getFontData, 0}},
+ {2353, {wxFontDialog, 'Destroy', undefined}},
+ {2354, {wxProgressDialog, new, 3}},
+ {2355, {wxProgressDialog, destruct, 0}},
+ {2356, {wxProgressDialog, resume, 0}},
+ {2357, {wxProgressDialog, update_2, 2}},
+ {2358, {wxProgressDialog, update_0, 0}},
+ {2359, {wxMessageDialog, new, 3}},
+ {2360, {wxMessageDialog, destruct, 0}},
+ {2361, {wxPageSetupDialog, new, 2}},
+ {2362, {wxPageSetupDialog, destruct, 0}},
+ {2363, {wxPageSetupDialog, getPageSetupData, 0}},
+ {2364, {wxPageSetupDialog, showModal, 0}},
+ {2365, {wxPageSetupDialogData, new_0, 0}},
+ {2366, {wxPageSetupDialogData, new_1_0, 1}},
+ {2367, {wxPageSetupDialogData, new_1_1, 1}},
+ {2368, {wxPageSetupDialogData, destruct, 0}},
+ {2369, {wxPageSetupDialogData, enableHelp, 1}},
+ {2370, {wxPageSetupDialogData, enableMargins, 1}},
+ {2371, {wxPageSetupDialogData, enableOrientation, 1}},
+ {2372, {wxPageSetupDialogData, enablePaper, 1}},
+ {2373, {wxPageSetupDialogData, enablePrinter, 1}},
+ {2374, {wxPageSetupDialogData, getDefaultMinMargins, 0}},
+ {2375, {wxPageSetupDialogData, getEnableMargins, 0}},
+ {2376, {wxPageSetupDialogData, getEnableOrientation, 0}},
+ {2377, {wxPageSetupDialogData, getEnablePaper, 0}},
+ {2378, {wxPageSetupDialogData, getEnablePrinter, 0}},
+ {2379, {wxPageSetupDialogData, getEnableHelp, 0}},
+ {2380, {wxPageSetupDialogData, getDefaultInfo, 0}},
+ {2381, {wxPageSetupDialogData, getMarginTopLeft, 0}},
+ {2382, {wxPageSetupDialogData, getMarginBottomRight, 0}},
+ {2383, {wxPageSetupDialogData, getMinMarginTopLeft, 0}},
+ {2384, {wxPageSetupDialogData, getMinMarginBottomRight, 0}},
+ {2385, {wxPageSetupDialogData, getPaperId, 0}},
+ {2386, {wxPageSetupDialogData, getPaperSize, 0}},
+ {2388, {wxPageSetupDialogData, getPrintData, 0}},
+ {2389, {wxPageSetupDialogData, isOk, 0}},
+ {2390, {wxPageSetupDialogData, setDefaultInfo, 1}},
+ {2391, {wxPageSetupDialogData, setDefaultMinMargins, 1}},
+ {2392, {wxPageSetupDialogData, setMarginTopLeft, 1}},
+ {2393, {wxPageSetupDialogData, setMarginBottomRight, 1}},
+ {2394, {wxPageSetupDialogData, setMinMarginTopLeft, 1}},
+ {2395, {wxPageSetupDialogData, setMinMarginBottomRight, 1}},
+ {2396, {wxPageSetupDialogData, setPaperId, 1}},
+ {2397, {wxPageSetupDialogData, setPaperSize_1_1, 1}},
+ {2398, {wxPageSetupDialogData, setPaperSize_1_0, 1}},
+ {2399, {wxPageSetupDialogData, setPrintData, 1}},
+ {2400, {wxPrintDialog, new_2_0, 2}},
+ {2401, {wxPrintDialog, new_2_1, 2}},
+ {2402, {wxPrintDialog, destruct, 0}},
+ {2403, {wxPrintDialog, getPrintDialogData, 0}},
+ {2404, {wxPrintDialog, getPrintDC, 0}},
+ {2405, {wxPrintDialogData, new_0, 0}},
+ {2406, {wxPrintDialogData, new_1_1, 1}},
+ {2407, {wxPrintDialogData, new_1_0, 1}},
+ {2408, {wxPrintDialogData, destruct, 0}},
+ {2409, {wxPrintDialogData, enableHelp, 1}},
+ {2410, {wxPrintDialogData, enablePageNumbers, 1}},
+ {2411, {wxPrintDialogData, enablePrintToFile, 1}},
+ {2412, {wxPrintDialogData, enableSelection, 1}},
+ {2413, {wxPrintDialogData, getAllPages, 0}},
+ {2414, {wxPrintDialogData, getCollate, 0}},
+ {2415, {wxPrintDialogData, getFromPage, 0}},
+ {2416, {wxPrintDialogData, getMaxPage, 0}},
+ {2417, {wxPrintDialogData, getMinPage, 0}},
+ {2418, {wxPrintDialogData, getNoCopies, 0}},
+ {2419, {wxPrintDialogData, getPrintData, 0}},
+ {2420, {wxPrintDialogData, getPrintToFile, 0}},
+ {2421, {wxPrintDialogData, getSelection, 0}},
+ {2422, {wxPrintDialogData, getToPage, 0}},
+ {2423, {wxPrintDialogData, isOk, 0}},
+ {2424, {wxPrintDialogData, setCollate, 1}},
+ {2425, {wxPrintDialogData, setFromPage, 1}},
+ {2426, {wxPrintDialogData, setMaxPage, 1}},
+ {2427, {wxPrintDialogData, setMinPage, 1}},
+ {2428, {wxPrintDialogData, setNoCopies, 1}},
+ {2429, {wxPrintDialogData, setPrintData, 1}},
+ {2430, {wxPrintDialogData, setPrintToFile, 1}},
+ {2431, {wxPrintDialogData, setSelection, 1}},
+ {2432, {wxPrintDialogData, setToPage, 1}},
+ {2433, {wxPrintData, new_0, 0}},
+ {2434, {wxPrintData, new_1, 1}},
+ {2435, {wxPrintData, destruct, 0}},
+ {2436, {wxPrintData, getCollate, 0}},
+ {2437, {wxPrintData, getBin, 0}},
+ {2438, {wxPrintData, getColour, 0}},
+ {2439, {wxPrintData, getDuplex, 0}},
+ {2440, {wxPrintData, getNoCopies, 0}},
+ {2441, {wxPrintData, getOrientation, 0}},
+ {2442, {wxPrintData, getPaperId, 0}},
+ {2443, {wxPrintData, getPrinterName, 0}},
+ {2444, {wxPrintData, getQuality, 0}},
+ {2445, {wxPrintData, isOk, 0}},
+ {2446, {wxPrintData, setBin, 1}},
+ {2447, {wxPrintData, setCollate, 1}},
+ {2448, {wxPrintData, setColour, 1}},
+ {2449, {wxPrintData, setDuplex, 1}},
+ {2450, {wxPrintData, setNoCopies, 1}},
+ {2451, {wxPrintData, setOrientation, 1}},
+ {2452, {wxPrintData, setPaperId, 1}},
+ {2453, {wxPrintData, setPrinterName, 1}},
+ {2454, {wxPrintData, setQuality, 1}},
+ {2457, {wxPrintPreview, new_2, 2}},
+ {2458, {wxPrintPreview, new_3, 3}},
+ {2460, {wxPrintPreview, destruct, 0}},
+ {2461, {wxPrintPreview, getCanvas, 0}},
+ {2462, {wxPrintPreview, getCurrentPage, 0}},
+ {2463, {wxPrintPreview, getFrame, 0}},
+ {2464, {wxPrintPreview, getMaxPage, 0}},
+ {2465, {wxPrintPreview, getMinPage, 0}},
+ {2466, {wxPrintPreview, getPrintout, 0}},
+ {2467, {wxPrintPreview, getPrintoutForPrinting, 0}},
+ {2468, {wxPrintPreview, isOk, 0}},
+ {2469, {wxPrintPreview, paintPage, 2}},
+ {2470, {wxPrintPreview, print, 1}},
+ {2471, {wxPrintPreview, renderPage, 1}},
+ {2472, {wxPrintPreview, setCanvas, 1}},
+ {2473, {wxPrintPreview, setCurrentPage, 1}},
+ {2474, {wxPrintPreview, setFrame, 1}},
+ {2475, {wxPrintPreview, setPrintout, 1}},
+ {2476, {wxPrintPreview, setZoom, 1}},
+ {2477, {wxPreviewFrame, new, 3}},
+ {2478, {wxPreviewFrame, destruct, 0}},
+ {2479, {wxPreviewFrame, createControlBar, 0}},
+ {2480, {wxPreviewFrame, createCanvas, 0}},
+ {2481, {wxPreviewFrame, initialize, 0}},
+ {2482, {wxPreviewFrame, onCloseWindow, 1}},
+ {2483, {wxPreviewControlBar, new, 4}},
+ {2484, {wxPreviewControlBar, destruct, 0}},
+ {2485, {wxPreviewControlBar, createButtons, 0}},
+ {2486, {wxPreviewControlBar, getPrintPreview, 0}},
+ {2487, {wxPreviewControlBar, getZoomControl, 0}},
+ {2488, {wxPreviewControlBar, setZoomControl, 1}},
+ {2490, {wxPrinter, new, 1}},
+ {2491, {wxPrinter, createAbortWindow, 2}},
+ {2492, {wxPrinter, getAbort, 0}},
+ {2493, {wxPrinter, getLastError, 0}},
+ {2494, {wxPrinter, getPrintDialogData, 0}},
+ {2495, {wxPrinter, print, 3}},
+ {2496, {wxPrinter, printDialog, 1}},
+ {2497, {wxPrinter, reportError, 3}},
+ {2498, {wxPrinter, setup, 1}},
+ {2499, {wxPrinter, 'Destroy', undefined}},
+ {2500, {wxXmlResource, new_1, 1}},
+ {2501, {wxXmlResource, new_2, 2}},
+ {2502, {wxXmlResource, destruct, 0}},
+ {2503, {wxXmlResource, attachUnknownControl, 3}},
+ {2504, {wxXmlResource, clearHandlers, 0}},
+ {2505, {wxXmlResource, compareVersion, 4}},
+ {2506, {wxXmlResource, get, 0}},
+ {2507, {wxXmlResource, getFlags, 0}},
+ {2508, {wxXmlResource, getVersion, 0}},
+ {2509, {wxXmlResource, getXRCID, 2}},
+ {2510, {wxXmlResource, initAllHandlers, 0}},
+ {2511, {wxXmlResource, load, 1}},
+ {2512, {wxXmlResource, loadBitmap, 1}},
+ {2513, {wxXmlResource, loadDialog_2, 2}},
+ {2514, {wxXmlResource, loadDialog_3, 3}},
+ {2515, {wxXmlResource, loadFrame_2, 2}},
+ {2516, {wxXmlResource, loadFrame_3, 3}},
+ {2517, {wxXmlResource, loadIcon, 1}},
+ {2518, {wxXmlResource, loadMenu, 1}},
+ {2519, {wxXmlResource, loadMenuBar_2, 2}},
+ {2520, {wxXmlResource, loadMenuBar_1, 1}},
+ {2521, {wxXmlResource, loadPanel_2, 2}},
+ {2522, {wxXmlResource, loadPanel_3, 3}},
+ {2523, {wxXmlResource, loadToolBar, 2}},
+ {2524, {wxXmlResource, set, 1}},
+ {2525, {wxXmlResource, setFlags, 1}},
+ {2526, {wxXmlResource, unload, 1}},
+ {2527, {wxXmlResource, xrcctrl, 3}},
+ {2528, {wxHtmlEasyPrinting, new, 1}},
+ {2529, {wxHtmlEasyPrinting, destruct, 0}},
+ {2530, {wxHtmlEasyPrinting, getPrintData, 0}},
+ {2531, {wxHtmlEasyPrinting, getPageSetupData, 0}},
+ {2532, {wxHtmlEasyPrinting, previewFile, 1}},
+ {2533, {wxHtmlEasyPrinting, previewText, 2}},
+ {2534, {wxHtmlEasyPrinting, printFile, 1}},
+ {2535, {wxHtmlEasyPrinting, printText, 2}},
+ {2536, {wxHtmlEasyPrinting, pageSetup, 0}},
+ {2537, {wxHtmlEasyPrinting, setFonts, 3}},
+ {2538, {wxHtmlEasyPrinting, setHeader, 2}},
+ {2539, {wxHtmlEasyPrinting, setFooter, 2}},
+ {2541, {wxGLCanvas, new_2, 2}},
+ {2542, {wxGLCanvas, new_3_1, 3}},
+ {2543, {wxGLCanvas, new_3_0, 3}},
+ {2544, {wxGLCanvas, getContext, 0}},
+ {2546, {wxGLCanvas, setCurrent, 0}},
+ {2547, {wxGLCanvas, swapBuffers, 0}},
+ {2548, {wxGLCanvas, 'Destroy', undefined}},
+ {2549, {wxAuiManager, new, 1}},
+ {2550, {wxAuiManager, destruct, 0}},
+ {2551, {wxAuiManager, addPane_2_1, 2}},
+ {2552, {wxAuiManager, addPane_3, 3}},
+ {2553, {wxAuiManager, addPane_2_0, 2}},
+ {2554, {wxAuiManager, detachPane, 1}},
+ {2555, {wxAuiManager, getAllPanes, 0}},
+ {2556, {wxAuiManager, getArtProvider, 0}},
+ {2557, {wxAuiManager, getDockSizeConstraint, 2}},
+ {2558, {wxAuiManager, getFlags, 0}},
+ {2559, {wxAuiManager, getManagedWindow, 0}},
+ {2560, {wxAuiManager, getManager, 1}},
+ {2561, {wxAuiManager, getPane_1_1, 1}},
+ {2562, {wxAuiManager, getPane_1_0, 1}},
+ {2563, {wxAuiManager, hideHint, 0}},
+ {2564, {wxAuiManager, insertPane, 3}},
+ {2565, {wxAuiManager, loadPaneInfo, 2}},
+ {2566, {wxAuiManager, loadPerspective, 2}},
+ {2567, {wxAuiManager, savePaneInfo, 1}},
+ {2568, {wxAuiManager, savePerspective, 0}},
+ {2569, {wxAuiManager, setArtProvider, 1}},
+ {2570, {wxAuiManager, setDockSizeConstraint, 2}},
+ {2571, {wxAuiManager, setFlags, 1}},
+ {2572, {wxAuiManager, setManagedWindow, 1}},
+ {2573, {wxAuiManager, showHint, 1}},
+ {2574, {wxAuiManager, unInit, 0}},
+ {2575, {wxAuiManager, update, 0}},
+ {2576, {wxAuiPaneInfo, new_0, 0}},
+ {2577, {wxAuiPaneInfo, new_1, 1}},
+ {2578, {wxAuiPaneInfo, destruct, 0}},
+ {2579, {wxAuiPaneInfo, bestSize_1, 1}},
+ {2580, {wxAuiPaneInfo, bestSize_2, 2}},
+ {2581, {wxAuiPaneInfo, bottom, 0}},
+ {2582, {wxAuiPaneInfo, bottomDockable, 1}},
+ {2583, {wxAuiPaneInfo, caption, 1}},
+ {2584, {wxAuiPaneInfo, captionVisible, 1}},
+ {2585, {wxAuiPaneInfo, centre, 0}},
+ {2586, {wxAuiPaneInfo, centrePane, 0}},
+ {2587, {wxAuiPaneInfo, closeButton, 1}},
+ {2588, {wxAuiPaneInfo, defaultPane, 0}},
+ {2589, {wxAuiPaneInfo, destroyOnClose, 1}},
+ {2590, {wxAuiPaneInfo, direction, 1}},
+ {2591, {wxAuiPaneInfo, dock, 0}},
+ {2592, {wxAuiPaneInfo, dockable, 1}},
+ {2593, {wxAuiPaneInfo, fixed, 0}},
+ {2594, {wxAuiPaneInfo, float, 0}},
+ {2595, {wxAuiPaneInfo, floatable, 1}},
+ {2596, {wxAuiPaneInfo, floatingPosition_1, 1}},
+ {2597, {wxAuiPaneInfo, floatingPosition_2, 2}},
+ {2598, {wxAuiPaneInfo, floatingSize_1, 1}},
+ {2599, {wxAuiPaneInfo, floatingSize_2, 2}},
+ {2600, {wxAuiPaneInfo, gripper, 1}},
+ {2601, {wxAuiPaneInfo, gripperTop, 1}},
+ {2602, {wxAuiPaneInfo, hasBorder, 0}},
+ {2603, {wxAuiPaneInfo, hasCaption, 0}},
+ {2604, {wxAuiPaneInfo, hasCloseButton, 0}},
+ {2605, {wxAuiPaneInfo, hasFlag, 1}},
+ {2606, {wxAuiPaneInfo, hasGripper, 0}},
+ {2607, {wxAuiPaneInfo, hasGripperTop, 0}},
+ {2608, {wxAuiPaneInfo, hasMaximizeButton, 0}},
+ {2609, {wxAuiPaneInfo, hasMinimizeButton, 0}},
+ {2610, {wxAuiPaneInfo, hasPinButton, 0}},
+ {2611, {wxAuiPaneInfo, hide, 0}},
+ {2612, {wxAuiPaneInfo, isBottomDockable, 0}},
+ {2613, {wxAuiPaneInfo, isDocked, 0}},
+ {2614, {wxAuiPaneInfo, isFixed, 0}},
+ {2615, {wxAuiPaneInfo, isFloatable, 0}},
+ {2616, {wxAuiPaneInfo, isFloating, 0}},
+ {2617, {wxAuiPaneInfo, isLeftDockable, 0}},
+ {2618, {wxAuiPaneInfo, isMovable, 0}},
+ {2619, {wxAuiPaneInfo, isOk, 0}},
+ {2620, {wxAuiPaneInfo, isResizable, 0}},
+ {2621, {wxAuiPaneInfo, isRightDockable, 0}},
+ {2622, {wxAuiPaneInfo, isShown, 0}},
+ {2623, {wxAuiPaneInfo, isToolbar, 0}},
+ {2624, {wxAuiPaneInfo, isTopDockable, 0}},
+ {2625, {wxAuiPaneInfo, layer, 1}},
+ {2626, {wxAuiPaneInfo, left, 0}},
+ {2627, {wxAuiPaneInfo, leftDockable, 1}},
+ {2628, {wxAuiPaneInfo, maxSize_1, 1}},
+ {2629, {wxAuiPaneInfo, maxSize_2, 2}},
+ {2630, {wxAuiPaneInfo, maximizeButton, 1}},
+ {2631, {wxAuiPaneInfo, minSize_1, 1}},
+ {2632, {wxAuiPaneInfo, minSize_2, 2}},
+ {2633, {wxAuiPaneInfo, minimizeButton, 1}},
+ {2634, {wxAuiPaneInfo, movable, 1}},
+ {2635, {wxAuiPaneInfo, name, 1}},
+ {2636, {wxAuiPaneInfo, paneBorder, 1}},
+ {2637, {wxAuiPaneInfo, pinButton, 1}},
+ {2638, {wxAuiPaneInfo, position, 1}},
+ {2639, {wxAuiPaneInfo, resizable, 1}},
+ {2640, {wxAuiPaneInfo, right, 0}},
+ {2641, {wxAuiPaneInfo, rightDockable, 1}},
+ {2642, {wxAuiPaneInfo, row, 1}},
+ {2643, {wxAuiPaneInfo, safeSet, 1}},
+ {2644, {wxAuiPaneInfo, setFlag, 2}},
+ {2645, {wxAuiPaneInfo, show, 1}},
+ {2646, {wxAuiPaneInfo, toolbarPane, 0}},
+ {2647, {wxAuiPaneInfo, top, 0}},
+ {2648, {wxAuiPaneInfo, topDockable, 1}},
+ {2649, {wxAuiPaneInfo, window, 1}},
+ {2650, {wxAuiNotebook, new_0, 0}},
+ {2651, {wxAuiNotebook, new_2, 2}},
+ {2652, {wxAuiNotebook, addPage, 3}},
+ {2653, {wxAuiNotebook, create, 2}},
+ {2654, {wxAuiNotebook, deletePage, 1}},
+ {2655, {wxAuiNotebook, getArtProvider, 0}},
+ {2656, {wxAuiNotebook, getPage, 1}},
+ {2657, {wxAuiNotebook, getPageBitmap, 1}},
+ {2658, {wxAuiNotebook, getPageCount, 0}},
+ {2659, {wxAuiNotebook, getPageIndex, 1}},
+ {2660, {wxAuiNotebook, getPageText, 1}},
+ {2661, {wxAuiNotebook, getSelection, 0}},
+ {2662, {wxAuiNotebook, insertPage, 4}},
+ {2663, {wxAuiNotebook, removePage, 1}},
+ {2664, {wxAuiNotebook, setArtProvider, 1}},
+ {2665, {wxAuiNotebook, setFont, 1}},
+ {2666, {wxAuiNotebook, setPageBitmap, 2}},
+ {2667, {wxAuiNotebook, setPageText, 2}},
+ {2668, {wxAuiNotebook, setSelection, 1}},
+ {2669, {wxAuiNotebook, setTabCtrlHeight, 1}},
+ {2670, {wxAuiNotebook, setUniformBitmapSize, 1}},
+ {2671, {wxAuiNotebook, 'Destroy', undefined}},
+ {2672, {wxMDIParentFrame, new_0, 0}},
+ {2673, {wxMDIParentFrame, new_4, 4}},
+ {2674, {wxMDIParentFrame, destruct, 0}},
+ {2675, {wxMDIParentFrame, activateNext, 0}},
+ {2676, {wxMDIParentFrame, activatePrevious, 0}},
+ {2677, {wxMDIParentFrame, arrangeIcons, 0}},
+ {2678, {wxMDIParentFrame, cascade, 0}},
+ {2679, {wxMDIParentFrame, create, 4}},
+ {2680, {wxMDIParentFrame, getActiveChild, 0}},
+ {2681, {wxMDIParentFrame, getClientWindow, 0}},
+ {2682, {wxMDIParentFrame, tile, 1}},
+ {2683, {wxMDIChildFrame, new_0, 0}},
+ {2684, {wxMDIChildFrame, new_4, 4}},
+ {2685, {wxMDIChildFrame, destruct, 0}},
+ {2686, {wxMDIChildFrame, activate, 0}},
+ {2687, {wxMDIChildFrame, create, 4}},
+ {2688, {wxMDIChildFrame, maximize, 1}},
+ {2689, {wxMDIChildFrame, restore, 0}},
+ {2690, {wxMDIClientWindow, new_0, 0}},
+ {2691, {wxMDIClientWindow, new_2, 2}},
+ {2692, {wxMDIClientWindow, destruct, 0}},
+ {2693, {wxMDIClientWindow, createClient, 2}},
+ {2694, {wxLayoutAlgorithm, new, 0}},
+ {2695, {wxLayoutAlgorithm, layoutFrame, 2}},
+ {2696, {wxLayoutAlgorithm, layoutMDIFrame, 2}},
+ {2697, {wxLayoutAlgorithm, layoutWindow, 2}},
+ {2698, {wxLayoutAlgorithm, 'Destroy', undefined}},
+ {2699, {wxEvent, getId, 0}},
+ {2700, {wxEvent, getSkipped, 0}},
+ {2701, {wxEvent, getTimestamp, 0}},
+ {2702, {wxEvent, isCommandEvent, 0}},
+ {2703, {wxEvent, resumePropagation, 1}},
+ {2704, {wxEvent, shouldPropagate, 0}},
+ {2705, {wxEvent, skip, 1}},
+ {2706, {wxEvent, stopPropagation, 0}},
+ {2707, {wxCommandEvent, getClientData, 0}},
+ {2708, {wxCommandEvent, getExtraLong, 0}},
+ {2709, {wxCommandEvent, getInt, 0}},
+ {2710, {wxCommandEvent, getSelection, 0}},
+ {2711, {wxCommandEvent, getString, 0}},
+ {2712, {wxCommandEvent, isChecked, 0}},
+ {2713, {wxCommandEvent, isSelection, 0}},
+ {2714, {wxCommandEvent, setInt, 1}},
+ {2715, {wxCommandEvent, setString, 1}},
+ {2716, {wxScrollEvent, getOrientation, 0}},
+ {2717, {wxScrollEvent, getPosition, 0}},
+ {2718, {wxScrollWinEvent, getOrientation, 0}},
+ {2719, {wxScrollWinEvent, getPosition, 0}},
+ {2720, {wxMouseEvent, altDown, 0}},
+ {2721, {wxMouseEvent, button, 1}},
+ {2722, {wxMouseEvent, buttonDClick, 1}},
+ {2723, {wxMouseEvent, buttonDown, 1}},
+ {2724, {wxMouseEvent, buttonUp, 1}},
+ {2725, {wxMouseEvent, cmdDown, 0}},
+ {2726, {wxMouseEvent, controlDown, 0}},
+ {2727, {wxMouseEvent, dragging, 0}},
+ {2728, {wxMouseEvent, entering, 0}},
+ {2729, {wxMouseEvent, getButton, 0}},
+ {2732, {wxMouseEvent, getPosition, 0}},
+ {2733, {wxMouseEvent, getLogicalPosition, 1}},
+ {2734, {wxMouseEvent, getLinesPerAction, 0}},
+ {2735, {wxMouseEvent, getWheelRotation, 0}},
+ {2736, {wxMouseEvent, getWheelDelta, 0}},
+ {2737, {wxMouseEvent, getX, 0}},
+ {2738, {wxMouseEvent, getY, 0}},
+ {2739, {wxMouseEvent, isButton, 0}},
+ {2740, {wxMouseEvent, isPageScroll, 0}},
+ {2741, {wxMouseEvent, leaving, 0}},
+ {2742, {wxMouseEvent, leftDClick, 0}},
+ {2743, {wxMouseEvent, leftDown, 0}},
+ {2744, {wxMouseEvent, leftIsDown, 0}},
+ {2745, {wxMouseEvent, leftUp, 0}},
+ {2746, {wxMouseEvent, metaDown, 0}},
+ {2747, {wxMouseEvent, middleDClick, 0}},
+ {2748, {wxMouseEvent, middleDown, 0}},
+ {2749, {wxMouseEvent, middleIsDown, 0}},
+ {2750, {wxMouseEvent, middleUp, 0}},
+ {2751, {wxMouseEvent, moving, 0}},
+ {2752, {wxMouseEvent, rightDClick, 0}},
+ {2753, {wxMouseEvent, rightDown, 0}},
+ {2754, {wxMouseEvent, rightIsDown, 0}},
+ {2755, {wxMouseEvent, rightUp, 0}},
+ {2756, {wxMouseEvent, shiftDown, 0}},
+ {2757, {wxSetCursorEvent, getCursor, 0}},
+ {2758, {wxSetCursorEvent, getX, 0}},
+ {2759, {wxSetCursorEvent, getY, 0}},
+ {2760, {wxSetCursorEvent, hasCursor, 0}},
+ {2761, {wxSetCursorEvent, setCursor, 1}},
+ {2762, {wxKeyEvent, altDown, 0}},
+ {2763, {wxKeyEvent, cmdDown, 0}},
+ {2764, {wxKeyEvent, controlDown, 0}},
+ {2765, {wxKeyEvent, getKeyCode, 0}},
+ {2766, {wxKeyEvent, getModifiers, 0}},
+ {2769, {wxKeyEvent, getPosition, 0}},
+ {2770, {wxKeyEvent, getRawKeyCode, 0}},
+ {2771, {wxKeyEvent, getRawKeyFlags, 0}},
+ {2772, {wxKeyEvent, getUnicodeKey, 0}},
+ {2773, {wxKeyEvent, getX, 0}},
+ {2774, {wxKeyEvent, getY, 0}},
+ {2775, {wxKeyEvent, hasModifiers, 0}},
+ {2776, {wxKeyEvent, metaDown, 0}},
+ {2777, {wxKeyEvent, shiftDown, 0}},
+ {2778, {wxSizeEvent, getSize, 0}},
+ {2779, {wxMoveEvent, getPosition, 0}},
+ {2780, {wxEraseEvent, getDC, 0}},
+ {2781, {wxFocusEvent, getWindow, 0}},
+ {2782, {wxChildFocusEvent, getWindow, 0}},
+ {2783, {wxMenuEvent, getMenu, 0}},
+ {2784, {wxMenuEvent, getMenuId, 0}},
+ {2785, {wxMenuEvent, isPopup, 0}},
+ {2786, {wxCloseEvent, canVeto, 0}},
+ {2787, {wxCloseEvent, getLoggingOff, 0}},
+ {2788, {wxCloseEvent, setCanVeto, 1}},
+ {2789, {wxCloseEvent, setLoggingOff, 1}},
+ {2790, {wxCloseEvent, veto, 1}},
+ {2791, {wxShowEvent, setShow, 1}},
+ {2792, {wxShowEvent, getShow, 0}},
+ {2793, {wxIconizeEvent, iconized, 0}},
+ {2794, {wxJoystickEvent, buttonDown, 1}},
+ {2795, {wxJoystickEvent, buttonIsDown, 1}},
+ {2796, {wxJoystickEvent, buttonUp, 1}},
+ {2797, {wxJoystickEvent, getButtonChange, 0}},
+ {2798, {wxJoystickEvent, getButtonState, 0}},
+ {2799, {wxJoystickEvent, getJoystick, 0}},
+ {2800, {wxJoystickEvent, getPosition, 0}},
+ {2801, {wxJoystickEvent, getZPosition, 0}},
+ {2802, {wxJoystickEvent, isButton, 0}},
+ {2803, {wxJoystickEvent, isMove, 0}},
+ {2804, {wxJoystickEvent, isZMove, 0}},
+ {2805, {wxUpdateUIEvent, canUpdate, 1}},
+ {2806, {wxUpdateUIEvent, check, 1}},
+ {2807, {wxUpdateUIEvent, enable, 1}},
+ {2808, {wxUpdateUIEvent, show, 1}},
+ {2809, {wxUpdateUIEvent, getChecked, 0}},
+ {2810, {wxUpdateUIEvent, getEnabled, 0}},
+ {2811, {wxUpdateUIEvent, getShown, 0}},
+ {2812, {wxUpdateUIEvent, getSetChecked, 0}},
+ {2813, {wxUpdateUIEvent, getSetEnabled, 0}},
+ {2814, {wxUpdateUIEvent, getSetShown, 0}},
+ {2815, {wxUpdateUIEvent, getSetText, 0}},
+ {2816, {wxUpdateUIEvent, getText, 0}},
+ {2817, {wxUpdateUIEvent, getMode, 0}},
+ {2818, {wxUpdateUIEvent, getUpdateInterval, 0}},
+ {2819, {wxUpdateUIEvent, resetUpdateTime, 0}},
+ {2820, {wxUpdateUIEvent, setMode, 1}},
+ {2821, {wxUpdateUIEvent, setText, 1}},
+ {2822, {wxUpdateUIEvent, setUpdateInterval, 1}},
+ {2823, {wxMouseCaptureChangedEvent, getCapturedWindow, 0}},
+ {2824, {wxPaletteChangedEvent, setChangedWindow, 1}},
+ {2825, {wxPaletteChangedEvent, getChangedWindow, 0}},
+ {2826, {wxQueryNewPaletteEvent, setPaletteRealized, 1}},
+ {2827, {wxQueryNewPaletteEvent, getPaletteRealized, 0}},
+ {2828, {wxNavigationKeyEvent, getDirection, 0}},
+ {2829, {wxNavigationKeyEvent, setDirection, 1}},
+ {2830, {wxNavigationKeyEvent, isWindowChange, 0}},
+ {2831, {wxNavigationKeyEvent, setWindowChange, 1}},
+ {2832, {wxNavigationKeyEvent, isFromTab, 0}},
+ {2833, {wxNavigationKeyEvent, setFromTab, 1}},
+ {2834, {wxNavigationKeyEvent, getCurrentFocus, 0}},
+ {2835, {wxNavigationKeyEvent, setCurrentFocus, 1}},
+ {2836, {wxHelpEvent, getOrigin, 0}},
+ {2837, {wxHelpEvent, getPosition, 0}},
+ {2838, {wxHelpEvent, setOrigin, 1}},
+ {2839, {wxHelpEvent, setPosition, 1}},
+ {2840, {wxContextMenuEvent, getPosition, 0}},
+ {2841, {wxContextMenuEvent, setPosition, 1}},
+ {2842, {wxIdleEvent, canSend, 1}},
+ {2843, {wxIdleEvent, getMode, 0}},
+ {2844, {wxIdleEvent, requestMore, 1}},
+ {2845, {wxIdleEvent, moreRequested, 0}},
+ {2846, {wxIdleEvent, setMode, 1}},
+ {2847, {wxGridEvent, altDown, 0}},
+ {2848, {wxGridEvent, controlDown, 0}},
+ {2849, {wxGridEvent, getCol, 0}},
+ {2850, {wxGridEvent, getPosition, 0}},
+ {2851, {wxGridEvent, getRow, 0}},
+ {2852, {wxGridEvent, metaDown, 0}},
+ {2853, {wxGridEvent, selecting, 0}},
+ {2854, {wxGridEvent, shiftDown, 0}},
+ {2855, {wxNotifyEvent, allow, 0}},
+ {2856, {wxNotifyEvent, isAllowed, 0}},
+ {2857, {wxNotifyEvent, veto, 0}},
+ {2858, {wxSashEvent, getEdge, 0}},
+ {2859, {wxSashEvent, getDragRect, 0}},
+ {2860, {wxSashEvent, getDragStatus, 0}},
+ {2861, {wxListEvent, getCacheFrom, 0}},
+ {2862, {wxListEvent, getCacheTo, 0}},
+ {2863, {wxListEvent, getKeyCode, 0}},
+ {2864, {wxListEvent, getIndex, 0}},
+ {2865, {wxListEvent, getColumn, 0}},
+ {2866, {wxListEvent, getPoint, 0}},
+ {2867, {wxListEvent, getLabel, 0}},
+ {2868, {wxListEvent, getText, 0}},
+ {2869, {wxListEvent, getImage, 0}},
+ {2870, {wxListEvent, getData, 0}},
+ {2871, {wxListEvent, getMask, 0}},
+ {2872, {wxListEvent, getItem, 0}},
+ {2873, {wxListEvent, isEditCancelled, 0}},
+ {2874, {wxDateEvent, getDate, 0}},
+ {2875, {wxCalendarEvent, getWeekDay, 0}},
+ {2876, {wxFileDirPickerEvent, getPath, 0}},
+ {2877, {wxColourPickerEvent, getColour, 0}},
+ {2878, {wxFontPickerEvent, getFont, 0}},
+ {2879, {wxStyledTextEvent, getPosition, 0}},
+ {2880, {wxStyledTextEvent, getKey, 0}},
+ {2881, {wxStyledTextEvent, getModifiers, 0}},
+ {2882, {wxStyledTextEvent, getModificationType, 0}},
+ {2883, {wxStyledTextEvent, getText, 0}},
+ {2884, {wxStyledTextEvent, getLength, 0}},
+ {2885, {wxStyledTextEvent, getLinesAdded, 0}},
+ {2886, {wxStyledTextEvent, getLine, 0}},
+ {2887, {wxStyledTextEvent, getFoldLevelNow, 0}},
+ {2888, {wxStyledTextEvent, getFoldLevelPrev, 0}},
+ {2889, {wxStyledTextEvent, getMargin, 0}},
+ {2890, {wxStyledTextEvent, getMessage, 0}},
+ {2891, {wxStyledTextEvent, getWParam, 0}},
+ {2892, {wxStyledTextEvent, getLParam, 0}},
+ {2893, {wxStyledTextEvent, getListType, 0}},
+ {2894, {wxStyledTextEvent, getX, 0}},
+ {2895, {wxStyledTextEvent, getY, 0}},
+ {2896, {wxStyledTextEvent, getDragText, 0}},
+ {2897, {wxStyledTextEvent, getDragAllowMove, 0}},
+ {2898, {wxStyledTextEvent, getDragResult, 0}},
+ {2899, {wxStyledTextEvent, getShift, 0}},
+ {2900, {wxStyledTextEvent, getControl, 0}},
+ {2901, {wxStyledTextEvent, getAlt, 0}},
+ {2902, {utils, getKeyState, 1}},
+ {2903, {utils, getMousePosition, 2}},
+ {2904, {utils, getMouseState, 0}},
+ {2905, {utils, setDetectableAutoRepeat, 1}},
+ {2906, {utils, bell, 0}},
+ {2907, {utils, findMenuItemId, 3}},
+ {2908, {utils, genericFindWindowAtPoint, 1}},
+ {2909, {utils, findWindowAtPoint, 1}},
+ {2910, {utils, beginBusyCursor, 1}},
+ {2911, {utils, endBusyCursor, 0}},
+ {2912, {utils, isBusy, 0}},
+ {2913, {utils, shutdown, 1}},
+ {2914, {utils, shell, 1}},
+ {2915, {utils, launchDefaultBrowser, 2}},
+ {2916, {utils, getEmailAddress, 0}},
+ {2917, {utils, getUserId, 0}},
+ {2918, {utils, getHomeDir, 0}},
+ {2919, {utils, newId, 0}},
+ {2920, {utils, registerId, 1}},
+ {2921, {utils, getCurrentId, 0}},
+ {2922, {utils, getOsDescription, 0}},
+ {2923, {utils, isPlatformLittleEndian, 0}},
+ {2924, {utils, isPlatform64Bit, 0}},
+ {2925, {wxPrintout, new, 1}},
+ {2926, {wxPrintout, destruct, 0}},
+ {2927, {wxPrintout, getDC, 0}},
+ {2928, {wxPrintout, getPageSizeMM, 2}},
+ {2929, {wxPrintout, getPageSizePixels, 2}},
+ {2930, {wxPrintout, getPaperRectPixels, 0}},
+ {2931, {wxPrintout, getPPIPrinter, 2}},
+ {2932, {wxPrintout, getPPIScreen, 2}},
+ {2933, {wxPrintout, getTitle, 0}},
+ {2934, {wxPrintout, isPreview, 0}},
+ {2935, {wxPrintout, fitThisSizeToPaper, 1}},
+ {2936, {wxPrintout, fitThisSizeToPage, 1}},
+ {2937, {wxPrintout, fitThisSizeToPageMargins, 2}},
+ {2938, {wxPrintout, mapScreenSizeToPaper, 0}},
+ {2939, {wxPrintout, mapScreenSizeToPage, 0}},
+ {2940, {wxPrintout, mapScreenSizeToPageMargins, 1}},
+ {2941, {wxPrintout, mapScreenSizeToDevice, 0}},
+ {2942, {wxPrintout, getLogicalPaperRect, 0}},
+ {2943, {wxPrintout, getLogicalPageRect, 0}},
+ {2944, {wxPrintout, getLogicalPageMarginsRect, 1}},
+ {2945, {wxPrintout, setLogicalOrigin, 2}},
+ {2946, {wxPrintout, offsetLogicalOrigin, 2}},
+ {2947, {wxStyledTextCtrl, new_2, 2}},
+ {2948, {wxStyledTextCtrl, new_0, 0}},
+ {2949, {wxStyledTextCtrl, destruct, 0}},
+ {2950, {wxStyledTextCtrl, create, 2}},
+ {2951, {wxStyledTextCtrl, addText, 1}},
+ {2952, {wxStyledTextCtrl, addStyledText, 1}},
+ {2953, {wxStyledTextCtrl, insertText, 2}},
+ {2954, {wxStyledTextCtrl, clearAll, 0}},
+ {2955, {wxStyledTextCtrl, clearDocumentStyle, 0}},
+ {2956, {wxStyledTextCtrl, getLength, 0}},
+ {2957, {wxStyledTextCtrl, getCharAt, 1}},
+ {2958, {wxStyledTextCtrl, getCurrentPos, 0}},
+ {2959, {wxStyledTextCtrl, getAnchor, 0}},
+ {2960, {wxStyledTextCtrl, getStyleAt, 1}},
+ {2961, {wxStyledTextCtrl, redo, 0}},
+ {2962, {wxStyledTextCtrl, setUndoCollection, 1}},
+ {2963, {wxStyledTextCtrl, selectAll, 0}},
+ {2964, {wxStyledTextCtrl, setSavePoint, 0}},
+ {2965, {wxStyledTextCtrl, getStyledText, 2}},
+ {2966, {wxStyledTextCtrl, canRedo, 0}},
+ {2967, {wxStyledTextCtrl, markerLineFromHandle, 1}},
+ {2968, {wxStyledTextCtrl, markerDeleteHandle, 1}},
+ {2969, {wxStyledTextCtrl, getUndoCollection, 0}},
+ {2970, {wxStyledTextCtrl, getViewWhiteSpace, 0}},
+ {2971, {wxStyledTextCtrl, setViewWhiteSpace, 1}},
+ {2972, {wxStyledTextCtrl, positionFromPoint, 1}},
+ {2973, {wxStyledTextCtrl, positionFromPointClose, 2}},
+ {2974, {wxStyledTextCtrl, gotoLine, 1}},
+ {2975, {wxStyledTextCtrl, gotoPos, 1}},
+ {2976, {wxStyledTextCtrl, setAnchor, 1}},
+ {2977, {wxStyledTextCtrl, getCurLine, 1}},
+ {2978, {wxStyledTextCtrl, getEndStyled, 0}},
+ {2979, {wxStyledTextCtrl, convertEOLs, 1}},
+ {2980, {wxStyledTextCtrl, getEOLMode, 0}},
+ {2981, {wxStyledTextCtrl, setEOLMode, 1}},
+ {2982, {wxStyledTextCtrl, startStyling, 2}},
+ {2983, {wxStyledTextCtrl, setStyling, 2}},
+ {2984, {wxStyledTextCtrl, getBufferedDraw, 0}},
+ {2985, {wxStyledTextCtrl, setBufferedDraw, 1}},
+ {2986, {wxStyledTextCtrl, setTabWidth, 1}},
+ {2987, {wxStyledTextCtrl, getTabWidth, 0}},
+ {2988, {wxStyledTextCtrl, setCodePage, 1}},
+ {2989, {wxStyledTextCtrl, markerDefine, 3}},
+ {2990, {wxStyledTextCtrl, markerSetForeground, 2}},
+ {2991, {wxStyledTextCtrl, markerSetBackground, 2}},
+ {2992, {wxStyledTextCtrl, markerAdd, 2}},
+ {2993, {wxStyledTextCtrl, markerDelete, 2}},
+ {2994, {wxStyledTextCtrl, markerDeleteAll, 1}},
+ {2995, {wxStyledTextCtrl, markerGet, 1}},
+ {2996, {wxStyledTextCtrl, markerNext, 2}},
+ {2997, {wxStyledTextCtrl, markerPrevious, 2}},
+ {2998, {wxStyledTextCtrl, markerDefineBitmap, 2}},
+ {2999, {wxStyledTextCtrl, markerAddSet, 2}},
+ {3000, {wxStyledTextCtrl, markerSetAlpha, 2}},
+ {3001, {wxStyledTextCtrl, setMarginType, 2}},
+ {3002, {wxStyledTextCtrl, getMarginType, 1}},
+ {3003, {wxStyledTextCtrl, setMarginWidth, 2}},
+ {3004, {wxStyledTextCtrl, getMarginWidth, 1}},
+ {3005, {wxStyledTextCtrl, setMarginMask, 2}},
+ {3006, {wxStyledTextCtrl, getMarginMask, 1}},
+ {3007, {wxStyledTextCtrl, setMarginSensitive, 2}},
+ {3008, {wxStyledTextCtrl, getMarginSensitive, 1}},
+ {3009, {wxStyledTextCtrl, styleClearAll, 0}},
+ {3010, {wxStyledTextCtrl, styleSetForeground, 2}},
+ {3011, {wxStyledTextCtrl, styleSetBackground, 2}},
+ {3012, {wxStyledTextCtrl, styleSetBold, 2}},
+ {3013, {wxStyledTextCtrl, styleSetItalic, 2}},
+ {3014, {wxStyledTextCtrl, styleSetSize, 2}},
+ {3015, {wxStyledTextCtrl, styleSetFaceName, 2}},
+ {3016, {wxStyledTextCtrl, styleSetEOLFilled, 2}},
+ {3017, {wxStyledTextCtrl, styleResetDefault, 0}},
+ {3018, {wxStyledTextCtrl, styleSetUnderline, 2}},
+ {3019, {wxStyledTextCtrl, styleSetCase, 2}},
+ {3020, {wxStyledTextCtrl, styleSetHotSpot, 2}},
+ {3021, {wxStyledTextCtrl, setSelForeground, 2}},
+ {3022, {wxStyledTextCtrl, setSelBackground, 2}},
+ {3023, {wxStyledTextCtrl, getSelAlpha, 0}},
+ {3024, {wxStyledTextCtrl, setSelAlpha, 1}},
+ {3025, {wxStyledTextCtrl, setCaretForeground, 1}},
+ {3026, {wxStyledTextCtrl, cmdKeyAssign, 3}},
+ {3027, {wxStyledTextCtrl, cmdKeyClear, 2}},
+ {3028, {wxStyledTextCtrl, cmdKeyClearAll, 0}},
+ {3029, {wxStyledTextCtrl, setStyleBytes, 2}},
+ {3030, {wxStyledTextCtrl, styleSetVisible, 2}},
+ {3031, {wxStyledTextCtrl, getCaretPeriod, 0}},
+ {3032, {wxStyledTextCtrl, setCaretPeriod, 1}},
+ {3033, {wxStyledTextCtrl, setWordChars, 1}},
+ {3034, {wxStyledTextCtrl, beginUndoAction, 0}},
+ {3035, {wxStyledTextCtrl, endUndoAction, 0}},
+ {3036, {wxStyledTextCtrl, indicatorSetStyle, 2}},
+ {3037, {wxStyledTextCtrl, indicatorGetStyle, 1}},
+ {3038, {wxStyledTextCtrl, indicatorSetForeground, 2}},
+ {3039, {wxStyledTextCtrl, indicatorGetForeground, 1}},
+ {3040, {wxStyledTextCtrl, setWhitespaceForeground, 2}},
+ {3041, {wxStyledTextCtrl, setWhitespaceBackground, 2}},
+ {3042, {wxStyledTextCtrl, getStyleBits, 0}},
+ {3043, {wxStyledTextCtrl, setLineState, 2}},
+ {3044, {wxStyledTextCtrl, getLineState, 1}},
+ {3045, {wxStyledTextCtrl, getMaxLineState, 0}},
+ {3046, {wxStyledTextCtrl, getCaretLineVisible, 0}},
+ {3047, {wxStyledTextCtrl, setCaretLineVisible, 1}},
+ {3048, {wxStyledTextCtrl, getCaretLineBackground, 0}},
+ {3049, {wxStyledTextCtrl, setCaretLineBackground, 1}},
+ {3050, {wxStyledTextCtrl, autoCompShow, 2}},
+ {3051, {wxStyledTextCtrl, autoCompCancel, 0}},
+ {3052, {wxStyledTextCtrl, autoCompActive, 0}},
+ {3053, {wxStyledTextCtrl, autoCompPosStart, 0}},
+ {3054, {wxStyledTextCtrl, autoCompComplete, 0}},
+ {3055, {wxStyledTextCtrl, autoCompStops, 1}},
+ {3056, {wxStyledTextCtrl, autoCompSetSeparator, 1}},
+ {3057, {wxStyledTextCtrl, autoCompGetSeparator, 0}},
+ {3058, {wxStyledTextCtrl, autoCompSelect, 1}},
+ {3059, {wxStyledTextCtrl, autoCompSetCancelAtStart, 1}},
+ {3060, {wxStyledTextCtrl, autoCompGetCancelAtStart, 0}},
+ {3061, {wxStyledTextCtrl, autoCompSetFillUps, 1}},
+ {3062, {wxStyledTextCtrl, autoCompSetChooseSingle, 1}},
+ {3063, {wxStyledTextCtrl, autoCompGetChooseSingle, 0}},
+ {3064, {wxStyledTextCtrl, autoCompSetIgnoreCase, 1}},
+ {3065, {wxStyledTextCtrl, autoCompGetIgnoreCase, 0}},
+ {3066, {wxStyledTextCtrl, userListShow, 2}},
+ {3067, {wxStyledTextCtrl, autoCompSetAutoHide, 1}},
+ {3068, {wxStyledTextCtrl, autoCompGetAutoHide, 0}},
+ {3069, {wxStyledTextCtrl, autoCompSetDropRestOfWord, 1}},
+ {3070, {wxStyledTextCtrl, autoCompGetDropRestOfWord, 0}},
+ {3071, {wxStyledTextCtrl, registerImage, 2}},
+ {3072, {wxStyledTextCtrl, clearRegisteredImages, 0}},
+ {3073, {wxStyledTextCtrl, autoCompGetTypeSeparator, 0}},
+ {3074, {wxStyledTextCtrl, autoCompSetTypeSeparator, 1}},
+ {3075, {wxStyledTextCtrl, autoCompSetMaxWidth, 1}},
+ {3076, {wxStyledTextCtrl, autoCompGetMaxWidth, 0}},
+ {3077, {wxStyledTextCtrl, autoCompSetMaxHeight, 1}},
+ {3078, {wxStyledTextCtrl, autoCompGetMaxHeight, 0}},
+ {3079, {wxStyledTextCtrl, setIndent, 1}},
+ {3080, {wxStyledTextCtrl, getIndent, 0}},
+ {3081, {wxStyledTextCtrl, setUseTabs, 1}},
+ {3082, {wxStyledTextCtrl, getUseTabs, 0}},
+ {3083, {wxStyledTextCtrl, setLineIndentation, 2}},
+ {3084, {wxStyledTextCtrl, getLineIndentation, 1}},
+ {3085, {wxStyledTextCtrl, getLineIndentPosition, 1}},
+ {3086, {wxStyledTextCtrl, getColumn, 1}},
+ {3087, {wxStyledTextCtrl, setUseHorizontalScrollBar, 1}},
+ {3088, {wxStyledTextCtrl, getUseHorizontalScrollBar, 0}},
+ {3089, {wxStyledTextCtrl, setIndentationGuides, 1}},
+ {3090, {wxStyledTextCtrl, getIndentationGuides, 0}},
+ {3091, {wxStyledTextCtrl, setHighlightGuide, 1}},
+ {3092, {wxStyledTextCtrl, getHighlightGuide, 0}},
+ {3093, {wxStyledTextCtrl, getLineEndPosition, 1}},
+ {3094, {wxStyledTextCtrl, getCodePage, 0}},
+ {3095, {wxStyledTextCtrl, getCaretForeground, 0}},
+ {3096, {wxStyledTextCtrl, getReadOnly, 0}},
+ {3097, {wxStyledTextCtrl, setCurrentPos, 1}},
+ {3098, {wxStyledTextCtrl, setSelectionStart, 1}},
+ {3099, {wxStyledTextCtrl, getSelectionStart, 0}},
+ {3100, {wxStyledTextCtrl, setSelectionEnd, 1}},
+ {3101, {wxStyledTextCtrl, getSelectionEnd, 0}},
+ {3102, {wxStyledTextCtrl, setPrintMagnification, 1}},
+ {3103, {wxStyledTextCtrl, getPrintMagnification, 0}},
+ {3104, {wxStyledTextCtrl, setPrintColourMode, 1}},
+ {3105, {wxStyledTextCtrl, getPrintColourMode, 0}},
+ {3106, {wxStyledTextCtrl, findText, 4}},
+ {3107, {wxStyledTextCtrl, formatRange, 7}},
+ {3108, {wxStyledTextCtrl, getFirstVisibleLine, 0}},
+ {3109, {wxStyledTextCtrl, getLine, 1}},
+ {3110, {wxStyledTextCtrl, getLineCount, 0}},
+ {3111, {wxStyledTextCtrl, setMarginLeft, 1}},
+ {3112, {wxStyledTextCtrl, getMarginLeft, 0}},
+ {3113, {wxStyledTextCtrl, setMarginRight, 1}},
+ {3114, {wxStyledTextCtrl, getMarginRight, 0}},
+ {3115, {wxStyledTextCtrl, getModify, 0}},
+ {3116, {wxStyledTextCtrl, setSelection, 2}},
+ {3117, {wxStyledTextCtrl, getSelectedText, 0}},
+ {3118, {wxStyledTextCtrl, getTextRange, 2}},
+ {3119, {wxStyledTextCtrl, hideSelection, 1}},
+ {3120, {wxStyledTextCtrl, lineFromPosition, 1}},
+ {3121, {wxStyledTextCtrl, positionFromLine, 1}},
+ {3122, {wxStyledTextCtrl, lineScroll, 2}},
+ {3123, {wxStyledTextCtrl, ensureCaretVisible, 0}},
+ {3124, {wxStyledTextCtrl, replaceSelection, 1}},
+ {3125, {wxStyledTextCtrl, setReadOnly, 1}},
+ {3126, {wxStyledTextCtrl, canPaste, 0}},
+ {3127, {wxStyledTextCtrl, canUndo, 0}},
+ {3128, {wxStyledTextCtrl, emptyUndoBuffer, 0}},
+ {3129, {wxStyledTextCtrl, undo, 0}},
+ {3130, {wxStyledTextCtrl, cut, 0}},
+ {3131, {wxStyledTextCtrl, copy, 0}},
+ {3132, {wxStyledTextCtrl, paste, 0}},
+ {3133, {wxStyledTextCtrl, clear, 0}},
+ {3134, {wxStyledTextCtrl, setText, 1}},
+ {3135, {wxStyledTextCtrl, getText, 0}},
+ {3136, {wxStyledTextCtrl, getTextLength, 0}},
+ {3137, {wxStyledTextCtrl, getOvertype, 0}},
+ {3138, {wxStyledTextCtrl, setCaretWidth, 1}},
+ {3139, {wxStyledTextCtrl, getCaretWidth, 0}},
+ {3140, {wxStyledTextCtrl, setTargetStart, 1}},
+ {3141, {wxStyledTextCtrl, getTargetStart, 0}},
+ {3142, {wxStyledTextCtrl, setTargetEnd, 1}},
+ {3143, {wxStyledTextCtrl, getTargetEnd, 0}},
+ {3144, {wxStyledTextCtrl, replaceTarget, 1}},
+ {3145, {wxStyledTextCtrl, searchInTarget, 1}},
+ {3146, {wxStyledTextCtrl, setSearchFlags, 1}},
+ {3147, {wxStyledTextCtrl, getSearchFlags, 0}},
+ {3148, {wxStyledTextCtrl, callTipShow, 2}},
+ {3149, {wxStyledTextCtrl, callTipCancel, 0}},
+ {3150, {wxStyledTextCtrl, callTipActive, 0}},
+ {3151, {wxStyledTextCtrl, callTipPosAtStart, 0}},
+ {3152, {wxStyledTextCtrl, callTipSetHighlight, 2}},
+ {3153, {wxStyledTextCtrl, callTipSetBackground, 1}},
+ {3154, {wxStyledTextCtrl, callTipSetForeground, 1}},
+ {3155, {wxStyledTextCtrl, callTipSetForegroundHighlight, 1}},
+ {3156, {wxStyledTextCtrl, callTipUseStyle, 1}},
+ {3157, {wxStyledTextCtrl, visibleFromDocLine, 1}},
+ {3158, {wxStyledTextCtrl, docLineFromVisible, 1}},
+ {3159, {wxStyledTextCtrl, wrapCount, 1}},
+ {3160, {wxStyledTextCtrl, setFoldLevel, 2}},
+ {3161, {wxStyledTextCtrl, getFoldLevel, 1}},
+ {3162, {wxStyledTextCtrl, getLastChild, 2}},
+ {3163, {wxStyledTextCtrl, getFoldParent, 1}},
+ {3164, {wxStyledTextCtrl, showLines, 2}},
+ {3165, {wxStyledTextCtrl, hideLines, 2}},
+ {3166, {wxStyledTextCtrl, getLineVisible, 1}},
+ {3167, {wxStyledTextCtrl, setFoldExpanded, 2}},
+ {3168, {wxStyledTextCtrl, getFoldExpanded, 1}},
+ {3169, {wxStyledTextCtrl, toggleFold, 1}},
+ {3170, {wxStyledTextCtrl, ensureVisible, 1}},
+ {3171, {wxStyledTextCtrl, setFoldFlags, 1}},
+ {3172, {wxStyledTextCtrl, ensureVisibleEnforcePolicy, 1}},
+ {3173, {wxStyledTextCtrl, setTabIndents, 1}},
+ {3174, {wxStyledTextCtrl, getTabIndents, 0}},
+ {3175, {wxStyledTextCtrl, setBackSpaceUnIndents, 1}},
+ {3176, {wxStyledTextCtrl, getBackSpaceUnIndents, 0}},
+ {3177, {wxStyledTextCtrl, setMouseDwellTime, 1}},
+ {3178, {wxStyledTextCtrl, getMouseDwellTime, 0}},
+ {3179, {wxStyledTextCtrl, wordStartPosition, 2}},
+ {3180, {wxStyledTextCtrl, wordEndPosition, 2}},
+ {3181, {wxStyledTextCtrl, setWrapMode, 1}},
+ {3182, {wxStyledTextCtrl, getWrapMode, 0}},
+ {3183, {wxStyledTextCtrl, setWrapVisualFlags, 1}},
+ {3184, {wxStyledTextCtrl, getWrapVisualFlags, 0}},
+ {3185, {wxStyledTextCtrl, setWrapVisualFlagsLocation, 1}},
+ {3186, {wxStyledTextCtrl, getWrapVisualFlagsLocation, 0}},
+ {3187, {wxStyledTextCtrl, setWrapStartIndent, 1}},
+ {3188, {wxStyledTextCtrl, getWrapStartIndent, 0}},
+ {3189, {wxStyledTextCtrl, setLayoutCache, 1}},
+ {3190, {wxStyledTextCtrl, getLayoutCache, 0}},
+ {3191, {wxStyledTextCtrl, setScrollWidth, 1}},
+ {3192, {wxStyledTextCtrl, getScrollWidth, 0}},
+ {3193, {wxStyledTextCtrl, textWidth, 2}},
+ {3194, {wxStyledTextCtrl, getEndAtLastLine, 0}},
+ {3195, {wxStyledTextCtrl, textHeight, 1}},
+ {3196, {wxStyledTextCtrl, setUseVerticalScrollBar, 1}},
+ {3197, {wxStyledTextCtrl, getUseVerticalScrollBar, 0}},
+ {3198, {wxStyledTextCtrl, appendText, 1}},
+ {3199, {wxStyledTextCtrl, getTwoPhaseDraw, 0}},
+ {3200, {wxStyledTextCtrl, setTwoPhaseDraw, 1}},
+ {3201, {wxStyledTextCtrl, targetFromSelection, 0}},
+ {3202, {wxStyledTextCtrl, linesJoin, 0}},
+ {3203, {wxStyledTextCtrl, linesSplit, 1}},
+ {3204, {wxStyledTextCtrl, setFoldMarginColour, 2}},
+ {3205, {wxStyledTextCtrl, setFoldMarginHiColour, 2}},
+ {3206, {wxStyledTextCtrl, lineDown, 0}},
+ {3207, {wxStyledTextCtrl, lineDownExtend, 0}},
+ {3208, {wxStyledTextCtrl, lineUp, 0}},
+ {3209, {wxStyledTextCtrl, lineUpExtend, 0}},
+ {3210, {wxStyledTextCtrl, charLeft, 0}},
+ {3211, {wxStyledTextCtrl, charLeftExtend, 0}},
+ {3212, {wxStyledTextCtrl, charRight, 0}},
+ {3213, {wxStyledTextCtrl, charRightExtend, 0}},
+ {3214, {wxStyledTextCtrl, wordLeft, 0}},
+ {3215, {wxStyledTextCtrl, wordLeftExtend, 0}},
+ {3216, {wxStyledTextCtrl, wordRight, 0}},
+ {3217, {wxStyledTextCtrl, wordRightExtend, 0}},
+ {3218, {wxStyledTextCtrl, home, 0}},
+ {3219, {wxStyledTextCtrl, homeExtend, 0}},
+ {3220, {wxStyledTextCtrl, lineEnd, 0}},
+ {3221, {wxStyledTextCtrl, lineEndExtend, 0}},
+ {3222, {wxStyledTextCtrl, documentStart, 0}},
+ {3223, {wxStyledTextCtrl, documentStartExtend, 0}},
+ {3224, {wxStyledTextCtrl, documentEnd, 0}},
+ {3225, {wxStyledTextCtrl, documentEndExtend, 0}},
+ {3226, {wxStyledTextCtrl, pageUp, 0}},
+ {3227, {wxStyledTextCtrl, pageUpExtend, 0}},
+ {3228, {wxStyledTextCtrl, pageDown, 0}},
+ {3229, {wxStyledTextCtrl, pageDownExtend, 0}},
+ {3230, {wxStyledTextCtrl, editToggleOvertype, 0}},
+ {3231, {wxStyledTextCtrl, cancel, 0}},
+ {3232, {wxStyledTextCtrl, deleteBack, 0}},
+ {3233, {wxStyledTextCtrl, tab, 0}},
+ {3234, {wxStyledTextCtrl, backTab, 0}},
+ {3235, {wxStyledTextCtrl, newLine, 0}},
+ {3236, {wxStyledTextCtrl, formFeed, 0}},
+ {3237, {wxStyledTextCtrl, vCHome, 0}},
+ {3238, {wxStyledTextCtrl, vCHomeExtend, 0}},
+ {3239, {wxStyledTextCtrl, zoomIn, 0}},
+ {3240, {wxStyledTextCtrl, zoomOut, 0}},
+ {3241, {wxStyledTextCtrl, delWordLeft, 0}},
+ {3242, {wxStyledTextCtrl, delWordRight, 0}},
+ {3243, {wxStyledTextCtrl, lineCut, 0}},
+ {3244, {wxStyledTextCtrl, lineDelete, 0}},
+ {3245, {wxStyledTextCtrl, lineTranspose, 0}},
+ {3246, {wxStyledTextCtrl, lineDuplicate, 0}},
+ {3247, {wxStyledTextCtrl, lowerCase, 0}},
+ {3248, {wxStyledTextCtrl, upperCase, 0}},
+ {3249, {wxStyledTextCtrl, lineScrollDown, 0}},
+ {3250, {wxStyledTextCtrl, lineScrollUp, 0}},
+ {3251, {wxStyledTextCtrl, deleteBackNotLine, 0}},
+ {3252, {wxStyledTextCtrl, homeDisplay, 0}},
+ {3253, {wxStyledTextCtrl, homeDisplayExtend, 0}},
+ {3254, {wxStyledTextCtrl, lineEndDisplay, 0}},
+ {3255, {wxStyledTextCtrl, lineEndDisplayExtend, 0}},
+ {3256, {wxStyledTextCtrl, homeWrapExtend, 0}},
+ {3257, {wxStyledTextCtrl, lineEndWrap, 0}},
+ {3258, {wxStyledTextCtrl, lineEndWrapExtend, 0}},
+ {3259, {wxStyledTextCtrl, vCHomeWrap, 0}},
+ {3260, {wxStyledTextCtrl, vCHomeWrapExtend, 0}},
+ {3261, {wxStyledTextCtrl, lineCopy, 0}},
+ {3262, {wxStyledTextCtrl, moveCaretInsideView, 0}},
+ {3263, {wxStyledTextCtrl, lineLength, 1}},
+ {3264, {wxStyledTextCtrl, braceHighlight, 2}},
+ {3265, {wxStyledTextCtrl, braceBadLight, 1}},
+ {3266, {wxStyledTextCtrl, braceMatch, 1}},
+ {3267, {wxStyledTextCtrl, getViewEOL, 0}},
+ {3268, {wxStyledTextCtrl, setViewEOL, 1}},
+ {3269, {wxStyledTextCtrl, setModEventMask, 1}},
+ {3270, {wxStyledTextCtrl, getEdgeColumn, 0}},
+ {3271, {wxStyledTextCtrl, setEdgeColumn, 1}},
+ {3272, {wxStyledTextCtrl, getEdgeMode, 0}},
+ {3273, {wxStyledTextCtrl, getEdgeColour, 0}},
+ {3274, {wxStyledTextCtrl, setEdgeColour, 1}},
+ {3275, {wxStyledTextCtrl, searchAnchor, 0}},
+ {3276, {wxStyledTextCtrl, searchNext, 2}},
+ {3277, {wxStyledTextCtrl, searchPrev, 2}},
+ {3278, {wxStyledTextCtrl, linesOnScreen, 0}},
+ {3279, {wxStyledTextCtrl, usePopUp, 1}},
+ {3280, {wxStyledTextCtrl, selectionIsRectangle, 0}},
+ {3281, {wxStyledTextCtrl, setZoom, 1}},
+ {3282, {wxStyledTextCtrl, getZoom, 0}},
+ {3283, {wxStyledTextCtrl, getModEventMask, 0}},
+ {3284, {wxStyledTextCtrl, setSTCFocus, 1}},
+ {3285, {wxStyledTextCtrl, getSTCFocus, 0}},
+ {3286, {wxStyledTextCtrl, setStatus, 1}},
+ {3287, {wxStyledTextCtrl, getStatus, 0}},
+ {3288, {wxStyledTextCtrl, setMouseDownCaptures, 1}},
+ {3289, {wxStyledTextCtrl, getMouseDownCaptures, 0}},
+ {3290, {wxStyledTextCtrl, setSTCCursor, 1}},
+ {3291, {wxStyledTextCtrl, getSTCCursor, 0}},
+ {3292, {wxStyledTextCtrl, setControlCharSymbol, 1}},
+ {3293, {wxStyledTextCtrl, getControlCharSymbol, 0}},
+ {3294, {wxStyledTextCtrl, wordPartLeft, 0}},
+ {3295, {wxStyledTextCtrl, wordPartLeftExtend, 0}},
+ {3296, {wxStyledTextCtrl, wordPartRight, 0}},
+ {3297, {wxStyledTextCtrl, wordPartRightExtend, 0}},
+ {3298, {wxStyledTextCtrl, setVisiblePolicy, 2}},
+ {3299, {wxStyledTextCtrl, delLineLeft, 0}},
+ {3300, {wxStyledTextCtrl, delLineRight, 0}},
+ {3301, {wxStyledTextCtrl, getXOffset, 0}},
+ {3302, {wxStyledTextCtrl, chooseCaretX, 0}},
+ {3303, {wxStyledTextCtrl, setXCaretPolicy, 2}},
+ {3304, {wxStyledTextCtrl, setYCaretPolicy, 2}},
+ {3305, {wxStyledTextCtrl, getPrintWrapMode, 0}},
+ {3306, {wxStyledTextCtrl, setHotspotActiveForeground, 2}},
+ {3307, {wxStyledTextCtrl, setHotspotActiveBackground, 2}},
+ {3308, {wxStyledTextCtrl, setHotspotActiveUnderline, 1}},
+ {3309, {wxStyledTextCtrl, setHotspotSingleLine, 1}},
+ {3310, {wxStyledTextCtrl, paraDownExtend, 0}},
+ {3311, {wxStyledTextCtrl, paraUp, 0}},
+ {3312, {wxStyledTextCtrl, paraUpExtend, 0}},
+ {3313, {wxStyledTextCtrl, positionBefore, 1}},
+ {3314, {wxStyledTextCtrl, positionAfter, 1}},
+ {3315, {wxStyledTextCtrl, copyRange, 2}},
+ {3316, {wxStyledTextCtrl, copyText, 2}},
+ {3317, {wxStyledTextCtrl, setSelectionMode, 1}},
+ {3318, {wxStyledTextCtrl, getSelectionMode, 0}},
+ {3319, {wxStyledTextCtrl, lineDownRectExtend, 0}},
+ {3320, {wxStyledTextCtrl, lineUpRectExtend, 0}},
+ {3321, {wxStyledTextCtrl, charLeftRectExtend, 0}},
+ {3322, {wxStyledTextCtrl, charRightRectExtend, 0}},
+ {3323, {wxStyledTextCtrl, homeRectExtend, 0}},
+ {3324, {wxStyledTextCtrl, vCHomeRectExtend, 0}},
+ {3325, {wxStyledTextCtrl, lineEndRectExtend, 0}},
+ {3326, {wxStyledTextCtrl, pageUpRectExtend, 0}},
+ {3327, {wxStyledTextCtrl, pageDownRectExtend, 0}},
+ {3328, {wxStyledTextCtrl, stutteredPageUp, 0}},
+ {3329, {wxStyledTextCtrl, stutteredPageUpExtend, 0}},
+ {3330, {wxStyledTextCtrl, stutteredPageDown, 0}},
+ {3331, {wxStyledTextCtrl, stutteredPageDownExtend, 0}},
+ {3332, {wxStyledTextCtrl, wordLeftEnd, 0}},
+ {3333, {wxStyledTextCtrl, wordLeftEndExtend, 0}},
+ {3334, {wxStyledTextCtrl, wordRightEnd, 0}},
+ {3335, {wxStyledTextCtrl, wordRightEndExtend, 0}},
+ {3336, {wxStyledTextCtrl, setWhitespaceChars, 1}},
+ {3337, {wxStyledTextCtrl, setCharsDefault, 0}},
+ {3338, {wxStyledTextCtrl, autoCompGetCurrent, 0}},
+ {3339, {wxStyledTextCtrl, allocate, 1}},
+ {3340, {wxStyledTextCtrl, findColumn, 2}},
+ {3341, {wxStyledTextCtrl, getCaretSticky, 0}},
+ {3342, {wxStyledTextCtrl, setCaretSticky, 1}},
+ {3343, {wxStyledTextCtrl, toggleCaretSticky, 0}},
+ {3344, {wxStyledTextCtrl, setPasteConvertEndings, 1}},
+ {3345, {wxStyledTextCtrl, getPasteConvertEndings, 0}},
+ {3346, {wxStyledTextCtrl, selectionDuplicate, 0}},
+ {3347, {wxStyledTextCtrl, setCaretLineBackAlpha, 1}},
+ {3348, {wxStyledTextCtrl, getCaretLineBackAlpha, 0}},
+ {3349, {wxStyledTextCtrl, startRecord, 0}},
+ {3350, {wxStyledTextCtrl, stopRecord, 0}},
+ {3351, {wxStyledTextCtrl, setLexer, 1}},
+ {3352, {wxStyledTextCtrl, getLexer, 0}},
+ {3353, {wxStyledTextCtrl, colourise, 2}},
+ {3354, {wxStyledTextCtrl, setProperty, 2}},
+ {3355, {wxStyledTextCtrl, setKeyWords, 2}},
+ {3356, {wxStyledTextCtrl, setLexerLanguage, 1}},
+ {3357, {wxStyledTextCtrl, getProperty, 1}},
+ {3358, {wxStyledTextCtrl, getStyleBitsNeeded, 0}},
+ {3359, {wxStyledTextCtrl, getCurrentLine, 0}},
+ {3360, {wxStyledTextCtrl, styleSetSpec, 2}},
+ {3361, {wxStyledTextCtrl, styleSetFont, 2}},
+ {3362, {wxStyledTextCtrl, styleSetFontAttr, 7}},
+ {3363, {wxStyledTextCtrl, styleSetCharacterSet, 2}},
+ {3364, {wxStyledTextCtrl, styleSetFontEncoding, 2}},
+ {3365, {wxStyledTextCtrl, cmdKeyExecute, 1}},
+ {3366, {wxStyledTextCtrl, setMargins, 2}},
+ {3367, {wxStyledTextCtrl, getSelection, 2}},
+ {3368, {wxStyledTextCtrl, pointFromPosition, 1}},
+ {3369, {wxStyledTextCtrl, scrollToLine, 1}},
+ {3370, {wxStyledTextCtrl, scrollToColumn, 1}},
+ {3371, {wxStyledTextCtrl, sendMsg, 2}},
+ {3372, {wxStyledTextCtrl, setVScrollBar, 1}},
+ {3373, {wxStyledTextCtrl, setHScrollBar, 1}},
+ {3374, {wxStyledTextCtrl, getLastKeydownProcessed, 0}},
+ {3375, {wxStyledTextCtrl, setLastKeydownProcessed, 1}},
+ {3376, {wxStyledTextCtrl, saveFile, 1}},
+ {3377, {wxStyledTextCtrl, loadFile, 1}},
+ {3378, {wxStyledTextCtrl, doDragOver, 3}},
+ {3379, {wxStyledTextCtrl, doDropText, 3}},
+ {3380, {wxStyledTextCtrl, getUseAntiAliasing, 0}},
+ {3381, {wxStyledTextCtrl, addTextRaw, 1}},
+ {3382, {wxStyledTextCtrl, insertTextRaw, 2}},
+ {3383, {wxStyledTextCtrl, getCurLineRaw, 1}},
+ {3384, {wxStyledTextCtrl, getLineRaw, 1}},
+ {3385, {wxStyledTextCtrl, getSelectedTextRaw, 0}},
+ {3386, {wxStyledTextCtrl, getTextRangeRaw, 2}},
+ {3387, {wxStyledTextCtrl, setTextRaw, 1}},
+ {3388, {wxStyledTextCtrl, getTextRaw, 0}},
+ {3389, {wxStyledTextCtrl, appendTextRaw, 1}},
+ {3390, {wxArtProvider, getBitmap, 2}},
+ {3391, {wxArtProvider, getIcon, 2}},
+ {3392, {wxTreeEvent, getKeyCode, 0}},
+ {3393, {wxTreeEvent, getItem, 0}},
+ {3394, {wxTreeEvent, getKeyEvent, 0}},
+ {3395, {wxTreeEvent, getLabel, 0}},
+ {3396, {wxTreeEvent, getOldItem, 0}},
+ {3397, {wxTreeEvent, getPoint, 0}},
+ {3398, {wxTreeEvent, isEditCancelled, 0}},
+ {3399, {wxTreeEvent, setToolTip, 1}},
+ {3400, {wxNotebookEvent, getOldSelection, 0}},
+ {3401, {wxNotebookEvent, getSelection, 0}},
+ {3402, {wxNotebookEvent, setOldSelection, 1}},
+ {3403, {wxNotebookEvent, setSelection, 1}},
+ {3404, {wxFileDataObject, new, 0}},
+ {3405, {wxFileDataObject, addFile, 1}},
+ {3406, {wxFileDataObject, getFilenames, 0}},
+ {3407, {wxFileDataObject, 'Destroy', undefined}},
+ {3408, {wxTextDataObject, new, 1}},
+ {3409, {wxTextDataObject, getTextLength, 0}},
+ {3410, {wxTextDataObject, getText, 0}},
+ {3411, {wxTextDataObject, setText, 1}},
+ {3412, {wxTextDataObject, 'Destroy', undefined}},
+ {3413, {wxBitmapDataObject, new_1_1, 1}},
+ {3414, {wxBitmapDataObject, new_1_0, 1}},
+ {3415, {wxBitmapDataObject, getBitmap, 0}},
+ {3416, {wxBitmapDataObject, setBitmap, 1}},
+ {3417, {wxBitmapDataObject, 'Destroy', undefined}},
+ {3419, {wxClipboard, new, 0}},
+ {3420, {wxClipboard, destruct, 0}},
+ {3421, {wxClipboard, addData, 1}},
+ {3422, {wxClipboard, clear, 0}},
+ {3423, {wxClipboard, close, 0}},
+ {3424, {wxClipboard, flush, 0}},
+ {3425, {wxClipboard, getData, 1}},
+ {3426, {wxClipboard, isOpened, 0}},
+ {3427, {wxClipboard, open, 0}},
+ {3428, {wxClipboard, setData, 1}},
+ {3430, {wxClipboard, usePrimarySelection, 1}},
+ {3431, {wxClipboard, isSupported, 1}},
+ {3432, {wxClipboard, get, 0}},
+ {3433, {wxSpinEvent, getPosition, 0}},
+ {3434, {wxSpinEvent, setPosition, 1}},
+ {3435, {wxSplitterWindow, new_0, 0}},
+ {3436, {wxSplitterWindow, new_2, 2}},
+ {3437, {wxSplitterWindow, destruct, 0}},
+ {3438, {wxSplitterWindow, create, 2}},
+ {3439, {wxSplitterWindow, getMinimumPaneSize, 0}},
+ {3440, {wxSplitterWindow, getSashGravity, 0}},
+ {3441, {wxSplitterWindow, getSashPosition, 0}},
+ {3442, {wxSplitterWindow, getSplitMode, 0}},
+ {3443, {wxSplitterWindow, getWindow1, 0}},
+ {3444, {wxSplitterWindow, getWindow2, 0}},
+ {3445, {wxSplitterWindow, initialize, 1}},
+ {3446, {wxSplitterWindow, isSplit, 0}},
+ {3447, {wxSplitterWindow, replaceWindow, 2}},
+ {3448, {wxSplitterWindow, setSashGravity, 1}},
+ {3449, {wxSplitterWindow, setSashPosition, 2}},
+ {3450, {wxSplitterWindow, setSashSize, 1}},
+ {3451, {wxSplitterWindow, setMinimumPaneSize, 1}},
+ {3452, {wxSplitterWindow, setSplitMode, 1}},
+ {3453, {wxSplitterWindow, splitHorizontally, 3}},
+ {3454, {wxSplitterWindow, splitVertically, 3}},
+ {3455, {wxSplitterWindow, unsplit, 1}},
+ {3456, {wxSplitterWindow, updateSize, 0}},
+ {3457, {wxSplitterEvent, getSashPosition, 0}},
+ {3458, {wxSplitterEvent, getX, 0}},
+ {3459, {wxSplitterEvent, getY, 0}},
+ {3460, {wxSplitterEvent, getWindowBeingRemoved, 0}},
+ {3461, {wxSplitterEvent, setSashPosition, 1}},
+ {3462, {wxHtmlWindow, new_0, 0}},
+ {3463, {wxHtmlWindow, new_2, 2}},
+ {3464, {wxHtmlWindow, appendToPage, 1}},
+ {3465, {wxHtmlWindow, getOpenedAnchor, 0}},
+ {3466, {wxHtmlWindow, getOpenedPage, 0}},
+ {3467, {wxHtmlWindow, getOpenedPageTitle, 0}},
+ {3468, {wxHtmlWindow, getRelatedFrame, 0}},
+ {3469, {wxHtmlWindow, historyBack, 0}},
+ {3470, {wxHtmlWindow, historyCanBack, 0}},
+ {3471, {wxHtmlWindow, historyCanForward, 0}},
+ {3472, {wxHtmlWindow, historyClear, 0}},
+ {3473, {wxHtmlWindow, historyForward, 0}},
+ {3474, {wxHtmlWindow, loadFile, 1}},
+ {3475, {wxHtmlWindow, loadPage, 1}},
+ {3476, {wxHtmlWindow, selectAll, 0}},
+ {3477, {wxHtmlWindow, selectionToText, 0}},
+ {3478, {wxHtmlWindow, selectLine, 1}},
+ {3479, {wxHtmlWindow, selectWord, 1}},
+ {3480, {wxHtmlWindow, setBorders, 1}},
+ {3481, {wxHtmlWindow, setFonts, 3}},
+ {3482, {wxHtmlWindow, setPage, 1}},
+ {3483, {wxHtmlWindow, setRelatedFrame, 2}},
+ {3484, {wxHtmlWindow, setRelatedStatusBar, 1}},
+ {3485, {wxHtmlWindow, toText, 0}},
+ {3486, {wxHtmlWindow, 'Destroy', undefined}},
+ {3487, {wxHtmlLinkEvent, getLinkInfo, 0}},
+ {3488, {wxSystemSettings, getColour, 1}},
+ {3489, {wxSystemSettings, getFont, 1}},
+ {3490, {wxSystemSettings, getMetric, 2}},
+ {3491, {wxSystemSettings, getScreenType, 0}},
+ {3492, {wxAuiNotebookEvent, setSelection, 1}},
+ {3493, {wxAuiNotebookEvent, getSelection, 0}},
+ {3494, {wxAuiNotebookEvent, setOldSelection, 1}},
+ {3495, {wxAuiNotebookEvent, getOldSelection, 0}},
+ {3496, {wxAuiNotebookEvent, setDragSource, 1}},
+ {3497, {wxAuiNotebookEvent, getDragSource, 0}},
+ {3498, {wxAuiManagerEvent, setManager, 1}},
+ {3499, {wxAuiManagerEvent, getManager, 0}},
+ {3500, {wxAuiManagerEvent, setPane, 1}},
+ {3501, {wxAuiManagerEvent, getPane, 0}},
+ {3502, {wxAuiManagerEvent, setButton, 1}},
+ {3503, {wxAuiManagerEvent, getButton, 0}},
+ {3504, {wxAuiManagerEvent, setDC, 1}},
+ {3505, {wxAuiManagerEvent, getDC, 0}},
+ {3506, {wxAuiManagerEvent, veto, 1}},
+ {3507, {wxAuiManagerEvent, getVeto, 0}},
+ {3508, {wxAuiManagerEvent, setCanVeto, 1}},
+ {3509, {wxAuiManagerEvent, canVeto, 0}},
+ {3510, {wxLogNull, new, 0}},
+ {3511, {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 cf672644c6..af74caaa25 100644
--- a/lib/wx/src/gen/wxe_funcs.hrl
+++ b/lib/wx/src/gen/wxe_funcs.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1600,1681 +1600,1693 @@
-define(wxListItem_SetText, 1754).
-define(wxListItem_SetTextColour, 1755).
-define(wxListItem_SetWidth, 1756).
--define(wxImageList_new_0, 1757).
--define(wxImageList_new_3, 1758).
--define(wxImageList_Add_1, 1759).
--define(wxImageList_Add_2_0, 1760).
--define(wxImageList_Add_2_1, 1761).
--define(wxImageList_Create, 1762).
--define(wxImageList_Draw, 1764).
--define(wxImageList_GetBitmap, 1765).
--define(wxImageList_GetIcon, 1766).
--define(wxImageList_GetImageCount, 1767).
--define(wxImageList_GetSize, 1768).
--define(wxImageList_Remove, 1769).
--define(wxImageList_RemoveAll, 1770).
--define(wxImageList_Replace_2, 1771).
--define(wxImageList_Replace_3, 1772).
--define(wxImageList_destroy, 1773).
--define(wxTextAttr_new_0, 1774).
--define(wxTextAttr_new_2, 1775).
--define(wxTextAttr_GetAlignment, 1776).
--define(wxTextAttr_GetBackgroundColour, 1777).
--define(wxTextAttr_GetFont, 1778).
--define(wxTextAttr_GetLeftIndent, 1779).
--define(wxTextAttr_GetLeftSubIndent, 1780).
--define(wxTextAttr_GetRightIndent, 1781).
--define(wxTextAttr_GetTabs, 1782).
--define(wxTextAttr_GetTextColour, 1783).
--define(wxTextAttr_HasBackgroundColour, 1784).
--define(wxTextAttr_HasFont, 1785).
--define(wxTextAttr_HasTextColour, 1786).
--define(wxTextAttr_GetFlags, 1787).
--define(wxTextAttr_IsDefault, 1788).
--define(wxTextAttr_SetAlignment, 1789).
--define(wxTextAttr_SetBackgroundColour, 1790).
--define(wxTextAttr_SetFlags, 1791).
--define(wxTextAttr_SetFont, 1792).
--define(wxTextAttr_SetLeftIndent, 1793).
--define(wxTextAttr_SetRightIndent, 1794).
--define(wxTextAttr_SetTabs, 1795).
--define(wxTextAttr_SetTextColour, 1796).
--define(wxTextAttr_destroy, 1797).
--define(wxTextCtrl_new_3, 1799).
--define(wxTextCtrl_new_0, 1800).
--define(wxTextCtrl_destruct, 1802).
--define(wxTextCtrl_AppendText, 1803).
--define(wxTextCtrl_CanCopy, 1804).
--define(wxTextCtrl_CanCut, 1805).
--define(wxTextCtrl_CanPaste, 1806).
--define(wxTextCtrl_CanRedo, 1807).
--define(wxTextCtrl_CanUndo, 1808).
--define(wxTextCtrl_Clear, 1809).
--define(wxTextCtrl_Copy, 1810).
--define(wxTextCtrl_Create, 1811).
--define(wxTextCtrl_Cut, 1812).
--define(wxTextCtrl_DiscardEdits, 1813).
--define(wxTextCtrl_EmulateKeyPress, 1814).
--define(wxTextCtrl_GetDefaultStyle, 1815).
--define(wxTextCtrl_GetInsertionPoint, 1816).
--define(wxTextCtrl_GetLastPosition, 1817).
--define(wxTextCtrl_GetLineLength, 1818).
--define(wxTextCtrl_GetLineText, 1819).
--define(wxTextCtrl_GetNumberOfLines, 1820).
--define(wxTextCtrl_GetRange, 1821).
--define(wxTextCtrl_GetSelection, 1822).
--define(wxTextCtrl_GetStringSelection, 1823).
--define(wxTextCtrl_GetStyle, 1824).
--define(wxTextCtrl_GetValue, 1825).
--define(wxTextCtrl_IsEditable, 1826).
--define(wxTextCtrl_IsModified, 1827).
--define(wxTextCtrl_IsMultiLine, 1828).
--define(wxTextCtrl_IsSingleLine, 1829).
--define(wxTextCtrl_LoadFile, 1830).
--define(wxTextCtrl_MarkDirty, 1831).
--define(wxTextCtrl_Paste, 1832).
--define(wxTextCtrl_PositionToXY, 1833).
--define(wxTextCtrl_Redo, 1834).
--define(wxTextCtrl_Remove, 1835).
--define(wxTextCtrl_Replace, 1836).
--define(wxTextCtrl_SaveFile, 1837).
--define(wxTextCtrl_SetDefaultStyle, 1838).
--define(wxTextCtrl_SetEditable, 1839).
--define(wxTextCtrl_SetInsertionPoint, 1840).
--define(wxTextCtrl_SetInsertionPointEnd, 1841).
--define(wxTextCtrl_SetMaxLength, 1843).
--define(wxTextCtrl_SetSelection, 1844).
--define(wxTextCtrl_SetStyle, 1845).
--define(wxTextCtrl_SetValue, 1846).
--define(wxTextCtrl_ShowPosition, 1847).
--define(wxTextCtrl_Undo, 1848).
--define(wxTextCtrl_WriteText, 1849).
--define(wxTextCtrl_XYToPosition, 1850).
--define(wxNotebook_new_0, 1853).
--define(wxNotebook_new_3, 1854).
--define(wxNotebook_destruct, 1855).
--define(wxNotebook_AddPage, 1856).
--define(wxNotebook_AdvanceSelection, 1857).
--define(wxNotebook_AssignImageList, 1858).
--define(wxNotebook_Create, 1859).
--define(wxNotebook_DeleteAllPages, 1860).
--define(wxNotebook_DeletePage, 1861).
--define(wxNotebook_RemovePage, 1862).
--define(wxNotebook_GetCurrentPage, 1863).
--define(wxNotebook_GetImageList, 1864).
--define(wxNotebook_GetPage, 1866).
--define(wxNotebook_GetPageCount, 1867).
--define(wxNotebook_GetPageImage, 1868).
--define(wxNotebook_GetPageText, 1869).
--define(wxNotebook_GetRowCount, 1870).
--define(wxNotebook_GetSelection, 1871).
--define(wxNotebook_GetThemeBackgroundColour, 1872).
--define(wxNotebook_HitTest, 1874).
--define(wxNotebook_InsertPage, 1876).
--define(wxNotebook_SetImageList, 1877).
--define(wxNotebook_SetPadding, 1878).
--define(wxNotebook_SetPageSize, 1879).
--define(wxNotebook_SetPageImage, 1880).
--define(wxNotebook_SetPageText, 1881).
--define(wxNotebook_SetSelection, 1882).
--define(wxNotebook_ChangeSelection, 1883).
--define(wxChoicebook_new_0, 1884).
--define(wxChoicebook_new_3, 1885).
--define(wxChoicebook_AddPage, 1886).
--define(wxChoicebook_AdvanceSelection, 1887).
--define(wxChoicebook_AssignImageList, 1888).
--define(wxChoicebook_Create, 1889).
--define(wxChoicebook_DeleteAllPages, 1890).
--define(wxChoicebook_DeletePage, 1891).
--define(wxChoicebook_RemovePage, 1892).
--define(wxChoicebook_GetCurrentPage, 1893).
--define(wxChoicebook_GetImageList, 1894).
--define(wxChoicebook_GetPage, 1896).
--define(wxChoicebook_GetPageCount, 1897).
--define(wxChoicebook_GetPageImage, 1898).
--define(wxChoicebook_GetPageText, 1899).
--define(wxChoicebook_GetSelection, 1900).
--define(wxChoicebook_HitTest, 1901).
--define(wxChoicebook_InsertPage, 1902).
--define(wxChoicebook_SetImageList, 1903).
--define(wxChoicebook_SetPageSize, 1904).
--define(wxChoicebook_SetPageImage, 1905).
--define(wxChoicebook_SetPageText, 1906).
--define(wxChoicebook_SetSelection, 1907).
--define(wxChoicebook_ChangeSelection, 1908).
--define(wxChoicebook_destroy, 1909).
--define(wxToolbook_new_0, 1910).
--define(wxToolbook_new_3, 1911).
--define(wxToolbook_AddPage, 1912).
--define(wxToolbook_AdvanceSelection, 1913).
--define(wxToolbook_AssignImageList, 1914).
--define(wxToolbook_Create, 1915).
--define(wxToolbook_DeleteAllPages, 1916).
--define(wxToolbook_DeletePage, 1917).
--define(wxToolbook_RemovePage, 1918).
--define(wxToolbook_GetCurrentPage, 1919).
--define(wxToolbook_GetImageList, 1920).
--define(wxToolbook_GetPage, 1922).
--define(wxToolbook_GetPageCount, 1923).
--define(wxToolbook_GetPageImage, 1924).
--define(wxToolbook_GetPageText, 1925).
--define(wxToolbook_GetSelection, 1926).
--define(wxToolbook_HitTest, 1928).
--define(wxToolbook_InsertPage, 1929).
--define(wxToolbook_SetImageList, 1930).
--define(wxToolbook_SetPageSize, 1931).
--define(wxToolbook_SetPageImage, 1932).
--define(wxToolbook_SetPageText, 1933).
--define(wxToolbook_SetSelection, 1934).
--define(wxToolbook_ChangeSelection, 1935).
--define(wxToolbook_destroy, 1936).
--define(wxListbook_new_0, 1937).
--define(wxListbook_new_3, 1938).
--define(wxListbook_AddPage, 1939).
--define(wxListbook_AdvanceSelection, 1940).
--define(wxListbook_AssignImageList, 1941).
--define(wxListbook_Create, 1942).
--define(wxListbook_DeleteAllPages, 1943).
--define(wxListbook_DeletePage, 1944).
--define(wxListbook_RemovePage, 1945).
--define(wxListbook_GetCurrentPage, 1946).
--define(wxListbook_GetImageList, 1947).
--define(wxListbook_GetPage, 1949).
--define(wxListbook_GetPageCount, 1950).
--define(wxListbook_GetPageImage, 1951).
--define(wxListbook_GetPageText, 1952).
--define(wxListbook_GetSelection, 1953).
--define(wxListbook_HitTest, 1955).
--define(wxListbook_InsertPage, 1956).
--define(wxListbook_SetImageList, 1957).
--define(wxListbook_SetPageSize, 1958).
--define(wxListbook_SetPageImage, 1959).
--define(wxListbook_SetPageText, 1960).
--define(wxListbook_SetSelection, 1961).
--define(wxListbook_ChangeSelection, 1962).
--define(wxListbook_destroy, 1963).
--define(wxTreebook_new_0, 1964).
--define(wxTreebook_new_3, 1965).
--define(wxTreebook_AddPage, 1966).
--define(wxTreebook_AdvanceSelection, 1967).
--define(wxTreebook_AssignImageList, 1968).
--define(wxTreebook_Create, 1969).
--define(wxTreebook_DeleteAllPages, 1970).
--define(wxTreebook_DeletePage, 1971).
--define(wxTreebook_RemovePage, 1972).
--define(wxTreebook_GetCurrentPage, 1973).
--define(wxTreebook_GetImageList, 1974).
--define(wxTreebook_GetPage, 1976).
--define(wxTreebook_GetPageCount, 1977).
--define(wxTreebook_GetPageImage, 1978).
--define(wxTreebook_GetPageText, 1979).
--define(wxTreebook_GetSelection, 1980).
--define(wxTreebook_ExpandNode, 1981).
--define(wxTreebook_IsNodeExpanded, 1982).
--define(wxTreebook_HitTest, 1984).
--define(wxTreebook_InsertPage, 1985).
--define(wxTreebook_InsertSubPage, 1986).
--define(wxTreebook_SetImageList, 1987).
--define(wxTreebook_SetPageSize, 1988).
--define(wxTreebook_SetPageImage, 1989).
--define(wxTreebook_SetPageText, 1990).
--define(wxTreebook_SetSelection, 1991).
--define(wxTreebook_ChangeSelection, 1992).
--define(wxTreebook_destroy, 1993).
--define(wxTreeCtrl_new_2, 1996).
--define(wxTreeCtrl_new_0, 1997).
--define(wxTreeCtrl_destruct, 1999).
--define(wxTreeCtrl_AddRoot, 2000).
--define(wxTreeCtrl_AppendItem, 2001).
--define(wxTreeCtrl_AssignImageList, 2002).
--define(wxTreeCtrl_AssignStateImageList, 2003).
--define(wxTreeCtrl_Collapse, 2004).
--define(wxTreeCtrl_CollapseAndReset, 2005).
--define(wxTreeCtrl_Create, 2006).
--define(wxTreeCtrl_Delete, 2007).
--define(wxTreeCtrl_DeleteAllItems, 2008).
--define(wxTreeCtrl_DeleteChildren, 2009).
--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).
+-define(wxListItemAttr_new_0, 1757).
+-define(wxListItemAttr_new_3, 1758).
+-define(wxListItemAttr_GetBackgroundColour, 1759).
+-define(wxListItemAttr_GetFont, 1760).
+-define(wxListItemAttr_GetTextColour, 1761).
+-define(wxListItemAttr_HasBackgroundColour, 1762).
+-define(wxListItemAttr_HasFont, 1763).
+-define(wxListItemAttr_HasTextColour, 1764).
+-define(wxListItemAttr_SetBackgroundColour, 1765).
+-define(wxListItemAttr_SetFont, 1766).
+-define(wxListItemAttr_SetTextColour, 1767).
+-define(wxListItemAttr_destroy, 1768).
+-define(wxImageList_new_0, 1769).
+-define(wxImageList_new_3, 1770).
+-define(wxImageList_Add_1, 1771).
+-define(wxImageList_Add_2_0, 1772).
+-define(wxImageList_Add_2_1, 1773).
+-define(wxImageList_Create, 1774).
+-define(wxImageList_Draw, 1776).
+-define(wxImageList_GetBitmap, 1777).
+-define(wxImageList_GetIcon, 1778).
+-define(wxImageList_GetImageCount, 1779).
+-define(wxImageList_GetSize, 1780).
+-define(wxImageList_Remove, 1781).
+-define(wxImageList_RemoveAll, 1782).
+-define(wxImageList_Replace_2, 1783).
+-define(wxImageList_Replace_3, 1784).
+-define(wxImageList_destroy, 1785).
+-define(wxTextAttr_new_0, 1786).
+-define(wxTextAttr_new_2, 1787).
+-define(wxTextAttr_GetAlignment, 1788).
+-define(wxTextAttr_GetBackgroundColour, 1789).
+-define(wxTextAttr_GetFont, 1790).
+-define(wxTextAttr_GetLeftIndent, 1791).
+-define(wxTextAttr_GetLeftSubIndent, 1792).
+-define(wxTextAttr_GetRightIndent, 1793).
+-define(wxTextAttr_GetTabs, 1794).
+-define(wxTextAttr_GetTextColour, 1795).
+-define(wxTextAttr_HasBackgroundColour, 1796).
+-define(wxTextAttr_HasFont, 1797).
+-define(wxTextAttr_HasTextColour, 1798).
+-define(wxTextAttr_GetFlags, 1799).
+-define(wxTextAttr_IsDefault, 1800).
+-define(wxTextAttr_SetAlignment, 1801).
+-define(wxTextAttr_SetBackgroundColour, 1802).
+-define(wxTextAttr_SetFlags, 1803).
+-define(wxTextAttr_SetFont, 1804).
+-define(wxTextAttr_SetLeftIndent, 1805).
+-define(wxTextAttr_SetRightIndent, 1806).
+-define(wxTextAttr_SetTabs, 1807).
+-define(wxTextAttr_SetTextColour, 1808).
+-define(wxTextAttr_destroy, 1809).
+-define(wxTextCtrl_new_3, 1811).
+-define(wxTextCtrl_new_0, 1812).
+-define(wxTextCtrl_destruct, 1814).
+-define(wxTextCtrl_AppendText, 1815).
+-define(wxTextCtrl_CanCopy, 1816).
+-define(wxTextCtrl_CanCut, 1817).
+-define(wxTextCtrl_CanPaste, 1818).
+-define(wxTextCtrl_CanRedo, 1819).
+-define(wxTextCtrl_CanUndo, 1820).
+-define(wxTextCtrl_Clear, 1821).
+-define(wxTextCtrl_Copy, 1822).
+-define(wxTextCtrl_Create, 1823).
+-define(wxTextCtrl_Cut, 1824).
+-define(wxTextCtrl_DiscardEdits, 1825).
+-define(wxTextCtrl_EmulateKeyPress, 1826).
+-define(wxTextCtrl_GetDefaultStyle, 1827).
+-define(wxTextCtrl_GetInsertionPoint, 1828).
+-define(wxTextCtrl_GetLastPosition, 1829).
+-define(wxTextCtrl_GetLineLength, 1830).
+-define(wxTextCtrl_GetLineText, 1831).
+-define(wxTextCtrl_GetNumberOfLines, 1832).
+-define(wxTextCtrl_GetRange, 1833).
+-define(wxTextCtrl_GetSelection, 1834).
+-define(wxTextCtrl_GetStringSelection, 1835).
+-define(wxTextCtrl_GetStyle, 1836).
+-define(wxTextCtrl_GetValue, 1837).
+-define(wxTextCtrl_IsEditable, 1838).
+-define(wxTextCtrl_IsModified, 1839).
+-define(wxTextCtrl_IsMultiLine, 1840).
+-define(wxTextCtrl_IsSingleLine, 1841).
+-define(wxTextCtrl_LoadFile, 1842).
+-define(wxTextCtrl_MarkDirty, 1843).
+-define(wxTextCtrl_Paste, 1844).
+-define(wxTextCtrl_PositionToXY, 1845).
+-define(wxTextCtrl_Redo, 1846).
+-define(wxTextCtrl_Remove, 1847).
+-define(wxTextCtrl_Replace, 1848).
+-define(wxTextCtrl_SaveFile, 1849).
+-define(wxTextCtrl_SetDefaultStyle, 1850).
+-define(wxTextCtrl_SetEditable, 1851).
+-define(wxTextCtrl_SetInsertionPoint, 1852).
+-define(wxTextCtrl_SetInsertionPointEnd, 1853).
+-define(wxTextCtrl_SetMaxLength, 1855).
+-define(wxTextCtrl_SetSelection, 1856).
+-define(wxTextCtrl_SetStyle, 1857).
+-define(wxTextCtrl_SetValue, 1858).
+-define(wxTextCtrl_ShowPosition, 1859).
+-define(wxTextCtrl_Undo, 1860).
+-define(wxTextCtrl_WriteText, 1861).
+-define(wxTextCtrl_XYToPosition, 1862).
+-define(wxNotebook_new_0, 1865).
+-define(wxNotebook_new_3, 1866).
+-define(wxNotebook_destruct, 1867).
+-define(wxNotebook_AddPage, 1868).
+-define(wxNotebook_AdvanceSelection, 1869).
+-define(wxNotebook_AssignImageList, 1870).
+-define(wxNotebook_Create, 1871).
+-define(wxNotebook_DeleteAllPages, 1872).
+-define(wxNotebook_DeletePage, 1873).
+-define(wxNotebook_RemovePage, 1874).
+-define(wxNotebook_GetCurrentPage, 1875).
+-define(wxNotebook_GetImageList, 1876).
+-define(wxNotebook_GetPage, 1878).
+-define(wxNotebook_GetPageCount, 1879).
+-define(wxNotebook_GetPageImage, 1880).
+-define(wxNotebook_GetPageText, 1881).
+-define(wxNotebook_GetRowCount, 1882).
+-define(wxNotebook_GetSelection, 1883).
+-define(wxNotebook_GetThemeBackgroundColour, 1884).
+-define(wxNotebook_HitTest, 1886).
+-define(wxNotebook_InsertPage, 1888).
+-define(wxNotebook_SetImageList, 1889).
+-define(wxNotebook_SetPadding, 1890).
+-define(wxNotebook_SetPageSize, 1891).
+-define(wxNotebook_SetPageImage, 1892).
+-define(wxNotebook_SetPageText, 1893).
+-define(wxNotebook_SetSelection, 1894).
+-define(wxNotebook_ChangeSelection, 1895).
+-define(wxChoicebook_new_0, 1896).
+-define(wxChoicebook_new_3, 1897).
+-define(wxChoicebook_AddPage, 1898).
+-define(wxChoicebook_AdvanceSelection, 1899).
+-define(wxChoicebook_AssignImageList, 1900).
+-define(wxChoicebook_Create, 1901).
+-define(wxChoicebook_DeleteAllPages, 1902).
+-define(wxChoicebook_DeletePage, 1903).
+-define(wxChoicebook_RemovePage, 1904).
+-define(wxChoicebook_GetCurrentPage, 1905).
+-define(wxChoicebook_GetImageList, 1906).
+-define(wxChoicebook_GetPage, 1908).
+-define(wxChoicebook_GetPageCount, 1909).
+-define(wxChoicebook_GetPageImage, 1910).
+-define(wxChoicebook_GetPageText, 1911).
+-define(wxChoicebook_GetSelection, 1912).
+-define(wxChoicebook_HitTest, 1913).
+-define(wxChoicebook_InsertPage, 1914).
+-define(wxChoicebook_SetImageList, 1915).
+-define(wxChoicebook_SetPageSize, 1916).
+-define(wxChoicebook_SetPageImage, 1917).
+-define(wxChoicebook_SetPageText, 1918).
+-define(wxChoicebook_SetSelection, 1919).
+-define(wxChoicebook_ChangeSelection, 1920).
+-define(wxChoicebook_destroy, 1921).
+-define(wxToolbook_new_0, 1922).
+-define(wxToolbook_new_3, 1923).
+-define(wxToolbook_AddPage, 1924).
+-define(wxToolbook_AdvanceSelection, 1925).
+-define(wxToolbook_AssignImageList, 1926).
+-define(wxToolbook_Create, 1927).
+-define(wxToolbook_DeleteAllPages, 1928).
+-define(wxToolbook_DeletePage, 1929).
+-define(wxToolbook_RemovePage, 1930).
+-define(wxToolbook_GetCurrentPage, 1931).
+-define(wxToolbook_GetImageList, 1932).
+-define(wxToolbook_GetPage, 1934).
+-define(wxToolbook_GetPageCount, 1935).
+-define(wxToolbook_GetPageImage, 1936).
+-define(wxToolbook_GetPageText, 1937).
+-define(wxToolbook_GetSelection, 1938).
+-define(wxToolbook_HitTest, 1940).
+-define(wxToolbook_InsertPage, 1941).
+-define(wxToolbook_SetImageList, 1942).
+-define(wxToolbook_SetPageSize, 1943).
+-define(wxToolbook_SetPageImage, 1944).
+-define(wxToolbook_SetPageText, 1945).
+-define(wxToolbook_SetSelection, 1946).
+-define(wxToolbook_ChangeSelection, 1947).
+-define(wxToolbook_destroy, 1948).
+-define(wxListbook_new_0, 1949).
+-define(wxListbook_new_3, 1950).
+-define(wxListbook_AddPage, 1951).
+-define(wxListbook_AdvanceSelection, 1952).
+-define(wxListbook_AssignImageList, 1953).
+-define(wxListbook_Create, 1954).
+-define(wxListbook_DeleteAllPages, 1955).
+-define(wxListbook_DeletePage, 1956).
+-define(wxListbook_RemovePage, 1957).
+-define(wxListbook_GetCurrentPage, 1958).
+-define(wxListbook_GetImageList, 1959).
+-define(wxListbook_GetPage, 1961).
+-define(wxListbook_GetPageCount, 1962).
+-define(wxListbook_GetPageImage, 1963).
+-define(wxListbook_GetPageText, 1964).
+-define(wxListbook_GetSelection, 1965).
+-define(wxListbook_HitTest, 1967).
+-define(wxListbook_InsertPage, 1968).
+-define(wxListbook_SetImageList, 1969).
+-define(wxListbook_SetPageSize, 1970).
+-define(wxListbook_SetPageImage, 1971).
+-define(wxListbook_SetPageText, 1972).
+-define(wxListbook_SetSelection, 1973).
+-define(wxListbook_ChangeSelection, 1974).
+-define(wxListbook_destroy, 1975).
+-define(wxTreebook_new_0, 1976).
+-define(wxTreebook_new_3, 1977).
+-define(wxTreebook_AddPage, 1978).
+-define(wxTreebook_AdvanceSelection, 1979).
+-define(wxTreebook_AssignImageList, 1980).
+-define(wxTreebook_Create, 1981).
+-define(wxTreebook_DeleteAllPages, 1982).
+-define(wxTreebook_DeletePage, 1983).
+-define(wxTreebook_RemovePage, 1984).
+-define(wxTreebook_GetCurrentPage, 1985).
+-define(wxTreebook_GetImageList, 1986).
+-define(wxTreebook_GetPage, 1988).
+-define(wxTreebook_GetPageCount, 1989).
+-define(wxTreebook_GetPageImage, 1990).
+-define(wxTreebook_GetPageText, 1991).
+-define(wxTreebook_GetSelection, 1992).
+-define(wxTreebook_ExpandNode, 1993).
+-define(wxTreebook_IsNodeExpanded, 1994).
+-define(wxTreebook_HitTest, 1996).
+-define(wxTreebook_InsertPage, 1997).
+-define(wxTreebook_InsertSubPage, 1998).
+-define(wxTreebook_SetImageList, 1999).
+-define(wxTreebook_SetPageSize, 2000).
+-define(wxTreebook_SetPageImage, 2001).
+-define(wxTreebook_SetPageText, 2002).
+-define(wxTreebook_SetSelection, 2003).
+-define(wxTreebook_ChangeSelection, 2004).
+-define(wxTreebook_destroy, 2005).
+-define(wxTreeCtrl_new_2, 2008).
+-define(wxTreeCtrl_new_0, 2009).
+-define(wxTreeCtrl_destruct, 2011).
+-define(wxTreeCtrl_AddRoot, 2012).
+-define(wxTreeCtrl_AppendItem, 2013).
+-define(wxTreeCtrl_AssignImageList, 2014).
+-define(wxTreeCtrl_AssignStateImageList, 2015).
+-define(wxTreeCtrl_Collapse, 2016).
+-define(wxTreeCtrl_CollapseAndReset, 2017).
+-define(wxTreeCtrl_Create, 2018).
+-define(wxTreeCtrl_Delete, 2019).
+-define(wxTreeCtrl_DeleteAllItems, 2020).
+-define(wxTreeCtrl_DeleteChildren, 2021).
+-define(wxTreeCtrl_EditLabel, 2022).
+-define(wxTreeCtrl_EnsureVisible, 2023).
+-define(wxTreeCtrl_Expand, 2024).
+-define(wxTreeCtrl_GetBoundingRect, 2025).
+-define(wxTreeCtrl_GetChildrenCount, 2027).
+-define(wxTreeCtrl_GetCount, 2028).
+-define(wxTreeCtrl_GetEditControl, 2029).
+-define(wxTreeCtrl_GetFirstChild, 2030).
+-define(wxTreeCtrl_GetNextChild, 2031).
+-define(wxTreeCtrl_GetFirstVisibleItem, 2032).
+-define(wxTreeCtrl_GetImageList, 2033).
+-define(wxTreeCtrl_GetIndent, 2034).
+-define(wxTreeCtrl_GetItemBackgroundColour, 2035).
+-define(wxTreeCtrl_GetItemData, 2036).
+-define(wxTreeCtrl_GetItemFont, 2037).
+-define(wxTreeCtrl_GetItemImage_1, 2038).
+-define(wxTreeCtrl_GetItemImage_2, 2039).
+-define(wxTreeCtrl_GetItemText, 2040).
+-define(wxTreeCtrl_GetItemTextColour, 2041).
+-define(wxTreeCtrl_GetLastChild, 2042).
+-define(wxTreeCtrl_GetNextSibling, 2043).
+-define(wxTreeCtrl_GetNextVisible, 2044).
+-define(wxTreeCtrl_GetItemParent, 2045).
+-define(wxTreeCtrl_GetPrevSibling, 2046).
+-define(wxTreeCtrl_GetPrevVisible, 2047).
+-define(wxTreeCtrl_GetRootItem, 2048).
+-define(wxTreeCtrl_GetSelection, 2049).
+-define(wxTreeCtrl_GetSelections, 2050).
+-define(wxTreeCtrl_GetStateImageList, 2051).
+-define(wxTreeCtrl_HitTest, 2052).
+-define(wxTreeCtrl_InsertItem, 2054).
+-define(wxTreeCtrl_IsBold, 2055).
+-define(wxTreeCtrl_IsExpanded, 2056).
+-define(wxTreeCtrl_IsSelected, 2057).
+-define(wxTreeCtrl_IsVisible, 2058).
+-define(wxTreeCtrl_ItemHasChildren, 2059).
+-define(wxTreeCtrl_PrependItem, 2060).
+-define(wxTreeCtrl_ScrollTo, 2061).
+-define(wxTreeCtrl_SelectItem_1, 2062).
+-define(wxTreeCtrl_SelectItem_2, 2063).
+-define(wxTreeCtrl_SetIndent, 2064).
+-define(wxTreeCtrl_SetImageList, 2065).
+-define(wxTreeCtrl_SetItemBackgroundColour, 2066).
+-define(wxTreeCtrl_SetItemBold, 2067).
+-define(wxTreeCtrl_SetItemData, 2068).
+-define(wxTreeCtrl_SetItemDropHighlight, 2069).
+-define(wxTreeCtrl_SetItemFont, 2070).
+-define(wxTreeCtrl_SetItemHasChildren, 2071).
+-define(wxTreeCtrl_SetItemImage_2, 2072).
+-define(wxTreeCtrl_SetItemImage_3, 2073).
+-define(wxTreeCtrl_SetItemText, 2074).
+-define(wxTreeCtrl_SetItemTextColour, 2075).
+-define(wxTreeCtrl_SetStateImageList, 2076).
+-define(wxTreeCtrl_SetWindowStyle, 2077).
+-define(wxTreeCtrl_SortChildren, 2078).
+-define(wxTreeCtrl_Toggle, 2079).
+-define(wxTreeCtrl_ToggleItemSelection, 2080).
+-define(wxTreeCtrl_Unselect, 2081).
+-define(wxTreeCtrl_UnselectAll, 2082).
+-define(wxTreeCtrl_UnselectItem, 2083).
+-define(wxScrollBar_new_0, 2084).
+-define(wxScrollBar_new_3, 2085).
+-define(wxScrollBar_destruct, 2086).
+-define(wxScrollBar_Create, 2087).
+-define(wxScrollBar_GetRange, 2088).
+-define(wxScrollBar_GetPageSize, 2089).
+-define(wxScrollBar_GetThumbPosition, 2090).
+-define(wxScrollBar_GetThumbSize, 2091).
+-define(wxScrollBar_SetThumbPosition, 2092).
+-define(wxScrollBar_SetScrollbar, 2093).
+-define(wxSpinButton_new_2, 2095).
+-define(wxSpinButton_new_0, 2096).
+-define(wxSpinButton_Create, 2097).
+-define(wxSpinButton_GetMax, 2098).
+-define(wxSpinButton_GetMin, 2099).
+-define(wxSpinButton_GetValue, 2100).
+-define(wxSpinButton_SetRange, 2101).
+-define(wxSpinButton_SetValue, 2102).
+-define(wxSpinButton_destroy, 2103).
+-define(wxSpinCtrl_new_0, 2104).
+-define(wxSpinCtrl_new_2, 2105).
+-define(wxSpinCtrl_Create, 2107).
+-define(wxSpinCtrl_SetValue_1_1, 2110).
+-define(wxSpinCtrl_SetValue_1_0, 2111).
+-define(wxSpinCtrl_GetValue, 2113).
+-define(wxSpinCtrl_SetRange, 2115).
+-define(wxSpinCtrl_SetSelection, 2116).
+-define(wxSpinCtrl_GetMin, 2118).
+-define(wxSpinCtrl_GetMax, 2120).
+-define(wxSpinCtrl_destroy, 2121).
+-define(wxStaticText_new_0, 2122).
+-define(wxStaticText_new_4, 2123).
+-define(wxStaticText_Create, 2124).
+-define(wxStaticText_GetLabel, 2125).
+-define(wxStaticText_SetLabel, 2126).
+-define(wxStaticText_Wrap, 2127).
+-define(wxStaticText_destroy, 2128).
+-define(wxStaticBitmap_new_0, 2129).
+-define(wxStaticBitmap_new_4, 2130).
+-define(wxStaticBitmap_Create, 2131).
+-define(wxStaticBitmap_GetBitmap, 2132).
+-define(wxStaticBitmap_SetBitmap, 2133).
+-define(wxStaticBitmap_destroy, 2134).
+-define(wxRadioBox_new, 2135).
+-define(wxRadioBox_destruct, 2137).
+-define(wxRadioBox_Create, 2138).
+-define(wxRadioBox_Enable_2, 2139).
+-define(wxRadioBox_Enable_1, 2140).
+-define(wxRadioBox_GetSelection, 2141).
+-define(wxRadioBox_GetString, 2142).
+-define(wxRadioBox_SetSelection, 2143).
+-define(wxRadioBox_Show_2, 2144).
+-define(wxRadioBox_Show_1, 2145).
+-define(wxRadioBox_GetColumnCount, 2146).
+-define(wxRadioBox_GetItemHelpText, 2147).
+-define(wxRadioBox_GetItemToolTip, 2148).
+-define(wxRadioBox_GetItemFromPoint, 2150).
+-define(wxRadioBox_GetRowCount, 2151).
+-define(wxRadioBox_IsItemEnabled, 2152).
+-define(wxRadioBox_IsItemShown, 2153).
+-define(wxRadioBox_SetItemHelpText, 2154).
+-define(wxRadioBox_SetItemToolTip, 2155).
+-define(wxRadioButton_new_0, 2156).
+-define(wxRadioButton_new_4, 2157).
+-define(wxRadioButton_Create, 2158).
+-define(wxRadioButton_GetValue, 2159).
+-define(wxRadioButton_SetValue, 2160).
+-define(wxRadioButton_destroy, 2161).
+-define(wxSlider_new_6, 2163).
+-define(wxSlider_new_0, 2164).
+-define(wxSlider_Create, 2165).
+-define(wxSlider_GetLineSize, 2166).
+-define(wxSlider_GetMax, 2167).
+-define(wxSlider_GetMin, 2168).
+-define(wxSlider_GetPageSize, 2169).
+-define(wxSlider_GetThumbLength, 2170).
+-define(wxSlider_GetValue, 2171).
+-define(wxSlider_SetLineSize, 2172).
+-define(wxSlider_SetPageSize, 2173).
+-define(wxSlider_SetRange, 2174).
+-define(wxSlider_SetThumbLength, 2175).
+-define(wxSlider_SetValue, 2176).
+-define(wxSlider_destroy, 2177).
+-define(wxDialog_new_4, 2179).
+-define(wxDialog_new_0, 2180).
+-define(wxDialog_destruct, 2182).
+-define(wxDialog_Create, 2183).
+-define(wxDialog_CreateButtonSizer, 2184).
+-define(wxDialog_CreateStdDialogButtonSizer, 2185).
+-define(wxDialog_EndModal, 2186).
+-define(wxDialog_GetAffirmativeId, 2187).
+-define(wxDialog_GetReturnCode, 2188).
+-define(wxDialog_IsModal, 2189).
+-define(wxDialog_SetAffirmativeId, 2190).
+-define(wxDialog_SetReturnCode, 2191).
+-define(wxDialog_Show, 2192).
+-define(wxDialog_ShowModal, 2193).
+-define(wxColourDialog_new_0, 2194).
+-define(wxColourDialog_new_2, 2195).
+-define(wxColourDialog_destruct, 2196).
+-define(wxColourDialog_Create, 2197).
+-define(wxColourDialog_GetColourData, 2198).
+-define(wxColourData_new_0, 2199).
+-define(wxColourData_new_1, 2200).
+-define(wxColourData_destruct, 2201).
+-define(wxColourData_GetChooseFull, 2202).
+-define(wxColourData_GetColour, 2203).
+-define(wxColourData_GetCustomColour, 2205).
+-define(wxColourData_SetChooseFull, 2206).
+-define(wxColourData_SetColour, 2207).
+-define(wxColourData_SetCustomColour, 2208).
+-define(wxPalette_new_0, 2209).
+-define(wxPalette_new_4, 2210).
+-define(wxPalette_destruct, 2212).
+-define(wxPalette_Create, 2213).
+-define(wxPalette_GetColoursCount, 2214).
+-define(wxPalette_GetPixel, 2215).
+-define(wxPalette_GetRGB, 2216).
+-define(wxPalette_IsOk, 2217).
+-define(wxDirDialog_new, 2221).
+-define(wxDirDialog_destruct, 2222).
+-define(wxDirDialog_GetPath, 2223).
+-define(wxDirDialog_GetMessage, 2224).
+-define(wxDirDialog_SetMessage, 2225).
+-define(wxDirDialog_SetPath, 2226).
+-define(wxFileDialog_new, 2230).
+-define(wxFileDialog_destruct, 2231).
+-define(wxFileDialog_GetDirectory, 2232).
+-define(wxFileDialog_GetFilename, 2233).
+-define(wxFileDialog_GetFilenames, 2234).
+-define(wxFileDialog_GetFilterIndex, 2235).
+-define(wxFileDialog_GetMessage, 2236).
+-define(wxFileDialog_GetPath, 2237).
+-define(wxFileDialog_GetPaths, 2238).
+-define(wxFileDialog_GetWildcard, 2239).
+-define(wxFileDialog_SetDirectory, 2240).
+-define(wxFileDialog_SetFilename, 2241).
+-define(wxFileDialog_SetFilterIndex, 2242).
+-define(wxFileDialog_SetMessage, 2243).
+-define(wxFileDialog_SetPath, 2244).
+-define(wxFileDialog_SetWildcard, 2245).
+-define(wxPickerBase_SetInternalMargin, 2246).
+-define(wxPickerBase_GetInternalMargin, 2247).
+-define(wxPickerBase_SetTextCtrlProportion, 2248).
+-define(wxPickerBase_SetPickerCtrlProportion, 2249).
+-define(wxPickerBase_GetTextCtrlProportion, 2250).
+-define(wxPickerBase_GetPickerCtrlProportion, 2251).
+-define(wxPickerBase_HasTextCtrl, 2252).
+-define(wxPickerBase_GetTextCtrl, 2253).
+-define(wxPickerBase_IsTextCtrlGrowable, 2254).
+-define(wxPickerBase_SetPickerCtrlGrowable, 2255).
+-define(wxPickerBase_SetTextCtrlGrowable, 2256).
+-define(wxPickerBase_IsPickerCtrlGrowable, 2257).
+-define(wxFilePickerCtrl_new_0, 2258).
+-define(wxFilePickerCtrl_new_3, 2259).
+-define(wxFilePickerCtrl_Create, 2260).
+-define(wxFilePickerCtrl_GetPath, 2261).
+-define(wxFilePickerCtrl_SetPath, 2262).
+-define(wxFilePickerCtrl_destroy, 2263).
+-define(wxDirPickerCtrl_new_0, 2264).
+-define(wxDirPickerCtrl_new_3, 2265).
+-define(wxDirPickerCtrl_Create, 2266).
+-define(wxDirPickerCtrl_GetPath, 2267).
+-define(wxDirPickerCtrl_SetPath, 2268).
+-define(wxDirPickerCtrl_destroy, 2269).
+-define(wxColourPickerCtrl_new_0, 2270).
+-define(wxColourPickerCtrl_new_3, 2271).
+-define(wxColourPickerCtrl_Create, 2272).
+-define(wxColourPickerCtrl_GetColour, 2273).
+-define(wxColourPickerCtrl_SetColour_1_1, 2274).
+-define(wxColourPickerCtrl_SetColour_1_0, 2275).
+-define(wxColourPickerCtrl_destroy, 2276).
+-define(wxDatePickerCtrl_new_0, 2277).
+-define(wxDatePickerCtrl_new_3, 2278).
+-define(wxDatePickerCtrl_GetRange, 2279).
+-define(wxDatePickerCtrl_GetValue, 2280).
+-define(wxDatePickerCtrl_SetRange, 2281).
+-define(wxDatePickerCtrl_SetValue, 2282).
+-define(wxDatePickerCtrl_destroy, 2283).
+-define(wxFontPickerCtrl_new_0, 2284).
+-define(wxFontPickerCtrl_new_3, 2285).
+-define(wxFontPickerCtrl_Create, 2286).
+-define(wxFontPickerCtrl_GetSelectedFont, 2287).
+-define(wxFontPickerCtrl_SetSelectedFont, 2288).
+-define(wxFontPickerCtrl_GetMaxPointSize, 2289).
+-define(wxFontPickerCtrl_SetMaxPointSize, 2290).
+-define(wxFontPickerCtrl_destroy, 2291).
+-define(wxFindReplaceDialog_new_0, 2294).
+-define(wxFindReplaceDialog_new_4, 2295).
+-define(wxFindReplaceDialog_destruct, 2296).
+-define(wxFindReplaceDialog_Create, 2297).
+-define(wxFindReplaceDialog_GetData, 2298).
+-define(wxFindReplaceData_new_0, 2299).
+-define(wxFindReplaceData_new_1, 2300).
+-define(wxFindReplaceData_GetFindString, 2301).
+-define(wxFindReplaceData_GetReplaceString, 2302).
+-define(wxFindReplaceData_GetFlags, 2303).
+-define(wxFindReplaceData_SetFlags, 2304).
+-define(wxFindReplaceData_SetFindString, 2305).
+-define(wxFindReplaceData_SetReplaceString, 2306).
+-define(wxFindReplaceData_destroy, 2307).
+-define(wxMultiChoiceDialog_new_0, 2308).
+-define(wxMultiChoiceDialog_new_5, 2310).
+-define(wxMultiChoiceDialog_GetSelections, 2311).
+-define(wxMultiChoiceDialog_SetSelections, 2312).
+-define(wxMultiChoiceDialog_destroy, 2313).
+-define(wxSingleChoiceDialog_new_0, 2314).
+-define(wxSingleChoiceDialog_new_5, 2316).
+-define(wxSingleChoiceDialog_GetSelection, 2317).
+-define(wxSingleChoiceDialog_GetStringSelection, 2318).
+-define(wxSingleChoiceDialog_SetSelection, 2319).
+-define(wxSingleChoiceDialog_destroy, 2320).
+-define(wxTextEntryDialog_new, 2321).
+-define(wxTextEntryDialog_GetValue, 2322).
+-define(wxTextEntryDialog_SetValue, 2323).
+-define(wxTextEntryDialog_destroy, 2324).
+-define(wxPasswordEntryDialog_new, 2325).
+-define(wxPasswordEntryDialog_destroy, 2326).
+-define(wxFontData_new_0, 2327).
+-define(wxFontData_new_1, 2328).
+-define(wxFontData_destruct, 2329).
+-define(wxFontData_EnableEffects, 2330).
+-define(wxFontData_GetAllowSymbols, 2331).
+-define(wxFontData_GetColour, 2332).
+-define(wxFontData_GetChosenFont, 2333).
+-define(wxFontData_GetEnableEffects, 2334).
+-define(wxFontData_GetInitialFont, 2335).
+-define(wxFontData_GetShowHelp, 2336).
+-define(wxFontData_SetAllowSymbols, 2337).
+-define(wxFontData_SetChosenFont, 2338).
+-define(wxFontData_SetColour, 2339).
+-define(wxFontData_SetInitialFont, 2340).
+-define(wxFontData_SetRange, 2341).
+-define(wxFontData_SetShowHelp, 2342).
+-define(wxFontDialog_new_0, 2346).
+-define(wxFontDialog_new_2, 2348).
+-define(wxFontDialog_Create, 2350).
+-define(wxFontDialog_GetFontData, 2351).
+-define(wxFontDialog_destroy, 2353).
+-define(wxProgressDialog_new, 2354).
+-define(wxProgressDialog_destruct, 2355).
+-define(wxProgressDialog_Resume, 2356).
+-define(wxProgressDialog_Update_2, 2357).
+-define(wxProgressDialog_Update_0, 2358).
+-define(wxMessageDialog_new, 2359).
+-define(wxMessageDialog_destruct, 2360).
+-define(wxPageSetupDialog_new, 2361).
+-define(wxPageSetupDialog_destruct, 2362).
+-define(wxPageSetupDialog_GetPageSetupData, 2363).
+-define(wxPageSetupDialog_ShowModal, 2364).
+-define(wxPageSetupDialogData_new_0, 2365).
+-define(wxPageSetupDialogData_new_1_0, 2366).
+-define(wxPageSetupDialogData_new_1_1, 2367).
+-define(wxPageSetupDialogData_destruct, 2368).
+-define(wxPageSetupDialogData_EnableHelp, 2369).
+-define(wxPageSetupDialogData_EnableMargins, 2370).
+-define(wxPageSetupDialogData_EnableOrientation, 2371).
+-define(wxPageSetupDialogData_EnablePaper, 2372).
+-define(wxPageSetupDialogData_EnablePrinter, 2373).
+-define(wxPageSetupDialogData_GetDefaultMinMargins, 2374).
+-define(wxPageSetupDialogData_GetEnableMargins, 2375).
+-define(wxPageSetupDialogData_GetEnableOrientation, 2376).
+-define(wxPageSetupDialogData_GetEnablePaper, 2377).
+-define(wxPageSetupDialogData_GetEnablePrinter, 2378).
+-define(wxPageSetupDialogData_GetEnableHelp, 2379).
+-define(wxPageSetupDialogData_GetDefaultInfo, 2380).
+-define(wxPageSetupDialogData_GetMarginTopLeft, 2381).
+-define(wxPageSetupDialogData_GetMarginBottomRight, 2382).
+-define(wxPageSetupDialogData_GetMinMarginTopLeft, 2383).
+-define(wxPageSetupDialogData_GetMinMarginBottomRight, 2384).
+-define(wxPageSetupDialogData_GetPaperId, 2385).
+-define(wxPageSetupDialogData_GetPaperSize, 2386).
+-define(wxPageSetupDialogData_GetPrintData, 2388).
+-define(wxPageSetupDialogData_IsOk, 2389).
+-define(wxPageSetupDialogData_SetDefaultInfo, 2390).
+-define(wxPageSetupDialogData_SetDefaultMinMargins, 2391).
+-define(wxPageSetupDialogData_SetMarginTopLeft, 2392).
+-define(wxPageSetupDialogData_SetMarginBottomRight, 2393).
+-define(wxPageSetupDialogData_SetMinMarginTopLeft, 2394).
+-define(wxPageSetupDialogData_SetMinMarginBottomRight, 2395).
+-define(wxPageSetupDialogData_SetPaperId, 2396).
+-define(wxPageSetupDialogData_SetPaperSize_1_1, 2397).
+-define(wxPageSetupDialogData_SetPaperSize_1_0, 2398).
+-define(wxPageSetupDialogData_SetPrintData, 2399).
+-define(wxPrintDialog_new_2_0, 2400).
+-define(wxPrintDialog_new_2_1, 2401).
+-define(wxPrintDialog_destruct, 2402).
+-define(wxPrintDialog_GetPrintDialogData, 2403).
+-define(wxPrintDialog_GetPrintDC, 2404).
+-define(wxPrintDialogData_new_0, 2405).
+-define(wxPrintDialogData_new_1_1, 2406).
+-define(wxPrintDialogData_new_1_0, 2407).
+-define(wxPrintDialogData_destruct, 2408).
+-define(wxPrintDialogData_EnableHelp, 2409).
+-define(wxPrintDialogData_EnablePageNumbers, 2410).
+-define(wxPrintDialogData_EnablePrintToFile, 2411).
+-define(wxPrintDialogData_EnableSelection, 2412).
+-define(wxPrintDialogData_GetAllPages, 2413).
+-define(wxPrintDialogData_GetCollate, 2414).
+-define(wxPrintDialogData_GetFromPage, 2415).
+-define(wxPrintDialogData_GetMaxPage, 2416).
+-define(wxPrintDialogData_GetMinPage, 2417).
+-define(wxPrintDialogData_GetNoCopies, 2418).
+-define(wxPrintDialogData_GetPrintData, 2419).
+-define(wxPrintDialogData_GetPrintToFile, 2420).
+-define(wxPrintDialogData_GetSelection, 2421).
+-define(wxPrintDialogData_GetToPage, 2422).
+-define(wxPrintDialogData_IsOk, 2423).
+-define(wxPrintDialogData_SetCollate, 2424).
+-define(wxPrintDialogData_SetFromPage, 2425).
+-define(wxPrintDialogData_SetMaxPage, 2426).
+-define(wxPrintDialogData_SetMinPage, 2427).
+-define(wxPrintDialogData_SetNoCopies, 2428).
+-define(wxPrintDialogData_SetPrintData, 2429).
+-define(wxPrintDialogData_SetPrintToFile, 2430).
+-define(wxPrintDialogData_SetSelection, 2431).
+-define(wxPrintDialogData_SetToPage, 2432).
+-define(wxPrintData_new_0, 2433).
+-define(wxPrintData_new_1, 2434).
+-define(wxPrintData_destruct, 2435).
+-define(wxPrintData_GetCollate, 2436).
+-define(wxPrintData_GetBin, 2437).
+-define(wxPrintData_GetColour, 2438).
+-define(wxPrintData_GetDuplex, 2439).
+-define(wxPrintData_GetNoCopies, 2440).
+-define(wxPrintData_GetOrientation, 2441).
+-define(wxPrintData_GetPaperId, 2442).
+-define(wxPrintData_GetPrinterName, 2443).
+-define(wxPrintData_GetQuality, 2444).
+-define(wxPrintData_IsOk, 2445).
+-define(wxPrintData_SetBin, 2446).
+-define(wxPrintData_SetCollate, 2447).
+-define(wxPrintData_SetColour, 2448).
+-define(wxPrintData_SetDuplex, 2449).
+-define(wxPrintData_SetNoCopies, 2450).
+-define(wxPrintData_SetOrientation, 2451).
+-define(wxPrintData_SetPaperId, 2452).
+-define(wxPrintData_SetPrinterName, 2453).
+-define(wxPrintData_SetQuality, 2454).
+-define(wxPrintPreview_new_2, 2457).
+-define(wxPrintPreview_new_3, 2458).
+-define(wxPrintPreview_destruct, 2460).
+-define(wxPrintPreview_GetCanvas, 2461).
+-define(wxPrintPreview_GetCurrentPage, 2462).
+-define(wxPrintPreview_GetFrame, 2463).
+-define(wxPrintPreview_GetMaxPage, 2464).
+-define(wxPrintPreview_GetMinPage, 2465).
+-define(wxPrintPreview_GetPrintout, 2466).
+-define(wxPrintPreview_GetPrintoutForPrinting, 2467).
+-define(wxPrintPreview_IsOk, 2468).
+-define(wxPrintPreview_PaintPage, 2469).
+-define(wxPrintPreview_Print, 2470).
+-define(wxPrintPreview_RenderPage, 2471).
+-define(wxPrintPreview_SetCanvas, 2472).
+-define(wxPrintPreview_SetCurrentPage, 2473).
+-define(wxPrintPreview_SetFrame, 2474).
+-define(wxPrintPreview_SetPrintout, 2475).
+-define(wxPrintPreview_SetZoom, 2476).
+-define(wxPreviewFrame_new, 2477).
+-define(wxPreviewFrame_destruct, 2478).
+-define(wxPreviewFrame_CreateControlBar, 2479).
+-define(wxPreviewFrame_CreateCanvas, 2480).
+-define(wxPreviewFrame_Initialize, 2481).
+-define(wxPreviewFrame_OnCloseWindow, 2482).
+-define(wxPreviewControlBar_new, 2483).
+-define(wxPreviewControlBar_destruct, 2484).
+-define(wxPreviewControlBar_CreateButtons, 2485).
+-define(wxPreviewControlBar_GetPrintPreview, 2486).
+-define(wxPreviewControlBar_GetZoomControl, 2487).
+-define(wxPreviewControlBar_SetZoomControl, 2488).
+-define(wxPrinter_new, 2490).
+-define(wxPrinter_CreateAbortWindow, 2491).
+-define(wxPrinter_GetAbort, 2492).
+-define(wxPrinter_GetLastError, 2493).
+-define(wxPrinter_GetPrintDialogData, 2494).
+-define(wxPrinter_Print, 2495).
+-define(wxPrinter_PrintDialog, 2496).
+-define(wxPrinter_ReportError, 2497).
+-define(wxPrinter_Setup, 2498).
+-define(wxPrinter_destroy, 2499).
+-define(wxXmlResource_new_1, 2500).
+-define(wxXmlResource_new_2, 2501).
+-define(wxXmlResource_destruct, 2502).
+-define(wxXmlResource_AttachUnknownControl, 2503).
+-define(wxXmlResource_ClearHandlers, 2504).
+-define(wxXmlResource_CompareVersion, 2505).
+-define(wxXmlResource_Get, 2506).
+-define(wxXmlResource_GetFlags, 2507).
+-define(wxXmlResource_GetVersion, 2508).
+-define(wxXmlResource_GetXRCID, 2509).
+-define(wxXmlResource_InitAllHandlers, 2510).
+-define(wxXmlResource_Load, 2511).
+-define(wxXmlResource_LoadBitmap, 2512).
+-define(wxXmlResource_LoadDialog_2, 2513).
+-define(wxXmlResource_LoadDialog_3, 2514).
+-define(wxXmlResource_LoadFrame_2, 2515).
+-define(wxXmlResource_LoadFrame_3, 2516).
+-define(wxXmlResource_LoadIcon, 2517).
+-define(wxXmlResource_LoadMenu, 2518).
+-define(wxXmlResource_LoadMenuBar_2, 2519).
+-define(wxXmlResource_LoadMenuBar_1, 2520).
+-define(wxXmlResource_LoadPanel_2, 2521).
+-define(wxXmlResource_LoadPanel_3, 2522).
+-define(wxXmlResource_LoadToolBar, 2523).
+-define(wxXmlResource_Set, 2524).
+-define(wxXmlResource_SetFlags, 2525).
+-define(wxXmlResource_Unload, 2526).
+-define(wxXmlResource_xrcctrl, 2527).
+-define(wxHtmlEasyPrinting_new, 2528).
+-define(wxHtmlEasyPrinting_destruct, 2529).
+-define(wxHtmlEasyPrinting_GetPrintData, 2530).
+-define(wxHtmlEasyPrinting_GetPageSetupData, 2531).
+-define(wxHtmlEasyPrinting_PreviewFile, 2532).
+-define(wxHtmlEasyPrinting_PreviewText, 2533).
+-define(wxHtmlEasyPrinting_PrintFile, 2534).
+-define(wxHtmlEasyPrinting_PrintText, 2535).
+-define(wxHtmlEasyPrinting_PageSetup, 2536).
+-define(wxHtmlEasyPrinting_SetFonts, 2537).
+-define(wxHtmlEasyPrinting_SetHeader, 2538).
+-define(wxHtmlEasyPrinting_SetFooter, 2539).
+-define(wxGLCanvas_new_2, 2541).
+-define(wxGLCanvas_new_3_1, 2542).
+-define(wxGLCanvas_new_3_0, 2543).
+-define(wxGLCanvas_GetContext, 2544).
+-define(wxGLCanvas_SetCurrent, 2546).
+-define(wxGLCanvas_SwapBuffers, 2547).
+-define(wxGLCanvas_destroy, 2548).
+-define(wxAuiManager_new, 2549).
+-define(wxAuiManager_destruct, 2550).
+-define(wxAuiManager_AddPane_2_1, 2551).
+-define(wxAuiManager_AddPane_3, 2552).
+-define(wxAuiManager_AddPane_2_0, 2553).
+-define(wxAuiManager_DetachPane, 2554).
+-define(wxAuiManager_GetAllPanes, 2555).
+-define(wxAuiManager_GetArtProvider, 2556).
+-define(wxAuiManager_GetDockSizeConstraint, 2557).
+-define(wxAuiManager_GetFlags, 2558).
+-define(wxAuiManager_GetManagedWindow, 2559).
+-define(wxAuiManager_GetManager, 2560).
+-define(wxAuiManager_GetPane_1_1, 2561).
+-define(wxAuiManager_GetPane_1_0, 2562).
+-define(wxAuiManager_HideHint, 2563).
+-define(wxAuiManager_InsertPane, 2564).
+-define(wxAuiManager_LoadPaneInfo, 2565).
+-define(wxAuiManager_LoadPerspective, 2566).
+-define(wxAuiManager_SavePaneInfo, 2567).
+-define(wxAuiManager_SavePerspective, 2568).
+-define(wxAuiManager_SetArtProvider, 2569).
+-define(wxAuiManager_SetDockSizeConstraint, 2570).
+-define(wxAuiManager_SetFlags, 2571).
+-define(wxAuiManager_SetManagedWindow, 2572).
+-define(wxAuiManager_ShowHint, 2573).
+-define(wxAuiManager_UnInit, 2574).
+-define(wxAuiManager_Update, 2575).
+-define(wxAuiPaneInfo_new_0, 2576).
+-define(wxAuiPaneInfo_new_1, 2577).
+-define(wxAuiPaneInfo_destruct, 2578).
+-define(wxAuiPaneInfo_BestSize_1, 2579).
+-define(wxAuiPaneInfo_BestSize_2, 2580).
+-define(wxAuiPaneInfo_Bottom, 2581).
+-define(wxAuiPaneInfo_BottomDockable, 2582).
+-define(wxAuiPaneInfo_Caption, 2583).
+-define(wxAuiPaneInfo_CaptionVisible, 2584).
+-define(wxAuiPaneInfo_Centre, 2585).
+-define(wxAuiPaneInfo_CentrePane, 2586).
+-define(wxAuiPaneInfo_CloseButton, 2587).
+-define(wxAuiPaneInfo_DefaultPane, 2588).
+-define(wxAuiPaneInfo_DestroyOnClose, 2589).
+-define(wxAuiPaneInfo_Direction, 2590).
+-define(wxAuiPaneInfo_Dock, 2591).
+-define(wxAuiPaneInfo_Dockable, 2592).
+-define(wxAuiPaneInfo_Fixed, 2593).
+-define(wxAuiPaneInfo_Float, 2594).
+-define(wxAuiPaneInfo_Floatable, 2595).
+-define(wxAuiPaneInfo_FloatingPosition_1, 2596).
+-define(wxAuiPaneInfo_FloatingPosition_2, 2597).
+-define(wxAuiPaneInfo_FloatingSize_1, 2598).
+-define(wxAuiPaneInfo_FloatingSize_2, 2599).
+-define(wxAuiPaneInfo_Gripper, 2600).
+-define(wxAuiPaneInfo_GripperTop, 2601).
+-define(wxAuiPaneInfo_HasBorder, 2602).
+-define(wxAuiPaneInfo_HasCaption, 2603).
+-define(wxAuiPaneInfo_HasCloseButton, 2604).
+-define(wxAuiPaneInfo_HasFlag, 2605).
+-define(wxAuiPaneInfo_HasGripper, 2606).
+-define(wxAuiPaneInfo_HasGripperTop, 2607).
+-define(wxAuiPaneInfo_HasMaximizeButton, 2608).
+-define(wxAuiPaneInfo_HasMinimizeButton, 2609).
+-define(wxAuiPaneInfo_HasPinButton, 2610).
+-define(wxAuiPaneInfo_Hide, 2611).
+-define(wxAuiPaneInfo_IsBottomDockable, 2612).
+-define(wxAuiPaneInfo_IsDocked, 2613).
+-define(wxAuiPaneInfo_IsFixed, 2614).
+-define(wxAuiPaneInfo_IsFloatable, 2615).
+-define(wxAuiPaneInfo_IsFloating, 2616).
+-define(wxAuiPaneInfo_IsLeftDockable, 2617).
+-define(wxAuiPaneInfo_IsMovable, 2618).
+-define(wxAuiPaneInfo_IsOk, 2619).
+-define(wxAuiPaneInfo_IsResizable, 2620).
+-define(wxAuiPaneInfo_IsRightDockable, 2621).
+-define(wxAuiPaneInfo_IsShown, 2622).
+-define(wxAuiPaneInfo_IsToolbar, 2623).
+-define(wxAuiPaneInfo_IsTopDockable, 2624).
+-define(wxAuiPaneInfo_Layer, 2625).
+-define(wxAuiPaneInfo_Left, 2626).
+-define(wxAuiPaneInfo_LeftDockable, 2627).
+-define(wxAuiPaneInfo_MaxSize_1, 2628).
+-define(wxAuiPaneInfo_MaxSize_2, 2629).
+-define(wxAuiPaneInfo_MaximizeButton, 2630).
+-define(wxAuiPaneInfo_MinSize_1, 2631).
+-define(wxAuiPaneInfo_MinSize_2, 2632).
+-define(wxAuiPaneInfo_MinimizeButton, 2633).
+-define(wxAuiPaneInfo_Movable, 2634).
+-define(wxAuiPaneInfo_Name, 2635).
+-define(wxAuiPaneInfo_PaneBorder, 2636).
+-define(wxAuiPaneInfo_PinButton, 2637).
+-define(wxAuiPaneInfo_Position, 2638).
+-define(wxAuiPaneInfo_Resizable, 2639).
+-define(wxAuiPaneInfo_Right, 2640).
+-define(wxAuiPaneInfo_RightDockable, 2641).
+-define(wxAuiPaneInfo_Row, 2642).
+-define(wxAuiPaneInfo_SafeSet, 2643).
+-define(wxAuiPaneInfo_SetFlag, 2644).
+-define(wxAuiPaneInfo_Show, 2645).
+-define(wxAuiPaneInfo_ToolbarPane, 2646).
+-define(wxAuiPaneInfo_Top, 2647).
+-define(wxAuiPaneInfo_TopDockable, 2648).
+-define(wxAuiPaneInfo_Window, 2649).
+-define(wxAuiNotebook_new_0, 2650).
+-define(wxAuiNotebook_new_2, 2651).
+-define(wxAuiNotebook_AddPage, 2652).
+-define(wxAuiNotebook_Create, 2653).
+-define(wxAuiNotebook_DeletePage, 2654).
+-define(wxAuiNotebook_GetArtProvider, 2655).
+-define(wxAuiNotebook_GetPage, 2656).
+-define(wxAuiNotebook_GetPageBitmap, 2657).
+-define(wxAuiNotebook_GetPageCount, 2658).
+-define(wxAuiNotebook_GetPageIndex, 2659).
+-define(wxAuiNotebook_GetPageText, 2660).
+-define(wxAuiNotebook_GetSelection, 2661).
+-define(wxAuiNotebook_InsertPage, 2662).
+-define(wxAuiNotebook_RemovePage, 2663).
+-define(wxAuiNotebook_SetArtProvider, 2664).
+-define(wxAuiNotebook_SetFont, 2665).
+-define(wxAuiNotebook_SetPageBitmap, 2666).
+-define(wxAuiNotebook_SetPageText, 2667).
+-define(wxAuiNotebook_SetSelection, 2668).
+-define(wxAuiNotebook_SetTabCtrlHeight, 2669).
+-define(wxAuiNotebook_SetUniformBitmapSize, 2670).
+-define(wxAuiNotebook_destroy, 2671).
+-define(wxMDIParentFrame_new_0, 2672).
+-define(wxMDIParentFrame_new_4, 2673).
+-define(wxMDIParentFrame_destruct, 2674).
+-define(wxMDIParentFrame_ActivateNext, 2675).
+-define(wxMDIParentFrame_ActivatePrevious, 2676).
+-define(wxMDIParentFrame_ArrangeIcons, 2677).
+-define(wxMDIParentFrame_Cascade, 2678).
+-define(wxMDIParentFrame_Create, 2679).
+-define(wxMDIParentFrame_GetActiveChild, 2680).
+-define(wxMDIParentFrame_GetClientWindow, 2681).
+-define(wxMDIParentFrame_Tile, 2682).
+-define(wxMDIChildFrame_new_0, 2683).
+-define(wxMDIChildFrame_new_4, 2684).
+-define(wxMDIChildFrame_destruct, 2685).
+-define(wxMDIChildFrame_Activate, 2686).
+-define(wxMDIChildFrame_Create, 2687).
+-define(wxMDIChildFrame_Maximize, 2688).
+-define(wxMDIChildFrame_Restore, 2689).
+-define(wxMDIClientWindow_new_0, 2690).
+-define(wxMDIClientWindow_new_2, 2691).
+-define(wxMDIClientWindow_destruct, 2692).
+-define(wxMDIClientWindow_CreateClient, 2693).
+-define(wxLayoutAlgorithm_new, 2694).
+-define(wxLayoutAlgorithm_LayoutFrame, 2695).
+-define(wxLayoutAlgorithm_LayoutMDIFrame, 2696).
+-define(wxLayoutAlgorithm_LayoutWindow, 2697).
+-define(wxLayoutAlgorithm_destroy, 2698).
+-define(wxEvent_GetId, 2699).
+-define(wxEvent_GetSkipped, 2700).
+-define(wxEvent_GetTimestamp, 2701).
+-define(wxEvent_IsCommandEvent, 2702).
+-define(wxEvent_ResumePropagation, 2703).
+-define(wxEvent_ShouldPropagate, 2704).
+-define(wxEvent_Skip, 2705).
+-define(wxEvent_StopPropagation, 2706).
+-define(wxCommandEvent_getClientData, 2707).
+-define(wxCommandEvent_GetExtraLong, 2708).
+-define(wxCommandEvent_GetInt, 2709).
+-define(wxCommandEvent_GetSelection, 2710).
+-define(wxCommandEvent_GetString, 2711).
+-define(wxCommandEvent_IsChecked, 2712).
+-define(wxCommandEvent_IsSelection, 2713).
+-define(wxCommandEvent_SetInt, 2714).
+-define(wxCommandEvent_SetString, 2715).
+-define(wxScrollEvent_GetOrientation, 2716).
+-define(wxScrollEvent_GetPosition, 2717).
+-define(wxScrollWinEvent_GetOrientation, 2718).
+-define(wxScrollWinEvent_GetPosition, 2719).
+-define(wxMouseEvent_AltDown, 2720).
+-define(wxMouseEvent_Button, 2721).
+-define(wxMouseEvent_ButtonDClick, 2722).
+-define(wxMouseEvent_ButtonDown, 2723).
+-define(wxMouseEvent_ButtonUp, 2724).
+-define(wxMouseEvent_CmdDown, 2725).
+-define(wxMouseEvent_ControlDown, 2726).
+-define(wxMouseEvent_Dragging, 2727).
+-define(wxMouseEvent_Entering, 2728).
+-define(wxMouseEvent_GetButton, 2729).
+-define(wxMouseEvent_GetPosition, 2732).
+-define(wxMouseEvent_GetLogicalPosition, 2733).
+-define(wxMouseEvent_GetLinesPerAction, 2734).
+-define(wxMouseEvent_GetWheelRotation, 2735).
+-define(wxMouseEvent_GetWheelDelta, 2736).
+-define(wxMouseEvent_GetX, 2737).
+-define(wxMouseEvent_GetY, 2738).
+-define(wxMouseEvent_IsButton, 2739).
+-define(wxMouseEvent_IsPageScroll, 2740).
+-define(wxMouseEvent_Leaving, 2741).
+-define(wxMouseEvent_LeftDClick, 2742).
+-define(wxMouseEvent_LeftDown, 2743).
+-define(wxMouseEvent_LeftIsDown, 2744).
+-define(wxMouseEvent_LeftUp, 2745).
+-define(wxMouseEvent_MetaDown, 2746).
+-define(wxMouseEvent_MiddleDClick, 2747).
+-define(wxMouseEvent_MiddleDown, 2748).
+-define(wxMouseEvent_MiddleIsDown, 2749).
+-define(wxMouseEvent_MiddleUp, 2750).
+-define(wxMouseEvent_Moving, 2751).
+-define(wxMouseEvent_RightDClick, 2752).
+-define(wxMouseEvent_RightDown, 2753).
+-define(wxMouseEvent_RightIsDown, 2754).
+-define(wxMouseEvent_RightUp, 2755).
+-define(wxMouseEvent_ShiftDown, 2756).
+-define(wxSetCursorEvent_GetCursor, 2757).
+-define(wxSetCursorEvent_GetX, 2758).
+-define(wxSetCursorEvent_GetY, 2759).
+-define(wxSetCursorEvent_HasCursor, 2760).
+-define(wxSetCursorEvent_SetCursor, 2761).
+-define(wxKeyEvent_AltDown, 2762).
+-define(wxKeyEvent_CmdDown, 2763).
+-define(wxKeyEvent_ControlDown, 2764).
+-define(wxKeyEvent_GetKeyCode, 2765).
+-define(wxKeyEvent_GetModifiers, 2766).
+-define(wxKeyEvent_GetPosition, 2769).
+-define(wxKeyEvent_GetRawKeyCode, 2770).
+-define(wxKeyEvent_GetRawKeyFlags, 2771).
+-define(wxKeyEvent_GetUnicodeKey, 2772).
+-define(wxKeyEvent_GetX, 2773).
+-define(wxKeyEvent_GetY, 2774).
+-define(wxKeyEvent_HasModifiers, 2775).
+-define(wxKeyEvent_MetaDown, 2776).
+-define(wxKeyEvent_ShiftDown, 2777).
+-define(wxSizeEvent_GetSize, 2778).
+-define(wxMoveEvent_GetPosition, 2779).
+-define(wxEraseEvent_GetDC, 2780).
+-define(wxFocusEvent_GetWindow, 2781).
+-define(wxChildFocusEvent_GetWindow, 2782).
+-define(wxMenuEvent_GetMenu, 2783).
+-define(wxMenuEvent_GetMenuId, 2784).
+-define(wxMenuEvent_IsPopup, 2785).
+-define(wxCloseEvent_CanVeto, 2786).
+-define(wxCloseEvent_GetLoggingOff, 2787).
+-define(wxCloseEvent_SetCanVeto, 2788).
+-define(wxCloseEvent_SetLoggingOff, 2789).
+-define(wxCloseEvent_Veto, 2790).
+-define(wxShowEvent_SetShow, 2791).
+-define(wxShowEvent_GetShow, 2792).
+-define(wxIconizeEvent_Iconized, 2793).
+-define(wxJoystickEvent_ButtonDown, 2794).
+-define(wxJoystickEvent_ButtonIsDown, 2795).
+-define(wxJoystickEvent_ButtonUp, 2796).
+-define(wxJoystickEvent_GetButtonChange, 2797).
+-define(wxJoystickEvent_GetButtonState, 2798).
+-define(wxJoystickEvent_GetJoystick, 2799).
+-define(wxJoystickEvent_GetPosition, 2800).
+-define(wxJoystickEvent_GetZPosition, 2801).
+-define(wxJoystickEvent_IsButton, 2802).
+-define(wxJoystickEvent_IsMove, 2803).
+-define(wxJoystickEvent_IsZMove, 2804).
+-define(wxUpdateUIEvent_CanUpdate, 2805).
+-define(wxUpdateUIEvent_Check, 2806).
+-define(wxUpdateUIEvent_Enable, 2807).
+-define(wxUpdateUIEvent_Show, 2808).
+-define(wxUpdateUIEvent_GetChecked, 2809).
+-define(wxUpdateUIEvent_GetEnabled, 2810).
+-define(wxUpdateUIEvent_GetShown, 2811).
+-define(wxUpdateUIEvent_GetSetChecked, 2812).
+-define(wxUpdateUIEvent_GetSetEnabled, 2813).
+-define(wxUpdateUIEvent_GetSetShown, 2814).
+-define(wxUpdateUIEvent_GetSetText, 2815).
+-define(wxUpdateUIEvent_GetText, 2816).
+-define(wxUpdateUIEvent_GetMode, 2817).
+-define(wxUpdateUIEvent_GetUpdateInterval, 2818).
+-define(wxUpdateUIEvent_ResetUpdateTime, 2819).
+-define(wxUpdateUIEvent_SetMode, 2820).
+-define(wxUpdateUIEvent_SetText, 2821).
+-define(wxUpdateUIEvent_SetUpdateInterval, 2822).
+-define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2823).
+-define(wxPaletteChangedEvent_SetChangedWindow, 2824).
+-define(wxPaletteChangedEvent_GetChangedWindow, 2825).
+-define(wxQueryNewPaletteEvent_SetPaletteRealized, 2826).
+-define(wxQueryNewPaletteEvent_GetPaletteRealized, 2827).
+-define(wxNavigationKeyEvent_GetDirection, 2828).
+-define(wxNavigationKeyEvent_SetDirection, 2829).
+-define(wxNavigationKeyEvent_IsWindowChange, 2830).
+-define(wxNavigationKeyEvent_SetWindowChange, 2831).
+-define(wxNavigationKeyEvent_IsFromTab, 2832).
+-define(wxNavigationKeyEvent_SetFromTab, 2833).
+-define(wxNavigationKeyEvent_GetCurrentFocus, 2834).
+-define(wxNavigationKeyEvent_SetCurrentFocus, 2835).
+-define(wxHelpEvent_GetOrigin, 2836).
+-define(wxHelpEvent_GetPosition, 2837).
+-define(wxHelpEvent_SetOrigin, 2838).
+-define(wxHelpEvent_SetPosition, 2839).
+-define(wxContextMenuEvent_GetPosition, 2840).
+-define(wxContextMenuEvent_SetPosition, 2841).
+-define(wxIdleEvent_CanSend, 2842).
+-define(wxIdleEvent_GetMode, 2843).
+-define(wxIdleEvent_RequestMore, 2844).
+-define(wxIdleEvent_MoreRequested, 2845).
+-define(wxIdleEvent_SetMode, 2846).
+-define(wxGridEvent_AltDown, 2847).
+-define(wxGridEvent_ControlDown, 2848).
+-define(wxGridEvent_GetCol, 2849).
+-define(wxGridEvent_GetPosition, 2850).
+-define(wxGridEvent_GetRow, 2851).
+-define(wxGridEvent_MetaDown, 2852).
+-define(wxGridEvent_Selecting, 2853).
+-define(wxGridEvent_ShiftDown, 2854).
+-define(wxNotifyEvent_Allow, 2855).
+-define(wxNotifyEvent_IsAllowed, 2856).
+-define(wxNotifyEvent_Veto, 2857).
+-define(wxSashEvent_GetEdge, 2858).
+-define(wxSashEvent_GetDragRect, 2859).
+-define(wxSashEvent_GetDragStatus, 2860).
+-define(wxListEvent_GetCacheFrom, 2861).
+-define(wxListEvent_GetCacheTo, 2862).
+-define(wxListEvent_GetKeyCode, 2863).
+-define(wxListEvent_GetIndex, 2864).
+-define(wxListEvent_GetColumn, 2865).
+-define(wxListEvent_GetPoint, 2866).
+-define(wxListEvent_GetLabel, 2867).
+-define(wxListEvent_GetText, 2868).
+-define(wxListEvent_GetImage, 2869).
+-define(wxListEvent_GetData, 2870).
+-define(wxListEvent_GetMask, 2871).
+-define(wxListEvent_GetItem, 2872).
+-define(wxListEvent_IsEditCancelled, 2873).
+-define(wxDateEvent_GetDate, 2874).
+-define(wxCalendarEvent_GetWeekDay, 2875).
+-define(wxFileDirPickerEvent_GetPath, 2876).
+-define(wxColourPickerEvent_GetColour, 2877).
+-define(wxFontPickerEvent_GetFont, 2878).
+-define(wxStyledTextEvent_GetPosition, 2879).
+-define(wxStyledTextEvent_GetKey, 2880).
+-define(wxStyledTextEvent_GetModifiers, 2881).
+-define(wxStyledTextEvent_GetModificationType, 2882).
+-define(wxStyledTextEvent_GetText, 2883).
+-define(wxStyledTextEvent_GetLength, 2884).
+-define(wxStyledTextEvent_GetLinesAdded, 2885).
+-define(wxStyledTextEvent_GetLine, 2886).
+-define(wxStyledTextEvent_GetFoldLevelNow, 2887).
+-define(wxStyledTextEvent_GetFoldLevelPrev, 2888).
+-define(wxStyledTextEvent_GetMargin, 2889).
+-define(wxStyledTextEvent_GetMessage, 2890).
+-define(wxStyledTextEvent_GetWParam, 2891).
+-define(wxStyledTextEvent_GetLParam, 2892).
+-define(wxStyledTextEvent_GetListType, 2893).
+-define(wxStyledTextEvent_GetX, 2894).
+-define(wxStyledTextEvent_GetY, 2895).
+-define(wxStyledTextEvent_GetDragText, 2896).
+-define(wxStyledTextEvent_GetDragAllowMove, 2897).
+-define(wxStyledTextEvent_GetDragResult, 2898).
+-define(wxStyledTextEvent_GetShift, 2899).
+-define(wxStyledTextEvent_GetControl, 2900).
+-define(wxStyledTextEvent_GetAlt, 2901).
+-define(utils_wxGetKeyState, 2902).
+-define(utils_wxGetMousePosition, 2903).
+-define(utils_wxGetMouseState, 2904).
+-define(utils_wxSetDetectableAutoRepeat, 2905).
+-define(utils_wxBell, 2906).
+-define(utils_wxFindMenuItemId, 2907).
+-define(utils_wxGenericFindWindowAtPoint, 2908).
+-define(utils_wxFindWindowAtPoint, 2909).
+-define(utils_wxBeginBusyCursor, 2910).
+-define(utils_wxEndBusyCursor, 2911).
+-define(utils_wxIsBusy, 2912).
+-define(utils_wxShutdown, 2913).
+-define(utils_wxShell, 2914).
+-define(utils_wxLaunchDefaultBrowser, 2915).
+-define(utils_wxGetEmailAddress, 2916).
+-define(utils_wxGetUserId, 2917).
+-define(utils_wxGetHomeDir, 2918).
+-define(utils_wxNewId, 2919).
+-define(utils_wxRegisterId, 2920).
+-define(utils_wxGetCurrentId, 2921).
+-define(utils_wxGetOsDescription, 2922).
+-define(utils_wxIsPlatformLittleEndian, 2923).
+-define(utils_wxIsPlatform64Bit, 2924).
+-define(wxPrintout_new, 2925).
+-define(wxPrintout_destruct, 2926).
+-define(wxPrintout_GetDC, 2927).
+-define(wxPrintout_GetPageSizeMM, 2928).
+-define(wxPrintout_GetPageSizePixels, 2929).
+-define(wxPrintout_GetPaperRectPixels, 2930).
+-define(wxPrintout_GetPPIPrinter, 2931).
+-define(wxPrintout_GetPPIScreen, 2932).
+-define(wxPrintout_GetTitle, 2933).
+-define(wxPrintout_IsPreview, 2934).
+-define(wxPrintout_FitThisSizeToPaper, 2935).
+-define(wxPrintout_FitThisSizeToPage, 2936).
+-define(wxPrintout_FitThisSizeToPageMargins, 2937).
+-define(wxPrintout_MapScreenSizeToPaper, 2938).
+-define(wxPrintout_MapScreenSizeToPage, 2939).
+-define(wxPrintout_MapScreenSizeToPageMargins, 2940).
+-define(wxPrintout_MapScreenSizeToDevice, 2941).
+-define(wxPrintout_GetLogicalPaperRect, 2942).
+-define(wxPrintout_GetLogicalPageRect, 2943).
+-define(wxPrintout_GetLogicalPageMarginsRect, 2944).
+-define(wxPrintout_SetLogicalOrigin, 2945).
+-define(wxPrintout_OffsetLogicalOrigin, 2946).
+-define(wxStyledTextCtrl_new_2, 2947).
+-define(wxStyledTextCtrl_new_0, 2948).
+-define(wxStyledTextCtrl_destruct, 2949).
+-define(wxStyledTextCtrl_Create, 2950).
+-define(wxStyledTextCtrl_AddText, 2951).
+-define(wxStyledTextCtrl_AddStyledText, 2952).
+-define(wxStyledTextCtrl_InsertText, 2953).
+-define(wxStyledTextCtrl_ClearAll, 2954).
+-define(wxStyledTextCtrl_ClearDocumentStyle, 2955).
+-define(wxStyledTextCtrl_GetLength, 2956).
+-define(wxStyledTextCtrl_GetCharAt, 2957).
+-define(wxStyledTextCtrl_GetCurrentPos, 2958).
+-define(wxStyledTextCtrl_GetAnchor, 2959).
+-define(wxStyledTextCtrl_GetStyleAt, 2960).
+-define(wxStyledTextCtrl_Redo, 2961).
+-define(wxStyledTextCtrl_SetUndoCollection, 2962).
+-define(wxStyledTextCtrl_SelectAll, 2963).
+-define(wxStyledTextCtrl_SetSavePoint, 2964).
+-define(wxStyledTextCtrl_GetStyledText, 2965).
+-define(wxStyledTextCtrl_CanRedo, 2966).
+-define(wxStyledTextCtrl_MarkerLineFromHandle, 2967).
+-define(wxStyledTextCtrl_MarkerDeleteHandle, 2968).
+-define(wxStyledTextCtrl_GetUndoCollection, 2969).
+-define(wxStyledTextCtrl_GetViewWhiteSpace, 2970).
+-define(wxStyledTextCtrl_SetViewWhiteSpace, 2971).
+-define(wxStyledTextCtrl_PositionFromPoint, 2972).
+-define(wxStyledTextCtrl_PositionFromPointClose, 2973).
+-define(wxStyledTextCtrl_GotoLine, 2974).
+-define(wxStyledTextCtrl_GotoPos, 2975).
+-define(wxStyledTextCtrl_SetAnchor, 2976).
+-define(wxStyledTextCtrl_GetCurLine, 2977).
+-define(wxStyledTextCtrl_GetEndStyled, 2978).
+-define(wxStyledTextCtrl_ConvertEOLs, 2979).
+-define(wxStyledTextCtrl_GetEOLMode, 2980).
+-define(wxStyledTextCtrl_SetEOLMode, 2981).
+-define(wxStyledTextCtrl_StartStyling, 2982).
+-define(wxStyledTextCtrl_SetStyling, 2983).
+-define(wxStyledTextCtrl_GetBufferedDraw, 2984).
+-define(wxStyledTextCtrl_SetBufferedDraw, 2985).
+-define(wxStyledTextCtrl_SetTabWidth, 2986).
+-define(wxStyledTextCtrl_GetTabWidth, 2987).
+-define(wxStyledTextCtrl_SetCodePage, 2988).
+-define(wxStyledTextCtrl_MarkerDefine, 2989).
+-define(wxStyledTextCtrl_MarkerSetForeground, 2990).
+-define(wxStyledTextCtrl_MarkerSetBackground, 2991).
+-define(wxStyledTextCtrl_MarkerAdd, 2992).
+-define(wxStyledTextCtrl_MarkerDelete, 2993).
+-define(wxStyledTextCtrl_MarkerDeleteAll, 2994).
+-define(wxStyledTextCtrl_MarkerGet, 2995).
+-define(wxStyledTextCtrl_MarkerNext, 2996).
+-define(wxStyledTextCtrl_MarkerPrevious, 2997).
+-define(wxStyledTextCtrl_MarkerDefineBitmap, 2998).
+-define(wxStyledTextCtrl_MarkerAddSet, 2999).
+-define(wxStyledTextCtrl_MarkerSetAlpha, 3000).
+-define(wxStyledTextCtrl_SetMarginType, 3001).
+-define(wxStyledTextCtrl_GetMarginType, 3002).
+-define(wxStyledTextCtrl_SetMarginWidth, 3003).
+-define(wxStyledTextCtrl_GetMarginWidth, 3004).
+-define(wxStyledTextCtrl_SetMarginMask, 3005).
+-define(wxStyledTextCtrl_GetMarginMask, 3006).
+-define(wxStyledTextCtrl_SetMarginSensitive, 3007).
+-define(wxStyledTextCtrl_GetMarginSensitive, 3008).
+-define(wxStyledTextCtrl_StyleClearAll, 3009).
+-define(wxStyledTextCtrl_StyleSetForeground, 3010).
+-define(wxStyledTextCtrl_StyleSetBackground, 3011).
+-define(wxStyledTextCtrl_StyleSetBold, 3012).
+-define(wxStyledTextCtrl_StyleSetItalic, 3013).
+-define(wxStyledTextCtrl_StyleSetSize, 3014).
+-define(wxStyledTextCtrl_StyleSetFaceName, 3015).
+-define(wxStyledTextCtrl_StyleSetEOLFilled, 3016).
+-define(wxStyledTextCtrl_StyleResetDefault, 3017).
+-define(wxStyledTextCtrl_StyleSetUnderline, 3018).
+-define(wxStyledTextCtrl_StyleSetCase, 3019).
+-define(wxStyledTextCtrl_StyleSetHotSpot, 3020).
+-define(wxStyledTextCtrl_SetSelForeground, 3021).
+-define(wxStyledTextCtrl_SetSelBackground, 3022).
+-define(wxStyledTextCtrl_GetSelAlpha, 3023).
+-define(wxStyledTextCtrl_SetSelAlpha, 3024).
+-define(wxStyledTextCtrl_SetCaretForeground, 3025).
+-define(wxStyledTextCtrl_CmdKeyAssign, 3026).
+-define(wxStyledTextCtrl_CmdKeyClear, 3027).
+-define(wxStyledTextCtrl_CmdKeyClearAll, 3028).
+-define(wxStyledTextCtrl_SetStyleBytes, 3029).
+-define(wxStyledTextCtrl_StyleSetVisible, 3030).
+-define(wxStyledTextCtrl_GetCaretPeriod, 3031).
+-define(wxStyledTextCtrl_SetCaretPeriod, 3032).
+-define(wxStyledTextCtrl_SetWordChars, 3033).
+-define(wxStyledTextCtrl_BeginUndoAction, 3034).
+-define(wxStyledTextCtrl_EndUndoAction, 3035).
+-define(wxStyledTextCtrl_IndicatorSetStyle, 3036).
+-define(wxStyledTextCtrl_IndicatorGetStyle, 3037).
+-define(wxStyledTextCtrl_IndicatorSetForeground, 3038).
+-define(wxStyledTextCtrl_IndicatorGetForeground, 3039).
+-define(wxStyledTextCtrl_SetWhitespaceForeground, 3040).
+-define(wxStyledTextCtrl_SetWhitespaceBackground, 3041).
+-define(wxStyledTextCtrl_GetStyleBits, 3042).
+-define(wxStyledTextCtrl_SetLineState, 3043).
+-define(wxStyledTextCtrl_GetLineState, 3044).
+-define(wxStyledTextCtrl_GetMaxLineState, 3045).
+-define(wxStyledTextCtrl_GetCaretLineVisible, 3046).
+-define(wxStyledTextCtrl_SetCaretLineVisible, 3047).
+-define(wxStyledTextCtrl_GetCaretLineBackground, 3048).
+-define(wxStyledTextCtrl_SetCaretLineBackground, 3049).
+-define(wxStyledTextCtrl_AutoCompShow, 3050).
+-define(wxStyledTextCtrl_AutoCompCancel, 3051).
+-define(wxStyledTextCtrl_AutoCompActive, 3052).
+-define(wxStyledTextCtrl_AutoCompPosStart, 3053).
+-define(wxStyledTextCtrl_AutoCompComplete, 3054).
+-define(wxStyledTextCtrl_AutoCompStops, 3055).
+-define(wxStyledTextCtrl_AutoCompSetSeparator, 3056).
+-define(wxStyledTextCtrl_AutoCompGetSeparator, 3057).
+-define(wxStyledTextCtrl_AutoCompSelect, 3058).
+-define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3059).
+-define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3060).
+-define(wxStyledTextCtrl_AutoCompSetFillUps, 3061).
+-define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3062).
+-define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3063).
+-define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3064).
+-define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3065).
+-define(wxStyledTextCtrl_UserListShow, 3066).
+-define(wxStyledTextCtrl_AutoCompSetAutoHide, 3067).
+-define(wxStyledTextCtrl_AutoCompGetAutoHide, 3068).
+-define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3069).
+-define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3070).
+-define(wxStyledTextCtrl_RegisterImage, 3071).
+-define(wxStyledTextCtrl_ClearRegisteredImages, 3072).
+-define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3073).
+-define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3074).
+-define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3075).
+-define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3076).
+-define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3077).
+-define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3078).
+-define(wxStyledTextCtrl_SetIndent, 3079).
+-define(wxStyledTextCtrl_GetIndent, 3080).
+-define(wxStyledTextCtrl_SetUseTabs, 3081).
+-define(wxStyledTextCtrl_GetUseTabs, 3082).
+-define(wxStyledTextCtrl_SetLineIndentation, 3083).
+-define(wxStyledTextCtrl_GetLineIndentation, 3084).
+-define(wxStyledTextCtrl_GetLineIndentPosition, 3085).
+-define(wxStyledTextCtrl_GetColumn, 3086).
+-define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3087).
+-define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3088).
+-define(wxStyledTextCtrl_SetIndentationGuides, 3089).
+-define(wxStyledTextCtrl_GetIndentationGuides, 3090).
+-define(wxStyledTextCtrl_SetHighlightGuide, 3091).
+-define(wxStyledTextCtrl_GetHighlightGuide, 3092).
+-define(wxStyledTextCtrl_GetLineEndPosition, 3093).
+-define(wxStyledTextCtrl_GetCodePage, 3094).
+-define(wxStyledTextCtrl_GetCaretForeground, 3095).
+-define(wxStyledTextCtrl_GetReadOnly, 3096).
+-define(wxStyledTextCtrl_SetCurrentPos, 3097).
+-define(wxStyledTextCtrl_SetSelectionStart, 3098).
+-define(wxStyledTextCtrl_GetSelectionStart, 3099).
+-define(wxStyledTextCtrl_SetSelectionEnd, 3100).
+-define(wxStyledTextCtrl_GetSelectionEnd, 3101).
+-define(wxStyledTextCtrl_SetPrintMagnification, 3102).
+-define(wxStyledTextCtrl_GetPrintMagnification, 3103).
+-define(wxStyledTextCtrl_SetPrintColourMode, 3104).
+-define(wxStyledTextCtrl_GetPrintColourMode, 3105).
+-define(wxStyledTextCtrl_FindText, 3106).
+-define(wxStyledTextCtrl_FormatRange, 3107).
+-define(wxStyledTextCtrl_GetFirstVisibleLine, 3108).
+-define(wxStyledTextCtrl_GetLine, 3109).
+-define(wxStyledTextCtrl_GetLineCount, 3110).
+-define(wxStyledTextCtrl_SetMarginLeft, 3111).
+-define(wxStyledTextCtrl_GetMarginLeft, 3112).
+-define(wxStyledTextCtrl_SetMarginRight, 3113).
+-define(wxStyledTextCtrl_GetMarginRight, 3114).
+-define(wxStyledTextCtrl_GetModify, 3115).
+-define(wxStyledTextCtrl_SetSelection, 3116).
+-define(wxStyledTextCtrl_GetSelectedText, 3117).
+-define(wxStyledTextCtrl_GetTextRange, 3118).
+-define(wxStyledTextCtrl_HideSelection, 3119).
+-define(wxStyledTextCtrl_LineFromPosition, 3120).
+-define(wxStyledTextCtrl_PositionFromLine, 3121).
+-define(wxStyledTextCtrl_LineScroll, 3122).
+-define(wxStyledTextCtrl_EnsureCaretVisible, 3123).
+-define(wxStyledTextCtrl_ReplaceSelection, 3124).
+-define(wxStyledTextCtrl_SetReadOnly, 3125).
+-define(wxStyledTextCtrl_CanPaste, 3126).
+-define(wxStyledTextCtrl_CanUndo, 3127).
+-define(wxStyledTextCtrl_EmptyUndoBuffer, 3128).
+-define(wxStyledTextCtrl_Undo, 3129).
+-define(wxStyledTextCtrl_Cut, 3130).
+-define(wxStyledTextCtrl_Copy, 3131).
+-define(wxStyledTextCtrl_Paste, 3132).
+-define(wxStyledTextCtrl_Clear, 3133).
+-define(wxStyledTextCtrl_SetText, 3134).
+-define(wxStyledTextCtrl_GetText, 3135).
+-define(wxStyledTextCtrl_GetTextLength, 3136).
+-define(wxStyledTextCtrl_GetOvertype, 3137).
+-define(wxStyledTextCtrl_SetCaretWidth, 3138).
+-define(wxStyledTextCtrl_GetCaretWidth, 3139).
+-define(wxStyledTextCtrl_SetTargetStart, 3140).
+-define(wxStyledTextCtrl_GetTargetStart, 3141).
+-define(wxStyledTextCtrl_SetTargetEnd, 3142).
+-define(wxStyledTextCtrl_GetTargetEnd, 3143).
+-define(wxStyledTextCtrl_ReplaceTarget, 3144).
+-define(wxStyledTextCtrl_SearchInTarget, 3145).
+-define(wxStyledTextCtrl_SetSearchFlags, 3146).
+-define(wxStyledTextCtrl_GetSearchFlags, 3147).
+-define(wxStyledTextCtrl_CallTipShow, 3148).
+-define(wxStyledTextCtrl_CallTipCancel, 3149).
+-define(wxStyledTextCtrl_CallTipActive, 3150).
+-define(wxStyledTextCtrl_CallTipPosAtStart, 3151).
+-define(wxStyledTextCtrl_CallTipSetHighlight, 3152).
+-define(wxStyledTextCtrl_CallTipSetBackground, 3153).
+-define(wxStyledTextCtrl_CallTipSetForeground, 3154).
+-define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3155).
+-define(wxStyledTextCtrl_CallTipUseStyle, 3156).
+-define(wxStyledTextCtrl_VisibleFromDocLine, 3157).
+-define(wxStyledTextCtrl_DocLineFromVisible, 3158).
+-define(wxStyledTextCtrl_WrapCount, 3159).
+-define(wxStyledTextCtrl_SetFoldLevel, 3160).
+-define(wxStyledTextCtrl_GetFoldLevel, 3161).
+-define(wxStyledTextCtrl_GetLastChild, 3162).
+-define(wxStyledTextCtrl_GetFoldParent, 3163).
+-define(wxStyledTextCtrl_ShowLines, 3164).
+-define(wxStyledTextCtrl_HideLines, 3165).
+-define(wxStyledTextCtrl_GetLineVisible, 3166).
+-define(wxStyledTextCtrl_SetFoldExpanded, 3167).
+-define(wxStyledTextCtrl_GetFoldExpanded, 3168).
+-define(wxStyledTextCtrl_ToggleFold, 3169).
+-define(wxStyledTextCtrl_EnsureVisible, 3170).
+-define(wxStyledTextCtrl_SetFoldFlags, 3171).
+-define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3172).
+-define(wxStyledTextCtrl_SetTabIndents, 3173).
+-define(wxStyledTextCtrl_GetTabIndents, 3174).
+-define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3175).
+-define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3176).
+-define(wxStyledTextCtrl_SetMouseDwellTime, 3177).
+-define(wxStyledTextCtrl_GetMouseDwellTime, 3178).
+-define(wxStyledTextCtrl_WordStartPosition, 3179).
+-define(wxStyledTextCtrl_WordEndPosition, 3180).
+-define(wxStyledTextCtrl_SetWrapMode, 3181).
+-define(wxStyledTextCtrl_GetWrapMode, 3182).
+-define(wxStyledTextCtrl_SetWrapVisualFlags, 3183).
+-define(wxStyledTextCtrl_GetWrapVisualFlags, 3184).
+-define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3185).
+-define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3186).
+-define(wxStyledTextCtrl_SetWrapStartIndent, 3187).
+-define(wxStyledTextCtrl_GetWrapStartIndent, 3188).
+-define(wxStyledTextCtrl_SetLayoutCache, 3189).
+-define(wxStyledTextCtrl_GetLayoutCache, 3190).
+-define(wxStyledTextCtrl_SetScrollWidth, 3191).
+-define(wxStyledTextCtrl_GetScrollWidth, 3192).
+-define(wxStyledTextCtrl_TextWidth, 3193).
+-define(wxStyledTextCtrl_GetEndAtLastLine, 3194).
+-define(wxStyledTextCtrl_TextHeight, 3195).
+-define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3196).
+-define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3197).
+-define(wxStyledTextCtrl_AppendText, 3198).
+-define(wxStyledTextCtrl_GetTwoPhaseDraw, 3199).
+-define(wxStyledTextCtrl_SetTwoPhaseDraw, 3200).
+-define(wxStyledTextCtrl_TargetFromSelection, 3201).
+-define(wxStyledTextCtrl_LinesJoin, 3202).
+-define(wxStyledTextCtrl_LinesSplit, 3203).
+-define(wxStyledTextCtrl_SetFoldMarginColour, 3204).
+-define(wxStyledTextCtrl_SetFoldMarginHiColour, 3205).
+-define(wxStyledTextCtrl_LineDown, 3206).
+-define(wxStyledTextCtrl_LineDownExtend, 3207).
+-define(wxStyledTextCtrl_LineUp, 3208).
+-define(wxStyledTextCtrl_LineUpExtend, 3209).
+-define(wxStyledTextCtrl_CharLeft, 3210).
+-define(wxStyledTextCtrl_CharLeftExtend, 3211).
+-define(wxStyledTextCtrl_CharRight, 3212).
+-define(wxStyledTextCtrl_CharRightExtend, 3213).
+-define(wxStyledTextCtrl_WordLeft, 3214).
+-define(wxStyledTextCtrl_WordLeftExtend, 3215).
+-define(wxStyledTextCtrl_WordRight, 3216).
+-define(wxStyledTextCtrl_WordRightExtend, 3217).
+-define(wxStyledTextCtrl_Home, 3218).
+-define(wxStyledTextCtrl_HomeExtend, 3219).
+-define(wxStyledTextCtrl_LineEnd, 3220).
+-define(wxStyledTextCtrl_LineEndExtend, 3221).
+-define(wxStyledTextCtrl_DocumentStart, 3222).
+-define(wxStyledTextCtrl_DocumentStartExtend, 3223).
+-define(wxStyledTextCtrl_DocumentEnd, 3224).
+-define(wxStyledTextCtrl_DocumentEndExtend, 3225).
+-define(wxStyledTextCtrl_PageUp, 3226).
+-define(wxStyledTextCtrl_PageUpExtend, 3227).
+-define(wxStyledTextCtrl_PageDown, 3228).
+-define(wxStyledTextCtrl_PageDownExtend, 3229).
+-define(wxStyledTextCtrl_EditToggleOvertype, 3230).
+-define(wxStyledTextCtrl_Cancel, 3231).
+-define(wxStyledTextCtrl_DeleteBack, 3232).
+-define(wxStyledTextCtrl_Tab, 3233).
+-define(wxStyledTextCtrl_BackTab, 3234).
+-define(wxStyledTextCtrl_NewLine, 3235).
+-define(wxStyledTextCtrl_FormFeed, 3236).
+-define(wxStyledTextCtrl_VCHome, 3237).
+-define(wxStyledTextCtrl_VCHomeExtend, 3238).
+-define(wxStyledTextCtrl_ZoomIn, 3239).
+-define(wxStyledTextCtrl_ZoomOut, 3240).
+-define(wxStyledTextCtrl_DelWordLeft, 3241).
+-define(wxStyledTextCtrl_DelWordRight, 3242).
+-define(wxStyledTextCtrl_LineCut, 3243).
+-define(wxStyledTextCtrl_LineDelete, 3244).
+-define(wxStyledTextCtrl_LineTranspose, 3245).
+-define(wxStyledTextCtrl_LineDuplicate, 3246).
+-define(wxStyledTextCtrl_LowerCase, 3247).
+-define(wxStyledTextCtrl_UpperCase, 3248).
+-define(wxStyledTextCtrl_LineScrollDown, 3249).
+-define(wxStyledTextCtrl_LineScrollUp, 3250).
+-define(wxStyledTextCtrl_DeleteBackNotLine, 3251).
+-define(wxStyledTextCtrl_HomeDisplay, 3252).
+-define(wxStyledTextCtrl_HomeDisplayExtend, 3253).
+-define(wxStyledTextCtrl_LineEndDisplay, 3254).
+-define(wxStyledTextCtrl_LineEndDisplayExtend, 3255).
+-define(wxStyledTextCtrl_HomeWrapExtend, 3256).
+-define(wxStyledTextCtrl_LineEndWrap, 3257).
+-define(wxStyledTextCtrl_LineEndWrapExtend, 3258).
+-define(wxStyledTextCtrl_VCHomeWrap, 3259).
+-define(wxStyledTextCtrl_VCHomeWrapExtend, 3260).
+-define(wxStyledTextCtrl_LineCopy, 3261).
+-define(wxStyledTextCtrl_MoveCaretInsideView, 3262).
+-define(wxStyledTextCtrl_LineLength, 3263).
+-define(wxStyledTextCtrl_BraceHighlight, 3264).
+-define(wxStyledTextCtrl_BraceBadLight, 3265).
+-define(wxStyledTextCtrl_BraceMatch, 3266).
+-define(wxStyledTextCtrl_GetViewEOL, 3267).
+-define(wxStyledTextCtrl_SetViewEOL, 3268).
+-define(wxStyledTextCtrl_SetModEventMask, 3269).
+-define(wxStyledTextCtrl_GetEdgeColumn, 3270).
+-define(wxStyledTextCtrl_SetEdgeColumn, 3271).
+-define(wxStyledTextCtrl_GetEdgeMode, 3272).
+-define(wxStyledTextCtrl_GetEdgeColour, 3273).
+-define(wxStyledTextCtrl_SetEdgeColour, 3274).
+-define(wxStyledTextCtrl_SearchAnchor, 3275).
+-define(wxStyledTextCtrl_SearchNext, 3276).
+-define(wxStyledTextCtrl_SearchPrev, 3277).
+-define(wxStyledTextCtrl_LinesOnScreen, 3278).
+-define(wxStyledTextCtrl_UsePopUp, 3279).
+-define(wxStyledTextCtrl_SelectionIsRectangle, 3280).
+-define(wxStyledTextCtrl_SetZoom, 3281).
+-define(wxStyledTextCtrl_GetZoom, 3282).
+-define(wxStyledTextCtrl_GetModEventMask, 3283).
+-define(wxStyledTextCtrl_SetSTCFocus, 3284).
+-define(wxStyledTextCtrl_GetSTCFocus, 3285).
+-define(wxStyledTextCtrl_SetStatus, 3286).
+-define(wxStyledTextCtrl_GetStatus, 3287).
+-define(wxStyledTextCtrl_SetMouseDownCaptures, 3288).
+-define(wxStyledTextCtrl_GetMouseDownCaptures, 3289).
+-define(wxStyledTextCtrl_SetSTCCursor, 3290).
+-define(wxStyledTextCtrl_GetSTCCursor, 3291).
+-define(wxStyledTextCtrl_SetControlCharSymbol, 3292).
+-define(wxStyledTextCtrl_GetControlCharSymbol, 3293).
+-define(wxStyledTextCtrl_WordPartLeft, 3294).
+-define(wxStyledTextCtrl_WordPartLeftExtend, 3295).
+-define(wxStyledTextCtrl_WordPartRight, 3296).
+-define(wxStyledTextCtrl_WordPartRightExtend, 3297).
+-define(wxStyledTextCtrl_SetVisiblePolicy, 3298).
+-define(wxStyledTextCtrl_DelLineLeft, 3299).
+-define(wxStyledTextCtrl_DelLineRight, 3300).
+-define(wxStyledTextCtrl_GetXOffset, 3301).
+-define(wxStyledTextCtrl_ChooseCaretX, 3302).
+-define(wxStyledTextCtrl_SetXCaretPolicy, 3303).
+-define(wxStyledTextCtrl_SetYCaretPolicy, 3304).
+-define(wxStyledTextCtrl_GetPrintWrapMode, 3305).
+-define(wxStyledTextCtrl_SetHotspotActiveForeground, 3306).
+-define(wxStyledTextCtrl_SetHotspotActiveBackground, 3307).
+-define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3308).
+-define(wxStyledTextCtrl_SetHotspotSingleLine, 3309).
+-define(wxStyledTextCtrl_ParaDownExtend, 3310).
+-define(wxStyledTextCtrl_ParaUp, 3311).
+-define(wxStyledTextCtrl_ParaUpExtend, 3312).
+-define(wxStyledTextCtrl_PositionBefore, 3313).
+-define(wxStyledTextCtrl_PositionAfter, 3314).
+-define(wxStyledTextCtrl_CopyRange, 3315).
+-define(wxStyledTextCtrl_CopyText, 3316).
+-define(wxStyledTextCtrl_SetSelectionMode, 3317).
+-define(wxStyledTextCtrl_GetSelectionMode, 3318).
+-define(wxStyledTextCtrl_LineDownRectExtend, 3319).
+-define(wxStyledTextCtrl_LineUpRectExtend, 3320).
+-define(wxStyledTextCtrl_CharLeftRectExtend, 3321).
+-define(wxStyledTextCtrl_CharRightRectExtend, 3322).
+-define(wxStyledTextCtrl_HomeRectExtend, 3323).
+-define(wxStyledTextCtrl_VCHomeRectExtend, 3324).
+-define(wxStyledTextCtrl_LineEndRectExtend, 3325).
+-define(wxStyledTextCtrl_PageUpRectExtend, 3326).
+-define(wxStyledTextCtrl_PageDownRectExtend, 3327).
+-define(wxStyledTextCtrl_StutteredPageUp, 3328).
+-define(wxStyledTextCtrl_StutteredPageUpExtend, 3329).
+-define(wxStyledTextCtrl_StutteredPageDown, 3330).
+-define(wxStyledTextCtrl_StutteredPageDownExtend, 3331).
+-define(wxStyledTextCtrl_WordLeftEnd, 3332).
+-define(wxStyledTextCtrl_WordLeftEndExtend, 3333).
+-define(wxStyledTextCtrl_WordRightEnd, 3334).
+-define(wxStyledTextCtrl_WordRightEndExtend, 3335).
+-define(wxStyledTextCtrl_SetWhitespaceChars, 3336).
+-define(wxStyledTextCtrl_SetCharsDefault, 3337).
+-define(wxStyledTextCtrl_AutoCompGetCurrent, 3338).
+-define(wxStyledTextCtrl_Allocate, 3339).
+-define(wxStyledTextCtrl_FindColumn, 3340).
+-define(wxStyledTextCtrl_GetCaretSticky, 3341).
+-define(wxStyledTextCtrl_SetCaretSticky, 3342).
+-define(wxStyledTextCtrl_ToggleCaretSticky, 3343).
+-define(wxStyledTextCtrl_SetPasteConvertEndings, 3344).
+-define(wxStyledTextCtrl_GetPasteConvertEndings, 3345).
+-define(wxStyledTextCtrl_SelectionDuplicate, 3346).
+-define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3347).
+-define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3348).
+-define(wxStyledTextCtrl_StartRecord, 3349).
+-define(wxStyledTextCtrl_StopRecord, 3350).
+-define(wxStyledTextCtrl_SetLexer, 3351).
+-define(wxStyledTextCtrl_GetLexer, 3352).
+-define(wxStyledTextCtrl_Colourise, 3353).
+-define(wxStyledTextCtrl_SetProperty, 3354).
+-define(wxStyledTextCtrl_SetKeyWords, 3355).
+-define(wxStyledTextCtrl_SetLexerLanguage, 3356).
+-define(wxStyledTextCtrl_GetProperty, 3357).
+-define(wxStyledTextCtrl_GetStyleBitsNeeded, 3358).
+-define(wxStyledTextCtrl_GetCurrentLine, 3359).
+-define(wxStyledTextCtrl_StyleSetSpec, 3360).
+-define(wxStyledTextCtrl_StyleSetFont, 3361).
+-define(wxStyledTextCtrl_StyleSetFontAttr, 3362).
+-define(wxStyledTextCtrl_StyleSetCharacterSet, 3363).
+-define(wxStyledTextCtrl_StyleSetFontEncoding, 3364).
+-define(wxStyledTextCtrl_CmdKeyExecute, 3365).
+-define(wxStyledTextCtrl_SetMargins, 3366).
+-define(wxStyledTextCtrl_GetSelection, 3367).
+-define(wxStyledTextCtrl_PointFromPosition, 3368).
+-define(wxStyledTextCtrl_ScrollToLine, 3369).
+-define(wxStyledTextCtrl_ScrollToColumn, 3370).
+-define(wxStyledTextCtrl_SendMsg, 3371).
+-define(wxStyledTextCtrl_SetVScrollBar, 3372).
+-define(wxStyledTextCtrl_SetHScrollBar, 3373).
+-define(wxStyledTextCtrl_GetLastKeydownProcessed, 3374).
+-define(wxStyledTextCtrl_SetLastKeydownProcessed, 3375).
+-define(wxStyledTextCtrl_SaveFile, 3376).
+-define(wxStyledTextCtrl_LoadFile, 3377).
+-define(wxStyledTextCtrl_DoDragOver, 3378).
+-define(wxStyledTextCtrl_DoDropText, 3379).
+-define(wxStyledTextCtrl_GetUseAntiAliasing, 3380).
+-define(wxStyledTextCtrl_AddTextRaw, 3381).
+-define(wxStyledTextCtrl_InsertTextRaw, 3382).
+-define(wxStyledTextCtrl_GetCurLineRaw, 3383).
+-define(wxStyledTextCtrl_GetLineRaw, 3384).
+-define(wxStyledTextCtrl_GetSelectedTextRaw, 3385).
+-define(wxStyledTextCtrl_GetTextRangeRaw, 3386).
+-define(wxStyledTextCtrl_SetTextRaw, 3387).
+-define(wxStyledTextCtrl_GetTextRaw, 3388).
+-define(wxStyledTextCtrl_AppendTextRaw, 3389).
+-define(wxArtProvider_GetBitmap, 3390).
+-define(wxArtProvider_GetIcon, 3391).
+-define(wxTreeEvent_GetKeyCode, 3392).
+-define(wxTreeEvent_GetItem, 3393).
+-define(wxTreeEvent_GetKeyEvent, 3394).
+-define(wxTreeEvent_GetLabel, 3395).
+-define(wxTreeEvent_GetOldItem, 3396).
+-define(wxTreeEvent_GetPoint, 3397).
+-define(wxTreeEvent_IsEditCancelled, 3398).
+-define(wxTreeEvent_SetToolTip, 3399).
+-define(wxNotebookEvent_GetOldSelection, 3400).
+-define(wxNotebookEvent_GetSelection, 3401).
+-define(wxNotebookEvent_SetOldSelection, 3402).
+-define(wxNotebookEvent_SetSelection, 3403).
+-define(wxFileDataObject_new, 3404).
+-define(wxFileDataObject_AddFile, 3405).
+-define(wxFileDataObject_GetFilenames, 3406).
+-define(wxFileDataObject_destroy, 3407).
+-define(wxTextDataObject_new, 3408).
+-define(wxTextDataObject_GetTextLength, 3409).
+-define(wxTextDataObject_GetText, 3410).
+-define(wxTextDataObject_SetText, 3411).
+-define(wxTextDataObject_destroy, 3412).
+-define(wxBitmapDataObject_new_1_1, 3413).
+-define(wxBitmapDataObject_new_1_0, 3414).
+-define(wxBitmapDataObject_GetBitmap, 3415).
+-define(wxBitmapDataObject_SetBitmap, 3416).
+-define(wxBitmapDataObject_destroy, 3417).
+-define(wxClipboard_new, 3419).
+-define(wxClipboard_destruct, 3420).
+-define(wxClipboard_AddData, 3421).
+-define(wxClipboard_Clear, 3422).
+-define(wxClipboard_Close, 3423).
+-define(wxClipboard_Flush, 3424).
+-define(wxClipboard_GetData, 3425).
+-define(wxClipboard_IsOpened, 3426).
+-define(wxClipboard_Open, 3427).
+-define(wxClipboard_SetData, 3428).
+-define(wxClipboard_UsePrimarySelection, 3430).
+-define(wxClipboard_IsSupported, 3431).
+-define(wxClipboard_Get, 3432).
+-define(wxSpinEvent_GetPosition, 3433).
+-define(wxSpinEvent_SetPosition, 3434).
+-define(wxSplitterWindow_new_0, 3435).
+-define(wxSplitterWindow_new_2, 3436).
+-define(wxSplitterWindow_destruct, 3437).
+-define(wxSplitterWindow_Create, 3438).
+-define(wxSplitterWindow_GetMinimumPaneSize, 3439).
+-define(wxSplitterWindow_GetSashGravity, 3440).
+-define(wxSplitterWindow_GetSashPosition, 3441).
+-define(wxSplitterWindow_GetSplitMode, 3442).
+-define(wxSplitterWindow_GetWindow1, 3443).
+-define(wxSplitterWindow_GetWindow2, 3444).
+-define(wxSplitterWindow_Initialize, 3445).
+-define(wxSplitterWindow_IsSplit, 3446).
+-define(wxSplitterWindow_ReplaceWindow, 3447).
+-define(wxSplitterWindow_SetSashGravity, 3448).
+-define(wxSplitterWindow_SetSashPosition, 3449).
+-define(wxSplitterWindow_SetSashSize, 3450).
+-define(wxSplitterWindow_SetMinimumPaneSize, 3451).
+-define(wxSplitterWindow_SetSplitMode, 3452).
+-define(wxSplitterWindow_SplitHorizontally, 3453).
+-define(wxSplitterWindow_SplitVertically, 3454).
+-define(wxSplitterWindow_Unsplit, 3455).
+-define(wxSplitterWindow_UpdateSize, 3456).
+-define(wxSplitterEvent_GetSashPosition, 3457).
+-define(wxSplitterEvent_GetX, 3458).
+-define(wxSplitterEvent_GetY, 3459).
+-define(wxSplitterEvent_GetWindowBeingRemoved, 3460).
+-define(wxSplitterEvent_SetSashPosition, 3461).
+-define(wxHtmlWindow_new_0, 3462).
+-define(wxHtmlWindow_new_2, 3463).
+-define(wxHtmlWindow_AppendToPage, 3464).
+-define(wxHtmlWindow_GetOpenedAnchor, 3465).
+-define(wxHtmlWindow_GetOpenedPage, 3466).
+-define(wxHtmlWindow_GetOpenedPageTitle, 3467).
+-define(wxHtmlWindow_GetRelatedFrame, 3468).
+-define(wxHtmlWindow_HistoryBack, 3469).
+-define(wxHtmlWindow_HistoryCanBack, 3470).
+-define(wxHtmlWindow_HistoryCanForward, 3471).
+-define(wxHtmlWindow_HistoryClear, 3472).
+-define(wxHtmlWindow_HistoryForward, 3473).
+-define(wxHtmlWindow_LoadFile, 3474).
+-define(wxHtmlWindow_LoadPage, 3475).
+-define(wxHtmlWindow_SelectAll, 3476).
+-define(wxHtmlWindow_SelectionToText, 3477).
+-define(wxHtmlWindow_SelectLine, 3478).
+-define(wxHtmlWindow_SelectWord, 3479).
+-define(wxHtmlWindow_SetBorders, 3480).
+-define(wxHtmlWindow_SetFonts, 3481).
+-define(wxHtmlWindow_SetPage, 3482).
+-define(wxHtmlWindow_SetRelatedFrame, 3483).
+-define(wxHtmlWindow_SetRelatedStatusBar, 3484).
+-define(wxHtmlWindow_ToText, 3485).
+-define(wxHtmlWindow_destroy, 3486).
+-define(wxHtmlLinkEvent_GetLinkInfo, 3487).
+-define(wxSystemSettings_GetColour, 3488).
+-define(wxSystemSettings_GetFont, 3489).
+-define(wxSystemSettings_GetMetric, 3490).
+-define(wxSystemSettings_GetScreenType, 3491).
+-define(wxAuiNotebookEvent_SetSelection, 3492).
+-define(wxAuiNotebookEvent_GetSelection, 3493).
+-define(wxAuiNotebookEvent_SetOldSelection, 3494).
+-define(wxAuiNotebookEvent_GetOldSelection, 3495).
+-define(wxAuiNotebookEvent_SetDragSource, 3496).
+-define(wxAuiNotebookEvent_GetDragSource, 3497).
+-define(wxAuiManagerEvent_SetManager, 3498).
+-define(wxAuiManagerEvent_GetManager, 3499).
+-define(wxAuiManagerEvent_SetPane, 3500).
+-define(wxAuiManagerEvent_GetPane, 3501).
+-define(wxAuiManagerEvent_SetButton, 3502).
+-define(wxAuiManagerEvent_GetButton, 3503).
+-define(wxAuiManagerEvent_SetDC, 3504).
+-define(wxAuiManagerEvent_GetDC, 3505).
+-define(wxAuiManagerEvent_Veto, 3506).
+-define(wxAuiManagerEvent_GetVeto, 3507).
+-define(wxAuiManagerEvent_SetCanVeto, 3508).
+-define(wxAuiManagerEvent_CanVeto, 3509).
+-define(wxLogNull_new, 3510).
+-define(wxLogNull_destroy, 3511).
diff --git a/lib/wx/src/wx.appup.src b/lib/wx/src/wx.appup.src
index c02edd2afb..1102af612e 100644
--- a/lib/wx/src/wx.appup.src
+++ b/lib/wx/src/wx.appup.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
%%
%% The 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,5 +18,6 @@
%% %CopyrightEnd%
{"%VSN%",
+ [ ],
[ ]
}.
diff --git a/lib/wx/src/wx_object.erl b/lib/wx/src/wx_object.erl
index bfd38960dd..82c4cfbad5 100644
--- a/lib/wx/src/wx_object.erl
+++ b/lib/wx/src/wx_object.erl
@@ -537,16 +537,16 @@ error_info(_Reason, application_controller, _Msg, _State, _Debug) ->
error_info(Reason, Name, Msg, State, Debug) ->
Reason1 =
case Reason of
- {undef,[{M,F,A}|MFAs]} ->
+ {undef,[{M,F,A,L}|MFAs]} ->
case code:is_loaded(M) of
false ->
- {'module could not be loaded',[{M,F,A}|MFAs]};
+ {'module could not be loaded',[{M,F,A,L}|MFAs]};
_ ->
case erlang:function_exported(M, F, length(A)) of
true ->
Reason;
false ->
- {'function not exported',[{M,F,A}|MFAs]}
+ {'function not exported',[{M,F,A,L}|MFAs]}
end
end;
_ ->
diff --git a/lib/wx/src/wxe_server.erl b/lib/wx/src/wxe_server.erl
index 40412987a5..69e2189fac 100644
--- a/lib/wx/src/wxe_server.erl
+++ b/lib/wx/src/wxe_server.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, 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 : wxe_server.erl
@@ -24,7 +24,7 @@
%%% Created : 17 Jan 2007 by Dan Gudmundsson <[email protected]>
%%%-------------------------------------------------------------------
-%% @hidden
+%% @hidden
-module(wxe_server).
-behaviour(gen_server).
@@ -65,7 +65,7 @@ start() ->
end;
Env = #wx_env{sv=Pid} ->
case erlang:is_process_alive(Pid) of
- true ->
+ true ->
Env;
false -> %% Ok we got an old wx env, someone forgot
erase(?WXE_IDENTIFIER), %% to call wx:destroy()
@@ -94,7 +94,7 @@ init([]) ->
{ok,#state{port=Port, cb_port=CBPort,
users=gb_trees:empty(), cb=gb_trees:empty(), cb_cnt=1}}.
-%% Register process
+%% Register process
handle_call(register_me, {From,_}, State=#state{users=Users}) ->
erlang:monitor(process, From),
case gb_trees:is_defined(From, Users) of
@@ -147,7 +147,7 @@ handle_cast({debug, Level}, State) ->
put(?WXE_IDENTIFIER, Env#wx_env{debug=Level}),
{noreply, State};
-handle_cast(_Msg, State) ->
+handle_cast(_Msg, State) ->
?log("Unknown message ~p sent to ~p~n",[_Msg, ?MODULE]),
{noreply, State}.
@@ -156,7 +156,7 @@ handle_cast(_Msg, State) ->
%% Callback request from driver
handle_info(Cb = {_, _, '_wx_invoke_cb_'}, State) ->
invoke_cb(Cb, State),
- {noreply, State};
+ {noreply, State};
handle_info({wx_delete_cb, FunId}, State0 = #state{cb=CB}) when is_integer(FunId) ->
case get(FunId) of
undefined ->
@@ -166,7 +166,7 @@ handle_info({wx_delete_cb, FunId}, State0 = #state{cb=CB}) when is_integer(FunId
{noreply, State0#state{cb=gb_trees:delete(Fun, CB)}}
end;
handle_info({'DOWN',_,process,Pid,_}, State=#state{users=Users0,cleaners=Cs}) ->
- try
+ try
User = gb_trees:get(Pid,Users0),
Users = gb_trees:delete(Pid,Users0),
Env = wx:get_env(),
@@ -210,7 +210,7 @@ handle_connect(Object, EvData, From, State0 = #state{users=Users}) ->
case Handler0 of
#wx_ref{} when Callback =:= 0 ->
CBHandler = Handler0,
- Handler = Handler0;
+ Handler = Handler0;
undefined when Callback =:= 0 ->
Handler = new_evt_listener(State0),
CBHandler = Handler;
@@ -225,7 +225,7 @@ handle_connect(Object, EvData, From, State0 = #state{users=Users}) ->
{FunId, State} = attach_fun(Callback,State1),
Res = wxEvtHandler:connect_impl(CBHandler,Object,
wxEvtHandler:replace_fun_with_id(EvData,FunId)),
- case Res of
+ case Res of
ok -> {reply,Res,State};
_Error -> {reply,Res,State0}
end;
@@ -238,11 +238,7 @@ invoke_cb({{Ev=#wx{}, Ref=#wx_ref{}}, FunId,_}, _S) ->
%% Event callbacks
case get(FunId) of
Fun when is_function(Fun) ->
- invoke_callback(fun() ->
- wxe_util:cast(?WXE_CB_START, <<>>),
- Fun(Ev, Ref),
- <<>>
- end);
+ invoke_callback(fun() -> Fun(Ev, Ref), <<>> end);
Err ->
?log("Internal Error ~p~n",[Err])
end;
@@ -254,12 +250,14 @@ invoke_cb({FunId, Args, _}, _S) when is_list(Args), is_integer(FunId) ->
Err ->
?log("Internal Error ~p ~p ~p~n",[Err, FunId, Args])
end.
-
+
invoke_callback(Fun) ->
Env = get(?WXE_IDENTIFIER),
CB = fun() ->
wx:set_env(Env),
- Res = try Return = Fun(),
+ wxe_util:cast(?WXE_CB_START, <<>>),
+ Res = try
+ Return = Fun(),
true = is_binary(Return),
Return
catch _:Reason ->
@@ -278,9 +276,9 @@ new_evt_listener(State) ->
get_result(State).
get_result(_State) ->
- receive
+ receive
{'_wxe_result_', Res} -> Res;
- {'_wxe_error_', Op, Error} ->
+ {'_wxe_error_', Op, Error} ->
erlang:error({Error, {wxEvtHandler, {internal_installer, Op}}})
end.
@@ -289,7 +287,7 @@ attach_fun(Fun, S = #state{cb=CB,cb_cnt=Next}) ->
{value, ID} ->
{ID,S};
none ->
- put(Next,Fun),
+ put(Next,Fun),
{Next,S#state{cb=gb_trees:insert(Fun,Next,CB),cb_cnt=Next+1}}
end.
@@ -297,7 +295,7 @@ handle_disconnect(Object, Evh, From, State0 = #state{users=Users0}) ->
User0 = #user{events=Evs0, evt_handler=PidH} = gb_trees:get(From, Users0),
Fun = wxEvtHandler:get_callback(Evh),
case find_handler(Evs0, Object, Fun) of
- [] ->
+ [] ->
{reply, false, State0};
Handlers ->
case disconnect(Object,Evh, Handlers) of
@@ -310,7 +308,7 @@ handle_disconnect(Object, Evh, From, State0 = #state{users=Users0}) ->
[] when PidH =/= undefined ->
wxEvtHandler:destroy_evt_listener(PidH),
User0#user{events=[], evt_handler=undefined};
- Evs ->
+ Evs ->
User0#user{events=Evs}
end,
{reply, true, State0#state{users=gb_trees:update(From,User,Users0)}};
@@ -345,7 +343,7 @@ find_handler([],_Object,_Fun,Res) ->
%% Cleanup
-%% The server handles callbacks from driver so every other wx call must
+%% The server handles callbacks from driver so every other wx call must
%% be called from another process, therefore the cleaning must be spawned.
%%
cleanup(Env, _Pid, Data) ->
@@ -358,7 +356,7 @@ cleanup(#user{objects=_Os,events=Evs, evt_handler=Handler}) ->
lists:foreach(fun(#event{object=_O, callback=CB, cb_handler=CbH}) ->
%%catch wxEvtHandler:disconnect_impl(CbH,O),
case is_function(CB) of
- true ->
+ true ->
wxEvtHandler:destroy_evt_listener(CbH);
false ->
ignore
diff --git a/lib/wx/test/wx_class_SUITE.erl b/lib/wx/test/wx_class_SUITE.erl
index 79e6833e9b..b75b0cc74e 100644
--- a/lib/wx/test/wx_class_SUITE.erl
+++ b/lib/wx/test/wx_class_SUITE.erl
@@ -18,14 +18,14 @@
%%%-------------------------------------------------------------------
%%% File : wx_class_SUITE.erl
%%% Author : Dan Gudmundsson <[email protected]>
-%%% Description :
+%%% Description :
%%%
%%% Created : 13 Nov 2008 by Dan Gudmundsson <[email protected]>
%%%-------------------------------------------------------------------
-module(wx_class_SUITE).
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
- init_per_suite/1, end_per_suite/1,
+-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
+ init_per_suite/1, end_per_suite/1,
init_per_testcase/2, end_per_testcase/2]).
-compile(export_all).
@@ -41,18 +41,18 @@ end_per_suite(Config) ->
init_per_testcase(Func,Config) ->
wx_test_lib:init_per_testcase(Func,Config).
-end_per_testcase(Func,Config) ->
+end_per_testcase(Func,Config) ->
wx_test_lib:end_per_testcase(Func,Config).
%% SUITE specification
suite() -> [{ct_hooks,[ts_install_cth]}].
-all() ->
+all() ->
[calendarCtrl, treeCtrl, notebook, staticBoxSizer,
- clipboard, helpFrame, htmlWindow, listCtrlSort,
+ clipboard, helpFrame, htmlWindow, listCtrlSort, listCtrlVirtual,
radioBox, systemSettings].
-groups() ->
+groups() ->
[].
init_per_group(_GroupName, Config) ->
@@ -70,9 +70,9 @@ calendarCtrl(Config) ->
Frame = ?mt(wxFrame, wxFrame:new(Wx, 1, "Calendar", [])),
Panel = wxPanel:new(Frame),
Sz = wxBoxSizer:new(?wxVERTICAL),
-
+
{YMD={_,_,Day},_} = DateTime = calendar:now_to_datetime(erlang:now()),
- Cal = ?mt(wxCalendarCtrl, wxCalendarCtrl:new(Panel, ?wxID_ANY,
+ Cal = ?mt(wxCalendarCtrl, wxCalendarCtrl:new(Panel, ?wxID_ANY,
[{date,DateTime}
])),
wxSizer:add(Sz,Cal),
@@ -91,25 +91,25 @@ calendarCtrl(Config) ->
?m({0,243,0,255}, wxCalendarDateAttr:getBackgroundColour(DateAttr1)),
?m({YMD, _},wxCalendarCtrl:getDate(Cal)),
-
- wxCalendarCtrl:connect(Cal, calendar_weekday_clicked),
- wxCalendarCtrl:connect(Cal, calendar_day_changed),
- wxCalendarCtrl:connect(Cal, calendar_month_changed),
+
+ wxCalendarCtrl:connect(Cal, calendar_weekday_clicked),
+ wxCalendarCtrl:connect(Cal, calendar_day_changed),
+ wxCalendarCtrl:connect(Cal, calendar_month_changed),
wxCalendarCtrl:connect(Cal, calendar_year_changed),
- wxCalendarCtrl:connect(Cal, calendar_doubleclicked),
+ wxCalendarCtrl:connect(Cal, calendar_doubleclicked),
wxCalendarCtrl:connect(Cal, calendar_sel_changed),
-
+
wxWindow:setSizer(Panel,Sz),
wxSizer:setSizeHints(Sz,Frame),
- wxWindow:show(Frame),
-
+ wxWindow:show(Frame),
+
wx_test_lib:wx_destroy(Frame,Config).
treeCtrl(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
treeCtrl(Config) ->
Wx = wx:new(),
-
+
Frame = wxFrame:new(Wx, ?wxID_ANY, "Frame"),
Panel = wxPanel:new(Frame, []),
Tree = ?mt(wxTreeCtrl,wxTreeCtrl:new(Panel, [{style , ?wxTR_HAS_BUTTONS}])),
@@ -122,25 +122,25 @@ treeCtrl(Config) ->
?m(ok, wxTreeCtrl:setItemData(Tree, Item2, {data, item2})),
Item3 = wxTreeCtrl:appendItem(Tree, Root, "Item3", []),
?m(ok, wxTreeCtrl:setItemData(Tree, Item3, {data, item3})),
-
+
Sizer = wxBoxSizer:new(?wxVERTICAL),
wxSizer:add(Sizer, Tree, [{flag, ?wxEXPAND}, {proportion, 1}]),
wxWindow:setSizerAndFit(Panel, Sizer),
wxFrame:show(Frame),
-
+
?m([], wxTreeCtrl:getItemData(Tree, Root)),
?m({data,item1}, wxTreeCtrl:getItemData(Tree, Item1)),
?m({data,item2}, wxTreeCtrl:getItemData(Tree, Item2)),
?m({data,item3}, wxTreeCtrl:getItemData(Tree, Item3)),
-
+
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).
notebook(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
@@ -210,13 +210,13 @@ staticBoxSizer(Config) ->
Frame = wxFrame:new(Wx, ?wxID_ANY, "Frame"),
Panel = wxPanel:new(Frame, []),
InclSizer = ?mt(wxStaticBoxSizer,
- wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ wxStaticBoxSizer:new(?wxVERTICAL, Panel,
[{label, "Module inclusion policy"}])),
Sizer = wxBoxSizer:new(?wxVERTICAL),
wxSizer:add(Sizer, InclSizer,
[{border, 2}, {flag, ?wxALL bor ?wxEXPAND}, {proportion, 1}]),
- wxWindow:setSizerAndFit(Panel, Sizer),
-
+ wxWindow:setSizerAndFit(Panel, Sizer),
+
wxWindow:show(Frame),
wx_test_lib:wx_destroy(Frame,Config).
@@ -263,13 +263,13 @@ clipboard(_Config) ->
wxClipboard:flush(CB),
?log("Stopping ~n",[]),
ok.
-
+
helpFrame(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
helpFrame(Config) ->
Wx = wx:new(),
MFrame = wx:batch(fun() ->
MFrame = wxFrame:new(Wx, ?wxID_ANY, "Main Frame"),
- wxPanel:new(MFrame, [{size, {600,400}}]),
+ wxPanel:new(MFrame, [{size, {600,400}}]),
wxWindow:show(MFrame),
MFrame
end),
@@ -279,11 +279,11 @@ helpFrame(Config) ->
{X, Y, W,H} = wxWindow:getScreenRect(MFrame),
io:format("Pos0: ~p ~p ~p Pos: ~p:~p Size: ~p:~p ~n",
[X0,Y0, wxWindow:clientToScreen(MFrame, {0,0}), X,Y,W,H]),
-
+
Pos = {X+5, Y+(H div 2)},
Size = {W-10, (H div 2) - 5},
- Comp = wxFrame:new(MFrame, ?wxID_ANY, "Completion Window",
+ Comp = wxFrame:new(MFrame, ?wxID_ANY, "Completion Window",
[{pos, Pos}, {size, Size},
{style, ?wxFRAME_FLOAT_ON_PARENT}]),
LB = wxListBox:new(Comp, 42, [{style, ?wxLB_SINGLE},
@@ -301,7 +301,7 @@ htmlWindow(Config) ->
{MFrame,HPanel} =
wx:batch(fun() ->
MFrame = wxFrame:new(Wx, ?wxID_ANY, "Main Frame"),
- HPanel = wxHtmlWindow:new(MFrame, [{size, {600,400}}]),
+ HPanel = wxHtmlWindow:new(MFrame, [{size, {600,400}}]),
wxWindow:show(MFrame),
{MFrame, HPanel}
end),
@@ -310,7 +310,7 @@ htmlWindow(Config) ->
WxMod = code:which(wx),
WxDir = filename:split(filename:dirname(WxMod)) -- ["ebin"],
Html = filename:join(filename:join(WxDir),filename:join("doc", "html")),
-
+
Index = filename:join(Html, "wx.html"),
?m(ok, wxHtmlWindow:connect(HPanel, command_html_link_clicked,
@@ -318,7 +318,7 @@ htmlWindow(Config) ->
fun(Ev,_) ->
io:format("Link clicked: ~p~n",[Ev])
end}])),
-
+
case filelib:is_file(Index) of
true ->
?m(true, wxHtmlWindow:loadFile(HPanel, Index)),
@@ -326,7 +326,7 @@ htmlWindow(Config) ->
false ->
ok
end,
-
+
wx_test_lib:wx_destroy(MFrame,Config).
@@ -334,18 +334,18 @@ listCtrlSort(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
listCtrlSort(Config) ->
Wx = wx:new(),
Frame = wxFrame:new(Wx, ?wxID_ANY, "Frame"),
-
+
LC = wxListCtrl:new(Frame, [{style, ?wxLC_REPORT bor ?wxLC_SORT_ASCENDING}]),
%% must be done crashes in wxwidgets otherwise.
wxListCtrl:insertColumn(LC, 0, "Column"),
-
- Add = fun(Int) ->
+
+ Add = fun(Int) ->
wxListCtrl:insertItem(LC, Int, integer_to_list(Int)),
%% ItemData Can only be integers currently
wxListCtrl:setItemData(LC, Int, abs(2500-Int))
end,
-
+
wx:foreach(Add, lists:seq(0,5000)),
wxWindow:show(Frame),
@@ -360,10 +360,10 @@ listCtrlSort(Config) ->
end
end)
end,
-
+
Time = timer:tc(erlang, apply, [Sort,[]]),
io:format("Sorted ~p ~n",[Time]),
-
+
Item = wxListItem:new(),
_List = wx:map(fun(Int) ->
wxListItem:setId(Item, Int),
@@ -374,6 +374,48 @@ listCtrlSort(Config) ->
wx_test_lib:wx_destroy(Frame,Config).
+listCtrlVirtual(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
+listCtrlVirtual(Config) ->
+ Wx = wx:new(),
+ Frame = wxFrame:new(Wx, ?wxID_ANY, "Frame"),
+ IA = wxListItemAttr:new(),
+ wxListItemAttr:setTextColour(IA, {190, 25, 25}),
+ LC = wxListCtrl:new(Frame,
+ [{style, ?wxLC_REPORT bor ?wxLC_VIRTUAL},
+ {onGetItemText, fun(_This, Item, 0) ->
+ "Row " ++ integer_to_list(Item);
+ (_, Item, 1) when Item rem 5 == 0 ->
+ "Column 2";
+ (_, _, _) -> ""
+ end},
+ {onGetItemAttr, fun(_This, Item) when Item rem 3 == 0 ->
+ IA;
+ (_This, _Item) ->
+ wx:typeCast(wx:null(), wxListItemAttr)
+ end},
+ {onGetItemColumnImage, fun(_This, Item, 1) ->
+ Item rem 4;
+ (_, _, _) ->
+ -1
+ end}
+ ]),
+
+ IL = wxImageList:new(16,16),
+ wxImageList:add(IL, wxArtProvider:getBitmap("wxART_COPY", [{size, {16,16}}])),
+ wxImageList:add(IL, wxArtProvider:getBitmap("wxART_MISSING_IMAGE", [{size, {16,16}}])),
+ wxImageList:add(IL, wxArtProvider:getBitmap("wxART_TICK_MARK", [{size, {16,16}}])),
+ wxImageList:add(IL, wxArtProvider:getBitmap("wxART_CROSS_MARK", [{size, {16,16}}])),
+ wxListCtrl:assignImageList(LC, IL, ?wxIMAGE_LIST_SMALL),
+
+ wxListCtrl:insertColumn(LC, 0, "Column 1"),
+ wxListCtrl:insertColumn(LC, 1, "Column 2"),
+ wxListCtrl:setColumnWidth(LC, 0, 200),
+ wxListCtrl:setColumnWidth(LC, 1, 200),
+ wxListCtrl:setItemCount(LC, 1000000),
+
+ wxWindow:show(Frame),
+ wx_test_lib:wx_destroy(Frame,Config).
+
radioBox(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
radioBox(Config) ->
@@ -382,7 +424,7 @@ radioBox(Config) ->
TrSortRadioBox = wxRadioBox:new(Frame, ?wxID_ANY, "Sort by:",
{100, 100},{100, 100}, ["Timestamp"]),
-
+
io:format("TrSortRadioBox ~p ~n", [TrSortRadioBox]),
%% If I uncomment any of these lines, it will crash
@@ -398,7 +440,7 @@ systemSettings(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo)
systemSettings(Config) ->
Wx = wx:new(),
Frame = wxFrame:new(Wx, ?wxID_ANY, "Frame"),
-
+
?m({_,_,_,_}, wxSystemSettings:getColour(?wxSYS_COLOUR_DESKTOP)),
?mt(wxFont, wxSystemSettings:getFont(?wxSYS_SYSTEM_FONT)),
?m(true, is_integer(wxSystemSettings:getMetric(?wxSYS_MOUSE_BUTTONS))),
@@ -406,3 +448,25 @@ systemSettings(Config) ->
wxWindow:show(Frame),
wx_test_lib:wx_destroy(Frame,Config).
+
+
+textCtrl(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
+textCtrl(Config) ->
+ Wx = wx:new(),
+ Frame = wxFrame:new(Wx, ?wxID_ANY, "Frame"),
+
+ TC = ?mt(wxTextCtrl, wxTextCtrl:new(Frame, ?wxID_ANY, [{style, ?wxTE_MULTILINE bor ?wxTE_RICH2}])),
+ wxTextCtrl:appendText(TC, "This line is in default color\n"),
+ Attr = ?mt(wxTextAttr, wxTextAttr:new(?wxRED)),
+ wxTextCtrl:setDefaultStyle(TC, Attr),
+ wxTextCtrl:appendText(TC, "This line is in ?wxRED color\n"),
+ wxTextAttr:setTextColour(Attr, ?wxBLACK),
+ wxTextCtrl:setDefaultStyle(TC, Attr),
+ wxTextCtrl:appendText(TC, "This line is in ?wxBLACK color\n"),
+ Default = wxSystemSettings:getColour(?wxSYS_COLOUR_WINDOWTEXT),
+ wxTextAttr:setTextColour(Attr, Default),
+ wxTextCtrl:setDefaultStyle(TC, Attr),
+ wxTextCtrl:appendText(TC, "This line is in default color\n"),
+ wxTextAttr:destroy(Attr),
+ wxWindow:show(Frame),
+ wx_test_lib:wx_destroy(Frame,Config).
diff --git a/lib/wx/test/wxt.erl b/lib/wx/test/wxt.erl
index 1f5b1cc3b1..c14d3f8647 100644
--- a/lib/wx/test/wxt.erl
+++ b/lib/wx/test/wxt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -72,7 +72,7 @@ resolve({Suite0, Case}) when is_atom(Suite0), is_atom(Case) ->
{Suite, Case2} ->
{Suite, Case2}
end;
-resolve(List) when list(List) ->
+resolve(List) when is_list(List) ->
[resolve(Case) || Case <- List].
alias(Suite) when is_atom(Suite) ->
@@ -104,7 +104,7 @@ read_config() ->
end.
%% Write new default config file
-write_config(Config) when list(Config) ->
+write_config(Config) when is_list(Config) ->
Fname = config_fname(),
{ok, Fd} = file:open(Fname, write),
write_list(Fd, Config),
diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk
index 7c440a7f5b..8685c633d4 100644
--- a/lib/wx/vsn.mk
+++ b/lib/wx/vsn.mk
@@ -1 +1 @@
-WX_VSN = 0.98.9
+WX_VSN = 0.99
diff --git a/lib/xmerl/doc/examples/Makefile b/lib/xmerl/doc/examples/Makefile
new file mode 100644
index 0000000000..2768ee1985
--- /dev/null
+++ b/lib/xmerl/doc/examples/Makefile
@@ -0,0 +1,61 @@
+ERLC = erlc
+EMULATOR = beam
+EBIN = .
+HTML = .
+XML = ./xml
+RM = rm -f
+
+# ----------------------------------------------------
+# Common Macros
+# ----------------------------------------------------
+include ../../vsn.mk
+VSN = $(XMERL_VSN)
+
+
+MODULES = \
+ xmerl_test \
+ test_html \
+ xserl_test \
+ mkdocs \
+ sdocbook2xhtml
+
+
+
+DOC_FILES = $(DOCS:%=$(HTML)/%.html)
+
+ERL_COMPILE_FLAGS += $(DEBUG) -I ../../include +warn_unused_wars +debug_info
+
+SUB_DIRECTORIES =
+
+#all: $(MODULES:%=$(EBIN)/%.$(EMULATOR)) xsm $(DOC_FILES)
+all opt: $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(DOC_FILES)
+
+info:
+ @echo "DOC_FILES: $(DOC_FILES)"
+
+clean:
+# @for d in $(SUB_DIRECTORIES); do \
+# cd $$d; $(MAKE) clean; \
+# done
+ $(RM) $(HTML)/*.html
+ $(RM) $(EBIN)/*.beam
+ $(RM) core *~
+
+debug: xsmdebug $(DOC_FILES)
+
+xsm:
+ @for d in $(SUB_DIRECTORIES); do \
+ cd $$d; $(MAKE); \
+ done
+
+xsmdebug:
+ @for d in $(SUB_DIRECTORIES); do \
+ cd $$d; $(MAKE) DEBUG=-Ddebug=1; \
+ done
+
+$(HTML)/%.html: $(XML)/%.xml
+ erl -noshell -pa ../../ebin -run mkdocs run $< $@ -s erlang halt
+
+$(EBIN)/%.beam: %.erl
+ $(ERLC) $(ERL_COMPILE_FLAGS) -o $(EBIN) $<
+
diff --git a/lib/xmerl/doc/examples/mkdocs.erl b/lib/xmerl/doc/examples/mkdocs.erl
new file mode 100644
index 0000000000..9faa12685b
--- /dev/null
+++ b/lib/xmerl/doc/examples/mkdocs.erl
@@ -0,0 +1,9 @@
+-module(mkdocs).
+-author('[email protected]').
+
+-export([run/1]).
+
+run([InFile, OutFile])->
+ {A,_}=xmerl_scan:file(InFile,[{fetch_fun, fun(DTDSpec,S) -> {ok,S} end}]),
+ B = sdocbook2xhtml:process_xml(A),
+ file:write_file(OutFile,[B]).
diff --git a/lib/xmerl/doc/examples/sdocbook2xhtml.erl b/lib/xmerl/doc/examples/sdocbook2xhtml.erl
new file mode 100644
index 0000000000..f96bf51963
--- /dev/null
+++ b/lib/xmerl/doc/examples/sdocbook2xhtml.erl
@@ -0,0 +1,823 @@
+%%%----------------------------------------------------------------------
+%%% File : sdocbook2xhtml.erl
+%%% Description : Erlang XSLT like "stylesheet" for exporting
+%%% Simplified Docbook XML to XHTML.
+%%%
+%%% Modules used : lists, io_lib, xmerl, xmerl_lib, xmerl_xs
+%%%
+%%%----------------------------------------------------------------------
+
+-module(sdocbook2xhtml).
+-author('[email protected]').
+
+
+-include("xmerl.hrl").
+-import(xmerl_lib, [markup/3,mapxml/2, foldxml/3, mapfoldxml/3]).
+-import(xmerl_xs, [ xslapply/2, value_of/1, select/2, built_in_rules/2]).
+
+-export([ process_xml/1 ]).
+
+-export([abbrev/4,
+ abstract/4,
+ acronym/4,
+ address/4,
+ anchor/4,
+ appendix/4,
+ appendixinfo/4,
+ article/4,
+ articleinfo/4,
+ audiodata/4,
+ audioobject/4,
+ author/4,
+ authorgroup/4,
+ authorinitials/4,
+ bibliography/4,
+ bibliomixed/4,
+ bibliomisc/4,
+ bibliomset/4,
+ biblioset/4,
+ blockquote/4,
+ caption/4,
+ citetitle/4,
+ city/4,
+ colspec/4,
+ command/4,
+ computeroutput/4,
+ copyright/4,
+ corpauthor/4,
+ country/4,
+ date/4,
+ edition/4,
+ editor/4,
+ email/4,
+ emphasis/4,
+ entry/4,
+ example/4,
+ fax/4,
+ figure/4,
+ filename/4,
+ firstname/4,
+ footnote/4,
+ holder/4,
+ honorific/4,
+ imagedata/4,
+ imageobject/4,
+ informaltable/4,
+ inlinemediaobject/4,
+ isbn/4,
+ issn/4,
+ issuenum/4,
+ legalnotice/4,
+ lineage/4,
+ link/4,
+ literal/4,
+ itemizedlist/4,
+ listitem/4,
+ mediaobject/4,
+ member/4,
+ note/4,
+ orderedlist/4,
+ othercredit/4,
+ othername/4,
+ para/4,
+ phone/4,
+ phrase/4,
+ programlisting/4,
+ publishername/4,
+ quote/4,
+ replaceable/4,
+ revhistory/4,
+ revision/4,
+ revnumber/4,
+ revremark/4,
+ row/4,
+ section/4,
+ sectioninfo/4,
+ simplelist/4,
+ subtitle/4,
+ surname/4,
+ systemitem/4,
+ table/4,
+ tbody/4,
+ term/4,
+ tfoot/4,
+ tgroup/4,
+ thead/4,
+ title/4,
+ titleabbrev/4,
+ trademark/4,
+ ulink/4,
+ userinput/4,
+ variablelist/4,
+ varlistentry/4,
+ xref/4,
+ year/4
+ ]).
+
+
+xmlhead() -> "<\?xml version=\"1.0\" encoding=\"iso-8859-1\"\?>".
+doctype() ->"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\
+ \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd \">\n".
+
+style() ->
+ "<style type=\"text/css\"> body {margin-left:10%; margin-right:5%;} \
+.logo{float:right;}
+.toc UL {
+ list-style-type: none;
+ border: solid;
+ border-width: thin;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ background: #f0f0f0;
+ letter-spacing: 2px;
+ line-height: 20px;
+}
+</style>".
+
+process_xml(E)->
+%% lists:flatten(template( E )).
+ template( E ).
+
+%% article is the root element
+template(E0 = #xmlElement{name=article})->
+
+ E = changetitle(E0), %% Add section numbering to titles
+
+ [ xmlhead(), doctype(),
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\" >"
+ "<head>"
+ "<title>",
+ value_of(select("articleinfo/title",E)),
+ "</title>",
+ style(),
+ "</head>"
+ "<body>",
+%% "<img src=\"/logo.png\" alt=\"no logo\" class=\"logo\" </img>",
+ xslapply( fun template/1, select("articleinfo",E)),
+ process_toc(E), %% Insert toc between info and main part of article
+ xslapply( fun template/1, select("section",E)),
+ xslapply( fun template/1, select("appendix",E)),
+ "</body></html>"];
+
+template(E = #xmlElement{name=Name})->
+ A = xslapply( fun template/1, E),
+ case catch
+ sdocbook2xhtml:Name(A, E#xmlElement.attributes, E#xmlElement.parents,E)
+ of
+ {'EXIT', {undef, _}} ->
+ A;
+ {'EXIT', Reason} ->
+ exit(Reason);
+ Res ->
+ Res
+ end;
+
+template(E) ->
+ built_in_rules( fun template/1, E).
+
+%% -------------------------------------------------------------------
+%% simple serialize tags
+
+abbrev(Data, Attrs, [{bibliomset,_}|_], E)->
+ ["<dt><abbr>", Data, "</abbr></dt><dd>"];
+abbrev(Data, Attrs, Parents, E)->
+ markup("abbr",Attrs, Data).
+
+
+abstract(Data, Attrs, Parents, E)->
+ ["<h3>Abstract</h3><blockquote>", Data, "</blockquote>"].
+
+acronym(Data, Attrs, Parents, E)->
+ markup("acronym",Attrs, Data).
+
+address(Data, Attrs, Parents, E)->
+ markup("address", Attrs, Data).
+
+anchor(Data, Attrs, Parents, E)->
+ case find_attribute(id, Attrs) of
+ {value,ID} ->
+ ["<a name=\"" ++ ID ++ "\">", Data, "</a>"];
+ false ->
+ Data
+ end.
+
+appendix(Data, Attrs, Parents, E)->
+ ["<h1>Appendix</h1>", Data].
+
+appendixinfo(Data,_,_,_)->
+ Data.
+
+article(Data, Attrs, Parents, E)->
+ ["<body>"
+ "<img src=\"/logga2.jpg\" alt=\"no logo\" class=\"logo\"
+width=\"50\"</img>",
+ Data,
+ "</body>"].
+
+articleinfo(Data,_,_,_)->
+ Data.
+
+audiodata(Data, Attrs, Parents, E)->Data.
+
+audioobject(_,_,_,_)->
+ [].
+
+author(Data, Attrs, [{authorgroup,_} | _], E)->
+ markup("dd", Attrs, Data);
+author(Data, Attrs, Parents, E)->
+ Data.
+
+authorgroup(Data,_,_,_)->
+ ["<dl><dt>Author</dt>",Data,"</dl>"].
+
+authorinitials(Data,_,_,_)-> Data.
+
+bibliography(Data, Attrs, Parents, E)->
+ ["<h3>Bibliography</h3>" ,Data].
+
+bibliomisc(Data,_,_,_)-> Data.
+bibliomixed(Data,_,_,_)-> ["<dl>",Data, "</dl>"].
+bibliomset(Data,_,_,_)-> [Data, "</dd>"].
+
+biblioset(Data,_,_,_)-> Data.
+
+blockquote(Data, Attrs, Parents, E)->
+ markup("blockquote",Attrs, Data).
+
+caption(Data, Attrs, Parents, E)-> Data.
+
+citetitle(Data,_,_,_)-> ["<i>",Data,"</i>"].
+
+city(Data,_,_,_)->
+ Data.
+
+%% Fix Me is it "col" element in html?
+colspec(_, Attrs,_,_)->
+ [].
+
+command(Data,_,_,_)->
+ ["<b><tt>", Data, "</tt></b>"].
+
+computeroutput(Data,_,_,_)->
+ ["<tt>", Data, "</tt>"].
+
+copyright(Data,_,_,_)->
+ [ "&copy; ", Data].
+
+corpauthor(Data,_,_,_)->
+ Data.
+
+country(Data,_,_,_)->
+ Data.
+
+date(Data,_,[{revision,_}|_],_)->
+ ["<td>", Data, "</td>"];
+date(Data,_,_,_)->
+ Data.
+
+edition(Data,_,_,_)->
+ Data.
+
+editor(Data,_,_,_)->
+ Data.
+
+email(Data,_,_,_)->
+ ["<i><a href=\"mailto:", Data,"\">",Data,"</a></i>"].
+
+emphasis(Data, Attrs, Parents, E)->
+ ["<em>", Data, "</em>"].
+
+%% Cell in a table
+entry(Data, Attrs, [{row,_}, {thead,_} | _], E)->
+ ["<th>", Data, "</th>"];
+entry(Data, Attrs, Parents, E)->
+ ["<td>", Data, "</td>"].
+
+example(Data, Attrs, Parents, E)->
+ ["<hr />", Data, "<hr />"].
+
+fax(Data, Attrs, Parents, E)->
+ ["<address>", Data, "</address>"].
+
+%% May contain ulink to image, resolved by ulink type
+figure(Data, _, _, _)->
+ Data.
+
+filename(Data, _, _, _)->
+ ["<i>", Data, "</i>"].
+
+firstname(Data, _, _, _)->
+ [Data , " " ].
+
+footnote(Data, _, _, _)->
+ Data.
+
+holder(Data, _, _, _)->
+ [" ",Data].
+
+honorific(Data, _, _, _)->
+ Data.
+
+imagedata(Data, Attrs, Parents, E)->
+ SRC =
+ case find_attribute(fileref, Attrs) of
+ {value,AS} ->
+ " src=" ++ AS ++ " ";
+ false ->
+ []
+ end,
+ ALT =
+ case SRC of
+ [] ->
+ " alt=\"No image!\" ";
+ _ ->" alt=\"" ++ SRC ++ "\" "
+ end,
+ WIDTH =
+ case find_attribute(width, Attrs) of
+ false ->
+ [];
+ {value,A} ->" width=" ++ A ++ " "
+ end,
+
+ ["<img " ++ SRC ++ ALT ++ WIDTH ++ "></img>"].
+
+
+imageobject(Data, Attrs, Parents, E)->
+ Data.
+
+informaltable(Data, Attrs, Parents, E)->
+ ["<table border=\"1\" >", Data, "</table>"].
+
+
+inlinemediaobject(Data, Attrs, Parents, E)->
+ Data.
+
+isbn(Data, Attrs, Parents, E)->
+ Data.
+
+issn(Data, Attrs, Parents, E)->
+ Data.
+
+issuenum(Data, Attrs, Parents, E)->
+ Data.
+
+itemizedlist(Data, Attrs, Parents, _)->
+ markup("ul", Attrs, Data).
+
+%keyword
+%{
+% display: inline;
+%}
+
+%keywordset
+%{
+% display: inline;
+%}
+
+legalnotice(Data, Attrs, Parents, _)->
+ markup("small", Attrs, Data).
+
+lineage(Data, Attrs, Parents, _)->
+ Data.
+
+%lineannotation
+%{
+% display: inline;
+%}
+
+% Hypertext link
+link(Data, Attrs, Parents, _)->
+ case find_attribute(linkend, Attrs) of
+ {value,LINK} ->
+ ["<a href=\"#" ++ LINK ++ "\">", Data, "</a>"];
+ false ->
+ Data
+ end.
+
+listitem(Data, Attrs, [{varlistentry,_} | _], E) ->
+ markup("dd", Attrs, Data);
+listitem(Data, Attrs, Parents, _)->
+ markup("li", Attrs, Data).
+
+literal(Data, Attrs, Parents, _)->
+ markup("tt", Attrs, Data).
+
+%literallayout
+%{
+% display: inline;
+%}
+
+mediaobject(Data, Attrs, Parents, _)->
+ Data.
+
+%% simplelist member
+member(Data, Attrs, Parents, _)->
+ [Data,"<br></br>"].
+
+note(Data, Attrs, Parents, _)->
+["<table border=\"1\" cellspacing=\"0\" cellpadding=\"5\" width=\"80%\"
+bgcolor=\"#CCCCCC\"><tr><td>NOTE</td><td><i>", Data, "</i></td></tr></table>"].
+
+%objectinfo
+%{
+% display: inline;
+%}
+
+%option
+%{
+% display: inline;
+%}
+
+orderedlist(Data, Attrs, Parents, _)->
+ markup("ol",Attrs,Data).
+
+%% Hmm otheraddr not in DTD
+%otheraddr
+%{
+% display: inline;
+%}
+
+othercredit(Data, Attrs, Parents, _)->Data.
+
+othername(Data, Attrs, Parents, E)->Data.
+
+%% IGNORE
+%pagenums
+%{
+% display: inline;
+%}
+
+para(Data, Attrs, [{listitem,_}|_], E)->
+ Data;
+para(Data, Attrs, [{note,_}|_], E)->
+ Data;
+para(Data, Attrs, Parents, E)->
+ markup("p", Attrs, Data).
+
+phone(Data, Attrs, Parents, E)->Data.
+
+phrase(Data, Attrs, Parents, E)->Data.
+
+%pob
+%{
+% display: inline;
+%}
+
+%postcode
+%{
+% display: inline;
+%}
+
+%printhistory
+%{
+% display: inline;
+%}
+
+%procedure
+%{
+% display: inline;
+%}
+
+programlisting(Data, Attrs, Parents, E)->
+["<table border=\"1\" cellspacing=\"0\" cellpadding=\"5\" width=\"100%\"
+bgcolor=\"#CCCCCC\"><tr><td><pre><code>", Data,
+"</code></pre></td></tr></table>"].
+
+%pubdate
+%{
+% display: inline;
+%}
+
+%publisher
+%{
+% display: inline;
+%}
+
+publishername(Data, Attrs, Parents, E)->
+ Data.
+
+quote(Data, Attrs, Parents, _)->
+ markup("q", Attrs, Data).
+
+replaceable(Data, Attrs, Parents,_)->
+ markup("i", Attrs, Data).
+
+revhistory(Data, Attrs, Parents,E)->
+ {A,B,C} = case E#xmlElement.language of
+ "en" -> {"Revision history","Date","Comment"};
+ "sv" -> {"Revisionshistoria","Datum","Kommentar"};
+ _ ->{"lang is undefined","lang is undefined","lang is undefined"}
+ end,
+
+ ["<h4>",A,"</h4>","<table><thead>"
+ "<tr><th>Rev.</th><th>",B,"</th><th>",C,"</th></tr></thead>", Data,
+ "</table>"].
+
+revision(Data, Attrs, Parents,_)->
+ markup("tr", Attrs, Data).
+
+revnumber(Data, Attrs, Parents,_)->
+ markup("td", Attrs, Data).
+
+revremark(Data, Attrs, Parents,_)->
+ markup("td", Attrs, Data).
+
+row(Data, Attrs, Parents, E)->
+ markup("tr", Attrs, Data).
+
+section(Data, Attrs, Parents, E)->
+ Data.
+
+sectioninfo(Data, Attrs, Parents, E)->Data.
+
+%sidebar
+%{
+% display: block;
+%}
+
+simplelist(Data, Attrs, Parents, E)->
+ ["<table border=\"1\" cellspacing=\"0\" cellpadding=\"5\"
+width=\"100%\"><tr><td>", Data, "</td></tr></table>"].
+
+
+%state
+%{
+% display: inline;
+%}
+
+%step
+%{
+% display: inline;
+%}
+
+%street
+%{
+% display: inline;
+%}
+
+%substeps
+%{
+% display: inline;
+%}
+
+subtitle(Data, Attrs, Parents, E)->
+ ["<h3>", Data, "</h3>"].
+
+surname(Data, Attrs, Parents, E)->Data.
+
+systemitem(Data, Attrs, Parents, E)->
+ markup("b", Attrs, Data).
+
+table(Data, Attrs, Parents, E)->
+ ["<table border=\"1\" cellspacing=\"0\" cellpadding=\"4\" >",
+ Data, "</table>"].
+
+%% Fix me alot
+tbody(Data, Attrs, Parents, E)->
+ markup("tbody", Attrs, Data).
+%{
+% display: table-row-group;
+%}
+
+term(Data, Attrs, [{varlistentry,_} | _], E) ->
+ markup("dt", Attrs, Data).
+
+
+%textobject
+%{
+% display: inline;
+%}
+
+tfoot(Data, Attrs, Parents, E)->
+ markup("tfoot",Attrs, Data).
+
+%% Fixme alot
+tgroup(Data, Attrs, Parents, E)->
+ markup("colgroup", Attrs, Data).
+%{
+% display: table;
+%}
+
+thead(Data, Attrs, Parents, E)->
+ markup("thead",Attrs, Data).
+%{
+% display: table-row-group;
+%}
+
+title(Data, Attrs, Parents, E)->
+%% io:fwrite("Parents ~p~n", [Parents]),
+ title1(Data, Attrs, Parents, E).
+
+title1(Data, Attrs, [{section,_}, {section,_}, {section,_},
+ {section,_}, {section,_}, {appendix,_} | _], E) ->
+ ["<h6>", Data, "</h6>"];
+title1(Data, Attrs, [{section,_}, {section,_}, {section,_},
+ {section,_}, {appendix,_} | _], E) ->
+ ["<h5>", Data, "</h5>"];
+title1(Data, Attrs, [{section,_}, {section,_}, {section,_},
+ {apendix,_} | _], E) ->
+ ["<h4>", Data, "</h4>"];
+title1(Data, Attrs, [{section,_}, {section,_}, {appendix,_} | _], E) ->
+ ["<h3>", Data, "</h3>"];
+title1(Data, Attrs, [{section,_}, {appendix,_} | _], E) ->
+ ["<h2>", Data, "</h2>"];
+title1(Data, Attrs, [{appendix,_} | _], E) ->
+ ["<h1>", Data, "</h1>"];
+
+title1(Data, Attrs, [{section,_}, {section,_}, {section,_},
+ {section,_}, {section,_}, {section,_} | _], E) ->
+ ["<h6>", Data, "</h6>"];
+title1(Data, Attrs, [{section,_}, {section,_}, {section,_},
+ {section,_}, {section,_} | _], E) ->
+ ["<h6>", Data, "</h6>"];
+title1(Data, Attrs, [{section,_}, {section,_}, {section,_},
+ {section,_} | _], E) ->
+ ["<h5>", Data, "</h5>"];
+title1(Data, Attrs, [{section,C}, {section,B}, {section,A} | _], E) ->
+ {value, Id} = find_attribute(id,Attrs),
+ ["<h4 id=\"", Id, "\">", Data, "</h4>"];
+title1(Data, Attrs, [{section,B}, {section,A} | _], E) ->
+ {value, Id} = find_attribute(id,Attrs),
+ ["<h3 id=\"", Id, "\">", Data, "</h3>"];
+title1(Data, Attrs, [{section,A} | _], E) ->
+ {value, Id} = find_attribute(id,Attrs),
+ ["<h2 id=\"", Id, "\">", Data, "</h2>"];
+title1(Data, Attrs, [{articleinfo,_} | _], E) ->
+ ["<h1>", Data, "</h1>"];
+title1(Data, Attrs, [{table,_} | _], E) ->
+ ["<caption>", Data, "</caption>"];
+title1(Data, Attrs, [{bibliomset,_} | _], E) ->
+ ["<i><b>", Data, "</b></i>"];
+title1(Data, Attrs, Parents, E)->
+ ["<h4>", Data, "</h4>"].
+
+titleabbrev(Data, Attrs, Parents, E)->[].
+
+trademark(Data, Attrs, Parents, E)->
+ [ Data, " &reg; "].
+
+ulink(Data, Attrs, Parents, E)->
+ case find_attribute(url, Attrs) of
+ {value,LINK} ->
+ ["<a href="++ LINK ++ ">", Data, "</a>"];
+ false ->
+ Data
+ end.
+
+
+%% User input is Constant Bold
+userinput(Data, Attrs, Parents, E)->
+ ["<tt><b>", Data, "</b></tt>"].
+
+variablelist(Data, Attrs, Parents, E)->
+ markup("dl", Attrs, Data).
+
+varlistentry(Data, Attrs, Parents, E)->Data.
+
+%videodata
+%{
+% display: inline;
+%}
+
+%videoobject
+%{
+% display: inline;
+%}
+
+%volumenum
+%{
+% display: inline;
+%}
+
+xref(Data, Attrs, Parents, E)->
+ case find_attribute(linkend, Attrs) of
+ {value,LINK} ->
+ ["<a href=\"#" ++ LINK ++ "\" />"];
+ false ->
+ Data
+ end.
+
+year(Data, Attrs, Parents, E)->Data.
+
+%% ----------------------------------------------------------
+%% Utils find_attribute copied from Ulf Wigers xmerl distribution
+
+find_attribute(Name, Attrs) ->
+ case lists:keysearch(Name, #xmlAttribute.name, Attrs) of
+ {value, #xmlAttribute{value = V}} ->
+ {value, V};
+ false ->
+ false
+ end.
+%% ------------
+
+changetitle(A) ->
+ Afun = fun changecount/2,
+ {E, Acc} = mapfoldxml(Afun, {0,0,0,0,0,0}, A),
+ E.
+
+changecount(#xmlElement{name=title}=E, {A,B,C,Ex,Fig,Tab})->
+ case E#xmlElement.parents of
+ [{example,_} |_] ->
+ {addexhead(E,{A,Ex+1}), {A,B,C,Ex+1,Fig,Tab} };
+ [{figure,_} |_] ->
+ {addfighead(E,{A,Fig+1}), {A,B,C,Ex,Fig+1,Tab} };
+ [{table,_} |_] ->
+ {addtablehead(E,{A,Tab+1}), {A,B,C,Ex,Fig,Tab+1} };
+ [{section,_},{section,_},{section,_},{article,_} |_] ->
+ {addheader(E,{A,B,C+1}), {A,B,C+1,Ex,Fig,Tab} };
+ [{section,_},{section,_},{article,_} |_] ->
+ { addheader(E,{A,B+1,0}), {A,B+1,0,Ex,Fig,Tab} };
+ [{section,_},{article,_} |_] ->
+ {addheader(E,{A+1,0,0}),{A+1,0,0,0,0,0}};
+ _ ->
+ {E,{A,B,C,Ex,Fig,Tab}}
+ end;
+changecount(E, Acc)->{E,Acc}.
+
+addexhead(#xmlElement{name=title,content=[#xmlText{}=T1|_]}= E, {Ch,No})->
+ NewHeader = "Example " ++
+ integer_to_list(Ch)++" - "++ integer_to_list(No) ++
+ " " ++ T1#xmlText.value,
+ E#xmlElement{content=[T1#xmlText{value=NewHeader}]}.
+addfighead(#xmlElement{name=title,content=[#xmlText{}=T1|_]}= E, {Ch,No})->
+ NewHeader = "Figure " ++
+ integer_to_list(Ch)++" - "++ integer_to_list(No) ++
+ " " ++ T1#xmlText.value,
+ E#xmlElement{content=[T1#xmlText{value=NewHeader}]}.
+addtablehead(#xmlElement{name=title,content=[#xmlText{}=T1|_]}= E, {Ch,No})->
+ NewHeader = "Table " ++
+ integer_to_list(Ch)++" - "++ integer_to_list(No) ++
+ " " ++ T1#xmlText.value,
+ E#xmlElement{content=[T1#xmlText{value=NewHeader}]}.
+
+addheader(#xmlElement{name=title,content=[#xmlText{}=T1|_]}= E, Chapters)->
+ NewHeader = chapterstring(Chapters)++ " " ++ T1#xmlText.value,
+ NewAtts = addid(E#xmlElement.attributes, Chapters),
+ E#xmlElement{content=[T1#xmlText{value=NewHeader}],
+ attributes = NewAtts}.
+
+chapterstring({A,0,0})->integer_to_list(A);
+chapterstring({A,B,0})->integer_to_list(A)++"."++ integer_to_list(B);
+chapterstring({A,B,C})->integer_to_list(A) ++ "." ++
+ integer_to_list(B) ++ "." ++
+ integer_to_list(C).
+
+%% addid add id attribute if it not already exists
+addid(OldAtts, Chapters)->
+ case find_attribute(id, OldAtts) of
+ {value,_} ->
+ OldAtts;
+ false ->
+ add_attribute(id,"sect_"++ chapterstring(Chapters),
+ OldAtts)
+ end.
+
+add_attribute(Name, Value, OldAtts)->
+ [#xmlAttribute{ name=Name, value = Value}| OldAtts ].
+
+
+process_toc(E)->
+ AFun = fun chapindex/2,
+ TOCR = foldxml(AFun, [], E),
+% Str = case find_attribute(lang, E#xmlElement.attributes) of
+% {value,"en"} -> "Table of Contents";
+% {value,"sv"} -> "Inneh�llsf�rtecking";
+% _ ->"lang is undefined"
+% end,
+ Str = case E#xmlElement.language of
+ "en" -> "Table of Contents";
+ "sv" -> "Inneh�llsf�rtecking";
+ _ ->"lang is undefined"
+ end,
+ TOC = ["<div class=\"toc\"><h3>",Str,"</h3><ul>",
+lists:reverse(TOCR), "</ul></div>"].
+
+chapindex(#xmlElement{name=title}=E, Accu)->
+ case E#xmlElement.parents of
+ [{section,_},{section,_},{section,_},{article,_} |_] ->
+ ["<li>"++spind(3)++ addlink(E,"toc_level_3") ++"</li>"| Accu];
+ [{section,_},{section,_},{article,_} |_] ->
+ ["<li>"++spind(2)++ addlink(E,"toc_level_2") ++ "</li>"| Accu];
+ [{section,_},{article,_} |_] ->
+ ["<li>"++spind(1)++ addlink(E,"toc_level_1") ++"</li>"| Accu];
+ _ ->
+ Accu
+ end;
+chapindex(E, Accu) ->
+ Accu.
+
+spind(0) ->"";
+spind(X)->
+ "&#160;&#160;" ++ spind(X-1).
+
+addlink(E, TocLevel)->
+ {value,LINK} = find_attribute(id,E#xmlElement.attributes),
+ [#xmlText{value=Title}|_] = E#xmlElement.content, %% Pfuii
+ "<a href=\"#" ++ LINK ++
+ "\" class=\"" ++ TocLevel ++ "\">" ++
+ Title ++ "</a>".
+
+
diff --git a/lib/xmerl/doc/examples/test_html.erl b/lib/xmerl/doc/examples/test_html.erl
new file mode 100755
index 0000000000..3ca15f30f8
--- /dev/null
+++ b/lib/xmerl/doc/examples/test_html.erl
@@ -0,0 +1,225 @@
+%%% The contents of this file are subject to the Erlang Public License,
+%%% Version 1.0, (the "License"); you may not use this file except in
+%%% compliance with the License. You may obtain a copy of the License at
+%%% http://www.erlang.org/license/EPL1_0.txt
+%%%
+%%% Software distributed under the License is distributed on an "AS IS"
+%%% 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 Original Code is xmerl-0.7
+%%%
+%%% The Initial Developer of the Original Code is Ericsson Telecom
+%%% AB. Portions created by Ericsson are Copyright (C), 1998, Ericsson
+%%% Telecom AB. All Rights Reserved.
+%%%
+%%% Contributor(s): ______________________________________.
+%%%
+%%%----------------------------------------------------------------------
+%%% #0. BASIC INFORMATION
+%%%----------------------------------------------------------------------
+%%% File: test_html.erl
+%%% Author : Ulf Wiger <[email protected]>
+
+%%% Description : Callback module for exporting XML to HTML with support
+%%% for special Erlang-related tags. (Experimental)
+%%%
+%%% Modules used : lists, io_lib
+%%%
+%%%----------------------------------------------------------------------
+
+-module(test_html).
+-author('[email protected]').
+
+
+-export(['#xml-inheritance#'/0]).
+
+%%% special Erlang forms
+-export(['EXIT'/4,
+ 'tuple_list'/4]).
+
+-export(['#root#'/4,
+ title/4,
+ heading/4,
+ section/4,
+ table/4,
+ row/4,
+ col/4,
+ data/4,
+ p/4, para/4, 'P'/4,
+ emphasis/4]).
+
+-include("xmerl.hrl").
+
+
+'#xml-inheritance#'() -> [xmerl_xml].
+
+
+
+%% The '#root#' tag is called when the entire structure has been exported.
+%% It does not appear in the structure itself.
+'#root#'(Data, Attrs, [], E) ->
+ Title =
+ case find_attribute(title, Attrs) of
+ {value, T} ->
+ ["<title>", T, "</title>"];
+ false ->
+ []
+ end,
+ ["<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n"
+ "<html>\n",
+ "<head>\n", Title, "</head>\n"
+ "<body>\n", Data, "</body>\n"].
+
+
+
+
+%%% Special token: EXIT
+'EXIT'(Reason, Attrs = [], Parents = [], E) ->
+ %% This happens e.g. if a request function crashes completely.
+ ["<pre>\n", mk_string({'EXIT', Reason}), "</pre>"].
+
+
+title(Str, Attrs, Parents, E) ->
+ ["<h1>", Str, "</h1>\n"].
+
+
+%%% section/3 is to be used instead of headings.
+section(Data, Attrs, [{section,_}, {section,_}, {section,_} | _], E) ->
+ opt_heading(Attrs, "<h4>", "</h4>", Data);
+section(Data, Attrs, [{section,_}, {section,_} | _], E) ->
+ opt_heading(Attrs, "<h3>", "</h3>", Data);
+section(Data, Attrs, [{section,_} | _], E) ->
+ opt_heading(Attrs, "<h2>", "</h2>", Data);
+section(Data, Attrs, Parents, E) ->
+ opt_heading(Attrs, "<h1>", "</h1>", Data).
+
+opt_heading(Attrs, StartTag, EndTag, Data) ->
+ case find_attribute(heading, Attrs) of
+ {value, Text} ->
+ [StartTag, Text, EndTag, "\n" | Data];
+ false ->
+ Data
+ end.
+
+
+%% tables
+%% e.g. {table, [{heading, [{col, H1}, {col, H2}]},
+%% {row, [{col, C11}, {col, C12}]},
+%% {row, [{col, C21}, {col, C22}]}]}.
+
+table(Data, Attrs, Parents, E) ->
+ Border = case find_attribute(border, Attrs) of
+ false ->
+ " border=1";
+ {value, N} ->
+ [" border=", mk_string(N)]
+ end,
+ ["<table", Border, ">\n", Data, "\n</table>\n"].
+
+row(Data, Attrs, [{table,_}|_], E) ->
+ ["<tr>", Data, "</tr>\n"].
+
+heading(Data, Attrs, [{table,_}|_], E) ->
+ ["<tr>", Data, "</tr>\n"].
+
+
+%% Context-sensitive columns (heading- or row columns)
+col(Data, Attrs, [{heading,_}, {table,_} | _], E) ->
+ ["<th>", nbsp_if_empty(Data), "</th>\n"];
+col(Data, Attrs, [{row,_}, {table,_} | _], E) ->
+ ["<td>", nbsp_if_empty(Data), "</td>\n"].
+
+
+tuple_list(List, Attrs, Parents, E) ->
+ Elems = case find_attribute(elements, Attrs) of
+ {value, Es} ->
+ Es;
+ false ->
+ case List of
+ [H|_] ->
+ lists:seq(1,size(H));
+ [] ->
+ []
+ end
+ end,
+ TableData = [{row, [{col, {element(P, Rec)}} || P <- Elems]} ||
+ Rec <- List],
+ Table = case find_attribute(heading, Attrs) of
+ {value, Cols} ->
+ Head = {heading, [{col, C} || C <- Cols]},
+ {table, [Head | TableData]};
+ false ->
+ {table, TableData}
+ end,
+ {'#xml-redefine#', Table}.
+
+
+data(Data, Pos, Attrs, Parents) ->
+ mk_string(Data).
+
+
+
+p(Data, Pos, Attrs, Parents) ->
+ {'#xml-alias#', 'P'}.
+
+para(Data, Pos, Attrs, Parents) ->
+ {'#xml-alias#', 'P'}.
+
+'P'(Data, Pos, Attrs, Parents) ->
+ ["<p>", mk_string(Data), "</p>\n"].
+
+
+emphasis(Str, Pos, Attrs, Parents) ->
+ ["<strong>", Str, "</strong>"].
+
+
+nbsp_if_empty(Data) when binary(Data), size(Data) == 0 ->
+ "&nbsp;";
+nbsp_if_empty(Data) when list(Data) ->
+ case catch list_to_binary(Data) of
+ {'EXIT', _} ->
+ nbsp_if_empty_term(Data);
+ B when size(B) == 0 ->
+ "&nbsp;";
+ _ ->
+ Data
+ end;
+nbsp_if_empty(Data) ->
+ nbsp_if_empty_term(Data).
+
+nbsp_if_empty_term(Data) ->
+ Str = io_lib:format("~p", [Data]),
+ case list_to_binary(Str) of
+ B when size(B) == 0 ->
+ "&nbsp;";
+ _ ->
+ Str
+ end.
+
+
+mk_string(I) when integer(I) ->
+ integer_to_list(I);
+mk_string(A) when atom(A) ->
+ atom_to_list(A);
+mk_string(L) when list(L) ->
+ %% again, we can't regognize a string without "parsing" it
+ case catch list_to_binary(L) of
+ {'EXIT',_} ->
+ io_lib:format("~p", [L]);
+ _ ->
+ L
+ end;
+mk_string(Term) ->
+ io_lib:format("~p", [Term]).
+
+
+
+find_attribute(Name, Attrs) ->
+ case lists:keysearch(Name, #xmlAttribute.name, Attrs) of
+ {value, #xmlAttribute{value = V}} ->
+ {value, V};
+ false ->
+ false
+ end.
diff --git a/lib/xmerl/doc/examples/xmerl_test.erl b/lib/xmerl/doc/examples/xmerl_test.erl
new file mode 100644
index 0000000000..b4288431f2
--- /dev/null
+++ b/lib/xmerl/doc/examples/xmerl_test.erl
@@ -0,0 +1,522 @@
+-module(xmerl_test).
+
+-compile(export_all).
+%%-export([Function/Arity, ...]).
+
+-define(XMERL_APP,).
+
+-include("xmerl.hrl").
+
+%% Export to HTML from "simple" format
+test1() ->
+ xmerl:export_simple(simple(), xmerl_html, [{title, "Doc Title"}]).
+
+
+%% Export to XML from "simple" format
+test2() ->
+ xmerl:export_simple(simple(), xmerl_xml, [{title, "Doc Title"}]).
+
+
+%% Parse XHTML, and export result to HTML and text
+test3() ->
+ FetchFun = fun(_DTDSpec, S) -> {ok, not_fetched,S} end,
+ {A, _} = xmerl_scan:string(html(),
+ [{fetch_fun,FetchFun}]),
+ io:format("From xmerl_scan:string/2~n ~p~n", [A]),
+ B = xmerl:export([A], xmerl_html),
+ io:format("From xmerl:export/2 xmerl_html filter~n ~p~n", [B]),
+ C = xmerl:export([A], xmerl_text),
+ io:format("From xmerl:export/2 xmerl_text filter~n ~p~n", [C]).
+
+
+test4() ->
+ FetchFun = fun(_DTDSpec, S) -> {ok, not_fetched, S} end,
+ {A,_} = xmerl_scan:string(xml_namespace(),
+ [{fetch_fun,FetchFun},
+ {namespace_conformant,true}]),
+ io:format("From xmerl_scan:string/2~n ~p~n", [A]).
+
+test5() ->
+ {ok, Cwd} = file:get_cwd(), % Assume we are in the examples dir...
+ File = Cwd ++ "/xml/xmerl.xml",
+ FetchFun = fun(_DTDSpec, S) -> {ok, not_fetched, S} end,
+% {Resp0,Rest0}=xmerl_eventp:stream(File,[]),
+% io:format("Tree: ~p~n",[Resp0]),
+ {Resp1, _Rest1}=xmerl_eventp:file_sax(File, ?MODULE, undefined,
+ [{fetch_fun, FetchFun}]),
+ io:format("Using file_sax: counted ~p paragraphs~n", [Resp1]),
+ {Resp2, _Rest2} = xmerl_eventp:stream_sax(File, ?MODULE, undefined, []),
+ io:format("Using stream_sax: counted ~p paragraphs~n", [Resp2]).
+
+test6() ->
+ FetchFun = fun(_DTDSpec, S) -> {ok, {string,""}, S} end,
+ {Doc, _} = xmerl_scan:string(xml_namespace(),
+ [{fetch_fun, FetchFun},
+ {namespace_conformant, true}]),
+ E = xmerl_xpath:string("child::title[position()=1]", Doc),
+ io:format("From xmerl_scan:string/2~n E=~p~n", [E]).
+
+
+simple() ->
+ [{document,
+ [{title, ["Doc Title"]},
+ {author, ["Ulf Wiger"]},
+ {section,[{heading, ["heading1"]},
+ {'P', ["This is a paragraph of text."]},
+ {section,[{heading, ["heading2"]},
+ {'P', ["This is another paragraph."]},
+ {table,[{border, ["1"]},
+ {heading,[{col, ["head1"]},
+ {col, ["head2"]}]},
+ {row, [{col, ["col11"]},
+ {col, ["col12"]}]},
+ {row, [{col, ["col21"]},
+ {col, ["col22"]}]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ].
+
+
+html() ->
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"DTD/xhtml1-strict.dtd\"><html>"
+ "<head><title>Doc Title</title><author>Ulf Wiger</author></head>"
+ "<h1>heading1</h1>"
+ "<p>This is a paragraph of text.</p>"
+ "<h2>heading2</h2>"
+ "<p>This is another paragraph.</p>"
+ "<table>"
+ "<thead><tr><td>head1</td><td>head2</td></tr></thead>"
+ "<tr><td>col11</td><td>col122</td></tr>"
+ "<tr><td>col21</td><td>col122</td></tr>"
+ "</table>"
+ "</html>".
+
+xml_namespace() ->
+ "<?xml version=\"1.0\"?>"
+ "<!-- initially, the default namespace is \"books\" -->"
+ "<book xmlns='urn:loc.gov:books' xmlns:isbn='urn:ISBN:0-395-36341-6'>"
+ "<title>Cheaper by the Dozen</title>"
+ "<isbn:number>1568491379</isbn:number>"
+ "<notes>"
+ "<!-- make HTML the default namespace for some comments -->"
+ "<p xmlns='urn:w3-org-ns:HTML'>"
+ "This is a <i>funny</i> book!"
+ "</p>"
+ "</notes>"
+ "</book>".
+
+
+%%% ============================================================================
+%%% Generic callbacks
+
+%'#text#'(Text) ->
+% [].
+
+'#root#'(Data, Attrs, [], _E) ->
+ io:format("root... Data=~p Attrs=~p E=~p~n",[Data,Attrs,_E]),
+ [].
+
+'#element#'(Tag, Data, Attrs, _Parents, _E) ->
+ io:format("Tag=~p~n Data=~p~n Attrs=~p~n Parents=~p~n E=~p~n",
+ [Tag, Data, Attrs, _Parents, _E]),
+ [].
+
+'#element#'(_Tag, _Data, _Attrs, CBstate) ->
+% io:format("Tag=~p~n Data=~p~n Attrs=~p~n CBstate=~p~n",
+% [Tag, Data, Attrs, CBstate]),
+ CBstate.
+
+'#text#'(Text, CBstate) ->
+ io:format("Text=~p~n CBstate=~p~n",
+ [Text, CBstate]),
+ CBstate.
+
+
+'#xml-inheritance#'() ->
+ [xmerl_html].
+
+
+
+
+%%% ============================================================================
+%%% To run these tests you must first download the testsuite from www.w3c.org
+%%% xmlconf.xml is the main test file that contains references to all the tests.
+%%% Thus parse this, export result and execute tests in the call-back functions.
+%%% Note:
+%%% - xmerl assumes all characters are represented with a single integer.
+w3cvalidate() ->
+ Tests = filename:join(filename:dirname(filename:absname(code:which(xmerl))),
+ "../w3c/xmlconf/xmlconf.xml"),
+ TestDir = filename:dirname(Tests),
+ io:format("Looking for W3C tests at ~p~n", [Tests]),
+ {ok, Bin} = file:read_file(Tests),
+
+% String = ucs:to_unicode(binary_to_list(Bin), 'utf-8'),
+% case xmerl_scan:string(String, [{xmlbase, TestDir}]) of
+ case xmerl_scan:string(binary_to_list(Bin), [{xmlbase, TestDir}]) of
+ {error, Reason} ->
+ io:format("ERROR xmerl:scan_file/2 Reason=~w~n", [Reason]);
+ {A, _Res} ->
+% io:format("From xmerl:scan_file/2 ~n A=~p~n Res=~w~n", [A,Res]),
+ C = xmerl:export([A], xmerl_test),
+ io:format("From xmerl:export/2 xmerl_text filter~n ~p~n", [C])
+ end.
+
+
+'TESTSUITE'(_Data, Attrs, _Parents, _E) ->
+ _Profile = find_attribute('PROFILE', Attrs),
+% io:format("testsuite Profile=~p~n", [Profile]),
+ [].
+
+'TESTCASES'(_Data, Attrs, _Parents, _E) ->
+ Profile = find_attribute('PROFILE', Attrs),
+ XMLbase = find_attribute('xml:base', Attrs),
+ io:format("testsuite Profile=~p~n xml:base=~p~n", [Profile, XMLbase]),
+ [].
+
+%% More info on Canonical Forms can be found at:
+%% http://dev.w3.org/cvsweb/~checkout~/2001/XML-Test-Suite/xmlconf/sun/cxml.html?content-type=text/html;%20charset=iso-8859-1
+'TEST'(Data, Attrs, _Parents, E) ->
+% io:format("test Attrs=~p~n Parents=~p~n E=~p~n",[Attrs, _Parents, E]),
+ Id = find_attribute('ID', Attrs),
+ io:format("Test: ~p ",[Id]),
+ Entities = find_attribute('ENTITIES', Attrs), % Always handle all entities
+ Output1 = find_attribute('OUTPUT', Attrs), %
+ Output3 = find_attribute('OUTPUT3', Attrs), % FIXME!
+ Sections = find_attribute('SECTIONS', Attrs),
+ Recommendation = find_attribute('RECOMMENDATION', Attrs), % FIXME!
+ Type = find_attribute('TYPE', Attrs), % Always handle all entities
+ Version = find_attribute('VERSION', Attrs), % FIXME!
+ URI = find_attribute('URI', Attrs),
+ Namespace = find_attribute('NAMESPACE', Attrs), % FIXME!
+
+ OutputForm=
+ if
+ Output1 =/= undefined -> Output1;
+ true -> Output3
+ end,
+ Test = filename:join(E#xmlElement.xmlbase, URI),
+% io:format("TEST URI=~p~n E=~p~n",[Test,E]),
+ case Type of
+ "valid" ->
+% io:format("Data=~p~n Attrs=~p~n Parents=~p~n Path=~p~n",
+% [Data, Attrs, _Parents, Test]),
+ test_valid(Test, Data, Sections, Entities, OutputForm, Recommendation,
+ Version, Namespace);
+ "invalid" ->
+ test_invalid(Test, Data, Sections, Entities, OutputForm, Recommendation,
+ Version, Namespace);
+ "not-wf" ->
+ test_notwf(Test, Data, Sections, Entities, OutputForm, Recommendation,
+ Version, Namespace);
+ "error" ->
+ test_error(Test, Data, Sections, Entities, OutputForm, Recommendation,
+ Version, Namespace)
+ end,
+ [].
+
+%% Really basic HTML font tweaks, to support highlighting
+%% some aspects of test descriptions ...
+'EM'(Data, _Attrs, _Parents, _E) ->
+ [$" |Data ++ [$"]].
+
+'B'(Data, _Attrs, _Parents, _E) ->
+ [$" |Data ++ [$"]].
+
+
+
+find_attribute(Tag,Attrs) ->
+ case xmerl_lib:find_attribute(Tag, Attrs) of
+ {value, Id} -> Id;
+ false -> undefined
+ end.
+
+
+-define(CONT, false).
+
+%%% All parsers must accept "valid" testcases.
+test_valid(URI, Data, Sections, Entities, OutputForm, Recommendation, Version,
+ Namespace) ->
+ io:format("nonvalidating ", []),
+ case nonvalidating_parser_q(URI) of
+ {Res, Tail} when is_record(Res, xmlElement) ->
+ case is_whitespace(Tail) of
+ true ->
+ io:format("OK ", []),
+ ok;
+ false ->
+ print_error({Res, Tail}, URI, Sections, Entities, OutputForm,
+ Recommendation,
+ Version, Namespace, Data),
+ if
+ ?CONT == false -> throw({'EXIT', failed_test});
+ true -> error
+ end
+ end;
+ Error ->
+ print_error(Error, URI, Sections, Entities, OutputForm, Recommendation,
+ Version, Namespace, Data),
+ if
+ ?CONT == false -> throw({'EXIT', failed_test});
+ true -> error
+ end
+ end,
+ io:format("validating ", []),
+ case validating_parser_q(URI) of
+ {Res2, Tail2} when is_record(Res2, xmlElement) ->
+ case is_whitespace(Tail2) of
+ true ->
+ io:format("OK~n", []),
+ ok;
+ false ->
+ print_error({Res2, Tail2}, URI, Sections, Entities, OutputForm,
+ Recommendation,
+ Version, Namespace, Data),
+ if
+ ?CONT == false -> throw({'EXIT', failed_test});
+ true -> error
+ end
+ end;
+ Error2 ->
+ print_error(Error2, URI, Sections, Entities, OutputForm, Recommendation,
+ Version, Namespace, Data),
+ if
+ ?CONT == false -> throw({'EXIT', failed_test});
+ true -> error
+ end
+ end.
+
+
+%%% Nonvalidating parsers must accept "invalid" testcases, but validating ones
+%%% must reject them.
+test_invalid(URI, Data, Sections, Entities, OutputForm, Recommendation, Version,
+ Namespace) ->
+ io:format("nonvalidating ", []),
+ case nonvalidating_parser_q(URI) of
+ {Res,Tail} when is_record(Res, xmlElement) ->
+ case is_whitespace(Tail) of
+ true ->
+ io:format("OK ", []),
+ ok;
+ false ->
+ print_error({Res, Tail}, URI, Sections, Entities, OutputForm,
+ Recommendation,
+ Version, Namespace, Data),
+ if
+ ?CONT == false -> throw({'EXIT', failed_test});
+ true -> error
+ end
+ end;
+ Error ->
+ print_error(Error, URI, Sections, Entities, OutputForm, Recommendation,
+ Version, Namespace, Data),
+ if
+ ?CONT == false -> throw({'EXIT', failed_test});
+ true -> error
+ end
+ end,
+ io:format("validating ", []),
+ case validating_parser_q(URI) of
+ {Res2, Tail2} when is_record(Res2, xmlElement) ->
+ case is_whitespace(Tail2) of
+ false ->
+ io:format("OK~n", []),
+ ok;
+ true ->
+ print_error({Res2, Tail2}, URI, Sections, Entities, OutputForm,
+ Recommendation,
+ Version, Namespace, Data),
+ if
+ ?CONT == false -> throw({'EXIT', failed_test});
+ true -> error
+ end
+ end;
+ {error, enoent} ->
+ print_error("Testfile not found", URI, Sections, Entities, OutputForm,
+ Recommendation, Version, Namespace, Data),
+ if
+ ?CONT == false -> throw({'EXIT', failed_test});
+ true -> error
+ end;
+ _Error2 ->
+ io:format("OK~n", []),
+ ok
+ end.
+
+%%% No parser should accept a "not-wf" testcase unless it's a nonvalidating
+%%% parser and the test contains external entities that the parser doesn't read
+test_notwf(URI, Data, Sections, Entities, OutputForm, Recommendation, Version,
+ Namespace) ->
+ io:format("nonvalidating ", []),
+ case nonvalidating_parser_q(URI) of
+ {Res, Tail} when is_record(Res, xmlElement) ->
+ case is_whitespace(Tail) of
+ false ->
+ io:format("OK ", []),
+ ok;
+ true ->
+ print_error({Res, Tail}, URI, Sections, Entities, OutputForm,
+ Recommendation,
+ Version, Namespace, Data),
+ if
+ ?CONT == false -> throw({'EXIT', failed_test});
+ true -> error
+ end
+ end;
+ {error,enoent} ->
+ print_error("Testfile not found",URI,Sections,Entities,OutputForm,
+ Recommendation,Version,Namespace,Data),
+ if
+ ?CONT==false -> throw({'EXIT', failed_test});
+ true -> error
+ end;
+ _Error ->
+ io:format("OK ",[]),
+ ok
+ end,
+ io:format("validating ",[]),
+ case validating_parser_q(URI) of
+ {Res2, Tail2} when is_record(Res2, xmlElement) ->
+ case is_whitespace(Tail2) of
+ false ->
+ io:format("OK~n", []),
+ ok;
+ true ->
+ print_error({Res2, Tail2}, URI, Sections, Entities, OutputForm,
+ Recommendation,
+ Version, Namespace, Data),
+ if
+ ?CONT == false -> throw({'EXIT', failed_test});
+ true -> error
+ end
+ end;
+ {error,enoent} ->
+ print_error("Testfile not found", URI, Sections, Entities, OutputForm,
+ Recommendation, Version, Namespace, Data),
+ if
+ ?CONT == false -> throw({'EXIT', failed_test});
+ true -> error
+ end;
+ _Error2 ->
+ io:format("OK~n", []),
+ ok
+ end.
+
+%%% Parsers are not required to report "errors", but xmerl will always...
+test_error(URI, Data, Sections, Entities, OutputForm, Recommendation, Version,
+ Namespace) ->
+ io:format("nonvalidating ", []),
+ case nonvalidating_parser_q(URI) of
+ {'EXIT', _Reason} ->
+ io:format("OK ", []),
+ ok;
+ {error, enoent} ->
+ print_error("Testfile not found", URI, Sections, Entities, OutputForm,
+ Recommendation, Version, Namespace, Data),
+ if
+ ?CONT == false -> throw({'EXIT', failed_test});
+ true -> error
+ end;
+ Res ->
+ print_error(Res, URI, Sections, Entities, OutputForm, Recommendation,
+ Version, Namespace, Data),
+ if
+ ?CONT == false -> throw({'EXIT', failed_test});
+ true -> error
+ end
+ end,
+ io:format("validating ", []),
+ case validating_parser_q(URI) of
+ {'EXIT', _Reason2} ->
+ io:format("OK~n", []),
+ ok;
+ {error, enoent} ->
+ print_error("Testfile not found", URI, Sections, Entities, OutputForm,
+ Recommendation, Version, Namespace, Data),
+ if
+ ?CONT == false -> throw({'EXIT', failed_test});
+ true -> error
+ end;
+ Res2 ->
+ print_error(Res2, URI, Sections, Entities, OutputForm, Recommendation,
+ Version, Namespace, Data),
+ if
+ ?CONT == false -> throw({'EXIT', failed_test});
+ true -> error
+ end
+ end.
+
+
+%%% Use xmerl as nonvalidating XML parser
+nonvalidating_parser(URI) ->
+ (catch xmerl_scan:file(URI, [])).
+
+
+%%% Use xmerl as nonvalidating XML parser
+nonvalidating_parser_q(URI) ->
+ (catch xmerl_scan:file(URI, [{quiet, true}])).
+
+
+%%% Use xmerl as validating XML parser
+validating_parser(URI) ->
+ (catch xmerl_scan:file(URI, [{validation, true}])).
+
+
+%%% Use xmerl as validating XML parser
+validating_parser_q(URI) ->
+ (catch xmerl_scan:file(URI, [{validation, true}, {quiet, true}])).
+
+
+is_whitespace([]) ->
+ true;
+is_whitespace([H |Rest]) when ?whitespace(H) ->
+ is_whitespace(Rest);
+is_whitespace(_) ->
+ false.
+
+
+print_error(Error, URI, Sections, Entities, OutputForm, Recommendation, Version,
+ Namespace, Data) ->
+ io:format("ERROR ~p~n URI=~p~n See Section ~s~n",[Error, URI, Sections]),
+ if
+ Entities == undefined -> ok;
+ true -> io:format(" Entities =~s~n",[Entities])
+ end,
+ if
+ OutputForm == undefined -> ok;
+ true -> io:format(" OutputForm=~s FIXME!~n",[OutputForm])
+ end,
+ if
+ Recommendation == undefined -> ok;
+ true -> io:format(" Recommendation=~s~n",[Recommendation])
+ end,
+ if
+ Version == undefined -> ok;
+ true -> io:format(" Version =~s~n",[Version])
+ end,
+ if
+ Namespace == undefined -> ok;
+ true -> io:format(" Namespace =~s~n",[Namespace])
+ end,
+ io:format(Data).
+
+
+
+
+
+
+
+
+
+%%% ============================================================================
+%%% Callbacks for parsing of Simplified DocBook XML
+
+para(_Data, _Attrs, US) ->
+ case US of
+ Int when is_integer(Int) -> Int+1;
+ undefined -> 1
+ end.
+
+
diff --git a/lib/xmerl/doc/examples/xml/test.xml b/lib/xmerl/doc/examples/xml/test.xml
new file mode 100755
index 0000000000..e803a83560
--- /dev/null
+++ b/lib/xmerl/doc/examples/xml/test.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" ?>
+<People>
+ <Person Type = "Personal">
+ </Person>
+</People>
+
diff --git a/lib/xmerl/doc/examples/xml/test2.xml b/lib/xmerl/doc/examples/xml/test2.xml
new file mode 100755
index 0000000000..0cb11194fc
--- /dev/null
+++ b/lib/xmerl/doc/examples/xml/test2.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding = "ISO-8859-1" ?>
+<People>
+ <!-- This is a real comment -->
+ <comment>This is a comment</comment>
+ <Person Type = "Personal">
+ </Person>
+</People>
+
diff --git a/lib/xmerl/doc/examples/xml/test3.xml b/lib/xmerl/doc/examples/xml/test3.xml
new file mode 100755
index 0000000000..dbdc1e62c2
--- /dev/null
+++ b/lib/xmerl/doc/examples/xml/test3.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding = 'ISO-8859-1' ?>
+<People>
+ <!-- This is a real comment -->
+ <comment>This is a comment</comment>
+ <Person Type = "Personal">
+ </Person>
+</People>
+
diff --git a/lib/xmerl/doc/examples/xml/test4.xml b/lib/xmerl/doc/examples/xml/test4.xml
new file mode 100755
index 0000000000..e9d85b8d8f
--- /dev/null
+++ b/lib/xmerl/doc/examples/xml/test4.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding = 'ISO-8859-1' ?>
+<People>
+ <!-- This is a real comment -->
+ <comment>
+ This is a comment
+ </comment>
+ <Person Type = "Personal">
+ </Person>
+</People>
diff --git a/lib/xmerl/doc/examples/xml/test5.xml b/lib/xmerl/doc/examples/xml/test5.xml
new file mode 100755
index 0000000000..e9d85b8d8f
--- /dev/null
+++ b/lib/xmerl/doc/examples/xml/test5.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding = 'ISO-8859-1' ?>
+<People>
+ <!-- This is a real comment -->
+ <comment>
+ This is a comment
+ </comment>
+ <Person Type = "Personal">
+ </Person>
+</People>
diff --git a/lib/xmerl/doc/examples/xml/testdtd.dtd b/lib/xmerl/doc/examples/xml/testdtd.dtd
new file mode 100755
index 0000000000..2ce1c513a6
--- /dev/null
+++ b/lib/xmerl/doc/examples/xml/testdtd.dtd
@@ -0,0 +1,17 @@
+<!ELEMENT PARAMETER ( #PCDATA | PARAMETER )* >
+<!ATTLIST PARAMETER NR ( 1000024 | 1000025 | 1000101 | 1000102 | 1000103
+| 1000105 | 1000110 | 1000115 | 1000198 ) #REQUIRED >
+<!ATTLIST PARAMETER UNIT CDATA #REQUIRED >
+
+<!ELEMENT PRODUCT ( USER_DEF, PRODUCTELEMENT+ ) >
+<!ATTLIST PRODUCT CUSTOMER CDATA #REQUIRED >
+<!ATTLIST PRODUCT DESCRIPTION CDATA #REQUIRED >
+<!ATTLIST PRODUCT GENERATOR NMTOKEN #REQUIRED >
+<!ATTLIST PRODUCT PRODUCTID NMTOKEN #REQUIRED >
+
+<!ELEMENT PRODUCTELEMENT ( PARAMETER+ ) >
+<!ATTLIST PRODUCTELEMENT ELEMENTID CDATA #REQUIRED >
+<!ATTLIST PRODUCTELEMENT TYPE NMTOKEN #REQUIRED >
+
+<!ELEMENT USER_DEF ( #PCDATA ) >
+
diff --git a/lib/xmerl/doc/examples/xml/xmerl.xml b/lib/xmerl/doc/examples/xml/xmerl.xml
new file mode 100755
index 0000000000..f02282dbef
--- /dev/null
+++ b/lib/xmerl/doc/examples/xml/xmerl.xml
@@ -0,0 +1,523 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE article
+ PUBLIC "-//OASIS//DTD Simplified DocBook XML V1.0//EN"
+ "http://www.oasis-open.org/docbook/xml/simple/1.0/sdocbook.dtd">
+
+<article lang="en" xml:lang="en" >
+ <articleinfo>
+ <title>XMerL - XML processing tools for Erlang</title>
+ <subtitle>Reference Manual</subtitle>
+ <authorgroup>
+ <author>
+ <firstname>Ulf</firstname>
+ <surname>Wiger</surname>
+ </author>
+ </authorgroup>
+ <revhistory>
+ <revision>
+ <revnumber>1.0</revnumber><date>2003-02-04</date>
+ <revremark>Converted xml from html</revremark>
+ </revision>
+ </revhistory>
+ <abstract>
+ <para>XMerL tools contains xmerl_scan; a non-validating XML
+ processor, xmerl_xpath; a XPath implementation, xmerl for export
+ of XML trees to HTML, XML or text and xmerl_xs for XSLT like
+ transforms in erlang.
+ </para>
+ </abstract>
+ </articleinfo>
+
+ <section>
+ <title>xmerl_scan - the XML processor</title>
+ <para>The (non-validating) XML processor is activated through
+ <computeroutput>xmerl_scan:string/[1,2]</computeroutput> or
+ <computeroutput>xmerl_scan:file/[1,2]</computeroutput>.
+ It returns records of the type defined in xmerl.hrl.
+ </para>
+
+ <para>As far as I can tell, xmerl_scan implements the complete XML
+ 1.0 spec, including:</para>
+ <itemizedlist>
+ <listitem><para>entity expansion</para></listitem>
+ <listitem><para>fetching and parsing external DTDs</para></listitem>
+ <listitem><para>contitional processing</para></listitem>
+ <listitem><para>UniCode</para></listitem>
+ <listitem><para>XML Names</para></listitem>
+ </itemizedlist>
+ <programlisting>
+xmerl_scan:string(Text [ , Options ]) -> #xmlElement{}.
+xmerl_scan:file(Filename [ , Options ]) -> #xmlElement{}. </programlisting>
+
+ <para>The Options are basically to specify the behaviour of the
+ scanner. See the source code for details, but you can specify
+ funs to handle scanner events (event_fun), process the document
+ entities once identified (hook_fun), and decide what to do if the
+ scanner runs into eof before the document is complete
+ (continuation_fun).</para>
+
+ <para>You can also specify a path (fetch_path) as a list of
+ directories to search when fetching files. If the file in question
+ is not in the fetch_path, the URI will be used as a file
+ name.</para>
+
+
+ <section>
+ <title>Customization functions</title>
+ <para>The XML processor offers a number of hooks for
+ customization. These hooks are defined as function objects, and
+ can be provided by the caller.</para>
+
+ <para>The following customization functions are available. If
+ they also have access to their own state variable, the access
+ function for this state is identified within parentheses:</para>
+
+ <itemizedlist>
+
+ <listitem><para>event function (<computeroutput>
+ xmerl_scan:event_state/[1,2]
+ </computeroutput>)</para></listitem>
+
+ <listitem><para>hook function (<computeroutput>
+ xmerl_scan:hook_state/[1,2]
+ </computeroutput>)</para></listitem>
+
+ <listitem><para>fetch function (<computeroutput>
+ xmerl_scan:fetch_state/[1,2] </computeroutput>)
+ </para></listitem>
+
+ <listitem><para>continuation function (<computeroutput>
+ xmerl_scan:cont_state/[1,2] </computeroutput>)
+ </para></listitem>
+
+ <listitem><para>rules function (<computeroutput>
+ xmerl_scan:rules_state/[1,2] </computeroutput>)
+ </para></listitem>
+
+ <listitem><para>accumulator function</para></listitem>
+
+ <listitem><para>close function</para></listitem>
+
+ </itemizedlist>
+
+ <para>For all of the above state access functions, the function
+ with one argument
+ (e.g. <computeroutput>event_fun(GlobalState)</computeroutput>)
+ will read the state variable, while the function with two
+ arguments (e.g.: <computeroutput>event_fun(NewStateData,
+ GlobalState)</computeroutput>) will modify it.</para>
+
+ <para>For each function, the description starts with the syntax
+ for specifying the function in the
+ <computeroutput>Options</computeroutput> list. The general forms
+ are <computeroutput>{Tag, Fun}</computeroutput>, or
+ <computeroutput>{Tag, Fun, LocalState}</computeroutput>. The
+ second form can be used to initialize the state variable in
+ question.</para>
+
+ <section>
+ <title>User State</title>
+
+ <para>All customization functions are free to access a
+ &quot;User state&quot; variable. Care must of course be taken
+ to coordinate the use of this state. It is recommended that
+ functions, which do not really have anything to contribute to
+ the &quot;global&quot; user state, use their own state
+ variable instead. Another option (used in
+ e.g. <computeroutput>xmerl_eventp.erl</computeroutput>) is for
+ customization functions to share one of the local states (in
+ <computeroutput>xmerl_eventp.erl</computeroutput>, the
+ continuation function and the fetch function both acces the
+ <computeroutput>cont_state</computeroutput>.)</para>
+
+ <para>Functions to access user state:</para>
+
+ <itemizedlist>
+
+ <listitem><para><computeroutput>
+ xmerl_scan:user_state(GlobalState) </computeroutput>
+ </para></listitem>
+
+ <listitem><para><computeroutput>xmerl_scan:user_state(UserState',
+ GlobalState) </computeroutput></para></listitem>
+
+ </itemizedlist>
+
+ </section>
+ <section>
+ <title>Event Function</title>
+
+ <para><computeroutput>{event_fun, fun()} | {event_fun, fun(),
+ LocalState}</computeroutput></para>
+
+ <para>The event function is called at the beginning and at the
+ end of a parsed entity. It has the following format and
+ semantics:</para>
+
+<programlisting>
+<![CDATA[
+fun(Event, GlobalState) ->
+ EventState = xmerl_scan:event_state(GlobalState),
+ EventState' = foo(Event, EventState),
+ GlobalState' = xmerl_scan:event_state(EventState', GlobalState)
+end.
+]]></programlisting>
+
+ </section>
+ <section>
+ <title>Hook Function</title>
+ <para> <computeroutput>{hook_fun, fun()} | {hook_fun, fun(),
+ LocalState}</computeroutput></para>
+
+
+
+<para>The hook function is called when the processor has parsed a complete
+entity. Format and semantics:</para>
+
+<programlisting>
+<![CDATA[
+fun(Entity, GlobalState) ->
+ HookState = xmerl_scan:hook_state(GlobalState),
+ {TransformedEntity, HookState'} = foo(Entity, HookState),
+ GlobalState' = xmerl_scan:hook_state(HookState', GlobalState),
+ {TransformedEntity, GlobalState'}
+end.
+]]></programlisting>
+
+ <para>The relationship between the event function, the hook
+ function and the accumulator function is as follows:</para>
+
+ <orderedlist>
+ <listitem><para>The event function is first called with an
+ 'ended' event for the parsed entity.</para></listitem>
+
+ <listitem><para>The hook function is called, possibly
+ re-formatting the entity.</para></listitem>
+
+ <listitem><para>The acc function is called in order to
+ (optionally) add the re-formatted entity to the contents of
+ its parent element.</para></listitem>
+
+ </orderedlist>
+
+ </section>
+ <section>
+ <title>Fetch Function</title>
+<para>
+<computeroutput>{fetch_fun, fun()} | {fetch_fun, fun(), LocalState}</computeroutput>
+</para>
+<para>The fetch function is called in order to fetch an external resource
+(e.g. a DTD).</para>
+
+<para>The fetch function can respond with three different return values:</para>
+
+ <programlisting>
+<![CDATA[
+ Result ::=
+ {ok, GlobalState'} |
+ {ok, {file, Filename}, GlobalState'} |
+ {ok, {string, String}, GlobalState'}
+]]></programlisting>
+
+<para>Format and semantics:</para>
+
+ <programlisting>
+<![CDATA[
+fun(URI, GlobalState) ->
+ FetchState = xmerl_scan:fetch_state(GlobalState),
+ Result = foo(URI, FetchState). % Result being one of the above
+end.
+]]></programlisting>
+
+ </section>
+ <section>
+ <title>Continuation Function</title>
+<para>
+<computeroutput>{continuation_fun, fun()} | {continuation_fun, fun(), LocalState}</computeroutput>
+</para>
+<para>The continuation function is called when the parser encounters the end
+of the byte stream. Format and semantics:</para>
+
+ <programlisting>
+<![CDATA[
+fun(Continue, Exception, GlobalState) ->
+ ContState = xmerl_scan:cont_state(GlobalState),
+ {Result, ContState'} = get_more_bytes(ContState),
+ GlobalState' = xmerl_scan:cont_state(ContState', GlobalState),
+ case Result of
+ [] ->
+ GlobalState' = xmerl_scan:cont_state(ContState', GlobalState),
+ Exception(GlobalState');
+ MoreBytes ->
+ {MoreBytes', Rest} = end_on_whitespace_char(MoreBytes),
+ ContState'' = update_cont_state(Rest, ContState'),
+ GlobalState' = xmerl_scan:cont_state(ContState'', GlobalState),
+ Continue(MoreBytes', GlobalState')
+ end
+end.
+]]></programlisting>
+ </section>
+ <section>
+ <title>Rules Functions</title>
+ <para>
+<computeroutput>
+{rules, ReadFun : fun(), WriteFun : fun(), LocalState} |
+{rules, Table : ets()}</computeroutput>
+</para>
+ <para>The rules functions take care of storing scanner
+ information in a rules database. User-provided rules functions
+ may opt to store the information in mnesia, or perhaps in the
+ user_state(LocalState).</para>
+
+ <para>The following modes exist:</para>
+
+ <itemizedlist>
+
+ <listitem><para>If the user doesn't specify an option, the
+ scanner creates an ets table, and uses built-in functions to
+ read and write data to it. When the scanner is done, the ets
+ table is deleted.</para></listitem>
+
+ <listitem><para>If the user specifies an ets table via the
+ <computeroutput>{rules, Table}</computeroutput> option, the
+ scanner uses this table. When the scanner is done, it does
+ <emphasis>not</emphasis> delete the table.</para></listitem>
+
+ <listitem><para>If the user specifies read and write
+ functions, the scanner will use them instead.</para></listitem>
+
+ </itemizedlist>
+
+ <para>The format for the read and write functions are as
+ follows:</para>
+
+
+<programlisting>
+<![CDATA[
+WriteFun(Context, Name, Definition, ScannerState) -> NewScannerState.
+ReadFun(Context, Name, ScannerState) -> Definition | undefined.
+]]></programlisting>
+
+ <para>Here is a summary of the data objects currently being
+ written by the scanner:</para>
+
+ <table>
+ <title>Scanner data objects</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Context</entry>
+ <entry>Key Value</entry>
+ <entry>Definition</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>notation</entry>
+ <entry>NotationName</entry>
+ <entry><computeroutput>{system, SL} | {public, PIDL, SL}</computeroutput></entry>
+ </row>
+ <row>
+ <entry>elem_def</entry>
+ <entry>ElementName</entry>
+ <entry><computeroutput>#xmlElement{content = ContentSpec}</computeroutput></entry>
+ </row>
+ <row>
+ <entry>parameter_entity</entry>
+ <entry>PEName</entry>
+ <entry><computeroutput>PEDef</computeroutput></entry>
+ </row>
+ <row>
+ <entry>entity</entry>
+ <entry>EntityName</entry>
+ <entry><computeroutput>EntityDef</computeroutput></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+
+<programlisting>
+<![CDATA[
+ContentSpec ::= empty | any | ElemContent
+ElemContent ::= {Mode, Elems}
+Mode ::= seq | choice
+Elems ::= [Elem]
+Elem ::= '#PCDATA' | Name | ElemContent | {Occurrence, Elems}
+Occurrence ::= '*' | '?' | '+'
+]]></programlisting>
+ <note><para>When &lt;Elem&gt; is not wrapped with
+&lt;Occurrence&gt;, (Occurrence = once) is implied.</para></note>
+
+ </section>
+ <section>
+ <title>Accumulator Function</title>
+ <para><computeroutput>{acc_fun, fun()} | {acc_fun, fun(),
+ LocalState}</computeroutput></para>
+
+ <para>The accumulator function is called to accumulate the
+ contents of an entity.When parsing very large files, it may
+ not be desireable to do so.In this case, an acc function can
+ be provided that simply doesn't accumulate.</para>
+
+ <para>Note that it is possible to even modify the parsed
+ entity before accumulating it, but this must be done with
+ care. <computeroutput>xmerl_scan</computeroutput> performs
+ post-processing of the element for namespace management. Thus,
+ the element must keep its original structure for this to
+ work.</para>
+
+ <para>The acc function has the following format and
+ semantics:</para>
+
+ <programlisting>
+<![CDATA[
+%% default accumulating acc fun
+fun(ParsedEntity, Acc, GlobalState) ->
+ {[X|Acc], GlobalState}.
+
+%% non-accumulating acc fun
+fun(ParsedEntity, Acc, GlobalState) ->
+ {Acc, GlobalState}.
+]]></programlisting>
+ </section>
+ <section>
+ <title>Close Function</title>
+
+ <para>The close function is called when a document (either the
+ main document or an external DTD) has been completely
+ parsed. When xmerl_scan was started using
+ <computeroutput>xmerl_scan:file/[1,2]</computeroutput>, the
+ file will be read in full, and closed immediately, before the
+ parsing starts, so when the close function is called, it will
+ not need to actually close the file. In this case, the close
+ function will be a good place to modify the state
+ variables.</para>
+
+ <para>Format and semantics:</para>
+
+ <programlisting>
+<![CDATA[
+fun(GlobalState) ->
+ GlobalState' = .... % state variables may be altered
+]]></programlisting>
+ </section>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>XPATH</title>
+
+ <programlisting>
+<![CDATA[
+xmerl_xpath:string(QueryString, #xmlElement{}) ->
+ [DocEntity]
+
+DocEntity : #xmlElement{}
+ | #xmlAttribute{}
+ | #xmlText{}
+ | #xmlPI{}
+ | #xmlComment{}
+]]></programlisting>
+
+ <para>The xmerl_xpath module does seem to handle the entire XPATH
+ 1.0 spec, but I haven't tested that much yet. The grammar is
+ defined in
+ <computeroutput>xmerl_xpath_parse.yrl</computeroutput>. The core
+ functions are defined in
+ <computeroutput>xmerl_xpath_pred.erl</computeroutput>.</para>
+ </section>
+ <section>
+ <title>Some useful shell commands for debugging the XPath parser</title>
+<para>
+ <command>
+<![CDATA[
+c(xmerl_xpath_scan).
+yecc:yecc("xmerl_xpath_parse.yrl", "xmerl_xpath_parse", true, []).
+c(xmerl_xpath_parse).
+
+xmerl_xpath_parse:parse(xmerl_xpath_scan:tokens("position() > -1")).
+xmerl_xpath_parse:parse(xmerl_xpath_scan:tokens("5 * 6 div 2")).
+xmerl_xpath_parse:parse(xmerl_xpath_scan:tokens("5 + 6 mod 2")).
+xmerl_xpath_parse:parse(xmerl_xpath_scan:tokens("5 * 6")).
+xmerl_xpath_parse:parse(xmerl_xpath_scan:tokens("5 * 6")).
+xmerl_xpath_parse:parse(xmerl_xpath_scan:tokens("-----6")).
+xmerl_xpath_parse:parse(xmerl_xpath_scan:tokens("parent::node()")).
+xmerl_xpath_parse:parse(xmerl_xpath_scan:tokens("descendant-or-self::node()")).
+xmerl_xpath_parse:parse(xmerl_xpath_scan:tokens("parent::processing-instruction('foo')")).]]></command></para>
+ </section>
+ <section>
+ <title>Erlang Data Structure Export</title>
+
+ <para>The idea as follows:</para>
+
+ <para>The Erlang data structure should look like this:</para>
+ <programlisting>
+<![CDATA[
+Element: {Tag, Attributes, Content}
+Tag : atom()
+Attributes: [{Key, Value}]
+Content: [String | Element]
+String: [char() | binary() | String]
+]]></programlisting>
+
+ <para>Some short forms are allowed:</para>
+ <programlisting>
+<![CDATA[
+{Tag, Content} -> {Tag, [], Content}
+Tag -> {Tag, [], []}
+]]></programlisting>
+
+ <para>Note that content lists must be flat, but strings can be
+ deep.</para>
+
+ <para>It is also allowed to include normal
+ <computeroutput>#xml...</computeroutput> elements in the simple
+ format.</para>
+
+ <para><computeroutput>xmerl:export_simple(Data,
+ Callback)</computeroutput> takes the above data structure and
+ exports it, using the callback module
+ <computeroutput>Callback</computeroutput>.</para>
+
+ <para>The callback module should contain hook functions for all
+ tags present in the data structure. The hook function must have
+ the format:</para>
+ <para><computeroutput> Tag(Data, Attrs, Parents, E)
+ </computeroutput></para>
+
+ <para>where E is an <computeroutput>#xmlElement{}</computeroutput>
+ record (see <computeroutput>xmerl.hrl</computeroutput>).</para>
+
+ <para>Attrs is converted from the simple <computeroutput>[{Key,
+ Value}]</computeroutput> to
+ <computeroutput>[#xmlAttribute{}]</computeroutput></para>
+
+ <para>Parents is a list of <computeroutput>[{ParentTag,
+ ParentTagPosition}]</computeroutput>.</para>
+
+ <para>The hook function should return either the Data to be
+ exported, or the tuple <computeroutput>{'#xml-redefine#',
+ NewStructure}</computeroutput>, where
+ <computeroutput>NewStructure</computeroutput> is an element (which
+ can be simple), or a (simple-) content list wrapped in a 1-tuple
+ as <computeroutput>{NewContent}</computeroutput>.</para>
+
+ <para>The callback module can inherit definitions from other
+ callback modules, through the required function
+ <computeroutput>'#xml-interitance#() ->
+ [ModuleName]</computeroutput>. </para>
+
+ <para>As long as a tag is represented in one of the callback
+ modules, things will work. It is of course also possible to
+ redefine a tag.</para>
+ <section>
+ <title>XSLT like transforms</title>
+ <para>See separate document <ulink url="xmerl_xs.html" >xmerl_xs.html
+ </ulink></para>.
+ </section>
+ </section>
+
+</article>
diff --git a/lib/xmerl/doc/examples/xml/xmerl_xs.xml b/lib/xmerl/doc/examples/xml/xmerl_xs.xml
new file mode 100644
index 0000000000..9a798808b9
--- /dev/null
+++ b/lib/xmerl/doc/examples/xml/xmerl_xs.xml
@@ -0,0 +1,541 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE article
+ PUBLIC "-//OASIS//DTD Simplified DocBook XML V1.0//EN"
+ "http://www.oasis-open.org/docbook/xml/simple/1.0/sdocbook.dtd">
+
+<article lang="en" xml:lang="en" >
+ <articleinfo>
+ <title>XSLT like transformations in Erlang </title>
+ <subtitle>User Guide</subtitle>
+ <authorgroup>
+ <author>
+ <firstname>Mikael</firstname>
+ <surname>Karlsson</surname>
+ </author>
+ </authorgroup>
+ <revhistory>
+ <revision>
+ <revnumber>1.0</revnumber><date>2002-10-25</date>
+ <revremark>First Draft</revremark>
+ </revision>
+ <revision>
+ <revnumber>1.1</revnumber><date>2003-02-05</date>
+ <revremark>Moved module xserl to xmerl application, renamed to
+ xmerl_xs</revremark>
+ </revision>
+ </revhistory>
+ <abstract>
+ <para>Erlang has similarities to XSLT since both languages
+ have a functional programming approach. Using the xpath implementation
+ in the existing xmerl application it is possible to write XSLT
+ like transforms in Erlang. One can also combine the
+ transformations with the erlang scripting possibility
+ in the yaws webserver to implement "on the fly" html
+ conversions of xml documents.
+ </para>
+ </abstract>
+ </articleinfo>
+
+
+ <section>
+ <title>Terminology</title>
+ <variablelist>
+ <varlistentry>
+ <term>XML</term>
+ <listitem>
+ <para>Extensible Markup Language</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>XSLT</term>
+ <listitem>
+ <para>Extensible Stylesheet Language: Transformations</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+ <section>
+ <title>Introduction</title>
+ <para>XSLT stylesheets are often used when transforming XML
+ documents, to other XML documents or (X)HTML for presentation.
+ There are a number of brick-sized books written on the
+ topic. XSLT contains quite many
+ functions and learning them all may take some effort, which
+ could be a reason why the author only has reached a basic level of
+ understanding. This document assumes a basic level of
+ understanding of XSLT.
+ </para>
+ <para>Since XSLT is based on a functional programming approach
+ with pattern matching and recursion it is possible to write
+ similar style sheets in Erlang. At least for basic
+ transforms. XPath which is used in XSLT is also already
+ implemented in the xmerl application written i Erlang. This
+ document describes how to use the XPath implementation together
+ with Erlangs pattern matching and a couple of functions to write
+ XSLT like transforms.</para>
+ <para>This approach is probably easier for an Erlanger but
+ if you need to use real XSLT stylesheets in order to "comply to
+ the standard" there is an adapter available to the Sablotron
+ XSLT package which is written i C++.
+ </para>
+ <para>
+ This document is written in the Simplified Docbook DTD which is
+ a subset of the complete one and converted to xhtml using a
+ stylesheet written in Erlang.
+ </para>
+ </section>
+
+ <section>
+ <title>Tools</title>
+ <section>
+ <title>xmerl</title>
+ <para><ulink url="http://sowap.sourceforge.net/" >xmerl</ulink>
+ is a xml parser written in Erlang</para>
+ <section>
+ <title>xmerl_xpath</title>
+ <para>XPath is in important part of XSLT and is implemented in
+ xmerl</para>
+ </section>
+ <section>
+ <title>xmerl_xs</title>
+ <para>
+ <ulink url="xmerl_xs.yaws" >xmerl_xs</ulink> is a very small
+ module acting as "syntactic sugar" for the XSLT lookalike
+ transforms. It uses xmerl_xpath.
+ </para>
+ </section>
+ </section>
+
+ <section>
+ <title>yaws</title>
+ <para>
+ <ulink url="http://yaws.hyber.org/" >Yaws</ulink>, Yet Another
+ Webserver, is a web server written in Erlang that support dynamic
+ content generation using embedded scripts, also written in Erlang.
+ </para>
+<!--
+ <figure>
+ <title>The Yaws logo</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="yaws_pb.gif" format="GIF" scale="50%"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+-->
+ <para>Yaws is not needed to make the XSLT like transformations, but
+ combining yaws and xmerl it is possible to do transformations
+ of XML documents to HTML in realtime, when clients requests a
+ web page. As an example I am able to edit this document using
+ emacs with psgml tools, save the document and just do a reload
+ in my browser to see the result. The parse/transform time is not
+ visually different compared to loading any other document in the
+ browser.
+ </para>
+ </section>
+
+ </section>
+
+ <section>
+ <title>Transformations</title>
+<para>
+ When xmerl_scan parses an xml string/file it returns a record of:
+</para>
+ <programlisting>
+<![CDATA[
+ -record(xmlElement, {
+ name,
+ parents = [],
+ pos,
+ attributes = [],
+ content = [],
+ language = [],
+ expanded_name = [],
+ nsinfo = [],% {Prefix, Local} | []
+ namespace = #xmlNamespace{}
+ }).
+ ]]>
+</programlisting>
+<para>
+ Were content is a mixed list of yet other xmlElement records and/or
+ xmlText (or other node types).
+</para>
+ <section>
+ <title>xmerl_xs functions</title>
+ <para>
+ Functions used:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term>xslapply/2</term>
+ <listitem>
+ <para>function to make things look similar
+ to xsl:apply-templates.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>value_of/1</term>
+ <listitem>
+ <para>Conatenates all text nodes within a tree.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>select/2</term>
+ <listitem>
+ <para>select(Str, E) extracts nodes from the XML tree using
+ xmerl_xpath.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>built_in_rules/2</term>
+ <listitem>
+ <para>The default fallback behaviour, template funs should
+ end with:
+ <computeroutput>template(E)->built_in_rules(fun
+ template/1, E).
+</computeroutput>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+<note><para>Text is escaped using xmerl_lib:export_text/1 for
+ "&lt;", "&gt;" and other relevant xml
+ characters when exported. So the value_of/1 and built_in_rules/2
+ functions should be replaced when not exporting to xml or html.
+</para></note>
+ </section>
+
+
+<section><title>Examples</title>
+ <example>
+ <title>Using xslapply</title>
+ <para>original XSLT:</para>
+ <programlisting>
+<![CDATA[
+ <xsl:template match="doc/title">
+ <h1>
+ <xsl:apply-templates/>
+ </h1>
+ </xsl:template>
+ ]]>
+ </programlisting>
+ <para>
+ becomes in Erlang:</para>
+ <programlisting>
+<![CDATA[
+ template(E = #xmlElement{ parents=[{'doc',_}|_], name='title'}) ->
+ ["<h1>",
+ xslapply(fun template/1, E),
+ "</h1>"];
+ ]]>
+ </programlisting>
+
+ </example>
+ <example>
+ <title>Using value_of and select</title>
+ <programlisting>
+<![CDATA[
+ <xsl:template match="title">
+ <div align="center"><h1><xsl:value-of select="." /></h1></div>
+ </xsl:template>
+ ]]>
+ </programlisting>
+ <para>
+ becomes:
+ </para>
+ <programlisting>
+<![CDATA[
+template(E = #xmlElement{name='title'}) ->
+ ["<div align=\"center\"><h1>", value_of(select(".", E)), "</h1></div>"];
+ ]]>
+ </programlisting>
+ </example>
+ <example>
+ <title>Simple xsl stylesheet</title>
+<para>
+ A complete example with the XSLT sheet in the xmerl distribution.
+</para>
+ <programlisting>
+<![CDATA[
+
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns="http://www.w3.org/TR/xhtml1/strict">
+
+ <xsl:strip-space elements="doc chapter section"/>
+ <xsl:output
+ method="xml"
+ indent="yes"
+ encoding="iso-8859-1"
+ />
+
+ <xsl:template match="doc">
+ <html>
+ <head>
+ <title>
+ <xsl:value-of select="title"/>
+ </title>
+ </head>
+ <body>
+ <xsl:apply-templates/>
+ </body>
+ </html>
+ </xsl:template>
+
+ <xsl:template match="doc/title">
+ <h1>
+ <xsl:apply-templates/>
+ </h1>
+ </xsl:template>
+
+ <xsl:template match="chapter/title">
+ <h2>
+ <xsl:apply-templates/>
+ </h2>
+ </xsl:template>
+
+ <xsl:template match="section/title">
+ <h3>
+ <xsl:apply-templates/>
+ </h3>
+ </xsl:template>
+
+ <xsl:template match="para">
+ <p>
+ <xsl:apply-templates/>
+ </p>
+ </xsl:template>
+
+ <xsl:template match="note">
+ <p class="note">
+ <b>NOTE: </b>
+ <xsl:apply-templates/>
+ </p>
+ </xsl:template>
+
+ <xsl:template match="emph">
+ <em>
+ <xsl:apply-templates/>
+ </em>
+ </xsl:template>
+
+</xsl:stylesheet>
+ ]]>
+ </programlisting>
+ </example>
+ <example>
+ <title>Erlang version</title>
+ <para>
+ Erlang transformation of previous example:
+ </para>
+ <programlisting>
+<![CDATA[
+
+-include("xmerl.hrl").
+
+-import(xmerl_xs,
+ [ xslapply/2, value_of/1, select/2, built_in_rules/2 ]).
+
+doctype()->
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\
+ \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd \">".
+
+process_xml(Doc)->
+ template(Doc).
+
+template(E = #xmlElement{name='doc'})->
+ [ "<\?xml version=\"1.0\" encoding=\"iso-8859-1\"\?>",
+ doctype(),
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\" >"
+ "<head>"
+ "<title>", value_of(select("title",E)), "</title>"
+ "</head>"
+ "<body>",
+ xslapply( fun template/1, E),
+ "</body>"
+ "</html>" ];
+
+
+template(E = #xmlElement{ parents=[{'doc',_}|_], name='title'}) ->
+ ["<h1>",
+ xslapply( fun template/1, E),
+ "</h1>"];
+
+template(E = #xmlElement{ parents=[{'chapter',_}|_], name='title'}) ->
+ ["<h2>",
+ xslapply( fun template/1, E),
+ "</h2>"];
+
+template(E = #xmlElement{ parents=[{'section',_}|_], name='title'}) ->
+ ["<h3>",
+ xslapply( fun template/1, E),
+ "</h3>"];
+
+template(E = #xmlElement{ name='para'}) ->
+ ["<p>", xslapply( fun template/1, E), "</p>"];
+
+template(E = #xmlElement{ name='note'}) ->
+ ["<p class=\"note\">"
+ "<b>NOTE: </b>",
+ xslapply( fun template/1, E),
+ "</p>"];
+
+template(E = #xmlElement{ name='emph'}) ->
+ ["<em>", xslapply( fun template/1, E), "</em>"];
+
+template(E)->
+ built_in_rules( fun template/1, E).
+ ]]>
+ </programlisting>
+ <para>
+ It is important to end with a call to
+ <computeroutput>xmerl_xs:built_in_rules/2</computeroutput>
+ if you want any text to be written in "push" transforms.
+ That are the ones using a lot <computeroutput>xslapply( fun
+ template/1, E )</computeroutput> instead of
+ <computeroutput>value_of(select("xpath",E))</computeroutput>,
+ which is pull...
+ </para>
+ </example>
+<para>The largest example is the stylesheet to transform this document
+ from the Simplified Docbook XML format to xhtml. The source
+ file is <computeroutput>sdocbook2xhtml.erl</computeroutput>.
+</para>
+</section>
+ <section>
+ <title>Tips and tricks</title>
+ <section>
+ <title>for-each</title>
+ <para>The function for-each is quite common in XSLT stylesheets.
+ It can often be rewritten and replaced by select/1. Since
+ select/1 returns a list of #xmlElements and xslapply/2
+ traverses them it is more or less the same as to loop over all
+ the elements.
+ </para>
+ </section>
+ <section>
+ <title>position()</title>
+ <para>The XSLT position() and #xmlElement.pos are not the
+ same. One has to make an own position in Erlang.</para>
+ <example>
+ <title>Counting positions</title>
+ <programlisting>
+<![CDATA[
+<xsl:template match="stanza">
+ <p><xsl:apply-templates select="line" /></p>
+</xsl:template>
+
+<xsl:template match="line">
+ <xsl:if test="position() mod 2 = 0">&#160;&#160;</xsl:if>
+ <xsl:value-of select="." /><br />
+</xsl:template>
+ ]]>
+ </programlisting>
+<para>Can be written as</para>
+ <programlisting>
+<![CDATA[
+template(E = #xmlElement{name='stanza'}) ->
+ {Lines,LineNo} = lists:mapfoldl(fun template_pos/2, 1, select("line", E)),
+ ["<p>", Lines, "</p>"].
+
+template_pos(E = #xmlElement{name='line'}, P) ->
+ {[indent_line(P rem 2), value_of(E#xmlElement.content), "<br />"], P + 1 }.
+
+indent_line(0)->"&#160;&#160;";
+indent_line(_)->"".
+ ]]>
+ </programlisting>
+ </example>
+ </section>
+ <section>
+ <title>Global tree awareness</title>
+ <para>In XSLT you have "root" access to the top of the tree
+ with XPath, even though you are somewhere deep in your
+ tree.</para>
+ <para>The xslapply/2 function only carries back the child part
+ of the tree to the template fun. But it is quite easy to write
+ template funs that handles both the child and top tree.</para>
+ <example>
+ <title>Passing the root tree</title>
+ <para>The following example piece will prepend the article
+ title to any section title</para>
+ <programlisting>
+<![CDATA[
+template(E = #xmlElement{name='title'}, ETop ) ->
+ ["<h3>", value_of(select("title", ETop))," - ",
+ xslapply( fun(A) -> template(A, ETop) end, E),
+ "</h3>"];
+ ]]>
+ </programlisting>
+ </example>
+ </section>
+ </section>
+
+ </section>
+
+
+ <section>
+ <title>Utility functions</title>
+ <para>
+ The module xmerl_xs contains the functions
+ <computeroutput>mapxml/2, foldxml/3</computeroutput> and
+ <computeroutput> mapfoldxml/3</computeroutput> to traverse
+ <literal>#xmlElement</literal> trees. They can be used in order
+ to build cross-references, see sdocbook2xhtml.erl for instance
+ where <computeroutput>foldxml/3</computeroutput> and
+ <computeroutput> mapfoldxml/3</computeroutput> are used to
+ number chapters, examples and figures and to build the Table of
+ contents for the document.
+ </para>
+ </section>
+
+
+ <section>
+ <title>Future enhancements</title>
+ <para>
+ More wish- than task-list at the moment.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>More stylesheets</para>
+ </listitem>
+ <listitem>
+ <para>On the fly exports to PDF for printing and also more
+ "polished" presentations.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>References</title>
+ <orderedlist>
+ <listitem>
+ <para><ulink url="../xml/xmerl_xs.xml" >XML source
+ file</ulink> for this document.
+ </para>
+ </listitem>
+ <listitem>
+ <para><ulink url="../xs/sdocbook2xhtml.erl" >Erlang style
+ sheet</ulink> used for this document. (Simplified Docbook DTD).</para>
+ </listitem>
+ <listitem>
+ <para><ulink url="http://www.erlang.org/" >Open Source Erlang</ulink>
+ </para>
+ </listitem>
+ </orderedlist>
+
+ </section>
+</article>
+
+<!--
+Local Variables:
+mode: xml
+sgml-indent-step: 2
+sgml-indent-data: t
+sgml-set-face: t
+sgml-insert-missing-element-comment: nil
+End:
+-->
diff --git a/lib/xmerl/doc/examples/xserl_test.erl b/lib/xmerl/doc/examples/xserl_test.erl
new file mode 100644
index 0000000000..69db75cfe8
--- /dev/null
+++ b/lib/xmerl/doc/examples/xserl_test.erl
@@ -0,0 +1,85 @@
+-module(xserl_test).
+-include("xmerl.hrl").
+-import(xserl,[ xslapply/2, value_of/1, select/2, built_in_rules/2 ]).
+-export([process_xml/1,test/0]).
+
+doctype()->
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\
+ \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd \">".
+
+test() ->
+ Str= "<?xml version=\"1.0\"?>"
+ "<doc xmlns='urn:loc.gov:books' xmlns:isbn='urn:ISBN:0-395-36341-6'>"
+ "<title>Cheaper by the Dozen</title>"
+ "<isbn:number>1568491379</isbn:number>"
+ "<note>"
+ "<!-- make HTML the default namespace for some commentary -->"
+ "<p xmlns='urn:w3-org-ns:HTML'>"
+ "This is a <i>funny</i> book!"
+ "</p>"
+ "</note>"
+ "</doc>",
+ {Doc,_}=xmerl_scan:string(Str,[{fetch_fun, fun(DTDSpec,S) -> {ok,S} end}]),
+
+ process_xml(Doc).
+
+process_xml(Doc)->
+ template(Doc).
+
+template(E = #xmlElement{name='doc'})->
+ [ "<\?xml version=\"1.0\" encoding=\"iso-8859-1\"\?>",
+ doctype(),
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\" >"
+ "<head>"
+ "<title>", xserl:value_of(select("title",E)), "</title>"
+ "</head>"
+ "<body>",
+ xslapply( fun template/1, E),
+ "</body>"
+ "</html>" ];
+
+
+template(E = #xmlElement{ parents=[{'doc',_}|_], name='title'}) ->
+ ["<h1>",
+%% xslapply( fun template/1, E),
+%% same as
+ lists:map( fun template/1, E#xmlElement.content ),
+ "</h1>"];
+
+template(E = #xmlElement{ parents=[{'chapter',_}|_], name='title'}) ->
+ ["<h2>",
+ xslapply( fun template/1, E),
+ "</h2>"];
+
+template(E = #xmlElement{ parents=[{'section',_}|_], name='title'}) ->
+ ["<h3>",
+ xslapply( fun template/1, E),
+ "</h3>"];
+
+template(E = #xmlElement{ name='para'}) ->
+ ["<p>",
+ xslapply( fun template/1, E),
+ "</p>"];
+
+template(E = #xmlElement{ name='note'}) ->
+ ["<p class=\"note\">"
+ "<b>NOTE: </b>",
+ xslapply( fun template/1, E),
+ "</p>"];
+
+template(E = #xmlElement{ name='emph'}) ->
+ ["<em>",
+ xslapply( fun template/1, E),
+ "</em>"];
+
+template(E)->
+ built_in_rules( fun template/1, E).
+
+%% It is important to end with a call to xserl:built_in_rules/2
+%% if you want any text to be written in "push" transforms.
+%% That are the ones using a lot xslapply( fun template/1, E )
+%% instead of value_of(select("xpath",E)), which is pull...
+%% Could maybe be caught as an exception in xslapply instead,
+%% but I think that could degrade performance - having an
+%% exception for every #xmlText element.
+
diff --git a/lib/xmerl/doc/src/notes.xml b/lib/xmerl/doc/src/notes.xml
index 8542435456..15c42d6f6a 100644
--- a/lib/xmerl/doc/src/notes.xml
+++ b/lib/xmerl/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,109 @@
<p>This document describes the changes made to the Xmerl application.</p>
+<section><title>Xmerl 1.2.10</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fixed a schema search bug in xmerl_xsd. </p> <p> A
+ new flag was needed in the xsd_state record so if the
+ state is saved there is an incompatibility and a state
+ conversion is needed. </p>
+ <p>
+ *** INCOMPATIBILITY with R14B03 ***</p>
+ <p>
+ Own Id: OTP-9410</p>
+ </item>
+ <item>
+ <p> Fixed xmerl_scan problems with entities in attribute
+ values. </p>
+ <p>
+ Own Id: OTP-9411</p>
+ </item>
+ <item>
+ <p> Streaming bug in xmerl_scan. </p> <p> If the
+ continuation_fun runs out of input at the end of an
+ attribute value then it crashed. (Thanks to Simon
+ Cornish) </p>
+ <p>
+ Own Id: OTP-9457</p>
+ </item>
+ <item>
+ <p>
+ Fixed xmerl_ucs UCS2 little endian en/decoding</p>
+ <p>
+ Corrected number of shift bytes in
+ xmerl_ucs:char_to_ucs2le and recursive call from
+ from_ucs2le to from_ucs4le. (Thanks to Michal Ptaszek)</p>
+ <p>
+ Own Id: OTP-9548</p>
+ </item>
+ <item>
+ <p>
+ Add latin9 (iso-8859-15) support in xmerl_ucs (Thanks to
+ David Julien)</p>
+ <p>
+ Own Id: OTP-9552</p>
+ </item>
+ <item>
+ <p>
+ Improve spelling throughout documentation, code comments
+ and error messages</p>
+ <p>
+ Own Id: OTP-9555</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Xmerl 1.2.9</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix minor typos and improve punctuation in the
+ xmerl_xpath @doc comment (Thanks to Marcus Marinelli)</p>
+ <p>
+ Own Id: OTP-9187</p>
+ </item>
+ <item>
+ <p>
+ Prevent xmerl from over-normalizing character references
+ in attributes</p>
+ <p>
+ Section 3.3.3 of the XML Recommendation gives the rules
+ for attribute-value normalization. One of those rules
+ requires that character references not be re-normalized
+ after being replaced with the referenced characters.
+ (Thanks to Tom Moertel)</p>
+ <p>
+ Own Id: OTP-9274</p>
+ </item>
+ <item>
+ <p> Fixed the default encoding option in SAX parser. </p>
+ <p>
+ Own Id: OTP-9288</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Added the xmerl test suites and examples to the open
+ source distribution. </p>
+ <p>
+ Own Id: OTP-9228</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Xmerl 1.2.8</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/xmerl/include/xmerl_xsd.hrl b/lib/xmerl/include/xmerl_xsd.hrl
index b527accc8c..6dad7d8ff0 100644
--- a/lib/xmerl/include/xmerl_xsd.hrl
+++ b/lib/xmerl/include/xmerl_xsd.hrl
@@ -36,6 +36,7 @@
schema_name,
vsn,
schema_preprocessed=false,
+ external_xsd_base=false,
xsd_base,
xml_options=[],
scope=[],
diff --git a/lib/xmerl/src/xmerl.erl b/lib/xmerl/src/xmerl.erl
index cf78f7bdf7..2332517988 100644
--- a/lib/xmerl/src/xmerl.erl
+++ b/lib/xmerl/src/xmerl.erl
@@ -307,7 +307,7 @@ apply_cb(Ms, F, Df, Args) ->
apply_cb([M|Ms], F, Df, Args, Ms0) ->
case catch apply(M, F, Args) of
- {'EXIT', {undef,[{M,F,_}|_]}} ->
+ {'EXIT', {undef,[{M,F,_,_}|_]}} ->
apply_cb(Ms, F, Df, Args, Ms0);
{'EXIT', Reason} ->
exit(Reason);
diff --git a/lib/xmerl/src/xmerl_sax_parser.erl b/lib/xmerl/src/xmerl_sax_parser.erl
index eb9f8deec6..45e2a928ac 100644
--- a/lib/xmerl/src/xmerl_sax_parser.erl
+++ b/lib/xmerl/src/xmerl_sax_parser.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -263,11 +263,11 @@ detect_charset_1(<<16#3C, 16#3F, 16#78, 16#6D, 16#6C, Xml2/binary>> = Xml, State
{Xml, State#xmerl_sax_parser_state{encoding=Enc}}
end;
_ ->
- {Xml, State#xmerl_sax_parser_state{encoding=utf8}}
+ {Xml, State}
end
end;
detect_charset_1(Xml, State) ->
- {Xml, State#xmerl_sax_parser_state{encoding=utf8}}.
+ {Xml, State}.
%%----------------------------------------------------------------------
%% Function: convert_encoding(Enc)
@@ -278,6 +278,7 @@ detect_charset_1(Xml, State) ->
convert_encoding(Enc) -> %% Just for 7,8 bit + utf8
case string:to_lower(Enc) of
"utf-8" -> utf8;
+ "us-ascii" -> utf8;
"iso-8859-1" -> latin1; % Handle all iso-8859 as latin1
"iso-8859-2" -> latin1;
"iso-8859-3" -> latin1;
diff --git a/lib/xmerl/src/xmerl_scan.erl b/lib/xmerl/src/xmerl_scan.erl
index e07d495fc7..25c6547497 100644
--- a/lib/xmerl/src/xmerl_scan.erl
+++ b/lib/xmerl/src/xmerl_scan.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -102,6 +102,7 @@
%% declaration. </dd>
%% </dl>
+
-module(xmerl_scan).
-vsn('0.20').
-date('03-09-16').
@@ -2073,10 +2074,10 @@ scan_element(T, S, Pos, Name, StartL, StartC, Attrs, Lang, Parents,
{AttName, NamespaceInfo, T1, S1} = scan_name(T, S),
{T2, S2} = scan_eq(T1, S1),
{AttType,_DefaultDecl} = get_att_type(S2,AttName,Name),
- {AttValue, T3, S3,IsNorm} = scan_att_value(T2, S2, AttType),
+ {AttValue, T3a, S3a,IsNorm} = scan_att_value(T2, S2, AttType),
%% check_default_value(S3,DefaultDecl,AttValue),
NewNS = check_namespace(AttName, NamespaceInfo, AttValue, NS),
- wfc_whitespace_betw_attrs(hd(T3),S3),
+ {T3,S3} = wfc_whitespace_betw_attrs(T3a,S3a),
?strip4,
AttrPos = case Attrs of
[] ->
@@ -2275,7 +2276,7 @@ scan_att_chars([H|T], S0, H, Acc, TmpAcc,AttType,IsNorm) -> % End quote
true ->
normalize(Acc,S,IsNorm)
end,
- {lists:reverse(Acc2), T, S2,IsNorm2};
+ {lists:flatten(lists:reverse(Acc2)), T, S2,IsNorm2};
scan_att_chars("&" ++ T, S0, Delim, Acc, TmpAcc,AT,IsNorm) -> % Reference
?bump_col(1),
{ExpRef, T1, S1} = scan_reference(T, S),
@@ -2283,8 +2284,16 @@ scan_att_chars("&" ++ T, S0, Delim, Acc, TmpAcc,AT,IsNorm) -> % Reference
true ->
scan_att_chars(T1,S1,Delim,[ExpRef|Acc],[ExpRef|TmpAcc],AT,IsNorm);
_ ->
- scan_att_chars(string_to_char_set(S#xmerl_scanner.encoding,ExpRef)
- ++ T1, S1, Delim, Acc,TmpAcc, AT,IsNorm)
+ Ch = string_to_char_set(S#xmerl_scanner.encoding, ExpRef),
+ case T of
+ "#" ++ _ ->
+ %% normalization rules (sec 3.3.3) require that for
+ %% character references, the referenced character be
+ %% added directly to the normalized value
+ scan_att_chars(T1, S1, Delim, Ch ++ Acc,TmpAcc, AT,IsNorm);
+ _ ->
+ scan_att_chars(Ch ++ T1, S1, Delim, Acc,TmpAcc, AT,IsNorm)
+ end
end;
scan_att_chars("<" ++ _T, S0, _Delim, _Acc,_, _,_) -> % Tags not allowed here
?fatal(unexpected_char, S0);
@@ -3275,12 +3284,17 @@ wfc_legal_char(Ch,S) ->
end.
-wfc_whitespace_betw_attrs(WS,_S) when ?whitespace(WS) ->
- ok;
-wfc_whitespace_betw_attrs($/,_S) ->
- ok;
-wfc_whitespace_betw_attrs($>,_S) ->
- ok;
+wfc_whitespace_betw_attrs([WS |_]=L,S) when ?whitespace(WS) ->
+ {L,S};
+wfc_whitespace_betw_attrs([$/ |_]=L,S) ->
+ {L,S};
+wfc_whitespace_betw_attrs([$> |_]=L,S) ->
+ {L,S};
+wfc_whitespace_betw_attrs([],S=#xmerl_scanner{continuation_fun = F}) ->
+ ?dbg("cont()...~n", []),
+ F(fun(MoreBytes, S1) -> wfc_whitespace_betw_attrs(MoreBytes, S1) end,
+ fun(S1) -> ?fatal(unexpected_end, S1) end,
+ S);
wfc_whitespace_betw_attrs(_,S) ->
?fatal({whitespace_required_between_attributes},S).
@@ -3909,7 +3923,7 @@ schemaLocations(#xmlElement{attributes=Atts,xmlbase=_Base}) ->
case lists:dropwhile(Pred,Atts) of
[#xmlAttribute{value=Paths}|_] ->
- case string:tokens(Paths," ") of
+ case string:tokens(Paths," \n\t\r") of
L when length(L) > 0 ->
case length(L) rem 2 of
0 ->
diff --git a/lib/xmerl/src/xmerl_ucs.erl b/lib/xmerl/src/xmerl_ucs.erl
index 7c45c838ab..6550a9d954 100644
--- a/lib/xmerl/src/xmerl_ucs.erl
+++ b/lib/xmerl/src/xmerl_ucs.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -43,6 +43,7 @@
-export([to_utf16be/1, from_utf16be/1, from_utf16be/2]).
-export([to_utf16le/1, from_utf16le/1, from_utf16le/2]).
-export([to_utf8/1, from_utf8/1]).
+-export([from_latin9/1]).
%%% NB: Non-canonical UTF-8 encodings and incorrectly used
%%% surrogate-pair codes are disallowed by this code. There are
@@ -177,13 +178,27 @@ to_utf8(List) when is_list(List) -> lists:flatmap(fun to_utf8/1, List);
to_utf8(Ch) -> char_to_utf8(Ch).
from_utf8(Bin) when is_binary(Bin) -> from_utf8(binary_to_list(Bin));
-from_utf8(List) ->
+from_utf8(List) ->
case expand_utf8(List) of
{Result,0} -> Result;
{_Res,_NumBadChar} ->
exit({ucs,{bad_utf8_character_code}})
end.
+%%% Latin9 support
+from_latin9(Bin) when is_binary(Bin) -> from_latin9(binary_to_list(Bin));
+from_latin9(List) ->
+ [ latin9_to_ucs4(Char) || Char <- List].
+
+latin9_to_ucs4(16#A4) -> 16#20AC;
+latin9_to_ucs4(16#A6) -> 16#160;
+latin9_to_ucs4(16#A8) -> 16#161;
+latin9_to_ucs4(16#B4) -> 16#17D;
+latin9_to_ucs4(16#B8) -> 16#17E;
+latin9_to_ucs4(16#BC) -> 16#152;
+latin9_to_ucs4(16#BD) -> 16#153;
+latin9_to_ucs4(16#BE) -> 16#178;
+latin9_to_ucs4(Other) -> Other.
@@ -238,7 +253,7 @@ from_ucs4le(Bin,Acc,Tail) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% UCS-2 support
-%%% FIXME! Don't know how to encode UCS-2!!
+%%% FIXME! Don't know how to encode UCS-2!!
%%% Currently I just encode as UCS-4, but strips the 16 higher bits.
char_to_ucs2be(Ch) ->
true = is_iso10646(Ch),
@@ -259,15 +274,15 @@ from_ucs2be(Bin,Acc,Tail) ->
char_to_ucs2le(Ch) ->
true = is_iso10646(Ch),
- [(Ch bsr 16) band 16#FF,
- (Ch bsr 24)].
+ [Ch band 16#FF,
+ (Ch bsr 8) band 16#FF].
from_ucs2le(<<Ch:16/little-signed-integer, Rest/binary>>,Acc,Tail) ->
if Ch < 0; Ch >= 16#D800, Ch < 16#E000; Ch =:= 16#FFFE; Ch =:= 16#FFFF ->
exit({bad_character_code,Ch});
true ->
- from_ucs4le(Rest,[Ch|Acc],Tail)
+ from_ucs2le(Rest,[Ch|Acc],Tail)
end;
from_ucs2le(<<>>,Acc,Tail) ->
lists:reverse(Acc,Tail);
@@ -476,6 +491,8 @@ to_unicode(Input,Cs) when Cs=='iso_8859-1:1987';Cs=='iso-ir-100';
Cs=='l1';Cs=='ibm819';
Cs=='cp819';Cs=='csisolatin1' ->
Input;
+to_unicode(Input,Cs) when Cs=='iso_8859-15';Cs=='iso-8859-15';Cs=='latin9' ->
+ from_latin9(Input);
% to_unicode(Input,Cs) when Cs=='mnemonic';Cs=='"mnemonic+ascii+38';
% Cs=='mnem';Cs=='"mnemonic+ascii+8200' ->
% from_mnemonic(Input);
diff --git a/lib/xmerl/src/xmerl_xpath.erl b/lib/xmerl/src/xmerl_xpath.erl
index e654a8ef1d..db3d3ac2d6 100644
--- a/lib/xmerl/src/xmerl_xpath.erl
+++ b/lib/xmerl/src/xmerl_xpath.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
%%
%% The 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,8 +19,8 @@
%% Description : Implements a search engine based on XPath
-%% @doc The xmerl_xpath module handles the entire XPath 1.0 spec
-%% XPath expressions typically occurs in XML attributes and are used to addres
+%% @doc The xmerl_xpath module handles the entire XPath 1.0 spec.
+%% XPath expressions typically occur in XML attributes and are used to address
%% parts of an XML document.
% The grammar is defined in <code>xmerl_xpath_parse.yrl</code>.
% The core functions are defined in <code>xmerl_xpath_pred.erl</code>.
diff --git a/lib/xmerl/src/xmerl_xsd.erl b/lib/xmerl/src/xmerl_xsd.erl
index c0923520c2..dfdc6138ef 100644
--- a/lib/xmerl/src/xmerl_xsd.erl
+++ b/lib/xmerl/src/xmerl_xsd.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -287,10 +287,19 @@ process_schema(Schema) ->
%% error reason. The error reason may be a list of several errors
%% or a single error encountered during the processing.
process_schema(Schema,Options) when is_list(Options) ->
- S = initiate_state(Options,Schema),
- process_schema2(xmerl_scan:file(filename:join(S#xsd_state.xsd_base, Schema)),S,Schema);
-process_schema(Schema,State) when is_record(State,xsd_state) ->
- process_schema2(xmerl_scan:file(filename:join(State#xsd_state.xsd_base, Schema)),State,Schema).
+ State = initiate_state(Options,Schema),
+ process_schema(Schema, State);
+process_schema(Schema, State=#xsd_state{fetch_fun=Fetch})->
+ case Fetch(Schema, State) of
+ {ok,{file,File},_} ->
+ process_schema2(xmerl_scan:file(File), State, Schema);
+ {ok,{string,Str},_} ->
+ process_schema2(xmerl_scan:string(Str), State, Schema);
+ {ok,[],_} ->
+ {error,enoent};
+ Err ->
+ Err
+ end.
process_schema2(Err={error,_},_,_) ->
Err;
@@ -319,12 +328,9 @@ process_schemas(Schemas) ->
%% error reason. The error reason may be a list of several errors
%% or a single error encountered during the processing.
process_schemas(Schemas=[{_,Schema}|_],Options) when is_list(Options) ->
- process_schemas(Schemas,initiate_state(Options,Schema));
+ State = initiate_state(Options,Schema),
+ process_schemas(Schemas, State);
process_schemas([{_NS,Schema}|Rest],State=#xsd_state{fetch_fun=Fetch}) ->
-%% case process_external_schema_once(Schema,if_list_to_atom(NS),State) of
-%% S when is_record(S,xsd_state) ->
-%% case process_schema(filename:join([State#xsd_state.xsd_base,Schema]),State) of
-%% {ok,S} ->
Res=
case Fetch(Schema,State) of
{ok,{file,File},_} ->
@@ -345,20 +351,20 @@ process_schemas([{_NS,Schema}|Rest],State=#xsd_state{fetch_fun=Fetch}) ->
process_schemas([],S) when is_record(S,xsd_state) ->
{ok,S}.
-
initiate_state(Opts,Schema) ->
XSDBase = filename:dirname(Schema),
{{state,S},RestOpts}=new_state(Opts),
S2 = create_tables(S),
- initiate_state2(S2#xsd_state{schema_name = Schema,
- xsd_base = XSDBase,
- fetch_fun = fun fetch/2},RestOpts).
+ initiate_state2(S2#xsd_state{schema_name = Schema, xsd_base=XSDBase,
+ fetch_fun = fun fetch/2},
+ RestOpts).
+
initiate_state2(S,[]) ->
S;
initiate_state2(S,[{tab2file,Bool}|T]) ->
initiate_state2(S#xsd_state{tab2file=Bool},T);
-initiate_state2(S,[{xsdbase,XSDBase}|T]) ->
- initiate_state2(S#xsd_state{xsd_base=XSDBase},T);
+initiate_state2(S,[{xsdbase, XSDBase}|T]) ->
+ initiate_state2(S#xsd_state{xsd_base=XSDBase, external_xsd_base=true},T);
initiate_state2(S,[{fetch_fun,FetchFun}|T]) ->
initiate_state2(S#xsd_state{fetch_fun=FetchFun},T);
initiate_state2(S,[{fetch_path,FetchPath}|T]) ->
@@ -736,7 +742,7 @@ element_content({IDC,S},El,Env)
{{IDC,IDConstr},S3};
Err ->
S3 = acc_errs(S2,{error_path(El,El#xmlElement.name),?MODULE,
- {erronous_content_in_identity_constraint,IDC,Err}}),
+ {erroneous_content_in_identity_constraint,IDC,Err}}),
{{IDC,[]},S3}
end;
element_content({selector,S},Sel,_Env) ->
@@ -2420,8 +2426,8 @@ validate_xml(XMLEl=#xmlElement{},SEl=#schema_element{},S) ->
%% 2 often
check_element_type(XML=[XMLTxt=#xmlText{}|Rest],CM=[CMEl|CMRest],Env,
Block,S,Checked) ->
- %% XMLTxt ��r det f��rsta av content i element,
- %% CMEl ��r den till��tna typen enligt schemat
+ %% XMLTxt is the first part of the elements content,
+ %% CMEl is the allowed type according to the schema
case is_whitespace(XMLTxt) of
true -> %% Ignore XMLEl
check_element_type(Rest,CM,Env,Block,S,[XMLTxt|Checked]);
@@ -2453,7 +2459,7 @@ check_element_type(XML=[#xmlElement{}|_],[{choice,{CM,Occ}}|_CMRest],
check_element_type(XML=[#xmlElement{}|_],[{all,{CM,Occ}}|_CMRest],
Env,_Block,S,Checked) ->
?debug("calling choice/6~n",[]),
- check_all(XML,CM,Occ,Env,S,Checked,XML);
+ check_all(XML,CM,Occ,Env,set_num_el(S,0),Checked,XML); %%LTH
%% 3 often. CMEL may be ((simpleType | complexType)?, (unique | key | keyref)*))
check_element_type(XML=[XMLEl=#xmlElement{}|_],[CMEl|CMRest],Env,
Block,S,Checked) ->
@@ -2921,7 +2927,7 @@ schemaLocations(El=#xmlElement{attributes=Atts},S) ->
[] ->
S;
[#xmlAttribute{value=Paths}|_] ->
- case string:tokens(Paths," ") of
+ case string:tokens(Paths," \n\t\r") of
L when length(L) > 0 ->
case length(L) rem 2 of
0 ->
@@ -3393,8 +3399,12 @@ qualified_node_set(Paths,[QN|QNs],El,S,Acc) ->
end
end,
{KeySequence,S2} = mapfoldl(Fun,S,Paths),
- qualified_node_set(Paths,QNs,El,S2,[flatten(KeySequence)|Acc]).
-
+ case flatten(KeySequence) of
+ [] ->
+ qualified_node_set(Paths,QNs,El,S2,Acc);
+ KS ->
+ qualified_node_set(Paths,QNs,El,S2,[KS|Acc])
+ end.
apply_field(F,El,S) ->
%% xmerl_xpath:string returns a list
@@ -5228,7 +5238,12 @@ fetch(URI,S) ->
[] -> %% empty systemliteral
[];
_ ->
- filename:join(S#xsd_state.xsd_base, URI)
+ case S#xsd_state.external_xsd_base of
+ true ->
+ filename:join(S#xsd_state.xsd_base, URI);
+ false ->
+ filename:join(S#xsd_state.xsd_base, filename:basename(URI))
+ end
end,
Path = path_locate(S#xsd_state.fetch_path, Filename, Fullname),
?dbg("fetch(~p) -> {file, ~p}.~n", [URI, Path]),
@@ -5556,7 +5571,7 @@ format_error({incomplete_file,_FileName,_Other}) ->
"Schema: The file containing a schema state must be produced by xmerl_xsd:state2file/[1,2].";
format_error({unexpected_content_in_any,A}) ->
io_lib:format("Schema: The any type is considered to have no content besides annotation. ~p was found.",[A]);
-format_error({erronous_content_in_identity_constraint,IDC,Err}) ->
+format_error({erroneous_content_in_identity_constraint,IDC,Err}) ->
io_lib:format("Schema: An ~p identity constraint must have one selector and one or more field in content. This case ~p",[IDC,Err]);
format_error({missing_xpath_attribute,IDCContent}) ->
io_lib:format("Schema: A ~p in a identity constraint must have a xpath attribute.",[IDCContent]);
diff --git a/lib/xmerl/src/xmerl_xsd_type.erl b/lib/xmerl/src/xmerl_xsd_type.erl
index 19951f030f..0f46b1f9aa 100644
--- a/lib/xmerl/src/xmerl_xsd_type.erl
+++ b/lib/xmerl/src/xmerl_xsd_type.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -612,7 +612,7 @@ check_NMTOKEN2([H|T]) ->
check_NMTOKEN2(T).
check_NMTOKENS(Value) ->
- TokList = string:tokens(Value," "),
+ TokList = string:tokens(Value," \n\t\r"),
lists:foreach(fun check_NMTOKEN/1,TokList),
{ok,Value}.
@@ -645,7 +645,7 @@ check_ENTITIES(Value) ->
check_list_type(Value,fun check_ENTITY/1).
check_list_type(Value,BaseTypeFun) ->
- Tokens = string:tokens(Value," "),
+ Tokens = string:tokens(Value," \n\t\r"),
lists:foreach(BaseTypeFun,Tokens),
{ok,Value}.
diff --git a/lib/xmerl/test/Makefile b/lib/xmerl/test/Makefile
new file mode 100644
index 0000000000..5a2a585841
--- /dev/null
+++ b/lib/xmerl/test/Makefile
@@ -0,0 +1,127 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2004-2011. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, 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
+
+# ----------------------------------------------------
+# Common Macros
+# ----------------------------------------------------
+
+include ../vsn.mk
+VSN = $(XMERL_VSN)
+
+RM = rm -f
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+HRL_DIR= $(ERL_TOP)/lib/xmerl/include/
+HRL_MODULES= $(HRL_DIR)xmerl $(HRL_DIR)xmerl_xsd
+HRL_FILES= $(HRL_MODULES:%=%.hrl)
+
+
+MODULES= \
+ xmerl_test \
+ xmerl_app_test \
+ xmerl_appup_test \
+ xmerl_test_lib \
+ xmerl_xsd_lib
+
+ERL_FILES= $(MODULES:%=%.erl)
+
+SUITE_FILES= \
+ xmerl_SUITE.erl \
+ xmerl_std_SUITE.erl \
+ xmerl_sax_SUITE.erl \
+ xmerl_sax_std_SUITE.erl \
+ xmerl_xsd_SUITE.erl \
+ xmerl_xsd_MS2002-01-16_SUITE.erl \
+ xmerl_xsd_NIST2002-01-16_SUITE.erl \
+ xmerl_xsd_Sun2002-01-16_SUITE.erl
+
+XML_FILES= \
+ testcases.dtd \
+ xmlconformance.msxsl \
+ xmlconformance.xsl
+
+
+TARGET_FILES= $(MODULES:%=%.$(EMULATOR))
+
+
+INSTALL_PROGS= $(TARGET_FILES)
+
+ifndef XMERL_PRESERV
+XMERL_PRESERV_TEST_DIRS=
+else
+XMERL_PRESERV_TEST_DIRS= -Ddont_rm_test_dirs
+endif
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+
+RELSYSDIR = $(RELEASE_PATH)/xmerl_test
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+
+#ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include -I$(ERL_TOP)/lib/xmerl/include/ $(XMERL_PRESERV_TEST_DIRS)
+
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+tests debug opt: xmerl_test.erl
+
+info:
+ @echo "HRL_FILES: $(HRL_FILES)"
+
+clean:
+ $(RM) *.beam
+ $(RM) xmerl_test.erl
+ $(RM) core *~
+
+xmerl_test.erl: ../doc/examples/xmerl_test.erl
+ cp $< $@
+ chmod u+w $@
+
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+
+release_tests_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)
+ $(INSTALL_DATA) $(SUITE_FILES) $(RELSYSDIR)
+ $(INSTALL_DATA) xmerl.spec xmerl.cover $(RELSYSDIR)
+ cp $(XML_FILES) $(RELSYSDIR)
+ @tar cfh - xmerl_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ @tar cfh - xmerl_std_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ @tar cfh - xmerl_xsd_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ @tar cfh - xmerl_xsd_MS2002-01-16_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ @tar cfh - xmerl_xsd_NIST2002-01-16_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ @tar cfh - xmerl_xsd_Sun2002-01-16_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+ chmod -R u+w $(RELSYSDIR)
diff --git a/lib/xmerl/test/ReadMe b/lib/xmerl/test/ReadMe
new file mode 100644
index 0000000000..effcff6fc4
--- /dev/null
+++ b/lib/xmerl/test/ReadMe
@@ -0,0 +1,24 @@
+
+W3C conformance tests
+=====================
+
+The xmerl tests contains a large number of conformance tests from W3C, which are located in the following
+directories.
+
+xmerl_std_SUITE_data:
+ These tests are fetched from http://www.w3.org/XML/Test/ and repackaged as four tgz files.
+ The W3C Copyright notice is located in the file xmerl_std_SUITE_data/w3c-copyright-19980720.html.
+
+xmerl_xsd_MS2002-01-16_SUITE_data:
+ These tests are fetched from http://www.w3.org/XML/2004/xml-schema-test-suite/index.html
+ The W3C Copyright notice is located in the file xmerl_xsd_MS2002-01-16_SUITE_data/w3c-copyright-19990405.html.
+
+xmerl_xsd_NIST2002-01-16_SUITE_data:
+ These tests are fetched from http://www.w3.org/XML/2004/xml-schema-test-suite/index.html
+ The W3C Copyright notice is located in the file xmerl_xsd_NIST2002-01-16_SUITE_data/w3c-copyright-19990405.html.
+
+xmerl_xsd_Sun2002-01-16_SUITE_data:
+ These tests are fetched from http://www.w3.org/XML/2004/xml-schema-test-suite/index.html
+ The W3C Copyright notice is located in the file xmerl_xsd_Sun2002-01-16_SUITE_data/w3c-copyright-19990405.html.
+
+
diff --git a/lib/xmerl/test/testcases.dtd b/lib/xmerl/test/testcases.dtd
new file mode 100644
index 0000000000..448d362991
--- /dev/null
+++ b/lib/xmerl/test/testcases.dtd
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ @(#)testcases.dtd 1.6 99/01/21
+ Original version copyright 1998 by Sun Microsystems, Inc.
+ All Rights Reserved.
+ Modifications copyright 1999 by OASIS.
+
+ 1999-06-09 00:20
+
+ DTD describing a database of XML tests.
+
+ NOTE: the OASIS/NIST test effort also has a DTD for its test
+ environment, but that DTD is not yet suited for automated test
+ processing. (Among other issues, it doesn't record information
+ putting any test case into the test matrix.) If that gets fixed,
+ it may be useful to switch over to that DTD.
+-->
+
+<!--
+ The root element of the whole collection is TESTSUITE. While not
+ very different from TESTCASES, it must be distinguished due to
+ improper processing by IE5.
+-->
+<!ELEMENT TESTSUITE ( TESTCASES+ )>
+<!ATTLIST TESTSUITE
+ PROFILE CDATA #IMPLIED
+ >
+
+<!--
+ The root element of a collection should be "TESTCASES". It groups
+ a set of tests in a particular "PROFILE", which is descriptive. For
+ example, a "Japanese" profile might group tests with documents
+ in standard Japanese encodings, using Japanese characters used
+ inside names and name tokens as well as inside text. Or the
+ profile might be associated with the test supplier.
+-->
+
+<!ELEMENT TESTCASES (TEST|TESTCASES)*>
+<!ATTLIST TESTCASES
+ PROFILE CDATA #IMPLIED
+ >
+
+<!--
+ The body of each TEST element is its description, used
+ to evaluate the diagnostic produced on negative tests.
+ People will generally read this to evaluate whether the
+ test failed for the correct reason.
+
+ The type of (external) ENTITIES required affect the results
+ permitted for certain types of nonvalidating parsers. In
+ some cases, errors (even well-formedness errors) can't be seen
+ without reading external parameter or general entities.
+
+ Each test has a unique ID used in diagnostics.
+
+ Tests with an OUTPUT attribute do dual duty: not only must parsers
+ accept the test, but the data they report must also have "Second
+ Canonical Form" as found in the specified output file. (This is
+ what James Clark titled "Canonical XML", with the addition of the
+ NOTATION declarations that all XML parsers are required to report.)
+
+ The OUTPUT3 attribute is like OUTPUT, but when sent through a
+ validating parser the data reported must have the "Third Canonical
+ Form" as found in the specified output file. (This is Second
+ Canonical form, with declarations of unparsed ENTITY values and
+ with all ignorable whitespace removed.)
+
+ Tests apply to one or more particular SECTIONS.
+
+ Each test has a TYPE:
+ * All parsers must accept "valid" testcases.
+ * Nonvalidating parsers must also accept "invalid" testcases,
+ but validating ones must reject them.
+ * No parser should accept a "not-wf" testcase unless it's a
+ nonvalidating parser and the test contains external entities
+ that the parser doesn't read.
+ * Parsers are not required to report "errors".
+
+ Each test is in a particular XML document, with a URI. If these
+ tests are accessed over a network, the path will be relative to
+ the base URI of the document holding the testcase.
+-->
+
+<!ELEMENT TEST (#PCDATA | EM | B)*>
+<!ATTLIST TEST
+ ENTITIES (both|none|parameter|general) "none"
+ ID ID #REQUIRED
+ OUTPUT CDATA #IMPLIED
+ OUTPUT3 CDATA #IMPLIED
+ SECTIONS CDATA #REQUIRED
+ TYPE (valid|invalid|not-wf|error) #REQUIRED
+ URI CDATA #REQUIRED
+ NAMESPACE (yes|no) "yes"
+ >
+
+<!--
+ Really basic HTML font tweaks, to support highlighting
+ some aspects of test descriptions ...
+ EM == emphasis (e.g. italics, fun colors)
+ B == bold
+-->
+<!ELEMENT EM (#PCDATA | B)*>
+<!ELEMENT B (#PCDATA | EM)*>
diff --git a/lib/xmerl/test/xmerl.cover b/lib/xmerl/test/xmerl.cover
new file mode 100644
index 0000000000..d0155946ea
--- /dev/null
+++ b/lib/xmerl/test/xmerl.cover
@@ -0,0 +1,2 @@
+{incl_app,xmerl,details}.
+
diff --git a/lib/xmerl/test/xmerl.spec b/lib/xmerl/test/xmerl.spec
new file mode 100644
index 0000000000..89ab31c755
--- /dev/null
+++ b/lib/xmerl/test/xmerl.spec
@@ -0,0 +1 @@
+{suites,"../xmerl_test",all}.
diff --git a/lib/xmerl/test/xmerl_SUITE.erl b/lib/xmerl/test/xmerl_SUITE.erl
new file mode 100644
index 0000000000..94c38d4d48
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE.erl
@@ -0,0 +1,664 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 ASN.1 application
+
+-module(xmerl_SUITE).
+
+-compile(export_all).
+
+%%----------------------------------------------------------------------
+%% Include files
+%%----------------------------------------------------------------------
+-include_lib("test_server/include/test_server.hrl").
+%%-include("xmerl.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
+-include_lib("kernel/include/file.hrl").
+
+
+%%======================================================================
+%% Tests
+%%======================================================================
+
+%%----------------------------------------------------------------------
+%% Test groups
+%%----------------------------------------------------------------------
+all() ->
+ [{group, cpd_tests}, xpath_text1, xpath_main,
+ xpath_abbreviated_syntax, xpath_functions,
+ {group, misc}, {group, eventp_tests},
+ {group, ticket_tests}, {group, app_test},
+ {group, appup_test}].
+
+groups() ->
+ [{cpd_tests, [],
+ [cpd_invalid1, cpd_invalid1_index, cpd_invalid2_index,
+ cpd_invalid_index3, cpd_invalid_is_layer,
+ cpd_expl_provided_DTD]},
+ {misc, [],
+ [latin1_alias, syntax_bug1, syntax_bug2, syntax_bug3,
+ pe_ref1, copyright, testXSEIF, export_simple1, export]},
+ {eventp_tests, [], [sax_parse_and_export]},
+ {ticket_tests, [],
+ [ticket_5998, ticket_7211, ticket_7214, ticket_7430,
+ ticket_6873, ticket_7496, ticket_8156, ticket_8697,
+ ticket_9411, ticket_9457]},
+ {app_test, [], [{xmerl_app_test, all}]},
+ {appup_test, [], [{xmerl_appup_test, all}]}].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+%%----------------------------------------------------------------------
+%% Initializations
+%%----------------------------------------------------------------------
+init_per_suite(doc) ->
+ ["Starts the test suite"];
+init_per_suite(Config) ->
+ Dog=test_server:timetrap({minutes,10}),
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line ok=erl_tar:extract("cpd.tar.gz",[compressed]),
+ ?line ok=erl_tar:extract("misc.tar.gz",[compressed]),
+ ?line ok = change_mode(["cpd", "misc"]),
+ ?line file:set_cwd(filename:join(?config(data_dir,Config),xpath)),
+ TestServerIncludeDir=filename:join(filename:dirname(code:priv_dir(test_server)), "include"),
+ ?line {ok, xpath_lib} = compile:file(xpath_lib, [{i, TestServerIncludeDir}]),
+ ?line {ok, xpath_text} = compile:file(xpath_text, [{i, TestServerIncludeDir}]),
+ ?line {ok, xpath_abbrev} = compile:file(xpath_abbrev, [{i, TestServerIncludeDir}]),
+ [{watchdog, Dog}|Config].
+
+
+-ifndef(dont_rm_test_dirs).
+end_per_suite(doc) ->
+ ["Stops the test suite"];
+end_per_suite(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line ok=rm_files(["cpd", "misc"]),
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ lists:keydelete(watchdog,1,Config).
+
+-else.
+end_per_suite(doc) ->
+ ["Stops the test suite"];
+end_per_suite(Config) ->
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ lists:keydelete(watchdog,1,Config).
+-endif.
+
+
+%% initialization before each testcase
+init_per_testcase(_TestCase,Config) ->
+ io:format("Config:~n~p",[Config]),
+ ?line {ok, _} = file:read_file_info(filename:join([?config(priv_dir,Config)])),
+ ?line code:add_patha(?config(priv_dir,Config)),
+ Dog=test_server:timetrap({minutes,10}),
+ [{watchdog, Dog}|Config].
+
+
+%% clean up after each testcase
+end_per_testcase(_Func,Config) ->
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+
+%%----------------------------------------------------------------------
+%% Test cases
+%%----------------------------------------------------------------------
+cpd_invalid1(suite) -> [];
+cpd_invalid1(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line case catch xmerl_scan:file(filename:join([?config(data_dir,Config), cpd,"cpd_test.xml"]),[]) of
+ {'EXIT',{fatal,Reason}} ->
+ case Reason of
+ {expected_markup,_Path,28,32} -> ok;
+ _ -> {comment,"parsing changed behaviour"}
+ end
+ end.
+
+cpd_invalid1_index(suite) -> [];
+cpd_invalid1_index(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line case catch xmerl_scan:file(filename:join([?config(data_dir,Config), cpd,"cpd_index.xml"]),[]) of
+ {'EXIT',{fatal,Reason}} ->
+ case Reason of
+ {{error,{whitespace_was_expected}},_Path,1,19} -> ok;
+ _ -> {comment,"parsing changed behaviour"}
+ end
+ end.
+
+cpd_invalid2_index(suite) -> [];
+cpd_invalid2_index(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line case catch xmerl_scan:file(filename:join([?config(data_dir,Config), cpd,"cpd_index2.xml"]),[]) of
+ {'EXIT',{fatal,Reason}} ->
+ case Reason of
+ {{invalid_target_name,_Ver},_Path,2,3} ->ok;
+ _ -> {comment,"parsing changed behaviour"}
+ end
+ end.
+
+cpd_invalid_index3(suite) -> [];
+cpd_invalid_index3(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line case catch xmerl_scan:file(filename:join([?config(data_dir,Config), cpd,"cpd_index3.xml"]),[]) of
+ {'EXIT',{fatal,Reason}} ->
+ case Reason of
+ {expected_markup,_Path,1,2} -> ok;
+ _ -> {comment,"parsing changed behaviour"}
+ end
+ end.
+
+cpd_invalid_is_layer(suite) -> [];
+cpd_invalid_is_layer(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line case catch xmerl_scan:file(filename:join([?config(data_dir,Config), cpd,"is_layer2.xml"]),[]) of
+ {'EXIT',{fatal,_Reason}} -> ok
+ end.
+
+cpd_expl_provided_DTD(suite) -> [];
+cpd_expl_provided_DTD(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {#xmlElement{},[]} = xmerl_scan:file(filename:join([?config(data_dir,Config), cpd,"file_wo_DTD.xml"]),[{validation,true},{doctype_DTD,"separate_DTD.dtd"}]).
+
+%%----------------------------------------------------------------------
+
+xpath_text1(suite) -> [];
+xpath_text1(Config) ->
+ ?line file:set_cwd(filename:join(?config(data_dir,Config),xpath)),
+ ?line ok = xpath_text:one().
+
+xpath_main(suite) -> [];
+xpath_main(Config) ->
+ ?line file:set_cwd(filename:join(?config(data_dir,Config),xpath)),
+ ?line ok = xpath_lib:test().
+
+xpath_abbreviated_syntax(suite) -> [];
+xpath_abbreviated_syntax(Config) ->
+ ?line file:set_cwd(filename:join(?config(data_dir,Config),xpath)),
+ ?line ok = xpath_abbrev:test().
+
+xpath_functions(suite) -> [];
+xpath_functions(Config) ->
+ ?line file:set_cwd(filename:join(?config(data_dir,Config),xpath)),
+ ?line ok = xpath_abbrev:functions().
+
+%%----------------------------------------------------------------------
+
+latin1_alias(suite) -> [];
+latin1_alias(Config) ->
+% ?line file:set_cwd(filename:join(?config(data_dir,Config),misc)),
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {_Elements,[]}=
+ xmerl_scan:file(filename:join([?config(data_dir,Config),
+ misc,"motorcycles.xml"]),
+ [{validation,true},
+ {encoding,'iso-8859-1'}]).
+
+syntax_bug1(suite) -> [];
+syntax_bug1(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {fatal,{"expected one of: ?>, standalone, encoding",
+ {file,'misc/syntax_bug1.xml'},{line,1},{col,21}}} =
+ case catch xmerl_scan:file('misc/syntax_bug1.xml') of
+ {'EXIT',Reason} ->
+ Reason;
+ Err -> Err
+ end.
+
+syntax_bug2(suite) -> [];
+syntax_bug2(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {fatal,{"expected one of: ?>, whitespace_character",
+ {file,'misc/syntax_bug2.xml'},{line,1},{col,20}}} =
+ case catch xmerl_scan:file('misc/syntax_bug2.xml') of
+ {'EXIT',Reason} ->
+ Reason;
+ Err -> Err
+ end.
+
+syntax_bug3(suite) -> [];
+syntax_bug3(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {fatal,{{endtag_does_not_match,{was,obj,should_have_been,int}},
+ {file,'misc/syntax_bug3.xml'},{line,4},{col,3}}} =
+ case catch xmerl_scan:file('misc/syntax_bug3.xml') of
+ {'EXIT',Reason} ->
+ Reason;
+ Err -> Err
+ end.
+
+pe_ref1(suite) -> [];
+pe_ref1(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {#xmlElement{},[]} = xmerl_scan:file(filename:join([?config(data_dir,Config), misc,"PE_ref1.xml"]),[{validation,true}]).
+
+copyright(suite) -> [];
+copyright(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {#xmlElement{},[]} = xmerl_scan:file(filename:join([?config(data_dir,Config), misc,"cprght.xml"]),[{validation,true}]).
+
+testXSEIF(suite) -> [];
+testXSEIF(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {#xmlElement{},[]} = xmerl_scan:file(filename:join([?config(data_dir,Config), misc,"ReplBoard_1_1543-CNA11313Uen.xml"]),[{validation,true}]).
+
+export_simple1(suite) -> [];
+export_simple1(Config) ->
+ Simple = simple(),
+ Res = xmerl:export_simple(Simple,xmerl_xml,[{title, "Doc Title"}]),
+ ?line "<?xml version="++_ = lists:flatten(Res),
+
+ %% Use of fun in simple content OTP-6679
+ Simple2 = simple2(),
+ Res2 = xmerl:export_simple(Simple2,xmerl_xml,[{title,"Doc Title"}]),
+ ?line true = (Res2 =:= Res),
+ ok.
+
+export(suite) -> [];
+export(Config) ->
+ DataDir = ?config(data_dir,Config),
+ Prolog = ["<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<!DOCTYPE motorcycles SYSTEM \"motorcycles.dtd\">\n"],
+ TestFile = filename:join([DataDir,"misc","motorcycles.xml"]),
+ ?line {E,_} = xmerl_scan:file(TestFile),
+ ?line Exported = xmerl:export([E],xmerl_xml,[{prolog,Prolog}]),
+ B = list_to_binary(Exported++"\n"),
+ ?line {ok,B} = file:read_file(TestFile),
+ ok.
+
+%%----------------------------------------------------------------------
+
+sax_parse_and_export(suite) -> [];
+sax_parse_and_export(Config) ->
+ ?line ok = sax_parse_export_xml_big(Config),
+ ?line ok = sax_parse_export_xml_small(Config).
+
+%%----------------------------------------------------------------------
+
+sax_parse_export_xml_big(Config) ->
+ DataDir = ?config(data_dir,Config),
+ OutDir = ?config(priv_dir,Config),
+ io:format("DataDir: ~p~n,OutDir:~p~n",[DataDir,OutDir]),
+ CMOMxml = filename:join([DataDir,"eventp","CMOM.xml"]),
+ ?line {Ex,[]} = xmerl_eventp:file_sax(CMOMxml, xmerl_xml,[],[]),
+ OutFile = filename:join([OutDir,"cmom"]),
+ file:delete(OutFile),
+ StubFile = filename:join([DataDir,"eventp","CelloMOM.stub"]),
+ ?line {ok,Bin} = file:read_file(StubFile),
+ ?line {ok,IO} = file:open(OutFile,[write,append]),
+ ?line ok = file:write(IO,Bin),
+ ?line ok = io:format(IO,"~s~n~n",[lists:flatten(Ex)]),
+ Cmd = lists:flatten(io_lib:format("cmp ~s ~s",[OutFile,CMOMxml])),
+ ?line [] = os:cmd(Cmd),
+ ok.
+
+sax_parse_export_xml_small(Config) ->
+ DataDir = ?config(data_dir,Config),
+ OutDir = ?config(priv_dir,Config),
+ Wurfl_xml = filename:join([DataDir,"eventp","wurfl.xml"]),
+ ?line {Ex,[]} = xmerl_eventp:file_sax(Wurfl_xml, xmerl_xml,[],[]),
+ OutFile = filename:join([OutDir,"wrfl"]),
+ file:delete(OutFile),
+ StubFile = filename:join([DataDir,"eventp","wurfl.stub"]),
+ ?line {ok,Bin} = file:read_file(StubFile),
+ ?line {ok,IO} = file:open(OutFile,[write,append]),
+ ?line ok = file:write(IO,Bin),
+ ?line ok = io:format(IO,"~s~n",[lists:flatten(Ex)]),
+ Cmd = lists:flatten(io_lib:format("cmp ~s ~s",[OutFile,Wurfl_xml])),
+ ?line [] = os:cmd(Cmd),
+ ok.
+
+
+simple() ->
+ [{document,
+ [{title, "Doc Title"}, {author, "Ulf Wiger"}],
+ [{section,
+ [{heading, "heading1"}],
+ [{'P', ["This is a paragraph of text."]},
+ {section,
+ [{heading, "heading2"}],
+ [{'P', ["This is another paragraph."]},
+ {table,
+ [{border, 1}],
+ [{heading,
+ [{col, ["head1"]},
+ {col, ["head2"]}]},
+ {row,
+ [{col, ["col11"]},
+ {col, ["col12"]}]},
+ {row,
+ [{col, ["col21"]},
+ {col, ["col22"]}]}]}]}]}]}].
+
+
+simple2() ->
+ GenC = fun ?MODULE:generate_section/1,
+ GenA = fun ?MODULE:generate_attr_title/1,
+ [{document,[{GenA,2}],[{GenC,1}]}].
+
+generate_attr_title(0) ->
+ done;
+generate_attr_title(1) ->
+ {{title,"Doc Title"},0};
+generate_attr_title(2) ->
+ {{author, "Ulf Wiger"},1}.
+generate_section(0) ->
+ done;
+generate_section(N) ->
+ GenC = fun ?MODULE:generate_section_content/1,
+ GenA = fun ?MODULE:generate_section_attribute/1,
+ {{section,[{GenA,1}],[{GenC,2}]},N-1}.
+
+generate_section_attribute(0) ->
+ done;
+generate_section_attribute(N) ->
+ {{heading, "heading1"},N-1}.
+
+
+generate_subsection_content(0) ->
+ done;
+generate_subsection_content(1) ->
+ {{'P',["This is another paragraph."]},0};
+generate_subsection_content(N) ->
+ {{table,[{fun ?MODULE:generate_border_attribute/1,1}],
+ [{fun ?MODULE:generate_table_content/1,2}]},N-1}.
+generate_section_content(0) ->
+ done;
+generate_section_content(1) ->
+ {{'P',["This is a paragraph of text."]},0};
+generate_section_content(N) ->
+ {{section,[{heading,"heading2"}],
+ [{fun ?MODULE:generate_subsection_content/1,2}]},N-1}.
+generate_border_attribute(0) ->
+ done;
+generate_border_attribute(N) ->
+ {{border,N},N-1}.
+generate_table_content(0) ->
+ done;
+generate_table_content(1) ->
+ {{fun ?MODULE:generate_heading/1,1},0};
+generate_table_content(N) ->
+ {{fun ?MODULE:generate_row/1, {2,2}},N-1}.
+generate_row({0,_}) ->
+ done;
+generate_row(N) ->
+ UpdateS = fun({2,_}) -> {1,2};(_) -> {0,0} end,
+ {{row,[{fun ?MODULE:generate_row_col/1, N}]},UpdateS(N)}.
+generate_row_col({_,0}) ->
+ done;
+generate_row_col(N={C,R}) ->
+ UpdateS = fun({X,Y}) -> {X,Y-1} end,
+ {{col,[lists:concat(["col",C,R])]},UpdateS(N)}.
+generate_heading(0) ->
+ done;
+generate_heading(N) ->
+ {{heading,[{fun ?MODULE:generate_heading_col/1,2}]},N-1}.
+generate_heading_col(0) ->
+ done;
+generate_heading_col(N) ->
+ {{col,[lists:concat(["head",N])]},N-1}.
+
+%%----------------------------------------------------------------------
+%% Ticket Tests
+%%----------------------------------------------------------------------
+
+%%
+%% ticket_5998
+%%
+%% A Kleene Closure child in a sequence consumed all following
+%% childs. This problem has been fixed.
+%%
+ticket_5998(suite) -> [];
+ticket_5998(Config) ->
+ DataDir = ?config(data_dir,Config),
+ %% First fix is tested by case syntax_bug2.
+
+ ?line case catch xmerl_scan:file(filename:join([DataDir,misc,
+ "ticket_5998_2.xml"])) of
+ {'EXIT',{fatal,Reason1}} ->
+ case Reason1 of
+ {{endtag_does_not_match,
+ {was,obj,should_have_been,int}},
+ _,_,_} -> ok;
+ _ -> {comment,"parsing changed behaviour"}
+ end
+ end,
+
+ ?line case catch xmerl_scan:file(filename:join([DataDir,misc,
+ "ticket_5998_3.xml"])) of
+ {'EXIT',{fatal,Reason2}} ->
+ case Reason2 of
+ {"expected one of: ?>, standalone, encoding",
+ _,_,_} -> ok;
+ _ -> {comment,"parsing changed behaviour"}
+ end
+ end.
+
+
+%%
+%% ticket_7211
+%%
+%% A Kleene Closure child in a sequence consumed all following
+%% childs. This problem has been fixed.
+%%
+ticket_7211(suite) -> [];
+ticket_7211(Config) ->
+ DataDir = ?config(data_dir,Config),
+ ?line {E,[]} =
+ xmerl_scan:file(filename:join([DataDir,misc,"notes2.xml"]),
+ [{fetch_path,[filename:join([DataDir,misc,erlang_docs_dtd])]},
+ {validation,dtd}]),
+
+ ?line ok = case E of
+ Rec when is_record(Rec,xmlElement) ->
+ ok;
+ _ ->
+ E
+ end,
+
+ ?line {E2,[]} =
+ xmerl_scan:file(filename:join([DataDir,misc,"XS.xml"]),
+ [{fetch_path,[filename:join([DataDir,misc,erlang_docs_dtd])]},
+ {validation,dtd}]),
+
+ ?line ok = case E2 of
+ Rec2 when is_record(Rec2,xmlElement) ->
+ ok;
+ _ ->
+ E2
+ end.
+
+%%
+%% ticket_7214
+%%
+%% Now validating xhtml1-transitional.dtd.
+%% A certain contentspec with a succeding choice, that didn't match
+%% all content, followed by other child elements caused a
+%% failure. This is now corrected.
+%%
+ticket_7214(suite) -> [];
+ticket_7214(Config) ->
+ DataDir = ?config(data_dir,Config),
+
+ ?line {E,[]} =
+ xmerl_scan:file(filename:join([DataDir,misc,'block_tags.html']),
+ [{validation,dtd},
+ {fetch_path,[filename:join([DataDir,misc,erlang_docs_dtd])]}]),
+
+ ?line ok = case E of
+ Rec when is_record(Rec,xmlElement) ->
+ ok;
+ _ ->
+ E
+ end.
+
+%%
+%% ticket_7430
+%%
+%% Problem with contents of numeric character references followed by
+%% UTF-8 characters..
+%%
+ticket_7430(suite) -> [];
+ticket_7430(Config) ->
+ DataDir = ?config(data_dir,Config),
+
+ ?line {E,[]} =
+ xmerl_scan:string("<a>\303\251&#xD;\303\251</a>",
+ [{encoding, 'utf-8'}]),
+
+ ?line ok = case E of
+ {xmlElement,a,a,[],
+ {xmlNamespace,[],[]},
+ [],1,[],
+ [{xmlText,[{a,1}],1,[],"�",text},
+ {xmlText,[{a,1}],2,[],"\n�",text}],
+ [],_,undeclared} ->
+ ok;
+ _ ->
+ E
+ end.
+
+ticket_6873(suite) -> [];
+ticket_6873(Config) ->
+ ?line file:set_cwd(filename:join(?config(data_dir,Config),xpath)),
+ ?line ok = xpath_abbrev:ticket_6873(),
+ ?line ok = xpath_lib:ticket_6873().
+
+ticket_7496(suite) -> [];
+ticket_7496(Config) ->
+ ?line file:set_cwd(filename:join(?config(data_dir,Config),xpath)),
+ ?line ok = xpath_abbrev:ticket_7496().
+
+ticket_8156(suite) -> [];
+ticket_8156(Config) ->
+ ?line {ftp,{[],[]},"testmachine1",21,"/w.erl"} = xmerl_uri:parse("ftp://testmachine1/w.erl"),
+ ?line {ftp,{"user",[]},"testmachine1",21,"/w.erl"} = xmerl_uri:parse("ftp://user@testmachine1/w.erl"),
+ ?line {ftp,{"user","hello"},"testmachine1",21,"/w.erl"} =
+ xmerl_uri:parse("ftp://user:hello@testmachine1/w.erl"),
+ ?line {ftp,{[],[]},"testmachine1",3000,"/w.erl"} = xmerl_uri:parse("ftp://testmachine1:3000/w.erl"),
+ ?line {ftp,{"user","hello"},"testmachine1",3000,"/w.erl"} =
+ xmerl_uri:parse("ftp://user:hello@testmachine1:3000/w.erl"),
+ ok.
+
+ticket_8697(suite) -> [];
+ticket_8697(doc) ->
+ ["Test that xmerl_scan can decode unicode entities properly"];
+ticket_8697(Config) ->
+ ?line {UTF8Output, []} = xmerl_scan:string("<?xml version=\"1\" ?>\n<text>" ++ [229, 145, 156] ++ "</text>"),
+ ?line #xmlElement{content = [#xmlText{value = UTF8Text}]} = UTF8Output,
+ ?line [16#545C] = UTF8Text,
+ ?line {DecEntityOutput, []} = xmerl_scan:string("<?xml version=\"1\" ?>\n<text>&#21596;</text>"),
+ ?line #xmlElement{content = [#xmlText{value = DecEntityText}]} = DecEntityOutput,
+ ?line [21596] = DecEntityText,
+ ?line {HexEntityOutput, []} = xmerl_scan:string("<?xml version=\"1\" ?>\n<text>&#x545C;</text>"),
+ ?line #xmlElement{content = [#xmlText{value = HexEntityText}]} = HexEntityOutput,
+ ?line [16#545C] = HexEntityText,
+ ok.
+
+ticket_9411(suite) -> [];
+ticket_9411(doc) ->
+ ["Test that xmerl_scan handles attribute that contains for example &quot"];
+ticket_9411(Config) ->
+ DataDir = ?config(data_dir,Config),
+
+ ?line {ok, Schema} = xmerl_xsd:process_schema(filename:join([DataDir,"misc/ticket_9411.xsd"])),
+ ?line {ok, Bin} = file:read_file(filename:join([DataDir,"misc/ticket_9411.xml"])),
+ ?line Xml = erlang:binary_to_list(Bin),
+ ?line {E, _} = xmerl_scan:string(Xml),
+ ?line {E, _} = xmerl_xsd:validate(E, Schema).
+
+ticket_9457(suite) -> [];
+ticket_9457(doc) ->
+ ["Test that xmerl_scan handles continuation correct when current input runs out at the end of an attribute value"];
+ticket_9457(Config) ->
+ Opts = [{continuation_fun, fun ticket_9457_cont/3, start}, {space, normalize}],
+ ?line {E, _} = xmerl_scan:string([], Opts).
+
+ticket_9457_cont(Continue, Exception, GlobalState) ->
+ case xmerl_scan:cont_state(GlobalState) of
+ start ->
+ G1 = xmerl_scan:cont_state(next, GlobalState),
+ Bytes = "<?xml version=\"1.0\" ?>\r\n<item a=\"b\"",
+ Continue(Bytes, G1);
+ next ->
+ G1 = xmerl_scan:cont_state(last, GlobalState),
+ Bytes = ">blah</item>\r\n",
+ Continue(Bytes, G1);
+ _ ->
+ Exception(GlobalState)
+ end.
+
+%%======================================================================
+%% Support Functions
+%%======================================================================
+
+%% Dir is a directory
+rm_f_(Dir) ->
+ ?line {ok,CWD} = file:get_cwd(),
+ ?line {ok,FileList} = file:list_dir(Dir),
+ ?line file:set_cwd(filename:join([CWD,Dir])),
+ rm_files(FileList),
+ ?line file:set_cwd(CWD),
+ ? line ok = file:del_dir(Dir).
+
+rm_files([])->
+ ok;
+rm_files([F|Fs]) ->
+ case filelib:is_dir(F) of
+ true ->
+ rm_f_(F);
+ _ ->
+ ?line ok = file:delete(F)
+ end,
+ rm_files(Fs).
+
+change_mode(Files) ->
+ change_mode3(Files).
+change_mode2(Dir)->
+ ?line {ok,CWD} = file:get_cwd(),
+ ?line {ok,FileList} = file:list_dir(Dir),
+ ?line file:set_cwd(filename:join([CWD,Dir])),
+ change_mode3(FileList),
+ ?line file:set_cwd(CWD).
+change_mode3([]) ->
+ ok;
+change_mode3([F|Fs]) ->
+ case filelib:is_dir(F) of
+ true ->
+ chmod(F),
+ change_mode2(F);
+ _ ->
+ chmod(F)
+ end,
+ change_mode3(Fs).
+
+chmod(F) ->
+ case file:read_file_info(F) of
+ {ok,FileInfo} ->
+ Mode= FileInfo#file_info.mode,
+ file:write_file_info(F,FileInfo#file_info{mode=8#00777 bor Mode});
+ _ ->
+ ok
+ end.
+
diff --git a/lib/xmerl/test/xmerl_SUITE_data/cpd.tar.gz b/lib/xmerl/test/xmerl_SUITE_data/cpd.tar.gz
new file mode 100644
index 0000000000..c750e14adf
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/cpd.tar.gz
Binary files differ
diff --git a/lib/xmerl/test/xmerl_SUITE_data/eventp/CMOM.xml b/lib/xmerl/test/xmerl_SUITE_data/eventp/CMOM.xml
new file mode 100644
index 0000000000..7c64046897
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/eventp/CMOM.xml
@@ -0,0 +1,30261 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!--
+ Document no: 1551-1/CSX10109
+ Revision: MOM-CELLO_4.3.1
+ Date: 12-17-2003
+ Author: Ake Pappila/Hsiang-Ling Teng
+
+ Generated from UML by uml2xml version 3.0 (based on DTD file rev. F)
+ Rational Rose model used: /vobs/cello/cma/cma_uml/CelloMOM.mdl
+-->
+
+<!DOCTYPE models SYSTEM "mp.dtd">
+
+<models>
+<mim name="MOM-CELLO_4.3.1-1" version="5" release="1">
+ <exception name="AttributeMissingException">
+ <description>Exception thrown when an attribute is missing during upgrade.</description>
+ </exception>
+
+ <exception name="EnableExistingProgramException">
+ <description>Exception thrown when enabling of existing programs fails.</description>
+ </exception>
+
+ <exception name="ExtraIdentifiersOfNonExistingLoadModulesException">
+ </exception>
+
+ <exception name="FileCopyException">
+ <description>Exception thrown when copying of files fails.</description>
+ </exception>
+
+ <exception name="FileNotExistException">
+ <description>Exception thrown when the specified file does not exist.</description>
+ </exception>
+
+ <exception name="FindAndReplaceException">
+ </exception>
+
+ <exception name="HeapPoolSettingsException">
+ <description>Exception thrown when the heap or pool setting is incorrect.</description>
+ </exception>
+
+ <exception name="AttributeValueOutOfRangeException">
+ <description>Exception thrown when an attribute value is out of range.</description>
+ </exception>
+
+ <exception name="CancelInstallRequestException">
+ <description>Exception thrown when a cancel install equest for some reason fails.</description>
+ </exception>
+
+ <exception name="ChecksumhandlerException">
+ <description>Exception thrown when the control of checksum for loadmodules has been rejaected due to 'null' recieved from resource layer.</description>
+ </exception>
+
+ <exception name="ClearAllPiuTypesReferencedByPlugInUnitException">
+ <description>Exception thrown when its not possible to clear all PiuTypes referenced by PlugInUnit.</description>
+ </exception>
+
+ <exception name="ConditionallyMandatoryAttributeOrElementMissingException">
+ <description>Exception thrown when an conditional mandatory attribute (or element) is missing.</description>
+ </exception>
+
+ <exception name="ConfigurationVersionMO_HandlerException">
+ <description>Exception thrown when the creation of a CV during upgrade fails.</description>
+ </exception>
+
+ <exception name="ControlFileDocumentHandlerException">
+ </exception>
+
+ <exception name="CreateLoadModuleException">
+ <description>Exception thrown when the creation of a load module fails.</description>
+ </exception>
+
+ <exception name="DisableExistingProgramsException">
+ <description>Exception thrown when disabling of existing programs for some reason fails.</description>
+ </exception>
+
+ <exception name="DocumentObjectProxyException">
+ </exception>
+
+ <exception name="ExplicitReplacementInInformationForRPUsException">
+ <description>Exception thrown when replacement of existing RPU information fails.</description>
+ </exception>
+
+ <exception name="InstallOfLoadModulesCancelledException">
+ <description>Exception thrown when the installation of Load Modules is cancelled.</description>
+ </exception>
+
+ <exception name="InstallOfLoadModulesPartlyExcecutedException">
+ <description>Exception thrown when the installment of Load Modules is only partly executed.</description>
+ </exception>
+
+ <exception name="InstallOfLoadModulesRejectedException">
+ <description>Exception thrown when the install of Load Modules is rejected.</description>
+ </exception>
+
+ <exception name="InstallRejectedFTP_ServerNotAccessibleException">
+ <description>Exception thrown when the install is rejected due to FTP server is not accessible.</description>
+ </exception>
+
+ <exception name="InstallRejectedGetLoadModuleFileException">
+ <description>Exception thrown when the install is rejected due to error when trying to retreive Load Module.</description>
+ </exception>
+
+ <exception name="InstallRejectedIP_AddressException">
+ <description>Exception thrown when install is rejected due to erronous IP address.</description>
+ </exception>
+
+ <exception name="InstallRejectedInsufficientDiskSpaceException">
+ <description>Exception thrown when the install is rejected due to insufficient disk space.</description>
+ </exception>
+
+ <exception name="InstallRejectedLoadListFileException">
+ </exception>
+
+ <exception name="InstallRequestException">
+ <description>Exception thrown when the installation of a Load Module fails.</description>
+ </exception>
+
+ <exception name="InsufficientDiskSpaceException">
+ <description>Exception thrown when the disk space is insufficient.</description>
+ </exception>
+
+ <exception name="JvmMO_HandlerException">
+ </exception>
+
+ <exception name="LoadModuleFIlePathLengthOutOfRangeException">
+ <description>Exception thrown when file path for the Load Module is out of length.</description>
+ </exception>
+
+ <exception name="LoadModuleMO_HandlerException">
+ </exception>
+
+ <exception name="ManagedElementDataMO_HandlerException">
+ </exception>
+
+ <exception name="MandatoryElementIsMissingException">
+ </exception>
+
+ <exception name="MergeControlFileException">
+ <description>Exception thrown when the merger of control files fails.</description>
+ </exception>
+
+ <exception name="PIU_MO_HandlerException">
+ </exception>
+
+ <exception name="ParseException">
+ </exception>
+
+ <exception name="ParserFactoryException">
+ </exception>
+
+ <exception name="PiuTypeDefinitionMissingInUpgradeControlFileException">
+ <description>Exception thrown when PiuType definitions is missing in the UCF file.</description>
+ </exception>
+
+ <exception name="PiuTypeMO_HandlerException">
+ </exception>
+
+ <exception name="ProductNumberAndRevisionAlreadyInUseException">
+ <description>Exception thrown when the product number and revision is already used.</description>
+ </exception>
+
+ <exception name="ProgramConfigurationException">
+ </exception>
+
+ <exception name="ReconfigureProgramsException">
+ <description>Exception thrown when reconfiguration of programs fails.</description>
+ </exception>
+
+ <exception name="ReferencedElementMissingException">
+ <description>Exception thrown when the referenced element is missing.</description>
+ </exception>
+
+ <exception name="RepertoireMO_HandlerException">
+ </exception>
+
+ <exception name="ReplaceConfigSupportMOsOpException">
+ </exception>
+
+ <exception name="ReserveLoadModulesException">
+ <description>Exception thrown when reserving a Load Module fails.</description>
+ </exception>
+
+ <exception name="SelectiveInstallFailureException">
+ <description>Exception thrown when a selective install fails.</description>
+ </exception>
+
+ <exception name="SlotMO_HandlerException">
+ </exception>
+
+ <exception name="SwAllocationMO_HandlerException">
+ </exception>
+
+ <exception name="UnexpectedAttributeException">
+ <description>Exception thrown when an unexpected attribute occurs at upgrade.</description>
+ </exception>
+
+ <exception name="UnexpectedAttributeFormatException">
+ <description>Exception thrown when an unexpected format of the attribute occurs.</description>
+ </exception>
+
+ <exception name="UnexpectedElementException">
+ <description>Exception thrown when </description>
+ </exception>
+
+ <exception name="UpgradeControlFileDataException">
+ </exception>
+
+ <exception name="UpgradeControlFileNotFoundException">
+ </exception>
+
+ <exception name="UpgradeControlFileParserException">
+ </exception>
+
+ <exception name="UpgradePackageDeleteException">
+ <description>Exception thrown when its not possible to delete the upgrade package.</description>
+ </exception>
+
+ <exception name="UpgradePackageDeleteNotAllowedException">
+ <description>Exception thrown when its not allowed to delete the upgrade package.</description>
+ </exception>
+
+ <exception name="UpgradePackageDoesNotExistException">
+ <description>Exception thrown when the specified upgrade package does not exist.</description>
+ </exception>
+
+ <exception name="UpgradePackageFileSystemErrorException">
+ <description>Exception thrown when an error in the file system occurs.</description>
+ </exception>
+
+ <exception name="UpgradeRejectedException">
+ <description>Exception thrown when the upgrade is rejected.</description>
+ </exception>
+
+ <exception name="ValidateException">
+ </exception>
+
+ <exception name="VerifyChecksumException">
+ <description>Exception thrown when the checksum is incorrect.</description>
+ </exception>
+
+ <exception name="VerifyCreationOfCVsException">
+ <description>Exception thrown when its not possible to verify the creation of CV's.</description>
+ </exception>
+
+ <exception name="VerifyOperationalPIUsException">
+ </exception>
+
+ <exception name="VerifyRejectedException">
+ </exception>
+
+ <exception name="VerifyRequestException">
+ </exception>
+
+ <exception name="VerifySupportedPIUsException">
+ </exception>
+
+ <exception name="VerifyUpgradeHandlerException">
+ </exception>
+
+ <exception name="VerifyUpgradeWindowException">
+ </exception>
+
+ <exception name="UpgradeLogFileNotAccessibleException">
+ <description>The upgrade trace log file is not accessible i.e. the log file exists but it is not possible to access it with write permission.</description>
+ </exception>
+
+ <exception name="UpgradeControlFileException">
+ <description>The file parser has found that the UpgradeControlFile is incorrect.</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="UpgradeNotPossibleException">
+ <description>Before an upgrade is started it was found that the upgrade can not take place. A possible reason is that the upgrade package that is running in the node is not in the upgrade window of this upgrade package. </description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="UpgradeLogFileNotInUseException">
+ <description>The upgrade trace output is currently not directed to a file.
+
+This is a property that can be changed in the trace property file (Trace_01.prop).
+</description>
+ </exception>
+
+ <enum name="UpgradePackageState">
+ <enumMember name="NOT_INSTALLED">
+ <description>The upgrade package is not installed.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="INSTALL_COMPLETED">
+ <description>The upgrade package is completely installed.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="UPGRADE_EXECUTING">
+ <description>Upgrade is executing. </description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="AWAITING_CONFIRMATION">
+ <description>The execution of upgrade needs confirmation before it proceeds.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="ONLY_DELETEABLE">
+ <description>In this state an Upgrade Package can only be deleted. Its actions, when invoked, will throw the exception ActionNotAllowed. </description>
+ <value>4</value>
+ </enumMember>
+ <enumMember name="INSTALL_EXECUTING">
+ <description>Installation of the upgrade package is executing.</description>
+ <value>5</value>
+ </enumMember>
+ <enumMember name="INSTALL_NOT_COMPLETED">
+ <description>The upgrade package is not completely installed i.e. parts of it has been installed. </description>
+ <value>6</value>
+ </enumMember>
+ <enumMember name="UPGRADE_COMPLETED">
+ <description>The upgrade has been successfully executed.</description>
+ <value>7</value>
+ </enumMember>
+ </enum>
+
+ <enum name="UpgradeProgressInformation">
+ <enumMember name="IDLE">
+ <description>No action is in progress. </description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="DOWNLOADING_FILES">
+ <description>Downloading of files (load modules) in progress.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="SAVING_CV">
+ <description>Saving a Configuration Version.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="RECONFIGURING_MOS">
+ <description>Operation ReplaceConfigSupportMOs detected in upgrade.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="INITIATING_LOADER_INFO">
+ <description>Trigger Initiate detected in upgrade sequence.</description>
+ <value>4</value>
+ </enumMember>
+ <enumMember name="PRELOADING">
+ <description>Trigger Preload detected in upgrade sequence.</description>
+ <value>5</value>
+ </enumMember>
+ <enumMember name="CONVERSION_OF_PERSISTENT_DATA">
+ <value>6</value>
+ </enumMember>
+ <enumMember name="APPLICATION_SPECIFIC_ACTION">
+ <description>'Unique trigger' for an application detected in upgrade sequence.</description>
+ <value>7</value>
+ </enumMember>
+ <enumMember name="SHUTDOWN_WAIT">
+ <value>8</value>
+ </enumMember>
+ <enumMember name="TAKING_NEW_SOFTWARE_INTO_SERVICE">
+ <value>9</value>
+ </enumMember>
+ <enumMember name="FINISH_AND_CLEANING_UP">
+ <description>The error handling is switched back to normal.</description>
+ <value>10</value>
+ </enumMember>
+ <enumMember name="RESTORING_SYSTEM_STATE">
+ <value>11</value>
+ </enumMember>
+ <enumMember name="EXECUTION_FAILED">
+ <description>Indicates that the execution of an install or an upgrade action has failed.</description>
+ <value>12</value>
+ </enumMember>
+ <enumMember name="CANCEL_OF_INSTALLATION_IS_EXECUTING">
+ <description>Indicates that cancellation of an ongoing installation is in progress.</description>
+ <value>13</value>
+ </enumMember>
+ <enumMember name="CANCEL_OF_INSTALLATION_FAILED">
+ <description>Indicates that the execution of a cancel install action failed.</description>
+ <value>14</value>
+ </enumMember>
+ <enumMember name="VERIFICATION_INITIATED">
+ <value>15</value>
+ </enumMember>
+ <enumMember name="VERIFYING_UPGRADE_FROM_VERSION">
+ <value>16</value>
+ </enumMember>
+ <enumMember name="VERIFYING_POSSIBLE_TO_CREATE_REQ_NO_CVS">
+ <value>17</value>
+ </enumMember>
+ <enumMember name="VERIFYING_PIUS_SUPPORTED">
+ <value>18</value>
+ </enumMember>
+ <enumMember name="VERIFYING_CHECKSUM_FOR_LM">
+ <value>19</value>
+ </enumMember>
+ <enumMember name="VERIFYING_PIUS_NOT_FAULTY">
+ <value>20</value>
+ </enumMember>
+ <enumMember name="VERIFICATION_FINISHED">
+ <value>21</value>
+ </enumMember>
+ <enumMember name="VERIFICATION_FAILED">
+ <value>22</value>
+ </enumMember>
+ </enum>
+
+ <enum name="InvokedAction">
+ <enumMember name="VERIFY_UPGRADE">
+ <description>The verifyUpgrade action has been invoked.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="UPGRADE">
+ <description>An upgrade action (one of the variants) has been invoked.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="INSTALL">
+ <description>An install action (one of the variants) has been invoked.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="CANCEL_INSTALL">
+ <description>The cancelInstall action has been invoked.</description>
+ <value>4</value>
+ </enumMember>
+ </enum>
+
+ <struct name="ActionResultData">
+ <structMember name="time">
+ <description>A timestamp.
+
+Format: "Date: 2003-04-24, Time: 20:52:11.182"</description>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </structMember>
+ <structMember name="typeOfInvokedAction">
+ <enumRef name="InvokedAction">
+ <defaultValue>VERIFY_UPGRADE</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="info">
+ <enumRef name="Information">
+ <defaultValue>EXECUTED</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="actionId">
+ <description>This id is used to link more than one result to one action</description>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="additionalInfo">
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </structMember>
+ </struct>
+
+ <enum name="Information">
+ <enumMember name="EXECUTED">
+ <description>The invoked action has been successfully executed without warnings.One of three possible main results of executed action.
+
+Value valid for type of invoked action:
+INSTALL
+CANCEL_INSTALL
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="UNSPECIFIED">
+ <description>A not specified error/ warning has been detected (see additional info for further details)
+
+Value valid for type of invoked action:
+INSTALL
+CANCEL_INSTALL
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="LM_CHECKSUM_VER_FAILED">
+ <description>A load module checksum verification has failed.
+
+Value valid for type of invoked action:
+INSTALL
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="NOT_ENOUGH_AVAIL_DISK_SPACE">
+ <description> There is not enough available disk space for the required number of new CVs (configuration versions) to be created automatically during an upgrade.
+
+Value valid for type of invoked action:
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="MAX_NO_CV_WILL_BE_EXCEEDED">
+ <description>The maximum number of allowed CVs (configuration versions) will be exceeded if the required number of new CVs is created automatically during an upgrade.
+
+Value valid for type of invoked action:
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>4</value>
+ </enumMember>
+ <enumMember name="UPGRADE_FROM_CURRENT_UP_NOT_ALLOWED">
+ <description>The Upgrade Window element in the Upgrade Control File does not specify the current Upgrade Package as a valid 'upgrade from' version.
+
+Value valid for type of invoked action:
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>5</value>
+ </enumMember>
+ <enumMember name="NON_SUPPORTED_PIU">
+ <description>A non supported Plug In Unit (PIU) has been detected i.e. the PIU in the node is not defined in the Upgrade Control File.
+This is not a fault that prevents an upgrade from being executed.
+
+Value valid for type of invoked action:
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>6</value>
+ </enumMember>
+ <enumMember name="FAULTY_PIU">
+ <description>A faulty Plug In Unit (PIU) has been detected.
+This is not a fault that prevents an upgrade from being executed.
+
+Value valid for type of invoked action:
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>7</value>
+ </enumMember>
+ <enumMember name="CREATION_OF_CV_FAILED">
+ <description>The auto-creation of an install CV failed.
+
+Value valid for type of invoked action:
+INSTALL
+</description>
+ <value>8</value>
+ </enumMember>
+ <enumMember name="ACTION_NOT_ALLOWED">
+ <description>The requested action is not allowed due to an other action already is in progress for an other UP MO.
+
+Value valid for type of invoked action:
+INSTALL
+CANCEL_INSTALL
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>9</value>
+ </enumMember>
+ <enumMember name="INSTALLATION_MANUALLY_CANCELLED">
+ <description>An ongoing installation has been cancelled (aborted) due to request from client.
+
+Value valid for type of invoked action:
+INSTALL</description>
+ <value>10</value>
+ </enumMember>
+ <enumMember name="FTP_SERVER_NOT_ACCESSIBLE">
+ <description>The FTP server to be used for downloads of load modules is not accessible.
+
+Value valid for type of invoked action:
+INSTALL</description>
+ <value>11</value>
+ </enumMember>
+ <enumMember name="INSUFFICIENT_DISK_SPACE_FOR_LOAD_MODULES">
+ <description>The required disk space for load modules to be installed is insufficient.
+
+Value valid for type of invoked action:
+INSTALL</description>
+ <value>12</value>
+ </enumMember>
+ <enumMember name="FTP_SERVER_IP_ADDRESS_ERROR">
+ <description>Error detected in the IP address of the FTP server.
+
+Value valid for type of invoked action:
+INSTALL</description>
+ <value>13</value>
+ </enumMember>
+ <enumMember name="DELTA_INSTALL_MERGE_ERROR">
+ <description>The install of the delta Upgrade Control File (UCF) failed i.e. the analysis of the delta UCF together with current active UP's UCF failed.
+
+Value valid for type of invoked action:
+INSTALL</description>
+ <value>14</value>
+ </enumMember>
+ <enumMember name="SELECTIVE_INSTALL_ERROR">
+ <description>Error detected during the selection phase of an install.
+
+Value valid for type of invoked action:
+INSTALL
+
+</description>
+ <value>15</value>
+ </enumMember>
+ <enumMember name="EXECUTION_FAILED">
+ <description>The execution of invoked action failed.One of three possible main results of executed action.
+
+Value valid for type of invoked action:
+INSTALL
+CANCEL_INSTALL
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>16</value>
+ </enumMember>
+ <enumMember name="EXECUTED_WITH_WARNINGS">
+ <description>The action has been successfully executed but with warnings.One of three possible main results of executed action.
+
+Value valid for type of invoked action:
+INSTALL
+CANCEL_INSTALL
+VERIFY_UPGRADE</description>
+ <value>17</value>
+ </enumMember>
+ </enum>
+
+ <exception name="FtpServerNotAccessibleException">
+ <description>Ftp server is not accessible. This may depend on erroneous IP address, username, password, or that the IP communication with the Ftp server is down, or that the Ftp server itself is malfunctioning. </description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="GetFileException">
+ <description>An error was encountered during FTP get file. A filePath in the upgradeControlFile may be inconsistent with a filepath on the Ftp server. </description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <struct name="PiuTypeProgramConfiguration">
+ <structMember name="tag">
+ <description>The tag is used as a reference between the PiuType MO and the Repertoire MO to find out how to create the program object under a PlugInUnit MO.</description>
+ <string/>
+ </structMember>
+ <structMember name="subParentLDN">
+ <description>Local distinguished name of the program parent from the PlugInUnit.
+
+Example:
+1. "Spu=1,Spm=2" (the program is to be created under: ...PlugInUnit=2,Spu=1,Spm=2")
+2. "" (empty string - the program is to be created directly under the PlugInUnit)</description>
+ <string/>
+ </structMember>
+ <structMember name="programMoTypeName">
+ <description>The name of the Program MO that will be created.</description>
+ <string/>
+ </structMember>
+ <structMember name="loadableProcessorName">
+ <description>The loadableProcessorName is a user friendly name of the processor.</description>
+ <string/>
+ </structMember>
+ </struct>
+
+ <struct name="RepertoireLoadModuleData">
+ <description>This structure contains load module data that belongs to a piu type.
+</description>
+ <structMember name="loadModuleDN">
+ <description>The distinguished name of the load module, which is needed and sufficient to convert the load module to a real object reference.</description>
+ <string/>
+ </structMember>
+ <structMember name="tag">
+ <description>The tag is used as a reference between the PiuType MO and the Repertoire MO to find out how to create the program object under a PlugInUnit MO.</description>
+ <string/>
+ </structMember>
+ </struct>
+
+ <struct name="ConfigurationVersionAttributes">
+ <structMember name="name">
+ <string>
+ </string>
+ </structMember>
+ <structMember name="identity">
+ <string>
+ </string>
+ </structMember>
+ <structMember name="type">
+ <string/>
+ </structMember>
+ <structMember name="upgradePackageId">
+ <string/>
+ </structMember>
+ <structMember name="operatorName">
+ <string>
+ </string>
+ </structMember>
+ <structMember name="operatorComment">
+ <string>
+ </string>
+ </structMember>
+ <structMember name="date">
+ <string/>
+ </structMember>
+ <structMember name="status">
+ <string/>
+ </structMember>
+ </struct>
+
+ <enum name="ConfigurationVersionType">
+ <enumMember name="standard">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="upgrade">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="minimal">
+ <value>2</value>
+ </enumMember>
+ <enumMember name="test">
+ <value>3</value>
+ </enumMember>
+ <enumMember name="autocreate">
+ <value>4</value>
+ </enumMember>
+ <enumMember name="other">
+ <value>5</value>
+ </enumMember>
+ </enum>
+
+ <enum name="LoadModuleLoaderType">
+ <enumMember name="OseLoader">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="SpmLoader">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="Jvm">
+ <value>2</value>
+ </enumMember>
+ <enumMember name="WebServer">
+ <value>3</value>
+ </enumMember>
+ <enumMember name="Other">
+ <value>99</value>
+ </enumMember>
+ <enumMember name="SpmFpgaLoader">
+ <value>4</value>
+ </enumMember>
+ <enumMember name="XpLoader">
+ <value>5</value>
+ </enumMember>
+ </enum>
+
+ <enum name="LoadModulePreLoadType">
+ <enumMember name="no">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="must">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="wish">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="RPUSwitchOverMode">
+ <description>This attribute can have the following values:
+
+AtPiuFault = Indicates the MP (where the normal RPU is configured) is faulty (HW error). This is the default value.
+
+AtPiuRestart = Indicates the MP (where the normal RPU is configured) is restarted.</description>
+ <enumMember name="AtPiuFault">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="AtPiuRestart">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="RPUNormalisationMode">
+ <description>This enumeration can have the following values:
+
+Manual = Indicates that no normalisation is performed by cello until the operator issues a "switch" action.
+
+Automatic = Indicates that Cello performs the normalisation automatically, after the failed RPU is available again. This is the default value.</description>
+ <enumMember name="Manual">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="Automatic">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="RPUReplicationMode">
+ <description>This enumaration contains the following values:
+
+Always = Data replication is always performed. This overrides the characteristics set on the each container ( that is associated with the RPU ).
+
+Never = Data replication is never performed. This overrides the characteristics set on the each container ( that is associated with the RPU ).
+
+AtShutdown = Each time the RSH (which handles the RPU) is shut down, a complete snapshot is taken and replicated to the other MP, if necessary. Otherwise, the replication is performed according to the characteristics set on each container ( that is associated with the RPU ).
+
+ApplControlled = The data replication is made according to the characteristics set on each container ( that is associated with the RPU ). This is the default value.</description>
+ <enumMember name="Always">
+ <description>Always = Data replication is always performed. This overrides the characteristics set on the each container ( that is associated with the RPU ).</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="Never">
+ <description>Data replication is never performed. This overrides the characteristics set on the each container ( that is associated with the RPU ).</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="AtShutdown">
+ <description>AtShutdown = Each time the RSH (which handles the RPU) is shut down, a complete snapshot is taken and replicated to the other MP, if necessary. Otherwise, the replication is performed according to the characteristics set on each container ( that is associated with the RPU ).</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="ApplControlled">
+ <description>ApplControlled = The data replication is made according to the characteristics set on each container ( that is associated with the RPU ). This is the default value.</description>
+ <value>4</value>
+ </enumMember>
+ </enum>
+
+ <enum name="RPUOperationalMode">
+ <description>This enumeration contains the following values:
+
+AsConfigured = The RSHs runs as the RPU is configured.
+SwitchOver = The RSHs has been switched over.
+Unavailable = No RSHs, that uses this RPU, are running.</description>
+ <enumMember name="AsConfigured">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="SwitchedOver">
+ <value>2</value>
+ </enumMember>
+ <enumMember name="Unavailable">
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <struct name="PiuTypeMOConfiguration">
+ <structMember name="subParentLDN">
+ <string/>
+ </structMember>
+ <structMember name="moTypeName">
+ <string/>
+ </structMember>
+ <structMember name="identity">
+ <string/>
+ </structMember>
+ </struct>
+
+ <struct name="AirFlowData">
+ <description>Control value for the fan unit. Needed by cooling function.
+</description>
+ <structMember name="normalLowTempAirFlow">
+ <description>Control value for the fan unit running in normal autonomous mode.
+This parameter is the subrack/fanunit airflow value that is required to achieve sufficient cooling at 20 degree
+centigrade or lower ambient temperature of the most demanding plug in unit (PIU) in the subrack. This airflow value
+shall be sufficient (but not unnecessarily large) to secure that no "normal overtemp" fault indication is issued.
+Default values = 250 m3/h. (value &gt;=0)
+</description>
+ <float>
+ <defaultValue>250</defaultValue>
+ </float>
+ </structMember>
+ <structMember name="normalHighTempAirFlow">
+ <description>Control value for the fan unit running in normal autonomous mode. This parameter is the subrack/fanunit airflow
+value that is required to achieve sufficient cooling at 50 degree centigrade ambient temperature of the most
+demanding plug in unit (PIU) in the subrack. This airflow value shall be sufficient (but not unnecessarily large) to
+secure that no "normal overtemp" fault indication is issued.
+Default values = 400 m3/h. (value &gt;=0)</description>
+ <float>
+ <defaultValue>400</defaultValue>
+ </float>
+ </structMember>
+ <structMember name="noiseReducedLowTempAirFlow">
+ <description>Control value for the fan unit running in noise reduction mode. This parameter is the subrack/fanunit airflow value
+that is required to achieve sufficient cooling at 20 degree centigrade or lower ambient temperature of the most
+demanding plug in unit (PIU) in the subrack. This airflow value shall be sufficient (but not unnecessarily large) to
+secure that no "exceptional overtemp" fault indication is issued
+Default values = 250 m3/h. (value &gt;=0)</description>
+ <float>
+ <defaultValue>250</defaultValue>
+ </float>
+ </structMember>
+ <structMember name="noiseReducedHighTempAirFlow">
+ <description>Control value for the fan unit running in noise reduction mode. This parameter is the subrack/fanunit airflow value
+that is required to achieve sufficient cooling at 50 degree centigrade ambient temperature of the most demanding
+plug in unit (PIU) in the subrack. This airflow value shall be sufficient (but not unnecessarily large) to secure
+that no "exceptional overtemp" fault indication is issued.
+Default values = 400 m3/h. (value &gt;=0)</description>
+ <float>
+ <defaultValue>400</defaultValue>
+ </float>
+ </structMember>
+ </struct>
+
+ <exception name="IpAddressException">
+ <description>Erroneous Ip Address Format</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="AueFailureException">
+ <description>An application upgrade engine has reported a failure. </description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="ActionNotAllowedException">
+ <description>The action is not allowed, the UpgradePackage MO is in wrong state.
+
+For example if you try 'upgrade()' before an 'install()' or 'forcedInstall()' has been done.</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="CVFileSystemErrorException">
+ <description>Exception thrown upon file system Error.</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="CVDBErrorException">
+ <description>Data Base Error Exception (error when creating database backup).</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="CVLLPErrorException">
+ <description>LLP Error Exception (error when creating ARMAMENT and LLP.LMID files).</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="CVAlreadyExistsException">
+ <description>The configuration version already exists (e.g. message at create).</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="CVDoesNotExistsException">
+ <description>The configuration version does not exist (e.g. message at setCVAsStartable).</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="CVDeleteNotAllowedException">
+ <description>It is not allowed to delete the configuration version, because it is in use (used as startable or in rollback list).</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="CVInvalidCVException">
+ <description>The configuration version is not valid (due to missing files).
+
+</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="CVFormatErrorException">
+ <description>Format Error in given configuration version name.
+
+The following characters are allowed within the name:
+[0-9], [A-Z], [a-z] and '&amp;','%',':','.','_', '-'
+
+Note! For comment and operatorName spaces (' ') are also allowed within the strings.</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="CVErrorException">
+ <description>Error Exception.</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="InstallException">
+ <description>Indicates that an error in an installation has occurred.</description>
+ <exceptionParameter name="install">
+ <description>The message of the exception.</description>
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="LogActivationException">
+ <description>Exception thrown when a database error occurs.</description>
+ </exception>
+
+ <exception name="InvalidDriveNameException">
+ <description>Exception thrown when an invalid drive name is specified or when a data base error occurs.</description>
+ </exception>
+
+ <exception name="VerifyUpgradeException">
+ </exception>
+
+ <exception name="CVActivityLogFilePathErrorException">
+ <description>Exception thrown when the log file path is wrong.</description>
+ </exception>
+
+ <exception name="CV_MaxNumberOfInstancesException">
+ <description>Exception thrown when max number of CV's in the system has been reached.</description>
+ </exception>
+
+ <exception name="Aal2PathIdNotUniqueException">
+ <exceptionParameter name="message">
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="PathAlreadyRegisteredException">
+ <exceptionParameter name="message">
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="NotInGroupException">
+ </exception>
+
+ <exception name="InvalidReferenceException">
+ </exception>
+
+ <exception name="InvalidPriorityException">
+ <description>Indicates an invalid priority level, i.e. the priority in question is out of the defined range.</description>
+ <exceptionParameter name="invalidPriority">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <struct name="QoSProfileClassA">
+ <description>This struct contains the values applicable for QoS Class A.</description>
+ <structMember name="boundOnProbOfDelay">
+ <description>Represents the upper bound on the probability that the delay in the node exceeds the delay limit given by the attribute "boundOnNodeDelay".
+
+Unit is 1/1000000000.
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>1000000000</max>
+ </range>
+ <defaultValue>500000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="boundOnProbOfLoss">
+ <description>Represents the upper bound of the cell loss probability in the current node.
+
+Unit is 1/1000000000.</description>
+ <long>
+ <range>
+ <min>0</min> <max>1000000000</max>
+ </range>
+ <defaultValue>500000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="boundOnNodeDelay">
+ <description>The upper bound on the delay (delay=queueing and serving of Aal2 packets in an Aal2 mux + delay on ATM layer) through the current node.
+Unit is micro seconds.</description>
+ <long>
+ <range>
+ <min>0</min> <max>10000</max>
+ </range>
+ <defaultValue>5000</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <struct name="QoSProfileClassB">
+ <description>This struct contains the values applicable for QoS Class B.</description>
+ <structMember name="boundOnProbOfDelay">
+ <description>Represents the upper bound on the probability that the delay in the node exceeds the delay limit given by the attribute "boundOnNodeDelay".
+
+Unit is 1/1000000000.</description>
+ <long>
+ <range>
+ <min>0</min> <max>1000000000</max>
+ </range>
+ <defaultValue>500000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="boundOnProbOfLoss">
+ <description>Represents the upper bound of the cell loss probability in the current node.
+
+Unit is 1/1000000000.
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>1000000000</max>
+ </range>
+ <defaultValue>500000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="boundOnNodeDelay">
+ <description>The upper bound on the delay (delay=queueing and serving of Aal2 packets in an Aal2 mux + delay on ATM layer) through the current node.
+Unit is micro seconds.</description>
+ <long>
+ <range>
+ <min>0</min> <max>20000</max>
+ </range>
+ <defaultValue>15000</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <struct name="QoSProfileClassC">
+ <description>This struct contains the values applicable for QoS Class C.
+
+NOTE: The attribute 'boundONodeDelay' is not applicable for QoS Class C so setting of this attribute will have no effect.</description>
+ <structMember name="boundOnProbOfDelay">
+ <description>Represents the upper bound on the probability that the delay in the node exceeds the delay limit given by the attribute "boundOnNodeDelay".
+
+Unit is 1/1000000000.</description>
+ <long>
+ <range>
+ <min>0</min> <max>1000000000</max>
+ </range>
+ <defaultValue>1000000000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="boundOnProbOfLoss">
+ <description>Represents the upper bound of the cell loss probability in the current node.
+
+Unit is 1/1000000000.
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>1000000000</max>
+ </range>
+ <defaultValue>1000000000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="boundOnNodeDelay">
+ <description>The upper bound on the delay (delay=queueing and serving of Aal2 packets in an Aal2 mux + delay on ATM layer) through the current node.
+Unit is micro seconds.</description>
+ <long>
+ <defaultValue>25000</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <struct name="QoSProfileClassD">
+ <description>This struct contains the values applicable for QoS Class D.
+
+NOTE: The attribute 'boundONodeDelay' is not applicable for QoS Class D so setting of this attribute will have no effect.</description>
+ <structMember name="boundOnProbOfDelay">
+ <description>Represents the upper bound on the probability that the delay in the node exceeds the delay limit given by the attribute "boundOnNodeDelay".
+
+Unit is 1/1000000000.</description>
+ <long>
+ <range>
+ <min>1</min> <max>1000000000</max>
+ </range>
+ <defaultValue>1000000000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="boundOnProbOfLoss">
+ <description>Represents the upper bound of the cell loss probability in the current node.
+
+Unit is 1/1000000000.</description>
+ <long>
+ <range>
+ <min>0</min> <max>1000000000</max>
+ </range>
+ <defaultValue>1000000000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="boundOnNodeDelay">
+ <description>The upper bound on the delay (delay=queueing and serving of Aal2 packets in an Aal2 mux + delay on ATM layer) through the current node.
+Unit is micro seconds.</description>
+ <long>
+ <defaultValue>50000</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <enum name="SupportedQoSClasses">
+ <enumMember name="NO_CLASS_SUPPORTED">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="CLASS_A">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="CLASS_B">
+ <value>2</value>
+ </enumMember>
+ <enumMember name="CLASS_A_B">
+ <value>3</value>
+ </enumMember>
+ <enumMember name="CLASS_C">
+ <value>4</value>
+ </enumMember>
+ <enumMember name="CLASS_A_C">
+ <value>5</value>
+ </enumMember>
+ <enumMember name="CLASS_B_C">
+ <value>6</value>
+ </enumMember>
+ <enumMember name="CLASS_A_B_C">
+ <value>7</value>
+ </enumMember>
+ <enumMember name="CLASS_D">
+ <value>8</value>
+ </enumMember>
+ <enumMember name="CLASS_A_D">
+ <value>9</value>
+ </enumMember>
+ <enumMember name="CLASS_B_D">
+ <value>10</value>
+ </enumMember>
+ <enumMember name="CLASS_A_B_D">
+ <value>11</value>
+ </enumMember>
+ <enumMember name="CLASS_C_D">
+ <value>12</value>
+ </enumMember>
+ <enumMember name="CLASS_A_C_D">
+ <value>13</value>
+ </enumMember>
+ <enumMember name="CLASS_B_C_D">
+ <value>14</value>
+ </enumMember>
+ <enumMember name="CLASS_A_B_C_D">
+ <value>15</value>
+ </enumMember>
+ </enum>
+
+ <exception name="IsReservedCanNotSetPathIdException">
+ <description>Exception thrown when an attempt is made to set or change the aal2PathId of an Aal2PathVccTp while its reserved by an other Aal2PathGrp</description>
+ </exception>
+
+ <exception name="IsUnlockedCanNotSetPathOwnerException">
+ <description>Exception thrown when an attempt is made to set or change the aal2PathOwner of an Aal2PathVccTp while its not LOCKED.</description>
+ </exception>
+
+ <enum name="SlotState">
+ <description>
+</description>
+ <enumMember name="free">
+ <description>It is free to be pre-configured with a new PlugInUnit. </description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="used">
+ <description>A PlugInUnit is inserted in the slot or the slot is pre-configured with a PlugInUnit.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="coveredByPiu">
+ <description>Currently not supported.</description>
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <struct name="AdminProductData">
+ <structMember name="productNumber">
+ <description>The product number of the product or document.
+
+Examples: ABC 101 001, CXC 123 456, 1/BFD 101 999
+
+In the case of UpgradePackage this is the document number of the upgrade package.</description>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>24</max>
+ </lengthRange>
+ </string>
+ </structMember>
+ <structMember name="productRevision">
+ <description>The revision of the product number.
+
+Examples: R1, r1a, R1A02, P7B</description>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>7</max>
+ </lengthRange>
+ </string>
+ </structMember>
+ <structMember name="productName">
+ <description>A user-friendly name of the product.</description>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>12</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </structMember>
+ <structMember name="productInfo">
+ <description>User-friendly information about the product.</description>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </structMember>
+ <structMember name="productionDate">
+ <description>The production date can be represented in two ways.
+
+1) The preferable syntax is a four-digit representation of the year, and a two-digit representation of the month and a two-digit representation of the day. The numbers of characters in this case, is eight.
+Example:
+19991231
+
+2) The date can also consist of two digits for the year, followed by the letter W for week and two digits for the number of week. The numbers of characters in this case, is five.
+Example:
+99W12
+</description>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>8</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </structMember>
+ </struct>
+
+ <struct name="OperProductData">
+ <structMember name="productName">
+ <description>A user-friendly name of the product.
+
+
+
+</description>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>12</max>
+ </lengthRange>
+ </string>
+ </structMember>
+ <structMember name="productNumber">
+ <description>Unique identity for each product, which is constituted by the Ericsson product number (ABC number).
+
+The maximum number of characters for a product number is 24 including 2 slashes, 2 spaces and 2 characters for origination notation.
+
+Example of product number:
+ABC 101 001
+(1/ABC 101 01/1234)
+123/ABCDE 101 1010/12345
+
+.</description>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>24</max>
+ </lengthRange>
+ </string>
+ </structMember>
+ <structMember name="productRevision">
+ <description>Indicates the revision state of the product. It consists of a letter R or P, one or two digits and/or one or two letters. The maximum number of characters is four inclusive R or P.
+Example: R1A, R1A02, P7B
+
+A suffix may be added to the revision state. The suffix may consists of one or two digits or one letter.
+
+
+</description>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>7</max>
+ </lengthRange>
+ </string>
+ </structMember>
+ <structMember name="serialNumber">
+ <description>The serial number consists of 13 alphanumerical characters grouped as 6 plus 7 characters. The first 6 characters are to be used for factory codes and the last 7 characters are used for an individual number or batch number.
+
+</description>
+ <string/>
+ </structMember>
+ <structMember name="productionDate">
+ <description>The production date can be represented in two ways.
+
+1) The preferable syntax is a four-digit representation of the year, and a two-digit representation of the month and a two-digit representation of the day. The numbers of characters in this case, is eight.
+Example:
+19991231
+
+2) The date can also consist of two digits for the year, followed by the letter W for week and two digits for the number of week. The numbers of characters in this case, is five.
+Example:
+99W12
+
+</description>
+ <string>
+ <lengthRange>
+ <min>5</min> <max>8</max>
+ </lengthRange>
+ </string>
+ </structMember>
+ </struct>
+
+ <enum name="LoadClass">
+ <description>Defines the phase in the load and start sequence.
+</description>
+ <enumMember name="coreOs">
+ <value>10</value>
+ </enumMember>
+ <enumMember name="coreDevice">
+ <value>50</value>
+ </enumMember>
+ <enumMember name="loadListProvider">
+ <value>100</value>
+ </enumMember>
+ <enumMember name="coreEarly">
+ <value>200</value>
+ </enumMember>
+ <enumMember name="coreLate">
+ <value>300</value>
+ </enumMember>
+ <enumMember name="networkAndConnectionHandling">
+ <value>400</value>
+ </enumMember>
+ <enumMember name="application">
+ <value>500</value>
+ </enumMember>
+ <enumMember name="upgrade">
+ <value>600</value>
+ </enumMember>
+ </enum>
+
+ <enum name="StartState">
+ <enumMember name="disabled">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="enabled">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="SubrackType">
+ <enumMember name="hub">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="device">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="PiuRole">
+ <enumMember name="mp">
+ <description>The board is a Main processor.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="bp">
+ <description>The board is a device board.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="others">
+ <description>The board is not a Main processor or a device board. </description>
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <enum name="RestartCause">
+ <description>This attribute indicates the restart cause of plugInUnit. The defined values are:
+1. piuRestartError: restart because of error.
+2. piuRestartUpgrade: restart because of system upgrade.
+</description>
+ <enumMember name="piuRestartUpgrade">
+ <description>This attributes indicates that the Piu restart cause is upgrade.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="piuRestartError">
+ <description>This attributes indicates that the Piu restart cause is error.</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="FanState">
+ <description>The Fan can be in one of three controlling state:
+- standalone: not manageable, full speed fans
+- autonomous: manageable, air-flow control
+- noiseReduced: time-limited low speed fan</description>
+ <enumMember name="standalone">
+ <description>It's running on itself, not manageable.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="autonomous">
+ <description>Manageable state.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="noiseReduced">
+ <description>Temporary state with reduced cooling.</description>
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <enum name="SeqRestarts">
+ <enumMember name="RESTARTS_WITH_NO_LIMITS">
+ <description>This attributes indicates unlimited restarts and no faulty marking of the PIU. Used for critical PIU's such as TUBs, SCBs and some ET-boards.
+</description>
+ <value>-1</value>
+ </enumMember>
+ <enumMember name="RESTARTS_WITH_WARM">
+ <description>This attributes indicates the following sequential restarts:
+-warm
+-refresh
+-cold
+-cold with fault marked (not loaded). Alarm sent.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="RESTARTS_WITH_REFRESH">
+ <description>This attributes indicates the following sequential restarts:
+-refresh
+-cold
+-cold with fault marked (not loaded). Alarm sent.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="RESTARTS_WITH_COLD">
+ <description>This attributes indicates the following sequential restarts:
+-cold
+-cold with fault marked (not loaded). Alarm sent.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="RESTARTS_WITH_FAULT_MARKED">
+ <description>This attributes indicates the following sequential restarts:
+-cold with fault marked (not loaded). Alarm sent.</description>
+ <value>0</value>
+ </enumMember>
+ </enum>
+
+ <exception name="RepertoireNotFoundException">
+ <description>This class is an exception class thrown when a equipment specific error occurs.
+</description>
+ </exception>
+
+ <exception name="SwAllocationNotFoundException">
+ <description>This class is an exception class thrown when a equipment specific error occurs.
+</description>
+ </exception>
+
+ <exception name="WebServerPathConfigurationException">
+ <description>This class is an exception class thrown when failed to configure the webserver root path
+</description>
+ </exception>
+
+ <exception name="FroLocationFailedException">
+ </exception>
+
+ <exception name="FroShutdownException">
+ </exception>
+
+ <exception name="NotUniqueLineNoException">
+ </exception>
+
+ <exception name="WrongPhysPathTermTypeException">
+ </exception>
+
+ <enum name="OperState">
+ <enumMember name="disabled">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="enabled">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="AdmState">
+ <enumMember name="locked">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="unlocked">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="shuttingDown">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <exception name="OccupiedException">
+ </exception>
+
+ <exception name="NotReservedException">
+ </exception>
+
+ <exception name="NotSupportedException">
+ </exception>
+
+ <enum name="SilPortState">
+ <description>Indication of Switch Internal Link port status.</description>
+ <enumMember name="portActive">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="portPassive">
+ <value>2</value>
+ </enumMember>
+ <enumMember name="portNotConnected">
+ <value>3</value>
+ </enumMember>
+ <enumMember name="portLocked">
+ <value>4</value>
+ </enumMember>
+ <enumMember name="portNotInstalled">
+ <value>5</value>
+ </enumMember>
+ </enum>
+
+ <exception name="InvalidIndexException">
+ <description>Index specified is invalid, i.e. it is out of the range of valid indices.</description>
+ <exceptionParameter name="invalidIndex">
+ <description>The exception message.</description>
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="TransactionException">
+ </exception>
+
+ <exception name="UndeletableMoException">
+ <description>Exception thrown when MO is not possible to delete.</description>
+ </exception>
+
+ <exception name="FroNotAccessibleException">
+ <description>Exception that is thrown when a FRO (Facade Resource Object in the resource layer) cannot be accessed.</description>
+ </exception>
+
+ <exception name="FroRequestFailedException">
+ <description>Exception that is thrown when the result of a request to a FRO (Facade Resource Object in the resource layer) is not ok.</description>
+ </exception>
+
+ <exception name="MoReservedByOtherUserException">
+ <description>Exception thrown when the MO is already reserved by another user (MO).</description>
+ </exception>
+
+ <exception name="MoHasChildrenException">
+ <description>Exception class thrown when an MO is requested to be deleted, but the MO has children, which must be deleted first.</description>
+ </exception>
+
+ <exception name="MoReservedNotDeletableException">
+ <description>Exception thrown when trying to delete an MO that is reserved by another MO (user).</description>
+ </exception>
+
+ <exception name="MaxNumberExceededException">
+ <description>Exception thrown when the maximum number of childrens for an MO is exceeded.</description>
+ </exception>
+
+ <exception name="AttrValueNotUniqueException">
+ <description>Exception thrown when a value of an attribute is not unique.</description>
+ </exception>
+
+ <exception name="EquipException">
+ </exception>
+
+ <exception name="IpFormatException">
+ </exception>
+
+ <exception name="IpException">
+ </exception>
+
+ <exception name="TransactionRequiredException">
+ <description>Exception class thrown when an MO is accessed outside a transaction but the access method requires a transaction.</description>
+ </exception>
+
+ <exception name="ValueOutOfRangeException">
+ <description>Exception thrown when an MO attribute is requested to be set, but the requested value is not accepted.</description>
+ </exception>
+
+ <exception name="WrongAttributeTypeException">
+ <description>Exception thrown when an MO attribute is requested to be set, but the requested value is of the wrong type. </description>
+ </exception>
+
+ <exception name="NotHandledAttributeTypeException">
+ <description>Exception class thrown when an attribute of not handled type is requested. </description>
+ </exception>
+
+ <exception name="NoSuchFieldException">
+ <description>Exception class thrown when a Struct is accessed but the reqested Struct element is not found. </description>
+ </exception>
+
+ <exception name="MoCanNotBeCreatedException">
+ </exception>
+
+ <exception name="NoSuchAttributeException">
+ <description>Exception thrown when an MO attribute is requested to be accessed but the access
+method for the is not defined (the attribute can not be accessed)</description>
+ </exception>
+
+ <exception name="MoCardinalityViolationException">
+ <description>Exception class thrown when the creation of an MO fails due to child - parent
+cardinality violation. The cardinality is specified in the MIM. </description>
+ </exception>
+
+ <exception name="IllegalParentException">
+ <description>Exception thrown when the parent of the MO is of the wrong type.</description>
+ </exception>
+
+ <exception name="AttrNotSettableAtCreateException">
+ <description>Exception thrown when a create is ordered with
+attribute values that are not settable at create.</description>
+ </exception>
+
+ <exception name="AttrMissingAtCreateException">
+ <description>Exception thrown when an attribute that is mandatory at create is missing.</description>
+ </exception>
+
+ <exception name="MoNameAlreadyTakenException">
+ <description>Exception thrown when an MO is created and the distinguished name of the MO is already in use.</description>
+ </exception>
+
+ <exception name="IllegalArgumentTypeException">
+ <description>Exception thrown if the argument supplied is of the wrong type, for example in an action.</description>
+ </exception>
+
+ <exception name="IllegalAttributeValueException">
+ <description>Exception thrown if the value of the attribute is not valid.</description>
+ </exception>
+
+ <enum name="RestartRank">
+ <enumMember name="RESTART_WARM">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="RESTART_REFRESH">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="RESTART_COLD">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="AvailabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <enumMember name="IN_TEST">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="FAILED">
+ <value>2</value>
+ </enumMember>
+ <enumMember name="POWER_OFF">
+ <value>4</value>
+ </enumMember>
+ <enumMember name="OFF_LINE">
+ <value>8</value>
+ </enumMember>
+ <enumMember name="OFF_DUTY">
+ <value>16</value>
+ </enumMember>
+ <enumMember name="DEGRADED">
+ <value>64</value>
+ </enumMember>
+ <enumMember name="NOT_INSTALLED">
+ <value>128</value>
+ </enumMember>
+ <enumMember name="LOG_FULL">
+ <value>256</value>
+ </enumMember>
+ <enumMember name="DEPENDENCY_LOCKED">
+ <value>544</value>
+ </enumMember>
+ <enumMember name="DEPENDENCY_FAILED">
+ <value>1056</value>
+ </enumMember>
+ <enumMember name="DEPENDENCY_SHUTTINGDOWN">
+ <value>2080</value>
+ </enumMember>
+ <enumMember name="NO_STATUS">
+ <value>0</value>
+ </enumMember>
+ </enum>
+
+ <exception name="InvalidMoReferenceException">
+ <description>Exception thrown when the submitted MO reference is invalid.</description>
+ </exception>
+
+ <exception name="FroNotLockedException">
+ <description>Exception thrown when a fRo cannot be accessed.</description>
+ </exception>
+
+ <exception name="GeneralErrorException">
+ <description>Exception thrown by an MO when there is a general error.</description>
+ </exception>
+
+ <exception name="IdentityNotAllowedException">
+ <description>Exception thrown when an identity (LDN) specified at create is not allowed.</description>
+ </exception>
+
+ <exception name="IllegalMoTypeException">
+ <description>Exception thrown when a reference to an MO is of a unexpected/wrong MO type.</description>
+ </exception>
+
+ <exception name="ImpossibleCollectAtmInfoException">
+ <description>Exception thrown when gathering of ATM info fails.</description>
+ </exception>
+
+ <exception name="MoCanNotBeDeletedException">
+ <description>Exception thrown when its not possible to delete an MO.</description>
+ </exception>
+
+ <exception name="MoNotPossibleToReserveException">
+ <description>Exception thrown when by an MO if its not possible to reserve the MO.</description>
+ </exception>
+
+ <exception name="MoNotReservedByUserException">
+ <description>Exception thrown when a user tries to release an MO that is not reserved by this user.</description>
+ </exception>
+
+ <exception name="NoDiskException">
+ <description>Exception thrown when there is no hard disk.</description>
+ </exception>
+
+ <exception name="RemovalFailedException">
+ <description>Exception thrown when an element cannot be removed from a sequence.</description>
+ </exception>
+
+ <exception name="RestartRejectedException">
+ <description>Exception thrown when restart of the PlugInUnit is not allowed.</description>
+ </exception>
+
+ <enum name="SyncMode">
+ <description>The Sync Mode Operation of the node.</description>
+ <enumMember name="NOT_USED">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="CDMA">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="WCDMA">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <struct name="Mtp2ProfileDataAnsi">
+ <structMember name="suermT">
+ <description>SUERM parameter T.
+Measured in SU units.</description>
+ <long>
+ <range>
+ <min>1</min> <max>511</max>
+ </range>
+ <defaultValue>64</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="suermD">
+ <description>SUREM parameter D.
+Measurement units are in SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>256</max>
+ </range>
+ <defaultValue>256</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="suermN">
+ <description>SUERM parameter N.
+Measurement units are in SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>256</max>
+ </range>
+ <defaultValue>16</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="tin">
+ <description>Normal AERM threshold, Tin. Number of signal errors that cause abortion of a normal proving peroid.
+
+Measurement units are SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>7</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="tie">
+ <description>Emergency AERM threshold, Tie. Number of signal units errors that cause abortion of an emergency proving period.
+
+Measurement units are SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>7</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="provings">
+ <description>Proving abort limit. Number of consecutive aborted proving periods that will cause a return to the Out Of Service state.
+
+Measurement units are the number of proving periods.</description>
+ <long>
+ <range>
+ <min>1</min> <max>7</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT1">
+ <description>Maximum time to stay in Aligned Ready state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>16300</max>
+ </range>
+ <defaultValue>12900</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT2">
+ <description>Maximum time to stay in Not Aligned state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>32700</max>
+ </range>
+ <defaultValue>5000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT3">
+ <description>Maximum time to stay in Aligned state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>16300</max>
+ </range>
+ <defaultValue>11500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4n">
+ <description>Length of the normal proving period.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>4000</max>
+ </range>
+ <defaultValue>2300</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4e">
+ <description>Length of the emergengcy proving period.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>4000</max>
+ </range>
+ <defaultValue>600</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT5">
+ <description>Time between sending Status Indication "B" while in the Congested state.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>1</min> <max>255</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT6">
+ <description>Maximum time a remote site may remain in the congestated state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>8100</max>
+ </range>
+ <defaultValue>1000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT7">
+ <description>Maximum time to wait for an expected acknowledgement of an MSU before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>2000</max>
+ </range>
+ <defaultValue>500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="bitRate">
+ <description>The speed of the link. Only supported values are 64 and 56 kbit/s.
+0 = 64 kbit/s.
+1 = 56 kbit/s.
+
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="errorCorrection">
+ <description>The error correction algorithm to use. Only Basic Error Correction (BEC) is supported.
+0 = BEC
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet1">
+ <description>Percentage of the Transmit Buffer that will cause MTP2 to signal congestion for prio 1 messages towards client.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet2">
+ <description>Percentage of the Transmit Buffer that will cause MTP2 to signal congestion for prio 2 messages towards client.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet3">
+ <description>Percentage of the Transmit Buffer that will cause MTP2 to signal congestion for prio 3 messages towards client.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>90</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement1">
+ <description>Percentage of the Transmit Buffer that ceases congestion for prio 1 messages.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement2">
+ <description>Percentage of the Transmit Buffer that ceases congestion for prio 2 messages.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement3">
+ <description>Percentage of the Transmit Buffer that ceases congestion for prio 3 messages.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionDiscardLevel1">
+ <description>Percentage of the Transmit Buffer where messages sent to MTP2 from client with priority less than 1 is discarded by MTP2.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionDiscardLevel2">
+ <description>Percentage of the Transmit Buffer where messages sent to MTP2 from client with priority less than 2 is discarded by MTP2.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionDiscardLevel3">
+ <description>Percentage of the Transmit Buffer where messages sent to MTP2 from client with priority less than 3 is discarded by MTP2.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="n1Onset">
+ <description>Number of MSUs in ReTransmit Buffer before onset of preventive retransmission in PCR.
+NOTE: Only valid if errorCorrection==SCC_MTP2_ERROR_CORRECTION_PCR.
+This value is ignored otherwise.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="n2Onset">
+ <description>Number of MSUs in ReTransmit Buffer before onset of preventive retransmission in PCR.
+NOTE: Only valid if errorCorrection==SCC_MTP2_ERROR_CORRECTION_PCR.
+This value is ignored otherwise.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <struct name="Mtp2ProfileDataItu">
+ <structMember name="suermT">
+ <description>SUERM parameter T.
+Measured in SU units.</description>
+ <long>
+ <range>
+ <min>1</min> <max>64</max>
+ </range>
+ <defaultValue>64</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="suermD">
+ <description>SUREM parameter D.
+Measurement units are in SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>256</max>
+ </range>
+ <defaultValue>256</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="suermN">
+ <description>SUERM parameter N.
+Measurement units are in SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>256</max>
+ </range>
+ <defaultValue>16</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="tin">
+ <description>Normal AERM threshold, Tin. Number of signal errors that cause abortion of a normal proving peroid.
+
+Measurement units are SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>7</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="tie">
+ <description>Emergency AERM threshold, Tie. Number of signal units errors that cause abortion of an emergency proving period.
+
+Measurement units are SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>7</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="provings">
+ <description>Proving abort limit. Number of consecutive aborted proving periods that will cause a return to the Out Of Service state.
+
+Measurement units are the number of proving periods.</description>
+ <long>
+ <range>
+ <min>1</min> <max>7</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT1">
+ <description>Maximum time to stay in Aligned Ready state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>65500</max>
+ </range>
+ <defaultValue>40000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT2">
+ <description>Maximum time to stay in Not Aligned state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>262000</max>
+ </range>
+ <defaultValue>5000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT3">
+ <description>Maximum time to stay in Aligned state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>2000</max>
+ </range>
+ <defaultValue>1000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4n">
+ <description>Length of the normal proving period.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>16300</max>
+ </range>
+ <defaultValue>7500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4e">
+ <description>Length of the emergengcy proving period.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>16300</max>
+ </range>
+ <defaultValue>400</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT5">
+ <description>Time between sending Status Indication "B" while in the Congested state.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>1</min> <max>255</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT6">
+ <description>Maximum time a remote site may remain in the congestated state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>8100</max>
+ </range>
+ <defaultValue>3000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT7">
+ <description>Maximum time to wait for an expected acknowledgement of an MSU before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>2000</max>
+ </range>
+ <defaultValue>500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="bitRate">
+ <description>The speed of the link. Only supported values are 64 and 56 kbit/s.
+0 = 64 kbit/s.
+1 = 56 kbit/s.
+
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="errorCorrection">
+ <description>The error correction algorithm to use. Only Basic Error Correction (BEC) is supported.
+0 = BEC
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet1">
+ <description>Percentage of the Transmit Buffer that will cause MTP2 to signal congestion for prio 1 messages towards client.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet2">
+ <description>Percentage of the Transmit Buffer that will cause MTP2 to signal congestion for prio 2 messages towards client.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet3">
+ <description>Percentage of the Transmit Buffer that will cause MTP2 to signal congestion for prio 3 messages towards client.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>90</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement1">
+ <description>Percentage of the Transmit Buffer that ceases congestion for prio 1 messages.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement2">
+ <description>Percentage of the Transmit Buffer that ceases congestion for prio 2 messages.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement3">
+ <description>Percentage of the Transmit Buffer that ceases congestion for prio 3 messages.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionDiscardLevel1">
+ <description>Percentage of the Transmit Buffer where messages sent to MTP2 from client with priority less than 1 is discarded by MTP2.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionDiscardLevel2">
+ <description>Percentage of the Transmit Buffer where messages sent to MTP2 from client with priority less than 2 is discarded by MTP2.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionDiscardLevel3">
+ <description>Percentage of the Transmit Buffer where messages sent to MTP2 from client with priority less than 3 is discarded by MTP2.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="n1Onset">
+ <description>Number of MSUs in ReTransmit Buffer before onset of preventive retransmission in PCR.
+NOTE: Only valid if errorCorrection==SCC_MTP2_ERROR_CORRECTION_PCR.
+This value is ignored otherwise.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="n2Onset">
+ <description>Number of MSUs in ReTransmit Buffer before onset of preventive retransmission in PCR.
+NOTE: Only valid if errorCorrection==SCC_MTP2_ERROR_CORRECTION_PCR.
+This value is ignored otherwise.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <struct name="Mtp2ProfileDataChina">
+ <structMember name="bitRate">
+ <description>The speed of the link. Only supported values are 64 and 56 kbit/s.
+0 = 64 kbit/s.
+1 = 56 kbit/s.
+
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="errorCorrection">
+ <description>The error correction algorithm to use. Only Basic Error Correction (BEC) is supported.
+0 = BEC</description>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="provings">
+ <description>Proving abort limit. Number of consecutive aborted proving periods that will cause a return to the Out Of Service state.
+
+Measurement units are the number of proving periods.</description>
+ <long>
+ <range>
+ <min>1</min> <max>7</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="suermD">
+ <description>SUERM parameter D.
+Measurement units are in SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>256</max>
+ </range>
+ <defaultValue>256</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="suermN">
+ <description>SUERM parameter N.
+Measurement units are in SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>256</max>
+ </range>
+ <defaultValue>16</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="suermT">
+ <description>SUERM parameter T.
+Measured in SU units.</description>
+ <long>
+ <range>
+ <min>1</min> <max>64</max>
+ </range>
+ <defaultValue>64</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="tie">
+ <description>Emergency AERM threshold, Tie. Number of signal units errors that cause abortion of an emergency proving period.
+
+Measurement units are SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>7</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT1">
+ <description>Maximum time to stay in Aligned Ready state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>65500</max>
+ </range>
+ <defaultValue>45000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT2">
+ <description>Maximum time to stay in Not Aligned state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>262000</max>
+ </range>
+ <defaultValue>132000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT3">
+ <description>Maximum time to stay in Aligned state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>2000</max>
+ </range>
+ <defaultValue>1000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4e">
+ <description>Length of the emergengcy proving period.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>16300</max>
+ </range>
+ <defaultValue>500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4n">
+ <description>Length of the normal proving period.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>16300</max>
+ </range>
+ <defaultValue>8200</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT5">
+ <description>Time between sending Status Indication "B" while in the Congested state.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>1</min> <max>255</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT6">
+ <description>Maximum time a remote site may remain in the congestated state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>8100</max>
+ </range>
+ <defaultValue>5000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT7">
+ <description>Maximum time to wait for an expected acknowledgement of an MSU before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>2000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="tin">
+ <description>Normal AERM threshold, Tin. Number of signal errors that cause abortion of a normal proving peroid.
+
+Measurement units are SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>7</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet1">
+ <description>Percentage of the Transmit Buffer that will cause MTP2 to signal congestion for prio 1 messages towards client.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet2">
+ <description>Percentage of the Transmit Buffer that will cause MTP2 to signal congestion for prio 2 messages towards client.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet3">
+ <description>Percentage of the Transmit Buffer that will cause MTP2 to signal congestion for prio 3 messages towards client.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>90</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement1">
+ <description>Percentage of the Transmit Buffer that ceases congestion for prio 1 messages.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement2">
+ <description>Percentage of the Transmit Buffer that ceases congestion for prio 2 messages.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement3">
+ <description>Percentage of the Transmit Buffer that ceases congestion for prio 3 messages.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionDiscardLevel1">
+ <description>Percentage of the Transmit Buffer where messages sent to MTP2 from client with priority less than 1 is discarded by MTP2.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionDiscardLevel2">
+ <description>Percentage of the Transmit Buffer where messages sent to MTP2 from client with priority less than 2 is discarded by MTP2.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionDiscardLevel3">
+ <description>Percentage of the Transmit Buffer where messages sent to MTP2 from client with priority less than 3 is discarded by MTP2.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="n1Onset">
+ <description>Number of MSUs in ReTransmit Buffer before onset of preventive retransmission in PCR.
+NOTE: Only valid if errorCorrection==SCC_MTP2_ERROR_CORRECTION_PCR.
+This value is ignored otherwise.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="n2Onset">
+ <description>Number of MSUs in ReTransmit Buffer before onset of preventive retransmission in PCR.
+NOTE: Only valid if errorCorrection==SCC_MTP2_ERROR_CORRECTION_PCR.
+This value is ignored otherwise.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <enum name="EmergencyStatus">
+ <description>This enumeration specifies the different stages of the emergency state.</description>
+ <enumMember name="NEVER_USED">
+ <description>Emergency state has not been activated since installation of license key file.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="ACTIVE">
+ <description>All capacity restrictions removed and all features enabled. The maximum time in this state is 7 days.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="USE_DEGRADED">
+ <description>A new license key file has to be istalled in order not to jopardize future use and performance.
+The maximum time in this state is 7 days.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="ACTIVE_AGAIN">
+ <description>All features enabled again for a maximum period of 7 days then a new license key file has to be installed in order to be able to use this node.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="USE_DISABLED">
+ <description>Use of the node is no longer allowed since no new license key file has been installed.</description>
+ <value>4</value>
+ </enumMember>
+ </enum>
+
+ <struct name="EmergencyInfo">
+ <description>This attribute provides information about the current EmergencyState.
+
+Note: for the states NEVER_USED and USE_DISABLED the return value for time is insignificant.</description>
+ <structMember name="state">
+ <description>The current emergency state of the license server.</description>
+ <enumRef name="EmergencyStatus">
+ <defaultValue>NEVER_USED</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="time">
+ <description>This attribute holds information on the time elapsed in this state.
+
+Note: The time out values for the states ALL_OPEN, DEGADED and PROLONGED is 7 days. The unit for this attribute is seconds.
+1 day = 86400 seconds
+7 days = 604800 seconds.</description>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <enum name="NodeRestartType">
+ <enumMember name="WARM_AT_PIU_RESTART">
+ <description>Warm node restart at restart of the last PIU.</description>
+ <value>4</value>
+ </enumMember>
+ <enumMember name="COLD_AT_PIU_RESTART">
+ <description>Cold node restart at restart of the last PIU.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="WARM_AT_PIU_FAULT">
+ <description>Warm node restart at fault mark of the last PIU.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="COLD_AT_PIU_FAULT">
+ <description>Cold node restart at fault mark of the last PIU.</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <struct name="UniSaalProfileData">
+ <structMember name="maxPD">
+ <description>Maximum number of SD PDUs before a poll is sent.
+
+maxPD &lt; initialCredit</description>
+ <long>
+ <range>
+ <min>10</min> <max>10000</max>
+ </range>
+ <defaultValue>25</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="maxStat">
+ <description>Maximum number, odd integer value, of list elements placed in a STAT PDU.
+
+Note: The maxStat attribute is dependent on the AAL5 maximum SDU size defined in the Aal5TpVccTp MO. The maxStat times 4 (octets) plus additional 12 octets (for header) must not exceed the AAL5 maximum SDU size (lower of the two directions, fromUserMaxSduSize and toUserMaxSduSize).
+The consistency control is not performed until the UniSaalTp MO is created since there is no relation between the UniSaalProfile MO and the Aal5TpVccTp MO.</description>
+ <long>
+ <range>
+ <min>3</min> <max>1001</max>
+ </range>
+ <defaultValue>67</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="initialCredit">
+ <description>Initial number of credits.
+
+Note: For 64 kbit/s use 30.
+
+Note! The value for initialCredit must be larger than the value of maxPD.
+</description>
+ <long>
+ <range>
+ <min>10</min> <max>1000</max>
+ </range>
+ <defaultValue>250</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerKeepAlive">
+ <description>Timer to be used during a period of no outstanding acknowledgements or new data pending receipt of credit. At timeout the peer is polled to see if it is alive. The timer determines the interval between polls in transient phase. This timer should be greater than the roundtripdelay and also greater than timerpoll. Time unit = milliseconds.
+</description>
+ <long>
+ <range>
+ <min>10</min> <max>10000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerNoResponse">
+ <description>Timer to determine the maximum time interval during which at least one STAT PDU reception is expected as a response to a poll. This timer should be equal to timerKeepAlive+roundtripdelay. Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>100000</max>
+ </range>
+ <defaultValue>7000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerIdle">
+ <description>Timer running when there are no PDUs to transmit and there are no outstanding acknowledgements or data pending for credit. When this timer is running, no POLL PDUs are sent. This timer should be significantly greater than timerKeepAlive value. Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>1000</min> <max>600000</max>
+ </range>
+ <defaultValue>15000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerCC">
+ <description>Timer determining the time between re-transmission of PDUs: BGN, END, ER, RS. Should be slightly more than the roundtripdelay. Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>10000</max>
+ </range>
+ <defaultValue>1000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerPoll">
+ <description>Timer that specifies the maximum time between sending of POLL PDUs to the peer receiver during other traffic (active phase). Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>100000</max>
+ </range>
+ <defaultValue>750</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="maxCC">
+ <description>Maximum number of re-transmissions of PDUs: BGN, END, ER, RS. Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet">
+ <description>Attribute specifying the percentage of the buffer that must be filled in order to cause congestion. Congestion is notified to the users of this protocol layer. The part of the buffer above the congestion level is used to take care of messages that were sent before the users stopped sending.
+
+This attribute should follow the rule 0 &lt;= congestationAbatement &lt; congestationOnSet &lt;= 100.</description>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement">
+ <description>Attribute specifying the percentage of the buffer for which congestion is stopped. If the congestionAbatement level is lesser but almost equal to congestionOnSet, congestion alarms might be raised and ceased very often.
+
+This attribute should follow the rule 0 &lt;= congestationAbatement &lt; congestationOnSet &lt;= 100.</description>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <struct name="NniSaalProfileData">
+ <description>Struct holding the values for an NniSaalProfile.
+
+NOTE: Congestition Level 1 - 3 is supported.</description>
+ <structMember name="timerPoll">
+ <description>Timer that specifies the maximum time between sending of POLL PDUs to the peer receiver during other traffic (active phase). Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>100000</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="maxCC">
+ <description>Maximum number of re-transmissions of PDUs: BGN, END, ER, RS.</description>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="maxPD">
+ <description>Maximum number of SD PDUs before a poll is sent.
+
+maxPD &lt; initialCredit</description>
+ <long>
+ <range>
+ <min>0</min> <max>10000</max>
+ </range>
+ <defaultValue>25</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="maxStat">
+ <description>Maximum number, odd integer value, of list elements placed in a STAT PDU.
+
+Note: The maxStat attribute is controlled by the AAL5 maximum SDU size defined in the Aal5TpVccTp MO. The maxStat times 4 (octets) plus additional 12 octets (for header) must not exceed the AAL5 maximum SDU size (lower of the two directions, fromUserMaxSduSize and toUserMaxSduSize).
+
+The consistency control is not performed until the NniSaalTp MO is created since there is no relation between the NniSaalProfile MO and the Aal5TpVccTp MO.</description>
+ <long>
+ <range>
+ <min>3</min> <max>1001</max>
+ </range>
+ <defaultValue>67</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="initialCredit">
+ <description>Initial number of credits.
+
+Note: For 64 kbit/s use 30.
+
+Note! The value for initialCredit must be larger than the value of maxPD.</description>
+ <long>
+ <range>
+ <min>10</min> <max>1000</max>
+ </range>
+ <defaultValue>250</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerKeepAlive">
+ <description>Timer to be used during a period of no outstanding acknowledgements or new data pending receipt of credit. At timeout the peer is polled to see if it is alive. The timer determines the interval between polls in transient phase. This timer should be greater than the roundtripdelay and also greater than timerpoll. Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>10000</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerNoResponse">
+ <description>Timer to determine the maximum time interval during which at least one STAT PDU reception is expected as a response to a poll.This timer should be equal to timerKeepAlive+roundtripdelay. Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>100000</max>
+ </range>
+ <defaultValue>500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerIdle">
+ <description>Timer running when there are no PDUs to transmit and there are no outstanding acknowledgements or data pending for credit. When this timer is running, no POLL PDUs are sent. This timer should be significantly greater than timerKeepAlive value. Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>10000</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerCC">
+ <description>Timer determining the time between re-transmission of PDUs: BGN, END, ER, RS. Time unit = milliseconds.
+Should be more than the roundtrip delay.</description>
+ <long>
+ <range>
+ <min>10</min> <max>10000</max>
+ </range>
+ <defaultValue>200</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="mps">
+ <description>Management Proving Status which is used to decide if proving is done or not during SAAL connection setup.
+</description>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionLevel1OnSet">
+ <description>Attribute specifying the percentage of the buffer that must be filled in order to cause congestion.
+Congestion is notified to the users of this protocol layer. The part of the buffer above the congestion
+level is used to take care of messages that were sent before the users stopped sending.
+
+Attribute specifying the percentage of the buffer that must be filled in order to cause congestion.
+Congestion is notified to the users of this protocol layer. The part of the buffer above the congestion
+level is used to take care of messages that were sent before the users stopped sending.
+
+This attribute should follow the rule 0 &lt;= congestationLevel1OnSet &lt;= congestationLevel2OnSet &lt;= congestationLevel3OnSet &lt;= 100.</description>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionLevel2OnSet">
+ <description>Attribute specifying the percentage of the buffer that must be filled in order to cause congestion.
+Congestion is notified to the users of this protocol layer. The part of the buffer above the congestion
+level is used to take care of messages that were sent before the users stopped sending.
+
+This attribute should follow the rule 0 &lt;= congestationLevel1OnSet &lt;= congestationLevel2OnSet &lt;= congestationLevel3OnSet &lt;= 100.</description>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionLevel3OnSet">
+ <description>Attribute specifying the percentage of the buffer that must be filled in order to cause congestion.
+Congestion is notified to the users of this protocol layer. The part of the buffer above the congestion
+level is used to take care of messages that were sent before the users stopped sending.
+
+This attribute should follow the rule 0 &lt;= congestationLevel1OnSet &lt;= congestationLevel2OnSet &lt;= congestationLevel3OnSet &lt;= 100.</description>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>90</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionLevel1Abatement">
+ <description>Attribute specifying the percentage of the buffer for which congestionLevel1 is stopped. If the congestionAbatement level is lesser but almost equal to congestionOnSet, congestion alarms might be raised and ceased very often.
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="nrOfPDUsDuringProving">
+ <description>The length of proving in terms of number of transmitted PDUs (n1).
+noOfPDUsDuringProving x T3 &lt; T2
+
+For the TTC standard the only allowed value is 0 (which means no proving).</description>
+ <long>
+ <range>
+ <min>0</min> <max>100000</max>
+ </range>
+ <defaultValue>1000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="maxNRP">
+ <description>State variable which defines max number of retransmissions of PDUs during proving to consider proving successful.
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerNoCredit">
+ <description>Maximum time of no credit. If the timer expires, the assured data transfer mode is released.</description>
+ <long>
+ <range>
+ <min>0</min> <max>100000</max>
+ </range>
+ <defaultValue>1500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerRepeatSrec">
+ <description>Timer which is set whenever a report of SSCOP recovery is received from the SSCF. If the timer is running when another report of recovery is received, the assured data transfer mode is released. If the timer expires, nothing is done. Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>0</min> <max>86400000</max>
+ </range>
+ <defaultValue>3600000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT1">
+ <description>Timer between the link release action and the next link re-establish action during the alignment. At expiry of timer T1, a new attempt to setup assured data transfer mode to the peer is done. Time unit = milliseconds.
+</description>
+ <long>
+ <range>
+ <min>10</min> <max>100000</max>
+ </range>
+ <defaultValue>5000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT2">
+ <description>Total time that SSCF will attempt alignment. At expiry of timer T2, the alignment procedure will be interrupted.
+ Time unit = milliseconds.
+</description>
+ <long>
+ <range>
+ <min>10</min> <max>200000</max>
+ </range>
+ <defaultValue>30000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT3">
+ <description>Time between proving PDUs. The timer is set such that loading of the signalling link is approximately 50% of its nominal rate.
+Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>5</min> <max>1000</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <exception name="ListOfTimeSlotsNotUniqueException">
+ <description>Exception thrown when a time slot appears more than once in the time slot list.</description>
+ </exception>
+
+ <enum name="RefActivity">
+ <description>RefActivity can have the following values:
+
+inactive = Synchronization reference is currently not used in system clock generation.
+active = Synchronization is used in system clock generation.
+</description>
+ <enumMember name="inactive">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="active">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="RefState">
+ <description>RefState can have the following values:
+failed = synchronization reference is not capable to perform its required tasks.
+degraded = capability of synchronization reference to perform its required tasks is degraded e.g. because of signal level degradation. This value is only applicable for traffic carrying (ET physical path termination) synchronization references. Note: attribute degradationIsFault controls whether synchronization reference degradation is interpreted as a synchronization reference fault or not.
+lossOfTracking = system clock regulation algorithm on TU board can not follow the 8kHz synchronization reference signal either because of the poor quality of the signal or because of a HW fault at TU board. If all synchronization references repeatedly end up to state lossOfTracking, fault is likely in TU HW.
+ok = synchronization reference is capable of performing its required tasks.
+</description>
+ <enumMember name="failed">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="degraded">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="lossOfTracking">
+ <value>2</value>
+ </enumMember>
+ <enumMember name="ok">
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <enum name="FaultCriteria">
+ <description>FaultCriteria can have the following values:
+degrNotFault = synchronization reference degradation is NOT interpreted as a synchronization reference fault.
+degrIsFault = synchronization reference degradation is interpreted as a synchronization reference fault.</description>
+ <enumMember name="degrNotFault">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="degrIsFault">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="ClockState">
+ <description>ClockState can have the following values:
+startUp =
+locked = system clock signal on Timing Unit is locked: a synchronization reference is used in the system clock generation, clock accuracy is 50 ppb or better.
+holdOver = system clock signal on Timing Unit is hold-over: no synchronization reference is used in system clock generation, clock accuracy is 50 ppb or better.
+freeRunning = system clock signal on Timing Unit is free running: no synchronization reference is used in system clock generation, clock accuracy is 4.6 ppm or better.
+failed = system clock signal on Timing Unit is failed: fault in system clock generation function, no quarantee of clock accuracy level.
+not Applicable = system clock signal on Timing Unit is not applicable: TU board not present.</description>
+ <enumMember name="unknownMode">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="startupMode">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="lockedMode">
+ <value>2</value>
+ </enumMember>
+ <enumMember name="holdOverMode">
+ <value>3</value>
+ </enumMember>
+ <enumMember name="freeRunningMode">
+ <value>4</value>
+ </enumMember>
+ <enumMember name="failedMode">
+ <value>5</value>
+ </enumMember>
+ <enumMember name="lossOfTrackingMode">
+ <value>6</value>
+ </enumMember>
+ <enumMember name="notApplicable">
+ <value>7</value>
+ </enumMember>
+ </enum>
+
+ <exception name="AlreadyRegisteredException">
+ <description>Exception thrown when an object is already registered.</description>
+ </exception>
+
+ <exception name="MaxNoOfRefRegisteredException">
+ <description>Exception thrown when the maximum number of references is reached.</description>
+ </exception>
+
+ <exception name="PriorityAlreadyInUseException">
+ <description>Exception thrown when a priority is already in use.</description>
+ </exception>
+
+ <exception name="PriorityOutOfRangeException">
+ <description>Exception thrown when the priority is out of range.</description>
+ </exception>
+
+ <exception name="NotPermittedException">
+ <description>Exception thrown when an reference is not valid, null or of incorrect type.</description>
+ </exception>
+
+ <exception name="NotRegisteredException">
+ <description>Exception thrown when trying to de-register an object that is not registered in the database.</description>
+ </exception>
+
+ <enum name="SystemClockRedundancy">
+ <enumMember name="SYSTEM_CLOCK_USERS_USE_PLANE_A">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="SYSTEM_CLOCK_USERS_USE_PLANE_B">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="SYSTEM_CLOCK_USERS_USE_PLANE_A_AND_B">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <exception name="NotUniqueFroIdException">
+ <description>Exception thrown when a fro Id is not unique.</description>
+ </exception>
+
+ <enum name="ActiveSwitchPlane">
+ <enumMember name="switchPlaneA">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="switchPlaneB">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="switchPlaneBoth">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="SwitchReliableGroup">
+ <description>A predefined group consisting of working links and their corresponding protecting links. These links form the n+m link redundancy. </description>
+ <enumMember name="physicalLinkStatusWorking">
+ <description>Defines physical link status.
+</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="physicalLinkStatusProtecting">
+ <description>Defines physical link status.
+</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="physicalLinkStatusUndefined">
+ <description>Defines physical link status.
+</description>
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <struct name="GlobalTitleData">
+ <structMember name="indicator">
+ <description>Global title indicator should have following values for both ITU and TTC:
+
+The values for the GT Indicator
+
+Value Comment
+
+0 No new global title
+2 TT only
+3 TT-NP-ES
+4 TT-NP-ES-NOA
+
+Explanation:
+
+TT = translation type
+NP = numbering plan
+ES = encoding scheme
+NOA = nature of address indication</description>
+ <long>
+ <range>
+ <min>0</min> <max>4</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="natureOfAddress">
+ <description>Indicates number type, i.e. national or international number.
+Coding of the Nature Address:
+
+0 = "unknown"
+1 = "Subscriber number"
+2 = "Reserved for national use"
+3 = "National significant number"
+4 = "International number"</description>
+ <long>
+ <range>
+ <min>0</min> <max>4</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="numberingPlan">
+ <description>Indicates which numbering plan that is used.
+
+Coding of the Numbering Plan:
+
+0 = "Unknown"
+1 = "ISDN/Telephony Numbering Plan"
+3 = "Data Numbering Plan"
+4 = "Telex Numbering Plan"
+5 = "Maritime Mobile Numbering Plan"
+6 = "Land Mobile Numbering Plan"
+7 = "ISDN/Mobile Numbering Plan"
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>7</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="translationType">
+ <description>Used to direct the message to the appropriate Global Title translation function.</description>
+ <long>
+ <range>
+ <min>0</min> <max>254</max>
+ </range>
+ </long>
+ </structMember>
+ <structMember name="addressInformation">
+ <description>Digit string of 1-37 digits, where each digit is 0-9, and B, C. B and C are for Code 11 and Code 12.
+The addressInformation may also contain wild card symbols: "*" or "?". Wild cards are only allowed for defining Global Title Translations, they are not allowed for specifying SCCP SAPs (built with SPC and Global Title or SPC + SSN + Global Title).</description>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>37</max>
+ </lengthRange>
+ </string>
+ </structMember>
+ <structMember name="encodingScheme">
+ <description>Indicates if the number of address signals are an odd or even number, and is coded as follows:
+
+0 = "Unknown"
+1 = "BCD, odd number of digits"
+2 = "BCD, even number of digits"
+
+Other values in the encoding scheme will result in the error "Wrong Nature Of Address", (Routing failure reason=No translation for an address of such nature).</description>
+ <long>
+ <range>
+ <min>0</min> <max>2</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <enum name="SharingMode">
+ <enumMember name="loadShare">
+ <description>The when sharing mode is set to loadShare the SCCP traffic is load shared between the two entities (access points).</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="dupliDominant">
+ <description>When the sharing mode is set to dupliDominant the second entity (access point) is a backup for the first entity.</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="EncodingScheme">
+ <description>Possible values for number signalling.</description>
+ <enumMember name="UNKNOWN">
+ <description>Unkown encoding scheme.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="ODD_NUMBER">
+ <description>BCD, odd number of digits.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="EVEN_NUMBER">
+ <description>BCD, even number of digits.</description>
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="GlobalTitleIndicator">
+ <description>Global title indicator values for China, ITU, TTC and ANSI.
+
+Note: China, ITU and TCC will use TT_ONLY, TT_NP_ES, TT_NP_ES_NOA, NOA_ONLY.
+
+ANSI will use:
+ANSI_TT_NP_ES = 5
+ANSI_TT_ONLY = 6
+</description>
+ <enumMember name="TT_ONLY">
+ <description>Translation Type only.
+
+Only valid for China, ITU and TTC.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="TT_NP_ES">
+ <description>Translation Type, Numbering Plan and Encoding Scheme.
+
+Only valid for China, ITU and TTC.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="TT_NP_ES_NOA">
+ <description>Translation Type, Numbering Plan, Encoding Scheme, and Nature Of Address indication.
+
+Only valid for China, ITU and TTC.</description>
+ <value>4</value>
+ </enumMember>
+ <enumMember name="NOA_ONLY">
+ <description>Nature of Address indicator only.
+
+Only valid for China, ITU and TTC.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="ANSI_TT_NP_ES">
+ <description>Translation Type, Numbering Plan and Encoding Scheme.
+
+Only valid for ANSI.
+</description>
+ <value>5</value>
+ </enumMember>
+ <enumMember name="ANSI_TT_ONLY">
+ <description>Translation Type only.
+
+Only valid for ANSI.
+</description>
+ <value>6</value>
+ </enumMember>
+ </enum>
+
+ <enum name="NatureOfAddress">
+ <description>Phone number types.</description>
+ <enumMember name="UNKNOWN">
+ <description>Unknown number type.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="SN">
+ <description>Subscriber number type.
+</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="RN">
+ <description>Reserved for national use, number type.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="NSN">
+ <description>National Significant Number type.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="IN">
+ <description>International number type.</description>
+ <value>4</value>
+ </enumMember>
+ </enum>
+
+ <enum name="NumberingPlan">
+ <description>Numbering plans.</description>
+ <enumMember name="UNKNOWN">
+ <description>Unknown numbering plan.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="TELEPHONY">
+ <description>ISDN/Telephony numbering plan.
+</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="DATA">
+ <description>Data numbering plan.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="TELEX">
+ <description>Telex numbering plan.
+</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="MOBILE_MARITIME">
+ <description>Maritime mobile numering plan.
+</description>
+ <value>4</value>
+ </enumMember>
+ <enumMember name="MOBILE_LAND">
+ <description>Land mobile numbering plan.
+</description>
+ <value>5</value>
+ </enumMember>
+ <enumMember name="MOBILE">
+ <description>ISDN/Mobile numbering plan.</description>
+ <value>6</value>
+ </enumMember>
+ </enum>
+
+ <enum name="SccpCountType">
+ <enumMember name="MESSAGES">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="OCTETS">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <struct name="Scmg">
+ <structMember name="sendSST">
+ <description>Controls when to send SST (SCCP Subsystem Test message).
+
+0 = Wait for tStatInfo timer to expire once after MTP_RESUME before sending SST.
+1 = Send SST immediately after MTP_RESUME, then start tStatInfo timer.</description>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="sendSSA">
+ <description>Controls when to send SSA (SCCP Subsystem Allowed message).
+
+0 = Do not send SSA when client attaches, wait until SST is received. (default for ANSI/CHINA/ITU/TTC)
+1 = Send SSA immediately when client attaches.</description>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="sendSSP">
+ <description>Controls whether to send SSP (SCCP Subsystem Prohibited message).
+
+0 = Do not send SSP when client detaches. (default for TTC)
+1 = Send SSP immediately when client detaches. (default for ANSI/CHINA/ITU)</description>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="useSST">
+ <description>Controls whether to send SST messages or not (SCCP Subsystem Test message).
+
+0 = Send SST as indicated by sendSST. (default for ANSI/CHINA/ITU)
+1 = (not used)
+2 = (not used)
+3 = Do not initiate SST messages at all, ie. do not start timer tStatInfo nor send any SST at MTP_RESUME. (default for TTC)</description>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="allowRemoteBroadcast">
+ <description>Controls the remote broadcast.
+
+0 = allow remote broadcast. (default for ANSI/CHINA/ITU/TTC)
+1 = do not allow remote broadcast</description>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="initiateTimerTcon">
+ <description>Controls whether to initiate hardcoded congestion timer or not.
+
+0 = start timer when SSC is received. (default for CHINA/ITU/TTC)
+1 = do not start timer
+
+Note! This attribute is not valid for the ANSI standard.</description>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <enum name="DiscardReturnServiceMsg">
+ <enumMember name="DISCARD">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="RETURN">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <exception name="WrongUserTypeException">
+ </exception>
+
+ <exception name="UsageNotPermittedException">
+ </exception>
+
+ <enum name="J1Type">
+ <description>J1Type can have the following values:
+J1_G = 0 according to TTC JT-G703/G704
+J1_I = 1 according to TCC JT-I431</description>
+ <enumMember name="j1_G">
+ <description>J1 according to TTC JT-G703/G704</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="j1_I">
+ <description>J1 according to TCC JT-I431</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="StandardMode">
+ <description>Indicates what standard the MAO is operating to.</description>
+ <enumMember name="TTC">
+ <description>The standard mode is Telecommunication Technology Committee (TTC).</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="ANSI">
+ <description>The standard mode ANSI.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="ETSI">
+ <description>The standard mode is ETSI.</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="MuxMode">
+ <description>Indicates what multiplexing is being used.</description>
+ <enumMember name="STANDBY">
+ <description>Standby for protection.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="E1_J1_T1_LEVEL">
+ <description>Multiplexing terminated at the E1/J1/T1 level.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="VC4_STS3CSPE_LEVEL">
+ <description>Multiplexing terminated at the VC-4/STS3CSPE level.</description>
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="Os155LoopBack">
+ <description>The loopback method available for use by the Os155SpiTtp MO.</description>
+ <enumMember name="NONE">
+ <description>No loopback in use.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="LINE">
+ <description>Loopingback using line.</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="SwitchModes">
+ <description>The switch modes.</description>
+ <enumMember name="AUTOMATIC">
+ <description>Automatic switching.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="LOCKED">
+ <description>Locked for swtiching.</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <exception name="FailedResourceException">
+ </exception>
+
+ <exception name="LockedResourceException">
+ </exception>
+
+ <exception name="UnknownReasonException">
+ </exception>
+
+ <exception name="AlreadyLockedException">
+ </exception>
+
+ <exception name="IncorrectOsi155SpiIdException">
+ </exception>
+
+ <enum name="PathTraceFormat">
+ <description>Path Trace Formats.</description>
+ <enumMember name="ITU_T_G707">
+ <description>16 byte path trace format according to ITU-T G707 table 4.</description>
+ <value>16</value>
+ </enumMember>
+ <enumMember name="GR_253_CORE">
+ <description>64 byte path trace format according to section 3.3.2.3, Telecordia GR-253-CORE.</description>
+ <value>64</value>
+ </enumMember>
+ </enum>
+
+ <enum name="Crc4Mode">
+ <description>Cyclical Redundancy Checks 4 modes.</description>
+ <enumMember name="OFF">
+ <description>CRC 4 is off.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="ON">
+ <description>CRC 4 is on.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="AUTOMATIC">
+ <description>CRC 4 is automatic.</description>
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="IdlePattern">
+ <description>Idle patterns.</description>
+ <enumMember name="A_LAW">
+ <description>A law idle pattern.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="U_LAW">
+ <description>Micro law idle pattern.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="UNDEFINED">
+ <description>Undefined idle pattern.</description>
+ <value>0</value>
+ </enumMember>
+ </enum>
+
+ <enum name="LoopbackState">
+ <description>The possible loopback states for E1/J1/T1/E3/T3PhysPathTerm MOs.</description>
+ <enumMember name="none">
+ <description>This is the normal state, no loop back is preformed (and ordinary traffic is running).</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="line">
+ <description>The phyiscal path is looped on the line side, the external incoming path is looped back to the external outgoing path.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="system">
+ <description>The physical path is looped on the system side, the (node-) internal incoming path is looped back to the internal outgoing path.</description>
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="TransmissionMode">
+ <description>L stands for long haul interface and S stands for short haul interface.
+The subsequent figure specifies the cable distance in feets.</description>
+ <enumMember name="L_6000">
+ <description>Long Haul 6000 ft, -0 dB</description>
+ <value>8</value>
+ </enumMember>
+ <enumMember name="L_4000">
+ <description>Long Haul 4000 ft, -7 dB</description>
+ <value>7</value>
+ </enumMember>
+ <enumMember name="L_2000">
+ <description>Long Haul 2000 ft, -15 dB</description>
+ <value>6</value>
+ </enumMember>
+ <enumMember name="L_0">
+ <description>Long Haul 0 ft, -22 dB</description>
+ <value>5</value>
+ </enumMember>
+ <enumMember name="S_133">
+ <description>Short Haul 0..133 ft</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="S_266">
+ <description>Short Haul 134..266 ft</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="S_399">
+ <description>Short Haul 267..399 ft</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="S_533">
+ <description>Short Haul 400..533 ft</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="S_655">
+ <description>Short Haul 534..655 ft</description>
+ <value>4</value>
+ </enumMember>
+ </enum>
+
+ <struct name="Mtp3bSpItuPriorityData">
+ <description>Priority attributes for MTP3b SP of the ITU standard.</description>
+ <structMember name="prioSlt">
+ <description>The prioSlt attribute sets the priority for the
+ Signalling Link Test Message and Acknowledge (SLTM / SLTA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioCo">
+ <description>The prioCo attribute sets the priority for the ChangeOver Order and Acknowledge (COO/COA) or eXtended Change over Order and Acknowledge (XCO/XCA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet)
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioCb">
+ <description>The prioCb attribute sets the priority for the
+ Change Back Declaration and Acknowledge (CBD / CBA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioEc">
+ <description>The prioEc attribute sets the priority for the
+Emergency Change over Order and Acknowledge (ECO / ECA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioRst">
+ <description>The prioRst attribute sets the priority for the
+signalling Route Set Test (RST) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioTra">
+ <description>The prioTra attribute sets the priority for the
+Traffic Restart Allowed signal (TRA) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioUpu">
+ <description>The prioUpu attribute sets the priority for the
+ User Part Unavailable (UPU) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioLink">
+ <description>The prioLink attribute sets the priority for link related messages when issued by the MTP3b itself. The messages are :
+
+Link INhibit (LIN), Link UNinhibit (LUN),
+Link Inhibit Denied (LID),
+Link Inhibit Acknowledge (LIA),
+Link Uninhibit Acknowledge (LUA),
+Link Forced Uninhibit (LFU),
+Link Local inhibit Test (LLT) and
+Link Remote inhibit Test (LRT)
+
+When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ </struct>
+
+ <struct name="Mtp3bSpItuTimerData">
+ <description>ITU timers for MTP3bSpItu. Timervalues in 1/10 s (deciseconds).</description>
+ <structMember name="timerT1">
+ <description>Delay to avoid message mis-sequencing on changeover.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT2">
+ <description>Timer for waiting for a COO or a COA.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT3">
+ <description>Delay to avoid message mis-sequencing on a time controlled diversion change back.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4">
+ <description>Timer for waiting for CBA, first attempt.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT5">
+ <description>Timer for waiting for CBA, second attempt
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT6">
+ <description>Timer for delay to avoid message mis-sequencing on controlled rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>9</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT8">
+ <description>Timer for delay to prohibit sending of TFP messages via the response method. This is a STP specific parameter, which is ignored when configured as an endpoint.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT10">
+ <description>Timer for waiting to repeat sending of RST periodically.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>400</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT12">
+ <description>Waiting for uninhibit acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT13">
+ <description>Timer for waiting for force uninhibit.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT14">
+ <description>Timer for waiting for inhibition acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT17">
+ <description>Delay to avoid oscillation of initial alignment failure and link restart.
+
+The value for this timer should be less than the value for timerT2.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>9</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTBsnt">
+ <description>Waiting for BSNT value from MTP-2 or SAAL (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTRetrieval">
+ <description>Timer for waiting for completion of buffer retrieval from MTP-2 or SAAL (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTStart">
+ <description>Timer for retransmission of DL_START_req if no answer received. Started when timerT17 expires. (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>1200</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTc">
+ <description>Controlling the period a route set is considered congested when a Transfer Controlled message has been received.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT18">
+ <description>Supervision timer for the first phase of a restarting STP. This is an STP specific parameter, which is ignored when configured as an endpoint.
+
+The value for this timer should be less than the value for timerT2.
+
+Unit: deciseconds (1/10 second).
+</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>550</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT19">
+ <description>Controlling the response of the receipt of a traffic restart message from an adjacent node.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>680</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT20">
+ <description>Overall MTP restart timer at the restarting MTP.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>600</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT21">
+ <description>Overall MTP restart timer at an adjacent signalling point to a restarting MTP.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>640</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT22">
+ <description>Local inhibit test timer.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>2500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT23">
+ <description>Remote inhibit test timer.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>2500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerSlta">
+ <description>Supervision timer for SLTA message (time within SLTA should arrive).
+
+Timer T1 in ITU Q.707 standard.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerSltm">
+ <description>Timer for sending SLTM periodically.
+
+Timer T2 in ITU Q.707 standard.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>400</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaTack">
+ <description>Timer used for message acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaPeriodicAudit">
+ <description>Timer used for audit procedure.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>300</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT1">
+ <description>Delay to avoid mis-sequencing of messages when an association fails.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT3">
+ <description>Delay to avoid mis-sequencing of messages when an association becomes active.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT6">
+ <description>Delay to avoid mis-sequencing on controlled rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT8">
+ <description>Delay to prohibit sending of DUNA messages via the response method.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT40">
+ <description>Delay to avoid message mis-sequencing on controlled/forced rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT41">
+ <description>Timer controlloing the traffic activation delay during restart phase.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT42">
+ <description>The forever interval period for trying association after an unsiccessfull trial.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaTc">
+ <description>Timer controlling the period a route set is considered congested when a SCON message has been received.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT15">
+ <description>Timer waiting to start signaling route set congestiontest. Used only if the Route Set
+Congestion Test Selectoption is set to "Use Route Set Congestion test".
+
+Guiding value 20 - 30.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT16">
+ <description>Timer waiting for route set congestion status update. Used only if the Route Set
+Congestion Test Selectoption is set to "Use Route Set Congestion test"
+
+Guiding value 14 - 22.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>14</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTDlack">
+ <description>Timer pending an acknowledge from the network layer for a DL_ACK_REQ.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaTassocack">
+ <description>Timer used for SCTP_ASSOCIATE_REQ message acknowledgement. This is the maximum time to wait for the SCTP_COMMUP_IND mesage before considering it to be an error.
+It should be longer than the time a message spends to reach the most distant destination, be processed and returned.</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <enum name="CongestLevel">
+ <description>The supported congestion levels.</description>
+ <enumMember name="level_0">
+ <description>No Congestion.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="level_1">
+ <description>Congestion level low.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="level_2">
+ <description>Congestion level medium.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="level_3">
+ <description>Congestion level high.</description>
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <exception name="ActivationFailedException">
+ </exception>
+
+ <exception name="NoAvailRouteException">
+ </exception>
+
+ <enum name="Mtp3bCongestLevel">
+ <enumMember name="notCongested">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="congested">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="Mtp3bNetworkInd">
+ <description>Indicates which type of geographical network, e.g. national, international, etc..
+
+Note: Not applicable for TTC.</description>
+ <enumMember name="INTERNATIONAL_NETWORK">
+ <description>International Network.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="SPARE">
+ <description>Spare (for international use only).</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="NATIONAL_NETWORK">
+ <description>National network.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="RESERVED_FOR_NATIONAL_USE">
+ <description>Reserved for national use.</description>
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <enum name="Mtp3bTfrHandling">
+ <description>Indicates how a TransFer Restricted (TFR) signal is handled.</description>
+ <enumMember name="HANDLE_AS_TFA">
+ <description>Treat the TransFer Restricted (FTR) signal as a TransFer Allowed (TFA) signal.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="IGNORED">
+ <description>Ignore the TransFer Restricted (TFR) signal.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="HANDLE_BY_STANDARD">
+ <description>Handle the incoming TRF messages according to the standard.</description>
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="Mtp3bSioSpareBitsUse">
+ <description>Indicates whether the two spare bits in the Service Information Octet (SIO) should be treated as spare or for indicating a priority level. </description>
+ <enumMember name="SPARE">
+ <description>The two spare bits in the SIO are treated as spare.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="PRIO">
+ <description>The two spare bits in the SIO are to be used for indicating a priority level.</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="Mtp3bItuVersion">
+ <description>Indicates which version of the ITU standard.</description>
+ <enumMember name="ITU_T_88">
+ <description>ITU-T -88.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="ITU_T_03_93">
+ <description>ITU-T 03/93.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="ITU_T_07_96">
+ <description>ITU-T 07/96</description>
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <struct name="Mtp3bSpAnsiTimerData">
+ <description>ANSI timers for MTP3bSpAnsi. Timervalues in 1/10 s (deciseconds).</description>
+ <structMember name="timerT1">
+ <description>Delay to avoid message mis-sequencing on changeover.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT2">
+ <description>Timer for waiting for a COO or a COA.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT3">
+ <description>Delay to avoid message mis-sequencing on a time controlled diversion change back.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4">
+ <description>Timer for waiting for CBA, first attempt.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT5">
+ <description>Timer for waiting for CBA, second attempt
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT6">
+ <description>Timer for delay to avoid message mis-sequencing on controlled rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>9</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT8">
+ <description>Timer for delay to prohibit sending of TFP messages via the response method. This is a STP specific parameter, which is ignored when configured as an endpoint.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT10">
+ <description>Timer for waiting to repeat sending of RST periodically.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>400</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT12">
+ <description>Waiting for uninhibit acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT13">
+ <description>Timer for waiting for force uninhibit.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT14">
+ <description>Timer for waiting for inhibition acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT15">
+ <description>Timer waiting to start signaling route set congestiontest. Used only if the Route Set
+Congestion Test Selectoption is set to "Use Route Set Congestion test".
+
+Guiding value 20 - 30.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT16">
+ <description>Timer waiting for route set congestion status update. Used only if the Route Set
+Congestion Test Selectoption is set to "Use Route Set Congestion test"
+
+Guiding value 14 - 22.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>14</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT17">
+ <description>Delay to avoid oscillation of initial alignment failure and link restart.
+
+The value for this timer should be less than the value for timerT2.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>9</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTBsnt">
+ <description>Waiting for BSNT value from MTP-2 or SAAL (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTRetrieval">
+ <description>Timer for waiting for completion of buffer retrieval from MTP-2 or SAAL (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTStart">
+ <description>Timer for retransmission of DL_START_req if no answer received. Started when timerT17 expires. (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>1200</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTc">
+ <description>Controlling the period a route set is considered congested when a Transfer Controlled message has been received.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT30">
+ <description>Timer to limit sending of TFPs and TFRs in response to unexpected TRA and TRW. This timer is specific for STP functionality and is ignored when configured as an endpoint.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>300</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT25">
+ <description>Delay extension timer invoked on reciept of a Traffic Restart Waiting message from an adjacent SP which is restarting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>300</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT26">
+ <description>Controlling the periodic resend of Traffic Restart Waiting messages during restart of the local node.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>120</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT27">
+ <description>Timer enforcing a minimum node unavailablility period during MTP restart.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT28">
+ <description>Delay timer controlling a timed reaction of the restart of an adjacent node.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT29">
+ <description>Timer controlling the response of the receipt of Traffic Restart messages from an adjacent node.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>600</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT20">
+ <description>Controlling the periodic resend of Local Inhibit Change Message.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>1000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT21">
+ <description>Controlling the periodic resend of Remote Inhibit Test Message.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>1000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT22">
+ <description>Delay on commencement of MTP Restart to allow the node to rebuild an accurate routing table based on messages for adjacent nodes.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>600</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT23">
+ <description>Supervision timer for routing updates on MTP Restart.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>40</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT31">
+ <description>Timer controlling the detection of false link congestion.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTDlack">
+ <description>Timer pending an acknowledge from the network layer for a DL_ACK_REQ.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerSltm">
+ <description>Timer for sending SLTM periodically.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>400</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerSlta">
+ <description>Supervision timer for SLTA message (time within SLTA should arrive).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaTack">
+ <description>Timer used for message acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaPeriodicAudit">
+ <description>Timer used for audit procedure.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>300</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT1">
+ <description>Delay to avoid mis-sequencing of messages when an association fails.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT3">
+ <description>Delay to avoid mis-sequencing of messages when an association becomes active.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT6">
+ <description>Delay to avoid mis-sequencing on controlled rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT8">
+ <description>Delay to prohibit sending of DUNA messages via the response method.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT40">
+ <description>Delay to avoid message mis-sequencing on controlled/forced rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT41">
+ <description>Timer controlloing the traffic activation delay during restart phase.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT42">
+ <description>The forever interval period for trying association after an unsiccessfull trial.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaTc">
+ <description>Timer controlling the period a route set is considered congested when a SCON message has been received.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaTassocack">
+ <description>Timer used for SCTP_ASSOCIATE_REQ message acknowledgement. This is the maximum time to wait for the SCTP_COMMUP_IND mesage before considering it to be an error.
+It should be longer than the time a message spends to reach the most distant destination, be processed and returned.</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <struct name="Mtp3bSpTtcTimerData">
+ <description>TTC timers for MTP3bSpTtc. Timervalues in 1/10 s (deciseconds).</description>
+ <structMember name="timerT1">
+ <description>Delay to avoid message mis-sequencing on changeover.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT2">
+ <description>Timer for waiting for a COO or a COA.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT3">
+ <description>Delay to avoid message mis-sequencing on a time controlled diversion change back.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4">
+ <description>Timer for waiting for CBA, first attempt.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT6">
+ <description>Timer for delay to avoid message mis-sequencing on controlled rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>9</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT8">
+ <description>Timer for delay to prohibit sending of TFP messages via the response method. This is a STP specific parameter, which is ignored when configured as an endpoint.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT10">
+ <description>Timer for waiting to repeat sending of RST periodically.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>400</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT17">
+ <description>Delay to avoid oscillation of initial alignment failure and link restart.
+
+The value for this timer should be less than the value for timerT2.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>9</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerSrt">
+ <description>Timer pending a Signalling Route Test Acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTBsnt">
+ <description>Waiting for BSNT value from MTP-2 or SAAL (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTRetrieval">
+ <description>Timer for waiting for completion of buffer retrieval from MTP-2 or SAAL (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTStart">
+ <description>Timer for retransmission of DL_START_req if no answer received. Started when timerT17 expires. (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>1200</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTc">
+ <description>Controlling the period a route set is considered congested when a Transfer Controlled message has been received.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT15">
+ <description>Timer waiting to start signaling route set congestiontest. Used only if the Route Set
+Congestion Test Selectoption is set to "Use Route Set Congestion test".
+
+Guiding value 20 - 30.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT16">
+ <description>Timer waiting for route set congestion status update. Used only if the Route Set
+Congestion Test Selectoption is set to "Use Route Set Congestion test"
+
+Guiding value 14 - 22.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>14</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTDlack">
+ <description>Timer pending an acknowledge from the network layer for a DL_ACK_REQ.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <struct name="Mtp3bSpAnsiPriorityData">
+ <description>Priority attributes for MTP3b SP of the ANSI standard.</description>
+ <structMember name="prioSlt">
+ <description>The prioSlt attribute sets the priority for the
+ Signalling Link Test Message and Acknowledge (SLTM / SLTA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioCo">
+ <description>The prioCo attribute sets the priority for the ChangeOver Order and Acknowledge (COO/COA) or eXtended Change over Order and Acknowledge (XCO/XCA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet)
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioCb">
+ <description>The prioCb attribute sets the priority for the
+ Change Back Declaration and Acknowledge (CBD / CBA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioEc">
+ <description>The prioEc attribute sets the priority for the
+Emergency Change over Order and Acknowledge (ECO / ECA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioRst">
+ <description>The prioRst attribute sets the priority for the
+signalling Route Set Test (RST) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioTra">
+ <description>The prioTra attribute sets the priority for the
+Traffic Restart Allowed signal (TRA) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioUpu">
+ <description>The prioUpu attribute sets the priority for the
+ User Part Unavailable (UPU) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioLink">
+ <description>The prioLink attribute sets the priority for link related messages when issued by the MTP3b itself. The messages are :
+
+Link INhibit (LIN), Link UNinhibit (LUN),
+Link Inhibit Denied (LID),
+Link Inhibit Acknowledge (LIA),
+Link Uninhibit Acknowledge (LUA),
+Link Forced Uninhibit (LFU),
+Link Local inhibit Test (LLT) and
+Link Remote inhibit Test (LRT)
+
+When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ </struct>
+
+ <struct name="Mtp3bSpTtcPriorityData">
+ <description>Priority attributes for MTP3b SP of the TTC standard.</description>
+ <structMember name="prioCo">
+ <description>The prioCo attribute sets the priority for the ChangeOver Order and Acknowledge (COO/COA) or eXtended Change over Order and Acknowledge (XCO/XCA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet)
+.</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioCb">
+ <description>The prioCb attribute sets the priority for the
+ Change Back Declaration and Acknowledge (CBD / CBA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioEc">
+ <description>The prioEc attribute sets the priority for the
+Emergency Change over Order and Acknowledge (ECO / ECA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioRst">
+ <description>The prioRst attribute sets the priority for the
+signalling Route Set Test (RST) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioTfa">
+ <description>The prioTfa attribute sets the priority for the Transfer Allowed, TFA, messages.
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioRt">
+ <description>The priority indicator used for indicating message priority for signalling route test messages (SRT/SRA).
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioTfc">
+ <description>The priority indicator used for indicating the message prioirity for TFC.
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ </struct>
+
+ <enum name="Mtp3bSpPriorityLevel">
+ <description>Indicates the priority level for MTP 3.</description>
+ <enumMember name="LOWEST">
+ <description>Lowest priority setting.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="LOW">
+ <description>Low priority setting.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="HIGH">
+ <description>High priority setting.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="HIGHEST">
+ <description>Highest priority setting.</description>
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <struct name="Mtp3bSpChinaTimerData">
+ <description>China timers for MTP3bSpChina. Timervalues in 1/10 s (deciseconds).</description>
+ <structMember name="timerSlta">
+ <description>Supervision timer for SLTA message (time within SLTA should arrive).
+
+Timer T1 in ITU Q.707 standard.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerSltm">
+ <description>Timer for sending SLTM periodically.
+
+Timer T2 in ITU Q.707 standard.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>400</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT1">
+ <description>Delay to avoid message mis-sequencing on changeover.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT10">
+ <description>Timer for waiting to repeat sending of RST periodically.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>400</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT12">
+ <description>Waiting for uninhibit acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT13">
+ <description>Timer for waiting for force uninhibit.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT14">
+ <description>Timer for waiting for inhibition acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT17">
+ <description>Delay to avoid oscillation of initial alignment failure and link restart.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>9</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT18">
+ <description>Supervision timer for the first phase of a restarting STP. This is an STP specific parameter, which is ignored when configured as an endpoint.
+
+Unit: deciseconds (1/10 second).
+</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>200</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT19">
+ <description>Controlling the response of the receipt of a traffic restart message from an adjacent node.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>40</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT2">
+ <description>Timer for waiting for a COO or a COA.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT20">
+ <description>Overall MTP restart timer at the restarting MTP.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>40</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT21">
+ <description>Overall MTP restart timer at an adjacent signalling point to a restarting MTP.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>300</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT22">
+ <description>Local inhibit test timer.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>2500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT23">
+ <description>Remote inhibit test timer.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>2500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT3">
+ <description>Delay to avoid message mis-sequencing on a time controlled diversion change back.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4">
+ <description>Timer for waiting for CBA, first attempt.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT5">
+ <description>Timer for waiting for CBA, second attempt
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT6">
+ <description>Timer for delay to avoid message mis-sequencing on controlled rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>9</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT8">
+ <description>Timer for delay to prohibit sending of TFP messages via the response method. This is a STP specific parameter, which is ignored when configured as an endpoint.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTBsnt">
+ <description>Waiting for BSNT value from MTP-2 or SAAL (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTc">
+ <description>Controlling the period a route set is considered congested when a Transfer Controlled message has been received.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTRetrieval">
+ <description>Timer for waiting for completion of buffer retrieval from MTP-2 or SAAL (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTStart">
+ <description>Timer for retransmission of DL_START_req if no answer received. Started when timerT17 expires. (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>1200</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaTack">
+ <description>Timer used for message acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaPeriodicAudit">
+ <description>Timer used for audit procedure.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>300</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT1">
+ <description>Delay to avoid mis-sequencing of messages when an association fails.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT3">
+ <description>Delay to avoid mis-sequencing of messages when an association becomes active.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT6">
+ <description>Delay to avoid mis-sequencing on controlled rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT8">
+ <description>Delay to prohibit sending of DUNA messages via the response method.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT40">
+ <description>Delay to avoid message mis-sequencing on controlled/forced rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT41">
+ <description>Timer controlloing the traffic activation delay during restart phase.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT42">
+ <description>The forever interval period for trying association after an unsiccessfull trial.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaTc">
+ <description>Timer controlling the period a route set is considered congested when a SCON message has been received.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT15">
+ <description>Timer waiting to start signaling route set congestiontest. Used only if the Route Set
+Congestion Test Selectoption is set to "Use Route Set Congestion test".
+
+Guiding value 20 - 30.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT16">
+ <description>Timer waiting for route set congestion status update. Used only if the Route Set
+Congestion Test Selectoption is set to "Use Route Set Congestion test"
+
+Guiding value 14 - 22.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>14</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTDlack">
+ <description>Timer pending an acknowledge from the network layer for a DL_ACK_REQ.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaTassocack">
+ <description>Timer used for SCTP_ASSOCIATE_REQ message acknowledgement. This is the maximum time to wait for the SCTP_COMMUP_IND mesage before considering it to be an error.
+It should be longer than the time a message spends to reach the most distant destination, be processed and returned.</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <enum name="Mtp3bNetworkIndTtc">
+ <description>Indicates which type of geographical network, e.g. national, international, etc..
+
+Note: Only for TTC.</description>
+ <enumMember name="NATIONAL_NETWORK">
+ <description>National network.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="SPARE">
+ <description>Spare (for international use only).</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="INTERNATIONAL_NETWORK">
+ <description>International Network.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="SPARE_1">
+ <description>Spare.</description>
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <enum name="Mtp3bUsageState">
+ <description>There are three possible states for the usageState attribute:
+
+- idle, the Mtp3bSl carries no traffic.
+- active, the Mtp3bSl is working normally, and there is traffic, and it is not congested.
+- busy, the Mtp3bSl is working but is congested (traffic is routed on other links).</description>
+ <enumMember name="IDLE">
+ <description>idle, the Mtp3bSl carries no traffic.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="ACTIVE">
+ <description>active, the Mtp3bSl is working normally, and there is traffic, and it is not congested.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="BUSY">
+ <description>busy, the Mtp3bSl is working but is congested (traffic is routed on other links).</description>
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="Mtp3bProceduralState">
+ <description>The procedural state of the link.
+
+0 - not initialized
+1 - initialized</description>
+ <enumMember name="NOT_INITIALIZED">
+ <description>0 - not initialized.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="INITIALIZED">
+ <description>1 - initialized.</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="NodeBehaviourType">
+ <description>The nodeBehaviorType attribute represents the MTP3b node type.</description>
+ <enumMember name="SEP">
+ <description>Signaling End Point.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="SEP_STP">
+ <description>Signalling Transfer and End Point, i.e the signalling point is of both type Signalling End Point (SEP) and Signalling Transfer Point (STP).</description>
+ <value>4</value>
+ </enumMember>
+ <enumMember name="SGW_STP_SEP">
+ <description>Signaling GateWay, Signaling End Point and Signalling Transfer Point, i.e the signalling point is of both type Signalling Transfer Point (STP), Signaling End Point (SEP) and Signaling GateWay (SGW).</description>
+ <value>5</value>
+ </enumMember>
+ </enum>
+
+ <struct name="Mtp3bSpChinaPriorityData">
+ <description>Priority attributes for MTP3b SP of the China standard.</description>
+ <structMember name="prioSlt">
+ <description>The prioSlt attribute sets the priority for the
+ Signalling Link Test Message and Acknowledge (SLTM / SLTA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioCo">
+ <description>The prioCo attribute sets the priority for the ChangeOver Order and Acknowledge (COO/COA) or eXtended Change over Order and Acknowledge (XCO/XCA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet)
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioCb">
+ <description>The prioCb attribute sets the priority for the
+ Change Back Declaration and Acknowledge (CBD / CBA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioEc">
+ <description>The prioEc attribute sets the priority for the
+Emergency Change over Order and Acknowledge (ECO / ECA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioRst">
+ <description>The prioRst attribute sets the priority for the
+signalling Route Set Test (RST) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioTra">
+ <description>The prioTra attribute sets the priority for the
+Traffic Restart Allowed signal (TRA) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioUpu">
+ <description>The prioUpu attribute sets the priority for the
+ User Part Unavailable (UPU) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioLink">
+ <description>The prioLink attribute sets the priority for link related messages when issued by the MTP3b itself. The messages are :
+
+Link INhibit (LIN), Link UNinhibit (LUN),
+Link Inhibit Denied (LID),
+Link Inhibit Acknowledge (LIA),
+Link Uninhibit Acknowledge (LUA),
+Link Forced Uninhibit (LFU),
+Link Local inhibit Test (LLT) and
+Link Remote inhibit Test (LRT)
+
+When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ </struct>
+
+ <enum name="Mtp3bRouteType">
+ <description>The type of Signalling Route.</description>
+ <enumMember name="TDM_ATM">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="IP">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="HomingState">
+ <enumMember name="SINGLE_HOMED_1">
+ <description>Single-homed with ipAddress1.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="SINGLE_HOMED_2">
+ <description>Single-homed with ipAddress2.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="MULTI_HOMED">
+ <description>Multihomed association with ipAddress1 and
+ipAddress2
+</description>
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <enum name="RouteState">
+ <description>The state of the signaling route.</description>
+ <enumMember name="NOT_BLOCKED">
+ <description>The signaling route is not blocked.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="BLOCKED">
+ <description>The signaling route is blocked.</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="WorkingMode">
+ <enumMember name="hostMode">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="routerMode">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="OspfMetricType">
+ <description>Open Shortest Path First metric type.</description>
+ <enumMember name="comparableCost">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="nonComparable">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="RouteType">
+ <description>The types of the routes found in the IP routing table.</description>
+ <enumMember name="INET_RTPROTO_OTHER">
+ <description>The source of information is unknown.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="INET_RTPROTO_LOCAL">
+ <description>Route created from local configuration data (both static and interface routes).
+Each interface created gets an entry in the routing table of the RO.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="INET_RTPROTO_NETMGMT">
+ <description>Route added by SNMP.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="INET_RTPROTO_OSPF">
+ <description>Route added by OSPF.</description>
+ <value>13</value>
+ </enumMember>
+ <enumMember name="INET_RTPROTR_ICMP">
+ <description>Route added by ICMP redirect message.</description>
+ <value>4</value>
+ </enumMember>
+ </enum>
+
+ <exception name="RouteNotFoundException">
+ <description>Invalid IP route has been given as a parameter to an action.</description>
+ <exceptionParameter name="routeNotFound">
+ <description>Exception message.</description>
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="InvalidRouteException">
+ <description>Invalid IP route has been given as a parameter to an action.</description>
+ <exceptionParameter name="invalidRoute">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <enum name="MauDuplexMode">
+ <enumMember name="HALF_DUPLEX">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="FULL_DUPLEX">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="ControllerMode">
+ <description>The controller mode of a physical interface.</description>
+ <enumMember name="CONTROLLER_E1">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="CONTROLLER_T1">
+ <value>2</value>
+ </enumMember>
+ <enumMember name="CONTROLLER_J1">
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <struct name="OspfAreaRange">
+ <description>ipAddress - the subnet address of the range.
+subnetMask - IP subnet mask of the range to be added.
+advertise - indicates whether the area range should be advertised into OSPF.
+</description>
+ <structMember name="ipAddress">
+ <string/>
+ </structMember>
+ <structMember name="subnetMask">
+ <description>Note! The subnet has to be contigious. That is, has the LSB set to 0 (zero).
+
+Example:
+
+255.255.255.X
+
+Contiguous subnet mask:
+11111111.11111111.11111111.11111110 (X = 254)
+11111111.11111111.11111111.11111100 (X = 252)
+
+Not-contiguous subnet mask:
+11111111.11111111.11111111.11111010 (X = 250)
+</description>
+ <string/>
+ </structMember>
+ <structMember name="advertise">
+ <boolean/>
+ </structMember>
+ </struct>
+
+ <struct name="RoutingTableEntry">
+ <description>IP routing table entry.</description>
+ <structMember name="destinationIpAddr">
+ <description>The destination IP address.</description>
+ <string/>
+ </structMember>
+ <structMember name="destinationNetworkMask">
+ <description>The destination IP network mask.</description>
+ <string/>
+ </structMember>
+ <structMember name="nextHopIpAddr">
+ <description>The next hop IP address.</description>
+ <string/>
+ </structMember>
+ <structMember name="routeMetric">
+ <description>The route metric.</description>
+ <long/>
+ </structMember>
+ <structMember name="routeType">
+ <description>The route type.</description>
+ <enumRef name="RouteType">
+ </enumRef>
+ </structMember>
+ <structMember name="interfaceName">
+ <description>The interface name.</description>
+ <string/>
+ </structMember>
+ <structMember name="redistribute">
+ <description>Indicates if the route should be redistributed.</description>
+ <boolean/>
+ </structMember>
+ <structMember name="active">
+ <description>Indicates if the route is active.</description>
+ <boolean/>
+ </structMember>
+ </struct>
+
+ <enum name="AutoConfigurationMode">
+ <description>Denotes whether the autoConfiguration mode for the IpAccessHost is turned on or off.</description>
+ <enumMember name="ON">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="OFF">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="Aal5TpSelectionModes">
+ <description>In case 'NO_PREFERENCE', 'LOCAL_MP_SELECT_VCC_AT_LINK_UP', LOCAL_MP_PEER_SELECTION_VCC' or 'LOCAL_MP_ACTIVE_RESELECTION' is selected the IpAtmLink MO will prefer Aal5TpVccTp on local MP (i.e. Aal5TpVccTp executing on the same MP as the IpAtmLink), but other Aal5TpVccTp will be accepted if needed.
+
+In case 'ONLY_LOCAL_MP' is selected, the ipAtmLink (Inet Link) will consider Aal5TpVccTp residing on other MPs as a malfunction and discard the usage of them. No InvArp sending will be performed on them and all incomming trafic on them will be discarded. If no local Aal5TpVccTp exists the operational state of the link will be changed to disabled.</description>
+ <enumMember name="NO_PREFERENCE">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="LOCAL_MP_SELECT_VCC_AT_LINK_UP">
+ <description>Prefer termination on local MP, select Vcc when link goes up.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="LOCAL_MP_PEER_SELECTION_VCC">
+ <description>Prefer termination on local MP, follow peer selection of Vcc.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="LOCAL_MP_ACTIVE_RESELECTION">
+ <description>Prefer termination on local MP, active reselection to new Aal5TpVccTp as soon as a better choice exists.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="ONLY_LOCAL_MP">
+ <description>Restricted to local MP, follow peer selection if termination is on local MP.
+</description>
+ <value>4</value>
+ </enumMember>
+ </enum>
+
+ <enum name="AlarmReport">
+ <description>Alarm report for the Virtual path connection termination point.
+RDI - Remote defect indication
+LOC - Loss of continuity
+AIS - Alarm indication signal</description>
+ <enumMember name="ALARM_LOC">
+ <description>For alarms of type Loss of continuity.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="ALARM_LOC_RDI">
+ <description>For alarms of type Loss of continuity and Remote defect indication.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="ALARM_AIS_LOC">
+ <description>For alarms of type Alarm indication signal and Loss of continuity.</description>
+ <value>6</value>
+ </enumMember>
+ <enumMember name="ALARM_AIS_RDI_LOC">
+ <description>For alarms of type Alarm indication signal, Remote defect indication and Loss of continuity.</description>
+ <value>7</value>
+ </enumMember>
+ </enum>
+
+ <enum name="AtmCounterMode">
+ <enumMember name="PM_MODE_OFF">
+ <description>Performance monitoring is turned off. PM counters give irrelevant values.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="PM_MODE_ONLYCOUNT">
+ <description>Performance monitoring counters are active
+</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="PM_MODE_FPM">
+ <description>FPM, Forward Performance Monitoring activated.
+
+Performance monitoring counters are active
+</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="PM_MODE_BR">
+ <description>Backward reporting, BR, cells are generated.
+
+Performance monitoring counters are active
+</description>
+ <value>4</value>
+ </enumMember>
+ <enumMember name="PM_MODE_FPM_BR">
+ <description>FPM, Forward Performance Monitoring activated.
+
+Backward reporting, BR, cells are generated.
+
+Performance monitoring counters are active
+</description>
+ <value>6</value>
+ </enumMember>
+ </enum>
+
+ <enum name="AtmNomPmBlkSize">
+ <description>Nominal performance monitoring, PM, blocksize. The minimum number of ATM cells to send before sending a Forward Performance Monitoring, FPM, cell.</description>
+ <enumMember name="NOM_PM_BLKSIZE_2_7">
+ <description>Nominal performance monitoring, PM, block size, 2e7 (2 to the power of 7).</description>
+ <value>128</value>
+ </enumMember>
+ <enumMember name="NOM_PM_BLKSIZE_2_8">
+ <description>Nominal performance monitoring, PM, block size, 2e8 (2 to the power of 8).</description>
+ <value>256</value>
+ </enumMember>
+ <enumMember name="NOM_PM_BLKSIZE_2_9">
+ <description>Nominal performance monitoring, PM, block size, 2e9 (2 to the power of 9).</description>
+ <value>512</value>
+ </enumMember>
+ <enumMember name="NOM_PM_BLKSIZE_2_10">
+ <description>Nominal performance monitoring, PM, block size, 2e10 (2 to the power of 10).</description>
+ <value>1024</value>
+ </enumMember>
+ <enumMember name="NOM_PM_BLKSIZE_2_11">
+ <description>Nominal performance monitoring, PM, block size, 2e11 (2 to the power of 11).</description>
+ <value>2048</value>
+ </enumMember>
+ <enumMember name="NOM_PM_BLKSIZE_2_12">
+ <description>Nominal performance monitoring, PM, block size, 2e12 (2 to the power of 12).</description>
+ <value>4096</value>
+ </enumMember>
+ <enumMember name="NOM_PM_BLKSIZE_2_13">
+ <description>Nominal performance monitoring, PM, block size, 2e13 (2 to the power of 13).</description>
+ <value>8192</value>
+ </enumMember>
+ <enumMember name="NOM_PM_BLKSIZE_2_14">
+ <description>Nominal performance monitoring, PM, block size, 2e14 (2 to the power of 14).</description>
+ <value>16384</value>
+ </enumMember>
+ <enumMember name="NOM_PM_BLKSIZE_2_15">
+ <description>Nominal performance monitoring, PM, block size, 2e15 (2 to the power of 15).</description>
+ <value>32768</value>
+ </enumMember>
+ </enum>
+
+ <enum name="ServiceCategory">
+ <enumMember name="SERVICE_CATEGORY_CBR">
+ <description>Service category Constant Bit rate, CBR.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="SERVICE_CATEGORY_UBR">
+ <description>Service category Unspecified Bit rate, UBR.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="SERVICE_CATEGORY_UBR_PLUS">
+ <description>Service category Unspecified Bit rate+, UBR+. UBR+ guarantees a certain bandwidth. If higher bandwidth is used it will be handled as UBR.</description>
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <enum name="AtmQos">
+ <description>ATM's Quality of Service classes.
+
+The ATM layer system provides four QoS classes, numbered 1 to 4, where CLASS_ONE gives the best QoS in regards to Cell Loss Ratio &lt;CLR&gt; and Cell Delay Variation &lt;CDV&gt; and CLASS_FOUR doesn't give any QoS guarantees. CLASS_ONE and CLASS_TWO are the only classes applicable for real time traffic.</description>
+ <enumMember name="CLASS_ONE">
+ <description>CDV &lt; 1 ms (milliseconds), CLR &lt; 10e-8. Typically used by timing unit.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="CLASS_TWO">
+ <description>CDV &lt; 1 ms, CLR &lt; 10e-7. Typically used for speech.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="CLASS_THREE">
+ <description>CLR &lt; 10e-5. Typically used for signalling.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="CLASS_FOUR">
+ <description>Typically used for IP.</description>
+ <value>4</value>
+ </enumMember>
+ </enum>
+
+ <struct name="ValueOfUnex">
+ <description>The attributes in this struct represents the ATM header, (vpi, vci, pti), of the last recieved unexpected cell.</description>
+ <structMember name="vpi">
+ <description>The ATM header vpi.</description>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="vci">
+ <description>The ATM header vci.</description>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="pti">
+ <description>The ATM header pti.</description>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <class name="TransportNetwork">
+ <description>This MO structures the transport network of the managed element. It is created automatically and cannot be deleted.
+
+The local distinguished name of this MO is ManagedElement=1, TransportNetwork=1.</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="TransportNetworkId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="getAal5ForNniSaal">
+ <description>This action returns a sequnce of Aal5TpVccTp MOs that is unreserved and executes on an MP.
+
+Also the following condition has to be fullfilled:
+
+MinAal5Sdu = min (fromUserMaxSduSize, toUserMaxSduSize)
+
+roundedDownSdu = (MinAal5Sdu - (MinAal5Sdu modulo 4) +4)
+
+roundedDownSdu &gt; low boundry for maxSduSize (in NniSaalTp)
+
+Note that the values for fromUserMaxSduSize and toUserMaxSduSize is the actual values set in the Aal5TpVccTp MO.
+Also note that the attributes minAal5Sdu and roundedDownSdu is used internaly in this action.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </returnType>
+ </action>
+ <action name="getAal5ForUniSaal">
+ <description>This action returns a sequnce of Aal5TpVccTp MOs that is unreserved and executes on an MP.
+
+Also the following condition has to be fullfilled:
+
+MinAal5Sdu = min (fromUserMaxSduSize, toUserMaxSduSize)
+
+roundedDownSdu = (MinAal5Sdu - (MinAal5Sdu modulo 4) +4)
+
+roundedDownSdu &gt; low boundry for maxSduSize (in UniSaalTp)
+
+Note that the values for fromUserMaxSduSize and toUserMaxSduSize is the actual values set in the Aal5TpVccTp MO.
+Also note that the attributes minAal5Sdu and roundedDownSdu is used internaly in this action.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </returnType>
+ </action>
+ <action name="getAal2PathForAal2Pdu">
+ <description>This action returns a sequence of all unreserved Aal2PathVccTp's that have an Aal2PathId that has not been
+used by another Aal2PathDistributionUnit under the same parent (Aal2Ap).
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </returnType>
+ <parameter name="aal2Ap">
+ <in/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="getRpuForAal2Pdu">
+ <description>This action returns a sequence of all ReliableProgramUniters that has not reached the maximun number of possible reservations
+and has not already been used by other Aal2PathDistributionUnit MO's (if exists) under the same parent (Aal2Ap MO).
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </returnType>
+ <parameter name="aal2Ap">
+ <in/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="getUnreservedPluginUnits">
+ <description>This action returns a sequence of PlugInUnits that is unreserved.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </returnType>
+ </action>
+ <action name="getDs0BundlesForMtp2">
+ <description>This action returns a sequence of Ds0Bundle MOs that is unreserved and only has one (1) timeSlot set in the listOfTimeSlots.
+The attribute tdmMode in these Ds0Bundles must be enabled.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="Slot">
+ <description>The Slot MO is used to represent a slot in a subrack. A slot can hold a plug-in-unit, a board, (represented by PlugInUnit MOs).
+
+The number of slots in a subrack is specified when defining the subrack.
+
+The system will automatically create the right number of Slot MOs in the subrack at creation of the Subrack MO.
+This MO cannot be deleted by an operator.
+
+The local distinguished names of this MO's are select with identity Slot=1 in the leftmost slot with incremental numbering towards the right in the subrack.. </description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>A user friendly name associated to the managed object
+
+</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="slotState">
+ <description>Gives the state of the slot.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="SlotState">
+ <defaultValue>free</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="slotNumber">
+ <description>The number of the position from the left side, starting from 1.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long/>
+ </dataType>
+ </attribute>
+ <attribute name="SlotId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="productData">
+ <description>This product data describes the plug-in-unit that is presently inserted. The information is only available when slotState = used.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <structRef name="OperProductData"/>
+ </dataType>
+ </attribute>
+ <attribute name="upgradeGroupId">
+ <description>The upgradeGroupId is able to group a number of PIUs, all in the group can be upgraded at the same time.
+
+If upgradeGroupTypeName is "", this attribute is not used.
+</description>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="upgradeGroupTypeName">
+ <description>The upgradeGroupTypeName, together with the upgradeGroupId, define an upgrade group.
+</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="ManagedObject">
+ <description>The Managed Object MO is not part of the model. It is only used to have valid reference types for certain attributes. </description>
+ <attribute name="ManagedObjectId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="getType">
+ <returnType>
+ <string/>
+ </returnType>
+ </action>
+ <action name="getId">
+ <returnType>
+ <string/>
+ </returnType>
+ </action>
+ <action name="getParent">
+ <returnType>
+ <moRef name="ManagedObject"/>
+ </returnType>
+ </action>
+ <action name="getChildren">
+ <returnType>
+ <long/>
+ </returnType>
+ </action>
+ <action name="getFullDistinguishedName">
+ <returnType>
+ <string/>
+ </returnType>
+ </action>
+ <action name="delete">
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="MoHasChildrenException"/>
+ <raisesException name="MoReservedByOtherUserException"/>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ <raisesException name="UndeletableMoException"/>
+ <raisesException name="TransactionRequiredException"/>
+ </action>
+ <action name="getLocalDistinguishedName">
+ <returnType>
+ <string/>
+ </returnType>
+ </action>
+ <action name="create">
+ <returnType>
+ <moRef name="ManagedObject"/>
+ </returnType>
+ <raisesException name="MoNameAlreadyTakenException"/>
+ <raisesException name="AttrMissingAtCreateException"/>
+ <raisesException name="AttrNotSettableAtCreateException"/>
+ <raisesException name="IllegalParentException"/>
+ <raisesException name="MoCardinalityViolationException"/>
+ <raisesException name="NoSuchAttributeException"/>
+ <raisesException name="MoCanNotBeCreatedException"/>
+ <raisesException name="NoSuchFieldException"/>
+ <raisesException name="NotHandledAttributeTypeException"/>
+ <raisesException name="WrongAttributeTypeException"/>
+ <raisesException name="ValueOutOfRangeException"/>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ <raisesException name="TransactionRequiredException"/>
+ <raisesException name="IpException"/>
+ <raisesException name="IpFormatException"/>
+ <raisesException name="EquipException"/>
+ <raisesException name="AttrValueNotUniqueException"/>
+ <raisesException name="MaxNumberExceededException"/>
+ <raisesException name="MoReservedNotDeletableException"/>
+ </action>
+ </class>
+
+ <class name="VclTp">
+ <description>This MO is used to represent the termination of an external VC link in the node.
+
+Note that a maximum of 10 000 MO of this kind may be configured in a node.
+
+Note! The performance monitoring counters in the VclTp MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.</description>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="externalVci">
+ <description>Virtual Channel Idenitifier, VCI, value for this Virtual Channel Link, VCL.
+
+Range: 32 - 65535.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>32</min> <max>65535</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="atmTrafficDescriptorId">
+ <description>Reference to the AtmTrafficDescriptor profile.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="AtmTrafficDescriptor"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>User that have reserved this VclTp.
+
+</description>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the VclTp.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmReceivedAtmCells">
+ <description>Performance monitoring counter for number of received ATM cells.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmTransmittedAtmCells">
+ <description>Performance monitoring counter for number of transmitted ATM cells.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status of the VclTp.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="VclTpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="eteLoopBack">
+ <description>Used by VclTp to inforce a Virtual Channel end-to-end loopback.
+false=Failed, true=Succeded.
+
+Note! This action requires a transaction.
+
+</description>
+ <returnType>
+ <boolean/>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="ManagedElement">
+ <description>The Managed Element MO is the top MO in the MOM. A management application will communicate with the Managed Element MO for the purpose of monitoring it and controlling it.
+
+The ManagedElement MO is automatically created and cannot be deleted.
+
+The local distinguished name of this MO is ManagedElement=1.</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="site">
+ <description>This attribute gives information about geographical location (e.g. place name).</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>255</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="logicalName">
+ <description>This attribute gives a logical name of a site.
+
+</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>255</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="productType">
+ <description>This attribute describes the product type and is always set to the value "Node".</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>Node</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="productName">
+ <description>This attribute describes the implemented functionality. </description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>12</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="productNumber">
+ <description>This attribute uniquely identifies the product (e.g. ROF123).</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>24</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="productRevision">
+ <description>This attribute identifies the version of the product (e.g. R2A).</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>7</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ManagedElementId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="restart">
+ <description>Restart the node with an unconditional reload.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="restartRank">
+ <in/>
+ <dataType>
+ <enumRef name="RestartRank">
+ </enumRef>
+ </dataType>
+ </parameter>
+ </action>
+ </class>
+
+ <class name="Equipment">
+ <description>This Managed Object is used as a structural element for the network element, i.e. it only acts as a container for other MO:s. This MO structures the equipment of the network element.
+
+The local distinguished name of this MO is ManagedElement=1, Equipment=1.</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="EquipmentId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Subrack">
+ <description>This MO is used to represent a subrack.
+</description>
+ <attribute name="userLabel">
+ <description>A free tag that a user can associated to the this managed object. The value has no relevance for the managed system.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="switchModule">
+ <description>A reference to a SwitchModule ManagedObject, from which the SwitchModule number can be retrived. That number describes how the subrack is connected to the node, i.e. how the subracks cables are connected to the hub subrack. (The hub subrack has switch module number 0).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="SwitchModule"/>
+ </dataType>
+ </attribute>
+ <attribute name="subrackType">
+ <description>There can only be one hub subrack in the node. The hub subrack is used to control switching and synchronization for the complete node.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="SubrackType">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="productType">
+ <description>This attribute describes the product type and is always set to the value "HW".</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>"HW"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeProductData">
+ <description>This product data describes the subrack that is configured to be installed.
+
+</description>
+ <mandatory/>
+ <dataType>
+ <structRef name="AdminProductData"/>
+ </dataType>
+ </attribute>
+ <attribute name="subrackPosition">
+ <description>The position of this subrack within a cabinet.
+The purpose of this attribute is to help an operator locate the source of an error by letting the system put this
+information in alarms. The system does not use this information in any other way i.e. it does not affect the
+operation of the system.
+The subrack position is an integer (1-n) stating the cabinet Id, starting from the left and a letter (A-Z) stating
+the Subrack vertical position starting from the ground, e.g. 5C.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="cabinetPosition">
+ <description>The position of the cabinet (within a group of other cabinets) in which this subrack is placed.
+The purpose of this attribute is to help an operator locate the source of an error by letting the system put this information in alarms. The system does not use this information in any other way i.e. it does not affect the operation of the system.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="SubrackId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="numberOfSlots">
+ <description>Defines the number of slot in the subrack. The default value is 28.
+
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>28</max>
+ </range>
+ <defaultValue>28</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="operationalProductData">
+ <description>The operational product data describes the subrack that is actually installed.
+
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <structRef name="OperProductData"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>A reference to the SwAllocation MO that has reserved this Subrack for Fan MO upgrades..
+The attribute is set/cleared by internal actions.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <action name="removeSlots">
+ <description>Removes the given number of Slot MOs from the model. The Slots with the highest slotNumber are removed. After the action no Slot will have apn = 0.
+The attribute numberOfSlots will be udated.
+
+If there is a child MO the action will fail and the MOHasChildrenException is thrown.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="numberOfSlotsToRemove">
+ <description>The number of slots to remove.</description>
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ </action>
+ </class>
+
+ <class name="LoadModule">
+ <description>This MO is used to represent software installed in the file system.
+
+LoadModule MO can represent files with executable code, files with text information
+(COI) or directories in Cello file system.
+
+MOs of this type are created automatically during system upgrade.
+MOs of this type are possible to create manually but a system upgrade
+is recommended to create them.
+
+Note! In order for a program to be reliable the following conditions must be fulfilled:
+
+1. The attribute 'loaderType' must be set to 'OseLoader'.
+2. The attribute 'oseProgramLoadClass' must be set to a value &gt; 100.
+3. The program must execute on a MP (Main Processor).
+
+</description>
+ <attribute name="userLabel">
+ <description>Free tag for marking this managed object.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="productData">
+ <description>Product information data.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="AdminProductData"/>
+ </dataType>
+ </attribute>
+ <attribute name="loadModuleFilePath">
+ <description>The path to this load module in the file system, including the file name.
+
+Example: /c/load_modules/CXC112874R1A01
+where /c/load_modules/ is the directory and CXC112874R1A01 is the file name.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="loaderType">
+ <description>The type of the program loader.
+
+Note! This corresponds to LoaderName in the Upgrade Control File (UCF).</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="LoadModuleLoaderType">
+ <defaultValue>OseLoader</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="otherLoaderName">
+ <description>This attribute must have a value if the loaderType attribute equals other.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="preLoad">
+ <description>A recommendation to the system to (if possible) cache this load module close to where its program(s) execute(s), e.g. in a flash file system. The purpose of this attribute is to enable faster loading at restart of programs referring to this load module.
+
+
+
+
+</description>
+ <dataType>
+ <enumRef name="LoadModulePreLoadType">
+ <defaultValue>no</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="fileFormat">
+ <description>The file format (RPDOUT, html, java, fpga, ...).</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="oseProgramLoadClass">
+ <description>Specifies in which load phase programs of this load module should be started.
+
+Note: If the LoadModule is a java archive file (.jar) it will be loaded in the load phase of the java machine rather than according to its own oseProgramLoadClass.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="LoadClass">
+ <defaultValue>application</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reliableProgramLabel">
+ <description>Reliable program identity.
+Compare this to the reliableProgramLabel in ReliableProgramUniter MO.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="isDirectory">
+ <description>Indicates if the load module is a file or directory.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="oseProgramPoolSize">
+ <description>This attribute sets the size of the program pool size. In the referenced loadModule there is
+possible to set this value at create.
+This value will then be fetched by program and used at create if no value is submitted at
+create of the program Mo.
+The referenced load module has a default size defined at compile time which is used if no
+value is submitted at create of loadModule or the program Mo.
+
+Note! The value of this attribute is overwritten during Software Upgrade.
+
+Unit is byte.
+
+</description>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="oseProgramHeapSize">
+ <description>This attribute sets the size of the program heap size. In the referenced loadModule there is possible to set this value at create. This value will then be fetched by program and used at create if no value is submitted at create of the program Mo.
+The referenced load module has a default size defined at compile time which is used if no value is submitted at create of loadModule or the program Mo.
+
+Note! The value of this attribute is overwritten during Software Upgrade.
+
+Unit is byte.
+
+</description>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="programMustBeSingleton">
+ <description>Indicator whether the (OSE) program must be a singleton or not.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="moppletEntries">
+ <description>Contains all class that are to be initialised and started when the JVM restarts.
+Technical note: The class name must specify the full package and class name in standard Java syntax, e.g. "se.ericsson.cello.X" ; must implement the se.ericsson.cello.moframework.Mopplet interface and be found in this LoadModule.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <sequence>
+ <string>
+ <defaultValue/>
+ </string>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="LoadModuleId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByUpgradePackage">
+ <description>Indicates whether this MO has been reserved by the UpgradePackage MO or not.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Synchronization">
+ <description>This MO is used to administer synchronization references for the network synchronization function and to view the system clock state of Timing Unit boards.
+
+Synchronization can have 0 to 8 relations to other MOs. The only valid MOs where relations can exist are E1Physpathterm, J1Physpathterm, T1Physpathterm, Os155SpiTtp, TU Synchronization Reference, and ManagedObject (for the non-Cello RXI820 MO) MOs. Note that maximum number of relations to these MOs is 8 all together.
+
+The synchronization MO is automatically created and cannot be deleted.
+
+Note: An external ManagedObject that wishes to be connected to the Synchronization MO must implement the following interface se.ericsson.cello.equipment.SyncReservable!
+
+The local distinguished name of this MO is ManagedElement=1,TransportNetwork=1,Synchronization=1
+
+.</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="degradationIsFault">
+ <description>Controls whether synchronization reference degradation (e.g. signal level degradation) is interpreted as a synchronization reference fault or not. Attribute value is only applicable for traffic carrying synchronization references</description>
+ <dataType>
+ <enumRef name="FaultCriteria">
+ <defaultValue>degrNotFault</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="systemClockA">
+ <description>State of system clock signal on Timing Unit A.
+Note that system clock generated by TU A (TU in slot 4) has higher priority than TU B (TU in slot 5) system clock, i.e. each device board uses system clocks according to this priority order.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="ClockState">
+ <defaultValue>unknownMode</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="systemClockB">
+ <description>State of system clock signal on Timing Unit B. Note that system clock generated by TU A (TU in slot 4) has higher priority than TU B (TU in slot 5) system clock, i.e. each device board uses system clocks according to this priority order.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="ClockState">
+ <defaultValue>unknownMode</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="syncReference">
+ <description>Set of synchronization reference physical resources. An MO reference to an TU synchronization reference MO implementation.
+A synchronization reference in added to the system by using action AddSyncRefResource.
+Note: if this attributes has value "Non-existing MO reference" then all the respective attributes of type sequence of 8 are not applicable.
+
+Note: The length of this sequence is always 8.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ <length>8</length>
+ <nonUnique/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="syncRefPriority">
+ <description>Synchronization reference priority.
+1 represents the highest and 8 the lowest priority. Every synchronization reference must have unique priority value. Value 0 means not applicable, that no synchronization with this priority is defined.
+This attribute is mandatory when adding a synchronization reference to the system (by using action addSyncRefResource).
+A priority value can be changed with the changeSyncRefPriority action provided that the priority is not already assigned to some other SyncRefResource.
+
+Note: The length of this sequence is always 8.</description>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <long>
+ <range>
+ <min>0</min> <max>8</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ <length>8</length>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="syncRefActivity">
+ <description>Set of synchronization reference activity attributes.
+
+Note: The length of this sequence is always 8.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <enumRef name="RefActivity">
+ <defaultValue>inactive</defaultValue>
+ </enumRef>
+ <length>8</length>
+ <nonUnique/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="syncRefStatus">
+ <description>Set of synchronization reference status attributes.
+
+Note: The length of this sequence is always 8.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <enumRef name="RefState">
+ <defaultValue>failed</defaultValue>
+ </enumRef>
+ <length>8</length>
+ <nonUnique/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="SynchronizationId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="systemClockRedundancy">
+ <description>Indicates if the node is redundant from Network Synchronization functions point of view.</description>
+ <dataType>
+ <enumRef name="SystemClockRedundancy">
+ <defaultValue>SYSTEM_CLOCK_USERS_USE_PLANE_A</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <action name="addSyncRefResource">
+ <description>This action adds one synchronization reference to the system. As a result of successful action, one set of attributes (attributes of type sequence of 8) is added to Synchronization MO.
+Parameters:
+syncReference: Managed object implementation, to which a mo-reference is to be added. See description of attribute SyncReference.
+syncPriority: Priority of synchronization reference. Each synchronization reference must have unique priority value, this must be checked by synchronization MO.
+
+Description of exceptions:
+- AlreadyRegistered: this reference is already registered
+- MaxNoOfRefRegistered: maximum number (8) of synchronization references already present
+- PriorityAlreadyInUse: syncPriority is identical with an existing synchronization reference priority
+- PriorityOutOfRange: invalid syncPriority value
+- InvalidMoReference: invalid syncReference for registration as a synchronization reference (invalid MO type)
+- NotPermitted: syncReference does not allow SyncReserve to be performed
+
+Note: An external ManagedObject that wishes to be connected to the Synchronization MO must implement the following interface se.ericsson.cello.equipment.SyncReservable!
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="syncReference">
+ <in/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </parameter>
+ <parameter name="syncPriority">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="AlreadyRegisteredException"/>
+ <raisesException name="MaxNoOfRefRegisteredException"/>
+ <raisesException name="PriorityAlreadyInUseException"/>
+ <raisesException name="PriorityOutOfRangeException"/>
+ <raisesException name="InvalidMoReferenceException"/>
+ <raisesException name="NotPermittedException"/>
+ </action>
+ <action name="removeSyncRefResource">
+ <description>This action removes one synchronization reference that has previously been added.
+(In future releases, this action should include a check whether the synchronization reference to be removed is the only existing synchronization reference. In that case, the user is asked for a confirmation to remove the last synchronization reference.)
+Parameters:
+syncReference: Managed object implementation, to which a mo-reference currently exists, but is now to be removed. See description of attribute SyncReference.
+
+Description of exceptions:
+- NotRegistered: synchronization reference is not registered
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="syncReference">
+ <in/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </parameter>
+ <raisesException name="NotRegisteredException"/>
+ </action>
+ <action name="changeSyncRefPriority">
+ <description>This action changes the synchronization priority of one previously registered synchronization reference resource.
+Parameters:
+syncReference: Managed object implementation, for which the synchronization priority is to be changed. See description of attribute syncReference.
+syncPriority: The new priority of synchronization reference. Each synchronization reference must have unique priority value, this must be checked by synchronization MO.
+
+Description of exceptions:
+- PriorityAlreadyInUse: syncPriority is identical with an existing synchronization reference priority
+- PriorityOutOfRange: invalid syncPriority value
+- NotRegistered: synchronization reference is not registered
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="syncReference">
+ <in/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </parameter>
+ <parameter name="syncPriority">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="PriorityAlreadyInUseException"/>
+ <raisesException name="PriorityOutOfRangeException"/>
+ <raisesException name="NotRegisteredException"/>
+ </action>
+ <action name="resetLossOfTracking">
+ <description>This action resets the detected Loss of Tracking error condition of one synchronization reference. After reset the synchronization reference is usable again.
+Parameters:
+syncReference: Specifies the synchronization reference for which the Loss of Tracking status is to be reset.
+
+Description of exceptions:
+- NotRegistered: synchronization reference is not registered
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="syncReference">
+ <in/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </parameter>
+ <raisesException name="NotRegisteredException"/>
+ </action>
+ </class>
+
+ <class name="SccpApLocal">
+ <description>This Managed Object represents an SCCP Local Access Point. An SCCP AP instance is a logical point in the SCCP network at which an SCCP user can access the services provided by the SCCP and the SCCP can deliver its services to the SCCP user. The SCCP Access Point is identified by a SubSystem Number (SSN).
+
+A local SccpAp represents an access point in the own node.
+
+The performance monitoring counters found in SccpApLocal MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is a shutdown request from the CLI (Cluster Interface).</description>
+ <attribute name="SccpApLocalId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the SCCP AP. The operability of the SCCP AP is described by this attribute which has two possible values:
+
+Disabled: The SCCP AP is totally inoperable and unable to provide the service to the user.
+
+Enabled: The SCCP AP is partly or fully operable and available for use.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="ssN">
+ <description>The sub system number, SSN, of the SCCP Access Point. Note that this has to be a unique number.
+
+If the SccpAp is local then the SSN has to be unique among all other SccpAp MOs under the same SccpSp MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>2</min> <max>255</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxConn">
+ <description>The maxConn attribute specifies the max number of connections allowed for this SCCP Access Point. It is only valid for local SCCP Access Points.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>524288</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="useS1">
+ <description>Controls adding of OPC from routing label to Calling Party Address if absent.
+
+False = Do not add OPC to Calling Part Address.
+True = Add OPC to Calling Part Address.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="SccpSp">
+ <description>The Signalling Connection Control Part, SCCP, Signalling Point, SP, MO is the placeholder for all SCCP related managed objects.
+
+Startime for accounting is set by attributes accountDateFileOutput and accountTimeFileOutput.
+The attribute accountPeriodFileOutput sets period for the accounting record to be stored on the /c file system.
+The accounting is stopped by setting the accountPeriodFileOutput to zero (0).
+NOTE: The SRP function and SccpAccountingCriteria MO's should only be created for one signalling stack, i.e one PIU.
+
+Note! The guiding values that can be found for some attributes is to be regarded as a recommendation for these attributes.
+Depending on the size of the network, traffic load, use and so forth it might be neccesary to set values for these attributes outside the guiding values.</description>
+ <attribute name="SccpSpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the SCCP SP. The operability of the SCCP SP is described by this attribute which has two possible values:
+
+Disabled: The SCCP SP is totally inoperable and unable to provide the service to the user (e.g. if the processor is not usable).
+
+Enabled: The SCCP SP is partly or fully operable and available for use.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="mtp3bSpId">
+ <description>The identity of the L3 Signaling Point used by this MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="prioSST">
+ <description>This attribute sets the priority for the Subsystem Test message when issued by the SCCP itself. When a message is transferred from the SCCP the message priority uses the two spare bits in the SIO.
+Coding of the message priority:
+0 Lowest priority
+1
+2
+3 Highest priority</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>3</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="prioIT">
+ <description>This attribute sets the priority for the Inactivity Test message when issued by the SCCP itself. When a message is transferred from the SCCP the message priority uses the two spare bits in the SIO.
+Coding of the message priority:
+0 Lowest priority
+1
+2
+3 Highest priority</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>3</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="prioRLSD">
+ <description>This attribute sets the priority for the connection release message when issued by the SCCP itself. When a message is transferred from the SCCP the message priority uses the two spare bits in the SIO.
+Coding of the message priority:
+0 Lowest priority
+1
+2
+3 Highest priority</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>3</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="prioGeneral">
+ <description>This attribute sets the priority for all the other messages which are issued by the SCCP itself. When a message is transferred from the SCCP the message priority uses the two spare bits in the SIO.
+
+Coding of the message priority:
+
+0 Lowest priority
+1
+2
+3 Highest priority</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>3</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="accountDateFileOutput">
+ <description>Date for accounting file output.
+Format in ASCI-code: yyyymmdd
+yyyy = 0000-9999
+mm = 01-12
+dd = 01-31
+
+Note! This is the start date for the output.</description>
+ <dataType>
+ <string>
+ <defaultValue>"00000000"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="accountTimeFileOutput">
+ <description>Time for accounting file output.
+Format in ASCI-code: hhmm
+hh = 00-23
+mm = 00-59</description>
+ <dataType>
+ <string>
+ <defaultValue>"0000"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="accountPeriodFileOutput">
+ <description>Period for accounting file output.
+Format: number of half hour.
+Range = 0, 1, 2, 4, 6, 8, 12, 16, 24, 48
+
+Note! if set to 0 (zero) the output will be stopped.</description>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="upperConnThres">
+ <description>The upper connection threshold allow the user to specify the level at which the upper connection threshold notification is triggered. The thresholds must be given as a percentage of the maximum number of connection resources made available for the entire SCCP.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="lowerConnThres">
+ <description>The lower connection threshold allow the user to specify the level at which the lower connection threshold notification is triggered. The thresholds must be given as a percentage of the maximum number of connection resources made available for the entire SCCP. The value must be less then UpperConnThres.
+
+The maximum value is less or equal to the upper connection threshold</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="swapUDTPointer">
+ <description>There are two ways to construct a UDTS from a UDT, the XUDTS will be constructed in the same way. One way is to only swap the pointers to Called Party Address and Calling Party Address in a UDT message when constructing a UDTS. The other way is to swap data. How this is done in the SCCP is configurable. The coding and interpretation is as follows:
+0, swap data Called party Address will be sent before Calling party Address
+1, swap pointers Called party Address will be sent after Calling party Address.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="hopCounterSclc">
+ <description>The SCLC hop counter is a parameter that is decremented for each performed GT translation for SCLC messages on the way to the end destination. If decrementing the counter results in the value of zero in a non-end destination node, the SCCP initiates the appropriate error procedure.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>15</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="hopCounterScoc">
+ <description>The SCOC hop counter is a parameter that is decremented for each performed GT translation for SCOC messages on the way to the end destination. If decrementing the counter results in the value of zero in no end destination node, the SCCP initiates the appropriate error procedure.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>15</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tconnEst">
+ <description>Connection establishment control timer.
+
+Unit: deciseconds (0.1 seconds).
+
+Guiding values;
+Range 600 - 1200, Default 600
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>600</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tIas">
+ <description>Send inactivity control timer.
+
+Unit: deciseconds (0.1 seconds).
+
+Guiding values;
+Range 3000-6000
+Default 3000</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>3000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tIar">
+ <description>Receive inactivity control timer.
+
+Unit: deciseconds (0.1 seconds).
+
+Guiding values;
+Range 6600-12600
+Default 6600</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>6600</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tRel">
+ <description>Connection release timer.
+
+Unit: deciseconds (0.1 seconds).
+
+Guiding values;
+Range 100-200
+Default 100</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tCong">
+ <description>Congestion timer.
+
+Unit: deciseconds (0.1 seconds).
+
+Guiding values;
+Range 10-2550
+Default 300</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>300</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tStatInfo">
+ <description>Subsystem Status Test timer.
+
+Unit: deciseconds (0.1 seconds).
+
+Guiding values;
+Range 10-2550
+Default 300</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>300</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tconnResp">
+ <description>Connection response waiting timer.
+
+Unit: deciseconds (0.1 seconds).
+
+Guiding values;
+Range 100-200
+Default 150</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>150</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tReass">
+ <description>Reassembly timer.
+
+Unit: deciseconds (0.1 seconds).
+
+Guiding values;
+Range 100-200
+Default 150</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>150</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tGuard">
+ <description>Guard timer for program restart not applicable for this CPP version. Instead a restart counter is used to improve restart performance.
+
+Unit: deciseconds (0.1 seconds).
+
+Guiding values;
+Range 13800-15000 (23-25 minutes)
+Default 1380 (23 minutes)
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>13800</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="smiValue">
+ <description>The SMI (Subsystem Multiplicity Indicator) is always ignored for incoming messages. This SCCP can however be configured to insert a specific SMI value in outgoing messages. The coding and interpretation is as follows:
+
+Coding Comment
+ 0 | Affected Subsystem multiplicity unknown.
+ 1 | Affected Subsystem is solitary.
+ 2 | Affected Subsystem is duplicated.
+ 3 | Spare.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>3</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="useSCMG">
+ <description>The use of SCMG functions.
+
+SST = SCCP Subsystem Test message.
+SSA = SCCP Subsystem Allowed message.
+SSP = SCCP Subsystem Prohibited message.
+SSC = SCCP Subsystem Congested message.
+
+The attributes contained in the struct is:
+initiateTimerTcon,
+allowRemoteBroadcast,
+useSST,
+useSSP,
+sendSSA,
+sendSST
+
+</description>
+ <dataType>
+ <structRef name="Scmg"/>
+ </dataType>
+ </attribute>
+ <attribute name="maxRelayedConn">
+ <description>Connection Oriented SCCP Signaling Relay Point (SRP-CO) and Maximum number of Relayed Connections is not used in this CPP version.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>524288</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUDTSent">
+ <description>Performance monitoring counter for number of sent UDT's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUDTRec">
+ <description>Performance monitoring counter for number of received UDT's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUDTSSent">
+ <description>Performance monitoring counter for number of sent UDTS's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUDTSRec">
+ <description>Performance monitoring counter for number of received UDTS's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfXUDTSent">
+ <description>Performance monitoring counter for number of sent XUDT's.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfXUDTRec">
+ <description>Performance management counter for number of received XUDT's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfXUDTSSent">
+ <description>Performance monitoring counter for number of sent XUDTS's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfXUDTSRec">
+ <description>Performance monitoring counter for number of received XUDTS's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCRSent">
+ <description>Performance monitoring counter for number of sent CR's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCRRec">
+ <description>Performance monitoring counter for number of received CR's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDT1Sent">
+ <description>Performance monitoring counter for number of sent DT1's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDT1Rec">
+ <description>Performance monitoring counter for number of received DT1's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfERRSent">
+ <description>Performance monitoring counter for number of sent ERR's.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfERRRec">
+ <description>Performance monitoring counter for number of received ERR's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSubsysAllowedSent">
+ <description>Performance monitoring counter for number of sent SSA's, subsystem allowed.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCREFRecFromNL">
+ <description>Performance monitoring counter for number of CREF messages received from NL.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCREFSentToNL">
+ <description>Performance monitoring counter for number of CREF messages sent to NL.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRLSDRecFromNL">
+ <description>Performance monitoring counter for number of RLSD messages received from NL.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRLSDSentToNL">
+ <description>Performance monitoring counter for number of RLSD messages sent to NL.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfConInUseExceedHighWaterMark">
+ <description>Performance monitoring counter for number of connections in use that has exceeded the high watermark threshold.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfConInUseReceededLowWaterMark">
+ <description>Performance monitoring counter for number of connections in use that has receded the low watermark threshold.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLUDTRec">
+ <description>Performance monitoring counter for number of received LUDT messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLUDTSSent">
+ <description>Performance monitoring counter for number of sent LUDTS messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="SccpScrc">
+ <description>The Signalling Connection Control Part Routing Control (SCCP SCRC) MO holds information about the SCCP routing control.</description>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="SccpScrcId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRoutingFailure">
+ <description>Performance monitoring counter for number of routing failures.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfConnectFailure">
+ <description>Performance monitoring counter for number of connect failures.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfHopCounterViolation">
+ <description>Performance monitoring counter for number of Hop counter violations.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRoutingFailNoTransAddrOfSuchNature">
+ <description>Performance monitoring counter for number of routing failures due to no translation for Nature of Address field.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRoutingFailNoTransSpecificAddr">
+ <description>Performance monitoring counter for number of routing failures due to no translation of specific address.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRoutingFailurePointCodeUnAvail">
+ <description>Performance monitoring counter for number of routing failures due to destination point code not available.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRoutingFailNetworkCongest">
+ <description>Performance monitoring counter for number of routing failures due to network congestion.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRoutingFailSubsysUnavail">
+ <description>Performance monitoring counter for number of routing failures due to destination subsystem unavailable.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRoutingFailReasonUnknown">
+ <description>Performance monitoring counter for number of routing failures due to unknown reason.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRoutingFailUnequippedSubsys">
+ <description>Performance monitoring counter for number of routing failures due to unequipped subsystem.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Program">
+ <description>The Program MO represent the executable software on the target hardware.
+
+MOs of this type are created automatically during system upgrade.
+MOs of this type are possible to create manually but a system upgrade
+is recommended to create them.
+
+Note! Some programs are not possible to restart or can take part in an RPU. For more information please refer to the LoadModule MO.
+
+</description>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="loadModule">
+ <description>This attribute gives information about which load module the program is instantiated from.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="LoadModule"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>This attribute shows whether the program has normal performance capability or not.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="startState">
+ <description>This attribute shows whether the program is permitted to enter operational state enabled or not after a PIU restart. The default state is disabled in order to avoid that an operating program and a new version of the same program have its startState enabled at the same time.
+
+It is used on all types of node restarts and restart of PlugInUnit with restartCause = piuRestartUpgrade.</description>
+ <dataType>
+ <enumRef name="StartState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="heapSize">
+ <description>This attribute sets the size of the program heap size.
+
+The value in the referenced LoadModule is fetched by program and used at create if no value is submitted at create of the program MO.
+
+The referenced load module has a default size defined at compile time wich is used if no value is submitted at create of loadModule or the program Mo.
+
+Note! The value of this attribute is overwritten during Software Upgrade.
+
+Note: If the program is a child to a Fan Mo this attribute is irrelevant.
+
+Note: Setting of this attribute will have no effect until the program is restarted.</description>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="poolSize">
+ <description>This attribute sets the size of the program pool size. In the referenced LoadModule there is possible to set this value at create.
+
+The value in the referenced LoadModule is fetched by program and used at create if no value is submitted at create of the program MO.
+
+The referenced load module has a default size defined at compile time wich is used if no value is submitted at create of
+LoadModule or the Program Mo.
+
+Note! The value of this attribute is overwritten during Software Upgrade.
+
+Only working for MP-Program
+
+Unit is bytes.
+
+Note: If the program is a child to a Fan Mo this attribute is irrelevant.
+
+Note: Setting of this attribute will not have any effect until the program is restarted.
+
+</description>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="restartTimer">
+ <description>This type specifies the time that a program have to execute without faults, until the restart counter is reset. The time value is interpreted as seconds.
+
+restartTimer= -1 : Forever, implies that the restart counter is only reset when the PIU is restarted.
+
+Note: If the program is a child to a Fan Mo this attribute is irrelevant.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>-1</min>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="restartCounterLimit">
+ <description>This attribute specifies the number of times that a program can restart, without escalation to a PIU restart. The possible values are:
+
+restartCounterLimit = -1 : Unlimited, means never restart PIU, regardless of the number of times the specific program restarts.
+
+Note: If the program is a child to a Fan Mo this attribute is irrelevant.
+
+Note! The value 3 means 3 restarts, hot, warm and finally as a last resort PIU restart.
+
+Note! The program escalates to a PIU restart when the number of restarts reaches the value set for this attribute.
+I.e. if for example the value is set to 5, escalation to PIU restart will occur at the fifth restart.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>-1</min>
+ </range>
+ <defaultValue>3</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ProgramId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="restart">
+ <description>Request to restart the program.
+Only valid for MP programs.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="UniSaalProfile">
+ <description>The UniSaal Profile MO represent and keeps attribute values used by one or more UNI SAAL termination point MOs.</description>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="UniSaalTp"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="profileData">
+ <description>See structure UniSaalProfileData</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="UniSaalProfileData"/>
+ </dataType>
+ </attribute>
+ <attribute name="UniSaalProfileId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="UniSaalTp">
+ <description>The MO represents an access point for a user where a UNI SAAL connection is terminated. The access point depends
+on an AAL5 connection termination located on the same processor.
+
+UniSaalTp can only terminate on a Mp processor.
+
+Note! The performance monitoring counters found in NniSaalTp MO is set to zero when the Mo and its RO is created.
+These counters are not reset unless there occurs a fault situation that demands a restart and recreation of the ROs.
+Also note that some of these counters are reset based on other conditions. For more details please refer to the
+descriptions of the performance monitoring counters in this MO.</description>
+ <attribute name="UniSaalTpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the UniSaalTp MO.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO.
+
+</description>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="uniSaalProfileId">
+ <description>Reference to a UniSaalProfile MO.
+
+The maxStat attribute defined in the UniSaalProfile MO is dependent on the AAL5 SDU size defined in the Aal5TpVccTp MO. See the description of the maxStat attribute in the UniSaalProfile MO.
+
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="UniSaalProfile"/>
+ </dataType>
+ </attribute>
+ <attribute name="aal5TpVccTpId">
+ <description>Reference to an Aal5TpVccTpMo.
+
+Note: The Aal5 termination point must terminate on a main processor, MP.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Aal5TpVccTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="maxSduSize">
+ <description>Maximum SAAL SDU size. The attribute is dependent on the AAL5 maximum SDU size defined in the Aal5TpVccTp MO. The 'maxSduSize' may not exceed the AAL5 maximum SDU size (the lower of the two directions, fromUserMaxSduSize and toUserMaxSduSize).
+
+Example: If 'fromUserMaxSduSize' is set to 256 and 'toUserMaxSduSize' is set to 512 in the Aal5TpVccTp MO, the ' maxSduSize' in the UniSaalTp MO may not exceed 252.
+
+(i.e. maxSduSize &lt;= the aal5MaxSduSize - 4 bytes)
+
+Note! When setting the value of 'maxSduSize' the 4 bytes used by the SAAL layer for the SAAL header has to be considered.
+
+Note! The upper limit of 2044 (2048 including the SAAL header) is due to limitations on the AAL5 layer.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>128</min> <max>2044</max>
+ </range>
+ <defaultValue>128</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSentSDUs">
+ <description>Number of successfully sent SDUs.
+Counts the number of successfully sent messages to the
+application using SAAL. Reset when the link goes InService or the counter "overflows".</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfReceivedSDUs">
+ <description>Number of successfully received SDUs.
+Counts the number of successfully received messages from
+ the application using SAAL. Reset when the link goes
+ InService or the counter "overflows".</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLinkInServiceTime">
+ <description>The accumulated time (in seconds) the signalling link has
+ been in service (in assured data transfer mode) since it was created. If the link is down the value 0 is returned.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAllSLFailures">
+ <description>Number of all Signalling Link failures.
+Is a total sum of the error counters:
+ - Number of protocol errors
+ - Number of unsuccessfully retransmissions
+ - Number of NoResponses
+ - Number of other errors</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfNoResponses">
+ <description>Number of no response. This counter is increased when SSCOP (Service Specific Connection Oriented Protocol)
+send an MaaError with error code P.
+For details refer to ITU-T Q.2110 - B-ISDN AATM Adaptation Layer - Service Specific Connection Oriented Protocol (SSCOP); (7/94).
+Counts the number of no responses detected the last 30 minutes.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalCongestions">
+ <description>Number of local congestions.
+This counter is increased when the sum of SAAL send and retransmission buffers are filled to more than 90%.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRemoteCongestions">
+ <description>Number of remote congestions.
+This counter is increased when the remote side gives SAAL no credit. Reset when the link goes InService or the counter "overflows".</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSequenceDataLosses">
+ <description>Number of sequences data loss.
+Counts the number of SD loss detected the last 30 minutes</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfProtocolErrors">
+ <description>Number of unsolicited or inappropriate PDUs. This counter is increased when SSCOP (Service Specific Connection Oriented Protocol)
+send an MaaError with error code Q.
+For details refer to ITU-T Q.2110 - B-ISDN AATM Adaptation Layer - Service Specific Connection Oriented Protocol (SSCOP); (7/94).
+Counts the number of protocol errors detected the last 30 minutes.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccReTransmissions">
+ <description>Number of unsuccessful retransmissions.
+Counts the number of unsuccessfully retransmissions detected the last 30 minutes.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfOtherErrors">
+ <description>Number of other list element errors. This counter is increased when SSCOP (Service Specific Connection Oriented Protocol)
+send an MaaError with error code Q-U.
+For details refer to ITU-T Q.2110 - B-ISDN AATM Adaptation Layer - Service Specific Connection Oriented Protocol (SSCOP); (7/94).
+Counts the number of other errors detected the last 30 minutes. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="E1PhysPathTerm">
+ <description>This MO represents an E1 (i.e. 2 Mbit/s) physical interface in the node. The E1PhysPathTerm MO does not define which type of traffic (TDM or ATM) that the interface should support.
+Please refer to the Ds0Bundle, AtmPort, IMALink and IMAGroup objects for details about configuration of traffic type.
+
+Note! The performance monitoring counters in the E1PhysPathTerm MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.
+</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>enabled or disabled according to the actual operational state of the Physical Line Termination. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="lineNo">
+ <description>The actual Line number on the board.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>8</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByTraffic">
+ <description>The identity of the reserving AtmPort MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ <attribute name="loopback">
+ <description>This attribute describes the current Loopback State of this physical path termination.
+
+Note! administrativeStatus must be set to locked when setting loopback attribute.</description>
+ <dataType>
+ <enumRef name="LoopbackState">
+ <defaultValue>none</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmEs">
+ <description>Performance Monitoring counter for ES, Errored Seconds.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSes">
+ <description>Performance Monitoring counter for Severely Errored Seconds, SES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="E1PhysPathTermId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="crc4Mode">
+ <description>Indicates what Cyclical Redundancy Check 4 Mode that is being used.</description>
+ <dataType>
+ <enumRef name="Crc4Mode">
+ <defaultValue>AUTOMATIC</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="idlePattern">
+ <description>The idle pattern.
+
+NOTE: Going from A_LAW or U_LAW to UNDEFINED is always allowed but setting up one ET board with
+both U_LAW and A_LAW is not allowed.
+E.g. If you want to change from A_LAW to U_LAW on one ET board you have to change idlePattern
+on each physical port belonging to the board to UNDEFINED first.
+A_LAW -&gt; UNDEFINED -&gt; U_LAW or U_LAW -&gt; UNDEFINED -&gt; A_LAW</description>
+ <dataType>
+ <enumRef name="IdlePattern">
+ <defaultValue>UNDEFINED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="degDegThr">
+ <description>The threshold decides how many of the received blocks that are allowed to have bit errors. The measurement is made on a per-second basis and if the threshold is passed the second is considered bad.
+
+This is a percentage value.
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="degDegM">
+ <description>How many bad seconds in a row that causes a Degraded Signal alarm.
+
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>2</min> <max>10</max>
+ </range>
+ <defaultValue>7</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="rdiReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="aisReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimeout">
+ <description>The shut-down timer. It is used when the administrativeState is set to shutdown.
+
+Value in seconds, must be a positive value.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100000</max>
+ </range>
+ <defaultValue>1800</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBySync">
+ <description>The identity of the reserving Synchronization MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Synchronization"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByImaLink">
+ <description>The identity of the reserving ImaLink MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ImaLink"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="J1PhysPathTerm">
+ <description>This MO represents an J1 (i.e. 1.5 Mbit/s) physical interface in the node. The J1PhysPathTerm MO does not define which type of traffic (TDM or ATM) that the interface should support.
+Please refer to the Ds0Bundle, AtmPort, IMALink and IMAGroup objects for details about configuration of traffic type.
+
+The performance monitoring counters in the J1PhysPathTerm MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.
+</description>
+ <attribute name="J1PhysPathTermId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="lineNo">
+ <description>The actual Line number on the board.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>8</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>enabled or disabled according to the actual operational state of the Physical Line Termination. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="physicalLineType">
+ <description>Supported interfaces is defined in J1Types</description>
+ <dataType>
+ <enumRef name="J1Type">
+ <defaultValue>j1_G</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByTraffic">
+ <description>The identity of the reserving AtmPort MO.
+
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ <attribute name="degThreshold">
+ <description>Maximum allowed BER(Bit Error Rate). Degraded signal (DEG) if BER &gt; degThreshold. The attribute gives a maximum BER of 10e-X, where X ranges from 5 to 9 (default 6)
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>3</min> <max>9</max>
+ </range>
+ <defaultValue>6</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="loopback">
+ <description>Possible values
+
+none - This is the normal state, no loop back is performed (and ordinary traffic is running).
+
+line - The physical path is looped on the line side, the external incoming path is looped back to the external outgoing path.
+
+system - The physical path is looped on the system side, the (node-) internal incoming path is looped back to the internal outgoing path.
+
+Note! administrativeStatus must be set to locked when setting loopback attribute.</description>
+ <dataType>
+ <enumRef name="LoopbackState">
+ <defaultValue>none</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmEs">
+ <description>Performance monitoring counter for Errored Seconds, ES.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSes">
+ <description>Performance monitoring counter for Severly Errored Seconds, SES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="idlePattern">
+ <description>The idle pattern.
+
+NOTE: Going from A_LAW or U_LAW to UNDEFINED is always allowed but setting up one ET board with
+both U_LAW and A_LAW is not allowed.
+E.g. If you want to change from A_LAW to U_LAW on one ET board you have to change idlePattern
+on each physical port belonging to the board to UNDEFINED first.
+A_LAW -&gt; UNDEFINED -&gt; U_LAW or U_LAW -&gt; UNDEFINED -&gt; A_LAW</description>
+ <dataType>
+ <enumRef name="IdlePattern">
+ <defaultValue>UNDEFINED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="rdiReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="aisReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimeout">
+ <description>The shut-down timer. It is used when the administrativeState is set to shutdown.
+
+Value in seconds, must be a positive value.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100000</max>
+ </range>
+ <defaultValue>1800</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBySync">
+ <description>The identity of the reserving Synchronization MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Synchronization"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByImaLink">
+ <description>The identity of the reserving ImaLink MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ImaLink"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Aal0TpVccTp">
+ <description>This MO is used to represent the point in the node where an AAL0 connection is terminated. At this point the user exchange SDUs with its peer at the remote end of the AAL0 connection.
+
+Note! The performance monitoring counters in this MO is set to 0 when counterMode is set to PM_MODE_ON.
+In PM_MODE_OFF no information at all is retrived. So any value for pm-monitoring is measured from the time
+of setting counterMode to PM_MODE_ON.
+At node restart these performance monitoring counters is reset to 0.
+
+</description>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="processorId">
+ <description>This attribute specifies on what processor the termination point resides. It could either be a board processor or main processor (MO type PlugInUnit), or a SP processor (MO type Spm).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational State reflects the operational state of the end points and the belonging node connections.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO.
+</description>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="vclTpId">
+ <description>The virtual channel to which this MO is termination.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="VclTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="Aal0TpVccTpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="continuityCheck">
+ <description>Continuitiy checking means that a cell is sent downstream when no user cell has been sent for a period of nominally 1 second.
+
+Activates VC end to end continuityCheck according to ITU.T rec I.610.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="nomPmBlkSize">
+ <description>Nominal performance monitoring (PM) blocksize. The minimum number of ATM cells to send before sending a Forward Performance Monitoring, FPM, cell.</description>
+ <dataType>
+ <enumRef name="AtmNomPmBlkSize">
+ <defaultValue>NOM_PM_BLKSIZE_2_10</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="counterMode">
+ <description>PM mode is set to indicate type of performance monitoring mode (i.e. activation of bidirectional PM measurements).
+
+</description>
+ <dataType>
+ <enumRef name="AtmCounterMode">
+ <defaultValue>PM_MODE_OFF</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwLostCells">
+ <description>Performance monitoring counter for forwarded lost cells.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwMissinsCells">
+ <description>Performance monitoring counter for number of forwarded missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwErrBlocks">
+ <description>Performance monitoring counter for number of forwarded errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostFpmCells">
+ <description>Performance monitoring counter for number of lost Forward Performance Monitoring, FPM cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwLostCells">
+ <description>Performance monitoring counter for number of lost backward cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwMissinsCells">
+ <description>Performance monitoring counter for number of backward missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwErrBlocks">
+ <description>Performance monitoring counter for number of backward errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostBrCells">
+ <description>Performance monitoring counter for number of lost Backward Reporting, BR, cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="alarmReport">
+ <description>Attribute to decide what type of alarms to be reported.</description>
+ <dataType>
+ <enumRef name="AlarmReport">
+ <defaultValue>ALARM_LOC</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Aal5TpVccTp">
+ <description>This MO is used to represent the point in the node where an AAL5 connection is terminated. At this point the user exchanges SDUs with its peer at the remote end of the AAL5 connection.
+
+Note! The 'mtuSize' on the IpAtmLink MO does not include 8 bytes required for the LLC/SNAP header and this should be taken into consideration when setting the SduSize on the Aal5TpVccTp MO.
+
+Note! The performance monitoring counters in this MO is set to 0 when counterMode is set to PM_MODE_ON.
+In PM_MODE_OFF no information at all is retrived. So any value for pm-monitoring is measured from the time
+of setting counterMode to PM_MODE_ON.
+At node restart these performance monitoring counters is reset to 0..</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="processorId">
+ <description>This attribute specifies on what processor the protocol is terminated. It could either be a board processor or main processor (PlugInUnit) or a SP processor (Spm).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="vclTpId">
+ <description>The virtual channel to which this MO is termination.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="VclTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational State reflects the operational state of the end points and the belonging node connections.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="fromUserMaxSduSize">
+ <description>The maximum SDU size in number of octets received from the user (called maxIngressSduSize in the FRO domain).
+
+The allowed range is dependent on the processorType.
+SP: LowestMaxSduSize =1, HighestMaxSduSize=1600
+BP: LowestMaxSduSize =1, HighestMaxSduSize=1600
+MP:LowestMaxSduSize =1, HighestMaxSduSize=2048</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>2048</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="toUserMaxSduSize">
+ <description>The maximum SDU size in number of octets sent to the user (called maxEgressSduSize in the FRO domain). This attribute is controlled by the processor type.
+
+The allowed range is dependent on the processorType.
+SP: LowestMaxSduSize =1, HighestMaxSduSize=1600
+BP: LowestMaxSduSize =1, HighestMaxSduSize=1600
+MP:LowestMaxSduSize =1, HighestMaxSduSize=2048</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>2048</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The attribute is set by the action reserve from a user of Aal5TpVccTp. It could either be a Cello user like IpAtmLink/UniSaalTp or a node application.
+
+</description>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="Aal5TpVccTpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="alarmReport">
+ <description>Attribute to decide what type of alarms to be reported.</description>
+ <dataType>
+ <enumRef name="AlarmReport">
+ <defaultValue>ALARM_LOC</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="continuityCheck">
+ <description>Continuitiy checking means that a cell is sent downstream when no user cell has been sent for a period of nominally 1 second. Continuity check both enables generation of CC cells as well as detection of LOC
+</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="nomPmBlkSize">
+ <description>Nominal performance monitoring (PM) blocksize. The minimum number of ATM cells to send before sending a Forward Performance Monitoring, FPM, cell.
+</description>
+ <dataType>
+ <enumRef name="AtmNomPmBlkSize">
+ <defaultValue>NOM_PM_BLKSIZE_2_10</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="counterMode">
+ <description>PM mode is set to indicate type of performance monitoring mode (i.e. activation of bidirectional PM measurements).
+
+</description>
+ <dataType>
+ <enumRef name="AtmCounterMode">
+ <defaultValue>PM_MODE_OFF</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwLostCells">
+ <description>Performance monitoring counter for number of lost forward cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwMissinsCells">
+ <description>Performance monitoring counter for number of forward missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwErrBlocks">
+ <description>Performance monitoring counter for number of forward errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostFpmCells">
+ <description>Performance monitoring counter for number of lost Forward Performance Monitoring, FPM, cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwLostCells">
+ <description>Performance monitoring counter for number of lost backward cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwMissinsCells">
+ <description>Performance monitoring counter for number of backward missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwErrBlocks">
+ <description>Performance monitoring counter for number of backward errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostBrCells">
+ <description>Performance monitoring counter for number of lost Backward Reporting, BR, cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="AtmPort">
+ <description>The AtmPort MO is used to configure a physical port for ATM traffic.
+ATM can be transported accross the physical layer in three distinct and different ways:
+
+- Normal mode
+
+An AtmPort MO is created with a reference to physical layer object (any of E1PhysPathTerm,
+J1PhysPathTerm, T1PhysPathTerm, E3PhysPathTerm, T3PhysPathTerm, Sts3CspeTtp, E1Ttp, T1Ttp or Vc4Ttp).
+The payload of that physical layer object is used to transport the ATM traffic.
+
+- Fractional ATM mode
+
+An AtmPort MO is created with a reference to a Ds0Bundle object. The Ds0Bundle specifies
+in this case the timeslots on the physical layer (any of E1PhysPathTerm,J1PhysPathTerm,
+T1PhysPathTerm, T1Ttp or E1Ttp) that should be used for ATM traffic. The remaining timeslots
+are not used at all.
+I.e. when fractional ATM is used only one Ds0Bundle can exist as a child to a physical port MO.
+
+- IMA mode
+
+In IMA mode, a number of physical ports are grouped together to form one "virtual" physical
+ATM pipe. In this mode the AtmPort MO is created with a reference to an IMAGroup MO.
+Please refer to the ImaGroup MO for further details.
+
+Note! The performance monitoring counters in the AtmPort MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again..
+
+
+</description>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="AtmPortId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the ATM port.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status of the AtmPort.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmTransmittedAtmCells">
+ <description>Performance monitoring counter for number of transmitted ATM cells through the ATM port. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmReceivedAtmCells">
+ <description>Performance monitoring counter for number of received ATM cells through the ATM port.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="valueOfLastCellWithUnexp">
+ <description>This attribute returns the ATM header, (vpi, vci, pti), of the last received unexpected cell.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <structRef name="ValueOfUnex"/>
+ </dataType>
+ </attribute>
+ <attribute name="uses">
+ <description>Reference to the physical port, IMA Group or Ds0Bundle used by the ATM port.
+
+The possible MOs are:
+E1PhysPathTerm, J1PhysPathTerm, T1PhysPathTerm, E3PhysPathTerm, T3PhysPathTerm, Sts3CspeTtp, Sts1SpeTtp, Vc4Ttp, E1Ttp, T1Ttp, Ds0Bundle and ImaGroup.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmSecondsWithUnexp">
+ <description>Performance monitoring counter for errored seconds with discarded cells due to protocol errors (unexpected, UNEX, events).
+
+I.610: With protcol errors is meant the reception of cells with either a non-standardized or a non-currently allocated header value.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="hecCorrectionMode">
+ <description>Header Error Correction.
+
+This attribute specifies if the AtmPort should detect and correct single bit errors or detect multiple bit errors in the ATM header.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp3bAp">
+ <description>This MO represents an MTP3b Access Point (in a remote node). An MTP3b AP is a logical point in the MTP network at which an
+MTP3b user can access the services provided by MTP3b and the MTP3b can deliver its services to the MTP3b user.
+
+The performance monitoring counters found in Mtp3Ap MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).
+
+</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="routeSetId">
+ <description>The routeSetId attribute points out the MTP3b Signalling Route Set (SRS) to which the Mtp3bAp MO is connected. </description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Mtp3bSrs"/>
+ </dataType>
+ </attribute>
+ <attribute name="serviceInd">
+ <description>The serviceInd attribute (Service Indicator, SI) is used by traffic handling functions to perform message distribution.
+Only SI=3 for SCCP usage and SI=12 for Q.2630.1 usage and SI=14 for GCP (H.248) usage have any meaning in this case.
+
+Full range of values for attribute SI:
+0 = Signalling network management messages
+1 = Signalling network testing &amp; maintenance regular messages
+2 = Signalling network testing &amp; maintenance special messages*
+3 = SCCP
+4 = Telephone User Part (TUP)
+5 = ISDN User Part (ISUP)
+6 = Data User Part, call and circuit related messages
+7 = Data User Part, facility registration and cancellation messages
+8 = MTP Testing User Part
+9 = Broadband ISDN User Part
+10 = Satellite ISDN User Part
+11 = Spare
+12 = Q.2630.1
+13 = Spare
+14 = H.248
+15 = Spare
+
+Note! The serviceIndicator has to be unique for each Mtp3bAp witin the same Mtp3bSrs.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>15</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operationalState attribute determines the operational status of the MTP3b AP .
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="Mtp3bApId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUserPartUnavailRec">
+ <description>A performance management counter for number of received User Part Unavailable messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAdjacentSPNotAccessible">
+ <description>Performance management counter for number of Adjacent SP's that are not accessible via direct links.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="NniSaalProfile">
+ <description>The NniSaal Profile MO represents and keeps attribute values used by one or more NNI SAAL termination point MOs.</description>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of NniSaalTps that have reserved this NniSaalProfile.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="NniSaalTp"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="profileData">
+ <description>See structure NniSaalProfileData.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="NniSaalProfileData"/>
+ </dataType>
+ </attribute>
+ <attribute name="NniSaalProfileId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="NniSaalTp">
+ <description>The MO represents an access point for a user where a NNI SAAL connection is terminated. The access point depends
+on an AAL5 connection termination located on the same processor.
+
+NniSaalTp can only terminate on a Mp processor.
+
+Note! The performance monitoring counters found in NniSaalTp MO is set to zero when the Mo and its RO is created.
+These counters are not reset unless there occurs a fault situation that demands a restart and recreation of the ROs.
+Also note that some of these counters are reset based on other conditions. For more details please refer to the
+descriptions of the performance monitoring counters in this MO.</description>
+ <attribute name="NniSaalTpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the NniSaalTp MO.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="nniSaalProfileId">
+ <description>Reference to a NniSaalProfile MO.
+
+The maxStat attribute defined in the NniSaalProfile MO is controlled by the AAL5 SDU size defined in the Aal5TpVccTp MO. See the description of the maxStat attribute in the NniSaalProfile MO.
+
+Note! The consistency check of the attributes in the two MOs mentioned above could not be performed until the NniSaalTp MO was created since there is no direct relation between the objects. It is therefore the responsibility of NniSaalTp to verify the consistency.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="NniSaalProfile"/>
+ </dataType>
+ </attribute>
+ <attribute name="aal5TpVccTpId">
+ <description>Reference to a Aal5TpVccTp MO.
+
+Note: The Aal5 termination point must terminate on a main processor, MP.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Aal5TpVccTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="maxSduSize">
+ <description>Maximum SAAL SDU size. The attribute is dependent on the AAL5 maximum SDU size defined in the Aal5TpVccTp MO. The 'maxSduSize' may not exceed the AAL5 maximum SDU size (the lower of the two directions, fromUserMaxSduSize and toUserMaxSduSize).
+
+Example: If 'fromUserMaxSduSize' is set to 256 and 'toUserMaxSduSize' is set to 512 in the Aal5TpVccTp MO, the ' maxSduSize' in the NniSaalTp MO may not exceed 252.
+
+(i.e. maxSduSize &lt;= the aal5MaxSduSize - 4 bytes)
+
+Note! When setting the value of 'maxSduSize' the 4 bytes used by the SAAL layer for the SAAL header has to be considered.
+
+Note! The upper limit of 2044 (2048 including the SAAL header) is due to limitations on the AAL5 layer.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>128</min> <max>2044</max>
+ </range>
+ <defaultValue>128</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSentSDUs">
+ <description>Number of successfully sent SDUs.
+Counts the number of successfully sent messages to the
+application using SAAL. Reset when the link goes InService or the counter "overflows".</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfReceivedSDUs">
+ <description>Number of successfully received SDUs.
+Counts the number of successfully received messages from
+ the application using SAAL. Reset when the link goes
+ InService or the counter "overflows".</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLinkInServiceTime">
+ <description>The accumulated time (in seconds) the signalling link has
+ been in service (in assured data transfer mode) since it was created. If the link is down the value 0 is returned.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAllSLFailures">
+ <description>Number of all Signalling Link failures.
+Is a total sum of the error counters:
+ - Number of protocol errors
+ - Number of unsuccessfully retransmissions
+ - Number of NoResponses
+ - Number of other errors</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfNoResponses">
+ <description>Number of no response.
+Counts the number of no responses detected the last 30 minutes.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalCongestions">
+ <description>Number of local congestions.
+This counter is increased when the sum of SAAL send and retransmission buffers are filled to more than the congestionOnSet attribute is configured to..</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRemoteCongestions">
+ <description>Number of remote congestions.
+This counter is increased when the remote side gives SAAL no credit. Reset when the link goes InService or the counter "overflows".</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAlignmentFailures">
+ <description>Number of alignment or proving failures. This counter is
+increased when "alignment not successful".
+The counter is reset when the link is created or the counter "overflows".</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSequenceDataLosses">
+ <description>Number of sequences data loss.
+Counts the number of SD loss detected the last 30 minutes</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfProtocolErrors">
+ <description>Number of unsolicited or inappropriate PDUs.
+Counts the number of protocol errors detected the last 30 minutes.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccReTransmissions">
+ <description>Number of unsuccessful retransmissions.
+Counts the number of unsuccessfully retransmissions detected the last 30 minutes.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfOtherErrors">
+ <description>Number of other list element errors.
+Counts the number of other errors detected the last 30 minutes. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="AtmTrafficDescriptor">
+ <description>This MO specifies traffic and QoS parameters for virtual channel connections.
+
+The attributes can only be set in certain combinations:
+
+CBR:
+ingressAtmQos /egressAtmQos:
+1, 2
+
+ingressAtmPcr /egressAtmPcr:
+mandatory (must be specified)
+
+ingressAtmMcr /egressAtmMcr:
+optional (not used, any value submitted will be ignored)
+
+UBR+:
+ingressAtmQos /egressAtmQos:
+3
+
+ingressAtmPcr /egressAtmPcr:
+optional (if shaping is used the desired rate is specified, 0 means no shaping)
+
+ingressAtmMcr /egressAtmMcr:
+mandatory (must be specified)
+
+UBR:
+ingressAtmQos /egressAtmQos:
+4
+
+ingressAtmPcr /egressAtmPcr:
+optional (not used, any value submitted will be ignored)
+
+ingressAtmMcr /egressAtmMcr:
+optional (not used, any value submitted will be ignored)
+
+Note that the VP sub layer only supports ServiceCategory = CBR and QoS = 1.
+
+Note! The performance monitoring counters in the AtmTrafficDescriptor MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.
+</description>
+ <attribute name="AtmTrafficDescriptorId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>This MO's user label.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ingressAtmPcr">
+ <description>Ingress ATM Peak cell rate (cells/s).
+
+Only positive values are allowed. This attribute is only mandatory when serviceCategory is CBR or UBR_PLUS.
+
+Note! When 'serviceCategory' is set to UBR this attribute has no relevance and the value submitted is ignored by the system.
+
+Note! When 'serviceCategory' is set to UBR+ the value 0 (zero) means that shaping is not used. A value larger than the minimum desired cell rate enables shaping to the rate specified.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ingressAtmQos">
+ <description>Ingress ATM quality of service.
+
+This attribute can be set to Class 1 and 2 if attribute serviceCategory is set to CBR.
+
+This attribute can be set to Class 3 if attribute serviceCategory is set to UBR+.
+
+This attribute can be set to Class 4 if attribute serviceCategory is set to UBR.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="AtmQos">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="egressAtmPcr">
+ <description>Egress ATM Peak cell rate (cells/s).
+
+Only positive values allowed.
+
+This attribute is only mandatory when serviceCategory is CBR or UBR_PLUS.
+
+Note! When 'serviceCategory' is set to UBR this attribute has no relevance and the value submitted is ignored by the system.
+
+Note! When 'serviceCategory' is set to UBR+ the value 0 (zero) means that shaping is not used. A value larger than the minimum desired cell rate enables shaping to the rate specified.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="egressAtmQos">
+ <description>Egress ATM quality of service.
+
+This attribute can be set to Class 1 and 2 if attribute serviceCategory is set to CBR.
+
+This attribute can be set to Class 3 if attribute serviceCategory is set to UBR+.
+
+This attribute can be set to Class 4 if attribute serviceCategory is set to UBR.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="AtmQos">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Sequence of Users that are using this AtmTrafficDescriptor.
+
+
+</description>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="egressAtmMcr">
+ <description>Egress ATM minimum desired cell rate.
+
+Only positive values allowed. The attribute is only mandatory when serviceCategory is UBR+.
+
+Note! When 'serviceCategory' is set to CBR or UBR this attribute has no relevance and the value submitted is ignored by the system.
+
+Note! This attribute cannot have a value larger than for 'egressAtmPcr'.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ingressAtmMcr">
+ <description>Ingress minimum desired cell rate (cells/s).
+
+Only positive vaues allowed. This attribute is mandatory only when serviceCategory is UBR+.
+
+Note! When 'serviceCategory' is set to CBR or UBR this attribute has no relevance and the value submitted is ignored by the system.
+
+Note! This attribute cannot have a value larger than for 'ingressAtmPcr'.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="serviceCategory">
+ <description>The service category.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="ServiceCategory">
+ </enumRef>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp3bSrs">
+ <description>This MO represents/models a MTP3b Signalling Route Set.
+
+The performance monitoring counters found in Mtp3Srs MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).</description>
+ <attribute name="Mtp3bSrsId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the Mtp3bSrs MO.
+
+There are two possible states for the operationalState attribute:
+
+- enabled, the MO is partly or fully operational.
+- disabled, the MO is not operational.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The attribute is set by the local action Reserve.
+
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="autoReroute">
+ <description>This flag indicates Whether automatic rerouting is performed(true) or not(false), between IP and ATM/TDM
+routes when configuration is made. If set to 'false', it has to be done manually, for ex. by management actions(orders).
+
+Note! The attribute 'autoReroute' will always be set to 'false' regardless of value submitted. This attribute is to be removed in coming releases.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean/>
+ </dataType>
+ </attribute>
+ <attribute name="destPointCode">
+ <description>The destPointCode attribute (destination point code, DPC) represents the point code of this Mtp3b SRS MO.
+The Destination Point Code in a Route Set has to be unique within each Signaling Point.
+
+Note! The format of destPointCode must correspond to the signallingPointCode format in the Mtp3bSp, i.e. ITU, ANSI, TTC or China.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16777215</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="congestedLevel">
+ <description>There are two possible states for the congestedLevel attribute:
+
+- notCongested, no change in congestion level.
+- congested, change in congestion level has occurred.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bCongestLevel">
+ <defaultValue>notCongested</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDiscardedMsgFromBroadToNarrow">
+ <description>Performance management counter for number of messages discarded from broadband to narrowband.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTransferControlledRec">
+ <description>Performance monitoring counter for number of received Transfer Control (TFC) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTransferProhibitedRec">
+ <description>Performance monitoring counter for number of received Transfer Prohibited (TFP) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTransferAllowedRec">
+ <description>Performance monitoring counter for number of received Transfer Allowed (TFA) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <action name="routeSetTestAnyRoute">
+ <description>The route set test is only available for the Japanese Mtp3b, TTC.
+
+See JT-Q.707 for details.
+
+The test selects a route in the route set and tests it.
+
+Possible return codes are:
+
+0 : successful test
+48 : unsuccessful test
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <long/>
+ </returnType>
+ </action>
+ <action name="routeSetTestSpecificRoute">
+ <description>The route set test is only available for the Japanese Mtp3b, TTC.
+
+See JT-Q.707 for details.
+
+The test tests the specified route.
+
+Possible return codes are:
+
+0 : successful test
+48 : unsuccessful test
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <long/>
+ </returnType>
+ <parameter name="routeId">
+ <in/>
+ <dataType>
+ <moRef name="Mtp3bSr"/>
+ </dataType>
+ </parameter>
+ </action>
+ </class>
+
+ <class name="PlugInUnit">
+ <description>This MO is used to represent a plug-in-unit, that is a board inserted in a slot in a subrack.
+
+Note! Before deleting the PlugInUnit MO, administrativeState must be set to locked.</description>
+ <attribute name="PlugInUnitId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>A free tag that a user can associated to the this managed object. The value has no relevance for the managed system.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of the PlugInUnit.
+
+The possibility to rollback the setting of this attribute is limited.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state is set to 'enabled' when the plug-in-unit has loaded and started its 'Basic' load module.</description>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="productType">
+ <description>This attribute describes the product type and is always set to the value "HW".</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>"HW"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="piuType">
+ <description>A reference to an available PiuType at create of a PIU.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="PiuType"/>
+ </dataType>
+ </attribute>
+ <attribute name="piuGroupNumber">
+ <description>Indicates which restart group the plug-in unit belongs to.
+Such a group consists of a number of plug-in units where at least one must be enabled (working) or performing recovery. When all plug-in units in a group are out of function, the node is restarted.
+
+Must have a positive value.
+
+Zero indicates no group.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>65536</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled. It is a bit mapped CORBA long, where one or more of the bits may be set. If none of the bits are set then the availability status is considered to be undefined.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of managed objects depending on PlugInUnit</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="pmProcessorLoad">
+ <description>The measurement is done over 100 ms, and returns the sum of load on processes up to, and including process priority 23. The sum is expressed in %
+
+Supported on MP, BP and SP boards.
+
+In case of SP boards the returned processor load is the load of the BP.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="allowedSeqRestarts">
+ <description>The number of automatic (do not require intervention from a human operator) sequential restarts that are allowed for a PIU. When this number of automatic restarts has been exceeded, the automatic restarting halts and the PIU is faulty marked.
+
+The time limit between two restarts is 5 minutes. This means that if the time between two restarts
+is less then 5 minutes the restarts are counted, otherwise the restart counter is reset.
+
+For example, 3 means 3 restarts with time limit &lt; 5 minutes are accepted but when the 4:th occurs within 5 minutes the board is considered faulty and an alarm is generated.</description>
+ <dataType>
+ <enumRef name="SeqRestarts">
+ <defaultValue>RESTARTS_WITH_WARM</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <action name="restart">
+ <description>
+Note! The restartCause can have the following values:
+1 = restart error
+2 = restart upgrade
+
+Note! The restartCause piuRestartUpgrade overrides the restartRank value and gives mainly restartRank=warm (or restartRank=refresh in some upgrade situations.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="restartRank">
+ <in/>
+ <dataType>
+ <enumRef name="RestartRank">
+ </enumRef>
+ </dataType>
+ </parameter>
+ <parameter name="restartCause">
+ <in/>
+ <dataType>
+ <enumRef name="RestartCause">
+ </enumRef>
+ </dataType>
+ </parameter>
+ <raisesException name="ValueOutOfRangeException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ </action>
+ </class>
+
+ <class name="Mtp3bSls">
+ <description>This MO represents the SS7 Signalling Link Set as defined in Recommendation Q.704 Ver. 3, April 28 1992 (ITU) T1.111-1996 (ANSI), JT-Q.704 Ver. 3, April 28 1992 (TTC) or GF001-9001 1990 (China).
+
+It provides information about a set of signalling links between an OPC/Adjacent PC pair. A link set is constructed from between 1 to16 Signalling Links (for China, Itu, Ttc and the ANSI standard), all of which have the same two end points (signalling points) as the Signalling Link Set. A Signalling LInk Set may be part of many routes.</description>
+ <attribute name="Mtp3bSlsId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Use label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the MTP3B SLS.
+
+The operability of the MTP3B SLS is described by the operationalState attribute which has two possible values:
+
+- Enabled: The MTP3B SLS is partly or fully operable and available for use. At least one of the belonging links (SL) is enabled.
+- Disabled: The MTP3B SLS is totally inoperable and unable to provide service to the user.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="usageState">
+ <description>The usageState reflects the usage state of the links in the link set. There are three possible values:
+
+- Active: At least one of the belonging SLs of the SLS is Active and no link is Busy.
+- Busy: If one of the belonging links is Busy.
+- Idle: All SLs of the SLS are Unavailable.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bUsageState">
+ <defaultValue>IDLE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="periodicLinkTestFlag">
+ <description>The periodicLinkTestFlag indicates if periodic sending of SLTM/SLTA messages are used or not. The SLTM message will be sent on every link which is "aligned" at an interval of (SLTM timer). The answer, SLTA is supposed to arrive within (SLTA timer). If this doesnt happen, or if the received SLTA doesnt match the sent SLTM a second SLTM will be sent. If this SLTM also fail then the link will be considered 'out-of-service' and a restart of that link will begin.
+
+ANSI: true is default.
+ITU: true is default.
+China: true is default.
+TTC: false is default.
+
+Note that TTC does not use this feature.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="mtp3bSrsId">
+ <description>The mtp3bSrsId attribute points out the corresponding MTP3b Signalling Route Set MO (adjacentDPC).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Mtp3bSrs"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="Mtp3bSr"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <action name="deactivateLinkSet">
+ <description>This action deactivates a link set, which means the containing signalling links are taken out of service.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ </action>
+ <action name="activateLinkSet">
+ <description>A linkset containing signalling links which are all out of service, is called a deactivated linkset. In order to start up the signalling links and get them into service, there is an Activate Link Set action, or rather, there are two similar actions for activation of a link set.
+
+If the action fails to activate a link the ActivationFailed exception is raised.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ </action>
+ <action name="emergencyActivateLinkSet">
+ <description>This action activates the signalling link with emergency alignment.
+It will also set autoStartLink = true
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ </action>
+ </class>
+
+ <class name="Mtp3bSr">
+ <description>This MO represents a MTP3b Signalling Route. A Signalling Route is used to convey MTP3b User messages from a origin SP to a destination SP (Signalling Point). This MO is multiple instansiated and is contained in the MO MTP3b Signalling Route Set. A Signalling Route is from a network point of view the sequence of link sets from a originating signalling point to a destination signalling point.
+
+Note! At least one signalling route in the signalling route set must have priority = 1.
+If lower priorities are defined the next level must be priority=2. (e.g. routes with priority =1 and =3 in a route set will not work).
+
+Note! Signalling Routes belonging to the same route set with the same priority must have the same type of bearer (Broad Band or Narrow Band).</description>
+ <attribute name="Mtp3bSrId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="linkSetM3uId">
+ <description>The MTP3b Signalling Link Set (MTP3bSls) or M3uAssociation to which the MTP3bSr MO is connected.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Operational state notification.There are two possible states for the operationalState attribute:
+- enabled, possible to perform operations on the MTP3b SR.
+- disabled, not possible to perform operations on the MTP3b SR.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="usageState">
+ <description>There are three possible states for the usageState attribute:
+
+-active, route is active.
+-busy, route is congested.
+-idle, route not in use.
+
+(idle=0, active=1, busy=2)
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bUsageState">
+ <defaultValue>IDLE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="priority">
+ <description>The priority of the alternative route. The traffic is directed to the highest priority route(s) available in the route set. If more than one route has the same priority within a route set then loadsharing is permitted between these routes.
+The value 1 is considered as the highest priority.</description>
+ <mandatory/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>5</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="routeType">
+ <description>The type of the route.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="Mtp3bRouteType">
+ <defaultValue>TDM_ATM</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="RouteBlockingState">
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="RouteState">
+ <defaultValue>NOT_BLOCKED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSecondsAccumulatedRouteUnavailable">
+ <description>The number of seconds (accumulated) route unavailable.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <action name="blockSignalingRoute">
+ <description>This action blocks the Signaling Route.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="deBlockSignalingRoute">
+ <description>This action deblocks the Signaling Route.
+
+Note! This action requires antransaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="IpSystem">
+ <description>The IP System MO constitutes the top structure level for IP related MOs in a Cello node.
+
+The IpSystem MO is automatically created and cannot be deleted.
+
+The local distinguished name of this MO is ManagedElement=1, IpSystem=1.
+</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>An operator defined label.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="IpSystemId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="ping">
+ <description>Ping - used to call a host or router to find out if it is present in the network. The following input parameter is used by the Ping action:
+The domain name or IP address to the host that shall be called.
+
+The following parameter is returned:
+Ping result: 'IP address/domain name' - is alive or no answer.
+
+Note! This action requires a transaction.
+</description>
+ <returnType>
+ <string/>
+ </returnType>
+ <parameter name="host">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="traceRoute">
+ <description>Trace route - used to get information about the route through the IP network that is used for a destination with a specific IP address.
+
+The following input parameter is used by the trace route action:
+The domain name or IP address to a host that shall be trace-routed.
+
+The following parameter is returned:
+Trace result - list of IP addresses/domain names or path not found.
+
+Note! This action requires a transaction.
+</description>
+ <returnType>
+ <string/>
+ </returnType>
+ <parameter name="host">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ </class>
+
+ <class name="IpAtmLink">
+ <description>This MO represents an Internet Protocol over ATM link. LLC/SNAP encapsulated packets over Atm Adaptation Layer 5, AAL5, ATM PVCs are used.
+
+Note: The performance monitoring counters in the IpAtmLink MO has a "Wrap-around time" of approximately 2 hours.
+
+Note! When setting the 'fromUserMaxSduSize' and 'toUserMaxSduSize' on the Aal5TpVccTp MO the defined SduSize should be 8 bytes larger then the 'mtuSize' on the IpAtmLink.
+
+Note! Only Aal5TpVccTp's that terminates on an MP (Main Processor) may be used when setting up IpAtmLink's.</description>
+ <attribute name="IpAtmLinkId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>The User Label attribute gives the operator the possibility to label the links.
+</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the IP over ATM link is dependent of the operational states of the underlying AAL5 termination points that are used to transport IP datagrams. If at least one operational AAL5 termination point (MO: AAL5 TP VCC TP) exists, the operational state of the IP over ATM Link is set to "ENABLED"</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled. It is a bit mapped CORBA long, where one or more of the bits may be set. If none of the bits are set then the availability status is considered to be undefined.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>If set, indicates that this IpAtmLink is reserved by the OspfInterface represented by this attribute.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="OspfInterface"/>
+ </dataType>
+ </attribute>
+ <attribute name="ipAddress">
+ <description>The input format used by the operator is four fields of digits, separated by a dot. Each field consists of three digits.
+
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="subnetMask">
+ <description>The attribute subnetMask states the subnet mask of the IP over ATM link (point to point link).
+
+The input format used by the operator is four fields of digits, separated by a dot. Each field consists of three digits.
+For a point to point link, the subnetmask 255.255.255.252 is very likely.
+
+Note! The subnet mask has to be contiguos. That is, it has the LSB's set to 0 (zero).
+
+Example:
+
+255.255.255.X
+
+Contiguous subnet mask:
+11111111.11111111.11111111.11111110 (X = 254)
+11111111.11111111.11111111.11111100 (X = 252)
+
+Not-contiguous subnet mask:
+11111111.11111111.11111111.11111010 (X = 250)
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="mtuSize">
+ <description>The attribute mtuSize states the maximum IP datagram size that may be sent on the IP over ATM link in bytes, without fragmentation. Recommended MTU size is 1500 bytes to prevent IP fragmentation.
+
+Note that the size of the IP datagram does not include the 8 Bytes added for the LLC/SNAP header before putting the IP datagram in AAL5 SDU.
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>576</min> <max>2040</max>
+ </range>
+ <defaultValue>1500</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="metric">
+ <description>The attribute metric states the metric "cost" of the IP over ATM link. The metric value is calculated as 10^8 /link bit speed.
+
+For example:
+Metric for 10 Mbps Ethernet = 10^8/10^7 = 10
+Metric for 100 Mbps Ethernet = 10^8/10^8 = 1</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>32767</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="monitor">
+ <description>This attribute indicates whether InvATMARP monitor is turned on or off.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="monitorInterval">
+ <description>The interval between sending monitor packets.
+Unit is seconds.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>60</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="monitorRetries">
+ <description>The number of retries when sending monitor packets.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>255</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="interfaceName">
+ <description>The interface name.
+
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="aal5TpVccTpSelectionMode">
+ <description>The selection mode for the Aal5TpVccTp's used by the IpAtmLink MO. Determines how the IpAtmLink MO selects the Aal5 termination points used.
+
+In case 'NO_PREFERENCE', 'LOCAL_MP_SELECT_VCC_AT_LINK_UP', LOCAL_MP_PEER_SELECTION_VCC' or 'LOCAL_MP_ACTIVE_RESELECTION' is selected the IpAtmLink MO will prefer Aal5TpVccTp on local MP (i.e. Aal5TpVccTp MOs executing on the same MP as the IpAtmLink), but other Aal5TpVccTp will be accepted if needed.
+
+In case 'ONLY_LOCAL_MP' is selected, the ipAtmLink (Inet Link) will consider Aal5TpVccTp residing on other MPs as a malfunction and discard the usage of them. No InvArp sending will be performed on them and all incomming trafic on them will be discarded. If no local Aal5TpVccTp exists the operational state of the link will be changed to disabled.
+
+ </description>
+ <dataType>
+ <enumRef name="Aal5TpSelectionModes">
+ <defaultValue>NO_PREFERENCE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="Aal5TpVccTpIdList">
+ <description>References to MOs of type Aal5TpVccTp representing the underlying AAL5 termination points (of a AAL5 PVC:s) for the IP over Atm link.
+
+The operator gives a list of relative distinguished names of the Aal5TpVccTp MO's to be used by the IP over ATM link.
+An Aal5TpVccTp MO may only be specified once in the list.
+
+To change in the set of Aal5TpVccTp MO's related to the IP over ATM link the link has to be deleted and then created with the desired set of AAL5 TP.
+
+Note! Only Aal5TpVccTp's that terminates on an MP (Main Processor) may be used when setting up IpAtmLink's.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <sequence>
+ <moRef name="Aal5TpVccTp"/>
+ <length>4</length>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInUcastPkts">
+ <description>Performance monitoring counter for the number of input unicast packets deliverred to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInNUcastPkts">
+ <description>Performance monitoring counter for the number of input broadcast/multicast packets deliverred to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfOutUcastPkts">
+ <description>Performance monitoring counter for the number of out unicast packets deliverred to higher layer</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfOutNUcastPkts">
+ <description>Performance monitoring counter for the number of output broadcast/multicast packets deliverred to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInErrors">
+ <description>Performance monitoring counter for the number of input packets discarded due to any error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInDiscards">
+ <description>Performance monitoring counter for the number of input packets discarded due to resource limitations.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfifOutDiscards">
+ <description>Performance monitoring counter for the number of outbound packets discarded due to resource limitations.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <action name="assignIpAddress">
+ <description>This action sets the IP address and the subnet mask.
+
+The changing of the IP address with the operation assignIpAddress, it might cause an interruption of the communication between the node and the network management tool. If an incorrect or erroneous IP address is configured, the communication with the node might be lost until the node is restarted or the IP address is changed to the correct value.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="ipAddress">
+ <description>The input format used by the operator is four fields of digits, separated by a dot. Each field consists of three digits.</description>
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="subnetMask">
+ <description>The input format used by the operator is four fields of digits, separated by a dot. Each field consists of three digits.</description>
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ </class>
+
+ <class name="EthernetLink">
+ <description>The Ethernet Link MO represents the Internet Protocol over Ethernet link. There is only one Ethernet link MO per Cello node.
+
+The changing of the IP address with operation assignIpAddress might cause interruption of the communication if the network management tool is connected via the ethernet link.
+
+Note: The EthernetLink MO can not be deleted!
+
+Note: The performance monitoring counters in the EthernetLink MO has a "Wrap-around time" of approximately 2 hours.
+</description>
+ <attribute name="userLabel">
+ <description>The User Label attribute gives the operator the possibility to label the links.
+
+</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ipAddress">
+ <description>The attribute ipAddress states the IP address of the Ethernet link, it is also the IP address for the O&amp;M host..
+
+The input format used by the operator is four fields of digits, separated by a dot. Each field consists of three digits.
+It must not be a broadcast or multicast address.
+
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="subnetMask">
+ <description>The attribute subnetMask states the subnet mask of the Ethernet link.
+
+The input format used by the operator is four fields of digits, separated by a dot. Each field consists of three digits.
+
+Note! The subnet mask has to contiguos. That is, it has the LSB set to 0 (zero).
+
+Example:
+
+255.255.255.X
+
+Contiguous subnet mask:
+11111111.11111111.11111111.11111110 (X = 254)
+11111111.11111111.11111111.11111100 (X = 252)
+
+Not-contiguous subnet mask:
+11111111.11111111.11111111.11111010 (X = 250)
+
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="broadcastAddress">
+ <description>The input format used by the operator is four fields of digits, separated by a dot. Each field consists of three digits.</description>
+ <mandatory/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="mtuSize">
+ <description>The IP layer expects the Ethernet link to have an MTU size (maximum Ethernet frame size without fragmentization) of 1500 bytes.
+
+The value is always the default value.
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>1500</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="metric">
+ <description>The attribute metric states the metric of the Ethernet link. The metric value is calculated as 10^8/link bit speed.
+
+For example:
+Metric for 10 Mbps Ethernet = 10^8/10^7 = 10
+Metric for 100 Mbps Ethernet = 10^8/10^8 = 1</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>32767</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the Ethernet link is dependent of the operational states of the underlying MAU:s that represents the Ethernet transceiver function. If at least one operational MAU exists, the operational state of the Ethernet Link is set to "ENABLED"</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="interfaceName">
+ <description>The interface name.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="macAddress">
+ <description>The mac address is persistently stored in flash prom on the MP where the IP stack resides. It is stored there at manufacturing. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <long/>
+ <length>6</length>
+ <nonUnique/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>If set, indicates that this EthernetLink is reserved by the OspfInterface MAO represented by this attribute.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="OspfInterface"/>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="EthernetLinkId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInUcastPkts">
+ <description>Performance monitoring counter for the number of input unicast packets deliverred to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInNUcastPkts">
+ <description>Performance monitoring counter for the number of input broadcast/multicast packets deliverred to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfOutUcastPkts">
+ <description>Performance monitoring counter for the number of out unicast packets deliverred to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInErrors">
+ <description>Performance monitoring counter for the number of input packets discarded due to any error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInDiscards">
+ <description>Performance monitoring counter for the number of input packets discarded due to resource limitations.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfOutNUcastPkts">
+ <description>Performance monitoring counter for the number of output broadcast/multicast packets deliverred to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfifOutDiscards">
+ <description>Performance monitoring counter for the number of outbound packets discarded due to resource limitations.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <action name="assignIpAddress">
+ <description>This action sets the IP address and the subnet mask.
+
+The changing of the IP address with the operation assignIpAddress,
+causes an interruption of the communication between the node and
+the network management tool. If an incorrect or erroneous IP address
+is configured, the communication with the node might be lost until
+the node is restarted or the IP address is changed to the correct
+value.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="ipAddress">
+ <description>The input format used by the operator is four fields of digits, separated by a dot. Each field consists of three digits.</description>
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="subnetMask">
+ <description>The input format used by the operator is four fields of digits, separated by a dot. Each field consists of three digits.</description>
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ </class>
+
+ <class name="IpRoutingTable">
+ <description>This MO holds the IP routing table.
+
+The IpRoutingTable MO is automatically created when the Ip MO is created.
+The IpRoutingTable MO can not be created manually.
+The IpRoutingTable MO can not be deleted.
+</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="indexOfDeletableStaticRoutes">
+ <description>This attribute gives the indexes for the static routes that are possible to delete by the operator.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="IpRoutingTableId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="addStaticRoute">
+ <description>Used to add a new static route to the routing table. It can be
+indicated if the static route should be redistributed by OSPF.
+When adding a static route with an ipaddress, which is not a subnet
+address, the ipaddress is recalculated to the corresponding subnet
+address, based on the ipaddress and the subnet mask. So when looking
+for this route using the action 'getRoutingTableEntry' it is in fact
+the recalculated ipaddress, that is displayed and not the ip address
+entered with addStaticRoute. This is an automatic correction.
+
+Note! If an attempt is made to add a static route with hopIpAddress starting with 0.0 an exception will be thrown.
+
+Note! This action requires a transaction.
+
+
+</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="ipAddress">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="subnetMask">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="hopIpAddress">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="routeMetric">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <parameter name="redistribute">
+ <in/>
+ <dataType>
+ <boolean/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="listRoutes">
+ <description>List routes actions is used to list all routes in the routing table. It requires no input parameters.
+
+The output is a formatted string, indicating the number of routes in the table followed by route information for each of these routes.
+
+The number of routes in the table is found at the very start of the returned string. Immediately following this is the information on each route in the list in turn. The route information for each route begins with a new line character ("\n") and is followed by the following data items (in the order written below), which are separated from each other by a SPACE character:
+
+- Destination IP address
+- Destination Network mask
+- Next hop IP address/Interface index of connected networks in dot-decimal format
+- Route metric
+- Route type
+- Interface name
+- Redistribute
+- Active
+
+Note that the next hop ipaddress is not an ipaddress per se, it is the subnet on wich the host/router to route to resides.
+
+Below is an example list of routes that could be returned from this action:
+
+"\n123.123.123.123 234.234.234.234 0.0.0.7 10 13 LE0 FALSE active\n122.122.122.122 233.233.233.233 0.0.0.6 2 8 LE0 TRUE active\n132.132.132.132 243.243.243.243. 0.0.0.7 9 13 LE0 TRUE inactive"
+
+In this case, there are three routes in the routing table. The first route has destination IP address of 123.123.123.123, the second route has it set to 122.122.122.122, while finally the third has it set to 132.132.132.132.
+
+NOTE that the route types can be of the following types:
+
+INET_RTPROTO_OTHER 1
+INET_RTPROTO_LOCAL 2
+INET_RTPROTO_NETMGMT 3
+INET_RTPROTO_ICMP 4
+INET_RTPROTO_OSPF 13
+
+The types listed above also denote the origin of the routing entry.
+
+Note! This action does not require a transaction.
+</description>
+ <returnType>
+ <string/>
+ </returnType>
+ </action>
+ <action name="getRoutingTableEntry">
+ <description>Returns a RoutingTableEntry according to the specified index.
+
+Should be used with action 'numberOfRoutes' within a transaction. To refresh the routing table stored in the MO, invoke the action 'numberOfRoutes'.
+
+Precondition: 0 &lt;= index &lt;= numberOfRoutes() - 1
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <structRef name="RoutingTableEntry"/>
+ </returnType>
+ <parameter name="index">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="InvalidIndexException"/>
+ </action>
+ <action name="numberOfRoutes">
+ <description>Returns the number of entries in the routing table.
+
+Each time this action is invoked, the MO retrieves routing table information from the resource layer and then builds a new array of RoutingTable structs to store this information.
+
+This action along with getRoutingTableEntry(), which allows one to iterate through the array stored in the MO, should be used together with a transaction.</description>
+ <returnType>
+ <long/>
+ </returnType>
+ </action>
+ <action name="deleteStaticRoute">
+ <description>Removes the RoutingTableEntry submitted as a parameter from the Routing Table, if it is found in the table.
+
+Note that only static roues, previously added, can be deleted with this action.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="routingTableEntry">
+ <in/>
+ <dataType>
+ <structRef name="RoutingTableEntry"/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ </class>
+
+ <class name="Ip">
+ <description>The Ip MO represents the IP protocol layer with IP forwarding functionality.
+
+Note: The performance monitoring counters in the Ip MO has a "Wrap-around time" of approximately 2 hours.
+
+</description>
+ <attribute name="IpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="workingMode">
+ <description>The workingMode of the IP MO controls if the IP stack in the node will work as a combined host/router (routerMode) or only as a host (hostMode).</description>
+ <mandatory/>
+ <dataType>
+ <enumRef name="WorkingMode">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="retransInterval">
+ <description>The retransmission interval. The units are seconds.
+Must be a value &gt; 0.</description>
+ <dataType>
+ <long>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="noOfRetrans">
+ <description>The number of retransmissions.
+Must be a value &gt; 0.</description>
+ <dataType>
+ <long>
+ <defaultValue>5</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="dnsServer">
+ <description>The Domain Name Server IP address.
+
+The IP address must be a Unicast IP address.
+</description>
+ <dataType>
+ <string>
+ <defaultValue>"127.0.0.1"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="isRecursiveSearch">
+ <description>Holds information about how the DNS client wants the DNS server do the search for the IP address in the network . It can be either Recursive search or Non-recursive search.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="isSubDomainName">
+ <description>Holds information about whether to use subsets of the fully qualified domain name to reach the simple domain name. It can be either Use subsets of domain name or Not use subsets of domain name.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="isDefDomainName">
+ <description>Holds information about whether the default domain name is present. It can be Present or Not present.
+
+</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="defDomainName">
+ <description>Contains default domain name.
+If 'isDefDomainName' is set to 'true' the domain name found in this attribute is used by the DNS resolver and there is no need to submit the complete domain name. If the domain name is for example 'ws5741.uab.ericsson.se' then the default domain name would be '.uab.ericsson.se'. If 'isDefDomainName' is set to true the there is no need for using '.uab.ericsson.se'. If set to false then the complete domain name has to be used.
+A valid domain name consists of 1 or more labels separated by dots (".").
+Valid characters for a label shall be limited to letters 'a' - 'z', 'A' - 'Z', digits '0' - '9', the character '-' ("dash").
+Character case shall be preserved. Labels shall start with a letter. Total length of a label shall not exceed 255 characters.
+
+Note! The first and last character in the domain name has to be within the following alphabet: letters 'a' - 'z', 'A' - 'Z' and digits '0' - '9'. For more information refer to RFC 952 and 1101.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the IP MO is ENABLED if at least one link is operational.
+
+Shows whether the MO is OK (enabled) or failed (disabled). The values are set by the system.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="numberOfLinks">
+ <description>Represents the number of interfaces (Ethernet and IP over
+ATM links) which has registered to the IP MO.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>If set, indicates that this Ip is reserved by the Ospf represented by this attribute.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Ospf"/>
+ </dataType>
+ </attribute>
+ <attribute name="useHostFile">
+ <description>Indicates if the hosts file should be used or not. The hostFile is used by the resolver and
+chosen as a source of information before querying a DNS server.
+
+true - use the host file.
+false - do not use the host file.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="dscp">
+ <description>The DiffServ CodePoint.
+The code point values are used by DiffServ enabled hosts and router to identify different service levels.
+When set, the DSCPs are mapped to PHBs (Per Hop Behaviours) by forwarding devices along the path
+between the source and destination. PHBs dictates how each packet will be handled i.e. what type of
+service that is applied to the packet when it is forwarded.
+
+Note! Only traffic originated from the node is tagged with the dscp value. The Cello router does not implement functionality for handling different service levels when routing IP traffic.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>63</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="icmpRedirect">
+ <description>Indicates if ICMP redirects is sent out or not.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="udpChecksumState">
+ <description>Enable/Disable generation of UDP checksum.
+0 = disabled
+1 = enabled
+
+The UDP checksum is used for verifying that the UDP header has not been damaged during transmit.</description>
+ <dataType>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="connectionAttemptTimer">
+ <description>The time that elapses before a connection (TCP) attempt times out.
+
+Unit is seconds.</description>
+ <dataType>
+ <long>
+ <defaultValue>75</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxRetransmissionAttempts">
+ <description>The maximum number of retransmission attempts before a TCP connection is dropped.
+The default value is 10 attempts, which is around 5 minutes.
+Setting this attribute value to -1 means infinity, and TCP will never give up in trying
+to establish a connection.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>-1</min>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIpInReceives">
+ <description>Performance monitoring counter for total number of datagrams received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfHdrErrors">
+ <description>Performance monitoring counter for the number of datagrams discarded due to format error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIpAddrErrors">
+ <description>Performance monitoring counter for the number of datagrams discarded due to misdelivery.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIpForwDatagrams">
+ <description>Performance monitoring counter for the number of datagrams forwarded.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIpInDiscards">
+ <description>Performance monitoring counter for the number of datagrams dascarded due to resource limitations.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIpOutDiscards">
+ <description>Performance monitoring counter for the number of datagrams discarded due to lack of resources.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIpReasmReqds">
+ <description>Performance monitoring counter for the number of fragments received needing reassembly.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIpReasmOKs">
+ <description>Performance monitoring counter for the number of datagrams successfully reassembled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="SccpEntitySet">
+ <description>This MO represents an SCCP EntitySet which is made of one SCCP Entity. An SCCP Entity is a local MTP-SAP + a DPC + possibly an SSN, i.e an SCCP EntitySet identifies the set of access points that result from a global title translation. An SCCP EntitySet may also be made of two SCCP Entities of the same type (if an SSN is present in one SCCP Entity, then an SSN shall also be present in the other). In the latter case the two SCCP entities may be considered either as a "primary" SCCP Entity and a "backup" SCCP Entity (dupli-dominant mode) or may be interpreted as two equal SCCP entities that can be used for outgoing loadsharing purpose. In this implementation they can only be considered as "primary" and "backup".The Routing Indicator (RI) in the Called Party Address is normally not set by the SCCP for outgoing messages and should therefore be set by the user. This means that if the user has set "Route on SSN" this will be the case after the GTT also even if the set consist of MTP-3b Access Points. However, if the set consists of SCCP Access Points the RI is implicitly set to "Route on SSN" by SCCP.
+
+DPC Destination Point Code
+GTT Global Title Translation
+MTP Message Transfer Part
+SAP Signalling Access Point
+SSN Subsystem Number
+
+Note: the SccpEntitySet MO depends either on MAOs of type SccpApLocal OR SccpApRemote, not on a mixture of these MAO types.</description>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="routeIds">
+ <description>The Entity Set routeId is an array of maximum two instances of Sccp ApLocal MO's OR two instances of SccpApRemote MO's OR two instances of Mtp3bAp MO's OR one instance of SccpSP MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ <length>2</length>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="sharingMode">
+ <description>The sharingMode attribute controls the distribution of SCCP traffic over the entities (Access Points) in the set.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="SharingMode">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="newSubSystemNumber">
+ <description>The new sub system number attribute is only valid if the Mtp3b Access Points are used in the set. In that case the SSN attribute allows to optionally set the subsystem number in the Called Party Address as a result of a Global Title Translation. If the set consists of SCCP Access Points the subsystem number in the Called Party Address is always implicitly set to the SCCP Access Point SAP (SSN) as a result of a Global Title Translation.
+This attribute is controlled by the type of AP(s) that the EntitySet refers to.
+
+The default value 0 means no new subsystem number.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>254</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="newGlobalTitle">
+ <description>The New Global Title attribute allows to optionally replace the global title in the Called Party Address as a result of a Global Title Translation (GTT). If the GT resulting from a GTT is different from the GT previously included in the Called Party Address, the newly produced GT replaces the existing one. The gtIndicator attribute is read-only and is derived from the combination of Nature Of Address, the Translation Type and Numbering Plan used.
+
+Default value is considered as no new Global Title.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="GlobalTitleData"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds a list of the reserving MO's.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="SccpEntitySetId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="SccpGlobalTitle">
+ <description>The SCCP Global Title MO represents a combination of a global title translator and a global title rule. If no Destination Point Code (DPC) is present in the Called Party Address, a Global Title (GT) is needed. Then a global title must be present in the Called Party Address, otherwise a routing error occurs. A global title translator is selected by SCCP based on a combination of the values of the Nature Of Address (NA), the translation type (TT), and the Numbering Plan (NP) if available, in this MO matched with the same information in the Called Party Address provided by an SCCP user. A global title translation rule is selected by SCCP by matching the Global Title Address Information and possibly the Encoding Scheme in this MO, with the same information in the Called Party Address provided by an SCCP user. A global title translation rule points to the SCCP Entity Set resulting from the global title translation (GTT).
+The translation results in a DPC and possibly a new Sub System Number (SSN) or GT or both (decided by the SCCP Entity Set it refers to). If the GT and/or SSN resulting from a GTT is different from the GT and/or SSN previously included in the Called Party Address, the newly produced GT and/or SSN replaces the existing one.
+
+GT - Global Title
+SCCP - Signalling Connection Control Part
+SSN - Sub System Number
+DPC - Destination Point Code
+TT - Translation Type
+GTT - Global Title Translation</description>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="gtIndicator">
+ <description>Global title indicator for China, ITU, TTC and ANSI.
+
+
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="GlobalTitleIndicator">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="natureOfAddress">
+ <description>Indicates number type, i.e. national or international number.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="NatureOfAddress">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="numberingPlan">
+ <description>Indicates which numbering plan that is used.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="NumberingPlan">
+ <defaultValue>UNKNOWN</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="translationType">
+ <description>Used to direct the message to the appropriate Global Title translation function.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>254</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="addressInformation">
+ <description>Digit string of 1-37 digits, where each digit is 0-9, and "B", "C". "B" and "C" are for Code 11 and Code 12.
+The addressInformation may also contain wild card symbols: "*" or "?". Wild cards are only allowed for defining Global Title Translations, they are not allowed for specifying SCCP SAPs (built with SPC and Global Title or SPC + SSN + Global Title).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>37</max>
+ </lengthRange>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="encodingScheme">
+ <description>Indicates if the number of address signals are an odd or even number.
+
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="EncodingScheme">
+ <defaultValue>UNKNOWN</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="sccpEntitySetId">
+ <description>The sccpEntitySetId attribute points out the corresponding SccpEntitySet MO.
+
+Note! This attribute is only optional if this MO is used by Policing. In all other cases it has to be set.</description>
+ <noNotification/>
+ <dataType>
+ <moRef name="SccpEntitySet"/>
+ </dataType>
+ </attribute>
+ <attribute name="SccpGlobalTitleId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Aal2PathVccTp">
+ <description>This MO is used to represent an AAL2 Path, i.e. an ATM VC connection that carries multiplexed AAL2 links.
+
+VCC TP - Virtual Channel Connection Termination Point.
+
+The total number of Aal2PathVccTps associated to an Aal2Ap, by connecting them to Aal2PathDistributionUnits under that Aal2Ap, must not exceed 632.
+
+The total number of Aal2PathVccTps associated to a ReliableProgramUniter, by connecting them to Aal2PathDistributionUnits associated to the ReliableProgramUniter, must not exceed 280.
+
+Note! The performance monitoring counters in this MO is set to 0 when counterMode is set to PM_MODE_ON.
+In PM_MODE_OFF no information at all is retrived. So any value for pm-monitoring is measured from the time of setting counterMode to PM_MODE_ON.
+At node restart these performance monitoring counters is reset to 0.
+</description>
+ <attribute name="Aal2PathVccTpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="vclTpId">
+ <description>Reference to the VclTp to be used by this Aal2PathVccTp.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="VclTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of the termination point. </description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>unlocked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Operational state of the termination point.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving Aal2PathDistribution MO.
+
+</description>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status of Aal2PathVccTp.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="continuityCheck">
+ <description>Continuitiy checking means that a cell is sent downstream when no user cell has been sent for a period of nominally 1 second.
+
+Activates VC end to end continuityCheck according to ITU.T rec I.610.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="counterMode">
+ <description>PM mode is set to indicate type of performance monitoring mode (ie. activation of bidirectional PM measurements).
+
+</description>
+ <dataType>
+ <enumRef name="AtmCounterMode">
+ <defaultValue>PM_MODE_OFF</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="nomPmBlocksize">
+ <description>Nominal performance monitoring (PM) blocksize. The minimum number of ATM cells to send before sending a Forward Performance Monitoring, FPM, cell.</description>
+ <dataType>
+ <enumRef name="AtmNomPmBlkSize">
+ <defaultValue>NOM_PM_BLKSIZE_2_10</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="timerCu">
+ <description>Timer that assures that CPS-packets with one or more octets already packed in the ATM cell wait at most the duration of timerCu before being scheduled for transmission.
+
+Units for timerCu is 10 to the power of -4 seconds. This value can be set in steps of 10 to the power of -4.
+
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="aal2PathId">
+ <description>This attribute is used to identify the path in the Q.2630.1 protocol.
+
+The pathId value must be unique within all Aal2PathDistributionUnits under the same Aal2Ap
+
+All integers &gt; 0 are allowed (not 0).
+
+The Aal2PathId is used by the Aal2 connection control function in two Aal2 nodes to uniquely identify an AAL2 path between the two nodes. This means that the value of the attribute Aal2PathId for an Aal2 path must be the same in each of the two nodes.
+
+In order to set this attribute, the Aal2PathVccTp may not be reserved. If an attempt is made, an "IsReservedCanNotSetPathId" exception is thrown.
+
+Note! Setting of this attribute will not have any effect until 'actionAddPath' in Aal2PathDistributionUnit MO' is called adding this MO to the list of Aal2PathVccTp MO's.</description>
+ <mandatory/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>2147483647</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="aal2PathOwner">
+ <description>This attribute indicates whether this Aal2 Path VCC Termination Point is considered the owner of the Aal2 Path in order to decide channel selection procedure in the Q.2630.1 protocol.
+
+Note! In order to set this attribute, the Aal2PathVccTp may not be reserved. If an attempt is made, an "IsReservedCanNotSetPathId" exception is thrown.
+
+Note! The administrativeState has to be LOCKED when this attribute is set, if not the "IsUnlockedCanNotSetPathOwner" exception is thrown.
+
+Note! Setting of this attribute will not have any effect until 'actionAddPath' in Aal2PathDistributionUnit MO' is called adding this MO to the list of Aal2PathVccTp MO's.</description>
+ <mandatory/>
+ <dataType>
+ <boolean/>
+ </dataType>
+ </attribute>
+ <attribute name="alarmReport">
+ <description>Attribute to decide what type of alarms to be reported.</description>
+ <dataType>
+ <enumRef name="AlarmReport">
+ <defaultValue>ALARM_LOC</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="aal2QoSProfileId">
+ <description>The identity of the QosProfile used by the Aal2PathVccTp.</description>
+ <mandatory/>
+ <dataType>
+ <moRef name="Aal2QosProfile"/>
+ </dataType>
+ </attribute>
+ <attribute name="aal2QoSAvailableProfiles">
+ <description>This attribute specifies which QoSClass that can be supported by this Aal2Path.
+</description>
+ <dataType>
+ <enumRef name="SupportedQoSClasses">
+ <defaultValue>CLASS_A_B_C_D</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwLostCells">
+ <description>Performance monitoring counter for forwarded lost cells.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwMissinsCells">
+ <description>Performance monitoring counter for number of forwarded missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwErrBlocks">
+ <description>Performance monitoring counter for number of forwarded errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostFpmCells">
+ <description>Performance monitoring counter for number of lost Forward Performance Monitoring, FPM cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwLostCells">
+ <description>Performance monitoring counter for number of lost backward cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwMissinsCells">
+ <description>Performance monitoring counter for number of backward missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwErrBlocks">
+ <description>Performance monitoring counter for number of backward errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostBrCells">
+ <description>Performance monitoring counter for number of lost Backward Reporting, BR, cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Aal2RoutingCase">
+ <description>This MO represents a AAL2 routing case which points out an AAL2 access point. </description>
+ <attribute name="Aal2RoutingCaseId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>For free use</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="routeList">
+ <description>An array of alternative routes identified by the concerned Aal2Ap MOs. A routeList can have 0 to 5 Aal2Aps.
+The Aal2Ap must be unique.
+Note! if this attribute is set, the routePriorityList also must be se with the same number of values ( if the routeList
+contains 3 routes, the routePriorityList must contain 3 prioritys).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <restricted/>
+ <dataType>
+ <sequence>
+ <moRef name="Aal2Ap"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="routePriorityList">
+ <description>A list of all the Aal2Ap priorities.
+The priority values can be in the range 1 to 5, one beeing the highest priority.
+The Aal2Aps can have the same priorities.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <restricted/>
+ <dataType>
+ <sequence>
+ <long>
+ <range>
+ <min>0</min> <max>5</max>
+ </range>
+ </long>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="numberDirection">
+ <description>Defines the possible set of AAL type 2 Service Endpoint Addresses (A2EA) that match the routing case.
+
+The number direction of a routing case shall be interpreted as all AAL type 2 Service Endpoint Addresses
+starting with the string of numbers defined in the number direction. For example, the AAL2 End System
+Addresses "12340" and "123400" will both match the number direction "1234".
+
+The AAL2 routing function uses a longest match comparison to select between routing cases with overlapping
+number directions. For example, given two routing cases A with the number direction "1234" and B with the number
+direction "12345" the AAL2 End System Address "12345" will be routed using routing case B, whereas the AAL
+type 2 Service Endpoint Addresses "12344" and "12346" will be routed using routing case A.
+
+NOTE: It is not allowed to use leading zeros when configuring this attribute.
+
+NOTE: It is not possible to replace an existing routing case by creating routing cases with number directions that
+completely overlap the number direction of the existing routing case.
+
+NOTE: It is not possible to create two routing cases with the exact same number directions in a node.
+
+NOTE: It is possible to create one or more routing cases with number directions that partially overlap the number
+direction of an existing routing case.
+
+Length range 1..15
+Alphabet: "0123456789"
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>15</max>
+ </lengthRange>
+ </string>
+ </dataType>
+ </attribute>
+ <action name="addAal2ApToRc">
+ <description>Adds the identified (and existing) Aal2Ap MO to the routeList. This action should also be used when changing the priority for an existing Aal2Ap MO. When submitting an existing Aal2Ap MO with a new priority the routing list will be updated with the new priority for the specified Aal2Ap MO.
+
+Note! In order to be able to update the priority for a routing entry, the routing entry first has to be deleted and then submitted with the new priority.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="priority">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <parameter name="route">
+ <in/>
+ <dataType>
+ <moRef name="Aal2Ap"/>
+ </dataType>
+ </parameter>
+ <raisesException name="InvalidPriorityException"/>
+ <raisesException name="IllegalArgumentTypeException"/>
+ <raisesException name="IllegalAttributeValueException"/>
+ </action>
+ <action name="removeAal2ApFromRc">
+ <description>Removes the identified Aal2Ap MO from the routeList.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="route">
+ <in/>
+ <dataType>
+ <moRef name="Aal2Ap"/>
+ </dataType>
+ </parameter>
+ <raisesException name="IllegalAttributeValueException"/>
+ <raisesException name="IllegalArgumentTypeException"/>
+ </action>
+ </class>
+
+ <class name="Aal2Sp">
+ <description>The Aal2Sp (AAL2 Signalling Point) MO is used to represent the AAL type 2 Service Endpoint Address of the node in the AAL2 network.
+There is one and only one instance of this MO in the ATM NE system.</description>
+ <attribute name="userLabel">
+ <description>For free use</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="a2ea">
+ <description>An E.164 format number that specifies the AAL type 2 Service Endpoint Address of the node.
+
+Length Range: 1..15
+Alphabet: "0123456789"
+
+Note! It is not allowed to use leading zeros when configuring this attribute.</description>
+ <mandatory/>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>15</max>
+ </lengthRange>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="Aal2SpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="pmUnsuccessfulConnsInternal">
+ <description>Performance monitoring counter for the number of unsuccessful attempts to establish connections due to node internal problems.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Aal2Ap">
+ <description>This MO represents a AAL2 Access Point signalling function associated with a single AAL2 signalling relationship to a remote peer AAL2 acess point signalling function. An AAL2 access point is either a high rate access point that uses MTP-3B for signalling or a low rate access point that uses UNI-SAAL for signalling.
+
+Aal2Ap - Aal2 Access Point
+
+Note! The performance monitoring counters in the AalAp MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.</description>
+ <attribute name="Aal2ApId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Free for use</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>This attribute holds a list of the reserving MOs.
+</description>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Operational state of the AAL2 AP.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status of the Aal2Ap.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="timerErq">
+ <description>Q.2630.2 establishment request timer. Unit is milli seconds.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>5000</min> <max>30000</max>
+ </range>
+ <defaultValue>5000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="timerRel">
+ <description>Q.2630.2 release request timer. Unit is milli seconds.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>2000</min> <max>60000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="sigLinkId">
+ <description>Reference to a UniSaalTp or Mtp3bAp MO that provides a signalling link for the Aal2Ap.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="secondarySigLinkId">
+ <description>Reference to a secondary signalling link MO of type UniSaalTp. This attribute can only be set when sigLinkId is of type UniSaalTp.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="rpuId">
+ <description>The physical location of an AP (Access Point) LR/HR (Low Rate/ High Rate) program represented by a reference to a RPU (ReliableProgramUniter) MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ReliableProgramUniter"/>
+ </dataType>
+ </attribute>
+ <attribute name="aal2QoSCodePointProfileId">
+ <description>The identity of the QoSCodePointProfile used by this MO.</description>
+ <dataType>
+ <moRef name="Aal2QosCodePointProfile"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmExisOrigConns">
+ <description>Performance monitoring counter pmExisOrigConns.
+Number of existing connections for the AP originating in this node.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="nrOfConfiguredAal2Paths">
+ <description>The total number of Aal2PathVccTp MOs configured on this Aal2 Ap.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="nrOfUnavailableAal2Paths">
+ <description>The total number of unavailable Aal2PathVccTp's on this Aal2 Ap, i.e. the number of Aal2PathVccTp MOs connectected to this Aal2Ap with 'administrativeState' LOCKED.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmExisTermConns">
+ <description>Performance monitoring counter pmExisTermConns.
+Number of existing connections for the AP terminating in this node.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmExisTransConns">
+ <description>Performance monitoring counter pmExisTransConns.
+Number of existing connections for the AP transiting in this node.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSuccOutConnsRemote">
+ <description>Performance monitoring counter pmSuccOutConnsRemote.
+Number of successful establishment of outgoing connections on this AP</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSuccInConnsRemote">
+ <description>Performance monitoring counter pmSuccInConnsRemote.
+Number of successful establishment of incoming connections on this AP.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUnSuccInConnsRemote">
+ <description>Performance monitoring counter pmUnSuccInConnsRemote.
+
+Number of unsuccessful establishment of incoming connections on this AP caused by reject from beyond this node.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUnSuccOutConnsRemote">
+ <description>Performance monitoring counter pmUnSuccOutConnsRemote.
+
+Number of unsuccessful establishment of outgoing connections on this AP caused by reject from remote side, reset from remote side, no reply or signalling link failure.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUnSuccInConnsLocal">
+ <description>Performance monitoring counter pmUnSuccInConnsLocal.
+Number of unsuccessful attempts to allocate Common Part Sublayer, CPS, resources during establishment of incoming connections on this AP caused by Channel Identifier, CID, and/or bandwidth collision or mismatch of Call Admission Control, CAC, between peers.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUnSuccOutConnsLocal">
+ <description>Performance monitoring counter pmUnSuccOutConnsLocal.
+
+Number of unsuccessful attempts to allocate CPS resources during establishment of outgoing connections on this AP. Caused by rejects in CAC (Connections Admission Control).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUnRecMessages">
+ <description>Performance monitoring counter pmUnRecMessages.
+
+Number of received unrecognized Q.2630.1 messages on this AP.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUnRecParams">
+ <description>Performance monitoring counter pmUnRecParams.
+
+Number of received Q.2630.1 messages with unrecognized parameters on this AP.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Etm1">
+ <description>This MO represents the hardware of the ET-M1 board type. It only represents the ET specific hardware, while the DBM module of the board is represented by the PlugInUnit MO.
+
+The ET-M1 board contains 8 physical ports that can be configured as either E1 (ETSI), J1 (TTC) or T1(ANSI). The board does not allow for a mix of E1, J1 and T1 ports, thus all configured ports on the board must be configured to the same standard.
+
+Each of the ports on the ET-M1 board can be used to carry either ATM traffic or circuit orientated (Nx64 Kbits/s connections) traffic.
+
+Each port can support up to 30 ATM VC connections. Two of these connections are reserved for AAL2 paths, and therefore two AAL2 multiplexers per port are available.
+
+Each port can support up to 2 VP connections.
+
+The ET-M1 board supports 1 bidirectional F4/F5 PM flow per port.
+
+Other restrictions:
+- All ports (configured for ATM) on the board must have the same value for the hecCorrection attribute (ATM Port MO).
+- It is possible to configure UBR+ traffic, but there is no guarantee on the minimum cell rate.
+- VP shaping is not supported (it is recommended to configure at most one VP per physical port).
+- VC shaping is not supported with an exception for AAL2 path traffic. This is shaped to the peak bandwidth on the VC connection.
+- When using the Etm1 board the performance monitoring counters in the transmit direction found on the AtmPort MO does not show the following cells: CC cells and OAM FPM cells.
+
+Note! IMA is not applicable for the ETM1 board.
+
+Note! When using fractional atm, timeslot 1 must be a part of the fraction.
+
+Note! ETM1 does not support EPD and PPD
+
+Note! ETM1 does not have a proper buffer management. Thus fairness of UBR+ traffic can not be guaranteed and shaping on UBR+ traffic is not possible.
+
+Note! The number of VCC TP+VPC TP with performance monitoring enabled (i.e. PM mode &lt;&gt; off) is restricted to 1 per port.
+</description>
+ <attribute name="userLabel">
+ <description>user label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Enabled or disabled according to the actual operational state of the Etm1 board.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="Etm1Id">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="TuSyncRef">
+ <description>This MO is used to administer synchronization reference (a synchronization input with support for 2MHz and 10MHz signals) on Timing Unit board.</description>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Operational state of TU synchronization reference</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>Administrative state of TU synchronization reference</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status of the TuSyncRef.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>When the TU synchronization reference is registered in the system as an usable synchronization reference, this MO reference is set by using "local" operation syncReserve(). When synchronization reference is de registered, "local" operation syncRelease is used. Note that the only valid user of these operations is Synchronization MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Synchronization"/>
+ </dataType>
+ </attribute>
+ <attribute name="TuSyncRefId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Spm">
+ <description>The Special purpose Processor Module MO, Spm, represents one of the Special Purpose Processors and its connected hardware. This object is used for SW management and restart. Hardware failure indications are sent to Spu.
+
+Note! If the board is of type SPB1 the maximum number of Spm MO's that is possible to create under the Spu MO is 3.
+If the board is of type SPB2 the maximum number of Spm MO's that is possible to create under the Spu MO is 5.</description>
+ <attribute name="SpmId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>user label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the SPM</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="switchModuleNumber">
+ <description>Switch Module Number</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="asciPortNumber">
+ <description>ASCI Port Number</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="executionResourceNumber">
+ <description>The identity of the SPM on the Special purpose Processor Unit (SPU).
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="runningResourceIdList">
+ <description>The list of identities of running Spm's
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <long/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="installedResourceIdList">
+ <description>The list of identities of installed Spm's in the system.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <long/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="spLinkName">
+ <description>The uniqe name of the link between the SP and BP.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <action name="restart">
+ <description>Restarts the SP.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ </class>
+
+ <class name="Spu">
+ <description>The Special purpose Processor Unit MO, Spu, represents the board specific HW on SPB. This objects collects HW failure indications on the board and issues/ceases alarms.</description>
+ <attribute name="userLabel">
+ <description>user label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the SPB board.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="spLinkName">
+ <description>The special purpose processor link name.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="SpuId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="restart">
+ <description>Restarts all SPs on the board (but not the BP).
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroNotAccessibleException"/>
+ </action>
+ </class>
+
+ <class name="AtmCrossConnection">
+ <description>This MO is used to represent the point-to-point ATM cross-connect relationship between two VCL termination points.</description>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Operational state for the cross connection.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="vclTpAId">
+ <description>Identifies the VclTp managed object involved in the A side of the cross connection (which consists of an A and B side).
+
+Must not be the same as vclTpBId.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="VclTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="vclTpBId">
+ <description>Identifies the VclTp managed object involved in the B side of the cross connection (which consists of an A and B side).
+
+Must not be the same as vclTpAId.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="VclTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="AtmCrossConnectionId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="ConfigurationVersion">
+ <description>The Configuration Version, CV, is an MO managing all on disk saved node configuration. This MO keeps all administrative data about the CV's including path and file-names of the configuration files. There may be more than one CV on the disk but only one is used at the time. A CV is always based on one Upgrade Package.
+
+The local distinguished name of this MO is ManagedElement=1, SwManagement=1, ConfigurationVersion=1.</description>
+ <systemCreated/>
+ <attribute name="ConfigurationVersionId">
+ <description>Configuration version MO's id.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="storedConfigurationVersions">
+ <description>List of stored configuration versions in the node.
+
+Stored in and read from the file system.
+
+List of stored configuration versions (CV) in the node.
+
+The list is a sequence of CVs.
+Each CV is presented as structure. A CV structure has following fields:
+ 1. Name
+ 2. Identity
+ 3. Type
+ 4. UpgradePackageId
+ 5. Operator name
+ 6. Comment
+ 7. Date
+ 8. Status
+
+The CV list is formatted as a sequence of ConfigurationVersionAttributes.
+Each struct contains one CV.
+
+The following characters are allowed within the struct members below.
+
+[0-9], [A-Z], [a-z] and '&amp;' , '%' , ':' , '.' , '_' , '-'
+
+Note! For comment and operatorName spaces (' ') are also allowed within the strings.
+
+Struct element description :
+-Name is in string format, max length is 40.
+-Identity is in string format, max length is 40.
+-Type is in string format, max length is 40.
+-UpgradePackageId is in string format, max length is 40.
+-Operator name is in string format, max length is 40.
+-Comment is in string format, max length is 40.
+-Date is in string format, max length is 40. Format for date is: weekday month date hour:min:seconds year.
+-Status is in string format, max length is 40.
+
+Note! The identity can not be the same as name. Identity should contain the product identity.
+
+
+</description>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <structRef name="ConfigurationVersionAttributes"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="currentLoadedConfigurationVersion">
+ <description>The name of the current loaded configuration version.
+
+Stored in and read from the file system.
+
+This is the configuration version that the system started with, i.e. the configuration version that was startable at the last node restart. </description>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="startableConfigurationVersion">
+ <description>The name of the configuration version that will be used at next node restart.
+
+Stored in and read from the file system.
+
+This attribute is set by the action "setStartable( name of cv)".
+Also set at rollback by the system. The first CV in the rollback list is then used.</description>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="rollbackList">
+ <description>A list of configuration versions to rollback to (configuration version name).
+
+The configuration version on the first line is used at the next rollback. That line is then automatically removed from the rollback list.
+
+This attribute is modified by actions setFirstRollbackList() and removeFromRollbackList()</description>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="currentUpgradePackage">
+ <description>A reference to current executing upgrade package.</description>
+ <readOnly/>
+ <dataType>
+ <moRef name="UpgradePackage"/>
+ </dataType>
+ </attribute>
+ <attribute name="autoCreatedCVIsTurnedOn">
+ <description>Flag that indicates that a configuration version will be created automatically once a day.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="timeForAutoCreatedCV">
+ <description>Time for the automatic creation of configuration versions once a day.
+
+The string must be specified as "HH:MM" to be accepted at set.
+
+See also Class Attribute autoCreatedCVIsTurnedOn.
+The time is UTC time.
+
+Note! If changing the clock on the node, this attribute must be set or
+the JVM MP must be reastarted.
+
+
+</description>
+ <dataType>
+ <string>
+ <defaultValue>"04:00"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="rollbackOn">
+ <description>Flag that indicates if rollback is enabled or not.
+When true the system will automatically set the rollback counter. In case of cyclic restarts a rollback will be issued after x restarts. x is defined by the rollbackInitCounterValue.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="rollbackInitTimerValue">
+ <description>Used by the system when rollback is switched on (autoRollbackOn=true). After the given time the node is considered not in a cyclic restart mode. The rollback counter will then be reset to its initial value (rollbackInitCounterValue).
+
+Timer value in minutes.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>10000</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="rollbackInitCounterValue">
+ <description>Initial value for the rollback counter. Used when rollback is switched on (autoRollbackOn=true).
+
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>10000</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="commandlogStatus">
+ <description>An attribute to indicate status of command log.
+It can be ON/OFF(true/false). </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="executingCv">
+ <description>The name of the executing Configuration Version, CV.
+
+Same as 'currentLoadedConfigurationVersion' after a node restart, changed to the value of lastCreatedCv when a CV is created.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="lastCreatedCv">
+ <description>The name of the last created Configuration Version, CV.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <action name="setStartable">
+ <description>The CV given will be the one used at the normal node restarts. Only A CV with status = OK can be set as startable.
+
+This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="configurationVersionName">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="create">
+ <description>A new CV directory will be created. A DB backup from the current RAM CV,
+an ARMAMENT file and the file LLP:LMid is created at the directory. The current
+command log file is copied to the CV directory first, then it removes the file from
+the current directory.
+
+Note: The file cmdlog.properties under /c/ will not be saved to the CV.
+
+The following characters are allowed in the Strings:
+
+[0-9], [A-Z], [a-z] and '&amp;' , '%' , ':' , '.' , '_' , '-'
+
+Note! For comment and operatorName spaces (' ') are also allowed within the strings
+
+-configurationVersionName is in string format, max length is 40 characters.
+-identity is in string format, max length is 40 characters.
+-operatorName is in string format, max length is 40 characters.
+-comment is in string format, max length is 40 characters.
+
+This action does not require a transaction.
+
+Note! The configurationVersionName and identity can not be the same. The identity should be the product identity.
+</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="configurationVersionName">
+ <description>One ASCII text string. It must be possible to create a directory with string. Do not use string "autocreated1" and "autocreated2" as cv name. They are used by the system.</description>
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="identity">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="type">
+ <description>Type of the configuration version [ standard | test | other ].</description>
+ <in/>
+ <dataType>
+ <enumRef name="ConfigurationVersionType">
+ <defaultValue>other</defaultValue>
+ </enumRef>
+ </dataType>
+ </parameter>
+ <parameter name="operatorName">
+ <description>The operator's name.</description>
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="comment">
+ <description>The operator's comment.</description>
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <raisesException name="ValueOutOfRangeException"/>
+ </action>
+ <action name="delete">
+ <description>Delete a configuration version (CV) permanently.
+
+If CV is referenced in the startable or in the rollback list, the action is not performed (an exception is thrown instead).
+
+Note! The latest created CV is not deletable until a node restart is performed or a new CV is created. Also note that a CV is not possible to delete when it has one of the folowing properties:
+- "loaded"
+- "startable"
+- The CV is found in the "rollbacklist"
+
+This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="configurationVersionName">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="removeFromRollbackList">
+ <description>Removes a Configuration Version (CV) from the rollback list.
+
+This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="configurationVersionName">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="setFirstRollbackList">
+ <description>Adds a Configuration Version (CV) first in the rollback list. This will cause the node to chose this CV at the next rollback. A CV with status NOK, can't be put in the rollback list.
+
+This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="configurationVersionName">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="activateCommandLog">
+ <description>This action activates the log.
+
+The inparameter is the drive name (where the command log file should be stored).
+
+Default command log is drive /c/.
+
+Note! Invoking this action affects the attribute'commandLogStatus'.
+
+Note! This action does not require a transaction.
+</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="cmdlogdriveName">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <raisesException name="InvalidDriveNameException"/>
+ <raisesException name="LogActivationException"/>
+ </action>
+ <action name="deactivateCommandLog">
+ <description>This action deactivates the logging of configuration commands.
+
+Please note that uncommited data will be lost.
+
+Note! Invoking this action affects the attribute'commandLogStatus'.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="LogActivationException"/>
+ </action>
+ </class>
+
+ <class name="SwManagement">
+ <description>This MO is used as a structural element for the SW managed object. The MO structures the software resources of the node.
+
+Note that the SwManagement MO is automatically created and cannot be deleted.
+
+The local distinguished name of this MO is ManagedElement=1, SwManagement=1.</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="SwManagementId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="normalizeRPU">
+ <description>This action will normalize all RPUs in the node.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="UpgradePackage">
+ <description>The UpgradePackage, UP, represents an upgrade package as stored in the node file system and as stored on the ftp server that it is/shall be fetched from.
+
+There may be more than one UP at the same time on the disk. One UP represents the running system issue in the node. That one is pointed out by the Configuration Version MO.
+
+The actions on an UpgradePackage MO, are actions that can be called to take that particular UpgradePackage into operation on the node.
+
+The deletion of the Upgrade Package on disk is performed when the associated Upgrade Package MO is deleted. The Upgrade Package's unique LoadModule MOs and files are deleted. ConfigurationVersions in otherReferringCVs are deleted.
+
+
+The UP MO refers to all load modules used in the UP. One load module may by used in more than one UP.
+
+Note at the start-up of the system/database/loading of a Configuration Version, special Upgrade Package MOs are created to represent Upgrade Packages that are stored on the disk but do not have an MO in the current Configuration Version. These special Upgrade Package MOs have are in the "onlyDeletable" state. In this state, the MO will throw ActionNotAllowedException on all its actions!
+
+MOs of this type are created automatically during system upgrade.
+MOs of this type are possible to create manually but a system upgrade
+is recommended to create them.</description>
+ <attribute name="UpgradePackageId">
+ <description>The identity of the MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free of use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="loadModuleList">
+ <description>List of references to load modules that belong to this upgrade package.
+
+The list will be null until a successful install has been performed.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="LoadModule"/>
+ <nonUnique/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="upgradeControlFilePath">
+ <description>Path to the .xml file on the node once it has been fetched from the FTP server.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="state">
+ <description>Contains the state of this upgrade package.
+
+The management system and/or operator need to act on some changes in the state attribute.
+
+This attribute is used to accept/reject and modify behavior of actions. For example action 'upgrade' is not allowed in state notInstalled. Furthermore, action 'upgrade' does not behave the same if state == 'Installed' compared to if state == 'executingUpgrade' or 'awaitingConfirm'.
+
+To continue and conclude the upgrade sequence when in state == 'awaitingConfirm', action 'confirmUpgrade()' must be called. In this state it is also advisable to check attribute 'confirmationDeadline' to see how much time it is left before automatic rollback is done.
+
+Upgrade Package MOs that are stored on disk but do not have an MO in the current Configuration Version are in state "onlyDeletable". An MO in this state will throw the exception ActionNotAllowedException on all its actions.
+
+</description>
+ <readOnly/>
+ <dataType>
+ <enumRef name="UpgradePackageState">
+ <defaultValue>NOT_INSTALLED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="progressHeader">
+ <description>Header enum describing the current progress indication.
+Note that this is only progress information, that should be shown to a human operator, because some operations may take time.
+
+Changes in the progress header NEVER entails that the operator or management system need to perform any particular actions. </description>
+ <readOnly/>
+ <dataType>
+ <enumRef name="UpgradeProgressInformation">
+ <defaultValue>IDLE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="progressTotal">
+ <description>
+This notification attribute is used to indicate progress for different steps in the upgrade sequence. The value gives the total number of steps that is to be performed in current step.
+
+This attribute is changed whenever 'progressHeader' is changed and indicates a maximum count for the progress of the progress counter. What items that are counted is specific for each case. For some cases, the counter is not yet implemented. In these cases, the progressTotal is set to zero (0) when the progressHeader is set.
+
+</description>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="progressCount">
+ <description>This attribute is used to indicate progress for different steps in the upgrade sequence. The value is separated in increments from 0 to progressTotal.
+
+The value of progressCount never exceeds the value of 'progressTotal'.
+
+For some cases, the counter is not yet implemented. In these cases, the progressCount is set to zero (0) when the progressHeader is set.</description>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeData">
+ <description>Contains product data for this upgrade package. This information is extracted from the upgrade control file. </description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <structRef name="AdminProductData"/>
+ </dataType>
+ </attribute>
+ <attribute name="confirmationDeadline">
+ <description>This attribute contains the deadline date and time for an operator confirmation. If the deadline is not met, then an automatic rollback to a previous configuration is issued by the system.
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ftpServerIpAddress">
+ <description>Ip address to the ftp server where the upgrade package is stored.
+
+The input format used by the operator is four fields of digits, separated by a dot.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="upFilePathOnFtpServer">
+ <description>File path on the FTP server to the upgrade control file. </description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="user">
+ <description>User id. to be used for logging in to the FTP server.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>anonymous</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="password">
+ <description>Password to the FTP server. This attribute is only supplied at create and is not readable.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>anonymous</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="upgradePackageDocumentId">
+ <description>The document number and revision of the uppgrade package where the white spaces has been removed and underscore between the document number and revision has been inserted e.g. 19089-CSX10901/1_A.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="deletePreventingCVs">
+ <description>The list containing the names of the Configuration Versions that stop the Upgrade Package MO from being deleted.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <string/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="otherReferringCVs">
+ <description>The list of names of Configuration Versions that refer to the Upgarde Package MO, but do not affect the deletable status of the Upgrade Package MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <string/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="isDeletable">
+ <description>Indicates if the Upgrade Package MO can be deleted.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="basedOnUpgradePackages">
+ <description>This attribute is only valid for Upgrade Packages of type Delta.It contains the merge history of this upgrade package.
+
+Example: [Product Data for normal UP (non Delta UP), Product Data for Delta UP1, Product Data for Delta UP2]. </description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <structRef name="AdminProductData"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="upCompatibilityIndex">
+ <description>This attribute states a compatibility index.
+
+If specified, it may be used when verifying that an upgrade 'from' state is valid for this Upgrade Package.
+
+Note: It is only used when the Upgrade Control File element upgrade window contains this type of information.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="cppUpVersion">
+ <description>This attribute states the CPP upgrade package version of this Upgrade Package</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <structRef name="AdminProductData"/>
+ </dataType>
+ </attribute>
+ <attribute name="actionResult">
+ <description>The attribute contains the result from the latest four invoked actions.
+
+This attribute is only valid for actions::
+- install (all variants)
+- cancelInstall
+- verifyUpgrade
+- upgrade (all variants, Note that the attribute is only valid when the verification phase discovers that upgrade is not possible').</description>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <structRef name="ActionResultData"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <action name="install">
+ <description>Load modules defined in the Upgrade Package Control file will only be downloaded to the node if the Load Module MO representing the load module file doesn't already exist.
+The result of this action is indicated in the attribute ActionResult. In case the installation fails after 'void' has been returned the attribute 'ProgressHeader' is set to 'InstallationExecutionFailed'.Already downloaded load modules (the downloaded file and the Load Module MO representing it) are not removed at installation failure.
+
+
+This action returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute actionResult.
+
+Note! This action will be removed in a later version.
+Note! This action does not require a transaction. </description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="FtpServerNotAccessibleException"/>
+ <raisesException name="GetFileException"/>
+ <raisesException name="IpAddressException"/>
+ <raisesException name="UpgradeControlFileException"/>
+ <raisesException name="ActionNotAllowedException"/>
+ <raisesException name="InstallException"/>
+ </action>
+ <action name="verifyUpgrade">
+ <description>Verifies that an upgrade is possible.
+
+The operation is not blocked while the verification is executing i.e. after basic controls the operation initiates the verification and returns 'void'.
+
+The progress of this action is indicated in the attribute ProgressHeader.The result of this action is indicated in the attribute ActionResult.
+
+This action returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute actionResult.
+
+Note: This action does not require a transaction.
+
+
+
+</description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="VerifyUpgradeException"/>
+ <raisesException name="ActionNotAllowedException"/>
+ </action>
+ <action name="upgrade">
+ <description>Upgrades the node. The operation is not blocked while upgrade is executing i.e. after basic controls the operation initiates the upgrade and returns 'void'.
+
+Before the real upgrade is started a verification phase is executed.
+
+The progress of this action is indicated in the attribute ProgressHeader.
+
+This action returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute actionResult.
+
+The result of this action is only indicated in attribute ActionResult in case the verification phase discovers that upgrade is not possible.
+
+Note: This action does not require a transaction.
+
+</description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="UpgradeNotPossibleException"/>
+ <raisesException name="ActionNotAllowedException"/>
+ </action>
+ <action name="rebootNodeUpgrade">
+ <description>The same as upgrade except that the hard upgrade sequence is always chosen.
+
+It could be helpful to use this method if the application has start- or upgrade- synchronization problems when using a soft upgrade sequence.
+
+This action returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute actionResult.
+
+The result of this action is only indicated in attribute ActionResult in case the verification phase discovers that upgrade is not possible.
+
+Note: This action does not require a transaction. </description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="UpgradeNotPossibleException"/>
+ <raisesException name="ActionNotAllowedException"/>
+ </action>
+ <action name="confirmUpgrade">
+ <description>The operator invokes this method when the trial period is over.
+The operation is not blocked while upgrade is executing i.e. after basic controls the operation initiates the upgrade and returns 'void'.In case the upgrade fails after 'void' has been returned the attribute ProgressHeader will be set to 'UpgradeExecutionFailed'.
+
+Note! This action does not require a transaction. </description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="UpgradeNotPossibleException"/>
+ <raisesException name="ActionNotAllowedException"/>
+ </action>
+ <action name="cancelUpgrade">
+ <description>Cancels an executing upgrade or an upgrade that is awaiting confirm.
+
+Note: This action performs a node restart so that the CV pointed out in the ConfigurationVersion MO is rolled back.
+
+Note! This action does not require a transaction. </description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="ActionNotAllowedException"/>
+ </action>
+ <action name="forcedInstall">
+ <description>All load modules defined in the Upgrade Package Control file will be downloaded to the node even if the Load Module MO representing the load module already exists i.e. existing load module files are replaced.
+The result of this action is indicated in the attribute ActionResult.In case the installation fails after 'void' has been returned the attribute 'ProgressHeader' is set to 'InstallationExecutionFailed'.Already downloaded load modules (the downloaded file and the Load Module MO representing it) are not removed at installation failure.
+
+
+This action returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute actionResult.
+
+Note! This action will be removed in a later version.
+Note! This action does not require a transaction. </description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="FtpServerNotAccessibleException"/>
+ <raisesException name="GetFileException"/>
+ <raisesException name="IpAddressException"/>
+ <raisesException name="UpgradeControlFileException"/>
+ <raisesException name="ActionNotAllowedException"/>
+ <raisesException name="InstallException"/>
+ </action>
+ <action name="nonBlockingInstall">
+ <description>Load modules defined in the Upgrade Package Control file will only be downloaded to the node if the Load Module MO representing the load module doesn't already exist.
+
+This action is non-blocking i.e. the action initiates the installation and returns 'void' immediately without waiting for the installation to be completed.
+
+In case the installation fails after 'void' has been returned, this will be indicated by change of the value of attribute 'ProgressHeader' to 'ExecutionFailed'. Already downloaded load modules (the downloaded file and the Load Module MO representing it) are not removed at installation failure.
+
+This action returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute actionResult.
+
+Note! This action does not require a transaction.
+</description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="ActionNotAllowedException"/>
+ <raisesException name="InstallException"/>
+ </action>
+ <action name="nonBlockingForcedInstall">
+ <description>All load modules defined in the Upgrade Package Control file will be downloaded to the node even if the Load Module MO representing the load module already exists i.e. existing load module files are replaced.
+This action is non-blocking i.e. the action initiates the installation and returns 'void' immediately without waiting for the installation to be completed.
+The result of this action is indicated in the attribute ActionResult.In case the installation fails after 'void' has been returned the attribute 'ProgressHeader' is set to 'InstallationExecutionFailed'. Already downloaded load modules (the downloaded file and the Load Module MO representing it) are not removed at installation failure.
+
+This action returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute actionResult.
+
+Note! This action does not require a transaction. </description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="ActionNotAllowedException"/>
+ <raisesException name="InstallException"/>
+ </action>
+ <action name="nonBlockingSelectiveForcedInstall">
+ <description>This action only installs the load modules that are required in this node i.e. the load modules required after successful execution of action upgrade on this upgrade package.
+
+A load module is considered to be required if one of the following criteria is fulfilled:
+a) The load module is included in a Repertoire MO where the Repertoire MO is connected to a SwAllocation MO and the SwAllocation MO is connected to a Slot MO, a Fan MO, a Jvm MO, a Webserver MO or an applicable type of application MO.
+b) The load module is of type 'other'.
+
+All required load modules will be downloaded to the node even if the Load Module MO representing the load module already exists i.e. existing load module files are replaced.
+
+This operation is non-blocking i.e. the action initiates the installation and returns "void" immediately without waiting for the installation to be completed.
+The result of this action is indicated in the attribute ActionResult.In case the installation fails after 'void' has been returned the attribute 'ProgressHeader' is set to 'InstallationExecutionFailed'. Already downloaded load modules (the downloaded file and the Load Module MO representing it) are not removed at installation failure.
+
+Note. The behaviour described for this action is also obtained for the other installation actions if the Upgrade Control File indicates that the upgrade package is of type selective (which is recommended).
+
+This action returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute actionResult.
+
+Note! This action does not require a transaction. </description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="ActionNotAllowedException"/>
+ <raisesException name="InstallException"/>
+ </action>
+ <action name="nonBlockingSelectiveInstall">
+ <description>This action only installs the load modules defined in the Upgrade Package Control file that are required in this node i.e. the load modules required after successful execution of action upgrade on this upgrade package.
+
+A load module is considered to be required if one of the following criteria is fulfilled:
+a) The load module is included in a Repertoire MO where the Repertoire MO is connected to a SwAllocation MO and the SwAllocation MO is connected to a Slot MO, a Fan MO, a Jvm MO, a Webserver MO or an applicable type of application MO.
+b) The load module is of type 'other'.
+
+Returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute
+actionResult.
+
+The required load modules will only be downloaded to the node if the Load Module MO representing the load module doesn't already exist.
+
+This action is non-blocking i.e. the action initiates the installation and returns 'void' immediately without waiting for the installation to be completed.
+
+The result of this action is indicated in the attribute ActionResult. In case the installation fails after 'void' has been returned the attribute 'ProgressHeader' is set to 'InstallationExecutionFailed'. Already downloaded load modules (the downloaded file and the Load Module MO representing it) are not removed at installation failure.long
+
+Note. The behaviour described for this action is also obtained for the other installation actions if the Upgrade Control File indicates that the upgrade package is of type selective (which is recommended).
+Note! This action does not require a transaction. </description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="ActionNotAllowedException"/>
+ <raisesException name="InstallException"/>
+ </action>
+ <action name="cancelInstall">
+ <description>This action interrupts an ongoing installation of an upgrade package.
+
+Already downloaded load modules (the downloaded file and the Load Module MO representing it) are not removed at execution of this action.
+
+This action is non-blocking i.e. the action initiates the cancel of the installation and returns 'void' immediately without waiting for the cancellation to be completed.
+
+During execution of this action the value of attribute 'ProgressHeader' is set to 'CancelOfInstallationIsExecuting'.
+
+In case the cancellation fails after 'void' has been returned this will be indicated by change of the value of attribute 'ProgressHeader' to 'CancelOfInstallationFailed'.
+
+Note! This action does not require a transaction.
+
+This action interrupts an ongoing installation of an upgrade package.
+Already downloaded load modules (the downloaded file and the Load Module MO representing it) are not removed at execution of this action.
+This action is non-blocking i.e. the action initiates the cancel of the installation and returns 'void' immediately without waiting for the cancellation to be completed.
+During execution of this action the value of attribute 'ProgressHeader' is set to 'CancelOfInstallationIsExecuting'.The result of this action is indicated in the attribute ActionResult.In case the cancellation fails after 'void' has been returned the attribute 'ProgressHeader' is set to 'CancelOfInstallationFailed'.
+
+This action returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute actionResult.
+
+Note! This action does not require a transaction. </description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="ActionNotAllowedException"/>
+ </action>
+ <action name="clearUpgradeLogFile">
+ <description>Is used to clear the contents of current upgrade log file.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="UpgradeLogFileNotInUseException"/>
+ <raisesException name="UpgradeLogFileNotAccessibleException"/>
+ </action>
+ </class>
+
+ <class name="Repertoire">
+ <description>The Repertoire is an abstraction of a functionality represented by a plug in unit type (PiuType MO) and one or more load modules (LoadModule MO). The repertoire also provides rules for PiuType/ Load Module combinations valid for a specific function where one function can be provided by one or many PiuType-Load Module combinations.
+These rules are used to load the correct software (Load Modules) to a PlugInUnit. This could be used as operator configuration support and/or in situations where automatic re-configuration is required (hot repair).
+
+MOs of this type are created automatically during system upgrade.
+MOs of this type are possible to create manually but a system upgrade is recommended to create them.</description>
+ <attribute name="userLabel">
+ <description>A user friendly name associated to the managed object. </description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="name">
+ <description>A function friendly name associated to the repertoire. The value must be unique with respect to all repertoires with the same install state.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="info">
+ <description>Information regarding the function.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="piuTypeList">
+ <description>A list containing all PiuType references that has been added to this repertoire.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="PiuType"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="RepertoireId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving SwAllocation MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="SwAllocation"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="OspfInterface">
+ <description>The OSPF Interface MO represents an interface that is used by the OSPF protocol to communicate with a neighbour node. By connecting an OSPF interface to a Link MO that Link is defined as a link to be used by OSPF.
+
+Each OspfInterface MO must always be connected to a OspfArea MO.
+</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ospfAreaRelated">
+ <description>The identity of the OspfArea connected to this OspfInterface. The default value is the default OspfArea MO.</description>
+ <dataType>
+ <moRef name="OspfArea"/>
+ </dataType>
+ </attribute>
+ <attribute name="lsaTransmissionInterval">
+ <description>The time, in seconds, between LSA re-transmissions over the interface - default value 5 seconds.</description>
+ <dataType>
+ <long>
+ <defaultValue>5</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="helloInterval">
+ <description>The time, in seconds, between sending OSPF Hello-packets over the interface. Default value 10 seconds.
+
+Note! Must be a positive value.</description>
+ <dataType>
+ <long>
+ <defaultValue>10</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="routerDeadInterval">
+ <description>The time, in seconds, after which a neighbor router is declared dead when not heard from.
+</description>
+ <dataType>
+ <long>
+ <defaultValue>40</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="interfaceTransitDelay">
+ <description>Estimated delay, in seconds, for the transmission of a link state update package over the interface.
+</description>
+ <dataType>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="interfacePriority">
+ <description>The interface priority. Each router is configured with a priority configured from 0 - 255 where 0 is the lowest priority and 255 the highest.
+
+Note! Must be a positive value.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="relatedLink">
+ <description>Each OSPF interface is connected to one IP link.
+The relatedLink can be either an IpAtmLink or an EthernetLink MO
+reference.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="OspfInterfaceId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfOspfIfEvents">
+ <description>Performance monitoring counter for the number of times this OSPF interface has changed its state or an error has occured.
+
+See RFC 1850.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Ospf">
+ <description>The Ospf MO represents an instance of the Open Shortest Path First (OSPF) routing protocol running in a Cello node.
+
+When the Ospf MO is created a default OspfArea MO is also created. This OspfArea has the areaId 000.000.000.000.
+
+The attribute range0 in the default OspfArea will contain the following values:
+advertise = false
+ipAddress = 000.000.000.000
+subnetMask = 000.000.000.000
+</description>
+ <attribute name="OspfId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ospfRouterId">
+ <description>The ospfRouterId attribute is in the form of an IP address.
+In order to able to set ospfRouterId the attribute
+administrativeState has to be set to locked. The ospfRouterId
+is uniquely identifying the router in the Autonomous System. By
+convention to ensure uniqueness, this should be configured to the
+value of one of the routers IP interface addresses.</description>
+ <mandatory/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="ospfASBdrRtrStatus">
+ <description>The ospfASBdrRtrStatus attribute controls, whether this router is configured as an Autonomous System border router (Routers connected to multiple areas are called area border routers). The attribute must be set to 'True' if the user wants to configure static routes, which should be distributed to other OSPF routes as external routes. Configuration of static routes is the same as adding and deleting static routes to the IpRoutingTable Mo.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the MO.
+The operationalState can only be enabled when the IP MO is in workingMode routerMode.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of the MO.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="ospfAreaBdrRtrStatus">
+ <description>Area border router flag - indicates whether the router is acting as an area border router or not.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="ipMo">
+ <description>The name of the Ip MO that the Ospf MO is to use</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Ip"/>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled. It is a bit mapped CORBA long, where one or more of the bits may be set. If none of the bits are set then the availability status is considered to be undefined.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfOspfOriginateNewLsas">
+ <description>The number of new link-state advertisments that have been originated. This number is incremented each time the router originates a new LSA.
+
+For more detailed information, see RFC 1850.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfOspfRxNewLsas">
+ <description>The number of link-state advertisments received determined to be new instantiations. This number does not include newer instantiations of self-originated link-state advertisments.
+
+For more detailed information, see RFC 1850.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="recoverTopoDb">
+ <description>Indicates whether the topology database is to be recovered from the database at restart.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="topoDbStoreInterv">
+ <description>The interval, in seconds, with which the topology database will be stored.</description>
+ <dataType>
+ <long>
+ <defaultValue>60</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="OspfArea">
+ <description>An OSPF autonomous system is divided into OSPF areas. The OSPF Area MO represents such OSPF areas.
+
+A default OspfArea MO is automatically created when the Ospf MO is created.
+It has the identity = 1, so LDN of this MO will be
+ManagedElement=1,IpSystem=1,Ospf=1,OspfArea=1.
+
+Note! A maximum of 4 OspfAreas can be configured each with a maximum of 8 interfaces.</description>
+ <attribute name="OspfAreaId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="stubArea">
+ <description>Indicates whether the OSPF area is a stub area or not.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="importExternalLsa">
+ <description>Indicates whether importing Autonomous System external LSA's is supported.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="sendAreaSummary">
+ <description>Import Area summary - indicates whether the router will originate and propagate summary LSAs into a stub-area.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="stubAreaMetric">
+ <description>Cost for default route that the router advertises into the area if the area is a stub area and the router is an area border router. By default set to the least metric among the interfaces to other areas.</description>
+ <dataType>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="stubAreaMetricType">
+ <description>Stub Area metric type.
+
+RFC 1850 (OSPF V2 MIB):
+
+comparableCost (external type 1)
+nonComparable (external type 2)</description>
+ <dataType>
+ <enumRef name="OspfMetricType">
+ <defaultValue>comparableCost</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="areaLsaChecksum">
+ <description>Area Lsa checksum - 32-bit unsigned sum of the link-state advertisements LS check sums contained in this area's link-state database.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="areaId">
+ <description>The OSPF area identity in form of an IP address. This areId uniquely identifies the area.
+AreaId 0.0.0.0 is used for the OSPF backbone.
+Range: 000.000.000.000 to 255.255.255.255.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="range0">
+ <description>OspfArea IP address range zero (0).</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="OspfAreaRange"/>
+ </dataType>
+ </attribute>
+ <attribute name="range1">
+ <description>OspfArea IP address range one (1).</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <structRef name="OspfAreaRange"/>
+ </dataType>
+ </attribute>
+ <attribute name="range2">
+ <description>OspfArea IP address range two (2).</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <structRef name="OspfAreaRange"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfOspfSpfRuns">
+ <description>The number of times that the intra-area route table has been calculated using this area's link-state database. This is typically done using Dijkstra's algorithm.
+
+For more detailed information, see RFC 1850.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds a list of the reserving OspfInterface MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="OspfInterface"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <action name="addAreaRange">
+ <description>Add aggregation range. Used to add a range of IP addresses to an OSPF area.
+
+Note! This action requires a transaction.
+</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="range">
+ <description>The area range aggregation.</description>
+ <in/>
+ <dataType>
+ <structRef name="OspfAreaRange"/>
+ </dataType>
+ </parameter>
+ <parameter name="rangeIndex">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="AttrMissingAtCreateException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="NoSuchFieldException"/>
+ <raisesException name="ValueOutOfRangeException"/>
+ <raisesException name="WrongAttributeTypeException"/>
+ </action>
+ <action name="deleteAreaRange">
+ <description>Delete an IP address range. Used to remove a range of IP addresses from an OSPF area.
+
+Input is the area aggregation range index.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="rangeIndex">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroNotAccessibleException"/>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="ValueOutOfRangeException"/>
+ </action>
+ </class>
+
+ <class name="SwitchCoreUnit">
+ <description>The Switch Core Unit MO, SCU, represents the board specific HW on the SCB. This object collects HW failure on the board and sends alarms. It is also used for configuration of board specific FW.
+This board can only be fitted in slot 1 and 28 in a standards subrack.
+The board has a number of switch internal link ports.</description>
+ <notificationTypes>alarm</notificationTypes>
+ <attribute name="userLabel">
+ <description>user label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeStateSili">
+ <description>The administrative state of the switch internal link ports on the switch board. The attribute refers to all ports (locking will lock all ports, unlocking unlock all ports).
+SILI -switch internal link interface.
+</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalStateSil">
+ <description>Operational state indicates the the traffic handling capability of all ports as a group on the board, i.e it is enabled if one or more of the eight ports is enabled. The purpose of this attribute is only for test.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalStateSync">
+ <description>Operational State for network synchronization distribution.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusSil">
+ <description>The availability status of the switch internal link (SIL) ports..
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusSync">
+ <description>Availability state for network synchronization distribution.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="SwitchCoreUnitId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>A list of the reserving MO's.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="silPorts">
+ <description>The attribute provides a list of port numbers.
+The port number is between 0-7 and is used to read state of the switch internal port.
+See action getSilPortState, getOperState and getAvailState.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <long/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <action name="getSilPortState">
+ <description>Returns status of the switch internal link port, which is the same as the LEDs on the unit.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <enumRef name="SilPortState">
+ </enumRef>
+ </returnType>
+ <parameter name="portNr">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="getSilOperState">
+ <description>Returns operational status of the switch internal link port.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <enumRef name="OperState">
+ </enumRef>
+ </returnType>
+ <parameter name="portNr">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="getSilAvailState">
+ <description>Returns availability status of the switch internal link port.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <long/>
+ </returnType>
+ <parameter name="portNr">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ </class>
+
+ <class name="GeneralProcessorUnit">
+ <description>The General purpose Processor Unit MO, GPU, represents the board specific HW on the GPB; hard disk, ethernet and serial port etc.
+
+Note! The 'availabilityStatus' for the GeneralProcessorUnit MO is retreived from the PlugInUnit MO.</description>
+ <attribute name="GeneralProcessorUnitId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Indicates if the function provided by the managed object is capable of performing its normal functions or not.
+
+Note! The value for operationalState is retrived from the GeneralProcessorUnit's parent, i.e. the PlugInUnit.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="hdVolumeDSize">
+ <description>The total size in bytes of the D volume.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="hdVolumeDFreespace">
+ <description>The amount in bytes of freespace available on the D volume.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="hdVolumePSize">
+ <description>The total size in bytes of the P volume.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="hdVolumePFreespace">
+ <description>The amount in bytes of freespace available on the P volume.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds the identity of the reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Jvm">
+ <description>The JVM MO is used to represent the Java Virtual Machine. This object is used for configuration JVM parameters, including SW management of Java class libraries used in the machine.
+
+The local distinguished name of this MO is ManagedElement=1, Equipment=1, JVM=1.</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="classpath">
+ <description>Current classpath, the JVM is using</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="admClasspath">
+ <description>New classpath that will be activated at next restart of JVM. The classpath has a directory, which contains the load module, i.e. the classpath references the load module.</description>
+ <dataType>
+ <sequence>
+ <moRef name="LoadModule"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="freeMemory">
+ <description>Free memory in the java machine, in bytes.
+
+NOTE: Before this value is read from the system the action 'garbageCollect' is invoked.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="totalMemory">
+ <description>Total amount of memory allocated to the java machine, in bytes.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="mopplets">
+ <description>Contains all classes that are to be initilised and started when the JVM restarts.
+
+Technical note: The specified classes must implement the se.ericsson.cello.moframework.Mopplet interface and be found in a jar/zip-file pointed out by the classpath.
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <string/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="main">
+ <description>Defines the start class name.
+e.g. "se.ericsson.cello.oms.Oms"</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="options">
+ <description>Current options:
+ -D&lt;property&gt;=&lt;value&gt; Set a system property value. Commonly java.class.path
+-Xms&lt;size&gt; Specify the size, in bytes, of the memory allocation pool.
+-Xss&lt;size&gt; Set thread stack size in bytes.
+-Xverify:[all | remote | none] Verify classes according to the suboption.
+ -Xverify:all verifies all classes.
+ -Xverify:remote verifies remote classes only.
+ -Xverify:none turns off class verification.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="JvmId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="properties">
+ <description>Determines the current system properties.
+
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <string/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="reliableProgramUniter">
+ <description>A reference to the ReliableProgramUniter that refers to the programs in the which the JVM executes.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ReliableProgramUniter"/>
+ </dataType>
+ </attribute>
+ <attribute name="admMain">
+ <description>New start class that will be activated at next restart of the JVM.
+e.g. "se.ericsson.cello.oms.Oms"</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="admOptions">
+ <description>This attribute is used when setting one or more administrative options.
+
+A set option is operational after the next Java Machine restart.
+
+See also attribute 'options'
+
+One or more options can be set, one option in each string of the
+sequence according to description below:
+
+Current options:
+ -D&lt;property&gt;=&lt;value&gt; Set a system property value. Commonly java.class.path
+-Xms&lt;size&gt; Specify the size, in bytes, of the memory allocation pool.
+-Xss&lt;size&gt; Set thread stack size in bytes.
+-Xverify:[all | remote | none] Verify classes according to the suboption.
+ -Xverify:all verifies all classes.
+ -Xverify:remote verifies remote classes only.
+ -Xverify:none turns off class verification.</description>
+ <dataType>
+ <sequence>
+ <string/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBySwAllocation">
+ <description>This attribute holds the identity of the reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="SwAllocation"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <action name="garbageCollect">
+ <description>Runs the garbage collector.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="setProperty">
+ <description>Sets a system property (i.e. propertys in the operating system).
+Note! The valeus set with this action is not saved in the database.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="name">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="value">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="restart">
+ <description>Restart of executing JVM instance.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="SwitchFabric">
+ <description>This MO represents the switch of a Cello node. It is used for general switch configuration.
+
+The system creates automatically one instance of this MO at restart.
+
+Today, only a maximum of 32 Switch Modules MOs and 2 SwitchInternalLinks MOs per InternalLinkGroup MOs are allowed in a Cello node. However, in theory the switch addressing space in the system allows up to 256 SwitchModules MOs. This would then mean there are 255 InternalLinkGroup MOs, each of which is allowed 256 SwitchInternalLink MOs by the addressing.
+
+The local distinguished name of this MO is ManagedElement=1, SwitchFabric=1.
+
+</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="SwitchFabricId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="SwitchModule">
+ <description>This MO represents two switch planes of one sub-rack, i.e. either the main switch or an external switch.
+
+Note! In a non-redundant system the administrativeStateSwitchPlaneA/B has to be set to locked for the non-present plane. </description>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="switchModuleNumber">
+ <description>Indicates the number of the switch module, SMN.
+
+switchModuleNumber &amp;gt;= 0
+
+The main switch module, with one or two TimingUnits, is given SMN = 0. SMN for extension switch modules depends on the port pair that the extension switch module is connected to in the main switch module.
+
+The SMN is calculated according to the following formula:
+
+Switch module number [1..255] = int (APN/2)*8 + ISL-port in main [1..8]
+
+APN - ASCC port number
+ISL - inter-switch link</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="secondSmnEvaluation">
+ <description>secondSmnEvaluation - There are two cables that
+are relevant for Switch Module Number (smn) numbering
+If the cabling is wrong secondSmnEvaluation
+will show the second opinion about smn.
+Under normal conditions secondSmnEvaluation = smn.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of the switch module.
+
+Note! When setting the 'administrativeState' to shutting down a notification about that the state has changed to 'locked' will be sent towards the operator. There is however no guarantee that this operation has been succesful despite the notification and state change due to limitations in the resource layer
+</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>unlocked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeStateSwitchPlaneA">
+ <description>The administrative state of switch plane A.
+It is not allowed to lock both switch plane A and B.
+
+Note! When setting the 'administrativeState' to shutting down a notification about that the state has changed to 'locked' will be sent towards the operator. There is however no guarantee that this operation has been succesful despite the notification and state change due to limitations in the resource layer</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>unlocked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeStateSwitchPlaneB">
+ <description>The administrative state of switch plane B.
+It is not allowed to lock both switch plane A and B.
+
+Note! When setting the 'administrativeState' to shutting down a notification about that the state has changed to 'locked' will be sent towards the operator. There is however no guarantee that this operation has been succesful despite the notification and state change due to limitations in the resource layer</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>unlocked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the Switch Module. At least one of switch plane is enabled. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalStateSwitchPlaneA">
+ <description>The operational state of Switch Module plane A. The state is disabled if any switch ports is faulty. But switch may still be used.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalStateSwitchPlaneB">
+ <description>The operational state of Switch Module plane B. The state is disabled if any switch ports is faulty. But switch may still be used.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status of the Switch Module.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusSwitchPlaneA">
+ <description>The availability status of the Switch Plane A.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusSwitchPlaneB">
+ <description>The availability status of the Switch Plane B.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="activeSwitchPlane">
+ <description>The active switch plane: A, B. During multiple faults, both plan A and B may be used.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="ActiveSwitchPlane">
+ <defaultValue>switchPlaneA</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="SwitchModuleId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="InternalLinkGroup">
+ <description>The Internal Link Group MO represents all switch internal links connecting the main switch to an external switch.
+
+Switch internal links are automatically grouped in Reliable Groups for redundancy.</description>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="switchModuleNumber1">
+ <description>Reference to the SwitchModule MO that is interconnected by the link in the InternalLinkGroup.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="SwitchModule"/>
+ </dataType>
+ </attribute>
+ <attribute name="switchModuleNumber2">
+ <description>Reference to the SwitchModule MO that is interconnected by the link in the InternalLinkGroup.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="SwitchModule"/>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative status of internal link group.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>unlocked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational status of internal link group.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="InternalLinkGroupId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="getRlgLinks">
+ <description>Returns a list of resource instance identities of the switch internal links in the specified Reliable Group.
+
+The existing Reliable Groups are listed with action getReliableLinkGroups.
+
+Note! This action is transactional.</description>
+ <returnType>
+ <sequence>
+ <longlong/>
+ </sequence>
+ </returnType>
+ <parameter name="rlgNumber">
+ <description>Reliable link group number.</description>
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="getLinkStatus">
+ <description>Returns the status of the specified switch internal link, within the specified Reliable Group.
+
+Note! This action is transactional.</description>
+ <returnType>
+ <enumRef name="SwitchReliableGroup">
+ </enumRef>
+ </returnType>
+ <parameter name="instanceId">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <parameter name="rlgNumber">
+ <description>Reliable link group number.</description>
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="getReliableLinkGroups">
+ <description>Returns a sequence of Reliable Group numbers.
+
+Each Reliable Group is identified by a unique number which can be used to read out the identities of the switch internal links that are allocated to the Reliable Group. This is done with action getRlgLinks.
+
+The allocation of switch internal links to Reliable Groups is automatic.
+
+Note! This action is transactional.
+</description>
+ <returnType>
+ <sequence>
+ <long/>
+ </sequence>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ </class>
+
+ <class name="SwitchInternalLink">
+ <description>This MO represents a link interconnecting the from either a SCB or SXB port on the main switch to a SCB on an external switch.
+
+The main switch is located in the hub subrack.
+
+The SCB is represented by the SwitchCoreUnit MO, while the SXB is represented by the SwitchExtensionUnit MO.
+
+Switch internal links are automatically grouped in Reliable Groups for redundancy.</description>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="SwitchInternalLinkId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="plugInUnit1">
+ <description>The reference of one connection point for a SwitchCoreUnit or SwitchExtensionUnit.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="plugInUnit2">
+ <description>The reference of one connection point for a SwitchCoreUnit or SwitchExtensionUnit.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="siliport1">
+ <description>Switch internal port number on PlugInUnit1.
+
+Note!
+On a standard SCB/SXB board, the ports are labeled from the bottom to the top.
+
+Port nr -&gt; label:
+ '0' 'D'
+ '1' 'C'
+ '2' 'B'
+ '3' 'A'
+
+Also note that his mapping will change when adding/removing a board.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>3</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="siliport2">
+ <description>Switch internal port number on PlugInUnit2.
+
+Note!
+On a standard SCB/SXB board, the ports are labeled from the bottom to the top.
+
+Port nr -&gt; label:
+ '0' 'D'
+ '1' 'C'
+ '2' 'B'
+ '3' 'A'
+
+Also note that his mapping will change when adding/removing a board.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>3</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of switch internal link.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>unlocked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalStateTraffic">
+ <description>The operational state of switch internal link. There is no traffic if the link is disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusTraffic">
+ <description>The availabilityl status of switch internal link.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalStateSync">
+ <description>The operational state of sync link. There is no clock distribution if the link is disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusSync">
+ <description>The availability state of sync link.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Etm4">
+ <description>This MO represents the hardware of the ET-M4 board type. It only represents the ET specific hardware, while the DBM module of the board is represented by the PlugInUnit MO.
+
+The ET-M4 board contains 2 physical ports that can be configured as either STM1(ETSI/TTC) or OC3C (ANSI). The board supports unchannelised ATM access (i.e. it maps ATMs cells directly into an SDH VC4 container).
+
+The board supports up to 1800 ATM VC connections.
+The number of terminated VPs are limited to 48/board.
+The board supports up to 750 VC UBR+ connections.
+
+The ET-M4 board contains 128 AAL2 multiplexers.
+The ET-M4 board supports up to 256 bidirectional F4/F5 PM flow per port.
+
+Note! IMA is not applicable for the ETM4 board.
+
+Note! The number of VCC TP+VPC TP with performance monitoring enabled (i.e. PM mode &lt;&gt; off) is restricted to 256 per board.
+
+Note! When using the Etm4 board the performance monitoring counters in the transmit direction found on the AtmPort MO does not show the following cells: CC cells and OAM FPM cells.</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Enabled or disabled according to the actual operational state of the hardware ETM4. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="Etm4Id">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="VpcTp">
+ <description>Virtual path connection termination point, VpcTp, is used to represent the point where the VPC and associated overhead (F4 OAM cells) are terminated/originated.
+
+Note! The performance monitoring counters in this MO is set to 0 when counterMode is set to PM_MODE_ON.
+In PM_MODE_OFF no information at all is retrived. So any value for pm-monitoring is measured from the time
+of setting counterMode to PM_MODE_ON.
+At node restart these performance monitoring counters is reset to 0.</description>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="VpcTpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>enabled or disabled according to the actual operational state of the VpcTp</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="continuityCheck">
+ <description>Continuity checking means that a cell is sent downstream when no user cell has been sent for a period of nominally 1 second. Continuity check both enables generation of CC cells as well as detection of LOC</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="counterMode">
+ <description>PM mode is set to indicate type of performance monitoring mode (i.e. activation of bidirectional PM measurements).
+
+</description>
+ <dataType>
+ <enumRef name="AtmCounterMode">
+ <defaultValue>PM_MODE_OFF</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="nomPmBlkSize">
+ <description>Nominal performance monitoring (PM) blocksize. The minimum number of ATM cells to send before sending a Forward Performance Monitoring, FPM, cell.
+</description>
+ <dataType>
+ <enumRef name="AtmNomPmBlkSize">
+ <defaultValue>NOM_PM_BLKSIZE_2_10</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwLostCells">
+ <description>Performance monitoring counter for number of lost forward cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwMissinsCells">
+ <description>Performance monitoring counter for number of forward missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwErrBlocks">
+ <description>Performance monitoring counter for number of forward errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostFpmCells">
+ <description>Performance monitoring counter for number of lost Forward Performance Monitoring, FPM, cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwLostCells">
+ <description>Performance monitoring counter for number of lost backward cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwMissinsCells">
+ <description>Performance monitoring counter for number of backward missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwErrBlocks">
+ <description>Performance monitoring counter for number of backward errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostBrCells">
+ <description>Performance monitoring counter for number of lost Backward Reporting, BR, cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="alarmReport">
+ <description>Attribute to decide what type of alarms to be reported.</description>
+ <dataType>
+ <enumRef name="AlarmReport">
+ <defaultValue>ALARM_LOC</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <action name="eteLoopBack">
+ <description>This action performs VC end to end loopback from this VpcTp.
+false=Failed, true=Succeded
+
+Note! This action requires a transaction.
+</description>
+ <returnType>
+ <boolean/>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="VplTp">
+ <description>This MO is used to represent the termination of a VP link.
+
+Note that a maximum of 999 MO's of this type may be configured.
+
+Note! For information on how many VplTp's that can be configured under the AtmPort MO please refer to the board that is parent to the termination reserved by the AtmPort MO.
+
+The performance monitoring counters in the VplTp MO is set to 0 (zero) at start or restart of the node.
+When the value is to large to fit in to a long (31bit) the counter turns over and starts from 0 again.</description>
+ <attribute name="userLabel">
+ <description>This MOs user label.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="atmTrafficDescriptor">
+ <description>Reference to the Atm Traffic Descriptor.</description>
+ <mandatory/>
+ <dataType>
+ <moRef name="AtmTrafficDescriptor"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>enabled or disabled according to the actual operational state of the VplTp.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="externalVpi">
+ <description>This is the virtual path identifier for the external ATM cells.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmReceivedAtmCells">
+ <description>Performance monitoring counter for number of received ATM cells for the VplTp.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmTransmittedAtmCells">
+ <description>Performance monitoring counter for number of transmitted ATM cells.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="VplTpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="TimingUnit">
+ <description>This MO represents a timing unit (reference clock) in the node.
+
+The corresponding Program shall be of LoadModuleLoaderType, SpmFpgaLoader.</description>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Operational state of TimingUnit</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status of the TimingUnit.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="TimingUnitId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="PiuType">
+ <description>The PiuType is an MO that holds product information about a PlugInUnit and the execution resources of the PlugInUnit. It is created/deleted during a software upgrade.
+The PiuType is used when creating execution MOs connected to a PlugInUnit and when allocating software to this resource.
+
+MOs of this type are created automatically during system upgrade.
+MOs of this type are possible to create manually but a system upgrade
+is recommended to create them.
+
+
+</description>
+ <attribute name="userLabel">
+ <description>A user friendly name associated to the managed object. </description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="productData">
+ <description>The productData describes the product number, short product revision, product name and product information of the PlugInUnit. The production date is not used.
+
+Trailing letters in the revision is recommended to be excluded in the PiuType. Example: R2B will be R2 without trailing letter, R2B/3 must be R2B/3 in the PiuType, R2B/A should be R2 in the PiuType.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="AdminProductData"/>
+ </dataType>
+ </attribute>
+ <attribute name="boardWidth">
+ <description>The width of the PlugInUnit board in steps of 5 mm.
+A PlugInUnit can use/cover more than the slot that it occupies.
+
+Example: boardWidth=3 corresponds to 3*5 = 15 mm.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long/>
+ </dataType>
+ </attribute>
+ <attribute name="airFlowData">
+ <description>Control value m3/h for the fan unit. Needed by cooling function.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="AirFlowData"/>
+ </dataType>
+ </attribute>
+ <attribute name="PiuTypeId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="role">
+ <description>The value will be MP if a board has the role of a Main processor.
+The value will be BP if a board has the role of a device board
+Otherwise the value will be OTHERS.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="PiuRole">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity's of the reserving MO's.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <action name="numberOfMoConfigurations">
+ <description>Returns the number of entries in the PIUTypeConfigurationArray.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <long/>
+ </returnType>
+ </action>
+ <action name="getMoConfiguration">
+ <description>Returns a struct of a specific MoConfiguration at a given index.
+The moConfiguration holds information about how to create the
+subordinate objects for a specific piu type.
+
+Precondition: 0 &lt;= index &lt;= numberOfMoConfigurations() - 1
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <structRef name="PiuTypeMOConfiguration"/>
+ </returnType>
+ <parameter name="index">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="InvalidIndexException"/>
+ </action>
+ </class>
+
+ <class name="SwAllocation">
+ <description>This MO is primarily used to handle data for automatic configuration of load modules. Automatic in the meaning that the system selects the appropriate load module and revision. A SWA may be related to a slot, indicating that a specific functionality is requested at this location. The SWA is manually created by the operator.
+
+The SWA object is related to (one or more) repertoires, which hold information on possible PIU-type/revisions and load module combinations.
+
+In some cases (e.g multi-purpose boards, boards with processor/FPGA-pools) it may not be possible to completely configure the PIU without instructions from the operator (e.g which load module runs on which processor/FPGA). In these cases a specialization of the SWA has to be designed in such a way that it can be manually configured.
+
+When a SwAllocation MO depends on a ManagedObject MO, this ManagedObject actually represents a RBS Fan.
+
+MOs of this type are created automatically during system upgrade.
+MOs of this type are possible to create manually but a system upgrade is recommended to create them.</description>
+ <attribute name="userLabel">
+ <description>Free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="role">
+ <description>The role of a slot/PIU. The role must be unique with respect to other SwAllocations in the node.
+
+This is a preparation to introduce predefined SwAllocation in future upgrade packages.</description>
+ <mandatory/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="repertoireList">
+ <description>A list of references to repertoires.</description>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="Repertoire"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="slotList">
+ <description>A list of references to mainly slots in a subrack, e.g. Slot or Fan MO. It may also refer to other objects handling auxiliary units, e.g. RBS Fan.</description>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="SwAllocationId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="addRepertoire">
+ <description>Adds the specifed repertoire to this list.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="aRepertoire">
+ <in/>
+ <dataType>
+ <moRef name="Repertoire"/>
+ </dataType>
+ </parameter>
+ <raisesException name="IllegalArgumentTypeException"/>
+ </action>
+ <action name="deleteRepertoire">
+ <description>Removes the first occurrence of the specified repertoire from this list.
+
+Notw! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="aRepertoire">
+ <in/>
+ <dataType>
+ <moRef name="Repertoire"/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="addSlot">
+ <description>Adds the specified Slot to the slotList.
+The slot can only be of type Slot MO, Fan MO, WebServer MO, JVM MO or an applicable type of application MO (e.g. for "RBS Fans").
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="aSlot">
+ <in/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </parameter>
+ <raisesException name="IllegalArgumentTypeException"/>
+ </action>
+ <action name="deleteSlot">
+ <description>Removes the first occurrence of the specified slot from this list.
+The slot can only be of type Slot MO, Fan MO, WebServer MO or an
+applicable type of application MO (e.g. for "RBS Fans").
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="aSlot">
+ <in/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="deleteAllRepertoires">
+ <description>Removes all repertoires from this list and sets its size to zero.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="deleteAllSlots">
+ <description>Removes all slots from this list and sets its size to zero.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="addSlots">
+ <description>Adds the specified Slot to the slotList.
+The slot can only be of type Slot MO, Fan MO, WebServer MO, JVM MO or an applicable type of application MO (e.g. for "RBS Fans").
+If the slot exists in the list, the object is ignored.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="managedObjects">
+ <in/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </parameter>
+ <raisesException name="IllegalArgumentTypeException"/>
+ </action>
+ <action name="addRepertoires">
+ <description>Adds the specifed repertoire to this list.
+
+If the repertoires exist in the list the repertoire is ignored.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="repertoire">
+ <in/>
+ <dataType>
+ <sequence>
+ <moRef name="Repertoire"/>
+ </sequence>
+ </dataType>
+ </parameter>
+ <raisesException name="IllegalArgumentTypeException"/>
+ </action>
+ </class>
+
+ <class name="MediumAccessUnit">
+ <description>The Medium Access Unit (MAU) MO represents the Ethernet transceiver function on a General Processor Board (GPB).
+
+Note! Ethernet links which are modelled by a MediumAccessUnit MO are used for O&amp;M IP traffic only. MediumAccessUnit MOs must not be configured under a GeneralProcessorUnit MO which have a IpAccessHostGpb referring to it.
+
+Note! This object is known in standards as "MediumAttachmentUnit".
+</description>
+ <attribute name="userLabel">
+ <description>Label for free use.
+</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Description of operational state which has an enumerated datatype</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="MediumAccessUnitId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="connectorLabel">
+ <description>This attribute is used by a management system to show the label on the port the connector is attached to.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>Eth</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDot3StatsLateCollisions">
+ <description>Performance management counter for the number of times that a collision was detected on the interface after the minimum length of a frame.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDot3StatsFCSErrors">
+ <description>Performance management counter for the number of frames that did not pass the FCS check.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="linkSpeed">
+ <description>The Link Speed, measurment unit is Mb/s..</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="duplexMode">
+ <description>The duplex mode used.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="MauDuplexMode">
+ <defaultValue>FULL_DUPLEX</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="ReliableProgramUniter">
+ <description>A Reliable Program Uniter (RPU) is a controlling and addressing entity providing one common addressing unit for two Reliable Programs. Or more correctly for parts of two Reliable Programs, each part is called a Resource Suite Handler (RSH). The RSH is implemented and owned by the application. It is not a function or a concept within Cello.
+
+MOs of this type are created automatically during system upgrade.
+MOs of this type are possible to create manually but a system upgrade
+is recommended to create them.</description>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reliableProgramLabel">
+ <description>Reliable Program Label.
+Compare this to the reliableProgramLabel in LoadModule MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="admActiveSlot">
+ <description>Reference to slot, contains the running "Normal" relation to a slot. If the reference is set to the passive slot, the passive slot will be cleared and only one relation will be set.</description>
+ <mandatory/>
+ <dataType>
+ <moRef name="Slot"/>
+ </dataType>
+ </attribute>
+ <attribute name="admPassiveSlot">
+ <description>Reference to slot, contains the running "Stand-by" relation to a slot. If the reference is set to the active slot or a null value, the passive slot will be cleared. </description>
+ <dataType>
+ <moRef name="Slot"/>
+ </dataType>
+ </attribute>
+ <attribute name="switchOver">
+ <description>This attribute controls when to switchover the RPU, if a certain type error situation occurs.</description>
+ <dataType>
+ <enumRef name="RPUSwitchOverMode">
+ <defaultValue>AtPiuFault</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="normalisation">
+ <description>This attribute controls when to switch back the RPU, after error recovery has been done.</description>
+ <dataType>
+ <enumRef name="RPUNormalisationMode">
+ <defaultValue>Automatic</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="replication">
+ <description>This attribute indicates that which level of data replication that is associated with the RPU.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="RPUReplicationMode">
+ <defaultValue>ApplControlled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalMode">
+ <description>This attribute indicates if the RSH execution mode (active/passive) in the two Reliable Program, matches the normal/stand-by relations set on the corresponding RPU.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="RPUOperationalMode">
+ <defaultValue>Unavailable</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="ReliableProgramUniterId">
+ <mandatory/>
+ <noNotification/>
+ <nonPersistent/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <action name="switch">
+ <description>This action will force the two corresponding RSHs to change their execution mode (active/passive). It will lead either to a switchover or to a switchback, depending of what value the operational Mode attribute is showing.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="ActionNotAllowedException"/>
+ </action>
+ </class>
+
+ <class name="ManagedElementData">
+ <description>This object contains attributes and actions on Cello node-level.
+
+The ManagedElementData MO is automatically created and cannot be deleted.
+
+The local distinguished name of this MO is ManagedElement=1, ManagedElementData=1.</description>
+ <systemCreated/>
+ <attribute name="ManagedElementDataId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="autoConfigurationAllowed">
+ <description>This attribute specifies if the system is allowed to auto create detected objects. Note that slots will always be auto created.
+
+Note! When setting this attribute from true to false the system creates a new CV.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="documentServerAddress">
+ <description>The base URL for the documentation server (ALEX). The attribute is read by Element Management application to find the documentation server in the network.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="logonServerAddress">
+ <description>A list of node names or IP addresses of the single logon servers (SLSs). The list uses commas to seperate the single logon server addresses, e.g. "https://SLS1,https://SLS2,https://SLS3", these addresses consists of the URLs to the concerned SLS servers. The attribute is read by Element Management application to find the single logon server in the network.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="dhcpServerAddresses">
+ <description>IP addresses to the DHCP server, used by the DHCP Relay Agent.
+
+Default is an empty array.
+
+Adding and removing addresses is done through the actions addDhcpServerAddress() and removeDhcpServerAddress().
+
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <string>
+ <defaultValue>empty</defaultValue>
+ </string>
+ <length>10</length>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="performanceDataPath">
+ <description>This attribute is used by the internal performance management service
+to know where to store it's data files. The attribute is the name of
+a path in the node.
+
+Example: /c/public_html/cello/XML_files/</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ntpServerAddressPrimary">
+ <description>This is the IP address to the NTP server</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ntpServiceActivePrimary">
+ <description>This is a boolean that controls if the node should poll the primary NTP server for information.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="ntpMinPollPrimary">
+ <description>This value states the minimum interval (in seconds) for polling the primary NTP server.
+
+Note! This value has to be &gt; 0.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>16</min> <max>131072</max>
+ </range>
+ <defaultValue>64</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ntpMaxPollPrimary">
+ <description>This value states the maximum interval (in seconds) for polling the primary NTP server.
+
+Note! This value has to be &gt; 0.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>16</min> <max>131072</max>
+ </range>
+ <defaultValue>1024</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ntpBurstFlagPrimary">
+ <description>This is the burst flag used towards the primary NTP server.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="ntpServerAddressSecondary">
+ <description>This is an alternative IP address to a NTP server</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ntpServiceActiveSecondary">
+ <description>This is a boolean that controls if the node should poll the secondary NTP server for information.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="ntpMinPollSecondary">
+ <description>This value states the minimum interval (in seconds) for polling the secondary NTP server.
+
+Note! This value has to be &gt; 0.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>16</min> <max>131072</max>
+ </range>
+ <defaultValue>64</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ntpMaxPollSecondary">
+ <description>This value states the maximum interval (in seconds) for polling the secondary NTP server.
+
+Note! This value has to be &gt; 0.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>16</min> <max>131072</max>
+ </range>
+ <defaultValue>1024</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ntpBurstFlagSecondary">
+ <description>This is the burst flag used towards the secondary NTP server.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="nodeUTCTime">
+ <description>This attribute specifies the UTC time used in the node. The attribute value is milliseconds since epoch (January 1, 1970, 00:00:00 GMT).
+The value may only be set while ntpServiceActive both for primary and secondary is false.</description>
+ <dataType>
+ <longlong>
+ <defaultValue>0</defaultValue>
+ </longlong>
+ </dataType>
+ </attribute>
+ <attribute name="nodeLocalTimeZone">
+ <description>This value states in what time zone the node is located. This attribute is needed by management application to convert UTC time from a log or NTP service to local time.
+It will not change the real time clock on the node.
+
+The timeZone is represented by three characters, example GMT.
+
+Available options are:
+
+TimeZone ID Offset
+GMT (Greenwich Mean Time) 0
+UTC (Coordinated Universal Time) 0
+ECT ( Central European Standard Time) + 1
+EET (Eastern European Time) + 2
+ART (Eastern European Time) + 2
+EAT (Eastern African Time) + 3
+MET (Iran Time) + 3.5
+NET (Armenia Time) + 4
+PLT (Pakistan Time) + 5
+IST (India Standard Time) + 5.5
+BST (Bangladesh Time) + 6
+VST (Indochina Time) + 7
+CTT (China Standard Time) + 8
+JST (Japan Standard Time) + 9
+CST (Central Standard Time) + 9.5
+EST (Eastern Standard Time) + 10
+AET (Eastern Standard Time) + 10
+SST (Solomon Is. Time) + 11
+NST (New Zealand Standard Time) + 12
+CAT (Central Alaska Time) - 1
+AGT (Argentina Time) - 3
+BET (Brazil Time) - 3
+CNT (Newfoundland Standard Time) - 3.5
+PRT (Atlantic Standard Time) - 4
+IET (Eastern Standard Time) - 5
+ACT (Central Standard Time) - 6
+PNT (Mountain Standard Time) - 7
+MST (Mountain Standard Time) - 7
+PST (Pacific Standard Time) - 8
+AST (Alaska Standard Time) - 9
+HST (Hawaii Standard Time) - 10
+MIT (West Saoma Time) - 11
+--
+
+Reference: http://www.greenwichmeantime.com
+</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="daylightSavingTime">
+ <description>This attribute states weather daylight saving time is used on this node. It is used to by the management application and will not change the real time clock on the node.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="hdVolumeCSize">
+ <description>The total size of the C volume on the Cello node in bytes. The C volume may be replicated on several hard disks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="hdVolumeCFreespace">
+ <description>The number of bytes of free space available on the C volume. The C volume may be replicated on several hard disks in a Cello node.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="nodeUniqueID">
+ <description>This is a unique node identity to be set only in the factory.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="swServerUrlList">
+ <description>A list of URLs of external server for downloading of software. A comma-separated list or URLs, complete with path and name of property file.
+
+Note: For downloading of software for system upgrade, see attribute ftpServerIpAddress in MO UpdradePackage.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="piuGroupEscalationType">
+ <description>The type of node restart when it is a problem with the last PIU in a PIU group.</description>
+ <dataType>
+ <enumRef name="NodeRestartType">
+ <defaultValue>WARM_AT_PIU_RESTART</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="syncModeOperation">
+ <description>The sync mode operation of the node. Note that this attribute is only relevant when the node contains CBU board. For all other cases the value shall be set to NOT_USED.</description>
+ <dataType>
+ <enumRef name="SyncMode">
+ <defaultValue>NOT_USED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <action name="createNtpPrimary">
+ <description>This action creates the primary Network Time Protocol. There can only exist one primary and one secondary ntp.
+
+Once the ntp is created it is possible to change the attributes, i.e ip address, burst flag, max- and min poll and which is the active one.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="ntpServerAddressPrimary">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="ntpMinPollPrimary">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <parameter name="ntpMaxPollPrimary">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <parameter name="ntpBurstFlagPrimary">
+ <in/>
+ <dataType>
+ <boolean/>
+ </dataType>
+ </parameter>
+ <parameter name="ntpServiceActivePrimary">
+ <in/>
+ <dataType>
+ <boolean/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="createNtpSecondary">
+ <description>This action creates the secondary/alterative Network Time Protocol.
+There can only exist one primary and one secondary ntp.
+
+Once the ntp is created it is possible to change the attributes, i.e ip address, burst flag, max- and min poll and which is the active one.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="ntpServerAddressSecondary">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="ntpMinPollSecondary">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <parameter name="ntpMaxPollSecondary">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <parameter name="ntpBurstFlagSecondary">
+ <in/>
+ <dataType>
+ <boolean/>
+ </dataType>
+ </parameter>
+ <parameter name="ntpServiceActiveSecondary">
+ <in/>
+ <dataType>
+ <boolean/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="deleteNtpPrimary">
+ <description>This action deletes the primary NTP.
+
+An exception will be thrown if the primary attributes are accessed (set and get).
+
+Note! This action requires a transaction.
+</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="deleteNtpSecondary">
+ <description>This action deletes the secondary NTP.
+
+An exception will be thrown if the secondary attributes are accessed (set and get).
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="addDhcpServerAddress">
+ <description>Takes an array of Ip addresses (Strings), and adds them to the list held by the Dhcp Relay Agent fRO.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="ipAddressArray">
+ <description>Elements are assumed to have the format of a String with 4 fields of numerics, each field separated with a dot. E.g. 123.322.34.123. An empty array or empty string in first element is not allowed. Max 10 elements.</description>
+ <in/>
+ <dataType>
+ <sequence>
+ <string/>
+ </sequence>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="removeDhcpServerAddress">
+ <description>Takes an array of Ip addresses (Strings), and removes them from the list held by the Dhcp Relay Agent fRO.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="ipAddressArray">
+ <description>Elements are assumed to have the format of a String with 4 fields of numerics, each field separated with a dot. E.g. 123.322.34.123. An empty array or empty string in first element is not allowed. Max 10 elements.</description>
+ <in/>
+ <dataType>
+ <sequence>
+ <string/>
+ </sequence>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="setNodeUniqueId">
+ <description>Used for setting the nodeUniqueId attribute. This method should only be used in the factory, i.e. it is not for general use by the operator.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="nodeUniqueId">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ </class>
+
+ <class name="SwitchExtensionUnit">
+ <description>This MO represents the Switch Extension Unit, SXU, board. The board may only be inserted in slot 2-27 (in a standard subrack).
+If redundant links are used, two boards must be inserted next to each other.
+The board has a number of switch internal link ports.</description>
+ <attribute name="SwitchExtensionUnitId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>This attribute is used to hold a user friendly name of the object if needed.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeStateSil">
+ <description>The administrative state of switch internal link ports on the switch board.
+The attribute refers to all ports (locking will lock all ports, unlocking will unlock all ports).
+SIL- switch internal link.
+
+</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>unlocked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalStateSil">
+ <description>Operational State for all ports. Operational state is enabled if one of the eight ports is enabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalStateSync">
+ <description>Operational State for network synchronization distribution</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusSil">
+ <description>The availability state of switch internal link (sil) ports.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusSync">
+ <description>The availability state of the sync link.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The attribute is set by the action Reserve.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="SilPorts">
+ <description>The attribute provides a list of port numbers.
+The port number is between 0-7 and is used to read state of the switch internal port.
+Se action getSilPortState, getSilOperState and getSilAvailState.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <long/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <action name="getSilPortState">
+ <description>Returns status of the switch internal link port.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <enumRef name="SilPortState">
+ </enumRef>
+ </returnType>
+ <parameter name="portNr">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="getSilOperState">
+ <description>Returns operational status of the switch internal link port.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <enumRef name="OperState">
+ </enumRef>
+ </returnType>
+ <parameter name="portNr">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="getSilAvailState">
+ <description>Returns availability status of the switch internal link port.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <long/>
+ </returnType>
+ <parameter name="portNr">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ </class>
+
+ <class name="Aal2PathDistributionUnit">
+ <description>This MO is used to represent an AAL2 Path Distribution Unit. Such a unit handles a set of Aal2PathVccTps that belong to the same Aal2 AP and that are handled by the same Path Resource Handling Program.
+This Path Resource Handling Program is referenced by the rpuId attribute.</description>
+ <attribute name="Aal2PathDistributionUnitId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="rpuId">
+ <description>The physical location of a CPS RC (Common Part Sub-Layer Resource Control) program represented by a reference to a ReliableProgramUniter.
+
+Note that one ReliableProgramUniter MO may only be referenced once under one Aal2Ap. That means all Aal2PathDistributionUnits must reference different ReliableProgramUniter MO's.
+
+Two Aal2PathDistributionUnits under different Aal2Ap's may however reference the same ReliableProgramUniter MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ReliableProgramUniter"/>
+ </dataType>
+ </attribute>
+ <attribute name="aal2PathVccTpList">
+ <description>List of references to Aal2PathVccTp MO:s.
+Note that setting of this attribute removes the current list of Aal2PathVccTp's.
+Each reference must be unique among all paths within all Aal2PathDistributionUnit's belonging to the same Aal2Ap.</description>
+ <dataType>
+ <sequence>
+ <moRef name="Aal2PathVccTp"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <action name="addPath">
+ <description>This action adds a list of Aal2PathVccTps to an Aal2PathDistributionUnit.
+
+If the data contains a reference to a non existing path, the exception InvalidReference is raised.
+
+If the path list contains a path that has a non-unique aal2PathId value, then the exception Aal2PathIdNotUnique is raised. The pathId value must be unique within all Aal2PathDistributionUnits under the same Aal2Ap.
+
+If the path list contains a path that already belongs to a Aal2PathDistributionUnit, then the exception PathAlreadyRegistered is raised.
+
+Note! Adding one or more Aal2PathVccTps using this action updates the attribute 'Aal2PathVccTpList'.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="aal2PathVccTpId">
+ <in/>
+ <dataType>
+ <sequence>
+ <moRef name="Aal2PathVccTp"/>
+ </sequence>
+ </dataType>
+ </parameter>
+ <raisesException name="InvalidReferenceException"/>
+ <raisesException name="Aal2PathIdNotUniqueException"/>
+ <raisesException name="PathAlreadyRegisteredException"/>
+ </action>
+ <action name="removePath">
+ <description>This action removes a list (sequence) of AAL2 path's from the Aal2PathDistributionUnit.
+
+If the path list contains a path that is not in this Aal2PathDistributionUnit, the exception NotInGroup is raised.
+
+Note! Removing one or more Aal2PathVccTps using this action updates the attribute 'Aal2PathVccTpList'.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="aal2PathList">
+ <in/>
+ <dataType>
+ <sequence>
+ <moRef name="Aal2PathVccTp"/>
+ </sequence>
+ </dataType>
+ </parameter>
+ <raisesException name="NotInGroupException"/>
+ </action>
+ </class>
+
+ <class name="Fan">
+ <description>The Fan is used for cooling the Cello-subrack and is connected to one or two
+SCU (switch core board). This MO is used for controlling and sending alarm from
+the Fan.
+
+Note, either the fan can be supplied by Cello and Fan MO is used, or alternatively the fan can supplied by a source external to Cello and therefore a ManagedObject MO is used to represent the fan.
+
+</description>
+ <attribute name="FanId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>user label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrativeState of Fan MO.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="connectedToScu">
+ <description>A Fan must always be connected to a Switch Core unit that mediates the communication with a main processor.
+
+In this attribute it is possible to see which SwichCoreUnit that the fan is connected to.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="SwitchCoreUnit"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state is set to 'enabled' when the Fan has loaded and started its load module.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="piuType">
+ <description>A reference to an available PiuType at create of a Fan.
+</description>
+ <mandatory/>
+ <dataType>
+ <moRef name="PiuType"/>
+ </dataType>
+ </attribute>
+ <attribute name="controllingState">
+ <description>The application that controls the Fan has three main states:
+- standalone: running on itself, not manageable
+- autonomous: manageable state
+- noiseReduced: temporary state with reduced cooling
+
+NOTE: This attribute is not supported in CPP 4.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="FanState">
+ <defaultValue>standalone</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="hdlcAddress">
+ <description>The physical address of the RS-485 communication link.
+Incorrect setting of the address can cause collision with other connected auxiliary units or lost connection. The default value should be suitable for most configurations.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>255</max>
+ </range>
+ <defaultValue>7</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO. </description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <action name="restartFan">
+ <description>A restart will cause the Fan to be initiated, re-booted and all load modules to be reloaded from persistent memory. This is also known as a forced reload.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="restartCause">
+ <in/>
+ <dataType>
+ <enumRef name="RestartCause">
+ </enumRef>
+ </dataType>
+ </parameter>
+ <raisesException name="EquipException"/>
+ <raisesException name="ValueOutOfRangeException"/>
+ </action>
+ </class>
+
+ <class name="Mtp2TpItu">
+ <description>This MO represents a MTP2 Termination Point for the ITU standard, as defined in Recommendation Q.703 07/96.
+
+The performance monitoring counters found in Mtp2Itu MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is a hardware fault, aal1 server/adm restart or node restart.
+
+NOTE: This MO cannot in anyway be related (either contain or by dependence) to an MO that belongs to a standard
+which is NOT the ITU standard.
+
+NOTE: There is a restriction of a maximum of 32 Mtp2Tp's per MP.</description>
+ <attribute name="userLabel">
+ <description>Free tag for marking this managed object.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="Mtp2TpItuId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the MTP2 Signalling Terminal.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="mtp2ProfileItuId">
+ <description>Reference to a Mtp2ProfileItu MO.
+
+Note: The bitRate can not be changed.</description>
+ <mandatory/>
+ <noNotification/>
+ <dataType>
+ <moRef name="Mtp2ProfileItu"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfReTransmittedOctets">
+ <description>Number of re-transmitted octets.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfNacks">
+ <description>Number of negative acknowledgements received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuReceivedInError">
+ <description>Number of signal units received in error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfStartedRBCongestion">
+ <description>Number of started local RB congestions.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSendBufferOctets">
+ <description>Number of octets in send buffer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLocalSIBTime">
+ <description>Total time in local SIB (Sending).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmRemoteSIBTime">
+ <description>Total time in remote SIB (Receiving).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSIOSIFTransmitted">
+ <description>Number of SIO &amp; SIF octets transmitted.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The attribute is set by the list of reserving MO's.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Mtp3bSlItu"/>
+ </dataType>
+ </attribute>
+ <attribute name="ds0BundleId">
+ <description>The Ds0Bundle MO that this MO references.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Ds0Bundle"/>
+ </dataType>
+ </attribute>
+ <attribute name="plugInUnitId">
+ <description>The PlugInUnit MO that this MO references.
+It indicates on which processor the Termination Point will be.
+
+Note: The PlugInUnit must be of type GPB.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="PlugInUnit"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUTransmitted">
+ <description>Number of MSUs transmitted.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSIOSIFReceived">
+ <description>Number of SIO and SIF octets received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUReceived">
+ <description>Number of MSUs received..</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp2TpAnsi">
+ <description>This MO represents a MTP2 Termination Point for the ANSI standard , as defined in T1.111-1996.
+
+The performance monitoring counters found in Mtp2Ansi MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is a hardware fault, aal1 server/adm restart or node restart.
+
+NOTE: This MO cannot in anyway be related (either contained by or dependent on) an MO that belongs to a
+standard which is NOT the ANSI standard.
+
+NOTE: There is a restriction of a maximum of 32 Mtp2Tp's per MP.</description>
+ <attribute name="userLabel">
+ <description>Free tag for marking this managed object.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="Mtp2TpAnsiId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the MTP2 Signalling Terminal.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="mtp2ProfileAnsiId">
+ <description>Reference to a Mtp2ProfileAnsi MO.
+
+Note: The bitRate can not be changed.</description>
+ <mandatory/>
+ <noNotification/>
+ <dataType>
+ <moRef name="Mtp2ProfileAnsi"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfReTransmittedOctets">
+ <description>Number of re-transmitted octets.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfNacks">
+ <description>Number of negative acknowledgements received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuReceivedInError">
+ <description>Number of signal units received in error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfStartedRBCongestion">
+ <description>Number of started local RB congestions.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSendBufferOctets">
+ <description>Number of octets in send buffer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLocalSIBTime">
+ <description>Total time in local SIB (Sending).
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmRemoteSIBTime">
+ <description>Total time in remote SIB (Receiving).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSIOSIFTransmitted">
+ <description>Number of SIO &amp; SIF octets transmitted.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUReceived">
+ <description>Number of MSUs received..</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Mtp3bSlAnsi"/>
+ </dataType>
+ </attribute>
+ <attribute name="ds0BundleId">
+ <description>The Ds0Bundle MO that this MO references.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Ds0Bundle"/>
+ </dataType>
+ </attribute>
+ <attribute name="plugInUnitId">
+ <description>The PlugInUnit MO that this MO references.
+It indicates on which processor the Termination Point will be.
+
+Note: The PlugInUnit must be of type GPB.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="PlugInUnit"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUTransmitted">
+ <description>Number of MSUs transmitted.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSIOSIFReceived">
+ <description>Number of SIO and SIF octets received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Ds0Bundle">
+ <description>The Ds0Bundle, Digital Signalling Level 0, MO represents a number of timeslots on a physical port.
+Any of E1PhysPathTerm, J1PhysPathTerm, T1PhysPathTerm, E1Ttp or T1Ttp.
+The Ds0Bundle can be used in three different ways:
+
+- Fractional ATM
+
+Please refer to the AtmPort MO for details. Note that the TdmMode attribute
+must be disabled.
+
+-Circuit emulation
+
+Please refer to Aal1VccTp MO for details. Note that the TdmMode attribute
+must be disabled. Note that only 4 Ds0Bundle's per port can be configured
+when running circuit emulation.
+
+- TDM Switching
+
+The Ds0Bundle is reserved for switching node internal Ds0 connections. In
+this mode, the tdmMode attribute should be enabled.
+
+
+</description>
+ <attribute name="Ds0BundleId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Free tag for marking this managed object.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availabiltity status of Ds0Bundle.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of Ds0Bundle.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="listOfTimeSlots">
+ <description>The list gives the time slots (within ATM traffic fraction) that are to be allocated to the Ds0Bundle.
+
+When a Ds0Bundle is contained by a E1PhysPathTerm the slots that can be placed in this list are 1 to 31.
+When a Ds0Bundle is contained by a J1PhysPathTerm then the slots that can be placed in this list are 1 to 24.
+When a Ds0Bundle is contained by a T1PhysPathTerm then the slots that can be placed in this list are 1 to 24.
+When a Ds0Bundle is contained by a E1Ttp the slots that can be placed in this list are 1 to 31.
+
+Note: the same timeslot cannot appear more than once in the list! If a E1/J/T1PhysPathTerm contains more than
+one Ds0Bundle, then the Ds0Bundles listOfTimeSlots must be mutually exclusive (i.e. slots in one list cannot be used in another list).
+
+Note! If the Ds0Bundle is used for carrying SS7 traffic, the listOfTimeSlots can only contain 1 (one) time slot.
+In this case that is if the Ds0Bundle is reserved by an Mtp2TpAnsi, Mtp2TpItu or Mtp2TpChina.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <sequence>
+ <long>
+ <range>
+ <min>0</min> <max>31</max>
+ </range>
+ </long>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="tdmMode">
+ <description>The state of tdmMode (Time Division Multiplexing), can be disabled/enabled.
+
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Aal1TpVccTp">
+ <description>The Aal1TpVccTp MO represents the Aal1 interworking function in a circuit emulation. The object refers to a Ds0Bundle which represents one end of the circuit emulation, and a VclTp which represents the other end.
+
+Note! The performance monitoring counters in this MO is set to 0 when counterMode is set to PM_MODE_ON.
+In PM_MODE_OFF no information at all is retrived. So any value for pm-monitoring is measured from the time
+of setting counterMode to PM_MODE_ON.
+At node restart these performance monitoring counters is reset to 0.</description>
+ <attribute name="userLabel">
+ <description>Free tag for marking this managed object.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ds0BundleId">
+ <description>The Ds0Bundle MO that this MO references.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Ds0Bundle"/>
+ </dataType>
+ </attribute>
+ <attribute name="partialFill">
+ <description>Indicates how many bytes are filled in each ATM cell. The value 47 indicates that the partial filled cells is not used, i.e. all the cells are filled completely.
+
+Partial filling of cells in used in circuit emulation. It is used to reduce packetisation delay. Refer to the ATM Forum specifications for more details.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>23</min> <max>47</max>
+ </range>
+ <defaultValue>47</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="cdvt">
+ <description>Specifies the cell delay variation tolerance. Refer to ATM Forum specifications for more details.
+
+Unit is micro seconds.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>100</min> <max>4000</max>
+ </range>
+ <defaultValue>1000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of Aal1TpVccTp.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="continuityCheck">
+ <description>Continuitiy checking means that a cell is sent downstream when no user cell has been sent for a period of nominally 1 second.
+
+Activates VC end to end continuityCheck according to ITU.T rec I.610.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="counterMode">
+ <description>Controls the activation of PM counters and F5 PM flow on the VC connection.</description>
+ <dataType>
+ <enumRef name="AtmCounterMode">
+ <defaultValue>PM_MODE_OFF</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="nomPmBlockSize">
+ <description>Nominal performance monitoring (PM) blocksize. The minimum number of ATM cells to send before sending a Forward Performance Monitoring, FPM, cell.</description>
+ <dataType>
+ <enumRef name="AtmNomPmBlkSize">
+ <defaultValue>NOM_PM_BLKSIZE_2_10</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwLostCells">
+ <description>Performance monitoring counter for forwarded lost cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwMissinsCells">
+ <description>Performance monitoring counter for number of forwarded missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwErrBlocks">
+ <description>Performance monitoring counter for number of forwarded errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostFpmCells">
+ <description>Performance monitoring counter for number of lost Forward Performance Monitoring, FPM cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwLostCells">
+ <description>Performance monitoring counter for number of lost backward cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwMissinsCells">
+ <description>Performance monitoring counter for number of backward missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwErrBlocks">
+ <description>Performance monitoring counter for number of backward errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostBrCells">
+ <description>Performance monitoring counter for number of lost Backward Reporting, BR, cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="Aal1TpVccTpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="vclTpId">
+ <description>The VclTp MO that this MO references.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="VclTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="alarmReport">
+ <description>Attribute to decide what type of alarms to be reported.</description>
+ <dataType>
+ <enumRef name="AlarmReport">
+ <defaultValue>ALARM_LOC</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp3bSpAnsi">
+ <description>Mtp3b Signalling Point for the ANSI standard.
+
+This MO represents/models the MTP3b Signaling Point characteristics/functions according to the Ansi standard.
+A signaling point is a logical node in the signaling network. The combination of signaling points and their interconnecting
+signaling links form the SS No. 7 signaling network. The signaling point represented by this object is a Local Signaling Point.
+
+The performance monitoring counters found in Mtp3SpAnsi MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).
+
+NOTE: IT IS NOT POSSIBLE TO CREATE SIGNALLING POINTS OF DIFFERENT STANDARDS!
+
+NOTE: This MO cannot in anyway be related (either contain or by dependence) to an MO that belongs to a standard which is NOT the ANSI standard.
+
+NOTE: The combination of network indicator (networkInd) and Signalling Point Code (signallingPointCode) has to be unique for each Signalling Point.
+
+NOTE: A maximum of 15 instances of this MO can be created on (referencing) the same PlugInUnit.
+
+NOTE: The maximum number of Signalling Points that can be created in a CPP based node is 24.
+
+NOTE: Deleting a singel L3 Signal Point is not possible, if it necessary to delete a Signal Point then all Signal Points has to be deleted. This also has to be done whitin the same transaction.
+
+NOTE: Any object created under a certain SP (Signaling Point) cannot refer to an object created under another SP. Nor can it refer to an object created under another SP.</description>
+ <attribute name="Mtp3bSpAnsiId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="rpuId">
+ <description>Holds a reference to the Reliable Program Uniter.
+The RPU is at the server.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ReliableProgramUniter"/>
+ </dataType>
+ </attribute>
+ <attribute name="networkInd">
+ <description>The network indicator, NI, is used for discrimination of messages between functionally different networks.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="Mtp3bNetworkInd">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="signallingPointCode">
+ <description>The signallingPointCode (Local Point Code) attribute (SPC) is used together with the network indicator (NI, networkInd attribute) to uniquely identify the MTP Signalling Point, SP.
+SP = NI-SPC.
+Size (2 exp 24)-1 (16777215).
+The SignallingPointCode (SPC) is normally grouped together as three numbers wich correspond to network identifier, network cluster, network cluster member. The three numbers are coded as 8-8-8 bits in the total SPC. To enter the SPC-value, you have to convert the 3 numbers to their binary code and then convert the whole 24-bit patterna as an integer. Sometimes the SPC is used as a whole uniqe number (no internal structure).
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16777215</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="testPatternSltm">
+ <description>The testPatternSltm attribute represents a string testpattern in the Signalling Link Test Message.
+
+Minimum string length 2 characters, maximum 30 characters. Allowed characters are 0-9, A-F.
+Only even number of characters is allowed.</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>2</min> <max>30</max>
+ </lengthRange>
+ <defaultValue>"A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="nodeBehaviour">
+ <description>The nodeBehaviour attribute represents the MTP3b node type.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="NodeBehaviourType">
+ <defaultValue>SEP</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="maxSizeReroutBuf">
+ <description>The maxSizeReroutBuf attribute represents the maximum size (in kB) of the rerouting buffer.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>5000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxSizeChangeBuf">
+ <description>The maxSizeChangeBuf attribute represents the maximum size (in kB) of the changeover buffer.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>5000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="transFrHandler">
+ <description>Determines how a TransFer Restricted signal (TFR) should be treated.
+</description>
+ <dataType>
+ <enumRef name="Mtp3bTfrHandling">
+ <defaultValue>IGNORED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="sioSpare">
+ <description>The sioSpare2 attribute determines if the two spare bits in the SIO (Service Information Octet) should be treated as spare.</description>
+ <dataType>
+ <enumRef name="Mtp3bSioSpareBitsUse">
+ <defaultValue>PRIO</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="m3uaNoOfAttempsOfDauds">
+ <description>For M3UA, number of attempts to send the DAUD message.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="noOfAttempsOfAssociationEstablishment">
+ <description>Number of attempts to send the SCTP_ASSOCIATE_REQ message.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>65535</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="statusIndInterval">
+ <description>The statusIndInterval attribute sets the interval for sending MTP-STATUS indication, i.e. send indication every Nth message .</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="resendTfcInterval">
+ <description>Send TFC back to originating signalling point code for every n:th message when
+the destination is congested. Set to 0 will suppress sending of TFC.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="sendSltmBefLink">
+ <description>The sendSltmBefLink attribute determines if the SLTM (Signalling Link Test Message) should be sent and a SLTA received before the link is considered to be in service.
+
+Note! It is not recommended nor is it in accordance with standard to set the value of this attribute to 'false' </description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="spPriority">
+ <description>Struct containing the ANSI priority attributes.
+</description>
+ <dataType>
+ <structRef name="Mtp3bSpAnsiPriorityData"/>
+ </dataType>
+ </attribute>
+ <attribute name="noOfCongestLevelForNI">
+ <description>Defines the number of congestion levels for NI.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>3</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="routeSetCongestTestFlag">
+ <description>Selection of which procedure to use during congestion handling if the national option with priorities is used.
+
+0, use TcTimer as described by the TTC standard.
+1, use Route Set Congestion Test as described by the ANSI, ITU and China Standard.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operationalState attribute reflects the operational status of the MTP3b SP.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="spTimer">
+ <description>Struct containing ANSI specific timer data.</description>
+ <dataType>
+ <structRef name="Mtp3bSpAnsiTimerData"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds a list of the reserving MO's. Can be of type SccpSp.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfForcedRerouteSuccessPerf">
+ <description>Performance monitoring counter for number of successfully performed forced rerouting.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfControlledRerouteSuccessPerf">
+ <description>Performance monitoring counter for number of successfully performed controlled rerouting.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfEmergencyChangeOverRec">
+ <description>Performance management counter for number of received emergency changeOver orders (ECO) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfChangeOverRec">
+ <description>Performance counter for number of changeOver order messages (COO/XCO) received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfChangeBackDeclRec">
+ <description>Performance management counter for number of received change Back Declarations (CBD) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSLTAFirstTimeOutRec">
+ <description>Performance management counter for number of SLTA first time out received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSLTASecondTimeOutRec">
+ <description>Performance management counter for number of SLTA second time out received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUPMsgDiscardedDueToRoutingErr">
+ <description>Performance monitoring counter for number of UP (user part) messages (MTP_TRANSFER_req) discarded due to routing error.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOAXCASent">
+ <description>Performance management counter for number of sent COA/XCA messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECOSent">
+ <description>Performance management counter for number of sent ECO messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECASent">
+ <description>Performance management counter for number of sent ECA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOAXCARec">
+ <description>Performance management counter for number of received COA/XCA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBARec">
+ <description>Performance management counter for number of received CBA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECARec">
+ <description>Performance management counter for number of received ECA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTRARec">
+ <description>Performance management counter for number of received TRA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTRASent">
+ <description>Performance management counter for number of sent TRA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTimerT21WasStarted">
+ <description>Performance monitoring counter for number of times the timer T21 was started (i.e. how many times the remote inhibit test message has been sent).
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBASent">
+ <description>Performance management counter for number of sent CBA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessForcedRerouting">
+ <description>Performance monitoring counter for number of unsuccessfully performed forced reroutings.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessControlledRerouting">
+ <description>Performance monitoring counter for number of unsuccessfully performed controlled reroutings.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocEstablish">
+ <description>Performance management counter for number of successful association establishment.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocEstablish">
+ <description>Performance management counter for number of unsuccessful association establishment.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpCommunicationErr">
+ <description>Performance management counter for number of SCTP communication error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpSendFailure">
+ <description>Performance management counter for number of SCTP send failure.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpBufOverflow">
+ <description>Performance management counter for number of SCTP stop sending data.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpResumeSending">
+ <description>Performance management counter for number of SCTP resume sending data.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpNetworkStatusChange">
+ <description>Performance management counter for number of SCTP network status change.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpAssociationRestart">
+ <description>Performance management counter for number of SCTP association restart.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocAbort">
+ <description>The number of successful abortions of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocShutDown">
+ <description>The number of succesful shutdowns of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocAbort">
+ <description>The number of unsuccessful abortions of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocShutDown">
+ <description>The number of unsuccesful shutdowns of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIncomingAssocEstabRequestInStateDownWhenStateEstabIsBlocked">
+ <description>The number of incoming request for association establishment when state on the association is 'DOWN' and establishment of associations is blocked. </description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMaxTrialsForAssocEstabReached">
+ <description>The number of times that the max limit for trying to establish an association has been reached.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMaxTrialsForAssocActivReached">
+ <description>The number of times that the max limit for trying to activate an association has been reached.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLowerPrioMsgDiscarded">
+ <description>The number of messages with low priority that has been discarded.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp3bSpItu">
+ <description>Mtp3b Signalling Point for the ITU standard.
+
+This MO represents/models the MTP3b Signaling Point characteristics/functions according to the ITU standard.
+A signaling point is a logical node in the signaling network. The combination of signaling points and their interconnecting
+signaling links form the SS No. 7 signaling network. The signaling point represented by this object is a Local Signaling Point.
+
+The performance monitoring counters found in Mtp3SpItu MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).
+
+NOTE: IT IS NOT POSSIBLE TO CREATE SIGNALLING POINTS OF DIFFERENT STANDARDS!
+
+NOTE: This MO cannot in anyway be related (either contain or by dependence) to an MO that belongs to a standard which is NOT the ITU standard.
+
+NOTE: The combination of network indicator (networkInd) and Signalling Point Code (signallingPointCode) has to be unique for each Signalling Point.
+
+NOTE: A maximum of 15 instances of this MO can be created on (referencing) the same PlugInUnit.
+
+NOTE: The maximum number of Signalling Points that can be created in a CPP based node is 24.
+
+NOTE: Deleting a singel L3 Signal Point is not possible, if it necessary to delete a Signal Point then all Signal Points has to be deleted. This also has to be done whitin the same transaction.
+
+NOTE: Any object created under a certain SP (Signaling Point) cannot refer to an object created under another SP. Nor can it refer to an object created under another SP.
+
+NOTE: The value of the attribute 'version' is valid for all SPs (Mtp3bSpItu MOs) and the value of the last created or changed SP will be used for all SPs.</description>
+ <attribute name="Mtp3bSpItuId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="networkInd">
+ <description>The networkInd attribute (NI) is used by signalling message handling functions in MTP3b
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="Mtp3bNetworkInd">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="signallingPointCode">
+ <description>The signallingPointCode (Local Point Code) attribute (SPC) is used together with the network indicator (NI, networkInd attribute) to uniquely identify the MTP Signalling Point, SP.
+SP = NI-SPC.
+Size (2 exp 14)-1 (16383).
+The SignallingPointCode (SPC) is normally used as a whole unique number (no internal structure). But sometimes the SPC is grouped together as three numbers which corresponds to zone, area/network, signalling point. If this is the case the three numbers are coded as 3-8-3 bits in the total SPC. To enter the SPC-value then you have to convert the three numbers to their binary code and then convert the whole 14-bit pattern as an integer.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16383</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="version">
+ <description>This attribute shows what MTP3b ITU standard the system follows. With ITU, it is possible using this attribute to set which of the ITU standard versions that shall be followed.
+
+Note! Setting of another value than 'ITU_T_07_96' at create will have no effect. The Signaling Point will always be created with the value 'ITU_T_07_96'.
+
+Note! It is not possible to hav signaling points with different versions in the node so setting of this attribute will effect all signaling points. The value for the last created or changed signaling point will be used for all signaling points.</description>
+ <dataType>
+ <enumRef name="Mtp3bItuVersion">
+ <defaultValue>ITU_T_07_96</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="nodeBehaviour">
+ <description>The nodeBehaviour attribute represents the MTP3b node type.
+
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="NodeBehaviourType">
+ <defaultValue>SEP</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="noOfCongestLevelForNI">
+ <description>Defines the number of congestion levels for NI.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>3</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="routeSetCongestTestFlag">
+ <description>Selection of which procedure to use during congestion handling if the national option with priorities is used.
+
+0, use TcTimer as described by the TTC standard.
+1, use Route Set Congestion Test as described by the ANSI, ITU and China Standard.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="resendTfcInterval">
+ <description>Send TFC back to originating signalling point code for every n:th message when
+the destination is congested. Set to 0 will suppress sending of TFC.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxSizeReroutBuf">
+ <description>The maxSizeReroutBuf attribute represents the maximum size (in kB) of the rerouting buffer.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>5000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxSizeChangeBuf">
+ <description>The maxSizeChangeBuf attribute represents the maximum size (in kB) of the changeover buffer.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>5000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="transFrHandler">
+ <description>Determines if a TransFer Restricted signal (TFR) should be treated as a TFA (TransFer Allowed signal) or be ignored.
+</description>
+ <dataType>
+ <enumRef name="Mtp3bTfrHandling">
+ <defaultValue>IGNORED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="sioSpare">
+ <description>The sioSpare2 attribute determines if the two spare bits in the SIO (Service Information Octet) should be treated as spare.</description>
+ <dataType>
+ <enumRef name="Mtp3bSioSpareBitsUse">
+ <defaultValue>PRIO</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="statusIndInterval">
+ <description>The statusIndInterval attribute sets the interval for sending MTP-STATUS indication, i.e. send indication every Nth message .</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="sendSltmBefLink">
+ <description>The sendSltmBefLink attribute determines if the SLTM (Signalling Link Test Message) should be sent and a SLTA received before the link is considered to be in service.
+
+Note! It is not recommended nor is it in accordance with standard to set the value of this attribute to 'false' </description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="testPatternSltm">
+ <description>The testPatternSltm attribute represents a string testpattern in the Signalling Link Test Message.
+
+Minimum string length 2 characters, maximum 30 characters. Allowed characters are 0-9, A-F.
+Only even number of characters is allowed.
+
+</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>2</min> <max>30</max>
+ </lengthRange>
+ <defaultValue>"A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="spPriority">
+ <description>Struct containing the priority attributes.
+</description>
+ <dataType>
+ <structRef name="Mtp3bSpItuPriorityData"/>
+ </dataType>
+ </attribute>
+ <attribute name="spTimer">
+ <description>Struct containing ITU specific timer attributes</description>
+ <dataType>
+ <structRef name="Mtp3bSpItuTimerData"/>
+ </dataType>
+ </attribute>
+ <attribute name="rpuId">
+ <description>Holds a reference to the Reliable Program Uniter.
+The RPU is at the server.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ReliableProgramUniter"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operationalState attribute reflects the operational status of the MTP3b SP.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="m3uaNoOfAttempsOfDauds">
+ <description>For M3UA, number of attempts to send the DAUD message.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="noOfAttempsOfAssociationEstablishment">
+ <description>Number of attempts to send the SCTP_ASSOCIATE_REQ message.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>65535</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds a list of the reserving MO's. Can be of type SccpSp.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfForcedRerouteSuccessPerf">
+ <description>Performance monitoring counter for number of successfully performed forced rerouting.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfControlledRerouteSuccessPerf">
+ <description>Performance monitoring counter for number of successfully performed controlled rerouting.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfEmergencyChangeOverRec">
+ <description>Performance management counter for number of received emergency changeOver orders (ECO) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfChangeOverRec">
+ <description>Performance counter for number of changeOver order messages (COO/XCO) received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfChangeBackDeclRec">
+ <description>Performance management counter for number of received change Back Declarations (CBD) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSLTAFirstTimeOutRec">
+ <description>Performance management counter for number of SLTA first time out received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSLTASecondTimeOutRec">
+ <description>Performance management counter for number of SLTA second time out received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUPMsgDiscardedDueToRoutingErr">
+ <description>Performance monitoring counter for number of UP (user part) messages (MTP_TRANSFER_req) discarded due to routing error.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOAXCASent">
+ <description>Performance management counter for number of sent COA/XCA messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECOSent">
+ <description>Performance management counter for number of sent ECO messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECASent">
+ <description>Performance management counter for number of sent ECA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOAXCARec">
+ <description>Performance management counter for number of received COA/XCA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBARec">
+ <description>Performance management counter for number of received CBA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECARec">
+ <description>Performance management counter for number of received ECA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTRARec">
+ <description>Performance management counter for number of received TRA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTRASent">
+ <description>Performance management counter for number of sent TRA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTimerT21WasStarted">
+ <description>Performance monitoring counter for number of times the timer T21 was started (i.e. adjacent SP restarted).
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBASent">
+ <description>Performance management counter for number of sent CBA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessForcedRerouting">
+ <description>Performance monitoring counter for number of unsuccessfully performed forced reroutings.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessControlledRerouting">
+ <description>Performance monitoring counter for number of unsuccessfully performed controlled reroutings.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocEstablish">
+ <description>Performance management counter for number of successful association establishment.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocEstablish">
+ <description>Performance management counter for number of unsuccessful association establishment.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpCommunicationErr">
+ <description>Performance management counter for number of SCTP communication error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpSendFailure">
+ <description>Performance management counter for number of SCTP send failure.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpBufOverflow">
+ <description>Performance management counter for number of SCTP stop sending data.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpResumeSending">
+ <description>Performance management counter for number of SCTP resume sending data.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpNetworkStatusChange">
+ <description>Performance management counter for number of SCTP network status change.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpAssociationRestart">
+ <description>Performance management counter for number of SCTP association restart.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocAbort">
+ <description>The number of successful abortions of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocShutDown">
+ <description>The number of succesful shutdowns of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocAbort">
+ <description>The number of unsuccessful abortions of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocShutDown">
+ <description>The number of unsuccesful shutdowns of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIncomingAssocEstabRequestInStateDownWhenStateEstabIsBlocked">
+ <description>The number of incoming request for association establishment when state on the association is 'DOWN' and establishment of associations is blocked. </description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMaxTrialsForAssocEstabReached">
+ <description>The number of times that the max limit for trying to establish an association has been reached.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMaxTrialsForAssocActivReached">
+ <description>The number of times that the max limit for trying to activate an association has been reached.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLowerPrioMsgDiscarded">
+ <description>The number of messages with low priority that has been discarded.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp3bSpTtc">
+ <description>Mtp3b Signalling Point for the TTC standard.
+
+This MO represents/models the MTP3b Signaling Point characteristics/functions according to the TTC standard.
+A signaling point is a logical node in the signaling network. The combination of signaling points and their interconnecting
+signaling links form the SS No. 7 signaling network. The signaling point represented by this object is a Local Signaling Point.
+
+The performance monitoring counters found in Mtp3SpTtc MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).
+
+NOTE: This MO cannot in anyway be related (either contain or by dependence) to an MO that belongs to a
+standard which is NOT the TTC standard.
+
+NOTE: IT IS NOT POSSIBLE TO CREATE SIGNALLING POINTS OF DIFFERENT STANDARDS!
+
+NOTE: The combination of network indicator (networkInd) and Signalling Point Code (signallingPointCode) has to be unique for each Signalling Point.
+
+NOTE: A maximum of 15 instances of this MO can be created on (referencing) the same PlugInUnit.
+
+NOTE: The maximum number of Signalling Points that can be created in a CPP based node is 24.
+
+NOTE: Deleting a singel L3 Signal Point is not possible, if it necessary to delete a Signal Point then all Signal Points has to be deleted. This also has to be done whitin the same transaction.
+
+NOTE: Any object created under a certain SP (Signaling Point) cannot refer to an object created under another SP. Nor can it refer to an object created under another SP.</description>
+ <attribute name="Mtp3bSpTtcId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="networkInd">
+ <description>The networkInd attribute (NI) is used by signalling message handling functions in MTP3b.
+
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="Mtp3bNetworkIndTtc">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="signallingPointCode">
+ <description>The signallingPointCode (Local Point Code) attribute (SPC) is used together with the network indicator (NI, networkInd attribute) to uniquely identify the MTP Signalling Point, SP.
+SP = NI-SPC.
+Size (2 exp 16)-1 (65535).
+The SignallingPointCode (SPC) is always used as a whole unique number (no internal structure).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="nodeBehaviour">
+ <description>The nodeBehaviour attribute represents the MTP3b node type.
+
+Note! Only SEP and STP is supported for the Ttc standard.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="NodeBehaviourType">
+ <defaultValue>SEP</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="routeSetCongestTestFlag">
+ <description>Selection of which procedure to use during congestion handling if the national option with priorities is used.
+
+0, use TcTimer as described by the TTC standard.
+1, use Route Set Congestion Test as described by the ANSI, ITU and China Standard.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="resendTfcInterval">
+ <description>Send TFC back to originating signalling point code for every n:th message when
+the destination is congested. Set to 0 will suppress sending of TFC.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxSizeReroutBuf">
+ <description>The maxSizeReroutBuf attribute represents the maximum size (in kB) of the rerouting buffer.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>5000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxSizeChangeBuf">
+ <description>The maxSizeChangeBuf attribute represents the maximum size (in kB) of the changeover buffer.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>5000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="statusIndInterval">
+ <description>The statusIndInterval attribute sets the interval for sending MTP-STATUS indication, i.e. send indication every Nth message .</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="testPatternSltm">
+ <description>The testPatternSltm attribute represents a string testpattern in the Signalling Link Test Message.
+
+String length 4 characters. Allowed characters are 0-9, A-F.
+
+</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>4</min> <max>4</max>
+ </lengthRange>
+ <defaultValue>"7711"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="spPriority">
+ <description>Struct containing the TTC priority attributes.
+</description>
+ <dataType>
+ <structRef name="Mtp3bSpTtcPriorityData"/>
+ </dataType>
+ </attribute>
+ <attribute name="rpuId">
+ <description>Holds a reference to the Reliable Program Uniter.
+The RPU is at the server.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ReliableProgramUniter"/>
+ </dataType>
+ </attribute>
+ <attribute name="spTimer">
+ <description>Struct containing TTC timer attributes.</description>
+ <noNotification/>
+ <dataType>
+ <structRef name="Mtp3bSpTtcTimerData"/>
+ </dataType>
+ </attribute>
+ <attribute name="noOfCongestLevelForNI">
+ <description>Defines the number of congestion levels for NI.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>3</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operationalState attribute reflects the operational status of the MTP3b SP.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds a list of the reserving MO's. Can be of type SccpSp.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfForcedRerouteSuccessPerf">
+ <description>Performance monitoring counter for number of successfully performed forced rerouting.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfControlledRerouteSuccessPerf">
+ <description>Performance monitoring counter for number of successfully performed controlled rerouting.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfEmergencyChangeOverRec">
+ <description>Performance management counter for number of received emergency changeOver orders (ECO) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfChangeOverRec">
+ <description>Performance counter for number of changeOver order messages (COO/XCO) received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfChangeBackDeclRec">
+ <description>Performance management counter for number of received change Back Declarations (CBD) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSLTAFirstTimeOutRec">
+ <description>Performance management counter for number of SLTA first time out received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSLTASecondTimeOutRec">
+ <description>Performance management counter for number of SLTA second time out received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUPMsgDiscardedDueToRoutingErr">
+ <description>Performance monitoring counter for number of UP (user part) messages (MTP_TRANSFER_req) discarded due to routing error.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOAXCASent">
+ <description>Performance management counter for number of sent COA/XCA messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECOSent">
+ <description>Performance management counter for number of sent ECO messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECASent">
+ <description>Performance management counter for number of sent ECA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOAXCARec">
+ <description>Performance management counter for number of received COA/XCA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBARec">
+ <description>Performance management counter for number of received CBA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECARec">
+ <description>Performance management counter for number of received ECA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTRARec">
+ <description>Performance management counter for number of received TRA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTRASent">
+ <description>Performance management counter for number of sent TRA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBASent">
+ <description>Performance management counter for number of sent CBA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessForcedRerouting">
+ <description>Performance monitoring counter for number of unsuccessfully performed forced reroutings.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessControlledRerouting">
+ <description>Performance monitoring counter for number of unsuccessfully performed controlled reroutings.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocEstablish">
+ <description>Performance management counter for number of successful association establishment.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocEstablish">
+ <description>Performance management counter for number of unsuccessful association establishment.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpCommunicationErr">
+ <description>Performance management counter for number of SCTP communication error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpSendFailure">
+ <description>Performance management counter for number of SCTP send failure.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpBufOverflow">
+ <description>Performance management counter for number of SCTP stop sending data.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpResumeSending">
+ <description>Performance management counter for number of SCTP resume sending data.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpNetworkStatusChange">
+ <description>Performance management counter for number of SCTP network status change.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpAssociationRestart">
+ <description>Performance management counter for number of SCTP association restart.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp3bSlAnsi">
+ <description>This MO represents an MTP3b Signalling Link for the ANSI standard. It represents the termination of the signalling link within the signalling point as defined in T1.111-1996.
+
+The total amount of links between any two specific nodes in the network shall not be more than 80 independent on how many linksets that are defined between the two nodes. The signalLinkCode for a link must be unique between the nodes, independent on which linkSet the link belongs to. A maximum of five linksets with a maximum of 16 links in each linkset can be configured. A maximum of 16 links between two adjacent nodes can be configured.
+
+NOTE: This MO cannot in anyway be related (either contain or by dependence) to an MO that belongs to a standard which is NOT the ANSI standard.
+
+The performance monitoring counters found in Mtp3SlAnsi MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).</description>
+ <attribute name="Mtp3bSlAnsiId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>This attribute reflects the operational status of the Mtp3bSlAnsi.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="tpId">
+ <description>The tpId attribute points out the termination point of the lower layer protocol.
+
+For narrowband this signalling link will be connected to an MTP L2 termination point (Mtp2Tp MO). And for broadband it will be connected to a NNI SAAL termination point (NniSaalTp Mo).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="linkState">
+ <description>The link state of the Mtp3bSlAnsi.
+
+The link state is a bit map which contains a combination of the following values: (in hexadecimal format)
+
+0x00 Available
+0x01 Failed
+0x02 Remotely blocked
+0x04 Locally blocked
+0x08 Remotely inhibited
+0x10 Locally inhibited
+0x20 Deactivated</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="usageState">
+ <description>There are three possible states for the usageState attribute:
+
+- idle, the Mtp3bSl carries no traffic.
+- active, the Mtp3bSl is working normally, and there is traffic, and it is not congested.
+- busy, the Mtp3bSl is working but is congested (traffic is routed on other links).
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bUsageState">
+ <defaultValue>IDLE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="signLinkCode">
+ <description>The signalling link code, SLC, used for this link.
+The signLinkCode for a link must be unique between the nodes,
+independent on in which linkSet the link belongs.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>15</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="proceduralState">
+ <description>The procedural state of the link.
+
+0 - not initialized
+1 - initialized
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bProceduralState">
+ <defaultValue>NOT_INITIALIZED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="linkCongestLevel">
+ <description>The congestion level of the link.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="CongestLevel">
+ <defaultValue>level_0</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="autoStartLink">
+ <description>Controls if the Mtp3bSL should be activated at create.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAALINServiceInd">
+ <description>Performance management counter for number of received link-in-service indications.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAALOUTInd">
+ <description>Performance management counter for number of received link-out-of-service indications.
+
+Note! This counter is incremented every time a link out of service indication is received for the link.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOOXCOSent">
+ <description>Performance management counter for number of sent change over order (COO/XCO) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBDSent">
+ <description>Performance management counter for number of sent CBD messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalLinkCongestRec">
+ <description>Performance monitoring counter for number of local link congestion primitives received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalLinkCongestCeaseRec">
+ <description>Performance monitoring counter for number of local link congestion ceased primitives received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSURec">
+ <description>Performance monitoring counter for number of received MSU's on this signalling link.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUSent">
+ <description>Performance monitoring counter for number of sent MSU's on this signalling link.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <action name="deactivate">
+ <description>This action deactivates the signalling link.
+ It will also set autoStartLink = false.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="activate">
+ <description>This action activates the signalling link with normal alignment. It will also set autoStartLink = true.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="emergencyActivate">
+ <description>This action activates the signalling link with emergency alignment.
+ It will also set autoStartLink = true
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="localInhibit">
+ <description>This action inhibits the Mtp3bSlAnsi. Signalling link management inhibiting is requested by management when it becomes necessary, e.g for maintenance or testing purposes to make or keep a signalling link unavailable to User Part-generated signalling traffic.
+Inhibiting of a signalling link may be requested by management function at either end of the link. The request is granted, provided that the inhibiting action does not cause any previously accessible destinations to become inaccessible at either end of the signalling link. The request may also be refused under certain circumstances such as congestion.
+Exception FroRequestFailed if it was not possible to inhibit.
+
+Note! This action requires a transaction.
+</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="localUninhibit">
+ <description>This action uninhibits the Mtp3bSlAnsi.
+
+Exception FrorequestFailed if it was not possible to uninhibit.
+
+Note! This action requires a transaction.
+</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ </class>
+
+ <class name="Mtp3bSlItu">
+ <description>This MO represents an MTP3b Signalling Link for the ITU standard. It represents the termination of the signalling link within the signalling point as defined in Q.704 and Q.2210 (07/96).
+
+The total amount of links between any two specific nodes in the network shall not be more than 16, independent on how many linksets that are defined between the two nodes. The signalLinkCode for a link must be unique between the nodes, independent on which linkSet the link belongs to.
+
+The performance monitoring counters found in Mtp3SlItu MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).
+
+NOTE: This MO cannot in anyway be related (either contain or by dependence) to an MO that belongs to a standard which is NOT the ITU standard.</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="tpId">
+ <description>The tpId attribute points out the termination point of the lower layer protocol.
+
+For narrowband this signalling link will be connected to an MTP L2 termination point (Mtp2Tp MO). And for broadband it will be connected to a NNI SAAL termination point (NniSaalTp Mo).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>This attribute reflects the operational status of the Mtp3bSl.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="linkState">
+ <description>The link state of the Mtp3bSl.
+
+The link state is a bit map which contains a combination of the following values: (in hexadecimal format)
+
+0x00 Available
+0x01 Failed
+0x02 Remotely blocked
+0x04 Locally blocked
+0x08 Remotely inhibited
+0x10 Locally inhibited
+0x20 Deactivated</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="usageState">
+ <description>There are three possible states for the usageState attribute:
+
+- idle, the Mtp3bSl carries no traffic.
+- active, the Mtp3bSl is working normally, and there is traffic, and it is not congested.
+- busy, the Mtp3bSl is working but is congested (traffic is routed on other links).
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bUsageState">
+ <defaultValue>IDLE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="signLinkCode">
+ <description>The signalling link code, SLC, used for this link.
+The signLinkCode for a link must be unique between the nodes,
+independent on in which linkSet the link belongs.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>15</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="proceduralState">
+ <description>The procedural state of the link.
+
+0 - not initialized
+1 - initialized
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bProceduralState">
+ <defaultValue>NOT_INITIALIZED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="linkCongestLevel">
+ <description>The congestion level of the link.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="CongestLevel">
+ <defaultValue>level_0</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="autoStartLink">
+ <description>Controls if the Mtp3b Signalling Link should be activated at create.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="prioBeforeSio">
+ <description>This Boolean tells if the message priority shall be inserted in an octet before the Service Indicator Octet (SIO).
+
+ITU default is false.
+</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAALINServiceInd">
+ <description>Performance management counter for number of received link-in-service indications.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAALOUTInd">
+ <description>Performance management counter for number of received link-out-of-service indications.
+
+Note! This counter is incremented every time a link out of service indication is received for the link.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOOXCOSent">
+ <description>Performance management counter for number of sent change over order (COO/XCO) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBDSent">
+ <description>Performance management counter for number of sent CBD messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalLinkCongestRec">
+ <description>Performance monitoring counter for number of local link congestion primitives received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalLinkCongestCeaseRec">
+ <description>Performance monitoring counter for number of local link congestion ceased primitives received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSURec">
+ <description>Performance monitoring counter for number of received MSU's on this signalling link.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUSent">
+ <description>Performance monitoring counter for number of sent MSU's on this signalling link.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="Mtp3bSlItuId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="localInhibit">
+ <description>This action inhibits the Mtp3bSlItu. Signalling link management inhibiting is requested by management when it becomes necessary, e.g for maintenance or testing purposes to make or keep a signalling link unavailable to User Part-generated signalling traffic.
+Inhibiting of a signalling link may be requested by management function at either end of the link. The request is granted, provided that the inhibiting action does not cause any previously accessible destinations to become inaccessible at either end of the signalling link. The request may also be refused under certain circumstances such as congestion.
+Exception FroRequestFailed if it was not possible to inhibit.
+
+Note! This action requires a transaction.
+</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="localUninhibit">
+ <description>This action uninhibits the Mtp3bSlItu.
+
+Exception FrorequestFailed if it was not possible to uninhibit.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="deactivate">
+ <description>This action deactivates the Mtp3bSl.
+It will also set autoStartLink = false.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="activate">
+ <description>This action activates the Mtp3bSl with normal alignment. It will also set autoStartLink = true.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="emergencyActivate">
+ <description>This action activates the Mtp3bSl with emergency alignment.
+It will also set autoStartLink = true
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="Mtp3bSlTtc">
+ <description>This MO represents an MTP3b Signalling Link for the TTC standard. It represents the termination of the signalling link within the signalling point as defined in JT-Q.704 Ver. 3, April 28 1992 and JT-Q.2210 Ver.1 April 24 1996.
+
+The total amount of links between any two specific nodes in the network shall not be more than 16, independent on how many linksets that are defined between the two nodes. The signalLinkCode for a link must be unique between the nodes, independent on which linkSet the link belongs to.
+
+The performance monitoring counters found in Mtp3SlTtc MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).
+
+NOTE: This MO cannot in anyway be related (either contain or by dependence) to an MO that belongs to a standard which is NOT the TTC standard.</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="tpId">
+ <description>The tpId attribute points out the termination point of the lower layer protocol. Only BroadBand is supported for TTC. The MO will be connected to a NNI SAAL termination point (NniSaalTp Mo).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>This attribute reflects the operational status of the Mtp3bSl.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="linkState">
+ <description>The link state of the Mtp3bSl.
+
+The link state is a bit map which contains a combination of the following values: (in hexadecimal format)
+
+0x00 Available
+0x01 Failed
+0x02 Remotely blocked
+0x04 Locally blocked
+0x08 Remotely inhibited
+0x10 Locally inhibited
+0x20 Deactivated</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="usageState">
+ <description>There are three possible states for the usageState attribute:
+
+- idle, the Mtp3bSl carries no traffic.
+- active, the Mtp3bSl is working normally, and there is traffic, and it is not congested.
+- busy, the Mtp3bSl is working but is congested (traffic is routed on other links).
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bUsageState">
+ <defaultValue>IDLE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="signLinkCode">
+ <description>The signalling link code, SLC, used for this link.
+The code have to be uniqe in this signal link set, i.e the signallingLinkCode for
+all the Mtp3bSl that belongs to the same Mtp3bSls must be unique(mutual exclusive). </description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>15</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="proceduralState">
+ <description>The procedural state of the link.
+
+0 - not initialized
+1 - initialized
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bProceduralState">
+ <defaultValue>NOT_INITIALIZED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="linkCongestLevel">
+ <description>The congestion level of the link.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="CongestLevel">
+ <defaultValue>level_0</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="autoStartLink">
+ <description>Controls if the Mtp3b Signalling Link should be activated at create.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="prioBeforeSio">
+ <description>This Boolean tells if the message priority shall be inserted in an octet before the Service Indicator Octet (SIO).
+
+</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAALINServiceInd">
+ <description>Performance management counter for number of received link-in-service indications.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAALOUTInd">
+ <description>Performance management counter for number of received link-out-of-service indications.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOOXCOSent">
+ <description>Performance management counter for number of sent change over order (COO/XCO) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBDSent">
+ <description>Performance management counter for number of sent CBD messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalLinkCongestRec">
+ <description>Performance monitoring counter for number of local link congestion primitives received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalLinkCongestCeaseRec">
+ <description>Performance monitoring counter for number of local link congestion ceased primitives received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSURec">
+ <description>Performance monitoring counter for number of received MSU's on this signalling link.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUSent">
+ <description>Performance monitoring counter for number of sent MSU's on this signalling link.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="Mtp3bSlTtcId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="deactivate">
+ <description>This action deactivates the Mtp3bSl.
+It will also set autoStartLink = false.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ </action>
+ <action name="activate">
+ <description>This action activates the signalling link with normal alignment. It will also set autoStartLink = true.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ </action>
+ <action name="emergencyActivate">
+ <description>This action activates the signalling link with emergency alignment.
+It will also set autoStartLink = true
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ </action>
+ </class>
+
+ <class name="Mtp2ProfileAnsi">
+ <description>The MTP 2 Profile MO represents and keeps attribute values used by one or more MTP 2 ANSI termination point MOs.</description>
+ <attribute name="userLabel">
+ <description>This MOs user label.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="Mtp2ProfileAnsiId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="profileData">
+ <description>Struct containing profile data.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="Mtp2ProfileDataAnsi"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of Mtp2TpAnsi MOs that have reserved this Mtp2TpProfileAnsi MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="Mtp2TpAnsi"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp2ProfileItu">
+ <description>The MTP 2 Profile MO represents and keeps attribute values used by one or more MTP 2 ITU termination point MOs.</description>
+ <attribute name="userLabel">
+ <description>The MOs user label.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="Mtp2ProfileItuId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="profileData">
+ <description>Struct containing profile data.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="Mtp2ProfileDataItu"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of Mtp2TpItu MOs that have reserved this Mtp2TpProfileItu MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="Mtp2TpItu"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="E1Ttp">
+ <description>This MO represents a channelised E1 interface in the node. The E1Ttp (Trail Termination Point) MO
+does not define which type of traffic (TDM or ATM) that the interface should support. Please refer to
+the Ds0Bundle, AtmPort, IMALink and IMAGroup objects for details about configuration of traffic type.
+
+The performance monitoring counters in the E1Ttp MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.
+
+Note! This MO is automatically created as a consequence of creating an Os155SpiTtpMo
+Please refer to the Os155SpiTtpMo for more details.
+
+</description>
+ <systemCreated/>
+ <attribute name="degDegThr">
+ <description>The threshold decides how many of the received blocks that are allowed to have bit errors. The measurement is made on a per-second basis and if the threshold is passed the second is considered bad.
+
+This is a percentage value.
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="degDegM">
+ <description>How many bad seconds in a row that causes a Degraded Signal alarm.
+
+
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>2</min> <max>10</max>
+ </range>
+ <defaultValue>7</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="aisReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="rdiReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="crc4Mode">
+ <description>Indicates what Cyclical Redundancy Check 4 Mode that is being used.</description>
+ <dataType>
+ <enumRef name="Crc4Mode">
+ <defaultValue>AUTOMATIC</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="idlePattern">
+ <description>The idle pattern.
+
+NOTE: Going from A_LAW or U_LAW to UNDEFINED is always allowed but setting up one ET board with
+both U_LAW and A_LAW is not allowed.
+E.g. If you want to change from A_LAW to U_LAW on one ET board you have to change idlePattern
+on each physical port belonging to the board to UNDEFINED first.
+A_LAW -&gt; UNDEFINED -&gt; U_LAW or U_LAW -&gt; UNDEFINED -&gt; A_LAW</description>
+ <dataType>
+ <enumRef name="IdlePattern">
+ <defaultValue>UNDEFINED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmEs">
+ <description>Performance monitoring counter of Errored Seconds (ES).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSes">
+ <description>Performance monitoring counter for Severely Errored Seconds.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="E1TtpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identityof the reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByImaLink">
+ <description>The identity of the reserving ImaLink MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ImaLink"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Vc4Ttp">
+ <description>This MO is automatically created as a consequence of creating an Os155SpiTtp object if any of the following conditions are true:
+a) standardmode = ETSI or
+b) standardmode = TTC and muxmode = VC4_STS3CSPE_LEVEL.
+
+It represents the termination of the SDH VC-4 path layer. The VC-4 can either be used for channelised access, in which case VC-12 MOs are created as children to the Vc4Ttp MO, or be used to carry ATM traffic, in which case there is a relationship between the AtmPort MO and the Vc4Ttp MO.
+
+Note! The performance monitoring counters in the Vc4TtpMO is set to 0 (zero) at start or restart of the node.
+When the value is to large to fit in to a long (31bit) the counter turns over and starts from 0 again.
+</description>
+ <systemCreated/>
+ <attribute name="pathTraceFormat">
+ <description>Indicates the format of the expectedPathtrace and transmittedPathtrace attributes. The format may be in 16 or 64 characters. Usually 16 is used for ETSI and 64 for ANSI/TTC.
+
+ITU_T_G707=16
+GR_253_CORE=64
+
+Note that the 16 characters format requires the operator to specify 15 characters where no character contains the null character (the 16th character is added automatically).
+
+Note that the 64 characters format requires the operator to specify 62 ASCII characters all different from null followed by CR/LF.</description>
+ <dataType>
+ <enumRef name="PathTraceFormat">
+ <defaultValue>ITU_T_G707</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="transmittedPathTrace">
+ <description>The transmitted path trace.
+Can be defined in two formats. The format may be in 16 or 64 characters. Usually 16 is used for ETSI and 64 for ANSI/TTC.
+
+Note: The string must be of 15 or 62 characters length, or empty string ("").
+
+</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>64</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="expectedPathTrace">
+ <description>Expected path trace.
+
+The string can be of 15 or 62 characters length, or empty string ("").
+
+Note: An empty string for this attribute means that the detection of Trace Identifier Mismatch (TIM) should be disabled. This attribute is set to empty string every time attribute pathTraceFormat is set.
+
+</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>64</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="timConsequentAction">
+ <description>Trace Identifier Mismatch (TIM) consequent action, i.e. for generation of Alarm Indication Signal (AIS) downstream and Remote Defect Indication (RDI) upstream as a consequence of the TIM detection.
+
+True - enabled.
+False - disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="vcDegThreshold">
+ <description>This threshold decides how many of the received blocks that are allowed to have bit errors. The measurement is made on a per-second basis and if the threshold is passed the second is considered bad.
+
+The attribute value is in unit of % (percent).</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="vcDegM">
+ <description>Indicates how many bad seconds in a row that causes a Degraded Signal alarm.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>2</min> <max>10</max>
+ </range>
+ <defaultValue>7</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="auAisReporting">
+ <description>AU AIS reporting.
+
+True - enable reporting.
+False - disable reporting.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="vcRdiReporting">
+ <description>VC RDI reporting.
+
+True - enable reporting.
+False - disable reporting.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmVcEs">
+ <description>Performance monitoring counter for Virtual Container 4, VC4, Errored Seconds, ES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmVcSes">
+ <description>Performance monitoring counter for Virtual Container 4, VC4, Severely Errored Seconds, SES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="Vc4TtpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Os155SpiTtp">
+ <description>This MO represents the physical interface and the termination of the SDH Regenerator and Multiplexer Section Layers.
+
+When creating the Os155SpiTtp a number of additional objects will be created. Depending on the values of standardmode and muxmode different objects will be created as described below:
+
+muxmode = standby
+standardmode = ETSI, TTC, ANSI
+No objects under the Os155SpiTtp is created.
+
+muxmode = VC4_STS3CSPE_LEVEL
+standardmode = ETSI, TTC
+A Vc4 MO is created under the Os155SpiTtp MO.
+
+muxmode = VC4_STS3CSPE_LEVEL
+standardmode = ANSI
+A Sts3CspeTtp MO is created under the Os155SpiTtp MO.
+
+The following two configurations is only applicable for the ET-MC41 board.
+
+muxmode = E1_J1_T1_LEVEL
+standardmode = ETSI
+A Vc4 MO, 63 Vc12Ttp MO's and 63 E1Ttp MO's is created under the Os155SpiTtp MO
+
+muxmode = E1_J1_T1_LEVEL
+standardmode = ANSI
+3 Sts1CspeTtp MO's, 3*28 Vt15Ttp MO's and 3*28 TiTtp MO's is created under the Os155SpiTtp MO.
+
+The performance monitoring counters in the Os155SpiTtp MO is set to 0 (zero) at start or restart of the node.
+When the value is too large too fit in to a long (31bit) the counter turns over and starts from 0 again.
+
+Note! If the Os155SpiTtp is configured as part of an Mspg protection group and is configured as standby, muxMode set to standby, no children's to this MO will be created.</description>
+ <attribute name="Os155SpiTtpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="lineNo">
+ <description>The actual line number.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>2</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="standardMode">
+ <description>The standard that this MO is operating to.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="StandardMode">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimeout">
+ <description>The shut-down timer. It is used when the administrativeState is set to shutdown.
+
+Value in seconds, must be a positive value.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100000</max>
+ </range>
+ <defaultValue>1800</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="muxMode">
+ <description>The level at which the STM-1/OC3 signal is demultiplexed.
+
+If parent is of type Etmc41, the valid muxMode is STANDBY or E1_J1_T1_LEVEL.
+If parent is of type Etm4, the valid muxMode is STANDBY or VC4_STS3CSPE_LEVEL.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="MuxMode">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="msDegThreshold">
+ <description>MS - multiplexer section.
+
+The threshold decides how many of the received blocks that are allowed to have bit errors. The measurement is made on a per-second basis and if the threshold is passed the second is considered bad.
+
+This is a percentage value.
+
+Note: When operating to the ANSI standard, this attribute has no meaning.
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="msDegM">
+ <description>MS - multiplexer section.
+
+How many bad seconds in a row that causes a Degraded Signal alarm.
+
+Note: When operating to the ANSI standard, this attribute has no meaning.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>2</min> <max>10</max>
+ </range>
+ <defaultValue>7</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="msRdiReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="msAisReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="loopBack">
+ <description>Enables or disables line loopback, i.e. the received signal is returned in the transmitted direction.
+
+none - This is the normal state, no loop back is performed (and ordinary traffic is running).
+
+line - The physical path is looped on the line side, the external incoming path is looped back to the external outgoing path.
+
+Note! administrativeStatus must be set to locked when setting loopback attribute.</description>
+ <dataType>
+ <enumRef name="Os155LoopBack">
+ <defaultValue>NONE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmMsEs">
+ <description>Performance monitoring counter for Multiplexer Section, MS, Errored Seconds, ES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmMsSes">
+ <description>Performance monitoring counter for Multiplexer Section, MS, Severely Errored Seconds, SES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBySync">
+ <description>The identity of the reserving Synchronization MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Synchronization"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Vc12Ttp">
+ <description>This MO is automatically created when the configuring the Os155SpiTtp. It represents the termination of the SDH VC-12 path layer.
+
+Note: This MO is only valid when the ETSI standard is in use.
+
+The performance monitoring counters in the Vc12TtpMO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.</description>
+ <systemCreated/>
+ <attribute name="Vc12TtpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="transmittedPathTrace">
+ <description>The transmitted path trace.
+
+Note: when 16 byte tracing is used, only 15 bytes should be used in the set action for this attribute.
+
+
+</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>64</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="expectedPathTrace">
+ <description>Expected path trace.
+
+Note: when 16 byte tracing is used, only 15 bytes should be used in the set action for this attribute.
+
+Note: An empty string for this attribute means that the detection of Trace Identifier Mismatch (TIM) should be disabled.
+</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>64</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="timConsequentAction">
+ <description>Trace Identifier Mismatch (TIM) consequent action, i.e. for generation of Alarm Indication Signal (AIS) downstream and Remote Defect Indication (RDI) upstream as a consequence of the TIM detection.
+
+True - enabled.
+False - disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="vcDegThreshold">
+ <description>This threshold decides how many of the received blocks that are allowed to have bit errors. The measurement is made on a per-second basis and if the threshold is passed the second is considered bad.
+
+The attribute value is in unit of % (percent).</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="vcDegM">
+ <description>Indicates how many bad seconds in a row that causes a Degraded Signal alarm.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>2</min> <max>10</max>
+ </range>
+ <defaultValue>7</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tuAisReporting">
+ <description>Timing Unit Alarm Indication Signal (TU AIS) reporting.
+
+True - enable reporting.
+False - disable reporting.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="vcRdiReporting">
+ <description>VC RDI reporting.
+
+True - enable reporting.
+False - disable reporting.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmVcEs">
+ <description>Performance monitoring counter for Virtual Container 12, VC12, Errored Seconds, ES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmVcSes">
+ <description>Performance monitoring counter for Virtual Container 12, VC12, Severely Errored Seconds, SES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimeout">
+ <description>The shut-down timer. It is used when the administrativeState is set to shutdown.
+
+Value in seconds, must be a positive value.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100000</max>
+ </range>
+ <defaultValue>1800</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Etmc1">
+ <description>This MO represents the hardware of the ET-MC1 board type. It only represents the ET specific hardware, the DBM module of the board is represented by the PlugInUnit MO.
+
+The ET-MC1 board contains 8 phyiscal ports that can be configured as either E1 (ETSI), J1 (TTC) or T1(ANSI). The board does not allow for a mix of E1, J1 and T1 ports, thus all configured ports on the board must be configured to the same standard.
+
+Each port on the ET-MC1 board can be used to carry either ATM traffic or circuit orientated (Nx64 Kbits/s connections) traffic.
+
+Each port can support up to 30 ATM VC connections. Two of these connections are reserved for AAL2 paths, and therefore two AAL2 multiplexers per port are available.
+
+Each port can support up to 2 VP connections.
+
+The ET-MC1 port supports one bidirectional F4/F5 PM flow per port.
+
+At the VP/VC endpoints, the Lost FPM/BR cells counters are not available.
+
+Note! The ETMC1 supports IMA.
+
+For more details on restrictions please refer to 155 17-21/CSX 101 09 Uen.
+
+Note! When the Etmc1 is part of the Cbu it is only possible to configure 4 physical ports of type E1, J1 or T1 on the Etmc1 board.</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Enabled or disabled according to the actual operational state of the ETMC1 board.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="Etmc1Id">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Etmc41">
+ <description>This MO represents the hardware of the ET-MC41 board type. It only represents the ET specific hardware, while the DBM module of the board is represented by the PlugInUnit MO.
+
+The ET-MC41 board contains a 155 Mbits/s physical optical port. The board can be configured as a E1 channelised board providing 63 logical E1 interfaces.
+
+Each E1 logical channel on the ET-MC41 can be used to carry either ATM traffic or circuit oriented (Nx64 kbit/s) traffic.
+
+Each E1 logical channel can support up to 30 ATM VC connections. Two of these connections are reserved for aal2 paths, and therefore two AAL2 multiplexers per E1/DS1/J1 channel are available.
+
+Each E1/DS1/J1 channel can suport up to 2 VP connections.
+
+The ET-MC41 board support one biderectional F4/F5 PM flow per E1 channel.
+
+Note! The ETMC41 supports IMA. However the E1 ports being part of the same IMA group can not be selected randomly.
+
+Note! The number of VCC TP+VPC TP with performance monitoring enabled (i.e. PM mode &lt;&gt; off) is restricted to 1 / port
+
+For more details on restrictions please refer to 155 17-21/CSX 101 09 Uen.</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Enabled or disabled according to the actual operational state of the ET-MC41 board.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="Etmc41Id">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp2ProfileChina">
+ <description>The MTP2 Profile MO represents and keeps attribute values used by one or more MTP2 China termination point MOs.</description>
+ <attribute name="Mtp2ProfileChinaId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="profileData">
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="Mtp2ProfileDataChina"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of Mtp2TpChina MOs that have reserved this Mtp2TpProfileChina MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="Mtp2TpChina"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>The MOs user label.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp2TpChina">
+ <description>This MO represents a MTP 2 termination point for the China standard, as defined in GF001-9001, plus supplement 1-3.
+
+The performance monitoring counters found in Mtp2China MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is a hardware fault, aal1 server/adm restart or node restart.
+
+NOTE: This MO cannot in anyway be related (either contained by or dependent on) an MO that belongs to a standard
+which is NOT the China standard.
+
+NOTE: There is a restriction of a maximum of 32 Mtp2Tp's per MP.
+
+</description>
+ <attribute name="ds0BundleId">
+ <description>The Ds0Bundle MO that this MO references.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Ds0Bundle"/>
+ </dataType>
+ </attribute>
+ <attribute name="mtp2ProfileChinaId">
+ <description>Reference to a Mtp2ProfileChina MO.
+
+Note: The bitRate can not be changed.</description>
+ <mandatory/>
+ <noNotification/>
+ <dataType>
+ <moRef name="Mtp2ProfileChina"/>
+ </dataType>
+ </attribute>
+ <attribute name="Mtp2TpChinaId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the MTP2 Signalling Terminal.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmLocalSIBTime">
+ <description>Total time in local SIB (Sending).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUTransmitted">
+ <description>Number of MSUs transmitted.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfNacks">
+ <description>Number of negative acknowledgements received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuReceivedInError">
+ <description>Number of signal units received in error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfReTransmittedOctets">
+ <description>Number of re-transmitted octets.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSendBufferOctets">
+ <description>Number of octets in send buffer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSIOSIFReceived">
+ <description>Number of SIO and SIF octets received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSIOSIFTransmitted">
+ <description>Number of SIO &amp; SIF octets transmitted.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfStartedRBCongestion">
+ <description>Number of started local RB congestions.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmRemoteSIBTime">
+ <description>Total time in remote SIB (Receiving).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Mtp3bSlChina"/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Free tag for marking this managed object.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="plugInUnitId">
+ <description>The PlugInUnit MO that this MO references.
+It indicates on which processor the Termination Point will be.
+
+Note: The PlugInUnit must be of type GPB.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="PlugInUnit"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUReceived">
+ <description>Number of MSUs received..</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp3bSlChina">
+ <description>This MO represents an MTP3b Signalling Link for the China standard. It represents the termination of the signalling link within the signalling point as defined in GF001-9001, plus supplement 1-3.
+
+The total amount of links between any two specific nodes in the network shall not be more than 16, independent on how many linksets that are defined between the two nodes. The signalLinkCode for a link must be unique between the nodes, independent on which linkSet the link belongs to.
+
+The performance monitoring counters found in Mtp3SlChina MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).
+
+NOTE: This MO cannot in anyway be related (either contain or by dependence) to an MO that belongs to a standard that is NOT the China standard.</description>
+ <attribute name="Mtp3bSlChinaId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>This attribute reflects the operational status of the Mtp3bSl.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="autoStartLink">
+ <description>Controls if the Mtp3b Signalling Link should be activated at create.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="linkCongestLevel">
+ <description>The congestion level of the link.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="CongestLevel">
+ <defaultValue>level_0</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="linkState">
+ <description>The link state of the Mtp3bSl.
+
+The link state is a bit map which contains a combination of the following values: (in hexadecimal format)
+
+0x00 Available
+0x01 Failed
+0x02 Remotely blocked
+0x04 Locally blocked
+0x08 Remotely inhibited
+0x10 Locally inhibited
+0x20 Deactivated</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="prioBeforeSio">
+ <description>This Boolean tells if the message priority shall be inserted in an octet before the Service Indicator Octet (SIO).
+
+China default is false.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="proceduralState">
+ <description>The procedural state of the link.
+
+0 - not initialized
+1 - initialized
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bProceduralState">
+ <defaultValue>NOT_INITIALIZED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="signLinkCode">
+ <description>The signalling link code, SLC, used for this link.
+The signLinkCode for a link must be unique between the nodes,
+independent on in which linkSet the link belongs.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>15</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tpId">
+ <description>The tpId attribute points out the termination point of the lower layer protocol.
+
+For narrowband this signalling link will be connected to an MTP L2 termination point (Mtp2Tp MO). And for broadband it will be connected to a NNI SAAL termination point (NniSaalTp Mo).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="usageState">
+ <description>There are three possible states for the usageState attribute:
+
+- idle, the Mtp3bSl carries no traffic.
+- active, the Mtp3bSl is working normally, and there is traffic, and it is not congested.
+- busy, the Mtp3bSl is working but is congested (traffic is routed on other links).
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bUsageState">
+ <defaultValue>IDLE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAALINServiceInd">
+ <description>Performance management counter for number of received link-in-service indications.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAALOUTInd">
+ <description>Performance management counter for number of received link-out-of-service indications.
+
+Note! This counter is incremented every time a link out of service indication is received for the link.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBDSent">
+ <description>Performance management counter for number of sent CBD messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOOXCOSent">
+ <description>Performance management counter for number of sent change over order (COO/XCO) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalLinkCongestCeaseRec">
+ <description>Performance monitoring counter for number of local link congestion ceased primitives received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalLinkCongestRec">
+ <description>Performance monitoring counter for number of local link congestion primitives received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSURec">
+ <description>Performance monitoring counter for number of received MSU's on this signalling link.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUSent">
+ <description>Performance monitoring counter for number of sent MSU's on this signalling link.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <action name="activate">
+ <description>This action activates the Mtp3bSl with normal alignment. It will also set autoStartLink = true.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="deactivate">
+ <description>This action deactivates the Mtp3bSl.
+It will also set autoStartLink = false.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="emergencyActivate">
+ <description>This action activates the Mtp3bSl with emergency alignment.
+It will also set autoStartLink = true
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="localInhibit">
+ <description>This action inhibits the Mtp3bSlChina. Signalling link management inhibiting is requested by management when it becomes necessary, e.g for maintenance or testing purposes to make or keep a signalling link unavailable to User Part-generated signalling traffic.
+Inhibiting of a signalling link may be requested by management function at either end of the link. The request is granted, provided that the inhibiting action does not cause any previously accessible destinations to become inaccessible at either end of the signalling link. The request may also be refused under certain circumstances such as congestion.
+Exception FroRequestFailed if it was not possible to inhibit.
+
+Note! This action requires a transaction.
+</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="localUninhibit">
+ <description>This action uninhibits the Mtp3bSlItu.
+
+Exception FrorequestFailed if it was not possible to uninhibit.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ </class>
+
+ <class name="Mtp3bSpChina">
+ <description>Mtp3b Signalling Point for the China standard.
+
+This MO represents/models the MTP3b Signaling Point characteristics/functions according to the China standard.
+A signaling point is a logical node in the signaling network. The combination of signaling points and their interconnecting
+signaling links form the SS No. 7 signaling network. The signaling point represented by this object is a Local Signaling Point.
+
+The performance monitoring counters found in Mtp3SpChina MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).
+
+NOTE: IT IS NOT POSSIBLE TO CREATE SIGNALLING POINTS OF DIFFERENT STANDARDS!
+
+NOTE: This MO cannot in anyway be related (either contain or by dependence) to an MO that belongs to a standard which is NOT the China standard.
+
+NOTE: The combination of network indicator (networkInd) and Signalling Point Code (signallingPointCode) has to be unique for each Signalling Point.
+
+NOTE: A maximum of 15 instances of this MO can be created on (referencing) the same PlugInUnit.
+
+NOTE: The maximum number of Signalling Points that can be created in a CPP based node is 24.
+
+NOTE: Deleting a singel L3 Signal Point is not possible, if it necessary to delete a Signal Point then all Signal Points has to be deleted. This also has to be done whitin the same transaction.
+
+NOTE: Any object created under a certain SP (Signaling Point) cannot refer to an object created under another SP. Nor can it refer to an object created under another SP.</description>
+ <attribute name="Mtp3bSpChinaId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="maxSizeChangeBuf">
+ <description>The maxSizeChangeBuf attribute represents the maximum size (in kB) of the changeover buffer.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>5000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxSizeReroutBuf">
+ <description>The maxSizeReroutBuf attribute represents the maximum size (in kB) of the rerouting buffer.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>5000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="networkInd">
+ <description>The network indicator, NI, is used for discrimination of messages between functionally different networks.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="Mtp3bNetworkInd">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operationalState attribute reflects the operational status of the MTP3b SP.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds a list of the reserving MO's. Can be of type SccpSp.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="sendSltmBefLink">
+ <description>The sendSltmBefLink attribute determines if the SLTM (Signalling Link Test Message) should be sent and a SLTA received before the link is considered to be in service.
+
+Note! It is not recommended nor is it in accordance with standard to set the value of this attribute to 'false' </description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="signallingPointCode">
+ <description>The signallingPointCode (Local Point Code) attribute (SPC) is used together with the network indicator (NI, networkInd attribute) to uniquely identify the MTP Signalling Point, SP.
+SP = NI-SPC.
+Size (2 exp 24)-1 (16777215).
+The SignallingPointCode (SPC) is nornally used as a whole unique number (no internal structure). But sometimes the SPC is grouped together as three numbers which corresponds to zone, area/network, signalling point. If this is the case the three numbers are coded as 8-8-8 bits in the total SPC. To enter the SPC-value then you have to convert the three numbers to their binary code and then convert the whole 24-bit pattern as an integer.
+ </description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16777215</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="nodeBehaviour">
+ <description>The nodeBehaviour attribute represents the MTP3b node type.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="NodeBehaviourType">
+ <defaultValue>SEP</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="noOfCongestLevelForNI">
+ <description>Defines the number of congestion levels for NI.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>3</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="routeSetCongestTestFlag">
+ <description>Selection of which procedure to use during congestion handling if the national option with priorities is used.
+
+0, use TcTimer as described by the TTC standard.
+1, use Route Set Congestion Test as described by the ANSI, ITU and China Standard.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="resendTfcInterval">
+ <description>Send TFC back to originating signalling point code for every n:th message when
+the destination is congested. Set to 0 will suppress sending of TFC.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="sioSpare">
+ <description>The sioSpare attribute determines if the two spare bits in the SIO (Service Information Octet) should be treated as spare.</description>
+ <dataType>
+ <enumRef name="Mtp3bSioSpareBitsUse">
+ <defaultValue>SPARE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="spPriority">
+ <description>Struct containing the priority attributes.
+
+Note: The China and ITU priorityData is identical so the ItuPriorityData is used for China to avoid duplication of data.</description>
+ <dataType>
+ <structRef name="Mtp3bSpChinaPriorityData"/>
+ </dataType>
+ </attribute>
+ <attribute name="spTimer">
+ <description>Struct containing China specific timer attributes</description>
+ <dataType>
+ <structRef name="Mtp3bSpChinaTimerData"/>
+ </dataType>
+ </attribute>
+ <attribute name="statusIndInterval">
+ <description>The statusIndInterval attribute sets the interval for sending MTP-STATUS indication, i.e. send indication every Nth message .</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="testPatternSltm">
+ <description>The testPatternSltm attribute represents a string testpattern in the Signalling Link Test Message.
+
+Minimum string length 2 characters, maximum 30 characters. Allowed characters are 0-9, A-F.
+Only even number of characters is allowed.
+
+</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>2</min> <max>30</max>
+ </lengthRange>
+ <defaultValue>"A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="transFrHandler">
+ <description>Determines if a TransFer Restricted signal (TFR) should be treated as a TFA (TransFer Allowed signal) or be ignored.
+</description>
+ <dataType>
+ <enumRef name="Mtp3bTfrHandling">
+ <defaultValue>IGNORED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="rpuId">
+ <description>Holds a reference to the Reliable Program Uniter.
+The RPU is at the server.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ReliableProgramUniter"/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="m3uaNoOfAttempsOfDauds">
+ <description>For M3UA, number of attempts to send the DAUD message.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="noOfAttempsOfAssociationEstablishment">
+ <description>Number of attempts to send the SCTP_ASSOCIATE_REQ message.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>65535</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="version">
+ <description>This attribute shows what MTP3b ITU standard the system follows. With ITU, it is possible using this attribute to set which of the ITU standard versions that shall be followed.
+
+Note! Setting of another value than 'ITU_T_07_96' at create will have no effect. The Signaling Point will always be created with the value 'ITU_T_07_96'.
+
+Note! It is not possible to hav signaling points with different versions in the node so setting of this attribute will effect all signaling points. The value for the last created or changed signaling point will be used for all signaling points.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bItuVersion">
+ <defaultValue>ITU_T_07_96</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBARec">
+ <description>Performance management counter for number of received CBA messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBASent">
+ <description>Performance management counter for number of sent CBA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfChangeBackDeclRec">
+ <description>Performance management counter for number of received change Back Declarations (CBD) messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfChangeOverRec">
+ <description>Performance counter for number of changeOver order messages (COO/XCO) received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOAXCARec">
+ <description>Performance management counter for number of received COA/XCA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOAXCASent">
+ <description>Performance management counter for number of sent COA/XCA messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfControlledRerouteSuccessPerf">
+ <description>Performance monitoring counter for number of successfully performed controlled rerouting.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECASent">
+ <description>Performance management counter for number of sent ECA messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECARec">
+ <description>Performance management counter for number of received ECA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECOSent">
+ <description>Performance management counter for number of sent ECO messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfEmergencyChangeOverRec">
+ <description>Performance management counter for number of received emergency changeOver orders (ECO) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfForcedRerouteSuccessPerf">
+ <description>Performance monitoring counter for number of successfully performed forced rerouting.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSLTAFirstTimeOutRec">
+ <description>Performance management counter for number of SLTA first time out received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSLTASecondTimeOutRec">
+ <description>Performance management counter for number of SLTA second time out received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTimerT21WasStarted">
+ <description>Performance monitoring counter for number of times the timer T21 was started (i.e. adjacent SP restarted).
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTRARec">
+ <description>Performance management counter for number of received TRA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTRASent">
+ <description>Performance management counter for number of sent TRA messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessControlledRerouting">
+ <description>Performance monitoring counter for number of unsuccessfully performed controlled reroutings.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessForcedRerouting">
+ <description>Performance monitoring counter for number of unsuccessfully performed forced reroutings.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUPMsgDiscardedDueToRoutingErr">
+ <description>Performance monitoring counter for number of UP (user part) messages (MTP_TRANSFER_req) discarded due to routing error.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocEstablish">
+ <description>Performance management counter for number of successful association establishment.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocEstablish">
+ <description>Performance management counter for number of unsuccessful association establishment.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpCommunicationErr">
+ <description>Performance management counter for number of SCTP communication error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpSendFailure">
+ <description>Performance management counter for number of SCTP send failure.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpBufOverflow">
+ <description>Performance management counter for number of SCTP stop sending data.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpResumeSending">
+ <description>Performance management counter for number of SCTP resume sending data.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpNetworkStatusChange">
+ <description>Performance management counter for number of SCTP network status change.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpAssociationRestart">
+ <description>Performance management counter for number of SCTP association restart.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocAbort">
+ <description>The number of successful abortions of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocShutDown">
+ <description>The number of succesful shutdowns of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocAbort">
+ <description>The number of unsuccessful abortions of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocShutDown">
+ <description>The number of unsuccesful shutdowns of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIncomingAssocEstabRequestInStateDownWhenStateEstabIsBlocked">
+ <description>The number of incoming request for association establishment when state on the association is 'DOWN' and establishment of associations is blocked. </description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMaxTrialsForAssocEstabReached">
+ <description>The number of times that the max limit for trying to establish an association has been reached.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMaxTrialsForAssocActivReached">
+ <description>The number of times that the max limit for trying to activate an association has been reached.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLowerPrioMsgDiscarded">
+ <description>The number of messages with low priority that has been discarded.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mspg">
+ <description>The MSPG (Multiplex Section Protection Group) object enables two different protection mechanism in Cello. First it enables a standard 1+1 MSP mechanism. A failure on the working line will thus cause a sub 50 ms switch to the standby line.
+Secondly the MSPG is used to enable equipment protection, whereas a failure of the working board will cause a switch to the standby board. While executing an equipment protection switch, the node on the other end of the multiplexer section, will experience a standard 1+1 MSP switch.
+
+It is possible to force traffic to one port/board by using administrative state.
+Setting administrative state to locked on the working board, will automatically cause an equipment switch to the standby board. Similarily setting administrative state to locked on the working port, will cause an MSP switch to the standby port.
+
+The process of configuring a MSP protection interface is as follows:
+1) Create the working interface as normal.
+2) Create the standby interface by creating an Os155SpiTtp with mux mode set to STANDBY (standby for protection).
+3) Create a MSPG object with references to the two Os155SpiTtp objects.
+
+Note! The ports selected for MSPG must be have the attribute standardMode configured in exactly the same way.
+
+Note! The Os155SpiTtp created for standby will not create any children, i.e no Vc4Ttp or Vc4Ttp, Vc12Ttp and E1Ttp will be created. Nor will object of type Sts1SpeTtp, Vt15Ttp or T1Ttp be created.</description>
+ <attribute name="os155SpiWorkingId">
+ <description>The working OS155 pyhiscal path termination.
+This is the administrative value.
+
+To retrive the Id of the current working port, use the selectedPort.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Os155SpiTtp"/>
+ </dataType>
+ </attribute>
+ <attribute name="os155SpiStandbyId">
+ <description>The standby OS155 physical path termination.
+This is the administrative value.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Os155SpiTtp"/>
+ </dataType>
+ </attribute>
+ <attribute name="switchMode">
+ <description>The switching mode.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="SwitchModes">
+ <defaultValue>AUTOMATIC</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the Mspg.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="MspgId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="selectedPort">
+ <description>The port currently selected by the MSPG. The selected port can only
+change due to a MSP or equipment switch.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Os155SpiTtp"/>
+ </dataType>
+ </attribute>
+ <attribute name="selectedBoard">
+ <description>The board currently providing the user traffic interface to the Cello switch.
+The only action that can change the selected board is an equipment switch.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="degCauseMsp">
+ <description>If set to true, then a swith is performed upon detection of DEG.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <action name="manualMspSwitch">
+ <description>Initiates a switch when there does not exist a defect.
+
+This action can fail for the following reasons:
+FailedResource - the switch was not possible due to a traffic affecting fault on the port to which the switch was requested (i.e. the one not currently selected).
+LockedResource - the port to which the switch is intended is administratively locked.
+UnknownReason - there exists another fault that prevents the action.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FailedResourceException"/>
+ <raisesException name="LockedResourceException"/>
+ <raisesException name="UnknownReasonException"/>
+ </action>
+ </class>
+
+ <class name="T1PhysPathTerm">
+ <description>This MO represents an T1 (i.e. 1.5 Mbit/s) physical interface in the node. The T1PhysPathTerm MO does not define which type of traffic (TDM or ATM) that the interface should support.
+Please refer to the Ds0Bundle, AtmPort, IMALink and IMAGroup objects for details about configuration of traffic type.
+
+</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="T1PhysPathTermId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="lineNo">
+ <description>The actual Line number on the board.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>8</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="loopback">
+ <description>Possible values
+
+none - This is the normal state, no loop back is performed (and ordinary traffic is running).
+
+line - The physical path is looped on the line side, the external incoming path is looped back to the external outgoing path.
+
+system - The physical path is looped on the system side, the (node-) internal incoming path is looped back to the internal outgoing path.
+
+Note! administrativeStatus must be set to locked when setting loopback attribute.</description>
+ <dataType>
+ <enumRef name="LoopbackState">
+ <defaultValue>none</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmEs">
+ <description>Performance monitoring counter for Errored Seconds, ES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSes">
+ <description>Performance monitoring counter for Severly Errored Seconds, SES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByTraffic">
+ <description>The identity of the reserving AtmPort MO. </description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Enabled or disabled according to the actual operational state of the Physical Line Termination. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="rdiReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="aisReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimeout">
+ <description>The shut-down timer. It is used when the administrativeState is set to shutdown.
+
+Value in seconds, must be a positive value.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100000</max>
+ </range>
+ <defaultValue>1800</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="idlePattern">
+ <description>The idle pattern.
+
+NOTE: Going from A_LAW or U_LAW to UNDEFINED is always allowed but setting up one ET board with
+both U_LAW and A_LAW is not allowed.
+E.g. If you want to change from A_LAW to U_LAW on one ET board you have to change idlePattern
+on each physical port belonging to the board to UNDEFINED first.
+A_LAW -&gt; UNDEFINED -&gt; U_LAW or U_LAW -&gt; UNDEFINED -&gt; A_LAW</description>
+ <dataType>
+ <enumRef name="IdlePattern">
+ <defaultValue>UNDEFINED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="transmissionMode">
+ <description>The type of transmission media.
+Refer to the TransmissionMode enumeration for details.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="TransmissionMode">
+ <defaultValue>S_133</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBySync">
+ <description>The identity of the reserving Synchronization MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Synchronization"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByImaLink">
+ <description>The identity of the reserving ImaLink MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ImaLink"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="ImaGroup">
+ <description>IMA, Inverse Multiplexing for ATM, makes it possible to group several physical
+interfaces together to form a virtual physical pipe for atm. The capacity of this
+pipe is equal to the sum of each of the physical interfaces included in the
+group.
+
+When IMA should be configured, an ATMPort MO is created with reference to an
+IMAGroup MO rather than a pure physical interface MO.
+The IMAGroup MO in turn is created with a list of the physical port MO's that
+are included in the group. The physical port MO's must be of the same type
+and be located on the same ET board.
+
+For each of the physical port MO's included in the IMAGroup, an IMALink object
+is automatically created. The IMALink object is responsible for handling link
+specific performance and fault management related to IMA.
+
+The ports can be of type E1PhysPathTerm, J1PhysPathTerm, T1PhysPathTerm, E1Ttp, T1Ttp.
+
+The performance monitoring counters in the ImaGroup MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.
+
+Note! A general restriction in Cello is that ports being part of the same IMA group
+must be located on the same board.
+
+Note! Only termination points on Etmc1 and Etmc41 boards are allowed as ImaLinks.
+
+Note! At least two links has to be configured in an Ima Group.</description>
+ <attribute name="ImaGroupId">
+ <description>The identity of the MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="physicalPortList">
+ <description>Holds a list of the physical ports connected to the ImaGroup.
+Can be of type:
+E1PhysPathTerm,
+J1PhysPathTerm,
+T1PhysPathTerm,
+E1Ttp,
+T1Ttp.</description>
+ <mandatory/>
+ <noNotification/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="requiredNumberOfLinks">
+ <description>The required number of links specifies the number of IMALinks that needs to be
+operational in order for the complete group to be operational. The bandwidth
+available for the ATMPort (and thus for creating VP/VC connections) is defined
+by this number.
+Setting the requiredNumberOfLinks field to K less than the number of physical
+links included in the IMAGroup, will reduce the bandwidth available to the atmport
+with the corresponding bandwidth but will also give the effect that K links
+failures can be tolerated with virtually no traffic disturbance.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>8</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="activeLinks">
+ <description>The number of active links in the ImaGroup.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Enabled or disabled according to the actual operational state of the ImaGroup.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmGrUasIma">
+ <description>This performance counter reflects the GrUasLma attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmGrFc">
+ <description>This performance counter reflects the GrFc attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmGrFcFe">
+ <description>This performance counter reflects the GrFcFe attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="ImaLink">
+ <description>This MO is automatically created as a consequence of creating an IMAGroup or
+adding links to an IMAGroup.
+It provides IMA Link specific performance and fault management information.
+
+The links can be of type E1PhysPathTerm, J1PhysPathTerm, T1PhysPathTerm, E1Ttp or T1Ttp.
+
+The performance monitoring counters in the ImaLink MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.
+
+Note! A general restriction in Cello is that ports being part of the same IMA group
+must be located on the same board.</description>
+ <attribute name="operationalState">
+ <description>Enabled or disabled according to the actual operational state of the ImaLink.
+If the operationalState is disabled the ImaLink will be blocked for traffic.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmIvIma">
+ <description>This performance counter reflects the LvLma attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ImaLinkId">
+ <description>The identity of the MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="pmOifIma">
+ <description>This performance counter reflects the OifLma attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSesIma">
+ <description>This performance counter reflects the SesLma attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSesImaFe">
+ <description>This performance counter reflects the SesLmaFe attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUasIma">
+ <description>This performance counter reflects the UasLma attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUasImaFe">
+ <description>This performance counter reflects the UasLmaFe attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmTxUusIma">
+ <description>This performance counter reflects the TxUusLma attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmRxUusIma">
+ <description>This performance counter reflects the RxUusLma attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmTxUusImaFe">
+ <description>This performance counter reflects the TxUusLmaFe attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmRxUusImaFe">
+ <description>This performance counter reflects the RxUusLmaFe attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmTxFc">
+ <description>This performance counter reflects the TxFc attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmRxFc">
+ <description>This performance counter reflects the RxFc attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmTxFcFe">
+ <description>This performance counter reflects the TxFcFe attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmRxFcFe">
+ <description>This performance counter reflects the RxFcFe attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmTxStuffIma">
+ <description>This performance counter reflects the TxStuffLma attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmRxStuffIma">
+ <description>This performance counter reflects the RxStuffLma attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="uses">
+ <description>Reference to the physical port represented by this MO.
+Can be of types E1PhysPathTerm, J1PhysPathTerm, T1PhysPathTerm, E1Ttp or T1Ttp.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Sts3CspeTtp">
+ <description>This MO represents the termination of the SONET higher order paths.
+This MO is automatically created when creating the OS155SPITTP with mux mode
+set to VC4_STS3CSPE_LEVEL and standardMode set to ANSI.
+
+The performance monitoring counters in the Sts3CspeTtp MO is set to 0 (zero) at start or restart of the node.
+When the value is to large to fit in to a long (31bit) the counter turns over and starts from 0 again.</description>
+ <attribute name="Sts3CspeTtpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>enabled or disabled according to the actual operational state of the Sts3CspeTtp.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="aisPReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="rdiPReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="timConsequentAction">
+ <description>Trace Identifier Mismatch (TIM) consequent action, i.e. for generation of Alarm Indication Signal (AIS) downstream and Remote Defect Indication (RDI) upstream as a consequence of the TIM detection.
+
+True - enabled.
+False - disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="expectedPathTrace">
+ <description>Expected path trace.
+
+The string can be of 64 characters length, or empty string ("").
+The string shall consist of 62 ASCII characters followed by CR/LF.
+The empty string shall be coded with the first character equal to ASCII null (i.e. byte value 0) and the rest dummy or non-existing.
+
+Note: An empty string for this attribute means that the detection of Trace Identifier Mismatch (TIM) should be disabled. This attribute is set to empty string every time attribute pathTraceFormat is set.</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>64</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="transmittedPathTrace">
+ <description>The transmitted path trace.
+
+The string shall consist of 62 ASCII characters followed by CR/LF.
+The empty string shall be coded with the first character equal to ASCII null (i.e. byte value 0) and the rest dummy or non-existing.</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>64</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Identity of the AtmPort reserving this MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmEsp">
+ <description>Performance Monitoring counter for ES, Errored Seconds.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSesp">
+ <description>Performance Monitoring counter for Severely Errored Seconds, SES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="WebServer">
+ <description>The WebServer MO represents the WebServer in the node.
+
+This object is used for configuration of the WebServer paths. By connecting this object to a
+SwAllocation MO that is connected to a Repertoire MO the WebServer paths will be
+automatically configured during system upgrade.
+
+The local distinguished name of this MO is ManagedElement=1, WebServer=1.
+
+The WebServer MO is created automatically by the system.</description>
+ <systemCreated/>
+ <attribute name="WebServerId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="webServerPaths">
+ <description>Paths that shall be used by the WebServer separated by the delimiter character ":".</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBySwAllocation">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="SwAllocation"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="IpAccessAutoConfig">
+ <description>This MO represents the Auto Configuration feature for the IpAccessHost's in Cello.
+
+</description>
+ <attribute name="IpAccessAutoConfigId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Hold a list of the identitys of the reserving IpAccessHost's.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="networkPrefix">
+ <description>The network prefix.
+
+The prefix denotes how many bits that are used for calculating the subnet mask.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>32</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="nrOfUnusedAdresses">
+ <description>The number of addresses in the range that are not used.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="totalNrOfAddresses">
+ <description>The total number of addresses in the range.
+
+Note that the first address in the range will be the same one as the one for networkAddress.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="minIpAddress">
+ <description>The lowest value that can be used as host IP address. If autoConfig=ON for an IpAccessHost, the operator does not explicitly have to assign an Ip Address and prefixLength to the host. This is done by the Control Plane, based on the IpAccesAutoConfig identity specified for the IpAccessHost.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="maxIpAddress">
+ <description>The highest value that can be used as host IP address. If autoConfig=ON for an IpAccessHost, the operator does not explicitly have to assign an Ip Address and prefixLength to the host. This is done by the Control Plane, based on the IpAccesAutoConfig identity specified for the IpAccessHost.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="IpAccessHostMsb">
+ <description>This MO represents the Ip Access Host used for payload. This host type executes on a MSB board (Media Stream Board used by Media Gateway).
+
+Note! If autoConfig is set to ON, the Ip Addresses and the Prefixes for this MO is set by the IpAccessAutoConfig MO.
+
+Note! There can be a maximum of 128 host's in the node.
+
+Note! The references to Aal5TpVccTp MO's has to be set in pairs.
+
+Note! The IpAccessMsbHost must execute on the sam MP as the Aal5TpVccTp that are defined in the attributes 'aal5TpVccTpRef1' and 'aal5TpVccTpRef2'.
+
+Note! The 'administrativeState' has to be set to LOCKED in order to be able to delete this host.</description>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the Ip Access Host.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>DEGRADED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of the Ip Access Host.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimer">
+ <description>The shut-down timer. It is used when the administrativeState is set to shutdown.
+
+Value in seconds, must be a positive value.</description>
+ <dataType>
+ <long>
+ <defaultValue>10</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="dspId">
+ <description>The identity of the DSP (Digital Signalling Processor) on a MSB board.
+
+Note! The value of this attribute has to be unique among the host's that execute on the same board.</description>
+ <mandatory/>
+ <noNotification/>
+ <nonPersistent/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="aal5TpVccTpRef1">
+ <description>Holds a reference to an Aal5 termination point (Aal5TpVccTp MO).
+
+Note! The Aal5TpVccTp references are mutually exclusive.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Aal5TpVccTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="aal5TpVccTpRef2">
+ <description>Holds a reference to an Aal5 termination point (Aal5TpVccTp MO).
+
+Note! The Aal5TpVccTp references are mutually exclusive.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Aal5TpVccTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="autoConfig">
+ <description>This attribute specifies whether the auto configuration feature for the Ip Access Host is used or not.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="AutoConfigurationMode">
+ <defaultValue>OFF</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="autoConfigIdentity">
+ <description>The identity of the IpAccessAutoConfig MO used by this host.
+
+Note! This attribute can only be set if 'autoConfig' is set to 'ON'.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="IpAccessAutoConfig"/>
+ </dataType>
+ </attribute>
+ <attribute name="ipAddress">
+ <description>The IpAddress.
+
+Note! If autoConfig = OFF this attribute is mandatory.
+
+Note! If the autoConfiguration is used for this IpAccessHost (autoConfig = ON) this attribute cannot be set. This attribute is then set by the 'IpAccessAutoConfig MO'.
+
+Note! The IpAddress has to be unique within the node.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="networkPrefix">
+ <description>The network prefix.
+
+The prefix denotes how many bits that are used for calculating the subnet mask.
+
+Note! If auto configuration is used (autoConfig = ON) this attribute cannot be set, the networkPrefix is then set in the ipAccessAutoConfig MO class.
+
+Note! If auto configuration is not used (autoConfig = OFF) this attribute must be set.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>32</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="linkStatusAddress">
+ <description>The link Status for Ip Address.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="mtu">
+ <description>The maximum transfer unit.
+
+Note! in order to be able to set the value for this attribute, the administrative state has to be locked.
+
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>72</min> <max>2048</max>
+ </range>
+ <defaultValue>1024</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ipDefaultTtl">
+ <description>The default value inserted into the Time-To-Live field of the IP header of datagrams originated at this entity,
+whenever a TTL value is not supplied by the transport layer protocol.
+
+Note! in order to be able to set the value for this attribute, the administrative state has to be locked.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>255</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInReceives">
+ <description>The total number of input datagrams received from interfaces, including those received in error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInHdrErrors">
+ <description>The number of input datagrams discarded due to errors in their IP headers, including bad checksums, version number
+mismatch, other format errors, time-to-live exceeded, errors discovered in processing their IP options, etc.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInAddrErrors">
+ <description>The number of input datagrams discarded because the IP address in their IP header's destination field was not a
+valid address to be received at this entity. This count includes invalid addresses (e.g., 0.0.0.0) and addresses of
+unsupported Classes (e.g., Class E). For entities which are not IP routers and therefore do not forward datagrams,
+this counter includes datagrams discarded because the destination address was not a local address.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInUnknownProtos">
+ <description>The number of locally-addressed datagrams received successfully but discarded because of an unknown or
+unsupported protocol.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInDiscards">
+ <description>The number of input IP datagrams for which no problems were encountered to prevent their continued processing, but which
+were discarded (e.g., for lack of buffer space). Note that this counter does not include any datagrams discarded while
+awaiting re-assembly.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInDelivers">
+ <description>The total number of input datagrams successfully delivered to IP user-protocols (including ICMP).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpOutRequests">
+ <description>The total number of IP datagrams which local IP user-protocols (including ICMP) supplied to IP in requests for
+transmission. Note that this counter does not include any datagrams counted in ipForwDatagrams</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpOutDiscards">
+ <description>The number of output IP datagrams for which no problem was encountered to prevent their transmission to their
+destination, but which were discarded (e.g., for lack of buffer space). Note that this counter would include
+datagrams counted in ipForwDatagrams if any such packets met this (discretionary) discard criterion.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInMsgs">
+ <description>The total number of ICMP messages which the entity received.
+Note that this counter includes all those counted by icmpInErrors</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInErrors">
+ <description>The number of ICMP messages which the entity received but determined as having
+ICMP-specific errors (bad ICMP checksums, bad length, etc.).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInDestUnreachs">
+ <description>The number of ICMP Destination Unreachable messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInTimeExcds">
+ <description>The number of ICMP Time Exceeded messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInParamProbs">
+ <description>The number of ICMP Parameter Problem messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInSrcQuenchs">
+ <description>The number of ICMP Source Quench messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInRedirects">
+ <description>The number of ICMP Redirect messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInEchos">
+ <description>The number of ICMP Echo (request) messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInEchoReps">
+ <description>The number of ICMP Echo Reply messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutMsgs">
+ <description>The total number of ICMP messages which this entity attempted to send.
+Note that this counter includes all those counted by icmpOutErrors.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutErrors">
+ <description>The number of ICMP messages which this entity did not send due to problems discovered within ICMP such as a lack of
+buffers. This value should not include errors discovered outside the ICMP layer such as the inability of IP to route the
+resultant datagram. In some implementations there may be no types of error which contribute to this counter's value.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutDestUnreachs">
+ <description>The number of ICMP Destination Unreachable messages sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutParmProbs">
+ <description>The number of ICMP Parameter Problem messages sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutEchos">
+ <description>The number of ICMP Echo (request) messages sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutEchoReps">
+ <description>The number of ICMP Echo Reply messages sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUdpInDatagrams">
+ <description>The total number of UDP datagrams delivered to UDP users.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUdpNoPorts">
+ <description>The total number of received UDP datagrams for which there was no application at the destination port.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUdpInErrors">
+ <description>The number of received UDP datagrams that could not be delivered for
+reasons other than the lack of an application at the destination port.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUdpOutDatagrams">
+ <description>The total number of UDP datagrams sent from this entity.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="IpAccessHostMsbId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="plugInUnitId">
+ <description>Holds a reference to the PlugInUnit.
+
+Note that the 'plugInUnitId has to be the same as the one defined in the attribute 'processorId' found on the Aal5TpVccTpMo.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="PlugInUnit"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Aal2QosProfile">
+ <description>This MO represents the definitions of properties for a set of Aal2 quality of service classes.</description>
+ <attribute name="Aal2QosProfileId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="profileClassA">
+ <description>This attribute holds the values applicable for QoS Class A.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="QoSProfileClassA"/>
+ </dataType>
+ </attribute>
+ <attribute name="profileClassB">
+ <description>This attribute holds the values applicable for QoS Class B.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="QoSProfileClassB"/>
+ </dataType>
+ </attribute>
+ <attribute name="profileClassC">
+ <description>This attribute holds the values applicable for QoS Class C.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="QoSProfileClassC"/>
+ </dataType>
+ </attribute>
+ <attribute name="profileClassD">
+ <description>This attribute holds the values applicable for QoS Class D.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="QoSProfileClassD"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving Aal2PathVccTp MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="Aal2PathVccTp"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Aal2QosCodePointProfile">
+ <description>This MO represents the QoS CodePoints for the different Aal2 QoS classes.</description>
+ <attribute name="Aal2QosCodePointProfileId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="qualityOfServiceCodePointA">
+ <description>The Code Point for Class A.
+
+Recommended value for Class A, 128.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="qualityOfServiceCodePointB">
+ <description>The Code Point for Class B.
+
+Recommended value for Class B, 129.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="qualityOfServiceCodePointC">
+ <description>The Code Point for Class C.
+
+Recommended value for Class C, 130.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="qualityOfServiceCodePointD">
+ <description>The Code Point for Class D.
+
+Recommended value for Class D, 131.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds the identity of the reserving Aal2Ap Mo.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="Aal2Ap"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="M3uAssociation">
+ <description>This MO represents the M3UA Association part of the M3UA (MTP3-User Adaptaion Layer) that is a protocol
+for the transport of any SS7 MTP3-User signalling (e.g., ISUP and SCCP messages) over IP using the services
+of the Stream Control Transmission Protocol.
+
+Note that the local port number is hard coded to 2905.
+
+
+</description>
+ <attribute name="M3uAssociationId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds a list of the reserving Signaling Route's (Mtp3bSr MO).
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="Mtp3bSr"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The Operational State of the M3Ua</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="mtp3bSrsId">
+ <description>The identity of the Signalling Route Set used.</description>
+ <mandatory/>
+ <noNotification/>
+ <nonPersistent/>
+ <restricted/>
+ <dataType>
+ <moRef name="Mtp3bSrs"/>
+ </dataType>
+ </attribute>
+ <attribute name="sctpId">
+ <description>The SctpHost used by this association.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Sctp"/>
+ </dataType>
+ </attribute>
+ <attribute name="dscp">
+ <description>The DSCP, DiffServCodePoint, for the internal M3UA user.
+Only one DSCP value is valid and set by the first defined MO 'instance'.
+
+NOTE: The value set for the 'dscp' when creating the first M3uAssociation under a signaling point will also be used for all other M3uAssociation MO's that are created under this signaling point. So setting the value for the 'dscp' on other instances than the first one created will have no effect. Note that associations created under a different signaling point can have a different dscp-value. </description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>63</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="associationState">
+ <description>The possible states of an M3Ua association.
+
+Bit 1 = 1 indicates INACTIVE
+Bit 2 = 1 indicates ACTIVE
+Bit 3 = 1 indicates ESTABLISHED
+Bit 4 = 1 indicates DOWN
+
+These values are mutually exclusive.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>15</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="localIpMask">
+ <description>This attribute denotes whether single or multi homing is used.
+
+Note! that all M3uAssociations that refers to the same SCTP MO must have this attribute set to the same value.
+
+Note! If localipMask=2 or localipMask=3 . the attribute ipAddress2 or autoConfigIdentity2 in IpAccessHostGpb MO must be defined.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="HomingState">
+ <defaultValue>SINGLE_HOMED_1</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="autoStartAssociation">
+ <description>If true, the M3ua layer in the stack will after a restart, start up all signalling associations.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="remotePortNumber">
+ <description>The port number of the remote signalling point (SP).</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>2905</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="remoteIpAddress1">
+ <description>Remote IpAddress 1, if not used the value should be an empty string.
+Range is 0.0.0.0 - 255.255.255.255
+
+Note! This address is concidered as the primary IP-address. In case of association establisment failure 'remoteIpAddress2' will be used.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="remoteIpAddress2">
+ <description>Remote IpAddress 2, if not used the value should be an empty string.
+Range is 0.0.0.0 - 255.255.255.255
+
+Note! This address cannot be the same as remoteIpAddress1. This address is used when trying to establish association in case association attempt using 'remoteIpAddress1' fails.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCommunicationLost">
+ <description>Number of communication losses.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCongestions">
+ <description>Number of congestions.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDunaRec">
+ <description>Number of DUNA messages received through the association.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDavaRec">
+ <description>Number of DAVA messages received through the association.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSconRec">
+ <description>Number of SCON messages received through the association.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDupuRec">
+ <description>Number of DUPU messages received through the association.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDataMsgSent">
+ <description>The number of data messages sent on the associations related to this signalling point.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDunaSent">
+ <description>Number of DUNA messages sent through the association.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDavaSent">
+ <description>Number of DAVA messages sent through the association.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSconSent">
+ <description>Number of SCON messages sent through the association.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDupuSent">
+ <description>Number of DUPU messages sent through the association.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDataMsgRec">
+ <description>Number of DATA (payload data) messages received through the association.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfErrorMsgRec">
+ <description>Number of ERROR messages received through the association.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfErrorMsgSent">
+ <description>Number of ERROR messages sent through the association.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfNotifyMsgRec">
+ <description>Number of NOTIFY messages received through the association.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDaudMsgSent">
+ <description>The number of daud messages sent on the associations related to this signalling point.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDaudMsgRec">
+ <description>The number of daud messages received on the associations related to this signalling point.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspupSent">
+ <description>The number of ASPUP sent.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspupReceived">
+ <description>The number of ASPUP received.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspdnSent">
+ <description>The number of ASPDN sent.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspdnReceived">
+ <description>The number of ASPDN received.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspacSent">
+ <description>The number of ASPAC sent.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspacReceived">
+ <description>The number of ASPAC received.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspiaSent">
+ <description>The number of ASPIA sent.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspiaReceived">
+ <description>The number of ASPIA received.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspupAckSent">
+ <description>The number of ASPUP_Ack sent.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspupAckReceived">
+ <description>The number of ASPUP_Ack received.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspdnAckSent">
+ <description>The number of ASPDN_Ack sent.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspdnAckReceived">
+ <description>The number of ASPDN_Ack received.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspacAckSent">
+ <description>The number of ASPAC_Ack sent.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspacAckReceived">
+ <description>The number of ASPAC_Ack received.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspiaAckSent">
+ <description>The number of ASPIA_Ack sent.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspiaAckReceived">
+ <description>The number of ASPIA_Ack received.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfM3uaDataMsgDiscarded">
+ <description>The number of data Messages discarded.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <action name="setAutoActivate">
+ <description>This action starts the association.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="setAutoDown">
+ <description>This action stops the association.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="Sctp">
+ <description>This MO represents the SCTP, Stream Control Transmission Protocol in Cello.
+SCTP is designed to transport signaling messages over IP networks.</description>
+ <attribute name="SctpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the Ip Access Host.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="numberOfAssociations">
+ <description>The maximum number of M3uAssociations that can be handled by this SCTP MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>512</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds a list of the M3Ua's handled by the SCTP.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="M3uAssociation"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="ipAccessHostGpbId">
+ <description>The identity of the IpAccessHostGbp reserved by this MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="IpAccessHostGpb"/>
+ </dataType>
+ </attribute>
+ <attribute name="minimumRto">
+ <description>The minimum value for RTO (Retransmission time-out).
+The minimumRto shall be larger than tSack + expected Round Trip Time.
+
+Unit is second/100.
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>4</min> <max>500</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maximumRto">
+ <description>The maximum value for RTO (Retransmission time-out).
+
+Unit is second/100.
+
+maximumRto must be larger than minimumRto.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>4</min> <max>180000</max>
+ </range>
+ <defaultValue>15</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="initialRto">
+ <description>The initial value that the RTO (Retransmission time-out) will take prior to the first RTT (Round Trip Time) measure.
+
+Note that the value for 'initialRto' has to be equal to or greater than 'minimumRto'.
+
+Unit is seconds/100.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>4</min> <max>180000</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="rtoAlphaIndex">
+ <description>This parameter is used for computing the value of the SRTT (Smoothed Round Trip Time) for a specific destination
+address. Is is used to weight the RTT values, and it's value must be between 0 and 1 (0 &lt; rtoAlpha &lt; 1). A value
+close to 1 gives a higher importance to the last RTT measurement.
+The range of possible values in the configuration file and the actual value given to this parameter within the module
+are the following:
+
+rtoAlphaIndex = 1 -&gt; RTO-Alpha = 1/2
+rtoAlphaIndex = 2 -&gt; RTO-Alpha = 1/4
+rtoAlphaIndex = 3 -&gt; RTO-Alpha = 1/8
+rtoAlphaIndex = 4 -&gt; RTO-Alpha = 1/16</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>4</max>
+ </range>
+ <defaultValue>3</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="rtoBetaIndex">
+ <description>This parameter is used for computing the the value of RTTVar (Round Trip Time Variation) of a destination
+address.
+It's value must be between 0 and 1 (0 &lt; rtoBetaIndex &lt; 1). A value close to 1 gives more importance to the
+last observed variation.
+The range of possible values in the configuration file and the actual value given to this parameter within the module
+are the following:
+
+rtoBetaIndex = 1 -&gt; RTO-Beta = 1/2
+rtoBetaIndex = 2 -&gt; RTO-Beta = 1/4
+rtoBetaIndex = 3 -&gt; RTO-Beta = 1/8
+rtoBetaIndex = 4 -&gt; RTO-Beta = 1/16
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>4</max>
+ </range>
+ <defaultValue>2</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="validCookieLife">
+ <description>This parameter sets up the lifespan of the State Cookie sent in the INIT_ACK chunk. It is used for limiting the
+the valid amount of time between sending the INIT_ACK and the reception of a COOKIE_ECHO chunk when
+establishing an association.
+If a COOKIE_ECHO chunk arrives after 'validCookieLife' has expired when sending an INIT_ACK chunk, the
+COOKIE_ECHO shall be discarded and no association will be established.
+
+Unit is seconds.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>180</max>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="allowedIncrementCookieLife">
+ <description>The sender of an INIT chunk may request to the remote endpoint a cookie life-span increase (for example, if a previous attempt to
+connect failed due to a state-cookie error). If the value sent in the "Cookie Preservative field" of the INIT chunk is less or equal to
+this parameter, the reciver of the INIT chunk will increase the 'validCookieLife' with the number of seconds specified. If the value
+present in the "Cookie Preservative field" is higher than this parameter, the cookie life should be incremented with the number of
+seconds specified by the parameter.
+
+Unit is seconds.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>180</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="keyChangePeriod">
+ <description>Defines how often the secret key used for computing the MAC (Message Authentication Code) on the State Cookie is changed.
+
+Unit is seconds.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>180</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="associationMaxRtx">
+ <description>This is the maximum number of consecutive retransmissions to a remote peer (on all the destination transport addresses of the peer, if it's multi homed). If the number of retransmissions becomes higher than this value, the remote peer shall be considered unreachable and the association shall be closed down.
+
+The value of this attribute should be greater than, or equal to the value of the attribute 'pathMaxRtx'.
+
+Note that for a specific association, it might happen that all the remote addresses (if the the remote end is multi homed) becomes unreachable without exceeding the 'associationMaxRtx'. In such a case the association will be closed down.
+
+Note! The value need to be increased to avoid frequent CommLost's in case of an unstable network.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>20</max>
+ </range>
+ <defaultValue>2</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pathMaxRtx">
+ <description>Maximum number of consecutive retransmissions to a remote transport address. If the number of retransmissions becomes higher than this value, the remote transport address shall be considered as "inactive" and no data shall be sent to it. If all of the remote transport addresses becomes "inactive", tha association will be closed down.
+
+Note! The value need to be increased to avoid frequent CommLost's in case of an unstable network.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>20</max>
+ </range>
+ <defaultValue>2</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxInitialRtrAtt">
+ <description>The maximum nimber of retransmissions allowed for both INIT and COOKIE_ECHO chunks. If the number of retransmissions
+exceeds this value, then the SCTP must abort the initialization of the association and report the error to the user.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxShutDownRtrAtt">
+ <description>The maximum number of retransmission during the shutdown phase of an association.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="heartbeatInterval">
+ <description>The amount of time added to the RTO (Retransmission Time Out) of a specific address when setting up the period of
+time between sending heartbeats. Small values can lead to an earlier detection of unreachable addresses than higher
+values. Note that sendig often might lead to performace penalty.
+
+Unit is seconds.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>1800</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="heartbeatStatus">
+ <description>This attribute enables/disables heartbeats for associations.
+
+True = Enables</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="maxIncomingStream">
+ <description>This is the maximum incoming streams (MIS) for an association. Established associations might have an IS less or equal to
+this, but it's MIS can never be higher than the value of this attribute.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16384</max>
+ </range>
+ <defaultValue>17</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxOutgoingStream">
+ <description>The maximum number of outgonig streams for an association.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16384</max>
+ </range>
+ <defaultValue>17</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxUserDataSize">
+ <description>The maximum number of bytes a user is allowed to pass as a non fragmentable user data in a SCTP_SEND_REQ message
+(fixed user MTU):
+The values for this attribute is 'user' data and do not include IP header (20 bytes), SCTP header (12 bytes) or DATA chunk
+header (16 bytes).
+
+Unit is bytes.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>528</min> <max>65484</max>
+ </range>
+ <defaultValue>1432</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="mBuffer">
+ <description>This attribute sets the size of the buffer used for storing user data pending to be sent or retransmitted in an association. I.e. establish the maximum amount of user data that SCTP shall buffer before discarding user messages.
+
+The Unit is in kilo bytes.
+
+Note! The restriction on this attribute is:
+mBuffer x number of M3uAssociation MOs connected to this Sctp + 20 Mb &lt;= the heap for Sctp program.
+
+Note! The value may need to be increased to ensure stable dataflow at high load.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>2048</max>
+ </range>
+ <defaultValue>128</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="nThreshold">
+ <description>This attribute sets the value of the threshold used by SCTP to stop the delivery of data on anassociation.
+Once nThreshold or more bytes are queued and pending to be sent, the SCTP layer shall issue an indication to the user.
+The value of nThreshold should be less than mBuffer in order to be effective. A normal value for nThreshold is 3/4 * mBuffer.
+
+Unit is kilo bytes.
+
+Note! The value may need to be increased to ensure stable dataflow at high load.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>2048</max>
+ </range>
+ <defaultValue>96</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tSack">
+ <description>The delay of sending the SACK. I.e. the time from DATA chunk reception to Sack chunk sending.
+
+Unit is second/100</description>
+ <dataType>
+ <long>
+ <range>
+ <min>2</min> <max>50</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxDataSizeIp">
+ <description>The maximum number of bytes SCTP shall be able to fetch every time it reads from the socket.
+
+Note! This value includes the Ip header, 20 bytes.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1500</min> <max>65535</max>
+ </range>
+ <defaultValue>8192</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="initialAdRecWin">
+ <description>The value of the initial advertised reciver window.
+
+Note! The range is 1500 to maxDataSizeIp.
+
+Unit is bytes.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1500</min> <max>65535</max>
+ </range>
+ <defaultValue>8192</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="intervalOobPkts">
+ <description>The number of seconds for the interval for which the counter for out of the blue chunks will be reset.
+
+Unit is seconds.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>6500</max>
+ </range>
+ <defaultValue>3600</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="intervalLostUser">
+ <description>The number of seconds for the interval for which the SCTP will decide that the SCTP user that lost the
+connection is dead. After the time specified in this attribute has elapsed, all associations related to the
+SCTP user will be destroyed.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>3600</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxBurst">
+ <description>The number of packages that will be sent during the fast retransmit phase when a SACK is processed.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16384</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="nPercentage">
+ <description>The size of 'n' inpercentage when SCTP_CONGESTION_CEASE_IND is sent. At 100 percent the
+primitive will buffer usage goes below 'nThreshold'.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>85</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="bundlingActivated">
+ <description>This attribute enables/disables the use of bundling.
+Valid values:
+1: enabled.
+0: disabled.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="bundlingTimer">
+ <description>This attribute specifies maximum SCTP bundling delay.
+Value=0 means that SCTP will only bundle what is available and send directly (no delay).
+Unit is milliseconds</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>1000</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpCurrEstab">
+ <description>Number of SCTP associations for which the current state is either ESTABLISHED, SHUTDOWN-PENDING, or SHUTDOWN-RECEIVED.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpActiveEstab">
+ <description>Number of times that SCTP associations have made a direct transition to the ESTABLISHED state from the COOKIE-ECHOED state.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpPassiveEstab">
+ <description>Number of times that SCTP associations have made a direct transition to the ESTABLISHED state from the CLOSED state.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpAborted">
+ <description>Number of times that SCTP associations have made a direct transition to the CLOSED state from any state using the primitive ABORT.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpShutdowns">
+ <description>Number of times that SCTP associations have made a direct transition to the CLOSED state from either the SHUTDOWN-SENT state or the SHUTDOWN-ACK-SENT state.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatAssocOutOfBlue">
+ <description>Number of out of the blue packets (SCTP packet correctly formed-right checksum- but the receiver is not able to identify the association to which this packet belongs) received by the host.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatSentChunks">
+ <description>Number of complete data chunks sent to the peers (no retransmissions included).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatRecChunks">
+ <description>Number of complete data chunks received from the peers (no retransmissions included).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatOutOfOrderSendChunks">
+ <description>Number of unordered chunks sent to the peers.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatOutOfOrderRecChunks">
+ <description>Number of unordered chunks received from the peers.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatChecksumErrorCounter">
+ <description>Number of SCTP packets received from the peers with an invalid checksum.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatRetransChunks">
+ <description>Number of data chunks retransmitted to the peers.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatSentControlChunks">
+ <description>Number of datagrams sent with chunk type id &gt; 0.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatReceivedControlChunks">
+ <description>Number of datagrams Receivedwith chunk type id &gt; 0.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatFragmentedUserMsg">
+ <description>Number of fragmented user messages, incremented when the first data chunk of a fragmented message is sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatReassembledUserMsg">
+ <description>Number of reassembled user messages, incremented when the first data chunk of a fragmented message is received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatSentPackages">
+ <description>Number of SCTP packages sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatReceivedPackages">
+ <description>Number of SCTP packages Received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatCommStop">
+ <description>Number of times the SCTP has sent a communication stop indication to the user.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatCommResume">
+ <description>Number of times SCTP has sent a communication resume indication to the user.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatSentChunksDropped">
+ <description>Number of sent chunks that SCTP has been forced to drop due to buffer overflow in the sending buffer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatRecChunksDropped">
+ <description>Number of received chunks that SCTP has been forced to drop due to buffer overflow in the receiving buffer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Sts1SpeTtp">
+ <description>This MO represents the termination of the SONET higher order paths.
+This MO is automatically created when creating the OS155SPITTP with mux mode
+set to E1_J1_T1_LEVEL and standardmode set to ANSI.
+
+The performance monitoring counters in the Sts1SpeTtp MO is set to 0 (zero) at start or restart of the node.
+When the value is to large to fit in to a long (31bit) the counter turns over and starts from 0 again.</description>
+ <attribute name="Sts1SpeTtpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>enabled or disabled according to the actual operational state of the Sts3CspeTtp.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="aisPReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="rdiPReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="timConsequentAction">
+ <description>Trace Identifier Mismatch (TIM) consequent action, i.e. for generation of Alarm Indication Signal (AIS) downstream and Remote Defect Indication (RDI) upstream as a consequence of the TIM detection.
+
+True - enabled.
+False - disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="expectedPathTrace">
+ <description>Expected path trace.
+
+The string can be of 64 characters length, or empty string ("").
+
+Note: An empty string for this attribute means that the detection of Trace Identifier Mismatch (TIM) should be disabled. This attribute is set to empty string every time attribute pathTraceFormat is set.</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>64</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="transmittedPathTrace">
+ <description>The transmitted path trace.
+Can be defined in two formats. The format may be in 16 or 64 characters. Usually 16 is used for ETSI and 64 for ANSI/TTC.
+
+Note: The string must be of 15 or 62 characters length, or empty string ("").</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>64</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="pmEsp">
+ <description>Performance Monitoring counter for ES, Errored Seconds.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSesp">
+ <description>Performance Monitoring counter for Severely Errored Seconds, SES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Vt15Ttp">
+ <description>This MO is automatically created when the configuring the Os155SpiTtp. It represents the termination of the SONET VP 1.5 path layer.
+
+This MO is automatically created when creating the Os155SpiTtp MO with the following conditions:
+muxmode = E1_J1_T1_LEVEL
+standardmode = ANSI
+
+The performance monitoring counters in the Vt15Ttp is set to 0 (zero) at start or restart of the node.
+When the value is too large too fit in to a long (31bit) the counter turns over and starts from 0 again.
+</description>
+ <systemCreated/>
+ <attribute name="Vt15TtpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="aisVreporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="rdiVreporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimer">
+ <description>This timer defines the time that elapses before shut down when administrativeState is se to 'shuttingDown'.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>100000</max>
+ </range>
+ <defaultValue>1800</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the Vt15Ttp MO.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of the Vt15Ttp MO.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmEs">
+ <description>Performance monitoring counter of Errored Seconds (ES).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSes">
+ <description>Performance monitoring counter for Serverely Errored Seconds.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="T1Ttp">
+ <description>This MO represents a channelised T1 interface in the node. The T1Ttp MO does not define which type of traffic (TDM or ATM) that the interface should support. Please refer to the Ds0Bundle, AtmPort, IMALink and IMAGroup objects for details about configuration of traffic type.
+
+The performance monitoring counters in the T1Ttp MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.
+
+Note! This MO is automatically created as a consequence of creating an Os155SpiTtpMo
+Please refer to the Os155SpiTtpMo for more details.</description>
+ <systemCreated/>
+ <attribute name="T1TtpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="aisReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="rdiReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the T1Ttp MO.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmEs">
+ <description>Performance monitoring counter of Errored Seconds (ES).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSes">
+ <description>Performance monitoring counter for Serverely Errored Seconds.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving AtmPort MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByImaLink">
+ <description>The identity of the reserving ImaLink MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ImaLink"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="E3PhysPathTerm">
+ <description>This MO represents an E3 (i.e. 34 Mbit/s) physical interface in the node. Please refer to the AtmPort object for details about configuration of traffic type.
+
+Note! The performance monitoring counters in the E3PhysPathTerm MO is set to 0 (zero) at start or restart of the node.
+When the value is too large too fit in to a long (31bit) the counter turns over and starts from 0 again.</description>
+ <attribute name="E3PhysPathTermId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of the E3PhysPathTerm.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimeout">
+ <description>The shut-down timer. It is used when the administrativeState is set to shutdown.
+
+Value in seconds, must be a positive value.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100000</max>
+ </range>
+ <defaultValue>1800</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>enabled or disabled according to the actual operational state of the Physical Line Termination. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="lineNo">
+ <description>The actual Line number on the board.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>2</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="loopback">
+ <description>Possible values
+
+none - This is the normal state, no loop back is performed (and ordinary traffic is running).
+
+line - The physical path is looped on the line side, the external incoming path is looped back to the external outgoing path.
+
+system - The physical path is looped on the system side, the (node-) internal incoming path is looped back to the internal outgoing path.
+
+Note! administrativeStatus must be set to locked when setting loopback attribute.</description>
+ <dataType>
+ <enumRef name="LoopbackState">
+ <defaultValue>none</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="degDegThr">
+ <description>The threshold decides how many of the received blocks that are allowed to have bit errors. The measurement is made on a per-second basis and if the threshold is passed the second is considered bad.
+
+This is a percentage value.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="degDegM">
+ <description>How many bad seconds in a row that causes a Degraded Signal alarm.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>2</min> <max>10</max>
+ </range>
+ <defaultValue>7</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="aisReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="rdiReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="pmEs">
+ <description>Performance Monitoring counter for ES, Errored Seconds.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSes">
+ <description>Performance Monitoring counter for Severely Errored Seconds, SES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByTraffic">
+ <description>The identity of the reserving AtmPort MO. </description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBySync">
+ <description>The identity of the reserving Synchronization MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Synchronization"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="T3PhysPathTerm">
+ <description>This MO represents an T3 (i.e. 45 Mbit/s) physical interface in the node. Please refer to the AtmPort object for details about configuration of traffic type.
+
+Note! The performance monitoring counters in the T3PhysPathTerm MO is set to 0 (zero) at start or restart of the node.
+When the value is too large too fit in to a long (31bit) the counter turns over and starts from 0 again.</description>
+ <attribute name="T3PhysPathTermId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>enabled or disabled according to the actual operational state of the Physical Line Termination. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of the T3PhysPathTerm MO.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimeout">
+ <description>The shut-down timer. It is used when the administrativeState is set to shutdown.
+
+Value in seconds, must be a positive value.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100000</max>
+ </range>
+ <defaultValue>1800</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="lineNo">
+ <description>The actual Line number on the board.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>2</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="loopback">
+ <description>Possible values
+
+none - This is the normal state, no loop back is performed (and ordinary traffic is running).
+
+line - The physical path is looped on the line side, the external incoming path is looped back to the external outgoing path.
+
+system - The physical path is looped on the system side, the (node-) internal incoming path is looped back to the internal outgoing path.
+
+Note! administrativeStatus must be set to locked when setting loopback attribute.</description>
+ <dataType>
+ <enumRef name="LoopbackState">
+ <defaultValue>none</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="aisReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="rdiReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="pmEsCpp">
+ <description>Performance Monitoring counter for ES, Errored Seconds based on C-bit parity.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSesCpp">
+ <description>Performance Monitoring counter for Severely Errored Seconds, SES based on C-bit parity.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByTraffic">
+ <description>The identity of the reserving AtmPort MO. </description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBySync">
+ <description>The identity of the reserving Synchronization MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Synchronization"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Etm3">
+ <description>This MO represents the hardware of the ET-M3 board type. It only represents the ET specific hardware, while the DBM module of the board is represented by the PlugInUnit MO.
+
+The ET-M3 board contains 2 physical ports that can be configured as either E3 (ETSI) or T3(ANSI).
+
+Each port on the ET-M3 board can be used to carry ATM traffic.
+
+At the VP/VC endpoints, the Lost FPM/BR cells counters are not available.
+
+IMA is not applicable for theETM3 board.
+
+The ET-M3 board supports eight bidirectional F4/F5 PM flow per port.
+
+The number of VCC TP+VPC TP with performance monitoring enabled (i.e. PM mode &lt;&gt; off) is restricted to 8/port.
+
+Each port can support up to 240 ATM VC connections. Sixteen of these connections are reserved for AAL2 paths, and therefore sixteen AAL2 multiplexers per port are available.
+
+Each port can support up to 16 VP connections. </description>
+ <attribute name="Etm3Id">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Enabled or disabled according to the actual operational state of the Etm3 board.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="SccpApRemote">
+ <description>This Managed Object represents an SCCP Remote Access Point. An SCCP AP instance is a logical point in the SCCP network at which an SCCP user can access the services provided by the SCCP and the SCCP can deliver its services to the SCCP user. The SCCP Remote Access Point is identified by a SubSystem Number (SSN).
+
+A remote SccpAp represents an access point in another node and is related to a Mtp3bAp MO.
+
+The performance monitoring counters found in SccpAp MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is a shutdown request from the CLI (Cluster Interface).</description>
+ <attribute name="SccpApRemoteId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the SCCP AP. The operability of the SCCP AP is described by this attribute which has two possible values:
+
+Disabled: The SCCP AP is totally inoperable and unable to provide the service to the user (e.g. if the MTP-3b AP is not usable).
+
+Enabled: The SCCP AP is partly or fully operable and available for use.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds a list of the reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="mtp3bApId">
+ <description>The identity of the Mtp3bAp used by this MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Mtp3bAp"/>
+ </dataType>
+ </attribute>
+ <attribute name="ssN">
+ <description>The sub system number, SSN, of the SCCP Access Point. Note that this has to be a unique number.
+
+The SSN has to be unique among all other SccpApRemote MOs that has the same DPC in their corresponding Mtp3bSrs MOs.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>2</min> <max>255</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="IpAccessHostGpb">
+ <description>This MO represents the Ip Access Host used for payload. This host type executes on a GPB board (GeneralPocessorUnit).
+
+Note! If autoConfig is set to ON, the Ip Addresses and the Prefixes for this MO is set by the IpAccessAutoConfig MO.
+
+Note! There can be a maximum of 128 host's in the node, and only one host on each main processor.
+
+Note! The host cannot be configured on a MP which have a MediumAccessUnit-child MO. They are exclusive.
+
+Note! The 'administrativeState' has to be set to LOCKED in order to be able to delete this host.</description>
+ <attribute name="IpAccessHostGpbId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO, can be of type Sctp.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the Ip Access Host.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>DEGRADED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of the Ip Access Host.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimer">
+ <description>The shut-down timer. It is used when the administrativeState is set to shutdown.
+
+Value in seconds, must be a positive value.</description>
+ <dataType>
+ <long>
+ <defaultValue>10</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="linkStatusAddress1">
+ <description>The link status for IpAddress1.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="linkStatusAddress2">
+ <description>The link status for IpAddress2, only valid if 2 IpAddresses are configured for this host.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="generalProcessorUnitId">
+ <description>Holds a reference to the GPU (GenerelProcessorUnit).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="GeneralProcessorUnit"/>
+ </dataType>
+ </attribute>
+ <attribute name="autoConfig">
+ <description>This attribute specifies whether the auto configuration feature for the Ip AccessHost is used or not.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="AutoConfigurationMode">
+ <defaultValue>OFF</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="autoConfigIdentity">
+ <description>The identity of the IpAccessAutoConfig MO used by this host.
+
+Note! This attribute is mandatory if 'autoConfig' is set to ON.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="IpAccessAutoConfig"/>
+ </dataType>
+ </attribute>
+ <attribute name="autoConfigIdentity2">
+ <description>The identity of the IpAccessAutoConfig MO used by this host.
+
+Note! This attribute can only be set if 'autoConfig' is set to 'ON'. This attribute is not neccesary to set if 'autoConfig' is set to ON, unless the host shall have two Ip Addresses automatically assigned.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="IpAccessAutoConfig"/>
+ </dataType>
+ </attribute>
+ <attribute name="ipAddress">
+ <description>The IpAddress.
+
+Note! If autoConfig = OFF this attribute is mandatory.
+Note! If the autoConfiguration is used for this IpAccessHostGpb (autoConfig = ON) this attribute cannot be set. This attribute is then set by the 'IpAccessAutoConfig MO'.
+Note! If the attribute is set, its value must not be the same as for attribute ipAddress2.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ipAddress2">
+ <description>The second IpAddress.
+
+Note! If autoConfig = OFF this attribute is possible to set. This attribute should only be set if multi-homing is used for this host (i.e. two addresses defined).
+Note! If the autoConfiguration is used for this IpAccessHostGpb (autoConfig = ON) this attribute cannot be set. This attribute is then set by the 'IpAccessAutoConfig MO'.
+Note! If the attribute is set, its value must not be the same as for attribute 'ipAddress'.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="pathMTUDiscovery">
+ <description>Specifies whether path MTU discovery should be used by this host.
+
+Note! in order to be able to set the value for this attribute, the administrative state has to be locked.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="mtu">
+ <description>The maximum transfer unit.
+
+The MTU has a initial value of 1452 if pathMTUDiscovery is set to false.
+If pathMTUDiscovery is set to true, the initial value of MTU is 1452.
+
+Note! in order to be able to set the value for this attribute, the administrative state has to be locked.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>72</min> <max>2048</max>
+ </range>
+ <defaultValue>1452</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ipDefaultTtl">
+ <description>The default value inserted into the Time-To-Live field of the IP header of datagrams originated at this entity,
+whenever a TTL value is not supplied by the transport layer protocol.
+
+Note! in order to be able to set the value for this attribute, the administrative state has to be locked.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>255</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ipReasmTimeout">
+ <description>The maximum number of seconds which received fragments are
+held while they are awaiting reassembly at this entity.
+
+Note! in order to be able to set the value for this attribute, the administrative state has to be locked.
+
+Note! The value for this attribute has to be positive.</description>
+ <dataType>
+ <long>
+ <defaultValue>300</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="nextHopIpAddr">
+ <description>The next hop IP address.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="nextHopIpAddr2">
+ <description>The secondary next hop IP address.
+
+Note! This attribute must only be set if one of the following conditions are fulfilled:
+1. Attribute 'ipAddress2' is set.
+2. Attribute 'autoConfig' = 'ON' and attribute 'autoConfigIdentity2' is set.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="networkPrefix">
+ <description>The network prefix.
+
+The prefix denotes how many bits that are used for calculating the subnet mask.
+
+Note! The default value 0 (zero) is most likely not possible to use and an other value should be submitted if this attribute is configured manually.
+Note! If auto configuration is not used (autoConfig = OFF) this attribute must be set (i.e. this attribute is then 'mandatory').
+Note! If auto configuration is used (autoConfig = ON) this attribute cannot be set, networkPrefix is then set by the ipAccessAutoConfig MO class.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>32</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="networkPrefix2">
+ <description>The second network prefix.
+
+The prefix denotes how many bits that are used for calculating the subnet mask.
+
+Note! The default value 0 (zero) is most likely not possible to use and an other value should be submitted if this attribute is configured manually.
+Note! If auto configuration is not used (autoConfig = OFF) and ipAddress2 is set this attribute must be set (i.e. this attribute is then 'mandatory').
+Note! If auto configuration is used (autoConfig = ON) this attribute cannot be set, networkPrefix2 is then set by the ipAccessAutoConfig MO class. </description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>32</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInReceives">
+ <description>The total number of input datagrams received from interfaces, including those received in error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInHdrErrors">
+ <description>The number of input datagrams discarded due to errors in their IP headers, including bad checksums, version number
+mismatch, other format errors, time-to-live exceeded, errors discovered in processing their IP options, etc.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInAddrErrors">
+ <description>The number of input datagrams discarded because the IP address in their IP header's destination field was not a
+valid address to be received at this entity. This count includes invalid addresses (e.g., 0.0.0.0) and addresses of
+unsupported Classes (e.g., Class E). For entities which are not IP routers and therefore do not forward datagrams,
+this counter includes datagrams discarded because the destination address was not a local address.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInUnknownProtos">
+ <description>The number of locally-addressed datagrams received successfully but discarded because of an unknown or
+unsupported protocol.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInDiscards">
+ <description>The number of input IP datagrams for which no problems were encountered to prevent their continued processing, but which
+were discarded (e.g., for lack of buffer space). Note that this counter does not include any datagrams discarded while
+awaiting re-assembly.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInDelivers">
+ <description>The total number of input datagrams successfully delivered to IP user-protocols (including ICMP).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpOutRequests">
+ <description>The total number of IP datagrams which local IP user-protocols (including ICMP) supplied to IP in requests for
+transmission. Note that this counter does not include any datagrams counted in ipForwDatagrams</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpOutDiscards">
+ <description>The number of output IP datagrams for which no problem was encountered to prevent their transmission to their
+destination, but which were discarded (e.g., for lack of buffer space). Note that this counter would include
+datagrams counted in ipForwDatagrams if any such packets met this (discretionary) discard criterion.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpReasmReqds">
+ <description>The number of IP fragments received which needed to be reassembled at this entity.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpReasmOKs">
+ <description>The number of IP datagrams successfully re-assembled.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpReasmFails">
+ <description>The number of failures detected by the IP re-assembly algorithm (for whatever reason: timed out, errors, etc).
+Note that this is not necessarily a count of discarded IP fragments since some algorithms (notably the algorithm
+in RFC 815) can lose track of the number of fragments by combining them as they are received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpFragOKs">
+ <description>The number of IP datagrams that have been successfully fragmented at this entity.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpFragFails">
+ <description>The number of IP datagrams that have been discarded because they needed to be fragmented
+at this entity but could not be, e.g., because their Don't Fragment flag was set.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpFragCreates">
+ <description>The number of IP datagram fragments that have been generated as a result of fragmentation at this entity.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInMsgs">
+ <description>The total number of ICMP messages which the entityreceived.
+Note that this counter includes all those counted by icmpInErrors</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInErrors">
+ <description>The number of ICMP messages which the entity received but determined as having
+ICMP-specific errors (bad ICMP checksums, bad length, etc.).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInDestUnreachs">
+ <description>The number of ICMP Destination Unreachable messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInTimeExcds">
+ <description>The number of ICMP Time Exceeded messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInParamProbs">
+ <description>The number of ICMP Parameter Problem messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInSrcQuenchs">
+ <description>The number of ICMP Source Quench messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInRedirects">
+ <description>The number of ICMP Redirect messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInEchos">
+ <description>The number of ICMP Echo (request) messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInEchoReps">
+ <description>The number of ICMP Echo Reply messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutMsgs">
+ <description>The total number of ICMP messages which this entity attempted to send.
+Note that this counter includes all those counted by icmpOutErrors.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutErrors">
+ <description>The number of ICMP messages which this entity did not send due to problems discovered within ICMP such as a lack of
+buffers. This value should not include errors discovered outside the ICMP layer such as the inability of IP to route the
+resultant datagram. In some implementations there may be no types of error which contribute to this counter's value.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutDestUnreachs">
+ <description>The number of ICMP Destination Unreachable messages sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutParmProbs">
+ <description>The number of ICMP Parameter Problem messages sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutEchos">
+ <description>The number of ICMP Echo (request) messages sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutEchoReps">
+ <description>The number of ICMP Echo Reply messages sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUdpInDatagrams">
+ <description>The total number of UDP datagrams delivered to UDP users.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUdpNoPorts">
+ <description>The total number of received UDP datagrams for which there was no application at the destination port.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUdpInErrors">
+ <description>The number of received UDP datagrams that could not be delivered for
+reasons other than the lack of an application at the destination port.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUdpOutDatagrams">
+ <description>The total number of UDP datagrams sent from this entity.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInUcastPkts">
+ <description>Performance monitoring counter for the number of input unicast packets delivered to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfOutUcastPkts">
+ <description>Performance monitoring counter for the number of out unicast packets delivered to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInErrors">
+ <description>Performance monitoring counter for the number of input packets discarded due to any error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInDiscards">
+ <description>Performance monitoring counter for the number of input packets discarded due to resource limitations.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInBroadcastPkts">
+ <description>Performance monitoring counter for the number of input broadcast packets delivered to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInMulticastPkts">
+ <description>Performance monitoring counter for the number of input multicast packets delivered to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfOutBroadcastPkts">
+ <description>Performance monitoring counter for the number of output broadcast packets delivered to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfOutMulticastPkts">
+ <description>Performance monitoring counter for the number of output multicast packets delivered to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="SystemFunctions">
+ <description>This MO structures the SystemFunctions of the managed element. It is created automatically and cannot be deleted.
+
+The local distinguished name of this MO is ManagedElement=1, SystemFunctions=1.</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="SystemFunctionsId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Licensing">
+ <description>This MO represents the Licensing (Software Keys) functions in Cello.</description>
+ <systemCreated/>
+ <attribute name="LicensingId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="emergencyStateInfo">
+ <description>This attribute holds information about the emergency status and the time remaining in the current state.
+
+Note! If the node is in emergency state USE_DEGRADED, or the emergency state is USE_DISABLED, the the value of'time' is insignificant.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <structRef name="EmergencyInfo"/>
+ </dataType>
+ </attribute>
+ <attribute name="licenseFileUrl">
+ <description>This attribute returns the URL to the License Key File so it can be viewed with an XML capable web browser
+in case this is a licensed node.
+
+Note! In case the node is not licensed, an empty string will be returned.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>256</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <action name="updateLicenseKeyFile">
+ <description>This action sends a request to the FTP/SFTP server to update the license key file.
+
+User Id for login to FTP/SFTP server where license key files are located.
+If a null string userId is given, anonymous FTP/SFTP transfer is assumed.
+Max length is 20 characters.
+
+Password for login to the FTP/SFTP server where license key files are located.
+Max length is 20 characters.
+
+The IpAddress of the FTP/SFTP server where license key files are located.
+Max length is 16 characters.
+
+Source name and path of the license key file on the FTP/SFTP server.
+Max length is 256 charcters.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="userId">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="password">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="ipAddress">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="sFile">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="setEmergencyState">
+ <description>This action sets the license server into emergency state.
+I.e. opens up all licensed features and capacity restrictions.
+Disabling emergency state is done by loading a new license key file.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="TimingUnit2">
+ <description>This MO represents a timing unit2 (reference clock) in the node.
+
+The corresponding Program shall be of LoadModuleLoaderType, SpmFpgaLoader.</description>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Operational state of TimingUnit</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status of the TimingUnit.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="TimingUnit2Id">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="SccpPolicing">
+ <description>The SccpPolicing MO represents the policing function in CPP.
+
+The originatingMtp3bSpc is a madatory attribute for policing in one local node (i.e. a SRP in one NI).
+For policing between two local nodes (i.e. a SRP between two NIs) the originatingMtp3bSpc can be replaced by the originatingSccpSpId.
+Optional attributes for policing in one local node (i.e a SRP in one NI) are destinationMtp3bSpc, destinationSccpSsn, originatingSccpSsn and policingGlobalTitle.
+For policing between two local nodes (i.e. a SRP between two NIs) the destinationMtp3bSpc can be replaced by the destinationSccpSpId.</description>
+ <attribute name="SccpPolicingId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="originatingMtp3bSpc">
+ <description>The value of the SPC (Signaling Point Code).
+
+Note! If the 'originatingSccpSpId' is specified the 'originatingMtp3bSpc' is invalid.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>16777215</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="destinationMtp3bSpc">
+ <description>The value of the destination SPC (Signaling Point Code).
+
+Note! The default value 0 (zero) means that no SPC is defined.
+Note! If no 'destinationSccpSp' is defined and the value of 'destinationMtp3bSpc' is set to 0 (zero), all Signalling Point Codes (SPC) are valid.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>16777215</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="originatingSccpSpId">
+ <description>The identity of the originating SccpSp MO must be used for policing between local nodes.
+
+Note! If the 'originatingSccpSpId' is specified the 'originatingMtp3bSpc' is invalid.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="originatingSccpSsn">
+ <description>The value of SSN in CgPA (Calling Party Address)
+
+Note! The value 0 (zero) means that all ssN (Sub System Number) are valid.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="destinationSccpSpId">
+ <description>The identity of the destination SccpSp MO can be used for policing between local nodes.
+
+Note! If the 'destinationSccpSpId' is specified the 'destinationMtp3bSpc' is invalid.
+Note! If no destination 'destinationSccpSp' is defined and the value of 'destinationMtp3bSpc' is set to 0, all local nodes are valid.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="destinationSccpSsn">
+ <description>The value of SSN inCdPA (Called Party Address).
+
+Note! The valu 0 (zero) means tha all ssN (Sub System Number) are valid.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="policingGlobalTitle">
+ <description>The Policing Global Title attribute allows to optionally police on Global Title
+
+Default value is considered as no policing Global Title and all GTs are valid.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="GlobalTitleData"/>
+ </dataType>
+ </attribute>
+ <attribute name="discardOrReturnServiceMsg">
+ <description>For a policing case whether to discard or return Service Messages, if the return option is set.</description>
+ <dataType>
+ <enumRef name="DiscardReturnServiceMsg">
+ <defaultValue>DISCARD</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRejectMsg">
+ <description>Performance monitoring counter for the number of rejected messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="SccpAccountingCriteria">
+ <description>The SccpAccountingCriteria MO and the SccpSp MO represents the accounting function in CPP.
+
+Attribute usageType specifies Accounting Remuneration (incoming GT messages) or Verification (outgoing GT messages).
+
+For Remuneration a SccpGlobalTitle MOId in attribute globalTitleId must be defined.
+For Verification a SccpGlobalTitle MOid is defined in attribute globalTitleId, or a SccpEntitySet MOid is defined if accounting shall be made on the resulting new GT.
+
+The attribute ssN is optional .
+The Mtp3bSrs MOid (including an SPC) in attribute pointerId is optional for accounting in one local node (SRP in one NI).
+The SccpSp MOid in attribute pointerId is optional for accounting between two local nodes (SRP between two NIs).
+Attribute countType specifies if Messages och Octets shall be counted.
+Start and stop of accounting and output period for the accounting file is specified in the SccpSp MO.</description>
+ <attribute name="SccpAccountingCriteriaId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="usageType">
+ <description>This attribute specifies if the MO is used for renumeration or verification.
+
+0 = Verification Criteria to detect outgoing massages that will be charged in the next relay node.
+
+1 = Renumeration Criteria to detect incoming messages for relaying, that will be charged.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long/>
+ </dataType>
+ </attribute>
+ <attribute name="ssN">
+ <description>Subsystem Number this Accounting Criteria applies to.
+SubSystem Number 0 (zero) means that any SSN in CdPA (Called Party Address) is valid.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="countType">
+ <description>Specifies type of countes that should be activated.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="SccpCountType">
+ <defaultValue>MESSAGES</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="globalTitleId">
+ <description>The identity of the SccpGlobalTitle MO or the SccpEntitySet MO used by this MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMsg">
+ <description>Performance monitoring counter for the number of messages, both incoming and outgoing.
+
+Note! If 'countType' is set to 'OCTETS' this counter is not valid.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfOctets">
+ <description>Performance monitoring counter for the number of octets, both incoming and outgoing.
+
+Note! If 'countType' is set to 'MESSAGES this counter is not valid.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pointerId">
+ <description>The pointer is an instance of a Mtp3bSrs MO OR an instance of a SccpSP MO.
+
+Note! If no pointerId is set all Signaling Point Codes (SPC) and all Sccp SP identities are valid.
+Note! It is not possible to submit the Id of the SccpSp that the SccpAccountingCriteria belongs to.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Cbu">
+ <description>This MO models the Cbu (Node Control Board) board in CPP.
+The Cbu board integrates the functionality of TUB, SCB, GPB and ETB (ET-MC1) into one Plug-In Unit.
+
+Note! The 'operationalState' is set to disabled if one of the functional parts is faulty. Even if the Cbu is marked with 'operationalState' DISABLED, parts of the Cbu can still be operational.
+
+Note! A functional part on a Cbu board can only be redundant with the same functional part on another Cbu board and thus not with that functional part implemented on a discrete board. Also note that redundancy is only applicable for the GPB part and the TimingUnit part of the Cbu board..
+
+Note! On the Cbu board it is only possible to configure a maximum of 4 physical path terminations. These can be of type E1PhysPathTerm, J1PhyspathTerm or T1PhyspathTerm. It is not possible to create physical path terminations of different standards on the same board.
+
+Note! The Gpu part of the Cbu board (General Processor Unit) retrieves its 'availabilityStatus' from the PlugInUnit MO, thus not represented on the Cbu MO.
+
+Note! When the ET-MC1 is part of the Cbu board it is only possible to configure 4 physical ports as either E1 (ETSI), J1 (TTC) or T1 (ANSI).
+
+Note! This unit may only be inserted in slot 1 and 24 (or more accurately at APN=1 and 0 in a non-standard subrack). If redundant configuration is needed, two Cbu's must be inserted in the subrack.
+If only one Cbu is used it must be placed in slot 1 (in a non-standard subrack) to be able to read the product information data of the subrack</description>
+ <attribute name="CbuId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Provides the possibility to put a user-friendly label on the MO instance.
+
+Note! This attribute cannot be used for uniquely identifing the MO.</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>128</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Enabled or disabled according to the actual operational state of the NCB board.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusEt">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.
+The 'availabilityStatusEt' gives the availability status for the ET part of the NCB board.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusTu">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.
+The 'availabilityStatusTu' gives the availability status for the Timing Unit part of the NCB board.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ </class>
+
+ <relationship name="ManagedElement_to_TransportNetwork">
+ <containment>
+ <parent>
+ <hasClass name="ManagedElement"/>
+ </parent>
+ <child>
+ <hasClass name="TransportNetwork"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Synchronization">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Synchronization"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_SccpSp">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="SccpSp"/>
+ <cardinality>
+ <min>0</min> <max>24</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_UniSaalProfile">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="UniSaalProfile"/>
+ <cardinality>
+ <min>0</min> <max>300</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_UniSaalTp">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="UniSaalTp"/>
+ <cardinality>
+ <min>0</min> <max>4800</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Aal0TpVccTp">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Aal0TpVccTp"/>
+ <cardinality>
+ <min>0</min> <max>2200</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Aal5TpVccTp">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Aal5TpVccTp"/>
+ <cardinality>
+ <min>0</min> <max>6000</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_AtmPort">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="AtmPort"/>
+ <cardinality>
+ <min>0</min> <max>500</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_NniSaalProfile">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="NniSaalProfile"/>
+ <cardinality>
+ <min>0</min> <max>50</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_NniSaalTp">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="NniSaalTp"/>
+ <cardinality>
+ <min>0</min> <max>600</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_AtmTrafficDescriptor">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="AtmTrafficDescriptor"/>
+ <cardinality>
+ <min>0</min> <max>1000</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Aal2PathVccTp">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Aal2PathVccTp"/>
+ <cardinality>
+ <min>0</min> <max>2000</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Aal2RoutingCase">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Aal2RoutingCase"/>
+ <cardinality>
+ <min>0</min> <max>900</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Aal2Sp">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Aal2Sp"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_AtmCrossConnection">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="AtmCrossConnection"/>
+ <cardinality>
+ <min>0</min> <max>5000</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp2TpItu">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp2TpItu"/>
+ <cardinality>
+ <min>0</min> <max>256</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp2TpAnsi">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp2TpAnsi"/>
+ <cardinality>
+ <min>0</min> <max>256</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Aal1TpVccTp">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Aal1TpVccTp"/>
+ <cardinality>
+ <min>0</min> <max>1000</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp3bSpAnsi">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSpAnsi"/>
+ <cardinality>
+ <min>0</min> <max>24</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp3bSpItu">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSpItu"/>
+ <cardinality>
+ <min>0</min> <max>24</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp3bSpTtc">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSpTtc"/>
+ <cardinality>
+ <min>0</min> <max>24</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp2ProfileAnsi">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp2ProfileAnsi"/>
+ <cardinality>
+ <min>0</min> <max>256</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp2ProfileItu">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp2ProfileItu"/>
+ <cardinality>
+ <min>0</min> <max>256</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp2ProfileChina">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp2ProfileChina"/>
+ <cardinality>
+ <min>0</min> <max>256</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp2TpChina">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp2TpChina"/>
+ <cardinality>
+ <min>0</min> <max>256</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp3bSpChina">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSpChina"/>
+ <cardinality>
+ <min>0</min> <max>24</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mspg">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mspg"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_ImaGroup">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="ImaGroup"/>
+ <cardinality>
+ <min>0</min> <max>200</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Aal2QosProfile">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Aal2QosProfile"/>
+ <cardinality>
+ <min>0</min> <max>20</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Aal2QosCodePointProfile">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Aal2QosCodePointProfile"/>
+ <cardinality>
+ <min>0</min> <max>20</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Sctp">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Sctp"/>
+ <cardinality>
+ <min>0</min> <max>10</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Subrack_to_Slot">
+ <containment>
+ <parent>
+ <hasClass name="Subrack"/>
+ </parent>
+ <child>
+ <hasClass name="Slot"/>
+ <cardinality>
+ <min>1</min> <max>28</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Slot_to_PlugInUnit">
+ <containment>
+ <parent>
+ <hasClass name="Slot"/>
+ </parent>
+ <child>
+ <hasClass name="PlugInUnit"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Slot_to_ManagedObject">
+ <containment>
+ <parent>
+ <hasClass name="Slot"/>
+ </parent>
+ <child>
+ <hasClass name="ManagedObject"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="ManagedElement_to_ManagedObject">
+ <containment>
+ <parent>
+ <hasClass name="ManagedElement"/>
+ </parent>
+ <child>
+ <hasClass name="ManagedObject"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_ManagedObject">
+ <description>This containment relation indicated that any kind of board may be used to specilize PlugInUnit.</description>
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="ManagedObject"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Subrack_to_ManagedObject">
+ <containment>
+ <parent>
+ <hasClass name="Subrack"/>
+ </parent>
+ <child>
+ <hasClass name="ManagedObject"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="VpcTp_to_VclTp">
+ <containment>
+ <parent>
+ <hasClass name="VpcTp"/>
+ </parent>
+ <child>
+ <hasClass name="VclTp"/>
+ <cardinality>
+ <min>0</min> <max>5000</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="ManagedElement_to_Equipment">
+ <containment>
+ <parent>
+ <hasClass name="ManagedElement"/>
+ </parent>
+ <child>
+ <hasClass name="Equipment"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="ManagedElement_to_IpSystem">
+ <containment>
+ <parent>
+ <hasClass name="ManagedElement"/>
+ </parent>
+ <child>
+ <hasClass name="IpSystem"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="ManagedElement_to_SwManagement">
+ <containment>
+ <parent>
+ <hasClass name="ManagedElement"/>
+ </parent>
+ <child>
+ <hasClass name="SwManagement"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="ManagedElement_to_SwitchFabric">
+ <containment>
+ <parent>
+ <hasClass name="ManagedElement"/>
+ </parent>
+ <child>
+ <hasClass name="SwitchFabric"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="ManagedElement_to_ManagedElementData">
+ <containment>
+ <parent>
+ <hasClass name="ManagedElement"/>
+ </parent>
+ <child>
+ <hasClass name="ManagedElementData"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="ManagedElement_to_SystemFunctions">
+ <containment>
+ <parent>
+ <hasClass name="ManagedElement"/>
+ </parent>
+ <child>
+ <hasClass name="SystemFunctions"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Equipment_to_Subrack">
+ <containment>
+ <parent>
+ <hasClass name="Equipment"/>
+ </parent>
+ <child>
+ <hasClass name="Subrack"/>
+ <cardinality>
+ <min>0</min> <max>9</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Equipment_to_Jvm">
+ <containment>
+ <parent>
+ <hasClass name="Equipment"/>
+ </parent>
+ <child>
+ <hasClass name="Jvm"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Subrack_to_Fan">
+ <containment>
+ <parent>
+ <hasClass name="Subrack"/>
+ </parent>
+ <child>
+ <hasClass name="Fan"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SwManagement_to_LoadModule">
+ <containment>
+ <parent>
+ <hasClass name="SwManagement"/>
+ </parent>
+ <child>
+ <hasClass name="LoadModule"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SccpScrc_to_SccpApLocal">
+ <description>The SccpApLocal represents a local SSN, no relation exists to an Mtp3bAp
+
+Of the possible 216 SccpAps allowed on a node, a maximum of 16 are allowed to be local, and a maximum of 200 are allowed to be remote.</description>
+ <containment>
+ <parent>
+ <hasClass name="SccpScrc"/>
+ </parent>
+ <child>
+ <hasClass name="SccpApLocal"/>
+ <cardinality>
+ <min>0</min> <max>16</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SccpSp_to_SccpScrc">
+ <containment>
+ <parent>
+ <hasClass name="SccpSp"/>
+ </parent>
+ <child>
+ <hasClass name="SccpScrc"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SccpScrc_to_SccpEntitySet">
+ <containment>
+ <parent>
+ <hasClass name="SccpScrc"/>
+ </parent>
+ <child>
+ <hasClass name="SccpEntitySet"/>
+ <cardinality>
+ <min>0</min> <max>2048</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SccpScrc_to_SccpGlobalTitle">
+ <containment>
+ <parent>
+ <hasClass name="SccpScrc"/>
+ </parent>
+ <child>
+ <hasClass name="SccpGlobalTitle"/>
+ <cardinality>
+ <min>0</min> <max>2048</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SccpScrc_to_SccpApRemote">
+ <containment>
+ <parent>
+ <hasClass name="SccpScrc"/>
+ </parent>
+ <child>
+ <hasClass name="SccpApRemote"/>
+ <cardinality>
+ <min>0</min> <max>200</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SccpScrc_to_SccpPolicing">
+ <containment>
+ <parent>
+ <hasClass name="SccpScrc"/>
+ </parent>
+ <child>
+ <hasClass name="SccpPolicing"/>
+ <cardinality>
+ <min>0</min> <max>1024</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SccpScrc_to_SccpAccountingCriteria">
+ <containment>
+ <parent>
+ <hasClass name="SccpScrc"/>
+ </parent>
+ <child>
+ <hasClass name="SccpAccountingCriteria"/>
+ <cardinality>
+ <min>0</min> <max>100</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Spm_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="Spm"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TimingUnit_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="TimingUnit"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etm4_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="Etm4"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etm1_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="Etm1"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etmc1_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="Etmc1"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etmc41_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="Etmc41"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TimingUnit2_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="TimingUnit2"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etm3_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="Etm3"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Spu_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="Spu"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Fan_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="Fan"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>1</min> <max>2</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etm1_to_E1PhysPathTerm">
+ <containment>
+ <parent>
+ <hasClass name="Etm1"/>
+ </parent>
+ <child>
+ <hasClass name="E1PhysPathTerm"/>
+ <cardinality>
+ <min>0</min> <max>8</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etmc1_to_E1PhysPathTerm">
+ <containment>
+ <parent>
+ <hasClass name="Etmc1"/>
+ </parent>
+ <child>
+ <hasClass name="E1PhysPathTerm"/>
+ <cardinality>
+ <min>0</min> <max>8</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="E1PhysPathTerm_to_Ds0Bundle">
+ <containment>
+ <parent>
+ <hasClass name="E1PhysPathTerm"/>
+ </parent>
+ <child>
+ <hasClass name="Ds0Bundle"/>
+ <cardinality>
+ <min>0</min> <max>31</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etm1_to_J1PhysPathTerm">
+ <containment>
+ <parent>
+ <hasClass name="Etm1"/>
+ </parent>
+ <child>
+ <hasClass name="J1PhysPathTerm"/>
+ <cardinality>
+ <min>0</min> <max>8</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etmc1_to_J1PhysPathTerm">
+ <containment>
+ <parent>
+ <hasClass name="Etmc1"/>
+ </parent>
+ <child>
+ <hasClass name="J1PhysPathTerm"/>
+ <cardinality>
+ <min>0</min> <max>8</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="J1PhysPathTerm_to_Ds0Bundle">
+ <containment>
+ <parent>
+ <hasClass name="J1PhysPathTerm"/>
+ </parent>
+ <child>
+ <hasClass name="Ds0Bundle"/>
+ <cardinality>
+ <min>0</min> <max>24</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="AtmPort_to_VplTp">
+ <containment>
+ <parent>
+ <hasClass name="AtmPort"/>
+ </parent>
+ <child>
+ <hasClass name="VplTp"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpChina_to_Mtp3bAp">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpChina"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bAp"/>
+ <cardinality>
+ <min>0</min> <max>510</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpAnsi_to_Mtp3bAp">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpAnsi"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bAp"/>
+ <cardinality>
+ <min>0</min> <max>510</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpItu_to_Mtp3bAp">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpItu"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bAp"/>
+ <cardinality>
+ <min>0</min> <max>510</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpTtc_to_Mtp3bAp">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpTtc"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bAp"/>
+ <cardinality>
+ <min>0</min> <max>510</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpItu_to_Mtp3bSrs">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpItu"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSrs"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpTtc_to_Mtp3bSrs">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpTtc"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSrs"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpChina_to_Mtp3bSrs">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpChina"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSrs"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSrs_to_Mtp3bSr">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSrs"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSr"/>
+ <cardinality>
+ <min>0</min> <max>5</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpAnsi_to_Mtp3bSrs">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpAnsi"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSrs"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_Etm1">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="Etm1"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_Spu">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="Spu"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_SwitchCoreUnit">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="SwitchCoreUnit"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_GeneralProcessorUnit">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="GeneralProcessorUnit"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_Etm4">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="Etm4"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_TimingUnit">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="TimingUnit"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_SwitchExtensionUnit">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="SwitchExtensionUnit"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_Etmc1">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="Etmc1"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_Etmc41">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="Etmc41"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_Etm3">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="Etm3"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_TimingUnit2">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="TimingUnit2"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_Cbu">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="Cbu"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpChina_to_Mtp3bSls">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpChina"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSls"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpItu_to_Mtp3bSls">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpItu"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSls"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpTtc_to_Mtp3bSls">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpTtc"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSls"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpAnsi_to_Mtp3bSls">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpAnsi"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSls"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpChina_to_Mtp3bSls_0">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpChina"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSls"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpAnsi_to_Mtp3bSls_0">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpAnsi"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSls"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpItu_to_Mtp3bSls_0">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpItu"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSls"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpTtc_to_Mtp3bSls_0">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpTtc"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSls"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSls_to_Mtp3bSlAnsi">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSls"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSlAnsi"/>
+ <cardinality>
+ <min>0</min> <max>16</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSls_to_Mtp3bSlItu">
+ <description>Multiplicity: 0..16</description>
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSls"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSlItu"/>
+ <cardinality>
+ <min>0</min> <max>16</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSls_to_Mtp3bSlTtc">
+ <description>Multiplicity: 0..16</description>
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSls"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSlTtc"/>
+ <cardinality>
+ <min>0</min> <max>16</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSls_to_Mtp3bSlChina">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSls"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSlChina"/>
+ <cardinality>
+ <min>0</min> <max>16</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="IpSystem_to_Ip">
+ <containment>
+ <parent>
+ <hasClass name="IpSystem"/>
+ </parent>
+ <child>
+ <hasClass name="Ip"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="IpSystem_to_Ospf">
+ <containment>
+ <parent>
+ <hasClass name="IpSystem"/>
+ </parent>
+ <child>
+ <hasClass name="Ospf"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="IpSystem_to_IpAccessAutoConfig">
+ <containment>
+ <parent>
+ <hasClass name="IpSystem"/>
+ </parent>
+ <child>
+ <hasClass name="IpAccessAutoConfig"/>
+ <cardinality>
+ <min>0</min> <max>32</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="IpSystem_to_IpAccessHostMsb">
+ <containment>
+ <parent>
+ <hasClass name="IpSystem"/>
+ </parent>
+ <child>
+ <hasClass name="IpAccessHostMsb"/>
+ <cardinality>
+ <min>0</min> <max>128</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="IpSystem_to_IpAccessHostGpb">
+ <containment>
+ <parent>
+ <hasClass name="IpSystem"/>
+ </parent>
+ <child>
+ <hasClass name="IpAccessHostGpb"/>
+ <cardinality>
+ <min>0</min> <max>128</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Ip_to_IpAtmLink">
+ <containment>
+ <parent>
+ <hasClass name="Ip"/>
+ </parent>
+ <child>
+ <hasClass name="IpAtmLink"/>
+ <cardinality>
+ <min>0</min> <max>500</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Ip_to_EthernetLink">
+ <containment>
+ <parent>
+ <hasClass name="Ip"/>
+ </parent>
+ <child>
+ <hasClass name="EthernetLink"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Ip_to_IpRoutingTable">
+ <containment>
+ <parent>
+ <hasClass name="Ip"/>
+ </parent>
+ <child>
+ <hasClass name="IpRoutingTable"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Aal2Sp_to_Aal2Ap">
+ <containment>
+ <parent>
+ <hasClass name="Aal2Sp"/>
+ </parent>
+ <child>
+ <hasClass name="Aal2Ap"/>
+ <cardinality>
+ <min>0</min> <max>850</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Aal2Ap_to_Aal2PathDistributionUnit">
+ <containment>
+ <parent>
+ <hasClass name="Aal2Ap"/>
+ </parent>
+ <child>
+ <hasClass name="Aal2PathDistributionUnit"/>
+ <cardinality>
+ <min>0</min> <max>26</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etm1_to_T1PhysPathTerm">
+ <containment>
+ <parent>
+ <hasClass name="Etm1"/>
+ </parent>
+ <child>
+ <hasClass name="T1PhysPathTerm"/>
+ <cardinality>
+ <min>0</min> <max>8</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TimingUnit_to_TuSyncRef">
+ <containment>
+ <parent>
+ <hasClass name="TimingUnit"/>
+ </parent>
+ <child>
+ <hasClass name="TuSyncRef"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TimingUnit2_to_TuSyncRef">
+ <containment>
+ <parent>
+ <hasClass name="TimingUnit2"/>
+ </parent>
+ <child>
+ <hasClass name="TuSyncRef"/>
+ <cardinality>
+ <min>0</min> <max>2</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Spu_to_Spm">
+ <containment>
+ <parent>
+ <hasClass name="Spu"/>
+ </parent>
+ <child>
+ <hasClass name="Spm"/>
+ <cardinality>
+ <min>0</min> <max>5</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SwManagement_to_ConfigurationVersion">
+ <containment>
+ <parent>
+ <hasClass name="SwManagement"/>
+ </parent>
+ <child>
+ <hasClass name="ConfigurationVersion"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SwManagement_to_UpgradePackage">
+ <containment>
+ <parent>
+ <hasClass name="SwManagement"/>
+ </parent>
+ <child>
+ <hasClass name="UpgradePackage"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SwManagement_to_Repertoire">
+ <containment>
+ <parent>
+ <hasClass name="SwManagement"/>
+ </parent>
+ <child>
+ <hasClass name="Repertoire"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SwManagement_to_PiuType">
+ <containment>
+ <parent>
+ <hasClass name="SwManagement"/>
+ </parent>
+ <child>
+ <hasClass name="PiuType"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SwManagement_to_SwAllocation">
+ <containment>
+ <parent>
+ <hasClass name="SwManagement"/>
+ </parent>
+ <child>
+ <hasClass name="SwAllocation"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SwManagement_to_ReliableProgramUniter">
+ <containment>
+ <parent>
+ <hasClass name="SwManagement"/>
+ </parent>
+ <child>
+ <hasClass name="ReliableProgramUniter"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Ospf_to_OspfInterface">
+ <containment>
+ <parent>
+ <hasClass name="Ospf"/>
+ </parent>
+ <child>
+ <hasClass name="OspfInterface"/>
+ <cardinality>
+ <min>0</min> <max>32</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Ospf_to_OspfArea">
+ <containment>
+ <parent>
+ <hasClass name="Ospf"/>
+ </parent>
+ <child>
+ <hasClass name="OspfArea"/>
+ <cardinality>
+ <min>1</min> <max>4</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Cbu_to_GeneralProcessorUnit">
+ <containment>
+ <parent>
+ <hasClass name="Cbu"/>
+ </parent>
+ <child>
+ <hasClass name="GeneralProcessorUnit"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="GeneralProcessorUnit_to_MediumAccessUnit">
+ <containment>
+ <parent>
+ <hasClass name="GeneralProcessorUnit"/>
+ </parent>
+ <child>
+ <hasClass name="MediumAccessUnit"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SwitchFabric_to_SwitchModule">
+ <containment>
+ <parent>
+ <hasClass name="SwitchFabric"/>
+ </parent>
+ <child>
+ <hasClass name="SwitchModule"/>
+ <cardinality>
+ <min>0</min> <max>32</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SwitchFabric_to_InternalLinkGroup">
+ <containment>
+ <parent>
+ <hasClass name="SwitchFabric"/>
+ </parent>
+ <child>
+ <hasClass name="InternalLinkGroup"/>
+ <cardinality>
+ <min>0</min> <max>31</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="InternalLinkGroup_to_SwitchInternalLink">
+ <containment>
+ <parent>
+ <hasClass name="InternalLinkGroup"/>
+ </parent>
+ <child>
+ <hasClass name="SwitchInternalLink"/>
+ <cardinality>
+ <min>0</min> <max>8</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etm4_to_Os155SpiTtp">
+ <containment>
+ <parent>
+ <hasClass name="Etm4"/>
+ </parent>
+ <child>
+ <hasClass name="Os155SpiTtp"/>
+ <cardinality>
+ <min>0</min> <max>2</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="VplTp_to_VpcTp">
+ <containment>
+ <parent>
+ <hasClass name="VplTp"/>
+ </parent>
+ <child>
+ <hasClass name="VpcTp"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="E1Ttp_to_Ds0Bundle">
+ <containment>
+ <parent>
+ <hasClass name="E1Ttp"/>
+ </parent>
+ <child>
+ <hasClass name="Ds0Bundle"/>
+ <cardinality>
+ <min>0</min> <max>31</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="T1PhysPathTerm_to_Ds0Bundle">
+ <containment>
+ <parent>
+ <hasClass name="T1PhysPathTerm"/>
+ </parent>
+ <child>
+ <hasClass name="Ds0Bundle"/>
+ <cardinality>
+ <min>0</min> <max>24</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="T1Ttp_to_Ds0Bundle">
+ <containment>
+ <parent>
+ <hasClass name="T1Ttp"/>
+ </parent>
+ <child>
+ <hasClass name="Ds0Bundle"/>
+ <cardinality>
+ <min>0</min> <max>24</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpAnsi_to_M3uAssociation">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpAnsi"/>
+ </parent>
+ <child>
+ <hasClass name="M3uAssociation"/>
+ <cardinality>
+ <min>0</min> <max>512</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpItu_to_M3uAssociation">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpItu"/>
+ </parent>
+ <child>
+ <hasClass name="M3uAssociation"/>
+ <cardinality>
+ <min>0</min> <max>512</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Vc12Ttp_to_E1Ttp">
+ <containment>
+ <parent>
+ <hasClass name="Vc12Ttp"/>
+ </parent>
+ <child>
+ <hasClass name="E1Ttp"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Os155SpiTtp_to_Vc4Ttp">
+ <containment>
+ <parent>
+ <hasClass name="Os155SpiTtp"/>
+ </parent>
+ <child>
+ <hasClass name="Vc4Ttp"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Vc4Ttp_to_Vc12Ttp">
+ <containment>
+ <parent>
+ <hasClass name="Vc4Ttp"/>
+ </parent>
+ <child>
+ <hasClass name="Vc12Ttp"/>
+ <cardinality>
+ <min>0</min> <max>63</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etmc41_to_Os155SpiTtp">
+ <containment>
+ <parent>
+ <hasClass name="Etmc41"/>
+ </parent>
+ <child>
+ <hasClass name="Os155SpiTtp"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Os155SpiTtp_to_Sts3CspeTtp">
+ <containment>
+ <parent>
+ <hasClass name="Os155SpiTtp"/>
+ </parent>
+ <child>
+ <hasClass name="Sts3CspeTtp"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Os155SpiTtp_to_Sts1SpeTtp">
+ <containment>
+ <parent>
+ <hasClass name="Os155SpiTtp"/>
+ </parent>
+ <child>
+ <hasClass name="Sts1SpeTtp"/>
+ <cardinality>
+ <min>0</min> <max>3</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Cbu_to_Etmc1">
+ <containment>
+ <parent>
+ <hasClass name="Cbu"/>
+ </parent>
+ <child>
+ <hasClass name="Etmc1"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etmc1_to_T1PhysPathTerm">
+ <containment>
+ <parent>
+ <hasClass name="Etmc1"/>
+ </parent>
+ <child>
+ <hasClass name="T1PhysPathTerm"/>
+ <cardinality>
+ <min>0</min> <max>8</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpChina_to_M3uAssociation">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpChina"/>
+ </parent>
+ <child>
+ <hasClass name="M3uAssociation"/>
+ <cardinality>
+ <min>0</min> <max>512</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="ImaGroup_to_ImaLink">
+ <containment>
+ <parent>
+ <hasClass name="ImaGroup"/>
+ </parent>
+ <child>
+ <hasClass name="ImaLink"/>
+ <cardinality>
+ <min>0</min> <max>8</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SystemFunctions_to_WebServer">
+ <containment>
+ <parent>
+ <hasClass name="SystemFunctions"/>
+ </parent>
+ <child>
+ <hasClass name="WebServer"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Sts1SpeTtp_to_Vt15Ttp">
+ <containment>
+ <parent>
+ <hasClass name="Sts1SpeTtp"/>
+ </parent>
+ <child>
+ <hasClass name="Vt15Ttp"/>
+ <cardinality>
+ <min>0</min> <max>28</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Vt15Ttp_to_T1Ttp">
+ <containment>
+ <parent>
+ <hasClass name="Vt15Ttp"/>
+ </parent>
+ <child>
+ <hasClass name="T1Ttp"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etm3_to_E3PhysPathTerm">
+ <containment>
+ <parent>
+ <hasClass name="Etm3"/>
+ </parent>
+ <child>
+ <hasClass name="E3PhysPathTerm"/>
+ <cardinality>
+ <min>0</min> <max>2</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etm3_to_T3PhysPathTerm">
+ <containment>
+ <parent>
+ <hasClass name="Etm3"/>
+ </parent>
+ <child>
+ <hasClass name="T3PhysPathTerm"/>
+ <cardinality>
+ <min>0</min> <max>2</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SystemFunctions_to_Licensing">
+ <containment>
+ <parent>
+ <hasClass name="SystemFunctions"/>
+ </parent>
+ <child>
+ <hasClass name="Licensing"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Cbu_to_TimingUnit2">
+ <containment>
+ <parent>
+ <hasClass name="Cbu"/>
+ </parent>
+ <child>
+ <hasClass name="TimingUnit2"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+</mim>
+
+</models>
+
diff --git a/lib/xmerl/test/xmerl_SUITE_data/eventp/CelloMOM.stub b/lib/xmerl/test/xmerl_SUITE_data/eventp/CelloMOM.stub
new file mode 100644
index 0000000000..754b1ecded
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/eventp/CelloMOM.stub
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!--
+ Document no: 1551-1/CSX10109
+ Revision: MOM-CELLO_4.3.1
+ Date: 12-17-2003
+ Author: Ake Pappila/Hsiang-Ling Teng
+
+ Generated from UML by uml2xml version 3.0 (based on DTD file rev. F)
+ Rational Rose model used: /vobs/cello/cma/cma_uml/CelloMOM.mdl
+-->
+
+<!DOCTYPE models SYSTEM "mp.dtd">
+
diff --git a/lib/xmerl/test/xmerl_SUITE_data/eventp/CelloMOM.xml b/lib/xmerl/test/xmerl_SUITE_data/eventp/CelloMOM.xml
new file mode 100644
index 0000000000..8f8cf54505
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/eventp/CelloMOM.xml
@@ -0,0 +1,30261 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!--
+ Document no: 1551-1/CSX10109
+ Revision: MOM-CELLO_4.3.1
+ Date: 12-17-2003
+ Author: Ake Pappila/Hsiang-Ling Teng
+
+ Generated from UML by uml2xml version 3.0 (based on DTD file rev. F)
+ Rational Rose model used: /vobs/cello/cma/cma_uml/CelloMOM.mdl
+-->
+
+<!DOCTYPE models SYSTEM "mp.dtd">
+
+<models>
+<mim name="MOM-CELLO_4.3.1-1" version="5" release="1">
+ <exception name="AttributeMissingException">
+ <description>Exception thrown when an attribute is missing during upgrade.</description>
+ </exception>
+
+ <exception name="EnableExistingProgramException">
+ <description>Exception thrown when enabling of existing programs fails.</description>
+ </exception>
+
+ <exception name="ExtraIdentifiersOfNonExistingLoadModulesException">
+ </exception>
+
+ <exception name="FileCopyException">
+ <description>Exception thrown when copying of files fails.</description>
+ </exception>
+
+ <exception name="FileNotExistException">
+ <description>Exception thrown when the specified file does not exist.</description>
+ </exception>
+
+ <exception name="FindAndReplaceException">
+ </exception>
+
+ <exception name="HeapPoolSettingsException">
+ <description>Exception thrown when the heap or pool setting is incorrect.</description>
+ </exception>
+
+ <exception name="AttributeValueOutOfRangeException">
+ <description>Exception thrown when an attribute value is out of range.</description>
+ </exception>
+
+ <exception name="CancelInstallRequestException">
+ <description>Exception thrown when a cancel install equest for some reason fails.</description>
+ </exception>
+
+ <exception name="ChecksumhandlerException">
+ <description>Exception thrown when the control of checksum for loadmodules has been rejaected due to 'null' recieved from resource layer.</description>
+ </exception>
+
+ <exception name="ClearAllPiuTypesReferencedByPlugInUnitException">
+ <description>Exception thrown when its not possible to clear all PiuTypes referenced by PlugInUnit.</description>
+ </exception>
+
+ <exception name="ConditionallyMandatoryAttributeOrElementMissingException">
+ <description>Exception thrown when an conditional mandatory attribute (or element) is missing.</description>
+ </exception>
+
+ <exception name="ConfigurationVersionMO_HandlerException">
+ <description>Exception thrown when the creation of a CV during upgrade fails.</description>
+ </exception>
+
+ <exception name="ControlFileDocumentHandlerException">
+ </exception>
+
+ <exception name="CreateLoadModuleException">
+ <description>Exception thrown when the creation of a load module fails.</description>
+ </exception>
+
+ <exception name="DisableExistingProgramsException">
+ <description>Exception thrown when disabling of existing programs for some reason fails.</description>
+ </exception>
+
+ <exception name="DocumentObjectProxyException">
+ </exception>
+
+ <exception name="ExplicitReplacementInInformationForRPUsException">
+ <description>Exception thrown when replacement of existing RPU information fails.</description>
+ </exception>
+
+ <exception name="InstallOfLoadModulesCancelledException">
+ <description>Exception thrown when the installation of Load Modules is cancelled.</description>
+ </exception>
+
+ <exception name="InstallOfLoadModulesPartlyExcecutedException">
+ <description>Exception thrown when the installment of Load Modules is only partly executed.</description>
+ </exception>
+
+ <exception name="InstallOfLoadModulesRejectedException">
+ <description>Exception thrown when the install of Load Modules is rejected.</description>
+ </exception>
+
+ <exception name="InstallRejectedFTP_ServerNotAccessibleException">
+ <description>Exception thrown when the install is rejected due to FTP server is not accessible.</description>
+ </exception>
+
+ <exception name="InstallRejectedGetLoadModuleFileException">
+ <description>Exception thrown when the install is rejected due to error when trying to retreive Load Module.</description>
+ </exception>
+
+ <exception name="InstallRejectedIP_AddressException">
+ <description>Exception thrown when install is rejected due to erronous IP address.</description>
+ </exception>
+
+ <exception name="InstallRejectedInsufficientDiskSpaceException">
+ <description>Exception thrown when the install is rejected due to insufficient disk space.</description>
+ </exception>
+
+ <exception name="InstallRejectedLoadListFileException">
+ </exception>
+
+ <exception name="InstallRequestException">
+ <description>Exception thrown when the installation of a Load Module fails.</description>
+ </exception>
+
+ <exception name="InsufficientDiskSpaceException">
+ <description>Exception thrown when the disk space is insufficient.</description>
+ </exception>
+
+ <exception name="JvmMO_HandlerException">
+ </exception>
+
+ <exception name="LoadModuleFIlePathLengthOutOfRangeException">
+ <description>Exception thrown when file path for the Load Module is out of length.</description>
+ </exception>
+
+ <exception name="LoadModuleMO_HandlerException">
+ </exception>
+
+ <exception name="ManagedElementDataMO_HandlerException">
+ </exception>
+
+ <exception name="MandatoryElementIsMissingException">
+ </exception>
+
+ <exception name="MergeControlFileException">
+ <description>Exception thrown when the merger of control files fails.</description>
+ </exception>
+
+ <exception name="PIU_MO_HandlerException">
+ </exception>
+
+ <exception name="ParseException">
+ </exception>
+
+ <exception name="ParserFactoryException">
+ </exception>
+
+ <exception name="PiuTypeDefinitionMissingInUpgradeControlFileException">
+ <description>Exception thrown when PiuType definitions is missing in the UCF file.</description>
+ </exception>
+
+ <exception name="PiuTypeMO_HandlerException">
+ </exception>
+
+ <exception name="ProductNumberAndRevisionAlreadyInUseException">
+ <description>Exception thrown when the product number and revision is already used.</description>
+ </exception>
+
+ <exception name="ProgramConfigurationException">
+ </exception>
+
+ <exception name="ReconfigureProgramsException">
+ <description>Exception thrown when reconfiguration of programs fails.</description>
+ </exception>
+
+ <exception name="ReferencedElementMissingException">
+ <description>Exception thrown when the referenced element is missing.</description>
+ </exception>
+
+ <exception name="RepertoireMO_HandlerException">
+ </exception>
+
+ <exception name="ReplaceConfigSupportMOsOpException">
+ </exception>
+
+ <exception name="ReserveLoadModulesException">
+ <description>Exception thrown when reserving a Load Module fails.</description>
+ </exception>
+
+ <exception name="SelectiveInstallFailureException">
+ <description>Exception thrown when a selective install fails.</description>
+ </exception>
+
+ <exception name="SlotMO_HandlerException">
+ </exception>
+
+ <exception name="SwAllocationMO_HandlerException">
+ </exception>
+
+ <exception name="UnexpectedAttributeException">
+ <description>Exception thrown when an unexpected attribute occurs at upgrade.</description>
+ </exception>
+
+ <exception name="UnexpectedAttributeFormatException">
+ <description>Exception thrown when an unexpected format of the attribute occurs.</description>
+ </exception>
+
+ <exception name="UnexpectedElementException">
+ <description>Exception thrown when </description>
+ </exception>
+
+ <exception name="UpgradeControlFileDataException">
+ </exception>
+
+ <exception name="UpgradeControlFileNotFoundException">
+ </exception>
+
+ <exception name="UpgradeControlFileParserException">
+ </exception>
+
+ <exception name="UpgradePackageDeleteException">
+ <description>Exception thrown when its not possible to delete the upgrade package.</description>
+ </exception>
+
+ <exception name="UpgradePackageDeleteNotAllowedException">
+ <description>Exception thrown when its not allowed to delete the upgrade package.</description>
+ </exception>
+
+ <exception name="UpgradePackageDoesNotExistException">
+ <description>Exception thrown when the specified upgrade package does not exist.</description>
+ </exception>
+
+ <exception name="UpgradePackageFileSystemErrorException">
+ <description>Exception thrown when an error in the file system occurs.</description>
+ </exception>
+
+ <exception name="UpgradeRejectedException">
+ <description>Exception thrown when the upgrade is rejected.</description>
+ </exception>
+
+ <exception name="ValidateException">
+ </exception>
+
+ <exception name="VerifyChecksumException">
+ <description>Exception thrown when the checksum is incorrect.</description>
+ </exception>
+
+ <exception name="VerifyCreationOfCVsException">
+ <description>Exception thrown when its not possible to verify the creation of CV's.</description>
+ </exception>
+
+ <exception name="VerifyOperationalPIUsException">
+ </exception>
+
+ <exception name="VerifyRejectedException">
+ </exception>
+
+ <exception name="VerifyRequestException">
+ </exception>
+
+ <exception name="VerifySupportedPIUsException">
+ </exception>
+
+ <exception name="VerifyUpgradeHandlerException">
+ </exception>
+
+ <exception name="VerifyUpgradeWindowException">
+ </exception>
+
+ <exception name="UpgradeLogFileNotAccessibleException">
+ <description>The upgrade trace log file is not accessible i.e. the log file exists but it is not possible to access it with write permission.</description>
+ </exception>
+
+ <exception name="UpgradeControlFileException">
+ <description>The file parser has found that the UpgradeControlFile is incorrect.</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="UpgradeNotPossibleException">
+ <description>Before an upgrade is started it was found that the upgrade can not take place. A possible reason is that the upgrade package that is running in the node is not in the upgrade window of this upgrade package. </description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="UpgradeLogFileNotInUseException">
+ <description>The upgrade trace output is currently not directed to a file.
+
+This is a property that can be changed in the trace property file (Trace_01.prop).
+</description>
+ </exception>
+
+ <enum name="UpgradePackageState">
+ <enumMember name="NOT_INSTALLED">
+ <description>The upgrade package is not installed.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="INSTALL_COMPLETED">
+ <description>The upgrade package is completely installed.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="UPGRADE_EXECUTING">
+ <description>Upgrade is executing. </description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="AWAITING_CONFIRMATION">
+ <description>The execution of upgrade needs confirmation before it proceeds.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="ONLY_DELETEABLE">
+ <description>In this state an Upgrade Package can only be deleted. Its actions, when invoked, will throw the exception ActionNotAllowed. </description>
+ <value>4</value>
+ </enumMember>
+ <enumMember name="INSTALL_EXECUTING">
+ <description>Installation of the upgrade package is executing.</description>
+ <value>5</value>
+ </enumMember>
+ <enumMember name="INSTALL_NOT_COMPLETED">
+ <description>The upgrade package is not completely installed i.e. parts of it has been installed. </description>
+ <value>6</value>
+ </enumMember>
+ <enumMember name="UPGRADE_COMPLETED">
+ <description>The upgrade has been successfully executed.</description>
+ <value>7</value>
+ </enumMember>
+ </enum>
+
+ <enum name="UpgradeProgressInformation">
+ <enumMember name="IDLE">
+ <description>No action is in progress. </description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="DOWNLOADING_FILES">
+ <description>Downloading of files (load modules) in progress.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="SAVING_CV">
+ <description>Saving a Configuration Version.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="RECONFIGURING_MOS">
+ <description>Operation ReplaceConfigSupportMOs detected in upgrade.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="INITIATING_LOADER_INFO">
+ <description>Trigger Initiate detected in upgrade sequence.</description>
+ <value>4</value>
+ </enumMember>
+ <enumMember name="PRELOADING">
+ <description>Trigger Preload detected in upgrade sequence.</description>
+ <value>5</value>
+ </enumMember>
+ <enumMember name="CONVERSION_OF_PERSISTENT_DATA">
+ <value>6</value>
+ </enumMember>
+ <enumMember name="APPLICATION_SPECIFIC_ACTION">
+ <description>'Unique trigger' for an application detected in upgrade sequence.</description>
+ <value>7</value>
+ </enumMember>
+ <enumMember name="SHUTDOWN_WAIT">
+ <value>8</value>
+ </enumMember>
+ <enumMember name="TAKING_NEW_SOFTWARE_INTO_SERVICE">
+ <value>9</value>
+ </enumMember>
+ <enumMember name="FINISH_AND_CLEANING_UP">
+ <description>The error handling is switched back to normal.</description>
+ <value>10</value>
+ </enumMember>
+ <enumMember name="RESTORING_SYSTEM_STATE">
+ <value>11</value>
+ </enumMember>
+ <enumMember name="EXECUTION_FAILED">
+ <description>Indicates that the execution of an install or an upgrade action has failed.</description>
+ <value>12</value>
+ </enumMember>
+ <enumMember name="CANCEL_OF_INSTALLATION_IS_EXECUTING">
+ <description>Indicates that cancellation of an ongoing installation is in progress.</description>
+ <value>13</value>
+ </enumMember>
+ <enumMember name="CANCEL_OF_INSTALLATION_FAILED">
+ <description>Indicates that the execution of a cancel install action failed.</description>
+ <value>14</value>
+ </enumMember>
+ <enumMember name="VERIFICATION_INITIATED">
+ <value>15</value>
+ </enumMember>
+ <enumMember name="VERIFYING_UPGRADE_FROM_VERSION">
+ <value>16</value>
+ </enumMember>
+ <enumMember name="VERIFYING_POSSIBLE_TO_CREATE_REQ_NO_CVS">
+ <value>17</value>
+ </enumMember>
+ <enumMember name="VERIFYING_PIUS_SUPPORTED">
+ <value>18</value>
+ </enumMember>
+ <enumMember name="VERIFYING_CHECKSUM_FOR_LM">
+ <value>19</value>
+ </enumMember>
+ <enumMember name="VERIFYING_PIUS_NOT_FAULTY">
+ <value>20</value>
+ </enumMember>
+ <enumMember name="VERIFICATION_FINISHED">
+ <value>21</value>
+ </enumMember>
+ <enumMember name="VERIFICATION_FAILED">
+ <value>22</value>
+ </enumMember>
+ </enum>
+
+ <enum name="InvokedAction">
+ <enumMember name="VERIFY_UPGRADE">
+ <description>The verifyUpgrade action has been invoked.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="UPGRADE">
+ <description>An upgrade action (one of the variants) has been invoked.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="INSTALL">
+ <description>An install action (one of the variants) has been invoked.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="CANCEL_INSTALL">
+ <description>The cancelInstall action has been invoked.</description>
+ <value>4</value>
+ </enumMember>
+ </enum>
+
+ <struct name="ActionResultData">
+ <structMember name="time">
+ <description>A timestamp.
+
+Format: "Date: 2003-04-24, Time: 20:52:11.182"</description>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </structMember>
+ <structMember name="typeOfInvokedAction">
+ <enumRef name="InvokedAction">
+ <defaultValue>VERIFY_UPGRADE</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="info">
+ <enumRef name="Information">
+ <defaultValue>EXECUTED</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="actionId">
+ <description>This id is used to link more than one result to one action</description>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="additionalInfo">
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </structMember>
+ </struct>
+
+ <enum name="Information">
+ <enumMember name="EXECUTED">
+ <description>The invoked action has been successfully executed without warnings.One of three possible main results of executed action.
+
+Value valid for type of invoked action:
+INSTALL
+CANCEL_INSTALL
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="UNSPECIFIED">
+ <description>A not specified error/ warning has been detected (see additional info for further details)
+
+Value valid for type of invoked action:
+INSTALL
+CANCEL_INSTALL
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="LM_CHECKSUM_VER_FAILED">
+ <description>A load module checksum verification has failed.
+
+Value valid for type of invoked action:
+INSTALL
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="NOT_ENOUGH_AVAIL_DISK_SPACE">
+ <description> There is not enough available disk space for the required number of new CVs (configuration versions) to be created automatically during an upgrade.
+
+Value valid for type of invoked action:
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="MAX_NO_CV_WILL_BE_EXCEEDED">
+ <description>The maximum number of allowed CVs (configuration versions) will be exceeded if the required number of new CVs is created automatically during an upgrade.
+
+Value valid for type of invoked action:
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>4</value>
+ </enumMember>
+ <enumMember name="UPGRADE_FROM_CURRENT_UP_NOT_ALLOWED">
+ <description>The Upgrade Window element in the Upgrade Control File does not specify the current Upgrade Package as a valid 'upgrade from' version.
+
+Value valid for type of invoked action:
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>5</value>
+ </enumMember>
+ <enumMember name="NON_SUPPORTED_PIU">
+ <description>A non supported Plug In Unit (PIU) has been detected i.e. the PIU in the node is not defined in the Upgrade Control File.
+This is not a fault that prevents an upgrade from being executed.
+
+Value valid for type of invoked action:
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>6</value>
+ </enumMember>
+ <enumMember name="FAULTY_PIU">
+ <description>A faulty Plug In Unit (PIU) has been detected.
+This is not a fault that prevents an upgrade from being executed.
+
+Value valid for type of invoked action:
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>7</value>
+ </enumMember>
+ <enumMember name="CREATION_OF_CV_FAILED">
+ <description>The auto-creation of an install CV failed.
+
+Value valid for type of invoked action:
+INSTALL
+</description>
+ <value>8</value>
+ </enumMember>
+ <enumMember name="ACTION_NOT_ALLOWED">
+ <description>The requested action is not allowed due to an other action already is in progress for an other UP MO.
+
+Value valid for type of invoked action:
+INSTALL
+CANCEL_INSTALL
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>9</value>
+ </enumMember>
+ <enumMember name="INSTALLATION_MANUALLY_CANCELLED">
+ <description>An ongoing installation has been cancelled (aborted) due to request from client.
+
+Value valid for type of invoked action:
+INSTALL</description>
+ <value>10</value>
+ </enumMember>
+ <enumMember name="FTP_SERVER_NOT_ACCESSIBLE">
+ <description>The FTP server to be used for downloads of load modules is not accessible.
+
+Value valid for type of invoked action:
+INSTALL</description>
+ <value>11</value>
+ </enumMember>
+ <enumMember name="INSUFFICIENT_DISK_SPACE_FOR_LOAD_MODULES">
+ <description>The required disk space for load modules to be installed is insufficient.
+
+Value valid for type of invoked action:
+INSTALL</description>
+ <value>12</value>
+ </enumMember>
+ <enumMember name="FTP_SERVER_IP_ADDRESS_ERROR">
+ <description>Error detected in the IP address of the FTP server.
+
+Value valid for type of invoked action:
+INSTALL</description>
+ <value>13</value>
+ </enumMember>
+ <enumMember name="DELTA_INSTALL_MERGE_ERROR">
+ <description>The install of the delta Upgrade Control File (UCF) failed i.e. the analysis of the delta UCF together with current active UP's UCF failed.
+
+Value valid for type of invoked action:
+INSTALL</description>
+ <value>14</value>
+ </enumMember>
+ <enumMember name="SELECTIVE_INSTALL_ERROR">
+ <description>Error detected during the selection phase of an install.
+
+Value valid for type of invoked action:
+INSTALL
+
+</description>
+ <value>15</value>
+ </enumMember>
+ <enumMember name="EXECUTION_FAILED">
+ <description>The execution of invoked action failed.One of three possible main results of executed action.
+
+Value valid for type of invoked action:
+INSTALL
+CANCEL_INSTALL
+VERIFY_UPGRADE
+UPGRADE</description>
+ <value>16</value>
+ </enumMember>
+ <enumMember name="EXECUTED_WITH_WARNINGS">
+ <description>The action has been successfully executed but with warnings.One of three possible main results of executed action.
+
+Value valid for type of invoked action:
+INSTALL
+CANCEL_INSTALL
+VERIFY_UPGRADE</description>
+ <value>17</value>
+ </enumMember>
+ </enum>
+
+ <exception name="FtpServerNotAccessibleException">
+ <description>Ftp server is not accessible. This may depend on erroneous IP address, username, password, or that the IP communication with the Ftp server is down, or that the Ftp server itself is malfunctioning. </description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="GetFileException">
+ <description>An error was encountered during FTP get file. A filePath in the upgradeControlFile may be inconsistent with a filepath on the Ftp server. </description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <struct name="PiuTypeProgramConfiguration">
+ <structMember name="tag">
+ <description>The tag is used as a reference between the PiuType MO and the Repertoire MO to find out how to create the program object under a PlugInUnit MO.</description>
+ <string/>
+ </structMember>
+ <structMember name="subParentLDN">
+ <description>Local distinguished name of the program parent from the PlugInUnit.
+
+Example:
+1. "Spu=1,Spm=2" (the program is to be created under: ...PlugInUnit=2,Spu=1,Spm=2")
+2. "" (empty string - the program is to be created directly under the PlugInUnit)</description>
+ <string/>
+ </structMember>
+ <structMember name="programMoTypeName">
+ <description>The name of the Program MO that will be created.</description>
+ <string/>
+ </structMember>
+ <structMember name="loadableProcessorName">
+ <description>The loadableProcessorName is a user friendly name of the processor.</description>
+ <string/>
+ </structMember>
+ </struct>
+
+ <struct name="RepertoireLoadModuleData">
+ <description>This structure contains load module data that belongs to a piu type.
+</description>
+ <structMember name="loadModuleDN">
+ <description>The distinguished name of the load module, which is needed and sufficient to convert the load module to a real object reference.</description>
+ <string/>
+ </structMember>
+ <structMember name="tag">
+ <description>The tag is used as a reference between the PiuType MO and the Repertoire MO to find out how to create the program object under a PlugInUnit MO.</description>
+ <string/>
+ </structMember>
+ </struct>
+
+ <struct name="ConfigurationVersionAttributes">
+ <structMember name="name">
+ <string>
+ </string>
+ </structMember>
+ <structMember name="identity">
+ <string>
+ </string>
+ </structMember>
+ <structMember name="type">
+ <string/>
+ </structMember>
+ <structMember name="upgradePackageId">
+ <string/>
+ </structMember>
+ <structMember name="operatorName">
+ <string>
+ </string>
+ </structMember>
+ <structMember name="operatorComment">
+ <string>
+ </string>
+ </structMember>
+ <structMember name="date">
+ <string/>
+ </structMember>
+ <structMember name="status">
+ <string/>
+ </structMember>
+ </struct>
+
+ <enum name="ConfigurationVersionType">
+ <enumMember name="standard">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="upgrade">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="minimal">
+ <value>2</value>
+ </enumMember>
+ <enumMember name="test">
+ <value>3</value>
+ </enumMember>
+ <enumMember name="autocreate">
+ <value>4</value>
+ </enumMember>
+ <enumMember name="other">
+ <value>5</value>
+ </enumMember>
+ </enum>
+
+ <enum name="LoadModuleLoaderType">
+ <enumMember name="OseLoader">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="SpmLoader">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="Jvm">
+ <value>2</value>
+ </enumMember>
+ <enumMember name="WebServer">
+ <value>3</value>
+ </enumMember>
+ <enumMember name="Other">
+ <value>99</value>
+ </enumMember>
+ <enumMember name="SpmFpgaLoader">
+ <value>4</value>
+ </enumMember>
+ <enumMember name="XpLoader">
+ <value>5</value>
+ </enumMember>
+ </enum>
+
+ <enum name="LoadModulePreLoadType">
+ <enumMember name="no">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="must">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="wish">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="RPUSwitchOverMode">
+ <description>This attribute can have the following values:
+
+AtPiuFault = Indicates the MP (where the normal RPU is configured) is faulty (HW error). This is the default value.
+
+AtPiuRestart = Indicates the MP (where the normal RPU is configured) is restarted.</description>
+ <enumMember name="AtPiuFault">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="AtPiuRestart">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="RPUNormalisationMode">
+ <description>This enumeration can have the following values:
+
+Manual = Indicates that no normalisation is performed by cello until the operator issues a "switch" action.
+
+Automatic = Indicates that Cello performs the normalisation automatically, after the failed RPU is available again. This is the default value.</description>
+ <enumMember name="Manual">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="Automatic">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="RPUReplicationMode">
+ <description>This enumaration contains the following values:
+
+Always = Data replication is always performed. This overrides the characteristics set on the each container ( that is associated with the RPU ).
+
+Never = Data replication is never performed. This overrides the characteristics set on the each container ( that is associated with the RPU ).
+
+AtShutdown = Each time the RSH (which handles the RPU) is shut down, a complete snapshot is taken and replicated to the other MP, if necessary. Otherwise, the replication is performed according to the characteristics set on each container ( that is associated with the RPU ).
+
+ApplControlled = The data replication is made according to the characteristics set on each container ( that is associated with the RPU ). This is the default value.</description>
+ <enumMember name="Always">
+ <description>Always = Data replication is always performed. This overrides the characteristics set on the each container ( that is associated with the RPU ).</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="Never">
+ <description>Data replication is never performed. This overrides the characteristics set on the each container ( that is associated with the RPU ).</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="AtShutdown">
+ <description>AtShutdown = Each time the RSH (which handles the RPU) is shut down, a complete snapshot is taken and replicated to the other MP, if necessary. Otherwise, the replication is performed according to the characteristics set on each container ( that is associated with the RPU ).</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="ApplControlled">
+ <description>ApplControlled = The data replication is made according to the characteristics set on each container ( that is associated with the RPU ). This is the default value.</description>
+ <value>4</value>
+ </enumMember>
+ </enum>
+
+ <enum name="RPUOperationalMode">
+ <description>This enumeration contains the following values:
+
+AsConfigured = The RSHs runs as the RPU is configured.
+SwitchOver = The RSHs has been switched over.
+Unavailable = No RSHs, that uses this RPU, are running.</description>
+ <enumMember name="AsConfigured">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="SwitchedOver">
+ <value>2</value>
+ </enumMember>
+ <enumMember name="Unavailable">
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <struct name="PiuTypeMOConfiguration">
+ <structMember name="subParentLDN">
+ <string/>
+ </structMember>
+ <structMember name="moTypeName">
+ <string/>
+ </structMember>
+ <structMember name="identity">
+ <string/>
+ </structMember>
+ </struct>
+
+ <struct name="AirFlowData">
+ <description>Control value for the fan unit. Needed by cooling function.
+</description>
+ <structMember name="normalLowTempAirFlow">
+ <description>Control value for the fan unit running in normal autonomous mode.
+This parameter is the subrack/fanunit airflow value that is required to achieve sufficient cooling at 20 degree
+centigrade or lower ambient temperature of the most demanding plug in unit (PIU) in the subrack. This airflow value
+shall be sufficient (but not unnecessarily large) to secure that no "normal overtemp" fault indication is issued.
+Default values = 250 m3/h. (value &gt;=0)
+</description>
+ <float>
+ <defaultValue>250</defaultValue>
+ </float>
+ </structMember>
+ <structMember name="normalHighTempAirFlow">
+ <description>Control value for the fan unit running in normal autonomous mode. This parameter is the subrack/fanunit airflow
+value that is required to achieve sufficient cooling at 50 degree centigrade ambient temperature of the most
+demanding plug in unit (PIU) in the subrack. This airflow value shall be sufficient (but not unnecessarily large) to
+secure that no "normal overtemp" fault indication is issued.
+Default values = 400 m3/h. (value &gt;=0)</description>
+ <float>
+ <defaultValue>400</defaultValue>
+ </float>
+ </structMember>
+ <structMember name="noiseReducedLowTempAirFlow">
+ <description>Control value for the fan unit running in noise reduction mode. This parameter is the subrack/fanunit airflow value
+that is required to achieve sufficient cooling at 20 degree centigrade or lower ambient temperature of the most
+demanding plug in unit (PIU) in the subrack. This airflow value shall be sufficient (but not unnecessarily large) to
+secure that no "exceptional overtemp" fault indication is issued
+Default values = 250 m3/h. (value &gt;=0)</description>
+ <float>
+ <defaultValue>250</defaultValue>
+ </float>
+ </structMember>
+ <structMember name="noiseReducedHighTempAirFlow">
+ <description>Control value for the fan unit running in noise reduction mode. This parameter is the subrack/fanunit airflow value
+that is required to achieve sufficient cooling at 50 degree centigrade ambient temperature of the most demanding
+plug in unit (PIU) in the subrack. This airflow value shall be sufficient (but not unnecessarily large) to secure
+that no "exceptional overtemp" fault indication is issued.
+Default values = 400 m3/h. (value &gt;=0)</description>
+ <float>
+ <defaultValue>400</defaultValue>
+ </float>
+ </structMember>
+ </struct>
+
+ <exception name="IpAddressException">
+ <description>Erroneous Ip Address Format</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="AueFailureException">
+ <description>An application upgrade engine has reported a failure. </description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="ActionNotAllowedException">
+ <description>The action is not allowed, the UpgradePackage MO is in wrong state.
+
+For example if you try 'upgrade()' before an 'install()' or 'forcedInstall()' has been done.</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="CVFileSystemErrorException">
+ <description>Exception thrown upon file system Error.</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="CVDBErrorException">
+ <description>Data Base Error Exception (error when creating database backup).</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="CVLLPErrorException">
+ <description>LLP Error Exception (error when creating ARMAMENT and LLP.LMID files).</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="CVAlreadyExistsException">
+ <description>The configuration version already exists (e.g. message at create).</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="CVDoesNotExistsException">
+ <description>The configuration version does not exist (e.g. message at setCVAsStartable).</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="CVDeleteNotAllowedException">
+ <description>It is not allowed to delete the configuration version, because it is in use (used as startable or in rollback list).</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="CVInvalidCVException">
+ <description>The configuration version is not valid (due to missing files).
+
+</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="CVFormatErrorException">
+ <description>Format Error in given configuration version name.
+
+The following characters are allowed within the name:
+[0-9], [A-Z], [a-z] and '&amp;','%',':','.','_', '-'
+
+Note! For comment and operatorName spaces (' ') are also allowed within the strings.</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="CVErrorException">
+ <description>Error Exception.</description>
+ <exceptionParameter name="message">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="InstallException">
+ <description>Indicates that an error in an installation has occurred.</description>
+ <exceptionParameter name="install">
+ <description>The message of the exception.</description>
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="LogActivationException">
+ <description>Exception thrown when a database error occurs.</description>
+ </exception>
+
+ <exception name="InvalidDriveNameException">
+ <description>Exception thrown when an invalid drive name is specified or when a data base error occurs.</description>
+ </exception>
+
+ <exception name="VerifyUpgradeException">
+ </exception>
+
+ <exception name="CVActivityLogFilePathErrorException">
+ <description>Exception thrown when the log file path is wrong.</description>
+ </exception>
+
+ <exception name="CV_MaxNumberOfInstancesException">
+ <description>Exception thrown when max number of CV's in the system has been reached.</description>
+ </exception>
+
+ <exception name="Aal2PathIdNotUniqueException">
+ <exceptionParameter name="message">
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="PathAlreadyRegisteredException">
+ <exceptionParameter name="message">
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="NotInGroupException">
+ </exception>
+
+ <exception name="InvalidReferenceException">
+ </exception>
+
+ <exception name="InvalidPriorityException">
+ <description>Indicates an invalid priority level, i.e. the priority in question is out of the defined range.</description>
+ <exceptionParameter name="invalidPriority">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <struct name="QoSProfileClassA">
+ <description>This struct contains the values applicable for QoS Class A.</description>
+ <structMember name="boundOnProbOfDelay">
+ <description>Represents the upper bound on the probability that the delay in the node exceeds the delay limit given by the attribute "boundOnNodeDelay".
+
+Unit is 1/1000000000.
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>1000000000</max>
+ </range>
+ <defaultValue>500000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="boundOnProbOfLoss">
+ <description>Represents the upper bound of the cell loss probability in the current node.
+
+Unit is 1/1000000000.</description>
+ <long>
+ <range>
+ <min>0</min> <max>1000000000</max>
+ </range>
+ <defaultValue>500000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="boundOnNodeDelay">
+ <description>The upper bound on the delay (delay=queueing and serving of Aal2 packets in an Aal2 mux + delay on ATM layer) through the current node.
+Unit is micro seconds.</description>
+ <long>
+ <range>
+ <min>0</min> <max>10000</max>
+ </range>
+ <defaultValue>5000</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <struct name="QoSProfileClassB">
+ <description>This struct contains the values applicable for QoS Class B.</description>
+ <structMember name="boundOnProbOfDelay">
+ <description>Represents the upper bound on the probability that the delay in the node exceeds the delay limit given by the attribute "boundOnNodeDelay".
+
+Unit is 1/1000000000.</description>
+ <long>
+ <range>
+ <min>0</min> <max>1000000000</max>
+ </range>
+ <defaultValue>500000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="boundOnProbOfLoss">
+ <description>Represents the upper bound of the cell loss probability in the current node.
+
+Unit is 1/1000000000.
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>1000000000</max>
+ </range>
+ <defaultValue>500000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="boundOnNodeDelay">
+ <description>The upper bound on the delay (delay=queueing and serving of Aal2 packets in an Aal2 mux + delay on ATM layer) through the current node.
+Unit is micro seconds.</description>
+ <long>
+ <range>
+ <min>0</min> <max>20000</max>
+ </range>
+ <defaultValue>15000</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <struct name="QoSProfileClassC">
+ <description>This struct contains the values applicable for QoS Class C.
+
+NOTE: The attribute 'boundONodeDelay' is not applicable for QoS Class C so setting of this attribute will have no effect.</description>
+ <structMember name="boundOnProbOfDelay">
+ <description>Represents the upper bound on the probability that the delay in the node exceeds the delay limit given by the attribute "boundOnNodeDelay".
+
+Unit is 1/1000000000.</description>
+ <long>
+ <range>
+ <min>0</min> <max>1000000000</max>
+ </range>
+ <defaultValue>1000000000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="boundOnProbOfLoss">
+ <description>Represents the upper bound of the cell loss probability in the current node.
+
+Unit is 1/1000000000.
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>1000000000</max>
+ </range>
+ <defaultValue>1000000000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="boundOnNodeDelay">
+ <description>The upper bound on the delay (delay=queueing and serving of Aal2 packets in an Aal2 mux + delay on ATM layer) through the current node.
+Unit is micro seconds.</description>
+ <long>
+ <defaultValue>25000</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <struct name="QoSProfileClassD">
+ <description>This struct contains the values applicable for QoS Class D.
+
+NOTE: The attribute 'boundONodeDelay' is not applicable for QoS Class D so setting of this attribute will have no effect.</description>
+ <structMember name="boundOnProbOfDelay">
+ <description>Represents the upper bound on the probability that the delay in the node exceeds the delay limit given by the attribute "boundOnNodeDelay".
+
+Unit is 1/1000000000.</description>
+ <long>
+ <range>
+ <min>1</min> <max>1000000000</max>
+ </range>
+ <defaultValue>1000000000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="boundOnProbOfLoss">
+ <description>Represents the upper bound of the cell loss probability in the current node.
+
+Unit is 1/1000000000.</description>
+ <long>
+ <range>
+ <min>0</min> <max>1000000000</max>
+ </range>
+ <defaultValue>1000000000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="boundOnNodeDelay">
+ <description>The upper bound on the delay (delay=queueing and serving of Aal2 packets in an Aal2 mux + delay on ATM layer) through the current node.
+Unit is micro seconds.</description>
+ <long>
+ <defaultValue>50000</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <enum name="SupportedQoSClasses">
+ <enumMember name="NO_CLASS_SUPPORTED">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="CLASS_A">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="CLASS_B">
+ <value>2</value>
+ </enumMember>
+ <enumMember name="CLASS_A_B">
+ <value>3</value>
+ </enumMember>
+ <enumMember name="CLASS_C">
+ <value>4</value>
+ </enumMember>
+ <enumMember name="CLASS_A_C">
+ <value>5</value>
+ </enumMember>
+ <enumMember name="CLASS_B_C">
+ <value>6</value>
+ </enumMember>
+ <enumMember name="CLASS_A_B_C">
+ <value>7</value>
+ </enumMember>
+ <enumMember name="CLASS_D">
+ <value>8</value>
+ </enumMember>
+ <enumMember name="CLASS_A_D">
+ <value>9</value>
+ </enumMember>
+ <enumMember name="CLASS_B_D">
+ <value>10</value>
+ </enumMember>
+ <enumMember name="CLASS_A_B_D">
+ <value>11</value>
+ </enumMember>
+ <enumMember name="CLASS_C_D">
+ <value>12</value>
+ </enumMember>
+ <enumMember name="CLASS_A_C_D">
+ <value>13</value>
+ </enumMember>
+ <enumMember name="CLASS_B_C_D">
+ <value>14</value>
+ </enumMember>
+ <enumMember name="CLASS_A_B_C_D">
+ <value>15</value>
+ </enumMember>
+ </enum>
+
+ <exception name="IsReservedCanNotSetPathIdException">
+ <description>Exception thrown when an attempt is made to set or change the aal2PathId of an Aal2PathVccTp while its reserved by an other Aal2PathGrp</description>
+ </exception>
+
+ <exception name="IsUnlockedCanNotSetPathOwnerException">
+ <description>Exception thrown when an attempt is made to set or change the aal2PathOwner of an Aal2PathVccTp while its not LOCKED.</description>
+ </exception>
+
+ <enum name="SlotState">
+ <description>
+</description>
+ <enumMember name="free">
+ <description>It is free to be pre-configured with a new PlugInUnit. </description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="used">
+ <description>A PlugInUnit is inserted in the slot or the slot is pre-configured with a PlugInUnit.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="coveredByPiu">
+ <description>Currently not supported.</description>
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <struct name="AdminProductData">
+ <structMember name="productNumber">
+ <description>The product number of the product or document.
+
+Examples: ABC 101 001, CXC 123 456, 1/BFD 101 999
+
+In the case of UpgradePackage this is the document number of the upgrade package.</description>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>24</max>
+ </lengthRange>
+ </string>
+ </structMember>
+ <structMember name="productRevision">
+ <description>The revision of the product number.
+
+Examples: R1, r1a, R1A02, P7B</description>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>7</max>
+ </lengthRange>
+ </string>
+ </structMember>
+ <structMember name="productName">
+ <description>A user-friendly name of the product.</description>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>12</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </structMember>
+ <structMember name="productInfo">
+ <description>User-friendly information about the product.</description>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </structMember>
+ <structMember name="productionDate">
+ <description>The production date can be represented in two ways.
+
+1) The preferable syntax is a four-digit representation of the year, and a two-digit representation of the month and a two-digit representation of the day. The numbers of characters in this case, is eight.
+Example:
+19991231
+
+2) The date can also consist of two digits for the year, followed by the letter W for week and two digits for the number of week. The numbers of characters in this case, is five.
+Example:
+99W12
+</description>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>8</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </structMember>
+ </struct>
+
+ <struct name="OperProductData">
+ <structMember name="productName">
+ <description>A user-friendly name of the product.
+
+
+
+</description>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>12</max>
+ </lengthRange>
+ </string>
+ </structMember>
+ <structMember name="productNumber">
+ <description>Unique identity for each product, which is constituted by the Ericsson product number (ABC number).
+
+The maximum number of characters for a product number is 24 including 2 slashes, 2 spaces and 2 characters for origination notation.
+
+Example of product number:
+ABC 101 001
+(1/ABC 101 01/1234)
+123/ABCDE 101 1010/12345
+
+.</description>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>24</max>
+ </lengthRange>
+ </string>
+ </structMember>
+ <structMember name="productRevision">
+ <description>Indicates the revision state of the product. It consists of a letter R or P, one or two digits and/or one or two letters. The maximum number of characters is four inclusive R or P.
+Example: R1A, R1A02, P7B
+
+A suffix may be added to the revision state. The suffix may consists of one or two digits or one letter.
+
+
+</description>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>7</max>
+ </lengthRange>
+ </string>
+ </structMember>
+ <structMember name="serialNumber">
+ <description>The serial number consists of 13 alphanumerical characters grouped as 6 plus 7 characters. The first 6 characters are to be used for factory codes and the last 7 characters are used for an individual number or batch number.
+
+</description>
+ <string/>
+ </structMember>
+ <structMember name="productionDate">
+ <description>The production date can be represented in two ways.
+
+1) The preferable syntax is a four-digit representation of the year, and a two-digit representation of the month and a two-digit representation of the day. The numbers of characters in this case, is eight.
+Example:
+19991231
+
+2) The date can also consist of two digits for the year, followed by the letter W for week and two digits for the number of week. The numbers of characters in this case, is five.
+Example:
+99W12
+
+</description>
+ <string>
+ <lengthRange>
+ <min>5</min> <max>8</max>
+ </lengthRange>
+ </string>
+ </structMember>
+ </struct>
+
+ <enum name="LoadClass">
+ <description>Defines the phase in the load and start sequence.
+</description>
+ <enumMember name="coreOs">
+ <value>10</value>
+ </enumMember>
+ <enumMember name="coreDevice">
+ <value>50</value>
+ </enumMember>
+ <enumMember name="loadListProvider">
+ <value>100</value>
+ </enumMember>
+ <enumMember name="coreEarly">
+ <value>200</value>
+ </enumMember>
+ <enumMember name="coreLate">
+ <value>300</value>
+ </enumMember>
+ <enumMember name="networkAndConnectionHandling">
+ <value>400</value>
+ </enumMember>
+ <enumMember name="application">
+ <value>500</value>
+ </enumMember>
+ <enumMember name="upgrade">
+ <value>600</value>
+ </enumMember>
+ </enum>
+
+ <enum name="StartState">
+ <enumMember name="disabled">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="enabled">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="SubrackType">
+ <enumMember name="hub">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="device">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="PiuRole">
+ <enumMember name="mp">
+ <description>The board is a Main processor.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="bp">
+ <description>The board is a device board.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="others">
+ <description>The board is not a Main processor or a device board. </description>
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <enum name="RestartCause">
+ <description>This attribute indicates the restart cause of plugInUnit. The defined values are:
+1. piuRestartError: restart because of error.
+2. piuRestartUpgrade: restart because of system upgrade.
+</description>
+ <enumMember name="piuRestartUpgrade">
+ <description>This attributes indicates that the Piu restart cause is upgrade.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="piuRestartError">
+ <description>This attributes indicates that the Piu restart cause is error.</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="FanState">
+ <description>The Fan can be in one of three controlling state:
+- standalone: not manageable, full speed fans
+- autonomous: manageable, air-flow control
+- noiseReduced: time-limited low speed fan</description>
+ <enumMember name="standalone">
+ <description>It's running on itself, not manageable.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="autonomous">
+ <description>Manageable state.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="noiseReduced">
+ <description>Temporary state with reduced cooling.</description>
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <enum name="SeqRestarts">
+ <enumMember name="RESTARTS_WITH_NO_LIMITS">
+ <description>This attributes indicates unlimited restarts and no faulty marking of the PIU. Used for critical PIU's such as TUBs, SCBs and some ET-boards.
+</description>
+ <value>-1</value>
+ </enumMember>
+ <enumMember name="RESTARTS_WITH_WARM">
+ <description>This attributes indicates the following sequential restarts:
+-warm
+-refresh
+-cold
+-cold with fault marked (not loaded). Alarm sent.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="RESTARTS_WITH_REFRESH">
+ <description>This attributes indicates the following sequential restarts:
+-refresh
+-cold
+-cold with fault marked (not loaded). Alarm sent.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="RESTARTS_WITH_COLD">
+ <description>This attributes indicates the following sequential restarts:
+-cold
+-cold with fault marked (not loaded). Alarm sent.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="RESTARTS_WITH_FAULT_MARKED">
+ <description>This attributes indicates the following sequential restarts:
+-cold with fault marked (not loaded). Alarm sent.</description>
+ <value>0</value>
+ </enumMember>
+ </enum>
+
+ <exception name="RepertoireNotFoundException">
+ <description>This class is an exception class thrown when a equipment specific error occurs.
+</description>
+ </exception>
+
+ <exception name="SwAllocationNotFoundException">
+ <description>This class is an exception class thrown when a equipment specific error occurs.
+</description>
+ </exception>
+
+ <exception name="WebServerPathConfigurationException">
+ <description>This class is an exception class thrown when failed to configure the webserver root path
+</description>
+ </exception>
+
+ <exception name="FroLocationFailedException">
+ </exception>
+
+ <exception name="FroShutdownException">
+ </exception>
+
+ <exception name="NotUniqueLineNoException">
+ </exception>
+
+ <exception name="WrongPhysPathTermTypeException">
+ </exception>
+
+ <enum name="OperState">
+ <enumMember name="disabled">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="enabled">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="AdmState">
+ <enumMember name="locked">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="unlocked">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="shuttingDown">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <exception name="OccupiedException">
+ </exception>
+
+ <exception name="NotReservedException">
+ </exception>
+
+ <exception name="NotSupportedException">
+ </exception>
+
+ <enum name="SilPortState">
+ <description>Indication of Switch Internal Link port status.</description>
+ <enumMember name="portActive">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="portPassive">
+ <value>2</value>
+ </enumMember>
+ <enumMember name="portNotConnected">
+ <value>3</value>
+ </enumMember>
+ <enumMember name="portLocked">
+ <value>4</value>
+ </enumMember>
+ <enumMember name="portNotInstalled">
+ <value>5</value>
+ </enumMember>
+ </enum>
+
+ <exception name="InvalidIndexException">
+ <description>Index specified is invalid, i.e. it is out of the range of valid indices.</description>
+ <exceptionParameter name="invalidIndex">
+ <description>The exception message.</description>
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="TransactionException">
+ </exception>
+
+ <exception name="UndeletableMoException">
+ <description>Exception thrown when MO is not possible to delete.</description>
+ </exception>
+
+ <exception name="FroNotAccessibleException">
+ <description>Exception that is thrown when a FRO (Facade Resource Object in the resource layer) cannot be accessed.</description>
+ </exception>
+
+ <exception name="FroRequestFailedException">
+ <description>Exception that is thrown when the result of a request to a FRO (Facade Resource Object in the resource layer) is not ok.</description>
+ </exception>
+
+ <exception name="MoReservedByOtherUserException">
+ <description>Exception thrown when the MO is already reserved by another user (MO).</description>
+ </exception>
+
+ <exception name="MoHasChildrenException">
+ <description>Exception class thrown when an MO is requested to be deleted, but the MO has children, which must be deleted first.</description>
+ </exception>
+
+ <exception name="MoReservedNotDeletableException">
+ <description>Exception thrown when trying to delete an MO that is reserved by another MO (user).</description>
+ </exception>
+
+ <exception name="MaxNumberExceededException">
+ <description>Exception thrown when the maximum number of childrens for an MO is exceeded.</description>
+ </exception>
+
+ <exception name="AttrValueNotUniqueException">
+ <description>Exception thrown when a value of an attribute is not unique.</description>
+ </exception>
+
+ <exception name="EquipException">
+ </exception>
+
+ <exception name="IpFormatException">
+ </exception>
+
+ <exception name="IpException">
+ </exception>
+
+ <exception name="TransactionRequiredException">
+ <description>Exception class thrown when an MO is accessed outside a transaction but the access method requires a transaction.</description>
+ </exception>
+
+ <exception name="ValueOutOfRangeException">
+ <description>Exception thrown when an MO attribute is requested to be set, but the requested value is not accepted.</description>
+ </exception>
+
+ <exception name="WrongAttributeTypeException">
+ <description>Exception thrown when an MO attribute is requested to be set, but the requested value is of the wrong type. </description>
+ </exception>
+
+ <exception name="NotHandledAttributeTypeException">
+ <description>Exception class thrown when an attribute of not handled type is requested. </description>
+ </exception>
+
+ <exception name="NoSuchFieldException">
+ <description>Exception class thrown when a Struct is accessed but the reqested Struct element is not found. </description>
+ </exception>
+
+ <exception name="MoCanNotBeCreatedException">
+ </exception>
+
+ <exception name="NoSuchAttributeException">
+ <description>Exception thrown when an MO attribute is requested to be accessed but the access
+method for the is not defined (the attribute can not be accessed)</description>
+ </exception>
+
+ <exception name="MoCardinalityViolationException">
+ <description>Exception class thrown when the creation of an MO fails due to child - parent
+cardinality violation. The cardinality is specified in the MIM. </description>
+ </exception>
+
+ <exception name="IllegalParentException">
+ <description>Exception thrown when the parent of the MO is of the wrong type.</description>
+ </exception>
+
+ <exception name="AttrNotSettableAtCreateException">
+ <description>Exception thrown when a create is ordered with
+attribute values that are not settable at create.</description>
+ </exception>
+
+ <exception name="AttrMissingAtCreateException">
+ <description>Exception thrown when an attribute that is mandatory at create is missing.</description>
+ </exception>
+
+ <exception name="MoNameAlreadyTakenException">
+ <description>Exception thrown when an MO is created and the distinguished name of the MO is already in use.</description>
+ </exception>
+
+ <exception name="IllegalArgumentTypeException">
+ <description>Exception thrown if the argument supplied is of the wrong type, for example in an action.</description>
+ </exception>
+
+ <exception name="IllegalAttributeValueException">
+ <description>Exception thrown if the value of the attribute is not valid.</description>
+ </exception>
+
+ <enum name="RestartRank">
+ <enumMember name="RESTART_WARM">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="RESTART_REFRESH">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="RESTART_COLD">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="AvailabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <enumMember name="IN_TEST">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="FAILED">
+ <value>2</value>
+ </enumMember>
+ <enumMember name="POWER_OFF">
+ <value>4</value>
+ </enumMember>
+ <enumMember name="OFF_LINE">
+ <value>8</value>
+ </enumMember>
+ <enumMember name="OFF_DUTY">
+ <value>16</value>
+ </enumMember>
+ <enumMember name="DEGRADED">
+ <value>64</value>
+ </enumMember>
+ <enumMember name="NOT_INSTALLED">
+ <value>128</value>
+ </enumMember>
+ <enumMember name="LOG_FULL">
+ <value>256</value>
+ </enumMember>
+ <enumMember name="DEPENDENCY_LOCKED">
+ <value>544</value>
+ </enumMember>
+ <enumMember name="DEPENDENCY_FAILED">
+ <value>1056</value>
+ </enumMember>
+ <enumMember name="DEPENDENCY_SHUTTINGDOWN">
+ <value>2080</value>
+ </enumMember>
+ <enumMember name="NO_STATUS">
+ <value>0</value>
+ </enumMember>
+ </enum>
+
+ <exception name="InvalidMoReferenceException">
+ <description>Exception thrown when the submitted MO reference is invalid.</description>
+ </exception>
+
+ <exception name="FroNotLockedException">
+ <description>Exception thrown when a fRo cannot be accessed.</description>
+ </exception>
+
+ <exception name="GeneralErrorException">
+ <description>Exception thrown by an MO when there is a general error.</description>
+ </exception>
+
+ <exception name="IdentityNotAllowedException">
+ <description>Exception thrown when an identity (LDN) specified at create is not allowed.</description>
+ </exception>
+
+ <exception name="IllegalMoTypeException">
+ <description>Exception thrown when a reference to an MO is of a unexpected/wrong MO type.</description>
+ </exception>
+
+ <exception name="ImpossibleCollectAtmInfoException">
+ <description>Exception thrown when gathering of ATM info fails.</description>
+ </exception>
+
+ <exception name="MoCanNotBeDeletedException">
+ <description>Exception thrown when its not possible to delete an MO.</description>
+ </exception>
+
+ <exception name="MoNotPossibleToReserveException">
+ <description>Exception thrown when by an MO if its not possible to reserve the MO.</description>
+ </exception>
+
+ <exception name="MoNotReservedByUserException">
+ <description>Exception thrown when a user tries to release an MO that is not reserved by this user.</description>
+ </exception>
+
+ <exception name="NoDiskException">
+ <description>Exception thrown when there is no hard disk.</description>
+ </exception>
+
+ <exception name="RemovalFailedException">
+ <description>Exception thrown when an element cannot be removed from a sequence.</description>
+ </exception>
+
+ <exception name="RestartRejectedException">
+ <description>Exception thrown when restart of the PlugInUnit is not allowed.</description>
+ </exception>
+
+ <enum name="SyncMode">
+ <description>The Sync Mode Operation of the node.</description>
+ <enumMember name="NOT_USED">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="CDMA">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="WCDMA">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <struct name="Mtp2ProfileDataAnsi">
+ <structMember name="suermT">
+ <description>SUERM parameter T.
+Measured in SU units.</description>
+ <long>
+ <range>
+ <min>1</min> <max>511</max>
+ </range>
+ <defaultValue>64</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="suermD">
+ <description>SUREM parameter D.
+Measurement units are in SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>256</max>
+ </range>
+ <defaultValue>256</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="suermN">
+ <description>SUERM parameter N.
+Measurement units are in SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>256</max>
+ </range>
+ <defaultValue>16</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="tin">
+ <description>Normal AERM threshold, Tin. Number of signal errors that cause abortion of a normal proving peroid.
+
+Measurement units are SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>7</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="tie">
+ <description>Emergency AERM threshold, Tie. Number of signal units errors that cause abortion of an emergency proving period.
+
+Measurement units are SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>7</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="provings">
+ <description>Proving abort limit. Number of consecutive aborted proving periods that will cause a return to the Out Of Service state.
+
+Measurement units are the number of proving periods.</description>
+ <long>
+ <range>
+ <min>1</min> <max>7</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT1">
+ <description>Maximum time to stay in Aligned Ready state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>16300</max>
+ </range>
+ <defaultValue>12900</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT2">
+ <description>Maximum time to stay in Not Aligned state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>32700</max>
+ </range>
+ <defaultValue>5000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT3">
+ <description>Maximum time to stay in Aligned state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>16300</max>
+ </range>
+ <defaultValue>11500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4n">
+ <description>Length of the normal proving period.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>4000</max>
+ </range>
+ <defaultValue>2300</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4e">
+ <description>Length of the emergengcy proving period.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>4000</max>
+ </range>
+ <defaultValue>600</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT5">
+ <description>Time between sending Status Indication "B" while in the Congested state.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>1</min> <max>255</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT6">
+ <description>Maximum time a remote site may remain in the congestated state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>8100</max>
+ </range>
+ <defaultValue>1000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT7">
+ <description>Maximum time to wait for an expected acknowledgement of an MSU before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>2000</max>
+ </range>
+ <defaultValue>500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="bitRate">
+ <description>The speed of the link. Only supported values are 64 and 56 kbit/s.
+0 = 64 kbit/s.
+1 = 56 kbit/s.
+
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="errorCorrection">
+ <description>The error correction algorithm to use. Only Basic Error Correction (BEC) is supported.
+0 = BEC
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet1">
+ <description>Percentage of the Transmit Buffer that will cause MTP2 to signal congestion for prio 1 messages towards client.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet2">
+ <description>Percentage of the Transmit Buffer that will cause MTP2 to signal congestion for prio 2 messages towards client.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet3">
+ <description>Percentage of the Transmit Buffer that will cause MTP2 to signal congestion for prio 3 messages towards client.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>90</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement1">
+ <description>Percentage of the Transmit Buffer that ceases congestion for prio 1 messages.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement2">
+ <description>Percentage of the Transmit Buffer that ceases congestion for prio 2 messages.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement3">
+ <description>Percentage of the Transmit Buffer that ceases congestion for prio 3 messages.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionDiscardLevel1">
+ <description>Percentage of the Transmit Buffer where messages sent to MTP2 from client with priority less than 1 is discarded by MTP2.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionDiscardLevel2">
+ <description>Percentage of the Transmit Buffer where messages sent to MTP2 from client with priority less than 2 is discarded by MTP2.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionDiscardLevel3">
+ <description>Percentage of the Transmit Buffer where messages sent to MTP2 from client with priority less than 3 is discarded by MTP2.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="n1Onset">
+ <description>Number of MSUs in ReTransmit Buffer before onset of preventive retransmission in PCR.
+NOTE: Only valid if errorCorrection==SCC_MTP2_ERROR_CORRECTION_PCR.
+This value is ignored otherwise.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="n2Onset">
+ <description>Number of MSUs in ReTransmit Buffer before onset of preventive retransmission in PCR.
+NOTE: Only valid if errorCorrection==SCC_MTP2_ERROR_CORRECTION_PCR.
+This value is ignored otherwise.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <struct name="Mtp2ProfileDataItu">
+ <structMember name="suermT">
+ <description>SUERM parameter T.
+Measured in SU units.</description>
+ <long>
+ <range>
+ <min>1</min> <max>64</max>
+ </range>
+ <defaultValue>64</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="suermD">
+ <description>SUREM parameter D.
+Measurement units are in SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>256</max>
+ </range>
+ <defaultValue>256</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="suermN">
+ <description>SUERM parameter N.
+Measurement units are in SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>256</max>
+ </range>
+ <defaultValue>16</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="tin">
+ <description>Normal AERM threshold, Tin. Number of signal errors that cause abortion of a normal proving peroid.
+
+Measurement units are SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>7</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="tie">
+ <description>Emergency AERM threshold, Tie. Number of signal units errors that cause abortion of an emergency proving period.
+
+Measurement units are SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>7</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="provings">
+ <description>Proving abort limit. Number of consecutive aborted proving periods that will cause a return to the Out Of Service state.
+
+Measurement units are the number of proving periods.</description>
+ <long>
+ <range>
+ <min>1</min> <max>7</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT1">
+ <description>Maximum time to stay in Aligned Ready state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>65500</max>
+ </range>
+ <defaultValue>40000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT2">
+ <description>Maximum time to stay in Not Aligned state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>262000</max>
+ </range>
+ <defaultValue>5000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT3">
+ <description>Maximum time to stay in Aligned state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>2000</max>
+ </range>
+ <defaultValue>1000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4n">
+ <description>Length of the normal proving period.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>16300</max>
+ </range>
+ <defaultValue>7500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4e">
+ <description>Length of the emergengcy proving period.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>16300</max>
+ </range>
+ <defaultValue>400</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT5">
+ <description>Time between sending Status Indication "B" while in the Congested state.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>1</min> <max>255</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT6">
+ <description>Maximum time a remote site may remain in the congestated state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>8100</max>
+ </range>
+ <defaultValue>3000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT7">
+ <description>Maximum time to wait for an expected acknowledgement of an MSU before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>2000</max>
+ </range>
+ <defaultValue>500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="bitRate">
+ <description>The speed of the link. Only supported values are 64 and 56 kbit/s.
+0 = 64 kbit/s.
+1 = 56 kbit/s.
+
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="errorCorrection">
+ <description>The error correction algorithm to use. Only Basic Error Correction (BEC) is supported.
+0 = BEC
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet1">
+ <description>Percentage of the Transmit Buffer that will cause MTP2 to signal congestion for prio 1 messages towards client.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet2">
+ <description>Percentage of the Transmit Buffer that will cause MTP2 to signal congestion for prio 2 messages towards client.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet3">
+ <description>Percentage of the Transmit Buffer that will cause MTP2 to signal congestion for prio 3 messages towards client.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>90</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement1">
+ <description>Percentage of the Transmit Buffer that ceases congestion for prio 1 messages.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement2">
+ <description>Percentage of the Transmit Buffer that ceases congestion for prio 2 messages.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement3">
+ <description>Percentage of the Transmit Buffer that ceases congestion for prio 3 messages.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionDiscardLevel1">
+ <description>Percentage of the Transmit Buffer where messages sent to MTP2 from client with priority less than 1 is discarded by MTP2.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionDiscardLevel2">
+ <description>Percentage of the Transmit Buffer where messages sent to MTP2 from client with priority less than 2 is discarded by MTP2.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionDiscardLevel3">
+ <description>Percentage of the Transmit Buffer where messages sent to MTP2 from client with priority less than 3 is discarded by MTP2.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="n1Onset">
+ <description>Number of MSUs in ReTransmit Buffer before onset of preventive retransmission in PCR.
+NOTE: Only valid if errorCorrection==SCC_MTP2_ERROR_CORRECTION_PCR.
+This value is ignored otherwise.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="n2Onset">
+ <description>Number of MSUs in ReTransmit Buffer before onset of preventive retransmission in PCR.
+NOTE: Only valid if errorCorrection==SCC_MTP2_ERROR_CORRECTION_PCR.
+This value is ignored otherwise.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <struct name="Mtp2ProfileDataChina">
+ <structMember name="bitRate">
+ <description>The speed of the link. Only supported values are 64 and 56 kbit/s.
+0 = 64 kbit/s.
+1 = 56 kbit/s.
+
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="errorCorrection">
+ <description>The error correction algorithm to use. Only Basic Error Correction (BEC) is supported.
+0 = BEC</description>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="provings">
+ <description>Proving abort limit. Number of consecutive aborted proving periods that will cause a return to the Out Of Service state.
+
+Measurement units are the number of proving periods.</description>
+ <long>
+ <range>
+ <min>1</min> <max>7</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="suermD">
+ <description>SUERM parameter D.
+Measurement units are in SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>256</max>
+ </range>
+ <defaultValue>256</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="suermN">
+ <description>SUERM parameter N.
+Measurement units are in SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>256</max>
+ </range>
+ <defaultValue>16</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="suermT">
+ <description>SUERM parameter T.
+Measured in SU units.</description>
+ <long>
+ <range>
+ <min>1</min> <max>64</max>
+ </range>
+ <defaultValue>64</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="tie">
+ <description>Emergency AERM threshold, Tie. Number of signal units errors that cause abortion of an emergency proving period.
+
+Measurement units are SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>7</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT1">
+ <description>Maximum time to stay in Aligned Ready state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>65500</max>
+ </range>
+ <defaultValue>45000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT2">
+ <description>Maximum time to stay in Not Aligned state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>262000</max>
+ </range>
+ <defaultValue>132000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT3">
+ <description>Maximum time to stay in Aligned state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>2000</max>
+ </range>
+ <defaultValue>1000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4e">
+ <description>Length of the emergengcy proving period.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>16300</max>
+ </range>
+ <defaultValue>500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4n">
+ <description>Length of the normal proving period.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>16300</max>
+ </range>
+ <defaultValue>8200</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT5">
+ <description>Time between sending Status Indication "B" while in the Congested state.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>1</min> <max>255</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT6">
+ <description>Maximum time a remote site may remain in the congestated state before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>8100</max>
+ </range>
+ <defaultValue>5000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT7">
+ <description>Maximum time to wait for an expected acknowledgement of an MSU before signalling link failure.
+
+Measurement units are milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>2000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="tin">
+ <description>Normal AERM threshold, Tin. Number of signal errors that cause abortion of a normal proving peroid.
+
+Measurement units are SUs.</description>
+ <long>
+ <range>
+ <min>1</min> <max>7</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet1">
+ <description>Percentage of the Transmit Buffer that will cause MTP2 to signal congestion for prio 1 messages towards client.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet2">
+ <description>Percentage of the Transmit Buffer that will cause MTP2 to signal congestion for prio 2 messages towards client.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet3">
+ <description>Percentage of the Transmit Buffer that will cause MTP2 to signal congestion for prio 3 messages towards client.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>90</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement1">
+ <description>Percentage of the Transmit Buffer that ceases congestion for prio 1 messages.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement2">
+ <description>Percentage of the Transmit Buffer that ceases congestion for prio 2 messages.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement3">
+ <description>Percentage of the Transmit Buffer that ceases congestion for prio 3 messages.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionDiscardLevel1">
+ <description>Percentage of the Transmit Buffer where messages sent to MTP2 from client with priority less than 1 is discarded by MTP2.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionDiscardLevel2">
+ <description>Percentage of the Transmit Buffer where messages sent to MTP2 from client with priority less than 2 is discarded by MTP2.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionDiscardLevel3">
+ <description>Percentage of the Transmit Buffer where messages sent to MTP2 from client with priority less than 3 is discarded by MTP2.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="n1Onset">
+ <description>Number of MSUs in ReTransmit Buffer before onset of preventive retransmission in PCR.
+NOTE: Only valid if errorCorrection==SCC_MTP2_ERROR_CORRECTION_PCR.
+This value is ignored otherwise.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="n2Onset">
+ <description>Number of MSUs in ReTransmit Buffer before onset of preventive retransmission in PCR.
+NOTE: Only valid if errorCorrection==SCC_MTP2_ERROR_CORRECTION_PCR.
+This value is ignored otherwise.</description>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <enum name="EmergencyStatus">
+ <description>This enumeration specifies the different stages of the emergency state.</description>
+ <enumMember name="NEVER_USED">
+ <description>Emergency state has not been activated since installation of license key file.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="ACTIVE">
+ <description>All capacity restrictions removed and all features enabled. The maximum time in this state is 7 days.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="USE_DEGRADED">
+ <description>A new license key file has to be istalled in order not to jopardize future use and performance.
+The maximum time in this state is 7 days.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="ACTIVE_AGAIN">
+ <description>All features enabled again for a maximum period of 7 days then a new license key file has to be installed in order to be able to use this node.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="USE_DISABLED">
+ <description>Use of the node is no longer allowed since no new license key file has been installed.</description>
+ <value>4</value>
+ </enumMember>
+ </enum>
+
+ <struct name="EmergencyInfo">
+ <description>This attribute provides information about the current EmergencyState.
+
+Note: for the states NEVER_USED and USE_DISABLED the return value for time is insignificant.</description>
+ <structMember name="state">
+ <description>The current emergency state of the license server.</description>
+ <enumRef name="EmergencyStatus">
+ <defaultValue>NEVER_USED</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="time">
+ <description>This attribute holds information on the time elapsed in this state.
+
+Note: The time out values for the states ALL_OPEN, DEGADED and PROLONGED is 7 days. The unit for this attribute is seconds.
+1 day = 86400 seconds
+7 days = 604800 seconds.</description>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <enum name="NodeRestartType">
+ <enumMember name="WARM_AT_PIU_RESTART">
+ <description>Warm node restart at restart of the last PIU.</description>
+ <value>4</value>
+ </enumMember>
+ <enumMember name="COLD_AT_PIU_RESTART">
+ <description>Cold node restart at restart of the last PIU.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="WARM_AT_PIU_FAULT">
+ <description>Warm node restart at fault mark of the last PIU.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="COLD_AT_PIU_FAULT">
+ <description>Cold node restart at fault mark of the last PIU.</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <struct name="UniSaalProfileData">
+ <structMember name="maxPD">
+ <description>Maximum number of SD PDUs before a poll is sent.
+
+maxPD &lt; initialCredit</description>
+ <long>
+ <range>
+ <min>10</min> <max>10000</max>
+ </range>
+ <defaultValue>25</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="maxStat">
+ <description>Maximum number, odd integer value, of list elements placed in a STAT PDU.
+
+Note: The maxStat attribute is dependent on the AAL5 maximum SDU size defined in the Aal5TpVccTp MO. The maxStat times 4 (octets) plus additional 12 octets (for header) must not exceed the AAL5 maximum SDU size (lower of the two directions, fromUserMaxSduSize and toUserMaxSduSize).
+The consistency control is not performed until the UniSaalTp MO is created since there is no relation between the UniSaalProfile MO and the Aal5TpVccTp MO.</description>
+ <long>
+ <range>
+ <min>3</min> <max>1001</max>
+ </range>
+ <defaultValue>67</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="initialCredit">
+ <description>Initial number of credits.
+
+Note: For 64 kbit/s use 30.
+
+Note! The value for initialCredit must be larger than the value of maxPD.
+</description>
+ <long>
+ <range>
+ <min>10</min> <max>1000</max>
+ </range>
+ <defaultValue>250</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerKeepAlive">
+ <description>Timer to be used during a period of no outstanding acknowledgements or new data pending receipt of credit. At timeout the peer is polled to see if it is alive. The timer determines the interval between polls in transient phase. This timer should be greater than the roundtripdelay and also greater than timerpoll. Time unit = milliseconds.
+</description>
+ <long>
+ <range>
+ <min>10</min> <max>10000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerNoResponse">
+ <description>Timer to determine the maximum time interval during which at least one STAT PDU reception is expected as a response to a poll. This timer should be equal to timerKeepAlive+roundtripdelay. Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>100000</max>
+ </range>
+ <defaultValue>7000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerIdle">
+ <description>Timer running when there are no PDUs to transmit and there are no outstanding acknowledgements or data pending for credit. When this timer is running, no POLL PDUs are sent. This timer should be significantly greater than timerKeepAlive value. Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>1000</min> <max>600000</max>
+ </range>
+ <defaultValue>15000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerCC">
+ <description>Timer determining the time between re-transmission of PDUs: BGN, END, ER, RS. Should be slightly more than the roundtripdelay. Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>10000</max>
+ </range>
+ <defaultValue>1000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerPoll">
+ <description>Timer that specifies the maximum time between sending of POLL PDUs to the peer receiver during other traffic (active phase). Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>100000</max>
+ </range>
+ <defaultValue>750</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="maxCC">
+ <description>Maximum number of re-transmissions of PDUs: BGN, END, ER, RS. Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionOnSet">
+ <description>Attribute specifying the percentage of the buffer that must be filled in order to cause congestion. Congestion is notified to the users of this protocol layer. The part of the buffer above the congestion level is used to take care of messages that were sent before the users stopped sending.
+
+This attribute should follow the rule 0 &lt;= congestationAbatement &lt; congestationOnSet &lt;= 100.</description>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionAbatement">
+ <description>Attribute specifying the percentage of the buffer for which congestion is stopped. If the congestionAbatement level is lesser but almost equal to congestionOnSet, congestion alarms might be raised and ceased very often.
+
+This attribute should follow the rule 0 &lt;= congestationAbatement &lt; congestationOnSet &lt;= 100.</description>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <struct name="NniSaalProfileData">
+ <description>Struct holding the values for an NniSaalProfile.
+
+NOTE: Congestition Level 1 - 3 is supported.</description>
+ <structMember name="timerPoll">
+ <description>Timer that specifies the maximum time between sending of POLL PDUs to the peer receiver during other traffic (active phase). Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>100000</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="maxCC">
+ <description>Maximum number of re-transmissions of PDUs: BGN, END, ER, RS.</description>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="maxPD">
+ <description>Maximum number of SD PDUs before a poll is sent.
+
+maxPD &lt; initialCredit</description>
+ <long>
+ <range>
+ <min>0</min> <max>10000</max>
+ </range>
+ <defaultValue>25</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="maxStat">
+ <description>Maximum number, odd integer value, of list elements placed in a STAT PDU.
+
+Note: The maxStat attribute is controlled by the AAL5 maximum SDU size defined in the Aal5TpVccTp MO. The maxStat times 4 (octets) plus additional 12 octets (for header) must not exceed the AAL5 maximum SDU size (lower of the two directions, fromUserMaxSduSize and toUserMaxSduSize).
+
+The consistency control is not performed until the NniSaalTp MO is created since there is no relation between the NniSaalProfile MO and the Aal5TpVccTp MO.</description>
+ <long>
+ <range>
+ <min>3</min> <max>1001</max>
+ </range>
+ <defaultValue>67</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="initialCredit">
+ <description>Initial number of credits.
+
+Note: For 64 kbit/s use 30.
+
+Note! The value for initialCredit must be larger than the value of maxPD.</description>
+ <long>
+ <range>
+ <min>10</min> <max>1000</max>
+ </range>
+ <defaultValue>250</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerKeepAlive">
+ <description>Timer to be used during a period of no outstanding acknowledgements or new data pending receipt of credit. At timeout the peer is polled to see if it is alive. The timer determines the interval between polls in transient phase. This timer should be greater than the roundtripdelay and also greater than timerpoll. Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>10000</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerNoResponse">
+ <description>Timer to determine the maximum time interval during which at least one STAT PDU reception is expected as a response to a poll.This timer should be equal to timerKeepAlive+roundtripdelay. Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>100000</max>
+ </range>
+ <defaultValue>500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerIdle">
+ <description>Timer running when there are no PDUs to transmit and there are no outstanding acknowledgements or data pending for credit. When this timer is running, no POLL PDUs are sent. This timer should be significantly greater than timerKeepAlive value. Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>10</min> <max>10000</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerCC">
+ <description>Timer determining the time between re-transmission of PDUs: BGN, END, ER, RS. Time unit = milliseconds.
+Should be more than the roundtrip delay.</description>
+ <long>
+ <range>
+ <min>10</min> <max>10000</max>
+ </range>
+ <defaultValue>200</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="mps">
+ <description>Management Proving Status which is used to decide if proving is done or not during SAAL connection setup.
+</description>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionLevel1OnSet">
+ <description>Attribute specifying the percentage of the buffer that must be filled in order to cause congestion.
+Congestion is notified to the users of this protocol layer. The part of the buffer above the congestion
+level is used to take care of messages that were sent before the users stopped sending.
+
+Attribute specifying the percentage of the buffer that must be filled in order to cause congestion.
+Congestion is notified to the users of this protocol layer. The part of the buffer above the congestion
+level is used to take care of messages that were sent before the users stopped sending.
+
+This attribute should follow the rule 0 &lt;= congestationLevel1OnSet &lt;= congestationLevel2OnSet &lt;= congestationLevel3OnSet &lt;= 100.</description>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>70</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionLevel2OnSet">
+ <description>Attribute specifying the percentage of the buffer that must be filled in order to cause congestion.
+Congestion is notified to the users of this protocol layer. The part of the buffer above the congestion
+level is used to take care of messages that were sent before the users stopped sending.
+
+This attribute should follow the rule 0 &lt;= congestationLevel1OnSet &lt;= congestationLevel2OnSet &lt;= congestationLevel3OnSet &lt;= 100.</description>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionLevel3OnSet">
+ <description>Attribute specifying the percentage of the buffer that must be filled in order to cause congestion.
+Congestion is notified to the users of this protocol layer. The part of the buffer above the congestion
+level is used to take care of messages that were sent before the users stopped sending.
+
+This attribute should follow the rule 0 &lt;= congestationLevel1OnSet &lt;= congestationLevel2OnSet &lt;= congestationLevel3OnSet &lt;= 100.</description>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>90</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="congestionLevel1Abatement">
+ <description>Attribute specifying the percentage of the buffer for which congestionLevel1 is stopped. If the congestionAbatement level is lesser but almost equal to congestionOnSet, congestion alarms might be raised and ceased very often.
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="nrOfPDUsDuringProving">
+ <description>The length of proving in terms of number of transmitted PDUs (n1).
+noOfPDUsDuringProving x T3 &lt; T2
+
+For the TTC standard the only allowed value is 0 (which means no proving).</description>
+ <long>
+ <range>
+ <min>0</min> <max>100000</max>
+ </range>
+ <defaultValue>1000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="maxNRP">
+ <description>State variable which defines max number of retransmissions of PDUs during proving to consider proving successful.
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerNoCredit">
+ <description>Maximum time of no credit. If the timer expires, the assured data transfer mode is released.</description>
+ <long>
+ <range>
+ <min>0</min> <max>100000</max>
+ </range>
+ <defaultValue>1500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerRepeatSrec">
+ <description>Timer which is set whenever a report of SSCOP recovery is received from the SSCF. If the timer is running when another report of recovery is received, the assured data transfer mode is released. If the timer expires, nothing is done. Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>0</min> <max>86400000</max>
+ </range>
+ <defaultValue>3600000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT1">
+ <description>Timer between the link release action and the next link re-establish action during the alignment. At expiry of timer T1, a new attempt to setup assured data transfer mode to the peer is done. Time unit = milliseconds.
+</description>
+ <long>
+ <range>
+ <min>10</min> <max>100000</max>
+ </range>
+ <defaultValue>5000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT2">
+ <description>Total time that SSCF will attempt alignment. At expiry of timer T2, the alignment procedure will be interrupted.
+ Time unit = milliseconds.
+</description>
+ <long>
+ <range>
+ <min>10</min> <max>200000</max>
+ </range>
+ <defaultValue>30000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT3">
+ <description>Time between proving PDUs. The timer is set such that loading of the signalling link is approximately 50% of its nominal rate.
+Time unit = milliseconds.</description>
+ <long>
+ <range>
+ <min>5</min> <max>1000</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <exception name="ListOfTimeSlotsNotUniqueException">
+ <description>Exception thrown when a time slot appears more than once in the time slot list.</description>
+ </exception>
+
+ <enum name="RefActivity">
+ <description>RefActivity can have the following values:
+
+inactive = Synchronization reference is currently not used in system clock generation.
+active = Synchronization is used in system clock generation.
+</description>
+ <enumMember name="inactive">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="active">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="RefState">
+ <description>RefState can have the following values:
+failed = synchronization reference is not capable to perform its required tasks.
+degraded = capability of synchronization reference to perform its required tasks is degraded e.g. because of signal level degradation. This value is only applicable for traffic carrying (ET physical path termination) synchronization references. Note: attribute degradationIsFault controls whether synchronization reference degradation is interpreted as a synchronization reference fault or not.
+lossOfTracking = system clock regulation algorithm on TU board can not follow the 8kHz synchronization reference signal either because of the poor quality of the signal or because of a HW fault at TU board. If all synchronization references repeatedly end up to state lossOfTracking, fault is likely in TU HW.
+ok = synchronization reference is capable of performing its required tasks.
+</description>
+ <enumMember name="failed">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="degraded">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="lossOfTracking">
+ <value>2</value>
+ </enumMember>
+ <enumMember name="ok">
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <enum name="FaultCriteria">
+ <description>FaultCriteria can have the following values:
+degrNotFault = synchronization reference degradation is NOT interpreted as a synchronization reference fault.
+degrIsFault = synchronization reference degradation is interpreted as a synchronization reference fault.</description>
+ <enumMember name="degrNotFault">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="degrIsFault">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="ClockState">
+ <description>ClockState can have the following values:
+startUp =
+locked = system clock signal on Timing Unit is locked: a synchronization reference is used in the system clock generation, clock accuracy is 50 ppb or better.
+holdOver = system clock signal on Timing Unit is hold-over: no synchronization reference is used in system clock generation, clock accuracy is 50 ppb or better.
+freeRunning = system clock signal on Timing Unit is free running: no synchronization reference is used in system clock generation, clock accuracy is 4.6 ppm or better.
+failed = system clock signal on Timing Unit is failed: fault in system clock generation function, no quarantee of clock accuracy level.
+not Applicable = system clock signal on Timing Unit is not applicable: TU board not present.</description>
+ <enumMember name="unknownMode">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="startupMode">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="lockedMode">
+ <value>2</value>
+ </enumMember>
+ <enumMember name="holdOverMode">
+ <value>3</value>
+ </enumMember>
+ <enumMember name="freeRunningMode">
+ <value>4</value>
+ </enumMember>
+ <enumMember name="failedMode">
+ <value>5</value>
+ </enumMember>
+ <enumMember name="lossOfTrackingMode">
+ <value>6</value>
+ </enumMember>
+ <enumMember name="notApplicable">
+ <value>7</value>
+ </enumMember>
+ </enum>
+
+ <exception name="AlreadyRegisteredException">
+ <description>Exception thrown when an object is already registered.</description>
+ </exception>
+
+ <exception name="MaxNoOfRefRegisteredException">
+ <description>Exception thrown when the maximum number of references is reached.</description>
+ </exception>
+
+ <exception name="PriorityAlreadyInUseException">
+ <description>Exception thrown when a priority is already in use.</description>
+ </exception>
+
+ <exception name="PriorityOutOfRangeException">
+ <description>Exception thrown when the priority is out of range.</description>
+ </exception>
+
+ <exception name="NotPermittedException">
+ <description>Exception thrown when an reference is not valid, null or of incorrect type.</description>
+ </exception>
+
+ <exception name="NotRegisteredException">
+ <description>Exception thrown when trying to de-register an object that is not registered in the database.</description>
+ </exception>
+
+ <enum name="SystemClockRedundancy">
+ <enumMember name="SYSTEM_CLOCK_USERS_USE_PLANE_A">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="SYSTEM_CLOCK_USERS_USE_PLANE_B">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="SYSTEM_CLOCK_USERS_USE_PLANE_A_AND_B">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <exception name="NotUniqueFroIdException">
+ <description>Exception thrown when a fro Id is not unique.</description>
+ </exception>
+
+ <enum name="ActiveSwitchPlane">
+ <enumMember name="switchPlaneA">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="switchPlaneB">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="switchPlaneBoth">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="SwitchReliableGroup">
+ <description>A predefined group consisting of working links and their corresponding protecting links. These links form the n+m link redundancy. </description>
+ <enumMember name="physicalLinkStatusWorking">
+ <description>Defines physical link status.
+</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="physicalLinkStatusProtecting">
+ <description>Defines physical link status.
+</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="physicalLinkStatusUndefined">
+ <description>Defines physical link status.
+</description>
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <struct name="GlobalTitleData">
+ <structMember name="indicator">
+ <description>Global title indicator should have following values for both ITU and TTC:
+
+The values for the GT Indicator
+
+Value Comment
+
+0 No new global title
+2 TT only
+3 TT-NP-ES
+4 TT-NP-ES-NOA
+
+Explanation:
+
+TT = translation type
+NP = numbering plan
+ES = encoding scheme
+NOA = nature of address indication</description>
+ <long>
+ <range>
+ <min>0</min> <max>4</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="natureOfAddress">
+ <description>Indicates number type, i.e. national or international number.
+Coding of the Nature Address:
+
+0 = "unknown"
+1 = "Subscriber number"
+2 = "Reserved for national use"
+3 = "National significant number"
+4 = "International number"</description>
+ <long>
+ <range>
+ <min>0</min> <max>4</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="numberingPlan">
+ <description>Indicates which numbering plan that is used.
+
+Coding of the Numbering Plan:
+
+0 = "Unknown"
+1 = "ISDN/Telephony Numbering Plan"
+3 = "Data Numbering Plan"
+4 = "Telex Numbering Plan"
+5 = "Maritime Mobile Numbering Plan"
+6 = "Land Mobile Numbering Plan"
+7 = "ISDN/Mobile Numbering Plan"
+</description>
+ <long>
+ <range>
+ <min>0</min> <max>7</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="translationType">
+ <description>Used to direct the message to the appropriate Global Title translation function.</description>
+ <long>
+ <range>
+ <min>0</min> <max>254</max>
+ </range>
+ </long>
+ </structMember>
+ <structMember name="addressInformation">
+ <description>Digit string of 1-37 digits, where each digit is 0-9, and B, C. B and C are for Code 11 and Code 12.
+The addressInformation may also contain wild card symbols: "*" or "?". Wild cards are only allowed for defining Global Title Translations, they are not allowed for specifying SCCP SAPs (built with SPC and Global Title or SPC + SSN + Global Title).</description>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>37</max>
+ </lengthRange>
+ </string>
+ </structMember>
+ <structMember name="encodingScheme">
+ <description>Indicates if the number of address signals are an odd or even number, and is coded as follows:
+
+0 = "Unknown"
+1 = "BCD, odd number of digits"
+2 = "BCD, even number of digits"
+
+Other values in the encoding scheme will result in the error "Wrong Nature Of Address", (Routing failure reason=No translation for an address of such nature).</description>
+ <long>
+ <range>
+ <min>0</min> <max>2</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <enum name="SharingMode">
+ <enumMember name="loadShare">
+ <description>The when sharing mode is set to loadShare the SCCP traffic is load shared between the two entities (access points).</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="dupliDominant">
+ <description>When the sharing mode is set to dupliDominant the second entity (access point) is a backup for the first entity.</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="EncodingScheme">
+ <description>Possible values for number signalling.</description>
+ <enumMember name="UNKNOWN">
+ <description>Unkown encoding scheme.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="ODD_NUMBER">
+ <description>BCD, odd number of digits.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="EVEN_NUMBER">
+ <description>BCD, even number of digits.</description>
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="GlobalTitleIndicator">
+ <description>Global title indicator values for China, ITU, TTC and ANSI.
+
+Note: China, ITU and TCC will use TT_ONLY, TT_NP_ES, TT_NP_ES_NOA, NOA_ONLY.
+
+ANSI will use:
+ANSI_TT_NP_ES = 5
+ANSI_TT_ONLY = 6
+</description>
+ <enumMember name="TT_ONLY">
+ <description>Translation Type only.
+
+Only valid for China, ITU and TTC.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="TT_NP_ES">
+ <description>Translation Type, Numbering Plan and Encoding Scheme.
+
+Only valid for China, ITU and TTC.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="TT_NP_ES_NOA">
+ <description>Translation Type, Numbering Plan, Encoding Scheme, and Nature Of Address indication.
+
+Only valid for China, ITU and TTC.</description>
+ <value>4</value>
+ </enumMember>
+ <enumMember name="NOA_ONLY">
+ <description>Nature of Address indicator only.
+
+Only valid for China, ITU and TTC.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="ANSI_TT_NP_ES">
+ <description>Translation Type, Numbering Plan and Encoding Scheme.
+
+Only valid for ANSI.
+</description>
+ <value>5</value>
+ </enumMember>
+ <enumMember name="ANSI_TT_ONLY">
+ <description>Translation Type only.
+
+Only valid for ANSI.
+</description>
+ <value>6</value>
+ </enumMember>
+ </enum>
+
+ <enum name="NatureOfAddress">
+ <description>Phone number types.</description>
+ <enumMember name="UNKNOWN">
+ <description>Unknown number type.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="SN">
+ <description>Subscriber number type.
+</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="RN">
+ <description>Reserved for national use, number type.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="NSN">
+ <description>National Significant Number type.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="IN">
+ <description>International number type.</description>
+ <value>4</value>
+ </enumMember>
+ </enum>
+
+ <enum name="NumberingPlan">
+ <description>Numbering plans.</description>
+ <enumMember name="UNKNOWN">
+ <description>Unknown numbering plan.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="TELEPHONY">
+ <description>ISDN/Telephony numbering plan.
+</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="DATA">
+ <description>Data numbering plan.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="TELEX">
+ <description>Telex numbering plan.
+</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="MOBILE_MARITIME">
+ <description>Maritime mobile numering plan.
+</description>
+ <value>4</value>
+ </enumMember>
+ <enumMember name="MOBILE_LAND">
+ <description>Land mobile numbering plan.
+</description>
+ <value>5</value>
+ </enumMember>
+ <enumMember name="MOBILE">
+ <description>ISDN/Mobile numbering plan.</description>
+ <value>6</value>
+ </enumMember>
+ </enum>
+
+ <enum name="SccpCountType">
+ <enumMember name="MESSAGES">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="OCTETS">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <struct name="Scmg">
+ <structMember name="sendSST">
+ <description>Controls when to send SST (SCCP Subsystem Test message).
+
+0 = Wait for tStatInfo timer to expire once after MTP_RESUME before sending SST.
+1 = Send SST immediately after MTP_RESUME, then start tStatInfo timer.</description>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="sendSSA">
+ <description>Controls when to send SSA (SCCP Subsystem Allowed message).
+
+0 = Do not send SSA when client attaches, wait until SST is received. (default for ANSI/CHINA/ITU/TTC)
+1 = Send SSA immediately when client attaches.</description>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="sendSSP">
+ <description>Controls whether to send SSP (SCCP Subsystem Prohibited message).
+
+0 = Do not send SSP when client detaches. (default for TTC)
+1 = Send SSP immediately when client detaches. (default for ANSI/CHINA/ITU)</description>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="useSST">
+ <description>Controls whether to send SST messages or not (SCCP Subsystem Test message).
+
+0 = Send SST as indicated by sendSST. (default for ANSI/CHINA/ITU)
+1 = (not used)
+2 = (not used)
+3 = Do not initiate SST messages at all, ie. do not start timer tStatInfo nor send any SST at MTP_RESUME. (default for TTC)</description>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="allowRemoteBroadcast">
+ <description>Controls the remote broadcast.
+
+0 = allow remote broadcast. (default for ANSI/CHINA/ITU/TTC)
+1 = do not allow remote broadcast</description>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="initiateTimerTcon">
+ <description>Controls whether to initiate hardcoded congestion timer or not.
+
+0 = start timer when SSC is received. (default for CHINA/ITU/TTC)
+1 = do not start timer
+
+Note! This attribute is not valid for the ANSI standard.</description>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <enum name="DiscardReturnServiceMsg">
+ <enumMember name="DISCARD">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="RETURN">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <exception name="WrongUserTypeException">
+ </exception>
+
+ <exception name="UsageNotPermittedException">
+ </exception>
+
+ <enum name="J1Type">
+ <description>J1Type can have the following values:
+J1_G = 0 according to TTC JT-G703/G704
+J1_I = 1 according to TCC JT-I431</description>
+ <enumMember name="j1_G">
+ <description>J1 according to TTC JT-G703/G704</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="j1_I">
+ <description>J1 according to TCC JT-I431</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="StandardMode">
+ <description>Indicates what standard the MAO is operating to.</description>
+ <enumMember name="TTC">
+ <description>The standard mode is Telecommunication Technology Committee (TTC).</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="ANSI">
+ <description>The standard mode ANSI.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="ETSI">
+ <description>The standard mode is ETSI.</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="MuxMode">
+ <description>Indicates what multiplexing is being used.</description>
+ <enumMember name="STANDBY">
+ <description>Standby for protection.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="E1_J1_T1_LEVEL">
+ <description>Multiplexing terminated at the E1/J1/T1 level.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="VC4_STS3CSPE_LEVEL">
+ <description>Multiplexing terminated at the VC-4/STS3CSPE level.</description>
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="Os155LoopBack">
+ <description>The loopback method available for use by the Os155SpiTtp MO.</description>
+ <enumMember name="NONE">
+ <description>No loopback in use.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="LINE">
+ <description>Loopingback using line.</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="SwitchModes">
+ <description>The switch modes.</description>
+ <enumMember name="AUTOMATIC">
+ <description>Automatic switching.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="LOCKED">
+ <description>Locked for swtiching.</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <exception name="FailedResourceException">
+ </exception>
+
+ <exception name="LockedResourceException">
+ </exception>
+
+ <exception name="UnknownReasonException">
+ </exception>
+
+ <exception name="AlreadyLockedException">
+ </exception>
+
+ <exception name="IncorrectOsi155SpiIdException">
+ </exception>
+
+ <enum name="PathTraceFormat">
+ <description>Path Trace Formats.</description>
+ <enumMember name="ITU_T_G707">
+ <description>16 byte path trace format according to ITU-T G707 table 4.</description>
+ <value>16</value>
+ </enumMember>
+ <enumMember name="GR_253_CORE">
+ <description>64 byte path trace format according to section 3.3.2.3, Telecordia GR-253-CORE.</description>
+ <value>64</value>
+ </enumMember>
+ </enum>
+
+ <enum name="Crc4Mode">
+ <description>Cyclical Redundancy Checks 4 modes.</description>
+ <enumMember name="OFF">
+ <description>CRC 4 is off.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="ON">
+ <description>CRC 4 is on.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="AUTOMATIC">
+ <description>CRC 4 is automatic.</description>
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="IdlePattern">
+ <description>Idle patterns.</description>
+ <enumMember name="A_LAW">
+ <description>A law idle pattern.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="U_LAW">
+ <description>Micro law idle pattern.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="UNDEFINED">
+ <description>Undefined idle pattern.</description>
+ <value>0</value>
+ </enumMember>
+ </enum>
+
+ <enum name="LoopbackState">
+ <description>The possible loopback states for E1/J1/T1/E3/T3PhysPathTerm MOs.</description>
+ <enumMember name="none">
+ <description>This is the normal state, no loop back is preformed (and ordinary traffic is running).</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="line">
+ <description>The phyiscal path is looped on the line side, the external incoming path is looped back to the external outgoing path.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="system">
+ <description>The physical path is looped on the system side, the (node-) internal incoming path is looped back to the internal outgoing path.</description>
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="TransmissionMode">
+ <description>L stands for long haul interface and S stands for short haul interface.
+The subsequent figure specifies the cable distance in feets.</description>
+ <enumMember name="L_6000">
+ <description>Long Haul 6000 ft, -0 dB</description>
+ <value>8</value>
+ </enumMember>
+ <enumMember name="L_4000">
+ <description>Long Haul 4000 ft, -7 dB</description>
+ <value>7</value>
+ </enumMember>
+ <enumMember name="L_2000">
+ <description>Long Haul 2000 ft, -15 dB</description>
+ <value>6</value>
+ </enumMember>
+ <enumMember name="L_0">
+ <description>Long Haul 0 ft, -22 dB</description>
+ <value>5</value>
+ </enumMember>
+ <enumMember name="S_133">
+ <description>Short Haul 0..133 ft</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="S_266">
+ <description>Short Haul 134..266 ft</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="S_399">
+ <description>Short Haul 267..399 ft</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="S_533">
+ <description>Short Haul 400..533 ft</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="S_655">
+ <description>Short Haul 534..655 ft</description>
+ <value>4</value>
+ </enumMember>
+ </enum>
+
+ <struct name="Mtp3bSpItuPriorityData">
+ <description>Priority attributes for MTP3b SP of the ITU standard.</description>
+ <structMember name="prioSlt">
+ <description>The prioSlt attribute sets the priority for the
+ Signalling Link Test Message and Acknowledge (SLTM / SLTA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioCo">
+ <description>The prioCo attribute sets the priority for the ChangeOver Order and Acknowledge (COO/COA) or eXtended Change over Order and Acknowledge (XCO/XCA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet)
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioCb">
+ <description>The prioCb attribute sets the priority for the
+ Change Back Declaration and Acknowledge (CBD / CBA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioEc">
+ <description>The prioEc attribute sets the priority for the
+Emergency Change over Order and Acknowledge (ECO / ECA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioRst">
+ <description>The prioRst attribute sets the priority for the
+signalling Route Set Test (RST) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioTra">
+ <description>The prioTra attribute sets the priority for the
+Traffic Restart Allowed signal (TRA) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioUpu">
+ <description>The prioUpu attribute sets the priority for the
+ User Part Unavailable (UPU) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioLink">
+ <description>The prioLink attribute sets the priority for link related messages when issued by the MTP3b itself. The messages are :
+
+Link INhibit (LIN), Link UNinhibit (LUN),
+Link Inhibit Denied (LID),
+Link Inhibit Acknowledge (LIA),
+Link Uninhibit Acknowledge (LUA),
+Link Forced Uninhibit (LFU),
+Link Local inhibit Test (LLT) and
+Link Remote inhibit Test (LRT)
+
+When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ </struct>
+
+ <struct name="Mtp3bSpItuTimerData">
+ <description>ITU timers for MTP3bSpItu. Timervalues in 1/10 s (deciseconds).</description>
+ <structMember name="timerT1">
+ <description>Delay to avoid message mis-sequencing on changeover.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT2">
+ <description>Timer for waiting for a COO or a COA.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT3">
+ <description>Delay to avoid message mis-sequencing on a time controlled diversion change back.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4">
+ <description>Timer for waiting for CBA, first attempt.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT5">
+ <description>Timer for waiting for CBA, second attempt
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT6">
+ <description>Timer for delay to avoid message mis-sequencing on controlled rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>9</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT8">
+ <description>Timer for delay to prohibit sending of TFP messages via the response method. This is a STP specific parameter, which is ignored when configured as an endpoint.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT10">
+ <description>Timer for waiting to repeat sending of RST periodically.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>400</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT12">
+ <description>Waiting for uninhibit acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT13">
+ <description>Timer for waiting for force uninhibit.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT14">
+ <description>Timer for waiting for inhibition acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT17">
+ <description>Delay to avoid oscillation of initial alignment failure and link restart.
+
+The value for this timer should be less than the value for timerT2.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>9</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTBsnt">
+ <description>Waiting for BSNT value from MTP-2 or SAAL (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTRetrieval">
+ <description>Timer for waiting for completion of buffer retrieval from MTP-2 or SAAL (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTStart">
+ <description>Timer for retransmission of DL_START_req if no answer received. Started when timerT17 expires. (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>1200</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTc">
+ <description>Controlling the period a route set is considered congested when a Transfer Controlled message has been received.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT18">
+ <description>Supervision timer for the first phase of a restarting STP. This is an STP specific parameter, which is ignored when configured as an endpoint.
+
+The value for this timer should be less than the value for timerT2.
+
+Unit: deciseconds (1/10 second).
+</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>550</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT19">
+ <description>Controlling the response of the receipt of a traffic restart message from an adjacent node.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>680</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT20">
+ <description>Overall MTP restart timer at the restarting MTP.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>600</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT21">
+ <description>Overall MTP restart timer at an adjacent signalling point to a restarting MTP.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>640</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT22">
+ <description>Local inhibit test timer.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>2500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT23">
+ <description>Remote inhibit test timer.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>2500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerSlta">
+ <description>Supervision timer for SLTA message (time within SLTA should arrive).
+
+Timer T1 in ITU Q.707 standard.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerSltm">
+ <description>Timer for sending SLTM periodically.
+
+Timer T2 in ITU Q.707 standard.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>400</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaTack">
+ <description>Timer used for message acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaPeriodicAudit">
+ <description>Timer used for audit procedure.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>300</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT1">
+ <description>Delay to avoid mis-sequencing of messages when an association fails.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT3">
+ <description>Delay to avoid mis-sequencing of messages when an association becomes active.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT6">
+ <description>Delay to avoid mis-sequencing on controlled rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT8">
+ <description>Delay to prohibit sending of DUNA messages via the response method.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT40">
+ <description>Delay to avoid message mis-sequencing on controlled/forced rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT41">
+ <description>Timer controlloing the traffic activation delay during restart phase.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT42">
+ <description>The forever interval period for trying association after an unsiccessfull trial.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaTc">
+ <description>Timer controlling the period a route set is considered congested when a SCON message has been received.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT15">
+ <description>Timer waiting to start signaling route set congestiontest. Used only if the Route Set
+Congestion Test Selectoption is set to "Use Route Set Congestion test".
+
+Guiding value 20 - 30.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT16">
+ <description>Timer waiting for route set congestion status update. Used only if the Route Set
+Congestion Test Selectoption is set to "Use Route Set Congestion test"
+
+Guiding value 14 - 22.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>14</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTDlack">
+ <description>Timer pending an acknowledge from the network layer for a DL_ACK_REQ.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaTassocack">
+ <description>Timer used for SCTP_ASSOCIATE_REQ message acknowledgement. This is the maximum time to wait for the SCTP_COMMUP_IND mesage before considering it to be an error.
+It should be longer than the time a message spends to reach the most distant destination, be processed and returned.</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <enum name="CongestLevel">
+ <description>The supported congestion levels.</description>
+ <enumMember name="level_0">
+ <description>No Congestion.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="level_1">
+ <description>Congestion level low.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="level_2">
+ <description>Congestion level medium.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="level_3">
+ <description>Congestion level high.</description>
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <exception name="ActivationFailedException">
+ </exception>
+
+ <exception name="NoAvailRouteException">
+ </exception>
+
+ <enum name="Mtp3bCongestLevel">
+ <enumMember name="notCongested">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="congested">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="Mtp3bNetworkInd">
+ <description>Indicates which type of geographical network, e.g. national, international, etc..
+
+Note: Not applicable for TTC.</description>
+ <enumMember name="INTERNATIONAL_NETWORK">
+ <description>International Network.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="SPARE">
+ <description>Spare (for international use only).</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="NATIONAL_NETWORK">
+ <description>National network.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="RESERVED_FOR_NATIONAL_USE">
+ <description>Reserved for national use.</description>
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <enum name="Mtp3bTfrHandling">
+ <description>Indicates how a TransFer Restricted (TFR) signal is handled.</description>
+ <enumMember name="HANDLE_AS_TFA">
+ <description>Treat the TransFer Restricted (FTR) signal as a TransFer Allowed (TFA) signal.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="IGNORED">
+ <description>Ignore the TransFer Restricted (TFR) signal.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="HANDLE_BY_STANDARD">
+ <description>Handle the incoming TRF messages according to the standard.</description>
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="Mtp3bSioSpareBitsUse">
+ <description>Indicates whether the two spare bits in the Service Information Octet (SIO) should be treated as spare or for indicating a priority level. </description>
+ <enumMember name="SPARE">
+ <description>The two spare bits in the SIO are treated as spare.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="PRIO">
+ <description>The two spare bits in the SIO are to be used for indicating a priority level.</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="Mtp3bItuVersion">
+ <description>Indicates which version of the ITU standard.</description>
+ <enumMember name="ITU_T_88">
+ <description>ITU-T -88.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="ITU_T_03_93">
+ <description>ITU-T 03/93.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="ITU_T_07_96">
+ <description>ITU-T 07/96</description>
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <struct name="Mtp3bSpAnsiTimerData">
+ <description>ANSI timers for MTP3bSpAnsi. Timervalues in 1/10 s (deciseconds).</description>
+ <structMember name="timerT1">
+ <description>Delay to avoid message mis-sequencing on changeover.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT2">
+ <description>Timer for waiting for a COO or a COA.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT3">
+ <description>Delay to avoid message mis-sequencing on a time controlled diversion change back.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4">
+ <description>Timer for waiting for CBA, first attempt.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT5">
+ <description>Timer for waiting for CBA, second attempt
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT6">
+ <description>Timer for delay to avoid message mis-sequencing on controlled rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>9</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT8">
+ <description>Timer for delay to prohibit sending of TFP messages via the response method. This is a STP specific parameter, which is ignored when configured as an endpoint.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT10">
+ <description>Timer for waiting to repeat sending of RST periodically.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>400</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT12">
+ <description>Waiting for uninhibit acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT13">
+ <description>Timer for waiting for force uninhibit.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT14">
+ <description>Timer for waiting for inhibition acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT15">
+ <description>Timer waiting to start signaling route set congestiontest. Used only if the Route Set
+Congestion Test Selectoption is set to "Use Route Set Congestion test".
+
+Guiding value 20 - 30.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT16">
+ <description>Timer waiting for route set congestion status update. Used only if the Route Set
+Congestion Test Selectoption is set to "Use Route Set Congestion test"
+
+Guiding value 14 - 22.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>14</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT17">
+ <description>Delay to avoid oscillation of initial alignment failure and link restart.
+
+The value for this timer should be less than the value for timerT2.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>9</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTBsnt">
+ <description>Waiting for BSNT value from MTP-2 or SAAL (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTRetrieval">
+ <description>Timer for waiting for completion of buffer retrieval from MTP-2 or SAAL (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTStart">
+ <description>Timer for retransmission of DL_START_req if no answer received. Started when timerT17 expires. (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>1200</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTc">
+ <description>Controlling the period a route set is considered congested when a Transfer Controlled message has been received.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT30">
+ <description>Timer to limit sending of TFPs and TFRs in response to unexpected TRA and TRW. This timer is specific for STP functionality and is ignored when configured as an endpoint.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>300</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT25">
+ <description>Delay extension timer invoked on reciept of a Traffic Restart Waiting message from an adjacent SP which is restarting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>300</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT26">
+ <description>Controlling the periodic resend of Traffic Restart Waiting messages during restart of the local node.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>120</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT27">
+ <description>Timer enforcing a minimum node unavailablility period during MTP restart.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT28">
+ <description>Delay timer controlling a timed reaction of the restart of an adjacent node.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT29">
+ <description>Timer controlling the response of the receipt of Traffic Restart messages from an adjacent node.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>600</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT20">
+ <description>Controlling the periodic resend of Local Inhibit Change Message.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>1000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT21">
+ <description>Controlling the periodic resend of Remote Inhibit Test Message.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>1000</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT22">
+ <description>Delay on commencement of MTP Restart to allow the node to rebuild an accurate routing table based on messages for adjacent nodes.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>600</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT23">
+ <description>Supervision timer for routing updates on MTP Restart.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>40</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT31">
+ <description>Timer controlling the detection of false link congestion.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTDlack">
+ <description>Timer pending an acknowledge from the network layer for a DL_ACK_REQ.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerSltm">
+ <description>Timer for sending SLTM periodically.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>400</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerSlta">
+ <description>Supervision timer for SLTA message (time within SLTA should arrive).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaTack">
+ <description>Timer used for message acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaPeriodicAudit">
+ <description>Timer used for audit procedure.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>300</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT1">
+ <description>Delay to avoid mis-sequencing of messages when an association fails.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT3">
+ <description>Delay to avoid mis-sequencing of messages when an association becomes active.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT6">
+ <description>Delay to avoid mis-sequencing on controlled rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT8">
+ <description>Delay to prohibit sending of DUNA messages via the response method.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT40">
+ <description>Delay to avoid message mis-sequencing on controlled/forced rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT41">
+ <description>Timer controlloing the traffic activation delay during restart phase.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT42">
+ <description>The forever interval period for trying association after an unsiccessfull trial.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaTc">
+ <description>Timer controlling the period a route set is considered congested when a SCON message has been received.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaTassocack">
+ <description>Timer used for SCTP_ASSOCIATE_REQ message acknowledgement. This is the maximum time to wait for the SCTP_COMMUP_IND mesage before considering it to be an error.
+It should be longer than the time a message spends to reach the most distant destination, be processed and returned.</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <struct name="Mtp3bSpTtcTimerData">
+ <description>TTC timers for MTP3bSpTtc. Timervalues in 1/10 s (deciseconds).</description>
+ <structMember name="timerT1">
+ <description>Delay to avoid message mis-sequencing on changeover.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT2">
+ <description>Timer for waiting for a COO or a COA.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT3">
+ <description>Delay to avoid message mis-sequencing on a time controlled diversion change back.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4">
+ <description>Timer for waiting for CBA, first attempt.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT6">
+ <description>Timer for delay to avoid message mis-sequencing on controlled rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>9</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT8">
+ <description>Timer for delay to prohibit sending of TFP messages via the response method. This is a STP specific parameter, which is ignored when configured as an endpoint.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT10">
+ <description>Timer for waiting to repeat sending of RST periodically.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>400</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT17">
+ <description>Delay to avoid oscillation of initial alignment failure and link restart.
+
+The value for this timer should be less than the value for timerT2.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>9</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerSrt">
+ <description>Timer pending a Signalling Route Test Acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTBsnt">
+ <description>Waiting for BSNT value from MTP-2 or SAAL (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTRetrieval">
+ <description>Timer for waiting for completion of buffer retrieval from MTP-2 or SAAL (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTStart">
+ <description>Timer for retransmission of DL_START_req if no answer received. Started when timerT17 expires. (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>1200</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTc">
+ <description>Controlling the period a route set is considered congested when a Transfer Controlled message has been received.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT15">
+ <description>Timer waiting to start signaling route set congestiontest. Used only if the Route Set
+Congestion Test Selectoption is set to "Use Route Set Congestion test".
+
+Guiding value 20 - 30.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT16">
+ <description>Timer waiting for route set congestion status update. Used only if the Route Set
+Congestion Test Selectoption is set to "Use Route Set Congestion test"
+
+Guiding value 14 - 22.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>14</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTDlack">
+ <description>Timer pending an acknowledge from the network layer for a DL_ACK_REQ.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <struct name="Mtp3bSpAnsiPriorityData">
+ <description>Priority attributes for MTP3b SP of the ANSI standard.</description>
+ <structMember name="prioSlt">
+ <description>The prioSlt attribute sets the priority for the
+ Signalling Link Test Message and Acknowledge (SLTM / SLTA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioCo">
+ <description>The prioCo attribute sets the priority for the ChangeOver Order and Acknowledge (COO/COA) or eXtended Change over Order and Acknowledge (XCO/XCA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet)
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioCb">
+ <description>The prioCb attribute sets the priority for the
+ Change Back Declaration and Acknowledge (CBD / CBA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioEc">
+ <description>The prioEc attribute sets the priority for the
+Emergency Change over Order and Acknowledge (ECO / ECA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioRst">
+ <description>The prioRst attribute sets the priority for the
+signalling Route Set Test (RST) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioTra">
+ <description>The prioTra attribute sets the priority for the
+Traffic Restart Allowed signal (TRA) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioUpu">
+ <description>The prioUpu attribute sets the priority for the
+ User Part Unavailable (UPU) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioLink">
+ <description>The prioLink attribute sets the priority for link related messages when issued by the MTP3b itself. The messages are :
+
+Link INhibit (LIN), Link UNinhibit (LUN),
+Link Inhibit Denied (LID),
+Link Inhibit Acknowledge (LIA),
+Link Uninhibit Acknowledge (LUA),
+Link Forced Uninhibit (LFU),
+Link Local inhibit Test (LLT) and
+Link Remote inhibit Test (LRT)
+
+When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ </struct>
+
+ <struct name="Mtp3bSpTtcPriorityData">
+ <description>Priority attributes for MTP3b SP of the TTC standard.</description>
+ <structMember name="prioCo">
+ <description>The prioCo attribute sets the priority for the ChangeOver Order and Acknowledge (COO/COA) or eXtended Change over Order and Acknowledge (XCO/XCA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet)
+.</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioCb">
+ <description>The prioCb attribute sets the priority for the
+ Change Back Declaration and Acknowledge (CBD / CBA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioEc">
+ <description>The prioEc attribute sets the priority for the
+Emergency Change over Order and Acknowledge (ECO / ECA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioRst">
+ <description>The prioRst attribute sets the priority for the
+signalling Route Set Test (RST) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioTfa">
+ <description>The prioTfa attribute sets the priority for the Transfer Allowed, TFA, messages.
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioRt">
+ <description>The priority indicator used for indicating message priority for signalling route test messages (SRT/SRA).
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioTfc">
+ <description>The priority indicator used for indicating the message prioirity for TFC.
+</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ </struct>
+
+ <enum name="Mtp3bSpPriorityLevel">
+ <description>Indicates the priority level for MTP 3.</description>
+ <enumMember name="LOWEST">
+ <description>Lowest priority setting.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="LOW">
+ <description>Low priority setting.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="HIGH">
+ <description>High priority setting.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="HIGHEST">
+ <description>Highest priority setting.</description>
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <struct name="Mtp3bSpChinaTimerData">
+ <description>China timers for MTP3bSpChina. Timervalues in 1/10 s (deciseconds).</description>
+ <structMember name="timerSlta">
+ <description>Supervision timer for SLTA message (time within SLTA should arrive).
+
+Timer T1 in ITU Q.707 standard.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerSltm">
+ <description>Timer for sending SLTM periodically.
+
+Timer T2 in ITU Q.707 standard.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>400</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT1">
+ <description>Delay to avoid message mis-sequencing on changeover.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT10">
+ <description>Timer for waiting to repeat sending of RST periodically.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>400</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT12">
+ <description>Waiting for uninhibit acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT13">
+ <description>Timer for waiting for force uninhibit.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT14">
+ <description>Timer for waiting for inhibition acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT17">
+ <description>Delay to avoid oscillation of initial alignment failure and link restart.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>9</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT18">
+ <description>Supervision timer for the first phase of a restarting STP. This is an STP specific parameter, which is ignored when configured as an endpoint.
+
+Unit: deciseconds (1/10 second).
+</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>200</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT19">
+ <description>Controlling the response of the receipt of a traffic restart message from an adjacent node.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>40</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT2">
+ <description>Timer for waiting for a COO or a COA.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT20">
+ <description>Overall MTP restart timer at the restarting MTP.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>40</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT21">
+ <description>Overall MTP restart timer at an adjacent signalling point to a restarting MTP.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>300</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT22">
+ <description>Local inhibit test timer.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>2500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT23">
+ <description>Remote inhibit test timer.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>2500</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT3">
+ <description>Delay to avoid message mis-sequencing on a time controlled diversion change back.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT4">
+ <description>Timer for waiting for CBA, first attempt.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT5">
+ <description>Timer for waiting for CBA, second attempt
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT6">
+ <description>Timer for delay to avoid message mis-sequencing on controlled rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>9</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT8">
+ <description>Timer for delay to prohibit sending of TFP messages via the response method. This is a STP specific parameter, which is ignored when configured as an endpoint.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTBsnt">
+ <description>Waiting for BSNT value from MTP-2 or SAAL (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTc">
+ <description>Controlling the period a route set is considered congested when a Transfer Controlled message has been received.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTRetrieval">
+ <description>Timer for waiting for completion of buffer retrieval from MTP-2 or SAAL (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTStart">
+ <description>Timer for retransmission of DL_START_req if no answer received. Started when timerT17 expires. (not standard timer).
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>1200</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaTack">
+ <description>Timer used for message acknowledgement.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaPeriodicAudit">
+ <description>Timer used for audit procedure.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>300</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT1">
+ <description>Delay to avoid mis-sequencing of messages when an association fails.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT3">
+ <description>Delay to avoid mis-sequencing of messages when an association becomes active.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT6">
+ <description>Delay to avoid mis-sequencing on controlled rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT8">
+ <description>Delay to prohibit sending of DUNA messages via the response method.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT40">
+ <description>Delay to avoid message mis-sequencing on controlled/forced rerouting.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT41">
+ <description>Timer controlloing the traffic activation delay during restart phase.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaT42">
+ <description>The forever interval period for trying association after an unsiccessfull trial.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaTc">
+ <description>Timer controlling the period a route set is considered congested when a SCON message has been received.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT15">
+ <description>Timer waiting to start signaling route set congestiontest. Used only if the Route Set
+Congestion Test Selectoption is set to "Use Route Set Congestion test".
+
+Guiding value 20 - 30.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerT16">
+ <description>Timer waiting for route set congestion status update. Used only if the Route Set
+Congestion Test Selectoption is set to "Use Route Set Congestion test"
+
+Guiding value 14 - 22.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>14</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerTDlack">
+ <description>Timer pending an acknowledge from the network layer for a DL_ACK_REQ.
+
+Unit: deciseconds (1/10 second).</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="timerM3uaTassocack">
+ <description>Timer used for SCTP_ASSOCIATE_REQ message acknowledgement. This is the maximum time to wait for the SCTP_COMMUP_IND mesage before considering it to be an error.
+It should be longer than the time a message spends to reach the most distant destination, be processed and returned.</description>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>20</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <enum name="Mtp3bNetworkIndTtc">
+ <description>Indicates which type of geographical network, e.g. national, international, etc..
+
+Note: Only for TTC.</description>
+ <enumMember name="NATIONAL_NETWORK">
+ <description>National network.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="SPARE">
+ <description>Spare (for international use only).</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="INTERNATIONAL_NETWORK">
+ <description>International Network.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="SPARE_1">
+ <description>Spare.</description>
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <enum name="Mtp3bUsageState">
+ <description>There are three possible states for the usageState attribute:
+
+- idle, the Mtp3bSl carries no traffic.
+- active, the Mtp3bSl is working normally, and there is traffic, and it is not congested.
+- busy, the Mtp3bSl is working but is congested (traffic is routed on other links).</description>
+ <enumMember name="IDLE">
+ <description>idle, the Mtp3bSl carries no traffic.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="ACTIVE">
+ <description>active, the Mtp3bSl is working normally, and there is traffic, and it is not congested.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="BUSY">
+ <description>busy, the Mtp3bSl is working but is congested (traffic is routed on other links).</description>
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="Mtp3bProceduralState">
+ <description>The procedural state of the link.
+
+0 - not initialized
+1 - initialized</description>
+ <enumMember name="NOT_INITIALIZED">
+ <description>0 - not initialized.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="INITIALIZED">
+ <description>1 - initialized.</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="NodeBehaviourType">
+ <description>The nodeBehaviorType attribute represents the MTP3b node type.</description>
+ <enumMember name="SEP">
+ <description>Signaling End Point.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="SEP_STP">
+ <description>Signalling Transfer and End Point, i.e the signalling point is of both type Signalling End Point (SEP) and Signalling Transfer Point (STP).</description>
+ <value>4</value>
+ </enumMember>
+ <enumMember name="SGW_STP_SEP">
+ <description>Signaling GateWay, Signaling End Point and Signalling Transfer Point, i.e the signalling point is of both type Signalling Transfer Point (STP), Signaling End Point (SEP) and Signaling GateWay (SGW).</description>
+ <value>5</value>
+ </enumMember>
+ </enum>
+
+ <struct name="Mtp3bSpChinaPriorityData">
+ <description>Priority attributes for MTP3b SP of the China standard.</description>
+ <structMember name="prioSlt">
+ <description>The prioSlt attribute sets the priority for the
+ Signalling Link Test Message and Acknowledge (SLTM / SLTA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioCo">
+ <description>The prioCo attribute sets the priority for the ChangeOver Order and Acknowledge (COO/COA) or eXtended Change over Order and Acknowledge (XCO/XCA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet)
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioCb">
+ <description>The prioCb attribute sets the priority for the
+ Change Back Declaration and Acknowledge (CBD / CBA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioEc">
+ <description>The prioEc attribute sets the priority for the
+Emergency Change over Order and Acknowledge (ECO / ECA) messages when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioRst">
+ <description>The prioRst attribute sets the priority for the
+signalling Route Set Test (RST) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioTra">
+ <description>The prioTra attribute sets the priority for the
+Traffic Restart Allowed signal (TRA) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioUpu">
+ <description>The prioUpu attribute sets the priority for the
+ User Part Unavailable (UPU) message when issued by the MTP3b itself. When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ <structMember name="prioLink">
+ <description>The prioLink attribute sets the priority for link related messages when issued by the MTP3b itself. The messages are :
+
+Link INhibit (LIN), Link UNinhibit (LUN),
+Link Inhibit Denied (LID),
+Link Inhibit Acknowledge (LIA),
+Link Uninhibit Acknowledge (LUA),
+Link Forced Uninhibit (LFU),
+Link Local inhibit Test (LLT) and
+Link Remote inhibit Test (LRT)
+
+When a message is transferred from the MTP3b the message priority uses the two spare bits in the SIO (Service Information Octet).
+
+lowest:0
+low:1
+high:2
+highest:3</description>
+ <enumRef name="Mtp3bSpPriorityLevel">
+ <defaultValue>HIGHEST</defaultValue>
+ </enumRef>
+ </structMember>
+ </struct>
+
+ <enum name="Mtp3bRouteType">
+ <description>The type of Signalling Route.</description>
+ <enumMember name="TDM_ATM">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="IP">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="HomingState">
+ <enumMember name="SINGLE_HOMED_1">
+ <description>Single-homed with ipAddress1.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="SINGLE_HOMED_2">
+ <description>Single-homed with ipAddress2.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="MULTI_HOMED">
+ <description>Multihomed association with ipAddress1 and
+ipAddress2
+</description>
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <enum name="RouteState">
+ <description>The state of the signaling route.</description>
+ <enumMember name="NOT_BLOCKED">
+ <description>The signaling route is not blocked.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="BLOCKED">
+ <description>The signaling route is blocked.</description>
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="WorkingMode">
+ <enumMember name="hostMode">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="routerMode">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="OspfMetricType">
+ <description>Open Shortest Path First metric type.</description>
+ <enumMember name="comparableCost">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="nonComparable">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="RouteType">
+ <description>The types of the routes found in the IP routing table.</description>
+ <enumMember name="INET_RTPROTO_OTHER">
+ <description>The source of information is unknown.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="INET_RTPROTO_LOCAL">
+ <description>Route created from local configuration data (both static and interface routes).
+Each interface created gets an entry in the routing table of the RO.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="INET_RTPROTO_NETMGMT">
+ <description>Route added by SNMP.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="INET_RTPROTO_OSPF">
+ <description>Route added by OSPF.</description>
+ <value>13</value>
+ </enumMember>
+ <enumMember name="INET_RTPROTR_ICMP">
+ <description>Route added by ICMP redirect message.</description>
+ <value>4</value>
+ </enumMember>
+ </enum>
+
+ <exception name="RouteNotFoundException">
+ <description>Invalid IP route has been given as a parameter to an action.</description>
+ <exceptionParameter name="routeNotFound">
+ <description>Exception message.</description>
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <exception name="InvalidRouteException">
+ <description>Invalid IP route has been given as a parameter to an action.</description>
+ <exceptionParameter name="invalidRoute">
+ <dataType>
+ <string/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+ <enum name="MauDuplexMode">
+ <enumMember name="HALF_DUPLEX">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="FULL_DUPLEX">
+ <value>1</value>
+ </enumMember>
+ </enum>
+
+ <enum name="ControllerMode">
+ <description>The controller mode of a physical interface.</description>
+ <enumMember name="CONTROLLER_E1">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="CONTROLLER_T1">
+ <value>2</value>
+ </enumMember>
+ <enumMember name="CONTROLLER_J1">
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <struct name="OspfAreaRange">
+ <description>ipAddress - the subnet address of the range.
+subnetMask - IP subnet mask of the range to be added.
+advertise - indicates whether the area range should be advertised into OSPF.
+</description>
+ <structMember name="ipAddress">
+ <string/>
+ </structMember>
+ <structMember name="subnetMask">
+ <description>Note! The subnet has to be contigious. That is, has the LSB set to 0 (zero).
+
+Example:
+
+255.255.255.X
+
+Contiguous subnet mask:
+11111111.11111111.11111111.11111110 (X = 254)
+11111111.11111111.11111111.11111100 (X = 252)
+
+Not-contiguous subnet mask:
+11111111.11111111.11111111.11111010 (X = 250)
+</description>
+ <string/>
+ </structMember>
+ <structMember name="advertise">
+ <boolean/>
+ </structMember>
+ </struct>
+
+ <struct name="RoutingTableEntry">
+ <description>IP routing table entry.</description>
+ <structMember name="destinationIpAddr">
+ <description>The destination IP address.</description>
+ <string/>
+ </structMember>
+ <structMember name="destinationNetworkMask">
+ <description>The destination IP network mask.</description>
+ <string/>
+ </structMember>
+ <structMember name="nextHopIpAddr">
+ <description>The next hop IP address.</description>
+ <string/>
+ </structMember>
+ <structMember name="routeMetric">
+ <description>The route metric.</description>
+ <long/>
+ </structMember>
+ <structMember name="routeType">
+ <description>The route type.</description>
+ <enumRef name="RouteType">
+ </enumRef>
+ </structMember>
+ <structMember name="interfaceName">
+ <description>The interface name.</description>
+ <string/>
+ </structMember>
+ <structMember name="redistribute">
+ <description>Indicates if the route should be redistributed.</description>
+ <boolean/>
+ </structMember>
+ <structMember name="active">
+ <description>Indicates if the route is active.</description>
+ <boolean/>
+ </structMember>
+ </struct>
+
+ <enum name="AutoConfigurationMode">
+ <description>Denotes whether the autoConfiguration mode for the IpAccessHost is turned on or off.</description>
+ <enumMember name="ON">
+ <value>1</value>
+ </enumMember>
+ <enumMember name="OFF">
+ <value>2</value>
+ </enumMember>
+ </enum>
+
+ <enum name="Aal5TpSelectionModes">
+ <description>In case 'NO_PREFERENCE', 'LOCAL_MP_SELECT_VCC_AT_LINK_UP', LOCAL_MP_PEER_SELECTION_VCC' or 'LOCAL_MP_ACTIVE_RESELECTION' is selected the IpAtmLink MO will prefer Aal5TpVccTp on local MP (i.e. Aal5TpVccTp executing on the same MP as the IpAtmLink), but other Aal5TpVccTp will be accepted if needed.
+
+In case 'ONLY_LOCAL_MP' is selected, the ipAtmLink (Inet Link) will consider Aal5TpVccTp residing on other MPs as a malfunction and discard the usage of them. No InvArp sending will be performed on them and all incomming trafic on them will be discarded. If no local Aal5TpVccTp exists the operational state of the link will be changed to disabled.</description>
+ <enumMember name="NO_PREFERENCE">
+ <value>0</value>
+ </enumMember>
+ <enumMember name="LOCAL_MP_SELECT_VCC_AT_LINK_UP">
+ <description>Prefer termination on local MP, select Vcc when link goes up.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="LOCAL_MP_PEER_SELECTION_VCC">
+ <description>Prefer termination on local MP, follow peer selection of Vcc.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="LOCAL_MP_ACTIVE_RESELECTION">
+ <description>Prefer termination on local MP, active reselection to new Aal5TpVccTp as soon as a better choice exists.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="ONLY_LOCAL_MP">
+ <description>Restricted to local MP, follow peer selection if termination is on local MP.
+</description>
+ <value>4</value>
+ </enumMember>
+ </enum>
+
+ <enum name="AlarmReport">
+ <description>Alarm report for the Virtual path connection termination point.
+RDI - Remote defect indication
+LOC - Loss of continuity
+AIS - Alarm indication signal</description>
+ <enumMember name="ALARM_LOC">
+ <description>For alarms of type Loss of continuity.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="ALARM_LOC_RDI">
+ <description>For alarms of type Loss of continuity and Remote defect indication.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="ALARM_AIS_LOC">
+ <description>For alarms of type Alarm indication signal and Loss of continuity.</description>
+ <value>6</value>
+ </enumMember>
+ <enumMember name="ALARM_AIS_RDI_LOC">
+ <description>For alarms of type Alarm indication signal, Remote defect indication and Loss of continuity.</description>
+ <value>7</value>
+ </enumMember>
+ </enum>
+
+ <enum name="AtmCounterMode">
+ <enumMember name="PM_MODE_OFF">
+ <description>Performance monitoring is turned off. PM counters give irrelevant values.</description>
+ <value>0</value>
+ </enumMember>
+ <enumMember name="PM_MODE_ONLYCOUNT">
+ <description>Performance monitoring counters are active
+</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="PM_MODE_FPM">
+ <description>FPM, Forward Performance Monitoring activated.
+
+Performance monitoring counters are active
+</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="PM_MODE_BR">
+ <description>Backward reporting, BR, cells are generated.
+
+Performance monitoring counters are active
+</description>
+ <value>4</value>
+ </enumMember>
+ <enumMember name="PM_MODE_FPM_BR">
+ <description>FPM, Forward Performance Monitoring activated.
+
+Backward reporting, BR, cells are generated.
+
+Performance monitoring counters are active
+</description>
+ <value>6</value>
+ </enumMember>
+ </enum>
+
+ <enum name="AtmNomPmBlkSize">
+ <description>Nominal performance monitoring, PM, blocksize. The minimum number of ATM cells to send before sending a Forward Performance Monitoring, FPM, cell.</description>
+ <enumMember name="NOM_PM_BLKSIZE_2_7">
+ <description>Nominal performance monitoring, PM, block size, 2e7 (2 to the power of 7).</description>
+ <value>128</value>
+ </enumMember>
+ <enumMember name="NOM_PM_BLKSIZE_2_8">
+ <description>Nominal performance monitoring, PM, block size, 2e8 (2 to the power of 8).</description>
+ <value>256</value>
+ </enumMember>
+ <enumMember name="NOM_PM_BLKSIZE_2_9">
+ <description>Nominal performance monitoring, PM, block size, 2e9 (2 to the power of 9).</description>
+ <value>512</value>
+ </enumMember>
+ <enumMember name="NOM_PM_BLKSIZE_2_10">
+ <description>Nominal performance monitoring, PM, block size, 2e10 (2 to the power of 10).</description>
+ <value>1024</value>
+ </enumMember>
+ <enumMember name="NOM_PM_BLKSIZE_2_11">
+ <description>Nominal performance monitoring, PM, block size, 2e11 (2 to the power of 11).</description>
+ <value>2048</value>
+ </enumMember>
+ <enumMember name="NOM_PM_BLKSIZE_2_12">
+ <description>Nominal performance monitoring, PM, block size, 2e12 (2 to the power of 12).</description>
+ <value>4096</value>
+ </enumMember>
+ <enumMember name="NOM_PM_BLKSIZE_2_13">
+ <description>Nominal performance monitoring, PM, block size, 2e13 (2 to the power of 13).</description>
+ <value>8192</value>
+ </enumMember>
+ <enumMember name="NOM_PM_BLKSIZE_2_14">
+ <description>Nominal performance monitoring, PM, block size, 2e14 (2 to the power of 14).</description>
+ <value>16384</value>
+ </enumMember>
+ <enumMember name="NOM_PM_BLKSIZE_2_15">
+ <description>Nominal performance monitoring, PM, block size, 2e15 (2 to the power of 15).</description>
+ <value>32768</value>
+ </enumMember>
+ </enum>
+
+ <enum name="ServiceCategory">
+ <enumMember name="SERVICE_CATEGORY_CBR">
+ <description>Service category Constant Bit rate, CBR.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="SERVICE_CATEGORY_UBR">
+ <description>Service category Unspecified Bit rate, UBR.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="SERVICE_CATEGORY_UBR_PLUS">
+ <description>Service category Unspecified Bit rate+, UBR+. UBR+ guarantees a certain bandwidth. If higher bandwidth is used it will be handled as UBR.</description>
+ <value>3</value>
+ </enumMember>
+ </enum>
+
+ <enum name="AtmQos">
+ <description>ATM's Quality of Service classes.
+
+The ATM layer system provides four QoS classes, numbered 1 to 4, where CLASS_ONE gives the best QoS in regards to Cell Loss Ratio &lt;CLR&gt; and Cell Delay Variation &lt;CDV&gt; and CLASS_FOUR doesn't give any QoS guarantees. CLASS_ONE and CLASS_TWO are the only classes applicable for real time traffic.</description>
+ <enumMember name="CLASS_ONE">
+ <description>CDV &lt; 1 ms (milliseconds), CLR &lt; 10e-8. Typically used by timing unit.</description>
+ <value>1</value>
+ </enumMember>
+ <enumMember name="CLASS_TWO">
+ <description>CDV &lt; 1 ms, CLR &lt; 10e-7. Typically used for speech.</description>
+ <value>2</value>
+ </enumMember>
+ <enumMember name="CLASS_THREE">
+ <description>CLR &lt; 10e-5. Typically used for signalling.</description>
+ <value>3</value>
+ </enumMember>
+ <enumMember name="CLASS_FOUR">
+ <description>Typically used for IP.</description>
+ <value>4</value>
+ </enumMember>
+ </enum>
+
+ <struct name="ValueOfUnex">
+ <description>The attributes in this struct represents the ATM header, (vpi, vci, pti), of the last recieved unexpected cell.</description>
+ <structMember name="vpi">
+ <description>The ATM header vpi.</description>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="vci">
+ <description>The ATM header vci.</description>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ <structMember name="pti">
+ <description>The ATM header pti.</description>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </structMember>
+ </struct>
+
+ <class name="TransportNetwork">
+ <description>This MO structures the transport network of the managed element. It is created automatically and cannot be deleted.
+
+The local distinguished name of this MO is ManagedElement=1, TransportNetwork=1.</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="TransportNetworkId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="getAal5ForNniSaal">
+ <description>This action returns a sequnce of Aal5TpVccTp MOs that is unreserved and executes on an MP.
+
+Also the following condition has to be fullfilled:
+
+MinAal5Sdu = min (fromUserMaxSduSize, toUserMaxSduSize)
+
+roundedDownSdu = (MinAal5Sdu - (MinAal5Sdu modulo 4) +4)
+
+roundedDownSdu &gt; low boundry for maxSduSize (in NniSaalTp)
+
+Note that the values for fromUserMaxSduSize and toUserMaxSduSize is the actual values set in the Aal5TpVccTp MO.
+Also note that the attributes minAal5Sdu and roundedDownSdu is used internaly in this action.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </returnType>
+ </action>
+ <action name="getAal5ForUniSaal">
+ <description>This action returns a sequnce of Aal5TpVccTp MOs that is unreserved and executes on an MP.
+
+Also the following condition has to be fullfilled:
+
+MinAal5Sdu = min (fromUserMaxSduSize, toUserMaxSduSize)
+
+roundedDownSdu = (MinAal5Sdu - (MinAal5Sdu modulo 4) +4)
+
+roundedDownSdu &gt; low boundry for maxSduSize (in UniSaalTp)
+
+Note that the values for fromUserMaxSduSize and toUserMaxSduSize is the actual values set in the Aal5TpVccTp MO.
+Also note that the attributes minAal5Sdu and roundedDownSdu is used internaly in this action.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </returnType>
+ </action>
+ <action name="getAal2PathForAal2Pdu">
+ <description>This action returns a sequence of all unreserved Aal2PathVccTp's that have an Aal2PathId that has not been
+used by another Aal2PathDistributionUnit under the same parent (Aal2Ap).
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </returnType>
+ <parameter name="aal2Ap">
+ <in/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="getRpuForAal2Pdu">
+ <description>This action returns a sequence of all ReliableProgramUniters that has not reached the maximun number of possible reservations
+and has not already been used by other Aal2PathDistributionUnit MO's (if exists) under the same parent (Aal2Ap MO).
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </returnType>
+ <parameter name="aal2Ap">
+ <in/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="getUnreservedPluginUnits">
+ <description>This action returns a sequence of PlugInUnits that is unreserved.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </returnType>
+ </action>
+ <action name="getDs0BundlesForMtp2">
+ <description>This action returns a sequence of Ds0Bundle MOs that is unreserved and only has one (1) timeSlot set in the listOfTimeSlots.
+The attribute tdmMode in these Ds0Bundles must be enabled.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="Slot">
+ <description>The Slot MO is used to represent a slot in a subrack. A slot can hold a plug-in-unit, a board, (represented by PlugInUnit MOs).
+
+The number of slots in a subrack is specified when defining the subrack.
+
+The system will automatically create the right number of Slot MOs in the subrack at creation of the Subrack MO.
+This MO cannot be deleted by an operator.
+
+The local distinguished names of this MO's are select with identity Slot=1 in the leftmost slot with incremental numbering towards the right in the subrack.. </description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>A user friendly name associated to the managed object
+
+</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="slotState">
+ <description>Gives the state of the slot.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="SlotState">
+ <defaultValue>free</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="slotNumber">
+ <description>The number of the position from the left side, starting from 1.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long/>
+ </dataType>
+ </attribute>
+ <attribute name="SlotId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="productData">
+ <description>This product data describes the plug-in-unit that is presently inserted. The information is only available when slotState = used.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <structRef name="OperProductData"/>
+ </dataType>
+ </attribute>
+ <attribute name="upgradeGroupId">
+ <description>The upgradeGroupId is able to group a number of PIUs, all in the group can be upgraded at the same time.
+
+If upgradeGroupTypeName is "", this attribute is not used.
+</description>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="upgradeGroupTypeName">
+ <description>The upgradeGroupTypeName, together with the upgradeGroupId, define an upgrade group.
+</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="ManagedObject">
+ <description>The Managed Object MO is not part of the model. It is only used to have valid reference types for certain attributes. </description>
+ <attribute name="ManagedObjectId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="getType">
+ <returnType>
+ <string/>
+ </returnType>
+ </action>
+ <action name="getId">
+ <returnType>
+ <string/>
+ </returnType>
+ </action>
+ <action name="getParent">
+ <returnType>
+ <moRef name="ManagedObject"/>
+ </returnType>
+ </action>
+ <action name="getChildren">
+ <returnType>
+ <long/>
+ </returnType>
+ </action>
+ <action name="getFullDistinguishedName">
+ <returnType>
+ <string/>
+ </returnType>
+ </action>
+ <action name="delete">
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="MoHasChildrenException"/>
+ <raisesException name="MoReservedByOtherUserException"/>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ <raisesException name="UndeletableMoException"/>
+ <raisesException name="TransactionRequiredException"/>
+ </action>
+ <action name="getLocalDistinguishedName">
+ <returnType>
+ <string/>
+ </returnType>
+ </action>
+ <action name="create">
+ <returnType>
+ <moRef name="ManagedObject"/>
+ </returnType>
+ <raisesException name="MoNameAlreadyTakenException"/>
+ <raisesException name="AttrMissingAtCreateException"/>
+ <raisesException name="AttrNotSettableAtCreateException"/>
+ <raisesException name="IllegalParentException"/>
+ <raisesException name="MoCardinalityViolationException"/>
+ <raisesException name="NoSuchAttributeException"/>
+ <raisesException name="MoCanNotBeCreatedException"/>
+ <raisesException name="NoSuchFieldException"/>
+ <raisesException name="NotHandledAttributeTypeException"/>
+ <raisesException name="WrongAttributeTypeException"/>
+ <raisesException name="ValueOutOfRangeException"/>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ <raisesException name="TransactionRequiredException"/>
+ <raisesException name="IpException"/>
+ <raisesException name="IpFormatException"/>
+ <raisesException name="EquipException"/>
+ <raisesException name="AttrValueNotUniqueException"/>
+ <raisesException name="MaxNumberExceededException"/>
+ <raisesException name="MoReservedNotDeletableException"/>
+ </action>
+ </class>
+
+ <class name="VclTp">
+ <description>This MO is used to represent the termination of an external VC link in the node.
+
+Note that a maximum of 10 000 MO of this kind may be configured in a node.
+
+Note! The performance monitoring counters in the VclTp MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.</description>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="externalVci">
+ <description>Virtual Channel Idenitifier, VCI, value for this Virtual Channel Link, VCL.
+
+Range: 32 - 65535.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>32</min> <max>65535</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="atmTrafficDescriptorId">
+ <description>Reference to the AtmTrafficDescriptor profile.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="AtmTrafficDescriptor"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>User that have reserved this VclTp.
+
+</description>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the VclTp.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmReceivedAtmCells">
+ <description>Performance monitoring counter for number of received ATM cells.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmTransmittedAtmCells">
+ <description>Performance monitoring counter for number of transmitted ATM cells.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status of the VclTp.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="VclTpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="eteLoopBack">
+ <description>Used by VclTp to inforce a Virtual Channel end-to-end loopback.
+false=Failed, true=Succeded.
+
+Note! This action requires a transaction.
+
+</description>
+ <returnType>
+ <boolean/>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="ManagedElement">
+ <description>The Managed Element MO is the top MO in the MOM. A management application will communicate with the Managed Element MO for the purpose of monitoring it and controlling it.
+
+The ManagedElement MO is automatically created and cannot be deleted.
+
+The local distinguished name of this MO is ManagedElement=1.</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="site">
+ <description>This attribute gives information about geographical location (e.g. place name).</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>255</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="logicalName">
+ <description>This attribute gives a logical name of a site.
+
+</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>255</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="productType">
+ <description>This attribute describes the product type and is always set to the value "Node".</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>Node</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="productName">
+ <description>This attribute describes the implemented functionality. </description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>12</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="productNumber">
+ <description>This attribute uniquely identifies the product (e.g. ROF123).</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>24</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="productRevision">
+ <description>This attribute identifies the version of the product (e.g. R2A).</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>7</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ManagedElementId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="restart">
+ <description>Restart the node with an unconditional reload.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="restartRank">
+ <in/>
+ <dataType>
+ <enumRef name="RestartRank">
+ </enumRef>
+ </dataType>
+ </parameter>
+ </action>
+ </class>
+
+ <class name="Equipment">
+ <description>This Managed Object is used as a structural element for the network element, i.e. it only acts as a container for other MO:s. This MO structures the equipment of the network element.
+
+The local distinguished name of this MO is ManagedElement=1, Equipment=1.</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="EquipmentId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Subrack">
+ <description>This MO is used to represent a subrack.
+</description>
+ <attribute name="userLabel">
+ <description>A free tag that a user can associated to the this managed object. The value has no relevance for the managed system.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="switchModule">
+ <description>A reference to a SwitchModule ManagedObject, from which the SwitchModule number can be retrived. That number describes how the subrack is connected to the node, i.e. how the subrack�s cables are connected to the hub subrack. (The hub subrack has switch module number �0�).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="SwitchModule"/>
+ </dataType>
+ </attribute>
+ <attribute name="subrackType">
+ <description>There can only be one hub subrack in the node. The hub subrack is used to control switching and synchronization for the complete node.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="SubrackType">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="productType">
+ <description>This attribute describes the product type and is always set to the value "HW".</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>"HW"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeProductData">
+ <description>This product data describes the subrack that is configured to be installed.
+
+</description>
+ <mandatory/>
+ <dataType>
+ <structRef name="AdminProductData"/>
+ </dataType>
+ </attribute>
+ <attribute name="subrackPosition">
+ <description>The position of this subrack within a cabinet.
+The purpose of this attribute is to help an operator locate the source of an error by letting the system put this
+information in alarms. The system does not use this information in any other way i.e. it does not affect the
+operation of the system.
+The subrack position is an integer (1-n) stating the cabinet Id, starting from the left and a letter (A-Z) stating
+the Subrack vertical position starting from the ground, e.g. 5C.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="cabinetPosition">
+ <description>The position of the cabinet (within a group of other cabinets) in which this subrack is placed.
+The purpose of this attribute is to help an operator locate the source of an error by letting the system put this information in alarms. The system does not use this information in any other way i.e. it does not affect the operation of the system.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="SubrackId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="numberOfSlots">
+ <description>Defines the number of slot in the subrack. The default value is 28.
+
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>28</max>
+ </range>
+ <defaultValue>28</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="operationalProductData">
+ <description>The operational product data describes the subrack that is actually installed.
+
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <structRef name="OperProductData"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>A reference to the SwAllocation MO that has reserved this Subrack for Fan MO upgrades..
+The attribute is set/cleared by internal actions.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <action name="removeSlots">
+ <description>Removes the given number of Slot MOs from the model. The Slots with the highest slotNumber are removed. After the action no Slot will have apn = 0.
+The attribute numberOfSlots will be udated.
+
+If there is a child MO the action will fail and the MOHasChildrenException is thrown.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="numberOfSlotsToRemove">
+ <description>The number of slots to remove.</description>
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ </action>
+ </class>
+
+ <class name="LoadModule">
+ <description>This MO is used to represent software installed in the file system.
+
+LoadModule MO can represent files with executable code, files with text information
+(COI) or directories in Cello file system.
+
+MOs of this type are created automatically during system upgrade.
+MOs of this type are possible to create manually but a system upgrade
+is recommended to create them.
+
+Note! In order for a program to be reliable the following conditions must be fulfilled:
+
+1. The attribute 'loaderType' must be set to 'OseLoader'.
+2. The attribute 'oseProgramLoadClass' must be set to a value &gt; 100.
+3. The program must execute on a MP (Main Processor).
+
+</description>
+ <attribute name="userLabel">
+ <description>Free tag for marking this managed object.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="productData">
+ <description>Product information data.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="AdminProductData"/>
+ </dataType>
+ </attribute>
+ <attribute name="loadModuleFilePath">
+ <description>The path to this load module in the file system, including the file name.
+
+Example: /c/load_modules/CXC112874R1A01
+where /c/load_modules/ is the directory and CXC112874R1A01 is the file name.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="loaderType">
+ <description>The type of the program loader.
+
+Note! This corresponds to LoaderName in the Upgrade Control File (UCF).</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="LoadModuleLoaderType">
+ <defaultValue>OseLoader</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="otherLoaderName">
+ <description>This attribute must have a value if the loaderType attribute equals other.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="preLoad">
+ <description>A recommendation to the system to (if possible) cache this load module close to where its program(s) execute(s), e.g. in a flash file system. The purpose of this attribute is to enable faster loading at restart of programs referring to this load module.
+
+
+
+
+</description>
+ <dataType>
+ <enumRef name="LoadModulePreLoadType">
+ <defaultValue>no</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="fileFormat">
+ <description>The file format (RPDOUT, html, java, fpga, ...).</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="oseProgramLoadClass">
+ <description>Specifies in which load phase programs of this load module should be started.
+
+Note: If the LoadModule is a java archive file (.jar) it will be loaded in the load phase of the java machine rather than according to its own oseProgramLoadClass.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="LoadClass">
+ <defaultValue>application</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reliableProgramLabel">
+ <description>Reliable program identity.
+Compare this to the reliableProgramLabel in ReliableProgramUniter MO.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="isDirectory">
+ <description>Indicates if the load module is a file or directory.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="oseProgramPoolSize">
+ <description>This attribute sets the size of the program pool size. In the referenced loadModule there is
+possible to set this value at create.
+This value will then be fetched by program and used at create if no value is submitted at
+create of the program Mo.
+The referenced load module has a default size defined at compile time which is used if no
+value is submitted at create of loadModule or the program Mo.
+
+Note! The value of this attribute is overwritten during Software Upgrade.
+
+Unit is byte.
+
+</description>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="oseProgramHeapSize">
+ <description>This attribute sets the size of the program heap size. In the referenced loadModule there is possible to set this value at create. This value will then be fetched by program and used at create if no value is submitted at create of the program Mo.
+The referenced load module has a default size defined at compile time which is used if no value is submitted at create of loadModule or the program Mo.
+
+Note! The value of this attribute is overwritten during Software Upgrade.
+
+Unit is byte.
+
+</description>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="programMustBeSingleton">
+ <description>Indicator whether the (OSE) program must be a singleton or not.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="moppletEntries">
+ <description>Contains all class that are to be initialised and started when the JVM restarts.
+Technical note: The class name must specify the full package and class name in standard Java syntax, e.g. "se.ericsson.cello.X" ; must implement the se.ericsson.cello.moframework.Mopplet interface and be found in this LoadModule.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <sequence>
+ <string>
+ <defaultValue/>
+ </string>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="LoadModuleId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByUpgradePackage">
+ <description>Indicates whether this MO has been reserved by the UpgradePackage MO or not.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Synchronization">
+ <description>This MO is used to administer synchronization references for the network synchronization function and to view the system clock state of Timing Unit boards.
+
+Synchronization can have 0 to 8 relations to other MOs. The only valid MOs where relations can exist are E1Physpathterm, J1Physpathterm, T1Physpathterm, Os155SpiTtp, TU Synchronization Reference, and ManagedObject (for the non-Cello RXI820 MO) MOs. Note that maximum number of relations to these MOs is 8 all together.
+
+The synchronization MO is automatically created and cannot be deleted.
+
+Note: An external ManagedObject that wishes to be connected to the Synchronization MO must implement the following interface se.ericsson.cello.equipment.SyncReservable!
+
+The local distinguished name of this MO is ManagedElement=1,TransportNetwork=1,Synchronization=1
+
+.</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="degradationIsFault">
+ <description>Controls whether synchronization reference degradation (e.g. signal level degradation) is interpreted as a synchronization reference fault or not. Attribute value is only applicable for traffic carrying synchronization references</description>
+ <dataType>
+ <enumRef name="FaultCriteria">
+ <defaultValue>degrNotFault</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="systemClockA">
+ <description>State of system clock signal on Timing Unit A.
+Note that system clock generated by TU A (TU in slot 4) has higher priority than TU B (TU in slot 5) system clock, i.e. each device board uses system clocks according to this priority order.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="ClockState">
+ <defaultValue>unknownMode</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="systemClockB">
+ <description>State of system clock signal on Timing Unit B. Note that system clock generated by TU A (TU in slot 4) has higher priority than TU B (TU in slot 5) system clock, i.e. each device board uses system clocks according to this priority order.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="ClockState">
+ <defaultValue>unknownMode</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="syncReference">
+ <description>Set of synchronization reference physical resources. An MO reference to an TU synchronization reference MO implementation.
+A synchronization reference in added to the system by using action AddSyncRefResource.
+Note: if this attributes has value "Non-existing MO reference" then all the respective attributes of type sequence of 8 are not applicable.
+
+Note: The length of this sequence is always 8.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ <length>8</length>
+ <nonUnique/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="syncRefPriority">
+ <description>Synchronization reference priority.
+1 represents the highest and 8 the lowest priority. Every synchronization reference must have unique priority value. Value 0 means not applicable, that no synchronization with this priority is defined.
+This attribute is mandatory when adding a synchronization reference to the system (by using action addSyncRefResource).
+A priority value can be changed with the changeSyncRefPriority action provided that the priority is not already assigned to some other SyncRefResource.
+
+Note: The length of this sequence is always 8.</description>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <long>
+ <range>
+ <min>0</min> <max>8</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ <length>8</length>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="syncRefActivity">
+ <description>Set of synchronization reference activity attributes.
+
+Note: The length of this sequence is always 8.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <enumRef name="RefActivity">
+ <defaultValue>inactive</defaultValue>
+ </enumRef>
+ <length>8</length>
+ <nonUnique/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="syncRefStatus">
+ <description>Set of synchronization reference status attributes.
+
+Note: The length of this sequence is always 8.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <enumRef name="RefState">
+ <defaultValue>failed</defaultValue>
+ </enumRef>
+ <length>8</length>
+ <nonUnique/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="SynchronizationId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="systemClockRedundancy">
+ <description>Indicates if the node is redundant from Network Synchronization functions point of view.</description>
+ <dataType>
+ <enumRef name="SystemClockRedundancy">
+ <defaultValue>SYSTEM_CLOCK_USERS_USE_PLANE_A</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <action name="addSyncRefResource">
+ <description>This action adds one synchronization reference to the system. As a result of successful action, one set of attributes (attributes of type sequence of 8) is added to Synchronization MO.
+Parameters:
+syncReference: Managed object implementation, to which a mo-reference is to be added. See description of attribute SyncReference.
+syncPriority: Priority of synchronization reference. Each synchronization reference must have unique priority value, this must be checked by synchronization MO.
+
+Description of exceptions:
+- AlreadyRegistered: this reference is already registered
+- MaxNoOfRefRegistered: maximum number (8) of synchronization references already present
+- PriorityAlreadyInUse: syncPriority is identical with an existing synchronization reference priority
+- PriorityOutOfRange: invalid syncPriority value
+- InvalidMoReference: invalid syncReference for registration as a synchronization reference (invalid MO type)
+- NotPermitted: syncReference does not allow SyncReserve to be performed
+
+Note: An external ManagedObject that wishes to be connected to the Synchronization MO must implement the following interface se.ericsson.cello.equipment.SyncReservable!
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="syncReference">
+ <in/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </parameter>
+ <parameter name="syncPriority">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="AlreadyRegisteredException"/>
+ <raisesException name="MaxNoOfRefRegisteredException"/>
+ <raisesException name="PriorityAlreadyInUseException"/>
+ <raisesException name="PriorityOutOfRangeException"/>
+ <raisesException name="InvalidMoReferenceException"/>
+ <raisesException name="NotPermittedException"/>
+ </action>
+ <action name="removeSyncRefResource">
+ <description>This action removes one synchronization reference that has previously been added.
+(In future releases, this action should include a check whether the synchronization reference to be removed is the only existing synchronization reference. In that case, the user is asked for a confirmation to remove the last synchronization reference.)
+Parameters:
+syncReference: Managed object implementation, to which a mo-reference currently exists, but is now to be removed. See description of attribute SyncReference.
+
+Description of exceptions:
+- NotRegistered: synchronization reference is not registered
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="syncReference">
+ <in/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </parameter>
+ <raisesException name="NotRegisteredException"/>
+ </action>
+ <action name="changeSyncRefPriority">
+ <description>This action changes the synchronization priority of one previously registered synchronization reference resource.
+Parameters:
+syncReference: Managed object implementation, for which the synchronization priority is to be changed. See description of attribute syncReference.
+syncPriority: The new priority of synchronization reference. Each synchronization reference must have unique priority value, this must be checked by synchronization MO.
+
+Description of exceptions:
+- PriorityAlreadyInUse: syncPriority is identical with an existing synchronization reference priority
+- PriorityOutOfRange: invalid syncPriority value
+- NotRegistered: synchronization reference is not registered
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="syncReference">
+ <in/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </parameter>
+ <parameter name="syncPriority">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="PriorityAlreadyInUseException"/>
+ <raisesException name="PriorityOutOfRangeException"/>
+ <raisesException name="NotRegisteredException"/>
+ </action>
+ <action name="resetLossOfTracking">
+ <description>This action resets the detected Loss of Tracking error condition of one synchronization reference. After reset the synchronization reference is usable again.
+Parameters:
+syncReference: Specifies the synchronization reference for which the Loss of Tracking status is to be reset.
+
+Description of exceptions:
+- NotRegistered: synchronization reference is not registered
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="syncReference">
+ <in/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </parameter>
+ <raisesException name="NotRegisteredException"/>
+ </action>
+ </class>
+
+ <class name="SccpApLocal">
+ <description>This Managed Object represents an SCCP Local Access Point. An SCCP AP instance is a logical point in the SCCP network at which an SCCP user can access the services provided by the SCCP and the SCCP can deliver its services to the SCCP user. The SCCP Access Point is identified by a SubSystem Number (SSN).
+
+A local SccpAp represents an access point in the own node.
+
+The performance monitoring counters found in SccpApLocal MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is a shutdown request from the CLI (Cluster Interface).</description>
+ <attribute name="SccpApLocalId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the SCCP AP. The operability of the SCCP AP is described by this attribute which has two possible values:
+
+Disabled: The SCCP AP is totally inoperable and unable to provide the service to the user.
+
+Enabled: The SCCP AP is partly or fully operable and available for use.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="ssN">
+ <description>The sub system number, SSN, of the SCCP Access Point. Note that this has to be a unique number.
+
+If the SccpAp is local then the SSN has to be unique among all other SccpAp MOs under the same SccpSp MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>2</min> <max>255</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxConn">
+ <description>The maxConn attribute specifies the max number of connections allowed for this SCCP Access Point. It is only valid for local SCCP Access Points.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>524288</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="useS1">
+ <description>Controls adding of OPC from routing label to Calling Party Address if absent.
+
+False = Do not add OPC to Calling Part Address.
+True = Add OPC to Calling Part Address.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="SccpSp">
+ <description>The Signalling Connection Control Part, SCCP, Signalling Point, SP, MO is the placeholder for all SCCP related managed objects.
+
+Startime for accounting is set by attributes accountDateFileOutput and accountTimeFileOutput.
+The attribute accountPeriodFileOutput sets period for the accounting record to be stored on the /c file system.
+The accounting is stopped by setting the accountPeriodFileOutput to zero (0).
+NOTE: The SRP function and SccpAccountingCriteria MO's should only be created for one signalling stack, i.e one PIU.
+
+Note! The guiding values that can be found for some attributes is to be regarded as a recommendation for these attributes.
+Depending on the size of the network, traffic load, use and so forth it might be neccesary to set values for these attributes outside the guiding values.</description>
+ <attribute name="SccpSpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the SCCP SP. The operability of the SCCP SP is described by this attribute which has two possible values:
+
+Disabled: The SCCP SP is totally inoperable and unable to provide the service to the user (e.g. if the processor is not usable).
+
+Enabled: The SCCP SP is partly or fully operable and available for use.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="mtp3bSpId">
+ <description>The identity of the L3 Signaling Point used by this MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="prioSST">
+ <description>This attribute sets the priority for the Subsystem Test message when issued by the SCCP itself. When a message is transferred from the SCCP the message priority uses the two spare bits in the SIO.
+Coding of the message priority:
+0 Lowest priority
+1
+2
+3 Highest priority</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>3</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="prioIT">
+ <description>This attribute sets the priority for the Inactivity Test message when issued by the SCCP itself. When a message is transferred from the SCCP the message priority uses the two spare bits in the SIO.
+Coding of the message priority:
+0 Lowest priority
+1
+2
+3 Highest priority</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>3</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="prioRLSD">
+ <description>This attribute sets the priority for the connection release message when issued by the SCCP itself. When a message is transferred from the SCCP the message priority uses the two spare bits in the SIO.
+Coding of the message priority:
+0 Lowest priority
+1
+2
+3 Highest priority</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>3</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="prioGeneral">
+ <description>This attribute sets the priority for all the other messages which are issued by the SCCP itself. When a message is transferred from the SCCP the message priority uses the two spare bits in the SIO.
+
+Coding of the message priority:
+
+0 Lowest priority
+1
+2
+3 Highest priority</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>3</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="accountDateFileOutput">
+ <description>Date for accounting file output.
+Format in ASCI-code: yyyymmdd
+yyyy = 0000-9999
+mm = 01-12
+dd = 01-31
+
+Note! This is the start date for the output.</description>
+ <dataType>
+ <string>
+ <defaultValue>"00000000"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="accountTimeFileOutput">
+ <description>Time for accounting file output.
+Format in ASCI-code: hhmm
+hh = 00-23
+mm = 00-59</description>
+ <dataType>
+ <string>
+ <defaultValue>"0000"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="accountPeriodFileOutput">
+ <description>Period for accounting file output.
+Format: number of half hour.
+Range = 0, 1, 2, 4, 6, 8, 12, 16, 24, 48
+
+Note! if set to 0 (zero) the output will be stopped.</description>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="upperConnThres">
+ <description>The upper connection threshold allow the user to specify the level at which the upper connection threshold notification is triggered. The thresholds must be given as a percentage of the maximum number of connection resources made available for the entire SCCP.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>80</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="lowerConnThres">
+ <description>The lower connection threshold allow the user to specify the level at which the lower connection threshold notification is triggered. The thresholds must be given as a percentage of the maximum number of connection resources made available for the entire SCCP. The value must be less then UpperConnThres.
+
+The maximum value is less or equal to the upper connection threshold</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="swapUDTPointer">
+ <description>There are two ways to construct a UDTS from a UDT, the XUDTS will be constructed in the same way. One way is to only swap the pointers to �Called Party Address� and �Calling Party Address� in a UDT message when constructing a UDTS. The other way is to swap data. How this is done in the SCCP is configurable. The coding and interpretation is as follows:
+0, swap data ��Called party Address� will be sent before �Calling party Address�
+1, swap pointers��Called party Address� will be sent after �Calling party Address�.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="hopCounterSclc">
+ <description>The SCLC hop counter is a parameter that is decremented for each performed GT translation for SCLC messages on the way to the end destination. If decrementing the counter results in the value of zero in a non-end destination node, the SCCP initiates the appropriate error procedure.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>15</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="hopCounterScoc">
+ <description>The SCOC hop counter is a parameter that is decremented for each performed GT translation for SCOC messages on the way to the end destination. If decrementing the counter results in the value of zero in no end destination node, the SCCP initiates the appropriate error procedure.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>15</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tconnEst">
+ <description>Connection establishment control timer.
+
+Unit: deciseconds (0.1 seconds).
+
+Guiding values;
+Range 600 - 1200, Default 600
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>600</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tIas">
+ <description>Send inactivity control timer.
+
+Unit: deciseconds (0.1 seconds).
+
+Guiding values;
+Range 3000-6000
+Default 3000</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>3000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tIar">
+ <description>Receive inactivity control timer.
+
+Unit: deciseconds (0.1 seconds).
+
+Guiding values;
+Range 6600-12600
+Default 6600</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>6600</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tRel">
+ <description>Connection release timer.
+
+Unit: deciseconds (0.1 seconds).
+
+Guiding values;
+Range 100-200
+Default 100</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>100</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tCong">
+ <description>Congestion timer.
+
+Unit: deciseconds (0.1 seconds).
+
+Guiding values;
+Range 10-2550
+Default 300</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>300</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tStatInfo">
+ <description>Subsystem Status Test timer.
+
+Unit: deciseconds (0.1 seconds).
+
+Guiding values;
+Range 10-2550
+Default 300</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>300</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tconnResp">
+ <description>Connection response waiting timer.
+
+Unit: deciseconds (0.1 seconds).
+
+Guiding values;
+Range 100-200
+Default 150</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>150</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tReass">
+ <description>Reassembly timer.
+
+Unit: deciseconds (0.1 seconds).
+
+Guiding values;
+Range 100-200
+Default 150</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>150</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tGuard">
+ <description>Guard timer for program restart not applicable for this CPP version. Instead a restart counter is used to improve restart performance.
+
+Unit: deciseconds (0.1 seconds).
+
+Guiding values;
+Range 13800-15000 (23-25 minutes)
+Default 1380 (23 minutes)
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>13800</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="smiValue">
+ <description>The SMI (Subsystem Multiplicity Indicator) is always ignored for incoming messages. This SCCP can however be configured to insert a specific SMI value in outgoing messages. The coding and interpretation is as follows:
+
+Coding Comment
+ 0 | Affected Subsystem multiplicity unknown.
+ 1 | Affected Subsystem is solitary.
+ 2 | Affected Subsystem is duplicated.
+ 3 | Spare.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>3</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="useSCMG">
+ <description>The use of SCMG functions.
+
+SST = SCCP Subsystem Test message.
+SSA = SCCP Subsystem Allowed message.
+SSP = SCCP Subsystem Prohibited message.
+SSC = SCCP Subsystem Congested message.
+
+The attributes contained in the struct is:
+initiateTimerTcon,
+allowRemoteBroadcast,
+useSST,
+useSSP,
+sendSSA,
+sendSST
+
+</description>
+ <dataType>
+ <structRef name="Scmg"/>
+ </dataType>
+ </attribute>
+ <attribute name="maxRelayedConn">
+ <description>Connection Oriented SCCP Signaling Relay Point (SRP-CO) and Maximum number of Relayed Connections is not used in this CPP version.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>524288</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUDTSent">
+ <description>Performance monitoring counter for number of sent UDT's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUDTRec">
+ <description>Performance monitoring counter for number of received UDT's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUDTSSent">
+ <description>Performance monitoring counter for number of sent UDTS's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUDTSRec">
+ <description>Performance monitoring counter for number of received UDTS's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfXUDTSent">
+ <description>Performance monitoring counter for number of sent XUDT's.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfXUDTRec">
+ <description>Performance management counter for number of received XUDT's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfXUDTSSent">
+ <description>Performance monitoring counter for number of sent XUDTS's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfXUDTSRec">
+ <description>Performance monitoring counter for number of received XUDTS's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCRSent">
+ <description>Performance monitoring counter for number of sent CR's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCRRec">
+ <description>Performance monitoring counter for number of received CR's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDT1Sent">
+ <description>Performance monitoring counter for number of sent DT1's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDT1Rec">
+ <description>Performance monitoring counter for number of received DT1's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfERRSent">
+ <description>Performance monitoring counter for number of sent ERR's.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfERRRec">
+ <description>Performance monitoring counter for number of received ERR's.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSubsysAllowedSent">
+ <description>Performance monitoring counter for number of sent SSA's, subsystem allowed.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCREFRecFromNL">
+ <description>Performance monitoring counter for number of CREF messages received from NL.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCREFSentToNL">
+ <description>Performance monitoring counter for number of CREF messages sent to NL.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRLSDRecFromNL">
+ <description>Performance monitoring counter for number of RLSD messages received from NL.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRLSDSentToNL">
+ <description>Performance monitoring counter for number of RLSD messages sent to NL.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfConInUseExceedHighWaterMark">
+ <description>Performance monitoring counter for number of connections in use that has exceeded the high watermark threshold.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfConInUseReceededLowWaterMark">
+ <description>Performance monitoring counter for number of connections in use that has receded the low watermark threshold.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLUDTRec">
+ <description>Performance monitoring counter for number of received LUDT messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLUDTSSent">
+ <description>Performance monitoring counter for number of sent LUDTS messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="SccpScrc">
+ <description>The Signalling Connection Control Part Routing Control (SCCP SCRC) MO holds information about the SCCP routing control.</description>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="SccpScrcId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRoutingFailure">
+ <description>Performance monitoring counter for number of routing failures.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfConnectFailure">
+ <description>Performance monitoring counter for number of connect failures.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfHopCounterViolation">
+ <description>Performance monitoring counter for number of Hop counter violations.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRoutingFailNoTransAddrOfSuchNature">
+ <description>Performance monitoring counter for number of routing failures due to no translation for Nature of Address field.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRoutingFailNoTransSpecificAddr">
+ <description>Performance monitoring counter for number of routing failures due to no translation of specific address.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRoutingFailurePointCodeUnAvail">
+ <description>Performance monitoring counter for number of routing failures due to destination point code not available.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRoutingFailNetworkCongest">
+ <description>Performance monitoring counter for number of routing failures due to network congestion.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRoutingFailSubsysUnavail">
+ <description>Performance monitoring counter for number of routing failures due to destination subsystem unavailable.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRoutingFailReasonUnknown">
+ <description>Performance monitoring counter for number of routing failures due to unknown reason.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRoutingFailUnequippedSubsys">
+ <description>Performance monitoring counter for number of routing failures due to unequipped subsystem.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Program">
+ <description>The Program MO represent the executable software on the target hardware.
+
+MOs of this type are created automatically during system upgrade.
+MOs of this type are possible to create manually but a system upgrade
+is recommended to create them.
+
+Note! Some programs are not possible to restart or can take part in an RPU. For more information please refer to the LoadModule MO.
+
+</description>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="loadModule">
+ <description>This attribute gives information about which load module the program is instantiated from.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="LoadModule"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>This attribute shows whether the program has normal performance capability or not.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="startState">
+ <description>This attribute shows whether the program is permitted to enter operational state enabled or not after a PIU restart. The default state is disabled in order to avoid that an operating program and a new version of the same program have its startState enabled at the same time.
+
+It is used on all types of node restarts and restart of PlugInUnit with restartCause = piuRestartUpgrade.</description>
+ <dataType>
+ <enumRef name="StartState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="heapSize">
+ <description>This attribute sets the size of the program heap size.
+
+The value in the referenced LoadModule is fetched by program and used at create if no value is submitted at create of the program MO.
+
+The referenced load module has a default size defined at compile time wich is used if no value is submitted at create of loadModule or the program Mo.
+
+Note! The value of this attribute is overwritten during Software Upgrade.
+
+Note: If the program is a child to a Fan Mo this attribute is irrelevant.
+
+Note: Setting of this attribute will have no effect until the program is restarted.</description>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="poolSize">
+ <description>This attribute sets the size of the program pool size. In the referenced LoadModule there is possible to set this value at create.
+
+The value in the referenced LoadModule is fetched by program and used at create if no value is submitted at create of the program MO.
+
+The referenced load module has a default size defined at compile time wich is used if no value is submitted at create of
+LoadModule or the Program Mo.
+
+Note! The value of this attribute is overwritten during Software Upgrade.
+
+Only working for MP-Program
+
+Unit is bytes.
+
+Note: If the program is a child to a Fan Mo this attribute is irrelevant.
+
+Note: Setting of this attribute will not have any effect until the program is restarted.
+
+</description>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="restartTimer">
+ <description>This type specifies the time that a program have to execute without faults, until the restart counter is reset. The time value is interpreted as seconds.
+
+restartTimer= -1 : Forever, implies that the restart counter is only reset when the PIU is restarted.
+
+Note: If the program is a child to a Fan Mo this attribute is irrelevant.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>-1</min>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="restartCounterLimit">
+ <description>This attribute specifies the number of times that a program can restart, without escalation to a PIU restart. The possible values are:
+
+restartCounterLimit = -1 : Unlimited, means never restart PIU, regardless of the number of times the specific program restarts.
+
+Note: If the program is a child to a Fan Mo this attribute is irrelevant.
+
+Note! The value 3 means 3 restarts, hot, warm and finally as a last resort PIU restart.
+
+Note! The program escalates to a PIU restart when the number of restarts reaches the value set for this attribute.
+I.e. if for example the value is set to 5, escalation to PIU restart will occur at the fifth restart.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>-1</min>
+ </range>
+ <defaultValue>3</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ProgramId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="restart">
+ <description>Request to restart the program.
+Only valid for MP programs.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="UniSaalProfile">
+ <description>The UniSaal Profile MO represent and keeps attribute values used by one or more UNI SAAL termination point MOs.</description>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="UniSaalTp"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="profileData">
+ <description>See structure UniSaalProfileData</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="UniSaalProfileData"/>
+ </dataType>
+ </attribute>
+ <attribute name="UniSaalProfileId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="UniSaalTp">
+ <description>The MO represents an access point for a user where a UNI SAAL connection is terminated. The access point depends
+on an AAL5 connection termination located on the same processor.
+
+UniSaalTp can only terminate on a Mp processor.
+
+Note! The performance monitoring counters found in NniSaalTp MO is set to zero when the Mo and its RO is created.
+These counters are not reset unless there occurs a fault situation that demands a restart and recreation of the ROs.
+Also note that some of these counters are reset based on other conditions. For more details please refer to the
+descriptions of the performance monitoring counters in this MO.</description>
+ <attribute name="UniSaalTpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the UniSaalTp MO.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO.
+
+</description>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="uniSaalProfileId">
+ <description>Reference to a UniSaalProfile MO.
+
+The maxStat attribute defined in the UniSaalProfile MO is dependent on the AAL5 SDU size defined in the Aal5TpVccTp MO. See the description of the maxStat attribute in the UniSaalProfile MO.
+
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="UniSaalProfile"/>
+ </dataType>
+ </attribute>
+ <attribute name="aal5TpVccTpId">
+ <description>Reference to an Aal5TpVccTpMo.
+
+Note: The Aal5 termination point must terminate on a main processor, MP.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Aal5TpVccTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="maxSduSize">
+ <description>Maximum SAAL SDU size. The attribute is dependent on the AAL5 maximum SDU size defined in the Aal5TpVccTp MO. The 'maxSduSize' may not exceed the AAL5 maximum SDU size (the lower of the two directions, fromUserMaxSduSize and toUserMaxSduSize).
+
+Example: If 'fromUserMaxSduSize' is set to 256 and 'toUserMaxSduSize' is set to 512 in the Aal5TpVccTp MO, the ' maxSduSize' in the UniSaalTp MO may not exceed 252.
+
+(i.e. maxSduSize &lt;= the aal5MaxSduSize - 4 bytes)
+
+Note! When setting the value of 'maxSduSize' the 4 bytes used by the SAAL layer for the SAAL header has to be considered.
+
+Note! The upper limit of 2044 (2048 including the SAAL header) is due to limitations on the AAL5 layer.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>128</min> <max>2044</max>
+ </range>
+ <defaultValue>128</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSentSDUs">
+ <description>Number of successfully sent SDUs.
+Counts the number of successfully sent messages to the
+application using SAAL. Reset when the link goes InService or the counter "overflows".</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfReceivedSDUs">
+ <description>Number of successfully received SDUs.
+Counts the number of successfully received messages from
+ the application using SAAL. Reset when the link goes
+ InService or the counter "overflows".</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLinkInServiceTime">
+ <description>The accumulated time (in seconds) the signalling link has
+ been in service (in assured data transfer mode) since it was created. If the link is down the value 0 is returned.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAllSLFailures">
+ <description>Number of all Signalling Link failures.
+Is a total sum of the error counters:
+ - Number of protocol errors
+ - Number of unsuccessfully retransmissions
+ - Number of NoResponses
+ - Number of other errors</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfNoResponses">
+ <description>Number of no response. This counter is increased when SSCOP (Service Specific Connection Oriented Protocol)
+send an MaaError with error code P.
+For details refer to ITU-T Q.2110 - B-ISDN AATM Adaptation Layer - Service Specific Connection Oriented Protocol (SSCOP); (7/94).
+Counts the number of no responses detected the last 30 minutes.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalCongestions">
+ <description>Number of local congestions.
+This counter is increased when the sum of SAAL send and retransmission buffers are filled to more than 90%.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRemoteCongestions">
+ <description>Number of remote congestions.
+This counter is increased when the remote side gives SAAL no credit. Reset when the link goes InService or the counter "overflows".</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSequenceDataLosses">
+ <description>Number of sequences data loss.
+Counts the number of SD loss detected the last 30 minutes</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfProtocolErrors">
+ <description>Number of unsolicited or inappropriate PDUs. This counter is increased when SSCOP (Service Specific Connection Oriented Protocol)
+send an MaaError with error code Q.
+For details refer to ITU-T Q.2110 - B-ISDN AATM Adaptation Layer - Service Specific Connection Oriented Protocol (SSCOP); (7/94).
+Counts the number of protocol errors detected the last 30 minutes.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccReTransmissions">
+ <description>Number of unsuccessful retransmissions.
+Counts the number of unsuccessfully retransmissions detected the last 30 minutes.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfOtherErrors">
+ <description>Number of other list element errors. This counter is increased when SSCOP (Service Specific Connection Oriented Protocol)
+send an MaaError with error code Q-U.
+For details refer to ITU-T Q.2110 - B-ISDN AATM Adaptation Layer - Service Specific Connection Oriented Protocol (SSCOP); (7/94).
+Counts the number of other errors detected the last 30 minutes. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="E1PhysPathTerm">
+ <description>This MO represents an E1 (i.e. 2 Mbit/s) physical interface in the node. The E1PhysPathTerm MO does not define which type of traffic (TDM or ATM) that the interface should support.
+Please refer to the Ds0Bundle, AtmPort, IMALink and IMAGroup objects for details about configuration of traffic type.
+
+Note! The performance monitoring counters in the E1PhysPathTerm MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.
+</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>enabled or disabled according to the actual operational state of the Physical Line Termination. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="lineNo">
+ <description>The actual Line number on the board.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>8</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByTraffic">
+ <description>The identity of the reserving AtmPort MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ <attribute name="loopback">
+ <description>This attribute describes the current Loopback State of this physical path termination.
+
+Note! administrativeStatus must be set to locked when setting loopback attribute.</description>
+ <dataType>
+ <enumRef name="LoopbackState">
+ <defaultValue>none</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmEs">
+ <description>Performance Monitoring counter for ES, Errored Seconds.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSes">
+ <description>Performance Monitoring counter for Severely Errored Seconds, SES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="E1PhysPathTermId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="crc4Mode">
+ <description>Indicates what Cyclical Redundancy Check 4 Mode that is being used.</description>
+ <dataType>
+ <enumRef name="Crc4Mode">
+ <defaultValue>AUTOMATIC</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="idlePattern">
+ <description>The idle pattern.
+
+NOTE: Going from A_LAW or U_LAW to UNDEFINED is always allowed but setting up one ET board with
+both U_LAW and A_LAW is not allowed.
+E.g. If you want to change from A_LAW to U_LAW on one ET board you have to change idlePattern
+on each physical port belonging to the board to UNDEFINED first.
+A_LAW -&gt; UNDEFINED -&gt; U_LAW or U_LAW -&gt; UNDEFINED -&gt; A_LAW</description>
+ <dataType>
+ <enumRef name="IdlePattern">
+ <defaultValue>UNDEFINED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="degDegThr">
+ <description>The threshold decides how many of the received blocks that are allowed to have bit errors. The measurement is made on a per-second basis and if the threshold is passed the second is considered bad.
+
+This is a percentage value.
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="degDegM">
+ <description>How many bad seconds in a row that causes a Degraded Signal alarm.
+
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>2</min> <max>10</max>
+ </range>
+ <defaultValue>7</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="rdiReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="aisReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimeout">
+ <description>The shut-down timer. It is used when the administrativeState is set to shutdown.
+
+Value in seconds, must be a positive value.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100000</max>
+ </range>
+ <defaultValue>1800</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBySync">
+ <description>The identity of the reserving Synchronization MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Synchronization"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByImaLink">
+ <description>The identity of the reserving ImaLink MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ImaLink"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="J1PhysPathTerm">
+ <description>This MO represents an J1 (i.e. 1.5 Mbit/s) physical interface in the node. The J1PhysPathTerm MO does not define which type of traffic (TDM or ATM) that the interface should support.
+Please refer to the Ds0Bundle, AtmPort, IMALink and IMAGroup objects for details about configuration of traffic type.
+
+The performance monitoring counters in the J1PhysPathTerm MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.
+</description>
+ <attribute name="J1PhysPathTermId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="lineNo">
+ <description>The actual Line number on the board.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>8</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>enabled or disabled according to the actual operational state of the Physical Line Termination. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="physicalLineType">
+ <description>Supported interfaces is defined in J1Types</description>
+ <dataType>
+ <enumRef name="J1Type">
+ <defaultValue>j1_G</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByTraffic">
+ <description>The identity of the reserving AtmPort MO.
+
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ <attribute name="degThreshold">
+ <description>Maximum allowed BER(Bit Error Rate). Degraded signal (DEG) if BER &gt; degThreshold. The attribute gives a maximum BER of 10e-X, where X ranges from 5 to 9 (default 6)
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>3</min> <max>9</max>
+ </range>
+ <defaultValue>6</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="loopback">
+ <description>Possible values
+
+none - This is the normal state, no loop back is performed (and ordinary traffic is running).
+
+line - The physical path is looped on the line side, the external incoming path is looped back to the external outgoing path.
+
+system - The physical path is looped on the system side, the (node-) internal incoming path is looped back to the internal outgoing path.
+
+Note! administrativeStatus must be set to locked when setting loopback attribute.</description>
+ <dataType>
+ <enumRef name="LoopbackState">
+ <defaultValue>none</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmEs">
+ <description>Performance monitoring counter for Errored Seconds, ES.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSes">
+ <description>Performance monitoring counter for Severly Errored Seconds, SES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="idlePattern">
+ <description>The idle pattern.
+
+NOTE: Going from A_LAW or U_LAW to UNDEFINED is always allowed but setting up one ET board with
+both U_LAW and A_LAW is not allowed.
+E.g. If you want to change from A_LAW to U_LAW on one ET board you have to change idlePattern
+on each physical port belonging to the board to UNDEFINED first.
+A_LAW -&gt; UNDEFINED -&gt; U_LAW or U_LAW -&gt; UNDEFINED -&gt; A_LAW</description>
+ <dataType>
+ <enumRef name="IdlePattern">
+ <defaultValue>UNDEFINED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="rdiReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="aisReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimeout">
+ <description>The shut-down timer. It is used when the administrativeState is set to shutdown.
+
+Value in seconds, must be a positive value.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100000</max>
+ </range>
+ <defaultValue>1800</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBySync">
+ <description>The identity of the reserving Synchronization MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Synchronization"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByImaLink">
+ <description>The identity of the reserving ImaLink MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ImaLink"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Aal0TpVccTp">
+ <description>This MO is used to represent the point in the node where an AAL0 connection is terminated. At this point the user exchange SDUs with its peer at the remote end of the AAL0 connection.
+
+Note! The performance monitoring counters in this MO is set to 0 when counterMode is set to PM_MODE_ON.
+In PM_MODE_OFF no information at all is retrived. So any value for pm-monitoring is measured from the time
+of setting counterMode to PM_MODE_ON.
+At node restart these performance monitoring counters is reset to 0.
+
+</description>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="processorId">
+ <description>This attribute specifies on what processor the termination point resides. It could either be a board processor or main processor (MO type PlugInUnit), or a SP processor (MO type Spm).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational State reflects the operational state of the end points and the belonging node connections.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO.
+</description>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="vclTpId">
+ <description>The virtual channel to which this MO is termination.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="VclTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="Aal0TpVccTpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="continuityCheck">
+ <description>Continuitiy checking means that a cell is sent downstream when no user cell has been sent for a period of nominally 1 second.
+
+Activates VC end to end continuityCheck according to ITU.T rec I.610.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="nomPmBlkSize">
+ <description>Nominal performance monitoring (PM) blocksize. The minimum number of ATM cells to send before sending a Forward Performance Monitoring, FPM, cell.</description>
+ <dataType>
+ <enumRef name="AtmNomPmBlkSize">
+ <defaultValue>NOM_PM_BLKSIZE_2_10</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="counterMode">
+ <description>PM mode is set to indicate type of performance monitoring mode (i.e. activation of bidirectional PM measurements).
+
+</description>
+ <dataType>
+ <enumRef name="AtmCounterMode">
+ <defaultValue>PM_MODE_OFF</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwLostCells">
+ <description>Performance monitoring counter for forwarded lost cells.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwMissinsCells">
+ <description>Performance monitoring counter for number of forwarded missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwErrBlocks">
+ <description>Performance monitoring counter for number of forwarded errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostFpmCells">
+ <description>Performance monitoring counter for number of lost Forward Performance Monitoring, FPM cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwLostCells">
+ <description>Performance monitoring counter for number of lost backward cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwMissinsCells">
+ <description>Performance monitoring counter for number of backward missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwErrBlocks">
+ <description>Performance monitoring counter for number of backward errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostBrCells">
+ <description>Performance monitoring counter for number of lost Backward Reporting, BR, cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="alarmReport">
+ <description>Attribute to decide what type of alarms to be reported.</description>
+ <dataType>
+ <enumRef name="AlarmReport">
+ <defaultValue>ALARM_LOC</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Aal5TpVccTp">
+ <description>This MO is used to represent the point in the node where an AAL5 connection is terminated. At this point the user exchanges SDUs with its peer at the remote end of the AAL5 connection.
+
+Note! The 'mtuSize' on the IpAtmLink MO does not include 8 bytes required for the LLC/SNAP header and this should be taken into consideration when setting the SduSize on the Aal5TpVccTp MO.
+
+Note! The performance monitoring counters in this MO is set to 0 when counterMode is set to PM_MODE_ON.
+In PM_MODE_OFF no information at all is retrived. So any value for pm-monitoring is measured from the time
+of setting counterMode to PM_MODE_ON.
+At node restart these performance monitoring counters is reset to 0..</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="processorId">
+ <description>This attribute specifies on what processor the protocol is terminated. It could either be a board processor or main processor (PlugInUnit) or a SP processor (Spm).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="vclTpId">
+ <description>The virtual channel to which this MO is termination.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="VclTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational State reflects the operational state of the end points and the belonging node connections.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="fromUserMaxSduSize">
+ <description>The maximum SDU size in number of octets received from the user (called maxIngressSduSize in the FRO domain).
+
+The allowed range is dependent on the processorType.
+SP: LowestMaxSduSize =1, HighestMaxSduSize=1600
+BP: LowestMaxSduSize =1, HighestMaxSduSize=1600
+MP:LowestMaxSduSize =1, HighestMaxSduSize=2048</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>2048</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="toUserMaxSduSize">
+ <description>The maximum SDU size in number of octets sent to the user (called maxEgressSduSize in the FRO domain). This attribute is controlled by the processor type.
+
+The allowed range is dependent on the processorType.
+SP: LowestMaxSduSize =1, HighestMaxSduSize=1600
+BP: LowestMaxSduSize =1, HighestMaxSduSize=1600
+MP:LowestMaxSduSize =1, HighestMaxSduSize=2048</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>2048</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The attribute is set by the action reserve from a user of Aal5TpVccTp. It could either be a Cello user like IpAtmLink/UniSaalTp or a node application.
+
+</description>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="Aal5TpVccTpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="alarmReport">
+ <description>Attribute to decide what type of alarms to be reported.</description>
+ <dataType>
+ <enumRef name="AlarmReport">
+ <defaultValue>ALARM_LOC</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="continuityCheck">
+ <description>Continuitiy checking means that a cell is sent downstream when no user cell has been sent for a period of nominally 1 second. Continuity check both enables generation of CC cells as well as detection of LOC
+</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="nomPmBlkSize">
+ <description>Nominal performance monitoring (PM) blocksize. The minimum number of ATM cells to send before sending a Forward Performance Monitoring, FPM, cell.
+</description>
+ <dataType>
+ <enumRef name="AtmNomPmBlkSize">
+ <defaultValue>NOM_PM_BLKSIZE_2_10</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="counterMode">
+ <description>PM mode is set to indicate type of performance monitoring mode (i.e. activation of bidirectional PM measurements).
+
+</description>
+ <dataType>
+ <enumRef name="AtmCounterMode">
+ <defaultValue>PM_MODE_OFF</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwLostCells">
+ <description>Performance monitoring counter for number of lost forward cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwMissinsCells">
+ <description>Performance monitoring counter for number of forward missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwErrBlocks">
+ <description>Performance monitoring counter for number of forward errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostFpmCells">
+ <description>Performance monitoring counter for number of lost Forward Performance Monitoring, FPM, cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwLostCells">
+ <description>Performance monitoring counter for number of lost backward cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwMissinsCells">
+ <description>Performance monitoring counter for number of backward missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwErrBlocks">
+ <description>Performance monitoring counter for number of backward errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostBrCells">
+ <description>Performance monitoring counter for number of lost Backward Reporting, BR, cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="AtmPort">
+ <description>The AtmPort MO is used to configure a physical port for ATM traffic.
+ATM can be transported accross the physical layer in three distinct and different ways:
+
+- Normal mode
+
+An AtmPort MO is created with a reference to physical layer object (any of E1PhysPathTerm,
+J1PhysPathTerm, T1PhysPathTerm, E3PhysPathTerm, T3PhysPathTerm, Sts3CspeTtp, E1Ttp, T1Ttp or Vc4Ttp).
+The payload of that physical layer object is used to transport the ATM traffic.
+
+- Fractional ATM mode
+
+An AtmPort MO is created with a reference to a Ds0Bundle object. The Ds0Bundle specifies
+in this case the timeslots on the physical layer (any of E1PhysPathTerm,J1PhysPathTerm,
+T1PhysPathTerm, T1Ttp or E1Ttp) that should be used for ATM traffic. The remaining timeslots
+are not used at all.
+I.e. when fractional ATM is used only one Ds0Bundle can exist as a child to a physical port MO.
+
+- IMA mode
+
+In IMA mode, a number of physical ports are grouped together to form one "virtual" physical
+ATM pipe. In this mode the AtmPort MO is created with a reference to an IMAGroup MO.
+Please refer to the ImaGroup MO for further details.
+
+Note! The performance monitoring counters in the AtmPort MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again..
+
+
+</description>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="AtmPortId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the ATM port.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status of the AtmPort.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmTransmittedAtmCells">
+ <description>Performance monitoring counter for number of transmitted ATM cells through the ATM port. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmReceivedAtmCells">
+ <description>Performance monitoring counter for number of received ATM cells through the ATM port.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="valueOfLastCellWithUnexp">
+ <description>This attribute returns the ATM header, (vpi, vci, pti), of the last received unexpected cell.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <structRef name="ValueOfUnex"/>
+ </dataType>
+ </attribute>
+ <attribute name="uses">
+ <description>Reference to the physical port, IMA Group or Ds0Bundle used by the ATM port.
+
+The possible MOs are:
+E1PhysPathTerm, J1PhysPathTerm, T1PhysPathTerm, E3PhysPathTerm, T3PhysPathTerm, Sts3CspeTtp, Sts1SpeTtp, Vc4Ttp, E1Ttp, T1Ttp, Ds0Bundle and ImaGroup.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmSecondsWithUnexp">
+ <description>Performance monitoring counter for errored seconds with discarded cells due to protocol errors (unexpected, UNEX, events).
+
+I.610: With protcol errors is meant the reception of cells with either a non-standardized or a non-currently allocated header value.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="hecCorrectionMode">
+ <description>Header Error Correction.
+
+This attribute specifies if the AtmPort should detect and correct single bit errors or detect multiple bit errors in the ATM header.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp3bAp">
+ <description>This MO represents an MTP3b Access Point (in a remote node). An MTP3b AP is a logical point in the MTP network at which an
+MTP3b user can access the services provided by MTP3b and the MTP3b can deliver its services to the MTP3b user.
+
+The performance monitoring counters found in Mtp3Ap MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).
+
+</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="routeSetId">
+ <description>The routeSetId attribute points out the MTP3b Signalling Route Set (SRS) to which the Mtp3bAp MO is connected. </description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Mtp3bSrs"/>
+ </dataType>
+ </attribute>
+ <attribute name="serviceInd">
+ <description>The serviceInd attribute (Service Indicator, SI) is used by traffic handling functions to perform message distribution.
+Only SI=3 for SCCP usage and SI=12 for Q.2630.1 usage and SI=14 for GCP (H.248) usage have any meaning in this case.
+
+Full range of values for attribute SI:
+0 = Signalling network management messages
+1 = Signalling network testing &amp; maintenance regular messages
+2 = Signalling network testing &amp; maintenance special messages*
+3 = SCCP
+4 = Telephone User Part (TUP)
+5 = ISDN User Part (ISUP)
+6 = Data User Part, call and circuit related messages
+7 = Data User Part, facility registration and cancellation messages
+8 = MTP Testing User Part
+9 = Broadband ISDN User Part
+10 = Satellite ISDN User Part
+11 = Spare
+12 = Q.2630.1
+13 = Spare
+14 = H.248
+15 = Spare
+
+Note! The serviceIndicator has to be unique for each Mtp3bAp witin the same Mtp3bSrs.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>15</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operationalState attribute determines the operational status of the MTP3b AP .
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="Mtp3bApId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUserPartUnavailRec">
+ <description>A performance management counter for number of received User Part Unavailable messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAdjacentSPNotAccessible">
+ <description>Performance management counter for number of Adjacent SP's that are not accessible via direct links.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="NniSaalProfile">
+ <description>The NniSaal Profile MO represents and keeps attribute values used by one or more NNI SAAL termination point MOs.</description>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of NniSaalTp�s that have reserved this NniSaalProfile.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="NniSaalTp"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="profileData">
+ <description>See structure NniSaalProfileData.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="NniSaalProfileData"/>
+ </dataType>
+ </attribute>
+ <attribute name="NniSaalProfileId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="NniSaalTp">
+ <description>The MO represents an access point for a user where a NNI SAAL connection is terminated. The access point depends
+on an AAL5 connection termination located on the same processor.
+
+NniSaalTp can only terminate on a Mp processor.
+
+Note! The performance monitoring counters found in NniSaalTp MO is set to zero when the Mo and its RO is created.
+These counters are not reset unless there occurs a fault situation that demands a restart and recreation of the ROs.
+Also note that some of these counters are reset based on other conditions. For more details please refer to the
+descriptions of the performance monitoring counters in this MO.</description>
+ <attribute name="NniSaalTpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the NniSaalTp MO.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="nniSaalProfileId">
+ <description>Reference to a NniSaalProfile MO.
+
+The maxStat attribute defined in the NniSaalProfile MO is controlled by the AAL5 SDU size defined in the Aal5TpVccTp MO. See the description of the maxStat attribute in the NniSaalProfile MO.
+
+Note! The consistency check of the attributes in the two MOs mentioned above could not be performed until the NniSaalTp MO was created since there is no direct relation between the objects. It is therefore the responsibility of NniSaalTp to verify the consistency.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="NniSaalProfile"/>
+ </dataType>
+ </attribute>
+ <attribute name="aal5TpVccTpId">
+ <description>Reference to a Aal5TpVccTp MO.
+
+Note: The Aal5 termination point must terminate on a main processor, MP.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Aal5TpVccTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="maxSduSize">
+ <description>Maximum SAAL SDU size. The attribute is dependent on the AAL5 maximum SDU size defined in the Aal5TpVccTp MO. The 'maxSduSize' may not exceed the AAL5 maximum SDU size (the lower of the two directions, fromUserMaxSduSize and toUserMaxSduSize).
+
+Example: If 'fromUserMaxSduSize' is set to 256 and 'toUserMaxSduSize' is set to 512 in the Aal5TpVccTp MO, the ' maxSduSize' in the NniSaalTp MO may not exceed 252.
+
+(i.e. maxSduSize &lt;= the aal5MaxSduSize - 4 bytes)
+
+Note! When setting the value of 'maxSduSize' the 4 bytes used by the SAAL layer for the SAAL header has to be considered.
+
+Note! The upper limit of 2044 (2048 including the SAAL header) is due to limitations on the AAL5 layer.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>128</min> <max>2044</max>
+ </range>
+ <defaultValue>128</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSentSDUs">
+ <description>Number of successfully sent SDUs.
+Counts the number of successfully sent messages to the
+application using SAAL. Reset when the link goes InService or the counter "overflows".</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfReceivedSDUs">
+ <description>Number of successfully received SDUs.
+Counts the number of successfully received messages from
+ the application using SAAL. Reset when the link goes
+ InService or the counter "overflows".</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLinkInServiceTime">
+ <description>The accumulated time (in seconds) the signalling link has
+ been in service (in assured data transfer mode) since it was created. If the link is down the value 0 is returned.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAllSLFailures">
+ <description>Number of all Signalling Link failures.
+Is a total sum of the error counters:
+ - Number of protocol errors
+ - Number of unsuccessfully retransmissions
+ - Number of NoResponses
+ - Number of other errors</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfNoResponses">
+ <description>Number of no response.
+Counts the number of no responses detected the last 30 minutes.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalCongestions">
+ <description>Number of local congestions.
+This counter is increased when the sum of SAAL send and retransmission buffers are filled to more than the congestionOnSet attribute is configured to..</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRemoteCongestions">
+ <description>Number of remote congestions.
+This counter is increased when the remote side gives SAAL no credit. Reset when the link goes InService or the counter "overflows".</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAlignmentFailures">
+ <description>Number of alignment or proving failures. This counter is
+increased when "alignment not successful".
+The counter is reset when the link is created or the counter "overflows".</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSequenceDataLosses">
+ <description>Number of sequences data loss.
+Counts the number of SD loss detected the last 30 minutes</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfProtocolErrors">
+ <description>Number of unsolicited or inappropriate PDUs.
+Counts the number of protocol errors detected the last 30 minutes.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccReTransmissions">
+ <description>Number of unsuccessful retransmissions.
+Counts the number of unsuccessfully retransmissions detected the last 30 minutes.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfOtherErrors">
+ <description>Number of other list element errors.
+Counts the number of other errors detected the last 30 minutes. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="AtmTrafficDescriptor">
+ <description>This MO specifies traffic and QoS parameters for virtual channel connections.
+
+The attributes can only be set in certain combinations:
+
+CBR:
+ingressAtmQos /egressAtmQos:
+1, 2
+
+ingressAtmPcr /egressAtmPcr:
+mandatory (must be specified)
+
+ingressAtmMcr /egressAtmMcr:
+optional (not used, any value submitted will be ignored)
+
+UBR+:
+ingressAtmQos /egressAtmQos:
+3
+
+ingressAtmPcr /egressAtmPcr:
+optional (if shaping is used the desired rate is specified, 0 means no shaping)
+
+ingressAtmMcr /egressAtmMcr:
+mandatory (must be specified)
+
+UBR:
+ingressAtmQos /egressAtmQos:
+4
+
+ingressAtmPcr /egressAtmPcr:
+optional (not used, any value submitted will be ignored)
+
+ingressAtmMcr /egressAtmMcr:
+optional (not used, any value submitted will be ignored)
+
+Note that the VP sub layer only supports ServiceCategory = CBR and QoS = 1.
+
+Note! The performance monitoring counters in the AtmTrafficDescriptor MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.
+</description>
+ <attribute name="AtmTrafficDescriptorId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>This MO's user label.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ingressAtmPcr">
+ <description>Ingress ATM Peak cell rate (cells/s).
+
+Only positive values are allowed. This attribute is only mandatory when serviceCategory is CBR or UBR_PLUS.
+
+Note! When 'serviceCategory' is set to UBR this attribute has no relevance and the value submitted is ignored by the system.
+
+Note! When 'serviceCategory' is set to UBR+ the value 0 (zero) means that shaping is not used. A value larger than the minimum desired cell rate enables shaping to the rate specified.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ingressAtmQos">
+ <description>Ingress ATM quality of service.
+
+This attribute can be set to Class 1 and 2 if attribute serviceCategory is set to CBR.
+
+This attribute can be set to Class 3 if attribute serviceCategory is set to UBR+.
+
+This attribute can be set to Class 4 if attribute serviceCategory is set to UBR.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="AtmQos">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="egressAtmPcr">
+ <description>Egress ATM Peak cell rate (cells/s).
+
+Only positive values allowed.
+
+This attribute is only mandatory when serviceCategory is CBR or UBR_PLUS.
+
+Note! When 'serviceCategory' is set to UBR this attribute has no relevance and the value submitted is ignored by the system.
+
+Note! When 'serviceCategory' is set to UBR+ the value 0 (zero) means that shaping is not used. A value larger than the minimum desired cell rate enables shaping to the rate specified.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="egressAtmQos">
+ <description>Egress ATM quality of service.
+
+This attribute can be set to Class 1 and 2 if attribute serviceCategory is set to CBR.
+
+This attribute can be set to Class 3 if attribute serviceCategory is set to UBR+.
+
+This attribute can be set to Class 4 if attribute serviceCategory is set to UBR.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="AtmQos">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Sequence of Users that are using this AtmTrafficDescriptor.
+
+
+</description>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="egressAtmMcr">
+ <description>Egress ATM minimum desired cell rate.
+
+Only positive values allowed. The attribute is only mandatory when serviceCategory is UBR+.
+
+Note! When 'serviceCategory' is set to CBR or UBR this attribute has no relevance and the value submitted is ignored by the system.
+
+Note! This attribute cannot have a value larger than for 'egressAtmPcr'.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ingressAtmMcr">
+ <description>Ingress minimum desired cell rate (cells/s).
+
+Only positive vaues allowed. This attribute is mandatory only when serviceCategory is UBR+.
+
+Note! When 'serviceCategory' is set to CBR or UBR this attribute has no relevance and the value submitted is ignored by the system.
+
+Note! This attribute cannot have a value larger than for 'ingressAtmPcr'.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="serviceCategory">
+ <description>The service category.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="ServiceCategory">
+ </enumRef>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp3bSrs">
+ <description>This MO represents/models a MTP3b Signalling Route Set.
+
+The performance monitoring counters found in Mtp3Srs MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).</description>
+ <attribute name="Mtp3bSrsId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the Mtp3bSrs MO.
+
+There are two possible states for the operationalState attribute:
+
+- enabled, the MO is partly or fully operational.
+- disabled, the MO is not operational.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The attribute is set by the local action Reserve.
+
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="autoReroute">
+ <description>This flag indicates Whether automatic rerouting is performed(true) or not(false), between IP and ATM/TDM
+routes when configuration is made. If set to 'false', it has to be done manually, for ex. by management actions(orders).
+
+Note! The attribute 'autoReroute' will always be set to 'false' regardless of value submitted. This attribute is to be removed in coming releases.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean/>
+ </dataType>
+ </attribute>
+ <attribute name="destPointCode">
+ <description>The destPointCode attribute (destination point code, DPC) represents the point code of this Mtp3b SRS MO.
+The Destination Point Code in a Route Set has to be unique within each Signaling Point.
+
+Note! The format of destPointCode must correspond to the signallingPointCode format in the Mtp3bSp, i.e. ITU, ANSI, TTC or China.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16777215</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="congestedLevel">
+ <description>There are two possible states for the congestedLevel attribute:
+
+- notCongested, no change in congestion level.
+- congested, change in congestion level has occurred.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bCongestLevel">
+ <defaultValue>notCongested</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDiscardedMsgFromBroadToNarrow">
+ <description>Performance management counter for number of messages discarded from broadband to narrowband.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTransferControlledRec">
+ <description>Performance monitoring counter for number of received Transfer Control (TFC) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTransferProhibitedRec">
+ <description>Performance monitoring counter for number of received Transfer Prohibited (TFP) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTransferAllowedRec">
+ <description>Performance monitoring counter for number of received Transfer Allowed (TFA) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <action name="routeSetTestAnyRoute">
+ <description>The route set test is only available for the Japanese Mtp3b, TTC.
+
+See JT-Q.707 for details.
+
+The test selects a route in the route set and tests it.
+
+Possible return codes are:
+
+0 : successful test
+48 : unsuccessful test
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <long/>
+ </returnType>
+ </action>
+ <action name="routeSetTestSpecificRoute">
+ <description>The route set test is only available for the Japanese Mtp3b, TTC.
+
+See JT-Q.707 for details.
+
+The test tests the specified route.
+
+Possible return codes are:
+
+0 : successful test
+48 : unsuccessful test
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <long/>
+ </returnType>
+ <parameter name="routeId">
+ <in/>
+ <dataType>
+ <moRef name="Mtp3bSr"/>
+ </dataType>
+ </parameter>
+ </action>
+ </class>
+
+ <class name="PlugInUnit">
+ <description>This MO is used to represent a plug-in-unit, that is a board inserted in a slot in a subrack.
+
+Note! Before deleting the PlugInUnit MO, administrativeState must be set to locked.</description>
+ <attribute name="PlugInUnitId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>A free tag that a user can associated to the this managed object. The value has no relevance for the managed system.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of the PlugInUnit.
+
+The possibility to rollback the setting of this attribute is limited.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state is set to 'enabled' when the plug-in-unit has loaded and started its 'Basic' load module.</description>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="productType">
+ <description>This attribute describes the product type and is always set to the value "HW".</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>"HW"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="piuType">
+ <description>A reference to an available PiuType at create of a PIU.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="PiuType"/>
+ </dataType>
+ </attribute>
+ <attribute name="piuGroupNumber">
+ <description>Indicates which restart group the plug-in unit belongs to.
+Such a group consists of a number of plug-in units where at least one must be enabled (working) or performing recovery. When all plug-in units in a group are out of function, the node is restarted.
+
+Must have a positive value.
+
+Zero indicates no group.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>65536</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled. It is a bit mapped CORBA long, where one or more of the bits may be set. If none of the bits are set then the availability status is considered to be undefined.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of managed objects depending on PlugInUnit</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="pmProcessorLoad">
+ <description>The measurement is done over 100 ms, and returns the sum of load on processes up to, and including process priority 23. The sum is expressed in %
+
+Supported on MP, BP and SP boards.
+
+In case of SP boards the returned processor load is the load of the BP.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="allowedSeqRestarts">
+ <description>The number of automatic (do not require intervention from a human operator) sequential restarts that are allowed for a PIU. When this number of automatic restarts has been exceeded, the automatic restarting halts and the PIU is faulty marked.
+
+The time limit between two restarts is 5 minutes. This means that if the time between two restarts
+is less then 5 minutes the restarts are counted, otherwise the restart counter is reset.
+
+For example, 3 means 3 restarts with time limit &lt; 5 minutes are accepted but when the 4:th occurs within 5 minutes the board is considered faulty and an alarm is generated.</description>
+ <dataType>
+ <enumRef name="SeqRestarts">
+ <defaultValue>RESTARTS_WITH_WARM</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <action name="restart">
+ <description>
+Note! The restartCause can have the following values:
+1 = restart error
+2 = restart upgrade
+
+Note! The restartCause piuRestartUpgrade overrides the restartRank value and gives mainly restartRank=warm (or restartRank=refresh in some upgrade situations.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="restartRank">
+ <in/>
+ <dataType>
+ <enumRef name="RestartRank">
+ </enumRef>
+ </dataType>
+ </parameter>
+ <parameter name="restartCause">
+ <in/>
+ <dataType>
+ <enumRef name="RestartCause">
+ </enumRef>
+ </dataType>
+ </parameter>
+ <raisesException name="ValueOutOfRangeException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ </action>
+ </class>
+
+ <class name="Mtp3bSls">
+ <description>This MO represents the SS7 Signalling Link Set as defined in Recommendation Q.704 Ver. 3, April 28 1992 (ITU) T1.111-1996 (ANSI), JT-Q.704 Ver. 3, April 28 1992 (TTC) or GF001-9001 1990 (China).
+
+It provides information about a set of signalling links between an OPC/Adjacent PC pair. A link set is constructed from between 1 to16 Signalling Links (for China, Itu, Ttc and the ANSI standard), all of which have the same two end points (signalling points) as the Signalling Link Set. A Signalling LInk Set may be part of many routes.</description>
+ <attribute name="Mtp3bSlsId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Use label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the MTP3B SLS.
+
+The operability of the MTP3B SLS is described by the operationalState attribute which has two possible values:
+
+- Enabled: The MTP3B SLS is partly or fully operable and available for use. At least one of the belonging links (SL) is enabled.
+- Disabled: The MTP3B SLS is totally inoperable and unable to provide service to the user.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="usageState">
+ <description>The usageState reflects the usage state of the links in the link set. There are three possible values:
+
+- Active: At least one of the belonging SLs of the SLS is Active and no link is Busy.
+- Busy: If one of the belonging links is Busy.
+- Idle: All SLs of the SLS are Unavailable.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bUsageState">
+ <defaultValue>IDLE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="periodicLinkTestFlag">
+ <description>The periodicLinkTestFlag indicates if periodic sending of SLTM/SLTA messages are used or not. The SLTM message will be sent on every link which is "aligned" at an interval of (SLTM timer). The answer, SLTA is supposed to arrive within (SLTA timer). If this doesn�t happen, or if the received SLTA doesn�t match the sent SLTM a second SLTM will be sent. If this SLTM also fail then the link will be considered 'out-of-service' and a restart of that link will begin.
+
+ANSI: true is default.
+ITU: true is default.
+China: true is default.
+TTC: false is default.
+
+Note that TTC does not use this feature.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="mtp3bSrsId">
+ <description>The mtp3bSrsId attribute points out the corresponding MTP3b Signalling Route Set MO (adjacentDPC).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Mtp3bSrs"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="Mtp3bSr"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <action name="deactivateLinkSet">
+ <description>This action deactivates a link set, which means the containing signalling links are taken out of service.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ </action>
+ <action name="activateLinkSet">
+ <description>A linkset containing signalling links which are all out of service, is called a deactivated linkset. In order to start up the signalling links and get them into service, there is an Activate Link Set action, or rather, there are two similar actions for activation of a link set.
+
+If the action fails to activate a link the ActivationFailed exception is raised.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ </action>
+ <action name="emergencyActivateLinkSet">
+ <description>This action activates the signalling link with emergency alignment.
+It will also set autoStartLink = true
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ </action>
+ </class>
+
+ <class name="Mtp3bSr">
+ <description>This MO represents a MTP3b Signalling Route. A Signalling Route is used to convey MTP3b User messages from a origin SP to a destination SP (Signalling Point). This MO is multiple instansiated and is contained in the MO MTP3b Signalling Route Set. A Signalling Route is from a network point of view the sequence of link sets from a originating signalling point to a destination signalling point.
+
+Note! At least one signalling route in the signalling route set must have priority = 1.
+If lower priorities are defined the next level must be priority=2. (e.g. routes with priority =1 and =3 in a route set will not work).
+
+Note! Signalling Routes belonging to the same route set with the same priority must have the same type of bearer (Broad Band or Narrow Band).</description>
+ <attribute name="Mtp3bSrId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="linkSetM3uId">
+ <description>The MTP3b Signalling Link Set (MTP3bSls) or M3uAssociation to which the MTP3bSr MO is connected.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Operational state notification.There are two possible states for the operationalState attribute:
+- enabled, possible to perform operations on the MTP3b SR.
+- disabled, not possible to perform operations on the MTP3b SR.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="usageState">
+ <description>There are three possible states for the usageState attribute:
+
+-active, route is active.
+-busy, route is congested.
+-idle, route not in use.
+
+(idle=0, active=1, busy=2)
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bUsageState">
+ <defaultValue>IDLE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="priority">
+ <description>The priority of the alternative route. The traffic is directed to the highest priority route(s) available in the route set. If more than one route has the same priority within a route set then loadsharing is permitted between these routes.
+The value 1 is considered as the highest priority.</description>
+ <mandatory/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>5</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="routeType">
+ <description>The type of the route.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="Mtp3bRouteType">
+ <defaultValue>TDM_ATM</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="RouteBlockingState">
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="RouteState">
+ <defaultValue>NOT_BLOCKED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSecondsAccumulatedRouteUnavailable">
+ <description>The number of seconds (accumulated) route unavailable.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <action name="blockSignalingRoute">
+ <description>This action blocks the Signaling Route.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="deBlockSignalingRoute">
+ <description>This action deblocks the Signaling Route.
+
+Note! This action requires antransaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="IpSystem">
+ <description>The IP System MO constitutes the top structure level for IP related MOs in a Cello node.
+
+The IpSystem MO is automatically created and cannot be deleted.
+
+The local distinguished name of this MO is ManagedElement=1, IpSystem=1.
+</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>An operator defined label.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="IpSystemId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="ping">
+ <description>Ping - used to call a host or router to find out if it is present in the network. The following input parameter is used by the Ping action:
+The domain name or IP address to the host that shall be called.
+
+The following parameter is returned:
+Ping result: 'IP address/domain name' - is alive or no answer.
+
+Note! This action requires a transaction.
+</description>
+ <returnType>
+ <string/>
+ </returnType>
+ <parameter name="host">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="traceRoute">
+ <description>Trace route - used to get information about the route through the IP network that is used for a destination with a specific IP address.
+
+The following input parameter is used by the trace route action:
+The domain name or IP address to a host that shall be trace-routed.
+
+The following parameter is returned:
+Trace result - list of IP addresses/domain names or path not found.
+
+Note! This action requires a transaction.
+</description>
+ <returnType>
+ <string/>
+ </returnType>
+ <parameter name="host">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ </class>
+
+ <class name="IpAtmLink">
+ <description>This MO represents an Internet Protocol over ATM link. LLC/SNAP encapsulated packets over Atm Adaptation Layer 5, AAL5, ATM PVCs are used.
+
+Note: The performance monitoring counters in the IpAtmLink MO has a "Wrap-around time" of approximately 2 hours.
+
+Note! When setting the 'fromUserMaxSduSize' and 'toUserMaxSduSize' on the Aal5TpVccTp MO the defined SduSize should be 8 bytes larger then the 'mtuSize' on the IpAtmLink.
+
+Note! Only Aal5TpVccTp's that terminates on an MP (Main Processor) may be used when setting up IpAtmLink's.</description>
+ <attribute name="IpAtmLinkId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>The User Label attribute gives the operator the possibility to label the links.
+</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the IP over ATM link is dependent of the operational states of the underlying AAL5 termination points that are used to transport IP datagrams. If at least one operational AAL5 termination point (MO: AAL5 TP VCC TP) exists, the operational state of the IP over ATM Link is set to "ENABLED"</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled. It is a bit mapped CORBA long, where one or more of the bits may be set. If none of the bits are set then the availability status is considered to be undefined.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>If set, indicates that this IpAtmLink is reserved by the OspfInterface represented by this attribute.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="OspfInterface"/>
+ </dataType>
+ </attribute>
+ <attribute name="ipAddress">
+ <description>The input format used by the operator is four fields of digits, separated by a dot. Each field consists of three digits.
+
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="subnetMask">
+ <description>The attribute subnetMask states the subnet mask of the IP over ATM link (point to point link).
+
+The input format used by the operator is four fields of digits, separated by a dot. Each field consists of three digits.
+For a point to point link, the subnetmask 255.255.255.252 is very likely.
+
+Note! The subnet mask has to be contiguos. That is, it has the LSB's set to 0 (zero).
+
+Example:
+
+255.255.255.X
+
+Contiguous subnet mask:
+11111111.11111111.11111111.11111110 (X = 254)
+11111111.11111111.11111111.11111100 (X = 252)
+
+Not-contiguous subnet mask:
+11111111.11111111.11111111.11111010 (X = 250)
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="mtuSize">
+ <description>The attribute mtuSize states the maximum IP datagram size that may be sent on the IP over ATM link in bytes, without fragmentation. Recommended MTU size is 1500 bytes to prevent IP fragmentation.
+
+Note that the size of the IP datagram does not include the 8 Bytes added for the LLC/SNAP header before putting the IP datagram in AAL5 SDU.
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>576</min> <max>2040</max>
+ </range>
+ <defaultValue>1500</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="metric">
+ <description>The attribute metric states the metric "cost" of the IP over ATM link. The metric value is calculated as 10^8 /link bit speed.
+
+For example:
+Metric for 10 Mbps Ethernet = 10^8/10^7 = 10
+Metric for 100 Mbps Ethernet = 10^8/10^8 = 1</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>32767</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="monitor">
+ <description>This attribute indicates whether InvATMARP monitor is turned on or off.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="monitorInterval">
+ <description>The interval between sending monitor packets.
+Unit is seconds.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>60</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="monitorRetries">
+ <description>The number of retries when sending monitor packets.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>255</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="interfaceName">
+ <description>The interface name.
+
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="aal5TpVccTpSelectionMode">
+ <description>The selection mode for the Aal5TpVccTp's used by the IpAtmLink MO. Determines how the IpAtmLink MO selects the Aal5 termination points used.
+
+In case 'NO_PREFERENCE', 'LOCAL_MP_SELECT_VCC_AT_LINK_UP', LOCAL_MP_PEER_SELECTION_VCC' or 'LOCAL_MP_ACTIVE_RESELECTION' is selected the IpAtmLink MO will prefer Aal5TpVccTp on local MP (i.e. Aal5TpVccTp MOs executing on the same MP as the IpAtmLink), but other Aal5TpVccTp will be accepted if needed.
+
+In case 'ONLY_LOCAL_MP' is selected, the ipAtmLink (Inet Link) will consider Aal5TpVccTp residing on other MPs as a malfunction and discard the usage of them. No InvArp sending will be performed on them and all incomming trafic on them will be discarded. If no local Aal5TpVccTp exists the operational state of the link will be changed to disabled.
+
+ </description>
+ <dataType>
+ <enumRef name="Aal5TpSelectionModes">
+ <defaultValue>NO_PREFERENCE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="Aal5TpVccTpIdList">
+ <description>References to MOs of type Aal5TpVccTp representing the underlying AAL5 termination points (of a AAL5 PVC:s) for the IP over Atm link.
+
+The operator gives a list of relative distinguished names of the Aal5TpVccTp MO's to be used by the IP over ATM link.
+An Aal5TpVccTp MO may only be specified once in the list.
+
+To change in the set of Aal5TpVccTp MO's related to the IP over ATM link the link has to be deleted and then created with the desired set of AAL5 TP.
+
+Note! Only Aal5TpVccTp's that terminates on an MP (Main Processor) may be used when setting up IpAtmLink's.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <sequence>
+ <moRef name="Aal5TpVccTp"/>
+ <length>4</length>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInUcastPkts">
+ <description>Performance monitoring counter for the number of input unicast packets deliverred to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInNUcastPkts">
+ <description>Performance monitoring counter for the number of input broadcast/multicast packets deliverred to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfOutUcastPkts">
+ <description>Performance monitoring counter for the number of out unicast packets deliverred to higher layer</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfOutNUcastPkts">
+ <description>Performance monitoring counter for the number of output broadcast/multicast packets deliverred to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInErrors">
+ <description>Performance monitoring counter for the number of input packets discarded due to any error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInDiscards">
+ <description>Performance monitoring counter for the number of input packets discarded due to resource limitations.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfifOutDiscards">
+ <description>Performance monitoring counter for the number of outbound packets discarded due to resource limitations.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <action name="assignIpAddress">
+ <description>This action sets the IP address and the subnet mask.
+
+The changing of the IP address with the operation assignIpAddress, it might cause an interruption of the communication between the node and the network management tool. If an incorrect or erroneous IP address is configured, the communication with the node might be lost until the node is restarted or the IP address is changed to the correct value.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="ipAddress">
+ <description>The input format used by the operator is four fields of digits, separated by a dot. Each field consists of three digits.</description>
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="subnetMask">
+ <description>The input format used by the operator is four fields of digits, separated by a dot. Each field consists of three digits.</description>
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ </class>
+
+ <class name="EthernetLink">
+ <description>The Ethernet Link MO represents the Internet Protocol over Ethernet link. There is only one Ethernet link MO per Cello node.
+
+The changing of the IP address with operation assignIpAddress might cause interruption of the communication if the network management tool is connected via the ethernet link.
+
+Note: The EthernetLink MO can not be deleted!
+
+Note: The performance monitoring counters in the EthernetLink MO has a "Wrap-around time" of approximately 2 hours.
+</description>
+ <attribute name="userLabel">
+ <description>The User Label attribute gives the operator the possibility to label the links.
+
+</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ipAddress">
+ <description>The attribute ipAddress states the IP address of the Ethernet link, it is also the IP address for the O&amp;M host..
+
+The input format used by the operator is four fields of digits, separated by a dot. Each field consists of three digits.
+It must not be a broadcast or multicast address.
+
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="subnetMask">
+ <description>The attribute subnetMask states the subnet mask of the Ethernet link.
+
+The input format used by the operator is four fields of digits, separated by a dot. Each field consists of three digits.
+
+Note! The subnet mask has to contiguos. That is, it has the LSB set to 0 (zero).
+
+Example:
+
+255.255.255.X
+
+Contiguous subnet mask:
+11111111.11111111.11111111.11111110 (X = 254)
+11111111.11111111.11111111.11111100 (X = 252)
+
+Not-contiguous subnet mask:
+11111111.11111111.11111111.11111010 (X = 250)
+
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="broadcastAddress">
+ <description>The input format used by the operator is four fields of digits, separated by a dot. Each field consists of three digits.</description>
+ <mandatory/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="mtuSize">
+ <description>The IP layer expects the Ethernet link to have an MTU size (maximum Ethernet frame size without fragmentization) of 1500 bytes.
+
+The value is always the default value.
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>1500</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="metric">
+ <description>The attribute metric states the metric of the Ethernet link. The metric value is calculated as 10^8/link bit speed.
+
+For example:
+Metric for 10 Mbps Ethernet = 10^8/10^7 = 10
+Metric for 100 Mbps Ethernet = 10^8/10^8 = 1</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>32767</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the Ethernet link is dependent of the operational states of the underlying MAU:s that represents the Ethernet transceiver function. If at least one operational MAU exists, the operational state of the Ethernet Link is set to "ENABLED"</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="interfaceName">
+ <description>The interface name.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="macAddress">
+ <description>The mac address is persistently stored in flash prom on the MP where the IP stack resides. It is stored there at manufacturing. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <long/>
+ <length>6</length>
+ <nonUnique/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>If set, indicates that this EthernetLink is reserved by the OspfInterface MAO represented by this attribute.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="OspfInterface"/>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="EthernetLinkId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInUcastPkts">
+ <description>Performance monitoring counter for the number of input unicast packets deliverred to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInNUcastPkts">
+ <description>Performance monitoring counter for the number of input broadcast/multicast packets deliverred to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfOutUcastPkts">
+ <description>Performance monitoring counter for the number of out unicast packets deliverred to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInErrors">
+ <description>Performance monitoring counter for the number of input packets discarded due to any error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInDiscards">
+ <description>Performance monitoring counter for the number of input packets discarded due to resource limitations.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfOutNUcastPkts">
+ <description>Performance monitoring counter for the number of output broadcast/multicast packets deliverred to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfifOutDiscards">
+ <description>Performance monitoring counter for the number of outbound packets discarded due to resource limitations.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <action name="assignIpAddress">
+ <description>This action sets the IP address and the subnet mask.
+
+The changing of the IP address with the operation assignIpAddress,
+causes an interruption of the communication between the node and
+the network management tool. If an incorrect or erroneous IP address
+is configured, the communication with the node might be lost until
+the node is restarted or the IP address is changed to the correct
+value.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="ipAddress">
+ <description>The input format used by the operator is four fields of digits, separated by a dot. Each field consists of three digits.</description>
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="subnetMask">
+ <description>The input format used by the operator is four fields of digits, separated by a dot. Each field consists of three digits.</description>
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ </class>
+
+ <class name="IpRoutingTable">
+ <description>This MO holds the IP routing table.
+
+The IpRoutingTable MO is automatically created when the Ip MO is created.
+The IpRoutingTable MO can not be created manually.
+The IpRoutingTable MO can not be deleted.
+</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="indexOfDeletableStaticRoutes">
+ <description>This attribute gives the indexes for the static routes that are possible to delete by the operator.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="IpRoutingTableId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="addStaticRoute">
+ <description>Used to add a new static route to the routing table. It can be
+indicated if the static route should be redistributed by OSPF.
+When adding a static route with an ipaddress, which is not a subnet
+address, the ipaddress is recalculated to the corresponding subnet
+address, based on the ipaddress and the subnet mask. So when looking
+for this route using the action 'getRoutingTableEntry' it is in fact
+the recalculated ipaddress, that is displayed and not the ip address
+entered with addStaticRoute. This is an automatic correction.
+
+Note! If an attempt is made to add a static route with hopIpAddress starting with 0.0 an exception will be thrown.
+
+Note! This action requires a transaction.
+
+
+</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="ipAddress">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="subnetMask">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="hopIpAddress">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="routeMetric">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <parameter name="redistribute">
+ <in/>
+ <dataType>
+ <boolean/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="listRoutes">
+ <description>List routes actions is used to list all routes in the routing table. It requires no input parameters.
+
+The output is a formatted string, indicating the number of routes in the table followed by route information for each of these routes.
+
+The number of routes in the table is found at the very start of the returned string. Immediately following this is the information on each route in the list in turn. The route information for each route begins with a new line character ("\n") and is followed by the following data items (in the order written below), which are separated from each other by a SPACE character:
+
+- Destination IP address
+- Destination Network mask
+- Next hop IP address/Interface index of connected networks in dot-decimal format
+- Route metric
+- Route type
+- Interface name
+- Redistribute
+- Active
+
+Note that the next hop ipaddress is not an ipaddress per se, it is the subnet on wich the host/router to route to resides.
+
+Below is an example list of routes that could be returned from this action:
+
+"\n123.123.123.123 234.234.234.234 0.0.0.7 10 13 LE0 FALSE active\n122.122.122.122 233.233.233.233 0.0.0.6 2 8 LE0 TRUE active\n132.132.132.132 243.243.243.243. 0.0.0.7 9 13 LE0 TRUE inactive"
+
+In this case, there are three routes in the routing table. The first route has destination IP address of 123.123.123.123, the second route has it set to 122.122.122.122, while finally the third has it set to 132.132.132.132.
+
+NOTE that the route types can be of the following types:
+
+INET_RTPROTO_OTHER 1
+INET_RTPROTO_LOCAL 2
+INET_RTPROTO_NETMGMT 3
+INET_RTPROTO_ICMP 4
+INET_RTPROTO_OSPF 13
+
+The types listed above also denote the origin of the routing entry.
+
+Note! This action does not require a transaction.
+</description>
+ <returnType>
+ <string/>
+ </returnType>
+ </action>
+ <action name="getRoutingTableEntry">
+ <description>Returns a RoutingTableEntry according to the specified index.
+
+Should be used with action 'numberOfRoutes' within a transaction. To refresh the routing table stored in the MO, invoke the action 'numberOfRoutes'.
+
+Precondition: 0 &lt;= index &lt;= numberOfRoutes() - 1
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <structRef name="RoutingTableEntry"/>
+ </returnType>
+ <parameter name="index">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="InvalidIndexException"/>
+ </action>
+ <action name="numberOfRoutes">
+ <description>Returns the number of entries in the routing table.
+
+Each time this action is invoked, the MO retrieves routing table information from the resource layer and then builds a new array of RoutingTable structs to store this information.
+
+This action along with getRoutingTableEntry(), which allows one to iterate through the array stored in the MO, should be used together with a transaction.</description>
+ <returnType>
+ <long/>
+ </returnType>
+ </action>
+ <action name="deleteStaticRoute">
+ <description>Removes the RoutingTableEntry submitted as a parameter from the Routing Table, if it is found in the table.
+
+Note that only static roues, previously added, can be deleted with this action.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="routingTableEntry">
+ <in/>
+ <dataType>
+ <structRef name="RoutingTableEntry"/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ </class>
+
+ <class name="Ip">
+ <description>The Ip MO represents the IP protocol layer with IP forwarding functionality.
+
+Note: The performance monitoring counters in the Ip MO has a "Wrap-around time" of approximately 2 hours.
+
+</description>
+ <attribute name="IpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="workingMode">
+ <description>The workingMode of the IP MO controls if the IP stack in the node will work as a combined host/router (routerMode) or only as a host (hostMode).</description>
+ <mandatory/>
+ <dataType>
+ <enumRef name="WorkingMode">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="retransInterval">
+ <description>The retransmission interval. The units are seconds.
+Must be a value &gt; 0.</description>
+ <dataType>
+ <long>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="noOfRetrans">
+ <description>The number of retransmissions.
+Must be a value &gt; 0.</description>
+ <dataType>
+ <long>
+ <defaultValue>5</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="dnsServer">
+ <description>The Domain Name Server IP address.
+
+The IP address must be a Unicast IP address.
+</description>
+ <dataType>
+ <string>
+ <defaultValue>"127.0.0.1"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="isRecursiveSearch">
+ <description>Holds information about how the DNS client wants the DNS server do the search for the IP address in the network . It can be either Recursive search or Non-recursive search.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="isSubDomainName">
+ <description>Holds information about whether to use subsets of the fully qualified domain name to reach the simple domain name. It can be either Use subsets of domain name or Not use subsets of domain name.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="isDefDomainName">
+ <description>Holds information about whether the default domain name is present. It can be Present or Not present.
+
+</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="defDomainName">
+ <description>Contains default domain name.
+If 'isDefDomainName' is set to 'true' the domain name found in this attribute is used by the DNS resolver and there is no need to submit the complete domain name. If the domain name is for example 'ws5741.uab.ericsson.se' then the default domain name would be '.uab.ericsson.se'. If 'isDefDomainName' is set to true the there is no need for using '.uab.ericsson.se'. If set to false then the complete domain name has to be used.
+A valid domain name consists of 1 or more labels separated by dots (".").
+Valid characters for a label shall be limited to letters 'a' - 'z', 'A' - 'Z', digits '0' - '9', the character '-' ("dash").
+Character case shall be preserved. Labels shall start with a letter. Total length of a label shall not exceed 255 characters.
+
+Note! The first and last character in the domain name has to be within the following alphabet: letters 'a' - 'z', 'A' - 'Z' and digits '0' - '9'. For more information refer to RFC 952 and 1101.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the IP MO is ENABLED if at least one link is operational.
+
+Shows whether the MO is OK (enabled) or failed (disabled). The values are set by the system.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="numberOfLinks">
+ <description>Represents the number of interfaces (Ethernet and IP over
+ATM links) which has registered to the IP MO.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>If set, indicates that this Ip is reserved by the Ospf represented by this attribute.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Ospf"/>
+ </dataType>
+ </attribute>
+ <attribute name="useHostFile">
+ <description>Indicates if the hosts file should be used or not. The hostFile is used by the resolver and
+chosen as a source of information before querying a DNS server.
+
+true - use the host file.
+false - do not use the host file.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="dscp">
+ <description>The DiffServ CodePoint.
+The code point values are used by DiffServ enabled hosts and router to identify different service levels.
+When set, the DSCPs are mapped to PHBs (Per Hop Behaviours) by forwarding devices along the path
+between the source and destination. PHBs dictates how each packet will be handled i.e. what type of
+service that is applied to the packet when it is forwarded.
+
+Note! Only traffic originated from the node is tagged with the dscp value. The Cello router does not implement functionality for handling different service levels when routing IP traffic.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>63</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="icmpRedirect">
+ <description>Indicates if ICMP redirects is sent out or not.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="udpChecksumState">
+ <description>Enable/Disable generation of UDP checksum.
+0 = disabled
+1 = enabled
+
+The UDP checksum is used for verifying that the UDP header has not been damaged during transmit.</description>
+ <dataType>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="connectionAttemptTimer">
+ <description>The time that elapses before a connection (TCP) attempt times out.
+
+Unit is seconds.</description>
+ <dataType>
+ <long>
+ <defaultValue>75</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxRetransmissionAttempts">
+ <description>The maximum number of retransmission attempts before a TCP connection is dropped.
+The default value is 10 attempts, which is around 5 minutes.
+Setting this attribute value to -1 means infinity, and TCP will never give up in trying
+to establish a connection.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>-1</min>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIpInReceives">
+ <description>Performance monitoring counter for total number of datagrams received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfHdrErrors">
+ <description>Performance monitoring counter for the number of datagrams discarded due to format error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIpAddrErrors">
+ <description>Performance monitoring counter for the number of datagrams discarded due to misdelivery.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIpForwDatagrams">
+ <description>Performance monitoring counter for the number of datagrams forwarded.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIpInDiscards">
+ <description>Performance monitoring counter for the number of datagrams dascarded due to resource limitations.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIpOutDiscards">
+ <description>Performance monitoring counter for the number of datagrams discarded due to lack of resources.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIpReasmReqds">
+ <description>Performance monitoring counter for the number of fragments received needing reassembly.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIpReasmOKs">
+ <description>Performance monitoring counter for the number of datagrams successfully reassembled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="SccpEntitySet">
+ <description>This MO represents an SCCP EntitySet which is made of one SCCP Entity. An SCCP Entity is a local MTP-SAP + a DPC + possibly an SSN, i.e an SCCP EntitySet identifies the set of access points that result from a global title translation. An SCCP EntitySet may also be made of two SCCP Entities of the same type (if an SSN is present in one SCCP Entity, then an SSN shall also be present in the other). In the latter case the two SCCP entities may be considered either as a "primary" SCCP Entity and a "backup" SCCP Entity (dupli-dominant mode) or may be interpreted as two equal SCCP entities that can be used for outgoing loadsharing purpose. In this implementation they can only be considered as "primary" and "backup".The Routing Indicator (RI) in the Called Party Address is normally not set by the SCCP for outgoing messages and should therefore be set by the user. This means that if the user has set "Route on SSN" this will be the case after the GTT also even if the set consist of MTP-3b Access Points. However, if the set consists of SCCP Access Points the RI is implicitly set to "Route on SSN" by SCCP.
+
+DPC Destination Point Code
+GTT Global Title Translation
+MTP Message Transfer Part
+SAP Signalling Access Point
+SSN Subsystem Number
+
+Note: the SccpEntitySet MO depends either on MAOs of type SccpApLocal OR SccpApRemote, not on a mixture of these MAO types.</description>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="routeIds">
+ <description>The Entity Set routeId is an array of maximum two instances of Sccp ApLocal MO's OR two instances of SccpApRemote MO's OR two instances of Mtp3bAp MO's OR one instance of SccpSP MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ <length>2</length>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="sharingMode">
+ <description>The sharingMode attribute controls the distribution of SCCP traffic over the entities (Access Points) in the set.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="SharingMode">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="newSubSystemNumber">
+ <description>The new sub system number attribute is only valid if the Mtp3b Access Points are used in the set. In that case the SSN attribute allows to optionally set the subsystem number in the Called Party Address as a result of a Global Title Translation. If the set consists of SCCP Access Points the subsystem number in the Called Party Address is always implicitly set to the SCCP Access Point SAP (SSN) as a result of a Global Title Translation.
+This attribute is controlled by the type of AP(s) that the EntitySet refers to.
+
+The default value 0 means no new subsystem number.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>254</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="newGlobalTitle">
+ <description>The New Global Title attribute allows to optionally replace the global title in the Called Party Address as a result of a Global Title Translation (GTT). If the GT resulting from a GTT is different from the GT previously included in the Called Party Address, the newly produced GT replaces the existing one. The gtIndicator attribute is read-only and is derived from the combination of Nature Of Address, the Translation Type and Numbering Plan used.
+
+Default value is considered as no new Global Title.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="GlobalTitleData"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds a list of the reserving MO's.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="SccpEntitySetId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="SccpGlobalTitle">
+ <description>The SCCP Global Title MO represents a combination of a global title translator and a global title rule. If no Destination Point Code (DPC) is present in the Called Party Address, a Global Title (GT) is needed. Then a global title must be present in the Called Party Address, otherwise a routing error occurs. A global title translator is selected by SCCP based on a combination of the values of the Nature Of Address (NA), the translation type (TT), and the Numbering Plan (NP) if available, in this MO matched with the same information in the Called Party Address provided by an SCCP user. A global title translation rule is selected by SCCP by matching the Global Title Address Information and possibly the Encoding Scheme in this MO, with the same information in the Called Party Address provided by an SCCP user. A global title translation rule points to the SCCP Entity Set resulting from the global title translation (GTT).
+The translation results in a DPC and possibly a new Sub System Number (SSN) or GT or both (decided by the SCCP Entity Set it refers to). If the GT and/or SSN resulting from a GTT is different from the GT and/or SSN previously included in the Called Party Address, the newly produced GT and/or SSN replaces the existing one.
+
+GT - Global Title
+SCCP - Signalling Connection Control Part
+SSN - Sub System Number
+DPC - Destination Point Code
+TT - Translation Type
+GTT - Global Title Translation</description>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="gtIndicator">
+ <description>Global title indicator for China, ITU, TTC and ANSI.
+
+
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="GlobalTitleIndicator">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="natureOfAddress">
+ <description>Indicates number type, i.e. national or international number.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="NatureOfAddress">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="numberingPlan">
+ <description>Indicates which numbering plan that is used.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="NumberingPlan">
+ <defaultValue>UNKNOWN</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="translationType">
+ <description>Used to direct the message to the appropriate Global Title translation function.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>254</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="addressInformation">
+ <description>Digit string of 1-37 digits, where each digit is 0-9, and "B", "C". "B" and "C" are for Code 11 and Code 12.
+The addressInformation may also contain wild card symbols: "*" or "?". Wild cards are only allowed for defining Global Title Translations, they are not allowed for specifying SCCP SAPs (built with SPC and Global Title or SPC + SSN + Global Title).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>37</max>
+ </lengthRange>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="encodingScheme">
+ <description>Indicates if the number of address signals are an odd or even number.
+
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="EncodingScheme">
+ <defaultValue>UNKNOWN</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="sccpEntitySetId">
+ <description>The sccpEntitySetId attribute points out the corresponding SccpEntitySet MO.
+
+Note! This attribute is only optional if this MO is used by Policing. In all other cases it has to be set.</description>
+ <noNotification/>
+ <dataType>
+ <moRef name="SccpEntitySet"/>
+ </dataType>
+ </attribute>
+ <attribute name="SccpGlobalTitleId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Aal2PathVccTp">
+ <description>This MO is used to represent an AAL2 Path, i.e. an ATM VC connection that carries multiplexed AAL2 links.
+
+VCC TP - Virtual Channel Connection Termination Point.
+
+The total number of Aal2PathVccTps associated to an Aal2Ap, by connecting them to Aal2PathDistributionUnits under that Aal2Ap, must not exceed 632.
+
+The total number of Aal2PathVccTps associated to a ReliableProgramUniter, by connecting them to Aal2PathDistributionUnits associated to the ReliableProgramUniter, must not exceed 280.
+
+Note! The performance monitoring counters in this MO is set to 0 when counterMode is set to PM_MODE_ON.
+In PM_MODE_OFF no information at all is retrived. So any value for pm-monitoring is measured from the time of setting counterMode to PM_MODE_ON.
+At node restart these performance monitoring counters is reset to 0.
+</description>
+ <attribute name="Aal2PathVccTpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="vclTpId">
+ <description>Reference to the VclTp to be used by this Aal2PathVccTp.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="VclTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of the termination point. </description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>unlocked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Operational state of the termination point.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving Aal2PathDistribution MO.
+
+</description>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status of Aal2PathVccTp.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="continuityCheck">
+ <description>Continuitiy checking means that a cell is sent downstream when no user cell has been sent for a period of nominally 1 second.
+
+Activates VC end to end continuityCheck according to ITU.T rec I.610.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="counterMode">
+ <description>PM mode is set to indicate type of performance monitoring mode (ie. activation of bidirectional PM measurements).
+
+</description>
+ <dataType>
+ <enumRef name="AtmCounterMode">
+ <defaultValue>PM_MODE_OFF</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="nomPmBlocksize">
+ <description>Nominal performance monitoring (PM) blocksize. The minimum number of ATM cells to send before sending a Forward Performance Monitoring, FPM, cell.</description>
+ <dataType>
+ <enumRef name="AtmNomPmBlkSize">
+ <defaultValue>NOM_PM_BLKSIZE_2_10</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="timerCu">
+ <description>Timer that assures that CPS-packets with one or more octets already packed in the ATM cell wait at most the duration of timerCu before being scheduled for transmission.
+
+Units for timerCu is 10 to the power of -4 seconds. This value can be set in steps of 10 to the power of -4.
+
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="aal2PathId">
+ <description>This attribute is used to identify the path in the Q.2630.1 protocol.
+
+The pathId value must be unique within all Aal2PathDistributionUnits under the same Aal2Ap
+
+All integers &gt; 0 are allowed (not 0).
+
+The Aal2PathId is used by the Aal2 connection control function in two Aal2 nodes to uniquely identify an AAL2 path between the two nodes. This means that the value of the attribute Aal2PathId for an Aal2 path must be the same in each of the two nodes.
+
+In order to set this attribute, the Aal2PathVccTp may not be reserved. If an attempt is made, an "IsReservedCanNotSetPathId" exception is thrown.
+
+Note! Setting of this attribute will not have any effect until 'actionAddPath' in Aal2PathDistributionUnit MO' is called adding this MO to the list of Aal2PathVccTp MO's.</description>
+ <mandatory/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>2147483647</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="aal2PathOwner">
+ <description>This attribute indicates whether this Aal2 Path VCC Termination Point is considered the owner of the Aal2 Path in order to decide channel selection procedure in the Q.2630.1 protocol.
+
+Note! In order to set this attribute, the Aal2PathVccTp may not be reserved. If an attempt is made, an "IsReservedCanNotSetPathId" exception is thrown.
+
+Note! The administrativeState has to be LOCKED when this attribute is set, if not the "IsUnlockedCanNotSetPathOwner" exception is thrown.
+
+Note! Setting of this attribute will not have any effect until 'actionAddPath' in Aal2PathDistributionUnit MO' is called adding this MO to the list of Aal2PathVccTp MO's.</description>
+ <mandatory/>
+ <dataType>
+ <boolean/>
+ </dataType>
+ </attribute>
+ <attribute name="alarmReport">
+ <description>Attribute to decide what type of alarms to be reported.</description>
+ <dataType>
+ <enumRef name="AlarmReport">
+ <defaultValue>ALARM_LOC</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="aal2QoSProfileId">
+ <description>The identity of the QosProfile used by the Aal2PathVccTp.</description>
+ <mandatory/>
+ <dataType>
+ <moRef name="Aal2QosProfile"/>
+ </dataType>
+ </attribute>
+ <attribute name="aal2QoSAvailableProfiles">
+ <description>This attribute specifies which QoSClass that can be supported by this Aal2Path.
+</description>
+ <dataType>
+ <enumRef name="SupportedQoSClasses">
+ <defaultValue>CLASS_A_B_C_D</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwLostCells">
+ <description>Performance monitoring counter for forwarded lost cells.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwMissinsCells">
+ <description>Performance monitoring counter for number of forwarded missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwErrBlocks">
+ <description>Performance monitoring counter for number of forwarded errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostFpmCells">
+ <description>Performance monitoring counter for number of lost Forward Performance Monitoring, FPM cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwLostCells">
+ <description>Performance monitoring counter for number of lost backward cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwMissinsCells">
+ <description>Performance monitoring counter for number of backward missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwErrBlocks">
+ <description>Performance monitoring counter for number of backward errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostBrCells">
+ <description>Performance monitoring counter for number of lost Backward Reporting, BR, cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Aal2RoutingCase">
+ <description>This MO represents a AAL2 routing case which points out an AAL2 access point. </description>
+ <attribute name="Aal2RoutingCaseId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>For free use</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="routeList">
+ <description>An array of alternative routes identified by the concerned Aal2Ap MOs. A routeList can have 0 to 5 Aal2Aps.
+The Aal2Ap must be unique.
+Note! if this attribute is set, the routePriorityList also must be se with the same number of values ( if the routeList
+contains 3 routes, the routePriorityList must contain 3 prioritys).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <restricted/>
+ <dataType>
+ <sequence>
+ <moRef name="Aal2Ap"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="routePriorityList">
+ <description>A list of all the Aal2Ap priorities.
+The priority values can be in the range 1 to 5, one beeing the highest priority.
+The Aal2Aps can have the same priorities.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <restricted/>
+ <dataType>
+ <sequence>
+ <long>
+ <range>
+ <min>0</min> <max>5</max>
+ </range>
+ </long>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="numberDirection">
+ <description>Defines the possible set of AAL type 2 Service Endpoint Addresses (A2EA) that match the routing case.
+
+The number direction of a routing case shall be interpreted as all AAL type 2 Service Endpoint Addresses
+starting with the string of numbers defined in the number direction. For example, the AAL2 End System
+Addresses "12340" and "123400" will both match the number direction "1234".
+
+The AAL2 routing function uses a longest match comparison to select between routing cases with overlapping
+number directions. For example, given two routing cases A with the number direction "1234" and B with the number
+direction "12345" the AAL2 End System Address "12345" will be routed using routing case B, whereas the AAL
+type 2 Service Endpoint Addresses "12344" and "12346" will be routed using routing case A.
+
+NOTE: It is not allowed to use leading zeros when configuring this attribute.
+
+NOTE: It is not possible to replace an existing routing case by creating routing cases with number directions that
+completely overlap the number direction of the existing routing case.
+
+NOTE: It is not possible to create two routing cases with the exact same number directions in a node.
+
+NOTE: It is possible to create one or more routing cases with number directions that partially overlap the number
+direction of an existing routing case.
+
+Length range 1..15
+Alphabet: "0123456789"
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>15</max>
+ </lengthRange>
+ </string>
+ </dataType>
+ </attribute>
+ <action name="addAal2ApToRc">
+ <description>Adds the identified (and existing) Aal2Ap MO to the routeList. This action should also be used when changing the priority for an existing Aal2Ap MO. When submitting an existing Aal2Ap MO with a new priority the routing list will be updated with the new priority for the specified Aal2Ap MO.
+
+Note! In order to be able to update the priority for a routing entry, the routing entry first has to be deleted and then submitted with the new priority.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="priority">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <parameter name="route">
+ <in/>
+ <dataType>
+ <moRef name="Aal2Ap"/>
+ </dataType>
+ </parameter>
+ <raisesException name="InvalidPriorityException"/>
+ <raisesException name="IllegalArgumentTypeException"/>
+ <raisesException name="IllegalAttributeValueException"/>
+ </action>
+ <action name="removeAal2ApFromRc">
+ <description>Removes the identified Aal2Ap MO from the routeList.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="route">
+ <in/>
+ <dataType>
+ <moRef name="Aal2Ap"/>
+ </dataType>
+ </parameter>
+ <raisesException name="IllegalAttributeValueException"/>
+ <raisesException name="IllegalArgumentTypeException"/>
+ </action>
+ </class>
+
+ <class name="Aal2Sp">
+ <description>The Aal2Sp (AAL2 Signalling Point) MO is used to represent the AAL type 2 Service Endpoint Address of the node in the AAL2 network.
+There is one and only one instance of this MO in the ATM NE system.</description>
+ <attribute name="userLabel">
+ <description>For free use</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="a2ea">
+ <description>An E.164 format number that specifies the AAL type 2 Service Endpoint Address of the node.
+
+Length Range: 1..15
+Alphabet: "0123456789"
+
+Note! It is not allowed to use leading zeros when configuring this attribute.</description>
+ <mandatory/>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>1</min> <max>15</max>
+ </lengthRange>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="Aal2SpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="pmUnsuccessfulConnsInternal">
+ <description>Performance monitoring counter for the number of unsuccessful attempts to establish connections due to node internal problems.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Aal2Ap">
+ <description>This MO represents a AAL2 Access Point signalling function associated with a single AAL2 signalling relationship to a remote peer AAL2 acess point signalling function. An AAL2 access point is either a high rate access point that uses MTP-3B for signalling or a low rate access point that uses UNI-SAAL for signalling.
+
+Aal2Ap - Aal2 Access Point
+
+Note! The performance monitoring counters in the AalAp MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.</description>
+ <attribute name="Aal2ApId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Free for use</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>This attribute holds a list of the reserving MOs.
+</description>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Operational state of the AAL2 AP.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status of the Aal2Ap.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="timerErq">
+ <description>Q.2630.2 establishment request timer. Unit is milli seconds.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>5000</min> <max>30000</max>
+ </range>
+ <defaultValue>5000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="timerRel">
+ <description>Q.2630.2 release request timer. Unit is milli seconds.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>2000</min> <max>60000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="sigLinkId">
+ <description>Reference to a UniSaalTp or Mtp3bAp MO that provides a signalling link for the Aal2Ap.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="secondarySigLinkId">
+ <description>Reference to a secondary signalling link MO of type UniSaalTp. This attribute can only be set when sigLinkId is of type UniSaalTp.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="rpuId">
+ <description>The physical location of an AP (Access Point) LR/HR (Low Rate/ High Rate) program represented by a reference to a RPU (ReliableProgramUniter) MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ReliableProgramUniter"/>
+ </dataType>
+ </attribute>
+ <attribute name="aal2QoSCodePointProfileId">
+ <description>The identity of the QoSCodePointProfile used by this MO.</description>
+ <dataType>
+ <moRef name="Aal2QosCodePointProfile"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmExisOrigConns">
+ <description>Performance monitoring counter pmExisOrigConns.
+Number of existing connections for the AP originating in this node.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="nrOfConfiguredAal2Paths">
+ <description>The total number of Aal2PathVccTp MOs configured on this Aal2 Ap.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="nrOfUnavailableAal2Paths">
+ <description>The total number of unavailable Aal2PathVccTp's on this Aal2 Ap, i.e. the number of Aal2PathVccTp MOs connectected to this Aal2Ap with 'administrativeState' LOCKED.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmExisTermConns">
+ <description>Performance monitoring counter pmExisTermConns.
+Number of existing connections for the AP terminating in this node.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmExisTransConns">
+ <description>Performance monitoring counter pmExisTransConns.
+Number of existing connections for the AP transiting in this node.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSuccOutConnsRemote">
+ <description>Performance monitoring counter pmSuccOutConnsRemote.
+Number of successful establishment of outgoing connections on this AP</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSuccInConnsRemote">
+ <description>Performance monitoring counter pmSuccInConnsRemote.
+Number of successful establishment of incoming connections on this AP.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUnSuccInConnsRemote">
+ <description>Performance monitoring counter pmUnSuccInConnsRemote.
+
+Number of unsuccessful establishment of incoming connections on this AP caused by reject from beyond this node.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUnSuccOutConnsRemote">
+ <description>Performance monitoring counter pmUnSuccOutConnsRemote.
+
+Number of unsuccessful establishment of outgoing connections on this AP caused by reject from remote side, reset from remote side, no reply or signalling link failure.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUnSuccInConnsLocal">
+ <description>Performance monitoring counter pmUnSuccInConnsLocal.
+Number of unsuccessful attempts to allocate Common Part Sublayer, CPS, resources during establishment of incoming connections on this AP caused by Channel Identifier, CID, and/or bandwidth collision or mismatch of Call Admission Control, CAC, between peers.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUnSuccOutConnsLocal">
+ <description>Performance monitoring counter pmUnSuccOutConnsLocal.
+
+Number of unsuccessful attempts to allocate CPS resources during establishment of outgoing connections on this AP. Caused by rejects in CAC (Connections Admission Control).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUnRecMessages">
+ <description>Performance monitoring counter pmUnRecMessages.
+
+Number of received unrecognized Q.2630.1 messages on this AP.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUnRecParams">
+ <description>Performance monitoring counter pmUnRecParams.
+
+Number of received Q.2630.1 messages with unrecognized parameters on this AP.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Etm1">
+ <description>This MO represents the hardware of the ET-M1 board type. It only represents the ET specific hardware, while the DBM module of the board is represented by the PlugInUnit MO.
+
+The ET-M1 board contains 8 physical ports that can be configured as either E1 (ETSI), J1 (TTC) or T1(ANSI). The board does not allow for a mix of E1, J1 and T1 ports, thus all configured ports on the board must be configured to the same standard.
+
+Each of the ports on the ET-M1 board can be used to carry either ATM traffic or circuit orientated (Nx64 Kbits/s connections) traffic.
+
+Each port can support up to 30 ATM VC connections. Two of these connections are reserved for AAL2 paths, and therefore two AAL2 multiplexers per port are available.
+
+Each port can support up to 2 VP connections.
+
+The ET-M1 board supports 1 bidirectional F4/F5 PM flow per port.
+
+Other restrictions:
+- All ports (configured for ATM) on the board must have the same value for the hecCorrection attribute (ATM Port MO).
+- It is possible to configure UBR+ traffic, but there is no guarantee on the minimum cell rate.
+- VP shaping is not supported (it is recommended to configure at most one VP per physical port).
+- VC shaping is not supported with an exception for AAL2 path traffic. This is shaped to the peak bandwidth on the VC connection.
+- When using the Etm1 board the performance monitoring counters in the transmit direction found on the AtmPort MO does not show the following cells: CC cells and OAM FPM cells.
+
+Note! IMA is not applicable for the ETM1 board.
+
+Note! When using fractional atm, timeslot 1 must be a part of the fraction.
+
+Note! ETM1 does not support EPD and PPD
+
+Note! ETM1 does not have a proper buffer management. Thus fairness of UBR+ traffic can not be guaranteed and shaping on UBR+ traffic is not possible.
+
+Note! The number of VCC TP+VPC TP with performance monitoring enabled (i.e. PM mode &lt;&gt; off) is restricted to 1 per port.
+</description>
+ <attribute name="userLabel">
+ <description>user label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Enabled or disabled according to the actual operational state of the Etm1 board.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="Etm1Id">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="TuSyncRef">
+ <description>This MO is used to administer synchronization reference (a synchronization input with support for 2MHz and 10MHz signals) on Timing Unit board.</description>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Operational state of TU synchronization reference</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>Administrative state of TU synchronization reference</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status of the TuSyncRef.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>When the TU synchronization reference is registered in the system as an usable synchronization reference, this MO reference is set by using "local" operation syncReserve(). When synchronization reference is de registered, "local" operation syncRelease is used. Note that the only valid user of these operations is Synchronization MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Synchronization"/>
+ </dataType>
+ </attribute>
+ <attribute name="TuSyncRefId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Spm">
+ <description>The Special purpose Processor Module MO, Spm, represents one of the Special Purpose Processors and its connected hardware. This object is used for SW management and restart. Hardware failure indications are sent to Spu.
+
+Note! If the board is of type SPB1 the maximum number of Spm MO's that is possible to create under the Spu MO is 3.
+If the board is of type SPB2 the maximum number of Spm MO's that is possible to create under the Spu MO is 5.</description>
+ <attribute name="SpmId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>user label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the SPM</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="switchModuleNumber">
+ <description>Switch Module Number</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="asciPortNumber">
+ <description>ASCI Port Number</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="executionResourceNumber">
+ <description>The identity of the SPM on the Special purpose Processor Unit (SPU).
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="runningResourceIdList">
+ <description>The list of identities of running Spm's
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <long/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="installedResourceIdList">
+ <description>The list of identities of installed Spm's in the system.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <long/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="spLinkName">
+ <description>The uniqe name of the link between the SP and BP.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <action name="restart">
+ <description>Restarts the SP.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ </class>
+
+ <class name="Spu">
+ <description>The Special purpose Processor Unit MO, Spu, represents the board specific HW on SPB. This objects collects HW failure indications on the board and issues/ceases alarms.</description>
+ <attribute name="userLabel">
+ <description>user label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the SPB board.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="spLinkName">
+ <description>The special purpose processor link name.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="SpuId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="restart">
+ <description>Restarts all SPs on the board (but not the BP).
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroNotAccessibleException"/>
+ </action>
+ </class>
+
+ <class name="AtmCrossConnection">
+ <description>This MO is used to represent the point-to-point ATM cross-connect relationship between two VCL termination points.</description>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Operational state for the cross connection.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="vclTpAId">
+ <description>Identifies the VclTp managed object involved in the A side of the cross connection (which consists of an A and B side).
+
+Must not be the same as vclTpBId.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="VclTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="vclTpBId">
+ <description>Identifies the VclTp managed object involved in the B side of the cross connection (which consists of an A and B side).
+
+Must not be the same as vclTpAId.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="VclTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="AtmCrossConnectionId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="ConfigurationVersion">
+ <description>The Configuration Version, CV, is an MO managing all on disk saved node configuration. This MO keeps all administrative data about the CV's including path and file-names of the configuration files. There may be more than one CV on the disk but only one is used at the time. A CV is always based on one Upgrade Package.
+
+The local distinguished name of this MO is ManagedElement=1, SwManagement=1, ConfigurationVersion=1.</description>
+ <systemCreated/>
+ <attribute name="ConfigurationVersionId">
+ <description>Configuration version MO's id.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="storedConfigurationVersions">
+ <description>List of stored configuration versions in the node.
+
+Stored in and read from the file system.
+
+List of stored configuration versions (CV) in the node.
+
+The list is a sequence of CVs.
+Each CV is presented as structure. A CV structure has following fields:
+ 1. Name
+ 2. Identity
+ 3. Type
+ 4. UpgradePackageId
+ 5. Operator name
+ 6. Comment
+ 7. Date
+ 8. Status
+
+The CV list is formatted as a sequence of ConfigurationVersionAttributes.
+Each struct contains one CV.
+
+The following characters are allowed within the struct members below.
+
+[0-9], [A-Z], [a-z] and '&amp;' , '%' , ':' , '.' , '_' , '-'
+
+Note! For comment and operatorName spaces (' ') are also allowed within the strings.
+
+Struct element description :
+-Name is in string format, max length is 40.
+-Identity is in string format, max length is 40.
+-Type is in string format, max length is 40.
+-UpgradePackageId is in string format, max length is 40.
+-Operator name is in string format, max length is 40.
+-Comment is in string format, max length is 40.
+-Date is in string format, max length is 40. Format for date is: weekday month date hour:min:seconds year.
+-Status is in string format, max length is 40.
+
+Note! The identity can not be the same as name. Identity should contain the product identity.
+
+
+</description>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <structRef name="ConfigurationVersionAttributes"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="currentLoadedConfigurationVersion">
+ <description>The name of the current loaded configuration version.
+
+Stored in and read from the file system.
+
+This is the configuration version that the system started with, i.e. the configuration version that was startable at the last node restart. </description>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="startableConfigurationVersion">
+ <description>The name of the configuration version that will be used at next node restart.
+
+Stored in and read from the file system.
+
+This attribute is set by the action "setStartable( name of cv)".
+Also set at rollback by the system. The first CV in the rollback list is then used.</description>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="rollbackList">
+ <description>A list of configuration versions to rollback to (configuration version name).
+
+The configuration version on the first line is used at the next rollback. That line is then automatically removed from the rollback list.
+
+This attribute is modified by actions setFirstRollbackList() and removeFromRollbackList()</description>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="currentUpgradePackage">
+ <description>A reference to current executing upgrade package.</description>
+ <readOnly/>
+ <dataType>
+ <moRef name="UpgradePackage"/>
+ </dataType>
+ </attribute>
+ <attribute name="autoCreatedCVIsTurnedOn">
+ <description>Flag that indicates that a configuration version will be created automatically once a day.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="timeForAutoCreatedCV">
+ <description>Time for the automatic creation of configuration versions once a day.
+
+The string must be specified as "HH:MM" to be accepted at set.
+
+See also Class Attribute autoCreatedCVIsTurnedOn.
+The time is UTC time.
+
+Note! If changing the clock on the node, this attribute must be set or
+the JVM MP must be reastarted.
+
+
+</description>
+ <dataType>
+ <string>
+ <defaultValue>"04:00"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="rollbackOn">
+ <description>Flag that indicates if rollback is enabled or not.
+When true the system will automatically set the rollback counter. In case of cyclic restarts a rollback will be issued after x restarts. x is defined by the rollbackInitCounterValue.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="rollbackInitTimerValue">
+ <description>Used by the system when rollback is switched on (autoRollbackOn=true). After the given time the node is considered not in a cyclic restart mode. The rollback counter will then be reset to its initial value (rollbackInitCounterValue).
+
+Timer value in minutes.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>10000</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="rollbackInitCounterValue">
+ <description>Initial value for the rollback counter. Used when rollback is switched on (autoRollbackOn=true).
+
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>10000</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="commandlogStatus">
+ <description>An attribute to indicate status of command log.
+It can be ON/OFF(true/false). </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="executingCv">
+ <description>The name of the executing Configuration Version, CV.
+
+Same as 'currentLoadedConfigurationVersion' after a node restart, changed to the value of lastCreatedCv when a CV is created.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="lastCreatedCv">
+ <description>The name of the last created Configuration Version, CV.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <action name="setStartable">
+ <description>The CV given will be the one used at the normal node restarts. Only A CV with status = OK can be set as startable.
+
+This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="configurationVersionName">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="create">
+ <description>A new CV directory will be created. A DB backup from the current RAM CV,
+an ARMAMENT file and the file LLP:LMid is created at the directory. The current
+command log file is copied to the CV directory first, then it removes the file from
+the current directory.
+
+Note: The file cmdlog.properties under /c/ will not be saved to the CV.
+
+The following characters are allowed in the Strings:
+
+[0-9], [A-Z], [a-z] and '&amp;' , '%' , ':' , '.' , '_' , '-'
+
+Note! For comment and operatorName spaces (' ') are also allowed within the strings
+
+-configurationVersionName is in string format, max length is 40 characters.
+-identity is in string format, max length is 40 characters.
+-operatorName is in string format, max length is 40 characters.
+-comment is in string format, max length is 40 characters.
+
+This action does not require a transaction.
+
+Note! The configurationVersionName and identity can not be the same. The identity should be the product identity.
+</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="configurationVersionName">
+ <description>One ASCII text string. It must be possible to create a directory with string. Do not use string "autocreated1" and "autocreated2" as cv name. They are used by the system.</description>
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="identity">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="type">
+ <description>Type of the configuration version [ standard | test | other ].</description>
+ <in/>
+ <dataType>
+ <enumRef name="ConfigurationVersionType">
+ <defaultValue>other</defaultValue>
+ </enumRef>
+ </dataType>
+ </parameter>
+ <parameter name="operatorName">
+ <description>The operator's name.</description>
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="comment">
+ <description>The operator's comment.</description>
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <raisesException name="ValueOutOfRangeException"/>
+ </action>
+ <action name="delete">
+ <description>Delete a configuration version (CV) permanently.
+
+If CV is referenced in the startable or in the rollback list, the action is not performed (an exception is thrown instead).
+
+Note! The latest created CV is not deletable until a node restart is performed or a new CV is created. Also note that a CV is not possible to delete when it has one of the folowing properties:
+- "loaded"
+- "startable"
+- The CV is found in the "rollbacklist"
+
+This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="configurationVersionName">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="removeFromRollbackList">
+ <description>Removes a Configuration Version (CV) from the rollback list.
+
+This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="configurationVersionName">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="setFirstRollbackList">
+ <description>Adds a Configuration Version (CV) first in the rollback list. This will cause the node to chose this CV at the next rollback. A CV with status NOK, can't be put in the rollback list.
+
+This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="configurationVersionName">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="activateCommandLog">
+ <description>This action activates the log.
+
+The inparameter is the drive name (where the command log file should be stored).
+
+Default command log is drive /c/.
+
+Note! Invoking this action affects the attribute'commandLogStatus'.
+
+Note! This action does not require a transaction.
+</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="cmdlogdriveName">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <raisesException name="InvalidDriveNameException"/>
+ <raisesException name="LogActivationException"/>
+ </action>
+ <action name="deactivateCommandLog">
+ <description>This action deactivates the logging of configuration commands.
+
+Please note that uncommited data will be lost.
+
+Note! Invoking this action affects the attribute'commandLogStatus'.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="LogActivationException"/>
+ </action>
+ </class>
+
+ <class name="SwManagement">
+ <description>This MO is used as a structural element for the SW managed object. The MO structures the software resources of the node.
+
+Note that the SwManagement MO is automatically created and cannot be deleted.
+
+The local distinguished name of this MO is ManagedElement=1, SwManagement=1.</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="SwManagementId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="normalizeRPU">
+ <description>This action will normalize all RPUs in the node.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="UpgradePackage">
+ <description>The UpgradePackage, UP, represents an upgrade package as stored in the node file system and as stored on the ftp server that it is/shall be fetched from.
+
+There may be more than one UP at the same time on the disk. One UP represents the running system issue in the node. That one is pointed out by the Configuration Version MO.
+
+The actions on an UpgradePackage MO, are actions that can be called to take that particular UpgradePackage into operation on the node.
+
+The deletion of the Upgrade Package on disk is performed when the associated Upgrade Package MO is deleted. The Upgrade Package's unique LoadModule MOs and files are deleted. ConfigurationVersions in otherReferringCVs are deleted.
+
+
+The UP MO refers to all load modules used in the UP. One load module may by used in more than one UP.
+
+Note at the start-up of the system/database/loading of a Configuration Version, special Upgrade Package MOs are created to represent Upgrade Packages that are stored on the disk but do not have an MO in the current Configuration Version. These special Upgrade Package MOs have are in the "onlyDeletable" state. In this state, the MO will throw ActionNotAllowedException on all its actions!
+
+MOs of this type are created automatically during system upgrade.
+MOs of this type are possible to create manually but a system upgrade
+is recommended to create them.</description>
+ <attribute name="UpgradePackageId">
+ <description>The identity of the MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free of use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="loadModuleList">
+ <description>List of references to load modules that belong to this upgrade package.
+
+The list will be null until a successful install has been performed.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="LoadModule"/>
+ <nonUnique/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="upgradeControlFilePath">
+ <description>Path to the .xml file on the node once it has been fetched from the FTP server.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="state">
+ <description>Contains the state of this upgrade package.
+
+The management system and/or operator need to act on some changes in the state attribute.
+
+This attribute is used to accept/reject and modify behavior of actions. For example action 'upgrade' is not allowed in state notInstalled. Furthermore, action 'upgrade' does not behave the same if state == 'Installed' compared to if state == 'executingUpgrade' or 'awaitingConfirm'.
+
+To continue and conclude the upgrade sequence when in state == 'awaitingConfirm', action 'confirmUpgrade()' must be called. In this state it is also advisable to check attribute 'confirmationDeadline' to see how much time it is left before automatic rollback is done.
+
+Upgrade Package MOs that are stored on disk but do not have an MO in the current Configuration Version are in state "onlyDeletable". An MO in this state will throw the exception ActionNotAllowedException on all its actions.
+
+</description>
+ <readOnly/>
+ <dataType>
+ <enumRef name="UpgradePackageState">
+ <defaultValue>NOT_INSTALLED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="progressHeader">
+ <description>Header enum describing the current progress indication.
+Note that this is only progress information, that should be shown to a human operator, because some operations may take time.
+
+Changes in the progress header NEVER entails that the operator or management system need to perform any particular actions. </description>
+ <readOnly/>
+ <dataType>
+ <enumRef name="UpgradeProgressInformation">
+ <defaultValue>IDLE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="progressTotal">
+ <description>
+This notification attribute is used to indicate progress for different steps in the upgrade sequence. The value gives the total number of steps that is to be performed in current step.
+
+This attribute is changed whenever 'progressHeader' is changed and indicates a maximum count for the progress of the progress counter. What items that are counted is specific for each case. For some cases, the counter is not yet implemented. In these cases, the progressTotal is set to zero (0) when the progressHeader is set.
+
+</description>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="progressCount">
+ <description>This attribute is used to indicate progress for different steps in the upgrade sequence. The value is separated in increments from 0 to progressTotal.
+
+The value of progressCount never exceeds the value of 'progressTotal'.
+
+For some cases, the counter is not yet implemented. In these cases, the progressCount is set to zero (0) when the progressHeader is set.</description>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeData">
+ <description>Contains product data for this upgrade package. This information is extracted from the upgrade control file. </description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <structRef name="AdminProductData"/>
+ </dataType>
+ </attribute>
+ <attribute name="confirmationDeadline">
+ <description>This attribute contains the deadline date and time for an operator confirmation. If the deadline is not met, then an automatic rollback to a previous configuration is issued by the system.
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ftpServerIpAddress">
+ <description>Ip address to the ftp server where the upgrade package is stored.
+
+The input format used by the operator is four fields of digits, separated by a dot.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="upFilePathOnFtpServer">
+ <description>File path on the FTP server to the upgrade control file. </description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="user">
+ <description>User id. to be used for logging in to the FTP server.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>anonymous</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="password">
+ <description>Password to the FTP server. This attribute is only supplied at create and is not readable.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>anonymous</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="upgradePackageDocumentId">
+ <description>The document number and revision of the uppgrade package where the white spaces has been removed and underscore between the document number and revision has been inserted e.g. 19089-CSX10901/1_A.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="deletePreventingCVs">
+ <description>The list containing the names of the Configuration Versions that stop the Upgrade Package MO from being deleted.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <string/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="otherReferringCVs">
+ <description>The list of names of Configuration Versions that refer to the Upgarde Package MO, but do not affect the deletable status of the Upgrade Package MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <string/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="isDeletable">
+ <description>Indicates if the Upgrade Package MO can be deleted.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="basedOnUpgradePackages">
+ <description>This attribute is only valid for Upgrade Packages of type Delta.It contains the merge history of this upgrade package.
+
+Example: [Product Data for normal UP (non Delta UP), Product Data for Delta UP1, Product Data for Delta UP2]. </description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <structRef name="AdminProductData"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="upCompatibilityIndex">
+ <description>This attribute states a compatibility index.
+
+If specified, it may be used when verifying that an upgrade 'from' state is valid for this Upgrade Package.
+
+Note: It is only used when the Upgrade Control File element upgrade window contains this type of information.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="cppUpVersion">
+ <description>This attribute states the CPP upgrade package version of this Upgrade Package</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <structRef name="AdminProductData"/>
+ </dataType>
+ </attribute>
+ <attribute name="actionResult">
+ <description>The attribute contains the result from the latest four invoked actions.
+
+This attribute is only valid for actions::
+- install (all variants)
+- cancelInstall
+- verifyUpgrade
+- upgrade (all variants, Note that the attribute is only valid when the verification phase discovers that upgrade is not possible').</description>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <structRef name="ActionResultData"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <action name="install">
+ <description>Load modules defined in the Upgrade Package Control file will only be downloaded to the node if the Load Module MO representing the load module file doesn't already exist.
+The result of this action is indicated in the attribute ActionResult. In case the installation fails after 'void' has been returned the attribute 'ProgressHeader' is set to 'InstallationExecutionFailed'.Already downloaded load modules (the downloaded file and the Load Module MO representing it) are not removed at installation failure.
+
+
+This action returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute actionResult.
+
+Note! This action will be removed in a later version.
+Note! This action does not require a transaction. </description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="FtpServerNotAccessibleException"/>
+ <raisesException name="GetFileException"/>
+ <raisesException name="IpAddressException"/>
+ <raisesException name="UpgradeControlFileException"/>
+ <raisesException name="ActionNotAllowedException"/>
+ <raisesException name="InstallException"/>
+ </action>
+ <action name="verifyUpgrade">
+ <description>Verifies that an upgrade is possible.
+
+The operation is not blocked while the verification is executing i.e. after basic controls the operation initiates the verification and returns 'void'.
+
+The progress of this action is indicated in the attribute ProgressHeader.The result of this action is indicated in the attribute ActionResult.
+
+This action returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute actionResult.
+
+Note: This action does not require a transaction.
+
+
+
+</description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="VerifyUpgradeException"/>
+ <raisesException name="ActionNotAllowedException"/>
+ </action>
+ <action name="upgrade">
+ <description>Upgrades the node. The operation is not blocked while upgrade is executing i.e. after basic controls the operation initiates the upgrade and returns 'void'.
+
+Before the real upgrade is started a verification phase is executed.
+
+The progress of this action is indicated in the attribute ProgressHeader.
+
+This action returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute actionResult.
+
+The result of this action is only indicated in attribute ActionResult in case the verification phase discovers that upgrade is not possible.
+
+Note: This action does not require a transaction.
+
+</description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="UpgradeNotPossibleException"/>
+ <raisesException name="ActionNotAllowedException"/>
+ </action>
+ <action name="rebootNodeUpgrade">
+ <description>The same as upgrade except that the hard upgrade sequence is always chosen.
+
+It could be helpful to use this method if the application has start- or upgrade- synchronization problems when using a soft upgrade sequence.
+
+This action returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute actionResult.
+
+The result of this action is only indicated in attribute ActionResult in case the verification phase discovers that upgrade is not possible.
+
+Note: This action does not require a transaction. </description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="UpgradeNotPossibleException"/>
+ <raisesException name="ActionNotAllowedException"/>
+ </action>
+ <action name="confirmUpgrade">
+ <description>The operator invokes this method when the trial period is over.
+The operation is not blocked while upgrade is executing i.e. after basic controls the operation initiates the upgrade and returns 'void'.In case the upgrade fails after 'void' has been returned the attribute ProgressHeader will be set to 'UpgradeExecutionFailed'.
+
+Note! This action does not require a transaction. </description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="UpgradeNotPossibleException"/>
+ <raisesException name="ActionNotAllowedException"/>
+ </action>
+ <action name="cancelUpgrade">
+ <description>Cancels an executing upgrade or an upgrade that is awaiting confirm.
+
+Note: This action performs a node restart so that the CV pointed out in the ConfigurationVersion MO is rolled back.
+
+Note! This action does not require a transaction. </description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="ActionNotAllowedException"/>
+ </action>
+ <action name="forcedInstall">
+ <description>All load modules defined in the Upgrade Package Control file will be downloaded to the node even if the Load Module MO representing the load module already exists i.e. existing load module files are replaced.
+The result of this action is indicated in the attribute ActionResult.In case the installation fails after 'void' has been returned the attribute 'ProgressHeader' is set to 'InstallationExecutionFailed'.Already downloaded load modules (the downloaded file and the Load Module MO representing it) are not removed at installation failure.
+
+
+This action returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute actionResult.
+
+Note! This action will be removed in a later version.
+Note! This action does not require a transaction. </description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="FtpServerNotAccessibleException"/>
+ <raisesException name="GetFileException"/>
+ <raisesException name="IpAddressException"/>
+ <raisesException name="UpgradeControlFileException"/>
+ <raisesException name="ActionNotAllowedException"/>
+ <raisesException name="InstallException"/>
+ </action>
+ <action name="nonBlockingInstall">
+ <description>Load modules defined in the Upgrade Package Control file will only be downloaded to the node if the Load Module MO representing the load module doesn't already exist.
+
+This action is non-blocking i.e. the action initiates the installation and returns 'void' immediately without waiting for the installation to be completed.
+
+In case the installation fails after 'void' has been returned, this will be indicated by change of the value of attribute 'ProgressHeader' to 'ExecutionFailed'. Already downloaded load modules (the downloaded file and the Load Module MO representing it) are not removed at installation failure.
+
+This action returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute actionResult.
+
+Note! This action does not require a transaction.
+</description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="ActionNotAllowedException"/>
+ <raisesException name="InstallException"/>
+ </action>
+ <action name="nonBlockingForcedInstall">
+ <description>All load modules defined in the Upgrade Package Control file will be downloaded to the node even if the Load Module MO representing the load module already exists i.e. existing load module files are replaced.
+This action is non-blocking i.e. the action initiates the installation and returns 'void' immediately without waiting for the installation to be completed.
+The result of this action is indicated in the attribute ActionResult.In case the installation fails after 'void' has been returned the attribute 'ProgressHeader' is set to 'InstallationExecutionFailed'. Already downloaded load modules (the downloaded file and the Load Module MO representing it) are not removed at installation failure.
+
+This action returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute actionResult.
+
+Note! This action does not require a transaction. </description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="ActionNotAllowedException"/>
+ <raisesException name="InstallException"/>
+ </action>
+ <action name="nonBlockingSelectiveForcedInstall">
+ <description>This action only installs the load modules that are required in this node i.e. the load modules required after successful execution of action upgrade on this upgrade package.
+
+A load module is considered to be required if one of the following criteria is fulfilled:
+a) The load module is included in a Repertoire MO where the Repertoire MO is connected to a SwAllocation MO and the SwAllocation MO is connected to a Slot MO, a Fan MO, a Jvm MO, a Webserver MO or an applicable type of application MO.
+b) The load module is of type 'other'.
+
+All required load modules will be downloaded to the node even if the Load Module MO representing the load module already exists i.e. existing load module files are replaced.
+
+This operation is non-blocking i.e. the action initiates the installation and returns "void" immediately without waiting for the installation to be completed.
+The result of this action is indicated in the attribute ActionResult.In case the installation fails after 'void' has been returned the attribute 'ProgressHeader' is set to 'InstallationExecutionFailed'. Already downloaded load modules (the downloaded file and the Load Module MO representing it) are not removed at installation failure.
+
+Note. The behaviour described for this action is also obtained for the other installation actions if the Upgrade Control File indicates that the upgrade package is of type selective (which is recommended).
+
+This action returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute actionResult.
+
+Note! This action does not require a transaction. </description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="ActionNotAllowedException"/>
+ <raisesException name="InstallException"/>
+ </action>
+ <action name="nonBlockingSelectiveInstall">
+ <description>This action only installs the load modules defined in the Upgrade Package Control file that are required in this node i.e. the load modules required after successful execution of action upgrade on this upgrade package.
+
+A load module is considered to be required if one of the following criteria is fulfilled:
+a) The load module is included in a Repertoire MO where the Repertoire MO is connected to a SwAllocation MO and the SwAllocation MO is connected to a Slot MO, a Fan MO, a Jvm MO, a Webserver MO or an applicable type of application MO.
+b) The load module is of type 'other'.
+
+Returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute
+actionResult.
+
+The required load modules will only be downloaded to the node if the Load Module MO representing the load module doesn't already exist.
+
+This action is non-blocking i.e. the action initiates the installation and returns 'void' immediately without waiting for the installation to be completed.
+
+The result of this action is indicated in the attribute ActionResult. In case the installation fails after 'void' has been returned the attribute 'ProgressHeader' is set to 'InstallationExecutionFailed'. Already downloaded load modules (the downloaded file and the Load Module MO representing it) are not removed at installation failure.long
+
+Note. The behaviour described for this action is also obtained for the other installation actions if the Upgrade Control File indicates that the upgrade package is of type selective (which is recommended).
+Note! This action does not require a transaction. </description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="ActionNotAllowedException"/>
+ <raisesException name="InstallException"/>
+ </action>
+ <action name="cancelInstall">
+ <description>This action interrupts an ongoing installation of an upgrade package.
+
+Already downloaded load modules (the downloaded file and the Load Module MO representing it) are not removed at execution of this action.
+
+This action is non-blocking i.e. the action initiates the cancel of the installation and returns 'void' immediately without waiting for the cancellation to be completed.
+
+During execution of this action the value of attribute 'ProgressHeader' is set to 'CancelOfInstallationIsExecuting'.
+
+In case the cancellation fails after 'void' has been returned this will be indicated by change of the value of attribute 'ProgressHeader' to 'CancelOfInstallationFailed'.
+
+Note! This action does not require a transaction.
+
+This action interrupts an ongoing installation of an upgrade package.
+Already downloaded load modules (the downloaded file and the Load Module MO representing it) are not removed at execution of this action.
+This action is non-blocking i.e. the action initiates the cancel of the installation and returns 'void' immediately without waiting for the cancellation to be completed.
+During execution of this action the value of attribute 'ProgressHeader' is set to 'CancelOfInstallationIsExecuting'.The result of this action is indicated in the attribute ActionResult.In case the cancellation fails after 'void' has been returned the attribute 'ProgressHeader' is set to 'CancelOfInstallationFailed'.
+
+This action returns an actionID (created by the server). This actionID shall be used to locate the result of the action in attribute actionResult.
+
+Note! This action does not require a transaction. </description>
+ <returnType>
+ <long/>
+ </returnType>
+ <raisesException name="ActionNotAllowedException"/>
+ </action>
+ <action name="clearUpgradeLogFile">
+ <description>Is used to clear the contents of current upgrade log file.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="UpgradeLogFileNotInUseException"/>
+ <raisesException name="UpgradeLogFileNotAccessibleException"/>
+ </action>
+ </class>
+
+ <class name="Repertoire">
+ <description>The Repertoire is an abstraction of a functionality represented by a plug in unit type (PiuType MO) and one or more load modules (LoadModule MO). The repertoire also provides rules for PiuType/ Load Module combinations valid for a specific function where one function can be provided by one or many PiuType-Load Module combinations.
+These rules are used to load the correct software (Load Modules) to a PlugInUnit. This could be used as operator configuration support and/or in situations where automatic re-configuration is required (hot repair).
+
+MOs of this type are created automatically during system upgrade.
+MOs of this type are possible to create manually but a system upgrade is recommended to create them.</description>
+ <attribute name="userLabel">
+ <description>A user friendly name associated to the managed object. </description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="name">
+ <description>A function friendly name associated to the repertoire. The value must be unique with respect to all repertoires with the same install state.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="info">
+ <description>Information regarding the function.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="piuTypeList">
+ <description>A list containing all PiuType references that has been added to this repertoire.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="PiuType"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="RepertoireId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving SwAllocation MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="SwAllocation"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="OspfInterface">
+ <description>The OSPF Interface MO represents an interface that is used by the OSPF protocol to communicate with a neighbour node. By connecting an OSPF interface to a Link MO that Link is defined as a link to be used by OSPF.
+
+Each OspfInterface MO must always be connected to a OspfArea MO.
+</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ospfAreaRelated">
+ <description>The identity of the OspfArea connected to this OspfInterface. The default value is the default OspfArea MO.</description>
+ <dataType>
+ <moRef name="OspfArea"/>
+ </dataType>
+ </attribute>
+ <attribute name="lsaTransmissionInterval">
+ <description>The time, in seconds, between LSA re-transmissions over the interface - default value 5 seconds.</description>
+ <dataType>
+ <long>
+ <defaultValue>5</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="helloInterval">
+ <description>The time, in seconds, between sending OSPF Hello-packets over the interface. Default value 10 seconds.
+
+Note! Must be a positive value.</description>
+ <dataType>
+ <long>
+ <defaultValue>10</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="routerDeadInterval">
+ <description>The time, in seconds, after which a neighbor router is declared dead when not heard from.
+</description>
+ <dataType>
+ <long>
+ <defaultValue>40</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="interfaceTransitDelay">
+ <description>Estimated delay, in seconds, for the transmission of a link state update package over the interface.
+</description>
+ <dataType>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="interfacePriority">
+ <description>The interface priority. Each router is configured with a priority configured from 0 - 255 where 0 is the lowest priority and 255 the highest.
+
+Note! Must be a positive value.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="relatedLink">
+ <description>Each OSPF interface is connected to one IP link.
+The relatedLink can be either an IpAtmLink or an EthernetLink MO
+reference.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="OspfInterfaceId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfOspfIfEvents">
+ <description>Performance monitoring counter for the number of times this OSPF interface has changed its state or an error has occured.
+
+See RFC 1850.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Ospf">
+ <description>The Ospf MO represents an instance of the Open Shortest Path First (OSPF) routing protocol running in a Cello node.
+
+When the Ospf MO is created a default OspfArea MO is also created. This OspfArea has the areaId 000.000.000.000.
+
+The attribute range0 in the default OspfArea will contain the following values:
+advertise = false
+ipAddress = 000.000.000.000
+subnetMask = 000.000.000.000
+</description>
+ <attribute name="OspfId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ospfRouterId">
+ <description>The ospfRouterId attribute is in the form of an IP address.
+In order to able to set ospfRouterId the attribute
+administrativeState has to be set to locked. The ospfRouterId
+is uniquely identifying the router in the Autonomous System. By
+convention to ensure uniqueness, this should be configured to the
+value of one of the routers IP interface addresses.</description>
+ <mandatory/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="ospfASBdrRtrStatus">
+ <description>The ospfASBdrRtrStatus attribute controls, whether this router is configured as an Autonomous System border router (Routers connected to multiple areas are called area border routers). The attribute must be set to 'True' if the user wants to configure static routes, which should be distributed to other OSPF routes as external routes. Configuration of static routes is the same as adding and deleting static routes to the IpRoutingTable Mo.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the MO.
+The operationalState can only be enabled when the IP MO is in workingMode routerMode.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of the MO.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="ospfAreaBdrRtrStatus">
+ <description>Area border router flag - indicates whether the router is acting as an area border router or not.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="ipMo">
+ <description>The name of the Ip MO that the Ospf MO is to use</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Ip"/>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled. It is a bit mapped CORBA long, where one or more of the bits may be set. If none of the bits are set then the availability status is considered to be undefined.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfOspfOriginateNewLsas">
+ <description>The number of new link-state advertisments that have been originated. This number is incremented each time the router originates a new LSA.
+
+For more detailed information, see RFC 1850.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfOspfRxNewLsas">
+ <description>The number of link-state advertisments received determined to be new instantiations. This number does not include newer instantiations of self-originated link-state advertisments.
+
+For more detailed information, see RFC 1850.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="recoverTopoDb">
+ <description>Indicates whether the topology database is to be recovered from the database at restart.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="topoDbStoreInterv">
+ <description>The interval, in seconds, with which the topology database will be stored.</description>
+ <dataType>
+ <long>
+ <defaultValue>60</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="OspfArea">
+ <description>An OSPF autonomous system is divided into OSPF areas. The OSPF Area MO represents such OSPF areas.
+
+A default OspfArea MO is automatically created when the Ospf MO is created.
+It has the identity = 1, so LDN of this MO will be
+ManagedElement=1,IpSystem=1,Ospf=1,OspfArea=1.
+
+Note! A maximum of 4 OspfAreas can be configured each with a maximum of 8 interfaces.</description>
+ <attribute name="OspfAreaId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="stubArea">
+ <description>Indicates whether the OSPF area is a stub area or not.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="importExternalLsa">
+ <description>Indicates whether importing Autonomous System external LSA's is supported.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="sendAreaSummary">
+ <description>Import Area summary - indicates whether the router will originate and propagate summary LSAs into a stub-area.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="stubAreaMetric">
+ <description>Cost for default route that the router advertises into the area if the area is a stub area and the router is an area border router. By default set to the least metric among the interfaces to other areas.</description>
+ <dataType>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="stubAreaMetricType">
+ <description>Stub Area metric type.
+
+RFC 1850 (OSPF V2 MIB):
+
+comparableCost (external type 1)
+nonComparable (external type 2)</description>
+ <dataType>
+ <enumRef name="OspfMetricType">
+ <defaultValue>comparableCost</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="areaLsaChecksum">
+ <description>Area Lsa checksum - 32-bit unsigned sum of the link-state advertisements LS check sums contained in this area's link-state database.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="areaId">
+ <description>The OSPF area identity in form of an IP address. This areId uniquely identifies the area.
+AreaId 0.0.0.0 is used for the OSPF backbone.
+Range: 000.000.000.000 to 255.255.255.255.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="range0">
+ <description>OspfArea IP address range zero (0).</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="OspfAreaRange"/>
+ </dataType>
+ </attribute>
+ <attribute name="range1">
+ <description>OspfArea IP address range one (1).</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <structRef name="OspfAreaRange"/>
+ </dataType>
+ </attribute>
+ <attribute name="range2">
+ <description>OspfArea IP address range two (2).</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <structRef name="OspfAreaRange"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfOspfSpfRuns">
+ <description>The number of times that the intra-area route table has been calculated using this area's link-state database. This is typically done using Dijkstra's algorithm.
+
+For more detailed information, see RFC 1850.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds a list of the reserving OspfInterface MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="OspfInterface"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <action name="addAreaRange">
+ <description>Add aggregation range. Used to add a range of IP addresses to an OSPF area.
+
+Note! This action requires a transaction.
+</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="range">
+ <description>The area range aggregation.</description>
+ <in/>
+ <dataType>
+ <structRef name="OspfAreaRange"/>
+ </dataType>
+ </parameter>
+ <parameter name="rangeIndex">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="AttrMissingAtCreateException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="NoSuchFieldException"/>
+ <raisesException name="ValueOutOfRangeException"/>
+ <raisesException name="WrongAttributeTypeException"/>
+ </action>
+ <action name="deleteAreaRange">
+ <description>Delete an IP address range. Used to remove a range of IP addresses from an OSPF area.
+
+Input is the area aggregation range index.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="rangeIndex">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroNotAccessibleException"/>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="ValueOutOfRangeException"/>
+ </action>
+ </class>
+
+ <class name="SwitchCoreUnit">
+ <description>The Switch Core Unit MO, SCU, represents the board specific HW on the SCB. This object collects HW failure on the board and sends alarms. It is also used for configuration of board specific FW.
+This board can only be fitted in slot 1 and 28 in a standards subrack.
+The board has a number of switch internal link ports.</description>
+ <notificationTypes>alarm</notificationTypes>
+ <attribute name="userLabel">
+ <description>user label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeStateSili">
+ <description>The administrative state of the switch internal link ports on the switch board. The attribute refers to all ports (locking will lock all ports, unlocking unlock all ports).
+SILI -switch internal link interface.
+</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalStateSil">
+ <description>Operational state indicates the the traffic handling capability of all ports as a group on the board, i.e it is enabled if one or more of the eight ports is enabled. The purpose of this attribute is only for test.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalStateSync">
+ <description>Operational State for network synchronization distribution.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusSil">
+ <description>The availability status of the switch internal link (SIL) ports..
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusSync">
+ <description>Availability state for network synchronization distribution.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="SwitchCoreUnitId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>A list of the reserving MO's.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="silPorts">
+ <description>The attribute provides a list of port numbers.
+The port number is between 0-7 and is used to read state of the switch internal port.
+See action getSilPortState, getOperState and getAvailState.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <long/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <action name="getSilPortState">
+ <description>Returns status of the switch internal link port, which is the same as the LEDs on the unit.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <enumRef name="SilPortState">
+ </enumRef>
+ </returnType>
+ <parameter name="portNr">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="getSilOperState">
+ <description>Returns operational status of the switch internal link port.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <enumRef name="OperState">
+ </enumRef>
+ </returnType>
+ <parameter name="portNr">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="getSilAvailState">
+ <description>Returns availability status of the switch internal link port.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <long/>
+ </returnType>
+ <parameter name="portNr">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ </class>
+
+ <class name="GeneralProcessorUnit">
+ <description>The General purpose Processor Unit MO, GPU, represents the board specific HW on the GPB; hard disk, ethernet and serial port etc.
+
+Note! The 'availabilityStatus' for the GeneralProcessorUnit MO is retreived from the PlugInUnit MO.</description>
+ <attribute name="GeneralProcessorUnitId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Indicates if the function provided by the managed object is capable of performing its normal functions or not.
+
+Note! The value for operationalState is retrived from the GeneralProcessorUnit's parent, i.e. the PlugInUnit.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="hdVolumeDSize">
+ <description>The total size in bytes of the D volume.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="hdVolumeDFreespace">
+ <description>The amount in bytes of freespace available on the D volume.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="hdVolumePSize">
+ <description>The total size in bytes of the P volume.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="hdVolumePFreespace">
+ <description>The amount in bytes of freespace available on the P volume.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds the identity of the reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Jvm">
+ <description>The JVM MO is used to represent the Java Virtual Machine. This object is used for configuration JVM parameters, including SW management of Java class libraries used in the machine.
+
+The local distinguished name of this MO is ManagedElement=1, Equipment=1, JVM=1.</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="classpath">
+ <description>Current classpath, the JVM is using</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="admClasspath">
+ <description>New classpath that will be activated at next restart of JVM. The classpath has a directory, which contains the load module, i.e. the classpath references the load module.</description>
+ <dataType>
+ <sequence>
+ <moRef name="LoadModule"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="freeMemory">
+ <description>Free memory in the java machine, in bytes.
+
+NOTE: Before this value is read from the system the action 'garbageCollect' is invoked.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="totalMemory">
+ <description>Total amount of memory allocated to the java machine, in bytes.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="mopplets">
+ <description>Contains all classes that are to be initilised and started when the JVM restarts.
+
+Technical note: The specified classes must implement the se.ericsson.cello.moframework.Mopplet interface and be found in a jar/zip-file pointed out by the classpath.
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <string/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="main">
+ <description>Defines the start class name.
+e.g. "se.ericsson.cello.oms.Oms"</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="options">
+ <description>Current options:
+ -D&lt;property&gt;=&lt;value&gt; Set a system property value. Commonly java.class.path
+-Xms&lt;size&gt; Specify the size, in bytes, of the memory allocation pool.
+-Xss&lt;size&gt; Set thread stack size in bytes.
+-Xverify:[all | remote | none] Verify classes according to the suboption.
+ -Xverify:all verifies all classes.
+ -Xverify:remote verifies remote classes only.
+ -Xverify:none turns off class verification.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="JvmId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="properties">
+ <description>Determines the current system properties.
+
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <string/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="reliableProgramUniter">
+ <description>A reference to the ReliableProgramUniter that refers to the programs in the which the JVM executes.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ReliableProgramUniter"/>
+ </dataType>
+ </attribute>
+ <attribute name="admMain">
+ <description>New start class that will be activated at next restart of the JVM.
+e.g. "se.ericsson.cello.oms.Oms"</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="admOptions">
+ <description>This attribute is used when setting one or more administrative options.
+
+A set option is operational after the next Java Machine restart.
+
+See also attribute 'options'
+
+One or more options can be set, one option in each string of the
+sequence according to description below:
+
+Current options:
+ -D&lt;property&gt;=&lt;value&gt; Set a system property value. Commonly java.class.path
+-Xms&lt;size&gt; Specify the size, in bytes, of the memory allocation pool.
+-Xss&lt;size&gt; Set thread stack size in bytes.
+-Xverify:[all | remote | none] Verify classes according to the suboption.
+ -Xverify:all verifies all classes.
+ -Xverify:remote verifies remote classes only.
+ -Xverify:none turns off class verification.</description>
+ <dataType>
+ <sequence>
+ <string/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBySwAllocation">
+ <description>This attribute holds the identity of the reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="SwAllocation"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <action name="garbageCollect">
+ <description>Runs the garbage collector.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="setProperty">
+ <description>Sets a system property (i.e. propertys in the operating system).
+Note! The valeus set with this action is not saved in the database.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="name">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="value">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="restart">
+ <description>Restart of executing JVM instance.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="SwitchFabric">
+ <description>This MO represents the switch of a Cello node. It is used for general switch configuration.
+
+The system creates automatically one instance of this MO at restart.
+
+Today, only a maximum of 32 Switch Modules MOs and 2 SwitchInternalLinks MOs per InternalLinkGroup MOs are allowed in a Cello node. However, in theory the switch addressing space in the system allows up to 256 SwitchModules MOs. This would then mean there are 255 InternalLinkGroup MOs, each of which is allowed 256 SwitchInternalLink MOs by the addressing.
+
+The local distinguished name of this MO is ManagedElement=1, SwitchFabric=1.
+
+</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="SwitchFabricId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="SwitchModule">
+ <description>This MO represents two switch planes of one sub-rack, i.e. either the main switch or an external switch.
+
+Note! In a non-redundant system the administrativeStateSwitchPlaneA/B has to be set to locked for the non-present plane. </description>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="switchModuleNumber">
+ <description>Indicates the number of the switch module, SMN.
+
+switchModuleNumber &amp;gt;= 0
+
+The main switch module, with one or two TimingUnits, is given SMN = 0. SMN for extension switch modules depends on the port pair that the extension switch module is connected to in the main switch module.
+
+The SMN is calculated according to the following formula:
+
+Switch module number [1..255] = int (APN/2)*8 + ISL-port in main [1..8]
+
+APN - ASCC port number
+ISL - inter-switch link</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="secondSmnEvaluation">
+ <description>secondSmnEvaluation - There are two cables that
+are relevant for Switch Module Number (smn) numbering
+If the cabling is wrong secondSmnEvaluation
+will show the second opinion about smn.
+Under normal conditions secondSmnEvaluation = smn.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of the switch module.
+
+Note! When setting the 'administrativeState' to shutting down a notification about that the state has changed to 'locked' will be sent towards the operator. There is however no guarantee that this operation has been succesful despite the notification and state change due to limitations in the resource layer
+</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>unlocked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeStateSwitchPlaneA">
+ <description>The administrative state of switch plane A.
+It is not allowed to lock both switch plane A and B.
+
+Note! When setting the 'administrativeState' to shutting down a notification about that the state has changed to 'locked' will be sent towards the operator. There is however no guarantee that this operation has been succesful despite the notification and state change due to limitations in the resource layer</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>unlocked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeStateSwitchPlaneB">
+ <description>The administrative state of switch plane B.
+It is not allowed to lock both switch plane A and B.
+
+Note! When setting the 'administrativeState' to shutting down a notification about that the state has changed to 'locked' will be sent towards the operator. There is however no guarantee that this operation has been succesful despite the notification and state change due to limitations in the resource layer</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>unlocked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the Switch Module. At least one of switch plane is enabled. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalStateSwitchPlaneA">
+ <description>The operational state of Switch Module plane A. The state is disabled if any switch ports is faulty. But switch may still be used.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalStateSwitchPlaneB">
+ <description>The operational state of Switch Module plane B. The state is disabled if any switch ports is faulty. But switch may still be used.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status of the Switch Module.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusSwitchPlaneA">
+ <description>The availability status of the Switch Plane A.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusSwitchPlaneB">
+ <description>The availability status of the Switch Plane B.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="activeSwitchPlane">
+ <description>The active switch plane: A, B. During multiple faults, both plan A and B may be used.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="ActiveSwitchPlane">
+ <defaultValue>switchPlaneA</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="SwitchModuleId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="InternalLinkGroup">
+ <description>The Internal Link Group MO represents all switch internal links connecting the main switch to an external switch.
+
+Switch internal links are automatically grouped in Reliable Groups for redundancy.</description>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="switchModuleNumber1">
+ <description>Reference to the SwitchModule MO that is interconnected by the link in the InternalLinkGroup.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="SwitchModule"/>
+ </dataType>
+ </attribute>
+ <attribute name="switchModuleNumber2">
+ <description>Reference to the SwitchModule MO that is interconnected by the link in the InternalLinkGroup.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="SwitchModule"/>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative status of internal link group.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>unlocked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational status of internal link group.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="InternalLinkGroupId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="getRlgLinks">
+ <description>Returns a list of resource instance identities of the switch internal links in the specified Reliable Group.
+
+The existing Reliable Groups are listed with action getReliableLinkGroups.
+
+Note! This action is transactional.</description>
+ <returnType>
+ <sequence>
+ <longlong/>
+ </sequence>
+ </returnType>
+ <parameter name="rlgNumber">
+ <description>Reliable link group number.</description>
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="getLinkStatus">
+ <description>Returns the status of the specified switch internal link, within the specified Reliable Group.
+
+Note! This action is transactional.</description>
+ <returnType>
+ <enumRef name="SwitchReliableGroup">
+ </enumRef>
+ </returnType>
+ <parameter name="instanceId">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <parameter name="rlgNumber">
+ <description>Reliable link group number.</description>
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="getReliableLinkGroups">
+ <description>Returns a sequence of Reliable Group numbers.
+
+Each Reliable Group is identified by a unique number which can be used to read out the identities of the switch internal links that are allocated to the Reliable Group. This is done with action getRlgLinks.
+
+The allocation of switch internal links to Reliable Groups is automatic.
+
+Note! This action is transactional.
+</description>
+ <returnType>
+ <sequence>
+ <long/>
+ </sequence>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ </class>
+
+ <class name="SwitchInternalLink">
+ <description>This MO represents a link interconnecting the from either a SCB or SXB port on the main switch to a SCB on an external switch.
+
+The main switch is located in the hub subrack.
+
+The SCB is represented by the SwitchCoreUnit MO, while the SXB is represented by the SwitchExtensionUnit MO.
+
+Switch internal links are automatically grouped in Reliable Groups for redundancy.</description>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="SwitchInternalLinkId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="plugInUnit1">
+ <description>The reference of one connection point for a SwitchCoreUnit or SwitchExtensionUnit.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="plugInUnit2">
+ <description>The reference of one connection point for a SwitchCoreUnit or SwitchExtensionUnit.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="siliport1">
+ <description>Switch internal port number on PlugInUnit1.
+
+Note!
+On a standard SCB/SXB board, the ports are labeled from the bottom to the top.
+
+Port nr -&gt; label:
+ '0' 'D'
+ '1' 'C'
+ '2' 'B'
+ '3' 'A'
+
+Also note that his mapping will change when adding/removing a board.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>3</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="siliport2">
+ <description>Switch internal port number on PlugInUnit2.
+
+Note!
+On a standard SCB/SXB board, the ports are labeled from the bottom to the top.
+
+Port nr -&gt; label:
+ '0' 'D'
+ '1' 'C'
+ '2' 'B'
+ '3' 'A'
+
+Also note that his mapping will change when adding/removing a board.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>3</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of switch internal link.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>unlocked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalStateTraffic">
+ <description>The operational state of switch internal link. There is no traffic if the link is disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusTraffic">
+ <description>The availabilityl status of switch internal link.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalStateSync">
+ <description>The operational state of sync link. There is no clock distribution if the link is disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusSync">
+ <description>The availability state of sync link.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Etm4">
+ <description>This MO represents the hardware of the ET-M4 board type. It only represents the ET specific hardware, while the DBM module of the board is represented by the PlugInUnit MO.
+
+The ET-M4 board contains 2 physical ports that can be configured as either STM1(ETSI/TTC) or OC3C (ANSI). The board supports unchannelised ATM access (i.e. it maps ATMs cells directly into an SDH VC4 container).
+
+The board supports up to 1800 ATM VC connections.
+The number of terminated VPs are limited to 48/board.
+The board supports up to 750 VC UBR+ connections.
+
+The ET-M4 board contains 128 AAL2 multiplexers.
+The ET-M4 board supports up to 256 bidirectional F4/F5 PM flow per port.
+
+Note! IMA is not applicable for the ETM4 board.
+
+Note! The number of VCC TP+VPC TP with performance monitoring enabled (i.e. PM mode &lt;&gt; off) is restricted to 256 per board.
+
+Note! When using the Etm4 board the performance monitoring counters in the transmit direction found on the AtmPort MO does not show the following cells: CC cells and OAM FPM cells.</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Enabled or disabled according to the actual operational state of the hardware ETM4. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="Etm4Id">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="VpcTp">
+ <description>Virtual path connection termination point, VpcTp, is used to represent the point where the VPC and associated overhead (F4 OAM cells) are terminated/originated.
+
+Note! The performance monitoring counters in this MO is set to 0 when counterMode is set to PM_MODE_ON.
+In PM_MODE_OFF no information at all is retrived. So any value for pm-monitoring is measured from the time
+of setting counterMode to PM_MODE_ON.
+At node restart these performance monitoring counters is reset to 0.</description>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="VpcTpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>enabled or disabled according to the actual operational state of the VpcTp</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="continuityCheck">
+ <description>Continuity checking means that a cell is sent downstream when no user cell has been sent for a period of nominally 1 second. Continuity check both enables generation of CC cells as well as detection of LOC</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="counterMode">
+ <description>PM mode is set to indicate type of performance monitoring mode (i.e. activation of bidirectional PM measurements).
+
+</description>
+ <dataType>
+ <enumRef name="AtmCounterMode">
+ <defaultValue>PM_MODE_OFF</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="nomPmBlkSize">
+ <description>Nominal performance monitoring (PM) blocksize. The minimum number of ATM cells to send before sending a Forward Performance Monitoring, FPM, cell.
+</description>
+ <dataType>
+ <enumRef name="AtmNomPmBlkSize">
+ <defaultValue>NOM_PM_BLKSIZE_2_10</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwLostCells">
+ <description>Performance monitoring counter for number of lost forward cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwMissinsCells">
+ <description>Performance monitoring counter for number of forward missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwErrBlocks">
+ <description>Performance monitoring counter for number of forward errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostFpmCells">
+ <description>Performance monitoring counter for number of lost Forward Performance Monitoring, FPM, cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwLostCells">
+ <description>Performance monitoring counter for number of lost backward cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwMissinsCells">
+ <description>Performance monitoring counter for number of backward missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwErrBlocks">
+ <description>Performance monitoring counter for number of backward errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostBrCells">
+ <description>Performance monitoring counter for number of lost Backward Reporting, BR, cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="alarmReport">
+ <description>Attribute to decide what type of alarms to be reported.</description>
+ <dataType>
+ <enumRef name="AlarmReport">
+ <defaultValue>ALARM_LOC</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <action name="eteLoopBack">
+ <description>This action performs VC end to end loopback from this VpcTp.
+false=Failed, true=Succeded
+
+Note! This action requires a transaction.
+</description>
+ <returnType>
+ <boolean/>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="VplTp">
+ <description>This MO is used to represent the termination of a VP link.
+
+Note that a maximum of 999 MO's of this type may be configured.
+
+Note! For information on how many VplTp's that can be configured under the AtmPort MO please refer to the board that is parent to the termination reserved by the AtmPort MO.
+
+The performance monitoring counters in the VplTp MO is set to 0 (zero) at start or restart of the node.
+When the value is to large to fit in to a long (31bit) the counter turns over and starts from 0 again.</description>
+ <attribute name="userLabel">
+ <description>This MOs user label.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="atmTrafficDescriptor">
+ <description>Reference to the Atm Traffic Descriptor.</description>
+ <mandatory/>
+ <dataType>
+ <moRef name="AtmTrafficDescriptor"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>enabled or disabled according to the actual operational state of the VplTp.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="externalVpi">
+ <description>This is the virtual path identifier for the external ATM cells.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmReceivedAtmCells">
+ <description>Performance monitoring counter for number of received ATM cells for the VplTp.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmTransmittedAtmCells">
+ <description>Performance monitoring counter for number of transmitted ATM cells.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="VplTpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="TimingUnit">
+ <description>This MO represents a timing unit (reference clock) in the node.
+
+The corresponding Program shall be of LoadModuleLoaderType, SpmFpgaLoader.</description>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Operational state of TimingUnit</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status of the TimingUnit.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="TimingUnitId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="PiuType">
+ <description>The PiuType is an MO that holds product information about a PlugInUnit and the execution resources of the PlugInUnit. It is created/deleted during a software upgrade.
+The PiuType is used when creating execution MOs connected to a PlugInUnit and when allocating software to this resource.
+
+MOs of this type are created automatically during system upgrade.
+MOs of this type are possible to create manually but a system upgrade
+is recommended to create them.
+
+
+</description>
+ <attribute name="userLabel">
+ <description>A user friendly name associated to the managed object. </description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="productData">
+ <description>The productData describes the product number, short product revision, product name and product information of the PlugInUnit. The production date is not used.
+
+Trailing letters in the revision is recommended to be excluded in the PiuType. Example: R2B will be R2 without trailing letter, R2B/3 must be R2B/3 in the PiuType, R2B/A should be R2 in the PiuType.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="AdminProductData"/>
+ </dataType>
+ </attribute>
+ <attribute name="boardWidth">
+ <description>The width of the PlugInUnit board in steps of 5 mm.
+A PlugInUnit can use/cover more than the slot that it occupies.
+
+Example: boardWidth=3 corresponds to 3*5 = 15 mm.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long/>
+ </dataType>
+ </attribute>
+ <attribute name="airFlowData">
+ <description>Control value m3/h for the fan unit. Needed by cooling function.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="AirFlowData"/>
+ </dataType>
+ </attribute>
+ <attribute name="PiuTypeId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="role">
+ <description>The value will be MP if a board has the role of a Main processor.
+The value will be BP if a board has the role of a device board
+Otherwise the value will be OTHERS.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="PiuRole">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity's of the reserving MO's.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <action name="numberOfMoConfigurations">
+ <description>Returns the number of entries in the PIUTypeConfigurationArray.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <long/>
+ </returnType>
+ </action>
+ <action name="getMoConfiguration">
+ <description>Returns a struct of a specific MoConfiguration at a given index.
+The moConfiguration holds information about how to create the
+subordinate objects for a specific piu type.
+
+Precondition: 0 &lt;= index &lt;= numberOfMoConfigurations() - 1
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <structRef name="PiuTypeMOConfiguration"/>
+ </returnType>
+ <parameter name="index">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="InvalidIndexException"/>
+ </action>
+ </class>
+
+ <class name="SwAllocation">
+ <description>This MO is primarily used to handle data for automatic configuration of load modules. Automatic in the meaning that the system selects the appropriate load module and revision. A SWA may be related to a slot, indicating that a specific functionality is requested at this location. The SWA is manually created by the operator.
+
+The SWA object is related to (one or more) repertoires, which hold information on possible PIU-type/revisions and load module combinations.
+
+In some cases (e.g multi-purpose boards, boards with processor/FPGA-pools) it may not be possible to completely configure the PIU without instructions from the operator (e.g which load module runs on which processor/FPGA). In these cases a specialization of the SWA has to be designed in such a way that it can be manually configured.
+
+When a SwAllocation MO depends on a ManagedObject MO, this ManagedObject actually represents a RBS Fan.
+
+MOs of this type are created automatically during system upgrade.
+MOs of this type are possible to create manually but a system upgrade is recommended to create them.</description>
+ <attribute name="userLabel">
+ <description>Free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="role">
+ <description>The role of a slot/PIU. The role must be unique with respect to other SwAllocations in the node.
+
+This is a preparation to introduce predefined SwAllocation in future upgrade packages.</description>
+ <mandatory/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="repertoireList">
+ <description>A list of references to repertoires.</description>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="Repertoire"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="slotList">
+ <description>A list of references to mainly slots in a subrack, e.g. Slot or Fan MO. It may also refer to other objects handling auxiliary units, e.g. RBS Fan.</description>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="SwAllocationId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="addRepertoire">
+ <description>Adds the specifed repertoire to this list.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="aRepertoire">
+ <in/>
+ <dataType>
+ <moRef name="Repertoire"/>
+ </dataType>
+ </parameter>
+ <raisesException name="IllegalArgumentTypeException"/>
+ </action>
+ <action name="deleteRepertoire">
+ <description>Removes the first occurrence of the specified repertoire from this list.
+
+Notw! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="aRepertoire">
+ <in/>
+ <dataType>
+ <moRef name="Repertoire"/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="addSlot">
+ <description>Adds the specified Slot to the slotList.
+The slot can only be of type Slot MO, Fan MO, WebServer MO, JVM MO or an applicable type of application MO (e.g. for "RBS Fans").
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="aSlot">
+ <in/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </parameter>
+ <raisesException name="IllegalArgumentTypeException"/>
+ </action>
+ <action name="deleteSlot">
+ <description>Removes the first occurrence of the specified slot from this list.
+The slot can only be of type Slot MO, Fan MO, WebServer MO or an
+applicable type of application MO (e.g. for "RBS Fans").
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="aSlot">
+ <in/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="deleteAllRepertoires">
+ <description>Removes all repertoires from this list and sets its size to zero.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="deleteAllSlots">
+ <description>Removes all slots from this list and sets its size to zero.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="addSlots">
+ <description>Adds the specified Slot to the slotList.
+The slot can only be of type Slot MO, Fan MO, WebServer MO, JVM MO or an applicable type of application MO (e.g. for "RBS Fans").
+If the slot exists in the list, the object is ignored.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="managedObjects">
+ <in/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </parameter>
+ <raisesException name="IllegalArgumentTypeException"/>
+ </action>
+ <action name="addRepertoires">
+ <description>Adds the specifed repertoire to this list.
+
+If the repertoires exist in the list the repertoire is ignored.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="repertoire">
+ <in/>
+ <dataType>
+ <sequence>
+ <moRef name="Repertoire"/>
+ </sequence>
+ </dataType>
+ </parameter>
+ <raisesException name="IllegalArgumentTypeException"/>
+ </action>
+ </class>
+
+ <class name="MediumAccessUnit">
+ <description>The Medium Access Unit (MAU) MO represents the Ethernet transceiver function on a General Processor Board (GPB).
+
+Note! Ethernet links which are modelled by a MediumAccessUnit MO are used for O&amp;M IP traffic only. MediumAccessUnit MOs must not be configured under a GeneralProcessorUnit MO which have a IpAccessHostGpb referring to it.
+
+Note! This object is known in standards as "MediumAttachmentUnit".
+</description>
+ <attribute name="userLabel">
+ <description>Label for free use.
+</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Description of operational state which has an enumerated datatype</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="MediumAccessUnitId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="connectorLabel">
+ <description>This attribute is used by a management system to show the label on the port the connector is attached to.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>Eth</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDot3StatsLateCollisions">
+ <description>Performance management counter for the number of times that a collision was detected on the interface after the minimum length of a frame.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDot3StatsFCSErrors">
+ <description>Performance management counter for the number of frames that did not pass the FCS check.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="linkSpeed">
+ <description>The Link Speed, measurment unit is Mb/s..</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="duplexMode">
+ <description>The duplex mode used.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="MauDuplexMode">
+ <defaultValue>FULL_DUPLEX</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="ReliableProgramUniter">
+ <description>A Reliable Program Uniter (RPU) is a controlling and addressing entity providing one common addressing unit for two Reliable Programs. Or more correctly for parts of two Reliable Programs, each part is called a Resource Suite Handler (RSH). The RSH is implemented and owned by the application. It is not a function or a concept within Cello.
+
+MOs of this type are created automatically during system upgrade.
+MOs of this type are possible to create manually but a system upgrade
+is recommended to create them.</description>
+ <attribute name="userLabel">
+ <description>For free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reliableProgramLabel">
+ <description>Reliable Program Label.
+Compare this to the reliableProgramLabel in LoadModule MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="admActiveSlot">
+ <description>Reference to slot, contains the running "Normal" relation to a slot. If the reference is set to the passive slot, the passive slot will be cleared and only one relation will be set.</description>
+ <mandatory/>
+ <dataType>
+ <moRef name="Slot"/>
+ </dataType>
+ </attribute>
+ <attribute name="admPassiveSlot">
+ <description>Reference to slot, contains the running "Stand-by" relation to a slot. If the reference is set to the active slot or a null value, the passive slot will be cleared. </description>
+ <dataType>
+ <moRef name="Slot"/>
+ </dataType>
+ </attribute>
+ <attribute name="switchOver">
+ <description>This attribute controls when to switchover the RPU, if a certain type error situation occurs.</description>
+ <dataType>
+ <enumRef name="RPUSwitchOverMode">
+ <defaultValue>AtPiuFault</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="normalisation">
+ <description>This attribute controls when to switch back the RPU, after error recovery has been done.</description>
+ <dataType>
+ <enumRef name="RPUNormalisationMode">
+ <defaultValue>Automatic</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="replication">
+ <description>This attribute indicates that which level of data replication that is associated with the RPU.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="RPUReplicationMode">
+ <defaultValue>ApplControlled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalMode">
+ <description>This attribute indicates if the RSH execution mode (active/passive) in the two Reliable Program, matches the normal/stand-by relations set on the corresponding RPU.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="RPUOperationalMode">
+ <defaultValue>Unavailable</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="ReliableProgramUniterId">
+ <mandatory/>
+ <noNotification/>
+ <nonPersistent/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <action name="switch">
+ <description>This action will force the two corresponding RSHs to change their execution mode (active/passive). It will lead either to a switchover or to a switchback, depending of what value the operational Mode attribute is showing.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="ActionNotAllowedException"/>
+ </action>
+ </class>
+
+ <class name="ManagedElementData">
+ <description>This object contains attributes and actions on Cello node-level.
+
+The ManagedElementData MO is automatically created and cannot be deleted.
+
+The local distinguished name of this MO is ManagedElement=1, ManagedElementData=1.</description>
+ <systemCreated/>
+ <attribute name="ManagedElementDataId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="autoConfigurationAllowed">
+ <description>This attribute specifies if the system is allowed to auto create detected objects. Note that slots will always be auto created.
+
+Note! When setting this attribute from true to false the system creates a new CV.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="documentServerAddress">
+ <description>The base URL for the documentation server (ALEX). The attribute is read by Element Management application to find the documentation server in the network.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="logonServerAddress">
+ <description>A list of node names or IP addresses of the single logon servers (SLSs). The list uses commas to seperate the single logon server addresses, e.g. "https://SLS1,https://SLS2,https://SLS3", these addresses consists of the URLs to the concerned SLS servers. The attribute is read by Element Management application to find the single logon server in the network.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="dhcpServerAddresses">
+ <description>IP addresses to the DHCP server, used by the DHCP Relay Agent.
+
+Default is an empty array.
+
+Adding and removing addresses is done through the actions addDhcpServerAddress() and removeDhcpServerAddress().
+
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <string>
+ <defaultValue>empty</defaultValue>
+ </string>
+ <length>10</length>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="performanceDataPath">
+ <description>This attribute is used by the internal performance management service
+to know where to store it's data files. The attribute is the name of
+a path in the node.
+
+Example: /c/public_html/cello/XML_files/</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ntpServerAddressPrimary">
+ <description>This is the IP address to the NTP server</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ntpServiceActivePrimary">
+ <description>This is a boolean that controls if the node should poll the primary NTP server for information.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="ntpMinPollPrimary">
+ <description>This value states the minimum interval (in seconds) for polling the primary NTP server.
+
+Note! This value has to be &gt; 0.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>16</min> <max>131072</max>
+ </range>
+ <defaultValue>64</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ntpMaxPollPrimary">
+ <description>This value states the maximum interval (in seconds) for polling the primary NTP server.
+
+Note! This value has to be &gt; 0.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>16</min> <max>131072</max>
+ </range>
+ <defaultValue>1024</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ntpBurstFlagPrimary">
+ <description>This is the burst flag used towards the primary NTP server.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="ntpServerAddressSecondary">
+ <description>This is an alternative IP address to a NTP server</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ntpServiceActiveSecondary">
+ <description>This is a boolean that controls if the node should poll the secondary NTP server for information.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="ntpMinPollSecondary">
+ <description>This value states the minimum interval (in seconds) for polling the secondary NTP server.
+
+Note! This value has to be &gt; 0.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>16</min> <max>131072</max>
+ </range>
+ <defaultValue>64</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ntpMaxPollSecondary">
+ <description>This value states the maximum interval (in seconds) for polling the secondary NTP server.
+
+Note! This value has to be &gt; 0.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>16</min> <max>131072</max>
+ </range>
+ <defaultValue>1024</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ntpBurstFlagSecondary">
+ <description>This is the burst flag used towards the secondary NTP server.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="nodeUTCTime">
+ <description>This attribute specifies the UTC time used in the node. The attribute value is milliseconds since epoch (January 1, 1970, 00:00:00 GMT).
+The value may only be set while ntpServiceActive both for primary and secondary is false.</description>
+ <dataType>
+ <longlong>
+ <defaultValue>0</defaultValue>
+ </longlong>
+ </dataType>
+ </attribute>
+ <attribute name="nodeLocalTimeZone">
+ <description>This value states in what time zone the node is located. This attribute is needed by management application to convert UTC time from a log or NTP service to local time.
+It will not change the real time clock on the node.
+
+The timeZone is represented by three characters, example GMT.
+
+Available options are:
+
+TimeZone ID Offset
+GMT (Greenwich Mean Time) 0
+UTC (Coordinated Universal Time) 0
+ECT ( Central European Standard Time) + 1
+EET (Eastern European Time) + 2
+ART (Eastern European Time) + 2
+EAT (Eastern African Time) + 3
+MET (Iran Time) + 3.5
+NET (Armenia Time) + 4
+PLT (Pakistan Time) + 5
+IST (India Standard Time) + 5.5
+BST (Bangladesh Time) + 6
+VST (Indochina Time) + 7
+CTT (China Standard Time) + 8
+JST (Japan Standard Time) + 9
+CST (Central Standard Time) + 9.5
+EST (Eastern Standard Time) + 10
+AET (Eastern Standard Time) + 10
+SST (Solomon Is. Time) + 11
+NST (New Zealand Standard Time) + 12
+CAT (Central Alaska Time) - 1
+AGT (Argentina Time) - 3
+BET (Brazil Time) - 3
+CNT (Newfoundland Standard Time) - 3.5
+PRT (Atlantic Standard Time) - 4
+IET (Eastern Standard Time) - 5
+ACT (Central Standard Time) - 6
+PNT (Mountain Standard Time) - 7
+MST (Mountain Standard Time) - 7
+PST (Pacific Standard Time) - 8
+AST (Alaska Standard Time) - 9
+HST (Hawaii Standard Time) - 10
+MIT (West Saoma Time) - 11
+--
+
+Reference: http://www.greenwichmeantime.com
+</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="daylightSavingTime">
+ <description>This attribute states weather daylight saving time is used on this node. It is used to by the management application and will not change the real time clock on the node.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="hdVolumeCSize">
+ <description>The total size of the C volume on the Cello node in bytes. The C volume may be replicated on several hard disks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="hdVolumeCFreespace">
+ <description>The number of bytes of free space available on the C volume. The C volume may be replicated on several hard disks in a Cello node.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="nodeUniqueID">
+ <description>This is a unique node identity to be set only in the factory.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="swServerUrlList">
+ <description>A list of URLs of external server for downloading of software. A comma-separated list or URLs, complete with path and name of property file.
+
+Note: For downloading of software for system upgrade, see attribute ftpServerIpAddress in MO UpdradePackage.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="piuGroupEscalationType">
+ <description>The type of node restart when it is a problem with the last PIU in a PIU group.</description>
+ <dataType>
+ <enumRef name="NodeRestartType">
+ <defaultValue>WARM_AT_PIU_RESTART</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="syncModeOperation">
+ <description>The sync mode operation of the node. Note that this attribute is only relevant when the node contains CBU board. For all other cases the value shall be set to NOT_USED.</description>
+ <dataType>
+ <enumRef name="SyncMode">
+ <defaultValue>NOT_USED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <action name="createNtpPrimary">
+ <description>This action creates the primary Network Time Protocol. There can only exist one primary and one secondary ntp.
+
+Once the ntp is created it is possible to change the attributes, i.e ip address, burst flag, max- and min poll and which is the active one.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="ntpServerAddressPrimary">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="ntpMinPollPrimary">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <parameter name="ntpMaxPollPrimary">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <parameter name="ntpBurstFlagPrimary">
+ <in/>
+ <dataType>
+ <boolean/>
+ </dataType>
+ </parameter>
+ <parameter name="ntpServiceActivePrimary">
+ <in/>
+ <dataType>
+ <boolean/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="createNtpSecondary">
+ <description>This action creates the secondary/alterative Network Time Protocol.
+There can only exist one primary and one secondary ntp.
+
+Once the ntp is created it is possible to change the attributes, i.e ip address, burst flag, max- and min poll and which is the active one.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="ntpServerAddressSecondary">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="ntpMinPollSecondary">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <parameter name="ntpMaxPollSecondary">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <parameter name="ntpBurstFlagSecondary">
+ <in/>
+ <dataType>
+ <boolean/>
+ </dataType>
+ </parameter>
+ <parameter name="ntpServiceActiveSecondary">
+ <in/>
+ <dataType>
+ <boolean/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="deleteNtpPrimary">
+ <description>This action deletes the primary NTP.
+
+An exception will be thrown if the primary attributes are accessed (set and get).
+
+Note! This action requires a transaction.
+</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="deleteNtpSecondary">
+ <description>This action deletes the secondary NTP.
+
+An exception will be thrown if the secondary attributes are accessed (set and get).
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="addDhcpServerAddress">
+ <description>Takes an array of Ip addresses (Strings), and adds them to the list held by the Dhcp Relay Agent fRO.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="ipAddressArray">
+ <description>Elements are assumed to have the format of a String with 4 fields of numerics, each field separated with a dot. E.g. 123.322.34.123. An empty array or empty string in first element is not allowed. Max 10 elements.</description>
+ <in/>
+ <dataType>
+ <sequence>
+ <string/>
+ </sequence>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="removeDhcpServerAddress">
+ <description>Takes an array of Ip addresses (Strings), and removes them from the list held by the Dhcp Relay Agent fRO.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="ipAddressArray">
+ <description>Elements are assumed to have the format of a String with 4 fields of numerics, each field separated with a dot. E.g. 123.322.34.123. An empty array or empty string in first element is not allowed. Max 10 elements.</description>
+ <in/>
+ <dataType>
+ <sequence>
+ <string/>
+ </sequence>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="setNodeUniqueId">
+ <description>Used for setting the nodeUniqueId attribute. This method should only be used in the factory, i.e. it is not for general use by the operator.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="nodeUniqueId">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ </class>
+
+ <class name="SwitchExtensionUnit">
+ <description>This MO represents the Switch Extension Unit, SXU, board. The board may only be inserted in slot 2-27 (in a standard subrack).
+If redundant links are used, two boards must be inserted next to each other.
+The board has a number of switch internal link ports.</description>
+ <attribute name="SwitchExtensionUnitId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>This attribute is used to hold a user friendly name of the object if needed.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeStateSil">
+ <description>The administrative state of switch internal link ports on the switch board.
+The attribute refers to all ports (locking will lock all ports, unlocking will unlock all ports).
+SIL- switch internal link.
+
+</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>unlocked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalStateSil">
+ <description>Operational State for all ports. Operational state is enabled if one of the eight ports is enabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalStateSync">
+ <description>Operational State for network synchronization distribution</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusSil">
+ <description>The availability state of switch internal link (sil) ports.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusSync">
+ <description>The availability state of the sync link.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The attribute is set by the action Reserve.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="SilPorts">
+ <description>The attribute provides a list of port numbers.
+The port number is between 0-7 and is used to read state of the switch internal port.
+Se action getSilPortState, getSilOperState and getSilAvailState.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <long/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <action name="getSilPortState">
+ <description>Returns status of the switch internal link port.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <enumRef name="SilPortState">
+ </enumRef>
+ </returnType>
+ <parameter name="portNr">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="getSilOperState">
+ <description>Returns operational status of the switch internal link port.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <enumRef name="OperState">
+ </enumRef>
+ </returnType>
+ <parameter name="portNr">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="getSilAvailState">
+ <description>Returns availability status of the switch internal link port.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <long/>
+ </returnType>
+ <parameter name="portNr">
+ <in/>
+ <dataType>
+ <long/>
+ </dataType>
+ </parameter>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ </class>
+
+ <class name="Aal2PathDistributionUnit">
+ <description>This MO is used to represent an AAL2 Path Distribution Unit. Such a unit handles a set of Aal2PathVccTps that belong to the same Aal2 AP and that are handled by the same Path Resource Handling Program.
+This Path Resource Handling Program is referenced by the rpuId attribute.</description>
+ <attribute name="Aal2PathDistributionUnitId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="rpuId">
+ <description>The physical location of a CPS RC (Common Part Sub-Layer Resource Control) program represented by a reference to a ReliableProgramUniter.
+
+Note that one ReliableProgramUniter MO may only be referenced once under one Aal2Ap. That means all Aal2PathDistributionUnits must reference different ReliableProgramUniter MO's.
+
+Two Aal2PathDistributionUnits under different Aal2Ap's may however reference the same ReliableProgramUniter MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ReliableProgramUniter"/>
+ </dataType>
+ </attribute>
+ <attribute name="aal2PathVccTpList">
+ <description>List of references to Aal2PathVccTp MO:s.
+Note that setting of this attribute removes the current list of Aal2PathVccTp's.
+Each reference must be unique among all paths within all Aal2PathDistributionUnit's belonging to the same Aal2Ap.</description>
+ <dataType>
+ <sequence>
+ <moRef name="Aal2PathVccTp"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <action name="addPath">
+ <description>This action adds a list of Aal2PathVccTps to an Aal2PathDistributionUnit.
+
+If the data contains a reference to a non existing path, the exception InvalidReference is raised.
+
+If the path list contains a path that has a non-unique aal2PathId value, then the exception Aal2PathIdNotUnique is raised. The pathId value must be unique within all Aal2PathDistributionUnits under the same Aal2Ap.
+
+If the path list contains a path that already belongs to a Aal2PathDistributionUnit, then the exception PathAlreadyRegistered is raised.
+
+Note! Adding one or more Aal2PathVccTps using this action updates the attribute 'Aal2PathVccTpList'.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="aal2PathVccTpId">
+ <in/>
+ <dataType>
+ <sequence>
+ <moRef name="Aal2PathVccTp"/>
+ </sequence>
+ </dataType>
+ </parameter>
+ <raisesException name="InvalidReferenceException"/>
+ <raisesException name="Aal2PathIdNotUniqueException"/>
+ <raisesException name="PathAlreadyRegisteredException"/>
+ </action>
+ <action name="removePath">
+ <description>This action removes a list (sequence) of AAL2 path's from the Aal2PathDistributionUnit.
+
+If the path list contains a path that is not in this Aal2PathDistributionUnit, the exception NotInGroup is raised.
+
+Note! Removing one or more Aal2PathVccTps using this action updates the attribute 'Aal2PathVccTpList'.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="aal2PathList">
+ <in/>
+ <dataType>
+ <sequence>
+ <moRef name="Aal2PathVccTp"/>
+ </sequence>
+ </dataType>
+ </parameter>
+ <raisesException name="NotInGroupException"/>
+ </action>
+ </class>
+
+ <class name="Fan">
+ <description>The Fan is used for cooling the Cello-subrack and is connected to one or two
+SCU (switch core board). This MO is used for controlling and sending alarm from
+the Fan.
+
+Note, either the fan can be supplied by Cello and Fan MO is used, or alternatively the fan can supplied by a source external to Cello and therefore a ManagedObject MO is used to represent the fan.
+
+</description>
+ <attribute name="FanId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>user label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrativeState of Fan MO.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="connectedToScu">
+ <description>A Fan must always be connected to a Switch Core unit that mediates the communication with a main processor.
+
+In this attribute it is possible to see which SwichCoreUnit that the fan is connected to.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="SwitchCoreUnit"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state is set to 'enabled' when the Fan has loaded and started its load module.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="piuType">
+ <description>A reference to an available PiuType at create of a Fan.
+</description>
+ <mandatory/>
+ <dataType>
+ <moRef name="PiuType"/>
+ </dataType>
+ </attribute>
+ <attribute name="controllingState">
+ <description>The application that controls the Fan has three main states:
+- standalone: running on itself, not manageable
+- autonomous: manageable state
+- noiseReduced: temporary state with reduced cooling
+
+NOTE: This attribute is not supported in CPP 4.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="FanState">
+ <defaultValue>standalone</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="hdlcAddress">
+ <description>The physical address of the RS-485 communication link.
+Incorrect setting of the address can cause collision with other connected auxiliary units or lost connection. The default value should be suitable for most configurations.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>255</max>
+ </range>
+ <defaultValue>7</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO. </description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <action name="restartFan">
+ <description>A restart will cause the Fan to be initiated, re-booted and all load modules to be reloaded from persistent memory. This is also known as a forced reload.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="restartCause">
+ <in/>
+ <dataType>
+ <enumRef name="RestartCause">
+ </enumRef>
+ </dataType>
+ </parameter>
+ <raisesException name="EquipException"/>
+ <raisesException name="ValueOutOfRangeException"/>
+ </action>
+ </class>
+
+ <class name="Mtp2TpItu">
+ <description>This MO represents a MTP2 Termination Point for the ITU standard, as defined in Recommendation Q.703 07/96.
+
+The performance monitoring counters found in Mtp2Itu MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is a hardware fault, aal1 server/adm restart or node restart.
+
+NOTE: This MO cannot in anyway be related (either contain or by dependence) to an MO that belongs to a standard
+which is NOT the ITU standard.
+
+NOTE: There is a restriction of a maximum of 32 Mtp2Tp's per MP.</description>
+ <attribute name="userLabel">
+ <description>Free tag for marking this managed object.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="Mtp2TpItuId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the MTP2 Signalling Terminal.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="mtp2ProfileItuId">
+ <description>Reference to a Mtp2ProfileItu MO.
+
+Note: The bitRate can not be changed.</description>
+ <mandatory/>
+ <noNotification/>
+ <dataType>
+ <moRef name="Mtp2ProfileItu"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfReTransmittedOctets">
+ <description>Number of re-transmitted octets.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfNacks">
+ <description>Number of negative acknowledgements received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuReceivedInError">
+ <description>Number of signal units received in error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfStartedRBCongestion">
+ <description>Number of started local RB congestions.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSendBufferOctets">
+ <description>Number of octets in send buffer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLocalSIBTime">
+ <description>Total time in local SIB (Sending).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmRemoteSIBTime">
+ <description>Total time in remote SIB (Receiving).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSIOSIFTransmitted">
+ <description>Number of SIO &amp; SIF octets transmitted.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The attribute is set by the list of reserving MO's.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Mtp3bSlItu"/>
+ </dataType>
+ </attribute>
+ <attribute name="ds0BundleId">
+ <description>The Ds0Bundle MO that this MO references.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Ds0Bundle"/>
+ </dataType>
+ </attribute>
+ <attribute name="plugInUnitId">
+ <description>The PlugInUnit MO that this MO references.
+It indicates on which processor the Termination Point will be.
+
+Note: The PlugInUnit must be of type GPB.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="PlugInUnit"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUTransmitted">
+ <description>Number of MSUs transmitted.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSIOSIFReceived">
+ <description>Number of SIO and SIF octets received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUReceived">
+ <description>Number of MSUs received..</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp2TpAnsi">
+ <description>This MO represents a MTP2 Termination Point for the ANSI standard , as defined in T1.111-1996.
+
+The performance monitoring counters found in Mtp2Ansi MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is a hardware fault, aal1 server/adm restart or node restart.
+
+NOTE: This MO cannot in anyway be related (either contained by or dependent on) an MO that belongs to a
+standard which is NOT the ANSI standard.
+
+NOTE: There is a restriction of a maximum of 32 Mtp2Tp's per MP.</description>
+ <attribute name="userLabel">
+ <description>Free tag for marking this managed object.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="Mtp2TpAnsiId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the MTP2 Signalling Terminal.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="mtp2ProfileAnsiId">
+ <description>Reference to a Mtp2ProfileAnsi MO.
+
+Note: The bitRate can not be changed.</description>
+ <mandatory/>
+ <noNotification/>
+ <dataType>
+ <moRef name="Mtp2ProfileAnsi"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfReTransmittedOctets">
+ <description>Number of re-transmitted octets.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfNacks">
+ <description>Number of negative acknowledgements received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuReceivedInError">
+ <description>Number of signal units received in error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfStartedRBCongestion">
+ <description>Number of started local RB congestions.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSendBufferOctets">
+ <description>Number of octets in send buffer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLocalSIBTime">
+ <description>Total time in local SIB (Sending).
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmRemoteSIBTime">
+ <description>Total time in remote SIB (Receiving).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSIOSIFTransmitted">
+ <description>Number of SIO &amp; SIF octets transmitted.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUReceived">
+ <description>Number of MSUs received..</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Mtp3bSlAnsi"/>
+ </dataType>
+ </attribute>
+ <attribute name="ds0BundleId">
+ <description>The Ds0Bundle MO that this MO references.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Ds0Bundle"/>
+ </dataType>
+ </attribute>
+ <attribute name="plugInUnitId">
+ <description>The PlugInUnit MO that this MO references.
+It indicates on which processor the Termination Point will be.
+
+Note: The PlugInUnit must be of type GPB.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="PlugInUnit"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUTransmitted">
+ <description>Number of MSUs transmitted.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSIOSIFReceived">
+ <description>Number of SIO and SIF octets received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Ds0Bundle">
+ <description>The Ds0Bundle, Digital Signalling Level 0, MO represents a number of timeslots on a physical port.
+Any of E1PhysPathTerm, J1PhysPathTerm, T1PhysPathTerm, E1Ttp or T1Ttp.
+The Ds0Bundle can be used in three different ways:
+
+- Fractional ATM
+
+Please refer to the AtmPort MO for details. Note that the TdmMode attribute
+must be disabled.
+
+-Circuit emulation
+
+Please refer to Aal1VccTp MO for details. Note that the TdmMode attribute
+must be disabled. Note that only 4 Ds0Bundle's per port can be configured
+when running circuit emulation.
+
+- TDM Switching
+
+The Ds0Bundle is reserved for switching node internal Ds0 connections. In
+this mode, the tdmMode attribute should be enabled.
+
+
+</description>
+ <attribute name="Ds0BundleId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Free tag for marking this managed object.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availabiltity status of Ds0Bundle.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of Ds0Bundle.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="listOfTimeSlots">
+ <description>The list gives the time slots (within ATM traffic fraction) that are to be allocated to the Ds0Bundle.
+
+When a Ds0Bundle is contained by a E1PhysPathTerm the slots that can be placed in this list are 1 to 31.
+When a Ds0Bundle is contained by a J1PhysPathTerm then the slots that can be placed in this list are 1 to 24.
+When a Ds0Bundle is contained by a T1PhysPathTerm then the slots that can be placed in this list are 1 to 24.
+When a Ds0Bundle is contained by a E1Ttp the slots that can be placed in this list are 1 to 31.
+
+Note: the same timeslot cannot appear more than once in the list! If a E1/J/T1PhysPathTerm contains more than
+one Ds0Bundle, then the Ds0Bundles listOfTimeSlots must be mutually exclusive (i.e. slots in one list cannot be used in another list).
+
+Note! If the Ds0Bundle is used for carrying SS7 traffic, the listOfTimeSlots can only contain 1 (one) time slot.
+In this case that is if the Ds0Bundle is reserved by an Mtp2TpAnsi, Mtp2TpItu or Mtp2TpChina.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <sequence>
+ <long>
+ <range>
+ <min>0</min> <max>31</max>
+ </range>
+ </long>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="tdmMode">
+ <description>The state of tdmMode (Time Division Multiplexing), can be disabled/enabled.
+
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Aal1TpVccTp">
+ <description>The Aal1TpVccTp MO represents the Aal1 interworking function in a circuit emulation. The object refers to a Ds0Bundle which represents one end of the circuit emulation, and a VclTp which represents the other end.
+
+Note! The performance monitoring counters in this MO is set to 0 when counterMode is set to PM_MODE_ON.
+In PM_MODE_OFF no information at all is retrived. So any value for pm-monitoring is measured from the time
+of setting counterMode to PM_MODE_ON.
+At node restart these performance monitoring counters is reset to 0.</description>
+ <attribute name="userLabel">
+ <description>Free tag for marking this managed object.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ds0BundleId">
+ <description>The Ds0Bundle MO that this MO references.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Ds0Bundle"/>
+ </dataType>
+ </attribute>
+ <attribute name="partialFill">
+ <description>Indicates how many bytes are filled in each ATM cell. The value 47 indicates that the partial filled cells is not used, i.e. all the cells are filled completely.
+
+Partial filling of cells in used in circuit emulation. It is used to reduce packetisation delay. Refer to the ATM Forum specifications for more details.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>23</min> <max>47</max>
+ </range>
+ <defaultValue>47</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="cdvt">
+ <description>Specifies the cell delay variation tolerance. Refer to ATM Forum specifications for more details.
+
+Unit is micro seconds.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>100</min> <max>4000</max>
+ </range>
+ <defaultValue>1000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of Aal1TpVccTp.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="continuityCheck">
+ <description>Continuitiy checking means that a cell is sent downstream when no user cell has been sent for a period of nominally 1 second.
+
+Activates VC end to end continuityCheck according to ITU.T rec I.610.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="counterMode">
+ <description>Controls the activation of PM counters and F5 PM flow on the VC connection.</description>
+ <dataType>
+ <enumRef name="AtmCounterMode">
+ <defaultValue>PM_MODE_OFF</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="nomPmBlockSize">
+ <description>Nominal performance monitoring (PM) blocksize. The minimum number of ATM cells to send before sending a Forward Performance Monitoring, FPM, cell.</description>
+ <dataType>
+ <enumRef name="AtmNomPmBlkSize">
+ <defaultValue>NOM_PM_BLKSIZE_2_10</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwLostCells">
+ <description>Performance monitoring counter for forwarded lost cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwMissinsCells">
+ <description>Performance monitoring counter for number of forwarded missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmFwErrBlocks">
+ <description>Performance monitoring counter for number of forwarded errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostFpmCells">
+ <description>Performance monitoring counter for number of lost Forward Performance Monitoring, FPM cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwLostCells">
+ <description>Performance monitoring counter for number of lost backward cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwMissinsCells">
+ <description>Performance monitoring counter for number of backward missinserted cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmBwErrBlocks">
+ <description>Performance monitoring counter for number of backward errored blocks.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmLostBrCells">
+ <description>Performance monitoring counter for number of lost Backward Reporting, BR, cells.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="Aal1TpVccTpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="vclTpId">
+ <description>The VclTp MO that this MO references.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="VclTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="alarmReport">
+ <description>Attribute to decide what type of alarms to be reported.</description>
+ <dataType>
+ <enumRef name="AlarmReport">
+ <defaultValue>ALARM_LOC</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp3bSpAnsi">
+ <description>Mtp3b Signalling Point for the ANSI standard.
+
+This MO represents/models the MTP3b Signaling Point characteristics/functions according to the Ansi standard.
+A signaling point is a logical node in the signaling network. The combination of signaling points and their interconnecting
+signaling links form the SS No. 7 signaling network. The signaling point represented by this object is a Local Signaling Point.
+
+The performance monitoring counters found in Mtp3SpAnsi MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).
+
+NOTE: IT IS NOT POSSIBLE TO CREATE SIGNALLING POINTS OF DIFFERENT STANDARDS!
+
+NOTE: This MO cannot in anyway be related (either contain or by dependence) to an MO that belongs to a standard which is NOT the ANSI standard.
+
+NOTE: The combination of network indicator (networkInd) and Signalling Point Code (signallingPointCode) has to be unique for each Signalling Point.
+
+NOTE: A maximum of 15 instances of this MO can be created on (referencing) the same PlugInUnit.
+
+NOTE: The maximum number of Signalling Points that can be created in a CPP based node is 24.
+
+NOTE: Deleting a singel L3 Signal Point is not possible, if it necessary to delete a Signal Point then all Signal Points has to be deleted. This also has to be done whitin the same transaction.
+
+NOTE: Any object created under a certain SP (Signaling Point) cannot refer to an object created under another SP. Nor can it refer to an object created under another SP.</description>
+ <attribute name="Mtp3bSpAnsiId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="rpuId">
+ <description>Holds a reference to the Reliable Program Uniter.
+The RPU is at the server.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ReliableProgramUniter"/>
+ </dataType>
+ </attribute>
+ <attribute name="networkInd">
+ <description>The network indicator, NI, is used for discrimination of messages between functionally different networks.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="Mtp3bNetworkInd">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="signallingPointCode">
+ <description>The signallingPointCode (Local Point Code) attribute (SPC) is used together with the network indicator (NI, networkInd attribute) to uniquely identify the MTP Signalling Point, SP.
+SP = NI-SPC.
+Size (2 exp 24)-1 (16777215).
+The SignallingPointCode (SPC) is normally grouped together as three numbers wich correspond to network identifier, network cluster, network cluster member. The three numbers are coded as 8-8-8 bits in the total SPC. To enter the SPC-value, you have to convert the 3 numbers to their binary code and then convert the whole 24-bit patterna as an integer. Sometimes the SPC is used as a whole uniqe number (no internal structure).
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16777215</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="testPatternSltm">
+ <description>The testPatternSltm attribute represents a string testpattern in the Signalling Link Test Message.
+
+Minimum string length 2 characters, maximum 30 characters. Allowed characters are 0-9, A-F.
+Only even number of characters is allowed.</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>2</min> <max>30</max>
+ </lengthRange>
+ <defaultValue>"A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="nodeBehaviour">
+ <description>The nodeBehaviour attribute represents the MTP3b node type.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="NodeBehaviourType">
+ <defaultValue>SEP</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="maxSizeReroutBuf">
+ <description>The maxSizeReroutBuf attribute represents the maximum size (in kB) of the rerouting buffer.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>5000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxSizeChangeBuf">
+ <description>The maxSizeChangeBuf attribute represents the maximum size (in kB) of the changeover buffer.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>5000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="transFrHandler">
+ <description>Determines how a TransFer Restricted signal (TFR) should be treated.
+</description>
+ <dataType>
+ <enumRef name="Mtp3bTfrHandling">
+ <defaultValue>IGNORED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="sioSpare">
+ <description>The sioSpare2 attribute determines if the two spare bits in the SIO (Service Information Octet) should be treated as spare.</description>
+ <dataType>
+ <enumRef name="Mtp3bSioSpareBitsUse">
+ <defaultValue>PRIO</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="m3uaNoOfAttempsOfDauds">
+ <description>For M3UA, number of attempts to send the DAUD message.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="noOfAttempsOfAssociationEstablishment">
+ <description>Number of attempts to send the SCTP_ASSOCIATE_REQ message.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>65535</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="statusIndInterval">
+ <description>The statusIndInterval attribute sets the interval for sending MTP-STATUS indication, i.e. send indication every Nth message .</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="resendTfcInterval">
+ <description>Send TFC back to originating signalling point code for every n:th message when
+the destination is congested. Set to 0 will suppress sending of TFC.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="sendSltmBefLink">
+ <description>The sendSltmBefLink attribute determines if the SLTM (Signalling Link Test Message) should be sent and a SLTA received before the link is considered to be in service.
+
+Note! It is not recommended nor is it in accordance with standard to set the value of this attribute to 'false' </description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="spPriority">
+ <description>Struct containing the ANSI priority attributes.
+</description>
+ <dataType>
+ <structRef name="Mtp3bSpAnsiPriorityData"/>
+ </dataType>
+ </attribute>
+ <attribute name="noOfCongestLevelForNI">
+ <description>Defines the number of congestion levels for NI.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>3</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="routeSetCongestTestFlag">
+ <description>Selection of which procedure to use during congestion handling if the national option with priorities is used.
+
+0, use TcTimer as described by the TTC standard.
+1, use Route Set Congestion Test as described by the ANSI, ITU and China Standard.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operationalState attribute reflects the operational status of the MTP3b SP.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="spTimer">
+ <description>Struct containing ANSI specific timer data.</description>
+ <dataType>
+ <structRef name="Mtp3bSpAnsiTimerData"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds a list of the reserving MO's. Can be of type SccpSp.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfForcedRerouteSuccessPerf">
+ <description>Performance monitoring counter for number of successfully performed forced rerouting.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfControlledRerouteSuccessPerf">
+ <description>Performance monitoring counter for number of successfully performed controlled rerouting.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfEmergencyChangeOverRec">
+ <description>Performance management counter for number of received emergency changeOver orders (ECO) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfChangeOverRec">
+ <description>Performance counter for number of changeOver order messages (COO/XCO) received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfChangeBackDeclRec">
+ <description>Performance management counter for number of received change Back Declarations (CBD) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSLTAFirstTimeOutRec">
+ <description>Performance management counter for number of SLTA first time out received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSLTASecondTimeOutRec">
+ <description>Performance management counter for number of SLTA second time out received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUPMsgDiscardedDueToRoutingErr">
+ <description>Performance monitoring counter for number of UP (user part) messages (MTP_TRANSFER_req) discarded due to routing error.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOAXCASent">
+ <description>Performance management counter for number of sent COA/XCA messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECOSent">
+ <description>Performance management counter for number of sent ECO messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECASent">
+ <description>Performance management counter for number of sent ECA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOAXCARec">
+ <description>Performance management counter for number of received COA/XCA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBARec">
+ <description>Performance management counter for number of received CBA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECARec">
+ <description>Performance management counter for number of received ECA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTRARec">
+ <description>Performance management counter for number of received TRA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTRASent">
+ <description>Performance management counter for number of sent TRA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTimerT21WasStarted">
+ <description>Performance monitoring counter for number of times the timer T21 was started (i.e. how many times the remote inhibit test message has been sent).
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBASent">
+ <description>Performance management counter for number of sent CBA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessForcedRerouting">
+ <description>Performance monitoring counter for number of unsuccessfully performed forced reroutings.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessControlledRerouting">
+ <description>Performance monitoring counter for number of unsuccessfully performed controlled reroutings.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocEstablish">
+ <description>Performance management counter for number of successful association establishment.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocEstablish">
+ <description>Performance management counter for number of unsuccessful association establishment.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpCommunicationErr">
+ <description>Performance management counter for number of SCTP communication error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpSendFailure">
+ <description>Performance management counter for number of SCTP send failure.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpBufOverflow">
+ <description>Performance management counter for number of SCTP stop sending data.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpResumeSending">
+ <description>Performance management counter for number of SCTP resume sending data.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpNetworkStatusChange">
+ <description>Performance management counter for number of SCTP network status change.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpAssociationRestart">
+ <description>Performance management counter for number of SCTP association restart.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocAbort">
+ <description>The number of successful abortions of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocShutDown">
+ <description>The number of succesful shutdowns of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocAbort">
+ <description>The number of unsuccessful abortions of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocShutDown">
+ <description>The number of unsuccesful shutdowns of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIncomingAssocEstabRequestInStateDownWhenStateEstabIsBlocked">
+ <description>The number of incoming request for association establishment when state on the association is 'DOWN' and establishment of associations is blocked. </description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMaxTrialsForAssocEstabReached">
+ <description>The number of times that the max limit for trying to establish an association has been reached.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMaxTrialsForAssocActivReached">
+ <description>The number of times that the max limit for trying to activate an association has been reached.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLowerPrioMsgDiscarded">
+ <description>The number of messages with low priority that has been discarded.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp3bSpItu">
+ <description>Mtp3b Signalling Point for the ITU standard.
+
+This MO represents/models the MTP3b Signaling Point characteristics/functions according to the ITU standard.
+A signaling point is a logical node in the signaling network. The combination of signaling points and their interconnecting
+signaling links form the SS No. 7 signaling network. The signaling point represented by this object is a Local Signaling Point.
+
+The performance monitoring counters found in Mtp3SpItu MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).
+
+NOTE: IT IS NOT POSSIBLE TO CREATE SIGNALLING POINTS OF DIFFERENT STANDARDS!
+
+NOTE: This MO cannot in anyway be related (either contain or by dependence) to an MO that belongs to a standard which is NOT the ITU standard.
+
+NOTE: The combination of network indicator (networkInd) and Signalling Point Code (signallingPointCode) has to be unique for each Signalling Point.
+
+NOTE: A maximum of 15 instances of this MO can be created on (referencing) the same PlugInUnit.
+
+NOTE: The maximum number of Signalling Points that can be created in a CPP based node is 24.
+
+NOTE: Deleting a singel L3 Signal Point is not possible, if it necessary to delete a Signal Point then all Signal Points has to be deleted. This also has to be done whitin the same transaction.
+
+NOTE: Any object created under a certain SP (Signaling Point) cannot refer to an object created under another SP. Nor can it refer to an object created under another SP.
+
+NOTE: The value of the attribute 'version' is valid for all SPs (Mtp3bSpItu MOs) and the value of the last created or changed SP will be used for all SPs.</description>
+ <attribute name="Mtp3bSpItuId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="networkInd">
+ <description>The networkInd attribute (NI) is used by signalling message handling functions in MTP3b
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="Mtp3bNetworkInd">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="signallingPointCode">
+ <description>The signallingPointCode (Local Point Code) attribute (SPC) is used together with the network indicator (NI, networkInd attribute) to uniquely identify the MTP Signalling Point, SP.
+SP = NI-SPC.
+Size (2 exp 14)-1 (16383).
+The SignallingPointCode (SPC) is normally used as a whole unique number (no internal structure). But sometimes the SPC is grouped together as three numbers which corresponds to zone, area/network, signalling point. If this is the case the three numbers are coded as 3-8-3 bits in the total SPC. To enter the SPC-value then you have to convert the three numbers to their binary code and then convert the whole 14-bit pattern as an integer.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16383</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="version">
+ <description>This attribute shows what MTP3b ITU standard the system follows. With ITU, it is possible using this attribute to set which of the ITU standard versions that shall be followed.
+
+Note! Setting of another value than 'ITU_T_07_96' at create will have no effect. The Signaling Point will always be created with the value 'ITU_T_07_96'.
+
+Note! It is not possible to hav signaling points with different versions in the node so setting of this attribute will effect all signaling points. The value for the last created or changed signaling point will be used for all signaling points.</description>
+ <dataType>
+ <enumRef name="Mtp3bItuVersion">
+ <defaultValue>ITU_T_07_96</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="nodeBehaviour">
+ <description>The nodeBehaviour attribute represents the MTP3b node type.
+
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="NodeBehaviourType">
+ <defaultValue>SEP</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="noOfCongestLevelForNI">
+ <description>Defines the number of congestion levels for NI.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>3</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="routeSetCongestTestFlag">
+ <description>Selection of which procedure to use during congestion handling if the national option with priorities is used.
+
+0, use TcTimer as described by the TTC standard.
+1, use Route Set Congestion Test as described by the ANSI, ITU and China Standard.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="resendTfcInterval">
+ <description>Send TFC back to originating signalling point code for every n:th message when
+the destination is congested. Set to 0 will suppress sending of TFC.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxSizeReroutBuf">
+ <description>The maxSizeReroutBuf attribute represents the maximum size (in kB) of the rerouting buffer.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>5000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxSizeChangeBuf">
+ <description>The maxSizeChangeBuf attribute represents the maximum size (in kB) of the changeover buffer.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>5000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="transFrHandler">
+ <description>Determines if a TransFer Restricted signal (TFR) should be treated as a TFA (TransFer Allowed signal) or be ignored.
+</description>
+ <dataType>
+ <enumRef name="Mtp3bTfrHandling">
+ <defaultValue>IGNORED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="sioSpare">
+ <description>The sioSpare2 attribute determines if the two spare bits in the SIO (Service Information Octet) should be treated as spare.</description>
+ <dataType>
+ <enumRef name="Mtp3bSioSpareBitsUse">
+ <defaultValue>PRIO</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="statusIndInterval">
+ <description>The statusIndInterval attribute sets the interval for sending MTP-STATUS indication, i.e. send indication every Nth message .</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="sendSltmBefLink">
+ <description>The sendSltmBefLink attribute determines if the SLTM (Signalling Link Test Message) should be sent and a SLTA received before the link is considered to be in service.
+
+Note! It is not recommended nor is it in accordance with standard to set the value of this attribute to 'false' </description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="testPatternSltm">
+ <description>The testPatternSltm attribute represents a string testpattern in the Signalling Link Test Message.
+
+Minimum string length 2 characters, maximum 30 characters. Allowed characters are 0-9, A-F.
+Only even number of characters is allowed.
+
+</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>2</min> <max>30</max>
+ </lengthRange>
+ <defaultValue>"A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="spPriority">
+ <description>Struct containing the priority attributes.
+</description>
+ <dataType>
+ <structRef name="Mtp3bSpItuPriorityData"/>
+ </dataType>
+ </attribute>
+ <attribute name="spTimer">
+ <description>Struct containing ITU specific timer attributes</description>
+ <dataType>
+ <structRef name="Mtp3bSpItuTimerData"/>
+ </dataType>
+ </attribute>
+ <attribute name="rpuId">
+ <description>Holds a reference to the Reliable Program Uniter.
+The RPU is at the server.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ReliableProgramUniter"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operationalState attribute reflects the operational status of the MTP3b SP.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="m3uaNoOfAttempsOfDauds">
+ <description>For M3UA, number of attempts to send the DAUD message.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="noOfAttempsOfAssociationEstablishment">
+ <description>Number of attempts to send the SCTP_ASSOCIATE_REQ message.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>65535</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds a list of the reserving MO's. Can be of type SccpSp.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfForcedRerouteSuccessPerf">
+ <description>Performance monitoring counter for number of successfully performed forced rerouting.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfControlledRerouteSuccessPerf">
+ <description>Performance monitoring counter for number of successfully performed controlled rerouting.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfEmergencyChangeOverRec">
+ <description>Performance management counter for number of received emergency changeOver orders (ECO) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfChangeOverRec">
+ <description>Performance counter for number of changeOver order messages (COO/XCO) received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfChangeBackDeclRec">
+ <description>Performance management counter for number of received change Back Declarations (CBD) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSLTAFirstTimeOutRec">
+ <description>Performance management counter for number of SLTA first time out received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSLTASecondTimeOutRec">
+ <description>Performance management counter for number of SLTA second time out received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUPMsgDiscardedDueToRoutingErr">
+ <description>Performance monitoring counter for number of UP (user part) messages (MTP_TRANSFER_req) discarded due to routing error.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOAXCASent">
+ <description>Performance management counter for number of sent COA/XCA messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECOSent">
+ <description>Performance management counter for number of sent ECO messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECASent">
+ <description>Performance management counter for number of sent ECA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOAXCARec">
+ <description>Performance management counter for number of received COA/XCA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBARec">
+ <description>Performance management counter for number of received CBA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECARec">
+ <description>Performance management counter for number of received ECA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTRARec">
+ <description>Performance management counter for number of received TRA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTRASent">
+ <description>Performance management counter for number of sent TRA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTimerT21WasStarted">
+ <description>Performance monitoring counter for number of times the timer T21 was started (i.e. adjacent SP restarted).
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBASent">
+ <description>Performance management counter for number of sent CBA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessForcedRerouting">
+ <description>Performance monitoring counter for number of unsuccessfully performed forced reroutings.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessControlledRerouting">
+ <description>Performance monitoring counter for number of unsuccessfully performed controlled reroutings.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocEstablish">
+ <description>Performance management counter for number of successful association establishment.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocEstablish">
+ <description>Performance management counter for number of unsuccessful association establishment.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpCommunicationErr">
+ <description>Performance management counter for number of SCTP communication error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpSendFailure">
+ <description>Performance management counter for number of SCTP send failure.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpBufOverflow">
+ <description>Performance management counter for number of SCTP stop sending data.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpResumeSending">
+ <description>Performance management counter for number of SCTP resume sending data.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpNetworkStatusChange">
+ <description>Performance management counter for number of SCTP network status change.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpAssociationRestart">
+ <description>Performance management counter for number of SCTP association restart.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocAbort">
+ <description>The number of successful abortions of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocShutDown">
+ <description>The number of succesful shutdowns of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocAbort">
+ <description>The number of unsuccessful abortions of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocShutDown">
+ <description>The number of unsuccesful shutdowns of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIncomingAssocEstabRequestInStateDownWhenStateEstabIsBlocked">
+ <description>The number of incoming request for association establishment when state on the association is 'DOWN' and establishment of associations is blocked. </description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMaxTrialsForAssocEstabReached">
+ <description>The number of times that the max limit for trying to establish an association has been reached.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMaxTrialsForAssocActivReached">
+ <description>The number of times that the max limit for trying to activate an association has been reached.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLowerPrioMsgDiscarded">
+ <description>The number of messages with low priority that has been discarded.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp3bSpTtc">
+ <description>Mtp3b Signalling Point for the TTC standard.
+
+This MO represents/models the MTP3b Signaling Point characteristics/functions according to the TTC standard.
+A signaling point is a logical node in the signaling network. The combination of signaling points and their interconnecting
+signaling links form the SS No. 7 signaling network. The signaling point represented by this object is a Local Signaling Point.
+
+The performance monitoring counters found in Mtp3SpTtc MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).
+
+NOTE: This MO cannot in anyway be related (either contain or by dependence) to an MO that belongs to a
+standard which is NOT the TTC standard.
+
+NOTE: IT IS NOT POSSIBLE TO CREATE SIGNALLING POINTS OF DIFFERENT STANDARDS!
+
+NOTE: The combination of network indicator (networkInd) and Signalling Point Code (signallingPointCode) has to be unique for each Signalling Point.
+
+NOTE: A maximum of 15 instances of this MO can be created on (referencing) the same PlugInUnit.
+
+NOTE: The maximum number of Signalling Points that can be created in a CPP based node is 24.
+
+NOTE: Deleting a singel L3 Signal Point is not possible, if it necessary to delete a Signal Point then all Signal Points has to be deleted. This also has to be done whitin the same transaction.
+
+NOTE: Any object created under a certain SP (Signaling Point) cannot refer to an object created under another SP. Nor can it refer to an object created under another SP.</description>
+ <attribute name="Mtp3bSpTtcId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="networkInd">
+ <description>The networkInd attribute (NI) is used by signalling message handling functions in MTP3b.
+
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="Mtp3bNetworkIndTtc">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="signallingPointCode">
+ <description>The signallingPointCode (Local Point Code) attribute (SPC) is used together with the network indicator (NI, networkInd attribute) to uniquely identify the MTP Signalling Point, SP.
+SP = NI-SPC.
+Size (2 exp 16)-1 (65535).
+The SignallingPointCode (SPC) is always used as a whole unique number (no internal structure).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="nodeBehaviour">
+ <description>The nodeBehaviour attribute represents the MTP3b node type.
+
+Note! Only SEP and STP is supported for the Ttc standard.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="NodeBehaviourType">
+ <defaultValue>SEP</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="routeSetCongestTestFlag">
+ <description>Selection of which procedure to use during congestion handling if the national option with priorities is used.
+
+0, use TcTimer as described by the TTC standard.
+1, use Route Set Congestion Test as described by the ANSI, ITU and China Standard.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="resendTfcInterval">
+ <description>Send TFC back to originating signalling point code for every n:th message when
+the destination is congested. Set to 0 will suppress sending of TFC.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxSizeReroutBuf">
+ <description>The maxSizeReroutBuf attribute represents the maximum size (in kB) of the rerouting buffer.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>5000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxSizeChangeBuf">
+ <description>The maxSizeChangeBuf attribute represents the maximum size (in kB) of the changeover buffer.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>5000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="statusIndInterval">
+ <description>The statusIndInterval attribute sets the interval for sending MTP-STATUS indication, i.e. send indication every Nth message .</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="testPatternSltm">
+ <description>The testPatternSltm attribute represents a string testpattern in the Signalling Link Test Message.
+
+String length 4 characters. Allowed characters are 0-9, A-F.
+
+</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>4</min> <max>4</max>
+ </lengthRange>
+ <defaultValue>"7711"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="spPriority">
+ <description>Struct containing the TTC priority attributes.
+</description>
+ <dataType>
+ <structRef name="Mtp3bSpTtcPriorityData"/>
+ </dataType>
+ </attribute>
+ <attribute name="rpuId">
+ <description>Holds a reference to the Reliable Program Uniter.
+The RPU is at the server.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ReliableProgramUniter"/>
+ </dataType>
+ </attribute>
+ <attribute name="spTimer">
+ <description>Struct containing TTC timer attributes.</description>
+ <noNotification/>
+ <dataType>
+ <structRef name="Mtp3bSpTtcTimerData"/>
+ </dataType>
+ </attribute>
+ <attribute name="noOfCongestLevelForNI">
+ <description>Defines the number of congestion levels for NI.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>3</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operationalState attribute reflects the operational status of the MTP3b SP.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds a list of the reserving MO's. Can be of type SccpSp.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfForcedRerouteSuccessPerf">
+ <description>Performance monitoring counter for number of successfully performed forced rerouting.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfControlledRerouteSuccessPerf">
+ <description>Performance monitoring counter for number of successfully performed controlled rerouting.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfEmergencyChangeOverRec">
+ <description>Performance management counter for number of received emergency changeOver orders (ECO) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfChangeOverRec">
+ <description>Performance counter for number of changeOver order messages (COO/XCO) received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfChangeBackDeclRec">
+ <description>Performance management counter for number of received change Back Declarations (CBD) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSLTAFirstTimeOutRec">
+ <description>Performance management counter for number of SLTA first time out received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSLTASecondTimeOutRec">
+ <description>Performance management counter for number of SLTA second time out received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUPMsgDiscardedDueToRoutingErr">
+ <description>Performance monitoring counter for number of UP (user part) messages (MTP_TRANSFER_req) discarded due to routing error.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOAXCASent">
+ <description>Performance management counter for number of sent COA/XCA messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECOSent">
+ <description>Performance management counter for number of sent ECO messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECASent">
+ <description>Performance management counter for number of sent ECA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOAXCARec">
+ <description>Performance management counter for number of received COA/XCA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBARec">
+ <description>Performance management counter for number of received CBA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECARec">
+ <description>Performance management counter for number of received ECA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTRARec">
+ <description>Performance management counter for number of received TRA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTRASent">
+ <description>Performance management counter for number of sent TRA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBASent">
+ <description>Performance management counter for number of sent CBA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessForcedRerouting">
+ <description>Performance monitoring counter for number of unsuccessfully performed forced reroutings.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessControlledRerouting">
+ <description>Performance monitoring counter for number of unsuccessfully performed controlled reroutings.
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocEstablish">
+ <description>Performance management counter for number of successful association establishment.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocEstablish">
+ <description>Performance management counter for number of unsuccessful association establishment.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpCommunicationErr">
+ <description>Performance management counter for number of SCTP communication error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpSendFailure">
+ <description>Performance management counter for number of SCTP send failure.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpBufOverflow">
+ <description>Performance management counter for number of SCTP stop sending data.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpResumeSending">
+ <description>Performance management counter for number of SCTP resume sending data.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpNetworkStatusChange">
+ <description>Performance management counter for number of SCTP network status change.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpAssociationRestart">
+ <description>Performance management counter for number of SCTP association restart.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp3bSlAnsi">
+ <description>This MO represents an MTP3b Signalling Link for the ANSI standard. It represents the termination of the signalling link within the signalling point as defined in T1.111-1996.
+
+The total amount of links between any two specific nodes in the network shall not be more than 80 independent on how many linksets that are defined between the two nodes. The signalLinkCode for a link must be unique between the nodes, independent on which linkSet the link belongs to. A maximum of five linksets with a maximum of 16 links in each linkset can be configured. A maximum of 16 links between two adjacent nodes can be configured.
+
+NOTE: This MO cannot in anyway be related (either contain or by dependence) to an MO that belongs to a standard which is NOT the ANSI standard.
+
+The performance monitoring counters found in Mtp3SlAnsi MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).</description>
+ <attribute name="Mtp3bSlAnsiId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>This attribute reflects the operational status of the Mtp3bSlAnsi.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="tpId">
+ <description>The tpId attribute points out the termination point of the lower layer protocol.
+
+For narrowband this signalling link will be connected to an MTP L2 termination point (Mtp2Tp MO). And for broadband it will be connected to a NNI SAAL termination point (NniSaalTp Mo).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="linkState">
+ <description>The link state of the Mtp3bSlAnsi.
+
+The link state is a bit map which contains a combination of the following values: (in hexadecimal format)
+
+0x00 Available
+0x01 Failed
+0x02 Remotely blocked
+0x04 Locally blocked
+0x08 Remotely inhibited
+0x10 Locally inhibited
+0x20 Deactivated</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="usageState">
+ <description>There are three possible states for the usageState attribute:
+
+- idle, the Mtp3bSl carries no traffic.
+- active, the Mtp3bSl is working normally, and there is traffic, and it is not congested.
+- busy, the Mtp3bSl is working but is congested (traffic is routed on other links).
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bUsageState">
+ <defaultValue>IDLE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="signLinkCode">
+ <description>The signalling link code, SLC, used for this link.
+The signLinkCode for a link must be unique between the nodes,
+independent on in which linkSet the link belongs.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>15</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="proceduralState">
+ <description>The procedural state of the link.
+
+0 - not initialized
+1 - initialized
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bProceduralState">
+ <defaultValue>NOT_INITIALIZED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="linkCongestLevel">
+ <description>The congestion level of the link.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="CongestLevel">
+ <defaultValue>level_0</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="autoStartLink">
+ <description>Controls if the Mtp3bSL should be activated at create.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAALINServiceInd">
+ <description>Performance management counter for number of received link-in-service indications.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAALOUTInd">
+ <description>Performance management counter for number of received link-out-of-service indications.
+
+Note! This counter is incremented every time a link out of service indication is received for the link.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOOXCOSent">
+ <description>Performance management counter for number of sent change over order (COO/XCO) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBDSent">
+ <description>Performance management counter for number of sent CBD messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalLinkCongestRec">
+ <description>Performance monitoring counter for number of local link congestion primitives received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalLinkCongestCeaseRec">
+ <description>Performance monitoring counter for number of local link congestion ceased primitives received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSURec">
+ <description>Performance monitoring counter for number of received MSU's on this signalling link.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUSent">
+ <description>Performance monitoring counter for number of sent MSU's on this signalling link.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <action name="deactivate">
+ <description>This action deactivates the signalling link.
+ It will also set autoStartLink = false.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="activate">
+ <description>This action activates the signalling link with normal alignment. It will also set autoStartLink = true.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="emergencyActivate">
+ <description>This action activates the signalling link with emergency alignment.
+ It will also set autoStartLink = true
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="localInhibit">
+ <description>This action inhibits the Mtp3bSlAnsi. Signalling link management inhibiting is requested by management when it becomes necessary, e.g for maintenance or testing purposes to make or keep a signalling link unavailable to User Part-generated signalling traffic.
+Inhibiting of a signalling link may be requested by management function at either end of the link. The request is granted, provided that the inhibiting action does not cause any previously accessible destinations to become inaccessible at either end of the signalling link. The request may also be refused under certain circumstances such as congestion.
+Exception FroRequestFailed if it was not possible to inhibit.
+
+Note! This action requires a transaction.
+</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="localUninhibit">
+ <description>This action uninhibits the Mtp3bSlAnsi.
+
+Exception FrorequestFailed if it was not possible to uninhibit.
+
+Note! This action requires a transaction.
+</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ </class>
+
+ <class name="Mtp3bSlItu">
+ <description>This MO represents an MTP3b Signalling Link for the ITU standard. It represents the termination of the signalling link within the signalling point as defined in Q.704 and Q.2210 (07/96).
+
+The total amount of links between any two specific nodes in the network shall not be more than 16, independent on how many linksets that are defined between the two nodes. The signalLinkCode for a link must be unique between the nodes, independent on which linkSet the link belongs to.
+
+The performance monitoring counters found in Mtp3SlItu MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).
+
+NOTE: This MO cannot in anyway be related (either contain or by dependence) to an MO that belongs to a standard which is NOT the ITU standard.</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="tpId">
+ <description>The tpId attribute points out the termination point of the lower layer protocol.
+
+For narrowband this signalling link will be connected to an MTP L2 termination point (Mtp2Tp MO). And for broadband it will be connected to a NNI SAAL termination point (NniSaalTp Mo).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>This attribute reflects the operational status of the Mtp3bSl.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="linkState">
+ <description>The link state of the Mtp3bSl.
+
+The link state is a bit map which contains a combination of the following values: (in hexadecimal format)
+
+0x00 Available
+0x01 Failed
+0x02 Remotely blocked
+0x04 Locally blocked
+0x08 Remotely inhibited
+0x10 Locally inhibited
+0x20 Deactivated</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="usageState">
+ <description>There are three possible states for the usageState attribute:
+
+- idle, the Mtp3bSl carries no traffic.
+- active, the Mtp3bSl is working normally, and there is traffic, and it is not congested.
+- busy, the Mtp3bSl is working but is congested (traffic is routed on other links).
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bUsageState">
+ <defaultValue>IDLE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="signLinkCode">
+ <description>The signalling link code, SLC, used for this link.
+The signLinkCode for a link must be unique between the nodes,
+independent on in which linkSet the link belongs.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>15</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="proceduralState">
+ <description>The procedural state of the link.
+
+0 - not initialized
+1 - initialized
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bProceduralState">
+ <defaultValue>NOT_INITIALIZED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="linkCongestLevel">
+ <description>The congestion level of the link.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="CongestLevel">
+ <defaultValue>level_0</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="autoStartLink">
+ <description>Controls if the Mtp3b Signalling Link should be activated at create.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="prioBeforeSio">
+ <description>This Boolean tells if the message priority shall be inserted in an octet before the Service Indicator Octet (SIO).
+
+ITU default is false.
+</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAALINServiceInd">
+ <description>Performance management counter for number of received link-in-service indications.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAALOUTInd">
+ <description>Performance management counter for number of received link-out-of-service indications.
+
+Note! This counter is incremented every time a link out of service indication is received for the link.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOOXCOSent">
+ <description>Performance management counter for number of sent change over order (COO/XCO) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBDSent">
+ <description>Performance management counter for number of sent CBD messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalLinkCongestRec">
+ <description>Performance monitoring counter for number of local link congestion primitives received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalLinkCongestCeaseRec">
+ <description>Performance monitoring counter for number of local link congestion ceased primitives received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSURec">
+ <description>Performance monitoring counter for number of received MSU's on this signalling link.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUSent">
+ <description>Performance monitoring counter for number of sent MSU's on this signalling link.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="Mtp3bSlItuId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="localInhibit">
+ <description>This action inhibits the Mtp3bSlItu. Signalling link management inhibiting is requested by management when it becomes necessary, e.g for maintenance or testing purposes to make or keep a signalling link unavailable to User Part-generated signalling traffic.
+Inhibiting of a signalling link may be requested by management function at either end of the link. The request is granted, provided that the inhibiting action does not cause any previously accessible destinations to become inaccessible at either end of the signalling link. The request may also be refused under certain circumstances such as congestion.
+Exception FroRequestFailed if it was not possible to inhibit.
+
+Note! This action requires a transaction.
+</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="localUninhibit">
+ <description>This action uninhibits the Mtp3bSlItu.
+
+Exception FrorequestFailed if it was not possible to uninhibit.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="deactivate">
+ <description>This action deactivates the Mtp3bSl.
+It will also set autoStartLink = false.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="activate">
+ <description>This action activates the Mtp3bSl with normal alignment. It will also set autoStartLink = true.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="emergencyActivate">
+ <description>This action activates the Mtp3bSl with emergency alignment.
+It will also set autoStartLink = true
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="Mtp3bSlTtc">
+ <description>This MO represents an MTP3b Signalling Link for the TTC standard. It represents the termination of the signalling link within the signalling point as defined in JT-Q.704 Ver. 3, April 28 1992 and JT-Q.2210 Ver.1 April 24 1996.
+
+The total amount of links between any two specific nodes in the network shall not be more than 16, independent on how many linksets that are defined between the two nodes. The signalLinkCode for a link must be unique between the nodes, independent on which linkSet the link belongs to.
+
+The performance monitoring counters found in Mtp3SlTtc MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).
+
+NOTE: This MO cannot in anyway be related (either contain or by dependence) to an MO that belongs to a standard which is NOT the TTC standard.</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="tpId">
+ <description>The tpId attribute points out the termination point of the lower layer protocol. Only BroadBand is supported for TTC. The MO will be connected to a NNI SAAL termination point (NniSaalTp Mo).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>This attribute reflects the operational status of the Mtp3bSl.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="linkState">
+ <description>The link state of the Mtp3bSl.
+
+The link state is a bit map which contains a combination of the following values: (in hexadecimal format)
+
+0x00 Available
+0x01 Failed
+0x02 Remotely blocked
+0x04 Locally blocked
+0x08 Remotely inhibited
+0x10 Locally inhibited
+0x20 Deactivated</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="usageState">
+ <description>There are three possible states for the usageState attribute:
+
+- idle, the Mtp3bSl carries no traffic.
+- active, the Mtp3bSl is working normally, and there is traffic, and it is not congested.
+- busy, the Mtp3bSl is working but is congested (traffic is routed on other links).
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bUsageState">
+ <defaultValue>IDLE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="signLinkCode">
+ <description>The signalling link code, SLC, used for this link.
+The code have to be uniqe in this signal link set, i.e the signallingLinkCode for
+all the Mtp3bSl that belongs to the same Mtp3bSls must be unique(mutual exclusive). </description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>15</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="proceduralState">
+ <description>The procedural state of the link.
+
+0 - not initialized
+1 - initialized
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bProceduralState">
+ <defaultValue>NOT_INITIALIZED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="linkCongestLevel">
+ <description>The congestion level of the link.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="CongestLevel">
+ <defaultValue>level_0</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="autoStartLink">
+ <description>Controls if the Mtp3b Signalling Link should be activated at create.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="prioBeforeSio">
+ <description>This Boolean tells if the message priority shall be inserted in an octet before the Service Indicator Octet (SIO).
+
+</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAALINServiceInd">
+ <description>Performance management counter for number of received link-in-service indications.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAALOUTInd">
+ <description>Performance management counter for number of received link-out-of-service indications.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOOXCOSent">
+ <description>Performance management counter for number of sent change over order (COO/XCO) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBDSent">
+ <description>Performance management counter for number of sent CBD messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalLinkCongestRec">
+ <description>Performance monitoring counter for number of local link congestion primitives received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalLinkCongestCeaseRec">
+ <description>Performance monitoring counter for number of local link congestion ceased primitives received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSURec">
+ <description>Performance monitoring counter for number of received MSU's on this signalling link.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUSent">
+ <description>Performance monitoring counter for number of sent MSU's on this signalling link.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="Mtp3bSlTtcId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <action name="deactivate">
+ <description>This action deactivates the Mtp3bSl.
+It will also set autoStartLink = false.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ </action>
+ <action name="activate">
+ <description>This action activates the signalling link with normal alignment. It will also set autoStartLink = true.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ </action>
+ <action name="emergencyActivate">
+ <description>This action activates the signalling link with emergency alignment.
+It will also set autoStartLink = true
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ <raisesException name="FroNotAccessibleException"/>
+ </action>
+ </class>
+
+ <class name="Mtp2ProfileAnsi">
+ <description>The MTP 2 Profile MO represents and keeps attribute values used by one or more MTP 2 ANSI termination point MOs.</description>
+ <attribute name="userLabel">
+ <description>This MOs user label.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="Mtp2ProfileAnsiId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="profileData">
+ <description>Struct containing profile data.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="Mtp2ProfileDataAnsi"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of Mtp2TpAnsi MOs that have reserved this Mtp2TpProfileAnsi MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="Mtp2TpAnsi"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp2ProfileItu">
+ <description>The MTP 2 Profile MO represents and keeps attribute values used by one or more MTP 2 ITU termination point MOs.</description>
+ <attribute name="userLabel">
+ <description>The MOs user label.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="Mtp2ProfileItuId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="profileData">
+ <description>Struct containing profile data.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="Mtp2ProfileDataItu"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of Mtp2TpItu MOs that have reserved this Mtp2TpProfileItu MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="Mtp2TpItu"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="E1Ttp">
+ <description>This MO represents a channelised E1 interface in the node. The E1Ttp (Trail Termination Point) MO
+does not define which type of traffic (TDM or ATM) that the interface should support. Please refer to
+the Ds0Bundle, AtmPort, IMALink and IMAGroup objects for details about configuration of traffic type.
+
+The performance monitoring counters in the E1Ttp MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.
+
+Note! This MO is automatically created as a consequence of creating an Os155SpiTtpMo
+Please refer to the Os155SpiTtpMo for more details.
+
+</description>
+ <systemCreated/>
+ <attribute name="degDegThr">
+ <description>The threshold decides how many of the received blocks that are allowed to have bit errors. The measurement is made on a per-second basis and if the threshold is passed the second is considered bad.
+
+This is a percentage value.
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="degDegM">
+ <description>How many bad seconds in a row that causes a Degraded Signal alarm.
+
+
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>2</min> <max>10</max>
+ </range>
+ <defaultValue>7</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="aisReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="rdiReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="crc4Mode">
+ <description>Indicates what Cyclical Redundancy Check 4 Mode that is being used.</description>
+ <dataType>
+ <enumRef name="Crc4Mode">
+ <defaultValue>AUTOMATIC</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="idlePattern">
+ <description>The idle pattern.
+
+NOTE: Going from A_LAW or U_LAW to UNDEFINED is always allowed but setting up one ET board with
+both U_LAW and A_LAW is not allowed.
+E.g. If you want to change from A_LAW to U_LAW on one ET board you have to change idlePattern
+on each physical port belonging to the board to UNDEFINED first.
+A_LAW -&gt; UNDEFINED -&gt; U_LAW or U_LAW -&gt; UNDEFINED -&gt; A_LAW</description>
+ <dataType>
+ <enumRef name="IdlePattern">
+ <defaultValue>UNDEFINED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmEs">
+ <description>Performance monitoring counter of Errored Seconds (ES).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSes">
+ <description>Performance monitoring counter for Severely Errored Seconds.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="E1TtpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identityof the reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByImaLink">
+ <description>The identity of the reserving ImaLink MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ImaLink"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Vc4Ttp">
+ <description>This MO is automatically created as a consequence of creating an Os155SpiTtp object if any of the following conditions are true:
+a) standardmode = ETSI or
+b) standardmode = TTC and muxmode = VC4_STS3CSPE_LEVEL.
+
+It represents the termination of the SDH VC-4 path layer. The VC-4 can either be used for channelised access, in which case VC-12 MOs are created as children to the Vc4Ttp MO, or be used to carry ATM traffic, in which case there is a relationship between the AtmPort MO and the Vc4Ttp MO.
+
+Note! The performance monitoring counters in the Vc4TtpMO is set to 0 (zero) at start or restart of the node.
+When the value is to large to fit in to a long (31bit) the counter turns over and starts from 0 again.
+</description>
+ <systemCreated/>
+ <attribute name="pathTraceFormat">
+ <description>Indicates the format of the expectedPathtrace and transmittedPathtrace attributes. The format may be in 16 or 64 characters. Usually 16 is used for ETSI and 64 for ANSI/TTC.
+
+ITU_T_G707=16
+GR_253_CORE=64
+
+Note that the 16 characters format requires the operator to specify 15 characters where no character contains the null character (the 16th character is added automatically).
+
+Note that the 64 characters format requires the operator to specify 62 ASCII characters all different from null followed by CR/LF.</description>
+ <dataType>
+ <enumRef name="PathTraceFormat">
+ <defaultValue>ITU_T_G707</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="transmittedPathTrace">
+ <description>The transmitted path trace.
+Can be defined in two formats. The format may be in 16 or 64 characters. Usually 16 is used for ETSI and 64 for ANSI/TTC.
+
+Note: The string must be of 15 or 62 characters length, or empty string ("").
+
+</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>64</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="expectedPathTrace">
+ <description>Expected path trace.
+
+The string can be of 15 or 62 characters length, or empty string ("").
+
+Note: An empty string for this attribute means that the detection of Trace Identifier Mismatch (TIM) should be disabled. This attribute is set to empty string every time attribute pathTraceFormat is set.
+
+</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>64</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="timConsequentAction">
+ <description>Trace Identifier Mismatch (TIM) consequent action, i.e. for generation of Alarm Indication Signal (AIS) downstream and Remote Defect Indication (RDI) upstream as a consequence of the TIM detection.
+
+True - enabled.
+False - disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="vcDegThreshold">
+ <description>This threshold decides how many of the received blocks that are allowed to have bit errors. The measurement is made on a per-second basis and if the threshold is passed the second is considered bad.
+
+The attribute value is in unit of % (percent).</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="vcDegM">
+ <description>Indicates how many bad seconds in a row that causes a Degraded Signal alarm.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>2</min> <max>10</max>
+ </range>
+ <defaultValue>7</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="auAisReporting">
+ <description>AU AIS reporting.
+
+True - enable reporting.
+False - disable reporting.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="vcRdiReporting">
+ <description>VC RDI reporting.
+
+True - enable reporting.
+False - disable reporting.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmVcEs">
+ <description>Performance monitoring counter for Virtual Container 4, VC4, Errored Seconds, ES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmVcSes">
+ <description>Performance monitoring counter for Virtual Container 4, VC4, Severely Errored Seconds, SES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="Vc4TtpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Os155SpiTtp">
+ <description>This MO represents the physical interface and the termination of the SDH Regenerator and Multiplexer Section Layers.
+
+When creating the Os155SpiTtp a number of additional objects will be created. Depending on the values of standardmode and muxmode different objects will be created as described below:
+
+muxmode = standby
+standardmode = ETSI, TTC, ANSI
+No objects under the Os155SpiTtp is created.
+
+muxmode = VC4_STS3CSPE_LEVEL
+standardmode = ETSI, TTC
+A Vc4 MO is created under the Os155SpiTtp MO.
+
+muxmode = VC4_STS3CSPE_LEVEL
+standardmode = ANSI
+A Sts3CspeTtp MO is created under the Os155SpiTtp MO.
+
+The following two configurations is only applicable for the ET-MC41 board.
+
+muxmode = E1_J1_T1_LEVEL
+standardmode = ETSI
+A Vc4 MO, 63 Vc12Ttp MO's and 63 E1Ttp MO's is created under the Os155SpiTtp MO
+
+muxmode = E1_J1_T1_LEVEL
+standardmode = ANSI
+3 Sts1CspeTtp MO's, 3*28 Vt15Ttp MO's and 3*28 TiTtp MO's is created under the Os155SpiTtp MO.
+
+The performance monitoring counters in the Os155SpiTtp MO is set to 0 (zero) at start or restart of the node.
+When the value is too large too fit in to a long (31bit) the counter turns over and starts from 0 again.
+
+Note! If the Os155SpiTtp is configured as part of an Mspg protection group and is configured as standby, muxMode set to standby, no children's to this MO will be created.</description>
+ <attribute name="Os155SpiTtpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="lineNo">
+ <description>The actual line number.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>2</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="standardMode">
+ <description>The standard that this MO is operating to.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="StandardMode">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimeout">
+ <description>The shut-down timer. It is used when the administrativeState is set to shutdown.
+
+Value in seconds, must be a positive value.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100000</max>
+ </range>
+ <defaultValue>1800</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="muxMode">
+ <description>The level at which the STM-1/OC3 signal is demultiplexed.
+
+If parent is of type Etmc41, the valid muxMode is STANDBY or E1_J1_T1_LEVEL.
+If parent is of type Etm4, the valid muxMode is STANDBY or VC4_STS3CSPE_LEVEL.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="MuxMode">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="msDegThreshold">
+ <description>MS - multiplexer section.
+
+The threshold decides how many of the received blocks that are allowed to have bit errors. The measurement is made on a per-second basis and if the threshold is passed the second is considered bad.
+
+This is a percentage value.
+
+Note: When operating to the ANSI standard, this attribute has no meaning.
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="msDegM">
+ <description>MS - multiplexer section.
+
+How many bad seconds in a row that causes a Degraded Signal alarm.
+
+Note: When operating to the ANSI standard, this attribute has no meaning.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>2</min> <max>10</max>
+ </range>
+ <defaultValue>7</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="msRdiReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="msAisReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="loopBack">
+ <description>Enables or disables line loopback, i.e. the received signal is returned in the transmitted direction.
+
+none - This is the normal state, no loop back is performed (and ordinary traffic is running).
+
+line - The physical path is looped on the line side, the external incoming path is looped back to the external outgoing path.
+
+Note! administrativeStatus must be set to locked when setting loopback attribute.</description>
+ <dataType>
+ <enumRef name="Os155LoopBack">
+ <defaultValue>NONE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmMsEs">
+ <description>Performance monitoring counter for Multiplexer Section, MS, Errored Seconds, ES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmMsSes">
+ <description>Performance monitoring counter for Multiplexer Section, MS, Severely Errored Seconds, SES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBySync">
+ <description>The identity of the reserving Synchronization MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Synchronization"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Vc12Ttp">
+ <description>This MO is automatically created when the configuring the Os155SpiTtp. It represents the termination of the SDH VC-12 path layer.
+
+Note: This MO is only valid when the ETSI standard is in use.
+
+The performance monitoring counters in the Vc12TtpMO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.</description>
+ <systemCreated/>
+ <attribute name="Vc12TtpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="transmittedPathTrace">
+ <description>The transmitted path trace.
+
+Note: when 16 byte tracing is used, only 15 bytes should be used in the set action for this attribute.
+
+
+</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>64</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="expectedPathTrace">
+ <description>Expected path trace.
+
+Note: when 16 byte tracing is used, only 15 bytes should be used in the set action for this attribute.
+
+Note: An empty string for this attribute means that the detection of Trace Identifier Mismatch (TIM) should be disabled.
+</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>64</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="timConsequentAction">
+ <description>Trace Identifier Mismatch (TIM) consequent action, i.e. for generation of Alarm Indication Signal (AIS) downstream and Remote Defect Indication (RDI) upstream as a consequence of the TIM detection.
+
+True - enabled.
+False - disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="vcDegThreshold">
+ <description>This threshold decides how many of the received blocks that are allowed to have bit errors. The measurement is made on a per-second basis and if the threshold is passed the second is considered bad.
+
+The attribute value is in unit of % (percent).</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="vcDegM">
+ <description>Indicates how many bad seconds in a row that causes a Degraded Signal alarm.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>2</min> <max>10</max>
+ </range>
+ <defaultValue>7</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tuAisReporting">
+ <description>Timing Unit Alarm Indication Signal (TU AIS) reporting.
+
+True - enable reporting.
+False - disable reporting.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="vcRdiReporting">
+ <description>VC RDI reporting.
+
+True - enable reporting.
+False - disable reporting.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmVcEs">
+ <description>Performance monitoring counter for Virtual Container 12, VC12, Errored Seconds, ES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmVcSes">
+ <description>Performance monitoring counter for Virtual Container 12, VC12, Severely Errored Seconds, SES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimeout">
+ <description>The shut-down timer. It is used when the administrativeState is set to shutdown.
+
+Value in seconds, must be a positive value.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100000</max>
+ </range>
+ <defaultValue>1800</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Etmc1">
+ <description>This MO represents the hardware of the ET-MC1 board type. It only represents the ET specific hardware, the DBM module of the board is represented by the PlugInUnit MO.
+
+The ET-MC1 board contains 8 phyiscal ports that can be configured as either E1 (ETSI), J1 (TTC) or T1(ANSI). The board does not allow for a mix of E1, J1 and T1 ports, thus all configured ports on the board must be configured to the same standard.
+
+Each port on the ET-MC1 board can be used to carry either ATM traffic or circuit orientated (Nx64 Kbits/s connections) traffic.
+
+Each port can support up to 30 ATM VC connections. Two of these connections are reserved for AAL2 paths, and therefore two AAL2 multiplexers per port are available.
+
+Each port can support up to 2 VP connections.
+
+The ET-MC1 port supports one bidirectional F4/F5 PM flow per port.
+
+At the VP/VC endpoints, the Lost FPM/BR cells counters are not available.
+
+Note! The ETMC1 supports IMA.
+
+For more details on restrictions please refer to 155 17-21/CSX 101 09 Uen.
+
+Note! When the Etmc1 is part of the Cbu it is only possible to configure 4 physical ports of type E1, J1 or T1 on the Etmc1 board.</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Enabled or disabled according to the actual operational state of the ETMC1 board.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="Etmc1Id">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Etmc41">
+ <description>This MO represents the hardware of the ET-MC41 board type. It only represents the ET specific hardware, while the DBM module of the board is represented by the PlugInUnit MO.
+
+The ET-MC41 board contains a 155 Mbits/s physical optical port. The board can be configured as a E1 channelised board providing 63 logical E1 interfaces.
+
+Each E1 logical channel on the ET-MC41 can be used to carry either ATM traffic or circuit oriented (Nx64 kbit/s) traffic.
+
+Each E1 logical channel can support up to 30 ATM VC connections. Two of these connections are reserved for aal2 paths, and therefore two AAL2 multiplexers per E1/DS1/J1 channel are available.
+
+Each E1/DS1/J1 channel can suport up to 2 VP connections.
+
+The ET-MC41 board support one biderectional F4/F5 PM flow per E1 channel.
+
+Note! The ETMC41 supports IMA. However the E1 ports being part of the same IMA group can not be selected randomly.
+
+Note! The number of VCC TP+VPC TP with performance monitoring enabled (i.e. PM mode &lt;&gt; off) is restricted to 1 / port
+
+For more details on restrictions please refer to 155 17-21/CSX 101 09 Uen.</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Enabled or disabled according to the actual operational state of the ET-MC41 board.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="Etmc41Id">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp2ProfileChina">
+ <description>The MTP2 Profile MO represents and keeps attribute values used by one or more MTP2 China termination point MOs.</description>
+ <attribute name="Mtp2ProfileChinaId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="profileData">
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="Mtp2ProfileDataChina"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of Mtp2TpChina MOs that have reserved this Mtp2TpProfileChina MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="Mtp2TpChina"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>The MOs user label.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp2TpChina">
+ <description>This MO represents a MTP 2 termination point for the China standard, as defined in GF001-9001, plus supplement 1-3.
+
+The performance monitoring counters found in Mtp2China MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is a hardware fault, aal1 server/adm restart or node restart.
+
+NOTE: This MO cannot in anyway be related (either contained by or dependent on) an MO that belongs to a standard
+which is NOT the China standard.
+
+NOTE: There is a restriction of a maximum of 32 Mtp2Tp's per MP.
+
+</description>
+ <attribute name="ds0BundleId">
+ <description>The Ds0Bundle MO that this MO references.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Ds0Bundle"/>
+ </dataType>
+ </attribute>
+ <attribute name="mtp2ProfileChinaId">
+ <description>Reference to a Mtp2ProfileChina MO.
+
+Note: The bitRate can not be changed.</description>
+ <mandatory/>
+ <noNotification/>
+ <dataType>
+ <moRef name="Mtp2ProfileChina"/>
+ </dataType>
+ </attribute>
+ <attribute name="Mtp2TpChinaId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the MTP2 Signalling Terminal.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmLocalSIBTime">
+ <description>Total time in local SIB (Sending).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUTransmitted">
+ <description>Number of MSUs transmitted.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfNacks">
+ <description>Number of negative acknowledgements received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuReceivedInError">
+ <description>Number of signal units received in error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfReTransmittedOctets">
+ <description>Number of re-transmitted octets.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSendBufferOctets">
+ <description>Number of octets in send buffer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSIOSIFReceived">
+ <description>Number of SIO and SIF octets received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSIOSIFTransmitted">
+ <description>Number of SIO &amp; SIF octets transmitted.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfStartedRBCongestion">
+ <description>Number of started local RB congestions.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmRemoteSIBTime">
+ <description>Total time in remote SIB (Receiving).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Mtp3bSlChina"/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Free tag for marking this managed object.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="plugInUnitId">
+ <description>The PlugInUnit MO that this MO references.
+It indicates on which processor the Termination Point will be.
+
+Note: The PlugInUnit must be of type GPB.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="PlugInUnit"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUReceived">
+ <description>Number of MSUs received..</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mtp3bSlChina">
+ <description>This MO represents an MTP3b Signalling Link for the China standard. It represents the termination of the signalling link within the signalling point as defined in GF001-9001, plus supplement 1-3.
+
+The total amount of links between any two specific nodes in the network shall not be more than 16, independent on how many linksets that are defined between the two nodes. The signalLinkCode for a link must be unique between the nodes, independent on which linkSet the link belongs to.
+
+The performance monitoring counters found in Mtp3SlChina MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).
+
+NOTE: This MO cannot in anyway be related (either contain or by dependence) to an MO that belongs to a standard that is NOT the China standard.</description>
+ <attribute name="Mtp3bSlChinaId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>This attribute reflects the operational status of the Mtp3bSl.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="autoStartLink">
+ <description>Controls if the Mtp3b Signalling Link should be activated at create.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="linkCongestLevel">
+ <description>The congestion level of the link.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="CongestLevel">
+ <defaultValue>level_0</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="linkState">
+ <description>The link state of the Mtp3bSl.
+
+The link state is a bit map which contains a combination of the following values: (in hexadecimal format)
+
+0x00 Available
+0x01 Failed
+0x02 Remotely blocked
+0x04 Locally blocked
+0x08 Remotely inhibited
+0x10 Locally inhibited
+0x20 Deactivated</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="prioBeforeSio">
+ <description>This Boolean tells if the message priority shall be inserted in an octet before the Service Indicator Octet (SIO).
+
+China default is false.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="proceduralState">
+ <description>The procedural state of the link.
+
+0 - not initialized
+1 - initialized
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bProceduralState">
+ <defaultValue>NOT_INITIALIZED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="signLinkCode">
+ <description>The signalling link code, SLC, used for this link.
+The signLinkCode for a link must be unique between the nodes,
+independent on in which linkSet the link belongs.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>15</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tpId">
+ <description>The tpId attribute points out the termination point of the lower layer protocol.
+
+For narrowband this signalling link will be connected to an MTP L2 termination point (Mtp2Tp MO). And for broadband it will be connected to a NNI SAAL termination point (NniSaalTp Mo).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="usageState">
+ <description>There are three possible states for the usageState attribute:
+
+- idle, the Mtp3bSl carries no traffic.
+- active, the Mtp3bSl is working normally, and there is traffic, and it is not congested.
+- busy, the Mtp3bSl is working but is congested (traffic is routed on other links).
+
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bUsageState">
+ <defaultValue>IDLE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAALINServiceInd">
+ <description>Performance management counter for number of received link-in-service indications.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAALOUTInd">
+ <description>Performance management counter for number of received link-out-of-service indications.
+
+Note! This counter is incremented every time a link out of service indication is received for the link.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBDSent">
+ <description>Performance management counter for number of sent CBD messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOOXCOSent">
+ <description>Performance management counter for number of sent change over order (COO/XCO) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalLinkCongestCeaseRec">
+ <description>Performance monitoring counter for number of local link congestion ceased primitives received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLocalLinkCongestRec">
+ <description>Performance monitoring counter for number of local link congestion primitives received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSURec">
+ <description>Performance monitoring counter for number of received MSU's on this signalling link.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMSUSent">
+ <description>Performance monitoring counter for number of sent MSU's on this signalling link.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <action name="activate">
+ <description>This action activates the Mtp3bSl with normal alignment. It will also set autoStartLink = true.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="deactivate">
+ <description>This action deactivates the Mtp3bSl.
+It will also set autoStartLink = false.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="emergencyActivate">
+ <description>This action activates the Mtp3bSl with emergency alignment.
+It will also set autoStartLink = true
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="localInhibit">
+ <description>This action inhibits the Mtp3bSlChina. Signalling link management inhibiting is requested by management when it becomes necessary, e.g for maintenance or testing purposes to make or keep a signalling link unavailable to User Part-generated signalling traffic.
+Inhibiting of a signalling link may be requested by management function at either end of the link. The request is granted, provided that the inhibiting action does not cause any previously accessible destinations to become inaccessible at either end of the signalling link. The request may also be refused under certain circumstances such as congestion.
+Exception FroRequestFailed if it was not possible to inhibit.
+
+Note! This action requires a transaction.
+</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ <action name="localUninhibit">
+ <description>This action uninhibits the Mtp3bSlItu.
+
+Exception FrorequestFailed if it was not possible to uninhibit.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FroRequestFailedException"/>
+ </action>
+ </class>
+
+ <class name="Mtp3bSpChina">
+ <description>Mtp3b Signalling Point for the China standard.
+
+This MO represents/models the MTP3b Signaling Point characteristics/functions according to the China standard.
+A signaling point is a logical node in the signaling network. The combination of signaling points and their interconnecting
+signaling links form the SS No. 7 signaling network. The signaling point represented by this object is a Local Signaling Point.
+
+The performance monitoring counters found in Mtp3SpChina MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is shutdown request from CLI (Cluster Interface).
+
+NOTE: IT IS NOT POSSIBLE TO CREATE SIGNALLING POINTS OF DIFFERENT STANDARDS!
+
+NOTE: This MO cannot in anyway be related (either contain or by dependence) to an MO that belongs to a standard which is NOT the China standard.
+
+NOTE: The combination of network indicator (networkInd) and Signalling Point Code (signallingPointCode) has to be unique for each Signalling Point.
+
+NOTE: A maximum of 15 instances of this MO can be created on (referencing) the same PlugInUnit.
+
+NOTE: The maximum number of Signalling Points that can be created in a CPP based node is 24.
+
+NOTE: Deleting a singel L3 Signal Point is not possible, if it necessary to delete a Signal Point then all Signal Points has to be deleted. This also has to be done whitin the same transaction.
+
+NOTE: Any object created under a certain SP (Signaling Point) cannot refer to an object created under another SP. Nor can it refer to an object created under another SP.</description>
+ <attribute name="Mtp3bSpChinaId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="maxSizeChangeBuf">
+ <description>The maxSizeChangeBuf attribute represents the maximum size (in kB) of the changeover buffer.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>5000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxSizeReroutBuf">
+ <description>The maxSizeReroutBuf attribute represents the maximum size (in kB) of the rerouting buffer.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>5000</max>
+ </range>
+ <defaultValue>2000</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="networkInd">
+ <description>The network indicator, NI, is used for discrimination of messages between functionally different networks.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="Mtp3bNetworkInd">
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operationalState attribute reflects the operational status of the MTP3b SP.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds a list of the reserving MO's. Can be of type SccpSp.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="sendSltmBefLink">
+ <description>The sendSltmBefLink attribute determines if the SLTM (Signalling Link Test Message) should be sent and a SLTA received before the link is considered to be in service.
+
+Note! It is not recommended nor is it in accordance with standard to set the value of this attribute to 'false' </description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="signallingPointCode">
+ <description>The signallingPointCode (Local Point Code) attribute (SPC) is used together with the network indicator (NI, networkInd attribute) to uniquely identify the MTP Signalling Point, SP.
+SP = NI-SPC.
+Size (2 exp 24)-1 (16777215).
+The SignallingPointCode (SPC) is nornally used as a whole unique number (no internal structure). But sometimes the SPC is grouped together as three numbers which corresponds to zone, area/network, signalling point. If this is the case the three numbers are coded as 8-8-8 bits in the total SPC. To enter the SPC-value then you have to convert the three numbers to their binary code and then convert the whole 24-bit pattern as an integer.
+ </description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16777215</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="nodeBehaviour">
+ <description>The nodeBehaviour attribute represents the MTP3b node type.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="NodeBehaviourType">
+ <defaultValue>SEP</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="noOfCongestLevelForNI">
+ <description>Defines the number of congestion levels for NI.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>3</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="routeSetCongestTestFlag">
+ <description>Selection of which procedure to use during congestion handling if the national option with priorities is used.
+
+0, use TcTimer as described by the TTC standard.
+1, use Route Set Congestion Test as described by the ANSI, ITU and China Standard.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="resendTfcInterval">
+ <description>Send TFC back to originating signalling point code for every n:th message when
+the destination is congested. Set to 0 will suppress sending of TFC.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="sioSpare">
+ <description>The sioSpare attribute determines if the two spare bits in the SIO (Service Information Octet) should be treated as spare.</description>
+ <dataType>
+ <enumRef name="Mtp3bSioSpareBitsUse">
+ <defaultValue>SPARE</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="spPriority">
+ <description>Struct containing the priority attributes.
+
+Note: The China and ITU priorityData is identical so the ItuPriorityData is used for China to avoid duplication of data.</description>
+ <dataType>
+ <structRef name="Mtp3bSpChinaPriorityData"/>
+ </dataType>
+ </attribute>
+ <attribute name="spTimer">
+ <description>Struct containing China specific timer attributes</description>
+ <dataType>
+ <structRef name="Mtp3bSpChinaTimerData"/>
+ </dataType>
+ </attribute>
+ <attribute name="statusIndInterval">
+ <description>The statusIndInterval attribute sets the interval for sending MTP-STATUS indication, i.e. send indication every Nth message .</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="testPatternSltm">
+ <description>The testPatternSltm attribute represents a string testpattern in the Signalling Link Test Message.
+
+Minimum string length 2 characters, maximum 30 characters. Allowed characters are 0-9, A-F.
+Only even number of characters is allowed.
+
+</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>2</min> <max>30</max>
+ </lengthRange>
+ <defaultValue>"A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5"</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="transFrHandler">
+ <description>Determines if a TransFer Restricted signal (TFR) should be treated as a TFA (TransFer Allowed signal) or be ignored.
+</description>
+ <dataType>
+ <enumRef name="Mtp3bTfrHandling">
+ <defaultValue>IGNORED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="rpuId">
+ <description>Holds a reference to the Reliable Program Uniter.
+The RPU is at the server.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ReliableProgramUniter"/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="m3uaNoOfAttempsOfDauds">
+ <description>For M3UA, number of attempts to send the DAUD message.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="noOfAttempsOfAssociationEstablishment">
+ <description>Number of attempts to send the SCTP_ASSOCIATE_REQ message.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>65535</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="version">
+ <description>This attribute shows what MTP3b ITU standard the system follows. With ITU, it is possible using this attribute to set which of the ITU standard versions that shall be followed.
+
+Note! Setting of another value than 'ITU_T_07_96' at create will have no effect. The Signaling Point will always be created with the value 'ITU_T_07_96'.
+
+Note! It is not possible to hav signaling points with different versions in the node so setting of this attribute will effect all signaling points. The value for the last created or changed signaling point will be used for all signaling points.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="Mtp3bItuVersion">
+ <defaultValue>ITU_T_07_96</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBARec">
+ <description>Performance management counter for number of received CBA messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCBASent">
+ <description>Performance management counter for number of sent CBA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfChangeBackDeclRec">
+ <description>Performance management counter for number of received change Back Declarations (CBD) messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfChangeOverRec">
+ <description>Performance counter for number of changeOver order messages (COO/XCO) received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOAXCARec">
+ <description>Performance management counter for number of received COA/XCA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCOAXCASent">
+ <description>Performance management counter for number of sent COA/XCA messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfControlledRerouteSuccessPerf">
+ <description>Performance monitoring counter for number of successfully performed controlled rerouting.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECASent">
+ <description>Performance management counter for number of sent ECA messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECARec">
+ <description>Performance management counter for number of received ECA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfECOSent">
+ <description>Performance management counter for number of sent ECO messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfEmergencyChangeOverRec">
+ <description>Performance management counter for number of received emergency changeOver orders (ECO) messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfForcedRerouteSuccessPerf">
+ <description>Performance monitoring counter for number of successfully performed forced rerouting.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSLTAFirstTimeOutRec">
+ <description>Performance management counter for number of SLTA first time out received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSLTASecondTimeOutRec">
+ <description>Performance management counter for number of SLTA second time out received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTimerT21WasStarted">
+ <description>Performance monitoring counter for number of times the timer T21 was started (i.e. adjacent SP restarted).
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTRARec">
+ <description>Performance management counter for number of received TRA messages.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfTRASent">
+ <description>Performance management counter for number of sent TRA messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessControlledRerouting">
+ <description>Performance monitoring counter for number of unsuccessfully performed controlled reroutings.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessForcedRerouting">
+ <description>Performance monitoring counter for number of unsuccessfully performed forced reroutings.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUPMsgDiscardedDueToRoutingErr">
+ <description>Performance monitoring counter for number of UP (user part) messages (MTP_TRANSFER_req) discarded due to routing error.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocEstablish">
+ <description>Performance management counter for number of successful association establishment.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocEstablish">
+ <description>Performance management counter for number of unsuccessful association establishment.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpCommunicationErr">
+ <description>Performance management counter for number of SCTP communication error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpSendFailure">
+ <description>Performance management counter for number of SCTP send failure.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpBufOverflow">
+ <description>Performance management counter for number of SCTP stop sending data.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpResumeSending">
+ <description>Performance management counter for number of SCTP resume sending data.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpNetworkStatusChange">
+ <description>Performance management counter for number of SCTP network status change.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSctpAssociationRestart">
+ <description>Performance management counter for number of SCTP association restart.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocAbort">
+ <description>The number of successful abortions of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSuccessAssocShutDown">
+ <description>The number of succesful shutdowns of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocAbort">
+ <description>The number of unsuccessful abortions of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfUnsuccessAssocShutDown">
+ <description>The number of unsuccesful shutdowns of signalling associations.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIncomingAssocEstabRequestInStateDownWhenStateEstabIsBlocked">
+ <description>The number of incoming request for association establishment when state on the association is 'DOWN' and establishment of associations is blocked. </description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMaxTrialsForAssocEstabReached">
+ <description>The number of times that the max limit for trying to establish an association has been reached.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMaxTrialsForAssocActivReached">
+ <description>The number of times that the max limit for trying to activate an association has been reached.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfLowerPrioMsgDiscarded">
+ <description>The number of messages with low priority that has been discarded.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Mspg">
+ <description>The MSPG (Multiplex Section Protection Group) object enables two different protection mechanism in Cello. First it enables a standard 1+1 MSP mechanism. A failure on the working line will thus cause a sub 50 ms switch to the standby line.
+Secondly the MSPG is used to enable equipment protection, whereas a failure of the working board will cause a switch to the standby board. While executing an equipment protection switch, the node on the other end of the multiplexer section, will experience a standard 1+1 MSP switch.
+
+It is possible to force traffic to one port/board by using administrative state.
+Setting administrative state to locked on the working board, will automatically cause an equipment switch to the standby board. Similarily setting administrative state to locked on the working port, will cause an MSP switch to the standby port.
+
+The process of configuring a MSP protection interface is as follows:
+1) Create the working interface as normal.
+2) Create the standby interface by creating an Os155SpiTtp with mux mode set to STANDBY (standby for protection).
+3) Create a MSPG object with references to the two Os155SpiTtp objects.
+
+Note! The ports selected for MSPG must be have the attribute standardMode configured in exactly the same way.
+
+Note! The Os155SpiTtp created for standby will not create any children, i.e no Vc4Ttp or Vc4Ttp, Vc12Ttp and E1Ttp will be created. Nor will object of type Sts1SpeTtp, Vt15Ttp or T1Ttp be created.</description>
+ <attribute name="os155SpiWorkingId">
+ <description>The working OS155 pyhiscal path termination.
+This is the administrative value.
+
+To retrive the Id of the current working port, use the selectedPort.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Os155SpiTtp"/>
+ </dataType>
+ </attribute>
+ <attribute name="os155SpiStandbyId">
+ <description>The standby OS155 physical path termination.
+This is the administrative value.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Os155SpiTtp"/>
+ </dataType>
+ </attribute>
+ <attribute name="switchMode">
+ <description>The switching mode.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="SwitchModes">
+ <defaultValue>AUTOMATIC</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the Mspg.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="MspgId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="selectedPort">
+ <description>The port currently selected by the MSPG. The selected port can only
+change due to a MSP or equipment switch.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Os155SpiTtp"/>
+ </dataType>
+ </attribute>
+ <attribute name="selectedBoard">
+ <description>The board currently providing the user traffic interface to the Cello switch.
+The only action that can change the selected board is an equipment switch.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="degCauseMsp">
+ <description>If set to true, then a swith is performed upon detection of DEG.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <action name="manualMspSwitch">
+ <description>Initiates a switch when there does not exist a defect.
+
+This action can fail for the following reasons:
+FailedResource - the switch was not possible due to a traffic affecting fault on the port to which the switch was requested (i.e. the one not currently selected).
+LockedResource - the port to which the switch is intended is administratively locked.
+UnknownReason - there exists another fault that prevents the action.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="FailedResourceException"/>
+ <raisesException name="LockedResourceException"/>
+ <raisesException name="UnknownReasonException"/>
+ </action>
+ </class>
+
+ <class name="T1PhysPathTerm">
+ <description>This MO represents an T1 (i.e. 1.5 Mbit/s) physical interface in the node. The T1PhysPathTerm MO does not define which type of traffic (TDM or ATM) that the interface should support.
+Please refer to the Ds0Bundle, AtmPort, IMALink and IMAGroup objects for details about configuration of traffic type.
+
+</description>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="T1PhysPathTermId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="lineNo">
+ <description>The actual Line number on the board.
+</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>8</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="loopback">
+ <description>Possible values
+
+none - This is the normal state, no loop back is performed (and ordinary traffic is running).
+
+line - The physical path is looped on the line side, the external incoming path is looped back to the external outgoing path.
+
+system - The physical path is looped on the system side, the (node-) internal incoming path is looped back to the internal outgoing path.
+
+Note! administrativeStatus must be set to locked when setting loopback attribute.</description>
+ <dataType>
+ <enumRef name="LoopbackState">
+ <defaultValue>none</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmEs">
+ <description>Performance monitoring counter for Errored Seconds, ES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSes">
+ <description>Performance monitoring counter for Severly Errored Seconds, SES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByTraffic">
+ <description>The identity of the reserving AtmPort MO. </description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Enabled or disabled according to the actual operational state of the Physical Line Termination. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="rdiReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="aisReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimeout">
+ <description>The shut-down timer. It is used when the administrativeState is set to shutdown.
+
+Value in seconds, must be a positive value.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100000</max>
+ </range>
+ <defaultValue>1800</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="idlePattern">
+ <description>The idle pattern.
+
+NOTE: Going from A_LAW or U_LAW to UNDEFINED is always allowed but setting up one ET board with
+both U_LAW and A_LAW is not allowed.
+E.g. If you want to change from A_LAW to U_LAW on one ET board you have to change idlePattern
+on each physical port belonging to the board to UNDEFINED first.
+A_LAW -&gt; UNDEFINED -&gt; U_LAW or U_LAW -&gt; UNDEFINED -&gt; A_LAW</description>
+ <dataType>
+ <enumRef name="IdlePattern">
+ <defaultValue>UNDEFINED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="transmissionMode">
+ <description>The type of transmission media.
+Refer to the TransmissionMode enumeration for details.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="TransmissionMode">
+ <defaultValue>S_133</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBySync">
+ <description>The identity of the reserving Synchronization MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Synchronization"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByImaLink">
+ <description>The identity of the reserving ImaLink MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ImaLink"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="ImaGroup">
+ <description>IMA, Inverse Multiplexing for ATM, makes it possible to group several physical
+interfaces together to form a virtual physical pipe for atm. The capacity of this
+pipe is equal to the sum of each of the physical interfaces included in the
+group.
+
+When IMA should be configured, an ATMPort MO is created with reference to an
+IMAGroup MO rather than a pure physical interface MO.
+The IMAGroup MO in turn is created with a list of the physical port MO's that
+are included in the group. The physical port MO's must be of the same type
+and be located on the same ET board.
+
+For each of the physical port MO's included in the IMAGroup, an IMALink object
+is automatically created. The IMALink object is responsible for handling link
+specific performance and fault management related to IMA.
+
+The ports can be of type E1PhysPathTerm, J1PhysPathTerm, T1PhysPathTerm, E1Ttp, T1Ttp.
+
+The performance monitoring counters in the ImaGroup MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.
+
+Note! A general restriction in Cello is that ports being part of the same IMA group
+must be located on the same board.
+
+Note! Only termination points on Etmc1 and Etmc41 boards are allowed as ImaLinks.
+
+Note! At least two links has to be configured in an Ima Group.</description>
+ <attribute name="ImaGroupId">
+ <description>The identity of the MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="physicalPortList">
+ <description>Holds a list of the physical ports connected to the ImaGroup.
+Can be of type:
+E1PhysPathTerm,
+J1PhysPathTerm,
+T1PhysPathTerm,
+E1Ttp,
+T1Ttp.</description>
+ <mandatory/>
+ <noNotification/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="requiredNumberOfLinks">
+ <description>The required number of links specifies the number of IMALinks that needs to be
+operational in order for the complete group to be operational. The bandwidth
+available for the ATMPort (and thus for creating VP/VC connections) is defined
+by this number.
+Setting the requiredNumberOfLinks field to K less than the number of physical
+links included in the IMAGroup, will reduce the bandwidth available to the atmport
+with the corresponding bandwidth but will also give the effect that K links
+failures can be tolerated with virtually no traffic disturbance.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>8</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="activeLinks">
+ <description>The number of active links in the ImaGroup.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Enabled or disabled according to the actual operational state of the ImaGroup.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmGrUasIma">
+ <description>This performance counter reflects the GrUasLma attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmGrFc">
+ <description>This performance counter reflects the GrFc attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmGrFcFe">
+ <description>This performance counter reflects the GrFcFe attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="ImaLink">
+ <description>This MO is automatically created as a consequence of creating an IMAGroup or
+adding links to an IMAGroup.
+It provides IMA Link specific performance and fault management information.
+
+The links can be of type E1PhysPathTerm, J1PhysPathTerm, T1PhysPathTerm, E1Ttp or T1Ttp.
+
+The performance monitoring counters in the ImaLink MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.
+
+Note! A general restriction in Cello is that ports being part of the same IMA group
+must be located on the same board.</description>
+ <attribute name="operationalState">
+ <description>Enabled or disabled according to the actual operational state of the ImaLink.
+If the operationalState is disabled the ImaLink will be blocked for traffic.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmIvIma">
+ <description>This performance counter reflects the LvLma attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ImaLinkId">
+ <description>The identity of the MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="pmOifIma">
+ <description>This performance counter reflects the OifLma attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSesIma">
+ <description>This performance counter reflects the SesLma attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSesImaFe">
+ <description>This performance counter reflects the SesLmaFe attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUasIma">
+ <description>This performance counter reflects the UasLma attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUasImaFe">
+ <description>This performance counter reflects the UasLmaFe attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmTxUusIma">
+ <description>This performance counter reflects the TxUusLma attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmRxUusIma">
+ <description>This performance counter reflects the RxUusLma attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmTxUusImaFe">
+ <description>This performance counter reflects the TxUusLmaFe attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmRxUusImaFe">
+ <description>This performance counter reflects the RxUusLmaFe attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmTxFc">
+ <description>This performance counter reflects the TxFc attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmRxFc">
+ <description>This performance counter reflects the RxFc attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmTxFcFe">
+ <description>This performance counter reflects the TxFcFe attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmRxFcFe">
+ <description>This performance counter reflects the RxFcFe attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmTxStuffIma">
+ <description>This performance counter reflects the TxStuffLma attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmRxStuffIma">
+ <description>This performance counter reflects the RxStuffLma attribute as defined by Inverse Multiplexing for ATM(IMA) specification ver. 1.1, AF-PHY-0086.001</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="uses">
+ <description>Reference to the physical port represented by this MO.
+Can be of types E1PhysPathTerm, J1PhysPathTerm, T1PhysPathTerm, E1Ttp or T1Ttp.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Sts3CspeTtp">
+ <description>This MO represents the termination of the SONET higher order paths.
+This MO is automatically created when creating the OS155SPITTP with mux mode
+set to VC4_STS3CSPE_LEVEL and standardMode set to ANSI.
+
+The performance monitoring counters in the Sts3CspeTtp MO is set to 0 (zero) at start or restart of the node.
+When the value is to large to fit in to a long (31bit) the counter turns over and starts from 0 again.</description>
+ <attribute name="Sts3CspeTtpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>User label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>enabled or disabled according to the actual operational state of the Sts3CspeTtp.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="aisPReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="rdiPReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="timConsequentAction">
+ <description>Trace Identifier Mismatch (TIM) consequent action, i.e. for generation of Alarm Indication Signal (AIS) downstream and Remote Defect Indication (RDI) upstream as a consequence of the TIM detection.
+
+True - enabled.
+False - disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="expectedPathTrace">
+ <description>Expected path trace.
+
+The string can be of 64 characters length, or empty string ("").
+The string shall consist of 62 ASCII characters followed by CR/LF.
+The empty string shall be coded with the first character equal to ASCII null (i.e. byte value 0) and the rest dummy or non-existing.
+
+Note: An empty string for this attribute means that the detection of Trace Identifier Mismatch (TIM) should be disabled. This attribute is set to empty string every time attribute pathTraceFormat is set.</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>64</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="transmittedPathTrace">
+ <description>The transmitted path trace.
+
+The string shall consist of 62 ASCII characters followed by CR/LF.
+The empty string shall be coded with the first character equal to ASCII null (i.e. byte value 0) and the rest dummy or non-existing.</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>64</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Identity of the AtmPort reserving this MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmEsp">
+ <description>Performance Monitoring counter for ES, Errored Seconds.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSesp">
+ <description>Performance Monitoring counter for Severely Errored Seconds, SES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="WebServer">
+ <description>The WebServer MO represents the WebServer in the node.
+
+This object is used for configuration of the WebServer paths. By connecting this object to a
+SwAllocation MO that is connected to a Repertoire MO the WebServer paths will be
+automatically configured during system upgrade.
+
+The local distinguished name of this MO is ManagedElement=1, WebServer=1.
+
+The WebServer MO is created automatically by the system.</description>
+ <systemCreated/>
+ <attribute name="WebServerId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="webServerPaths">
+ <description>Paths that shall be used by the WebServer separated by the delimiter character ":".</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBySwAllocation">
+ <description>List of reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="SwAllocation"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="IpAccessAutoConfig">
+ <description>This MO represents the Auto Configuration feature for the IpAccessHost's in Cello.
+
+</description>
+ <attribute name="IpAccessAutoConfigId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Hold a list of the identitys of the reserving IpAccessHost's.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="networkPrefix">
+ <description>The network prefix.
+
+The prefix denotes how many bits that are used for calculating the subnet mask.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>32</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="nrOfUnusedAdresses">
+ <description>The number of addresses in the range that are not used.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="totalNrOfAddresses">
+ <description>The total number of addresses in the range.
+
+Note that the first address in the range will be the same one as the one for networkAddress.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="minIpAddress">
+ <description>The lowest value that can be used as host IP address. If autoConfig=ON for an IpAccessHost, the operator does not explicitly have to assign an Ip Address and prefixLength to the host. This is done by the Control Plane, based on the IpAccesAutoConfig identity specified for the IpAccessHost.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="maxIpAddress">
+ <description>The highest value that can be used as host IP address. If autoConfig=ON for an IpAccessHost, the operator does not explicitly have to assign an Ip Address and prefixLength to the host. This is done by the Control Plane, based on the IpAccesAutoConfig identity specified for the IpAccessHost.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="IpAccessHostMsb">
+ <description>This MO represents the Ip Access Host used for payload. This host type executes on a MSB board (Media Stream Board used by Media Gateway).
+
+Note! If autoConfig is set to ON, the Ip Addresses and the Prefixes for this MO is set by the IpAccessAutoConfig MO.
+
+Note! There can be a maximum of 128 host's in the node.
+
+Note! The references to Aal5TpVccTp MO's has to be set in pairs.
+
+Note! The IpAccessMsbHost must execute on the sam MP as the Aal5TpVccTp that are defined in the attributes 'aal5TpVccTpRef1' and 'aal5TpVccTpRef2'.
+
+Note! The 'administrativeState' has to be set to LOCKED in order to be able to delete this host.</description>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the Ip Access Host.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>DEGRADED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of the Ip Access Host.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimer">
+ <description>The shut-down timer. It is used when the administrativeState is set to shutdown.
+
+Value in seconds, must be a positive value.</description>
+ <dataType>
+ <long>
+ <defaultValue>10</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="dspId">
+ <description>The identity of the DSP (Digital Signalling Processor) on a MSB board.
+
+Note! The value of this attribute has to be unique among the host's that execute on the same board.</description>
+ <mandatory/>
+ <noNotification/>
+ <nonPersistent/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="aal5TpVccTpRef1">
+ <description>Holds a reference to an Aal5 termination point (Aal5TpVccTp MO).
+
+Note! The Aal5TpVccTp references are mutually exclusive.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Aal5TpVccTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="aal5TpVccTpRef2">
+ <description>Holds a reference to an Aal5 termination point (Aal5TpVccTp MO).
+
+Note! The Aal5TpVccTp references are mutually exclusive.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Aal5TpVccTp"/>
+ </dataType>
+ </attribute>
+ <attribute name="autoConfig">
+ <description>This attribute specifies whether the auto configuration feature for the Ip Access Host is used or not.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="AutoConfigurationMode">
+ <defaultValue>OFF</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="autoConfigIdentity">
+ <description>The identity of the IpAccessAutoConfig MO used by this host.
+
+Note! This attribute can only be set if 'autoConfig' is set to 'ON'.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="IpAccessAutoConfig"/>
+ </dataType>
+ </attribute>
+ <attribute name="ipAddress">
+ <description>The IpAddress.
+
+Note! If autoConfig = OFF this attribute is mandatory.
+
+Note! If the autoConfiguration is used for this IpAccessHost (autoConfig = ON) this attribute cannot be set. This attribute is then set by the 'IpAccessAutoConfig MO'.
+
+Note! The IpAddress has to be unique within the node.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="networkPrefix">
+ <description>The network prefix.
+
+The prefix denotes how many bits that are used for calculating the subnet mask.
+
+Note! If auto configuration is used (autoConfig = ON) this attribute cannot be set, the networkPrefix is then set in the ipAccessAutoConfig MO class.
+
+Note! If auto configuration is not used (autoConfig = OFF) this attribute must be set.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>32</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="linkStatusAddress">
+ <description>The link Status for Ip Address.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="mtu">
+ <description>The maximum transfer unit.
+
+Note! in order to be able to set the value for this attribute, the administrative state has to be locked.
+
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>72</min> <max>2048</max>
+ </range>
+ <defaultValue>1024</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ipDefaultTtl">
+ <description>The default value inserted into the Time-To-Live field of the IP header of datagrams originated at this entity,
+whenever a TTL value is not supplied by the transport layer protocol.
+
+Note! in order to be able to set the value for this attribute, the administrative state has to be locked.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>255</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInReceives">
+ <description>The total number of input datagrams received from interfaces, including those received in error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInHdrErrors">
+ <description>The number of input datagrams discarded due to errors in their IP headers, including bad checksums, version number
+mismatch, other format errors, time-to-live exceeded, errors discovered in processing their IP options, etc.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInAddrErrors">
+ <description>The number of input datagrams discarded because the IP address in their IP header's destination field was not a
+valid address to be received at this entity. This count includes invalid addresses (e.g., 0.0.0.0) and addresses of
+unsupported Classes (e.g., Class E). For entities which are not IP routers and therefore do not forward datagrams,
+this counter includes datagrams discarded because the destination address was not a local address.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInUnknownProtos">
+ <description>The number of locally-addressed datagrams received successfully but discarded because of an unknown or
+unsupported protocol.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInDiscards">
+ <description>The number of input IP datagrams for which no problems were encountered to prevent their continued processing, but which
+were discarded (e.g., for lack of buffer space). Note that this counter does not include any datagrams discarded while
+awaiting re-assembly.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInDelivers">
+ <description>The total number of input datagrams successfully delivered to IP user-protocols (including ICMP).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpOutRequests">
+ <description>The total number of IP datagrams which local IP user-protocols (including ICMP) supplied to IP in requests for
+transmission. Note that this counter does not include any datagrams counted in ipForwDatagrams</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpOutDiscards">
+ <description>The number of output IP datagrams for which no problem was encountered to prevent their transmission to their
+destination, but which were discarded (e.g., for lack of buffer space). Note that this counter would include
+datagrams counted in ipForwDatagrams if any such packets met this (discretionary) discard criterion.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInMsgs">
+ <description>The total number of ICMP messages which the entity received.
+Note that this counter includes all those counted by icmpInErrors</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInErrors">
+ <description>The number of ICMP messages which the entity received but determined as having
+ICMP-specific errors (bad ICMP checksums, bad length, etc.).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInDestUnreachs">
+ <description>The number of ICMP Destination Unreachable messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInTimeExcds">
+ <description>The number of ICMP Time Exceeded messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInParamProbs">
+ <description>The number of ICMP Parameter Problem messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInSrcQuenchs">
+ <description>The number of ICMP Source Quench messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInRedirects">
+ <description>The number of ICMP Redirect messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInEchos">
+ <description>The number of ICMP Echo (request) messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInEchoReps">
+ <description>The number of ICMP Echo Reply messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutMsgs">
+ <description>The total number of ICMP messages which this entity attempted to send.
+Note that this counter includes all those counted by icmpOutErrors.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutErrors">
+ <description>The number of ICMP messages which this entity did not send due to problems discovered within ICMP such as a lack of
+buffers. This value should not include errors discovered outside the ICMP layer such as the inability of IP to route the
+resultant datagram. In some implementations there may be no types of error which contribute to this counter's value.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutDestUnreachs">
+ <description>The number of ICMP Destination Unreachable messages sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutParmProbs">
+ <description>The number of ICMP Parameter Problem messages sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutEchos">
+ <description>The number of ICMP Echo (request) messages sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutEchoReps">
+ <description>The number of ICMP Echo Reply messages sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUdpInDatagrams">
+ <description>The total number of UDP datagrams delivered to UDP users.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUdpNoPorts">
+ <description>The total number of received UDP datagrams for which there was no application at the destination port.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUdpInErrors">
+ <description>The number of received UDP datagrams that could not be delivered for
+reasons other than the lack of an application at the destination port.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUdpOutDatagrams">
+ <description>The total number of UDP datagrams sent from this entity.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="IpAccessHostMsbId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="plugInUnitId">
+ <description>Holds a reference to the PlugInUnit.
+
+Note that the 'plugInUnitId has to be the same as the one defined in the attribute 'processorId' found on the Aal5TpVccTpMo.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="PlugInUnit"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Aal2QosProfile">
+ <description>This MO represents the definitions of properties for a set of Aal2 quality of service classes.</description>
+ <attribute name="Aal2QosProfileId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="profileClassA">
+ <description>This attribute holds the values applicable for QoS Class A.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="QoSProfileClassA"/>
+ </dataType>
+ </attribute>
+ <attribute name="profileClassB">
+ <description>This attribute holds the values applicable for QoS Class B.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="QoSProfileClassB"/>
+ </dataType>
+ </attribute>
+ <attribute name="profileClassC">
+ <description>This attribute holds the values applicable for QoS Class C.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="QoSProfileClassC"/>
+ </dataType>
+ </attribute>
+ <attribute name="profileClassD">
+ <description>This attribute holds the values applicable for QoS Class D.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="QoSProfileClassD"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>List of reserving Aal2PathVccTp MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="Aal2PathVccTp"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Aal2QosCodePointProfile">
+ <description>This MO represents the QoS CodePoints for the different Aal2 QoS classes.</description>
+ <attribute name="Aal2QosCodePointProfileId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="qualityOfServiceCodePointA">
+ <description>The Code Point for Class A.
+
+Recommended value for Class A, 128.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="qualityOfServiceCodePointB">
+ <description>The Code Point for Class B.
+
+Recommended value for Class B, 129.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="qualityOfServiceCodePointC">
+ <description>The Code Point for Class C.
+
+Recommended value for Class C, 130.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="qualityOfServiceCodePointD">
+ <description>The Code Point for Class D.
+
+Recommended value for Class D, 131.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds the identity of the reserving Aal2Ap Mo.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="Aal2Ap"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="M3uAssociation">
+ <description>This MO represents the M3UA Association part of the M3UA (MTP3-User Adaptaion Layer) that is a protocol
+for the transport of any SS7 MTP3-User signalling (e.g., ISUP and SCCP messages) over IP using the services
+of the Stream Control Transmission Protocol.
+
+Note that the local port number is hard coded to 2905.
+
+
+</description>
+ <attribute name="M3uAssociationId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds a list of the reserving Signaling Route's (Mtp3bSr MO).
+</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="Mtp3bSr"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The Operational State of the M3Ua</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="mtp3bSrsId">
+ <description>The identity of the Signalling Route Set used.</description>
+ <mandatory/>
+ <noNotification/>
+ <nonPersistent/>
+ <restricted/>
+ <dataType>
+ <moRef name="Mtp3bSrs"/>
+ </dataType>
+ </attribute>
+ <attribute name="sctpId">
+ <description>The SctpHost used by this association.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Sctp"/>
+ </dataType>
+ </attribute>
+ <attribute name="dscp">
+ <description>The DSCP, DiffServCodePoint, for the internal M3UA user.
+Only one DSCP value is valid and set by the first defined MO 'instance'.
+
+NOTE: The value set for the 'dscp' when creating the first M3uAssociation under a signaling point will also be used for all other M3uAssociation MO's that are created under this signaling point. So setting the value for the 'dscp' on other instances than the first one created will have no effect. Note that associations created under a different signaling point can have a different dscp-value. </description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>63</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="associationState">
+ <description>The possible states of an M3Ua association.
+
+Bit 1 = 1 indicates INACTIVE
+Bit 2 = 1 indicates ACTIVE
+Bit 3 = 1 indicates ESTABLISHED
+Bit 4 = 1 indicates DOWN
+
+These values are mutually exclusive.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>15</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="localIpMask">
+ <description>This attribute denotes whether single or multi homing is used.
+
+Note! that all M3uAssociations that refers to the same SCTP MO must have this attribute set to the same value.
+
+Note! If localipMask=2 or localipMask=3 . the attribute ipAddress2 or autoConfigIdentity2 in IpAccessHostGpb MO must be defined.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="HomingState">
+ <defaultValue>SINGLE_HOMED_1</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="autoStartAssociation">
+ <description>If true, the M3ua layer in the stack will after a restart, start up all signalling associations.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="remotePortNumber">
+ <description>The port number of the remote signalling point (SP).</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>65535</max>
+ </range>
+ <defaultValue>2905</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="remoteIpAddress1">
+ <description>Remote IpAddress 1, if not used the value should be an empty string.
+Range is 0.0.0.0 - 255.255.255.255
+
+Note! This address is concidered as the primary IP-address. In case of association establisment failure 'remoteIpAddress2' will be used.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="remoteIpAddress2">
+ <description>Remote IpAddress 2, if not used the value should be an empty string.
+Range is 0.0.0.0 - 255.255.255.255
+
+Note! This address cannot be the same as remoteIpAddress1. This address is used when trying to establish association in case association attempt using 'remoteIpAddress1' fails.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCommunicationLost">
+ <description>Number of communication losses.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfCongestions">
+ <description>Number of congestions.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDunaRec">
+ <description>Number of DUNA messages received through the association.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDavaRec">
+ <description>Number of DAVA messages received through the association.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSconRec">
+ <description>Number of SCON messages received through the association.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDupuRec">
+ <description>Number of DUPU messages received through the association.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDataMsgSent">
+ <description>The number of data messages sent on the associations related to this signalling point.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDunaSent">
+ <description>Number of DUNA messages sent through the association.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDavaSent">
+ <description>Number of DAVA messages sent through the association.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfSconSent">
+ <description>Number of SCON messages sent through the association.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDupuSent">
+ <description>Number of DUPU messages sent through the association.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDataMsgRec">
+ <description>Number of DATA (payload data) messages received through the association.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfErrorMsgRec">
+ <description>Number of ERROR messages received through the association.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfErrorMsgSent">
+ <description>Number of ERROR messages sent through the association.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfNotifyMsgRec">
+ <description>Number of NOTIFY messages received through the association.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDaudMsgSent">
+ <description>The number of daud messages sent on the associations related to this signalling point.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfDaudMsgRec">
+ <description>The number of daud messages received on the associations related to this signalling point.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspupSent">
+ <description>The number of ASPUP sent.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspupReceived">
+ <description>The number of ASPUP received.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspdnSent">
+ <description>The number of ASPDN sent.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspdnReceived">
+ <description>The number of ASPDN received.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspacSent">
+ <description>The number of ASPAC sent.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspacReceived">
+ <description>The number of ASPAC received.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspiaSent">
+ <description>The number of ASPIA sent.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspiaReceived">
+ <description>The number of ASPIA received.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspupAckSent">
+ <description>The number of ASPUP_Ack sent.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspupAckReceived">
+ <description>The number of ASPUP_Ack received.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspdnAckSent">
+ <description>The number of ASPDN_Ack sent.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspdnAckReceived">
+ <description>The number of ASPDN_Ack received.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspacAckSent">
+ <description>The number of ASPAC_Ack sent.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspacAckReceived">
+ <description>The number of ASPAC_Ack received.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspiaAckSent">
+ <description>The number of ASPIA_Ack sent.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfAspiaAckReceived">
+ <description>The number of ASPIA_Ack received.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfM3uaDataMsgDiscarded">
+ <description>The number of data Messages discarded.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <action name="setAutoActivate">
+ <description>This action starts the association.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="setAutoDown">
+ <description>This action stops the association.
+
+Note! This action requires a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="Sctp">
+ <description>This MO represents the SCTP, Stream Control Transmission Protocol in Cello.
+SCTP is designed to transport signaling messages over IP networks.</description>
+ <attribute name="SctpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the Ip Access Host.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="numberOfAssociations">
+ <description>The maximum number of M3uAssociations that can be handled by this SCTP MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>512</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds a list of the M3Ua's handled by the SCTP.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="M3uAssociation"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="ipAccessHostGpbId">
+ <description>The identity of the IpAccessHostGbp reserved by this MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="IpAccessHostGpb"/>
+ </dataType>
+ </attribute>
+ <attribute name="minimumRto">
+ <description>The minimum value for RTO (Retransmission time-out).
+The minimumRto shall be larger than tSack + expected Round Trip Time.
+
+Unit is second/100.
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>4</min> <max>500</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maximumRto">
+ <description>The maximum value for RTO (Retransmission time-out).
+
+Unit is second/100.
+
+maximumRto must be larger than minimumRto.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>4</min> <max>180000</max>
+ </range>
+ <defaultValue>15</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="initialRto">
+ <description>The initial value that the RTO (Retransmission time-out) will take prior to the first RTT (Round Trip Time) measure.
+
+Note that the value for 'initialRto' has to be equal to or greater than 'minimumRto'.
+
+Unit is seconds/100.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>4</min> <max>180000</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="rtoAlphaIndex">
+ <description>This parameter is used for computing the value of the SRTT (Smoothed Round Trip Time) for a specific destination
+address. Is is used to weight the RTT values, and it's value must be between 0 and 1 (0 &lt; rtoAlpha &lt; 1). A value
+close to 1 gives a higher importance to the last RTT measurement.
+The range of possible values in the configuration file and the actual value given to this parameter within the module
+are the following:
+
+rtoAlphaIndex = 1 -&gt; RTO-Alpha = 1/2
+rtoAlphaIndex = 2 -&gt; RTO-Alpha = 1/4
+rtoAlphaIndex = 3 -&gt; RTO-Alpha = 1/8
+rtoAlphaIndex = 4 -&gt; RTO-Alpha = 1/16</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>4</max>
+ </range>
+ <defaultValue>3</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="rtoBetaIndex">
+ <description>This parameter is used for computing the the value of RTTVar (Round Trip Time Variation) of a destination
+address.
+It's value must be between 0 and 1 (0 &lt; rtoBetaIndex &lt; 1). A value close to 1 gives more importance to the
+last observed variation.
+The range of possible values in the configuration file and the actual value given to this parameter within the module
+are the following:
+
+rtoBetaIndex = 1 -&gt; RTO-Beta = 1/2
+rtoBetaIndex = 2 -&gt; RTO-Beta = 1/4
+rtoBetaIndex = 3 -&gt; RTO-Beta = 1/8
+rtoBetaIndex = 4 -&gt; RTO-Beta = 1/16
+</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>4</max>
+ </range>
+ <defaultValue>2</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="validCookieLife">
+ <description>This parameter sets up the lifespan of the State Cookie sent in the INIT_ACK chunk. It is used for limiting the
+the valid amount of time between sending the INIT_ACK and the reception of a COOKIE_ECHO chunk when
+establishing an association.
+If a COOKIE_ECHO chunk arrives after 'validCookieLife' has expired when sending an INIT_ACK chunk, the
+COOKIE_ECHO shall be discarded and no association will be established.
+
+Unit is seconds.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>180</max>
+ </range>
+ <defaultValue>60</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="allowedIncrementCookieLife">
+ <description>The sender of an INIT chunk may request to the remote endpoint a cookie life-span increase (for example, if a previous attempt to
+connect failed due to a state-cookie error). If the value sent in the "Cookie Preservative field" of the INIT chunk is less or equal to
+this parameter, the reciver of the INIT chunk will increase the 'validCookieLife' with the number of seconds specified. If the value
+present in the "Cookie Preservative field" is higher than this parameter, the cookie life should be incremented with the number of
+seconds specified by the parameter.
+
+Unit is seconds.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>180</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="keyChangePeriod">
+ <description>Defines how often the secret key used for computing the MAC (Message Authentication Code) on the State Cookie is changed.
+
+Unit is seconds.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>180</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="associationMaxRtx">
+ <description>This is the maximum number of consecutive retransmissions to a remote peer (on all the destination transport addresses of the peer, if it's multi homed). If the number of retransmissions becomes higher than this value, the remote peer shall be considered unreachable and the association shall be closed down.
+
+The value of this attribute should be greater than, or equal to the value of the attribute 'pathMaxRtx'.
+
+Note that for a specific association, it might happen that all the remote addresses (if the the remote end is multi homed) becomes unreachable without exceeding the 'associationMaxRtx'. In such a case the association will be closed down.
+
+Note! The value need to be increased to avoid frequent CommLost's in case of an unstable network.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>20</max>
+ </range>
+ <defaultValue>2</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pathMaxRtx">
+ <description>Maximum number of consecutive retransmissions to a remote transport address. If the number of retransmissions becomes higher than this value, the remote transport address shall be considered as "inactive" and no data shall be sent to it. If all of the remote transport addresses becomes "inactive", tha association will be closed down.
+
+Note! The value need to be increased to avoid frequent CommLost's in case of an unstable network.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>20</max>
+ </range>
+ <defaultValue>2</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxInitialRtrAtt">
+ <description>The maximum nimber of retransmissions allowed for both INIT and COOKIE_ECHO chunks. If the number of retransmissions
+exceeds this value, then the SCTP must abort the initialization of the association and report the error to the user.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16</max>
+ </range>
+ <defaultValue>8</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxShutDownRtrAtt">
+ <description>The maximum number of retransmission during the shutdown phase of an association.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="heartbeatInterval">
+ <description>The amount of time added to the RTO (Retransmission Time Out) of a specific address when setting up the period of
+time between sending heartbeats. Small values can lead to an earlier detection of unreachable addresses than higher
+values. Note that sendig often might lead to performace penalty.
+
+Unit is seconds.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>1800</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="heartbeatStatus">
+ <description>This attribute enables/disables heartbeats for associations.
+
+True = Enables</description>
+ <dataType>
+ <boolean>
+ <defaultValue>true</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="maxIncomingStream">
+ <description>This is the maximum incoming streams (MIS) for an association. Established associations might have an IS less or equal to
+this, but it's MIS can never be higher than the value of this attribute.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16384</max>
+ </range>
+ <defaultValue>17</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxOutgoingStream">
+ <description>The maximum number of outgonig streams for an association.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16384</max>
+ </range>
+ <defaultValue>17</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxUserDataSize">
+ <description>The maximum number of bytes a user is allowed to pass as a non fragmentable user data in a SCTP_SEND_REQ message
+(fixed user MTU):
+The values for this attribute is 'user' data and do not include IP header (20 bytes), SCTP header (12 bytes) or DATA chunk
+header (16 bytes).
+
+Unit is bytes.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>528</min> <max>65484</max>
+ </range>
+ <defaultValue>1432</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="mBuffer">
+ <description>This attribute sets the size of the buffer used for storing user data pending to be sent or retransmitted in an association. I.e. establish the maximum amount of user data that SCTP shall buffer before discarding user messages.
+
+The Unit is in kilo bytes.
+
+Note! The restriction on this attribute is:
+mBuffer x number of M3uAssociation MOs connected to this Sctp + 20 Mb &lt;= the heap for Sctp program.
+
+Note! The value may need to be increased to ensure stable dataflow at high load.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>2048</max>
+ </range>
+ <defaultValue>128</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="nThreshold">
+ <description>This attribute sets the value of the threshold used by SCTP to stop the delivery of data on anassociation.
+Once nThreshold or more bytes are queued and pending to be sent, the SCTP layer shall issue an indication to the user.
+The value of nThreshold should be less than mBuffer in order to be effective. A normal value for nThreshold is 3/4 * mBuffer.
+
+Unit is kilo bytes.
+
+Note! The value may need to be increased to ensure stable dataflow at high load.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>2048</max>
+ </range>
+ <defaultValue>96</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="tSack">
+ <description>The delay of sending the SACK. I.e. the time from DATA chunk reception to Sack chunk sending.
+
+Unit is second/100</description>
+ <dataType>
+ <long>
+ <range>
+ <min>2</min> <max>50</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxDataSizeIp">
+ <description>The maximum number of bytes SCTP shall be able to fetch every time it reads from the socket.
+
+Note! This value includes the Ip header, 20 bytes.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1500</min> <max>65535</max>
+ </range>
+ <defaultValue>8192</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="initialAdRecWin">
+ <description>The value of the initial advertised reciver window.
+
+Note! The range is 1500 to maxDataSizeIp.
+
+Unit is bytes.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1500</min> <max>65535</max>
+ </range>
+ <defaultValue>8192</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="intervalOobPkts">
+ <description>The number of seconds for the interval for which the counter for out of the blue chunks will be reset.
+
+Unit is seconds.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>6500</max>
+ </range>
+ <defaultValue>3600</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="intervalLostUser">
+ <description>The number of seconds for the interval for which the SCTP will decide that the SCTP user that lost the
+connection is dead. After the time specified in this attribute has elapsed, all associations related to the
+SCTP user will be destroyed.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>3600</max>
+ </range>
+ <defaultValue>5</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="maxBurst">
+ <description>The number of packages that will be sent during the fast retransmit phase when a SACK is processed.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>16384</max>
+ </range>
+ <defaultValue>4</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="nPercentage">
+ <description>The size of 'n' inpercentage when SCTP_CONGESTION_CEASE_IND is sent. At 100 percent the
+primitive will buffer usage goes below 'nThreshold'.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>100</max>
+ </range>
+ <defaultValue>85</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="bundlingActivated">
+ <description>This attribute enables/disables the use of bundling.
+Valid values:
+1: enabled.
+0: disabled.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>1</max>
+ </range>
+ <defaultValue>1</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="bundlingTimer">
+ <description>This attribute specifies maximum SCTP bundling delay.
+Value=0 means that SCTP will only bundle what is available and send directly (no delay).
+Unit is milliseconds</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>1000</max>
+ </range>
+ <defaultValue>10</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpCurrEstab">
+ <description>Number of SCTP associations for which the current state is either ESTABLISHED, SHUTDOWN-PENDING, or SHUTDOWN-RECEIVED.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpActiveEstab">
+ <description>Number of times that SCTP associations have made a direct transition to the ESTABLISHED state from the COOKIE-ECHOED state.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpPassiveEstab">
+ <description>Number of times that SCTP associations have made a direct transition to the ESTABLISHED state from the CLOSED state.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpAborted">
+ <description>Number of times that SCTP associations have made a direct transition to the CLOSED state from any state using the primitive ABORT.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpShutdowns">
+ <description>Number of times that SCTP associations have made a direct transition to the CLOSED state from either the SHUTDOWN-SENT state or the SHUTDOWN-ACK-SENT state.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatAssocOutOfBlue">
+ <description>Number of out of the blue packets (SCTP packet correctly formed-right checksum- but the receiver is not able to identify the association to which this packet belongs) received by the host.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatSentChunks">
+ <description>Number of complete data chunks sent to the peers (no retransmissions included).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatRecChunks">
+ <description>Number of complete data chunks received from the peers (no retransmissions included).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatOutOfOrderSendChunks">
+ <description>Number of unordered chunks sent to the peers.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatOutOfOrderRecChunks">
+ <description>Number of unordered chunks received from the peers.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatChecksumErrorCounter">
+ <description>Number of SCTP packets received from the peers with an invalid checksum.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatRetransChunks">
+ <description>Number of data chunks retransmitted to the peers.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatSentControlChunks">
+ <description>Number of datagrams sent with chunk type id &gt; 0.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatReceivedControlChunks">
+ <description>Number of datagrams Receivedwith chunk type id &gt; 0.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatFragmentedUserMsg">
+ <description>Number of fragmented user messages, incremented when the first data chunk of a fragmented message is sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatReassembledUserMsg">
+ <description>Number of reassembled user messages, incremented when the first data chunk of a fragmented message is received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatSentPackages">
+ <description>Number of SCTP packages sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatReceivedPackages">
+ <description>Number of SCTP packages Received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatCommStop">
+ <description>Number of times the SCTP has sent a communication stop indication to the user.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatCommResume">
+ <description>Number of times SCTP has sent a communication resume indication to the user.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatSentChunksDropped">
+ <description>Number of sent chunks that SCTP has been forced to drop due to buffer overflow in the sending buffer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSctpStatRecChunksDropped">
+ <description>Number of received chunks that SCTP has been forced to drop due to buffer overflow in the receiving buffer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Sts1SpeTtp">
+ <description>This MO represents the termination of the SONET higher order paths.
+This MO is automatically created when creating the OS155SPITTP with mux mode
+set to E1_J1_T1_LEVEL and standardmode set to ANSI.
+
+The performance monitoring counters in the Sts1SpeTtp MO is set to 0 (zero) at start or restart of the node.
+When the value is to large to fit in to a long (31bit) the counter turns over and starts from 0 again.</description>
+ <attribute name="Sts1SpeTtpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>enabled or disabled according to the actual operational state of the Sts3CspeTtp.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="aisPReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="rdiPReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="timConsequentAction">
+ <description>Trace Identifier Mismatch (TIM) consequent action, i.e. for generation of Alarm Indication Signal (AIS) downstream and Remote Defect Indication (RDI) upstream as a consequence of the TIM detection.
+
+True - enabled.
+False - disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="expectedPathTrace">
+ <description>Expected path trace.
+
+The string can be of 64 characters length, or empty string ("").
+
+Note: An empty string for this attribute means that the detection of Trace Identifier Mismatch (TIM) should be disabled. This attribute is set to empty string every time attribute pathTraceFormat is set.</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>64</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="transmittedPathTrace">
+ <description>The transmitted path trace.
+Can be defined in two formats. The format may be in 16 or 64 characters. Usually 16 is used for ETSI and 64 for ANSI/TTC.
+
+Note: The string must be of 15 or 62 characters length, or empty string ("").</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>64</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="pmEsp">
+ <description>Performance Monitoring counter for ES, Errored Seconds.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSesp">
+ <description>Performance Monitoring counter for Severely Errored Seconds, SES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Vt15Ttp">
+ <description>This MO is automatically created when the configuring the Os155SpiTtp. It represents the termination of the SONET VP 1.5 path layer.
+
+This MO is automatically created when creating the Os155SpiTtp MO with the following conditions:
+muxmode = E1_J1_T1_LEVEL
+standardmode = ANSI
+
+The performance monitoring counters in the Vt15Ttp is set to 0 (zero) at start or restart of the node.
+When the value is too large too fit in to a long (31bit) the counter turns over and starts from 0 again.
+</description>
+ <systemCreated/>
+ <attribute name="Vt15TtpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="aisVreporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="rdiVreporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimer">
+ <description>This timer defines the time that elapses before shut down when administrativeState is se to 'shuttingDown'.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>100000</max>
+ </range>
+ <defaultValue>1800</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the Vt15Ttp MO.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of the Vt15Ttp MO.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmEs">
+ <description>Performance monitoring counter of Errored Seconds (ES).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSes">
+ <description>Performance monitoring counter for Serverely Errored Seconds.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="T1Ttp">
+ <description>This MO represents a channelised T1 interface in the node. The T1Ttp MO does not define which type of traffic (TDM or ATM) that the interface should support. Please refer to the Ds0Bundle, AtmPort, IMALink and IMAGroup objects for details about configuration of traffic type.
+
+The performance monitoring counters in the T1Ttp MO is set to 0 (zero) at start or restart of the node.
+When the value is to large too fit in to a long (31bit) the counter turns over and starts from 0 again.
+
+Note! This MO is automatically created as a consequence of creating an Os155SpiTtpMo
+Please refer to the Os155SpiTtpMo for more details.</description>
+ <systemCreated/>
+ <attribute name="T1TtpId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="aisReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="rdiReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the T1Ttp MO.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmEs">
+ <description>Performance monitoring counter of Errored Seconds (ES).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSes">
+ <description>Performance monitoring counter for Serverely Errored Seconds.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving AtmPort MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByImaLink">
+ <description>The identity of the reserving ImaLink MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ImaLink"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="E3PhysPathTerm">
+ <description>This MO represents an E3 (i.e. 34 Mbit/s) physical interface in the node. Please refer to the AtmPort object for details about configuration of traffic type.
+
+Note! The performance monitoring counters in the E3PhysPathTerm MO is set to 0 (zero) at start or restart of the node.
+When the value is too large too fit in to a long (31bit) the counter turns over and starts from 0 again.</description>
+ <attribute name="E3PhysPathTermId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of the E3PhysPathTerm.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimeout">
+ <description>The shut-down timer. It is used when the administrativeState is set to shutdown.
+
+Value in seconds, must be a positive value.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100000</max>
+ </range>
+ <defaultValue>1800</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>enabled or disabled according to the actual operational state of the Physical Line Termination. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="lineNo">
+ <description>The actual Line number on the board.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>2</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="loopback">
+ <description>Possible values
+
+none - This is the normal state, no loop back is performed (and ordinary traffic is running).
+
+line - The physical path is looped on the line side, the external incoming path is looped back to the external outgoing path.
+
+system - The physical path is looped on the system side, the (node-) internal incoming path is looped back to the internal outgoing path.
+
+Note! administrativeStatus must be set to locked when setting loopback attribute.</description>
+ <dataType>
+ <enumRef name="LoopbackState">
+ <defaultValue>none</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="degDegThr">
+ <description>The threshold decides how many of the received blocks that are allowed to have bit errors. The measurement is made on a per-second basis and if the threshold is passed the second is considered bad.
+
+This is a percentage value.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100</max>
+ </range>
+ <defaultValue>30</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="degDegM">
+ <description>How many bad seconds in a row that causes a Degraded Signal alarm.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>2</min> <max>10</max>
+ </range>
+ <defaultValue>7</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="aisReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="rdiReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="pmEs">
+ <description>Performance Monitoring counter for ES, Errored Seconds.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSes">
+ <description>Performance Monitoring counter for Severely Errored Seconds, SES.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByTraffic">
+ <description>The identity of the reserving AtmPort MO. </description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBySync">
+ <description>The identity of the reserving Synchronization MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Synchronization"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="T3PhysPathTerm">
+ <description>This MO represents an T3 (i.e. 45 Mbit/s) physical interface in the node. Please refer to the AtmPort object for details about configuration of traffic type.
+
+Note! The performance monitoring counters in the T3PhysPathTerm MO is set to 0 (zero) at start or restart of the node.
+When the value is too large too fit in to a long (31bit) the counter turns over and starts from 0 again.</description>
+ <attribute name="T3PhysPathTermId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>enabled or disabled according to the actual operational state of the Physical Line Termination. </description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of the T3PhysPathTerm MO.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimeout">
+ <description>The shut-down timer. It is used when the administrativeState is set to shutdown.
+
+Value in seconds, must be a positive value.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>100000</max>
+ </range>
+ <defaultValue>1800</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="lineNo">
+ <description>The actual Line number on the board.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>2</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="loopback">
+ <description>Possible values
+
+none - This is the normal state, no loop back is performed (and ordinary traffic is running).
+
+line - The physical path is looped on the line side, the external incoming path is looped back to the external outgoing path.
+
+system - The physical path is looped on the system side, the (node-) internal incoming path is looped back to the internal outgoing path.
+
+Note! administrativeStatus must be set to locked when setting loopback attribute.</description>
+ <dataType>
+ <enumRef name="LoopbackState">
+ <defaultValue>none</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="aisReporting">
+ <description>Indicates whether Alarm Indication Signal, AIS, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="rdiReporting">
+ <description>Indicates whether Remote Defect Indication, RDI, alarms are to be issued.
+
+true - reporting enabled.
+false - reporting disabled.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="pmEsCpp">
+ <description>Performance Monitoring counter for ES, Errored Seconds based on C-bit parity.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmSesCpp">
+ <description>Performance Monitoring counter for Severely Errored Seconds, SES based on C-bit parity.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="reservedByTraffic">
+ <description>The identity of the reserving AtmPort MO. </description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="AtmPort"/>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBySync">
+ <description>The identity of the reserving Synchronization MO.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="Synchronization"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Etm3">
+ <description>This MO represents the hardware of the ET-M3 board type. It only represents the ET specific hardware, while the DBM module of the board is represented by the PlugInUnit MO.
+
+The ET-M3 board contains 2 physical ports that can be configured as either E3 (ETSI) or T3(ANSI).
+
+Each port on the ET-M3 board can be used to carry ATM traffic.
+
+At the VP/VC endpoints, the Lost FPM/BR cells counters are not available.
+
+IMA is not applicable for theETM3 board.
+
+The ET-M3 board supports eight bidirectional F4/F5 PM flow per port.
+
+The number of VCC TP+VPC TP with performance monitoring enabled (i.e. PM mode &lt;&gt; off) is restricted to 8/port.
+
+Each port can support up to 240 ATM VC connections. Sixteen of these connections are reserved for AAL2 paths, and therefore sixteen AAL2 multiplexers per port are available.
+
+Each port can support up to 16 VP connections. </description>
+ <attribute name="Etm3Id">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Enabled or disabled according to the actual operational state of the Etm3 board.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="SccpApRemote">
+ <description>This Managed Object represents an SCCP Remote Access Point. An SCCP AP instance is a logical point in the SCCP network at which an SCCP user can access the services provided by the SCCP and the SCCP can deliver its services to the SCCP user. The SCCP Remote Access Point is identified by a SubSystem Number (SSN).
+
+A remote SccpAp represents an access point in another node and is related to a Mtp3bAp MO.
+
+The performance monitoring counters found in SccpAp MO is reset, set to zero, when the object is created.
+These counters will not be reset again unless there is a shutdown request from the CLI (Cluster Interface).</description>
+ <attribute name="SccpApRemoteId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the SCCP AP. The operability of the SCCP AP is described by this attribute which has two possible values:
+
+Disabled: The SCCP AP is totally inoperable and unable to provide the service to the user (e.g. if the MTP-3b AP is not usable).
+
+Enabled: The SCCP AP is partly or fully operable and available for use.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>Holds a list of the reserving MOs.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <sequence>
+ <moRef name="ManagedObject"/>
+ </sequence>
+ </dataType>
+ </attribute>
+ <attribute name="mtp3bApId">
+ <description>The identity of the Mtp3bAp used by this MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="Mtp3bAp"/>
+ </dataType>
+ </attribute>
+ <attribute name="ssN">
+ <description>The sub system number, SSN, of the SCCP Access Point. Note that this has to be a unique number.
+
+The SSN has to be unique among all other SccpApRemote MOs that has the same DPC in their corresponding Mtp3bSrs MOs.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>2</min> <max>255</max>
+ </range>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="IpAccessHostGpb">
+ <description>This MO represents the Ip Access Host used for payload. This host type executes on a GPB board (GeneralPocessorUnit).
+
+Note! If autoConfig is set to ON, the Ip Addresses and the Prefixes for this MO is set by the IpAccessAutoConfig MO.
+
+Note! There can be a maximum of 128 host's in the node, and only one host on each main processor.
+
+Note! The host cannot be configured on a MP which have a MediumAccessUnit-child MO. They are exclusive.
+
+Note! The 'administrativeState' has to be set to LOCKED in order to be able to delete this host.</description>
+ <attribute name="IpAccessHostGpbId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="reservedBy">
+ <description>The identity of the reserving MO, can be of type Sctp.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>The operational state of the Ip Access Host.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>DEGRADED</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="administrativeState">
+ <description>The administrative state of the Ip Access Host.</description>
+ <dataType>
+ <enumRef name="AdmState">
+ <defaultValue>locked</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="shutDownTimer">
+ <description>The shut-down timer. It is used when the administrativeState is set to shutdown.
+
+Value in seconds, must be a positive value.</description>
+ <dataType>
+ <long>
+ <defaultValue>10</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="linkStatusAddress1">
+ <description>The link status for IpAddress1.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="linkStatusAddress2">
+ <description>The link status for IpAddress2, only valid if 2 IpAddresses are configured for this host.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="generalProcessorUnitId">
+ <description>Holds a reference to the GPU (GenerelProcessorUnit).</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="GeneralProcessorUnit"/>
+ </dataType>
+ </attribute>
+ <attribute name="autoConfig">
+ <description>This attribute specifies whether the auto configuration feature for the Ip AccessHost is used or not.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="AutoConfigurationMode">
+ <defaultValue>OFF</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="autoConfigIdentity">
+ <description>The identity of the IpAccessAutoConfig MO used by this host.
+
+Note! This attribute is mandatory if 'autoConfig' is set to ON.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="IpAccessAutoConfig"/>
+ </dataType>
+ </attribute>
+ <attribute name="autoConfigIdentity2">
+ <description>The identity of the IpAccessAutoConfig MO used by this host.
+
+Note! This attribute can only be set if 'autoConfig' is set to 'ON'. This attribute is not neccesary to set if 'autoConfig' is set to ON, unless the host shall have two Ip Addresses automatically assigned.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="IpAccessAutoConfig"/>
+ </dataType>
+ </attribute>
+ <attribute name="ipAddress">
+ <description>The IpAddress.
+
+Note! If autoConfig = OFF this attribute is mandatory.
+Note! If the autoConfiguration is used for this IpAccessHostGpb (autoConfig = ON) this attribute cannot be set. This attribute is then set by the 'IpAccessAutoConfig MO'.
+Note! If the attribute is set, its value must not be the same as for attribute ipAddress2.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="ipAddress2">
+ <description>The second IpAddress.
+
+Note! If autoConfig = OFF this attribute is possible to set. This attribute should only be set if multi-homing is used for this host (i.e. two addresses defined).
+Note! If the autoConfiguration is used for this IpAccessHostGpb (autoConfig = ON) this attribute cannot be set. This attribute is then set by the 'IpAccessAutoConfig MO'.
+Note! If the attribute is set, its value must not be the same as for attribute 'ipAddress'.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="pathMTUDiscovery">
+ <description>Specifies whether path MTU discovery should be used by this host.
+
+Note! in order to be able to set the value for this attribute, the administrative state has to be locked.</description>
+ <dataType>
+ <boolean>
+ <defaultValue>false</defaultValue>
+ </boolean>
+ </dataType>
+ </attribute>
+ <attribute name="mtu">
+ <description>The maximum transfer unit.
+
+The MTU has a initial value of 1452 if pathMTUDiscovery is set to false.
+If pathMTUDiscovery is set to true, the initial value of MTU is 1452.
+
+Note! in order to be able to set the value for this attribute, the administrative state has to be locked.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>72</min> <max>2048</max>
+ </range>
+ <defaultValue>1452</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ipDefaultTtl">
+ <description>The default value inserted into the Time-To-Live field of the IP header of datagrams originated at this entity,
+whenever a TTL value is not supplied by the transport layer protocol.
+
+Note! in order to be able to set the value for this attribute, the administrative state has to be locked.</description>
+ <dataType>
+ <long>
+ <range>
+ <min>1</min> <max>255</max>
+ </range>
+ <defaultValue>50</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="ipReasmTimeout">
+ <description>The maximum number of seconds which received fragments are
+held while they are awaiting reassembly at this entity.
+
+Note! in order to be able to set the value for this attribute, the administrative state has to be locked.
+
+Note! The value for this attribute has to be positive.</description>
+ <dataType>
+ <long>
+ <defaultValue>300</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="nextHopIpAddr">
+ <description>The next hop IP address.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="nextHopIpAddr2">
+ <description>The secondary next hop IP address.
+
+Note! This attribute must only be set if one of the following conditions are fulfilled:
+1. Attribute 'ipAddress2' is set.
+2. Attribute 'autoConfig' = 'ON' and attribute 'autoConfigIdentity2' is set.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="networkPrefix">
+ <description>The network prefix.
+
+The prefix denotes how many bits that are used for calculating the subnet mask.
+
+Note! The default value 0 (zero) is most likely not possible to use and an other value should be submitted if this attribute is configured manually.
+Note! If auto configuration is not used (autoConfig = OFF) this attribute must be set (i.e. this attribute is then 'mandatory').
+Note! If auto configuration is used (autoConfig = ON) this attribute cannot be set, networkPrefix is then set by the ipAccessAutoConfig MO class.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>32</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="networkPrefix2">
+ <description>The second network prefix.
+
+The prefix denotes how many bits that are used for calculating the subnet mask.
+
+Note! The default value 0 (zero) is most likely not possible to use and an other value should be submitted if this attribute is configured manually.
+Note! If auto configuration is not used (autoConfig = OFF) and ipAddress2 is set this attribute must be set (i.e. this attribute is then 'mandatory').
+Note! If auto configuration is used (autoConfig = ON) this attribute cannot be set, networkPrefix2 is then set by the ipAccessAutoConfig MO class. </description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>32</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInReceives">
+ <description>The total number of input datagrams received from interfaces, including those received in error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInHdrErrors">
+ <description>The number of input datagrams discarded due to errors in their IP headers, including bad checksums, version number
+mismatch, other format errors, time-to-live exceeded, errors discovered in processing their IP options, etc.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInAddrErrors">
+ <description>The number of input datagrams discarded because the IP address in their IP header's destination field was not a
+valid address to be received at this entity. This count includes invalid addresses (e.g., 0.0.0.0) and addresses of
+unsupported Classes (e.g., Class E). For entities which are not IP routers and therefore do not forward datagrams,
+this counter includes datagrams discarded because the destination address was not a local address.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInUnknownProtos">
+ <description>The number of locally-addressed datagrams received successfully but discarded because of an unknown or
+unsupported protocol.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInDiscards">
+ <description>The number of input IP datagrams for which no problems were encountered to prevent their continued processing, but which
+were discarded (e.g., for lack of buffer space). Note that this counter does not include any datagrams discarded while
+awaiting re-assembly.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpInDelivers">
+ <description>The total number of input datagrams successfully delivered to IP user-protocols (including ICMP).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpOutRequests">
+ <description>The total number of IP datagrams which local IP user-protocols (including ICMP) supplied to IP in requests for
+transmission. Note that this counter does not include any datagrams counted in ipForwDatagrams</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpOutDiscards">
+ <description>The number of output IP datagrams for which no problem was encountered to prevent their transmission to their
+destination, but which were discarded (e.g., for lack of buffer space). Note that this counter would include
+datagrams counted in ipForwDatagrams if any such packets met this (discretionary) discard criterion.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpReasmReqds">
+ <description>The number of IP fragments received which needed to be reassembled at this entity.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpReasmOKs">
+ <description>The number of IP datagrams successfully re-assembled.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpReasmFails">
+ <description>The number of failures detected by the IP re-assembly algorithm (for whatever reason: timed out, errors, etc).
+Note that this is not necessarily a count of discarded IP fragments since some algorithms (notably the algorithm
+in RFC 815) can lose track of the number of fragments by combining them as they are received.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpFragOKs">
+ <description>The number of IP datagrams that have been successfully fragmented at this entity.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpFragFails">
+ <description>The number of IP datagrams that have been discarded because they needed to be fragmented
+at this entity but could not be, e.g., because their Don't Fragment flag was set.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIpFragCreates">
+ <description>The number of IP datagram fragments that have been generated as a result of fragmentation at this entity.
+</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInMsgs">
+ <description>The total number of ICMP messages which the entityreceived.
+Note that this counter includes all those counted by icmpInErrors</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInErrors">
+ <description>The number of ICMP messages which the entity received but determined as having
+ICMP-specific errors (bad ICMP checksums, bad length, etc.).</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInDestUnreachs">
+ <description>The number of ICMP Destination Unreachable messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInTimeExcds">
+ <description>The number of ICMP Time Exceeded messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInParamProbs">
+ <description>The number of ICMP Parameter Problem messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInSrcQuenchs">
+ <description>The number of ICMP Source Quench messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInRedirects">
+ <description>The number of ICMP Redirect messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInEchos">
+ <description>The number of ICMP Echo (request) messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpInEchoReps">
+ <description>The number of ICMP Echo Reply messages received.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutMsgs">
+ <description>The total number of ICMP messages which this entity attempted to send.
+Note that this counter includes all those counted by icmpOutErrors.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutErrors">
+ <description>The number of ICMP messages which this entity did not send due to problems discovered within ICMP such as a lack of
+buffers. This value should not include errors discovered outside the ICMP layer such as the inability of IP to route the
+resultant datagram. In some implementations there may be no types of error which contribute to this counter's value.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutDestUnreachs">
+ <description>The number of ICMP Destination Unreachable messages sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutParmProbs">
+ <description>The number of ICMP Parameter Problem messages sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutEchos">
+ <description>The number of ICMP Echo (request) messages sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmIcmpOutEchoReps">
+ <description>The number of ICMP Echo Reply messages sent.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUdpInDatagrams">
+ <description>The total number of UDP datagrams delivered to UDP users.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUdpNoPorts">
+ <description>The total number of received UDP datagrams for which there was no application at the destination port.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUdpInErrors">
+ <description>The number of received UDP datagrams that could not be delivered for
+reasons other than the lack of an application at the destination port.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmUdpOutDatagrams">
+ <description>The total number of UDP datagrams sent from this entity.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInUcastPkts">
+ <description>Performance monitoring counter for the number of input unicast packets delivered to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfOutUcastPkts">
+ <description>Performance monitoring counter for the number of out unicast packets delivered to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInErrors">
+ <description>Performance monitoring counter for the number of input packets discarded due to any error.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInDiscards">
+ <description>Performance monitoring counter for the number of input packets discarded due to resource limitations.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInBroadcastPkts">
+ <description>Performance monitoring counter for the number of input broadcast packets delivered to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfInMulticastPkts">
+ <description>Performance monitoring counter for the number of input multicast packets delivered to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfOutBroadcastPkts">
+ <description>Performance monitoring counter for the number of output broadcast packets delivered to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfIfOutMulticastPkts">
+ <description>Performance monitoring counter for the number of output multicast packets delivered to higher layer.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="SystemFunctions">
+ <description>This MO structures the SystemFunctions of the managed element. It is created automatically and cannot be deleted.
+
+The local distinguished name of this MO is ManagedElement=1, SystemFunctions=1.</description>
+ <systemCreated/>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="SystemFunctionsId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Licensing">
+ <description>This MO represents the Licensing (Software Keys) functions in Cello.</description>
+ <systemCreated/>
+ <attribute name="LicensingId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="emergencyStateInfo">
+ <description>This attribute holds information about the emergency status and the time remaining in the current state.
+
+Note! If the node is in emergency state USE_DEGRADED, or the emergency state is USE_DISABLED, the the value of'time' is insignificant.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <structRef name="EmergencyInfo"/>
+ </dataType>
+ </attribute>
+ <attribute name="licenseFileUrl">
+ <description>This attribute returns the URL to the License Key File so it can be viewed with an XML capable web browser
+in case this is a licensed node.
+
+Note! In case the node is not licensed, an empty string will be returned.</description>
+ <noNotification/>
+ <readOnly/>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>256</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <action name="updateLicenseKeyFile">
+ <description>This action sends a request to the FTP/SFTP server to update the license key file.
+
+User Id for login to FTP/SFTP server where license key files are located.
+If a null string userId is given, anonymous FTP/SFTP transfer is assumed.
+Max length is 20 characters.
+
+Password for login to the FTP/SFTP server where license key files are located.
+Max length is 20 characters.
+
+The IpAddress of the FTP/SFTP server where license key files are located.
+Max length is 16 characters.
+
+Source name and path of the license key file on the FTP/SFTP server.
+Max length is 256 charcters.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="userId">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="password">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="ipAddress">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ <parameter name="sFile">
+ <in/>
+ <dataType>
+ <string/>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="setEmergencyState">
+ <description>This action sets the license server into emergency state.
+I.e. opens up all licensed features and capacity restrictions.
+Disabling emergency state is done by loading a new license key file.
+
+Note! This action does not require a transaction.</description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ </class>
+
+ <class name="TimingUnit2">
+ <description>This MO represents a timing unit2 (reference clock) in the node.
+
+The corresponding Program shall be of LoadModuleLoaderType, SpmFpgaLoader.</description>
+ <attribute name="userLabel">
+ <description>Label for free use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Operational state of TimingUnit</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatus">
+ <description>The availability status of the TimingUnit.
+
+The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="TimingUnit2Id">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="SccpPolicing">
+ <description>The SccpPolicing MO represents the policing function in CPP.
+
+The originatingMtp3bSpc is a madatory attribute for policing in one local node (i.e. a SRP in one NI).
+For policing between two local nodes (i.e. a SRP between two NIs) the originatingMtp3bSpc can be replaced by the originatingSccpSpId.
+Optional attributes for policing in one local node (i.e a SRP in one NI) are destinationMtp3bSpc, destinationSccpSsn, originatingSccpSsn and policingGlobalTitle.
+For policing between two local nodes (i.e. a SRP between two NIs) the destinationMtp3bSpc can be replaced by the destinationSccpSpId.</description>
+ <attribute name="SccpPolicingId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="originatingMtp3bSpc">
+ <description>The value of the SPC (Signaling Point Code).
+
+Note! If the 'originatingSccpSpId' is specified the 'originatingMtp3bSpc' is invalid.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>16777215</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="destinationMtp3bSpc">
+ <description>The value of the destination SPC (Signaling Point Code).
+
+Note! The default value 0 (zero) means that no SPC is defined.
+Note! If no 'destinationSccpSp' is defined and the value of 'destinationMtp3bSpc' is set to 0 (zero), all Signalling Point Codes (SPC) are valid.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>16777215</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="originatingSccpSpId">
+ <description>The identity of the originating SccpSp MO must be used for policing between local nodes.
+
+Note! If the 'originatingSccpSpId' is specified the 'originatingMtp3bSpc' is invalid.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="originatingSccpSsn">
+ <description>The value of SSN in CgPA (Calling Party Address)
+
+Note! The value 0 (zero) means that all ssN (Sub System Number) are valid.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="destinationSccpSpId">
+ <description>The identity of the destination SccpSp MO can be used for policing between local nodes.
+
+Note! If the 'destinationSccpSpId' is specified the 'destinationMtp3bSpc' is invalid.
+Note! If no destination 'destinationSccpSp' is defined and the value of 'destinationMtp3bSpc' is set to 0, all local nodes are valid.
+</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="destinationSccpSsn">
+ <description>The value of SSN inCdPA (Called Party Address).
+
+Note! The valu 0 (zero) means tha all ssN (Sub System Number) are valid.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="policingGlobalTitle">
+ <description>The Policing Global Title attribute allows to optionally police on Global Title
+
+Default value is considered as no policing Global Title and all GTs are valid.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <structRef name="GlobalTitleData"/>
+ </dataType>
+ </attribute>
+ <attribute name="discardOrReturnServiceMsg">
+ <description>For a policing case whether to discard or return Service Messages, if the return option is set.</description>
+ <dataType>
+ <enumRef name="DiscardReturnServiceMsg">
+ <defaultValue>DISCARD</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfRejectMsg">
+ <description>Performance monitoring counter for the number of rejected messages.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="SccpAccountingCriteria">
+ <description>The SccpAccountingCriteria MO and the SccpSp MO represents the accounting function in CPP.
+
+Attribute usageType specifies Accounting Remuneration (incoming GT messages) or Verification (outgoing GT messages).
+
+For Remuneration a SccpGlobalTitle MOId in attribute globalTitleId must be defined.
+For Verification a SccpGlobalTitle MOid is defined in attribute globalTitleId, or a SccpEntitySet MOid is defined if accounting shall be made on the resulting new GT.
+
+The attribute ssN is optional .
+The Mtp3bSrs MOid (including an SPC) in attribute pointerId is optional for accounting in one local node (SRP in one NI).
+The SccpSp MOid in attribute pointerId is optional for accounting between two local nodes (SRP between two NIs).
+Attribute countType specifies if Messages och Octets shall be counted.
+Start and stop of accounting and output period for the accounting file is specified in the SccpSp MO.</description>
+ <attribute name="SccpAccountingCriteriaId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Label free for use.</description>
+ <dataType>
+ <string>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="usageType">
+ <description>This attribute specifies if the MO is used for renumeration or verification.
+
+0 = Verification Criteria to detect outgoing massages that will be charged in the next relay node.
+
+1 = Renumeration Criteria to detect incoming messages for relaying, that will be charged.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long/>
+ </dataType>
+ </attribute>
+ <attribute name="ssN">
+ <description>Subsystem Number this Accounting Criteria applies to.
+SubSystem Number 0 (zero) means that any SSN in CdPA (Called Party Address) is valid.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <long>
+ <range>
+ <min>0</min> <max>255</max>
+ </range>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="countType">
+ <description>Specifies type of countes that should be activated.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <enumRef name="SccpCountType">
+ <defaultValue>MESSAGES</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="globalTitleId">
+ <description>The identity of the SccpGlobalTitle MO or the SccpEntitySet MO used by this MO.</description>
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfMsg">
+ <description>Performance monitoring counter for the number of messages, both incoming and outgoing.
+
+Note! If 'countType' is set to 'OCTETS' this counter is not valid.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pmNoOfOctets">
+ <description>Performance monitoring counter for the number of octets, both incoming and outgoing.
+
+Note! If 'countType' is set to 'MESSAGES this counter is not valid.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <long>
+ <defaultValue>0</defaultValue>
+ </long>
+ </dataType>
+ </attribute>
+ <attribute name="pointerId">
+ <description>The pointer is an instance of a Mtp3bSrs MO OR an instance of a SccpSP MO.
+
+Note! If no pointerId is set all Signaling Point Codes (SPC) and all Sccp SP identities are valid.
+Note! It is not possible to submit the Id of the SccpSp that the SccpAccountingCriteria belongs to.</description>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <moRef name="ManagedObject"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="Cbu">
+ <description>This MO models the Cbu (Node Control Board) board in CPP.
+The Cbu board integrates the functionality of TUB, SCB, GPB and ETB (ET-MC1) into one Plug-In Unit.
+
+Note! The 'operationalState' is set to disabled if one of the functional parts is faulty. Even if the Cbu is marked with 'operationalState' DISABLED, parts of the Cbu can still be operational.
+
+Note! A functional part on a Cbu board can only be redundant with the same functional part on another Cbu board and thus not with that functional part implemented on a discrete board. Also note that redundancy is only applicable for the GPB part and the TimingUnit part of the Cbu board..
+
+Note! On the Cbu board it is only possible to configure a maximum of 4 physical path terminations. These can be of type E1PhysPathTerm, J1PhyspathTerm or T1PhyspathTerm. It is not possible to create physical path terminations of different standards on the same board.
+
+Note! The Gpu part of the Cbu board (General Processor Unit) retrieves its 'availabilityStatus' from the PlugInUnit MO, thus not represented on the Cbu MO.
+
+Note! When the ET-MC1 is part of the Cbu board it is only possible to configure 4 physical ports as either E1 (ETSI), J1 (TTC) or T1 (ANSI).
+
+Note! This unit may only be inserted in slot 1 and 24 (or more accurately at APN=1 and 0 in a non-standard subrack). If redundant configuration is needed, two Cbu's must be inserted in the subrack.
+If only one Cbu is used it must be placed in slot 1 (in a non-standard subrack) to be able to read the product information data of the subrack</description>
+ <attribute name="CbuId">
+ <mandatory/>
+ <noNotification/>
+ <restricted/>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="userLabel">
+ <description>Provides the possibility to put a user-friendly label on the MO instance.
+
+Note! This attribute cannot be used for uniquely identifing the MO.</description>
+ <dataType>
+ <string>
+ <lengthRange>
+ <min>0</min> <max>128</max>
+ </lengthRange>
+ <defaultValue>""</defaultValue>
+ </string>
+ </dataType>
+ </attribute>
+ <attribute name="operationalState">
+ <description>Enabled or disabled according to the actual operational state of the NCB board.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="OperState">
+ <defaultValue>disabled</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusEt">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.
+The 'availabilityStatusEt' gives the availability status for the ET part of the NCB board.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ <attribute name="availabilityStatusTu">
+ <description>The availability status is used to qualify the operational state. It indicates why the operational state has changed its value to disabled.
+The 'availabilityStatusTu' gives the availability status for the Timing Unit part of the NCB board.</description>
+ <noNotification/>
+ <nonPersistent/>
+ <readOnly/>
+ <dataType>
+ <enumRef name="AvailabilityStatus">
+ <defaultValue>NO_STATUS</defaultValue>
+ </enumRef>
+ </dataType>
+ </attribute>
+ </class>
+
+ <relationship name="ManagedElement_to_TransportNetwork">
+ <containment>
+ <parent>
+ <hasClass name="ManagedElement"/>
+ </parent>
+ <child>
+ <hasClass name="TransportNetwork"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Synchronization">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Synchronization"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_SccpSp">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="SccpSp"/>
+ <cardinality>
+ <min>0</min> <max>24</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_UniSaalProfile">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="UniSaalProfile"/>
+ <cardinality>
+ <min>0</min> <max>300</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_UniSaalTp">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="UniSaalTp"/>
+ <cardinality>
+ <min>0</min> <max>4800</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Aal0TpVccTp">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Aal0TpVccTp"/>
+ <cardinality>
+ <min>0</min> <max>2200</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Aal5TpVccTp">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Aal5TpVccTp"/>
+ <cardinality>
+ <min>0</min> <max>6000</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_AtmPort">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="AtmPort"/>
+ <cardinality>
+ <min>0</min> <max>500</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_NniSaalProfile">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="NniSaalProfile"/>
+ <cardinality>
+ <min>0</min> <max>50</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_NniSaalTp">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="NniSaalTp"/>
+ <cardinality>
+ <min>0</min> <max>600</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_AtmTrafficDescriptor">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="AtmTrafficDescriptor"/>
+ <cardinality>
+ <min>0</min> <max>1000</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Aal2PathVccTp">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Aal2PathVccTp"/>
+ <cardinality>
+ <min>0</min> <max>2000</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Aal2RoutingCase">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Aal2RoutingCase"/>
+ <cardinality>
+ <min>0</min> <max>900</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Aal2Sp">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Aal2Sp"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_AtmCrossConnection">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="AtmCrossConnection"/>
+ <cardinality>
+ <min>0</min> <max>5000</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp2TpItu">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp2TpItu"/>
+ <cardinality>
+ <min>0</min> <max>256</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp2TpAnsi">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp2TpAnsi"/>
+ <cardinality>
+ <min>0</min> <max>256</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Aal1TpVccTp">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Aal1TpVccTp"/>
+ <cardinality>
+ <min>0</min> <max>1000</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp3bSpAnsi">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSpAnsi"/>
+ <cardinality>
+ <min>0</min> <max>24</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp3bSpItu">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSpItu"/>
+ <cardinality>
+ <min>0</min> <max>24</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp3bSpTtc">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSpTtc"/>
+ <cardinality>
+ <min>0</min> <max>24</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp2ProfileAnsi">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp2ProfileAnsi"/>
+ <cardinality>
+ <min>0</min> <max>256</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp2ProfileItu">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp2ProfileItu"/>
+ <cardinality>
+ <min>0</min> <max>256</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp2ProfileChina">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp2ProfileChina"/>
+ <cardinality>
+ <min>0</min> <max>256</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp2TpChina">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp2TpChina"/>
+ <cardinality>
+ <min>0</min> <max>256</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mtp3bSpChina">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSpChina"/>
+ <cardinality>
+ <min>0</min> <max>24</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Mspg">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Mspg"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_ImaGroup">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="ImaGroup"/>
+ <cardinality>
+ <min>0</min> <max>200</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Aal2QosProfile">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Aal2QosProfile"/>
+ <cardinality>
+ <min>0</min> <max>20</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Aal2QosCodePointProfile">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Aal2QosCodePointProfile"/>
+ <cardinality>
+ <min>0</min> <max>20</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TransportNetwork_to_Sctp">
+ <containment>
+ <parent>
+ <hasClass name="TransportNetwork"/>
+ </parent>
+ <child>
+ <hasClass name="Sctp"/>
+ <cardinality>
+ <min>0</min> <max>10</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Subrack_to_Slot">
+ <containment>
+ <parent>
+ <hasClass name="Subrack"/>
+ </parent>
+ <child>
+ <hasClass name="Slot"/>
+ <cardinality>
+ <min>1</min> <max>28</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Slot_to_PlugInUnit">
+ <containment>
+ <parent>
+ <hasClass name="Slot"/>
+ </parent>
+ <child>
+ <hasClass name="PlugInUnit"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Slot_to_ManagedObject">
+ <containment>
+ <parent>
+ <hasClass name="Slot"/>
+ </parent>
+ <child>
+ <hasClass name="ManagedObject"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="ManagedElement_to_ManagedObject">
+ <containment>
+ <parent>
+ <hasClass name="ManagedElement"/>
+ </parent>
+ <child>
+ <hasClass name="ManagedObject"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_ManagedObject">
+ <description>This containment relation indicated that any kind of board may be used to specilize PlugInUnit.</description>
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="ManagedObject"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Subrack_to_ManagedObject">
+ <containment>
+ <parent>
+ <hasClass name="Subrack"/>
+ </parent>
+ <child>
+ <hasClass name="ManagedObject"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="VpcTp_to_VclTp">
+ <containment>
+ <parent>
+ <hasClass name="VpcTp"/>
+ </parent>
+ <child>
+ <hasClass name="VclTp"/>
+ <cardinality>
+ <min>0</min> <max>5000</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="ManagedElement_to_Equipment">
+ <containment>
+ <parent>
+ <hasClass name="ManagedElement"/>
+ </parent>
+ <child>
+ <hasClass name="Equipment"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="ManagedElement_to_IpSystem">
+ <containment>
+ <parent>
+ <hasClass name="ManagedElement"/>
+ </parent>
+ <child>
+ <hasClass name="IpSystem"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="ManagedElement_to_SwManagement">
+ <containment>
+ <parent>
+ <hasClass name="ManagedElement"/>
+ </parent>
+ <child>
+ <hasClass name="SwManagement"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="ManagedElement_to_SwitchFabric">
+ <containment>
+ <parent>
+ <hasClass name="ManagedElement"/>
+ </parent>
+ <child>
+ <hasClass name="SwitchFabric"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="ManagedElement_to_ManagedElementData">
+ <containment>
+ <parent>
+ <hasClass name="ManagedElement"/>
+ </parent>
+ <child>
+ <hasClass name="ManagedElementData"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="ManagedElement_to_SystemFunctions">
+ <containment>
+ <parent>
+ <hasClass name="ManagedElement"/>
+ </parent>
+ <child>
+ <hasClass name="SystemFunctions"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Equipment_to_Subrack">
+ <containment>
+ <parent>
+ <hasClass name="Equipment"/>
+ </parent>
+ <child>
+ <hasClass name="Subrack"/>
+ <cardinality>
+ <min>0</min> <max>9</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Equipment_to_Jvm">
+ <containment>
+ <parent>
+ <hasClass name="Equipment"/>
+ </parent>
+ <child>
+ <hasClass name="Jvm"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Subrack_to_Fan">
+ <containment>
+ <parent>
+ <hasClass name="Subrack"/>
+ </parent>
+ <child>
+ <hasClass name="Fan"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SwManagement_to_LoadModule">
+ <containment>
+ <parent>
+ <hasClass name="SwManagement"/>
+ </parent>
+ <child>
+ <hasClass name="LoadModule"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SccpScrc_to_SccpApLocal">
+ <description>The SccpApLocal represents a local SSN, no relation exists to an Mtp3bAp
+
+Of the possible 216 SccpAps allowed on a node, a maximum of 16 are allowed to be local, and a maximum of 200 are allowed to be remote.</description>
+ <containment>
+ <parent>
+ <hasClass name="SccpScrc"/>
+ </parent>
+ <child>
+ <hasClass name="SccpApLocal"/>
+ <cardinality>
+ <min>0</min> <max>16</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SccpSp_to_SccpScrc">
+ <containment>
+ <parent>
+ <hasClass name="SccpSp"/>
+ </parent>
+ <child>
+ <hasClass name="SccpScrc"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SccpScrc_to_SccpEntitySet">
+ <containment>
+ <parent>
+ <hasClass name="SccpScrc"/>
+ </parent>
+ <child>
+ <hasClass name="SccpEntitySet"/>
+ <cardinality>
+ <min>0</min> <max>2048</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SccpScrc_to_SccpGlobalTitle">
+ <containment>
+ <parent>
+ <hasClass name="SccpScrc"/>
+ </parent>
+ <child>
+ <hasClass name="SccpGlobalTitle"/>
+ <cardinality>
+ <min>0</min> <max>2048</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SccpScrc_to_SccpApRemote">
+ <containment>
+ <parent>
+ <hasClass name="SccpScrc"/>
+ </parent>
+ <child>
+ <hasClass name="SccpApRemote"/>
+ <cardinality>
+ <min>0</min> <max>200</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SccpScrc_to_SccpPolicing">
+ <containment>
+ <parent>
+ <hasClass name="SccpScrc"/>
+ </parent>
+ <child>
+ <hasClass name="SccpPolicing"/>
+ <cardinality>
+ <min>0</min> <max>1024</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SccpScrc_to_SccpAccountingCriteria">
+ <containment>
+ <parent>
+ <hasClass name="SccpScrc"/>
+ </parent>
+ <child>
+ <hasClass name="SccpAccountingCriteria"/>
+ <cardinality>
+ <min>0</min> <max>100</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Spm_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="Spm"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TimingUnit_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="TimingUnit"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etm4_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="Etm4"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etm1_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="Etm1"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etmc1_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="Etmc1"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etmc41_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="Etmc41"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TimingUnit2_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="TimingUnit2"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etm3_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="Etm3"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Spu_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="Spu"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Fan_to_Program">
+ <containment>
+ <parent>
+ <hasClass name="Fan"/>
+ </parent>
+ <child>
+ <hasClass name="Program"/>
+ <cardinality>
+ <min>1</min> <max>2</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etm1_to_E1PhysPathTerm">
+ <containment>
+ <parent>
+ <hasClass name="Etm1"/>
+ </parent>
+ <child>
+ <hasClass name="E1PhysPathTerm"/>
+ <cardinality>
+ <min>0</min> <max>8</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etmc1_to_E1PhysPathTerm">
+ <containment>
+ <parent>
+ <hasClass name="Etmc1"/>
+ </parent>
+ <child>
+ <hasClass name="E1PhysPathTerm"/>
+ <cardinality>
+ <min>0</min> <max>8</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="E1PhysPathTerm_to_Ds0Bundle">
+ <containment>
+ <parent>
+ <hasClass name="E1PhysPathTerm"/>
+ </parent>
+ <child>
+ <hasClass name="Ds0Bundle"/>
+ <cardinality>
+ <min>0</min> <max>31</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etm1_to_J1PhysPathTerm">
+ <containment>
+ <parent>
+ <hasClass name="Etm1"/>
+ </parent>
+ <child>
+ <hasClass name="J1PhysPathTerm"/>
+ <cardinality>
+ <min>0</min> <max>8</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etmc1_to_J1PhysPathTerm">
+ <containment>
+ <parent>
+ <hasClass name="Etmc1"/>
+ </parent>
+ <child>
+ <hasClass name="J1PhysPathTerm"/>
+ <cardinality>
+ <min>0</min> <max>8</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="J1PhysPathTerm_to_Ds0Bundle">
+ <containment>
+ <parent>
+ <hasClass name="J1PhysPathTerm"/>
+ </parent>
+ <child>
+ <hasClass name="Ds0Bundle"/>
+ <cardinality>
+ <min>0</min> <max>24</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="AtmPort_to_VplTp">
+ <containment>
+ <parent>
+ <hasClass name="AtmPort"/>
+ </parent>
+ <child>
+ <hasClass name="VplTp"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpChina_to_Mtp3bAp">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpChina"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bAp"/>
+ <cardinality>
+ <min>0</min> <max>510</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpAnsi_to_Mtp3bAp">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpAnsi"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bAp"/>
+ <cardinality>
+ <min>0</min> <max>510</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpItu_to_Mtp3bAp">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpItu"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bAp"/>
+ <cardinality>
+ <min>0</min> <max>510</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpTtc_to_Mtp3bAp">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpTtc"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bAp"/>
+ <cardinality>
+ <min>0</min> <max>510</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpItu_to_Mtp3bSrs">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpItu"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSrs"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpTtc_to_Mtp3bSrs">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpTtc"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSrs"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpChina_to_Mtp3bSrs">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpChina"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSrs"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSrs_to_Mtp3bSr">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSrs"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSr"/>
+ <cardinality>
+ <min>0</min> <max>5</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpAnsi_to_Mtp3bSrs">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpAnsi"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSrs"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_Etm1">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="Etm1"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_Spu">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="Spu"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_SwitchCoreUnit">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="SwitchCoreUnit"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_GeneralProcessorUnit">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="GeneralProcessorUnit"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_Etm4">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="Etm4"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_TimingUnit">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="TimingUnit"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_SwitchExtensionUnit">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="SwitchExtensionUnit"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_Etmc1">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="Etmc1"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_Etmc41">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="Etmc41"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_Etm3">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="Etm3"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_TimingUnit2">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="TimingUnit2"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="PlugInUnit_to_Cbu">
+ <containment>
+ <parent>
+ <hasClass name="PlugInUnit"/>
+ </parent>
+ <child>
+ <hasClass name="Cbu"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpChina_to_Mtp3bSls">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpChina"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSls"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpItu_to_Mtp3bSls">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpItu"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSls"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpTtc_to_Mtp3bSls">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpTtc"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSls"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpAnsi_to_Mtp3bSls">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpAnsi"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSls"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpChina_to_Mtp3bSls_0">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpChina"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSls"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpAnsi_to_Mtp3bSls_0">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpAnsi"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSls"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpItu_to_Mtp3bSls_0">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpItu"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSls"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpTtc_to_Mtp3bSls_0">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpTtc"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSls"/>
+ <cardinality>
+ <min>0</min> <max>255</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSls_to_Mtp3bSlAnsi">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSls"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSlAnsi"/>
+ <cardinality>
+ <min>0</min> <max>16</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSls_to_Mtp3bSlItu">
+ <description>Multiplicity: 0..16</description>
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSls"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSlItu"/>
+ <cardinality>
+ <min>0</min> <max>16</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSls_to_Mtp3bSlTtc">
+ <description>Multiplicity: 0..16</description>
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSls"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSlTtc"/>
+ <cardinality>
+ <min>0</min> <max>16</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSls_to_Mtp3bSlChina">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSls"/>
+ </parent>
+ <child>
+ <hasClass name="Mtp3bSlChina"/>
+ <cardinality>
+ <min>0</min> <max>16</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="IpSystem_to_Ip">
+ <containment>
+ <parent>
+ <hasClass name="IpSystem"/>
+ </parent>
+ <child>
+ <hasClass name="Ip"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="IpSystem_to_Ospf">
+ <containment>
+ <parent>
+ <hasClass name="IpSystem"/>
+ </parent>
+ <child>
+ <hasClass name="Ospf"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="IpSystem_to_IpAccessAutoConfig">
+ <containment>
+ <parent>
+ <hasClass name="IpSystem"/>
+ </parent>
+ <child>
+ <hasClass name="IpAccessAutoConfig"/>
+ <cardinality>
+ <min>0</min> <max>32</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="IpSystem_to_IpAccessHostMsb">
+ <containment>
+ <parent>
+ <hasClass name="IpSystem"/>
+ </parent>
+ <child>
+ <hasClass name="IpAccessHostMsb"/>
+ <cardinality>
+ <min>0</min> <max>128</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="IpSystem_to_IpAccessHostGpb">
+ <containment>
+ <parent>
+ <hasClass name="IpSystem"/>
+ </parent>
+ <child>
+ <hasClass name="IpAccessHostGpb"/>
+ <cardinality>
+ <min>0</min> <max>128</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Ip_to_IpAtmLink">
+ <containment>
+ <parent>
+ <hasClass name="Ip"/>
+ </parent>
+ <child>
+ <hasClass name="IpAtmLink"/>
+ <cardinality>
+ <min>0</min> <max>500</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Ip_to_EthernetLink">
+ <containment>
+ <parent>
+ <hasClass name="Ip"/>
+ </parent>
+ <child>
+ <hasClass name="EthernetLink"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Ip_to_IpRoutingTable">
+ <containment>
+ <parent>
+ <hasClass name="Ip"/>
+ </parent>
+ <child>
+ <hasClass name="IpRoutingTable"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Aal2Sp_to_Aal2Ap">
+ <containment>
+ <parent>
+ <hasClass name="Aal2Sp"/>
+ </parent>
+ <child>
+ <hasClass name="Aal2Ap"/>
+ <cardinality>
+ <min>0</min> <max>850</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Aal2Ap_to_Aal2PathDistributionUnit">
+ <containment>
+ <parent>
+ <hasClass name="Aal2Ap"/>
+ </parent>
+ <child>
+ <hasClass name="Aal2PathDistributionUnit"/>
+ <cardinality>
+ <min>0</min> <max>26</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etm1_to_T1PhysPathTerm">
+ <containment>
+ <parent>
+ <hasClass name="Etm1"/>
+ </parent>
+ <child>
+ <hasClass name="T1PhysPathTerm"/>
+ <cardinality>
+ <min>0</min> <max>8</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TimingUnit_to_TuSyncRef">
+ <containment>
+ <parent>
+ <hasClass name="TimingUnit"/>
+ </parent>
+ <child>
+ <hasClass name="TuSyncRef"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="TimingUnit2_to_TuSyncRef">
+ <containment>
+ <parent>
+ <hasClass name="TimingUnit2"/>
+ </parent>
+ <child>
+ <hasClass name="TuSyncRef"/>
+ <cardinality>
+ <min>0</min> <max>2</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Spu_to_Spm">
+ <containment>
+ <parent>
+ <hasClass name="Spu"/>
+ </parent>
+ <child>
+ <hasClass name="Spm"/>
+ <cardinality>
+ <min>0</min> <max>5</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SwManagement_to_ConfigurationVersion">
+ <containment>
+ <parent>
+ <hasClass name="SwManagement"/>
+ </parent>
+ <child>
+ <hasClass name="ConfigurationVersion"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SwManagement_to_UpgradePackage">
+ <containment>
+ <parent>
+ <hasClass name="SwManagement"/>
+ </parent>
+ <child>
+ <hasClass name="UpgradePackage"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SwManagement_to_Repertoire">
+ <containment>
+ <parent>
+ <hasClass name="SwManagement"/>
+ </parent>
+ <child>
+ <hasClass name="Repertoire"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SwManagement_to_PiuType">
+ <containment>
+ <parent>
+ <hasClass name="SwManagement"/>
+ </parent>
+ <child>
+ <hasClass name="PiuType"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SwManagement_to_SwAllocation">
+ <containment>
+ <parent>
+ <hasClass name="SwManagement"/>
+ </parent>
+ <child>
+ <hasClass name="SwAllocation"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SwManagement_to_ReliableProgramUniter">
+ <containment>
+ <parent>
+ <hasClass name="SwManagement"/>
+ </parent>
+ <child>
+ <hasClass name="ReliableProgramUniter"/>
+ <cardinality>
+ <min>0</min>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Ospf_to_OspfInterface">
+ <containment>
+ <parent>
+ <hasClass name="Ospf"/>
+ </parent>
+ <child>
+ <hasClass name="OspfInterface"/>
+ <cardinality>
+ <min>0</min> <max>32</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Ospf_to_OspfArea">
+ <containment>
+ <parent>
+ <hasClass name="Ospf"/>
+ </parent>
+ <child>
+ <hasClass name="OspfArea"/>
+ <cardinality>
+ <min>1</min> <max>4</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Cbu_to_GeneralProcessorUnit">
+ <containment>
+ <parent>
+ <hasClass name="Cbu"/>
+ </parent>
+ <child>
+ <hasClass name="GeneralProcessorUnit"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="GeneralProcessorUnit_to_MediumAccessUnit">
+ <containment>
+ <parent>
+ <hasClass name="GeneralProcessorUnit"/>
+ </parent>
+ <child>
+ <hasClass name="MediumAccessUnit"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SwitchFabric_to_SwitchModule">
+ <containment>
+ <parent>
+ <hasClass name="SwitchFabric"/>
+ </parent>
+ <child>
+ <hasClass name="SwitchModule"/>
+ <cardinality>
+ <min>0</min> <max>32</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SwitchFabric_to_InternalLinkGroup">
+ <containment>
+ <parent>
+ <hasClass name="SwitchFabric"/>
+ </parent>
+ <child>
+ <hasClass name="InternalLinkGroup"/>
+ <cardinality>
+ <min>0</min> <max>31</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="InternalLinkGroup_to_SwitchInternalLink">
+ <containment>
+ <parent>
+ <hasClass name="InternalLinkGroup"/>
+ </parent>
+ <child>
+ <hasClass name="SwitchInternalLink"/>
+ <cardinality>
+ <min>0</min> <max>8</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etm4_to_Os155SpiTtp">
+ <containment>
+ <parent>
+ <hasClass name="Etm4"/>
+ </parent>
+ <child>
+ <hasClass name="Os155SpiTtp"/>
+ <cardinality>
+ <min>0</min> <max>2</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="VplTp_to_VpcTp">
+ <containment>
+ <parent>
+ <hasClass name="VplTp"/>
+ </parent>
+ <child>
+ <hasClass name="VpcTp"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="E1Ttp_to_Ds0Bundle">
+ <containment>
+ <parent>
+ <hasClass name="E1Ttp"/>
+ </parent>
+ <child>
+ <hasClass name="Ds0Bundle"/>
+ <cardinality>
+ <min>0</min> <max>31</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="T1PhysPathTerm_to_Ds0Bundle">
+ <containment>
+ <parent>
+ <hasClass name="T1PhysPathTerm"/>
+ </parent>
+ <child>
+ <hasClass name="Ds0Bundle"/>
+ <cardinality>
+ <min>0</min> <max>24</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="T1Ttp_to_Ds0Bundle">
+ <containment>
+ <parent>
+ <hasClass name="T1Ttp"/>
+ </parent>
+ <child>
+ <hasClass name="Ds0Bundle"/>
+ <cardinality>
+ <min>0</min> <max>24</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpAnsi_to_M3uAssociation">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpAnsi"/>
+ </parent>
+ <child>
+ <hasClass name="M3uAssociation"/>
+ <cardinality>
+ <min>0</min> <max>512</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpItu_to_M3uAssociation">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpItu"/>
+ </parent>
+ <child>
+ <hasClass name="M3uAssociation"/>
+ <cardinality>
+ <min>0</min> <max>512</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Vc12Ttp_to_E1Ttp">
+ <containment>
+ <parent>
+ <hasClass name="Vc12Ttp"/>
+ </parent>
+ <child>
+ <hasClass name="E1Ttp"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Os155SpiTtp_to_Vc4Ttp">
+ <containment>
+ <parent>
+ <hasClass name="Os155SpiTtp"/>
+ </parent>
+ <child>
+ <hasClass name="Vc4Ttp"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Vc4Ttp_to_Vc12Ttp">
+ <containment>
+ <parent>
+ <hasClass name="Vc4Ttp"/>
+ </parent>
+ <child>
+ <hasClass name="Vc12Ttp"/>
+ <cardinality>
+ <min>0</min> <max>63</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etmc41_to_Os155SpiTtp">
+ <containment>
+ <parent>
+ <hasClass name="Etmc41"/>
+ </parent>
+ <child>
+ <hasClass name="Os155SpiTtp"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Os155SpiTtp_to_Sts3CspeTtp">
+ <containment>
+ <parent>
+ <hasClass name="Os155SpiTtp"/>
+ </parent>
+ <child>
+ <hasClass name="Sts3CspeTtp"/>
+ <cardinality>
+ <min>0</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Os155SpiTtp_to_Sts1SpeTtp">
+ <containment>
+ <parent>
+ <hasClass name="Os155SpiTtp"/>
+ </parent>
+ <child>
+ <hasClass name="Sts1SpeTtp"/>
+ <cardinality>
+ <min>0</min> <max>3</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Cbu_to_Etmc1">
+ <containment>
+ <parent>
+ <hasClass name="Cbu"/>
+ </parent>
+ <child>
+ <hasClass name="Etmc1"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etmc1_to_T1PhysPathTerm">
+ <containment>
+ <parent>
+ <hasClass name="Etmc1"/>
+ </parent>
+ <child>
+ <hasClass name="T1PhysPathTerm"/>
+ <cardinality>
+ <min>0</min> <max>8</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Mtp3bSpChina_to_M3uAssociation">
+ <containment>
+ <parent>
+ <hasClass name="Mtp3bSpChina"/>
+ </parent>
+ <child>
+ <hasClass name="M3uAssociation"/>
+ <cardinality>
+ <min>0</min> <max>512</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="ImaGroup_to_ImaLink">
+ <containment>
+ <parent>
+ <hasClass name="ImaGroup"/>
+ </parent>
+ <child>
+ <hasClass name="ImaLink"/>
+ <cardinality>
+ <min>0</min> <max>8</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SystemFunctions_to_WebServer">
+ <containment>
+ <parent>
+ <hasClass name="SystemFunctions"/>
+ </parent>
+ <child>
+ <hasClass name="WebServer"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Sts1SpeTtp_to_Vt15Ttp">
+ <containment>
+ <parent>
+ <hasClass name="Sts1SpeTtp"/>
+ </parent>
+ <child>
+ <hasClass name="Vt15Ttp"/>
+ <cardinality>
+ <min>0</min> <max>28</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Vt15Ttp_to_T1Ttp">
+ <containment>
+ <parent>
+ <hasClass name="Vt15Ttp"/>
+ </parent>
+ <child>
+ <hasClass name="T1Ttp"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etm3_to_E3PhysPathTerm">
+ <containment>
+ <parent>
+ <hasClass name="Etm3"/>
+ </parent>
+ <child>
+ <hasClass name="E3PhysPathTerm"/>
+ <cardinality>
+ <min>0</min> <max>2</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Etm3_to_T3PhysPathTerm">
+ <containment>
+ <parent>
+ <hasClass name="Etm3"/>
+ </parent>
+ <child>
+ <hasClass name="T3PhysPathTerm"/>
+ <cardinality>
+ <min>0</min> <max>2</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="SystemFunctions_to_Licensing">
+ <containment>
+ <parent>
+ <hasClass name="SystemFunctions"/>
+ </parent>
+ <child>
+ <hasClass name="Licensing"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Cbu_to_TimingUnit2">
+ <containment>
+ <parent>
+ <hasClass name="Cbu"/>
+ </parent>
+ <child>
+ <hasClass name="TimingUnit2"/>
+ <cardinality>
+ <min>1</min> <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+</mim>
+
+</models>
+
diff --git a/lib/xmerl/test/xmerl_SUITE_data/eventp/mp.dtd b/lib/xmerl/test/xmerl_SUITE_data/eventp/mp.dtd
new file mode 100644
index 0000000000..1f6e31e772
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/eventp/mp.dtd
@@ -0,0 +1,274 @@
+<!-- 15531-APR 90163: rev F -->
+<!-- Date- 2000-10-16 -->
+<!-- Author- Johnni Sigeti -->
+<!-- Author- Niklas Storm -->
+<!-- Author- Hui Lin -->
+
+<!-- Revision History
+ A Raghunath Squid version
+ PB1 epkjsig 1999-09-09 Removed uLong, uShort, union
+ and inherits.
+ PB2 epkjsig 1999-09-23 Rewritten with new
+ requirements
+ PB3 epkjsig 1999-09-26 Updated after team review
+ B epkjsig 1999-10-06 Updated after inspection
+ PC1 epkjsig 1999-10-28 Added mandatory attribute
+ for associations.
+ PC2 epkjsig 1999-11-22 Added MORef as attribute
+ PC3 qpknian 2000-01-03 Added support object class.
+ PC4 qpknian 2000-01-18 Removed illegal characters
+ in comments.
+ PC5 qpknian 2000-01-21 Updated model tag. class and
+ soClass elements should be in
+ separate models.
+ C qpknian 2000-02-10 Approved after inspection.
+ PD1 qpknian 2000-03-02 Added applicationTag.
+ Added notificationTypes.
+ Removed controlled.
+ Renamed readOnly to advisoryReadOnly.
+ PD2 qpknian 2000-03-21 Added softLink to hoppers.
+ D qpknian 2000-04-26 Approved after inspection.
+ PE1 qpknian 2000-06-27 Updated for CR41 (use Corba types)
+ E qpknian 2000-09-01 Approved after inspection.
+ PF1 eiuhlin 2000-08-21 Updated for CR43 (Rename Model to MIM, add INTER-MIM)
+ PF2 eiuhlin 2000-09-20 Support uniDirectionalAssociation and biDirectionalAssociation
+ Add static to Attribute
+ Add enumRef and sequence to struct
+ PF3 eiuhlin 2000-09-20 Add maxLength to sequence
+ PF4 eiuhlin 2000-09-21 Define Element static
+ PF5 eiuhlin 2000-09-27 Remove ATTLIST name from moRef
+ PF6 eiuhlin 2000-10-02 Remove tag <helpRef>, <icon>
+ Add associationClass to bi and uni-directional association
+ Change tag <target> to <supported>
+ Remove ATTLIST name from supporter and supported
+ Add ATTLIST name to moRef
+ Remove tag <advisoryReadOnly>
+ Add tag <readOnly> and <undefined>
+ PF7 eiuhlin 2000-10-04 Add ATTLIST name to interMim
+ F eiuhlin 2000-10-16 Approved after inspection.
+-->
+
+
+<!-- Common -->
+<!ELEMENT description (#PCDATA)>
+
+
+<!ELEMENT applicationTag (#PCDATA)>
+
+
+<!-- Models definition -->
+<!ELEMENT models (mim|interMim)*>
+
+<!ELEMENT mim (description?, applicationTag?,
+
+ (struct | enum | exception)*,
+ class+, relationship*)>
+<!ATTLIST mim name ID #REQUIRED
+ version CDATA #REQUIRED
+ release CDATA #REQUIRED>
+
+<!ELEMENT interMim (description?, applicationTag?,
+
+ (struct | enum )*,
+ relationship*)>
+
+<!ATTLIST interMim name CDATA #REQUIRED>
+
+<!-- MO class definition -->
+<!ELEMENT class (description?, applicationTag?,
+ systemCreated?, notificationTypes?, (action | attribute)*)>
+<!ATTLIST class name CDATA #REQUIRED>
+
+<!ELEMENT systemCreated EMPTY>
+
+<!ELEMENT notificationTypes (#PCDATA)>
+
+
+<!-- Relations -->
+<!ELEMENT relationship (description?, applicationTag?,
+ (biDirectionalAssociation |uniDirectionalAssociation | containment|softLink|support))>
+<!ATTLIST relationship name CDATA #REQUIRED>
+
+<!ELEMENT softLink (parent, child+)>
+
+<!ELEMENT support (supporter,supported+)>
+
+<!ELEMENT supporter (description?, applicationTag?,
+ hasClass, cardinality?)>
+
+<!ELEMENT supported (description?, applicationTag?,
+ hasClass, cardinality?)>
+
+<!ELEMENT biDirectionalAssociation (mandatory?, associationEnd, associationEnd+, associationClass?)>
+
+<!ELEMENT uniDirectionalAssociation (mandatory?, hasClass, associationEnd+, associationClass?)>
+
+<!ELEMENT containment (parent, child+)>
+
+<!ELEMENT associationEnd (description?, applicationTag?,
+ hasClass, cardinality?)>
+<!ATTLIST associationEnd name CDATA #REQUIRED>
+
+<!ELEMENT associationClass (attribute+)>
+
+<!ELEMENT parent (description?, applicationTag?,
+ hasClass)>
+<!ELEMENT child (description?, applicationTag?,
+ hasClass, cardinality?)>
+
+<!ELEMENT cardinality (min | max | (min, max))>
+
+<!ELEMENT hasClass EMPTY>
+<!ATTLIST hasClass name CDATA #REQUIRED
+ inMim CDATA #IMPLIED
+ ofVersion CDATA #IMPLIED>
+
+
+
+
+<!-- Data types -->
+<!ENTITY % corbaTypes "boolean | octet | char | double | float |
+ long | longlong | short | string | wstring">
+<!ENTITY % availableTypes "%corbaTypes; | enumRef | structRef |
+ moRef | sequence">
+
+
+<!-- For attributes, parameters and exceptions -->
+<!ELEMENT dataType (%availableTypes;)>
+
+<!-- For actions -->
+<!ELEMENT returnType (void | %availableTypes;)>
+
+
+<!-- Return data types -->
+<!ELEMENT void EMPTY>
+
+
+<!-- Primitive data types -->
+<!ELEMENT boolean (defaultValue?)>
+
+<!ELEMENT octet (range?, defaultValue?)>
+
+<!ELEMENT char (range?, defaultValue?)>
+
+<!ELEMENT double (range?, defaultValue?)>
+
+<!ELEMENT float (range?, defaultValue?)>
+
+<!ELEMENT long (range?, defaultValue?)>
+
+<!ELEMENT longlong (range?, defaultValue?)>
+
+<!ELEMENT short (range?, defaultValue?)>
+
+<!ELEMENT string (lengthRange?, (validValues | alphabet)?, defaultValue?)>
+
+<!ELEMENT wstring (lengthRange?, (validValues | alphabet)?, defaultValue?)>
+
+
+<!ELEMENT alphabet (#PCDATA)>
+<!ELEMENT validValues (#PCDATA)>
+
+<!ELEMENT lengthRange (min?, (min, max)*, max?)>
+<!ELEMENT range (min?, (min, max)*, max?)>
+
+<!ELEMENT max (#PCDATA)>
+<!ELEMENT min (#PCDATA)>
+
+<!ELEMENT defaultValue (#PCDATA)>
+
+
+<!-- Enum data type -->
+<!ELEMENT enum (description?, applicationTag?,
+ enumMember+, defaultValue?)>
+<!ATTLIST enum name CDATA #REQUIRED>
+
+<!ELEMENT enumMember (description?, applicationTag?,
+ value?)>
+<!ATTLIST enumMember name CDATA #REQUIRED>
+
+<!ELEMENT enumRef (defaultValue?)>
+<!ATTLIST enumRef name CDATA #REQUIRED>
+
+<!ELEMENT value (#PCDATA)>
+
+
+<!-- Struct data type -->
+<!ELEMENT struct (description?, applicationTag?,
+ structMember+)>
+<!ATTLIST struct name CDATA #REQUIRED>
+
+<!ELEMENT structMember (description?, applicationTag?,
+ (%corbaTypes; | sequence | enumRef))>
+<!ATTLIST structMember name CDATA #REQUIRED>
+
+<!ELEMENT structRef EMPTY>
+<!ATTLIST structRef name CDATA #REQUIRED>
+
+
+<!-- Sequence data type -->
+<!ELEMENT sequence ((%corbaTypes; | enumRef | structRef | moRef),
+ length?, maxLength?, nonUnique?)>
+
+<!ELEMENT length (#PCDATA)>
+
+<!ELEMENT maxLength (#PCDATA)>
+
+<!ELEMENT nonUnique EMPTY>
+
+
+<!-- MoRef data type -->
+<!ELEMENT moRef EMPTY>
+
+<!ATTLIST moRef name CDATA #REQUIRED>
+
+<!-- Attribute -->
+<!ELEMENT attribute (description?, applicationTag?,
+ local?, mandatory?, noNotification?,
+ nonPersistent?, readOnly?, restricted?, static?,undefined?, dataType)>
+<!ATTLIST attribute name CDATA #REQUIRED>
+
+
+<!-- Attribute controls -->
+<!-- nonUnique is defined under the sequence data type. -->
+
+<!ELEMENT local EMPTY>
+
+<!ELEMENT mandatory EMPTY>
+
+<!ELEMENT noNotification EMPTY>
+
+<!ELEMENT nonPersistent EMPTY>
+
+<!ELEMENT readOnly EMPTY>
+
+<!ELEMENT restricted EMPTY>
+
+<!ELEMENT static EMPTY>
+
+<!ELEMENT undefined EMPTY>
+
+
+<!-- Action -->
+<!ELEMENT action (description?, applicationTag?,
+ returnType, parameter*, raisesException*)>
+<!ATTLIST action name CDATA #REQUIRED>
+
+<!ELEMENT parameter (description?, applicationTag?,
+ (in | out | inout), dataType)>
+<!ATTLIST parameter name CDATA #REQUIRED>
+
+<!ELEMENT in EMPTY>
+<!ELEMENT inout EMPTY>
+<!ELEMENT out EMPTY>
+
+<!ELEMENT exception (description?, applicationTag?,
+ exceptionParameter*)>
+<!ATTLIST exception name CDATA #REQUIRED>
+
+<!ELEMENT exceptionParameter (description?, applicationTag?,
+ dataType)>
+<!ATTLIST exceptionParameter name CDATA #REQUIRED>
+
+<!ELEMENT raisesException EMPTY>
+<!ATTLIST raisesException name CDATA #REQUIRED>
diff --git a/lib/xmerl/test/xmerl_SUITE_data/eventp/wurfl.stub b/lib/xmerl/test/xmerl_SUITE_data/eventp/wurfl.stub
new file mode 100644
index 0000000000..78d980d5b7
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/eventp/wurfl.stub
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE wurfl [
+<!ELEMENT version (#PCDATA)>
+<!ELEMENT wurfl (version)>
+]>
diff --git a/lib/xmerl/test/xmerl_SUITE_data/eventp/wurfl.xml b/lib/xmerl/test/xmerl_SUITE_data/eventp/wurfl.xml
new file mode 100644
index 0000000000..ea96469af3
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/eventp/wurfl.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE wurfl [
+<!ELEMENT version (#PCDATA)>
+<!ELEMENT wurfl (version)>
+]>
+<wurfl>
+ <version>
+</version>
+</wurfl>
diff --git a/lib/xmerl/test/xmerl_SUITE_data/misc.tar.gz b/lib/xmerl/test/xmerl_SUITE_data/misc.tar.gz
new file mode 100644
index 0000000000..fef7431845
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/misc.tar.gz
Binary files differ
diff --git a/lib/xmerl/test/xmerl_SUITE_data/xpath/documentRoot.xml b/lib/xmerl/test/xmerl_SUITE_data/xpath/documentRoot.xml
new file mode 100644
index 0000000000..667a44b7fe
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/xpath/documentRoot.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<documentRoot>
+<!-- Test data from
+ http://www.whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm -->
+<?value ="2"?>
+<parent name="data" >
+ <child id="1" name="alpha" >Some Text</child>
+ <child id="2" name="beta" >
+ <grandchild id="2.1" name="beta-alpha" ></grandchild>
+ <grandchild id="2.2" name="beta-beta" ></grandchild>
+ </child>
+ <pet name="tigger" type="cat" >
+ <data>
+ <birthday month="sept" day="19" ></birthday>
+ <food name="Acme Cat Food" ></food>
+ </data>
+ </pet>
+ <pet name="Fido" type="dog" >
+ <description>
+ Large dog!
+ </description>
+ <data>
+ <birthday month="feb" day="3" ></birthday>
+ <food name="Acme Dog Food" ></food>
+ </data>
+ </pet>
+ <rogue name="is this real?" >
+ <data>
+ Hates dogs!
+ </data>
+ </rogue>
+ <child id="3" name="gamma" mark="yes" >
+ <!-- A comment -->
+ <description>
+ Likes all animals - especially dogs!
+ </description>
+ <grandchild id="3.1" name="gamma-alpha" >
+ <![CDATA[ Some non-parsable character data ]]>
+ </grandchild>
+ <grandchild id="3.2" name="gamma-beta" ></grandchild>
+ </child>
+</parent>
+</documentRoot> \ No newline at end of file
diff --git a/lib/xmerl/test/xmerl_SUITE_data/xpath/e1074.xml b/lib/xmerl/test/xmerl_SUITE_data/xpath/e1074.xml
new file mode 100644
index 0000000000..920a9e67e1
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/xpath/e1074.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+ <root id="1">
+ <elem1 id="2">
+ <elem2 id="3">
+ <e id="4"/>
+ <elem3 id="5">
+ <e id="6"/>
+ </elem3>
+ <elem3 id="7"/>
+ </elem2>
+ </elem1>
+ <elem1 id="8">
+ <elem2 id="9"/>
+ <e id="10"/>
+ <e id="11"/>
+ </elem1>
+ <e id="12"/>
+ </root>
diff --git a/lib/xmerl/test/xmerl_SUITE_data/xpath/e1075.xml b/lib/xmerl/test/xmerl_SUITE_data/xpath/e1075.xml
new file mode 100644
index 0000000000..920a9e67e1
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/xpath/e1075.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+ <root id="1">
+ <elem1 id="2">
+ <elem2 id="3">
+ <e id="4"/>
+ <elem3 id="5">
+ <e id="6"/>
+ </elem3>
+ <elem3 id="7"/>
+ </elem2>
+ </elem1>
+ <elem1 id="8">
+ <elem2 id="9"/>
+ <e id="10"/>
+ <e id="11"/>
+ </elem1>
+ <e id="12"/>
+ </root>
diff --git a/lib/xmerl/test/xmerl_SUITE_data/xpath/e1076.xml b/lib/xmerl/test/xmerl_SUITE_data/xpath/e1076.xml
new file mode 100644
index 0000000000..c9ffebb202
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/xpath/e1076.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+ <root id="1">
+ <elem1 id="2">cat</elem1>
+ <elem1 id="3"> dog </elem1>
+ <elem1 id="4">
+ cat
+ <elem2 id="5">
+ <elem3 id="6">cat</elem3>
+ </elem2>
+ dog
+ </elem1>
+ <elem1 id="7">Cat</elem1>
+ </root>
diff --git a/lib/xmerl/test/xmerl_SUITE_data/xpath/e1077.xml b/lib/xmerl/test/xmerl_SUITE_data/xpath/e1077.xml
new file mode 100644
index 0000000000..9aa548e13c
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/xpath/e1077.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE root [ <!ELEMENT e (e*) >
+ <!ATTLIST e id ID #REQUIRED>
+ ]>
+ <root>
+ <e id="1">
+ <e id="two">
+ <e id="3"/>
+ <e id="4">
+ <e id="the fifth"/>
+ </e>
+ <e id="6"/>
+ </e>
+ </e>
+ <e id="seven"/>
+ </root>
diff --git a/lib/xmerl/test/xmerl_SUITE_data/xpath/e1078.xml b/lib/xmerl/test/xmerl_SUITE_data/xpath/e1078.xml
new file mode 100644
index 0000000000..a90db50145
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/xpath/e1078.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+ <root id="1">
+ <elem1 id="2" pet="cat"/>
+ <elem1 id="3" pet=" dog " age="8"/>
+ <elem1 id="4" pet="Cat" >
+ <elem2 id="5">
+ <elem3 id="6" age="10"/>
+ </elem2>
+ </elem1>
+ <elem1 id="7" pet="dog"/>
+ </root>
diff --git a/lib/xmerl/test/xmerl_SUITE_data/xpath/motorcycles.xml b/lib/xmerl/test/xmerl_SUITE_data/xpath/motorcycles.xml
new file mode 100644
index 0000000000..b3629dce34
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/xpath/motorcycles.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<motorcycles>
+ <bike year="2000" color="black">
+ <name>
+ <manufacturer>Suzuki</manufacturer>
+ <brandName>Suzuki VL 1500</brandName>
+ <additionalName>Intruder</additionalName>
+ </name>
+ <engine>V-engine, 2-cylinders, 1500 cc</engine>
+ <kind>custom</kind>
+ <drive>cardan</drive>
+ <accessories>Sissy bar, luggage carrier,V&amp;H exhaust pipes</accessories>
+ </bike>
+ <date>2004.08.25</date>
+ <bike year="1983" color="read pearl">
+ <name>
+ <manufacturer>Yamaha</manufacturer>
+ <brandName>XJ 400</brandName>
+ </name>
+ <engine>4 cylinder, 400 cc</engine>
+ <kind>alround</kind>
+ <drive>chain</drive>
+ <comment>Good shape!</comment>
+ </bike>
+</motorcycles>
diff --git a/lib/xmerl/test/xmerl_SUITE_data/xpath/myBS_model.xml b/lib/xmerl/test/xmerl_SUITE_data/xpath/myBS_model.xml
new file mode 100644
index 0000000000..58f90662a4
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/xpath/myBS_model.xml
@@ -0,0 +1,6 @@
+<myBS_model>
+
+ <blipp id="name1"/>
+ <blipp id="name2"/>
+
+</myBS_model>
diff --git a/lib/xmerl/test/xmerl_SUITE_data/xpath/purchaseOrder.xml b/lib/xmerl/test/xmerl_SUITE_data/xpath/purchaseOrder.xml
new file mode 100644
index 0000000000..a5ae223d65
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/xpath/purchaseOrder.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<apo:purchaseOrder xmlns:apo="http://www.example.com/PO1"
+ orderDate="1999-10-20">
+ <billTo country="US">
+ <name>Robert Smith</name>
+ <street>8 Oak Avenue</street>
+ <!-- etc. -->
+ <city>Old Town</city>
+ <state>PA</state>
+ <zip>95819</zip>
+ </billTo>
+ <apo:comment>Hurry, my lawn is going wild!</apo:comment>
+ <shipTo country="US">
+ <name>Alice Smith</name>
+ <street>123 Maple Street</street>
+ <!-- etc. -->
+ <city>Mill Valley</city>
+ <state>CA</state>
+ <zip>90952</zip>
+ </shipTo>
+ <!-- etc. -->
+ <items>
+ <item partNum="872-AA">
+ <productName>Lawnmower</productName>
+ <quantity>1</quantity>
+ <USPrice>148.95</USPrice>
+ <comment>Confirm this is electric</comment>
+ </item>
+ <item partNum="926-AA">
+ <productName>Baby Monitor</productName>
+ <quantity>1</quantity>
+ <USPrice>39.98</USPrice>
+ <shipDate>1999-05-21</shipDate>
+ </item>
+ </items>
+</apo:purchaseOrder>
diff --git a/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath.xml b/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath.xml
new file mode 100644
index 0000000000..248fbd413d
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath.xml
@@ -0,0 +1,25 @@
+<myBS_model>
+
+ <blipp id="name1">
+ <blupp att="bluppa"/>
+ </blipp>
+ <blipp id="name2">
+ <blupp att2="bluppb">
+ <plopp name="pl">here are some text</plopp>
+ </blupp>
+ </blipp>
+ <blipp id="name3" test="test1">
+ <blupp att2="bluppc">
+ <plopp name="plp">here are some more text</plopp>
+ </blupp>
+ <blupp att="bluppc2"/>
+ </blipp>
+
+ <blipp2 bid="name1">
+ <blupp att="bluppa"/>
+ <blupp att2="bluppb">
+ <plopp name="pl">here are some additional text</plopp>
+ </blupp>
+ </blipp2>
+
+</myBS_model> \ No newline at end of file
diff --git a/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl b/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl
new file mode 100644
index 0000000000..850b7f8135
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_abbrev.erl
@@ -0,0 +1,266 @@
+%%%-------------------------------------------------------------------
+%%% File : xpath_abbrev.erl
+%%% Author : Bertil Karlsson <bertil@finrod>
+%%% Description :
+%%%
+%%% Created : 17 Jan 2006 by Bertil Karlsson <bertil@finrod>
+%%%-------------------------------------------------------------------
+-module(xpath_abbrev).
+
+-export([test/0, check_node_set/2, ticket_6873/0, ticket_7496/0, functions/0]).
+
+-include("test_server.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
+
+test() ->
+ ?line {E,_} = xmerl_scan:file("xpath.xml"),
+
+ ?line Res1 = xmerl_xpath:string("blipp",E),
+ ?line ok = check_node_set("blipp",Res1),
+ ?line Res2 = xmerl_xpath:string("*",E),
+ ?line ok = check_node_set("*",Res2),
+ ?line Res3 = xmerl_xpath:string("blipp/blupp/plopp/text()",E),
+ ?line ok = check_node_set("blipp/blupp/plopp/text()",Res3),
+ ?line Res4 = xmerl_xpath:string("blipp/blupp/@att2",E),
+ ?line ok = check_node_set("blipp/blupp/@att2",Res4),
+ ?line Res5 = xmerl_xpath:string("blipp/@*",E),
+ ?line ok = check_node_set("blipp/@*",Res5),
+ ?line Res6 = xmerl_xpath:string("blipp[2]",E),
+ ?line ok = check_node_set("blipp[2]",Res6),
+ ?line Res7 = xmerl_xpath:string("blipp[last()]",E),
+ ?line ok = check_node_set("blipp[last()]",Res7),
+ ?line Res8 = xmerl_xpath:string("*/blupp",E),
+ ?line ok = check_node_set("*/blupp",Res8),
+ ?line Res9 = xmerl_xpath:string("/myBS_model/blipp[3]/blupp[2]",E),
+ ?line ok = check_node_set("/myBS_model/blipp[3]/blupp[2]",Res9),
+ ?line Res10 = xmerl_xpath:string("blipp//plopp",E),
+ ?line ok = check_node_set("blipp//plopp",Res10),
+ ?line Res11 = xmerl_xpath:string("//plopp",E),
+ ?line ok = check_node_set("//plopp",Res11),
+ ?line Res12 = xmerl_xpath:string("//blupp/plopp",E),
+ ?line ok = check_node_set("//blupp/plopp",Res12),
+ ?line Res13 = xmerl_xpath:string(".",E),
+ ?line ok = check_node_set(".",Res13),
+ ?line Res14 = xmerl_xpath:string(".//blipp2",E),
+ ?line ok = check_node_set(".//blipp2",Res14),
+ ?line Res15 = xmerl_xpath:string(".//blipp2/blupp/plopp/..",E),
+ ?line ok = check_node_set(".//blipp2/blupp/plopp/..",Res15),
+ ?line Res16 = xmerl_xpath:string(".//blipp[2]/blupp/plopp/../@att2",E),
+ ?line ok = check_node_set(".//blipp[2]/blupp/plopp/../@att2",Res16),
+ ?line Res17 = xmerl_xpath:string(".//blipp/blupp/plopp[2]/../@att2",E),
+ ?line ok = check_node_set(".//blipp/blupp/plopp[2]/../@att2",Res17),
+ ?line Res18 = xmerl_xpath:string("blipp[@id='name2']",E),
+ ?line ok = check_node_set("blipp[@id='name2']",Res18),
+ ?line Res19 = xmerl_xpath:string("blipp[@id='name2'][3]",E),
+ ?line ok = check_node_set("blipp[@id='name2'][3]",Res19),
+ ?line Res20 = xmerl_xpath:string("//blupp[plopp=\"here are some more text\"]",E),
+ ?line ok = check_node_set("//blupp[plopp=\"here are some more text\"]",Res20),
+ ?line Res21 = xmerl_xpath:string("//blupp[plopp]",E),
+ ?line ok = check_node_set("//blupp[plopp]",Res21),
+ ?line Res22 = xmerl_xpath:string("blipp[@id and @test]",E),
+ ?line ok = check_node_set("blipp[@id and @test]",Res22).
+
+check_node_set("blipp",[E1,E2,E3]) ->
+ ?line ok = xml_element_name(E1,blipp),
+ ?line ok = xml_element_name(E2,blipp),
+ ?line ok = xml_element_name(E3,blipp),
+ ok;
+check_node_set("*",[E1,E2,E3,E4]) ->
+ ?line ok = xml_element_name(E1,blipp),
+ ?line ok = xml_element_name(E2,blipp),
+ ?line ok = xml_element_name(E3,blipp),
+ ?line ok = xml_element_name(E4,blipp2),
+ ok;
+check_node_set("blipp/blupp/plopp/text()",[T1,T2]) ->
+ ?line #xmlText{value="here are some text"} = T1,
+ ?line #xmlText{value="here are some more text"} = T2,
+ ok;
+check_node_set("blipp/blupp/@att2",[A1,A2]) ->
+ ?line #xmlAttribute{name=att2} = A1,
+ ?line #xmlAttribute{name=att2} = A2,
+ ok;
+check_node_set("blipp/@*",[A1,A2,A3,A4]) ->
+ ?line #xmlAttribute{} = A1,
+ ?line #xmlAttribute{} = A2,
+ ?line #xmlAttribute{} = A3,
+ ?line #xmlAttribute{} = A4,
+ ok;
+check_node_set("blipp[2]",[E]) ->
+ ?line #xmlElement{name=blipp,
+ attributes=[#xmlAttribute{name=id,value="name2"}]} = E,
+ ok;
+check_node_set("blipp[last()]",[E]) ->
+ ?line #xmlElement{name=blipp,
+ attributes=[#xmlAttribute{name=id,value="name3"}|_]} = E,
+ ok;
+check_node_set("*/blupp",[E1,E2,E3,E4,E5,E6]) ->
+ ?line ok = xml_element_name(E1,blupp),
+ ?line ok = xml_element_name(E2,blupp),
+ ?line ok = xml_element_name(E3,blupp),
+ ?line ok = xml_element_name(E4,blupp),
+ ?line ok = xml_element_name(E5,blupp),
+ ?line ok = xml_element_name(E6,blupp),
+ ok;
+check_node_set("/myBS_model/blipp[3]/blupp[2]",[E]) ->
+ ?line #xmlElement{name=blupp,
+ attributes=[#xmlAttribute{name=att,value="bluppc2"}]}=E,
+ ok;
+check_node_set("blipp//plopp",[#xmlElement{name=plopp},#xmlElement{name=plopp}]) ->
+ ok;
+check_node_set("//plopp",[E1,E2,E3]) ->
+ ?line ok = xml_element_name(E1,plopp),
+ ?line ok = xml_element_name(E2,plopp),
+ ?line ok = xml_element_name(E3,plopp),
+ ok;
+check_node_set("//blupp/plopp",[E1,E2,E3]) ->
+ ?line ok = xml_element_name(E1,plopp),
+ ?line ok = xml_element_name(E2,plopp),
+ ?line ok = xml_element_name(E3,plopp),
+ ok;
+check_node_set(".",[#xmlElement{name=myBS_model}]) ->
+ ok;
+check_node_set(".//blipp2",[#xmlElement{name=blipp2}]) ->
+ ok;
+check_node_set(".//blipp2/blupp/plopp/..",[#xmlElement{name=blupp}]) ->
+ ok;
+check_node_set(".//blipp[2]/blupp/plopp/../@att2",[#xmlAttribute{name=att2,value="bluppb"}]) ->
+ ok;
+check_node_set(".//blipp/blupp/plopp[2]/../@att2",[#xmlAttribute{name=att2,value="bluppc"}]) ->
+ ok;
+check_node_set("blipp[@id='name2']",[E]) ->
+ ?line #xmlElement{name=blipp,
+ attributes=[#xmlAttribute{name=id,value="name2"}]}=E,
+ ok;
+check_node_set("blipp[@id='name2'][3]",[]) ->
+ ok;
+check_node_set("//blupp[plopp=\"here are some more text\"]",[E]) ->
+ ?line #xmlElement{name=blupp,
+ content=[_T,#xmlElement{name=plopp,content=C}|_]} = E,
+ ?line true = lists:keymember("here are some more text",#xmlText.value,C),
+ ok;
+check_node_set("//blupp[plopp]",[E1,E2,E3]) ->
+ ?line #xmlElement{name=blupp,
+ content=C1} = E1,
+ ?line true = lists:keymember(plopp,#xmlElement.name,C1),
+ ?line #xmlElement{name=blupp,
+ content=C2} = E2,
+ ?line true = lists:keymember(plopp,#xmlElement.name,C2),
+ ?line #xmlElement{name=blupp,
+ content=C3} = E3,
+ ?line true = lists:keymember(plopp,#xmlElement.name,C3),
+ ok;
+check_node_set("blipp[@id and @test]",[E]) ->
+ ?line #xmlElement{name=blipp,
+ attributes=Atts} = E,
+ ?line true = lists:keymember(id,#xmlAttribute.name,Atts),
+ ?line true = lists:keymember(test,#xmlAttribute.name,Atts),
+ ok;
+check_node_set(Pattern,NodeSet) ->
+ io:format("Pattern: ~p~nNodeSet: ~p~n",[Pattern,NodeSet]),
+ error.
+
+xml_element_name(E,N) ->
+ ?line #xmlElement{name=N} = E,
+ ok.
+
+ticket_6873() ->
+ ?line [#xmlElement{}] = xmerl_xpath:string("//foo[contains(@bar, 'oe')]",element(1,xmerl_scan:string("<foo bar=\"Joe\" />"))),
+ ok.
+
+ticket_7496() ->
+ Test = fun(Doc, XPath, Exp) ->
+ Result = xmerl_xpath:string(XPath, Doc),
+ ?line Exp = [Name || #xmlElement{name = Name} <- Result],
+ ok
+ end,
+ ?line {Doc1,_} = xmerl_scan:string("<a><b/> <c/> <d/> <e/></a>"),
+ ?line ok = Test(Doc1, "//b/following::*", [c, d, e]),
+ ?line ok = Test(Doc1,"//b/following::*[1]", [c]),
+ ?line ok = Test(Doc1,"//b/following::*[position()=1]", [c]),
+ ?line ok = Test(Doc1,"//b/following::*[3]", [e]),
+ ?line ok = Test(Doc1,"//b/following::*[position()=3]", [e]),
+ ?line ok = Test(Doc1,"//e/preceding::*", [b, c, d]),
+ ?line ok = Test(Doc1,"//e/preceding::*[1]", [d]),
+ ?line ok = Test(Doc1,"//e/preceding::*[position()=1]", [d]),
+ ?line ok = Test(Doc1,"//e/preceding::*[3]", [b]),
+ ?line ok = Test(Doc1,"//e/preceding::*[position()=3]", [b]),
+ ?line ok = Test(Doc1,"//b/following::*[position() mod 2=0]", [d]),
+ ?line ok = Test(Doc1,"//b/self::*", [b]),
+
+ ?line {Doc2,_} = xmerl_scan:string("<a><b/> <c><d/></c> <e/> <f><g/></f> <h/> <i><j/></i> <k/></a>"),
+ ?line ok = Test(Doc2,"//g/preceding::*", [b, c, d, e]),
+ ?line ok = Test(Doc2, "//g/following::*", [h, i, j, k]),
+ ?line ok = Test(Doc2,"//g/ancestor::*", [a, f]),
+ ?line ok = Test(Doc2,"//g/ancestor::*[1]", [f]),
+ ?line ok = Test(Doc2,"//g/ancestor::*[2]", [a]),
+ ?line ok = Test(Doc2,"//g/ancestor-or-self::*", [a, f, g]),
+ ?line ok = Test(Doc2,"//g/ancestor-or-self::*[1]", [g]),
+ ?line ok = Test(Doc2,"//g/ancestor-or-self::*[2]", [f]),
+ ?line ok = Test(Doc2,"//g/ancestor-or-self::*[3]", [a]),
+ ?line ok = Test(Doc2,"/descendant::*", [a, b, c, d, e, f, g, h, i, j, k]),
+ ?line ok = Test(Doc2,"//f/preceding-sibling::*", [b, c, e]),
+ ?line ok = Test(Doc2,"//f/following-sibling::*", [h, i, k]),
+ ?line ok = Test(Doc2,"//f/self::*", [f]),
+ ?line ok = Test(Doc2,"//f/ancestor::*", [a]),
+ ?line ok = Test(Doc2,"//f/descendant::*", [g]),
+ ?line ok = Test(Doc2,"//f/preceding::*", [b, c, d, e]),
+ ?line ok = Test(Doc2,"//f/following::*", [h, i, j, k]),
+ ?line ok = Test(Doc2,"//text()[1]/following-sibling::*", [c, e, f, h, i, k]),
+
+ ?line {Doc3,_} = xmerl_scan:file("documentRoot.xml"),
+ ?line ok = Test(Doc3,"//child",[child,child,child]),
+ ?line ok = Test(Doc3,"//child[@name='beta']",[child]),
+ ?line [{xmlAttribute,id,[],[],[],[],1,[],"2",false}] =
+ xmerl_xpath:string("/documentRoot/parent/child[@name='beta']/@id",Doc3),
+ ?line ok = Test(Doc3,"/documentRoot/parent/child|/documentRoot/parent/pet",
+ [child,child,child,pet,pet]),
+ ?line ok = Test(Doc3,"//*[starts-with(local-name(),'p')]",
+ [parent,pet,pet]).
+
+
+functions() ->
+ Test = fun(Doc, XPath, Exp) ->
+ Result = xmerl_xpath:string(XPath, Doc),
+ ?line Exp = [begin
+ case Obj of
+ #xmlElement{name = EName} ->
+ EName;
+ #xmlAttribute{name = AName} ->
+ AName;
+ #xmlText{value=Text} ->
+ Text
+ end
+ end|| Obj <- Result],
+ ok
+ end,
+ Foo =
+ "<foo>"
+ " <bar>"
+ " <name>Xml</name>"
+ " <value>1</value>"
+ " </bar>"
+ " <bar>"
+ " <name>Xpath</name>"
+ " <value>2</value>"
+ " </bar>"
+ " <bar>"
+ " <name>Erlang</name>"
+ " <value>3</value>"
+ " </bar>"
+ "</foo>",
+ {Doc,_} = xmerl_scan:string(Foo),
+ ?line ok = Test(Doc,"/foo/bar[name = 'Xml']/value/text()",["1"]),
+ ?line ok = Test(Doc,"/foo/bar/node()/text()",
+ ["Xml","1","Xpath","2","Erlang","3"]),
+ ?line ok = Test(Doc,"/foo/bar[contains(name, 'path')]",[bar]),
+ ?line ok = Test(Doc,"/foo/bar[starts-with(name, 'X')]",[bar,bar]),
+ ?line ok = Test(Doc,"/foo/bar[value = string(1)]/value/text()",["1"]),
+
+
+ {Doc2,_}= xmerl_scan:file("purchaseOrder.xml"),
+ ?line ok = Test(Doc2,"//*[starts-with(local-name(),'c')]",
+ ['apo:comment',city,city,comment]),
+ ?line ok = Test(Doc2,"//*[starts-with(name(),'c')]",
+ [city,city,comment]),
+ ?line ok = Test(Doc2,"//*[starts-with(name(),'{http://www.example.com/PO1')]",
+ ['apo:purchaseOrder','apo:comment']).
diff --git a/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_lib.erl b/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_lib.erl
new file mode 100644
index 0000000000..4cde46826e
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_lib.erl
@@ -0,0 +1,184 @@
+%%%-------------------------------------------------------------------
+%%% File : xpath_lib.erl
+%%% Author : Bertil Karlsson <bertil@finrod>
+%%% Description :
+%%%
+%%% Created : 13 Jan 2006 by Bertil Karlsson <bertil@finrod>
+%%%-------------------------------------------------------------------
+-module(xpath_lib).
+
+-export([test/0,check_node_set/2,ticket_6873/0]).
+
+-include("test_server.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
+
+test() ->
+ ?line {E,_} = xmerl_scan:file("myBS_model.xml"),
+ ?line Res1 = xmerl_xpath:string("blipp",E),
+ ?line ok = check_node_set("blipp",Res1),
+ ?line Res2 = xmerl_xpath:string("//blipp",E),
+ ?line ok = check_node_set("//blipp",Res2),
+ ?line Res3 = xmerl_xpath:string("/myBS_model/blipp",E),
+ ?line ok = check_node_set("/myBS_model/blipp",Res3),
+ ?line Res4 = xmerl_xpath:string("blipp[@id=\"name1\"]",E),
+ ?line ok = check_node_set("blipp[@id=\"name1\"]",Res4),
+ ?line Res5 = xmerl_xpath:string("//blipp[@id=\"name1\"]",E),
+ ?line ok = check_node_set("//blipp[@id=\"name1\"]",Res5),
+ ?line Res6 = xmerl_xpath:string("/myBS_model/blipp[@id=\"name1\"]",E),
+ ?line ok = check_node_set("/myBS_model/blipp[@id=\"name1\"]",Res6).
+
+
+check_node_set("blipp",[H1,H2]) ->
+ ?line #xmlElement{name = blipp} = H1,
+ ?line #xmlElement{name = blipp} = H2,
+ ok;
+check_node_set("//blipp",[H1,H2]) ->
+ ?line #xmlElement{name = blipp} = H1,
+ ?line #xmlElement{name = blipp} = H2,
+ ok;
+check_node_set("/myBS_model/blipp",[H1,H2]) ->
+ ?line #xmlElement{name = blipp} = H1,
+ ?line #xmlElement{name = blipp} = H2,
+ ok;
+check_node_set("blipp[@id=\"name1\"]",[H]) ->
+ ?line H#xmlElement{attributes=#xmlAttribute{name=id,value="name1"}},
+ ok;
+check_node_set("//blipp[@id=\"name1\"]",[H]) ->
+ ?line H#xmlElement{attributes=#xmlAttribute{name=id,value="name1"}},
+ ok;
+check_node_set("/myBS_model/blipp[@id=\"name1\"]",[H]) ->
+ ?line H#xmlElement{attributes=#xmlAttribute{name=id,value="name1"}},
+ ok.
+
+ticket_6873() ->
+ GetId =
+ fun(Atts) ->
+ case lists:keysearch(id,#xmlAttribute.name,Atts) of
+ {value,#xmlAttribute{value=AttV}} -> AttV;
+ _ -> novalue
+ end
+ end,
+ Test =
+ fun(Doc, XPath, Exp) ->
+ Result = xmerl_xpath:string(XPath, Doc),
+ Exp = [begin
+ case Obj of
+ #xmlElement{name = EName,attributes=Atts} ->
+ {EName,GetId(Atts)};
+ #xmlAttribute{name = AName} ->
+ AName;
+ #xmlText{value=Text} ->
+ Text
+ end
+ end|| Obj <- Result],
+ ok
+ end,
+
+
+
+ Doc1 = get_doc("e1074"),
+ ?line ok = Test(Doc1,"/*",[{root,"1"}]),
+ ?line ok = Test(Doc1,"/root",[{root,"1"}]),
+ ?line ok = Test(Doc1,"/root/*",[{elem1,"2"},{elem1,"8"},{e,"12"}]),
+ ?line ok = Test(Doc1,"/root/e",[{e,"12"}]),
+ ?line ok = Test(Doc1,"//e",[{e,"12"},{e,"4"},{e,"6"},{e,"10"},{e,"11"}]),
+ ?line ok = Test(Doc1,"//*[name() != 'e']",
+ [{root,"1"},{elem1,"2"},{elem1,"8"},{elem2,"3"},
+ {elem3,"5"},{elem3,"7"},{elem2,"9"}]),
+ ?line ok = Test(Doc1,"//elem1/e",[{e,"10"},{e,"11"}]),
+ ?line ok = Test(Doc1,"//elem1//e",[{e,"4"},{e,"6"},{e,"10"},{e,"11"}]),
+ ?line ok = Test(Doc1,"//*[*]",
+ [{root,"1"},{elem1,"2"},{elem1,"8"},
+ {elem2,"3"},{elem3,"5"}]),
+ ?line ok = Test(Doc1,"//*[not(*)]",
+ [{e,"12"},{e,"4"},{elem3,"7"},{e,"6"},
+ {elem2,"9"},{e,"10"},{e,"11"}]),
+ %% contents would be empty in the above expression
+ ?line [#xmlElement{content=[]}|_] = xmerl_xpath:string("//*[not(*)]",Doc1),
+ ?line ok = Test(Doc1,"//*[e]",[{root,"1"},{elem1,"8"},{elem2,"3"},{elem3,"5"}]),
+ ?line ok = Test(Doc1,"//*[count(e)>1]",[{elem1,"8"}]),
+ ?line ok = Test(Doc1,"//*[not(e) and name() != 'e']",
+ [{elem1,"2"},{elem3,"7"},{elem2,"9"}]),
+ ?line ok = Test(Doc1,"/*/*/*/e",[{e,"4"}]),
+ ?line ok = Test(Doc1,"//*[starts-with(name(), 'el')]",
+ [{elem1,"2"},{elem1,"8"},{elem2,"3"},
+ {elem3,"5"},{elem3,"7"},{elem2,"9"}]),
+ ?line ok = Test(Doc1,"//*[contains(name(), 'lem1')]",
+ [{elem1,"2"},{elem1,"8"}]),
+ ?line ok = Test(Doc1,"/*/e | //elem2/e",[{e,"4"},{e,"12"}]),
+
+ io:format("Tested ~p~n",[e1074]),
+
+ Doc2 = get_doc("e1075"),
+ ?line ok = Test(Doc2,"/*/*[1]",[{elem1,"2"}]),
+ ?line ok = Test(Doc2,"/root/elem1[2]",[{elem1,"8"}]),
+
+ %% Get all first-born e elements in the document; that is, for all
+ %% e elements with e element siblings, include only the first
+ %% sibling.Note that //e[1] does not return the first e element in
+ %% the document because the [1] predicate applies to e, which
+ %% represents the set of e elements under one element and not to
+ %% //e, which represents the set of e elements in the document.
+ %% ?line ok = Test(Doc2,"//e[1]",[{e,"4"},{e,"6"},{e,"10"},{e,"12"}]),
+
+ %% The following expression retrieves the first e element in the
+ %% document:
+ %% ?line ok = Test(Doc2,"(//e)[1]",[{e,4}]),
+
+ %% For all e elements with e element siblings, include only the
+ %% first 3 siblings
+ %% ?line ok = Test(Doc2,"//e[position() <= 3]",[{e,"4"},{e,"6"},{e,"10"},{e,"11"},{e,"12"}]),
+
+ %% Get all last-born e elements in the document; that is, for all
+ %% e elements with e element siblings, include only the last
+ %% sibling
+ %% ?line ok = Test(Doc2,"//e[last()]",[{e,"4"},{e,"6"},{e,"11"},{e,"12"}]),
+
+ %% Get the last e element in the document
+ %% ?line ok = Test(Doc2,"(//e)[last()]", [{e,"12"}]),
+
+
+ io:format("Tested ~p~n",[e1075]),
+
+
+ Doc3 = get_doc("e1076"),
+ ?line ok = Test(Doc3,"//*[.='cat']",[{elem1,"2"},{elem3,"6"}]),
+ ?line ok = Test(Doc3,"//*[.='dog']",[]),
+ ?line ok = Test(Doc3,"//*[contains(.,'cat')]",
+ [{elem1,"2"},{elem1,"4"},{elem3,"6"}]),
+ ?line ok = Test(Doc3,"//elem3[contains(.,'cat')]",[{elem3,"6"}]),
+ ?line ok = Test(Doc3,"//*[contains(child::text(),'cat')]",[{elem1,"2"},{elem1,"4"},{elem3,"6"}]),
+ ?line ok = Test(Doc3,"//*[count(*)=0 and contains(.,'cat')]",[{elem1,"2"},{elem3,"6"}]),
+ ?line ok = Test(Doc3,"//*[contains(translate(.,'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'),'CAT')]",[{elem1,"2"},{elem1,"4"},{elem1,"7"},{elem3,"6"}]),
+
+ io:format("Tested ~p~n",[e1076]),
+
+ Doc4 = get_doc("e1078"),
+ ?line ok = Test(Doc4,"//*[@pet='cat']",[{elem1,"2"}]),
+ ?line ok = Test(Doc4,"//*[@pet='dog']",[{elem1,"7"}]),
+ ?line ok = Test(Doc4,"//*[contains(@pet,'dog')]",
+ [{elem1,"3"},{elem1,"7"}]),
+ ?line ok = Test(Doc4,"//*[@age]",[{elem1,"3"},{elem3,"6"}]),
+ ?line ok = Test(Doc4,"//elem1[@age]",[{elem1,"3"}]),
+ ?line ok = Test(Doc4,"//*[@pet and @age]",[{elem1,"3"}]),
+ ?line ok = Test(Doc4,"//*[contains(translate(@pet,'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'),'CAT')]",[{elem1,"2"},{elem1,"4"}]),
+
+ io:format("Tested ~p~n",[e1078]),
+
+
+ Doc5 = get_doc("e1077"),
+ ?line ok = Test(Doc5,"id('3')",[{e,"3"}]),
+
+ %% Get all e elements directly under element id 3
+ %% ?line ok = Test(Doc5,"id('two')/e",[{e,"3"},{e,"4"},{e,"6"}]),
+ ?line ok = Test(Doc5,"id('two 3 seven the fifth')",[{e,"seven"},{e,"3"},{e,"two"}]),
+ ?line ok = Test(Doc5,"id('100')",[]),
+
+ io:format("Tested ~p~n",[e1077]),
+ ok.
+
+
+
+get_doc(Name) ->
+ ?line {Doc,_} = xmerl_scan:file(Name++".xml"),
+ Doc.
diff --git a/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_text.erl b/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_text.erl
new file mode 100644
index 0000000000..e39ad6bcb0
--- /dev/null
+++ b/lib/xmerl/test/xmerl_SUITE_data/xpath/xpath_text.erl
@@ -0,0 +1,28 @@
+%%%-------------------------------------------------------------------
+%%% File : xpath_text.erl
+%%% Author : Bertil Karlsson <bertil@finrod>
+%%% Description :
+%%%
+%%% Created : 14 Dec 2004 by Bertil Karlsson <bertil@finrod>
+%%%-------------------------------------------------------------------
+-module(xpath_text).
+
+-compile(export_all).
+
+-include("test_server.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
+
+-import(xmerl_xs,
+ [ xslapply/2, value_of/1, select/2, built_in_rules/2 ]).
+
+
+one() ->
+ ?line {A,_}=xmerl_scan:file('motorcycles.xml'),
+ ?line [["Suzuki","Yamaha"]] = template(A),
+ ok.
+
+%%% templates, test of OTP-5268
+template(E = #xmlElement{name='motorcycles'}) ->
+ [value_of(select("bike/name/manufacturer/text()",E))];
+template(E) -> built_in_rules(fun template/1, E).
+
diff --git a/lib/xmerl/test/xmerl_app_test.erl b/lib/xmerl/test/xmerl_app_test.erl
new file mode 100644
index 0000000000..4cc4bf3791
--- /dev/null
+++ b/lib/xmerl/test/xmerl_app_test.erl
@@ -0,0 +1,242 @@
+%%
+%% %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: Verify the application specifics of the Megaco application
+%%----------------------------------------------------------------------
+-module(xmerl_app_test).
+
+-compile(export_all).
+
+%-include("megaco_test_lib.hrl").
+
+
+% t() -> megaco_test_lib:t(?MODULE).
+% t(Case) -> megaco_test_lib:t({?MODULE, Case}).
+
+
+% %% Test server callbacks
+% init_per_testcase(Case, Config) ->
+% megaco_test_lib:init_per_testcase(Case, Config).
+
+% end_per_testcase(Case, Config) ->
+% megaco_test_lib:end_per_testcase(Case, Config).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+all() ->
+ [fields, modules, exportall, app_depend].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+init_per_suite(suite) -> [];
+init_per_suite(doc) -> [];
+init_per_suite(Config) when is_list(Config) ->
+ case is_app(xmerl) of
+ {ok, AppFile} ->
+ io:format("AppFile: ~n~p~n", [AppFile]),
+ [{app_file, AppFile}|Config];
+ {error, Reason} ->
+ fail(Reason)
+ end.
+
+is_app(App) ->
+ LibDir = code:lib_dir(App),
+ File = filename:join([LibDir, "ebin", atom_to_list(App) ++ ".app"]),
+ case file:consult(File) of
+ {ok, [{application, App, AppFile}]} ->
+ {ok, AppFile};
+ Error ->
+ {error, {invalid_format, Error}}
+ end.
+
+
+end_per_suite(suite) -> [];
+end_per_suite(doc) -> [];
+end_per_suite(Config) when is_list(Config) ->
+ Config.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+fields(suite) ->
+ [];
+fields(doc) ->
+ [];
+fields(Config) when is_list(Config) ->
+ AppFile = key1search(app_file, Config),
+ Fields = [vsn, description, modules, registered, applications],
+ case check_fields(Fields, AppFile, []) of
+ [] ->
+ ok;
+ Missing ->
+ fail({missing_fields, Missing})
+ end.
+
+check_fields([], _AppFile, Missing) ->
+ Missing;
+check_fields([Field|Fields], AppFile, Missing) ->
+ check_fields(Fields, AppFile, check_field(Field, AppFile, Missing)).
+
+check_field(Name, AppFile, Missing) ->
+ io:format("checking field: ~p~n", [Name]),
+ case lists:keymember(Name, 1, AppFile) of
+ true ->
+ Missing;
+ false ->
+ [Name|Missing]
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+modules(suite) ->
+ [];
+modules(doc) ->
+ [];
+modules(Config) when is_list(Config) ->
+ AppFile = key1search(app_file, Config),
+ Mods = key1search(modules, AppFile),
+ EbinList = get_ebin_mods(xmerl),
+ case missing_modules(Mods, EbinList, []) of
+ [] ->
+ ok;
+ Missing ->
+ throw({error, {missing_modules, Missing}})
+ end,
+ case extra_modules(Mods, EbinList, []) of
+ [] ->
+ ok;
+ Extra ->
+ throw({error, {extra_modules, Extra}})
+ end,
+ {ok, Mods}.
+
+get_ebin_mods(App) ->
+ LibDir = code:lib_dir(App),
+ EbinDir = filename:join([LibDir,"ebin"]),
+ {ok, Files0} = file:list_dir(EbinDir),
+ Files1 = [lists:reverse(File) || File <- Files0],
+ [list_to_atom(lists:reverse(Name)) || [$m,$a,$e,$b,$.|Name] <- Files1].
+
+
+missing_modules([], _Ebins, Missing) ->
+ Missing;
+missing_modules([Mod|Mods], Ebins, Missing) ->
+ case lists:member(Mod, Ebins) of
+ true ->
+ missing_modules(Mods, Ebins, Missing);
+ false ->
+ io:format("missing module: ~p~n", [Mod]),
+ missing_modules(Mods, Ebins, [Mod|Missing])
+ end.
+
+
+extra_modules(_Mods, [], Extra) ->
+ Extra;
+extra_modules(Mods, [Mod|Ebins], Extra) ->
+ case lists:member(Mod, Mods) of
+ true ->
+ extra_modules(Mods, Ebins, Extra);
+ false ->
+ io:format("supefluous module: ~p~n", [Mod]),
+ extra_modules(Mods, Ebins, [Mod|Extra])
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+exportall(suite) ->
+ [];
+exportall(doc) ->
+ [];
+exportall(Config) when is_list(Config) ->
+ AppFile = key1search(app_file, Config),
+ Mods = key1search(modules, AppFile),
+ check_export_all(Mods).
+
+
+check_export_all([]) ->
+ ok;
+check_export_all([Mod|Mods]) ->
+ case (catch apply(Mod, module_info, [compile])) of
+ {'EXIT', {undef, _}} ->
+ check_export_all(Mods);
+ O ->
+ case lists:keysearch(options, 1, O) of
+ false ->
+ check_export_all(Mods);
+ {value, {options, List}} ->
+ case lists:member(export_all, List) of
+ true ->
+ throw({error, {export_all, Mod}});
+ false ->
+ check_export_all(Mods)
+ end
+ end
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+app_depend(suite) ->
+ [];
+app_depend(doc) ->
+ [];
+app_depend(Config) when is_list(Config) ->
+ AppFile = key1search(app_file, Config),
+ Apps = key1search(applications, AppFile),
+ check_apps(Apps).
+
+
+check_apps([]) ->
+ ok;
+check_apps([App|Apps]) ->
+ case is_app(App) of
+ {ok, _} ->
+ check_apps(Apps);
+ Error ->
+ throw({error, {missing_app, {App, Error}}})
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+fail(Reason) ->
+ exit({suite_failed, Reason}).
+
+key1search(Key, L) ->
+ case lists:keysearch(Key, 1, L) of
+ undefined ->
+ fail({not_found, Key, L});
+ {value, {Key, Value}} ->
+ Value
+ end.
diff --git a/lib/xmerl/test/xmerl_appup_test.erl b/lib/xmerl/test/xmerl_appup_test.erl
new file mode 100644
index 0000000000..80c8d8e4fd
--- /dev/null
+++ b/lib/xmerl/test/xmerl_appup_test.erl
@@ -0,0 +1,392 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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: Verify the application specifics of the Megaco application
+%%----------------------------------------------------------------------
+-module(xmerl_appup_test).
+
+-compile(export_all).
+
+%-include("megaco_test_lib.hrl").
+
+
+%t() -> megaco_test_lib:t(?MODULE).
+%t(Case) -> megaco_test_lib:t({?MODULE, Case}).
+
+
+%% Test server callbacks
+% init_per_testcase(Case, Config) ->
+% megaco_test_lib:init_per_testcase(Case, Config).
+
+% end_per_testcase(Case, Config) ->
+% megaco_test_lib:end_per_testcase(Case, Config).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+all() ->
+ [appup].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+init_per_suite(suite) -> [];
+init_per_suite(doc) -> [];
+init_per_suite(Config) when is_list(Config) ->
+ AppFile = file_name(xmerl, ".app"),
+ AppupFile = file_name(xmerl, ".appup"),
+ [{app_file, AppFile}, {appup_file, AppupFile}|Config].
+
+
+file_name(App, Ext) ->
+ LibDir = code:lib_dir(App),
+ filename:join([LibDir, "ebin", atom_to_list(App) ++ Ext]).
+
+
+end_per_suite(suite) -> [];
+end_per_suite(doc) -> [];
+end_per_suite(Config) when is_list(Config) ->
+ Config.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+appup(suite) ->
+ [];
+appup(doc) ->
+ "perform a simple check of the appup file";
+appup(Config) when is_list(Config) ->
+ AppupFile = key1search(appup_file, Config),
+ AppFile = key1search(app_file, Config),
+ Modules = modules(AppFile),
+ check_appup(AppupFile, Modules).
+
+modules(File) ->
+ case file:consult(File) of
+ {ok, [{application,xmerl,Info}]} ->
+ case lists:keysearch(modules,1,Info) of
+ {value, {modules, Modules}} ->
+ Modules;
+ false ->
+ fail({bad_appinfo, Info})
+ end;
+ Error ->
+ fail({bad_appfile, Error})
+ end.
+
+
+check_appup(AppupFile, Modules) ->
+ case file:consult(AppupFile) of
+ {ok, [{V, UpFrom, DownTo}]} ->
+ io:format("V= ~p, UpFrom= ~p, DownTo= ~p, Modules= ~p~n",
+ [V, UpFrom, DownTo, Modules]),
+ check_appup(V, UpFrom, DownTo, Modules);
+ Else ->
+ fail({bad_appupfile, Else})
+ end.
+
+
+check_appup(V, UpFrom, DownTo, Modules) ->
+ check_version(V),
+ check_depends(up, UpFrom, Modules),
+ check_depends(down, DownTo, Modules),
+ ok.
+
+
+check_depends(_, [], _) ->
+ ok;
+check_depends(UpDown, [Dep|Deps], Modules) ->
+ check_depend(UpDown, Dep, Modules),
+ check_depends(UpDown, Deps, Modules).
+
+
+check_depend(up,I={add_application, _App}, Modules) ->
+ d("check_instructions(~w) -> entry with"
+ "~n Instruction: ~p"
+ "~n Modules: ~p", [up,I , Modules]),
+ ok;
+check_depend(down,I={remove_application, _App}, Modules) ->
+ d("check_instructions(~w) -> entry with"
+ "~n Instruction: ~p"
+ "~n Modules: ~p", [down,I , Modules]),
+ ok;
+check_depend(UpDown, {V, Instructions}, Modules) ->
+ d("check_instructions(~w) -> entry with"
+ "~n V: ~p"
+ "~n Modules: ~p", [UpDown, V, Modules]),
+ check_version(V),
+ case check_instructions(UpDown,
+ Instructions, Instructions, [], [], Modules) of
+ {_Good, []} ->
+ ok;
+ {_, Bad} ->
+ fail({bad_instructions, Bad, UpDown})
+ end.
+
+
+check_instructions(_, [], _, Good, Bad, _) ->
+ {lists:reverse(Good), lists:reverse(Bad)};
+check_instructions(UpDown, [Instr|Instrs], AllInstr, Good, Bad, Modules) ->
+ d("check_instructions(~w) -> entry with"
+ "~n Instr: ~p", [UpDown,Instr]),
+ case (catch check_instruction(UpDown, Instr, AllInstr, Modules)) of
+ ok ->
+ check_instructions(UpDown, Instrs, AllInstr,
+ [Instr|Good], Bad, Modules);
+ {error, Reason} ->
+ d("check_instructions(~w) -> bad instruction: "
+ "~n Reason: ~p", [UpDown,Reason]),
+ check_instructions(UpDown, Instrs, AllInstr, Good,
+ [{Instr, Reason}|Bad], Modules)
+ end.
+
+%% A new module is added
+check_instruction(up, {add_module, Module}, _, Modules)
+ when is_atom(Module) ->
+ d("check_instruction -> entry when up-add_module instruction with"
+ "~n Module: ~p", [Module]),
+ check_module(Module, Modules);
+
+%% An old module is re-added
+check_instruction(down, {add_module, Module}, _, Modules)
+ when is_atom(Module) ->
+ d("check_instruction -> entry when down-add_module instruction with"
+ "~n Module: ~p", [Module]),
+ case (catch check_module(Module, Modules)) of
+ {error, {unknown_module, Module, Modules}} ->
+ ok;
+ ok ->
+ local_error({existing_readded_module, Module})
+ end;
+
+%% Removing a module on upgrade:
+%% - the module has been removed from the app-file.
+%% - check that no module depends on this (removed) module
+check_instruction(up, {remove, {Module, Pre, Post}}, _, Modules)
+ when is_atom(Module), is_atom(Pre), is_atom(Post) ->
+ d("check_instruction -> entry when up-remove instruction with"
+ "~n Module: ~p"
+ "~n Pre: ~p"
+ "~n Post: ~p", [Module, Pre, Post]),
+ case (catch check_module(Module, Modules)) of
+ {error, {unknown_module, Module, Modules}} ->
+ check_purge(Pre),
+ check_purge(Post);
+ ok ->
+ local_error({existing_removed_module, Module})
+ end;
+
+%% Removing a module on downgrade: the module exist
+%% in the app-file.
+check_instruction(down, {remove, {Module, Pre, Post}}, AllInstr, Modules)
+ when is_atom(Module), is_atom(Pre), is_atom(Post) ->
+ d("check_instruction -> entry when down-remove instruction with"
+ "~n Module: ~p"
+ "~n Pre: ~p"
+ "~n Post: ~p", [Module, Pre, Post]),
+ case (catch check_module(Module, Modules)) of
+ ok ->
+ check_purge(Pre),
+ check_purge(Post),
+ check_no_remove_depends(Module, AllInstr);
+ {error, {unknown_module, Module, Modules}} ->
+ local_error({nonexisting_removed_module, Module})
+ end;
+
+check_instruction(_, {load_module, Module, Pre, Post, Depend},
+ AllInstr, Modules)
+ when is_atom(Module), is_atom(Pre), is_atom(Post), is_list(Depend) ->
+ d("check_instruction -> entry when load_module instruction with"
+ "~n Module: ~p"
+ "~n Pre: ~p"
+ "~n Post: ~p"
+ "~n Depend: ~p", [Module, Pre, Post, Depend]),
+ check_module(Module, Modules),
+ check_module_depend(Module, Depend, Modules),
+ check_module_depend(Module, Depend, updated_modules(AllInstr, [])),
+ check_purge(Pre),
+ check_purge(Post);
+
+check_instruction(_, {update, Module, Change, Pre, Post, Depend},
+ AllInstr, Modules)
+ when is_atom(Module), is_atom(Pre), is_atom(Post), is_list(Depend) ->
+ d("check_instruction -> entry when update instruction with"
+ "~n Module: ~p"
+ "~n Change: ~p"
+ "~n Pre: ~p"
+ "~n Post: ~p"
+ "~n Depend: ~p", [Module, Change, Pre, Post, Depend]),
+ check_module(Module, Modules),
+ check_module_depend(Module, Depend, Modules),
+ check_module_depend(Module, Depend, updated_modules(AllInstr, [])),
+ check_change(Change),
+ check_purge(Pre),
+ check_purge(Post);
+
+check_instruction(_, Instr, _AllInstr, _Modules) ->
+ d("check_instruction -> entry when unknown instruction with"
+ "~n Instr: ~p", [Instr]),
+ local_error({error, {unknown_instruction, Instr}}).
+
+
+%% If Module X depends on Module Y, then module Y must have an update
+%% instruction of some sort (otherwise the depend is faulty).
+updated_modules([], Modules) ->
+ d("update_modules -> entry when done with"
+ "~n Modules: ~p", [Modules]),
+ Modules;
+updated_modules([Instr |Instrs], Modules) ->
+ d("update_modules -> entry with"
+ "~n Instr: ~p"
+ "~n Modules: ~p", [Instr,Modules]),
+ Module = instruction_module(Instr),
+ d("update_modules -> Module: ~p", [Module]),
+ updated_modules(Instrs, [Module|Modules]).
+
+instruction_module({add_module, Module}) ->
+ Module;
+instruction_module({remove, {Module, _, _}}) ->
+ Module;
+instruction_module({load_module, Module, _, _, _}) ->
+ Module;
+instruction_module({update, Module, _, _, _, _}) ->
+ Module;
+instruction_module(Instr) ->
+ d("instruction_module -> entry when unknown instruction with"
+ "~n Instr: ~p", [Instr]),
+ local_error({error, {unknown_instruction, Instr}}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+check_version(V) when is_list(V) ->
+ ok;
+check_version(V) ->
+ local_error({bad_version, V}).
+
+
+check_module(M, Modules) when is_atom(M) ->
+ case lists:member(M,Modules) of
+ true ->
+ ok;
+ false ->
+ local_error({unknown_module, M, Modules})
+ end;
+check_module(M, _) ->
+ local_error({bad_module, M}).
+
+
+check_module_depend(M, [], _) when is_atom(M) ->
+ d("check_module_depend -> entry with"
+ "~n M: ~p", [M]),
+ ok;
+check_module_depend(M, Deps, Modules) when is_atom(M), is_list(Deps) ->
+ d("check_module_depend -> entry with"
+ "~n M: ~p"
+ "~n Deps: ~p"
+ "~n Modules: ~p", [M, Deps, Modules]),
+ case [Dep || Dep <- Deps, lists:member(Dep, Modules) == false] of
+ [] ->
+ ok;
+ Unknown ->
+ local_error({unknown_depend_modules, Unknown})
+ end;
+check_module_depend(_M, D, _Modules) ->
+ d("check_module_depend -> entry when bad depend with"
+ "~n D: ~p", [D]),
+ local_error({bad_depend, D}).
+
+
+check_no_remove_depends(_Module, []) ->
+ ok;
+check_no_remove_depends(Module, [Instr|Instrs]) ->
+ check_no_remove_depend(Module, Instr),
+ check_no_remove_depends(Module, Instrs).
+
+check_no_remove_depend(Module, {load_module, Mod, _Pre, _Post, Depend}) ->
+ case lists:member(Module, Depend) of
+ true ->
+ local_error({removed_module_in_depend, load_module, Mod, Module});
+ false ->
+ ok
+ end;
+check_no_remove_depend(Module, {update, Mod, _Change, _Pre, _Post, Depend}) ->
+ case lists:member(Module, Depend) of
+ true ->
+ local_error({removed_module_in_depend, update, Mod, Module});
+ false ->
+ ok
+ end;
+check_no_remove_depend(_, _) ->
+ ok.
+
+
+check_change(soft) ->
+ ok;
+check_change({advanced, _Something}) ->
+ ok;
+check_change(Change) ->
+ local_error({bad_change, Change}).
+
+
+check_purge(soft_purge) ->
+ ok;
+check_purge(brutal_purge) ->
+ ok;
+check_purge(Purge) ->
+ local_error({bad_purge, Purge}).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+local_error(Reason) ->
+ throw({error, Reason}).
+
+fail(Reason) ->
+ exit({suite_failed, Reason}).
+
+key1search(Key, L) ->
+ case lists:keysearch(Key, 1, L) of
+ undefined ->
+ fail({not_found, Key, L});
+ {value, {Key, Value}} ->
+ Value
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+d(F, A) ->
+ d(false, F, A).
+
+d(true, F, A) ->
+ io:format(F ++ "~n", A);
+d(_, _, _) ->
+ ok.
+
+
diff --git a/lib/xmerl/test/xmerl_sax_SUITE.erl b/lib/xmerl/test/xmerl_sax_SUITE.erl
new file mode 100644
index 0000000000..563bbaaa06
--- /dev/null
+++ b/lib/xmerl/test/xmerl_sax_SUITE.erl
@@ -0,0 +1,110 @@
+%%-*-erlang-*-
+%%----------------------------------------------------------------------
+%% %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%
+%%----------------------------------------------------------------------
+%% File : xmerl_sax_SUITE.erl
+%% Created : 2009-06-01
+%%----------------------------------------------------------------------
+-module(xmerl_sax_SUITE).
+-compile(export_all).
+
+%%----------------------------------------------------------------------
+%% Include files
+%%----------------------------------------------------------------------
+-include_lib("test_server/include/test_server.hrl").
+-include_lib("kernel/include/file.hrl").
+
+%%======================================================================
+%% External functions
+%%======================================================================
+
+%%----------------------------------------------------------------------
+%% Initializations
+%%----------------------------------------------------------------------
+
+init_per_suite(doc) ->
+ ["Starts the test suite"];
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(doc) ->
+ ["Stops the test suite"];
+end_per_suite(Config) ->
+ Config.
+
+
+
+%% initialization before each testcase
+init_per_testcase(_TestCase,Config) ->
+ Config.
+
+%% clean up after each testcase
+end_per_testcase(_Func,_Config) ->
+ ok.
+
+%%----------------------------------------------------------------------
+%% Tests
+%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% ID: ticket_8213
+%% Description: Checks that end of document is checked properly when continuation fun is missing.
+ticket_8213(suite) -> [];
+ticket_8213(_Config) ->
+ ?line {ok,ok,[]} = xmerl_sax_parser:stream("<elem/>", [{event_fun, fun (_E,_,_) -> ok end}]).
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% ID: ticket_8214
+%% Description: Checks that attributes with default namespace don't get [] in NS field.
+ticket_8214(suite) -> [];
+ticket_8214(_Config) ->
+ ?line {ok,ok,[]} =
+ xmerl_sax_parser:stream("<elem attr='123' x:attr='234' xmlns='http://lshift.net/d' "
+ "xmlns:x='http://lshift.net/x' />",
+ [{event_fun, fun ({startElement,"http://lshift.net/d","elem",
+ {[],"elem"},
+ [{[],[],"attr","123"},{"http://lshift.net/x","x","attr","234"}]},
+ _, _) ->ok;
+ ({startElement, _, "elem",_,_}, _,_) ->
+ throw({test, "Error in startElement tuple"});
+ (_E,_,_) -> ok
+ end}]).
+
+%%----------------------------------------------------------------------
+%% Bug test cases
+%%
+
+%%----------------------------------------------------------------------
+%% Test Suite
+%%
+all() ->
+ [{group, bugs}].
+
+groups() ->
+ [{bugs, [], [ticket_8213, ticket_8214]}].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
diff --git a/lib/xmerl/test/xmerl_sax_std_SUITE.erl b/lib/xmerl/test/xmerl_sax_std_SUITE.erl
new file mode 100644
index 0000000000..2b7b59dacf
--- /dev/null
+++ b/lib/xmerl/test/xmerl_sax_std_SUITE.erl
@@ -0,0 +1,25635 @@
+
+%%----------------------------------------------------------------------
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 : xmerl_sax_std_SUITE.erl
+%% Created : 2009-06-01
+%%----------------------------------------------------------------------
+-module(xmerl_sax_std_SUITE).
+-compile(export_all).
+
+%%----------------------------------------------------------------------
+%% Include files
+%%----------------------------------------------------------------------
+-include_lib("test_server/include/test_server.hrl").
+-include_lib("kernel/include/file.hrl").
+
+%%======================================================================
+%% External functions
+%%======================================================================
+
+%%----------------------------------------------------------------------
+%% Initializations
+%%----------------------------------------------------------------------
+
+init_per_suite(doc) ->
+ ["Starts the test suite"];
+init_per_suite(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line ok=erl_tar:extract("ibm.tgz",[compressed]),
+ ?line ok=erl_tar:extract("japanese.tgz",[compressed]),
+ ?line ok=erl_tar:extract("oasis.tgz",[compressed]),
+ ?line ok=erl_tar:extract("sun.tgz",[compressed]),
+ ?line ok=erl_tar:extract("xmltest.tgz",[compressed]),
+ ?line ok = change_mode(["ibm","japanese","oasis",
+ "sun","xmltest"]),
+ Config.
+
+-ifndef(dont_rm_test_dirs).
+
+end_per_suite(doc) ->
+ ["Stops the test suite"];
+end_per_suite(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line ok=rm_files(["ibm","japanese","oasis","sun","xmltest"]),
+ Config.
+
+-else.
+
+end_per_suite(doc) ->
+ ["Stops the test suite"];
+end_per_suite(Config) ->
+ Config.
+
+-endif.
+
+%% initialization before each testcase
+init_per_testcase(_TestCase,Config) ->
+ io:format("Config:\n~p\n",[Config]),
+ ?line {ok, _} = file:read_file_info(filename:join([?config(priv_dir,Config)])),
+ ?line code:add_patha(?config(priv_dir,Config)),
+% Dog=test_server:timetrap({minutes,10}),
+% [{watchdog, Dog}|Config].
+ Config.
+
+%% clean up after each testcase
+end_per_testcase(_Func,_Config) ->
+% Dog=?config(watchdog, Config),
+% test_server:timetrap_cancel(Dog),
+ ok.
+
+%%----------------------------------------------------------------------
+%% Tests
+%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/001.xml
+%% ID: not-wf-sa-001
+%% Type: not-wf
+%% Sections: 3.1 [41]
+'not-wf-sa-001'(suite) -> [];
+'not-wf-sa-001'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/001.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/002.xml
+%% ID: not-wf-sa-002
+%% Type: not-wf
+%% Sections: 2.3 [4]
+'not-wf-sa-002'(suite) -> [];
+'not-wf-sa-002'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/002.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/003.xml
+%% ID: not-wf-sa-003
+%% Type: not-wf
+%% Sections: 2.6 [16]
+'not-wf-sa-003'(suite) -> [];
+'not-wf-sa-003'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/003.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/004.xml
+%% ID: not-wf-sa-004
+%% Type: not-wf
+%% Sections: 2.6 [16]
+'not-wf-sa-004'(suite) -> [];
+'not-wf-sa-004'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/004.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/005.xml
+%% ID: not-wf-sa-005
+%% Type: not-wf
+%% Sections: 2.6 [16]
+'not-wf-sa-005'(suite) -> [];
+'not-wf-sa-005'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/005.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/006.xml
+%% ID: not-wf-sa-006
+%% Type: not-wf
+%% Sections: 2.5 [16]
+'not-wf-sa-006'(suite) -> [];
+'not-wf-sa-006'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/006.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/007.xml
+%% ID: not-wf-sa-007
+%% Type: not-wf
+%% Sections: 4.1 [68]
+'not-wf-sa-007'(suite) -> [];
+'not-wf-sa-007'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/007.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/008.xml
+%% ID: not-wf-sa-008
+%% Type: not-wf
+%% Sections: 2.3 [5]
+'not-wf-sa-008'(suite) -> [];
+'not-wf-sa-008'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/008.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/009.xml
+%% ID: not-wf-sa-009
+%% Type: not-wf
+%% Sections: 4.1 [66]
+'not-wf-sa-009'(suite) -> [];
+'not-wf-sa-009'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/009.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/010.xml
+%% ID: not-wf-sa-010
+%% Type: not-wf
+%% Sections: 4.1 [68]
+'not-wf-sa-010'(suite) -> [];
+'not-wf-sa-010'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/010.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/011.xml
+%% ID: not-wf-sa-011
+%% Type: not-wf
+%% Sections: 3.1 [41]
+'not-wf-sa-011'(suite) -> [];
+'not-wf-sa-011'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/011.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/012.xml
+%% ID: not-wf-sa-012
+%% Type: not-wf
+%% Sections: 2.3 [10]
+'not-wf-sa-012'(suite) -> [];
+'not-wf-sa-012'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/012.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/013.xml
+%% ID: not-wf-sa-013
+%% Type: not-wf
+%% Sections: 2.3 [10]
+'not-wf-sa-013'(suite) -> [];
+'not-wf-sa-013'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/013.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/014.xml
+%% ID: not-wf-sa-014
+%% Type: not-wf
+%% Sections: 2.3 [10]
+'not-wf-sa-014'(suite) -> [];
+'not-wf-sa-014'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/014.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/015.xml
+%% ID: not-wf-sa-015
+%% Type: not-wf
+%% Sections: 3.1 [41]
+'not-wf-sa-015'(suite) -> [];
+'not-wf-sa-015'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/015.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/016.xml
+%% ID: not-wf-sa-016
+%% Type: not-wf
+%% Sections: 3.1 [41]
+'not-wf-sa-016'(suite) -> [];
+'not-wf-sa-016'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/016.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/017.xml
+%% ID: not-wf-sa-017
+%% Type: not-wf
+%% Sections: 2.7 [18]
+'not-wf-sa-017'(suite) -> [];
+'not-wf-sa-017'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/017.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/018.xml
+%% ID: not-wf-sa-018
+%% Type: not-wf
+%% Sections: 2.7 [19]
+'not-wf-sa-018'(suite) -> [];
+'not-wf-sa-018'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/018.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/019.xml
+%% ID: not-wf-sa-019
+%% Type: not-wf
+%% Sections: 3.1 [42]
+'not-wf-sa-019'(suite) -> [];
+'not-wf-sa-019'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/019.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/020.xml
+%% ID: not-wf-sa-020
+%% Type: not-wf
+%% Sections: 2.3 [10]
+'not-wf-sa-020'(suite) -> [];
+'not-wf-sa-020'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/020.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/021.xml
+%% ID: not-wf-sa-021
+%% Type: not-wf
+%% Sections: 2.3 [10]
+'not-wf-sa-021'(suite) -> [];
+'not-wf-sa-021'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/021.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/022.xml
+%% ID: not-wf-sa-022
+%% Type: not-wf
+%% Sections: 4.1 [66]
+'not-wf-sa-022'(suite) -> [];
+'not-wf-sa-022'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/022.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/023.xml
+%% ID: not-wf-sa-023
+%% Type: not-wf
+%% Sections: 2.3 [5]
+'not-wf-sa-023'(suite) -> [];
+'not-wf-sa-023'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/023.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/024.xml
+%% ID: not-wf-sa-024
+%% Type: not-wf
+%% Sections: 2.3 [5]
+'not-wf-sa-024'(suite) -> [];
+'not-wf-sa-024'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/024.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/025.xml
+%% ID: not-wf-sa-025
+%% Type: not-wf
+%% Sections: 2.4 [14]
+'not-wf-sa-025'(suite) -> [];
+'not-wf-sa-025'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/025.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/026.xml
+%% ID: not-wf-sa-026
+%% Type: not-wf
+%% Sections: 2.4 [14]
+'not-wf-sa-026'(suite) -> [];
+'not-wf-sa-026'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/026.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/027.xml
+%% ID: not-wf-sa-027
+%% Type: not-wf
+%% Sections: 2.5 [15]
+'not-wf-sa-027'(suite) -> [];
+'not-wf-sa-027'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/027.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/028.xml
+%% ID: not-wf-sa-028
+%% Type: not-wf
+%% Sections: 2.6 [16]
+'not-wf-sa-028'(suite) -> [];
+'not-wf-sa-028'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/028.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/029.xml
+%% ID: not-wf-sa-029
+%% Type: not-wf
+%% Sections: 2.4 [14]
+'not-wf-sa-029'(suite) -> [];
+'not-wf-sa-029'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/029.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/030.xml
+%% ID: not-wf-sa-030
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-030'(suite) -> [];
+'not-wf-sa-030'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/030.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/031.xml
+%% ID: not-wf-sa-031
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-031'(suite) -> [];
+'not-wf-sa-031'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/031.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/032.xml
+%% ID: not-wf-sa-032
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-032'(suite) -> [];
+'not-wf-sa-032'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/032.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/033.xml
+%% ID: not-wf-sa-033
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-033'(suite) -> [];
+'not-wf-sa-033'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/033.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/034.xml
+%% ID: not-wf-sa-034
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-034'(suite) -> [];
+'not-wf-sa-034'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/034.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/035.xml
+%% ID: not-wf-sa-035
+%% Type: not-wf
+%% Sections: 3.1 [43]
+'not-wf-sa-035'(suite) -> [];
+'not-wf-sa-035'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/035.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/036.xml
+%% ID: not-wf-sa-036
+%% Type: not-wf
+%% Sections: 2.8 [27]
+'not-wf-sa-036'(suite) -> [];
+'not-wf-sa-036'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/036.xml"]),
+ %% Special case becase we returns everything after a legal document
+ %% as an rest instead of giving and error to let the user handle
+ %% multipple docs on a stream.
+ ?line {ok,_,<<"Illegal data\r\n">>} = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]).
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/037.xml
+%% ID: not-wf-sa-037
+%% Type: not-wf
+%% Sections: 2.8 [27]
+'not-wf-sa-037'(suite) -> [];
+'not-wf-sa-037'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/037.xml"]),
+ %% Special case becase we returns everything after a legal document
+ %% as an rest instead of giving and error to let the user handle
+ %% multipple docs on a stream.
+ ?line {ok,_,<<"&#32;\r\n">>} = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]).
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/038.xml
+%% ID: not-wf-sa-038
+%% Type: not-wf
+%% Sections: 3.1
+'not-wf-sa-038'(suite) -> [];
+'not-wf-sa-038'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/038.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/039.xml
+%% ID: not-wf-sa-039
+%% Type: not-wf
+%% Sections: 3
+'not-wf-sa-039'(suite) -> [];
+'not-wf-sa-039'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/039.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/040.xml
+%% ID: not-wf-sa-040
+%% Type: not-wf
+%% Sections: 2.8 [27]
+'not-wf-sa-040'(suite) -> [];
+'not-wf-sa-040'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/040.xml"]),
+ %% Special case becase we returns everything after a legal document
+ %% as an rest instead of giving and error to let the user handle
+ %% multipple docs on a stream.
+ ?line {ok,_,<<"<doc></doc>\r\n">>} = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]).
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/041.xml
+%% ID: not-wf-sa-041
+%% Type: not-wf
+%% Sections: 2.8 [27]
+'not-wf-sa-041'(suite) -> [];
+'not-wf-sa-041'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/041.xml"]),
+ %% Special case becase we returns everything after a legal document
+ %% as an rest instead of giving and error to let the user handle
+ %% multipple docs on a stream.
+ ?line {ok,_,<<"<doc></doc>\r\n">>} = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]).
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/042.xml
+%% ID: not-wf-sa-042
+%% Type: not-wf
+%% Sections: 3.1 [42]
+'not-wf-sa-042'(suite) -> [];
+'not-wf-sa-042'(Config) -> {skip, "Fix 1"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/042.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/043.xml
+%% ID: not-wf-sa-043
+%% Type: not-wf
+%% Sections: 2.8 [27]
+'not-wf-sa-043'(suite) -> [];
+'not-wf-sa-043'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/043.xml"]),
+ %% Special case becase we returns everything after a legal document
+ %% as an rest instead of giving and error to let the user handle
+ %% multipple docs on a stream.
+ ?line {ok,_,<<"Illegal data\r\n">>} = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]).
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/044.xml
+%% ID: not-wf-sa-044
+%% Type: not-wf
+%% Sections: 2.8 [27]
+'not-wf-sa-044'(suite) -> [];
+'not-wf-sa-044'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/044.xml"]),
+ %% Special case becase we returns everything after a legal document
+ %% as an rest instead of giving and error to let the user handle
+ %% multipple docs on a stream.
+ ?line {ok,_,<<"<doc/>\r\n">>} = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]).
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/045.xml
+%% ID: not-wf-sa-045
+%% Type: not-wf
+%% Sections: 3.1 [44]
+'not-wf-sa-045'(suite) -> [];
+'not-wf-sa-045'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/045.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/046.xml
+%% ID: not-wf-sa-046
+%% Type: not-wf
+%% Sections: 3.1 [40]
+'not-wf-sa-046'(suite) -> [];
+'not-wf-sa-046'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/046.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/047.xml
+%% ID: not-wf-sa-047
+%% Type: not-wf
+%% Sections: 3.1 [44]
+'not-wf-sa-047'(suite) -> [];
+'not-wf-sa-047'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/047.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/048.xml
+%% ID: not-wf-sa-048
+%% Type: not-wf
+%% Sections: 2.8 [27]
+'not-wf-sa-048'(suite) -> [];
+'not-wf-sa-048'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/048.xml"]),
+ %% Special case becase we returns everything after a legal document
+ %% as an rest instead of giving and error to let the user handle
+ %% multipple docs on a stream.
+ ?line {ok,_,<<"<![CDATA[]]>\r\n">>} = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]).
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/049.xml
+%% ID: not-wf-sa-049
+%% Type: not-wf
+%% Sections: 3.1 [40]
+'not-wf-sa-049'(suite) -> [];
+'not-wf-sa-049'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/049.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/050.xml
+%% ID: not-wf-sa-050
+%% Type: not-wf
+%% Sections: 2.1 [1]
+'not-wf-sa-050'(suite) -> [];
+'not-wf-sa-050'(Config) -> {skip, "Fix 3"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/050.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/051.xml
+%% ID: not-wf-sa-051
+%% Type: not-wf
+%% Sections: 2.7 [18]
+'not-wf-sa-051'(suite) -> [];
+'not-wf-sa-051'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/051.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/052.xml
+%% ID: not-wf-sa-052
+%% Type: not-wf
+%% Sections: 4.1 [66]
+'not-wf-sa-052'(suite) -> [];
+'not-wf-sa-052'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/052.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/053.xml
+%% ID: not-wf-sa-053
+%% Type: not-wf
+%% Sections: 3.1 [42]
+'not-wf-sa-053'(suite) -> [];
+'not-wf-sa-053'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/053.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/054.xml
+%% ID: not-wf-sa-054
+%% Type: not-wf
+%% Sections: 4.2.2 [75]
+'not-wf-sa-054'(suite) -> [];
+'not-wf-sa-054'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/054.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/055.xml
+%% ID: not-wf-sa-055
+%% Type: not-wf
+%% Sections: 2.8 [28]
+'not-wf-sa-055'(suite) -> [];
+'not-wf-sa-055'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/055.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/056.xml
+%% ID: not-wf-sa-056
+%% Type: not-wf
+%% Sections: 2.8 [28]
+'not-wf-sa-056'(suite) -> [];
+'not-wf-sa-056'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/056.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/057.xml
+%% ID: not-wf-sa-057
+%% Type: not-wf
+%% Sections: 3.2 [45]
+'not-wf-sa-057'(suite) -> [];
+'not-wf-sa-057'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/057.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/058.xml
+%% ID: not-wf-sa-058
+%% Type: not-wf
+%% Sections: 3.3.1 [54]
+'not-wf-sa-058'(suite) -> [];
+'not-wf-sa-058'(_Config) -> {skip, "Attlist Notation parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/058.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/059.xml
+%% ID: not-wf-sa-059
+%% Type: not-wf
+%% Sections: 3.3.1 [59]
+'not-wf-sa-059'(suite) -> [];
+'not-wf-sa-059'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/059.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/060.xml
+%% ID: not-wf-sa-060
+%% Type: not-wf
+%% Sections: 3.3.1 [56]
+'not-wf-sa-060'(suite) -> [];
+'not-wf-sa-060'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/060.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/061.xml
+%% ID: not-wf-sa-061
+%% Type: not-wf
+%% Sections: 4.2.2 [75]
+'not-wf-sa-061'(suite) -> [];
+'not-wf-sa-061'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/061.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/062.xml
+%% ID: not-wf-sa-062
+%% Type: not-wf
+%% Sections: 4.2 [71]
+'not-wf-sa-062'(suite) -> [];
+'not-wf-sa-062'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/062.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/063.xml
+%% ID: not-wf-sa-063
+%% Type: not-wf
+%% Sections: 2.8 [29]
+'not-wf-sa-063'(suite) -> [];
+'not-wf-sa-063'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/063.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/064.xml
+%% ID: not-wf-sa-064
+%% Type: not-wf
+%% Sections: 3.3 [53]
+'not-wf-sa-064'(suite) -> [];
+'not-wf-sa-064'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/064.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/065.xml
+%% ID: not-wf-sa-065
+%% Type: not-wf
+%% Sections: 3.3 [53]
+'not-wf-sa-065'(suite) -> [];
+'not-wf-sa-065'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/065.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/066.xml
+%% ID: not-wf-sa-066
+%% Type: not-wf
+%% Sections: 3.3 [52]
+'not-wf-sa-066'(suite) -> [];
+'not-wf-sa-066'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/066.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/067.xml
+%% ID: not-wf-sa-067
+%% Type: not-wf
+%% Sections: 3.3 [53]
+'not-wf-sa-067'(suite) -> [];
+'not-wf-sa-067'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/067.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/068.xml
+%% ID: not-wf-sa-068
+%% Type: not-wf
+%% Sections: 3.3.1 [58]
+'not-wf-sa-068'(suite) -> [];
+'not-wf-sa-068'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/068.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/069.xml
+%% ID: not-wf-sa-069
+%% Type: not-wf
+%% Sections: 4.2.2 [76]
+'not-wf-sa-069'(suite) -> [];
+'not-wf-sa-069'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/069.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/070.xml
+%% ID: not-wf-sa-070
+%% Type: not-wf
+%% Sections: 2.5 [16]
+'not-wf-sa-070'(suite) -> [];
+'not-wf-sa-070'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/070.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/071.xml
+%% ID: not-wf-sa-071
+%% Type: not-wf
+%% Sections: 4.1 [68]
+'not-wf-sa-071'(suite) -> [];
+'not-wf-sa-071'(_Config) -> {skip, "No loop detection yet"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/071.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/072.xml
+%% ID: not-wf-sa-072
+%% Type: not-wf
+%% Sections: 4.1 [68]
+'not-wf-sa-072'(suite) -> [];
+'not-wf-sa-072'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/072.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/073.xml
+%% ID: not-wf-sa-073
+%% Type: not-wf
+%% Sections: 4.1 [68]
+'not-wf-sa-073'(suite) -> [];
+'not-wf-sa-073'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/073.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/074.xml
+%% ID: not-wf-sa-074
+%% Type: not-wf
+%% Sections: 4.3.2
+'not-wf-sa-074'(suite) -> [];
+'not-wf-sa-074'(_Config) -> {skip, "Entity not correct tag pair NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/074.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/075.xml
+%% ID: not-wf-sa-075
+%% Type: not-wf
+%% Sections: 4.1 [68]
+'not-wf-sa-075'(suite) -> [];
+'not-wf-sa-075'(_Config) -> {skip, "No loop detection yet"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/075.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/076.xml
+%% ID: not-wf-sa-076
+%% Type: not-wf
+%% Sections: 4.1 [68]
+'not-wf-sa-076'(suite) -> [];
+'not-wf-sa-076'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/076.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/077.xml
+%% ID: not-wf-sa-077
+%% Type: not-wf
+%% Sections: 41. [68]
+'not-wf-sa-077'(suite) -> [];
+'not-wf-sa-077'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/077.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/078.xml
+%% ID: not-wf-sa-078
+%% Type: not-wf
+%% Sections: 4.1 [68]
+'not-wf-sa-078'(suite) -> [];
+'not-wf-sa-078'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/078.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/079.xml
+%% ID: not-wf-sa-079
+%% Type: not-wf
+%% Sections: 4.1 [68]
+'not-wf-sa-079'(suite) -> [];
+'not-wf-sa-079'(_Config) -> {skip, "No loop detection yet"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/079.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/080.xml
+%% ID: not-wf-sa-080
+%% Type: not-wf
+%% Sections: 4.1 [68]
+'not-wf-sa-080'(suite) -> [];
+'not-wf-sa-080'(_Config) -> {skip, "No loop detection yet"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/080.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/081.xml
+%% ID: not-wf-sa-081
+%% Type: not-wf
+%% Sections: 3.1
+'not-wf-sa-081'(suite) -> [];
+'not-wf-sa-081'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/081.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/082.xml
+%% ID: not-wf-sa-082
+%% Type: not-wf
+%% Sections: 3.1
+'not-wf-sa-082'(suite) -> [];
+'not-wf-sa-082'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/082.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/083.xml
+%% ID: not-wf-sa-083
+%% Type: not-wf
+%% Sections: 4.2.2 [76]
+'not-wf-sa-083'(suite) -> [];
+'not-wf-sa-083'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/083.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/084.xml
+%% ID: not-wf-sa-084
+%% Type: not-wf
+%% Sections: 4.1
+'not-wf-sa-084'(suite) -> [];
+'not-wf-sa-084'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/084.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/085.xml
+%% ID: not-wf-sa-085
+%% Type: not-wf
+%% Sections: 2.3 [13]
+'not-wf-sa-085'(suite) -> [];
+'not-wf-sa-085'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/085.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/086.xml
+%% ID: not-wf-sa-086
+%% Type: not-wf
+%% Sections: 2.3 [13]
+'not-wf-sa-086'(suite) -> [];
+'not-wf-sa-086'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/086.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/087.xml
+%% ID: not-wf-sa-087
+%% Type: not-wf
+%% Sections: 2.3 [13]
+'not-wf-sa-087'(suite) -> [];
+'not-wf-sa-087'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/087.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/088.xml
+%% ID: not-wf-sa-088
+%% Type: not-wf
+%% Sections: 2.3 [10]
+'not-wf-sa-088'(suite) -> [];
+'not-wf-sa-088'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/088.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/089.xml
+%% ID: not-wf-sa-089
+%% Type: not-wf
+%% Sections: 4.2 [74]
+'not-wf-sa-089'(suite) -> [];
+'not-wf-sa-089'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/089.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/090.xml
+%% ID: not-wf-sa-090
+%% Type: not-wf
+%% Sections: 2.3 [10]
+'not-wf-sa-090'(suite) -> [];
+'not-wf-sa-090'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/090.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/091.xml
+%% ID: not-wf-sa-091
+%% Type: not-wf
+%% Sections: 4.2 [74]
+'not-wf-sa-091'(suite) -> [];
+'not-wf-sa-091'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/091.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/092.xml
+%% ID: not-wf-sa-092
+%% Type: not-wf
+%% Sections: 4.5
+'not-wf-sa-092'(suite) -> [];
+'not-wf-sa-092'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/092.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/093.xml
+%% ID: not-wf-sa-093
+%% Type: not-wf
+%% Sections: 4.1 [66]
+'not-wf-sa-093'(suite) -> [];
+'not-wf-sa-093'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/093.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/094.xml
+%% ID: not-wf-sa-094
+%% Type: not-wf
+%% Sections: 2.8 [24]
+'not-wf-sa-094'(suite) -> [];
+'not-wf-sa-094'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/094.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/095.xml
+%% ID: not-wf-sa-095
+%% Type: not-wf
+%% Sections: 2.8 [23]
+'not-wf-sa-095'(suite) -> [];
+'not-wf-sa-095'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/095.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/096.xml
+%% ID: not-wf-sa-096
+%% Type: not-wf
+%% Sections: 2.9 [32]
+'not-wf-sa-096'(suite) -> [];
+'not-wf-sa-096'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/096.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/097.xml
+%% ID: not-wf-sa-097
+%% Type: not-wf
+%% Sections: 2.8 [24]
+'not-wf-sa-097'(suite) -> [];
+'not-wf-sa-097'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/097.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/098.xml
+%% ID: not-wf-sa-098
+%% Type: not-wf
+%% Sections: 2.8 [23]
+'not-wf-sa-098'(suite) -> [];
+'not-wf-sa-098'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/098.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/099.xml
+%% ID: not-wf-sa-099
+%% Type: not-wf
+%% Sections: 2.8 [23]
+'not-wf-sa-099'(suite) -> [];
+'not-wf-sa-099'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/099.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/100.xml
+%% ID: not-wf-sa-100
+%% Type: not-wf
+%% Sections: 2.9 [32]
+'not-wf-sa-100'(suite) -> [];
+'not-wf-sa-100'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/100.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/101.xml
+%% ID: not-wf-sa-101
+%% Type: not-wf
+%% Sections: 4.3.3 [81]
+'not-wf-sa-101'(suite) -> [];
+'not-wf-sa-101'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/101.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/102.xml
+%% ID: not-wf-sa-102
+%% Type: not-wf
+%% Sections: 2.8 [26]
+'not-wf-sa-102'(suite) -> [];
+'not-wf-sa-102'(Config) -> {skip, "Fix 2"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/102.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/103.xml
+%% ID: not-wf-sa-103
+%% Type: not-wf
+%% Sections: 4.3.2
+'not-wf-sa-103'(suite) -> [];
+'not-wf-sa-103'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/103.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/104.xml
+%% ID: not-wf-sa-104
+%% Type: not-wf
+%% Sections: 4.3.2
+'not-wf-sa-104'(suite) -> [];
+'not-wf-sa-104'(_Config) -> {skip, "Entity not correct tag pair NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/104.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/105.xml
+%% ID: not-wf-sa-105
+%% Type: not-wf
+%% Sections: 2.7
+'not-wf-sa-105'(suite) -> [];
+'not-wf-sa-105'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/105.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/106.xml
+%% ID: not-wf-sa-106
+%% Type: not-wf
+%% Sections: 4.2
+'not-wf-sa-106'(suite) -> [];
+'not-wf-sa-106'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/106.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/107.xml
+%% ID: not-wf-sa-107
+%% Type: not-wf
+%% Sections: 2.8 [28]
+'not-wf-sa-107'(suite) -> [];
+'not-wf-sa-107'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/107.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/108.xml
+%% ID: not-wf-sa-108
+%% Type: not-wf
+%% Sections: 2.7 [19]
+'not-wf-sa-108'(suite) -> [];
+'not-wf-sa-108'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/108.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/109.xml
+%% ID: not-wf-sa-109
+%% Type: not-wf
+%% Sections: 4.2 [70]
+'not-wf-sa-109'(suite) -> [];
+'not-wf-sa-109'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/109.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/110.xml
+%% ID: not-wf-sa-110
+%% Type: not-wf
+%% Sections: 4.1 [68]
+'not-wf-sa-110'(suite) -> [];
+'not-wf-sa-110'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/110.xml"]),
+ %% Special case becase we returns everything after a legal document
+ %% as an rest instead of giving and error to let the user handle
+ %% multipple docs on a stream.
+ ?line {ok,_,<<"&e;\r\n">>} = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]).
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/111.xml
+%% ID: not-wf-sa-111
+%% Type: not-wf
+%% Sections: 3.1 [43]
+'not-wf-sa-111'(suite) -> [];
+'not-wf-sa-111'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/111.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/112.xml
+%% ID: not-wf-sa-112
+%% Type: not-wf
+%% Sections: 2.7 [19]
+'not-wf-sa-112'(suite) -> [];
+'not-wf-sa-112'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/112.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/113.xml
+%% ID: not-wf-sa-113
+%% Type: not-wf
+%% Sections: 2.3 [9]
+'not-wf-sa-113'(suite) -> [];
+'not-wf-sa-113'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/113.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/114.xml
+%% ID: not-wf-sa-114
+%% Type: not-wf
+%% Sections: 2.3 [9]
+'not-wf-sa-114'(suite) -> [];
+'not-wf-sa-114'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/114.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/115.xml
+%% ID: not-wf-sa-115
+%% Type: not-wf
+%% Sections: 4.5
+'not-wf-sa-115'(suite) -> [];
+'not-wf-sa-115'(_Config) -> {skip, "& expansion not correct"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/115.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/116.xml
+%% ID: not-wf-sa-116
+%% Type: not-wf
+%% Sections: 4.3.2
+'not-wf-sa-116'(suite) -> [];
+'not-wf-sa-116'(_Config) -> {skip, "& expansion not correct"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/116.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/117.xml
+%% ID: not-wf-sa-117
+%% Type: not-wf
+%% Sections: 4.3.2
+'not-wf-sa-117'(suite) -> [];
+'not-wf-sa-117'(_Config) -> {skip, "& expansion not correct"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/117.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/118.xml
+%% ID: not-wf-sa-118
+%% Type: not-wf
+%% Sections: 4.1 [68]
+'not-wf-sa-118'(suite) -> [];
+'not-wf-sa-118'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/118.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/119.xml
+%% ID: not-wf-sa-119
+%% Type: not-wf
+%% Sections: 4.3.2
+'not-wf-sa-119'(suite) -> [];
+'not-wf-sa-119'(_Config) -> {skip, "& expansion not correct"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/119.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/120.xml
+%% ID: not-wf-sa-120
+%% Type: not-wf
+%% Sections: 4.5
+'not-wf-sa-120'(suite) -> [];
+'not-wf-sa-120'(_Config) -> {skip, "& expansion not correct"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/120.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/121.xml
+%% ID: not-wf-sa-121
+%% Type: not-wf
+%% Sections: 4.1 [68]
+'not-wf-sa-121'(suite) -> [];
+'not-wf-sa-121'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/121.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/122.xml
+%% ID: not-wf-sa-122
+%% Type: not-wf
+%% Sections: 3.2.1 [47]
+'not-wf-sa-122'(suite) -> [];
+'not-wf-sa-122'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/122.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/123.xml
+%% ID: not-wf-sa-123
+%% Type: not-wf
+%% Sections: 3.2.1 [48]
+'not-wf-sa-123'(suite) -> [];
+'not-wf-sa-123'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/123.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/124.xml
+%% ID: not-wf-sa-124
+%% Type: not-wf
+%% Sections: 3.2.2 [51]
+'not-wf-sa-124'(suite) -> [];
+'not-wf-sa-124'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/124.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/125.xml
+%% ID: not-wf-sa-125
+%% Type: not-wf
+%% Sections: 3.2.2 [51]
+'not-wf-sa-125'(suite) -> [];
+'not-wf-sa-125'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/125.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/126.xml
+%% ID: not-wf-sa-126
+%% Type: not-wf
+%% Sections: 3.2.2 [51]
+'not-wf-sa-126'(suite) -> [];
+'not-wf-sa-126'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/126.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/127.xml
+%% ID: not-wf-sa-127
+%% Type: not-wf
+%% Sections: 3.2.2 [51]
+'not-wf-sa-127'(suite) -> [];
+'not-wf-sa-127'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/127.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/128.xml
+%% ID: not-wf-sa-128
+%% Type: not-wf
+%% Sections: 2.7 [18]
+'not-wf-sa-128'(suite) -> [];
+'not-wf-sa-128'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/128.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/129.xml
+%% ID: not-wf-sa-129
+%% Type: not-wf
+%% Sections: 3.2 [45]
+'not-wf-sa-129'(suite) -> [];
+'not-wf-sa-129'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/129.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/130.xml
+%% ID: not-wf-sa-130
+%% Type: not-wf
+%% Sections: 3.2 [45]
+'not-wf-sa-130'(suite) -> [];
+'not-wf-sa-130'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/130.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/131.xml
+%% ID: not-wf-sa-131
+%% Type: not-wf
+%% Sections: 3.2 [45]
+'not-wf-sa-131'(suite) -> [];
+'not-wf-sa-131'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/131.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/132.xml
+%% ID: not-wf-sa-132
+%% Type: not-wf
+%% Sections: 3.2.1 [50]
+'not-wf-sa-132'(suite) -> [];
+'not-wf-sa-132'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/132.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/133.xml
+%% ID: not-wf-sa-133
+%% Type: not-wf
+%% Sections: 3.2.1
+'not-wf-sa-133'(suite) -> [];
+'not-wf-sa-133'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/133.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/134.xml
+%% ID: not-wf-sa-134
+%% Type: not-wf
+%% Sections: 3.2.1
+'not-wf-sa-134'(suite) -> [];
+'not-wf-sa-134'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/134.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/135.xml
+%% ID: not-wf-sa-135
+%% Type: not-wf
+%% Sections: 3.2.1 [47]
+'not-wf-sa-135'(suite) -> [];
+'not-wf-sa-135'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/135.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/136.xml
+%% ID: not-wf-sa-136
+%% Type: not-wf
+%% Sections: 3.2 [45]
+'not-wf-sa-136'(suite) -> [];
+'not-wf-sa-136'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/136.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/137.xml
+%% ID: not-wf-sa-137
+%% Type: not-wf
+%% Sections: 3.2 [45]
+'not-wf-sa-137'(suite) -> [];
+'not-wf-sa-137'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/137.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/138.xml
+%% ID: not-wf-sa-138
+%% Type: not-wf
+%% Sections: 3.2.1 [48]
+'not-wf-sa-138'(suite) -> [];
+'not-wf-sa-138'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/138.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/139.xml
+%% ID: not-wf-sa-139
+%% Type: not-wf
+%% Sections: 3.2.1 [46]
+'not-wf-sa-139'(suite) -> [];
+'not-wf-sa-139'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/139.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/140.xml
+%% ID: not-wf-sa-140
+%% Type: not-wf
+%% Sections: 2.3 [4]
+'not-wf-sa-140'(suite) -> [];
+'not-wf-sa-140'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/140.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/141.xml
+%% ID: not-wf-sa-141
+%% Type: not-wf
+%% Sections: 2.3 [5]
+'not-wf-sa-141'(suite) -> [];
+'not-wf-sa-141'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/141.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/142.xml
+%% ID: not-wf-sa-142
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-142'(suite) -> [];
+'not-wf-sa-142'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/142.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/143.xml
+%% ID: not-wf-sa-143
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-143'(suite) -> [];
+'not-wf-sa-143'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/143.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/144.xml
+%% ID: not-wf-sa-144
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-144'(suite) -> [];
+'not-wf-sa-144'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/144.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/145.xml
+%% ID: not-wf-sa-145
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-145'(suite) -> [];
+'not-wf-sa-145'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/145.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/146.xml
+%% ID: not-wf-sa-146
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-146'(suite) -> [];
+'not-wf-sa-146'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/146.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/147.xml
+%% ID: not-wf-sa-147
+%% Type: not-wf
+%% Sections: 2.8 [22]
+'not-wf-sa-147'(suite) -> [];
+'not-wf-sa-147'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/147.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/148.xml
+%% ID: not-wf-sa-148
+%% Type: not-wf
+%% Sections: 2.8 [22]
+'not-wf-sa-148'(suite) -> [];
+'not-wf-sa-148'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/148.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/149.xml
+%% ID: not-wf-sa-149
+%% Type: not-wf
+%% Sections: 2.8 [28]
+'not-wf-sa-149'(suite) -> [];
+'not-wf-sa-149'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/149.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/150.xml
+%% ID: not-wf-sa-150
+%% Type: not-wf
+%% Sections: 3.1 [43]
+'not-wf-sa-150'(suite) -> [];
+'not-wf-sa-150'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/150.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/151.xml
+%% ID: not-wf-sa-151
+%% Type: not-wf
+%% Sections: 2.8 [27]
+'not-wf-sa-151'(suite) -> [];
+'not-wf-sa-151'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/151.xml"]),
+ %% Special case becase we returns everything after a legal document
+ %% as an rest instead of giving and error to let the user handle
+ %% multipple docs on a stream.
+ ?line {ok,_,<<"xml version=\"1.0\"?>\r\n">>} = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]).
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/152.xml
+%% ID: not-wf-sa-152
+%% Type: not-wf
+%% Sections: 2.8 [22]
+'not-wf-sa-152'(suite) -> [];
+'not-wf-sa-152'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/152.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/153.xml
+%% ID: not-wf-sa-153
+%% Type: not-wf
+%% Sections: 4.3.2
+'not-wf-sa-153'(suite) -> [];
+'not-wf-sa-153'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/153.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/154.xml
+%% ID: not-wf-sa-154
+%% Type: not-wf
+%% Sections: 2.8 2.6 [23, 17]
+'not-wf-sa-154'(suite) -> [];
+'not-wf-sa-154'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/154.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/155.xml
+%% ID: not-wf-sa-155
+%% Type: not-wf
+%% Sections: 2.8 2.6 [23, 17]
+'not-wf-sa-155'(suite) -> [];
+'not-wf-sa-155'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/155.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/156.xml
+%% ID: not-wf-sa-156
+%% Type: not-wf
+%% Sections: 2.8 2.6 [23, 17]
+'not-wf-sa-156'(suite) -> [];
+'not-wf-sa-156'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/156.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/157.xml
+%% ID: not-wf-sa-157
+%% Type: not-wf
+%% Sections: 2.6 [17]
+'not-wf-sa-157'(suite) -> [];
+'not-wf-sa-157'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/157.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/158.xml
+%% ID: not-wf-sa-158
+%% Type: not-wf
+%% Sections: 3.3 [52]
+'not-wf-sa-158'(suite) -> [];
+'not-wf-sa-158'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/158.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/159.xml
+%% ID: not-wf-sa-159
+%% Type: not-wf
+%% Sections: 2.3 [9]
+'not-wf-sa-159'(suite) -> [];
+'not-wf-sa-159'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/159.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/160.xml
+%% ID: not-wf-sa-160
+%% Type: not-wf
+%% Sections: 2.8
+'not-wf-sa-160'(suite) -> [];
+'not-wf-sa-160'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/160.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/161.xml
+%% ID: not-wf-sa-161
+%% Type: not-wf
+%% Sections: 2.8
+'not-wf-sa-161'(suite) -> [];
+'not-wf-sa-161'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/161.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/162.xml
+%% ID: not-wf-sa-162
+%% Type: not-wf
+%% Sections: 2.8
+'not-wf-sa-162'(suite) -> [];
+'not-wf-sa-162'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/162.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/163.xml
+%% ID: not-wf-sa-163
+%% Type: not-wf
+%% Sections: 4.1 [69]
+'not-wf-sa-163'(suite) -> [];
+'not-wf-sa-163'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/163.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/164.xml
+%% ID: not-wf-sa-164
+%% Type: not-wf
+%% Sections: 4.1 [69]
+'not-wf-sa-164'(suite) -> [];
+'not-wf-sa-164'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/164.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/165.xml
+%% ID: not-wf-sa-165
+%% Type: not-wf
+%% Sections: 4.2 [72]
+'not-wf-sa-165'(suite) -> [];
+'not-wf-sa-165'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/165.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/166.xml
+%% ID: not-wf-sa-166
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-166'(suite) -> [];
+'not-wf-sa-166'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/166.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/167.xml
+%% ID: not-wf-sa-167
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-167'(suite) -> [];
+'not-wf-sa-167'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/167.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/168.xml
+%% ID: not-wf-sa-168
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-168'(suite) -> [];
+'not-wf-sa-168'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/168.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/169.xml
+%% ID: not-wf-sa-169
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-169'(suite) -> [];
+'not-wf-sa-169'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/169.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/170.xml
+%% ID: not-wf-sa-170
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-170'(suite) -> [];
+'not-wf-sa-170'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/170.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/171.xml
+%% ID: not-wf-sa-171
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-171'(suite) -> [];
+'not-wf-sa-171'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/171.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/172.xml
+%% ID: not-wf-sa-172
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-172'(suite) -> [];
+'not-wf-sa-172'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/172.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/173.xml
+%% ID: not-wf-sa-173
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-173'(suite) -> [];
+'not-wf-sa-173'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/173.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/174.xml
+%% ID: not-wf-sa-174
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-174'(suite) -> [];
+'not-wf-sa-174'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/174.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/175.xml
+%% ID: not-wf-sa-175
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-175'(suite) -> [];
+'not-wf-sa-175'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/175.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/176.xml
+%% ID: not-wf-sa-176
+%% Type: not-wf
+%% Sections: 3 [39]
+'not-wf-sa-176'(suite) -> [];
+'not-wf-sa-176'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/176.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/177.xml
+%% ID: not-wf-sa-177
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'not-wf-sa-177'(suite) -> [];
+'not-wf-sa-177'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/177.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/178.xml
+%% ID: not-wf-sa-178
+%% Type: not-wf
+%% Sections: 3.1 [41]
+'not-wf-sa-178'(suite) -> [];
+'not-wf-sa-178'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/178.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/179.xml
+%% ID: not-wf-sa-179
+%% Type: not-wf
+%% Sections: 4.1 [66]
+'not-wf-sa-179'(suite) -> [];
+'not-wf-sa-179'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/179.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/180.xml
+%% ID: not-wf-sa-180
+%% Type: not-wf
+%% Sections: 4.1
+'not-wf-sa-180'(suite) -> [];
+'not-wf-sa-180'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/180.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/181.xml
+%% ID: not-wf-sa-181
+%% Type: not-wf
+%% Sections: 4.3.2
+'not-wf-sa-181'(suite) -> [];
+'not-wf-sa-181'(_Config) -> {skip, "Entity not tag pair NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/181.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/182.xml
+%% ID: not-wf-sa-182
+%% Type: not-wf
+%% Sections: 4.3.2
+'not-wf-sa-182'(suite) -> [];
+'not-wf-sa-182'(_Config) -> {skip, "Entity not tag pair NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/182.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/183.xml
+%% ID: not-wf-sa-183
+%% Type: not-wf
+%% Sections: 3.2.2 [51]
+'not-wf-sa-183'(suite) -> [];
+'not-wf-sa-183'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/183.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/184.xml
+%% ID: not-wf-sa-184
+%% Type: not-wf
+%% Sections: 3.2.2 [51]
+'not-wf-sa-184'(suite) -> [];
+'not-wf-sa-184'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/184.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/185.xml
+%% ID: not-wf-sa-185
+%% Type: not-wf
+%% Sections: 4.1
+'not-wf-sa-185'(suite) -> [];
+'not-wf-sa-185'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/185.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sa/186.xml
+%% ID: not-wf-sa-186
+%% Type: not-wf
+%% Sections: 3.1 [44]
+'not-wf-sa-186'(suite) -> [];
+'not-wf-sa-186'(Config) -> {skip, "Fix 2"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/sa/186.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/not-sa/001.xml
+%% ID: not-wf-not-sa-001
+%% Type: not-wf
+%% Sections: 3.4 [62]
+'not-wf-not-sa-001'(suite) -> [];
+'not-wf-not-sa-001'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/not-sa/001.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/not-sa/002.xml
+%% ID: not-wf-not-sa-002
+%% Type: not-wf
+%% Sections: 2.6 [17]
+'not-wf-not-sa-002'(suite) -> [];
+'not-wf-not-sa-002'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/not-sa/002.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/not-sa/003.xml
+%% ID: not-wf-not-sa-003
+%% Type: not-wf
+%% Sections: 3.4 [62]
+'not-wf-not-sa-003'(suite) -> [];
+'not-wf-not-sa-003'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/not-sa/003.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/not-sa/004.xml
+%% ID: not-wf-not-sa-004
+%% Type: not-wf
+%% Sections: 3.4 [62]
+'not-wf-not-sa-004'(suite) -> [];
+'not-wf-not-sa-004'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/not-sa/004.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/not-sa/005.xml
+%% ID: not-wf-not-sa-005
+%% Type: error
+%% Sections: 4.1
+'not-wf-not-sa-005'(suite) -> [];
+'not-wf-not-sa-005'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/not-sa/005.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "error").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/not-sa/006.xml
+%% ID: not-wf-not-sa-006
+%% Type: not-wf
+%% Sections: 3.4 [62]
+'not-wf-not-sa-006'(suite) -> [];
+'not-wf-not-sa-006'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/not-sa/006.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/not-sa/007.xml
+%% ID: not-wf-not-sa-007
+%% Type: not-wf
+%% Sections: 4.3.2 [79]
+'not-wf-not-sa-007'(suite) -> [];
+'not-wf-not-sa-007'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/not-sa/007.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/not-sa/008.xml
+%% ID: not-wf-not-sa-008
+%% Type: not-wf
+%% Sections: 4.1 [69]
+'not-wf-not-sa-008'(suite) -> [];
+'not-wf-not-sa-008'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/not-sa/008.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/not-sa/009.xml
+%% ID: not-wf-not-sa-009
+%% Type: not-wf
+%% Sections: 2.8
+'not-wf-not-sa-009'(suite) -> [];
+'not-wf-not-sa-009'(_Config) -> {skip, "not a complete content in PE NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/not-sa/009.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/ext-sa/001.xml
+%% ID: not-wf-ext-sa-001
+%% Type: not-wf
+%% Sections: 4.1
+'not-wf-ext-sa-001'(suite) -> [];
+'not-wf-ext-sa-001'(Config) -> {skip, "Fix 1"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/ext-sa/001.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/ext-sa/002.xml
+%% ID: not-wf-ext-sa-002
+%% Type: not-wf
+%% Sections: 4.3.1 4.3.2 [77, 78]
+'not-wf-ext-sa-002'(suite) -> [];
+'not-wf-ext-sa-002'(Config) -> {skip, "Fix 1"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/ext-sa/002.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/ext-sa/003.xml
+%% ID: not-wf-ext-sa-003
+%% Type: not-wf
+%% Sections: 2.6 [17]
+'not-wf-ext-sa-003'(suite) -> [];
+'not-wf-ext-sa-003'(Config) -> {skip, "Fix 1"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","not-wf/ext-sa/003.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/002.xml
+%% ID: invalid--002
+%% Type: invalid
+%% Sections: 3.2.1
+'invalid--002'(suite) -> [];
+'invalid--002'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","invalid/002.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/005.xml
+%% ID: invalid--005
+%% Type: invalid
+%% Sections: 2.8
+'invalid--005'(suite) -> [];
+'invalid--005'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","invalid/005.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/006.xml
+%% ID: invalid--006
+%% Type: invalid
+%% Sections: 2.8
+'invalid--006'(suite) -> [];
+'invalid--006'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","invalid/006.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/not-sa/022.xml
+%% ID: invalid-not-sa-022
+%% Type: invalid
+%% Sections: 3.4 [62]
+'invalid-not-sa-022'(suite) -> [];
+'invalid-not-sa-022'(_Config) -> {skip, "DTD element content parsing NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","invalid/not-sa/022.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/001.xml
+%% ID: valid-sa-001
+%% Type: valid
+%% Sections: 3.2.2 [51]
+'valid-sa-001'(suite) -> [];
+'valid-sa-001'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/001.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/002.xml
+%% ID: valid-sa-002
+%% Type: valid
+%% Sections: 3.1 [40]
+'valid-sa-002'(suite) -> [];
+'valid-sa-002'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/002.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/003.xml
+%% ID: valid-sa-003
+%% Type: valid
+%% Sections: 3.1 [42]
+'valid-sa-003'(suite) -> [];
+'valid-sa-003'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/003.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/004.xml
+%% ID: valid-sa-004
+%% Type: valid
+%% Sections: 3.1 [41]
+'valid-sa-004'(suite) -> [];
+'valid-sa-004'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/004.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/005.xml
+%% ID: valid-sa-005
+%% Type: valid
+%% Sections: 3.1 [40]
+'valid-sa-005'(suite) -> [];
+'valid-sa-005'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/005.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/006.xml
+%% ID: valid-sa-006
+%% Type: valid
+%% Sections: 3.1 [41]
+'valid-sa-006'(suite) -> [];
+'valid-sa-006'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/006.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/007.xml
+%% ID: valid-sa-007
+%% Type: valid
+%% Sections: 3.1 4.6 [43]
+'valid-sa-007'(suite) -> [];
+'valid-sa-007'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/007.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/008.xml
+%% ID: valid-sa-008
+%% Type: valid
+%% Sections: 2.4 3.1 [43]
+'valid-sa-008'(suite) -> [];
+'valid-sa-008'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/008.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/009.xml
+%% ID: valid-sa-009
+%% Type: valid
+%% Sections: 2.3 3.1 [43]
+'valid-sa-009'(suite) -> [];
+'valid-sa-009'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/009.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/010.xml
+%% ID: valid-sa-010
+%% Type: valid
+%% Sections: 3.1 [40]
+'valid-sa-010'(suite) -> [];
+'valid-sa-010'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/010.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/011.xml
+%% ID: valid-sa-011
+%% Type: valid
+%% Sections: 3.1 [40]
+'valid-sa-011'(suite) -> [];
+'valid-sa-011'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/011.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/012.xml
+%% ID: valid-sa-012
+%% Type: valid
+%% Sections: 2.3 [4]
+'valid-sa-012'(suite) -> [];
+'valid-sa-012'(Config) -> {skip, "Fix 1"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/012.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/013.xml
+%% ID: valid-sa-013
+%% Type: valid
+%% Sections: 2.3 3.1 [13] [40]
+'valid-sa-013'(suite) -> [];
+'valid-sa-013'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/013.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/014.xml
+%% ID: valid-sa-014
+%% Type: valid
+%% Sections: 2.3 3.1 [13] [40]
+'valid-sa-014'(suite) -> [];
+'valid-sa-014'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/014.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/015.xml
+%% ID: valid-sa-015
+%% Type: valid
+%% Sections: 2.3 3.1 [13] [40]
+'valid-sa-015'(suite) -> [];
+'valid-sa-015'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/015.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/016.xml
+%% ID: valid-sa-016
+%% Type: valid
+%% Sections: 2.6 3.1 [16] [43]
+'valid-sa-016'(suite) -> [];
+'valid-sa-016'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/016.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/017.xml
+%% ID: valid-sa-017
+%% Type: valid
+%% Sections: 2.6 3.1 [16] [43]
+'valid-sa-017'(suite) -> [];
+'valid-sa-017'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/017.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/018.xml
+%% ID: valid-sa-018
+%% Type: valid
+%% Sections: 2.7 3.1 [18] [43]
+'valid-sa-018'(suite) -> [];
+'valid-sa-018'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/018.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/019.xml
+%% ID: valid-sa-019
+%% Type: valid
+%% Sections: 2.7 3.1 [18] [43]
+'valid-sa-019'(suite) -> [];
+'valid-sa-019'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/019.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/020.xml
+%% ID: valid-sa-020
+%% Type: valid
+%% Sections: 2.7 3.1 [18] [43]
+'valid-sa-020'(suite) -> [];
+'valid-sa-020'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/020.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/021.xml
+%% ID: valid-sa-021
+%% Type: valid
+%% Sections: 2.5 3.1 [15] [43]
+'valid-sa-021'(suite) -> [];
+'valid-sa-021'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/021.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/022.xml
+%% ID: valid-sa-022
+%% Type: valid
+%% Sections: 2.5 3.1 [15] [43]
+'valid-sa-022'(suite) -> [];
+'valid-sa-022'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/022.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/023.xml
+%% ID: valid-sa-023
+%% Type: valid
+%% Sections: 3.1 [43]
+'valid-sa-023'(suite) -> [];
+'valid-sa-023'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/023.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/024.xml
+%% ID: valid-sa-024
+%% Type: valid
+%% Sections: 3.1 4.1 [43] [66]
+'valid-sa-024'(suite) -> [];
+'valid-sa-024'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/024.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/025.xml
+%% ID: valid-sa-025
+%% Type: valid
+%% Sections: 3.2 [46]
+'valid-sa-025'(suite) -> [];
+'valid-sa-025'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/025.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/026.xml
+%% ID: valid-sa-026
+%% Type: valid
+%% Sections: 3.2 [46]
+'valid-sa-026'(suite) -> [];
+'valid-sa-026'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/026.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/027.xml
+%% ID: valid-sa-027
+%% Type: valid
+%% Sections: 3.2 [46]
+'valid-sa-027'(suite) -> [];
+'valid-sa-027'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/027.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/028.xml
+%% ID: valid-sa-028
+%% Type: valid
+%% Sections: 2.8 [24]
+'valid-sa-028'(suite) -> [];
+'valid-sa-028'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/028.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/029.xml
+%% ID: valid-sa-029
+%% Type: valid
+%% Sections: 2.8 [24]
+'valid-sa-029'(suite) -> [];
+'valid-sa-029'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/029.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/030.xml
+%% ID: valid-sa-030
+%% Type: valid
+%% Sections: 2.8 [25]
+'valid-sa-030'(suite) -> [];
+'valid-sa-030'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/030.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/031.xml
+%% ID: valid-sa-031
+%% Type: valid
+%% Sections: 4.3.3 [80]
+'valid-sa-031'(suite) -> [];
+'valid-sa-031'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/031.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/032.xml
+%% ID: valid-sa-032
+%% Type: valid
+%% Sections: 2.9 [32]
+'valid-sa-032'(suite) -> [];
+'valid-sa-032'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/032.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/033.xml
+%% ID: valid-sa-033
+%% Type: valid
+%% Sections: 2.8 [23]
+'valid-sa-033'(suite) -> [];
+'valid-sa-033'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/033.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/034.xml
+%% ID: valid-sa-034
+%% Type: valid
+%% Sections: 3.1 [44]
+'valid-sa-034'(suite) -> [];
+'valid-sa-034'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/034.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/035.xml
+%% ID: valid-sa-035
+%% Type: valid
+%% Sections: 3.1 [44]
+'valid-sa-035'(suite) -> [];
+'valid-sa-035'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/035.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/036.xml
+%% ID: valid-sa-036
+%% Type: valid
+%% Sections: 2.6 [16]
+'valid-sa-036'(suite) -> [];
+'valid-sa-036'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/036.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/037.xml
+%% ID: valid-sa-037
+%% Type: valid
+%% Sections: 2.6 [15]
+'valid-sa-037'(suite) -> [];
+'valid-sa-037'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/037.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/038.xml
+%% ID: valid-sa-038
+%% Type: valid
+%% Sections: 2.6 [15]
+'valid-sa-038'(suite) -> [];
+'valid-sa-038'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/038.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/039.xml
+%% ID: valid-sa-039
+%% Type: valid
+%% Sections: 2.6 [16]
+'valid-sa-039'(suite) -> [];
+'valid-sa-039'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/039.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/040.xml
+%% ID: valid-sa-040
+%% Type: valid
+%% Sections: 3.3 3.3.1 [52] [54]
+'valid-sa-040'(suite) -> [];
+'valid-sa-040'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/040.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/041.xml
+%% ID: valid-sa-041
+%% Type: valid
+%% Sections: 3.3.1 4.1 [54] [66]
+'valid-sa-041'(suite) -> [];
+'valid-sa-041'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/041.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/042.xml
+%% ID: valid-sa-042
+%% Type: valid
+%% Sections: 3.3.1 4.1 [54] [66]
+'valid-sa-042'(suite) -> [];
+'valid-sa-042'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/042.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/043.xml
+%% ID: valid-sa-043
+%% Type: valid
+%% Sections: 3.3
+'valid-sa-043'(suite) -> [];
+'valid-sa-043'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/043.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/044.xml
+%% ID: valid-sa-044
+%% Type: valid
+%% Sections: 3.1 [44]
+'valid-sa-044'(suite) -> [];
+'valid-sa-044'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/044.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/045.xml
+%% ID: valid-sa-045
+%% Type: valid
+%% Sections: 3.3 [52]
+'valid-sa-045'(suite) -> [];
+'valid-sa-045'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/045.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/046.xml
+%% ID: valid-sa-046
+%% Type: valid
+%% Sections: 3.3 [52]
+'valid-sa-046'(suite) -> [];
+'valid-sa-046'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/046.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/047.xml
+%% ID: valid-sa-047
+%% Type: valid
+%% Sections: 3.1 [43]
+'valid-sa-047'(suite) -> [];
+'valid-sa-047'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/047.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/048.xml
+%% ID: valid-sa-048
+%% Type: valid
+%% Sections: 2.4 3.1 [14] [43]
+'valid-sa-048'(suite) -> [];
+'valid-sa-048'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/048.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/049.xml
+%% ID: valid-sa-049
+%% Type: valid
+%% Sections: 2.2 [2]
+'valid-sa-049'(suite) -> [];
+'valid-sa-049'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/049.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/050.xml
+%% ID: valid-sa-050
+%% Type: valid
+%% Sections: 2.2 [2]
+'valid-sa-050'(suite) -> [];
+'valid-sa-050'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/050.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/051.xml
+%% ID: valid-sa-051
+%% Type: valid
+%% Sections: 2.2 [2]
+'valid-sa-051'(suite) -> [];
+'valid-sa-051'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/051.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/052.xml
+%% ID: valid-sa-052
+%% Type: valid
+%% Sections: 2.2 [2]
+'valid-sa-052'(suite) -> [];
+'valid-sa-052'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/052.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/053.xml
+%% ID: valid-sa-053
+%% Type: valid
+%% Sections: 4.4.2
+'valid-sa-053'(suite) -> [];
+'valid-sa-053'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/053.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/054.xml
+%% ID: valid-sa-054
+%% Type: valid
+%% Sections: 3.1 [40] [42]
+'valid-sa-054'(suite) -> [];
+'valid-sa-054'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/054.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/055.xml
+%% ID: valid-sa-055
+%% Type: valid
+%% Sections: 2.6 2.10 [16]
+'valid-sa-055'(suite) -> [];
+'valid-sa-055'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/055.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/056.xml
+%% ID: valid-sa-056
+%% Type: valid
+%% Sections: 3.3.1 4.1 [54] [66]
+'valid-sa-056'(suite) -> [];
+'valid-sa-056'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/056.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/057.xml
+%% ID: valid-sa-057
+%% Type: valid
+%% Sections: 3.2.1 [47]
+'valid-sa-057'(suite) -> [];
+'valid-sa-057'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/057.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/058.xml
+%% ID: valid-sa-058
+%% Type: valid
+%% Sections: 3.3.3
+'valid-sa-058'(suite) -> [];
+'valid-sa-058'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/058.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/059.xml
+%% ID: valid-sa-059
+%% Type: valid
+%% Sections: 3.2 3.3 [46] [53]
+'valid-sa-059'(suite) -> [];
+'valid-sa-059'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/059.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/060.xml
+%% ID: valid-sa-060
+%% Type: valid
+%% Sections: 4.1 [66]
+'valid-sa-060'(suite) -> [];
+'valid-sa-060'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/060.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/061.xml
+%% ID: valid-sa-061
+%% Type: valid
+%% Sections: 4.1 [66]
+'valid-sa-061'(suite) -> [];
+'valid-sa-061'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/061.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/062.xml
+%% ID: valid-sa-062
+%% Type: valid
+%% Sections: 4.1 [66]
+'valid-sa-062'(suite) -> [];
+'valid-sa-062'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/062.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/063.xml
+%% ID: valid-sa-063
+%% Type: valid
+%% Sections: 2.3 [5]
+'valid-sa-063'(suite) -> [];
+'valid-sa-063'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/063.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/064.xml
+%% ID: valid-sa-064
+%% Type: valid
+%% Sections: 4.1 [66]
+'valid-sa-064'(suite) -> [];
+'valid-sa-064'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/064.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/065.xml
+%% ID: valid-sa-065
+%% Type: valid
+%% Sections: 4.5
+'valid-sa-065'(suite) -> [];
+'valid-sa-065'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/065.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/066.xml
+%% ID: valid-sa-066
+%% Type: valid
+%% Sections: 4.1 [66]
+'valid-sa-066'(suite) -> [];
+'valid-sa-066'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/066.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/067.xml
+%% ID: valid-sa-067
+%% Type: valid
+%% Sections: 4.1 [66]
+'valid-sa-067'(suite) -> [];
+'valid-sa-067'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/067.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/068.xml
+%% ID: valid-sa-068
+%% Type: valid
+%% Sections: 2.11, 4.5
+'valid-sa-068'(suite) -> [];
+'valid-sa-068'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/068.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/069.xml
+%% ID: valid-sa-069
+%% Type: valid
+%% Sections: 4.7
+'valid-sa-069'(suite) -> [];
+'valid-sa-069'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/069.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/070.xml
+%% ID: valid-sa-070
+%% Type: valid
+%% Sections: 4.4.8
+'valid-sa-070'(suite) -> [];
+'valid-sa-070'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/070.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/071.xml
+%% ID: valid-sa-071
+%% Type: valid
+%% Sections: 3.3 3.3.1 [52] [56]
+'valid-sa-071'(suite) -> [];
+'valid-sa-071'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/071.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/072.xml
+%% ID: valid-sa-072
+%% Type: valid
+%% Sections: 3.3 3.3.1 [52] [56]
+'valid-sa-072'(suite) -> [];
+'valid-sa-072'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/072.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/073.xml
+%% ID: valid-sa-073
+%% Type: valid
+%% Sections: 3.3 3.3.1 [52] [56]
+'valid-sa-073'(suite) -> [];
+'valid-sa-073'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/073.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/074.xml
+%% ID: valid-sa-074
+%% Type: valid
+%% Sections: 3.3 3.3.1 [52] [56]
+'valid-sa-074'(suite) -> [];
+'valid-sa-074'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/074.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/075.xml
+%% ID: valid-sa-075
+%% Type: valid
+%% Sections: 3.3 3.3.1 [52] [56]
+'valid-sa-075'(suite) -> [];
+'valid-sa-075'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/075.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/076.xml
+%% ID: valid-sa-076
+%% Type: valid
+%% Sections: 3.3.1
+'valid-sa-076'(suite) -> [];
+'valid-sa-076'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/076.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/077.xml
+%% ID: valid-sa-077
+%% Type: valid
+%% Sections: 3.3 3.3.1 [52] [54]
+'valid-sa-077'(suite) -> [];
+'valid-sa-077'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/077.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/078.xml
+%% ID: valid-sa-078
+%% Type: valid
+%% Sections: 3.3 3.3.1 [52] [54]
+'valid-sa-078'(suite) -> [];
+'valid-sa-078'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/078.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/079.xml
+%% ID: valid-sa-079
+%% Type: valid
+%% Sections: 3.3 3.3.2 [52] [60]
+'valid-sa-079'(suite) -> [];
+'valid-sa-079'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/079.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/080.xml
+%% ID: valid-sa-080
+%% Type: valid
+%% Sections: 3.3 3.3.2 [52] [60]
+'valid-sa-080'(suite) -> [];
+'valid-sa-080'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/080.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/081.xml
+%% ID: valid-sa-081
+%% Type: valid
+%% Sections: 3.2.1 [50]
+'valid-sa-081'(suite) -> [];
+'valid-sa-081'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/081.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/082.xml
+%% ID: valid-sa-082
+%% Type: valid
+%% Sections: 4.2 [72]
+'valid-sa-082'(suite) -> [];
+'valid-sa-082'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/082.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/083.xml
+%% ID: valid-sa-083
+%% Type: valid
+%% Sections: 4.2 [72]
+'valid-sa-083'(suite) -> [];
+'valid-sa-083'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/083.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/084.xml
+%% ID: valid-sa-084
+%% Type: valid
+%% Sections: 2.10
+'valid-sa-084'(suite) -> [];
+'valid-sa-084'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/084.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/085.xml
+%% ID: valid-sa-085
+%% Type: valid
+%% Sections: 4
+'valid-sa-085'(suite) -> [];
+'valid-sa-085'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/085.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/086.xml
+%% ID: valid-sa-086
+%% Type: valid
+%% Sections: 4.2
+'valid-sa-086'(suite) -> [];
+'valid-sa-086'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/086.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/087.xml
+%% ID: valid-sa-087
+%% Type: valid
+%% Sections: 4.5
+'valid-sa-087'(suite) -> [];
+'valid-sa-087'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/087.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/088.xml
+%% ID: valid-sa-088
+%% Type: valid
+%% Sections: 4.5
+'valid-sa-088'(suite) -> [];
+'valid-sa-088'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/088.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/089.xml
+%% ID: valid-sa-089
+%% Type: valid
+%% Sections: 4.1 [66]
+'valid-sa-089'(suite) -> [];
+'valid-sa-089'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/089.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/090.xml
+%% ID: valid-sa-090
+%% Type: valid
+%% Sections: 3.3.1
+'valid-sa-090'(suite) -> [];
+'valid-sa-090'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/090.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/091.xml
+%% ID: valid-sa-091
+%% Type: valid
+%% Sections: 3.3.1
+'valid-sa-091'(suite) -> [];
+'valid-sa-091'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/091.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/092.xml
+%% ID: valid-sa-092
+%% Type: valid
+%% Sections: 2.3 2.10
+'valid-sa-092'(suite) -> [];
+'valid-sa-092'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/092.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/093.xml
+%% ID: valid-sa-093
+%% Type: valid
+%% Sections: 2.10
+'valid-sa-093'(suite) -> [];
+'valid-sa-093'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/093.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/094.xml
+%% ID: valid-sa-094
+%% Type: valid
+%% Sections: 2.8
+'valid-sa-094'(suite) -> [];
+'valid-sa-094'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/094.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/095.xml
+%% ID: valid-sa-095
+%% Type: valid
+%% Sections: 3.3.3
+'valid-sa-095'(suite) -> [];
+'valid-sa-095'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/095.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/096.xml
+%% ID: valid-sa-096
+%% Type: valid
+%% Sections: 3.3.3
+'valid-sa-096'(suite) -> [];
+'valid-sa-096'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/096.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/097.xml
+%% ID: valid-sa-097
+%% Type: valid
+%% Sections: 3.3
+'valid-sa-097'(suite) -> [];
+'valid-sa-097'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/097.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/098.xml
+%% ID: valid-sa-098
+%% Type: valid
+%% Sections: 2.6 2.10 [16]
+'valid-sa-098'(suite) -> [];
+'valid-sa-098'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/098.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/099.xml
+%% ID: valid-sa-099
+%% Type: valid
+%% Sections: 4.3.3 [81]
+'valid-sa-099'(suite) -> [];
+'valid-sa-099'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/099.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/100.xml
+%% ID: valid-sa-100
+%% Type: valid
+%% Sections: 2.3 [12]
+'valid-sa-100'(suite) -> [];
+'valid-sa-100'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/100.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/101.xml
+%% ID: valid-sa-101
+%% Type: valid
+%% Sections: 4.5
+'valid-sa-101'(suite) -> [];
+'valid-sa-101'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/101.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/102.xml
+%% ID: valid-sa-102
+%% Type: valid
+%% Sections: 3.3.3
+'valid-sa-102'(suite) -> [];
+'valid-sa-102'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/102.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/103.xml
+%% ID: valid-sa-103
+%% Type: valid
+%% Sections: 3.3.3
+'valid-sa-103'(suite) -> [];
+'valid-sa-103'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/103.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/104.xml
+%% ID: valid-sa-104
+%% Type: valid
+%% Sections: 3.1 [40]
+'valid-sa-104'(suite) -> [];
+'valid-sa-104'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/104.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/105.xml
+%% ID: valid-sa-105
+%% Type: valid
+%% Sections: 3.3.3
+'valid-sa-105'(suite) -> [];
+'valid-sa-105'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/105.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/106.xml
+%% ID: valid-sa-106
+%% Type: valid
+%% Sections: 3.3.3
+'valid-sa-106'(suite) -> [];
+'valid-sa-106'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/106.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/107.xml
+%% ID: valid-sa-107
+%% Type: valid
+%% Sections: 3.3.3
+'valid-sa-107'(suite) -> [];
+'valid-sa-107'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/107.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/108.xml
+%% ID: valid-sa-108
+%% Type: valid
+%% Sections: 2.11, 3.3.3
+'valid-sa-108'(suite) -> [];
+'valid-sa-108'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/108.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/109.xml
+%% ID: valid-sa-109
+%% Type: valid
+%% Sections: 2.3 3.1 [10][40][41]
+'valid-sa-109'(suite) -> [];
+'valid-sa-109'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/109.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/110.xml
+%% ID: valid-sa-110
+%% Type: valid
+%% Sections: 3.3.3
+'valid-sa-110'(suite) -> [];
+'valid-sa-110'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/110.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/111.xml
+%% ID: valid-sa-111
+%% Type: valid
+%% Sections: 3.3.3
+'valid-sa-111'(suite) -> [];
+'valid-sa-111'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/111.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/112.xml
+%% ID: valid-sa-112
+%% Type: valid
+%% Sections: 3.2.1 [48][49]
+'valid-sa-112'(suite) -> [];
+'valid-sa-112'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/112.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/113.xml
+%% ID: valid-sa-113
+%% Type: valid
+%% Sections: 3.3 [52][53]
+'valid-sa-113'(suite) -> [];
+'valid-sa-113'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/113.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/114.xml
+%% ID: valid-sa-114
+%% Type: valid
+%% Sections: 2.7 [20]
+'valid-sa-114'(suite) -> [];
+'valid-sa-114'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/114.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/115.xml
+%% ID: valid-sa-115
+%% Type: valid
+%% Sections: 3.3.3
+'valid-sa-115'(suite) -> [];
+'valid-sa-115'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/115.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/116.xml
+%% ID: valid-sa-116
+%% Type: valid
+%% Sections: 2.11
+'valid-sa-116'(suite) -> [];
+'valid-sa-116'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/116.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/117.xml
+%% ID: valid-sa-117
+%% Type: valid
+%% Sections: 4.5
+'valid-sa-117'(suite) -> [];
+'valid-sa-117'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/117.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/118.xml
+%% ID: valid-sa-118
+%% Type: valid
+%% Sections: 4.5
+'valid-sa-118'(suite) -> [];
+'valid-sa-118'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/118.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa/119.xml
+%% ID: valid-sa-119
+%% Type: valid
+%% Sections: 2.5
+'valid-sa-119'(suite) -> [];
+'valid-sa-119'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/sa/119.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/001.xml
+%% ID: valid-not-sa-001
+%% Type: valid
+%% Sections: 4.2.2 [75]
+'valid-not-sa-001'(suite) -> [];
+'valid-not-sa-001'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/001.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/002.xml
+%% ID: valid-not-sa-002
+%% Type: valid
+%% Sections: 4.2.2 [75]
+'valid-not-sa-002'(suite) -> [];
+'valid-not-sa-002'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/002.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/003.xml
+%% ID: valid-not-sa-003
+%% Type: valid
+%% Sections: 4.1 [69]
+'valid-not-sa-003'(suite) -> [];
+'valid-not-sa-003'(_Config) -> {skip, "external entity NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/003.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/004.xml
+%% ID: valid-not-sa-004
+%% Type: valid
+%% Sections: 4.1 [69]
+'valid-not-sa-004'(suite) -> [];
+'valid-not-sa-004'(_Config) -> {skip, "external entity NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/004.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/005.xml
+%% ID: valid-not-sa-005
+%% Type: valid
+%% Sections: 4.1 [69]
+'valid-not-sa-005'(suite) -> [];
+'valid-not-sa-005'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/005.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/006.xml
+%% ID: valid-not-sa-006
+%% Type: valid
+%% Sections: 3.3 [52]
+'valid-not-sa-006'(suite) -> [];
+'valid-not-sa-006'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/006.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/007.xml
+%% ID: valid-not-sa-007
+%% Type: valid
+%% Sections: 3.3 [52]
+'valid-not-sa-007'(suite) -> [];
+'valid-not-sa-007'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/007.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/008.xml
+%% ID: valid-not-sa-008
+%% Type: valid
+%% Sections: 4.2.2 [75]
+'valid-not-sa-008'(suite) -> [];
+'valid-not-sa-008'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/008.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/009.xml
+%% ID: valid-not-sa-009
+%% Type: valid
+%% Sections: 4.2.2 [75]
+'valid-not-sa-009'(suite) -> [];
+'valid-not-sa-009'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/009.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/010.xml
+%% ID: valid-not-sa-010
+%% Type: valid
+%% Sections: 3.3 [52]
+'valid-not-sa-010'(suite) -> [];
+'valid-not-sa-010'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/010.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/011.xml
+%% ID: valid-not-sa-011
+%% Type: valid
+%% Sections: 4.2 4.2.1 [72] [75]
+'valid-not-sa-011'(suite) -> [];
+'valid-not-sa-011'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/011.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/012.xml
+%% ID: valid-not-sa-012
+%% Type: valid
+%% Sections: 4.3.1 [77]
+'valid-not-sa-012'(suite) -> [];
+'valid-not-sa-012'(Config) -> {skip, "Fix 3"}.
+ %% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/012.xml"]),
+ %% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/013.xml
+%% ID: valid-not-sa-013
+%% Type: valid
+%% Sections: 3.4 [62]
+'valid-not-sa-013'(suite) -> [];
+'valid-not-sa-013'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/013.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/014.xml
+%% ID: valid-not-sa-014
+%% Type: valid
+%% Sections: 3.4 [62]
+'valid-not-sa-014'(suite) -> [];
+'valid-not-sa-014'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/014.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/015.xml
+%% ID: valid-not-sa-015
+%% Type: valid
+%% Sections: 3.4 [63]
+'valid-not-sa-015'(suite) -> [];
+'valid-not-sa-015'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/015.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/016.xml
+%% ID: valid-not-sa-016
+%% Type: valid
+%% Sections: 3.4 [62]
+'valid-not-sa-016'(suite) -> [];
+'valid-not-sa-016'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/016.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/017.xml
+%% ID: valid-not-sa-017
+%% Type: valid
+%% Sections: 4.2 [72]
+'valid-not-sa-017'(suite) -> [];
+'valid-not-sa-017'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/017.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/018.xml
+%% ID: valid-not-sa-018
+%% Type: valid
+%% Sections: 4.2.2 [75]
+'valid-not-sa-018'(suite) -> [];
+'valid-not-sa-018'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/018.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/019.xml
+%% ID: valid-not-sa-019
+%% Type: valid
+%% Sections: 4.4.8
+'valid-not-sa-019'(suite) -> [];
+'valid-not-sa-019'(_Config) -> {skip, "partly replacement of markupdecls"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/019.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/020.xml
+%% ID: valid-not-sa-020
+%% Type: valid
+%% Sections: 4.4.8
+'valid-not-sa-020'(suite) -> [];
+'valid-not-sa-020'(_Config) -> {skip, "partly replacement of markupdecls"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/020.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/021.xml
+%% ID: valid-not-sa-021
+%% Type: valid
+%% Sections: 4.2 [72]
+'valid-not-sa-021'(suite) -> [];
+'valid-not-sa-021'(_Config) -> {skip, "partly replacement of markupdecls"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/021.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/023.xml
+%% ID: valid-not-sa-023
+%% Type: valid
+%% Sections: 2.3 4.1 [10] [69]
+'valid-not-sa-023'(suite) -> [];
+'valid-not-sa-023'(_Config) -> {skip, "partly replacement of markupdecls"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/023.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/024.xml
+%% ID: valid-not-sa-024
+%% Type: valid
+%% Sections: 2.8, 4.1 [69]
+'valid-not-sa-024'(suite) -> [];
+'valid-not-sa-024'(_Config) -> {skip, "partly replacement of markupdecls"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/024.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/025.xml
+%% ID: valid-not-sa-025
+%% Type: valid
+%% Sections: 4.2
+'valid-not-sa-025'(suite) -> [];
+'valid-not-sa-025'(_Config) -> {skip, "partly replacement of markupdecls"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/025.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/026.xml
+%% ID: valid-not-sa-026
+%% Type: valid
+%% Sections: 3.3 [52]
+'valid-not-sa-026'(suite) -> [];
+'valid-not-sa-026'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/026.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/027.xml
+%% ID: valid-not-sa-027
+%% Type: valid
+%% Sections: 4.1 [69]
+'valid-not-sa-027'(suite) -> [];
+'valid-not-sa-027'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/027.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/028.xml
+%% ID: valid-not-sa-028
+%% Type: valid
+%% Sections: 3.4 [62]
+'valid-not-sa-028'(suite) -> [];
+'valid-not-sa-028'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/028.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/029.xml
+%% ID: valid-not-sa-029
+%% Type: valid
+%% Sections: 3.4 [62]
+'valid-not-sa-029'(suite) -> [];
+'valid-not-sa-029'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/029.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/030.xml
+%% ID: valid-not-sa-030
+%% Type: valid
+%% Sections: 3.4 [62]
+'valid-not-sa-030'(suite) -> [];
+'valid-not-sa-030'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/030.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa/031.xml
+%% ID: valid-not-sa-031
+%% Type: valid
+%% Sections: 2.7
+'valid-not-sa-031'(suite) -> [];
+'valid-not-sa-031'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/not-sa/031.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/ext-sa/001.xml
+%% ID: valid-ext-sa-001
+%% Type: valid
+%% Sections: 2.11
+'valid-ext-sa-001'(suite) -> [];
+'valid-ext-sa-001'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/ext-sa/001.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/ext-sa/002.xml
+%% ID: valid-ext-sa-002
+%% Type: valid
+%% Sections: 2.11
+'valid-ext-sa-002'(suite) -> [];
+'valid-ext-sa-002'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/ext-sa/002.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/ext-sa/003.xml
+%% ID: valid-ext-sa-003
+%% Type: valid
+%% Sections: 3.1 4.1 [43] [68]
+'valid-ext-sa-003'(suite) -> [];
+'valid-ext-sa-003'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/ext-sa/003.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/ext-sa/004.xml
+%% ID: valid-ext-sa-004
+%% Type: valid
+%% Sections: 2.11
+'valid-ext-sa-004'(suite) -> [];
+'valid-ext-sa-004'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/ext-sa/004.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/ext-sa/005.xml
+%% ID: valid-ext-sa-005
+%% Type: valid
+%% Sections: 3.2.1 4.2.2 [48] [75]
+'valid-ext-sa-005'(suite) -> [];
+'valid-ext-sa-005'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/ext-sa/005.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/ext-sa/006.xml
+%% ID: valid-ext-sa-006
+%% Type: valid
+%% Sections: 2.11 3.2.1 3.2.2 4.2.2 [48] [51] [75]
+'valid-ext-sa-006'(suite) -> [];
+'valid-ext-sa-006'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/ext-sa/006.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/ext-sa/007.xml
+%% ID: valid-ext-sa-007
+%% Type: valid
+%% Sections: 4.2.2 4.4.3 [75]
+'valid-ext-sa-007'(suite) -> [];
+'valid-ext-sa-007'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/ext-sa/007.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/ext-sa/008.xml
+%% ID: valid-ext-sa-008
+%% Type: valid
+%% Sections: 4.2.2 4.3.3. 4.4.3 [75] [80]
+'valid-ext-sa-008'(suite) -> [];
+'valid-ext-sa-008'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/ext-sa/008.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/ext-sa/009.xml
+%% ID: valid-ext-sa-009
+%% Type: valid
+%% Sections: 2.11
+'valid-ext-sa-009'(suite) -> [];
+'valid-ext-sa-009'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/ext-sa/009.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/ext-sa/011.xml
+%% ID: valid-ext-sa-011
+%% Type: valid
+%% Sections: 2.11 4.2.2 [75]
+'valid-ext-sa-011'(suite) -> [];
+'valid-ext-sa-011'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/ext-sa/011.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/ext-sa/012.xml
+%% ID: valid-ext-sa-012
+%% Type: valid
+%% Sections: 4.2.1 4.2.2
+'valid-ext-sa-012'(suite) -> [];
+'valid-ext-sa-012'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/ext-sa/012.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/ext-sa/013.xml
+%% ID: valid-ext-sa-013
+%% Type: valid
+%% Sections: 3.3.3
+'valid-ext-sa-013'(suite) -> [];
+'valid-ext-sa-013'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/ext-sa/013.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/ext-sa/014.xml
+%% ID: valid-ext-sa-014
+%% Type: valid
+%% Sections: 4.1 4.4.3 [68]
+'valid-ext-sa-014'(suite) -> [];
+'valid-ext-sa-014'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"xmltest","valid/ext-sa/014.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: James Clark XMLTEST cases, 18-Nov-1998
+
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: James Clark XML 1.0 Tests
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: pr-xml-euc-jp.xml
+%% ID: pr-xml-euc-jp
+%% Type: error
+%% Sections: 4.3.3 [4,84]
+'pr-xml-euc-jp'(suite) -> [];
+'pr-xml-euc-jp'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"japanese","pr-xml-euc-jp.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "error").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: pr-xml-iso-2022-jp.xml
+%% ID: pr-xml-iso-2022-jp
+%% Type: error
+%% Sections: 4.3.3 [4,84]
+'pr-xml-iso-2022-jp'(suite) -> [];
+'pr-xml-iso-2022-jp'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"japanese","pr-xml-iso-2022-jp.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "error").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: pr-xml-little-endian.xml
+%% ID: pr-xml-little
+%% Type: valid
+%% Sections: 4.3.3 [4,84]
+'pr-xml-little'(suite) -> [];
+'pr-xml-little'(Config) -> {skip, "Fix 3"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"japanese","pr-xml-little-endian.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: pr-xml-shift_jis.xml
+%% ID: pr-xml-shift_jis
+%% Type: error
+%% Sections: 4.3.3 [4,84]
+'pr-xml-shift_jis'(suite) -> [];
+'pr-xml-shift_jis'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"japanese","pr-xml-shift_jis.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "error").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: pr-xml-utf-16.xml
+%% ID: pr-xml-utf-16
+%% Type: valid
+%% Sections: 4.3.3 [4,84]
+'pr-xml-utf-16'(suite) -> [];
+'pr-xml-utf-16'(Config) -> {skip, "Fix 3"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"japanese","pr-xml-utf-16.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: pr-xml-utf-8.xml
+%% ID: pr-xml-utf-8
+%% Type: valid
+%% Sections: 4.3.3 [4,84]
+'pr-xml-utf-8'(suite) -> [];
+'pr-xml-utf-8'(Config) -> {skip, "Fix 3"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"japanese","pr-xml-utf-8.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: weekly-euc-jp.xml
+%% ID: weekly-euc-jp
+%% Type: error
+%% Sections: 4.3.3 [4,84]
+'weekly-euc-jp'(suite) -> [];
+'weekly-euc-jp'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"japanese","weekly-euc-jp.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "error").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: weekly-iso-2022-jp.xml
+%% ID: weekly-iso-2022-jp
+%% Type: error
+%% Sections: 4.3.3 [4,84]
+'weekly-iso-2022-jp'(suite) -> [];
+'weekly-iso-2022-jp'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"japanese","weekly-iso-2022-jp.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "error").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: weekly-little-endian.xml
+%% ID: weekly-little
+%% Type: valid
+%% Sections: 4.3.3 [4,84]
+'weekly-little'(suite) -> [];
+'weekly-little'(Config) -> {skip, "Fix 3"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"japanese","weekly-little-endian.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: weekly-shift_jis.xml
+%% ID: weekly-shift_jis
+%% Type: error
+%% Sections: 4.3.3 [4,84]
+'weekly-shift_jis'(suite) -> [];
+'weekly-shift_jis'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"japanese","weekly-shift_jis.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "error").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: weekly-utf-16.xml
+%% ID: weekly-utf-16
+%% Type: valid
+%% Sections: 4.3.3 [4,84]
+'weekly-utf-16'(suite) -> [];
+'weekly-utf-16'(Config) -> {skip, "Fix 3"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"japanese","weekly-utf-16.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: weekly-utf-8.xml
+%% ID: weekly-utf-8
+%% Type: valid
+%% Sections: 4.3.3 [4,84]
+'weekly-utf-8'(suite) -> [];
+'weekly-utf-8'(Config) -> {skip, "Fix 3"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"japanese","weekly-utf-8.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: Fuji Xerox Japanese Text Tests
+
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: Fuji Xerox Japanese Text Tests XML 1.0 Tests
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/pe01.xml
+%% ID: pe01
+%% Type: valid
+%% Sections: 2.8
+'pe01'(suite) -> [];
+'pe01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/pe01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/dtd00.xml
+%% ID: dtd00
+%% Type: valid
+%% Sections: 3.2.2 [51]
+'dtd00'(suite) -> [];
+'dtd00'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/dtd00.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/dtd01.xml
+%% ID: dtd01
+%% Type: valid
+%% Sections: 2.5 [15]
+'dtd01'(suite) -> [];
+'dtd01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/dtd01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/element.xml
+%% ID: element
+%% Type: valid
+%% Sections: 3
+'element'(suite) -> [];
+'element'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/element.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/ext01.xml
+%% ID: ext01
+%% Type: valid
+%% Sections: 4.3.1 4.3.2 [77] [78]
+'ext01'(suite) -> [];
+'ext01'(Config) -> {skip, "Fix 3"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/ext01.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/ext02.xml
+%% ID: ext02
+%% Type: valid
+%% Sections: 4.3.2 [78]
+'ext02'(suite) -> [];
+'ext02'(Config) -> {skip, "Fix 3"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/ext02.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa01.xml
+%% ID: not-sa01
+%% Type: valid
+%% Sections: 2.9
+'not-sa01'(suite) -> [];
+'not-sa01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/not-sa01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa02.xml
+%% ID: not-sa02
+%% Type: valid
+%% Sections: 2.9
+'not-sa02'(suite) -> [];
+'not-sa02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/not-sa02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa03.xml
+%% ID: not-sa03
+%% Type: valid
+%% Sections: 2.9
+'not-sa03'(suite) -> [];
+'not-sa03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/not-sa03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/not-sa04.xml
+%% ID: not-sa04
+%% Type: valid
+%% Sections: 2.9
+'not-sa04'(suite) -> [];
+'not-sa04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/not-sa04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/notation01.xml
+%% ID: notation01
+%% Type: valid
+%% Sections: 4.7 [82]
+'notation01'(suite) -> [];
+'notation01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/notation01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/optional.xml
+%% ID: optional
+%% Type: valid
+%% Sections: 3 3.2.1 [47]
+'optional'(suite) -> [];
+'optional'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/optional.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/required00.xml
+%% ID: required00
+%% Type: valid
+%% Sections: 3.3.2 [60]
+'required00'(suite) -> [];
+'required00'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/required00.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa01.xml
+%% ID: sa01
+%% Type: valid
+%% Sections: 2.9 [32]
+'sa01'(suite) -> [];
+'sa01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/sa01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa02.xml
+%% ID: sa02
+%% Type: valid
+%% Sections: 2.9 [32]
+'sa02'(suite) -> [];
+'sa02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/sa02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa03.xml
+%% ID: sa03
+%% Type: valid
+%% Sections: 2.9 [32]
+'sa03'(suite) -> [];
+'sa03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/sa03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa04.xml
+%% ID: sa04
+%% Type: valid
+%% Sections: 2.9 [32]
+'sa04'(suite) -> [];
+'sa04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/sa04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sa05.xml
+%% ID: sa05
+%% Type: valid
+%% Sections: 2.9 [32]
+'sa05'(suite) -> [];
+'sa05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/sa05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/sgml01.xml
+%% ID: v-sgml01
+%% Type: valid
+%% Sections: 3.3.1 [59]
+'v-sgml01'(suite) -> [];
+'v-sgml01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/sgml01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/v-lang01.xml
+%% ID: v-lang01
+%% Type: valid
+%% Sections: 2.12 [35]
+'v-lang01'(suite) -> [];
+'v-lang01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/v-lang01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/v-lang02.xml
+%% ID: v-lang02
+%% Type: valid
+%% Sections: 2.12 [35]
+'v-lang02'(suite) -> [];
+'v-lang02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/v-lang02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/v-lang03.xml
+%% ID: v-lang03
+%% Type: valid
+%% Sections: 2.12 [36]
+'v-lang03'(suite) -> [];
+'v-lang03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/v-lang03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/v-lang04.xml
+%% ID: v-lang04
+%% Type: valid
+%% Sections: 2.12 [37]
+'v-lang04'(suite) -> [];
+'v-lang04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/v-lang04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/v-lang05.xml
+%% ID: v-lang05
+%% Type: valid
+%% Sections: 2.12 [35]
+'v-lang05'(suite) -> [];
+'v-lang05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/v-lang05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/v-lang06.xml
+%% ID: v-lang06
+%% Type: valid
+%% Sections: 2.12 [37]
+'v-lang06'(suite) -> [];
+'v-lang06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/v-lang06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/pe00.xml
+%% ID: v-pe00
+%% Type: valid
+%% Sections: 4.5
+'v-pe00'(suite) -> [];
+'v-pe00'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/pe00.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/pe03.xml
+%% ID: v-pe03
+%% Type: valid
+%% Sections: 4.5
+'v-pe03'(suite) -> [];
+'v-pe03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/pe03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/pe02.xml
+%% ID: v-pe02
+%% Type: valid
+%% Sections: 4.5
+'v-pe02'(suite) -> [];
+'v-pe02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","valid/pe02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/dtd01.xml
+%% ID: inv-dtd01
+%% Type: invalid
+%% Sections: 3.2.2
+'inv-dtd01'(suite) -> [];
+'inv-dtd01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/dtd01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/dtd02.xml
+%% ID: inv-dtd02
+%% Type: invalid
+%% Sections: 4.2.2
+'inv-dtd02'(suite) -> [];
+'inv-dtd02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/dtd02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/dtd03.xml
+%% ID: inv-dtd03
+%% Type: invalid
+%% Sections: 3
+'inv-dtd03'(suite) -> [];
+'inv-dtd03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/dtd03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/el01.xml
+%% ID: el01
+%% Type: invalid
+%% Sections: 3
+'el01'(suite) -> [];
+'el01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/el01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/el02.xml
+%% ID: el02
+%% Type: invalid
+%% Sections: 3
+'el02'(suite) -> [];
+'el02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/el02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/el03.xml
+%% ID: el03
+%% Type: invalid
+%% Sections: 3
+'el03'(suite) -> [];
+'el03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/el03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/el04.xml
+%% ID: el04
+%% Type: invalid
+%% Sections: 3.2
+'el04'(suite) -> [];
+'el04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/el04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/el05.xml
+%% ID: el05
+%% Type: invalid
+%% Sections: 3.2.2
+'el05'(suite) -> [];
+'el05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/el05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/el06.xml
+%% ID: el06
+%% Type: invalid
+%% Sections: 3
+'el06'(suite) -> [];
+'el06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/el06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/id01.xml
+%% ID: id01
+%% Type: invalid
+%% Sections: 3.3.1
+'id01'(suite) -> [];
+'id01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/id01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/id02.xml
+%% ID: id02
+%% Type: invalid
+%% Sections: 3.3.1
+'id02'(suite) -> [];
+'id02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/id02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/id03.xml
+%% ID: id03
+%% Type: invalid
+%% Sections: 3.3.1
+'id03'(suite) -> [];
+'id03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/id03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/id04.xml
+%% ID: id04
+%% Type: invalid
+%% Sections: 3.3.1
+'id04'(suite) -> [];
+'id04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/id04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/id05.xml
+%% ID: id05
+%% Type: invalid
+%% Sections: 3.3.1
+'id05'(suite) -> [];
+'id05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/id05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/id06.xml
+%% ID: id06
+%% Type: invalid
+%% Sections: 3.3.1
+'id06'(suite) -> [];
+'id06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/id06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/id07.xml
+%% ID: id07
+%% Type: invalid
+%% Sections: 3.3.1
+'id07'(suite) -> [];
+'id07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/id07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/id08.xml
+%% ID: id08
+%% Type: invalid
+%% Sections: 3.3.1
+'id08'(suite) -> [];
+'id08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/id08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/id09.xml
+%% ID: id09
+%% Type: invalid
+%% Sections: 3.3.1
+'id09'(suite) -> [];
+'id09'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/id09.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/not-sa01.xml
+%% ID: inv-not-sa01
+%% Type: invalid
+%% Sections: 2.9
+'inv-not-sa01'(suite) -> [];
+'inv-not-sa01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/not-sa01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/not-sa02.xml
+%% ID: inv-not-sa02
+%% Type: invalid
+%% Sections: 2.9
+'inv-not-sa02'(suite) -> [];
+'inv-not-sa02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/not-sa02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/not-sa04.xml
+%% ID: inv-not-sa04
+%% Type: invalid
+%% Sections: 2.9
+'inv-not-sa04'(suite) -> [];
+'inv-not-sa04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/not-sa04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/not-sa05.xml
+%% ID: inv-not-sa05
+%% Type: invalid
+%% Sections: 2.9
+'inv-not-sa05'(suite) -> [];
+'inv-not-sa05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/not-sa05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/not-sa06.xml
+%% ID: inv-not-sa06
+%% Type: invalid
+%% Sections: 2.9
+'inv-not-sa06'(suite) -> [];
+'inv-not-sa06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/not-sa06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/not-sa07.xml
+%% ID: inv-not-sa07
+%% Type: invalid
+%% Sections: 2.9
+'inv-not-sa07'(suite) -> [];
+'inv-not-sa07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/not-sa07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/not-sa08.xml
+%% ID: inv-not-sa08
+%% Type: invalid
+%% Sections: 2.9
+'inv-not-sa08'(suite) -> [];
+'inv-not-sa08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/not-sa08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/not-sa09.xml
+%% ID: inv-not-sa09
+%% Type: invalid
+%% Sections: 2.9
+'inv-not-sa09'(suite) -> [];
+'inv-not-sa09'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/not-sa09.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/not-sa10.xml
+%% ID: inv-not-sa10
+%% Type: invalid
+%% Sections: 2.9
+'inv-not-sa10'(suite) -> [];
+'inv-not-sa10'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/not-sa10.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/not-sa11.xml
+%% ID: inv-not-sa11
+%% Type: invalid
+%% Sections: 2.9
+'inv-not-sa11'(suite) -> [];
+'inv-not-sa11'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/not-sa11.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/not-sa12.xml
+%% ID: inv-not-sa12
+%% Type: invalid
+%% Sections: 2.9
+'inv-not-sa12'(suite) -> [];
+'inv-not-sa12'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/not-sa12.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/not-sa13.xml
+%% ID: inv-not-sa13
+%% Type: invalid
+%% Sections: 2.9
+'inv-not-sa13'(suite) -> [];
+'inv-not-sa13'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/not-sa13.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/not-sa14.xml
+%% ID: inv-not-sa14
+%% Type: invalid
+%% Sections: 3
+'inv-not-sa14'(suite) -> [];
+'inv-not-sa14'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/not-sa14.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional01.xml
+%% ID: optional01
+%% Type: invalid
+%% Sections: 3
+'optional01'(suite) -> [];
+'optional01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional02.xml
+%% ID: optional02
+%% Type: invalid
+%% Sections: 3
+'optional02'(suite) -> [];
+'optional02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional03.xml
+%% ID: optional03
+%% Type: invalid
+%% Sections: 3
+'optional03'(suite) -> [];
+'optional03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional04.xml
+%% ID: optional04
+%% Type: invalid
+%% Sections: 3
+'optional04'(suite) -> [];
+'optional04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional05.xml
+%% ID: optional05
+%% Type: invalid
+%% Sections: 3
+'optional05'(suite) -> [];
+'optional05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional06.xml
+%% ID: optional06
+%% Type: invalid
+%% Sections: 3
+'optional06'(suite) -> [];
+'optional06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional07.xml
+%% ID: optional07
+%% Type: invalid
+%% Sections: 3
+'optional07'(suite) -> [];
+'optional07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional08.xml
+%% ID: optional08
+%% Type: invalid
+%% Sections: 3
+'optional08'(suite) -> [];
+'optional08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional09.xml
+%% ID: optional09
+%% Type: invalid
+%% Sections: 3
+'optional09'(suite) -> [];
+'optional09'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional09.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional10.xml
+%% ID: optional10
+%% Type: invalid
+%% Sections: 3
+'optional10'(suite) -> [];
+'optional10'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional10.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional11.xml
+%% ID: optional11
+%% Type: invalid
+%% Sections: 3
+'optional11'(suite) -> [];
+'optional11'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional11.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional12.xml
+%% ID: optional12
+%% Type: invalid
+%% Sections: 3
+'optional12'(suite) -> [];
+'optional12'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional12.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional13.xml
+%% ID: optional13
+%% Type: invalid
+%% Sections: 3
+'optional13'(suite) -> [];
+'optional13'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional13.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional14.xml
+%% ID: optional14
+%% Type: invalid
+%% Sections: 3
+'optional14'(suite) -> [];
+'optional14'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional14.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional20.xml
+%% ID: optional20
+%% Type: invalid
+%% Sections: 3
+'optional20'(suite) -> [];
+'optional20'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional20.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional21.xml
+%% ID: optional21
+%% Type: invalid
+%% Sections: 3
+'optional21'(suite) -> [];
+'optional21'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional21.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional22.xml
+%% ID: optional22
+%% Type: invalid
+%% Sections: 3
+'optional22'(suite) -> [];
+'optional22'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional22.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional23.xml
+%% ID: optional23
+%% Type: invalid
+%% Sections: 3
+'optional23'(suite) -> [];
+'optional23'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional23.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional24.xml
+%% ID: optional24
+%% Type: invalid
+%% Sections: 3
+'optional24'(suite) -> [];
+'optional24'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional24.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/optional25.xml
+%% ID: optional25
+%% Type: invalid
+%% Sections: 3
+'optional25'(suite) -> [];
+'optional25'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/optional25.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/required00.xml
+%% ID: inv-required00
+%% Type: invalid
+%% Sections: 3.3.2
+'inv-required00'(suite) -> [];
+'inv-required00'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/required00.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/required01.xml
+%% ID: inv-required01
+%% Type: invalid
+%% Sections: 3.1 2.10
+'inv-required01'(suite) -> [];
+'inv-required01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/required01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/required02.xml
+%% ID: inv-required02
+%% Type: invalid
+%% Sections: 3.1 2.12
+'inv-required02'(suite) -> [];
+'inv-required02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/required02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/root.xml
+%% ID: root
+%% Type: invalid
+%% Sections: 2.8
+'root'(suite) -> [];
+'root'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/root.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/attr01.xml
+%% ID: attr01
+%% Type: invalid
+%% Sections: 3.3.1
+'attr01'(suite) -> [];
+'attr01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/attr01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/attr02.xml
+%% ID: attr02
+%% Type: invalid
+%% Sections: 3.3.1
+'attr02'(suite) -> [];
+'attr02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/attr02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/attr03.xml
+%% ID: attr03
+%% Type: invalid
+%% Sections: 3.3.1
+'attr03'(suite) -> [];
+'attr03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/attr03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/attr04.xml
+%% ID: attr04
+%% Type: invalid
+%% Sections: 3.3.1
+'attr04'(suite) -> [];
+'attr04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/attr04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/attr05.xml
+%% ID: attr05
+%% Type: invalid
+%% Sections: 3.3.1
+'attr05'(suite) -> [];
+'attr05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/attr05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/attr06.xml
+%% ID: attr06
+%% Type: invalid
+%% Sections: 3.3.1
+'attr06'(suite) -> [];
+'attr06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/attr06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/attr07.xml
+%% ID: attr07
+%% Type: invalid
+%% Sections: 3.3.1
+'attr07'(suite) -> [];
+'attr07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/attr07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/attr08.xml
+%% ID: attr08
+%% Type: invalid
+%% Sections: 3.3.2
+'attr08'(suite) -> [];
+'attr08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/attr08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/attr09.xml
+%% ID: attr09
+%% Type: invalid
+%% Sections: 3.3.2
+'attr09'(suite) -> [];
+'attr09'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/attr09.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/attr10.xml
+%% ID: attr10
+%% Type: invalid
+%% Sections: 3.3.2
+'attr10'(suite) -> [];
+'attr10'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/attr10.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/attr11.xml
+%% ID: attr11
+%% Type: invalid
+%% Sections: 3.3.2
+'attr11'(suite) -> [];
+'attr11'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/attr11.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/attr12.xml
+%% ID: attr12
+%% Type: invalid
+%% Sections: 3.3.2
+'attr12'(suite) -> [];
+'attr12'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/attr12.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/attr13.xml
+%% ID: attr13
+%% Type: invalid
+%% Sections: 3.3.2
+'attr13'(suite) -> [];
+'attr13'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/attr13.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/attr14.xml
+%% ID: attr14
+%% Type: invalid
+%% Sections: 3.3.2
+'attr14'(suite) -> [];
+'attr14'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/attr14.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/attr15.xml
+%% ID: attr15
+%% Type: invalid
+%% Sections: 3.3.2
+'attr15'(suite) -> [];
+'attr15'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/attr15.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/attr16.xml
+%% ID: attr16
+%% Type: invalid
+%% Sections: 3.3.2
+'attr16'(suite) -> [];
+'attr16'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/attr16.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/utf16b.xml
+%% ID: utf16b
+%% Type: invalid
+%% Sections: 4.3.3 2.8
+'utf16b'(suite) -> [];
+'utf16b'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/utf16b.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/utf16l.xml
+%% ID: utf16l
+%% Type: invalid
+%% Sections: 4.3.3 2.8
+'utf16l'(suite) -> [];
+'utf16l'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/utf16l.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/empty.xml
+%% ID: empty
+%% Type: invalid
+%% Sections: 2.4 2.7 [18] 3
+'empty'(suite) -> [];
+'empty'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","invalid/empty.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/not-sa03.xml
+%% ID: not-wf-sa03
+%% Type: not-wf
+%% Sections: 2.9
+'not-wf-sa03'(suite) -> [];
+'not-wf-sa03'(Config) -> {skip, "Fix 3"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/not-sa03.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/attlist01.xml
+%% ID: attlist01
+%% Type: not-wf
+%% Sections: 3.3.1 [56]
+'attlist01'(suite) -> [];
+'attlist01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/attlist01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/attlist02.xml
+%% ID: attlist02
+%% Type: not-wf
+%% Sections: 3.3.1 [56]
+'attlist02'(suite) -> [];
+'attlist02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/attlist02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/attlist03.xml
+%% ID: attlist03
+%% Type: not-wf
+%% Sections: 3.3.1 [59]
+'attlist03'(suite) -> [];
+'attlist03'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/attlist03.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/attlist04.xml
+%% ID: attlist04
+%% Type: not-wf
+%% Sections: 3.3.1 [56]
+'attlist04'(suite) -> [];
+'attlist04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/attlist04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/attlist05.xml
+%% ID: attlist05
+%% Type: not-wf
+%% Sections: 3.3.1 [56]
+'attlist05'(suite) -> [];
+'attlist05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/attlist05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/attlist06.xml
+%% ID: attlist06
+%% Type: not-wf
+%% Sections: 3.3.1 [56]
+'attlist06'(suite) -> [];
+'attlist06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/attlist06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/attlist07.xml
+%% ID: attlist07
+%% Type: not-wf
+%% Sections: 3.3.1 [56]
+'attlist07'(suite) -> [];
+'attlist07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/attlist07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/attlist08.xml
+%% ID: attlist08
+%% Type: not-wf
+%% Sections: 3.3.1 [56]
+'attlist08'(suite) -> [];
+'attlist08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/attlist08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/attlist09.xml
+%% ID: attlist09
+%% Type: not-wf
+%% Sections: 3.3.1 [56]
+'attlist09'(suite) -> [];
+'attlist09'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/attlist09.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/attlist10.xml
+%% ID: attlist10
+%% Type: not-wf
+%% Sections: 3.1 [40]
+'attlist10'(suite) -> [];
+'attlist10'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/attlist10.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/attlist11.xml
+%% ID: attlist11
+%% Type: not-wf
+%% Sections: 3.1 [44]
+'attlist11'(suite) -> [];
+'attlist11'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/attlist11.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/cond01.xml
+%% ID: cond01
+%% Type: not-wf
+%% Sections: 3.4 [61]
+'cond01'(suite) -> [];
+'cond01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/cond01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/cond02.xml
+%% ID: cond02
+%% Type: not-wf
+%% Sections: 3.4 [61]
+'cond02'(suite) -> [];
+'cond02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/cond02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/content01.xml
+%% ID: content01
+%% Type: not-wf
+%% Sections: 3.2.1 [48]
+'content01'(suite) -> [];
+'content01'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/content01.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/content02.xml
+%% ID: content02
+%% Type: not-wf
+%% Sections: 3.2.1 [48]
+'content02'(suite) -> [];
+'content02'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/content02.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/content03.xml
+%% ID: content03
+%% Type: not-wf
+%% Sections: 3.2.1 [48]
+'content03'(suite) -> [];
+'content03'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/content03.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/decl01.xml
+%% ID: decl01
+%% Type: not-wf
+%% Sections: 4.3.1 [77]
+'decl01'(suite) -> [];
+'decl01'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/decl01.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/dtd00.xml
+%% ID: nwf-dtd00
+%% Type: not-wf
+%% Sections: 3.2.1 [55]
+'nwf-dtd00'(suite) -> [];
+'nwf-dtd00'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/dtd00.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/dtd01.xml
+%% ID: nwf-dtd01
+%% Type: not-wf
+%% Sections: 3.2.1 [55]
+'nwf-dtd01'(suite) -> [];
+'nwf-dtd01'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/dtd01.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/dtd02.xml
+%% ID: dtd02
+%% Type: not-wf
+%% Sections: 4.1 [69]
+'dtd02'(suite) -> [];
+'dtd02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/dtd02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/dtd03.xml
+%% ID: dtd03
+%% Type: not-wf
+%% Sections: 4.1 [69]
+'dtd03'(suite) -> [];
+'dtd03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/dtd03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/dtd04.xml
+%% ID: dtd04
+%% Type: not-wf
+%% Sections: 4.2.2 [75]
+'dtd04'(suite) -> [];
+'dtd04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/dtd04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/dtd05.xml
+%% ID: dtd05
+%% Type: not-wf
+%% Sections: 4.2.2 [75]
+'dtd05'(suite) -> [];
+'dtd05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/dtd05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/dtd07.xml
+%% ID: dtd07
+%% Type: not-wf
+%% Sections: 4.3.1 [77]
+'dtd07'(suite) -> [];
+'dtd07'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/dtd07.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/element00.xml
+%% ID: element00
+%% Type: not-wf
+%% Sections: 3.1 [42]
+'element00'(suite) -> [];
+'element00'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/element00.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/element01.xml
+%% ID: element01
+%% Type: not-wf
+%% Sections: 3.1 [42]
+'element01'(suite) -> [];
+'element01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/element01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/element02.xml
+%% ID: element02
+%% Type: not-wf
+%% Sections: 3.1 [43]
+'element02'(suite) -> [];
+'element02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/element02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/element03.xml
+%% ID: element03
+%% Type: not-wf
+%% Sections: 3.1 [43]
+'element03'(suite) -> [];
+'element03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/element03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/element04.xml
+%% ID: element04
+%% Type: not-wf
+%% Sections: 3.1 [43]
+'element04'(suite) -> [];
+'element04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/element04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/encoding01.xml
+%% ID: encoding01
+%% Type: not-wf
+%% Sections: 4.3.3 [81]
+'encoding01'(suite) -> [];
+'encoding01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/encoding01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/encoding02.xml
+%% ID: encoding02
+%% Type: not-wf
+%% Sections: 4.3.3 [81]
+'encoding02'(suite) -> [];
+'encoding02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/encoding02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/encoding03.xml
+%% ID: encoding03
+%% Type: not-wf
+%% Sections: 4.3.3 [81]
+'encoding03'(suite) -> [];
+'encoding03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/encoding03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/encoding04.xml
+%% ID: encoding04
+%% Type: not-wf
+%% Sections: 4.3.3 [81]
+'encoding04'(suite) -> [];
+'encoding04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/encoding04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/encoding05.xml
+%% ID: encoding05
+%% Type: not-wf
+%% Sections: 4.3.3 [81]
+'encoding05'(suite) -> [];
+'encoding05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/encoding05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/encoding06.xml
+%% ID: encoding06
+%% Type: not-wf
+%% Sections: 4.3.3 [81]
+'encoding06'(suite) -> [];
+'encoding06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/encoding06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/encoding07.xml
+%% ID: encoding07
+%% Type: not-wf
+%% Sections: 4.3.1 [77]
+'encoding07'(suite) -> [];
+'encoding07'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/encoding07.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/pi.xml
+%% ID: pi
+%% Type: not-wf
+%% Sections: 2.6 [16]
+'pi'(suite) -> [];
+'pi'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/pi.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/pubid01.xml
+%% ID: pubid01
+%% Type: not-wf
+%% Sections: 2.3 [12]
+'pubid01'(suite) -> [];
+'pubid01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/pubid01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/pubid02.xml
+%% ID: pubid02
+%% Type: not-wf
+%% Sections: 2.3 [12]
+'pubid02'(suite) -> [];
+'pubid02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/pubid02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/pubid03.xml
+%% ID: pubid03
+%% Type: not-wf
+%% Sections: 2.3 [12]
+'pubid03'(suite) -> [];
+'pubid03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/pubid03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/pubid04.xml
+%% ID: pubid04
+%% Type: not-wf
+%% Sections: 2.3 [12]
+'pubid04'(suite) -> [];
+'pubid04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/pubid04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/pubid05.xml
+%% ID: pubid05
+%% Type: not-wf
+%% Sections: 2.3 [12]
+'pubid05'(suite) -> [];
+'pubid05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/pubid05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sgml01.xml
+%% ID: sgml01
+%% Type: not-wf
+%% Sections: 3 [39]
+'sgml01'(suite) -> [];
+'sgml01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/sgml01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sgml02.xml
+%% ID: sgml02
+%% Type: not-wf
+%% Sections: 2.8
+'sgml02'(suite) -> [];
+'sgml02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/sgml02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sgml03.xml
+%% ID: sgml03
+%% Type: not-wf
+%% Sections: 2.5 [15]
+'sgml03'(suite) -> [];
+'sgml03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/sgml03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sgml04.xml
+%% ID: sgml04
+%% Type: not-wf
+%% Sections: 3.3 [52]
+'sgml04'(suite) -> [];
+'sgml04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/sgml04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sgml05.xml
+%% ID: sgml05
+%% Type: not-wf
+%% Sections: 3.2 [45]
+'sgml05'(suite) -> [];
+'sgml05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/sgml05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sgml06.xml
+%% ID: sgml06
+%% Type: not-wf
+%% Sections: 3.3 [52]
+'sgml06'(suite) -> [];
+'sgml06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/sgml06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sgml07.xml
+%% ID: sgml07
+%% Type: not-wf
+%% Sections: 3.2 [45]
+'sgml07'(suite) -> [];
+'sgml07'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/sgml07.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sgml08.xml
+%% ID: sgml08
+%% Type: not-wf
+%% Sections: 3.2 [45]
+'sgml08'(suite) -> [];
+'sgml08'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/sgml08.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sgml09.xml
+%% ID: sgml09
+%% Type: not-wf
+%% Sections: 3.2 [45]
+'sgml09'(suite) -> [];
+'sgml09'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/sgml09.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sgml10.xml
+%% ID: sgml10
+%% Type: not-wf
+%% Sections: 3.2 [45]
+'sgml10'(suite) -> [];
+'sgml10'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/sgml10.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sgml11.xml
+%% ID: sgml11
+%% Type: not-wf
+%% Sections: 3.2 [46]
+'sgml11'(suite) -> [];
+'sgml11'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/sgml11.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sgml12.xml
+%% ID: sgml12
+%% Type: not-wf
+%% Sections: 3.2 [46]
+'sgml12'(suite) -> [];
+'sgml12'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/sgml12.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/sgml13.xml
+%% ID: sgml13
+%% Type: not-wf
+%% Sections: 3.2.1 [47]
+'sgml13'(suite) -> [];
+'sgml13'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/sgml13.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/uri01.xml
+%% ID: uri01
+%% Type: error
+%% Sections: 4.2.2 [75]
+'uri01'(suite) -> [];
+'uri01'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"sun","not-wf/uri01.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "error").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: Sun Microsystems XML Tests
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p01pass2.xml
+%% ID: o-p01pass2
+%% Type: valid
+%% Sections: 2.2 [1]
+'o-p01pass2'(suite) -> [];
+'o-p01pass2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p01pass2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p06pass1.xml
+%% ID: o-p06pass1
+%% Type: valid
+%% Sections: 2.3 [6]
+'o-p06pass1'(suite) -> [];
+'o-p06pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p06pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p07pass1.xml
+%% ID: o-p07pass1
+%% Type: valid
+%% Sections: 2.3 [7]
+'o-p07pass1'(suite) -> [];
+'o-p07pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p07pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p08pass1.xml
+%% ID: o-p08pass1
+%% Type: valid
+%% Sections: 2.3 [8]
+'o-p08pass1'(suite) -> [];
+'o-p08pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p08pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p09pass1.xml
+%% ID: o-p09pass1
+%% Type: valid
+%% Sections: 2.3 [9]
+'o-p09pass1'(suite) -> [];
+'o-p09pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p09pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p12pass1.xml
+%% ID: o-p12pass1
+%% Type: valid
+%% Sections: 2.3 [12]
+'o-p12pass1'(suite) -> [];
+'o-p12pass1'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p12pass1.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p22pass4.xml
+%% ID: o-p22pass4
+%% Type: valid
+%% Sections: 2.8 [22]
+'o-p22pass4'(suite) -> [];
+'o-p22pass4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p22pass4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p22pass5.xml
+%% ID: o-p22pass5
+%% Type: valid
+%% Sections: 2.8 [22]
+'o-p22pass5'(suite) -> [];
+'o-p22pass5'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p22pass5.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p22pass6.xml
+%% ID: o-p22pass6
+%% Type: valid
+%% Sections: 2.8 [22]
+'o-p22pass6'(suite) -> [];
+'o-p22pass6'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p22pass6.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p28pass1.xml
+%% ID: o-p28pass1
+%% Type: valid
+%% Sections: 3.1 [43] [44]
+'o-p28pass1'(suite) -> [];
+'o-p28pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p28pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p28pass3.xml
+%% ID: o-p28pass3
+%% Type: valid
+%% Sections: 2.8 4.1 [28] [69]
+'o-p28pass3'(suite) -> [];
+'o-p28pass3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p28pass3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p28pass4.xml
+%% ID: o-p28pass4
+%% Type: valid
+%% Sections: 2.8 4.2.2 [28] [75]
+'o-p28pass4'(suite) -> [];
+'o-p28pass4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p28pass4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p28pass5.xml
+%% ID: o-p28pass5
+%% Type: valid
+%% Sections: 2.8 4.1 [28] [69]
+'o-p28pass5'(suite) -> [];
+'o-p28pass5'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p28pass5.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p29pass1.xml
+%% ID: o-p29pass1
+%% Type: valid
+%% Sections: 2.8 [29]
+'o-p29pass1'(suite) -> [];
+'o-p29pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p29pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p30pass1.xml
+%% ID: o-p30pass1
+%% Type: valid
+%% Sections: 2.8 4.2.2 [30] [75]
+'o-p30pass1'(suite) -> [];
+'o-p30pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p30pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p30pass2.xml
+%% ID: o-p30pass2
+%% Type: valid
+%% Sections: 2.8 4.2.2 4.3.1 [30] [75] [77]
+'o-p30pass2'(suite) -> [];
+'o-p30pass2'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p30pass2.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p31pass1.xml
+%% ID: o-p31pass1
+%% Type: valid
+%% Sections: 2.8 [31]
+'o-p31pass1'(suite) -> [];
+'o-p31pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p31pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p31pass2.xml
+%% ID: o-p31pass2
+%% Type: valid
+%% Sections: 2.8 3.4 4.2.2 [31] [62] [63] [75]
+'o-p31pass2'(suite) -> [];
+'o-p31pass2'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p31pass2.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p43pass1.xml
+%% ID: o-p43pass1
+%% Type: valid
+%% Sections: 2.4 2.5 2.6 2.7 [15] [16] [18]
+'o-p43pass1'(suite) -> [];
+'o-p43pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p43pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p45pass1.xml
+%% ID: o-p45pass1
+%% Type: valid
+%% Sections: 3.2 [45]
+'o-p45pass1'(suite) -> [];
+'o-p45pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p45pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p46pass1.xml
+%% ID: o-p46pass1
+%% Type: valid
+%% Sections: 3.2 3.2.1 3.2.2 [45] [46] [47] [51]
+'o-p46pass1'(suite) -> [];
+'o-p46pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p46pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p47pass1.xml
+%% ID: o-p47pass1
+%% Type: valid
+%% Sections: 3.2 3.2.1 [45] [46] [47]
+'o-p47pass1'(suite) -> [];
+'o-p47pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p47pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p48pass1.xml
+%% ID: o-p48pass1
+%% Type: valid
+%% Sections: 3.2 3.2.1 [45] [46] [47]
+'o-p48pass1'(suite) -> [];
+'o-p48pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p48pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p49pass1.xml
+%% ID: o-p49pass1
+%% Type: valid
+%% Sections: 3.2 3.2.1 [45] [46] [47]
+'o-p49pass1'(suite) -> [];
+'o-p49pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p49pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p50pass1.xml
+%% ID: o-p50pass1
+%% Type: valid
+%% Sections: 3.2 3.2.1 [45] [46] [47]
+'o-p50pass1'(suite) -> [];
+'o-p50pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p50pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p51pass1.xml
+%% ID: o-p51pass1
+%% Type: valid
+%% Sections: 3.2.2 [51]
+'o-p51pass1'(suite) -> [];
+'o-p51pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p51pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p52pass1.xml
+%% ID: o-p52pass1
+%% Type: valid
+%% Sections: 3.3 [52]
+'o-p52pass1'(suite) -> [];
+'o-p52pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p52pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p53pass1.xml
+%% ID: o-p53pass1
+%% Type: valid
+%% Sections: 3.3 [53]
+'o-p53pass1'(suite) -> [];
+'o-p53pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p53pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p54pass1.xml
+%% ID: o-p54pass1
+%% Type: valid
+%% Sections: 3.3.1 [54]
+'o-p54pass1'(suite) -> [];
+'o-p54pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p54pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p55pass1.xml
+%% ID: o-p55pass1
+%% Type: valid
+%% Sections: 3.3.1 [55]
+'o-p55pass1'(suite) -> [];
+'o-p55pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p55pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p56pass1.xml
+%% ID: o-p56pass1
+%% Type: valid
+%% Sections: 3.3.1 [56]
+'o-p56pass1'(suite) -> [];
+'o-p56pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p56pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p57pass1.xml
+%% ID: o-p57pass1
+%% Type: valid
+%% Sections: 3.3.1 [57]
+'o-p57pass1'(suite) -> [];
+'o-p57pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p57pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p58pass1.xml
+%% ID: o-p58pass1
+%% Type: valid
+%% Sections: 3.3.1 [58]
+'o-p58pass1'(suite) -> [];
+'o-p58pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p58pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p59pass1.xml
+%% ID: o-p59pass1
+%% Type: valid
+%% Sections: 3.3.1 [59]
+'o-p59pass1'(suite) -> [];
+'o-p59pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p59pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p60pass1.xml
+%% ID: o-p60pass1
+%% Type: valid
+%% Sections: 3.3.2 [60]
+'o-p60pass1'(suite) -> [];
+'o-p60pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p60pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p61pass1.xml
+%% ID: o-p61pass1
+%% Type: valid
+%% Sections: 3.4 [61]
+'o-p61pass1'(suite) -> [];
+'o-p61pass1'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p61pass1.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p62pass1.xml
+%% ID: o-p62pass1
+%% Type: valid
+%% Sections: 3.4 [62]
+'o-p62pass1'(suite) -> [];
+'o-p62pass1'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p62pass1.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p63pass1.xml
+%% ID: o-p63pass1
+%% Type: valid
+%% Sections: 3.4 [63]
+'o-p63pass1'(suite) -> [];
+'o-p63pass1'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p63pass1.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p64pass1.xml
+%% ID: o-p64pass1
+%% Type: valid
+%% Sections: 3.4 [64]
+'o-p64pass1'(suite) -> [];
+'o-p64pass1'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p64pass1.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p68pass1.xml
+%% ID: o-p68pass1
+%% Type: valid
+%% Sections: 4.1 [68]
+'o-p68pass1'(suite) -> [];
+'o-p68pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p68pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p69pass1.xml
+%% ID: o-p69pass1
+%% Type: valid
+%% Sections: 4.1 [69]
+'o-p69pass1'(suite) -> [];
+'o-p69pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p69pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p70pass1.xml
+%% ID: o-p70pass1
+%% Type: valid
+%% Sections: 4.2 [70]
+'o-p70pass1'(suite) -> [];
+'o-p70pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p70pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p71pass1.xml
+%% ID: o-p71pass1
+%% Type: valid
+%% Sections: 4.2 [71]
+'o-p71pass1'(suite) -> [];
+'o-p71pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p71pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p72pass1.xml
+%% ID: o-p72pass1
+%% Type: valid
+%% Sections: 4.2 [72]
+'o-p72pass1'(suite) -> [];
+'o-p72pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p72pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p73pass1.xml
+%% ID: o-p73pass1
+%% Type: valid
+%% Sections: 4.2 [73]
+'o-p73pass1'(suite) -> [];
+'o-p73pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p73pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p76pass1.xml
+%% ID: o-p76pass1
+%% Type: valid
+%% Sections: 4.2.2 [76]
+'o-p76pass1'(suite) -> [];
+'o-p76pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p76pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p01pass1.xml
+%% ID: o-p01pass1
+%% Type: invalid
+%% Sections: 2.1 [1]
+'o-p01pass1'(suite) -> [];
+'o-p01pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p01pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p01pass3.xml
+%% ID: o-p01pass3
+%% Type: invalid
+%% Sections: 2.1 [1]
+'o-p01pass3'(suite) -> [];
+'o-p01pass3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p01pass3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03pass1.xml
+%% ID: o-p03pass1
+%% Type: invalid
+%% Sections: 2.3 [3]
+'o-p03pass1'(suite) -> [];
+'o-p03pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p04pass1.xml
+%% ID: o-p04pass1
+%% Type: invalid
+%% Sections: 2.3 [4]
+'o-p04pass1'(suite) -> [];
+'o-p04pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p04pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p05pass1.xml
+%% ID: o-p05pass1
+%% Type: invalid
+%% Sections: 2.3 [5]
+'o-p05pass1'(suite) -> [];
+'o-p05pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p05pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p06fail1.xml
+%% ID: o-p06fail1
+%% Type: invalid
+%% Sections: 2.3 [6]
+'o-p06fail1'(suite) -> [];
+'o-p06fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p06fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p08fail1.xml
+%% ID: o-p08fail1
+%% Type: invalid
+%% Sections: 2.3 [8]
+'o-p08fail1'(suite) -> [];
+'o-p08fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p08fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p08fail2.xml
+%% ID: o-p08fail2
+%% Type: invalid
+%% Sections: 2.3 [8]
+'o-p08fail2'(suite) -> [];
+'o-p08fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p08fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p10pass1.xml
+%% ID: o-p10pass1
+%% Type: invalid
+%% Sections: 2.3 [10]
+'o-p10pass1'(suite) -> [];
+'o-p10pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p10pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p14pass1.xml
+%% ID: o-p14pass1
+%% Type: invalid
+%% Sections: 2.4 [14]
+'o-p14pass1'(suite) -> [];
+'o-p14pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p14pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p15pass1.xml
+%% ID: o-p15pass1
+%% Type: invalid
+%% Sections: 2.5 [15]
+'o-p15pass1'(suite) -> [];
+'o-p15pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p15pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p16pass1.xml
+%% ID: o-p16pass1
+%% Type: invalid
+%% Sections: 2.6 [16] [17]
+'o-p16pass1'(suite) -> [];
+'o-p16pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p16pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p16pass2.xml
+%% ID: o-p16pass2
+%% Type: invalid
+%% Sections: 2.6 [16]
+'o-p16pass2'(suite) -> [];
+'o-p16pass2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p16pass2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p16pass3.xml
+%% ID: o-p16pass3
+%% Type: invalid
+%% Sections: 2.6 [16]
+'o-p16pass3'(suite) -> [];
+'o-p16pass3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p16pass3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p18pass1.xml
+%% ID: o-p18pass1
+%% Type: invalid
+%% Sections: 2.7 [18]
+'o-p18pass1'(suite) -> [];
+'o-p18pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p18pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p22pass1.xml
+%% ID: o-p22pass1
+%% Type: invalid
+%% Sections: 2.8 [22]
+'o-p22pass1'(suite) -> [];
+'o-p22pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p22pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p22pass2.xml
+%% ID: o-p22pass2
+%% Type: invalid
+%% Sections: 2.8 [22]
+'o-p22pass2'(suite) -> [];
+'o-p22pass2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p22pass2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p22pass3.xml
+%% ID: o-p22pass3
+%% Type: invalid
+%% Sections: 2.8 [22]
+'o-p22pass3'(suite) -> [];
+'o-p22pass3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p22pass3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p23pass1.xml
+%% ID: o-p23pass1
+%% Type: invalid
+%% Sections: 2.8 [23]
+'o-p23pass1'(suite) -> [];
+'o-p23pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p23pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p23pass2.xml
+%% ID: o-p23pass2
+%% Type: invalid
+%% Sections: 2.8 [23]
+'o-p23pass2'(suite) -> [];
+'o-p23pass2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p23pass2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p23pass3.xml
+%% ID: o-p23pass3
+%% Type: invalid
+%% Sections: 2.8 [23]
+'o-p23pass3'(suite) -> [];
+'o-p23pass3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p23pass3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p23pass4.xml
+%% ID: o-p23pass4
+%% Type: invalid
+%% Sections: 2.8 [23]
+'o-p23pass4'(suite) -> [];
+'o-p23pass4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p23pass4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p24pass1.xml
+%% ID: o-p24pass1
+%% Type: invalid
+%% Sections: 2.8 [24]
+'o-p24pass1'(suite) -> [];
+'o-p24pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p24pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p24pass2.xml
+%% ID: o-p24pass2
+%% Type: invalid
+%% Sections: 2.8 [24]
+'o-p24pass2'(suite) -> [];
+'o-p24pass2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p24pass2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p24pass3.xml
+%% ID: o-p24pass3
+%% Type: invalid
+%% Sections: 2.8 [24]
+'o-p24pass3'(suite) -> [];
+'o-p24pass3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p24pass3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p24pass4.xml
+%% ID: o-p24pass4
+%% Type: invalid
+%% Sections: 2.8 [24]
+'o-p24pass4'(suite) -> [];
+'o-p24pass4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p24pass4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p25pass1.xml
+%% ID: o-p25pass1
+%% Type: invalid
+%% Sections: 2.8 [25]
+'o-p25pass1'(suite) -> [];
+'o-p25pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p25pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p25pass2.xml
+%% ID: o-p25pass2
+%% Type: invalid
+%% Sections: 2.8 [25]
+'o-p25pass2'(suite) -> [];
+'o-p25pass2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p25pass2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p26pass1.xml
+%% ID: o-p26pass1
+%% Type: invalid
+%% Sections: 2.8 [26]
+'o-p26pass1'(suite) -> [];
+'o-p26pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p26pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p27pass1.xml
+%% ID: o-p27pass1
+%% Type: invalid
+%% Sections: 2.8 [27]
+'o-p27pass1'(suite) -> [];
+'o-p27pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p27pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p27pass2.xml
+%% ID: o-p27pass2
+%% Type: invalid
+%% Sections: 2.8 [27]
+'o-p27pass2'(suite) -> [];
+'o-p27pass2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p27pass2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p27pass3.xml
+%% ID: o-p27pass3
+%% Type: invalid
+%% Sections: 2.8 [27]
+'o-p27pass3'(suite) -> [];
+'o-p27pass3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p27pass3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p27pass4.xml
+%% ID: o-p27pass4
+%% Type: invalid
+%% Sections: 2.8 [27]
+'o-p27pass4'(suite) -> [];
+'o-p27pass4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p27pass4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p32pass1.xml
+%% ID: o-p32pass1
+%% Type: invalid
+%% Sections: 2.9 [32]
+'o-p32pass1'(suite) -> [];
+'o-p32pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p32pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p32pass2.xml
+%% ID: o-p32pass2
+%% Type: invalid
+%% Sections: 2.9 [32]
+'o-p32pass2'(suite) -> [];
+'o-p32pass2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p32pass2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p39pass1.xml
+%% ID: o-p39pass1
+%% Type: invalid
+%% Sections: 3 3.1 [39] [44]
+'o-p39pass1'(suite) -> [];
+'o-p39pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p39pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p39pass2.xml
+%% ID: o-p39pass2
+%% Type: invalid
+%% Sections: 3 3.1 [39] [43]
+'o-p39pass2'(suite) -> [];
+'o-p39pass2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p39pass2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p40pass1.xml
+%% ID: o-p40pass1
+%% Type: invalid
+%% Sections: 3.1 [40]
+'o-p40pass1'(suite) -> [];
+'o-p40pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p40pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p40pass2.xml
+%% ID: o-p40pass2
+%% Type: invalid
+%% Sections: 3.1 [40]
+'o-p40pass2'(suite) -> [];
+'o-p40pass2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p40pass2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p40pass3.xml
+%% ID: o-p40pass3
+%% Type: invalid
+%% Sections: 3.1 [40] [41]
+'o-p40pass3'(suite) -> [];
+'o-p40pass3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p40pass3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p40pass4.xml
+%% ID: o-p40pass4
+%% Type: invalid
+%% Sections: 3.1 [40]
+'o-p40pass4'(suite) -> [];
+'o-p40pass4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p40pass4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p41pass1.xml
+%% ID: o-p41pass1
+%% Type: invalid
+%% Sections: 3.1 [41]
+'o-p41pass1'(suite) -> [];
+'o-p41pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p41pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p41pass2.xml
+%% ID: o-p41pass2
+%% Type: invalid
+%% Sections: 3.1 [41]
+'o-p41pass2'(suite) -> [];
+'o-p41pass2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p41pass2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p42pass1.xml
+%% ID: o-p42pass1
+%% Type: invalid
+%% Sections: 3.1 [42]
+'o-p42pass1'(suite) -> [];
+'o-p42pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p42pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p42pass2.xml
+%% ID: o-p42pass2
+%% Type: invalid
+%% Sections: 3.1 [42]
+'o-p42pass2'(suite) -> [];
+'o-p42pass2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p42pass2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p44pass1.xml
+%% ID: o-p44pass1
+%% Type: invalid
+%% Sections: 3.1 [44]
+'o-p44pass1'(suite) -> [];
+'o-p44pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p44pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p44pass2.xml
+%% ID: o-p44pass2
+%% Type: invalid
+%% Sections: 3.1 [44]
+'o-p44pass2'(suite) -> [];
+'o-p44pass2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p44pass2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p44pass3.xml
+%% ID: o-p44pass3
+%% Type: invalid
+%% Sections: 3.1 [44]
+'o-p44pass3'(suite) -> [];
+'o-p44pass3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p44pass3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p44pass4.xml
+%% ID: o-p44pass4
+%% Type: invalid
+%% Sections: 3.1 [44]
+'o-p44pass4'(suite) -> [];
+'o-p44pass4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p44pass4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p44pass5.xml
+%% ID: o-p44pass5
+%% Type: invalid
+%% Sections: 3.1 [44]
+'o-p44pass5'(suite) -> [];
+'o-p44pass5'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p44pass5.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p66pass1.xml
+%% ID: o-p66pass1
+%% Type: invalid
+%% Sections: 4.1 [66]
+'o-p66pass1'(suite) -> [];
+'o-p66pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p66pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p74pass1.xml
+%% ID: o-p74pass1
+%% Type: invalid
+%% Sections: 4.2 [74]
+'o-p74pass1'(suite) -> [];
+'o-p74pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p74pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p75pass1.xml
+%% ID: o-p75pass1
+%% Type: invalid
+%% Sections: 4.2.2 [75]
+'o-p75pass1'(suite) -> [];
+'o-p75pass1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p75pass1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: e2.xml
+%% ID: o-e2
+%% Type: invalid
+%% Sections: 3.3.1 [58] [59] Errata [E2]
+'o-e2'(suite) -> [];
+'o-e2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","e2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p01fail1.xml
+%% ID: o-p01fail1
+%% Type: not-wf
+%% Sections: 2.1 [1]
+'o-p01fail1'(suite) -> [];
+'o-p01fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p01fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p01fail2.xml
+%% ID: o-p01fail2
+%% Type: not-wf
+%% Sections: 2.1 [1]
+'o-p01fail2'(suite) -> [];
+'o-p01fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p01fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p01fail3.xml
+%% ID: o-p01fail3
+%% Type: not-wf
+%% Sections: 2.1 [1]
+'o-p01fail3'(suite) -> [];
+'o-p01fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p01fail3.xml"]),
+ %% Special case becase we returns everything after a legal document
+ %% as an rest instead of giving and error to let the user handle
+ %% multipple docs on a stream.
+ ?line {ok,_, <<"<bad/>", _/binary>>} = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]).
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p01fail4.xml
+%% ID: o-p01fail4
+%% Type: not-wf
+%% Sections: 2.1 [1]
+'o-p01fail4'(suite) -> [];
+'o-p01fail4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p01fail4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail1.xml
+%% ID: o-p02fail1
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail1'(suite) -> [];
+'o-p02fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail10.xml
+%% ID: o-p02fail10
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail10'(suite) -> [];
+'o-p02fail10'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail10.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail11.xml
+%% ID: o-p02fail11
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail11'(suite) -> [];
+'o-p02fail11'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail11.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail12.xml
+%% ID: o-p02fail12
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail12'(suite) -> [];
+'o-p02fail12'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail12.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail13.xml
+%% ID: o-p02fail13
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail13'(suite) -> [];
+'o-p02fail13'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail13.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail14.xml
+%% ID: o-p02fail14
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail14'(suite) -> [];
+'o-p02fail14'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail14.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail15.xml
+%% ID: o-p02fail15
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail15'(suite) -> [];
+'o-p02fail15'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail15.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail16.xml
+%% ID: o-p02fail16
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail16'(suite) -> [];
+'o-p02fail16'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail16.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail17.xml
+%% ID: o-p02fail17
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail17'(suite) -> [];
+'o-p02fail17'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail17.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail18.xml
+%% ID: o-p02fail18
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail18'(suite) -> [];
+'o-p02fail18'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail18.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail19.xml
+%% ID: o-p02fail19
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail19'(suite) -> [];
+'o-p02fail19'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail19.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail2.xml
+%% ID: o-p02fail2
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail2'(suite) -> [];
+'o-p02fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail20.xml
+%% ID: o-p02fail20
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail20'(suite) -> [];
+'o-p02fail20'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail20.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail21.xml
+%% ID: o-p02fail21
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail21'(suite) -> [];
+'o-p02fail21'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail21.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail22.xml
+%% ID: o-p02fail22
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail22'(suite) -> [];
+'o-p02fail22'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail22.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail23.xml
+%% ID: o-p02fail23
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail23'(suite) -> [];
+'o-p02fail23'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail23.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail24.xml
+%% ID: o-p02fail24
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail24'(suite) -> [];
+'o-p02fail24'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail24.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail25.xml
+%% ID: o-p02fail25
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail25'(suite) -> [];
+'o-p02fail25'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail25.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail26.xml
+%% ID: o-p02fail26
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail26'(suite) -> [];
+'o-p02fail26'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail26.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail27.xml
+%% ID: o-p02fail27
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail27'(suite) -> [];
+'o-p02fail27'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail27.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail28.xml
+%% ID: o-p02fail28
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail28'(suite) -> [];
+'o-p02fail28'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail28.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail29.xml
+%% ID: o-p02fail29
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail29'(suite) -> [];
+'o-p02fail29'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail29.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail3.xml
+%% ID: o-p02fail3
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail3'(suite) -> [];
+'o-p02fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail30.xml
+%% ID: o-p02fail30
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail30'(suite) -> [];
+'o-p02fail30'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail30.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail31.xml
+%% ID: o-p02fail31
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail31'(suite) -> [];
+'o-p02fail31'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail31.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail4.xml
+%% ID: o-p02fail4
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail4'(suite) -> [];
+'o-p02fail4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail5.xml
+%% ID: o-p02fail5
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail5'(suite) -> [];
+'o-p02fail5'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail5.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail6.xml
+%% ID: o-p02fail6
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail6'(suite) -> [];
+'o-p02fail6'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail6.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail7.xml
+%% ID: o-p02fail7
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail7'(suite) -> [];
+'o-p02fail7'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail7.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail8.xml
+%% ID: o-p02fail8
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail8'(suite) -> [];
+'o-p02fail8'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail8.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p02fail9.xml
+%% ID: o-p02fail9
+%% Type: not-wf
+%% Sections: 2.2 [2]
+'o-p02fail9'(suite) -> [];
+'o-p02fail9'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p02fail9.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail1.xml
+%% ID: o-p03fail1
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail1'(suite) -> [];
+'o-p03fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail10.xml
+%% ID: o-p03fail10
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail10'(suite) -> [];
+'o-p03fail10'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail10.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail11.xml
+%% ID: o-p03fail11
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail11'(suite) -> [];
+'o-p03fail11'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail11.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail12.xml
+%% ID: o-p03fail12
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail12'(suite) -> [];
+'o-p03fail12'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail12.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail13.xml
+%% ID: o-p03fail13
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail13'(suite) -> [];
+'o-p03fail13'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail13.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail14.xml
+%% ID: o-p03fail14
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail14'(suite) -> [];
+'o-p03fail14'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail14.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail15.xml
+%% ID: o-p03fail15
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail15'(suite) -> [];
+'o-p03fail15'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail15.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail16.xml
+%% ID: o-p03fail16
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail16'(suite) -> [];
+'o-p03fail16'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail16.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail17.xml
+%% ID: o-p03fail17
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail17'(suite) -> [];
+'o-p03fail17'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail17.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail18.xml
+%% ID: o-p03fail18
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail18'(suite) -> [];
+'o-p03fail18'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail18.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail19.xml
+%% ID: o-p03fail19
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail19'(suite) -> [];
+'o-p03fail19'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail19.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail2.xml
+%% ID: o-p03fail2
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail2'(suite) -> [];
+'o-p03fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail20.xml
+%% ID: o-p03fail20
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail20'(suite) -> [];
+'o-p03fail20'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail20.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail21.xml
+%% ID: o-p03fail21
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail21'(suite) -> [];
+'o-p03fail21'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail21.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail22.xml
+%% ID: o-p03fail22
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail22'(suite) -> [];
+'o-p03fail22'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail22.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail23.xml
+%% ID: o-p03fail23
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail23'(suite) -> [];
+'o-p03fail23'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail23.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail24.xml
+%% ID: o-p03fail24
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail24'(suite) -> [];
+'o-p03fail24'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail24.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail25.xml
+%% ID: o-p03fail25
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail25'(suite) -> [];
+'o-p03fail25'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail25.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail26.xml
+%% ID: o-p03fail26
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail26'(suite) -> [];
+'o-p03fail26'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail26.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail27.xml
+%% ID: o-p03fail27
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail27'(suite) -> [];
+'o-p03fail27'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail27.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail28.xml
+%% ID: o-p03fail28
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail28'(suite) -> [];
+'o-p03fail28'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail28.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail29.xml
+%% ID: o-p03fail29
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail29'(suite) -> [];
+'o-p03fail29'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail29.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail3.xml
+%% ID: o-p03fail3
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail3'(suite) -> [];
+'o-p03fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail4.xml
+%% ID: o-p03fail4
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail4'(suite) -> [];
+'o-p03fail4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail5.xml
+%% ID: o-p03fail5
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail5'(suite) -> [];
+'o-p03fail5'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail5.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail7.xml
+%% ID: o-p03fail7
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail7'(suite) -> [];
+'o-p03fail7'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail7.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail8.xml
+%% ID: o-p03fail8
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail8'(suite) -> [];
+'o-p03fail8'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail8.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p03fail9.xml
+%% ID: o-p03fail9
+%% Type: not-wf
+%% Sections: 2.3 [3]
+'o-p03fail9'(suite) -> [];
+'o-p03fail9'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p03fail9.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p04fail1.xml
+%% ID: o-p04fail1
+%% Type: not-wf
+%% Sections: 2.3 [4]
+'o-p04fail1'(suite) -> [];
+'o-p04fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p04fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p04fail2.xml
+%% ID: o-p04fail2
+%% Type: not-wf
+%% Sections: 2.3 [4]
+'o-p04fail2'(suite) -> [];
+'o-p04fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p04fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p04fail3.xml
+%% ID: o-p04fail3
+%% Type: not-wf
+%% Sections: 2.3 [4]
+'o-p04fail3'(suite) -> [];
+'o-p04fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p04fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p05fail1.xml
+%% ID: o-p05fail1
+%% Type: not-wf
+%% Sections: 2.3 [5]
+'o-p05fail1'(suite) -> [];
+'o-p05fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p05fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p05fail2.xml
+%% ID: o-p05fail2
+%% Type: not-wf
+%% Sections: 2.3 [5]
+'o-p05fail2'(suite) -> [];
+'o-p05fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p05fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p05fail3.xml
+%% ID: o-p05fail3
+%% Type: not-wf
+%% Sections: 2.3 [5]
+'o-p05fail3'(suite) -> [];
+'o-p05fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p05fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p05fail4.xml
+%% ID: o-p05fail4
+%% Type: not-wf
+%% Sections: 2.3 [5]
+'o-p05fail4'(suite) -> [];
+'o-p05fail4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p05fail4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p05fail5.xml
+%% ID: o-p05fail5
+%% Type: not-wf
+%% Sections: 2.3 [5]
+'o-p05fail5'(suite) -> [];
+'o-p05fail5'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p05fail5.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p09fail1.xml
+%% ID: o-p09fail1
+%% Type: not-wf
+%% Sections: 2.3 [9]
+'o-p09fail1'(suite) -> [];
+'o-p09fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p09fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p09fail2.xml
+%% ID: o-p09fail2
+%% Type: not-wf
+%% Sections: 2.3 [9]
+'o-p09fail2'(suite) -> [];
+'o-p09fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p09fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p09fail3.xml
+%% ID: o-p09fail3
+%% Type: not-wf
+%% Sections: 2.3 [9]
+'o-p09fail3'(suite) -> [];
+'o-p09fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p09fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p09fail4.xml
+%% ID: o-p09fail4
+%% Type: not-wf
+%% Sections: 2.3 [9]
+'o-p09fail4'(suite) -> [];
+'o-p09fail4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p09fail4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p09fail5.xml
+%% ID: o-p09fail5
+%% Type: not-wf
+%% Sections: 2.3 [9]
+'o-p09fail5'(suite) -> [];
+'o-p09fail5'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p09fail5.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p10fail1.xml
+%% ID: o-p10fail1
+%% Type: not-wf
+%% Sections: 2.3 [10]
+'o-p10fail1'(suite) -> [];
+'o-p10fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p10fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p10fail2.xml
+%% ID: o-p10fail2
+%% Type: not-wf
+%% Sections: 2.3 [10]
+'o-p10fail2'(suite) -> [];
+'o-p10fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p10fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p10fail3.xml
+%% ID: o-p10fail3
+%% Type: not-wf
+%% Sections: 2.3 [10]
+'o-p10fail3'(suite) -> [];
+'o-p10fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p10fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p11fail1.xml
+%% ID: o-p11fail1
+%% Type: not-wf
+%% Sections: 2.3 [11]
+'o-p11fail1'(suite) -> [];
+'o-p11fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p11fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p11fail2.xml
+%% ID: o-p11fail2
+%% Type: not-wf
+%% Sections: 2.3 [11]
+'o-p11fail2'(suite) -> [];
+'o-p11fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p11fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p12fail1.xml
+%% ID: o-p12fail1
+%% Type: not-wf
+%% Sections: 2.3 [12]
+'o-p12fail1'(suite) -> [];
+'o-p12fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p12fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p12fail2.xml
+%% ID: o-p12fail2
+%% Type: not-wf
+%% Sections: 2.3 [12]
+'o-p12fail2'(suite) -> [];
+'o-p12fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p12fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p12fail3.xml
+%% ID: o-p12fail3
+%% Type: not-wf
+%% Sections: 2.3 [12]
+'o-p12fail3'(suite) -> [];
+'o-p12fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p12fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p12fail4.xml
+%% ID: o-p12fail4
+%% Type: not-wf
+%% Sections: 2.3 [12]
+'o-p12fail4'(suite) -> [];
+'o-p12fail4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p12fail4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p12fail5.xml
+%% ID: o-p12fail5
+%% Type: not-wf
+%% Sections: 2.3 [12]
+'o-p12fail5'(suite) -> [];
+'o-p12fail5'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p12fail5.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p12fail6.xml
+%% ID: o-p12fail6
+%% Type: not-wf
+%% Sections: 2.3 [12]
+'o-p12fail6'(suite) -> [];
+'o-p12fail6'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p12fail6.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p12fail7.xml
+%% ID: o-p12fail7
+%% Type: not-wf
+%% Sections: 2.3 [13]
+'o-p12fail7'(suite) -> [];
+'o-p12fail7'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p12fail7.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p14fail1.xml
+%% ID: o-p14fail1
+%% Type: not-wf
+%% Sections: 2.4 [14]
+'o-p14fail1'(suite) -> [];
+'o-p14fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p14fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p14fail2.xml
+%% ID: o-p14fail2
+%% Type: not-wf
+%% Sections: 2.4 [14]
+'o-p14fail2'(suite) -> [];
+'o-p14fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p14fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p14fail3.xml
+%% ID: o-p14fail3
+%% Type: not-wf
+%% Sections: 2.4 [14]
+'o-p14fail3'(suite) -> [];
+'o-p14fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p14fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p15fail1.xml
+%% ID: o-p15fail1
+%% Type: not-wf
+%% Sections: 2.5 [15]
+'o-p15fail1'(suite) -> [];
+'o-p15fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p15fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p15fail2.xml
+%% ID: o-p15fail2
+%% Type: not-wf
+%% Sections: 2.5 [15]
+'o-p15fail2'(suite) -> [];
+'o-p15fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p15fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p15fail3.xml
+%% ID: o-p15fail3
+%% Type: not-wf
+%% Sections: 2.5 [15]
+'o-p15fail3'(suite) -> [];
+'o-p15fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p15fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p16fail1.xml
+%% ID: o-p16fail1
+%% Type: not-wf
+%% Sections: 2.6 [16]
+'o-p16fail1'(suite) -> [];
+'o-p16fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p16fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p16fail2.xml
+%% ID: o-p16fail2
+%% Type: not-wf
+%% Sections: 2.6 [16]
+'o-p16fail2'(suite) -> [];
+'o-p16fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p16fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p16fail3.xml
+%% ID: o-p16fail3
+%% Type: not-wf
+%% Sections: 2.6 [16]
+'o-p16fail3'(suite) -> [];
+'o-p16fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p16fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p18fail1.xml
+%% ID: o-p18fail1
+%% Type: not-wf
+%% Sections: 2.7 [18]
+'o-p18fail1'(suite) -> [];
+'o-p18fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p18fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p18fail2.xml
+%% ID: o-p18fail2
+%% Type: not-wf
+%% Sections: 2.7 [18]
+'o-p18fail2'(suite) -> [];
+'o-p18fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p18fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p18fail3.xml
+%% ID: o-p18fail3
+%% Type: not-wf
+%% Sections: 2.7 [18]
+'o-p18fail3'(suite) -> [];
+'o-p18fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p18fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p22fail1.xml
+%% ID: o-p22fail1
+%% Type: not-wf
+%% Sections: 2.8 [22]
+'o-p22fail1'(suite) -> [];
+'o-p22fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p22fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p22fail2.xml
+%% ID: o-p22fail2
+%% Type: not-wf
+%% Sections: 2.8 [22]
+'o-p22fail2'(suite) -> [];
+'o-p22fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p22fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p23fail1.xml
+%% ID: o-p23fail1
+%% Type: not-wf
+%% Sections: 2.8 [23]
+'o-p23fail1'(suite) -> [];
+'o-p23fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p23fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p23fail2.xml
+%% ID: o-p23fail2
+%% Type: not-wf
+%% Sections: 2.8 [23]
+'o-p23fail2'(suite) -> [];
+'o-p23fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p23fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p23fail3.xml
+%% ID: o-p23fail3
+%% Type: not-wf
+%% Sections: 2.8 [23]
+'o-p23fail3'(suite) -> [];
+'o-p23fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p23fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p23fail4.xml
+%% ID: o-p23fail4
+%% Type: not-wf
+%% Sections: 2.8 [23]
+'o-p23fail4'(suite) -> [];
+'o-p23fail4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p23fail4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p23fail5.xml
+%% ID: o-p23fail5
+%% Type: not-wf
+%% Sections: 2.8 [23]
+'o-p23fail5'(suite) -> [];
+'o-p23fail5'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p23fail5.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p24fail1.xml
+%% ID: o-p24fail1
+%% Type: not-wf
+%% Sections: 2.8 [24]
+'o-p24fail1'(suite) -> [];
+'o-p24fail1'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p24fail1.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p24fail2.xml
+%% ID: o-p24fail2
+%% Type: not-wf
+%% Sections: 2.8 [24]
+'o-p24fail2'(suite) -> [];
+'o-p24fail2'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p24fail2.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p25fail1.xml
+%% ID: o-p25fail1
+%% Type: not-wf
+%% Sections: 2.8 [25]
+'o-p25fail1'(suite) -> [];
+'o-p25fail1'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p25fail1.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p26fail1.xml
+%% ID: o-p26fail1
+%% Type: not-wf
+%% Sections: 2.8 [26]
+'o-p26fail1'(suite) -> [];
+'o-p26fail1'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p26fail1.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p26fail2.xml
+%% ID: o-p26fail2
+%% Type: not-wf
+%% Sections: 2.8 [26]
+'o-p26fail2'(suite) -> [];
+'o-p26fail2'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p26fail2.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p27fail1.xml
+%% ID: o-p27fail1
+%% Type: not-wf
+%% Sections: 2.8 [27]
+'o-p27fail1'(suite) -> [];
+'o-p27fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p27fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p28fail1.xml
+%% ID: o-p28fail1
+%% Type: not-wf
+%% Sections: 2.8 [28]
+'o-p28fail1'(suite) -> [];
+'o-p28fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p28fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p29fail1.xml
+%% ID: o-p29fail1
+%% Type: not-wf
+%% Sections: 2.8 [29]
+'o-p29fail1'(suite) -> [];
+'o-p29fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p29fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p30fail1.xml
+%% ID: o-p30fail1
+%% Type: not-wf
+%% Sections: 2.8 [30]
+'o-p30fail1'(suite) -> [];
+'o-p30fail1'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p30fail1.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p31fail1.xml
+%% ID: o-p31fail1
+%% Type: not-wf
+%% Sections: 2.8 [31]
+'o-p31fail1'(suite) -> [];
+'o-p31fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p31fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p32fail1.xml
+%% ID: o-p32fail1
+%% Type: not-wf
+%% Sections: 2.9 [32]
+'o-p32fail1'(suite) -> [];
+'o-p32fail1'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p32fail1.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p32fail2.xml
+%% ID: o-p32fail2
+%% Type: not-wf
+%% Sections: 2.9 [32]
+'o-p32fail2'(suite) -> [];
+'o-p32fail2'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p32fail2.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p32fail3.xml
+%% ID: o-p32fail3
+%% Type: not-wf
+%% Sections: 2.9 [32]
+'o-p32fail3'(suite) -> [];
+'o-p32fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p32fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p32fail4.xml
+%% ID: o-p32fail4
+%% Type: not-wf
+%% Sections: 2.9 [32]
+'o-p32fail4'(suite) -> [];
+'o-p32fail4'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p32fail4.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p32fail5.xml
+%% ID: o-p32fail5
+%% Type: not-wf
+%% Sections: 2.9 [32]
+'o-p32fail5'(suite) -> [];
+'o-p32fail5'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p32fail5.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p39fail1.xml
+%% ID: o-p39fail1
+%% Type: not-wf
+%% Sections: 3 [39]
+'o-p39fail1'(suite) -> [];
+'o-p39fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p39fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p39fail2.xml
+%% ID: o-p39fail2
+%% Type: not-wf
+%% Sections: 3 [39]
+'o-p39fail2'(suite) -> [];
+'o-p39fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p39fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p39fail3.xml
+%% ID: o-p39fail3
+%% Type: not-wf
+%% Sections: 3 [39]
+'o-p39fail3'(suite) -> [];
+'o-p39fail3'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p39fail3.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p39fail4.xml
+%% ID: o-p39fail4
+%% Type: not-wf
+%% Sections: 2.8 [23]
+'o-p39fail4'(suite) -> [];
+'o-p39fail4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p39fail4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p39fail5.xml
+%% ID: o-p39fail5
+%% Type: not-wf
+%% Sections: 2.8 [23]
+'o-p39fail5'(suite) -> [];
+'o-p39fail5'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p39fail5.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p40fail1.xml
+%% ID: o-p40fail1
+%% Type: not-wf
+%% Sections: 3.1 [40]
+'o-p40fail1'(suite) -> [];
+'o-p40fail1'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p40fail1.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p40fail2.xml
+%% ID: o-p40fail2
+%% Type: not-wf
+%% Sections: 3.1 [40]
+'o-p40fail2'(suite) -> [];
+'o-p40fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p40fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p40fail3.xml
+%% ID: o-p40fail3
+%% Type: not-wf
+%% Sections: 3.1 [40]
+'o-p40fail3'(suite) -> [];
+'o-p40fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p40fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p40fail4.xml
+%% ID: o-p40fail4
+%% Type: not-wf
+%% Sections: 3.1 [40]
+'o-p40fail4'(suite) -> [];
+'o-p40fail4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p40fail4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p41fail1.xml
+%% ID: o-p41fail1
+%% Type: not-wf
+%% Sections: 3.1 [41]
+'o-p41fail1'(suite) -> [];
+'o-p41fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p41fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p41fail2.xml
+%% ID: o-p41fail2
+%% Type: not-wf
+%% Sections: 3.1 [41]
+'o-p41fail2'(suite) -> [];
+'o-p41fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p41fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p41fail3.xml
+%% ID: o-p41fail3
+%% Type: not-wf
+%% Sections: 3.1 [41]
+'o-p41fail3'(suite) -> [];
+'o-p41fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p41fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p42fail1.xml
+%% ID: o-p42fail1
+%% Type: not-wf
+%% Sections: 3.1 [42]
+'o-p42fail1'(suite) -> [];
+'o-p42fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p42fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p42fail2.xml
+%% ID: o-p42fail2
+%% Type: not-wf
+%% Sections: 3.1 [42]
+'o-p42fail2'(suite) -> [];
+'o-p42fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p42fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p42fail3.xml
+%% ID: o-p42fail3
+%% Type: not-wf
+%% Sections: 3.1 [42]
+'o-p42fail3'(suite) -> [];
+'o-p42fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p42fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p43fail1.xml
+%% ID: o-p43fail1
+%% Type: not-wf
+%% Sections: 3.1 [43]
+'o-p43fail1'(suite) -> [];
+'o-p43fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p43fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p43fail2.xml
+%% ID: o-p43fail2
+%% Type: not-wf
+%% Sections: 3.1 [43]
+'o-p43fail2'(suite) -> [];
+'o-p43fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p43fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p43fail3.xml
+%% ID: o-p43fail3
+%% Type: not-wf
+%% Sections: 3.1 [43]
+'o-p43fail3'(suite) -> [];
+'o-p43fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p43fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p44fail1.xml
+%% ID: o-p44fail1
+%% Type: not-wf
+%% Sections: 3.1 [44]
+'o-p44fail1'(suite) -> [];
+'o-p44fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p44fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p44fail2.xml
+%% ID: o-p44fail2
+%% Type: not-wf
+%% Sections: 3.1 [44]
+'o-p44fail2'(suite) -> [];
+'o-p44fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p44fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p44fail3.xml
+%% ID: o-p44fail3
+%% Type: not-wf
+%% Sections: 3.1 [44]
+'o-p44fail3'(suite) -> [];
+'o-p44fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p44fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p44fail4.xml
+%% ID: o-p44fail4
+%% Type: not-wf
+%% Sections: 3.1 [44]
+'o-p44fail4'(suite) -> [];
+'o-p44fail4'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p44fail4.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p44fail5.xml
+%% ID: o-p44fail5
+%% Type: not-wf
+%% Sections: 3.1 [44]
+'o-p44fail5'(suite) -> [];
+'o-p44fail5'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p44fail5.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p45fail1.xml
+%% ID: o-p45fail1
+%% Type: not-wf
+%% Sections: 3.2 [45]
+'o-p45fail1'(suite) -> [];
+'o-p45fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p45fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p45fail2.xml
+%% ID: o-p45fail2
+%% Type: not-wf
+%% Sections: 3.2 [45]
+'o-p45fail2'(suite) -> [];
+'o-p45fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p45fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p45fail3.xml
+%% ID: o-p45fail3
+%% Type: not-wf
+%% Sections: 3.2 [45]
+'o-p45fail3'(suite) -> [];
+'o-p45fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p45fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p45fail4.xml
+%% ID: o-p45fail4
+%% Type: not-wf
+%% Sections: 3.2 [45]
+'o-p45fail4'(suite) -> [];
+'o-p45fail4'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p45fail4.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p46fail1.xml
+%% ID: o-p46fail1
+%% Type: not-wf
+%% Sections: 3.2 [46]
+'o-p46fail1'(suite) -> [];
+'o-p46fail1'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p46fail1.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p46fail2.xml
+%% ID: o-p46fail2
+%% Type: not-wf
+%% Sections: 3.2 [46]
+'o-p46fail2'(suite) -> [];
+'o-p46fail2'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p46fail2.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p46fail3.xml
+%% ID: o-p46fail3
+%% Type: not-wf
+%% Sections: 3.2 [46]
+'o-p46fail3'(suite) -> [];
+'o-p46fail3'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p46fail3.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p46fail4.xml
+%% ID: o-p46fail4
+%% Type: not-wf
+%% Sections: 3.2 [46]
+'o-p46fail4'(suite) -> [];
+'o-p46fail4'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p46fail4.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p46fail5.xml
+%% ID: o-p46fail5
+%% Type: not-wf
+%% Sections: 3.2 [46]
+'o-p46fail5'(suite) -> [];
+'o-p46fail5'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p46fail5.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p46fail6.xml
+%% ID: o-p46fail6
+%% Type: not-wf
+%% Sections: 3.2 [46]
+'o-p46fail6'(suite) -> [];
+'o-p46fail6'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p46fail6.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p47fail1.xml
+%% ID: o-p47fail1
+%% Type: not-wf
+%% Sections: 3.2.1 [47]
+'o-p47fail1'(suite) -> [];
+'o-p47fail1'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p47fail1.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p47fail2.xml
+%% ID: o-p47fail2
+%% Type: not-wf
+%% Sections: 3.2.1 [47]
+'o-p47fail2'(suite) -> [];
+'o-p47fail2'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p47fail2.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p47fail3.xml
+%% ID: o-p47fail3
+%% Type: not-wf
+%% Sections: 3.2.1 [47]
+'o-p47fail3'(suite) -> [];
+'o-p47fail3'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p47fail3.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p47fail4.xml
+%% ID: o-p47fail4
+%% Type: not-wf
+%% Sections: 3.2.1 [47]
+'o-p47fail4'(suite) -> [];
+'o-p47fail4'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p47fail4.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p48fail1.xml
+%% ID: o-p48fail1
+%% Type: not-wf
+%% Sections: 3.2.1 [48]
+'o-p48fail1'(suite) -> [];
+'o-p48fail1'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p48fail1.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p48fail2.xml
+%% ID: o-p48fail2
+%% Type: not-wf
+%% Sections: 3.2.1 [48]
+'o-p48fail2'(suite) -> [];
+'o-p48fail2'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p48fail2.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p49fail1.xml
+%% ID: o-p49fail1
+%% Type: not-wf
+%% Sections: 3.2.1 [49]
+'o-p49fail1'(suite) -> [];
+'o-p49fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p49fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p50fail1.xml
+%% ID: o-p50fail1
+%% Type: not-wf
+%% Sections: 3.2.1 [50]
+'o-p50fail1'(suite) -> [];
+'o-p50fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p50fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p51fail1.xml
+%% ID: o-p51fail1
+%% Type: not-wf
+%% Sections: 3.2.2 [51]
+'o-p51fail1'(suite) -> [];
+'o-p51fail1'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p51fail1.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p51fail2.xml
+%% ID: o-p51fail2
+%% Type: not-wf
+%% Sections: 3.2.2 [51]
+'o-p51fail2'(suite) -> [];
+'o-p51fail2'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p51fail2.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p51fail3.xml
+%% ID: o-p51fail3
+%% Type: not-wf
+%% Sections: 3.2.2 [51]
+'o-p51fail3'(suite) -> [];
+'o-p51fail3'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p51fail3.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p51fail4.xml
+%% ID: o-p51fail4
+%% Type: not-wf
+%% Sections: 3.2.2 [51]
+'o-p51fail4'(suite) -> [];
+'o-p51fail4'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p51fail4.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p51fail5.xml
+%% ID: o-p51fail5
+%% Type: not-wf
+%% Sections: 3.2.2 [51]
+'o-p51fail5'(suite) -> [];
+'o-p51fail5'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p51fail5.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p51fail6.xml
+%% ID: o-p51fail6
+%% Type: not-wf
+%% Sections: 3.2.2 [51]
+'o-p51fail6'(suite) -> [];
+'o-p51fail6'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p51fail6.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p51fail7.xml
+%% ID: o-p51fail7
+%% Type: not-wf
+%% Sections: 3.2.2 [51]
+'o-p51fail7'(suite) -> [];
+'o-p51fail7'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p51fail7.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p52fail1.xml
+%% ID: o-p52fail1
+%% Type: not-wf
+%% Sections: 3.3 [52]
+'o-p52fail1'(suite) -> [];
+'o-p52fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p52fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p52fail2.xml
+%% ID: o-p52fail2
+%% Type: not-wf
+%% Sections: 3.3 [52]
+'o-p52fail2'(suite) -> [];
+'o-p52fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p52fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p53fail1.xml
+%% ID: o-p53fail1
+%% Type: not-wf
+%% Sections: 3.3 [53]
+'o-p53fail1'(suite) -> [];
+'o-p53fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p53fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p53fail2.xml
+%% ID: o-p53fail2
+%% Type: not-wf
+%% Sections: 3.3 [53]
+'o-p53fail2'(suite) -> [];
+'o-p53fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p53fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p53fail3.xml
+%% ID: o-p53fail3
+%% Type: not-wf
+%% Sections: 3.3 [53]
+'o-p53fail3'(suite) -> [];
+'o-p53fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p53fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p53fail4.xml
+%% ID: o-p53fail4
+%% Type: not-wf
+%% Sections: 3.3 [53]
+'o-p53fail4'(suite) -> [];
+'o-p53fail4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p53fail4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p53fail5.xml
+%% ID: o-p53fail5
+%% Type: not-wf
+%% Sections: 3.3 [53]
+'o-p53fail5'(suite) -> [];
+'o-p53fail5'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p53fail5.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p54fail1.xml
+%% ID: o-p54fail1
+%% Type: not-wf
+%% Sections: 3.3.1 [54]
+'o-p54fail1'(suite) -> [];
+'o-p54fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p54fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p55fail1.xml
+%% ID: o-p55fail1
+%% Type: not-wf
+%% Sections: 3.3.1 [55]
+'o-p55fail1'(suite) -> [];
+'o-p55fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p55fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p56fail1.xml
+%% ID: o-p56fail1
+%% Type: not-wf
+%% Sections: 3.3.1 [56]
+'o-p56fail1'(suite) -> [];
+'o-p56fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p56fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p56fail2.xml
+%% ID: o-p56fail2
+%% Type: not-wf
+%% Sections: 3.3.1 [56]
+'o-p56fail2'(suite) -> [];
+'o-p56fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p56fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p56fail3.xml
+%% ID: o-p56fail3
+%% Type: not-wf
+%% Sections: 3.3.1 [56]
+'o-p56fail3'(suite) -> [];
+'o-p56fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p56fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p56fail4.xml
+%% ID: o-p56fail4
+%% Type: not-wf
+%% Sections: 3.3.1 [56]
+'o-p56fail4'(suite) -> [];
+'o-p56fail4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p56fail4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p56fail5.xml
+%% ID: o-p56fail5
+%% Type: not-wf
+%% Sections: 3.3.1 [56]
+'o-p56fail5'(suite) -> [];
+'o-p56fail5'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p56fail5.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p57fail1.xml
+%% ID: o-p57fail1
+%% Type: not-wf
+%% Sections: 3.3.1 [57]
+'o-p57fail1'(suite) -> [];
+'o-p57fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p57fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p58fail1.xml
+%% ID: o-p58fail1
+%% Type: not-wf
+%% Sections: 3.3.1 [58]
+'o-p58fail1'(suite) -> [];
+'o-p58fail1'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p58fail1.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p58fail2.xml
+%% ID: o-p58fail2
+%% Type: not-wf
+%% Sections: 3.3.1 [58]
+'o-p58fail2'(suite) -> [];
+'o-p58fail2'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p58fail2.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p58fail3.xml
+%% ID: o-p58fail3
+%% Type: not-wf
+%% Sections: 3.3.1 [58]
+'o-p58fail3'(suite) -> [];
+'o-p58fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p58fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p58fail4.xml
+%% ID: o-p58fail4
+%% Type: not-wf
+%% Sections: 3.3.1 [58]
+'o-p58fail4'(suite) -> [];
+'o-p58fail4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p58fail4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p58fail5.xml
+%% ID: o-p58fail5
+%% Type: not-wf
+%% Sections: 3.3.1 [58]
+'o-p58fail5'(suite) -> [];
+'o-p58fail5'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p58fail5.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p58fail6.xml
+%% ID: o-p58fail6
+%% Type: not-wf
+%% Sections: 3.3.1 [58]
+'o-p58fail6'(suite) -> [];
+'o-p58fail6'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p58fail6.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p58fail7.xml
+%% ID: o-p58fail7
+%% Type: not-wf
+%% Sections: 3.3.1 [58]
+'o-p58fail7'(suite) -> [];
+'o-p58fail7'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p58fail7.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p58fail8.xml
+%% ID: o-p58fail8
+%% Type: not-wf
+%% Sections: 3.3.1 [58]
+'o-p58fail8'(suite) -> [];
+'o-p58fail8'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p58fail8.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p59fail1.xml
+%% ID: o-p59fail1
+%% Type: not-wf
+%% Sections: 3.3.1 [59]
+'o-p59fail1'(suite) -> [];
+'o-p59fail1'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p59fail1.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p59fail2.xml
+%% ID: o-p59fail2
+%% Type: not-wf
+%% Sections: 3.3.1 [59]
+'o-p59fail2'(suite) -> [];
+'o-p59fail2'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p59fail2.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p59fail3.xml
+%% ID: o-p59fail3
+%% Type: not-wf
+%% Sections: 3.3.1 [59]
+'o-p59fail3'(suite) -> [];
+'o-p59fail3'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p59fail3.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p60fail1.xml
+%% ID: o-p60fail1
+%% Type: not-wf
+%% Sections: 3.3.2 [60]
+'o-p60fail1'(suite) -> [];
+'o-p60fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p60fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p60fail2.xml
+%% ID: o-p60fail2
+%% Type: not-wf
+%% Sections: 3.3.2 [60]
+'o-p60fail2'(suite) -> [];
+'o-p60fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p60fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p60fail3.xml
+%% ID: o-p60fail3
+%% Type: not-wf
+%% Sections: 3.3.2 [60]
+'o-p60fail3'(suite) -> [];
+'o-p60fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p60fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p60fail4.xml
+%% ID: o-p60fail4
+%% Type: not-wf
+%% Sections: 3.3.2 [60]
+'o-p60fail4'(suite) -> [];
+'o-p60fail4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p60fail4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p60fail5.xml
+%% ID: o-p60fail5
+%% Type: not-wf
+%% Sections: 3.3.2 [60]
+'o-p60fail5'(suite) -> [];
+'o-p60fail5'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p60fail5.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p61fail1.xml
+%% ID: o-p61fail1
+%% Type: not-wf
+%% Sections: 3.4 [61]
+'o-p61fail1'(suite) -> [];
+'o-p61fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p61fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p62fail1.xml
+%% ID: o-p62fail1
+%% Type: not-wf
+%% Sections: 3.4 [62]
+'o-p62fail1'(suite) -> [];
+'o-p62fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p62fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p62fail2.xml
+%% ID: o-p62fail2
+%% Type: not-wf
+%% Sections: 3.4 [62]
+'o-p62fail2'(suite) -> [];
+'o-p62fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p62fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p63fail1.xml
+%% ID: o-p63fail1
+%% Type: not-wf
+%% Sections: 3.4 [63]
+'o-p63fail1'(suite) -> [];
+'o-p63fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p63fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p63fail2.xml
+%% ID: o-p63fail2
+%% Type: not-wf
+%% Sections: 3.4 [63]
+'o-p63fail2'(suite) -> [];
+'o-p63fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p63fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p64fail1.xml
+%% ID: o-p64fail1
+%% Type: not-wf
+%% Sections: 3.4 [64]
+'o-p64fail1'(suite) -> [];
+'o-p64fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p64fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p64fail2.xml
+%% ID: o-p64fail2
+%% Type: not-wf
+%% Sections: 3.4 [64]
+'o-p64fail2'(suite) -> [];
+'o-p64fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p64fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p66fail1.xml
+%% ID: o-p66fail1
+%% Type: not-wf
+%% Sections: 4.1 [66]
+'o-p66fail1'(suite) -> [];
+'o-p66fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p66fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p66fail2.xml
+%% ID: o-p66fail2
+%% Type: not-wf
+%% Sections: 4.1 [66]
+'o-p66fail2'(suite) -> [];
+'o-p66fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p66fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p66fail3.xml
+%% ID: o-p66fail3
+%% Type: not-wf
+%% Sections: 4.1 [66]
+'o-p66fail3'(suite) -> [];
+'o-p66fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p66fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p66fail4.xml
+%% ID: o-p66fail4
+%% Type: not-wf
+%% Sections: 4.1 [66]
+'o-p66fail4'(suite) -> [];
+'o-p66fail4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p66fail4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p66fail5.xml
+%% ID: o-p66fail5
+%% Type: not-wf
+%% Sections: 4.1 [66]
+'o-p66fail5'(suite) -> [];
+'o-p66fail5'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p66fail5.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p66fail6.xml
+%% ID: o-p66fail6
+%% Type: not-wf
+%% Sections: 4.1 [66]
+'o-p66fail6'(suite) -> [];
+'o-p66fail6'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p66fail6.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p68fail1.xml
+%% ID: o-p68fail1
+%% Type: not-wf
+%% Sections: 4.1 [68]
+'o-p68fail1'(suite) -> [];
+'o-p68fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p68fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p68fail2.xml
+%% ID: o-p68fail2
+%% Type: not-wf
+%% Sections: 4.1 [68]
+'o-p68fail2'(suite) -> [];
+'o-p68fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p68fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p68fail3.xml
+%% ID: o-p68fail3
+%% Type: not-wf
+%% Sections: 4.1 [68]
+'o-p68fail3'(suite) -> [];
+'o-p68fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p68fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p69fail1.xml
+%% ID: o-p69fail1
+%% Type: not-wf
+%% Sections: 4.1 [69]
+'o-p69fail1'(suite) -> [];
+'o-p69fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p69fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p69fail2.xml
+%% ID: o-p69fail2
+%% Type: not-wf
+%% Sections: 4.1 [69]
+'o-p69fail2'(suite) -> [];
+'o-p69fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p69fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p69fail3.xml
+%% ID: o-p69fail3
+%% Type: not-wf
+%% Sections: 4.1 [69]
+'o-p69fail3'(suite) -> [];
+'o-p69fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p69fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p70fail1.xml
+%% ID: o-p70fail1
+%% Type: not-wf
+%% Sections: 4.2 [70]
+'o-p70fail1'(suite) -> [];
+'o-p70fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p70fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p71fail1.xml
+%% ID: o-p71fail1
+%% Type: not-wf
+%% Sections: 4.2 [71]
+'o-p71fail1'(suite) -> [];
+'o-p71fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p71fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p71fail2.xml
+%% ID: o-p71fail2
+%% Type: not-wf
+%% Sections: 4.2 [71]
+'o-p71fail2'(suite) -> [];
+'o-p71fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p71fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p71fail3.xml
+%% ID: o-p71fail3
+%% Type: not-wf
+%% Sections: 4.2 [71]
+'o-p71fail3'(suite) -> [];
+'o-p71fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p71fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p71fail4.xml
+%% ID: o-p71fail4
+%% Type: not-wf
+%% Sections: 4.2 [71]
+'o-p71fail4'(suite) -> [];
+'o-p71fail4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p71fail4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p72fail1.xml
+%% ID: o-p72fail1
+%% Type: not-wf
+%% Sections: 4.2 [72]
+'o-p72fail1'(suite) -> [];
+'o-p72fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p72fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p72fail2.xml
+%% ID: o-p72fail2
+%% Type: not-wf
+%% Sections: 4.2 [72]
+'o-p72fail2'(suite) -> [];
+'o-p72fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p72fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p72fail3.xml
+%% ID: o-p72fail3
+%% Type: not-wf
+%% Sections: 4.2 [72]
+'o-p72fail3'(suite) -> [];
+'o-p72fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p72fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p72fail4.xml
+%% ID: o-p72fail4
+%% Type: not-wf
+%% Sections: 4.2 [72]
+'o-p72fail4'(suite) -> [];
+'o-p72fail4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p72fail4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p73fail1.xml
+%% ID: o-p73fail1
+%% Type: not-wf
+%% Sections: 4.2 [73]
+'o-p73fail1'(suite) -> [];
+'o-p73fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p73fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p73fail2.xml
+%% ID: o-p73fail2
+%% Type: not-wf
+%% Sections: 4.2 [73]
+'o-p73fail2'(suite) -> [];
+'o-p73fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p73fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p73fail3.xml
+%% ID: o-p73fail3
+%% Type: not-wf
+%% Sections: 4.2 [73]
+'o-p73fail3'(suite) -> [];
+'o-p73fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p73fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p73fail4.xml
+%% ID: o-p73fail4
+%% Type: not-wf
+%% Sections: 4.2 [73]
+'o-p73fail4'(suite) -> [];
+'o-p73fail4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p73fail4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p73fail5.xml
+%% ID: o-p73fail5
+%% Type: not-wf
+%% Sections: 4.2 [73]
+'o-p73fail5'(suite) -> [];
+'o-p73fail5'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p73fail5.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p74fail1.xml
+%% ID: o-p74fail1
+%% Type: not-wf
+%% Sections: 4.2 [74]
+'o-p74fail1'(suite) -> [];
+'o-p74fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p74fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p74fail2.xml
+%% ID: o-p74fail2
+%% Type: not-wf
+%% Sections: 4.2 [74]
+'o-p74fail2'(suite) -> [];
+'o-p74fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p74fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p74fail3.xml
+%% ID: o-p74fail3
+%% Type: not-wf
+%% Sections: 4.2 [74]
+'o-p74fail3'(suite) -> [];
+'o-p74fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p74fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p75fail1.xml
+%% ID: o-p75fail1
+%% Type: not-wf
+%% Sections: 4.2.2 [75]
+'o-p75fail1'(suite) -> [];
+'o-p75fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p75fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p75fail2.xml
+%% ID: o-p75fail2
+%% Type: not-wf
+%% Sections: 4.2.2 [75]
+'o-p75fail2'(suite) -> [];
+'o-p75fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p75fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p75fail3.xml
+%% ID: o-p75fail3
+%% Type: not-wf
+%% Sections: 4.2.2 [75]
+'o-p75fail3'(suite) -> [];
+'o-p75fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p75fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p75fail4.xml
+%% ID: o-p75fail4
+%% Type: not-wf
+%% Sections: 4.2.2 [75]
+'o-p75fail4'(suite) -> [];
+'o-p75fail4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p75fail4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p75fail5.xml
+%% ID: o-p75fail5
+%% Type: not-wf
+%% Sections: 4.2.2 [75]
+'o-p75fail5'(suite) -> [];
+'o-p75fail5'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p75fail5.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p75fail6.xml
+%% ID: o-p75fail6
+%% Type: not-wf
+%% Sections: 4.2.2 [75]
+'o-p75fail6'(suite) -> [];
+'o-p75fail6'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p75fail6.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p76fail1.xml
+%% ID: o-p76fail1
+%% Type: not-wf
+%% Sections: 4.2.2 [76]
+'o-p76fail1'(suite) -> [];
+'o-p76fail1'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p76fail1.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p76fail2.xml
+%% ID: o-p76fail2
+%% Type: not-wf
+%% Sections: 4.2.2 [76]
+'o-p76fail2'(suite) -> [];
+'o-p76fail2'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p76fail2.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p76fail3.xml
+%% ID: o-p76fail3
+%% Type: not-wf
+%% Sections: 4.2.2 [76]
+'o-p76fail3'(suite) -> [];
+'o-p76fail3'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p76fail3.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p76fail4.xml
+%% ID: o-p76fail4
+%% Type: not-wf
+%% Sections: 4.2.2 [76]
+'o-p76fail4'(suite) -> [];
+'o-p76fail4'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p76fail4.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: p11pass1.xml
+%% ID: o-p11pass1
+%% Type: error
+%% Sections: 2.3, 4.2.2 [11]
+'o-p11pass1'(suite) -> [];
+'o-p11pass1'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"oasis","p11pass1.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "error").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: OASIS/NIST TESTS, 1-Nov-1998
+
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: OASIS/NIST XML 1.0 Tests
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P28/ibm28i01.xml
+%% ID: ibm-invalid-P28-ibm28i01.xml
+%% Type: invalid
+%% Sections: 2.8
+'ibm-invalid-P28-ibm28i01'(suite) -> [];
+'ibm-invalid-P28-ibm28i01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P28/ibm28i01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 28
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P32/ibm32i01.xml
+%% ID: ibm-invalid-P32-ibm32i01.xml
+%% Type: invalid
+%% Sections: 2.9
+'ibm-invalid-P32-ibm32i01'(suite) -> [];
+'ibm-invalid-P32-ibm32i01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P32/ibm32i01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P32/ibm32i03.xml
+%% ID: ibm-invalid-P32-ibm32i03.xml
+%% Type: invalid
+%% Sections: 2.9
+'ibm-invalid-P32-ibm32i03'(suite) -> [];
+'ibm-invalid-P32-ibm32i03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P32/ibm32i03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P32/ibm32i04.xml
+%% ID: ibm-invalid-P32-ibm32i04.xml
+%% Type: invalid
+%% Sections: 2.9
+'ibm-invalid-P32-ibm32i04'(suite) -> [];
+'ibm-invalid-P32-ibm32i04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P32/ibm32i04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 32
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P39/ibm39i01.xml
+%% ID: ibm-invalid-P39-ibm39i01.xml
+%% Type: invalid
+%% Sections: 3
+'ibm-invalid-P39-ibm39i01'(suite) -> [];
+'ibm-invalid-P39-ibm39i01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P39/ibm39i01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P39/ibm39i02.xml
+%% ID: ibm-invalid-P39-ibm39i02.xml
+%% Type: invalid
+%% Sections: 3
+'ibm-invalid-P39-ibm39i02'(suite) -> [];
+'ibm-invalid-P39-ibm39i02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P39/ibm39i02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P39/ibm39i03.xml
+%% ID: ibm-invalid-P39-ibm39i03.xml
+%% Type: invalid
+%% Sections: 3
+'ibm-invalid-P39-ibm39i03'(suite) -> [];
+'ibm-invalid-P39-ibm39i03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P39/ibm39i03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P39/ibm39i04.xml
+%% ID: ibm-invalid-P39-ibm39i04.xml
+%% Type: invalid
+%% Sections: 3
+'ibm-invalid-P39-ibm39i04'(suite) -> [];
+'ibm-invalid-P39-ibm39i04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P39/ibm39i04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 39
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P41/ibm41i01.xml
+%% ID: ibm-invalid-P41-ibm41i01.xml
+%% Type: invalid
+%% Sections: 3.1
+'ibm-invalid-P41-ibm41i01'(suite) -> [];
+'ibm-invalid-P41-ibm41i01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P41/ibm41i01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P41/ibm41i02.xml
+%% ID: ibm-invalid-P41-ibm41i02.xml
+%% Type: invalid
+%% Sections: 3.1
+'ibm-invalid-P41-ibm41i02'(suite) -> [];
+'ibm-invalid-P41-ibm41i02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P41/ibm41i02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 41
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P45/ibm45i01.xml
+%% ID: ibm-invalid-P45-ibm45i01.xml
+%% Type: invalid
+%% Sections: 3.2
+'ibm-invalid-P45-ibm45i01'(suite) -> [];
+'ibm-invalid-P45-ibm45i01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P45/ibm45i01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 45
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P49/ibm49i01.xml
+%% ID: ibm-invalid-P49-ibm49i01.xml
+%% Type: invalid
+%% Sections: 3.2.1
+'ibm-invalid-P49-ibm49i01'(suite) -> [];
+'ibm-invalid-P49-ibm49i01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P49/ibm49i01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 49
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P50/ibm50i01.xml
+%% ID: ibm-invalid-P50-ibm50i01.xml
+%% Type: invalid
+%% Sections: 3.2.1
+'ibm-invalid-P50-ibm50i01'(suite) -> [];
+'ibm-invalid-P50-ibm50i01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P50/ibm50i01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 50
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P51/ibm51i01.xml
+%% ID: ibm-invalid-P51-ibm51i01.xml
+%% Type: invalid
+%% Sections: 3.2.2
+'ibm-invalid-P51-ibm51i01'(suite) -> [];
+'ibm-invalid-P51-ibm51i01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P51/ibm51i01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P51/ibm51i03.xml
+%% ID: ibm-invalid-P51-ibm51i03.xml
+%% Type: invalid
+%% Sections: 3.2.2
+'ibm-invalid-P51-ibm51i03'(suite) -> [];
+'ibm-invalid-P51-ibm51i03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P51/ibm51i03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 51
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P56/ibm56i01.xml
+%% ID: ibm-invalid-P56-ibm56i01.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P56-ibm56i01'(suite) -> [];
+'ibm-invalid-P56-ibm56i01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P56/ibm56i01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P56/ibm56i02.xml
+%% ID: ibm-invalid-P56-ibm56i02.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P56-ibm56i02'(suite) -> [];
+'ibm-invalid-P56-ibm56i02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P56/ibm56i02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P56/ibm56i03.xml
+%% ID: ibm-invalid-P56-ibm56i03.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P56-ibm56i03'(suite) -> [];
+'ibm-invalid-P56-ibm56i03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P56/ibm56i03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P56/ibm56i05.xml
+%% ID: ibm-invalid-P56-ibm56i05.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P56-ibm56i05'(suite) -> [];
+'ibm-invalid-P56-ibm56i05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P56/ibm56i05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P56/ibm56i06.xml
+%% ID: ibm-invalid-P56-ibm56i06.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P56-ibm56i06'(suite) -> [];
+'ibm-invalid-P56-ibm56i06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P56/ibm56i06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P56/ibm56i07.xml
+%% ID: ibm-invalid-P56-ibm56i07.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P56-ibm56i07'(suite) -> [];
+'ibm-invalid-P56-ibm56i07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P56/ibm56i07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P56/ibm56i08.xml
+%% ID: ibm-invalid-P56-ibm56i08.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P56-ibm56i08'(suite) -> [];
+'ibm-invalid-P56-ibm56i08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P56/ibm56i08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P56/ibm56i09.xml
+%% ID: ibm-invalid-P56-ibm56i09.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P56-ibm56i09'(suite) -> [];
+'ibm-invalid-P56-ibm56i09'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P56/ibm56i09.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P56/ibm56i10.xml
+%% ID: ibm-invalid-P56-ibm56i10.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P56-ibm56i10'(suite) -> [];
+'ibm-invalid-P56-ibm56i10'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P56/ibm56i10.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P56/ibm56i11.xml
+%% ID: ibm-invalid-P56-ibm56i11.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P56-ibm56i11'(suite) -> [];
+'ibm-invalid-P56-ibm56i11'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P56/ibm56i11.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P56/ibm56i12.xml
+%% ID: ibm-invalid-P56-ibm56i12.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P56-ibm56i12'(suite) -> [];
+'ibm-invalid-P56-ibm56i12'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P56/ibm56i12.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P56/ibm56i13.xml
+%% ID: ibm-invalid-P56-ibm56i13.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P56-ibm56i13'(suite) -> [];
+'ibm-invalid-P56-ibm56i13'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P56/ibm56i13.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P56/ibm56i14.xml
+%% ID: ibm-invalid-P56-ibm56i14.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P56-ibm56i14'(suite) -> [];
+'ibm-invalid-P56-ibm56i14'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P56/ibm56i14.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P56/ibm56i15.xml
+%% ID: ibm-invalid-P56-ibm56i15.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P56-ibm56i15'(suite) -> [];
+'ibm-invalid-P56-ibm56i15'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P56/ibm56i15.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P56/ibm56i16.xml
+%% ID: ibm-invalid-P56-ibm56i16.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P56-ibm56i16'(suite) -> [];
+'ibm-invalid-P56-ibm56i16'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P56/ibm56i16.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P56/ibm56i17.xml
+%% ID: ibm-invalid-P56-ibm56i17.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P56-ibm56i17'(suite) -> [];
+'ibm-invalid-P56-ibm56i17'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P56/ibm56i17.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P56/ibm56i18.xml
+%% ID: ibm-invalid-P56-ibm56i18.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P56-ibm56i18'(suite) -> [];
+'ibm-invalid-P56-ibm56i18'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P56/ibm56i18.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 56
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P58/ibm58i01.xml
+%% ID: ibm-invalid-P58-ibm58i01.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P58-ibm58i01'(suite) -> [];
+'ibm-invalid-P58-ibm58i01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P58/ibm58i01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P58/ibm58i02.xml
+%% ID: ibm-invalid-P58-ibm58i02.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P58-ibm58i02'(suite) -> [];
+'ibm-invalid-P58-ibm58i02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P58/ibm58i02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 58
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P59/ibm59i01.xml
+%% ID: ibm-invalid-P59-ibm59i01.xml
+%% Type: invalid
+%% Sections: 3.3.1
+'ibm-invalid-P59-ibm59i01'(suite) -> [];
+'ibm-invalid-P59-ibm59i01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P59/ibm59i01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 59
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P60/ibm60i01.xml
+%% ID: ibm-invalid-P60-ibm60i01.xml
+%% Type: invalid
+%% Sections: 3.3.2
+'ibm-invalid-P60-ibm60i01'(suite) -> [];
+'ibm-invalid-P60-ibm60i01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P60/ibm60i01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P60/ibm60i02.xml
+%% ID: ibm-invalid-P60-ibm60i02.xml
+%% Type: invalid
+%% Sections: 3.3.2
+'ibm-invalid-P60-ibm60i02'(suite) -> [];
+'ibm-invalid-P60-ibm60i02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P60/ibm60i02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P60/ibm60i03.xml
+%% ID: ibm-invalid-P60-ibm60i03.xml
+%% Type: invalid
+%% Sections: 3.3.2
+'ibm-invalid-P60-ibm60i03'(suite) -> [];
+'ibm-invalid-P60-ibm60i03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P60/ibm60i03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P60/ibm60i04.xml
+%% ID: ibm-invalid-P60-ibm60i04.xml
+%% Type: invalid
+%% Sections: 3.3.2
+'ibm-invalid-P60-ibm60i04'(suite) -> [];
+'ibm-invalid-P60-ibm60i04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P60/ibm60i04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 60
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P68/ibm68i01.xml
+%% ID: ibm-invalid-P68-ibm68i01.xml
+%% Type: error
+%% Sections: 4.1
+'ibm-invalid-P68-ibm68i01'(suite) -> [];
+'ibm-invalid-P68-ibm68i01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P68/ibm68i01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "error").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P68/ibm68i02.xml
+%% ID: ibm-invalid-P68-ibm68i02.xml
+%% Type: error
+%% Sections: 4.1
+'ibm-invalid-P68-ibm68i02'(suite) -> [];
+'ibm-invalid-P68-ibm68i02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P68/ibm68i02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "error").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P68/ibm68i03.xml
+%% ID: ibm-invalid-P68-ibm68i03.xml
+%% Type: error
+%% Sections: 4.1
+'ibm-invalid-P68-ibm68i03'(suite) -> [];
+'ibm-invalid-P68-ibm68i03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P68/ibm68i03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "error").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P68/ibm68i04.xml
+%% ID: ibm-invalid-P68-ibm68i04.xml
+%% Type: error
+%% Sections: 4.1
+'ibm-invalid-P68-ibm68i04'(suite) -> [];
+'ibm-invalid-P68-ibm68i04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P68/ibm68i04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "error").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 68
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P69/ibm69i01.xml
+%% ID: ibm-invalid-P69-ibm69i01.xml
+%% Type: error
+%% Sections: 4.1
+'ibm-invalid-P69-ibm69i01'(suite) -> [];
+'ibm-invalid-P69-ibm69i01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P69/ibm69i01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "error").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P69/ibm69i02.xml
+%% ID: ibm-invalid-P69-ibm69i02.xml
+%% Type: error
+%% Sections: 4.1
+'ibm-invalid-P69-ibm69i02'(suite) -> [];
+'ibm-invalid-P69-ibm69i02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P69/ibm69i02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "error").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P69/ibm69i03.xml
+%% ID: ibm-invalid-P69-ibm69i03.xml
+%% Type: error
+%% Sections: 4.1
+'ibm-invalid-P69-ibm69i03'(suite) -> [];
+'ibm-invalid-P69-ibm69i03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P69/ibm69i03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "error").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P69/ibm69i04.xml
+%% ID: ibm-invalid-P69-ibm69i04.xml
+%% Type: error
+%% Sections: 4.1
+'ibm-invalid-P69-ibm69i04'(suite) -> [];
+'ibm-invalid-P69-ibm69i04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P69/ibm69i04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "error").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 69
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: invalid/P76/ibm76i01.xml
+%% ID: ibm-invalid-P76-ibm76i01.xml
+%% Type: invalid
+%% Sections: 4.2.2
+'ibm-invalid-P76-ibm76i01'(suite) -> [];
+'ibm-invalid-P76-ibm76i01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","invalid/P76/ibm76i01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "invalid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 76
+
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - invalid tests
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P01/ibm01n01.xml
+%% ID: ibm-not-wf-P01-ibm01n01.xml
+%% Type: not-wf
+%% Sections: 2.1
+'ibm-not-wf-P01-ibm01n01'(suite) -> [];
+'ibm-not-wf-P01-ibm01n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P01/ibm01n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P01/ibm01n02.xml
+%% ID: ibm-not-wf-P01-ibm01n02.xml
+%% Type: not-wf
+%% Sections: 2.1
+'ibm-not-wf-P01-ibm01n02'(suite) -> [];
+'ibm-not-wf-P01-ibm01n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P01/ibm01n02.xml"]),
+ %% Special case becase we returns everything after a legal document
+ %% as an rest instead of giving and error to let the user handle
+ %% multipple docs on a stream.
+ ?line {ok,_, <<"xml version=\"1.0\"?>", _/binary>>} = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]).
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P01/ibm01n03.xml
+%% ID: ibm-not-wf-P01-ibm01n03.xml
+%% Type: not-wf
+%% Sections: 2.1
+'ibm-not-wf-P01-ibm01n03'(suite) -> [];
+'ibm-not-wf-P01-ibm01n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P01/ibm01n03.xml"]),
+ %% Special case becase we returns everything after a legal document
+ %% as an rest instead of giving and error to let the user handle
+ %% multipple docs on a stream.
+ ?line {ok,_, <<"<title>Wrong combination!</title>", _/binary>>} = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]).
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 1
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n01.xml
+%% ID: ibm-not-wf-P02-ibm02n01.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n01'(suite) -> [];
+'ibm-not-wf-P02-ibm02n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n02.xml
+%% ID: ibm-not-wf-P02-ibm02n02.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n02'(suite) -> [];
+'ibm-not-wf-P02-ibm02n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n03.xml
+%% ID: ibm-not-wf-P02-ibm02n03.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n03'(suite) -> [];
+'ibm-not-wf-P02-ibm02n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n04.xml
+%% ID: ibm-not-wf-P02-ibm02n04.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n04'(suite) -> [];
+'ibm-not-wf-P02-ibm02n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n05.xml
+%% ID: ibm-not-wf-P02-ibm02n05.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n05'(suite) -> [];
+'ibm-not-wf-P02-ibm02n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n06.xml
+%% ID: ibm-not-wf-P02-ibm02n06.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n06'(suite) -> [];
+'ibm-not-wf-P02-ibm02n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n07.xml
+%% ID: ibm-not-wf-P02-ibm02n07.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n07'(suite) -> [];
+'ibm-not-wf-P02-ibm02n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n08.xml
+%% ID: ibm-not-wf-P02-ibm02n08.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n08'(suite) -> [];
+'ibm-not-wf-P02-ibm02n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n09.xml
+%% ID: ibm-not-wf-P02-ibm02n09.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n09'(suite) -> [];
+'ibm-not-wf-P02-ibm02n09'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n09.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n10.xml
+%% ID: ibm-not-wf-P02-ibm02n10.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n10'(suite) -> [];
+'ibm-not-wf-P02-ibm02n10'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n10.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n11.xml
+%% ID: ibm-not-wf-P02-ibm02n11.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n11'(suite) -> [];
+'ibm-not-wf-P02-ibm02n11'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n11.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n12.xml
+%% ID: ibm-not-wf-P02-ibm02n12.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n12'(suite) -> [];
+'ibm-not-wf-P02-ibm02n12'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n12.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n13.xml
+%% ID: ibm-not-wf-P02-ibm02n13.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n13'(suite) -> [];
+'ibm-not-wf-P02-ibm02n13'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n13.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n14.xml
+%% ID: ibm-not-wf-P02-ibm02n14.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n14'(suite) -> [];
+'ibm-not-wf-P02-ibm02n14'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n14.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n15.xml
+%% ID: ibm-not-wf-P02-ibm02n15.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n15'(suite) -> [];
+'ibm-not-wf-P02-ibm02n15'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n15.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n16.xml
+%% ID: ibm-not-wf-P02-ibm02n16.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n16'(suite) -> [];
+'ibm-not-wf-P02-ibm02n16'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n16.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n17.xml
+%% ID: ibm-not-wf-P02-ibm02n17.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n17'(suite) -> [];
+'ibm-not-wf-P02-ibm02n17'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n17.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n18.xml
+%% ID: ibm-not-wf-P02-ibm02n18.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n18'(suite) -> [];
+'ibm-not-wf-P02-ibm02n18'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n18.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n19.xml
+%% ID: ibm-not-wf-P02-ibm02n19.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n19'(suite) -> [];
+'ibm-not-wf-P02-ibm02n19'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n19.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n20.xml
+%% ID: ibm-not-wf-P02-ibm02n20.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n20'(suite) -> [];
+'ibm-not-wf-P02-ibm02n20'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n20.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n21.xml
+%% ID: ibm-not-wf-P02-ibm02n21.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n21'(suite) -> [];
+'ibm-not-wf-P02-ibm02n21'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n21.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n22.xml
+%% ID: ibm-not-wf-P02-ibm02n22.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n22'(suite) -> [];
+'ibm-not-wf-P02-ibm02n22'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n22.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n23.xml
+%% ID: ibm-not-wf-P02-ibm02n23.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n23'(suite) -> [];
+'ibm-not-wf-P02-ibm02n23'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n23.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n24.xml
+%% ID: ibm-not-wf-P02-ibm02n24.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n24'(suite) -> [];
+'ibm-not-wf-P02-ibm02n24'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n24.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n25.xml
+%% ID: ibm-not-wf-P02-ibm02n25.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n25'(suite) -> [];
+'ibm-not-wf-P02-ibm02n25'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n25.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n26.xml
+%% ID: ibm-not-wf-P02-ibm02n26.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n26'(suite) -> [];
+'ibm-not-wf-P02-ibm02n26'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n26.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n27.xml
+%% ID: ibm-not-wf-P02-ibm02n27.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n27'(suite) -> [];
+'ibm-not-wf-P02-ibm02n27'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n27.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n28.xml
+%% ID: ibm-not-wf-P02-ibm02n28.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n28'(suite) -> [];
+'ibm-not-wf-P02-ibm02n28'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n28.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n29.xml
+%% ID: ibm-not-wf-P02-ibm02n29.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n29'(suite) -> [];
+'ibm-not-wf-P02-ibm02n29'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n29.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n30.xml
+%% ID: ibm-not-wf-P02-ibm02n30.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n30'(suite) -> [];
+'ibm-not-wf-P02-ibm02n30'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n30.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n31.xml
+%% ID: ibm-not-wf-P02-ibm02n31.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n31'(suite) -> [];
+'ibm-not-wf-P02-ibm02n31'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n31.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n32.xml
+%% ID: ibm-not-wf-P02-ibm02n32.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n32'(suite) -> [];
+'ibm-not-wf-P02-ibm02n32'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n32.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P02/ibm02n33.xml
+%% ID: ibm-not-wf-P02-ibm02n33.xml
+%% Type: not-wf
+%% Sections: 2.2
+'ibm-not-wf-P02-ibm02n33'(suite) -> [];
+'ibm-not-wf-P02-ibm02n33'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P02/ibm02n33.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 2
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P03/ibm03n01.xml
+%% ID: ibm-not-wf-P03-ibm03n01.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P03-ibm03n01'(suite) -> [];
+'ibm-not-wf-P03-ibm03n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P03/ibm03n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 3
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P04/ibm04n01.xml
+%% ID: ibm-not-wf-P04-ibm04n01.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P04-ibm04n01'(suite) -> [];
+'ibm-not-wf-P04-ibm04n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P04/ibm04n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P04/ibm04n02.xml
+%% ID: ibm-not-wf-P04-ibm04n02.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P04-ibm04n02'(suite) -> [];
+'ibm-not-wf-P04-ibm04n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P04/ibm04n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P04/ibm04n03.xml
+%% ID: ibm-not-wf-P04-ibm04n03.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P04-ibm04n03'(suite) -> [];
+'ibm-not-wf-P04-ibm04n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P04/ibm04n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P04/ibm04n04.xml
+%% ID: ibm-not-wf-P04-ibm04n04.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P04-ibm04n04'(suite) -> [];
+'ibm-not-wf-P04-ibm04n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P04/ibm04n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P04/ibm04n05.xml
+%% ID: ibm-not-wf-P04-ibm04n05.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P04-ibm04n05'(suite) -> [];
+'ibm-not-wf-P04-ibm04n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P04/ibm04n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P04/ibm04n06.xml
+%% ID: ibm-not-wf-P04-ibm04n06.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P04-ibm04n06'(suite) -> [];
+'ibm-not-wf-P04-ibm04n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P04/ibm04n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P04/ibm04n07.xml
+%% ID: ibm-not-wf-P04-ibm04n07.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P04-ibm04n07'(suite) -> [];
+'ibm-not-wf-P04-ibm04n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P04/ibm04n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P04/ibm04n08.xml
+%% ID: ibm-not-wf-P04-ibm04n08.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P04-ibm04n08'(suite) -> [];
+'ibm-not-wf-P04-ibm04n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P04/ibm04n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P04/ibm04n09.xml
+%% ID: ibm-not-wf-P04-ibm04n09.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P04-ibm04n09'(suite) -> [];
+'ibm-not-wf-P04-ibm04n09'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P04/ibm04n09.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P04/ibm04n10.xml
+%% ID: ibm-not-wf-P04-ibm04n10.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P04-ibm04n10'(suite) -> [];
+'ibm-not-wf-P04-ibm04n10'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P04/ibm04n10.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P04/ibm04n11.xml
+%% ID: ibm-not-wf-P04-ibm04n11.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P04-ibm04n11'(suite) -> [];
+'ibm-not-wf-P04-ibm04n11'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P04/ibm04n11.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P04/ibm04n12.xml
+%% ID: ibm-not-wf-P04-ibm04n12.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P04-ibm04n12'(suite) -> [];
+'ibm-not-wf-P04-ibm04n12'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P04/ibm04n12.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P04/ibm04n13.xml
+%% ID: ibm-not-wf-P04-ibm04n13.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P04-ibm04n13'(suite) -> [];
+'ibm-not-wf-P04-ibm04n13'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P04/ibm04n13.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P04/ibm04n14.xml
+%% ID: ibm-not-wf-P04-ibm04n14.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P04-ibm04n14'(suite) -> [];
+'ibm-not-wf-P04-ibm04n14'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P04/ibm04n14.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P04/ibm04n15.xml
+%% ID: ibm-not-wf-P04-ibm04n15.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P04-ibm04n15'(suite) -> [];
+'ibm-not-wf-P04-ibm04n15'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P04/ibm04n15.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P04/ibm04n16.xml
+%% ID: ibm-not-wf-P04-ibm04n16.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P04-ibm04n16'(suite) -> [];
+'ibm-not-wf-P04-ibm04n16'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P04/ibm04n16.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P04/ibm04n17.xml
+%% ID: ibm-not-wf-P04-ibm04n17.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P04-ibm04n17'(suite) -> [];
+'ibm-not-wf-P04-ibm04n17'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P04/ibm04n17.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P04/ibm04n18.xml
+%% ID: ibm-not-wf-P04-ibm04n18.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P04-ibm04n18'(suite) -> [];
+'ibm-not-wf-P04-ibm04n18'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P04/ibm04n18.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 4
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P05/ibm05n01.xml
+%% ID: ibm-not-wf-P05-ibm05n01.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P05-ibm05n01'(suite) -> [];
+'ibm-not-wf-P05-ibm05n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P05/ibm05n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P05/ibm05n02.xml
+%% ID: ibm-not-wf-P05-ibm05n02.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P05-ibm05n02'(suite) -> [];
+'ibm-not-wf-P05-ibm05n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P05/ibm05n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P05/ibm05n03.xml
+%% ID: ibm-not-wf-P05-ibm05n03.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P05-ibm05n03'(suite) -> [];
+'ibm-not-wf-P05-ibm05n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P05/ibm05n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 5
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P09/ibm09n01.xml
+%% ID: ibm-not-wf-P09-ibm09n01.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P09-ibm09n01'(suite) -> [];
+'ibm-not-wf-P09-ibm09n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P09/ibm09n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P09/ibm09n02.xml
+%% ID: ibm-not-wf-P09-ibm09n02.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P09-ibm09n02'(suite) -> [];
+'ibm-not-wf-P09-ibm09n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P09/ibm09n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P09/ibm09n03.xml
+%% ID: ibm-not-wf-P09-ibm09n03.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P09-ibm09n03'(suite) -> [];
+'ibm-not-wf-P09-ibm09n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P09/ibm09n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P09/ibm09n04.xml
+%% ID: ibm-not-wf-P09-ibm09n04.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P09-ibm09n04'(suite) -> [];
+'ibm-not-wf-P09-ibm09n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P09/ibm09n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 9
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P10/ibm10n01.xml
+%% ID: ibm-not-wf-P10-ibm10n01.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P10-ibm10n01'(suite) -> [];
+'ibm-not-wf-P10-ibm10n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P10/ibm10n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P10/ibm10n02.xml
+%% ID: ibm-not-wf-P10-ibm10n02.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P10-ibm10n02'(suite) -> [];
+'ibm-not-wf-P10-ibm10n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P10/ibm10n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P10/ibm10n03.xml
+%% ID: ibm-not-wf-P10-ibm10n03.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P10-ibm10n03'(suite) -> [];
+'ibm-not-wf-P10-ibm10n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P10/ibm10n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P10/ibm10n04.xml
+%% ID: ibm-not-wf-P10-ibm10n04.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P10-ibm10n04'(suite) -> [];
+'ibm-not-wf-P10-ibm10n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P10/ibm10n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P10/ibm10n05.xml
+%% ID: ibm-not-wf-P10-ibm10n05.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P10-ibm10n05'(suite) -> [];
+'ibm-not-wf-P10-ibm10n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P10/ibm10n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P10/ibm10n06.xml
+%% ID: ibm-not-wf-P10-ibm10n06.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P10-ibm10n06'(suite) -> [];
+'ibm-not-wf-P10-ibm10n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P10/ibm10n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P10/ibm10n07.xml
+%% ID: ibm-not-wf-P10-ibm10n07.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P10-ibm10n07'(suite) -> [];
+'ibm-not-wf-P10-ibm10n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P10/ibm10n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P10/ibm10n08.xml
+%% ID: ibm-not-wf-P10-ibm10n08.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P10-ibm10n08'(suite) -> [];
+'ibm-not-wf-P10-ibm10n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P10/ibm10n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 10
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P11/ibm11n01.xml
+%% ID: ibm-not-wf-P11-ibm11n01.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P11-ibm11n01'(suite) -> [];
+'ibm-not-wf-P11-ibm11n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P11/ibm11n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P11/ibm11n02.xml
+%% ID: ibm-not-wf-P11-ibm11n02.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P11-ibm11n02'(suite) -> [];
+'ibm-not-wf-P11-ibm11n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P11/ibm11n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P11/ibm11n03.xml
+%% ID: ibm-not-wf-P11-ibm11n03.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P11-ibm11n03'(suite) -> [];
+'ibm-not-wf-P11-ibm11n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P11/ibm11n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P11/ibm11n04.xml
+%% ID: ibm-not-wf-P11-ibm11n04.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P11-ibm11n04'(suite) -> [];
+'ibm-not-wf-P11-ibm11n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P11/ibm11n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 11
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P12/ibm12n01.xml
+%% ID: ibm-not-wf-P12-ibm12n01.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P12-ibm12n01'(suite) -> [];
+'ibm-not-wf-P12-ibm12n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P12/ibm12n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P12/ibm12n02.xml
+%% ID: ibm-not-wf-P12-ibm12n02.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P12-ibm12n02'(suite) -> [];
+'ibm-not-wf-P12-ibm12n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P12/ibm12n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P12/ibm12n03.xml
+%% ID: ibm-not-wf-P12-ibm12n03.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P12-ibm12n03'(suite) -> [];
+'ibm-not-wf-P12-ibm12n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P12/ibm12n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 12
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P13/ibm13n01.xml
+%% ID: ibm-not-wf-P13-ibm13n01.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P13-ibm13n01'(suite) -> [];
+'ibm-not-wf-P13-ibm13n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P13/ibm13n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P13/ibm13n02.xml
+%% ID: ibm-not-wf-P13-ibm13n02.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P13-ibm13n02'(suite) -> [];
+'ibm-not-wf-P13-ibm13n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P13/ibm13n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P13/ibm13n03.xml
+%% ID: ibm-not-wf-P13-ibm13n03.xml
+%% Type: not-wf
+%% Sections: 2.3
+'ibm-not-wf-P13-ibm13n03'(suite) -> [];
+'ibm-not-wf-P13-ibm13n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P13/ibm13n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 13
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P14/ibm14n01.xml
+%% ID: ibm-not-wf-P14-ibm14n01.xml
+%% Type: not-wf
+%% Sections: 2.4
+'ibm-not-wf-P14-ibm14n01'(suite) -> [];
+'ibm-not-wf-P14-ibm14n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P14/ibm14n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P14/ibm14n02.xml
+%% ID: ibm-not-wf-P14-ibm14n02.xml
+%% Type: not-wf
+%% Sections: 2.4
+'ibm-not-wf-P14-ibm14n02'(suite) -> [];
+'ibm-not-wf-P14-ibm14n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P14/ibm14n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P14/ibm14n03.xml
+%% ID: ibm-not-wf-P14-ibm14n03.xml
+%% Type: not-wf
+%% Sections: 2.4
+'ibm-not-wf-P14-ibm14n03'(suite) -> [];
+'ibm-not-wf-P14-ibm14n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P14/ibm14n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 14
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P15/ibm15n01.xml
+%% ID: ibm-not-wf-P15-ibm15n01.xml
+%% Type: not-wf
+%% Sections: 2.5
+'ibm-not-wf-P15-ibm15n01'(suite) -> [];
+'ibm-not-wf-P15-ibm15n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P15/ibm15n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P15/ibm15n02.xml
+%% ID: ibm-not-wf-P15-ibm15n02.xml
+%% Type: not-wf
+%% Sections: 2.5
+'ibm-not-wf-P15-ibm15n02'(suite) -> [];
+'ibm-not-wf-P15-ibm15n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P15/ibm15n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P15/ibm15n03.xml
+%% ID: ibm-not-wf-P15-ibm15n03.xml
+%% Type: not-wf
+%% Sections: 2.5
+'ibm-not-wf-P15-ibm15n03'(suite) -> [];
+'ibm-not-wf-P15-ibm15n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P15/ibm15n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P15/ibm15n04.xml
+%% ID: ibm-not-wf-P15-ibm15n04.xml
+%% Type: not-wf
+%% Sections: 2.5
+'ibm-not-wf-P15-ibm15n04'(suite) -> [];
+'ibm-not-wf-P15-ibm15n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P15/ibm15n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 15
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P16/ibm16n01.xml
+%% ID: ibm-not-wf-P16-ibm16n01.xml
+%% Type: not-wf
+%% Sections: 2.6
+'ibm-not-wf-P16-ibm16n01'(suite) -> [];
+'ibm-not-wf-P16-ibm16n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P16/ibm16n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P16/ibm16n02.xml
+%% ID: ibm-not-wf-P16-ibm16n02.xml
+%% Type: not-wf
+%% Sections: 2.6
+'ibm-not-wf-P16-ibm16n02'(suite) -> [];
+'ibm-not-wf-P16-ibm16n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P16/ibm16n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P16/ibm16n03.xml
+%% ID: ibm-not-wf-P16-ibm16n03.xml
+%% Type: not-wf
+%% Sections: 2.6
+'ibm-not-wf-P16-ibm16n03'(suite) -> [];
+'ibm-not-wf-P16-ibm16n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P16/ibm16n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P16/ibm16n04.xml
+%% ID: ibm-not-wf-P16-ibm16n04.xml
+%% Type: not-wf
+%% Sections: 2.6
+'ibm-not-wf-P16-ibm16n04'(suite) -> [];
+'ibm-not-wf-P16-ibm16n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P16/ibm16n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 16
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P17/ibm17n01.xml
+%% ID: ibm-not-wf-P17-ibm17n01.xml
+%% Type: not-wf
+%% Sections: 2.6
+'ibm-not-wf-P17-ibm17n01'(suite) -> [];
+'ibm-not-wf-P17-ibm17n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P17/ibm17n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P17/ibm17n02.xml
+%% ID: ibm-not-wf-P17-ibm17n02.xml
+%% Type: not-wf
+%% Sections: 2.6
+'ibm-not-wf-P17-ibm17n02'(suite) -> [];
+'ibm-not-wf-P17-ibm17n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P17/ibm17n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P17/ibm17n03.xml
+%% ID: ibm-not-wf-P17-ibm17n03.xml
+%% Type: not-wf
+%% Sections: 2.6
+'ibm-not-wf-P17-ibm17n03'(suite) -> [];
+'ibm-not-wf-P17-ibm17n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P17/ibm17n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P17/ibm17n04.xml
+%% ID: ibm-not-wf-P17-ibm17n04.xml
+%% Type: not-wf
+%% Sections: 2.6
+'ibm-not-wf-P17-ibm17n04'(suite) -> [];
+'ibm-not-wf-P17-ibm17n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P17/ibm17n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 17
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P18/ibm18n01.xml
+%% ID: ibm-not-wf-P18-ibm18n01.xml
+%% Type: not-wf
+%% Sections: 2.7
+'ibm-not-wf-P18-ibm18n01'(suite) -> [];
+'ibm-not-wf-P18-ibm18n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P18/ibm18n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P18/ibm18n02.xml
+%% ID: ibm-not-wf-P18-ibm18n02.xml
+%% Type: not-wf
+%% Sections: 2.7
+'ibm-not-wf-P18-ibm18n02'(suite) -> [];
+'ibm-not-wf-P18-ibm18n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P18/ibm18n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 18
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P19/ibm19n01.xml
+%% ID: ibm-not-wf-P19-ibm19n01.xml
+%% Type: not-wf
+%% Sections: 2.7
+'ibm-not-wf-P19-ibm19n01'(suite) -> [];
+'ibm-not-wf-P19-ibm19n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P19/ibm19n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P19/ibm19n02.xml
+%% ID: ibm-not-wf-P19-ibm19n02.xml
+%% Type: not-wf
+%% Sections: 2.7
+'ibm-not-wf-P19-ibm19n02'(suite) -> [];
+'ibm-not-wf-P19-ibm19n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P19/ibm19n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P19/ibm19n03.xml
+%% ID: ibm-not-wf-P19-ibm19n03.xml
+%% Type: not-wf
+%% Sections: 2.7
+'ibm-not-wf-P19-ibm19n03'(suite) -> [];
+'ibm-not-wf-P19-ibm19n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P19/ibm19n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 19
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P20/ibm20n01.xml
+%% ID: ibm-not-wf-P20-ibm20n01.xml
+%% Type: not-wf
+%% Sections: 2.7
+'ibm-not-wf-P20-ibm20n01'(suite) -> [];
+'ibm-not-wf-P20-ibm20n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P20/ibm20n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 20
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P21/ibm21n01.xml
+%% ID: ibm-not-wf-P21-ibm21n01.xml
+%% Type: not-wf
+%% Sections: 2.7
+'ibm-not-wf-P21-ibm21n01'(suite) -> [];
+'ibm-not-wf-P21-ibm21n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P21/ibm21n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P21/ibm21n02.xml
+%% ID: ibm-not-wf-P21-ibm21n02.xml
+%% Type: not-wf
+%% Sections: 2.7
+'ibm-not-wf-P21-ibm21n02'(suite) -> [];
+'ibm-not-wf-P21-ibm21n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P21/ibm21n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P21/ibm21n03.xml
+%% ID: ibm-not-wf-P21-ibm21n03.xml
+%% Type: not-wf
+%% Sections: 2.7
+'ibm-not-wf-P21-ibm21n03'(suite) -> [];
+'ibm-not-wf-P21-ibm21n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P21/ibm21n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 21
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P22/ibm22n01.xml
+%% ID: ibm-not-wf-P22-ibm22n01.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P22-ibm22n01'(suite) -> [];
+'ibm-not-wf-P22-ibm22n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P22/ibm22n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P22/ibm22n02.xml
+%% ID: ibm-not-wf-P22-ibm22n02.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P22-ibm22n02'(suite) -> [];
+'ibm-not-wf-P22-ibm22n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P22/ibm22n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P22/ibm22n03.xml
+%% ID: ibm-not-wf-P22-ibm22n03.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P22-ibm22n03'(suite) -> [];
+'ibm-not-wf-P22-ibm22n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P22/ibm22n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 22
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P23/ibm23n01.xml
+%% ID: ibm-not-wf-P23-ibm23n01.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P23-ibm23n01'(suite) -> [];
+'ibm-not-wf-P23-ibm23n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P23/ibm23n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P23/ibm23n02.xml
+%% ID: ibm-not-wf-P23-ibm23n02.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P23-ibm23n02'(suite) -> [];
+'ibm-not-wf-P23-ibm23n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P23/ibm23n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P23/ibm23n03.xml
+%% ID: ibm-not-wf-P23-ibm23n03.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P23-ibm23n03'(suite) -> [];
+'ibm-not-wf-P23-ibm23n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P23/ibm23n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P23/ibm23n04.xml
+%% ID: ibm-not-wf-P23-ibm23n04.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P23-ibm23n04'(suite) -> [];
+'ibm-not-wf-P23-ibm23n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P23/ibm23n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P23/ibm23n05.xml
+%% ID: ibm-not-wf-P23-ibm23n05.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P23-ibm23n05'(suite) -> [];
+'ibm-not-wf-P23-ibm23n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P23/ibm23n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P23/ibm23n06.xml
+%% ID: ibm-not-wf-P23-ibm23n06.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P23-ibm23n06'(suite) -> [];
+'ibm-not-wf-P23-ibm23n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P23/ibm23n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 23
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P24/ibm24n01.xml
+%% ID: ibm-not-wf-P24-ibm24n01.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P24-ibm24n01'(suite) -> [];
+'ibm-not-wf-P24-ibm24n01'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P24/ibm24n01.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P24/ibm24n02.xml
+%% ID: ibm-not-wf-P24-ibm24n02.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P24-ibm24n02'(suite) -> [];
+'ibm-not-wf-P24-ibm24n02'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P24/ibm24n02.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P24/ibm24n03.xml
+%% ID: ibm-not-wf-P24-ibm24n03.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P24-ibm24n03'(suite) -> [];
+'ibm-not-wf-P24-ibm24n03'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P24/ibm24n03.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P24/ibm24n04.xml
+%% ID: ibm-not-wf-P24-ibm24n04.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P24-ibm24n04'(suite) -> [];
+'ibm-not-wf-P24-ibm24n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P24/ibm24n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P24/ibm24n05.xml
+%% ID: ibm-not-wf-P24-ibm24n05.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P24-ibm24n05'(suite) -> [];
+'ibm-not-wf-P24-ibm24n05'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P24/ibm24n05.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P24/ibm24n06.xml
+%% ID: ibm-not-wf-P24-ibm24n06.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P24-ibm24n06'(suite) -> [];
+'ibm-not-wf-P24-ibm24n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P24/ibm24n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P24/ibm24n07.xml
+%% ID: ibm-not-wf-P24-ibm24n07.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P24-ibm24n07'(suite) -> [];
+'ibm-not-wf-P24-ibm24n07'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P24/ibm24n07.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P24/ibm24n08.xml
+%% ID: ibm-not-wf-P24-ibm24n08.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P24-ibm24n08'(suite) -> [];
+'ibm-not-wf-P24-ibm24n08'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P24/ibm24n08.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P24/ibm24n09.xml
+%% ID: ibm-not-wf-P24-ibm24n09.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P24-ibm24n09'(suite) -> [];
+'ibm-not-wf-P24-ibm24n09'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P24/ibm24n09.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 24
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P25/ibm25n01.xml
+%% ID: ibm-not-wf-P25-ibm25n01.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P25-ibm25n01'(suite) -> [];
+'ibm-not-wf-P25-ibm25n01'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P25/ibm25n01.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P25/ibm25n02.xml
+%% ID: ibm-not-wf-P25-ibm25n02.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P25-ibm25n02'(suite) -> [];
+'ibm-not-wf-P25-ibm25n02'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P25/ibm25n02.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 25
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P26/ibm26n01.xml
+%% ID: ibm-not-wf-P26-ibm26n01.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P26-ibm26n01'(suite) -> [];
+'ibm-not-wf-P26-ibm26n01'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P26/ibm26n01.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 26
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P27/ibm27n01.xml
+%% ID: ibm-not-wf-P27-ibm27n01.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P27-ibm27n01'(suite) -> [];
+'ibm-not-wf-P27-ibm27n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P27/ibm27n01.xml"]),
+ %% Special case becase we returns everything after a legal document
+ %% as an rest instead of giving and error to let the user handle
+ %% multipple docs on a stream.
+ ?line {ok,_, <<"<!ELEMENT cat EMPTY>">>} = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]).
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 27
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P28/ibm28n01.xml
+%% ID: ibm-not-wf-P28-ibm28n01.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P28-ibm28n01'(suite) -> [];
+'ibm-not-wf-P28-ibm28n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P28/ibm28n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P28/ibm28n02.xml
+%% ID: ibm-not-wf-P28-ibm28n02.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P28-ibm28n02'(suite) -> [];
+'ibm-not-wf-P28-ibm28n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P28/ibm28n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P28/ibm28n03.xml
+%% ID: ibm-not-wf-P28-ibm28n03.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P28-ibm28n03'(suite) -> [];
+'ibm-not-wf-P28-ibm28n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P28/ibm28n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P28/ibm28n04.xml
+%% ID: ibm-not-wf-P28-ibm28n04.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P28-ibm28n04'(suite) -> [];
+'ibm-not-wf-P28-ibm28n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P28/ibm28n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P28/ibm28n05.xml
+%% ID: ibm-not-wf-P28-ibm28n05.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P28-ibm28n05'(suite) -> [];
+'ibm-not-wf-P28-ibm28n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P28/ibm28n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P28/ibm28n06.xml
+%% ID: ibm-not-wf-P28-ibm28n06.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P28-ibm28n06'(suite) -> [];
+'ibm-not-wf-P28-ibm28n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P28/ibm28n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P28/ibm28n07.xml
+%% ID: ibm-not-wf-P28-ibm28n07.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P28-ibm28n07'(suite) -> [];
+'ibm-not-wf-P28-ibm28n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P28/ibm28n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P28/ibm28n08.xml
+%% ID: ibm-not-wf-P28-ibm28n08.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P28-ibm28n08'(suite) -> [];
+'ibm-not-wf-P28-ibm28n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P28/ibm28n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 28
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/p28a/ibm28an01.xml
+%% ID: ibm-not-wf-p28a-ibm28an01.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-p28a-ibm28an01'(suite) -> [];
+'ibm-not-wf-p28a-ibm28an01'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/p28a/ibm28an01.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 28a
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P29/ibm29n01.xml
+%% ID: ibm-not-wf-P29-ibm29n01.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P29-ibm29n01'(suite) -> [];
+'ibm-not-wf-P29-ibm29n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P29/ibm29n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P29/ibm29n02.xml
+%% ID: ibm-not-wf-P29-ibm29n02.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P29-ibm29n02'(suite) -> [];
+'ibm-not-wf-P29-ibm29n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P29/ibm29n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P29/ibm29n03.xml
+%% ID: ibm-not-wf-P29-ibm29n03.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P29-ibm29n03'(suite) -> [];
+'ibm-not-wf-P29-ibm29n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P29/ibm29n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P29/ibm29n04.xml
+%% ID: ibm-not-wf-P29-ibm29n04.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P29-ibm29n04'(suite) -> [];
+'ibm-not-wf-P29-ibm29n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P29/ibm29n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P29/ibm29n05.xml
+%% ID: ibm-not-wf-P29-ibm29n05.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P29-ibm29n05'(suite) -> [];
+'ibm-not-wf-P29-ibm29n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P29/ibm29n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P29/ibm29n06.xml
+%% ID: ibm-not-wf-P29-ibm29n06.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P29-ibm29n06'(suite) -> [];
+'ibm-not-wf-P29-ibm29n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P29/ibm29n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P29/ibm29n07.xml
+%% ID: ibm-not-wf-P29-ibm29n07.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P29-ibm29n07'(suite) -> [];
+'ibm-not-wf-P29-ibm29n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P29/ibm29n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 29
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P30/ibm30n01.xml
+%% ID: ibm-not-wf-P30-ibm30n01.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P30-ibm30n01'(suite) -> [];
+'ibm-not-wf-P30-ibm30n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P30/ibm30n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 30
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P31/ibm31n01.xml
+%% ID: ibm-not-wf-P31-ibm31n01.xml
+%% Type: not-wf
+%% Sections: 2.8
+'ibm-not-wf-P31-ibm31n01'(suite) -> [];
+'ibm-not-wf-P31-ibm31n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P31/ibm31n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 31
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P32/ibm32n01.xml
+%% ID: ibm-not-wf-P32-ibm32n01.xml
+%% Type: not-wf
+%% Sections: 2.9
+'ibm-not-wf-P32-ibm32n01'(suite) -> [];
+'ibm-not-wf-P32-ibm32n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P32/ibm32n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P32/ibm32n02.xml
+%% ID: ibm-not-wf-P32-ibm32n02.xml
+%% Type: not-wf
+%% Sections: 2.9
+'ibm-not-wf-P32-ibm32n02'(suite) -> [];
+'ibm-not-wf-P32-ibm32n02'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P32/ibm32n02.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P32/ibm32n03.xml
+%% ID: ibm-not-wf-P32-ibm32n03.xml
+%% Type: not-wf
+%% Sections: 2.9
+'ibm-not-wf-P32-ibm32n03'(suite) -> [];
+'ibm-not-wf-P32-ibm32n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P32/ibm32n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P32/ibm32n04.xml
+%% ID: ibm-not-wf-P32-ibm32n04.xml
+%% Type: not-wf
+%% Sections: 2.9
+'ibm-not-wf-P32-ibm32n04'(suite) -> [];
+'ibm-not-wf-P32-ibm32n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P32/ibm32n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P32/ibm32n05.xml
+%% ID: ibm-not-wf-P32-ibm32n05.xml
+%% Type: not-wf
+%% Sections: 2.9
+'ibm-not-wf-P32-ibm32n05'(suite) -> [];
+'ibm-not-wf-P32-ibm32n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P32/ibm32n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P32/ibm32n06.xml
+%% ID: ibm-not-wf-P32-ibm32n06.xml
+%% Type: not-wf
+%% Sections: 2.9
+'ibm-not-wf-P32-ibm32n06'(suite) -> [];
+'ibm-not-wf-P32-ibm32n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P32/ibm32n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P32/ibm32n07.xml
+%% ID: ibm-not-wf-P32-ibm32n07.xml
+%% Type: not-wf
+%% Sections: 2.9
+'ibm-not-wf-P32-ibm32n07'(suite) -> [];
+'ibm-not-wf-P32-ibm32n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P32/ibm32n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P32/ibm32n08.xml
+%% ID: ibm-not-wf-P32-ibm32n08.xml
+%% Type: not-wf
+%% Sections: 2.9
+'ibm-not-wf-P32-ibm32n08'(suite) -> [];
+'ibm-not-wf-P32-ibm32n08'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P32/ibm32n08.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P32/ibm32n09.xml
+%% ID: ibm-not-wf-P32-ibm32n09.xml
+%% Type: not-wf
+%% Sections: 2.9
+'ibm-not-wf-P32-ibm32n09'(suite) -> [];
+'ibm-not-wf-P32-ibm32n09'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P32/ibm32n09.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 32
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P39/ibm39n01.xml
+%% ID: ibm-not-wf-P39-ibm39n01.xml
+%% Type: not-wf
+%% Sections: 3
+'ibm-not-wf-P39-ibm39n01'(suite) -> [];
+'ibm-not-wf-P39-ibm39n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P39/ibm39n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P39/ibm39n02.xml
+%% ID: ibm-not-wf-P39-ibm39n02.xml
+%% Type: not-wf
+%% Sections: 3
+'ibm-not-wf-P39-ibm39n02'(suite) -> [];
+'ibm-not-wf-P39-ibm39n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P39/ibm39n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P39/ibm39n03.xml
+%% ID: ibm-not-wf-P39-ibm39n03.xml
+%% Type: not-wf
+%% Sections: 3
+'ibm-not-wf-P39-ibm39n03'(suite) -> [];
+'ibm-not-wf-P39-ibm39n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P39/ibm39n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P39/ibm39n04.xml
+%% ID: ibm-not-wf-P39-ibm39n04.xml
+%% Type: not-wf
+%% Sections: 3
+'ibm-not-wf-P39-ibm39n04'(suite) -> [];
+'ibm-not-wf-P39-ibm39n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P39/ibm39n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P39/ibm39n05.xml
+%% ID: ibm-not-wf-P39-ibm39n05.xml
+%% Type: not-wf
+%% Sections: 3
+'ibm-not-wf-P39-ibm39n05'(suite) -> [];
+'ibm-not-wf-P39-ibm39n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P39/ibm39n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P39/ibm39n06.xml
+%% ID: ibm-not-wf-P39-ibm39n06.xml
+%% Type: not-wf
+%% Sections: 3
+'ibm-not-wf-P39-ibm39n06'(suite) -> [];
+'ibm-not-wf-P39-ibm39n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P39/ibm39n06.xml"]),
+ %% Special case becase we returns everything after a legal document
+ %% as an rest instead of giving and error to let the user handle
+ %% multipple docs on a stream.
+ ?line {ok,_,<<"content after end tag\r\n">>} = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]).
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 39
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P40/ibm40n01.xml
+%% ID: ibm-not-wf-P40-ibm40n01.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P40-ibm40n01'(suite) -> [];
+'ibm-not-wf-P40-ibm40n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P40/ibm40n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P40/ibm40n02.xml
+%% ID: ibm-not-wf-P40-ibm40n02.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P40-ibm40n02'(suite) -> [];
+'ibm-not-wf-P40-ibm40n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P40/ibm40n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P40/ibm40n03.xml
+%% ID: ibm-not-wf-P40-ibm40n03.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P40-ibm40n03'(suite) -> [];
+'ibm-not-wf-P40-ibm40n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P40/ibm40n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P40/ibm40n04.xml
+%% ID: ibm-not-wf-P40-ibm40n04.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P40-ibm40n04'(suite) -> [];
+'ibm-not-wf-P40-ibm40n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P40/ibm40n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P40/ibm40n05.xml
+%% ID: ibm-not-wf-P40-ibm40n05.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P40-ibm40n05'(suite) -> [];
+'ibm-not-wf-P40-ibm40n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P40/ibm40n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 40
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P41/ibm41n01.xml
+%% ID: ibm-not-wf-P41-ibm41n01.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P41-ibm41n01'(suite) -> [];
+'ibm-not-wf-P41-ibm41n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P41/ibm41n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P41/ibm41n02.xml
+%% ID: ibm-not-wf-P41-ibm41n02.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P41-ibm41n02'(suite) -> [];
+'ibm-not-wf-P41-ibm41n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P41/ibm41n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P41/ibm41n03.xml
+%% ID: ibm-not-wf-P41-ibm41n03.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P41-ibm41n03'(suite) -> [];
+'ibm-not-wf-P41-ibm41n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P41/ibm41n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P41/ibm41n04.xml
+%% ID: ibm-not-wf-P41-ibm41n04.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P41-ibm41n04'(suite) -> [];
+'ibm-not-wf-P41-ibm41n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P41/ibm41n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P41/ibm41n05.xml
+%% ID: ibm-not-wf-P41-ibm41n05.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P41-ibm41n05'(suite) -> [];
+'ibm-not-wf-P41-ibm41n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P41/ibm41n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P41/ibm41n06.xml
+%% ID: ibm-not-wf-P41-ibm41n06.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P41-ibm41n06'(suite) -> [];
+'ibm-not-wf-P41-ibm41n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P41/ibm41n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P41/ibm41n07.xml
+%% ID: ibm-not-wf-P41-ibm41n07.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P41-ibm41n07'(suite) -> [];
+'ibm-not-wf-P41-ibm41n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P41/ibm41n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P41/ibm41n08.xml
+%% ID: ibm-not-wf-P41-ibm41n08.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P41-ibm41n08'(suite) -> [];
+'ibm-not-wf-P41-ibm41n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P41/ibm41n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P41/ibm41n09.xml
+%% ID: ibm-not-wf-P41-ibm41n09.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P41-ibm41n09'(suite) -> [];
+'ibm-not-wf-P41-ibm41n09'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P41/ibm41n09.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P41/ibm41n10.xml
+%% ID: ibm-not-wf-P41-ibm41n10.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P41-ibm41n10'(suite) -> [];
+'ibm-not-wf-P41-ibm41n10'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P41/ibm41n10.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P41/ibm41n11.xml
+%% ID: ibm-not-wf-P41-ibm41n11.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P41-ibm41n11'(suite) -> [];
+'ibm-not-wf-P41-ibm41n11'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P41/ibm41n11.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P41/ibm41n12.xml
+%% ID: ibm-not-wf-P41-ibm41n12.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P41-ibm41n12'(suite) -> [];
+'ibm-not-wf-P41-ibm41n12'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P41/ibm41n12.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P41/ibm41n13.xml
+%% ID: ibm-not-wf-P41-ibm41n13.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P41-ibm41n13'(suite) -> [];
+'ibm-not-wf-P41-ibm41n13'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P41/ibm41n13.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P41/ibm41n14.xml
+%% ID: ibm-not-wf-P41-ibm41n14.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P41-ibm41n14'(suite) -> [];
+'ibm-not-wf-P41-ibm41n14'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P41/ibm41n14.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 41
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P42/ibm42n01.xml
+%% ID: ibm-not-wf-P42-ibm42n01.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P42-ibm42n01'(suite) -> [];
+'ibm-not-wf-P42-ibm42n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P42/ibm42n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P42/ibm42n02.xml
+%% ID: ibm-not-wf-P42-ibm42n02.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P42-ibm42n02'(suite) -> [];
+'ibm-not-wf-P42-ibm42n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P42/ibm42n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P42/ibm42n03.xml
+%% ID: ibm-not-wf-P42-ibm42n03.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P42-ibm42n03'(suite) -> [];
+'ibm-not-wf-P42-ibm42n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P42/ibm42n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P42/ibm42n04.xml
+%% ID: ibm-not-wf-P42-ibm42n04.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P42-ibm42n04'(suite) -> [];
+'ibm-not-wf-P42-ibm42n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P42/ibm42n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P42/ibm42n05.xml
+%% ID: ibm-not-wf-P42-ibm42n05.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P42-ibm42n05'(suite) -> [];
+'ibm-not-wf-P42-ibm42n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P42/ibm42n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 42
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P43/ibm43n01.xml
+%% ID: ibm-not-wf-P43-ibm43n01.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P43-ibm43n01'(suite) -> [];
+'ibm-not-wf-P43-ibm43n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P43/ibm43n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P43/ibm43n02.xml
+%% ID: ibm-not-wf-P43-ibm43n02.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P43-ibm43n02'(suite) -> [];
+'ibm-not-wf-P43-ibm43n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P43/ibm43n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P43/ibm43n04.xml
+%% ID: ibm-not-wf-P43-ibm43n04.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P43-ibm43n04'(suite) -> [];
+'ibm-not-wf-P43-ibm43n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P43/ibm43n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P43/ibm43n05.xml
+%% ID: ibm-not-wf-P43-ibm43n05.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P43-ibm43n05'(suite) -> [];
+'ibm-not-wf-P43-ibm43n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P43/ibm43n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 43
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P44/ibm44n01.xml
+%% ID: ibm-not-wf-P44-ibm44n01.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P44-ibm44n01'(suite) -> [];
+'ibm-not-wf-P44-ibm44n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P44/ibm44n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P44/ibm44n02.xml
+%% ID: ibm-not-wf-P44-ibm44n02.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P44-ibm44n02'(suite) -> [];
+'ibm-not-wf-P44-ibm44n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P44/ibm44n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P44/ibm44n03.xml
+%% ID: ibm-not-wf-P44-ibm44n03.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P44-ibm44n03'(suite) -> [];
+'ibm-not-wf-P44-ibm44n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P44/ibm44n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P44/ibm44n04.xml
+%% ID: ibm-not-wf-P44-ibm44n04.xml
+%% Type: not-wf
+%% Sections: 3.1
+'ibm-not-wf-P44-ibm44n04'(suite) -> [];
+'ibm-not-wf-P44-ibm44n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P44/ibm44n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 44
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P45/ibm45n01.xml
+%% ID: ibm-not-wf-P45-ibm45n01.xml
+%% Type: not-wf
+%% Sections: 3.2
+'ibm-not-wf-P45-ibm45n01'(suite) -> [];
+'ibm-not-wf-P45-ibm45n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P45/ibm45n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P45/ibm45n02.xml
+%% ID: ibm-not-wf-P45-ibm45n02.xml
+%% Type: not-wf
+%% Sections: 3.2
+'ibm-not-wf-P45-ibm45n02'(suite) -> [];
+'ibm-not-wf-P45-ibm45n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P45/ibm45n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P45/ibm45n03.xml
+%% ID: ibm-not-wf-P45-ibm45n03.xml
+%% Type: not-wf
+%% Sections: 3.2
+'ibm-not-wf-P45-ibm45n03'(suite) -> [];
+'ibm-not-wf-P45-ibm45n03'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P45/ibm45n03.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P45/ibm45n04.xml
+%% ID: ibm-not-wf-P45-ibm45n04.xml
+%% Type: not-wf
+%% Sections: 3.2
+'ibm-not-wf-P45-ibm45n04'(suite) -> [];
+'ibm-not-wf-P45-ibm45n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P45/ibm45n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P45/ibm45n05.xml
+%% ID: ibm-not-wf-P45-ibm45n05.xml
+%% Type: not-wf
+%% Sections: 3.2
+'ibm-not-wf-P45-ibm45n05'(suite) -> [];
+'ibm-not-wf-P45-ibm45n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P45/ibm45n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P45/ibm45n06.xml
+%% ID: ibm-not-wf-P45-ibm45n06.xml
+%% Type: not-wf
+%% Sections: 3.2
+'ibm-not-wf-P45-ibm45n06'(suite) -> [];
+'ibm-not-wf-P45-ibm45n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P45/ibm45n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P45/ibm45n07.xml
+%% ID: ibm-not-wf-P45-ibm45n07.xml
+%% Type: not-wf
+%% Sections: 3.2
+'ibm-not-wf-P45-ibm45n07'(suite) -> [];
+'ibm-not-wf-P45-ibm45n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P45/ibm45n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P45/ibm45n08.xml
+%% ID: ibm-not-wf-P45-ibm45n08.xml
+%% Type: not-wf
+%% Sections: 3.2
+'ibm-not-wf-P45-ibm45n08'(suite) -> [];
+'ibm-not-wf-P45-ibm45n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P45/ibm45n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P45/ibm45n09.xml
+%% ID: ibm-not-wf-P45-ibm45n09.xml
+%% Type: not-wf
+%% Sections: 3.2
+'ibm-not-wf-P45-ibm45n09'(suite) -> [];
+'ibm-not-wf-P45-ibm45n09'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P45/ibm45n09.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 45
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P46/ibm46n01.xml
+%% ID: ibm-not-wf-P46-ibm46n01.xml
+%% Type: not-wf
+%% Sections: 3.2
+'ibm-not-wf-P46-ibm46n01'(suite) -> [];
+'ibm-not-wf-P46-ibm46n01'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P46/ibm46n01.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P46/ibm46n02.xml
+%% ID: ibm-not-wf-P46-ibm46n02.xml
+%% Type: not-wf
+%% Sections: 3.2
+'ibm-not-wf-P46-ibm46n02'(suite) -> [];
+'ibm-not-wf-P46-ibm46n02'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P46/ibm46n02.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P46/ibm46n03.xml
+%% ID: ibm-not-wf-P46-ibm46n03.xml
+%% Type: not-wf
+%% Sections: 3.2
+'ibm-not-wf-P46-ibm46n03'(suite) -> [];
+'ibm-not-wf-P46-ibm46n03'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P46/ibm46n03.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P46/ibm46n04.xml
+%% ID: ibm-not-wf-P46-ibm46n04.xml
+%% Type: not-wf
+%% Sections: 3.2
+'ibm-not-wf-P46-ibm46n04'(suite) -> [];
+'ibm-not-wf-P46-ibm46n04'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P46/ibm46n04.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P46/ibm46n05.xml
+%% ID: ibm-not-wf-P46-ibm46n05.xml
+%% Type: not-wf
+%% Sections: 3.2
+'ibm-not-wf-P46-ibm46n05'(suite) -> [];
+'ibm-not-wf-P46-ibm46n05'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P46/ibm46n05.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 46
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P47/ibm47n01.xml
+%% ID: ibm-not-wf-P47-ibm47n01.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P47-ibm47n01'(suite) -> [];
+'ibm-not-wf-P47-ibm47n01'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P47/ibm47n01.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P47/ibm47n02.xml
+%% ID: ibm-not-wf-P47-ibm47n02.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P47-ibm47n02'(suite) -> [];
+'ibm-not-wf-P47-ibm47n02'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P47/ibm47n02.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P47/ibm47n03.xml
+%% ID: ibm-not-wf-P47-ibm47n03.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P47-ibm47n03'(suite) -> [];
+'ibm-not-wf-P47-ibm47n03'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P47/ibm47n03.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P47/ibm47n04.xml
+%% ID: ibm-not-wf-P47-ibm47n04.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P47-ibm47n04'(suite) -> [];
+'ibm-not-wf-P47-ibm47n04'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P47/ibm47n04.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P47/ibm47n05.xml
+%% ID: ibm-not-wf-P47-ibm47n05.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P47-ibm47n05'(suite) -> [];
+'ibm-not-wf-P47-ibm47n05'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P47/ibm47n05.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P47/ibm47n06.xml
+%% ID: ibm-not-wf-P47-ibm47n06.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P47-ibm47n06'(suite) -> [];
+'ibm-not-wf-P47-ibm47n06'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P47/ibm47n06.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 47
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P48/ibm48n01.xml
+%% ID: ibm-not-wf-P48-ibm48n01.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P48-ibm48n01'(suite) -> [];
+'ibm-not-wf-P48-ibm48n01'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P48/ibm48n01.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P48/ibm48n02.xml
+%% ID: ibm-not-wf-P48-ibm48n02.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P48-ibm48n02'(suite) -> [];
+'ibm-not-wf-P48-ibm48n02'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P48/ibm48n02.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P48/ibm48n03.xml
+%% ID: ibm-not-wf-P48-ibm48n03.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P48-ibm48n03'(suite) -> [];
+'ibm-not-wf-P48-ibm48n03'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P48/ibm48n03.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P48/ibm48n04.xml
+%% ID: ibm-not-wf-P48-ibm48n04.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P48-ibm48n04'(suite) -> [];
+'ibm-not-wf-P48-ibm48n04'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P48/ibm48n04.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P48/ibm48n05.xml
+%% ID: ibm-not-wf-P48-ibm48n05.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P48-ibm48n05'(suite) -> [];
+'ibm-not-wf-P48-ibm48n05'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P48/ibm48n05.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P48/ibm48n06.xml
+%% ID: ibm-not-wf-P48-ibm48n06.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P48-ibm48n06'(suite) -> [];
+'ibm-not-wf-P48-ibm48n06'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P48/ibm48n06.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P48/ibm48n07.xml
+%% ID: ibm-not-wf-P48-ibm48n07.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P48-ibm48n07'(suite) -> [];
+'ibm-not-wf-P48-ibm48n07'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P48/ibm48n07.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 48
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P49/ibm49n01.xml
+%% ID: ibm-not-wf-P49-ibm49n01.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P49-ibm49n01'(suite) -> [];
+'ibm-not-wf-P49-ibm49n01'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P49/ibm49n01.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P49/ibm49n02.xml
+%% ID: ibm-not-wf-P49-ibm49n02.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P49-ibm49n02'(suite) -> [];
+'ibm-not-wf-P49-ibm49n02'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P49/ibm49n02.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P49/ibm49n03.xml
+%% ID: ibm-not-wf-P49-ibm49n03.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P49-ibm49n03'(suite) -> [];
+'ibm-not-wf-P49-ibm49n03'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P49/ibm49n03.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P49/ibm49n04.xml
+%% ID: ibm-not-wf-P49-ibm49n04.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P49-ibm49n04'(suite) -> [];
+'ibm-not-wf-P49-ibm49n04'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P49/ibm49n04.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P49/ibm49n05.xml
+%% ID: ibm-not-wf-P49-ibm49n05.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P49-ibm49n05'(suite) -> [];
+'ibm-not-wf-P49-ibm49n05'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P49/ibm49n05.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P49/ibm49n06.xml
+%% ID: ibm-not-wf-P49-ibm49n06.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P49-ibm49n06'(suite) -> [];
+'ibm-not-wf-P49-ibm49n06'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P49/ibm49n06.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 49
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P50/ibm50n01.xml
+%% ID: ibm-not-wf-P50-ibm50n01.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P50-ibm50n01'(suite) -> [];
+'ibm-not-wf-P50-ibm50n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P50/ibm50n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P50/ibm50n02.xml
+%% ID: ibm-not-wf-P50-ibm50n02.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P50-ibm50n02'(suite) -> [];
+'ibm-not-wf-P50-ibm50n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P50/ibm50n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P50/ibm50n03.xml
+%% ID: ibm-not-wf-P50-ibm50n03.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P50-ibm50n03'(suite) -> [];
+'ibm-not-wf-P50-ibm50n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P50/ibm50n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P50/ibm50n04.xml
+%% ID: ibm-not-wf-P50-ibm50n04.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P50-ibm50n04'(suite) -> [];
+'ibm-not-wf-P50-ibm50n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P50/ibm50n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P50/ibm50n05.xml
+%% ID: ibm-not-wf-P50-ibm50n05.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P50-ibm50n05'(suite) -> [];
+'ibm-not-wf-P50-ibm50n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P50/ibm50n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P50/ibm50n06.xml
+%% ID: ibm-not-wf-P50-ibm50n06.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P50-ibm50n06'(suite) -> [];
+'ibm-not-wf-P50-ibm50n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P50/ibm50n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P50/ibm50n07.xml
+%% ID: ibm-not-wf-P50-ibm50n07.xml
+%% Type: not-wf
+%% Sections: 3.2.1
+'ibm-not-wf-P50-ibm50n07'(suite) -> [];
+'ibm-not-wf-P50-ibm50n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P50/ibm50n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 50
+
+testcases67(suite) -> [].
+%% ['ibm-not-wf-P50-ibm50n01','ibm-not-wf-P50-ibm50n02','ibm-not-wf-P50-ibm50n03','ibm-not-wf-P50-ibm50n04','ibm-not-wf-P50-ibm50n05','ibm-not-wf-P50-ibm50n06','ibm-not-wf-P50-ibm50n07'].
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P51/ibm51n01.xml
+%% ID: ibm-not-wf-P51-ibm51n01.xml
+%% Type: not-wf
+%% Sections: 3.2.2
+'ibm-not-wf-P51-ibm51n01'(suite) -> [];
+'ibm-not-wf-P51-ibm51n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P51/ibm51n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P51/ibm51n02.xml
+%% ID: ibm-not-wf-P51-ibm51n02.xml
+%% Type: not-wf
+%% Sections: 3.2.2
+'ibm-not-wf-P51-ibm51n02'(suite) -> [];
+'ibm-not-wf-P51-ibm51n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P51/ibm51n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P51/ibm51n03.xml
+%% ID: ibm-not-wf-P51-ibm51n03.xml
+%% Type: not-wf
+%% Sections: 3.2.2
+'ibm-not-wf-P51-ibm51n03'(suite) -> [];
+'ibm-not-wf-P51-ibm51n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P51/ibm51n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P51/ibm51n04.xml
+%% ID: ibm-not-wf-P51-ibm51n04.xml
+%% Type: not-wf
+%% Sections: 3.2.2
+'ibm-not-wf-P51-ibm51n04'(suite) -> [];
+'ibm-not-wf-P51-ibm51n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P51/ibm51n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P51/ibm51n05.xml
+%% ID: ibm-not-wf-P51-ibm51n05.xml
+%% Type: not-wf
+%% Sections: 3.2.2
+'ibm-not-wf-P51-ibm51n05'(suite) -> [];
+'ibm-not-wf-P51-ibm51n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P51/ibm51n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P51/ibm51n06.xml
+%% ID: ibm-not-wf-P51-ibm51n06.xml
+%% Type: not-wf
+%% Sections: 3.2.2
+'ibm-not-wf-P51-ibm51n06'(suite) -> [];
+'ibm-not-wf-P51-ibm51n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P51/ibm51n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P51/ibm51n07.xml
+%% ID: ibm-not-wf-P51-ibm51n07.xml
+%% Type: not-wf
+%% Sections: 3.2.2
+'ibm-not-wf-P51-ibm51n07'(suite) -> [];
+'ibm-not-wf-P51-ibm51n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P51/ibm51n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 51
+
+testcases68(suite) -> [].
+%% ['ibm-not-wf-P51-ibm51n01','ibm-not-wf-P51-ibm51n02','ibm-not-wf-P51-ibm51n03','ibm-not-wf-P51-ibm51n04','ibm-not-wf-P51-ibm51n05','ibm-not-wf-P51-ibm51n06','ibm-not-wf-P51-ibm51n07'].
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P52/ibm52n01.xml
+%% ID: ibm-not-wf-P52-ibm52n01.xml
+%% Type: not-wf
+%% Sections: 3.3
+'ibm-not-wf-P52-ibm52n01'(suite) -> [];
+'ibm-not-wf-P52-ibm52n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P52/ibm52n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P52/ibm52n02.xml
+%% ID: ibm-not-wf-P52-ibm52n02.xml
+%% Type: not-wf
+%% Sections: 3.3
+'ibm-not-wf-P52-ibm52n02'(suite) -> [];
+'ibm-not-wf-P52-ibm52n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P52/ibm52n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P52/ibm52n03.xml
+%% ID: ibm-not-wf-P52-ibm52n03.xml
+%% Type: not-wf
+%% Sections: 3.3
+'ibm-not-wf-P52-ibm52n03'(suite) -> [];
+'ibm-not-wf-P52-ibm52n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P52/ibm52n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P52/ibm52n04.xml
+%% ID: ibm-not-wf-P52-ibm52n04.xml
+%% Type: not-wf
+%% Sections: 3.3
+'ibm-not-wf-P52-ibm52n04'(suite) -> [];
+'ibm-not-wf-P52-ibm52n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P52/ibm52n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P52/ibm52n05.xml
+%% ID: ibm-not-wf-P52-ibm52n05.xml
+%% Type: not-wf
+%% Sections: 3.3
+'ibm-not-wf-P52-ibm52n05'(suite) -> [];
+'ibm-not-wf-P52-ibm52n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P52/ibm52n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P52/ibm52n06.xml
+%% ID: ibm-not-wf-P52-ibm52n06.xml
+%% Type: not-wf
+%% Sections: 3.3
+'ibm-not-wf-P52-ibm52n06'(suite) -> [];
+'ibm-not-wf-P52-ibm52n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P52/ibm52n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 52
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P53/ibm53n01.xml
+%% ID: ibm-not-wf-P53-ibm53n01.xml
+%% Type: not-wf
+%% Sections: 3.3
+'ibm-not-wf-P53-ibm53n01'(suite) -> [];
+'ibm-not-wf-P53-ibm53n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P53/ibm53n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P53/ibm53n02.xml
+%% ID: ibm-not-wf-P53-ibm53n02.xml
+%% Type: not-wf
+%% Sections: 3.3
+'ibm-not-wf-P53-ibm53n02'(suite) -> [];
+'ibm-not-wf-P53-ibm53n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P53/ibm53n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P53/ibm53n03.xml
+%% ID: ibm-not-wf-P53-ibm53n03.xml
+%% Type: not-wf
+%% Sections: 3.3
+'ibm-not-wf-P53-ibm53n03'(suite) -> [];
+'ibm-not-wf-P53-ibm53n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P53/ibm53n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P53/ibm53n04.xml
+%% ID: ibm-not-wf-P53-ibm53n04.xml
+%% Type: not-wf
+%% Sections: 3.3
+'ibm-not-wf-P53-ibm53n04'(suite) -> [];
+'ibm-not-wf-P53-ibm53n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P53/ibm53n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P53/ibm53n05.xml
+%% ID: ibm-not-wf-P53-ibm53n05.xml
+%% Type: not-wf
+%% Sections: 3.3
+'ibm-not-wf-P53-ibm53n05'(suite) -> [];
+'ibm-not-wf-P53-ibm53n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P53/ibm53n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P53/ibm53n06.xml
+%% ID: ibm-not-wf-P53-ibm53n06.xml
+%% Type: not-wf
+%% Sections: 3.3
+'ibm-not-wf-P53-ibm53n06'(suite) -> [];
+'ibm-not-wf-P53-ibm53n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P53/ibm53n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P53/ibm53n07.xml
+%% ID: ibm-not-wf-P53-ibm53n07.xml
+%% Type: not-wf
+%% Sections: 3.3
+'ibm-not-wf-P53-ibm53n07'(suite) -> [];
+'ibm-not-wf-P53-ibm53n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P53/ibm53n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P53/ibm53n08.xml
+%% ID: ibm-not-wf-P53-ibm53n08.xml
+%% Type: not-wf
+%% Sections: 3.3
+'ibm-not-wf-P53-ibm53n08'(suite) -> [];
+'ibm-not-wf-P53-ibm53n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P53/ibm53n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 53
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P54/ibm54n01.xml
+%% ID: ibm-not-wf-P54-ibm54n01.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P54-ibm54n01'(suite) -> [];
+'ibm-not-wf-P54-ibm54n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P54/ibm54n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P54/ibm54n02.xml
+%% ID: ibm-not-wf-P54-ibm54n02.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P54-ibm54n02'(suite) -> [];
+'ibm-not-wf-P54-ibm54n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P54/ibm54n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 54
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P55/ibm55n01.xml
+%% ID: ibm-not-wf-P55-ibm55n01.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P55-ibm55n01'(suite) -> [];
+'ibm-not-wf-P55-ibm55n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P55/ibm55n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P55/ibm55n02.xml
+%% ID: ibm-not-wf-P55-ibm55n02.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P55-ibm55n02'(suite) -> [];
+'ibm-not-wf-P55-ibm55n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P55/ibm55n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P55/ibm55n03.xml
+%% ID: ibm-not-wf-P55-ibm55n03.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P55-ibm55n03'(suite) -> [];
+'ibm-not-wf-P55-ibm55n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P55/ibm55n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 55
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P56/ibm56n01.xml
+%% ID: ibm-not-wf-P56-ibm56n01.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P56-ibm56n01'(suite) -> [];
+'ibm-not-wf-P56-ibm56n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P56/ibm56n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P56/ibm56n02.xml
+%% ID: ibm-not-wf-P56-ibm56n02.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P56-ibm56n02'(suite) -> [];
+'ibm-not-wf-P56-ibm56n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P56/ibm56n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P56/ibm56n03.xml
+%% ID: ibm-not-wf-P56-ibm56n03.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P56-ibm56n03'(suite) -> [];
+'ibm-not-wf-P56-ibm56n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P56/ibm56n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P56/ibm56n04.xml
+%% ID: ibm-not-wf-P56-ibm56n04.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P56-ibm56n04'(suite) -> [];
+'ibm-not-wf-P56-ibm56n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P56/ibm56n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P56/ibm56n05.xml
+%% ID: ibm-not-wf-P56-ibm56n05.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P56-ibm56n05'(suite) -> [];
+'ibm-not-wf-P56-ibm56n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P56/ibm56n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P56/ibm56n06.xml
+%% ID: ibm-not-wf-P56-ibm56n06.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P56-ibm56n06'(suite) -> [];
+'ibm-not-wf-P56-ibm56n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P56/ibm56n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P56/ibm56n07.xml
+%% ID: ibm-not-wf-P56-ibm56n07.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P56-ibm56n07'(suite) -> [];
+'ibm-not-wf-P56-ibm56n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P56/ibm56n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 56
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P57/ibm57n01.xml
+%% ID: ibm-not-wf-P57-ibm57n01.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P57-ibm57n01'(suite) -> [];
+'ibm-not-wf-P57-ibm57n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P57/ibm57n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 57
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P58/ibm58n01.xml
+%% ID: ibm-not-wf-P58-ibm58n01.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P58-ibm58n01'(suite) -> [];
+'ibm-not-wf-P58-ibm58n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P58/ibm58n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P58/ibm58n02.xml
+%% ID: ibm-not-wf-P58-ibm58n02.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P58-ibm58n02'(suite) -> [];
+'ibm-not-wf-P58-ibm58n02'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P58/ibm58n02.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P58/ibm58n03.xml
+%% ID: ibm-not-wf-P58-ibm58n03.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P58-ibm58n03'(suite) -> [];
+'ibm-not-wf-P58-ibm58n03'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P58/ibm58n03.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P58/ibm58n04.xml
+%% ID: ibm-not-wf-P58-ibm58n04.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P58-ibm58n04'(suite) -> [];
+'ibm-not-wf-P58-ibm58n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P58/ibm58n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P58/ibm58n05.xml
+%% ID: ibm-not-wf-P58-ibm58n05.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P58-ibm58n05'(suite) -> [];
+'ibm-not-wf-P58-ibm58n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P58/ibm58n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P58/ibm58n06.xml
+%% ID: ibm-not-wf-P58-ibm58n06.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P58-ibm58n06'(suite) -> [];
+'ibm-not-wf-P58-ibm58n06'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P58/ibm58n06.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P58/ibm58n07.xml
+%% ID: ibm-not-wf-P58-ibm58n07.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P58-ibm58n07'(suite) -> [];
+'ibm-not-wf-P58-ibm58n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P58/ibm58n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P58/ibm58n08.xml
+%% ID: ibm-not-wf-P58-ibm58n08.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P58-ibm58n08'(suite) -> [];
+'ibm-not-wf-P58-ibm58n08'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P58/ibm58n08.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 58
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P59/ibm59n01.xml
+%% ID: ibm-not-wf-P59-ibm59n01.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P59-ibm59n01'(suite) -> [];
+'ibm-not-wf-P59-ibm59n01'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P59/ibm59n01.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P59/ibm59n02.xml
+%% ID: ibm-not-wf-P59-ibm59n02.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P59-ibm59n02'(suite) -> [];
+'ibm-not-wf-P59-ibm59n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P59/ibm59n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P59/ibm59n03.xml
+%% ID: ibm-not-wf-P59-ibm59n03.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P59-ibm59n03'(suite) -> [];
+'ibm-not-wf-P59-ibm59n03'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P59/ibm59n03.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P59/ibm59n04.xml
+%% ID: ibm-not-wf-P59-ibm59n04.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P59-ibm59n04'(suite) -> [];
+'ibm-not-wf-P59-ibm59n04'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P59/ibm59n04.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P59/ibm59n05.xml
+%% ID: ibm-not-wf-P59-ibm59n05.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P59-ibm59n05'(suite) -> [];
+'ibm-not-wf-P59-ibm59n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P59/ibm59n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P59/ibm59n06.xml
+%% ID: ibm-not-wf-P59-ibm59n06.xml
+%% Type: not-wf
+%% Sections: 3.3.1
+'ibm-not-wf-P59-ibm59n06'(suite) -> [];
+'ibm-not-wf-P59-ibm59n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P59/ibm59n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 59
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P60/ibm60n01.xml
+%% ID: ibm-not-wf-P60-ibm60n01.xml
+%% Type: not-wf
+%% Sections: 3.3.2
+'ibm-not-wf-P60-ibm60n01'(suite) -> [];
+'ibm-not-wf-P60-ibm60n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P60/ibm60n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P60/ibm60n02.xml
+%% ID: ibm-not-wf-P60-ibm60n02.xml
+%% Type: not-wf
+%% Sections: 3.3.2
+'ibm-not-wf-P60-ibm60n02'(suite) -> [];
+'ibm-not-wf-P60-ibm60n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P60/ibm60n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P60/ibm60n03.xml
+%% ID: ibm-not-wf-P60-ibm60n03.xml
+%% Type: not-wf
+%% Sections: 3.3.2
+'ibm-not-wf-P60-ibm60n03'(suite) -> [];
+'ibm-not-wf-P60-ibm60n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P60/ibm60n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P60/ibm60n04.xml
+%% ID: ibm-not-wf-P60-ibm60n04.xml
+%% Type: not-wf
+%% Sections: 3.3.2
+'ibm-not-wf-P60-ibm60n04'(suite) -> [];
+'ibm-not-wf-P60-ibm60n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P60/ibm60n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P60/ibm60n05.xml
+%% ID: ibm-not-wf-P60-ibm60n05.xml
+%% Type: not-wf
+%% Sections: 3.3.2
+'ibm-not-wf-P60-ibm60n05'(suite) -> [];
+'ibm-not-wf-P60-ibm60n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P60/ibm60n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P60/ibm60n06.xml
+%% ID: ibm-not-wf-P60-ibm60n06.xml
+%% Type: not-wf
+%% Sections: 3.3.2
+'ibm-not-wf-P60-ibm60n06'(suite) -> [];
+'ibm-not-wf-P60-ibm60n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P60/ibm60n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P60/ibm60n07.xml
+%% ID: ibm-not-wf-P60-ibm60n07.xml
+%% Type: not-wf
+%% Sections: 3.3.2
+'ibm-not-wf-P60-ibm60n07'(suite) -> [];
+'ibm-not-wf-P60-ibm60n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P60/ibm60n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P60/ibm60n08.xml
+%% ID: ibm-not-wf-P60-ibm60n08.xml
+%% Type: not-wf
+%% Sections: 3.3.2
+'ibm-not-wf-P60-ibm60n08'(suite) -> [];
+'ibm-not-wf-P60-ibm60n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P60/ibm60n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 60
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P61/ibm61n01.xml
+%% ID: ibm-not-wf-P61-ibm61n01.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P61-ibm61n01'(suite) -> [];
+'ibm-not-wf-P61-ibm61n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P61/ibm61n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 61
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P62/ibm62n01.xml
+%% ID: ibm-not-wf-P62-ibm62n01.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P62-ibm62n01'(suite) -> [];
+'ibm-not-wf-P62-ibm62n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P62/ibm62n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P62/ibm62n02.xml
+%% ID: ibm-not-wf-P62-ibm62n02.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P62-ibm62n02'(suite) -> [];
+'ibm-not-wf-P62-ibm62n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P62/ibm62n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P62/ibm62n03.xml
+%% ID: ibm-not-wf-P62-ibm62n03.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P62-ibm62n03'(suite) -> [];
+'ibm-not-wf-P62-ibm62n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P62/ibm62n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P62/ibm62n04.xml
+%% ID: ibm-not-wf-P62-ibm62n04.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P62-ibm62n04'(suite) -> [];
+'ibm-not-wf-P62-ibm62n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P62/ibm62n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P62/ibm62n05.xml
+%% ID: ibm-not-wf-P62-ibm62n05.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P62-ibm62n05'(suite) -> [];
+'ibm-not-wf-P62-ibm62n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P62/ibm62n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P62/ibm62n06.xml
+%% ID: ibm-not-wf-P62-ibm62n06.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P62-ibm62n06'(suite) -> [];
+'ibm-not-wf-P62-ibm62n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P62/ibm62n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P62/ibm62n07.xml
+%% ID: ibm-not-wf-P62-ibm62n07.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P62-ibm62n07'(suite) -> [];
+'ibm-not-wf-P62-ibm62n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P62/ibm62n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P62/ibm62n08.xml
+%% ID: ibm-not-wf-P62-ibm62n08.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P62-ibm62n08'(suite) -> [];
+'ibm-not-wf-P62-ibm62n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P62/ibm62n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 62
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P63/ibm63n01.xml
+%% ID: ibm-not-wf-P63-ibm63n01.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P63-ibm63n01'(suite) -> [];
+'ibm-not-wf-P63-ibm63n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P63/ibm63n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P63/ibm63n02.xml
+%% ID: ibm-not-wf-P63-ibm63n02.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P63-ibm63n02'(suite) -> [];
+'ibm-not-wf-P63-ibm63n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P63/ibm63n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P63/ibm63n03.xml
+%% ID: ibm-not-wf-P63-ibm63n03.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P63-ibm63n03'(suite) -> [];
+'ibm-not-wf-P63-ibm63n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P63/ibm63n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P63/ibm63n04.xml
+%% ID: ibm-not-wf-P63-ibm63n04.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P63-ibm63n04'(suite) -> [];
+'ibm-not-wf-P63-ibm63n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P63/ibm63n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P63/ibm63n05.xml
+%% ID: ibm-not-wf-P63-ibm63n05.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P63-ibm63n05'(suite) -> [];
+'ibm-not-wf-P63-ibm63n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P63/ibm63n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P63/ibm63n06.xml
+%% ID: ibm-not-wf-P63-ibm63n06.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P63-ibm63n06'(suite) -> [];
+'ibm-not-wf-P63-ibm63n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P63/ibm63n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P63/ibm63n07.xml
+%% ID: ibm-not-wf-P63-ibm63n07.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P63-ibm63n07'(suite) -> [];
+'ibm-not-wf-P63-ibm63n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P63/ibm63n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 63
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P64/ibm64n01.xml
+%% ID: ibm-not-wf-P64-ibm64n01.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P64-ibm64n01'(suite) -> [];
+'ibm-not-wf-P64-ibm64n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P64/ibm64n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P64/ibm64n02.xml
+%% ID: ibm-not-wf-P64-ibm64n02.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P64-ibm64n02'(suite) -> [];
+'ibm-not-wf-P64-ibm64n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P64/ibm64n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P64/ibm64n03.xml
+%% ID: ibm-not-wf-P64-ibm64n03.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P64-ibm64n03'(suite) -> [];
+'ibm-not-wf-P64-ibm64n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P64/ibm64n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 64
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P65/ibm65n01.xml
+%% ID: ibm-not-wf-P65-ibm65n01.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P65-ibm65n01'(suite) -> [];
+'ibm-not-wf-P65-ibm65n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P65/ibm65n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P65/ibm65n02.xml
+%% ID: ibm-not-wf-P65-ibm65n02.xml
+%% Type: not-wf
+%% Sections: 3.4
+'ibm-not-wf-P65-ibm65n02'(suite) -> [];
+'ibm-not-wf-P65-ibm65n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P65/ibm65n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 65
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P66/ibm66n01.xml
+%% ID: ibm-not-wf-P66-ibm66n01.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P66-ibm66n01'(suite) -> [];
+'ibm-not-wf-P66-ibm66n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P66/ibm66n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P66/ibm66n02.xml
+%% ID: ibm-not-wf-P66-ibm66n02.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P66-ibm66n02'(suite) -> [];
+'ibm-not-wf-P66-ibm66n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P66/ibm66n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P66/ibm66n03.xml
+%% ID: ibm-not-wf-P66-ibm66n03.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P66-ibm66n03'(suite) -> [];
+'ibm-not-wf-P66-ibm66n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P66/ibm66n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P66/ibm66n04.xml
+%% ID: ibm-not-wf-P66-ibm66n04.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P66-ibm66n04'(suite) -> [];
+'ibm-not-wf-P66-ibm66n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P66/ibm66n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P66/ibm66n05.xml
+%% ID: ibm-not-wf-P66-ibm66n05.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P66-ibm66n05'(suite) -> [];
+'ibm-not-wf-P66-ibm66n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P66/ibm66n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P66/ibm66n06.xml
+%% ID: ibm-not-wf-P66-ibm66n06.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P66-ibm66n06'(suite) -> [];
+'ibm-not-wf-P66-ibm66n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P66/ibm66n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P66/ibm66n07.xml
+%% ID: ibm-not-wf-P66-ibm66n07.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P66-ibm66n07'(suite) -> [];
+'ibm-not-wf-P66-ibm66n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P66/ibm66n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P66/ibm66n08.xml
+%% ID: ibm-not-wf-P66-ibm66n08.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P66-ibm66n08'(suite) -> [];
+'ibm-not-wf-P66-ibm66n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P66/ibm66n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P66/ibm66n09.xml
+%% ID: ibm-not-wf-P66-ibm66n09.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P66-ibm66n09'(suite) -> [];
+'ibm-not-wf-P66-ibm66n09'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P66/ibm66n09.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P66/ibm66n10.xml
+%% ID: ibm-not-wf-P66-ibm66n10.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P66-ibm66n10'(suite) -> [];
+'ibm-not-wf-P66-ibm66n10'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P66/ibm66n10.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P66/ibm66n11.xml
+%% ID: ibm-not-wf-P66-ibm66n11.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P66-ibm66n11'(suite) -> [];
+'ibm-not-wf-P66-ibm66n11'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P66/ibm66n11.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P66/ibm66n12.xml
+%% ID: ibm-not-wf-P66-ibm66n12.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P66-ibm66n12'(suite) -> [];
+'ibm-not-wf-P66-ibm66n12'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P66/ibm66n12.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P66/ibm66n13.xml
+%% ID: ibm-not-wf-P66-ibm66n13.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P66-ibm66n13'(suite) -> [];
+'ibm-not-wf-P66-ibm66n13'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P66/ibm66n13.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P66/ibm66n14.xml
+%% ID: ibm-not-wf-P66-ibm66n14.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P66-ibm66n14'(suite) -> [];
+'ibm-not-wf-P66-ibm66n14'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P66/ibm66n14.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P66/ibm66n15.xml
+%% ID: ibm-not-wf-P66-ibm66n15.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P66-ibm66n15'(suite) -> [];
+'ibm-not-wf-P66-ibm66n15'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P66/ibm66n15.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 66
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P68/ibm68n01.xml
+%% ID: ibm-not-wf-P68-ibm68n01.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P68-ibm68n01'(suite) -> [];
+'ibm-not-wf-P68-ibm68n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P68/ibm68n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P68/ibm68n02.xml
+%% ID: ibm-not-wf-P68-ibm68n02.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P68-ibm68n02'(suite) -> [];
+'ibm-not-wf-P68-ibm68n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P68/ibm68n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P68/ibm68n03.xml
+%% ID: ibm-not-wf-P68-ibm68n03.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P68-ibm68n03'(suite) -> [];
+'ibm-not-wf-P68-ibm68n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P68/ibm68n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P68/ibm68n04.xml
+%% ID: ibm-not-wf-P68-ibm68n04.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P68-ibm68n04'(suite) -> [];
+'ibm-not-wf-P68-ibm68n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P68/ibm68n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P68/ibm68n05.xml
+%% ID: ibm-not-wf-P68-ibm68n05.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P68-ibm68n05'(suite) -> [];
+'ibm-not-wf-P68-ibm68n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P68/ibm68n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P68/ibm68n06.xml
+%% ID: ibm-not-wf-P68-ibm68n06.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P68-ibm68n06'(suite) -> [];
+'ibm-not-wf-P68-ibm68n06'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P68/ibm68n06.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P68/ibm68n07.xml
+%% ID: ibm-not-wf-P68-ibm68n07.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P68-ibm68n07'(suite) -> [];
+'ibm-not-wf-P68-ibm68n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P68/ibm68n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P68/ibm68n08.xml
+%% ID: ibm-not-wf-P68-ibm68n08.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P68-ibm68n08'(suite) -> [];
+'ibm-not-wf-P68-ibm68n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P68/ibm68n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P68/ibm68n09.xml
+%% ID: ibm-not-wf-P68-ibm68n09.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P68-ibm68n09'(suite) -> [];
+'ibm-not-wf-P68-ibm68n09'(_Config) -> {skip, "No loop detection yet"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P68/ibm68n09.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P68/ibm68n10.xml
+%% ID: ibm-not-wf-P68-ibm68n10.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P68-ibm68n10'(suite) -> [];
+'ibm-not-wf-P68-ibm68n10'(_Config) -> {skip, "No loop detection yet"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P68/ibm68n10.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 68
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P69/ibm69n01.xml
+%% ID: ibm-not-wf-P69-ibm69n01.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P69-ibm69n01'(suite) -> [];
+'ibm-not-wf-P69-ibm69n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P69/ibm69n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P69/ibm69n02.xml
+%% ID: ibm-not-wf-P69-ibm69n02.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P69-ibm69n02'(suite) -> [];
+'ibm-not-wf-P69-ibm69n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P69/ibm69n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P69/ibm69n03.xml
+%% ID: ibm-not-wf-P69-ibm69n03.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P69-ibm69n03'(suite) -> [];
+'ibm-not-wf-P69-ibm69n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P69/ibm69n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P69/ibm69n04.xml
+%% ID: ibm-not-wf-P69-ibm69n04.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P69-ibm69n04'(suite) -> [];
+'ibm-not-wf-P69-ibm69n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P69/ibm69n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P69/ibm69n05.xml
+%% ID: ibm-not-wf-P69-ibm69n05.xml
+%% Type: error
+%% Sections: 4.1
+'ibm-not-wf-P69-ibm69n05'(suite) -> [];
+'ibm-not-wf-P69-ibm69n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P69/ibm69n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "error").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P69/ibm69n06.xml
+%% ID: ibm-not-wf-P69-ibm69n06.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P69-ibm69n06'(suite) -> [];
+'ibm-not-wf-P69-ibm69n06'(_Config) -> {skip, "No loop detection yet"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P69/ibm69n06.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P69/ibm69n07.xml
+%% ID: ibm-not-wf-P69-ibm69n07.xml
+%% Type: not-wf
+%% Sections: 4.1
+'ibm-not-wf-P69-ibm69n07'(suite) -> [];
+'ibm-not-wf-P69-ibm69n07'(_Config) -> {skip, "No loop detection yet"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P69/ibm69n07.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 69
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P71/ibm70n01.xml
+%% ID: ibm-not-wf-P71-ibm70n01.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P71-ibm70n01'(suite) -> [];
+'ibm-not-wf-P71-ibm70n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P71/ibm70n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P71/ibm71n01.xml
+%% ID: ibm-not-wf-P71-ibm71n01.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P71-ibm71n01'(suite) -> [];
+'ibm-not-wf-P71-ibm71n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P71/ibm71n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P71/ibm71n02.xml
+%% ID: ibm-not-wf-P71-ibm71n02.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P71-ibm71n02'(suite) -> [];
+'ibm-not-wf-P71-ibm71n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P71/ibm71n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P71/ibm71n03.xml
+%% ID: ibm-not-wf-P71-ibm71n03.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P71-ibm71n03'(suite) -> [];
+'ibm-not-wf-P71-ibm71n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P71/ibm71n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P71/ibm71n04.xml
+%% ID: ibm-not-wf-P71-ibm71n04.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P71-ibm71n04'(suite) -> [];
+'ibm-not-wf-P71-ibm71n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P71/ibm71n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P71/ibm71n05.xml
+%% ID: ibm-not-wf-P71-ibm71n05.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P71-ibm71n05'(suite) -> [];
+'ibm-not-wf-P71-ibm71n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P71/ibm71n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P71/ibm71n06.xml
+%% ID: ibm-not-wf-P71-ibm71n06.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P71-ibm71n06'(suite) -> [];
+'ibm-not-wf-P71-ibm71n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P71/ibm71n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P71/ibm71n07.xml
+%% ID: ibm-not-wf-P71-ibm71n07.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P71-ibm71n07'(suite) -> [];
+'ibm-not-wf-P71-ibm71n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P71/ibm71n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P71/ibm71n08.xml
+%% ID: ibm-not-wf-P71-ibm71n08.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P71-ibm71n08'(suite) -> [];
+'ibm-not-wf-P71-ibm71n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P71/ibm71n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 71
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P72/ibm72n01.xml
+%% ID: ibm-not-wf-P72-ibm72n01.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P72-ibm72n01'(suite) -> [];
+'ibm-not-wf-P72-ibm72n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P72/ibm72n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P72/ibm72n02.xml
+%% ID: ibm-not-wf-P72-ibm72n02.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P72-ibm72n02'(suite) -> [];
+'ibm-not-wf-P72-ibm72n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P72/ibm72n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P72/ibm72n03.xml
+%% ID: ibm-not-wf-P72-ibm72n03.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P72-ibm72n03'(suite) -> [];
+'ibm-not-wf-P72-ibm72n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P72/ibm72n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P72/ibm72n04.xml
+%% ID: ibm-not-wf-P72-ibm72n04.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P72-ibm72n04'(suite) -> [];
+'ibm-not-wf-P72-ibm72n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P72/ibm72n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P72/ibm72n05.xml
+%% ID: ibm-not-wf-P72-ibm72n05.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P72-ibm72n05'(suite) -> [];
+'ibm-not-wf-P72-ibm72n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P72/ibm72n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P72/ibm72n06.xml
+%% ID: ibm-not-wf-P72-ibm72n06.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P72-ibm72n06'(suite) -> [];
+'ibm-not-wf-P72-ibm72n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P72/ibm72n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P72/ibm72n07.xml
+%% ID: ibm-not-wf-P72-ibm72n07.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P72-ibm72n07'(suite) -> [];
+'ibm-not-wf-P72-ibm72n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P72/ibm72n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P72/ibm72n08.xml
+%% ID: ibm-not-wf-P72-ibm72n08.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P72-ibm72n08'(suite) -> [];
+'ibm-not-wf-P72-ibm72n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P72/ibm72n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P72/ibm72n09.xml
+%% ID: ibm-not-wf-P72-ibm72n09.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P72-ibm72n09'(suite) -> [];
+'ibm-not-wf-P72-ibm72n09'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P72/ibm72n09.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 72
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P73/ibm73n01.xml
+%% ID: ibm-not-wf-P73-ibm73n01.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P73-ibm73n01'(suite) -> [];
+'ibm-not-wf-P73-ibm73n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P73/ibm73n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P73/ibm73n03.xml
+%% ID: ibm-not-wf-P73-ibm73n03.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P73-ibm73n03'(suite) -> [];
+'ibm-not-wf-P73-ibm73n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P73/ibm73n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 73
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P74/ibm74n01.xml
+%% ID: ibm-not-wf-P74-ibm74n01.xml
+%% Type: not-wf
+%% Sections: 4.2
+'ibm-not-wf-P74-ibm74n01'(suite) -> [];
+'ibm-not-wf-P74-ibm74n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P74/ibm74n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 74
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P75/ibm75n01.xml
+%% ID: ibm-not-wf-P75-ibm75n01.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P75-ibm75n01'(suite) -> [];
+'ibm-not-wf-P75-ibm75n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P75/ibm75n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P75/ibm75n02.xml
+%% ID: ibm-not-wf-P75-ibm75n02.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P75-ibm75n02'(suite) -> [];
+'ibm-not-wf-P75-ibm75n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P75/ibm75n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P75/ibm75n03.xml
+%% ID: ibm-not-wf-P75-ibm75n03.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P75-ibm75n03'(suite) -> [];
+'ibm-not-wf-P75-ibm75n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P75/ibm75n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P75/ibm75n04.xml
+%% ID: ibm-not-wf-P75-ibm75n04.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P75-ibm75n04'(suite) -> [];
+'ibm-not-wf-P75-ibm75n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P75/ibm75n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P75/ibm75n05.xml
+%% ID: ibm-not-wf-P75-ibm75n05.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P75-ibm75n05'(suite) -> [];
+'ibm-not-wf-P75-ibm75n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P75/ibm75n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P75/ibm75n06.xml
+%% ID: ibm-not-wf-P75-ibm75n06.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P75-ibm75n06'(suite) -> [];
+'ibm-not-wf-P75-ibm75n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P75/ibm75n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P75/ibm75n07.xml
+%% ID: ibm-not-wf-P75-ibm75n07.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P75-ibm75n07'(suite) -> [];
+'ibm-not-wf-P75-ibm75n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P75/ibm75n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P75/ibm75n08.xml
+%% ID: ibm-not-wf-P75-ibm75n08.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P75-ibm75n08'(suite) -> [];
+'ibm-not-wf-P75-ibm75n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P75/ibm75n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P75/ibm75n09.xml
+%% ID: ibm-not-wf-P75-ibm75n09.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P75-ibm75n09'(suite) -> [];
+'ibm-not-wf-P75-ibm75n09'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P75/ibm75n09.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P75/ibm75n10.xml
+%% ID: ibm-not-wf-P75-ibm75n10.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P75-ibm75n10'(suite) -> [];
+'ibm-not-wf-P75-ibm75n10'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P75/ibm75n10.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P75/ibm75n11.xml
+%% ID: ibm-not-wf-P75-ibm75n11.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P75-ibm75n11'(suite) -> [];
+'ibm-not-wf-P75-ibm75n11'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P75/ibm75n11.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P75/ibm75n12.xml
+%% ID: ibm-not-wf-P75-ibm75n12.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P75-ibm75n12'(suite) -> [];
+'ibm-not-wf-P75-ibm75n12'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P75/ibm75n12.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P75/ibm75n13.xml
+%% ID: ibm-not-wf-P75-ibm75n13.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P75-ibm75n13'(suite) -> [];
+'ibm-not-wf-P75-ibm75n13'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P75/ibm75n13.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 75
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P76/ibm76n01.xml
+%% ID: ibm-not-wf-P76-ibm76n01.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P76-ibm76n01'(suite) -> [];
+'ibm-not-wf-P76-ibm76n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P76/ibm76n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P76/ibm76n02.xml
+%% ID: ibm-not-wf-P76-ibm76n02.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P76-ibm76n02'(suite) -> [];
+'ibm-not-wf-P76-ibm76n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P76/ibm76n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P76/ibm76n03.xml
+%% ID: ibm-not-wf-P76-ibm76n03.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P76-ibm76n03'(suite) -> [];
+'ibm-not-wf-P76-ibm76n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P76/ibm76n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P76/ibm76n04.xml
+%% ID: ibm-not-wf-P76-ibm76n04.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P76-ibm76n04'(suite) -> [];
+'ibm-not-wf-P76-ibm76n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P76/ibm76n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P76/ibm76n05.xml
+%% ID: ibm-not-wf-P76-ibm76n05.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P76-ibm76n05'(suite) -> [];
+'ibm-not-wf-P76-ibm76n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P76/ibm76n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P76/ibm76n06.xml
+%% ID: ibm-not-wf-P76-ibm76n06.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P76-ibm76n06'(suite) -> [];
+'ibm-not-wf-P76-ibm76n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P76/ibm76n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P76/ibm76n07.xml
+%% ID: ibm-not-wf-P76-ibm76n07.xml
+%% Type: not-wf
+%% Sections: 4.2.2
+'ibm-not-wf-P76-ibm76n07'(suite) -> [];
+'ibm-not-wf-P76-ibm76n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P76/ibm76n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 76
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P77/ibm77n01.xml
+%% ID: ibm-not-wf-P77-ibm77n01.xml
+%% Type: not-wf
+%% Sections: 4.3.1
+'ibm-not-wf-P77-ibm77n01'(suite) -> [];
+'ibm-not-wf-P77-ibm77n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P77/ibm77n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P77/ibm77n02.xml
+%% ID: ibm-not-wf-P77-ibm77n02.xml
+%% Type: not-wf
+%% Sections: 4.3.1
+'ibm-not-wf-P77-ibm77n02'(suite) -> [];
+'ibm-not-wf-P77-ibm77n02'(Config) -> {skip, "Fix 3"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P77/ibm77n02.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P77/ibm77n03.xml
+%% ID: ibm-not-wf-P77-ibm77n03.xml
+%% Type: not-wf
+%% Sections: 4.3.1
+'ibm-not-wf-P77-ibm77n03'(suite) -> [];
+'ibm-not-wf-P77-ibm77n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P77/ibm77n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P77/ibm77n04.xml
+%% ID: ibm-not-wf-P77-ibm77n04.xml
+%% Type: not-wf
+%% Sections: 4.3.1
+'ibm-not-wf-P77-ibm77n04'(suite) -> [];
+'ibm-not-wf-P77-ibm77n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P77/ibm77n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 77
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P78/ibm78n01.xml
+%% ID: ibm-not-wf-P78-ibm78n01.xml
+%% Type: not-wf
+%% Sections: 4.3.2
+'ibm-not-wf-P78-ibm78n01'(suite) -> [];
+'ibm-not-wf-P78-ibm78n01'(Config) -> {skip, "Fix 3"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P78/ibm78n01.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P78/ibm78n02.xml
+%% ID: ibm-not-wf-P78-ibm78n02.xml
+%% Type: not-wf
+%% Sections: 4.3.2
+'ibm-not-wf-P78-ibm78n02'(suite) -> [];
+'ibm-not-wf-P78-ibm78n02'(Config) -> {skip, "Fix 3"}.
+ %%?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ %%?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P78/ibm78n02.xml"]),
+ %%?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ %%?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 78
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P79/ibm79n01.xml
+%% ID: ibm-not-wf-P79-ibm79n01.xml
+%% Type: not-wf
+%% Sections: 4.3.2
+'ibm-not-wf-P79-ibm79n01'(suite) -> [];
+'ibm-not-wf-P79-ibm79n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P79/ibm79n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P79/ibm79n02.xml
+%% ID: ibm-not-wf-P79-ibm79n02.xml
+%% Type: not-wf
+%% Sections: 4.3.2
+'ibm-not-wf-P79-ibm79n02'(suite) -> [];
+'ibm-not-wf-P79-ibm79n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P79/ibm79n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 79
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P80/ibm80n01.xml
+%% ID: ibm-not-wf-P80-ibm80n01.xml
+%% Type: not-wf
+%% Sections: 4.3.3
+'ibm-not-wf-P80-ibm80n01'(suite) -> [];
+'ibm-not-wf-P80-ibm80n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P80/ibm80n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P80/ibm80n02.xml
+%% ID: ibm-not-wf-P80-ibm80n02.xml
+%% Type: not-wf
+%% Sections: 4.3.3
+'ibm-not-wf-P80-ibm80n02'(suite) -> [];
+'ibm-not-wf-P80-ibm80n02'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P80/ibm80n02.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P80/ibm80n03.xml
+%% ID: ibm-not-wf-P80-ibm80n03.xml
+%% Type: not-wf
+%% Sections: 4.3.3
+'ibm-not-wf-P80-ibm80n03'(suite) -> [];
+'ibm-not-wf-P80-ibm80n03'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P80/ibm80n03.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P80/ibm80n04.xml
+%% ID: ibm-not-wf-P80-ibm80n04.xml
+%% Type: not-wf
+%% Sections: 4.3.3
+'ibm-not-wf-P80-ibm80n04'(suite) -> [];
+'ibm-not-wf-P80-ibm80n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P80/ibm80n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P80/ibm80n05.xml
+%% ID: ibm-not-wf-P80-ibm80n05.xml
+%% Type: not-wf
+%% Sections: 4.3.3
+'ibm-not-wf-P80-ibm80n05'(suite) -> [];
+'ibm-not-wf-P80-ibm80n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P80/ibm80n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P80/ibm80n06.xml
+%% ID: ibm-not-wf-P80-ibm80n06.xml
+%% Type: not-wf
+%% Sections: 4.3.3
+'ibm-not-wf-P80-ibm80n06'(suite) -> [];
+'ibm-not-wf-P80-ibm80n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P80/ibm80n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 80
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P81/ibm81n01.xml
+%% ID: ibm-not-wf-P81-ibm81n01.xml
+%% Type: not-wf
+%% Sections: 4.3.3
+'ibm-not-wf-P81-ibm81n01'(suite) -> [];
+'ibm-not-wf-P81-ibm81n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P81/ibm81n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P81/ibm81n02.xml
+%% ID: ibm-not-wf-P81-ibm81n02.xml
+%% Type: not-wf
+%% Sections: 4.3.3
+'ibm-not-wf-P81-ibm81n02'(suite) -> [];
+'ibm-not-wf-P81-ibm81n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P81/ibm81n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P81/ibm81n03.xml
+%% ID: ibm-not-wf-P81-ibm81n03.xml
+%% Type: not-wf
+%% Sections: 4.3.3
+'ibm-not-wf-P81-ibm81n03'(suite) -> [];
+'ibm-not-wf-P81-ibm81n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P81/ibm81n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P81/ibm81n04.xml
+%% ID: ibm-not-wf-P81-ibm81n04.xml
+%% Type: not-wf
+%% Sections: 4.3.3
+'ibm-not-wf-P81-ibm81n04'(suite) -> [];
+'ibm-not-wf-P81-ibm81n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P81/ibm81n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P81/ibm81n05.xml
+%% ID: ibm-not-wf-P81-ibm81n05.xml
+%% Type: not-wf
+%% Sections: 4.3.3
+'ibm-not-wf-P81-ibm81n05'(suite) -> [];
+'ibm-not-wf-P81-ibm81n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P81/ibm81n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P81/ibm81n06.xml
+%% ID: ibm-not-wf-P81-ibm81n06.xml
+%% Type: not-wf
+%% Sections: 4.3.3
+'ibm-not-wf-P81-ibm81n06'(suite) -> [];
+'ibm-not-wf-P81-ibm81n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P81/ibm81n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P81/ibm81n07.xml
+%% ID: ibm-not-wf-P81-ibm81n07.xml
+%% Type: not-wf
+%% Sections: 4.3.3
+'ibm-not-wf-P81-ibm81n07'(suite) -> [];
+'ibm-not-wf-P81-ibm81n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P81/ibm81n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P81/ibm81n08.xml
+%% ID: ibm-not-wf-P81-ibm81n08.xml
+%% Type: not-wf
+%% Sections: 4.3.3
+'ibm-not-wf-P81-ibm81n08'(suite) -> [];
+'ibm-not-wf-P81-ibm81n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P81/ibm81n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P81/ibm81n09.xml
+%% ID: ibm-not-wf-P81-ibm81n09.xml
+%% Type: not-wf
+%% Sections: 4.3.3
+'ibm-not-wf-P81-ibm81n09'(suite) -> [];
+'ibm-not-wf-P81-ibm81n09'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P81/ibm81n09.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 81
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P82/ibm82n01.xml
+%% ID: ibm-not-wf-P82-ibm82n01.xml
+%% Type: not-wf
+%% Sections: 4.7
+'ibm-not-wf-P82-ibm82n01'(suite) -> [];
+'ibm-not-wf-P82-ibm82n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P82/ibm82n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P82/ibm82n02.xml
+%% ID: ibm-not-wf-P82-ibm82n02.xml
+%% Type: not-wf
+%% Sections: 4.7
+'ibm-not-wf-P82-ibm82n02'(suite) -> [];
+'ibm-not-wf-P82-ibm82n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P82/ibm82n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P82/ibm82n03.xml
+%% ID: ibm-not-wf-P82-ibm82n03.xml
+%% Type: not-wf
+%% Sections: 4.7
+'ibm-not-wf-P82-ibm82n03'(suite) -> [];
+'ibm-not-wf-P82-ibm82n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P82/ibm82n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P82/ibm82n04.xml
+%% ID: ibm-not-wf-P82-ibm82n04.xml
+%% Type: not-wf
+%% Sections: 4.7
+'ibm-not-wf-P82-ibm82n04'(suite) -> [];
+'ibm-not-wf-P82-ibm82n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P82/ibm82n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P82/ibm82n05.xml
+%% ID: ibm-not-wf-P82-ibm82n05.xml
+%% Type: not-wf
+%% Sections: 4.7
+'ibm-not-wf-P82-ibm82n05'(suite) -> [];
+'ibm-not-wf-P82-ibm82n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P82/ibm82n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P82/ibm82n06.xml
+%% ID: ibm-not-wf-P82-ibm82n06.xml
+%% Type: not-wf
+%% Sections: 4.7
+'ibm-not-wf-P82-ibm82n06'(suite) -> [];
+'ibm-not-wf-P82-ibm82n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P82/ibm82n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P82/ibm82n07.xml
+%% ID: ibm-not-wf-P82-ibm82n07.xml
+%% Type: not-wf
+%% Sections: 4.7
+'ibm-not-wf-P82-ibm82n07'(suite) -> [];
+'ibm-not-wf-P82-ibm82n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P82/ibm82n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P82/ibm82n08.xml
+%% ID: ibm-not-wf-P82-ibm82n08.xml
+%% Type: not-wf
+%% Sections: 4.7
+'ibm-not-wf-P82-ibm82n08'(suite) -> [];
+'ibm-not-wf-P82-ibm82n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P82/ibm82n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 82
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P83/ibm83n01.xml
+%% ID: ibm-not-wf-P83-ibm83n01.xml
+%% Type: not-wf
+%% Sections: 4.7
+'ibm-not-wf-P83-ibm83n01'(suite) -> [];
+'ibm-not-wf-P83-ibm83n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P83/ibm83n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P83/ibm83n02.xml
+%% ID: ibm-not-wf-P83-ibm83n02.xml
+%% Type: not-wf
+%% Sections: 4.7
+'ibm-not-wf-P83-ibm83n02'(suite) -> [];
+'ibm-not-wf-P83-ibm83n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P83/ibm83n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P83/ibm83n03.xml
+%% ID: ibm-not-wf-P83-ibm83n03.xml
+%% Type: not-wf
+%% Sections: 4.7
+'ibm-not-wf-P83-ibm83n03'(suite) -> [];
+'ibm-not-wf-P83-ibm83n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P83/ibm83n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P83/ibm83n04.xml
+%% ID: ibm-not-wf-P83-ibm83n04.xml
+%% Type: not-wf
+%% Sections: 4.7
+'ibm-not-wf-P83-ibm83n04'(suite) -> [];
+'ibm-not-wf-P83-ibm83n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P83/ibm83n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P83/ibm83n05.xml
+%% ID: ibm-not-wf-P83-ibm83n05.xml
+%% Type: not-wf
+%% Sections: 4.7
+'ibm-not-wf-P83-ibm83n05'(suite) -> [];
+'ibm-not-wf-P83-ibm83n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P83/ibm83n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P83/ibm83n06.xml
+%% ID: ibm-not-wf-P83-ibm83n06.xml
+%% Type: not-wf
+%% Sections: 4.7
+'ibm-not-wf-P83-ibm83n06'(suite) -> [];
+'ibm-not-wf-P83-ibm83n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P83/ibm83n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 83
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n01.xml
+%% ID: ibm-not-wf-P85-ibm85n01.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n01'(suite) -> [];
+'ibm-not-wf-P85-ibm85n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n02.xml
+%% ID: ibm-not-wf-P85-ibm85n02.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n02'(suite) -> [];
+'ibm-not-wf-P85-ibm85n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n03.xml
+%% ID: ibm-not-wf-P85-ibm85n03.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n03'(suite) -> [];
+'ibm-not-wf-P85-ibm85n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n04.xml
+%% ID: ibm-not-wf-P85-ibm85n04.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n04'(suite) -> [];
+'ibm-not-wf-P85-ibm85n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n05.xml
+%% ID: ibm-not-wf-P85-ibm85n05.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n05'(suite) -> [];
+'ibm-not-wf-P85-ibm85n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n06.xml
+%% ID: ibm-not-wf-P85-ibm85n06.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n06'(suite) -> [];
+'ibm-not-wf-P85-ibm85n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n07.xml
+%% ID: ibm-not-wf-P85-ibm85n07.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n07'(suite) -> [];
+'ibm-not-wf-P85-ibm85n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n08.xml
+%% ID: ibm-not-wf-P85-ibm85n08.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n08'(suite) -> [];
+'ibm-not-wf-P85-ibm85n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n09.xml
+%% ID: ibm-not-wf-P85-ibm85n09.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n09'(suite) -> [];
+'ibm-not-wf-P85-ibm85n09'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n09.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n10.xml
+%% ID: ibm-not-wf-P85-ibm85n10.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n10'(suite) -> [];
+'ibm-not-wf-P85-ibm85n10'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n10.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n100.xml
+%% ID: ibm-not-wf-P85-ibm85n100.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n100'(suite) -> [];
+'ibm-not-wf-P85-ibm85n100'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n100.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n101.xml
+%% ID: ibm-not-wf-P85-ibm85n101.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n101'(suite) -> [];
+'ibm-not-wf-P85-ibm85n101'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n101.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n102.xml
+%% ID: ibm-not-wf-P85-ibm85n102.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n102'(suite) -> [];
+'ibm-not-wf-P85-ibm85n102'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n102.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n103.xml
+%% ID: ibm-not-wf-P85-ibm85n103.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n103'(suite) -> [];
+'ibm-not-wf-P85-ibm85n103'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n103.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n104.xml
+%% ID: ibm-not-wf-P85-ibm85n104.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n104'(suite) -> [];
+'ibm-not-wf-P85-ibm85n104'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n104.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n105.xml
+%% ID: ibm-not-wf-P85-ibm85n105.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n105'(suite) -> [];
+'ibm-not-wf-P85-ibm85n105'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n105.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n106.xml
+%% ID: ibm-not-wf-P85-ibm85n106.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n106'(suite) -> [];
+'ibm-not-wf-P85-ibm85n106'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n106.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n107.xml
+%% ID: ibm-not-wf-P85-ibm85n107.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n107'(suite) -> [];
+'ibm-not-wf-P85-ibm85n107'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n107.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n108.xml
+%% ID: ibm-not-wf-P85-ibm85n108.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n108'(suite) -> [];
+'ibm-not-wf-P85-ibm85n108'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n108.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n109.xml
+%% ID: ibm-not-wf-P85-ibm85n109.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n109'(suite) -> [];
+'ibm-not-wf-P85-ibm85n109'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n109.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n11.xml
+%% ID: ibm-not-wf-P85-ibm85n11.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n11'(suite) -> [];
+'ibm-not-wf-P85-ibm85n11'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n11.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n110.xml
+%% ID: ibm-not-wf-P85-ibm85n110.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n110'(suite) -> [];
+'ibm-not-wf-P85-ibm85n110'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n110.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n111.xml
+%% ID: ibm-not-wf-P85-ibm85n111.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n111'(suite) -> [];
+'ibm-not-wf-P85-ibm85n111'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n111.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n112.xml
+%% ID: ibm-not-wf-P85-ibm85n112.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n112'(suite) -> [];
+'ibm-not-wf-P85-ibm85n112'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n112.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n113.xml
+%% ID: ibm-not-wf-P85-ibm85n113.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n113'(suite) -> [];
+'ibm-not-wf-P85-ibm85n113'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n113.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n114.xml
+%% ID: ibm-not-wf-P85-ibm85n114.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n114'(suite) -> [];
+'ibm-not-wf-P85-ibm85n114'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n114.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n115.xml
+%% ID: ibm-not-wf-P85-ibm85n115.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n115'(suite) -> [];
+'ibm-not-wf-P85-ibm85n115'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n115.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n116.xml
+%% ID: ibm-not-wf-P85-ibm85n116.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n116'(suite) -> [];
+'ibm-not-wf-P85-ibm85n116'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n116.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n117.xml
+%% ID: ibm-not-wf-P85-ibm85n117.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n117'(suite) -> [];
+'ibm-not-wf-P85-ibm85n117'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n117.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n118.xml
+%% ID: ibm-not-wf-P85-ibm85n118.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n118'(suite) -> [];
+'ibm-not-wf-P85-ibm85n118'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n118.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n119.xml
+%% ID: ibm-not-wf-P85-ibm85n119.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n119'(suite) -> [];
+'ibm-not-wf-P85-ibm85n119'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n119.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n12.xml
+%% ID: ibm-not-wf-P85-ibm85n12.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n12'(suite) -> [];
+'ibm-not-wf-P85-ibm85n12'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n12.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n120.xml
+%% ID: ibm-not-wf-P85-ibm85n120.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n120'(suite) -> [];
+'ibm-not-wf-P85-ibm85n120'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n120.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n121.xml
+%% ID: ibm-not-wf-P85-ibm85n121.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n121'(suite) -> [];
+'ibm-not-wf-P85-ibm85n121'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n121.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n122.xml
+%% ID: ibm-not-wf-P85-ibm85n122.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n122'(suite) -> [];
+'ibm-not-wf-P85-ibm85n122'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n122.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n123.xml
+%% ID: ibm-not-wf-P85-ibm85n123.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n123'(suite) -> [];
+'ibm-not-wf-P85-ibm85n123'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n123.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n124.xml
+%% ID: ibm-not-wf-P85-ibm85n124.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n124'(suite) -> [];
+'ibm-not-wf-P85-ibm85n124'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n124.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n125.xml
+%% ID: ibm-not-wf-P85-ibm85n125.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n125'(suite) -> [];
+'ibm-not-wf-P85-ibm85n125'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n125.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n126.xml
+%% ID: ibm-not-wf-P85-ibm85n126.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n126'(suite) -> [];
+'ibm-not-wf-P85-ibm85n126'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n126.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n127.xml
+%% ID: ibm-not-wf-P85-ibm85n127.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n127'(suite) -> [];
+'ibm-not-wf-P85-ibm85n127'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n127.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n128.xml
+%% ID: ibm-not-wf-P85-ibm85n128.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n128'(suite) -> [];
+'ibm-not-wf-P85-ibm85n128'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n128.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n129.xml
+%% ID: ibm-not-wf-P85-ibm85n129.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n129'(suite) -> [];
+'ibm-not-wf-P85-ibm85n129'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n129.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n13.xml
+%% ID: ibm-not-wf-P85-ibm85n13.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n13'(suite) -> [];
+'ibm-not-wf-P85-ibm85n13'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n13.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n130.xml
+%% ID: ibm-not-wf-P85-ibm85n130.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n130'(suite) -> [];
+'ibm-not-wf-P85-ibm85n130'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n130.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n131.xml
+%% ID: ibm-not-wf-P85-ibm85n131.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n131'(suite) -> [];
+'ibm-not-wf-P85-ibm85n131'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n131.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n132.xml
+%% ID: ibm-not-wf-P85-ibm85n132.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n132'(suite) -> [];
+'ibm-not-wf-P85-ibm85n132'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n132.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n133.xml
+%% ID: ibm-not-wf-P85-ibm85n133.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n133'(suite) -> [];
+'ibm-not-wf-P85-ibm85n133'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n133.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n134.xml
+%% ID: ibm-not-wf-P85-ibm85n134.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n134'(suite) -> [];
+'ibm-not-wf-P85-ibm85n134'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n134.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n135.xml
+%% ID: ibm-not-wf-P85-ibm85n135.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n135'(suite) -> [];
+'ibm-not-wf-P85-ibm85n135'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n135.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n136.xml
+%% ID: ibm-not-wf-P85-ibm85n136.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n136'(suite) -> [];
+'ibm-not-wf-P85-ibm85n136'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n136.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n137.xml
+%% ID: ibm-not-wf-P85-ibm85n137.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n137'(suite) -> [];
+'ibm-not-wf-P85-ibm85n137'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n137.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n138.xml
+%% ID: ibm-not-wf-P85-ibm85n138.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n138'(suite) -> [];
+'ibm-not-wf-P85-ibm85n138'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n138.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n139.xml
+%% ID: ibm-not-wf-P85-ibm85n139.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n139'(suite) -> [];
+'ibm-not-wf-P85-ibm85n139'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n139.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n14.xml
+%% ID: ibm-not-wf-P85-ibm85n14.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n14'(suite) -> [];
+'ibm-not-wf-P85-ibm85n14'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n14.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n140.xml
+%% ID: ibm-not-wf-P85-ibm85n140.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n140'(suite) -> [];
+'ibm-not-wf-P85-ibm85n140'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n140.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n141.xml
+%% ID: ibm-not-wf-P85-ibm85n141.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n141'(suite) -> [];
+'ibm-not-wf-P85-ibm85n141'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n141.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n142.xml
+%% ID: ibm-not-wf-P85-ibm85n142.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n142'(suite) -> [];
+'ibm-not-wf-P85-ibm85n142'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n142.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n143.xml
+%% ID: ibm-not-wf-P85-ibm85n143.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n143'(suite) -> [];
+'ibm-not-wf-P85-ibm85n143'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n143.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n144.xml
+%% ID: ibm-not-wf-P85-ibm85n144.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n144'(suite) -> [];
+'ibm-not-wf-P85-ibm85n144'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n144.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n145.xml
+%% ID: ibm-not-wf-P85-ibm85n145.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n145'(suite) -> [];
+'ibm-not-wf-P85-ibm85n145'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n145.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n146.xml
+%% ID: ibm-not-wf-P85-ibm85n146.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n146'(suite) -> [];
+'ibm-not-wf-P85-ibm85n146'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n146.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n147.xml
+%% ID: ibm-not-wf-P85-ibm85n147.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n147'(suite) -> [];
+'ibm-not-wf-P85-ibm85n147'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n147.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n148.xml
+%% ID: ibm-not-wf-P85-ibm85n148.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n148'(suite) -> [];
+'ibm-not-wf-P85-ibm85n148'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n148.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n149.xml
+%% ID: ibm-not-wf-P85-ibm85n149.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n149'(suite) -> [];
+'ibm-not-wf-P85-ibm85n149'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n149.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n15.xml
+%% ID: ibm-not-wf-P85-ibm85n15.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n15'(suite) -> [];
+'ibm-not-wf-P85-ibm85n15'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n15.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n150.xml
+%% ID: ibm-not-wf-P85-ibm85n150.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n150'(suite) -> [];
+'ibm-not-wf-P85-ibm85n150'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n150.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n151.xml
+%% ID: ibm-not-wf-P85-ibm85n151.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n151'(suite) -> [];
+'ibm-not-wf-P85-ibm85n151'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n151.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n152.xml
+%% ID: ibm-not-wf-P85-ibm85n152.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n152'(suite) -> [];
+'ibm-not-wf-P85-ibm85n152'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n152.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n153.xml
+%% ID: ibm-not-wf-P85-ibm85n153.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n153'(suite) -> [];
+'ibm-not-wf-P85-ibm85n153'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n153.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n154.xml
+%% ID: ibm-not-wf-P85-ibm85n154.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n154'(suite) -> [];
+'ibm-not-wf-P85-ibm85n154'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n154.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n155.xml
+%% ID: ibm-not-wf-P85-ibm85n155.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n155'(suite) -> [];
+'ibm-not-wf-P85-ibm85n155'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n155.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n156.xml
+%% ID: ibm-not-wf-P85-ibm85n156.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n156'(suite) -> [];
+'ibm-not-wf-P85-ibm85n156'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n156.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n157.xml
+%% ID: ibm-not-wf-P85-ibm85n157.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n157'(suite) -> [];
+'ibm-not-wf-P85-ibm85n157'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n157.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n158.xml
+%% ID: ibm-not-wf-P85-ibm85n158.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n158'(suite) -> [];
+'ibm-not-wf-P85-ibm85n158'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n158.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n159.xml
+%% ID: ibm-not-wf-P85-ibm85n159.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n159'(suite) -> [];
+'ibm-not-wf-P85-ibm85n159'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n159.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n16.xml
+%% ID: ibm-not-wf-P85-ibm85n16.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n16'(suite) -> [];
+'ibm-not-wf-P85-ibm85n16'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n16.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n160.xml
+%% ID: ibm-not-wf-P85-ibm85n160.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n160'(suite) -> [];
+'ibm-not-wf-P85-ibm85n160'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n160.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n161.xml
+%% ID: ibm-not-wf-P85-ibm85n161.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n161'(suite) -> [];
+'ibm-not-wf-P85-ibm85n161'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n161.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n162.xml
+%% ID: ibm-not-wf-P85-ibm85n162.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n162'(suite) -> [];
+'ibm-not-wf-P85-ibm85n162'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n162.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n163.xml
+%% ID: ibm-not-wf-P85-ibm85n163.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n163'(suite) -> [];
+'ibm-not-wf-P85-ibm85n163'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n163.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n164.xml
+%% ID: ibm-not-wf-P85-ibm85n164.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n164'(suite) -> [];
+'ibm-not-wf-P85-ibm85n164'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n164.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n165.xml
+%% ID: ibm-not-wf-P85-ibm85n165.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n165'(suite) -> [];
+'ibm-not-wf-P85-ibm85n165'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n165.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n166.xml
+%% ID: ibm-not-wf-P85-ibm85n166.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n166'(suite) -> [];
+'ibm-not-wf-P85-ibm85n166'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n166.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n167.xml
+%% ID: ibm-not-wf-P85-ibm85n167.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n167'(suite) -> [];
+'ibm-not-wf-P85-ibm85n167'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n167.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n168.xml
+%% ID: ibm-not-wf-P85-ibm85n168.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n168'(suite) -> [];
+'ibm-not-wf-P85-ibm85n168'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n168.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n169.xml
+%% ID: ibm-not-wf-P85-ibm85n169.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n169'(suite) -> [];
+'ibm-not-wf-P85-ibm85n169'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n169.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n17.xml
+%% ID: ibm-not-wf-P85-ibm85n17.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n17'(suite) -> [];
+'ibm-not-wf-P85-ibm85n17'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n17.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n170.xml
+%% ID: ibm-not-wf-P85-ibm85n170.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n170'(suite) -> [];
+'ibm-not-wf-P85-ibm85n170'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n170.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n171.xml
+%% ID: ibm-not-wf-P85-ibm85n171.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n171'(suite) -> [];
+'ibm-not-wf-P85-ibm85n171'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n171.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n172.xml
+%% ID: ibm-not-wf-P85-ibm85n172.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n172'(suite) -> [];
+'ibm-not-wf-P85-ibm85n172'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n172.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n173.xml
+%% ID: ibm-not-wf-P85-ibm85n173.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n173'(suite) -> [];
+'ibm-not-wf-P85-ibm85n173'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n173.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n174.xml
+%% ID: ibm-not-wf-P85-ibm85n174.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n174'(suite) -> [];
+'ibm-not-wf-P85-ibm85n174'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n174.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n175.xml
+%% ID: ibm-not-wf-P85-ibm85n175.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n175'(suite) -> [];
+'ibm-not-wf-P85-ibm85n175'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n175.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n176.xml
+%% ID: ibm-not-wf-P85-ibm85n176.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n176'(suite) -> [];
+'ibm-not-wf-P85-ibm85n176'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n176.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n177.xml
+%% ID: ibm-not-wf-P85-ibm85n177.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n177'(suite) -> [];
+'ibm-not-wf-P85-ibm85n177'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n177.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n178.xml
+%% ID: ibm-not-wf-P85-ibm85n178.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n178'(suite) -> [];
+'ibm-not-wf-P85-ibm85n178'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n178.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n179.xml
+%% ID: ibm-not-wf-P85-ibm85n179.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n179'(suite) -> [];
+'ibm-not-wf-P85-ibm85n179'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n179.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n18.xml
+%% ID: ibm-not-wf-P85-ibm85n18.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n18'(suite) -> [];
+'ibm-not-wf-P85-ibm85n18'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n18.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n180.xml
+%% ID: ibm-not-wf-P85-ibm85n180.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n180'(suite) -> [];
+'ibm-not-wf-P85-ibm85n180'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n180.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n181.xml
+%% ID: ibm-not-wf-P85-ibm85n181.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n181'(suite) -> [];
+'ibm-not-wf-P85-ibm85n181'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n181.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n182.xml
+%% ID: ibm-not-wf-P85-ibm85n182.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n182'(suite) -> [];
+'ibm-not-wf-P85-ibm85n182'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n182.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n183.xml
+%% ID: ibm-not-wf-P85-ibm85n183.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n183'(suite) -> [];
+'ibm-not-wf-P85-ibm85n183'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n183.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n184.xml
+%% ID: ibm-not-wf-P85-ibm85n184.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n184'(suite) -> [];
+'ibm-not-wf-P85-ibm85n184'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n184.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n185.xml
+%% ID: ibm-not-wf-P85-ibm85n185.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n185'(suite) -> [];
+'ibm-not-wf-P85-ibm85n185'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n185.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n186.xml
+%% ID: ibm-not-wf-P85-ibm85n186.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n186'(suite) -> [];
+'ibm-not-wf-P85-ibm85n186'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n186.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n187.xml
+%% ID: ibm-not-wf-P85-ibm85n187.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n187'(suite) -> [];
+'ibm-not-wf-P85-ibm85n187'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n187.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n188.xml
+%% ID: ibm-not-wf-P85-ibm85n188.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n188'(suite) -> [];
+'ibm-not-wf-P85-ibm85n188'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n188.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n189.xml
+%% ID: ibm-not-wf-P85-ibm85n189.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n189'(suite) -> [];
+'ibm-not-wf-P85-ibm85n189'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n189.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n19.xml
+%% ID: ibm-not-wf-P85-ibm85n19.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n19'(suite) -> [];
+'ibm-not-wf-P85-ibm85n19'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n19.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n190.xml
+%% ID: ibm-not-wf-P85-ibm85n190.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n190'(suite) -> [];
+'ibm-not-wf-P85-ibm85n190'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n190.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n191.xml
+%% ID: ibm-not-wf-P85-ibm85n191.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n191'(suite) -> [];
+'ibm-not-wf-P85-ibm85n191'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n191.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n192.xml
+%% ID: ibm-not-wf-P85-ibm85n192.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n192'(suite) -> [];
+'ibm-not-wf-P85-ibm85n192'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n192.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n193.xml
+%% ID: ibm-not-wf-P85-ibm85n193.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n193'(suite) -> [];
+'ibm-not-wf-P85-ibm85n193'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n193.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n194.xml
+%% ID: ibm-not-wf-P85-ibm85n194.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n194'(suite) -> [];
+'ibm-not-wf-P85-ibm85n194'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n194.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n195.xml
+%% ID: ibm-not-wf-P85-ibm85n195.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n195'(suite) -> [];
+'ibm-not-wf-P85-ibm85n195'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n195.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n196.xml
+%% ID: ibm-not-wf-P85-ibm85n196.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n196'(suite) -> [];
+'ibm-not-wf-P85-ibm85n196'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n196.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n197.xml
+%% ID: ibm-not-wf-P85-ibm85n197.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n197'(suite) -> [];
+'ibm-not-wf-P85-ibm85n197'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n197.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n198.xml
+%% ID: ibm-not-wf-P85-ibm85n198.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n198'(suite) -> [];
+'ibm-not-wf-P85-ibm85n198'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n198.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n20.xml
+%% ID: ibm-not-wf-P85-ibm85n20.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n20'(suite) -> [];
+'ibm-not-wf-P85-ibm85n20'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n20.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n21.xml
+%% ID: ibm-not-wf-P85-ibm85n21.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n21'(suite) -> [];
+'ibm-not-wf-P85-ibm85n21'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n21.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n22.xml
+%% ID: ibm-not-wf-P85-ibm85n22.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n22'(suite) -> [];
+'ibm-not-wf-P85-ibm85n22'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n22.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n23.xml
+%% ID: ibm-not-wf-P85-ibm85n23.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n23'(suite) -> [];
+'ibm-not-wf-P85-ibm85n23'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n23.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n24.xml
+%% ID: ibm-not-wf-P85-ibm85n24.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n24'(suite) -> [];
+'ibm-not-wf-P85-ibm85n24'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n24.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n25.xml
+%% ID: ibm-not-wf-P85-ibm85n25.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n25'(suite) -> [];
+'ibm-not-wf-P85-ibm85n25'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n25.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n26.xml
+%% ID: ibm-not-wf-P85-ibm85n26.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n26'(suite) -> [];
+'ibm-not-wf-P85-ibm85n26'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n26.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n27.xml
+%% ID: ibm-not-wf-P85-ibm85n27.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n27'(suite) -> [];
+'ibm-not-wf-P85-ibm85n27'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n27.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n28.xml
+%% ID: ibm-not-wf-P85-ibm85n28.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n28'(suite) -> [];
+'ibm-not-wf-P85-ibm85n28'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n28.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n29.xml
+%% ID: ibm-not-wf-P85-ibm85n29.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n29'(suite) -> [];
+'ibm-not-wf-P85-ibm85n29'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n29.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n30.xml
+%% ID: ibm-not-wf-P85-ibm85n30.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n30'(suite) -> [];
+'ibm-not-wf-P85-ibm85n30'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n30.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n31.xml
+%% ID: ibm-not-wf-P85-ibm85n31.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n31'(suite) -> [];
+'ibm-not-wf-P85-ibm85n31'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n31.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n32.xml
+%% ID: ibm-not-wf-P85-ibm85n32.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n32'(suite) -> [];
+'ibm-not-wf-P85-ibm85n32'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n32.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n33.xml
+%% ID: ibm-not-wf-P85-ibm85n33.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n33'(suite) -> [];
+'ibm-not-wf-P85-ibm85n33'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n33.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n34.xml
+%% ID: ibm-not-wf-P85-ibm85n34.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n34'(suite) -> [];
+'ibm-not-wf-P85-ibm85n34'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n34.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n35.xml
+%% ID: ibm-not-wf-P85-ibm85n35.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n35'(suite) -> [];
+'ibm-not-wf-P85-ibm85n35'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n35.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n36.xml
+%% ID: ibm-not-wf-P85-ibm85n36.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n36'(suite) -> [];
+'ibm-not-wf-P85-ibm85n36'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n36.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n37.xml
+%% ID: ibm-not-wf-P85-ibm85n37.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n37'(suite) -> [];
+'ibm-not-wf-P85-ibm85n37'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n37.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n38.xml
+%% ID: ibm-not-wf-P85-ibm85n38.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n38'(suite) -> [];
+'ibm-not-wf-P85-ibm85n38'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n38.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n39.xml
+%% ID: ibm-not-wf-P85-ibm85n39.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n39'(suite) -> [];
+'ibm-not-wf-P85-ibm85n39'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n39.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n40.xml
+%% ID: ibm-not-wf-P85-ibm85n40.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n40'(suite) -> [];
+'ibm-not-wf-P85-ibm85n40'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n40.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n41.xml
+%% ID: ibm-not-wf-P85-ibm85n41.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n41'(suite) -> [];
+'ibm-not-wf-P85-ibm85n41'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n41.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n42.xml
+%% ID: ibm-not-wf-P85-ibm85n42.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n42'(suite) -> [];
+'ibm-not-wf-P85-ibm85n42'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n42.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n43.xml
+%% ID: ibm-not-wf-P85-ibm85n43.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n43'(suite) -> [];
+'ibm-not-wf-P85-ibm85n43'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n43.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n44.xml
+%% ID: ibm-not-wf-P85-ibm85n44.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n44'(suite) -> [];
+'ibm-not-wf-P85-ibm85n44'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n44.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n45.xml
+%% ID: ibm-not-wf-P85-ibm85n45.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n45'(suite) -> [];
+'ibm-not-wf-P85-ibm85n45'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n45.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n46.xml
+%% ID: ibm-not-wf-P85-ibm85n46.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n46'(suite) -> [];
+'ibm-not-wf-P85-ibm85n46'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n46.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n47.xml
+%% ID: ibm-not-wf-P85-ibm85n47.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n47'(suite) -> [];
+'ibm-not-wf-P85-ibm85n47'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n47.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n48.xml
+%% ID: ibm-not-wf-P85-ibm85n48.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n48'(suite) -> [];
+'ibm-not-wf-P85-ibm85n48'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n48.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n49.xml
+%% ID: ibm-not-wf-P85-ibm85n49.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n49'(suite) -> [];
+'ibm-not-wf-P85-ibm85n49'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n49.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n50.xml
+%% ID: ibm-not-wf-P85-ibm85n50.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n50'(suite) -> [];
+'ibm-not-wf-P85-ibm85n50'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n50.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n51.xml
+%% ID: ibm-not-wf-P85-ibm85n51.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n51'(suite) -> [];
+'ibm-not-wf-P85-ibm85n51'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n51.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n52.xml
+%% ID: ibm-not-wf-P85-ibm85n52.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n52'(suite) -> [];
+'ibm-not-wf-P85-ibm85n52'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n52.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n53.xml
+%% ID: ibm-not-wf-P85-ibm85n53.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n53'(suite) -> [];
+'ibm-not-wf-P85-ibm85n53'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n53.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n54.xml
+%% ID: ibm-not-wf-P85-ibm85n54.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n54'(suite) -> [];
+'ibm-not-wf-P85-ibm85n54'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n54.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n55.xml
+%% ID: ibm-not-wf-P85-ibm85n55.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n55'(suite) -> [];
+'ibm-not-wf-P85-ibm85n55'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n55.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n56.xml
+%% ID: ibm-not-wf-P85-ibm85n56.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n56'(suite) -> [];
+'ibm-not-wf-P85-ibm85n56'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n56.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n57.xml
+%% ID: ibm-not-wf-P85-ibm85n57.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n57'(suite) -> [];
+'ibm-not-wf-P85-ibm85n57'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n57.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n58.xml
+%% ID: ibm-not-wf-P85-ibm85n58.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n58'(suite) -> [];
+'ibm-not-wf-P85-ibm85n58'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n58.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n59.xml
+%% ID: ibm-not-wf-P85-ibm85n59.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n59'(suite) -> [];
+'ibm-not-wf-P85-ibm85n59'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n59.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n60.xml
+%% ID: ibm-not-wf-P85-ibm85n60.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n60'(suite) -> [];
+'ibm-not-wf-P85-ibm85n60'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n60.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n61.xml
+%% ID: ibm-not-wf-P85-ibm85n61.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n61'(suite) -> [];
+'ibm-not-wf-P85-ibm85n61'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n61.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n62.xml
+%% ID: ibm-not-wf-P85-ibm85n62.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n62'(suite) -> [];
+'ibm-not-wf-P85-ibm85n62'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n62.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n63.xml
+%% ID: ibm-not-wf-P85-ibm85n63.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n63'(suite) -> [];
+'ibm-not-wf-P85-ibm85n63'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n63.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n64.xml
+%% ID: ibm-not-wf-P85-ibm85n64.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n64'(suite) -> [];
+'ibm-not-wf-P85-ibm85n64'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n64.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n65.xml
+%% ID: ibm-not-wf-P85-ibm85n65.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n65'(suite) -> [];
+'ibm-not-wf-P85-ibm85n65'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n65.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n66.xml
+%% ID: ibm-not-wf-P85-ibm85n66.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n66'(suite) -> [];
+'ibm-not-wf-P85-ibm85n66'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n66.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n67.xml
+%% ID: ibm-not-wf-P85-ibm85n67.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n67'(suite) -> [];
+'ibm-not-wf-P85-ibm85n67'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n67.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n68.xml
+%% ID: ibm-not-wf-P85-ibm85n68.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n68'(suite) -> [];
+'ibm-not-wf-P85-ibm85n68'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n68.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n69.xml
+%% ID: ibm-not-wf-P85-ibm85n69.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n69'(suite) -> [];
+'ibm-not-wf-P85-ibm85n69'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n69.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n70.xml
+%% ID: ibm-not-wf-P85-ibm85n70.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n70'(suite) -> [];
+'ibm-not-wf-P85-ibm85n70'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n70.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n71.xml
+%% ID: ibm-not-wf-P85-ibm85n71.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n71'(suite) -> [];
+'ibm-not-wf-P85-ibm85n71'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n71.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n72.xml
+%% ID: ibm-not-wf-P85-ibm85n72.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n72'(suite) -> [];
+'ibm-not-wf-P85-ibm85n72'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n72.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n73.xml
+%% ID: ibm-not-wf-P85-ibm85n73.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n73'(suite) -> [];
+'ibm-not-wf-P85-ibm85n73'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n73.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n74.xml
+%% ID: ibm-not-wf-P85-ibm85n74.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n74'(suite) -> [];
+'ibm-not-wf-P85-ibm85n74'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n74.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n75.xml
+%% ID: ibm-not-wf-P85-ibm85n75.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n75'(suite) -> [];
+'ibm-not-wf-P85-ibm85n75'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n75.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n76.xml
+%% ID: ibm-not-wf-P85-ibm85n76.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n76'(suite) -> [];
+'ibm-not-wf-P85-ibm85n76'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n76.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n77.xml
+%% ID: ibm-not-wf-P85-ibm85n77.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n77'(suite) -> [];
+'ibm-not-wf-P85-ibm85n77'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n77.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n78.xml
+%% ID: ibm-not-wf-P85-ibm85n78.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n78'(suite) -> [];
+'ibm-not-wf-P85-ibm85n78'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n78.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n79.xml
+%% ID: ibm-not-wf-P85-ibm85n79.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n79'(suite) -> [];
+'ibm-not-wf-P85-ibm85n79'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n79.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n80.xml
+%% ID: ibm-not-wf-P85-ibm85n80.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n80'(suite) -> [];
+'ibm-not-wf-P85-ibm85n80'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n80.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n81.xml
+%% ID: ibm-not-wf-P85-ibm85n81.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n81'(suite) -> [];
+'ibm-not-wf-P85-ibm85n81'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n81.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n82.xml
+%% ID: ibm-not-wf-P85-ibm85n82.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n82'(suite) -> [];
+'ibm-not-wf-P85-ibm85n82'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n82.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n83.xml
+%% ID: ibm-not-wf-P85-ibm85n83.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n83'(suite) -> [];
+'ibm-not-wf-P85-ibm85n83'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n83.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n84.xml
+%% ID: ibm-not-wf-P85-ibm85n84.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n84'(suite) -> [];
+'ibm-not-wf-P85-ibm85n84'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n84.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n85.xml
+%% ID: ibm-not-wf-P85-ibm85n85.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n85'(suite) -> [];
+'ibm-not-wf-P85-ibm85n85'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n85.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n86.xml
+%% ID: ibm-not-wf-P85-ibm85n86.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n86'(suite) -> [];
+'ibm-not-wf-P85-ibm85n86'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n86.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n87.xml
+%% ID: ibm-not-wf-P85-ibm85n87.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n87'(suite) -> [];
+'ibm-not-wf-P85-ibm85n87'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n87.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n88.xml
+%% ID: ibm-not-wf-P85-ibm85n88.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n88'(suite) -> [];
+'ibm-not-wf-P85-ibm85n88'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n88.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n89.xml
+%% ID: ibm-not-wf-P85-ibm85n89.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n89'(suite) -> [];
+'ibm-not-wf-P85-ibm85n89'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n89.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n90.xml
+%% ID: ibm-not-wf-P85-ibm85n90.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n90'(suite) -> [];
+'ibm-not-wf-P85-ibm85n90'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n90.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n91.xml
+%% ID: ibm-not-wf-P85-ibm85n91.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n91'(suite) -> [];
+'ibm-not-wf-P85-ibm85n91'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n91.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n92.xml
+%% ID: ibm-not-wf-P85-ibm85n92.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n92'(suite) -> [];
+'ibm-not-wf-P85-ibm85n92'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n92.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n93.xml
+%% ID: ibm-not-wf-P85-ibm85n93.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n93'(suite) -> [];
+'ibm-not-wf-P85-ibm85n93'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n93.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n94.xml
+%% ID: ibm-not-wf-P85-ibm85n94.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n94'(suite) -> [];
+'ibm-not-wf-P85-ibm85n94'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n94.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n95.xml
+%% ID: ibm-not-wf-P85-ibm85n95.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n95'(suite) -> [];
+'ibm-not-wf-P85-ibm85n95'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n95.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n96.xml
+%% ID: ibm-not-wf-P85-ibm85n96.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n96'(suite) -> [];
+'ibm-not-wf-P85-ibm85n96'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n96.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n97.xml
+%% ID: ibm-not-wf-P85-ibm85n97.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n97'(suite) -> [];
+'ibm-not-wf-P85-ibm85n97'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n97.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n98.xml
+%% ID: ibm-not-wf-P85-ibm85n98.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n98'(suite) -> [];
+'ibm-not-wf-P85-ibm85n98'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n98.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P85/ibm85n99.xml
+%% ID: ibm-not-wf-P85-ibm85n99.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P85-ibm85n99'(suite) -> [];
+'ibm-not-wf-P85-ibm85n99'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P85/ibm85n99.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 85
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P86/ibm86n01.xml
+%% ID: ibm-not-wf-P86-ibm86n01.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P86-ibm86n01'(suite) -> [];
+'ibm-not-wf-P86-ibm86n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P86/ibm86n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P86/ibm86n02.xml
+%% ID: ibm-not-wf-P86-ibm86n02.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P86-ibm86n02'(suite) -> [];
+'ibm-not-wf-P86-ibm86n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P86/ibm86n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P86/ibm86n03.xml
+%% ID: ibm-not-wf-P86-ibm86n03.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P86-ibm86n03'(suite) -> [];
+'ibm-not-wf-P86-ibm86n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P86/ibm86n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P86/ibm86n04.xml
+%% ID: ibm-not-wf-P86-ibm86n04.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P86-ibm86n04'(suite) -> [];
+'ibm-not-wf-P86-ibm86n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P86/ibm86n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 86
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n01.xml
+%% ID: ibm-not-wf-P87-ibm87n01.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n01'(suite) -> [];
+'ibm-not-wf-P87-ibm87n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n02.xml
+%% ID: ibm-not-wf-P87-ibm87n02.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n02'(suite) -> [];
+'ibm-not-wf-P87-ibm87n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n03.xml
+%% ID: ibm-not-wf-P87-ibm87n03.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n03'(suite) -> [];
+'ibm-not-wf-P87-ibm87n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n04.xml
+%% ID: ibm-not-wf-P87-ibm87n04.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n04'(suite) -> [];
+'ibm-not-wf-P87-ibm87n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n05.xml
+%% ID: ibm-not-wf-P87-ibm87n05.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n05'(suite) -> [];
+'ibm-not-wf-P87-ibm87n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n06.xml
+%% ID: ibm-not-wf-P87-ibm87n06.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n06'(suite) -> [];
+'ibm-not-wf-P87-ibm87n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n07.xml
+%% ID: ibm-not-wf-P87-ibm87n07.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n07'(suite) -> [];
+'ibm-not-wf-P87-ibm87n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n08.xml
+%% ID: ibm-not-wf-P87-ibm87n08.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n08'(suite) -> [];
+'ibm-not-wf-P87-ibm87n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n09.xml
+%% ID: ibm-not-wf-P87-ibm87n09.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n09'(suite) -> [];
+'ibm-not-wf-P87-ibm87n09'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n09.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n10.xml
+%% ID: ibm-not-wf-P87-ibm87n10.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n10'(suite) -> [];
+'ibm-not-wf-P87-ibm87n10'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n10.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n11.xml
+%% ID: ibm-not-wf-P87-ibm87n11.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n11'(suite) -> [];
+'ibm-not-wf-P87-ibm87n11'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n11.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n12.xml
+%% ID: ibm-not-wf-P87-ibm87n12.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n12'(suite) -> [];
+'ibm-not-wf-P87-ibm87n12'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n12.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n13.xml
+%% ID: ibm-not-wf-P87-ibm87n13.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n13'(suite) -> [];
+'ibm-not-wf-P87-ibm87n13'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n13.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n14.xml
+%% ID: ibm-not-wf-P87-ibm87n14.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n14'(suite) -> [];
+'ibm-not-wf-P87-ibm87n14'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n14.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n15.xml
+%% ID: ibm-not-wf-P87-ibm87n15.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n15'(suite) -> [];
+'ibm-not-wf-P87-ibm87n15'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n15.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n16.xml
+%% ID: ibm-not-wf-P87-ibm87n16.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n16'(suite) -> [];
+'ibm-not-wf-P87-ibm87n16'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n16.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n17.xml
+%% ID: ibm-not-wf-P87-ibm87n17.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n17'(suite) -> [];
+'ibm-not-wf-P87-ibm87n17'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n17.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n18.xml
+%% ID: ibm-not-wf-P87-ibm87n18.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n18'(suite) -> [];
+'ibm-not-wf-P87-ibm87n18'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n18.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n19.xml
+%% ID: ibm-not-wf-P87-ibm87n19.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n19'(suite) -> [];
+'ibm-not-wf-P87-ibm87n19'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n19.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n20.xml
+%% ID: ibm-not-wf-P87-ibm87n20.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n20'(suite) -> [];
+'ibm-not-wf-P87-ibm87n20'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n20.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n21.xml
+%% ID: ibm-not-wf-P87-ibm87n21.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n21'(suite) -> [];
+'ibm-not-wf-P87-ibm87n21'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n21.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n22.xml
+%% ID: ibm-not-wf-P87-ibm87n22.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n22'(suite) -> [];
+'ibm-not-wf-P87-ibm87n22'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n22.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n23.xml
+%% ID: ibm-not-wf-P87-ibm87n23.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n23'(suite) -> [];
+'ibm-not-wf-P87-ibm87n23'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n23.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n24.xml
+%% ID: ibm-not-wf-P87-ibm87n24.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n24'(suite) -> [];
+'ibm-not-wf-P87-ibm87n24'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n24.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n25.xml
+%% ID: ibm-not-wf-P87-ibm87n25.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n25'(suite) -> [];
+'ibm-not-wf-P87-ibm87n25'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n25.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n26.xml
+%% ID: ibm-not-wf-P87-ibm87n26.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n26'(suite) -> [];
+'ibm-not-wf-P87-ibm87n26'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n26.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n27.xml
+%% ID: ibm-not-wf-P87-ibm87n27.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n27'(suite) -> [];
+'ibm-not-wf-P87-ibm87n27'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n27.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n28.xml
+%% ID: ibm-not-wf-P87-ibm87n28.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n28'(suite) -> [];
+'ibm-not-wf-P87-ibm87n28'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n28.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n29.xml
+%% ID: ibm-not-wf-P87-ibm87n29.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n29'(suite) -> [];
+'ibm-not-wf-P87-ibm87n29'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n29.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n30.xml
+%% ID: ibm-not-wf-P87-ibm87n30.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n30'(suite) -> [];
+'ibm-not-wf-P87-ibm87n30'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n30.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n31.xml
+%% ID: ibm-not-wf-P87-ibm87n31.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n31'(suite) -> [];
+'ibm-not-wf-P87-ibm87n31'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n31.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n32.xml
+%% ID: ibm-not-wf-P87-ibm87n32.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n32'(suite) -> [];
+'ibm-not-wf-P87-ibm87n32'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n32.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n33.xml
+%% ID: ibm-not-wf-P87-ibm87n33.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n33'(suite) -> [];
+'ibm-not-wf-P87-ibm87n33'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n33.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n34.xml
+%% ID: ibm-not-wf-P87-ibm87n34.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n34'(suite) -> [];
+'ibm-not-wf-P87-ibm87n34'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n34.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n35.xml
+%% ID: ibm-not-wf-P87-ibm87n35.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n35'(suite) -> [];
+'ibm-not-wf-P87-ibm87n35'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n35.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n36.xml
+%% ID: ibm-not-wf-P87-ibm87n36.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n36'(suite) -> [];
+'ibm-not-wf-P87-ibm87n36'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n36.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n37.xml
+%% ID: ibm-not-wf-P87-ibm87n37.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n37'(suite) -> [];
+'ibm-not-wf-P87-ibm87n37'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n37.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n38.xml
+%% ID: ibm-not-wf-P87-ibm87n38.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n38'(suite) -> [];
+'ibm-not-wf-P87-ibm87n38'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n38.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n39.xml
+%% ID: ibm-not-wf-P87-ibm87n39.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n39'(suite) -> [];
+'ibm-not-wf-P87-ibm87n39'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n39.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n40.xml
+%% ID: ibm-not-wf-P87-ibm87n40.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n40'(suite) -> [];
+'ibm-not-wf-P87-ibm87n40'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n40.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n41.xml
+%% ID: ibm-not-wf-P87-ibm87n41.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n41'(suite) -> [];
+'ibm-not-wf-P87-ibm87n41'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n41.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n42.xml
+%% ID: ibm-not-wf-P87-ibm87n42.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n42'(suite) -> [];
+'ibm-not-wf-P87-ibm87n42'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n42.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n43.xml
+%% ID: ibm-not-wf-P87-ibm87n43.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n43'(suite) -> [];
+'ibm-not-wf-P87-ibm87n43'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n43.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n44.xml
+%% ID: ibm-not-wf-P87-ibm87n44.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n44'(suite) -> [];
+'ibm-not-wf-P87-ibm87n44'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n44.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n45.xml
+%% ID: ibm-not-wf-P87-ibm87n45.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n45'(suite) -> [];
+'ibm-not-wf-P87-ibm87n45'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n45.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n46.xml
+%% ID: ibm-not-wf-P87-ibm87n46.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n46'(suite) -> [];
+'ibm-not-wf-P87-ibm87n46'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n46.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n47.xml
+%% ID: ibm-not-wf-P87-ibm87n47.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n47'(suite) -> [];
+'ibm-not-wf-P87-ibm87n47'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n47.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n48.xml
+%% ID: ibm-not-wf-P87-ibm87n48.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n48'(suite) -> [];
+'ibm-not-wf-P87-ibm87n48'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n48.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n49.xml
+%% ID: ibm-not-wf-P87-ibm87n49.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n49'(suite) -> [];
+'ibm-not-wf-P87-ibm87n49'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n49.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n50.xml
+%% ID: ibm-not-wf-P87-ibm87n50.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n50'(suite) -> [];
+'ibm-not-wf-P87-ibm87n50'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n50.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n51.xml
+%% ID: ibm-not-wf-P87-ibm87n51.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n51'(suite) -> [];
+'ibm-not-wf-P87-ibm87n51'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n51.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n52.xml
+%% ID: ibm-not-wf-P87-ibm87n52.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n52'(suite) -> [];
+'ibm-not-wf-P87-ibm87n52'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n52.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n53.xml
+%% ID: ibm-not-wf-P87-ibm87n53.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n53'(suite) -> [];
+'ibm-not-wf-P87-ibm87n53'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n53.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n54.xml
+%% ID: ibm-not-wf-P87-ibm87n54.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n54'(suite) -> [];
+'ibm-not-wf-P87-ibm87n54'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n54.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n55.xml
+%% ID: ibm-not-wf-P87-ibm87n55.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n55'(suite) -> [];
+'ibm-not-wf-P87-ibm87n55'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n55.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n56.xml
+%% ID: ibm-not-wf-P87-ibm87n56.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n56'(suite) -> [];
+'ibm-not-wf-P87-ibm87n56'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n56.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n57.xml
+%% ID: ibm-not-wf-P87-ibm87n57.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n57'(suite) -> [];
+'ibm-not-wf-P87-ibm87n57'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n57.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n58.xml
+%% ID: ibm-not-wf-P87-ibm87n58.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n58'(suite) -> [];
+'ibm-not-wf-P87-ibm87n58'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n58.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n59.xml
+%% ID: ibm-not-wf-P87-ibm87n59.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n59'(suite) -> [];
+'ibm-not-wf-P87-ibm87n59'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n59.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n60.xml
+%% ID: ibm-not-wf-P87-ibm87n60.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n60'(suite) -> [];
+'ibm-not-wf-P87-ibm87n60'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n60.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n61.xml
+%% ID: ibm-not-wf-P87-ibm87n61.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n61'(suite) -> [];
+'ibm-not-wf-P87-ibm87n61'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n61.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n62.xml
+%% ID: ibm-not-wf-P87-ibm87n62.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n62'(suite) -> [];
+'ibm-not-wf-P87-ibm87n62'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n62.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n63.xml
+%% ID: ibm-not-wf-P87-ibm87n63.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n63'(suite) -> [];
+'ibm-not-wf-P87-ibm87n63'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n63.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n64.xml
+%% ID: ibm-not-wf-P87-ibm87n64.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n64'(suite) -> [];
+'ibm-not-wf-P87-ibm87n64'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n64.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n66.xml
+%% ID: ibm-not-wf-P87-ibm87n66.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n66'(suite) -> [];
+'ibm-not-wf-P87-ibm87n66'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n66.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n67.xml
+%% ID: ibm-not-wf-P87-ibm87n67.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n67'(suite) -> [];
+'ibm-not-wf-P87-ibm87n67'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n67.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n68.xml
+%% ID: ibm-not-wf-P87-ibm87n68.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n68'(suite) -> [];
+'ibm-not-wf-P87-ibm87n68'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n68.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n69.xml
+%% ID: ibm-not-wf-P87-ibm87n69.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n69'(suite) -> [];
+'ibm-not-wf-P87-ibm87n69'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n69.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n70.xml
+%% ID: ibm-not-wf-P87-ibm87n70.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n70'(suite) -> [];
+'ibm-not-wf-P87-ibm87n70'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n70.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n71.xml
+%% ID: ibm-not-wf-P87-ibm87n71.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n71'(suite) -> [];
+'ibm-not-wf-P87-ibm87n71'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n71.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n72.xml
+%% ID: ibm-not-wf-P87-ibm87n72.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n72'(suite) -> [];
+'ibm-not-wf-P87-ibm87n72'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n72.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n73.xml
+%% ID: ibm-not-wf-P87-ibm87n73.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n73'(suite) -> [];
+'ibm-not-wf-P87-ibm87n73'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n73.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n74.xml
+%% ID: ibm-not-wf-P87-ibm87n74.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n74'(suite) -> [];
+'ibm-not-wf-P87-ibm87n74'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n74.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n75.xml
+%% ID: ibm-not-wf-P87-ibm87n75.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n75'(suite) -> [];
+'ibm-not-wf-P87-ibm87n75'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n75.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n76.xml
+%% ID: ibm-not-wf-P87-ibm87n76.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n76'(suite) -> [];
+'ibm-not-wf-P87-ibm87n76'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n76.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n77.xml
+%% ID: ibm-not-wf-P87-ibm87n77.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n77'(suite) -> [];
+'ibm-not-wf-P87-ibm87n77'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n77.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n78.xml
+%% ID: ibm-not-wf-P87-ibm87n78.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n78'(suite) -> [];
+'ibm-not-wf-P87-ibm87n78'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n78.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n79.xml
+%% ID: ibm-not-wf-P87-ibm87n79.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n79'(suite) -> [];
+'ibm-not-wf-P87-ibm87n79'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n79.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n80.xml
+%% ID: ibm-not-wf-P87-ibm87n80.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n80'(suite) -> [];
+'ibm-not-wf-P87-ibm87n80'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n80.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n81.xml
+%% ID: ibm-not-wf-P87-ibm87n81.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n81'(suite) -> [];
+'ibm-not-wf-P87-ibm87n81'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n81.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n82.xml
+%% ID: ibm-not-wf-P87-ibm87n82.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n82'(suite) -> [];
+'ibm-not-wf-P87-ibm87n82'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n82.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n83.xml
+%% ID: ibm-not-wf-P87-ibm87n83.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n83'(suite) -> [];
+'ibm-not-wf-P87-ibm87n83'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n83.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n84.xml
+%% ID: ibm-not-wf-P87-ibm87n84.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n84'(suite) -> [];
+'ibm-not-wf-P87-ibm87n84'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n84.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P87/ibm87n85.xml
+%% ID: ibm-not-wf-P87-ibm87n85.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P87-ibm87n85'(suite) -> [];
+'ibm-not-wf-P87-ibm87n85'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P87/ibm87n85.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 87
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P88/ibm88n01.xml
+%% ID: ibm-not-wf-P88-ibm88n01.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P88-ibm88n01'(suite) -> [];
+'ibm-not-wf-P88-ibm88n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P88/ibm88n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P88/ibm88n02.xml
+%% ID: ibm-not-wf-P88-ibm88n02.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P88-ibm88n02'(suite) -> [];
+'ibm-not-wf-P88-ibm88n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P88/ibm88n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P88/ibm88n03.xml
+%% ID: ibm-not-wf-P88-ibm88n03.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P88-ibm88n03'(suite) -> [];
+'ibm-not-wf-P88-ibm88n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P88/ibm88n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P88/ibm88n04.xml
+%% ID: ibm-not-wf-P88-ibm88n04.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P88-ibm88n04'(suite) -> [];
+'ibm-not-wf-P88-ibm88n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P88/ibm88n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P88/ibm88n05.xml
+%% ID: ibm-not-wf-P88-ibm88n05.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P88-ibm88n05'(suite) -> [];
+'ibm-not-wf-P88-ibm88n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P88/ibm88n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P88/ibm88n06.xml
+%% ID: ibm-not-wf-P88-ibm88n06.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P88-ibm88n06'(suite) -> [];
+'ibm-not-wf-P88-ibm88n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P88/ibm88n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P88/ibm88n08.xml
+%% ID: ibm-not-wf-P88-ibm88n08.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P88-ibm88n08'(suite) -> [];
+'ibm-not-wf-P88-ibm88n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P88/ibm88n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P88/ibm88n09.xml
+%% ID: ibm-not-wf-P88-ibm88n09.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P88-ibm88n09'(suite) -> [];
+'ibm-not-wf-P88-ibm88n09'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P88/ibm88n09.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P88/ibm88n10.xml
+%% ID: ibm-not-wf-P88-ibm88n10.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P88-ibm88n10'(suite) -> [];
+'ibm-not-wf-P88-ibm88n10'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P88/ibm88n10.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P88/ibm88n11.xml
+%% ID: ibm-not-wf-P88-ibm88n11.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P88-ibm88n11'(suite) -> [];
+'ibm-not-wf-P88-ibm88n11'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P88/ibm88n11.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P88/ibm88n12.xml
+%% ID: ibm-not-wf-P88-ibm88n12.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P88-ibm88n12'(suite) -> [];
+'ibm-not-wf-P88-ibm88n12'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P88/ibm88n12.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P88/ibm88n13.xml
+%% ID: ibm-not-wf-P88-ibm88n13.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P88-ibm88n13'(suite) -> [];
+'ibm-not-wf-P88-ibm88n13'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P88/ibm88n13.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P88/ibm88n14.xml
+%% ID: ibm-not-wf-P88-ibm88n14.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P88-ibm88n14'(suite) -> [];
+'ibm-not-wf-P88-ibm88n14'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P88/ibm88n14.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P88/ibm88n15.xml
+%% ID: ibm-not-wf-P88-ibm88n15.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P88-ibm88n15'(suite) -> [];
+'ibm-not-wf-P88-ibm88n15'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P88/ibm88n15.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P88/ibm88n16.xml
+%% ID: ibm-not-wf-P88-ibm88n16.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P88-ibm88n16'(suite) -> [];
+'ibm-not-wf-P88-ibm88n16'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P88/ibm88n16.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 88
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P89/ibm89n01.xml
+%% ID: ibm-not-wf-P89-ibm89n01.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P89-ibm89n01'(suite) -> [];
+'ibm-not-wf-P89-ibm89n01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P89/ibm89n01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P89/ibm89n02.xml
+%% ID: ibm-not-wf-P89-ibm89n02.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P89-ibm89n02'(suite) -> [];
+'ibm-not-wf-P89-ibm89n02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P89/ibm89n02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P89/ibm89n03.xml
+%% ID: ibm-not-wf-P89-ibm89n03.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P89-ibm89n03'(suite) -> [];
+'ibm-not-wf-P89-ibm89n03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P89/ibm89n03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P89/ibm89n04.xml
+%% ID: ibm-not-wf-P89-ibm89n04.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P89-ibm89n04'(suite) -> [];
+'ibm-not-wf-P89-ibm89n04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P89/ibm89n04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P89/ibm89n05.xml
+%% ID: ibm-not-wf-P89-ibm89n05.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P89-ibm89n05'(suite) -> [];
+'ibm-not-wf-P89-ibm89n05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P89/ibm89n05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P89/ibm89n06.xml
+%% ID: ibm-not-wf-P89-ibm89n06.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P89-ibm89n06'(suite) -> [];
+'ibm-not-wf-P89-ibm89n06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P89/ibm89n06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P89/ibm89n07.xml
+%% ID: ibm-not-wf-P89-ibm89n07.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P89-ibm89n07'(suite) -> [];
+'ibm-not-wf-P89-ibm89n07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P89/ibm89n07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P89/ibm89n08.xml
+%% ID: ibm-not-wf-P89-ibm89n08.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P89-ibm89n08'(suite) -> [];
+'ibm-not-wf-P89-ibm89n08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P89/ibm89n08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P89/ibm89n09.xml
+%% ID: ibm-not-wf-P89-ibm89n09.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P89-ibm89n09'(suite) -> [];
+'ibm-not-wf-P89-ibm89n09'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P89/ibm89n09.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P89/ibm89n10.xml
+%% ID: ibm-not-wf-P89-ibm89n10.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P89-ibm89n10'(suite) -> [];
+'ibm-not-wf-P89-ibm89n10'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P89/ibm89n10.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P89/ibm89n11.xml
+%% ID: ibm-not-wf-P89-ibm89n11.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P89-ibm89n11'(suite) -> [];
+'ibm-not-wf-P89-ibm89n11'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P89/ibm89n11.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: not-wf/P89/ibm89n12.xml
+%% ID: ibm-not-wf-P89-ibm89n12.xml
+%% Type: not-wf
+%% Sections: B.
+'ibm-not-wf-P89-ibm89n12'(suite) -> [];
+'ibm-not-wf-P89-ibm89n12'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","not-wf/P89/ibm89n12.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "not-wf").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 89
+
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - not-wf tests
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P01/ibm01v01.xml
+%% ID: ibm-valid-P01-ibm01v01.xml
+%% Type: valid
+%% Sections: 2.1
+'ibm-valid-P01-ibm01v01'(suite) -> [];
+'ibm-valid-P01-ibm01v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P01/ibm01v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 1
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P02/ibm02v01.xml
+%% ID: ibm-valid-P02-ibm02v01.xml
+%% Type: valid
+%% Sections: 2.2
+'ibm-valid-P02-ibm02v01'(suite) -> [];
+'ibm-valid-P02-ibm02v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P02/ibm02v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 2
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P03/ibm03v01.xml
+%% ID: ibm-valid-P03-ibm03v01.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P03-ibm03v01'(suite) -> [];
+'ibm-valid-P03-ibm03v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P03/ibm03v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 3
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P09/ibm09v01.xml
+%% ID: ibm-valid-P09-ibm09v01.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P09-ibm09v01'(suite) -> [];
+'ibm-valid-P09-ibm09v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P09/ibm09v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P09/ibm09v02.xml
+%% ID: ibm-valid-P09-ibm09v02.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P09-ibm09v02'(suite) -> [];
+'ibm-valid-P09-ibm09v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P09/ibm09v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P09/ibm09v03.xml
+%% ID: ibm-valid-P09-ibm09v03.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P09-ibm09v03'(suite) -> [];
+'ibm-valid-P09-ibm09v03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P09/ibm09v03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P09/ibm09v04.xml
+%% ID: ibm-valid-P09-ibm09v04.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P09-ibm09v04'(suite) -> [];
+'ibm-valid-P09-ibm09v04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P09/ibm09v04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P09/ibm09v05.xml
+%% ID: ibm-valid-P09-ibm09v05.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P09-ibm09v05'(suite) -> [];
+'ibm-valid-P09-ibm09v05'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P09/ibm09v05.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 9
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P10/ibm10v01.xml
+%% ID: ibm-valid-P10-ibm10v01.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P10-ibm10v01'(suite) -> [];
+'ibm-valid-P10-ibm10v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P10/ibm10v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P10/ibm10v02.xml
+%% ID: ibm-valid-P10-ibm10v02.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P10-ibm10v02'(suite) -> [];
+'ibm-valid-P10-ibm10v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P10/ibm10v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P10/ibm10v03.xml
+%% ID: ibm-valid-P10-ibm10v03.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P10-ibm10v03'(suite) -> [];
+'ibm-valid-P10-ibm10v03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P10/ibm10v03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P10/ibm10v04.xml
+%% ID: ibm-valid-P10-ibm10v04.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P10-ibm10v04'(suite) -> [];
+'ibm-valid-P10-ibm10v04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P10/ibm10v04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P10/ibm10v05.xml
+%% ID: ibm-valid-P10-ibm10v05.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P10-ibm10v05'(suite) -> [];
+'ibm-valid-P10-ibm10v05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P10/ibm10v05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P10/ibm10v06.xml
+%% ID: ibm-valid-P10-ibm10v06.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P10-ibm10v06'(suite) -> [];
+'ibm-valid-P10-ibm10v06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P10/ibm10v06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P10/ibm10v07.xml
+%% ID: ibm-valid-P10-ibm10v07.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P10-ibm10v07'(suite) -> [];
+'ibm-valid-P10-ibm10v07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P10/ibm10v07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P10/ibm10v08.xml
+%% ID: ibm-valid-P10-ibm10v08.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P10-ibm10v08'(suite) -> [];
+'ibm-valid-P10-ibm10v08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P10/ibm10v08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 10
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P11/ibm11v01.xml
+%% ID: ibm-valid-P11-ibm11v01.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P11-ibm11v01'(suite) -> [];
+'ibm-valid-P11-ibm11v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P11/ibm11v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P11/ibm11v02.xml
+%% ID: ibm-valid-P11-ibm11v02.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P11-ibm11v02'(suite) -> [];
+'ibm-valid-P11-ibm11v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P11/ibm11v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P11/ibm11v03.xml
+%% ID: ibm-valid-P11-ibm11v03.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P11-ibm11v03'(suite) -> [];
+'ibm-valid-P11-ibm11v03'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P11/ibm11v03.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P11/ibm11v04.xml
+%% ID: ibm-valid-P11-ibm11v04.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P11-ibm11v04'(suite) -> [];
+'ibm-valid-P11-ibm11v04'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P11/ibm11v04.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 11
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P12/ibm12v01.xml
+%% ID: ibm-valid-P12-ibm12v01.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P12-ibm12v01'(suite) -> [];
+'ibm-valid-P12-ibm12v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P12/ibm12v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P12/ibm12v02.xml
+%% ID: ibm-valid-P12-ibm12v02.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P12-ibm12v02'(suite) -> [];
+'ibm-valid-P12-ibm12v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P12/ibm12v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P12/ibm12v03.xml
+%% ID: ibm-valid-P12-ibm12v03.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P12-ibm12v03'(suite) -> [];
+'ibm-valid-P12-ibm12v03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P12/ibm12v03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P12/ibm12v04.xml
+%% ID: ibm-valid-P12-ibm12v04.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P12-ibm12v04'(suite) -> [];
+'ibm-valid-P12-ibm12v04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P12/ibm12v04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 12
+
+testcases111(suite) -> [].
+%% ['ibm-valid-P12-ibm12v01','ibm-valid-P12-ibm12v02','ibm-valid-P12-ibm12v03','ibm-valid-P12-ibm12v04'].
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P13/ibm13v01.xml
+%% ID: ibm-valid-P13-ibm13v01.xml
+%% Type: valid
+%% Sections: 2.3
+'ibm-valid-P13-ibm13v01'(suite) -> [];
+'ibm-valid-P13-ibm13v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P13/ibm13v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 13
+
+testcases112(suite) -> [].
+%% ['ibm-valid-P13-ibm13v01'].
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P14/ibm14v01.xml
+%% ID: ibm-valid-P14-ibm14v01.xml
+%% Type: valid
+%% Sections: 2.4
+'ibm-valid-P14-ibm14v01'(suite) -> [];
+'ibm-valid-P14-ibm14v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P14/ibm14v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P14/ibm14v02.xml
+%% ID: ibm-valid-P14-ibm14v02.xml
+%% Type: valid
+%% Sections: 2.4
+'ibm-valid-P14-ibm14v02'(suite) -> [];
+'ibm-valid-P14-ibm14v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P14/ibm14v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P14/ibm14v03.xml
+%% ID: ibm-valid-P14-ibm14v03.xml
+%% Type: valid
+%% Sections: 2.4
+'ibm-valid-P14-ibm14v03'(suite) -> [];
+'ibm-valid-P14-ibm14v03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P14/ibm14v03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 14
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P15/ibm15v01.xml
+%% ID: ibm-valid-P15-ibm15v01.xml
+%% Type: valid
+%% Sections: 2.5
+'ibm-valid-P15-ibm15v01'(suite) -> [];
+'ibm-valid-P15-ibm15v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P15/ibm15v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P15/ibm15v02.xml
+%% ID: ibm-valid-P15-ibm15v02.xml
+%% Type: valid
+%% Sections: 2.5
+'ibm-valid-P15-ibm15v02'(suite) -> [];
+'ibm-valid-P15-ibm15v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P15/ibm15v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P15/ibm15v03.xml
+%% ID: ibm-valid-P15-ibm15v03.xml
+%% Type: valid
+%% Sections: 2.5
+'ibm-valid-P15-ibm15v03'(suite) -> [];
+'ibm-valid-P15-ibm15v03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P15/ibm15v03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P15/ibm15v04.xml
+%% ID: ibm-valid-P15-ibm15v04.xml
+%% Type: valid
+%% Sections: 2.5
+'ibm-valid-P15-ibm15v04'(suite) -> [];
+'ibm-valid-P15-ibm15v04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P15/ibm15v04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 15
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P16/ibm16v01.xml
+%% ID: ibm-valid-P16-ibm16v01.xml
+%% Type: valid
+%% Sections: 2.6
+'ibm-valid-P16-ibm16v01'(suite) -> [];
+'ibm-valid-P16-ibm16v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P16/ibm16v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P16/ibm16v02.xml
+%% ID: ibm-valid-P16-ibm16v02.xml
+%% Type: valid
+%% Sections: 2.6
+'ibm-valid-P16-ibm16v02'(suite) -> [];
+'ibm-valid-P16-ibm16v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P16/ibm16v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P16/ibm16v03.xml
+%% ID: ibm-valid-P16-ibm16v03.xml
+%% Type: valid
+%% Sections: 2.6
+'ibm-valid-P16-ibm16v03'(suite) -> [];
+'ibm-valid-P16-ibm16v03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P16/ibm16v03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 16
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P17/ibm17v01.xml
+%% ID: ibm-valid-P17-ibm17v01.xml
+%% Type: valid
+%% Sections: 2.6
+'ibm-valid-P17-ibm17v01'(suite) -> [];
+'ibm-valid-P17-ibm17v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P17/ibm17v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 17
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P18/ibm18v01.xml
+%% ID: ibm-valid-P18-ibm18v01.xml
+%% Type: valid
+%% Sections: 2.7
+'ibm-valid-P18-ibm18v01'(suite) -> [];
+'ibm-valid-P18-ibm18v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P18/ibm18v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 18
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P19/ibm19v01.xml
+%% ID: ibm-valid-P19-ibm19v01.xml
+%% Type: valid
+%% Sections: 2.7
+'ibm-valid-P19-ibm19v01'(suite) -> [];
+'ibm-valid-P19-ibm19v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P19/ibm19v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 19
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P20/ibm20v01.xml
+%% ID: ibm-valid-P20-ibm20v01.xml
+%% Type: valid
+%% Sections: 2.7
+'ibm-valid-P20-ibm20v01'(suite) -> [];
+'ibm-valid-P20-ibm20v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P20/ibm20v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P20/ibm20v02.xml
+%% ID: ibm-valid-P20-ibm20v02.xml
+%% Type: valid
+%% Sections: 2.7
+'ibm-valid-P20-ibm20v02'(suite) -> [];
+'ibm-valid-P20-ibm20v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P20/ibm20v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 20
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P21/ibm21v01.xml
+%% ID: ibm-valid-P21-ibm21v01.xml
+%% Type: valid
+%% Sections: 2.7
+'ibm-valid-P21-ibm21v01'(suite) -> [];
+'ibm-valid-P21-ibm21v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P21/ibm21v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 21
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P22/ibm22v01.xml
+%% ID: ibm-valid-P22-ibm22v01.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P22-ibm22v01'(suite) -> [];
+'ibm-valid-P22-ibm22v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P22/ibm22v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P22/ibm22v02.xml
+%% ID: ibm-valid-P22-ibm22v02.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P22-ibm22v02'(suite) -> [];
+'ibm-valid-P22-ibm22v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P22/ibm22v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P22/ibm22v03.xml
+%% ID: ibm-valid-P22-ibm22v03.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P22-ibm22v03'(suite) -> [];
+'ibm-valid-P22-ibm22v03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P22/ibm22v03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P22/ibm22v04.xml
+%% ID: ibm-valid-P22-ibm22v04.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P22-ibm22v04'(suite) -> [];
+'ibm-valid-P22-ibm22v04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P22/ibm22v04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P22/ibm22v05.xml
+%% ID: ibm-valid-P22-ibm22v05.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P22-ibm22v05'(suite) -> [];
+'ibm-valid-P22-ibm22v05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P22/ibm22v05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P22/ibm22v06.xml
+%% ID: ibm-valid-P22-ibm22v06.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P22-ibm22v06'(suite) -> [];
+'ibm-valid-P22-ibm22v06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P22/ibm22v06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P22/ibm22v07.xml
+%% ID: ibm-valid-P22-ibm22v07.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P22-ibm22v07'(suite) -> [];
+'ibm-valid-P22-ibm22v07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P22/ibm22v07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 22
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P23/ibm23v01.xml
+%% ID: ibm-valid-P23-ibm23v01.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P23-ibm23v01'(suite) -> [];
+'ibm-valid-P23-ibm23v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P23/ibm23v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P23/ibm23v02.xml
+%% ID: ibm-valid-P23-ibm23v02.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P23-ibm23v02'(suite) -> [];
+'ibm-valid-P23-ibm23v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P23/ibm23v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P23/ibm23v03.xml
+%% ID: ibm-valid-P23-ibm23v03.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P23-ibm23v03'(suite) -> [];
+'ibm-valid-P23-ibm23v03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P23/ibm23v03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P23/ibm23v04.xml
+%% ID: ibm-valid-P23-ibm23v04.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P23-ibm23v04'(suite) -> [];
+'ibm-valid-P23-ibm23v04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P23/ibm23v04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P23/ibm23v05.xml
+%% ID: ibm-valid-P23-ibm23v05.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P23-ibm23v05'(suite) -> [];
+'ibm-valid-P23-ibm23v05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P23/ibm23v05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P23/ibm23v06.xml
+%% ID: ibm-valid-P23-ibm23v06.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P23-ibm23v06'(suite) -> [];
+'ibm-valid-P23-ibm23v06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P23/ibm23v06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 23
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P24/ibm24v01.xml
+%% ID: ibm-valid-P24-ibm24v01.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P24-ibm24v01'(suite) -> [];
+'ibm-valid-P24-ibm24v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P24/ibm24v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P24/ibm24v02.xml
+%% ID: ibm-valid-P24-ibm24v02.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P24-ibm24v02'(suite) -> [];
+'ibm-valid-P24-ibm24v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P24/ibm24v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 24
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P25/ibm25v01.xml
+%% ID: ibm-valid-P25-ibm25v01.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P25-ibm25v01'(suite) -> [];
+'ibm-valid-P25-ibm25v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P25/ibm25v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P25/ibm25v02.xml
+%% ID: ibm-valid-P25-ibm25v02.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P25-ibm25v02'(suite) -> [];
+'ibm-valid-P25-ibm25v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P25/ibm25v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P25/ibm25v03.xml
+%% ID: ibm-valid-P25-ibm25v03.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P25-ibm25v03'(suite) -> [];
+'ibm-valid-P25-ibm25v03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P25/ibm25v03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P25/ibm25v04.xml
+%% ID: ibm-valid-P25-ibm25v04.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P25-ibm25v04'(suite) -> [];
+'ibm-valid-P25-ibm25v04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P25/ibm25v04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 25
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P26/ibm26v01.xml
+%% ID: ibm-valid-P26-ibm26v01.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P26-ibm26v01'(suite) -> [];
+'ibm-valid-P26-ibm26v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P26/ibm26v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 26
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P27/ibm27v01.xml
+%% ID: ibm-valid-P27-ibm27v01.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P27-ibm27v01'(suite) -> [];
+'ibm-valid-P27-ibm27v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P27/ibm27v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P27/ibm27v02.xml
+%% ID: ibm-valid-P27-ibm27v02.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P27-ibm27v02'(suite) -> [];
+'ibm-valid-P27-ibm27v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P27/ibm27v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P27/ibm27v03.xml
+%% ID: ibm-valid-P27-ibm27v03.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P27-ibm27v03'(suite) -> [];
+'ibm-valid-P27-ibm27v03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P27/ibm27v03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 27
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P28/ibm28v01.xml
+%% ID: ibm-valid-P28-ibm28v01.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P28-ibm28v01'(suite) -> [];
+'ibm-valid-P28-ibm28v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P28/ibm28v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P28/ibm28v02.xml
+%% ID: ibm-valid-P28-ibm28v02.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P28-ibm28v02'(suite) -> [];
+'ibm-valid-P28-ibm28v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P28/ibm28v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 28
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P29/ibm29v01.xml
+%% ID: ibm-valid-P29-ibm29v01.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P29-ibm29v01'(suite) -> [];
+'ibm-valid-P29-ibm29v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P29/ibm29v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P29/ibm29v02.xml
+%% ID: ibm-valid-P29-ibm29v02.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P29-ibm29v02'(suite) -> [];
+'ibm-valid-P29-ibm29v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P29/ibm29v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 29
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P30/ibm30v01.xml
+%% ID: ibm-valid-P30-ibm30v01.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P30-ibm30v01'(suite) -> [];
+'ibm-valid-P30-ibm30v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P30/ibm30v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P30/ibm30v02.xml
+%% ID: ibm-valid-P30-ibm30v02.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P30-ibm30v02'(suite) -> [];
+'ibm-valid-P30-ibm30v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P30/ibm30v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 30
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P31/ibm31v01.xml
+%% ID: ibm-valid-P31-ibm31v01.xml
+%% Type: valid
+%% Sections: 2.8
+'ibm-valid-P31-ibm31v01'(suite) -> [];
+'ibm-valid-P31-ibm31v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P31/ibm31v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 31
+
+testcases130(suite) -> [].
+%% ['ibm-valid-P31-ibm31v01'].
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P32/ibm32v01.xml
+%% ID: ibm-valid-P32-ibm32v01.xml
+%% Type: valid
+%% Sections: 2.9
+'ibm-valid-P32-ibm32v01'(suite) -> [];
+'ibm-valid-P32-ibm32v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P32/ibm32v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P32/ibm32v02.xml
+%% ID: ibm-valid-P32-ibm32v02.xml
+%% Type: valid
+%% Sections: 2.9
+'ibm-valid-P32-ibm32v02'(suite) -> [];
+'ibm-valid-P32-ibm32v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P32/ibm32v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P32/ibm32v03.xml
+%% ID: ibm-valid-P32-ibm32v03.xml
+%% Type: valid
+%% Sections: 2.9
+'ibm-valid-P32-ibm32v03'(suite) -> [];
+'ibm-valid-P32-ibm32v03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P32/ibm32v03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P32/ibm32v04.xml
+%% ID: ibm-valid-P32-ibm32v04.xml
+%% Type: valid
+%% Sections: 2.9
+'ibm-valid-P32-ibm32v04'(suite) -> [];
+'ibm-valid-P32-ibm32v04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P32/ibm32v04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 32
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P33/ibm33v01.xml
+%% ID: ibm-valid-P33-ibm33v01.xml
+%% Type: valid
+%% Sections: 2.12
+'ibm-valid-P33-ibm33v01'(suite) -> [];
+'ibm-valid-P33-ibm33v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P33/ibm33v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 33
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P34/ibm34v01.xml
+%% ID: ibm-valid-P34-ibm34v01.xml
+%% Type: valid
+%% Sections: 2.12
+'ibm-valid-P34-ibm34v01'(suite) -> [];
+'ibm-valid-P34-ibm34v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P34/ibm34v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 34
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P35/ibm35v01.xml
+%% ID: ibm-valid-P35-ibm35v01.xml
+%% Type: valid
+%% Sections: 2.12
+'ibm-valid-P35-ibm35v01'(suite) -> [];
+'ibm-valid-P35-ibm35v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P35/ibm35v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 35
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P36/ibm36v01.xml
+%% ID: ibm-valid-P36-ibm36v01.xml
+%% Type: valid
+%% Sections: 2.12
+'ibm-valid-P36-ibm36v01'(suite) -> [];
+'ibm-valid-P36-ibm36v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P36/ibm36v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 36
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P37/ibm37v01.xml
+%% ID: ibm-valid-P37-ibm37v01.xml
+%% Type: valid
+%% Sections: 2.12
+'ibm-valid-P37-ibm37v01'(suite) -> [];
+'ibm-valid-P37-ibm37v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P37/ibm37v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 37
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P38/ibm38v01.xml
+%% ID: ibm-valid-P38-ibm38v01.xml
+%% Type: valid
+%% Sections: 2.12
+'ibm-valid-P38-ibm38v01'(suite) -> [];
+'ibm-valid-P38-ibm38v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P38/ibm38v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 38
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P39/ibm39v01.xml
+%% ID: ibm-valid-P39-ibm39v01.xml
+%% Type: valid
+%% Sections: 3
+'ibm-valid-P39-ibm39v01'(suite) -> [];
+'ibm-valid-P39-ibm39v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P39/ibm39v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 39
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P40/ibm40v01.xml
+%% ID: ibm-valid-P40-ibm40v01.xml
+%% Type: valid
+%% Sections: 3.1
+'ibm-valid-P40-ibm40v01'(suite) -> [];
+'ibm-valid-P40-ibm40v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P40/ibm40v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 40
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P41/ibm41v01.xml
+%% ID: ibm-valid-P41-ibm41v01.xml
+%% Type: valid
+%% Sections: 3.1
+'ibm-valid-P41-ibm41v01'(suite) -> [];
+'ibm-valid-P41-ibm41v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P41/ibm41v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 41
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P42/ibm42v01.xml
+%% ID: ibm-valid-P42-ibm42v01.xml
+%% Type: valid
+%% Sections: 3.1
+'ibm-valid-P42-ibm42v01'(suite) -> [];
+'ibm-valid-P42-ibm42v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P42/ibm42v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 42
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P43/ibm43v01.xml
+%% ID: ibm-valid-P43-ibm43v01.xml
+%% Type: valid
+%% Sections: 3.1
+'ibm-valid-P43-ibm43v01'(suite) -> [];
+'ibm-valid-P43-ibm43v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P43/ibm43v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 43
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P44/ibm44v01.xml
+%% ID: ibm-valid-P44-ibm44v01.xml
+%% Type: valid
+%% Sections: 3.1
+'ibm-valid-P44-ibm44v01'(suite) -> [];
+'ibm-valid-P44-ibm44v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P44/ibm44v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 44
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P45/ibm45v01.xml
+%% ID: ibm-valid-P45-ibm45v01.xml
+%% Type: valid
+%% Sections: 3.2
+'ibm-valid-P45-ibm45v01'(suite) -> [];
+'ibm-valid-P45-ibm45v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P45/ibm45v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 45
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P47/ibm47v01.xml
+%% ID: ibm-valid-P47-ibm47v01.xml
+%% Type: valid
+%% Sections: 3.2.1
+'ibm-valid-P47-ibm47v01'(suite) -> [];
+'ibm-valid-P47-ibm47v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P47/ibm47v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 47
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P49/ibm49v01.xml
+%% ID: ibm-valid-P49-ibm49v01.xml
+%% Type: valid
+%% Sections: 3.2.1
+'ibm-valid-P49-ibm49v01'(suite) -> [];
+'ibm-valid-P49-ibm49v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P49/ibm49v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 49
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P50/ibm50v01.xml
+%% ID: ibm-valid-P50-ibm50v01.xml
+%% Type: valid
+%% Sections: 3.2.1
+'ibm-valid-P50-ibm50v01'(suite) -> [];
+'ibm-valid-P50-ibm50v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P50/ibm50v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 50
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P51/ibm51v01.xml
+%% ID: ibm-valid-P51-ibm51v01.xml
+%% Type: valid
+%% Sections: 3.2.2
+'ibm-valid-P51-ibm51v01'(suite) -> [];
+'ibm-valid-P51-ibm51v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P51/ibm51v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P51/ibm51v02.xml
+%% ID: ibm-valid-P51-ibm51v02.xml
+%% Type: valid
+%% Sections: 3.2.2
+'ibm-valid-P51-ibm51v02'(suite) -> [];
+'ibm-valid-P51-ibm51v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P51/ibm51v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 51
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P52/ibm52v01.xml
+%% ID: ibm-valid-P52-ibm52v01.xml
+%% Type: valid
+%% Sections: 3.3
+'ibm-valid-P52-ibm52v01'(suite) -> [];
+'ibm-valid-P52-ibm52v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P52/ibm52v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 52
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P54/ibm54v01.xml
+%% ID: ibm-valid-P54-ibm54v01.xml
+%% Type: valid
+%% Sections: 3.3.1
+'ibm-valid-P54-ibm54v01'(suite) -> [];
+'ibm-valid-P54-ibm54v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P54/ibm54v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P54/ibm54v02.xml
+%% ID: ibm-valid-P54-ibm54v02.xml
+%% Type: valid
+%% Sections: 3.3.1
+'ibm-valid-P54-ibm54v02'(suite) -> [];
+'ibm-valid-P54-ibm54v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P54/ibm54v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P54/ibm54v03.xml
+%% ID: ibm-valid-P54-ibm54v03.xml
+%% Type: valid
+%% Sections: 3.3.1
+'ibm-valid-P54-ibm54v03'(suite) -> [];
+'ibm-valid-P54-ibm54v03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P54/ibm54v03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 54
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P55/ibm55v01.xml
+%% ID: ibm-valid-P55-ibm55v01.xml
+%% Type: valid
+%% Sections: 3.3.1
+'ibm-valid-P55-ibm55v01'(suite) -> [];
+'ibm-valid-P55-ibm55v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P55/ibm55v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 55
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P56/ibm56v01.xml
+%% ID: ibm-valid-P56-ibm56v01.xml
+%% Type: valid
+%% Sections: 3.3.1
+'ibm-valid-P56-ibm56v01'(suite) -> [];
+'ibm-valid-P56-ibm56v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P56/ibm56v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P56/ibm56v02.xml
+%% ID: ibm-valid-P56-ibm56v02.xml
+%% Type: valid
+%% Sections: 3.3.1
+'ibm-valid-P56-ibm56v02'(suite) -> [];
+'ibm-valid-P56-ibm56v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P56/ibm56v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P56/ibm56v03.xml
+%% ID: ibm-valid-P56-ibm56v03.xml
+%% Type: valid
+%% Sections: 3.3.1
+'ibm-valid-P56-ibm56v03'(suite) -> [];
+'ibm-valid-P56-ibm56v03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P56/ibm56v03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P56/ibm56v04.xml
+%% ID: ibm-valid-P56-ibm56v04.xml
+%% Type: valid
+%% Sections: 3.3.1
+'ibm-valid-P56-ibm56v04'(suite) -> [];
+'ibm-valid-P56-ibm56v04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P56/ibm56v04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P56/ibm56v05.xml
+%% ID: ibm-valid-P56-ibm56v05.xml
+%% Type: valid
+%% Sections: 3.3.1
+'ibm-valid-P56-ibm56v05'(suite) -> [];
+'ibm-valid-P56-ibm56v05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P56/ibm56v05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P56/ibm56v06.xml
+%% ID: ibm-valid-P56-ibm56v06.xml
+%% Type: valid
+%% Sections: 3.3.1
+'ibm-valid-P56-ibm56v06'(suite) -> [];
+'ibm-valid-P56-ibm56v06'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P56/ibm56v06.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P56/ibm56v07.xml
+%% ID: ibm-valid-P56-ibm56v07.xml
+%% Type: valid
+%% Sections: 3.3.1
+'ibm-valid-P56-ibm56v07'(suite) -> [];
+'ibm-valid-P56-ibm56v07'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P56/ibm56v07.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P56/ibm56v08.xml
+%% ID: ibm-valid-P56-ibm56v08.xml
+%% Type: valid
+%% Sections: 3.3.1
+'ibm-valid-P56-ibm56v08'(suite) -> [];
+'ibm-valid-P56-ibm56v08'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P56/ibm56v08.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P56/ibm56v09.xml
+%% ID: ibm-valid-P56-ibm56v09.xml
+%% Type: valid
+%% Sections: 3.3.1
+'ibm-valid-P56-ibm56v09'(suite) -> [];
+'ibm-valid-P56-ibm56v09'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P56/ibm56v09.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P56/ibm56v10.xml
+%% ID: ibm-valid-P56-ibm56v10.xml
+%% Type: valid
+%% Sections: 3.3.1
+'ibm-valid-P56-ibm56v10'(suite) -> [];
+'ibm-valid-P56-ibm56v10'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P56/ibm56v10.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 56
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P57/ibm57v01.xml
+%% ID: ibm-valid-P57-ibm57v01.xml
+%% Type: valid
+%% Sections: 3.3.1
+'ibm-valid-P57-ibm57v01'(suite) -> [];
+'ibm-valid-P57-ibm57v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P57/ibm57v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 57
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P58/ibm58v01.xml
+%% ID: ibm-valid-P58-ibm58v01.xml
+%% Type: valid
+%% Sections: 3.3.1
+'ibm-valid-P58-ibm58v01'(suite) -> [];
+'ibm-valid-P58-ibm58v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P58/ibm58v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P58/ibm58v02.xml
+%% ID: ibm-valid-P58-ibm58v02.xml
+%% Type: valid
+%% Sections: 3.3.1
+'ibm-valid-P58-ibm58v02'(suite) -> [];
+'ibm-valid-P58-ibm58v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P58/ibm58v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 58
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P59/ibm59v01.xml
+%% ID: ibm-valid-P59-ibm59v01.xml
+%% Type: valid
+%% Sections: 3.3.1
+'ibm-valid-P59-ibm59v01'(suite) -> [];
+'ibm-valid-P59-ibm59v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P59/ibm59v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P59/ibm59v02.xml
+%% ID: ibm-valid-P59-ibm59v02.xml
+%% Type: valid
+%% Sections: 3.3.1
+'ibm-valid-P59-ibm59v02'(suite) -> [];
+'ibm-valid-P59-ibm59v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P59/ibm59v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 59
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P60/ibm60v01.xml
+%% ID: ibm-valid-P60-ibm60v01.xml
+%% Type: valid
+%% Sections: 3.3.2
+'ibm-valid-P60-ibm60v01'(suite) -> [];
+'ibm-valid-P60-ibm60v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P60/ibm60v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P60/ibm60v02.xml
+%% ID: ibm-valid-P60-ibm60v02.xml
+%% Type: valid
+%% Sections: 3.3.2
+'ibm-valid-P60-ibm60v02'(suite) -> [];
+'ibm-valid-P60-ibm60v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P60/ibm60v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P60/ibm60v03.xml
+%% ID: ibm-valid-P60-ibm60v03.xml
+%% Type: valid
+%% Sections: 3.3.2
+'ibm-valid-P60-ibm60v03'(suite) -> [];
+'ibm-valid-P60-ibm60v03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P60/ibm60v03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P60/ibm60v04.xml
+%% ID: ibm-valid-P60-ibm60v04.xml
+%% Type: valid
+%% Sections: 3.3.2
+'ibm-valid-P60-ibm60v04'(suite) -> [];
+'ibm-valid-P60-ibm60v04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P60/ibm60v04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 60
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P61/ibm61v01.xml
+%% ID: ibm-valid-P61-ibm61v01.xml
+%% Type: valid
+%% Sections: 3.4
+'ibm-valid-P61-ibm61v01'(suite) -> [];
+'ibm-valid-P61-ibm61v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P61/ibm61v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P61/ibm61v02.xml
+%% ID: ibm-valid-P61-ibm61v02.xml
+%% Type: valid
+%% Sections: 3.4
+'ibm-valid-P61-ibm61v02'(suite) -> [];
+'ibm-valid-P61-ibm61v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P61/ibm61v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 61
+
+testcases157(suite) -> [].
+%% ['ibm-valid-P61-ibm61v01','ibm-valid-P61-ibm61v02'].
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P62/ibm62v01.xml
+%% ID: ibm-valid-P62-ibm62v01.xml
+%% Type: valid
+%% Sections: 3.4
+'ibm-valid-P62-ibm62v01'(suite) -> [];
+'ibm-valid-P62-ibm62v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P62/ibm62v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P62/ibm62v02.xml
+%% ID: ibm-valid-P62-ibm62v02.xml
+%% Type: valid
+%% Sections: 3.4
+'ibm-valid-P62-ibm62v02'(suite) -> [];
+'ibm-valid-P62-ibm62v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P62/ibm62v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P62/ibm62v03.xml
+%% ID: ibm-valid-P62-ibm62v03.xml
+%% Type: valid
+%% Sections: 3.4
+'ibm-valid-P62-ibm62v03'(suite) -> [];
+'ibm-valid-P62-ibm62v03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P62/ibm62v03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P62/ibm62v04.xml
+%% ID: ibm-valid-P62-ibm62v04.xml
+%% Type: valid
+%% Sections: 3.4
+'ibm-valid-P62-ibm62v04'(suite) -> [];
+'ibm-valid-P62-ibm62v04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P62/ibm62v04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P62/ibm62v05.xml
+%% ID: ibm-valid-P62-ibm62v05.xml
+%% Type: valid
+%% Sections: 3.4
+'ibm-valid-P62-ibm62v05'(suite) -> [];
+'ibm-valid-P62-ibm62v05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P62/ibm62v05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 62
+
+testcases158(suite) -> [].
+%% ['ibm-valid-P62-ibm62v01','ibm-valid-P62-ibm62v02','ibm-valid-P62-ibm62v03','ibm-valid-P62-ibm62v04','ibm-valid-P62-ibm62v05'].
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P63/ibm63v01.xml
+%% ID: ibm-valid-P63-ibm63v01.xml
+%% Type: valid
+%% Sections: 3.4
+'ibm-valid-P63-ibm63v01'(suite) -> [];
+'ibm-valid-P63-ibm63v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P63/ibm63v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P63/ibm63v02.xml
+%% ID: ibm-valid-P63-ibm63v02.xml
+%% Type: valid
+%% Sections: 3.4
+'ibm-valid-P63-ibm63v02'(suite) -> [];
+'ibm-valid-P63-ibm63v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P63/ibm63v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P63/ibm63v03.xml
+%% ID: ibm-valid-P63-ibm63v03.xml
+%% Type: valid
+%% Sections: 3.4
+'ibm-valid-P63-ibm63v03'(suite) -> [];
+'ibm-valid-P63-ibm63v03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P63/ibm63v03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P63/ibm63v04.xml
+%% ID: ibm-valid-P63-ibm63v04.xml
+%% Type: valid
+%% Sections: 3.4
+'ibm-valid-P63-ibm63v04'(suite) -> [];
+'ibm-valid-P63-ibm63v04'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P63/ibm63v04.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P63/ibm63v05.xml
+%% ID: ibm-valid-P63-ibm63v05.xml
+%% Type: valid
+%% Sections: 3.4
+'ibm-valid-P63-ibm63v05'(suite) -> [];
+'ibm-valid-P63-ibm63v05'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P63/ibm63v05.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 63
+
+testcases159(suite) -> [].
+%% ['ibm-valid-P63-ibm63v01','ibm-valid-P63-ibm63v02','ibm-valid-P63-ibm63v03','ibm-valid-P63-ibm63v04','ibm-valid-P63-ibm63v05'].
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P64/ibm64v01.xml
+%% ID: ibm-valid-P64-ibm64v01.xml
+%% Type: valid
+%% Sections: 3.4
+'ibm-valid-P64-ibm64v01'(suite) -> [];
+'ibm-valid-P64-ibm64v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P64/ibm64v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P64/ibm64v02.xml
+%% ID: ibm-valid-P64-ibm64v02.xml
+%% Type: valid
+%% Sections: 3.4
+'ibm-valid-P64-ibm64v02'(suite) -> [];
+'ibm-valid-P64-ibm64v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P64/ibm64v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P64/ibm64v03.xml
+%% ID: ibm-valid-P64-ibm64v03.xml
+%% Type: valid
+%% Sections: 3.4
+'ibm-valid-P64-ibm64v03'(suite) -> [];
+'ibm-valid-P64-ibm64v03'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P64/ibm64v03.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 64
+
+testcases160(suite) -> [].
+%% ['ibm-valid-P64-ibm64v01','ibm-valid-P64-ibm64v02','ibm-valid-P64-ibm64v03'].
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P65/ibm65v01.xml
+%% ID: ibm-valid-P65-ibm65v01.xml
+%% Type: valid
+%% Sections: 3.4
+'ibm-valid-P65-ibm65v01'(suite) -> [];
+'ibm-valid-P65-ibm65v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P65/ibm65v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P65/ibm65v02.xml
+%% ID: ibm-valid-P65-ibm65v02.xml
+%% Type: valid
+%% Sections: 3.4
+'ibm-valid-P65-ibm65v02'(suite) -> [];
+'ibm-valid-P65-ibm65v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P65/ibm65v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 65
+
+testcases161(suite) -> [].
+%% ['ibm-valid-P65-ibm65v01','ibm-valid-P65-ibm65v02'].
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P66/ibm66v01.xml
+%% ID: ibm-valid-P66-ibm66v01.xml
+%% Type: valid
+%% Sections: 4.1
+'ibm-valid-P66-ibm66v01'(suite) -> [];
+'ibm-valid-P66-ibm66v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P66/ibm66v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 66
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P67/ibm67v01.xml
+%% ID: ibm-valid-P67-ibm67v01.xml
+%% Type: valid
+%% Sections: 4.1
+'ibm-valid-P67-ibm67v01'(suite) -> [];
+'ibm-valid-P67-ibm67v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P67/ibm67v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 67
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P68/ibm68v01.xml
+%% ID: ibm-valid-P68-ibm68v01.xml
+%% Type: valid
+%% Sections: 4.1
+'ibm-valid-P68-ibm68v01'(suite) -> [];
+'ibm-valid-P68-ibm68v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P68/ibm68v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P68/ibm68v02.xml
+%% ID: ibm-valid-P68-ibm68v02.xml
+%% Type: valid
+%% Sections: 4.1
+'ibm-valid-P68-ibm68v02'(suite) -> [];
+'ibm-valid-P68-ibm68v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P68/ibm68v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 68
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P69/ibm69v01.xml
+%% ID: ibm-valid-P69-ibm69v01.xml
+%% Type: valid
+%% Sections: 4.1
+'ibm-valid-P69-ibm69v01'(suite) -> [];
+'ibm-valid-P69-ibm69v01'(_Config) -> {skip, "NYI"}.
+%% ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+%% ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P69/ibm69v01.xml"]),
+%% ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+%% ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P69/ibm69v02.xml
+%% ID: ibm-valid-P69-ibm69v02.xml
+%% Type: valid
+%% Sections: 4.1
+'ibm-valid-P69-ibm69v02'(suite) -> [];
+'ibm-valid-P69-ibm69v02'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P69/ibm69v02.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 69
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P70/ibm70v01.xml
+%% ID: ibm-valid-P70-ibm70v01.xml
+%% Type: valid
+%% Sections: 4.2
+'ibm-valid-P70-ibm70v01'(suite) -> [];
+'ibm-valid-P70-ibm70v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P70/ibm70v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 70
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P78/ibm78v01.xml
+%% ID: ibm-valid-P78-ibm78v01.xml
+%% Type: valid
+%% Sections: 4.3.2
+'ibm-valid-P78-ibm78v01'(suite) -> [];
+'ibm-valid-P78-ibm78v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P78/ibm78v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 78
+
+testcases167(suite) -> [].
+%% ['ibm-valid-P78-ibm78v01'].
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P79/ibm79v01.xml
+%% ID: ibm-valid-P79-ibm79v01.xml
+%% Type: valid
+%% Sections: 4.3.2
+'ibm-valid-P79-ibm79v01'(suite) -> [];
+'ibm-valid-P79-ibm79v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P79/ibm79v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 79
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P82/ibm82v01.xml
+%% ID: ibm-valid-P82-ibm82v01.xml
+%% Type: valid
+%% Sections: 4.7
+'ibm-valid-P82-ibm82v01'(suite) -> [];
+'ibm-valid-P82-ibm82v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P82/ibm82v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 82
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P85/ibm85v01.xml
+%% ID: ibm-valid-P85-ibm85v01.xml
+%% Type: valid
+%% Sections: B.
+'ibm-valid-P85-ibm85v01'(suite) -> [];
+'ibm-valid-P85-ibm85v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P85/ibm85v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 85
+
+testcases170(suite) -> [].
+%% ['ibm-valid-P85-ibm85v01'].
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P86/ibm86v01.xml
+%% ID: ibm-valid-P86-ibm86v01.xml
+%% Type: valid
+%% Sections: B.
+'ibm-valid-P86-ibm86v01'(suite) -> [];
+'ibm-valid-P86-ibm86v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P86/ibm86v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 86
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P87/ibm87v01.xml
+%% ID: ibm-valid-P87-ibm87v01.xml
+%% Type: valid
+%% Sections: B.
+'ibm-valid-P87-ibm87v01'(suite) -> [];
+'ibm-valid-P87-ibm87v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P87/ibm87v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 87
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P88/ibm88v01.xml
+%% ID: ibm-valid-P88-ibm88v01.xml
+%% Type: valid
+%% Sections: B.
+'ibm-valid-P88-ibm88v01'(suite) -> [];
+'ibm-valid-P88-ibm88v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P88/ibm88v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 88
+
+
+%%----------------------------------------------------------------------
+%% Test Case
+%% Uri: valid/P89/ibm89v01.xml
+%% ID: ibm-valid-P89-ibm89v01.xml
+%% Type: valid
+%% Sections: B.
+'ibm-valid-P89-ibm89v01'(suite) -> [];
+'ibm-valid-P89-ibm89v01'(Config) ->
+ ?line file:set_cwd(xmerl_test_lib:get_data_dir(Config)),
+ ?line Path = filename:join([xmerl_test_lib:get_data_dir(Config),"ibm","valid/P89/ibm89v01.xml"]),
+ ?line R = xmerl_sax_parser:file(Path, [{event_fun, fun(_,_,S) -> S end}]),
+ ?line check_result(R, "valid").
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - Production 89
+
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML Conformance Test Suite - valid tests
+
+
+%%----------------------------------------------------------------------
+%% Test Cases
+%% Profile: IBM XML 1.0 Tests
+
+
+%%----------------------------------------------------------------------
+%% Test Suite
+%% Profile: XML 1.0 (2nd edition) W3C Conformance Test Suite, 6 October 2000
+
+all() ->
+ [{group, testcases1}, {group, testcases3},
+ {group, testcases5}, {group, testcases6},
+ {group, testcases8}].
+
+groups() ->
+ [{testcases2, [],
+ ['not-wf-sa-001', 'not-wf-sa-002', 'not-wf-sa-003',
+ 'not-wf-sa-004', 'not-wf-sa-005', 'not-wf-sa-006',
+ 'not-wf-sa-007', 'not-wf-sa-008', 'not-wf-sa-009',
+ 'not-wf-sa-010', 'not-wf-sa-011', 'not-wf-sa-012',
+ 'not-wf-sa-013', 'not-wf-sa-014', 'not-wf-sa-015',
+ 'not-wf-sa-016', 'not-wf-sa-017', 'not-wf-sa-018',
+ 'not-wf-sa-019', 'not-wf-sa-020', 'not-wf-sa-021',
+ 'not-wf-sa-022', 'not-wf-sa-023', 'not-wf-sa-024',
+ 'not-wf-sa-025', 'not-wf-sa-026', 'not-wf-sa-027',
+ 'not-wf-sa-028', 'not-wf-sa-029', 'not-wf-sa-030',
+ 'not-wf-sa-031', 'not-wf-sa-032', 'not-wf-sa-033',
+ 'not-wf-sa-034', 'not-wf-sa-035', 'not-wf-sa-036',
+ 'not-wf-sa-037', 'not-wf-sa-038', 'not-wf-sa-039',
+ 'not-wf-sa-040', 'not-wf-sa-041', 'not-wf-sa-042',
+ 'not-wf-sa-043', 'not-wf-sa-044', 'not-wf-sa-045',
+ 'not-wf-sa-046', 'not-wf-sa-047', 'not-wf-sa-048',
+ 'not-wf-sa-049', 'not-wf-sa-050', 'not-wf-sa-051',
+ 'not-wf-sa-052', 'not-wf-sa-053', 'not-wf-sa-054',
+ 'not-wf-sa-055', 'not-wf-sa-056', 'not-wf-sa-057',
+ 'not-wf-sa-058', 'not-wf-sa-059', 'not-wf-sa-060',
+ 'not-wf-sa-061', 'not-wf-sa-062', 'not-wf-sa-063',
+ 'not-wf-sa-064', 'not-wf-sa-065', 'not-wf-sa-066',
+ 'not-wf-sa-067', 'not-wf-sa-068', 'not-wf-sa-069',
+ 'not-wf-sa-070', 'not-wf-sa-071', 'not-wf-sa-072',
+ 'not-wf-sa-073', 'not-wf-sa-074', 'not-wf-sa-075',
+ 'not-wf-sa-076', 'not-wf-sa-077', 'not-wf-sa-078',
+ 'not-wf-sa-079', 'not-wf-sa-080', 'not-wf-sa-081',
+ 'not-wf-sa-082', 'not-wf-sa-083', 'not-wf-sa-084',
+ 'not-wf-sa-085', 'not-wf-sa-086', 'not-wf-sa-087',
+ 'not-wf-sa-088', 'not-wf-sa-089', 'not-wf-sa-090',
+ 'not-wf-sa-091', 'not-wf-sa-092', 'not-wf-sa-093',
+ 'not-wf-sa-094', 'not-wf-sa-095', 'not-wf-sa-096',
+ 'not-wf-sa-097', 'not-wf-sa-098', 'not-wf-sa-099',
+ 'not-wf-sa-100', 'not-wf-sa-101', 'not-wf-sa-102',
+ 'not-wf-sa-103', 'not-wf-sa-104', 'not-wf-sa-105',
+ 'not-wf-sa-106', 'not-wf-sa-107', 'not-wf-sa-108',
+ 'not-wf-sa-109', 'not-wf-sa-110', 'not-wf-sa-111',
+ 'not-wf-sa-112', 'not-wf-sa-113', 'not-wf-sa-114',
+ 'not-wf-sa-115', 'not-wf-sa-116', 'not-wf-sa-117',
+ 'not-wf-sa-118', 'not-wf-sa-119', 'not-wf-sa-120',
+ 'not-wf-sa-121', 'not-wf-sa-122', 'not-wf-sa-123',
+ 'not-wf-sa-124', 'not-wf-sa-125', 'not-wf-sa-126',
+ 'not-wf-sa-127', 'not-wf-sa-128', 'not-wf-sa-129',
+ 'not-wf-sa-130', 'not-wf-sa-131', 'not-wf-sa-132',
+ 'not-wf-sa-133', 'not-wf-sa-134', 'not-wf-sa-135',
+ 'not-wf-sa-136', 'not-wf-sa-137', 'not-wf-sa-138',
+ 'not-wf-sa-139', 'not-wf-sa-140', 'not-wf-sa-141',
+ 'not-wf-sa-142', 'not-wf-sa-143', 'not-wf-sa-144',
+ 'not-wf-sa-145', 'not-wf-sa-146', 'not-wf-sa-147',
+ 'not-wf-sa-148', 'not-wf-sa-149', 'not-wf-sa-150',
+ 'not-wf-sa-151', 'not-wf-sa-152', 'not-wf-sa-153',
+ 'not-wf-sa-154', 'not-wf-sa-155', 'not-wf-sa-156',
+ 'not-wf-sa-157', 'not-wf-sa-158', 'not-wf-sa-159',
+ 'not-wf-sa-160', 'not-wf-sa-161', 'not-wf-sa-162',
+ 'not-wf-sa-163', 'not-wf-sa-164', 'not-wf-sa-165',
+ 'not-wf-sa-166', 'not-wf-sa-167', 'not-wf-sa-168',
+ 'not-wf-sa-169', 'not-wf-sa-170', 'not-wf-sa-171',
+ 'not-wf-sa-172', 'not-wf-sa-173', 'not-wf-sa-174',
+ 'not-wf-sa-175', 'not-wf-sa-176', 'not-wf-sa-177',
+ 'not-wf-sa-178', 'not-wf-sa-179', 'not-wf-sa-180',
+ 'not-wf-sa-181', 'not-wf-sa-182', 'not-wf-sa-183',
+ 'not-wf-sa-184', 'not-wf-sa-185', 'not-wf-sa-186',
+ 'not-wf-not-sa-001', 'not-wf-not-sa-002',
+ 'not-wf-not-sa-003', 'not-wf-not-sa-004',
+ 'not-wf-not-sa-005', 'not-wf-not-sa-006',
+ 'not-wf-not-sa-007', 'not-wf-not-sa-008',
+ 'not-wf-not-sa-009', 'not-wf-ext-sa-001',
+ 'not-wf-ext-sa-002', 'not-wf-ext-sa-003',
+ 'invalid--002', 'invalid--005', 'invalid--006',
+ 'invalid-not-sa-022', 'valid-sa-001', 'valid-sa-002',
+ 'valid-sa-003', 'valid-sa-004', 'valid-sa-005',
+ 'valid-sa-006', 'valid-sa-007', 'valid-sa-008',
+ 'valid-sa-009', 'valid-sa-010', 'valid-sa-011',
+ 'valid-sa-012', 'valid-sa-013', 'valid-sa-014',
+ 'valid-sa-015', 'valid-sa-016', 'valid-sa-017',
+ 'valid-sa-018', 'valid-sa-019', 'valid-sa-020',
+ 'valid-sa-021', 'valid-sa-022', 'valid-sa-023',
+ 'valid-sa-024', 'valid-sa-025', 'valid-sa-026',
+ 'valid-sa-027', 'valid-sa-028', 'valid-sa-029',
+ 'valid-sa-030', 'valid-sa-031', 'valid-sa-032',
+ 'valid-sa-033', 'valid-sa-034', 'valid-sa-035',
+ 'valid-sa-036', 'valid-sa-037', 'valid-sa-038',
+ 'valid-sa-039', 'valid-sa-040', 'valid-sa-041',
+ 'valid-sa-042', 'valid-sa-043', 'valid-sa-044',
+ 'valid-sa-045', 'valid-sa-046', 'valid-sa-047',
+ 'valid-sa-048', 'valid-sa-049', 'valid-sa-050',
+ 'valid-sa-051', 'valid-sa-052', 'valid-sa-053',
+ 'valid-sa-054', 'valid-sa-055', 'valid-sa-056',
+ 'valid-sa-057', 'valid-sa-058', 'valid-sa-059',
+ 'valid-sa-060', 'valid-sa-061', 'valid-sa-062',
+ 'valid-sa-063', 'valid-sa-064', 'valid-sa-065',
+ 'valid-sa-066', 'valid-sa-067', 'valid-sa-068',
+ 'valid-sa-069', 'valid-sa-070', 'valid-sa-071',
+ 'valid-sa-072', 'valid-sa-073', 'valid-sa-074',
+ 'valid-sa-075', 'valid-sa-076', 'valid-sa-077',
+ 'valid-sa-078', 'valid-sa-079', 'valid-sa-080',
+ 'valid-sa-081', 'valid-sa-082', 'valid-sa-083',
+ 'valid-sa-084', 'valid-sa-085', 'valid-sa-086',
+ 'valid-sa-087', 'valid-sa-088', 'valid-sa-089',
+ 'valid-sa-090', 'valid-sa-091', 'valid-sa-092',
+ 'valid-sa-093', 'valid-sa-094', 'valid-sa-095',
+ 'valid-sa-096', 'valid-sa-097', 'valid-sa-098',
+ 'valid-sa-099', 'valid-sa-100', 'valid-sa-101',
+ 'valid-sa-102', 'valid-sa-103', 'valid-sa-104',
+ 'valid-sa-105', 'valid-sa-106', 'valid-sa-107',
+ 'valid-sa-108', 'valid-sa-109', 'valid-sa-110',
+ 'valid-sa-111', 'valid-sa-112', 'valid-sa-113',
+ 'valid-sa-114', 'valid-sa-115', 'valid-sa-116',
+ 'valid-sa-117', 'valid-sa-118', 'valid-sa-119',
+ 'valid-not-sa-001', 'valid-not-sa-002',
+ 'valid-not-sa-003', 'valid-not-sa-004',
+ 'valid-not-sa-005', 'valid-not-sa-006',
+ 'valid-not-sa-007', 'valid-not-sa-008',
+ 'valid-not-sa-009', 'valid-not-sa-010',
+ 'valid-not-sa-011', 'valid-not-sa-012',
+ 'valid-not-sa-013', 'valid-not-sa-014',
+ 'valid-not-sa-015', 'valid-not-sa-016',
+ 'valid-not-sa-017', 'valid-not-sa-018',
+ 'valid-not-sa-019', 'valid-not-sa-020',
+ 'valid-not-sa-021', 'valid-not-sa-023',
+ 'valid-not-sa-024', 'valid-not-sa-025',
+ 'valid-not-sa-026', 'valid-not-sa-027',
+ 'valid-not-sa-028', 'valid-not-sa-029',
+ 'valid-not-sa-030', 'valid-not-sa-031',
+ 'valid-ext-sa-001', 'valid-ext-sa-002',
+ 'valid-ext-sa-003', 'valid-ext-sa-004',
+ 'valid-ext-sa-005', 'valid-ext-sa-006',
+ 'valid-ext-sa-007', 'valid-ext-sa-008',
+ 'valid-ext-sa-009', 'valid-ext-sa-011',
+ 'valid-ext-sa-012', 'valid-ext-sa-013',
+ 'valid-ext-sa-014']},
+ {testcases1, [], [{group, testcases2}]},
+ {testcases4, [],
+ ['pr-xml-euc-jp', 'pr-xml-iso-2022-jp', 'pr-xml-little',
+ 'pr-xml-shift_jis', 'pr-xml-utf-16', 'pr-xml-utf-8',
+ 'weekly-euc-jp', 'weekly-iso-2022-jp', 'weekly-little',
+ 'weekly-shift_jis', 'weekly-utf-16', 'weekly-utf-8']},
+ {testcases3, [], [{group, testcases4}]},
+ {testcases5, [],
+ [pe01, dtd00, dtd01, element, ext01, ext02, 'not-sa01',
+ 'not-sa02', 'not-sa03', 'not-sa04', notation01,
+ optional, required00, sa01, sa02, sa03, sa04, sa05,
+ 'v-sgml01', 'v-lang01', 'v-lang02', 'v-lang03',
+ 'v-lang04', 'v-lang05', 'v-lang06', 'v-pe00', 'v-pe03',
+ 'v-pe02', 'inv-dtd01', 'inv-dtd02', 'inv-dtd03', el01,
+ el02, el03, el04, el05, el06, id01, id02, id03, id04,
+ id05, id06, id07, id08, id09, 'inv-not-sa01',
+ 'inv-not-sa02', 'inv-not-sa04', 'inv-not-sa05',
+ 'inv-not-sa06', 'inv-not-sa07', 'inv-not-sa08',
+ 'inv-not-sa09', 'inv-not-sa10', 'inv-not-sa11',
+ 'inv-not-sa12', 'inv-not-sa13', 'inv-not-sa14',
+ optional01, optional02, optional03, optional04,
+ optional05, optional06, optional07, optional08,
+ optional09, optional10, optional11, optional12,
+ optional13, optional14, optional20, optional21,
+ optional22, optional23, optional24, optional25,
+ 'inv-required00', 'inv-required01', 'inv-required02',
+ root, attr01, attr02, attr03, attr04, attr05, attr06,
+ attr07, attr08, attr09, attr10, attr11, attr12, attr13,
+ attr14, attr15, attr16, utf16b, utf16l, empty,
+ 'not-wf-sa03', attlist01, attlist02, attlist03,
+ attlist04, attlist05, attlist06, attlist07, attlist08,
+ attlist09, attlist10, attlist11, cond01, cond02,
+ content01, content02, content03, decl01, 'nwf-dtd00',
+ 'nwf-dtd01', dtd02, dtd03, dtd04, dtd05, dtd07,
+ element00, element01, element02, element03, element04,
+ encoding01, encoding02, encoding03, encoding04,
+ encoding05, encoding06, encoding07, pi, pubid01,
+ pubid02, pubid03, pubid04, pubid05, sgml01, sgml02,
+ sgml03, sgml04, sgml05, sgml06, sgml07, sgml08, sgml09,
+ sgml10, sgml11, sgml12, sgml13, uri01]},
+ {testcases7, [],
+ ['o-p01pass2', 'o-p06pass1', 'o-p07pass1', 'o-p08pass1',
+ 'o-p09pass1', 'o-p12pass1', 'o-p22pass4', 'o-p22pass5',
+ 'o-p22pass6', 'o-p28pass1', 'o-p28pass3', 'o-p28pass4',
+ 'o-p28pass5', 'o-p29pass1', 'o-p30pass1', 'o-p30pass2',
+ 'o-p31pass1', 'o-p31pass2', 'o-p43pass1', 'o-p45pass1',
+ 'o-p46pass1', 'o-p47pass1', 'o-p48pass1', 'o-p49pass1',
+ 'o-p50pass1', 'o-p51pass1', 'o-p52pass1', 'o-p53pass1',
+ 'o-p54pass1', 'o-p55pass1', 'o-p56pass1', 'o-p57pass1',
+ 'o-p58pass1', 'o-p59pass1', 'o-p60pass1', 'o-p61pass1',
+ 'o-p62pass1', 'o-p63pass1', 'o-p64pass1', 'o-p68pass1',
+ 'o-p69pass1', 'o-p70pass1', 'o-p71pass1', 'o-p72pass1',
+ 'o-p73pass1', 'o-p76pass1', 'o-p01pass1', 'o-p01pass3',
+ 'o-p03pass1', 'o-p04pass1', 'o-p05pass1', 'o-p06fail1',
+ 'o-p08fail1', 'o-p08fail2', 'o-p10pass1', 'o-p14pass1',
+ 'o-p15pass1', 'o-p16pass1', 'o-p16pass2', 'o-p16pass3',
+ 'o-p18pass1', 'o-p22pass1', 'o-p22pass2', 'o-p22pass3',
+ 'o-p23pass1', 'o-p23pass2', 'o-p23pass3', 'o-p23pass4',
+ 'o-p24pass1', 'o-p24pass2', 'o-p24pass3', 'o-p24pass4',
+ 'o-p25pass1', 'o-p25pass2', 'o-p26pass1', 'o-p27pass1',
+ 'o-p27pass2', 'o-p27pass3', 'o-p27pass4', 'o-p32pass1',
+ 'o-p32pass2', 'o-p39pass1', 'o-p39pass2', 'o-p40pass1',
+ 'o-p40pass2', 'o-p40pass3', 'o-p40pass4', 'o-p41pass1',
+ 'o-p41pass2', 'o-p42pass1', 'o-p42pass2', 'o-p44pass1',
+ 'o-p44pass2', 'o-p44pass3', 'o-p44pass4', 'o-p44pass5',
+ 'o-p66pass1', 'o-p74pass1', 'o-p75pass1', 'o-e2',
+ 'o-p01fail1', 'o-p01fail2', 'o-p01fail3', 'o-p01fail4',
+ 'o-p02fail1', 'o-p02fail10', 'o-p02fail11',
+ 'o-p02fail12', 'o-p02fail13', 'o-p02fail14',
+ 'o-p02fail15', 'o-p02fail16', 'o-p02fail17',
+ 'o-p02fail18', 'o-p02fail19', 'o-p02fail2',
+ 'o-p02fail20', 'o-p02fail21', 'o-p02fail22',
+ 'o-p02fail23', 'o-p02fail24', 'o-p02fail25',
+ 'o-p02fail26', 'o-p02fail27', 'o-p02fail28',
+ 'o-p02fail29', 'o-p02fail3', 'o-p02fail30',
+ 'o-p02fail31', 'o-p02fail4', 'o-p02fail5', 'o-p02fail6',
+ 'o-p02fail7', 'o-p02fail8', 'o-p02fail9', 'o-p03fail1',
+ 'o-p03fail10', 'o-p03fail11', 'o-p03fail12',
+ 'o-p03fail13', 'o-p03fail14', 'o-p03fail15',
+ 'o-p03fail16', 'o-p03fail17', 'o-p03fail18',
+ 'o-p03fail19', 'o-p03fail2', 'o-p03fail20',
+ 'o-p03fail21', 'o-p03fail22', 'o-p03fail23',
+ 'o-p03fail24', 'o-p03fail25', 'o-p03fail26',
+ 'o-p03fail27', 'o-p03fail28', 'o-p03fail29',
+ 'o-p03fail3', 'o-p03fail4', 'o-p03fail5', 'o-p03fail7',
+ 'o-p03fail8', 'o-p03fail9', 'o-p04fail1', 'o-p04fail2',
+ 'o-p04fail3', 'o-p05fail1', 'o-p05fail2', 'o-p05fail3',
+ 'o-p05fail4', 'o-p05fail5', 'o-p09fail1', 'o-p09fail2',
+ 'o-p09fail3', 'o-p09fail4', 'o-p09fail5', 'o-p10fail1',
+ 'o-p10fail2', 'o-p10fail3', 'o-p11fail1', 'o-p11fail2',
+ 'o-p12fail1', 'o-p12fail2', 'o-p12fail3', 'o-p12fail4',
+ 'o-p12fail5', 'o-p12fail6', 'o-p12fail7', 'o-p14fail1',
+ 'o-p14fail2', 'o-p14fail3', 'o-p15fail1', 'o-p15fail2',
+ 'o-p15fail3', 'o-p16fail1', 'o-p16fail2', 'o-p16fail3',
+ 'o-p18fail1', 'o-p18fail2', 'o-p18fail3', 'o-p22fail1',
+ 'o-p22fail2', 'o-p23fail1', 'o-p23fail2', 'o-p23fail3',
+ 'o-p23fail4', 'o-p23fail5', 'o-p24fail1', 'o-p24fail2',
+ 'o-p25fail1', 'o-p26fail1', 'o-p26fail2', 'o-p27fail1',
+ 'o-p28fail1', 'o-p29fail1', 'o-p30fail1', 'o-p31fail1',
+ 'o-p32fail1', 'o-p32fail2', 'o-p32fail3', 'o-p32fail4',
+ 'o-p32fail5', 'o-p39fail1', 'o-p39fail2', 'o-p39fail3',
+ 'o-p39fail4', 'o-p39fail5', 'o-p40fail1', 'o-p40fail2',
+ 'o-p40fail3', 'o-p40fail4', 'o-p41fail1', 'o-p41fail2',
+ 'o-p41fail3', 'o-p42fail1', 'o-p42fail2', 'o-p42fail3',
+ 'o-p43fail1', 'o-p43fail2', 'o-p43fail3', 'o-p44fail1',
+ 'o-p44fail2', 'o-p44fail3', 'o-p44fail4', 'o-p44fail5',
+ 'o-p45fail1', 'o-p45fail2', 'o-p45fail3', 'o-p45fail4',
+ 'o-p46fail1', 'o-p46fail2', 'o-p46fail3', 'o-p46fail4',
+ 'o-p46fail5', 'o-p46fail6', 'o-p47fail1', 'o-p47fail2',
+ 'o-p47fail3', 'o-p47fail4', 'o-p48fail1', 'o-p48fail2',
+ 'o-p49fail1', 'o-p50fail1', 'o-p51fail1', 'o-p51fail2',
+ 'o-p51fail3', 'o-p51fail4', 'o-p51fail5', 'o-p51fail6',
+ 'o-p51fail7', 'o-p52fail1', 'o-p52fail2', 'o-p53fail1',
+ 'o-p53fail2', 'o-p53fail3', 'o-p53fail4', 'o-p53fail5',
+ 'o-p54fail1', 'o-p55fail1', 'o-p56fail1', 'o-p56fail2',
+ 'o-p56fail3', 'o-p56fail4', 'o-p56fail5', 'o-p57fail1',
+ 'o-p58fail1', 'o-p58fail2', 'o-p58fail3', 'o-p58fail4',
+ 'o-p58fail5', 'o-p58fail6', 'o-p58fail7', 'o-p58fail8',
+ 'o-p59fail1', 'o-p59fail2', 'o-p59fail3', 'o-p60fail1',
+ 'o-p60fail2', 'o-p60fail3', 'o-p60fail4', 'o-p60fail5',
+ 'o-p61fail1', 'o-p62fail1', 'o-p62fail2', 'o-p63fail1',
+ 'o-p63fail2', 'o-p64fail1', 'o-p64fail2', 'o-p66fail1',
+ 'o-p66fail2', 'o-p66fail3', 'o-p66fail4', 'o-p66fail5',
+ 'o-p66fail6', 'o-p68fail1', 'o-p68fail2', 'o-p68fail3',
+ 'o-p69fail1', 'o-p69fail2', 'o-p69fail3', 'o-p70fail1',
+ 'o-p71fail1', 'o-p71fail2', 'o-p71fail3', 'o-p71fail4',
+ 'o-p72fail1', 'o-p72fail2', 'o-p72fail3', 'o-p72fail4',
+ 'o-p73fail1', 'o-p73fail2', 'o-p73fail3', 'o-p73fail4',
+ 'o-p73fail5', 'o-p74fail1', 'o-p74fail2', 'o-p74fail3',
+ 'o-p75fail1', 'o-p75fail2', 'o-p75fail3', 'o-p75fail4',
+ 'o-p75fail5', 'o-p75fail6', 'o-p76fail1', 'o-p76fail2',
+ 'o-p76fail3', 'o-p76fail4', 'o-p11pass1']},
+ {testcases6, [], [{group, testcases7}]},
+ {testcases10, [], ['ibm-invalid-P28-ibm28i01']},
+ {testcases11, [],
+ ['ibm-invalid-P32-ibm32i01', 'ibm-invalid-P32-ibm32i03',
+ 'ibm-invalid-P32-ibm32i04']},
+ {testcases12, [],
+ ['ibm-invalid-P39-ibm39i01', 'ibm-invalid-P39-ibm39i02',
+ 'ibm-invalid-P39-ibm39i03',
+ 'ibm-invalid-P39-ibm39i04']},
+ {testcases13, [],
+ ['ibm-invalid-P41-ibm41i01',
+ 'ibm-invalid-P41-ibm41i02']},
+ {testcases14, [], ['ibm-invalid-P45-ibm45i01']},
+ {testcases15, [], ['ibm-invalid-P49-ibm49i01']},
+ {testcases16, [], ['ibm-invalid-P50-ibm50i01']},
+ {testcases17, [],
+ ['ibm-invalid-P51-ibm51i01',
+ 'ibm-invalid-P51-ibm51i03']},
+ {testcases18, [],
+ ['ibm-invalid-P56-ibm56i01', 'ibm-invalid-P56-ibm56i02',
+ 'ibm-invalid-P56-ibm56i03', 'ibm-invalid-P56-ibm56i05',
+ 'ibm-invalid-P56-ibm56i06', 'ibm-invalid-P56-ibm56i07',
+ 'ibm-invalid-P56-ibm56i08', 'ibm-invalid-P56-ibm56i09',
+ 'ibm-invalid-P56-ibm56i10', 'ibm-invalid-P56-ibm56i11',
+ 'ibm-invalid-P56-ibm56i12', 'ibm-invalid-P56-ibm56i13',
+ 'ibm-invalid-P56-ibm56i14', 'ibm-invalid-P56-ibm56i15',
+ 'ibm-invalid-P56-ibm56i16', 'ibm-invalid-P56-ibm56i17',
+ 'ibm-invalid-P56-ibm56i18']},
+ {testcases19, [],
+ ['ibm-invalid-P58-ibm58i01',
+ 'ibm-invalid-P58-ibm58i02']},
+ {testcases20, [], ['ibm-invalid-P59-ibm59i01']},
+ {testcases21, [],
+ ['ibm-invalid-P60-ibm60i01', 'ibm-invalid-P60-ibm60i02',
+ 'ibm-invalid-P60-ibm60i03',
+ 'ibm-invalid-P60-ibm60i04']},
+ {testcases22, [],
+ ['ibm-invalid-P68-ibm68i01', 'ibm-invalid-P68-ibm68i02',
+ 'ibm-invalid-P68-ibm68i03',
+ 'ibm-invalid-P68-ibm68i04']},
+ {testcases23, [],
+ ['ibm-invalid-P69-ibm69i01', 'ibm-invalid-P69-ibm69i02',
+ 'ibm-invalid-P69-ibm69i03',
+ 'ibm-invalid-P69-ibm69i04']},
+ {testcases24, [], ['ibm-invalid-P76-ibm76i01']},
+ {testcases9, [],
+ [{group, testcases10}, {group, testcases11},
+ {group, testcases12}, {group, testcases13},
+ {group, testcases14}, {group, testcases15},
+ {group, testcases16}, {group, testcases17},
+ {group, testcases18}, {group, testcases19},
+ {group, testcases20}, {group, testcases21},
+ {group, testcases22}, {group, testcases23},
+ {group, testcases24}]},
+ {testcases26, [],
+ ['ibm-not-wf-P01-ibm01n01', 'ibm-not-wf-P01-ibm01n02',
+ 'ibm-not-wf-P01-ibm01n03']},
+ {testcases27, [],
+ ['ibm-not-wf-P02-ibm02n01', 'ibm-not-wf-P02-ibm02n02',
+ 'ibm-not-wf-P02-ibm02n03', 'ibm-not-wf-P02-ibm02n04',
+ 'ibm-not-wf-P02-ibm02n05', 'ibm-not-wf-P02-ibm02n06',
+ 'ibm-not-wf-P02-ibm02n07', 'ibm-not-wf-P02-ibm02n08',
+ 'ibm-not-wf-P02-ibm02n09', 'ibm-not-wf-P02-ibm02n10',
+ 'ibm-not-wf-P02-ibm02n11', 'ibm-not-wf-P02-ibm02n12',
+ 'ibm-not-wf-P02-ibm02n13', 'ibm-not-wf-P02-ibm02n14',
+ 'ibm-not-wf-P02-ibm02n15', 'ibm-not-wf-P02-ibm02n16',
+ 'ibm-not-wf-P02-ibm02n17', 'ibm-not-wf-P02-ibm02n18',
+ 'ibm-not-wf-P02-ibm02n19', 'ibm-not-wf-P02-ibm02n20',
+ 'ibm-not-wf-P02-ibm02n21', 'ibm-not-wf-P02-ibm02n22',
+ 'ibm-not-wf-P02-ibm02n23', 'ibm-not-wf-P02-ibm02n24',
+ 'ibm-not-wf-P02-ibm02n25', 'ibm-not-wf-P02-ibm02n26',
+ 'ibm-not-wf-P02-ibm02n27', 'ibm-not-wf-P02-ibm02n28',
+ 'ibm-not-wf-P02-ibm02n29', 'ibm-not-wf-P02-ibm02n30',
+ 'ibm-not-wf-P02-ibm02n31', 'ibm-not-wf-P02-ibm02n32',
+ 'ibm-not-wf-P02-ibm02n33']},
+ {testcases28, [], ['ibm-not-wf-P03-ibm03n01']},
+ {testcases29, [],
+ ['ibm-not-wf-P04-ibm04n01', 'ibm-not-wf-P04-ibm04n02',
+ 'ibm-not-wf-P04-ibm04n03', 'ibm-not-wf-P04-ibm04n04',
+ 'ibm-not-wf-P04-ibm04n05', 'ibm-not-wf-P04-ibm04n06',
+ 'ibm-not-wf-P04-ibm04n07', 'ibm-not-wf-P04-ibm04n08',
+ 'ibm-not-wf-P04-ibm04n09', 'ibm-not-wf-P04-ibm04n10',
+ 'ibm-not-wf-P04-ibm04n11', 'ibm-not-wf-P04-ibm04n12',
+ 'ibm-not-wf-P04-ibm04n13', 'ibm-not-wf-P04-ibm04n14',
+ 'ibm-not-wf-P04-ibm04n15', 'ibm-not-wf-P04-ibm04n16',
+ 'ibm-not-wf-P04-ibm04n17', 'ibm-not-wf-P04-ibm04n18']},
+ {testcases30, [],
+ ['ibm-not-wf-P05-ibm05n01', 'ibm-not-wf-P05-ibm05n02',
+ 'ibm-not-wf-P05-ibm05n03']},
+ {testcases31, [],
+ ['ibm-not-wf-P09-ibm09n01', 'ibm-not-wf-P09-ibm09n02',
+ 'ibm-not-wf-P09-ibm09n03', 'ibm-not-wf-P09-ibm09n04']},
+ {testcases32, [],
+ ['ibm-not-wf-P10-ibm10n01', 'ibm-not-wf-P10-ibm10n02',
+ 'ibm-not-wf-P10-ibm10n03', 'ibm-not-wf-P10-ibm10n04',
+ 'ibm-not-wf-P10-ibm10n05', 'ibm-not-wf-P10-ibm10n06',
+ 'ibm-not-wf-P10-ibm10n07', 'ibm-not-wf-P10-ibm10n08']},
+ {testcases33, [],
+ ['ibm-not-wf-P11-ibm11n01', 'ibm-not-wf-P11-ibm11n02',
+ 'ibm-not-wf-P11-ibm11n03', 'ibm-not-wf-P11-ibm11n04']},
+ {testcases34, [],
+ ['ibm-not-wf-P12-ibm12n01', 'ibm-not-wf-P12-ibm12n02',
+ 'ibm-not-wf-P12-ibm12n03']},
+ {testcases35, [],
+ ['ibm-not-wf-P13-ibm13n01', 'ibm-not-wf-P13-ibm13n02',
+ 'ibm-not-wf-P13-ibm13n03']},
+ {testcases36, [],
+ ['ibm-not-wf-P14-ibm14n01', 'ibm-not-wf-P14-ibm14n02',
+ 'ibm-not-wf-P14-ibm14n03']},
+ {testcases37, [],
+ ['ibm-not-wf-P15-ibm15n01', 'ibm-not-wf-P15-ibm15n02',
+ 'ibm-not-wf-P15-ibm15n03', 'ibm-not-wf-P15-ibm15n04']},
+ {testcases38, [],
+ ['ibm-not-wf-P16-ibm16n01', 'ibm-not-wf-P16-ibm16n02',
+ 'ibm-not-wf-P16-ibm16n03', 'ibm-not-wf-P16-ibm16n04']},
+ {testcases39, [],
+ ['ibm-not-wf-P17-ibm17n01', 'ibm-not-wf-P17-ibm17n02',
+ 'ibm-not-wf-P17-ibm17n03', 'ibm-not-wf-P17-ibm17n04']},
+ {testcases40, [],
+ ['ibm-not-wf-P18-ibm18n01', 'ibm-not-wf-P18-ibm18n02']},
+ {testcases41, [],
+ ['ibm-not-wf-P19-ibm19n01', 'ibm-not-wf-P19-ibm19n02',
+ 'ibm-not-wf-P19-ibm19n03']},
+ {testcases42, [], ['ibm-not-wf-P20-ibm20n01']},
+ {testcases43, [],
+ ['ibm-not-wf-P21-ibm21n01', 'ibm-not-wf-P21-ibm21n02',
+ 'ibm-not-wf-P21-ibm21n03']},
+ {testcases44, [],
+ ['ibm-not-wf-P22-ibm22n01', 'ibm-not-wf-P22-ibm22n02',
+ 'ibm-not-wf-P22-ibm22n03']},
+ {testcases45, [],
+ ['ibm-not-wf-P23-ibm23n01', 'ibm-not-wf-P23-ibm23n02',
+ 'ibm-not-wf-P23-ibm23n03', 'ibm-not-wf-P23-ibm23n04',
+ 'ibm-not-wf-P23-ibm23n05', 'ibm-not-wf-P23-ibm23n06']},
+ {testcases46, [],
+ ['ibm-not-wf-P24-ibm24n01', 'ibm-not-wf-P24-ibm24n02',
+ 'ibm-not-wf-P24-ibm24n03', 'ibm-not-wf-P24-ibm24n04',
+ 'ibm-not-wf-P24-ibm24n05', 'ibm-not-wf-P24-ibm24n06',
+ 'ibm-not-wf-P24-ibm24n07', 'ibm-not-wf-P24-ibm24n08',
+ 'ibm-not-wf-P24-ibm24n09']},
+ {testcases47, [],
+ ['ibm-not-wf-P25-ibm25n01', 'ibm-not-wf-P25-ibm25n02']},
+ {testcases48, [], ['ibm-not-wf-P26-ibm26n01']},
+ {testcases49, [], ['ibm-not-wf-P27-ibm27n01']},
+ {testcases50, [],
+ ['ibm-not-wf-P28-ibm28n01', 'ibm-not-wf-P28-ibm28n02',
+ 'ibm-not-wf-P28-ibm28n03', 'ibm-not-wf-P28-ibm28n04',
+ 'ibm-not-wf-P28-ibm28n05', 'ibm-not-wf-P28-ibm28n06',
+ 'ibm-not-wf-P28-ibm28n07', 'ibm-not-wf-P28-ibm28n08']},
+ {testcases51, [], ['ibm-not-wf-p28a-ibm28an01']},
+ {testcases52, [],
+ ['ibm-not-wf-P29-ibm29n01', 'ibm-not-wf-P29-ibm29n02',
+ 'ibm-not-wf-P29-ibm29n03', 'ibm-not-wf-P29-ibm29n04',
+ 'ibm-not-wf-P29-ibm29n05', 'ibm-not-wf-P29-ibm29n06',
+ 'ibm-not-wf-P29-ibm29n07']},
+ {testcases53, [], ['ibm-not-wf-P30-ibm30n01']},
+ {testcases54, [], ['ibm-not-wf-P31-ibm31n01']},
+ {testcases55, [],
+ ['ibm-not-wf-P32-ibm32n01', 'ibm-not-wf-P32-ibm32n02',
+ 'ibm-not-wf-P32-ibm32n03', 'ibm-not-wf-P32-ibm32n04',
+ 'ibm-not-wf-P32-ibm32n05', 'ibm-not-wf-P32-ibm32n06',
+ 'ibm-not-wf-P32-ibm32n07', 'ibm-not-wf-P32-ibm32n08',
+ 'ibm-not-wf-P32-ibm32n09']},
+ {testcases56, [],
+ ['ibm-not-wf-P39-ibm39n01', 'ibm-not-wf-P39-ibm39n02',
+ 'ibm-not-wf-P39-ibm39n03', 'ibm-not-wf-P39-ibm39n04',
+ 'ibm-not-wf-P39-ibm39n05', 'ibm-not-wf-P39-ibm39n06']},
+ {testcases57, [],
+ ['ibm-not-wf-P40-ibm40n01', 'ibm-not-wf-P40-ibm40n02',
+ 'ibm-not-wf-P40-ibm40n03', 'ibm-not-wf-P40-ibm40n04',
+ 'ibm-not-wf-P40-ibm40n05']},
+ {testcases58, [],
+ ['ibm-not-wf-P41-ibm41n01', 'ibm-not-wf-P41-ibm41n02',
+ 'ibm-not-wf-P41-ibm41n03', 'ibm-not-wf-P41-ibm41n04',
+ 'ibm-not-wf-P41-ibm41n05', 'ibm-not-wf-P41-ibm41n06',
+ 'ibm-not-wf-P41-ibm41n07', 'ibm-not-wf-P41-ibm41n08',
+ 'ibm-not-wf-P41-ibm41n09', 'ibm-not-wf-P41-ibm41n10',
+ 'ibm-not-wf-P41-ibm41n11', 'ibm-not-wf-P41-ibm41n12',
+ 'ibm-not-wf-P41-ibm41n13', 'ibm-not-wf-P41-ibm41n14']},
+ {testcases59, [],
+ ['ibm-not-wf-P42-ibm42n01', 'ibm-not-wf-P42-ibm42n02',
+ 'ibm-not-wf-P42-ibm42n03', 'ibm-not-wf-P42-ibm42n04',
+ 'ibm-not-wf-P42-ibm42n05']},
+ {testcases60, [],
+ ['ibm-not-wf-P43-ibm43n01', 'ibm-not-wf-P43-ibm43n02',
+ 'ibm-not-wf-P43-ibm43n04', 'ibm-not-wf-P43-ibm43n05']},
+ {testcases61, [],
+ ['ibm-not-wf-P44-ibm44n01', 'ibm-not-wf-P44-ibm44n02',
+ 'ibm-not-wf-P44-ibm44n03', 'ibm-not-wf-P44-ibm44n04']},
+ {testcases62, [],
+ ['ibm-not-wf-P45-ibm45n01', 'ibm-not-wf-P45-ibm45n02',
+ 'ibm-not-wf-P45-ibm45n03', 'ibm-not-wf-P45-ibm45n04',
+ 'ibm-not-wf-P45-ibm45n05', 'ibm-not-wf-P45-ibm45n06',
+ 'ibm-not-wf-P45-ibm45n07', 'ibm-not-wf-P45-ibm45n08',
+ 'ibm-not-wf-P45-ibm45n09']},
+ {testcases63, [],
+ ['ibm-not-wf-P46-ibm46n01', 'ibm-not-wf-P46-ibm46n02',
+ 'ibm-not-wf-P46-ibm46n03', 'ibm-not-wf-P46-ibm46n04',
+ 'ibm-not-wf-P46-ibm46n05']},
+ {testcases64, [],
+ ['ibm-not-wf-P47-ibm47n01', 'ibm-not-wf-P47-ibm47n02',
+ 'ibm-not-wf-P47-ibm47n03', 'ibm-not-wf-P47-ibm47n04',
+ 'ibm-not-wf-P47-ibm47n05', 'ibm-not-wf-P47-ibm47n06']},
+ {testcases65, [],
+ ['ibm-not-wf-P48-ibm48n01', 'ibm-not-wf-P48-ibm48n02',
+ 'ibm-not-wf-P48-ibm48n03', 'ibm-not-wf-P48-ibm48n04',
+ 'ibm-not-wf-P48-ibm48n05', 'ibm-not-wf-P48-ibm48n06',
+ 'ibm-not-wf-P48-ibm48n07']},
+ {testcases66, [],
+ ['ibm-not-wf-P49-ibm49n01', 'ibm-not-wf-P49-ibm49n02',
+ 'ibm-not-wf-P49-ibm49n03', 'ibm-not-wf-P49-ibm49n04',
+ 'ibm-not-wf-P49-ibm49n05', 'ibm-not-wf-P49-ibm49n06']},
+ {testcases67, [],
+ ['ibm-not-wf-P50-ibm50n01','ibm-not-wf-P50-ibm50n02',
+ 'ibm-not-wf-P50-ibm50n03','ibm-not-wf-P50-ibm50n04',
+ 'ibm-not-wf-P50-ibm50n05','ibm-not-wf-P50-ibm50n06',
+ 'ibm-not-wf-P50-ibm50n07']},
+ {testcases68, [],
+ ['ibm-not-wf-P51-ibm51n01','ibm-not-wf-P51-ibm51n02',
+ 'ibm-not-wf-P51-ibm51n03','ibm-not-wf-P51-ibm51n04',
+ 'ibm-not-wf-P51-ibm51n05','ibm-not-wf-P51-ibm51n06',
+ 'ibm-not-wf-P51-ibm51n07']},
+ {testcases69, [],
+ ['ibm-not-wf-P52-ibm52n01', 'ibm-not-wf-P52-ibm52n02',
+ 'ibm-not-wf-P52-ibm52n03', 'ibm-not-wf-P52-ibm52n04',
+ 'ibm-not-wf-P52-ibm52n05', 'ibm-not-wf-P52-ibm52n06']},
+ {testcases70, [],
+ ['ibm-not-wf-P53-ibm53n01', 'ibm-not-wf-P53-ibm53n02',
+ 'ibm-not-wf-P53-ibm53n03', 'ibm-not-wf-P53-ibm53n04',
+ 'ibm-not-wf-P53-ibm53n05', 'ibm-not-wf-P53-ibm53n06',
+ 'ibm-not-wf-P53-ibm53n07', 'ibm-not-wf-P53-ibm53n08']},
+ {testcases71, [],
+ ['ibm-not-wf-P54-ibm54n01', 'ibm-not-wf-P54-ibm54n02']},
+ {testcases72, [],
+ ['ibm-not-wf-P55-ibm55n01', 'ibm-not-wf-P55-ibm55n02',
+ 'ibm-not-wf-P55-ibm55n03']},
+ {testcases73, [],
+ ['ibm-not-wf-P56-ibm56n01', 'ibm-not-wf-P56-ibm56n02',
+ 'ibm-not-wf-P56-ibm56n03', 'ibm-not-wf-P56-ibm56n04',
+ 'ibm-not-wf-P56-ibm56n05', 'ibm-not-wf-P56-ibm56n06',
+ 'ibm-not-wf-P56-ibm56n07']},
+ {testcases74, [], ['ibm-not-wf-P57-ibm57n01']},
+ {testcases75, [],
+ ['ibm-not-wf-P58-ibm58n01', 'ibm-not-wf-P58-ibm58n02',
+ 'ibm-not-wf-P58-ibm58n03', 'ibm-not-wf-P58-ibm58n04',
+ 'ibm-not-wf-P58-ibm58n05', 'ibm-not-wf-P58-ibm58n06',
+ 'ibm-not-wf-P58-ibm58n07', 'ibm-not-wf-P58-ibm58n08']},
+ {testcases76, [],
+ ['ibm-not-wf-P59-ibm59n01', 'ibm-not-wf-P59-ibm59n02',
+ 'ibm-not-wf-P59-ibm59n03', 'ibm-not-wf-P59-ibm59n04',
+ 'ibm-not-wf-P59-ibm59n05', 'ibm-not-wf-P59-ibm59n06']},
+ {testcases77, [],
+ ['ibm-not-wf-P60-ibm60n01', 'ibm-not-wf-P60-ibm60n02',
+ 'ibm-not-wf-P60-ibm60n03', 'ibm-not-wf-P60-ibm60n04',
+ 'ibm-not-wf-P60-ibm60n05', 'ibm-not-wf-P60-ibm60n06',
+ 'ibm-not-wf-P60-ibm60n07', 'ibm-not-wf-P60-ibm60n08']},
+ {testcases78, [], ['ibm-not-wf-P61-ibm61n01']},
+ {testcases79, [],
+ ['ibm-not-wf-P62-ibm62n01', 'ibm-not-wf-P62-ibm62n02',
+ 'ibm-not-wf-P62-ibm62n03', 'ibm-not-wf-P62-ibm62n04',
+ 'ibm-not-wf-P62-ibm62n05', 'ibm-not-wf-P62-ibm62n06',
+ 'ibm-not-wf-P62-ibm62n07', 'ibm-not-wf-P62-ibm62n08']},
+ {testcases80, [],
+ ['ibm-not-wf-P63-ibm63n01', 'ibm-not-wf-P63-ibm63n02',
+ 'ibm-not-wf-P63-ibm63n03', 'ibm-not-wf-P63-ibm63n04',
+ 'ibm-not-wf-P63-ibm63n05', 'ibm-not-wf-P63-ibm63n06',
+ 'ibm-not-wf-P63-ibm63n07']},
+ {testcases81, [],
+ ['ibm-not-wf-P64-ibm64n01', 'ibm-not-wf-P64-ibm64n02',
+ 'ibm-not-wf-P64-ibm64n03']},
+ {testcases82, [],
+ ['ibm-not-wf-P65-ibm65n01', 'ibm-not-wf-P65-ibm65n02']},
+ {testcases83, [],
+ ['ibm-not-wf-P66-ibm66n01', 'ibm-not-wf-P66-ibm66n02',
+ 'ibm-not-wf-P66-ibm66n03', 'ibm-not-wf-P66-ibm66n04',
+ 'ibm-not-wf-P66-ibm66n05', 'ibm-not-wf-P66-ibm66n06',
+ 'ibm-not-wf-P66-ibm66n07', 'ibm-not-wf-P66-ibm66n08',
+ 'ibm-not-wf-P66-ibm66n09', 'ibm-not-wf-P66-ibm66n10',
+ 'ibm-not-wf-P66-ibm66n11', 'ibm-not-wf-P66-ibm66n12',
+ 'ibm-not-wf-P66-ibm66n13', 'ibm-not-wf-P66-ibm66n14',
+ 'ibm-not-wf-P66-ibm66n15']},
+ {testcases84, [],
+ ['ibm-not-wf-P68-ibm68n01', 'ibm-not-wf-P68-ibm68n02',
+ 'ibm-not-wf-P68-ibm68n03', 'ibm-not-wf-P68-ibm68n04',
+ 'ibm-not-wf-P68-ibm68n05', 'ibm-not-wf-P68-ibm68n06',
+ 'ibm-not-wf-P68-ibm68n07', 'ibm-not-wf-P68-ibm68n08',
+ 'ibm-not-wf-P68-ibm68n09', 'ibm-not-wf-P68-ibm68n10']},
+ {testcases85, [],
+ ['ibm-not-wf-P69-ibm69n01', 'ibm-not-wf-P69-ibm69n02',
+ 'ibm-not-wf-P69-ibm69n03', 'ibm-not-wf-P69-ibm69n04',
+ 'ibm-not-wf-P69-ibm69n05', 'ibm-not-wf-P69-ibm69n06',
+ 'ibm-not-wf-P69-ibm69n07']},
+ {testcases86, [],
+ ['ibm-not-wf-P71-ibm70n01', 'ibm-not-wf-P71-ibm71n01',
+ 'ibm-not-wf-P71-ibm71n02', 'ibm-not-wf-P71-ibm71n03',
+ 'ibm-not-wf-P71-ibm71n04', 'ibm-not-wf-P71-ibm71n05',
+ 'ibm-not-wf-P71-ibm71n06', 'ibm-not-wf-P71-ibm71n07',
+ 'ibm-not-wf-P71-ibm71n08']},
+ {testcases87, [],
+ ['ibm-not-wf-P72-ibm72n01', 'ibm-not-wf-P72-ibm72n02',
+ 'ibm-not-wf-P72-ibm72n03', 'ibm-not-wf-P72-ibm72n04',
+ 'ibm-not-wf-P72-ibm72n05', 'ibm-not-wf-P72-ibm72n06',
+ 'ibm-not-wf-P72-ibm72n07', 'ibm-not-wf-P72-ibm72n08',
+ 'ibm-not-wf-P72-ibm72n09']},
+ {testcases88, [],
+ ['ibm-not-wf-P73-ibm73n01', 'ibm-not-wf-P73-ibm73n03']},
+ {testcases89, [], ['ibm-not-wf-P74-ibm74n01']},
+ {testcases90, [],
+ ['ibm-not-wf-P75-ibm75n01', 'ibm-not-wf-P75-ibm75n02',
+ 'ibm-not-wf-P75-ibm75n03', 'ibm-not-wf-P75-ibm75n04',
+ 'ibm-not-wf-P75-ibm75n05', 'ibm-not-wf-P75-ibm75n06',
+ 'ibm-not-wf-P75-ibm75n07', 'ibm-not-wf-P75-ibm75n08',
+ 'ibm-not-wf-P75-ibm75n09', 'ibm-not-wf-P75-ibm75n10',
+ 'ibm-not-wf-P75-ibm75n11', 'ibm-not-wf-P75-ibm75n12',
+ 'ibm-not-wf-P75-ibm75n13']},
+ {testcases91, [],
+ ['ibm-not-wf-P76-ibm76n01', 'ibm-not-wf-P76-ibm76n02',
+ 'ibm-not-wf-P76-ibm76n03', 'ibm-not-wf-P76-ibm76n04',
+ 'ibm-not-wf-P76-ibm76n05', 'ibm-not-wf-P76-ibm76n06',
+ 'ibm-not-wf-P76-ibm76n07']},
+ {testcases92, [],
+ ['ibm-not-wf-P77-ibm77n01', 'ibm-not-wf-P77-ibm77n02',
+ 'ibm-not-wf-P77-ibm77n03', 'ibm-not-wf-P77-ibm77n04']},
+ {testcases93, [],
+ ['ibm-not-wf-P78-ibm78n01', 'ibm-not-wf-P78-ibm78n02']},
+ {testcases94, [],
+ ['ibm-not-wf-P79-ibm79n01', 'ibm-not-wf-P79-ibm79n02']},
+ {testcases95, [],
+ ['ibm-not-wf-P80-ibm80n01', 'ibm-not-wf-P80-ibm80n02',
+ 'ibm-not-wf-P80-ibm80n03', 'ibm-not-wf-P80-ibm80n04',
+ 'ibm-not-wf-P80-ibm80n05', 'ibm-not-wf-P80-ibm80n06']},
+ {testcases96, [],
+ ['ibm-not-wf-P81-ibm81n01', 'ibm-not-wf-P81-ibm81n02',
+ 'ibm-not-wf-P81-ibm81n03', 'ibm-not-wf-P81-ibm81n04',
+ 'ibm-not-wf-P81-ibm81n05', 'ibm-not-wf-P81-ibm81n06',
+ 'ibm-not-wf-P81-ibm81n07', 'ibm-not-wf-P81-ibm81n08',
+ 'ibm-not-wf-P81-ibm81n09']},
+ {testcases97, [],
+ ['ibm-not-wf-P82-ibm82n01', 'ibm-not-wf-P82-ibm82n02',
+ 'ibm-not-wf-P82-ibm82n03', 'ibm-not-wf-P82-ibm82n04',
+ 'ibm-not-wf-P82-ibm82n05', 'ibm-not-wf-P82-ibm82n06',
+ 'ibm-not-wf-P82-ibm82n07', 'ibm-not-wf-P82-ibm82n08']},
+ {testcases98, [],
+ ['ibm-not-wf-P83-ibm83n01', 'ibm-not-wf-P83-ibm83n02',
+ 'ibm-not-wf-P83-ibm83n03', 'ibm-not-wf-P83-ibm83n04',
+ 'ibm-not-wf-P83-ibm83n05', 'ibm-not-wf-P83-ibm83n06']},
+ {testcases99, [],
+ ['ibm-not-wf-P85-ibm85n01', 'ibm-not-wf-P85-ibm85n02',
+ 'ibm-not-wf-P85-ibm85n03', 'ibm-not-wf-P85-ibm85n04',
+ 'ibm-not-wf-P85-ibm85n05', 'ibm-not-wf-P85-ibm85n06',
+ 'ibm-not-wf-P85-ibm85n07', 'ibm-not-wf-P85-ibm85n08',
+ 'ibm-not-wf-P85-ibm85n09', 'ibm-not-wf-P85-ibm85n10',
+ 'ibm-not-wf-P85-ibm85n100', 'ibm-not-wf-P85-ibm85n101',
+ 'ibm-not-wf-P85-ibm85n102', 'ibm-not-wf-P85-ibm85n103',
+ 'ibm-not-wf-P85-ibm85n104', 'ibm-not-wf-P85-ibm85n105',
+ 'ibm-not-wf-P85-ibm85n106', 'ibm-not-wf-P85-ibm85n107',
+ 'ibm-not-wf-P85-ibm85n108', 'ibm-not-wf-P85-ibm85n109',
+ 'ibm-not-wf-P85-ibm85n11', 'ibm-not-wf-P85-ibm85n110',
+ 'ibm-not-wf-P85-ibm85n111', 'ibm-not-wf-P85-ibm85n112',
+ 'ibm-not-wf-P85-ibm85n113', 'ibm-not-wf-P85-ibm85n114',
+ 'ibm-not-wf-P85-ibm85n115', 'ibm-not-wf-P85-ibm85n116',
+ 'ibm-not-wf-P85-ibm85n117', 'ibm-not-wf-P85-ibm85n118',
+ 'ibm-not-wf-P85-ibm85n119', 'ibm-not-wf-P85-ibm85n12',
+ 'ibm-not-wf-P85-ibm85n120', 'ibm-not-wf-P85-ibm85n121',
+ 'ibm-not-wf-P85-ibm85n122', 'ibm-not-wf-P85-ibm85n123',
+ 'ibm-not-wf-P85-ibm85n124', 'ibm-not-wf-P85-ibm85n125',
+ 'ibm-not-wf-P85-ibm85n126', 'ibm-not-wf-P85-ibm85n127',
+ 'ibm-not-wf-P85-ibm85n128', 'ibm-not-wf-P85-ibm85n129',
+ 'ibm-not-wf-P85-ibm85n13', 'ibm-not-wf-P85-ibm85n130',
+ 'ibm-not-wf-P85-ibm85n131', 'ibm-not-wf-P85-ibm85n132',
+ 'ibm-not-wf-P85-ibm85n133', 'ibm-not-wf-P85-ibm85n134',
+ 'ibm-not-wf-P85-ibm85n135', 'ibm-not-wf-P85-ibm85n136',
+ 'ibm-not-wf-P85-ibm85n137', 'ibm-not-wf-P85-ibm85n138',
+ 'ibm-not-wf-P85-ibm85n139', 'ibm-not-wf-P85-ibm85n14',
+ 'ibm-not-wf-P85-ibm85n140', 'ibm-not-wf-P85-ibm85n141',
+ 'ibm-not-wf-P85-ibm85n142', 'ibm-not-wf-P85-ibm85n143',
+ 'ibm-not-wf-P85-ibm85n144', 'ibm-not-wf-P85-ibm85n145',
+ 'ibm-not-wf-P85-ibm85n146', 'ibm-not-wf-P85-ibm85n147',
+ 'ibm-not-wf-P85-ibm85n148', 'ibm-not-wf-P85-ibm85n149',
+ 'ibm-not-wf-P85-ibm85n15', 'ibm-not-wf-P85-ibm85n150',
+ 'ibm-not-wf-P85-ibm85n151', 'ibm-not-wf-P85-ibm85n152',
+ 'ibm-not-wf-P85-ibm85n153', 'ibm-not-wf-P85-ibm85n154',
+ 'ibm-not-wf-P85-ibm85n155', 'ibm-not-wf-P85-ibm85n156',
+ 'ibm-not-wf-P85-ibm85n157', 'ibm-not-wf-P85-ibm85n158',
+ 'ibm-not-wf-P85-ibm85n159', 'ibm-not-wf-P85-ibm85n16',
+ 'ibm-not-wf-P85-ibm85n160', 'ibm-not-wf-P85-ibm85n161',
+ 'ibm-not-wf-P85-ibm85n162', 'ibm-not-wf-P85-ibm85n163',
+ 'ibm-not-wf-P85-ibm85n164', 'ibm-not-wf-P85-ibm85n165',
+ 'ibm-not-wf-P85-ibm85n166', 'ibm-not-wf-P85-ibm85n167',
+ 'ibm-not-wf-P85-ibm85n168', 'ibm-not-wf-P85-ibm85n169',
+ 'ibm-not-wf-P85-ibm85n17', 'ibm-not-wf-P85-ibm85n170',
+ 'ibm-not-wf-P85-ibm85n171', 'ibm-not-wf-P85-ibm85n172',
+ 'ibm-not-wf-P85-ibm85n173', 'ibm-not-wf-P85-ibm85n174',
+ 'ibm-not-wf-P85-ibm85n175', 'ibm-not-wf-P85-ibm85n176',
+ 'ibm-not-wf-P85-ibm85n177', 'ibm-not-wf-P85-ibm85n178',
+ 'ibm-not-wf-P85-ibm85n179', 'ibm-not-wf-P85-ibm85n18',
+ 'ibm-not-wf-P85-ibm85n180', 'ibm-not-wf-P85-ibm85n181',
+ 'ibm-not-wf-P85-ibm85n182', 'ibm-not-wf-P85-ibm85n183',
+ 'ibm-not-wf-P85-ibm85n184', 'ibm-not-wf-P85-ibm85n185',
+ 'ibm-not-wf-P85-ibm85n186', 'ibm-not-wf-P85-ibm85n187',
+ 'ibm-not-wf-P85-ibm85n188', 'ibm-not-wf-P85-ibm85n189',
+ 'ibm-not-wf-P85-ibm85n19', 'ibm-not-wf-P85-ibm85n190',
+ 'ibm-not-wf-P85-ibm85n191', 'ibm-not-wf-P85-ibm85n192',
+ 'ibm-not-wf-P85-ibm85n193', 'ibm-not-wf-P85-ibm85n194',
+ 'ibm-not-wf-P85-ibm85n195', 'ibm-not-wf-P85-ibm85n196',
+ 'ibm-not-wf-P85-ibm85n197', 'ibm-not-wf-P85-ibm85n198',
+ 'ibm-not-wf-P85-ibm85n20', 'ibm-not-wf-P85-ibm85n21',
+ 'ibm-not-wf-P85-ibm85n22', 'ibm-not-wf-P85-ibm85n23',
+ 'ibm-not-wf-P85-ibm85n24', 'ibm-not-wf-P85-ibm85n25',
+ 'ibm-not-wf-P85-ibm85n26', 'ibm-not-wf-P85-ibm85n27',
+ 'ibm-not-wf-P85-ibm85n28', 'ibm-not-wf-P85-ibm85n29',
+ 'ibm-not-wf-P85-ibm85n30', 'ibm-not-wf-P85-ibm85n31',
+ 'ibm-not-wf-P85-ibm85n32', 'ibm-not-wf-P85-ibm85n33',
+ 'ibm-not-wf-P85-ibm85n34', 'ibm-not-wf-P85-ibm85n35',
+ 'ibm-not-wf-P85-ibm85n36', 'ibm-not-wf-P85-ibm85n37',
+ 'ibm-not-wf-P85-ibm85n38', 'ibm-not-wf-P85-ibm85n39',
+ 'ibm-not-wf-P85-ibm85n40', 'ibm-not-wf-P85-ibm85n41',
+ 'ibm-not-wf-P85-ibm85n42', 'ibm-not-wf-P85-ibm85n43',
+ 'ibm-not-wf-P85-ibm85n44', 'ibm-not-wf-P85-ibm85n45',
+ 'ibm-not-wf-P85-ibm85n46', 'ibm-not-wf-P85-ibm85n47',
+ 'ibm-not-wf-P85-ibm85n48', 'ibm-not-wf-P85-ibm85n49',
+ 'ibm-not-wf-P85-ibm85n50', 'ibm-not-wf-P85-ibm85n51',
+ 'ibm-not-wf-P85-ibm85n52', 'ibm-not-wf-P85-ibm85n53',
+ 'ibm-not-wf-P85-ibm85n54', 'ibm-not-wf-P85-ibm85n55',
+ 'ibm-not-wf-P85-ibm85n56', 'ibm-not-wf-P85-ibm85n57',
+ 'ibm-not-wf-P85-ibm85n58', 'ibm-not-wf-P85-ibm85n59',
+ 'ibm-not-wf-P85-ibm85n60', 'ibm-not-wf-P85-ibm85n61',
+ 'ibm-not-wf-P85-ibm85n62', 'ibm-not-wf-P85-ibm85n63',
+ 'ibm-not-wf-P85-ibm85n64', 'ibm-not-wf-P85-ibm85n65',
+ 'ibm-not-wf-P85-ibm85n66', 'ibm-not-wf-P85-ibm85n67',
+ 'ibm-not-wf-P85-ibm85n68', 'ibm-not-wf-P85-ibm85n69',
+ 'ibm-not-wf-P85-ibm85n70', 'ibm-not-wf-P85-ibm85n71',
+ 'ibm-not-wf-P85-ibm85n72', 'ibm-not-wf-P85-ibm85n73',
+ 'ibm-not-wf-P85-ibm85n74', 'ibm-not-wf-P85-ibm85n75',
+ 'ibm-not-wf-P85-ibm85n76', 'ibm-not-wf-P85-ibm85n77',
+ 'ibm-not-wf-P85-ibm85n78', 'ibm-not-wf-P85-ibm85n79',
+ 'ibm-not-wf-P85-ibm85n80', 'ibm-not-wf-P85-ibm85n81',
+ 'ibm-not-wf-P85-ibm85n82', 'ibm-not-wf-P85-ibm85n83',
+ 'ibm-not-wf-P85-ibm85n84', 'ibm-not-wf-P85-ibm85n85',
+ 'ibm-not-wf-P85-ibm85n86', 'ibm-not-wf-P85-ibm85n87',
+ 'ibm-not-wf-P85-ibm85n88', 'ibm-not-wf-P85-ibm85n89',
+ 'ibm-not-wf-P85-ibm85n90', 'ibm-not-wf-P85-ibm85n91',
+ 'ibm-not-wf-P85-ibm85n92', 'ibm-not-wf-P85-ibm85n93',
+ 'ibm-not-wf-P85-ibm85n94', 'ibm-not-wf-P85-ibm85n95',
+ 'ibm-not-wf-P85-ibm85n96', 'ibm-not-wf-P85-ibm85n97',
+ 'ibm-not-wf-P85-ibm85n98', 'ibm-not-wf-P85-ibm85n99']},
+ {testcases100, [],
+ ['ibm-not-wf-P86-ibm86n01', 'ibm-not-wf-P86-ibm86n02',
+ 'ibm-not-wf-P86-ibm86n03', 'ibm-not-wf-P86-ibm86n04']},
+ {testcases101, [],
+ ['ibm-not-wf-P87-ibm87n01', 'ibm-not-wf-P87-ibm87n02',
+ 'ibm-not-wf-P87-ibm87n03', 'ibm-not-wf-P87-ibm87n04',
+ 'ibm-not-wf-P87-ibm87n05', 'ibm-not-wf-P87-ibm87n06',
+ 'ibm-not-wf-P87-ibm87n07', 'ibm-not-wf-P87-ibm87n08',
+ 'ibm-not-wf-P87-ibm87n09', 'ibm-not-wf-P87-ibm87n10',
+ 'ibm-not-wf-P87-ibm87n11', 'ibm-not-wf-P87-ibm87n12',
+ 'ibm-not-wf-P87-ibm87n13', 'ibm-not-wf-P87-ibm87n14',
+ 'ibm-not-wf-P87-ibm87n15', 'ibm-not-wf-P87-ibm87n16',
+ 'ibm-not-wf-P87-ibm87n17', 'ibm-not-wf-P87-ibm87n18',
+ 'ibm-not-wf-P87-ibm87n19', 'ibm-not-wf-P87-ibm87n20',
+ 'ibm-not-wf-P87-ibm87n21', 'ibm-not-wf-P87-ibm87n22',
+ 'ibm-not-wf-P87-ibm87n23', 'ibm-not-wf-P87-ibm87n24',
+ 'ibm-not-wf-P87-ibm87n25', 'ibm-not-wf-P87-ibm87n26',
+ 'ibm-not-wf-P87-ibm87n27', 'ibm-not-wf-P87-ibm87n28',
+ 'ibm-not-wf-P87-ibm87n29', 'ibm-not-wf-P87-ibm87n30',
+ 'ibm-not-wf-P87-ibm87n31', 'ibm-not-wf-P87-ibm87n32',
+ 'ibm-not-wf-P87-ibm87n33', 'ibm-not-wf-P87-ibm87n34',
+ 'ibm-not-wf-P87-ibm87n35', 'ibm-not-wf-P87-ibm87n36',
+ 'ibm-not-wf-P87-ibm87n37', 'ibm-not-wf-P87-ibm87n38',
+ 'ibm-not-wf-P87-ibm87n39', 'ibm-not-wf-P87-ibm87n40',
+ 'ibm-not-wf-P87-ibm87n41', 'ibm-not-wf-P87-ibm87n42',
+ 'ibm-not-wf-P87-ibm87n43', 'ibm-not-wf-P87-ibm87n44',
+ 'ibm-not-wf-P87-ibm87n45', 'ibm-not-wf-P87-ibm87n46',
+ 'ibm-not-wf-P87-ibm87n47', 'ibm-not-wf-P87-ibm87n48',
+ 'ibm-not-wf-P87-ibm87n49', 'ibm-not-wf-P87-ibm87n50',
+ 'ibm-not-wf-P87-ibm87n51', 'ibm-not-wf-P87-ibm87n52',
+ 'ibm-not-wf-P87-ibm87n53', 'ibm-not-wf-P87-ibm87n54',
+ 'ibm-not-wf-P87-ibm87n55', 'ibm-not-wf-P87-ibm87n56',
+ 'ibm-not-wf-P87-ibm87n57', 'ibm-not-wf-P87-ibm87n58',
+ 'ibm-not-wf-P87-ibm87n59', 'ibm-not-wf-P87-ibm87n60',
+ 'ibm-not-wf-P87-ibm87n61', 'ibm-not-wf-P87-ibm87n62',
+ 'ibm-not-wf-P87-ibm87n63', 'ibm-not-wf-P87-ibm87n64',
+ 'ibm-not-wf-P87-ibm87n66', 'ibm-not-wf-P87-ibm87n67',
+ 'ibm-not-wf-P87-ibm87n68', 'ibm-not-wf-P87-ibm87n69',
+ 'ibm-not-wf-P87-ibm87n70', 'ibm-not-wf-P87-ibm87n71',
+ 'ibm-not-wf-P87-ibm87n72', 'ibm-not-wf-P87-ibm87n73',
+ 'ibm-not-wf-P87-ibm87n74', 'ibm-not-wf-P87-ibm87n75',
+ 'ibm-not-wf-P87-ibm87n76', 'ibm-not-wf-P87-ibm87n77',
+ 'ibm-not-wf-P87-ibm87n78', 'ibm-not-wf-P87-ibm87n79',
+ 'ibm-not-wf-P87-ibm87n80', 'ibm-not-wf-P87-ibm87n81',
+ 'ibm-not-wf-P87-ibm87n82', 'ibm-not-wf-P87-ibm87n83',
+ 'ibm-not-wf-P87-ibm87n84', 'ibm-not-wf-P87-ibm87n85']},
+ {testcases102, [],
+ ['ibm-not-wf-P88-ibm88n01', 'ibm-not-wf-P88-ibm88n02',
+ 'ibm-not-wf-P88-ibm88n03', 'ibm-not-wf-P88-ibm88n04',
+ 'ibm-not-wf-P88-ibm88n05', 'ibm-not-wf-P88-ibm88n06',
+ 'ibm-not-wf-P88-ibm88n08', 'ibm-not-wf-P88-ibm88n09',
+ 'ibm-not-wf-P88-ibm88n10', 'ibm-not-wf-P88-ibm88n11',
+ 'ibm-not-wf-P88-ibm88n12', 'ibm-not-wf-P88-ibm88n13',
+ 'ibm-not-wf-P88-ibm88n14', 'ibm-not-wf-P88-ibm88n15',
+ 'ibm-not-wf-P88-ibm88n16']},
+ {testcases103, [],
+ ['ibm-not-wf-P89-ibm89n01', 'ibm-not-wf-P89-ibm89n02',
+ 'ibm-not-wf-P89-ibm89n03', 'ibm-not-wf-P89-ibm89n04',
+ 'ibm-not-wf-P89-ibm89n05', 'ibm-not-wf-P89-ibm89n06',
+ 'ibm-not-wf-P89-ibm89n07', 'ibm-not-wf-P89-ibm89n08',
+ 'ibm-not-wf-P89-ibm89n09', 'ibm-not-wf-P89-ibm89n10',
+ 'ibm-not-wf-P89-ibm89n11', 'ibm-not-wf-P89-ibm89n12']},
+ {testcases25, [],
+ [{group, testcases26}, {group, testcases27},
+ {group, testcases28}, {group, testcases29},
+ {group, testcases30}, {group, testcases31},
+ {group, testcases32}, {group, testcases33},
+ {group, testcases34}, {group, testcases35},
+ {group, testcases36}, {group, testcases37},
+ {group, testcases38}, {group, testcases39},
+ {group, testcases40}, {group, testcases41},
+ {group, testcases42}, {group, testcases43},
+ {group, testcases44}, {group, testcases45},
+ {group, testcases46}, {group, testcases47},
+ {group, testcases48}, {group, testcases49},
+ {group, testcases50}, {group, testcases51},
+ {group, testcases52}, {group, testcases53},
+ {group, testcases54}, {group, testcases55},
+ {group, testcases56}, {group, testcases57},
+ {group, testcases58}, {group, testcases59},
+ {group, testcases60}, {group, testcases61},
+ {group, testcases62}, {group, testcases63},
+ {group, testcases64}, {group, testcases65},
+ {group, testcases66},
+% {group, testcases67}, {group, testcases68},
+ {group, testcases69}, {group, testcases70},
+ {group, testcases71}, {group, testcases72},
+ {group, testcases73}, {group, testcases74},
+ {group, testcases75}, {group, testcases76},
+ {group, testcases77}, {group, testcases78},
+ {group, testcases79}, {group, testcases80},
+ {group, testcases81}, {group, testcases82},
+ {group, testcases83}, {group, testcases84},
+ {group, testcases85}, {group, testcases86},
+ {group, testcases87}, {group, testcases88},
+ {group, testcases89}, {group, testcases90},
+ {group, testcases91}, {group, testcases92},
+ {group, testcases93}, {group, testcases94},
+ {group, testcases95}, {group, testcases96},
+ {group, testcases97}, {group, testcases98},
+ {group, testcases99}, {group, testcases100},
+ {group, testcases101}, {group, testcases102},
+ {group, testcases103}]},
+ {testcases105, [], ['ibm-valid-P01-ibm01v01']},
+ {testcases106, [], ['ibm-valid-P02-ibm02v01']},
+ {testcases107, [], ['ibm-valid-P03-ibm03v01']},
+ {testcases108, [],
+ ['ibm-valid-P09-ibm09v01', 'ibm-valid-P09-ibm09v02',
+ 'ibm-valid-P09-ibm09v03', 'ibm-valid-P09-ibm09v04',
+ 'ibm-valid-P09-ibm09v05']},
+ {testcases109, [],
+ ['ibm-valid-P10-ibm10v01', 'ibm-valid-P10-ibm10v02',
+ 'ibm-valid-P10-ibm10v03', 'ibm-valid-P10-ibm10v04',
+ 'ibm-valid-P10-ibm10v05', 'ibm-valid-P10-ibm10v06',
+ 'ibm-valid-P10-ibm10v07', 'ibm-valid-P10-ibm10v08']},
+ {testcases110, [],
+ ['ibm-valid-P11-ibm11v01', 'ibm-valid-P11-ibm11v02',
+ 'ibm-valid-P11-ibm11v03', 'ibm-valid-P11-ibm11v04']},
+ {testcases111, [],
+ ['ibm-valid-P12-ibm12v01','ibm-valid-P12-ibm12v02',
+ 'ibm-valid-P12-ibm12v03','ibm-valid-P12-ibm12v04']},
+ {testcases112, [], ['ibm-valid-P13-ibm13v01']},
+ {testcases113, [],
+ ['ibm-valid-P14-ibm14v01', 'ibm-valid-P14-ibm14v02',
+ 'ibm-valid-P14-ibm14v03']},
+ {testcases114, [],
+ ['ibm-valid-P15-ibm15v01', 'ibm-valid-P15-ibm15v02',
+ 'ibm-valid-P15-ibm15v03', 'ibm-valid-P15-ibm15v04']},
+ {testcases115, [],
+ ['ibm-valid-P16-ibm16v01', 'ibm-valid-P16-ibm16v02',
+ 'ibm-valid-P16-ibm16v03']},
+ {testcases116, [], ['ibm-valid-P17-ibm17v01']},
+ {testcases117, [], ['ibm-valid-P18-ibm18v01']},
+ {testcases118, [], ['ibm-valid-P19-ibm19v01']},
+ {testcases119, [],
+ ['ibm-valid-P20-ibm20v01', 'ibm-valid-P20-ibm20v02']},
+ {testcases120, [], ['ibm-valid-P21-ibm21v01']},
+ {testcases121, [],
+ ['ibm-valid-P22-ibm22v01', 'ibm-valid-P22-ibm22v02',
+ 'ibm-valid-P22-ibm22v03', 'ibm-valid-P22-ibm22v04',
+ 'ibm-valid-P22-ibm22v05', 'ibm-valid-P22-ibm22v06',
+ 'ibm-valid-P22-ibm22v07']},
+ {testcases122, [],
+ ['ibm-valid-P23-ibm23v01', 'ibm-valid-P23-ibm23v02',
+ 'ibm-valid-P23-ibm23v03', 'ibm-valid-P23-ibm23v04',
+ 'ibm-valid-P23-ibm23v05', 'ibm-valid-P23-ibm23v06']},
+ {testcases123, [],
+ ['ibm-valid-P24-ibm24v01', 'ibm-valid-P24-ibm24v02']},
+ {testcases124, [],
+ ['ibm-valid-P25-ibm25v01', 'ibm-valid-P25-ibm25v02',
+ 'ibm-valid-P25-ibm25v03', 'ibm-valid-P25-ibm25v04']},
+ {testcases125, [], ['ibm-valid-P26-ibm26v01']},
+ {testcases126, [],
+ ['ibm-valid-P27-ibm27v01', 'ibm-valid-P27-ibm27v02',
+ 'ibm-valid-P27-ibm27v03']},
+ {testcases127, [],
+ ['ibm-valid-P28-ibm28v01', 'ibm-valid-P28-ibm28v02']},
+ {testcases128, [],
+ ['ibm-valid-P29-ibm29v01', 'ibm-valid-P29-ibm29v02']},
+ {testcases129, [],
+ ['ibm-valid-P30-ibm30v01', 'ibm-valid-P30-ibm30v02']},
+ {testcases130, [],
+ ['ibm-valid-P31-ibm31v01']},
+ {testcases131, [],
+ ['ibm-valid-P32-ibm32v01', 'ibm-valid-P32-ibm32v02',
+ 'ibm-valid-P32-ibm32v03', 'ibm-valid-P32-ibm32v04']},
+ {testcases132, [], ['ibm-valid-P33-ibm33v01']},
+ {testcases133, [], ['ibm-valid-P34-ibm34v01']},
+ {testcases134, [], ['ibm-valid-P35-ibm35v01']},
+ {testcases135, [], ['ibm-valid-P36-ibm36v01']},
+ {testcases136, [], ['ibm-valid-P37-ibm37v01']},
+ {testcases137, [], ['ibm-valid-P38-ibm38v01']},
+ {testcases138, [], ['ibm-valid-P39-ibm39v01']},
+ {testcases139, [], ['ibm-valid-P40-ibm40v01']},
+ {testcases140, [], ['ibm-valid-P41-ibm41v01']},
+ {testcases141, [], ['ibm-valid-P42-ibm42v01']},
+ {testcases142, [], ['ibm-valid-P43-ibm43v01']},
+ {testcases143, [], ['ibm-valid-P44-ibm44v01']},
+ {testcases144, [], ['ibm-valid-P45-ibm45v01']},
+ {testcases145, [], ['ibm-valid-P47-ibm47v01']},
+ {testcases146, [], ['ibm-valid-P49-ibm49v01']},
+ {testcases147, [], ['ibm-valid-P50-ibm50v01']},
+ {testcases148, [],
+ ['ibm-valid-P51-ibm51v01', 'ibm-valid-P51-ibm51v02']},
+ {testcases149, [], ['ibm-valid-P52-ibm52v01']},
+ {testcases150, [],
+ ['ibm-valid-P54-ibm54v01', 'ibm-valid-P54-ibm54v02',
+ 'ibm-valid-P54-ibm54v03']},
+ {testcases151, [], ['ibm-valid-P55-ibm55v01']},
+ {testcases152, [],
+ ['ibm-valid-P56-ibm56v01', 'ibm-valid-P56-ibm56v02',
+ 'ibm-valid-P56-ibm56v03', 'ibm-valid-P56-ibm56v04',
+ 'ibm-valid-P56-ibm56v05', 'ibm-valid-P56-ibm56v06',
+ 'ibm-valid-P56-ibm56v07', 'ibm-valid-P56-ibm56v08',
+ 'ibm-valid-P56-ibm56v09', 'ibm-valid-P56-ibm56v10']},
+ {testcases153, [], ['ibm-valid-P57-ibm57v01']},
+ {testcases154, [],
+ ['ibm-valid-P58-ibm58v01', 'ibm-valid-P58-ibm58v02']},
+ {testcases155, [],
+ ['ibm-valid-P59-ibm59v01', 'ibm-valid-P59-ibm59v02']},
+ {testcases156, [],
+ ['ibm-valid-P60-ibm60v01', 'ibm-valid-P60-ibm60v02',
+ 'ibm-valid-P60-ibm60v03', 'ibm-valid-P60-ibm60v04']},
+ {testcases157, [],
+ ['ibm-valid-P61-ibm61v01','ibm-valid-P61-ibm61v02']},
+ {testcases158, [],
+ ['ibm-valid-P62-ibm62v01','ibm-valid-P62-ibm62v02',
+ 'ibm-valid-P62-ibm62v03','ibm-valid-P62-ibm62v04',
+ 'ibm-valid-P62-ibm62v05']},
+ {testcases159, [],
+ ['ibm-valid-P63-ibm63v01','ibm-valid-P63-ibm63v02',
+ 'ibm-valid-P63-ibm63v03','ibm-valid-P63-ibm63v04',
+ 'ibm-valid-P63-ibm63v05']},
+ {testcases160, [],
+ ['ibm-valid-P64-ibm64v01','ibm-valid-P64-ibm64v02',
+ 'ibm-valid-P64-ibm64v03']},
+ {testcases161, [], ['ibm-valid-P65-ibm65v01','ibm-valid-P65-ibm65v02']},
+ {testcases162, [], ['ibm-valid-P66-ibm66v01']},
+ {testcases163, [], ['ibm-valid-P67-ibm67v01']},
+ {testcases164, [],
+ ['ibm-valid-P68-ibm68v01', 'ibm-valid-P68-ibm68v02']},
+ {testcases165, [],
+ ['ibm-valid-P69-ibm69v01', 'ibm-valid-P69-ibm69v02']},
+ {testcases166, [], ['ibm-valid-P70-ibm70v01']},
+ {testcases167, [], ['ibm-valid-P78-ibm78v01']},
+ {testcases168, [], ['ibm-valid-P79-ibm79v01']},
+ {testcases169, [], ['ibm-valid-P82-ibm82v01']},
+ {testcases170, [], ['ibm-valid-P85-ibm85v01']},
+ {testcases171, [], ['ibm-valid-P86-ibm86v01']},
+ {testcases172, [], ['ibm-valid-P87-ibm87v01']},
+ {testcases173, [], ['ibm-valid-P88-ibm88v01']},
+ {testcases174, [], ['ibm-valid-P89-ibm89v01']},
+ {testcases104, [],
+ [{group, testcases105}, {group, testcases106},
+ {group, testcases107}, {group, testcases108},
+ {group, testcases109}, {group, testcases110},
+% {group, testcases111}, {group,testcases112},
+ {group, testcases113},
+ {group, testcases114}, {group, testcases115},
+ {group, testcases116}, {group, testcases117},
+ {group, testcases118}, {group, testcases119},
+ {group, testcases120}, {group, testcases121},
+ {group, testcases122}, {group, testcases123},
+ {group, testcases124}, {group, testcases125},
+ {group, testcases126}, {group, testcases127},
+ {group, testcases128}, {group, testcases129},
+% {group, testcases130},
+ {group, testcases131},
+ {group, testcases132}, {group, testcases133},
+ {group, testcases134}, {group, testcases135},
+ {group, testcases136}, {group, testcases137},
+ {group, testcases138}, {group, testcases139},
+ {group, testcases140}, {group, testcases141},
+ {group, testcases142}, {group, testcases143},
+ {group, testcases144}, {group, testcases145},
+ {group, testcases146}, {group, testcases147},
+ {group, testcases148}, {group, testcases149},
+ {group, testcases150}, {group, testcases151},
+ {group, testcases152}, {group, testcases153},
+ {group, testcases154}, {group, testcases155},
+ {group, testcases156}, % {group, testcases157},
+% {group, testcases158}, {group, testcases159},
+% {group, testcases160}, {group, testcases161},
+ {group, testcases162}, {group, testcases163},
+ {group, testcases164}, {group, testcases165},
+ {group, testcases166}, %{group, testcases167},
+ {group, testcases168}, {group, testcases169},
+% {group, testcases170},
+ {group, testcases171},
+ {group, testcases172}, {group, testcases173},
+ {group, testcases174}]},
+ {testcases8, [],
+ [{group, testcases9}, {group, testcases25},
+ {group, testcases104}]}].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+%%======================================================================
+%% Support Functions
+%%======================================================================
+
+%% Dir is a directory
+rm_f_(Dir) ->
+ ?line {ok,CWD} = file:get_cwd(),
+ ?line {ok,FileList} = file:list_dir(Dir),
+ ?line file:set_cwd(filename:join([CWD,Dir])),
+ rm_files(FileList),
+ ?line file:set_cwd(CWD),
+ ? line ok = file:del_dir(Dir).
+
+rm_files([])->
+ ok;
+rm_files([F|Fs]) ->
+ case filelib:is_dir(F) of
+ true ->
+ rm_f_(F);
+ _ ->
+ ?line ok = file:delete(F)
+ end,
+ rm_files(Fs).
+
+
+change_mode(Files) ->
+ change_mode3(Files).
+change_mode2(Dir)->
+ ?line {ok,CWD} = file:get_cwd(),
+ ?line {ok,FileList} = file:list_dir(Dir),
+ ?line file:set_cwd(filename:join([CWD,Dir])),
+ change_mode3(FileList),
+ ?line file:set_cwd(CWD).
+change_mode3([]) ->
+ ok;
+change_mode3([F|Fs]) ->
+ case filelib:is_dir(F) of
+ true ->
+ chmod(F),
+ change_mode2(F);
+ _ ->
+ chmod(F)
+ end,
+ change_mode3(Fs).
+
+chmod(F) ->
+ case file:read_file_info(F) of
+ {ok,FileInfo} ->
+ Mode= FileInfo#file_info.mode,
+ file:write_file_info(F,FileInfo#file_info{mode=8#00777 bor Mode});
+ _ ->
+ ok
+ end.
+
+%%----------------------------------------------------------------------
+%% check_result
+check_result({fatal_error,_,_,_,_}, "error") ->
+ ok;
+check_result({ok, _, _}, "invalid") ->
+ ok;
+check_result({fatal_error,_,_,_,_}, "not-wf") ->
+ ok;
+check_result({ok, _, _}, "valid") ->
+ ok.
+
diff --git a/lib/xmerl/test/xmerl_std_SUITE.erl b/lib/xmerl/test/xmerl_std_SUITE.erl
new file mode 100644
index 0000000000..c3cc9007d3
--- /dev/null
+++ b/lib/xmerl/test/xmerl_std_SUITE.erl
@@ -0,0 +1,11799 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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(xmerl_std_SUITE).
+
+-compile(export_all).
+
+%%----------------------------------------------------------------------
+%% Include files
+%%----------------------------------------------------------------------
+-include_lib("test_server/include/test_server.hrl").
+%%-include("xmerl.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
+
+-define(ibm_dir,"ibm").
+-define(sun_dir,"sun").
+-define(japanese_dir,"japanese").
+-define(oasis_dir,"oasis").
+-define(xmltest_dir,"xmltest").
+
+%%======================================================================
+%% Tests
+%%======================================================================
+
+%%----------------------------------------------------------------------
+%% Test groups
+%%----------------------------------------------------------------------
+%% totally 1788 test cases
+all() ->
+ ['sun-valid'(suite), 'sun-invalid'(suite),
+ 'sun-not-wf'(suite), 'sun-error'(suite),
+ 'jclark-xmltest'(suite), 'xerox-japanese'(suite),
+ 'nist-oasis'(suite), 'ibm-invalid'(suite),
+ 'ibm-not-wf'(suite), 'ibm-valid'(suite)].
+
+groups() ->
+ [{sun_test_cases, [],
+ 'sun-valid'(suite) ++
+ 'sun-invalid'(suite) ++
+ 'sun-not-wf'(suite) ++ 'sun-error'(suite)},
+ {ibm_test_cases, [],
+ 'ibm-invalid'(suite) ++
+ 'ibm-not-wf'(suite) ++ 'ibm-valid'(suite)},
+ {xmltest_test_cases, [], 'jclark-xmltest'(suite)},
+ {japanese_test_cases, [], 'xerox-japanese'(suite)},
+ {oasis_test_cases, [], 'nist-oasis'(suite)}].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+
+'sun-valid'(suite) -> %% 28 test cases
+ ['v-pe02','v-pe03','v-pe00','v-lang06','v-lang05','v-lang04',
+ 'v-lang03','v-lang02','v-lang01','v-sgml01',sa05,sa04,sa03,sa02,
+ sa01,required00,optional,notation01,'not-sa04','not-sa03',
+ 'not-sa02','not-sa01',ext02,ext01,element,dtd01,dtd00,pe01].
+'sun-invalid'(suite) -> %% 74 test cases
+ [empty,utf16l,utf16b,attr16,attr15,attr14,attr13,attr12,attr11,
+ attr10,attr09,attr08,attr07,attr06,attr05,attr04,attr03,attr02,
+ attr01,root,'inv-required02','inv-required01','inv-required00',
+ optional25,optional24,optional23,optional22,optional21,optional20,
+ optional14,optional13,optional12,optional11,optional10,optional09,
+ optional08,optional07,optional06,optional05,optional04,optional03,
+ optional02,optional01,'inv-not-sa14','inv-not-sa13','inv-not-sa12',
+ 'inv-not-sa11','inv-not-sa10','inv-not-sa09','inv-not-sa08',
+ 'inv-not-sa07','inv-not-sa06','inv-not-sa05','inv-not-sa04',
+ 'inv-not-sa02','inv-not-sa01',id09,id08,id07,id06,id05,id04,id03,
+ id02,id01,el06,el05,el04,el03,el02,el01,'inv-dtd03','inv-dtd02',
+ 'inv-dtd01'].
+'sun-not-wf'(suite)-> %% 56 test cases
+ [sgml13,sgml12,sgml11,sgml10,sgml09,sgml08,sgml07,sgml06,sgml05,
+ sgml04,sgml03,sgml02,sgml01,pubid05,pubid04,pubid03,pubid02,pubid01,
+ pi,encoding07,encoding06,encoding05,encoding04,encoding03,encoding02,
+ encoding01,element04,element03,element02,element01,element00,dtd07,
+ dtd05,dtd04,dtd03,dtd02,'nwf-dtd01','nwf-dtd00',decl01,content03,
+ content02,content01,cond02,cond01,attlist11,attlist10,attlist09,
+ attlist08,attlist07,attlist06,attlist05,attlist04,attlist03,
+ attlist02,attlist01,'not-wf-sa03'].
+'sun-error'(suite)->
+ %% 1 test case
+ [uri01].
+'jclark-xmltest'(suite) ->
+ %% 364 test cases
+ ['valid-ext-sa-014','valid-ext-sa-013','valid-ext-sa-012',
+ 'valid-ext-sa-011','valid-ext-sa-009','valid-ext-sa-008',
+ 'valid-ext-sa-007','valid-ext-sa-006','valid-ext-sa-005',
+ 'valid-ext-sa-004','valid-ext-sa-003','valid-ext-sa-002',
+ 'valid-ext-sa-001','valid-not-sa-031','valid-not-sa-030',
+ 'valid-not-sa-029','valid-not-sa-028','valid-not-sa-027',
+ 'valid-not-sa-026','valid-not-sa-025','valid-not-sa-024',
+ 'valid-not-sa-023','valid-not-sa-021','valid-not-sa-020',
+ 'valid-not-sa-019','valid-not-sa-018','valid-not-sa-017',
+ 'valid-not-sa-016','valid-not-sa-015','valid-not-sa-014',
+ 'valid-not-sa-013','valid-not-sa-012','valid-not-sa-011',
+ 'valid-not-sa-010','valid-not-sa-009','valid-not-sa-008',
+ 'valid-not-sa-007','valid-not-sa-006','valid-not-sa-005',
+ 'valid-not-sa-004','valid-not-sa-003','valid-not-sa-002',
+ 'valid-not-sa-001','valid-sa-119','valid-sa-118','valid-sa-117',
+ 'valid-sa-116','valid-sa-115','valid-sa-114','valid-sa-113',
+ 'valid-sa-112','valid-sa-111','valid-sa-110','valid-sa-109',
+ 'valid-sa-108','valid-sa-107','valid-sa-106','valid-sa-105',
+ 'valid-sa-104','valid-sa-103','valid-sa-102','valid-sa-101',
+ 'valid-sa-100','valid-sa-099','valid-sa-098','valid-sa-097',
+ 'valid-sa-096','valid-sa-095','valid-sa-094','valid-sa-093',
+ 'valid-sa-092','valid-sa-091','valid-sa-090','valid-sa-089',
+ 'valid-sa-088','valid-sa-087','valid-sa-086','valid-sa-085',
+ 'valid-sa-084','valid-sa-083','valid-sa-082','valid-sa-081',
+ 'valid-sa-080','valid-sa-079','valid-sa-078','valid-sa-077',
+ 'valid-sa-076','valid-sa-075','valid-sa-074','valid-sa-073',
+ 'valid-sa-072','valid-sa-071','valid-sa-070','valid-sa-069',
+ 'valid-sa-068','valid-sa-067','valid-sa-066','valid-sa-065',
+ 'valid-sa-064','valid-sa-063','valid-sa-062','valid-sa-061',
+ 'valid-sa-060','valid-sa-059','valid-sa-058','valid-sa-057',
+ 'valid-sa-056','valid-sa-055','valid-sa-054','valid-sa-053',
+ 'valid-sa-052','valid-sa-051','valid-sa-050','valid-sa-049',
+ 'valid-sa-048','valid-sa-047','valid-sa-046','valid-sa-045',
+ 'valid-sa-044','valid-sa-043','valid-sa-042','valid-sa-041',
+ 'valid-sa-040','valid-sa-039','valid-sa-038','valid-sa-037',
+ 'valid-sa-036','valid-sa-035','valid-sa-034','valid-sa-033',
+ 'valid-sa-032','valid-sa-031','valid-sa-030','valid-sa-029',
+ 'valid-sa-028','valid-sa-027','valid-sa-026','valid-sa-025',
+ 'valid-sa-024','valid-sa-023','valid-sa-022','valid-sa-021',
+ 'valid-sa-020','valid-sa-019','valid-sa-018','valid-sa-017',
+ 'valid-sa-016','valid-sa-015','valid-sa-014','valid-sa-013',
+ 'valid-sa-012','valid-sa-011','valid-sa-010','valid-sa-009',
+ 'valid-sa-008','valid-sa-007','valid-sa-006','valid-sa-005',
+ 'valid-sa-004','valid-sa-003','valid-sa-002','valid-sa-001',
+ 'invalid-not-sa-022','invalid--006','invalid--005','invalid--002',
+ 'not-wf-ext-sa-003','not-wf-ext-sa-002','not-wf-ext-sa-001',
+ 'not-wf-not-sa-009','not-wf-not-sa-008','not-wf-not-sa-007',
+ 'not-wf-not-sa-006','not-wf-not-sa-005','not-wf-not-sa-004',
+ 'not-wf-not-sa-003','not-wf-not-sa-002','not-wf-not-sa-001',
+ 'not-wf-sa-186','not-wf-sa-185','not-wf-sa-184','not-wf-sa-183',
+ 'not-wf-sa-182','not-wf-sa-181','not-wf-sa-180','not-wf-sa-179',
+ 'not-wf-sa-178','not-wf-sa-177','not-wf-sa-176','not-wf-sa-175',
+ 'not-wf-sa-174','not-wf-sa-173','not-wf-sa-172','not-wf-sa-171',
+ 'not-wf-sa-170','not-wf-sa-169','not-wf-sa-168','not-wf-sa-167',
+ 'not-wf-sa-166','not-wf-sa-165','not-wf-sa-164','not-wf-sa-163',
+ 'not-wf-sa-162','not-wf-sa-161','not-wf-sa-160','not-wf-sa-159',
+ 'not-wf-sa-158','not-wf-sa-157','not-wf-sa-156','not-wf-sa-155',
+ 'not-wf-sa-154','not-wf-sa-153','not-wf-sa-152','not-wf-sa-151',
+ 'not-wf-sa-150','not-wf-sa-149','not-wf-sa-148','not-wf-sa-147',
+ 'not-wf-sa-146','not-wf-sa-145','not-wf-sa-144','not-wf-sa-143',
+ 'not-wf-sa-142','not-wf-sa-141','not-wf-sa-140','not-wf-sa-139',
+ 'not-wf-sa-138','not-wf-sa-137','not-wf-sa-136','not-wf-sa-135',
+ 'not-wf-sa-134','not-wf-sa-133','not-wf-sa-132','not-wf-sa-131',
+ 'not-wf-sa-130','not-wf-sa-129','not-wf-sa-128','not-wf-sa-127',
+ 'not-wf-sa-126','not-wf-sa-125','not-wf-sa-124','not-wf-sa-123',
+ 'not-wf-sa-122','not-wf-sa-121','not-wf-sa-120','not-wf-sa-119',
+ 'not-wf-sa-118','not-wf-sa-117','not-wf-sa-116','not-wf-sa-115',
+ 'not-wf-sa-114','not-wf-sa-113','not-wf-sa-112','not-wf-sa-111',
+ 'not-wf-sa-110','not-wf-sa-109','not-wf-sa-108','not-wf-sa-107',
+ 'not-wf-sa-106','not-wf-sa-105','not-wf-sa-104','not-wf-sa-103',
+ 'not-wf-sa-102','not-wf-sa-101','not-wf-sa-100','not-wf-sa-099',
+ 'not-wf-sa-098','not-wf-sa-097','not-wf-sa-096','not-wf-sa-095',
+ 'not-wf-sa-094','not-wf-sa-093','not-wf-sa-092','not-wf-sa-091',
+ 'not-wf-sa-090','not-wf-sa-089','not-wf-sa-088','not-wf-sa-087',
+ 'not-wf-sa-086','not-wf-sa-085','not-wf-sa-084','not-wf-sa-083',
+ 'not-wf-sa-082','not-wf-sa-081','not-wf-sa-080','not-wf-sa-079',
+ 'not-wf-sa-078','not-wf-sa-077','not-wf-sa-076','not-wf-sa-075',
+ 'not-wf-sa-074','not-wf-sa-073','not-wf-sa-072','not-wf-sa-071',
+ 'not-wf-sa-070','not-wf-sa-069','not-wf-sa-068','not-wf-sa-067',
+ 'not-wf-sa-066','not-wf-sa-065','not-wf-sa-064','not-wf-sa-063',
+ 'not-wf-sa-062','not-wf-sa-061','not-wf-sa-060','not-wf-sa-059',
+ 'not-wf-sa-058','not-wf-sa-057','not-wf-sa-056','not-wf-sa-055',
+ 'not-wf-sa-054','not-wf-sa-053','not-wf-sa-052','not-wf-sa-051',
+ 'not-wf-sa-050','not-wf-sa-049','not-wf-sa-048','not-wf-sa-047',
+ 'not-wf-sa-046','not-wf-sa-045','not-wf-sa-044','not-wf-sa-043',
+ 'not-wf-sa-042','not-wf-sa-041','not-wf-sa-040','not-wf-sa-039',
+ 'not-wf-sa-038','not-wf-sa-037','not-wf-sa-036','not-wf-sa-035',
+ 'not-wf-sa-034','not-wf-sa-033','not-wf-sa-032','not-wf-sa-031',
+ 'not-wf-sa-030','not-wf-sa-029','not-wf-sa-028','not-wf-sa-027',
+ 'not-wf-sa-026','not-wf-sa-025','not-wf-sa-024','not-wf-sa-023',
+ 'not-wf-sa-022','not-wf-sa-021','not-wf-sa-020','not-wf-sa-019',
+ 'not-wf-sa-018','not-wf-sa-017','not-wf-sa-016','not-wf-sa-015',
+ 'not-wf-sa-014','not-wf-sa-013','not-wf-sa-012','not-wf-sa-011',
+ 'not-wf-sa-010','not-wf-sa-009','not-wf-sa-008','not-wf-sa-007',
+ 'not-wf-sa-006','not-wf-sa-005','not-wf-sa-004','not-wf-sa-003',
+ 'not-wf-sa-002','not-wf-sa-001'].
+'xerox-japanese'(suite) ->
+ %% 12 test cases
+ ['japanese-weekly-utf-8','japanese-weekly-utf-16',
+ 'japanese-weekly-shift_jis','japanese-weekly-little',
+ 'japanese-weekly-iso-2022-jp','japanese-weekly-euc-jp',
+ 'japanese-pr-xml-utf-8','japanese-pr-xml-utf-16',
+ 'japanese-pr-xml-shift_jis','japanese-pr-xml-little',
+ 'japanese-pr-xml-iso-2022-jp','japanese-pr-xml-euc-jp'].
+'nist-oasis'(suite) ->
+ %% 348 test cases
+ ['o-p11pass1','o-p76fail4','o-p76fail3','o-p76fail2','o-p76fail1',
+ 'o-p75fail6','o-p75fail5','o-p75fail4','o-p75fail3','o-p75fail2',
+ 'o-p75fail1','o-p74fail3','o-p74fail2','o-p74fail1','o-p73fail5',
+ 'o-p73fail4','o-p73fail3','o-p73fail2','o-p73fail1','o-p72fail4',
+ 'o-p72fail3','o-p72fail2','o-p72fail1','o-p71fail4','o-p71fail3',
+ 'o-p71fail2','o-p71fail1','o-p70fail1','o-p69fail3','o-p69fail2',
+ 'o-p69fail1','o-p68fail3','o-p68fail2','o-p68fail1','o-p66fail6',
+ 'o-p66fail5','o-p66fail4','o-p66fail3','o-p66fail2','o-p66fail1',
+ 'o-p64fail2','o-p64fail1','o-p63fail2','o-p63fail1','o-p62fail2',
+ 'o-p62fail1','o-p61fail1','o-p60fail5','o-p60fail4','o-p60fail3',
+ 'o-p60fail2','o-p60fail1','o-p59fail3','o-p59fail2','o-p59fail1',
+ 'o-p58fail8','o-p58fail7','o-p58fail6','o-p58fail5','o-p58fail4',
+ 'o-p58fail3','o-p58fail2','o-p58fail1','o-p57fail1','o-p56fail5',
+ 'o-p56fail4','o-p56fail3','o-p56fail2','o-p56fail1','o-p55fail1',
+ 'o-p54fail1','o-p53fail5','o-p53fail4','o-p53fail3','o-p53fail2',
+ 'o-p53fail1','o-p52fail2','o-p52fail1','o-p51fail7','o-p51fail6',
+ 'o-p51fail5','o-p51fail4','o-p51fail3','o-p51fail2','o-p51fail1',
+ 'o-p50fail1','o-p49fail1','o-p48fail2','o-p48fail1','o-p47fail4',
+ 'o-p47fail3','o-p47fail2','o-p47fail1','o-p46fail6','o-p46fail5',
+ 'o-p46fail4','o-p46fail3','o-p46fail2','o-p46fail1','o-p45fail4',
+ 'o-p45fail3','o-p45fail2','o-p45fail1','o-p44fail5','o-p44fail4',
+ 'o-p44fail3','o-p44fail2','o-p44fail1','o-p43fail3','o-p43fail2',
+ 'o-p43fail1','o-p42fail3','o-p42fail2','o-p42fail1','o-p41fail3',
+ 'o-p41fail2','o-p41fail1','o-p40fail4','o-p40fail3','o-p40fail2',
+ 'o-p40fail1','o-p39fail5','o-p39fail4','o-p39fail3','o-p39fail2',
+ 'o-p39fail1','o-p32fail5','o-p32fail4','o-p32fail3','o-p32fail2',
+ 'o-p32fail1','o-p31fail1','o-p30fail1','o-p29fail1','o-p28fail1',
+ 'o-p27fail1','o-p26fail2','o-p26fail1','o-p25fail1','o-p24fail2',
+ 'o-p24fail1','o-p23fail5','o-p23fail4','o-p23fail3','o-p23fail2',
+ 'o-p23fail1','o-p22fail2','o-p22fail1','o-p18fail3','o-p18fail2',
+ 'o-p18fail1','o-p16fail3','o-p16fail2','o-p16fail1','o-p15fail3',
+ 'o-p15fail2','o-p15fail1','o-p14fail3','o-p14fail2','o-p14fail1',
+ 'o-p12fail7','o-p12fail6','o-p12fail5','o-p12fail4','o-p12fail3',
+ 'o-p12fail2','o-p12fail1','o-p11fail2','o-p11fail1','o-p10fail3',
+ 'o-p10fail2','o-p10fail1','o-p09fail5','o-p09fail4','o-p09fail3',
+ 'o-p09fail2','o-p09fail1','o-p05fail5','o-p05fail4','o-p05fail3',
+ 'o-p05fail2','o-p05fail1','o-p04fail3','o-p04fail2','o-p04fail1',
+ 'o-p03fail9','o-p03fail8','o-p03fail7','o-p03fail5','o-p03fail4',
+ 'o-p03fail3','o-p03fail29','o-p03fail28','o-p03fail27','o-p03fail26',
+ 'o-p03fail25','o-p03fail24','o-p03fail23','o-p03fail22','o-p03fail21',
+ 'o-p03fail20','o-p03fail2','o-p03fail19','o-p03fail18','o-p03fail17',
+ 'o-p03fail16','o-p03fail15','o-p03fail14','o-p03fail13','o-p03fail12',
+ 'o-p03fail11','o-p03fail10','o-p03fail1','o-p02fail9','o-p02fail8',
+ 'o-p02fail7','o-p02fail6','o-p02fail5','o-p02fail4','o-p02fail31',
+ 'o-p02fail30','o-p02fail3','o-p02fail29','o-p02fail28','o-p02fail27',
+ 'o-p02fail26','o-p02fail25','o-p02fail24','o-p02fail23','o-p02fail22',
+ 'o-p02fail21','o-p02fail20','o-p02fail2','o-p02fail19','o-p02fail18',
+ 'o-p02fail17','o-p02fail16','o-p02fail15','o-p02fail14','o-p02fail13',
+ 'o-p02fail12','o-p02fail11','o-p02fail10','o-p02fail1','o-p01fail4',
+ 'o-p01fail3','o-p01fail2','o-p01fail1','o-e2','o-p75pass1',
+ 'o-p74pass1','o-p66pass1','o-p44pass5','o-p44pass4','o-p44pass3',
+ 'o-p44pass2','o-p44pass1','o-p42pass2','o-p42pass1','o-p41pass2',
+ 'o-p41pass1','o-p40pass4','o-p40pass3','o-p40pass2','o-p40pass1',
+ 'o-p39pass2','o-p39pass1','o-p32pass2','o-p32pass1','o-p27pass4',
+ 'o-p27pass3','o-p27pass2','o-p27pass1','o-p26pass1','o-p25pass2',
+ 'o-p25pass1','o-p24pass4','o-p24pass3','o-p24pass2','o-p24pass1',
+ 'o-p23pass4','o-p23pass3','o-p23pass2','o-p23pass1','o-p22pass3',
+ 'o-p22pass2','o-p22pass1','o-p18pass1','o-p16pass3','o-p16pass2',
+ 'o-p16pass1','o-p15pass1','o-p14pass1','o-p10pass1','o-p08fail2',
+ 'o-p08fail1','o-p06fail1','o-p05pass1','o-p04pass1','o-p03pass1',
+ 'o-p01pass3','o-p01pass1','o-p76pass1','o-p73pass1','o-p72pass1',
+ 'o-p71pass1','o-p70pass1','o-p69pass1','o-p68pass1','o-p64pass1',
+ 'o-p63pass1','o-p62pass1','o-p61pass1','o-p60pass1','o-p59pass1',
+ 'o-p58pass1','o-p57pass1','o-p56pass1','o-p55pass1','o-p54pass1',
+ 'o-p53pass1','o-p52pass1','o-p51pass1','o-p50pass1','o-p49pass1',
+ 'o-p48pass1','o-p47pass1','o-p46pass1','o-p45pass1','o-p43pass1',
+ 'o-p31pass2','o-p31pass1','o-p30pass2','o-p30pass1','o-p29pass1',
+ 'o-p28pass5','o-p28pass4','o-p28pass3','o-p28pass1','o-p22pass6',
+ 'o-p22pass5','o-p22pass4','o-p12pass1','o-p09pass1','o-p08pass1',
+ 'o-p07pass1','o-p06pass1','o-p01pass2'].
+'ibm-invalid'(suite) ->
+ %% 48 test cases
+ ['ibm-invalid-P76-ibm76i01','ibm-invalid-P69-ibm69i04',
+ 'ibm-invalid-P69-ibm69i03','ibm-invalid-P69-ibm69i02',
+ 'ibm-invalid-P69-ibm69i01','ibm-invalid-P68-ibm68i04',
+ 'ibm-invalid-P68-ibm68i03','ibm-invalid-P68-ibm68i02',
+ 'ibm-invalid-P68-ibm68i01','ibm-invalid-P60-ibm60i04',
+ 'ibm-invalid-P60-ibm60i03','ibm-invalid-P60-ibm60i02',
+ 'ibm-invalid-P60-ibm60i01','ibm-invalid-P59-ibm59i01',
+ 'ibm-invalid-P58-ibm58i02','ibm-invalid-P58-ibm58i01',
+ 'ibm-invalid-P56-ibm56i18','ibm-invalid-P56-ibm56i17',
+ 'ibm-invalid-P56-ibm56i16','ibm-invalid-P56-ibm56i15',
+ 'ibm-invalid-P56-ibm56i14','ibm-invalid-P56-ibm56i13',
+ 'ibm-invalid-P56-ibm56i12','ibm-invalid-P56-ibm56i11',
+ 'ibm-invalid-P56-ibm56i10','ibm-invalid-P56-ibm56i09',
+ 'ibm-invalid-P56-ibm56i08','ibm-invalid-P56-ibm56i07',
+ 'ibm-invalid-P56-ibm56i06','ibm-invalid-P56-ibm56i05',
+ 'ibm-invalid-P56-ibm56i03','ibm-invalid-P56-ibm56i02',
+ 'ibm-invalid-P56-ibm56i01','ibm-invalid-P51-ibm51i03',
+ 'ibm-invalid-P51-ibm51i01','ibm-invalid-P50-ibm50i01',
+ 'ibm-invalid-P49-ibm49i01','ibm-invalid-P45-ibm45i01',
+ 'ibm-invalid-P41-ibm41i02','ibm-invalid-P41-ibm41i01',
+ 'ibm-invalid-P39-ibm39i04','ibm-invalid-P39-ibm39i03',
+ 'ibm-invalid-P39-ibm39i02','ibm-invalid-P39-ibm39i01',
+ 'ibm-invalid-P32-ibm32i04','ibm-invalid-P32-ibm32i03',
+ 'ibm-invalid-P32-ibm32i01','ibm-invalid-P28-ibm28i01'].
+'ibm-not-wf'(suite) ->
+ %% 731 test cases
+ ['ibm-not-wf-P89-ibm89n12','ibm-not-wf-P89-ibm89n11',
+ 'ibm-not-wf-P89-ibm89n10','ibm-not-wf-P89-ibm89n09',
+ 'ibm-not-wf-P89-ibm89n08','ibm-not-wf-P89-ibm89n07',
+ 'ibm-not-wf-P89-ibm89n06','ibm-not-wf-P89-ibm89n05',
+ 'ibm-not-wf-P89-ibm89n04','ibm-not-wf-P89-ibm89n03',
+ 'ibm-not-wf-P89-ibm89n02','ibm-not-wf-P89-ibm89n01',
+ 'ibm-not-wf-P88-ibm88n16','ibm-not-wf-P88-ibm88n15',
+ 'ibm-not-wf-P88-ibm88n14','ibm-not-wf-P88-ibm88n13',
+ 'ibm-not-wf-P88-ibm88n12','ibm-not-wf-P88-ibm88n11',
+ 'ibm-not-wf-P88-ibm88n10','ibm-not-wf-P88-ibm88n09',
+ 'ibm-not-wf-P88-ibm88n08','ibm-not-wf-P88-ibm88n06',
+ 'ibm-not-wf-P88-ibm88n05','ibm-not-wf-P88-ibm88n04',
+ 'ibm-not-wf-P88-ibm88n03','ibm-not-wf-P88-ibm88n02',
+ 'ibm-not-wf-P88-ibm88n01','ibm-not-wf-P87-ibm87n85',
+ 'ibm-not-wf-P87-ibm87n84','ibm-not-wf-P87-ibm87n83',
+ 'ibm-not-wf-P87-ibm87n82','ibm-not-wf-P87-ibm87n81',
+ 'ibm-not-wf-P87-ibm87n80','ibm-not-wf-P87-ibm87n79',
+ 'ibm-not-wf-P87-ibm87n78','ibm-not-wf-P87-ibm87n77',
+ 'ibm-not-wf-P87-ibm87n76','ibm-not-wf-P87-ibm87n75',
+ 'ibm-not-wf-P87-ibm87n74','ibm-not-wf-P87-ibm87n73',
+ 'ibm-not-wf-P87-ibm87n72','ibm-not-wf-P87-ibm87n71',
+ 'ibm-not-wf-P87-ibm87n70','ibm-not-wf-P87-ibm87n69',
+ 'ibm-not-wf-P87-ibm87n68','ibm-not-wf-P87-ibm87n67',
+ 'ibm-not-wf-P87-ibm87n66','ibm-not-wf-P87-ibm87n64',
+ 'ibm-not-wf-P87-ibm87n63','ibm-not-wf-P87-ibm87n62',
+ 'ibm-not-wf-P87-ibm87n61','ibm-not-wf-P87-ibm87n60',
+ 'ibm-not-wf-P87-ibm87n59','ibm-not-wf-P87-ibm87n58',
+ 'ibm-not-wf-P87-ibm87n57','ibm-not-wf-P87-ibm87n56',
+ 'ibm-not-wf-P87-ibm87n55','ibm-not-wf-P87-ibm87n54',
+ 'ibm-not-wf-P87-ibm87n53','ibm-not-wf-P87-ibm87n52',
+ 'ibm-not-wf-P87-ibm87n51','ibm-not-wf-P87-ibm87n50',
+ 'ibm-not-wf-P87-ibm87n49','ibm-not-wf-P87-ibm87n48',
+ 'ibm-not-wf-P87-ibm87n47','ibm-not-wf-P87-ibm87n46',
+ 'ibm-not-wf-P87-ibm87n45','ibm-not-wf-P87-ibm87n44',
+ 'ibm-not-wf-P87-ibm87n43','ibm-not-wf-P87-ibm87n42',
+ 'ibm-not-wf-P87-ibm87n41','ibm-not-wf-P87-ibm87n40',
+ 'ibm-not-wf-P87-ibm87n39','ibm-not-wf-P87-ibm87n38',
+ 'ibm-not-wf-P87-ibm87n37','ibm-not-wf-P87-ibm87n36',
+ 'ibm-not-wf-P87-ibm87n35','ibm-not-wf-P87-ibm87n34',
+ 'ibm-not-wf-P87-ibm87n33','ibm-not-wf-P87-ibm87n32',
+ 'ibm-not-wf-P87-ibm87n31','ibm-not-wf-P87-ibm87n30',
+ 'ibm-not-wf-P87-ibm87n29','ibm-not-wf-P87-ibm87n28',
+ 'ibm-not-wf-P87-ibm87n27','ibm-not-wf-P87-ibm87n26',
+ 'ibm-not-wf-P87-ibm87n25','ibm-not-wf-P87-ibm87n24',
+ 'ibm-not-wf-P87-ibm87n23','ibm-not-wf-P87-ibm87n22',
+ 'ibm-not-wf-P87-ibm87n21','ibm-not-wf-P87-ibm87n20',
+ 'ibm-not-wf-P87-ibm87n19','ibm-not-wf-P87-ibm87n18',
+ 'ibm-not-wf-P87-ibm87n17','ibm-not-wf-P87-ibm87n16',
+ 'ibm-not-wf-P87-ibm87n15','ibm-not-wf-P87-ibm87n14',
+ 'ibm-not-wf-P87-ibm87n13','ibm-not-wf-P87-ibm87n12',
+ 'ibm-not-wf-P87-ibm87n11','ibm-not-wf-P87-ibm87n10',
+ 'ibm-not-wf-P87-ibm87n09','ibm-not-wf-P87-ibm87n08',
+ 'ibm-not-wf-P87-ibm87n07','ibm-not-wf-P87-ibm87n06',
+ 'ibm-not-wf-P87-ibm87n05','ibm-not-wf-P87-ibm87n04',
+ 'ibm-not-wf-P87-ibm87n03','ibm-not-wf-P87-ibm87n02',
+ 'ibm-not-wf-P87-ibm87n01','ibm-not-wf-P86-ibm86n04',
+ 'ibm-not-wf-P86-ibm86n03','ibm-not-wf-P86-ibm86n02',
+ 'ibm-not-wf-P86-ibm86n01','ibm-not-wf-P85-ibm85n99',
+ 'ibm-not-wf-P85-ibm85n98','ibm-not-wf-P85-ibm85n97',
+ 'ibm-not-wf-P85-ibm85n96','ibm-not-wf-P85-ibm85n95',
+ 'ibm-not-wf-P85-ibm85n94','ibm-not-wf-P85-ibm85n93',
+ 'ibm-not-wf-P85-ibm85n92','ibm-not-wf-P85-ibm85n91',
+ 'ibm-not-wf-P85-ibm85n90','ibm-not-wf-P85-ibm85n89',
+ 'ibm-not-wf-P85-ibm85n88','ibm-not-wf-P85-ibm85n87',
+ 'ibm-not-wf-P85-ibm85n86','ibm-not-wf-P85-ibm85n85',
+ 'ibm-not-wf-P85-ibm85n84','ibm-not-wf-P85-ibm85n83',
+ 'ibm-not-wf-P85-ibm85n82','ibm-not-wf-P85-ibm85n81',
+ 'ibm-not-wf-P85-ibm85n80','ibm-not-wf-P85-ibm85n79',
+ 'ibm-not-wf-P85-ibm85n78','ibm-not-wf-P85-ibm85n77',
+ 'ibm-not-wf-P85-ibm85n76','ibm-not-wf-P85-ibm85n75',
+ 'ibm-not-wf-P85-ibm85n74','ibm-not-wf-P85-ibm85n73',
+ 'ibm-not-wf-P85-ibm85n72','ibm-not-wf-P85-ibm85n71',
+ 'ibm-not-wf-P85-ibm85n70','ibm-not-wf-P85-ibm85n69',
+ 'ibm-not-wf-P85-ibm85n68','ibm-not-wf-P85-ibm85n67',
+ 'ibm-not-wf-P85-ibm85n66','ibm-not-wf-P85-ibm85n65',
+ 'ibm-not-wf-P85-ibm85n64','ibm-not-wf-P85-ibm85n63',
+ 'ibm-not-wf-P85-ibm85n62','ibm-not-wf-P85-ibm85n61',
+ 'ibm-not-wf-P85-ibm85n60','ibm-not-wf-P85-ibm85n59',
+ 'ibm-not-wf-P85-ibm85n58','ibm-not-wf-P85-ibm85n57',
+ 'ibm-not-wf-P85-ibm85n56','ibm-not-wf-P85-ibm85n55',
+ 'ibm-not-wf-P85-ibm85n54','ibm-not-wf-P85-ibm85n53',
+ 'ibm-not-wf-P85-ibm85n52','ibm-not-wf-P85-ibm85n51',
+ 'ibm-not-wf-P85-ibm85n50','ibm-not-wf-P85-ibm85n49',
+ 'ibm-not-wf-P85-ibm85n48','ibm-not-wf-P85-ibm85n47',
+ 'ibm-not-wf-P85-ibm85n46','ibm-not-wf-P85-ibm85n45',
+ 'ibm-not-wf-P85-ibm85n44','ibm-not-wf-P85-ibm85n43',
+ 'ibm-not-wf-P85-ibm85n42','ibm-not-wf-P85-ibm85n41',
+ 'ibm-not-wf-P85-ibm85n40','ibm-not-wf-P85-ibm85n39',
+ 'ibm-not-wf-P85-ibm85n38','ibm-not-wf-P85-ibm85n37',
+ 'ibm-not-wf-P85-ibm85n36','ibm-not-wf-P85-ibm85n35',
+ 'ibm-not-wf-P85-ibm85n34','ibm-not-wf-P85-ibm85n33',
+ 'ibm-not-wf-P85-ibm85n32','ibm-not-wf-P85-ibm85n31',
+ 'ibm-not-wf-P85-ibm85n30','ibm-not-wf-P85-ibm85n29',
+ 'ibm-not-wf-P85-ibm85n28','ibm-not-wf-P85-ibm85n27',
+ 'ibm-not-wf-P85-ibm85n26','ibm-not-wf-P85-ibm85n25',
+ 'ibm-not-wf-P85-ibm85n24','ibm-not-wf-P85-ibm85n23',
+ 'ibm-not-wf-P85-ibm85n22','ibm-not-wf-P85-ibm85n21',
+ 'ibm-not-wf-P85-ibm85n20','ibm-not-wf-P85-ibm85n198',
+ 'ibm-not-wf-P85-ibm85n197','ibm-not-wf-P85-ibm85n196',
+ 'ibm-not-wf-P85-ibm85n195','ibm-not-wf-P85-ibm85n194',
+ 'ibm-not-wf-P85-ibm85n193','ibm-not-wf-P85-ibm85n192',
+ 'ibm-not-wf-P85-ibm85n191','ibm-not-wf-P85-ibm85n190',
+ 'ibm-not-wf-P85-ibm85n19','ibm-not-wf-P85-ibm85n189',
+ 'ibm-not-wf-P85-ibm85n188','ibm-not-wf-P85-ibm85n187',
+ 'ibm-not-wf-P85-ibm85n186','ibm-not-wf-P85-ibm85n185',
+ 'ibm-not-wf-P85-ibm85n184','ibm-not-wf-P85-ibm85n183',
+ 'ibm-not-wf-P85-ibm85n182','ibm-not-wf-P85-ibm85n181',
+ 'ibm-not-wf-P85-ibm85n180','ibm-not-wf-P85-ibm85n18',
+ 'ibm-not-wf-P85-ibm85n179','ibm-not-wf-P85-ibm85n178',
+ 'ibm-not-wf-P85-ibm85n177','ibm-not-wf-P85-ibm85n176',
+ 'ibm-not-wf-P85-ibm85n175','ibm-not-wf-P85-ibm85n174',
+ 'ibm-not-wf-P85-ibm85n173','ibm-not-wf-P85-ibm85n172',
+ 'ibm-not-wf-P85-ibm85n171','ibm-not-wf-P85-ibm85n170',
+ 'ibm-not-wf-P85-ibm85n17','ibm-not-wf-P85-ibm85n169',
+ 'ibm-not-wf-P85-ibm85n168','ibm-not-wf-P85-ibm85n167',
+ 'ibm-not-wf-P85-ibm85n166','ibm-not-wf-P85-ibm85n165',
+ 'ibm-not-wf-P85-ibm85n164','ibm-not-wf-P85-ibm85n163',
+ 'ibm-not-wf-P85-ibm85n162','ibm-not-wf-P85-ibm85n161',
+ 'ibm-not-wf-P85-ibm85n160','ibm-not-wf-P85-ibm85n16',
+ 'ibm-not-wf-P85-ibm85n159','ibm-not-wf-P85-ibm85n158',
+ 'ibm-not-wf-P85-ibm85n157','ibm-not-wf-P85-ibm85n156',
+ 'ibm-not-wf-P85-ibm85n155','ibm-not-wf-P85-ibm85n154',
+ 'ibm-not-wf-P85-ibm85n153','ibm-not-wf-P85-ibm85n152',
+ 'ibm-not-wf-P85-ibm85n151','ibm-not-wf-P85-ibm85n150',
+ 'ibm-not-wf-P85-ibm85n15','ibm-not-wf-P85-ibm85n149',
+ 'ibm-not-wf-P85-ibm85n148','ibm-not-wf-P85-ibm85n147',
+ 'ibm-not-wf-P85-ibm85n146','ibm-not-wf-P85-ibm85n145',
+ 'ibm-not-wf-P85-ibm85n144','ibm-not-wf-P85-ibm85n143',
+ 'ibm-not-wf-P85-ibm85n142','ibm-not-wf-P85-ibm85n141',
+ 'ibm-not-wf-P85-ibm85n140','ibm-not-wf-P85-ibm85n14',
+ 'ibm-not-wf-P85-ibm85n139','ibm-not-wf-P85-ibm85n138',
+ 'ibm-not-wf-P85-ibm85n137','ibm-not-wf-P85-ibm85n136',
+ 'ibm-not-wf-P85-ibm85n135','ibm-not-wf-P85-ibm85n134',
+ 'ibm-not-wf-P85-ibm85n133','ibm-not-wf-P85-ibm85n132',
+ 'ibm-not-wf-P85-ibm85n131','ibm-not-wf-P85-ibm85n130',
+ 'ibm-not-wf-P85-ibm85n13','ibm-not-wf-P85-ibm85n129',
+ 'ibm-not-wf-P85-ibm85n128','ibm-not-wf-P85-ibm85n127',
+ 'ibm-not-wf-P85-ibm85n126','ibm-not-wf-P85-ibm85n125',
+ 'ibm-not-wf-P85-ibm85n124','ibm-not-wf-P85-ibm85n123',
+ 'ibm-not-wf-P85-ibm85n122','ibm-not-wf-P85-ibm85n121',
+ 'ibm-not-wf-P85-ibm85n120','ibm-not-wf-P85-ibm85n12',
+ 'ibm-not-wf-P85-ibm85n119','ibm-not-wf-P85-ibm85n118',
+ 'ibm-not-wf-P85-ibm85n117','ibm-not-wf-P85-ibm85n116',
+ 'ibm-not-wf-P85-ibm85n115','ibm-not-wf-P85-ibm85n114',
+ 'ibm-not-wf-P85-ibm85n113','ibm-not-wf-P85-ibm85n112',
+ 'ibm-not-wf-P85-ibm85n111','ibm-not-wf-P85-ibm85n110',
+ 'ibm-not-wf-P85-ibm85n11','ibm-not-wf-P85-ibm85n109',
+ 'ibm-not-wf-P85-ibm85n108','ibm-not-wf-P85-ibm85n107',
+ 'ibm-not-wf-P85-ibm85n106','ibm-not-wf-P85-ibm85n105',
+ 'ibm-not-wf-P85-ibm85n104','ibm-not-wf-P85-ibm85n103',
+ 'ibm-not-wf-P85-ibm85n102','ibm-not-wf-P85-ibm85n101',
+ 'ibm-not-wf-P85-ibm85n100','ibm-not-wf-P85-ibm85n10',
+ 'ibm-not-wf-P85-ibm85n09','ibm-not-wf-P85-ibm85n08',
+ 'ibm-not-wf-P85-ibm85n07','ibm-not-wf-P85-ibm85n06',
+ 'ibm-not-wf-P85-ibm85n05','ibm-not-wf-P85-ibm85n04',
+ 'ibm-not-wf-P85-ibm85n03','ibm-not-wf-P85-ibm85n02',
+ 'ibm-not-wf-P85-ibm85n01','ibm-not-wf-P83-ibm83n06',
+ 'ibm-not-wf-P83-ibm83n05','ibm-not-wf-P83-ibm83n04',
+ 'ibm-not-wf-P83-ibm83n03','ibm-not-wf-P83-ibm83n02',
+ 'ibm-not-wf-P83-ibm83n01','ibm-not-wf-P82-ibm82n08',
+ 'ibm-not-wf-P82-ibm82n07','ibm-not-wf-P82-ibm82n06',
+ 'ibm-not-wf-P82-ibm82n05','ibm-not-wf-P82-ibm82n04',
+ 'ibm-not-wf-P82-ibm82n03','ibm-not-wf-P82-ibm82n02',
+ 'ibm-not-wf-P82-ibm82n01','ibm-not-wf-P81-ibm81n09',
+ 'ibm-not-wf-P81-ibm81n08','ibm-not-wf-P81-ibm81n07',
+ 'ibm-not-wf-P81-ibm81n06','ibm-not-wf-P81-ibm81n05',
+ 'ibm-not-wf-P81-ibm81n04','ibm-not-wf-P81-ibm81n03',
+ 'ibm-not-wf-P81-ibm81n02','ibm-not-wf-P81-ibm81n01',
+ 'ibm-not-wf-P80-ibm80n06','ibm-not-wf-P80-ibm80n05',
+ 'ibm-not-wf-P80-ibm80n04','ibm-not-wf-P80-ibm80n03',
+ 'ibm-not-wf-P80-ibm80n02','ibm-not-wf-P80-ibm80n01',
+ 'ibm-not-wf-P79-ibm79n02','ibm-not-wf-P79-ibm79n01',
+ 'ibm-not-wf-P78-ibm78n02','ibm-not-wf-P78-ibm78n01',
+ 'ibm-not-wf-P77-ibm77n04','ibm-not-wf-P77-ibm77n03',
+ 'ibm-not-wf-P77-ibm77n02','ibm-not-wf-P77-ibm77n01',
+ 'ibm-not-wf-P76-ibm76n07','ibm-not-wf-P76-ibm76n06',
+ 'ibm-not-wf-P76-ibm76n05','ibm-not-wf-P76-ibm76n04',
+ 'ibm-not-wf-P76-ibm76n03','ibm-not-wf-P76-ibm76n02',
+ 'ibm-not-wf-P76-ibm76n01','ibm-not-wf-P75-ibm75n13',
+ 'ibm-not-wf-P75-ibm75n12','ibm-not-wf-P75-ibm75n11',
+ 'ibm-not-wf-P75-ibm75n10','ibm-not-wf-P75-ibm75n09',
+ 'ibm-not-wf-P75-ibm75n08','ibm-not-wf-P75-ibm75n07',
+ 'ibm-not-wf-P75-ibm75n06','ibm-not-wf-P75-ibm75n05',
+ 'ibm-not-wf-P75-ibm75n04','ibm-not-wf-P75-ibm75n03',
+ 'ibm-not-wf-P75-ibm75n02','ibm-not-wf-P75-ibm75n01',
+ 'ibm-not-wf-P74-ibm74n01','ibm-not-wf-P73-ibm73n03',
+ 'ibm-not-wf-P73-ibm73n01','ibm-not-wf-P72-ibm72n09',
+ 'ibm-not-wf-P72-ibm72n08','ibm-not-wf-P72-ibm72n07',
+ 'ibm-not-wf-P72-ibm72n06','ibm-not-wf-P72-ibm72n05',
+ 'ibm-not-wf-P72-ibm72n04','ibm-not-wf-P72-ibm72n03',
+ 'ibm-not-wf-P72-ibm72n02','ibm-not-wf-P72-ibm72n01',
+ 'ibm-not-wf-P71-ibm71n08','ibm-not-wf-P71-ibm71n07',
+ 'ibm-not-wf-P71-ibm71n06','ibm-not-wf-P71-ibm71n05',
+ 'ibm-not-wf-P71-ibm71n04','ibm-not-wf-P71-ibm71n03',
+ 'ibm-not-wf-P71-ibm71n02','ibm-not-wf-P71-ibm71n01',
+ 'ibm-not-wf-P71-ibm70n01','ibm-not-wf-P69-ibm69n07',
+ 'ibm-not-wf-P69-ibm69n06','ibm-not-wf-P69-ibm69n05',
+ 'ibm-not-wf-P69-ibm69n04','ibm-not-wf-P69-ibm69n03',
+ 'ibm-not-wf-P69-ibm69n02','ibm-not-wf-P69-ibm69n01',
+ 'ibm-not-wf-P68-ibm68n10','ibm-not-wf-P68-ibm68n09',
+ 'ibm-not-wf-P68-ibm68n08','ibm-not-wf-P68-ibm68n07',
+ 'ibm-not-wf-P68-ibm68n06','ibm-not-wf-P68-ibm68n05',
+ 'ibm-not-wf-P68-ibm68n04','ibm-not-wf-P68-ibm68n03',
+ 'ibm-not-wf-P68-ibm68n02','ibm-not-wf-P68-ibm68n01',
+ 'ibm-not-wf-P66-ibm66n15','ibm-not-wf-P66-ibm66n14',
+ 'ibm-not-wf-P66-ibm66n13','ibm-not-wf-P66-ibm66n12',
+ 'ibm-not-wf-P66-ibm66n11','ibm-not-wf-P66-ibm66n10',
+ 'ibm-not-wf-P66-ibm66n09','ibm-not-wf-P66-ibm66n08',
+ 'ibm-not-wf-P66-ibm66n07','ibm-not-wf-P66-ibm66n06',
+ 'ibm-not-wf-P66-ibm66n05','ibm-not-wf-P66-ibm66n04',
+ 'ibm-not-wf-P66-ibm66n03','ibm-not-wf-P66-ibm66n02',
+ 'ibm-not-wf-P66-ibm66n01','ibm-not-wf-P65-ibm65n02',
+ 'ibm-not-wf-P65-ibm65n01','ibm-not-wf-P64-ibm64n03',
+ 'ibm-not-wf-P64-ibm64n02','ibm-not-wf-P64-ibm64n01',
+ 'ibm-not-wf-P63-ibm63n07','ibm-not-wf-P63-ibm63n06',
+ 'ibm-not-wf-P63-ibm63n05','ibm-not-wf-P63-ibm63n04',
+ 'ibm-not-wf-P63-ibm63n03','ibm-not-wf-P63-ibm63n02',
+ 'ibm-not-wf-P63-ibm63n01','ibm-not-wf-P62-ibm62n08',
+ 'ibm-not-wf-P62-ibm62n07','ibm-not-wf-P62-ibm62n06',
+ 'ibm-not-wf-P62-ibm62n05','ibm-not-wf-P62-ibm62n04',
+ 'ibm-not-wf-P62-ibm62n03','ibm-not-wf-P62-ibm62n02',
+ 'ibm-not-wf-P62-ibm62n01','ibm-not-wf-P61-ibm61n01',
+ 'ibm-not-wf-P60-ibm60n08','ibm-not-wf-P60-ibm60n07',
+ 'ibm-not-wf-P60-ibm60n06','ibm-not-wf-P60-ibm60n05',
+ 'ibm-not-wf-P60-ibm60n04','ibm-not-wf-P60-ibm60n03',
+ 'ibm-not-wf-P60-ibm60n02','ibm-not-wf-P60-ibm60n01',
+ 'ibm-not-wf-P59-ibm59n06','ibm-not-wf-P59-ibm59n05',
+ 'ibm-not-wf-P59-ibm59n04','ibm-not-wf-P59-ibm59n03',
+ 'ibm-not-wf-P59-ibm59n02','ibm-not-wf-P59-ibm59n01',
+ 'ibm-not-wf-P58-ibm58n08','ibm-not-wf-P58-ibm58n07',
+ 'ibm-not-wf-P58-ibm58n06','ibm-not-wf-P58-ibm58n05',
+ 'ibm-not-wf-P58-ibm58n04','ibm-not-wf-P58-ibm58n03',
+ 'ibm-not-wf-P58-ibm58n02','ibm-not-wf-P58-ibm58n01',
+ 'ibm-not-wf-P57-ibm57n01','ibm-not-wf-P56-ibm56n07',
+ 'ibm-not-wf-P56-ibm56n06','ibm-not-wf-P56-ibm56n05',
+ 'ibm-not-wf-P56-ibm56n04','ibm-not-wf-P56-ibm56n03',
+ 'ibm-not-wf-P56-ibm56n02','ibm-not-wf-P56-ibm56n01',
+ 'ibm-not-wf-P55-ibm55n03','ibm-not-wf-P55-ibm55n02',
+ 'ibm-not-wf-P55-ibm55n01','ibm-not-wf-P54-ibm54n02',
+ 'ibm-not-wf-P54-ibm54n01','ibm-not-wf-P53-ibm53n08',
+ 'ibm-not-wf-P53-ibm53n07','ibm-not-wf-P53-ibm53n06',
+ 'ibm-not-wf-P53-ibm53n05','ibm-not-wf-P53-ibm53n04',
+ 'ibm-not-wf-P53-ibm53n03','ibm-not-wf-P53-ibm53n02',
+ 'ibm-not-wf-P53-ibm53n01','ibm-not-wf-P52-ibm52n06',
+ 'ibm-not-wf-P52-ibm52n05','ibm-not-wf-P52-ibm52n04',
+ 'ibm-not-wf-P52-ibm52n03','ibm-not-wf-P52-ibm52n02',
+ 'ibm-not-wf-P52-ibm52n01','ibm-not-wf-P51-ibm51n07',
+ 'ibm-not-wf-P51-ibm51n06','ibm-not-wf-P51-ibm51n05',
+ 'ibm-not-wf-P51-ibm51n04','ibm-not-wf-P51-ibm51n03',
+ 'ibm-not-wf-P51-ibm51n02','ibm-not-wf-P51-ibm51n01',
+ 'ibm-not-wf-P50-ibm50n07','ibm-not-wf-P50-ibm50n06',
+ 'ibm-not-wf-P50-ibm50n05','ibm-not-wf-P50-ibm50n04',
+ 'ibm-not-wf-P50-ibm50n03','ibm-not-wf-P50-ibm50n02',
+ 'ibm-not-wf-P50-ibm50n01','ibm-not-wf-P49-ibm49n06',
+ 'ibm-not-wf-P49-ibm49n05','ibm-not-wf-P49-ibm49n04',
+ 'ibm-not-wf-P49-ibm49n03','ibm-not-wf-P49-ibm49n02',
+ 'ibm-not-wf-P49-ibm49n01','ibm-not-wf-P48-ibm48n07',
+ 'ibm-not-wf-P48-ibm48n06','ibm-not-wf-P48-ibm48n05',
+ 'ibm-not-wf-P48-ibm48n04','ibm-not-wf-P48-ibm48n03',
+ 'ibm-not-wf-P48-ibm48n02','ibm-not-wf-P48-ibm48n01',
+ 'ibm-not-wf-P47-ibm47n06','ibm-not-wf-P47-ibm47n05',
+ 'ibm-not-wf-P47-ibm47n04','ibm-not-wf-P47-ibm47n03',
+ 'ibm-not-wf-P47-ibm47n02','ibm-not-wf-P47-ibm47n01',
+ 'ibm-not-wf-P46-ibm46n05','ibm-not-wf-P46-ibm46n04',
+ 'ibm-not-wf-P46-ibm46n03','ibm-not-wf-P46-ibm46n02',
+ 'ibm-not-wf-P46-ibm46n01','ibm-not-wf-P45-ibm45n09',
+ 'ibm-not-wf-P45-ibm45n08','ibm-not-wf-P45-ibm45n07',
+ 'ibm-not-wf-P45-ibm45n06','ibm-not-wf-P45-ibm45n05',
+ 'ibm-not-wf-P45-ibm45n04','ibm-not-wf-P45-ibm45n03',
+ 'ibm-not-wf-P45-ibm45n02','ibm-not-wf-P45-ibm45n01',
+ 'ibm-not-wf-P44-ibm44n04','ibm-not-wf-P44-ibm44n03',
+ 'ibm-not-wf-P44-ibm44n02','ibm-not-wf-P44-ibm44n01',
+ 'ibm-not-wf-P43-ibm43n05','ibm-not-wf-P43-ibm43n04',
+ 'ibm-not-wf-P43-ibm43n02','ibm-not-wf-P43-ibm43n01',
+ 'ibm-not-wf-P42-ibm42n05','ibm-not-wf-P42-ibm42n04',
+ 'ibm-not-wf-P42-ibm42n03','ibm-not-wf-P42-ibm42n02',
+ 'ibm-not-wf-P42-ibm42n01','ibm-not-wf-P41-ibm41n14',
+ 'ibm-not-wf-P41-ibm41n13','ibm-not-wf-P41-ibm41n12',
+ 'ibm-not-wf-P41-ibm41n11','ibm-not-wf-P41-ibm41n10',
+ 'ibm-not-wf-P41-ibm41n09','ibm-not-wf-P41-ibm41n08',
+ 'ibm-not-wf-P41-ibm41n07','ibm-not-wf-P41-ibm41n06',
+ 'ibm-not-wf-P41-ibm41n05','ibm-not-wf-P41-ibm41n04',
+ 'ibm-not-wf-P41-ibm41n03','ibm-not-wf-P41-ibm41n02',
+ 'ibm-not-wf-P41-ibm41n01','ibm-not-wf-P40-ibm40n05',
+ 'ibm-not-wf-P40-ibm40n04','ibm-not-wf-P40-ibm40n03',
+ 'ibm-not-wf-P40-ibm40n02','ibm-not-wf-P40-ibm40n01',
+ 'ibm-not-wf-P39-ibm39n06','ibm-not-wf-P39-ibm39n05',
+ 'ibm-not-wf-P39-ibm39n04','ibm-not-wf-P39-ibm39n03',
+ 'ibm-not-wf-P39-ibm39n02','ibm-not-wf-P39-ibm39n01',
+ 'ibm-not-wf-P32-ibm32n09','ibm-not-wf-P32-ibm32n08',
+ 'ibm-not-wf-P32-ibm32n07','ibm-not-wf-P32-ibm32n06',
+ 'ibm-not-wf-P32-ibm32n05','ibm-not-wf-P32-ibm32n04',
+ 'ibm-not-wf-P32-ibm32n03','ibm-not-wf-P32-ibm32n02',
+ 'ibm-not-wf-P32-ibm32n01','ibm-not-wf-P31-ibm31n01',
+ 'ibm-not-wf-P30-ibm30n01','ibm-not-wf-P29-ibm29n07',
+ 'ibm-not-wf-P29-ibm29n06','ibm-not-wf-P29-ibm29n05',
+ 'ibm-not-wf-P29-ibm29n04','ibm-not-wf-P29-ibm29n03',
+ 'ibm-not-wf-P29-ibm29n02','ibm-not-wf-P29-ibm29n01',
+ 'ibm-not-wf-P28a-ibm28an01','ibm-not-wf-P28-ibm28n08',
+ 'ibm-not-wf-P28-ibm28n07','ibm-not-wf-P28-ibm28n06',
+ 'ibm-not-wf-P28-ibm28n05','ibm-not-wf-P28-ibm28n04',
+ 'ibm-not-wf-P28-ibm28n03','ibm-not-wf-P28-ibm28n02',
+ 'ibm-not-wf-P28-ibm28n01','ibm-not-wf-P27-ibm27n01',
+ 'ibm-not-wf-P26-ibm26n01','ibm-not-wf-P25-ibm25n02',
+ 'ibm-not-wf-P25-ibm25n01','ibm-not-wf-P24-ibm24n09',
+ 'ibm-not-wf-P24-ibm24n08','ibm-not-wf-P24-ibm24n07',
+ 'ibm-not-wf-P24-ibm24n06','ibm-not-wf-P24-ibm24n05',
+ 'ibm-not-wf-P24-ibm24n04','ibm-not-wf-P24-ibm24n03',
+ 'ibm-not-wf-P24-ibm24n02','ibm-not-wf-P24-ibm24n01',
+ 'ibm-not-wf-P23-ibm23n06','ibm-not-wf-P23-ibm23n05',
+ 'ibm-not-wf-P23-ibm23n04','ibm-not-wf-P23-ibm23n03',
+ 'ibm-not-wf-P23-ibm23n02','ibm-not-wf-P23-ibm23n01',
+ 'ibm-not-wf-P22-ibm22n03','ibm-not-wf-P22-ibm22n02',
+ 'ibm-not-wf-P22-ibm22n01','ibm-not-wf-P21-ibm21n03',
+ 'ibm-not-wf-P21-ibm21n02','ibm-not-wf-P21-ibm21n01',
+ 'ibm-not-wf-P20-ibm20n01','ibm-not-wf-P19-ibm19n03',
+ 'ibm-not-wf-P19-ibm19n02','ibm-not-wf-P19-ibm19n01',
+ 'ibm-not-wf-P18-ibm18n02','ibm-not-wf-P18-ibm18n01',
+ 'ibm-not-wf-P17-ibm17n04','ibm-not-wf-P17-ibm17n03',
+ 'ibm-not-wf-P17-ibm17n02','ibm-not-wf-P17-ibm17n01',
+ 'ibm-not-wf-P16-ibm16n04','ibm-not-wf-P16-ibm16n03',
+ 'ibm-not-wf-P16-ibm16n02','ibm-not-wf-P16-ibm16n01',
+ 'ibm-not-wf-P15-ibm15n04','ibm-not-wf-P15-ibm15n03',
+ 'ibm-not-wf-P15-ibm15n02','ibm-not-wf-P15-ibm15n01',
+ 'ibm-not-wf-P14-ibm14n03','ibm-not-wf-P14-ibm14n02',
+ 'ibm-not-wf-P14-ibm14n01','ibm-not-wf-P13-ibm13n03',
+ 'ibm-not-wf-P13-ibm13n02','ibm-not-wf-P13-ibm13n01',
+ 'ibm-not-wf-P12-ibm12n03','ibm-not-wf-P12-ibm12n02',
+ 'ibm-not-wf-P12-ibm12n01','ibm-not-wf-P11-ibm11n04',
+ 'ibm-not-wf-P11-ibm11n03','ibm-not-wf-P11-ibm11n02',
+ 'ibm-not-wf-P11-ibm11n01','ibm-not-wf-P10-ibm10n08',
+ 'ibm-not-wf-P10-ibm10n07','ibm-not-wf-P10-ibm10n06',
+ 'ibm-not-wf-P10-ibm10n05','ibm-not-wf-P10-ibm10n04',
+ 'ibm-not-wf-P10-ibm10n03','ibm-not-wf-P10-ibm10n02',
+ 'ibm-not-wf-P10-ibm10n01','ibm-not-wf-P09-ibm09n04',
+ 'ibm-not-wf-P09-ibm09n03','ibm-not-wf-P09-ibm09n02',
+ 'ibm-not-wf-P09-ibm09n01','ibm-not-wf-P05-ibm05n03',
+ 'ibm-not-wf-P05-ibm05n02','ibm-not-wf-P05-ibm05n01',
+ 'ibm-not-wf-P04-ibm04n18','ibm-not-wf-P04-ibm04n17',
+ 'ibm-not-wf-P04-ibm04n16','ibm-not-wf-P04-ibm04n15',
+ 'ibm-not-wf-P04-ibm04n14','ibm-not-wf-P04-ibm04n13',
+ 'ibm-not-wf-P04-ibm04n12','ibm-not-wf-P04-ibm04n11',
+ 'ibm-not-wf-P04-ibm04n10','ibm-not-wf-P04-ibm04n09',
+ 'ibm-not-wf-P04-ibm04n08','ibm-not-wf-P04-ibm04n07',
+ 'ibm-not-wf-P04-ibm04n06','ibm-not-wf-P04-ibm04n05',
+ 'ibm-not-wf-P04-ibm04n04','ibm-not-wf-P04-ibm04n03',
+ 'ibm-not-wf-P04-ibm04n02','ibm-not-wf-P04-ibm04n01',
+ 'ibm-not-wf-P03-ibm03n01','ibm-not-wf-P02-ibm02n33',
+ 'ibm-not-wf-P02-ibm02n32','ibm-not-wf-P02-ibm02n31',
+ 'ibm-not-wf-P02-ibm02n30','ibm-not-wf-P02-ibm02n29',
+ 'ibm-not-wf-P02-ibm02n28','ibm-not-wf-P02-ibm02n27',
+ 'ibm-not-wf-P02-ibm02n26','ibm-not-wf-P02-ibm02n25',
+ 'ibm-not-wf-P02-ibm02n24','ibm-not-wf-P02-ibm02n23',
+ 'ibm-not-wf-P02-ibm02n22','ibm-not-wf-P02-ibm02n21',
+ 'ibm-not-wf-P02-ibm02n20','ibm-not-wf-P02-ibm02n19',
+ 'ibm-not-wf-P02-ibm02n18','ibm-not-wf-P02-ibm02n17',
+ 'ibm-not-wf-P02-ibm02n16','ibm-not-wf-P02-ibm02n15',
+ 'ibm-not-wf-P02-ibm02n14','ibm-not-wf-P02-ibm02n13',
+ 'ibm-not-wf-P02-ibm02n12','ibm-not-wf-P02-ibm02n11',
+ 'ibm-not-wf-P02-ibm02n10','ibm-not-wf-P02-ibm02n09',
+ 'ibm-not-wf-P02-ibm02n08','ibm-not-wf-P02-ibm02n07',
+ 'ibm-not-wf-P02-ibm02n06','ibm-not-wf-P02-ibm02n05',
+ 'ibm-not-wf-P02-ibm02n04','ibm-not-wf-P02-ibm02n03',
+ 'ibm-not-wf-P02-ibm02n02','ibm-not-wf-P02-ibm02n01',
+ 'ibm-not-wf-P01-ibm01n03','ibm-not-wf-P01-ibm01n02',
+ 'ibm-not-wf-P01-ibm01n01'].
+
+'ibm-valid'(suite) ->
+ %% 149 test cases
+ ['ibm-valid-P89-ibm89v01','ibm-valid-P88-ibm88v01',
+ 'ibm-valid-P87-ibm87v01','ibm-valid-P86-ibm86v01',
+ 'ibm-valid-P85-ibm85v01','ibm-valid-P82-ibm82v01',
+ 'ibm-valid-P79-ibm79v01','ibm-valid-P78-ibm78v01',
+ 'ibm-valid-P70-ibm70v01','ibm-valid-P69-ibm69v02',
+ 'ibm-valid-P69-ibm69v01','ibm-valid-P68-ibm68v02',
+ 'ibm-valid-P68-ibm68v01','ibm-valid-P67-ibm67v01',
+ 'ibm-valid-P66-ibm66v01','ibm-valid-P65-ibm65v02',
+ 'ibm-valid-P65-ibm65v01','ibm-valid-P64-ibm64v03',
+ 'ibm-valid-P64-ibm64v02','ibm-valid-P64-ibm64v01',
+ 'ibm-valid-P63-ibm63v05','ibm-valid-P63-ibm63v04',
+ 'ibm-valid-P63-ibm63v03','ibm-valid-P63-ibm63v02',
+ 'ibm-valid-P63-ibm63v01','ibm-valid-P62-ibm62v05',
+ 'ibm-valid-P62-ibm62v04','ibm-valid-P62-ibm62v03',
+ 'ibm-valid-P62-ibm62v02','ibm-valid-P62-ibm62v01',
+ 'ibm-valid-P61-ibm61v02','ibm-valid-P61-ibm61v01',
+ 'ibm-valid-P60-ibm60v04','ibm-valid-P60-ibm60v03',
+ 'ibm-valid-P60-ibm60v02','ibm-valid-P60-ibm60v01',
+ 'ibm-valid-P59-ibm59v02','ibm-valid-P59-ibm59v01',
+ 'ibm-valid-P58-ibm58v02','ibm-valid-P58-ibm58v01',
+ 'ibm-valid-P57-ibm57v01','ibm-valid-P56-ibm56v10',
+ 'ibm-valid-P56-ibm56v09','ibm-valid-P56-ibm56v08',
+ 'ibm-valid-P56-ibm56v07','ibm-valid-P56-ibm56v06',
+ 'ibm-valid-P56-ibm56v05','ibm-valid-P56-ibm56v04',
+ 'ibm-valid-P56-ibm56v03','ibm-valid-P56-ibm56v02',
+ 'ibm-valid-P56-ibm56v01','ibm-valid-P55-ibm55v01',
+ 'ibm-valid-P54-ibm54v03','ibm-valid-P54-ibm54v02',
+ 'ibm-valid-P54-ibm54v01','ibm-valid-P52-ibm52v01',
+ 'ibm-valid-P51-ibm51v02','ibm-valid-P51-ibm51v01',
+ 'ibm-valid-P50-ibm50v01','ibm-valid-P49-ibm49v01',
+ 'ibm-valid-P47-ibm47v01','ibm-valid-P45-ibm45v01',
+ 'ibm-valid-P44-ibm44v01','ibm-valid-P43-ibm43v01',
+ 'ibm-valid-P42-ibm42v01','ibm-valid-P41-ibm41v01',
+ 'ibm-valid-P40-ibm40v01','ibm-valid-P39-ibm39v01',
+ 'ibm-valid-P38-ibm38v01','ibm-valid-P37-ibm37v01',
+ 'ibm-valid-P36-ibm36v01','ibm-valid-P35-ibm35v01',
+ 'ibm-valid-P34-ibm34v01','ibm-valid-P33-ibm33v01',
+ 'ibm-valid-P32-ibm32v04','ibm-valid-P32-ibm32v03',
+ 'ibm-valid-P32-ibm32v02','ibm-valid-P32-ibm32v01',
+ 'ibm-valid-P31-ibm31v01','ibm-valid-P30-ibm30v02',
+ 'ibm-valid-P30-ibm30v01','ibm-valid-P29-ibm29v02',
+ 'ibm-valid-P29-ibm29v01','ibm-valid-P28-ibm28v02',
+ 'ibm-valid-P28-ibm28v01','ibm-valid-P27-ibm27v03',
+ 'ibm-valid-P27-ibm27v02','ibm-valid-P27-ibm27v01',
+ 'ibm-valid-P26-ibm26v01','ibm-valid-P25-ibm25v04',
+ 'ibm-valid-P25-ibm25v03','ibm-valid-P25-ibm25v02',
+ 'ibm-valid-P25-ibm25v01','ibm-valid-P24-ibm24v02',
+ 'ibm-valid-P24-ibm24v01','ibm-valid-P23-ibm23v06',
+ 'ibm-valid-P23-ibm23v05','ibm-valid-P23-ibm23v04',
+ 'ibm-valid-P23-ibm23v03','ibm-valid-P23-ibm23v02',
+ 'ibm-valid-P23-ibm23v01','ibm-valid-P22-ibm22v07',
+ 'ibm-valid-P22-ibm22v06','ibm-valid-P22-ibm22v05',
+ 'ibm-valid-P22-ibm22v04','ibm-valid-P22-ibm22v03',
+ 'ibm-valid-P22-ibm22v02','ibm-valid-P22-ibm22v01',
+ 'ibm-valid-P21-ibm21v01','ibm-valid-P20-ibm20v02',
+ 'ibm-valid-P20-ibm20v01','ibm-valid-P19-ibm19v01',
+ 'ibm-valid-P18-ibm18v01','ibm-valid-P17-ibm17v01',
+ 'ibm-valid-P16-ibm16v03','ibm-valid-P16-ibm16v02',
+ 'ibm-valid-P16-ibm16v01','ibm-valid-P15-ibm15v04',
+ 'ibm-valid-P15-ibm15v03','ibm-valid-P15-ibm15v02',
+ 'ibm-valid-P15-ibm15v01','ibm-valid-P14-ibm14v03',
+ 'ibm-valid-P14-ibm14v02','ibm-valid-P14-ibm14v01',
+ 'ibm-valid-P13-ibm13v01','ibm-valid-P12-ibm12v04',
+ 'ibm-valid-P12-ibm12v03','ibm-valid-P12-ibm12v02',
+ 'ibm-valid-P12-ibm12v01','ibm-valid-P11-ibm11v04',
+ 'ibm-valid-P11-ibm11v03','ibm-valid-P11-ibm11v02',
+ 'ibm-valid-P11-ibm11v01','ibm-valid-P10-ibm10v08',
+ 'ibm-valid-P10-ibm10v07','ibm-valid-P10-ibm10v06',
+ 'ibm-valid-P10-ibm10v05','ibm-valid-P10-ibm10v04',
+ 'ibm-valid-P10-ibm10v03','ibm-valid-P10-ibm10v02',
+ 'ibm-valid-P10-ibm10v01','ibm-valid-P09-ibm09v05',
+ 'ibm-valid-P09-ibm09v04','ibm-valid-P09-ibm09v03',
+ 'ibm-valid-P09-ibm09v02','ibm-valid-P09-ibm09v01',
+ 'ibm-valid-P03-ibm03v01','ibm-valid-P02-ibm02v01',
+ 'ibm-valid-P01-ibm01v01'].
+
+%%----------------------------------------------------------------------
+%% Initializations
+%%----------------------------------------------------------------------
+
+init_per_suite(doc) ->
+ ["Starts the test suite"];
+init_per_suite(Config) ->
+ Dog=test_server:timetrap({minutes,10}),
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line ok=erl_tar:extract("ibm.tgz",[compressed]),
+ ?line ok=erl_tar:extract("japanese.tgz",[compressed]),
+ ?line ok=erl_tar:extract("oasis.tgz",[compressed]),
+ ?line ok=erl_tar:extract("sun.tgz",[compressed]),
+ ?line ok=erl_tar:extract("xmltest.tgz",[compressed]),
+ ?line ok = change_mode(["ibm","japanese","oasis",
+ "sun","xmltest"]),
+ [{watchdog, Dog}|Config].
+
+
+-ifndef(dont_rm_test_dirs).
+end_per_suite(doc) ->
+ ["Stops the test suite"];
+end_per_suite(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line ok=rm_files(["ibm","japanese","oasis","sun","xmltest"]),
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ lists:keydelete(watchdog,1,Config).
+
+-else.
+end_per_suite(doc) ->
+ ["Stops the test suite"];
+end_per_suite(Config) ->
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ lists:keydelete(watchdog,1,Config).
+-endif.
+
+%% initialization before each testcase
+init_per_testcase(_TestCase,Config) ->
+ io:format("Config:~n~p",[Config]),
+ ?line {ok, _} = file:read_file_info(filename:join([?config(priv_dir,Config)])),
+ ?line code:add_patha(?config(priv_dir,Config)),
+ Dog=test_server:timetrap({minutes,10}),
+ [{watchdog, Dog}|Config].
+
+
+%% clean up after each testcase
+end_per_testcase(_Func,Config) ->
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+
+%%----------------------------------------------------------------------
+%% Test cases
+%%----------------------------------------------------------------------
+'v-pe02'(suite) -> [];
+'v-pe02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"v-pe02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'v-pe03'(suite) -> [];
+'v-pe03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"v-pe03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'v-pe00'(suite) -> [];
+'v-pe00'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"v-pe00.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'v-lang06'(suite) -> [];
+'v-lang06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"v-lang06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'v-lang05'(suite) -> [];
+'v-lang05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"v-lang05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'v-lang04'(suite) -> [];
+'v-lang04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"v-lang04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'v-lang03'(suite) -> [];
+'v-lang03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"v-lang03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'v-lang02'(suite) -> [];
+'v-lang02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"v-lang02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'v-lang01'(suite) -> [];
+'v-lang01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"v-lang01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'v-sgml01'(suite) -> [];
+'v-sgml01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"v-sgml01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'sa05'(suite) -> [];
+'sa05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"sa05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'sa04'(suite) -> [];
+'sa04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"sa04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'sa03'(suite) -> [];
+'sa03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"sa03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'sa02'(suite) -> [];
+'sa02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"sa02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'sa01'(suite) -> [];
+'sa01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"sa01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'required00'(suite) -> [];
+'required00'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"required00.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional'(suite) -> [];
+'optional'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'notation01'(suite) -> [];
+'notation01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"notation01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-sa04'(suite) -> [];
+'not-sa04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"not-sa04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-sa03'(suite) -> [];
+'not-sa03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"not-sa03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-sa02'(suite) -> [];
+'not-sa02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"not-sa02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-sa01'(suite) -> [];
+'not-sa01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"not-sa01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ext02'(suite) -> [];
+'ext02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"ext02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ext01'(suite) -> [];
+'ext01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"ext01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'element'(suite) -> [];
+'element'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"element.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'dtd01'(suite) -> [];
+'dtd01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"dtd01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'dtd00'(suite) -> [];
+'dtd00'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"dtd00.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'pe01'(suite) -> [];
+'pe01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"pe01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+%%----------------------------------------------------------------------
+
+'empty'(suite) -> [];
+'empty'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"empty.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'utf16l'(suite) -> [];
+'utf16l'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"utf16l.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'utf16b'(suite) -> [];
+'utf16b'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"utf16b.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attr16'(suite) -> [];
+'attr16'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attr16.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attr15'(suite) -> [];
+'attr15'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attr15.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attr14'(suite) -> [];
+'attr14'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attr14.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attr13'(suite) -> [];
+'attr13'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attr13.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attr12'(suite) -> [];
+'attr12'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attr12.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attr11'(suite) -> [];
+'attr11'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attr11.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attr10'(suite) -> [];
+'attr10'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attr10.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attr09'(suite) -> [];
+'attr09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attr09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attr08'(suite) -> [];
+'attr08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attr08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attr07'(suite) -> [];
+'attr07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attr07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attr06'(suite) -> [];
+'attr06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attr06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attr05'(suite) -> [];
+'attr05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attr05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attr04'(suite) -> [];
+'attr04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attr04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attr03'(suite) -> [];
+'attr03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attr03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attr02'(suite) -> [];
+'attr02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attr02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attr01'(suite) -> [];
+'attr01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attr01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'root'(suite) -> [];
+'root'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"root.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'inv-required02'(suite) -> [];
+'inv-required02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"inv-required02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'inv-required01'(suite) -> [];
+'inv-required01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"inv-required01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'inv-required00'(suite) -> [];
+'inv-required00'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"inv-required00.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional25'(suite) -> [];
+'optional25'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional25.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional24'(suite) -> [];
+'optional24'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional24.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional23'(suite) -> [];
+'optional23'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional23.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional22'(suite) -> [];
+'optional22'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional22.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional21'(suite) -> [];
+'optional21'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional21.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional20'(suite) -> [];
+'optional20'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional20.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional14'(suite) -> [];
+'optional14'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional14.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional13'(suite) -> [];
+'optional13'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional13.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional12'(suite) -> [];
+'optional12'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional12.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional11'(suite) -> [];
+'optional11'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional11.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional10'(suite) -> [];
+'optional10'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional10.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional09'(suite) -> [];
+'optional09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional08'(suite) -> [];
+'optional08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional07'(suite) -> [];
+'optional07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional06'(suite) -> [];
+'optional06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional05'(suite) -> [];
+'optional05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional04'(suite) -> [];
+'optional04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional03'(suite) -> [];
+'optional03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional02'(suite) -> [];
+'optional02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'optional01'(suite) -> [];
+'optional01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"optional01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'inv-not-sa14'(suite) -> [];
+'inv-not-sa14'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"inv-not-sa14.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'inv-not-sa13'(suite) -> [];
+'inv-not-sa13'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"inv-not-sa13.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'inv-not-sa12'(suite) -> [];
+'inv-not-sa12'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"inv-not-sa12.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'inv-not-sa11'(suite) -> [];
+'inv-not-sa11'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"inv-not-sa11.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'inv-not-sa10'(suite) -> [];
+'inv-not-sa10'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"inv-not-sa10.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'inv-not-sa09'(suite) -> [];
+'inv-not-sa09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"inv-not-sa09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'inv-not-sa08'(suite) -> [];
+'inv-not-sa08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"inv-not-sa08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'inv-not-sa07'(suite) -> [];
+'inv-not-sa07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"inv-not-sa07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'inv-not-sa06'(suite) -> [];
+'inv-not-sa06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"inv-not-sa06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'inv-not-sa05'(suite) -> [];
+'inv-not-sa05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"inv-not-sa05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'inv-not-sa04'(suite) -> [];
+'inv-not-sa04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"inv-not-sa04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'inv-not-sa02'(suite) -> [];
+'inv-not-sa02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"inv-not-sa02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'inv-not-sa01'(suite) -> [];
+'inv-not-sa01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"inv-not-sa01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'id09'(suite) -> [];
+'id09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"id09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'id08'(suite) -> [];
+'id08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"id08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'id07'(suite) -> [];
+'id07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"id07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'id06'(suite) -> [];
+'id06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"id06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'id05'(suite) -> [];
+'id05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"id05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'id04'(suite) -> [];
+'id04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"id04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'id03'(suite) -> [];
+'id03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"id03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'id02'(suite) -> [];
+'id02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"id02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'id01'(suite) -> [];
+'id01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"id01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'el06'(suite) -> [];
+'el06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"el06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'el05'(suite) -> [];
+'el05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"el05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'el04'(suite) -> [];
+'el04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"el04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'el03'(suite) -> [];
+'el03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"el03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'el02'(suite) -> [];
+'el02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"el02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'el01'(suite) -> [];
+'el01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"el01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'inv-dtd03'(suite) -> [];
+'inv-dtd03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"inv-dtd03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'inv-dtd02'(suite) -> [];
+'inv-dtd02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"inv-dtd02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'inv-dtd01'(suite) -> [];
+'inv-dtd01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"inv-dtd01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+%%----------------------------------------------------------------------
+
+'sgml13'(suite) -> [];
+'sgml13'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"sgml13.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'sgml12'(suite) -> [];
+'sgml12'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"sgml12.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'sgml11'(suite) -> [];
+'sgml11'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"sgml11.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'sgml10'(suite) -> [];
+'sgml10'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"sgml10.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'sgml09'(suite) -> [];
+'sgml09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"sgml09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'sgml08'(suite) -> [];
+'sgml08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"sgml08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'sgml07'(suite) -> [];
+'sgml07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"sgml07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'sgml06'(suite) -> [];
+'sgml06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"sgml06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'sgml05'(suite) -> [];
+'sgml05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"sgml05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'sgml04'(suite) -> [];
+'sgml04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"sgml04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'sgml03'(suite) -> [];
+'sgml03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"sgml03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'sgml02'(suite) -> [];
+'sgml02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"sgml02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'sgml01'(suite) -> [];
+'sgml01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"sgml01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'pubid05'(suite) -> [];
+'pubid05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"pubid05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'pubid04'(suite) -> [];
+'pubid04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"pubid04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'pubid03'(suite) -> [];
+'pubid03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"pubid03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'pubid02'(suite) -> [];
+'pubid02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"pubid02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'pubid01'(suite) -> [];
+'pubid01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"pubid01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'pi'(suite) -> [];
+'pi'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"pi.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'encoding07'(suite) -> [];
+'encoding07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"encoding07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'encoding06'(suite) -> [];
+'encoding06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"encoding06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'encoding05'(suite) -> [];
+'encoding05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"encoding05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'encoding04'(suite) -> [];
+'encoding04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"encoding04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'encoding03'(suite) -> [];
+'encoding03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"encoding03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'encoding02'(suite) -> [];
+'encoding02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"encoding02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'encoding01'(suite) -> [];
+'encoding01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"encoding01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'element04'(suite) -> [];
+'element04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"element04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'element03'(suite) -> [];
+'element03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"element03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'element02'(suite) -> [];
+'element02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"element02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'element01'(suite) -> [];
+'element01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"element01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'element00'(suite) -> [];
+'element00'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"element00.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'dtd07'(suite) -> [];
+'dtd07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"dtd07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'dtd05'(suite) -> [];
+'dtd05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"dtd05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'dtd04'(suite) -> [];
+'dtd04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"dtd04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'dtd03'(suite) -> [];
+'dtd03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"dtd03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'dtd02'(suite) -> [];
+'dtd02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"dtd02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'nwf-dtd01'(suite) -> [];
+'nwf-dtd01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"nwf-dtd01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'nwf-dtd00'(suite) -> [];
+'nwf-dtd00'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"nwf-dtd00.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'decl01'(suite) -> [];
+'decl01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"decl01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'content03'(suite) -> [];
+'content03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"content03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'content02'(suite) -> [];
+'content02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"content02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'content01'(suite) -> [];
+'content01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"content01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'cond02'(suite) -> [];
+'cond02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"cond02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'cond01'(suite) -> [];
+'cond01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"cond01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attlist11'(suite) -> [];
+'attlist11'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attlist11.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attlist10'(suite) -> [];
+'attlist10'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attlist10.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attlist09'(suite) -> [];
+'attlist09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attlist09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attlist08'(suite) -> [];
+'attlist08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attlist08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attlist07'(suite) -> [];
+'attlist07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attlist07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attlist06'(suite) -> [];
+'attlist06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attlist06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attlist05'(suite) -> [];
+'attlist05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attlist05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attlist04'(suite) -> [];
+'attlist04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attlist04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attlist03'(suite) -> [];
+'attlist03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attlist03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attlist02'(suite) -> [];
+'attlist02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attlist02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'attlist01'(suite) -> [];
+'attlist01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"attlist01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa03'(suite) -> [];
+'not-wf-sa03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"not-wf-sa03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+%%----------------------------------------------------------------------
+
+'uri01'(suite) -> [];
+'uri01'(doc) ->
+ ["URI fragments disallowed"];
+'uri01'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),sun,"uri01.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["URI fragments disallowed"]}.
+
+%%----------------------------------------------------------------------
+
+'valid-ext-sa-014'(suite) -> [];
+'valid-ext-sa-014'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-ext-sa-014.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-ext-sa-013'(suite) -> [];
+'valid-ext-sa-013'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-ext-sa-013.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-ext-sa-012'(suite) -> [];
+'valid-ext-sa-012'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-ext-sa-012.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-ext-sa-011'(suite) -> [];
+'valid-ext-sa-011'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-ext-sa-011.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-ext-sa-009'(suite) -> [];
+'valid-ext-sa-009'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-ext-sa-009.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-ext-sa-008'(suite) -> [];
+'valid-ext-sa-008'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-ext-sa-008.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-ext-sa-007'(suite) -> [];
+'valid-ext-sa-007'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-ext-sa-007.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-ext-sa-006'(suite) -> [];
+'valid-ext-sa-006'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-ext-sa-006.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-ext-sa-005'(suite) -> [];
+'valid-ext-sa-005'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-ext-sa-005.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-ext-sa-004'(suite) -> [];
+'valid-ext-sa-004'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-ext-sa-004.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-ext-sa-003'(suite) -> [];
+'valid-ext-sa-003'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-ext-sa-003.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-ext-sa-002'(suite) -> [];
+'valid-ext-sa-002'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-ext-sa-002.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-ext-sa-001'(suite) -> [];
+'valid-ext-sa-001'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-ext-sa-001.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-031'(suite) -> [];
+'valid-not-sa-031'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-031.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-030'(suite) -> [];
+'valid-not-sa-030'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-030.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-029'(suite) -> [];
+'valid-not-sa-029'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-029.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-028'(suite) -> [];
+'valid-not-sa-028'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-028.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-027'(suite) -> [];
+'valid-not-sa-027'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-027.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-026'(suite) -> [];
+'valid-not-sa-026'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-026.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-025'(suite) -> [];
+'valid-not-sa-025'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-025.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-024'(suite) -> [];
+'valid-not-sa-024'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-024.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-023'(suite) -> [];
+'valid-not-sa-023'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-023.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-021'(suite) -> [];
+'valid-not-sa-021'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-021.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-020'(suite) -> [];
+'valid-not-sa-020'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-020.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-019'(suite) -> [];
+'valid-not-sa-019'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-019.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-018'(suite) -> [];
+'valid-not-sa-018'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-018.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-017'(suite) -> [];
+'valid-not-sa-017'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-017.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-016'(suite) -> [];
+'valid-not-sa-016'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-016.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-015'(suite) -> [];
+'valid-not-sa-015'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-015.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-014'(suite) -> [];
+'valid-not-sa-014'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-014.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-013'(suite) -> [];
+'valid-not-sa-013'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-013.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-012'(suite) -> [];
+'valid-not-sa-012'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-012.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-011'(suite) -> [];
+'valid-not-sa-011'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-011.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-010'(suite) -> [];
+'valid-not-sa-010'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-010.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-009'(suite) -> [];
+'valid-not-sa-009'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-009.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-008'(suite) -> [];
+'valid-not-sa-008'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-008.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-007'(suite) -> [];
+'valid-not-sa-007'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-007.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-006'(suite) -> [];
+'valid-not-sa-006'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-006.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-005'(suite) -> [];
+'valid-not-sa-005'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-005.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-004'(suite) -> [];
+'valid-not-sa-004'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-004.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-003'(suite) -> [];
+'valid-not-sa-003'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-003.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-002'(suite) -> [];
+'valid-not-sa-002'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-002.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-not-sa-001'(suite) -> [];
+'valid-not-sa-001'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-not-sa-001.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-119'(suite) -> [];
+'valid-sa-119'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-119.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-118'(suite) -> [];
+'valid-sa-118'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-118.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-117'(suite) -> [];
+'valid-sa-117'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-117.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-116'(suite) -> [];
+'valid-sa-116'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-116.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-115'(suite) -> [];
+'valid-sa-115'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-115.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-114'(suite) -> [];
+'valid-sa-114'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-114.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-113'(suite) -> [];
+'valid-sa-113'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-113.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-112'(suite) -> [];
+'valid-sa-112'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-112.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-111'(suite) -> [];
+'valid-sa-111'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-111.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-110'(suite) -> [];
+'valid-sa-110'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-110.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-109'(suite) -> [];
+'valid-sa-109'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-109.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-108'(suite) -> [];
+'valid-sa-108'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-108.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-107'(suite) -> [];
+'valid-sa-107'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-107.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-106'(suite) -> [];
+'valid-sa-106'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-106.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-105'(suite) -> [];
+'valid-sa-105'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-105.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-104'(suite) -> [];
+'valid-sa-104'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-104.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-103'(suite) -> [];
+'valid-sa-103'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-103.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-102'(suite) -> [];
+'valid-sa-102'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-102.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-101'(suite) -> [];
+'valid-sa-101'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-101.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-100'(suite) -> [];
+'valid-sa-100'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-100.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["recursive xml spec"]}.
+
+'valid-sa-099'(suite) -> [];
+'valid-sa-099'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-099.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-098'(suite) -> [];
+'valid-sa-098'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-098.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-097'(suite) -> [];
+'valid-sa-097'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-097.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-096'(suite) -> [];
+'valid-sa-096'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-096.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-095'(suite) -> [];
+'valid-sa-095'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-095.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-094'(suite) -> [];
+'valid-sa-094'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-094.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-093'(suite) -> [];
+'valid-sa-093'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-093.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-092'(suite) -> [];
+'valid-sa-092'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-092.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-091'(suite) -> [];
+'valid-sa-091'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-091.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-090'(suite) -> [];
+'valid-sa-090'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-090.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-089'(suite) -> [];
+'valid-sa-089'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-089.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-088'(suite) -> [];
+'valid-sa-088'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-088.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-087'(suite) -> [];
+'valid-sa-087'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-087.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-086'(suite) -> [];
+'valid-sa-086'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-086.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-085'(suite) -> [];
+'valid-sa-085'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-085.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-084'(suite) -> [];
+'valid-sa-084'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-084.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-083'(suite) -> [];
+'valid-sa-083'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-083.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-082'(suite) -> [];
+'valid-sa-082'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-082.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-081'(suite) -> [];
+'valid-sa-081'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-081.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-080'(suite) -> [];
+'valid-sa-080'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-080.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-079'(suite) -> [];
+'valid-sa-079'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-079.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-078'(suite) -> [];
+'valid-sa-078'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-078.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-077'(suite) -> [];
+'valid-sa-077'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-077.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-076'(suite) -> [];
+'valid-sa-076'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-076.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-075'(suite) -> [];
+'valid-sa-075'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-075.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-074'(suite) -> [];
+'valid-sa-074'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-074.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-073'(suite) -> [];
+'valid-sa-073'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-073.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-072'(suite) -> [];
+'valid-sa-072'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-072.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-071'(suite) -> [];
+'valid-sa-071'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-071.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-070'(suite) -> [];
+'valid-sa-070'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-070.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-069'(suite) -> [];
+'valid-sa-069'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-069.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-068'(suite) -> [];
+'valid-sa-068'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-068.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-067'(suite) -> [];
+'valid-sa-067'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-067.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-066'(suite) -> [];
+'valid-sa-066'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-066.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-065'(suite) -> [];
+'valid-sa-065'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-065.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-064'(suite) -> [];
+'valid-sa-064'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-064.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["Fails to handle UTF-8 encoded names, when they are converted to atoms"]}.
+
+'valid-sa-063'(suite) -> [];
+'valid-sa-063'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-063.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["Fails to handle Unicode integer (UTF-8) encoded names, when they are converted to atoms"]}.
+
+'valid-sa-062'(suite) -> [];
+'valid-sa-062'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-062.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-061'(suite) -> [];
+'valid-sa-061'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-061.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-060'(suite) -> [];
+'valid-sa-060'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-060.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-059'(suite) -> [];
+'valid-sa-059'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-059.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-058'(suite) -> [];
+'valid-sa-058'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-058.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-057'(suite) -> [];
+'valid-sa-057'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-057.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-056'(suite) -> [];
+'valid-sa-056'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-056.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-055'(suite) -> [];
+'valid-sa-055'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-055.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-054'(suite) -> [];
+'valid-sa-054'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-054.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-053'(suite) -> [];
+'valid-sa-053'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-053.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-052'(suite) -> [];
+'valid-sa-052'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-052.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-051'(suite) -> [];
+'valid-sa-051'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-051.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["Fails to handle Unicode integer (UTF-16) encoded names, when they are converted to atoms"]}.
+'valid-sa-050'(suite) -> [];
+'valid-sa-050'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-050.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-049'(suite) -> [];
+'valid-sa-049'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-049.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-048'(suite) -> [];
+'valid-sa-048'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-048.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-047'(suite) -> [];
+'valid-sa-047'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-047.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-046'(suite) -> [];
+'valid-sa-046'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-046.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-045'(suite) -> [];
+'valid-sa-045'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-045.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-044'(suite) -> [];
+'valid-sa-044'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-044.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-043'(suite) -> [];
+'valid-sa-043'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-043.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-042'(suite) -> [];
+'valid-sa-042'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-042.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-041'(suite) -> [];
+'valid-sa-041'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-041.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-040'(suite) -> [];
+'valid-sa-040'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-040.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-039'(suite) -> [];
+'valid-sa-039'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-039.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-038'(suite) -> [];
+'valid-sa-038'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-038.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-037'(suite) -> [];
+'valid-sa-037'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-037.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-036'(suite) -> [];
+'valid-sa-036'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-036.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-035'(suite) -> [];
+'valid-sa-035'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-035.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-034'(suite) -> [];
+'valid-sa-034'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-034.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-033'(suite) -> [];
+'valid-sa-033'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-033.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-032'(suite) -> [];
+'valid-sa-032'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-032.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-031'(suite) -> [];
+'valid-sa-031'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-031.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-030'(suite) -> [];
+'valid-sa-030'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-030.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-029'(suite) -> [];
+'valid-sa-029'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-029.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-028'(suite) -> [];
+'valid-sa-028'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-028.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-027'(suite) -> [];
+'valid-sa-027'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-027.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-026'(suite) -> [];
+'valid-sa-026'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-026.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-025'(suite) -> [];
+'valid-sa-025'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-025.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-024'(suite) -> [];
+'valid-sa-024'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-024.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-023'(suite) -> [];
+'valid-sa-023'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-023.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-022'(suite) -> [];
+'valid-sa-022'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-022.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-021'(suite) -> [];
+'valid-sa-021'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-021.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-020'(suite) -> [];
+'valid-sa-020'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-020.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-019'(suite) -> [];
+'valid-sa-019'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-019.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-018'(suite) -> [];
+'valid-sa-018'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-018.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-017'(suite) -> [];
+'valid-sa-017'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-017.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-016'(suite) -> [];
+'valid-sa-016'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-016.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-015'(suite) -> [];
+'valid-sa-015'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-015.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-014'(suite) -> [];
+'valid-sa-014'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-014.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-013'(suite) -> [];
+'valid-sa-013'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-013.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-012'(suite) -> [];
+'valid-sa-012'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-012.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-011'(suite) -> [];
+'valid-sa-011'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-011.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-010'(suite) -> [];
+'valid-sa-010'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-010.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-009'(suite) -> [];
+'valid-sa-009'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-009.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-008'(suite) -> [];
+'valid-sa-008'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-008.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-007'(suite) -> [];
+'valid-sa-007'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-007.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-006'(suite) -> [];
+'valid-sa-006'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-006.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-005'(suite) -> [];
+'valid-sa-005'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-005.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-004'(suite) -> [];
+'valid-sa-004'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-004.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-003'(suite) -> [];
+'valid-sa-003'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-003.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-002'(suite) -> [];
+'valid-sa-002'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-002.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'valid-sa-001'(suite) -> [];
+'valid-sa-001'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"valid-sa-001.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'invalid-not-sa-022'(suite) -> [];
+'invalid-not-sa-022'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"invalid-not-sa-022.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'invalid--006'(suite) -> [];
+'invalid--006'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"invalid--006.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'invalid--005'(suite) -> [];
+'invalid--005'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"invalid--005.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'invalid--002'(suite) -> [];
+'invalid--002'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"invalid--002.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-ext-sa-003'(suite) -> [];
+'not-wf-ext-sa-003'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-ext-sa-003.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-ext-sa-002'(suite) -> [];
+'not-wf-ext-sa-002'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-ext-sa-002.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-ext-sa-001'(suite) -> [];
+'not-wf-ext-sa-001'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-ext-sa-001.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-not-sa-009'(suite) -> [];
+'not-wf-not-sa-009'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-not-sa-009.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-not-sa-008'(suite) -> [];
+'not-wf-not-sa-008'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-not-sa-008.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-not-sa-007'(suite) -> [];
+'not-wf-not-sa-007'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-not-sa-007.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-not-sa-006'(suite) -> [];
+'not-wf-not-sa-006'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-not-sa-006.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-not-sa-005'(suite) -> [];
+'not-wf-not-sa-005'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-not-sa-005.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-not-sa-004'(suite) -> [];
+'not-wf-not-sa-004'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-not-sa-004.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-not-sa-003'(suite) -> [];
+'not-wf-not-sa-003'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-not-sa-003.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-not-sa-002'(suite) -> [];
+'not-wf-not-sa-002'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-not-sa-002.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-not-sa-001'(suite) -> [];
+'not-wf-not-sa-001'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-not-sa-001.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-186'(suite) -> [];
+'not-wf-sa-186'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-186.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-185'(suite) -> [];
+'not-wf-sa-185'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-185.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-184'(suite) -> [];
+'not-wf-sa-184'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-184.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-183'(suite) -> [];
+'not-wf-sa-183'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-183.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-182'(suite) -> [];
+'not-wf-sa-182'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-182.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-181'(suite) -> [];
+'not-wf-sa-181'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-181.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-180'(suite) -> [];
+'not-wf-sa-180'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-180.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-179'(suite) -> [];
+'not-wf-sa-179'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-179.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-178'(suite) -> [];
+'not-wf-sa-178'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-178.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-177'(suite) -> [];
+'not-wf-sa-177'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-177.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["do not support UTF-8 (only Latin-1), therefore not ","able to check the illegal FFFF/FFFE (Unicode) characters"]}.
+
+'not-wf-sa-176'(suite) -> [];
+'not-wf-sa-176'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-176.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-175'(suite) -> [];
+'not-wf-sa-175'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-175.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["do not support UTF-8 (only Latin-1), therefore not ","able to check the illegal FFFF/FFFE (Unicode) characters"]}.
+
+'not-wf-sa-174'(suite) -> [];
+'not-wf-sa-174'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-174.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["do not support UTF-8 (only Latin-1), therefore not ","able to check the illegal FFFF/FFFE (Unicode) characters"]}.
+
+'not-wf-sa-173'(suite) -> [];
+'not-wf-sa-173'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-173.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["do not support UTF-8 (only Latin-1), therefore not ","able to check the illegal FFFF/FFFE (Unicode) characters"]}.
+
+'not-wf-sa-172'(suite) -> [];
+'not-wf-sa-172'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-172.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["do not support UTF-8 (only Latin-1), therefore not ","able to check the illegal FFFF/FFFE (Unicode) characters"]}.
+
+'not-wf-sa-171'(suite) -> [];
+'not-wf-sa-171'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-171.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["do not support UTF-8 (only Latin-1), therefore not ","able to check the illegal FFFF/FFFE (Unicode) characters"]}.
+
+'not-wf-sa-170'(suite) -> [];
+'not-wf-sa-170'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-170.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["UTF-8 encoding of UCS-4 characters"]}.
+
+'not-wf-sa-169'(suite) -> [];
+'not-wf-sa-169'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-169.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["UTF-8 encoding of an illegal unpaired surrogate (DC00)"]}.
+
+'not-wf-sa-168'(suite) -> [];
+'not-wf-sa-168'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-168.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["UTF-8 encoding of an illegal unpaired surrogate (D800)"]}.
+
+'not-wf-sa-167'(suite) -> [];
+'not-wf-sa-167'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-167.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["UTF-8 encoding of an illegal FFFE"]}.
+
+'not-wf-sa-166'(suite) -> [];
+'not-wf-sa-166'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-166.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["UTF-8 encoding of an illegal FFFE"]}.
+
+'not-wf-sa-165'(suite) -> [];
+'not-wf-sa-165'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-165.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-164'(suite) -> [];
+'not-wf-sa-164'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-164.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-163'(suite) -> [];
+'not-wf-sa-163'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-163.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-162'(suite) -> [];
+'not-wf-sa-162'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-162.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-161'(suite) -> [];
+'not-wf-sa-161'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-161.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-160'(suite) -> [];
+'not-wf-sa-160'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-160.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-159'(suite) -> [];
+'not-wf-sa-159'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-159.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-158'(suite) -> [];
+'not-wf-sa-158'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-158.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-157'(suite) -> [];
+'not-wf-sa-157'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-157.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-156'(suite) -> [];
+'not-wf-sa-156'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-156.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-155'(suite) -> [];
+'not-wf-sa-155'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-155.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-154'(suite) -> [];
+'not-wf-sa-154'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-154.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-153'(suite) -> [];
+'not-wf-sa-153'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-153.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-152'(suite) -> [];
+'not-wf-sa-152'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-152.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-151'(suite) -> [];
+'not-wf-sa-151'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-151.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["don't bother wath's in the Misc production"]}.
+
+'not-wf-sa-150'(suite) -> [];
+'not-wf-sa-150'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-150.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-149'(suite) -> [];
+'not-wf-sa-149'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-149.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-148'(suite) -> [];
+'not-wf-sa-148'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-148.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-147'(suite) -> [];
+'not-wf-sa-147'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-147.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-146'(suite) -> [];
+'not-wf-sa-146'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-146.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-145'(suite) -> [];
+'not-wf-sa-145'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-145.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-144'(suite) -> [];
+'not-wf-sa-144'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-144.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-143'(suite) -> [];
+'not-wf-sa-143'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-143.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-142'(suite) -> [];
+'not-wf-sa-142'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-142.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-141'(suite) -> [];
+'not-wf-sa-141'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-141.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-140'(suite) -> [];
+'not-wf-sa-140'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-140.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-139'(suite) -> [];
+'not-wf-sa-139'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-139.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-138'(suite) -> [];
+'not-wf-sa-138'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-138.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-137'(suite) -> [];
+'not-wf-sa-137'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-137.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-136'(suite) -> [];
+'not-wf-sa-136'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-136.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-135'(suite) -> [];
+'not-wf-sa-135'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-135.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-134'(suite) -> [];
+'not-wf-sa-134'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-134.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-133'(suite) -> [];
+'not-wf-sa-133'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-133.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-132'(suite) -> [];
+'not-wf-sa-132'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-132.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-131'(suite) -> [];
+'not-wf-sa-131'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-131.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-130'(suite) -> [];
+'not-wf-sa-130'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-130.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-129'(suite) -> [];
+'not-wf-sa-129'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-129.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-128'(suite) -> [];
+'not-wf-sa-128'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-128.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-127'(suite) -> [];
+'not-wf-sa-127'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-127.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-126'(suite) -> [];
+'not-wf-sa-126'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-126.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-125'(suite) -> [];
+'not-wf-sa-125'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-125.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-124'(suite) -> [];
+'not-wf-sa-124'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-124.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-123'(suite) -> [];
+'not-wf-sa-123'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-123.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-122'(suite) -> [];
+'not-wf-sa-122'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-122.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-121'(suite) -> [];
+'not-wf-sa-121'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-121.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-120'(suite) -> [];
+'not-wf-sa-120'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-120.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-119'(suite) -> [];
+'not-wf-sa-119'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-119.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-118'(suite) -> [];
+'not-wf-sa-118'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-118.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-117'(suite) -> [];
+'not-wf-sa-117'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-117.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-116'(suite) -> [];
+'not-wf-sa-116'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-116.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-115'(suite) -> [];
+'not-wf-sa-115'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-115.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-114'(suite) -> [];
+'not-wf-sa-114'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-114.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-113'(suite) -> [];
+'not-wf-sa-113'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-113.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-112'(suite) -> [];
+'not-wf-sa-112'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-112.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-111'(suite) -> [];
+'not-wf-sa-111'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-111.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-110'(suite) -> [];
+'not-wf-sa-110'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-110.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-109'(suite) -> [];
+'not-wf-sa-109'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-109.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-108'(suite) -> [];
+'not-wf-sa-108'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-108.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-107'(suite) -> [];
+'not-wf-sa-107'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-107.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-106'(suite) -> [];
+'not-wf-sa-106'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-106.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-105'(suite) -> [];
+'not-wf-sa-105'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-105.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-104'(suite) -> [];
+'not-wf-sa-104'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-104.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-103'(suite) -> [];
+'not-wf-sa-103'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-103.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-102'(suite) -> [];
+'not-wf-sa-102'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-102.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-101'(suite) -> [];
+'not-wf-sa-101'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-101.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-100'(suite) -> [];
+'not-wf-sa-100'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-100.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-099'(suite) -> [];
+'not-wf-sa-099'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-099.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-098'(suite) -> [];
+'not-wf-sa-098'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-098.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-097'(suite) -> [];
+'not-wf-sa-097'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-097.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-096'(suite) -> [];
+'not-wf-sa-096'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-096.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-095'(suite) -> [];
+'not-wf-sa-095'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-095.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-094'(suite) -> [];
+'not-wf-sa-094'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-094.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-093'(suite) -> [];
+'not-wf-sa-093'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-093.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-092'(suite) -> [];
+'not-wf-sa-092'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-092.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-091'(suite) -> [];
+'not-wf-sa-091'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-091.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-090'(suite) -> [];
+'not-wf-sa-090'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-090.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-089'(suite) -> [];
+'not-wf-sa-089'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-089.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-088'(suite) -> [];
+'not-wf-sa-088'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-088.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-087'(suite) -> [];
+'not-wf-sa-087'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-087.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-086'(suite) -> [];
+'not-wf-sa-086'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-086.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-085'(suite) -> [];
+'not-wf-sa-085'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-085.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-084'(suite) -> [];
+'not-wf-sa-084'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-084.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-083'(suite) -> [];
+'not-wf-sa-083'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-083.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-082'(suite) -> [];
+'not-wf-sa-082'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-082.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-081'(suite) -> [];
+'not-wf-sa-081'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-081.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-080'(suite) -> [];
+'not-wf-sa-080'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-080.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-079'(suite) -> [];
+'not-wf-sa-079'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-079.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-078'(suite) -> [];
+'not-wf-sa-078'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-078.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-077'(suite) -> [];
+'not-wf-sa-077'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-077.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-076'(suite) -> [];
+'not-wf-sa-076'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-076.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-075'(suite) -> [];
+'not-wf-sa-075'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-075.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-074'(suite) -> [];
+'not-wf-sa-074'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-074.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-073'(suite) -> [];
+'not-wf-sa-073'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-073.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-072'(suite) -> [];
+'not-wf-sa-072'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-072.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-071'(suite) -> [];
+'not-wf-sa-071'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-071.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-070'(suite) -> [];
+'not-wf-sa-070'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-070.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-069'(suite) -> [];
+'not-wf-sa-069'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-069.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-068'(suite) -> [];
+'not-wf-sa-068'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-068.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-067'(suite) -> [];
+'not-wf-sa-067'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-067.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-066'(suite) -> [];
+'not-wf-sa-066'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-066.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-065'(suite) -> [];
+'not-wf-sa-065'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-065.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-064'(suite) -> [];
+'not-wf-sa-064'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-064.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-063'(suite) -> [];
+'not-wf-sa-063'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-063.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-062'(suite) -> [];
+'not-wf-sa-062'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-062.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-061'(suite) -> [];
+'not-wf-sa-061'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-061.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-060'(suite) -> [];
+'not-wf-sa-060'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-060.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-059'(suite) -> [];
+'not-wf-sa-059'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-059.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-058'(suite) -> [];
+'not-wf-sa-058'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-058.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-057'(suite) -> [];
+'not-wf-sa-057'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-057.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-056'(suite) -> [];
+'not-wf-sa-056'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-056.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-055'(suite) -> [];
+'not-wf-sa-055'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-055.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-054'(suite) -> [];
+'not-wf-sa-054'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-054.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-053'(suite) -> [];
+'not-wf-sa-053'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-053.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-052'(suite) -> [];
+'not-wf-sa-052'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-052.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-051'(suite) -> [];
+'not-wf-sa-051'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-051.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-050'(suite) -> [];
+'not-wf-sa-050'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-050.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-049'(suite) -> [];
+'not-wf-sa-049'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-049.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-048'(suite) -> [];
+'not-wf-sa-048'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-048.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-047'(suite) -> [];
+'not-wf-sa-047'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-047.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-046'(suite) -> [];
+'not-wf-sa-046'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-046.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-045'(suite) -> [];
+'not-wf-sa-045'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-045.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-044'(suite) -> [];
+'not-wf-sa-044'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-044.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-043'(suite) -> [];
+'not-wf-sa-043'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-043.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-042'(suite) -> [];
+'not-wf-sa-042'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-042.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-041'(suite) -> [];
+'not-wf-sa-041'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-041.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-040'(suite) -> [];
+'not-wf-sa-040'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-040.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-039'(suite) -> [];
+'not-wf-sa-039'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-039.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-038'(suite) -> [];
+'not-wf-sa-038'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-038.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-037'(suite) -> [];
+'not-wf-sa-037'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-037.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-036'(suite) -> [];
+'not-wf-sa-036'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-036.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-035'(suite) -> [];
+'not-wf-sa-035'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-035.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-034'(suite) -> [];
+'not-wf-sa-034'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-034.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-033'(suite) -> [];
+'not-wf-sa-033'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-033.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-032'(suite) -> [];
+'not-wf-sa-032'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-032.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-031'(suite) -> [];
+'not-wf-sa-031'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-031.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-030'(suite) -> [];
+'not-wf-sa-030'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-030.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-029'(suite) -> [];
+'not-wf-sa-029'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-029.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-028'(suite) -> [];
+'not-wf-sa-028'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-028.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-027'(suite) -> [];
+'not-wf-sa-027'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-027.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-026'(suite) -> [];
+'not-wf-sa-026'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-026.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-025'(suite) -> [];
+'not-wf-sa-025'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-025.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-024'(suite) -> [];
+'not-wf-sa-024'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-024.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-023'(suite) -> [];
+'not-wf-sa-023'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-023.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-022'(suite) -> [];
+'not-wf-sa-022'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-022.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-021'(suite) -> [];
+'not-wf-sa-021'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-021.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-020'(suite) -> [];
+'not-wf-sa-020'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-020.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-019'(suite) -> [];
+'not-wf-sa-019'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-019.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-018'(suite) -> [];
+'not-wf-sa-018'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-018.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-017'(suite) -> [];
+'not-wf-sa-017'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-017.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-016'(suite) -> [];
+'not-wf-sa-016'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-016.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-015'(suite) -> [];
+'not-wf-sa-015'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-015.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-014'(suite) -> [];
+'not-wf-sa-014'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-014.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-013'(suite) -> [];
+'not-wf-sa-013'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-013.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-012'(suite) -> [];
+'not-wf-sa-012'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-012.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-011'(suite) -> [];
+'not-wf-sa-011'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-011.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-010'(suite) -> [];
+'not-wf-sa-010'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-010.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-009'(suite) -> [];
+'not-wf-sa-009'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-009.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-008'(suite) -> [];
+'not-wf-sa-008'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-008.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-007'(suite) -> [];
+'not-wf-sa-007'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-007.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-006'(suite) -> [];
+'not-wf-sa-006'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-006.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-005'(suite) -> [];
+'not-wf-sa-005'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-005.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-004'(suite) -> [];
+'not-wf-sa-004'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-004.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-003'(suite) -> [];
+'not-wf-sa-003'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-003.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-002'(suite) -> [];
+'not-wf-sa-002'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-002.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'not-wf-sa-001'(suite) -> [];
+'not-wf-sa-001'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),xmltest,"not-wf-sa-001.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+%%----------------------------------------------------------------------
+
+'japanese-weekly-utf-8'(suite) -> [];
+'japanese-weekly-utf-8'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),japanese,"japanese-weekly-utf-8.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["UTF-8 encoding of japanese characters"]}.
+
+'japanese-weekly-utf-16'(suite) -> [];
+'japanese-weekly-utf-16'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),japanese,"japanese-weekly-utf-16.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["Test support for UTF-16 encoding, and XML names which contain Japanese characters."]}.
+
+'japanese-weekly-shift_jis'(suite) -> [];
+'japanese-weekly-shift_jis'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),japanese,"japanese-weekly-shift_jis.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'japanese-weekly-little'(suite) -> [];
+'japanese-weekly-little'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),japanese,"japanese-weekly-little.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["Test support for little-endian UTF-16 encoding, and XML names which contain Japanese characters."]}.
+
+'japanese-weekly-iso-2022-jp'(suite) -> [];
+'japanese-weekly-iso-2022-jp'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),japanese,"japanese-weekly-iso-2022-jp.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'japanese-weekly-euc-jp'(suite) -> [];
+'japanese-weekly-euc-jp'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),japanese,"japanese-weekly-euc-jp.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'japanese-pr-xml-utf-8'(suite) -> [];
+'japanese-pr-xml-utf-8'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),japanese,"japanese-pr-xml-utf-8.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["Test support for UTF-8 text which relies on Japanese characters"]}.
+
+'japanese-pr-xml-utf-16'(suite) -> [];
+'japanese-pr-xml-utf-16'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),japanese,"japanese-pr-xml-utf-16.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["Test support UTF-16 text which relies on Japanese characters."]}.
+
+'japanese-pr-xml-shift_jis'(suite) -> [];
+'japanese-pr-xml-shift_jis'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),japanese,"japanese-pr-xml-shift_jis.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'japanese-pr-xml-little'(suite) -> [];
+'japanese-pr-xml-little'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),japanese,"japanese-pr-xml-little.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["Test support for little-endian UTF-16 text which relies on Japanese characters."]}.
+
+'japanese-pr-xml-iso-2022-jp'(suite) -> [];
+'japanese-pr-xml-iso-2022-jp'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),japanese,"japanese-pr-xml-iso-2022-jp.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'japanese-pr-xml-euc-jp'(suite) -> [];
+'japanese-pr-xml-euc-jp'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),japanese,"japanese-pr-xml-euc-jp.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+%%----------------------------------------------------------------------
+
+'o-p11pass1'(suite) -> [];
+'o-p11pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p11pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p76fail4'(suite) -> [];
+'o-p76fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p76fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p76fail3'(suite) -> [];
+'o-p76fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p76fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p76fail2'(suite) -> [];
+'o-p76fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p76fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p76fail1'(suite) -> [];
+'o-p76fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p76fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p75fail6'(suite) -> [];
+'o-p75fail6'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p75fail6.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p75fail5'(suite) -> [];
+'o-p75fail5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p75fail5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p75fail4'(suite) -> [];
+'o-p75fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p75fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p75fail3'(suite) -> [];
+'o-p75fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p75fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p75fail2'(suite) -> [];
+'o-p75fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p75fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p75fail1'(suite) -> [];
+'o-p75fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p75fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p74fail3'(suite) -> [];
+'o-p74fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p74fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p74fail2'(suite) -> [];
+'o-p74fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p74fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p74fail1'(suite) -> [];
+'o-p74fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p74fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p73fail5'(suite) -> [];
+'o-p73fail5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p73fail5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p73fail4'(suite) -> [];
+'o-p73fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p73fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p73fail3'(suite) -> [];
+'o-p73fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p73fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p73fail2'(suite) -> [];
+'o-p73fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p73fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p73fail1'(suite) -> [];
+'o-p73fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p73fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p72fail4'(suite) -> [];
+'o-p72fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p72fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p72fail3'(suite) -> [];
+'o-p72fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p72fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p72fail2'(suite) -> [];
+'o-p72fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p72fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p72fail1'(suite) -> [];
+'o-p72fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p72fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p71fail4'(suite) -> [];
+'o-p71fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p71fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p71fail3'(suite) -> [];
+'o-p71fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p71fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p71fail2'(suite) -> [];
+'o-p71fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p71fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p71fail1'(suite) -> [];
+'o-p71fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p71fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p70fail1'(suite) -> [];
+'o-p70fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p70fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p69fail3'(suite) -> [];
+'o-p69fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p69fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p69fail2'(suite) -> [];
+'o-p69fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p69fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p69fail1'(suite) -> [];
+'o-p69fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p69fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p68fail3'(suite) -> [];
+'o-p68fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p68fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p68fail2'(suite) -> [];
+'o-p68fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p68fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p68fail1'(suite) -> [];
+'o-p68fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p68fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p66fail6'(suite) -> [];
+'o-p66fail6'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p66fail6.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p66fail5'(suite) -> [];
+'o-p66fail5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p66fail5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p66fail4'(suite) -> [];
+'o-p66fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p66fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p66fail3'(suite) -> [];
+'o-p66fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p66fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p66fail2'(suite) -> [];
+'o-p66fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p66fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p66fail1'(suite) -> [];
+'o-p66fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p66fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p64fail2'(suite) -> [];
+'o-p64fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p64fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p64fail1'(suite) -> [];
+'o-p64fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p64fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p63fail2'(suite) -> [];
+'o-p63fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p63fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p63fail1'(suite) -> [];
+'o-p63fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p63fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p62fail2'(suite) -> [];
+'o-p62fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p62fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p62fail1'(suite) -> [];
+'o-p62fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p62fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p61fail1'(suite) -> [];
+'o-p61fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p61fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p60fail5'(suite) -> [];
+'o-p60fail5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p60fail5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p60fail4'(suite) -> [];
+'o-p60fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p60fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p60fail3'(suite) -> [];
+'o-p60fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p60fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p60fail2'(suite) -> [];
+'o-p60fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p60fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p60fail1'(suite) -> [];
+'o-p60fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p60fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p59fail3'(suite) -> [];
+'o-p59fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p59fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p59fail2'(suite) -> [];
+'o-p59fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p59fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p59fail1'(suite) -> [];
+'o-p59fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p59fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p58fail8'(suite) -> [];
+'o-p58fail8'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p58fail8.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p58fail7'(suite) -> [];
+'o-p58fail7'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p58fail7.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p58fail6'(suite) -> [];
+'o-p58fail6'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p58fail6.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p58fail5'(suite) -> [];
+'o-p58fail5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p58fail5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p58fail4'(suite) -> [];
+'o-p58fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p58fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p58fail3'(suite) -> [];
+'o-p58fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p58fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p58fail2'(suite) -> [];
+'o-p58fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p58fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p58fail1'(suite) -> [];
+'o-p58fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p58fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p57fail1'(suite) -> [];
+'o-p57fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p57fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p56fail5'(suite) -> [];
+'o-p56fail5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p56fail5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p56fail4'(suite) -> [];
+'o-p56fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p56fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p56fail3'(suite) -> [];
+'o-p56fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p56fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p56fail2'(suite) -> [];
+'o-p56fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p56fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p56fail1'(suite) -> [];
+'o-p56fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p56fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p55fail1'(suite) -> [];
+'o-p55fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p55fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p54fail1'(suite) -> [];
+'o-p54fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p54fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p53fail5'(suite) -> [];
+'o-p53fail5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p53fail5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p53fail4'(suite) -> [];
+'o-p53fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p53fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p53fail3'(suite) -> [];
+'o-p53fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p53fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p53fail2'(suite) -> [];
+'o-p53fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p53fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p53fail1'(suite) -> [];
+'o-p53fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p53fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p52fail2'(suite) -> [];
+'o-p52fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p52fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p52fail1'(suite) -> [];
+'o-p52fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p52fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p51fail7'(suite) -> [];
+'o-p51fail7'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p51fail7.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p51fail6'(suite) -> [];
+'o-p51fail6'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p51fail6.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p51fail5'(suite) -> [];
+'o-p51fail5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p51fail5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p51fail4'(suite) -> [];
+'o-p51fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p51fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p51fail3'(suite) -> [];
+'o-p51fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p51fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p51fail2'(suite) -> [];
+'o-p51fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p51fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p51fail1'(suite) -> [];
+'o-p51fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p51fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p50fail1'(suite) -> [];
+'o-p50fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p50fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p49fail1'(suite) -> [];
+'o-p49fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p49fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p48fail2'(suite) -> [];
+'o-p48fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p48fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p48fail1'(suite) -> [];
+'o-p48fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p48fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p47fail4'(suite) -> [];
+'o-p47fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p47fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p47fail3'(suite) -> [];
+'o-p47fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p47fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p47fail2'(suite) -> [];
+'o-p47fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p47fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p47fail1'(suite) -> [];
+'o-p47fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p47fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p46fail6'(suite) -> [];
+'o-p46fail6'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p46fail6.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p46fail5'(suite) -> [];
+'o-p46fail5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p46fail5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p46fail4'(suite) -> [];
+'o-p46fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p46fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p46fail3'(suite) -> [];
+'o-p46fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p46fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p46fail2'(suite) -> [];
+'o-p46fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p46fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p46fail1'(suite) -> [];
+'o-p46fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p46fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p45fail4'(suite) -> [];
+'o-p45fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p45fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p45fail3'(suite) -> [];
+'o-p45fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p45fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p45fail2'(suite) -> [];
+'o-p45fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p45fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p45fail1'(suite) -> [];
+'o-p45fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p45fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p44fail5'(suite) -> [];
+'o-p44fail5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p44fail5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p44fail4'(suite) -> [];
+'o-p44fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p44fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p44fail3'(suite) -> [];
+'o-p44fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p44fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p44fail2'(suite) -> [];
+'o-p44fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p44fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p44fail1'(suite) -> [];
+'o-p44fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p44fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p43fail3'(suite) -> [];
+'o-p43fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p43fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p43fail2'(suite) -> [];
+'o-p43fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p43fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p43fail1'(suite) -> [];
+'o-p43fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p43fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p42fail3'(suite) -> [];
+'o-p42fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p42fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p42fail2'(suite) -> [];
+'o-p42fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p42fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p42fail1'(suite) -> [];
+'o-p42fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p42fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p41fail3'(suite) -> [];
+'o-p41fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p41fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p41fail2'(suite) -> [];
+'o-p41fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p41fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p41fail1'(suite) -> [];
+'o-p41fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p41fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p40fail4'(suite) -> [];
+'o-p40fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p40fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p40fail3'(suite) -> [];
+'o-p40fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p40fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p40fail2'(suite) -> [];
+'o-p40fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p40fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p40fail1'(suite) -> [];
+'o-p40fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p40fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p39fail5'(suite) -> [];
+'o-p39fail5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p39fail5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p39fail4'(suite) -> [];
+'o-p39fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p39fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p39fail3'(suite) -> [];
+'o-p39fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p39fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p39fail2'(suite) -> [];
+'o-p39fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p39fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p39fail1'(suite) -> [];
+'o-p39fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p39fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p32fail5'(suite) -> [];
+'o-p32fail5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p32fail5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p32fail4'(suite) -> [];
+'o-p32fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p32fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p32fail3'(suite) -> [];
+'o-p32fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p32fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p32fail2'(suite) -> [];
+'o-p32fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p32fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p32fail1'(suite) -> [];
+'o-p32fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p32fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p31fail1'(suite) -> [];
+'o-p31fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p31fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p30fail1'(suite) -> [];
+'o-p30fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p30fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p29fail1'(suite) -> [];
+'o-p29fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p29fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p28fail1'(suite) -> [];
+'o-p28fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p28fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p27fail1'(suite) -> [];
+'o-p27fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p27fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p26fail2'(suite) -> [];
+'o-p26fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p26fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p26fail1'(suite) -> [];
+'o-p26fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p26fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p25fail1'(suite) -> [];
+'o-p25fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p25fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p24fail2'(suite) -> [];
+'o-p24fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p24fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p24fail1'(suite) -> [];
+'o-p24fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p24fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p23fail5'(suite) -> [];
+'o-p23fail5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p23fail5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p23fail4'(suite) -> [];
+'o-p23fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p23fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p23fail3'(suite) -> [];
+'o-p23fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p23fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p23fail2'(suite) -> [];
+'o-p23fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p23fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p23fail1'(suite) -> [];
+'o-p23fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p23fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p22fail2'(suite) -> [];
+'o-p22fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p22fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p22fail1'(suite) -> [];
+'o-p22fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p22fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p18fail3'(suite) -> [];
+'o-p18fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p18fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p18fail2'(suite) -> [];
+'o-p18fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p18fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p18fail1'(suite) -> [];
+'o-p18fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p18fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p16fail3'(suite) -> [];
+'o-p16fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p16fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p16fail2'(suite) -> [];
+'o-p16fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p16fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p16fail1'(suite) -> [];
+'o-p16fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p16fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p15fail3'(suite) -> [];
+'o-p15fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p15fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p15fail2'(suite) -> [];
+'o-p15fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p15fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p15fail1'(suite) -> [];
+'o-p15fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p15fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p14fail3'(suite) -> [];
+'o-p14fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p14fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p14fail2'(suite) -> [];
+'o-p14fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p14fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p14fail1'(suite) -> [];
+'o-p14fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p14fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p12fail7'(suite) -> [];
+'o-p12fail7'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p12fail7.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p12fail6'(suite) -> [];
+'o-p12fail6'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p12fail6.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p12fail5'(suite) -> [];
+'o-p12fail5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p12fail5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p12fail4'(suite) -> [];
+'o-p12fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p12fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p12fail3'(suite) -> [];
+'o-p12fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p12fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p12fail2'(suite) -> [];
+'o-p12fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p12fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p12fail1'(suite) -> [];
+'o-p12fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p12fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p11fail2'(suite) -> [];
+'o-p11fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p11fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p11fail1'(suite) -> [];
+'o-p11fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p11fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p10fail3'(suite) -> [];
+'o-p10fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p10fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p10fail2'(suite) -> [];
+'o-p10fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p10fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p10fail1'(suite) -> [];
+'o-p10fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p10fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p09fail5'(suite) -> [];
+'o-p09fail5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p09fail5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p09fail4'(suite) -> [];
+'o-p09fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p09fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p09fail3'(suite) -> [];
+'o-p09fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p09fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p09fail2'(suite) -> [];
+'o-p09fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p09fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p09fail1'(suite) -> [];
+'o-p09fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p09fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p05fail5'(suite) -> [];
+'o-p05fail5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p05fail5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p05fail4'(suite) -> [];
+'o-p05fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p05fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p05fail3'(suite) -> [];
+'o-p05fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p05fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p05fail2'(suite) -> [];
+'o-p05fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p05fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p05fail1'(suite) -> [];
+'o-p05fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p05fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p04fail3'(suite) -> [];
+'o-p04fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p04fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p04fail2'(suite) -> [];
+'o-p04fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p04fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p04fail1'(suite) -> [];
+'o-p04fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p04fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail9'(suite) -> [];
+'o-p03fail9'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail9.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail8'(suite) -> [];
+'o-p03fail8'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail8.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail7'(suite) -> [];
+'o-p03fail7'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail7.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail5'(suite) -> [];
+'o-p03fail5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail4'(suite) -> [];
+'o-p03fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail3'(suite) -> [];
+'o-p03fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail29'(suite) -> [];
+'o-p03fail29'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail29.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail28'(suite) -> [];
+'o-p03fail28'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail28.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail27'(suite) -> [];
+'o-p03fail27'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail27.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail26'(suite) -> [];
+'o-p03fail26'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail26.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail25'(suite) -> [];
+'o-p03fail25'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail25.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail24'(suite) -> [];
+'o-p03fail24'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail24.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail23'(suite) -> [];
+'o-p03fail23'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail23.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail22'(suite) -> [];
+'o-p03fail22'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail22.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail21'(suite) -> [];
+'o-p03fail21'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail21.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail20'(suite) -> [];
+'o-p03fail20'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail20.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail2'(suite) -> [];
+'o-p03fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail19'(suite) -> [];
+'o-p03fail19'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail19.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail18'(suite) -> [];
+'o-p03fail18'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail18.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail17'(suite) -> [];
+'o-p03fail17'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail17.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail16'(suite) -> [];
+'o-p03fail16'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail16.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail15'(suite) -> [];
+'o-p03fail15'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail15.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail14'(suite) -> [];
+'o-p03fail14'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail14.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail13'(suite) -> [];
+'o-p03fail13'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail13.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail12'(suite) -> [];
+'o-p03fail12'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail12.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail11'(suite) -> [];
+'o-p03fail11'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail11.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail10'(suite) -> [];
+'o-p03fail10'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail10.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p03fail1'(suite) -> [];
+'o-p03fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail9'(suite) -> [];
+'o-p02fail9'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail9.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail8'(suite) -> [];
+'o-p02fail8'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail8.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail7'(suite) -> [];
+'o-p02fail7'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail7.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail6'(suite) -> [];
+'o-p02fail6'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail6.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail5'(suite) -> [];
+'o-p02fail5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail4'(suite) -> [];
+'o-p02fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail31'(suite) -> [];
+'o-p02fail31'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail31.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail30'(suite) -> [];
+'o-p02fail30'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail30.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail3'(suite) -> [];
+'o-p02fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail29'(suite) -> [];
+'o-p02fail29'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail29.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail28'(suite) -> [];
+'o-p02fail28'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail28.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail27'(suite) -> [];
+'o-p02fail27'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail27.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail26'(suite) -> [];
+'o-p02fail26'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail26.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail25'(suite) -> [];
+'o-p02fail25'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail25.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail24'(suite) -> [];
+'o-p02fail24'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail24.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail23'(suite) -> [];
+'o-p02fail23'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail23.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail22'(suite) -> [];
+'o-p02fail22'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail22.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail21'(suite) -> [];
+'o-p02fail21'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail21.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail20'(suite) -> [];
+'o-p02fail20'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail20.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail2'(suite) -> [];
+'o-p02fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail19'(suite) -> [];
+'o-p02fail19'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail19.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail18'(suite) -> [];
+'o-p02fail18'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail18.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail17'(suite) -> [];
+'o-p02fail17'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail17.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail16'(suite) -> [];
+'o-p02fail16'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail16.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail15'(suite) -> [];
+'o-p02fail15'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail15.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail14'(suite) -> [];
+'o-p02fail14'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail14.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail13'(suite) -> [];
+'o-p02fail13'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail13.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail12'(suite) -> [];
+'o-p02fail12'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail12.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail11'(suite) -> [];
+'o-p02fail11'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail11.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail10'(suite) -> [];
+'o-p02fail10'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail10.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p02fail1'(suite) -> [];
+'o-p02fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p02fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p01fail4'(suite) -> [];
+'o-p01fail4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p01fail4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p01fail3'(suite) -> [];
+'o-p01fail3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p01fail3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p01fail2'(suite) -> [];
+'o-p01fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p01fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p01fail1'(suite) -> [];
+'o-p01fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p01fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-e2'(suite) -> [];
+'o-e2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-e2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p75pass1'(suite) -> [];
+'o-p75pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p75pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p74pass1'(suite) -> [];
+'o-p74pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p74pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p66pass1'(suite) -> [];
+'o-p66pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p66pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p44pass5'(suite) -> [];
+'o-p44pass5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p44pass5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p44pass4'(suite) -> [];
+'o-p44pass4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p44pass4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p44pass3'(suite) -> [];
+'o-p44pass3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p44pass3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p44pass2'(suite) -> [];
+'o-p44pass2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p44pass2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p44pass1'(suite) -> [];
+'o-p44pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p44pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p42pass2'(suite) -> [];
+'o-p42pass2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p42pass2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p42pass1'(suite) -> [];
+'o-p42pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p42pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p41pass2'(suite) -> [];
+'o-p41pass2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p41pass2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p41pass1'(suite) -> [];
+'o-p41pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p41pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p40pass4'(suite) -> [];
+'o-p40pass4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p40pass4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p40pass3'(suite) -> [];
+'o-p40pass3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p40pass3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p40pass2'(suite) -> [];
+'o-p40pass2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p40pass2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p40pass1'(suite) -> [];
+'o-p40pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p40pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p39pass2'(suite) -> [];
+'o-p39pass2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p39pass2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p39pass1'(suite) -> [];
+'o-p39pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p39pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p32pass2'(suite) -> [];
+'o-p32pass2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p32pass2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p32pass1'(suite) -> [];
+'o-p32pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p32pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p27pass4'(suite) -> [];
+'o-p27pass4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p27pass4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p27pass3'(suite) -> [];
+'o-p27pass3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p27pass3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p27pass2'(suite) -> [];
+'o-p27pass2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p27pass2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p27pass1'(suite) -> [];
+'o-p27pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p27pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p26pass1'(suite) -> [];
+'o-p26pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p26pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p25pass2'(suite) -> [];
+'o-p25pass2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p25pass2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p25pass1'(suite) -> [];
+'o-p25pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p25pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p24pass4'(suite) -> [];
+'o-p24pass4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p24pass4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p24pass3'(suite) -> [];
+'o-p24pass3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p24pass3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p24pass2'(suite) -> [];
+'o-p24pass2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p24pass2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p24pass1'(suite) -> [];
+'o-p24pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p24pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p23pass4'(suite) -> [];
+'o-p23pass4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p23pass4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p23pass3'(suite) -> [];
+'o-p23pass3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p23pass3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p23pass2'(suite) -> [];
+'o-p23pass2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p23pass2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p23pass1'(suite) -> [];
+'o-p23pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p23pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p22pass3'(suite) -> [];
+'o-p22pass3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p22pass3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p22pass2'(suite) -> [];
+'o-p22pass2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p22pass2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p22pass1'(suite) -> [];
+'o-p22pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p22pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p18pass1'(suite) -> [];
+'o-p18pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p18pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p16pass3'(suite) -> [];
+'o-p16pass3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p16pass3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p16pass2'(suite) -> [];
+'o-p16pass2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p16pass2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p16pass1'(suite) -> [];
+'o-p16pass1'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p16pass1.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["Hard to interpret the meaning of the XML1.0 spec. See section 2.6 and 2.3."]}.
+
+'o-p15pass1'(suite) -> [];
+'o-p15pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p15pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p14pass1'(suite) -> [];
+'o-p14pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p14pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p10pass1'(suite) -> [];
+'o-p10pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p10pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p08fail2'(suite) -> [];
+'o-p08fail2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p08fail2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p08fail1'(suite) -> [];
+'o-p08fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p08fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p06fail1'(suite) -> [];
+'o-p06fail1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p06fail1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p05pass1'(suite) -> [];
+'o-p05pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p05pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p04pass1'(suite) -> [];
+'o-p04pass1'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p04pass1.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["Fails to handle name containing characters > x#ff, since they are converted to atoms"]}.
+'o-p03pass1'(suite) -> [];
+'o-p03pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p03pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p01pass3'(suite) -> [];
+'o-p01pass3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p01pass3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p01pass1'(suite) -> [];
+'o-p01pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p01pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p76pass1'(suite) -> [];
+'o-p76pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p76pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p73pass1'(suite) -> [];
+'o-p73pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p73pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p72pass1'(suite) -> [];
+'o-p72pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p72pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p71pass1'(suite) -> [];
+'o-p71pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p71pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p70pass1'(suite) -> [];
+'o-p70pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p70pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p69pass1'(suite) -> [];
+'o-p69pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p69pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p68pass1'(suite) -> [];
+'o-p68pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p68pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p64pass1'(suite) -> [];
+'o-p64pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p64pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p63pass1'(suite) -> [];
+'o-p63pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p63pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p62pass1'(suite) -> [];
+'o-p62pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p62pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p61pass1'(suite) -> [];
+'o-p61pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p61pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p60pass1'(suite) -> [];
+'o-p60pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p60pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p59pass1'(suite) -> [];
+'o-p59pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p59pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p58pass1'(suite) -> [];
+'o-p58pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p58pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p57pass1'(suite) -> [];
+'o-p57pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p57pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p56pass1'(suite) -> [];
+'o-p56pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p56pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p55pass1'(suite) -> [];
+'o-p55pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p55pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p54pass1'(suite) -> [];
+'o-p54pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p54pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p53pass1'(suite) -> [];
+'o-p53pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p53pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p52pass1'(suite) -> [];
+'o-p52pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p52pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p51pass1'(suite) -> [];
+'o-p51pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p51pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p50pass1'(suite) -> [];
+'o-p50pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p50pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p49pass1'(suite) -> [];
+'o-p49pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p49pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p48pass1'(suite) -> [];
+'o-p48pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p48pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p47pass1'(suite) -> [];
+'o-p47pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p47pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p46pass1'(suite) -> [];
+'o-p46pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p46pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p45pass1'(suite) -> [];
+'o-p45pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p45pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p43pass1'(suite) -> [];
+'o-p43pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p43pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p31pass2'(suite) -> [];
+'o-p31pass2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p31pass2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p31pass1'(suite) -> [];
+'o-p31pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p31pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p30pass2'(suite) -> [];
+'o-p30pass2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p30pass2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p30pass1'(suite) -> [];
+'o-p30pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p30pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p29pass1'(suite) -> [];
+'o-p29pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p29pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p28pass5'(suite) -> [];
+'o-p28pass5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p28pass5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p28pass4'(suite) -> [];
+'o-p28pass4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p28pass4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p28pass3'(suite) -> [];
+'o-p28pass3'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p28pass3.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p28pass1'(suite) -> [];
+'o-p28pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p28pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p22pass6'(suite) -> [];
+'o-p22pass6'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p22pass6.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p22pass5'(suite) -> [];
+'o-p22pass5'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p22pass5.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p22pass4'(suite) -> [];
+'o-p22pass4'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p22pass4.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p12pass1'(suite) -> [];
+'o-p12pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p12pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p09pass1'(suite) -> [];
+'o-p09pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p09pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p08pass1'(suite) -> [];
+'o-p08pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p08pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p07pass1'(suite) -> [];
+'o-p07pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p07pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p06pass1'(suite) -> [];
+'o-p06pass1'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p06pass1.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'o-p01pass2'(suite) -> [];
+'o-p01pass2'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),oasis,"o-p01pass2.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+%%----------------------------------------------------------------------
+
+'ibm-invalid-P76-ibm76i01'(suite) -> [];
+'ibm-invalid-P76-ibm76i01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P76-ibm76i01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P69-ibm69i04'(suite) -> [];
+'ibm-invalid-P69-ibm69i04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P69-ibm69i04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P69-ibm69i03'(suite) -> [];
+'ibm-invalid-P69-ibm69i03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P69-ibm69i03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P69-ibm69i02'(suite) -> [];
+'ibm-invalid-P69-ibm69i02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P69-ibm69i02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P69-ibm69i01'(suite) -> [];
+'ibm-invalid-P69-ibm69i01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P69-ibm69i01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P68-ibm68i04'(suite) -> [];
+'ibm-invalid-P68-ibm68i04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P68-ibm68i04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P68-ibm68i03'(suite) -> [];
+'ibm-invalid-P68-ibm68i03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P68-ibm68i03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P68-ibm68i02'(suite) -> [];
+'ibm-invalid-P68-ibm68i02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P68-ibm68i02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P68-ibm68i01'(suite) -> [];
+'ibm-invalid-P68-ibm68i01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P68-ibm68i01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P60-ibm60i04'(suite) -> [];
+'ibm-invalid-P60-ibm60i04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P60-ibm60i04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P60-ibm60i03'(suite) -> [];
+'ibm-invalid-P60-ibm60i03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P60-ibm60i03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P60-ibm60i02'(suite) -> [];
+'ibm-invalid-P60-ibm60i02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P60-ibm60i02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P60-ibm60i01'(suite) -> [];
+'ibm-invalid-P60-ibm60i01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P60-ibm60i01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P59-ibm59i01'(suite) -> [];
+'ibm-invalid-P59-ibm59i01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P59-ibm59i01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P58-ibm58i02'(suite) -> [];
+'ibm-invalid-P58-ibm58i02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P58-ibm58i02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P58-ibm58i01'(suite) -> [];
+'ibm-invalid-P58-ibm58i01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P58-ibm58i01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P56-ibm56i18'(suite) -> [];
+'ibm-invalid-P56-ibm56i18'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P56-ibm56i18.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P56-ibm56i17'(suite) -> [];
+'ibm-invalid-P56-ibm56i17'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P56-ibm56i17.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P56-ibm56i16'(suite) -> [];
+'ibm-invalid-P56-ibm56i16'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P56-ibm56i16.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P56-ibm56i15'(suite) -> [];
+'ibm-invalid-P56-ibm56i15'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P56-ibm56i15.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P56-ibm56i14'(suite) -> [];
+'ibm-invalid-P56-ibm56i14'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P56-ibm56i14.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P56-ibm56i13'(suite) -> [];
+'ibm-invalid-P56-ibm56i13'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P56-ibm56i13.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P56-ibm56i12'(suite) -> [];
+'ibm-invalid-P56-ibm56i12'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P56-ibm56i12.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P56-ibm56i11'(suite) -> [];
+'ibm-invalid-P56-ibm56i11'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P56-ibm56i11.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P56-ibm56i10'(suite) -> [];
+'ibm-invalid-P56-ibm56i10'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P56-ibm56i10.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P56-ibm56i09'(suite) -> [];
+'ibm-invalid-P56-ibm56i09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P56-ibm56i09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P56-ibm56i08'(suite) -> [];
+'ibm-invalid-P56-ibm56i08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P56-ibm56i08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P56-ibm56i07'(suite) -> [];
+'ibm-invalid-P56-ibm56i07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P56-ibm56i07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P56-ibm56i06'(suite) -> [];
+'ibm-invalid-P56-ibm56i06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P56-ibm56i06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P56-ibm56i05'(suite) -> [];
+'ibm-invalid-P56-ibm56i05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P56-ibm56i05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P56-ibm56i03'(suite) -> [];
+'ibm-invalid-P56-ibm56i03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P56-ibm56i03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P56-ibm56i02'(suite) -> [];
+'ibm-invalid-P56-ibm56i02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P56-ibm56i02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P56-ibm56i01'(suite) -> [];
+'ibm-invalid-P56-ibm56i01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P56-ibm56i01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P51-ibm51i03'(suite) -> [];
+'ibm-invalid-P51-ibm51i03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P51-ibm51i03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P51-ibm51i01'(suite) -> [];
+'ibm-invalid-P51-ibm51i01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P51-ibm51i01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P50-ibm50i01'(suite) -> [];
+'ibm-invalid-P50-ibm50i01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P50-ibm50i01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P49-ibm49i01'(suite) -> [];
+'ibm-invalid-P49-ibm49i01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P49-ibm49i01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P45-ibm45i01'(suite) -> [];
+'ibm-invalid-P45-ibm45i01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P45-ibm45i01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P41-ibm41i02'(suite) -> [];
+'ibm-invalid-P41-ibm41i02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P41-ibm41i02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P41-ibm41i01'(suite) -> [];
+'ibm-invalid-P41-ibm41i01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P41-ibm41i01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P39-ibm39i04'(suite) -> [];
+'ibm-invalid-P39-ibm39i04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P39-ibm39i04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P39-ibm39i03'(suite) -> [];
+'ibm-invalid-P39-ibm39i03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P39-ibm39i03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P39-ibm39i02'(suite) -> [];
+'ibm-invalid-P39-ibm39i02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P39-ibm39i02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P39-ibm39i01'(suite) -> [];
+'ibm-invalid-P39-ibm39i01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P39-ibm39i01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P32-ibm32i04'(suite) -> [];
+'ibm-invalid-P32-ibm32i04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P32-ibm32i04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P32-ibm32i03'(suite) -> [];
+'ibm-invalid-P32-ibm32i03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P32-ibm32i03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P32-ibm32i01'(suite) -> [];
+'ibm-invalid-P32-ibm32i01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P32-ibm32i01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-invalid-P28-ibm28i01'(suite) -> [];
+'ibm-invalid-P28-ibm28i01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-invalid-P28-ibm28i01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+%%----------------------------------------------------------------------
+
+'ibm-not-wf-P89-ibm89n12'(suite) -> [];
+'ibm-not-wf-P89-ibm89n12'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P89-ibm89n12.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P89-ibm89n11'(suite) -> [];
+'ibm-not-wf-P89-ibm89n11'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P89-ibm89n11.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P89-ibm89n10'(suite) -> [];
+'ibm-not-wf-P89-ibm89n10'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P89-ibm89n10.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P89-ibm89n09'(suite) -> [];
+'ibm-not-wf-P89-ibm89n09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P89-ibm89n09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P89-ibm89n08'(suite) -> [];
+'ibm-not-wf-P89-ibm89n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P89-ibm89n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P89-ibm89n07'(suite) -> [];
+'ibm-not-wf-P89-ibm89n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P89-ibm89n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P89-ibm89n06'(suite) -> [];
+'ibm-not-wf-P89-ibm89n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P89-ibm89n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P89-ibm89n05'(suite) -> [];
+'ibm-not-wf-P89-ibm89n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P89-ibm89n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P89-ibm89n04'(suite) -> [];
+'ibm-not-wf-P89-ibm89n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P89-ibm89n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P89-ibm89n03'(suite) -> [];
+'ibm-not-wf-P89-ibm89n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P89-ibm89n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P89-ibm89n02'(suite) -> [];
+'ibm-not-wf-P89-ibm89n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P89-ibm89n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P89-ibm89n01'(suite) -> [];
+'ibm-not-wf-P89-ibm89n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P89-ibm89n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P88-ibm88n16'(suite) -> [];
+'ibm-not-wf-P88-ibm88n16'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P88-ibm88n16.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P88-ibm88n15'(suite) -> [];
+'ibm-not-wf-P88-ibm88n15'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P88-ibm88n15.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P88-ibm88n14'(suite) -> [];
+'ibm-not-wf-P88-ibm88n14'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P88-ibm88n14.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P88-ibm88n13'(suite) -> [];
+'ibm-not-wf-P88-ibm88n13'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P88-ibm88n13.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P88-ibm88n12'(suite) -> [];
+'ibm-not-wf-P88-ibm88n12'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P88-ibm88n12.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P88-ibm88n11'(suite) -> [];
+'ibm-not-wf-P88-ibm88n11'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P88-ibm88n11.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P88-ibm88n10'(suite) -> [];
+'ibm-not-wf-P88-ibm88n10'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P88-ibm88n10.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P88-ibm88n09'(suite) -> [];
+'ibm-not-wf-P88-ibm88n09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P88-ibm88n09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P88-ibm88n08'(suite) -> [];
+'ibm-not-wf-P88-ibm88n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P88-ibm88n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P88-ibm88n06'(suite) -> [];
+'ibm-not-wf-P88-ibm88n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P88-ibm88n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P88-ibm88n05'(suite) -> [];
+'ibm-not-wf-P88-ibm88n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P88-ibm88n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P88-ibm88n04'(suite) -> [];
+'ibm-not-wf-P88-ibm88n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P88-ibm88n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P88-ibm88n03'(suite) -> [];
+'ibm-not-wf-P88-ibm88n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P88-ibm88n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P88-ibm88n02'(suite) -> [];
+'ibm-not-wf-P88-ibm88n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P88-ibm88n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P88-ibm88n01'(suite) -> [];
+'ibm-not-wf-P88-ibm88n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P88-ibm88n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n85'(suite) -> [];
+'ibm-not-wf-P87-ibm87n85'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n85.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n84'(suite) -> [];
+'ibm-not-wf-P87-ibm87n84'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n84.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n83'(suite) -> [];
+'ibm-not-wf-P87-ibm87n83'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n83.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n82'(suite) -> [];
+'ibm-not-wf-P87-ibm87n82'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n82.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n81'(suite) -> [];
+'ibm-not-wf-P87-ibm87n81'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n81.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n80'(suite) -> [];
+'ibm-not-wf-P87-ibm87n80'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n80.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n79'(suite) -> [];
+'ibm-not-wf-P87-ibm87n79'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n79.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n78'(suite) -> [];
+'ibm-not-wf-P87-ibm87n78'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n78.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n77'(suite) -> [];
+'ibm-not-wf-P87-ibm87n77'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n77.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n76'(suite) -> [];
+'ibm-not-wf-P87-ibm87n76'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n76.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n75'(suite) -> [];
+'ibm-not-wf-P87-ibm87n75'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n75.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n74'(suite) -> [];
+'ibm-not-wf-P87-ibm87n74'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n74.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n73'(suite) -> [];
+'ibm-not-wf-P87-ibm87n73'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n73.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n72'(suite) -> [];
+'ibm-not-wf-P87-ibm87n72'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n72.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n71'(suite) -> [];
+'ibm-not-wf-P87-ibm87n71'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n71.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n70'(suite) -> [];
+'ibm-not-wf-P87-ibm87n70'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n70.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n69'(suite) -> [];
+'ibm-not-wf-P87-ibm87n69'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n69.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n68'(suite) -> [];
+'ibm-not-wf-P87-ibm87n68'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n68.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n67'(suite) -> [];
+'ibm-not-wf-P87-ibm87n67'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n67.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n66'(suite) -> [];
+'ibm-not-wf-P87-ibm87n66'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n66.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n64'(suite) -> [];
+'ibm-not-wf-P87-ibm87n64'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n64.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n63'(suite) -> [];
+'ibm-not-wf-P87-ibm87n63'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n63.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n62'(suite) -> [];
+'ibm-not-wf-P87-ibm87n62'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n62.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n61'(suite) -> [];
+'ibm-not-wf-P87-ibm87n61'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n61.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n60'(suite) -> [];
+'ibm-not-wf-P87-ibm87n60'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n60.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n59'(suite) -> [];
+'ibm-not-wf-P87-ibm87n59'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n59.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n58'(suite) -> [];
+'ibm-not-wf-P87-ibm87n58'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n58.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n57'(suite) -> [];
+'ibm-not-wf-P87-ibm87n57'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n57.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n56'(suite) -> [];
+'ibm-not-wf-P87-ibm87n56'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n56.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n55'(suite) -> [];
+'ibm-not-wf-P87-ibm87n55'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n55.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n54'(suite) -> [];
+'ibm-not-wf-P87-ibm87n54'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n54.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n53'(suite) -> [];
+'ibm-not-wf-P87-ibm87n53'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n53.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n52'(suite) -> [];
+'ibm-not-wf-P87-ibm87n52'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n52.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n51'(suite) -> [];
+'ibm-not-wf-P87-ibm87n51'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n51.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n50'(suite) -> [];
+'ibm-not-wf-P87-ibm87n50'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n50.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n49'(suite) -> [];
+'ibm-not-wf-P87-ibm87n49'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n49.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n48'(suite) -> [];
+'ibm-not-wf-P87-ibm87n48'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n48.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n47'(suite) -> [];
+'ibm-not-wf-P87-ibm87n47'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n47.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n46'(suite) -> [];
+'ibm-not-wf-P87-ibm87n46'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n46.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n45'(suite) -> [];
+'ibm-not-wf-P87-ibm87n45'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n45.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n44'(suite) -> [];
+'ibm-not-wf-P87-ibm87n44'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n44.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n43'(suite) -> [];
+'ibm-not-wf-P87-ibm87n43'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n43.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n42'(suite) -> [];
+'ibm-not-wf-P87-ibm87n42'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n42.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n41'(suite) -> [];
+'ibm-not-wf-P87-ibm87n41'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n41.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n40'(suite) -> [];
+'ibm-not-wf-P87-ibm87n40'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n40.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n39'(suite) -> [];
+'ibm-not-wf-P87-ibm87n39'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n39.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n38'(suite) -> [];
+'ibm-not-wf-P87-ibm87n38'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n38.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n37'(suite) -> [];
+'ibm-not-wf-P87-ibm87n37'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n37.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n36'(suite) -> [];
+'ibm-not-wf-P87-ibm87n36'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n36.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n35'(suite) -> [];
+'ibm-not-wf-P87-ibm87n35'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n35.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n34'(suite) -> [];
+'ibm-not-wf-P87-ibm87n34'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n34.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n33'(suite) -> [];
+'ibm-not-wf-P87-ibm87n33'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n33.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n32'(suite) -> [];
+'ibm-not-wf-P87-ibm87n32'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n32.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n31'(suite) -> [];
+'ibm-not-wf-P87-ibm87n31'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n31.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n30'(suite) -> [];
+'ibm-not-wf-P87-ibm87n30'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n30.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n29'(suite) -> [];
+'ibm-not-wf-P87-ibm87n29'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n29.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n28'(suite) -> [];
+'ibm-not-wf-P87-ibm87n28'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n28.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n27'(suite) -> [];
+'ibm-not-wf-P87-ibm87n27'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n27.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n26'(suite) -> [];
+'ibm-not-wf-P87-ibm87n26'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n26.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n25'(suite) -> [];
+'ibm-not-wf-P87-ibm87n25'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n25.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n24'(suite) -> [];
+'ibm-not-wf-P87-ibm87n24'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n24.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n23'(suite) -> [];
+'ibm-not-wf-P87-ibm87n23'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n23.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n22'(suite) -> [];
+'ibm-not-wf-P87-ibm87n22'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n22.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n21'(suite) -> [];
+'ibm-not-wf-P87-ibm87n21'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n21.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n20'(suite) -> [];
+'ibm-not-wf-P87-ibm87n20'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n20.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n19'(suite) -> [];
+'ibm-not-wf-P87-ibm87n19'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n19.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n18'(suite) -> [];
+'ibm-not-wf-P87-ibm87n18'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n18.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n17'(suite) -> [];
+'ibm-not-wf-P87-ibm87n17'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n17.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n16'(suite) -> [];
+'ibm-not-wf-P87-ibm87n16'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n16.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n15'(suite) -> [];
+'ibm-not-wf-P87-ibm87n15'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n15.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n14'(suite) -> [];
+'ibm-not-wf-P87-ibm87n14'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n14.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n13'(suite) -> [];
+'ibm-not-wf-P87-ibm87n13'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n13.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n12'(suite) -> [];
+'ibm-not-wf-P87-ibm87n12'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n12.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n11'(suite) -> [];
+'ibm-not-wf-P87-ibm87n11'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n11.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n10'(suite) -> [];
+'ibm-not-wf-P87-ibm87n10'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n10.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n09'(suite) -> [];
+'ibm-not-wf-P87-ibm87n09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n08'(suite) -> [];
+'ibm-not-wf-P87-ibm87n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n07'(suite) -> [];
+'ibm-not-wf-P87-ibm87n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n06'(suite) -> [];
+'ibm-not-wf-P87-ibm87n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n05'(suite) -> [];
+'ibm-not-wf-P87-ibm87n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n04'(suite) -> [];
+'ibm-not-wf-P87-ibm87n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n03'(suite) -> [];
+'ibm-not-wf-P87-ibm87n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n02'(suite) -> [];
+'ibm-not-wf-P87-ibm87n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P87-ibm87n01'(suite) -> [];
+'ibm-not-wf-P87-ibm87n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P87-ibm87n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P86-ibm86n04'(suite) -> [];
+'ibm-not-wf-P86-ibm86n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P86-ibm86n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P86-ibm86n03'(suite) -> [];
+'ibm-not-wf-P86-ibm86n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P86-ibm86n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P86-ibm86n02'(suite) -> [];
+'ibm-not-wf-P86-ibm86n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P86-ibm86n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P86-ibm86n01'(suite) -> [];
+'ibm-not-wf-P86-ibm86n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P86-ibm86n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n99'(suite) -> [];
+'ibm-not-wf-P85-ibm85n99'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n99.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n98'(suite) -> [];
+'ibm-not-wf-P85-ibm85n98'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n98.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n97'(suite) -> [];
+'ibm-not-wf-P85-ibm85n97'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n97.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n96'(suite) -> [];
+'ibm-not-wf-P85-ibm85n96'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n96.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n95'(suite) -> [];
+'ibm-not-wf-P85-ibm85n95'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n95.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n94'(suite) -> [];
+'ibm-not-wf-P85-ibm85n94'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n94.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n93'(suite) -> [];
+'ibm-not-wf-P85-ibm85n93'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n93.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n92'(suite) -> [];
+'ibm-not-wf-P85-ibm85n92'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n92.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n91'(suite) -> [];
+'ibm-not-wf-P85-ibm85n91'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n91.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n90'(suite) -> [];
+'ibm-not-wf-P85-ibm85n90'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n90.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n89'(suite) -> [];
+'ibm-not-wf-P85-ibm85n89'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n89.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n88'(suite) -> [];
+'ibm-not-wf-P85-ibm85n88'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n88.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n87'(suite) -> [];
+'ibm-not-wf-P85-ibm85n87'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n87.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n86'(suite) -> [];
+'ibm-not-wf-P85-ibm85n86'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n86.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n85'(suite) -> [];
+'ibm-not-wf-P85-ibm85n85'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n85.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n84'(suite) -> [];
+'ibm-not-wf-P85-ibm85n84'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n84.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n83'(suite) -> [];
+'ibm-not-wf-P85-ibm85n83'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n83.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n82'(suite) -> [];
+'ibm-not-wf-P85-ibm85n82'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n82.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n81'(suite) -> [];
+'ibm-not-wf-P85-ibm85n81'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n81.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n80'(suite) -> [];
+'ibm-not-wf-P85-ibm85n80'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n80.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n79'(suite) -> [];
+'ibm-not-wf-P85-ibm85n79'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n79.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n78'(suite) -> [];
+'ibm-not-wf-P85-ibm85n78'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n78.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n77'(suite) -> [];
+'ibm-not-wf-P85-ibm85n77'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n77.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n76'(suite) -> [];
+'ibm-not-wf-P85-ibm85n76'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n76.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n75'(suite) -> [];
+'ibm-not-wf-P85-ibm85n75'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n75.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n74'(suite) -> [];
+'ibm-not-wf-P85-ibm85n74'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n74.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n73'(suite) -> [];
+'ibm-not-wf-P85-ibm85n73'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n73.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n72'(suite) -> [];
+'ibm-not-wf-P85-ibm85n72'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n72.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n71'(suite) -> [];
+'ibm-not-wf-P85-ibm85n71'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n71.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n70'(suite) -> [];
+'ibm-not-wf-P85-ibm85n70'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n70.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n69'(suite) -> [];
+'ibm-not-wf-P85-ibm85n69'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n69.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n68'(suite) -> [];
+'ibm-not-wf-P85-ibm85n68'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n68.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n67'(suite) -> [];
+'ibm-not-wf-P85-ibm85n67'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n67.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n66'(suite) -> [];
+'ibm-not-wf-P85-ibm85n66'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n66.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n65'(suite) -> [];
+'ibm-not-wf-P85-ibm85n65'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n65.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n64'(suite) -> [];
+'ibm-not-wf-P85-ibm85n64'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n64.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n63'(suite) -> [];
+'ibm-not-wf-P85-ibm85n63'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n63.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n62'(suite) -> [];
+'ibm-not-wf-P85-ibm85n62'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n62.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n61'(suite) -> [];
+'ibm-not-wf-P85-ibm85n61'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n61.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n60'(suite) -> [];
+'ibm-not-wf-P85-ibm85n60'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n60.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n59'(suite) -> [];
+'ibm-not-wf-P85-ibm85n59'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n59.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n58'(suite) -> [];
+'ibm-not-wf-P85-ibm85n58'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n58.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n57'(suite) -> [];
+'ibm-not-wf-P85-ibm85n57'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n57.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n56'(suite) -> [];
+'ibm-not-wf-P85-ibm85n56'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n56.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n55'(suite) -> [];
+'ibm-not-wf-P85-ibm85n55'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n55.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n54'(suite) -> [];
+'ibm-not-wf-P85-ibm85n54'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n54.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n53'(suite) -> [];
+'ibm-not-wf-P85-ibm85n53'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n53.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n52'(suite) -> [];
+'ibm-not-wf-P85-ibm85n52'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n52.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n51'(suite) -> [];
+'ibm-not-wf-P85-ibm85n51'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n51.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n50'(suite) -> [];
+'ibm-not-wf-P85-ibm85n50'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n50.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n49'(suite) -> [];
+'ibm-not-wf-P85-ibm85n49'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n49.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n48'(suite) -> [];
+'ibm-not-wf-P85-ibm85n48'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n48.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n47'(suite) -> [];
+'ibm-not-wf-P85-ibm85n47'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n47.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n46'(suite) -> [];
+'ibm-not-wf-P85-ibm85n46'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n46.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n45'(suite) -> [];
+'ibm-not-wf-P85-ibm85n45'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n45.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n44'(suite) -> [];
+'ibm-not-wf-P85-ibm85n44'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n44.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n43'(suite) -> [];
+'ibm-not-wf-P85-ibm85n43'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n43.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n42'(suite) -> [];
+'ibm-not-wf-P85-ibm85n42'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n42.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n41'(suite) -> [];
+'ibm-not-wf-P85-ibm85n41'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n41.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n40'(suite) -> [];
+'ibm-not-wf-P85-ibm85n40'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n40.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n39'(suite) -> [];
+'ibm-not-wf-P85-ibm85n39'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n39.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n38'(suite) -> [];
+'ibm-not-wf-P85-ibm85n38'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n38.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n37'(suite) -> [];
+'ibm-not-wf-P85-ibm85n37'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n37.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n36'(suite) -> [];
+'ibm-not-wf-P85-ibm85n36'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n36.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n35'(suite) -> [];
+'ibm-not-wf-P85-ibm85n35'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n35.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n34'(suite) -> [];
+'ibm-not-wf-P85-ibm85n34'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n34.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n33'(suite) -> [];
+'ibm-not-wf-P85-ibm85n33'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n33.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n32'(suite) -> [];
+'ibm-not-wf-P85-ibm85n32'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n32.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n31'(suite) -> [];
+'ibm-not-wf-P85-ibm85n31'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n31.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n30'(suite) -> [];
+'ibm-not-wf-P85-ibm85n30'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n30.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n29'(suite) -> [];
+'ibm-not-wf-P85-ibm85n29'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n29.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n28'(suite) -> [];
+'ibm-not-wf-P85-ibm85n28'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n28.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n27'(suite) -> [];
+'ibm-not-wf-P85-ibm85n27'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n27.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n26'(suite) -> [];
+'ibm-not-wf-P85-ibm85n26'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n26.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n25'(suite) -> [];
+'ibm-not-wf-P85-ibm85n25'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n25.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n24'(suite) -> [];
+'ibm-not-wf-P85-ibm85n24'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n24.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n23'(suite) -> [];
+'ibm-not-wf-P85-ibm85n23'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n23.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n22'(suite) -> [];
+'ibm-not-wf-P85-ibm85n22'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n22.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n21'(suite) -> [];
+'ibm-not-wf-P85-ibm85n21'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n21.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n20'(suite) -> [];
+'ibm-not-wf-P85-ibm85n20'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n20.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n198'(suite) -> [];
+'ibm-not-wf-P85-ibm85n198'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n198.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n197'(suite) -> [];
+'ibm-not-wf-P85-ibm85n197'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n197.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n196'(suite) -> [];
+'ibm-not-wf-P85-ibm85n196'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n196.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n195'(suite) -> [];
+'ibm-not-wf-P85-ibm85n195'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n195.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n194'(suite) -> [];
+'ibm-not-wf-P85-ibm85n194'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n194.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n193'(suite) -> [];
+'ibm-not-wf-P85-ibm85n193'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n193.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n192'(suite) -> [];
+'ibm-not-wf-P85-ibm85n192'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n192.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n191'(suite) -> [];
+'ibm-not-wf-P85-ibm85n191'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n191.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n190'(suite) -> [];
+'ibm-not-wf-P85-ibm85n190'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n190.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n19'(suite) -> [];
+'ibm-not-wf-P85-ibm85n19'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n19.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n189'(suite) -> [];
+'ibm-not-wf-P85-ibm85n189'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n189.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n188'(suite) -> [];
+'ibm-not-wf-P85-ibm85n188'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n188.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n187'(suite) -> [];
+'ibm-not-wf-P85-ibm85n187'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n187.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n186'(suite) -> [];
+'ibm-not-wf-P85-ibm85n186'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n186.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n185'(suite) -> [];
+'ibm-not-wf-P85-ibm85n185'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n185.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n184'(suite) -> [];
+'ibm-not-wf-P85-ibm85n184'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n184.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n183'(suite) -> [];
+'ibm-not-wf-P85-ibm85n183'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n183.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n182'(suite) -> [];
+'ibm-not-wf-P85-ibm85n182'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n182.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n181'(suite) -> [];
+'ibm-not-wf-P85-ibm85n181'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n181.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n180'(suite) -> [];
+'ibm-not-wf-P85-ibm85n180'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n180.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n18'(suite) -> [];
+'ibm-not-wf-P85-ibm85n18'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n18.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n179'(suite) -> [];
+'ibm-not-wf-P85-ibm85n179'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n179.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n178'(suite) -> [];
+'ibm-not-wf-P85-ibm85n178'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n178.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n177'(suite) -> [];
+'ibm-not-wf-P85-ibm85n177'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n177.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n176'(suite) -> [];
+'ibm-not-wf-P85-ibm85n176'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n176.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n175'(suite) -> [];
+'ibm-not-wf-P85-ibm85n175'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n175.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n174'(suite) -> [];
+'ibm-not-wf-P85-ibm85n174'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n174.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n173'(suite) -> [];
+'ibm-not-wf-P85-ibm85n173'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n173.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n172'(suite) -> [];
+'ibm-not-wf-P85-ibm85n172'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n172.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n171'(suite) -> [];
+'ibm-not-wf-P85-ibm85n171'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n171.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n170'(suite) -> [];
+'ibm-not-wf-P85-ibm85n170'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n170.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n17'(suite) -> [];
+'ibm-not-wf-P85-ibm85n17'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n17.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n169'(suite) -> [];
+'ibm-not-wf-P85-ibm85n169'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n169.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n168'(suite) -> [];
+'ibm-not-wf-P85-ibm85n168'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n168.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n167'(suite) -> [];
+'ibm-not-wf-P85-ibm85n167'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n167.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n166'(suite) -> [];
+'ibm-not-wf-P85-ibm85n166'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n166.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n165'(suite) -> [];
+'ibm-not-wf-P85-ibm85n165'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n165.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n164'(suite) -> [];
+'ibm-not-wf-P85-ibm85n164'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n164.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n163'(suite) -> [];
+'ibm-not-wf-P85-ibm85n163'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n163.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n162'(suite) -> [];
+'ibm-not-wf-P85-ibm85n162'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n162.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n161'(suite) -> [];
+'ibm-not-wf-P85-ibm85n161'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n161.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n160'(suite) -> [];
+'ibm-not-wf-P85-ibm85n160'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n160.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n16'(suite) -> [];
+'ibm-not-wf-P85-ibm85n16'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n16.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n159'(suite) -> [];
+'ibm-not-wf-P85-ibm85n159'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n159.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n158'(suite) -> [];
+'ibm-not-wf-P85-ibm85n158'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n158.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n157'(suite) -> [];
+'ibm-not-wf-P85-ibm85n157'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n157.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n156'(suite) -> [];
+'ibm-not-wf-P85-ibm85n156'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n156.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n155'(suite) -> [];
+'ibm-not-wf-P85-ibm85n155'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n155.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n154'(suite) -> [];
+'ibm-not-wf-P85-ibm85n154'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n154.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n153'(suite) -> [];
+'ibm-not-wf-P85-ibm85n153'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n153.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n152'(suite) -> [];
+'ibm-not-wf-P85-ibm85n152'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n152.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n151'(suite) -> [];
+'ibm-not-wf-P85-ibm85n151'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n151.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n150'(suite) -> [];
+'ibm-not-wf-P85-ibm85n150'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n150.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n15'(suite) -> [];
+'ibm-not-wf-P85-ibm85n15'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n15.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n149'(suite) -> [];
+'ibm-not-wf-P85-ibm85n149'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n149.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n148'(suite) -> [];
+'ibm-not-wf-P85-ibm85n148'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n148.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n147'(suite) -> [];
+'ibm-not-wf-P85-ibm85n147'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n147.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n146'(suite) -> [];
+'ibm-not-wf-P85-ibm85n146'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n146.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n145'(suite) -> [];
+'ibm-not-wf-P85-ibm85n145'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n145.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n144'(suite) -> [];
+'ibm-not-wf-P85-ibm85n144'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n144.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n143'(suite) -> [];
+'ibm-not-wf-P85-ibm85n143'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n143.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n142'(suite) -> [];
+'ibm-not-wf-P85-ibm85n142'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n142.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n141'(suite) -> [];
+'ibm-not-wf-P85-ibm85n141'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n141.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n140'(suite) -> [];
+'ibm-not-wf-P85-ibm85n140'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n140.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n14'(suite) -> [];
+'ibm-not-wf-P85-ibm85n14'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n14.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n139'(suite) -> [];
+'ibm-not-wf-P85-ibm85n139'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n139.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n138'(suite) -> [];
+'ibm-not-wf-P85-ibm85n138'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n138.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n137'(suite) -> [];
+'ibm-not-wf-P85-ibm85n137'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n137.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n136'(suite) -> [];
+'ibm-not-wf-P85-ibm85n136'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n136.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n135'(suite) -> [];
+'ibm-not-wf-P85-ibm85n135'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n135.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n134'(suite) -> [];
+'ibm-not-wf-P85-ibm85n134'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n134.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n133'(suite) -> [];
+'ibm-not-wf-P85-ibm85n133'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n133.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n132'(suite) -> [];
+'ibm-not-wf-P85-ibm85n132'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n132.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n131'(suite) -> [];
+'ibm-not-wf-P85-ibm85n131'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n131.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n130'(suite) -> [];
+'ibm-not-wf-P85-ibm85n130'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n130.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n13'(suite) -> [];
+'ibm-not-wf-P85-ibm85n13'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n13.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n129'(suite) -> [];
+'ibm-not-wf-P85-ibm85n129'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n129.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n128'(suite) -> [];
+'ibm-not-wf-P85-ibm85n128'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n128.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n127'(suite) -> [];
+'ibm-not-wf-P85-ibm85n127'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n127.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n126'(suite) -> [];
+'ibm-not-wf-P85-ibm85n126'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n126.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n125'(suite) -> [];
+'ibm-not-wf-P85-ibm85n125'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n125.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n124'(suite) -> [];
+'ibm-not-wf-P85-ibm85n124'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n124.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n123'(suite) -> [];
+'ibm-not-wf-P85-ibm85n123'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n123.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n122'(suite) -> [];
+'ibm-not-wf-P85-ibm85n122'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n122.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n121'(suite) -> [];
+'ibm-not-wf-P85-ibm85n121'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n121.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n120'(suite) -> [];
+'ibm-not-wf-P85-ibm85n120'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n120.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n12'(suite) -> [];
+'ibm-not-wf-P85-ibm85n12'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n12.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n119'(suite) -> [];
+'ibm-not-wf-P85-ibm85n119'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n119.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n118'(suite) -> [];
+'ibm-not-wf-P85-ibm85n118'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n118.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n117'(suite) -> [];
+'ibm-not-wf-P85-ibm85n117'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n117.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n116'(suite) -> [];
+'ibm-not-wf-P85-ibm85n116'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n116.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n115'(suite) -> [];
+'ibm-not-wf-P85-ibm85n115'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n115.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n114'(suite) -> [];
+'ibm-not-wf-P85-ibm85n114'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n114.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n113'(suite) -> [];
+'ibm-not-wf-P85-ibm85n113'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n113.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n112'(suite) -> [];
+'ibm-not-wf-P85-ibm85n112'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n112.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n111'(suite) -> [];
+'ibm-not-wf-P85-ibm85n111'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n111.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n110'(suite) -> [];
+'ibm-not-wf-P85-ibm85n110'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n110.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n11'(suite) -> [];
+'ibm-not-wf-P85-ibm85n11'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n11.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n109'(suite) -> [];
+'ibm-not-wf-P85-ibm85n109'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n109.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n108'(suite) -> [];
+'ibm-not-wf-P85-ibm85n108'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n108.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n107'(suite) -> [];
+'ibm-not-wf-P85-ibm85n107'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n107.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n106'(suite) -> [];
+'ibm-not-wf-P85-ibm85n106'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n106.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n105'(suite) -> [];
+'ibm-not-wf-P85-ibm85n105'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n105.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n104'(suite) -> [];
+'ibm-not-wf-P85-ibm85n104'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n104.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n103'(suite) -> [];
+'ibm-not-wf-P85-ibm85n103'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n103.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n102'(suite) -> [];
+'ibm-not-wf-P85-ibm85n102'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n102.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n101'(suite) -> [];
+'ibm-not-wf-P85-ibm85n101'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n101.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n100'(suite) -> [];
+'ibm-not-wf-P85-ibm85n100'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n100.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n10'(suite) -> [];
+'ibm-not-wf-P85-ibm85n10'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n10.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n09'(suite) -> [];
+'ibm-not-wf-P85-ibm85n09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n08'(suite) -> [];
+'ibm-not-wf-P85-ibm85n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n07'(suite) -> [];
+'ibm-not-wf-P85-ibm85n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n06'(suite) -> [];
+'ibm-not-wf-P85-ibm85n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n05'(suite) -> [];
+'ibm-not-wf-P85-ibm85n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n04'(suite) -> [];
+'ibm-not-wf-P85-ibm85n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n03'(suite) -> [];
+'ibm-not-wf-P85-ibm85n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n02'(suite) -> [];
+'ibm-not-wf-P85-ibm85n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P85-ibm85n01'(suite) -> [];
+'ibm-not-wf-P85-ibm85n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P85-ibm85n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P83-ibm83n06'(suite) -> [];
+'ibm-not-wf-P83-ibm83n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P83-ibm83n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P83-ibm83n05'(suite) -> [];
+'ibm-not-wf-P83-ibm83n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P83-ibm83n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P83-ibm83n04'(suite) -> [];
+'ibm-not-wf-P83-ibm83n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P83-ibm83n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P83-ibm83n03'(suite) -> [];
+'ibm-not-wf-P83-ibm83n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P83-ibm83n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P83-ibm83n02'(suite) -> [];
+'ibm-not-wf-P83-ibm83n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P83-ibm83n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P83-ibm83n01'(suite) -> [];
+'ibm-not-wf-P83-ibm83n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P83-ibm83n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P82-ibm82n08'(suite) -> [];
+'ibm-not-wf-P82-ibm82n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P82-ibm82n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P82-ibm82n07'(suite) -> [];
+'ibm-not-wf-P82-ibm82n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P82-ibm82n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P82-ibm82n06'(suite) -> [];
+'ibm-not-wf-P82-ibm82n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P82-ibm82n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P82-ibm82n05'(suite) -> [];
+'ibm-not-wf-P82-ibm82n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P82-ibm82n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P82-ibm82n04'(suite) -> [];
+'ibm-not-wf-P82-ibm82n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P82-ibm82n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P82-ibm82n03'(suite) -> [];
+'ibm-not-wf-P82-ibm82n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P82-ibm82n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P82-ibm82n02'(suite) -> [];
+'ibm-not-wf-P82-ibm82n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P82-ibm82n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P82-ibm82n01'(suite) -> [];
+'ibm-not-wf-P82-ibm82n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P82-ibm82n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P81-ibm81n09'(suite) -> [];
+'ibm-not-wf-P81-ibm81n09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P81-ibm81n09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P81-ibm81n08'(suite) -> [];
+'ibm-not-wf-P81-ibm81n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P81-ibm81n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P81-ibm81n07'(suite) -> [];
+'ibm-not-wf-P81-ibm81n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P81-ibm81n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P81-ibm81n06'(suite) -> [];
+'ibm-not-wf-P81-ibm81n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P81-ibm81n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P81-ibm81n05'(suite) -> [];
+'ibm-not-wf-P81-ibm81n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P81-ibm81n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P81-ibm81n04'(suite) -> [];
+'ibm-not-wf-P81-ibm81n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P81-ibm81n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P81-ibm81n03'(suite) -> [];
+'ibm-not-wf-P81-ibm81n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P81-ibm81n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P81-ibm81n02'(suite) -> [];
+'ibm-not-wf-P81-ibm81n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P81-ibm81n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P81-ibm81n01'(suite) -> [];
+'ibm-not-wf-P81-ibm81n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P81-ibm81n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P80-ibm80n06'(suite) -> [];
+'ibm-not-wf-P80-ibm80n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P80-ibm80n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P80-ibm80n05'(suite) -> [];
+'ibm-not-wf-P80-ibm80n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P80-ibm80n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P80-ibm80n04'(suite) -> [];
+'ibm-not-wf-P80-ibm80n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P80-ibm80n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P80-ibm80n03'(suite) -> [];
+'ibm-not-wf-P80-ibm80n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P80-ibm80n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P80-ibm80n02'(suite) -> [];
+'ibm-not-wf-P80-ibm80n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P80-ibm80n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P80-ibm80n01'(suite) -> [];
+'ibm-not-wf-P80-ibm80n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P80-ibm80n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P79-ibm79n02'(suite) -> [];
+'ibm-not-wf-P79-ibm79n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P79-ibm79n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P79-ibm79n01'(suite) -> [];
+'ibm-not-wf-P79-ibm79n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P79-ibm79n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P78-ibm78n02'(suite) -> [];
+'ibm-not-wf-P78-ibm78n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P78-ibm78n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P78-ibm78n01'(suite) -> [];
+'ibm-not-wf-P78-ibm78n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P78-ibm78n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P77-ibm77n04'(suite) -> [];
+'ibm-not-wf-P77-ibm77n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P77-ibm77n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P77-ibm77n03'(suite) -> [];
+'ibm-not-wf-P77-ibm77n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P77-ibm77n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P77-ibm77n02'(suite) -> [];
+'ibm-not-wf-P77-ibm77n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P77-ibm77n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P77-ibm77n01'(suite) -> [];
+'ibm-not-wf-P77-ibm77n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P77-ibm77n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P76-ibm76n07'(suite) -> [];
+'ibm-not-wf-P76-ibm76n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P76-ibm76n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P76-ibm76n06'(suite) -> [];
+'ibm-not-wf-P76-ibm76n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P76-ibm76n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P76-ibm76n05'(suite) -> [];
+'ibm-not-wf-P76-ibm76n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P76-ibm76n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P76-ibm76n04'(suite) -> [];
+'ibm-not-wf-P76-ibm76n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P76-ibm76n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P76-ibm76n03'(suite) -> [];
+'ibm-not-wf-P76-ibm76n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P76-ibm76n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P76-ibm76n02'(suite) -> [];
+'ibm-not-wf-P76-ibm76n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P76-ibm76n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P76-ibm76n01'(suite) -> [];
+'ibm-not-wf-P76-ibm76n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P76-ibm76n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P75-ibm75n13'(suite) -> [];
+'ibm-not-wf-P75-ibm75n13'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P75-ibm75n13.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P75-ibm75n12'(suite) -> [];
+'ibm-not-wf-P75-ibm75n12'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P75-ibm75n12.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P75-ibm75n11'(suite) -> [];
+'ibm-not-wf-P75-ibm75n11'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P75-ibm75n11.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P75-ibm75n10'(suite) -> [];
+'ibm-not-wf-P75-ibm75n10'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P75-ibm75n10.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P75-ibm75n09'(suite) -> [];
+'ibm-not-wf-P75-ibm75n09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P75-ibm75n09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P75-ibm75n08'(suite) -> [];
+'ibm-not-wf-P75-ibm75n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P75-ibm75n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P75-ibm75n07'(suite) -> [];
+'ibm-not-wf-P75-ibm75n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P75-ibm75n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P75-ibm75n06'(suite) -> [];
+'ibm-not-wf-P75-ibm75n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P75-ibm75n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P75-ibm75n05'(suite) -> [];
+'ibm-not-wf-P75-ibm75n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P75-ibm75n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P75-ibm75n04'(suite) -> [];
+'ibm-not-wf-P75-ibm75n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P75-ibm75n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P75-ibm75n03'(suite) -> [];
+'ibm-not-wf-P75-ibm75n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P75-ibm75n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P75-ibm75n02'(suite) -> [];
+'ibm-not-wf-P75-ibm75n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P75-ibm75n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P75-ibm75n01'(suite) -> [];
+'ibm-not-wf-P75-ibm75n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P75-ibm75n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P74-ibm74n01'(suite) -> [];
+'ibm-not-wf-P74-ibm74n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P74-ibm74n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P73-ibm73n03'(suite) -> [];
+'ibm-not-wf-P73-ibm73n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P73-ibm73n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P73-ibm73n01'(suite) -> [];
+'ibm-not-wf-P73-ibm73n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P73-ibm73n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P72-ibm72n09'(suite) -> [];
+'ibm-not-wf-P72-ibm72n09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P72-ibm72n09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P72-ibm72n08'(suite) -> [];
+'ibm-not-wf-P72-ibm72n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P72-ibm72n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P72-ibm72n07'(suite) -> [];
+'ibm-not-wf-P72-ibm72n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P72-ibm72n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P72-ibm72n06'(suite) -> [];
+'ibm-not-wf-P72-ibm72n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P72-ibm72n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P72-ibm72n05'(suite) -> [];
+'ibm-not-wf-P72-ibm72n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P72-ibm72n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P72-ibm72n04'(suite) -> [];
+'ibm-not-wf-P72-ibm72n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P72-ibm72n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P72-ibm72n03'(suite) -> [];
+'ibm-not-wf-P72-ibm72n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P72-ibm72n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P72-ibm72n02'(suite) -> [];
+'ibm-not-wf-P72-ibm72n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P72-ibm72n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P72-ibm72n01'(suite) -> [];
+'ibm-not-wf-P72-ibm72n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P72-ibm72n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P71-ibm71n08'(suite) -> [];
+'ibm-not-wf-P71-ibm71n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P71-ibm71n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P71-ibm71n07'(suite) -> [];
+'ibm-not-wf-P71-ibm71n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P71-ibm71n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P71-ibm71n06'(suite) -> [];
+'ibm-not-wf-P71-ibm71n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P71-ibm71n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P71-ibm71n05'(suite) -> [];
+'ibm-not-wf-P71-ibm71n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P71-ibm71n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P71-ibm71n04'(suite) -> [];
+'ibm-not-wf-P71-ibm71n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P71-ibm71n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P71-ibm71n03'(suite) -> [];
+'ibm-not-wf-P71-ibm71n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P71-ibm71n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P71-ibm71n02'(suite) -> [];
+'ibm-not-wf-P71-ibm71n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P71-ibm71n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P71-ibm71n01'(suite) -> [];
+'ibm-not-wf-P71-ibm71n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P71-ibm71n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P71-ibm70n01'(suite) -> [];
+'ibm-not-wf-P71-ibm70n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P71-ibm70n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P69-ibm69n07'(suite) -> [];
+'ibm-not-wf-P69-ibm69n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P69-ibm69n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P69-ibm69n06'(suite) -> [];
+'ibm-not-wf-P69-ibm69n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P69-ibm69n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P69-ibm69n05'(suite) -> [];
+'ibm-not-wf-P69-ibm69n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P69-ibm69n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P69-ibm69n04'(suite) -> [];
+'ibm-not-wf-P69-ibm69n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P69-ibm69n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P69-ibm69n03'(suite) -> [];
+'ibm-not-wf-P69-ibm69n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P69-ibm69n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P69-ibm69n02'(suite) -> [];
+'ibm-not-wf-P69-ibm69n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P69-ibm69n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P69-ibm69n01'(suite) -> [];
+'ibm-not-wf-P69-ibm69n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P69-ibm69n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P68-ibm68n10'(suite) -> [];
+'ibm-not-wf-P68-ibm68n10'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P68-ibm68n10.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P68-ibm68n09'(suite) -> [];
+'ibm-not-wf-P68-ibm68n09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P68-ibm68n09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P68-ibm68n08'(suite) -> [];
+'ibm-not-wf-P68-ibm68n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P68-ibm68n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P68-ibm68n07'(suite) -> [];
+'ibm-not-wf-P68-ibm68n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P68-ibm68n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P68-ibm68n06'(suite) -> [];
+'ibm-not-wf-P68-ibm68n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P68-ibm68n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P68-ibm68n05'(suite) -> [];
+'ibm-not-wf-P68-ibm68n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P68-ibm68n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P68-ibm68n04'(suite) -> [];
+'ibm-not-wf-P68-ibm68n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P68-ibm68n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P68-ibm68n03'(suite) -> [];
+'ibm-not-wf-P68-ibm68n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P68-ibm68n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P68-ibm68n02'(suite) -> [];
+'ibm-not-wf-P68-ibm68n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P68-ibm68n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P68-ibm68n01'(suite) -> [];
+'ibm-not-wf-P68-ibm68n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P68-ibm68n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P66-ibm66n15'(suite) -> [];
+'ibm-not-wf-P66-ibm66n15'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P66-ibm66n15.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P66-ibm66n14'(suite) -> [];
+'ibm-not-wf-P66-ibm66n14'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P66-ibm66n14.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P66-ibm66n13'(suite) -> [];
+'ibm-not-wf-P66-ibm66n13'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P66-ibm66n13.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P66-ibm66n12'(suite) -> [];
+'ibm-not-wf-P66-ibm66n12'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P66-ibm66n12.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P66-ibm66n11'(suite) -> [];
+'ibm-not-wf-P66-ibm66n11'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P66-ibm66n11.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P66-ibm66n10'(suite) -> [];
+'ibm-not-wf-P66-ibm66n10'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P66-ibm66n10.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P66-ibm66n09'(suite) -> [];
+'ibm-not-wf-P66-ibm66n09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P66-ibm66n09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P66-ibm66n08'(suite) -> [];
+'ibm-not-wf-P66-ibm66n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P66-ibm66n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P66-ibm66n07'(suite) -> [];
+'ibm-not-wf-P66-ibm66n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P66-ibm66n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P66-ibm66n06'(suite) -> [];
+'ibm-not-wf-P66-ibm66n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P66-ibm66n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P66-ibm66n05'(suite) -> [];
+'ibm-not-wf-P66-ibm66n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P66-ibm66n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P66-ibm66n04'(suite) -> [];
+'ibm-not-wf-P66-ibm66n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P66-ibm66n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P66-ibm66n03'(suite) -> [];
+'ibm-not-wf-P66-ibm66n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P66-ibm66n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P66-ibm66n02'(suite) -> [];
+'ibm-not-wf-P66-ibm66n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P66-ibm66n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P66-ibm66n01'(suite) -> [];
+'ibm-not-wf-P66-ibm66n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P66-ibm66n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P65-ibm65n02'(suite) -> [];
+'ibm-not-wf-P65-ibm65n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P65-ibm65n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P65-ibm65n01'(suite) -> [];
+'ibm-not-wf-P65-ibm65n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P65-ibm65n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P64-ibm64n03'(suite) -> [];
+'ibm-not-wf-P64-ibm64n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P64-ibm64n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P64-ibm64n02'(suite) -> [];
+'ibm-not-wf-P64-ibm64n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P64-ibm64n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P64-ibm64n01'(suite) -> [];
+'ibm-not-wf-P64-ibm64n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P64-ibm64n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P63-ibm63n07'(suite) -> [];
+'ibm-not-wf-P63-ibm63n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P63-ibm63n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P63-ibm63n06'(suite) -> [];
+'ibm-not-wf-P63-ibm63n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P63-ibm63n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P63-ibm63n05'(suite) -> [];
+'ibm-not-wf-P63-ibm63n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P63-ibm63n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P63-ibm63n04'(suite) -> [];
+'ibm-not-wf-P63-ibm63n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P63-ibm63n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P63-ibm63n03'(suite) -> [];
+'ibm-not-wf-P63-ibm63n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P63-ibm63n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P63-ibm63n02'(suite) -> [];
+'ibm-not-wf-P63-ibm63n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P63-ibm63n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P63-ibm63n01'(suite) -> [];
+'ibm-not-wf-P63-ibm63n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P63-ibm63n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P62-ibm62n08'(suite) -> [];
+'ibm-not-wf-P62-ibm62n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P62-ibm62n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P62-ibm62n07'(suite) -> [];
+'ibm-not-wf-P62-ibm62n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P62-ibm62n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P62-ibm62n06'(suite) -> [];
+'ibm-not-wf-P62-ibm62n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P62-ibm62n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P62-ibm62n05'(suite) -> [];
+'ibm-not-wf-P62-ibm62n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P62-ibm62n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P62-ibm62n04'(suite) -> [];
+'ibm-not-wf-P62-ibm62n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P62-ibm62n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P62-ibm62n03'(suite) -> [];
+'ibm-not-wf-P62-ibm62n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P62-ibm62n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P62-ibm62n02'(suite) -> [];
+'ibm-not-wf-P62-ibm62n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P62-ibm62n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P62-ibm62n01'(suite) -> [];
+'ibm-not-wf-P62-ibm62n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P62-ibm62n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P61-ibm61n01'(suite) -> [];
+'ibm-not-wf-P61-ibm61n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P61-ibm61n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P60-ibm60n08'(suite) -> [];
+'ibm-not-wf-P60-ibm60n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P60-ibm60n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P60-ibm60n07'(suite) -> [];
+'ibm-not-wf-P60-ibm60n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P60-ibm60n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P60-ibm60n06'(suite) -> [];
+'ibm-not-wf-P60-ibm60n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P60-ibm60n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P60-ibm60n05'(suite) -> [];
+'ibm-not-wf-P60-ibm60n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P60-ibm60n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P60-ibm60n04'(suite) -> [];
+'ibm-not-wf-P60-ibm60n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P60-ibm60n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P60-ibm60n03'(suite) -> [];
+'ibm-not-wf-P60-ibm60n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P60-ibm60n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P60-ibm60n02'(suite) -> [];
+'ibm-not-wf-P60-ibm60n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P60-ibm60n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P60-ibm60n01'(suite) -> [];
+'ibm-not-wf-P60-ibm60n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P60-ibm60n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P59-ibm59n06'(suite) -> [];
+'ibm-not-wf-P59-ibm59n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P59-ibm59n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P59-ibm59n05'(suite) -> [];
+'ibm-not-wf-P59-ibm59n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P59-ibm59n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P59-ibm59n04'(suite) -> [];
+'ibm-not-wf-P59-ibm59n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P59-ibm59n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P59-ibm59n03'(suite) -> [];
+'ibm-not-wf-P59-ibm59n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P59-ibm59n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P59-ibm59n02'(suite) -> [];
+'ibm-not-wf-P59-ibm59n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P59-ibm59n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P59-ibm59n01'(suite) -> [];
+'ibm-not-wf-P59-ibm59n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P59-ibm59n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P58-ibm58n08'(suite) -> [];
+'ibm-not-wf-P58-ibm58n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P58-ibm58n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P58-ibm58n07'(suite) -> [];
+'ibm-not-wf-P58-ibm58n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P58-ibm58n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P58-ibm58n06'(suite) -> [];
+'ibm-not-wf-P58-ibm58n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P58-ibm58n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P58-ibm58n05'(suite) -> [];
+'ibm-not-wf-P58-ibm58n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P58-ibm58n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P58-ibm58n04'(suite) -> [];
+'ibm-not-wf-P58-ibm58n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P58-ibm58n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P58-ibm58n03'(suite) -> [];
+'ibm-not-wf-P58-ibm58n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P58-ibm58n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P58-ibm58n02'(suite) -> [];
+'ibm-not-wf-P58-ibm58n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P58-ibm58n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P58-ibm58n01'(suite) -> [];
+'ibm-not-wf-P58-ibm58n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P58-ibm58n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P57-ibm57n01'(suite) -> [];
+'ibm-not-wf-P57-ibm57n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P57-ibm57n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P56-ibm56n07'(suite) -> [];
+'ibm-not-wf-P56-ibm56n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P56-ibm56n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P56-ibm56n06'(suite) -> [];
+'ibm-not-wf-P56-ibm56n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P56-ibm56n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P56-ibm56n05'(suite) -> [];
+'ibm-not-wf-P56-ibm56n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P56-ibm56n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P56-ibm56n04'(suite) -> [];
+'ibm-not-wf-P56-ibm56n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P56-ibm56n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P56-ibm56n03'(suite) -> [];
+'ibm-not-wf-P56-ibm56n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P56-ibm56n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P56-ibm56n02'(suite) -> [];
+'ibm-not-wf-P56-ibm56n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P56-ibm56n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P56-ibm56n01'(suite) -> [];
+'ibm-not-wf-P56-ibm56n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P56-ibm56n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P55-ibm55n03'(suite) -> [];
+'ibm-not-wf-P55-ibm55n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P55-ibm55n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P55-ibm55n02'(suite) -> [];
+'ibm-not-wf-P55-ibm55n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P55-ibm55n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P55-ibm55n01'(suite) -> [];
+'ibm-not-wf-P55-ibm55n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P55-ibm55n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P54-ibm54n02'(suite) -> [];
+'ibm-not-wf-P54-ibm54n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P54-ibm54n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P54-ibm54n01'(suite) -> [];
+'ibm-not-wf-P54-ibm54n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P54-ibm54n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P53-ibm53n08'(suite) -> [];
+'ibm-not-wf-P53-ibm53n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P53-ibm53n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P53-ibm53n07'(suite) -> [];
+'ibm-not-wf-P53-ibm53n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P53-ibm53n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P53-ibm53n06'(suite) -> [];
+'ibm-not-wf-P53-ibm53n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P53-ibm53n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P53-ibm53n05'(suite) -> [];
+'ibm-not-wf-P53-ibm53n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P53-ibm53n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P53-ibm53n04'(suite) -> [];
+'ibm-not-wf-P53-ibm53n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P53-ibm53n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P53-ibm53n03'(suite) -> [];
+'ibm-not-wf-P53-ibm53n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P53-ibm53n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P53-ibm53n02'(suite) -> [];
+'ibm-not-wf-P53-ibm53n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P53-ibm53n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P53-ibm53n01'(suite) -> [];
+'ibm-not-wf-P53-ibm53n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P53-ibm53n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P52-ibm52n06'(suite) -> [];
+'ibm-not-wf-P52-ibm52n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P52-ibm52n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P52-ibm52n05'(suite) -> [];
+'ibm-not-wf-P52-ibm52n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P52-ibm52n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P52-ibm52n04'(suite) -> [];
+'ibm-not-wf-P52-ibm52n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P52-ibm52n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P52-ibm52n03'(suite) -> [];
+'ibm-not-wf-P52-ibm52n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P52-ibm52n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P52-ibm52n02'(suite) -> [];
+'ibm-not-wf-P52-ibm52n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P52-ibm52n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P52-ibm52n01'(suite) -> [];
+'ibm-not-wf-P52-ibm52n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P52-ibm52n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P51-ibm51n07'(suite) -> [];
+'ibm-not-wf-P51-ibm51n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P51-ibm51n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P51-ibm51n06'(suite) -> [];
+'ibm-not-wf-P51-ibm51n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P51-ibm51n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P51-ibm51n05'(suite) -> [];
+'ibm-not-wf-P51-ibm51n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P51-ibm51n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P51-ibm51n04'(suite) -> [];
+'ibm-not-wf-P51-ibm51n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P51-ibm51n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P51-ibm51n03'(suite) -> [];
+'ibm-not-wf-P51-ibm51n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P51-ibm51n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P51-ibm51n02'(suite) -> [];
+'ibm-not-wf-P51-ibm51n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P51-ibm51n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P51-ibm51n01'(suite) -> [];
+'ibm-not-wf-P51-ibm51n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P51-ibm51n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P50-ibm50n07'(suite) -> [];
+'ibm-not-wf-P50-ibm50n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P50-ibm50n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P50-ibm50n06'(suite) -> [];
+'ibm-not-wf-P50-ibm50n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P50-ibm50n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P50-ibm50n05'(suite) -> [];
+'ibm-not-wf-P50-ibm50n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P50-ibm50n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P50-ibm50n04'(suite) -> [];
+'ibm-not-wf-P50-ibm50n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P50-ibm50n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P50-ibm50n03'(suite) -> [];
+'ibm-not-wf-P50-ibm50n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P50-ibm50n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P50-ibm50n02'(suite) -> [];
+'ibm-not-wf-P50-ibm50n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P50-ibm50n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P50-ibm50n01'(suite) -> [];
+'ibm-not-wf-P50-ibm50n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P50-ibm50n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P49-ibm49n06'(suite) -> [];
+'ibm-not-wf-P49-ibm49n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P49-ibm49n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P49-ibm49n05'(suite) -> [];
+'ibm-not-wf-P49-ibm49n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P49-ibm49n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P49-ibm49n04'(suite) -> [];
+'ibm-not-wf-P49-ibm49n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P49-ibm49n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P49-ibm49n03'(suite) -> [];
+'ibm-not-wf-P49-ibm49n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P49-ibm49n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P49-ibm49n02'(suite) -> [];
+'ibm-not-wf-P49-ibm49n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P49-ibm49n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P49-ibm49n01'(suite) -> [];
+'ibm-not-wf-P49-ibm49n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P49-ibm49n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P48-ibm48n07'(suite) -> [];
+'ibm-not-wf-P48-ibm48n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P48-ibm48n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P48-ibm48n06'(suite) -> [];
+'ibm-not-wf-P48-ibm48n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P48-ibm48n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P48-ibm48n05'(suite) -> [];
+'ibm-not-wf-P48-ibm48n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P48-ibm48n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P48-ibm48n04'(suite) -> [];
+'ibm-not-wf-P48-ibm48n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P48-ibm48n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P48-ibm48n03'(suite) -> [];
+'ibm-not-wf-P48-ibm48n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P48-ibm48n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P48-ibm48n02'(suite) -> [];
+'ibm-not-wf-P48-ibm48n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P48-ibm48n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P48-ibm48n01'(suite) -> [];
+'ibm-not-wf-P48-ibm48n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P48-ibm48n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P47-ibm47n06'(suite) -> [];
+'ibm-not-wf-P47-ibm47n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P47-ibm47n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P47-ibm47n05'(suite) -> [];
+'ibm-not-wf-P47-ibm47n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P47-ibm47n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P47-ibm47n04'(suite) -> [];
+'ibm-not-wf-P47-ibm47n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P47-ibm47n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P47-ibm47n03'(suite) -> [];
+'ibm-not-wf-P47-ibm47n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P47-ibm47n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P47-ibm47n02'(suite) -> [];
+'ibm-not-wf-P47-ibm47n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P47-ibm47n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P47-ibm47n01'(suite) -> [];
+'ibm-not-wf-P47-ibm47n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P47-ibm47n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P46-ibm46n05'(suite) -> [];
+'ibm-not-wf-P46-ibm46n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P46-ibm46n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P46-ibm46n04'(suite) -> [];
+'ibm-not-wf-P46-ibm46n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P46-ibm46n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P46-ibm46n03'(suite) -> [];
+'ibm-not-wf-P46-ibm46n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P46-ibm46n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P46-ibm46n02'(suite) -> [];
+'ibm-not-wf-P46-ibm46n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P46-ibm46n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P46-ibm46n01'(suite) -> [];
+'ibm-not-wf-P46-ibm46n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P46-ibm46n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P45-ibm45n09'(suite) -> [];
+'ibm-not-wf-P45-ibm45n09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P45-ibm45n09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P45-ibm45n08'(suite) -> [];
+'ibm-not-wf-P45-ibm45n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P45-ibm45n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P45-ibm45n07'(suite) -> [];
+'ibm-not-wf-P45-ibm45n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P45-ibm45n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P45-ibm45n06'(suite) -> [];
+'ibm-not-wf-P45-ibm45n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P45-ibm45n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P45-ibm45n05'(suite) -> [];
+'ibm-not-wf-P45-ibm45n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P45-ibm45n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P45-ibm45n04'(suite) -> [];
+'ibm-not-wf-P45-ibm45n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P45-ibm45n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P45-ibm45n03'(suite) -> [];
+'ibm-not-wf-P45-ibm45n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P45-ibm45n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P45-ibm45n02'(suite) -> [];
+'ibm-not-wf-P45-ibm45n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P45-ibm45n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P45-ibm45n01'(suite) -> [];
+'ibm-not-wf-P45-ibm45n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P45-ibm45n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P44-ibm44n04'(suite) -> [];
+'ibm-not-wf-P44-ibm44n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P44-ibm44n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P44-ibm44n03'(suite) -> [];
+'ibm-not-wf-P44-ibm44n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P44-ibm44n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P44-ibm44n02'(suite) -> [];
+'ibm-not-wf-P44-ibm44n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P44-ibm44n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P44-ibm44n01'(suite) -> [];
+'ibm-not-wf-P44-ibm44n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P44-ibm44n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P43-ibm43n05'(suite) -> [];
+'ibm-not-wf-P43-ibm43n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P43-ibm43n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P43-ibm43n04'(suite) -> [];
+'ibm-not-wf-P43-ibm43n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P43-ibm43n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P43-ibm43n02'(suite) -> [];
+'ibm-not-wf-P43-ibm43n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P43-ibm43n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P43-ibm43n01'(suite) -> [];
+'ibm-not-wf-P43-ibm43n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P43-ibm43n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P42-ibm42n05'(suite) -> [];
+'ibm-not-wf-P42-ibm42n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P42-ibm42n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P42-ibm42n04'(suite) -> [];
+'ibm-not-wf-P42-ibm42n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P42-ibm42n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P42-ibm42n03'(suite) -> [];
+'ibm-not-wf-P42-ibm42n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P42-ibm42n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P42-ibm42n02'(suite) -> [];
+'ibm-not-wf-P42-ibm42n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P42-ibm42n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P42-ibm42n01'(suite) -> [];
+'ibm-not-wf-P42-ibm42n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P42-ibm42n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P41-ibm41n14'(suite) -> [];
+'ibm-not-wf-P41-ibm41n14'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P41-ibm41n14.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P41-ibm41n13'(suite) -> [];
+'ibm-not-wf-P41-ibm41n13'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P41-ibm41n13.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P41-ibm41n12'(suite) -> [];
+'ibm-not-wf-P41-ibm41n12'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P41-ibm41n12.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P41-ibm41n11'(suite) -> [];
+'ibm-not-wf-P41-ibm41n11'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P41-ibm41n11.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P41-ibm41n10'(suite) -> [];
+'ibm-not-wf-P41-ibm41n10'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P41-ibm41n10.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P41-ibm41n09'(suite) -> [];
+'ibm-not-wf-P41-ibm41n09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P41-ibm41n09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P41-ibm41n08'(suite) -> [];
+'ibm-not-wf-P41-ibm41n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P41-ibm41n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P41-ibm41n07'(suite) -> [];
+'ibm-not-wf-P41-ibm41n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P41-ibm41n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P41-ibm41n06'(suite) -> [];
+'ibm-not-wf-P41-ibm41n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P41-ibm41n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P41-ibm41n05'(suite) -> [];
+'ibm-not-wf-P41-ibm41n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P41-ibm41n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P41-ibm41n04'(suite) -> [];
+'ibm-not-wf-P41-ibm41n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P41-ibm41n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P41-ibm41n03'(suite) -> [];
+'ibm-not-wf-P41-ibm41n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P41-ibm41n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P41-ibm41n02'(suite) -> [];
+'ibm-not-wf-P41-ibm41n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P41-ibm41n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P41-ibm41n01'(suite) -> [];
+'ibm-not-wf-P41-ibm41n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P41-ibm41n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P40-ibm40n05'(suite) -> [];
+'ibm-not-wf-P40-ibm40n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P40-ibm40n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P40-ibm40n04'(suite) -> [];
+'ibm-not-wf-P40-ibm40n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P40-ibm40n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P40-ibm40n03'(suite) -> [];
+'ibm-not-wf-P40-ibm40n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P40-ibm40n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P40-ibm40n02'(suite) -> [];
+'ibm-not-wf-P40-ibm40n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P40-ibm40n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P40-ibm40n01'(suite) -> [];
+'ibm-not-wf-P40-ibm40n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P40-ibm40n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P39-ibm39n06'(suite) -> [];
+'ibm-not-wf-P39-ibm39n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P39-ibm39n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P39-ibm39n05'(suite) -> [];
+'ibm-not-wf-P39-ibm39n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P39-ibm39n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P39-ibm39n04'(suite) -> [];
+'ibm-not-wf-P39-ibm39n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P39-ibm39n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P39-ibm39n03'(suite) -> [];
+'ibm-not-wf-P39-ibm39n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P39-ibm39n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P39-ibm39n02'(suite) -> [];
+'ibm-not-wf-P39-ibm39n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P39-ibm39n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P39-ibm39n01'(suite) -> [];
+'ibm-not-wf-P39-ibm39n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P39-ibm39n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P32-ibm32n09'(suite) -> [];
+'ibm-not-wf-P32-ibm32n09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P32-ibm32n09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P32-ibm32n08'(suite) -> [];
+'ibm-not-wf-P32-ibm32n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P32-ibm32n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P32-ibm32n07'(suite) -> [];
+'ibm-not-wf-P32-ibm32n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P32-ibm32n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P32-ibm32n06'(suite) -> [];
+'ibm-not-wf-P32-ibm32n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P32-ibm32n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P32-ibm32n05'(suite) -> [];
+'ibm-not-wf-P32-ibm32n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P32-ibm32n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P32-ibm32n04'(suite) -> [];
+'ibm-not-wf-P32-ibm32n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P32-ibm32n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P32-ibm32n03'(suite) -> [];
+'ibm-not-wf-P32-ibm32n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P32-ibm32n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P32-ibm32n02'(suite) -> [];
+'ibm-not-wf-P32-ibm32n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P32-ibm32n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P32-ibm32n01'(suite) -> [];
+'ibm-not-wf-P32-ibm32n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P32-ibm32n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P31-ibm31n01'(suite) -> [];
+'ibm-not-wf-P31-ibm31n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P31-ibm31n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P30-ibm30n01'(suite) -> [];
+'ibm-not-wf-P30-ibm30n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P30-ibm30n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P29-ibm29n07'(suite) -> [];
+'ibm-not-wf-P29-ibm29n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P29-ibm29n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P29-ibm29n06'(suite) -> [];
+'ibm-not-wf-P29-ibm29n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P29-ibm29n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P29-ibm29n05'(suite) -> [];
+'ibm-not-wf-P29-ibm29n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P29-ibm29n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P29-ibm29n04'(suite) -> [];
+'ibm-not-wf-P29-ibm29n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P29-ibm29n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P29-ibm29n03'(suite) -> [];
+'ibm-not-wf-P29-ibm29n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P29-ibm29n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P29-ibm29n02'(suite) -> [];
+'ibm-not-wf-P29-ibm29n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P29-ibm29n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P29-ibm29n01'(suite) -> [];
+'ibm-not-wf-P29-ibm29n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P29-ibm29n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P28a-ibm28an01'(suite) -> [];
+'ibm-not-wf-P28a-ibm28an01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P28a-ibm28an01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P28-ibm28n08'(suite) -> [];
+'ibm-not-wf-P28-ibm28n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P28-ibm28n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P28-ibm28n07'(suite) -> [];
+'ibm-not-wf-P28-ibm28n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P28-ibm28n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P28-ibm28n06'(suite) -> [];
+'ibm-not-wf-P28-ibm28n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P28-ibm28n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P28-ibm28n05'(suite) -> [];
+'ibm-not-wf-P28-ibm28n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P28-ibm28n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P28-ibm28n04'(suite) -> [];
+'ibm-not-wf-P28-ibm28n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P28-ibm28n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P28-ibm28n03'(suite) -> [];
+'ibm-not-wf-P28-ibm28n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P28-ibm28n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P28-ibm28n02'(suite) -> [];
+'ibm-not-wf-P28-ibm28n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P28-ibm28n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P28-ibm28n01'(suite) -> [];
+'ibm-not-wf-P28-ibm28n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P28-ibm28n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P27-ibm27n01'(suite) -> [];
+'ibm-not-wf-P27-ibm27n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P27-ibm27n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P26-ibm26n01'(suite) -> [];
+'ibm-not-wf-P26-ibm26n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P26-ibm26n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P25-ibm25n02'(suite) -> [];
+'ibm-not-wf-P25-ibm25n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P25-ibm25n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P25-ibm25n01'(suite) -> [];
+'ibm-not-wf-P25-ibm25n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P25-ibm25n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P24-ibm24n09'(suite) -> [];
+'ibm-not-wf-P24-ibm24n09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P24-ibm24n09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P24-ibm24n08'(suite) -> [];
+'ibm-not-wf-P24-ibm24n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P24-ibm24n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P24-ibm24n07'(suite) -> [];
+'ibm-not-wf-P24-ibm24n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P24-ibm24n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P24-ibm24n06'(suite) -> [];
+'ibm-not-wf-P24-ibm24n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P24-ibm24n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P24-ibm24n05'(suite) -> [];
+'ibm-not-wf-P24-ibm24n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P24-ibm24n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P24-ibm24n04'(suite) -> [];
+'ibm-not-wf-P24-ibm24n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P24-ibm24n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P24-ibm24n03'(suite) -> [];
+'ibm-not-wf-P24-ibm24n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P24-ibm24n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P24-ibm24n02'(suite) -> [];
+'ibm-not-wf-P24-ibm24n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P24-ibm24n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P24-ibm24n01'(suite) -> [];
+'ibm-not-wf-P24-ibm24n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P24-ibm24n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P23-ibm23n06'(suite) -> [];
+'ibm-not-wf-P23-ibm23n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P23-ibm23n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P23-ibm23n05'(suite) -> [];
+'ibm-not-wf-P23-ibm23n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P23-ibm23n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P23-ibm23n04'(suite) -> [];
+'ibm-not-wf-P23-ibm23n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P23-ibm23n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P23-ibm23n03'(suite) -> [];
+'ibm-not-wf-P23-ibm23n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P23-ibm23n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P23-ibm23n02'(suite) -> [];
+'ibm-not-wf-P23-ibm23n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P23-ibm23n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P23-ibm23n01'(suite) -> [];
+'ibm-not-wf-P23-ibm23n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P23-ibm23n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P22-ibm22n03'(suite) -> [];
+'ibm-not-wf-P22-ibm22n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P22-ibm22n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P22-ibm22n02'(suite) -> [];
+'ibm-not-wf-P22-ibm22n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P22-ibm22n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P22-ibm22n01'(suite) -> [];
+'ibm-not-wf-P22-ibm22n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P22-ibm22n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P21-ibm21n03'(suite) -> [];
+'ibm-not-wf-P21-ibm21n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P21-ibm21n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P21-ibm21n02'(suite) -> [];
+'ibm-not-wf-P21-ibm21n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P21-ibm21n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P21-ibm21n01'(suite) -> [];
+'ibm-not-wf-P21-ibm21n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P21-ibm21n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P20-ibm20n01'(suite) -> [];
+'ibm-not-wf-P20-ibm20n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P20-ibm20n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P19-ibm19n03'(suite) -> [];
+'ibm-not-wf-P19-ibm19n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P19-ibm19n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P19-ibm19n02'(suite) -> [];
+'ibm-not-wf-P19-ibm19n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P19-ibm19n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P19-ibm19n01'(suite) -> [];
+'ibm-not-wf-P19-ibm19n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P19-ibm19n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P18-ibm18n02'(suite) -> [];
+'ibm-not-wf-P18-ibm18n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P18-ibm18n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P18-ibm18n01'(suite) -> [];
+'ibm-not-wf-P18-ibm18n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P18-ibm18n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P17-ibm17n04'(suite) -> [];
+'ibm-not-wf-P17-ibm17n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P17-ibm17n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P17-ibm17n03'(suite) -> [];
+'ibm-not-wf-P17-ibm17n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P17-ibm17n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P17-ibm17n02'(suite) -> [];
+'ibm-not-wf-P17-ibm17n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P17-ibm17n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P17-ibm17n01'(suite) -> [];
+'ibm-not-wf-P17-ibm17n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P17-ibm17n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P16-ibm16n04'(suite) -> [];
+'ibm-not-wf-P16-ibm16n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P16-ibm16n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P16-ibm16n03'(suite) -> [];
+'ibm-not-wf-P16-ibm16n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P16-ibm16n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P16-ibm16n02'(suite) -> [];
+'ibm-not-wf-P16-ibm16n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P16-ibm16n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P16-ibm16n01'(suite) -> [];
+'ibm-not-wf-P16-ibm16n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P16-ibm16n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P15-ibm15n04'(suite) -> [];
+'ibm-not-wf-P15-ibm15n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P15-ibm15n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P15-ibm15n03'(suite) -> [];
+'ibm-not-wf-P15-ibm15n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P15-ibm15n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P15-ibm15n02'(suite) -> [];
+'ibm-not-wf-P15-ibm15n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P15-ibm15n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P15-ibm15n01'(suite) -> [];
+'ibm-not-wf-P15-ibm15n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P15-ibm15n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P14-ibm14n03'(suite) -> [];
+'ibm-not-wf-P14-ibm14n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P14-ibm14n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P14-ibm14n02'(suite) -> [];
+'ibm-not-wf-P14-ibm14n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P14-ibm14n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P14-ibm14n01'(suite) -> [];
+'ibm-not-wf-P14-ibm14n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P14-ibm14n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P13-ibm13n03'(suite) -> [];
+'ibm-not-wf-P13-ibm13n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P13-ibm13n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P13-ibm13n02'(suite) -> [];
+'ibm-not-wf-P13-ibm13n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P13-ibm13n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P13-ibm13n01'(suite) -> [];
+'ibm-not-wf-P13-ibm13n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P13-ibm13n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P12-ibm12n03'(suite) -> [];
+'ibm-not-wf-P12-ibm12n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P12-ibm12n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P12-ibm12n02'(suite) -> [];
+'ibm-not-wf-P12-ibm12n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P12-ibm12n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P12-ibm12n01'(suite) -> [];
+'ibm-not-wf-P12-ibm12n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P12-ibm12n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P11-ibm11n04'(suite) -> [];
+'ibm-not-wf-P11-ibm11n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P11-ibm11n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P11-ibm11n03'(suite) -> [];
+'ibm-not-wf-P11-ibm11n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P11-ibm11n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P11-ibm11n02'(suite) -> [];
+'ibm-not-wf-P11-ibm11n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P11-ibm11n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P11-ibm11n01'(suite) -> [];
+'ibm-not-wf-P11-ibm11n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P11-ibm11n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P10-ibm10n08'(suite) -> [];
+'ibm-not-wf-P10-ibm10n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P10-ibm10n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P10-ibm10n07'(suite) -> [];
+'ibm-not-wf-P10-ibm10n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P10-ibm10n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P10-ibm10n06'(suite) -> [];
+'ibm-not-wf-P10-ibm10n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P10-ibm10n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P10-ibm10n05'(suite) -> [];
+'ibm-not-wf-P10-ibm10n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P10-ibm10n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P10-ibm10n04'(suite) -> [];
+'ibm-not-wf-P10-ibm10n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P10-ibm10n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P10-ibm10n03'(suite) -> [];
+'ibm-not-wf-P10-ibm10n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P10-ibm10n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P10-ibm10n02'(suite) -> [];
+'ibm-not-wf-P10-ibm10n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P10-ibm10n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P10-ibm10n01'(suite) -> [];
+'ibm-not-wf-P10-ibm10n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P10-ibm10n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P09-ibm09n04'(suite) -> [];
+'ibm-not-wf-P09-ibm09n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P09-ibm09n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P09-ibm09n03'(suite) -> [];
+'ibm-not-wf-P09-ibm09n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P09-ibm09n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P09-ibm09n02'(suite) -> [];
+'ibm-not-wf-P09-ibm09n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P09-ibm09n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P09-ibm09n01'(suite) -> [];
+'ibm-not-wf-P09-ibm09n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P09-ibm09n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P05-ibm05n03'(suite) -> [];
+'ibm-not-wf-P05-ibm05n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P05-ibm05n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P05-ibm05n02'(suite) -> [];
+'ibm-not-wf-P05-ibm05n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P05-ibm05n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P05-ibm05n01'(suite) -> [];
+'ibm-not-wf-P05-ibm05n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P05-ibm05n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P04-ibm04n18'(suite) -> [];
+'ibm-not-wf-P04-ibm04n18'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P04-ibm04n18.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P04-ibm04n17'(suite) -> [];
+'ibm-not-wf-P04-ibm04n17'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P04-ibm04n17.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P04-ibm04n16'(suite) -> [];
+'ibm-not-wf-P04-ibm04n16'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P04-ibm04n16.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P04-ibm04n15'(suite) -> [];
+'ibm-not-wf-P04-ibm04n15'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P04-ibm04n15.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P04-ibm04n14'(suite) -> [];
+'ibm-not-wf-P04-ibm04n14'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P04-ibm04n14.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P04-ibm04n13'(suite) -> [];
+'ibm-not-wf-P04-ibm04n13'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P04-ibm04n13.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P04-ibm04n12'(suite) -> [];
+'ibm-not-wf-P04-ibm04n12'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P04-ibm04n12.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P04-ibm04n11'(suite) -> [];
+'ibm-not-wf-P04-ibm04n11'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P04-ibm04n11.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P04-ibm04n10'(suite) -> [];
+'ibm-not-wf-P04-ibm04n10'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P04-ibm04n10.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P04-ibm04n09'(suite) -> [];
+'ibm-not-wf-P04-ibm04n09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P04-ibm04n09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P04-ibm04n08'(suite) -> [];
+'ibm-not-wf-P04-ibm04n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P04-ibm04n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P04-ibm04n07'(suite) -> [];
+'ibm-not-wf-P04-ibm04n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P04-ibm04n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P04-ibm04n06'(suite) -> [];
+'ibm-not-wf-P04-ibm04n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P04-ibm04n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P04-ibm04n05'(suite) -> [];
+'ibm-not-wf-P04-ibm04n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P04-ibm04n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P04-ibm04n04'(suite) -> [];
+'ibm-not-wf-P04-ibm04n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P04-ibm04n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P04-ibm04n03'(suite) -> [];
+'ibm-not-wf-P04-ibm04n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P04-ibm04n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P04-ibm04n02'(suite) -> [];
+'ibm-not-wf-P04-ibm04n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P04-ibm04n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P04-ibm04n01'(suite) -> [];
+'ibm-not-wf-P04-ibm04n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P04-ibm04n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P03-ibm03n01'(suite) -> [];
+'ibm-not-wf-P03-ibm03n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P03-ibm03n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n33'(suite) -> [];
+'ibm-not-wf-P02-ibm02n33'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n33.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n32'(suite) -> [];
+'ibm-not-wf-P02-ibm02n32'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n32.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n31'(suite) -> [];
+'ibm-not-wf-P02-ibm02n31'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n31.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n30'(suite) -> [];
+'ibm-not-wf-P02-ibm02n30'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n30.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n29'(suite) -> [];
+'ibm-not-wf-P02-ibm02n29'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n29.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n28'(suite) -> [];
+'ibm-not-wf-P02-ibm02n28'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n28.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n27'(suite) -> [];
+'ibm-not-wf-P02-ibm02n27'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n27.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n26'(suite) -> [];
+'ibm-not-wf-P02-ibm02n26'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n26.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n25'(suite) -> [];
+'ibm-not-wf-P02-ibm02n25'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n25.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n24'(suite) -> [];
+'ibm-not-wf-P02-ibm02n24'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n24.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n23'(suite) -> [];
+'ibm-not-wf-P02-ibm02n23'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n23.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n22'(suite) -> [];
+'ibm-not-wf-P02-ibm02n22'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n22.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n21'(suite) -> [];
+'ibm-not-wf-P02-ibm02n21'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n21.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n20'(suite) -> [];
+'ibm-not-wf-P02-ibm02n20'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n20.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n19'(suite) -> [];
+'ibm-not-wf-P02-ibm02n19'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n19.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n18'(suite) -> [];
+'ibm-not-wf-P02-ibm02n18'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n18.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n17'(suite) -> [];
+'ibm-not-wf-P02-ibm02n17'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n17.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n16'(suite) -> [];
+'ibm-not-wf-P02-ibm02n16'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n16.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n15'(suite) -> [];
+'ibm-not-wf-P02-ibm02n15'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n15.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n14'(suite) -> [];
+'ibm-not-wf-P02-ibm02n14'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n14.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n13'(suite) -> [];
+'ibm-not-wf-P02-ibm02n13'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n13.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n12'(suite) -> [];
+'ibm-not-wf-P02-ibm02n12'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n12.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n11'(suite) -> [];
+'ibm-not-wf-P02-ibm02n11'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n11.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n10'(suite) -> [];
+'ibm-not-wf-P02-ibm02n10'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n10.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n09'(suite) -> [];
+'ibm-not-wf-P02-ibm02n09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n08'(suite) -> [];
+'ibm-not-wf-P02-ibm02n08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n07'(suite) -> [];
+'ibm-not-wf-P02-ibm02n07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n06'(suite) -> [];
+'ibm-not-wf-P02-ibm02n06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n05'(suite) -> [];
+'ibm-not-wf-P02-ibm02n05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n04'(suite) -> [];
+'ibm-not-wf-P02-ibm02n04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n03'(suite) -> [];
+'ibm-not-wf-P02-ibm02n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n02'(suite) -> [];
+'ibm-not-wf-P02-ibm02n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P02-ibm02n01'(suite) -> [];
+'ibm-not-wf-P02-ibm02n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P02-ibm02n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P01-ibm01n03'(suite) -> [];
+'ibm-not-wf-P01-ibm01n03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P01-ibm01n03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P01-ibm01n02'(suite) -> [];
+'ibm-not-wf-P01-ibm01n02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P01-ibm01n02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-not-wf-P01-ibm01n01'(suite) -> [];
+'ibm-not-wf-P01-ibm01n01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-not-wf-P01-ibm01n01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+%%----------------------------------------------------------------------
+
+'ibm-valid-P89-ibm89v01'(suite) -> [];
+'ibm-valid-P89-ibm89v01'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P89-ibm89v01.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["Fails to handle name containing characters > x#ff, since they are converted to atoms"]}.
+
+'ibm-valid-P88-ibm88v01'(suite) -> [];
+'ibm-valid-P88-ibm88v01'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P88-ibm88v01.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["Fails to handle name containing characters > x#ff, since they are converted to atoms"]}.
+
+'ibm-valid-P87-ibm87v01'(suite) -> [];
+'ibm-valid-P87-ibm87v01'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P87-ibm87v01.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["Fails to handle name containing characters > x#ff, since they are converted to atoms"]}.
+
+'ibm-valid-P86-ibm86v01'(suite) -> [];
+'ibm-valid-P86-ibm86v01'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P86-ibm86v01.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["Fails to handle name containing characters > x#ff, since they are converted to atoms"]}.
+
+'ibm-valid-P85-ibm85v01'(suite) -> [];
+'ibm-valid-P85-ibm85v01'(_Config) ->
+% ?line file:set_cwd(?config(data_dir,Config)),
+% ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P85-ibm85v01.xml"]),[]),
+% ?line xmerl:export([A],xmerl_test).
+ {skip,["Fails to handle name containing characters > x#ff, since they are converted to atoms"]}.
+
+'ibm-valid-P82-ibm82v01'(suite) -> [];
+'ibm-valid-P82-ibm82v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P82-ibm82v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P79-ibm79v01'(suite) -> [];
+'ibm-valid-P79-ibm79v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P79-ibm79v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P78-ibm78v01'(suite) -> [];
+'ibm-valid-P78-ibm78v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P78-ibm78v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P70-ibm70v01'(suite) -> [];
+'ibm-valid-P70-ibm70v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P70-ibm70v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P69-ibm69v02'(suite) -> [];
+'ibm-valid-P69-ibm69v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P69-ibm69v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P69-ibm69v01'(suite) -> [];
+'ibm-valid-P69-ibm69v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P69-ibm69v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P68-ibm68v02'(suite) -> [];
+'ibm-valid-P68-ibm68v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P68-ibm68v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P68-ibm68v01'(suite) -> [];
+'ibm-valid-P68-ibm68v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P68-ibm68v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P67-ibm67v01'(suite) -> [];
+'ibm-valid-P67-ibm67v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P67-ibm67v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P66-ibm66v01'(suite) -> [];
+'ibm-valid-P66-ibm66v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P66-ibm66v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P65-ibm65v02'(suite) -> [];
+'ibm-valid-P65-ibm65v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P65-ibm65v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P65-ibm65v01'(suite) -> [];
+'ibm-valid-P65-ibm65v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P65-ibm65v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P64-ibm64v03'(suite) -> [];
+'ibm-valid-P64-ibm64v03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P64-ibm64v03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P64-ibm64v02'(suite) -> [];
+'ibm-valid-P64-ibm64v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P64-ibm64v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P64-ibm64v01'(suite) -> [];
+'ibm-valid-P64-ibm64v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P64-ibm64v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P63-ibm63v05'(suite) -> [];
+'ibm-valid-P63-ibm63v05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P63-ibm63v05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P63-ibm63v04'(suite) -> [];
+'ibm-valid-P63-ibm63v04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P63-ibm63v04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P63-ibm63v03'(suite) -> [];
+'ibm-valid-P63-ibm63v03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P63-ibm63v03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P63-ibm63v02'(suite) -> [];
+'ibm-valid-P63-ibm63v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P63-ibm63v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P63-ibm63v01'(suite) -> [];
+'ibm-valid-P63-ibm63v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P63-ibm63v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P62-ibm62v05'(suite) -> [];
+'ibm-valid-P62-ibm62v05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P62-ibm62v05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P62-ibm62v04'(suite) -> [];
+'ibm-valid-P62-ibm62v04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P62-ibm62v04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P62-ibm62v03'(suite) -> [];
+'ibm-valid-P62-ibm62v03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P62-ibm62v03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P62-ibm62v02'(suite) -> [];
+'ibm-valid-P62-ibm62v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P62-ibm62v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P62-ibm62v01'(suite) -> [];
+'ibm-valid-P62-ibm62v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P62-ibm62v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P61-ibm61v02'(suite) -> [];
+'ibm-valid-P61-ibm61v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P61-ibm61v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P61-ibm61v01'(suite) -> [];
+'ibm-valid-P61-ibm61v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P61-ibm61v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P60-ibm60v04'(suite) -> [];
+'ibm-valid-P60-ibm60v04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P60-ibm60v04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P60-ibm60v03'(suite) -> [];
+'ibm-valid-P60-ibm60v03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P60-ibm60v03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P60-ibm60v02'(suite) -> [];
+'ibm-valid-P60-ibm60v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P60-ibm60v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P60-ibm60v01'(suite) -> [];
+'ibm-valid-P60-ibm60v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P60-ibm60v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P59-ibm59v02'(suite) -> [];
+'ibm-valid-P59-ibm59v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P59-ibm59v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P59-ibm59v01'(suite) -> [];
+'ibm-valid-P59-ibm59v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P59-ibm59v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P58-ibm58v02'(suite) -> [];
+'ibm-valid-P58-ibm58v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P58-ibm58v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P58-ibm58v01'(suite) -> [];
+'ibm-valid-P58-ibm58v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P58-ibm58v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P57-ibm57v01'(suite) -> [];
+'ibm-valid-P57-ibm57v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P57-ibm57v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P56-ibm56v10'(suite) -> [];
+'ibm-valid-P56-ibm56v10'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P56-ibm56v10.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P56-ibm56v09'(suite) -> [];
+'ibm-valid-P56-ibm56v09'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P56-ibm56v09.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P56-ibm56v08'(suite) -> [];
+'ibm-valid-P56-ibm56v08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P56-ibm56v08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P56-ibm56v07'(suite) -> [];
+'ibm-valid-P56-ibm56v07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P56-ibm56v07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P56-ibm56v06'(suite) -> [];
+'ibm-valid-P56-ibm56v06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P56-ibm56v06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P56-ibm56v05'(suite) -> [];
+'ibm-valid-P56-ibm56v05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P56-ibm56v05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P56-ibm56v04'(suite) -> [];
+'ibm-valid-P56-ibm56v04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P56-ibm56v04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P56-ibm56v03'(suite) -> [];
+'ibm-valid-P56-ibm56v03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P56-ibm56v03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P56-ibm56v02'(suite) -> [];
+'ibm-valid-P56-ibm56v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P56-ibm56v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P56-ibm56v01'(suite) -> [];
+'ibm-valid-P56-ibm56v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P56-ibm56v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P55-ibm55v01'(suite) -> [];
+'ibm-valid-P55-ibm55v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P55-ibm55v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P54-ibm54v03'(suite) -> [];
+'ibm-valid-P54-ibm54v03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P54-ibm54v03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P54-ibm54v02'(suite) -> [];
+'ibm-valid-P54-ibm54v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P54-ibm54v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P54-ibm54v01'(suite) -> [];
+'ibm-valid-P54-ibm54v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P54-ibm54v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P52-ibm52v01'(suite) -> [];
+'ibm-valid-P52-ibm52v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P52-ibm52v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P51-ibm51v02'(suite) -> [];
+'ibm-valid-P51-ibm51v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P51-ibm51v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P51-ibm51v01'(suite) -> [];
+'ibm-valid-P51-ibm51v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P51-ibm51v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P50-ibm50v01'(suite) -> [];
+'ibm-valid-P50-ibm50v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P50-ibm50v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P49-ibm49v01'(suite) -> [];
+'ibm-valid-P49-ibm49v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P49-ibm49v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P47-ibm47v01'(suite) -> [];
+'ibm-valid-P47-ibm47v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P47-ibm47v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P45-ibm45v01'(suite) -> [];
+'ibm-valid-P45-ibm45v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P45-ibm45v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P44-ibm44v01'(suite) -> [];
+'ibm-valid-P44-ibm44v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P44-ibm44v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P43-ibm43v01'(suite) -> [];
+'ibm-valid-P43-ibm43v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P43-ibm43v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P42-ibm42v01'(suite) -> [];
+'ibm-valid-P42-ibm42v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P42-ibm42v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P41-ibm41v01'(suite) -> [];
+'ibm-valid-P41-ibm41v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P41-ibm41v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P40-ibm40v01'(suite) -> [];
+'ibm-valid-P40-ibm40v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P40-ibm40v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P39-ibm39v01'(suite) -> [];
+'ibm-valid-P39-ibm39v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P39-ibm39v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P38-ibm38v01'(suite) -> [];
+'ibm-valid-P38-ibm38v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P38-ibm38v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P37-ibm37v01'(suite) -> [];
+'ibm-valid-P37-ibm37v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P37-ibm37v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P36-ibm36v01'(suite) -> [];
+'ibm-valid-P36-ibm36v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P36-ibm36v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P35-ibm35v01'(suite) -> [];
+'ibm-valid-P35-ibm35v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P35-ibm35v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P34-ibm34v01'(suite) -> [];
+'ibm-valid-P34-ibm34v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P34-ibm34v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P33-ibm33v01'(suite) -> [];
+'ibm-valid-P33-ibm33v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P33-ibm33v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P32-ibm32v04'(suite) -> [];
+'ibm-valid-P32-ibm32v04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P32-ibm32v04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P32-ibm32v03'(suite) -> [];
+'ibm-valid-P32-ibm32v03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P32-ibm32v03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P32-ibm32v02'(suite) -> [];
+'ibm-valid-P32-ibm32v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P32-ibm32v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P32-ibm32v01'(suite) -> [];
+'ibm-valid-P32-ibm32v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P32-ibm32v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P31-ibm31v01'(suite) -> [];
+'ibm-valid-P31-ibm31v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P31-ibm31v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P30-ibm30v02'(suite) -> [];
+'ibm-valid-P30-ibm30v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P30-ibm30v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P30-ibm30v01'(suite) -> [];
+'ibm-valid-P30-ibm30v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P30-ibm30v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P29-ibm29v02'(suite) -> [];
+'ibm-valid-P29-ibm29v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P29-ibm29v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P29-ibm29v01'(suite) -> [];
+'ibm-valid-P29-ibm29v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P29-ibm29v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P28-ibm28v02'(suite) -> [];
+'ibm-valid-P28-ibm28v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P28-ibm28v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P28-ibm28v01'(suite) -> [];
+'ibm-valid-P28-ibm28v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P28-ibm28v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P27-ibm27v03'(suite) -> [];
+'ibm-valid-P27-ibm27v03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P27-ibm27v03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P27-ibm27v02'(suite) -> [];
+'ibm-valid-P27-ibm27v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P27-ibm27v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P27-ibm27v01'(suite) -> [];
+'ibm-valid-P27-ibm27v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P27-ibm27v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P26-ibm26v01'(suite) -> [];
+'ibm-valid-P26-ibm26v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P26-ibm26v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P25-ibm25v04'(suite) -> [];
+'ibm-valid-P25-ibm25v04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P25-ibm25v04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P25-ibm25v03'(suite) -> [];
+'ibm-valid-P25-ibm25v03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P25-ibm25v03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P25-ibm25v02'(suite) -> [];
+'ibm-valid-P25-ibm25v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P25-ibm25v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P25-ibm25v01'(suite) -> [];
+'ibm-valid-P25-ibm25v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P25-ibm25v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P24-ibm24v02'(suite) -> [];
+'ibm-valid-P24-ibm24v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P24-ibm24v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P24-ibm24v01'(suite) -> [];
+'ibm-valid-P24-ibm24v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P24-ibm24v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P23-ibm23v06'(suite) -> [];
+'ibm-valid-P23-ibm23v06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P23-ibm23v06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P23-ibm23v05'(suite) -> [];
+'ibm-valid-P23-ibm23v05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P23-ibm23v05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P23-ibm23v04'(suite) -> [];
+'ibm-valid-P23-ibm23v04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P23-ibm23v04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P23-ibm23v03'(suite) -> [];
+'ibm-valid-P23-ibm23v03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P23-ibm23v03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P23-ibm23v02'(suite) -> [];
+'ibm-valid-P23-ibm23v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P23-ibm23v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P23-ibm23v01'(suite) -> [];
+'ibm-valid-P23-ibm23v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P23-ibm23v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P22-ibm22v07'(suite) -> [];
+'ibm-valid-P22-ibm22v07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P22-ibm22v07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P22-ibm22v06'(suite) -> [];
+'ibm-valid-P22-ibm22v06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P22-ibm22v06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P22-ibm22v05'(suite) -> [];
+'ibm-valid-P22-ibm22v05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P22-ibm22v05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P22-ibm22v04'(suite) -> [];
+'ibm-valid-P22-ibm22v04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P22-ibm22v04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P22-ibm22v03'(suite) -> [];
+'ibm-valid-P22-ibm22v03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P22-ibm22v03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P22-ibm22v02'(suite) -> [];
+'ibm-valid-P22-ibm22v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P22-ibm22v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P22-ibm22v01'(suite) -> [];
+'ibm-valid-P22-ibm22v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P22-ibm22v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P21-ibm21v01'(suite) -> [];
+'ibm-valid-P21-ibm21v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P21-ibm21v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P20-ibm20v02'(suite) -> [];
+'ibm-valid-P20-ibm20v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P20-ibm20v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P20-ibm20v01'(suite) -> [];
+'ibm-valid-P20-ibm20v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P20-ibm20v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P19-ibm19v01'(suite) -> [];
+'ibm-valid-P19-ibm19v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P19-ibm19v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P18-ibm18v01'(suite) -> [];
+'ibm-valid-P18-ibm18v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P18-ibm18v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P17-ibm17v01'(suite) -> [];
+'ibm-valid-P17-ibm17v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P17-ibm17v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P16-ibm16v03'(suite) -> [];
+'ibm-valid-P16-ibm16v03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P16-ibm16v03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P16-ibm16v02'(suite) -> [];
+'ibm-valid-P16-ibm16v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P16-ibm16v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P16-ibm16v01'(suite) -> [];
+'ibm-valid-P16-ibm16v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P16-ibm16v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P15-ibm15v04'(suite) -> [];
+'ibm-valid-P15-ibm15v04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P15-ibm15v04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P15-ibm15v03'(suite) -> [];
+'ibm-valid-P15-ibm15v03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P15-ibm15v03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P15-ibm15v02'(suite) -> [];
+'ibm-valid-P15-ibm15v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P15-ibm15v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P15-ibm15v01'(suite) -> [];
+'ibm-valid-P15-ibm15v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P15-ibm15v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P14-ibm14v03'(suite) -> [];
+'ibm-valid-P14-ibm14v03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P14-ibm14v03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P14-ibm14v02'(suite) -> [];
+'ibm-valid-P14-ibm14v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P14-ibm14v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P14-ibm14v01'(suite) -> [];
+'ibm-valid-P14-ibm14v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P14-ibm14v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P13-ibm13v01'(suite) -> [];
+'ibm-valid-P13-ibm13v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P13-ibm13v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P12-ibm12v04'(suite) -> [];
+'ibm-valid-P12-ibm12v04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P12-ibm12v04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P12-ibm12v03'(suite) -> [];
+'ibm-valid-P12-ibm12v03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P12-ibm12v03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P12-ibm12v02'(suite) -> [];
+'ibm-valid-P12-ibm12v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P12-ibm12v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P12-ibm12v01'(suite) -> [];
+'ibm-valid-P12-ibm12v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P12-ibm12v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P11-ibm11v04'(suite) -> [];
+'ibm-valid-P11-ibm11v04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P11-ibm11v04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P11-ibm11v03'(suite) -> [];
+'ibm-valid-P11-ibm11v03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P11-ibm11v03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P11-ibm11v02'(suite) -> [];
+'ibm-valid-P11-ibm11v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P11-ibm11v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P11-ibm11v01'(suite) -> [];
+'ibm-valid-P11-ibm11v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P11-ibm11v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P10-ibm10v08'(suite) -> [];
+'ibm-valid-P10-ibm10v08'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P10-ibm10v08.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P10-ibm10v07'(suite) -> [];
+'ibm-valid-P10-ibm10v07'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P10-ibm10v07.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P10-ibm10v06'(suite) -> [];
+'ibm-valid-P10-ibm10v06'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P10-ibm10v06.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P10-ibm10v05'(suite) -> [];
+'ibm-valid-P10-ibm10v05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P10-ibm10v05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P10-ibm10v04'(suite) -> [];
+'ibm-valid-P10-ibm10v04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P10-ibm10v04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P10-ibm10v03'(suite) -> [];
+'ibm-valid-P10-ibm10v03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P10-ibm10v03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P10-ibm10v02'(suite) -> [];
+'ibm-valid-P10-ibm10v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P10-ibm10v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P10-ibm10v01'(suite) -> [];
+'ibm-valid-P10-ibm10v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P10-ibm10v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P09-ibm09v05'(suite) -> [];
+'ibm-valid-P09-ibm09v05'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P09-ibm09v05.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P09-ibm09v04'(suite) -> [];
+'ibm-valid-P09-ibm09v04'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P09-ibm09v04.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P09-ibm09v03'(suite) -> [];
+'ibm-valid-P09-ibm09v03'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P09-ibm09v03.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P09-ibm09v02'(suite) -> [];
+'ibm-valid-P09-ibm09v02'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P09-ibm09v02.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P09-ibm09v01'(suite) -> [];
+'ibm-valid-P09-ibm09v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P09-ibm09v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P03-ibm03v01'(suite) -> [];
+'ibm-valid-P03-ibm03v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P03-ibm03v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P02-ibm02v01'(suite) -> [];
+'ibm-valid-P02-ibm02v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P02-ibm02v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+'ibm-valid-P01-ibm01v01'(suite) -> [];
+'ibm-valid-P01-ibm01v01'(Config) ->
+ ?line file:set_cwd(?config(data_dir,Config)),
+ ?line {A,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),ibm,"ibm-valid-P01-ibm01v01.xml"]),[]),
+ ?line xmerl:export([A],xmerl_test).
+
+
+
+%%======================================================================
+%% Support Functions
+%%======================================================================
+
+%% Dir is a directory
+rm_f_(Dir) ->
+ ?line {ok,CWD} = file:get_cwd(),
+ ?line {ok,FileList} = file:list_dir(Dir),
+ ?line file:set_cwd(filename:join([CWD,Dir])),
+ rm_files(FileList),
+ ?line file:set_cwd(CWD),
+ ? line ok = file:del_dir(Dir).
+
+rm_files([])->
+ ok;
+rm_files([F|Fs]) ->
+ case filelib:is_dir(F) of
+ true ->
+ rm_f_(F);
+ _ ->
+ ?line ok = file:delete(F)
+ end,
+ rm_files(Fs).
+
+-include_lib("kernel/include/file.hrl").
+change_mode(Files) ->
+ change_mode3(Files).
+change_mode2(Dir)->
+ ?line {ok,CWD} = file:get_cwd(),
+ ?line {ok,FileList} = file:list_dir(Dir),
+ ?line file:set_cwd(filename:join([CWD,Dir])),
+ change_mode3(FileList),
+ ?line file:set_cwd(CWD).
+change_mode3([]) ->
+ ok;
+change_mode3([F|Fs]) ->
+ case filelib:is_dir(F) of
+ true ->
+ chmod(F),
+ change_mode2(F);
+ _ ->
+ chmod(F)
+ end,
+ change_mode3(Fs).
+
+chmod(F) ->
+ case file:read_file_info(F) of
+ {ok,FileInfo} ->
+ Mode= FileInfo#file_info.mode,
+ file:write_file_info(F,FileInfo#file_info{mode=8#00777 bor Mode});
+ _ ->
+ ok
+ end.
+
+
+
+
+
+%%add_xml_path(TestCase) ->
+%testcase_dir(TestCase) ->
+% add_xml_path(lists:member(TestCase,ibm_test_cases(suite)),?ibm_dir,TestCase,
+% [{fun japanese_test_cases/1,?japanese_dir},
+% {fun oasis_test_cases/1,?oasis_dir},
+% {fun sun_test_cases/1,?sun_dir},
+% {fun xmltest_test_cases/1,?xmltest_dir}]).
+%add_xml_path(true,Dir,_,_) ->
+% io:format("directory in path:~p~n",[Dir]),
+%% ?line code:add_patha(Dir);
+% Dir;
+%add_xml_path(_,_,TestCase,[{NextTCs,NextDir}|Rest]) ->
+% add_xml_path(lists:member(TestCase,NextTCs(suite)),NextDir,TestCase,Rest);
+%add_xml_path(false,_,TC,[]) ->
+% exit({error,{xmltests,uncovered_test_case,TC}}).
+
diff --git a/lib/xmerl/test/xmerl_std_SUITE_data/ibm.tgz b/lib/xmerl/test/xmerl_std_SUITE_data/ibm.tgz
new file mode 100644
index 0000000000..c36bcb5bd3
--- /dev/null
+++ b/lib/xmerl/test/xmerl_std_SUITE_data/ibm.tgz
Binary files differ
diff --git a/lib/xmerl/test/xmerl_std_SUITE_data/japanese.tgz b/lib/xmerl/test/xmerl_std_SUITE_data/japanese.tgz
new file mode 100644
index 0000000000..cf1d71a2fd
--- /dev/null
+++ b/lib/xmerl/test/xmerl_std_SUITE_data/japanese.tgz
Binary files differ
diff --git a/lib/xmerl/test/xmerl_std_SUITE_data/oasis.tgz b/lib/xmerl/test/xmerl_std_SUITE_data/oasis.tgz
new file mode 100644
index 0000000000..ab809a63e7
--- /dev/null
+++ b/lib/xmerl/test/xmerl_std_SUITE_data/oasis.tgz
Binary files differ
diff --git a/lib/xmerl/test/xmerl_std_SUITE_data/sun.tgz b/lib/xmerl/test/xmerl_std_SUITE_data/sun.tgz
new file mode 100644
index 0000000000..022e64ab9e
--- /dev/null
+++ b/lib/xmerl/test/xmerl_std_SUITE_data/sun.tgz
Binary files differ
diff --git a/lib/xmerl/test/xmerl_std_SUITE_data/w3c-copyright-19980720.html b/lib/xmerl/test/xmerl_std_SUITE_data/w3c-copyright-19980720.html
new file mode 100644
index 0000000000..bc5c62fdbc
--- /dev/null
+++ b/lib/xmerl/test/xmerl_std_SUITE_data/w3c-copyright-19980720.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"><head>
+
+
+<meta name="generator" content="HTML Tidy, see www.w3.org">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<link rel="stylesheet" type="text/css" href="copyright-software-19980720_files/base.css"><title>W3C IPR SOFTWARE NOTICE</title></head><body bgcolor="#ffffff" text="#000000">
+<h1>W3C<sup>�</sup> SOFTWARE NOTICE AND LICENSE</h1>
+
+<h3>Copyright � 1994-2002 <a href="http://www.w3.org/">World
+Wide Web Consortium</a>, (<a href="http://www.lcs.mit.edu/">Massachusetts Institute of
+Technology</a>, <a href="http://www.inria.fr/">Institut National de
+Recherche en Informatique et en Automatique</a>, <a href="http://www.keio.ac.jp/">Keio University</a>). All Rights
+Reserved. http://www.w3.org/Consortium/Legal/</h3>
+
+<p>This W3C work (including software, documents, or other related
+items) is being provided by the copyright holders under the
+following license. By obtaining, using and/or copying this work,
+you (the licensee) agree that you have read, understood, and will
+comply with the following terms and conditions:</p>
+
+<p>Permission to use, copy, modify, and distribute this software
+and its documentation, with or without modification,&nbsp; for any
+purpose and without fee or royalty is hereby granted, provided that
+you include the following on ALL copies of the software and
+documentation or portions thereof, including modifications, that
+you make:</p>
+
+<ol>
+<li>The full text of this NOTICE in a location viewable to users of
+the redistributed or derivative work.</li>
+
+<li>Any pre-existing intellectual property disclaimers, notices, or
+terms and conditions. If none exist, a short notice of the
+following form (hypertext is preferred, text is permitted) should
+be used within the body of any redistributed or derivative code:
+"Copyright � [$date-of-software] <a href="http://www.w3.org/">World Wide Web Consortium</a>, (<a href="http://www.lcs.mit.edu/">Massachusetts Institute of
+Technology</a>, <a href="http://www.inria.fr/">Institut National de
+Recherche en Informatique et en Automatique</a>, <a href="http://www.keio.ac.jp/">Keio University</a>). All Rights
+Reserved. http://www.w3.org/Consortium/Legal/"</li>
+
+<li>Notice of any changes or modifications to the W3C files,
+including the date changes were made. (We recommend you provide
+URIs to the location from which the code is derived.)</li>
+</ol>
+
+<p>THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND
+COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF
+MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE
+USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD
+PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.</p>
+
+<p>COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT,
+SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE
+SOFTWARE OR DOCUMENTATION.</p>
+
+<p>The name and trademarks of copyright holders may NOT be used in
+advertising or publicity pertaining to the software without
+specific, written prior permission. Title to copyright in this
+software and any associated documentation will at all times remain
+with copyright holders.</p>
+
+<p>____________________________________</p>
+
+<p>This formulation of W3C's notice and license became active on
+August 14 1998 so as to improve compatibility with GPL. This
+version ensures that W3C software licensing terms are no more
+restrictive than GPL and consequently W3C software may be
+distributed in GPL packages. See the <a href="http://www.w3.org/Consortium/Legal/copyright-software-19980519.html">older formulation</a> for
+the policy prior to this date. Please see our <a href="http://www.w3.org/Consortium/Legal/IPR-FAQ.html">Copyright FAQ</a> for common questions about
+using materials from our site, including specific terms and
+conditions for packages like libwww, Amaya, and Jigsaw. Other
+questions about this notice can be directed to <a href="mailto:[email protected]">[email protected]</a>.<br>
+&nbsp;</p>
+
+<p>&nbsp;</p>
+
+<address><a href="http://www.w3.org/Help/Webmaster.html">webmaster</a><br>
+ (last updated $Date: 2002/02/13 14:08:32 $)</address>
+</body></html> \ No newline at end of file
diff --git a/lib/xmerl/test/xmerl_std_SUITE_data/xmltest.tgz b/lib/xmerl/test/xmerl_std_SUITE_data/xmltest.tgz
new file mode 100644
index 0000000000..d49fe26ff0
--- /dev/null
+++ b/lib/xmerl/test/xmerl_std_SUITE_data/xmltest.tgz
Binary files differ
diff --git a/lib/xmerl/test/xmerl_test_lib.erl b/lib/xmerl/test/xmerl_test_lib.erl
new file mode 100644
index 0000000000..a83956c076
--- /dev/null
+++ b/lib/xmerl/test/xmerl_test_lib.erl
@@ -0,0 +1,92 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 : xmerl_test_lib.erl
+%%% Author : Bertil Karlsson <bertil@finrod>
+%%% Description :
+%%%
+%%% Created : 28 Apr 2006 by Bertil Karlsson <bertil@finrod>
+%%%-------------------------------------------------------------------
+-module(xmerl_test_lib).
+
+-compile(export_all).
+
+-include_lib("test_server/include/test_server.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
+
+%% cmp_element/2
+%% First argument result after parsing
+%% Second argument result after validation
+cmp_element(E,E) ->
+ ok;
+cmp_element(#xmlElement{name=N,attributes=A1,content=C1},
+ #xmlElement{name=N,attributes=A2,content=C2}) ->
+ case cmp_attributes(A1,A2) of
+ ok ->
+ cmp_elements(C1,C2);
+ Err -> Err
+ end;
+cmp_element(#xmlText{},#xmlText{}) ->
+ ok;
+cmp_element(A,B) ->
+ {error,{A,does_not_match,B}}.
+
+cmp_elements([H1|T1],[H2|T2]) ->
+ case cmp_element(H1,H2) of
+ ok ->
+ cmp_elements(T1,T2);
+ Err ->
+ Err
+ end;
+cmp_elements([],[]) ->
+ ok.
+
+%% All attributes in argument 1 must be present in 2
+cmp_attributes([A1|T1],Atts2) ->
+ case keysearch_delete(A1#xmlAttribute.name,#xmlAttribute.name,Atts2) of
+ {A2,NewAtts2} ->
+ case A1#xmlAttribute.value == A2#xmlAttribute.value of
+ true ->
+ cmp_attributes(T1,NewAtts2);
+ _ ->
+ {error,{mismatching_values_in_attsibutes,A1,A2}}
+ end;
+ _ ->
+ {error,{no_matching_attsibute,A1,in,Atts2}}
+ end;
+cmp_attributes([],_) ->
+ ok.
+
+keysearch_delete(Key,N,List) ->
+ case lists:keysearch(Key,N,List) of
+ {value,Res} ->
+ {Res,lists:keydelete(Key,N,List)};
+ _ ->
+ false
+ end.
+
+
+%% Some test suites use the same testdata ("xmerl_sax_std_SUITE" and "xmerl_std_SUITE"),
+%% so the data directory is not cloned. This function retrieves the path to
+%% the original data directory.
+
+get_data_dir(Config) ->
+ Data0 = ?config(data_dir, Config),
+ {ok,Data,_} = regexp:sub(Data0, "xmerl_sax_std_SUITE", "xmerl_std_SUITE"),
+ Data.
diff --git a/lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE.erl b/lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE.erl
new file mode 100644
index 0000000000..44ec4b592d
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE.erl
@@ -0,0 +1,24131 @@
+%%
+%% %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%
+%%
+%%
+%%% Purpose : Test suite for the xmerl application
+
+%% Do NOT edit this file. It is generated by the generate_xsd_suite module
+%% For more info read the comments in the header of that file.
+
+-module('xmerl_xsd_MS2002-01-16_SUITE').
+
+-compile(export_all).
+
+-include_lib("test_server/include/test_server.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
+-include_lib("xmerl/include/xmerl_xsd.hrl").
+
+
+all() ->
+ [att, ct, elem, group, idc_, id, mgABCD, mgEFG, mgHIJ,
+ mgK, mgLM, mgN, mgOP, mgQR, mgS, particlesAB,
+ particlesCDE, particlesFHI, particlesJ,
+ particlesKOSRTQUVW, stABCDE, stFGH, stIJK, stZ,
+ wildABCDEF, wildGHI, wildJKLMNQOP, wildZ].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+
+%% initialization before the test suite
+init_per_suite(Config) ->
+ Dog=test_server:timetrap({minutes,10}),
+ xmerl_xsd_lib:unpack(Config,msx),
+ {ok,LogFile} = xmerl_xsd_lib:create_error_log_file(Config,msx),
+ test_server:timetrap_cancel(Dog),
+ [{suite,msx},{xmerl_error_log,LogFile}|Config].
+
+end_per_suite(Config) ->
+ xmerl_xsd_lib:rmdir(Config,msx),
+ xmerl_xsd_lib:close_error_log_file(Config),
+ ok.
+
+%% initialization before each testcase
+init_per_testcase(TestCase,Config) ->
+ Dog=test_server:timetrap({minutes,3}),
+ [{testcase,TestCase},{watchdog, Dog}|Config].
+
+%% clean up after each testcase
+end_per_testcase(_Func,Config) ->
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+%% Syntax Checking for Attribute Declaration
+
+att(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attA001.xsd','./msxsdtest/attribute',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ ?line {STRes1,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attA002.xsd','./msxsdtest/attribute',invalid),
+ STResList2 = [STRes1|STResList1],
+
+
+ ?line {STRes2,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attA003.xsd','./msxsdtest/attribute',invalid),
+ STResList3 = [STRes2|STResList2],
+
+
+ ?line {STRes3,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attA004.xsd','./msxsdtest/attribute',invalid),
+ STResList4 = [STRes3|STResList3],
+
+
+ ?line {STRes4,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attA005.xsd','./msxsdtest/attribute',invalid),
+ STResList5 = [STRes4|STResList4],
+
+
+ ?line {STRes5,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attA006.xsd','./msxsdtest/attribute',invalid),
+ STResList6 = [STRes5|STResList5],
+
+
+ ?line {STRes6,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attA007.xsd','./msxsdtest/attribute',valid),
+ STResList7 = [STRes6|STResList6],
+
+
+ ?line {STRes7,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attA008.xsd','./msxsdtest/attribute',valid),
+ STResList8 = [STRes7|STResList7],
+
+
+ ?line {STRes8,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attB001.xsd','./msxsdtest/attribute',valid),
+ STResList9 = [STRes8|STResList8],
+
+
+ ?line {STRes9,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attB002.xsd','./msxsdtest/attribute',valid),
+ STResList10 = [STRes9|STResList9],
+
+
+ ?line {STRes10,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attB003.xsd','./msxsdtest/attribute',valid),
+ STResList11 = [STRes10|STResList10],
+
+
+ ?line {STRes11,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attB004.xsd','./msxsdtest/attribute',valid),
+ STResList12 = [STRes11|STResList11],
+
+
+ ?line {STRes12,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attB005.xsd','./msxsdtest/attribute',invalid),
+ STResList13 = [STRes12|STResList12],
+
+
+ ?line {STRes13,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attB006.xsd','./msxsdtest/attribute',invalid),
+ STResList14 = [STRes13|STResList13],
+
+
+ ?line {STRes14,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attC001.xsd','./msxsdtest/attribute',valid),
+ STResList15 = [STRes14|STResList14],
+
+
+
+
+ ?line {STRes15,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attC003.xsd','./msxsdtest/attribute',valid),
+ STResList16 = [STRes15|STResList15],
+
+
+ ?line {STRes16,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attC004.xsd','./msxsdtest/attribute',invalid),
+ STResList17 = [STRes16|STResList16],
+
+
+ ?line {STRes17,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attC005.xsd','./msxsdtest/attribute',invalid),
+ STResList18 = [STRes17|STResList17],
+
+
+ ?line {STRes18,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attC006.xsd','./msxsdtest/attribute',invalid),
+ STResList19 = [STRes18|STResList18],
+
+
+ ?line {STRes19,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attC007.xsd','./msxsdtest/attribute',invalid),
+ STResList20 = [STRes19|STResList19],
+
+
+ ?line {STRes20,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attC008.xsd','./msxsdtest/attribute',invalid),
+ STResList21 = [STRes20|STResList20],
+
+
+ ?line {STRes21,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attC009.xsd','./msxsdtest/attribute',invalid),
+ STResList22 = [STRes21|STResList21],
+
+
+ ?line {STRes22,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attC010.xsd','./msxsdtest/attribute',invalid),
+ STResList23 = [STRes22|STResList22],
+
+
+ ?line {STRes23,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attD001.xsd','./msxsdtest/attribute',valid),
+ STResList24 = [STRes23|STResList23],
+
+
+ ?line {STRes24,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attD002.xsd','./msxsdtest/attribute',invalid),
+ STResList25 = [STRes24|STResList24],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attD003.xsd','./msxsdtest/attribute',valid),
+ STResList26 = [STRes25|STResList25],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attD003.xml','./msxsdtest/attribute',valid,S25),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attD004.xsd','./msxsdtest/attribute',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attD004.xml','./msxsdtest/attribute',valid,S26),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes27,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attD005.xsd','./msxsdtest/attribute',invalid),
+ STResList28 = [STRes27|STResList27],
+
+
+ ?line {STRes28,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attD006.xsd','./msxsdtest/attribute',invalid),
+ STResList29 = [STRes28|STResList28],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attD007.xsd','./msxsdtest/attribute',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attD007.xml','./msxsdtest/attribute',valid,S29),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attE001.xsd','./msxsdtest/attribute',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attE001.xml','./msxsdtest/attribute',valid,S30),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes31,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attE002.xsd','./msxsdtest/attribute',invalid),
+ STResList32 = [STRes31|STResList31],
+
+
+ ?line {STRes32,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attE003.xsd','./msxsdtest/attribute',invalid),
+ STResList33 = [STRes32|STResList32],
+
+
+ ?line {STRes33,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attE004.xsd','./msxsdtest/attribute',invalid),
+ STResList34 = [STRes33|STResList33],
+
+
+ ?line {STRes34,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attE005.xsd','./msxsdtest/attribute',invalid),
+ STResList35 = [STRes34|STResList34],
+
+
+ ?line {STRes35,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attE006.xsd','./msxsdtest/attribute',invalid),
+ STResList36 = [STRes35|STResList35],
+
+
+ ?line {STRes36,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attE007.xsd','./msxsdtest/attribute',invalid),
+ STResList37 = [STRes36|STResList36],
+
+
+ ?line {STRes37,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attE008.xsd','./msxsdtest/attribute',valid),
+ STResList38 = [STRes37|STResList37],
+
+
+ ?line {STRes38,S38} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attF001.xsd','./msxsdtest/attribute',valid),
+ STResList39 = [STRes38|STResList38],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attF001.xml','./msxsdtest/attribute',invalid,S38),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes39,S39} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attF002.xsd','./msxsdtest/attribute',valid),
+ STResList40 = [STRes39|STResList39],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attF002.xml','./msxsdtest/attribute',valid,S39),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes40,S40} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attF003.xsd','./msxsdtest/attribute',valid),
+ STResList41 = [STRes40|STResList40],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attF003.xml','./msxsdtest/attribute',valid,S40),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes41,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attF004.xsd','./msxsdtest/attribute',invalid),
+ STResList42 = [STRes41|STResList41],
+
+
+ ?line {STRes42,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attF005.xsd','./msxsdtest/attribute',invalid),
+ STResList43 = [STRes42|STResList42],
+
+
+ ?line {STRes43,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attF006.xsd','./msxsdtest/attribute',invalid),
+ STResList44 = [STRes43|STResList43],
+
+
+ ?line {STRes44,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attF007.xsd','./msxsdtest/attribute',invalid),
+ STResList45 = [STRes44|STResList44],
+
+
+ ?line {STRes45,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attF008.xsd','./msxsdtest/attribute',invalid),
+ STResList46 = [STRes45|STResList45],
+
+
+ ?line {STRes46,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attF009.xsd','./msxsdtest/attribute',invalid),
+ STResList47 = [STRes46|STResList46],
+
+
+ ?line {STRes47,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attF010.xsd','./msxsdtest/attribute',invalid),
+ STResList48 = [STRes47|STResList47],
+
+
+ ?line {STRes48,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attF011.xsd','./msxsdtest/attribute',invalid),
+ STResList49 = [STRes48|STResList48],
+
+
+ ?line {STRes49,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attG001.xsd','./msxsdtest/attribute',valid),
+ STResList50 = [STRes49|STResList49],
+
+
+ ?line {STRes50,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attG002.xsd','./msxsdtest/attribute',valid),
+ STResList51 = [STRes50|STResList50],
+
+
+ ?line {STRes51,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attG003.xsd','./msxsdtest/attribute',valid),
+ STResList52 = [STRes51|STResList51],
+
+
+ ?line {STRes52,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attH001.xsd','./msxsdtest/attribute',invalid),
+ STResList53 = [STRes52|STResList52],
+
+
+ ?line {STRes53,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attI001.xsd','./msxsdtest/attribute',valid),
+ STResList54 = [STRes53|STResList53],
+
+
+ ?line {STRes54,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attI002.xsd','./msxsdtest/attribute',valid),
+ STResList55 = [STRes54|STResList54],
+
+
+ ?line {STRes55,S55} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attI003.xsd','./msxsdtest/attribute',valid),
+ STResList56 = [STRes55|STResList55],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attI003.xml','./msxsdtest/attribute',valid,S55),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes56,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attI004.xsd','./msxsdtest/attribute',invalid),
+ STResList57 = [STRes56|STResList56],
+
+
+ ?line {STRes57,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attI005.xsd','./msxsdtest/attribute',invalid),
+ STResList58 = [STRes57|STResList57],
+
+
+ ?line {STRes58,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attI006.xsd','./msxsdtest/attribute',invalid),
+ STResList59 = [STRes58|STResList58],
+
+
+ ?line {STRes59,S59} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attJ001.xsd','./msxsdtest/attribute',valid),
+ STResList60 = [STRes59|STResList59],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attJ001.xml','./msxsdtest/attribute',valid,S59),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes60,S60} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attJ002.xsd','./msxsdtest/attribute',valid),
+ STResList61 = [STRes60|STResList60],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attJ002.xml','./msxsdtest/attribute',invalid,S60),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes61,S61} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attJ003.xsd','./msxsdtest/attribute',valid),
+ STResList62 = [STRes61|STResList61],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attJ003.xml','./msxsdtest/attribute',invalid,S61),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes62,S62} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attJ004.xsd','./msxsdtest/attribute',valid),
+ STResList63 = [STRes62|STResList62],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attJ004.xml','./msxsdtest/attribute',valid,S62),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes63,S63} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attJ005.xsd','./msxsdtest/attribute',valid),
+ STResList64 = [STRes63|STResList63],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attJ005.xml','./msxsdtest/attribute',valid,S63),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes64,S64} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attJ006.xsd','./msxsdtest/attribute',valid),
+ STResList65 = [STRes64|STResList64],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attJ006.xml','./msxsdtest/attribute',valid,S64),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes65,S65} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attJ007.xsd','./msxsdtest/attribute',valid),
+ STResList66 = [STRes65|STResList65],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attJ007.xml','./msxsdtest/attribute',valid,S65),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes66,S66} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attJ008.xsd','./msxsdtest/attribute',valid),
+ STResList67 = [STRes66|STResList66],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attJ008.xml','./msxsdtest/attribute',invalid,S66),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes67,S67} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attJ009.xsd','./msxsdtest/attribute',valid),
+ STResList68 = [STRes67|STResList67],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attJ009.xml','./msxsdtest/attribute',invalid,S67),
+ ITResList17 = [ITRes16|ITResList16],
+
+
+ ?line {STRes68,S68} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attJ010.xsd','./msxsdtest/attribute',valid),
+ STResList69 = [STRes68|STResList68],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attJ010.xml','./msxsdtest/attribute',invalid,S68),
+ ITResList18 = [ITRes17|ITResList17],
+
+
+ ?line {STRes69,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attJ011.xsd','./msxsdtest/attribute',invalid),
+ STResList70 = [STRes69|STResList69],
+
+
+ ?line {STRes70,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attJ012.xsd','./msxsdtest/attribute',invalid),
+ STResList71 = [STRes70|STResList70],
+
+
+ ?line {STRes71,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attJ013.xsd','./msxsdtest/attribute',invalid),
+ STResList72 = [STRes71|STResList71],
+
+
+ ?line {STRes72,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attJ014.xsd','./msxsdtest/attribute',invalid),
+ STResList73 = [STRes72|STResList72],
+
+
+ ?line {STRes73,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attJ015.xsd','./msxsdtest/attribute',invalid),
+ STResList74 = [STRes73|STResList73],
+
+
+ ?line {STRes74,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attJ016.xsd','./msxsdtest/attribute',invalid),
+ STResList75 = [STRes74|STResList74],
+
+
+ ?line {STRes75,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attJ017.xsd','./msxsdtest/attribute',invalid),
+ STResList76 = [STRes75|STResList75],
+
+
+ ?line {STRes76,S76} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attJ018.xsd','./msxsdtest/attribute',valid),
+ STResList77 = [STRes76|STResList76],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attJ018.xml','./msxsdtest/attribute',valid,S76),
+ ITResList19 = [ITRes18|ITResList18],
+
+
+ ?line {STRes77,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKa001.xsd','./msxsdtest/attribute',invalid),
+ STResList78 = [STRes77|STResList77],
+
+
+ ?line {STRes78,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKa002.xsd','./msxsdtest/attribute',valid),
+ STResList79 = [STRes78|STResList78],
+
+
+ ?line {STRes79,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKa003.xsd','./msxsdtest/attribute',invalid),
+ STResList80 = [STRes79|STResList79],
+
+
+ ?line {STRes80,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKa004.xsd','./msxsdtest/attribute',invalid),
+ STResList81 = [STRes80|STResList80],
+
+
+ ?line {STRes81,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKa005.xsd','./msxsdtest/attribute',invalid),
+ STResList82 = [STRes81|STResList81],
+
+
+ ?line {STRes82,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKa006.xsd','./msxsdtest/attribute',valid),
+ STResList83 = [STRes82|STResList82],
+
+
+ ?line {STRes83,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKa007.xsd','./msxsdtest/attribute',invalid),
+ STResList84 = [STRes83|STResList83],
+
+
+ ?line {STRes84,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKa008.xsd','./msxsdtest/attribute',invalid),
+ STResList85 = [STRes84|STResList84],
+
+
+ ?line {STRes85,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKa009.xsd','./msxsdtest/attribute',invalid),
+ STResList86 = [STRes85|STResList85],
+
+
+ ?line {STRes86,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKa010.xsd','./msxsdtest/attribute',invalid),
+ STResList87 = [STRes86|STResList86],
+
+
+ ?line {STRes87,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKa011.xsd','./msxsdtest/attribute',invalid),
+ STResList88 = [STRes87|STResList87],
+
+
+ ?line {STRes88,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKa012.xsd','./msxsdtest/attribute',invalid),
+ STResList89 = [STRes88|STResList88],
+
+
+ ?line {STRes89,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKa013.xsd','./msxsdtest/attribute',invalid),
+ STResList90 = [STRes89|STResList89],
+
+
+ ?line {STRes90,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKa014.xsd','./msxsdtest/attribute',invalid),
+ STResList91 = [STRes90|STResList90],
+
+
+ ?line {STRes91,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKa015.xsd','./msxsdtest/attribute',invalid),
+ STResList92 = [STRes91|STResList91],
+
+
+ ?line {STRes92,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKb001.xsd','./msxsdtest/attribute',invalid),
+ STResList93 = [STRes92|STResList92],
+
+
+ ?line {STRes93,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKb002.xsd','./msxsdtest/attribute',valid),
+ STResList94 = [STRes93|STResList93],
+
+
+ ?line {STRes94,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKb003.xsd','./msxsdtest/attribute',valid),
+ STResList95 = [STRes94|STResList94],
+
+
+ ?line {STRes95,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKb004.xsd','./msxsdtest/attribute',invalid),
+ STResList96 = [STRes95|STResList95],
+
+
+ ?line {STRes96,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKb005.xsd','./msxsdtest/attribute',invalid),
+ STResList97 = [STRes96|STResList96],
+
+
+ ?line {STRes97,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKb006.xsd','./msxsdtest/attribute',valid),
+ STResList98 = [STRes97|STResList97],
+
+
+ ?line {STRes98,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKb007.xsd','./msxsdtest/attribute',valid),
+ STResList99 = [STRes98|STResList98],
+
+
+ ?line {STRes99,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKb008.xsd','./msxsdtest/attribute',valid),
+ STResList100 = [STRes99|STResList99],
+
+
+ ?line {STRes100,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKb009.xsd','./msxsdtest/attribute',valid),
+ STResList101 = [STRes100|STResList100],
+
+
+ ?line {STRes101,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKb010.xsd','./msxsdtest/attribute',invalid),
+ STResList102 = [STRes101|STResList101],
+
+
+ ?line {STRes102,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKb011.xsd','./msxsdtest/attribute',invalid),
+ STResList103 = [STRes102|STResList102],
+
+
+ ?line {STRes103,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKb012.xsd','./msxsdtest/attribute',invalid),
+ STResList104 = [STRes103|STResList103],
+
+
+ ?line {STRes104,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKb013.xsd','./msxsdtest/attribute',invalid),
+ STResList105 = [STRes104|STResList104],
+
+
+ ?line {STRes105,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKb014.xsd','./msxsdtest/attribute',invalid),
+ STResList106 = [STRes105|STResList105],
+
+
+ ?line {STRes106,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKb015.xsd','./msxsdtest/attribute',invalid),
+ STResList107 = [STRes106|STResList106],
+
+
+ ?line {STRes107,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKb016.xsd','./msxsdtest/attribute',invalid),
+ STResList108 = [STRes107|STResList107],
+
+
+ ?line {STRes108,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKb017.xsd','./msxsdtest/attribute',invalid),
+ STResList109 = [STRes108|STResList108],
+
+
+ ?line {STRes109,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKb018.xsd','./msxsdtest/attribute',invalid),
+ STResList110 = [STRes109|STResList109],
+
+
+ ?line {STRes110,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKc001.xsd','./msxsdtest/attribute',invalid),
+ STResList111 = [STRes110|STResList110],
+
+
+ ?line {STRes111,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKc002.xsd','./msxsdtest/attribute',valid),
+ STResList112 = [STRes111|STResList111],
+
+
+ ?line {STRes112,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKc003.xsd','./msxsdtest/attribute',valid),
+ STResList113 = [STRes112|STResList112],
+
+
+ ?line {STRes113,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKc004.xsd','./msxsdtest/attribute',invalid),
+ STResList114 = [STRes113|STResList113],
+
+
+ ?line {STRes114,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKc005.xsd','./msxsdtest/attribute',invalid),
+ STResList115 = [STRes114|STResList114],
+
+
+ ?line {STRes115,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKc006.xsd','./msxsdtest/attribute',valid),
+ STResList116 = [STRes115|STResList115],
+
+
+ ?line {STRes116,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKc007.xsd','./msxsdtest/attribute',valid),
+ STResList117 = [STRes116|STResList116],
+
+
+ ?line {STRes117,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKc008.xsd','./msxsdtest/attribute',valid),
+ STResList118 = [STRes117|STResList117],
+
+
+ ?line {STRes118,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKc009.xsd','./msxsdtest/attribute',valid),
+ STResList119 = [STRes118|STResList118],
+
+
+ ?line {STRes119,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKc010.xsd','./msxsdtest/attribute',invalid),
+ STResList120 = [STRes119|STResList119],
+
+
+ ?line {STRes120,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKc011.xsd','./msxsdtest/attribute',invalid),
+ STResList121 = [STRes120|STResList120],
+
+
+ ?line {STRes121,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKc012.xsd','./msxsdtest/attribute',invalid),
+ STResList122 = [STRes121|STResList121],
+
+
+ ?line {STRes122,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKc013.xsd','./msxsdtest/attribute',invalid),
+ STResList123 = [STRes122|STResList122],
+
+
+ ?line {STRes123,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKc014.xsd','./msxsdtest/attribute',invalid),
+ STResList124 = [STRes123|STResList123],
+
+
+ ?line {STRes124,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKc015.xsd','./msxsdtest/attribute',invalid),
+ STResList125 = [STRes124|STResList124],
+
+
+ ?line {STRes125,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKc016.xsd','./msxsdtest/attribute',invalid),
+ STResList126 = [STRes125|STResList125],
+
+
+ ?line {STRes126,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKc017.xsd','./msxsdtest/attribute',invalid),
+ STResList127 = [STRes126|STResList126],
+
+
+ ?line {STRes127,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attKc018.xsd','./msxsdtest/attribute',invalid),
+ STResList128 = [STRes127|STResList127],
+
+
+ ?line {STRes128,S128} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attLa001.xsd','./msxsdtest/attribute',valid),
+ STResList129 = [STRes128|STResList128],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attLa001.xml','./msxsdtest/attribute',valid,S128),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes129,S129} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attLa002.xsd','./msxsdtest/attribute',valid),
+ STResList130 = [STRes129|STResList129],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attLa002.xml','./msxsdtest/attribute',valid,S129),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes130,S130} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attLa003.xsd','./msxsdtest/attribute',valid),
+ STResList131 = [STRes130|STResList130],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attLa003.xml','./msxsdtest/attribute',valid,S130),
+ ITResList22 = [ITRes21|ITResList21],
+
+
+ ?line {STRes131,S131} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attLa004.xsd','./msxsdtest/attribute',valid),
+ STResList132 = [STRes131|STResList131],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attLa004.xml','./msxsdtest/attribute',valid,S131),
+ ITResList23 = [ITRes22|ITResList22],
+
+
+ ?line {STRes132,S132} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attLa005.xsd','./msxsdtest/attribute',valid),
+ STResList133 = [STRes132|STResList132],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attLa005.xml','./msxsdtest/attribute',invalid,S132),
+ ITResList24 = [ITRes23|ITResList23],
+
+
+ ?line {STRes133,S133} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attLa006.xsd','./msxsdtest/attribute',valid),
+ STResList134 = [STRes133|STResList133],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attLa006.xml','./msxsdtest/attribute',valid,S133),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes134,S134} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attLb001.xsd','./msxsdtest/attribute',valid),
+ STResList135 = [STRes134|STResList134],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attLb001.xml','./msxsdtest/attribute',valid,S134),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes135,S135} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attLb002.xsd','./msxsdtest/attribute',valid),
+ STResList136 = [STRes135|STResList135],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attLb002.xml','./msxsdtest/attribute',valid,S135),
+ ITResList27 = [ITRes26|ITResList26],
+
+
+ ?line {STRes136,S136} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attLb003.xsd','./msxsdtest/attribute',valid),
+ STResList137 = [STRes136|STResList136],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attLb003.xml','./msxsdtest/attribute',valid,S136),
+ ITResList28 = [ITRes27|ITResList27],
+
+
+ ?line {STRes137,S137} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attLb004.xsd','./msxsdtest/attribute',valid),
+ STResList138 = [STRes137|STResList137],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attLb004.xml','./msxsdtest/attribute',valid,S137),
+ ITResList29 = [ITRes28|ITResList28],
+
+
+ ?line {STRes138,S138} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attLb005.xsd','./msxsdtest/attribute',valid),
+ STResList139 = [STRes138|STResList138],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attLb005.xml','./msxsdtest/attribute',invalid,S138),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes139,S139} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attLb006.xsd','./msxsdtest/attribute',valid),
+ STResList140 = [STRes139|STResList139],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attLb006.xml','./msxsdtest/attribute',valid,S139),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes140,S140} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attLc001.xsd','./msxsdtest/attribute',valid),
+ STResList141 = [STRes140|STResList140],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attLc001.xml','./msxsdtest/attribute',valid,S140),
+ ITResList32 = [ITRes31|ITResList31],
+
+
+ ?line {STRes141,S141} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attLc002.xsd','./msxsdtest/attribute',valid),
+ STResList142 = [STRes141|STResList141],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attLc002.xml','./msxsdtest/attribute',valid,S141),
+ ITResList33 = [ITRes32|ITResList32],
+
+
+ ?line {STRes142,S142} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attLc003.xsd','./msxsdtest/attribute',valid),
+ STResList143 = [STRes142|STResList142],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attLc003.xml','./msxsdtest/attribute',valid,S142),
+ ITResList34 = [ITRes33|ITResList33],
+
+
+ ?line {STRes143,S143} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attLc004.xsd','./msxsdtest/attribute',valid),
+ STResList144 = [STRes143|STResList143],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attLc004.xml','./msxsdtest/attribute',valid,S143),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes144,S144} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attLc005.xsd','./msxsdtest/attribute',valid),
+ STResList145 = [STRes144|STResList144],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attLc005.xml','./msxsdtest/attribute',invalid,S144),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes145,S145} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attLc006.xsd','./msxsdtest/attribute',valid),
+ STResList146 = [STRes145|STResList145],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attLc006.xml','./msxsdtest/attribute',valid,S145),
+ ITResList37 = [ITRes36|ITResList36],
+
+
+ ?line {STRes146,S146} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMa001.xsd','./msxsdtest/attribute',valid),
+ STResList147 = [STRes146|STResList146],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMa001.xml','./msxsdtest/attribute',invalid,S146),
+ ITResList38 = [ITRes37|ITResList37],
+
+
+ ?line {STRes147,S147} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMa002.xsd','./msxsdtest/attribute',valid),
+ STResList148 = [STRes147|STResList147],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMa002.xml','./msxsdtest/attribute',invalid,S147),
+ ITResList39 = [ITRes38|ITResList38],
+
+
+ ?line {STRes148,S148} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMa003.xsd','./msxsdtest/attribute',valid),
+ STResList149 = [STRes148|STResList148],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMa003.xml','./msxsdtest/attribute',valid,S148),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes149,S149} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMa004.xsd','./msxsdtest/attribute',valid),
+ STResList150 = [STRes149|STResList149],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMa004.xml','./msxsdtest/attribute',valid,S149),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes150,S150} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMb001.xsd','./msxsdtest/attribute',valid),
+ STResList151 = [STRes150|STResList150],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMb001.xml','./msxsdtest/attribute',invalid,S150),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes151,S151} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMb002.xsd','./msxsdtest/attribute',valid),
+ STResList152 = [STRes151|STResList151],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMb002.xml','./msxsdtest/attribute',invalid,S151),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes152,S152} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMb003.xsd','./msxsdtest/attribute',valid),
+ STResList153 = [STRes152|STResList152],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMb003.xml','./msxsdtest/attribute',invalid,S152),
+ ITResList44 = [ITRes43|ITResList43],
+
+
+ ?line {STRes153,S153} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMb004.xsd','./msxsdtest/attribute',valid),
+ STResList154 = [STRes153|STResList153],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMb004.xml','./msxsdtest/attribute',valid,S153),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes154,S154} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMb005.xsd','./msxsdtest/attribute',valid),
+ STResList155 = [STRes154|STResList154],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMb005.xml','./msxsdtest/attribute',valid,S154),
+ ITResList46 = [ITRes45|ITResList45],
+
+
+ ?line {STRes155,S155} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMb006.xsd','./msxsdtest/attribute',valid),
+ STResList156 = [STRes155|STResList155],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMb006.xml','./msxsdtest/attribute',valid,S155),
+ ITResList47 = [ITRes46|ITResList46],
+
+
+ ?line {STRes156,S156} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMb007.xsd','./msxsdtest/attribute',valid),
+ STResList157 = [STRes156|STResList156],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMb007.xml','./msxsdtest/attribute',valid,S156),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes157,S157} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMb008.xsd','./msxsdtest/attribute',valid),
+ STResList158 = [STRes157|STResList157],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMb008.xml','./msxsdtest/attribute',valid,S157),
+ ITResList49 = [ITRes48|ITResList48],
+
+
+ ?line {STRes158,S158} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMb009.xsd','./msxsdtest/attribute',valid),
+ STResList159 = [STRes158|STResList158],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMb009.xml','./msxsdtest/attribute',valid,S158),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes159,S159} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMb010.xsd','./msxsdtest/attribute',valid),
+ STResList160 = [STRes159|STResList159],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMb010.xml','./msxsdtest/attribute',invalid,S159),
+ ITResList51 = [ITRes50|ITResList50],
+
+
+ ?line {STRes160,S160} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMb011.xsd','./msxsdtest/attribute',valid),
+ STResList161 = [STRes160|STResList160],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMb011.xml','./msxsdtest/attribute',invalid,S160),
+ ITResList52 = [ITRes51|ITResList51],
+
+
+ ?line {STRes161,S161} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMb012.xsd','./msxsdtest/attribute',valid),
+ STResList162 = [STRes161|STResList161],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMb012.xml','./msxsdtest/attribute',invalid,S161),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes162,S162} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMc001.xsd','./msxsdtest/attribute',valid),
+ STResList163 = [STRes162|STResList162],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMc001.xml','./msxsdtest/attribute',invalid,S162),
+ ITResList54 = [ITRes53|ITResList53],
+
+
+ ?line {STRes163,S163} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMc002.xsd','./msxsdtest/attribute',valid),
+ STResList164 = [STRes163|STResList163],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMc002.xml','./msxsdtest/attribute',invalid,S163),
+ ITResList55 = [ITRes54|ITResList54],
+
+
+ ?line {STRes164,S164} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMc003.xsd','./msxsdtest/attribute',valid),
+ STResList165 = [STRes164|STResList164],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMc003.xml','./msxsdtest/attribute',invalid,S164),
+ ITResList56 = [ITRes55|ITResList55],
+
+
+ ?line {STRes165,S165} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMc004.xsd','./msxsdtest/attribute',valid),
+ STResList166 = [STRes165|STResList165],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMc004.xml','./msxsdtest/attribute',valid,S165),
+ ITResList57 = [ITRes56|ITResList56],
+
+
+ ?line {STRes166,S166} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMc005.xsd','./msxsdtest/attribute',valid),
+ STResList167 = [STRes166|STResList166],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMc005.xml','./msxsdtest/attribute',valid,S166),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes167,S167} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMc006.xsd','./msxsdtest/attribute',valid),
+ STResList168 = [STRes167|STResList167],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMc006.xml','./msxsdtest/attribute',valid,S167),
+ ITResList59 = [ITRes58|ITResList58],
+
+
+ ?line {STRes168,S168} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMc007.xsd','./msxsdtest/attribute',valid),
+ STResList169 = [STRes168|STResList168],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMc007.xml','./msxsdtest/attribute',valid,S168),
+ ITResList60 = [ITRes59|ITResList59],
+
+
+ ?line {STRes169,S169} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMc008.xsd','./msxsdtest/attribute',valid),
+ STResList170 = [STRes169|STResList169],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMc008.xml','./msxsdtest/attribute',valid,S169),
+ ITResList61 = [ITRes60|ITResList60],
+
+
+ ?line {STRes170,S170} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMc009.xsd','./msxsdtest/attribute',valid),
+ STResList171 = [STRes170|STResList170],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMc009.xml','./msxsdtest/attribute',valid,S170),
+ ITResList62 = [ITRes61|ITResList61],
+
+
+ ?line {STRes171,S171} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMc010.xsd','./msxsdtest/attribute',valid),
+ STResList172 = [STRes171|STResList171],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMc010.xml','./msxsdtest/attribute',invalid,S171),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes172,S172} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMc011.xsd','./msxsdtest/attribute',valid),
+ STResList173 = [STRes172|STResList172],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMc011.xml','./msxsdtest/attribute',invalid,S172),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes173,S173} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attMc012.xsd','./msxsdtest/attribute',valid),
+ STResList174 = [STRes173|STResList173],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attMc012.xml','./msxsdtest/attribute',invalid,S173),
+ ITResList65 = [ITRes64|ITResList64],
+
+
+ ?line {STRes174,S174} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO001.xsd','./msxsdtest/attribute',valid),
+ STResList175 = [STRes174|STResList174],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attO001.xml','./msxsdtest/attribute',invalid,S174),
+ ITResList66 = [ITRes65|ITResList65],
+
+
+ ?line {STRes175,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO002.xsd','./msxsdtest/attribute',invalid),
+ STResList176 = [STRes175|STResList175],
+
+
+ ?line {STRes176,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO003.xsd','./msxsdtest/attribute',invalid),
+ STResList177 = [STRes176|STResList176],
+
+
+ ?line {STRes177,S177} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO004.xsd','./msxsdtest/attribute',valid),
+ STResList178 = [STRes177|STResList177],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attO004.xml','./msxsdtest/attribute',invalid,S177),
+ ITResList67 = [ITRes66|ITResList66],
+
+
+ ?line {STRes178,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO005.xsd','./msxsdtest/attribute',invalid),
+ STResList179 = [STRes178|STResList178],
+
+
+ ?line {STRes179,S179} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO006.xsd','./msxsdtest/attribute',valid),
+ STResList180 = [STRes179|STResList179],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attO006.xml','./msxsdtest/attribute',valid,S179),
+ ITResList68 = [ITRes67|ITResList67],
+
+
+ ?line {STRes180,S180} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO007.xsd','./msxsdtest/attribute',valid),
+ STResList181 = [STRes180|STResList180],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attO007.xml','./msxsdtest/attribute',valid,S180),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes181,S181} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO008.xsd','./msxsdtest/attribute',valid),
+ STResList182 = [STRes181|STResList181],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attO008.xml','./msxsdtest/attribute',invalid,S181),
+ ITResList70 = [ITRes69|ITResList69],
+
+
+ ?line {STRes182,S182} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO009.xsd','./msxsdtest/attribute',valid),
+ STResList183 = [STRes182|STResList182],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attO009.xml','./msxsdtest/attribute',valid,S182),
+ ITResList71 = [ITRes70|ITResList70],
+
+
+ ?line {STRes183,S183} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO010.xsd','./msxsdtest/attribute',valid),
+ STResList184 = [STRes183|STResList183],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attO010.xml','./msxsdtest/attribute',valid,S183),
+ ITResList72 = [ITRes71|ITResList71],
+
+
+ ?line {STRes184,S184} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO011.xsd','./msxsdtest/attribute',valid),
+ STResList185 = [STRes184|STResList184],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attO011.xml','./msxsdtest/attribute',valid,S184),
+ ITResList73 = [ITRes72|ITResList72],
+
+
+ ?line {STRes185,S185} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO012.xsd','./msxsdtest/attribute',valid),
+ STResList186 = [STRes185|STResList185],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attO012.xml','./msxsdtest/attribute',invalid,S185),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes186,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO013.xsd','./msxsdtest/attribute',invalid),
+ STResList187 = [STRes186|STResList186],
+
+
+ ?line {STRes187,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO014.xsd','./msxsdtest/attribute',invalid),
+ STResList188 = [STRes187|STResList187],
+
+
+ ?line {STRes188,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO015.xsd','./msxsdtest/attribute',invalid),
+ STResList189 = [STRes188|STResList188],
+
+
+ ?line {STRes189,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO016.xsd','./msxsdtest/attribute',invalid),
+ STResList190 = [STRes189|STResList189],
+
+
+ ?line {STRes190,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO017.xsd','./msxsdtest/attribute',invalid),
+ STResList191 = [STRes190|STResList190],
+
+
+ ?line {STRes191,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO018.xsd','./msxsdtest/attribute',valid),
+ STResList192 = [STRes191|STResList191],
+
+
+ ?line {STRes192,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO019.xsd','./msxsdtest/attribute',invalid),
+ STResList193 = [STRes192|STResList192],
+
+
+ ?line {STRes193,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO020.xsd','./msxsdtest/attribute',invalid),
+ STResList194 = [STRes193|STResList193],
+
+
+ ?line {STRes194,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO021.xsd','./msxsdtest/attribute',invalid),
+ STResList195 = [STRes194|STResList194],
+
+
+ ?line {STRes195,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO022.xsd','./msxsdtest/attribute',invalid),
+ STResList196 = [STRes195|STResList195],
+
+
+ ?line {STRes196,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO023.xsd','./msxsdtest/attribute',invalid),
+ STResList197 = [STRes196|STResList196],
+
+
+ ?line {STRes197,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO024.xsd','./msxsdtest/attribute',invalid),
+ STResList198 = [STRes197|STResList197],
+
+
+ ?line {STRes198,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attO025.xsd','./msxsdtest/attribute',valid),
+ STResList199 = [STRes198|STResList198],
+
+
+ ?line {STRes199,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP001.xsd','./msxsdtest/attribute',invalid),
+ STResList200 = [STRes199|STResList199],
+
+
+ ?line {STRes200,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP002.xsd','./msxsdtest/attribute',invalid),
+ STResList201 = [STRes200|STResList200],
+
+
+ ?line {STRes201,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP003.xsd','./msxsdtest/attribute',invalid),
+ STResList202 = [STRes201|STResList201],
+
+
+ ?line {STRes202,S202} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP004.xsd','./msxsdtest/attribute',valid),
+ STResList203 = [STRes202|STResList202],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP004.xml','./msxsdtest/attribute',valid,S202),
+ ITResList75 = [ITRes74|ITResList74],
+
+
+ ?line {STRes203,S203} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP005.xsd','./msxsdtest/attribute',valid),
+ STResList204 = [STRes203|STResList203],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP005.xml','./msxsdtest/attribute',invalid,S203),
+ ITResList76 = [ITRes75|ITResList75],
+
+
+ ?line {STRes204,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP006.xsd','./msxsdtest/attribute',invalid),
+ STResList205 = [STRes204|STResList204],
+
+
+ ?line {STRes205,S205} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP007.xsd','./msxsdtest/attribute',valid),
+ STResList206 = [STRes205|STResList205],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP007.xml','./msxsdtest/attribute',valid,S205),
+ ITResList77 = [ITRes76|ITResList76],
+
+
+ ?line {STRes206,S206} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP008.xsd','./msxsdtest/attribute',valid),
+ STResList207 = [STRes206|STResList206],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP008.xml','./msxsdtest/attribute',invalid,S206),
+ ITResList78 = [ITRes77|ITResList77],
+
+
+ ?line {STRes207,S207} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP009.xsd','./msxsdtest/attribute',valid),
+ STResList208 = [STRes207|STResList207],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP009.xml','./msxsdtest/attribute',valid,S207),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes208,S208} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP010.xsd','./msxsdtest/attribute',valid),
+ STResList209 = [STRes208|STResList208],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP010.xml','./msxsdtest/attribute',invalid,S208),
+ ITResList80 = [ITRes79|ITResList79],
+
+
+ ?line {STRes209,S209} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP011.xsd','./msxsdtest/attribute',valid),
+ STResList210 = [STRes209|STResList209],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP011.xml','./msxsdtest/attribute',valid,S209),
+ ITResList81 = [ITRes80|ITResList80],
+
+
+ ?line {STRes210,S210} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP012.xsd','./msxsdtest/attribute',valid),
+ STResList211 = [STRes210|STResList210],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP012.xml','./msxsdtest/attribute',invalid,S210),
+ ITResList82 = [ITRes81|ITResList81],
+
+
+ ?line {STRes211,S211} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP013.xsd','./msxsdtest/attribute',valid),
+ STResList212 = [STRes211|STResList211],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP013.xml','./msxsdtest/attribute',valid,S211),
+ ITResList83 = [ITRes82|ITResList82],
+
+
+ ?line {STRes212,S212} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP014.xsd','./msxsdtest/attribute',valid),
+ STResList213 = [STRes212|STResList212],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP014.xml','./msxsdtest/attribute',invalid,S212),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes213,S213} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP015.xsd','./msxsdtest/attribute',valid),
+ STResList214 = [STRes213|STResList213],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP015.xml','./msxsdtest/attribute',valid,S213),
+ ITResList85 = [ITRes84|ITResList84],
+
+
+ ?line {STRes214,S214} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP016.xsd','./msxsdtest/attribute',valid),
+ STResList215 = [STRes214|STResList214],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP016.xml','./msxsdtest/attribute',invalid,S214),
+ ITResList86 = [ITRes85|ITResList85],
+
+
+ ?line {STRes215,S215} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP017.xsd','./msxsdtest/attribute',valid),
+ STResList216 = [STRes215|STResList215],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP017.xml','./msxsdtest/attribute',valid,S215),
+ ITResList87 = [ITRes86|ITResList86],
+
+
+ ?line {STRes216,S216} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP018.xsd','./msxsdtest/attribute',valid),
+ STResList217 = [STRes216|STResList216],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP018.xml','./msxsdtest/attribute',invalid,S216),
+ ITResList88 = [ITRes87|ITResList87],
+
+
+ ?line {STRes217,S217} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP019.xsd','./msxsdtest/attribute',valid),
+ STResList218 = [STRes217|STResList217],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP019.xml','./msxsdtest/attribute',valid,S217),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes218,S218} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP020.xsd','./msxsdtest/attribute',valid),
+ STResList219 = [STRes218|STResList218],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP020.xml','./msxsdtest/attribute',invalid,S218),
+ ITResList90 = [ITRes89|ITResList89],
+
+
+ ?line {STRes219,S219} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP021.xsd','./msxsdtest/attribute',valid),
+ STResList220 = [STRes219|STResList219],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP021.xml','./msxsdtest/attribute',valid,S219),
+ ITResList91 = [ITRes90|ITResList90],
+
+
+ ?line {STRes220,S220} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP022.xsd','./msxsdtest/attribute',valid),
+ STResList221 = [STRes220|STResList220],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP022.xml','./msxsdtest/attribute',valid,S220),
+ ITResList92 = [ITRes91|ITResList91],
+
+
+ ?line {STRes221,S221} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP023.xsd','./msxsdtest/attribute',valid),
+ STResList222 = [STRes221|STResList221],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP023.xml','./msxsdtest/attribute',valid,S221),
+ ITResList93 = [ITRes92|ITResList92],
+
+
+ ?line {STRes222,S222} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP024.xsd','./msxsdtest/attribute',valid),
+ STResList223 = [STRes222|STResList222],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP024.xml','./msxsdtest/attribute',valid,S222),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes223,S223} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP025.xsd','./msxsdtest/attribute',valid),
+ STResList224 = [STRes223|STResList223],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP025.xml','./msxsdtest/attribute',valid,S223),
+ ITResList95 = [ITRes94|ITResList94],
+
+
+ ?line {STRes224,S224} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP026.xsd','./msxsdtest/attribute',valid),
+ STResList225 = [STRes224|STResList224],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP026.xml','./msxsdtest/attribute',valid,S224),
+ ITResList96 = [ITRes95|ITResList95],
+
+
+ ?line {STRes225,S225} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP027.xsd','./msxsdtest/attribute',valid),
+ STResList226 = [STRes225|STResList225],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP027.xml','./msxsdtest/attribute',invalid,S225),
+ ITResList97 = [ITRes96|ITResList96],
+
+
+ ?line {STRes226,S226} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP028.xsd','./msxsdtest/attribute',valid),
+ STResList227 = [STRes226|STResList226],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP028.xml','./msxsdtest/attribute',valid,S226),
+ ITResList98 = [ITRes97|ITResList97],
+
+
+ ?line {STRes227,S227} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP029.xsd','./msxsdtest/attribute',valid),
+ STResList228 = [STRes227|STResList227],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP029.xml','./msxsdtest/attribute',valid,S227),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes228,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP030.xsd','./msxsdtest/attribute',invalid),
+ STResList229 = [STRes228|STResList228],
+
+
+ ?line {STRes229,S229} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP031.xsd','./msxsdtest/attribute',valid),
+ STResList230 = [STRes229|STResList229],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP031.xml','./msxsdtest/attribute',invalid,S229),
+ ITResList100 = [ITRes99|ITResList99],
+
+
+ ?line {STRes230,S230} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attP032.xsd','./msxsdtest/attribute',valid),
+ STResList231 = [STRes230|STResList230],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attP032.xml','./msxsdtest/attribute',valid,S230),
+ ITResList101 = [ITRes100|ITResList100],
+
+
+ ?line {STRes231,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attQ001.xsd','./msxsdtest/attribute',invalid),
+ STResList232 = [STRes231|STResList231],
+
+
+ ?line {STRes232,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attQ002.xsd','./msxsdtest/attribute',invalid),
+ STResList233 = [STRes232|STResList232],
+
+
+ ?line {STRes233,S233} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attQ003.xsd','./msxsdtest/attribute',valid),
+ STResList234 = [STRes233|STResList233],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attQ003.xml','./msxsdtest/attribute',valid,S233),
+ ITResList102 = [ITRes101|ITResList101],
+
+
+ ?line {STRes234,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attQ004.xsd','./msxsdtest/attribute',invalid),
+ STResList235 = [STRes234|STResList234],
+
+
+ ?line {STRes235,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attQ005.xsd','./msxsdtest/attribute',invalid),
+ STResList236 = [STRes235|STResList235],
+
+
+ ?line {STRes236,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attQ006.xsd','./msxsdtest/attribute',invalid),
+ STResList237 = [STRes236|STResList236],
+
+
+ ?line {STRes237,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attQ007.xsd','./msxsdtest/attribute',invalid),
+ STResList238 = [STRes237|STResList237],
+
+
+ ?line {STRes238,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attQ008.xsd','./msxsdtest/attribute',invalid),
+ STResList239 = [STRes238|STResList238],
+
+
+ ?line {STRes239,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attQ009.xsd','./msxsdtest/attribute',invalid),
+ STResList240 = [STRes239|STResList239],
+
+
+ ?line {STRes240,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attQ010.xsd','./msxsdtest/attribute',valid),
+ STResList241 = [STRes240|STResList240],
+
+
+ ?line {STRes241,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attQ011.xsd','./msxsdtest/attribute',invalid),
+ STResList242 = [STRes241|STResList241],
+
+
+ ?line {STRes242,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attQ012.xsd','./msxsdtest/attribute',invalid),
+ STResList243 = [STRes242|STResList242],
+
+
+ ?line {STRes243,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attQ013.xsd','./msxsdtest/attribute',invalid),
+ STResList244 = [STRes243|STResList243],
+
+
+ ?line {STRes244,S244} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attQ014.xsd','./msxsdtest/attribute',valid),
+ STResList245 = [STRes244|STResList244],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attQ014.xml','./msxsdtest/attribute',valid,S244),
+ ITResList103 = [ITRes102|ITResList102],
+
+
+ ?line {STRes245,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attQ015.xsd','./msxsdtest/attribute',invalid),
+ STResList246 = [STRes245|STResList245],
+
+
+ ?line {STRes246,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attQ016.xsd','./msxsdtest/attribute',invalid),
+ STResList247 = [STRes246|STResList246],
+
+
+ ?line {STRes247,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attQ017.xsd','./msxsdtest/attribute',invalid),
+ STResList248 = [STRes247|STResList247],
+
+
+ ?line {STRes248,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attQ018.xsd','./msxsdtest/attribute',invalid),
+ STResList249 = [STRes248|STResList248],
+
+
+ ?line {STRes249,S249} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attQ019.xsd','./msxsdtest/attribute',valid),
+ STResList250 = [STRes249|STResList249],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attQ019.xml','./msxsdtest/attribute',valid,S249),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes250,S250} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attZ001.xsd','./msxsdtest/attribute',valid),
+ STResList251 = [STRes250|STResList250],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attZ001.xml','./msxsdtest/attribute',invalid,S250),
+ ITResList105 = [ITRes104|ITResList104],
+
+
+ ?line {STRes251,S251} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attZ002.xsd','./msxsdtest/attribute',valid),
+ STResList252 = [STRes251|STResList251],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attZ002.xml','./msxsdtest/attribute',invalid,S251),
+ ITResList106 = [ITRes105|ITResList105],
+
+
+ ?line {STRes252,S252} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attribute/attZ003.xsd','./msxsdtest/attribute',valid),
+ STResList253 = [STRes252|STResList252],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attribute/attZ003.xml','./msxsdtest/attribute',invalid,S252),
+ ITResList107 = [ITRes106|ITResList106],
+
+
+ ?line {STRes253,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgA001.xsd','./msxsdtest/attributeGroup',valid),
+ STResList254 = [STRes253|STResList253],
+
+
+ ?line {STRes254,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgA002.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList255 = [STRes254|STResList254],
+
+
+ ?line {STRes255,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgA003.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList256 = [STRes255|STResList255],
+
+
+ ?line {STRes256,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgA004.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList257 = [STRes256|STResList256],
+
+
+ ?line {STRes257,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgA005.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList258 = [STRes257|STResList257],
+
+
+ ?line {STRes258,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgA006.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList259 = [STRes258|STResList258],
+
+
+ ?line {STRes259,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgA007.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList260 = [STRes259|STResList259],
+
+
+ ?line {STRes260,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgA008.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList261 = [STRes260|STResList260],
+
+
+ ?line {STRes261,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgA009.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList262 = [STRes261|STResList261],
+
+
+ ?line {STRes262,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgB001.xsd','./msxsdtest/attributeGroup',valid),
+ STResList263 = [STRes262|STResList262],
+
+
+ ?line {STRes263,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgB002.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList264 = [STRes263|STResList263],
+
+
+ ?line {STRes264,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgB003.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList265 = [STRes264|STResList264],
+
+
+ ?line {STRes265,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgB004.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList266 = [STRes265|STResList265],
+
+
+ ?line {STRes266,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgB005.xsd','./msxsdtest/attributeGroup',valid),
+ STResList267 = [STRes266|STResList266],
+
+
+ ?line {STRes267,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgB006.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList268 = [STRes267|STResList267],
+
+
+ ?line {STRes268,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgB007.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList269 = [STRes268|STResList268],
+
+
+ ?line {STRes269,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgB008.xsd','./msxsdtest/attributeGroup',valid),
+ STResList270 = [STRes269|STResList269],
+
+
+ ?line {STRes270,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgB009.xsd','./msxsdtest/attributeGroup',valid),
+ STResList271 = [STRes270|STResList270],
+
+
+ ?line {STRes271,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgB010.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList272 = [STRes271|STResList271],
+
+
+ ?line {STRes272,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgB011.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList273 = [STRes272|STResList272],
+
+
+ ?line {STRes273,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgB012.xsd','./msxsdtest/attributeGroup',valid),
+ STResList274 = [STRes273|STResList273],
+
+
+ ?line {STRes274,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgB013.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList275 = [STRes274|STResList274],
+
+
+ ?line {STRes275,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgB014.xsd','./msxsdtest/attributeGroup',valid),
+ STResList276 = [STRes275|STResList275],
+
+
+ ?line {STRes276,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgB015.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList277 = [STRes276|STResList276],
+
+
+ ?line {STRes277,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC001.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList278 = [STRes277|STResList277],
+
+
+ ?line {STRes278,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC002.xsd','./msxsdtest/attributeGroup',valid),
+ STResList279 = [STRes278|STResList278],
+
+
+ ?line {STRes279,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC003.xsd','./msxsdtest/attributeGroup',valid),
+ STResList280 = [STRes279|STResList279],
+
+
+ ?line {STRes280,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC004.xsd','./msxsdtest/attributeGroup',valid),
+ STResList281 = [STRes280|STResList280],
+
+
+ ?line {STRes281,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC005.xsd','./msxsdtest/attributeGroup',valid),
+ STResList282 = [STRes281|STResList281],
+
+
+ ?line {STRes282,S282} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC006.xsd','./msxsdtest/attributeGroup',valid),
+ STResList283 = [STRes282|STResList282],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgC006.xml','./msxsdtest/attributeGroup',invalid,S282),
+ ITResList108 = [ITRes107|ITResList107],
+
+
+ ?line {STRes283,S283} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC007.xsd','./msxsdtest/attributeGroup',valid),
+ STResList284 = [STRes283|STResList283],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgC007.xml','./msxsdtest/attributeGroup',valid,S283),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes284,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC008.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList285 = [STRes284|STResList284],
+
+
+ ?line {STRes285,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC009.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList286 = [STRes285|STResList285],
+
+
+ ?line {STRes286,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC010.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList287 = [STRes286|STResList286],
+
+
+ ?line {STRes287,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC011.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList288 = [STRes287|STResList287],
+
+
+ ?line {STRes288,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC012.xsd','./msxsdtest/attributeGroup',valid),
+ STResList289 = [STRes288|STResList288],
+
+
+ ?line {STRes289,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC013.xsd','./msxsdtest/attributeGroup',valid),
+ STResList290 = [STRes289|STResList289],
+
+
+ ?line {STRes290,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC014.xsd','./msxsdtest/attributeGroup',valid),
+ STResList291 = [STRes290|STResList290],
+
+
+ ?line {STRes291,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC015.xsd','./msxsdtest/attributeGroup',valid),
+ STResList292 = [STRes291|STResList291],
+
+
+ ?line {STRes292,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC016.xsd','./msxsdtest/attributeGroup',valid),
+ STResList293 = [STRes292|STResList292],
+
+
+ ?line {STRes293,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC017.xsd','./msxsdtest/attributeGroup',valid),
+ STResList294 = [STRes293|STResList293],
+
+
+ ?line {STRes294,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC018.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList295 = [STRes294|STResList294],
+
+
+ ?line {STRes295,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC019.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList296 = [STRes295|STResList295],
+
+
+ ?line {STRes296,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC020.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList297 = [STRes296|STResList296],
+
+
+ ?line {STRes297,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC021.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList298 = [STRes297|STResList297],
+
+
+ ?line {STRes298,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC022.xsd','./msxsdtest/attributeGroup',valid),
+ STResList299 = [STRes298|STResList298],
+
+
+ ?line {STRes299,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC023.xsd','./msxsdtest/attributeGroup',valid),
+ STResList300 = [STRes299|STResList299],
+
+
+ ?line {STRes300,S300} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC024.xsd','./msxsdtest/attributeGroup',valid),
+ STResList301 = [STRes300|STResList300],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgC024.xml','./msxsdtest/attributeGroup',valid,S300),
+ ITResList110 = [ITRes109|ITResList109],
+
+
+ ?line {STRes301,S301} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC025.xsd','./msxsdtest/attributeGroup',valid),
+ STResList302 = [STRes301|STResList301],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgC025.xml','./msxsdtest/attributeGroup',invalid,S301),
+ ITResList111 = [ITRes110|ITResList110],
+
+
+ ?line {STRes302,S302} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC026.xsd','./msxsdtest/attributeGroup',valid),
+ STResList303 = [STRes302|STResList302],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgC026.xml','./msxsdtest/attributeGroup',valid,S302),
+ ITResList112 = [ITRes111|ITResList111],
+
+
+ ?line {STRes303,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC027.xsd','./msxsdtest/attributeGroup',valid),
+ STResList304 = [STRes303|STResList303],
+
+
+ ?line {STRes304,S304} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC028.xsd','./msxsdtest/attributeGroup',valid),
+ STResList305 = [STRes304|STResList304],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgC028.xml','./msxsdtest/attributeGroup',invalid,S304),
+ ITResList113 = [ITRes112|ITResList112],
+
+
+ ?line {STRes305,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC029.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList306 = [STRes305|STResList305],
+
+
+ ?line {STRes306,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC030.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList307 = [STRes306|STResList306],
+
+
+ ?line {STRes307,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC031.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList308 = [STRes307|STResList307],
+
+
+ ?line {STRes308,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC032.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList309 = [STRes308|STResList308],
+
+
+ ?line {STRes309,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC033.xsd','./msxsdtest/attributeGroup',valid),
+ STResList310 = [STRes309|STResList309],
+
+
+ ?line {STRes310,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC034.xsd','./msxsdtest/attributeGroup',valid),
+ STResList311 = [STRes310|STResList310],
+
+
+ ?line {STRes311,S311} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC035.xsd','./msxsdtest/attributeGroup',valid),
+ STResList312 = [STRes311|STResList311],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgC035.xml','./msxsdtest/attributeGroup',valid,S311),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes312,S312} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC036.xsd','./msxsdtest/attributeGroup',valid),
+ STResList313 = [STRes312|STResList312],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgC036.xml','./msxsdtest/attributeGroup',valid,S312),
+ ITResList115 = [ITRes114|ITResList114],
+
+
+ ?line {STRes313,S313} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC037.xsd','./msxsdtest/attributeGroup',valid),
+ STResList314 = [STRes313|STResList313],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgC037.xml','./msxsdtest/attributeGroup',valid,S313),
+ ITResList116 = [ITRes115|ITResList115],
+
+
+ ?line {STRes314,S314} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC038.xsd','./msxsdtest/attributeGroup',valid),
+ STResList315 = [STRes314|STResList314],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgC038.xml','./msxsdtest/attributeGroup',valid,S314),
+ ITResList117 = [ITRes116|ITResList116],
+
+
+ ?line {STRes315,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC039.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList316 = [STRes315|STResList315],
+
+
+ ?line {STRes316,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC040.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList317 = [STRes316|STResList316],
+
+
+ ?line {STRes317,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC041.xsd','./msxsdtest/attributeGroup',valid),
+ STResList318 = [STRes317|STResList317],
+
+
+ ?line {STRes318,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC042.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList319 = [STRes318|STResList318],
+
+
+ ?line {STRes319,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC043.xsd','./msxsdtest/attributeGroup',valid),
+ STResList320 = [STRes319|STResList319],
+
+
+ ?line {STRes320,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC044.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList321 = [STRes320|STResList320],
+
+
+ ?line {STRes321,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgC045.xsd','./msxsdtest/attributeGroup',valid),
+ STResList322 = [STRes321|STResList321],
+
+
+ ?line {STRes322,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD001.xsd','./msxsdtest/attributeGroup',valid),
+ STResList323 = [STRes322|STResList322],
+
+
+ ?line {STRes323,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD002.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList324 = [STRes323|STResList323],
+
+
+ ?line {STRes324,S324} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD003.xsd','./msxsdtest/attributeGroup',valid),
+ STResList325 = [STRes324|STResList324],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD003.xml','./msxsdtest/attributeGroup',valid,S324),
+ ITResList118 = [ITRes117|ITResList117],
+
+
+ ?line {STRes325,S325} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD004.xsd','./msxsdtest/attributeGroup',valid),
+ STResList326 = [STRes325|STResList325],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD004.xml','./msxsdtest/attributeGroup',valid,S325),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes326,S326} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD005.xsd','./msxsdtest/attributeGroup',valid),
+ STResList327 = [STRes326|STResList326],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD005.xml','./msxsdtest/attributeGroup',valid,S326),
+ ITResList120 = [ITRes119|ITResList119],
+
+
+ ?line {STRes327,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD006.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList328 = [STRes327|STResList327],
+
+
+ ?line {STRes328,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD007.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList329 = [STRes328|STResList328],
+
+
+ ?line {STRes329,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD008.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList330 = [STRes329|STResList329],
+
+
+ ?line {STRes330,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD009.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList331 = [STRes330|STResList330],
+
+
+ ?line {STRes331,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD010.xsd','./msxsdtest/attributeGroup',valid),
+ STResList332 = [STRes331|STResList331],
+
+
+ ?line {STRes332,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD011.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList333 = [STRes332|STResList332],
+
+
+ ?line {STRes333,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD012.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList334 = [STRes333|STResList333],
+
+
+ ?line {STRes334,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD013.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList335 = [STRes334|STResList334],
+
+
+ ?line {STRes335,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD014.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList336 = [STRes335|STResList335],
+
+
+ ?line {STRes336,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD015.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList337 = [STRes336|STResList336],
+
+
+ ?line {STRes337,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD016.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList338 = [STRes337|STResList337],
+
+
+ ?line {STRes338,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD017.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList339 = [STRes338|STResList338],
+
+
+ ?line {STRes339,S339} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD018.xsd','./msxsdtest/attributeGroup',valid),
+ STResList340 = [STRes339|STResList339],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD018.xml','./msxsdtest/attributeGroup',valid,S339),
+ ITResList121 = [ITRes120|ITResList120],
+
+
+ ?line {STRes340,S340} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD019.xsd','./msxsdtest/attributeGroup',valid),
+ STResList341 = [STRes340|STResList340],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD019.xml','./msxsdtest/attributeGroup',valid,S340),
+ ITResList122 = [ITRes121|ITResList121],
+
+
+ ?line {STRes341,S341} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD020.xsd','./msxsdtest/attributeGroup',valid),
+ STResList342 = [STRes341|STResList341],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD020.xml','./msxsdtest/attributeGroup',valid,S341),
+ ITResList123 = [ITRes122|ITResList122],
+
+
+ ?line {STRes342,S342} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD021.xsd','./msxsdtest/attributeGroup',valid),
+ STResList343 = [STRes342|STResList342],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD021.xml','./msxsdtest/attributeGroup',valid,S342),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes343,S343} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD022.xsd','./msxsdtest/attributeGroup',valid),
+ STResList344 = [STRes343|STResList343],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD022.xml','./msxsdtest/attributeGroup',valid,S343),
+ ITResList125 = [ITRes124|ITResList124],
+
+
+ ?line {STRes344,S344} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD023.xsd','./msxsdtest/attributeGroup',valid),
+ STResList345 = [STRes344|STResList344],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD023.xml','./msxsdtest/attributeGroup',invalid,S344),
+ ITResList126 = [ITRes125|ITResList125],
+
+
+ ?line {STRes345,S345} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD024.xsd','./msxsdtest/attributeGroup',valid),
+ STResList346 = [STRes345|STResList345],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD024.xml','./msxsdtest/attributeGroup',invalid,S345),
+ ITResList127 = [ITRes126|ITResList126],
+
+
+ ?line {STRes346,S346} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD025.xsd','./msxsdtest/attributeGroup',valid),
+ STResList347 = [STRes346|STResList346],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD025.xml','./msxsdtest/attributeGroup',valid,S346),
+ ITResList128 = [ITRes127|ITResList127],
+
+
+ ?line {STRes347,S347} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD026.xsd','./msxsdtest/attributeGroup',valid),
+ STResList348 = [STRes347|STResList347],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD026.xml','./msxsdtest/attributeGroup',invalid,S347),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes348,S348} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD027.xsd','./msxsdtest/attributeGroup',valid),
+ STResList349 = [STRes348|STResList348],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD027.xml','./msxsdtest/attributeGroup',valid,S348),
+ ITResList130 = [ITRes129|ITResList129],
+
+
+ ?line {STRes349,S349} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD028.xsd','./msxsdtest/attributeGroup',valid),
+ STResList350 = [STRes349|STResList349],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD028.xml','./msxsdtest/attributeGroup',invalid,S349),
+ ITResList131 = [ITRes130|ITResList130],
+
+
+ ?line {STRes350,S350} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD029.xsd','./msxsdtest/attributeGroup',valid),
+ STResList351 = [STRes350|STResList350],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD029.xml','./msxsdtest/attributeGroup',valid,S350),
+ ITResList132 = [ITRes131|ITResList131],
+
+
+ ?line {STRes351,S351} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD030.xsd','./msxsdtest/attributeGroup',valid),
+ STResList352 = [STRes351|STResList351],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD030.xml','./msxsdtest/attributeGroup',invalid,S351),
+ ITResList133 = [ITRes132|ITResList132],
+
+
+ ?line {STRes352,S352} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD031.xsd','./msxsdtest/attributeGroup',valid),
+ STResList353 = [STRes352|STResList352],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD031.xml','./msxsdtest/attributeGroup',valid,S352),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes353,S353} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD032.xsd','./msxsdtest/attributeGroup',valid),
+ STResList354 = [STRes353|STResList353],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD032.xml','./msxsdtest/attributeGroup',valid,S353),
+ ITResList135 = [ITRes134|ITResList134],
+
+
+ ?line {STRes354,S354} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD033.xsd','./msxsdtest/attributeGroup',valid),
+ STResList355 = [STRes354|STResList354],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD033.xml','./msxsdtest/attributeGroup',valid,S354),
+ ITResList136 = [ITRes135|ITResList135],
+
+
+ ?line {STRes355,S355} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD034.xsd','./msxsdtest/attributeGroup',valid),
+ STResList356 = [STRes355|STResList355],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD034.xml','./msxsdtest/attributeGroup',valid,S355),
+ ITResList137 = [ITRes136|ITResList136],
+
+
+ ?line {STRes356,S356} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD035.xsd','./msxsdtest/attributeGroup',valid),
+ STResList357 = [STRes356|STResList356],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD035.xml','./msxsdtest/attributeGroup',invalid,S356),
+ ITResList138 = [ITRes137|ITResList137],
+
+
+ ?line {STRes357,S357} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD036.xsd','./msxsdtest/attributeGroup',valid),
+ STResList358 = [STRes357|STResList357],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD036.xml','./msxsdtest/attributeGroup',valid,S357),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ ?line {STRes358,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD037.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList359 = [STRes358|STResList358],
+
+
+ ?line {STRes359,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD038.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList360 = [STRes359|STResList359],
+
+
+ ?line {STRes360,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD039.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList361 = [STRes360|STResList360],
+
+
+ ?line {STRes361,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD040.xsd','./msxsdtest/attributeGroup',valid),
+ STResList362 = [STRes361|STResList361],
+
+
+ ?line {STRes362,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD041.xsd','./msxsdtest/attributeGroup',invalid),
+ STResList363 = [STRes362|STResList362],
+
+
+ ?line {STRes363,S363} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/attributeGroup/attgD042.xsd','./msxsdtest/attributeGroup',valid),
+ STResList364 = [STRes363|STResList363],
+ ?line ITRes139 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/attributeGroup/attgD042.xml','./msxsdtest/attributeGroup',invalid,S363),
+ ITResList140 = [ITRes139|ITResList139],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList364,ITResList140).
+
+%% Syntax Checking for top level complexType Declaration.
+%% Syntax Checking for simpleContent complexType Declaration.
+%% Syntax Checking for comlexContent complexType Declaration
+%% complexType Validation checking
+%% complexType Schema Component Constraints
+
+ct(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA001.xsd','./msxsdtest/complexType',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA001.xml','./msxsdtest/complexType',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA002.xsd','./msxsdtest/complexType',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA002.xml','./msxsdtest/complexType',valid,S1),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA003.xsd','./msxsdtest/complexType',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA003.xml','./msxsdtest/complexType',valid,S2),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes3,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA004.xsd','./msxsdtest/complexType',invalid),
+ STResList4 = [STRes3|STResList3],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA005.xsd','./msxsdtest/complexType',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA005.xml','./msxsdtest/complexType',valid,S4),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes5,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA006.xsd','./msxsdtest/complexType',invalid),
+ STResList6 = [STRes5|STResList5],
+
+
+ ?line {STRes6,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA007.xsd','./msxsdtest/complexType',invalid),
+ STResList7 = [STRes6|STResList6],
+
+
+ ?line {STRes7,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA008.xsd','./msxsdtest/complexType',invalid),
+ STResList8 = [STRes7|STResList7],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA009.xsd','./msxsdtest/complexType',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA009.xml','./msxsdtest/complexType',valid,S8),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA010.xsd','./msxsdtest/complexType',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA010.xml','./msxsdtest/complexType',valid,S9),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA011.xsd','./msxsdtest/complexType',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA011.xml','./msxsdtest/complexType',valid,S10),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA012.xsd','./msxsdtest/complexType',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA012.xml','./msxsdtest/complexType',valid,S11),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA013.xsd','./msxsdtest/complexType',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA013.xml','./msxsdtest/complexType',valid,S12),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes13,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA014.xsd','./msxsdtest/complexType',invalid),
+ STResList14 = [STRes13|STResList13],
+
+
+ ?line {STRes14,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA015.xsd','./msxsdtest/complexType',invalid),
+ STResList15 = [STRes14|STResList14],
+
+
+ ?line {STRes15,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA016.xsd','./msxsdtest/complexType',invalid),
+ STResList16 = [STRes15|STResList15],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA017.xsd','./msxsdtest/complexType',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA017.xml','./msxsdtest/complexType',valid,S16),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA018.xsd','./msxsdtest/complexType',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA018.xml','./msxsdtest/complexType',valid,S17),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA019.xsd','./msxsdtest/complexType',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA019.xml','./msxsdtest/complexType',valid,S18),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA020.xsd','./msxsdtest/complexType',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA020.xml','./msxsdtest/complexType',valid,S19),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA021.xsd','./msxsdtest/complexType',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA021.xml','./msxsdtest/complexType',valid,S20),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA022.xsd','./msxsdtest/complexType',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA022.xml','./msxsdtest/complexType',valid,S21),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes22,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA023.xsd','./msxsdtest/complexType',invalid),
+ STResList23 = [STRes22|STResList22],
+
+
+ ?line {STRes23,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA024.xsd','./msxsdtest/complexType',invalid),
+ STResList24 = [STRes23|STResList23],
+
+
+ ?line {STRes24,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA025.xsd','./msxsdtest/complexType',invalid),
+ STResList25 = [STRes24|STResList24],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA026.xsd','./msxsdtest/complexType',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA026.xml','./msxsdtest/complexType',valid,S25),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA027.xsd','./msxsdtest/complexType',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA027.xml','./msxsdtest/complexType',valid,S26),
+ ITResList17 = [ITRes16|ITResList16],
+
+
+ ?line {STRes27,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA028.xsd','./msxsdtest/complexType',invalid),
+ STResList28 = [STRes27|STResList27],
+
+
+ ?line {STRes28,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA029.xsd','./msxsdtest/complexType',invalid),
+ STResList29 = [STRes28|STResList28],
+
+
+ ?line {STRes29,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA030.xsd','./msxsdtest/complexType',invalid),
+ STResList30 = [STRes29|STResList29],
+
+
+ ?line {STRes30,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA031.xsd','./msxsdtest/complexType',invalid),
+ STResList31 = [STRes30|STResList30],
+
+
+ ?line {STRes31,S31} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA032.xsd','./msxsdtest/complexType',valid),
+ STResList32 = [STRes31|STResList31],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA032.xml','./msxsdtest/complexType',valid,S31),
+ ITResList18 = [ITRes17|ITResList17],
+
+
+ ?line {STRes32,S32} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA033.xsd','./msxsdtest/complexType',valid),
+ STResList33 = [STRes32|STResList32],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA033.xml','./msxsdtest/complexType',valid,S32),
+ ITResList19 = [ITRes18|ITResList18],
+
+
+ ?line {STRes33,S33} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA034.xsd','./msxsdtest/complexType',valid),
+ STResList34 = [STRes33|STResList33],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA034.xml','./msxsdtest/complexType',valid,S33),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA035.xsd','./msxsdtest/complexType',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA035.xml','./msxsdtest/complexType',valid,S34),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes35,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA036.xsd','./msxsdtest/complexType',invalid),
+ STResList36 = [STRes35|STResList35],
+
+
+ ?line {STRes36,S36} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA037.xsd','./msxsdtest/complexType',valid),
+ STResList37 = [STRes36|STResList36],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA037.xml','./msxsdtest/complexType',valid,S36),
+ ITResList22 = [ITRes21|ITResList21],
+
+
+ ?line {STRes37,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA038.xsd','./msxsdtest/complexType',invalid),
+ STResList38 = [STRes37|STResList37],
+
+
+ ?line {STRes38,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA039.xsd','./msxsdtest/complexType',invalid),
+ STResList39 = [STRes38|STResList38],
+
+
+ ?line {STRes39,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA040.xsd','./msxsdtest/complexType',invalid),
+ STResList40 = [STRes39|STResList39],
+
+
+ ?line {STRes40,S40} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA041.xsd','./msxsdtest/complexType',valid),
+ STResList41 = [STRes40|STResList40],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA041.xml','./msxsdtest/complexType',valid,S40),
+ ITResList23 = [ITRes22|ITResList22],
+
+
+ ?line {STRes41,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA042.xsd','./msxsdtest/complexType',invalid),
+ STResList42 = [STRes41|STResList41],
+
+
+ ?line {STRes42,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA043.xsd','./msxsdtest/complexType',invalid),
+ STResList43 = [STRes42|STResList42],
+
+
+ ?line {STRes43,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA044.xsd','./msxsdtest/complexType',invalid),
+ STResList44 = [STRes43|STResList43],
+
+
+ ?line {STRes44,S44} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA045.xsd','./msxsdtest/complexType',valid),
+ STResList45 = [STRes44|STResList44],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA045.xml','./msxsdtest/complexType',valid,S44),
+ ITResList24 = [ITRes23|ITResList23],
+
+
+ ?line {STRes45,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA046.xsd','./msxsdtest/complexType',invalid),
+ STResList46 = [STRes45|STResList45],
+
+
+ ?line {STRes46,S46} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA047.xsd','./msxsdtest/complexType',valid),
+ STResList47 = [STRes46|STResList46],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA047.xml','./msxsdtest/complexType',valid,S46),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes47,S47} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA048.xsd','./msxsdtest/complexType',valid),
+ STResList48 = [STRes47|STResList47],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA048.xml','./msxsdtest/complexType',valid,S47),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes48,S48} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctA049.xsd','./msxsdtest/complexType',valid),
+ STResList49 = [STRes48|STResList48],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctA049.xml','./msxsdtest/complexType',valid,S48),
+ ITResList27 = [ITRes26|ITResList26],
+
+
+ ?line {STRes49,S49} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB001.xsd','./msxsdtest/complexType',valid),
+ STResList50 = [STRes49|STResList49],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB001.xml','./msxsdtest/complexType',valid,S49),
+ ITResList28 = [ITRes27|ITResList27],
+
+
+ ?line {STRes50,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB002.xsd','./msxsdtest/complexType',invalid),
+ STResList51 = [STRes50|STResList50],
+
+
+ ?line {STRes51,S51} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB003.xsd','./msxsdtest/complexType',valid),
+ STResList52 = [STRes51|STResList51],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB003.xml','./msxsdtest/complexType',valid,S51),
+ ITResList29 = [ITRes28|ITResList28],
+
+
+ ?line {STRes52,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB004.xsd','./msxsdtest/complexType',invalid),
+ STResList53 = [STRes52|STResList52],
+
+
+ ?line {STRes53,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB005.xsd','./msxsdtest/complexType',invalid),
+ STResList54 = [STRes53|STResList53],
+
+
+ ?line {STRes54,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB006.xsd','./msxsdtest/complexType',invalid),
+ STResList55 = [STRes54|STResList54],
+
+
+ ?line {STRes55,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB007.xsd','./msxsdtest/complexType',invalid),
+ STResList56 = [STRes55|STResList55],
+
+
+ ?line {STRes56,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB008.xsd','./msxsdtest/complexType',invalid),
+ STResList57 = [STRes56|STResList56],
+
+
+ ?line {STRes57,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB009.xsd','./msxsdtest/complexType',invalid),
+ STResList58 = [STRes57|STResList57],
+
+
+ ?line {STRes58,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB010.xsd','./msxsdtest/complexType',invalid),
+ STResList59 = [STRes58|STResList58],
+
+
+ ?line {STRes59,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB011.xsd','./msxsdtest/complexType',invalid),
+ STResList60 = [STRes59|STResList59],
+
+
+ ?line {STRes60,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB012.xsd','./msxsdtest/complexType',invalid),
+ STResList61 = [STRes60|STResList60],
+
+
+ ?line {STRes61,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB013.xsd','./msxsdtest/complexType',invalid),
+ STResList62 = [STRes61|STResList61],
+
+
+ ?line {STRes62,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB014.xsd','./msxsdtest/complexType',invalid),
+ STResList63 = [STRes62|STResList62],
+
+
+ ?line {STRes63,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB015.xsd','./msxsdtest/complexType',invalid),
+ STResList64 = [STRes63|STResList63],
+
+
+ ?line {STRes64,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB016.xsd','./msxsdtest/complexType',invalid),
+ STResList65 = [STRes64|STResList64],
+
+
+ ?line {STRes65,S65} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB017.xsd','./msxsdtest/complexType',valid),
+ STResList66 = [STRes65|STResList65],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB017.xml','./msxsdtest/complexType',valid,S65),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes66,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB018.xsd','./msxsdtest/complexType',invalid),
+ STResList67 = [STRes66|STResList66],
+
+
+ ?line {STRes67,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB019.xsd','./msxsdtest/complexType',invalid),
+ STResList68 = [STRes67|STResList67],
+
+
+ ?line {STRes68,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB020.xsd','./msxsdtest/complexType',invalid),
+ STResList69 = [STRes68|STResList68],
+
+
+ ?line {STRes69,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB021.xsd','./msxsdtest/complexType',invalid),
+ STResList70 = [STRes69|STResList69],
+
+
+ ?line {STRes70,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB022.xsd','./msxsdtest/complexType',invalid),
+ STResList71 = [STRes70|STResList70],
+
+
+ ?line {STRes71,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB023.xsd','./msxsdtest/complexType',invalid),
+ STResList72 = [STRes71|STResList71],
+
+
+ ?line {STRes72,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB024.xsd','./msxsdtest/complexType',invalid),
+ STResList73 = [STRes72|STResList72],
+
+
+ ?line {STRes73,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB025.xsd','./msxsdtest/complexType',invalid),
+ STResList74 = [STRes73|STResList73],
+
+
+ ?line {STRes74,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB026.xsd','./msxsdtest/complexType',invalid),
+ STResList75 = [STRes74|STResList74],
+
+
+ ?line {STRes75,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB027.xsd','./msxsdtest/complexType',invalid),
+ STResList76 = [STRes75|STResList75],
+
+
+ ?line {STRes76,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB028.xsd','./msxsdtest/complexType',invalid),
+ STResList77 = [STRes76|STResList76],
+
+
+ ?line {STRes77,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB029.xsd','./msxsdtest/complexType',invalid),
+ STResList78 = [STRes77|STResList77],
+
+
+ ?line {STRes78,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB030.xsd','./msxsdtest/complexType',invalid),
+ STResList79 = [STRes78|STResList78],
+
+
+ ?line {STRes79,S79} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB031.xsd','./msxsdtest/complexType',valid),
+ STResList80 = [STRes79|STResList79],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB031.xml','./msxsdtest/complexType',valid,S79),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes80,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB032.xsd','./msxsdtest/complexType',invalid),
+ STResList81 = [STRes80|STResList80],
+
+
+ ?line {STRes81,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB033.xsd','./msxsdtest/complexType',invalid),
+ STResList82 = [STRes81|STResList81],
+
+
+ ?line {STRes82,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB034.xsd','./msxsdtest/complexType',invalid),
+ STResList83 = [STRes82|STResList82],
+
+
+ ?line {STRes83,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB035.xsd','./msxsdtest/complexType',invalid),
+ STResList84 = [STRes83|STResList83],
+
+
+ ?line {STRes84,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB036.xsd','./msxsdtest/complexType',invalid),
+ STResList85 = [STRes84|STResList84],
+
+
+ ?line {STRes85,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB037.xsd','./msxsdtest/complexType',invalid),
+ STResList86 = [STRes85|STResList85],
+
+
+ ?line {STRes86,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB038.xsd','./msxsdtest/complexType',invalid),
+ STResList87 = [STRes86|STResList86],
+
+
+ ?line {STRes87,S87} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB039.xsd','./msxsdtest/complexType',valid),
+ STResList88 = [STRes87|STResList87],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB039.xml','./msxsdtest/complexType',valid,S87),
+ ITResList32 = [ITRes31|ITResList31],
+
+
+ ?line {STRes88,S88} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB040.xsd','./msxsdtest/complexType',valid),
+ STResList89 = [STRes88|STResList88],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB040.xml','./msxsdtest/complexType',valid,S88),
+ ITResList33 = [ITRes32|ITResList32],
+
+
+ ?line {STRes89,S89} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB041.xsd','./msxsdtest/complexType',valid),
+ STResList90 = [STRes89|STResList89],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB041.xml','./msxsdtest/complexType',valid,S89),
+ ITResList34 = [ITRes33|ITResList33],
+
+
+ ?line {STRes90,S90} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB042.xsd','./msxsdtest/complexType',valid),
+ STResList91 = [STRes90|STResList90],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB042.xml','./msxsdtest/complexType',valid,S90),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes91,S91} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB043.xsd','./msxsdtest/complexType',valid),
+ STResList92 = [STRes91|STResList91],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB043.xml','./msxsdtest/complexType',valid,S91),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes92,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB044.xsd','./msxsdtest/complexType',invalid),
+ STResList93 = [STRes92|STResList92],
+
+
+ ?line {STRes93,S93} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB045.xsd','./msxsdtest/complexType',valid),
+ STResList94 = [STRes93|STResList93],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB045.xml','./msxsdtest/complexType',valid,S93),
+ ITResList37 = [ITRes36|ITResList36],
+
+
+ ?line {STRes94,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB046.xsd','./msxsdtest/complexType',invalid),
+ STResList95 = [STRes94|STResList94],
+
+
+ ?line {STRes95,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB047.xsd','./msxsdtest/complexType',invalid),
+ STResList96 = [STRes95|STResList95],
+
+
+ ?line {STRes96,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB048.xsd','./msxsdtest/complexType',invalid),
+ STResList97 = [STRes96|STResList96],
+
+
+ ?line {STRes97,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB049.xsd','./msxsdtest/complexType',invalid),
+ STResList98 = [STRes97|STResList97],
+
+
+ ?line {STRes98,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB050.xsd','./msxsdtest/complexType',invalid),
+ STResList99 = [STRes98|STResList98],
+
+
+ ?line {STRes99,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB051.xsd','./msxsdtest/complexType',invalid),
+ STResList100 = [STRes99|STResList99],
+
+
+ ?line {STRes100,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB052.xsd','./msxsdtest/complexType',invalid),
+ STResList101 = [STRes100|STResList100],
+
+
+ ?line {STRes101,S101} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB053.xsd','./msxsdtest/complexType',valid),
+ STResList102 = [STRes101|STResList101],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB053.xml','./msxsdtest/complexType',valid,S101),
+ ITResList38 = [ITRes37|ITResList37],
+
+
+ ?line {STRes102,S102} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB054.xsd','./msxsdtest/complexType',valid),
+ STResList103 = [STRes102|STResList102],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB054.xml','./msxsdtest/complexType',valid,S102),
+ ITResList39 = [ITRes38|ITResList38],
+
+
+ ?line {STRes103,S103} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB055.xsd','./msxsdtest/complexType',valid),
+ STResList104 = [STRes103|STResList103],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB055.xml','./msxsdtest/complexType',valid,S103),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes104,S104} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB056.xsd','./msxsdtest/complexType',valid),
+ STResList105 = [STRes104|STResList104],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB056.xml','./msxsdtest/complexType',valid,S104),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes105,S105} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB057.xsd','./msxsdtest/complexType',valid),
+ STResList106 = [STRes105|STResList105],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB057.xml','./msxsdtest/complexType',valid,S105),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes106,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB058.xsd','./msxsdtest/complexType',invalid),
+ STResList107 = [STRes106|STResList106],
+
+
+ ?line {STRes107,S107} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB059.xsd','./msxsdtest/complexType',valid),
+ STResList108 = [STRes107|STResList107],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB059.xml','./msxsdtest/complexType',valid,S107),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes108,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB060.xsd','./msxsdtest/complexType',invalid),
+ STResList109 = [STRes108|STResList108],
+
+
+ ?line {STRes109,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB061.xsd','./msxsdtest/complexType',invalid),
+ STResList110 = [STRes109|STResList109],
+
+
+ ?line {STRes110,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB062.xsd','./msxsdtest/complexType',invalid),
+ STResList111 = [STRes110|STResList110],
+
+
+ ?line {STRes111,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB063.xsd','./msxsdtest/complexType',invalid),
+ STResList112 = [STRes111|STResList111],
+
+
+ ?line {STRes112,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB064.xsd','./msxsdtest/complexType',invalid),
+ STResList113 = [STRes112|STResList112],
+
+
+ ?line {STRes113,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB065.xsd','./msxsdtest/complexType',invalid),
+ STResList114 = [STRes113|STResList113],
+
+
+ ?line {STRes114,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB066.xsd','./msxsdtest/complexType',invalid),
+ STResList115 = [STRes114|STResList114],
+
+
+ ?line {STRes115,S115} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB067.xsd','./msxsdtest/complexType',valid),
+ STResList116 = [STRes115|STResList115],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB067.xml','./msxsdtest/complexType',valid,S115),
+ ITResList44 = [ITRes43|ITResList43],
+
+
+ ?line {STRes116,S116} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB068.xsd','./msxsdtest/complexType',valid),
+ STResList117 = [STRes116|STResList116],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB068.xml','./msxsdtest/complexType',valid,S116),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes117,S117} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB069.xsd','./msxsdtest/complexType',valid),
+ STResList118 = [STRes117|STResList117],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB069.xml','./msxsdtest/complexType',valid,S117),
+ ITResList46 = [ITRes45|ITResList45],
+
+
+ ?line {STRes118,S118} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB070.xsd','./msxsdtest/complexType',valid),
+ STResList119 = [STRes118|STResList118],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB070.xml','./msxsdtest/complexType',valid,S118),
+ ITResList47 = [ITRes46|ITResList46],
+
+
+ ?line {STRes119,S119} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB071.xsd','./msxsdtest/complexType',valid),
+ STResList120 = [STRes119|STResList119],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB071.xml','./msxsdtest/complexType',valid,S119),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes120,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB072.xsd','./msxsdtest/complexType',invalid),
+ STResList121 = [STRes120|STResList120],
+
+
+ ?line {STRes121,S121} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB073.xsd','./msxsdtest/complexType',valid),
+ STResList122 = [STRes121|STResList121],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB073.xml','./msxsdtest/complexType',valid,S121),
+ ITResList49 = [ITRes48|ITResList48],
+
+
+ ?line {STRes122,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB074.xsd','./msxsdtest/complexType',invalid),
+ STResList123 = [STRes122|STResList122],
+
+
+ ?line {STRes123,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB075.xsd','./msxsdtest/complexType',invalid),
+ STResList124 = [STRes123|STResList123],
+
+
+ ?line {STRes124,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB076.xsd','./msxsdtest/complexType',invalid),
+ STResList125 = [STRes124|STResList124],
+
+
+ ?line {STRes125,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB077.xsd','./msxsdtest/complexType',invalid),
+ STResList126 = [STRes125|STResList125],
+
+
+ ?line {STRes126,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB078.xsd','./msxsdtest/complexType',invalid),
+ STResList127 = [STRes126|STResList126],
+
+
+ ?line {STRes127,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB079.xsd','./msxsdtest/complexType',invalid),
+ STResList128 = [STRes127|STResList127],
+
+
+ ?line {STRes128,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB080.xsd','./msxsdtest/complexType',invalid),
+ STResList129 = [STRes128|STResList128],
+
+
+ ?line {STRes129,S129} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB081.xsd','./msxsdtest/complexType',valid),
+ STResList130 = [STRes129|STResList129],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB081.xml','./msxsdtest/complexType',valid,S129),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes130,S130} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB082.xsd','./msxsdtest/complexType',valid),
+ STResList131 = [STRes130|STResList130],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB082.xml','./msxsdtest/complexType',valid,S130),
+ ITResList51 = [ITRes50|ITResList50],
+
+
+ ?line {STRes131,S131} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB083.xsd','./msxsdtest/complexType',valid),
+ STResList132 = [STRes131|STResList131],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB083.xml','./msxsdtest/complexType',valid,S131),
+ ITResList52 = [ITRes51|ITResList51],
+
+
+ ?line {STRes132,S132} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB084.xsd','./msxsdtest/complexType',valid),
+ STResList133 = [STRes132|STResList132],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB084.xml','./msxsdtest/complexType',valid,S132),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes133,S133} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB085.xsd','./msxsdtest/complexType',valid),
+ STResList134 = [STRes133|STResList133],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB085.xml','./msxsdtest/complexType',valid,S133),
+ ITResList54 = [ITRes53|ITResList53],
+
+
+ ?line {STRes134,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB086.xsd','./msxsdtest/complexType',invalid),
+ STResList135 = [STRes134|STResList134],
+
+
+ ?line {STRes135,S135} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB087.xsd','./msxsdtest/complexType',valid),
+ STResList136 = [STRes135|STResList135],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB087.xml','./msxsdtest/complexType',valid,S135),
+ ITResList55 = [ITRes54|ITResList54],
+
+
+ ?line {STRes136,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB088.xsd','./msxsdtest/complexType',invalid),
+ STResList137 = [STRes136|STResList136],
+
+
+ ?line {STRes137,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB089.xsd','./msxsdtest/complexType',invalid),
+ STResList138 = [STRes137|STResList137],
+
+
+ ?line {STRes138,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB090.xsd','./msxsdtest/complexType',invalid),
+ STResList139 = [STRes138|STResList138],
+
+
+ ?line {STRes139,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB091.xsd','./msxsdtest/complexType',invalid),
+ STResList140 = [STRes139|STResList139],
+
+
+ ?line {STRes140,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB092.xsd','./msxsdtest/complexType',invalid),
+ STResList141 = [STRes140|STResList140],
+
+
+ ?line {STRes141,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB093.xsd','./msxsdtest/complexType',invalid),
+ STResList142 = [STRes141|STResList141],
+
+
+ ?line {STRes142,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB094.xsd','./msxsdtest/complexType',invalid),
+ STResList143 = [STRes142|STResList142],
+
+
+ ?line {STRes143,S143} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB095.xsd','./msxsdtest/complexType',valid),
+ STResList144 = [STRes143|STResList143],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB095.xml','./msxsdtest/complexType',valid,S143),
+ ITResList56 = [ITRes55|ITResList55],
+
+
+ ?line {STRes144,S144} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB096.xsd','./msxsdtest/complexType',valid),
+ STResList145 = [STRes144|STResList144],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB096.xml','./msxsdtest/complexType',valid,S144),
+ ITResList57 = [ITRes56|ITResList56],
+
+
+ ?line {STRes145,S145} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB097.xsd','./msxsdtest/complexType',valid),
+ STResList146 = [STRes145|STResList145],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB097.xml','./msxsdtest/complexType',valid,S145),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes146,S146} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB098.xsd','./msxsdtest/complexType',valid),
+ STResList147 = [STRes146|STResList146],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB098.xml','./msxsdtest/complexType',valid,S146),
+ ITResList59 = [ITRes58|ITResList58],
+
+
+ ?line {STRes147,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB099.xsd','./msxsdtest/complexType',invalid),
+ STResList148 = [STRes147|STResList147],
+
+
+ ?line {STRes148,S148} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB100.xsd','./msxsdtest/complexType',valid),
+ STResList149 = [STRes148|STResList148],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB100.xml','./msxsdtest/complexType',valid,S148),
+ ITResList60 = [ITRes59|ITResList59],
+
+
+ ?line {STRes149,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB101.xsd','./msxsdtest/complexType',invalid),
+ STResList150 = [STRes149|STResList149],
+
+
+ ?line {STRes150,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB102.xsd','./msxsdtest/complexType',invalid),
+ STResList151 = [STRes150|STResList150],
+
+
+ ?line {STRes151,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB103.xsd','./msxsdtest/complexType',invalid),
+ STResList152 = [STRes151|STResList151],
+
+
+ ?line {STRes152,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB104.xsd','./msxsdtest/complexType',invalid),
+ STResList153 = [STRes152|STResList152],
+
+
+ ?line {STRes153,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB105.xsd','./msxsdtest/complexType',invalid),
+ STResList154 = [STRes153|STResList153],
+
+
+ ?line {STRes154,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB106.xsd','./msxsdtest/complexType',invalid),
+ STResList155 = [STRes154|STResList154],
+
+
+ ?line {STRes155,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB107.xsd','./msxsdtest/complexType',invalid),
+ STResList156 = [STRes155|STResList155],
+
+
+ ?line {STRes156,S156} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB108.xsd','./msxsdtest/complexType',valid),
+ STResList157 = [STRes156|STResList156],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB108.xml','./msxsdtest/complexType',valid,S156),
+ ITResList61 = [ITRes60|ITResList60],
+
+
+ ?line {STRes157,S157} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB109.xsd','./msxsdtest/complexType',valid),
+ STResList158 = [STRes157|STResList157],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB109.xml','./msxsdtest/complexType',valid,S157),
+ ITResList62 = [ITRes61|ITResList61],
+
+
+ ?line {STRes158,S158} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB110.xsd','./msxsdtest/complexType',valid),
+ STResList159 = [STRes158|STResList158],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB110.xml','./msxsdtest/complexType',valid,S158),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes159,S159} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB111.xsd','./msxsdtest/complexType',valid),
+ STResList160 = [STRes159|STResList159],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB111.xml','./msxsdtest/complexType',valid,S159),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes160,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB112.xsd','./msxsdtest/complexType',invalid),
+ STResList161 = [STRes160|STResList160],
+
+
+ ?line {STRes161,S161} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB113.xsd','./msxsdtest/complexType',valid),
+ STResList162 = [STRes161|STResList161],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctB113.xml','./msxsdtest/complexType',valid,S161),
+ ITResList65 = [ITRes64|ITResList64],
+
+
+ ?line {STRes162,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB114.xsd','./msxsdtest/complexType',invalid),
+ STResList163 = [STRes162|STResList162],
+
+
+ ?line {STRes163,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB115.xsd','./msxsdtest/complexType',invalid),
+ STResList164 = [STRes163|STResList163],
+
+
+ ?line {STRes164,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB116.xsd','./msxsdtest/complexType',invalid),
+ STResList165 = [STRes164|STResList164],
+
+
+ ?line {STRes165,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB117.xsd','./msxsdtest/complexType',invalid),
+ STResList166 = [STRes165|STResList165],
+
+
+ ?line {STRes166,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB118.xsd','./msxsdtest/complexType',invalid),
+ STResList167 = [STRes166|STResList166],
+
+
+ ?line {STRes167,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB119.xsd','./msxsdtest/complexType',invalid),
+ STResList168 = [STRes167|STResList167],
+
+
+ ?line {STRes168,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB120.xsd','./msxsdtest/complexType',invalid),
+ STResList169 = [STRes168|STResList168],
+
+
+ ?line {STRes169,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB121.xsd','./msxsdtest/complexType',invalid),
+ STResList170 = [STRes169|STResList169],
+
+
+ ?line {STRes170,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB122.xsd','./msxsdtest/complexType',invalid),
+ STResList171 = [STRes170|STResList170],
+
+
+ ?line {STRes171,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB123.xsd','./msxsdtest/complexType',invalid),
+ STResList172 = [STRes171|STResList171],
+
+
+ ?line {STRes172,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB124.xsd','./msxsdtest/complexType',invalid),
+ STResList173 = [STRes172|STResList172],
+
+
+ ?line {STRes173,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctB125.xsd','./msxsdtest/complexType',invalid),
+ STResList174 = [STRes173|STResList173],
+
+
+ ?line {STRes174,S174} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctC001.xsd','./msxsdtest/complexType',valid),
+ STResList175 = [STRes174|STResList174],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctC001.xml','./msxsdtest/complexType',valid,S174),
+ ITResList66 = [ITRes65|ITResList65],
+
+
+ ?line {STRes175,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctC002.xsd','./msxsdtest/complexType',invalid),
+ STResList176 = [STRes175|STResList175],
+
+
+ ?line {STRes176,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctC003.xsd','./msxsdtest/complexType',invalid),
+ STResList177 = [STRes176|STResList176],
+
+
+ ?line {STRes177,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctC004.xsd','./msxsdtest/complexType',invalid),
+ STResList178 = [STRes177|STResList177],
+
+
+ ?line {STRes178,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctC005.xsd','./msxsdtest/complexType',invalid),
+ STResList179 = [STRes178|STResList178],
+
+
+ ?line {STRes179,S179} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctC006.xsd','./msxsdtest/complexType',valid),
+ STResList180 = [STRes179|STResList179],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctC006.xml','./msxsdtest/complexType',valid,S179),
+ ITResList67 = [ITRes66|ITResList66],
+
+
+ ?line {STRes180,S180} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctC007.xsd','./msxsdtest/complexType',valid),
+ STResList181 = [STRes180|STResList180],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctC007.xml','./msxsdtest/complexType',valid,S180),
+ ITResList68 = [ITRes67|ITResList67],
+
+
+ ?line {STRes181,S181} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctC008.xsd','./msxsdtest/complexType',valid),
+ STResList182 = [STRes181|STResList181],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctC008.xml','./msxsdtest/complexType',valid,S181),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes182,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctC009.xsd','./msxsdtest/complexType',invalid),
+ STResList183 = [STRes182|STResList182],
+
+
+ ?line {STRes183,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctC010.xsd','./msxsdtest/complexType',invalid),
+ STResList184 = [STRes183|STResList183],
+
+
+ ?line {STRes184,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctC011.xsd','./msxsdtest/complexType',invalid),
+ STResList185 = [STRes184|STResList184],
+
+
+ ?line {STRes185,S185} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctC012.xsd','./msxsdtest/complexType',valid),
+ STResList186 = [STRes185|STResList185],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctC012.xml','./msxsdtest/complexType',valid,S185),
+ ITResList70 = [ITRes69|ITResList69],
+
+
+ ?line {STRes186,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD001.xsd','./msxsdtest/complexType',invalid),
+ STResList187 = [STRes186|STResList186],
+
+
+ ?line {STRes187,S187} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD002.xsd','./msxsdtest/complexType',valid),
+ STResList188 = [STRes187|STResList187],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD002.xml','./msxsdtest/complexType',valid,S187),
+ ITResList71 = [ITRes70|ITResList70],
+
+
+ ?line {STRes188,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD003.xsd','./msxsdtest/complexType',invalid),
+ STResList189 = [STRes188|STResList188],
+
+
+ ?line {STRes189,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD004.xsd','./msxsdtest/complexType',invalid),
+ STResList190 = [STRes189|STResList189],
+
+
+ ?line {STRes190,S190} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD005.xsd','./msxsdtest/complexType',valid),
+ STResList191 = [STRes190|STResList190],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD005.xml','./msxsdtest/complexType',valid,S190),
+ ITResList72 = [ITRes71|ITResList71],
+
+
+ ?line {STRes191,S191} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD006.xsd','./msxsdtest/complexType',valid),
+ STResList192 = [STRes191|STResList191],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD006.xml','./msxsdtest/complexType',valid,S191),
+ ITResList73 = [ITRes72|ITResList72],
+
+
+ ?line {STRes192,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD007.xsd','./msxsdtest/complexType',invalid),
+ STResList193 = [STRes192|STResList192],
+
+
+ ?line {STRes193,S193} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD008.xsd','./msxsdtest/complexType',valid),
+ STResList194 = [STRes193|STResList193],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD008.xml','./msxsdtest/complexType',valid,S193),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes194,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD009.xsd','./msxsdtest/complexType',invalid),
+ STResList195 = [STRes194|STResList194],
+
+
+ ?line {STRes195,S195} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD010.xsd','./msxsdtest/complexType',valid),
+ STResList196 = [STRes195|STResList195],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD010.xml','./msxsdtest/complexType',valid,S195),
+ ITResList75 = [ITRes74|ITResList74],
+
+
+ ?line {STRes196,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD011.xsd','./msxsdtest/complexType',invalid),
+ STResList197 = [STRes196|STResList196],
+
+
+ ?line {STRes197,S197} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD012.xsd','./msxsdtest/complexType',valid),
+ STResList198 = [STRes197|STResList197],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD012.xml','./msxsdtest/complexType',valid,S197),
+ ITResList76 = [ITRes75|ITResList75],
+
+
+ ?line {STRes198,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD013.xsd','./msxsdtest/complexType',invalid),
+ STResList199 = [STRes198|STResList198],
+
+
+ ?line {STRes199,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD014.xsd','./msxsdtest/complexType',invalid),
+ STResList200 = [STRes199|STResList199],
+
+
+ ?line {STRes200,S200} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD015.xsd','./msxsdtest/complexType',valid),
+ STResList201 = [STRes200|STResList200],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD015.xml','./msxsdtest/complexType',valid,S200),
+ ITResList77 = [ITRes76|ITResList76],
+
+
+ ?line {STRes201,S201} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD016.xsd','./msxsdtest/complexType',valid),
+ STResList202 = [STRes201|STResList201],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD016.xml','./msxsdtest/complexType',valid,S201),
+ ITResList78 = [ITRes77|ITResList77],
+
+
+ ?line {STRes202,S202} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD017.xsd','./msxsdtest/complexType',valid),
+ STResList203 = [STRes202|STResList202],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD017.xml','./msxsdtest/complexType',valid,S202),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes203,S203} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD018.xsd','./msxsdtest/complexType',valid),
+ STResList204 = [STRes203|STResList203],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD018.xml','./msxsdtest/complexType',valid,S203),
+ ITResList80 = [ITRes79|ITResList79],
+
+
+ ?line {STRes204,S204} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD019.xsd','./msxsdtest/complexType',valid),
+ STResList205 = [STRes204|STResList204],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD019.xml','./msxsdtest/complexType',valid,S204),
+ ITResList81 = [ITRes80|ITResList80],
+
+
+ ?line {STRes205,S205} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD020.xsd','./msxsdtest/complexType',valid),
+ STResList206 = [STRes205|STResList205],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD020.xml','./msxsdtest/complexType',valid,S205),
+ ITResList82 = [ITRes81|ITResList81],
+
+
+ ?line {STRes206,S206} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD021.xsd','./msxsdtest/complexType',valid),
+ STResList207 = [STRes206|STResList206],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD021.xml','./msxsdtest/complexType',valid,S206),
+ ITResList83 = [ITRes82|ITResList82],
+
+
+ ?line {STRes207,S207} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD022.xsd','./msxsdtest/complexType',valid),
+ STResList208 = [STRes207|STResList207],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD022.xml','./msxsdtest/complexType',valid,S207),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes208,S208} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD023.xsd','./msxsdtest/complexType',valid),
+ STResList209 = [STRes208|STResList208],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD023.xml','./msxsdtest/complexType',valid,S208),
+ ITResList85 = [ITRes84|ITResList84],
+
+
+ ?line {STRes209,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD024.xsd','./msxsdtest/complexType',invalid),
+ STResList210 = [STRes209|STResList209],
+
+
+ ?line {STRes210,S210} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD025.xsd','./msxsdtest/complexType',valid),
+ STResList211 = [STRes210|STResList210],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD025.xml','./msxsdtest/complexType',valid,S210),
+ ITResList86 = [ITRes85|ITResList85],
+
+
+ ?line {STRes211,S211} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD026.xsd','./msxsdtest/complexType',valid),
+ STResList212 = [STRes211|STResList211],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD026.xml','./msxsdtest/complexType',valid,S211),
+ ITResList87 = [ITRes86|ITResList86],
+
+
+ ?line {STRes212,S212} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD027.xsd','./msxsdtest/complexType',valid),
+ STResList213 = [STRes212|STResList212],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD027.xml','./msxsdtest/complexType',valid,S212),
+ ITResList88 = [ITRes87|ITResList87],
+
+
+ ?line {STRes213,S213} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD028.xsd','./msxsdtest/complexType',valid),
+ STResList214 = [STRes213|STResList213],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD028.xml','./msxsdtest/complexType',valid,S213),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes214,S214} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD029.xsd','./msxsdtest/complexType',valid),
+ STResList215 = [STRes214|STResList214],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD029.xml','./msxsdtest/complexType',valid,S214),
+ ITResList90 = [ITRes89|ITResList89],
+
+
+ ?line {STRes215,S215} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD030.xsd','./msxsdtest/complexType',valid),
+ STResList216 = [STRes215|STResList215],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD030.xml','./msxsdtest/complexType',valid,S215),
+ ITResList91 = [ITRes90|ITResList90],
+
+
+ ?line {STRes216,S216} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD031.xsd','./msxsdtest/complexType',valid),
+ STResList217 = [STRes216|STResList216],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD031.xml','./msxsdtest/complexType',valid,S216),
+ ITResList92 = [ITRes91|ITResList91],
+
+
+ ?line {STRes217,S217} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD032.xsd','./msxsdtest/complexType',valid),
+ STResList218 = [STRes217|STResList217],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD032.xml','./msxsdtest/complexType',valid,S217),
+ ITResList93 = [ITRes92|ITResList92],
+
+
+ ?line {STRes218,S218} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD033.xsd','./msxsdtest/complexType',valid),
+ STResList219 = [STRes218|STResList218],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD033.xml','./msxsdtest/complexType',valid,S218),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes219,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD034.xsd','./msxsdtest/complexType',invalid),
+ STResList220 = [STRes219|STResList219],
+
+
+ ?line {STRes220,S220} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD035.xsd','./msxsdtest/complexType',valid),
+ STResList221 = [STRes220|STResList220],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctD035.xml','./msxsdtest/complexType',valid,S220),
+ ITResList95 = [ITRes94|ITResList94],
+
+
+ ?line {STRes221,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD036.xsd','./msxsdtest/complexType',invalid),
+ STResList222 = [STRes221|STResList221],
+
+
+ ?line {STRes222,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD037.xsd','./msxsdtest/complexType',invalid),
+ STResList223 = [STRes222|STResList222],
+
+
+ ?line {STRes223,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD038.xsd','./msxsdtest/complexType',invalid),
+ STResList224 = [STRes223|STResList223],
+
+
+ ?line {STRes224,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD039.xsd','./msxsdtest/complexType',invalid),
+ STResList225 = [STRes224|STResList224],
+
+
+ ?line {STRes225,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD040.xsd','./msxsdtest/complexType',invalid),
+ STResList226 = [STRes225|STResList225],
+
+
+ ?line {STRes226,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD041.xsd','./msxsdtest/complexType',invalid),
+ STResList227 = [STRes226|STResList226],
+
+
+ ?line {STRes227,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD042.xsd','./msxsdtest/complexType',invalid),
+ STResList228 = [STRes227|STResList227],
+
+
+ ?line {STRes228,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctD043.xsd','./msxsdtest/complexType',invalid),
+ STResList229 = [STRes228|STResList228],
+
+
+ ?line {STRes229,S229} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctE001.xsd','./msxsdtest/complexType',valid),
+ STResList230 = [STRes229|STResList229],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctE001.xml','./msxsdtest/complexType',valid,S229),
+ ITResList96 = [ITRes95|ITResList95],
+
+
+ ?line {STRes230,S230} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctE002.xsd','./msxsdtest/complexType',valid),
+ STResList231 = [STRes230|STResList230],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctE002.xml','./msxsdtest/complexType',valid,S230),
+ ITResList97 = [ITRes96|ITResList96],
+
+
+ ?line {STRes231,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctE003.xsd','./msxsdtest/complexType',invalid),
+ STResList232 = [STRes231|STResList231],
+
+
+ ?line {STRes232,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctE004.xsd','./msxsdtest/complexType',invalid),
+ STResList233 = [STRes232|STResList232],
+
+
+ ?line {STRes233,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctE005.xsd','./msxsdtest/complexType',invalid),
+ STResList234 = [STRes233|STResList233],
+
+
+ ?line {STRes234,S234} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctE006.xsd','./msxsdtest/complexType',valid),
+ STResList235 = [STRes234|STResList234],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctE006.xml','./msxsdtest/complexType',valid,S234),
+ ITResList98 = [ITRes97|ITResList97],
+
+
+ ?line {STRes235,S235} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctE007.xsd','./msxsdtest/complexType',valid),
+ STResList236 = [STRes235|STResList235],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctE007.xml','./msxsdtest/complexType',valid,S235),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes236,S236} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctE008.xsd','./msxsdtest/complexType',valid),
+ STResList237 = [STRes236|STResList236],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctE008.xml','./msxsdtest/complexType',valid,S236),
+ ITResList100 = [ITRes99|ITResList99],
+
+
+ ?line {STRes237,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctE009.xsd','./msxsdtest/complexType',invalid),
+ STResList238 = [STRes237|STResList237],
+
+
+ ?line {STRes238,S238} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctE010.xsd','./msxsdtest/complexType',valid),
+ STResList239 = [STRes238|STResList238],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctE010.xml','./msxsdtest/complexType',valid,S238),
+ ITResList101 = [ITRes100|ITResList100],
+
+
+ ?line {STRes239,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctE011.xsd','./msxsdtest/complexType',invalid),
+ STResList240 = [STRes239|STResList239],
+
+
+ ?line {STRes240,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctE012.xsd','./msxsdtest/complexType',invalid),
+ STResList241 = [STRes240|STResList240],
+
+
+ ?line {STRes241,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctE013.xsd','./msxsdtest/complexType',invalid),
+ STResList242 = [STRes241|STResList241],
+
+
+ ?line {STRes242,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctE014.xsd','./msxsdtest/complexType',invalid),
+ STResList243 = [STRes242|STResList242],
+
+
+ ?line {STRes243,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctE015.xsd','./msxsdtest/complexType',invalid),
+ STResList244 = [STRes243|STResList243],
+
+
+ ?line {STRes244,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctE016.xsd','./msxsdtest/complexType',invalid),
+ STResList245 = [STRes244|STResList244],
+
+
+ ?line {STRes245,S245} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctE017.xsd','./msxsdtest/complexType',valid),
+ STResList246 = [STRes245|STResList245],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctE017.xml','./msxsdtest/complexType',valid,S245),
+ ITResList102 = [ITRes101|ITResList101],
+
+
+ ?line {STRes246,S246} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctF001.xsd','./msxsdtest/complexType',valid),
+ STResList247 = [STRes246|STResList246],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctF001.xml','./msxsdtest/complexType',valid,S246),
+ ITResList103 = [ITRes102|ITResList102],
+
+
+ ?line {STRes247,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctF002.xsd','./msxsdtest/complexType',invalid),
+ STResList248 = [STRes247|STResList247],
+
+
+ ?line {STRes248,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctF003.xsd','./msxsdtest/complexType',invalid),
+ STResList249 = [STRes248|STResList248],
+
+
+ ?line {STRes249,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctF004.xsd','./msxsdtest/complexType',invalid),
+ STResList250 = [STRes249|STResList249],
+
+
+ ?line {STRes250,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctF005.xsd','./msxsdtest/complexType',invalid),
+ STResList251 = [STRes250|STResList250],
+
+
+ ?line {STRes251,S251} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctF006.xsd','./msxsdtest/complexType',valid),
+ STResList252 = [STRes251|STResList251],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctF006.xml','./msxsdtest/complexType',valid,S251),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes252,S252} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctF007.xsd','./msxsdtest/complexType',valid),
+ STResList253 = [STRes252|STResList252],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctF007.xml','./msxsdtest/complexType',valid,S252),
+ ITResList105 = [ITRes104|ITResList104],
+
+
+ ?line {STRes253,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctF008.xsd','./msxsdtest/complexType',invalid),
+ STResList254 = [STRes253|STResList253],
+
+
+ ?line {STRes254,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctF009.xsd','./msxsdtest/complexType',invalid),
+ STResList255 = [STRes254|STResList254],
+
+
+ ?line {STRes255,S255} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctF010.xsd','./msxsdtest/complexType',valid),
+ STResList256 = [STRes255|STResList255],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctF010.xml','./msxsdtest/complexType',valid,S255),
+ ITResList106 = [ITRes105|ITResList105],
+
+
+ ?line {STRes256,S256} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctF011.xsd','./msxsdtest/complexType',valid),
+ STResList257 = [STRes256|STResList256],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctF011.xml','./msxsdtest/complexType',valid,S256),
+ ITResList107 = [ITRes106|ITResList106],
+
+
+ ?line {STRes257,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctF012.xsd','./msxsdtest/complexType',invalid),
+ STResList258 = [STRes257|STResList257],
+
+
+ ?line {STRes258,S258} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctF013.xsd','./msxsdtest/complexType',valid),
+ STResList259 = [STRes258|STResList258],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctF013.xml','./msxsdtest/complexType',valid,S258),
+ ITResList108 = [ITRes107|ITResList107],
+
+
+ ?line {STRes259,S259} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctF014.xsd','./msxsdtest/complexType',valid),
+ STResList260 = [STRes259|STResList259],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctF014.xml','./msxsdtest/complexType',valid,S259),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes260,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctF015.xsd','./msxsdtest/complexType',invalid),
+ STResList261 = [STRes260|STResList260],
+
+
+ ?line {STRes261,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctF016.xsd','./msxsdtest/complexType',invalid),
+ STResList262 = [STRes261|STResList261],
+
+
+ ?line {STRes262,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctF017.xsd','./msxsdtest/complexType',invalid),
+ STResList263 = [STRes262|STResList262],
+
+
+ ?line {STRes263,S263} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG001.xsd','./msxsdtest/complexType',valid),
+ STResList264 = [STRes263|STResList263],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG001.xml','./msxsdtest/complexType',valid,S263),
+ ITResList110 = [ITRes109|ITResList109],
+
+
+ ?line {STRes264,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG002.xsd','./msxsdtest/complexType',invalid),
+ STResList265 = [STRes264|STResList264],
+
+
+ ?line {STRes265,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG003.xsd','./msxsdtest/complexType',invalid),
+ STResList266 = [STRes265|STResList265],
+
+
+ ?line {STRes266,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG004.xsd','./msxsdtest/complexType',invalid),
+ STResList267 = [STRes266|STResList266],
+
+
+ ?line {STRes267,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG005.xsd','./msxsdtest/complexType',invalid),
+ STResList268 = [STRes267|STResList267],
+
+
+ ?line {STRes268,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG006.xsd','./msxsdtest/complexType',invalid),
+ STResList269 = [STRes268|STResList268],
+
+
+ ?line {STRes269,S269} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG007.xsd','./msxsdtest/complexType',valid),
+ STResList270 = [STRes269|STResList269],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG007.xml','./msxsdtest/complexType',valid,S269),
+ ITResList111 = [ITRes110|ITResList110],
+
+
+ ?line {STRes270,S270} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG008.xsd','./msxsdtest/complexType',valid),
+ STResList271 = [STRes270|STResList270],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG008.xml','./msxsdtest/complexType',valid,S270),
+ ITResList112 = [ITRes111|ITResList111],
+
+
+ ?line {STRes271,S271} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG009.xsd','./msxsdtest/complexType',valid),
+ STResList272 = [STRes271|STResList271],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG009.xml','./msxsdtest/complexType',valid,S271),
+ ITResList113 = [ITRes112|ITResList112],
+
+
+ ?line {STRes272,S272} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG010.xsd','./msxsdtest/complexType',valid),
+ STResList273 = [STRes272|STResList272],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG010.xml','./msxsdtest/complexType',valid,S272),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes273,S273} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG011.xsd','./msxsdtest/complexType',valid),
+ STResList274 = [STRes273|STResList273],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG011.xml','./msxsdtest/complexType',valid,S273),
+ ITResList115 = [ITRes114|ITResList114],
+
+
+ ?line {STRes274,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG012.xsd','./msxsdtest/complexType',invalid),
+ STResList275 = [STRes274|STResList274],
+
+
+ ?line {STRes275,S275} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG013.xsd','./msxsdtest/complexType',valid),
+ STResList276 = [STRes275|STResList275],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG013.xml','./msxsdtest/complexType',valid,S275),
+ ITResList116 = [ITRes115|ITResList115],
+
+
+ ?line {STRes276,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG014.xsd','./msxsdtest/complexType',invalid),
+ STResList277 = [STRes276|STResList276],
+
+
+ ?line {STRes277,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG015.xsd','./msxsdtest/complexType',invalid),
+ STResList278 = [STRes277|STResList277],
+
+
+ ?line {STRes278,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG016.xsd','./msxsdtest/complexType',invalid),
+ STResList279 = [STRes278|STResList278],
+
+
+ ?line {STRes279,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG017.xsd','./msxsdtest/complexType',invalid),
+ STResList280 = [STRes279|STResList279],
+
+
+ ?line {STRes280,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG018.xsd','./msxsdtest/complexType',invalid),
+ STResList281 = [STRes280|STResList280],
+
+
+ ?line {STRes281,S281} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG019.xsd','./msxsdtest/complexType',valid),
+ STResList282 = [STRes281|STResList281],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG019.xml','./msxsdtest/complexType',valid,S281),
+ ITResList117 = [ITRes116|ITResList116],
+
+
+ ?line {STRes282,S282} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG020.xsd','./msxsdtest/complexType',valid),
+ STResList283 = [STRes282|STResList282],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG020.xml','./msxsdtest/complexType',valid,S282),
+ ITResList118 = [ITRes117|ITResList117],
+
+
+ ?line {STRes283,S283} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG021.xsd','./msxsdtest/complexType',valid),
+ STResList284 = [STRes283|STResList283],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG021.xml','./msxsdtest/complexType',valid,S283),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes284,S284} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG022.xsd','./msxsdtest/complexType',valid),
+ STResList285 = [STRes284|STResList284],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG022.xml','./msxsdtest/complexType',valid,S284),
+ ITResList120 = [ITRes119|ITResList119],
+
+
+ ?line {STRes285,S285} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG023.xsd','./msxsdtest/complexType',valid),
+ STResList286 = [STRes285|STResList285],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG023.xml','./msxsdtest/complexType',valid,S285),
+ ITResList121 = [ITRes120|ITResList120],
+
+
+ ?line {STRes286,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG024.xsd','./msxsdtest/complexType',invalid),
+ STResList287 = [STRes286|STResList286],
+
+
+ ?line {STRes287,S287} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG025.xsd','./msxsdtest/complexType',valid),
+ STResList288 = [STRes287|STResList287],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG025.xml','./msxsdtest/complexType',valid,S287),
+ ITResList122 = [ITRes121|ITResList121],
+
+
+ ?line {STRes288,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG026.xsd','./msxsdtest/complexType',invalid),
+ STResList289 = [STRes288|STResList288],
+
+
+ ?line {STRes289,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG027.xsd','./msxsdtest/complexType',invalid),
+ STResList290 = [STRes289|STResList289],
+
+
+ ?line {STRes290,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG028.xsd','./msxsdtest/complexType',invalid),
+ STResList291 = [STRes290|STResList290],
+
+
+ ?line {STRes291,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG029.xsd','./msxsdtest/complexType',invalid),
+ STResList292 = [STRes291|STResList291],
+
+
+ ?line {STRes292,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG030.xsd','./msxsdtest/complexType',invalid),
+ STResList293 = [STRes292|STResList292],
+
+
+ ?line {STRes293,S293} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG031.xsd','./msxsdtest/complexType',valid),
+ STResList294 = [STRes293|STResList293],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG031.xml','./msxsdtest/complexType',valid,S293),
+ ITResList123 = [ITRes122|ITResList122],
+
+
+ ?line {STRes294,S294} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG032.xsd','./msxsdtest/complexType',valid),
+ STResList295 = [STRes294|STResList294],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG032.xml','./msxsdtest/complexType',valid,S294),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes295,S295} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG033.xsd','./msxsdtest/complexType',valid),
+ STResList296 = [STRes295|STResList295],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG033.xml','./msxsdtest/complexType',valid,S295),
+ ITResList125 = [ITRes124|ITResList124],
+
+
+ ?line {STRes296,S296} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG034.xsd','./msxsdtest/complexType',valid),
+ STResList297 = [STRes296|STResList296],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG034.xml','./msxsdtest/complexType',valid,S296),
+ ITResList126 = [ITRes125|ITResList125],
+
+
+ ?line {STRes297,S297} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG035.xsd','./msxsdtest/complexType',valid),
+ STResList298 = [STRes297|STResList297],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG035.xml','./msxsdtest/complexType',valid,S297),
+ ITResList127 = [ITRes126|ITResList126],
+
+
+ ?line {STRes298,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG036.xsd','./msxsdtest/complexType',invalid),
+ STResList299 = [STRes298|STResList298],
+
+
+ ?line {STRes299,S299} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG037.xsd','./msxsdtest/complexType',valid),
+ STResList300 = [STRes299|STResList299],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG037.xml','./msxsdtest/complexType',valid,S299),
+ ITResList128 = [ITRes127|ITResList127],
+
+
+ ?line {STRes300,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG038.xsd','./msxsdtest/complexType',invalid),
+ STResList301 = [STRes300|STResList300],
+
+
+ ?line {STRes301,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG039.xsd','./msxsdtest/complexType',invalid),
+ STResList302 = [STRes301|STResList301],
+
+
+ ?line {STRes302,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG040.xsd','./msxsdtest/complexType',invalid),
+ STResList303 = [STRes302|STResList302],
+
+
+ ?line {STRes303,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG041.xsd','./msxsdtest/complexType',invalid),
+ STResList304 = [STRes303|STResList303],
+
+
+ ?line {STRes304,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG042.xsd','./msxsdtest/complexType',invalid),
+ STResList305 = [STRes304|STResList304],
+
+
+ ?line {STRes305,S305} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG043.xsd','./msxsdtest/complexType',valid),
+ STResList306 = [STRes305|STResList305],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG043.xml','./msxsdtest/complexType',valid,S305),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes306,S306} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG044.xsd','./msxsdtest/complexType',valid),
+ STResList307 = [STRes306|STResList306],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG044.xml','./msxsdtest/complexType',valid,S306),
+ ITResList130 = [ITRes129|ITResList129],
+
+
+ ?line {STRes307,S307} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG045.xsd','./msxsdtest/complexType',valid),
+ STResList308 = [STRes307|STResList307],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG045.xml','./msxsdtest/complexType',valid,S307),
+ ITResList131 = [ITRes130|ITResList130],
+
+
+ ?line {STRes308,S308} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG046.xsd','./msxsdtest/complexType',valid),
+ STResList309 = [STRes308|STResList308],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG046.xml','./msxsdtest/complexType',valid,S308),
+ ITResList132 = [ITRes131|ITResList131],
+
+
+ ?line {STRes309,S309} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG047.xsd','./msxsdtest/complexType',valid),
+ STResList310 = [STRes309|STResList309],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG047.xml','./msxsdtest/complexType',valid,S309),
+ ITResList133 = [ITRes132|ITResList132],
+
+
+ ?line {STRes310,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG048.xsd','./msxsdtest/complexType',invalid),
+ STResList311 = [STRes310|STResList310],
+
+
+ ?line {STRes311,S311} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG049.xsd','./msxsdtest/complexType',valid),
+ STResList312 = [STRes311|STResList311],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG049.xml','./msxsdtest/complexType',valid,S311),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes312,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG050.xsd','./msxsdtest/complexType',invalid),
+ STResList313 = [STRes312|STResList312],
+
+
+ ?line {STRes313,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG051.xsd','./msxsdtest/complexType',invalid),
+ STResList314 = [STRes313|STResList313],
+
+
+ ?line {STRes314,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG052.xsd','./msxsdtest/complexType',invalid),
+ STResList315 = [STRes314|STResList314],
+
+
+ ?line {STRes315,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG053.xsd','./msxsdtest/complexType',invalid),
+ STResList316 = [STRes315|STResList315],
+
+
+ ?line {STRes316,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG054.xsd','./msxsdtest/complexType',invalid),
+ STResList317 = [STRes316|STResList316],
+
+
+ ?line {STRes317,S317} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG055.xsd','./msxsdtest/complexType',valid),
+ STResList318 = [STRes317|STResList317],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG055.xml','./msxsdtest/complexType',valid,S317),
+ ITResList135 = [ITRes134|ITResList134],
+
+
+ ?line {STRes318,S318} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG056.xsd','./msxsdtest/complexType',valid),
+ STResList319 = [STRes318|STResList318],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG056.xml','./msxsdtest/complexType',valid,S318),
+ ITResList136 = [ITRes135|ITResList135],
+
+
+ ?line {STRes319,S319} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG057.xsd','./msxsdtest/complexType',valid),
+ STResList320 = [STRes319|STResList319],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG057.xml','./msxsdtest/complexType',valid,S319),
+ ITResList137 = [ITRes136|ITResList136],
+
+
+ ?line {STRes320,S320} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG058.xsd','./msxsdtest/complexType',valid),
+ STResList321 = [STRes320|STResList320],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG058.xml','./msxsdtest/complexType',valid,S320),
+ ITResList138 = [ITRes137|ITResList137],
+
+
+ ?line {STRes321,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG059.xsd','./msxsdtest/complexType',invalid),
+ STResList322 = [STRes321|STResList321],
+
+
+ ?line {STRes322,S322} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG060.xsd','./msxsdtest/complexType',valid),
+ STResList323 = [STRes322|STResList322],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG060.xml','./msxsdtest/complexType',valid,S322),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ ?line {STRes323,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG061.xsd','./msxsdtest/complexType',invalid),
+ STResList324 = [STRes323|STResList323],
+
+
+ ?line {STRes324,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG062.xsd','./msxsdtest/complexType',invalid),
+ STResList325 = [STRes324|STResList324],
+
+
+ ?line {STRes325,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG063.xsd','./msxsdtest/complexType',invalid),
+ STResList326 = [STRes325|STResList325],
+
+
+ ?line {STRes326,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG064.xsd','./msxsdtest/complexType',invalid),
+ STResList327 = [STRes326|STResList326],
+
+
+ ?line {STRes327,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG065.xsd','./msxsdtest/complexType',invalid),
+ STResList328 = [STRes327|STResList327],
+
+
+ ?line {STRes328,S328} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG066.xsd','./msxsdtest/complexType',valid),
+ STResList329 = [STRes328|STResList328],
+ ?line ITRes139 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG066.xml','./msxsdtest/complexType',valid,S328),
+ ITResList140 = [ITRes139|ITResList139],
+
+
+ ?line {STRes329,S329} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG067.xsd','./msxsdtest/complexType',valid),
+ STResList330 = [STRes329|STResList329],
+ ?line ITRes140 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG067.xml','./msxsdtest/complexType',valid,S329),
+ ITResList141 = [ITRes140|ITResList140],
+
+
+ ?line {STRes330,S330} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG068.xsd','./msxsdtest/complexType',valid),
+ STResList331 = [STRes330|STResList330],
+ ?line ITRes141 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG068.xml','./msxsdtest/complexType',valid,S330),
+ ITResList142 = [ITRes141|ITResList141],
+
+
+ ?line {STRes331,S331} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG069.xsd','./msxsdtest/complexType',valid),
+ STResList332 = [STRes331|STResList331],
+ ?line ITRes142 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG069.xml','./msxsdtest/complexType',valid,S331),
+ ITResList143 = [ITRes142|ITResList142],
+
+
+ ?line {STRes332,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG070.xsd','./msxsdtest/complexType',invalid),
+ STResList333 = [STRes332|STResList332],
+
+
+ ?line {STRes333,S333} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG071.xsd','./msxsdtest/complexType',valid),
+ STResList334 = [STRes333|STResList333],
+ ?line ITRes143 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctG071.xml','./msxsdtest/complexType',valid,S333),
+ ITResList144 = [ITRes143|ITResList143],
+
+
+ ?line {STRes334,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG072.xsd','./msxsdtest/complexType',invalid),
+ STResList335 = [STRes334|STResList334],
+
+
+ ?line {STRes335,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG073.xsd','./msxsdtest/complexType',invalid),
+ STResList336 = [STRes335|STResList335],
+
+
+ ?line {STRes336,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG074.xsd','./msxsdtest/complexType',invalid),
+ STResList337 = [STRes336|STResList336],
+
+
+ ?line {STRes337,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG075.xsd','./msxsdtest/complexType',invalid),
+ STResList338 = [STRes337|STResList337],
+
+
+ ?line {STRes338,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG076.xsd','./msxsdtest/complexType',invalid),
+ STResList339 = [STRes338|STResList338],
+
+
+ ?line {STRes339,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG077.xsd','./msxsdtest/complexType',invalid),
+ STResList340 = [STRes339|STResList339],
+
+
+ ?line {STRes340,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG078.xsd','./msxsdtest/complexType',invalid),
+ STResList341 = [STRes340|STResList340],
+
+
+ ?line {STRes341,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG079.xsd','./msxsdtest/complexType',invalid),
+ STResList342 = [STRes341|STResList341],
+
+
+ ?line {STRes342,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG080.xsd','./msxsdtest/complexType',invalid),
+ STResList343 = [STRes342|STResList342],
+
+
+ ?line {STRes343,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctG081.xsd','./msxsdtest/complexType',invalid),
+ STResList344 = [STRes343|STResList343],
+
+
+ ?line {STRes344,S344} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH001.xsd','./msxsdtest/complexType',valid),
+ STResList345 = [STRes344|STResList344],
+ ?line ITRes144 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH001.xml','./msxsdtest/complexType',valid,S344),
+ ITResList145 = [ITRes144|ITResList144],
+
+
+ ?line {STRes345,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH002.xsd','./msxsdtest/complexType',invalid),
+ STResList346 = [STRes345|STResList345],
+
+
+ ?line {STRes346,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH003.xsd','./msxsdtest/complexType',invalid),
+ STResList347 = [STRes346|STResList346],
+
+
+ ?line {STRes347,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH004.xsd','./msxsdtest/complexType',invalid),
+ STResList348 = [STRes347|STResList347],
+
+
+ ?line {STRes348,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH005.xsd','./msxsdtest/complexType',invalid),
+ STResList349 = [STRes348|STResList348],
+
+
+ ?line {STRes349,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH006.xsd','./msxsdtest/complexType',invalid),
+ STResList350 = [STRes349|STResList349],
+
+
+ ?line {STRes350,S350} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH007.xsd','./msxsdtest/complexType',valid),
+ STResList351 = [STRes350|STResList350],
+ ?line ITRes145 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH007.xml','./msxsdtest/complexType',valid,S350),
+ ITResList146 = [ITRes145|ITResList145],
+
+
+ ?line {STRes351,S351} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH008.xsd','./msxsdtest/complexType',valid),
+ STResList352 = [STRes351|STResList351],
+ ?line ITRes146 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH008.xml','./msxsdtest/complexType',valid,S351),
+ ITResList147 = [ITRes146|ITResList146],
+
+
+ ?line {STRes352,S352} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH009.xsd','./msxsdtest/complexType',valid),
+ STResList353 = [STRes352|STResList352],
+ ?line ITRes147 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH009.xml','./msxsdtest/complexType',valid,S352),
+ ITResList148 = [ITRes147|ITResList147],
+
+
+ ?line {STRes353,S353} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH010.xsd','./msxsdtest/complexType',valid),
+ STResList354 = [STRes353|STResList353],
+ ?line ITRes148 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH010.xml','./msxsdtest/complexType',valid,S353),
+ ITResList149 = [ITRes148|ITResList148],
+
+
+ ?line {STRes354,S354} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH011.xsd','./msxsdtest/complexType',valid),
+ STResList355 = [STRes354|STResList354],
+ ?line ITRes149 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH011.xml','./msxsdtest/complexType',valid,S354),
+ ITResList150 = [ITRes149|ITResList149],
+
+
+ ?line {STRes355,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH012.xsd','./msxsdtest/complexType',invalid),
+ STResList356 = [STRes355|STResList355],
+
+
+ ?line {STRes356,S356} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH013.xsd','./msxsdtest/complexType',valid),
+ STResList357 = [STRes356|STResList356],
+ ?line ITRes150 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH013.xml','./msxsdtest/complexType',valid,S356),
+ ITResList151 = [ITRes150|ITResList150],
+
+
+ ?line {STRes357,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH014.xsd','./msxsdtest/complexType',invalid),
+ STResList358 = [STRes357|STResList357],
+
+
+ ?line {STRes358,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH015.xsd','./msxsdtest/complexType',invalid),
+ STResList359 = [STRes358|STResList358],
+
+
+ ?line {STRes359,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH016.xsd','./msxsdtest/complexType',invalid),
+ STResList360 = [STRes359|STResList359],
+
+
+ ?line {STRes360,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH017.xsd','./msxsdtest/complexType',invalid),
+ STResList361 = [STRes360|STResList360],
+
+
+ ?line {STRes361,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH018.xsd','./msxsdtest/complexType',invalid),
+ STResList362 = [STRes361|STResList361],
+
+
+ ?line {STRes362,S362} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH019.xsd','./msxsdtest/complexType',valid),
+ STResList363 = [STRes362|STResList362],
+ ?line ITRes151 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH019.xml','./msxsdtest/complexType',valid,S362),
+ ITResList152 = [ITRes151|ITResList151],
+
+
+ ?line {STRes363,S363} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH020.xsd','./msxsdtest/complexType',valid),
+ STResList364 = [STRes363|STResList363],
+ ?line ITRes152 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH020.xml','./msxsdtest/complexType',valid,S363),
+ ITResList153 = [ITRes152|ITResList152],
+
+
+ ?line {STRes364,S364} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH021.xsd','./msxsdtest/complexType',valid),
+ STResList365 = [STRes364|STResList364],
+ ?line ITRes153 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH021.xml','./msxsdtest/complexType',valid,S364),
+ ITResList154 = [ITRes153|ITResList153],
+
+
+ ?line {STRes365,S365} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH022.xsd','./msxsdtest/complexType',valid),
+ STResList366 = [STRes365|STResList365],
+ ?line ITRes154 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH022.xml','./msxsdtest/complexType',valid,S365),
+ ITResList155 = [ITRes154|ITResList154],
+
+
+ ?line {STRes366,S366} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH023.xsd','./msxsdtest/complexType',valid),
+ STResList367 = [STRes366|STResList366],
+ ?line ITRes155 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH023.xml','./msxsdtest/complexType',valid,S366),
+ ITResList156 = [ITRes155|ITResList155],
+
+
+ ?line {STRes367,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH024.xsd','./msxsdtest/complexType',invalid),
+ STResList368 = [STRes367|STResList367],
+
+
+ ?line {STRes368,S368} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH025.xsd','./msxsdtest/complexType',valid),
+ STResList369 = [STRes368|STResList368],
+ ?line ITRes156 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH025.xml','./msxsdtest/complexType',valid,S368),
+ ITResList157 = [ITRes156|ITResList156],
+
+
+ ?line {STRes369,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH026.xsd','./msxsdtest/complexType',invalid),
+ STResList370 = [STRes369|STResList369],
+
+
+ ?line {STRes370,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH027.xsd','./msxsdtest/complexType',invalid),
+ STResList371 = [STRes370|STResList370],
+
+
+ ?line {STRes371,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH028.xsd','./msxsdtest/complexType',invalid),
+ STResList372 = [STRes371|STResList371],
+
+
+ ?line {STRes372,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH029.xsd','./msxsdtest/complexType',invalid),
+ STResList373 = [STRes372|STResList372],
+
+
+ ?line {STRes373,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH030.xsd','./msxsdtest/complexType',invalid),
+ STResList374 = [STRes373|STResList373],
+
+
+ ?line {STRes374,S374} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH031.xsd','./msxsdtest/complexType',valid),
+ STResList375 = [STRes374|STResList374],
+ ?line ITRes157 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH031.xml','./msxsdtest/complexType',valid,S374),
+ ITResList158 = [ITRes157|ITResList157],
+
+
+ ?line {STRes375,S375} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH032.xsd','./msxsdtest/complexType',valid),
+ STResList376 = [STRes375|STResList375],
+ ?line ITRes158 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH032.xml','./msxsdtest/complexType',valid,S375),
+ ITResList159 = [ITRes158|ITResList158],
+
+
+ ?line {STRes376,S376} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH033.xsd','./msxsdtest/complexType',valid),
+ STResList377 = [STRes376|STResList376],
+ ?line ITRes159 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH033.xml','./msxsdtest/complexType',valid,S376),
+ ITResList160 = [ITRes159|ITResList159],
+
+
+ ?line {STRes377,S377} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH034.xsd','./msxsdtest/complexType',valid),
+ STResList378 = [STRes377|STResList377],
+ ?line ITRes160 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH034.xml','./msxsdtest/complexType',valid,S377),
+ ITResList161 = [ITRes160|ITResList160],
+
+
+ ?line {STRes378,S378} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH035.xsd','./msxsdtest/complexType',valid),
+ STResList379 = [STRes378|STResList378],
+ ?line ITRes161 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH035.xml','./msxsdtest/complexType',valid,S378),
+ ITResList162 = [ITRes161|ITResList161],
+
+
+ ?line {STRes379,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH036.xsd','./msxsdtest/complexType',invalid),
+ STResList380 = [STRes379|STResList379],
+
+
+ ?line {STRes380,S380} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH037.xsd','./msxsdtest/complexType',valid),
+ STResList381 = [STRes380|STResList380],
+ ?line ITRes162 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH037.xml','./msxsdtest/complexType',valid,S380),
+ ITResList163 = [ITRes162|ITResList162],
+
+
+ ?line {STRes381,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH038.xsd','./msxsdtest/complexType',invalid),
+ STResList382 = [STRes381|STResList381],
+
+
+ ?line {STRes382,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH039.xsd','./msxsdtest/complexType',invalid),
+ STResList383 = [STRes382|STResList382],
+
+
+ ?line {STRes383,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH040.xsd','./msxsdtest/complexType',invalid),
+ STResList384 = [STRes383|STResList383],
+
+
+ ?line {STRes384,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH041.xsd','./msxsdtest/complexType',invalid),
+ STResList385 = [STRes384|STResList384],
+
+
+ ?line {STRes385,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH042.xsd','./msxsdtest/complexType',invalid),
+ STResList386 = [STRes385|STResList385],
+
+
+ ?line {STRes386,S386} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH043.xsd','./msxsdtest/complexType',valid),
+ STResList387 = [STRes386|STResList386],
+ ?line ITRes163 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH043.xml','./msxsdtest/complexType',valid,S386),
+ ITResList164 = [ITRes163|ITResList163],
+
+
+ ?line {STRes387,S387} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH044.xsd','./msxsdtest/complexType',valid),
+ STResList388 = [STRes387|STResList387],
+ ?line ITRes164 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH044.xml','./msxsdtest/complexType',valid,S387),
+ ITResList165 = [ITRes164|ITResList164],
+
+
+ ?line {STRes388,S388} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH045.xsd','./msxsdtest/complexType',valid),
+ STResList389 = [STRes388|STResList388],
+ ?line ITRes165 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH045.xml','./msxsdtest/complexType',valid,S388),
+ ITResList166 = [ITRes165|ITResList165],
+
+
+ ?line {STRes389,S389} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH046.xsd','./msxsdtest/complexType',valid),
+ STResList390 = [STRes389|STResList389],
+ ?line ITRes166 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH046.xml','./msxsdtest/complexType',valid,S389),
+ ITResList167 = [ITRes166|ITResList166],
+
+
+ ?line {STRes390,S390} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH047.xsd','./msxsdtest/complexType',valid),
+ STResList391 = [STRes390|STResList390],
+ ?line ITRes167 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH047.xml','./msxsdtest/complexType',valid,S390),
+ ITResList168 = [ITRes167|ITResList167],
+
+
+ ?line {STRes391,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH048.xsd','./msxsdtest/complexType',invalid),
+ STResList392 = [STRes391|STResList391],
+
+
+ ?line {STRes392,S392} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH049.xsd','./msxsdtest/complexType',valid),
+ STResList393 = [STRes392|STResList392],
+ ?line ITRes168 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH049.xml','./msxsdtest/complexType',valid,S392),
+ ITResList169 = [ITRes168|ITResList168],
+
+
+ ?line {STRes393,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH050.xsd','./msxsdtest/complexType',invalid),
+ STResList394 = [STRes393|STResList393],
+
+
+ ?line {STRes394,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH051.xsd','./msxsdtest/complexType',invalid),
+ STResList395 = [STRes394|STResList394],
+
+
+ ?line {STRes395,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH052.xsd','./msxsdtest/complexType',invalid),
+ STResList396 = [STRes395|STResList395],
+
+
+ ?line {STRes396,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH053.xsd','./msxsdtest/complexType',invalid),
+ STResList397 = [STRes396|STResList396],
+
+
+ ?line {STRes397,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH054.xsd','./msxsdtest/complexType',invalid),
+ STResList398 = [STRes397|STResList397],
+
+
+ ?line {STRes398,S398} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH055.xsd','./msxsdtest/complexType',valid),
+ STResList399 = [STRes398|STResList398],
+ ?line ITRes169 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH055.xml','./msxsdtest/complexType',valid,S398),
+ ITResList170 = [ITRes169|ITResList169],
+
+
+ ?line {STRes399,S399} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH056.xsd','./msxsdtest/complexType',valid),
+ STResList400 = [STRes399|STResList399],
+ ?line ITRes170 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH056.xml','./msxsdtest/complexType',valid,S399),
+ ITResList171 = [ITRes170|ITResList170],
+
+
+ ?line {STRes400,S400} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH057.xsd','./msxsdtest/complexType',valid),
+ STResList401 = [STRes400|STResList400],
+ ?line ITRes171 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH057.xml','./msxsdtest/complexType',valid,S400),
+ ITResList172 = [ITRes171|ITResList171],
+
+
+ ?line {STRes401,S401} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH058.xsd','./msxsdtest/complexType',valid),
+ STResList402 = [STRes401|STResList401],
+ ?line ITRes172 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH058.xml','./msxsdtest/complexType',valid,S401),
+ ITResList173 = [ITRes172|ITResList172],
+
+
+ ?line {STRes402,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH059.xsd','./msxsdtest/complexType',invalid),
+ STResList403 = [STRes402|STResList402],
+
+
+ ?line {STRes403,S403} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH060.xsd','./msxsdtest/complexType',valid),
+ STResList404 = [STRes403|STResList403],
+ ?line ITRes173 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH060.xml','./msxsdtest/complexType',valid,S403),
+ ITResList174 = [ITRes173|ITResList173],
+
+
+ ?line {STRes404,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH061.xsd','./msxsdtest/complexType',invalid),
+ STResList405 = [STRes404|STResList404],
+
+
+ ?line {STRes405,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH062.xsd','./msxsdtest/complexType',invalid),
+ STResList406 = [STRes405|STResList405],
+
+
+ ?line {STRes406,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH063.xsd','./msxsdtest/complexType',invalid),
+ STResList407 = [STRes406|STResList406],
+
+
+ ?line {STRes407,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH064.xsd','./msxsdtest/complexType',invalid),
+ STResList408 = [STRes407|STResList407],
+
+
+ ?line {STRes408,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH065.xsd','./msxsdtest/complexType',invalid),
+ STResList409 = [STRes408|STResList408],
+
+
+ ?line {STRes409,S409} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH066.xsd','./msxsdtest/complexType',valid),
+ STResList410 = [STRes409|STResList409],
+ ?line ITRes174 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH066.xml','./msxsdtest/complexType',valid,S409),
+ ITResList175 = [ITRes174|ITResList174],
+
+
+ ?line {STRes410,S410} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH067.xsd','./msxsdtest/complexType',valid),
+ STResList411 = [STRes410|STResList410],
+ ?line ITRes175 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH067.xml','./msxsdtest/complexType',valid,S410),
+ ITResList176 = [ITRes175|ITResList175],
+
+
+ ?line {STRes411,S411} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH068.xsd','./msxsdtest/complexType',valid),
+ STResList412 = [STRes411|STResList411],
+ ?line ITRes176 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH068.xml','./msxsdtest/complexType',valid,S411),
+ ITResList177 = [ITRes176|ITResList176],
+
+
+ ?line {STRes412,S412} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH069.xsd','./msxsdtest/complexType',valid),
+ STResList413 = [STRes412|STResList412],
+ ?line ITRes177 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH069.xml','./msxsdtest/complexType',valid,S412),
+ ITResList178 = [ITRes177|ITResList177],
+
+
+ ?line {STRes413,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH070.xsd','./msxsdtest/complexType',invalid),
+ STResList414 = [STRes413|STResList413],
+
+
+ ?line {STRes414,S414} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH071.xsd','./msxsdtest/complexType',valid),
+ STResList415 = [STRes414|STResList414],
+ ?line ITRes178 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH071.xml','./msxsdtest/complexType',valid,S414),
+ ITResList179 = [ITRes178|ITResList178],
+
+
+ ?line {STRes415,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH072.xsd','./msxsdtest/complexType',invalid),
+ STResList416 = [STRes415|STResList415],
+
+
+ ?line {STRes416,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH073.xsd','./msxsdtest/complexType',invalid),
+ STResList417 = [STRes416|STResList416],
+
+
+ ?line {STRes417,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH074.xsd','./msxsdtest/complexType',invalid),
+ STResList418 = [STRes417|STResList417],
+
+
+ ?line {STRes418,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH075.xsd','./msxsdtest/complexType',invalid),
+ STResList419 = [STRes418|STResList418],
+
+
+ ?line {STRes419,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH076.xsd','./msxsdtest/complexType',invalid),
+ STResList420 = [STRes419|STResList419],
+
+
+ ?line {STRes420,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH077.xsd','./msxsdtest/complexType',invalid),
+ STResList421 = [STRes420|STResList420],
+
+
+ ?line {STRes421,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH078.xsd','./msxsdtest/complexType',invalid),
+ STResList422 = [STRes421|STResList421],
+
+
+ ?line {STRes422,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH079.xsd','./msxsdtest/complexType',invalid),
+ STResList423 = [STRes422|STResList422],
+
+
+ ?line {STRes423,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH080.xsd','./msxsdtest/complexType',invalid),
+ STResList424 = [STRes423|STResList423],
+
+
+ ?line {STRes424,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH081.xsd','./msxsdtest/complexType',invalid),
+ STResList425 = [STRes424|STResList424],
+
+
+ ?line {STRes425,S425} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctH082.xsd','./msxsdtest/complexType',valid),
+ STResList426 = [STRes425|STResList425],
+ ?line ITRes179 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctH082.xml','./msxsdtest/complexType',valid,S425),
+ ITResList180 = [ITRes179|ITResList179],
+
+
+ ?line {STRes426,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI001.xsd','./msxsdtest/complexType',invalid),
+ STResList427 = [STRes426|STResList426],
+
+
+ ?line {STRes427,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI002.xsd','./msxsdtest/complexType',invalid),
+ STResList428 = [STRes427|STResList427],
+
+
+ ?line {STRes428,S428} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI003.xsd','./msxsdtest/complexType',valid),
+ STResList429 = [STRes428|STResList428],
+ ?line ITRes180 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI003.xml','./msxsdtest/complexType',valid,S428),
+ ITResList181 = [ITRes180|ITResList180],
+
+
+ ?line {STRes429,S429} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI004.xsd','./msxsdtest/complexType',valid),
+ STResList430 = [STRes429|STResList429],
+ ?line ITRes181 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI004.xml','./msxsdtest/complexType',valid,S429),
+ ITResList182 = [ITRes181|ITResList181],
+
+
+ ?line {STRes430,S430} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI005.xsd','./msxsdtest/complexType',valid),
+ STResList431 = [STRes430|STResList430],
+ ?line ITRes182 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI005.xml','./msxsdtest/complexType',valid,S430),
+ ITResList183 = [ITRes182|ITResList182],
+
+
+ ?line {STRes431,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI006.xsd','./msxsdtest/complexType',invalid),
+ STResList432 = [STRes431|STResList431],
+
+
+ ?line {STRes432,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI007.xsd','./msxsdtest/complexType',invalid),
+ STResList433 = [STRes432|STResList432],
+
+
+ ?line {STRes433,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI008.xsd','./msxsdtest/complexType',invalid),
+ STResList434 = [STRes433|STResList433],
+
+
+ ?line {STRes434,S434} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI009.xsd','./msxsdtest/complexType',valid),
+ STResList435 = [STRes434|STResList434],
+ ?line ITRes183 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI009.xml','./msxsdtest/complexType',valid,S434),
+ ITResList184 = [ITRes183|ITResList183],
+
+
+ ?line {STRes435,S435} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI010.xsd','./msxsdtest/complexType',valid),
+ STResList436 = [STRes435|STResList435],
+ ?line ITRes184 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI010.xml','./msxsdtest/complexType',valid,S435),
+ ITResList185 = [ITRes184|ITResList184],
+
+
+ ?line {STRes436,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI011.xsd','./msxsdtest/complexType',invalid),
+ STResList437 = [STRes436|STResList436],
+
+
+ ?line {STRes437,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI012.xsd','./msxsdtest/complexType',invalid),
+ STResList438 = [STRes437|STResList437],
+
+
+ ?line {STRes438,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI013.xsd','./msxsdtest/complexType',invalid),
+ STResList439 = [STRes438|STResList438],
+
+
+ ?line {STRes439,S439} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI014.xsd','./msxsdtest/complexType',valid),
+ STResList440 = [STRes439|STResList439],
+ ?line ITRes185 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI014.xml','./msxsdtest/complexType',valid,S439),
+ ITResList186 = [ITRes185|ITResList185],
+
+
+ ?line {STRes440,S440} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI015.xsd','./msxsdtest/complexType',valid),
+ STResList441 = [STRes440|STResList440],
+ ?line ITRes186 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI015.xml','./msxsdtest/complexType',valid,S440),
+ ITResList187 = [ITRes186|ITResList186],
+
+
+ ?line {STRes441,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI016.xsd','./msxsdtest/complexType',invalid),
+ STResList442 = [STRes441|STResList441],
+
+
+ ?line {STRes442,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI017.xsd','./msxsdtest/complexType',invalid),
+ STResList443 = [STRes442|STResList442],
+
+
+ ?line {STRes443,S443} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI018.xsd','./msxsdtest/complexType',valid),
+ STResList444 = [STRes443|STResList443],
+ ?line ITRes187 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI018.xml','./msxsdtest/complexType',valid,S443),
+ ITResList188 = [ITRes187|ITResList187],
+
+
+ ?line {STRes444,S444} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI019.xsd','./msxsdtest/complexType',valid),
+ STResList445 = [STRes444|STResList444],
+ ?line ITRes188 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI019.xml','./msxsdtest/complexType',valid,S444),
+ ITResList189 = [ITRes188|ITResList188],
+
+
+ ?line {STRes445,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI020.xsd','./msxsdtest/complexType',invalid),
+ STResList446 = [STRes445|STResList445],
+
+
+ ?line {STRes446,S446} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI021.xsd','./msxsdtest/complexType',valid),
+ STResList447 = [STRes446|STResList446],
+ ?line ITRes189 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI021.xml','./msxsdtest/complexType',valid,S446),
+ ITResList190 = [ITRes189|ITResList189],
+
+
+ ?line {STRes447,S447} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI022.xsd','./msxsdtest/complexType',valid),
+ STResList448 = [STRes447|STResList447],
+ ?line ITRes190 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI022.xml','./msxsdtest/complexType',valid,S447),
+ ITResList191 = [ITRes190|ITResList190],
+
+
+ ?line {STRes448,S448} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI023.xsd','./msxsdtest/complexType',valid),
+ STResList449 = [STRes448|STResList448],
+ ?line ITRes191 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI023.xml','./msxsdtest/complexType',valid,S448),
+ ITResList192 = [ITRes191|ITResList191],
+
+
+ ?line {STRes449,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI024.xsd','./msxsdtest/complexType',invalid),
+ STResList450 = [STRes449|STResList449],
+
+
+ ?line {STRes450,S450} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI025.xsd','./msxsdtest/complexType',valid),
+ STResList451 = [STRes450|STResList450],
+ ?line ITRes192 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI025.xml','./msxsdtest/complexType',valid,S450),
+ ITResList193 = [ITRes192|ITResList192],
+
+
+ ?line {STRes451,S451} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI026.xsd','./msxsdtest/complexType',valid),
+ STResList452 = [STRes451|STResList451],
+ ?line ITRes193 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI026.xml','./msxsdtest/complexType',valid,S451),
+ ITResList194 = [ITRes193|ITResList193],
+
+
+ ?line {STRes452,S452} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI027.xsd','./msxsdtest/complexType',valid),
+ STResList453 = [STRes452|STResList452],
+ ?line ITRes194 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI027.xml','./msxsdtest/complexType',valid,S452),
+ ITResList195 = [ITRes194|ITResList194],
+
+
+ ?line {STRes453,S453} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI028.xsd','./msxsdtest/complexType',valid),
+ STResList454 = [STRes453|STResList453],
+ ?line ITRes195 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI028.xml','./msxsdtest/complexType',valid,S453),
+ ITResList196 = [ITRes195|ITResList195],
+
+
+ ?line {STRes454,S454} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI029.xsd','./msxsdtest/complexType',valid),
+ STResList455 = [STRes454|STResList454],
+ ?line ITRes196 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI029.xml','./msxsdtest/complexType',valid,S454),
+ ITResList197 = [ITRes196|ITResList196],
+
+
+ ?line {STRes455,S455} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI030.xsd','./msxsdtest/complexType',valid),
+ STResList456 = [STRes455|STResList455],
+ ?line ITRes197 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI030.xml','./msxsdtest/complexType',invalid,S455),
+ ITResList198 = [ITRes197|ITResList197],
+
+
+ ?line {STRes456,S456} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI031.xsd','./msxsdtest/complexType',valid),
+ STResList457 = [STRes456|STResList456],
+ ?line ITRes198 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI031.xml','./msxsdtest/complexType',invalid,S456),
+ ITResList199 = [ITRes198|ITResList198],
+
+
+ ?line {STRes457,S457} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI032.xsd','./msxsdtest/complexType',valid),
+ STResList458 = [STRes457|STResList457],
+ ?line ITRes199 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI032.xml','./msxsdtest/complexType',invalid,S457),
+ ITResList200 = [ITRes199|ITResList199],
+
+
+ ?line {STRes458,S458} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI033.xsd','./msxsdtest/complexType',valid),
+ STResList459 = [STRes458|STResList458],
+ ?line ITRes200 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI033.xml','./msxsdtest/complexType',valid,S458),
+ ITResList201 = [ITRes200|ITResList200],
+
+
+ ?line {STRes459,S459} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI034.xsd','./msxsdtest/complexType',valid),
+ STResList460 = [STRes459|STResList459],
+ ?line ITRes201 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI034.xml','./msxsdtest/complexType',valid,S459),
+ ITResList202 = [ITRes201|ITResList201],
+
+
+ ?line {STRes460,S460} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI035.xsd','./msxsdtest/complexType',valid),
+ STResList461 = [STRes460|STResList460],
+ ?line ITRes202 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI035.xml','./msxsdtest/complexType',invalid,S460),
+ ITResList203 = [ITRes202|ITResList202],
+
+
+ ?line {STRes461,S461} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI036.xsd','./msxsdtest/complexType',valid),
+ STResList462 = [STRes461|STResList461],
+ ?line ITRes203 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI036.xml','./msxsdtest/complexType',valid,S461),
+ ITResList204 = [ITRes203|ITResList203],
+
+
+ ?line {STRes462,S462} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI037.xsd','./msxsdtest/complexType',valid),
+ STResList463 = [STRes462|STResList462],
+ ?line ITRes204 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI037.xml','./msxsdtest/complexType',valid,S462),
+ ITResList205 = [ITRes204|ITResList204],
+
+
+ ?line {STRes463,S463} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI038.xsd','./msxsdtest/complexType',valid),
+ STResList464 = [STRes463|STResList463],
+ ?line ITRes205 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI038.xml','./msxsdtest/complexType',invalid,S463),
+ ITResList206 = [ITRes205|ITResList205],
+
+
+ ?line {STRes464,S464} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI039.xsd','./msxsdtest/complexType',valid),
+ STResList465 = [STRes464|STResList464],
+ ?line ITRes206 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI039.xml','./msxsdtest/complexType',invalid,S464),
+ ITResList207 = [ITRes206|ITResList206],
+
+
+ ?line {STRes465,S465} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI040.xsd','./msxsdtest/complexType',valid),
+ STResList466 = [STRes465|STResList465],
+ ?line ITRes207 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI040.xml','./msxsdtest/complexType',valid,S465),
+ ITResList208 = [ITRes207|ITResList207],
+
+
+ ?line {STRes466,S466} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI041.xsd','./msxsdtest/complexType',valid),
+ STResList467 = [STRes466|STResList466],
+ ?line ITRes208 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI041.xml','./msxsdtest/complexType',valid,S466),
+ ITResList209 = [ITRes208|ITResList208],
+
+
+ ?line {STRes467,S467} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI042.xsd','./msxsdtest/complexType',valid),
+ STResList468 = [STRes467|STResList467],
+ ?line ITRes209 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI042.xml','./msxsdtest/complexType',invalid,S467),
+ ITResList210 = [ITRes209|ITResList209],
+
+
+ ?line {STRes468,S468} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI043.xsd','./msxsdtest/complexType',valid),
+ STResList469 = [STRes468|STResList468],
+ ?line ITRes210 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI043.xml','./msxsdtest/complexType',valid,S468),
+ ITResList211 = [ITRes210|ITResList210],
+
+
+ ?line {STRes469,S469} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI044.xsd','./msxsdtest/complexType',valid),
+ STResList470 = [STRes469|STResList469],
+ ?line ITRes211 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI044.xml','./msxsdtest/complexType',valid,S469),
+ ITResList212 = [ITRes211|ITResList211],
+
+
+ ?line {STRes470,S470} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI045.xsd','./msxsdtest/complexType',valid),
+ STResList471 = [STRes470|STResList470],
+ ?line ITRes212 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI045.xml','./msxsdtest/complexType',invalid,S470),
+ ITResList213 = [ITRes212|ITResList212],
+
+
+ ?line {STRes471,S471} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI046.xsd','./msxsdtest/complexType',valid),
+ STResList472 = [STRes471|STResList471],
+ ?line ITRes213 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI046.xml','./msxsdtest/complexType',valid,S471),
+ ITResList214 = [ITRes213|ITResList213],
+
+
+ ?line {STRes472,S472} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI047.xsd','./msxsdtest/complexType',valid),
+ STResList473 = [STRes472|STResList472],
+ ?line ITRes214 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI047.xml','./msxsdtest/complexType',valid,S472),
+ ITResList215 = [ITRes214|ITResList214],
+
+
+ ?line {STRes473,S473} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI048.xsd','./msxsdtest/complexType',valid),
+ STResList474 = [STRes473|STResList473],
+ ?line ITRes215 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI048.xml','./msxsdtest/complexType',invalid,S473),
+ ITResList216 = [ITRes215|ITResList215],
+
+
+ ?line {STRes474,S474} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI049.xsd','./msxsdtest/complexType',valid),
+ STResList475 = [STRes474|STResList474],
+ ?line ITRes216 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI049.xml','./msxsdtest/complexType',invalid,S474),
+ ITResList217 = [ITRes216|ITResList216],
+
+
+ ?line {STRes475,S475} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctI050.xsd','./msxsdtest/complexType',valid),
+ STResList476 = [STRes475|STResList475],
+ ?line ITRes217 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctI050.xml','./msxsdtest/complexType',valid,S475),
+ ITResList218 = [ITRes217|ITResList217],
+
+
+ ?line {STRes476,S476} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctJ001.xsd','./msxsdtest/complexType',valid),
+ STResList477 = [STRes476|STResList476],
+ ?line ITRes218 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctJ001.xml','./msxsdtest/complexType',valid,S476),
+ ITResList219 = [ITRes218|ITResList218],
+
+
+ ?line {STRes477,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctJ002.xsd','./msxsdtest/complexType',invalid),
+ STResList478 = [STRes477|STResList477],
+
+
+ ?line {STRes478,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctJ003.xsd','./msxsdtest/complexType',invalid),
+ STResList479 = [STRes478|STResList478],
+
+
+ ?line {STRes479,S479} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctK001.xsd','./msxsdtest/complexType',valid),
+ STResList480 = [STRes479|STResList479],
+ ?line ITRes219 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctK001.xml','./msxsdtest/complexType',valid,S479),
+ ITResList220 = [ITRes219|ITResList219],
+
+
+ ?line {STRes480,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctK002.xsd','./msxsdtest/complexType',invalid),
+ STResList481 = [STRes480|STResList480],
+
+
+ ?line {STRes481,S481} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL001.xsd','./msxsdtest/complexType',valid),
+ STResList482 = [STRes481|STResList481],
+ ?line ITRes220 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL001.xml','./msxsdtest/complexType',invalid,S481),
+ ITResList221 = [ITRes220|ITResList220],
+
+
+ ?line {STRes482,S482} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL002.xsd','./msxsdtest/complexType',valid),
+ STResList483 = [STRes482|STResList482],
+ ?line ITRes221 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL002.xml','./msxsdtest/complexType',invalid,S482),
+ ITResList222 = [ITRes221|ITResList221],
+
+
+ ?line {STRes483,S483} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL003.xsd','./msxsdtest/complexType',valid),
+ STResList484 = [STRes483|STResList483],
+ ?line ITRes222 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL003.xml','./msxsdtest/complexType',valid,S483),
+ ITResList223 = [ITRes222|ITResList222],
+
+
+ ?line {STRes484,S484} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL004.xsd','./msxsdtest/complexType',valid),
+ STResList485 = [STRes484|STResList484],
+ ?line ITRes223 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL004.xml','./msxsdtest/complexType',invalid,S484),
+ ITResList224 = [ITRes223|ITResList223],
+
+
+ ?line {STRes485,S485} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL005.xsd','./msxsdtest/complexType',valid),
+ STResList486 = [STRes485|STResList485],
+ ?line ITRes224 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL005.xml','./msxsdtest/complexType',valid,S485),
+ ITResList225 = [ITRes224|ITResList224],
+
+
+ ?line {STRes486,S486} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL006.xsd','./msxsdtest/complexType',valid),
+ STResList487 = [STRes486|STResList486],
+ ?line ITRes225 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL006.xml','./msxsdtest/complexType',invalid,S486),
+ ITResList226 = [ITRes225|ITResList225],
+
+
+ ?line {STRes487,S487} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL007.xsd','./msxsdtest/complexType',valid),
+ STResList488 = [STRes487|STResList487],
+ ?line ITRes226 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL007.xml','./msxsdtest/complexType',valid,S487),
+ ITResList227 = [ITRes226|ITResList226],
+
+
+ ?line {STRes488,S488} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL008.xsd','./msxsdtest/complexType',valid),
+ STResList489 = [STRes488|STResList488],
+ ?line ITRes227 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL008.xml','./msxsdtest/complexType',valid,S488),
+ ITResList228 = [ITRes227|ITResList227],
+
+
+ ?line {STRes489,S489} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL009.xsd','./msxsdtest/complexType',valid),
+ STResList490 = [STRes489|STResList489],
+ ?line ITRes228 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL009.xml','./msxsdtest/complexType',invalid,S489),
+ ITResList229 = [ITRes228|ITResList228],
+
+
+ ?line {STRes490,S490} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL010.xsd','./msxsdtest/complexType',valid),
+ STResList491 = [STRes490|STResList490],
+ ?line ITRes229 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL010.xml','./msxsdtest/complexType',invalid,S490),
+ ITResList230 = [ITRes229|ITResList229],
+
+
+ ?line {STRes491,S491} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL011.xsd','./msxsdtest/complexType',valid),
+ STResList492 = [STRes491|STResList491],
+ ?line ITRes230 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL011.xml','./msxsdtest/complexType',valid,S491),
+ ITResList231 = [ITRes230|ITResList230],
+
+
+ ?line {STRes492,S492} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL012.xsd','./msxsdtest/complexType',valid),
+ STResList493 = [STRes492|STResList492],
+ ?line ITRes231 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL012.xml','./msxsdtest/complexType',invalid,S492),
+ ITResList232 = [ITRes231|ITResList231],
+
+
+ ?line {STRes493,S493} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL013.xsd','./msxsdtest/complexType',valid),
+ STResList494 = [STRes493|STResList493],
+ ?line ITRes232 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL013.xml','./msxsdtest/complexType',invalid,S493),
+ ITResList233 = [ITRes232|ITResList232],
+
+
+ ?line {STRes494,S494} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL014.xsd','./msxsdtest/complexType',valid),
+ STResList495 = [STRes494|STResList494],
+ ?line ITRes233 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL014.xml','./msxsdtest/complexType',valid,S494),
+ ITResList234 = [ITRes233|ITResList233],
+
+
+ ?line {STRes495,S495} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL015.xsd','./msxsdtest/complexType',valid),
+ STResList496 = [STRes495|STResList495],
+ ?line ITRes234 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL015.xml','./msxsdtest/complexType',valid,S495),
+ ITResList235 = [ITRes234|ITResList234],
+
+
+ ?line {STRes496,S496} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL016.xsd','./msxsdtest/complexType',valid),
+ STResList497 = [STRes496|STResList496],
+ ?line ITRes235 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL016.xml','./msxsdtest/complexType',valid,S496),
+ ITResList236 = [ITRes235|ITResList235],
+
+
+ ?line {STRes497,S497} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL017.xsd','./msxsdtest/complexType',valid),
+ STResList498 = [STRes497|STResList497],
+ ?line ITRes236 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL017.xml','./msxsdtest/complexType',valid,S497),
+ ITResList237 = [ITRes236|ITResList236],
+
+
+ ?line {STRes498,S498} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL018.xsd','./msxsdtest/complexType',valid),
+ STResList499 = [STRes498|STResList498],
+ ?line ITRes237 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL018.xml','./msxsdtest/complexType',valid,S498),
+ ITResList238 = [ITRes237|ITResList237],
+
+
+ ?line {STRes499,S499} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL019.xsd','./msxsdtest/complexType',valid),
+ STResList500 = [STRes499|STResList499],
+ ?line ITRes238 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL019.xml','./msxsdtest/complexType',valid,S499),
+ ITResList239 = [ITRes238|ITResList238],
+
+
+ ?line {STRes500,S500} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL020.xsd','./msxsdtest/complexType',valid),
+ STResList501 = [STRes500|STResList500],
+ ?line ITRes239 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL020.xml','./msxsdtest/complexType',invalid,S500),
+ ITResList240 = [ITRes239|ITResList239],
+
+
+ ?line {STRes501,S501} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctL021.xsd','./msxsdtest/complexType',valid),
+ STResList502 = [STRes501|STResList501],
+ ?line ITRes240 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctL021.xml','./msxsdtest/complexType',valid,S501),
+ ITResList241 = [ITRes240|ITResList240],
+
+
+ ?line {STRes502,S502} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/bug67200.xsd','./msxsdtest/complexType',valid),
+ STResList503 = [STRes502|STResList502],
+ ?line ITRes241 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/bug67200.xml','./msxsdtest/complexType',valid,S502),
+ ITResList242 = [ITRes241|ITResList241],
+
+
+ ?line {STRes503,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctM001.xsd','./msxsdtest/complexType',invalid),
+ STResList504 = [STRes503|STResList503],
+
+
+ ?line {STRes504,S504} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctM002.xsd','./msxsdtest/complexType',valid),
+ STResList505 = [STRes504|STResList504],
+ ?line ITRes242 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctM002.xml','./msxsdtest/complexType',valid,S504),
+ ITResList243 = [ITRes242|ITResList242],
+
+
+ ?line {STRes505,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctM003.xsd','./msxsdtest/complexType',invalid),
+ STResList506 = [STRes505|STResList505],
+
+
+ ?line {STRes506,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctM004.xsd','./msxsdtest/complexType',invalid),
+ STResList507 = [STRes506|STResList506],
+
+
+ ?line {STRes507,S507} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctN001.xsd','./msxsdtest/complexType',valid),
+ STResList508 = [STRes507|STResList507],
+ ?line ITRes243 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctN001.xml','./msxsdtest/complexType',valid,S507),
+ ITResList244 = [ITRes243|ITResList243],
+
+
+ ?line {STRes508,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctN002.xsd','./msxsdtest/complexType',invalid),
+ STResList509 = [STRes508|STResList508],
+
+
+ ?line {STRes509,S509} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctN003.xsd','./msxsdtest/complexType',valid),
+ STResList510 = [STRes509|STResList509],
+ ?line ITRes244 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctN003.xml','./msxsdtest/complexType',valid,S509),
+ ITResList245 = [ITRes244|ITResList244],
+
+
+ ?line {STRes510,S510} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctN004.xsd','./msxsdtest/complexType',valid),
+ STResList511 = [STRes510|STResList510],
+ ?line ITRes245 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctN004.xml','./msxsdtest/complexType',valid,S510),
+ ITResList246 = [ITRes245|ITResList245],
+
+
+ ?line {STRes511,S511} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctO001.xsd','./msxsdtest/complexType',valid),
+ STResList512 = [STRes511|STResList511],
+ ?line ITRes246 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctO001.xml','./msxsdtest/complexType',valid,S511),
+ ITResList247 = [ITRes246|ITResList246],
+
+
+ ?line {STRes512,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctO002.xsd','./msxsdtest/complexType',invalid),
+ STResList513 = [STRes512|STResList512],
+
+
+ ?line {STRes513,S513} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctO003.xsd','./msxsdtest/complexType',valid),
+ STResList514 = [STRes513|STResList513],
+ ?line ITRes247 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctO003.xml','./msxsdtest/complexType',valid,S513),
+ ITResList248 = [ITRes247|ITResList247],
+
+
+ ?line {STRes514,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctO004.xsd','./msxsdtest/complexType',invalid),
+ STResList515 = [STRes514|STResList514],
+
+
+ ?line {STRes515,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctO005.xsd','./msxsdtest/complexType',invalid),
+ STResList516 = [STRes515|STResList515],
+
+
+ ?line {STRes516,S516} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctO006.xsd','./msxsdtest/complexType',valid),
+ STResList517 = [STRes516|STResList516],
+ ?line ITRes248 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/complexType/ctO006.xml','./msxsdtest/complexType',valid,S516),
+ ITResList249 = [ITRes248|ITResList248],
+
+
+ ?line {STRes517,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/complexType/ctO007.xsd','./msxsdtest/complexType',invalid),
+ STResList518 = [STRes517|STResList517],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList518,ITResList249).
+
+%% 3.3.2 XML Representation of Element Declaration.
+%% 3.3.4 Element Declaration Validation Rules.
+%% element Validation checking.
+%% Regular Expression Validation checking.
+%% Bug Regressions Specs section: 3.3.4
+
+elem(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemA001.xsd','./msxsdtest/element',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ ?line {STRes1,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemA002.xsd','./msxsdtest/element',valid),
+ STResList2 = [STRes1|STResList1],
+
+
+ ?line {STRes2,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemA003.xsd','./msxsdtest/element',valid),
+ STResList3 = [STRes2|STResList2],
+
+
+ ?line {STRes3,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemA004.xsd','./msxsdtest/element',valid),
+ STResList4 = [STRes3|STResList3],
+
+
+ ?line {STRes4,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemA005.xsd','./msxsdtest/element',valid),
+ STResList5 = [STRes4|STResList4],
+
+
+ ?line {STRes5,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemA006.xsd','./msxsdtest/element',invalid),
+ STResList6 = [STRes5|STResList5],
+
+
+ ?line {STRes6,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemA007.xsd','./msxsdtest/element',valid),
+ STResList7 = [STRes6|STResList6],
+
+
+ ?line {STRes7,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemA009.xsd','./msxsdtest/element',invalid),
+ STResList8 = [STRes7|STResList7],
+
+
+ ?line {STRes8,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemA010.xsd','./msxsdtest/element',invalid),
+ STResList9 = [STRes8|STResList8],
+
+
+ ?line {STRes9,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemA011.xsd','./msxsdtest/element',invalid),
+ STResList10 = [STRes9|STResList9],
+
+
+ ?line {STRes10,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemA012.xsd','./msxsdtest/element',invalid),
+ STResList11 = [STRes10|STResList10],
+
+
+ ?line {STRes11,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemA013.xsd','./msxsdtest/element',invalid),
+ STResList12 = [STRes11|STResList11],
+
+
+ ?line {STRes12,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemA014.xsd','./msxsdtest/element',invalid),
+ STResList13 = [STRes12|STResList12],
+
+
+ ?line {STRes13,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemA015.xsd','./msxsdtest/element',valid),
+ STResList14 = [STRes13|STResList13],
+
+
+ ?line {STRes14,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemA016.xsd','./msxsdtest/element',valid),
+ STResList15 = [STRes14|STResList14],
+
+
+ ?line {STRes15,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemA017.xsd','./msxsdtest/element',valid),
+ STResList16 = [STRes15|STResList15],
+
+
+ ?line {STRes16,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemB001.xsd','./msxsdtest/element',valid),
+ STResList17 = [STRes16|STResList16],
+
+
+ ?line {STRes17,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemB002.xsd','./msxsdtest/element',valid),
+ STResList18 = [STRes17|STResList17],
+
+
+ ?line {STRes18,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemB003.xsd','./msxsdtest/element',invalid),
+ STResList19 = [STRes18|STResList18],
+
+
+ ?line {STRes19,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemB004.xsd','./msxsdtest/element',invalid),
+ STResList20 = [STRes19|STResList19],
+
+
+ ?line {STRes20,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemB005.xsd','./msxsdtest/element',invalid),
+ STResList21 = [STRes20|STResList20],
+
+
+ ?line {STRes21,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemB006.xsd','./msxsdtest/element',invalid),
+ STResList22 = [STRes21|STResList21],
+
+
+ ?line {STRes22,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemB007.xsd','./msxsdtest/element',valid),
+ STResList23 = [STRes22|STResList22],
+
+
+ ?line {STRes23,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemB008.xsd','./msxsdtest/element',valid),
+ STResList24 = [STRes23|STResList23],
+
+
+ ?line {STRes24,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemB009.xsd','./msxsdtest/element',invalid),
+ STResList25 = [STRes24|STResList24],
+
+
+ ?line {STRes25,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemB010.xsd','./msxsdtest/element',invalid),
+ STResList26 = [STRes25|STResList25],
+
+
+ ?line {STRes26,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemC001.xsd','./msxsdtest/element',valid),
+ STResList27 = [STRes26|STResList26],
+
+
+ ?line {STRes27,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemC002.xsd','./msxsdtest/element',valid),
+ STResList28 = [STRes27|STResList27],
+
+
+ ?line {STRes28,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemC003.xsd','./msxsdtest/element',valid),
+ STResList29 = [STRes28|STResList28],
+
+
+ ?line {STRes29,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemC004.xsd','./msxsdtest/element',valid),
+ STResList30 = [STRes29|STResList29],
+
+
+ ?line {STRes30,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemC005.xsd','./msxsdtest/element',valid),
+ STResList31 = [STRes30|STResList30],
+
+
+ ?line {STRes31,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemC006.xsd','./msxsdtest/element',valid),
+ STResList32 = [STRes31|STResList31],
+
+
+ ?line {STRes32,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemC007.xsd','./msxsdtest/element',valid),
+ STResList33 = [STRes32|STResList32],
+
+
+ ?line {STRes33,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemC008.xsd','./msxsdtest/element',valid),
+ STResList34 = [STRes33|STResList33],
+
+
+ ?line {STRes34,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemC009.xsd','./msxsdtest/element',invalid),
+ STResList35 = [STRes34|STResList34],
+
+
+ ?line {STRes35,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemC010.xsd','./msxsdtest/element',invalid),
+ STResList36 = [STRes35|STResList35],
+
+
+ ?line {STRes36,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemC011.xsd','./msxsdtest/element',invalid),
+ STResList37 = [STRes36|STResList36],
+
+
+ ?line {STRes37,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemC012.xsd','./msxsdtest/element',invalid),
+ STResList38 = [STRes37|STResList37],
+
+
+ ?line {STRes38,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemC013.xsd','./msxsdtest/element',invalid),
+ STResList39 = [STRes38|STResList38],
+
+
+ ?line {STRes39,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemC014.xsd','./msxsdtest/element',invalid),
+ STResList40 = [STRes39|STResList39],
+
+
+ ?line {STRes40,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemC015.xsd','./msxsdtest/element',invalid),
+ STResList41 = [STRes40|STResList40],
+
+
+ ?line {STRes41,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemC016.xsd','./msxsdtest/element',invalid),
+ STResList42 = [STRes41|STResList41],
+
+
+ ?line {STRes42,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemC017.xsd','./msxsdtest/element',invalid),
+ STResList43 = [STRes42|STResList42],
+
+
+ ?line {STRes43,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemC018.xsd','./msxsdtest/element',valid),
+ STResList44 = [STRes43|STResList43],
+
+
+ ?line {STRes44,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemC020.xsd','./msxsdtest/element',valid),
+ STResList45 = [STRes44|STResList44],
+
+
+ ?line {STRes45,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemD001.xsd','./msxsdtest/element',valid),
+ STResList46 = [STRes45|STResList45],
+
+
+ ?line {STRes46,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemD002.xsd','./msxsdtest/element',valid),
+ STResList47 = [STRes46|STResList46],
+
+
+ ?line {STRes47,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemD003.xsd','./msxsdtest/element',invalid),
+ STResList48 = [STRes47|STResList47],
+
+
+ ?line {STRes48,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemD004.xsd','./msxsdtest/element',invalid),
+ STResList49 = [STRes48|STResList48],
+
+
+ ?line {STRes49,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemD005.xsd','./msxsdtest/element',invalid),
+ STResList50 = [STRes49|STResList49],
+
+
+ ?line {STRes50,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemD006.xsd','./msxsdtest/element',valid),
+ STResList51 = [STRes50|STResList50],
+
+
+ ?line {STRes51,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemE001.xsd','./msxsdtest/element',valid),
+ STResList52 = [STRes51|STResList51],
+
+
+ ?line {STRes52,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemE002.xsd','./msxsdtest/element',valid),
+ STResList53 = [STRes52|STResList52],
+
+
+ ?line {STRes53,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemE003.xsd','./msxsdtest/element',valid),
+ STResList54 = [STRes53|STResList53],
+
+
+ ?line {STRes54,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemE004.xsd','./msxsdtest/element',valid),
+ STResList55 = [STRes54|STResList54],
+
+
+ ?line {STRes55,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemE005.xsd','./msxsdtest/element',valid),
+ STResList56 = [STRes55|STResList55],
+
+
+ ?line {STRes56,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemE006.xsd','./msxsdtest/element',invalid),
+ STResList57 = [STRes56|STResList56],
+
+
+ ?line {STRes57,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemE007.xsd','./msxsdtest/element',invalid),
+ STResList58 = [STRes57|STResList57],
+
+
+ ?line {STRes58,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemE008.xsd','./msxsdtest/element',invalid),
+ STResList59 = [STRes58|STResList58],
+
+
+ ?line {STRes59,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemE009.xsd','./msxsdtest/element',invalid),
+ STResList60 = [STRes59|STResList59],
+
+
+ ?line {STRes60,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemF001.xsd','./msxsdtest/element',valid),
+ STResList61 = [STRes60|STResList60],
+
+
+ ?line {STRes61,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemF002.xsd','./msxsdtest/element',valid),
+ STResList62 = [STRes61|STResList61],
+
+
+ ?line {STRes62,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemF003.xsd','./msxsdtest/element',valid),
+ STResList63 = [STRes62|STResList62],
+
+
+ ?line {STRes63,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemF004.xsd','./msxsdtest/element',invalid),
+ STResList64 = [STRes63|STResList63],
+
+
+ ?line {STRes64,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemF005.xsd','./msxsdtest/element',valid),
+ STResList65 = [STRes64|STResList64],
+
+
+ ?line {STRes65,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemF006.xsd','./msxsdtest/element',invalid),
+ STResList66 = [STRes65|STResList65],
+
+
+ ?line {STRes66,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemF007.xsd','./msxsdtest/element',invalid),
+ STResList67 = [STRes66|STResList66],
+
+
+ ?line {STRes67,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemF008.xsd','./msxsdtest/element',invalid),
+ STResList68 = [STRes67|STResList67],
+
+
+ ?line {STRes68,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemF009.xsd','./msxsdtest/element',invalid),
+ STResList69 = [STRes68|STResList68],
+
+
+ ?line {STRes69,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemF010.xsd','./msxsdtest/element',invalid),
+ STResList70 = [STRes69|STResList69],
+
+
+ ?line {STRes70,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemF011.xsd','./msxsdtest/element',invalid),
+ STResList71 = [STRes70|STResList70],
+
+
+ ?line {STRes71,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemF012.xsd','./msxsdtest/element',invalid),
+ STResList72 = [STRes71|STResList71],
+
+
+ ?line {STRes72,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemF013.xsd','./msxsdtest/element',invalid),
+ STResList73 = [STRes72|STResList72],
+
+
+ ?line {STRes73,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemF014.xsd','./msxsdtest/element',invalid),
+ STResList74 = [STRes73|STResList73],
+
+
+ ?line {STRes74,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemF015.xsd','./msxsdtest/element',invalid),
+ STResList75 = [STRes74|STResList74],
+
+
+ ?line {STRes75,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemF016.xsd','./msxsdtest/element',invalid),
+ STResList76 = [STRes75|STResList75],
+
+
+ ?line {STRes76,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemF017.xsd','./msxsdtest/element',invalid),
+ STResList77 = [STRes76|STResList76],
+
+
+ ?line {STRes77,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemF018.xsd','./msxsdtest/element',valid),
+ STResList78 = [STRes77|STResList77],
+
+
+ ?line {STRes78,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemG001.xsd','./msxsdtest/element',valid),
+ STResList79 = [STRes78|STResList78],
+
+
+ ?line {STRes79,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemG002.xsd','./msxsdtest/element',valid),
+ STResList80 = [STRes79|STResList79],
+
+
+ ?line {STRes80,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemG003.xsd','./msxsdtest/element',invalid),
+ STResList81 = [STRes80|STResList80],
+
+
+ ?line {STRes81,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemG004.xsd','./msxsdtest/element',invalid),
+ STResList82 = [STRes81|STResList81],
+
+
+ ?line {STRes82,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemG005.xsd','./msxsdtest/element',valid),
+ STResList83 = [STRes82|STResList82],
+
+
+ ?line {STRes83,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemH001.xsd','./msxsdtest/element',valid),
+ STResList84 = [STRes83|STResList83],
+
+
+ ?line {STRes84,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemH002.xsd','./msxsdtest/element',valid),
+ STResList85 = [STRes84|STResList84],
+
+
+ ?line {STRes85,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemH003.xsd','./msxsdtest/element',invalid),
+ STResList86 = [STRes85|STResList85],
+
+
+ ?line {STRes86,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemH004.xsd','./msxsdtest/element',invalid),
+ STResList87 = [STRes86|STResList86],
+
+
+ ?line {STRes87,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemH005.xsd','./msxsdtest/element',invalid),
+ STResList88 = [STRes87|STResList87],
+
+
+ ?line {STRes88,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemH006.xsd','./msxsdtest/element',invalid),
+ STResList89 = [STRes88|STResList88],
+
+
+ ?line {STRes89,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemI001.xsd','./msxsdtest/element',valid),
+ STResList90 = [STRes89|STResList89],
+
+
+ ?line {STRes90,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemI002.xsd','./msxsdtest/element',valid),
+ STResList91 = [STRes90|STResList90],
+
+
+ ?line {STRes91,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemI003.xsd','./msxsdtest/element',invalid),
+ STResList92 = [STRes91|STResList91],
+
+
+ ?line {STRes92,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemI004.xsd','./msxsdtest/element',invalid),
+ STResList93 = [STRes92|STResList92],
+
+
+ ?line {STRes93,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemI005.xsd','./msxsdtest/element',invalid),
+ STResList94 = [STRes93|STResList93],
+
+
+ ?line {STRes94,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ001.xsd','./msxsdtest/element',valid),
+ STResList95 = [STRes94|STResList94],
+
+
+ ?line {STRes95,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ002.xsd','./msxsdtest/element',valid),
+ STResList96 = [STRes95|STResList95],
+
+
+ ?line {STRes96,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ003.xsd','./msxsdtest/element',valid),
+ STResList97 = [STRes96|STResList96],
+
+
+ ?line {STRes97,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ004.xsd','./msxsdtest/element',valid),
+ STResList98 = [STRes97|STResList97],
+
+
+ ?line {STRes98,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ005.xsd','./msxsdtest/element',valid),
+ STResList99 = [STRes98|STResList98],
+
+
+ ?line {STRes99,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ006.xsd','./msxsdtest/element',invalid),
+ STResList100 = [STRes99|STResList99],
+
+
+ ?line {STRes100,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ007.xsd','./msxsdtest/element',invalid),
+ STResList101 = [STRes100|STResList100],
+
+
+ ?line {STRes101,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ008.xsd','./msxsdtest/element',invalid),
+ STResList102 = [STRes101|STResList101],
+
+
+ ?line {STRes102,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ009.xsd','./msxsdtest/element',valid),
+ STResList103 = [STRes102|STResList102],
+
+
+ ?line {STRes103,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ010.xsd','./msxsdtest/element',valid),
+ STResList104 = [STRes103|STResList103],
+
+
+ ?line {STRes104,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ011.xsd','./msxsdtest/element',valid),
+ STResList105 = [STRes104|STResList104],
+
+
+ ?line {STRes105,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ012.xsd','./msxsdtest/element',invalid),
+ STResList106 = [STRes105|STResList105],
+
+
+ ?line {STRes106,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ013.xsd','./msxsdtest/element',valid),
+ STResList107 = [STRes106|STResList106],
+
+
+ ?line {STRes107,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ014.xsd','./msxsdtest/element',invalid),
+ STResList108 = [STRes107|STResList107],
+
+
+ ?line {STRes108,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ015.xsd','./msxsdtest/element',invalid),
+ STResList109 = [STRes108|STResList108],
+
+
+ ?line {STRes109,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ016.xsd','./msxsdtest/element',invalid),
+ STResList110 = [STRes109|STResList109],
+
+
+ ?line {STRes110,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ017.xsd','./msxsdtest/element',valid),
+ STResList111 = [STRes110|STResList110],
+
+
+ ?line {STRes111,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ018.xsd','./msxsdtest/element',valid),
+ STResList112 = [STRes111|STResList111],
+
+
+ ?line {STRes112,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ019.xsd','./msxsdtest/element',invalid),
+ STResList113 = [STRes112|STResList112],
+
+
+ ?line {STRes113,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ020.xsd','./msxsdtest/element',invalid),
+ STResList114 = [STRes113|STResList113],
+
+
+ ?line {STRes114,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemJ021.xsd','./msxsdtest/element',valid),
+ STResList115 = [STRes114|STResList114],
+
+
+ ?line {STRes115,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemK001.xsd','./msxsdtest/element',valid),
+ STResList116 = [STRes115|STResList115],
+
+
+ ?line {STRes116,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemK002.xsd','./msxsdtest/element',valid),
+ STResList117 = [STRes116|STResList116],
+
+
+ ?line {STRes117,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemK003.xsd','./msxsdtest/element',invalid),
+ STResList118 = [STRes117|STResList117],
+
+
+ ?line {STRes118,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemK004.xsd','./msxsdtest/element',invalid),
+ STResList119 = [STRes118|STResList118],
+
+
+ ?line {STRes119,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemK005.xsd','./msxsdtest/element',invalid),
+ STResList120 = [STRes119|STResList119],
+
+
+ ?line {STRes120,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemK006.xsd','./msxsdtest/element',invalid),
+ STResList121 = [STRes120|STResList120],
+
+
+ ?line {STRes121,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemK007.xsd','./msxsdtest/element',invalid),
+ STResList122 = [STRes121|STResList121],
+
+
+ ?line {STRes122,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemL001.xsd','./msxsdtest/element',valid),
+ STResList123 = [STRes122|STResList122],
+
+
+ ?line {STRes123,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemL002.xsd','./msxsdtest/element',invalid),
+ STResList124 = [STRes123|STResList123],
+
+
+ ?line {STRes124,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemL003.xsd','./msxsdtest/element',invalid),
+ STResList125 = [STRes124|STResList124],
+
+
+ ?line {STRes125,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemL004.xsd','./msxsdtest/element',valid),
+ STResList126 = [STRes125|STResList125],
+
+
+ ?line {STRes126,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemL005.xsd','./msxsdtest/element',valid),
+ STResList127 = [STRes126|STResList126],
+
+
+ ?line {STRes127,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemM001.xsd','./msxsdtest/element',valid),
+ STResList128 = [STRes127|STResList127],
+
+
+ ?line {STRes128,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemM002.xsd','./msxsdtest/element',invalid),
+ STResList129 = [STRes128|STResList128],
+
+
+ ?line {STRes129,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemM003.xsd','./msxsdtest/element',invalid),
+ STResList130 = [STRes129|STResList129],
+
+
+ ?line {STRes130,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemM004.xsd','./msxsdtest/element',valid),
+ STResList131 = [STRes130|STResList130],
+
+
+ ?line {STRes131,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemM005.xsd','./msxsdtest/element',invalid),
+ STResList132 = [STRes131|STResList131],
+
+
+ ?line {STRes132,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemN001.xsd','./msxsdtest/element',valid),
+ STResList133 = [STRes132|STResList132],
+
+
+ ?line {STRes133,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemN002.xsd','./msxsdtest/element',valid),
+ STResList134 = [STRes133|STResList133],
+
+
+ ?line {STRes134,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemN003.xsd','./msxsdtest/element',valid),
+ STResList135 = [STRes134|STResList134],
+
+
+ ?line {STRes135,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemN004.xsd','./msxsdtest/element',valid),
+ STResList136 = [STRes135|STResList135],
+
+
+ ?line {STRes136,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemN005.xsd','./msxsdtest/element',valid),
+ STResList137 = [STRes136|STResList136],
+
+
+ ?line {STRes137,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemN006.xsd','./msxsdtest/element',invalid),
+ STResList138 = [STRes137|STResList137],
+
+
+ ?line {STRes138,S138} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemO001.xsd','./msxsdtest/element',valid),
+ STResList139 = [STRes138|STResList138],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemO001.xml','./msxsdtest/element',invalid,S138),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes139,S139} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemO002.xsd','./msxsdtest/element',valid),
+ STResList140 = [STRes139|STResList139],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemO002.xml','./msxsdtest/element',valid,S139),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes140,S140} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemO003.xsd','./msxsdtest/element',valid),
+ STResList141 = [STRes140|STResList140],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemO003.xml','./msxsdtest/element',valid,S140),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes141,S141} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemO004.xsd','./msxsdtest/element',valid),
+ STResList142 = [STRes141|STResList141],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemO004.xml','./msxsdtest/element',valid,S141),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes142,S142} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemO005.xsd','./msxsdtest/element',valid),
+ STResList143 = [STRes142|STResList142],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemO005.xml','./msxsdtest/element',valid,S142),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes143,S143} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemO006.xsd','./msxsdtest/element',valid),
+ STResList144 = [STRes143|STResList143],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemO006.xml','./msxsdtest/element',valid,S143),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes144,S144} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemO007.xsd','./msxsdtest/element',valid),
+ STResList145 = [STRes144|STResList144],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemO007.xml','./msxsdtest/element',invalid,S144),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes145,S145} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemO008.xsd','./msxsdtest/element',valid),
+ STResList146 = [STRes145|STResList145],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemO008.xml','./msxsdtest/element',valid,S145),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes146,S146} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemO009.xsd','./msxsdtest/element',valid),
+ STResList147 = [STRes146|STResList146],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemO009.xml','./msxsdtest/element',valid,S146),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes147,S147} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemO010.xsd','./msxsdtest/element',valid),
+ STResList148 = [STRes147|STResList147],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemO010.xml','./msxsdtest/element',invalid,S147),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes148,S148} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemO011.xsd','./msxsdtest/element',valid),
+ STResList149 = [STRes148|STResList148],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemO011.xml','./msxsdtest/element',invalid,S148),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes149,S149} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemO012.xsd','./msxsdtest/element',valid),
+ STResList150 = [STRes149|STResList149],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemO012.xml','./msxsdtest/element',valid,S149),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes150,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemP001.xsd','./msxsdtest/element',invalid),
+ STResList151 = [STRes150|STResList150],
+
+
+ ?line {STRes151,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemP002.xsd','./msxsdtest/element',invalid),
+ STResList152 = [STRes151|STResList151],
+
+
+ ?line {STRes152,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemP003.xsd','./msxsdtest/element',valid),
+ STResList153 = [STRes152|STResList152],
+
+
+ ?line {STRes153,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemP004.xsd','./msxsdtest/element',valid),
+ STResList154 = [STRes153|STResList153],
+
+
+ ?line {STRes154,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemP005.xsd','./msxsdtest/element',invalid),
+ STResList155 = [STRes154|STResList154],
+
+
+ ?line {STRes155,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemP006.xsd','./msxsdtest/element',invalid),
+ STResList156 = [STRes155|STResList155],
+
+
+ ?line {STRes156,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemP007.xsd','./msxsdtest/element',invalid),
+ STResList157 = [STRes156|STResList156],
+
+
+ ?line {STRes157,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemP008.xsd','./msxsdtest/element',invalid),
+ STResList158 = [STRes157|STResList157],
+
+
+ ?line {STRes158,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemP009.xsd','./msxsdtest/element',invalid),
+ STResList159 = [STRes158|STResList158],
+
+
+ ?line {STRes159,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ001.xsd','./msxsdtest/element',valid),
+ STResList160 = [STRes159|STResList159],
+
+
+ ?line {STRes160,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ002.xsd','./msxsdtest/element',valid),
+ STResList161 = [STRes160|STResList160],
+
+
+ ?line {STRes161,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ003.xsd','./msxsdtest/element',valid),
+ STResList162 = [STRes161|STResList161],
+
+
+ ?line {STRes162,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ004.xsd','./msxsdtest/element',invalid),
+ STResList163 = [STRes162|STResList162],
+
+
+ ?line {STRes163,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ005.xsd','./msxsdtest/element',valid),
+ STResList164 = [STRes163|STResList163],
+
+
+ ?line {STRes164,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ006.xsd','./msxsdtest/element',invalid),
+ STResList165 = [STRes164|STResList164],
+
+
+ ?line {STRes165,S165} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ007.xsd','./msxsdtest/element',valid),
+ STResList166 = [STRes165|STResList165],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemQ007.xml','./msxsdtest/element',invalid,S165),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes166,S166} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ008.xsd','./msxsdtest/element',valid),
+ STResList167 = [STRes166|STResList166],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemQ008.xml','./msxsdtest/element',valid,S166),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes167,S167} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ009.xsd','./msxsdtest/element',valid),
+ STResList168 = [STRes167|STResList167],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemQ009.xml','./msxsdtest/element',invalid,S167),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes168,S168} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ010.xsd','./msxsdtest/element',valid),
+ STResList169 = [STRes168|STResList168],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemQ010.xml','./msxsdtest/element',invalid,S168),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes169,S169} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ011.xsd','./msxsdtest/element',valid),
+ STResList170 = [STRes169|STResList169],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemQ011.xml','./msxsdtest/element',valid,S169),
+ ITResList17 = [ITRes16|ITResList16],
+
+
+ ?line {STRes170,S170} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ012.xsd','./msxsdtest/element',valid),
+ STResList171 = [STRes170|STResList170],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemQ012.xml','./msxsdtest/element',invalid,S170),
+ ITResList18 = [ITRes17|ITResList17],
+
+
+ ?line {STRes171,S171} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ013.xsd','./msxsdtest/element',valid),
+ STResList172 = [STRes171|STResList171],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemQ013.xml','./msxsdtest/element',valid,S171),
+ ITResList19 = [ITRes18|ITResList18],
+
+
+ ?line {STRes172,S172} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ014.xsd','./msxsdtest/element',valid),
+ STResList173 = [STRes172|STResList172],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemQ014.xml','./msxsdtest/element',invalid,S172),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes173,S173} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ015.xsd','./msxsdtest/element',valid),
+ STResList174 = [STRes173|STResList173],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemQ015.xml','./msxsdtest/element',valid,S173),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes174,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ016.xsd','./msxsdtest/element',valid),
+ STResList175 = [STRes174|STResList174],
+
+
+ ?line {STRes175,S175} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ017.xsd','./msxsdtest/element',valid),
+ STResList176 = [STRes175|STResList175],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemQ017.xml','./msxsdtest/element',valid,S175),
+ ITResList22 = [ITRes21|ITResList21],
+
+
+ ?line {STRes176,S176} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ018.xsd','./msxsdtest/element',valid),
+ STResList177 = [STRes176|STResList176],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemQ018.xml','./msxsdtest/element',invalid,S176),
+ ITResList23 = [ITRes22|ITResList22],
+
+
+ ?line {STRes177,S177} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ019.xsd','./msxsdtest/element',valid),
+ STResList178 = [STRes177|STResList177],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemQ019.xml','./msxsdtest/element',invalid,S177),
+ ITResList24 = [ITRes23|ITResList23],
+
+
+ ?line {STRes178,S178} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ020.xsd','./msxsdtest/element',valid),
+ STResList179 = [STRes178|STResList178],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemQ020.xml','./msxsdtest/element',valid,S178),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes179,S179} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ021.xsd','./msxsdtest/element',valid),
+ STResList180 = [STRes179|STResList179],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemQ021.xml','./msxsdtest/element',valid,S179),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes180,S180} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemQ022.xsd','./msxsdtest/element',valid),
+ STResList181 = [STRes180|STResList180],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemQ022.xml','./msxsdtest/element',valid,S180),
+ ITResList27 = [ITRes26|ITResList26],
+
+
+ ?line {STRes181,S181} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemR001.xsd','./msxsdtest/element',valid),
+ STResList182 = [STRes181|STResList181],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemR001.xml','./msxsdtest/element',valid,S181),
+ ITResList28 = [ITRes27|ITResList27],
+
+
+ ?line {STRes182,S182} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemR002.xsd','./msxsdtest/element',valid),
+ STResList183 = [STRes182|STResList182],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemR002.xml','./msxsdtest/element',valid,S182),
+ ITResList29 = [ITRes28|ITResList28],
+
+
+ ?line {STRes183,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemR003.xsd','./msxsdtest/element',invalid),
+ STResList184 = [STRes183|STResList183],
+
+
+ ?line {STRes184,S184} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemR004.xsd','./msxsdtest/element',valid),
+ STResList185 = [STRes184|STResList184],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemR004.xml','./msxsdtest/element',valid,S184),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes185,S185} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemR005.xsd','./msxsdtest/element',valid),
+ STResList186 = [STRes185|STResList185],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemR005.xml','./msxsdtest/element',valid,S185),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes186,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemR006.xsd','./msxsdtest/element',invalid),
+ STResList187 = [STRes186|STResList186],
+
+
+ ?line {STRes187,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemS001.xsd','./msxsdtest/element',invalid),
+ STResList188 = [STRes187|STResList187],
+
+
+ ?line {STRes188,S188} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemS002.xsd','./msxsdtest/element',valid),
+ STResList189 = [STRes188|STResList188],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemS002.xml','./msxsdtest/element',valid,S188),
+ ITResList32 = [ITRes31|ITResList31],
+
+
+ ?line {STRes189,S189} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemS003.xsd','./msxsdtest/element',valid),
+ STResList190 = [STRes189|STResList189],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemS003.xml','./msxsdtest/element',valid,S189),
+ ITResList33 = [ITRes32|ITResList32],
+
+
+ ?line {STRes190,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemS004.xsd','./msxsdtest/element',invalid),
+ STResList191 = [STRes190|STResList190],
+
+
+ ?line {STRes191,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemS005.xsd','./msxsdtest/element',invalid),
+ STResList192 = [STRes191|STResList191],
+
+
+ ?line {STRes192,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemS006.xsd','./msxsdtest/element',invalid),
+ STResList193 = [STRes192|STResList192],
+
+
+ ?line {STRes193,S193} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemS007.xsd','./msxsdtest/element',valid),
+ STResList194 = [STRes193|STResList193],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemS007.xml','./msxsdtest/element',valid,S193),
+ ITResList34 = [ITRes33|ITResList33],
+
+
+ ?line {STRes194,S194} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemS008.xsd','./msxsdtest/element',valid),
+ STResList195 = [STRes194|STResList194],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemS008.xml','./msxsdtest/element',valid,S194),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes195,S195} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT001.xsd','./msxsdtest/element',valid),
+ STResList196 = [STRes195|STResList195],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT001.xml','./msxsdtest/element',invalid,S195),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes196,S196} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT002.xsd','./msxsdtest/element',valid),
+ STResList197 = [STRes196|STResList196],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT002.xml','./msxsdtest/element',valid,S196),
+ ITResList37 = [ITRes36|ITResList36],
+
+
+ ?line {STRes197,S197} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT003.xsd','./msxsdtest/element',valid),
+ STResList198 = [STRes197|STResList197],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT003.xml','./msxsdtest/element',valid,S197),
+ ITResList38 = [ITRes37|ITResList37],
+
+
+ ?line {STRes198,S198} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT004.xsd','./msxsdtest/element',valid),
+ STResList199 = [STRes198|STResList198],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT004.xml','./msxsdtest/element',invalid,S198),
+ ITResList39 = [ITRes38|ITResList38],
+
+
+ ?line {STRes199,S199} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT005.xsd','./msxsdtest/element',valid),
+ STResList200 = [STRes199|STResList199],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT005.xml','./msxsdtest/element',invalid,S199),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes200,S200} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT006.xsd','./msxsdtest/element',valid),
+ STResList201 = [STRes200|STResList200],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT006.xml','./msxsdtest/element',invalid,S200),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes201,S201} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT007.xsd','./msxsdtest/element',valid),
+ STResList202 = [STRes201|STResList201],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT007.xml','./msxsdtest/element',valid,S201),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes202,S202} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT008.xsd','./msxsdtest/element',valid),
+ STResList203 = [STRes202|STResList202],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT008.xml','./msxsdtest/element',valid,S202),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes203,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT009.xsd','./msxsdtest/element',invalid),
+ STResList204 = [STRes203|STResList203],
+
+
+ ?line {STRes204,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT010.xsd','./msxsdtest/element',invalid),
+ STResList205 = [STRes204|STResList204],
+
+
+ ?line {STRes205,S205} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT011.xsd','./msxsdtest/element',valid),
+ STResList206 = [STRes205|STResList205],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT011.xml','./msxsdtest/element',invalid,S205),
+ ITResList44 = [ITRes43|ITResList43],
+
+
+ ?line {STRes206,S206} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT012.xsd','./msxsdtest/element',valid),
+ STResList207 = [STRes206|STResList206],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT012.xml','./msxsdtest/element',invalid,S206),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes207,S207} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT013.xsd','./msxsdtest/element',valid),
+ STResList208 = [STRes207|STResList207],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT013.xml','./msxsdtest/element',invalid,S207),
+ ITResList46 = [ITRes45|ITResList45],
+
+
+ ?line {STRes208,S208} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT014.xsd','./msxsdtest/element',valid),
+ STResList209 = [STRes208|STResList208],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT014.xml','./msxsdtest/element',valid,S208),
+ ITResList47 = [ITRes46|ITResList46],
+
+
+ ?line {STRes209,S209} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT015.xsd','./msxsdtest/element',valid),
+ STResList210 = [STRes209|STResList209],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT015.xml','./msxsdtest/element',valid,S209),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes210,S210} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT016.xsd','./msxsdtest/element',valid),
+ STResList211 = [STRes210|STResList210],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT016.xml','./msxsdtest/element',valid,S210),
+ ITResList49 = [ITRes48|ITResList48],
+
+
+ ?line {STRes211,S211} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT017.xsd','./msxsdtest/element',valid),
+ STResList212 = [STRes211|STResList211],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT017.xml','./msxsdtest/element',invalid,S211),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes212,S212} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT018.xsd','./msxsdtest/element',valid),
+ STResList213 = [STRes212|STResList212],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT018.xml','./msxsdtest/element',invalid,S212),
+ ITResList51 = [ITRes50|ITResList50],
+
+
+ ?line {STRes213,S213} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT019.xsd','./msxsdtest/element',valid),
+ STResList214 = [STRes213|STResList213],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT019.xml','./msxsdtest/element',invalid,S213),
+ ITResList52 = [ITRes51|ITResList51],
+
+
+ ?line {STRes214,S214} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT022.xsd','./msxsdtest/element',valid),
+ STResList215 = [STRes214|STResList214],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT022.xml','./msxsdtest/element',valid,S214),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes215,S215} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT024.xsd','./msxsdtest/element',valid),
+ STResList216 = [STRes215|STResList215],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT024.xml','./msxsdtest/element',invalid,S215),
+ ITResList54 = [ITRes53|ITResList53],
+
+
+ ?line {STRes216,S216} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT025.xsd','./msxsdtest/element',valid),
+ STResList217 = [STRes216|STResList216],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT025.xml','./msxsdtest/element',valid,S216),
+ ITResList55 = [ITRes54|ITResList54],
+
+
+ ?line {STRes217,S217} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT026.xsd','./msxsdtest/element',valid),
+ STResList218 = [STRes217|STResList217],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT026.xml','./msxsdtest/element',valid,S217),
+ ITResList56 = [ITRes55|ITResList55],
+
+
+ ?line {STRes218,S218} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT027.xsd','./msxsdtest/element',valid),
+ STResList219 = [STRes218|STResList218],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT027.xml','./msxsdtest/element',valid,S218),
+ ITResList57 = [ITRes56|ITResList56],
+
+
+ ?line {STRes219,S219} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT028.xsd','./msxsdtest/element',valid),
+ STResList220 = [STRes219|STResList219],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT028.xml','./msxsdtest/element',valid,S219),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes220,S220} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT029.xsd','./msxsdtest/element',valid),
+ STResList221 = [STRes220|STResList220],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT029.xml','./msxsdtest/element',valid,S220),
+ ITResList59 = [ITRes58|ITResList58],
+
+
+ ?line {STRes221,S221} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT030.xsd','./msxsdtest/element',valid),
+ STResList222 = [STRes221|STResList221],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT030.xml','./msxsdtest/element',valid,S221),
+ ITResList60 = [ITRes59|ITResList59],
+
+
+ ?line {STRes222,S222} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT031.xsd','./msxsdtest/element',valid),
+ STResList223 = [STRes222|STResList222],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT031.xml','./msxsdtest/element',invalid,S222),
+ ITResList61 = [ITRes60|ITResList60],
+
+
+ ?line {STRes223,S223} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT032.xsd','./msxsdtest/element',valid),
+ STResList224 = [STRes223|STResList223],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT032.xml','./msxsdtest/element',valid,S223),
+ ITResList62 = [ITRes61|ITResList61],
+
+
+ ?line {STRes224,S224} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT033.xsd','./msxsdtest/element',valid),
+ STResList225 = [STRes224|STResList224],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT033.xml','./msxsdtest/element',invalid,S224),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes225,S225} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT038.xsd','./msxsdtest/element',valid),
+ STResList226 = [STRes225|STResList225],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT038.xml','./msxsdtest/element',valid,S225),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes226,S226} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT039.xsd','./msxsdtest/element',valid),
+ STResList227 = [STRes226|STResList226],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT039.xml','./msxsdtest/element',invalid,S226),
+ ITResList65 = [ITRes64|ITResList64],
+
+
+ ?line {STRes227,S227} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT040.xsd','./msxsdtest/element',valid),
+ STResList228 = [STRes227|STResList227],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT040.xml','./msxsdtest/element',valid,S227),
+ ITResList66 = [ITRes65|ITResList65],
+
+
+ ?line {STRes228,S228} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT041.xsd','./msxsdtest/element',valid),
+ STResList229 = [STRes228|STResList228],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT041.xml','./msxsdtest/element',valid,S228),
+ ITResList67 = [ITRes66|ITResList66],
+
+
+ ?line {STRes229,S229} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT042.xsd','./msxsdtest/element',valid),
+ STResList230 = [STRes229|STResList229],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT042.xml','./msxsdtest/element',valid,S229),
+ ITResList68 = [ITRes67|ITResList67],
+
+
+ ?line {STRes230,S230} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT043.xsd','./msxsdtest/element',valid),
+ STResList231 = [STRes230|STResList230],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT043.xml','./msxsdtest/element',valid,S230),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes231,S231} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT044.xsd','./msxsdtest/element',valid),
+ STResList232 = [STRes231|STResList231],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT044.xml','./msxsdtest/element',valid,S231),
+ ITResList70 = [ITRes69|ITResList69],
+
+
+ ?line {STRes232,S232} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT045.xsd','./msxsdtest/element',valid),
+ STResList233 = [STRes232|STResList232],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT045.xml','./msxsdtest/element',invalid,S232),
+ ITResList71 = [ITRes70|ITResList70],
+
+
+ ?line {STRes233,S233} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT046.xsd','./msxsdtest/element',valid),
+ STResList234 = [STRes233|STResList233],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT046.xml','./msxsdtest/element',invalid,S233),
+ ITResList72 = [ITRes71|ITResList71],
+
+
+ ?line {STRes234,S234} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT047.xsd','./msxsdtest/element',valid),
+ STResList235 = [STRes234|STResList234],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT047.xml','./msxsdtest/element',invalid,S234),
+ ITResList73 = [ITRes72|ITResList72],
+
+
+ ?line {STRes235,S235} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT048.xsd','./msxsdtest/element',valid),
+ STResList236 = [STRes235|STResList235],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT048.xml','./msxsdtest/element',invalid,S235),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes236,S236} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT049.xsd','./msxsdtest/element',valid),
+ STResList237 = [STRes236|STResList236],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT049.xml','./msxsdtest/element',invalid,S236),
+ ITResList75 = [ITRes74|ITResList74],
+
+
+ ?line {STRes237,S237} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT050.xsd','./msxsdtest/element',valid),
+ STResList238 = [STRes237|STResList237],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT050.xml','./msxsdtest/element',invalid,S237),
+ ITResList76 = [ITRes75|ITResList75],
+
+
+ ?line {STRes238,S238} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT051.xsd','./msxsdtest/element',valid),
+ STResList239 = [STRes238|STResList238],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT051.xml','./msxsdtest/element',invalid,S238),
+ ITResList77 = [ITRes76|ITResList76],
+
+
+ ?line {STRes239,S239} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT052.xsd','./msxsdtest/element',valid),
+ STResList240 = [STRes239|STResList239],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT052.xml','./msxsdtest/element',invalid,S239),
+ ITResList78 = [ITRes77|ITResList77],
+
+
+ ?line {STRes240,S240} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT053.xsd','./msxsdtest/element',valid),
+ STResList241 = [STRes240|STResList240],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT053.xml','./msxsdtest/element',invalid,S240),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes241,S241} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT054.xsd','./msxsdtest/element',valid),
+ STResList242 = [STRes241|STResList241],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT054.xml','./msxsdtest/element',invalid,S241),
+ ITResList80 = [ITRes79|ITResList79],
+
+
+ ?line {STRes242,S242} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT055.xsd','./msxsdtest/element',valid),
+ STResList243 = [STRes242|STResList242],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT055.xml','./msxsdtest/element',invalid,S242),
+ ITResList81 = [ITRes80|ITResList80],
+
+
+ ?line {STRes243,S243} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT056.xsd','./msxsdtest/element',valid),
+ STResList244 = [STRes243|STResList243],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT056.xml','./msxsdtest/element',invalid,S243),
+ ITResList82 = [ITRes81|ITResList81],
+
+
+ ?line {STRes244,S244} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT057.xsd','./msxsdtest/element',valid),
+ STResList245 = [STRes244|STResList244],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT057.xml','./msxsdtest/element',invalid,S244),
+ ITResList83 = [ITRes82|ITResList82],
+
+
+ ?line {STRes245,S245} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT058.xsd','./msxsdtest/element',valid),
+ STResList246 = [STRes245|STResList245],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT058.xml','./msxsdtest/element',valid,S245),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes246,S246} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemT074.xsd','./msxsdtest/element',valid),
+ STResList247 = [STRes246|STResList246],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemT074.xml','./msxsdtest/element',invalid,S246),
+ ITResList85 = [ITRes84|ITResList84],
+
+
+ ?line {STRes247,S247} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU001.xsd','./msxsdtest/element',valid),
+ STResList248 = [STRes247|STResList247],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU001.xml','./msxsdtest/element',valid,S247),
+ ITResList86 = [ITRes85|ITResList85],
+
+
+ ?line {STRes248,S248} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU002.xsd','./msxsdtest/element',valid),
+ STResList249 = [STRes248|STResList248],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU002.xml','./msxsdtest/element',valid,S248),
+ ITResList87 = [ITRes86|ITResList86],
+
+
+ ?line {STRes249,S249} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU003.xsd','./msxsdtest/element',valid),
+ STResList250 = [STRes249|STResList249],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU003.xml','./msxsdtest/element',valid,S249),
+ ITResList88 = [ITRes87|ITResList87],
+
+
+ ?line {STRes250,S250} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU004.xsd','./msxsdtest/element',valid),
+ STResList251 = [STRes250|STResList250],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU004.xml','./msxsdtest/element',valid,S250),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes251,S251} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU005.xsd','./msxsdtest/element',valid),
+ STResList252 = [STRes251|STResList251],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU005.xml','./msxsdtest/element',valid,S251),
+ ITResList90 = [ITRes89|ITResList89],
+
+
+ ?line {STRes252,S252} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU006.xsd','./msxsdtest/element',valid),
+ STResList253 = [STRes252|STResList252],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU006.xml','./msxsdtest/element',valid,S252),
+ ITResList91 = [ITRes90|ITResList90],
+
+
+ ?line {STRes253,S253} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU007.xsd','./msxsdtest/element',valid),
+ STResList254 = [STRes253|STResList253],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU007.xml','./msxsdtest/element',valid,S253),
+ ITResList92 = [ITRes91|ITResList91],
+
+
+ ?line {STRes254,S254} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU008.xsd','./msxsdtest/element',valid),
+ STResList255 = [STRes254|STResList254],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU008.xml','./msxsdtest/element',valid,S254),
+ ITResList93 = [ITRes92|ITResList92],
+
+
+ ?line {STRes255,S255} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU009.xsd','./msxsdtest/element',valid),
+ STResList256 = [STRes255|STResList255],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU009.xml','./msxsdtest/element',valid,S255),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes256,S256} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU010.xsd','./msxsdtest/element',valid),
+ STResList257 = [STRes256|STResList256],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU010.xml','./msxsdtest/element',valid,S256),
+ ITResList95 = [ITRes94|ITResList94],
+
+
+ ?line {STRes257,S257} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU011.xsd','./msxsdtest/element',valid),
+ STResList258 = [STRes257|STResList257],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU011.xml','./msxsdtest/element',valid,S257),
+ ITResList96 = [ITRes95|ITResList95],
+
+
+ ?line {STRes258,S258} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU012.xsd','./msxsdtest/element',valid),
+ STResList259 = [STRes258|STResList258],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU012.xml','./msxsdtest/element',valid,S258),
+ ITResList97 = [ITRes96|ITResList96],
+
+
+ ?line {STRes259,S259} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU013.xsd','./msxsdtest/element',valid),
+ STResList260 = [STRes259|STResList259],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU013.xml','./msxsdtest/element',valid,S259),
+ ITResList98 = [ITRes97|ITResList97],
+
+
+ ?line {STRes260,S260} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU014.xsd','./msxsdtest/element',valid),
+ STResList261 = [STRes260|STResList260],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU014.xml','./msxsdtest/element',valid,S260),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes261,S261} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU015.xsd','./msxsdtest/element',valid),
+ STResList262 = [STRes261|STResList261],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU015.xml','./msxsdtest/element',valid,S261),
+ ITResList100 = [ITRes99|ITResList99],
+
+
+ ?line {STRes262,S262} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU017.xsd','./msxsdtest/element',valid),
+ STResList263 = [STRes262|STResList262],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU017.xml','./msxsdtest/element',valid,S262),
+ ITResList101 = [ITRes100|ITResList100],
+
+
+ ?line {STRes263,S263} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU018.xsd','./msxsdtest/element',valid),
+ STResList264 = [STRes263|STResList263],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU018.xml','./msxsdtest/element',valid,S263),
+ ITResList102 = [ITRes101|ITResList101],
+
+
+ ?line {STRes264,S264} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU019.xsd','./msxsdtest/element',valid),
+ STResList265 = [STRes264|STResList264],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU019.xml','./msxsdtest/element',valid,S264),
+ ITResList103 = [ITRes102|ITResList102],
+
+
+ ?line {STRes265,S265} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU020.xsd','./msxsdtest/element',valid),
+ STResList266 = [STRes265|STResList265],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU020.xml','./msxsdtest/element',valid,S265),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes266,S266} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU021.xsd','./msxsdtest/element',valid),
+ STResList267 = [STRes266|STResList266],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU021.xml','./msxsdtest/element',valid,S266),
+ ITResList105 = [ITRes104|ITResList104],
+
+
+ ?line {STRes267,S267} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU022.xsd','./msxsdtest/element',valid),
+ STResList268 = [STRes267|STResList267],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU022.xml','./msxsdtest/element',valid,S267),
+ ITResList106 = [ITRes105|ITResList105],
+
+
+ ?line {STRes268,S268} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU023.xsd','./msxsdtest/element',valid),
+ STResList269 = [STRes268|STResList268],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU023.xml','./msxsdtest/element',valid,S268),
+ ITResList107 = [ITRes106|ITResList106],
+
+
+ ?line {STRes269,S269} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU024.xsd','./msxsdtest/element',valid),
+ STResList270 = [STRes269|STResList269],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU024.xml','./msxsdtest/element',valid,S269),
+ ITResList108 = [ITRes107|ITResList107],
+
+
+ ?line {STRes270,S270} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemU025.xsd','./msxsdtest/element',valid),
+ STResList271 = [STRes270|STResList270],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemU025.xml','./msxsdtest/element',invalid,S270),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes271,S271} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemZ001.xsd','./msxsdtest/element',valid),
+ STResList272 = [STRes271|STResList271],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemZ001.xml','./msxsdtest/element',invalid,S271),
+ ITResList110 = [ITRes109|ITResList109],
+
+
+ ?line {STRes272,S272} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemZ002.xsd','./msxsdtest/element',valid),
+ STResList273 = [STRes272|STResList272],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemZ002.xml','./msxsdtest/element',valid,S272),
+ ITResList111 = [ITRes110|ITResList110],
+
+
+ ?line {STRes273,S273} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemZ003.xsd','./msxsdtest/element',valid),
+ STResList274 = [STRes273|STResList273],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/element/elemZ003.xml','./msxsdtest/element',valid,S273),
+ ITResList112 = [ITRes111|ITResList111],
+
+
+ ?line {STRes274,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemZ004.xsd','./msxsdtest/element',valid),
+ STResList275 = [STRes274|STResList274],
+
+
+ ?line {STRes275,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/element/elemZ005.xsd','./msxsdtest/element',valid),
+ STResList276 = [STRes275|STResList275],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList276,ITResList112).
+
+%% Syntax Checking Model Group Tests.
+%% Content Checking Model Group Tests.
+
+group(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupA001.xsd','./msxsdtest/Group',valid),
+ STResList1 = [STRes0|STResList0],
+
+
+ ?line {STRes1,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupA002.xsd','./msxsdtest/Group',valid),
+ STResList2 = [STRes1|STResList1],
+
+
+ ?line {STRes2,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupA003.xsd','./msxsdtest/Group',invalid),
+ STResList3 = [STRes2|STResList2],
+
+
+ ?line {STRes3,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupA004.xsd','./msxsdtest/Group',invalid),
+ STResList4 = [STRes3|STResList3],
+
+
+ ?line {STRes4,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupA005.xsd','./msxsdtest/Group',invalid),
+ STResList5 = [STRes4|STResList4],
+
+
+ ?line {STRes5,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupA006.xsd','./msxsdtest/Group',invalid),
+ STResList6 = [STRes5|STResList5],
+
+
+ ?line {STRes6,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupA007.xsd','./msxsdtest/Group',invalid),
+ STResList7 = [STRes6|STResList6],
+
+
+ ?line {STRes7,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupA008.xsd','./msxsdtest/Group',invalid),
+ STResList8 = [STRes7|STResList7],
+
+
+ ?line {STRes8,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupA009.xsd','./msxsdtest/Group',invalid),
+ STResList9 = [STRes8|STResList8],
+
+
+ ?line {STRes9,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupA010.xsd','./msxsdtest/Group',invalid),
+ STResList10 = [STRes9|STResList9],
+
+
+ ?line {STRes10,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupA011.xsd','./msxsdtest/Group',valid),
+ STResList11 = [STRes10|STResList10],
+
+
+ ?line {STRes11,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupA012.xsd','./msxsdtest/Group',invalid),
+ STResList12 = [STRes11|STResList11],
+
+
+ ?line {STRes12,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupB001.xsd','./msxsdtest/Group',invalid),
+ STResList13 = [STRes12|STResList12],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupB002.xsd','./msxsdtest/Group',valid),
+ STResList14 = [STRes13|STResList13],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupB002.xml','./msxsdtest/Group',valid,S13),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupB003.xsd','./msxsdtest/Group',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupB003.xml','./msxsdtest/Group',valid,S14),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupB004.xsd','./msxsdtest/Group',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupB004.xml','./msxsdtest/Group',valid,S15),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupB005.xsd','./msxsdtest/Group',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupB005.xml','./msxsdtest/Group',valid,S16),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupB006.xsd','./msxsdtest/Group',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupB006.xml','./msxsdtest/Group',valid,S17),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes18,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupB007.xsd','./msxsdtest/Group',invalid),
+ STResList19 = [STRes18|STResList18],
+
+
+ ?line {STRes19,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupB008.xsd','./msxsdtest/Group',invalid),
+ STResList20 = [STRes19|STResList19],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupB009.xsd','./msxsdtest/Group',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupB009.xml','./msxsdtest/Group',valid,S20),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupB010.xsd','./msxsdtest/Group',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupB010.xml','./msxsdtest/Group',valid,S21),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes22,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupB011.xsd','./msxsdtest/Group',invalid),
+ STResList23 = [STRes22|STResList22],
+
+
+ ?line {STRes23,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupB012.xsd','./msxsdtest/Group',invalid),
+ STResList24 = [STRes23|STResList23],
+
+
+ ?line {STRes24,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupB013.xsd','./msxsdtest/Group',invalid),
+ STResList25 = [STRes24|STResList24],
+
+
+ ?line {STRes25,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupB014.xsd','./msxsdtest/Group',invalid),
+ STResList26 = [STRes25|STResList25],
+
+
+ ?line {STRes26,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupB015.xsd','./msxsdtest/Group',invalid),
+ STResList27 = [STRes26|STResList26],
+
+
+ ?line {STRes27,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupB016.xsd','./msxsdtest/Group',invalid),
+ STResList28 = [STRes27|STResList27],
+
+
+ ?line {STRes28,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupB017.xsd','./msxsdtest/Group',valid),
+ STResList29 = [STRes28|STResList28],
+
+
+ ?line {STRes29,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupC001.xsd','./msxsdtest/Group',invalid),
+ STResList30 = [STRes29|STResList29],
+
+
+ ?line {STRes30,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupC002.xsd','./msxsdtest/Group',invalid),
+ STResList31 = [STRes30|STResList30],
+
+
+ ?line {STRes31,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupC003.xsd','./msxsdtest/Group',invalid),
+ STResList32 = [STRes31|STResList31],
+
+
+ ?line {STRes32,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupC004.xsd','./msxsdtest/Group',invalid),
+ STResList33 = [STRes32|STResList32],
+
+
+ ?line {STRes33,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupC005.xsd','./msxsdtest/Group',invalid),
+ STResList34 = [STRes33|STResList33],
+
+
+ ?line {STRes34,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupC006.xsd','./msxsdtest/Group',invalid),
+ STResList35 = [STRes34|STResList34],
+
+
+ ?line {STRes35,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupC007.xsd','./msxsdtest/Group',invalid),
+ STResList36 = [STRes35|STResList35],
+
+
+ ?line {STRes36,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupC008.xsd','./msxsdtest/Group',invalid),
+ STResList37 = [STRes36|STResList36],
+
+
+ ?line {STRes37,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupC009.xsd','./msxsdtest/Group',invalid),
+ STResList38 = [STRes37|STResList37],
+
+
+ ?line {STRes38,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupC010.xsd','./msxsdtest/Group',invalid),
+ STResList39 = [STRes38|STResList38],
+
+
+ ?line {STRes39,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupC011.xsd','./msxsdtest/Group',valid),
+ STResList40 = [STRes39|STResList39],
+
+
+ ?line {STRes40,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupC012.xsd','./msxsdtest/Group',invalid),
+ STResList41 = [STRes40|STResList40],
+
+
+ ?line {STRes41,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupD001.xsd','./msxsdtest/Group',invalid),
+ STResList42 = [STRes41|STResList41],
+
+
+ ?line {STRes42,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupD002.xsd','./msxsdtest/Group',invalid),
+ STResList43 = [STRes42|STResList42],
+
+
+ ?line {STRes43,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupD003.xsd','./msxsdtest/Group',invalid),
+ STResList44 = [STRes43|STResList43],
+
+
+ ?line {STRes44,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupD004.xsd','./msxsdtest/Group',invalid),
+ STResList45 = [STRes44|STResList44],
+
+
+ ?line {STRes45,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupE001.xsd','./msxsdtest/Group',valid),
+ STResList46 = [STRes45|STResList45],
+
+
+ ?line {STRes46,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupE002.xsd','./msxsdtest/Group',invalid),
+ STResList47 = [STRes46|STResList46],
+
+
+ ?line {STRes47,S47} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupE003.xsd','./msxsdtest/Group',valid),
+ STResList48 = [STRes47|STResList47],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupE003.xml','./msxsdtest/Group',invalid,S47),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes48,S48} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupE004.xsd','./msxsdtest/Group',valid),
+ STResList49 = [STRes48|STResList48],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupE004.xml','./msxsdtest/Group',valid,S48),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes49,S49} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupE005.xsd','./msxsdtest/Group',valid),
+ STResList50 = [STRes49|STResList49],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupE005.xml','./msxsdtest/Group',invalid,S49),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes50,S50} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF001.xsd','./msxsdtest/Group',valid),
+ STResList51 = [STRes50|STResList50],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF001.xml','./msxsdtest/Group',valid,S50),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes51,S51} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF002.xsd','./msxsdtest/Group',valid),
+ STResList52 = [STRes51|STResList51],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF002.xml','./msxsdtest/Group',valid,S51),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes52,S52} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF003.xsd','./msxsdtest/Group',valid),
+ STResList53 = [STRes52|STResList52],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF003.xml','./msxsdtest/Group',invalid,S52),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes53,S53} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF004.xsd','./msxsdtest/Group',valid),
+ STResList54 = [STRes53|STResList53],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF004.xml','./msxsdtest/Group',valid,S53),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes54,S54} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF005.xsd','./msxsdtest/Group',valid),
+ STResList55 = [STRes54|STResList54],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF005.xml','./msxsdtest/Group',valid,S54),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes55,S55} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF006.xsd','./msxsdtest/Group',valid),
+ STResList56 = [STRes55|STResList55],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF006.xml','./msxsdtest/Group',invalid,S55),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes56,S56} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF007.xsd','./msxsdtest/Group',valid),
+ STResList57 = [STRes56|STResList56],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF007.xml','./msxsdtest/Group',valid,S56),
+ ITResList17 = [ITRes16|ITResList16],
+
+
+ ?line {STRes57,S57} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF008.xsd','./msxsdtest/Group',valid),
+ STResList58 = [STRes57|STResList57],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF008.xml','./msxsdtest/Group',invalid,S57),
+ ITResList18 = [ITRes17|ITResList17],
+
+
+ ?line {STRes58,S58} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF009.xsd','./msxsdtest/Group',valid),
+ STResList59 = [STRes58|STResList58],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF009.xml','./msxsdtest/Group',valid,S58),
+ ITResList19 = [ITRes18|ITResList18],
+
+
+ ?line {STRes59,S59} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF010.xsd','./msxsdtest/Group',valid),
+ STResList60 = [STRes59|STResList59],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF010.xml','./msxsdtest/Group',invalid,S59),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes60,S60} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF011.xsd','./msxsdtest/Group',valid),
+ STResList61 = [STRes60|STResList60],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF011.xml','./msxsdtest/Group',valid,S60),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes61,S61} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF012.xsd','./msxsdtest/Group',valid),
+ STResList62 = [STRes61|STResList61],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF012.xml','./msxsdtest/Group',invalid,S61),
+ ITResList22 = [ITRes21|ITResList21],
+
+
+ ?line {STRes62,S62} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF013.xsd','./msxsdtest/Group',valid),
+ STResList63 = [STRes62|STResList62],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF013.xml','./msxsdtest/Group',invalid,S62),
+ ITResList23 = [ITRes22|ITResList22],
+
+
+ ?line {STRes63,S63} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF014.xsd','./msxsdtest/Group',valid),
+ STResList64 = [STRes63|STResList63],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF014.xml','./msxsdtest/Group',valid,S63),
+ ITResList24 = [ITRes23|ITResList23],
+
+
+ ?line {STRes64,S64} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF015.xsd','./msxsdtest/Group',valid),
+ STResList65 = [STRes64|STResList64],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF015.xml','./msxsdtest/Group',invalid,S64),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes65,S65} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF016.xsd','./msxsdtest/Group',valid),
+ STResList66 = [STRes65|STResList65],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF016.xml','./msxsdtest/Group',invalid,S65),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes66,S66} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF017.xsd','./msxsdtest/Group',valid),
+ STResList67 = [STRes66|STResList66],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF017.xml','./msxsdtest/Group',valid,S66),
+ ITResList27 = [ITRes26|ITResList26],
+
+
+ ?line {STRes67,S67} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF018.xsd','./msxsdtest/Group',valid),
+ STResList68 = [STRes67|STResList67],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF018.xml','./msxsdtest/Group',valid,S67),
+ ITResList28 = [ITRes27|ITResList27],
+
+
+ ?line {STRes68,S68} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF019.xsd','./msxsdtest/Group',valid),
+ STResList69 = [STRes68|STResList68],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF019.xml','./msxsdtest/Group',invalid,S68),
+ ITResList29 = [ITRes28|ITResList28],
+
+
+ ?line {STRes69,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF020.xsd','./msxsdtest/Group',invalid),
+ STResList70 = [STRes69|STResList69],
+
+
+ ?line {STRes70,S70} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF021.xsd','./msxsdtest/Group',valid),
+ STResList71 = [STRes70|STResList70],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupF021.xml','./msxsdtest/Group',valid,S70),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes71,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF022.xsd','./msxsdtest/Group',invalid),
+ STResList72 = [STRes71|STResList71],
+
+
+ ?line {STRes72,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF023.xsd','./msxsdtest/Group',invalid),
+ STResList73 = [STRes72|STResList72],
+
+
+ ?line {STRes73,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF024.xsd','./msxsdtest/Group',invalid),
+ STResList74 = [STRes73|STResList73],
+
+
+ ?line {STRes74,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupF025.xsd','./msxsdtest/Group',invalid),
+ STResList75 = [STRes74|STResList74],
+
+
+ ?line {STRes75,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupG001.xsd','./msxsdtest/Group',valid),
+ STResList76 = [STRes75|STResList75],
+
+
+ ?line {STRes76,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupG002.xsd','./msxsdtest/Group',invalid),
+ STResList77 = [STRes76|STResList76],
+
+
+ ?line {STRes77,S77} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupG003.xsd','./msxsdtest/Group',valid),
+ STResList78 = [STRes77|STResList77],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupG003.xml','./msxsdtest/Group',invalid,S77),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes78,S78} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupG004.xsd','./msxsdtest/Group',valid),
+ STResList79 = [STRes78|STResList78],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupG004.xml','./msxsdtest/Group',valid,S78),
+ ITResList32 = [ITRes31|ITResList31],
+
+
+ ?line {STRes79,S79} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupG005.xsd','./msxsdtest/Group',valid),
+ STResList80 = [STRes79|STResList79],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupG005.xml','./msxsdtest/Group',invalid,S79),
+ ITResList33 = [ITRes32|ITResList32],
+
+
+ ?line {STRes80,S80} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH001.xsd','./msxsdtest/Group',valid),
+ STResList81 = [STRes80|STResList80],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH001.xml','./msxsdtest/Group',valid,S80),
+ ITResList34 = [ITRes33|ITResList33],
+
+
+ ?line {STRes81,S81} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH002.xsd','./msxsdtest/Group',valid),
+ STResList82 = [STRes81|STResList81],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH002.xml','./msxsdtest/Group',valid,S81),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes82,S82} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH003.xsd','./msxsdtest/Group',valid),
+ STResList83 = [STRes82|STResList82],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH003.xml','./msxsdtest/Group',invalid,S82),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes83,S83} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH004.xsd','./msxsdtest/Group',valid),
+ STResList84 = [STRes83|STResList83],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH004.xml','./msxsdtest/Group',valid,S83),
+ ITResList37 = [ITRes36|ITResList36],
+
+
+ ?line {STRes84,S84} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH005.xsd','./msxsdtest/Group',valid),
+ STResList85 = [STRes84|STResList84],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH005.xml','./msxsdtest/Group',valid,S84),
+ ITResList38 = [ITRes37|ITResList37],
+
+
+ ?line {STRes85,S85} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH006.xsd','./msxsdtest/Group',valid),
+ STResList86 = [STRes85|STResList85],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH006.xml','./msxsdtest/Group',invalid,S85),
+ ITResList39 = [ITRes38|ITResList38],
+
+
+ ?line {STRes86,S86} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH007.xsd','./msxsdtest/Group',valid),
+ STResList87 = [STRes86|STResList86],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH007.xml','./msxsdtest/Group',valid,S86),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes87,S87} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH008.xsd','./msxsdtest/Group',valid),
+ STResList88 = [STRes87|STResList87],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH008.xml','./msxsdtest/Group',invalid,S87),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes88,S88} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH009.xsd','./msxsdtest/Group',valid),
+ STResList89 = [STRes88|STResList88],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH009.xml','./msxsdtest/Group',valid,S88),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes89,S89} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH010.xsd','./msxsdtest/Group',valid),
+ STResList90 = [STRes89|STResList89],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH010.xml','./msxsdtest/Group',invalid,S89),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes90,S90} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH011.xsd','./msxsdtest/Group',valid),
+ STResList91 = [STRes90|STResList90],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH011.xml','./msxsdtest/Group',valid,S90),
+ ITResList44 = [ITRes43|ITResList43],
+
+
+ ?line {STRes91,S91} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH012.xsd','./msxsdtest/Group',valid),
+ STResList92 = [STRes91|STResList91],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH012.xml','./msxsdtest/Group',invalid,S91),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes92,S92} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH013.xsd','./msxsdtest/Group',valid),
+ STResList93 = [STRes92|STResList92],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH013.xml','./msxsdtest/Group',invalid,S92),
+ ITResList46 = [ITRes45|ITResList45],
+
+
+ ?line {STRes93,S93} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH014.xsd','./msxsdtest/Group',valid),
+ STResList94 = [STRes93|STResList93],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH014.xml','./msxsdtest/Group',valid,S93),
+ ITResList47 = [ITRes46|ITResList46],
+
+
+ ?line {STRes94,S94} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH015.xsd','./msxsdtest/Group',valid),
+ STResList95 = [STRes94|STResList94],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH015.xml','./msxsdtest/Group',invalid,S94),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes95,S95} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH016.xsd','./msxsdtest/Group',valid),
+ STResList96 = [STRes95|STResList95],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH016.xml','./msxsdtest/Group',invalid,S95),
+ ITResList49 = [ITRes48|ITResList48],
+
+
+ ?line {STRes96,S96} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH017.xsd','./msxsdtest/Group',valid),
+ STResList97 = [STRes96|STResList96],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH017.xml','./msxsdtest/Group',valid,S96),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes97,S97} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH018.xsd','./msxsdtest/Group',valid),
+ STResList98 = [STRes97|STResList97],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH018.xml','./msxsdtest/Group',valid,S97),
+ ITResList51 = [ITRes50|ITResList50],
+
+
+ ?line {STRes98,S98} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH019.xsd','./msxsdtest/Group',valid),
+ STResList99 = [STRes98|STResList98],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH019.xml','./msxsdtest/Group',invalid,S98),
+ ITResList52 = [ITRes51|ITResList51],
+
+
+ ?line {STRes99,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH020.xsd','./msxsdtest/Group',invalid),
+ STResList100 = [STRes99|STResList99],
+
+
+ ?line {STRes100,S100} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH021.xsd','./msxsdtest/Group',valid),
+ STResList101 = [STRes100|STResList100],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupH021.xml','./msxsdtest/Group',valid,S100),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes101,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH022.xsd','./msxsdtest/Group',invalid),
+ STResList102 = [STRes101|STResList101],
+
+
+ ?line {STRes102,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH023.xsd','./msxsdtest/Group',invalid),
+ STResList103 = [STRes102|STResList102],
+
+
+ ?line {STRes103,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH024.xsd','./msxsdtest/Group',invalid),
+ STResList104 = [STRes103|STResList103],
+
+
+ ?line {STRes104,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupH025.xsd','./msxsdtest/Group',invalid),
+ STResList105 = [STRes104|STResList104],
+
+
+ ?line {STRes105,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupI001.xsd','./msxsdtest/Group',valid),
+ STResList106 = [STRes105|STResList105],
+
+
+ ?line {STRes106,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupI002.xsd','./msxsdtest/Group',invalid),
+ STResList107 = [STRes106|STResList106],
+
+
+ ?line {STRes107,S107} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupI003.xsd','./msxsdtest/Group',valid),
+ STResList108 = [STRes107|STResList107],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupI003.xml','./msxsdtest/Group',invalid,S107),
+ ITResList54 = [ITRes53|ITResList53],
+
+
+ ?line {STRes108,S108} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupI004.xsd','./msxsdtest/Group',valid),
+ STResList109 = [STRes108|STResList108],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupI004.xml','./msxsdtest/Group',valid,S108),
+ ITResList55 = [ITRes54|ITResList54],
+
+
+ ?line {STRes109,S109} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupI005.xsd','./msxsdtest/Group',valid),
+ STResList110 = [STRes109|STResList109],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupI005.xml','./msxsdtest/Group',invalid,S109),
+ ITResList56 = [ITRes55|ITResList55],
+
+
+ ?line {STRes110,S110} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ001.xsd','./msxsdtest/Group',valid),
+ STResList111 = [STRes110|STResList110],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ001.xml','./msxsdtest/Group',valid,S110),
+ ITResList57 = [ITRes56|ITResList56],
+
+
+ ?line {STRes111,S111} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ002.xsd','./msxsdtest/Group',valid),
+ STResList112 = [STRes111|STResList111],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ002.xml','./msxsdtest/Group',valid,S111),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes112,S112} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ003.xsd','./msxsdtest/Group',valid),
+ STResList113 = [STRes112|STResList112],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ003.xml','./msxsdtest/Group',invalid,S112),
+ ITResList59 = [ITRes58|ITResList58],
+
+
+ ?line {STRes113,S113} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ004.xsd','./msxsdtest/Group',valid),
+ STResList114 = [STRes113|STResList113],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ004.xml','./msxsdtest/Group',valid,S113),
+ ITResList60 = [ITRes59|ITResList59],
+
+
+ ?line {STRes114,S114} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ005.xsd','./msxsdtest/Group',valid),
+ STResList115 = [STRes114|STResList114],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ005.xml','./msxsdtest/Group',valid,S114),
+ ITResList61 = [ITRes60|ITResList60],
+
+
+ ?line {STRes115,S115} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ006.xsd','./msxsdtest/Group',valid),
+ STResList116 = [STRes115|STResList115],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ006.xml','./msxsdtest/Group',invalid,S115),
+ ITResList62 = [ITRes61|ITResList61],
+
+
+ ?line {STRes116,S116} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ007.xsd','./msxsdtest/Group',valid),
+ STResList117 = [STRes116|STResList116],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ007.xml','./msxsdtest/Group',valid,S116),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes117,S117} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ008.xsd','./msxsdtest/Group',valid),
+ STResList118 = [STRes117|STResList117],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ008.xml','./msxsdtest/Group',invalid,S117),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes118,S118} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ009.xsd','./msxsdtest/Group',valid),
+ STResList119 = [STRes118|STResList118],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ009.xml','./msxsdtest/Group',valid,S118),
+ ITResList65 = [ITRes64|ITResList64],
+
+
+ ?line {STRes119,S119} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ010.xsd','./msxsdtest/Group',valid),
+ STResList120 = [STRes119|STResList119],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ010.xml','./msxsdtest/Group',invalid,S119),
+ ITResList66 = [ITRes65|ITResList65],
+
+
+ ?line {STRes120,S120} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ011.xsd','./msxsdtest/Group',valid),
+ STResList121 = [STRes120|STResList120],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ011.xml','./msxsdtest/Group',valid,S120),
+ ITResList67 = [ITRes66|ITResList66],
+
+
+ ?line {STRes121,S121} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ012.xsd','./msxsdtest/Group',valid),
+ STResList122 = [STRes121|STResList121],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ012.xml','./msxsdtest/Group',invalid,S121),
+ ITResList68 = [ITRes67|ITResList67],
+
+
+ ?line {STRes122,S122} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ013.xsd','./msxsdtest/Group',valid),
+ STResList123 = [STRes122|STResList122],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ013.xml','./msxsdtest/Group',invalid,S122),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes123,S123} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ014.xsd','./msxsdtest/Group',valid),
+ STResList124 = [STRes123|STResList123],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ014.xml','./msxsdtest/Group',valid,S123),
+ ITResList70 = [ITRes69|ITResList69],
+
+
+ ?line {STRes124,S124} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ015.xsd','./msxsdtest/Group',valid),
+ STResList125 = [STRes124|STResList124],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ015.xml','./msxsdtest/Group',invalid,S124),
+ ITResList71 = [ITRes70|ITResList70],
+
+
+ ?line {STRes125,S125} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ016.xsd','./msxsdtest/Group',valid),
+ STResList126 = [STRes125|STResList125],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ016.xml','./msxsdtest/Group',invalid,S125),
+ ITResList72 = [ITRes71|ITResList71],
+
+
+ ?line {STRes126,S126} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ017.xsd','./msxsdtest/Group',valid),
+ STResList127 = [STRes126|STResList126],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ017.xml','./msxsdtest/Group',valid,S126),
+ ITResList73 = [ITRes72|ITResList72],
+
+
+ ?line {STRes127,S127} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ018.xsd','./msxsdtest/Group',valid),
+ STResList128 = [STRes127|STResList127],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ018.xml','./msxsdtest/Group',valid,S127),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes128,S128} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ019.xsd','./msxsdtest/Group',valid),
+ STResList129 = [STRes128|STResList128],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ019.xml','./msxsdtest/Group',invalid,S128),
+ ITResList75 = [ITRes74|ITResList74],
+
+
+ ?line {STRes129,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ020.xsd','./msxsdtest/Group',invalid),
+ STResList130 = [STRes129|STResList129],
+
+
+ ?line {STRes130,S130} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ021.xsd','./msxsdtest/Group',valid),
+ STResList131 = [STRes130|STResList130],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupJ021.xml','./msxsdtest/Group',valid,S130),
+ ITResList76 = [ITRes75|ITResList75],
+
+
+ ?line {STRes131,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ022.xsd','./msxsdtest/Group',invalid),
+ STResList132 = [STRes131|STResList131],
+
+
+ ?line {STRes132,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ023.xsd','./msxsdtest/Group',invalid),
+ STResList133 = [STRes132|STResList132],
+
+
+ ?line {STRes133,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ024.xsd','./msxsdtest/Group',invalid),
+ STResList134 = [STRes133|STResList133],
+
+
+ ?line {STRes134,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupJ025.xsd','./msxsdtest/Group',invalid),
+ STResList135 = [STRes134|STResList134],
+
+
+ ?line {STRes135,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupK001.xsd','./msxsdtest/Group',valid),
+ STResList136 = [STRes135|STResList135],
+
+
+ ?line {STRes136,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupK002.xsd','./msxsdtest/Group',invalid),
+ STResList137 = [STRes136|STResList136],
+
+
+ ?line {STRes137,S137} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupK003.xsd','./msxsdtest/Group',valid),
+ STResList138 = [STRes137|STResList137],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupK003.xml','./msxsdtest/Group',invalid,S137),
+ ITResList77 = [ITRes76|ITResList76],
+
+
+ ?line {STRes138,S138} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupK004.xsd','./msxsdtest/Group',valid),
+ STResList139 = [STRes138|STResList138],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupK004.xml','./msxsdtest/Group',valid,S138),
+ ITResList78 = [ITRes77|ITResList77],
+
+
+ ?line {STRes139,S139} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupK005.xsd','./msxsdtest/Group',valid),
+ STResList140 = [STRes139|STResList139],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupK005.xml','./msxsdtest/Group',invalid,S139),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes140,S140} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL001.xsd','./msxsdtest/Group',valid),
+ STResList141 = [STRes140|STResList140],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL001.xml','./msxsdtest/Group',valid,S140),
+ ITResList80 = [ITRes79|ITResList79],
+
+
+ ?line {STRes141,S141} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL002.xsd','./msxsdtest/Group',valid),
+ STResList142 = [STRes141|STResList141],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL002.xml','./msxsdtest/Group',valid,S141),
+ ITResList81 = [ITRes80|ITResList80],
+
+
+ ?line {STRes142,S142} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL003.xsd','./msxsdtest/Group',valid),
+ STResList143 = [STRes142|STResList142],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL003.xml','./msxsdtest/Group',invalid,S142),
+ ITResList82 = [ITRes81|ITResList81],
+
+
+ ?line {STRes143,S143} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL004.xsd','./msxsdtest/Group',valid),
+ STResList144 = [STRes143|STResList143],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL004.xml','./msxsdtest/Group',valid,S143),
+ ITResList83 = [ITRes82|ITResList82],
+
+
+ ?line {STRes144,S144} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL005.xsd','./msxsdtest/Group',valid),
+ STResList145 = [STRes144|STResList144],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL005.xml','./msxsdtest/Group',valid,S144),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes145,S145} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL006.xsd','./msxsdtest/Group',valid),
+ STResList146 = [STRes145|STResList145],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL006.xml','./msxsdtest/Group',invalid,S145),
+ ITResList85 = [ITRes84|ITResList84],
+
+
+ ?line {STRes146,S146} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL007.xsd','./msxsdtest/Group',valid),
+ STResList147 = [STRes146|STResList146],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL007.xml','./msxsdtest/Group',valid,S146),
+ ITResList86 = [ITRes85|ITResList85],
+
+
+ ?line {STRes147,S147} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL008.xsd','./msxsdtest/Group',valid),
+ STResList148 = [STRes147|STResList147],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL008.xml','./msxsdtest/Group',invalid,S147),
+ ITResList87 = [ITRes86|ITResList86],
+
+
+ ?line {STRes148,S148} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL009.xsd','./msxsdtest/Group',valid),
+ STResList149 = [STRes148|STResList148],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL009.xml','./msxsdtest/Group',valid,S148),
+ ITResList88 = [ITRes87|ITResList87],
+
+
+ ?line {STRes149,S149} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL010.xsd','./msxsdtest/Group',valid),
+ STResList150 = [STRes149|STResList149],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL010.xml','./msxsdtest/Group',invalid,S149),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes150,S150} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL011.xsd','./msxsdtest/Group',valid),
+ STResList151 = [STRes150|STResList150],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL011.xml','./msxsdtest/Group',valid,S150),
+ ITResList90 = [ITRes89|ITResList89],
+
+
+ ?line {STRes151,S151} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL012.xsd','./msxsdtest/Group',valid),
+ STResList152 = [STRes151|STResList151],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL012.xml','./msxsdtest/Group',invalid,S151),
+ ITResList91 = [ITRes90|ITResList90],
+
+
+ ?line {STRes152,S152} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL013.xsd','./msxsdtest/Group',valid),
+ STResList153 = [STRes152|STResList152],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL013.xml','./msxsdtest/Group',invalid,S152),
+ ITResList92 = [ITRes91|ITResList91],
+
+
+ ?line {STRes153,S153} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL014.xsd','./msxsdtest/Group',valid),
+ STResList154 = [STRes153|STResList153],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL014.xml','./msxsdtest/Group',valid,S153),
+ ITResList93 = [ITRes92|ITResList92],
+
+
+ ?line {STRes154,S154} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL015.xsd','./msxsdtest/Group',valid),
+ STResList155 = [STRes154|STResList154],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL015.xml','./msxsdtest/Group',invalid,S154),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes155,S155} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL016.xsd','./msxsdtest/Group',valid),
+ STResList156 = [STRes155|STResList155],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL016.xml','./msxsdtest/Group',invalid,S155),
+ ITResList95 = [ITRes94|ITResList94],
+
+
+ ?line {STRes156,S156} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL017.xsd','./msxsdtest/Group',valid),
+ STResList157 = [STRes156|STResList156],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL017.xml','./msxsdtest/Group',valid,S156),
+ ITResList96 = [ITRes95|ITResList95],
+
+
+ ?line {STRes157,S157} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL018.xsd','./msxsdtest/Group',valid),
+ STResList158 = [STRes157|STResList157],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL018.xml','./msxsdtest/Group',valid,S157),
+ ITResList97 = [ITRes96|ITResList96],
+
+
+ ?line {STRes158,S158} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL019.xsd','./msxsdtest/Group',valid),
+ STResList159 = [STRes158|STResList158],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL019.xml','./msxsdtest/Group',invalid,S158),
+ ITResList98 = [ITRes97|ITResList97],
+
+
+ ?line {STRes159,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL020.xsd','./msxsdtest/Group',invalid),
+ STResList160 = [STRes159|STResList159],
+
+
+ ?line {STRes160,S160} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL021.xsd','./msxsdtest/Group',valid),
+ STResList161 = [STRes160|STResList160],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupL021.xml','./msxsdtest/Group',valid,S160),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes161,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL022.xsd','./msxsdtest/Group',invalid),
+ STResList162 = [STRes161|STResList161],
+
+
+ ?line {STRes162,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL023.xsd','./msxsdtest/Group',invalid),
+ STResList163 = [STRes162|STResList162],
+
+
+ ?line {STRes163,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL024.xsd','./msxsdtest/Group',invalid),
+ STResList164 = [STRes163|STResList163],
+
+
+ ?line {STRes164,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupL025.xsd','./msxsdtest/Group',invalid),
+ STResList165 = [STRes164|STResList164],
+
+
+ ?line {STRes165,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupM001.xsd','./msxsdtest/Group',valid),
+ STResList166 = [STRes165|STResList165],
+
+
+ ?line {STRes166,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupM002.xsd','./msxsdtest/Group',invalid),
+ STResList167 = [STRes166|STResList166],
+
+
+ ?line {STRes167,S167} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupM003.xsd','./msxsdtest/Group',valid),
+ STResList168 = [STRes167|STResList167],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupM003.xml','./msxsdtest/Group',invalid,S167),
+ ITResList100 = [ITRes99|ITResList99],
+
+
+ ?line {STRes168,S168} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupM004.xsd','./msxsdtest/Group',valid),
+ STResList169 = [STRes168|STResList168],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupM004.xml','./msxsdtest/Group',valid,S168),
+ ITResList101 = [ITRes100|ITResList100],
+
+
+ ?line {STRes169,S169} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupM005.xsd','./msxsdtest/Group',valid),
+ STResList170 = [STRes169|STResList169],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupM005.xml','./msxsdtest/Group',invalid,S169),
+ ITResList102 = [ITRes101|ITResList101],
+
+
+ ?line {STRes170,S170} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN001.xsd','./msxsdtest/Group',valid),
+ STResList171 = [STRes170|STResList170],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN001.xml','./msxsdtest/Group',valid,S170),
+ ITResList103 = [ITRes102|ITResList102],
+
+
+ ?line {STRes171,S171} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN002.xsd','./msxsdtest/Group',valid),
+ STResList172 = [STRes171|STResList171],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN002.xml','./msxsdtest/Group',valid,S171),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes172,S172} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN003.xsd','./msxsdtest/Group',valid),
+ STResList173 = [STRes172|STResList172],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN003.xml','./msxsdtest/Group',invalid,S172),
+ ITResList105 = [ITRes104|ITResList104],
+
+
+ ?line {STRes173,S173} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN004.xsd','./msxsdtest/Group',valid),
+ STResList174 = [STRes173|STResList173],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN004.xml','./msxsdtest/Group',valid,S173),
+ ITResList106 = [ITRes105|ITResList105],
+
+
+ ?line {STRes174,S174} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN005.xsd','./msxsdtest/Group',valid),
+ STResList175 = [STRes174|STResList174],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN005.xml','./msxsdtest/Group',valid,S174),
+ ITResList107 = [ITRes106|ITResList106],
+
+
+ ?line {STRes175,S175} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN006.xsd','./msxsdtest/Group',valid),
+ STResList176 = [STRes175|STResList175],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN006.xml','./msxsdtest/Group',invalid,S175),
+ ITResList108 = [ITRes107|ITResList107],
+
+
+ ?line {STRes176,S176} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN007.xsd','./msxsdtest/Group',valid),
+ STResList177 = [STRes176|STResList176],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN007.xml','./msxsdtest/Group',valid,S176),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes177,S177} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN008.xsd','./msxsdtest/Group',valid),
+ STResList178 = [STRes177|STResList177],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN008.xml','./msxsdtest/Group',invalid,S177),
+ ITResList110 = [ITRes109|ITResList109],
+
+
+ ?line {STRes178,S178} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN009.xsd','./msxsdtest/Group',valid),
+ STResList179 = [STRes178|STResList178],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN009.xml','./msxsdtest/Group',valid,S178),
+ ITResList111 = [ITRes110|ITResList110],
+
+
+ ?line {STRes179,S179} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN010.xsd','./msxsdtest/Group',valid),
+ STResList180 = [STRes179|STResList179],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN010.xml','./msxsdtest/Group',invalid,S179),
+ ITResList112 = [ITRes111|ITResList111],
+
+
+ ?line {STRes180,S180} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN011.xsd','./msxsdtest/Group',valid),
+ STResList181 = [STRes180|STResList180],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN011.xml','./msxsdtest/Group',valid,S180),
+ ITResList113 = [ITRes112|ITResList112],
+
+
+ ?line {STRes181,S181} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN012.xsd','./msxsdtest/Group',valid),
+ STResList182 = [STRes181|STResList181],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN012.xml','./msxsdtest/Group',invalid,S181),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes182,S182} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN013.xsd','./msxsdtest/Group',valid),
+ STResList183 = [STRes182|STResList182],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN013.xml','./msxsdtest/Group',invalid,S182),
+ ITResList115 = [ITRes114|ITResList114],
+
+
+ ?line {STRes183,S183} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN014.xsd','./msxsdtest/Group',valid),
+ STResList184 = [STRes183|STResList183],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN014.xml','./msxsdtest/Group',valid,S183),
+ ITResList116 = [ITRes115|ITResList115],
+
+
+ ?line {STRes184,S184} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN015.xsd','./msxsdtest/Group',valid),
+ STResList185 = [STRes184|STResList184],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN015.xml','./msxsdtest/Group',invalid,S184),
+ ITResList117 = [ITRes116|ITResList116],
+
+
+ ?line {STRes185,S185} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN016.xsd','./msxsdtest/Group',valid),
+ STResList186 = [STRes185|STResList185],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN016.xml','./msxsdtest/Group',invalid,S185),
+ ITResList118 = [ITRes117|ITResList117],
+
+
+ ?line {STRes186,S186} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN017.xsd','./msxsdtest/Group',valid),
+ STResList187 = [STRes186|STResList186],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN017.xml','./msxsdtest/Group',valid,S186),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes187,S187} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN018.xsd','./msxsdtest/Group',valid),
+ STResList188 = [STRes187|STResList187],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN018.xml','./msxsdtest/Group',valid,S187),
+ ITResList120 = [ITRes119|ITResList119],
+
+
+ ?line {STRes188,S188} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN019.xsd','./msxsdtest/Group',valid),
+ STResList189 = [STRes188|STResList188],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN019.xml','./msxsdtest/Group',invalid,S188),
+ ITResList121 = [ITRes120|ITResList120],
+
+
+ ?line {STRes189,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN020.xsd','./msxsdtest/Group',invalid),
+ STResList190 = [STRes189|STResList189],
+
+
+ ?line {STRes190,S190} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN021.xsd','./msxsdtest/Group',valid),
+ STResList191 = [STRes190|STResList190],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupN021.xml','./msxsdtest/Group',valid,S190),
+ ITResList122 = [ITRes121|ITResList121],
+
+
+ ?line {STRes191,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN022.xsd','./msxsdtest/Group',invalid),
+ STResList192 = [STRes191|STResList191],
+
+
+ ?line {STRes192,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN023.xsd','./msxsdtest/Group',invalid),
+ STResList193 = [STRes192|STResList192],
+
+
+ ?line {STRes193,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN024.xsd','./msxsdtest/Group',invalid),
+ STResList194 = [STRes193|STResList193],
+
+
+ ?line {STRes194,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupN025.xsd','./msxsdtest/Group',invalid),
+ STResList195 = [STRes194|STResList194],
+
+
+ ?line {STRes195,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO001.xsd','./msxsdtest/Group',valid),
+ STResList196 = [STRes195|STResList195],
+
+
+ ?line {STRes196,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO002.xsd','./msxsdtest/Group',invalid),
+ STResList197 = [STRes196|STResList196],
+
+
+ ?line {STRes197,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO003.xsd','./msxsdtest/Group',invalid),
+ STResList198 = [STRes197|STResList197],
+
+
+ ?line {STRes198,S198} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO004.xsd','./msxsdtest/Group',valid),
+ STResList199 = [STRes198|STResList198],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupO004.xml','./msxsdtest/Group',valid,S198),
+ ITResList123 = [ITRes122|ITResList122],
+
+
+ ?line {STRes199,S199} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO005.xsd','./msxsdtest/Group',valid),
+ STResList200 = [STRes199|STResList199],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupO005.xml','./msxsdtest/Group',invalid,S199),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes200,S200} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO006.xsd','./msxsdtest/Group',valid),
+ STResList201 = [STRes200|STResList200],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupO006.xml','./msxsdtest/Group',valid,S200),
+ ITResList125 = [ITRes124|ITResList124],
+
+
+ ?line {STRes201,S201} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO007.xsd','./msxsdtest/Group',valid),
+ STResList202 = [STRes201|STResList201],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupO007.xml','./msxsdtest/Group',invalid,S201),
+ ITResList126 = [ITRes125|ITResList125],
+
+
+ ?line {STRes202,S202} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO008.xsd','./msxsdtest/Group',valid),
+ STResList203 = [STRes202|STResList202],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupO008.xml','./msxsdtest/Group',valid,S202),
+ ITResList127 = [ITRes126|ITResList126],
+
+
+ ?line {STRes203,S203} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO009.xsd','./msxsdtest/Group',valid),
+ STResList204 = [STRes203|STResList203],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Group/groupO009.xml','./msxsdtest/Group',invalid,S203),
+ ITResList128 = [ITRes127|ITResList127],
+
+
+ ?line {STRes204,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO010.xsd','./msxsdtest/Group',invalid),
+ STResList205 = [STRes204|STResList204],
+
+
+ ?line {STRes205,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO011.xsd','./msxsdtest/Group',invalid),
+ STResList206 = [STRes205|STResList205],
+
+
+ ?line {STRes206,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO012.xsd','./msxsdtest/Group',invalid),
+ STResList207 = [STRes206|STResList206],
+
+
+ ?line {STRes207,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO013.xsd','./msxsdtest/Group',invalid),
+ STResList208 = [STRes207|STResList207],
+
+
+ ?line {STRes208,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO014.xsd','./msxsdtest/Group',valid),
+ STResList209 = [STRes208|STResList208],
+
+
+ ?line {STRes209,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO015.xsd','./msxsdtest/Group',invalid),
+ STResList210 = [STRes209|STResList209],
+
+
+ ?line {STRes210,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO016.xsd','./msxsdtest/Group',invalid),
+ STResList211 = [STRes210|STResList210],
+
+
+ ?line {STRes211,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO017.xsd','./msxsdtest/Group',invalid),
+ STResList212 = [STRes211|STResList211],
+
+
+ ?line {STRes212,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO018.xsd','./msxsdtest/Group',invalid),
+ STResList213 = [STRes212|STResList212],
+
+
+ ?line {STRes213,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO019.xsd','./msxsdtest/Group',invalid),
+ STResList214 = [STRes213|STResList213],
+
+
+ ?line {STRes214,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO020.xsd','./msxsdtest/Group',invalid),
+ STResList215 = [STRes214|STResList214],
+
+
+ ?line {STRes215,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO021.xsd','./msxsdtest/Group',invalid),
+ STResList216 = [STRes215|STResList215],
+
+
+ ?line {STRes216,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO022.xsd','./msxsdtest/Group',invalid),
+ STResList217 = [STRes216|STResList216],
+
+
+ ?line {STRes217,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO023.xsd','./msxsdtest/Group',invalid),
+ STResList218 = [STRes217|STResList217],
+
+
+ ?line {STRes218,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO024.xsd','./msxsdtest/Group',invalid),
+ STResList219 = [STRes218|STResList218],
+
+
+ ?line {STRes219,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO025.xsd','./msxsdtest/Group',invalid),
+ STResList220 = [STRes219|STResList219],
+
+
+ ?line {STRes220,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO026.xsd','./msxsdtest/Group',invalid),
+ STResList221 = [STRes220|STResList220],
+
+
+ ?line {STRes221,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Group/groupO027.xsd','./msxsdtest/Group',invalid),
+ STResList222 = [STRes221|STResList221],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList222,ITResList128).
+
+%% 3.11.1 The Identity-constraint Definition Schema Component.
+
+idc_(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_string.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S1),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_token.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S2),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_language.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_language.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S3),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_Name.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_Name.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S4),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_NCName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_NCName.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S5),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_ID.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_ID.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S6),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_IDREF.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_IDREF.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S7),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S8),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S9),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S10),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S11),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S12),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S13),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S14),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_nonPositiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_nonPositiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S15),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_negativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_negativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S16),
+ ITResList17 = [ITRes16|ITResList16],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_long.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S17),
+ ITResList18 = [ITRes17|ITResList17],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_int.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S18),
+ ITResList19 = [ITRes18|ITResList18],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_short.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S19),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S20),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S21),
+ ITResList22 = [ITRes21|ITResList21],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S22),
+ ITResList23 = [ITRes22|ITResList22],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S23),
+ ITResList24 = [ITRes23|ITResList23],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S24),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S25),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S26),
+ ITResList27 = [ITRes26|ITResList26],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S27),
+ ITResList28 = [ITRes27|ITResList27],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S28),
+ ITResList29 = [ITRes28|ITResList28],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_QName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_QName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S29),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_NOTATION.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_NOTATION.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S30),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes31,S31} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList32 = [STRes31|STResList31],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S31),
+ ITResList32 = [ITRes31|ITResList31],
+
+
+ ?line {STRes32,S32} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_dateTime.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList33 = [STRes32|STResList32],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_dateTime.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S32),
+ ITResList33 = [ITRes32|ITResList32],
+
+
+ ?line {STRes33,S33} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_time.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList34 = [STRes33|STResList33],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_time.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S33),
+ ITResList34 = [ITRes33|ITResList33],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_date.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_date.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S34),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes35,S35} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_gYearMonth.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList36 = [STRes35|STResList35],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_gYearMonth.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S35),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes36,S36} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_gYear.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList37 = [STRes36|STResList36],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_gYear.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S36),
+ ITResList37 = [ITRes36|ITResList36],
+
+
+ ?line {STRes37,S37} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_gMonthDay.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList38 = [STRes37|STResList37],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_gMonthDay.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S37),
+ ITResList38 = [ITRes37|ITResList37],
+
+
+ ?line {STRes38,S38} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_gDay.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList39 = [STRes38|STResList38],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_gDay.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S38),
+ ITResList39 = [ITRes38|ITResList38],
+
+
+ ?line {STRes39,S39} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_gMonth.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList40 = [STRes39|STResList39],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_string_gMonth.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S39),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes40,S40} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList41 = [STRes40|STResList40],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_string.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S40),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes41,S41} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList42 = [STRes41|STResList41],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S41),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes42,S42} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList43 = [STRes42|STResList42],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_token.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S42),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes43,S43} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_language.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList44 = [STRes43|STResList43],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_language.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S43),
+ ITResList44 = [ITRes43|ITResList43],
+
+
+ ?line {STRes44,S44} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_Name.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList45 = [STRes44|STResList44],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_Name.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S44),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes45,S45} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_NCName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList46 = [STRes45|STResList45],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_NCName.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S45),
+ ITResList46 = [ITRes45|ITResList45],
+
+
+ ?line {STRes46,S46} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_ID.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList47 = [STRes46|STResList46],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_ID.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S46),
+ ITResList47 = [ITRes46|ITResList46],
+
+
+ ?line {STRes47,S47} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_IDREF.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList48 = [STRes47|STResList47],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_IDREF.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S47),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes48,S48} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList49 = [STRes48|STResList48],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S48),
+ ITResList49 = [ITRes48|ITResList48],
+
+
+ ?line {STRes49,S49} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList50 = [STRes49|STResList49],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S49),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes50,S50} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList51 = [STRes50|STResList50],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S50),
+ ITResList51 = [ITRes50|ITResList50],
+
+
+ ?line {STRes51,S51} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList52 = [STRes51|STResList51],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S51),
+ ITResList52 = [ITRes51|ITResList51],
+
+
+ ?line {STRes52,S52} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList53 = [STRes52|STResList52],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S52),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes53,S53} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList54 = [STRes53|STResList53],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S53),
+ ITResList54 = [ITRes53|ITResList53],
+
+
+ ?line {STRes54,S54} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList55 = [STRes54|STResList54],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S54),
+ ITResList55 = [ITRes54|ITResList54],
+
+
+ ?line {STRes55,S55} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_nonPositiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList56 = [STRes55|STResList55],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_nonPositiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S55),
+ ITResList56 = [ITRes55|ITResList55],
+
+
+ ?line {STRes56,S56} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_negativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList57 = [STRes56|STResList56],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_negativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S56),
+ ITResList57 = [ITRes56|ITResList56],
+
+
+ ?line {STRes57,S57} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList58 = [STRes57|STResList57],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_long.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S57),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes58,S58} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList59 = [STRes58|STResList58],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_int.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S58),
+ ITResList59 = [ITRes58|ITResList58],
+
+
+ ?line {STRes59,S59} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList60 = [STRes59|STResList59],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_short.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S59),
+ ITResList60 = [ITRes59|ITResList59],
+
+
+ ?line {STRes60,S60} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList61 = [STRes60|STResList60],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S60),
+ ITResList61 = [ITRes60|ITResList60],
+
+
+ ?line {STRes61,S61} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList62 = [STRes61|STResList61],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S61),
+ ITResList62 = [ITRes61|ITResList61],
+
+
+ ?line {STRes62,S62} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList63 = [STRes62|STResList62],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S62),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes63,S63} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList64 = [STRes63|STResList63],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S63),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes64,S64} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList65 = [STRes64|STResList64],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S64),
+ ITResList65 = [ITRes64|ITResList64],
+
+
+ ?line {STRes65,S65} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList66 = [STRes65|STResList65],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S65),
+ ITResList66 = [ITRes65|ITResList65],
+
+
+ ?line {STRes66,S66} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList67 = [STRes66|STResList66],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S66),
+ ITResList67 = [ITRes66|ITResList66],
+
+
+ ?line {STRes67,S67} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList68 = [STRes67|STResList67],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S67),
+ ITResList68 = [ITRes67|ITResList67],
+
+
+ ?line {STRes68,S68} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList69 = [STRes68|STResList68],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S68),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes69,S69} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_QName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList70 = [STRes69|STResList69],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_QName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S69),
+ ITResList70 = [ITRes69|ITResList69],
+
+
+ ?line {STRes70,S70} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_NOTATION.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList71 = [STRes70|STResList70],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_NOTATION.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S70),
+ ITResList71 = [ITRes70|ITResList70],
+
+
+ ?line {STRes71,S71} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList72 = [STRes71|STResList71],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S71),
+ ITResList72 = [ITRes71|ITResList71],
+
+
+ ?line {STRes72,S72} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_dateTime.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList73 = [STRes72|STResList72],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_dateTime.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S72),
+ ITResList73 = [ITRes72|ITResList72],
+
+
+ ?line {STRes73,S73} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_time.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList74 = [STRes73|STResList73],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_time.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S73),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes74,S74} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_date.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList75 = [STRes74|STResList74],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_date.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S74),
+ ITResList75 = [ITRes74|ITResList74],
+
+
+ ?line {STRes75,S75} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_gYearMonth.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList76 = [STRes75|STResList75],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_gYearMonth.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S75),
+ ITResList76 = [ITRes75|ITResList75],
+
+
+ ?line {STRes76,S76} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_gYear.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList77 = [STRes76|STResList76],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_gYear.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S76),
+ ITResList77 = [ITRes76|ITResList76],
+
+
+ ?line {STRes77,S77} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_gMonthDay.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList78 = [STRes77|STResList77],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_gMonthDay.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S77),
+ ITResList78 = [ITRes77|ITResList77],
+
+
+ ?line {STRes78,S78} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_gDay.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList79 = [STRes78|STResList78],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_gDay.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S78),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes79,S79} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_gMonth.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList80 = [STRes79|STResList79],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_normalizedString_gMonth.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S79),
+ ITResList80 = [ITRes79|ITResList79],
+
+
+ ?line {STRes80,S80} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList81 = [STRes80|STResList80],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_string.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S80),
+ ITResList81 = [ITRes80|ITResList80],
+
+
+ ?line {STRes81,S81} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList82 = [STRes81|STResList81],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S81),
+ ITResList82 = [ITRes81|ITResList81],
+
+
+ ?line {STRes82,S82} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList83 = [STRes82|STResList82],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_token.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S82),
+ ITResList83 = [ITRes82|ITResList82],
+
+
+ ?line {STRes83,S83} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_language.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList84 = [STRes83|STResList83],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_language.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S83),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes84,S84} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_Name.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList85 = [STRes84|STResList84],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_Name.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S84),
+ ITResList85 = [ITRes84|ITResList84],
+
+
+ ?line {STRes85,S85} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_NCName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList86 = [STRes85|STResList85],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_NCName.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S85),
+ ITResList86 = [ITRes85|ITResList85],
+
+
+ ?line {STRes86,S86} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_ID.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList87 = [STRes86|STResList86],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_ID.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S86),
+ ITResList87 = [ITRes86|ITResList86],
+
+
+ ?line {STRes87,S87} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_IDREF.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList88 = [STRes87|STResList87],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_IDREF.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S87),
+ ITResList88 = [ITRes87|ITResList87],
+
+
+ ?line {STRes88,S88} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList89 = [STRes88|STResList88],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S88),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes89,S89} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList90 = [STRes89|STResList89],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S89),
+ ITResList90 = [ITRes89|ITResList89],
+
+
+ ?line {STRes90,S90} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList91 = [STRes90|STResList90],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S90),
+ ITResList91 = [ITRes90|ITResList90],
+
+
+ ?line {STRes91,S91} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList92 = [STRes91|STResList91],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S91),
+ ITResList92 = [ITRes91|ITResList91],
+
+
+ ?line {STRes92,S92} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList93 = [STRes92|STResList92],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S92),
+ ITResList93 = [ITRes92|ITResList92],
+
+
+ ?line {STRes93,S93} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList94 = [STRes93|STResList93],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S93),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes94,S94} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList95 = [STRes94|STResList94],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S94),
+ ITResList95 = [ITRes94|ITResList94],
+
+
+ ?line {STRes95,S95} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_nonPositiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList96 = [STRes95|STResList95],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_nonPositiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S95),
+ ITResList96 = [ITRes95|ITResList95],
+
+
+ ?line {STRes96,S96} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_negativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList97 = [STRes96|STResList96],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_negativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S96),
+ ITResList97 = [ITRes96|ITResList96],
+
+
+ ?line {STRes97,S97} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList98 = [STRes97|STResList97],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_long.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S97),
+ ITResList98 = [ITRes97|ITResList97],
+
+
+ ?line {STRes98,S98} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList99 = [STRes98|STResList98],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_int.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S98),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes99,S99} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList100 = [STRes99|STResList99],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_short.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S99),
+ ITResList100 = [ITRes99|ITResList99],
+
+
+ ?line {STRes100,S100} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList101 = [STRes100|STResList100],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S100),
+ ITResList101 = [ITRes100|ITResList100],
+
+
+ ?line {STRes101,S101} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList102 = [STRes101|STResList101],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S101),
+ ITResList102 = [ITRes101|ITResList101],
+
+
+ ?line {STRes102,S102} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList103 = [STRes102|STResList102],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S102),
+ ITResList103 = [ITRes102|ITResList102],
+
+
+ ?line {STRes103,S103} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList104 = [STRes103|STResList103],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S103),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes104,S104} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList105 = [STRes104|STResList104],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S104),
+ ITResList105 = [ITRes104|ITResList104],
+
+
+ ?line {STRes105,S105} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList106 = [STRes105|STResList105],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S105),
+ ITResList106 = [ITRes105|ITResList105],
+
+
+ ?line {STRes106,S106} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList107 = [STRes106|STResList106],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S106),
+ ITResList107 = [ITRes106|ITResList106],
+
+
+ ?line {STRes107,S107} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList108 = [STRes107|STResList107],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S107),
+ ITResList108 = [ITRes107|ITResList107],
+
+
+ ?line {STRes108,S108} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList109 = [STRes108|STResList108],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S108),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes109,S109} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_QName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList110 = [STRes109|STResList109],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_QName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S109),
+ ITResList110 = [ITRes109|ITResList109],
+
+
+ ?line {STRes110,S110} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_NOTATION.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList111 = [STRes110|STResList110],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_NOTATION.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S110),
+ ITResList111 = [ITRes110|ITResList110],
+
+
+ ?line {STRes111,S111} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList112 = [STRes111|STResList111],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S111),
+ ITResList112 = [ITRes111|ITResList111],
+
+
+ ?line {STRes112,S112} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_dateTime.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList113 = [STRes112|STResList112],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_dateTime.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S112),
+ ITResList113 = [ITRes112|ITResList112],
+
+
+ ?line {STRes113,S113} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_time.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList114 = [STRes113|STResList113],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_time.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S113),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes114,S114} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_date.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList115 = [STRes114|STResList114],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_date.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S114),
+ ITResList115 = [ITRes114|ITResList114],
+
+
+ ?line {STRes115,S115} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_gYearMonth.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList116 = [STRes115|STResList115],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_gYearMonth.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S115),
+ ITResList116 = [ITRes115|ITResList115],
+
+
+ ?line {STRes116,S116} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_gYear.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList117 = [STRes116|STResList116],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_gYear.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S116),
+ ITResList117 = [ITRes116|ITResList116],
+
+
+ ?line {STRes117,S117} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_gMonthDay.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList118 = [STRes117|STResList117],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_gMonthDay.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S117),
+ ITResList118 = [ITRes117|ITResList117],
+
+
+ ?line {STRes118,S118} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_gDay.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList119 = [STRes118|STResList118],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_gDay.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S118),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes119,S119} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_gMonth.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList120 = [STRes119|STResList119],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_token_gMonth.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S119),
+ ITResList120 = [ITRes119|ITResList119],
+
+
+ ?line {STRes120,S120} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList121 = [STRes120|STResList120],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_string.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S120),
+ ITResList121 = [ITRes120|ITResList120],
+
+
+ ?line {STRes121,S121} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList122 = [STRes121|STResList121],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S121),
+ ITResList122 = [ITRes121|ITResList121],
+
+
+ ?line {STRes122,S122} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList123 = [STRes122|STResList122],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_token.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S122),
+ ITResList123 = [ITRes122|ITResList122],
+
+
+ ?line {STRes123,S123} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_language.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList124 = [STRes123|STResList123],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_language.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S123),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes124,S124} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_Name.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList125 = [STRes124|STResList124],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_Name.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S124),
+ ITResList125 = [ITRes124|ITResList124],
+
+
+ ?line {STRes125,S125} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_NCName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList126 = [STRes125|STResList125],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_NCName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S125),
+ ITResList126 = [ITRes125|ITResList125],
+
+
+ ?line {STRes126,S126} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_ID.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList127 = [STRes126|STResList126],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_ID.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S126),
+ ITResList127 = [ITRes126|ITResList126],
+
+
+ ?line {STRes127,S127} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_IDREF.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList128 = [STRes127|STResList127],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_IDREF.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S127),
+ ITResList128 = [ITRes127|ITResList127],
+
+
+ ?line {STRes128,S128} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_IDREFS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList129 = [STRes128|STResList128],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_IDREFS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S128),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes129,S129} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList130 = [STRes129|STResList129],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S129),
+ ITResList130 = [ITRes129|ITResList129],
+
+
+ ?line {STRes130,S130} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList131 = [STRes130|STResList130],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S130),
+ ITResList131 = [ITRes130|ITResList130],
+
+
+ ?line {STRes131,S131} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList132 = [STRes131|STResList131],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S131),
+ ITResList132 = [ITRes131|ITResList131],
+
+
+ ?line {STRes132,S132} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_QName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList133 = [STRes132|STResList132],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_QName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S132),
+ ITResList133 = [ITRes132|ITResList132],
+
+
+ ?line {STRes133,S133} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_NOTATION.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList134 = [STRes133|STResList133],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_language_NOTATION.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S133),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes134,S134} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList135 = [STRes134|STResList134],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_string.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S134),
+ ITResList135 = [ITRes134|ITResList134],
+
+
+ ?line {STRes135,S135} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList136 = [STRes135|STResList135],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S135),
+ ITResList136 = [ITRes135|ITResList135],
+
+
+ ?line {STRes136,S136} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList137 = [STRes136|STResList136],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_token.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S136),
+ ITResList137 = [ITRes136|ITResList136],
+
+
+ ?line {STRes137,S137} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_language.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList138 = [STRes137|STResList137],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_language.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S137),
+ ITResList138 = [ITRes137|ITResList137],
+
+
+ ?line {STRes138,S138} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_Name.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList139 = [STRes138|STResList138],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_Name.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S138),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ ?line {STRes139,S139} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_NCName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList140 = [STRes139|STResList139],
+ ?line ITRes139 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_NCName.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S139),
+ ITResList140 = [ITRes139|ITResList139],
+
+
+ ?line {STRes140,S140} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_ID.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList141 = [STRes140|STResList140],
+ ?line ITRes140 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_ID.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S140),
+ ITResList141 = [ITRes140|ITResList140],
+
+
+ ?line {STRes141,S141} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_IDREF.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList142 = [STRes141|STResList141],
+ ?line ITRes141 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_IDREF.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S141),
+ ITResList142 = [ITRes141|ITResList141],
+
+
+ ?line {STRes142,S142} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList143 = [STRes142|STResList142],
+ ?line ITRes142 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S142),
+ ITResList143 = [ITRes142|ITResList142],
+
+
+ ?line {STRes143,S143} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList144 = [STRes143|STResList143],
+ ?line ITRes143 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S143),
+ ITResList144 = [ITRes143|ITResList143],
+
+
+ ?line {STRes144,S144} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList145 = [STRes144|STResList144],
+ ?line ITRes144 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S144),
+ ITResList145 = [ITRes144|ITResList144],
+
+
+ ?line {STRes145,S145} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList146 = [STRes145|STResList145],
+ ?line ITRes145 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S145),
+ ITResList146 = [ITRes145|ITResList145],
+
+
+ ?line {STRes146,S146} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_QName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList147 = [STRes146|STResList146],
+ ?line ITRes146 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_QName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S146),
+ ITResList147 = [ITRes146|ITResList146],
+
+
+ ?line {STRes147,S147} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_NOTATION.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList148 = [STRes147|STResList147],
+ ?line ITRes147 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_NOTATION.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S147),
+ ITResList148 = [ITRes147|ITResList147],
+
+
+ ?line {STRes148,S148} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList149 = [STRes148|STResList148],
+ ?line ITRes148 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_Name_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S148),
+ ITResList149 = [ITRes148|ITResList148],
+
+
+ ?line {STRes149,S149} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList150 = [STRes149|STResList149],
+ ?line ITRes149 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_string.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S149),
+ ITResList150 = [ITRes149|ITResList149],
+
+
+ ?line {STRes150,S150} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList151 = [STRes150|STResList150],
+ ?line ITRes150 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S150),
+ ITResList151 = [ITRes150|ITResList150],
+
+
+ ?line {STRes151,S151} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList152 = [STRes151|STResList151],
+ ?line ITRes151 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_token.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S151),
+ ITResList152 = [ITRes151|ITResList151],
+
+
+ ?line {STRes152,S152} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_language.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList153 = [STRes152|STResList152],
+ ?line ITRes152 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_language.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S152),
+ ITResList153 = [ITRes152|ITResList152],
+
+
+ ?line {STRes153,S153} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_Name.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList154 = [STRes153|STResList153],
+ ?line ITRes153 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_Name.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S153),
+ ITResList154 = [ITRes153|ITResList153],
+
+
+ ?line {STRes154,S154} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_NCName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList155 = [STRes154|STResList154],
+ ?line ITRes154 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_NCName.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S154),
+ ITResList155 = [ITRes154|ITResList154],
+
+
+ ?line {STRes155,S155} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_ID.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList156 = [STRes155|STResList155],
+ ?line ITRes155 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_ID.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S155),
+ ITResList156 = [ITRes155|ITResList155],
+
+
+ ?line {STRes156,S156} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_IDREF.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList157 = [STRes156|STResList156],
+ ?line ITRes156 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_IDREF.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S156),
+ ITResList157 = [ITRes156|ITResList156],
+
+
+ ?line {STRes157,S157} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList158 = [STRes157|STResList157],
+ ?line ITRes157 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S157),
+ ITResList158 = [ITRes157|ITResList157],
+
+
+ ?line {STRes158,S158} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList159 = [STRes158|STResList158],
+ ?line ITRes158 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S158),
+ ITResList159 = [ITRes158|ITResList158],
+
+
+ ?line {STRes159,S159} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList160 = [STRes159|STResList159],
+ ?line ITRes159 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S159),
+ ITResList160 = [ITRes159|ITResList159],
+
+
+ ?line {STRes160,S160} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList161 = [STRes160|STResList160],
+ ?line ITRes160 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S160),
+ ITResList161 = [ITRes160|ITResList160],
+
+
+ ?line {STRes161,S161} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_QName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList162 = [STRes161|STResList161],
+ ?line ITRes161 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_QName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S161),
+ ITResList162 = [ITRes161|ITResList161],
+
+
+ ?line {STRes162,S162} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_NOTATION.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList163 = [STRes162|STResList162],
+ ?line ITRes162 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_NOTATION.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S162),
+ ITResList163 = [ITRes162|ITResList162],
+
+
+ ?line {STRes163,S163} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList164 = [STRes163|STResList163],
+ ?line ITRes163 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NCName_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S163),
+ ITResList164 = [ITRes163|ITResList163],
+
+
+ ?line {STRes164,S164} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList165 = [STRes164|STResList164],
+ ?line ITRes164 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_string.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S164),
+ ITResList165 = [ITRes164|ITResList164],
+
+
+ ?line {STRes165,S165} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList166 = [STRes165|STResList165],
+ ?line ITRes165 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S165),
+ ITResList166 = [ITRes165|ITResList165],
+
+
+ ?line {STRes166,S166} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList167 = [STRes166|STResList166],
+ ?line ITRes166 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_token.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S166),
+ ITResList167 = [ITRes166|ITResList166],
+
+
+ ?line {STRes167,S167} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_language.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList168 = [STRes167|STResList167],
+ ?line ITRes167 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_language.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S167),
+ ITResList168 = [ITRes167|ITResList167],
+
+
+ ?line {STRes168,S168} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_Name.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList169 = [STRes168|STResList168],
+ ?line ITRes168 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_Name.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S168),
+ ITResList169 = [ITRes168|ITResList168],
+
+
+ ?line {STRes169,S169} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_NCName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList170 = [STRes169|STResList169],
+ ?line ITRes169 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_NCName.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S169),
+ ITResList170 = [ITRes169|ITResList169],
+
+
+ ?line {STRes170,S170} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_ID.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList171 = [STRes170|STResList170],
+ ?line ITRes170 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_ID.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S170),
+ ITResList171 = [ITRes170|ITResList170],
+
+
+ ?line {STRes171,S171} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_IDREF.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList172 = [STRes171|STResList171],
+ ?line ITRes171 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_IDREF.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S171),
+ ITResList172 = [ITRes171|ITResList171],
+
+
+ ?line {STRes172,S172} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_IDREFS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList173 = [STRes172|STResList172],
+ ?line ITRes172 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_IDREFS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S172),
+ ITResList173 = [ITRes172|ITResList172],
+
+
+ ?line {STRes173,S173} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList174 = [STRes173|STResList173],
+ ?line ITRes173 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S173),
+ ITResList174 = [ITRes173|ITResList173],
+
+
+ ?line {STRes174,S174} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList175 = [STRes174|STResList174],
+ ?line ITRes174 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S174),
+ ITResList175 = [ITRes174|ITResList174],
+
+
+ ?line {STRes175,S175} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList176 = [STRes175|STResList175],
+ ?line ITRes175 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S175),
+ ITResList176 = [ITRes175|ITResList175],
+
+
+ ?line {STRes176,S176} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList177 = [STRes176|STResList176],
+ ?line ITRes176 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S176),
+ ITResList177 = [ITRes176|ITResList176],
+
+
+ ?line {STRes177,S177} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_QName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList178 = [STRes177|STResList177],
+ ?line ITRes177 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_QName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S177),
+ ITResList178 = [ITRes177|ITResList177],
+
+
+ ?line {STRes178,S178} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_NOTATION.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList179 = [STRes178|STResList178],
+ ?line ITRes178 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_NOTATION.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S178),
+ ITResList179 = [ITRes178|ITResList178],
+
+
+ ?line {STRes179,S179} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList180 = [STRes179|STResList179],
+ ?line ITRes179 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_ID_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S179),
+ ITResList180 = [ITRes179|ITResList179],
+
+
+ ?line {STRes180,S180} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList181 = [STRes180|STResList180],
+ ?line ITRes180 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_string.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S180),
+ ITResList181 = [ITRes180|ITResList180],
+
+
+ ?line {STRes181,S181} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList182 = [STRes181|STResList181],
+ ?line ITRes181 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S181),
+ ITResList182 = [ITRes181|ITResList181],
+
+
+ ?line {STRes182,S182} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList183 = [STRes182|STResList182],
+ ?line ITRes182 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_token.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S182),
+ ITResList183 = [ITRes182|ITResList182],
+
+
+ ?line {STRes183,S183} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_language.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList184 = [STRes183|STResList183],
+ ?line ITRes183 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_language.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S183),
+ ITResList184 = [ITRes183|ITResList183],
+
+
+ ?line {STRes184,S184} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_Name.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList185 = [STRes184|STResList184],
+ ?line ITRes184 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_Name.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S184),
+ ITResList185 = [ITRes184|ITResList184],
+
+
+ ?line {STRes185,S185} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_NCName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList186 = [STRes185|STResList185],
+ ?line ITRes185 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_NCName.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S185),
+ ITResList186 = [ITRes185|ITResList185],
+
+
+ ?line {STRes186,S186} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_ID.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList187 = [STRes186|STResList186],
+ ?line ITRes186 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_ID.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S186),
+ ITResList187 = [ITRes186|ITResList186],
+
+
+ ?line {STRes187,S187} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_IDREF.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList188 = [STRes187|STResList187],
+ ?line ITRes187 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_IDREF.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S187),
+ ITResList188 = [ITRes187|ITResList187],
+
+
+ ?line {STRes188,S188} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList189 = [STRes188|STResList188],
+ ?line ITRes188 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S188),
+ ITResList189 = [ITRes188|ITResList188],
+
+
+ ?line {STRes189,S189} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList190 = [STRes189|STResList189],
+ ?line ITRes189 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S189),
+ ITResList190 = [ITRes189|ITResList189],
+
+
+ ?line {STRes190,S190} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList191 = [STRes190|STResList190],
+ ?line ITRes190 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S190),
+ ITResList191 = [ITRes190|ITResList190],
+
+
+ ?line {STRes191,S191} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList192 = [STRes191|STResList191],
+ ?line ITRes191 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S191),
+ ITResList192 = [ITRes191|ITResList191],
+
+
+ ?line {STRes192,S192} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_QName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList193 = [STRes192|STResList192],
+ ?line ITRes192 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_QName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S192),
+ ITResList193 = [ITRes192|ITResList192],
+
+
+ ?line {STRes193,S193} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_NOTATION.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList194 = [STRes193|STResList193],
+ ?line ITRes193 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_NOTATION.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S193),
+ ITResList194 = [ITRes193|ITResList193],
+
+
+ ?line {STRes194,S194} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList195 = [STRes194|STResList194],
+ ?line ITRes194 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREF_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S194),
+ ITResList195 = [ITRes194|ITResList194],
+
+
+ ?line {STRes195,S195} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREFS_language.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList196 = [STRes195|STResList195],
+ ?line ITRes195 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREFS_language.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S195),
+ ITResList196 = [ITRes195|ITResList195],
+
+
+ ?line {STRes196,S196} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREFS_ID.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList197 = [STRes196|STResList196],
+ ?line ITRes196 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREFS_ID.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S196),
+ ITResList197 = [ITRes196|ITResList196],
+
+
+ ?line {STRes197,S197} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREFS_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList198 = [STRes197|STResList197],
+ ?line ITRes197 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREFS_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S197),
+ ITResList198 = [ITRes197|ITResList197],
+
+
+ ?line {STRes198,S198} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREFS_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList199 = [STRes198|STResList198],
+ ?line ITRes198 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREFS_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S198),
+ ITResList199 = [ITRes198|ITResList198],
+
+
+ ?line {STRes199,S199} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREFS_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList200 = [STRes199|STResList199],
+ ?line ITRes199 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREFS_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S199),
+ ITResList200 = [ITRes199|ITResList199],
+
+
+ ?line {STRes200,S200} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREFS_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList201 = [STRes200|STResList200],
+ ?line ITRes200 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREFS_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S200),
+ ITResList201 = [ITRes200|ITResList200],
+
+
+ ?line {STRes201,S201} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREFS_QName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList202 = [STRes201|STResList201],
+ ?line ITRes201 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREFS_QName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S201),
+ ITResList202 = [ITRes201|ITResList201],
+
+
+ ?line {STRes202,S202} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREFS_NOTATION.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList203 = [STRes202|STResList202],
+ ?line ITRes202 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREFS_NOTATION.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S202),
+ ITResList203 = [ITRes202|ITResList202],
+
+
+ ?line {STRes203,S203} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREFS_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList204 = [STRes203|STResList203],
+ ?line ITRes203 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_IDREFS_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S203),
+ ITResList204 = [ITRes203|ITResList203],
+
+
+ ?line {STRes204,S204} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList205 = [STRes204|STResList204],
+ ?line ITRes204 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_string.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S204),
+ ITResList205 = [ITRes204|ITResList204],
+
+
+ ?line {STRes205,S205} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList206 = [STRes205|STResList205],
+ ?line ITRes205 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S205),
+ ITResList206 = [ITRes205|ITResList205],
+
+
+ ?line {STRes206,S206} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList207 = [STRes206|STResList206],
+ ?line ITRes206 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_token.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S206),
+ ITResList207 = [ITRes206|ITResList206],
+
+
+ ?line {STRes207,S207} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_language.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList208 = [STRes207|STResList207],
+ ?line ITRes207 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_language.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S207),
+ ITResList208 = [ITRes207|ITResList207],
+
+
+ ?line {STRes208,S208} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_Name.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList209 = [STRes208|STResList208],
+ ?line ITRes208 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_Name.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S208),
+ ITResList209 = [ITRes208|ITResList208],
+
+
+ ?line {STRes209,S209} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_NCName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList210 = [STRes209|STResList209],
+ ?line ITRes209 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_NCName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S209),
+ ITResList210 = [ITRes209|ITResList209],
+
+
+ ?line {STRes210,S210} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_ID.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList211 = [STRes210|STResList210],
+ ?line ITRes210 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_ID.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S210),
+ ITResList211 = [ITRes210|ITResList210],
+
+
+ ?line {STRes211,S211} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_IDREF.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList212 = [STRes211|STResList211],
+ ?line ITRes211 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_IDREF.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S211),
+ ITResList212 = [ITRes211|ITResList211],
+
+
+ ?line {STRes212,S212} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_IDREFS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList213 = [STRes212|STResList212],
+ ?line ITRes212 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_IDREFS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S212),
+ ITResList213 = [ITRes212|ITResList212],
+
+
+ ?line {STRes213,S213} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList214 = [STRes213|STResList213],
+ ?line ITRes213 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S213),
+ ITResList214 = [ITRes213|ITResList213],
+
+
+ ?line {STRes214,S214} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList215 = [STRes214|STResList214],
+ ?line ITRes214 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S214),
+ ITResList215 = [ITRes214|ITResList214],
+
+
+ ?line {STRes215,S215} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList216 = [STRes215|STResList215],
+ ?line ITRes215 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S215),
+ ITResList216 = [ITRes215|ITResList215],
+
+
+ ?line {STRes216,S216} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList217 = [STRes216|STResList216],
+ ?line ITRes216 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S216),
+ ITResList217 = [ITRes216|ITResList216],
+
+
+ ?line {STRes217,S217} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList218 = [STRes217|STResList217],
+ ?line ITRes217 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S217),
+ ITResList218 = [ITRes217|ITResList217],
+
+
+ ?line {STRes218,S218} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList219 = [STRes218|STResList218],
+ ?line ITRes218 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S218),
+ ITResList219 = [ITRes218|ITResList218],
+
+
+ ?line {STRes219,S219} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList220 = [STRes219|STResList219],
+ ?line ITRes219 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S219),
+ ITResList220 = [ITRes219|ITResList219],
+
+
+ ?line {STRes220,S220} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_nonPositiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList221 = [STRes220|STResList220],
+ ?line ITRes220 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_nonPositiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S220),
+ ITResList221 = [ITRes220|ITResList220],
+
+
+ ?line {STRes221,S221} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_negativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList222 = [STRes221|STResList221],
+ ?line ITRes221 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_negativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S221),
+ ITResList222 = [ITRes221|ITResList221],
+
+
+ ?line {STRes222,S222} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList223 = [STRes222|STResList222],
+ ?line ITRes222 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_long.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S222),
+ ITResList223 = [ITRes222|ITResList222],
+
+
+ ?line {STRes223,S223} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList224 = [STRes223|STResList223],
+ ?line ITRes223 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_int.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S223),
+ ITResList224 = [ITRes223|ITResList223],
+
+
+ ?line {STRes224,S224} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList225 = [STRes224|STResList224],
+ ?line ITRes224 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_short.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S224),
+ ITResList225 = [ITRes224|ITResList224],
+
+
+ ?line {STRes225,S225} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList226 = [STRes225|STResList225],
+ ?line ITRes225 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S225),
+ ITResList226 = [ITRes225|ITResList225],
+
+
+ ?line {STRes226,S226} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList227 = [STRes226|STResList226],
+ ?line ITRes226 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S226),
+ ITResList227 = [ITRes226|ITResList226],
+
+
+ ?line {STRes227,S227} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList228 = [STRes227|STResList227],
+ ?line ITRes227 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S227),
+ ITResList228 = [ITRes227|ITResList227],
+
+
+ ?line {STRes228,S228} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList229 = [STRes228|STResList228],
+ ?line ITRes228 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S228),
+ ITResList229 = [ITRes228|ITResList228],
+
+
+ ?line {STRes229,S229} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList230 = [STRes229|STResList229],
+ ?line ITRes229 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S229),
+ ITResList230 = [ITRes229|ITResList229],
+
+
+ ?line {STRes230,S230} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList231 = [STRes230|STResList230],
+ ?line ITRes230 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S230),
+ ITResList231 = [ITRes230|ITResList230],
+
+
+ ?line {STRes231,S231} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList232 = [STRes231|STResList231],
+ ?line ITRes231 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S231),
+ ITResList232 = [ITRes231|ITResList231],
+
+
+ ?line {STRes232,S232} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList233 = [STRes232|STResList232],
+ ?line ITRes232 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S232),
+ ITResList233 = [ITRes232|ITResList232],
+
+
+ ?line {STRes233,S233} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList234 = [STRes233|STResList233],
+ ?line ITRes233 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S233),
+ ITResList234 = [ITRes233|ITResList233],
+
+
+ ?line {STRes234,S234} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_QName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList235 = [STRes234|STResList234],
+ ?line ITRes234 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_QName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S234),
+ ITResList235 = [ITRes234|ITResList234],
+
+
+ ?line {STRes235,S235} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_NOTATION.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList236 = [STRes235|STResList235],
+ ?line ITRes235 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_NOTATION.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S235),
+ ITResList236 = [ITRes235|ITResList235],
+
+
+ ?line {STRes236,S236} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList237 = [STRes236|STResList236],
+ ?line ITRes236 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S236),
+ ITResList237 = [ITRes236|ITResList236],
+
+
+ ?line {STRes237,S237} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_dateTime.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList238 = [STRes237|STResList237],
+ ?line ITRes237 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_dateTime.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S237),
+ ITResList238 = [ITRes237|ITResList237],
+
+
+ ?line {STRes238,S238} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_time.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList239 = [STRes238|STResList238],
+ ?line ITRes238 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_time.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S238),
+ ITResList239 = [ITRes238|ITResList238],
+
+
+ ?line {STRes239,S239} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_date.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList240 = [STRes239|STResList239],
+ ?line ITRes239 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_date.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S239),
+ ITResList240 = [ITRes239|ITResList239],
+
+
+ ?line {STRes240,S240} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_gYearMonth.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList241 = [STRes240|STResList240],
+ ?line ITRes240 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_gYearMonth.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S240),
+ ITResList241 = [ITRes240|ITResList240],
+
+
+ ?line {STRes241,S241} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_gYear.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList242 = [STRes241|STResList241],
+ ?line ITRes241 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_gYear.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S241),
+ ITResList242 = [ITRes241|ITResList241],
+
+
+ ?line {STRes242,S242} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_gMonthDay.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList243 = [STRes242|STResList242],
+ ?line ITRes242 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_gMonthDay.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S242),
+ ITResList243 = [ITRes242|ITResList242],
+
+
+ ?line {STRes243,S243} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_gDay.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList244 = [STRes243|STResList243],
+ ?line ITRes243 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_gDay.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S243),
+ ITResList244 = [ITRes243|ITResList243],
+
+
+ ?line {STRes244,S244} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_gMonth.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList245 = [STRes244|STResList244],
+ ?line ITRes244 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKEN_gMonth.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S244),
+ ITResList245 = [ITRes244|ITResList244],
+
+
+ ?line {STRes245,S245} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_language.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList246 = [STRes245|STResList245],
+ ?line ITRes245 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_language.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S245),
+ ITResList246 = [ITRes245|ITResList245],
+
+
+ ?line {STRes246,S246} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_Name.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList247 = [STRes246|STResList246],
+ ?line ITRes246 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_Name.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S246),
+ ITResList247 = [ITRes246|ITResList246],
+
+
+ ?line {STRes247,S247} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_NCName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList248 = [STRes247|STResList247],
+ ?line ITRes247 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_NCName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S247),
+ ITResList248 = [ITRes247|ITResList247],
+
+
+ ?line {STRes248,S248} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_ID.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList249 = [STRes248|STResList248],
+ ?line ITRes248 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_ID.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S248),
+ ITResList249 = [ITRes248|ITResList248],
+
+
+ ?line {STRes249,S249} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_IDREF.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList250 = [STRes249|STResList249],
+ ?line ITRes249 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_IDREF.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S249),
+ ITResList250 = [ITRes249|ITResList249],
+
+
+ ?line {STRes250,S250} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_IDREFS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList251 = [STRes250|STResList250],
+ ?line ITRes250 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_IDREFS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S250),
+ ITResList251 = [ITRes250|ITResList250],
+
+
+ ?line {STRes251,S251} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList252 = [STRes251|STResList251],
+ ?line ITRes251 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S251),
+ ITResList252 = [ITRes251|ITResList251],
+
+
+ ?line {STRes252,S252} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList253 = [STRes252|STResList252],
+ ?line ITRes252 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S252),
+ ITResList253 = [ITRes252|ITResList252],
+
+
+ ?line {STRes253,S253} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList254 = [STRes253|STResList253],
+ ?line ITRes253 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S253),
+ ITResList254 = [ITRes253|ITResList253],
+
+
+ ?line {STRes254,S254} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList255 = [STRes254|STResList254],
+ ?line ITRes254 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S254),
+ ITResList255 = [ITRes254|ITResList254],
+
+
+ ?line {STRes255,S255} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList256 = [STRes255|STResList255],
+ ?line ITRes255 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S255),
+ ITResList256 = [ITRes255|ITResList255],
+
+
+ ?line {STRes256,S256} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList257 = [STRes256|STResList256],
+ ?line ITRes256 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S256),
+ ITResList257 = [ITRes256|ITResList256],
+
+
+ ?line {STRes257,S257} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_nonPositiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList258 = [STRes257|STResList257],
+ ?line ITRes257 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_nonPositiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S257),
+ ITResList258 = [ITRes257|ITResList257],
+
+
+ ?line {STRes258,S258} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_negativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList259 = [STRes258|STResList258],
+ ?line ITRes258 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_negativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S258),
+ ITResList259 = [ITRes258|ITResList258],
+
+
+ ?line {STRes259,S259} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList260 = [STRes259|STResList259],
+ ?line ITRes259 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_long.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S259),
+ ITResList260 = [ITRes259|ITResList259],
+
+
+ ?line {STRes260,S260} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList261 = [STRes260|STResList260],
+ ?line ITRes260 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_int.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S260),
+ ITResList261 = [ITRes260|ITResList260],
+
+
+ ?line {STRes261,S261} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList262 = [STRes261|STResList261],
+ ?line ITRes261 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_short.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S261),
+ ITResList262 = [ITRes261|ITResList261],
+
+
+ ?line {STRes262,S262} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList263 = [STRes262|STResList262],
+ ?line ITRes262 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S262),
+ ITResList263 = [ITRes262|ITResList262],
+
+
+ ?line {STRes263,S263} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList264 = [STRes263|STResList263],
+ ?line ITRes263 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S263),
+ ITResList264 = [ITRes263|ITResList263],
+
+
+ ?line {STRes264,S264} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList265 = [STRes264|STResList264],
+ ?line ITRes264 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S264),
+ ITResList265 = [ITRes264|ITResList264],
+
+
+ ?line {STRes265,S265} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList266 = [STRes265|STResList265],
+ ?line ITRes265 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S265),
+ ITResList266 = [ITRes265|ITResList265],
+
+
+ ?line {STRes266,S266} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList267 = [STRes266|STResList266],
+ ?line ITRes266 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S266),
+ ITResList267 = [ITRes266|ITResList266],
+
+
+ ?line {STRes267,S267} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList268 = [STRes267|STResList267],
+ ?line ITRes267 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S267),
+ ITResList268 = [ITRes267|ITResList267],
+
+
+ ?line {STRes268,S268} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList269 = [STRes268|STResList268],
+ ?line ITRes268 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S268),
+ ITResList269 = [ITRes268|ITResList268],
+
+
+ ?line {STRes269,S269} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList270 = [STRes269|STResList269],
+ ?line ITRes269 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S269),
+ ITResList270 = [ITRes269|ITResList269],
+
+
+ ?line {STRes270,S270} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList271 = [STRes270|STResList270],
+ ?line ITRes270 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S270),
+ ITResList271 = [ITRes270|ITResList270],
+
+
+ ?line {STRes271,S271} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_QName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList272 = [STRes271|STResList271],
+ ?line ITRes271 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_QName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S271),
+ ITResList272 = [ITRes271|ITResList271],
+
+
+ ?line {STRes272,S272} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_NOTATION.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList273 = [STRes272|STResList272],
+ ?line ITRes272 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_NOTATION.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S272),
+ ITResList273 = [ITRes272|ITResList272],
+
+
+ ?line {STRes273,S273} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList274 = [STRes273|STResList273],
+ ?line ITRes273 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S273),
+ ITResList274 = [ITRes273|ITResList273],
+
+
+ ?line {STRes274,S274} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_dateTime.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList275 = [STRes274|STResList274],
+ ?line ITRes274 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_dateTime.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S274),
+ ITResList275 = [ITRes274|ITResList274],
+
+
+ ?line {STRes275,S275} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_time.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList276 = [STRes275|STResList275],
+ ?line ITRes275 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_time.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S275),
+ ITResList276 = [ITRes275|ITResList275],
+
+
+ ?line {STRes276,S276} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_date.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList277 = [STRes276|STResList276],
+ ?line ITRes276 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_date.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S276),
+ ITResList277 = [ITRes276|ITResList276],
+
+
+ ?line {STRes277,S277} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_gYearMonth.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList278 = [STRes277|STResList277],
+ ?line ITRes277 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_gYearMonth.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S277),
+ ITResList278 = [ITRes277|ITResList277],
+
+
+ ?line {STRes278,S278} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_gYear.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList279 = [STRes278|STResList278],
+ ?line ITRes278 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_gYear.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S278),
+ ITResList279 = [ITRes278|ITResList278],
+
+
+ ?line {STRes279,S279} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_gMonthDay.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList280 = [STRes279|STResList279],
+ ?line ITRes279 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_gMonthDay.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S279),
+ ITResList280 = [ITRes279|ITResList279],
+
+
+ ?line {STRes280,S280} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_gDay.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList281 = [STRes280|STResList280],
+ ?line ITRes280 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_gDay.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S280),
+ ITResList281 = [ITRes280|ITResList280],
+
+
+ ?line {STRes281,S281} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_gMonth.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList282 = [STRes281|STResList281],
+ ?line ITRes281 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NMTOKENS_gMonth.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S281),
+ ITResList282 = [ITRes281|ITResList281],
+
+
+ ?line {STRes282,S282} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList283 = [STRes282|STResList282],
+ ?line ITRes282 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S282),
+ ITResList283 = [ITRes282|ITResList282],
+
+
+ ?line {STRes283,S283} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList284 = [STRes283|STResList283],
+ ?line ITRes283 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S283),
+ ITResList284 = [ITRes283|ITResList283],
+
+
+ ?line {STRes284,S284} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList285 = [STRes284|STResList284],
+ ?line ITRes284 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S284),
+ ITResList285 = [ITRes284|ITResList284],
+
+
+ ?line {STRes285,S285} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_Name.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList286 = [STRes285|STResList285],
+ ?line ITRes285 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_Name.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S285),
+ ITResList286 = [ITRes285|ITResList285],
+
+
+ ?line {STRes286,S286} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_NCName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList287 = [STRes286|STResList286],
+ ?line ITRes286 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_NCName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S286),
+ ITResList287 = [ITRes286|ITResList286],
+
+
+ ?line {STRes287,S287} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_ID.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList288 = [STRes287|STResList287],
+ ?line ITRes287 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_ID.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S287),
+ ITResList288 = [ITRes287|ITResList287],
+
+
+ ?line {STRes288,S288} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_IDREF.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList289 = [STRes288|STResList288],
+ ?line ITRes288 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_IDREF.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S288),
+ ITResList289 = [ITRes288|ITResList288],
+
+
+ ?line {STRes289,S289} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_IDREFS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList290 = [STRes289|STResList289],
+ ?line ITRes289 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_IDREFS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S289),
+ ITResList290 = [ITRes289|ITResList289],
+
+
+ ?line {STRes290,S290} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList291 = [STRes290|STResList290],
+ ?line ITRes290 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S290),
+ ITResList291 = [ITRes290|ITResList290],
+
+
+ ?line {STRes291,S291} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList292 = [STRes291|STResList291],
+ ?line ITRes291 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S291),
+ ITResList292 = [ITRes291|ITResList291],
+
+
+ ?line {STRes292,S292} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList293 = [STRes292|STResList292],
+ ?line ITRes292 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S292),
+ ITResList293 = [ITRes292|ITResList292],
+
+
+ ?line {STRes293,S293} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList294 = [STRes293|STResList293],
+ ?line ITRes293 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S293),
+ ITResList294 = [ITRes293|ITResList293],
+
+
+ ?line {STRes294,S294} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList295 = [STRes294|STResList294],
+ ?line ITRes294 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S294),
+ ITResList295 = [ITRes294|ITResList294],
+
+
+ ?line {STRes295,S295} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList296 = [STRes295|STResList295],
+ ?line ITRes295 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S295),
+ ITResList296 = [ITRes295|ITResList295],
+
+
+ ?line {STRes296,S296} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList297 = [STRes296|STResList296],
+ ?line ITRes296 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S296),
+ ITResList297 = [ITRes296|ITResList296],
+
+
+ ?line {STRes297,S297} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList298 = [STRes297|STResList297],
+ ?line ITRes297 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S297),
+ ITResList298 = [ITRes297|ITResList297],
+
+
+ ?line {STRes298,S298} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_nonPositiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList299 = [STRes298|STResList298],
+ ?line ITRes298 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_nonPositiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S298),
+ ITResList299 = [ITRes298|ITResList298],
+
+
+ ?line {STRes299,S299} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList300 = [STRes299|STResList299],
+ ?line ITRes299 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_long.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S299),
+ ITResList300 = [ITRes299|ITResList299],
+
+
+ ?line {STRes300,S300} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList301 = [STRes300|STResList300],
+ ?line ITRes300 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_int.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S300),
+ ITResList301 = [ITRes300|ITResList300],
+
+
+ ?line {STRes301,S301} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList302 = [STRes301|STResList301],
+ ?line ITRes301 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_short.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S301),
+ ITResList302 = [ITRes301|ITResList301],
+
+
+ ?line {STRes302,S302} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList303 = [STRes302|STResList302],
+ ?line ITRes302 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S302),
+ ITResList303 = [ITRes302|ITResList302],
+
+
+ ?line {STRes303,S303} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList304 = [STRes303|STResList303],
+ ?line ITRes303 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S303),
+ ITResList304 = [ITRes303|ITResList303],
+
+
+ ?line {STRes304,S304} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList305 = [STRes304|STResList304],
+ ?line ITRes304 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S304),
+ ITResList305 = [ITRes304|ITResList304],
+
+
+ ?line {STRes305,S305} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList306 = [STRes305|STResList305],
+ ?line ITRes305 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S305),
+ ITResList306 = [ITRes305|ITResList305],
+
+
+ ?line {STRes306,S306} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList307 = [STRes306|STResList306],
+ ?line ITRes306 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S306),
+ ITResList307 = [ITRes306|ITResList306],
+
+
+ ?line {STRes307,S307} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList308 = [STRes307|STResList307],
+ ?line ITRes307 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S307),
+ ITResList308 = [ITRes307|ITResList307],
+
+
+ ?line {STRes308,S308} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList309 = [STRes308|STResList308],
+ ?line ITRes308 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S308),
+ ITResList309 = [ITRes308|ITResList308],
+
+
+ ?line {STRes309,S309} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList310 = [STRes309|STResList309],
+ ?line ITRes309 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S309),
+ ITResList310 = [ITRes309|ITResList309],
+
+
+ ?line {STRes310,S310} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList311 = [STRes310|STResList310],
+ ?line ITRes310 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S310),
+ ITResList311 = [ITRes310|ITResList310],
+
+
+ ?line {STRes311,S311} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_QName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList312 = [STRes311|STResList311],
+ ?line ITRes311 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_QName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S311),
+ ITResList312 = [ITRes311|ITResList311],
+
+
+ ?line {STRes312,S312} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_NOTATION.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList313 = [STRes312|STResList312],
+ ?line ITRes312 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_boolean_NOTATION.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S312),
+ ITResList313 = [ITRes312|ITResList312],
+
+
+ ?line {STRes313,S313} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList314 = [STRes313|STResList313],
+ ?line ITRes313 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S313),
+ ITResList314 = [ITRes313|ITResList313],
+
+
+ ?line {STRes314,S314} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList315 = [STRes314|STResList314],
+ ?line ITRes314 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S314),
+ ITResList315 = [ITRes314|ITResList314],
+
+
+ ?line {STRes315,S315} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList316 = [STRes315|STResList315],
+ ?line ITRes315 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S315),
+ ITResList316 = [ITRes315|ITResList315],
+
+
+ ?line {STRes316,S316} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList317 = [STRes316|STResList316],
+ ?line ITRes316 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S316),
+ ITResList317 = [ITRes316|ITResList316],
+
+
+ ?line {STRes317,S317} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList318 = [STRes317|STResList317],
+ ?line ITRes317 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S317),
+ ITResList318 = [ITRes317|ITResList317],
+
+
+ ?line {STRes318,S318} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList319 = [STRes318|STResList318],
+ ?line ITRes318 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S318),
+ ITResList319 = [ITRes318|ITResList318],
+
+
+ ?line {STRes319,S319} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList320 = [STRes319|STResList319],
+ ?line ITRes319 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S319),
+ ITResList320 = [ITRes319|ITResList319],
+
+
+ ?line {STRes320,S320} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList321 = [STRes320|STResList320],
+ ?line ITRes320 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S320),
+ ITResList321 = [ITRes320|ITResList320],
+
+
+ ?line {STRes321,S321} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList322 = [STRes321|STResList321],
+ ?line ITRes321 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S321),
+ ITResList322 = [ITRes321|ITResList321],
+
+
+ ?line {STRes322,S322} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList323 = [STRes322|STResList322],
+ ?line ITRes322 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S322),
+ ITResList323 = [ITRes322|ITResList322],
+
+
+ ?line {STRes323,S323} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList324 = [STRes323|STResList323],
+ ?line ITRes323 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_long.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S323),
+ ITResList324 = [ITRes323|ITResList323],
+
+
+ ?line {STRes324,S324} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList325 = [STRes324|STResList324],
+ ?line ITRes324 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_int.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S324),
+ ITResList325 = [ITRes324|ITResList324],
+
+
+ ?line {STRes325,S325} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList326 = [STRes325|STResList325],
+ ?line ITRes325 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_short.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S325),
+ ITResList326 = [ITRes325|ITResList325],
+
+
+ ?line {STRes326,S326} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList327 = [STRes326|STResList326],
+ ?line ITRes326 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S326),
+ ITResList327 = [ITRes326|ITResList326],
+
+
+ ?line {STRes327,S327} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList328 = [STRes327|STResList327],
+ ?line ITRes327 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S327),
+ ITResList328 = [ITRes327|ITResList327],
+
+
+ ?line {STRes328,S328} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList329 = [STRes328|STResList328],
+ ?line ITRes328 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S328),
+ ITResList329 = [ITRes328|ITResList328],
+
+
+ ?line {STRes329,S329} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList330 = [STRes329|STResList329],
+ ?line ITRes329 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S329),
+ ITResList330 = [ITRes329|ITResList329],
+
+
+ ?line {STRes330,S330} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList331 = [STRes330|STResList330],
+ ?line ITRes330 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S330),
+ ITResList331 = [ITRes330|ITResList330],
+
+
+ ?line {STRes331,S331} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList332 = [STRes331|STResList331],
+ ?line ITRes331 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S331),
+ ITResList332 = [ITRes331|ITResList331],
+
+
+ ?line {STRes332,S332} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList333 = [STRes332|STResList332],
+ ?line ITRes332 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S332),
+ ITResList333 = [ITRes332|ITResList332],
+
+
+ ?line {STRes333,S333} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList334 = [STRes333|STResList333],
+ ?line ITRes333 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S333),
+ ITResList334 = [ITRes333|ITResList333],
+
+
+ ?line {STRes334,S334} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList335 = [STRes334|STResList334],
+ ?line ITRes334 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_base64Binary_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S334),
+ ITResList335 = [ITRes334|ITResList334],
+
+
+ ?line {STRes335,S335} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList336 = [STRes335|STResList335],
+ ?line ITRes335 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S335),
+ ITResList336 = [ITRes335|ITResList335],
+
+
+ ?line {STRes336,S336} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList337 = [STRes336|STResList336],
+ ?line ITRes336 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S336),
+ ITResList337 = [ITRes336|ITResList336],
+
+
+ ?line {STRes337,S337} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList338 = [STRes337|STResList337],
+ ?line ITRes337 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S337),
+ ITResList338 = [ITRes337|ITResList337],
+
+
+ ?line {STRes338,S338} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList339 = [STRes338|STResList338],
+ ?line ITRes338 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S338),
+ ITResList339 = [ITRes338|ITResList338],
+
+
+ ?line {STRes339,S339} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList340 = [STRes339|STResList339],
+ ?line ITRes339 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S339),
+ ITResList340 = [ITRes339|ITResList339],
+
+
+ ?line {STRes340,S340} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList341 = [STRes340|STResList340],
+ ?line ITRes340 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S340),
+ ITResList341 = [ITRes340|ITResList340],
+
+
+ ?line {STRes341,S341} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList342 = [STRes341|STResList341],
+ ?line ITRes341 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S341),
+ ITResList342 = [ITRes341|ITResList341],
+
+
+ ?line {STRes342,S342} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList343 = [STRes342|STResList342],
+ ?line ITRes342 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S342),
+ ITResList343 = [ITRes342|ITResList342],
+
+
+ ?line {STRes343,S343} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList344 = [STRes343|STResList343],
+ ?line ITRes343 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S343),
+ ITResList344 = [ITRes343|ITResList343],
+
+
+ ?line {STRes344,S344} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList345 = [STRes344|STResList344],
+ ?line ITRes344 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S344),
+ ITResList345 = [ITRes344|ITResList344],
+
+
+ ?line {STRes345,S345} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList346 = [STRes345|STResList345],
+ ?line ITRes345 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_long.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S345),
+ ITResList346 = [ITRes345|ITResList345],
+
+
+ ?line {STRes346,S346} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList347 = [STRes346|STResList346],
+ ?line ITRes346 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_int.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S346),
+ ITResList347 = [ITRes346|ITResList346],
+
+
+ ?line {STRes347,S347} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList348 = [STRes347|STResList347],
+ ?line ITRes347 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_short.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S347),
+ ITResList348 = [ITRes347|ITResList347],
+
+
+ ?line {STRes348,S348} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList349 = [STRes348|STResList348],
+ ?line ITRes348 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S348),
+ ITResList349 = [ITRes348|ITResList348],
+
+
+ ?line {STRes349,S349} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList350 = [STRes349|STResList349],
+ ?line ITRes349 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S349),
+ ITResList350 = [ITRes349|ITResList349],
+
+
+ ?line {STRes350,S350} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList351 = [STRes350|STResList350],
+ ?line ITRes350 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S350),
+ ITResList351 = [ITRes350|ITResList350],
+
+
+ ?line {STRes351,S351} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList352 = [STRes351|STResList351],
+ ?line ITRes351 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S351),
+ ITResList352 = [ITRes351|ITResList351],
+
+
+ ?line {STRes352,S352} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList353 = [STRes352|STResList352],
+ ?line ITRes352 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S352),
+ ITResList353 = [ITRes352|ITResList352],
+
+
+ ?line {STRes353,S353} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList354 = [STRes353|STResList353],
+ ?line ITRes353 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S353),
+ ITResList354 = [ITRes353|ITResList353],
+
+
+ ?line {STRes354,S354} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList355 = [STRes354|STResList354],
+ ?line ITRes354 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S354),
+ ITResList355 = [ITRes354|ITResList354],
+
+
+ ?line {STRes355,S355} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList356 = [STRes355|STResList355],
+ ?line ITRes355 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S355),
+ ITResList356 = [ITRes355|ITResList355],
+
+
+ ?line {STRes356,S356} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList357 = [STRes356|STResList356],
+ ?line ITRes356 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_hexBinary_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S356),
+ ITResList357 = [ITRes356|ITResList356],
+
+
+ ?line {STRes357,S357} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList358 = [STRes357|STResList357],
+ ?line ITRes357 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S357),
+ ITResList358 = [ITRes357|ITResList357],
+
+
+ ?line {STRes358,S358} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList359 = [STRes358|STResList358],
+ ?line ITRes358 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S358),
+ ITResList359 = [ITRes358|ITResList358],
+
+
+ ?line {STRes359,S359} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList360 = [STRes359|STResList359],
+ ?line ITRes359 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S359),
+ ITResList360 = [ITRes359|ITResList359],
+
+
+ ?line {STRes360,S360} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList361 = [STRes360|STResList360],
+ ?line ITRes360 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S360),
+ ITResList361 = [ITRes360|ITResList360],
+
+
+ ?line {STRes361,S361} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList362 = [STRes361|STResList361],
+ ?line ITRes361 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S361),
+ ITResList362 = [ITRes361|ITResList361],
+
+
+ ?line {STRes362,S362} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList363 = [STRes362|STResList362],
+ ?line ITRes362 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S362),
+ ITResList363 = [ITRes362|ITResList362],
+
+
+ ?line {STRes363,S363} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList364 = [STRes363|STResList363],
+ ?line ITRes363 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S363),
+ ITResList364 = [ITRes363|ITResList363],
+
+
+ ?line {STRes364,S364} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList365 = [STRes364|STResList364],
+ ?line ITRes364 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S364),
+ ITResList365 = [ITRes364|ITResList364],
+
+
+ ?line {STRes365,S365} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList366 = [STRes365|STResList365],
+ ?line ITRes365 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_float.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S365),
+ ITResList366 = [ITRes365|ITResList365],
+
+
+ ?line {STRes366,S366} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList367 = [STRes366|STResList366],
+ ?line ITRes366 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S366),
+ ITResList367 = [ITRes366|ITResList366],
+
+
+ ?line {STRes367,S367} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList368 = [STRes367|STResList367],
+ ?line ITRes367 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S367),
+ ITResList368 = [ITRes367|ITResList367],
+
+
+ ?line {STRes368,S368} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_nonPositiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList369 = [STRes368|STResList368],
+ ?line ITRes368 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_nonPositiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S368),
+ ITResList369 = [ITRes368|ITResList368],
+
+
+ ?line {STRes369,S369} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_negativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList370 = [STRes369|STResList369],
+ ?line ITRes369 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_negativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S369),
+ ITResList370 = [ITRes369|ITResList369],
+
+
+ ?line {STRes370,S370} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList371 = [STRes370|STResList370],
+ ?line ITRes370 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_long.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S370),
+ ITResList371 = [ITRes370|ITResList370],
+
+
+ ?line {STRes371,S371} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList372 = [STRes371|STResList371],
+ ?line ITRes371 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_int.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S371),
+ ITResList372 = [ITRes371|ITResList371],
+
+
+ ?line {STRes372,S372} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList373 = [STRes372|STResList372],
+ ?line ITRes372 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_short.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S372),
+ ITResList373 = [ITRes372|ITResList372],
+
+
+ ?line {STRes373,S373} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList374 = [STRes373|STResList373],
+ ?line ITRes373 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S373),
+ ITResList374 = [ITRes373|ITResList373],
+
+
+ ?line {STRes374,S374} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList375 = [STRes374|STResList374],
+ ?line ITRes374 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S374),
+ ITResList375 = [ITRes374|ITResList374],
+
+
+ ?line {STRes375,S375} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList376 = [STRes375|STResList375],
+ ?line ITRes375 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S375),
+ ITResList376 = [ITRes375|ITResList375],
+
+
+ ?line {STRes376,S376} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList377 = [STRes376|STResList376],
+ ?line ITRes376 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S376),
+ ITResList377 = [ITRes376|ITResList376],
+
+
+ ?line {STRes377,S377} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList378 = [STRes377|STResList377],
+ ?line ITRes377 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S377),
+ ITResList378 = [ITRes377|ITResList377],
+
+
+ ?line {STRes378,S378} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList379 = [STRes378|STResList378],
+ ?line ITRes378 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S378),
+ ITResList379 = [ITRes378|ITResList378],
+
+
+ ?line {STRes379,S379} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList380 = [STRes379|STResList379],
+ ?line ITRes379 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S379),
+ ITResList380 = [ITRes379|ITResList379],
+
+
+ ?line {STRes380,S380} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList381 = [STRes380|STResList380],
+ ?line ITRes380 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S380),
+ ITResList381 = [ITRes380|ITResList380],
+
+
+ ?line {STRes381,S381} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList382 = [STRes381|STResList381],
+ ?line ITRes381 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_float_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S381),
+ ITResList382 = [ITRes381|ITResList381],
+
+
+ ?line {STRes382,S382} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList383 = [STRes382|STResList382],
+ ?line ITRes382 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S382),
+ ITResList383 = [ITRes382|ITResList382],
+
+
+ ?line {STRes383,S383} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList384 = [STRes383|STResList383],
+ ?line ITRes383 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S383),
+ ITResList384 = [ITRes383|ITResList383],
+
+
+ ?line {STRes384,S384} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList385 = [STRes384|STResList384],
+ ?line ITRes384 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S384),
+ ITResList385 = [ITRes384|ITResList384],
+
+
+ ?line {STRes385,S385} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList386 = [STRes385|STResList385],
+ ?line ITRes385 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S385),
+ ITResList386 = [ITRes385|ITResList385],
+
+
+ ?line {STRes386,S386} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList387 = [STRes386|STResList386],
+ ?line ITRes386 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S386),
+ ITResList387 = [ITRes386|ITResList386],
+
+
+ ?line {STRes387,S387} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList388 = [STRes387|STResList387],
+ ?line ITRes387 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S387),
+ ITResList388 = [ITRes387|ITResList387],
+
+
+ ?line {STRes388,S388} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList389 = [STRes388|STResList388],
+ ?line ITRes388 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S388),
+ ITResList389 = [ITRes388|ITResList388],
+
+
+ ?line {STRes389,S389} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList390 = [STRes389|STResList389],
+ ?line ITRes389 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S389),
+ ITResList390 = [ITRes389|ITResList389],
+
+
+ ?line {STRes390,S390} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList391 = [STRes390|STResList390],
+ ?line ITRes390 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S390),
+ ITResList391 = [ITRes390|ITResList390],
+
+
+ ?line {STRes391,S391} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList392 = [STRes391|STResList391],
+ ?line ITRes391 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S391),
+ ITResList392 = [ITRes391|ITResList391],
+
+
+ ?line {STRes392,S392} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList393 = [STRes392|STResList392],
+ ?line ITRes392 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S392),
+ ITResList393 = [ITRes392|ITResList392],
+
+
+ ?line {STRes393,S393} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_nonPositiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList394 = [STRes393|STResList393],
+ ?line ITRes393 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_nonPositiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S393),
+ ITResList394 = [ITRes393|ITResList393],
+
+
+ ?line {STRes394,S394} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_negativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList395 = [STRes394|STResList394],
+ ?line ITRes394 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_negativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S394),
+ ITResList395 = [ITRes394|ITResList394],
+
+
+ ?line {STRes395,S395} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList396 = [STRes395|STResList395],
+ ?line ITRes395 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_long.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S395),
+ ITResList396 = [ITRes395|ITResList395],
+
+
+ ?line {STRes396,S396} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList397 = [STRes396|STResList396],
+ ?line ITRes396 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_int.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S396),
+ ITResList397 = [ITRes396|ITResList396],
+
+
+ ?line {STRes397,S397} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList398 = [STRes397|STResList397],
+ ?line ITRes397 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_short.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S397),
+ ITResList398 = [ITRes397|ITResList397],
+
+
+ ?line {STRes398,S398} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList399 = [STRes398|STResList398],
+ ?line ITRes398 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S398),
+ ITResList399 = [ITRes398|ITResList398],
+
+
+ ?line {STRes399,S399} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList400 = [STRes399|STResList399],
+ ?line ITRes399 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S399),
+ ITResList400 = [ITRes399|ITResList399],
+
+
+ ?line {STRes400,S400} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList401 = [STRes400|STResList400],
+ ?line ITRes400 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S400),
+ ITResList401 = [ITRes400|ITResList400],
+
+
+ ?line {STRes401,S401} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList402 = [STRes401|STResList401],
+ ?line ITRes401 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S401),
+ ITResList402 = [ITRes401|ITResList401],
+
+
+ ?line {STRes402,S402} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList403 = [STRes402|STResList402],
+ ?line ITRes402 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S402),
+ ITResList403 = [ITRes402|ITResList402],
+
+
+ ?line {STRes403,S403} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList404 = [STRes403|STResList403],
+ ?line ITRes403 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S403),
+ ITResList404 = [ITRes403|ITResList403],
+
+
+ ?line {STRes404,S404} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList405 = [STRes404|STResList404],
+ ?line ITRes404 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S404),
+ ITResList405 = [ITRes404|ITResList404],
+
+
+ ?line {STRes405,S405} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList406 = [STRes405|STResList405],
+ ?line ITRes405 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S405),
+ ITResList406 = [ITRes405|ITResList405],
+
+
+ ?line {STRes406,S406} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList407 = [STRes406|STResList406],
+ ?line ITRes406 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_decimal_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S406),
+ ITResList407 = [ITRes406|ITResList406],
+
+
+ ?line {STRes407,S407} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList408 = [STRes407|STResList407],
+ ?line ITRes407 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S407),
+ ITResList408 = [ITRes407|ITResList407],
+
+
+ ?line {STRes408,S408} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList409 = [STRes408|STResList408],
+ ?line ITRes408 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S408),
+ ITResList409 = [ITRes408|ITResList408],
+
+
+ ?line {STRes409,S409} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList410 = [STRes409|STResList409],
+ ?line ITRes409 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S409),
+ ITResList410 = [ITRes409|ITResList409],
+
+
+ ?line {STRes410,S410} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList411 = [STRes410|STResList410],
+ ?line ITRes410 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S410),
+ ITResList411 = [ITRes410|ITResList410],
+
+
+ ?line {STRes411,S411} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList412 = [STRes411|STResList411],
+ ?line ITRes411 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S411),
+ ITResList412 = [ITRes411|ITResList411],
+
+
+ ?line {STRes412,S412} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList413 = [STRes412|STResList412],
+ ?line ITRes412 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S412),
+ ITResList413 = [ITRes412|ITResList412],
+
+
+ ?line {STRes413,S413} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList414 = [STRes413|STResList413],
+ ?line ITRes413 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S413),
+ ITResList414 = [ITRes413|ITResList413],
+
+
+ ?line {STRes414,S414} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList415 = [STRes414|STResList414],
+ ?line ITRes414 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S414),
+ ITResList415 = [ITRes414|ITResList414],
+
+
+ ?line {STRes415,S415} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList416 = [STRes415|STResList415],
+ ?line ITRes415 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S415),
+ ITResList416 = [ITRes415|ITResList415],
+
+
+ ?line {STRes416,S416} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList417 = [STRes416|STResList416],
+ ?line ITRes416 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S416),
+ ITResList417 = [ITRes416|ITResList416],
+
+
+ ?line {STRes417,S417} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList418 = [STRes417|STResList417],
+ ?line ITRes417 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S417),
+ ITResList418 = [ITRes417|ITResList417],
+
+
+ ?line {STRes418,S418} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_nonPositiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList419 = [STRes418|STResList418],
+ ?line ITRes418 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_nonPositiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S418),
+ ITResList419 = [ITRes418|ITResList418],
+
+
+ ?line {STRes419,S419} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_negativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList420 = [STRes419|STResList419],
+ ?line ITRes419 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_negativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S419),
+ ITResList420 = [ITRes419|ITResList419],
+
+
+ ?line {STRes420,S420} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList421 = [STRes420|STResList420],
+ ?line ITRes420 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_long.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S420),
+ ITResList421 = [ITRes420|ITResList420],
+
+
+ ?line {STRes421,S421} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList422 = [STRes421|STResList421],
+ ?line ITRes421 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_int.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S421),
+ ITResList422 = [ITRes421|ITResList421],
+
+
+ ?line {STRes422,S422} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList423 = [STRes422|STResList422],
+ ?line ITRes422 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_short.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S422),
+ ITResList423 = [ITRes422|ITResList422],
+
+
+ ?line {STRes423,S423} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList424 = [STRes423|STResList423],
+ ?line ITRes423 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S423),
+ ITResList424 = [ITRes423|ITResList423],
+
+
+ ?line {STRes424,S424} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList425 = [STRes424|STResList424],
+ ?line ITRes424 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S424),
+ ITResList425 = [ITRes424|ITResList424],
+
+
+ ?line {STRes425,S425} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList426 = [STRes425|STResList425],
+ ?line ITRes425 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S425),
+ ITResList426 = [ITRes425|ITResList425],
+
+
+ ?line {STRes426,S426} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList427 = [STRes426|STResList426],
+ ?line ITRes426 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S426),
+ ITResList427 = [ITRes426|ITResList426],
+
+
+ ?line {STRes427,S427} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList428 = [STRes427|STResList427],
+ ?line ITRes427 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S427),
+ ITResList428 = [ITRes427|ITResList427],
+
+
+ ?line {STRes428,S428} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList429 = [STRes428|STResList428],
+ ?line ITRes428 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S428),
+ ITResList429 = [ITRes428|ITResList428],
+
+
+ ?line {STRes429,S429} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList430 = [STRes429|STResList429],
+ ?line ITRes429 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S429),
+ ITResList430 = [ITRes429|ITResList429],
+
+
+ ?line {STRes430,S430} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList431 = [STRes430|STResList430],
+ ?line ITRes430 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S430),
+ ITResList431 = [ITRes430|ITResList430],
+
+
+ ?line {STRes431,S431} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList432 = [STRes431|STResList431],
+ ?line ITRes431 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_integer_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S431),
+ ITResList432 = [ITRes431|ITResList431],
+
+
+ ?line {STRes432,S432} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList433 = [STRes432|STResList432],
+ ?line ITRes432 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S432),
+ ITResList433 = [ITRes432|ITResList432],
+
+
+ ?line {STRes433,S433} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList434 = [STRes433|STResList433],
+ ?line ITRes433 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S433),
+ ITResList434 = [ITRes433|ITResList433],
+
+
+ ?line {STRes434,S434} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList435 = [STRes434|STResList434],
+ ?line ITRes434 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S434),
+ ITResList435 = [ITRes434|ITResList434],
+
+
+ ?line {STRes435,S435} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList436 = [STRes435|STResList435],
+ ?line ITRes435 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S435),
+ ITResList436 = [ITRes435|ITResList435],
+
+
+ ?line {STRes436,S436} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList437 = [STRes436|STResList436],
+ ?line ITRes436 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S436),
+ ITResList437 = [ITRes436|ITResList436],
+
+
+ ?line {STRes437,S437} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList438 = [STRes437|STResList437],
+ ?line ITRes437 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S437),
+ ITResList438 = [ITRes437|ITResList437],
+
+
+ ?line {STRes438,S438} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList439 = [STRes438|STResList438],
+ ?line ITRes438 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S438),
+ ITResList439 = [ITRes438|ITResList438],
+
+
+ ?line {STRes439,S439} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList440 = [STRes439|STResList439],
+ ?line ITRes439 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S439),
+ ITResList440 = [ITRes439|ITResList439],
+
+
+ ?line {STRes440,S440} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList441 = [STRes440|STResList440],
+ ?line ITRes440 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S440),
+ ITResList441 = [ITRes440|ITResList440],
+
+
+ ?line {STRes441,S441} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_nonPositiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList442 = [STRes441|STResList441],
+ ?line ITRes441 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_nonPositiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S441),
+ ITResList442 = [ITRes441|ITResList441],
+
+
+ ?line {STRes442,S442} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_negativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList443 = [STRes442|STResList442],
+ ?line ITRes442 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_negativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S442),
+ ITResList443 = [ITRes442|ITResList442],
+
+
+ ?line {STRes443,S443} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList444 = [STRes443|STResList443],
+ ?line ITRes443 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_long.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S443),
+ ITResList444 = [ITRes443|ITResList443],
+
+
+ ?line {STRes444,S444} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList445 = [STRes444|STResList444],
+ ?line ITRes444 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_int.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S444),
+ ITResList445 = [ITRes444|ITResList444],
+
+
+ ?line {STRes445,S445} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList446 = [STRes445|STResList445],
+ ?line ITRes445 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_short.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S445),
+ ITResList446 = [ITRes445|ITResList445],
+
+
+ ?line {STRes446,S446} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList447 = [STRes446|STResList446],
+ ?line ITRes446 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S446),
+ ITResList447 = [ITRes446|ITResList446],
+
+
+ ?line {STRes447,S447} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList448 = [STRes447|STResList447],
+ ?line ITRes447 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S447),
+ ITResList448 = [ITRes447|ITResList447],
+
+
+ ?line {STRes448,S448} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList449 = [STRes448|STResList448],
+ ?line ITRes448 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonPositiveInteger_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S448),
+ ITResList449 = [ITRes448|ITResList448],
+
+
+ ?line {STRes449,S449} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList450 = [STRes449|STResList449],
+ ?line ITRes449 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S449),
+ ITResList450 = [ITRes449|ITResList449],
+
+
+ ?line {STRes450,S450} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList451 = [STRes450|STResList450],
+ ?line ITRes450 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S450),
+ ITResList451 = [ITRes450|ITResList450],
+
+
+ ?line {STRes451,S451} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList452 = [STRes451|STResList451],
+ ?line ITRes451 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S451),
+ ITResList452 = [ITRes451|ITResList451],
+
+
+ ?line {STRes452,S452} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList453 = [STRes452|STResList452],
+ ?line ITRes452 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S452),
+ ITResList453 = [ITRes452|ITResList452],
+
+
+ ?line {STRes453,S453} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList454 = [STRes453|STResList453],
+ ?line ITRes453 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S453),
+ ITResList454 = [ITRes453|ITResList453],
+
+
+ ?line {STRes454,S454} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList455 = [STRes454|STResList454],
+ ?line ITRes454 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S454),
+ ITResList455 = [ITRes454|ITResList454],
+
+
+ ?line {STRes455,S455} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList456 = [STRes455|STResList455],
+ ?line ITRes455 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S455),
+ ITResList456 = [ITRes455|ITResList455],
+
+
+ ?line {STRes456,S456} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList457 = [STRes456|STResList456],
+ ?line ITRes456 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S456),
+ ITResList457 = [ITRes456|ITResList456],
+
+
+ ?line {STRes457,S457} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_nonPositiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList458 = [STRes457|STResList457],
+ ?line ITRes457 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_nonPositiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S457),
+ ITResList458 = [ITRes457|ITResList457],
+
+
+ ?line {STRes458,S458} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_negativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList459 = [STRes458|STResList458],
+ ?line ITRes458 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_negativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S458),
+ ITResList459 = [ITRes458|ITResList458],
+
+
+ ?line {STRes459,S459} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList460 = [STRes459|STResList459],
+ ?line ITRes459 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_long.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S459),
+ ITResList460 = [ITRes459|ITResList459],
+
+
+ ?line {STRes460,S460} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList461 = [STRes460|STResList460],
+ ?line ITRes460 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_int.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S460),
+ ITResList461 = [ITRes460|ITResList460],
+
+
+ ?line {STRes461,S461} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList462 = [STRes461|STResList461],
+ ?line ITRes461 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_short.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S461),
+ ITResList462 = [ITRes461|ITResList461],
+
+
+ ?line {STRes462,S462} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList463 = [STRes462|STResList462],
+ ?line ITRes462 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S462),
+ ITResList463 = [ITRes462|ITResList462],
+
+
+ ?line {STRes463,S463} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList464 = [STRes463|STResList463],
+ ?line ITRes463 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S463),
+ ITResList464 = [ITRes463|ITResList463],
+
+
+ ?line {STRes464,S464} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList465 = [STRes464|STResList464],
+ ?line ITRes464 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_negativeInteger_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S464),
+ ITResList465 = [ITRes464|ITResList464],
+
+
+ ?line {STRes465,S465} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList466 = [STRes465|STResList465],
+ ?line ITRes465 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S465),
+ ITResList466 = [ITRes465|ITResList465],
+
+
+ ?line {STRes466,S466} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList467 = [STRes466|STResList466],
+ ?line ITRes466 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S466),
+ ITResList467 = [ITRes466|ITResList466],
+
+
+ ?line {STRes467,S467} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList468 = [STRes467|STResList467],
+ ?line ITRes467 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S467),
+ ITResList468 = [ITRes467|ITResList467],
+
+
+ ?line {STRes468,S468} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList469 = [STRes468|STResList468],
+ ?line ITRes468 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S468),
+ ITResList469 = [ITRes468|ITResList468],
+
+
+ ?line {STRes469,S469} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList470 = [STRes469|STResList469],
+ ?line ITRes469 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S469),
+ ITResList470 = [ITRes469|ITResList469],
+
+
+ ?line {STRes470,S470} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList471 = [STRes470|STResList470],
+ ?line ITRes470 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S470),
+ ITResList471 = [ITRes470|ITResList470],
+
+
+ ?line {STRes471,S471} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList472 = [STRes471|STResList471],
+ ?line ITRes471 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S471),
+ ITResList472 = [ITRes471|ITResList471],
+
+
+ ?line {STRes472,S472} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList473 = [STRes472|STResList472],
+ ?line ITRes472 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S472),
+ ITResList473 = [ITRes472|ITResList472],
+
+
+ ?line {STRes473,S473} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList474 = [STRes473|STResList473],
+ ?line ITRes473 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S473),
+ ITResList474 = [ITRes473|ITResList473],
+
+
+ ?line {STRes474,S474} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList475 = [STRes474|STResList474],
+ ?line ITRes474 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S474),
+ ITResList475 = [ITRes474|ITResList474],
+
+
+ ?line {STRes475,S475} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList476 = [STRes475|STResList475],
+ ?line ITRes475 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S475),
+ ITResList476 = [ITRes475|ITResList475],
+
+
+ ?line {STRes476,S476} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_nonPositiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList477 = [STRes476|STResList476],
+ ?line ITRes476 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_nonPositiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S476),
+ ITResList477 = [ITRes476|ITResList476],
+
+
+ ?line {STRes477,S477} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_negativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList478 = [STRes477|STResList477],
+ ?line ITRes477 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_negativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S477),
+ ITResList478 = [ITRes477|ITResList477],
+
+
+ ?line {STRes478,S478} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList479 = [STRes478|STResList478],
+ ?line ITRes478 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_long.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S478),
+ ITResList479 = [ITRes478|ITResList478],
+
+
+ ?line {STRes479,S479} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList480 = [STRes479|STResList479],
+ ?line ITRes479 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_int.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S479),
+ ITResList480 = [ITRes479|ITResList479],
+
+
+ ?line {STRes480,S480} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList481 = [STRes480|STResList480],
+ ?line ITRes480 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_short.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S480),
+ ITResList481 = [ITRes480|ITResList480],
+
+
+ ?line {STRes481,S481} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList482 = [STRes481|STResList481],
+ ?line ITRes481 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S481),
+ ITResList482 = [ITRes481|ITResList481],
+
+
+ ?line {STRes482,S482} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList483 = [STRes482|STResList482],
+ ?line ITRes482 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S482),
+ ITResList483 = [ITRes482|ITResList482],
+
+
+ ?line {STRes483,S483} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList484 = [STRes483|STResList483],
+ ?line ITRes483 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S483),
+ ITResList484 = [ITRes483|ITResList483],
+
+
+ ?line {STRes484,S484} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList485 = [STRes484|STResList484],
+ ?line ITRes484 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S484),
+ ITResList485 = [ITRes484|ITResList484],
+
+
+ ?line {STRes485,S485} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList486 = [STRes485|STResList485],
+ ?line ITRes485 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S485),
+ ITResList486 = [ITRes485|ITResList485],
+
+
+ ?line {STRes486,S486} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList487 = [STRes486|STResList486],
+ ?line ITRes486 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S486),
+ ITResList487 = [ITRes486|ITResList486],
+
+
+ ?line {STRes487,S487} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList488 = [STRes487|STResList487],
+ ?line ITRes487 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S487),
+ ITResList488 = [ITRes487|ITResList487],
+
+
+ ?line {STRes488,S488} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList489 = [STRes488|STResList488],
+ ?line ITRes488 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S488),
+ ITResList489 = [ITRes488|ITResList488],
+
+
+ ?line {STRes489,S489} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList490 = [STRes489|STResList489],
+ ?line ITRes489 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_long_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S489),
+ ITResList490 = [ITRes489|ITResList489],
+
+
+ ?line {STRes490,S490} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList491 = [STRes490|STResList490],
+ ?line ITRes490 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S490),
+ ITResList491 = [ITRes490|ITResList490],
+
+
+ ?line {STRes491,S491} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList492 = [STRes491|STResList491],
+ ?line ITRes491 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S491),
+ ITResList492 = [ITRes491|ITResList491],
+
+
+ ?line {STRes492,S492} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList493 = [STRes492|STResList492],
+ ?line ITRes492 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S492),
+ ITResList493 = [ITRes492|ITResList492],
+
+
+ ?line {STRes493,S493} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList494 = [STRes493|STResList493],
+ ?line ITRes493 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S493),
+ ITResList494 = [ITRes493|ITResList493],
+
+
+ ?line {STRes494,S494} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList495 = [STRes494|STResList494],
+ ?line ITRes494 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S494),
+ ITResList495 = [ITRes494|ITResList494],
+
+
+ ?line {STRes495,S495} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList496 = [STRes495|STResList495],
+ ?line ITRes495 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S495),
+ ITResList496 = [ITRes495|ITResList495],
+
+
+ ?line {STRes496,S496} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList497 = [STRes496|STResList496],
+ ?line ITRes496 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S496),
+ ITResList497 = [ITRes496|ITResList496],
+
+
+ ?line {STRes497,S497} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList498 = [STRes497|STResList497],
+ ?line ITRes497 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S497),
+ ITResList498 = [ITRes497|ITResList497],
+
+
+ ?line {STRes498,S498} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList499 = [STRes498|STResList498],
+ ?line ITRes498 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S498),
+ ITResList499 = [ITRes498|ITResList498],
+
+
+ ?line {STRes499,S499} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList500 = [STRes499|STResList499],
+ ?line ITRes499 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S499),
+ ITResList500 = [ITRes499|ITResList499],
+
+
+ ?line {STRes500,S500} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList501 = [STRes500|STResList500],
+ ?line ITRes500 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S500),
+ ITResList501 = [ITRes500|ITResList500],
+
+
+ ?line {STRes501,S501} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_nonPositiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList502 = [STRes501|STResList501],
+ ?line ITRes501 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_nonPositiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S501),
+ ITResList502 = [ITRes501|ITResList501],
+
+
+ ?line {STRes502,S502} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_negativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList503 = [STRes502|STResList502],
+ ?line ITRes502 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_negativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S502),
+ ITResList503 = [ITRes502|ITResList502],
+
+
+ ?line {STRes503,S503} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList504 = [STRes503|STResList503],
+ ?line ITRes503 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_long.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S503),
+ ITResList504 = [ITRes503|ITResList503],
+
+
+ ?line {STRes504,S504} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList505 = [STRes504|STResList504],
+ ?line ITRes504 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_int.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S504),
+ ITResList505 = [ITRes504|ITResList504],
+
+
+ ?line {STRes505,S505} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList506 = [STRes505|STResList505],
+ ?line ITRes505 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_short.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S505),
+ ITResList506 = [ITRes505|ITResList505],
+
+
+ ?line {STRes506,S506} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList507 = [STRes506|STResList506],
+ ?line ITRes506 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S506),
+ ITResList507 = [ITRes506|ITResList506],
+
+
+ ?line {STRes507,S507} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList508 = [STRes507|STResList507],
+ ?line ITRes507 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S507),
+ ITResList508 = [ITRes507|ITResList507],
+
+
+ ?line {STRes508,S508} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList509 = [STRes508|STResList508],
+ ?line ITRes508 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S508),
+ ITResList509 = [ITRes508|ITResList508],
+
+
+ ?line {STRes509,S509} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList510 = [STRes509|STResList509],
+ ?line ITRes509 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S509),
+ ITResList510 = [ITRes509|ITResList509],
+
+
+ ?line {STRes510,S510} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList511 = [STRes510|STResList510],
+ ?line ITRes510 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S510),
+ ITResList511 = [ITRes510|ITResList510],
+
+
+ ?line {STRes511,S511} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList512 = [STRes511|STResList511],
+ ?line ITRes511 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S511),
+ ITResList512 = [ITRes511|ITResList511],
+
+
+ ?line {STRes512,S512} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList513 = [STRes512|STResList512],
+ ?line ITRes512 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S512),
+ ITResList513 = [ITRes512|ITResList512],
+
+
+ ?line {STRes513,S513} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList514 = [STRes513|STResList513],
+ ?line ITRes513 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S513),
+ ITResList514 = [ITRes513|ITResList513],
+
+
+ ?line {STRes514,S514} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList515 = [STRes514|STResList514],
+ ?line ITRes514 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_int_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S514),
+ ITResList515 = [ITRes514|ITResList514],
+
+
+ ?line {STRes515,S515} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList516 = [STRes515|STResList515],
+ ?line ITRes515 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S515),
+ ITResList516 = [ITRes515|ITResList515],
+
+
+ ?line {STRes516,S516} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList517 = [STRes516|STResList516],
+ ?line ITRes516 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S516),
+ ITResList517 = [ITRes516|ITResList516],
+
+
+ ?line {STRes517,S517} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList518 = [STRes517|STResList517],
+ ?line ITRes517 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S517),
+ ITResList518 = [ITRes517|ITResList517],
+
+
+ ?line {STRes518,S518} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList519 = [STRes518|STResList518],
+ ?line ITRes518 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S518),
+ ITResList519 = [ITRes518|ITResList518],
+
+
+ ?line {STRes519,S519} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList520 = [STRes519|STResList519],
+ ?line ITRes519 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S519),
+ ITResList520 = [ITRes519|ITResList519],
+
+
+ ?line {STRes520,S520} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList521 = [STRes520|STResList520],
+ ?line ITRes520 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S520),
+ ITResList521 = [ITRes520|ITResList520],
+
+
+ ?line {STRes521,S521} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList522 = [STRes521|STResList521],
+ ?line ITRes521 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S521),
+ ITResList522 = [ITRes521|ITResList521],
+
+
+ ?line {STRes522,S522} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList523 = [STRes522|STResList522],
+ ?line ITRes522 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S522),
+ ITResList523 = [ITRes522|ITResList522],
+
+
+ ?line {STRes523,S523} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList524 = [STRes523|STResList523],
+ ?line ITRes523 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S523),
+ ITResList524 = [ITRes523|ITResList523],
+
+
+ ?line {STRes524,S524} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList525 = [STRes524|STResList524],
+ ?line ITRes524 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S524),
+ ITResList525 = [ITRes524|ITResList524],
+
+
+ ?line {STRes525,S525} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList526 = [STRes525|STResList525],
+ ?line ITRes525 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S525),
+ ITResList526 = [ITRes525|ITResList525],
+
+
+ ?line {STRes526,S526} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_nonPositiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList527 = [STRes526|STResList526],
+ ?line ITRes526 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_nonPositiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S526),
+ ITResList527 = [ITRes526|ITResList526],
+
+
+ ?line {STRes527,S527} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_negativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList528 = [STRes527|STResList527],
+ ?line ITRes527 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_negativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S527),
+ ITResList528 = [ITRes527|ITResList527],
+
+
+ ?line {STRes528,S528} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList529 = [STRes528|STResList528],
+ ?line ITRes528 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_long.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S528),
+ ITResList529 = [ITRes528|ITResList528],
+
+
+ ?line {STRes529,S529} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList530 = [STRes529|STResList529],
+ ?line ITRes529 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_int.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S529),
+ ITResList530 = [ITRes529|ITResList529],
+
+
+ ?line {STRes530,S530} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList531 = [STRes530|STResList530],
+ ?line ITRes530 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_short.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S530),
+ ITResList531 = [ITRes530|ITResList530],
+
+
+ ?line {STRes531,S531} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList532 = [STRes531|STResList531],
+ ?line ITRes531 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S531),
+ ITResList532 = [ITRes531|ITResList531],
+
+
+ ?line {STRes532,S532} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList533 = [STRes532|STResList532],
+ ?line ITRes532 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S532),
+ ITResList533 = [ITRes532|ITResList532],
+
+
+ ?line {STRes533,S533} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList534 = [STRes533|STResList533],
+ ?line ITRes533 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S533),
+ ITResList534 = [ITRes533|ITResList533],
+
+
+ ?line {STRes534,S534} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList535 = [STRes534|STResList534],
+ ?line ITRes534 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S534),
+ ITResList535 = [ITRes534|ITResList534],
+
+
+ ?line {STRes535,S535} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList536 = [STRes535|STResList535],
+ ?line ITRes535 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S535),
+ ITResList536 = [ITRes535|ITResList535],
+
+
+ ?line {STRes536,S536} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList537 = [STRes536|STResList536],
+ ?line ITRes536 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S536),
+ ITResList537 = [ITRes536|ITResList536],
+
+
+ ?line {STRes537,S537} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList538 = [STRes537|STResList537],
+ ?line ITRes537 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S537),
+ ITResList538 = [ITRes537|ITResList537],
+
+
+ ?line {STRes538,S538} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList539 = [STRes538|STResList538],
+ ?line ITRes538 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S538),
+ ITResList539 = [ITRes538|ITResList538],
+
+
+ ?line {STRes539,S539} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList540 = [STRes539|STResList539],
+ ?line ITRes539 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_short_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S539),
+ ITResList540 = [ITRes539|ITResList539],
+
+
+ ?line {STRes540,S540} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList541 = [STRes540|STResList540],
+ ?line ITRes540 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S540),
+ ITResList541 = [ITRes540|ITResList540],
+
+
+ ?line {STRes541,S541} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList542 = [STRes541|STResList541],
+ ?line ITRes541 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S541),
+ ITResList542 = [ITRes541|ITResList541],
+
+
+ ?line {STRes542,S542} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList543 = [STRes542|STResList542],
+ ?line ITRes542 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S542),
+ ITResList543 = [ITRes542|ITResList542],
+
+
+ ?line {STRes543,S543} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList544 = [STRes543|STResList543],
+ ?line ITRes543 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S543),
+ ITResList544 = [ITRes543|ITResList543],
+
+
+ ?line {STRes544,S544} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList545 = [STRes544|STResList544],
+ ?line ITRes544 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S544),
+ ITResList545 = [ITRes544|ITResList544],
+
+
+ ?line {STRes545,S545} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList546 = [STRes545|STResList545],
+ ?line ITRes545 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S545),
+ ITResList546 = [ITRes545|ITResList545],
+
+
+ ?line {STRes546,S546} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList547 = [STRes546|STResList546],
+ ?line ITRes546 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S546),
+ ITResList547 = [ITRes546|ITResList546],
+
+
+ ?line {STRes547,S547} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList548 = [STRes547|STResList547],
+ ?line ITRes547 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S547),
+ ITResList548 = [ITRes547|ITResList547],
+
+
+ ?line {STRes548,S548} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList549 = [STRes548|STResList548],
+ ?line ITRes548 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S548),
+ ITResList549 = [ITRes548|ITResList548],
+
+
+ ?line {STRes549,S549} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList550 = [STRes549|STResList549],
+ ?line ITRes549 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S549),
+ ITResList550 = [ITRes549|ITResList549],
+
+
+ ?line {STRes550,S550} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList551 = [STRes550|STResList550],
+ ?line ITRes550 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S550),
+ ITResList551 = [ITRes550|ITResList550],
+
+
+ ?line {STRes551,S551} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_nonPositiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList552 = [STRes551|STResList551],
+ ?line ITRes551 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_nonPositiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S551),
+ ITResList552 = [ITRes551|ITResList551],
+
+
+ ?line {STRes552,S552} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_negativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList553 = [STRes552|STResList552],
+ ?line ITRes552 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_negativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S552),
+ ITResList553 = [ITRes552|ITResList552],
+
+
+ ?line {STRes553,S553} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList554 = [STRes553|STResList553],
+ ?line ITRes553 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_long.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S553),
+ ITResList554 = [ITRes553|ITResList553],
+
+
+ ?line {STRes554,S554} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList555 = [STRes554|STResList554],
+ ?line ITRes554 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_int.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S554),
+ ITResList555 = [ITRes554|ITResList554],
+
+
+ ?line {STRes555,S555} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList556 = [STRes555|STResList555],
+ ?line ITRes555 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_short.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S555),
+ ITResList556 = [ITRes555|ITResList555],
+
+
+ ?line {STRes556,S556} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList557 = [STRes556|STResList556],
+ ?line ITRes556 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S556),
+ ITResList557 = [ITRes556|ITResList556],
+
+
+ ?line {STRes557,S557} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList558 = [STRes557|STResList557],
+ ?line ITRes557 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S557),
+ ITResList558 = [ITRes557|ITResList557],
+
+
+ ?line {STRes558,S558} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList559 = [STRes558|STResList558],
+ ?line ITRes558 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S558),
+ ITResList559 = [ITRes558|ITResList558],
+
+
+ ?line {STRes559,S559} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList560 = [STRes559|STResList559],
+ ?line ITRes559 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S559),
+ ITResList560 = [ITRes559|ITResList559],
+
+
+ ?line {STRes560,S560} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList561 = [STRes560|STResList560],
+ ?line ITRes560 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S560),
+ ITResList561 = [ITRes560|ITResList560],
+
+
+ ?line {STRes561,S561} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList562 = [STRes561|STResList561],
+ ?line ITRes561 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S561),
+ ITResList562 = [ITRes561|ITResList561],
+
+
+ ?line {STRes562,S562} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList563 = [STRes562|STResList562],
+ ?line ITRes562 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S562),
+ ITResList563 = [ITRes562|ITResList562],
+
+
+ ?line {STRes563,S563} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList564 = [STRes563|STResList563],
+ ?line ITRes563 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S563),
+ ITResList564 = [ITRes563|ITResList563],
+
+
+ ?line {STRes564,S564} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList565 = [STRes564|STResList564],
+ ?line ITRes564 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_byte_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S564),
+ ITResList565 = [ITRes564|ITResList564],
+
+
+ ?line {STRes565,S565} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList566 = [STRes565|STResList565],
+ ?line ITRes565 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S565),
+ ITResList566 = [ITRes565|ITResList565],
+
+
+ ?line {STRes566,S566} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList567 = [STRes566|STResList566],
+ ?line ITRes566 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S566),
+ ITResList567 = [ITRes566|ITResList566],
+
+
+ ?line {STRes567,S567} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList568 = [STRes567|STResList567],
+ ?line ITRes567 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S567),
+ ITResList568 = [ITRes567|ITResList567],
+
+
+ ?line {STRes568,S568} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList569 = [STRes568|STResList568],
+ ?line ITRes568 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S568),
+ ITResList569 = [ITRes568|ITResList568],
+
+
+ ?line {STRes569,S569} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList570 = [STRes569|STResList569],
+ ?line ITRes569 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S569),
+ ITResList570 = [ITRes569|ITResList569],
+
+
+ ?line {STRes570,S570} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList571 = [STRes570|STResList570],
+ ?line ITRes570 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S570),
+ ITResList571 = [ITRes570|ITResList570],
+
+
+ ?line {STRes571,S571} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList572 = [STRes571|STResList571],
+ ?line ITRes571 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S571),
+ ITResList572 = [ITRes571|ITResList571],
+
+
+ ?line {STRes572,S572} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList573 = [STRes572|STResList572],
+ ?line ITRes572 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S572),
+ ITResList573 = [ITRes572|ITResList572],
+
+
+ ?line {STRes573,S573} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList574 = [STRes573|STResList573],
+ ?line ITRes573 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S573),
+ ITResList574 = [ITRes573|ITResList573],
+
+
+ ?line {STRes574,S574} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList575 = [STRes574|STResList574],
+ ?line ITRes574 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S574),
+ ITResList575 = [ITRes574|ITResList574],
+
+
+ ?line {STRes575,S575} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList576 = [STRes575|STResList575],
+ ?line ITRes575 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S575),
+ ITResList576 = [ITRes575|ITResList575],
+
+
+ ?line {STRes576,S576} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList577 = [STRes576|STResList576],
+ ?line ITRes576 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_long.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S576),
+ ITResList577 = [ITRes576|ITResList576],
+
+
+ ?line {STRes577,S577} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList578 = [STRes577|STResList577],
+ ?line ITRes577 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_int.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S577),
+ ITResList578 = [ITRes577|ITResList577],
+
+
+ ?line {STRes578,S578} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList579 = [STRes578|STResList578],
+ ?line ITRes578 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_short.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S578),
+ ITResList579 = [ITRes578|ITResList578],
+
+
+ ?line {STRes579,S579} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList580 = [STRes579|STResList579],
+ ?line ITRes579 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S579),
+ ITResList580 = [ITRes579|ITResList579],
+
+
+ ?line {STRes580,S580} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList581 = [STRes580|STResList580],
+ ?line ITRes580 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S580),
+ ITResList581 = [ITRes580|ITResList580],
+
+
+ ?line {STRes581,S581} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList582 = [STRes581|STResList581],
+ ?line ITRes581 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S581),
+ ITResList582 = [ITRes581|ITResList581],
+
+
+ ?line {STRes582,S582} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList583 = [STRes582|STResList582],
+ ?line ITRes582 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S582),
+ ITResList583 = [ITRes582|ITResList582],
+
+
+ ?line {STRes583,S583} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList584 = [STRes583|STResList583],
+ ?line ITRes583 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S583),
+ ITResList584 = [ITRes583|ITResList583],
+
+
+ ?line {STRes584,S584} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList585 = [STRes584|STResList584],
+ ?line ITRes584 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S584),
+ ITResList585 = [ITRes584|ITResList584],
+
+
+ ?line {STRes585,S585} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList586 = [STRes585|STResList585],
+ ?line ITRes585 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S585),
+ ITResList586 = [ITRes585|ITResList585],
+
+
+ ?line {STRes586,S586} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList587 = [STRes586|STResList586],
+ ?line ITRes586 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S586),
+ ITResList587 = [ITRes586|ITResList586],
+
+
+ ?line {STRes587,S587} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList588 = [STRes587|STResList587],
+ ?line ITRes587 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_nonNegativeInteger_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S587),
+ ITResList588 = [ITRes587|ITResList587],
+
+
+ ?line {STRes588,S588} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList589 = [STRes588|STResList588],
+ ?line ITRes588 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S588),
+ ITResList589 = [ITRes588|ITResList588],
+
+
+ ?line {STRes589,S589} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList590 = [STRes589|STResList589],
+ ?line ITRes589 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S589),
+ ITResList590 = [ITRes589|ITResList589],
+
+
+ ?line {STRes590,S590} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList591 = [STRes590|STResList590],
+ ?line ITRes590 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S590),
+ ITResList591 = [ITRes590|ITResList590],
+
+
+ ?line {STRes591,S591} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList592 = [STRes591|STResList591],
+ ?line ITRes591 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S591),
+ ITResList592 = [ITRes591|ITResList591],
+
+
+ ?line {STRes592,S592} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList593 = [STRes592|STResList592],
+ ?line ITRes592 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S592),
+ ITResList593 = [ITRes592|ITResList592],
+
+
+ ?line {STRes593,S593} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList594 = [STRes593|STResList593],
+ ?line ITRes593 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S593),
+ ITResList594 = [ITRes593|ITResList593],
+
+
+ ?line {STRes594,S594} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList595 = [STRes594|STResList594],
+ ?line ITRes594 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S594),
+ ITResList595 = [ITRes594|ITResList594],
+
+
+ ?line {STRes595,S595} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList596 = [STRes595|STResList595],
+ ?line ITRes595 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S595),
+ ITResList596 = [ITRes595|ITResList595],
+
+
+ ?line {STRes596,S596} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList597 = [STRes596|STResList596],
+ ?line ITRes596 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S596),
+ ITResList597 = [ITRes596|ITResList596],
+
+
+ ?line {STRes597,S597} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList598 = [STRes597|STResList597],
+ ?line ITRes597 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S597),
+ ITResList598 = [ITRes597|ITResList597],
+
+
+ ?line {STRes598,S598} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList599 = [STRes598|STResList598],
+ ?line ITRes598 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S598),
+ ITResList599 = [ITRes598|ITResList598],
+
+
+ ?line {STRes599,S599} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList600 = [STRes599|STResList599],
+ ?line ITRes599 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_long.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S599),
+ ITResList600 = [ITRes599|ITResList599],
+
+
+ ?line {STRes600,S600} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList601 = [STRes600|STResList600],
+ ?line ITRes600 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_int.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S600),
+ ITResList601 = [ITRes600|ITResList600],
+
+
+ ?line {STRes601,S601} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList602 = [STRes601|STResList601],
+ ?line ITRes601 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_short.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S601),
+ ITResList602 = [ITRes601|ITResList601],
+
+
+ ?line {STRes602,S602} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList603 = [STRes602|STResList602],
+ ?line ITRes602 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S602),
+ ITResList603 = [ITRes602|ITResList602],
+
+
+ ?line {STRes603,S603} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList604 = [STRes603|STResList603],
+ ?line ITRes603 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S603),
+ ITResList604 = [ITRes603|ITResList603],
+
+
+ ?line {STRes604,S604} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList605 = [STRes604|STResList604],
+ ?line ITRes604 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S604),
+ ITResList605 = [ITRes604|ITResList604],
+
+
+ ?line {STRes605,S605} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList606 = [STRes605|STResList605],
+ ?line ITRes605 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S605),
+ ITResList606 = [ITRes605|ITResList605],
+
+
+ ?line {STRes606,S606} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList607 = [STRes606|STResList606],
+ ?line ITRes606 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S606),
+ ITResList607 = [ITRes606|ITResList606],
+
+
+ ?line {STRes607,S607} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList608 = [STRes607|STResList607],
+ ?line ITRes607 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S607),
+ ITResList608 = [ITRes607|ITResList607],
+
+
+ ?line {STRes608,S608} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList609 = [STRes608|STResList608],
+ ?line ITRes608 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S608),
+ ITResList609 = [ITRes608|ITResList608],
+
+
+ ?line {STRes609,S609} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList610 = [STRes609|STResList609],
+ ?line ITRes609 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S609),
+ ITResList610 = [ITRes609|ITResList609],
+
+
+ ?line {STRes610,S610} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList611 = [STRes610|STResList610],
+ ?line ITRes610 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_positiveInteger_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S610),
+ ITResList611 = [ITRes610|ITResList610],
+
+
+ ?line {STRes611,S611} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList612 = [STRes611|STResList611],
+ ?line ITRes611 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S611),
+ ITResList612 = [ITRes611|ITResList611],
+
+
+ ?line {STRes612,S612} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList613 = [STRes612|STResList612],
+ ?line ITRes612 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S612),
+ ITResList613 = [ITRes612|ITResList612],
+
+
+ ?line {STRes613,S613} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList614 = [STRes613|STResList613],
+ ?line ITRes613 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S613),
+ ITResList614 = [ITRes613|ITResList613],
+
+
+ ?line {STRes614,S614} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList615 = [STRes614|STResList614],
+ ?line ITRes614 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S614),
+ ITResList615 = [ITRes614|ITResList614],
+
+
+ ?line {STRes615,S615} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList616 = [STRes615|STResList615],
+ ?line ITRes615 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S615),
+ ITResList616 = [ITRes615|ITResList615],
+
+
+ ?line {STRes616,S616} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList617 = [STRes616|STResList616],
+ ?line ITRes616 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S616),
+ ITResList617 = [ITRes616|ITResList616],
+
+
+ ?line {STRes617,S617} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList618 = [STRes617|STResList617],
+ ?line ITRes617 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S617),
+ ITResList618 = [ITRes617|ITResList617],
+
+
+ ?line {STRes618,S618} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList619 = [STRes618|STResList618],
+ ?line ITRes618 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S618),
+ ITResList619 = [ITRes618|ITResList618],
+
+
+ ?line {STRes619,S619} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList620 = [STRes619|STResList619],
+ ?line ITRes619 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S619),
+ ITResList620 = [ITRes619|ITResList619],
+
+
+ ?line {STRes620,S620} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList621 = [STRes620|STResList620],
+ ?line ITRes620 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S620),
+ ITResList621 = [ITRes620|ITResList620],
+
+
+ ?line {STRes621,S621} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList622 = [STRes621|STResList621],
+ ?line ITRes621 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S621),
+ ITResList622 = [ITRes621|ITResList621],
+
+
+ ?line {STRes622,S622} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList623 = [STRes622|STResList622],
+ ?line ITRes622 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_long.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S622),
+ ITResList623 = [ITRes622|ITResList622],
+
+
+ ?line {STRes623,S623} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList624 = [STRes623|STResList623],
+ ?line ITRes623 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_int.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S623),
+ ITResList624 = [ITRes623|ITResList623],
+
+
+ ?line {STRes624,S624} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList625 = [STRes624|STResList624],
+ ?line ITRes624 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_short.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S624),
+ ITResList625 = [ITRes624|ITResList624],
+
+
+ ?line {STRes625,S625} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList626 = [STRes625|STResList625],
+ ?line ITRes625 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S625),
+ ITResList626 = [ITRes625|ITResList625],
+
+
+ ?line {STRes626,S626} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList627 = [STRes626|STResList626],
+ ?line ITRes626 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S626),
+ ITResList627 = [ITRes626|ITResList626],
+
+
+ ?line {STRes627,S627} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList628 = [STRes627|STResList627],
+ ?line ITRes627 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S627),
+ ITResList628 = [ITRes627|ITResList627],
+
+
+ ?line {STRes628,S628} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList629 = [STRes628|STResList628],
+ ?line ITRes628 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S628),
+ ITResList629 = [ITRes628|ITResList628],
+
+
+ ?line {STRes629,S629} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList630 = [STRes629|STResList629],
+ ?line ITRes629 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S629),
+ ITResList630 = [ITRes629|ITResList629],
+
+
+ ?line {STRes630,S630} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList631 = [STRes630|STResList630],
+ ?line ITRes630 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S630),
+ ITResList631 = [ITRes630|ITResList630],
+
+
+ ?line {STRes631,S631} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList632 = [STRes631|STResList631],
+ ?line ITRes631 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S631),
+ ITResList632 = [ITRes631|ITResList631],
+
+
+ ?line {STRes632,S632} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList633 = [STRes632|STResList632],
+ ?line ITRes632 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S632),
+ ITResList633 = [ITRes632|ITResList632],
+
+
+ ?line {STRes633,S633} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList634 = [STRes633|STResList633],
+ ?line ITRes633 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedLong_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S633),
+ ITResList634 = [ITRes633|ITResList633],
+
+
+ ?line {STRes634,S634} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList635 = [STRes634|STResList634],
+ ?line ITRes634 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S634),
+ ITResList635 = [ITRes634|ITResList634],
+
+
+ ?line {STRes635,S635} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList636 = [STRes635|STResList635],
+ ?line ITRes635 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S635),
+ ITResList636 = [ITRes635|ITResList635],
+
+
+ ?line {STRes636,S636} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList637 = [STRes636|STResList636],
+ ?line ITRes636 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S636),
+ ITResList637 = [ITRes636|ITResList636],
+
+
+ ?line {STRes637,S637} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList638 = [STRes637|STResList637],
+ ?line ITRes637 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S637),
+ ITResList638 = [ITRes637|ITResList637],
+
+
+ ?line {STRes638,S638} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList639 = [STRes638|STResList638],
+ ?line ITRes638 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S638),
+ ITResList639 = [ITRes638|ITResList638],
+
+
+ ?line {STRes639,S639} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList640 = [STRes639|STResList639],
+ ?line ITRes639 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S639),
+ ITResList640 = [ITRes639|ITResList639],
+
+
+ ?line {STRes640,S640} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList641 = [STRes640|STResList640],
+ ?line ITRes640 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S640),
+ ITResList641 = [ITRes640|ITResList640],
+
+
+ ?line {STRes641,S641} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList642 = [STRes641|STResList641],
+ ?line ITRes641 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S641),
+ ITResList642 = [ITRes641|ITResList641],
+
+
+ ?line {STRes642,S642} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList643 = [STRes642|STResList642],
+ ?line ITRes642 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S642),
+ ITResList643 = [ITRes642|ITResList642],
+
+
+ ?line {STRes643,S643} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList644 = [STRes643|STResList643],
+ ?line ITRes643 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S643),
+ ITResList644 = [ITRes643|ITResList643],
+
+
+ ?line {STRes644,S644} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList645 = [STRes644|STResList644],
+ ?line ITRes644 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S644),
+ ITResList645 = [ITRes644|ITResList644],
+
+
+ ?line {STRes645,S645} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList646 = [STRes645|STResList645],
+ ?line ITRes645 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_long.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S645),
+ ITResList646 = [ITRes645|ITResList645],
+
+
+ ?line {STRes646,S646} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList647 = [STRes646|STResList646],
+ ?line ITRes646 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_int.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S646),
+ ITResList647 = [ITRes646|ITResList646],
+
+
+ ?line {STRes647,S647} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList648 = [STRes647|STResList647],
+ ?line ITRes647 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_short.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S647),
+ ITResList648 = [ITRes647|ITResList647],
+
+
+ ?line {STRes648,S648} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList649 = [STRes648|STResList648],
+ ?line ITRes648 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S648),
+ ITResList649 = [ITRes648|ITResList648],
+
+
+ ?line {STRes649,S649} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList650 = [STRes649|STResList649],
+ ?line ITRes649 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S649),
+ ITResList650 = [ITRes649|ITResList649],
+
+
+ ?line {STRes650,S650} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList651 = [STRes650|STResList650],
+ ?line ITRes650 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S650),
+ ITResList651 = [ITRes650|ITResList650],
+
+
+ ?line {STRes651,S651} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList652 = [STRes651|STResList651],
+ ?line ITRes651 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S651),
+ ITResList652 = [ITRes651|ITResList651],
+
+
+ ?line {STRes652,S652} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList653 = [STRes652|STResList652],
+ ?line ITRes652 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S652),
+ ITResList653 = [ITRes652|ITResList652],
+
+
+ ?line {STRes653,S653} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList654 = [STRes653|STResList653],
+ ?line ITRes653 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S653),
+ ITResList654 = [ITRes653|ITResList653],
+
+
+ ?line {STRes654,S654} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList655 = [STRes654|STResList654],
+ ?line ITRes654 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S654),
+ ITResList655 = [ITRes654|ITResList654],
+
+
+ ?line {STRes655,S655} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList656 = [STRes655|STResList655],
+ ?line ITRes655 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S655),
+ ITResList656 = [ITRes655|ITResList655],
+
+
+ ?line {STRes656,S656} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList657 = [STRes656|STResList656],
+ ?line ITRes656 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedInt_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S656),
+ ITResList657 = [ITRes656|ITResList656],
+
+
+ ?line {STRes657,S657} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList658 = [STRes657|STResList657],
+ ?line ITRes657 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S657),
+ ITResList658 = [ITRes657|ITResList657],
+
+
+ ?line {STRes658,S658} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList659 = [STRes658|STResList658],
+ ?line ITRes658 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S658),
+ ITResList659 = [ITRes658|ITResList658],
+
+
+ ?line {STRes659,S659} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList660 = [STRes659|STResList659],
+ ?line ITRes659 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S659),
+ ITResList660 = [ITRes659|ITResList659],
+
+
+ ?line {STRes660,S660} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList661 = [STRes660|STResList660],
+ ?line ITRes660 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S660),
+ ITResList661 = [ITRes660|ITResList660],
+
+
+ ?line {STRes661,S661} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList662 = [STRes661|STResList661],
+ ?line ITRes661 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S661),
+ ITResList662 = [ITRes661|ITResList661],
+
+
+ ?line {STRes662,S662} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList663 = [STRes662|STResList662],
+ ?line ITRes662 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S662),
+ ITResList663 = [ITRes662|ITResList662],
+
+
+ ?line {STRes663,S663} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList664 = [STRes663|STResList663],
+ ?line ITRes663 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S663),
+ ITResList664 = [ITRes663|ITResList663],
+
+
+ ?line {STRes664,S664} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList665 = [STRes664|STResList664],
+ ?line ITRes664 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S664),
+ ITResList665 = [ITRes664|ITResList664],
+
+
+ ?line {STRes665,S665} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList666 = [STRes665|STResList665],
+ ?line ITRes665 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S665),
+ ITResList666 = [ITRes665|ITResList665],
+
+
+ ?line {STRes666,S666} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList667 = [STRes666|STResList666],
+ ?line ITRes666 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S666),
+ ITResList667 = [ITRes666|ITResList666],
+
+
+ ?line {STRes667,S667} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList668 = [STRes667|STResList667],
+ ?line ITRes667 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S667),
+ ITResList668 = [ITRes667|ITResList667],
+
+
+ ?line {STRes668,S668} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList669 = [STRes668|STResList668],
+ ?line ITRes668 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_long.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S668),
+ ITResList669 = [ITRes668|ITResList668],
+
+
+ ?line {STRes669,S669} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList670 = [STRes669|STResList669],
+ ?line ITRes669 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_int.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S669),
+ ITResList670 = [ITRes669|ITResList669],
+
+
+ ?line {STRes670,S670} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList671 = [STRes670|STResList670],
+ ?line ITRes670 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_short.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S670),
+ ITResList671 = [ITRes670|ITResList670],
+
+
+ ?line {STRes671,S671} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList672 = [STRes671|STResList671],
+ ?line ITRes671 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S671),
+ ITResList672 = [ITRes671|ITResList671],
+
+
+ ?line {STRes672,S672} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList673 = [STRes672|STResList672],
+ ?line ITRes672 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S672),
+ ITResList673 = [ITRes672|ITResList672],
+
+
+ ?line {STRes673,S673} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList674 = [STRes673|STResList673],
+ ?line ITRes673 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S673),
+ ITResList674 = [ITRes673|ITResList673],
+
+
+ ?line {STRes674,S674} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList675 = [STRes674|STResList674],
+ ?line ITRes674 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S674),
+ ITResList675 = [ITRes674|ITResList674],
+
+
+ ?line {STRes675,S675} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList676 = [STRes675|STResList675],
+ ?line ITRes675 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S675),
+ ITResList676 = [ITRes675|ITResList675],
+
+
+ ?line {STRes676,S676} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList677 = [STRes676|STResList676],
+ ?line ITRes676 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S676),
+ ITResList677 = [ITRes676|ITResList676],
+
+
+ ?line {STRes677,S677} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList678 = [STRes677|STResList677],
+ ?line ITRes677 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S677),
+ ITResList678 = [ITRes677|ITResList677],
+
+
+ ?line {STRes678,S678} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList679 = [STRes678|STResList678],
+ ?line ITRes678 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S678),
+ ITResList679 = [ITRes678|ITResList678],
+
+
+ ?line {STRes679,S679} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList680 = [STRes679|STResList679],
+ ?line ITRes679 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedShort_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S679),
+ ITResList680 = [ITRes679|ITResList679],
+
+
+ ?line {STRes680,S680} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList681 = [STRes680|STResList680],
+ ?line ITRes680 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S680),
+ ITResList681 = [ITRes680|ITResList680],
+
+
+ ?line {STRes681,S681} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList682 = [STRes681|STResList681],
+ ?line ITRes681 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S681),
+ ITResList682 = [ITRes681|ITResList681],
+
+
+ ?line {STRes682,S682} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList683 = [STRes682|STResList682],
+ ?line ITRes682 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S682),
+ ITResList683 = [ITRes682|ITResList682],
+
+
+ ?line {STRes683,S683} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList684 = [STRes683|STResList683],
+ ?line ITRes683 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S683),
+ ITResList684 = [ITRes683|ITResList683],
+
+
+ ?line {STRes684,S684} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList685 = [STRes684|STResList684],
+ ?line ITRes684 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S684),
+ ITResList685 = [ITRes684|ITResList684],
+
+
+ ?line {STRes685,S685} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList686 = [STRes685|STResList685],
+ ?line ITRes685 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S685),
+ ITResList686 = [ITRes685|ITResList685],
+
+
+ ?line {STRes686,S686} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList687 = [STRes686|STResList686],
+ ?line ITRes686 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S686),
+ ITResList687 = [ITRes686|ITResList686],
+
+
+ ?line {STRes687,S687} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList688 = [STRes687|STResList687],
+ ?line ITRes687 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S687),
+ ITResList688 = [ITRes687|ITResList687],
+
+
+ ?line {STRes688,S688} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList689 = [STRes688|STResList688],
+ ?line ITRes688 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S688),
+ ITResList689 = [ITRes688|ITResList688],
+
+
+ ?line {STRes689,S689} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList690 = [STRes689|STResList689],
+ ?line ITRes689 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S689),
+ ITResList690 = [ITRes689|ITResList689],
+
+
+ ?line {STRes690,S690} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList691 = [STRes690|STResList690],
+ ?line ITRes690 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S690),
+ ITResList691 = [ITRes690|ITResList690],
+
+
+ ?line {STRes691,S691} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList692 = [STRes691|STResList691],
+ ?line ITRes691 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_long.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S691),
+ ITResList692 = [ITRes691|ITResList691],
+
+
+ ?line {STRes692,S692} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList693 = [STRes692|STResList692],
+ ?line ITRes692 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_int.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S692),
+ ITResList693 = [ITRes692|ITResList692],
+
+
+ ?line {STRes693,S693} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList694 = [STRes693|STResList693],
+ ?line ITRes693 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_short.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S693),
+ ITResList694 = [ITRes693|ITResList693],
+
+
+ ?line {STRes694,S694} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList695 = [STRes694|STResList694],
+ ?line ITRes694 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S694),
+ ITResList695 = [ITRes694|ITResList694],
+
+
+ ?line {STRes695,S695} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList696 = [STRes695|STResList695],
+ ?line ITRes695 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S695),
+ ITResList696 = [ITRes695|ITResList695],
+
+
+ ?line {STRes696,S696} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList697 = [STRes696|STResList696],
+ ?line ITRes696 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S696),
+ ITResList697 = [ITRes696|ITResList696],
+
+
+ ?line {STRes697,S697} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList698 = [STRes697|STResList697],
+ ?line ITRes697 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S697),
+ ITResList698 = [ITRes697|ITResList697],
+
+
+ ?line {STRes698,S698} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList699 = [STRes698|STResList698],
+ ?line ITRes698 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S698),
+ ITResList699 = [ITRes698|ITResList698],
+
+
+ ?line {STRes699,S699} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList700 = [STRes699|STResList699],
+ ?line ITRes699 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S699),
+ ITResList700 = [ITRes699|ITResList699],
+
+
+ ?line {STRes700,S700} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList701 = [STRes700|STResList700],
+ ?line ITRes700 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S700),
+ ITResList701 = [ITRes700|ITResList700],
+
+
+ ?line {STRes701,S701} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList702 = [STRes701|STResList701],
+ ?line ITRes701 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S701),
+ ITResList702 = [ITRes701|ITResList701],
+
+
+ ?line {STRes702,S702} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList703 = [STRes702|STResList702],
+ ?line ITRes702 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_unsignedByte_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S702),
+ ITResList703 = [ITRes702|ITResList702],
+
+
+ ?line {STRes703,S703} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList704 = [STRes703|STResList703],
+ ?line ITRes703 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S703),
+ ITResList704 = [ITRes703|ITResList703],
+
+
+ ?line {STRes704,S704} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList705 = [STRes704|STResList704],
+ ?line ITRes704 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S704),
+ ITResList705 = [ITRes704|ITResList704],
+
+
+ ?line {STRes705,S705} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList706 = [STRes705|STResList705],
+ ?line ITRes705 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S705),
+ ITResList706 = [ITRes705|ITResList705],
+
+
+ ?line {STRes706,S706} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList707 = [STRes706|STResList706],
+ ?line ITRes706 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S706),
+ ITResList707 = [ITRes706|ITResList706],
+
+
+ ?line {STRes707,S707} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList708 = [STRes707|STResList707],
+ ?line ITRes707 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S707),
+ ITResList708 = [ITRes707|ITResList707],
+
+
+ ?line {STRes708,S708} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList709 = [STRes708|STResList708],
+ ?line ITRes708 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S708),
+ ITResList709 = [ITRes708|ITResList708],
+
+
+ ?line {STRes709,S709} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList710 = [STRes709|STResList709],
+ ?line ITRes709 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S709),
+ ITResList710 = [ITRes709|ITResList709],
+
+
+ ?line {STRes710,S710} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList711 = [STRes710|STResList710],
+ ?line ITRes710 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S710),
+ ITResList711 = [ITRes710|ITResList710],
+
+
+ ?line {STRes711,S711} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList712 = [STRes711|STResList711],
+ ?line ITRes711 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S711),
+ ITResList712 = [ITRes711|ITResList711],
+
+
+ ?line {STRes712,S712} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList713 = [STRes712|STResList712],
+ ?line ITRes712 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S712),
+ ITResList713 = [ITRes712|ITResList712],
+
+
+ ?line {STRes713,S713} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList714 = [STRes713|STResList713],
+ ?line ITRes713 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S713),
+ ITResList714 = [ITRes713|ITResList713],
+
+
+ ?line {STRes714,S714} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_nonPositiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList715 = [STRes714|STResList714],
+ ?line ITRes714 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_nonPositiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S714),
+ ITResList715 = [ITRes714|ITResList714],
+
+
+ ?line {STRes715,S715} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_negativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList716 = [STRes715|STResList715],
+ ?line ITRes715 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_negativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S715),
+ ITResList716 = [ITRes715|ITResList715],
+
+
+ ?line {STRes716,S716} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList717 = [STRes716|STResList716],
+ ?line ITRes716 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_long.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S716),
+ ITResList717 = [ITRes716|ITResList716],
+
+
+ ?line {STRes717,S717} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList718 = [STRes717|STResList717],
+ ?line ITRes717 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_int.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S717),
+ ITResList718 = [ITRes717|ITResList717],
+
+
+ ?line {STRes718,S718} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList719 = [STRes718|STResList718],
+ ?line ITRes718 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_short.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S718),
+ ITResList719 = [ITRes718|ITResList718],
+
+
+ ?line {STRes719,S719} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList720 = [STRes719|STResList719],
+ ?line ITRes719 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S719),
+ ITResList720 = [ITRes719|ITResList719],
+
+
+ ?line {STRes720,S720} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList721 = [STRes720|STResList720],
+ ?line ITRes720 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S720),
+ ITResList721 = [ITRes720|ITResList720],
+
+
+ ?line {STRes721,S721} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList722 = [STRes721|STResList721],
+ ?line ITRes721 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S721),
+ ITResList722 = [ITRes721|ITResList721],
+
+
+ ?line {STRes722,S722} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList723 = [STRes722|STResList722],
+ ?line ITRes722 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S722),
+ ITResList723 = [ITRes722|ITResList722],
+
+
+ ?line {STRes723,S723} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList724 = [STRes723|STResList723],
+ ?line ITRes723 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S723),
+ ITResList724 = [ITRes723|ITResList723],
+
+
+ ?line {STRes724,S724} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList725 = [STRes724|STResList724],
+ ?line ITRes724 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S724),
+ ITResList725 = [ITRes724|ITResList724],
+
+
+ ?line {STRes725,S725} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList726 = [STRes725|STResList725],
+ ?line ITRes725 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S725),
+ ITResList726 = [ITRes725|ITResList725],
+
+
+ ?line {STRes726,S726} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList727 = [STRes726|STResList726],
+ ?line ITRes726 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_double.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S726),
+ ITResList727 = [ITRes726|ITResList726],
+
+
+ ?line {STRes727,S727} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList728 = [STRes727|STResList727],
+ ?line ITRes727 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_double_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S727),
+ ITResList728 = [ITRes727|ITResList727],
+
+
+ ?line {STRes728,S728} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList729 = [STRes728|STResList728],
+ ?line ITRes728 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S728),
+ ITResList729 = [ITRes728|ITResList728],
+
+
+ ?line {STRes729,S729} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList730 = [STRes729|STResList729],
+ ?line ITRes729 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S729),
+ ITResList730 = [ITRes729|ITResList729],
+
+
+ ?line {STRes730,S730} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList731 = [STRes730|STResList730],
+ ?line ITRes730 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S730),
+ ITResList731 = [ITRes730|ITResList730],
+
+
+ ?line {STRes731,S731} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_language.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList732 = [STRes731|STResList731],
+ ?line ITRes731 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_language.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S731),
+ ITResList732 = [ITRes731|ITResList731],
+
+
+ ?line {STRes732,S732} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_Name.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList733 = [STRes732|STResList732],
+ ?line ITRes732 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_Name.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S732),
+ ITResList733 = [ITRes732|ITResList732],
+
+
+ ?line {STRes733,S733} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_NCName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList734 = [STRes733|STResList733],
+ ?line ITRes733 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_NCName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S733),
+ ITResList734 = [ITRes733|ITResList733],
+
+
+ ?line {STRes734,S734} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_ID.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList735 = [STRes734|STResList734],
+ ?line ITRes734 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_ID.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S734),
+ ITResList735 = [ITRes734|ITResList734],
+
+
+ ?line {STRes735,S735} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_IDREF.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList736 = [STRes735|STResList735],
+ ?line ITRes735 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_IDREF.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S735),
+ ITResList736 = [ITRes735|ITResList735],
+
+
+ ?line {STRes736,S736} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_IDREFS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList737 = [STRes736|STResList736],
+ ?line ITRes736 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_IDREFS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S736),
+ ITResList737 = [ITRes736|ITResList736],
+
+
+ ?line {STRes737,S737} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList738 = [STRes737|STResList737],
+ ?line ITRes737 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S737),
+ ITResList738 = [ITRes737|ITResList737],
+
+
+ ?line {STRes738,S738} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList739 = [STRes738|STResList738],
+ ?line ITRes738 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S738),
+ ITResList739 = [ITRes738|ITResList738],
+
+
+ ?line {STRes739,S739} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList740 = [STRes739|STResList739],
+ ?line ITRes739 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S739),
+ ITResList740 = [ITRes739|ITResList739],
+
+
+ ?line {STRes740,S740} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_base64Binary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList741 = [STRes740|STResList740],
+ ?line ITRes740 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_base64Binary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S740),
+ ITResList741 = [ITRes740|ITResList740],
+
+
+ ?line {STRes741,S741} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_hexBinary.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList742 = [STRes741|STResList741],
+ ?line ITRes741 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_hexBinary.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S741),
+ ITResList742 = [ITRes741|ITResList741],
+
+
+ ?line {STRes742,S742} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_float.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList743 = [STRes742|STResList742],
+ ?line ITRes742 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_float.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S742),
+ ITResList743 = [ITRes742|ITResList742],
+
+
+ ?line {STRes743,S743} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_decimal.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList744 = [STRes743|STResList743],
+ ?line ITRes743 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_decimal.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S743),
+ ITResList744 = [ITRes743|ITResList743],
+
+
+ ?line {STRes744,S744} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_integer.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList745 = [STRes744|STResList744],
+ ?line ITRes744 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_integer.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S744),
+ ITResList745 = [ITRes744|ITResList744],
+
+
+ ?line {STRes745,S745} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_nonPositiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList746 = [STRes745|STResList745],
+ ?line ITRes745 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_nonPositiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S745),
+ ITResList746 = [ITRes745|ITResList745],
+
+
+ ?line {STRes746,S746} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_negativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList747 = [STRes746|STResList746],
+ ?line ITRes746 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_negativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S746),
+ ITResList747 = [ITRes746|ITResList746],
+
+
+ ?line {STRes747,S747} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_long.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList748 = [STRes747|STResList747],
+ ?line ITRes747 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_long.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S747),
+ ITResList748 = [ITRes747|ITResList747],
+
+
+ ?line {STRes748,S748} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_int.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList749 = [STRes748|STResList748],
+ ?line ITRes748 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_int.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S748),
+ ITResList749 = [ITRes748|ITResList748],
+
+
+ ?line {STRes749,S749} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_short.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList750 = [STRes749|STResList749],
+ ?line ITRes749 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_short.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S749),
+ ITResList750 = [ITRes749|ITResList749],
+
+
+ ?line {STRes750,S750} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_byte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList751 = [STRes750|STResList750],
+ ?line ITRes750 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_byte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S750),
+ ITResList751 = [ITRes750|ITResList750],
+
+
+ ?line {STRes751,S751} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_nonNegativeInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList752 = [STRes751|STResList751],
+ ?line ITRes751 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_nonNegativeInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S751),
+ ITResList752 = [ITRes751|ITResList751],
+
+
+ ?line {STRes752,S752} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_positiveInteger.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList753 = [STRes752|STResList752],
+ ?line ITRes752 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_positiveInteger.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S752),
+ ITResList753 = [ITRes752|ITResList752],
+
+
+ ?line {STRes753,S753} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_unsignedLong.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList754 = [STRes753|STResList753],
+ ?line ITRes753 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_unsignedLong.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S753),
+ ITResList754 = [ITRes753|ITResList753],
+
+
+ ?line {STRes754,S754} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_unsignedInt.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList755 = [STRes754|STResList754],
+ ?line ITRes754 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_unsignedInt.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S754),
+ ITResList755 = [ITRes754|ITResList754],
+
+
+ ?line {STRes755,S755} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_unsignedShort.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList756 = [STRes755|STResList755],
+ ?line ITRes755 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_unsignedShort.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S755),
+ ITResList756 = [ITRes755|ITResList755],
+
+
+ ?line {STRes756,S756} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_unsignedByte.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList757 = [STRes756|STResList756],
+ ?line ITRes756 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_unsignedByte.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S756),
+ ITResList757 = [ITRes756|ITResList756],
+
+
+ ?line {STRes757,S757} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_double.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList758 = [STRes757|STResList757],
+ ?line ITRes757 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_double.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S757),
+ ITResList758 = [ITRes757|ITResList757],
+
+
+ ?line {STRes758,S758} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList759 = [STRes758|STResList758],
+ ?line ITRes758 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S758),
+ ITResList759 = [ITRes758|ITResList758],
+
+
+ ?line {STRes759,S759} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_QName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList760 = [STRes759|STResList759],
+ ?line ITRes759 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_QName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S759),
+ ITResList760 = [ITRes759|ITResList759],
+
+
+ ?line {STRes760,S760} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_NOTATION.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList761 = [STRes760|STResList760],
+ ?line ITRes760 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_NOTATION.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S760),
+ ITResList761 = [ITRes760|ITResList760],
+
+
+ ?line {STRes761,S761} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList762 = [STRes761|STResList761],
+ ?line ITRes761 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S761),
+ ITResList762 = [ITRes761|ITResList761],
+
+
+ ?line {STRes762,S762} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_dateTime.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList763 = [STRes762|STResList762],
+ ?line ITRes762 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_dateTime.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S762),
+ ITResList763 = [ITRes762|ITResList762],
+
+
+ ?line {STRes763,S763} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_time.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList764 = [STRes763|STResList763],
+ ?line ITRes763 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_time.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S763),
+ ITResList764 = [ITRes763|ITResList763],
+
+
+ ?line {STRes764,S764} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_date.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList765 = [STRes764|STResList764],
+ ?line ITRes764 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_date.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S764),
+ ITResList765 = [ITRes764|ITResList764],
+
+
+ ?line {STRes765,S765} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_gYearMonth.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList766 = [STRes765|STResList765],
+ ?line ITRes765 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_gYearMonth.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S765),
+ ITResList766 = [ITRes765|ITResList765],
+
+
+ ?line {STRes766,S766} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_gYear.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList767 = [STRes766|STResList766],
+ ?line ITRes766 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_gYear.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S766),
+ ITResList767 = [ITRes766|ITResList766],
+
+
+ ?line {STRes767,S767} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_gMonthDay.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList768 = [STRes767|STResList767],
+ ?line ITRes767 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_gMonthDay.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S767),
+ ITResList768 = [ITRes767|ITResList767],
+
+
+ ?line {STRes768,S768} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_gDay.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList769 = [STRes768|STResList768],
+ ?line ITRes768 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_gDay.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S768),
+ ITResList769 = [ITRes768|ITResList768],
+
+
+ ?line {STRes769,S769} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_gMonth.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList770 = [STRes769|STResList769],
+ ?line ITRes769 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_anyURI_gMonth.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S769),
+ ITResList770 = [ITRes769|ITResList769],
+
+
+ ?line {STRes770,S770} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList771 = [STRes770|STResList770],
+ ?line ITRes770 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S770),
+ ITResList771 = [ITRes770|ITResList770],
+
+
+ ?line {STRes771,S771} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList772 = [STRes771|STResList771],
+ ?line ITRes771 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S771),
+ ITResList772 = [ITRes771|ITResList771],
+
+
+ ?line {STRes772,S772} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList773 = [STRes772|STResList772],
+ ?line ITRes772 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S772),
+ ITResList773 = [ITRes772|ITResList772],
+
+
+ ?line {STRes773,S773} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_language.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList774 = [STRes773|STResList773],
+ ?line ITRes773 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_language.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S773),
+ ITResList774 = [ITRes773|ITResList773],
+
+
+ ?line {STRes774,S774} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_Name.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList775 = [STRes774|STResList774],
+ ?line ITRes774 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_Name.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S774),
+ ITResList775 = [ITRes774|ITResList774],
+
+
+ ?line {STRes775,S775} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_NCName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList776 = [STRes775|STResList775],
+ ?line ITRes775 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_NCName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S775),
+ ITResList776 = [ITRes775|ITResList775],
+
+
+ ?line {STRes776,S776} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_ID.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList777 = [STRes776|STResList776],
+ ?line ITRes776 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_ID.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S776),
+ ITResList777 = [ITRes776|ITResList776],
+
+
+ ?line {STRes777,S777} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_IDREF.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList778 = [STRes777|STResList777],
+ ?line ITRes777 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_IDREF.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S777),
+ ITResList778 = [ITRes777|ITResList777],
+
+
+ ?line {STRes778,S778} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_IDREFS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList779 = [STRes778|STResList778],
+ ?line ITRes778 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_IDREFS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S778),
+ ITResList779 = [ITRes778|ITResList778],
+
+
+ ?line {STRes779,S779} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList780 = [STRes779|STResList779],
+ ?line ITRes779 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S779),
+ ITResList780 = [ITRes779|ITResList779],
+
+
+ ?line {STRes780,S780} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList781 = [STRes780|STResList780],
+ ?line ITRes780 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S780),
+ ITResList781 = [ITRes780|ITResList780],
+
+
+ ?line {STRes781,S781} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList782 = [STRes781|STResList781],
+ ?line ITRes781 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S781),
+ ITResList782 = [ITRes781|ITResList781],
+
+
+ ?line {STRes782,S782} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList783 = [STRes782|STResList782],
+ ?line ITRes782 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S782),
+ ITResList783 = [ITRes782|ITResList782],
+
+
+ ?line {STRes783,S783} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_QName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList784 = [STRes783|STResList783],
+ ?line ITRes783 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_QName.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S783),
+ ITResList784 = [ITRes783|ITResList783],
+
+
+ ?line {STRes784,S784} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList785 = [STRes784|STResList784],
+ ?line ITRes784 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_QName_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S784),
+ ITResList785 = [ITRes784|ITResList784],
+
+
+ ?line {STRes785,S785} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList786 = [STRes785|STResList785],
+ ?line ITRes785 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S785),
+ ITResList786 = [ITRes785|ITResList785],
+
+
+ ?line {STRes786,S786} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList787 = [STRes786|STResList786],
+ ?line ITRes786 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S786),
+ ITResList787 = [ITRes786|ITResList786],
+
+
+ ?line {STRes787,S787} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList788 = [STRes787|STResList787],
+ ?line ITRes787 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S787),
+ ITResList788 = [ITRes787|ITResList787],
+
+
+ ?line {STRes788,S788} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_language.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList789 = [STRes788|STResList788],
+ ?line ITRes788 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_language.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S788),
+ ITResList789 = [ITRes788|ITResList788],
+
+
+ ?line {STRes789,S789} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_Name.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList790 = [STRes789|STResList789],
+ ?line ITRes789 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_Name.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S789),
+ ITResList790 = [ITRes789|ITResList789],
+
+
+ ?line {STRes790,S790} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_NCName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList791 = [STRes790|STResList790],
+ ?line ITRes790 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_NCName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S790),
+ ITResList791 = [ITRes790|ITResList790],
+
+
+ ?line {STRes791,S791} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_ID.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList792 = [STRes791|STResList791],
+ ?line ITRes791 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_ID.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S791),
+ ITResList792 = [ITRes791|ITResList791],
+
+
+ ?line {STRes792,S792} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_IDREF.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList793 = [STRes792|STResList792],
+ ?line ITRes792 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_IDREF.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S792),
+ ITResList793 = [ITRes792|ITResList792],
+
+
+ ?line {STRes793,S793} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_IDREFS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList794 = [STRes793|STResList793],
+ ?line ITRes793 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_IDREFS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S793),
+ ITResList794 = [ITRes793|ITResList793],
+
+
+ ?line {STRes794,S794} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList795 = [STRes794|STResList794],
+ ?line ITRes794 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S794),
+ ITResList795 = [ITRes794|ITResList794],
+
+
+ ?line {STRes795,S795} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList796 = [STRes795|STResList795],
+ ?line ITRes795 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S795),
+ ITResList796 = [ITRes795|ITResList795],
+
+
+ ?line {STRes796,S796} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_boolean.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList797 = [STRes796|STResList796],
+ ?line ITRes796 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_boolean.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S796),
+ ITResList797 = [ITRes796|ITResList796],
+
+
+ ?line {STRes797,S797} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList798 = [STRes797|STResList797],
+ ?line ITRes797 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S797),
+ ITResList798 = [ITRes797|ITResList797],
+
+
+ ?line {STRes798,S798} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_NOTATION.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList799 = [STRes798|STResList798],
+ ?line ITRes798 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_NOTATION.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S798),
+ ITResList799 = [ITRes798|ITResList798],
+
+
+ ?line {STRes799,S799} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList800 = [STRes799|STResList799],
+ ?line ITRes799 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_NOTATION_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S799),
+ ITResList800 = [ITRes799|ITResList799],
+
+
+ ?line {STRes800,S800} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList801 = [STRes800|STResList800],
+ ?line ITRes800 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S800),
+ ITResList801 = [ITRes800|ITResList800],
+
+
+ ?line {STRes801,S801} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList802 = [STRes801|STResList801],
+ ?line ITRes801 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S801),
+ ITResList802 = [ITRes801|ITResList801],
+
+
+ ?line {STRes802,S802} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList803 = [STRes802|STResList802],
+ ?line ITRes802 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S802),
+ ITResList803 = [ITRes802|ITResList802],
+
+
+ ?line {STRes803,S803} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_Name.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList804 = [STRes803|STResList803],
+ ?line ITRes803 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_Name.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S803),
+ ITResList804 = [ITRes803|ITResList803],
+
+
+ ?line {STRes804,S804} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_NCName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList805 = [STRes804|STResList804],
+ ?line ITRes804 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_NCName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S804),
+ ITResList805 = [ITRes804|ITResList804],
+
+
+ ?line {STRes805,S805} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_ID.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList806 = [STRes805|STResList805],
+ ?line ITRes805 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_ID.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S805),
+ ITResList806 = [ITRes805|ITResList805],
+
+
+ ?line {STRes806,S806} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_IDREF.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList807 = [STRes806|STResList806],
+ ?line ITRes806 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_IDREF.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S806),
+ ITResList807 = [ITRes806|ITResList806],
+
+
+ ?line {STRes807,S807} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_IDREFS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList808 = [STRes807|STResList807],
+ ?line ITRes807 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_IDREFS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S807),
+ ITResList808 = [ITRes807|ITResList807],
+
+
+ ?line {STRes808,S808} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList809 = [STRes808|STResList808],
+ ?line ITRes808 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S808),
+ ITResList809 = [ITRes808|ITResList808],
+
+
+ ?line {STRes809,S809} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList810 = [STRes809|STResList809],
+ ?line ITRes809 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S809),
+ ITResList810 = [ITRes809|ITResList809],
+
+
+ ?line {STRes810,S810} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList811 = [STRes810|STResList810],
+ ?line ITRes810 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S810),
+ ITResList811 = [ITRes810|ITResList810],
+
+
+ ?line {STRes811,S811} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_QName.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList812 = [STRes811|STResList811],
+ ?line ITRes811 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_QName.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S811),
+ ITResList812 = [ITRes811|ITResList811],
+
+
+ ?line {STRes812,S812} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_NOTATION.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList813 = [STRes812|STResList812],
+ ?line ITRes812 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_NOTATION.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S812),
+ ITResList813 = [ITRes812|ITResList812],
+
+
+ ?line {STRes813,S813} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList814 = [STRes813|STResList813],
+ ?line ITRes813 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S813),
+ ITResList814 = [ITRes813|ITResList813],
+
+
+ ?line {STRes814,S814} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_dateTime.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList815 = [STRes814|STResList814],
+ ?line ITRes814 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_dateTime.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S814),
+ ITResList815 = [ITRes814|ITResList814],
+
+
+ ?line {STRes815,S815} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_time.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList816 = [STRes815|STResList815],
+ ?line ITRes815 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_time.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S815),
+ ITResList816 = [ITRes815|ITResList815],
+
+
+ ?line {STRes816,S816} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_date.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList817 = [STRes816|STResList816],
+ ?line ITRes816 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_date.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S816),
+ ITResList817 = [ITRes816|ITResList816],
+
+
+ ?line {STRes817,S817} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_gYearMonth.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList818 = [STRes817|STResList817],
+ ?line ITRes817 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_gYearMonth.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S817),
+ ITResList818 = [ITRes817|ITResList817],
+
+
+ ?line {STRes818,S818} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_gYear.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList819 = [STRes818|STResList818],
+ ?line ITRes818 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_gYear.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S818),
+ ITResList819 = [ITRes818|ITResList818],
+
+
+ ?line {STRes819,S819} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_gMonthDay.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList820 = [STRes819|STResList819],
+ ?line ITRes819 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_gMonthDay.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S819),
+ ITResList820 = [ITRes819|ITResList819],
+
+
+ ?line {STRes820,S820} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_gDay.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList821 = [STRes820|STResList820],
+ ?line ITRes820 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_gDay.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S820),
+ ITResList821 = [ITRes820|ITResList820],
+
+
+ ?line {STRes821,S821} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_gMonth.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList822 = [STRes821|STResList821],
+ ?line ITRes821 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_duration_gMonth.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S821),
+ ITResList822 = [ITRes821|ITResList821],
+
+
+ ?line {STRes822,S822} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_dateTime_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList823 = [STRes822|STResList822],
+ ?line ITRes822 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_dateTime_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S822),
+ ITResList823 = [ITRes822|ITResList822],
+
+
+ ?line {STRes823,S823} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_dateTime_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList824 = [STRes823|STResList823],
+ ?line ITRes823 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_dateTime_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S823),
+ ITResList824 = [ITRes823|ITResList823],
+
+
+ ?line {STRes824,S824} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_dateTime_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList825 = [STRes824|STResList824],
+ ?line ITRes824 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_dateTime_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S824),
+ ITResList825 = [ITRes824|ITResList824],
+
+
+ ?line {STRes825,S825} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_dateTime_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList826 = [STRes825|STResList825],
+ ?line ITRes825 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_dateTime_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S825),
+ ITResList826 = [ITRes825|ITResList825],
+
+
+ ?line {STRes826,S826} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_dateTime_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList827 = [STRes826|STResList826],
+ ?line ITRes826 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_dateTime_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S826),
+ ITResList827 = [ITRes826|ITResList826],
+
+
+ ?line {STRes827,S827} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_dateTime_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList828 = [STRes827|STResList827],
+ ?line ITRes827 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_dateTime_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S827),
+ ITResList828 = [ITRes827|ITResList827],
+
+
+ ?line {STRes828,S828} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_dateTime_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList829 = [STRes828|STResList828],
+ ?line ITRes828 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_dateTime_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S828),
+ ITResList829 = [ITRes828|ITResList828],
+
+
+ ?line {STRes829,S829} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_dateTime_dateTime.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList830 = [STRes829|STResList829],
+ ?line ITRes829 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_dateTime_dateTime.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S829),
+ ITResList830 = [ITRes829|ITResList829],
+
+
+ ?line {STRes830,S830} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_dateTime_date.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList831 = [STRes830|STResList830],
+ ?line ITRes830 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_dateTime_date.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S830),
+ ITResList831 = [ITRes830|ITResList830],
+
+
+ ?line {STRes831,S831} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_time_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList832 = [STRes831|STResList831],
+ ?line ITRes831 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_time_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S831),
+ ITResList832 = [ITRes831|ITResList831],
+
+
+ ?line {STRes832,S832} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_time_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList833 = [STRes832|STResList832],
+ ?line ITRes832 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_time_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S832),
+ ITResList833 = [ITRes832|ITResList832],
+
+
+ ?line {STRes833,S833} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_time_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList834 = [STRes833|STResList833],
+ ?line ITRes833 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_time_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S833),
+ ITResList834 = [ITRes833|ITResList833],
+
+
+ ?line {STRes834,S834} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_time_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList835 = [STRes834|STResList834],
+ ?line ITRes834 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_time_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S834),
+ ITResList835 = [ITRes834|ITResList834],
+
+
+ ?line {STRes835,S835} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_time_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList836 = [STRes835|STResList835],
+ ?line ITRes835 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_time_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S835),
+ ITResList836 = [ITRes835|ITResList835],
+
+
+ ?line {STRes836,S836} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_time_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList837 = [STRes836|STResList836],
+ ?line ITRes836 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_time_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S836),
+ ITResList837 = [ITRes836|ITResList836],
+
+
+ ?line {STRes837,S837} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_time_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList838 = [STRes837|STResList837],
+ ?line ITRes837 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_time_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S837),
+ ITResList838 = [ITRes837|ITResList837],
+
+
+ ?line {STRes838,S838} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_time_time.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList839 = [STRes838|STResList838],
+ ?line ITRes838 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_time_time.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S838),
+ ITResList839 = [ITRes838|ITResList838],
+
+
+ ?line {STRes839,S839} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_date_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList840 = [STRes839|STResList839],
+ ?line ITRes839 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_date_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S839),
+ ITResList840 = [ITRes839|ITResList839],
+
+
+ ?line {STRes840,S840} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_date_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList841 = [STRes840|STResList840],
+ ?line ITRes840 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_date_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S840),
+ ITResList841 = [ITRes840|ITResList840],
+
+
+ ?line {STRes841,S841} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_date_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList842 = [STRes841|STResList841],
+ ?line ITRes841 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_date_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S841),
+ ITResList842 = [ITRes841|ITResList841],
+
+
+ ?line {STRes842,S842} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_date_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList843 = [STRes842|STResList842],
+ ?line ITRes842 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_date_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S842),
+ ITResList843 = [ITRes842|ITResList842],
+
+
+ ?line {STRes843,S843} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_date_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList844 = [STRes843|STResList843],
+ ?line ITRes843 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_date_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S843),
+ ITResList844 = [ITRes843|ITResList843],
+
+
+ ?line {STRes844,S844} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_date_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList845 = [STRes844|STResList844],
+ ?line ITRes844 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_date_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S844),
+ ITResList845 = [ITRes844|ITResList844],
+
+
+ ?line {STRes845,S845} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_date_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList846 = [STRes845|STResList845],
+ ?line ITRes845 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_date_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S845),
+ ITResList846 = [ITRes845|ITResList845],
+
+
+ ?line {STRes846,S846} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_date_dateTime.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList847 = [STRes846|STResList846],
+ ?line ITRes846 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_date_dateTime.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S846),
+ ITResList847 = [ITRes846|ITResList846],
+
+
+ ?line {STRes847,S847} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_date_date.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList848 = [STRes847|STResList847],
+ ?line ITRes847 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_date_date.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S847),
+ ITResList848 = [ITRes847|ITResList847],
+
+
+ ?line {STRes848,S848} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYearMonth_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList849 = [STRes848|STResList848],
+ ?line ITRes848 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYearMonth_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S848),
+ ITResList849 = [ITRes848|ITResList848],
+
+
+ ?line {STRes849,S849} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYearMonth_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList850 = [STRes849|STResList849],
+ ?line ITRes849 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYearMonth_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S849),
+ ITResList850 = [ITRes849|ITResList849],
+
+
+ ?line {STRes850,S850} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYearMonth_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList851 = [STRes850|STResList850],
+ ?line ITRes850 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYearMonth_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S850),
+ ITResList851 = [ITRes850|ITResList850],
+
+
+ ?line {STRes851,S851} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYearMonth_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList852 = [STRes851|STResList851],
+ ?line ITRes851 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYearMonth_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S851),
+ ITResList852 = [ITRes851|ITResList851],
+
+
+ ?line {STRes852,S852} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYearMonth_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList853 = [STRes852|STResList852],
+ ?line ITRes852 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYearMonth_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S852),
+ ITResList853 = [ITRes852|ITResList852],
+
+
+ ?line {STRes853,S853} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYearMonth_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList854 = [STRes853|STResList853],
+ ?line ITRes853 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYearMonth_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S853),
+ ITResList854 = [ITRes853|ITResList853],
+
+
+ ?line {STRes854,S854} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYearMonth_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList855 = [STRes854|STResList854],
+ ?line ITRes854 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYearMonth_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S854),
+ ITResList855 = [ITRes854|ITResList854],
+
+
+ ?line {STRes855,S855} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYearMonth_gYearMonth.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList856 = [STRes855|STResList855],
+ ?line ITRes855 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYearMonth_gYearMonth.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S855),
+ ITResList856 = [ITRes855|ITResList855],
+
+
+ ?line {STRes856,S856} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYear_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList857 = [STRes856|STResList856],
+ ?line ITRes856 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYear_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S856),
+ ITResList857 = [ITRes856|ITResList856],
+
+
+ ?line {STRes857,S857} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYear_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList858 = [STRes857|STResList857],
+ ?line ITRes857 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYear_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S857),
+ ITResList858 = [ITRes857|ITResList857],
+
+
+ ?line {STRes858,S858} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYear_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList859 = [STRes858|STResList858],
+ ?line ITRes858 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYear_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S858),
+ ITResList859 = [ITRes858|ITResList858],
+
+
+ ?line {STRes859,S859} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYear_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList860 = [STRes859|STResList859],
+ ?line ITRes859 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYear_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S859),
+ ITResList860 = [ITRes859|ITResList859],
+
+
+ ?line {STRes860,S860} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYear_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList861 = [STRes860|STResList860],
+ ?line ITRes860 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYear_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S860),
+ ITResList861 = [ITRes860|ITResList860],
+
+
+ ?line {STRes861,S861} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYear_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList862 = [STRes861|STResList861],
+ ?line ITRes861 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYear_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S861),
+ ITResList862 = [ITRes861|ITResList861],
+
+
+ ?line {STRes862,S862} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYear_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList863 = [STRes862|STResList862],
+ ?line ITRes862 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYear_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S862),
+ ITResList863 = [ITRes862|ITResList862],
+
+
+ ?line {STRes863,S863} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYear_gYear.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList864 = [STRes863|STResList863],
+ ?line ITRes863 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gYear_gYear.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S863),
+ ITResList864 = [ITRes863|ITResList863],
+
+
+ ?line {STRes864,S864} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonthDay_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList865 = [STRes864|STResList864],
+ ?line ITRes864 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonthDay_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S864),
+ ITResList865 = [ITRes864|ITResList864],
+
+
+ ?line {STRes865,S865} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonthDay_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList866 = [STRes865|STResList865],
+ ?line ITRes865 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonthDay_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S865),
+ ITResList866 = [ITRes865|ITResList865],
+
+
+ ?line {STRes866,S866} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonthDay_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList867 = [STRes866|STResList866],
+ ?line ITRes866 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonthDay_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S866),
+ ITResList867 = [ITRes866|ITResList866],
+
+
+ ?line {STRes867,S867} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonthDay_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList868 = [STRes867|STResList867],
+ ?line ITRes867 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonthDay_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S867),
+ ITResList868 = [ITRes867|ITResList867],
+
+
+ ?line {STRes868,S868} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonthDay_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList869 = [STRes868|STResList868],
+ ?line ITRes868 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonthDay_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S868),
+ ITResList869 = [ITRes868|ITResList868],
+
+
+ ?line {STRes869,S869} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonthDay_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList870 = [STRes869|STResList869],
+ ?line ITRes869 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonthDay_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S869),
+ ITResList870 = [ITRes869|ITResList869],
+
+
+ ?line {STRes870,S870} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonthDay_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList871 = [STRes870|STResList870],
+ ?line ITRes870 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonthDay_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S870),
+ ITResList871 = [ITRes870|ITResList870],
+
+
+ ?line {STRes871,S871} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonthDay_gMonthDay.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList872 = [STRes871|STResList871],
+ ?line ITRes871 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonthDay_gMonthDay.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S871),
+ ITResList872 = [ITRes871|ITResList871],
+
+
+ ?line {STRes872,S872} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gDay_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList873 = [STRes872|STResList872],
+ ?line ITRes872 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gDay_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S872),
+ ITResList873 = [ITRes872|ITResList872],
+
+
+ ?line {STRes873,S873} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gDay_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList874 = [STRes873|STResList873],
+ ?line ITRes873 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gDay_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S873),
+ ITResList874 = [ITRes873|ITResList873],
+
+
+ ?line {STRes874,S874} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gDay_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList875 = [STRes874|STResList874],
+ ?line ITRes874 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gDay_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S874),
+ ITResList875 = [ITRes874|ITResList874],
+
+
+ ?line {STRes875,S875} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gDay_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList876 = [STRes875|STResList875],
+ ?line ITRes875 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gDay_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S875),
+ ITResList876 = [ITRes875|ITResList875],
+
+
+ ?line {STRes876,S876} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gDay_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList877 = [STRes876|STResList876],
+ ?line ITRes876 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gDay_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S876),
+ ITResList877 = [ITRes876|ITResList876],
+
+
+ ?line {STRes877,S877} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gDay_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList878 = [STRes877|STResList877],
+ ?line ITRes877 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gDay_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S877),
+ ITResList878 = [ITRes877|ITResList877],
+
+
+ ?line {STRes878,S878} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gDay_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList879 = [STRes878|STResList878],
+ ?line ITRes878 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gDay_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S878),
+ ITResList879 = [ITRes878|ITResList878],
+
+
+ ?line {STRes879,S879} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gDay_gDay.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList880 = [STRes879|STResList879],
+ ?line ITRes879 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gDay_gDay.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S879),
+ ITResList880 = [ITRes879|ITResList879],
+
+
+ ?line {STRes880,S880} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonth_string.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList881 = [STRes880|STResList880],
+ ?line ITRes880 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonth_string.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S880),
+ ITResList881 = [ITRes880|ITResList880],
+
+
+ ?line {STRes881,S881} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonth_normalizedString.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList882 = [STRes881|STResList881],
+ ?line ITRes881 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonth_normalizedString.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S881),
+ ITResList882 = [ITRes881|ITResList881],
+
+
+ ?line {STRes882,S882} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonth_token.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList883 = [STRes882|STResList882],
+ ?line ITRes882 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonth_token.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S882),
+ ITResList883 = [ITRes882|ITResList882],
+
+
+ ?line {STRes883,S883} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonth_NMTOKEN.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList884 = [STRes883|STResList883],
+ ?line ITRes883 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonth_NMTOKEN.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S883),
+ ITResList884 = [ITRes883|ITResList883],
+
+
+ ?line {STRes884,S884} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonth_NMTOKENS.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList885 = [STRes884|STResList884],
+ ?line ITRes884 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonth_NMTOKENS.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S884),
+ ITResList885 = [ITRes884|ITResList884],
+
+
+ ?line {STRes885,S885} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonth_anyURI.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList886 = [STRes885|STResList885],
+ ?line ITRes885 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonth_anyURI.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S885),
+ ITResList886 = [ITRes885|ITResList885],
+
+
+ ?line {STRes886,S886} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonth_duration.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList887 = [STRes886|STResList886],
+ ?line ITRes886 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonth_duration.xml','./msxsdtest/identityConstraint/idc_datatypes',invalid,S886),
+ ITResList887 = [ITRes886|ITResList886],
+
+
+ ?line {STRes887,S887} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonth_gMonth.xsd','./msxsdtest/identityConstraint/idc_datatypes',valid),
+ STResList888 = [STRes887|STResList887],
+ ?line ITRes887 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idc_datatypes/idc_gMonth_gMonth.xml','./msxsdtest/identityConstraint/idc_datatypes',valid,S887),
+ ITResList888 = [ITRes887|ITResList887],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList888,ITResList888).
+
+%% Identity-constraint Definition Schema Component.
+%% Identity-constraint Validation Rules.
+%% Selector identity-constraint xpath bnf.
+%% Field identity-constraint xpath bnf.
+%% XPath validation.
+%% Bug Regressions
+
+id(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA001.xsd','./msxsdtest/identityConstraint',valid),
+ STResList1 = [STRes0|STResList0],
+
+
+ ?line {STRes1,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA002.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList2 = [STRes1|STResList1],
+
+
+ ?line {STRes2,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA003.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList3 = [STRes2|STResList2],
+
+
+ ?line {STRes3,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA004.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList4 = [STRes3|STResList3],
+
+
+ ?line {STRes4,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA005.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList5 = [STRes4|STResList4],
+
+
+ ?line {STRes5,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA006.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList6 = [STRes5|STResList5],
+
+
+ ?line {STRes6,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA007.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList7 = [STRes6|STResList6],
+
+
+ ?line {STRes7,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA008.xsd','./msxsdtest/identityConstraint',valid),
+ STResList8 = [STRes7|STResList7],
+
+
+ ?line {STRes8,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA009.xsd','./msxsdtest/identityConstraint',valid),
+ STResList9 = [STRes8|STResList8],
+
+
+ ?line {STRes9,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA010.xsd','./msxsdtest/identityConstraint',valid),
+ STResList10 = [STRes9|STResList9],
+
+
+ ?line {STRes10,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA011.xsd','./msxsdtest/identityConstraint',valid),
+ STResList11 = [STRes10|STResList10],
+
+
+ ?line {STRes11,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA012.xsd','./msxsdtest/identityConstraint',valid),
+ STResList12 = [STRes11|STResList11],
+
+
+ ?line {STRes12,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA013.xsd','./msxsdtest/identityConstraint',valid),
+ STResList13 = [STRes12|STResList12],
+
+
+ ?line {STRes13,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA014.xsd','./msxsdtest/identityConstraint',valid),
+ STResList14 = [STRes13|STResList13],
+
+
+ ?line {STRes14,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA015.xsd','./msxsdtest/identityConstraint',valid),
+ STResList15 = [STRes14|STResList14],
+
+
+ ?line {STRes15,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA016.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList16 = [STRes15|STResList15],
+
+
+ ?line {STRes16,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA017.xsd','./msxsdtest/identityConstraint',valid),
+ STResList17 = [STRes16|STResList16],
+
+
+ ?line {STRes17,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA018.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList18 = [STRes17|STResList17],
+
+
+ ?line {STRes18,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA019.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList19 = [STRes18|STResList18],
+
+
+ ?line {STRes19,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA020.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList20 = [STRes19|STResList19],
+
+
+ ?line {STRes20,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA021.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList21 = [STRes20|STResList20],
+
+
+ ?line {STRes21,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA022.xsd','./msxsdtest/identityConstraint',valid),
+ STResList22 = [STRes21|STResList21],
+
+
+ ?line {STRes22,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA023.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList23 = [STRes22|STResList22],
+
+
+ ?line {STRes23,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA024.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList24 = [STRes23|STResList23],
+
+
+ ?line {STRes24,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA025.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList25 = [STRes24|STResList24],
+
+
+ ?line {STRes25,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA026.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList26 = [STRes25|STResList25],
+
+
+ ?line {STRes26,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA027.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList27 = [STRes26|STResList26],
+
+
+ ?line {STRes27,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA028.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList28 = [STRes27|STResList27],
+
+
+ ?line {STRes28,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA029.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList29 = [STRes28|STResList28],
+
+
+ ?line {STRes29,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA030.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList30 = [STRes29|STResList29],
+
+
+ ?line {STRes30,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA031.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList31 = [STRes30|STResList30],
+
+
+ ?line {STRes31,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA032.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList32 = [STRes31|STResList31],
+
+
+ ?line {STRes32,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA033.xsd','./msxsdtest/identityConstraint',valid),
+ STResList33 = [STRes32|STResList32],
+
+
+ ?line {STRes33,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA034.xsd','./msxsdtest/identityConstraint',valid),
+ STResList34 = [STRes33|STResList33],
+
+
+ ?line {STRes34,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA035.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList35 = [STRes34|STResList34],
+
+
+ ?line {STRes35,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA036.xsd','./msxsdtest/identityConstraint',valid),
+ STResList36 = [STRes35|STResList35],
+
+
+ ?line {STRes36,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA037.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList37 = [STRes36|STResList36],
+
+
+ ?line {STRes37,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA038.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList38 = [STRes37|STResList37],
+
+
+ ?line {STRes38,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA039.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList39 = [STRes38|STResList38],
+
+
+ ?line {STRes39,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA040.xsd','./msxsdtest/identityConstraint',valid),
+ STResList40 = [STRes39|STResList39],
+
+
+ ?line {STRes40,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA041.xsd','./msxsdtest/identityConstraint',valid),
+ STResList41 = [STRes40|STResList40],
+
+
+ ?line {STRes41,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA042.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList42 = [STRes41|STResList41],
+
+
+ ?line {STRes42,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA043.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList43 = [STRes42|STResList42],
+
+
+ ?line {STRes43,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA044.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList44 = [STRes43|STResList43],
+
+
+ ?line {STRes44,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA045.xsd','./msxsdtest/identityConstraint',valid),
+ STResList45 = [STRes44|STResList44],
+
+
+ ?line {STRes45,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA046.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList46 = [STRes45|STResList45],
+
+
+ ?line {STRes46,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA047.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList47 = [STRes46|STResList46],
+
+
+ ?line {STRes47,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA048.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList48 = [STRes47|STResList47],
+
+
+ ?line {STRes48,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA049.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList49 = [STRes48|STResList48],
+
+
+ ?line {STRes49,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA050.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList50 = [STRes49|STResList49],
+
+
+ ?line {STRes50,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA051.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList51 = [STRes50|STResList50],
+
+
+ ?line {STRes51,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA052.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList52 = [STRes51|STResList51],
+
+
+ ?line {STRes52,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA053.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList53 = [STRes52|STResList52],
+
+
+ ?line {STRes53,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA054.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList54 = [STRes53|STResList53],
+
+
+ ?line {STRes54,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA055.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList55 = [STRes54|STResList54],
+
+
+ ?line {STRes55,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA056.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList56 = [STRes55|STResList55],
+
+
+ ?line {STRes56,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA057.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList57 = [STRes56|STResList56],
+
+
+ ?line {STRes57,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA058.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList58 = [STRes57|STResList57],
+
+
+ ?line {STRes58,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA059.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList59 = [STRes58|STResList58],
+
+
+ ?line {STRes59,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idA060.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList60 = [STRes59|STResList59],
+
+
+ ?line {STRes60,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB001.xsd','./msxsdtest/identityConstraint',valid),
+ STResList61 = [STRes60|STResList60],
+
+
+ ?line {STRes61,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB002.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList62 = [STRes61|STResList61],
+
+
+ ?line {STRes62,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB003.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList63 = [STRes62|STResList62],
+
+
+ ?line {STRes63,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB004.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList64 = [STRes63|STResList63],
+
+
+ ?line {STRes64,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB005.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList65 = [STRes64|STResList64],
+
+
+ ?line {STRes65,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB006.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList66 = [STRes65|STResList65],
+
+
+ ?line {STRes66,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB007.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList67 = [STRes66|STResList66],
+
+
+ ?line {STRes67,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB008.xsd','./msxsdtest/identityConstraint',valid),
+ STResList68 = [STRes67|STResList67],
+
+
+ ?line {STRes68,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB009.xsd','./msxsdtest/identityConstraint',valid),
+ STResList69 = [STRes68|STResList68],
+
+
+ ?line {STRes69,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB010.xsd','./msxsdtest/identityConstraint',valid),
+ STResList70 = [STRes69|STResList69],
+
+
+ ?line {STRes70,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB011.xsd','./msxsdtest/identityConstraint',valid),
+ STResList71 = [STRes70|STResList70],
+
+
+ ?line {STRes71,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB012.xsd','./msxsdtest/identityConstraint',valid),
+ STResList72 = [STRes71|STResList71],
+
+
+ ?line {STRes72,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB013.xsd','./msxsdtest/identityConstraint',valid),
+ STResList73 = [STRes72|STResList72],
+
+
+ ?line {STRes73,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB014.xsd','./msxsdtest/identityConstraint',valid),
+ STResList74 = [STRes73|STResList73],
+
+
+ ?line {STRes74,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB015.xsd','./msxsdtest/identityConstraint',valid),
+ STResList75 = [STRes74|STResList74],
+
+
+ ?line {STRes75,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB016.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList76 = [STRes75|STResList75],
+
+
+ ?line {STRes76,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB017.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList77 = [STRes76|STResList76],
+
+
+ ?line {STRes77,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB018.xsd','./msxsdtest/identityConstraint',valid),
+ STResList78 = [STRes77|STResList77],
+
+
+ ?line {STRes78,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB019.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList79 = [STRes78|STResList78],
+
+
+ ?line {STRes79,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB020.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList80 = [STRes79|STResList79],
+
+
+ ?line {STRes80,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB021.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList81 = [STRes80|STResList80],
+
+
+ ?line {STRes81,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB022.xsd','./msxsdtest/identityConstraint',valid),
+ STResList82 = [STRes81|STResList81],
+
+
+ ?line {STRes82,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB023.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList83 = [STRes82|STResList82],
+
+
+ ?line {STRes83,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB024.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList84 = [STRes83|STResList83],
+
+
+ ?line {STRes84,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB025.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList85 = [STRes84|STResList84],
+
+
+ ?line {STRes85,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB026.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList86 = [STRes85|STResList85],
+
+
+ ?line {STRes86,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB027.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList87 = [STRes86|STResList86],
+
+
+ ?line {STRes87,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB028.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList88 = [STRes87|STResList87],
+
+
+ ?line {STRes88,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB029.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList89 = [STRes88|STResList88],
+
+
+ ?line {STRes89,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB030.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList90 = [STRes89|STResList89],
+
+
+ ?line {STRes90,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB031.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList91 = [STRes90|STResList90],
+
+
+ ?line {STRes91,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB032.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList92 = [STRes91|STResList91],
+
+
+ ?line {STRes92,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB033.xsd','./msxsdtest/identityConstraint',valid),
+ STResList93 = [STRes92|STResList92],
+
+
+ ?line {STRes93,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB034.xsd','./msxsdtest/identityConstraint',valid),
+ STResList94 = [STRes93|STResList93],
+
+
+ ?line {STRes94,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB035.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList95 = [STRes94|STResList94],
+
+
+ ?line {STRes95,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB036.xsd','./msxsdtest/identityConstraint',valid),
+ STResList96 = [STRes95|STResList95],
+
+
+ ?line {STRes96,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB037.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList97 = [STRes96|STResList96],
+
+
+ ?line {STRes97,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB038.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList98 = [STRes97|STResList97],
+
+
+ ?line {STRes98,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB039.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList99 = [STRes98|STResList98],
+
+
+ ?line {STRes99,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB040.xsd','./msxsdtest/identityConstraint',valid),
+ STResList100 = [STRes99|STResList99],
+
+
+ ?line {STRes100,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB041.xsd','./msxsdtest/identityConstraint',valid),
+ STResList101 = [STRes100|STResList100],
+
+
+ ?line {STRes101,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB042.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList102 = [STRes101|STResList101],
+
+
+ ?line {STRes102,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB043.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList103 = [STRes102|STResList102],
+
+
+ ?line {STRes103,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB044.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList104 = [STRes103|STResList103],
+
+
+ ?line {STRes104,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB045.xsd','./msxsdtest/identityConstraint',valid),
+ STResList105 = [STRes104|STResList104],
+
+
+ ?line {STRes105,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB046.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList106 = [STRes105|STResList105],
+
+
+ ?line {STRes106,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB047.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList107 = [STRes106|STResList106],
+
+
+ ?line {STRes107,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB048.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList108 = [STRes107|STResList107],
+
+
+ ?line {STRes108,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB049.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList109 = [STRes108|STResList108],
+
+
+ ?line {STRes109,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB050.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList110 = [STRes109|STResList109],
+
+
+ ?line {STRes110,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB051.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList111 = [STRes110|STResList110],
+
+
+ ?line {STRes111,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB052.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList112 = [STRes111|STResList111],
+
+
+ ?line {STRes112,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB053.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList113 = [STRes112|STResList112],
+
+
+ ?line {STRes113,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB054.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList114 = [STRes113|STResList113],
+
+
+ ?line {STRes114,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB055.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList115 = [STRes114|STResList114],
+
+
+ ?line {STRes115,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB056.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList116 = [STRes115|STResList115],
+
+
+ ?line {STRes116,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB057.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList117 = [STRes116|STResList116],
+
+
+ ?line {STRes117,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB058.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList118 = [STRes117|STResList117],
+
+
+ ?line {STRes118,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB059.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList119 = [STRes118|STResList118],
+
+
+ ?line {STRes119,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idB060.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList120 = [STRes119|STResList119],
+
+
+ ?line {STRes120,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC001.xsd','./msxsdtest/identityConstraint',valid),
+ STResList121 = [STRes120|STResList120],
+
+
+ ?line {STRes121,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC002.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList122 = [STRes121|STResList121],
+
+
+ ?line {STRes122,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC003.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList123 = [STRes122|STResList122],
+
+
+ ?line {STRes123,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC004.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList124 = [STRes123|STResList123],
+
+
+ ?line {STRes124,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC005.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList125 = [STRes124|STResList124],
+
+
+ ?line {STRes125,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC006.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList126 = [STRes125|STResList125],
+
+
+ ?line {STRes126,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC007.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList127 = [STRes126|STResList126],
+
+
+ ?line {STRes127,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC008.xsd','./msxsdtest/identityConstraint',valid),
+ STResList128 = [STRes127|STResList127],
+
+
+ ?line {STRes128,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC009.xsd','./msxsdtest/identityConstraint',valid),
+ STResList129 = [STRes128|STResList128],
+
+
+ ?line {STRes129,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC010.xsd','./msxsdtest/identityConstraint',valid),
+ STResList130 = [STRes129|STResList129],
+
+
+ ?line {STRes130,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC011.xsd','./msxsdtest/identityConstraint',valid),
+ STResList131 = [STRes130|STResList130],
+
+
+ ?line {STRes131,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC012.xsd','./msxsdtest/identityConstraint',valid),
+ STResList132 = [STRes131|STResList131],
+
+
+ ?line {STRes132,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC013.xsd','./msxsdtest/identityConstraint',valid),
+ STResList133 = [STRes132|STResList132],
+
+
+ ?line {STRes133,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC014.xsd','./msxsdtest/identityConstraint',valid),
+ STResList134 = [STRes133|STResList133],
+
+
+ ?line {STRes134,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC015.xsd','./msxsdtest/identityConstraint',valid),
+ STResList135 = [STRes134|STResList134],
+
+
+ ?line {STRes135,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC016.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList136 = [STRes135|STResList135],
+
+
+ ?line {STRes136,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC017.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList137 = [STRes136|STResList136],
+
+
+ ?line {STRes137,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC018.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList138 = [STRes137|STResList137],
+
+
+ ?line {STRes138,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC019.xsd','./msxsdtest/identityConstraint',valid),
+ STResList139 = [STRes138|STResList138],
+
+
+ ?line {STRes139,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC020.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList140 = [STRes139|STResList139],
+
+
+ ?line {STRes140,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC021.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList141 = [STRes140|STResList140],
+
+
+ ?line {STRes141,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC022.xsd','./msxsdtest/identityConstraint',valid),
+ STResList142 = [STRes141|STResList141],
+
+
+ ?line {STRes142,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC023.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList143 = [STRes142|STResList142],
+
+
+ ?line {STRes143,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC024.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList144 = [STRes143|STResList143],
+
+
+ ?line {STRes144,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC025.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList145 = [STRes144|STResList144],
+
+
+ ?line {STRes145,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC026.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList146 = [STRes145|STResList145],
+
+
+ ?line {STRes146,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC027.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList147 = [STRes146|STResList146],
+
+
+ ?line {STRes147,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC028.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList148 = [STRes147|STResList147],
+
+
+ ?line {STRes148,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC029.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList149 = [STRes148|STResList148],
+
+
+ ?line {STRes149,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC030.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList150 = [STRes149|STResList149],
+
+
+ ?line {STRes150,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC031.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList151 = [STRes150|STResList150],
+
+
+ ?line {STRes151,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC032.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList152 = [STRes151|STResList151],
+
+
+ ?line {STRes152,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC033.xsd','./msxsdtest/identityConstraint',valid),
+ STResList153 = [STRes152|STResList152],
+
+
+ ?line {STRes153,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC034.xsd','./msxsdtest/identityConstraint',valid),
+ STResList154 = [STRes153|STResList153],
+
+
+ ?line {STRes154,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC035.xsd','./msxsdtest/identityConstraint',valid),
+ STResList155 = [STRes154|STResList154],
+
+
+ ?line {STRes155,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC036.xsd','./msxsdtest/identityConstraint',valid),
+ STResList156 = [STRes155|STResList155],
+
+
+ ?line {STRes156,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC038.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList157 = [STRes156|STResList156],
+
+
+ ?line {STRes157,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC039.xsd','./msxsdtest/identityConstraint',valid),
+ STResList158 = [STRes157|STResList157],
+
+
+ ?line {STRes158,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC040.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList159 = [STRes158|STResList158],
+
+
+ ?line {STRes159,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC041.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList160 = [STRes159|STResList159],
+
+
+ ?line {STRes160,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC042.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList161 = [STRes160|STResList160],
+
+
+ ?line {STRes161,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC043.xsd','./msxsdtest/identityConstraint',valid),
+ STResList162 = [STRes161|STResList161],
+
+
+ ?line {STRes162,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC044.xsd','./msxsdtest/identityConstraint',valid),
+ STResList163 = [STRes162|STResList162],
+
+
+ ?line {STRes163,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC045.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList164 = [STRes163|STResList163],
+
+
+ ?line {STRes164,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC046.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList165 = [STRes164|STResList164],
+
+
+ ?line {STRes165,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC047.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList166 = [STRes165|STResList165],
+
+
+ ?line {STRes166,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC048.xsd','./msxsdtest/identityConstraint',valid),
+ STResList167 = [STRes166|STResList166],
+
+
+ ?line {STRes167,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC049.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList168 = [STRes167|STResList167],
+
+
+ ?line {STRes168,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC050.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList169 = [STRes168|STResList168],
+
+
+ ?line {STRes169,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC051.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList170 = [STRes169|STResList169],
+
+
+ ?line {STRes170,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC052.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList171 = [STRes170|STResList170],
+
+
+ ?line {STRes171,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC053.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList172 = [STRes171|STResList171],
+
+
+ ?line {STRes172,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC054.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList173 = [STRes172|STResList172],
+
+
+ ?line {STRes173,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC055.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList174 = [STRes173|STResList173],
+
+
+ ?line {STRes174,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC056.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList175 = [STRes174|STResList174],
+
+
+ ?line {STRes175,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC057.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList176 = [STRes175|STResList175],
+
+
+ ?line {STRes176,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC058.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList177 = [STRes176|STResList176],
+
+
+ ?line {STRes177,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC059.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList178 = [STRes177|STResList177],
+
+
+ ?line {STRes178,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC060.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList179 = [STRes178|STResList178],
+
+
+ ?line {STRes179,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC061.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList180 = [STRes179|STResList179],
+
+
+ ?line {STRes180,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC062.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList181 = [STRes180|STResList180],
+
+
+ ?line {STRes181,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idC063.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList182 = [STRes181|STResList181],
+
+
+ ?line {STRes182,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD001.xsd','./msxsdtest/identityConstraint',valid),
+ STResList183 = [STRes182|STResList182],
+
+
+ ?line {STRes183,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD002.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList184 = [STRes183|STResList183],
+
+
+ ?line {STRes184,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD003.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList185 = [STRes184|STResList184],
+
+
+ ?line {STRes185,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD004.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList186 = [STRes185|STResList185],
+
+
+ ?line {STRes186,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD005.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList187 = [STRes186|STResList186],
+
+
+ ?line {STRes187,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD006.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList188 = [STRes187|STResList187],
+
+
+ ?line {STRes188,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD007.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList189 = [STRes188|STResList188],
+
+
+ ?line {STRes189,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD008.xsd','./msxsdtest/identityConstraint',valid),
+ STResList190 = [STRes189|STResList189],
+
+
+ ?line {STRes190,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD009.xsd','./msxsdtest/identityConstraint',valid),
+ STResList191 = [STRes190|STResList190],
+
+
+ ?line {STRes191,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD010.xsd','./msxsdtest/identityConstraint',valid),
+ STResList192 = [STRes191|STResList191],
+
+
+ ?line {STRes192,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD011.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList193 = [STRes192|STResList192],
+
+
+ ?line {STRes193,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD012.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList194 = [STRes193|STResList193],
+
+
+ ?line {STRes194,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD013.xsd','./msxsdtest/identityConstraint',valid),
+ STResList195 = [STRes194|STResList194],
+
+
+ ?line {STRes195,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD014.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList196 = [STRes195|STResList195],
+
+
+ ?line {STRes196,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD015.xsd','./msxsdtest/identityConstraint',valid),
+ STResList197 = [STRes196|STResList196],
+
+
+ ?line {STRes197,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD016.xsd','./msxsdtest/identityConstraint',valid),
+ STResList198 = [STRes197|STResList197],
+
+
+ ?line {STRes198,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD017.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList199 = [STRes198|STResList198],
+
+
+ ?line {STRes199,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD018.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList200 = [STRes199|STResList199],
+
+
+ ?line {STRes200,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD019.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList201 = [STRes200|STResList200],
+
+
+ ?line {STRes201,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD020.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList202 = [STRes201|STResList201],
+
+
+ ?line {STRes202,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD021.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList203 = [STRes202|STResList202],
+
+
+ ?line {STRes203,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD022.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList204 = [STRes203|STResList203],
+
+
+ ?line {STRes204,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD023.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList205 = [STRes204|STResList204],
+
+
+ ?line {STRes205,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD024.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList206 = [STRes205|STResList205],
+
+
+ ?line {STRes206,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD025.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList207 = [STRes206|STResList206],
+
+
+ ?line {STRes207,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD026.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList208 = [STRes207|STResList207],
+
+
+ ?line {STRes208,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD027.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList209 = [STRes208|STResList208],
+
+
+ ?line {STRes209,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD028.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList210 = [STRes209|STResList209],
+
+
+ ?line {STRes210,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD029.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList211 = [STRes210|STResList210],
+
+
+ ?line {STRes211,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD030.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList212 = [STRes211|STResList211],
+
+
+ ?line {STRes212,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD031.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList213 = [STRes212|STResList212],
+
+
+ ?line {STRes213,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD032.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList214 = [STRes213|STResList213],
+
+
+ ?line {STRes214,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idD033.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList215 = [STRes214|STResList214],
+
+
+ ?line {STRes215,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE001.xsd','./msxsdtest/identityConstraint',valid),
+ STResList216 = [STRes215|STResList215],
+
+
+ ?line {STRes216,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE002.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList217 = [STRes216|STResList216],
+
+
+ ?line {STRes217,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE003.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList218 = [STRes217|STResList217],
+
+
+ ?line {STRes218,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE004.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList219 = [STRes218|STResList218],
+
+
+ ?line {STRes219,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE005.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList220 = [STRes219|STResList219],
+
+
+ ?line {STRes220,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE006.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList221 = [STRes220|STResList220],
+
+
+ ?line {STRes221,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE007.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList222 = [STRes221|STResList221],
+
+
+ ?line {STRes222,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE008.xsd','./msxsdtest/identityConstraint',valid),
+ STResList223 = [STRes222|STResList222],
+
+
+ ?line {STRes223,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE009.xsd','./msxsdtest/identityConstraint',valid),
+ STResList224 = [STRes223|STResList223],
+
+
+ ?line {STRes224,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE010.xsd','./msxsdtest/identityConstraint',valid),
+ STResList225 = [STRes224|STResList224],
+
+
+ ?line {STRes225,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE011.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList226 = [STRes225|STResList225],
+
+
+ ?line {STRes226,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE012.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList227 = [STRes226|STResList226],
+
+
+ ?line {STRes227,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE013.xsd','./msxsdtest/identityConstraint',valid),
+ STResList228 = [STRes227|STResList227],
+
+
+ ?line {STRes228,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE014.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList229 = [STRes228|STResList228],
+
+
+ ?line {STRes229,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE015.xsd','./msxsdtest/identityConstraint',valid),
+ STResList230 = [STRes229|STResList229],
+
+
+ ?line {STRes230,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE016.xsd','./msxsdtest/identityConstraint',valid),
+ STResList231 = [STRes230|STResList230],
+
+
+ ?line {STRes231,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE017.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList232 = [STRes231|STResList231],
+
+
+ ?line {STRes232,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE018.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList233 = [STRes232|STResList232],
+
+
+ ?line {STRes233,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE019.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList234 = [STRes233|STResList233],
+
+
+ ?line {STRes234,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE020.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList235 = [STRes234|STResList234],
+
+
+ ?line {STRes235,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE021.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList236 = [STRes235|STResList235],
+
+
+ ?line {STRes236,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE022.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList237 = [STRes236|STResList236],
+
+
+ ?line {STRes237,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE023.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList238 = [STRes237|STResList237],
+
+
+ ?line {STRes238,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE024.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList239 = [STRes238|STResList238],
+
+
+ ?line {STRes239,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE025.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList240 = [STRes239|STResList239],
+
+
+ ?line {STRes240,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE026.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList241 = [STRes240|STResList240],
+
+
+ ?line {STRes241,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE027.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList242 = [STRes241|STResList241],
+
+
+ ?line {STRes242,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE028.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList243 = [STRes242|STResList242],
+
+
+ ?line {STRes243,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE029.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList244 = [STRes243|STResList243],
+
+
+ ?line {STRes244,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE030.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList245 = [STRes244|STResList244],
+
+
+ ?line {STRes245,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE031.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList246 = [STRes245|STResList245],
+
+
+ ?line {STRes246,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE032.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList247 = [STRes246|STResList246],
+
+
+ ?line {STRes247,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idE033.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList248 = [STRes247|STResList247],
+
+
+ ?line {STRes248,S248} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF001.xsd','./msxsdtest/identityConstraint',valid),
+ STResList249 = [STRes248|STResList248],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF001.xml','./msxsdtest/identityConstraint',valid,S248),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes249,S249} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF003.xsd','./msxsdtest/identityConstraint',valid),
+ STResList250 = [STRes249|STResList249],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF003.xml','./msxsdtest/identityConstraint',valid,S249),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes250,S250} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF004.xsd','./msxsdtest/identityConstraint',valid),
+ STResList251 = [STRes250|STResList250],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF004.xml','./msxsdtest/identityConstraint',valid,S250),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes251,S251} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF005.xsd','./msxsdtest/identityConstraint',valid),
+ STResList252 = [STRes251|STResList251],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF005.xml','./msxsdtest/identityConstraint',invalid,S251),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes252,S252} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF006.xsd','./msxsdtest/identityConstraint',valid),
+ STResList253 = [STRes252|STResList252],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF006.xml','./msxsdtest/identityConstraint',invalid,S252),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes253,S253} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF007.xsd','./msxsdtest/identityConstraint',valid),
+ STResList254 = [STRes253|STResList253],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF007.xml','./msxsdtest/identityConstraint',valid,S253),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes254,S254} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF008.xsd','./msxsdtest/identityConstraint',valid),
+ STResList255 = [STRes254|STResList254],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF008.xml','./msxsdtest/identityConstraint',invalid,S254),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes255,S255} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF009.xsd','./msxsdtest/identityConstraint',valid),
+ STResList256 = [STRes255|STResList255],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF009.xml','./msxsdtest/identityConstraint',valid,S255),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes256,S256} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF010.xsd','./msxsdtest/identityConstraint',valid),
+ STResList257 = [STRes256|STResList256],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF010.xml','./msxsdtest/identityConstraint',invalid,S256),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes257,S257} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF011.xsd','./msxsdtest/identityConstraint',valid),
+ STResList258 = [STRes257|STResList257],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF011.xml','./msxsdtest/identityConstraint',valid,S257),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes258,S258} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF012.xsd','./msxsdtest/identityConstraint',valid),
+ STResList259 = [STRes258|STResList258],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF012.xml','./msxsdtest/identityConstraint',valid,S258),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes259,S259} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF013.xsd','./msxsdtest/identityConstraint',valid),
+ STResList260 = [STRes259|STResList259],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF013.xml','./msxsdtest/identityConstraint',valid,S259),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes260,S260} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF014.xsd','./msxsdtest/identityConstraint',valid),
+ STResList261 = [STRes260|STResList260],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF014.xml','./msxsdtest/identityConstraint',valid,S260),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes261,S261} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF015.xsd','./msxsdtest/identityConstraint',valid),
+ STResList262 = [STRes261|STResList261],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF015.xml','./msxsdtest/identityConstraint',invalid,S261),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes262,S262} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF016.xsd','./msxsdtest/identityConstraint',valid),
+ STResList263 = [STRes262|STResList262],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF016.xml','./msxsdtest/identityConstraint',invalid,S262),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes263,S263} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF017.xsd','./msxsdtest/identityConstraint',valid),
+ STResList264 = [STRes263|STResList263],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF017.xml','./msxsdtest/identityConstraint',invalid,S263),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes264,S264} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF018.xsd','./msxsdtest/identityConstraint',valid),
+ STResList265 = [STRes264|STResList264],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF018.xml','./msxsdtest/identityConstraint',invalid,S264),
+ ITResList17 = [ITRes16|ITResList16],
+
+
+ ?line {STRes265,S265} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF019.xsd','./msxsdtest/identityConstraint',valid),
+ STResList266 = [STRes265|STResList265],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF019.xml','./msxsdtest/identityConstraint',valid,S265),
+ ITResList18 = [ITRes17|ITResList17],
+
+
+ ?line {STRes266,S266} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF020.xsd','./msxsdtest/identityConstraint',valid),
+ STResList267 = [STRes266|STResList266],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF020.xml','./msxsdtest/identityConstraint',valid,S266),
+ ITResList19 = [ITRes18|ITResList18],
+
+
+ ?line {STRes267,S267} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF021.xsd','./msxsdtest/identityConstraint',valid),
+ STResList268 = [STRes267|STResList267],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF021.xml','./msxsdtest/identityConstraint',valid,S267),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes268,S268} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF022.xsd','./msxsdtest/identityConstraint',valid),
+ STResList269 = [STRes268|STResList268],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF022.xml','./msxsdtest/identityConstraint',valid,S268),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes269,S269} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF023.xsd','./msxsdtest/identityConstraint',valid),
+ STResList270 = [STRes269|STResList269],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF023.xml','./msxsdtest/identityConstraint',valid,S269),
+ ITResList22 = [ITRes21|ITResList21],
+
+
+ ?line {STRes270,S270} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF024.xsd','./msxsdtest/identityConstraint',valid),
+ STResList271 = [STRes270|STResList270],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF024.xml','./msxsdtest/identityConstraint',valid,S270),
+ ITResList23 = [ITRes22|ITResList22],
+
+
+ ?line {STRes271,S271} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF025.xsd','./msxsdtest/identityConstraint',valid),
+ STResList272 = [STRes271|STResList271],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF025.xml','./msxsdtest/identityConstraint',valid,S271),
+ ITResList24 = [ITRes23|ITResList23],
+
+
+ ?line {STRes272,S272} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF026.xsd','./msxsdtest/identityConstraint',valid),
+ STResList273 = [STRes272|STResList272],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF026.xml','./msxsdtest/identityConstraint',valid,S272),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes273,S273} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF027.xsd','./msxsdtest/identityConstraint',valid),
+ STResList274 = [STRes273|STResList273],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF027.xml','./msxsdtest/identityConstraint',valid,S273),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes274,S274} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF028.xsd','./msxsdtest/identityConstraint',valid),
+ STResList275 = [STRes274|STResList274],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF028.xml','./msxsdtest/identityConstraint',valid,S274),
+ ITResList27 = [ITRes26|ITResList26],
+
+
+ ?line {STRes275,S275} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF029.xsd','./msxsdtest/identityConstraint',valid),
+ STResList276 = [STRes275|STResList275],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF029.xml','./msxsdtest/identityConstraint',valid,S275),
+ ITResList28 = [ITRes27|ITResList27],
+
+
+ ?line {STRes276,S276} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF030.xsd','./msxsdtest/identityConstraint',valid),
+ STResList277 = [STRes276|STResList276],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF030.xml','./msxsdtest/identityConstraint',valid,S276),
+ ITResList29 = [ITRes28|ITResList28],
+
+
+ ?line {STRes277,S277} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF031.xsd','./msxsdtest/identityConstraint',valid),
+ STResList278 = [STRes277|STResList277],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF031.xml','./msxsdtest/identityConstraint',valid,S277),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes278,S278} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF032.xsd','./msxsdtest/identityConstraint',valid),
+ STResList279 = [STRes278|STResList278],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF032.xml','./msxsdtest/identityConstraint',valid,S278),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes279,S279} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF033.xsd','./msxsdtest/identityConstraint',valid),
+ STResList280 = [STRes279|STResList279],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF033.xml','./msxsdtest/identityConstraint',valid,S279),
+ ITResList32 = [ITRes31|ITResList31],
+
+
+ ?line {STRes280,S280} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF034.xsd','./msxsdtest/identityConstraint',valid),
+ STResList281 = [STRes280|STResList280],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF034.xml','./msxsdtest/identityConstraint',valid,S280),
+ ITResList33 = [ITRes32|ITResList32],
+
+
+ ?line {STRes281,S281} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF035.xsd','./msxsdtest/identityConstraint',valid),
+ STResList282 = [STRes281|STResList281],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF035.xml','./msxsdtest/identityConstraint',valid,S281),
+ ITResList34 = [ITRes33|ITResList33],
+
+
+ ?line {STRes282,S282} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idF036.xsd','./msxsdtest/identityConstraint',valid),
+ STResList283 = [STRes282|STResList282],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idF036.xml','./msxsdtest/identityConstraint',valid,S282),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes283,S283} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG001.xsd','./msxsdtest/identityConstraint',valid),
+ STResList284 = [STRes283|STResList283],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG001.xml','./msxsdtest/identityConstraint',valid,S283),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes284,S284} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG003.xsd','./msxsdtest/identityConstraint',valid),
+ STResList285 = [STRes284|STResList284],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG003.xml','./msxsdtest/identityConstraint',invalid,S284),
+ ITResList37 = [ITRes36|ITResList36],
+
+
+ ?line {STRes285,S285} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG004.xsd','./msxsdtest/identityConstraint',valid),
+ STResList286 = [STRes285|STResList285],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG004.xml','./msxsdtest/identityConstraint',valid,S285),
+ ITResList38 = [ITRes37|ITResList37],
+
+
+ ?line {STRes286,S286} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG005.xsd','./msxsdtest/identityConstraint',valid),
+ STResList287 = [STRes286|STResList286],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG005.xml','./msxsdtest/identityConstraint',invalid,S286),
+ ITResList39 = [ITRes38|ITResList38],
+
+
+ ?line {STRes287,S287} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG006.xsd','./msxsdtest/identityConstraint',valid),
+ STResList288 = [STRes287|STResList287],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG006.xml','./msxsdtest/identityConstraint',invalid,S287),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes288,S288} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG007.xsd','./msxsdtest/identityConstraint',valid),
+ STResList289 = [STRes288|STResList288],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG007.xml','./msxsdtest/identityConstraint',valid,S288),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes289,S289} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG008.xsd','./msxsdtest/identityConstraint',valid),
+ STResList290 = [STRes289|STResList289],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG008.xml','./msxsdtest/identityConstraint',invalid,S289),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes290,S290} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG009.xsd','./msxsdtest/identityConstraint',valid),
+ STResList291 = [STRes290|STResList290],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG009.xml','./msxsdtest/identityConstraint',invalid,S290),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes291,S291} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG010.xsd','./msxsdtest/identityConstraint',valid),
+ STResList292 = [STRes291|STResList291],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG010.xml','./msxsdtest/identityConstraint',invalid,S291),
+ ITResList44 = [ITRes43|ITResList43],
+
+
+ ?line {STRes292,S292} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG011.xsd','./msxsdtest/identityConstraint',valid),
+ STResList293 = [STRes292|STResList292],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG011.xml','./msxsdtest/identityConstraint',invalid,S292),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes293,S293} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG012.xsd','./msxsdtest/identityConstraint',valid),
+ STResList294 = [STRes293|STResList293],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG012.xml','./msxsdtest/identityConstraint',invalid,S293),
+ ITResList46 = [ITRes45|ITResList45],
+
+
+ ?line {STRes294,S294} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG013.xsd','./msxsdtest/identityConstraint',valid),
+ STResList295 = [STRes294|STResList294],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG013.xml','./msxsdtest/identityConstraint',valid,S294),
+ ITResList47 = [ITRes46|ITResList46],
+
+
+ ?line {STRes295,S295} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG014.xsd','./msxsdtest/identityConstraint',valid),
+ STResList296 = [STRes295|STResList295],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG014.xml','./msxsdtest/identityConstraint',valid,S295),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes296,S296} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG015.xsd','./msxsdtest/identityConstraint',valid),
+ STResList297 = [STRes296|STResList296],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG015.xml','./msxsdtest/identityConstraint',valid,S296),
+ ITResList49 = [ITRes48|ITResList48],
+
+
+ ?line {STRes297,S297} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG016.xsd','./msxsdtest/identityConstraint',valid),
+ STResList298 = [STRes297|STResList297],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG016.xml','./msxsdtest/identityConstraint',valid,S297),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes298,S298} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG017.xsd','./msxsdtest/identityConstraint',valid),
+ STResList299 = [STRes298|STResList298],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG017.xml','./msxsdtest/identityConstraint',valid,S298),
+ ITResList51 = [ITRes50|ITResList50],
+
+
+ ?line {STRes299,S299} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG018.xsd','./msxsdtest/identityConstraint',valid),
+ STResList300 = [STRes299|STResList299],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG018.xml','./msxsdtest/identityConstraint',valid,S299),
+ ITResList52 = [ITRes51|ITResList51],
+
+
+ ?line {STRes300,S300} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG019.xsd','./msxsdtest/identityConstraint',valid),
+ STResList301 = [STRes300|STResList300],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG019.xml','./msxsdtest/identityConstraint',valid,S300),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes301,S301} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG020.xsd','./msxsdtest/identityConstraint',valid),
+ STResList302 = [STRes301|STResList301],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG020.xml','./msxsdtest/identityConstraint',invalid,S301),
+ ITResList54 = [ITRes53|ITResList53],
+
+
+ ?line {STRes302,S302} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG021.xsd','./msxsdtest/identityConstraint',valid),
+ STResList303 = [STRes302|STResList302],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG021.xml','./msxsdtest/identityConstraint',valid,S302),
+ ITResList55 = [ITRes54|ITResList54],
+
+
+ ?line {STRes303,S303} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG022.xsd','./msxsdtest/identityConstraint',valid),
+ STResList304 = [STRes303|STResList303],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG022.xml','./msxsdtest/identityConstraint',valid,S303),
+ ITResList56 = [ITRes55|ITResList55],
+
+
+ ?line {STRes304,S304} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG023.xsd','./msxsdtest/identityConstraint',valid),
+ STResList305 = [STRes304|STResList304],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG023.xml','./msxsdtest/identityConstraint',valid,S304),
+ ITResList57 = [ITRes56|ITResList56],
+
+
+ ?line {STRes305,S305} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG024.xsd','./msxsdtest/identityConstraint',valid),
+ STResList306 = [STRes305|STResList305],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG024.xml','./msxsdtest/identityConstraint',valid,S305),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes306,S306} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG025.xsd','./msxsdtest/identityConstraint',valid),
+ STResList307 = [STRes306|STResList306],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG025.xml','./msxsdtest/identityConstraint',invalid,S306),
+ ITResList59 = [ITRes58|ITResList58],
+
+
+ ?line {STRes307,S307} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG026.xsd','./msxsdtest/identityConstraint',valid),
+ STResList308 = [STRes307|STResList307],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG026.xml','./msxsdtest/identityConstraint',valid,S307),
+ ITResList60 = [ITRes59|ITResList59],
+
+
+ ?line {STRes308,S308} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG027.xsd','./msxsdtest/identityConstraint',valid),
+ STResList309 = [STRes308|STResList308],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG027.xml','./msxsdtest/identityConstraint',valid,S308),
+ ITResList61 = [ITRes60|ITResList60],
+
+
+ ?line {STRes309,S309} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG028.xsd','./msxsdtest/identityConstraint',valid),
+ STResList310 = [STRes309|STResList309],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG028.xml','./msxsdtest/identityConstraint',valid,S309),
+ ITResList62 = [ITRes61|ITResList61],
+
+
+ ?line {STRes310,S310} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG029.xsd','./msxsdtest/identityConstraint',valid),
+ STResList311 = [STRes310|STResList310],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG029.xml','./msxsdtest/identityConstraint',valid,S310),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes311,S311} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idG030.xsd','./msxsdtest/identityConstraint',valid),
+ STResList312 = [STRes311|STResList311],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idG030.xml','./msxsdtest/identityConstraint',valid,S311),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes312,S312} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH001.xsd','./msxsdtest/identityConstraint',valid),
+ STResList313 = [STRes312|STResList312],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH001.xml','./msxsdtest/identityConstraint',valid,S312),
+ ITResList65 = [ITRes64|ITResList64],
+
+
+ ?line {STRes313,S313} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH003.xsd','./msxsdtest/identityConstraint',valid),
+ STResList314 = [STRes313|STResList313],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH003.xml','./msxsdtest/identityConstraint',valid,S313),
+ ITResList66 = [ITRes65|ITResList65],
+
+
+ ?line {STRes314,S314} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH004.xsd','./msxsdtest/identityConstraint',valid),
+ STResList315 = [STRes314|STResList314],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH004.xml','./msxsdtest/identityConstraint',valid,S314),
+ ITResList67 = [ITRes66|ITResList66],
+
+
+ ?line {STRes315,S315} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH005.xsd','./msxsdtest/identityConstraint',valid),
+ STResList316 = [STRes315|STResList315],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH005.xml','./msxsdtest/identityConstraint',invalid,S315),
+ ITResList68 = [ITRes67|ITResList67],
+
+
+ ?line {STRes316,S316} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH006.xsd','./msxsdtest/identityConstraint',valid),
+ STResList317 = [STRes316|STResList316],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH006.xml','./msxsdtest/identityConstraint',invalid,S316),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes317,S317} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH007.xsd','./msxsdtest/identityConstraint',valid),
+ STResList318 = [STRes317|STResList317],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH007.xml','./msxsdtest/identityConstraint',valid,S317),
+ ITResList70 = [ITRes69|ITResList69],
+
+
+ ?line {STRes318,S318} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH008.xsd','./msxsdtest/identityConstraint',valid),
+ STResList319 = [STRes318|STResList318],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH008.xml','./msxsdtest/identityConstraint',valid,S318),
+ ITResList71 = [ITRes70|ITResList70],
+
+
+ ?line {STRes319,S319} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH009.xsd','./msxsdtest/identityConstraint',valid),
+ STResList320 = [STRes319|STResList319],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH009.xml','./msxsdtest/identityConstraint',valid,S319),
+ ITResList72 = [ITRes71|ITResList71],
+
+
+ ?line {STRes320,S320} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH010.xsd','./msxsdtest/identityConstraint',valid),
+ STResList321 = [STRes320|STResList320],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH010.xml','./msxsdtest/identityConstraint',invalid,S320),
+ ITResList73 = [ITRes72|ITResList72],
+
+
+ ?line {STRes321,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH011.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList322 = [STRes321|STResList321],
+
+
+ ?line {STRes322,S322} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH012.xsd','./msxsdtest/identityConstraint',valid),
+ STResList323 = [STRes322|STResList322],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH012.xml','./msxsdtest/identityConstraint',invalid,S322),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes323,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH013.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList324 = [STRes323|STResList323],
+
+
+ ?line {STRes324,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH014.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList325 = [STRes324|STResList324],
+
+
+ ?line {STRes325,S325} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH015.xsd','./msxsdtest/identityConstraint',valid),
+ STResList326 = [STRes325|STResList325],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH015.xml','./msxsdtest/identityConstraint',valid,S325),
+ ITResList75 = [ITRes74|ITResList74],
+
+
+ ?line {STRes326,S326} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH016.xsd','./msxsdtest/identityConstraint',valid),
+ STResList327 = [STRes326|STResList326],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH016.xml','./msxsdtest/identityConstraint',valid,S326),
+ ITResList76 = [ITRes75|ITResList75],
+
+
+ ?line {STRes327,S327} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH017.xsd','./msxsdtest/identityConstraint',valid),
+ STResList328 = [STRes327|STResList327],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH017.xml','./msxsdtest/identityConstraint',valid,S327),
+ ITResList77 = [ITRes76|ITResList76],
+
+
+ ?line {STRes328,S328} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH018.xsd','./msxsdtest/identityConstraint',valid),
+ STResList329 = [STRes328|STResList328],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH018.xml','./msxsdtest/identityConstraint',valid,S328),
+ ITResList78 = [ITRes77|ITResList77],
+
+
+ ?line {STRes329,S329} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH019.xsd','./msxsdtest/identityConstraint',valid),
+ STResList330 = [STRes329|STResList329],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH019.xml','./msxsdtest/identityConstraint',valid,S329),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes330,S330} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH020.xsd','./msxsdtest/identityConstraint',valid),
+ STResList331 = [STRes330|STResList330],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH020.xml','./msxsdtest/identityConstraint',valid,S330),
+ ITResList80 = [ITRes79|ITResList79],
+
+
+ ?line {STRes331,S331} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH021.xsd','./msxsdtest/identityConstraint',valid),
+ STResList332 = [STRes331|STResList331],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH021.xml','./msxsdtest/identityConstraint',valid,S331),
+ ITResList81 = [ITRes80|ITResList80],
+
+
+ ?line {STRes332,S332} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH022.xsd','./msxsdtest/identityConstraint',valid),
+ STResList333 = [STRes332|STResList332],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH022.xml','./msxsdtest/identityConstraint',valid,S332),
+ ITResList82 = [ITRes81|ITResList81],
+
+
+ ?line {STRes333,S333} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH023.xsd','./msxsdtest/identityConstraint',valid),
+ STResList334 = [STRes333|STResList333],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH023.xml','./msxsdtest/identityConstraint',valid,S333),
+ ITResList83 = [ITRes82|ITResList82],
+
+
+ ?line {STRes334,S334} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH024.xsd','./msxsdtest/identityConstraint',valid),
+ STResList335 = [STRes334|STResList334],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH024.xml','./msxsdtest/identityConstraint',valid,S334),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes335,S335} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH025.xsd','./msxsdtest/identityConstraint',valid),
+ STResList336 = [STRes335|STResList335],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH025.xml','./msxsdtest/identityConstraint',valid,S335),
+ ITResList85 = [ITRes84|ITResList84],
+
+
+ ?line {STRes336,S336} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH026.xsd','./msxsdtest/identityConstraint',valid),
+ STResList337 = [STRes336|STResList336],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH026.xml','./msxsdtest/identityConstraint',valid,S336),
+ ITResList86 = [ITRes85|ITResList85],
+
+
+ ?line {STRes337,S337} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH027.xsd','./msxsdtest/identityConstraint',valid),
+ STResList338 = [STRes337|STResList337],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH027.xml','./msxsdtest/identityConstraint',valid,S337),
+ ITResList87 = [ITRes86|ITResList86],
+
+
+ ?line {STRes338,S338} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH028.xsd','./msxsdtest/identityConstraint',valid),
+ STResList339 = [STRes338|STResList338],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH028.xml','./msxsdtest/identityConstraint',valid,S338),
+ ITResList88 = [ITRes87|ITResList87],
+
+
+ ?line {STRes339,S339} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH029.xsd','./msxsdtest/identityConstraint',valid),
+ STResList340 = [STRes339|STResList339],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH029.xml','./msxsdtest/identityConstraint',valid,S339),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes340,S340} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH030.xsd','./msxsdtest/identityConstraint',valid),
+ STResList341 = [STRes340|STResList340],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH030.xml','./msxsdtest/identityConstraint',valid,S340),
+ ITResList90 = [ITRes89|ITResList89],
+
+
+ ?line {STRes341,S341} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH031.xsd','./msxsdtest/identityConstraint',valid),
+ STResList342 = [STRes341|STResList341],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH031.xml','./msxsdtest/identityConstraint',valid,S341),
+ ITResList91 = [ITRes90|ITResList90],
+
+
+ ?line {STRes342,S342} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH032.xsd','./msxsdtest/identityConstraint',valid),
+ STResList343 = [STRes342|STResList342],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH032.xml','./msxsdtest/identityConstraint',valid,S342),
+ ITResList92 = [ITRes91|ITResList91],
+
+
+ ?line {STRes343,S343} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH034.xsd','./msxsdtest/identityConstraint',valid),
+ STResList344 = [STRes343|STResList343],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idH034.xml','./msxsdtest/identityConstraint',valid,S343),
+ ITResList93 = [ITRes92|ITResList92],
+
+
+ ?line {STRes344,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idH035.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList345 = [STRes344|STResList344],
+
+
+ ?line {STRes345,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI001.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList346 = [STRes345|STResList345],
+
+
+ ?line {STRes346,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI002.xsd','./msxsdtest/identityConstraint',valid),
+ STResList347 = [STRes346|STResList346],
+
+
+ ?line {STRes347,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI003.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList348 = [STRes347|STResList347],
+
+
+ ?line {STRes348,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI004.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList349 = [STRes348|STResList348],
+
+
+ ?line {STRes349,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI005.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList350 = [STRes349|STResList349],
+
+
+ ?line {STRes350,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI006.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList351 = [STRes350|STResList350],
+
+
+ ?line {STRes351,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI007.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList352 = [STRes351|STResList351],
+
+
+ ?line {STRes352,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI008.xsd','./msxsdtest/identityConstraint',valid),
+ STResList353 = [STRes352|STResList352],
+
+
+ ?line {STRes353,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI009.xsd','./msxsdtest/identityConstraint',valid),
+ STResList354 = [STRes353|STResList353],
+
+
+ ?line {STRes354,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI010.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList355 = [STRes354|STResList354],
+
+
+ ?line {STRes355,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI011.xsd','./msxsdtest/identityConstraint',valid),
+ STResList356 = [STRes355|STResList355],
+
+
+ ?line {STRes356,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI012.xsd','./msxsdtest/identityConstraint',valid),
+ STResList357 = [STRes356|STResList356],
+
+
+ ?line {STRes357,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI013.xsd','./msxsdtest/identityConstraint',valid),
+ STResList358 = [STRes357|STResList357],
+
+
+ ?line {STRes358,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI014.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList359 = [STRes358|STResList358],
+
+
+ ?line {STRes359,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI015.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList360 = [STRes359|STResList359],
+
+
+ ?line {STRes360,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI016.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList361 = [STRes360|STResList360],
+
+
+ ?line {STRes361,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI017.xsd','./msxsdtest/identityConstraint',valid),
+ STResList362 = [STRes361|STResList361],
+
+
+ ?line {STRes362,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI018.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList363 = [STRes362|STResList362],
+
+
+ ?line {STRes363,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI019.xsd','./msxsdtest/identityConstraint',valid),
+ STResList364 = [STRes363|STResList363],
+
+
+ ?line {STRes364,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI020.xsd','./msxsdtest/identityConstraint',valid),
+ STResList365 = [STRes364|STResList364],
+
+
+ ?line {STRes365,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI021.xsd','./msxsdtest/identityConstraint',valid),
+ STResList366 = [STRes365|STResList365],
+
+
+ ?line {STRes366,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI022.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList367 = [STRes366|STResList366],
+
+
+ ?line {STRes367,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI023.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList368 = [STRes367|STResList367],
+
+
+ ?line {STRes368,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI024.xsd','./msxsdtest/identityConstraint',valid),
+ STResList369 = [STRes368|STResList368],
+
+
+ ?line {STRes369,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI025.xsd','./msxsdtest/identityConstraint',valid),
+ STResList370 = [STRes369|STResList369],
+
+
+ ?line {STRes370,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI026.xsd','./msxsdtest/identityConstraint',valid),
+ STResList371 = [STRes370|STResList370],
+
+
+ ?line {STRes371,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI027.xsd','./msxsdtest/identityConstraint',valid),
+ STResList372 = [STRes371|STResList371],
+
+
+ ?line {STRes372,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI028.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList373 = [STRes372|STResList372],
+
+
+ ?line {STRes373,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI029.xsd','./msxsdtest/identityConstraint',valid),
+ STResList374 = [STRes373|STResList373],
+
+
+ ?line {STRes374,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI030.xsd','./msxsdtest/identityConstraint',valid),
+ STResList375 = [STRes374|STResList374],
+
+
+ ?line {STRes375,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI031.xsd','./msxsdtest/identityConstraint',valid),
+ STResList376 = [STRes375|STResList375],
+
+
+ ?line {STRes376,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI032.xsd','./msxsdtest/identityConstraint',valid),
+ STResList377 = [STRes376|STResList376],
+
+
+ ?line {STRes377,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI033.xsd','./msxsdtest/identityConstraint',valid),
+ STResList378 = [STRes377|STResList377],
+
+
+ ?line {STRes378,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI034.xsd','./msxsdtest/identityConstraint',valid),
+ STResList379 = [STRes378|STResList378],
+
+
+ ?line {STRes379,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI035.xsd','./msxsdtest/identityConstraint',valid),
+ STResList380 = [STRes379|STResList379],
+
+
+ ?line {STRes380,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI036.xsd','./msxsdtest/identityConstraint',valid),
+ STResList381 = [STRes380|STResList380],
+
+
+ ?line {STRes381,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI037.xsd','./msxsdtest/identityConstraint',valid),
+ STResList382 = [STRes381|STResList381],
+
+
+ ?line {STRes382,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI038.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList383 = [STRes382|STResList382],
+
+
+ ?line {STRes383,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI039.xsd','./msxsdtest/identityConstraint',valid),
+ STResList384 = [STRes383|STResList383],
+
+
+ ?line {STRes384,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI040.xsd','./msxsdtest/identityConstraint',valid),
+ STResList385 = [STRes384|STResList384],
+
+
+ ?line {STRes385,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI041.xsd','./msxsdtest/identityConstraint',valid),
+ STResList386 = [STRes385|STResList385],
+
+
+ ?line {STRes386,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI042.xsd','./msxsdtest/identityConstraint',valid),
+ STResList387 = [STRes386|STResList386],
+
+
+ ?line {STRes387,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI043.xsd','./msxsdtest/identityConstraint',valid),
+ STResList388 = [STRes387|STResList387],
+
+
+ ?line {STRes388,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI044.xsd','./msxsdtest/identityConstraint',valid),
+ STResList389 = [STRes388|STResList388],
+
+
+ ?line {STRes389,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI045.xsd','./msxsdtest/identityConstraint',valid),
+ STResList390 = [STRes389|STResList389],
+
+
+ ?line {STRes390,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI046.xsd','./msxsdtest/identityConstraint',valid),
+ STResList391 = [STRes390|STResList390],
+
+
+ ?line {STRes391,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI047.xsd','./msxsdtest/identityConstraint',valid),
+ STResList392 = [STRes391|STResList391],
+
+
+ ?line {STRes392,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI048.xsd','./msxsdtest/identityConstraint',valid),
+ STResList393 = [STRes392|STResList392],
+
+
+ ?line {STRes393,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI049.xsd','./msxsdtest/identityConstraint',valid),
+ STResList394 = [STRes393|STResList393],
+
+
+ ?line {STRes394,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI050.xsd','./msxsdtest/identityConstraint',valid),
+ STResList395 = [STRes394|STResList394],
+
+
+ ?line {STRes395,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI051.xsd','./msxsdtest/identityConstraint',valid),
+ STResList396 = [STRes395|STResList395],
+
+
+ ?line {STRes396,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI052.xsd','./msxsdtest/identityConstraint',valid),
+ STResList397 = [STRes396|STResList396],
+
+
+ ?line {STRes397,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI053.xsd','./msxsdtest/identityConstraint',valid),
+ STResList398 = [STRes397|STResList397],
+
+
+ ?line {STRes398,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI054.xsd','./msxsdtest/identityConstraint',valid),
+ STResList399 = [STRes398|STResList398],
+
+
+ ?line {STRes399,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI055.xsd','./msxsdtest/identityConstraint',valid),
+ STResList400 = [STRes399|STResList399],
+
+
+ ?line {STRes400,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI056.xsd','./msxsdtest/identityConstraint',valid),
+ STResList401 = [STRes400|STResList400],
+
+
+ ?line {STRes401,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI057.xsd','./msxsdtest/identityConstraint',valid),
+ STResList402 = [STRes401|STResList401],
+
+
+ ?line {STRes402,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI058.xsd','./msxsdtest/identityConstraint',valid),
+ STResList403 = [STRes402|STResList402],
+
+
+ ?line {STRes403,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI059.xsd','./msxsdtest/identityConstraint',valid),
+ STResList404 = [STRes403|STResList403],
+
+
+ ?line {STRes404,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI060.xsd','./msxsdtest/identityConstraint',valid),
+ STResList405 = [STRes404|STResList404],
+
+
+ ?line {STRes405,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI061.xsd','./msxsdtest/identityConstraint',valid),
+ STResList406 = [STRes405|STResList405],
+
+
+ ?line {STRes406,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI062.xsd','./msxsdtest/identityConstraint',valid),
+ STResList407 = [STRes406|STResList406],
+
+
+ ?line {STRes407,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI063.xsd','./msxsdtest/identityConstraint',valid),
+ STResList408 = [STRes407|STResList407],
+
+
+ ?line {STRes408,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI064.xsd','./msxsdtest/identityConstraint',valid),
+ STResList409 = [STRes408|STResList408],
+
+
+ ?line {STRes409,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI065.xsd','./msxsdtest/identityConstraint',valid),
+ STResList410 = [STRes409|STResList409],
+
+
+ ?line {STRes410,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI066.xsd','./msxsdtest/identityConstraint',valid),
+ STResList411 = [STRes410|STResList410],
+
+
+ ?line {STRes411,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI067.xsd','./msxsdtest/identityConstraint',valid),
+ STResList412 = [STRes411|STResList411],
+
+
+ ?line {STRes412,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI068.xsd','./msxsdtest/identityConstraint',valid),
+ STResList413 = [STRes412|STResList412],
+
+
+ ?line {STRes413,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI069.xsd','./msxsdtest/identityConstraint',valid),
+ STResList414 = [STRes413|STResList413],
+
+
+ ?line {STRes414,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI070.xsd','./msxsdtest/identityConstraint',valid),
+ STResList415 = [STRes414|STResList414],
+
+
+ ?line {STRes415,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI071.xsd','./msxsdtest/identityConstraint',valid),
+ STResList416 = [STRes415|STResList415],
+
+
+ ?line {STRes416,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI072.xsd','./msxsdtest/identityConstraint',valid),
+ STResList417 = [STRes416|STResList416],
+
+
+ ?line {STRes417,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI073.xsd','./msxsdtest/identityConstraint',valid),
+ STResList418 = [STRes417|STResList417],
+
+
+ ?line {STRes418,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI074.xsd','./msxsdtest/identityConstraint',valid),
+ STResList419 = [STRes418|STResList418],
+
+
+ ?line {STRes419,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI075.xsd','./msxsdtest/identityConstraint',valid),
+ STResList420 = [STRes419|STResList419],
+
+
+ ?line {STRes420,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI076.xsd','./msxsdtest/identityConstraint',valid),
+ STResList421 = [STRes420|STResList420],
+
+
+ ?line {STRes421,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI077.xsd','./msxsdtest/identityConstraint',valid),
+ STResList422 = [STRes421|STResList421],
+
+
+ ?line {STRes422,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI078.xsd','./msxsdtest/identityConstraint',valid),
+ STResList423 = [STRes422|STResList422],
+
+
+ ?line {STRes423,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI079.xsd','./msxsdtest/identityConstraint',valid),
+ STResList424 = [STRes423|STResList423],
+
+
+ ?line {STRes424,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI080.xsd','./msxsdtest/identityConstraint',valid),
+ STResList425 = [STRes424|STResList424],
+
+
+ ?line {STRes425,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI081.xsd','./msxsdtest/identityConstraint',valid),
+ STResList426 = [STRes425|STResList425],
+
+
+ ?line {STRes426,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI082.xsd','./msxsdtest/identityConstraint',valid),
+ STResList427 = [STRes426|STResList426],
+
+
+ ?line {STRes427,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI083.xsd','./msxsdtest/identityConstraint',valid),
+ STResList428 = [STRes427|STResList427],
+
+
+ ?line {STRes428,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI084.xsd','./msxsdtest/identityConstraint',valid),
+ STResList429 = [STRes428|STResList428],
+
+
+ ?line {STRes429,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI085.xsd','./msxsdtest/identityConstraint',valid),
+ STResList430 = [STRes429|STResList429],
+
+
+ ?line {STRes430,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI086.xsd','./msxsdtest/identityConstraint',valid),
+ STResList431 = [STRes430|STResList430],
+
+
+ ?line {STRes431,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI087.xsd','./msxsdtest/identityConstraint',valid),
+ STResList432 = [STRes431|STResList431],
+
+
+ ?line {STRes432,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI088.xsd','./msxsdtest/identityConstraint',valid),
+ STResList433 = [STRes432|STResList432],
+
+
+ ?line {STRes433,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI089.xsd','./msxsdtest/identityConstraint',valid),
+ STResList434 = [STRes433|STResList433],
+
+
+ ?line {STRes434,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI090.xsd','./msxsdtest/identityConstraint',valid),
+ STResList435 = [STRes434|STResList434],
+
+
+ ?line {STRes435,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI091.xsd','./msxsdtest/identityConstraint',valid),
+ STResList436 = [STRes435|STResList435],
+
+
+ ?line {STRes436,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI092.xsd','./msxsdtest/identityConstraint',valid),
+ STResList437 = [STRes436|STResList436],
+
+
+ ?line {STRes437,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI093.xsd','./msxsdtest/identityConstraint',valid),
+ STResList438 = [STRes437|STResList437],
+
+
+ ?line {STRes438,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI094.xsd','./msxsdtest/identityConstraint',valid),
+ STResList439 = [STRes438|STResList438],
+
+
+ ?line {STRes439,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI095.xsd','./msxsdtest/identityConstraint',valid),
+ STResList440 = [STRes439|STResList439],
+
+
+ ?line {STRes440,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI096.xsd','./msxsdtest/identityConstraint',valid),
+ STResList441 = [STRes440|STResList440],
+
+
+ ?line {STRes441,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI097.xsd','./msxsdtest/identityConstraint',valid),
+ STResList442 = [STRes441|STResList441],
+
+
+ ?line {STRes442,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI098.xsd','./msxsdtest/identityConstraint',valid),
+ STResList443 = [STRes442|STResList442],
+
+
+ ?line {STRes443,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI099.xsd','./msxsdtest/identityConstraint',valid),
+ STResList444 = [STRes443|STResList443],
+
+
+ ?line {STRes444,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI100.xsd','./msxsdtest/identityConstraint',valid),
+ STResList445 = [STRes444|STResList444],
+
+
+ ?line {STRes445,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI101.xsd','./msxsdtest/identityConstraint',valid),
+ STResList446 = [STRes445|STResList445],
+
+
+ ?line {STRes446,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI102.xsd','./msxsdtest/identityConstraint',valid),
+ STResList447 = [STRes446|STResList446],
+
+
+ ?line {STRes447,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI103.xsd','./msxsdtest/identityConstraint',valid),
+ STResList448 = [STRes447|STResList447],
+
+
+ ?line {STRes448,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI104.xsd','./msxsdtest/identityConstraint',valid),
+ STResList449 = [STRes448|STResList448],
+
+
+ ?line {STRes449,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI105.xsd','./msxsdtest/identityConstraint',valid),
+ STResList450 = [STRes449|STResList449],
+
+
+ ?line {STRes450,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI106.xsd','./msxsdtest/identityConstraint',valid),
+ STResList451 = [STRes450|STResList450],
+
+
+ ?line {STRes451,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI107.xsd','./msxsdtest/identityConstraint',valid),
+ STResList452 = [STRes451|STResList451],
+
+
+ ?line {STRes452,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI108.xsd','./msxsdtest/identityConstraint',valid),
+ STResList453 = [STRes452|STResList452],
+
+
+ ?line {STRes453,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI109.xsd','./msxsdtest/identityConstraint',valid),
+ STResList454 = [STRes453|STResList453],
+
+
+ ?line {STRes454,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI110.xsd','./msxsdtest/identityConstraint',valid),
+ STResList455 = [STRes454|STResList454],
+
+
+ ?line {STRes455,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI111.xsd','./msxsdtest/identityConstraint',valid),
+ STResList456 = [STRes455|STResList455],
+
+
+ ?line {STRes456,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI112.xsd','./msxsdtest/identityConstraint',valid),
+ STResList457 = [STRes456|STResList456],
+
+
+ ?line {STRes457,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI113.xsd','./msxsdtest/identityConstraint',valid),
+ STResList458 = [STRes457|STResList457],
+
+
+ ?line {STRes458,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI114.xsd','./msxsdtest/identityConstraint',valid),
+ STResList459 = [STRes458|STResList458],
+
+
+ ?line {STRes459,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI115.xsd','./msxsdtest/identityConstraint',valid),
+ STResList460 = [STRes459|STResList459],
+
+
+ ?line {STRes460,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI116.xsd','./msxsdtest/identityConstraint',valid),
+ STResList461 = [STRes460|STResList460],
+
+
+ ?line {STRes461,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI117.xsd','./msxsdtest/identityConstraint',valid),
+ STResList462 = [STRes461|STResList461],
+
+
+ ?line {STRes462,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI118.xsd','./msxsdtest/identityConstraint',valid),
+ STResList463 = [STRes462|STResList462],
+
+
+ ?line {STRes463,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI119.xsd','./msxsdtest/identityConstraint',valid),
+ STResList464 = [STRes463|STResList463],
+
+
+ ?line {STRes464,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI120.xsd','./msxsdtest/identityConstraint',valid),
+ STResList465 = [STRes464|STResList464],
+
+
+ ?line {STRes465,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI121.xsd','./msxsdtest/identityConstraint',valid),
+ STResList466 = [STRes465|STResList465],
+
+
+ ?line {STRes466,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI122.xsd','./msxsdtest/identityConstraint',valid),
+ STResList467 = [STRes466|STResList466],
+
+
+ ?line {STRes467,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI123.xsd','./msxsdtest/identityConstraint',valid),
+ STResList468 = [STRes467|STResList467],
+
+
+ ?line {STRes468,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI124.xsd','./msxsdtest/identityConstraint',valid),
+ STResList469 = [STRes468|STResList468],
+
+
+ ?line {STRes469,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI125.xsd','./msxsdtest/identityConstraint',valid),
+ STResList470 = [STRes469|STResList469],
+
+
+ ?line {STRes470,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI126.xsd','./msxsdtest/identityConstraint',valid),
+ STResList471 = [STRes470|STResList470],
+
+
+ ?line {STRes471,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI127.xsd','./msxsdtest/identityConstraint',valid),
+ STResList472 = [STRes471|STResList471],
+
+
+ ?line {STRes472,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI128.xsd','./msxsdtest/identityConstraint',valid),
+ STResList473 = [STRes472|STResList472],
+
+
+ ?line {STRes473,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI129.xsd','./msxsdtest/identityConstraint',valid),
+ STResList474 = [STRes473|STResList473],
+
+
+ ?line {STRes474,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI130.xsd','./msxsdtest/identityConstraint',valid),
+ STResList475 = [STRes474|STResList474],
+
+
+ ?line {STRes475,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI131.xsd','./msxsdtest/identityConstraint',valid),
+ STResList476 = [STRes475|STResList475],
+
+
+ ?line {STRes476,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI132.xsd','./msxsdtest/identityConstraint',valid),
+ STResList477 = [STRes476|STResList476],
+
+
+ ?line {STRes477,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI133.xsd','./msxsdtest/identityConstraint',valid),
+ STResList478 = [STRes477|STResList477],
+
+
+ ?line {STRes478,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI134.xsd','./msxsdtest/identityConstraint',valid),
+ STResList479 = [STRes478|STResList478],
+
+
+ ?line {STRes479,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI135.xsd','./msxsdtest/identityConstraint',valid),
+ STResList480 = [STRes479|STResList479],
+
+
+ ?line {STRes480,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI136.xsd','./msxsdtest/identityConstraint',valid),
+ STResList481 = [STRes480|STResList480],
+
+
+ ?line {STRes481,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI137.xsd','./msxsdtest/identityConstraint',valid),
+ STResList482 = [STRes481|STResList481],
+
+
+ ?line {STRes482,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI138.xsd','./msxsdtest/identityConstraint',valid),
+ STResList483 = [STRes482|STResList482],
+
+
+ ?line {STRes483,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI139.xsd','./msxsdtest/identityConstraint',valid),
+ STResList484 = [STRes483|STResList483],
+
+
+ ?line {STRes484,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI140.xsd','./msxsdtest/identityConstraint',valid),
+ STResList485 = [STRes484|STResList484],
+
+
+ ?line {STRes485,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI141.xsd','./msxsdtest/identityConstraint',valid),
+ STResList486 = [STRes485|STResList485],
+
+
+ ?line {STRes486,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI142.xsd','./msxsdtest/identityConstraint',valid),
+ STResList487 = [STRes486|STResList486],
+
+
+ ?line {STRes487,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI143.xsd','./msxsdtest/identityConstraint',valid),
+ STResList488 = [STRes487|STResList487],
+
+
+ ?line {STRes488,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI144.xsd','./msxsdtest/identityConstraint',valid),
+ STResList489 = [STRes488|STResList488],
+
+
+ ?line {STRes489,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI145.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList490 = [STRes489|STResList489],
+
+
+ ?line {STRes490,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI146.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList491 = [STRes490|STResList490],
+
+
+ ?line {STRes491,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI147.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList492 = [STRes491|STResList491],
+
+
+ ?line {STRes492,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI148.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList493 = [STRes492|STResList492],
+
+
+ ?line {STRes493,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI149.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList494 = [STRes493|STResList493],
+
+
+ ?line {STRes494,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI150.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList495 = [STRes494|STResList494],
+
+
+ ?line {STRes495,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI151.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList496 = [STRes495|STResList495],
+
+
+ ?line {STRes496,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idI152.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList497 = [STRes496|STResList496],
+
+
+ ?line {STRes497,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ001.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList498 = [STRes497|STResList497],
+
+
+ ?line {STRes498,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ002.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList499 = [STRes498|STResList498],
+
+
+ ?line {STRes499,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ003.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList500 = [STRes499|STResList499],
+
+
+ ?line {STRes500,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ004.xsd','./msxsdtest/identityConstraint',valid),
+ STResList501 = [STRes500|STResList500],
+
+
+ ?line {STRes501,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ005.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList502 = [STRes501|STResList501],
+
+
+ ?line {STRes502,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ006.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList503 = [STRes502|STResList502],
+
+
+ ?line {STRes503,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ007.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList504 = [STRes503|STResList503],
+
+
+ ?line {STRes504,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ008.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList505 = [STRes504|STResList504],
+
+
+ ?line {STRes505,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ009.xsd','./msxsdtest/identityConstraint',valid),
+ STResList506 = [STRes505|STResList505],
+
+
+ ?line {STRes506,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ010.xsd','./msxsdtest/identityConstraint',valid),
+ STResList507 = [STRes506|STResList506],
+
+
+ ?line {STRes507,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ011.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList508 = [STRes507|STResList507],
+
+
+ ?line {STRes508,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ012.xsd','./msxsdtest/identityConstraint',valid),
+ STResList509 = [STRes508|STResList508],
+
+
+ ?line {STRes509,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ013.xsd','./msxsdtest/identityConstraint',valid),
+ STResList510 = [STRes509|STResList509],
+
+
+ ?line {STRes510,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ014.xsd','./msxsdtest/identityConstraint',valid),
+ STResList511 = [STRes510|STResList510],
+
+
+ ?line {STRes511,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ015.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList512 = [STRes511|STResList511],
+
+
+ ?line {STRes512,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ016.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList513 = [STRes512|STResList512],
+
+
+ ?line {STRes513,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ017.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList514 = [STRes513|STResList513],
+
+
+ ?line {STRes514,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ018.xsd','./msxsdtest/identityConstraint',valid),
+ STResList515 = [STRes514|STResList514],
+
+
+ ?line {STRes515,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ019.xsd','./msxsdtest/identityConstraint',valid),
+ STResList516 = [STRes515|STResList515],
+
+
+ ?line {STRes516,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ020.xsd','./msxsdtest/identityConstraint',valid),
+ STResList517 = [STRes516|STResList516],
+
+
+ ?line {STRes517,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ021.xsd','./msxsdtest/identityConstraint',valid),
+ STResList518 = [STRes517|STResList517],
+
+
+ ?line {STRes518,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ022.xsd','./msxsdtest/identityConstraint',valid),
+ STResList519 = [STRes518|STResList518],
+
+
+ ?line {STRes519,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ023.xsd','./msxsdtest/identityConstraint',valid),
+ STResList520 = [STRes519|STResList519],
+
+
+ ?line {STRes520,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ024.xsd','./msxsdtest/identityConstraint',valid),
+ STResList521 = [STRes520|STResList520],
+
+
+ ?line {STRes521,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ025.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList522 = [STRes521|STResList521],
+
+
+ ?line {STRes522,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ026.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList523 = [STRes522|STResList522],
+
+
+ ?line {STRes523,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ027.xsd','./msxsdtest/identityConstraint',valid),
+ STResList524 = [STRes523|STResList523],
+
+
+ ?line {STRes524,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ028.xsd','./msxsdtest/identityConstraint',valid),
+ STResList525 = [STRes524|STResList524],
+
+
+ ?line {STRes525,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ029.xsd','./msxsdtest/identityConstraint',valid),
+ STResList526 = [STRes525|STResList525],
+
+
+ ?line {STRes526,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ030.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList527 = [STRes526|STResList526],
+
+
+ ?line {STRes527,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ031.xsd','./msxsdtest/identityConstraint',valid),
+ STResList528 = [STRes527|STResList527],
+
+
+ ?line {STRes528,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ032.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList529 = [STRes528|STResList528],
+
+
+ ?line {STRes529,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ033.xsd','./msxsdtest/identityConstraint',valid),
+ STResList530 = [STRes529|STResList529],
+
+
+ ?line {STRes530,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ034.xsd','./msxsdtest/identityConstraint',valid),
+ STResList531 = [STRes530|STResList530],
+
+
+ ?line {STRes531,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ035.xsd','./msxsdtest/identityConstraint',valid),
+ STResList532 = [STRes531|STResList531],
+
+
+ ?line {STRes532,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ036.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList533 = [STRes532|STResList532],
+
+
+ ?line {STRes533,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ037.xsd','./msxsdtest/identityConstraint',valid),
+ STResList534 = [STRes533|STResList533],
+
+
+ ?line {STRes534,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ038.xsd','./msxsdtest/identityConstraint',valid),
+ STResList535 = [STRes534|STResList534],
+
+
+ ?line {STRes535,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ039.xsd','./msxsdtest/identityConstraint',valid),
+ STResList536 = [STRes535|STResList535],
+
+
+ ?line {STRes536,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ040.xsd','./msxsdtest/identityConstraint',valid),
+ STResList537 = [STRes536|STResList536],
+
+
+ ?line {STRes537,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ041.xsd','./msxsdtest/identityConstraint',valid),
+ STResList538 = [STRes537|STResList537],
+
+
+ ?line {STRes538,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ042.xsd','./msxsdtest/identityConstraint',valid),
+ STResList539 = [STRes538|STResList538],
+
+
+ ?line {STRes539,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ043.xsd','./msxsdtest/identityConstraint',valid),
+ STResList540 = [STRes539|STResList539],
+
+
+ ?line {STRes540,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ044.xsd','./msxsdtest/identityConstraint',valid),
+ STResList541 = [STRes540|STResList540],
+
+
+ ?line {STRes541,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ045.xsd','./msxsdtest/identityConstraint',valid),
+ STResList542 = [STRes541|STResList541],
+
+
+ ?line {STRes542,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ046.xsd','./msxsdtest/identityConstraint',valid),
+ STResList543 = [STRes542|STResList542],
+
+
+ ?line {STRes543,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ047.xsd','./msxsdtest/identityConstraint',valid),
+ STResList544 = [STRes543|STResList543],
+
+
+ ?line {STRes544,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ048.xsd','./msxsdtest/identityConstraint',valid),
+ STResList545 = [STRes544|STResList544],
+
+
+ ?line {STRes545,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ049.xsd','./msxsdtest/identityConstraint',valid),
+ STResList546 = [STRes545|STResList545],
+
+
+ ?line {STRes546,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ050.xsd','./msxsdtest/identityConstraint',valid),
+ STResList547 = [STRes546|STResList546],
+
+
+ ?line {STRes547,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ051.xsd','./msxsdtest/identityConstraint',valid),
+ STResList548 = [STRes547|STResList547],
+
+
+ ?line {STRes548,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ052.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList549 = [STRes548|STResList548],
+
+
+ ?line {STRes549,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ053.xsd','./msxsdtest/identityConstraint',valid),
+ STResList550 = [STRes549|STResList549],
+
+
+ ?line {STRes550,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ054.xsd','./msxsdtest/identityConstraint',valid),
+ STResList551 = [STRes550|STResList550],
+
+
+ ?line {STRes551,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ055.xsd','./msxsdtest/identityConstraint',valid),
+ STResList552 = [STRes551|STResList551],
+
+
+ ?line {STRes552,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ056.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList553 = [STRes552|STResList552],
+
+
+ ?line {STRes553,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ057.xsd','./msxsdtest/identityConstraint',valid),
+ STResList554 = [STRes553|STResList553],
+
+
+ ?line {STRes554,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ058.xsd','./msxsdtest/identityConstraint',valid),
+ STResList555 = [STRes554|STResList554],
+
+
+ ?line {STRes555,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ059.xsd','./msxsdtest/identityConstraint',valid),
+ STResList556 = [STRes555|STResList555],
+
+
+ ?line {STRes556,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ060.xsd','./msxsdtest/identityConstraint',valid),
+ STResList557 = [STRes556|STResList556],
+
+
+ ?line {STRes557,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ061.xsd','./msxsdtest/identityConstraint',valid),
+ STResList558 = [STRes557|STResList557],
+
+
+ ?line {STRes558,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ062.xsd','./msxsdtest/identityConstraint',valid),
+ STResList559 = [STRes558|STResList558],
+
+
+ ?line {STRes559,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ063.xsd','./msxsdtest/identityConstraint',valid),
+ STResList560 = [STRes559|STResList559],
+
+
+ ?line {STRes560,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ064.xsd','./msxsdtest/identityConstraint',valid),
+ STResList561 = [STRes560|STResList560],
+
+
+ ?line {STRes561,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ065.xsd','./msxsdtest/identityConstraint',valid),
+ STResList562 = [STRes561|STResList561],
+
+
+ ?line {STRes562,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ066.xsd','./msxsdtest/identityConstraint',valid),
+ STResList563 = [STRes562|STResList562],
+
+
+ ?line {STRes563,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ067.xsd','./msxsdtest/identityConstraint',valid),
+ STResList564 = [STRes563|STResList563],
+
+
+ ?line {STRes564,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ068.xsd','./msxsdtest/identityConstraint',valid),
+ STResList565 = [STRes564|STResList564],
+
+
+ ?line {STRes565,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ069.xsd','./msxsdtest/identityConstraint',valid),
+ STResList566 = [STRes565|STResList565],
+
+
+ ?line {STRes566,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ070.xsd','./msxsdtest/identityConstraint',valid),
+ STResList567 = [STRes566|STResList566],
+
+
+ ?line {STRes567,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ071.xsd','./msxsdtest/identityConstraint',valid),
+ STResList568 = [STRes567|STResList567],
+
+
+ ?line {STRes568,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ072.xsd','./msxsdtest/identityConstraint',valid),
+ STResList569 = [STRes568|STResList568],
+
+
+ ?line {STRes569,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ073.xsd','./msxsdtest/identityConstraint',valid),
+ STResList570 = [STRes569|STResList569],
+
+
+ ?line {STRes570,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ074.xsd','./msxsdtest/identityConstraint',valid),
+ STResList571 = [STRes570|STResList570],
+
+
+ ?line {STRes571,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ075.xsd','./msxsdtest/identityConstraint',valid),
+ STResList572 = [STRes571|STResList571],
+
+
+ ?line {STRes572,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ076.xsd','./msxsdtest/identityConstraint',valid),
+ STResList573 = [STRes572|STResList572],
+
+
+ ?line {STRes573,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ077.xsd','./msxsdtest/identityConstraint',valid),
+ STResList574 = [STRes573|STResList573],
+
+
+ ?line {STRes574,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ078.xsd','./msxsdtest/identityConstraint',valid),
+ STResList575 = [STRes574|STResList574],
+
+
+ ?line {STRes575,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ079.xsd','./msxsdtest/identityConstraint',valid),
+ STResList576 = [STRes575|STResList575],
+
+
+ ?line {STRes576,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ080.xsd','./msxsdtest/identityConstraint',valid),
+ STResList577 = [STRes576|STResList576],
+
+
+ ?line {STRes577,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ081.xsd','./msxsdtest/identityConstraint',valid),
+ STResList578 = [STRes577|STResList577],
+
+
+ ?line {STRes578,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ082.xsd','./msxsdtest/identityConstraint',valid),
+ STResList579 = [STRes578|STResList578],
+
+
+ ?line {STRes579,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ083.xsd','./msxsdtest/identityConstraint',valid),
+ STResList580 = [STRes579|STResList579],
+
+
+ ?line {STRes580,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ084.xsd','./msxsdtest/identityConstraint',valid),
+ STResList581 = [STRes580|STResList580],
+
+
+ ?line {STRes581,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ085.xsd','./msxsdtest/identityConstraint',valid),
+ STResList582 = [STRes581|STResList581],
+
+
+ ?line {STRes582,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ086.xsd','./msxsdtest/identityConstraint',valid),
+ STResList583 = [STRes582|STResList582],
+
+
+ ?line {STRes583,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ087.xsd','./msxsdtest/identityConstraint',valid),
+ STResList584 = [STRes583|STResList583],
+
+
+ ?line {STRes584,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ088.xsd','./msxsdtest/identityConstraint',valid),
+ STResList585 = [STRes584|STResList584],
+
+
+ ?line {STRes585,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ089.xsd','./msxsdtest/identityConstraint',valid),
+ STResList586 = [STRes585|STResList585],
+
+
+ ?line {STRes586,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ090.xsd','./msxsdtest/identityConstraint',valid),
+ STResList587 = [STRes586|STResList586],
+
+
+ ?line {STRes587,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ091.xsd','./msxsdtest/identityConstraint',valid),
+ STResList588 = [STRes587|STResList587],
+
+
+ ?line {STRes588,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ092.xsd','./msxsdtest/identityConstraint',valid),
+ STResList589 = [STRes588|STResList588],
+
+
+ ?line {STRes589,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ093.xsd','./msxsdtest/identityConstraint',valid),
+ STResList590 = [STRes589|STResList589],
+
+
+ ?line {STRes590,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ094.xsd','./msxsdtest/identityConstraint',valid),
+ STResList591 = [STRes590|STResList590],
+
+
+ ?line {STRes591,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ095.xsd','./msxsdtest/identityConstraint',valid),
+ STResList592 = [STRes591|STResList591],
+
+
+ ?line {STRes592,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ096.xsd','./msxsdtest/identityConstraint',valid),
+ STResList593 = [STRes592|STResList592],
+
+
+ ?line {STRes593,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ097.xsd','./msxsdtest/identityConstraint',valid),
+ STResList594 = [STRes593|STResList593],
+
+
+ ?line {STRes594,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ098.xsd','./msxsdtest/identityConstraint',valid),
+ STResList595 = [STRes594|STResList594],
+
+
+ ?line {STRes595,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ099.xsd','./msxsdtest/identityConstraint',valid),
+ STResList596 = [STRes595|STResList595],
+
+
+ ?line {STRes596,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ100.xsd','./msxsdtest/identityConstraint',valid),
+ STResList597 = [STRes596|STResList596],
+
+
+ ?line {STRes597,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ101.xsd','./msxsdtest/identityConstraint',valid),
+ STResList598 = [STRes597|STResList597],
+
+
+ ?line {STRes598,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ102.xsd','./msxsdtest/identityConstraint',valid),
+ STResList599 = [STRes598|STResList598],
+
+
+ ?line {STRes599,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ103.xsd','./msxsdtest/identityConstraint',valid),
+ STResList600 = [STRes599|STResList599],
+
+
+ ?line {STRes600,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ104.xsd','./msxsdtest/identityConstraint',valid),
+ STResList601 = [STRes600|STResList600],
+
+
+ ?line {STRes601,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ105.xsd','./msxsdtest/identityConstraint',valid),
+ STResList602 = [STRes601|STResList601],
+
+
+ ?line {STRes602,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ106.xsd','./msxsdtest/identityConstraint',valid),
+ STResList603 = [STRes602|STResList602],
+
+
+ ?line {STRes603,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ107.xsd','./msxsdtest/identityConstraint',valid),
+ STResList604 = [STRes603|STResList603],
+
+
+ ?line {STRes604,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ108.xsd','./msxsdtest/identityConstraint',valid),
+ STResList605 = [STRes604|STResList604],
+
+
+ ?line {STRes605,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ109.xsd','./msxsdtest/identityConstraint',valid),
+ STResList606 = [STRes605|STResList605],
+
+
+ ?line {STRes606,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ110.xsd','./msxsdtest/identityConstraint',valid),
+ STResList607 = [STRes606|STResList606],
+
+
+ ?line {STRes607,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ111.xsd','./msxsdtest/identityConstraint',valid),
+ STResList608 = [STRes607|STResList607],
+
+
+ ?line {STRes608,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ112.xsd','./msxsdtest/identityConstraint',valid),
+ STResList609 = [STRes608|STResList608],
+
+
+ ?line {STRes609,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ113.xsd','./msxsdtest/identityConstraint',valid),
+ STResList610 = [STRes609|STResList609],
+
+
+ ?line {STRes610,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ114.xsd','./msxsdtest/identityConstraint',valid),
+ STResList611 = [STRes610|STResList610],
+
+
+ ?line {STRes611,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ115.xsd','./msxsdtest/identityConstraint',valid),
+ STResList612 = [STRes611|STResList611],
+
+
+ ?line {STRes612,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ116.xsd','./msxsdtest/identityConstraint',valid),
+ STResList613 = [STRes612|STResList612],
+
+
+ ?line {STRes613,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ117.xsd','./msxsdtest/identityConstraint',valid),
+ STResList614 = [STRes613|STResList613],
+
+
+ ?line {STRes614,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ118.xsd','./msxsdtest/identityConstraint',valid),
+ STResList615 = [STRes614|STResList614],
+
+
+ ?line {STRes615,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ119.xsd','./msxsdtest/identityConstraint',valid),
+ STResList616 = [STRes615|STResList615],
+
+
+ ?line {STRes616,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ120.xsd','./msxsdtest/identityConstraint',valid),
+ STResList617 = [STRes616|STResList616],
+
+
+ ?line {STRes617,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ121.xsd','./msxsdtest/identityConstraint',valid),
+ STResList618 = [STRes617|STResList617],
+
+
+ ?line {STRes618,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ122.xsd','./msxsdtest/identityConstraint',valid),
+ STResList619 = [STRes618|STResList618],
+
+
+ ?line {STRes619,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ123.xsd','./msxsdtest/identityConstraint',valid),
+ STResList620 = [STRes619|STResList619],
+
+
+ ?line {STRes620,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ124.xsd','./msxsdtest/identityConstraint',valid),
+ STResList621 = [STRes620|STResList620],
+
+
+ ?line {STRes621,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ125.xsd','./msxsdtest/identityConstraint',valid),
+ STResList622 = [STRes621|STResList621],
+
+
+ ?line {STRes622,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ126.xsd','./msxsdtest/identityConstraint',valid),
+ STResList623 = [STRes622|STResList622],
+
+
+ ?line {STRes623,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ127.xsd','./msxsdtest/identityConstraint',valid),
+ STResList624 = [STRes623|STResList623],
+
+
+ ?line {STRes624,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ128.xsd','./msxsdtest/identityConstraint',valid),
+ STResList625 = [STRes624|STResList624],
+
+
+ ?line {STRes625,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ129.xsd','./msxsdtest/identityConstraint',valid),
+ STResList626 = [STRes625|STResList625],
+
+
+ ?line {STRes626,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ130.xsd','./msxsdtest/identityConstraint',valid),
+ STResList627 = [STRes626|STResList626],
+
+
+ ?line {STRes627,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ131.xsd','./msxsdtest/identityConstraint',valid),
+ STResList628 = [STRes627|STResList627],
+
+
+ ?line {STRes628,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ132.xsd','./msxsdtest/identityConstraint',valid),
+ STResList629 = [STRes628|STResList628],
+
+
+ ?line {STRes629,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ133.xsd','./msxsdtest/identityConstraint',valid),
+ STResList630 = [STRes629|STResList629],
+
+
+ ?line {STRes630,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ134.xsd','./msxsdtest/identityConstraint',valid),
+ STResList631 = [STRes630|STResList630],
+
+
+ ?line {STRes631,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ135.xsd','./msxsdtest/identityConstraint',valid),
+ STResList632 = [STRes631|STResList631],
+
+
+ ?line {STRes632,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ136.xsd','./msxsdtest/identityConstraint',valid),
+ STResList633 = [STRes632|STResList632],
+
+
+ ?line {STRes633,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ137.xsd','./msxsdtest/identityConstraint',valid),
+ STResList634 = [STRes633|STResList633],
+
+
+ ?line {STRes634,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ138.xsd','./msxsdtest/identityConstraint',valid),
+ STResList635 = [STRes634|STResList634],
+
+
+ ?line {STRes635,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ139.xsd','./msxsdtest/identityConstraint',valid),
+ STResList636 = [STRes635|STResList635],
+
+
+ ?line {STRes636,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ140.xsd','./msxsdtest/identityConstraint',valid),
+ STResList637 = [STRes636|STResList636],
+
+
+ ?line {STRes637,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ141.xsd','./msxsdtest/identityConstraint',valid),
+ STResList638 = [STRes637|STResList637],
+
+
+ ?line {STRes638,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ142.xsd','./msxsdtest/identityConstraint',valid),
+ STResList639 = [STRes638|STResList638],
+
+
+ ?line {STRes639,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ143.xsd','./msxsdtest/identityConstraint',valid),
+ STResList640 = [STRes639|STResList639],
+
+
+ ?line {STRes640,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ144.xsd','./msxsdtest/identityConstraint',valid),
+ STResList641 = [STRes640|STResList640],
+
+
+ ?line {STRes641,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ145.xsd','./msxsdtest/identityConstraint',valid),
+ STResList642 = [STRes641|STResList641],
+
+
+ ?line {STRes642,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ146.xsd','./msxsdtest/identityConstraint',valid),
+ STResList643 = [STRes642|STResList642],
+
+
+ ?line {STRes643,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ147.xsd','./msxsdtest/identityConstraint',valid),
+ STResList644 = [STRes643|STResList643],
+
+
+ ?line {STRes644,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ148.xsd','./msxsdtest/identityConstraint',valid),
+ STResList645 = [STRes644|STResList644],
+
+
+ ?line {STRes645,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ149.xsd','./msxsdtest/identityConstraint',valid),
+ STResList646 = [STRes645|STResList645],
+
+
+ ?line {STRes646,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ150.xsd','./msxsdtest/identityConstraint',valid),
+ STResList647 = [STRes646|STResList646],
+
+
+ ?line {STRes647,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ151.xsd','./msxsdtest/identityConstraint',valid),
+ STResList648 = [STRes647|STResList647],
+
+
+ ?line {STRes648,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ152.xsd','./msxsdtest/identityConstraint',valid),
+ STResList649 = [STRes648|STResList648],
+
+
+ ?line {STRes649,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ153.xsd','./msxsdtest/identityConstraint',valid),
+ STResList650 = [STRes649|STResList649],
+
+
+ ?line {STRes650,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ154.xsd','./msxsdtest/identityConstraint',valid),
+ STResList651 = [STRes650|STResList650],
+
+
+ ?line {STRes651,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ155.xsd','./msxsdtest/identityConstraint',valid),
+ STResList652 = [STRes651|STResList651],
+
+
+ ?line {STRes652,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ156.xsd','./msxsdtest/identityConstraint',valid),
+ STResList653 = [STRes652|STResList652],
+
+
+ ?line {STRes653,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ157.xsd','./msxsdtest/identityConstraint',valid),
+ STResList654 = [STRes653|STResList653],
+
+
+ ?line {STRes654,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ158.xsd','./msxsdtest/identityConstraint',valid),
+ STResList655 = [STRes654|STResList654],
+
+
+ ?line {STRes655,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ159.xsd','./msxsdtest/identityConstraint',valid),
+ STResList656 = [STRes655|STResList655],
+
+
+ ?line {STRes656,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ160.xsd','./msxsdtest/identityConstraint',valid),
+ STResList657 = [STRes656|STResList656],
+
+
+ ?line {STRes657,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ161.xsd','./msxsdtest/identityConstraint',valid),
+ STResList658 = [STRes657|STResList657],
+
+
+ ?line {STRes658,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ162.xsd','./msxsdtest/identityConstraint',valid),
+ STResList659 = [STRes658|STResList658],
+
+
+ ?line {STRes659,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ163.xsd','./msxsdtest/identityConstraint',valid),
+ STResList660 = [STRes659|STResList659],
+
+
+ ?line {STRes660,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ164.xsd','./msxsdtest/identityConstraint',valid),
+ STResList661 = [STRes660|STResList660],
+
+
+ ?line {STRes661,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ165.xsd','./msxsdtest/identityConstraint',valid),
+ STResList662 = [STRes661|STResList661],
+
+
+ ?line {STRes662,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ166.xsd','./msxsdtest/identityConstraint',valid),
+ STResList663 = [STRes662|STResList662],
+
+
+ ?line {STRes663,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ167.xsd','./msxsdtest/identityConstraint',valid),
+ STResList664 = [STRes663|STResList663],
+
+
+ ?line {STRes664,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ168.xsd','./msxsdtest/identityConstraint',valid),
+ STResList665 = [STRes664|STResList664],
+
+
+ ?line {STRes665,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ169.xsd','./msxsdtest/identityConstraint',valid),
+ STResList666 = [STRes665|STResList665],
+
+
+ ?line {STRes666,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ170.xsd','./msxsdtest/identityConstraint',valid),
+ STResList667 = [STRes666|STResList666],
+
+
+ ?line {STRes667,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ171.xsd','./msxsdtest/identityConstraint',valid),
+ STResList668 = [STRes667|STResList667],
+
+
+ ?line {STRes668,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ172.xsd','./msxsdtest/identityConstraint',valid),
+ STResList669 = [STRes668|STResList668],
+
+
+ ?line {STRes669,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ173.xsd','./msxsdtest/identityConstraint',valid),
+ STResList670 = [STRes669|STResList669],
+
+
+ ?line {STRes670,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ174.xsd','./msxsdtest/identityConstraint',valid),
+ STResList671 = [STRes670|STResList670],
+
+
+ ?line {STRes671,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ175.xsd','./msxsdtest/identityConstraint',valid),
+ STResList672 = [STRes671|STResList671],
+
+
+ ?line {STRes672,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ176.xsd','./msxsdtest/identityConstraint',valid),
+ STResList673 = [STRes672|STResList672],
+
+
+ ?line {STRes673,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ177.xsd','./msxsdtest/identityConstraint',valid),
+ STResList674 = [STRes673|STResList673],
+
+
+ ?line {STRes674,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ178.xsd','./msxsdtest/identityConstraint',valid),
+ STResList675 = [STRes674|STResList674],
+
+
+ ?line {STRes675,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ179.xsd','./msxsdtest/identityConstraint',valid),
+ STResList676 = [STRes675|STResList675],
+
+
+ ?line {STRes676,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ180.xsd','./msxsdtest/identityConstraint',valid),
+ STResList677 = [STRes676|STResList676],
+
+
+ ?line {STRes677,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ181.xsd','./msxsdtest/identityConstraint',valid),
+ STResList678 = [STRes677|STResList677],
+
+
+ ?line {STRes678,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ182.xsd','./msxsdtest/identityConstraint',valid),
+ STResList679 = [STRes678|STResList678],
+
+
+ ?line {STRes679,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ183.xsd','./msxsdtest/identityConstraint',valid),
+ STResList680 = [STRes679|STResList679],
+
+
+ ?line {STRes680,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ184.xsd','./msxsdtest/identityConstraint',valid),
+ STResList681 = [STRes680|STResList680],
+
+
+ ?line {STRes681,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ185.xsd','./msxsdtest/identityConstraint',valid),
+ STResList682 = [STRes681|STResList681],
+
+
+ ?line {STRes682,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ186.xsd','./msxsdtest/identityConstraint',valid),
+ STResList683 = [STRes682|STResList682],
+
+
+ ?line {STRes683,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ187.xsd','./msxsdtest/identityConstraint',valid),
+ STResList684 = [STRes683|STResList683],
+
+
+ ?line {STRes684,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ188.xsd','./msxsdtest/identityConstraint',valid),
+ STResList685 = [STRes684|STResList684],
+
+
+ ?line {STRes685,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ189.xsd','./msxsdtest/identityConstraint',valid),
+ STResList686 = [STRes685|STResList685],
+
+
+ ?line {STRes686,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ190.xsd','./msxsdtest/identityConstraint',valid),
+ STResList687 = [STRes686|STResList686],
+
+
+ ?line {STRes687,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ191.xsd','./msxsdtest/identityConstraint',valid),
+ STResList688 = [STRes687|STResList687],
+
+
+ ?line {STRes688,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ192.xsd','./msxsdtest/identityConstraint',valid),
+ STResList689 = [STRes688|STResList688],
+
+
+ ?line {STRes689,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ193.xsd','./msxsdtest/identityConstraint',valid),
+ STResList690 = [STRes689|STResList689],
+
+
+ ?line {STRes690,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ194.xsd','./msxsdtest/identityConstraint',valid),
+ STResList691 = [STRes690|STResList690],
+
+
+ ?line {STRes691,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ195.xsd','./msxsdtest/identityConstraint',valid),
+ STResList692 = [STRes691|STResList691],
+
+
+ ?line {STRes692,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ196.xsd','./msxsdtest/identityConstraint',valid),
+ STResList693 = [STRes692|STResList692],
+
+
+ ?line {STRes693,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ197.xsd','./msxsdtest/identityConstraint',valid),
+ STResList694 = [STRes693|STResList693],
+
+
+ ?line {STRes694,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ198.xsd','./msxsdtest/identityConstraint',valid),
+ STResList695 = [STRes694|STResList694],
+
+
+ ?line {STRes695,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ199.xsd','./msxsdtest/identityConstraint',valid),
+ STResList696 = [STRes695|STResList695],
+
+
+ ?line {STRes696,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ200.xsd','./msxsdtest/identityConstraint',valid),
+ STResList697 = [STRes696|STResList696],
+
+
+ ?line {STRes697,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ201.xsd','./msxsdtest/identityConstraint',valid),
+ STResList698 = [STRes697|STResList697],
+
+
+ ?line {STRes698,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ202.xsd','./msxsdtest/identityConstraint',valid),
+ STResList699 = [STRes698|STResList698],
+
+
+ ?line {STRes699,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ203.xsd','./msxsdtest/identityConstraint',valid),
+ STResList700 = [STRes699|STResList699],
+
+
+ ?line {STRes700,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ204.xsd','./msxsdtest/identityConstraint',valid),
+ STResList701 = [STRes700|STResList700],
+
+
+ ?line {STRes701,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ205.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList702 = [STRes701|STResList701],
+
+
+ ?line {STRes702,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ206.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList703 = [STRes702|STResList702],
+
+
+ ?line {STRes703,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ207.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList704 = [STRes703|STResList703],
+
+
+ ?line {STRes704,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ208.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList705 = [STRes704|STResList704],
+
+
+ ?line {STRes705,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ209.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList706 = [STRes705|STResList705],
+
+
+ ?line {STRes706,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idJ210.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList707 = [STRes706|STResList706],
+
+
+ ?line {STRes707,S707} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idK001.xsd','./msxsdtest/identityConstraint',valid),
+ STResList708 = [STRes707|STResList707],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idK001.xml','./msxsdtest/identityConstraint',valid,S707),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes708,S708} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idK002.xsd','./msxsdtest/identityConstraint',valid),
+ STResList709 = [STRes708|STResList708],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idK002.xml','./msxsdtest/identityConstraint',valid,S708),
+ ITResList95 = [ITRes94|ITResList94],
+
+
+ ?line {STRes709,S709} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idK003.xsd','./msxsdtest/identityConstraint',valid),
+ STResList710 = [STRes709|STResList709],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idK003.xml','./msxsdtest/identityConstraint',invalid,S709),
+ ITResList96 = [ITRes95|ITResList95],
+
+
+ ?line {STRes710,S710} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idK004.xsd','./msxsdtest/identityConstraint',valid),
+ STResList711 = [STRes710|STResList710],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idK004.xml','./msxsdtest/identityConstraint',valid,S710),
+ ITResList97 = [ITRes96|ITResList96],
+
+
+ ?line {STRes711,S711} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idK005.xsd','./msxsdtest/identityConstraint',valid),
+ STResList712 = [STRes711|STResList711],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idK005.xml','./msxsdtest/identityConstraint',valid,S711),
+ ITResList98 = [ITRes97|ITResList97],
+
+
+ ?line {STRes712,S712} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idK006.xsd','./msxsdtest/identityConstraint',valid),
+ STResList713 = [STRes712|STResList712],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idK006.xml','./msxsdtest/identityConstraint',valid,S712),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes713,S713} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idK007.xsd','./msxsdtest/identityConstraint',valid),
+ STResList714 = [STRes713|STResList713],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idK007.xml','./msxsdtest/identityConstraint',valid,S713),
+ ITResList100 = [ITRes99|ITResList99],
+
+
+ ?line {STRes714,S714} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idK008.xsd','./msxsdtest/identityConstraint',valid),
+ STResList715 = [STRes714|STResList714],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idK008.xml','./msxsdtest/identityConstraint',valid,S714),
+ ITResList101 = [ITRes100|ITResList100],
+
+
+ ?line {STRes715,S715} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idK009.xsd','./msxsdtest/identityConstraint',valid),
+ STResList716 = [STRes715|STResList715],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idK009.xml','./msxsdtest/identityConstraint',valid,S715),
+ ITResList102 = [ITRes101|ITResList101],
+
+
+ ?line {STRes716,S716} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idK010.xsd','./msxsdtest/identityConstraint',valid),
+ STResList717 = [STRes716|STResList716],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idK010.xml','./msxsdtest/identityConstraint',valid,S716),
+ ITResList103 = [ITRes102|ITResList102],
+
+
+ ?line {STRes717,S717} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idK011.xsd','./msxsdtest/identityConstraint',valid),
+ STResList718 = [STRes717|STResList717],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idK011.xml','./msxsdtest/identityConstraint',valid,S717),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes718,S718} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idK012.xsd','./msxsdtest/identityConstraint',valid),
+ STResList719 = [STRes718|STResList718],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idK012.xml','./msxsdtest/identityConstraint',invalid,S718),
+ ITResList105 = [ITRes104|ITResList104],
+
+
+ ?line {STRes719,S719} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idK013.xsd','./msxsdtest/identityConstraint',valid),
+ STResList720 = [STRes719|STResList719],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idK013.xml','./msxsdtest/identityConstraint',valid,S719),
+ ITResList106 = [ITRes105|ITResList105],
+
+
+ ?line {STRes720,S720} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idK014.xsd','./msxsdtest/identityConstraint',valid),
+ STResList721 = [STRes720|STResList720],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idK014.xml','./msxsdtest/identityConstraint',valid,S720),
+ ITResList107 = [ITRes106|ITResList106],
+
+
+ ?line {STRes721,S721} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idK015.xsd','./msxsdtest/identityConstraint',valid),
+ STResList722 = [STRes721|STResList721],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idK015.xml','./msxsdtest/identityConstraint',valid,S721),
+ ITResList108 = [ITRes107|ITResList107],
+
+
+ ?line {STRes722,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idK016.xsd','./msxsdtest/identityConstraint',invalid),
+ STResList723 = [STRes722|STResList722],
+
+
+ ?line {STRes723,S723} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idK017.xsd','./msxsdtest/identityConstraint',valid),
+ STResList724 = [STRes723|STResList723],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idK017.xml','./msxsdtest/identityConstraint',valid,S723),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes724,S724} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL001.xsd','./msxsdtest/identityConstraint',valid),
+ STResList725 = [STRes724|STResList724],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL001.xml','./msxsdtest/identityConstraint',valid,S724),
+ ITResList110 = [ITRes109|ITResList109],
+
+
+ ?line {STRes725,S725} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL002.xsd','./msxsdtest/identityConstraint',valid),
+ STResList726 = [STRes725|STResList725],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL002.xml','./msxsdtest/identityConstraint',invalid,S725),
+ ITResList111 = [ITRes110|ITResList110],
+
+
+ ?line {STRes726,S726} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL003.xsd','./msxsdtest/identityConstraint',valid),
+ STResList727 = [STRes726|STResList726],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL003.xml','./msxsdtest/identityConstraint',valid,S726),
+ ITResList112 = [ITRes111|ITResList111],
+
+
+ ?line {STRes727,S727} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL004.xsd','./msxsdtest/identityConstraint',valid),
+ STResList728 = [STRes727|STResList727],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL004.xml','./msxsdtest/identityConstraint',valid,S727),
+ ITResList113 = [ITRes112|ITResList112],
+
+
+ ?line {STRes728,S728} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL005.xsd','./msxsdtest/identityConstraint',valid),
+ STResList729 = [STRes728|STResList728],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL005.xml','./msxsdtest/identityConstraint',valid,S728),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes729,S729} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL006.xsd','./msxsdtest/identityConstraint',valid),
+ STResList730 = [STRes729|STResList729],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL006.xml','./msxsdtest/identityConstraint',invalid,S729),
+ ITResList115 = [ITRes114|ITResList114],
+
+
+ ?line {STRes730,S730} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL007.xsd','./msxsdtest/identityConstraint',valid),
+ STResList731 = [STRes730|STResList730],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL007.xml','./msxsdtest/identityConstraint',invalid,S730),
+ ITResList116 = [ITRes115|ITResList115],
+
+
+ ?line {STRes731,S731} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL008.xsd','./msxsdtest/identityConstraint',valid),
+ STResList732 = [STRes731|STResList731],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL008.xml','./msxsdtest/identityConstraint',valid,S731),
+ ITResList117 = [ITRes116|ITResList116],
+
+
+ ?line {STRes732,S732} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL009.xsd','./msxsdtest/identityConstraint',valid),
+ STResList733 = [STRes732|STResList732],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL009.xml','./msxsdtest/identityConstraint',valid,S732),
+ ITResList118 = [ITRes117|ITResList117],
+
+
+ ?line {STRes733,S733} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL010.xsd','./msxsdtest/identityConstraint',valid),
+ STResList734 = [STRes733|STResList733],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL010.xml','./msxsdtest/identityConstraint',valid,S733),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes734,S734} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL011.xsd','./msxsdtest/identityConstraint',valid),
+ STResList735 = [STRes734|STResList734],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL011.xml','./msxsdtest/identityConstraint',invalid,S734),
+ ITResList120 = [ITRes119|ITResList119],
+
+
+ ?line {STRes735,S735} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL012.xsd','./msxsdtest/identityConstraint',valid),
+ STResList736 = [STRes735|STResList735],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL012.xml','./msxsdtest/identityConstraint',invalid,S735),
+ ITResList121 = [ITRes120|ITResList120],
+
+
+ ?line {STRes736,S736} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL013.xsd','./msxsdtest/identityConstraint',valid),
+ STResList737 = [STRes736|STResList736],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL013.xml','./msxsdtest/identityConstraint',valid,S736),
+ ITResList122 = [ITRes121|ITResList121],
+
+
+ ?line {STRes737,S737} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL014.xsd','./msxsdtest/identityConstraint',valid),
+ STResList738 = [STRes737|STResList737],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL014.xml','./msxsdtest/identityConstraint',valid,S737),
+ ITResList123 = [ITRes122|ITResList122],
+
+
+ ?line {STRes738,S738} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL015.xsd','./msxsdtest/identityConstraint',valid),
+ STResList739 = [STRes738|STResList738],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL015.xml','./msxsdtest/identityConstraint',invalid,S738),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes739,S739} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL016.xsd','./msxsdtest/identityConstraint',valid),
+ STResList740 = [STRes739|STResList739],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL016.xml','./msxsdtest/identityConstraint',valid,S739),
+ ITResList125 = [ITRes124|ITResList124],
+
+
+ ?line {STRes740,S740} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL017.xsd','./msxsdtest/identityConstraint',valid),
+ STResList741 = [STRes740|STResList740],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL017.xml','./msxsdtest/identityConstraint',valid,S740),
+ ITResList126 = [ITRes125|ITResList125],
+
+
+ ?line {STRes741,S741} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL018.xsd','./msxsdtest/identityConstraint',valid),
+ STResList742 = [STRes741|STResList741],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL018.xml','./msxsdtest/identityConstraint',valid,S741),
+ ITResList127 = [ITRes126|ITResList126],
+
+
+ ?line {STRes742,S742} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL019.xsd','./msxsdtest/identityConstraint',valid),
+ STResList743 = [STRes742|STResList742],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL019.xml','./msxsdtest/identityConstraint',invalid,S742),
+ ITResList128 = [ITRes127|ITResList127],
+
+
+ ?line {STRes743,S743} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL020.xsd','./msxsdtest/identityConstraint',valid),
+ STResList744 = [STRes743|STResList743],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL020.xml','./msxsdtest/identityConstraint',valid,S743),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes744,S744} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL021.xsd','./msxsdtest/identityConstraint',valid),
+ STResList745 = [STRes744|STResList744],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL021.xml','./msxsdtest/identityConstraint',valid,S744),
+ ITResList130 = [ITRes129|ITResList129],
+
+
+ ?line {STRes745,S745} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL022.xsd','./msxsdtest/identityConstraint',valid),
+ STResList746 = [STRes745|STResList745],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL022.xml','./msxsdtest/identityConstraint',invalid,S745),
+ ITResList131 = [ITRes130|ITResList130],
+
+
+ ?line {STRes746,S746} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL023.xsd','./msxsdtest/identityConstraint',valid),
+ STResList747 = [STRes746|STResList746],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL023.xml','./msxsdtest/identityConstraint',valid,S746),
+ ITResList132 = [ITRes131|ITResList131],
+
+
+ ?line {STRes747,S747} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL024.xsd','./msxsdtest/identityConstraint',valid),
+ STResList748 = [STRes747|STResList747],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL024.xml','./msxsdtest/identityConstraint',valid,S747),
+ ITResList133 = [ITRes132|ITResList132],
+
+
+ ?line {STRes748,S748} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL025.xsd','./msxsdtest/identityConstraint',valid),
+ STResList749 = [STRes748|STResList748],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL025.xml','./msxsdtest/identityConstraint',invalid,S748),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes749,S749} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL026.xsd','./msxsdtest/identityConstraint',valid),
+ STResList750 = [STRes749|STResList749],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL026.xml','./msxsdtest/identityConstraint',valid,S749),
+ ITResList135 = [ITRes134|ITResList134],
+
+
+ ?line {STRes750,S750} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL027.xsd','./msxsdtest/identityConstraint',valid),
+ STResList751 = [STRes750|STResList750],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL027.xml','./msxsdtest/identityConstraint',invalid,S750),
+ ITResList136 = [ITRes135|ITResList135],
+
+
+ ?line {STRes751,S751} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL028.xsd','./msxsdtest/identityConstraint',valid),
+ STResList752 = [STRes751|STResList751],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL028.xml','./msxsdtest/identityConstraint',valid,S751),
+ ITResList137 = [ITRes136|ITResList136],
+
+
+ ?line {STRes752,S752} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL029.xsd','./msxsdtest/identityConstraint',valid),
+ STResList753 = [STRes752|STResList752],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL029.xml','./msxsdtest/identityConstraint',valid,S752),
+ ITResList138 = [ITRes137|ITResList137],
+
+
+ ?line {STRes753,S753} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL030.xsd','./msxsdtest/identityConstraint',valid),
+ STResList754 = [STRes753|STResList753],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL030.xml','./msxsdtest/identityConstraint',valid,S753),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ ?line {STRes754,S754} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL031.xsd','./msxsdtest/identityConstraint',valid),
+ STResList755 = [STRes754|STResList754],
+ ?line ITRes139 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL031.xml','./msxsdtest/identityConstraint',invalid,S754),
+ ITResList140 = [ITRes139|ITResList139],
+
+
+ ?line {STRes755,S755} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL032.xsd','./msxsdtest/identityConstraint',valid),
+ STResList756 = [STRes755|STResList755],
+ ?line ITRes140 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL032.xml','./msxsdtest/identityConstraint',invalid,S755),
+ ITResList141 = [ITRes140|ITResList140],
+
+
+ ?line {STRes756,S756} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL033.xsd','./msxsdtest/identityConstraint',valid),
+ STResList757 = [STRes756|STResList756],
+ ?line ITRes141 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL033.xml','./msxsdtest/identityConstraint',valid,S756),
+ ITResList142 = [ITRes141|ITResList141],
+
+
+ ?line {STRes757,S757} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL034.xsd','./msxsdtest/identityConstraint',valid),
+ STResList758 = [STRes757|STResList757],
+ ?line ITRes142 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL034.xml','./msxsdtest/identityConstraint',valid,S757),
+ ITResList143 = [ITRes142|ITResList142],
+
+
+ ?line {STRes758,S758} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL035.xsd','./msxsdtest/identityConstraint',valid),
+ STResList759 = [STRes758|STResList758],
+ ?line ITRes143 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL035.xml','./msxsdtest/identityConstraint',valid,S758),
+ ITResList144 = [ITRes143|ITResList143],
+
+
+ ?line {STRes759,S759} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL036.xsd','./msxsdtest/identityConstraint',valid),
+ STResList760 = [STRes759|STResList759],
+ ?line ITRes144 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL036.xml','./msxsdtest/identityConstraint',invalid,S759),
+ ITResList145 = [ITRes144|ITResList144],
+
+
+ ?line {STRes760,S760} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL037.xsd','./msxsdtest/identityConstraint',valid),
+ STResList761 = [STRes760|STResList760],
+ ?line ITRes145 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL037.xml','./msxsdtest/identityConstraint',invalid,S760),
+ ITResList146 = [ITRes145|ITResList145],
+
+
+ ?line {STRes761,S761} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL038.xsd','./msxsdtest/identityConstraint',valid),
+ STResList762 = [STRes761|STResList761],
+ ?line ITRes146 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL038.xml','./msxsdtest/identityConstraint',valid,S761),
+ ITResList147 = [ITRes146|ITResList146],
+
+
+ ?line {STRes762,S762} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL039.xsd','./msxsdtest/identityConstraint',valid),
+ STResList763 = [STRes762|STResList762],
+ ?line ITRes147 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL039.xml','./msxsdtest/identityConstraint',valid,S762),
+ ITResList148 = [ITRes147|ITResList147],
+
+
+ ?line {STRes763,S763} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL040.xsd','./msxsdtest/identityConstraint',valid),
+ STResList764 = [STRes763|STResList763],
+ ?line ITRes148 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL040.xml','./msxsdtest/identityConstraint',invalid,S763),
+ ITResList149 = [ITRes148|ITResList148],
+
+
+ ?line {STRes764,S764} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL041.xsd','./msxsdtest/identityConstraint',valid),
+ STResList765 = [STRes764|STResList764],
+ ?line ITRes149 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL041.xml','./msxsdtest/identityConstraint',valid,S764),
+ ITResList150 = [ITRes149|ITResList149],
+
+
+ ?line {STRes765,S765} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL042.xsd','./msxsdtest/identityConstraint',valid),
+ STResList766 = [STRes765|STResList765],
+ ?line ITRes150 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL042.xml','./msxsdtest/identityConstraint',valid,S765),
+ ITResList151 = [ITRes150|ITResList150],
+
+
+ ?line {STRes766,S766} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL043.xsd','./msxsdtest/identityConstraint',valid),
+ STResList767 = [STRes766|STResList766],
+ ?line ITRes151 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL043.xml','./msxsdtest/identityConstraint',valid,S766),
+ ITResList152 = [ITRes151|ITResList151],
+
+
+ ?line {STRes767,S767} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL044.xsd','./msxsdtest/identityConstraint',valid),
+ STResList768 = [STRes767|STResList767],
+ ?line ITRes152 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL044.xml','./msxsdtest/identityConstraint',invalid,S767),
+ ITResList153 = [ITRes152|ITResList152],
+
+
+ ?line {STRes768,S768} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL045.xsd','./msxsdtest/identityConstraint',valid),
+ STResList769 = [STRes768|STResList768],
+ ?line ITRes153 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL045.xml','./msxsdtest/identityConstraint',valid,S768),
+ ITResList154 = [ITRes153|ITResList153],
+
+
+ ?line {STRes769,S769} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL046.xsd','./msxsdtest/identityConstraint',valid),
+ STResList770 = [STRes769|STResList769],
+ ?line ITRes154 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL046.xml','./msxsdtest/identityConstraint',valid,S769),
+ ITResList155 = [ITRes154|ITResList154],
+
+
+ ?line {STRes770,S770} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL047.xsd','./msxsdtest/identityConstraint',valid),
+ STResList771 = [STRes770|STResList770],
+ ?line ITRes155 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL047.xml','./msxsdtest/identityConstraint',invalid,S770),
+ ITResList156 = [ITRes155|ITResList155],
+
+
+ ?line {STRes771,S771} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL048.xsd','./msxsdtest/identityConstraint',valid),
+ STResList772 = [STRes771|STResList771],
+ ?line ITRes156 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL048.xml','./msxsdtest/identityConstraint',valid,S771),
+ ITResList157 = [ITRes156|ITResList156],
+
+
+ ?line {STRes772,S772} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL049.xsd','./msxsdtest/identityConstraint',valid),
+ STResList773 = [STRes772|STResList772],
+ ?line ITRes157 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL049.xml','./msxsdtest/identityConstraint',valid,S772),
+ ITResList158 = [ITRes157|ITResList157],
+
+
+ ?line {STRes773,S773} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL050.xsd','./msxsdtest/identityConstraint',valid),
+ STResList774 = [STRes773|STResList773],
+ ?line ITRes158 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL050.xml','./msxsdtest/identityConstraint',invalid,S773),
+ ITResList159 = [ITRes158|ITResList158],
+
+
+ ?line {STRes774,S774} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL051.xsd','./msxsdtest/identityConstraint',valid),
+ STResList775 = [STRes774|STResList774],
+ ?line ITRes159 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL051.xml','./msxsdtest/identityConstraint',valid,S774),
+ ITResList160 = [ITRes159|ITResList159],
+
+
+ ?line {STRes775,S775} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL052.xsd','./msxsdtest/identityConstraint',valid),
+ STResList776 = [STRes775|STResList775],
+ ?line ITRes160 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL052.xml','./msxsdtest/identityConstraint',invalid,S775),
+ ITResList161 = [ITRes160|ITResList160],
+
+
+ ?line {STRes776,S776} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL053.xsd','./msxsdtest/identityConstraint',valid),
+ STResList777 = [STRes776|STResList776],
+ ?line ITRes161 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL053.xml','./msxsdtest/identityConstraint',valid,S776),
+ ITResList162 = [ITRes161|ITResList161],
+
+
+ ?line {STRes777,S777} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL054.xsd','./msxsdtest/identityConstraint',valid),
+ STResList778 = [STRes777|STResList777],
+ ?line ITRes162 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL054.xml','./msxsdtest/identityConstraint',valid,S777),
+ ITResList163 = [ITRes162|ITResList162],
+
+
+ ?line {STRes778,S778} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL055.xsd','./msxsdtest/identityConstraint',valid),
+ STResList779 = [STRes778|STResList778],
+ ?line ITRes163 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL055.xml','./msxsdtest/identityConstraint',valid,S778),
+ ITResList164 = [ITRes163|ITResList163],
+
+
+ ?line {STRes779,S779} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL056.xsd','./msxsdtest/identityConstraint',valid),
+ STResList780 = [STRes779|STResList779],
+ ?line ITRes164 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL056.xml','./msxsdtest/identityConstraint',invalid,S779),
+ ITResList165 = [ITRes164|ITResList164],
+
+
+ ?line {STRes780,S780} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL057.xsd','./msxsdtest/identityConstraint',valid),
+ STResList781 = [STRes780|STResList780],
+ ?line ITRes165 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL057.xml','./msxsdtest/identityConstraint',invalid,S780),
+ ITResList166 = [ITRes165|ITResList165],
+
+
+ ?line {STRes781,S781} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL058.xsd','./msxsdtest/identityConstraint',valid),
+ STResList782 = [STRes781|STResList781],
+ ?line ITRes166 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL058.xml','./msxsdtest/identityConstraint',valid,S781),
+ ITResList167 = [ITRes166|ITResList166],
+
+
+ ?line {STRes782,S782} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL059.xsd','./msxsdtest/identityConstraint',valid),
+ STResList783 = [STRes782|STResList782],
+ ?line ITRes167 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL059.xml','./msxsdtest/identityConstraint',valid,S782),
+ ITResList168 = [ITRes167|ITResList167],
+
+
+ ?line {STRes783,S783} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL060.xsd','./msxsdtest/identityConstraint',valid),
+ STResList784 = [STRes783|STResList783],
+ ?line ITRes168 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL060.xml','./msxsdtest/identityConstraint',valid,S783),
+ ITResList169 = [ITRes168|ITResList168],
+
+
+ ?line {STRes784,S784} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL061.xsd','./msxsdtest/identityConstraint',valid),
+ STResList785 = [STRes784|STResList784],
+ ?line ITRes169 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL061.xml','./msxsdtest/identityConstraint',invalid,S784),
+ ITResList170 = [ITRes169|ITResList169],
+
+
+ ?line {STRes785,S785} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL062.xsd','./msxsdtest/identityConstraint',valid),
+ STResList786 = [STRes785|STResList785],
+ ?line ITRes170 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL062.xml','./msxsdtest/identityConstraint',invalid,S785),
+ ITResList171 = [ITRes170|ITResList170],
+
+
+ ?line {STRes786,S786} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL063.xsd','./msxsdtest/identityConstraint',valid),
+ STResList787 = [STRes786|STResList786],
+ ?line ITRes171 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL063.xml','./msxsdtest/identityConstraint',valid,S786),
+ ITResList172 = [ITRes171|ITResList171],
+
+
+ ?line {STRes787,S787} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL064.xsd','./msxsdtest/identityConstraint',valid),
+ STResList788 = [STRes787|STResList787],
+ ?line ITRes172 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL064.xml','./msxsdtest/identityConstraint',valid,S787),
+ ITResList173 = [ITRes172|ITResList172],
+
+
+ ?line {STRes788,S788} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL065.xsd','./msxsdtest/identityConstraint',valid),
+ STResList789 = [STRes788|STResList788],
+ ?line ITRes173 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL065.xml','./msxsdtest/identityConstraint',invalid,S788),
+ ITResList174 = [ITRes173|ITResList173],
+
+
+ ?line {STRes789,S789} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL066.xsd','./msxsdtest/identityConstraint',valid),
+ STResList790 = [STRes789|STResList789],
+ ?line ITRes174 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL066.xml','./msxsdtest/identityConstraint',valid,S789),
+ ITResList175 = [ITRes174|ITResList174],
+
+
+ ?line {STRes790,S790} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL067.xsd','./msxsdtest/identityConstraint',valid),
+ STResList791 = [STRes790|STResList790],
+ ?line ITRes175 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL067.xml','./msxsdtest/identityConstraint',valid,S790),
+ ITResList176 = [ITRes175|ITResList175],
+
+
+ ?line {STRes791,S791} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL068.xsd','./msxsdtest/identityConstraint',valid),
+ STResList792 = [STRes791|STResList791],
+ ?line ITRes176 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL068.xml','./msxsdtest/identityConstraint',valid,S791),
+ ITResList177 = [ITRes176|ITResList176],
+
+
+ ?line {STRes792,S792} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL069.xsd','./msxsdtest/identityConstraint',valid),
+ STResList793 = [STRes792|STResList792],
+ ?line ITRes177 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL069.xml','./msxsdtest/identityConstraint',invalid,S792),
+ ITResList178 = [ITRes177|ITResList177],
+
+
+ ?line {STRes793,S793} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL070.xsd','./msxsdtest/identityConstraint',valid),
+ STResList794 = [STRes793|STResList793],
+ ?line ITRes178 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL070.xml','./msxsdtest/identityConstraint',valid,S793),
+ ITResList179 = [ITRes178|ITResList178],
+
+
+ ?line {STRes794,S794} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL071.xsd','./msxsdtest/identityConstraint',valid),
+ STResList795 = [STRes794|STResList794],
+ ?line ITRes179 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL071.xml','./msxsdtest/identityConstraint',valid,S794),
+ ITResList180 = [ITRes179|ITResList179],
+
+
+ ?line {STRes795,S795} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL072.xsd','./msxsdtest/identityConstraint',valid),
+ STResList796 = [STRes795|STResList795],
+ ?line ITRes180 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL072.xml','./msxsdtest/identityConstraint',invalid,S795),
+ ITResList181 = [ITRes180|ITResList180],
+
+
+ ?line {STRes796,S796} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL073.xsd','./msxsdtest/identityConstraint',valid),
+ STResList797 = [STRes796|STResList796],
+ ?line ITRes181 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL073.xml','./msxsdtest/identityConstraint',valid,S796),
+ ITResList182 = [ITRes181|ITResList181],
+
+
+ ?line {STRes797,S797} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL074.xsd','./msxsdtest/identityConstraint',valid),
+ STResList798 = [STRes797|STResList797],
+ ?line ITRes182 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL074.xml','./msxsdtest/identityConstraint',valid,S797),
+ ITResList183 = [ITRes182|ITResList182],
+
+
+ ?line {STRes798,S798} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL075.xsd','./msxsdtest/identityConstraint',valid),
+ STResList799 = [STRes798|STResList798],
+ ?line ITRes183 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL075.xml','./msxsdtest/identityConstraint',invalid,S798),
+ ITResList184 = [ITRes183|ITResList183],
+
+
+ ?line {STRes799,S799} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL076.xsd','./msxsdtest/identityConstraint',valid),
+ STResList800 = [STRes799|STResList799],
+ ?line ITRes184 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL076.xml','./msxsdtest/identityConstraint',valid,S799),
+ ITResList185 = [ITRes184|ITResList184],
+
+
+ ?line {STRes800,S800} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL077.xsd','./msxsdtest/identityConstraint',valid),
+ STResList801 = [STRes800|STResList800],
+ ?line ITRes185 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL077.xml','./msxsdtest/identityConstraint',valid,S800),
+ ITResList186 = [ITRes185|ITResList185],
+
+
+ ?line {STRes801,S801} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL078.xsd','./msxsdtest/identityConstraint',valid),
+ STResList802 = [STRes801|STResList801],
+ ?line ITRes186 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL078.xml','./msxsdtest/identityConstraint',valid,S801),
+ ITResList187 = [ITRes186|ITResList186],
+
+
+ ?line {STRes802,S802} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL079.xsd','./msxsdtest/identityConstraint',valid),
+ STResList803 = [STRes802|STResList802],
+ ?line ITRes187 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL079.xml','./msxsdtest/identityConstraint',invalid,S802),
+ ITResList188 = [ITRes187|ITResList187],
+
+
+ ?line {STRes803,S803} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL080.xsd','./msxsdtest/identityConstraint',valid),
+ STResList804 = [STRes803|STResList803],
+ ?line ITRes188 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL080.xml','./msxsdtest/identityConstraint',invalid,S803),
+ ITResList189 = [ITRes188|ITResList188],
+
+
+ ?line {STRes804,S804} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL081.xsd','./msxsdtest/identityConstraint',valid),
+ STResList805 = [STRes804|STResList804],
+ ?line ITRes189 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL081.xml','./msxsdtest/identityConstraint',invalid,S804),
+ ITResList190 = [ITRes189|ITResList189],
+
+
+ ?line {STRes805,S805} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL082.xsd','./msxsdtest/identityConstraint',valid),
+ STResList806 = [STRes805|STResList805],
+ ?line ITRes190 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL082.xml','./msxsdtest/identityConstraint',valid,S805),
+ ITResList191 = [ITRes190|ITResList190],
+
+
+ ?line {STRes806,S806} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL083.xsd','./msxsdtest/identityConstraint',valid),
+ STResList807 = [STRes806|STResList806],
+ ?line ITRes191 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL083.xml','./msxsdtest/identityConstraint',invalid,S806),
+ ITResList192 = [ITRes191|ITResList191],
+
+
+ ?line {STRes807,S807} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL084.xsd','./msxsdtest/identityConstraint',valid),
+ STResList808 = [STRes807|STResList807],
+ ?line ITRes192 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL084.xml','./msxsdtest/identityConstraint',valid,S807),
+ ITResList193 = [ITRes192|ITResList192],
+
+
+ ?line {STRes808,S808} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL085.xsd','./msxsdtest/identityConstraint',valid),
+ STResList809 = [STRes808|STResList808],
+ ?line ITRes193 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL085.xml','./msxsdtest/identityConstraint',invalid,S808),
+ ITResList194 = [ITRes193|ITResList193],
+
+
+ ?line {STRes809,S809} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL086.xsd','./msxsdtest/identityConstraint',valid),
+ STResList810 = [STRes809|STResList809],
+ ?line ITRes194 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL086.xml','./msxsdtest/identityConstraint',valid,S809),
+ ITResList195 = [ITRes194|ITResList194],
+
+
+ ?line {STRes810,S810} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL087.xsd','./msxsdtest/identityConstraint',valid),
+ STResList811 = [STRes810|STResList810],
+ ?line ITRes195 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL087.xml','./msxsdtest/identityConstraint',invalid,S810),
+ ITResList196 = [ITRes195|ITResList195],
+
+
+ ?line {STRes811,S811} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL088.xsd','./msxsdtest/identityConstraint',valid),
+ STResList812 = [STRes811|STResList811],
+ ?line ITRes196 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL088.xml','./msxsdtest/identityConstraint',valid,S811),
+ ITResList197 = [ITRes196|ITResList196],
+
+
+ ?line {STRes812,S812} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL089.xsd','./msxsdtest/identityConstraint',valid),
+ STResList813 = [STRes812|STResList812],
+ ?line ITRes197 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL089.xml','./msxsdtest/identityConstraint',invalid,S812),
+ ITResList198 = [ITRes197|ITResList197],
+
+
+ ?line {STRes813,S813} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL090.xsd','./msxsdtest/identityConstraint',valid),
+ STResList814 = [STRes813|STResList813],
+ ?line ITRes198 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL090.xml','./msxsdtest/identityConstraint',valid,S813),
+ ITResList199 = [ITRes198|ITResList198],
+
+
+ ?line {STRes814,S814} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL091.xsd','./msxsdtest/identityConstraint',valid),
+ STResList815 = [STRes814|STResList814],
+ ?line ITRes199 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL091.xml','./msxsdtest/identityConstraint',invalid,S814),
+ ITResList200 = [ITRes199|ITResList199],
+
+
+ ?line {STRes815,S815} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL092.xsd','./msxsdtest/identityConstraint',valid),
+ STResList816 = [STRes815|STResList815],
+ ?line ITRes200 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL092.xml','./msxsdtest/identityConstraint',valid,S815),
+ ITResList201 = [ITRes200|ITResList200],
+
+
+ ?line {STRes816,S816} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL093.xsd','./msxsdtest/identityConstraint',valid),
+ STResList817 = [STRes816|STResList816],
+ ?line ITRes201 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL093.xml','./msxsdtest/identityConstraint',invalid,S816),
+ ITResList202 = [ITRes201|ITResList201],
+
+
+ ?line {STRes817,S817} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL094.xsd','./msxsdtest/identityConstraint',valid),
+ STResList818 = [STRes817|STResList817],
+ ?line ITRes202 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL094.xml','./msxsdtest/identityConstraint',valid,S817),
+ ITResList203 = [ITRes202|ITResList202],
+
+
+ ?line {STRes818,S818} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL095.xsd','./msxsdtest/identityConstraint',valid),
+ STResList819 = [STRes818|STResList818],
+ ?line ITRes203 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL095.xml','./msxsdtest/identityConstraint',invalid,S818),
+ ITResList204 = [ITRes203|ITResList203],
+
+
+ ?line {STRes819,S819} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL096.xsd','./msxsdtest/identityConstraint',valid),
+ STResList820 = [STRes819|STResList819],
+ ?line ITRes204 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL096.xml','./msxsdtest/identityConstraint',valid,S819),
+ ITResList205 = [ITRes204|ITResList204],
+
+
+ ?line {STRes820,S820} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL097.xsd','./msxsdtest/identityConstraint',valid),
+ STResList821 = [STRes820|STResList820],
+ ?line ITRes205 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL097.xml','./msxsdtest/identityConstraint',invalid,S820),
+ ITResList206 = [ITRes205|ITResList205],
+
+
+ ?line {STRes821,S821} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL098.xsd','./msxsdtest/identityConstraint',valid),
+ STResList822 = [STRes821|STResList821],
+ ?line ITRes206 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL098.xml','./msxsdtest/identityConstraint',valid,S821),
+ ITResList207 = [ITRes206|ITResList206],
+
+
+ ?line {STRes822,S822} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL099.xsd','./msxsdtest/identityConstraint',valid),
+ STResList823 = [STRes822|STResList822],
+ ?line ITRes207 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL099.xml','./msxsdtest/identityConstraint',invalid,S822),
+ ITResList208 = [ITRes207|ITResList207],
+
+
+ ?line {STRes823,S823} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL100.xsd','./msxsdtest/identityConstraint',valid),
+ STResList824 = [STRes823|STResList823],
+ ?line ITRes208 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL100.xml','./msxsdtest/identityConstraint',valid,S823),
+ ITResList209 = [ITRes208|ITResList208],
+
+
+ ?line {STRes824,S824} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL101.xsd','./msxsdtest/identityConstraint',valid),
+ STResList825 = [STRes824|STResList824],
+ ?line ITRes209 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL101.xml','./msxsdtest/identityConstraint',invalid,S824),
+ ITResList210 = [ITRes209|ITResList209],
+
+
+ ?line {STRes825,S825} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL102.xsd','./msxsdtest/identityConstraint',valid),
+ STResList826 = [STRes825|STResList825],
+ ?line ITRes210 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL102.xml','./msxsdtest/identityConstraint',valid,S825),
+ ITResList211 = [ITRes210|ITResList210],
+
+
+ ?line {STRes826,S826} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idL103.xsd','./msxsdtest/identityConstraint',valid),
+ STResList827 = [STRes826|STResList826],
+ ?line ITRes211 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idL103.xml','./msxsdtest/identityConstraint',invalid,S826),
+ ITResList212 = [ITRes211|ITResList211],
+
+
+ ?line {STRes827,S827} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idZ001.xsd','./msxsdtest/identityConstraint',valid),
+ STResList828 = [STRes827|STResList827],
+ ?line ITRes212 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idZ001.xml','./msxsdtest/identityConstraint',invalid,S827),
+ ITResList213 = [ITRes212|ITResList212],
+
+
+ ?line {STRes828,S828} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idZ002.xsd','./msxsdtest/identityConstraint',valid),
+ STResList829 = [STRes828|STResList828],
+ ?line ITRes213 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idZ002.xml','./msxsdtest/identityConstraint',invalid,S828),
+ ITResList214 = [ITRes213|ITResList213],
+
+
+
+
+ ?line {STRes829,S829} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/identityConstraint/idZ004.xsd','./msxsdtest/identityConstraint',valid),
+ STResList830 = [STRes829|STResList829],
+ ?line ITRes214 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/identityConstraint/idZ004.xml','./msxsdtest/identityConstraint',invalid,S829),
+ ITResList215 = [ITRes214|ITResList214],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList830,ITResList215).
+
+%% model groups (ALL).
+
+mgABCD(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgA001.xsd','./msxsdtest/ModelGroups',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgA001.xml','./msxsdtest/ModelGroups',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes1,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgA002.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList2 = [STRes1|STResList1],
+
+
+ ?line {STRes2,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgA003.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList3 = [STRes2|STResList2],
+
+
+ ?line {STRes3,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgA004.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList4 = [STRes3|STResList3],
+
+
+ ?line {STRes4,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgA005.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList5 = [STRes4|STResList4],
+
+
+ ?line {STRes5,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgA006.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList6 = [STRes5|STResList5],
+
+
+ ?line {STRes6,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgA007.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList7 = [STRes6|STResList6],
+
+
+ ?line {STRes7,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgA008.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList8 = [STRes7|STResList7],
+
+
+ ?line {STRes8,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgA009.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList9 = [STRes8|STResList8],
+
+
+ ?line {STRes9,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgA010.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList10 = [STRes9|STResList9],
+
+
+ ?line {STRes10,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgA011.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList11 = [STRes10|STResList10],
+
+
+ ?line {STRes11,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgA012.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList12 = [STRes11|STResList11],
+
+
+ ?line {STRes12,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgA013.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList13 = [STRes12|STResList12],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgA014.xsd','./msxsdtest/ModelGroups',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgA014.xml','./msxsdtest/ModelGroups',valid,S13),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgA015.xsd','./msxsdtest/ModelGroups',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgA015.xml','./msxsdtest/ModelGroups',valid,S14),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgA016.xsd','./msxsdtest/ModelGroups',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgA016.xml','./msxsdtest/ModelGroups',valid,S15),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgA017.xsd','./msxsdtest/ModelGroups',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgA017.xml','./msxsdtest/ModelGroups',valid,S16),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes17,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgA018.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList18 = [STRes17|STResList17],
+
+
+ ?line {STRes18,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgA019.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList19 = [STRes18|STResList18],
+
+
+ ?line {STRes19,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAa001.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList20 = [STRes19|STResList19],
+
+
+ ?line {STRes20,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAa002.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList21 = [STRes20|STResList20],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAa003.xsd','./msxsdtest/ModelGroups',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgAa003.xml','./msxsdtest/ModelGroups',valid,S21),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes22,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAa004.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList23 = [STRes22|STResList22],
+
+
+ ?line {STRes23,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAa005.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList24 = [STRes23|STResList23],
+
+
+ ?line {STRes24,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAa006.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList25 = [STRes24|STResList24],
+
+
+ ?line {STRes25,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAa007.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList26 = [STRes25|STResList25],
+
+
+ ?line {STRes26,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAa008.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList27 = [STRes26|STResList26],
+
+
+ ?line {STRes27,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAa009.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList28 = [STRes27|STResList27],
+
+
+ ?line {STRes28,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAa010.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList29 = [STRes28|STResList28],
+
+
+ ?line {STRes29,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAb001.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList30 = [STRes29|STResList29],
+
+
+ ?line {STRes30,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAb002.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList31 = [STRes30|STResList30],
+
+
+ ?line {STRes31,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAb003.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList32 = [STRes31|STResList31],
+
+
+ ?line {STRes32,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAb004.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList33 = [STRes32|STResList32],
+
+
+ ?line {STRes33,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAb005.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList34 = [STRes33|STResList33],
+
+
+ ?line {STRes34,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAb006.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList35 = [STRes34|STResList34],
+
+
+ ?line {STRes35,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAb007.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList36 = [STRes35|STResList35],
+
+
+ ?line {STRes36,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAb008.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList37 = [STRes36|STResList36],
+
+
+ ?line {STRes37,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAb009.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList38 = [STRes37|STResList37],
+
+
+ ?line {STRes38,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgAb010.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList39 = [STRes38|STResList38],
+
+
+ ?line {STRes39,S39} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgB001.xsd','./msxsdtest/ModelGroups',valid),
+ STResList40 = [STRes39|STResList39],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgB001.xml','./msxsdtest/ModelGroups',valid,S39),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes40,S40} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgB002.xsd','./msxsdtest/ModelGroups',valid),
+ STResList41 = [STRes40|STResList40],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgB002.xml','./msxsdtest/ModelGroups',valid,S40),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes41,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgB003.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList42 = [STRes41|STResList41],
+
+
+ ?line {STRes42,S42} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgB004.xsd','./msxsdtest/ModelGroups',valid),
+ STResList43 = [STRes42|STResList42],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgB004.xml','./msxsdtest/ModelGroups',valid,S42),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes43,S43} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgB006.xsd','./msxsdtest/ModelGroups',valid),
+ STResList44 = [STRes43|STResList43],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgB006.xml','./msxsdtest/ModelGroups',valid,S43),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes44,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgB007.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList45 = [STRes44|STResList44],
+
+
+ ?line {STRes45,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgB008.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList46 = [STRes45|STResList45],
+
+
+ ?line {STRes46,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgB009.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList47 = [STRes46|STResList46],
+
+
+ ?line {STRes47,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgB010.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList48 = [STRes47|STResList47],
+
+
+ ?line {STRes48,S48} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgC001.xsd','./msxsdtest/ModelGroups',valid),
+ STResList49 = [STRes48|STResList48],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgC001.xml','./msxsdtest/ModelGroups',invalid,S48),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes49,S49} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgC002.xsd','./msxsdtest/ModelGroups',valid),
+ STResList50 = [STRes49|STResList49],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgC002.xml','./msxsdtest/ModelGroups',valid,S49),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes50,S50} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgC003.xsd','./msxsdtest/ModelGroups',valid),
+ STResList51 = [STRes50|STResList50],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgC003.xml','./msxsdtest/ModelGroups',invalid,S50),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes51,S51} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgC004.xsd','./msxsdtest/ModelGroups',valid),
+ STResList52 = [STRes51|STResList51],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgC004.xml','./msxsdtest/ModelGroups',valid,S51),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes52,S52} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgC005.xsd','./msxsdtest/ModelGroups',valid),
+ STResList53 = [STRes52|STResList52],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgC005.xml','./msxsdtest/ModelGroups',invalid,S52),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes53,S53} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgC006.xsd','./msxsdtest/ModelGroups',valid),
+ STResList54 = [STRes53|STResList53],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgC006.xml','./msxsdtest/ModelGroups',valid,S53),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes54,S54} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgC007.xsd','./msxsdtest/ModelGroups',valid),
+ STResList55 = [STRes54|STResList54],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgC007.xml','./msxsdtest/ModelGroups',invalid,S54),
+ ITResList17 = [ITRes16|ITResList16],
+
+
+ ?line {STRes55,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgC008.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList56 = [STRes55|STResList55],
+
+
+ ?line {STRes56,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgC009.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList57 = [STRes56|STResList56],
+
+
+ ?line {STRes57,S57} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgC010.xsd','./msxsdtest/ModelGroups',valid),
+ STResList58 = [STRes57|STResList57],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgC010.xml','./msxsdtest/ModelGroups',invalid,S57),
+ ITResList18 = [ITRes17|ITResList17],
+
+
+ ?line {STRes58,S58} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgC011.xsd','./msxsdtest/ModelGroups',valid),
+ STResList59 = [STRes58|STResList58],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgC011.xml','./msxsdtest/ModelGroups',valid,S58),
+ ITResList19 = [ITRes18|ITResList18],
+
+
+ ?line {STRes59,S59} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgC012.xsd','./msxsdtest/ModelGroups',valid),
+ STResList60 = [STRes59|STResList59],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgC012.xml','./msxsdtest/ModelGroups',invalid,S59),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes60,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgC013.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList61 = [STRes60|STResList60],
+
+
+ ?line {STRes61,S61} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgC014.xsd','./msxsdtest/ModelGroups',valid),
+ STResList62 = [STRes61|STResList61],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgC014.xml','./msxsdtest/ModelGroups',valid,S61),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes62,S62} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgD001.xsd','./msxsdtest/ModelGroups',valid),
+ STResList63 = [STRes62|STResList62],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgD001.xml','./msxsdtest/ModelGroups',valid,S62),
+ ITResList22 = [ITRes21|ITResList21],
+
+
+ ?line {STRes63,S63} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgD005.xsd','./msxsdtest/ModelGroups',valid),
+ STResList64 = [STRes63|STResList63],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgD005.xml','./msxsdtest/ModelGroups',valid,S63),
+ ITResList23 = [ITRes22|ITResList22],
+
+
+ ?line {STRes64,S64} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgD009.xsd','./msxsdtest/ModelGroups',valid),
+ STResList65 = [STRes64|STResList64],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgD009.xml','./msxsdtest/ModelGroups',valid,S64),
+ ITResList24 = [ITRes23|ITResList23],
+
+
+ ?line {STRes65,S65} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgD013.xsd','./msxsdtest/ModelGroups',valid),
+ STResList66 = [STRes65|STResList65],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgD013.xml','./msxsdtest/ModelGroups',valid,S65),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList66,ITResList25).
+
+%% model groups ( sequence ).
+
+mgEFG(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgE001.xsd','./msxsdtest/ModelGroups',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgE001.xml','./msxsdtest/ModelGroups',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes1,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgE002.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList2 = [STRes1|STResList1],
+
+
+ ?line {STRes2,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgE003.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList3 = [STRes2|STResList2],
+
+
+ ?line {STRes3,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgE004.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList4 = [STRes3|STResList3],
+
+
+ ?line {STRes4,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgE005.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList5 = [STRes4|STResList4],
+
+
+ ?line {STRes5,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgE006.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList6 = [STRes5|STResList5],
+
+
+ ?line {STRes6,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgE007.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList7 = [STRes6|STResList6],
+
+
+ ?line {STRes7,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgE008.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList8 = [STRes7|STResList7],
+
+
+ ?line {STRes8,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgE009.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList9 = [STRes8|STResList8],
+
+
+ ?line {STRes9,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgE010.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList10 = [STRes9|STResList9],
+
+
+ ?line {STRes10,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgE011.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList11 = [STRes10|STResList10],
+
+
+ ?line {STRes11,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgE012.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList12 = [STRes11|STResList11],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgE013.xsd','./msxsdtest/ModelGroups',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgE013.xml','./msxsdtest/ModelGroups',valid,S12),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgE014.xsd','./msxsdtest/ModelGroups',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgE014.xml','./msxsdtest/ModelGroups',valid,S13),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgE015.xsd','./msxsdtest/ModelGroups',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgE015.xml','./msxsdtest/ModelGroups',valid,S14),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgE016.xsd','./msxsdtest/ModelGroups',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgE016.xml','./msxsdtest/ModelGroups',valid,S15),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgE017.xsd','./msxsdtest/ModelGroups',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgE017.xml','./msxsdtest/ModelGroups',valid,S16),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgE018.xsd','./msxsdtest/ModelGroups',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgE018.xml','./msxsdtest/ModelGroups',valid,S17),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes18,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgEa001.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList19 = [STRes18|STResList18],
+
+
+ ?line {STRes19,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgEa002.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList20 = [STRes19|STResList19],
+
+
+ ?line {STRes20,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgEa003.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList21 = [STRes20|STResList20],
+
+
+ ?line {STRes21,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgEa004.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList22 = [STRes21|STResList21],
+
+
+ ?line {STRes22,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgEa005.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList23 = [STRes22|STResList22],
+
+
+ ?line {STRes23,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgEa006.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList24 = [STRes23|STResList23],
+
+
+ ?line {STRes24,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgEa007.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList25 = [STRes24|STResList24],
+
+
+ ?line {STRes25,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgEa008.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList26 = [STRes25|STResList25],
+
+
+ ?line {STRes26,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgEb001.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList27 = [STRes26|STResList26],
+
+
+ ?line {STRes27,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgEb002.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList28 = [STRes27|STResList27],
+
+
+ ?line {STRes28,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgEb003.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList29 = [STRes28|STResList28],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgEb004.xsd','./msxsdtest/ModelGroups',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgEb004.xml','./msxsdtest/ModelGroups',valid,S29),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgEb005.xsd','./msxsdtest/ModelGroups',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgEb005.xml','./msxsdtest/ModelGroups',valid,S30),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes31,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgEb006.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList32 = [STRes31|STResList31],
+
+
+ ?line {STRes32,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgEb007.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList33 = [STRes32|STResList32],
+
+
+ ?line {STRes33,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgEb008.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList34 = [STRes33|STResList33],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF001.xsd','./msxsdtest/ModelGroups',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgF001.xml','./msxsdtest/ModelGroups',valid,S34),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes35,S35} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF002.xsd','./msxsdtest/ModelGroups',valid),
+ STResList36 = [STRes35|STResList35],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgF002.xml','./msxsdtest/ModelGroups',valid,S35),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes36,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF003.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList37 = [STRes36|STResList36],
+
+
+ ?line {STRes37,S37} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF004.xsd','./msxsdtest/ModelGroups',valid),
+ STResList38 = [STRes37|STResList37],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgF004.xml','./msxsdtest/ModelGroups',valid,S37),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes38,S38} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF005.xsd','./msxsdtest/ModelGroups',valid),
+ STResList39 = [STRes38|STResList38],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgF005.xml','./msxsdtest/ModelGroups',valid,S38),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes39,S39} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF006.xsd','./msxsdtest/ModelGroups',valid),
+ STResList40 = [STRes39|STResList39],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgF006.xml','./msxsdtest/ModelGroups',valid,S39),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes40,S40} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF007.xsd','./msxsdtest/ModelGroups',valid),
+ STResList41 = [STRes40|STResList40],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgF007.xml','./msxsdtest/ModelGroups',valid,S40),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes41,S41} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF008.xsd','./msxsdtest/ModelGroups',valid),
+ STResList42 = [STRes41|STResList41],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgF008.xml','./msxsdtest/ModelGroups',valid,S41),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes42,S42} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF009.xsd','./msxsdtest/ModelGroups',valid),
+ STResList43 = [STRes42|STResList42],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgF009.xml','./msxsdtest/ModelGroups',valid,S42),
+ ITResList17 = [ITRes16|ITResList16],
+
+
+ ?line {STRes43,S43} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF010.xsd','./msxsdtest/ModelGroups',valid),
+ STResList44 = [STRes43|STResList43],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgF010.xml','./msxsdtest/ModelGroups',valid,S43),
+ ITResList18 = [ITRes17|ITResList17],
+
+
+ ?line {STRes44,S44} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF011.xsd','./msxsdtest/ModelGroups',valid),
+ STResList45 = [STRes44|STResList44],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgF011.xml','./msxsdtest/ModelGroups',valid,S44),
+ ITResList19 = [ITRes18|ITResList18],
+
+
+ ?line {STRes45,S45} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF012.xsd','./msxsdtest/ModelGroups',valid),
+ STResList46 = [STRes45|STResList45],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgF012.xml','./msxsdtest/ModelGroups',valid,S45),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes46,S46} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF013.xsd','./msxsdtest/ModelGroups',valid),
+ STResList47 = [STRes46|STResList46],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgF013.xml','./msxsdtest/ModelGroups',valid,S46),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes47,S47} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF014.xsd','./msxsdtest/ModelGroups',valid),
+ STResList48 = [STRes47|STResList47],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgF014.xml','./msxsdtest/ModelGroups',valid,S47),
+ ITResList22 = [ITRes21|ITResList21],
+
+
+ ?line {STRes48,S48} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF015.xsd','./msxsdtest/ModelGroups',valid),
+ STResList49 = [STRes48|STResList48],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgF015.xml','./msxsdtest/ModelGroups',valid,S48),
+ ITResList23 = [ITRes22|ITResList22],
+
+
+ ?line {STRes49,S49} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF016.xsd','./msxsdtest/ModelGroups',valid),
+ STResList50 = [STRes49|STResList49],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgF016.xml','./msxsdtest/ModelGroups',valid,S49),
+ ITResList24 = [ITRes23|ITResList23],
+
+
+ ?line {STRes50,S50} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF017.xsd','./msxsdtest/ModelGroups',valid),
+ STResList51 = [STRes50|STResList50],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgF017.xml','./msxsdtest/ModelGroups',valid,S50),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes51,S51} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF018.xsd','./msxsdtest/ModelGroups',valid),
+ STResList52 = [STRes51|STResList51],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgF018.xml','./msxsdtest/ModelGroups',valid,S51),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes52,S52} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF019.xsd','./msxsdtest/ModelGroups',valid),
+ STResList53 = [STRes52|STResList52],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgF019.xml','./msxsdtest/ModelGroups',valid,S52),
+ ITResList27 = [ITRes26|ITResList26],
+
+
+ ?line {STRes53,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF020.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList54 = [STRes53|STResList53],
+
+
+ ?line {STRes54,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF021.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList55 = [STRes54|STResList54],
+
+
+ ?line {STRes55,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF022.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList56 = [STRes55|STResList55],
+
+
+ ?line {STRes56,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgF023.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList57 = [STRes56|STResList56],
+
+
+ ?line {STRes57,S57} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG001.xsd','./msxsdtest/ModelGroups',valid),
+ STResList58 = [STRes57|STResList57],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG001.xml','./msxsdtest/ModelGroups',valid,S57),
+ ITResList28 = [ITRes27|ITResList27],
+
+
+ ?line {STRes58,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG002.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList59 = [STRes58|STResList58],
+
+
+ ?line {STRes59,S59} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG003.xsd','./msxsdtest/ModelGroups',valid),
+ STResList60 = [STRes59|STResList59],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG003.xml','./msxsdtest/ModelGroups',invalid,S59),
+ ITResList29 = [ITRes28|ITResList28],
+
+
+ ?line {STRes60,S60} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG004.xsd','./msxsdtest/ModelGroups',valid),
+ STResList61 = [STRes60|STResList60],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG004.xml','./msxsdtest/ModelGroups',valid,S60),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes61,S61} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG005.xsd','./msxsdtest/ModelGroups',valid),
+ STResList62 = [STRes61|STResList61],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG005.xml','./msxsdtest/ModelGroups',invalid,S61),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes62,S62} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG006.xsd','./msxsdtest/ModelGroups',valid),
+ STResList63 = [STRes62|STResList62],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG006.xml','./msxsdtest/ModelGroups',valid,S62),
+ ITResList32 = [ITRes31|ITResList31],
+
+
+ ?line {STRes63,S63} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG007.xsd','./msxsdtest/ModelGroups',valid),
+ STResList64 = [STRes63|STResList63],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG007.xml','./msxsdtest/ModelGroups',valid,S63),
+ ITResList33 = [ITRes32|ITResList32],
+
+
+ ?line {STRes64,S64} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG008.xsd','./msxsdtest/ModelGroups',valid),
+ STResList65 = [STRes64|STResList64],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG008.xml','./msxsdtest/ModelGroups',invalid,S64),
+ ITResList34 = [ITRes33|ITResList33],
+
+
+ ?line {STRes65,S65} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG009.xsd','./msxsdtest/ModelGroups',valid),
+ STResList66 = [STRes65|STResList65],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG009.xml','./msxsdtest/ModelGroups',valid,S65),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes66,S66} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG010.xsd','./msxsdtest/ModelGroups',valid),
+ STResList67 = [STRes66|STResList66],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG010.xml','./msxsdtest/ModelGroups',valid,S66),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes67,S67} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG011.xsd','./msxsdtest/ModelGroups',valid),
+ STResList68 = [STRes67|STResList67],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG011.xml','./msxsdtest/ModelGroups',invalid,S67),
+ ITResList37 = [ITRes36|ITResList36],
+
+
+ ?line {STRes68,S68} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG012.xsd','./msxsdtest/ModelGroups',valid),
+ STResList69 = [STRes68|STResList68],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG012.xml','./msxsdtest/ModelGroups',valid,S68),
+ ITResList38 = [ITRes37|ITResList37],
+
+
+ ?line {STRes69,S69} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG013.xsd','./msxsdtest/ModelGroups',valid),
+ STResList70 = [STRes69|STResList69],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG013.xml','./msxsdtest/ModelGroups',invalid,S69),
+ ITResList39 = [ITRes38|ITResList38],
+
+
+ ?line {STRes70,S70} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG014.xsd','./msxsdtest/ModelGroups',valid),
+ STResList71 = [STRes70|STResList70],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG014.xml','./msxsdtest/ModelGroups',valid,S70),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes71,S71} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG015.xsd','./msxsdtest/ModelGroups',valid),
+ STResList72 = [STRes71|STResList71],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG015.xml','./msxsdtest/ModelGroups',invalid,S71),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes72,S72} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG016.xsd','./msxsdtest/ModelGroups',valid),
+ STResList73 = [STRes72|STResList72],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG016.xml','./msxsdtest/ModelGroups',valid,S72),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes73,S73} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG017.xsd','./msxsdtest/ModelGroups',valid),
+ STResList74 = [STRes73|STResList73],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG017.xml','./msxsdtest/ModelGroups',invalid,S73),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes74,S74} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG018.xsd','./msxsdtest/ModelGroups',valid),
+ STResList75 = [STRes74|STResList74],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG018.xml','./msxsdtest/ModelGroups',invalid,S74),
+ ITResList44 = [ITRes43|ITResList43],
+
+
+ ?line {STRes75,S75} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG019.xsd','./msxsdtest/ModelGroups',valid),
+ STResList76 = [STRes75|STResList75],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG019.xml','./msxsdtest/ModelGroups',valid,S75),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes76,S76} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG020.xsd','./msxsdtest/ModelGroups',valid),
+ STResList77 = [STRes76|STResList76],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG020.xml','./msxsdtest/ModelGroups',invalid,S76),
+ ITResList46 = [ITRes45|ITResList45],
+
+
+ ?line {STRes77,S77} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG021.xsd','./msxsdtest/ModelGroups',valid),
+ STResList78 = [STRes77|STResList77],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG021.xml','./msxsdtest/ModelGroups',invalid,S77),
+ ITResList47 = [ITRes46|ITResList46],
+
+
+ ?line {STRes78,S78} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG022.xsd','./msxsdtest/ModelGroups',valid),
+ STResList79 = [STRes78|STResList78],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG022.xml','./msxsdtest/ModelGroups',valid,S78),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes79,S79} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG023.xsd','./msxsdtest/ModelGroups',valid),
+ STResList80 = [STRes79|STResList79],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG023.xml','./msxsdtest/ModelGroups',valid,S79),
+ ITResList49 = [ITRes48|ITResList48],
+
+
+ ?line {STRes80,S80} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG024.xsd','./msxsdtest/ModelGroups',valid),
+ STResList81 = [STRes80|STResList80],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG024.xml','./msxsdtest/ModelGroups',invalid,S80),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes81,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG025.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList82 = [STRes81|STResList81],
+
+
+ ?line {STRes82,S82} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG026.xsd','./msxsdtest/ModelGroups',valid),
+ STResList83 = [STRes82|STResList82],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgG026.xml','./msxsdtest/ModelGroups',valid,S82),
+ ITResList51 = [ITRes50|ITResList50],
+
+
+ ?line {STRes83,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG027.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList84 = [STRes83|STResList83],
+
+
+ ?line {STRes84,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG028.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList85 = [STRes84|STResList84],
+
+
+ ?line {STRes85,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG029.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList86 = [STRes85|STResList85],
+
+
+ ?line {STRes86,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgG030.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList87 = [STRes86|STResList86],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList87,ITResList51).
+
+%% model groups ( choice ).
+
+mgHIJ(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgH001.xsd','./msxsdtest/ModelGroups',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgH001.xml','./msxsdtest/ModelGroups',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes1,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgH002.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList2 = [STRes1|STResList1],
+
+
+ ?line {STRes2,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgH003.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList3 = [STRes2|STResList2],
+
+
+ ?line {STRes3,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgH004.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList4 = [STRes3|STResList3],
+
+
+ ?line {STRes4,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgH005.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList5 = [STRes4|STResList4],
+
+
+ ?line {STRes5,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgH006.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList6 = [STRes5|STResList5],
+
+
+ ?line {STRes6,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgH007.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList7 = [STRes6|STResList6],
+
+
+ ?line {STRes7,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgH008.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList8 = [STRes7|STResList7],
+
+
+ ?line {STRes8,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgH009.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList9 = [STRes8|STResList8],
+
+
+ ?line {STRes9,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgH010.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList10 = [STRes9|STResList9],
+
+
+ ?line {STRes10,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgH011.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList11 = [STRes10|STResList10],
+
+
+ ?line {STRes11,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgH012.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList12 = [STRes11|STResList11],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgH013.xsd','./msxsdtest/ModelGroups',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgH013.xml','./msxsdtest/ModelGroups',valid,S12),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgH014.xsd','./msxsdtest/ModelGroups',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgH014.xml','./msxsdtest/ModelGroups',valid,S13),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgH015.xsd','./msxsdtest/ModelGroups',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgH015.xml','./msxsdtest/ModelGroups',valid,S14),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgH016.xsd','./msxsdtest/ModelGroups',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgH016.xml','./msxsdtest/ModelGroups',valid,S15),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgH017.xsd','./msxsdtest/ModelGroups',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgH017.xml','./msxsdtest/ModelGroups',valid,S16),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgH018.xsd','./msxsdtest/ModelGroups',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgH018.xml','./msxsdtest/ModelGroups',valid,S17),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes18,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgHa001.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList19 = [STRes18|STResList18],
+
+
+ ?line {STRes19,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgHa002.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList20 = [STRes19|STResList19],
+
+
+ ?line {STRes20,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgHa003.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList21 = [STRes20|STResList20],
+
+
+ ?line {STRes21,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgHa004.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList22 = [STRes21|STResList21],
+
+
+ ?line {STRes22,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgHa005.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList23 = [STRes22|STResList22],
+
+
+ ?line {STRes23,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgHa006.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList24 = [STRes23|STResList23],
+
+
+ ?line {STRes24,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgHa007.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList25 = [STRes24|STResList24],
+
+
+ ?line {STRes25,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgHa008.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList26 = [STRes25|STResList25],
+
+
+ ?line {STRes26,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgHb001.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList27 = [STRes26|STResList26],
+
+
+ ?line {STRes27,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgHb002.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList28 = [STRes27|STResList27],
+
+
+ ?line {STRes28,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgHb003.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList29 = [STRes28|STResList28],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgHb004.xsd','./msxsdtest/ModelGroups',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgHb004.xml','./msxsdtest/ModelGroups',valid,S29),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgHb005.xsd','./msxsdtest/ModelGroups',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgHb005.xml','./msxsdtest/ModelGroups',valid,S30),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes31,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgHb006.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList32 = [STRes31|STResList31],
+
+
+ ?line {STRes32,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgHb007.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList33 = [STRes32|STResList32],
+
+
+ ?line {STRes33,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgHb008.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList34 = [STRes33|STResList33],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI001.xsd','./msxsdtest/ModelGroups',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgI001.xml','./msxsdtest/ModelGroups',valid,S34),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes35,S35} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI002.xsd','./msxsdtest/ModelGroups',valid),
+ STResList36 = [STRes35|STResList35],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgI002.xml','./msxsdtest/ModelGroups',valid,S35),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes36,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI003.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList37 = [STRes36|STResList36],
+
+
+ ?line {STRes37,S37} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI004.xsd','./msxsdtest/ModelGroups',valid),
+ STResList38 = [STRes37|STResList37],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgI004.xml','./msxsdtest/ModelGroups',valid,S37),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes38,S38} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI005.xsd','./msxsdtest/ModelGroups',valid),
+ STResList39 = [STRes38|STResList38],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgI005.xml','./msxsdtest/ModelGroups',valid,S38),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes39,S39} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI006.xsd','./msxsdtest/ModelGroups',valid),
+ STResList40 = [STRes39|STResList39],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgI006.xml','./msxsdtest/ModelGroups',valid,S39),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes40,S40} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI007.xsd','./msxsdtest/ModelGroups',valid),
+ STResList41 = [STRes40|STResList40],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgI007.xml','./msxsdtest/ModelGroups',valid,S40),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes41,S41} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI008.xsd','./msxsdtest/ModelGroups',valid),
+ STResList42 = [STRes41|STResList41],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgI008.xml','./msxsdtest/ModelGroups',valid,S41),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes42,S42} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI009.xsd','./msxsdtest/ModelGroups',valid),
+ STResList43 = [STRes42|STResList42],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgI009.xml','./msxsdtest/ModelGroups',valid,S42),
+ ITResList17 = [ITRes16|ITResList16],
+
+
+ ?line {STRes43,S43} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI010.xsd','./msxsdtest/ModelGroups',valid),
+ STResList44 = [STRes43|STResList43],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgI010.xml','./msxsdtest/ModelGroups',valid,S43),
+ ITResList18 = [ITRes17|ITResList17],
+
+
+ ?line {STRes44,S44} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI011.xsd','./msxsdtest/ModelGroups',valid),
+ STResList45 = [STRes44|STResList44],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgI011.xml','./msxsdtest/ModelGroups',valid,S44),
+ ITResList19 = [ITRes18|ITResList18],
+
+
+ ?line {STRes45,S45} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI012.xsd','./msxsdtest/ModelGroups',valid),
+ STResList46 = [STRes45|STResList45],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgI012.xml','./msxsdtest/ModelGroups',valid,S45),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes46,S46} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI013.xsd','./msxsdtest/ModelGroups',valid),
+ STResList47 = [STRes46|STResList46],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgI013.xml','./msxsdtest/ModelGroups',valid,S46),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes47,S47} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI014.xsd','./msxsdtest/ModelGroups',valid),
+ STResList48 = [STRes47|STResList47],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgI014.xml','./msxsdtest/ModelGroups',valid,S47),
+ ITResList22 = [ITRes21|ITResList21],
+
+
+ ?line {STRes48,S48} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI015.xsd','./msxsdtest/ModelGroups',valid),
+ STResList49 = [STRes48|STResList48],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgI015.xml','./msxsdtest/ModelGroups',valid,S48),
+ ITResList23 = [ITRes22|ITResList22],
+
+
+ ?line {STRes49,S49} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI016.xsd','./msxsdtest/ModelGroups',valid),
+ STResList50 = [STRes49|STResList49],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgI016.xml','./msxsdtest/ModelGroups',valid,S49),
+ ITResList24 = [ITRes23|ITResList23],
+
+
+ ?line {STRes50,S50} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI017.xsd','./msxsdtest/ModelGroups',valid),
+ STResList51 = [STRes50|STResList50],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgI017.xml','./msxsdtest/ModelGroups',valid,S50),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes51,S51} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI018.xsd','./msxsdtest/ModelGroups',valid),
+ STResList52 = [STRes51|STResList51],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgI018.xml','./msxsdtest/ModelGroups',valid,S51),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes52,S52} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI019.xsd','./msxsdtest/ModelGroups',valid),
+ STResList53 = [STRes52|STResList52],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgI019.xml','./msxsdtest/ModelGroups',valid,S52),
+ ITResList27 = [ITRes26|ITResList26],
+
+
+ ?line {STRes53,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI020.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList54 = [STRes53|STResList53],
+
+
+ ?line {STRes54,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI021.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList55 = [STRes54|STResList54],
+
+
+ ?line {STRes55,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI022.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList56 = [STRes55|STResList55],
+
+
+ ?line {STRes56,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgI023.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList57 = [STRes56|STResList56],
+
+
+ ?line {STRes57,S57} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ001.xsd','./msxsdtest/ModelGroups',valid),
+ STResList58 = [STRes57|STResList57],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ001.xml','./msxsdtest/ModelGroups',valid,S57),
+ ITResList28 = [ITRes27|ITResList27],
+
+
+ ?line {STRes58,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ002.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList59 = [STRes58|STResList58],
+
+
+ ?line {STRes59,S59} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ003.xsd','./msxsdtest/ModelGroups',valid),
+ STResList60 = [STRes59|STResList59],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ003.xml','./msxsdtest/ModelGroups',invalid,S59),
+ ITResList29 = [ITRes28|ITResList28],
+
+
+ ?line {STRes60,S60} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ004.xsd','./msxsdtest/ModelGroups',valid),
+ STResList61 = [STRes60|STResList60],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ004.xml','./msxsdtest/ModelGroups',valid,S60),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes61,S61} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ005.xsd','./msxsdtest/ModelGroups',valid),
+ STResList62 = [STRes61|STResList61],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ005.xml','./msxsdtest/ModelGroups',invalid,S61),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes62,S62} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ006.xsd','./msxsdtest/ModelGroups',valid),
+ STResList63 = [STRes62|STResList62],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ006.xml','./msxsdtest/ModelGroups',valid,S62),
+ ITResList32 = [ITRes31|ITResList31],
+
+
+ ?line {STRes63,S63} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ007.xsd','./msxsdtest/ModelGroups',valid),
+ STResList64 = [STRes63|STResList63],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ007.xml','./msxsdtest/ModelGroups',valid,S63),
+ ITResList33 = [ITRes32|ITResList32],
+
+
+ ?line {STRes64,S64} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ008.xsd','./msxsdtest/ModelGroups',valid),
+ STResList65 = [STRes64|STResList64],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ008.xml','./msxsdtest/ModelGroups',invalid,S64),
+ ITResList34 = [ITRes33|ITResList33],
+
+
+ ?line {STRes65,S65} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ009.xsd','./msxsdtest/ModelGroups',valid),
+ STResList66 = [STRes65|STResList65],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ009.xml','./msxsdtest/ModelGroups',valid,S65),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes66,S66} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ010.xsd','./msxsdtest/ModelGroups',valid),
+ STResList67 = [STRes66|STResList66],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ010.xml','./msxsdtest/ModelGroups',valid,S66),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes67,S67} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ011.xsd','./msxsdtest/ModelGroups',valid),
+ STResList68 = [STRes67|STResList67],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ011.xml','./msxsdtest/ModelGroups',invalid,S67),
+ ITResList37 = [ITRes36|ITResList36],
+
+
+ ?line {STRes68,S68} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ012.xsd','./msxsdtest/ModelGroups',valid),
+ STResList69 = [STRes68|STResList68],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ012.xml','./msxsdtest/ModelGroups',valid,S68),
+ ITResList38 = [ITRes37|ITResList37],
+
+
+ ?line {STRes69,S69} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ013.xsd','./msxsdtest/ModelGroups',valid),
+ STResList70 = [STRes69|STResList69],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ013.xml','./msxsdtest/ModelGroups',invalid,S69),
+ ITResList39 = [ITRes38|ITResList38],
+
+
+ ?line {STRes70,S70} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ014.xsd','./msxsdtest/ModelGroups',valid),
+ STResList71 = [STRes70|STResList70],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ014.xml','./msxsdtest/ModelGroups',valid,S70),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes71,S71} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ015.xsd','./msxsdtest/ModelGroups',valid),
+ STResList72 = [STRes71|STResList71],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ015.xml','./msxsdtest/ModelGroups',invalid,S71),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes72,S72} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ016.xsd','./msxsdtest/ModelGroups',valid),
+ STResList73 = [STRes72|STResList72],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ016.xml','./msxsdtest/ModelGroups',valid,S72),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes73,S73} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ017.xsd','./msxsdtest/ModelGroups',valid),
+ STResList74 = [STRes73|STResList73],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ017.xml','./msxsdtest/ModelGroups',invalid,S73),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes74,S74} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ018.xsd','./msxsdtest/ModelGroups',valid),
+ STResList75 = [STRes74|STResList74],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ018.xml','./msxsdtest/ModelGroups',invalid,S74),
+ ITResList44 = [ITRes43|ITResList43],
+
+
+ ?line {STRes75,S75} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ019.xsd','./msxsdtest/ModelGroups',valid),
+ STResList76 = [STRes75|STResList75],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ019.xml','./msxsdtest/ModelGroups',valid,S75),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes76,S76} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ020.xsd','./msxsdtest/ModelGroups',valid),
+ STResList77 = [STRes76|STResList76],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ020.xml','./msxsdtest/ModelGroups',invalid,S76),
+ ITResList46 = [ITRes45|ITResList45],
+
+
+ ?line {STRes77,S77} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ021.xsd','./msxsdtest/ModelGroups',valid),
+ STResList78 = [STRes77|STResList77],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ021.xml','./msxsdtest/ModelGroups',invalid,S77),
+ ITResList47 = [ITRes46|ITResList46],
+
+
+ ?line {STRes78,S78} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ022.xsd','./msxsdtest/ModelGroups',valid),
+ STResList79 = [STRes78|STResList78],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ022.xml','./msxsdtest/ModelGroups',valid,S78),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes79,S79} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ023.xsd','./msxsdtest/ModelGroups',valid),
+ STResList80 = [STRes79|STResList79],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ023.xml','./msxsdtest/ModelGroups',valid,S79),
+ ITResList49 = [ITRes48|ITResList48],
+
+
+ ?line {STRes80,S80} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ024.xsd','./msxsdtest/ModelGroups',valid),
+ STResList81 = [STRes80|STResList80],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ024.xml','./msxsdtest/ModelGroups',invalid,S80),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes81,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ025.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList82 = [STRes81|STResList81],
+
+
+ ?line {STRes82,S82} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ026.xsd','./msxsdtest/ModelGroups',valid),
+ STResList83 = [STRes82|STResList82],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgJ026.xml','./msxsdtest/ModelGroups',valid,S82),
+ ITResList51 = [ITRes50|ITResList50],
+
+
+ ?line {STRes83,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ027.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList84 = [STRes83|STResList83],
+
+
+ ?line {STRes84,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ028.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList85 = [STRes84|STResList84],
+
+
+ ?line {STRes85,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ029.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList86 = [STRes85|STResList85],
+
+
+ ?line {STRes86,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgJ030.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList87 = [STRes86|STResList86],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList87,ITResList51).
+
+%% model group validation checking (sequence).
+
+mgK(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgK001.xsd','./msxsdtest/ModelGroups',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgK001.xml','./msxsdtest/ModelGroups',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgK002.xsd','./msxsdtest/ModelGroups',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgK002.xml','./msxsdtest/ModelGroups',invalid,S1),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgK003.xsd','./msxsdtest/ModelGroups',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgK003.xml','./msxsdtest/ModelGroups',invalid,S2),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgK004.xsd','./msxsdtest/ModelGroups',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgK004.xml','./msxsdtest/ModelGroups',valid,S3),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgK005.xsd','./msxsdtest/ModelGroups',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgK005.xml','./msxsdtest/ModelGroups',invalid,S4),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgK006.xsd','./msxsdtest/ModelGroups',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgK006.xml','./msxsdtest/ModelGroups',invalid,S5),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgK007.xsd','./msxsdtest/ModelGroups',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgK007.xml','./msxsdtest/ModelGroups',invalid,S6),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgK008.xsd','./msxsdtest/ModelGroups',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgK008.xml','./msxsdtest/ModelGroups',invalid,S7),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgK009.xsd','./msxsdtest/ModelGroups',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgK009.xml','./msxsdtest/ModelGroups',valid,S8),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgK010.xsd','./msxsdtest/ModelGroups',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgK010.xml','./msxsdtest/ModelGroups',invalid,S9),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList10,ITResList10).
+
+%% model group validation checking (choice, all).
+
+mgLM(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgL001.xsd','./msxsdtest/ModelGroups',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgL001.xml','./msxsdtest/ModelGroups',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgL002.xsd','./msxsdtest/ModelGroups',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgL002.xml','./msxsdtest/ModelGroups',invalid,S1),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgL003.xsd','./msxsdtest/ModelGroups',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgL003.xml','./msxsdtest/ModelGroups',invalid,S2),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgL004.xsd','./msxsdtest/ModelGroups',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgL004.xml','./msxsdtest/ModelGroups',valid,S3),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgL005.xsd','./msxsdtest/ModelGroups',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgL005.xml','./msxsdtest/ModelGroups',invalid,S4),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgL006.xsd','./msxsdtest/ModelGroups',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgL006.xml','./msxsdtest/ModelGroups',valid,S5),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgL007.xsd','./msxsdtest/ModelGroups',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgL007.xml','./msxsdtest/ModelGroups',invalid,S6),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgL008.xsd','./msxsdtest/ModelGroups',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgL008.xml','./msxsdtest/ModelGroups',valid,S7),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgL009.xsd','./msxsdtest/ModelGroups',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgL009.xml','./msxsdtest/ModelGroups',valid,S8),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgL010.xsd','./msxsdtest/ModelGroups',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgL010.xml','./msxsdtest/ModelGroups',invalid,S9),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgM002.xsd','./msxsdtest/ModelGroups',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgM002.xml','./msxsdtest/ModelGroups',invalid,S10),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgM003.xsd','./msxsdtest/ModelGroups',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgM003.xml','./msxsdtest/ModelGroups',invalid,S11),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgM004.xsd','./msxsdtest/ModelGroups',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgM004.xml','./msxsdtest/ModelGroups',valid,S12),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgM005.xsd','./msxsdtest/ModelGroups',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgM005.xml','./msxsdtest/ModelGroups',invalid,S13),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgM006.xsd','./msxsdtest/ModelGroups',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgM006.xml','./msxsdtest/ModelGroups',invalid,S14),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgM007.xsd','./msxsdtest/ModelGroups',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgM007.xml','./msxsdtest/ModelGroups',invalid,S15),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgM008.xsd','./msxsdtest/ModelGroups',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgM008.xml','./msxsdtest/ModelGroups',valid,S16),
+ ITResList17 = [ITRes16|ITResList16],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgM009.xsd','./msxsdtest/ModelGroups',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgM009.xml','./msxsdtest/ModelGroups',valid,S17),
+ ITResList18 = [ITRes17|ITResList17],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgM010.xsd','./msxsdtest/ModelGroups',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgM010.xml','./msxsdtest/ModelGroups',invalid,S18),
+ ITResList19 = [ITRes18|ITResList18],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgM011.xsd','./msxsdtest/ModelGroups',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgM011.xml','./msxsdtest/ModelGroups',valid,S19),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgM012.xsd','./msxsdtest/ModelGroups',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgM012.xml','./msxsdtest/ModelGroups',invalid,S20),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgM013.xsd','./msxsdtest/ModelGroups',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgM013.xml','./msxsdtest/ModelGroups',valid,S21),
+ ITResList22 = [ITRes21|ITResList21],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgM014.xsd','./msxsdtest/ModelGroups',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgM014.xml','./msxsdtest/ModelGroups',invalid,S22),
+ ITResList23 = [ITRes22|ITResList22],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList23,ITResList23).
+
+%% Element Sequence Valid.
+
+mgN(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgN001.xsd','./msxsdtest/ModelGroups',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgN001.xml','./msxsdtest/ModelGroups',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgN002.xsd','./msxsdtest/ModelGroups',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgN002.xml','./msxsdtest/ModelGroups',invalid,S1),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgN003.xsd','./msxsdtest/ModelGroups',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgN003.xml','./msxsdtest/ModelGroups',invalid,S2),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgN004.xsd','./msxsdtest/ModelGroups',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgN004.xml','./msxsdtest/ModelGroups',invalid,S3),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgN005.xsd','./msxsdtest/ModelGroups',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgN005.xml','./msxsdtest/ModelGroups',valid,S4),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgN006.xsd','./msxsdtest/ModelGroups',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgN006.xml','./msxsdtest/ModelGroups',invalid,S5),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgN007.xsd','./msxsdtest/ModelGroups',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgN007.xml','./msxsdtest/ModelGroups',invalid,S6),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgN008.xsd','./msxsdtest/ModelGroups',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgN008.xml','./msxsdtest/ModelGroups',invalid,S7),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgN009.xsd','./msxsdtest/ModelGroups',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgN009.xml','./msxsdtest/ModelGroups',invalid,S8),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgN010.xsd','./msxsdtest/ModelGroups',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgN010.xml','./msxsdtest/ModelGroups',invalid,S9),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgN011.xsd','./msxsdtest/ModelGroups',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgN011.xml','./msxsdtest/ModelGroups',invalid,S10),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgN012.xsd','./msxsdtest/ModelGroups',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgN012.xml','./msxsdtest/ModelGroups',valid,S11),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgN013.xsd','./msxsdtest/ModelGroups',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgN013.xml','./msxsdtest/ModelGroups',invalid,S12),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgN014.xsd','./msxsdtest/ModelGroups',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgN014.xml','./msxsdtest/ModelGroups',invalid,S13),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgN015.xsd','./msxsdtest/ModelGroups',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgN015.xml','./msxsdtest/ModelGroups',invalid,S14),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgN016.xsd','./msxsdtest/ModelGroups',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgN016.xml','./msxsdtest/ModelGroups',invalid,S15),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList16,ITResList16).
+
+%% All Group Limited.
+
+mgOP(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO001.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO002.xsd','./msxsdtest/ModelGroups',valid),
+ STResList2 = [STRes1|STResList1],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO002.xml','./msxsdtest/ModelGroups',valid,S1),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes2,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO003.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList3 = [STRes2|STResList2],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO004.xsd','./msxsdtest/ModelGroups',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO004.xml','./msxsdtest/ModelGroups',valid,S3),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO005.xsd','./msxsdtest/ModelGroups',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO005.xml','./msxsdtest/ModelGroups',valid,S4),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO006.xsd','./msxsdtest/ModelGroups',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO006.xml','./msxsdtest/ModelGroups',valid,S5),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO007.xsd','./msxsdtest/ModelGroups',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO007.xml','./msxsdtest/ModelGroups',valid,S6),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO008.xsd','./msxsdtest/ModelGroups',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO008.xml','./msxsdtest/ModelGroups',valid,S7),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO009.xsd','./msxsdtest/ModelGroups',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO009.xml','./msxsdtest/ModelGroups',valid,S8),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO010.xsd','./msxsdtest/ModelGroups',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO010.xml','./msxsdtest/ModelGroups',valid,S9),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO011.xsd','./msxsdtest/ModelGroups',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO011.xml','./msxsdtest/ModelGroups',valid,S10),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes11,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO012.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList12 = [STRes11|STResList11],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO013.xsd','./msxsdtest/ModelGroups',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO013.xml','./msxsdtest/ModelGroups',valid,S12),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO014.xsd','./msxsdtest/ModelGroups',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO014.xml','./msxsdtest/ModelGroups',valid,S13),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO015.xsd','./msxsdtest/ModelGroups',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO015.xml','./msxsdtest/ModelGroups',valid,S14),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO016.xsd','./msxsdtest/ModelGroups',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO016.xml','./msxsdtest/ModelGroups',valid,S15),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO017.xsd','./msxsdtest/ModelGroups',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO017.xml','./msxsdtest/ModelGroups',valid,S16),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes17,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO018.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList18 = [STRes17|STResList17],
+
+
+ ?line {STRes18,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO019.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList19 = [STRes18|STResList18],
+
+
+ ?line {STRes19,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO020.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList20 = [STRes19|STResList19],
+
+
+ ?line {STRes20,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO021.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList21 = [STRes20|STResList20],
+
+
+ ?line {STRes21,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO022.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList22 = [STRes21|STResList21],
+
+
+ ?line {STRes22,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO023.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList23 = [STRes22|STResList22],
+
+
+ ?line {STRes23,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO024.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList24 = [STRes23|STResList23],
+
+
+ ?line {STRes24,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO025.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList25 = [STRes24|STResList24],
+
+
+ ?line {STRes25,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO026.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList26 = [STRes25|STResList25],
+
+
+ ?line {STRes26,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO027.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList27 = [STRes26|STResList26],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO028.xsd','./msxsdtest/ModelGroups',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO028.xml','./msxsdtest/ModelGroups',valid,S27),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO029.xsd','./msxsdtest/ModelGroups',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO029.xml','./msxsdtest/ModelGroups',valid,S28),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO030.xsd','./msxsdtest/ModelGroups',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO030.xml','./msxsdtest/ModelGroups',valid,S29),
+ ITResList17 = [ITRes16|ITResList16],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO031.xsd','./msxsdtest/ModelGroups',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO031.xml','./msxsdtest/ModelGroups',valid,S30),
+ ITResList18 = [ITRes17|ITResList17],
+
+
+ ?line {STRes31,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO032.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList32 = [STRes31|STResList31],
+
+
+ ?line {STRes32,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO033.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList33 = [STRes32|STResList32],
+
+
+ ?line {STRes33,S33} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO034.xsd','./msxsdtest/ModelGroups',valid),
+ STResList34 = [STRes33|STResList33],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO034.xml','./msxsdtest/ModelGroups',valid,S33),
+ ITResList19 = [ITRes18|ITResList18],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO035.xsd','./msxsdtest/ModelGroups',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO035.xml','./msxsdtest/ModelGroups',valid,S34),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes35,S35} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO036.xsd','./msxsdtest/ModelGroups',valid),
+ STResList36 = [STRes35|STResList35],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO036.xml','./msxsdtest/ModelGroups',valid,S35),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes36,S36} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO037.xsd','./msxsdtest/ModelGroups',valid),
+ STResList37 = [STRes36|STResList36],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO037.xml','./msxsdtest/ModelGroups',valid,S36),
+ ITResList22 = [ITRes21|ITResList21],
+
+
+ ?line {STRes37,S37} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgO038.xsd','./msxsdtest/ModelGroups',valid),
+ STResList38 = [STRes37|STResList37],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgO038.xml','./msxsdtest/ModelGroups',valid,S37),
+ ITResList23 = [ITRes22|ITResList22],
+
+
+ ?line {STRes38,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgP039.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList39 = [STRes38|STResList38],
+
+
+ ?line {STRes39,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgP040.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList40 = [STRes39|STResList39],
+
+
+ ?line {STRes40,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgP041.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList41 = [STRes40|STResList40],
+
+
+ ?line {STRes41,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgP042.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList42 = [STRes41|STResList41],
+
+
+ ?line {STRes42,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgP043.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList43 = [STRes42|STResList42],
+
+
+ ?line {STRes43,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgP049.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList44 = [STRes43|STResList43],
+
+
+ ?line {STRes44,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgP050.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList45 = [STRes44|STResList44],
+
+
+ ?line {STRes45,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgP055.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList46 = [STRes45|STResList45],
+
+
+ ?line {STRes46,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgP056.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList47 = [STRes46|STResList46],
+
+
+ ?line {STRes47,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgP057.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList48 = [STRes47|STResList47],
+
+
+ ?line {STRes48,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgP058.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList49 = [STRes48|STResList48],
+
+
+ ?line {STRes49,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgP059.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList50 = [STRes49|STResList49],
+
+
+ ?line {STRes50,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgP060.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList51 = [STRes50|STResList50],
+
+
+ ?line {STRes51,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgP061.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList52 = [STRes51|STResList51],
+
+
+ ?line {STRes52,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgP062.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList53 = [STRes52|STResList52],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList53,ITResList23).
+
+%% Element Declarations Consistent, 3.8.6
+
+mgQR(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ001.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ002.xsd','./msxsdtest/ModelGroups',valid),
+ STResList2 = [STRes1|STResList1],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgQ002.xml','./msxsdtest/ModelGroups',valid,S1),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ003.xsd','./msxsdtest/ModelGroups',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgQ003.xml','./msxsdtest/ModelGroups',valid,S2),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes3,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ004.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList4 = [STRes3|STResList3],
+
+
+ ?line {STRes4,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ005.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList5 = [STRes4|STResList4],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ006.xsd','./msxsdtest/ModelGroups',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgQ006.xml','./msxsdtest/ModelGroups',valid,S5),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ007.xsd','./msxsdtest/ModelGroups',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgQ007.xml','./msxsdtest/ModelGroups',valid,S6),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ008.xsd','./msxsdtest/ModelGroups',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgQ008.xml','./msxsdtest/ModelGroups',valid,S7),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ009.xsd','./msxsdtest/ModelGroups',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgQ009.xml','./msxsdtest/ModelGroups',valid,S8),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes9,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ010.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList10 = [STRes9|STResList9],
+
+
+ ?line {STRes10,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ011.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList11 = [STRes10|STResList10],
+
+
+ ?line {STRes11,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ012.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList12 = [STRes11|STResList11],
+
+
+ ?line {STRes12,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ013.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList13 = [STRes12|STResList12],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ014.xsd','./msxsdtest/ModelGroups',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgQ014.xml','./msxsdtest/ModelGroups',valid,S13),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ015.xsd','./msxsdtest/ModelGroups',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgQ015.xml','./msxsdtest/ModelGroups',valid,S14),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ016.xsd','./msxsdtest/ModelGroups',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgQ016.xml','./msxsdtest/ModelGroups',valid,S15),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ017.xsd','./msxsdtest/ModelGroups',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgQ017.xml','./msxsdtest/ModelGroups',valid,S16),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ018.xsd','./msxsdtest/ModelGroups',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgQ018.xml','./msxsdtest/ModelGroups',valid,S17),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ019.xsd','./msxsdtest/ModelGroups',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgQ019.xml','./msxsdtest/ModelGroups',valid,S18),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ020.xsd','./msxsdtest/ModelGroups',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/ModelGroups/mgQ020.xml','./msxsdtest/ModelGroups',valid,S19),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes20,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgQ021.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList21 = [STRes20|STResList20],
+
+
+ ?line {STRes21,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR001.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList22 = [STRes21|STResList21],
+
+
+ ?line {STRes22,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR002.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList23 = [STRes22|STResList22],
+
+
+ ?line {STRes23,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR003.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList24 = [STRes23|STResList23],
+
+
+ ?line {STRes24,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR004.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList25 = [STRes24|STResList24],
+
+
+ ?line {STRes25,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR005.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList26 = [STRes25|STResList25],
+
+
+ ?line {STRes26,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR006.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList27 = [STRes26|STResList26],
+
+
+ ?line {STRes27,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR007.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList28 = [STRes27|STResList27],
+
+
+ ?line {STRes28,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR008.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList29 = [STRes28|STResList28],
+
+
+ ?line {STRes29,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR009.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList30 = [STRes29|STResList29],
+
+
+ ?line {STRes30,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR010.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList31 = [STRes30|STResList30],
+
+
+ ?line {STRes31,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR011.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList32 = [STRes31|STResList31],
+
+
+ ?line {STRes32,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR012.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList33 = [STRes32|STResList32],
+
+
+ ?line {STRes33,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR013.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList34 = [STRes33|STResList33],
+
+
+ ?line {STRes34,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR014.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList35 = [STRes34|STResList34],
+
+
+ ?line {STRes35,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR015.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList36 = [STRes35|STResList35],
+
+
+ ?line {STRes36,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR016.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList37 = [STRes36|STResList36],
+
+
+ ?line {STRes37,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR017.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList38 = [STRes37|STResList37],
+
+
+ ?line {STRes38,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR018.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList39 = [STRes38|STResList38],
+
+
+ ?line {STRes39,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR019.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList40 = [STRes39|STResList39],
+
+
+ ?line {STRes40,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR020.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList41 = [STRes40|STResList40],
+
+
+ ?line {STRes41,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR021.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList42 = [STRes41|STResList41],
+
+
+ ?line {STRes42,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/ModelGroups/mgR022.xsd','./msxsdtest/ModelGroups',invalid),
+ STResList43 = [STRes42|STResList42],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList43,ITResList13).
+
+%% Deterministic Sequences.
+
+mgS(Config) when is_list(Config) ->
+
+
+
+
+
+
+
+
+ xmerl_xsd_lib:compare_test_results(Config,[],[]).
+
+%% 3.9.1 The Particle Schema Component.
+
+particlesAB(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesA001.xsd','./msxsdtest/Particles',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesA001.xml','./msxsdtest/Particles',invalid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesA002.xsd','./msxsdtest/Particles',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesA002.xml','./msxsdtest/Particles',valid,S1),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesA003.xsd','./msxsdtest/Particles',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesA003.xml','./msxsdtest/Particles',invalid,S2),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesA004.xsd','./msxsdtest/Particles',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesA004.xml','./msxsdtest/Particles',invalid,S3),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesA005.xsd','./msxsdtest/Particles',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesA005.xml','./msxsdtest/Particles',invalid,S4),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesA006.xsd','./msxsdtest/Particles',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesA006.xml','./msxsdtest/Particles',valid,S5),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesA007.xsd','./msxsdtest/Particles',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesA007.xml','./msxsdtest/Particles',valid,S6),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesA008.xsd','./msxsdtest/Particles',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesA008.xml','./msxsdtest/Particles',invalid,S7),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesA009.xsd','./msxsdtest/Particles',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesA009.xml','./msxsdtest/Particles',invalid,S8),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesA010.xsd','./msxsdtest/Particles',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesA010.xml','./msxsdtest/Particles',valid,S9),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesA011.xsd','./msxsdtest/Particles',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesA011.xml','./msxsdtest/Particles',valid,S10),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesA012.xsd','./msxsdtest/Particles',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesA012.xml','./msxsdtest/Particles',invalid,S11),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesA013.xsd','./msxsdtest/Particles',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesA013.xml','./msxsdtest/Particles',invalid,S12),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesA014.xsd','./msxsdtest/Particles',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesA014.xml','./msxsdtest/Particles',valid,S13),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesA015.xsd','./msxsdtest/Particles',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesA015.xml','./msxsdtest/Particles',valid,S14),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesB001.xsd','./msxsdtest/Particles',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesB001.xml','./msxsdtest/Particles',invalid,S15),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesB002.xsd','./msxsdtest/Particles',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesB002.xml','./msxsdtest/Particles',valid,S16),
+ ITResList17 = [ITRes16|ITResList16],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesB003.xsd','./msxsdtest/Particles',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesB003.xml','./msxsdtest/Particles',invalid,S17),
+ ITResList18 = [ITRes17|ITResList17],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesB004.xsd','./msxsdtest/Particles',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesB004.xml','./msxsdtest/Particles',invalid,S18),
+ ITResList19 = [ITRes18|ITResList18],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesB005.xsd','./msxsdtest/Particles',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesB005.xml','./msxsdtest/Particles',valid,S19),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesB006.xsd','./msxsdtest/Particles',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesB006.xml','./msxsdtest/Particles',valid,S20),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesB007.xsd','./msxsdtest/Particles',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesB007.xml','./msxsdtest/Particles',invalid,S21),
+ ITResList22 = [ITRes21|ITResList21],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesB008.xsd','./msxsdtest/Particles',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesB008.xml','./msxsdtest/Particles',invalid,S22),
+ ITResList23 = [ITRes22|ITResList22],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesB009.xsd','./msxsdtest/Particles',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesB009.xml','./msxsdtest/Particles',valid,S23),
+ ITResList24 = [ITRes23|ITResList23],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesB010.xsd','./msxsdtest/Particles',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesB010.xml','./msxsdtest/Particles',valid,S24),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesB011.xsd','./msxsdtest/Particles',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesB011.xml','./msxsdtest/Particles',invalid,S25),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesB012.xsd','./msxsdtest/Particles',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesB012.xml','./msxsdtest/Particles',invalid,S26),
+ ITResList27 = [ITRes26|ITResList26],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesB013.xsd','./msxsdtest/Particles',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesB013.xml','./msxsdtest/Particles',valid,S27),
+ ITResList28 = [ITRes27|ITResList27],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesB014.xsd','./msxsdtest/Particles',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesB014.xml','./msxsdtest/Particles',valid,S28),
+ ITResList29 = [ITRes28|ITResList28],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesB015.xsd','./msxsdtest/Particles',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesB015.xml','./msxsdtest/Particles',invalid,S29),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList30,ITResList30).
+
+%% 3.9.4 Particle Validation Rules: Element Sequence Locally Valid.
+
+particlesCDE(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC001.xsd','./msxsdtest/Particles',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC001.xml','./msxsdtest/Particles',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC002.xsd','./msxsdtest/Particles',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC002.xml','./msxsdtest/Particles',valid,S1),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC003.xsd','./msxsdtest/Particles',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC003.xml','./msxsdtest/Particles',valid,S2),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC004.xsd','./msxsdtest/Particles',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC004.xml','./msxsdtest/Particles',valid,S3),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC005.xsd','./msxsdtest/Particles',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC005.xml','./msxsdtest/Particles',valid,S4),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC006.xsd','./msxsdtest/Particles',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC006.xml','./msxsdtest/Particles',valid,S5),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC007.xsd','./msxsdtest/Particles',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC007.xml','./msxsdtest/Particles',invalid,S6),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC008.xsd','./msxsdtest/Particles',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC008.xml','./msxsdtest/Particles',valid,S7),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC009.xsd','./msxsdtest/Particles',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC009.xml','./msxsdtest/Particles',valid,S8),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC010.xsd','./msxsdtest/Particles',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC010.xml','./msxsdtest/Particles',valid,S9),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC011.xsd','./msxsdtest/Particles',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC011.xml','./msxsdtest/Particles',valid,S10),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC012.xsd','./msxsdtest/Particles',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC012.xml','./msxsdtest/Particles',invalid,S11),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC013.xsd','./msxsdtest/Particles',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC013.xml','./msxsdtest/Particles',invalid,S12),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC014.xsd','./msxsdtest/Particles',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC014.xml','./msxsdtest/Particles',invalid,S13),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC015.xsd','./msxsdtest/Particles',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC015.xml','./msxsdtest/Particles',valid,S14),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC016.xsd','./msxsdtest/Particles',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC016.xml','./msxsdtest/Particles',valid,S15),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC017.xsd','./msxsdtest/Particles',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC017.xml','./msxsdtest/Particles',invalid,S16),
+ ITResList17 = [ITRes16|ITResList16],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC018.xsd','./msxsdtest/Particles',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC018.xml','./msxsdtest/Particles',invalid,S17),
+ ITResList18 = [ITRes17|ITResList17],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC019.xsd','./msxsdtest/Particles',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC019.xml','./msxsdtest/Particles',invalid,S18),
+ ITResList19 = [ITRes18|ITResList18],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC020.xsd','./msxsdtest/Particles',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC020.xml','./msxsdtest/Particles',invalid,S19),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC021.xsd','./msxsdtest/Particles',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC021.xml','./msxsdtest/Particles',valid,S20),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC022.xsd','./msxsdtest/Particles',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC022.xml','./msxsdtest/Particles',invalid,S21),
+ ITResList22 = [ITRes21|ITResList21],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC023.xsd','./msxsdtest/Particles',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC023.xml','./msxsdtest/Particles',invalid,S22),
+ ITResList23 = [ITRes22|ITResList22],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC024.xsd','./msxsdtest/Particles',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC024.xml','./msxsdtest/Particles',invalid,S23),
+ ITResList24 = [ITRes23|ITResList23],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC025.xsd','./msxsdtest/Particles',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC025.xml','./msxsdtest/Particles',invalid,S24),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC026.xsd','./msxsdtest/Particles',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC026.xml','./msxsdtest/Particles',invalid,S25),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC027.xsd','./msxsdtest/Particles',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC027.xml','./msxsdtest/Particles',valid,S26),
+ ITResList27 = [ITRes26|ITResList26],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC028.xsd','./msxsdtest/Particles',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC028.xml','./msxsdtest/Particles',valid,S27),
+ ITResList28 = [ITRes27|ITResList27],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC029.xsd','./msxsdtest/Particles',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC029.xml','./msxsdtest/Particles',valid,S28),
+ ITResList29 = [ITRes28|ITResList28],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC030.xsd','./msxsdtest/Particles',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC030.xml','./msxsdtest/Particles',valid,S29),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC031.xsd','./msxsdtest/Particles',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC031.xml','./msxsdtest/Particles',invalid,S30),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes31,S31} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC032.xsd','./msxsdtest/Particles',valid),
+ STResList32 = [STRes31|STResList31],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC032.xml','./msxsdtest/Particles',invalid,S31),
+ ITResList32 = [ITRes31|ITResList31],
+
+
+ ?line {STRes32,S32} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC033.xsd','./msxsdtest/Particles',valid),
+ STResList33 = [STRes32|STResList32],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC033.xml','./msxsdtest/Particles',invalid,S32),
+ ITResList33 = [ITRes32|ITResList32],
+
+
+ ?line {STRes33,S33} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC034.xsd','./msxsdtest/Particles',valid),
+ STResList34 = [STRes33|STResList33],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC034.xml','./msxsdtest/Particles',valid,S33),
+ ITResList34 = [ITRes33|ITResList33],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC035.xsd','./msxsdtest/Particles',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC035.xml','./msxsdtest/Particles',invalid,S34),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes35,S35} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC036.xsd','./msxsdtest/Particles',valid),
+ STResList36 = [STRes35|STResList35],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC036.xml','./msxsdtest/Particles',invalid,S35),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes36,S36} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC037.xsd','./msxsdtest/Particles',valid),
+ STResList37 = [STRes36|STResList36],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC037.xml','./msxsdtest/Particles',valid,S36),
+ ITResList37 = [ITRes36|ITResList36],
+
+
+ ?line {STRes37,S37} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC038.xsd','./msxsdtest/Particles',valid),
+ STResList38 = [STRes37|STResList37],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC038.xml','./msxsdtest/Particles',invalid,S37),
+ ITResList38 = [ITRes37|ITResList37],
+
+
+ ?line {STRes38,S38} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC039.xsd','./msxsdtest/Particles',valid),
+ STResList39 = [STRes38|STResList38],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC039.xml','./msxsdtest/Particles',invalid,S38),
+ ITResList39 = [ITRes38|ITResList38],
+
+
+ ?line {STRes39,S39} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC040.xsd','./msxsdtest/Particles',valid),
+ STResList40 = [STRes39|STResList39],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC040.xml','./msxsdtest/Particles',valid,S39),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes40,S40} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC041.xsd','./msxsdtest/Particles',valid),
+ STResList41 = [STRes40|STResList40],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC041.xml','./msxsdtest/Particles',valid,S40),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes41,S41} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC042.xsd','./msxsdtest/Particles',valid),
+ STResList42 = [STRes41|STResList41],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC042.xml','./msxsdtest/Particles',invalid,S41),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes42,S42} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC043.xsd','./msxsdtest/Particles',valid),
+ STResList43 = [STRes42|STResList42],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC043.xml','./msxsdtest/Particles',valid,S42),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes43,S43} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC044.xsd','./msxsdtest/Particles',valid),
+ STResList44 = [STRes43|STResList43],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC044.xml','./msxsdtest/Particles',valid,S43),
+ ITResList44 = [ITRes43|ITResList43],
+
+
+ ?line {STRes44,S44} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC045.xsd','./msxsdtest/Particles',valid),
+ STResList45 = [STRes44|STResList44],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC045.xml','./msxsdtest/Particles',valid,S44),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes45,S45} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC046.xsd','./msxsdtest/Particles',valid),
+ STResList46 = [STRes45|STResList45],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC046.xml','./msxsdtest/Particles',valid,S45),
+ ITResList46 = [ITRes45|ITResList45],
+
+
+ ?line {STRes46,S46} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC047.xsd','./msxsdtest/Particles',valid),
+ STResList47 = [STRes46|STResList46],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC047.xml','./msxsdtest/Particles',invalid,S46),
+ ITResList47 = [ITRes46|ITResList46],
+
+
+ ?line {STRes47,S47} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesC048.xsd','./msxsdtest/Particles',valid),
+ STResList48 = [STRes47|STResList47],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesC048.xml','./msxsdtest/Particles',invalid,S47),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes48,S48} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDa001.xsd','./msxsdtest/Particles',valid),
+ STResList49 = [STRes48|STResList48],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDa001.xml','./msxsdtest/Particles',invalid,S48),
+ ITResList49 = [ITRes48|ITResList48],
+
+
+ ?line {STRes49,S49} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDa002.xsd','./msxsdtest/Particles',valid),
+ STResList50 = [STRes49|STResList49],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDa002.xml','./msxsdtest/Particles',valid,S49),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes50,S50} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDa003.xsd','./msxsdtest/Particles',valid),
+ STResList51 = [STRes50|STResList50],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDa003.xml','./msxsdtest/Particles',invalid,S50),
+ ITResList51 = [ITRes50|ITResList50],
+
+
+ ?line {STRes51,S51} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDa004.xsd','./msxsdtest/Particles',valid),
+ STResList52 = [STRes51|STResList51],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDa004.xml','./msxsdtest/Particles',invalid,S51),
+ ITResList52 = [ITRes51|ITResList51],
+
+
+ ?line {STRes52,S52} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDa005.xsd','./msxsdtest/Particles',valid),
+ STResList53 = [STRes52|STResList52],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDa005.xml','./msxsdtest/Particles',invalid,S52),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes53,S53} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDa006.xsd','./msxsdtest/Particles',valid),
+ STResList54 = [STRes53|STResList53],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDa006.xml','./msxsdtest/Particles',invalid,S53),
+ ITResList54 = [ITRes53|ITResList53],
+
+
+ ?line {STRes54,S54} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDa007.xsd','./msxsdtest/Particles',valid),
+ STResList55 = [STRes54|STResList54],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDa007.xml','./msxsdtest/Particles',valid,S54),
+ ITResList55 = [ITRes54|ITResList54],
+
+
+ ?line {STRes55,S55} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDa008.xsd','./msxsdtest/Particles',valid),
+ STResList56 = [STRes55|STResList55],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDa008.xml','./msxsdtest/Particles',invalid,S55),
+ ITResList56 = [ITRes55|ITResList55],
+
+
+ ?line {STRes56,S56} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDa009.xsd','./msxsdtest/Particles',valid),
+ STResList57 = [STRes56|STResList56],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDa009.xml','./msxsdtest/Particles',invalid,S56),
+ ITResList57 = [ITRes56|ITResList56],
+
+
+ ?line {STRes57,S57} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDa010.xsd','./msxsdtest/Particles',valid),
+ STResList58 = [STRes57|STResList57],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDa010.xml','./msxsdtest/Particles',invalid,S57),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes58,S58} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDa011.xsd','./msxsdtest/Particles',valid),
+ STResList59 = [STRes58|STResList58],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDa011.xml','./msxsdtest/Particles',invalid,S58),
+ ITResList59 = [ITRes58|ITResList58],
+
+
+ ?line {STRes59,S59} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDb001.xsd','./msxsdtest/Particles',valid),
+ STResList60 = [STRes59|STResList59],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDb001.xml','./msxsdtest/Particles',invalid,S59),
+ ITResList60 = [ITRes59|ITResList59],
+
+
+ ?line {STRes60,S60} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDb002.xsd','./msxsdtest/Particles',valid),
+ STResList61 = [STRes60|STResList60],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDb002.xml','./msxsdtest/Particles',valid,S60),
+ ITResList61 = [ITRes60|ITResList60],
+
+
+ ?line {STRes61,S61} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDb003.xsd','./msxsdtest/Particles',valid),
+ STResList62 = [STRes61|STResList61],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDb003.xml','./msxsdtest/Particles',invalid,S61),
+ ITResList62 = [ITRes61|ITResList61],
+
+
+ ?line {STRes62,S62} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDb004.xsd','./msxsdtest/Particles',valid),
+ STResList63 = [STRes62|STResList62],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDb004.xml','./msxsdtest/Particles',invalid,S62),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes63,S63} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDb005.xsd','./msxsdtest/Particles',valid),
+ STResList64 = [STRes63|STResList63],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDb005.xml','./msxsdtest/Particles',invalid,S63),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes64,S64} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDb006.xsd','./msxsdtest/Particles',valid),
+ STResList65 = [STRes64|STResList64],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDb006.xml','./msxsdtest/Particles',invalid,S64),
+ ITResList65 = [ITRes64|ITResList64],
+
+
+ ?line {STRes65,S65} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDb007.xsd','./msxsdtest/Particles',valid),
+ STResList66 = [STRes65|STResList65],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDb007.xml','./msxsdtest/Particles',valid,S65),
+ ITResList66 = [ITRes65|ITResList65],
+
+
+ ?line {STRes66,S66} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDb008.xsd','./msxsdtest/Particles',valid),
+ STResList67 = [STRes66|STResList66],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDb008.xml','./msxsdtest/Particles',invalid,S66),
+ ITResList67 = [ITRes66|ITResList66],
+
+
+ ?line {STRes67,S67} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDb009.xsd','./msxsdtest/Particles',valid),
+ STResList68 = [STRes67|STResList67],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDb009.xml','./msxsdtest/Particles',invalid,S67),
+ ITResList68 = [ITRes67|ITResList67],
+
+
+ ?line {STRes68,S68} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDb010.xsd','./msxsdtest/Particles',valid),
+ STResList69 = [STRes68|STResList68],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDb010.xml','./msxsdtest/Particles',invalid,S68),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes69,S69} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDb011.xsd','./msxsdtest/Particles',valid),
+ STResList70 = [STRes69|STResList69],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDb011.xml','./msxsdtest/Particles',invalid,S69),
+ ITResList70 = [ITRes69|ITResList69],
+
+
+ ?line {STRes70,S70} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDc001.xsd','./msxsdtest/Particles',valid),
+ STResList71 = [STRes70|STResList70],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDc001.xml','./msxsdtest/Particles',valid,S70),
+ ITResList71 = [ITRes70|ITResList70],
+
+
+ ?line {STRes71,S71} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDc002.xsd','./msxsdtest/Particles',valid),
+ STResList72 = [STRes71|STResList71],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDc002.xml','./msxsdtest/Particles',valid,S71),
+ ITResList72 = [ITRes71|ITResList71],
+
+
+ ?line {STRes72,S72} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDc003.xsd','./msxsdtest/Particles',valid),
+ STResList73 = [STRes72|STResList72],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDc003.xml','./msxsdtest/Particles',valid,S72),
+ ITResList73 = [ITRes72|ITResList72],
+
+
+ ?line {STRes73,S73} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDc004.xsd','./msxsdtest/Particles',valid),
+ STResList74 = [STRes73|STResList73],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDc004.xml','./msxsdtest/Particles',valid,S73),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes74,S74} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDc005.xsd','./msxsdtest/Particles',valid),
+ STResList75 = [STRes74|STResList74],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDc005.xml','./msxsdtest/Particles',valid,S74),
+ ITResList75 = [ITRes74|ITResList74],
+
+
+ ?line {STRes75,S75} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDc006.xsd','./msxsdtest/Particles',valid),
+ STResList76 = [STRes75|STResList75],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDc006.xml','./msxsdtest/Particles',valid,S75),
+ ITResList76 = [ITRes75|ITResList75],
+
+
+ ?line {STRes76,S76} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDc007.xsd','./msxsdtest/Particles',valid),
+ STResList77 = [STRes76|STResList76],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDc007.xml','./msxsdtest/Particles',valid,S76),
+ ITResList77 = [ITRes76|ITResList76],
+
+
+ ?line {STRes77,S77} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDc008.xsd','./msxsdtest/Particles',valid),
+ STResList78 = [STRes77|STResList77],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDc008.xml','./msxsdtest/Particles',valid,S77),
+ ITResList78 = [ITRes77|ITResList77],
+
+
+ ?line {STRes78,S78} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesDc009.xsd','./msxsdtest/Particles',valid),
+ STResList79 = [STRes78|STResList78],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesDc009.xml','./msxsdtest/Particles',valid,S78),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes79,S79} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa001.xsd','./msxsdtest/Particles',valid),
+ STResList80 = [STRes79|STResList79],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa001.xml','./msxsdtest/Particles',valid,S79),
+ ITResList80 = [ITRes79|ITResList79],
+
+
+ ?line {STRes80,S80} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa002.xsd','./msxsdtest/Particles',valid),
+ STResList81 = [STRes80|STResList80],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa002.xml','./msxsdtest/Particles',invalid,S80),
+ ITResList81 = [ITRes80|ITResList80],
+
+
+ ?line {STRes81,S81} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa003.xsd','./msxsdtest/Particles',valid),
+ STResList82 = [STRes81|STResList81],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa003.xml','./msxsdtest/Particles',valid,S81),
+ ITResList82 = [ITRes81|ITResList81],
+
+
+ ?line {STRes82,S82} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa004.xsd','./msxsdtest/Particles',valid),
+ STResList83 = [STRes82|STResList82],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa004.xml','./msxsdtest/Particles',valid,S82),
+ ITResList83 = [ITRes82|ITResList82],
+
+
+ ?line {STRes83,S83} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa005.xsd','./msxsdtest/Particles',valid),
+ STResList84 = [STRes83|STResList83],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa005.xml','./msxsdtest/Particles',invalid,S83),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes84,S84} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa006.xsd','./msxsdtest/Particles',valid),
+ STResList85 = [STRes84|STResList84],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa006.xml','./msxsdtest/Particles',invalid,S84),
+ ITResList85 = [ITRes84|ITResList84],
+
+
+ ?line {STRes85,S85} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa007.xsd','./msxsdtest/Particles',valid),
+ STResList86 = [STRes85|STResList85],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa007.xml','./msxsdtest/Particles',invalid,S85),
+ ITResList86 = [ITRes85|ITResList85],
+
+
+ ?line {STRes86,S86} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa008.xsd','./msxsdtest/Particles',valid),
+ STResList87 = [STRes86|STResList86],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa008.xml','./msxsdtest/Particles',valid,S86),
+ ITResList87 = [ITRes86|ITResList86],
+
+
+ ?line {STRes87,S87} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa009.xsd','./msxsdtest/Particles',valid),
+ STResList88 = [STRes87|STResList87],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa009.xml','./msxsdtest/Particles',invalid,S87),
+ ITResList88 = [ITRes87|ITResList87],
+
+
+ ?line {STRes88,S88} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa010.xsd','./msxsdtest/Particles',valid),
+ STResList89 = [STRes88|STResList88],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa010.xml','./msxsdtest/Particles',valid,S88),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes89,S89} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa011.xsd','./msxsdtest/Particles',valid),
+ STResList90 = [STRes89|STResList89],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa011.xml','./msxsdtest/Particles',valid,S89),
+ ITResList90 = [ITRes89|ITResList89],
+
+
+ ?line {STRes90,S90} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa012.xsd','./msxsdtest/Particles',valid),
+ STResList91 = [STRes90|STResList90],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa012.xml','./msxsdtest/Particles',invalid,S90),
+ ITResList91 = [ITRes90|ITResList90],
+
+
+ ?line {STRes91,S91} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa013.xsd','./msxsdtest/Particles',valid),
+ STResList92 = [STRes91|STResList91],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa013.xml','./msxsdtest/Particles',invalid,S91),
+ ITResList92 = [ITRes91|ITResList91],
+
+
+ ?line {STRes92,S92} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa014.xsd','./msxsdtest/Particles',valid),
+ STResList93 = [STRes92|STResList92],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa014.xml','./msxsdtest/Particles',invalid,S92),
+ ITResList93 = [ITRes92|ITResList92],
+
+
+ ?line {STRes93,S93} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa015.xsd','./msxsdtest/Particles',valid),
+ STResList94 = [STRes93|STResList93],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa015.xml','./msxsdtest/Particles',valid,S93),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes94,S94} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa016.xsd','./msxsdtest/Particles',valid),
+ STResList95 = [STRes94|STResList94],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa016.xml','./msxsdtest/Particles',invalid,S94),
+ ITResList95 = [ITRes94|ITResList94],
+
+
+ ?line {STRes95,S95} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa017.xsd','./msxsdtest/Particles',valid),
+ STResList96 = [STRes95|STResList95],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa017.xml','./msxsdtest/Particles',valid,S95),
+ ITResList96 = [ITRes95|ITResList95],
+
+
+ ?line {STRes96,S96} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa018.xsd','./msxsdtest/Particles',valid),
+ STResList97 = [STRes96|STResList96],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa018.xml','./msxsdtest/Particles',valid,S96),
+ ITResList97 = [ITRes96|ITResList96],
+
+
+ ?line {STRes97,S97} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa019.xsd','./msxsdtest/Particles',valid),
+ STResList98 = [STRes97|STResList97],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa019.xml','./msxsdtest/Particles',invalid,S97),
+ ITResList98 = [ITRes97|ITResList97],
+
+
+ ?line {STRes98,S98} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa020.xsd','./msxsdtest/Particles',valid),
+ STResList99 = [STRes98|STResList98],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa020.xml','./msxsdtest/Particles',invalid,S98),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes99,S99} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa021.xsd','./msxsdtest/Particles',valid),
+ STResList100 = [STRes99|STResList99],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEa021.xml','./msxsdtest/Particles',invalid,S99),
+ ITResList100 = [ITRes99|ITResList99],
+
+
+ ?line {STRes100,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa022.xsd','./msxsdtest/Particles',invalid),
+ STResList101 = [STRes100|STResList100],
+
+
+ ?line {STRes101,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa023.xsd','./msxsdtest/Particles',invalid),
+ STResList102 = [STRes101|STResList101],
+
+
+ ?line {STRes102,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa024.xsd','./msxsdtest/Particles',invalid),
+ STResList103 = [STRes102|STResList102],
+
+
+ ?line {STRes103,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEa025.xsd','./msxsdtest/Particles',invalid),
+ STResList104 = [STRes103|STResList103],
+
+
+ ?line {STRes104,S104} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb001.xsd','./msxsdtest/Particles',valid),
+ STResList105 = [STRes104|STResList104],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb001.xml','./msxsdtest/Particles',valid,S104),
+ ITResList101 = [ITRes100|ITResList100],
+
+
+ ?line {STRes105,S105} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb002.xsd','./msxsdtest/Particles',valid),
+ STResList106 = [STRes105|STResList105],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb002.xml','./msxsdtest/Particles',invalid,S105),
+ ITResList102 = [ITRes101|ITResList101],
+
+
+ ?line {STRes106,S106} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb003.xsd','./msxsdtest/Particles',valid),
+ STResList107 = [STRes106|STResList106],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb003.xml','./msxsdtest/Particles',valid,S106),
+ ITResList103 = [ITRes102|ITResList102],
+
+
+ ?line {STRes107,S107} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb004.xsd','./msxsdtest/Particles',valid),
+ STResList108 = [STRes107|STResList107],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb004.xml','./msxsdtest/Particles',invalid,S107),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes108,S108} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb005.xsd','./msxsdtest/Particles',valid),
+ STResList109 = [STRes108|STResList108],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb005.xml','./msxsdtest/Particles',invalid,S108),
+ ITResList105 = [ITRes104|ITResList104],
+
+
+ ?line {STRes109,S109} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb006.xsd','./msxsdtest/Particles',valid),
+ STResList110 = [STRes109|STResList109],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb006.xml','./msxsdtest/Particles',invalid,S109),
+ ITResList106 = [ITRes105|ITResList105],
+
+
+ ?line {STRes110,S110} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb007.xsd','./msxsdtest/Particles',valid),
+ STResList111 = [STRes110|STResList110],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb007.xml','./msxsdtest/Particles',invalid,S110),
+ ITResList107 = [ITRes106|ITResList106],
+
+
+ ?line {STRes111,S111} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb008.xsd','./msxsdtest/Particles',valid),
+ STResList112 = [STRes111|STResList111],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb008.xml','./msxsdtest/Particles',invalid,S111),
+ ITResList108 = [ITRes107|ITResList107],
+
+
+ ?line {STRes112,S112} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb009.xsd','./msxsdtest/Particles',valid),
+ STResList113 = [STRes112|STResList112],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb009.xml','./msxsdtest/Particles',invalid,S112),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes113,S113} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb010.xsd','./msxsdtest/Particles',valid),
+ STResList114 = [STRes113|STResList113],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb010.xml','./msxsdtest/Particles',valid,S113),
+ ITResList110 = [ITRes109|ITResList109],
+
+
+ ?line {STRes114,S114} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb011.xsd','./msxsdtest/Particles',valid),
+ STResList115 = [STRes114|STResList114],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb011.xml','./msxsdtest/Particles',invalid,S114),
+ ITResList111 = [ITRes110|ITResList110],
+
+
+ ?line {STRes115,S115} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb012.xsd','./msxsdtest/Particles',valid),
+ STResList116 = [STRes115|STResList115],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb012.xml','./msxsdtest/Particles',invalid,S115),
+ ITResList112 = [ITRes111|ITResList111],
+
+
+ ?line {STRes116,S116} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb013.xsd','./msxsdtest/Particles',valid),
+ STResList117 = [STRes116|STResList116],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb013.xml','./msxsdtest/Particles',invalid,S116),
+ ITResList113 = [ITRes112|ITResList112],
+
+
+ ?line {STRes117,S117} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb014.xsd','./msxsdtest/Particles',valid),
+ STResList118 = [STRes117|STResList117],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb014.xml','./msxsdtest/Particles',invalid,S117),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes118,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb015.xsd','./msxsdtest/Particles',invalid),
+ STResList119 = [STRes118|STResList118],
+
+
+ ?line {STRes119,S119} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb016.xsd','./msxsdtest/Particles',valid),
+ STResList120 = [STRes119|STResList119],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb016.xml','./msxsdtest/Particles',valid,S119),
+ ITResList115 = [ITRes114|ITResList114],
+
+
+ ?line {STRes120,S120} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb017.xsd','./msxsdtest/Particles',valid),
+ STResList121 = [STRes120|STResList120],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb017.xml','./msxsdtest/Particles',invalid,S120),
+ ITResList116 = [ITRes115|ITResList115],
+
+
+ ?line {STRes121,S121} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb018.xsd','./msxsdtest/Particles',valid),
+ STResList122 = [STRes121|STResList121],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb018.xml','./msxsdtest/Particles',invalid,S121),
+ ITResList117 = [ITRes116|ITResList116],
+
+
+ ?line {STRes122,S122} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb019.xsd','./msxsdtest/Particles',valid),
+ STResList123 = [STRes122|STResList122],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb019.xml','./msxsdtest/Particles',valid,S122),
+ ITResList118 = [ITRes117|ITResList117],
+
+
+ ?line {STRes123,S123} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb020.xsd','./msxsdtest/Particles',valid),
+ STResList124 = [STRes123|STResList123],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb020.xml','./msxsdtest/Particles',invalid,S123),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes124,S124} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb021.xsd','./msxsdtest/Particles',valid),
+ STResList125 = [STRes124|STResList124],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb021.xml','./msxsdtest/Particles',invalid,S124),
+ ITResList120 = [ITRes119|ITResList119],
+
+
+ ?line {STRes125,S125} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb022.xsd','./msxsdtest/Particles',valid),
+ STResList126 = [STRes125|STResList125],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb022.xml','./msxsdtest/Particles',invalid,S125),
+ ITResList121 = [ITRes120|ITResList120],
+
+
+ ?line {STRes126,S126} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb023.xsd','./msxsdtest/Particles',valid),
+ STResList127 = [STRes126|STResList126],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb023.xml','./msxsdtest/Particles',invalid,S126),
+ ITResList122 = [ITRes121|ITResList121],
+
+
+ ?line {STRes127,S127} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb024.xsd','./msxsdtest/Particles',valid),
+ STResList128 = [STRes127|STResList127],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb024.xml','./msxsdtest/Particles',invalid,S127),
+ ITResList123 = [ITRes122|ITResList122],
+
+
+ ?line {STRes128,S128} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb025.xsd','./msxsdtest/Particles',valid),
+ STResList129 = [STRes128|STResList128],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb025.xml','./msxsdtest/Particles',invalid,S128),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes129,S129} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb026.xsd','./msxsdtest/Particles',valid),
+ STResList130 = [STRes129|STResList129],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb026.xml','./msxsdtest/Particles',valid,S129),
+ ITResList125 = [ITRes124|ITResList124],
+
+
+ ?line {STRes130,S130} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb027.xsd','./msxsdtest/Particles',valid),
+ STResList131 = [STRes130|STResList130],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb027.xml','./msxsdtest/Particles',valid,S130),
+ ITResList126 = [ITRes125|ITResList125],
+
+
+ ?line {STRes131,S131} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb028.xsd','./msxsdtest/Particles',valid),
+ STResList132 = [STRes131|STResList131],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb028.xml','./msxsdtest/Particles',invalid,S131),
+ ITResList127 = [ITRes126|ITResList126],
+
+
+ ?line {STRes132,S132} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb029.xsd','./msxsdtest/Particles',valid),
+ STResList133 = [STRes132|STResList132],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb029.xml','./msxsdtest/Particles',invalid,S132),
+ ITResList128 = [ITRes127|ITResList127],
+
+
+ ?line {STRes133,S133} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb030.xsd','./msxsdtest/Particles',valid),
+ STResList134 = [STRes133|STResList133],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb030.xml','./msxsdtest/Particles',invalid,S133),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes134,S134} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb031.xsd','./msxsdtest/Particles',valid),
+ STResList135 = [STRes134|STResList134],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb031.xml','./msxsdtest/Particles',invalid,S134),
+ ITResList130 = [ITRes129|ITResList129],
+
+
+ ?line {STRes135,S135} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb032.xsd','./msxsdtest/Particles',valid),
+ STResList136 = [STRes135|STResList135],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb032.xml','./msxsdtest/Particles',invalid,S135),
+ ITResList131 = [ITRes130|ITResList130],
+
+
+ ?line {STRes136,S136} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb033.xsd','./msxsdtest/Particles',valid),
+ STResList137 = [STRes136|STResList136],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb033.xml','./msxsdtest/Particles',invalid,S136),
+ ITResList132 = [ITRes131|ITResList131],
+
+
+ ?line {STRes137,S137} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb034.xsd','./msxsdtest/Particles',valid),
+ STResList138 = [STRes137|STResList137],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb034.xml','./msxsdtest/Particles',invalid,S137),
+ ITResList133 = [ITRes132|ITResList132],
+
+
+ ?line {STRes138,S138} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb035.xsd','./msxsdtest/Particles',valid),
+ STResList139 = [STRes138|STResList138],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb035.xml','./msxsdtest/Particles',invalid,S138),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes139,S139} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb036.xsd','./msxsdtest/Particles',valid),
+ STResList140 = [STRes139|STResList139],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb036.xml','./msxsdtest/Particles',valid,S139),
+ ITResList135 = [ITRes134|ITResList134],
+
+
+ ?line {STRes140,S140} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb037.xsd','./msxsdtest/Particles',valid),
+ STResList141 = [STRes140|STResList140],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb037.xml','./msxsdtest/Particles',invalid,S140),
+ ITResList136 = [ITRes135|ITResList135],
+
+
+ ?line {STRes141,S141} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb038.xsd','./msxsdtest/Particles',valid),
+ STResList142 = [STRes141|STResList141],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb038.xml','./msxsdtest/Particles',valid,S141),
+ ITResList137 = [ITRes136|ITResList136],
+
+
+ ?line {STRes142,S142} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEb039.xsd','./msxsdtest/Particles',valid),
+ STResList143 = [STRes142|STResList142],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEb039.xml','./msxsdtest/Particles',invalid,S142),
+ ITResList138 = [ITRes137|ITResList137],
+
+
+ ?line {STRes143,S143} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc001.xsd','./msxsdtest/Particles',valid),
+ STResList144 = [STRes143|STResList143],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc001.xml','./msxsdtest/Particles',valid,S143),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ ?line {STRes144,S144} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc002.xsd','./msxsdtest/Particles',valid),
+ STResList145 = [STRes144|STResList144],
+ ?line ITRes139 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc002.xml','./msxsdtest/Particles',valid,S144),
+ ITResList140 = [ITRes139|ITResList139],
+
+
+ ?line {STRes145,S145} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc003.xsd','./msxsdtest/Particles',valid),
+ STResList146 = [STRes145|STResList145],
+ ?line ITRes140 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc003.xml','./msxsdtest/Particles',invalid,S145),
+ ITResList141 = [ITRes140|ITResList140],
+
+
+ ?line {STRes146,S146} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc004.xsd','./msxsdtest/Particles',valid),
+ STResList147 = [STRes146|STResList146],
+ ?line ITRes141 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc004.xml','./msxsdtest/Particles',invalid,S146),
+ ITResList142 = [ITRes141|ITResList141],
+
+
+ ?line {STRes147,S147} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc005.xsd','./msxsdtest/Particles',valid),
+ STResList148 = [STRes147|STResList147],
+ ?line ITRes142 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc005.xml','./msxsdtest/Particles',invalid,S147),
+ ITResList143 = [ITRes142|ITResList142],
+
+
+ ?line {STRes148,S148} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc006.xsd','./msxsdtest/Particles',valid),
+ STResList149 = [STRes148|STResList148],
+ ?line ITRes143 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc006.xml','./msxsdtest/Particles',valid,S148),
+ ITResList144 = [ITRes143|ITResList143],
+
+
+ ?line {STRes149,S149} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc007.xsd','./msxsdtest/Particles',valid),
+ STResList150 = [STRes149|STResList149],
+ ?line ITRes144 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc007.xml','./msxsdtest/Particles',invalid,S149),
+ ITResList145 = [ITRes144|ITResList144],
+
+
+ ?line {STRes150,S150} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc008.xsd','./msxsdtest/Particles',valid),
+ STResList151 = [STRes150|STResList150],
+ ?line ITRes145 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc008.xml','./msxsdtest/Particles',invalid,S150),
+ ITResList146 = [ITRes145|ITResList145],
+
+
+ ?line {STRes151,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc009.xsd','./msxsdtest/Particles',invalid),
+ STResList152 = [STRes151|STResList151],
+
+
+ ?line {STRes152,S152} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc010.xsd','./msxsdtest/Particles',valid),
+ STResList153 = [STRes152|STResList152],
+ ?line ITRes146 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc010.xml','./msxsdtest/Particles',valid,S152),
+ ITResList147 = [ITRes146|ITResList146],
+
+
+ ?line {STRes153,S153} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc011.xsd','./msxsdtest/Particles',valid),
+ STResList154 = [STRes153|STResList153],
+ ?line ITRes147 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc011.xml','./msxsdtest/Particles',invalid,S153),
+ ITResList148 = [ITRes147|ITResList147],
+
+
+ ?line {STRes154,S154} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc012.xsd','./msxsdtest/Particles',valid),
+ STResList155 = [STRes154|STResList154],
+ ?line ITRes148 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc012.xml','./msxsdtest/Particles',valid,S154),
+ ITResList149 = [ITRes148|ITResList148],
+
+
+ ?line {STRes155,S155} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc013.xsd','./msxsdtest/Particles',valid),
+ STResList156 = [STRes155|STResList155],
+ ?line ITRes149 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc013.xml','./msxsdtest/Particles',invalid,S155),
+ ITResList150 = [ITRes149|ITResList149],
+
+
+ ?line {STRes156,S156} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc014.xsd','./msxsdtest/Particles',valid),
+ STResList157 = [STRes156|STResList156],
+ ?line ITRes150 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc014.xml','./msxsdtest/Particles',invalid,S156),
+ ITResList151 = [ITRes150|ITResList150],
+
+
+ ?line {STRes157,S157} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc015.xsd','./msxsdtest/Particles',valid),
+ STResList158 = [STRes157|STResList157],
+ ?line ITRes151 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc015.xml','./msxsdtest/Particles',invalid,S157),
+ ITResList152 = [ITRes151|ITResList151],
+
+
+ ?line {STRes158,S158} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc016.xsd','./msxsdtest/Particles',valid),
+ STResList159 = [STRes158|STResList158],
+ ?line ITRes152 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc016.xml','./msxsdtest/Particles',valid,S158),
+ ITResList153 = [ITRes152|ITResList152],
+
+
+ ?line {STRes159,S159} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc017.xsd','./msxsdtest/Particles',valid),
+ STResList160 = [STRes159|STResList159],
+ ?line ITRes153 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc017.xml','./msxsdtest/Particles',valid,S159),
+ ITResList154 = [ITRes153|ITResList153],
+
+
+ ?line {STRes160,S160} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc018.xsd','./msxsdtest/Particles',valid),
+ STResList161 = [STRes160|STResList160],
+ ?line ITRes154 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc018.xml','./msxsdtest/Particles',valid,S160),
+ ITResList155 = [ITRes154|ITResList154],
+
+
+ ?line {STRes161,S161} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc019.xsd','./msxsdtest/Particles',valid),
+ STResList162 = [STRes161|STResList161],
+ ?line ITRes155 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc019.xml','./msxsdtest/Particles',valid,S161),
+ ITResList156 = [ITRes155|ITResList155],
+
+
+ ?line {STRes162,S162} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc020.xsd','./msxsdtest/Particles',valid),
+ STResList163 = [STRes162|STResList162],
+ ?line ITRes156 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc020.xml','./msxsdtest/Particles',valid,S162),
+ ITResList157 = [ITRes156|ITResList156],
+
+
+ ?line {STRes163,S163} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc021.xsd','./msxsdtest/Particles',valid),
+ STResList164 = [STRes163|STResList163],
+ ?line ITRes157 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc021.xml','./msxsdtest/Particles',valid,S163),
+ ITResList158 = [ITRes157|ITResList157],
+
+
+ ?line {STRes164,S164} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc022.xsd','./msxsdtest/Particles',valid),
+ STResList165 = [STRes164|STResList164],
+ ?line ITRes158 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc022.xml','./msxsdtest/Particles',invalid,S164),
+ ITResList159 = [ITRes158|ITResList158],
+
+
+ ?line {STRes165,S165} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc023.xsd','./msxsdtest/Particles',valid),
+ STResList166 = [STRes165|STResList165],
+ ?line ITRes159 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc023.xml','./msxsdtest/Particles',invalid,S165),
+ ITResList160 = [ITRes159|ITResList159],
+
+
+ ?line {STRes166,S166} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc024.xsd','./msxsdtest/Particles',valid),
+ STResList167 = [STRes166|STResList166],
+ ?line ITRes160 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc024.xml','./msxsdtest/Particles',invalid,S166),
+ ITResList161 = [ITRes160|ITResList160],
+
+
+ ?line {STRes167,S167} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc025.xsd','./msxsdtest/Particles',valid),
+ STResList168 = [STRes167|STResList167],
+ ?line ITRes161 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc025.xml','./msxsdtest/Particles',invalid,S167),
+ ITResList162 = [ITRes161|ITResList161],
+
+
+ ?line {STRes168,S168} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc026.xsd','./msxsdtest/Particles',valid),
+ STResList169 = [STRes168|STResList168],
+ ?line ITRes162 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc026.xml','./msxsdtest/Particles',invalid,S168),
+ ITResList163 = [ITRes162|ITResList162],
+
+
+ ?line {STRes169,S169} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc027.xsd','./msxsdtest/Particles',valid),
+ STResList170 = [STRes169|STResList169],
+ ?line ITRes163 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc027.xml','./msxsdtest/Particles',invalid,S169),
+ ITResList164 = [ITRes163|ITResList163],
+
+
+ ?line {STRes170,S170} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc028.xsd','./msxsdtest/Particles',valid),
+ STResList171 = [STRes170|STResList170],
+ ?line ITRes164 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc028.xml','./msxsdtest/Particles',invalid,S170),
+ ITResList165 = [ITRes164|ITResList164],
+
+
+ ?line {STRes171,S171} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc029.xsd','./msxsdtest/Particles',valid),
+ STResList172 = [STRes171|STResList171],
+ ?line ITRes165 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc029.xml','./msxsdtest/Particles',valid,S171),
+ ITResList166 = [ITRes165|ITResList165],
+
+
+ ?line {STRes172,S172} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc030.xsd','./msxsdtest/Particles',valid),
+ STResList173 = [STRes172|STResList172],
+ ?line ITRes166 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc030.xml','./msxsdtest/Particles',valid,S172),
+ ITResList167 = [ITRes166|ITResList166],
+
+
+ ?line {STRes173,S173} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc031.xsd','./msxsdtest/Particles',valid),
+ STResList174 = [STRes173|STResList173],
+ ?line ITRes167 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc031.xml','./msxsdtest/Particles',valid,S173),
+ ITResList168 = [ITRes167|ITResList167],
+
+
+ ?line {STRes174,S174} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc032.xsd','./msxsdtest/Particles',valid),
+ STResList175 = [STRes174|STResList174],
+ ?line ITRes168 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc032.xml','./msxsdtest/Particles',valid,S174),
+ ITResList169 = [ITRes168|ITResList168],
+
+
+ ?line {STRes175,S175} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc033.xsd','./msxsdtest/Particles',valid),
+ STResList176 = [STRes175|STResList175],
+ ?line ITRes169 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc033.xml','./msxsdtest/Particles',valid,S175),
+ ITResList170 = [ITRes169|ITResList169],
+
+
+ ?line {STRes176,S176} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc034.xsd','./msxsdtest/Particles',valid),
+ STResList177 = [STRes176|STResList176],
+ ?line ITRes170 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc034.xml','./msxsdtest/Particles',valid,S176),
+ ITResList171 = [ITRes170|ITResList170],
+
+
+ ?line {STRes177,S177} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc035.xsd','./msxsdtest/Particles',valid),
+ STResList178 = [STRes177|STResList177],
+ ?line ITRes171 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc035.xml','./msxsdtest/Particles',valid,S177),
+ ITResList172 = [ITRes171|ITResList171],
+
+
+ ?line {STRes178,S178} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc036.xsd','./msxsdtest/Particles',valid),
+ STResList179 = [STRes178|STResList178],
+ ?line ITRes172 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc036.xml','./msxsdtest/Particles',valid,S178),
+ ITResList173 = [ITRes172|ITResList172],
+
+
+ ?line {STRes179,S179} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc037.xsd','./msxsdtest/Particles',valid),
+ STResList180 = [STRes179|STResList179],
+ ?line ITRes173 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc037.xml','./msxsdtest/Particles',valid,S179),
+ ITResList174 = [ITRes173|ITResList173],
+
+
+ ?line {STRes180,S180} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc038.xsd','./msxsdtest/Particles',valid),
+ STResList181 = [STRes180|STResList180],
+ ?line ITRes174 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc038.xml','./msxsdtest/Particles',invalid,S180),
+ ITResList175 = [ITRes174|ITResList174],
+
+
+ ?line {STRes181,S181} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc039.xsd','./msxsdtest/Particles',valid),
+ STResList182 = [STRes181|STResList181],
+ ?line ITRes175 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc039.xml','./msxsdtest/Particles',invalid,S181),
+ ITResList176 = [ITRes175|ITResList175],
+
+
+ ?line {STRes182,S182} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc040.xsd','./msxsdtest/Particles',valid),
+ STResList183 = [STRes182|STResList182],
+ ?line ITRes176 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc040.xml','./msxsdtest/Particles',invalid,S182),
+ ITResList177 = [ITRes176|ITResList176],
+
+
+ ?line {STRes183,S183} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEc041.xsd','./msxsdtest/Particles',valid),
+ STResList184 = [STRes183|STResList183],
+ ?line ITRes177 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesEc041.xml','./msxsdtest/Particles',invalid,S183),
+ ITResList178 = [ITRes177|ITResList177],
+
+
+ ?line {STRes184,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesEd001.xsd','./msxsdtest/Particles',invalid),
+ STResList185 = [STRes184|STResList184],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList185,ITResList178).
+
+%% 3.9.6 Schema Component Constraint: Particle ....
+
+particlesFHI(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesFa001.xsd','./msxsdtest/Particles',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesFa001.xml','./msxsdtest/Particles',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesFa002.xsd','./msxsdtest/Particles',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesFa002.xml','./msxsdtest/Particles',valid,S1),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesFa003.xsd','./msxsdtest/Particles',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesFa003.xml','./msxsdtest/Particles',valid,S2),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesFa004.xsd','./msxsdtest/Particles',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesFa004.xml','./msxsdtest/Particles',valid,S3),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesFa005.xsd','./msxsdtest/Particles',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesFa005.xml','./msxsdtest/Particles',valid,S4),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesFb001.xsd','./msxsdtest/Particles',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesFb001.xml','./msxsdtest/Particles',valid,S5),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes6,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesFb002.xsd','./msxsdtest/Particles',invalid),
+ STResList7 = [STRes6|STResList6],
+
+
+ ?line {STRes7,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesFb003.xsd','./msxsdtest/Particles',invalid),
+ STResList8 = [STRes7|STResList7],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesFb004.xsd','./msxsdtest/Particles',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesFb004.xml','./msxsdtest/Particles',valid,S8),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes9,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesFb005.xsd','./msxsdtest/Particles',invalid),
+ STResList10 = [STRes9|STResList9],
+
+
+ ?line {STRes10,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesFb006.xsd','./msxsdtest/Particles',invalid),
+ STResList11 = [STRes10|STResList10],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHa001.xsd','./msxsdtest/Particles',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesHa001.xml','./msxsdtest/Particles',valid,S11),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHa002.xsd','./msxsdtest/Particles',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesHa002.xml','./msxsdtest/Particles',valid,S12),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHa003.xsd','./msxsdtest/Particles',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesHa003.xml','./msxsdtest/Particles',valid,S13),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHa004.xsd','./msxsdtest/Particles',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesHa004.xml','./msxsdtest/Particles',valid,S14),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHa005.xsd','./msxsdtest/Particles',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesHa005.xml','./msxsdtest/Particles',valid,S15),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHa006.xsd','./msxsdtest/Particles',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesHa006.xml','./msxsdtest/Particles',valid,S16),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHa007.xsd','./msxsdtest/Particles',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesHa007.xml','./msxsdtest/Particles',valid,S17),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes18,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHa008.xsd','./msxsdtest/Particles',invalid),
+ STResList19 = [STRes18|STResList18],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHa009.xsd','./msxsdtest/Particles',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesHa009.xml','./msxsdtest/Particles',valid,S19),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHa010.xsd','./msxsdtest/Particles',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesHa010.xml','./msxsdtest/Particles',valid,S20),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHa011.xsd','./msxsdtest/Particles',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesHa011.xml','./msxsdtest/Particles',valid,S21),
+ ITResList17 = [ITRes16|ITResList16],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHa012.xsd','./msxsdtest/Particles',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesHa012.xml','./msxsdtest/Particles',valid,S22),
+ ITResList18 = [ITRes17|ITResList17],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHa013.xsd','./msxsdtest/Particles',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesHa013.xml','./msxsdtest/Particles',valid,S23),
+ ITResList19 = [ITRes18|ITResList18],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHa014.xsd','./msxsdtest/Particles',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesHa014.xml','./msxsdtest/Particles',valid,S24),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHa015.xsd','./msxsdtest/Particles',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesHa015.xml','./msxsdtest/Particles',valid,S25),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHa016.xsd','./msxsdtest/Particles',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesHa016.xml','./msxsdtest/Particles',valid,S26),
+ ITResList22 = [ITRes21|ITResList21],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHa017.xsd','./msxsdtest/Particles',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesHa017.xml','./msxsdtest/Particles',valid,S27),
+ ITResList23 = [ITRes22|ITResList22],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHa018.xsd','./msxsdtest/Particles',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesHa018.xml','./msxsdtest/Particles',valid,S28),
+ ITResList24 = [ITRes23|ITResList23],
+
+
+ ?line {STRes29,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHb001.xsd','./msxsdtest/Particles',invalid),
+ STResList30 = [STRes29|STResList29],
+
+
+ ?line {STRes30,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHb002.xsd','./msxsdtest/Particles',invalid),
+ STResList31 = [STRes30|STResList30],
+
+
+ ?line {STRes31,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHb003.xsd','./msxsdtest/Particles',invalid),
+ STResList32 = [STRes31|STResList31],
+
+
+ ?line {STRes32,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHb004.xsd','./msxsdtest/Particles',invalid),
+ STResList33 = [STRes32|STResList32],
+
+
+ ?line {STRes33,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHb006.xsd','./msxsdtest/Particles',invalid),
+ STResList34 = [STRes33|STResList33],
+
+
+ ?line {STRes34,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHb007.xsd','./msxsdtest/Particles',invalid),
+ STResList35 = [STRes34|STResList34],
+
+
+ ?line {STRes35,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHb008.xsd','./msxsdtest/Particles',invalid),
+ STResList36 = [STRes35|STResList35],
+
+
+ ?line {STRes36,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHb009.xsd','./msxsdtest/Particles',invalid),
+ STResList37 = [STRes36|STResList36],
+
+
+ ?line {STRes37,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHb010.xsd','./msxsdtest/Particles',invalid),
+ STResList38 = [STRes37|STResList37],
+
+
+ ?line {STRes38,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesHb011.xsd','./msxsdtest/Particles',invalid),
+ STResList39 = [STRes38|STResList38],
+
+
+ ?line {STRes39,S39} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIa001.xsd','./msxsdtest/Particles',valid),
+ STResList40 = [STRes39|STResList39],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIa001.xml','./msxsdtest/Particles',valid,S39),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes40,S40} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIa003.xsd','./msxsdtest/Particles',valid),
+ STResList41 = [STRes40|STResList40],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIa003.xml','./msxsdtest/Particles',valid,S40),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes41,S41} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIa004.xsd','./msxsdtest/Particles',valid),
+ STResList42 = [STRes41|STResList41],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIa004.xml','./msxsdtest/Particles',valid,S41),
+ ITResList27 = [ITRes26|ITResList26],
+
+
+ ?line {STRes42,S42} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIa005.xsd','./msxsdtest/Particles',valid),
+ STResList43 = [STRes42|STResList42],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIa005.xml','./msxsdtest/Particles',valid,S42),
+ ITResList28 = [ITRes27|ITResList27],
+
+
+ ?line {STRes43,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIa006.xsd','./msxsdtest/Particles',invalid),
+ STResList44 = [STRes43|STResList43],
+
+
+ ?line {STRes44,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIa008.xsd','./msxsdtest/Particles',invalid),
+ STResList45 = [STRes44|STResList44],
+
+
+ ?line {STRes45,S45} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIb001.xsd','./msxsdtest/Particles',valid),
+ STResList46 = [STRes45|STResList45],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIb001.xml','./msxsdtest/Particles',valid,S45),
+ ITResList29 = [ITRes28|ITResList28],
+
+
+ ?line {STRes46,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIb002.xsd','./msxsdtest/Particles',invalid),
+ STResList47 = [STRes46|STResList46],
+
+
+ ?line {STRes47,S47} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIb003.xsd','./msxsdtest/Particles',valid),
+ STResList48 = [STRes47|STResList47],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIb003.xml','./msxsdtest/Particles',valid,S47),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes48,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIb004.xsd','./msxsdtest/Particles',invalid),
+ STResList49 = [STRes48|STResList48],
+
+
+ ?line {STRes49,S49} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIb005.xsd','./msxsdtest/Particles',valid),
+ STResList50 = [STRes49|STResList49],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIb005.xml','./msxsdtest/Particles',valid,S49),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes50,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIb006.xsd','./msxsdtest/Particles',invalid),
+ STResList51 = [STRes50|STResList50],
+
+
+ ?line {STRes51,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIb007.xsd','./msxsdtest/Particles',invalid),
+ STResList52 = [STRes51|STResList51],
+
+
+ ?line {STRes52,S52} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIc001.xsd','./msxsdtest/Particles',valid),
+ STResList53 = [STRes52|STResList52],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIc001.xml','./msxsdtest/Particles',valid,S52),
+ ITResList32 = [ITRes31|ITResList31],
+
+
+ ?line {STRes53,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIc002.xsd','./msxsdtest/Particles',invalid),
+ STResList54 = [STRes53|STResList53],
+
+
+ ?line {STRes54,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIc003.xsd','./msxsdtest/Particles',invalid),
+ STResList55 = [STRes54|STResList54],
+
+
+ ?line {STRes55,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIc004.xsd','./msxsdtest/Particles',invalid),
+ STResList56 = [STRes55|STResList55],
+
+
+ ?line {STRes56,S56} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIc005.xsd','./msxsdtest/Particles',valid),
+ STResList57 = [STRes56|STResList56],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIc005.xml','./msxsdtest/Particles',valid,S56),
+ ITResList33 = [ITRes32|ITResList32],
+
+
+ ?line {STRes57,S57} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIc006.xsd','./msxsdtest/Particles',valid),
+ STResList58 = [STRes57|STResList57],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIc006.xml','./msxsdtest/Particles',valid,S57),
+ ITResList34 = [ITRes33|ITResList33],
+
+
+ ?line {STRes58,S58} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIc007.xsd','./msxsdtest/Particles',valid),
+ STResList59 = [STRes58|STResList58],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIc007.xml','./msxsdtest/Particles',valid,S58),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes59,S59} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesId001.xsd','./msxsdtest/Particles',valid),
+ STResList60 = [STRes59|STResList59],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesId001.xml','./msxsdtest/Particles',valid,S59),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes60,S60} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesId002.xsd','./msxsdtest/Particles',valid),
+ STResList61 = [STRes60|STResList60],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesId002.xml','./msxsdtest/Particles',valid,S60),
+ ITResList37 = [ITRes36|ITResList36],
+
+
+ ?line {STRes61,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesId003.xsd','./msxsdtest/Particles',invalid),
+ STResList62 = [STRes61|STResList61],
+
+
+ ?line {STRes62,S62} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesId004.xsd','./msxsdtest/Particles',valid),
+ STResList63 = [STRes62|STResList62],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesId004.xml','./msxsdtest/Particles',valid,S62),
+ ITResList38 = [ITRes37|ITResList37],
+
+
+ ?line {STRes63,S63} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesId005.xsd','./msxsdtest/Particles',valid),
+ STResList64 = [STRes63|STResList63],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesId005.xml','./msxsdtest/Particles',valid,S63),
+ ITResList39 = [ITRes38|ITResList38],
+
+
+ ?line {STRes64,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesId006.xsd','./msxsdtest/Particles',invalid),
+ STResList65 = [STRes64|STResList64],
+
+
+ ?line {STRes65,S65} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesId007.xsd','./msxsdtest/Particles',valid),
+ STResList66 = [STRes65|STResList65],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesId007.xml','./msxsdtest/Particles',valid,S65),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes66,S66} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesId008.xsd','./msxsdtest/Particles',valid),
+ STResList67 = [STRes66|STResList66],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesId008.xml','./msxsdtest/Particles',valid,S66),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes67,S67} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesId009.xsd','./msxsdtest/Particles',valid),
+ STResList68 = [STRes67|STResList67],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesId009.xml','./msxsdtest/Particles',valid,S67),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes68,S68} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesId010.xsd','./msxsdtest/Particles',valid),
+ STResList69 = [STRes68|STResList68],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesId010.xml','./msxsdtest/Particles',valid,S68),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes69,S69} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesId011.xsd','./msxsdtest/Particles',valid),
+ STResList70 = [STRes69|STResList69],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesId011.xml','./msxsdtest/Particles',valid,S69),
+ ITResList44 = [ITRes43|ITResList43],
+
+
+ ?line {STRes70,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesId012.xsd','./msxsdtest/Particles',invalid),
+ STResList71 = [STRes70|STResList70],
+
+
+ ?line {STRes71,S71} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIe001.xsd','./msxsdtest/Particles',valid),
+ STResList72 = [STRes71|STResList71],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIe001.xml','./msxsdtest/Particles',valid,S71),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes72,S72} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIe002.xsd','./msxsdtest/Particles',valid),
+ STResList73 = [STRes72|STResList72],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIe002.xml','./msxsdtest/Particles',valid,S72),
+ ITResList46 = [ITRes45|ITResList45],
+
+
+ ?line {STRes73,S73} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIe003.xsd','./msxsdtest/Particles',valid),
+ STResList74 = [STRes73|STResList73],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIe003.xml','./msxsdtest/Particles',valid,S73),
+ ITResList47 = [ITRes46|ITResList46],
+
+
+ ?line {STRes74,S74} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIe004.xsd','./msxsdtest/Particles',valid),
+ STResList75 = [STRes74|STResList74],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIe004.xml','./msxsdtest/Particles',valid,S74),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes75,S75} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIe005.xsd','./msxsdtest/Particles',valid),
+ STResList76 = [STRes75|STResList75],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIe005.xml','./msxsdtest/Particles',valid,S75),
+ ITResList49 = [ITRes48|ITResList48],
+
+
+ ?line {STRes76,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIe006.xsd','./msxsdtest/Particles',invalid),
+ STResList77 = [STRes76|STResList76],
+
+
+ ?line {STRes77,S77} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIe007.xsd','./msxsdtest/Particles',valid),
+ STResList78 = [STRes77|STResList77],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIe007.xml','./msxsdtest/Particles',valid,S77),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes78,S78} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIe008.xsd','./msxsdtest/Particles',valid),
+ STResList79 = [STRes78|STResList78],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIe008.xml','./msxsdtest/Particles',valid,S78),
+ ITResList51 = [ITRes50|ITResList50],
+
+
+ ?line {STRes79,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIe009.xsd','./msxsdtest/Particles',invalid),
+ STResList80 = [STRes79|STResList79],
+
+
+ ?line {STRes80,S80} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIe010.xsd','./msxsdtest/Particles',valid),
+ STResList81 = [STRes80|STResList80],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIe010.xml','./msxsdtest/Particles',valid,S80),
+ ITResList52 = [ITRes51|ITResList51],
+
+
+ ?line {STRes81,S81} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIe011.xsd','./msxsdtest/Particles',valid),
+ STResList82 = [STRes81|STResList81],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIe011.xml','./msxsdtest/Particles',valid,S81),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes82,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIe012.xsd','./msxsdtest/Particles',invalid),
+ STResList83 = [STRes82|STResList82],
+
+
+ ?line {STRes83,S83} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIe013.xsd','./msxsdtest/Particles',valid),
+ STResList84 = [STRes83|STResList83],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIe013.xml','./msxsdtest/Particles',valid,S83),
+ ITResList54 = [ITRes53|ITResList53],
+
+
+ ?line {STRes84,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIe014.xsd','./msxsdtest/Particles',invalid),
+ STResList85 = [STRes84|STResList84],
+
+
+ ?line {STRes85,S85} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIe015.xsd','./msxsdtest/Particles',valid),
+ STResList86 = [STRes85|STResList85],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIe015.xml','./msxsdtest/Particles',valid,S85),
+ ITResList55 = [ITRes54|ITResList54],
+
+
+ ?line {STRes86,S86} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIe016.xsd','./msxsdtest/Particles',valid),
+ STResList87 = [STRes86|STResList86],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIe016.xml','./msxsdtest/Particles',valid,S86),
+ ITResList56 = [ITRes55|ITResList55],
+
+
+ ?line {STRes87,S87} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIf001.xsd','./msxsdtest/Particles',valid),
+ STResList88 = [STRes87|STResList87],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIf001.xml','./msxsdtest/Particles',valid,S87),
+ ITResList57 = [ITRes56|ITResList56],
+
+
+ ?line {STRes88,S88} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIf002.xsd','./msxsdtest/Particles',valid),
+ STResList89 = [STRes88|STResList88],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIf002.xml','./msxsdtest/Particles',valid,S88),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes89,S89} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIf003.xsd','./msxsdtest/Particles',valid),
+ STResList90 = [STRes89|STResList89],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIf003.xml','./msxsdtest/Particles',valid,S89),
+ ITResList59 = [ITRes58|ITResList58],
+
+
+ ?line {STRes90,S90} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIf004.xsd','./msxsdtest/Particles',valid),
+ STResList91 = [STRes90|STResList90],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIf004.xml','./msxsdtest/Particles',valid,S90),
+ ITResList60 = [ITRes59|ITResList59],
+
+
+ ?line {STRes91,S91} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIf005.xsd','./msxsdtest/Particles',valid),
+ STResList92 = [STRes91|STResList91],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIf005.xml','./msxsdtest/Particles',valid,S91),
+ ITResList61 = [ITRes60|ITResList60],
+
+
+ ?line {STRes92,S92} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIf006.xsd','./msxsdtest/Particles',valid),
+ STResList93 = [STRes92|STResList92],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIf006.xml','./msxsdtest/Particles',valid,S92),
+ ITResList62 = [ITRes61|ITResList61],
+
+
+ ?line {STRes93,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIf007.xsd','./msxsdtest/Particles',invalid),
+ STResList94 = [STRes93|STResList93],
+
+
+ ?line {STRes94,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIf008.xsd','./msxsdtest/Particles',invalid),
+ STResList95 = [STRes94|STResList94],
+
+
+ ?line {STRes95,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIf009.xsd','./msxsdtest/Particles',invalid),
+ STResList96 = [STRes95|STResList95],
+
+
+ ?line {STRes96,S96} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIg001.xsd','./msxsdtest/Particles',valid),
+ STResList97 = [STRes96|STResList96],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIg001.xml','./msxsdtest/Particles',valid,S96),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes97,S97} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIg002.xsd','./msxsdtest/Particles',valid),
+ STResList98 = [STRes97|STResList97],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIg002.xml','./msxsdtest/Particles',valid,S97),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes98,S98} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIg003.xsd','./msxsdtest/Particles',valid),
+ STResList99 = [STRes98|STResList98],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIg003.xml','./msxsdtest/Particles',valid,S98),
+ ITResList65 = [ITRes64|ITResList64],
+
+
+ ?line {STRes99,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIg004.xsd','./msxsdtest/Particles',invalid),
+ STResList100 = [STRes99|STResList99],
+
+
+ ?line {STRes100,S100} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIg005.xsd','./msxsdtest/Particles',valid),
+ STResList101 = [STRes100|STResList100],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIg005.xml','./msxsdtest/Particles',valid,S100),
+ ITResList66 = [ITRes65|ITResList65],
+
+
+ ?line {STRes101,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIg006.xsd','./msxsdtest/Particles',invalid),
+ STResList102 = [STRes101|STResList101],
+
+
+ ?line {STRes102,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIg007.xsd','./msxsdtest/Particles',invalid),
+ STResList103 = [STRes102|STResList102],
+
+
+ ?line {STRes103,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIg008.xsd','./msxsdtest/Particles',invalid),
+ STResList104 = [STRes103|STResList103],
+
+
+ ?line {STRes104,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIg009.xsd','./msxsdtest/Particles',invalid),
+ STResList105 = [STRes104|STResList104],
+
+
+ ?line {STRes105,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIg010.xsd','./msxsdtest/Particles',invalid),
+ STResList106 = [STRes105|STResList105],
+
+
+ ?line {STRes106,S106} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIg011.xsd','./msxsdtest/Particles',valid),
+ STResList107 = [STRes106|STResList106],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIg011.xml','./msxsdtest/Particles',valid,S106),
+ ITResList67 = [ITRes66|ITResList66],
+
+
+ ?line {STRes107,S107} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIg012.xsd','./msxsdtest/Particles',valid),
+ STResList108 = [STRes107|STResList107],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIg012.xml','./msxsdtest/Particles',valid,S107),
+ ITResList68 = [ITRes67|ITResList67],
+
+
+ ?line {STRes108,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIg013.xsd','./msxsdtest/Particles',invalid),
+ STResList109 = [STRes108|STResList108],
+
+
+ ?line {STRes109,S109} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIg014.xsd','./msxsdtest/Particles',valid),
+ STResList110 = [STRes109|STResList109],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIg014.xml','./msxsdtest/Particles',valid,S109),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes110,S110} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIg015.xsd','./msxsdtest/Particles',valid),
+ STResList111 = [STRes110|STResList110],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIg015.xml','./msxsdtest/Particles',valid,S110),
+ ITResList70 = [ITRes69|ITResList69],
+
+
+ ?line {STRes111,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIg016.xsd','./msxsdtest/Particles',invalid),
+ STResList112 = [STRes111|STResList111],
+
+
+ ?line {STRes112,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIh001.xsd','./msxsdtest/Particles',invalid),
+ STResList113 = [STRes112|STResList112],
+
+
+ ?line {STRes113,S113} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIj001.xsd','./msxsdtest/Particles',valid),
+ STResList114 = [STRes113|STResList113],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIj001.xml','./msxsdtest/Particles',valid,S113),
+ ITResList71 = [ITRes70|ITResList70],
+
+
+ ?line {STRes114,S114} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIj002.xsd','./msxsdtest/Particles',valid),
+ STResList115 = [STRes114|STResList114],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIj002.xml','./msxsdtest/Particles',valid,S114),
+ ITResList72 = [ITRes71|ITResList71],
+
+
+ ?line {STRes115,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIj003.xsd','./msxsdtest/Particles',invalid),
+ STResList116 = [STRes115|STResList115],
+
+
+ ?line {STRes116,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIj004.xsd','./msxsdtest/Particles',invalid),
+ STResList117 = [STRes116|STResList116],
+
+
+ ?line {STRes117,S117} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIj005.xsd','./msxsdtest/Particles',valid),
+ STResList118 = [STRes117|STResList117],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIj005.xml','./msxsdtest/Particles',valid,S117),
+ ITResList73 = [ITRes72|ITResList72],
+
+
+ ?line {STRes118,S118} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIj006.xsd','./msxsdtest/Particles',valid),
+ STResList119 = [STRes118|STResList118],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIj006.xml','./msxsdtest/Particles',valid,S118),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes119,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIj007.xsd','./msxsdtest/Particles',invalid),
+ STResList120 = [STRes119|STResList119],
+
+
+ ?line {STRes120,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIj008.xsd','./msxsdtest/Particles',invalid),
+ STResList121 = [STRes120|STResList120],
+
+
+ ?line {STRes121,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIj009.xsd','./msxsdtest/Particles',invalid),
+ STResList122 = [STRes121|STResList121],
+
+
+ ?line {STRes122,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIj010.xsd','./msxsdtest/Particles',invalid),
+ STResList123 = [STRes122|STResList122],
+
+
+ ?line {STRes123,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIj011.xsd','./msxsdtest/Particles',invalid),
+ STResList124 = [STRes123|STResList123],
+
+
+ ?line {STRes124,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIj012.xsd','./msxsdtest/Particles',invalid),
+ STResList125 = [STRes124|STResList124],
+
+
+ ?line {STRes125,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIj013.xsd','./msxsdtest/Particles',invalid),
+ STResList126 = [STRes125|STResList125],
+
+
+ ?line {STRes126,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIj015.xsd','./msxsdtest/Particles',invalid),
+ STResList127 = [STRes126|STResList126],
+
+
+ ?line {STRes127,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIj016.xsd','./msxsdtest/Particles',invalid),
+ STResList128 = [STRes127|STResList127],
+
+
+ ?line {STRes128,S128} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk001.xsd','./msxsdtest/Particles',valid),
+ STResList129 = [STRes128|STResList128],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIk001.xml','./msxsdtest/Particles',valid,S128),
+ ITResList75 = [ITRes74|ITResList74],
+
+
+ ?line {STRes129,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk002.xsd','./msxsdtest/Particles',invalid),
+ STResList130 = [STRes129|STResList129],
+
+
+ ?line {STRes130,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk003.xsd','./msxsdtest/Particles',invalid),
+ STResList131 = [STRes130|STResList130],
+
+
+ ?line {STRes131,S131} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk004.xsd','./msxsdtest/Particles',valid),
+ STResList132 = [STRes131|STResList131],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIk004.xml','./msxsdtest/Particles',valid,S131),
+ ITResList76 = [ITRes75|ITResList75],
+
+
+ ?line {STRes132,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk005.xsd','./msxsdtest/Particles',invalid),
+ STResList133 = [STRes132|STResList132],
+
+
+ ?line {STRes133,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk006.xsd','./msxsdtest/Particles',invalid),
+ STResList134 = [STRes133|STResList133],
+
+
+ ?line {STRes134,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk007.xsd','./msxsdtest/Particles',invalid),
+ STResList135 = [STRes134|STResList134],
+
+
+ ?line {STRes135,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk008.xsd','./msxsdtest/Particles',invalid),
+ STResList136 = [STRes135|STResList135],
+
+
+ ?line {STRes136,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk009.xsd','./msxsdtest/Particles',invalid),
+ STResList137 = [STRes136|STResList136],
+
+
+ ?line {STRes137,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk010.xsd','./msxsdtest/Particles',invalid),
+ STResList138 = [STRes137|STResList137],
+
+
+ ?line {STRes138,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk011.xsd','./msxsdtest/Particles',invalid),
+ STResList139 = [STRes138|STResList138],
+
+
+ ?line {STRes139,S139} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk012.xsd','./msxsdtest/Particles',valid),
+ STResList140 = [STRes139|STResList139],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIk012.xml','./msxsdtest/Particles',valid,S139),
+ ITResList77 = [ITRes76|ITResList76],
+
+
+ ?line {STRes140,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk013.xsd','./msxsdtest/Particles',invalid),
+ STResList141 = [STRes140|STResList140],
+
+
+ ?line {STRes141,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk015.xsd','./msxsdtest/Particles',invalid),
+ STResList142 = [STRes141|STResList141],
+
+
+ ?line {STRes142,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk016.xsd','./msxsdtest/Particles',invalid),
+ STResList143 = [STRes142|STResList142],
+
+
+ ?line {STRes143,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk019.xsd','./msxsdtest/Particles',invalid),
+ STResList144 = [STRes143|STResList143],
+
+
+ ?line {STRes144,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk020.xsd','./msxsdtest/Particles',invalid),
+ STResList145 = [STRes144|STResList144],
+
+
+ ?line {STRes145,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk021.xsd','./msxsdtest/Particles',invalid),
+ STResList146 = [STRes145|STResList145],
+
+
+ ?line {STRes146,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk022.xsd','./msxsdtest/Particles',invalid),
+ STResList147 = [STRes146|STResList146],
+
+
+ ?line {STRes147,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk024.xsd','./msxsdtest/Particles',invalid),
+ STResList148 = [STRes147|STResList147],
+
+
+ ?line {STRes148,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk025.xsd','./msxsdtest/Particles',invalid),
+ STResList149 = [STRes148|STResList148],
+
+
+ ?line {STRes149,S149} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk026.xsd','./msxsdtest/Particles',valid),
+ STResList150 = [STRes149|STResList149],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesIk026.xml','./msxsdtest/Particles',valid,S149),
+ ITResList78 = [ITRes77|ITResList77],
+
+
+ ?line {STRes150,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesIk027.xsd','./msxsdtest/Particles',invalid),
+ STResList151 = [STRes150|STResList150],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList151,ITResList78).
+
+%% 3.9.6 Particle Derivation.
+
+particlesJ(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJa001.xsd','./msxsdtest/Particles',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJa001.xml','./msxsdtest/Particles',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJa002.xsd','./msxsdtest/Particles',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJa002.xml','./msxsdtest/Particles',valid,S1),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes2,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJa003.xsd','./msxsdtest/Particles',invalid),
+ STResList3 = [STRes2|STResList2],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJa004.xsd','./msxsdtest/Particles',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJa004.xml','./msxsdtest/Particles',valid,S3),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJa005.xsd','./msxsdtest/Particles',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJa005.xml','./msxsdtest/Particles',valid,S4),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes5,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJa006.xsd','./msxsdtest/Particles',invalid),
+ STResList6 = [STRes5|STResList5],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJa007.xsd','./msxsdtest/Particles',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJa007.xml','./msxsdtest/Particles',valid,S6),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJa008.xsd','./msxsdtest/Particles',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJa008.xml','./msxsdtest/Particles',valid,S7),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJa009.xsd','./msxsdtest/Particles',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJa009.xml','./msxsdtest/Particles',valid,S8),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJa010.xsd','./msxsdtest/Particles',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJa010.xml','./msxsdtest/Particles',valid,S9),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJa011.xsd','./msxsdtest/Particles',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJa011.xml','./msxsdtest/Particles',valid,S10),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes11,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJa012.xsd','./msxsdtest/Particles',invalid),
+ STResList12 = [STRes11|STResList11],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJb001.xsd','./msxsdtest/Particles',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJb001.xml','./msxsdtest/Particles',valid,S12),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJb002.xsd','./msxsdtest/Particles',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJb002.xml','./msxsdtest/Particles',valid,S13),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJb003.xsd','./msxsdtest/Particles',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJb003.xml','./msxsdtest/Particles',valid,S14),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJb004.xsd','./msxsdtest/Particles',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJb004.xml','./msxsdtest/Particles',valid,S15),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJb005.xsd','./msxsdtest/Particles',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJb005.xml','./msxsdtest/Particles',valid,S16),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes17,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJb006.xsd','./msxsdtest/Particles',invalid),
+ STResList18 = [STRes17|STResList17],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJb007.xsd','./msxsdtest/Particles',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJb007.xml','./msxsdtest/Particles',valid,S18),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJb008.xsd','./msxsdtest/Particles',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJb008.xml','./msxsdtest/Particles',valid,S19),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes20,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJb009.xsd','./msxsdtest/Particles',invalid),
+ STResList21 = [STRes20|STResList20],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJb010.xsd','./msxsdtest/Particles',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJb010.xml','./msxsdtest/Particles',valid,S21),
+ ITResList17 = [ITRes16|ITResList16],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJb011.xsd','./msxsdtest/Particles',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJb011.xml','./msxsdtest/Particles',valid,S22),
+ ITResList18 = [ITRes17|ITResList17],
+
+
+ ?line {STRes23,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJb012.xsd','./msxsdtest/Particles',invalid),
+ STResList24 = [STRes23|STResList23],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJb013.xsd','./msxsdtest/Particles',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJb013.xml','./msxsdtest/Particles',valid,S24),
+ ITResList19 = [ITRes18|ITResList18],
+
+
+ ?line {STRes25,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJb014.xsd','./msxsdtest/Particles',invalid),
+ STResList26 = [STRes25|STResList25],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJb015.xsd','./msxsdtest/Particles',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJb015.xml','./msxsdtest/Particles',valid,S26),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJb016.xsd','./msxsdtest/Particles',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJb016.xml','./msxsdtest/Particles',valid,S27),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJc001.xsd','./msxsdtest/Particles',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJc001.xml','./msxsdtest/Particles',valid,S28),
+ ITResList22 = [ITRes21|ITResList21],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJc002.xsd','./msxsdtest/Particles',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJc002.xml','./msxsdtest/Particles',valid,S29),
+ ITResList23 = [ITRes22|ITResList22],
+
+
+ ?line {STRes30,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJc003.xsd','./msxsdtest/Particles',invalid),
+ STResList31 = [STRes30|STResList30],
+
+
+ ?line {STRes31,S31} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJc004.xsd','./msxsdtest/Particles',valid),
+ STResList32 = [STRes31|STResList31],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJc004.xml','./msxsdtest/Particles',valid,S31),
+ ITResList24 = [ITRes23|ITResList23],
+
+
+ ?line {STRes32,S32} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJc005.xsd','./msxsdtest/Particles',valid),
+ STResList33 = [STRes32|STResList32],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJc005.xml','./msxsdtest/Particles',valid,S32),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes33,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJc006.xsd','./msxsdtest/Particles',invalid),
+ STResList34 = [STRes33|STResList33],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJc007.xsd','./msxsdtest/Particles',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJc007.xml','./msxsdtest/Particles',valid,S34),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes35,S35} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJc008.xsd','./msxsdtest/Particles',valid),
+ STResList36 = [STRes35|STResList35],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJc008.xml','./msxsdtest/Particles',valid,S35),
+ ITResList27 = [ITRes26|ITResList26],
+
+
+ ?line {STRes36,S36} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJc009.xsd','./msxsdtest/Particles',valid),
+ STResList37 = [STRes36|STResList36],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJc009.xml','./msxsdtest/Particles',valid,S36),
+ ITResList28 = [ITRes27|ITResList27],
+
+
+ ?line {STRes37,S37} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJc010.xsd','./msxsdtest/Particles',valid),
+ STResList38 = [STRes37|STResList37],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJc010.xml','./msxsdtest/Particles',valid,S37),
+ ITResList29 = [ITRes28|ITResList28],
+
+
+ ?line {STRes38,S38} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJc011.xsd','./msxsdtest/Particles',valid),
+ STResList39 = [STRes38|STResList38],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJc011.xml','./msxsdtest/Particles',valid,S38),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes39,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJc012.xsd','./msxsdtest/Particles',invalid),
+ STResList40 = [STRes39|STResList39],
+
+
+ ?line {STRes40,S40} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJd001.xsd','./msxsdtest/Particles',valid),
+ STResList41 = [STRes40|STResList40],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJd001.xml','./msxsdtest/Particles',valid,S40),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes41,S41} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJd002.xsd','./msxsdtest/Particles',valid),
+ STResList42 = [STRes41|STResList41],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJd002.xml','./msxsdtest/Particles',valid,S41),
+ ITResList32 = [ITRes31|ITResList31],
+
+
+ ?line {STRes42,S42} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJd003.xsd','./msxsdtest/Particles',valid),
+ STResList43 = [STRes42|STResList42],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJd003.xml','./msxsdtest/Particles',valid,S42),
+ ITResList33 = [ITRes32|ITResList32],
+
+
+ ?line {STRes43,S43} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJd004.xsd','./msxsdtest/Particles',valid),
+ STResList44 = [STRes43|STResList43],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJd004.xml','./msxsdtest/Particles',valid,S43),
+ ITResList34 = [ITRes33|ITResList33],
+
+
+ ?line {STRes44,S44} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJd005.xsd','./msxsdtest/Particles',valid),
+ STResList45 = [STRes44|STResList44],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJd005.xml','./msxsdtest/Particles',valid,S44),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes45,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJd006.xsd','./msxsdtest/Particles',invalid),
+ STResList46 = [STRes45|STResList45],
+
+
+ ?line {STRes46,S46} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJd007.xsd','./msxsdtest/Particles',valid),
+ STResList47 = [STRes46|STResList46],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJd007.xml','./msxsdtest/Particles',valid,S46),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes47,S47} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJd008.xsd','./msxsdtest/Particles',valid),
+ STResList48 = [STRes47|STResList47],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJd008.xml','./msxsdtest/Particles',valid,S47),
+ ITResList37 = [ITRes36|ITResList36],
+
+
+ ?line {STRes48,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJd009.xsd','./msxsdtest/Particles',invalid),
+ STResList49 = [STRes48|STResList48],
+
+
+ ?line {STRes49,S49} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJd010.xsd','./msxsdtest/Particles',valid),
+ STResList50 = [STRes49|STResList49],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJd010.xml','./msxsdtest/Particles',valid,S49),
+ ITResList38 = [ITRes37|ITResList37],
+
+
+ ?line {STRes50,S50} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJd011.xsd','./msxsdtest/Particles',valid),
+ STResList51 = [STRes50|STResList50],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJd011.xml','./msxsdtest/Particles',valid,S50),
+ ITResList39 = [ITRes38|ITResList38],
+
+
+ ?line {STRes51,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJd012.xsd','./msxsdtest/Particles',invalid),
+ STResList52 = [STRes51|STResList51],
+
+
+ ?line {STRes52,S52} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJd013.xsd','./msxsdtest/Particles',valid),
+ STResList53 = [STRes52|STResList52],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJd013.xml','./msxsdtest/Particles',valid,S52),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes53,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJd014.xsd','./msxsdtest/Particles',invalid),
+ STResList54 = [STRes53|STResList53],
+
+
+ ?line {STRes54,S54} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJd015.xsd','./msxsdtest/Particles',valid),
+ STResList55 = [STRes54|STResList54],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJd015.xml','./msxsdtest/Particles',valid,S54),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes55,S55} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJd016.xsd','./msxsdtest/Particles',valid),
+ STResList56 = [STRes55|STResList55],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJd016.xml','./msxsdtest/Particles',valid,S55),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes56,S56} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJe001.xsd','./msxsdtest/Particles',valid),
+ STResList57 = [STRes56|STResList56],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJe001.xml','./msxsdtest/Particles',valid,S56),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes57,S57} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJe002.xsd','./msxsdtest/Particles',valid),
+ STResList58 = [STRes57|STResList57],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJe002.xml','./msxsdtest/Particles',valid,S57),
+ ITResList44 = [ITRes43|ITResList43],
+
+
+ ?line {STRes58,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJe003.xsd','./msxsdtest/Particles',invalid),
+ STResList59 = [STRes58|STResList58],
+
+
+ ?line {STRes59,S59} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJe004.xsd','./msxsdtest/Particles',valid),
+ STResList60 = [STRes59|STResList59],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJe004.xml','./msxsdtest/Particles',valid,S59),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes60,S60} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJe005.xsd','./msxsdtest/Particles',valid),
+ STResList61 = [STRes60|STResList60],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJe005.xml','./msxsdtest/Particles',valid,S60),
+ ITResList46 = [ITRes45|ITResList45],
+
+
+ ?line {STRes61,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJe006.xsd','./msxsdtest/Particles',invalid),
+ STResList62 = [STRes61|STResList61],
+
+
+ ?line {STRes62,S62} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJe007.xsd','./msxsdtest/Particles',valid),
+ STResList63 = [STRes62|STResList62],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJe007.xml','./msxsdtest/Particles',valid,S62),
+ ITResList47 = [ITRes46|ITResList46],
+
+
+ ?line {STRes63,S63} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJe008.xsd','./msxsdtest/Particles',valid),
+ STResList64 = [STRes63|STResList63],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJe008.xml','./msxsdtest/Particles',valid,S63),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes64,S64} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJe009.xsd','./msxsdtest/Particles',valid),
+ STResList65 = [STRes64|STResList64],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJe009.xml','./msxsdtest/Particles',valid,S64),
+ ITResList49 = [ITRes48|ITResList48],
+
+
+ ?line {STRes65,S65} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJe010.xsd','./msxsdtest/Particles',valid),
+ STResList66 = [STRes65|STResList65],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJe010.xml','./msxsdtest/Particles',valid,S65),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes66,S66} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJe011.xsd','./msxsdtest/Particles',valid),
+ STResList67 = [STRes66|STResList66],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJe011.xml','./msxsdtest/Particles',valid,S66),
+ ITResList51 = [ITRes50|ITResList50],
+
+
+ ?line {STRes67,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJe012.xsd','./msxsdtest/Particles',invalid),
+ STResList68 = [STRes67|STResList67],
+
+
+ ?line {STRes68,S68} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJf001.xsd','./msxsdtest/Particles',valid),
+ STResList69 = [STRes68|STResList68],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJf001.xml','./msxsdtest/Particles',valid,S68),
+ ITResList52 = [ITRes51|ITResList51],
+
+
+ ?line {STRes69,S69} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJf002.xsd','./msxsdtest/Particles',valid),
+ STResList70 = [STRes69|STResList69],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJf002.xml','./msxsdtest/Particles',valid,S69),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes70,S70} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJf003.xsd','./msxsdtest/Particles',valid),
+ STResList71 = [STRes70|STResList70],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJf003.xml','./msxsdtest/Particles',valid,S70),
+ ITResList54 = [ITRes53|ITResList53],
+
+
+ ?line {STRes71,S71} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJf004.xsd','./msxsdtest/Particles',valid),
+ STResList72 = [STRes71|STResList71],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJf004.xml','./msxsdtest/Particles',valid,S71),
+ ITResList55 = [ITRes54|ITResList54],
+
+
+ ?line {STRes72,S72} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJf005.xsd','./msxsdtest/Particles',valid),
+ STResList73 = [STRes72|STResList72],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJf005.xml','./msxsdtest/Particles',valid,S72),
+ ITResList56 = [ITRes55|ITResList55],
+
+
+ ?line {STRes73,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJf006.xsd','./msxsdtest/Particles',invalid),
+ STResList74 = [STRes73|STResList73],
+
+
+ ?line {STRes74,S74} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJf007.xsd','./msxsdtest/Particles',valid),
+ STResList75 = [STRes74|STResList74],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJf007.xml','./msxsdtest/Particles',valid,S74),
+ ITResList57 = [ITRes56|ITResList56],
+
+
+ ?line {STRes75,S75} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJf008.xsd','./msxsdtest/Particles',valid),
+ STResList76 = [STRes75|STResList75],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJf008.xml','./msxsdtest/Particles',valid,S75),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes76,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJf009.xsd','./msxsdtest/Particles',invalid),
+ STResList77 = [STRes76|STResList76],
+
+
+ ?line {STRes77,S77} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJf010.xsd','./msxsdtest/Particles',valid),
+ STResList78 = [STRes77|STResList77],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJf010.xml','./msxsdtest/Particles',valid,S77),
+ ITResList59 = [ITRes58|ITResList58],
+
+
+ ?line {STRes78,S78} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJf011.xsd','./msxsdtest/Particles',valid),
+ STResList79 = [STRes78|STResList78],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJf011.xml','./msxsdtest/Particles',valid,S78),
+ ITResList60 = [ITRes59|ITResList59],
+
+
+ ?line {STRes79,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJf012.xsd','./msxsdtest/Particles',invalid),
+ STResList80 = [STRes79|STResList79],
+
+
+ ?line {STRes80,S80} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJf013.xsd','./msxsdtest/Particles',valid),
+ STResList81 = [STRes80|STResList80],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJf013.xml','./msxsdtest/Particles',valid,S80),
+ ITResList61 = [ITRes60|ITResList60],
+
+
+ ?line {STRes81,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJf014.xsd','./msxsdtest/Particles',invalid),
+ STResList82 = [STRes81|STResList81],
+
+
+ ?line {STRes82,S82} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJf015.xsd','./msxsdtest/Particles',valid),
+ STResList83 = [STRes82|STResList82],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJf015.xml','./msxsdtest/Particles',valid,S82),
+ ITResList62 = [ITRes61|ITResList61],
+
+
+ ?line {STRes83,S83} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJf016.xsd','./msxsdtest/Particles',valid),
+ STResList84 = [STRes83|STResList83],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJf016.xml','./msxsdtest/Particles',valid,S83),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes84,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJg001.xsd','./msxsdtest/Particles',invalid),
+ STResList85 = [STRes84|STResList84],
+
+
+ ?line {STRes85,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJh001.xsd','./msxsdtest/Particles',invalid),
+ STResList86 = [STRes85|STResList85],
+
+
+ ?line {STRes86,S86} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJj001.xsd','./msxsdtest/Particles',valid),
+ STResList87 = [STRes86|STResList86],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJj001.xml','./msxsdtest/Particles',valid,S86),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes87,S87} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJj002.xsd','./msxsdtest/Particles',valid),
+ STResList88 = [STRes87|STResList87],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJj002.xml','./msxsdtest/Particles',valid,S87),
+ ITResList65 = [ITRes64|ITResList64],
+
+
+ ?line {STRes88,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJj003.xsd','./msxsdtest/Particles',invalid),
+ STResList89 = [STRes88|STResList88],
+
+
+ ?line {STRes89,S89} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJj004.xsd','./msxsdtest/Particles',valid),
+ STResList90 = [STRes89|STResList89],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJj004.xml','./msxsdtest/Particles',valid,S89),
+ ITResList66 = [ITRes65|ITResList65],
+
+
+ ?line {STRes90,S90} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJj005.xsd','./msxsdtest/Particles',valid),
+ STResList91 = [STRes90|STResList90],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJj005.xml','./msxsdtest/Particles',valid,S90),
+ ITResList67 = [ITRes66|ITResList66],
+
+
+ ?line {STRes91,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJj006.xsd','./msxsdtest/Particles',invalid),
+ STResList92 = [STRes91|STResList91],
+
+
+ ?line {STRes92,S92} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJj007.xsd','./msxsdtest/Particles',valid),
+ STResList93 = [STRes92|STResList92],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJj007.xml','./msxsdtest/Particles',valid,S92),
+ ITResList68 = [ITRes67|ITResList67],
+
+
+ ?line {STRes93,S93} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJj008.xsd','./msxsdtest/Particles',valid),
+ STResList94 = [STRes93|STResList93],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJj008.xml','./msxsdtest/Particles',valid,S93),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes94,S94} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJj009.xsd','./msxsdtest/Particles',valid),
+ STResList95 = [STRes94|STResList94],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJj009.xml','./msxsdtest/Particles',valid,S94),
+ ITResList70 = [ITRes69|ITResList69],
+
+
+ ?line {STRes95,S95} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJj010.xsd','./msxsdtest/Particles',valid),
+ STResList96 = [STRes95|STResList95],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJj010.xml','./msxsdtest/Particles',valid,S95),
+ ITResList71 = [ITRes70|ITResList70],
+
+
+ ?line {STRes96,S96} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJj011.xsd','./msxsdtest/Particles',valid),
+ STResList97 = [STRes96|STResList96],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJj011.xml','./msxsdtest/Particles',valid,S96),
+ ITResList72 = [ITRes71|ITResList71],
+
+
+ ?line {STRes97,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJj012.xsd','./msxsdtest/Particles',invalid),
+ STResList98 = [STRes97|STResList97],
+
+
+ ?line {STRes98,S98} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJk001.xsd','./msxsdtest/Particles',valid),
+ STResList99 = [STRes98|STResList98],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJk001.xml','./msxsdtest/Particles',valid,S98),
+ ITResList73 = [ITRes72|ITResList72],
+
+
+ ?line {STRes99,S99} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJk002.xsd','./msxsdtest/Particles',valid),
+ STResList100 = [STRes99|STResList99],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJk002.xml','./msxsdtest/Particles',valid,S99),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes100,S100} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJk003.xsd','./msxsdtest/Particles',valid),
+ STResList101 = [STRes100|STResList100],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJk003.xml','./msxsdtest/Particles',valid,S100),
+ ITResList75 = [ITRes74|ITResList74],
+
+
+ ?line {STRes101,S101} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJk004.xsd','./msxsdtest/Particles',valid),
+ STResList102 = [STRes101|STResList101],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJk004.xml','./msxsdtest/Particles',valid,S101),
+ ITResList76 = [ITRes75|ITResList75],
+
+
+ ?line {STRes102,S102} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJk005.xsd','./msxsdtest/Particles',valid),
+ STResList103 = [STRes102|STResList102],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJk005.xml','./msxsdtest/Particles',valid,S102),
+ ITResList77 = [ITRes76|ITResList76],
+
+
+ ?line {STRes103,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJk006.xsd','./msxsdtest/Particles',invalid),
+ STResList104 = [STRes103|STResList103],
+
+
+ ?line {STRes104,S104} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJk007.xsd','./msxsdtest/Particles',valid),
+ STResList105 = [STRes104|STResList104],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJk007.xml','./msxsdtest/Particles',valid,S104),
+ ITResList78 = [ITRes77|ITResList77],
+
+
+ ?line {STRes105,S105} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJk008.xsd','./msxsdtest/Particles',valid),
+ STResList106 = [STRes105|STResList105],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJk008.xml','./msxsdtest/Particles',valid,S105),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes106,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJk009.xsd','./msxsdtest/Particles',invalid),
+ STResList107 = [STRes106|STResList106],
+
+
+ ?line {STRes107,S107} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJk010.xsd','./msxsdtest/Particles',valid),
+ STResList108 = [STRes107|STResList107],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJk010.xml','./msxsdtest/Particles',valid,S107),
+ ITResList80 = [ITRes79|ITResList79],
+
+
+ ?line {STRes108,S108} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJk011.xsd','./msxsdtest/Particles',valid),
+ STResList109 = [STRes108|STResList108],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJk011.xml','./msxsdtest/Particles',valid,S108),
+ ITResList81 = [ITRes80|ITResList80],
+
+
+ ?line {STRes109,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJk012.xsd','./msxsdtest/Particles',invalid),
+ STResList110 = [STRes109|STResList109],
+
+
+ ?line {STRes110,S110} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJk013.xsd','./msxsdtest/Particles',valid),
+ STResList111 = [STRes110|STResList110],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJk013.xml','./msxsdtest/Particles',valid,S110),
+ ITResList82 = [ITRes81|ITResList81],
+
+
+ ?line {STRes111,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJk014.xsd','./msxsdtest/Particles',invalid),
+ STResList112 = [STRes111|STResList111],
+
+
+ ?line {STRes112,S112} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesJk015.xsd','./msxsdtest/Particles',valid),
+ STResList113 = [STRes112|STResList112],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesJk015.xml','./msxsdtest/Particles',valid,S112),
+ ITResList83 = [ITRes82|ITResList82],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList113,ITResList83).
+
+%% 3.9.6 Particle Restriction.
+
+particlesKOSRTQUVW(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesK001.xsd','./msxsdtest/Particles',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesK001.xml','./msxsdtest/Particles',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesK002.xsd','./msxsdtest/Particles',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesK002.xml','./msxsdtest/Particles',valid,S1),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesK003.xsd','./msxsdtest/Particles',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesK003.xml','./msxsdtest/Particles',valid,S2),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes3,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesK004.xsd','./msxsdtest/Particles',invalid),
+ STResList4 = [STRes3|STResList3],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesK005.xsd','./msxsdtest/Particles',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesK005.xml','./msxsdtest/Particles',valid,S4),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes5,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesK006.xsd','./msxsdtest/Particles',invalid),
+ STResList6 = [STRes5|STResList5],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesK008.xsd','./msxsdtest/Particles',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesK008.xml','./msxsdtest/Particles',valid,S6),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOa001.xsd','./msxsdtest/Particles',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOa001.xml','./msxsdtest/Particles',valid,S7),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes8,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOa002.xsd','./msxsdtest/Particles',invalid),
+ STResList9 = [STRes8|STResList8],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOa003.xsd','./msxsdtest/Particles',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOa003.xml','./msxsdtest/Particles',valid,S9),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes10,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOa004.xsd','./msxsdtest/Particles',invalid),
+ STResList11 = [STRes10|STResList10],
+
+
+ ?line {STRes11,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOa005.xsd','./msxsdtest/Particles',invalid),
+ STResList12 = [STRes11|STResList11],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOa006.xsd','./msxsdtest/Particles',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOa006.xml','./msxsdtest/Particles',valid,S12),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes13,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOa007.xsd','./msxsdtest/Particles',invalid),
+ STResList14 = [STRes13|STResList13],
+
+
+ ?line {STRes14,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOa008.xsd','./msxsdtest/Particles',invalid),
+ STResList15 = [STRes14|STResList14],
+
+
+ ?line {STRes15,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOa009.xsd','./msxsdtest/Particles',invalid),
+ STResList16 = [STRes15|STResList15],
+
+
+ ?line {STRes16,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOa010.xsd','./msxsdtest/Particles',invalid),
+ STResList17 = [STRes16|STResList16],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOa011.xsd','./msxsdtest/Particles',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOa011.xml','./msxsdtest/Particles',valid,S17),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOa012.xsd','./msxsdtest/Particles',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOa012.xml','./msxsdtest/Particles',valid,S18),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOa013.xsd','./msxsdtest/Particles',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOa013.xml','./msxsdtest/Particles',valid,S19),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOa014.xsd','./msxsdtest/Particles',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOa014.xml','./msxsdtest/Particles',valid,S20),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes21,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOa015.xsd','./msxsdtest/Particles',invalid),
+ STResList22 = [STRes21|STResList21],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb001.xsd','./msxsdtest/Particles',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb001.xml','./msxsdtest/Particles',valid,S22),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb002.xsd','./msxsdtest/Particles',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb002.xml','./msxsdtest/Particles',valid,S23),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb003.xsd','./msxsdtest/Particles',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb003.xml','./msxsdtest/Particles',valid,S24),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb004.xsd','./msxsdtest/Particles',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb004.xml','./msxsdtest/Particles',valid,S25),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb005.xsd','./msxsdtest/Particles',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb005.xml','./msxsdtest/Particles',valid,S26),
+ ITResList17 = [ITRes16|ITResList16],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb006.xsd','./msxsdtest/Particles',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb006.xml','./msxsdtest/Particles',valid,S27),
+ ITResList18 = [ITRes17|ITResList17],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb007.xsd','./msxsdtest/Particles',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb007.xml','./msxsdtest/Particles',valid,S28),
+ ITResList19 = [ITRes18|ITResList18],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb008.xsd','./msxsdtest/Particles',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb008.xml','./msxsdtest/Particles',valid,S29),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb009.xsd','./msxsdtest/Particles',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb009.xml','./msxsdtest/Particles',valid,S30),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes31,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb010.xsd','./msxsdtest/Particles',invalid),
+ STResList32 = [STRes31|STResList31],
+
+
+ ?line {STRes32,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb011.xsd','./msxsdtest/Particles',invalid),
+ STResList33 = [STRes32|STResList32],
+
+
+ ?line {STRes33,S33} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb012.xsd','./msxsdtest/Particles',valid),
+ STResList34 = [STRes33|STResList33],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb012.xml','./msxsdtest/Particles',valid,S33),
+ ITResList22 = [ITRes21|ITResList21],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb013.xsd','./msxsdtest/Particles',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb013.xml','./msxsdtest/Particles',valid,S34),
+ ITResList23 = [ITRes22|ITResList22],
+
+
+ ?line {STRes35,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb014.xsd','./msxsdtest/Particles',invalid),
+ STResList36 = [STRes35|STResList35],
+
+
+ ?line {STRes36,S36} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb015.xsd','./msxsdtest/Particles',valid),
+ STResList37 = [STRes36|STResList36],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb015.xml','./msxsdtest/Particles',valid,S36),
+ ITResList24 = [ITRes23|ITResList23],
+
+
+ ?line {STRes37,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb016.xsd','./msxsdtest/Particles',invalid),
+ STResList38 = [STRes37|STResList37],
+
+
+ ?line {STRes38,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb017.xsd','./msxsdtest/Particles',invalid),
+ STResList39 = [STRes38|STResList38],
+
+
+ ?line {STRes39,S39} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb018.xsd','./msxsdtest/Particles',valid),
+ STResList40 = [STRes39|STResList39],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb018.xml','./msxsdtest/Particles',valid,S39),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes40,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb019.xsd','./msxsdtest/Particles',invalid),
+ STResList41 = [STRes40|STResList40],
+
+
+ ?line {STRes41,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb020.xsd','./msxsdtest/Particles',invalid),
+ STResList42 = [STRes41|STResList41],
+
+
+ ?line {STRes42,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb021.xsd','./msxsdtest/Particles',invalid),
+ STResList43 = [STRes42|STResList42],
+
+
+ ?line {STRes43,S43} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb022.xsd','./msxsdtest/Particles',valid),
+ STResList44 = [STRes43|STResList43],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb022.xml','./msxsdtest/Particles',valid,S43),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes44,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb023.xsd','./msxsdtest/Particles',invalid),
+ STResList45 = [STRes44|STResList44],
+
+
+ ?line {STRes45,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb024.xsd','./msxsdtest/Particles',invalid),
+ STResList46 = [STRes45|STResList45],
+
+
+ ?line {STRes46,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb025.xsd','./msxsdtest/Particles',invalid),
+ STResList47 = [STRes46|STResList46],
+
+
+ ?line {STRes47,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb026.xsd','./msxsdtest/Particles',invalid),
+ STResList48 = [STRes47|STResList47],
+
+
+ ?line {STRes48,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb027.xsd','./msxsdtest/Particles',invalid),
+ STResList49 = [STRes48|STResList48],
+
+
+ ?line {STRes49,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb028.xsd','./msxsdtest/Particles',invalid),
+ STResList50 = [STRes49|STResList49],
+
+
+ ?line {STRes50,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb029.xsd','./msxsdtest/Particles',invalid),
+ STResList51 = [STRes50|STResList50],
+
+
+ ?line {STRes51,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb030.xsd','./msxsdtest/Particles',invalid),
+ STResList52 = [STRes51|STResList51],
+
+
+ ?line {STRes52,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb031.xsd','./msxsdtest/Particles',invalid),
+ STResList53 = [STRes52|STResList52],
+
+
+ ?line {STRes53,S53} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb032.xsd','./msxsdtest/Particles',valid),
+ STResList54 = [STRes53|STResList53],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb032.xml','./msxsdtest/Particles',valid,S53),
+ ITResList27 = [ITRes26|ITResList26],
+
+
+ ?line {STRes54,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb033.xsd','./msxsdtest/Particles',invalid),
+ STResList55 = [STRes54|STResList54],
+
+
+ ?line {STRes55,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb034.xsd','./msxsdtest/Particles',invalid),
+ STResList56 = [STRes55|STResList55],
+
+
+ ?line {STRes56,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb035.xsd','./msxsdtest/Particles',invalid),
+ STResList57 = [STRes56|STResList56],
+
+
+ ?line {STRes57,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb036.xsd','./msxsdtest/Particles',invalid),
+ STResList58 = [STRes57|STResList57],
+
+
+ ?line {STRes58,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb037.xsd','./msxsdtest/Particles',invalid),
+ STResList59 = [STRes58|STResList58],
+
+
+ ?line {STRes59,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb038.xsd','./msxsdtest/Particles',invalid),
+ STResList60 = [STRes59|STResList59],
+
+
+ ?line {STRes60,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb039.xsd','./msxsdtest/Particles',invalid),
+ STResList61 = [STRes60|STResList60],
+
+
+ ?line {STRes61,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb040.xsd','./msxsdtest/Particles',invalid),
+ STResList62 = [STRes61|STResList61],
+
+
+ ?line {STRes62,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb041.xsd','./msxsdtest/Particles',invalid),
+ STResList63 = [STRes62|STResList62],
+
+
+ ?line {STRes63,S63} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb042.xsd','./msxsdtest/Particles',valid),
+ STResList64 = [STRes63|STResList63],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb042.xml','./msxsdtest/Particles',valid,S63),
+ ITResList28 = [ITRes27|ITResList27],
+
+
+ ?line {STRes64,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb043.xsd','./msxsdtest/Particles',invalid),
+ STResList65 = [STRes64|STResList64],
+
+
+ ?line {STRes65,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb044.xsd','./msxsdtest/Particles',invalid),
+ STResList66 = [STRes65|STResList65],
+
+
+ ?line {STRes66,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb045.xsd','./msxsdtest/Particles',invalid),
+ STResList67 = [STRes66|STResList66],
+
+
+ ?line {STRes67,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb046.xsd','./msxsdtest/Particles',invalid),
+ STResList68 = [STRes67|STResList67],
+
+
+ ?line {STRes68,S68} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb047.xsd','./msxsdtest/Particles',valid),
+ STResList69 = [STRes68|STResList68],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb047.xml','./msxsdtest/Particles',valid,S68),
+ ITResList29 = [ITRes28|ITResList28],
+
+
+ ?line {STRes69,S69} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb048.xsd','./msxsdtest/Particles',valid),
+ STResList70 = [STRes69|STResList69],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb048.xml','./msxsdtest/Particles',valid,S69),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes70,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb049.xsd','./msxsdtest/Particles',invalid),
+ STResList71 = [STRes70|STResList70],
+
+
+ ?line {STRes71,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb050.xsd','./msxsdtest/Particles',invalid),
+ STResList72 = [STRes71|STResList71],
+
+
+ ?line {STRes72,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb051.xsd','./msxsdtest/Particles',invalid),
+ STResList73 = [STRes72|STResList72],
+
+
+ ?line {STRes73,S73} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb052.xsd','./msxsdtest/Particles',valid),
+ STResList74 = [STRes73|STResList73],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb052.xml','./msxsdtest/Particles',valid,S73),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes74,S74} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb053.xsd','./msxsdtest/Particles',valid),
+ STResList75 = [STRes74|STResList74],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb053.xml','./msxsdtest/Particles',valid,S74),
+ ITResList32 = [ITRes31|ITResList31],
+
+
+ ?line {STRes75,S75} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb054.xsd','./msxsdtest/Particles',valid),
+ STResList76 = [STRes75|STResList75],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb054.xml','./msxsdtest/Particles',valid,S75),
+ ITResList33 = [ITRes32|ITResList32],
+
+
+ ?line {STRes76,S76} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb055.xsd','./msxsdtest/Particles',valid),
+ STResList77 = [STRes76|STResList76],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb055.xml','./msxsdtest/Particles',valid,S76),
+ ITResList34 = [ITRes33|ITResList33],
+
+
+ ?line {STRes77,S77} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb056.xsd','./msxsdtest/Particles',valid),
+ STResList78 = [STRes77|STResList77],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb056.xml','./msxsdtest/Particles',valid,S77),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes78,S78} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb057.xsd','./msxsdtest/Particles',valid),
+ STResList79 = [STRes78|STResList78],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb057.xml','./msxsdtest/Particles',valid,S78),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes79,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb058.xsd','./msxsdtest/Particles',invalid),
+ STResList80 = [STRes79|STResList79],
+
+
+ ?line {STRes80,S80} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb059.xsd','./msxsdtest/Particles',valid),
+ STResList81 = [STRes80|STResList80],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb059.xml','./msxsdtest/Particles',valid,S80),
+ ITResList37 = [ITRes36|ITResList36],
+
+
+ ?line {STRes81,S81} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesOb060.xsd','./msxsdtest/Particles',valid),
+ STResList82 = [STRes81|STResList81],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesOb060.xml','./msxsdtest/Particles',valid,S81),
+ ITResList38 = [ITRes37|ITResList37],
+
+
+ ?line {STRes82,S82} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesS001.xsd','./msxsdtest/Particles',valid),
+ STResList83 = [STRes82|STResList82],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesS001.xml','./msxsdtest/Particles',valid,S82),
+ ITResList39 = [ITRes38|ITResList38],
+
+
+ ?line {STRes83,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesS002.xsd','./msxsdtest/Particles',invalid),
+ STResList84 = [STRes83|STResList83],
+
+
+ ?line {STRes84,S84} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesS003.xsd','./msxsdtest/Particles',valid),
+ STResList85 = [STRes84|STResList84],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesS003.xml','./msxsdtest/Particles',valid,S84),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes85,S85} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesS004.xsd','./msxsdtest/Particles',valid),
+ STResList86 = [STRes85|STResList85],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesS004.xml','./msxsdtest/Particles',valid,S85),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes86,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesS005.xsd','./msxsdtest/Particles',invalid),
+ STResList87 = [STRes86|STResList86],
+
+
+ ?line {STRes87,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesS006.xsd','./msxsdtest/Particles',invalid),
+ STResList88 = [STRes87|STResList87],
+
+
+ ?line {STRes88,S88} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesS007.xsd','./msxsdtest/Particles',valid),
+ STResList89 = [STRes88|STResList88],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesS007.xml','./msxsdtest/Particles',valid,S88),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes89,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesS008.xsd','./msxsdtest/Particles',invalid),
+ STResList90 = [STRes89|STResList89],
+
+
+ ?line {STRes90,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesS009.xsd','./msxsdtest/Particles',invalid),
+ STResList91 = [STRes90|STResList90],
+
+
+ ?line {STRes91,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesS010.xsd','./msxsdtest/Particles',invalid),
+ STResList92 = [STRes91|STResList91],
+
+
+ ?line {STRes92,S92} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesS011.xsd','./msxsdtest/Particles',valid),
+ STResList93 = [STRes92|STResList92],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesS011.xml','./msxsdtest/Particles',valid,S92),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes93,S93} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR001.xsd','./msxsdtest/Particles',valid),
+ STResList94 = [STRes93|STResList93],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR001.xml','./msxsdtest/Particles',valid,S93),
+ ITResList44 = [ITRes43|ITResList43],
+
+
+ ?line {STRes94,S94} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR002.xsd','./msxsdtest/Particles',valid),
+ STResList95 = [STRes94|STResList94],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR002.xml','./msxsdtest/Particles',valid,S94),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes95,S95} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR003.xsd','./msxsdtest/Particles',valid),
+ STResList96 = [STRes95|STResList95],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR003.xml','./msxsdtest/Particles',valid,S95),
+ ITResList46 = [ITRes45|ITResList45],
+
+
+ ?line {STRes96,S96} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR004.xsd','./msxsdtest/Particles',valid),
+ STResList97 = [STRes96|STResList96],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR004.xml','./msxsdtest/Particles',valid,S96),
+ ITResList47 = [ITRes46|ITResList46],
+
+
+ ?line {STRes97,S97} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR005.xsd','./msxsdtest/Particles',valid),
+ STResList98 = [STRes97|STResList97],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR005.xml','./msxsdtest/Particles',valid,S97),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes98,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR006.xsd','./msxsdtest/Particles',invalid),
+ STResList99 = [STRes98|STResList98],
+
+
+ ?line {STRes99,S99} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR007.xsd','./msxsdtest/Particles',valid),
+ STResList100 = [STRes99|STResList99],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR007.xml','./msxsdtest/Particles',valid,S99),
+ ITResList49 = [ITRes48|ITResList48],
+
+
+ ?line {STRes100,S100} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR008.xsd','./msxsdtest/Particles',valid),
+ STResList101 = [STRes100|STResList100],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR008.xml','./msxsdtest/Particles',valid,S100),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes101,S101} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR009.xsd','./msxsdtest/Particles',valid),
+ STResList102 = [STRes101|STResList101],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR009.xml','./msxsdtest/Particles',valid,S101),
+ ITResList51 = [ITRes50|ITResList50],
+
+
+ ?line {STRes102,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR010.xsd','./msxsdtest/Particles',invalid),
+ STResList103 = [STRes102|STResList102],
+
+
+ ?line {STRes103,S103} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR011.xsd','./msxsdtest/Particles',valid),
+ STResList104 = [STRes103|STResList103],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR011.xml','./msxsdtest/Particles',valid,S103),
+ ITResList52 = [ITRes51|ITResList51],
+
+
+ ?line {STRes104,S104} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR012.xsd','./msxsdtest/Particles',valid),
+ STResList105 = [STRes104|STResList104],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR012.xml','./msxsdtest/Particles',valid,S104),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes105,S105} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR013.xsd','./msxsdtest/Particles',valid),
+ STResList106 = [STRes105|STResList105],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR013.xml','./msxsdtest/Particles',valid,S105),
+ ITResList54 = [ITRes53|ITResList53],
+
+
+ ?line {STRes106,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR014.xsd','./msxsdtest/Particles',invalid),
+ STResList107 = [STRes106|STResList106],
+
+
+ ?line {STRes107,S107} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR015.xsd','./msxsdtest/Particles',valid),
+ STResList108 = [STRes107|STResList107],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR015.xml','./msxsdtest/Particles',valid,S107),
+ ITResList55 = [ITRes54|ITResList54],
+
+
+ ?line {STRes108,S108} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR016.xsd','./msxsdtest/Particles',valid),
+ STResList109 = [STRes108|STResList108],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR016.xml','./msxsdtest/Particles',valid,S108),
+ ITResList56 = [ITRes55|ITResList55],
+
+
+ ?line {STRes109,S109} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR017.xsd','./msxsdtest/Particles',valid),
+ STResList110 = [STRes109|STResList109],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR017.xml','./msxsdtest/Particles',valid,S109),
+ ITResList57 = [ITRes56|ITResList56],
+
+
+ ?line {STRes110,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR018.xsd','./msxsdtest/Particles',invalid),
+ STResList111 = [STRes110|STResList110],
+
+
+ ?line {STRes111,S111} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR019.xsd','./msxsdtest/Particles',valid),
+ STResList112 = [STRes111|STResList111],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR019.xml','./msxsdtest/Particles',valid,S111),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes112,S112} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR020.xsd','./msxsdtest/Particles',valid),
+ STResList113 = [STRes112|STResList112],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR020.xml','./msxsdtest/Particles',valid,S112),
+ ITResList59 = [ITRes58|ITResList58],
+
+
+ ?line {STRes113,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR021.xsd','./msxsdtest/Particles',invalid),
+ STResList114 = [STRes113|STResList113],
+
+
+ ?line {STRes114,S114} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR022.xsd','./msxsdtest/Particles',valid),
+ STResList115 = [STRes114|STResList114],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR022.xml','./msxsdtest/Particles',valid,S114),
+ ITResList60 = [ITRes59|ITResList59],
+
+
+ ?line {STRes115,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR023.xsd','./msxsdtest/Particles',invalid),
+ STResList116 = [STRes115|STResList115],
+
+
+ ?line {STRes116,S116} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR024.xsd','./msxsdtest/Particles',valid),
+ STResList117 = [STRes116|STResList116],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR024.xml','./msxsdtest/Particles',valid,S116),
+ ITResList61 = [ITRes60|ITResList60],
+
+
+ ?line {STRes117,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR025.xsd','./msxsdtest/Particles',invalid),
+ STResList118 = [STRes117|STResList117],
+
+
+ ?line {STRes118,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR026.xsd','./msxsdtest/Particles',invalid),
+ STResList119 = [STRes118|STResList118],
+
+
+ ?line {STRes119,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR027.xsd','./msxsdtest/Particles',invalid),
+ STResList120 = [STRes119|STResList119],
+
+
+ ?line {STRes120,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR028.xsd','./msxsdtest/Particles',invalid),
+ STResList121 = [STRes120|STResList120],
+
+
+ ?line {STRes121,S121} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR029.xsd','./msxsdtest/Particles',valid),
+ STResList122 = [STRes121|STResList121],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR029.xml','./msxsdtest/Particles',valid,S121),
+ ITResList62 = [ITRes61|ITResList61],
+
+
+ ?line {STRes122,S122} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR030.xsd','./msxsdtest/Particles',valid),
+ STResList123 = [STRes122|STResList122],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesR030.xml','./msxsdtest/Particles',valid,S122),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes123,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesR031.xsd','./msxsdtest/Particles',invalid),
+ STResList124 = [STRes123|STResList123],
+
+
+ ?line {STRes124,S124} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesT001.xsd','./msxsdtest/Particles',valid),
+ STResList125 = [STRes124|STResList124],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesT001.xml','./msxsdtest/Particles',valid,S124),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes125,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesT002.xsd','./msxsdtest/Particles',invalid),
+ STResList126 = [STRes125|STResList125],
+
+
+ ?line {STRes126,S126} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesT003.xsd','./msxsdtest/Particles',valid),
+ STResList127 = [STRes126|STResList126],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesT003.xml','./msxsdtest/Particles',valid,S126),
+ ITResList65 = [ITRes64|ITResList64],
+
+
+ ?line {STRes127,S127} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesT004.xsd','./msxsdtest/Particles',valid),
+ STResList128 = [STRes127|STResList127],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesT004.xml','./msxsdtest/Particles',valid,S127),
+ ITResList66 = [ITRes65|ITResList65],
+
+
+ ?line {STRes128,S128} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesT005.xsd','./msxsdtest/Particles',valid),
+ STResList129 = [STRes128|STResList128],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesT005.xml','./msxsdtest/Particles',valid,S128),
+ ITResList67 = [ITRes66|ITResList66],
+
+
+ ?line {STRes129,S129} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesT006.xsd','./msxsdtest/Particles',valid),
+ STResList130 = [STRes129|STResList129],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesT006.xml','./msxsdtest/Particles',valid,S129),
+ ITResList68 = [ITRes67|ITResList67],
+
+
+ ?line {STRes130,S130} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesT007.xsd','./msxsdtest/Particles',valid),
+ STResList131 = [STRes130|STResList130],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesT007.xml','./msxsdtest/Particles',valid,S130),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes131,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesT008.xsd','./msxsdtest/Particles',invalid),
+ STResList132 = [STRes131|STResList131],
+
+
+ ?line {STRes132,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesT009.xsd','./msxsdtest/Particles',invalid),
+ STResList133 = [STRes132|STResList132],
+
+
+ ?line {STRes133,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesT010.xsd','./msxsdtest/Particles',invalid),
+ STResList134 = [STRes133|STResList133],
+
+
+ ?line {STRes134,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesT011.xsd','./msxsdtest/Particles',invalid),
+ STResList135 = [STRes134|STResList134],
+
+
+ ?line {STRes135,S135} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesT012.xsd','./msxsdtest/Particles',valid),
+ STResList136 = [STRes135|STResList135],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesT012.xml','./msxsdtest/Particles',valid,S135),
+ ITResList70 = [ITRes69|ITResList69],
+
+
+ ?line {STRes136,S136} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesT013.xsd','./msxsdtest/Particles',valid),
+ STResList137 = [STRes136|STResList136],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesT013.xml','./msxsdtest/Particles',valid,S136),
+ ITResList71 = [ITRes70|ITResList70],
+
+
+ ?line {STRes137,S137} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesT014.xsd','./msxsdtest/Particles',valid),
+ STResList138 = [STRes137|STResList137],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesT014.xml','./msxsdtest/Particles',valid,S137),
+ ITResList72 = [ITRes71|ITResList71],
+
+
+ ?line {STRes138,S138} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ001.xsd','./msxsdtest/Particles',valid),
+ STResList139 = [STRes138|STResList138],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesQ001.xml','./msxsdtest/Particles',valid,S138),
+ ITResList73 = [ITRes72|ITResList72],
+
+
+ ?line {STRes139,S139} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ002.xsd','./msxsdtest/Particles',valid),
+ STResList140 = [STRes139|STResList139],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesQ002.xml','./msxsdtest/Particles',valid,S139),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes140,S140} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ003.xsd','./msxsdtest/Particles',valid),
+ STResList141 = [STRes140|STResList140],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesQ003.xml','./msxsdtest/Particles',valid,S140),
+ ITResList75 = [ITRes74|ITResList74],
+
+
+ ?line {STRes141,S141} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ004.xsd','./msxsdtest/Particles',valid),
+ STResList142 = [STRes141|STResList141],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesQ004.xml','./msxsdtest/Particles',valid,S141),
+ ITResList76 = [ITRes75|ITResList75],
+
+
+ ?line {STRes142,S142} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ005.xsd','./msxsdtest/Particles',valid),
+ STResList143 = [STRes142|STResList142],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesQ005.xml','./msxsdtest/Particles',valid,S142),
+ ITResList77 = [ITRes76|ITResList76],
+
+
+ ?line {STRes143,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ006.xsd','./msxsdtest/Particles',invalid),
+ STResList144 = [STRes143|STResList143],
+
+
+ ?line {STRes144,S144} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ007.xsd','./msxsdtest/Particles',valid),
+ STResList145 = [STRes144|STResList144],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesQ007.xml','./msxsdtest/Particles',valid,S144),
+ ITResList78 = [ITRes77|ITResList77],
+
+
+ ?line {STRes145,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ008.xsd','./msxsdtest/Particles',invalid),
+ STResList146 = [STRes145|STResList145],
+
+
+ ?line {STRes146,S146} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ011.xsd','./msxsdtest/Particles',valid),
+ STResList147 = [STRes146|STResList146],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesQ011.xml','./msxsdtest/Particles',valid,S146),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes147,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ012.xsd','./msxsdtest/Particles',invalid),
+ STResList148 = [STRes147|STResList147],
+
+
+ ?line {STRes148,S148} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ013.xsd','./msxsdtest/Particles',valid),
+ STResList149 = [STRes148|STResList148],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesQ013.xml','./msxsdtest/Particles',valid,S148),
+ ITResList80 = [ITRes79|ITResList79],
+
+
+ ?line {STRes149,S149} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ016.xsd','./msxsdtest/Particles',valid),
+ STResList150 = [STRes149|STResList149],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesQ016.xml','./msxsdtest/Particles',valid,S149),
+ ITResList81 = [ITRes80|ITResList80],
+
+
+ ?line {STRes150,S150} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ017.xsd','./msxsdtest/Particles',valid),
+ STResList151 = [STRes150|STResList150],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesQ017.xml','./msxsdtest/Particles',valid,S150),
+ ITResList82 = [ITRes81|ITResList81],
+
+
+ ?line {STRes151,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ018.xsd','./msxsdtest/Particles',invalid),
+ STResList152 = [STRes151|STResList151],
+
+
+ ?line {STRes152,S152} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ019.xsd','./msxsdtest/Particles',valid),
+ STResList153 = [STRes152|STResList152],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesQ019.xml','./msxsdtest/Particles',valid,S152),
+ ITResList83 = [ITRes82|ITResList82],
+
+
+ ?line {STRes153,S153} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ020.xsd','./msxsdtest/Particles',valid),
+ STResList154 = [STRes153|STResList153],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesQ020.xml','./msxsdtest/Particles',valid,S153),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes154,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ021.xsd','./msxsdtest/Particles',invalid),
+ STResList155 = [STRes154|STResList154],
+
+
+ ?line {STRes155,S155} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ022.xsd','./msxsdtest/Particles',valid),
+ STResList156 = [STRes155|STResList155],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesQ022.xml','./msxsdtest/Particles',valid,S155),
+ ITResList85 = [ITRes84|ITResList84],
+
+
+ ?line {STRes156,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ023.xsd','./msxsdtest/Particles',invalid),
+ STResList157 = [STRes156|STResList156],
+
+
+ ?line {STRes157,S157} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ024.xsd','./msxsdtest/Particles',valid),
+ STResList158 = [STRes157|STResList157],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesQ024.xml','./msxsdtest/Particles',valid,S157),
+ ITResList86 = [ITRes85|ITResList85],
+
+
+ ?line {STRes158,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ025.xsd','./msxsdtest/Particles',invalid),
+ STResList159 = [STRes158|STResList158],
+
+
+ ?line {STRes159,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ026.xsd','./msxsdtest/Particles',invalid),
+ STResList160 = [STRes159|STResList159],
+
+
+ ?line {STRes160,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ027.xsd','./msxsdtest/Particles',invalid),
+ STResList161 = [STRes160|STResList160],
+
+
+ ?line {STRes161,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ028.xsd','./msxsdtest/Particles',invalid),
+ STResList162 = [STRes161|STResList161],
+
+
+ ?line {STRes162,S162} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ029.xsd','./msxsdtest/Particles',valid),
+ STResList163 = [STRes162|STResList162],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesQ029.xml','./msxsdtest/Particles',valid,S162),
+ ITResList87 = [ITRes86|ITResList86],
+
+
+ ?line {STRes163,S163} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ030.xsd','./msxsdtest/Particles',valid),
+ STResList164 = [STRes163|STResList163],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesQ030.xml','./msxsdtest/Particles',valid,S163),
+ ITResList88 = [ITRes87|ITResList87],
+
+
+ ?line {STRes164,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesQ031.xsd','./msxsdtest/Particles',invalid),
+ STResList165 = [STRes164|STResList164],
+
+
+ ?line {STRes165,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesU001.xsd','./msxsdtest/Particles',invalid),
+ STResList166 = [STRes165|STResList165],
+
+
+ ?line {STRes166,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesU002.xsd','./msxsdtest/Particles',invalid),
+ STResList167 = [STRes166|STResList166],
+
+
+ ?line {STRes167,S167} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesU003.xsd','./msxsdtest/Particles',valid),
+ STResList168 = [STRes167|STResList167],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesU003.xml','./msxsdtest/Particles',valid,S167),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes168,S168} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesU004.xsd','./msxsdtest/Particles',valid),
+ STResList169 = [STRes168|STResList168],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesU004.xml','./msxsdtest/Particles',valid,S168),
+ ITResList90 = [ITRes89|ITResList89],
+
+
+ ?line {STRes169,S169} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesU005.xsd','./msxsdtest/Particles',valid),
+ STResList170 = [STRes169|STResList169],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesU005.xml','./msxsdtest/Particles',valid,S169),
+ ITResList91 = [ITRes90|ITResList90],
+
+
+ ?line {STRes170,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesU006.xsd','./msxsdtest/Particles',invalid),
+ STResList171 = [STRes170|STResList170],
+
+
+ ?line {STRes171,S171} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesU007.xsd','./msxsdtest/Particles',valid),
+ STResList172 = [STRes171|STResList171],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesU007.xml','./msxsdtest/Particles',valid,S171),
+ ITResList92 = [ITRes91|ITResList91],
+
+
+ ?line {STRes172,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesU008.xsd','./msxsdtest/Particles',invalid),
+ STResList173 = [STRes172|STResList172],
+
+
+ ?line {STRes173,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesU009.xsd','./msxsdtest/Particles',invalid),
+ STResList174 = [STRes173|STResList173],
+
+
+ ?line {STRes174,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesV002.xsd','./msxsdtest/Particles',invalid),
+ STResList175 = [STRes174|STResList174],
+
+
+ ?line {STRes175,S175} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesV003.xsd','./msxsdtest/Particles',valid),
+ STResList176 = [STRes175|STResList175],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesV003.xml','./msxsdtest/Particles',valid,S175),
+ ITResList93 = [ITRes92|ITResList92],
+
+
+ ?line {STRes176,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesV005.xsd','./msxsdtest/Particles',invalid),
+ STResList177 = [STRes176|STResList176],
+
+
+ ?line {STRes177,S177} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesV006.xsd','./msxsdtest/Particles',valid),
+ STResList178 = [STRes177|STResList177],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesV006.xml','./msxsdtest/Particles',valid,S177),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes178,S178} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesV007.xsd','./msxsdtest/Particles',valid),
+ STResList179 = [STRes178|STResList178],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesV007.xml','./msxsdtest/Particles',valid,S178),
+ ITResList95 = [ITRes94|ITResList94],
+
+
+ ?line {STRes179,S179} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesV008.xsd','./msxsdtest/Particles',valid),
+ STResList180 = [STRes179|STResList179],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesV008.xml','./msxsdtest/Particles',valid,S179),
+ ITResList96 = [ITRes95|ITResList95],
+
+
+ ?line {STRes180,S180} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesV009.xsd','./msxsdtest/Particles',valid),
+ STResList181 = [STRes180|STResList180],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesV009.xml','./msxsdtest/Particles',valid,S180),
+ ITResList97 = [ITRes96|ITResList96],
+
+
+ ?line {STRes181,S181} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesV010.xsd','./msxsdtest/Particles',valid),
+ STResList182 = [STRes181|STResList181],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesV010.xml','./msxsdtest/Particles',valid,S181),
+ ITResList98 = [ITRes97|ITResList97],
+
+
+ ?line {STRes182,S182} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesV011.xsd','./msxsdtest/Particles',valid),
+ STResList183 = [STRes182|STResList182],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesV011.xml','./msxsdtest/Particles',valid,S182),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes183,S183} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesV012.xsd','./msxsdtest/Particles',valid),
+ STResList184 = [STRes183|STResList183],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesV012.xml','./msxsdtest/Particles',valid,S183),
+ ITResList100 = [ITRes99|ITResList99],
+
+
+ ?line {STRes184,S184} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesV013.xsd','./msxsdtest/Particles',valid),
+ STResList185 = [STRes184|STResList184],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesV013.xml','./msxsdtest/Particles',valid,S184),
+ ITResList101 = [ITRes100|ITResList100],
+
+
+ ?line {STRes185,S185} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesV014.xsd','./msxsdtest/Particles',valid),
+ STResList186 = [STRes185|STResList185],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesV014.xml','./msxsdtest/Particles',valid,S185),
+ ITResList102 = [ITRes101|ITResList101],
+
+
+ ?line {STRes186,S186} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesV015.xsd','./msxsdtest/Particles',valid),
+ STResList187 = [STRes186|STResList186],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesV015.xml','./msxsdtest/Particles',valid,S186),
+ ITResList103 = [ITRes102|ITResList102],
+
+
+ ?line {STRes187,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesV016.xsd','./msxsdtest/Particles',invalid),
+ STResList188 = [STRes187|STResList187],
+
+
+ ?line {STRes188,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesV017.xsd','./msxsdtest/Particles',invalid),
+ STResList189 = [STRes188|STResList188],
+
+
+ ?line {STRes189,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesV018.xsd','./msxsdtest/Particles',invalid),
+ STResList190 = [STRes189|STResList189],
+
+
+ ?line {STRes190,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesV020.xsd','./msxsdtest/Particles',invalid),
+ STResList191 = [STRes190|STResList190],
+
+
+ ?line {STRes191,S191} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesW001.xsd','./msxsdtest/Particles',valid),
+ STResList192 = [STRes191|STResList191],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesW001.xml','./msxsdtest/Particles',valid,S191),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes192,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesW002.xsd','./msxsdtest/Particles',invalid),
+ STResList193 = [STRes192|STResList192],
+
+
+ ?line {STRes193,S193} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesW003.xsd','./msxsdtest/Particles',valid),
+ STResList194 = [STRes193|STResList193],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesW003.xml','./msxsdtest/Particles',valid,S193),
+ ITResList105 = [ITRes104|ITResList104],
+
+
+ ?line {STRes194,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesW005.xsd','./msxsdtest/Particles',invalid),
+ STResList195 = [STRes194|STResList194],
+
+
+ ?line {STRes195,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesW006.xsd','./msxsdtest/Particles',valid),
+ STResList196 = [STRes195|STResList195],
+
+
+ ?line {STRes196,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesW007.xsd','./msxsdtest/Particles',invalid),
+ STResList197 = [STRes196|STResList196],
+
+
+ ?line {STRes197,S197} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesW008.xsd','./msxsdtest/Particles',valid),
+ STResList198 = [STRes197|STResList197],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesW008.xml','./msxsdtest/Particles',valid,S197),
+ ITResList106 = [ITRes105|ITResList105],
+
+
+ ?line {STRes198,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesW010.xsd','./msxsdtest/Particles',invalid),
+ STResList199 = [STRes198|STResList198],
+
+
+ ?line {STRes199,S199} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesW011.xsd','./msxsdtest/Particles',valid),
+ STResList200 = [STRes199|STResList199],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesW011.xml','./msxsdtest/Particles',valid,S199),
+ ITResList107 = [ITRes106|ITResList106],
+
+
+ ?line {STRes200,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesW012.xsd','./msxsdtest/Particles',invalid),
+ STResList201 = [STRes200|STResList200],
+
+
+ ?line {STRes201,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesW013.xsd','./msxsdtest/Particles',invalid),
+ STResList202 = [STRes201|STResList201],
+
+
+ ?line {STRes202,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesW014.xsd','./msxsdtest/Particles',invalid),
+ STResList203 = [STRes202|STResList202],
+
+
+ ?line {STRes203,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesW015.xsd','./msxsdtest/Particles',invalid),
+ STResList204 = [STRes203|STResList203],
+
+
+ ?line {STRes204,S204} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/Particles/particlesW016.xsd','./msxsdtest/Particles',valid),
+ STResList205 = [STRes204|STResList204],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/Particles/particlesW016.xml','./msxsdtest/Particles',valid,S204),
+ ITResList108 = [ITRes107|ITResList107],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList205,ITResList108).
+
+%% Syntax Checking for simpleType Declaration.
+
+stABCDE(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA001.xsd','./msxsdtest/simpleType',valid),
+ STResList1 = [STRes0|STResList0],
+
+
+ ?line {STRes1,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA002.xsd','./msxsdtest/simpleType',invalid),
+ STResList2 = [STRes1|STResList1],
+
+
+ ?line {STRes2,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA003.xsd','./msxsdtest/simpleType',invalid),
+ STResList3 = [STRes2|STResList2],
+
+
+ ?line {STRes3,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA004.xsd','./msxsdtest/simpleType',invalid),
+ STResList4 = [STRes3|STResList3],
+
+
+ ?line {STRes4,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA005.xsd','./msxsdtest/simpleType',invalid),
+ STResList5 = [STRes4|STResList4],
+
+
+ ?line {STRes5,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA006.xsd','./msxsdtest/simpleType',valid),
+ STResList6 = [STRes5|STResList5],
+
+
+ ?line {STRes6,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA007.xsd','./msxsdtest/simpleType',valid),
+ STResList7 = [STRes6|STResList6],
+
+
+ ?line {STRes7,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA008.xsd','./msxsdtest/simpleType',invalid),
+ STResList8 = [STRes7|STResList7],
+
+
+ ?line {STRes8,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA009.xsd','./msxsdtest/simpleType',invalid),
+ STResList9 = [STRes8|STResList8],
+
+
+ ?line {STRes9,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA010.xsd','./msxsdtest/simpleType',invalid),
+ STResList10 = [STRes9|STResList9],
+
+
+ ?line {STRes10,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA011.xsd','./msxsdtest/simpleType',invalid),
+ STResList11 = [STRes10|STResList10],
+
+
+ ?line {STRes11,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA012.xsd','./msxsdtest/simpleType',invalid),
+ STResList12 = [STRes11|STResList11],
+
+
+ ?line {STRes12,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA013.xsd','./msxsdtest/simpleType',invalid),
+ STResList13 = [STRes12|STResList12],
+
+
+ ?line {STRes13,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA014.xsd','./msxsdtest/simpleType',invalid),
+ STResList14 = [STRes13|STResList13],
+
+
+ ?line {STRes14,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA015.xsd','./msxsdtest/simpleType',invalid),
+ STResList15 = [STRes14|STResList14],
+
+
+ ?line {STRes15,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA016.xsd','./msxsdtest/simpleType',valid),
+ STResList16 = [STRes15|STResList15],
+
+
+ ?line {STRes16,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA017.xsd','./msxsdtest/simpleType',invalid),
+ STResList17 = [STRes16|STResList16],
+
+
+ ?line {STRes17,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA018.xsd','./msxsdtest/simpleType',valid),
+ STResList18 = [STRes17|STResList17],
+
+
+ ?line {STRes18,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA019.xsd','./msxsdtest/simpleType',valid),
+ STResList19 = [STRes18|STResList18],
+
+
+ ?line {STRes19,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stA020.xsd','./msxsdtest/simpleType',valid),
+ STResList20 = [STRes19|STResList19],
+
+
+ ?line {STRes20,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB001.xsd','./msxsdtest/simpleType',invalid),
+ STResList21 = [STRes20|STResList20],
+
+
+ ?line {STRes21,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB002.xsd','./msxsdtest/simpleType',invalid),
+ STResList22 = [STRes21|STResList21],
+
+
+ ?line {STRes22,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB003.xsd','./msxsdtest/simpleType',valid),
+ STResList23 = [STRes22|STResList22],
+
+
+ ?line {STRes23,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB004.xsd','./msxsdtest/simpleType',invalid),
+ STResList24 = [STRes23|STResList23],
+
+
+ ?line {STRes24,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB005.xsd','./msxsdtest/simpleType',invalid),
+ STResList25 = [STRes24|STResList24],
+
+
+ ?line {STRes25,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB006.xsd','./msxsdtest/simpleType',valid),
+ STResList26 = [STRes25|STResList25],
+
+
+ ?line {STRes26,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB007.xsd','./msxsdtest/simpleType',invalid),
+ STResList27 = [STRes26|STResList26],
+
+
+ ?line {STRes27,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB008.xsd','./msxsdtest/simpleType',valid),
+ STResList28 = [STRes27|STResList27],
+
+
+ ?line {STRes28,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB009.xsd','./msxsdtest/simpleType',invalid),
+ STResList29 = [STRes28|STResList28],
+
+
+ ?line {STRes29,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB010.xsd','./msxsdtest/simpleType',invalid),
+ STResList30 = [STRes29|STResList29],
+
+
+ ?line {STRes30,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB011.xsd','./msxsdtest/simpleType',valid),
+ STResList31 = [STRes30|STResList30],
+
+
+ ?line {STRes31,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB012.xsd','./msxsdtest/simpleType',valid),
+ STResList32 = [STRes31|STResList31],
+
+
+ ?line {STRes32,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB013.xsd','./msxsdtest/simpleType',invalid),
+ STResList33 = [STRes32|STResList32],
+
+
+ ?line {STRes33,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB014.xsd','./msxsdtest/simpleType',invalid),
+ STResList34 = [STRes33|STResList33],
+
+
+ ?line {STRes34,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB015.xsd','./msxsdtest/simpleType',valid),
+ STResList35 = [STRes34|STResList34],
+
+
+ ?line {STRes35,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB016.xsd','./msxsdtest/simpleType',invalid),
+ STResList36 = [STRes35|STResList35],
+
+
+ ?line {STRes36,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB017.xsd','./msxsdtest/simpleType',invalid),
+ STResList37 = [STRes36|STResList36],
+
+
+ ?line {STRes37,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB018.xsd','./msxsdtest/simpleType',invalid),
+ STResList38 = [STRes37|STResList37],
+
+
+ ?line {STRes38,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB019.xsd','./msxsdtest/simpleType',invalid),
+ STResList39 = [STRes38|STResList38],
+
+
+ ?line {STRes39,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB020.xsd','./msxsdtest/simpleType',invalid),
+ STResList40 = [STRes39|STResList39],
+
+
+ ?line {STRes40,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB021.xsd','./msxsdtest/simpleType',invalid),
+ STResList41 = [STRes40|STResList40],
+
+
+ ?line {STRes41,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB022.xsd','./msxsdtest/simpleType',invalid),
+ STResList42 = [STRes41|STResList41],
+
+
+ ?line {STRes42,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB023.xsd','./msxsdtest/simpleType',invalid),
+ STResList43 = [STRes42|STResList42],
+
+
+ ?line {STRes43,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stB024.xsd','./msxsdtest/simpleType',invalid),
+ STResList44 = [STRes43|STResList43],
+
+
+ ?line {STRes44,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC001.xsd','./msxsdtest/simpleType',valid),
+ STResList45 = [STRes44|STResList44],
+
+
+ ?line {STRes45,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC002.xsd','./msxsdtest/simpleType',invalid),
+ STResList46 = [STRes45|STResList45],
+
+
+ ?line {STRes46,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC003.xsd','./msxsdtest/simpleType',valid),
+ STResList47 = [STRes46|STResList46],
+
+
+ ?line {STRes47,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC004.xsd','./msxsdtest/simpleType',invalid),
+ STResList48 = [STRes47|STResList47],
+
+
+ ?line {STRes48,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC005.xsd','./msxsdtest/simpleType',valid),
+ STResList49 = [STRes48|STResList48],
+
+
+ ?line {STRes49,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC006.xsd','./msxsdtest/simpleType',invalid),
+ STResList50 = [STRes49|STResList49],
+
+
+ ?line {STRes50,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC007.xsd','./msxsdtest/simpleType',invalid),
+ STResList51 = [STRes50|STResList50],
+
+
+ ?line {STRes51,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC008.xsd','./msxsdtest/simpleType',invalid),
+ STResList52 = [STRes51|STResList51],
+
+
+ ?line {STRes52,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC009.xsd','./msxsdtest/simpleType',invalid),
+ STResList53 = [STRes52|STResList52],
+
+
+ ?line {STRes53,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC010.xsd','./msxsdtest/simpleType',valid),
+ STResList54 = [STRes53|STResList53],
+
+
+ ?line {STRes54,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC011.xsd','./msxsdtest/simpleType',invalid),
+ STResList55 = [STRes54|STResList54],
+
+
+ ?line {STRes55,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC012.xsd','./msxsdtest/simpleType',invalid),
+ STResList56 = [STRes55|STResList55],
+
+
+ ?line {STRes56,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC013.xsd','./msxsdtest/simpleType',invalid),
+ STResList57 = [STRes56|STResList56],
+
+
+ ?line {STRes57,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC014.xsd','./msxsdtest/simpleType',valid),
+ STResList58 = [STRes57|STResList57],
+
+
+ ?line {STRes58,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC015.xsd','./msxsdtest/simpleType',valid),
+ STResList59 = [STRes58|STResList58],
+
+
+ ?line {STRes59,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC016.xsd','./msxsdtest/simpleType',valid),
+ STResList60 = [STRes59|STResList59],
+
+
+ ?line {STRes60,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC017.xsd','./msxsdtest/simpleType',valid),
+ STResList61 = [STRes60|STResList60],
+
+
+ ?line {STRes61,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC018.xsd','./msxsdtest/simpleType',valid),
+ STResList62 = [STRes61|STResList61],
+
+
+ ?line {STRes62,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC019.xsd','./msxsdtest/simpleType',valid),
+ STResList63 = [STRes62|STResList62],
+
+
+ ?line {STRes63,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC020.xsd','./msxsdtest/simpleType',valid),
+ STResList64 = [STRes63|STResList63],
+
+
+ ?line {STRes64,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC021.xsd','./msxsdtest/simpleType',valid),
+ STResList65 = [STRes64|STResList64],
+
+
+ ?line {STRes65,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC022.xsd','./msxsdtest/simpleType',valid),
+ STResList66 = [STRes65|STResList65],
+
+
+ ?line {STRes66,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC023.xsd','./msxsdtest/simpleType',invalid),
+ STResList67 = [STRes66|STResList66],
+
+
+ ?line {STRes67,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC024.xsd','./msxsdtest/simpleType',valid),
+ STResList68 = [STRes67|STResList67],
+
+
+ ?line {STRes68,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC025.xsd','./msxsdtest/simpleType',valid),
+ STResList69 = [STRes68|STResList68],
+
+
+ ?line {STRes69,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC026.xsd','./msxsdtest/simpleType',valid),
+ STResList70 = [STRes69|STResList69],
+
+
+ ?line {STRes70,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC027.xsd','./msxsdtest/simpleType',invalid),
+ STResList71 = [STRes70|STResList70],
+
+
+ ?line {STRes71,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC028.xsd','./msxsdtest/simpleType',invalid),
+ STResList72 = [STRes71|STResList71],
+
+
+ ?line {STRes72,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC029.xsd','./msxsdtest/simpleType',invalid),
+ STResList73 = [STRes72|STResList72],
+
+
+ ?line {STRes73,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC030.xsd','./msxsdtest/simpleType',valid),
+ STResList74 = [STRes73|STResList73],
+
+
+ ?line {STRes74,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC031.xsd','./msxsdtest/simpleType',invalid),
+ STResList75 = [STRes74|STResList74],
+
+
+ ?line {STRes75,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC032.xsd','./msxsdtest/simpleType',invalid),
+ STResList76 = [STRes75|STResList75],
+
+
+ ?line {STRes76,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stC033.xsd','./msxsdtest/simpleType',valid),
+ STResList77 = [STRes76|STResList76],
+
+
+ ?line {STRes77,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD001.xsd','./msxsdtest/simpleType',valid),
+ STResList78 = [STRes77|STResList77],
+
+
+ ?line {STRes78,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD002.xsd','./msxsdtest/simpleType',invalid),
+ STResList79 = [STRes78|STResList78],
+
+
+ ?line {STRes79,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD003.xsd','./msxsdtest/simpleType',invalid),
+ STResList80 = [STRes79|STResList79],
+
+
+ ?line {STRes80,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD004.xsd','./msxsdtest/simpleType',invalid),
+ STResList81 = [STRes80|STResList80],
+
+
+ ?line {STRes81,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD005.xsd','./msxsdtest/simpleType',invalid),
+ STResList82 = [STRes81|STResList81],
+
+
+ ?line {STRes82,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD006.xsd','./msxsdtest/simpleType',valid),
+ STResList83 = [STRes82|STResList82],
+
+
+ ?line {STRes83,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD007.xsd','./msxsdtest/simpleType',valid),
+ STResList84 = [STRes83|STResList83],
+
+
+ ?line {STRes84,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD008.xsd','./msxsdtest/simpleType',valid),
+ STResList85 = [STRes84|STResList84],
+
+
+ ?line {STRes85,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD009.xsd','./msxsdtest/simpleType',invalid),
+ STResList86 = [STRes85|STResList85],
+
+
+ ?line {STRes86,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD010.xsd','./msxsdtest/simpleType',invalid),
+ STResList87 = [STRes86|STResList86],
+
+
+ ?line {STRes87,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD011.xsd','./msxsdtest/simpleType',valid),
+ STResList88 = [STRes87|STResList87],
+
+
+ ?line {STRes88,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD012.xsd','./msxsdtest/simpleType',valid),
+ STResList89 = [STRes88|STResList88],
+
+
+ ?line {STRes89,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD013.xsd','./msxsdtest/simpleType',valid),
+ STResList90 = [STRes89|STResList89],
+
+
+ ?line {STRes90,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD014.xsd','./msxsdtest/simpleType',valid),
+ STResList91 = [STRes90|STResList90],
+
+
+ ?line {STRes91,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD015.xsd','./msxsdtest/simpleType',invalid),
+ STResList92 = [STRes91|STResList91],
+
+
+ ?line {STRes92,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD016.xsd','./msxsdtest/simpleType',invalid),
+ STResList93 = [STRes92|STResList92],
+
+
+ ?line {STRes93,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD017.xsd','./msxsdtest/simpleType',invalid),
+ STResList94 = [STRes93|STResList93],
+
+
+ ?line {STRes94,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD018.xsd','./msxsdtest/simpleType',invalid),
+ STResList95 = [STRes94|STResList94],
+
+
+ ?line {STRes95,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD019.xsd','./msxsdtest/simpleType',invalid),
+ STResList96 = [STRes95|STResList95],
+
+
+ ?line {STRes96,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD020.xsd','./msxsdtest/simpleType',valid),
+ STResList97 = [STRes96|STResList96],
+
+
+ ?line {STRes97,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stD021.xsd','./msxsdtest/simpleType',valid),
+ STResList98 = [STRes97|STResList97],
+
+
+ ?line {STRes98,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stE001.xsd','./msxsdtest/simpleType',valid),
+ STResList99 = [STRes98|STResList98],
+
+
+ ?line {STRes99,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stE002.xsd','./msxsdtest/simpleType',invalid),
+ STResList100 = [STRes99|STResList99],
+
+
+ ?line {STRes100,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stE003.xsd','./msxsdtest/simpleType',invalid),
+ STResList101 = [STRes100|STResList100],
+
+
+ ?line {STRes101,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stE004.xsd','./msxsdtest/simpleType',invalid),
+ STResList102 = [STRes101|STResList101],
+
+
+ ?line {STRes102,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stE005.xsd','./msxsdtest/simpleType',invalid),
+ STResList103 = [STRes102|STResList102],
+
+
+ ?line {STRes103,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stE006.xsd','./msxsdtest/simpleType',valid),
+ STResList104 = [STRes103|STResList103],
+
+
+ ?line {STRes104,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stE007.xsd','./msxsdtest/simpleType',valid),
+ STResList105 = [STRes104|STResList104],
+
+
+ ?line {STRes105,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stE008.xsd','./msxsdtest/simpleType',invalid),
+ STResList106 = [STRes105|STResList105],
+
+
+ ?line {STRes106,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stE009.xsd','./msxsdtest/simpleType',valid),
+ STResList107 = [STRes106|STResList106],
+
+
+ ?line {STRes107,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stE010.xsd','./msxsdtest/simpleType',valid),
+ STResList108 = [STRes107|STResList107],
+
+
+ ?line {STRes108,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stE011.xsd','./msxsdtest/simpleType',valid),
+ STResList109 = [STRes108|STResList108],
+
+
+ ?line {STRes109,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stE012.xsd','./msxsdtest/simpleType',invalid),
+ STResList110 = [STRes109|STResList109],
+
+
+ ?line {STRes110,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stE013.xsd','./msxsdtest/simpleType',valid),
+ STResList111 = [STRes110|STResList110],
+
+
+ ?line {STRes111,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stE014.xsd','./msxsdtest/simpleType',valid),
+ STResList112 = [STRes111|STResList111],
+
+
+ ?line {STRes112,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stE015.xsd','./msxsdtest/simpleType',invalid),
+ STResList113 = [STRes112|STResList112],
+
+
+ ?line {STRes113,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stE016.xsd','./msxsdtest/simpleType',invalid),
+ STResList114 = [STRes113|STResList113],
+
+
+ ?line {STRes114,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stE017.xsd','./msxsdtest/simpleType',valid),
+ STResList115 = [STRes114|STResList114],
+
+
+ ?line {STRes115,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stE018.xsd','./msxsdtest/simpleType',invalid),
+ STResList116 = [STRes115|STResList115],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList116,[]).
+
+%% simpleType Validation checking.
+
+stFGH(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF001.xsd','./msxsdtest/simpleType',valid),
+ STResList1 = [STRes0|STResList0],
+
+
+ ?line {STRes1,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF002.xsd','./msxsdtest/simpleType',valid),
+ STResList2 = [STRes1|STResList1],
+
+
+ ?line {STRes2,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF003.xsd','./msxsdtest/simpleType',valid),
+ STResList3 = [STRes2|STResList2],
+
+
+ ?line {STRes3,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF004.xsd','./msxsdtest/simpleType',valid),
+ STResList4 = [STRes3|STResList3],
+
+
+ ?line {STRes4,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF005.xsd','./msxsdtest/simpleType',invalid),
+ STResList5 = [STRes4|STResList4],
+
+
+ ?line {STRes5,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF006.xsd','./msxsdtest/simpleType',valid),
+ STResList6 = [STRes5|STResList5],
+
+
+ ?line {STRes6,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF007.xsd','./msxsdtest/simpleType',invalid),
+ STResList7 = [STRes6|STResList6],
+
+
+ ?line {STRes7,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF008.xsd','./msxsdtest/simpleType',invalid),
+ STResList8 = [STRes7|STResList7],
+
+
+ ?line {STRes8,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF009.xsd','./msxsdtest/simpleType',invalid),
+ STResList9 = [STRes8|STResList8],
+
+
+ ?line {STRes9,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF010.xsd','./msxsdtest/simpleType',invalid),
+ STResList10 = [STRes9|STResList9],
+
+
+ ?line {STRes10,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF011.xsd','./msxsdtest/simpleType',invalid),
+ STResList11 = [STRes10|STResList10],
+
+
+ ?line {STRes11,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF012.xsd','./msxsdtest/simpleType',invalid),
+ STResList12 = [STRes11|STResList11],
+
+
+ ?line {STRes12,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF013.xsd','./msxsdtest/simpleType',invalid),
+ STResList13 = [STRes12|STResList12],
+
+
+ ?line {STRes13,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF014.xsd','./msxsdtest/simpleType',invalid),
+ STResList14 = [STRes13|STResList13],
+
+
+ ?line {STRes14,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF015.xsd','./msxsdtest/simpleType',invalid),
+ STResList15 = [STRes14|STResList14],
+
+
+ ?line {STRes15,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF016.xsd','./msxsdtest/simpleType',valid),
+ STResList16 = [STRes15|STResList15],
+
+
+ ?line {STRes16,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF017.xsd','./msxsdtest/simpleType',valid),
+ STResList17 = [STRes16|STResList16],
+
+
+ ?line {STRes17,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF018.xsd','./msxsdtest/simpleType',invalid),
+ STResList18 = [STRes17|STResList17],
+
+
+ ?line {STRes18,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF019.xsd','./msxsdtest/simpleType',invalid),
+ STResList19 = [STRes18|STResList18],
+
+
+ ?line {STRes19,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF020.xsd','./msxsdtest/simpleType',invalid),
+ STResList20 = [STRes19|STResList19],
+
+
+ ?line {STRes20,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF021.xsd','./msxsdtest/simpleType',invalid),
+ STResList21 = [STRes20|STResList20],
+
+
+ ?line {STRes21,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF022.xsd','./msxsdtest/simpleType',invalid),
+ STResList22 = [STRes21|STResList21],
+
+
+ ?line {STRes22,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF023.xsd','./msxsdtest/simpleType',invalid),
+ STResList23 = [STRes22|STResList22],
+
+
+ ?line {STRes23,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF024.xsd','./msxsdtest/simpleType',invalid),
+ STResList24 = [STRes23|STResList23],
+
+
+ ?line {STRes24,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF025.xsd','./msxsdtest/simpleType',invalid),
+ STResList25 = [STRes24|STResList24],
+
+
+ ?line {STRes25,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF026.xsd','./msxsdtest/simpleType',invalid),
+ STResList26 = [STRes25|STResList25],
+
+
+ ?line {STRes26,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF027.xsd','./msxsdtest/simpleType',invalid),
+ STResList27 = [STRes26|STResList26],
+
+
+ ?line {STRes27,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF028.xsd','./msxsdtest/simpleType',invalid),
+ STResList28 = [STRes27|STResList27],
+
+
+ ?line {STRes28,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF029.xsd','./msxsdtest/simpleType',invalid),
+ STResList29 = [STRes28|STResList28],
+
+
+ ?line {STRes29,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF030.xsd','./msxsdtest/simpleType',invalid),
+ STResList30 = [STRes29|STResList29],
+
+
+ ?line {STRes30,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF031.xsd','./msxsdtest/simpleType',invalid),
+ STResList31 = [STRes30|STResList30],
+
+
+ ?line {STRes31,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF032.xsd','./msxsdtest/simpleType',valid),
+ STResList32 = [STRes31|STResList31],
+
+
+ ?line {STRes32,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF033.xsd','./msxsdtest/simpleType',invalid),
+ STResList33 = [STRes32|STResList32],
+
+
+ ?line {STRes33,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF034.xsd','./msxsdtest/simpleType',valid),
+ STResList34 = [STRes33|STResList33],
+
+
+ ?line {STRes34,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF035.xsd','./msxsdtest/simpleType',invalid),
+ STResList35 = [STRes34|STResList34],
+
+
+ ?line {STRes35,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF036.xsd','./msxsdtest/simpleType',valid),
+ STResList36 = [STRes35|STResList35],
+
+
+ ?line {STRes36,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stF037.xsd','./msxsdtest/simpleType',invalid),
+ STResList37 = [STRes36|STResList36],
+
+
+ ?line {STRes37,S37} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stG001.xsd','./msxsdtest/simpleType',valid),
+ STResList38 = [STRes37|STResList37],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stG001.xml','./msxsdtest/simpleType',valid,S37),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes38,S38} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stG002.xsd','./msxsdtest/simpleType',valid),
+ STResList39 = [STRes38|STResList38],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stG002.xml','./msxsdtest/simpleType',valid,S38),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes39,S39} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stG003.xsd','./msxsdtest/simpleType',valid),
+ STResList40 = [STRes39|STResList39],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stG003.xml','./msxsdtest/simpleType',invalid,S39),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes40,S40} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stG004.xsd','./msxsdtest/simpleType',valid),
+ STResList41 = [STRes40|STResList40],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stG004.xml','./msxsdtest/simpleType',valid,S40),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes41,S41} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stG005.xsd','./msxsdtest/simpleType',valid),
+ STResList42 = [STRes41|STResList41],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stG005.xml','./msxsdtest/simpleType',invalid,S41),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes42,S42} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stG006.xsd','./msxsdtest/simpleType',valid),
+ STResList43 = [STRes42|STResList42],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stG006.xml','./msxsdtest/simpleType',valid,S42),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes43,S43} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stG007.xsd','./msxsdtest/simpleType',valid),
+ STResList44 = [STRes43|STResList43],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stG007.xml','./msxsdtest/simpleType',invalid,S43),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes44,S44} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stG008.xsd','./msxsdtest/simpleType',valid),
+ STResList45 = [STRes44|STResList44],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stG008.xml','./msxsdtest/simpleType',valid,S44),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes45,S45} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stG009.xsd','./msxsdtest/simpleType',valid),
+ STResList46 = [STRes45|STResList45],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stG009.xml','./msxsdtest/simpleType',invalid,S45),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes46,S46} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stG010.xsd','./msxsdtest/simpleType',valid),
+ STResList47 = [STRes46|STResList46],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stG010.xml','./msxsdtest/simpleType',valid,S46),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes47,S47} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stG011.xsd','./msxsdtest/simpleType',valid),
+ STResList48 = [STRes47|STResList47],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stG011.xml','./msxsdtest/simpleType',invalid,S47),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes48,S48} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stG012.xsd','./msxsdtest/simpleType',valid),
+ STResList49 = [STRes48|STResList48],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stG012.xml','./msxsdtest/simpleType',valid,S48),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes49,S49} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stG013.xsd','./msxsdtest/simpleType',valid),
+ STResList50 = [STRes49|STResList49],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stG013.xml','./msxsdtest/simpleType',invalid,S49),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes50,S50} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stH001.xsd','./msxsdtest/simpleType',valid),
+ STResList51 = [STRes50|STResList50],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stH001.xml','./msxsdtest/simpleType',valid,S50),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes51,S51} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stH002.xsd','./msxsdtest/simpleType',valid),
+ STResList52 = [STRes51|STResList51],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stH002.xml','./msxsdtest/simpleType',invalid,S51),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes52,S52} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stH003.xsd','./msxsdtest/simpleType',valid),
+ STResList53 = [STRes52|STResList52],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stH003.xml','./msxsdtest/simpleType',valid,S52),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes53,S53} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stH004.xsd','./msxsdtest/simpleType',valid),
+ STResList54 = [STRes53|STResList53],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stH004.xml','./msxsdtest/simpleType',invalid,S53),
+ ITResList17 = [ITRes16|ITResList16],
+
+
+ ?line {STRes54,S54} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stH005.xsd','./msxsdtest/simpleType',valid),
+ STResList55 = [STRes54|STResList54],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stH005.xml','./msxsdtest/simpleType',valid,S54),
+ ITResList18 = [ITRes17|ITResList17],
+
+
+ ?line {STRes55,S55} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stH006.xsd','./msxsdtest/simpleType',valid),
+ STResList56 = [STRes55|STResList55],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stH006.xml','./msxsdtest/simpleType',invalid,S55),
+ ITResList19 = [ITRes18|ITResList18],
+
+
+ ?line {STRes56,S56} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stH007.xsd','./msxsdtest/simpleType',valid),
+ STResList57 = [STRes56|STResList56],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stH007.xml','./msxsdtest/simpleType',valid,S56),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes57,S57} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stH008.xsd','./msxsdtest/simpleType',valid),
+ STResList58 = [STRes57|STResList57],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stH008.xml','./msxsdtest/simpleType',invalid,S57),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList58,ITResList21).
+
+%% simpleType Schema Component Constraints.
+
+stIJK(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stI001.xsd','./msxsdtest/simpleType',valid),
+ STResList1 = [STRes0|STResList0],
+
+
+ ?line {STRes1,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stI002.xsd','./msxsdtest/simpleType',valid),
+ STResList2 = [STRes1|STResList1],
+
+
+ ?line {STRes2,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stI003.xsd','./msxsdtest/simpleType',valid),
+ STResList3 = [STRes2|STResList2],
+
+
+ ?line {STRes3,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stI004.xsd','./msxsdtest/simpleType',invalid),
+ STResList4 = [STRes3|STResList3],
+
+
+ ?line {STRes4,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stI005.xsd','./msxsdtest/simpleType',invalid),
+ STResList5 = [STRes4|STResList4],
+
+
+ ?line {STRes5,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stJ001.xsd','./msxsdtest/simpleType',valid),
+ STResList6 = [STRes5|STResList5],
+
+
+ ?line {STRes6,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stJ002.xsd','./msxsdtest/simpleType',valid),
+ STResList7 = [STRes6|STResList6],
+
+
+ ?line {STRes7,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stJ003.xsd','./msxsdtest/simpleType',invalid),
+ STResList8 = [STRes7|STResList7],
+
+
+ ?line {STRes8,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stJ004.xsd','./msxsdtest/simpleType',valid),
+ STResList9 = [STRes8|STResList8],
+
+
+ ?line {STRes9,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stJ005.xsd','./msxsdtest/simpleType',valid),
+ STResList10 = [STRes9|STResList9],
+
+
+ ?line {STRes10,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stJ006.xsd','./msxsdtest/simpleType',valid),
+ STResList11 = [STRes10|STResList10],
+
+
+ ?line {STRes11,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stJ007.xsd','./msxsdtest/simpleType',valid),
+ STResList12 = [STRes11|STResList11],
+
+
+ ?line {STRes12,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stJ008.xsd','./msxsdtest/simpleType',valid),
+ STResList13 = [STRes12|STResList12],
+
+
+ ?line {STRes13,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stJ009.xsd','./msxsdtest/simpleType',invalid),
+ STResList14 = [STRes13|STResList13],
+
+
+ ?line {STRes14,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stJ010.xsd','./msxsdtest/simpleType',invalid),
+ STResList15 = [STRes14|STResList14],
+
+
+ ?line {STRes15,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stJ011.xsd','./msxsdtest/simpleType',invalid),
+ STResList16 = [STRes15|STResList15],
+
+
+ ?line {STRes16,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stJ012.xsd','./msxsdtest/simpleType',invalid),
+ STResList17 = [STRes16|STResList16],
+
+
+ ?line {STRes17,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stJ013.xsd','./msxsdtest/simpleType',invalid),
+ STResList18 = [STRes17|STResList17],
+
+
+ ?line {STRes18,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stJ014.xsd','./msxsdtest/simpleType',invalid),
+ STResList19 = [STRes18|STResList18],
+
+
+ ?line {STRes19,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stJ015.xsd','./msxsdtest/simpleType',invalid),
+ STResList20 = [STRes19|STResList19],
+
+
+ ?line {STRes20,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stJ016.xsd','./msxsdtest/simpleType',invalid),
+ STResList21 = [STRes20|STResList20],
+
+
+ ?line {STRes21,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stJ017.xsd','./msxsdtest/simpleType',invalid),
+ STResList22 = [STRes21|STResList21],
+
+
+ ?line {STRes22,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stJ018.xsd','./msxsdtest/simpleType',invalid),
+ STResList23 = [STRes22|STResList22],
+
+
+ ?line {STRes23,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stJ019.xsd','./msxsdtest/simpleType',invalid),
+ STResList24 = [STRes23|STResList23],
+
+
+ ?line {STRes24,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stK001.xsd','./msxsdtest/simpleType',valid),
+ STResList25 = [STRes24|STResList24],
+
+
+ ?line {STRes25,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stK002.xsd','./msxsdtest/simpleType',invalid),
+ STResList26 = [STRes25|STResList25],
+
+
+ ?line {STRes26,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stK003.xsd','./msxsdtest/simpleType',invalid),
+ STResList27 = [STRes26|STResList26],
+
+
+ ?line {STRes27,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stK004.xsd','./msxsdtest/simpleType',valid),
+ STResList28 = [STRes27|STResList27],
+
+
+ ?line {STRes28,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stK005.xsd','./msxsdtest/simpleType',invalid),
+ STResList29 = [STRes28|STResList28],
+
+
+ ?line {STRes29,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stK006.xsd','./msxsdtest/simpleType',invalid),
+ STResList30 = [STRes29|STResList29],
+
+
+ ?line {STRes30,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stK007.xsd','./msxsdtest/simpleType',invalid),
+ STResList31 = [STRes30|STResList30],
+
+
+ ?line {STRes31,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stK008.xsd','./msxsdtest/simpleType',valid),
+ STResList32 = [STRes31|STResList31],
+
+
+ ?line {STRes32,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stK009.xsd','./msxsdtest/simpleType',valid),
+ STResList33 = [STRes32|STResList32],
+
+
+ ?line {STRes33,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stK010.xsd','./msxsdtest/simpleType',invalid),
+ STResList34 = [STRes33|STResList33],
+
+
+ ?line {STRes34,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stK011.xsd','./msxsdtest/simpleType',invalid),
+ STResList35 = [STRes34|STResList34],
+
+
+ ?line {STRes35,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stK012.xsd','./msxsdtest/simpleType',invalid),
+ STResList36 = [STRes35|STResList35],
+
+
+ ?line {STRes36,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stK013.xsd','./msxsdtest/simpleType',invalid),
+ STResList37 = [STRes36|STResList36],
+
+
+ ?line {STRes37,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stK014.xsd','./msxsdtest/simpleType',invalid),
+ STResList38 = [STRes37|STResList37],
+
+
+ ?line {STRes38,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stK015.xsd','./msxsdtest/simpleType',invalid),
+ STResList39 = [STRes38|STResList38],
+
+
+ ?line {STRes39,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stK016.xsd','./msxsdtest/simpleType',invalid),
+ STResList40 = [STRes39|STResList39],
+
+
+ ?line {STRes40,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stK017.xsd','./msxsdtest/simpleType',invalid),
+ STResList41 = [STRes40|STResList40],
+
+
+ ?line {STRes41,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stK018.xsd','./msxsdtest/simpleType',invalid),
+ STResList42 = [STRes41|STResList41],
+
+
+ ?line {STRes42,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stK019.xsd','./msxsdtest/simpleType',invalid),
+ STResList43 = [STRes42|STResList42],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList43,[]).
+
+%% Bug Regressions.
+
+stZ(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stZ001.xsd','./msxsdtest/simpleType',valid),
+ STResList1 = [STRes0|STResList0],
+
+
+ ?line {STRes1,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stZ002.xsd','./msxsdtest/simpleType',invalid),
+ STResList2 = [STRes1|STResList1],
+
+
+ ?line {STRes2,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stZ003.xsd','./msxsdtest/simpleType',invalid),
+ STResList3 = [STRes2|STResList2],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/simpleType/stZ004.xsd','./msxsdtest/simpleType',valid),
+ STResList4 = [STRes3|STResList3],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/simpleType/stZ004.xml','./msxsdtest/simpleType',valid,S3),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList4,ITResList1).
+
+%% Syntax Validation - any.
+
+wildABCDEF(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildA001.xsd','./msxsdtest/wildCards',valid),
+ STResList1 = [STRes0|STResList0],
+
+
+ ?line {STRes1,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildA002.xsd','./msxsdtest/wildCards',valid),
+ STResList2 = [STRes1|STResList1],
+
+
+ ?line {STRes2,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildA003.xsd','./msxsdtest/wildCards',invalid),
+ STResList3 = [STRes2|STResList2],
+
+
+ ?line {STRes3,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildA004.xsd','./msxsdtest/wildCards',invalid),
+ STResList4 = [STRes3|STResList3],
+
+
+ ?line {STRes4,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildA005.xsd','./msxsdtest/wildCards',invalid),
+ STResList5 = [STRes4|STResList4],
+
+
+ ?line {STRes5,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildA006.xsd','./msxsdtest/wildCards',invalid),
+ STResList6 = [STRes5|STResList5],
+
+
+ ?line {STRes6,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildA007.xsd','./msxsdtest/wildCards',invalid),
+ STResList7 = [STRes6|STResList6],
+
+
+ ?line {STRes7,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildA008.xsd','./msxsdtest/wildCards',invalid),
+ STResList8 = [STRes7|STResList7],
+
+
+ ?line {STRes8,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB009.xsd','./msxsdtest/wildCards',valid),
+ STResList9 = [STRes8|STResList8],
+
+
+ ?line {STRes9,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB010.xsd','./msxsdtest/wildCards',valid),
+ STResList10 = [STRes9|STResList9],
+
+
+ ?line {STRes10,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB011.xsd','./msxsdtest/wildCards',valid),
+ STResList11 = [STRes10|STResList10],
+
+
+ ?line {STRes11,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB012.xsd','./msxsdtest/wildCards',valid),
+ STResList12 = [STRes11|STResList11],
+
+
+ ?line {STRes12,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB013.xsd','./msxsdtest/wildCards',valid),
+ STResList13 = [STRes12|STResList12],
+
+
+ ?line {STRes13,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB014.xsd','./msxsdtest/wildCards',invalid),
+ STResList14 = [STRes13|STResList13],
+
+
+ ?line {STRes14,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB015.xsd','./msxsdtest/wildCards',invalid),
+ STResList15 = [STRes14|STResList14],
+
+
+ ?line {STRes15,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB016.xsd','./msxsdtest/wildCards',invalid),
+ STResList16 = [STRes15|STResList15],
+
+
+ ?line {STRes16,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB017.xsd','./msxsdtest/wildCards',valid),
+ STResList17 = [STRes16|STResList16],
+
+
+ ?line {STRes17,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB018.xsd','./msxsdtest/wildCards',valid),
+ STResList18 = [STRes17|STResList17],
+
+
+ ?line {STRes18,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB019.xsd','./msxsdtest/wildCards',valid),
+ STResList19 = [STRes18|STResList18],
+
+
+ ?line {STRes19,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB020.xsd','./msxsdtest/wildCards',invalid),
+ STResList20 = [STRes19|STResList19],
+
+
+ ?line {STRes20,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB021.xsd','./msxsdtest/wildCards',valid),
+ STResList21 = [STRes20|STResList20],
+
+
+ ?line {STRes21,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB022.xsd','./msxsdtest/wildCards',invalid),
+ STResList22 = [STRes21|STResList21],
+
+
+ ?line {STRes22,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB023.xsd','./msxsdtest/wildCards',invalid),
+ STResList23 = [STRes22|STResList22],
+
+
+ ?line {STRes23,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB024.xsd','./msxsdtest/wildCards',invalid),
+ STResList24 = [STRes23|STResList23],
+
+
+ ?line {STRes24,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB025.xsd','./msxsdtest/wildCards',valid),
+ STResList25 = [STRes24|STResList24],
+
+
+ ?line {STRes25,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB026.xsd','./msxsdtest/wildCards',valid),
+ STResList26 = [STRes25|STResList25],
+
+
+ ?line {STRes26,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB027.xsd','./msxsdtest/wildCards',invalid),
+ STResList27 = [STRes26|STResList26],
+
+
+ ?line {STRes27,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB028.xsd','./msxsdtest/wildCards',invalid),
+ STResList28 = [STRes27|STResList27],
+
+
+ ?line {STRes28,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildB029.xsd','./msxsdtest/wildCards',valid),
+ STResList29 = [STRes28|STResList28],
+
+
+ ?line {STRes29,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC030.xsd','./msxsdtest/wildCards',valid),
+ STResList30 = [STRes29|STResList29],
+
+
+ ?line {STRes30,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC031.xsd','./msxsdtest/wildCards',valid),
+ STResList31 = [STRes30|STResList30],
+
+
+ ?line {STRes31,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC032.xsd','./msxsdtest/wildCards',valid),
+ STResList32 = [STRes31|STResList31],
+
+
+ ?line {STRes32,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC033.xsd','./msxsdtest/wildCards',valid),
+ STResList33 = [STRes32|STResList32],
+
+
+ ?line {STRes33,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC034.xsd','./msxsdtest/wildCards',valid),
+ STResList34 = [STRes33|STResList33],
+
+
+ ?line {STRes34,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC035.xsd','./msxsdtest/wildCards',invalid),
+ STResList35 = [STRes34|STResList34],
+
+
+ ?line {STRes35,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC036.xsd','./msxsdtest/wildCards',invalid),
+ STResList36 = [STRes35|STResList35],
+
+
+ ?line {STRes36,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC037.xsd','./msxsdtest/wildCards',valid),
+ STResList37 = [STRes36|STResList36],
+
+
+ ?line {STRes37,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC038.xsd','./msxsdtest/wildCards',valid),
+ STResList38 = [STRes37|STResList37],
+
+
+ ?line {STRes38,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC039.xsd','./msxsdtest/wildCards',valid),
+ STResList39 = [STRes38|STResList38],
+
+
+ ?line {STRes39,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC040.xsd','./msxsdtest/wildCards',valid),
+ STResList40 = [STRes39|STResList39],
+
+
+ ?line {STRes40,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC041.xsd','./msxsdtest/wildCards',valid),
+ STResList41 = [STRes40|STResList40],
+
+
+ ?line {STRes41,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC042.xsd','./msxsdtest/wildCards',valid),
+ STResList42 = [STRes41|STResList41],
+
+
+ ?line {STRes42,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC043.xsd','./msxsdtest/wildCards',valid),
+ STResList43 = [STRes42|STResList42],
+
+
+ ?line {STRes43,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC044.xsd','./msxsdtest/wildCards',valid),
+ STResList44 = [STRes43|STResList43],
+
+
+ ?line {STRes44,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC045.xsd','./msxsdtest/wildCards',valid),
+ STResList45 = [STRes44|STResList44],
+
+
+ ?line {STRes45,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC046.xsd','./msxsdtest/wildCards',valid),
+ STResList46 = [STRes45|STResList45],
+
+
+ ?line {STRes46,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC047.xsd','./msxsdtest/wildCards',valid),
+ STResList47 = [STRes46|STResList46],
+
+
+ ?line {STRes47,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC048.xsd','./msxsdtest/wildCards',valid),
+ STResList48 = [STRes47|STResList47],
+
+
+ ?line {STRes48,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC049.xsd','./msxsdtest/wildCards',invalid),
+ STResList49 = [STRes48|STResList48],
+
+
+ ?line {STRes49,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC050.xsd','./msxsdtest/wildCards',invalid),
+ STResList50 = [STRes49|STResList49],
+
+
+ ?line {STRes50,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC051.xsd','./msxsdtest/wildCards',invalid),
+ STResList51 = [STRes50|STResList50],
+
+
+ ?line {STRes51,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC052.xsd','./msxsdtest/wildCards',invalid),
+ STResList52 = [STRes51|STResList51],
+
+
+ ?line {STRes52,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC053.xsd','./msxsdtest/wildCards',invalid),
+ STResList53 = [STRes52|STResList52],
+
+
+ ?line {STRes53,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC054.xsd','./msxsdtest/wildCards',valid),
+ STResList54 = [STRes53|STResList53],
+
+
+ ?line {STRes54,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC055.xsd','./msxsdtest/wildCards',invalid),
+ STResList55 = [STRes54|STResList54],
+
+
+ ?line {STRes55,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC056.xsd','./msxsdtest/wildCards',invalid),
+ STResList56 = [STRes55|STResList55],
+
+
+ ?line {STRes56,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC057.xsd','./msxsdtest/wildCards',invalid),
+ STResList57 = [STRes56|STResList56],
+
+
+ ?line {STRes57,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC058.xsd','./msxsdtest/wildCards',invalid),
+ STResList58 = [STRes57|STResList57],
+
+
+ ?line {STRes58,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC059.xsd','./msxsdtest/wildCards',valid),
+ STResList59 = [STRes58|STResList58],
+
+
+ ?line {STRes59,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC060.xsd','./msxsdtest/wildCards',valid),
+ STResList60 = [STRes59|STResList59],
+
+
+ ?line {STRes60,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC061.xsd','./msxsdtest/wildCards',valid),
+ STResList61 = [STRes60|STResList60],
+
+
+ ?line {STRes61,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC062.xsd','./msxsdtest/wildCards',valid),
+ STResList62 = [STRes61|STResList61],
+
+
+ ?line {STRes62,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC063.xsd','./msxsdtest/wildCards',valid),
+ STResList63 = [STRes62|STResList62],
+
+
+ ?line {STRes63,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC064.xsd','./msxsdtest/wildCards',valid),
+ STResList64 = [STRes63|STResList63],
+
+
+ ?line {STRes64,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC065.xsd','./msxsdtest/wildCards',valid),
+ STResList65 = [STRes64|STResList64],
+
+
+ ?line {STRes65,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC066.xsd','./msxsdtest/wildCards',invalid),
+ STResList66 = [STRes65|STResList65],
+
+
+ ?line {STRes66,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC067.xsd','./msxsdtest/wildCards',invalid),
+ STResList67 = [STRes66|STResList66],
+
+
+ ?line {STRes67,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC068.xsd','./msxsdtest/wildCards',valid),
+ STResList68 = [STRes67|STResList67],
+
+
+ ?line {STRes68,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC069.xsd','./msxsdtest/wildCards',valid),
+ STResList69 = [STRes68|STResList68],
+
+
+ ?line {STRes69,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildC070.xsd','./msxsdtest/wildCards',valid),
+ STResList70 = [STRes69|STResList69],
+
+
+ ?line {STRes70,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildD071.xsd','./msxsdtest/wildCards',invalid),
+ STResList71 = [STRes70|STResList70],
+
+
+ ?line {STRes71,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildD072.xsd','./msxsdtest/wildCards',valid),
+ STResList72 = [STRes71|STResList71],
+
+
+ ?line {STRes72,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildD073.xsd','./msxsdtest/wildCards',valid),
+ STResList73 = [STRes72|STResList72],
+
+
+ ?line {STRes73,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildD074.xsd','./msxsdtest/wildCards',valid),
+ STResList74 = [STRes73|STResList73],
+
+
+ ?line {STRes74,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildD075.xsd','./msxsdtest/wildCards',invalid),
+ STResList75 = [STRes74|STResList74],
+
+
+ ?line {STRes75,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildD076.xsd','./msxsdtest/wildCards',invalid),
+ STResList76 = [STRes75|STResList75],
+
+
+ ?line {STRes76,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildD077.xsd','./msxsdtest/wildCards',invalid),
+ STResList77 = [STRes76|STResList76],
+
+
+ ?line {STRes77,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildD078.xsd','./msxsdtest/wildCards',invalid),
+ STResList78 = [STRes77|STResList77],
+
+
+ ?line {STRes78,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildD079.xsd','./msxsdtest/wildCards',invalid),
+ STResList79 = [STRes78|STResList78],
+
+
+ ?line {STRes79,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildE001.xsd','./msxsdtest/wildCards',valid),
+ STResList80 = [STRes79|STResList79],
+
+
+ ?line {STRes80,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildE002.xsd','./msxsdtest/wildCards',invalid),
+ STResList81 = [STRes80|STResList80],
+
+
+ ?line {STRes81,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF001.xsd','./msxsdtest/wildCards',valid),
+ STResList82 = [STRes81|STResList81],
+
+
+ ?line {STRes82,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF002.xsd','./msxsdtest/wildCards',valid),
+ STResList83 = [STRes82|STResList82],
+
+
+ ?line {STRes83,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF003.xsd','./msxsdtest/wildCards',valid),
+ STResList84 = [STRes83|STResList83],
+
+
+ ?line {STRes84,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF004.xsd','./msxsdtest/wildCards',valid),
+ STResList85 = [STRes84|STResList84],
+
+
+ ?line {STRes85,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF005.xsd','./msxsdtest/wildCards',valid),
+ STResList86 = [STRes85|STResList85],
+
+
+ ?line {STRes86,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF006.xsd','./msxsdtest/wildCards',invalid),
+ STResList87 = [STRes86|STResList86],
+
+
+ ?line {STRes87,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF007.xsd','./msxsdtest/wildCards',invalid),
+ STResList88 = [STRes87|STResList87],
+
+
+ ?line {STRes88,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF008.xsd','./msxsdtest/wildCards',invalid),
+ STResList89 = [STRes88|STResList88],
+
+
+ ?line {STRes89,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF009.xsd','./msxsdtest/wildCards',invalid),
+ STResList90 = [STRes89|STResList89],
+
+
+ ?line {STRes90,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF010.xsd','./msxsdtest/wildCards',invalid),
+ STResList91 = [STRes90|STResList90],
+
+
+ ?line {STRes91,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF011.xsd','./msxsdtest/wildCards',valid),
+ STResList92 = [STRes91|STResList91],
+
+
+ ?line {STRes92,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF012.xsd','./msxsdtest/wildCards',invalid),
+ STResList93 = [STRes92|STResList92],
+
+
+ ?line {STRes93,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF013.xsd','./msxsdtest/wildCards',invalid),
+ STResList94 = [STRes93|STResList93],
+
+
+ ?line {STRes94,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF014.xsd','./msxsdtest/wildCards',invalid),
+ STResList95 = [STRes94|STResList94],
+
+
+ ?line {STRes95,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF015.xsd','./msxsdtest/wildCards',invalid),
+ STResList96 = [STRes95|STResList95],
+
+
+ ?line {STRes96,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF016.xsd','./msxsdtest/wildCards',invalid),
+ STResList97 = [STRes96|STResList96],
+
+
+ ?line {STRes97,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF017.xsd','./msxsdtest/wildCards',valid),
+ STResList98 = [STRes97|STResList97],
+
+
+ ?line {STRes98,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF018.xsd','./msxsdtest/wildCards',invalid),
+ STResList99 = [STRes98|STResList98],
+
+
+ ?line {STRes99,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF019.xsd','./msxsdtest/wildCards',valid),
+ STResList100 = [STRes99|STResList99],
+
+
+ ?line {STRes100,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildF020.xsd','./msxsdtest/wildCards',valid),
+ STResList101 = [STRes100|STResList100],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList101,[]).
+
+%% 3.10.4 Wildcard Validation Rules - any.
+
+wildGHI(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG001.xsd','./msxsdtest/wildCards',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG001.xml','./msxsdtest/wildCards',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG002.xsd','./msxsdtest/wildCards',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG002.xml','./msxsdtest/wildCards',valid,S1),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG003.xsd','./msxsdtest/wildCards',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG003.xml','./msxsdtest/wildCards',invalid,S2),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG004.xsd','./msxsdtest/wildCards',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG004.xml','./msxsdtest/wildCards',valid,S3),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG005.xsd','./msxsdtest/wildCards',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG005.xml','./msxsdtest/wildCards',invalid,S4),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG006.xsd','./msxsdtest/wildCards',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG006.xml','./msxsdtest/wildCards',valid,S5),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG007.xsd','./msxsdtest/wildCards',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG007.xml','./msxsdtest/wildCards',valid,S6),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG008.xsd','./msxsdtest/wildCards',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG008.xml','./msxsdtest/wildCards',invalid,S7),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG009.xsd','./msxsdtest/wildCards',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG009.xml','./msxsdtest/wildCards',invalid,S8),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG010.xsd','./msxsdtest/wildCards',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG010.xml','./msxsdtest/wildCards',valid,S9),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG011.xsd','./msxsdtest/wildCards',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG011.xml','./msxsdtest/wildCards',invalid,S10),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG012.xsd','./msxsdtest/wildCards',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG012.xml','./msxsdtest/wildCards',valid,S11),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG013.xsd','./msxsdtest/wildCards',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG013.xml','./msxsdtest/wildCards',valid,S12),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG014.xsd','./msxsdtest/wildCards',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG014.xml','./msxsdtest/wildCards',invalid,S13),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG015.xsd','./msxsdtest/wildCards',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG015.xml','./msxsdtest/wildCards',valid,S14),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG016.xsd','./msxsdtest/wildCards',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG016.xml','./msxsdtest/wildCards',valid,S15),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG017.xsd','./msxsdtest/wildCards',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG017.xml','./msxsdtest/wildCards',invalid,S16),
+ ITResList17 = [ITRes16|ITResList16],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG018.xsd','./msxsdtest/wildCards',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG018.xml','./msxsdtest/wildCards',valid,S17),
+ ITResList18 = [ITRes17|ITResList17],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG019.xsd','./msxsdtest/wildCards',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG019.xml','./msxsdtest/wildCards',invalid,S18),
+ ITResList19 = [ITRes18|ITResList18],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG020.xsd','./msxsdtest/wildCards',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG020.xml','./msxsdtest/wildCards',invalid,S19),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG021.xsd','./msxsdtest/wildCards',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG021.xml','./msxsdtest/wildCards',valid,S20),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG022.xsd','./msxsdtest/wildCards',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG022.xml','./msxsdtest/wildCards',invalid,S21),
+ ITResList22 = [ITRes21|ITResList21],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG023.xsd','./msxsdtest/wildCards',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG023.xml','./msxsdtest/wildCards',valid,S22),
+ ITResList23 = [ITRes22|ITResList22],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG024.xsd','./msxsdtest/wildCards',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG024.xml','./msxsdtest/wildCards',invalid,S23),
+ ITResList24 = [ITRes23|ITResList23],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG025.xsd','./msxsdtest/wildCards',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG025.xml','./msxsdtest/wildCards',invalid,S24),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG026.xsd','./msxsdtest/wildCards',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG026.xml','./msxsdtest/wildCards',valid,S25),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG027.xsd','./msxsdtest/wildCards',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG027.xml','./msxsdtest/wildCards',valid,S26),
+ ITResList27 = [ITRes26|ITResList26],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG028.xsd','./msxsdtest/wildCards',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG028.xml','./msxsdtest/wildCards',invalid,S27),
+ ITResList28 = [ITRes27|ITResList27],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG029.xsd','./msxsdtest/wildCards',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG029.xml','./msxsdtest/wildCards',invalid,S28),
+ ITResList29 = [ITRes28|ITResList28],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG030.xsd','./msxsdtest/wildCards',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG030.xml','./msxsdtest/wildCards',invalid,S29),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG031.xsd','./msxsdtest/wildCards',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG031.xml','./msxsdtest/wildCards',valid,S30),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes31,S31} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG032.xsd','./msxsdtest/wildCards',valid),
+ STResList32 = [STRes31|STResList31],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG032.xml','./msxsdtest/wildCards',invalid,S31),
+ ITResList32 = [ITRes31|ITResList31],
+
+
+ ?line {STRes32,S32} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG033.xsd','./msxsdtest/wildCards',valid),
+ STResList33 = [STRes32|STResList32],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG033.xml','./msxsdtest/wildCards',valid,S32),
+ ITResList33 = [ITRes32|ITResList32],
+
+
+ ?line {STRes33,S33} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG034.xsd','./msxsdtest/wildCards',valid),
+ STResList34 = [STRes33|STResList33],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG034.xml','./msxsdtest/wildCards',invalid,S33),
+ ITResList34 = [ITRes33|ITResList33],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG035.xsd','./msxsdtest/wildCards',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG035.xml','./msxsdtest/wildCards',valid,S34),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes35,S35} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG036.xsd','./msxsdtest/wildCards',valid),
+ STResList36 = [STRes35|STResList35],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG036.xml','./msxsdtest/wildCards',invalid,S35),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes36,S36} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG037.xsd','./msxsdtest/wildCards',valid),
+ STResList37 = [STRes36|STResList36],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG037.xml','./msxsdtest/wildCards',valid,S36),
+ ITResList37 = [ITRes36|ITResList36],
+
+
+ ?line {STRes37,S37} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG038.xsd','./msxsdtest/wildCards',valid),
+ STResList38 = [STRes37|STResList37],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG038.xml','./msxsdtest/wildCards',valid,S37),
+ ITResList38 = [ITRes37|ITResList37],
+
+
+ ?line {STRes38,S38} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG039.xsd','./msxsdtest/wildCards',valid),
+ STResList39 = [STRes38|STResList38],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG039.xml','./msxsdtest/wildCards',invalid,S38),
+ ITResList39 = [ITRes38|ITResList38],
+
+
+ ?line {STRes39,S39} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildG040.xsd','./msxsdtest/wildCards',valid),
+ STResList40 = [STRes39|STResList39],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildG040.xml','./msxsdtest/wildCards',valid,S39),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes40,S40} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildH001.xsd','./msxsdtest/wildCards',valid),
+ STResList41 = [STRes40|STResList40],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildH001.xml','./msxsdtest/wildCards',invalid,S40),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes41,S41} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildH002.xsd','./msxsdtest/wildCards',valid),
+ STResList42 = [STRes41|STResList41],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildH002.xml','./msxsdtest/wildCards',invalid,S41),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes42,S42} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildH003.xsd','./msxsdtest/wildCards',valid),
+ STResList43 = [STRes42|STResList42],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildH003.xml','./msxsdtest/wildCards',valid,S42),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes43,S43} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildH004.xsd','./msxsdtest/wildCards',valid),
+ STResList44 = [STRes43|STResList43],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildH004.xml','./msxsdtest/wildCards',valid,S43),
+ ITResList44 = [ITRes43|ITResList43],
+
+
+ ?line {STRes44,S44} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildH006.xsd','./msxsdtest/wildCards',valid),
+ STResList45 = [STRes44|STResList44],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildH006.xml','./msxsdtest/wildCards',invalid,S44),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes45,S45} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildH007.xsd','./msxsdtest/wildCards',valid),
+ STResList46 = [STRes45|STResList45],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildH007.xml','./msxsdtest/wildCards',valid,S45),
+ ITResList46 = [ITRes45|ITResList45],
+
+
+ ?line {STRes46,S46} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildH008.xsd','./msxsdtest/wildCards',valid),
+ STResList47 = [STRes46|STResList46],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildH008.xml','./msxsdtest/wildCards',invalid,S46),
+ ITResList47 = [ITRes46|ITResList46],
+
+
+ ?line {STRes47,S47} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildH009.xsd','./msxsdtest/wildCards',valid),
+ STResList48 = [STRes47|STResList47],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildH009.xml','./msxsdtest/wildCards',valid,S47),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes48,S48} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildH010.xsd','./msxsdtest/wildCards',valid),
+ STResList49 = [STRes48|STResList48],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildH010.xml','./msxsdtest/wildCards',valid,S48),
+ ITResList49 = [ITRes48|ITResList48],
+
+
+ ?line {STRes49,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildI001.xsd','./msxsdtest/wildCards',valid),
+ STResList50 = [STRes49|STResList49],
+
+
+ ?line {STRes50,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildI002.xsd','./msxsdtest/wildCards',invalid),
+ STResList51 = [STRes50|STResList50],
+
+
+ ?line {STRes51,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildI003.xsd','./msxsdtest/wildCards',invalid),
+ STResList52 = [STRes51|STResList51],
+
+
+ ?line {STRes52,S52} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildI004.xsd','./msxsdtest/wildCards',valid),
+ STResList53 = [STRes52|STResList52],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildI004.xml','./msxsdtest/wildCards',valid,S52),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes53,S53} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildI005.xsd','./msxsdtest/wildCards',valid),
+ STResList54 = [STRes53|STResList53],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildI005.xml','./msxsdtest/wildCards',valid,S53),
+ ITResList51 = [ITRes50|ITResList50],
+
+
+ ?line {STRes54,S54} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildI006.xsd','./msxsdtest/wildCards',valid),
+ STResList55 = [STRes54|STResList54],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildI006.xml','./msxsdtest/wildCards',valid,S54),
+ ITResList52 = [ITRes51|ITResList51],
+
+
+ ?line {STRes55,S55} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildI007.xsd','./msxsdtest/wildCards',valid),
+ STResList56 = [STRes55|STResList55],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildI007.xml','./msxsdtest/wildCards',valid,S55),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes56,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildI008.xsd','./msxsdtest/wildCards',invalid),
+ STResList57 = [STRes56|STResList56],
+
+
+ ?line {STRes57,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildI009.xsd','./msxsdtest/wildCards',invalid),
+ STResList58 = [STRes57|STResList57],
+
+
+ ?line {STRes58,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildI010.xsd','./msxsdtest/wildCards',invalid),
+ STResList59 = [STRes58|STResList58],
+
+
+ ?line {STRes59,S59} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildI011.xsd','./msxsdtest/wildCards',valid),
+ STResList60 = [STRes59|STResList59],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildI011.xml','./msxsdtest/wildCards',valid,S59),
+ ITResList54 = [ITRes53|ITResList53],
+
+
+ ?line {STRes60,S60} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildI012.xsd','./msxsdtest/wildCards',valid),
+ STResList61 = [STRes60|STResList60],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildI012.xml','./msxsdtest/wildCards',valid,S60),
+ ITResList55 = [ITRes54|ITResList54],
+
+
+ ?line {STRes61,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildI013.xsd','./msxsdtest/wildCards',invalid),
+ STResList62 = [STRes61|STResList61],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList62,ITResList55).
+
+%% Syntax Validation - anyAttribute.
+
+wildJKLMNQOP(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildJ001.xsd','./msxsdtest/wildCards',valid),
+ STResList1 = [STRes0|STResList0],
+
+
+ ?line {STRes1,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildJ002.xsd','./msxsdtest/wildCards',valid),
+ STResList2 = [STRes1|STResList1],
+
+
+ ?line {STRes2,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildJ003.xsd','./msxsdtest/wildCards',invalid),
+ STResList3 = [STRes2|STResList2],
+
+
+ ?line {STRes3,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildJ004.xsd','./msxsdtest/wildCards',invalid),
+ STResList4 = [STRes3|STResList3],
+
+
+ ?line {STRes4,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildJ005.xsd','./msxsdtest/wildCards',invalid),
+ STResList5 = [STRes4|STResList4],
+
+
+ ?line {STRes5,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildJ006.xsd','./msxsdtest/wildCards',invalid),
+ STResList6 = [STRes5|STResList5],
+
+
+ ?line {STRes6,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildJ007.xsd','./msxsdtest/wildCards',invalid),
+ STResList7 = [STRes6|STResList6],
+
+
+ ?line {STRes7,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildJ008.xsd','./msxsdtest/wildCards',invalid),
+ STResList8 = [STRes7|STResList7],
+
+
+ ?line {STRes8,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK001.xsd','./msxsdtest/wildCards',valid),
+ STResList9 = [STRes8|STResList8],
+
+
+ ?line {STRes9,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK002.xsd','./msxsdtest/wildCards',invalid),
+ STResList10 = [STRes9|STResList9],
+
+
+ ?line {STRes10,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK003.xsd','./msxsdtest/wildCards',valid),
+ STResList11 = [STRes10|STResList10],
+
+
+ ?line {STRes11,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK004.xsd','./msxsdtest/wildCards',valid),
+ STResList12 = [STRes11|STResList11],
+
+
+ ?line {STRes12,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK005.xsd','./msxsdtest/wildCards',valid),
+ STResList13 = [STRes12|STResList12],
+
+
+ ?line {STRes13,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK006.xsd','./msxsdtest/wildCards',invalid),
+ STResList14 = [STRes13|STResList13],
+
+
+ ?line {STRes14,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK007.xsd','./msxsdtest/wildCards',invalid),
+ STResList15 = [STRes14|STResList14],
+
+
+ ?line {STRes15,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK008.xsd','./msxsdtest/wildCards',valid),
+ STResList16 = [STRes15|STResList15],
+
+
+ ?line {STRes16,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK009.xsd','./msxsdtest/wildCards',valid),
+ STResList17 = [STRes16|STResList16],
+
+
+ ?line {STRes17,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK010.xsd','./msxsdtest/wildCards',valid),
+ STResList18 = [STRes17|STResList17],
+
+
+ ?line {STRes18,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK011.xsd','./msxsdtest/wildCards',valid),
+ STResList19 = [STRes18|STResList18],
+
+
+ ?line {STRes19,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK012.xsd','./msxsdtest/wildCards',valid),
+ STResList20 = [STRes19|STResList19],
+
+
+ ?line {STRes20,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK013.xsd','./msxsdtest/wildCards',valid),
+ STResList21 = [STRes20|STResList20],
+
+
+ ?line {STRes21,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK014.xsd','./msxsdtest/wildCards',valid),
+ STResList22 = [STRes21|STResList21],
+
+
+ ?line {STRes22,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK015.xsd','./msxsdtest/wildCards',valid),
+ STResList23 = [STRes22|STResList22],
+
+
+ ?line {STRes23,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK016.xsd','./msxsdtest/wildCards',valid),
+ STResList24 = [STRes23|STResList23],
+
+
+ ?line {STRes24,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK017.xsd','./msxsdtest/wildCards',valid),
+ STResList25 = [STRes24|STResList24],
+
+
+ ?line {STRes25,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK018.xsd','./msxsdtest/wildCards',valid),
+ STResList26 = [STRes25|STResList25],
+
+
+ ?line {STRes26,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK019.xsd','./msxsdtest/wildCards',valid),
+ STResList27 = [STRes26|STResList26],
+
+
+ ?line {STRes27,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK020.xsd','./msxsdtest/wildCards',invalid),
+ STResList28 = [STRes27|STResList27],
+
+
+ ?line {STRes28,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK021.xsd','./msxsdtest/wildCards',invalid),
+ STResList29 = [STRes28|STResList28],
+
+
+ ?line {STRes29,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK022.xsd','./msxsdtest/wildCards',invalid),
+ STResList30 = [STRes29|STResList29],
+
+
+ ?line {STRes30,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK023.xsd','./msxsdtest/wildCards',invalid),
+ STResList31 = [STRes30|STResList30],
+
+
+ ?line {STRes31,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK024.xsd','./msxsdtest/wildCards',invalid),
+ STResList32 = [STRes31|STResList31],
+
+
+ ?line {STRes32,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK025.xsd','./msxsdtest/wildCards',valid),
+ STResList33 = [STRes32|STResList32],
+
+
+ ?line {STRes33,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK026.xsd','./msxsdtest/wildCards',invalid),
+ STResList34 = [STRes33|STResList33],
+
+
+ ?line {STRes34,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK027.xsd','./msxsdtest/wildCards',invalid),
+ STResList35 = [STRes34|STResList34],
+
+
+ ?line {STRes35,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK028.xsd','./msxsdtest/wildCards',invalid),
+ STResList36 = [STRes35|STResList35],
+
+
+ ?line {STRes36,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK029.xsd','./msxsdtest/wildCards',invalid),
+ STResList37 = [STRes36|STResList36],
+
+
+ ?line {STRes37,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK030.xsd','./msxsdtest/wildCards',valid),
+ STResList38 = [STRes37|STResList37],
+
+
+ ?line {STRes38,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK031.xsd','./msxsdtest/wildCards',valid),
+ STResList39 = [STRes38|STResList38],
+
+
+ ?line {STRes39,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK032.xsd','./msxsdtest/wildCards',valid),
+ STResList40 = [STRes39|STResList39],
+
+
+ ?line {STRes40,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK033.xsd','./msxsdtest/wildCards',valid),
+ STResList41 = [STRes40|STResList40],
+
+
+ ?line {STRes41,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK034.xsd','./msxsdtest/wildCards',valid),
+ STResList42 = [STRes41|STResList41],
+
+
+ ?line {STRes42,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK035.xsd','./msxsdtest/wildCards',valid),
+ STResList43 = [STRes42|STResList42],
+
+
+ ?line {STRes43,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK036.xsd','./msxsdtest/wildCards',valid),
+ STResList44 = [STRes43|STResList43],
+
+
+ ?line {STRes44,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK037.xsd','./msxsdtest/wildCards',valid),
+ STResList45 = [STRes44|STResList44],
+
+
+ ?line {STRes45,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK038.xsd','./msxsdtest/wildCards',invalid),
+ STResList46 = [STRes45|STResList45],
+
+
+ ?line {STRes46,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK039.xsd','./msxsdtest/wildCards',valid),
+ STResList47 = [STRes46|STResList46],
+
+
+ ?line {STRes47,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK040.xsd','./msxsdtest/wildCards',valid),
+ STResList48 = [STRes47|STResList47],
+
+
+ ?line {STRes48,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildK041.xsd','./msxsdtest/wildCards',valid),
+ STResList49 = [STRes48|STResList48],
+
+
+ ?line {STRes49,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildL001.xsd','./msxsdtest/wildCards',invalid),
+ STResList50 = [STRes49|STResList49],
+
+
+ ?line {STRes50,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildL002.xsd','./msxsdtest/wildCards',valid),
+ STResList51 = [STRes50|STResList50],
+
+
+ ?line {STRes51,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildL003.xsd','./msxsdtest/wildCards',valid),
+ STResList52 = [STRes51|STResList51],
+
+
+ ?line {STRes52,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildL004.xsd','./msxsdtest/wildCards',valid),
+ STResList53 = [STRes52|STResList52],
+
+
+ ?line {STRes53,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildL005.xsd','./msxsdtest/wildCards',invalid),
+ STResList54 = [STRes53|STResList53],
+
+
+ ?line {STRes54,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildL006.xsd','./msxsdtest/wildCards',invalid),
+ STResList55 = [STRes54|STResList54],
+
+
+ ?line {STRes55,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildL007.xsd','./msxsdtest/wildCards',invalid),
+ STResList56 = [STRes55|STResList55],
+
+
+ ?line {STRes56,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildL008.xsd','./msxsdtest/wildCards',invalid),
+ STResList57 = [STRes56|STResList56],
+
+
+ ?line {STRes57,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildL009.xsd','./msxsdtest/wildCards',invalid),
+ STResList58 = [STRes57|STResList57],
+
+
+ ?line {STRes58,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildM001.xsd','./msxsdtest/wildCards',valid),
+ STResList59 = [STRes58|STResList58],
+
+
+ ?line {STRes59,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildM002.xsd','./msxsdtest/wildCards',invalid),
+ STResList60 = [STRes59|STResList59],
+
+
+ ?line {STRes60,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN001.xsd','./msxsdtest/wildCards',invalid),
+ STResList61 = [STRes60|STResList60],
+
+
+ ?line {STRes61,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN002.xsd','./msxsdtest/wildCards',valid),
+ STResList62 = [STRes61|STResList61],
+
+
+ ?line {STRes62,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN003.xsd','./msxsdtest/wildCards',valid),
+ STResList63 = [STRes62|STResList62],
+
+
+ ?line {STRes63,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN004.xsd','./msxsdtest/wildCards',valid),
+ STResList64 = [STRes63|STResList63],
+
+
+ ?line {STRes64,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN005.xsd','./msxsdtest/wildCards',valid),
+ STResList65 = [STRes64|STResList64],
+
+
+ ?line {STRes65,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN006.xsd','./msxsdtest/wildCards',invalid),
+ STResList66 = [STRes65|STResList65],
+
+
+ ?line {STRes66,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN007.xsd','./msxsdtest/wildCards',invalid),
+ STResList67 = [STRes66|STResList66],
+
+
+ ?line {STRes67,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN008.xsd','./msxsdtest/wildCards',invalid),
+ STResList68 = [STRes67|STResList67],
+
+
+ ?line {STRes68,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN009.xsd','./msxsdtest/wildCards',invalid),
+ STResList69 = [STRes68|STResList68],
+
+
+ ?line {STRes69,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN010.xsd','./msxsdtest/wildCards',invalid),
+ STResList70 = [STRes69|STResList69],
+
+
+ ?line {STRes70,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN011.xsd','./msxsdtest/wildCards',valid),
+ STResList71 = [STRes70|STResList70],
+
+
+ ?line {STRes71,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN012.xsd','./msxsdtest/wildCards',invalid),
+ STResList72 = [STRes71|STResList71],
+
+
+ ?line {STRes72,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN013.xsd','./msxsdtest/wildCards',invalid),
+ STResList73 = [STRes72|STResList72],
+
+
+ ?line {STRes73,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN014.xsd','./msxsdtest/wildCards',invalid),
+ STResList74 = [STRes73|STResList73],
+
+
+ ?line {STRes74,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN015.xsd','./msxsdtest/wildCards',invalid),
+ STResList75 = [STRes74|STResList74],
+
+
+ ?line {STRes75,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN016.xsd','./msxsdtest/wildCards',invalid),
+ STResList76 = [STRes75|STResList75],
+
+
+ ?line {STRes76,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN017.xsd','./msxsdtest/wildCards',valid),
+ STResList77 = [STRes76|STResList76],
+
+
+ ?line {STRes77,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN018.xsd','./msxsdtest/wildCards',invalid),
+ STResList78 = [STRes77|STResList77],
+
+
+ ?line {STRes78,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN019.xsd','./msxsdtest/wildCards',valid),
+ STResList79 = [STRes78|STResList78],
+
+
+ ?line {STRes79,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildN020.xsd','./msxsdtest/wildCards',valid),
+ STResList80 = [STRes79|STResList79],
+
+
+ ?line {STRes80,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildQ001.xsd','./msxsdtest/wildCards',invalid),
+ STResList81 = [STRes80|STResList80],
+
+
+ ?line {STRes81,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildQ002.xsd','./msxsdtest/wildCards',invalid),
+ STResList82 = [STRes81|STResList81],
+
+
+ ?line {STRes82,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildQ003.xsd','./msxsdtest/wildCards',invalid),
+ STResList83 = [STRes82|STResList82],
+
+
+ ?line {STRes83,_} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildQ004.xsd','./msxsdtest/wildCards',invalid),
+ STResList84 = [STRes83|STResList83],
+
+
+ ?line {STRes84,S84} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO001.xsd','./msxsdtest/wildCards',valid),
+ STResList85 = [STRes84|STResList84],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO001.xml','./msxsdtest/wildCards',valid,S84),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes85,S85} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO002.xsd','./msxsdtest/wildCards',valid),
+ STResList86 = [STRes85|STResList85],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO002.xml','./msxsdtest/wildCards',valid,S85),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes86,S86} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO003.xsd','./msxsdtest/wildCards',valid),
+ STResList87 = [STRes86|STResList86],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO003.xml','./msxsdtest/wildCards',invalid,S86),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes87,S87} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO004.xsd','./msxsdtest/wildCards',valid),
+ STResList88 = [STRes87|STResList87],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO004.xml','./msxsdtest/wildCards',valid,S87),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes88,S88} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO005.xsd','./msxsdtest/wildCards',valid),
+ STResList89 = [STRes88|STResList88],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO005.xml','./msxsdtest/wildCards',valid,S88),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes89,S89} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO006.xsd','./msxsdtest/wildCards',valid),
+ STResList90 = [STRes89|STResList89],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO006.xml','./msxsdtest/wildCards',invalid,S89),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes90,S90} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO007.xsd','./msxsdtest/wildCards',valid),
+ STResList91 = [STRes90|STResList90],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO007.xml','./msxsdtest/wildCards',valid,S90),
+ ITResList7 = [ITRes6|ITResList6],
+
+
+ ?line {STRes91,S91} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO008.xsd','./msxsdtest/wildCards',valid),
+ STResList92 = [STRes91|STResList91],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO008.xml','./msxsdtest/wildCards',invalid,S91),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ ?line {STRes92,S92} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO009.xsd','./msxsdtest/wildCards',valid),
+ STResList93 = [STRes92|STResList92],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO009.xml','./msxsdtest/wildCards',invalid,S92),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes93,S93} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO010.xsd','./msxsdtest/wildCards',valid),
+ STResList94 = [STRes93|STResList93],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO010.xml','./msxsdtest/wildCards',valid,S93),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes94,S94} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO011.xsd','./msxsdtest/wildCards',valid),
+ STResList95 = [STRes94|STResList94],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO011.xml','./msxsdtest/wildCards',invalid,S94),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes95,S95} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO012.xsd','./msxsdtest/wildCards',valid),
+ STResList96 = [STRes95|STResList95],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO012.xml','./msxsdtest/wildCards',valid,S95),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ ?line {STRes96,S96} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO013.xsd','./msxsdtest/wildCards',valid),
+ STResList97 = [STRes96|STResList96],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO013.xml','./msxsdtest/wildCards',valid,S96),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes97,S97} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO014.xsd','./msxsdtest/wildCards',valid),
+ STResList98 = [STRes97|STResList97],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO014.xml','./msxsdtest/wildCards',invalid,S97),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ ?line {STRes98,S98} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO015.xsd','./msxsdtest/wildCards',valid),
+ STResList99 = [STRes98|STResList98],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO015.xml','./msxsdtest/wildCards',valid,S98),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes99,S99} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO016.xsd','./msxsdtest/wildCards',valid),
+ STResList100 = [STRes99|STResList99],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO016.xml','./msxsdtest/wildCards',valid,S99),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes100,S100} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO017.xsd','./msxsdtest/wildCards',valid),
+ STResList101 = [STRes100|STResList100],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO017.xml','./msxsdtest/wildCards',invalid,S100),
+ ITResList17 = [ITRes16|ITResList16],
+
+
+ ?line {STRes101,S101} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO018.xsd','./msxsdtest/wildCards',valid),
+ STResList102 = [STRes101|STResList101],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO018.xml','./msxsdtest/wildCards',valid,S101),
+ ITResList18 = [ITRes17|ITResList17],
+
+
+ ?line {STRes102,S102} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO019.xsd','./msxsdtest/wildCards',valid),
+ STResList103 = [STRes102|STResList102],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO019.xml','./msxsdtest/wildCards',valid,S102),
+ ITResList19 = [ITRes18|ITResList18],
+
+
+ ?line {STRes103,S103} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO020.xsd','./msxsdtest/wildCards',valid),
+ STResList104 = [STRes103|STResList103],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO020.xml','./msxsdtest/wildCards',invalid,S103),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes104,S104} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO021.xsd','./msxsdtest/wildCards',valid),
+ STResList105 = [STRes104|STResList104],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO021.xml','./msxsdtest/wildCards',valid,S104),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes105,S105} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO022.xsd','./msxsdtest/wildCards',valid),
+ STResList106 = [STRes105|STResList105],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO022.xml','./msxsdtest/wildCards',invalid,S105),
+ ITResList22 = [ITRes21|ITResList21],
+
+
+ ?line {STRes106,S106} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO023.xsd','./msxsdtest/wildCards',valid),
+ STResList107 = [STRes106|STResList106],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO023.xml','./msxsdtest/wildCards',valid,S106),
+ ITResList23 = [ITRes22|ITResList22],
+
+
+ ?line {STRes107,S107} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO024.xsd','./msxsdtest/wildCards',valid),
+ STResList108 = [STRes107|STResList107],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO024.xml','./msxsdtest/wildCards',invalid,S107),
+ ITResList24 = [ITRes23|ITResList23],
+
+
+ ?line {STRes108,S108} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO025.xsd','./msxsdtest/wildCards',valid),
+ STResList109 = [STRes108|STResList108],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO025.xml','./msxsdtest/wildCards',invalid,S108),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes109,S109} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO026.xsd','./msxsdtest/wildCards',valid),
+ STResList110 = [STRes109|STResList109],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO026.xml','./msxsdtest/wildCards',valid,S109),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes110,S110} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO027.xsd','./msxsdtest/wildCards',valid),
+ STResList111 = [STRes110|STResList110],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO027.xml','./msxsdtest/wildCards',valid,S110),
+ ITResList27 = [ITRes26|ITResList26],
+
+
+ ?line {STRes111,S111} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO028.xsd','./msxsdtest/wildCards',valid),
+ STResList112 = [STRes111|STResList111],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO028.xml','./msxsdtest/wildCards',invalid,S111),
+ ITResList28 = [ITRes27|ITResList27],
+
+
+ ?line {STRes112,S112} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO029.xsd','./msxsdtest/wildCards',valid),
+ STResList113 = [STRes112|STResList112],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO029.xml','./msxsdtest/wildCards',valid,S112),
+ ITResList29 = [ITRes28|ITResList28],
+
+
+ ?line {STRes113,S113} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO030.xsd','./msxsdtest/wildCards',valid),
+ STResList114 = [STRes113|STResList113],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO030.xml','./msxsdtest/wildCards',invalid,S113),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes114,S114} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO031.xsd','./msxsdtest/wildCards',valid),
+ STResList115 = [STRes114|STResList114],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO031.xml','./msxsdtest/wildCards',valid,S114),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes115,S115} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO032.xsd','./msxsdtest/wildCards',valid),
+ STResList116 = [STRes115|STResList115],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO032.xml','./msxsdtest/wildCards',invalid,S115),
+ ITResList32 = [ITRes31|ITResList31],
+
+
+ ?line {STRes116,S116} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO033.xsd','./msxsdtest/wildCards',valid),
+ STResList117 = [STRes116|STResList116],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO033.xml','./msxsdtest/wildCards',valid,S116),
+ ITResList33 = [ITRes32|ITResList32],
+
+
+ ?line {STRes117,S117} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO034.xsd','./msxsdtest/wildCards',valid),
+ STResList118 = [STRes117|STResList117],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO034.xml','./msxsdtest/wildCards',invalid,S117),
+ ITResList34 = [ITRes33|ITResList33],
+
+
+ ?line {STRes118,S118} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO035.xsd','./msxsdtest/wildCards',valid),
+ STResList119 = [STRes118|STResList118],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO035.xml','./msxsdtest/wildCards',invalid,S118),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes119,S119} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO037.xsd','./msxsdtest/wildCards',valid),
+ STResList120 = [STRes119|STResList119],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO037.xml','./msxsdtest/wildCards',valid,S119),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes120,S120} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO038.xsd','./msxsdtest/wildCards',valid),
+ STResList121 = [STRes120|STResList120],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO038.xml','./msxsdtest/wildCards',valid,S120),
+ ITResList37 = [ITRes36|ITResList36],
+
+
+ ?line {STRes121,S121} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO039.xsd','./msxsdtest/wildCards',valid),
+ STResList122 = [STRes121|STResList121],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO039.xml','./msxsdtest/wildCards',invalid,S121),
+ ITResList38 = [ITRes37|ITResList37],
+
+
+ ?line {STRes122,S122} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildO040.xsd','./msxsdtest/wildCards',valid),
+ STResList123 = [STRes122|STResList122],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildO040.xml','./msxsdtest/wildCards',valid,S122),
+ ITResList39 = [ITRes38|ITResList38],
+
+
+ ?line {STRes123,S123} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildP001.xsd','./msxsdtest/wildCards',valid),
+ STResList124 = [STRes123|STResList123],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildP001.xml','./msxsdtest/wildCards',valid,S123),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes124,S124} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildP002.xsd','./msxsdtest/wildCards',valid),
+ STResList125 = [STRes124|STResList124],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildP002.xml','./msxsdtest/wildCards',invalid,S124),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes125,S125} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildP003.xsd','./msxsdtest/wildCards',valid),
+ STResList126 = [STRes125|STResList125],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildP003.xml','./msxsdtest/wildCards',valid,S125),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes126,S126} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildP004.xsd','./msxsdtest/wildCards',valid),
+ STResList127 = [STRes126|STResList126],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildP004.xml','./msxsdtest/wildCards',valid,S126),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes127,S127} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildP005.xsd','./msxsdtest/wildCards',valid),
+ STResList128 = [STRes127|STResList127],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildP005.xml','./msxsdtest/wildCards',valid,S127),
+ ITResList44 = [ITRes43|ITResList43],
+
+
+ ?line {STRes128,S128} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildP006.xsd','./msxsdtest/wildCards',valid),
+ STResList129 = [STRes128|STResList128],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildP006.xml','./msxsdtest/wildCards',valid,S128),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList129,ITResList45).
+
+%% Bugs - Wildcards.
+
+wildZ(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./msxsdtest/wildCards/wildZ001.xsd','./msxsdtest/wildCards',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./msxsdtest/wildCards/wildZ001.xml','./msxsdtest/wildCards',invalid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList1).
+
diff --git a/lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE_data/msx_failed_cases.log b/lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE_data/msx_failed_cases.log
new file mode 100644
index 0000000000..a89a9a798c
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE_data/msx_failed_cases.log
@@ -0,0 +1,2234 @@
+{att,{["attgD041.xsd",
+ "attgD039.xsd",
+ "attgD038.xsd",
+ "attgD037.xsd",
+ "attgD017.xsd",
+ "attgD015.xsd",
+ "attgD012.xsd",
+ "attgD009.xsd",
+ "attgD008.xsd",
+ "attgD007.xsd",
+ "attgD006.xsd",
+ "attgD002.xsd",
+ "attgC044.xsd",
+ "attgC033.xsd",
+ "attgC028.xsd",
+ "attgC027.xsd",
+ "attgC026.xsd",
+ "attgC025.xsd",
+ "attgC024.xsd",
+ "attgC023.xsd",
+ "attgC020.xsd",
+ "attgC010.xsd",
+ "attgC001.xsd",
+ "attgB006.xsd",
+ "attgB003.xsd",
+ "attgB002.xsd",
+ "attgA009.xsd",
+ "attgA008.xsd",
+ "attgA007.xsd",
+ "attgA006.xsd",
+ "attgA005.xsd",
+ "attgA004.xsd",
+ "attgA003.xsd",
+ "attgA002.xsd",
+ "attZ003.xsd",
+ "attQ013.xsd",
+ "attQ012.xsd",
+ "attQ011.xsd",
+ "attQ009.xsd",
+ "attQ008.xsd",
+ "attQ007.xsd",
+ "attQ006.xsd",
+ "attQ004.xsd",
+ "attQ002.xsd",
+ "attQ001.xsd",
+ "attP030.xsd",
+ "attP006.xsd",
+ "attP002.xsd",
+ "attP001.xsd",
+ "attO024.xsd",
+ "attO023.xsd",
+ "attO022.xsd",
+ "attO021.xsd",
+ "attO020.xsd",
+ "attO019.xsd",
+ "attO017.xsd",
+ "attO016.xsd",
+ "attO015.xsd",
+ "attO014.xsd",
+ "attO013.xsd",
+ "attO005.xsd",
+ "attO003.xsd",
+ "attO002.xsd",
+ "attKc018.xsd",
+ "attKc017.xsd",
+ "attKc016.xsd",
+ "attKc015.xsd",
+ "attKc014.xsd",
+ "attKc013.xsd",
+ "attKc012.xsd",
+ "attKc011.xsd",
+ "attKc010.xsd",
+ "attKc005.xsd",
+ "attKc004.xsd",
+ "attKc001.xsd",
+ "attKb018.xsd",
+ "attKb017.xsd",
+ "attKb016.xsd",
+ "attKb015.xsd",
+ "attKb014.xsd",
+ "attKb013.xsd",
+ "attKb012.xsd",
+ "attKb011.xsd",
+ "attKb010.xsd",
+ "attKb005.xsd",
+ "attKb004.xsd",
+ "attKb001.xsd",
+ "attKa015.xsd",
+ "attKa011.xsd",
+ "attKa009.xsd",
+ "attKa008.xsd",
+ "attKa007.xsd",
+ "attKa005.xsd",
+ "attKa004.xsd",
+ "attKa003.xsd",
+ "attI005.xsd",
+ "attI004.xsd",
+ "attH001.xsd",
+ "attE006.xsd",
+ "attC010.xsd",
+ "attC009.xsd",
+ "attC008.xsd",
+ "attC007.xsd",
+ "attC006.xsd",
+ "attC005.xsd",
+ "attA002.xsd",
+ "attA001.xsd",
+ "attgD036.xml",
+ "attgD034.xml",
+ "attgD033.xml",
+ "attgD031.xml",
+ "attgD029.xml",
+ "attgD027.xml",
+ "attgD026.xml",
+ "attgD024.xml",
+ "attgD022.xml",
+ "attgC038.xml",
+ "attgC037.xml",
+ "attgC036.xml",
+ "attgC035.xml",
+ "attgC026.xml",
+ "attgC024.xml",
+ "attgC007.xml",
+ "attZ002.xml",
+ "attZ001.xml",
+ "attP031.xml",
+ "attP020.xml",
+ "attP018.xml",
+ "attP016.xml",
+ "attP014.xml",
+ "attP012.xml",
+ "attP010.xml",
+ "attP009.xml",
+ "attP005.xml",
+ "attO012.xml",
+ "attO008.xml",
+ "attO006.xml",
+ "attMc012.xml",
+ "attMc011.xml",
+ "attMc010.xml",
+ "attMc003.xml",
+ "attMc002.xml",
+ "attMc001.xml",
+ "attMb012.xml",
+ "attMb011.xml",
+ "attMb010.xml",
+ "attMb003.xml",
+ "attMb002.xml",
+ "attMb001.xml",
+ "attMa002.xml",
+ "attMa001.xml",
+ "attLc005.xml",
+ "attLb005.xml",
+ "attLa005.xml",
+ "attJ008.xml",
+ "attJ003.xml",
+ "attJ002.xml",
+ "attF001.xml",
+ "attD007.xml",
+ "attD004.xml"],[]}}.
+{ct,{["ctO004.xsd",
+ "ctO002.xsd",
+ "ctN002.xsd",
+ "ctM004.xsd",
+ "ctM003.xsd",
+ "ctM001.xsd",
+ "ctJ003.xsd",
+ "ctJ002.xsd",
+ "ctI024.xsd",
+ "ctI020.xsd",
+ "ctI017.xsd",
+ "ctI016.xsd",
+ "ctI013.xsd",
+ "ctI012.xsd",
+ "ctI011.xsd",
+ "ctI008.xsd",
+ "ctI007.xsd",
+ "ctI006.xsd",
+ "ctH081.xsd",
+ "ctH078.xsd",
+ "ctH077.xsd",
+ "ctH076.xsd",
+ "ctH075.xsd",
+ "ctH074.xsd",
+ "ctH073.xsd",
+ "ctH072.xsd",
+ "ctH069.xsd",
+ "ctH068.xsd",
+ "ctH067.xsd",
+ "ctH066.xsd",
+ "ctH060.xsd",
+ "ctH059.xsd",
+ "ctH057.xsd",
+ "ctH056.xsd",
+ "ctH054.xsd",
+ "ctH053.xsd",
+ "ctH052.xsd",
+ "ctH051.xsd",
+ "ctH050.xsd",
+ "ctH048.xsd",
+ "ctH046.xsd",
+ "ctH045.xsd",
+ "ctH042.xsd",
+ "ctH041.xsd",
+ "ctH040.xsd",
+ "ctH039.xsd",
+ "ctH038.xsd",
+ "ctH036.xsd",
+ "ctH034.xsd",
+ "ctH033.xsd",
+ "ctH030.xsd",
+ "ctH029.xsd",
+ "ctH028.xsd",
+ "ctH027.xsd",
+ "ctH026.xsd",
+ "ctH024.xsd",
+ "ctH022.xsd",
+ "ctH021.xsd",
+ "ctH018.xsd",
+ "ctH017.xsd",
+ "ctH016.xsd",
+ "ctH015.xsd",
+ "ctH014.xsd",
+ "ctH012.xsd",
+ "ctH010.xsd",
+ "ctH009.xsd",
+ "ctH006.xsd",
+ "ctH005.xsd",
+ "ctH004.xsd",
+ "ctH003.xsd",
+ "ctH002.xsd",
+ "ctG076.xsd",
+ "ctG075.xsd",
+ "ctG071.xsd",
+ "ctG069.xsd",
+ "ctG068.xsd",
+ "ctG067.xsd",
+ "ctG066.xsd",
+ "ctG060.xsd",
+ "ctG058.xsd",
+ "ctG057.xsd",
+ "ctG056.xsd",
+ "ctG055.xsd",
+ "ctG054.xsd",
+ "ctG053.xsd",
+ "ctG049.xsd",
+ "ctG046.xsd",
+ "ctG045.xsd",
+ "ctG038.xsd",
+ "ctG034.xsd",
+ "ctG033.xsd",
+ "ctG026.xsd",
+ "ctG023.xsd",
+ "ctG022.xsd",
+ "ctG021.xsd",
+ "ctG020.xsd",
+ "ctG019.xsd",
+ "ctG013.xsd",
+ "ctG011.xsd",
+ "ctG010.xsd",
+ "ctG009.xsd",
+ "ctG008.xsd",
+ "ctG007.xsd",
+ "ctG001.xsd",
+ "ctF013.xsd",
+ "ctF009.xsd",
+ "ctF008.xsd",
+ "ctF007.xsd",
+ "ctF005.xsd",
+ "ctF004.xsd",
+ "ctF003.xsd",
+ "ctF002.xsd",
+ "ctE016.xsd",
+ "ctE015.xsd",
+ "ctE014.xsd",
+ "ctE013.xsd",
+ "ctE012.xsd",
+ "ctE011.xsd",
+ "ctE009.xsd",
+ "ctE005.xsd",
+ "ctE003.xsd",
+ "ctD043.xsd",
+ "ctD042.xsd",
+ "ctD041.xsd",
+ "ctD040.xsd",
+ "ctD032.xsd",
+ "ctD031.xsd",
+ "ctD011.xsd",
+ "ctD007.xsd",
+ "ctD004.xsd",
+ "ctD001.xsd",
+ "ctC005.xsd",
+ "ctC004.xsd",
+ "ctC003.xsd",
+ "ctC002.xsd",
+ "ctB125.xsd",
+ "ctB124.xsd",
+ "ctB123.xsd",
+ "ctB122.xsd",
+ "ctB121.xsd",
+ "ctB120.xsd",
+ "ctB119.xsd",
+ "ctB118.xsd",
+ "ctB117.xsd",
+ "ctB116.xsd",
+ "ctB115.xsd",
+ "ctB114.xsd",
+ "ctB112.xsd",
+ "ctB107.xsd",
+ "ctB106.xsd",
+ "ctB105.xsd",
+ "ctB104.xsd",
+ "ctB102.xsd",
+ "ctB101.xsd",
+ "ctB099.xsd",
+ "ctB094.xsd",
+ "ctB093.xsd",
+ "ctB092.xsd",
+ "ctB091.xsd",
+ "ctB090.xsd",
+ "ctB089.xsd",
+ "ctB088.xsd",
+ "ctB086.xsd",
+ "ctB080.xsd",
+ "ctB079.xsd",
+ "ctB078.xsd",
+ "ctB077.xsd",
+ "ctB076.xsd",
+ "ctB075.xsd",
+ "ctB074.xsd",
+ "ctB072.xsd",
+ "ctB066.xsd",
+ "ctB065.xsd",
+ "ctB064.xsd",
+ "ctB063.xsd",
+ "ctB062.xsd",
+ "ctB061.xsd",
+ "ctB060.xsd",
+ "ctB058.xsd",
+ "ctB052.xsd",
+ "ctB051.xsd",
+ "ctB050.xsd",
+ "ctB049.xsd",
+ "ctB048.xsd",
+ "ctB047.xsd",
+ "ctB046.xsd",
+ "ctB044.xsd",
+ "ctB038.xsd",
+ "ctB037.xsd",
+ "ctB036.xsd",
+ "ctB035.xsd",
+ "ctB034.xsd",
+ "ctB033.xsd",
+ "ctB032.xsd",
+ "ctB030.xsd",
+ "ctB029.xsd",
+ "ctB026.xsd",
+ "ctB025.xsd",
+ "ctB024.xsd",
+ "ctB023.xsd",
+ "ctB022.xsd",
+ "ctB021.xsd",
+ "ctB020.xsd",
+ "ctB019.xsd",
+ "ctB018.xsd",
+ "ctB016.xsd",
+ "ctB015.xsd",
+ "ctB014.xsd",
+ "ctB013.xsd",
+ "ctB012.xsd",
+ "ctB011.xsd",
+ "ctB010.xsd",
+ "ctB009.xsd",
+ "ctB008.xsd",
+ "ctB007.xsd",
+ "ctB005.xsd",
+ "ctB004.xsd",
+ "ctB002.xsd",
+ "ctA046.xsd",
+ "ctA044.xsd",
+ "ctA043.xsd",
+ "ctA042.xsd",
+ "ctA031.xsd",
+ "ctA030.xsd",
+ "ctA029.xsd",
+ "ctA028.xsd",
+ "ctA024.xsd",
+ "ctA023.xsd",
+ "ctA015.xsd",
+ "ctA014.xsd",
+ "ctO006.xml",
+ "ctL021.xml",
+ "ctL018.xml",
+ "ctL016.xml",
+ "ctL005.xml",
+ "ctJ001.xml",
+ "ctI049.xml",
+ "ctI048.xml",
+ "ctI045.xml",
+ "ctI042.xml",
+ "ctI041.xml",
+ "ctI040.xml",
+ "ctI035.xml",
+ "ctI032.xml",
+ "ctI031.xml",
+ "ctI030.xml",
+ "ctH082.xml",
+ "ctH069.xml",
+ "ctH068.xml",
+ "ctH067.xml",
+ "ctH066.xml",
+ "ctH060.xml",
+ "ctH057.xml",
+ "ctH056.xml",
+ "ctH046.xml",
+ "ctH045.xml",
+ "ctH035.xml",
+ "ctH034.xml",
+ "ctH033.xml",
+ "ctH032.xml",
+ "ctH031.xml",
+ "ctH025.xml",
+ "ctH023.xml",
+ "ctH022.xml",
+ "ctH021.xml",
+ "ctH020.xml",
+ "ctH019.xml",
+ "ctH013.xml",
+ "ctH011.xml",
+ "ctH010.xml",
+ "ctH009.xml",
+ "ctH008.xml",
+ "ctH007.xml",
+ "ctH001.xml",
+ "ctG071.xml",
+ "ctG069.xml",
+ "ctG068.xml",
+ "ctG067.xml",
+ "ctG066.xml",
+ "ctG060.xml",
+ "ctG058.xml",
+ "ctG057.xml",
+ "ctG056.xml",
+ "ctG055.xml",
+ "ctG049.xml",
+ "ctG047.xml",
+ "ctG046.xml",
+ "ctG045.xml",
+ "ctG035.xml",
+ "ctG034.xml",
+ "ctG033.xml",
+ "ctG023.xml",
+ "ctG022.xml",
+ "ctG021.xml",
+ "ctG020.xml",
+ "ctG019.xml",
+ "ctG013.xml",
+ "ctG011.xml",
+ "ctG010.xml",
+ "ctG009.xml",
+ "ctG008.xml",
+ "ctG007.xml",
+ "ctG001.xml",
+ "ctF014.xml",
+ "ctF013.xml",
+ "ctF011.xml",
+ "ctF007.xml",
+ "ctF006.xml",
+ "ctD032.xml",
+ "ctD031.xml"],[]}}.
+{elem,{["elemT015.xsd",
+ "elemT014.xsd",
+ "elemT013.xsd",
+ "elemT012.xsd",
+ "elemT011.xsd",
+ "elemS006.xsd",
+ "elemS005.xsd",
+ "elemS004.xsd",
+ "elemS001.xsd",
+ "elemQ006.xsd",
+ "elemQ004.xsd",
+ "elemP006.xsd",
+ "elemN006.xsd",
+ "elemL003.xsd",
+ "elemK007.xsd",
+ "elemJ020.xsd",
+ "elemJ019.xsd",
+ "elemJ015.xsd",
+ "elemJ012.xsd",
+ "elemJ007.xsd",
+ "elemH006.xsd",
+ "elemH005.xsd",
+ "elemH004.xsd",
+ "elemH003.xsd",
+ "elemG004.xsd",
+ "elemG003.xsd",
+ "elemE006.xsd",
+ "elemD005.xsd",
+ "elemD004.xsd",
+ "elemA014.xsd",
+ "elemA013.xsd",
+ "elemA011.xsd",
+ "elemA010.xsd",
+ "elemA009.xsd",
+ "elemA006.xsd",
+ "elemZ001.xml",
+ "elemZ002.xml",
+ "elemU007.xml",
+ "elemU006.xml",
+ "elemU005.xml",
+ "elemU003.xml",
+ "elemT058.xml",
+ "elemT044.xml",
+ "elemT043.xml",
+ "elemT042.xml",
+ "elemT041.xml",
+ "elemT040.xml",
+ "elemT039.xml",
+ "elemT029.xml",
+ "elemT028.xml",
+ "elemT027.xml",
+ "elemT026.xml",
+ "elemT024.xml",
+ "elemT022.xml",
+ "elemT018.xml",
+ "elemT015.xml",
+ "elemT014.xml",
+ "elemT004.xml",
+ "elemT001.xml",
+ "elemQ022.xml",
+ "elemQ019.xml",
+ "elemQ018.xml",
+ "elemO011.xml",
+ "elemO006.xml"],[]}}.
+{group,{["groupO027.xsd",
+ "groupO025.xsd",
+ "groupO024.xsd",
+ "groupO023.xsd",
+ "groupO022.xsd",
+ "groupO021.xsd",
+ "groupO020.xsd",
+ "groupO019.xsd",
+ "groupO018.xsd",
+ "groupO017.xsd",
+ "groupO016.xsd",
+ "groupO015.xsd",
+ "groupO013.xsd",
+ "groupO012.xsd",
+ "groupO011.xsd",
+ "groupO010.xsd",
+ "groupO003.xsd",
+ "groupO002.xsd",
+ "groupN025.xsd",
+ "groupN024.xsd",
+ "groupN023.xsd",
+ "groupN022.xsd",
+ "groupM002.xsd",
+ "groupL025.xsd",
+ "groupL024.xsd",
+ "groupL023.xsd",
+ "groupL022.xsd",
+ "groupK002.xsd",
+ "groupJ025.xsd",
+ "groupJ024.xsd",
+ "groupJ023.xsd",
+ "groupJ022.xsd",
+ "groupI003.xsd",
+ "groupI002.xsd",
+ "groupH019.xsd",
+ "groupH018.xsd",
+ "groupH016.xsd",
+ "groupH015.xsd",
+ "groupH014.xsd",
+ "groupH013.xsd",
+ "groupH012.xsd",
+ "groupH011.xsd",
+ "groupH010.xsd",
+ "groupH009.xsd",
+ "groupH008.xsd",
+ "groupH006.xsd",
+ "groupH005.xsd",
+ "groupH004.xsd",
+ "groupH003.xsd",
+ "groupH002.xsd",
+ "groupH001.xsd",
+ "groupG005.xsd",
+ "groupG004.xsd",
+ "groupG003.xsd",
+ "groupG001.xsd",
+ "groupF025.xsd",
+ "groupF024.xsd",
+ "groupF023.xsd",
+ "groupF022.xsd",
+ "groupE002.xsd",
+ "groupD003.xsd",
+ "groupD001.xsd",
+ "groupC010.xsd",
+ "groupC008.xsd",
+ "groupC007.xsd",
+ "groupC006.xsd",
+ "groupC004.xsd",
+ "groupB017.xsd",
+ "groupB015.xsd",
+ "groupB014.xsd",
+ "groupB013.xsd",
+ "groupB012.xsd",
+ "groupB002.xsd",
+ "groupB001.xsd",
+ "groupA012.xsd",
+ "groupA010.xsd",
+ "groupA009.xsd",
+ "groupA007.xsd",
+ "groupA006.xsd",
+ "groupA005.xsd",
+ "groupA004.xsd",
+ "groupA003.xsd",
+ "groupO009.xml",
+ "groupO007.xml",
+ "groupO004.xml",
+ "groupN019.xml",
+ "groupN015.xml",
+ "groupN012.xml",
+ "groupN008.xml",
+ "groupN007.xml",
+ "groupN006.xml",
+ "groupN003.xml",
+ "groupM005.xml",
+ "groupL019.xml",
+ "groupL015.xml",
+ "groupL012.xml",
+ "groupL008.xml",
+ "groupL007.xml",
+ "groupL006.xml",
+ "groupL003.xml",
+ "groupK005.xml",
+ "groupJ019.xml",
+ "groupJ015.xml",
+ "groupJ012.xml",
+ "groupJ008.xml",
+ "groupJ007.xml",
+ "groupJ006.xml",
+ "groupJ003.xml",
+ "groupI005.xml",
+ "groupH018.xml",
+ "groupH014.xml",
+ "groupH011.xml",
+ "groupH009.xml",
+ "groupH007.xml",
+ "groupH005.xml",
+ "groupH004.xml",
+ "groupH002.xml",
+ "groupH001.xml",
+ "groupG004.xml",
+ "groupF021.xml",
+ "groupF018.xml",
+ "groupF017.xml",
+ "groupF016.xml",
+ "groupF014.xml",
+ "groupF013.xml",
+ "groupF011.xml",
+ "groupF010.xml",
+ "groupF009.xml",
+ "groupF005.xml",
+ "groupF002.xml",
+ "groupE004.xml",
+ "groupE003.xml",
+ "groupB010.xml",
+ "groupB009.xml",
+ "groupB002.xml"],[]}}.
+{idc_,{["idc_gMonth_gMonth.xml",
+ "idc_gDay_gDay.xml",
+ "idc_gMonthDay_gMonthDay.xml",
+ "idc_gYear_gYear.xml",
+ "idc_gYearMonth_gYearMonth.xml",
+ "idc_date_date.xml",
+ "idc_time_time.xml",
+ "idc_dateTime_dateTime.xml",
+ "idc_duration_duration.xml",
+ "idc_NOTATION_NOTATION.xml",
+ "idc_QName_QName.xml",
+ "idc_anyURI_anyURI.xml",
+ "idc_double_double.xml",
+ "idc_unsignedByte_unsignedByte.xml",
+ "idc_unsignedByte_unsignedShort.xml",
+ "idc_unsignedByte_unsignedInt.xml",
+ "idc_unsignedByte_unsignedLong.xml",
+ "idc_unsignedByte_integer.xml",
+ "idc_unsignedByte_decimal.xml",
+ "idc_unsignedShort_unsignedByte.xml",
+ "idc_unsignedShort_unsignedShort.xml",
+ "idc_unsignedShort_unsignedInt.xml",
+ "idc_unsignedShort_unsignedLong.xml",
+ "idc_unsignedShort_integer.xml",
+ "idc_unsignedShort_decimal.xml",
+ "idc_unsignedInt_unsignedByte.xml",
+ "idc_unsignedInt_unsignedShort.xml",
+ "idc_unsignedInt_unsignedInt.xml",
+ "idc_unsignedInt_unsignedLong.xml",
+ "idc_unsignedInt_integer.xml",
+ "idc_unsignedInt_decimal.xml",
+ "idc_unsignedLong_unsignedByte.xml",
+ "idc_unsignedLong_unsignedShort.xml",
+ "idc_unsignedLong_unsignedInt.xml",
+ "idc_unsignedLong_unsignedLong.xml",
+ "idc_unsignedLong_integer.xml",
+ "idc_unsignedLong_decimal.xml",
+ "idc_positiveInteger_integer.xml",
+ "idc_positiveInteger_decimal.xml",
+ "idc_nonNegativeInteger_integer.xml",
+ "idc_nonNegativeInteger_decimal.xml",
+ "idc_byte_byte.xml",
+ "idc_byte_short.xml",
+ "idc_byte_int.xml",
+ "idc_byte_long.xml",
+ "idc_byte_integer.xml",
+ "idc_byte_decimal.xml",
+ "idc_short_byte.xml",
+ "idc_short_short.xml",
+ "idc_short_int.xml",
+ "idc_short_long.xml",
+ "idc_short_integer.xml",
+ "idc_short_decimal.xml",
+ "idc_int_byte.xml",
+ "idc_int_short.xml",
+ "idc_int_int.xml",
+ "idc_int_long.xml",
+ "idc_int_integer.xml",
+ "idc_int_decimal.xml",
+ "idc_long_byte.xml",
+ "idc_long_short.xml",
+ "idc_long_int.xml",
+ "idc_long_long.xml",
+ "idc_long_integer.xml",
+ "idc_long_decimal.xml",
+ "idc_negativeInteger_integer.xml",
+ "idc_negativeInteger_decimal.xml",
+ "idc_nonPositiveInteger_integer.xml",
+ "idc_nonPositiveInteger_decimal.xml",
+ "idc_integer_unsignedByte.xml",
+ "idc_integer_unsignedShort.xml",
+ "idc_integer_unsignedInt.xml",
+ "idc_integer_unsignedLong.xml",
+ "idc_integer_positiveInteger.xml",
+ "idc_integer_nonNegativeInteger.xml",
+ "idc_integer_byte.xml",
+ "idc_integer_short.xml",
+ "idc_integer_int.xml",
+ "idc_integer_long.xml",
+ "idc_integer_negativeInteger.xml",
+ "idc_integer_nonPositiveInteger.xml",
+ "idc_integer_integer.xml",
+ "idc_integer_decimal.xml",
+ "idc_decimal_unsignedByte.xml",
+ "idc_decimal_unsignedShort.xml",
+ "idc_decimal_unsignedInt.xml",
+ "idc_decimal_unsignedLong.xml",
+ "idc_decimal_positiveInteger.xml",
+ "idc_decimal_nonNegativeInteger.xml",
+ "idc_decimal_byte.xml",
+ "idc_decimal_short.xml",
+ "idc_decimal_int.xml",
+ "idc_decimal_long.xml",
+ "idc_decimal_negativeInteger.xml",
+ "idc_decimal_nonPositiveInteger.xml",
+ "idc_decimal_integer.xml",
+ "idc_decimal_decimal.xml",
+ "idc_float_float.xml",
+ "idc_boolean_boolean.xml",
+ "idc_NMTOKEN_NMTOKEN.xml",
+ "idc_NMTOKEN_token.xml",
+ "idc_NMTOKEN_normalizedString.xml",
+ "idc_NMTOKEN_string.xml",
+ "idc_IDREF_IDREF.xml",
+ "idc_IDREF_NCName.xml",
+ "idc_IDREF_Name.xml",
+ "idc_IDREF_token.xml",
+ "idc_IDREF_normalizedString.xml",
+ "idc_IDREF_string.xml",
+ "idc_ID_NCName.xml",
+ "idc_ID_Name.xml",
+ "idc_ID_token.xml",
+ "idc_ID_normalizedString.xml",
+ "idc_ID_string.xml",
+ "idc_NCName_IDREF.xml",
+ "idc_NCName_ID.xml",
+ "idc_NCName_NCName.xml",
+ "idc_NCName_Name.xml",
+ "idc_NCName_token.xml",
+ "idc_NCName_normalizedString.xml",
+ "idc_NCName_string.xml",
+ "idc_Name_IDREF.xml",
+ "idc_Name_ID.xml",
+ "idc_Name_NCName.xml",
+ "idc_Name_Name.xml",
+ "idc_Name_token.xml",
+ "idc_Name_normalizedString.xml",
+ "idc_Name_string.xml",
+ "idc_language_language.xml",
+ "idc_language_token.xml",
+ "idc_language_normalizedString.xml",
+ "idc_language_string.xml",
+ "idc_token_NMTOKEN.xml",
+ "idc_token_IDREF.xml",
+ "idc_token_ID.xml",
+ "idc_token_NCName.xml",
+ "idc_token_Name.xml",
+ "idc_token_language.xml",
+ "idc_token_token.xml",
+ "idc_token_normalizedString.xml",
+ "idc_token_string.xml",
+ "idc_normalizedString_NMTOKEN.xml",
+ "idc_normalizedString_IDREF.xml",
+ "idc_normalizedString_ID.xml",
+ "idc_normalizedString_NCName.xml",
+ "idc_normalizedString_Name.xml",
+ "idc_normalizedString_language.xml",
+ "idc_normalizedString_token.xml",
+ "idc_normalizedString_string.xml",
+ "idc_string_NMTOKEN.xml",
+ "idc_string_IDREF.xml",
+ "idc_string_ID.xml",
+ "idc_string_NCName.xml",
+ "idc_string_Name.xml",
+ "idc_string_language.xml",
+ "idc_string_token.xml",
+ "idc_string_normalizedString.xml",
+ "idc_string_string.xml"],["idc_unsignedByte_nonNegativeInteger.xsd",
+ "idc_unsignedByte_normalizedString.xsd",
+ "idc_unsignedShort_positiveInteger.xsd",
+ "idc_unsignedShort_nonNegativeInteger.xsd",
+ "idc_unsignedShort_normalizedString.xsd",
+ "idc_unsignedInt_nonNegativeInteger.xsd",
+ "idc_unsignedLong_nonNegativeInteger.xsd",
+ "idc_unsignedLong_normalizedString.xsd",
+ "idc_positiveInteger_unsignedShort.xsd",
+ "idc_positiveInteger_positiveInteger.xsd",
+ "idc_positiveInteger_nonNegativeInteger.xsd",
+ "idc_positiveInteger_normalizedString.xsd",
+ "idc_nonNegativeInteger_unsignedByte.xsd",
+ "idc_nonNegativeInteger_unsignedShort.xsd",
+ "idc_nonNegativeInteger_unsignedInt.xsd",
+ "idc_nonNegativeInteger_unsignedLong.xsd",
+ "idc_nonNegativeInteger_positiveInteger.xsd",
+ "idc_nonNegativeInteger_nonNegativeInteger.xsd",
+ "idc_nonNegativeInteger_base64Binary.xsd",
+ "idc_nonNegativeInteger_normalizedString.xsd",
+ "idc_negativeInteger_negativeInteger.xsd",
+ "idc_negativeInteger_nonPositiveInteger.xsd",
+ "idc_negativeInteger_normalizedString.xsd",
+ "idc_nonPositiveInteger_negativeInteger.xsd",
+ "idc_nonPositiveInteger_nonPositiveInteger.xsd",
+ "idc_nonPositiveInteger_normalizedString.xsd",
+ "idc_base64Binary_nonNegativeInteger.xsd",
+ "idc_base64Binary_normalizedString.xsd",
+ "idc_normalizedString_unsignedByte.xsd",
+ "idc_normalizedString_unsignedShort.xsd",
+ "idc_normalizedString_unsignedLong.xsd",
+ "idc_normalizedString_positiveInteger.xsd",
+ "idc_normalizedString_nonNegativeInteger.xsd",
+ "idc_normalizedString_negativeInteger.xsd",
+ "idc_normalizedString_nonPositiveInteger.xsd",
+ "idc_normalizedString_base64Binary.xsd",
+ "idc_normalizedString_normalizedString.xsd",
+ "idc_unsignedByte_nonNegativeInteger.xml",
+ "idc_unsignedByte_normalizedString.xml",
+ "idc_unsignedShort_positiveInteger.xml",
+ "idc_unsignedShort_nonNegativeInteger.xml",
+ "idc_unsignedShort_normalizedString.xml",
+ "idc_unsignedInt_nonNegativeInteger.xml",
+ "idc_unsignedLong_nonNegativeInteger.xml",
+ "idc_unsignedLong_normalizedString.xml",
+ "idc_positiveInteger_unsignedShort.xml",
+ "idc_positiveInteger_positiveInteger.xml",
+ "idc_positiveInteger_nonNegativeInteger.xml",
+ "idc_positiveInteger_normalizedString.xml",
+ "idc_nonNegativeInteger_unsignedByte.xml",
+ "idc_nonNegativeInteger_unsignedShort.xml",
+ "idc_nonNegativeInteger_unsignedInt.xml",
+ "idc_nonNegativeInteger_unsignedLong.xml",
+ "idc_nonNegativeInteger_positiveInteger.xml",
+ "idc_nonNegativeInteger_nonNegativeInteger.xml",
+ "idc_nonNegativeInteger_base64Binary.xml",
+ "idc_nonNegativeInteger_normalizedString.xml",
+ "idc_negativeInteger_negativeInteger.xml",
+ "idc_negativeInteger_nonPositiveInteger.xml",
+ "idc_negativeInteger_normalizedString.xml",
+ "idc_nonPositiveInteger_negativeInteger.xml",
+ "idc_nonPositiveInteger_nonPositiveInteger.xml",
+ "idc_nonPositiveInteger_normalizedString.xml",
+ "idc_base64Binary_nonNegativeInteger.xml",
+ "idc_base64Binary_normalizedString.xml",
+ "idc_normalizedString_unsignedByte.xml",
+ "idc_normalizedString_unsignedShort.xml",
+ "idc_normalizedString_unsignedLong.xml",
+ "idc_normalizedString_positiveInteger.xml",
+ "idc_normalizedString_nonNegativeInteger.xml",
+ "idc_normalizedString_negativeInteger.xml",
+ "idc_normalizedString_nonPositiveInteger.xml",
+ "idc_normalizedString_base64Binary.xml",
+ "idc_normalizedString_normalizedString.xml"]}}.
+{id,{["idK016.xsd",
+ "idK015.xsd",
+ "idJ204.xsd",
+ "idJ203.xsd",
+ "idJ202.xsd",
+ "idJ201.xsd",
+ "idJ200.xsd",
+ "idJ199.xsd",
+ "idJ198.xsd",
+ "idJ197.xsd",
+ "idJ196.xsd",
+ "idJ195.xsd",
+ "idJ194.xsd",
+ "idJ193.xsd",
+ "idJ192.xsd",
+ "idJ191.xsd",
+ "idJ190.xsd",
+ "idJ189.xsd",
+ "idJ188.xsd",
+ "idJ187.xsd",
+ "idJ186.xsd",
+ "idJ185.xsd",
+ "idJ184.xsd",
+ "idJ183.xsd",
+ "idJ182.xsd",
+ "idJ181.xsd",
+ "idJ180.xsd",
+ "idJ179.xsd",
+ "idJ178.xsd",
+ "idJ177.xsd",
+ "idJ176.xsd",
+ "idJ175.xsd",
+ "idJ174.xsd",
+ "idJ173.xsd",
+ "idJ172.xsd",
+ "idJ171.xsd",
+ "idJ170.xsd",
+ "idJ169.xsd",
+ "idJ168.xsd",
+ "idJ167.xsd",
+ "idJ166.xsd",
+ "idJ165.xsd",
+ "idJ164.xsd",
+ "idJ163.xsd",
+ "idJ162.xsd",
+ "idJ161.xsd",
+ "idJ160.xsd",
+ "idJ159.xsd",
+ "idJ158.xsd",
+ "idJ157.xsd",
+ "idJ156.xsd",
+ "idJ155.xsd",
+ "idJ154.xsd",
+ "idJ153.xsd",
+ "idJ152.xsd",
+ "idJ151.xsd",
+ "idJ150.xsd",
+ "idJ149.xsd",
+ "idJ148.xsd",
+ "idJ147.xsd",
+ "idJ146.xsd",
+ "idJ145.xsd",
+ "idJ144.xsd",
+ "idJ143.xsd",
+ "idJ142.xsd",
+ "idJ141.xsd",
+ "idJ140.xsd",
+ "idJ139.xsd",
+ "idJ138.xsd",
+ "idJ137.xsd",
+ "idJ136.xsd",
+ "idJ135.xsd",
+ "idJ134.xsd",
+ "idJ133.xsd",
+ "idJ132.xsd",
+ "idJ131.xsd",
+ "idJ130.xsd",
+ "idJ129.xsd",
+ "idJ128.xsd",
+ "idJ127.xsd",
+ "idJ126.xsd",
+ "idJ125.xsd",
+ "idJ124.xsd",
+ "idJ123.xsd",
+ "idJ122.xsd",
+ "idJ121.xsd",
+ "idJ120.xsd",
+ "idJ119.xsd",
+ "idJ118.xsd",
+ "idJ117.xsd",
+ "idJ116.xsd",
+ "idJ115.xsd",
+ "idJ114.xsd",
+ "idJ113.xsd",
+ "idJ112.xsd",
+ "idJ111.xsd",
+ "idJ110.xsd",
+ "idJ109.xsd",
+ "idJ108.xsd",
+ "idJ107.xsd",
+ "idJ106.xsd",
+ "idJ105.xsd",
+ "idJ104.xsd",
+ "idJ103.xsd",
+ "idJ102.xsd",
+ "idJ101.xsd",
+ "idJ100.xsd",
+ "idJ099.xsd",
+ "idJ098.xsd",
+ "idJ097.xsd",
+ "idJ096.xsd",
+ "idJ095.xsd",
+ "idJ094.xsd",
+ "idJ093.xsd",
+ "idJ092.xsd",
+ "idJ091.xsd",
+ "idJ090.xsd",
+ "idJ089.xsd",
+ "idJ088.xsd",
+ "idJ087.xsd",
+ "idJ086.xsd",
+ "idJ085.xsd",
+ "idJ084.xsd",
+ "idJ083.xsd",
+ "idJ082.xsd",
+ "idJ081.xsd",
+ "idJ080.xsd",
+ "idJ079.xsd",
+ "idJ078.xsd",
+ "idJ077.xsd",
+ "idJ076.xsd",
+ "idJ075.xsd",
+ "idJ074.xsd",
+ "idJ073.xsd",
+ "idJ072.xsd",
+ "idJ071.xsd",
+ "idJ070.xsd",
+ "idJ069.xsd",
+ "idJ068.xsd",
+ "idJ067.xsd",
+ "idJ066.xsd",
+ "idJ065.xsd",
+ "idJ064.xsd",
+ "idJ063.xsd",
+ "idJ062.xsd",
+ "idJ061.xsd",
+ "idJ060.xsd",
+ "idJ059.xsd",
+ "idJ058.xsd",
+ "idJ057.xsd",
+ "idJ055.xsd",
+ "idJ054.xsd",
+ "idJ053.xsd",
+ "idJ051.xsd",
+ "idJ050.xsd",
+ "idJ049.xsd",
+ "idJ048.xsd",
+ "idJ047.xsd",
+ "idJ046.xsd",
+ "idJ045.xsd",
+ "idJ044.xsd",
+ "idJ043.xsd",
+ "idJ042.xsd",
+ "idJ041.xsd",
+ "idJ040.xsd",
+ "idJ039.xsd",
+ "idJ038.xsd",
+ "idJ037.xsd",
+ "idJ035.xsd",
+ "idJ034.xsd",
+ "idJ033.xsd",
+ "idJ031.xsd",
+ "idJ029.xsd",
+ "idJ028.xsd",
+ "idJ027.xsd",
+ "idJ024.xsd",
+ "idJ023.xsd",
+ "idJ022.xsd",
+ "idJ021.xsd",
+ "idJ020.xsd",
+ "idJ019.xsd",
+ "idJ018.xsd",
+ "idJ014.xsd",
+ "idJ013.xsd",
+ "idJ012.xsd",
+ "idJ011.xsd",
+ "idJ010.xsd",
+ "idJ009.xsd",
+ "idJ004.xsd",
+ "idI144.xsd",
+ "idI143.xsd",
+ "idI142.xsd",
+ "idI141.xsd",
+ "idI140.xsd",
+ "idI139.xsd",
+ "idI138.xsd",
+ "idI137.xsd",
+ "idI136.xsd",
+ "idI135.xsd",
+ "idI134.xsd",
+ "idI133.xsd",
+ "idI132.xsd",
+ "idI131.xsd",
+ "idI130.xsd",
+ "idI129.xsd",
+ "idI128.xsd",
+ "idI127.xsd",
+ "idI126.xsd",
+ "idI125.xsd",
+ "idI124.xsd",
+ "idI123.xsd",
+ "idI122.xsd",
+ "idI121.xsd",
+ "idI120.xsd",
+ "idI119.xsd",
+ "idI118.xsd",
+ "idI117.xsd",
+ "idI116.xsd",
+ "idI115.xsd",
+ "idI114.xsd",
+ "idI113.xsd",
+ "idI112.xsd",
+ "idI111.xsd",
+ "idI110.xsd",
+ "idI109.xsd",
+ "idI108.xsd",
+ "idI107.xsd",
+ "idI106.xsd",
+ "idI105.xsd",
+ "idI104.xsd",
+ "idI103.xsd",
+ "idI102.xsd",
+ "idI101.xsd",
+ "idI100.xsd",
+ "idI099.xsd",
+ "idI098.xsd",
+ "idI097.xsd",
+ "idI096.xsd",
+ "idI095.xsd",
+ "idI094.xsd",
+ "idI093.xsd",
+ "idI092.xsd",
+ "idI091.xsd",
+ "idI090.xsd",
+ "idI089.xsd",
+ "idI088.xsd",
+ "idI087.xsd",
+ "idI086.xsd",
+ "idI085.xsd",
+ "idI084.xsd",
+ "idI083.xsd",
+ "idI082.xsd",
+ "idI081.xsd",
+ "idI080.xsd",
+ "idI079.xsd",
+ "idI078.xsd",
+ "idI077.xsd",
+ "idI076.xsd",
+ "idI075.xsd",
+ "idI074.xsd",
+ "idI073.xsd",
+ "idI072.xsd",
+ "idI071.xsd",
+ "idI070.xsd",
+ "idI069.xsd",
+ "idI068.xsd",
+ "idI067.xsd",
+ "idI066.xsd",
+ "idI065.xsd",
+ "idI064.xsd",
+ "idI063.xsd",
+ "idI062.xsd",
+ "idI061.xsd",
+ "idI060.xsd",
+ "idI059.xsd",
+ "idI058.xsd",
+ "idI057.xsd",
+ "idI056.xsd",
+ "idI055.xsd",
+ "idI054.xsd",
+ "idI053.xsd",
+ "idI052.xsd",
+ "idI051.xsd",
+ "idI050.xsd",
+ "idI049.xsd",
+ "idI048.xsd",
+ "idI047.xsd",
+ "idI046.xsd",
+ "idI045.xsd",
+ "idI044.xsd",
+ "idI043.xsd",
+ "idI042.xsd",
+ "idI041.xsd",
+ "idI040.xsd",
+ "idI039.xsd",
+ "idI037.xsd",
+ "idI036.xsd",
+ "idI035.xsd",
+ "idI034.xsd",
+ "idI033.xsd",
+ "idI032.xsd",
+ "idI031.xsd",
+ "idI030.xsd",
+ "idI029.xsd",
+ "idI027.xsd",
+ "idI026.xsd",
+ "idI025.xsd",
+ "idI024.xsd",
+ "idI021.xsd",
+ "idI020.xsd",
+ "idI019.xsd",
+ "idI017.xsd",
+ "idI013.xsd",
+ "idI012.xsd",
+ "idI011.xsd",
+ "idI010.xsd",
+ "idI009.xsd",
+ "idI008.xsd",
+ "idI002.xsd",
+ "idE033.xsd",
+ "idE032.xsd",
+ "idE031.xsd",
+ "idE030.xsd",
+ "idE029.xsd",
+ "idE028.xsd",
+ "idE027.xsd",
+ "idE026.xsd",
+ "idE025.xsd",
+ "idE024.xsd",
+ "idE023.xsd",
+ "idE022.xsd",
+ "idE021.xsd",
+ "idE020.xsd",
+ "idE019.xsd",
+ "idE018.xsd",
+ "idE017.xsd",
+ "idE014.xsd",
+ "idE012.xsd",
+ "idE011.xsd",
+ "idE007.xsd",
+ "idE006.xsd",
+ "idE005.xsd",
+ "idE004.xsd",
+ "idE003.xsd",
+ "idE002.xsd",
+ "idD033.xsd",
+ "idD032.xsd",
+ "idD031.xsd",
+ "idD030.xsd",
+ "idD029.xsd",
+ "idD028.xsd",
+ "idD027.xsd",
+ "idD026.xsd",
+ "idD025.xsd",
+ "idD024.xsd",
+ "idD023.xsd",
+ "idD022.xsd",
+ "idD021.xsd",
+ "idD020.xsd",
+ "idD019.xsd",
+ "idD018.xsd",
+ "idD017.xsd",
+ "idD014.xsd",
+ "idD012.xsd",
+ "idD011.xsd",
+ "idD006.xsd",
+ "idD005.xsd",
+ "idD004.xsd",
+ "idD003.xsd",
+ "idD002.xsd",
+ "idC047.xsd",
+ "idC046.xsd",
+ "idC045.xsd",
+ "idC032.xsd",
+ "idC031.xsd",
+ "idC030.xsd",
+ "idC029.xsd",
+ "idC028.xsd",
+ "idC027.xsd",
+ "idC026.xsd",
+ "idC025.xsd",
+ "idC024.xsd",
+ "idC023.xsd",
+ "idC021.xsd",
+ "idC020.xsd",
+ "idC018.xsd",
+ "idC017.xsd",
+ "idC016.xsd",
+ "idC007.xsd",
+ "idC006.xsd",
+ "idC005.xsd",
+ "idC004.xsd",
+ "idC003.xsd",
+ "idC002.xsd",
+ "idB044.xsd",
+ "idB043.xsd",
+ "idB042.xsd",
+ "idB035.xsd",
+ "idB032.xsd",
+ "idB031.xsd",
+ "idB030.xsd",
+ "idB029.xsd",
+ "idB028.xsd",
+ "idB027.xsd",
+ "idB026.xsd",
+ "idB025.xsd",
+ "idB024.xsd",
+ "idB023.xsd",
+ "idB021.xsd",
+ "idB020.xsd",
+ "idB019.xsd",
+ "idB017.xsd",
+ "idB016.xsd",
+ "idB007.xsd",
+ "idB006.xsd",
+ "idB004.xsd",
+ "idB003.xsd",
+ "idB002.xsd",
+ "idA044.xsd",
+ "idA043.xsd",
+ "idA042.xsd",
+ "idA035.xsd",
+ "idA032.xsd",
+ "idA031.xsd",
+ "idA030.xsd",
+ "idA029.xsd",
+ "idA028.xsd",
+ "idA027.xsd",
+ "idA026.xsd",
+ "idA025.xsd",
+ "idA024.xsd",
+ "idA023.xsd",
+ "idA021.xsd",
+ "idA020.xsd",
+ "idA019.xsd",
+ "idA018.xsd",
+ "idA016.xsd",
+ "idA007.xsd",
+ "idA006.xsd",
+ "idA005.xsd",
+ "idA004.xsd",
+ "idA003.xsd",
+ "idA002.xsd",
+ "idL102.xml",
+ "idL100.xml",
+ "idL098.xml",
+ "idL096.xml",
+ "idL094.xml",
+ "idL092.xml",
+ "idL090.xml",
+ "idL075.xml",
+ "idL072.xml",
+ "idL069.xml",
+ "idL065.xml",
+ "idL062.xml",
+ "idL061.xml",
+ "idL057.xml",
+ "idL056.xml",
+ "idL052.xml",
+ "idL049.xml",
+ "idL048.xml",
+ "idL025.xml",
+ "idL024.xml",
+ "idL023.xml",
+ "idK015.xml",
+ "idK014.xml",
+ "idK012.xml",
+ "idK003.xml",
+ "idH034.xml",
+ "idH032.xml",
+ "idH023.xml",
+ "idH012.xml",
+ "idH010.xml",
+ "idH006.xml",
+ "idG030.xml",
+ "idG028.xml",
+ "idG019.xml",
+ "idG012.xml",
+ "idG011.xml",
+ "idG006.xml",
+ "idF036.xml",
+ "idF034.xml",
+ "idF033.xml",
+ "idF031.xml",
+ "idF026.xml",
+ "idF025.xml",
+ "idF017.xml",
+ "idF016.xml",
+ "idF014.xml",
+ "idF013.xml",
+ "idF012.xml",
+ "idF010.xml",
+ "idF009.xml",
+ "idF004.xml",
+ "idF003.xml"],[]}}.
+{mgABCD,{["mgC013.xsd",
+ "mgC009.xsd",
+ "mgC008.xsd",
+ "mgB010.xsd",
+ "mgB009.xsd",
+ "mgB008.xsd",
+ "mgB007.xsd",
+ "mgB003.xsd",
+ "mgAb007.xsd",
+ "mgAb006.xsd",
+ "mgAb004.xsd",
+ "mgAb003.xsd",
+ "mgAb002.xsd",
+ "mgAa007.xsd",
+ "mgAa006.xsd",
+ "mgAa004.xsd",
+ "mgAa002.xsd",
+ "mgA019.xsd",
+ "mgA018.xsd",
+ "mgA013.xsd",
+ "mgA012.xsd",
+ "mgA011.xsd",
+ "mgA008.xsd",
+ "mgA007.xsd",
+ "mgA005.xsd",
+ "mgA004.xsd",
+ "mgA003.xsd",
+ "mgA002.xsd",
+ "mgA015.xml"],[]}}.
+{mgEFG,{["mgG030.xsd",
+ "mgG029.xsd",
+ "mgG028.xsd",
+ "mgG027.xsd",
+ "mgG025.xsd",
+ "mgG002.xsd",
+ "mgF023.xsd",
+ "mgF022.xsd",
+ "mgF021.xsd",
+ "mgF020.xsd",
+ "mgF003.xsd",
+ "mgEb002.xsd",
+ "mgEa005.xsd",
+ "mgEa004.xsd",
+ "mgEa002.xsd",
+ "mgE012.xsd",
+ "mgE011.xsd",
+ "mgE010.xsd",
+ "mgE008.xsd",
+ "mgE007.xsd",
+ "mgE006.xsd",
+ "mgE005.xsd",
+ "mgE004.xsd",
+ "mgE003.xsd",
+ "mgE002.xsd",
+ "mgG026.xml",
+ "mgG023.xml",
+ "mgG013.xml",
+ "mgF019.xml",
+ "mgF016.xml",
+ "mgF015.xml",
+ "mgF014.xml",
+ "mgF013.xml",
+ "mgF012.xml",
+ "mgF011.xml",
+ "mgF010.xml",
+ "mgF009.xml",
+ "mgEb005.xml",
+ "mgEb004.xml",
+ "mgE014.xml"],[]}}.
+{mgHIJ,{["mgJ030.xsd",
+ "mgJ029.xsd",
+ "mgJ028.xsd",
+ "mgJ027.xsd",
+ "mgJ025.xsd",
+ "mgJ002.xsd",
+ "mgI023.xsd",
+ "mgI022.xsd",
+ "mgI021.xsd",
+ "mgI020.xsd",
+ "mgI003.xsd",
+ "mgHb002.xsd",
+ "mgHa005.xsd",
+ "mgHa004.xsd",
+ "mgHa002.xsd",
+ "mgH012.xsd",
+ "mgH011.xsd",
+ "mgH008.xsd",
+ "mgH007.xsd",
+ "mgH006.xsd",
+ "mgH005.xsd",
+ "mgH004.xsd",
+ "mgH003.xsd",
+ "mgH002.xsd",
+ "mgJ026.xml",
+ "mgJ023.xml",
+ "mgJ013.xml",
+ "mgJ001.xml",
+ "mgHb005.xml",
+ "mgHb004.xml",
+ "mgH015.xml"],[]}}.
+{mgOP,{["mgP056.xsd",
+ "mgP055.xsd",
+ "mgP049.xsd",
+ "mgP042.xsd",
+ "mgP040.xsd",
+ "mgP039.xsd",
+ "mgO036.xsd",
+ "mgO029.xsd",
+ "mgO027.xsd",
+ "mgO019.xsd",
+ "mgO018.xsd",
+ "mgO015.xsd",
+ "mgO008.xsd",
+ "mgO003.xsd",
+ "mgO001.xsd",
+ "mgO038.xml",
+ "mgO037.xml",
+ "mgO036.xml",
+ "mgO035.xml",
+ "mgO034.xml",
+ "mgO031.xml",
+ "mgO029.xml",
+ "mgO017.xml",
+ "mgO016.xml",
+ "mgO015.xml",
+ "mgO014.xml",
+ "mgO013.xml",
+ "mgO011.xml",
+ "mgO010.xml",
+ "mgO009.xml",
+ "mgO008.xml",
+ "mgO007.xml",
+ "mgO006.xml",
+ "mgO005.xml"],[]}}.
+{mgQR,{["mgR022.xsd",
+ "mgR021.xsd",
+ "mgR020.xsd",
+ "mgR019.xsd",
+ "mgR018.xsd",
+ "mgR017.xsd",
+ "mgR016.xsd",
+ "mgR015.xsd",
+ "mgR014.xsd",
+ "mgR013.xsd",
+ "mgR012.xsd",
+ "mgR011.xsd",
+ "mgR010.xsd",
+ "mgR009.xsd",
+ "mgR008.xsd",
+ "mgR007.xsd",
+ "mgR006.xsd",
+ "mgR005.xsd",
+ "mgR004.xsd",
+ "mgR003.xsd",
+ "mgR002.xsd",
+ "mgR001.xsd",
+ "mgQ021.xsd",
+ "mgQ013.xsd",
+ "mgQ012.xsd",
+ "mgQ011.xsd",
+ "mgQ010.xsd",
+ "mgQ005.xsd",
+ "mgQ004.xsd",
+ "mgQ001.xsd",
+ "mgQ017.xml",
+ "mgQ016.xml",
+ "mgQ015.xml",
+ "mgQ014.xml",
+ "mgQ002.xml"],[]}}.
+{particlesAB,{["particlesB015.xml",
+ "particlesB010.xml",
+ "particlesA013.xml",
+ "particlesA011.xml",
+ "particlesA010.xml",
+ "particlesA009.xml",
+ "particlesA007.xml",
+ "particlesA006.xml",
+ "particlesA005.xml"],[]}}.
+{particlesCDE,{["particlesEd001.xsd",
+ "particlesEc009.xsd",
+ "particlesEb015.xsd",
+ "particlesEa025.xsd",
+ "particlesEa024.xsd",
+ "particlesEa023.xsd",
+ "particlesEa022.xsd",
+ "particlesEc039.xml",
+ "particlesEc038.xml",
+ "particlesEc023.xml",
+ "particlesEc022.xml",
+ "particlesEc013.xml",
+ "particlesEc010.xml",
+ "particlesEc007.xml",
+ "particlesEc003.xml",
+ "particlesEb030.xml",
+ "particlesEb022.xml",
+ "particlesEb016.xml",
+ "particlesEb013.xml",
+ "particlesEb006.xml",
+ "particlesEa018.xml",
+ "particlesEa017.xml",
+ "particlesEa011.xml",
+ "particlesEa010.xml",
+ "particlesEa004.xml",
+ "particlesEa003.xml",
+ "particlesC039.xml",
+ "particlesC036.xml",
+ "particlesC035.xml",
+ "particlesC032.xml",
+ "particlesC031.xml",
+ "particlesC025.xml",
+ "particlesC024.xml",
+ "particlesC023.xml",
+ "particlesC022.xml",
+ "particlesC020.xml",
+ "particlesC019.xml",
+ "particlesC018.xml",
+ "particlesC017.xml",
+ "particlesC014.xml",
+ "particlesC013.xml",
+ "particlesC012.xml",
+ "particlesC010.xml",
+ "particlesC009.xml"],[]}}.
+{particlesFHI,{["particlesIk026.xsd",
+ "particlesIk024.xsd",
+ "particlesIk021.xsd",
+ "particlesIk019.xsd",
+ "particlesIk012.xsd",
+ "particlesIk007.xsd",
+ "particlesIk006.xsd",
+ "particlesIk005.xsd",
+ "particlesIk003.xsd",
+ "particlesIk002.xsd",
+ "particlesIj016.xsd",
+ "particlesIj015.xsd",
+ "particlesIj013.xsd",
+ "particlesIj011.xsd",
+ "particlesIj010.xsd",
+ "particlesIj009.xsd",
+ "particlesIj008.xsd",
+ "particlesIj007.xsd",
+ "particlesIj004.xsd",
+ "particlesIj003.xsd",
+ "particlesIh001.xsd",
+ "particlesIg016.xsd",
+ "particlesIg013.xsd",
+ "particlesIg010.xsd",
+ "particlesIg009.xsd",
+ "particlesIg008.xsd",
+ "particlesIg007.xsd",
+ "particlesIg004.xsd",
+ "particlesIf009.xsd",
+ "particlesIf008.xsd",
+ "particlesIf007.xsd",
+ "particlesIe014.xsd",
+ "particlesIe012.xsd",
+ "particlesIe009.xsd",
+ "particlesIe006.xsd",
+ "particlesId012.xsd",
+ "particlesId006.xsd",
+ "particlesId003.xsd",
+ "particlesIb007.xsd",
+ "particlesIb006.xsd",
+ "particlesIa008.xsd",
+ "particlesIa006.xsd",
+ "particlesHb011.xsd",
+ "particlesHb008.xsd",
+ "particlesHb004.xsd",
+ "particlesHb003.xsd",
+ "particlesHb001.xsd",
+ "particlesHa008.xsd",
+ "particlesHa007.xsd",
+ "particlesHa006.xsd",
+ "particlesHa005.xsd",
+ "particlesHa004.xsd",
+ "particlesHa003.xsd",
+ "particlesHa002.xsd",
+ "particlesFb006.xsd",
+ "particlesFb005.xsd",
+ "particlesFb004.xsd",
+ "particlesFb003.xsd",
+ "particlesFb002.xsd",
+ "particlesIk026.xml",
+ "particlesIk012.xml",
+ "particlesIf006.xml",
+ "particlesIf001.xml",
+ "particlesIe004.xml",
+ "particlesHa007.xml",
+ "particlesHa006.xml",
+ "particlesHa005.xml",
+ "particlesHa004.xml",
+ "particlesHa003.xml",
+ "particlesHa002.xml",
+ "particlesFb004.xml",
+ "particlesFb001.xml",
+ "particlesFa001.xml"],[]}}.
+{particlesJ,{["particlesJk015.xsd",
+ "particlesJk013.xsd",
+ "particlesJk011.xsd",
+ "particlesJk010.xsd",
+ "particlesJk008.xsd",
+ "particlesJk007.xsd",
+ "particlesJk005.xsd",
+ "particlesJk004.xsd",
+ "particlesJk003.xsd",
+ "particlesJk002.xsd",
+ "particlesJk001.xsd",
+ "particlesJj011.xsd",
+ "particlesJj010.xsd",
+ "particlesJj009.xsd",
+ "particlesJj008.xsd",
+ "particlesJj007.xsd",
+ "particlesJj005.xsd",
+ "particlesJj004.xsd",
+ "particlesJj002.xsd",
+ "particlesJj001.xsd",
+ "particlesJf016.xsd",
+ "particlesJf015.xsd",
+ "particlesJf013.xsd",
+ "particlesJf011.xsd",
+ "particlesJf010.xsd",
+ "particlesJf008.xsd",
+ "particlesJf007.xsd",
+ "particlesJf005.xsd",
+ "particlesJf004.xsd",
+ "particlesJf003.xsd",
+ "particlesJf002.xsd",
+ "particlesJf001.xsd",
+ "particlesJe011.xsd",
+ "particlesJe010.xsd",
+ "particlesJe009.xsd",
+ "particlesJe008.xsd",
+ "particlesJe007.xsd",
+ "particlesJe005.xsd",
+ "particlesJe004.xsd",
+ "particlesJe002.xsd",
+ "particlesJe001.xsd",
+ "particlesJd016.xsd",
+ "particlesJd015.xsd",
+ "particlesJd013.xsd",
+ "particlesJd011.xsd",
+ "particlesJd010.xsd",
+ "particlesJd008.xsd",
+ "particlesJd007.xsd",
+ "particlesJd005.xsd",
+ "particlesJd004.xsd",
+ "particlesJd003.xsd",
+ "particlesJd002.xsd",
+ "particlesJd001.xsd",
+ "particlesJc011.xsd",
+ "particlesJc010.xsd",
+ "particlesJc009.xsd",
+ "particlesJc008.xsd",
+ "particlesJc007.xsd",
+ "particlesJc005.xsd",
+ "particlesJc004.xsd",
+ "particlesJc002.xsd",
+ "particlesJc001.xsd",
+ "particlesJb016.xsd",
+ "particlesJb015.xsd",
+ "particlesJb013.xsd",
+ "particlesJb011.xsd",
+ "particlesJb010.xsd",
+ "particlesJb008.xsd",
+ "particlesJb007.xsd",
+ "particlesJb005.xsd",
+ "particlesJb004.xsd",
+ "particlesJb003.xsd",
+ "particlesJb002.xsd",
+ "particlesJb001.xsd",
+ "particlesJa011.xsd",
+ "particlesJa010.xsd",
+ "particlesJa009.xsd",
+ "particlesJa008.xsd",
+ "particlesJa007.xsd",
+ "particlesJa005.xsd",
+ "particlesJa004.xsd",
+ "particlesJa002.xsd",
+ "particlesJa001.xsd",
+ "particlesJk015.xml",
+ "particlesJk013.xml",
+ "particlesJk011.xml",
+ "particlesJk010.xml",
+ "particlesJk008.xml",
+ "particlesJk007.xml",
+ "particlesJk005.xml",
+ "particlesJk004.xml",
+ "particlesJk003.xml",
+ "particlesJk002.xml",
+ "particlesJk001.xml",
+ "particlesJj011.xml",
+ "particlesJj010.xml",
+ "particlesJj009.xml",
+ "particlesJj008.xml",
+ "particlesJj007.xml",
+ "particlesJj005.xml",
+ "particlesJj004.xml",
+ "particlesJj002.xml",
+ "particlesJj001.xml",
+ "particlesJf016.xml",
+ "particlesJf015.xml",
+ "particlesJf013.xml",
+ "particlesJf011.xml",
+ "particlesJf010.xml",
+ "particlesJf008.xml",
+ "particlesJf007.xml",
+ "particlesJf005.xml",
+ "particlesJf004.xml",
+ "particlesJf003.xml",
+ "particlesJf002.xml",
+ "particlesJf001.xml",
+ "particlesJe011.xml",
+ "particlesJe010.xml",
+ "particlesJe009.xml",
+ "particlesJe008.xml",
+ "particlesJe007.xml",
+ "particlesJe005.xml",
+ "particlesJe004.xml",
+ "particlesJe002.xml",
+ "particlesJe001.xml",
+ "particlesJd016.xml",
+ "particlesJd015.xml",
+ "particlesJd013.xml",
+ "particlesJd011.xml",
+ "particlesJd010.xml",
+ "particlesJd008.xml",
+ "particlesJd007.xml",
+ "particlesJd005.xml",
+ "particlesJd004.xml",
+ "particlesJd003.xml",
+ "particlesJd002.xml",
+ "particlesJd001.xml",
+ "particlesJc011.xml",
+ "particlesJc010.xml",
+ "particlesJc009.xml",
+ "particlesJc008.xml",
+ "particlesJc007.xml",
+ "particlesJc005.xml",
+ "particlesJc004.xml",
+ "particlesJc002.xml",
+ "particlesJc001.xml",
+ "particlesJb016.xml",
+ "particlesJb015.xml",
+ "particlesJb013.xml",
+ "particlesJb011.xml",
+ "particlesJb010.xml",
+ "particlesJb008.xml",
+ "particlesJb007.xml",
+ "particlesJb005.xml",
+ "particlesJb004.xml",
+ "particlesJb003.xml",
+ "particlesJb002.xml",
+ "particlesJb001.xml",
+ "particlesJa011.xml",
+ "particlesJa010.xml",
+ "particlesJa009.xml",
+ "particlesJa008.xml",
+ "particlesJa007.xml",
+ "particlesJa005.xml",
+ "particlesJa004.xml",
+ "particlesJa002.xml",
+ "particlesJa001.xml"],[]}}.
+{particlesKOSRTQUVW,{["particlesW015.xsd",
+ "particlesW013.xsd",
+ "particlesW010.xsd",
+ "particlesW007.xsd",
+ "particlesW005.xsd",
+ "particlesW002.xsd",
+ "particlesV015.xsd",
+ "particlesV014.xsd",
+ "particlesV013.xsd",
+ "particlesV012.xsd",
+ "particlesV011.xsd",
+ "particlesV010.xsd",
+ "particlesV009.xsd",
+ "particlesV008.xsd",
+ "particlesV007.xsd",
+ "particlesV006.xsd",
+ "particlesV003.xsd",
+ "particlesU007.xsd",
+ "particlesU005.xsd",
+ "particlesU004.xsd",
+ "particlesU003.xsd",
+ "particlesQ031.xsd",
+ "particlesQ028.xsd",
+ "particlesQ027.xsd",
+ "particlesQ026.xsd",
+ "particlesQ025.xsd",
+ "particlesQ023.xsd",
+ "particlesQ021.xsd",
+ "particlesQ018.xsd",
+ "particlesQ012.xsd",
+ "particlesQ008.xsd",
+ "particlesQ006.xsd",
+ "particlesT011.xsd",
+ "particlesT010.xsd",
+ "particlesT009.xsd",
+ "particlesT008.xsd",
+ "particlesT002.xsd",
+ "particlesR031.xsd",
+ "particlesR028.xsd",
+ "particlesR027.xsd",
+ "particlesR026.xsd",
+ "particlesR025.xsd",
+ "particlesR023.xsd",
+ "particlesR021.xsd",
+ "particlesR018.xsd",
+ "particlesR014.xsd",
+ "particlesR010.xsd",
+ "particlesR006.xsd",
+ "particlesS011.xsd",
+ "particlesS007.xsd",
+ "particlesS004.xsd",
+ "particlesS003.xsd",
+ "particlesS001.xsd",
+ "particlesOb058.xsd",
+ "particlesOb051.xsd",
+ "particlesOb050.xsd",
+ "particlesOb049.xsd",
+ "particlesOb046.xsd",
+ "particlesOb045.xsd",
+ "particlesOb044.xsd",
+ "particlesOb043.xsd",
+ "particlesOb041.xsd",
+ "particlesOb040.xsd",
+ "particlesOb039.xsd",
+ "particlesOb038.xsd",
+ "particlesOb037.xsd",
+ "particlesOb036.xsd",
+ "particlesOb035.xsd",
+ "particlesOb034.xsd",
+ "particlesOb033.xsd",
+ "particlesOb031.xsd",
+ "particlesOb030.xsd",
+ "particlesOb029.xsd",
+ "particlesOb028.xsd",
+ "particlesOb027.xsd",
+ "particlesOb026.xsd",
+ "particlesOb025.xsd",
+ "particlesOb024.xsd",
+ "particlesOb023.xsd",
+ "particlesOb021.xsd",
+ "particlesOb020.xsd",
+ "particlesOb019.xsd",
+ "particlesOb017.xsd",
+ "particlesOb016.xsd",
+ "particlesOb014.xsd",
+ "particlesOb011.xsd",
+ "particlesOb010.xsd",
+ "particlesOa015.xsd",
+ "particlesOa010.xsd",
+ "particlesOa009.xsd",
+ "particlesOa008.xsd",
+ "particlesOa007.xsd",
+ "particlesOa005.xsd",
+ "particlesOa004.xsd",
+ "particlesOa002.xsd",
+ "particlesK008.xsd",
+ "particlesK005.xsd",
+ "particlesK003.xsd",
+ "particlesK002.xsd",
+ "particlesK001.xsd",
+ "particlesV015.xml",
+ "particlesV014.xml",
+ "particlesV013.xml",
+ "particlesV012.xml",
+ "particlesV011.xml",
+ "particlesV010.xml",
+ "particlesV009.xml",
+ "particlesV008.xml",
+ "particlesV007.xml",
+ "particlesV006.xml",
+ "particlesV003.xml",
+ "particlesU007.xml",
+ "particlesU005.xml",
+ "particlesU004.xml",
+ "particlesU003.xml",
+ "particlesQ022.xml",
+ "particlesQ020.xml",
+ "particlesQ019.xml",
+ "particlesQ017.xml",
+ "particlesQ016.xml",
+ "particlesT003.xml",
+ "particlesR022.xml",
+ "particlesR019.xml",
+ "particlesR016.xml",
+ "particlesR011.xml",
+ "particlesS011.xml",
+ "particlesS007.xml",
+ "particlesS004.xml",
+ "particlesS003.xml",
+ "particlesS001.xml",
+ "particlesOb055.xml",
+ "particlesOb042.xml",
+ "particlesOb007.xml",
+ "particlesOb003.xml",
+ "particlesOa014.xml",
+ "particlesOa013.xml",
+ "particlesOa012.xml",
+ "particlesOa011.xml",
+ "particlesK008.xml",
+ "particlesK005.xml",
+ "particlesK003.xml",
+ "particlesK002.xml",
+ "particlesK001.xml"],[]}}.
+{stABCDE,{["stE016.xsd",
+ "stE015.xsd",
+ "stE014.xsd",
+ "stE012.xsd",
+ "stE008.xsd",
+ "stE005.xsd",
+ "stE004.xsd",
+ "stE003.xsd",
+ "stE002.xsd",
+ "stD020.xsd",
+ "stD018.xsd",
+ "stD017.xsd",
+ "stD016.xsd",
+ "stD010.xsd",
+ "stD009.xsd",
+ "stD005.xsd",
+ "stD004.xsd",
+ "stD003.xsd",
+ "stD002.xsd",
+ "stC032.xsd",
+ "stC029.xsd",
+ "stC009.xsd",
+ "stC008.xsd",
+ "stC007.xsd",
+ "stC006.xsd",
+ "stC003.xsd",
+ "stB024.xsd",
+ "stB023.xsd",
+ "stB022.xsd",
+ "stB021.xsd",
+ "stB020.xsd",
+ "stB019.xsd",
+ "stB018.xsd",
+ "stB017.xsd",
+ "stB016.xsd",
+ "stB014.xsd",
+ "stB013.xsd",
+ "stB010.xsd",
+ "stB009.xsd",
+ "stB004.xsd",
+ "stB002.xsd",
+ "stB001.xsd",
+ "stA017.xsd",
+ "stA015.xsd",
+ "stA014.xsd",
+ "stA013.xsd",
+ "stA012.xsd",
+ "stA011.xsd",
+ "stA010.xsd",
+ "stA009.xsd",
+ "stA008.xsd",
+ "stA005.xsd",
+ "stA004.xsd",
+ "stA003.xsd",
+ "stA002.xsd"],[]}}.
+{stFGH,{["stH002.xsd",
+ "stH001.xsd",
+ "stG005.xsd",
+ "stG004.xsd",
+ "stF037.xsd",
+ "stF035.xsd",
+ "stF033.xsd",
+ "stF031.xsd",
+ "stF027.xsd",
+ "stF026.xsd",
+ "stF025.xsd",
+ "stF024.xsd",
+ "stF020.xsd",
+ "stF019.xsd",
+ "stF018.xsd",
+ "stF012.xsd",
+ "stF011.xsd",
+ "stF010.xsd",
+ "stF009.xsd",
+ "stH007.xml",
+ "stH005.xml",
+ "stH003.xml",
+ "stH001.xml",
+ "stG012.xml",
+ "stG010.xml",
+ "stG008.xml",
+ "stG006.xml",
+ "stG004.xml",
+ "stG002.xml",
+ "stG001.xml"],[]}}.
+{stIJK,{["stK014.xsd",
+ "stK013.xsd",
+ "stK012.xsd",
+ "stK011.xsd",
+ "stK007.xsd",
+ "stK006.xsd",
+ "stK005.xsd",
+ "stJ019.xsd",
+ "stJ013.xsd",
+ "stJ012.xsd",
+ "stJ011.xsd",
+ "stJ010.xsd",
+ "stJ002.xsd",
+ "stI005.xsd"],[]}}.
+{stZ,{["stZ003.xsd","stZ002.xsd"],[]}}.
+{wildABCDEF,{["wildF018.xsd",
+ "wildF016.xsd",
+ "wildF015.xsd",
+ "wildF014.xsd",
+ "wildF013.xsd",
+ "wildF012.xsd",
+ "wildF010.xsd",
+ "wildF009.xsd",
+ "wildF008.xsd",
+ "wildF007.xsd",
+ "wildF006.xsd",
+ "wildE002.xsd",
+ "wildD079.xsd",
+ "wildD078.xsd",
+ "wildD077.xsd",
+ "wildD076.xsd",
+ "wildD075.xsd",
+ "wildD071.xsd",
+ "wildC067.xsd",
+ "wildC066.xsd",
+ "wildC058.xsd",
+ "wildC057.xsd",
+ "wildC056.xsd",
+ "wildC055.xsd",
+ "wildC053.xsd",
+ "wildC052.xsd",
+ "wildC051.xsd",
+ "wildC050.xsd",
+ "wildC049.xsd",
+ "wildC036.xsd",
+ "wildC035.xsd",
+ "wildB028.xsd",
+ "wildB027.xsd",
+ "wildB023.xsd",
+ "wildB020.xsd",
+ "wildB015.xsd",
+ "wildA008.xsd",
+ "wildA007.xsd",
+ "wildA006.xsd",
+ "wildA005.xsd",
+ "wildA004.xsd",
+ "wildA003.xsd"],[]}}.
+{wildGHI,{["wildI013.xsd",
+ "wildI010.xsd",
+ "wildI009.xsd",
+ "wildI008.xsd",
+ "wildI003.xsd",
+ "wildI002.xsd",
+ "wildI007.xml",
+ "wildH006.xml",
+ "wildH002.xml",
+ "wildG039.xml",
+ "wildG037.xml",
+ "wildG036.xml",
+ "wildG032.xml",
+ "wildG029.xml",
+ "wildG028.xml",
+ "wildG024.xml",
+ "wildG022.xml",
+ "wildG020.xml",
+ "wildG019.xml",
+ "wildG014.xml",
+ "wildG013.xml",
+ "wildG011.xml",
+ "wildG010.xml",
+ "wildG009.xml",
+ "wildG008.xml",
+ "wildG005.xml",
+ "wildG004.xml",
+ "wildG002.xml"],[]}}.
+{wildJKLMNQOP,{["wildQ004.xsd",
+ "wildQ003.xsd",
+ "wildQ002.xsd",
+ "wildQ001.xsd",
+ "wildN018.xsd",
+ "wildN016.xsd",
+ "wildN015.xsd",
+ "wildN014.xsd",
+ "wildN013.xsd",
+ "wildN012.xsd",
+ "wildN010.xsd",
+ "wildN009.xsd",
+ "wildN008.xsd",
+ "wildN007.xsd",
+ "wildN006.xsd",
+ "wildN001.xsd",
+ "wildM002.xsd",
+ "wildL009.xsd",
+ "wildL008.xsd",
+ "wildL007.xsd",
+ "wildL006.xsd",
+ "wildL005.xsd",
+ "wildL001.xsd",
+ "wildK038.xsd",
+ "wildK029.xsd",
+ "wildK028.xsd",
+ "wildK027.xsd",
+ "wildK026.xsd",
+ "wildK024.xsd",
+ "wildK023.xsd",
+ "wildK022.xsd",
+ "wildK021.xsd",
+ "wildK020.xsd",
+ "wildK007.xsd",
+ "wildK006.xsd",
+ "wildK002.xsd",
+ "wildJ008.xsd",
+ "wildJ007.xsd",
+ "wildJ006.xsd",
+ "wildJ005.xsd",
+ "wildJ004.xsd",
+ "wildJ003.xsd",
+ "wildP006.xml",
+ "wildP005.xml",
+ "wildP004.xml",
+ "wildP003.xml",
+ "wildP001.xml",
+ "wildO040.xml",
+ "wildO038.xml",
+ "wildO037.xml",
+ "wildO033.xml",
+ "wildO031.xml",
+ "wildO030.xml",
+ "wildO027.xml",
+ "wildO026.xml",
+ "wildO023.xml",
+ "wildO021.xml",
+ "wildO020.xml",
+ "wildO018.xml",
+ "wildO013.xml",
+ "wildO012.xml",
+ "wildO010.xml",
+ "wildO007.xml",
+ "wildO006.xml",
+ "wildO004.xml"],[]}}.
diff --git a/lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE_data/msxsdtest.tar.gz b/lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE_data/msxsdtest.tar.gz
new file mode 100644
index 0000000000..05f9dfe08f
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE_data/msxsdtest.tar.gz
Binary files differ
diff --git a/lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE_data/w3c-copyright-19990405.html b/lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE_data/w3c-copyright-19990405.html
new file mode 100644
index 0000000000..5c89ffd95e
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_MS2002-01-16_SUITE_data/w3c-copyright-19990405.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html><head>
+
+
+ <meta http-equiv="Content-Type" content="text/html"><title>DOCUMENT NOTICE</title>
+
+ <link rel="stylesheet" type="text/css" href="copyright-documents-19990405_files/base.css"></head><body bgcolor="#ffffff" text="#000000">
+<h1>W3C<sup>�</sup> DOCUMENT NOTICE AND LICENSE</h1>
+
+<h3>Copyright � 1994-2002 <a href="http://www.w3.org/">World Wide Web
+Consortium</a>, (<a href="http://www.lcs.mit.edu/">Massachusetts Institute of
+Technology</a>, <a href="http://www.inria.fr/">Institut National de Recherche
+en Informatique et en Automatique</a>, <a href="http://www.keio.ac.jp/">Keio
+University</a>). All Rights Reserved.<br>
+http://www.w3.org/Consortium/Legal/</h3>
+
+<p>Public documents on the W3C site are provided by the copyright holders
+under the following license. The software or Document Type Definitions (DTDs)
+associated with W3C specifications are governed by the <a href="http://www.w3.org/Consortium/Legal/copyright-software.html"> Software
+Notice</a>. By using and/or copying this document, or the W3C document from
+which this statement is linked, you (the licensee) agree that you have read,
+understood, and will comply with the following terms and conditions:</p>
+
+<p>Permission to use, copy, and distribute the contents of this document, or
+the W3C document from which this statement is linked, in any medium for any
+purpose and without fee or royalty is hereby granted, provided that you
+include the following on <i>ALL</i> copies of the document, or portions
+thereof, that you use:</p>
+<ol>
+ <li>A link or URL to the original W3C document.</li>
+ <li>The pre-existing copyright notice of the original author, or if it
+ doesn't exist, a notice of the form: "Copyright � [$date-of-document] <a href="http://www.w3.org/">World Wide Web Consortium</a>, (<a href="http://www.lcs.mit.edu/">Massachusetts Institute of Technology</a>,
+ <a href="http://www.inria.fr/"> Institut National de Recherche en
+ Informatique et en Automatique</a>, <a href="http://www.keio.ac.jp/">Keio
+ University</a>). All Rights Reserved.
+ http://www.w3.org/Consortium/Legal/" (Hypertext is preferred, but a
+ textual representation is permitted.)</li>
+ <li><em>If it exists</em>, the STATUS of the W3C document.</li>
+</ol>
+
+<p>When space permits, inclusion of the full text of this <b> NOTICE</b>
+should be provided. We request that authorship attribution be provided in any
+software, documents, or other items or products that you create pursuant to
+the implementation of the contents of this document, or any portion
+thereof.</p>
+
+<p>No right to create modifications or derivatives of W3C documents is
+granted pursuant to this license. However, if additional requirements
+(documented in the <a href="http://www.w3.org/Consortium/Legal/IPR-FAQ.html">Copyright FAQ</a>) are satisfied,
+the right to create modifications or derivatives is&nbsp;sometimes granted by the
+W3C to individuals complying with those requirements.</p>
+
+<p>THIS DOCUMENT IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO
+REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED
+TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
+NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE DOCUMENT ARE SUITABLE
+FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF SUCH CONTENTS WILL NOT
+INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.</p>
+
+<p>COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE DOCUMENT OR THE
+PERFORMANCE OR IMPLEMENTATION OF THE CONTENTS THEREOF.</p>
+
+<p>The name and trademarks of copyright holders may NOT be used in
+advertising or publicity pertaining to this document or its contents without
+specific, written prior permission. Title to copyright in this document will
+at all times remain with copyright holders.</p>
+
+<p>----------------------------------------------------------------------------</p>
+
+<p>This formulation of W3C's notice and license became active on April 05
+1999 so as to account for the treatment of DTDs, schema's and bindings. See
+the <a href="http://www.w3.org/Consortium/Legal/copyright-documents-19990218.html"> older formulation</a> for
+the policy prior to this date. Please see our <a href="http://www.w3.org/Consortium/Legal/IPR-FAQ.html">Copyright FAQ</a> for common questions about using
+materials from our site, including specific terms and conditions for packages
+like libwww, Amaya, and Jigsaw. Other questions about this notice can be
+directed to <a href="mailto:[email protected]">[email protected]</a>.</p>
+<address>
+ <a href="http://w3.org/Help/Webmaster.html">webmaster</a><br>
+ (last updated by reagle on 1999/04/99.)
+</address>
+</body></html> \ No newline at end of file
diff --git a/lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE.erl b/lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE.erl
new file mode 100644
index 0000000000..daebf1393d
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE.erl
@@ -0,0 +1,15962 @@
+%%
+%% %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%
+%%
+%%
+%%% Purpose : Test suite for the xmerl application
+
+%% Do NOT edit this file. It is generated by the generate_xsd_suite module
+%% For more info read the comments in the header of that file.
+
+-module('xmerl_xsd_NIST2002-01-16_SUITE').
+
+-compile(export_all).
+
+-include_lib("test_server/include/test_server.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
+-include_lib("xmerl/include/xmerl_xsd.hrl").
+
+
+all() ->
+ ['NISTSchema-anyURI', 'NISTSchema-base64Binary',
+ 'NISTSchema-boolean', 'NISTSchema-byte',
+ 'NISTSchema-date-', 'NISTSchema-dateTime',
+ 'NISTSchema-decimal', 'NISTSchema-double',
+ 'NISTSchema-duration', 'NISTSchema-float',
+ 'NISTSchema-gDay', 'NISTSchema-gMonth-',
+ 'NISTSchema-gMonthDay', 'NISTSchema-gYear-',
+ 'NISTSchema-gYearMonth', 'NISTSchema-hexBinary',
+ 'NISTSchema-ID', 'NISTSchema-int-',
+ 'NISTSchema-integer', 'NISTSchema-language',
+ 'NISTSchema-long', 'NISTSchema-Name',
+ 'NISTSchema-NCName', 'NISTSchema-negativeInteger',
+ 'NISTSchema-NMTOKEN', 'NISTSchema-nonNegativeInteger',
+ 'NISTSchema-nonPositiveInteger',
+ 'NISTSchema-normalizedString',
+ 'NISTSchema-positiveInteger', 'NISTSchema-QName',
+ 'NISTSchema-short', 'NISTSchema-string',
+ 'NISTSchema-time', 'NISTSchema-token',
+ 'NISTSchema-unsignedByte', 'NISTSchema-unsignedInt',
+ 'NISTSchema-unsignedLong', 'NISTSchema-unsignedShort'].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+
+%% initialization before the test suite
+init_per_suite(Config) ->
+ Dog=test_server:timetrap({minutes,10}),
+ xmerl_xsd_lib:unpack(Config,nist),
+ {ok,LogFile} = xmerl_xsd_lib:create_error_log_file(Config,nist),
+ test_server:timetrap_cancel(Dog),
+ [{suite,nist},{xmerl_error_log,LogFile}|Config].
+
+end_per_suite(Config) ->
+ xmerl_xsd_lib:rmdir(Config,nist),
+ xmerl_xsd_lib:close_error_log_file(Config),
+ ok.
+
+%% initialization before each testcase
+init_per_testcase(TestCase,Config) ->
+ Dog=test_server:timetrap({minutes,3}),
+ [{testcase,TestCase},{watchdog, Dog}|Config].
+
+%% clean up after each testcase
+end_per_testcase(_Func,Config) ->
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+%% Data type derived by restriction of anyURI by facets
+
+'NISTSchema-anyURI'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./NISTTestsAll/NISTSchema-anyURI-maxLength-1.xsd','./NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-maxLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-maxLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-maxLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-maxLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-5-2.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-5-3.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-5-4.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-maxLength-5-5.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-minLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-minLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-minLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-minLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList42 = [ITRes41|ITResList41],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList43 = [ITRes42|ITResList42],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList44 = [ITRes43|ITResList43],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-minLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-5-2.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-5-3.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-5-4.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList48 = [ITRes47|ITResList47],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-minLength-5-5.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList49 = [ITRes48|ITResList48],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-length-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-1-2.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-1-3.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-1-4.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList53 = [ITRes52|ITResList52],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-1-5.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList54 = [ITRes53|ITResList53],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-length-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList58 = [ITRes57|ITResList57],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList59 = [ITRes58|ITResList58],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-length-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList63 = [ITRes62|ITResList62],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-length-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-length-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-length-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-anyURI-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-anyURI-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList26,ITResList129).
+
+%% Data type derived by restriction of base64binary by facets
+
+'NISTSchema-base64Binary'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-maxLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-maxLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-maxLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-maxLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-maxLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-5-2.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-5-3.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-5-4.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-maxLength-5-5.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-minLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-minLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-minLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-minLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList42 = [ITRes41|ITResList41],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList43 = [ITRes42|ITResList42],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-minLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-5-2.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-5-3.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList48 = [ITRes47|ITResList47],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-5-4.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-minLength-5-5.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-length-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-1-2.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-1-3.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList53 = [ITRes52|ITResList52],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-1-4.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-1-5.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList55 = [ITRes54|ITResList54],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-length-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList58 = [ITRes57|ITResList57],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList60 = [ITRes59|ITResList59],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-length-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList63 = [ITRes62|ITResList62],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList64 = [ITRes63|ITResList63],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList65 = [ITRes64|ITResList64],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-length-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList69 = [ITRes68|ITResList68],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList70 = [ITRes69|ITResList69],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-length-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList74 = [ITRes73|ITResList73],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-length-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList75 = [ITRes74|ITResList74],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList79 = [ITRes78|ITResList78],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList80 = [ITRes79|ITResList79],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList84 = [ITRes83|ITResList83],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList85 = [ITRes84|ITResList84],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList89 = [ITRes88|ITResList88],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList90 = [ITRes89|ITResList89],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList94 = [ITRes93|ITResList93],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList95 = [ITRes94|ITResList94],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList99 = [ITRes98|ITResList98],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList100 = [ITRes99|ITResList99],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList104 = [ITRes103|ITResList103],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList105 = [ITRes104|ITResList104],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList109 = [ITRes108|ITResList108],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList110 = [ITRes109|ITResList109],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList114 = [ITRes113|ITResList113],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList115 = [ITRes114|ITResList114],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList119 = [ITRes118|ITResList118],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList120 = [ITRes119|ITResList119],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList124 = [ITRes123|ITResList123],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList125 = [ITRes124|ITResList124],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-base64Binary-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList129 = [ITRes128|ITResList128],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-base64Binary-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList130 = [ITRes129|ITResList129],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList26,ITResList130).
+
+%% Data type derived by restriction of boolean by facets
+
+'NISTSchema-boolean'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-boolean-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-boolean-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-boolean-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-boolean-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-boolean-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-boolean-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-boolean-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-boolean-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-boolean-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-boolean-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList5 = [ITRes4|ITResList4],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-boolean-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-boolean-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-boolean-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-boolean-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList5,ITResList9).
+
+%% Data type derived by restriction of byte by facets
+
+'NISTSchema-byte'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-fractionDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-fractionDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-fractionDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-fractionDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-fractionDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-fractionDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-totalDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-totalDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-totalDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-totalDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-totalDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-totalDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-totalDigits-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-totalDigits-2-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-totalDigits-2-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-totalDigits-2-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-totalDigits-2-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-totalDigits-2-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-totalDigits-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-totalDigits-3-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-totalDigits-3-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-totalDigits-3-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-totalDigits-3-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-totalDigits-3-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ ?line {STRes31,S31} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList32 = [STRes31|STResList31],
+ ?line ITRes139 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList140 = [ITRes139|ITResList139],
+ ?line ITRes140 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList141 = [ITRes140|ITResList140],
+ ?line ITRes141 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList142 = [ITRes141|ITResList141],
+ ?line ITRes142 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList143 = [ITRes142|ITResList142],
+ ?line ITRes143 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList144 = [ITRes143|ITResList143],
+
+
+ ?line {STRes32,S32} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList33 = [STRes32|STResList32],
+ ?line ITRes144 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList145 = [ITRes144|ITResList144],
+ ?line ITRes145 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList146 = [ITRes145|ITResList145],
+ ?line ITRes146 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList147 = [ITRes146|ITResList146],
+ ?line ITRes147 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList148 = [ITRes147|ITResList147],
+ ?line ITRes148 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList149 = [ITRes148|ITResList148],
+
+
+ ?line {STRes33,S33} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList34 = [STRes33|STResList33],
+ ?line ITRes149 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList150 = [ITRes149|ITResList149],
+ ?line ITRes150 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList151 = [ITRes150|ITResList150],
+ ?line ITRes151 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList152 = [ITRes151|ITResList151],
+ ?line ITRes152 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList153 = [ITRes152|ITResList152],
+ ?line ITRes153 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList154 = [ITRes153|ITResList153],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-byte-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes154 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList155 = [ITRes154|ITResList154],
+ ?line ITRes155 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList156 = [ITRes155|ITResList155],
+ ?line ITRes156 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList157 = [ITRes156|ITResList156],
+ ?line ITRes157 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList158 = [ITRes157|ITResList157],
+ ?line ITRes158 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-byte-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList159 = [ITRes158|ITResList158],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList35,ITResList159).
+
+%% Data type derived by restriction of date by facets
+
+'NISTSchema-date-'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-date-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-date-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList31,ITResList139).
+
+%% Data type derived by restriction of dateTime by facets
+
+'NISTSchema-dateTime'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-dateTime-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-dateTime-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList31,ITResList139).
+
+%% Data type derived by restriction of decimal by facets
+
+'NISTSchema-decimal'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-fractionDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-fractionDigits-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-fractionDigits-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-fractionDigits-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-fractionDigits-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-fractionDigits-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-totalDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-totalDigits-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-2-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-2-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-2-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-2-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-2-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-totalDigits-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-3-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-3-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-3-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-3-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-3-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-totalDigits-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-4-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-4-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-4-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-4-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-4-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-totalDigits-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-5-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-5-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-5-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-5-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-totalDigits-5-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ ?line {STRes31,S31} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList32 = [STRes31|STResList31],
+ ?line ITRes139 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList140 = [ITRes139|ITResList139],
+ ?line ITRes140 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList141 = [ITRes140|ITResList140],
+ ?line ITRes141 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList142 = [ITRes141|ITResList141],
+ ?line ITRes142 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList143 = [ITRes142|ITResList142],
+ ?line ITRes143 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList144 = [ITRes143|ITResList143],
+
+
+ ?line {STRes32,S32} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList33 = [STRes32|STResList32],
+ ?line ITRes144 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList145 = [ITRes144|ITResList144],
+ ?line ITRes145 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList146 = [ITRes145|ITResList145],
+ ?line ITRes146 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList147 = [ITRes146|ITResList146],
+ ?line ITRes147 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList148 = [ITRes147|ITResList147],
+ ?line ITRes148 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList149 = [ITRes148|ITResList148],
+
+
+ ?line {STRes33,S33} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList34 = [STRes33|STResList33],
+ ?line ITRes149 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList150 = [ITRes149|ITResList149],
+ ?line ITRes150 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList151 = [ITRes150|ITResList150],
+ ?line ITRes151 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList152 = [ITRes151|ITResList151],
+ ?line ITRes152 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList153 = [ITRes152|ITResList152],
+ ?line ITRes153 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList154 = [ITRes153|ITResList153],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes154 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList155 = [ITRes154|ITResList154],
+ ?line ITRes155 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList156 = [ITRes155|ITResList155],
+ ?line ITRes156 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList157 = [ITRes156|ITResList156],
+ ?line ITRes157 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList158 = [ITRes157|ITResList157],
+ ?line ITRes158 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList159 = [ITRes158|ITResList158],
+
+
+ ?line {STRes35,S35} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList36 = [STRes35|STResList35],
+ ?line ITRes159 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList160 = [ITRes159|ITResList159],
+ ?line ITRes160 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList161 = [ITRes160|ITResList160],
+ ?line ITRes161 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList162 = [ITRes161|ITResList161],
+ ?line ITRes162 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList163 = [ITRes162|ITResList162],
+ ?line ITRes163 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList164 = [ITRes163|ITResList163],
+
+
+ ?line {STRes36,S36} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList37 = [STRes36|STResList36],
+ ?line ITRes164 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList165 = [ITRes164|ITResList164],
+ ?line ITRes165 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList166 = [ITRes165|ITResList165],
+ ?line ITRes166 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList167 = [ITRes166|ITResList166],
+ ?line ITRes167 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList168 = [ITRes167|ITResList167],
+ ?line ITRes168 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList169 = [ITRes168|ITResList168],
+
+
+ ?line {STRes37,S37} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList38 = [STRes37|STResList37],
+ ?line ITRes169 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S37),
+ ITResList170 = [ITRes169|ITResList169],
+ ?line ITRes170 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S37),
+ ITResList171 = [ITRes170|ITResList170],
+ ?line ITRes171 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S37),
+ ITResList172 = [ITRes171|ITResList171],
+ ?line ITRes172 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S37),
+ ITResList173 = [ITRes172|ITResList172],
+ ?line ITRes173 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S37),
+ ITResList174 = [ITRes173|ITResList173],
+
+
+ ?line {STRes38,S38} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList39 = [STRes38|STResList38],
+ ?line ITRes174 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S38),
+ ITResList175 = [ITRes174|ITResList174],
+ ?line ITRes175 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S38),
+ ITResList176 = [ITRes175|ITResList175],
+ ?line ITRes176 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S38),
+ ITResList177 = [ITRes176|ITResList176],
+ ?line ITRes177 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S38),
+ ITResList178 = [ITRes177|ITResList177],
+ ?line ITRes178 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S38),
+ ITResList179 = [ITRes178|ITResList178],
+
+
+ ?line {STRes39,S39} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList40 = [STRes39|STResList39],
+ ?line ITRes179 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S39),
+ ITResList180 = [ITRes179|ITResList179],
+ ?line ITRes180 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S39),
+ ITResList181 = [ITRes180|ITResList180],
+ ?line ITRes181 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S39),
+ ITResList182 = [ITRes181|ITResList181],
+ ?line ITRes182 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S39),
+ ITResList183 = [ITRes182|ITResList182],
+ ?line ITRes183 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S39),
+ ITResList184 = [ITRes183|ITResList183],
+
+
+ ?line {STRes40,S40} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-decimal-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList41 = [STRes40|STResList40],
+ ?line ITRes184 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S40),
+ ITResList185 = [ITRes184|ITResList184],
+ ?line ITRes185 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S40),
+ ITResList186 = [ITRes185|ITResList185],
+ ?line ITRes186 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S40),
+ ITResList187 = [ITRes186|ITResList186],
+ ?line ITRes187 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S40),
+ ITResList188 = [ITRes187|ITResList187],
+ ?line ITRes188 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-decimal-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S40),
+ ITResList189 = [ITRes188|ITResList188],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList41,ITResList189).
+
+%% Data type derived by restriction of double by facets
+
+'NISTSchema-double'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-double-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-double-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList31,ITResList139).
+
+%% Data type derived by restriction of duration by facets
+
+'NISTSchema-duration'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-duration-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-duration-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList31,ITResList139).
+
+%% Data type derived by restriction of float by facets
+
+'NISTSchema-float'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-float-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-float-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList31,ITResList139).
+
+%% Data type derived by restriction of gDay by facets
+
+'NISTSchema-gDay'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList79 = [ITRes78|ITResList78],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList84 = [ITRes83|ITResList83],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList89 = [ITRes88|ITResList88],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList94 = [ITRes93|ITResList93],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList99 = [ITRes98|ITResList98],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList104 = [ITRes103|ITResList103],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList109 = [ITRes108|ITResList108],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList114 = [ITRes113|ITResList113],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList119 = [ITRes118|ITResList118],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList124 = [ITRes123|ITResList123],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList129 = [ITRes128|ITResList128],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gDay-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList134 = [ITRes133|ITResList133],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gDay-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList31,ITResList135).
+
+%% Data type derived by restriction of gMonth by facets
+
+'NISTSchema-gMonth-'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonth-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonth-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList31,ITResList139).
+
+%% Data type derived by restriction of gMonthDay by facets
+
+'NISTSchema-gMonthDay'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gMonthDay-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gMonthDay-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList31,ITResList139).
+
+%% Data type derived by restriction of gYear by facets
+
+'NISTSchema-gYear-'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList69 = [ITRes68|ITResList68],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList74 = [ITRes73|ITResList73],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList79 = [ITRes78|ITResList78],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList84 = [ITRes83|ITResList83],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList89 = [ITRes88|ITResList88],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList94 = [ITRes93|ITResList93],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList99 = [ITRes98|ITResList98],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList104 = [ITRes103|ITResList103],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList109 = [ITRes108|ITResList108],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList114 = [ITRes113|ITResList113],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList119 = [ITRes118|ITResList118],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList124 = [ITRes123|ITResList123],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList129 = [ITRes128|ITResList128],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYear-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList134 = [ITRes133|ITResList133],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYear-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList31,ITResList135).
+
+%% Data type derived by restriction of gYearMonth by facets
+
+'NISTSchema-gYearMonth'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-gYearMonth-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-gYearMonth-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList31,ITResList139).
+
+%% Data type derived by restriction of hexBinary by facets
+
+'NISTSchema-hexBinary'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-maxLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-maxLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-maxLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-maxLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-maxLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-5-2.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-5-3.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-5-4.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-maxLength-5-5.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-minLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-minLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-minLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-minLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList42 = [ITRes41|ITResList41],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList43 = [ITRes42|ITResList42],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-minLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-5-2.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-5-3.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList48 = [ITRes47|ITResList47],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-5-4.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-minLength-5-5.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-length-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-1-2.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-1-3.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList53 = [ITRes52|ITResList52],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-1-4.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-1-5.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList55 = [ITRes54|ITResList54],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-length-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList58 = [ITRes57|ITResList57],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList60 = [ITRes59|ITResList59],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-length-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList63 = [ITRes62|ITResList62],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList64 = [ITRes63|ITResList63],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList65 = [ITRes64|ITResList64],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-length-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList69 = [ITRes68|ITResList68],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList70 = [ITRes69|ITResList69],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-length-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList74 = [ITRes73|ITResList73],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-length-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList75 = [ITRes74|ITResList74],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList79 = [ITRes78|ITResList78],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList80 = [ITRes79|ITResList79],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList84 = [ITRes83|ITResList83],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList85 = [ITRes84|ITResList84],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList89 = [ITRes88|ITResList88],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList90 = [ITRes89|ITResList89],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList94 = [ITRes93|ITResList93],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList95 = [ITRes94|ITResList94],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList99 = [ITRes98|ITResList98],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList100 = [ITRes99|ITResList99],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList104 = [ITRes103|ITResList103],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList105 = [ITRes104|ITResList104],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList109 = [ITRes108|ITResList108],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList110 = [ITRes109|ITResList109],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList114 = [ITRes113|ITResList113],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList115 = [ITRes114|ITResList114],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList119 = [ITRes118|ITResList118],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList120 = [ITRes119|ITResList119],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList124 = [ITRes123|ITResList123],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList125 = [ITRes124|ITResList124],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-hexBinary-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList129 = [ITRes128|ITResList128],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-hexBinary-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList130 = [ITRes129|ITResList129],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList26,ITResList130).
+
+%% Data type derived by restriction of ID by facets
+
+'NISTSchema-ID'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-maxLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-maxLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-maxLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-maxLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-maxLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-5-2.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-5-3.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-5-4.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-maxLength-5-5.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-minLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-minLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-minLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-minLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList42 = [ITRes41|ITResList41],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList43 = [ITRes42|ITResList42],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-minLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-5-2.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-5-3.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList48 = [ITRes47|ITResList47],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-5-4.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-minLength-5-5.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-length-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-1-2.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-1-3.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList53 = [ITRes52|ITResList52],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-1-4.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-1-5.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList55 = [ITRes54|ITResList54],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-length-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList58 = [ITRes57|ITResList57],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList60 = [ITRes59|ITResList59],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-length-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList63 = [ITRes62|ITResList62],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList64 = [ITRes63|ITResList63],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList65 = [ITRes64|ITResList64],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-length-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList69 = [ITRes68|ITResList68],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList70 = [ITRes69|ITResList69],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-length-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList74 = [ITRes73|ITResList73],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-length-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList75 = [ITRes74|ITResList74],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList79 = [ITRes78|ITResList78],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList80 = [ITRes79|ITResList79],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList84 = [ITRes83|ITResList83],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList85 = [ITRes84|ITResList84],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList89 = [ITRes88|ITResList88],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList90 = [ITRes89|ITResList89],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList94 = [ITRes93|ITResList93],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList95 = [ITRes94|ITResList94],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList99 = [ITRes98|ITResList98],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList100 = [ITRes99|ITResList99],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList104 = [ITRes103|ITResList103],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList105 = [ITRes104|ITResList104],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList109 = [ITRes108|ITResList108],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList110 = [ITRes109|ITResList109],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList114 = [ITRes113|ITResList113],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList115 = [ITRes114|ITResList114],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList119 = [ITRes118|ITResList118],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList120 = [ITRes119|ITResList119],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList124 = [ITRes123|ITResList123],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList125 = [ITRes124|ITResList124],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-ID-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList129 = [ITRes128|ITResList128],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-ID-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList130 = [ITRes129|ITResList129],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList26,ITResList130).
+
+%% Data type derived by restriction of int by facets
+
+'NISTSchema-int-'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-fractionDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-fractionDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-fractionDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-fractionDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-fractionDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-fractionDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-totalDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-totalDigits-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-2-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-2-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-2-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-2-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-2-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-totalDigits-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-3-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-3-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-3-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-3-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-3-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-totalDigits-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-4-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-4-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-4-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-4-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-4-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-totalDigits-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-5-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-5-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-5-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-5-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-totalDigits-5-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ ?line {STRes31,S31} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList32 = [STRes31|STResList31],
+ ?line ITRes139 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList140 = [ITRes139|ITResList139],
+ ?line ITRes140 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList141 = [ITRes140|ITResList140],
+ ?line ITRes141 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList142 = [ITRes141|ITResList141],
+ ?line ITRes142 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList143 = [ITRes142|ITResList142],
+ ?line ITRes143 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList144 = [ITRes143|ITResList143],
+
+
+ ?line {STRes32,S32} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList33 = [STRes32|STResList32],
+ ?line ITRes144 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList145 = [ITRes144|ITResList144],
+ ?line ITRes145 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList146 = [ITRes145|ITResList145],
+ ?line ITRes146 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList147 = [ITRes146|ITResList146],
+ ?line ITRes147 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList148 = [ITRes147|ITResList147],
+ ?line ITRes148 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList149 = [ITRes148|ITResList148],
+
+
+ ?line {STRes33,S33} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList34 = [STRes33|STResList33],
+ ?line ITRes149 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList150 = [ITRes149|ITResList149],
+ ?line ITRes150 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList151 = [ITRes150|ITResList150],
+ ?line ITRes151 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList152 = [ITRes151|ITResList151],
+ ?line ITRes152 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList153 = [ITRes152|ITResList152],
+ ?line ITRes153 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList154 = [ITRes153|ITResList153],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes154 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList155 = [ITRes154|ITResList154],
+ ?line ITRes155 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList156 = [ITRes155|ITResList155],
+ ?line ITRes156 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList157 = [ITRes156|ITResList156],
+ ?line ITRes157 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList158 = [ITRes157|ITResList157],
+ ?line ITRes158 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList159 = [ITRes158|ITResList158],
+
+
+ ?line {STRes35,S35} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList36 = [STRes35|STResList35],
+ ?line ITRes159 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList160 = [ITRes159|ITResList159],
+ ?line ITRes160 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList161 = [ITRes160|ITResList160],
+ ?line ITRes161 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList162 = [ITRes161|ITResList161],
+ ?line ITRes162 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList163 = [ITRes162|ITResList162],
+ ?line ITRes163 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList164 = [ITRes163|ITResList163],
+
+
+ ?line {STRes36,S36} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-int-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList37 = [STRes36|STResList36],
+ ?line ITRes164 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList165 = [ITRes164|ITResList164],
+ ?line ITRes165 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList166 = [ITRes165|ITResList165],
+ ?line ITRes166 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList167 = [ITRes166|ITResList166],
+ ?line ITRes167 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList168 = [ITRes167|ITResList167],
+ ?line ITRes168 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-int-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList169 = [ITRes168|ITResList168],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList37,ITResList169).
+
+%% Data type derived by restriction of integer by facets
+
+'NISTSchema-integer'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-fractionDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-fractionDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-fractionDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-fractionDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-fractionDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-fractionDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-totalDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-totalDigits-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-2-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-2-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-2-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-2-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-2-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-totalDigits-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-3-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-3-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-3-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-3-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-3-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-totalDigits-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-4-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-4-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-4-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-4-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-4-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-totalDigits-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-5-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-5-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-5-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-5-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-totalDigits-5-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ ?line {STRes31,S31} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList32 = [STRes31|STResList31],
+ ?line ITRes139 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList140 = [ITRes139|ITResList139],
+ ?line ITRes140 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList141 = [ITRes140|ITResList140],
+ ?line ITRes141 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList142 = [ITRes141|ITResList141],
+ ?line ITRes142 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList143 = [ITRes142|ITResList142],
+ ?line ITRes143 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList144 = [ITRes143|ITResList143],
+
+
+ ?line {STRes32,S32} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList33 = [STRes32|STResList32],
+ ?line ITRes144 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList145 = [ITRes144|ITResList144],
+ ?line ITRes145 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList146 = [ITRes145|ITResList145],
+ ?line ITRes146 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList147 = [ITRes146|ITResList146],
+ ?line ITRes147 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList148 = [ITRes147|ITResList147],
+ ?line ITRes148 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList149 = [ITRes148|ITResList148],
+
+
+ ?line {STRes33,S33} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList34 = [STRes33|STResList33],
+ ?line ITRes149 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList150 = [ITRes149|ITResList149],
+ ?line ITRes150 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList151 = [ITRes150|ITResList150],
+ ?line ITRes151 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList152 = [ITRes151|ITResList151],
+ ?line ITRes152 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList153 = [ITRes152|ITResList152],
+ ?line ITRes153 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList154 = [ITRes153|ITResList153],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes154 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList155 = [ITRes154|ITResList154],
+ ?line ITRes155 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList156 = [ITRes155|ITResList155],
+ ?line ITRes156 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList157 = [ITRes156|ITResList156],
+ ?line ITRes157 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList158 = [ITRes157|ITResList157],
+ ?line ITRes158 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList159 = [ITRes158|ITResList158],
+
+
+ ?line {STRes35,S35} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList36 = [STRes35|STResList35],
+ ?line ITRes159 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList160 = [ITRes159|ITResList159],
+ ?line ITRes160 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList161 = [ITRes160|ITResList160],
+ ?line ITRes161 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList162 = [ITRes161|ITResList161],
+ ?line ITRes162 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList163 = [ITRes162|ITResList162],
+ ?line ITRes163 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList164 = [ITRes163|ITResList163],
+
+
+ ?line {STRes36,S36} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-integer-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList37 = [STRes36|STResList36],
+ ?line ITRes164 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList165 = [ITRes164|ITResList164],
+ ?line ITRes165 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList166 = [ITRes165|ITResList165],
+ ?line ITRes166 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList167 = [ITRes166|ITResList166],
+ ?line ITRes167 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList168 = [ITRes167|ITResList167],
+ ?line ITRes168 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-integer-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList169 = [ITRes168|ITResList168],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList37,ITResList169).
+
+%% Data type derived by restriction of language by facets
+
+'NISTSchema-language'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-maxLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-maxLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-maxLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList10 = [ITRes9|ITResList9],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-maxLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList15 = [ITRes14|ITResList14],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-maxLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-5-2.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-5-3.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-5-4.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList20 = [ITRes19|ITResList19],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-maxLength-5-5.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-minLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-minLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-minLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-minLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-minLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-5-2.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList43 = [ITRes42|ITResList42],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-5-3.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-5-4.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-minLength-5-5.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList46 = [ITRes45|ITResList45],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-length-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-1-2.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList48 = [ITRes47|ITResList47],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-1-3.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-1-4.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-1-5.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList51 = [ITRes50|ITResList50],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-length-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList53 = [ITRes52|ITResList52],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList56 = [ITRes55|ITResList55],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-length-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList58 = [ITRes57|ITResList57],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList61 = [ITRes60|ITResList60],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-length-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList63 = [ITRes62|ITResList62],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList64 = [ITRes63|ITResList63],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList66 = [ITRes65|ITResList65],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-length-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList69 = [ITRes68|ITResList68],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-length-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList71 = [ITRes70|ITResList70],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList74 = [ITRes73|ITResList73],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList76 = [ITRes75|ITResList75],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList79 = [ITRes78|ITResList78],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList81 = [ITRes80|ITResList80],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList84 = [ITRes83|ITResList83],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList86 = [ITRes85|ITResList85],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList89 = [ITRes88|ITResList88],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList91 = [ITRes90|ITResList90],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList94 = [ITRes93|ITResList93],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList96 = [ITRes95|ITResList95],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList99 = [ITRes98|ITResList98],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList101 = [ITRes100|ITResList100],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList104 = [ITRes103|ITResList103],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList106 = [ITRes105|ITResList105],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList109 = [ITRes108|ITResList108],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList111 = [ITRes110|ITResList110],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList114 = [ITRes113|ITResList113],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList116 = [ITRes115|ITResList115],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList119 = [ITRes118|ITResList118],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList121 = [ITRes120|ITResList120],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-language-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList124 = [ITRes123|ITResList123],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-language-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList126 = [ITRes125|ITResList125],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList26,ITResList126).
+
+%% Data type derived by restriction of long by facets
+
+'NISTSchema-long'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-fractionDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-fractionDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-fractionDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-fractionDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-fractionDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-fractionDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-totalDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-totalDigits-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-2-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-2-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-2-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-2-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-2-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-totalDigits-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-3-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-3-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-3-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-3-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-3-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-totalDigits-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-4-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-4-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-4-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-4-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-4-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-totalDigits-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-5-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-5-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-5-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-5-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-totalDigits-5-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ ?line {STRes31,S31} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList32 = [STRes31|STResList31],
+ ?line ITRes139 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList140 = [ITRes139|ITResList139],
+ ?line ITRes140 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList141 = [ITRes140|ITResList140],
+ ?line ITRes141 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList142 = [ITRes141|ITResList141],
+ ?line ITRes142 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList143 = [ITRes142|ITResList142],
+ ?line ITRes143 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList144 = [ITRes143|ITResList143],
+
+
+ ?line {STRes32,S32} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList33 = [STRes32|STResList32],
+ ?line ITRes144 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList145 = [ITRes144|ITResList144],
+ ?line ITRes145 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList146 = [ITRes145|ITResList145],
+ ?line ITRes146 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList147 = [ITRes146|ITResList146],
+ ?line ITRes147 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList148 = [ITRes147|ITResList147],
+ ?line ITRes148 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList149 = [ITRes148|ITResList148],
+
+
+ ?line {STRes33,S33} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList34 = [STRes33|STResList33],
+ ?line ITRes149 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList150 = [ITRes149|ITResList149],
+ ?line ITRes150 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList151 = [ITRes150|ITResList150],
+ ?line ITRes151 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList152 = [ITRes151|ITResList151],
+ ?line ITRes152 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList153 = [ITRes152|ITResList152],
+ ?line ITRes153 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList154 = [ITRes153|ITResList153],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes154 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList155 = [ITRes154|ITResList154],
+ ?line ITRes155 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList156 = [ITRes155|ITResList155],
+ ?line ITRes156 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList157 = [ITRes156|ITResList156],
+ ?line ITRes157 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList158 = [ITRes157|ITResList157],
+ ?line ITRes158 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList159 = [ITRes158|ITResList158],
+
+
+ ?line {STRes35,S35} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList36 = [STRes35|STResList35],
+ ?line ITRes159 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList160 = [ITRes159|ITResList159],
+ ?line ITRes160 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList161 = [ITRes160|ITResList160],
+ ?line ITRes161 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList162 = [ITRes161|ITResList161],
+ ?line ITRes162 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList163 = [ITRes162|ITResList162],
+ ?line ITRes163 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList164 = [ITRes163|ITResList163],
+
+
+ ?line {STRes36,S36} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-long-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList37 = [STRes36|STResList36],
+ ?line ITRes164 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList165 = [ITRes164|ITResList164],
+ ?line ITRes165 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList166 = [ITRes165|ITResList165],
+ ?line ITRes166 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList167 = [ITRes166|ITResList166],
+ ?line ITRes167 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList168 = [ITRes167|ITResList167],
+ ?line ITRes168 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-long-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList169 = [ITRes168|ITResList168],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList37,ITResList169).
+
+%% Data type derived by restriction of Name by facets
+
+'NISTSchema-Name'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-maxLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-maxLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-maxLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-maxLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-maxLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-5-2.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-5-3.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-5-4.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-maxLength-5-5.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-minLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-minLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-minLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-minLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList42 = [ITRes41|ITResList41],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList43 = [ITRes42|ITResList42],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-minLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-5-2.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-5-3.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList48 = [ITRes47|ITResList47],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-5-4.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-minLength-5-5.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-length-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-1-2.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-1-3.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList53 = [ITRes52|ITResList52],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-1-4.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-1-5.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList55 = [ITRes54|ITResList54],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-length-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList58 = [ITRes57|ITResList57],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList60 = [ITRes59|ITResList59],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-length-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList63 = [ITRes62|ITResList62],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList64 = [ITRes63|ITResList63],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList65 = [ITRes64|ITResList64],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-length-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList69 = [ITRes68|ITResList68],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList70 = [ITRes69|ITResList69],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-length-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList74 = [ITRes73|ITResList73],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-length-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList75 = [ITRes74|ITResList74],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList79 = [ITRes78|ITResList78],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList80 = [ITRes79|ITResList79],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList84 = [ITRes83|ITResList83],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList85 = [ITRes84|ITResList84],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList89 = [ITRes88|ITResList88],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList90 = [ITRes89|ITResList89],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList94 = [ITRes93|ITResList93],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList95 = [ITRes94|ITResList94],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList99 = [ITRes98|ITResList98],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList100 = [ITRes99|ITResList99],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList104 = [ITRes103|ITResList103],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList105 = [ITRes104|ITResList104],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList109 = [ITRes108|ITResList108],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList110 = [ITRes109|ITResList109],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList114 = [ITRes113|ITResList113],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList115 = [ITRes114|ITResList114],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList119 = [ITRes118|ITResList118],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList120 = [ITRes119|ITResList119],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList124 = [ITRes123|ITResList123],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList125 = [ITRes124|ITResList124],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-Name-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList129 = [ITRes128|ITResList128],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-Name-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList130 = [ITRes129|ITResList129],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList26,ITResList130).
+
+%% Data type derived by restriction of NCName by facets
+
+'NISTSchema-NCName'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-maxLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-maxLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-maxLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-maxLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-maxLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-5-2.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-5-3.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-5-4.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-maxLength-5-5.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-minLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-minLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-minLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-minLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList42 = [ITRes41|ITResList41],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList43 = [ITRes42|ITResList42],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-minLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-5-2.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-5-3.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList48 = [ITRes47|ITResList47],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-5-4.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-minLength-5-5.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-length-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-1-2.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-1-3.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList53 = [ITRes52|ITResList52],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-1-4.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-1-5.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList55 = [ITRes54|ITResList54],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-length-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList58 = [ITRes57|ITResList57],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList60 = [ITRes59|ITResList59],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-length-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList63 = [ITRes62|ITResList62],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList64 = [ITRes63|ITResList63],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList65 = [ITRes64|ITResList64],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-length-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList69 = [ITRes68|ITResList68],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList70 = [ITRes69|ITResList69],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-length-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList74 = [ITRes73|ITResList73],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-length-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList75 = [ITRes74|ITResList74],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList79 = [ITRes78|ITResList78],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList80 = [ITRes79|ITResList79],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList84 = [ITRes83|ITResList83],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList85 = [ITRes84|ITResList84],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList89 = [ITRes88|ITResList88],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList90 = [ITRes89|ITResList89],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList94 = [ITRes93|ITResList93],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList95 = [ITRes94|ITResList94],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList99 = [ITRes98|ITResList98],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList100 = [ITRes99|ITResList99],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList104 = [ITRes103|ITResList103],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList105 = [ITRes104|ITResList104],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList109 = [ITRes108|ITResList108],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList110 = [ITRes109|ITResList109],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList114 = [ITRes113|ITResList113],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList115 = [ITRes114|ITResList114],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList119 = [ITRes118|ITResList118],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList120 = [ITRes119|ITResList119],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList124 = [ITRes123|ITResList123],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList125 = [ITRes124|ITResList124],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NCName-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList129 = [ITRes128|ITResList128],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NCName-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList130 = [ITRes129|ITResList129],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList26,ITResList130).
+
+%% Data type derived by restriction of negativeInteger by facets
+
+'NISTSchema-negativeInteger'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-fractionDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-fractionDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-fractionDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-fractionDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-fractionDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-fractionDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-totalDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-totalDigits-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-2-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-2-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-2-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-2-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-2-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-totalDigits-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-3-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-3-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-3-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-3-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-3-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-totalDigits-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-4-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-4-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-4-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-4-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-4-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-totalDigits-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-5-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-5-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-5-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-5-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-totalDigits-5-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ ?line {STRes31,S31} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList32 = [STRes31|STResList31],
+ ?line ITRes139 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList140 = [ITRes139|ITResList139],
+ ?line ITRes140 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList141 = [ITRes140|ITResList140],
+ ?line ITRes141 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList142 = [ITRes141|ITResList141],
+ ?line ITRes142 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList143 = [ITRes142|ITResList142],
+ ?line ITRes143 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList144 = [ITRes143|ITResList143],
+
+
+ ?line {STRes32,S32} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList33 = [STRes32|STResList32],
+ ?line ITRes144 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList145 = [ITRes144|ITResList144],
+ ?line ITRes145 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList146 = [ITRes145|ITResList145],
+ ?line ITRes146 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList147 = [ITRes146|ITResList146],
+ ?line ITRes147 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList148 = [ITRes147|ITResList147],
+ ?line ITRes148 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList149 = [ITRes148|ITResList148],
+
+
+ ?line {STRes33,S33} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList34 = [STRes33|STResList33],
+ ?line ITRes149 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList150 = [ITRes149|ITResList149],
+ ?line ITRes150 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList151 = [ITRes150|ITResList150],
+ ?line ITRes151 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList152 = [ITRes151|ITResList151],
+ ?line ITRes152 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList153 = [ITRes152|ITResList152],
+ ?line ITRes153 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList154 = [ITRes153|ITResList153],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes154 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList155 = [ITRes154|ITResList154],
+ ?line ITRes155 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList156 = [ITRes155|ITResList155],
+ ?line ITRes156 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList157 = [ITRes156|ITResList156],
+ ?line ITRes157 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList158 = [ITRes157|ITResList157],
+ ?line ITRes158 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList159 = [ITRes158|ITResList158],
+
+
+ ?line {STRes35,S35} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList36 = [STRes35|STResList35],
+ ?line ITRes159 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList160 = [ITRes159|ITResList159],
+ ?line ITRes160 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList161 = [ITRes160|ITResList160],
+ ?line ITRes161 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList162 = [ITRes161|ITResList161],
+ ?line ITRes162 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList163 = [ITRes162|ITResList162],
+ ?line ITRes163 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList164 = [ITRes163|ITResList163],
+
+
+ ?line {STRes36,S36} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-negativeInteger-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList37 = [STRes36|STResList36],
+ ?line ITRes164 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList165 = [ITRes164|ITResList164],
+ ?line ITRes165 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList166 = [ITRes165|ITResList165],
+ ?line ITRes166 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList167 = [ITRes166|ITResList166],
+ ?line ITRes167 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList168 = [ITRes167|ITResList167],
+ ?line ITRes168 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-negativeInteger-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList169 = [ITRes168|ITResList168],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList37,ITResList169).
+
+%% Data type derived by restriction of NMTOKEN by facets
+
+'NISTSchema-NMTOKEN'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-maxLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-maxLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-maxLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-maxLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-maxLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-5-2.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-5-3.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-5-4.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-maxLength-5-5.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-minLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-minLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-minLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-minLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList42 = [ITRes41|ITResList41],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList43 = [ITRes42|ITResList42],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-minLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-5-2.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-5-3.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList48 = [ITRes47|ITResList47],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-5-4.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-minLength-5-5.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-length-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-1-2.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-1-3.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList53 = [ITRes52|ITResList52],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-1-4.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-1-5.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList55 = [ITRes54|ITResList54],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-length-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList58 = [ITRes57|ITResList57],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList60 = [ITRes59|ITResList59],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-length-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList63 = [ITRes62|ITResList62],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList64 = [ITRes63|ITResList63],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList65 = [ITRes64|ITResList64],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-length-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList69 = [ITRes68|ITResList68],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList70 = [ITRes69|ITResList69],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-length-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList74 = [ITRes73|ITResList73],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-length-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList75 = [ITRes74|ITResList74],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList79 = [ITRes78|ITResList78],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList80 = [ITRes79|ITResList79],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList84 = [ITRes83|ITResList83],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList85 = [ITRes84|ITResList84],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList89 = [ITRes88|ITResList88],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList90 = [ITRes89|ITResList89],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList94 = [ITRes93|ITResList93],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList95 = [ITRes94|ITResList94],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList99 = [ITRes98|ITResList98],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList100 = [ITRes99|ITResList99],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList104 = [ITRes103|ITResList103],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList105 = [ITRes104|ITResList104],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList109 = [ITRes108|ITResList108],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList110 = [ITRes109|ITResList109],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList114 = [ITRes113|ITResList113],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList115 = [ITRes114|ITResList114],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList118 = [ITRes117|ITResList117],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList119 = [ITRes118|ITResList118],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList123 = [ITRes122|ITResList122],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-NMTOKEN-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList124 = [ITRes123|ITResList123],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-NMTOKEN-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList128 = [ITRes127|ITResList127],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList26,ITResList128).
+
+%% Data type derived by restriction of nonNegativeInteger by facets
+
+'NISTSchema-nonNegativeInteger'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-fractionDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-fractionDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-fractionDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-fractionDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-fractionDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-fractionDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-totalDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-totalDigits-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-2-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-2-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-2-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-2-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-2-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-totalDigits-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-3-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-3-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-3-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-3-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-3-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-totalDigits-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-4-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-4-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-4-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-4-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-4-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-totalDigits-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-5-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-5-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-5-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-5-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-totalDigits-5-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ ?line {STRes31,S31} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList32 = [STRes31|STResList31],
+ ?line ITRes139 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList140 = [ITRes139|ITResList139],
+ ?line ITRes140 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList141 = [ITRes140|ITResList140],
+ ?line ITRes141 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList142 = [ITRes141|ITResList141],
+ ?line ITRes142 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList143 = [ITRes142|ITResList142],
+ ?line ITRes143 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList144 = [ITRes143|ITResList143],
+
+
+ ?line {STRes32,S32} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList33 = [STRes32|STResList32],
+ ?line ITRes144 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList145 = [ITRes144|ITResList144],
+ ?line ITRes145 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList146 = [ITRes145|ITResList145],
+ ?line ITRes146 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList147 = [ITRes146|ITResList146],
+ ?line ITRes147 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList148 = [ITRes147|ITResList147],
+ ?line ITRes148 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList149 = [ITRes148|ITResList148],
+
+
+ ?line {STRes33,S33} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList34 = [STRes33|STResList33],
+ ?line ITRes149 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList150 = [ITRes149|ITResList149],
+ ?line ITRes150 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList151 = [ITRes150|ITResList150],
+ ?line ITRes151 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList152 = [ITRes151|ITResList151],
+ ?line ITRes152 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList153 = [ITRes152|ITResList152],
+ ?line ITRes153 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList154 = [ITRes153|ITResList153],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes154 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList155 = [ITRes154|ITResList154],
+ ?line ITRes155 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList156 = [ITRes155|ITResList155],
+ ?line ITRes156 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList157 = [ITRes156|ITResList156],
+ ?line ITRes157 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList158 = [ITRes157|ITResList157],
+ ?line ITRes158 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList159 = [ITRes158|ITResList158],
+
+
+ ?line {STRes35,S35} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList36 = [STRes35|STResList35],
+ ?line ITRes159 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList160 = [ITRes159|ITResList159],
+ ?line ITRes160 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList161 = [ITRes160|ITResList160],
+ ?line ITRes161 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList162 = [ITRes161|ITResList161],
+ ?line ITRes162 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList163 = [ITRes162|ITResList162],
+ ?line ITRes163 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList164 = [ITRes163|ITResList163],
+
+
+ ?line {STRes36,S36} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonNegativeInteger-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList37 = [STRes36|STResList36],
+ ?line ITRes164 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList165 = [ITRes164|ITResList164],
+ ?line ITRes165 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList166 = [ITRes165|ITResList165],
+ ?line ITRes166 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList167 = [ITRes166|ITResList166],
+ ?line ITRes167 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList168 = [ITRes167|ITResList167],
+ ?line ITRes168 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonNegativeInteger-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList169 = [ITRes168|ITResList168],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList37,ITResList169).
+
+%% Data type derived by restriction of nonPositiveInteger by facets
+
+'NISTSchema-nonPositiveInteger'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-fractionDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-fractionDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-fractionDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-fractionDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-fractionDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-fractionDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-totalDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-totalDigits-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-2-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-2-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-2-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-2-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-2-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-totalDigits-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-3-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-3-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-3-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-3-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-3-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-totalDigits-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-4-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-4-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-4-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-4-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-4-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-totalDigits-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-5-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-5-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-5-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-5-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-totalDigits-5-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ ?line {STRes31,S31} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList32 = [STRes31|STResList31],
+ ?line ITRes139 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList140 = [ITRes139|ITResList139],
+ ?line ITRes140 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList141 = [ITRes140|ITResList140],
+ ?line ITRes141 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList142 = [ITRes141|ITResList141],
+ ?line ITRes142 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList143 = [ITRes142|ITResList142],
+ ?line ITRes143 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList144 = [ITRes143|ITResList143],
+
+
+ ?line {STRes32,S32} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList33 = [STRes32|STResList32],
+ ?line ITRes144 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList145 = [ITRes144|ITResList144],
+ ?line ITRes145 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList146 = [ITRes145|ITResList145],
+ ?line ITRes146 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList147 = [ITRes146|ITResList146],
+ ?line ITRes147 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList148 = [ITRes147|ITResList147],
+ ?line ITRes148 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList149 = [ITRes148|ITResList148],
+
+
+ ?line {STRes33,S33} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList34 = [STRes33|STResList33],
+ ?line ITRes149 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList150 = [ITRes149|ITResList149],
+ ?line ITRes150 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList151 = [ITRes150|ITResList150],
+ ?line ITRes151 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList152 = [ITRes151|ITResList151],
+ ?line ITRes152 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList153 = [ITRes152|ITResList152],
+ ?line ITRes153 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList154 = [ITRes153|ITResList153],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes154 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList155 = [ITRes154|ITResList154],
+ ?line ITRes155 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList156 = [ITRes155|ITResList155],
+ ?line ITRes156 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList157 = [ITRes156|ITResList156],
+ ?line ITRes157 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList158 = [ITRes157|ITResList157],
+ ?line ITRes158 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList159 = [ITRes158|ITResList158],
+
+
+ ?line {STRes35,S35} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList36 = [STRes35|STResList35],
+ ?line ITRes159 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList160 = [ITRes159|ITResList159],
+ ?line ITRes160 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList161 = [ITRes160|ITResList160],
+ ?line ITRes161 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList162 = [ITRes161|ITResList161],
+ ?line ITRes162 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList163 = [ITRes162|ITResList162],
+ ?line ITRes163 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList164 = [ITRes163|ITResList163],
+
+
+ ?line {STRes36,S36} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-nonPositiveInteger-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList37 = [STRes36|STResList36],
+ ?line ITRes164 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList165 = [ITRes164|ITResList164],
+ ?line ITRes165 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList166 = [ITRes165|ITResList165],
+ ?line ITRes166 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList167 = [ITRes166|ITResList166],
+ ?line ITRes167 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList168 = [ITRes167|ITResList167],
+ ?line ITRes168 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-nonPositiveInteger-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList169 = [ITRes168|ITResList168],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList37,ITResList169).
+
+%% Data type derived by restriction of normalizedString by facets
+
+'NISTSchema-normalizedString'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-maxLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-maxLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList5 = [ITRes4|ITResList4],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-maxLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList10 = [ITRes9|ITResList9],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-maxLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList15 = [ITRes14|ITResList14],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-maxLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-5-2.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-5-3.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-5-4.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList20 = [ITRes19|ITResList19],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-maxLength-5-5.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-minLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-minLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-minLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-minLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-minLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-5-2.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList43 = [ITRes42|ITResList42],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-5-3.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-5-4.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-minLength-5-5.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList46 = [ITRes45|ITResList45],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-length-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList47 = [ITRes46|ITResList46],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-length-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList52 = [ITRes51|ITResList51],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-length-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList57 = [ITRes56|ITResList56],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-length-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList62 = [ITRes61|ITResList61],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-length-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList64 = [ITRes63|ITResList63],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-length-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList67 = [ITRes66|ITResList66],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList69 = [ITRes68|ITResList68],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList72 = [ITRes71|ITResList71],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList74 = [ITRes73|ITResList73],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList77 = [ITRes76|ITResList76],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList79 = [ITRes78|ITResList78],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList82 = [ITRes81|ITResList81],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList84 = [ITRes83|ITResList83],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList87 = [ITRes86|ITResList86],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList89 = [ITRes88|ITResList88],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList92 = [ITRes91|ITResList91],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList94 = [ITRes93|ITResList93],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList97 = [ITRes96|ITResList96],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList99 = [ITRes98|ITResList98],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList102 = [ITRes101|ITResList101],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList104 = [ITRes103|ITResList103],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList107 = [ITRes106|ITResList106],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList109 = [ITRes108|ITResList108],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList112 = [ITRes111|ITResList111],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList114 = [ITRes113|ITResList113],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList117 = [ITRes116|ITResList116],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList119 = [ITRes118|ITResList118],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList122 = [ITRes121|ITResList121],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-normalizedString-whiteSpace-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-whiteSpace-2-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-whiteSpace-2-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList124 = [ITRes123|ITResList123],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-whiteSpace-2-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-whiteSpace-2-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-normalizedString-whiteSpace-2-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList127 = [ITRes126|ITResList126],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList27,ITResList127).
+
+%% Data type derived by restriction of positiveInteger by facets
+
+'NISTSchema-positiveInteger'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-fractionDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-fractionDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-fractionDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-fractionDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-fractionDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-fractionDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-totalDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-totalDigits-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-2-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-2-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-2-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-2-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-2-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-totalDigits-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-3-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-3-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-3-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-3-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-3-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-totalDigits-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-4-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-4-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-4-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-4-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-4-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-totalDigits-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-5-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-5-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-5-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-5-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-totalDigits-5-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ ?line {STRes31,S31} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList32 = [STRes31|STResList31],
+ ?line ITRes139 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList140 = [ITRes139|ITResList139],
+ ?line ITRes140 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList141 = [ITRes140|ITResList140],
+ ?line ITRes141 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList142 = [ITRes141|ITResList141],
+ ?line ITRes142 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList143 = [ITRes142|ITResList142],
+ ?line ITRes143 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList144 = [ITRes143|ITResList143],
+
+
+ ?line {STRes32,S32} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList33 = [STRes32|STResList32],
+ ?line ITRes144 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList145 = [ITRes144|ITResList144],
+ ?line ITRes145 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList146 = [ITRes145|ITResList145],
+ ?line ITRes146 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList147 = [ITRes146|ITResList146],
+ ?line ITRes147 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList148 = [ITRes147|ITResList147],
+ ?line ITRes148 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList149 = [ITRes148|ITResList148],
+
+
+ ?line {STRes33,S33} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList34 = [STRes33|STResList33],
+ ?line ITRes149 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList150 = [ITRes149|ITResList149],
+ ?line ITRes150 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList151 = [ITRes150|ITResList150],
+ ?line ITRes151 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList152 = [ITRes151|ITResList151],
+ ?line ITRes152 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList153 = [ITRes152|ITResList152],
+ ?line ITRes153 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList154 = [ITRes153|ITResList153],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes154 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList155 = [ITRes154|ITResList154],
+ ?line ITRes155 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList156 = [ITRes155|ITResList155],
+ ?line ITRes156 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList157 = [ITRes156|ITResList156],
+ ?line ITRes157 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList158 = [ITRes157|ITResList157],
+ ?line ITRes158 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList159 = [ITRes158|ITResList158],
+
+
+ ?line {STRes35,S35} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList36 = [STRes35|STResList35],
+ ?line ITRes159 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList160 = [ITRes159|ITResList159],
+ ?line ITRes160 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList161 = [ITRes160|ITResList160],
+ ?line ITRes161 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList162 = [ITRes161|ITResList161],
+ ?line ITRes162 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList163 = [ITRes162|ITResList162],
+ ?line ITRes163 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList164 = [ITRes163|ITResList163],
+
+
+ ?line {STRes36,S36} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-positiveInteger-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList37 = [STRes36|STResList36],
+ ?line ITRes164 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList165 = [ITRes164|ITResList164],
+ ?line ITRes165 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList166 = [ITRes165|ITResList165],
+ ?line ITRes166 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList167 = [ITRes166|ITResList166],
+ ?line ITRes167 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList168 = [ITRes167|ITResList167],
+ ?line ITRes168 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-positiveInteger-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList169 = [ITRes168|ITResList168],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList37,ITResList169).
+
+%% Data type derived by restriction of QName by facets
+
+'NISTSchema-QName'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-maxLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-maxLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-maxLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-maxLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-maxLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-5-2.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-5-3.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-5-4.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-maxLength-5-5.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList25 = [ITRes24|ITResList24],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-minLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList30 = [ITRes29|ITResList29],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-minLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList35 = [ITRes34|ITResList34],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-minLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList40 = [ITRes39|ITResList39],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-minLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList42 = [ITRes41|ITResList41],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList43 = [ITRes42|ITResList42],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList45 = [ITRes44|ITResList44],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-minLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-5-2.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-5-3.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList48 = [ITRes47|ITResList47],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-5-4.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-minLength-5-5.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList50 = [ITRes49|ITResList49],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-length-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-1-2.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-1-3.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList53 = [ITRes52|ITResList52],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-1-4.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-1-5.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList55 = [ITRes54|ITResList54],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-length-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList58 = [ITRes57|ITResList57],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList60 = [ITRes59|ITResList59],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-length-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList63 = [ITRes62|ITResList62],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList64 = [ITRes63|ITResList63],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList65 = [ITRes64|ITResList64],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-length-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList69 = [ITRes68|ITResList68],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList70 = [ITRes69|ITResList69],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-length-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList74 = [ITRes73|ITResList73],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-length-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList75 = [ITRes74|ITResList74],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList79 = [ITRes78|ITResList78],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList80 = [ITRes79|ITResList79],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList84 = [ITRes83|ITResList83],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList85 = [ITRes84|ITResList84],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList89 = [ITRes88|ITResList88],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList90 = [ITRes89|ITResList89],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList94 = [ITRes93|ITResList93],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList95 = [ITRes94|ITResList94],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList99 = [ITRes98|ITResList98],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList100 = [ITRes99|ITResList99],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList104 = [ITRes103|ITResList103],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList105 = [ITRes104|ITResList104],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList109 = [ITRes108|ITResList108],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList110 = [ITRes109|ITResList109],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList114 = [ITRes113|ITResList113],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList115 = [ITRes114|ITResList114],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList119 = [ITRes118|ITResList118],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList120 = [ITRes119|ITResList119],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList124 = [ITRes123|ITResList123],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList125 = [ITRes124|ITResList124],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-QName-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList129 = [ITRes128|ITResList128],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-QName-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList130 = [ITRes129|ITResList129],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList26,ITResList130).
+
+%% Data type derived by restriction of short by facets
+
+'NISTSchema-short'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-fractionDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-fractionDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-fractionDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-fractionDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-fractionDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-fractionDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-totalDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-totalDigits-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-2-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-2-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-2-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-2-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-2-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-totalDigits-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-3-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-3-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-3-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-3-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-3-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-totalDigits-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-4-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-4-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-4-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-4-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-4-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-totalDigits-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-5-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-5-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-5-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-5-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-totalDigits-5-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ ?line {STRes31,S31} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList32 = [STRes31|STResList31],
+ ?line ITRes139 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList140 = [ITRes139|ITResList139],
+ ?line ITRes140 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList141 = [ITRes140|ITResList140],
+ ?line ITRes141 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList142 = [ITRes141|ITResList141],
+ ?line ITRes142 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList143 = [ITRes142|ITResList142],
+ ?line ITRes143 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList144 = [ITRes143|ITResList143],
+
+
+ ?line {STRes32,S32} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList33 = [STRes32|STResList32],
+ ?line ITRes144 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList145 = [ITRes144|ITResList144],
+ ?line ITRes145 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList146 = [ITRes145|ITResList145],
+ ?line ITRes146 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList147 = [ITRes146|ITResList146],
+ ?line ITRes147 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList148 = [ITRes147|ITResList147],
+ ?line ITRes148 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList149 = [ITRes148|ITResList148],
+
+
+ ?line {STRes33,S33} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList34 = [STRes33|STResList33],
+ ?line ITRes149 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList150 = [ITRes149|ITResList149],
+ ?line ITRes150 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList151 = [ITRes150|ITResList150],
+ ?line ITRes151 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList152 = [ITRes151|ITResList151],
+ ?line ITRes152 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList153 = [ITRes152|ITResList152],
+ ?line ITRes153 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList154 = [ITRes153|ITResList153],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes154 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList155 = [ITRes154|ITResList154],
+ ?line ITRes155 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList156 = [ITRes155|ITResList155],
+ ?line ITRes156 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList157 = [ITRes156|ITResList156],
+ ?line ITRes157 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList158 = [ITRes157|ITResList157],
+ ?line ITRes158 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList159 = [ITRes158|ITResList158],
+
+
+ ?line {STRes35,S35} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList36 = [STRes35|STResList35],
+ ?line ITRes159 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList160 = [ITRes159|ITResList159],
+ ?line ITRes160 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList161 = [ITRes160|ITResList160],
+ ?line ITRes161 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList162 = [ITRes161|ITResList161],
+ ?line ITRes162 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList163 = [ITRes162|ITResList162],
+ ?line ITRes163 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList164 = [ITRes163|ITResList163],
+
+
+ ?line {STRes36,S36} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-short-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList37 = [STRes36|STResList36],
+ ?line ITRes164 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList165 = [ITRes164|ITResList164],
+ ?line ITRes165 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList166 = [ITRes165|ITResList165],
+ ?line ITRes166 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList167 = [ITRes166|ITResList166],
+ ?line ITRes167 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList168 = [ITRes167|ITResList167],
+ ?line ITRes168 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-short-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList169 = [ITRes168|ITResList168],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList37,ITResList169).
+
+%% Data type derived by restriction of string by facets
+
+'NISTSchema-string'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-maxLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-maxLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList5 = [ITRes4|ITResList4],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-maxLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList10 = [ITRes9|ITResList9],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-maxLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList15 = [ITRes14|ITResList14],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-maxLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-5-2.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-5-3.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-5-4.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList20 = [ITRes19|ITResList19],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-maxLength-5-5.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-minLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-minLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-minLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-minLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-minLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-5-2.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList43 = [ITRes42|ITResList42],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-5-3.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-5-4.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-minLength-5-5.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList46 = [ITRes45|ITResList45],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-length-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList47 = [ITRes46|ITResList46],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-length-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList52 = [ITRes51|ITResList51],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-length-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList57 = [ITRes56|ITResList56],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-length-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList62 = [ITRes61|ITResList61],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-length-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList64 = [ITRes63|ITResList63],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-length-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList67 = [ITRes66|ITResList66],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList69 = [ITRes68|ITResList68],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList72 = [ITRes71|ITResList71],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList74 = [ITRes73|ITResList73],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList77 = [ITRes76|ITResList76],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList79 = [ITRes78|ITResList78],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList82 = [ITRes81|ITResList81],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList84 = [ITRes83|ITResList83],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList87 = [ITRes86|ITResList86],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList89 = [ITRes88|ITResList88],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList92 = [ITRes91|ITResList91],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList94 = [ITRes93|ITResList93],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList97 = [ITRes96|ITResList96],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList99 = [ITRes98|ITResList98],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList102 = [ITRes101|ITResList101],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList104 = [ITRes103|ITResList103],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList107 = [ITRes106|ITResList106],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList109 = [ITRes108|ITResList108],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList112 = [ITRes111|ITResList111],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList114 = [ITRes113|ITResList113],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList117 = [ITRes116|ITResList116],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList119 = [ITRes118|ITResList118],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList122 = [ITRes121|ITResList121],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-whiteSpace-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-whiteSpace-2-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-whiteSpace-2-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList124 = [ITRes123|ITResList123],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-whiteSpace-2-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-whiteSpace-2-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-whiteSpace-2-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList127 = [ITRes126|ITResList126],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-string-whiteSpace-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-whiteSpace-3-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-whiteSpace-3-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList129 = [ITRes128|ITResList128],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-whiteSpace-3-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-whiteSpace-3-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-string-whiteSpace-3-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList132 = [ITRes131|ITResList131],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList28,ITResList132).
+
+%% Data type derived by restriction of time by facets
+
+'NISTSchema-time'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-time-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-time-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList31,ITResList139).
+
+%% Data type derived by restriction of token by facets
+
+'NISTSchema-token'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-maxLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-maxLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList5 = [ITRes4|ITResList4],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-maxLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList10 = [ITRes9|ITResList9],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-maxLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList15 = [ITRes14|ITResList14],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-maxLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-5-2.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-5-3.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-5-4.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList20 = [ITRes19|ITResList19],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-maxLength-5-5.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-minLength-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-minLength-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-minLength-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-minLength-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-minLength-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-5-2.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList43 = [ITRes42|ITResList42],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-5-3.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-5-4.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-minLength-5-5.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList46 = [ITRes45|ITResList45],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-length-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList47 = [ITRes46|ITResList46],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-length-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList52 = [ITRes51|ITResList51],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-length-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList57 = [ITRes56|ITResList56],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-length-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList62 = [ITRes61|ITResList61],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-length-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList64 = [ITRes63|ITResList63],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-length-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList67 = [ITRes66|ITResList66],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList69 = [ITRes68|ITResList68],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList72 = [ITRes71|ITResList71],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList74 = [ITRes73|ITResList73],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList77 = [ITRes76|ITResList76],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList79 = [ITRes78|ITResList78],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList82 = [ITRes81|ITResList81],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList84 = [ITRes83|ITResList83],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList87 = [ITRes86|ITResList86],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList89 = [ITRes88|ITResList88],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList92 = [ITRes91|ITResList91],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList94 = [ITRes93|ITResList93],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList97 = [ITRes96|ITResList96],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList99 = [ITRes98|ITResList98],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList102 = [ITRes101|ITResList101],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList104 = [ITRes103|ITResList103],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList107 = [ITRes106|ITResList106],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList109 = [ITRes108|ITResList108],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList112 = [ITRes111|ITResList111],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList114 = [ITRes113|ITResList113],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList117 = [ITRes116|ITResList116],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-token-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList119 = [ITRes118|ITResList118],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-token-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList122 = [ITRes121|ITResList121],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList26,ITResList122).
+
+%% Data type derived by restriction of unsignedByte by facets
+
+'NISTSchema-unsignedByte'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-fractionDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-fractionDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-fractionDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-fractionDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-fractionDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-fractionDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-totalDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-totalDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-totalDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-totalDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-totalDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-totalDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-totalDigits-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-totalDigits-2-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-totalDigits-2-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-totalDigits-2-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-totalDigits-2-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-totalDigits-2-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-totalDigits-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-totalDigits-3-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-totalDigits-3-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-totalDigits-3-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-totalDigits-3-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-totalDigits-3-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ ?line {STRes31,S31} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList32 = [STRes31|STResList31],
+ ?line ITRes139 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList140 = [ITRes139|ITResList139],
+ ?line ITRes140 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList141 = [ITRes140|ITResList140],
+ ?line ITRes141 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList142 = [ITRes141|ITResList141],
+ ?line ITRes142 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList143 = [ITRes142|ITResList142],
+ ?line ITRes143 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList144 = [ITRes143|ITResList143],
+
+
+ ?line {STRes32,S32} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedByte-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList33 = [STRes32|STResList32],
+ ?line ITRes144 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList145 = [ITRes144|ITResList144],
+ ?line ITRes145 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList146 = [ITRes145|ITResList145],
+ ?line ITRes146 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList147 = [ITRes146|ITResList146],
+ ?line ITRes147 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList148 = [ITRes147|ITResList147],
+ ?line ITRes148 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedByte-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList149 = [ITRes148|ITResList148],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList33,ITResList149).
+
+%% Data type derived by restriction of unsignedInt by facets
+
+'NISTSchema-unsignedInt'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-fractionDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-fractionDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-fractionDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-fractionDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-fractionDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-fractionDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-totalDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-totalDigits-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-2-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-2-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-2-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-2-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-2-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-totalDigits-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-3-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-3-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-3-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-3-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-3-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-totalDigits-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-4-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-4-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-4-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-4-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-4-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-totalDigits-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-5-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-5-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-5-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-5-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-totalDigits-5-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ ?line {STRes31,S31} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList32 = [STRes31|STResList31],
+ ?line ITRes139 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList140 = [ITRes139|ITResList139],
+ ?line ITRes140 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList141 = [ITRes140|ITResList140],
+ ?line ITRes141 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList142 = [ITRes141|ITResList141],
+ ?line ITRes142 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList143 = [ITRes142|ITResList142],
+ ?line ITRes143 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList144 = [ITRes143|ITResList143],
+
+
+ ?line {STRes32,S32} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList33 = [STRes32|STResList32],
+ ?line ITRes144 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList145 = [ITRes144|ITResList144],
+ ?line ITRes145 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList146 = [ITRes145|ITResList145],
+ ?line ITRes146 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList147 = [ITRes146|ITResList146],
+ ?line ITRes147 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList148 = [ITRes147|ITResList147],
+ ?line ITRes148 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList149 = [ITRes148|ITResList148],
+
+
+ ?line {STRes33,S33} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList34 = [STRes33|STResList33],
+ ?line ITRes149 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList150 = [ITRes149|ITResList149],
+ ?line ITRes150 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList151 = [ITRes150|ITResList150],
+ ?line ITRes151 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList152 = [ITRes151|ITResList151],
+ ?line ITRes152 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList153 = [ITRes152|ITResList152],
+ ?line ITRes153 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList154 = [ITRes153|ITResList153],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes154 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList155 = [ITRes154|ITResList154],
+ ?line ITRes155 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList156 = [ITRes155|ITResList155],
+ ?line ITRes156 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList157 = [ITRes156|ITResList156],
+ ?line ITRes157 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList158 = [ITRes157|ITResList157],
+ ?line ITRes158 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList159 = [ITRes158|ITResList158],
+
+
+ ?line {STRes35,S35} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList36 = [STRes35|STResList35],
+ ?line ITRes159 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList160 = [ITRes159|ITResList159],
+ ?line ITRes160 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList161 = [ITRes160|ITResList160],
+ ?line ITRes161 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList162 = [ITRes161|ITResList161],
+ ?line ITRes162 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList163 = [ITRes162|ITResList162],
+ ?line ITRes163 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList164 = [ITRes163|ITResList163],
+
+
+ ?line {STRes36,S36} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedInt-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList37 = [STRes36|STResList36],
+ ?line ITRes164 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList165 = [ITRes164|ITResList164],
+ ?line ITRes165 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList166 = [ITRes165|ITResList165],
+ ?line ITRes166 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList167 = [ITRes166|ITResList166],
+ ?line ITRes167 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList168 = [ITRes167|ITResList167],
+ ?line ITRes168 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedInt-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList169 = [ITRes168|ITResList168],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList37,ITResList169).
+
+%% Data type derived by restriction of unsignedLong by facets
+
+'NISTSchema-unsignedLong'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-fractionDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-fractionDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-fractionDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-fractionDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-fractionDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-fractionDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-totalDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-totalDigits-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-2-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-2-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-2-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-2-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-2-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-totalDigits-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-3-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-3-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-3-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-3-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-3-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-totalDigits-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-4-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-4-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-4-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-4-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-4-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-totalDigits-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-5-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-5-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-5-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-5-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-totalDigits-5-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ ?line {STRes31,S31} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList32 = [STRes31|STResList31],
+ ?line ITRes139 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList140 = [ITRes139|ITResList139],
+ ?line ITRes140 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList141 = [ITRes140|ITResList140],
+ ?line ITRes141 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList142 = [ITRes141|ITResList141],
+ ?line ITRes142 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList143 = [ITRes142|ITResList142],
+ ?line ITRes143 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList144 = [ITRes143|ITResList143],
+
+
+ ?line {STRes32,S32} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList33 = [STRes32|STResList32],
+ ?line ITRes144 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList145 = [ITRes144|ITResList144],
+ ?line ITRes145 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList146 = [ITRes145|ITResList145],
+ ?line ITRes146 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList147 = [ITRes146|ITResList146],
+ ?line ITRes147 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList148 = [ITRes147|ITResList147],
+ ?line ITRes148 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList149 = [ITRes148|ITResList148],
+
+
+ ?line {STRes33,S33} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList34 = [STRes33|STResList33],
+ ?line ITRes149 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList150 = [ITRes149|ITResList149],
+ ?line ITRes150 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList151 = [ITRes150|ITResList150],
+ ?line ITRes151 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList152 = [ITRes151|ITResList151],
+ ?line ITRes152 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList153 = [ITRes152|ITResList152],
+ ?line ITRes153 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList154 = [ITRes153|ITResList153],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes154 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList155 = [ITRes154|ITResList154],
+ ?line ITRes155 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList156 = [ITRes155|ITResList155],
+ ?line ITRes156 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList157 = [ITRes156|ITResList156],
+ ?line ITRes157 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList158 = [ITRes157|ITResList157],
+ ?line ITRes158 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList159 = [ITRes158|ITResList158],
+
+
+ ?line {STRes35,S35} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList36 = [STRes35|STResList35],
+ ?line ITRes159 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList160 = [ITRes159|ITResList159],
+ ?line ITRes160 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList161 = [ITRes160|ITResList160],
+ ?line ITRes161 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList162 = [ITRes161|ITResList161],
+ ?line ITRes162 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList163 = [ITRes162|ITResList162],
+ ?line ITRes163 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList164 = [ITRes163|ITResList163],
+
+
+ ?line {STRes36,S36} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedLong-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList37 = [STRes36|STResList36],
+ ?line ITRes164 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList165 = [ITRes164|ITResList164],
+ ?line ITRes165 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList166 = [ITRes165|ITResList165],
+ ?line ITRes166 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList167 = [ITRes166|ITResList166],
+ ?line ITRes167 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList168 = [ITRes167|ITResList167],
+ ?line ITRes168 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedLong-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList169 = [ITRes168|ITResList168],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList37,ITResList169).
+
+%% Data type derived by restriction of unsignedShort by facets
+
+'NISTSchema-unsignedShort'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-minExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ ?line {STRes1,S1} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-minExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList2 = [STRes1|STResList1],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S1),
+ ITResList10 = [ITRes9|ITResList9],
+
+
+ ?line {STRes2,S2} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-minExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList3 = [STRes2|STResList2],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S2),
+ ITResList15 = [ITRes14|ITResList14],
+
+
+ ?line {STRes3,S3} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-minExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList4 = [STRes3|STResList3],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S3),
+ ITResList20 = [ITRes19|ITResList19],
+
+
+ ?line {STRes4,S4} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-minExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList5 = [STRes4|STResList4],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S4),
+ ITResList21 = [ITRes20|ITResList20],
+
+
+ ?line {STRes5,S5} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-minInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList6 = [STRes5|STResList5],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-1-2.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-1-3.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-1-4.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-1-5.xml','./nisttest/NISTTestsAll',valid,S5),
+ ITResList26 = [ITRes25|ITResList25],
+
+
+ ?line {STRes6,S6} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-minInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList7 = [STRes6|STResList6],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S6),
+ ITResList31 = [ITRes30|ITResList30],
+
+
+ ?line {STRes7,S7} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-minInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList8 = [STRes7|STResList7],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList34 = [ITRes33|ITResList33],
+ ?line ITRes34 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList35 = [ITRes34|ITResList34],
+ ?line ITRes35 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S7),
+ ITResList36 = [ITRes35|ITResList35],
+
+
+ ?line {STRes8,S8} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-minInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList9 = [STRes8|STResList8],
+ ?line ITRes36 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList37 = [ITRes36|ITResList36],
+ ?line ITRes37 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList38 = [ITRes37|ITResList37],
+ ?line ITRes38 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList39 = [ITRes38|ITResList38],
+ ?line ITRes39 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList40 = [ITRes39|ITResList39],
+ ?line ITRes40 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S8),
+ ITResList41 = [ITRes40|ITResList40],
+
+
+ ?line {STRes9,S9} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-minInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList10 = [STRes9|STResList9],
+ ?line ITRes41 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-minInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S9),
+ ITResList42 = [ITRes41|ITResList41],
+
+
+ ?line {STRes10,S10} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-maxExclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList11 = [STRes10|STResList10],
+ ?line ITRes42 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S10),
+ ITResList43 = [ITRes42|ITResList42],
+
+
+ ?line {STRes11,S11} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-maxExclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList12 = [STRes11|STResList11],
+ ?line ITRes43 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList44 = [ITRes43|ITResList43],
+ ?line ITRes44 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList45 = [ITRes44|ITResList44],
+ ?line ITRes45 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList46 = [ITRes45|ITResList45],
+ ?line ITRes46 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList47 = [ITRes46|ITResList46],
+ ?line ITRes47 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S11),
+ ITResList48 = [ITRes47|ITResList47],
+
+
+ ?line {STRes12,S12} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-maxExclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList13 = [STRes12|STResList12],
+ ?line ITRes48 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList49 = [ITRes48|ITResList48],
+ ?line ITRes49 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList50 = [ITRes49|ITResList49],
+ ?line ITRes50 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList51 = [ITRes50|ITResList50],
+ ?line ITRes51 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList52 = [ITRes51|ITResList51],
+ ?line ITRes52 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S12),
+ ITResList53 = [ITRes52|ITResList52],
+
+
+ ?line {STRes13,S13} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-maxExclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList14 = [STRes13|STResList13],
+ ?line ITRes53 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList54 = [ITRes53|ITResList53],
+ ?line ITRes54 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList55 = [ITRes54|ITResList54],
+ ?line ITRes55 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList56 = [ITRes55|ITResList55],
+ ?line ITRes56 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList57 = [ITRes56|ITResList56],
+ ?line ITRes57 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S13),
+ ITResList58 = [ITRes57|ITResList57],
+
+
+ ?line {STRes14,S14} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-maxExclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList15 = [STRes14|STResList14],
+ ?line ITRes58 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList59 = [ITRes58|ITResList58],
+ ?line ITRes59 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList60 = [ITRes59|ITResList59],
+ ?line ITRes60 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList61 = [ITRes60|ITResList60],
+ ?line ITRes61 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList62 = [ITRes61|ITResList61],
+ ?line ITRes62 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxExclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S14),
+ ITResList63 = [ITRes62|ITResList62],
+
+
+ ?line {STRes15,S15} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-maxInclusive-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList16 = [STRes15|STResList15],
+ ?line ITRes63 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-1-1.xml','./nisttest/NISTTestsAll',valid,S15),
+ ITResList64 = [ITRes63|ITResList63],
+
+
+ ?line {STRes16,S16} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-maxInclusive-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList17 = [STRes16|STResList16],
+ ?line ITRes64 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-2-1.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList65 = [ITRes64|ITResList64],
+ ?line ITRes65 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-2-2.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList66 = [ITRes65|ITResList65],
+ ?line ITRes66 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-2-3.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList67 = [ITRes66|ITResList66],
+ ?line ITRes67 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-2-4.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList68 = [ITRes67|ITResList67],
+ ?line ITRes68 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-2-5.xml','./nisttest/NISTTestsAll',valid,S16),
+ ITResList69 = [ITRes68|ITResList68],
+
+
+ ?line {STRes17,S17} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-maxInclusive-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList18 = [STRes17|STResList17],
+ ?line ITRes69 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-3-1.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList70 = [ITRes69|ITResList69],
+ ?line ITRes70 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-3-2.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList71 = [ITRes70|ITResList70],
+ ?line ITRes71 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-3-3.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList72 = [ITRes71|ITResList71],
+ ?line ITRes72 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-3-4.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList73 = [ITRes72|ITResList72],
+ ?line ITRes73 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-3-5.xml','./nisttest/NISTTestsAll',valid,S17),
+ ITResList74 = [ITRes73|ITResList73],
+
+
+ ?line {STRes18,S18} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-maxInclusive-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList19 = [STRes18|STResList18],
+ ?line ITRes74 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-4-1.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList75 = [ITRes74|ITResList74],
+ ?line ITRes75 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-4-2.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList76 = [ITRes75|ITResList75],
+ ?line ITRes76 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-4-3.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList77 = [ITRes76|ITResList76],
+ ?line ITRes77 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-4-4.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList78 = [ITRes77|ITResList77],
+ ?line ITRes78 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-4-5.xml','./nisttest/NISTTestsAll',valid,S18),
+ ITResList79 = [ITRes78|ITResList78],
+
+
+ ?line {STRes19,S19} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-maxInclusive-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList20 = [STRes19|STResList19],
+ ?line ITRes79 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-5-1.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList80 = [ITRes79|ITResList79],
+ ?line ITRes80 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-5-2.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList81 = [ITRes80|ITResList80],
+ ?line ITRes81 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-5-3.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList82 = [ITRes81|ITResList81],
+ ?line ITRes82 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-5-4.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList83 = [ITRes82|ITResList82],
+ ?line ITRes83 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-maxInclusive-5-5.xml','./nisttest/NISTTestsAll',valid,S19),
+ ITResList84 = [ITRes83|ITResList83],
+
+
+ ?line {STRes20,S20} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-fractionDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList21 = [STRes20|STResList20],
+ ?line ITRes84 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-fractionDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList85 = [ITRes84|ITResList84],
+ ?line ITRes85 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-fractionDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList86 = [ITRes85|ITResList85],
+ ?line ITRes86 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-fractionDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList87 = [ITRes86|ITResList86],
+ ?line ITRes87 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-fractionDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList88 = [ITRes87|ITResList87],
+ ?line ITRes88 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-fractionDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S20),
+ ITResList89 = [ITRes88|ITResList88],
+
+
+ ?line {STRes21,S21} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-totalDigits-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList22 = [STRes21|STResList21],
+ ?line ITRes89 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-1-1.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList90 = [ITRes89|ITResList89],
+ ?line ITRes90 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-1-2.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList91 = [ITRes90|ITResList90],
+ ?line ITRes91 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-1-3.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList92 = [ITRes91|ITResList91],
+ ?line ITRes92 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-1-4.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList93 = [ITRes92|ITResList92],
+ ?line ITRes93 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-1-5.xml','./nisttest/NISTTestsAll',valid,S21),
+ ITResList94 = [ITRes93|ITResList93],
+
+
+ ?line {STRes22,S22} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-totalDigits-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList23 = [STRes22|STResList22],
+ ?line ITRes94 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-2-1.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList95 = [ITRes94|ITResList94],
+ ?line ITRes95 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-2-2.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList96 = [ITRes95|ITResList95],
+ ?line ITRes96 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-2-3.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList97 = [ITRes96|ITResList96],
+ ?line ITRes97 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-2-4.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList98 = [ITRes97|ITResList97],
+ ?line ITRes98 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-2-5.xml','./nisttest/NISTTestsAll',valid,S22),
+ ITResList99 = [ITRes98|ITResList98],
+
+
+ ?line {STRes23,S23} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-totalDigits-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList24 = [STRes23|STResList23],
+ ?line ITRes99 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-3-1.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList100 = [ITRes99|ITResList99],
+ ?line ITRes100 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-3-2.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList101 = [ITRes100|ITResList100],
+ ?line ITRes101 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-3-3.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList102 = [ITRes101|ITResList101],
+ ?line ITRes102 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-3-4.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList103 = [ITRes102|ITResList102],
+ ?line ITRes103 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-3-5.xml','./nisttest/NISTTestsAll',valid,S23),
+ ITResList104 = [ITRes103|ITResList103],
+
+
+ ?line {STRes24,S24} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-totalDigits-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList25 = [STRes24|STResList24],
+ ?line ITRes104 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-4-1.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList105 = [ITRes104|ITResList104],
+ ?line ITRes105 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-4-2.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList106 = [ITRes105|ITResList105],
+ ?line ITRes106 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-4-3.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList107 = [ITRes106|ITResList106],
+ ?line ITRes107 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-4-4.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList108 = [ITRes107|ITResList107],
+ ?line ITRes108 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-4-5.xml','./nisttest/NISTTestsAll',valid,S24),
+ ITResList109 = [ITRes108|ITResList108],
+
+
+ ?line {STRes25,S25} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-totalDigits-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList26 = [STRes25|STResList25],
+ ?line ITRes109 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-5-1.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList110 = [ITRes109|ITResList109],
+ ?line ITRes110 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-5-2.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList111 = [ITRes110|ITResList110],
+ ?line ITRes111 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-5-3.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList112 = [ITRes111|ITResList111],
+ ?line ITRes112 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-5-4.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList113 = [ITRes112|ITResList112],
+ ?line ITRes113 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-totalDigits-5-5.xml','./nisttest/NISTTestsAll',valid,S25),
+ ITResList114 = [ITRes113|ITResList113],
+
+
+ ?line {STRes26,S26} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-pattern-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList27 = [STRes26|STResList26],
+ ?line ITRes114 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-1-1.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList115 = [ITRes114|ITResList114],
+ ?line ITRes115 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-1-2.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList116 = [ITRes115|ITResList115],
+ ?line ITRes116 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-1-3.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList117 = [ITRes116|ITResList116],
+ ?line ITRes117 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-1-4.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList118 = [ITRes117|ITResList117],
+ ?line ITRes118 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-1-5.xml','./nisttest/NISTTestsAll',valid,S26),
+ ITResList119 = [ITRes118|ITResList118],
+
+
+ ?line {STRes27,S27} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-pattern-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList28 = [STRes27|STResList27],
+ ?line ITRes119 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-2-1.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList120 = [ITRes119|ITResList119],
+ ?line ITRes120 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-2-2.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList121 = [ITRes120|ITResList120],
+ ?line ITRes121 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-2-3.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList122 = [ITRes121|ITResList121],
+ ?line ITRes122 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-2-4.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList123 = [ITRes122|ITResList122],
+ ?line ITRes123 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-2-5.xml','./nisttest/NISTTestsAll',valid,S27),
+ ITResList124 = [ITRes123|ITResList123],
+
+
+ ?line {STRes28,S28} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-pattern-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList29 = [STRes28|STResList28],
+ ?line ITRes124 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-3-1.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList125 = [ITRes124|ITResList124],
+ ?line ITRes125 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-3-2.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList126 = [ITRes125|ITResList125],
+ ?line ITRes126 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-3-3.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList127 = [ITRes126|ITResList126],
+ ?line ITRes127 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-3-4.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList128 = [ITRes127|ITResList127],
+ ?line ITRes128 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-3-5.xml','./nisttest/NISTTestsAll',valid,S28),
+ ITResList129 = [ITRes128|ITResList128],
+
+
+ ?line {STRes29,S29} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-pattern-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList30 = [STRes29|STResList29],
+ ?line ITRes129 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-4-1.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList130 = [ITRes129|ITResList129],
+ ?line ITRes130 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-4-2.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList131 = [ITRes130|ITResList130],
+ ?line ITRes131 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-4-3.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList132 = [ITRes131|ITResList131],
+ ?line ITRes132 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-4-4.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList133 = [ITRes132|ITResList132],
+ ?line ITRes133 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-4-5.xml','./nisttest/NISTTestsAll',valid,S29),
+ ITResList134 = [ITRes133|ITResList133],
+
+
+ ?line {STRes30,S30} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-pattern-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList31 = [STRes30|STResList30],
+ ?line ITRes134 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-5-1.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList135 = [ITRes134|ITResList134],
+ ?line ITRes135 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-5-2.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList136 = [ITRes135|ITResList135],
+ ?line ITRes136 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-5-3.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList137 = [ITRes136|ITResList136],
+ ?line ITRes137 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-5-4.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList138 = [ITRes137|ITResList137],
+ ?line ITRes138 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-pattern-5-5.xml','./nisttest/NISTTestsAll',valid,S30),
+ ITResList139 = [ITRes138|ITResList138],
+
+
+ ?line {STRes31,S31} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-enumeration-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList32 = [STRes31|STResList31],
+ ?line ITRes139 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-1-1.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList140 = [ITRes139|ITResList139],
+ ?line ITRes140 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-1-2.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList141 = [ITRes140|ITResList140],
+ ?line ITRes141 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-1-3.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList142 = [ITRes141|ITResList141],
+ ?line ITRes142 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-1-4.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList143 = [ITRes142|ITResList142],
+ ?line ITRes143 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-1-5.xml','./nisttest/NISTTestsAll',valid,S31),
+ ITResList144 = [ITRes143|ITResList143],
+
+
+ ?line {STRes32,S32} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-enumeration-2.xsd','./nisttest/NISTTestsAll',valid),
+ STResList33 = [STRes32|STResList32],
+ ?line ITRes144 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-2-1.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList145 = [ITRes144|ITResList144],
+ ?line ITRes145 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-2-2.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList146 = [ITRes145|ITResList145],
+ ?line ITRes146 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-2-3.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList147 = [ITRes146|ITResList146],
+ ?line ITRes147 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-2-4.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList148 = [ITRes147|ITResList147],
+ ?line ITRes148 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-2-5.xml','./nisttest/NISTTestsAll',valid,S32),
+ ITResList149 = [ITRes148|ITResList148],
+
+
+ ?line {STRes33,S33} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-enumeration-3.xsd','./nisttest/NISTTestsAll',valid),
+ STResList34 = [STRes33|STResList33],
+ ?line ITRes149 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-3-1.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList150 = [ITRes149|ITResList149],
+ ?line ITRes150 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-3-2.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList151 = [ITRes150|ITResList150],
+ ?line ITRes151 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-3-3.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList152 = [ITRes151|ITResList151],
+ ?line ITRes152 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-3-4.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList153 = [ITRes152|ITResList152],
+ ?line ITRes153 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-3-5.xml','./nisttest/NISTTestsAll',valid,S33),
+ ITResList154 = [ITRes153|ITResList153],
+
+
+ ?line {STRes34,S34} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-enumeration-4.xsd','./nisttest/NISTTestsAll',valid),
+ STResList35 = [STRes34|STResList34],
+ ?line ITRes154 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-4-1.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList155 = [ITRes154|ITResList154],
+ ?line ITRes155 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-4-2.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList156 = [ITRes155|ITResList155],
+ ?line ITRes156 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-4-3.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList157 = [ITRes156|ITResList156],
+ ?line ITRes157 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-4-4.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList158 = [ITRes157|ITResList157],
+ ?line ITRes158 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-4-5.xml','./nisttest/NISTTestsAll',valid,S34),
+ ITResList159 = [ITRes158|ITResList158],
+
+
+ ?line {STRes35,S35} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-enumeration-5.xsd','./nisttest/NISTTestsAll',valid),
+ STResList36 = [STRes35|STResList35],
+ ?line ITRes159 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-5-1.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList160 = [ITRes159|ITResList159],
+ ?line ITRes160 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-5-2.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList161 = [ITRes160|ITResList160],
+ ?line ITRes161 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-5-3.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList162 = [ITRes161|ITResList161],
+ ?line ITRes162 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-5-4.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList163 = [ITRes162|ITResList162],
+ ?line ITRes163 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-enumeration-5-5.xml','./nisttest/NISTTestsAll',valid,S35),
+ ITResList164 = [ITRes163|ITResList163],
+
+
+ ?line {STRes36,S36} = xmerl_xsd_lib:schema_test(Config,'./nisttest/NISTTestsAll/NISTSchema-unsignedShort-whiteSpace-1.xsd','./nisttest/NISTTestsAll',valid),
+ STResList37 = [STRes36|STResList36],
+ ?line ITRes164 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-whiteSpace-1-1.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList165 = [ITRes164|ITResList164],
+ ?line ITRes165 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-whiteSpace-1-2.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList166 = [ITRes165|ITResList165],
+ ?line ITRes166 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-whiteSpace-1-3.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList167 = [ITRes166|ITResList166],
+ ?line ITRes167 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-whiteSpace-1-4.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList168 = [ITRes167|ITResList167],
+ ?line ITRes168 = xmerl_xsd_lib:instance_test(Config,'./nisttest/NISTTestsAll/NISTXML-unsignedShort-whiteSpace-1-5.xml','./nisttest/NISTTestsAll',valid,S36),
+ ITResList169 = [ITRes168|ITResList168],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList37,ITResList169).
+
diff --git a/lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE_data/nist_failed_cases.log b/lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE_data/nist_failed_cases.log
new file mode 100644
index 0000000000..e10b6463fe
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE_data/nist_failed_cases.log
@@ -0,0 +1,894 @@
+{'NISTSchema-anyURI',{["NISTXML-anyURI-maxLength-1-5.xml",
+ "NISTXML-anyURI-maxLength-1-4.xml",
+ "NISTXML-anyURI-maxLength-1-3.xml",
+ "NISTXML-anyURI-maxLength-1-2.xml",
+ "NISTXML-anyURI-maxLength-1-1.xml"],["NISTSchema-anyURI-maxLength-1.xsd"]}}.
+{'NISTSchema-base64Binary',{["NISTXML-base64Binary-length-5-5.xml",
+ "NISTXML-base64Binary-length-5-4.xml",
+ "NISTXML-base64Binary-length-5-3.xml",
+ "NISTXML-base64Binary-length-5-2.xml",
+ "NISTXML-base64Binary-length-5-1.xml",
+ "NISTXML-base64Binary-length-4-5.xml",
+ "NISTXML-base64Binary-length-4-4.xml",
+ "NISTXML-base64Binary-length-4-3.xml",
+ "NISTXML-base64Binary-length-4-2.xml",
+ "NISTXML-base64Binary-length-4-1.xml",
+ "NISTXML-base64Binary-length-3-5.xml",
+ "NISTXML-base64Binary-length-3-4.xml",
+ "NISTXML-base64Binary-length-3-3.xml",
+ "NISTXML-base64Binary-length-3-2.xml",
+ "NISTXML-base64Binary-length-3-1.xml",
+ "NISTXML-base64Binary-length-2-5.xml",
+ "NISTXML-base64Binary-length-2-4.xml",
+ "NISTXML-base64Binary-length-2-3.xml",
+ "NISTXML-base64Binary-length-2-2.xml",
+ "NISTXML-base64Binary-length-2-1.xml",
+ "NISTXML-base64Binary-length-1-5.xml",
+ "NISTXML-base64Binary-length-1-4.xml",
+ "NISTXML-base64Binary-length-1-3.xml",
+ "NISTXML-base64Binary-length-1-2.xml",
+ "NISTXML-base64Binary-length-1-1.xml",
+ "NISTXML-base64Binary-maxLength-5-5.xml",
+ "NISTXML-base64Binary-maxLength-5-4.xml",
+ "NISTXML-base64Binary-maxLength-4-5.xml",
+ "NISTXML-base64Binary-maxLength-4-4.xml",
+ "NISTXML-base64Binary-maxLength-3-5.xml",
+ "NISTXML-base64Binary-maxLength-3-4.xml",
+ "NISTXML-base64Binary-maxLength-2-5.xml",
+ "NISTXML-base64Binary-maxLength-2-4.xml",
+ "NISTXML-base64Binary-maxLength-1-5.xml",
+ "NISTXML-base64Binary-maxLength-1-4.xml",
+ "NISTXML-base64Binary-maxLength-1-3.xml",
+ "NISTXML-base64Binary-maxLength-1-2.xml",
+ "NISTXML-base64Binary-maxLength-1-1.xml"],[]}}.
+{'NISTSchema-date-',{["NISTXML-date-maxInclusive-5-5.xml",
+ "NISTXML-date-maxInclusive-5-4.xml",
+ "NISTXML-date-maxInclusive-5-3.xml",
+ "NISTXML-date-maxInclusive-5-2.xml",
+ "NISTXML-date-maxInclusive-5-1.xml",
+ "NISTXML-date-maxInclusive-4-5.xml",
+ "NISTXML-date-maxInclusive-4-4.xml",
+ "NISTXML-date-maxInclusive-4-3.xml",
+ "NISTXML-date-maxInclusive-4-2.xml",
+ "NISTXML-date-maxInclusive-4-1.xml",
+ "NISTXML-date-maxInclusive-3-5.xml",
+ "NISTXML-date-maxInclusive-3-4.xml",
+ "NISTXML-date-maxInclusive-3-3.xml",
+ "NISTXML-date-maxInclusive-3-2.xml",
+ "NISTXML-date-maxInclusive-3-1.xml",
+ "NISTXML-date-maxInclusive-2-5.xml",
+ "NISTXML-date-maxInclusive-2-4.xml",
+ "NISTXML-date-maxInclusive-2-3.xml",
+ "NISTXML-date-maxInclusive-2-2.xml",
+ "NISTXML-date-maxInclusive-2-1.xml",
+ "NISTXML-date-maxInclusive-1-1.xml",
+ "NISTXML-date-maxExclusive-5-5.xml",
+ "NISTXML-date-maxExclusive-5-4.xml",
+ "NISTXML-date-maxExclusive-5-3.xml",
+ "NISTXML-date-maxExclusive-5-2.xml",
+ "NISTXML-date-maxExclusive-5-1.xml",
+ "NISTXML-date-maxExclusive-4-5.xml",
+ "NISTXML-date-maxExclusive-4-4.xml",
+ "NISTXML-date-maxExclusive-4-3.xml",
+ "NISTXML-date-maxExclusive-4-2.xml",
+ "NISTXML-date-maxExclusive-4-1.xml",
+ "NISTXML-date-maxExclusive-3-5.xml",
+ "NISTXML-date-maxExclusive-3-4.xml",
+ "NISTXML-date-maxExclusive-3-3.xml",
+ "NISTXML-date-maxExclusive-3-2.xml",
+ "NISTXML-date-maxExclusive-3-1.xml",
+ "NISTXML-date-maxExclusive-2-5.xml",
+ "NISTXML-date-maxExclusive-2-4.xml",
+ "NISTXML-date-maxExclusive-2-3.xml",
+ "NISTXML-date-maxExclusive-2-2.xml",
+ "NISTXML-date-maxExclusive-2-1.xml",
+ "NISTXML-date-maxExclusive-1-1.xml",
+ "NISTXML-date-minInclusive-5-1.xml",
+ "NISTXML-date-minInclusive-4-5.xml",
+ "NISTXML-date-minInclusive-4-4.xml",
+ "NISTXML-date-minInclusive-4-3.xml",
+ "NISTXML-date-minInclusive-4-2.xml",
+ "NISTXML-date-minInclusive-4-1.xml",
+ "NISTXML-date-minInclusive-3-5.xml",
+ "NISTXML-date-minInclusive-3-4.xml",
+ "NISTXML-date-minInclusive-3-3.xml",
+ "NISTXML-date-minInclusive-3-2.xml",
+ "NISTXML-date-minInclusive-3-1.xml",
+ "NISTXML-date-minInclusive-2-5.xml",
+ "NISTXML-date-minInclusive-2-4.xml",
+ "NISTXML-date-minInclusive-2-3.xml",
+ "NISTXML-date-minInclusive-2-2.xml",
+ "NISTXML-date-minInclusive-2-1.xml",
+ "NISTXML-date-minInclusive-1-5.xml",
+ "NISTXML-date-minInclusive-1-4.xml",
+ "NISTXML-date-minInclusive-1-3.xml",
+ "NISTXML-date-minInclusive-1-2.xml",
+ "NISTXML-date-minInclusive-1-1.xml",
+ "NISTXML-date-minExclusive-5-1.xml",
+ "NISTXML-date-minExclusive-4-5.xml",
+ "NISTXML-date-minExclusive-4-4.xml",
+ "NISTXML-date-minExclusive-4-3.xml",
+ "NISTXML-date-minExclusive-4-2.xml",
+ "NISTXML-date-minExclusive-4-1.xml",
+ "NISTXML-date-minExclusive-3-5.xml",
+ "NISTXML-date-minExclusive-3-4.xml",
+ "NISTXML-date-minExclusive-3-3.xml",
+ "NISTXML-date-minExclusive-3-2.xml",
+ "NISTXML-date-minExclusive-3-1.xml",
+ "NISTXML-date-minExclusive-2-5.xml",
+ "NISTXML-date-minExclusive-2-4.xml",
+ "NISTXML-date-minExclusive-2-3.xml",
+ "NISTXML-date-minExclusive-2-2.xml",
+ "NISTXML-date-minExclusive-2-1.xml",
+ "NISTXML-date-minExclusive-1-5.xml",
+ "NISTXML-date-minExclusive-1-4.xml",
+ "NISTXML-date-minExclusive-1-3.xml",
+ "NISTXML-date-minExclusive-1-2.xml",
+ "NISTXML-date-minExclusive-1-1.xml"],[]}}.
+{'NISTSchema-decimal',{["NISTXML-decimal-maxExclusive-5-5.xml",
+ "NISTXML-decimal-maxExclusive-4-5.xml",
+ "NISTXML-decimal-maxExclusive-3-5.xml",
+ "NISTXML-decimal-maxExclusive-2-5.xml",
+ "NISTXML-decimal-maxExclusive-1-1.xml",
+ "NISTXML-decimal-minExclusive-5-1.xml",
+ "NISTXML-decimal-minExclusive-4-5.xml",
+ "NISTXML-decimal-minExclusive-4-4.xml",
+ "NISTXML-decimal-minExclusive-4-1.xml",
+ "NISTXML-decimal-minExclusive-3-1.xml",
+ "NISTXML-decimal-minExclusive-2-1.xml",
+ "NISTXML-decimal-minExclusive-1-1.xml"],[]}}.
+{'NISTSchema-double',{["NISTXML-double-maxInclusive-5-5.xml",
+ "NISTXML-double-maxInclusive-5-4.xml",
+ "NISTXML-double-maxInclusive-5-3.xml",
+ "NISTXML-double-maxInclusive-5-2.xml",
+ "NISTXML-double-maxInclusive-5-1.xml",
+ "NISTXML-double-maxInclusive-4-5.xml",
+ "NISTXML-double-maxInclusive-4-4.xml",
+ "NISTXML-double-maxInclusive-4-3.xml",
+ "NISTXML-double-maxInclusive-4-2.xml",
+ "NISTXML-double-maxInclusive-4-1.xml",
+ "NISTXML-double-maxInclusive-3-5.xml",
+ "NISTXML-double-maxInclusive-3-4.xml",
+ "NISTXML-double-maxInclusive-3-3.xml",
+ "NISTXML-double-maxInclusive-3-2.xml",
+ "NISTXML-double-maxInclusive-3-1.xml",
+ "NISTXML-double-maxInclusive-2-5.xml",
+ "NISTXML-double-maxInclusive-2-4.xml",
+ "NISTXML-double-maxInclusive-2-3.xml",
+ "NISTXML-double-maxInclusive-2-2.xml",
+ "NISTXML-double-maxInclusive-2-1.xml",
+ "NISTXML-double-maxExclusive-5-5.xml",
+ "NISTXML-double-maxExclusive-5-4.xml",
+ "NISTXML-double-maxExclusive-5-3.xml",
+ "NISTXML-double-maxExclusive-5-2.xml",
+ "NISTXML-double-maxExclusive-5-1.xml",
+ "NISTXML-double-maxExclusive-4-5.xml",
+ "NISTXML-double-maxExclusive-4-4.xml",
+ "NISTXML-double-maxExclusive-4-3.xml",
+ "NISTXML-double-maxExclusive-4-2.xml",
+ "NISTXML-double-maxExclusive-4-1.xml",
+ "NISTXML-double-maxExclusive-3-5.xml",
+ "NISTXML-double-maxExclusive-3-4.xml",
+ "NISTXML-double-maxExclusive-3-3.xml",
+ "NISTXML-double-maxExclusive-3-2.xml",
+ "NISTXML-double-maxExclusive-3-1.xml",
+ "NISTXML-double-maxExclusive-2-5.xml",
+ "NISTXML-double-maxExclusive-2-4.xml",
+ "NISTXML-double-maxExclusive-2-3.xml",
+ "NISTXML-double-maxExclusive-2-2.xml",
+ "NISTXML-double-maxExclusive-2-1.xml",
+ "NISTXML-double-maxExclusive-1-1.xml",
+ "NISTXML-double-minInclusive-4-5.xml",
+ "NISTXML-double-minInclusive-4-4.xml",
+ "NISTXML-double-minInclusive-4-3.xml",
+ "NISTXML-double-minInclusive-4-2.xml",
+ "NISTXML-double-minInclusive-3-5.xml",
+ "NISTXML-double-minInclusive-3-4.xml",
+ "NISTXML-double-minInclusive-3-3.xml",
+ "NISTXML-double-minInclusive-3-2.xml",
+ "NISTXML-double-minInclusive-2-5.xml",
+ "NISTXML-double-minInclusive-2-4.xml",
+ "NISTXML-double-minInclusive-2-3.xml",
+ "NISTXML-double-minInclusive-2-2.xml",
+ "NISTXML-double-minInclusive-1-5.xml",
+ "NISTXML-double-minInclusive-1-4.xml",
+ "NISTXML-double-minInclusive-1-3.xml",
+ "NISTXML-double-minInclusive-1-2.xml",
+ "NISTXML-double-minExclusive-5-1.xml",
+ "NISTXML-double-minExclusive-4-5.xml",
+ "NISTXML-double-minExclusive-4-4.xml",
+ "NISTXML-double-minExclusive-4-3.xml",
+ "NISTXML-double-minExclusive-3-5.xml",
+ "NISTXML-double-minExclusive-3-4.xml",
+ "NISTXML-double-minExclusive-3-3.xml",
+ "NISTXML-double-minExclusive-3-2.xml",
+ "NISTXML-double-minExclusive-3-1.xml",
+ "NISTXML-double-minExclusive-2-5.xml",
+ "NISTXML-double-minExclusive-2-4.xml",
+ "NISTXML-double-minExclusive-2-3.xml",
+ "NISTXML-double-minExclusive-2-2.xml",
+ "NISTXML-double-minExclusive-2-1.xml",
+ "NISTXML-double-minExclusive-1-5.xml",
+ "NISTXML-double-minExclusive-1-4.xml",
+ "NISTXML-double-minExclusive-1-3.xml",
+ "NISTXML-double-minExclusive-1-2.xml",
+ "NISTXML-double-minExclusive-1-1.xml"],[]}}.
+{'NISTSchema-gDay',{["NISTXML-gDay-maxInclusive-5-5.xml",
+ "NISTXML-gDay-maxInclusive-5-4.xml",
+ "NISTXML-gDay-maxInclusive-5-3.xml",
+ "NISTXML-gDay-maxInclusive-5-2.xml",
+ "NISTXML-gDay-maxInclusive-5-1.xml",
+ "NISTXML-gDay-maxInclusive-4-1.xml",
+ "NISTXML-gDay-maxInclusive-3-5.xml",
+ "NISTXML-gDay-maxInclusive-3-4.xml",
+ "NISTXML-gDay-maxInclusive-3-3.xml",
+ "NISTXML-gDay-maxInclusive-3-2.xml",
+ "NISTXML-gDay-maxInclusive-3-1.xml",
+ "NISTXML-gDay-maxInclusive-2-5.xml",
+ "NISTXML-gDay-maxInclusive-2-4.xml",
+ "NISTXML-gDay-maxInclusive-2-3.xml",
+ "NISTXML-gDay-maxInclusive-2-2.xml",
+ "NISTXML-gDay-maxInclusive-2-1.xml",
+ "NISTXML-gDay-maxInclusive-1-1.xml",
+ "NISTXML-gDay-maxExclusive-5-5.xml",
+ "NISTXML-gDay-maxExclusive-5-4.xml",
+ "NISTXML-gDay-maxExclusive-5-3.xml",
+ "NISTXML-gDay-maxExclusive-5-2.xml",
+ "NISTXML-gDay-maxExclusive-5-1.xml",
+ "NISTXML-gDay-maxExclusive-4-5.xml",
+ "NISTXML-gDay-maxExclusive-4-4.xml",
+ "NISTXML-gDay-maxExclusive-4-3.xml",
+ "NISTXML-gDay-maxExclusive-4-2.xml",
+ "NISTXML-gDay-maxExclusive-4-1.xml",
+ "NISTXML-gDay-maxExclusive-3-5.xml",
+ "NISTXML-gDay-maxExclusive-3-4.xml",
+ "NISTXML-gDay-maxExclusive-3-3.xml",
+ "NISTXML-gDay-maxExclusive-3-2.xml",
+ "NISTXML-gDay-maxExclusive-3-1.xml",
+ "NISTXML-gDay-maxExclusive-2-5.xml",
+ "NISTXML-gDay-maxExclusive-2-4.xml",
+ "NISTXML-gDay-maxExclusive-2-3.xml",
+ "NISTXML-gDay-maxExclusive-2-2.xml",
+ "NISTXML-gDay-maxExclusive-2-1.xml",
+ "NISTXML-gDay-maxExclusive-1-1.xml",
+ "NISTXML-gDay-minInclusive-5-1.xml",
+ "NISTXML-gDay-minInclusive-4-5.xml",
+ "NISTXML-gDay-minInclusive-4-4.xml",
+ "NISTXML-gDay-minInclusive-4-3.xml",
+ "NISTXML-gDay-minInclusive-4-2.xml",
+ "NISTXML-gDay-minInclusive-4-1.xml",
+ "NISTXML-gDay-minInclusive-3-5.xml",
+ "NISTXML-gDay-minInclusive-3-4.xml",
+ "NISTXML-gDay-minInclusive-3-3.xml",
+ "NISTXML-gDay-minInclusive-3-2.xml",
+ "NISTXML-gDay-minInclusive-3-1.xml",
+ "NISTXML-gDay-minInclusive-2-5.xml",
+ "NISTXML-gDay-minInclusive-2-4.xml",
+ "NISTXML-gDay-minInclusive-2-3.xml",
+ "NISTXML-gDay-minInclusive-2-2.xml",
+ "NISTXML-gDay-minInclusive-2-1.xml",
+ "NISTXML-gDay-minInclusive-1-5.xml",
+ "NISTXML-gDay-minInclusive-1-4.xml",
+ "NISTXML-gDay-minInclusive-1-3.xml",
+ "NISTXML-gDay-minInclusive-1-2.xml",
+ "NISTXML-gDay-minInclusive-1-1.xml",
+ "NISTXML-gDay-minExclusive-5-1.xml",
+ "NISTXML-gDay-minExclusive-4-5.xml",
+ "NISTXML-gDay-minExclusive-4-4.xml",
+ "NISTXML-gDay-minExclusive-4-3.xml",
+ "NISTXML-gDay-minExclusive-4-2.xml",
+ "NISTXML-gDay-minExclusive-4-1.xml",
+ "NISTXML-gDay-minExclusive-3-5.xml",
+ "NISTXML-gDay-minExclusive-3-4.xml",
+ "NISTXML-gDay-minExclusive-3-3.xml",
+ "NISTXML-gDay-minExclusive-3-2.xml",
+ "NISTXML-gDay-minExclusive-3-1.xml",
+ "NISTXML-gDay-minExclusive-2-5.xml",
+ "NISTXML-gDay-minExclusive-2-4.xml",
+ "NISTXML-gDay-minExclusive-2-3.xml",
+ "NISTXML-gDay-minExclusive-2-2.xml",
+ "NISTXML-gDay-minExclusive-2-1.xml",
+ "NISTXML-gDay-minExclusive-1-5.xml",
+ "NISTXML-gDay-minExclusive-1-4.xml",
+ "NISTXML-gDay-minExclusive-1-3.xml",
+ "NISTXML-gDay-minExclusive-1-2.xml",
+ "NISTXML-gDay-minExclusive-1-1.xml"],[]}}.
+{'NISTSchema-gMonth-',{["NISTXML-gMonth-whiteSpace-1-5.xml",
+ "NISTXML-gMonth-whiteSpace-1-4.xml",
+ "NISTXML-gMonth-whiteSpace-1-3.xml",
+ "NISTXML-gMonth-whiteSpace-1-2.xml",
+ "NISTXML-gMonth-whiteSpace-1-1.xml",
+ "NISTXML-gMonth-enumeration-5-5.xml",
+ "NISTXML-gMonth-enumeration-5-4.xml",
+ "NISTXML-gMonth-enumeration-5-3.xml",
+ "NISTXML-gMonth-enumeration-5-2.xml",
+ "NISTXML-gMonth-enumeration-5-1.xml",
+ "NISTXML-gMonth-enumeration-4-5.xml",
+ "NISTXML-gMonth-enumeration-4-4.xml",
+ "NISTXML-gMonth-enumeration-4-3.xml",
+ "NISTXML-gMonth-enumeration-4-2.xml",
+ "NISTXML-gMonth-enumeration-4-1.xml",
+ "NISTXML-gMonth-enumeration-3-5.xml",
+ "NISTXML-gMonth-enumeration-3-4.xml",
+ "NISTXML-gMonth-enumeration-3-3.xml",
+ "NISTXML-gMonth-enumeration-3-2.xml",
+ "NISTXML-gMonth-enumeration-3-1.xml",
+ "NISTXML-gMonth-enumeration-2-5.xml",
+ "NISTXML-gMonth-enumeration-2-4.xml",
+ "NISTXML-gMonth-enumeration-2-3.xml",
+ "NISTXML-gMonth-enumeration-2-2.xml",
+ "NISTXML-gMonth-enumeration-2-1.xml",
+ "NISTXML-gMonth-enumeration-1-5.xml",
+ "NISTXML-gMonth-enumeration-1-4.xml",
+ "NISTXML-gMonth-enumeration-1-3.xml",
+ "NISTXML-gMonth-enumeration-1-2.xml",
+ "NISTXML-gMonth-enumeration-1-1.xml",
+ "NISTXML-gMonth-pattern-5-5.xml",
+ "NISTXML-gMonth-pattern-5-4.xml",
+ "NISTXML-gMonth-pattern-5-3.xml",
+ "NISTXML-gMonth-pattern-5-2.xml",
+ "NISTXML-gMonth-pattern-5-1.xml",
+ "NISTXML-gMonth-pattern-4-5.xml",
+ "NISTXML-gMonth-pattern-4-4.xml",
+ "NISTXML-gMonth-pattern-4-3.xml",
+ "NISTXML-gMonth-pattern-4-2.xml",
+ "NISTXML-gMonth-pattern-4-1.xml",
+ "NISTXML-gMonth-pattern-3-5.xml",
+ "NISTXML-gMonth-pattern-3-4.xml",
+ "NISTXML-gMonth-pattern-3-3.xml",
+ "NISTXML-gMonth-pattern-3-2.xml",
+ "NISTXML-gMonth-pattern-3-1.xml",
+ "NISTXML-gMonth-pattern-2-5.xml",
+ "NISTXML-gMonth-pattern-2-4.xml",
+ "NISTXML-gMonth-pattern-2-3.xml",
+ "NISTXML-gMonth-pattern-2-2.xml",
+ "NISTXML-gMonth-pattern-2-1.xml",
+ "NISTXML-gMonth-pattern-1-5.xml",
+ "NISTXML-gMonth-pattern-1-4.xml",
+ "NISTXML-gMonth-pattern-1-3.xml",
+ "NISTXML-gMonth-pattern-1-2.xml",
+ "NISTXML-gMonth-pattern-1-1.xml",
+ "NISTXML-gMonth-maxInclusive-5-5.xml",
+ "NISTXML-gMonth-maxInclusive-5-4.xml",
+ "NISTXML-gMonth-maxInclusive-5-3.xml",
+ "NISTXML-gMonth-maxInclusive-5-2.xml",
+ "NISTXML-gMonth-maxInclusive-5-1.xml",
+ "NISTXML-gMonth-maxInclusive-4-5.xml",
+ "NISTXML-gMonth-maxInclusive-4-4.xml",
+ "NISTXML-gMonth-maxInclusive-4-3.xml",
+ "NISTXML-gMonth-maxInclusive-4-2.xml",
+ "NISTXML-gMonth-maxInclusive-4-1.xml",
+ "NISTXML-gMonth-maxInclusive-3-5.xml",
+ "NISTXML-gMonth-maxInclusive-3-4.xml",
+ "NISTXML-gMonth-maxInclusive-3-3.xml",
+ "NISTXML-gMonth-maxInclusive-3-2.xml",
+ "NISTXML-gMonth-maxInclusive-3-1.xml",
+ "NISTXML-gMonth-maxInclusive-2-5.xml",
+ "NISTXML-gMonth-maxInclusive-2-4.xml",
+ "NISTXML-gMonth-maxInclusive-2-3.xml",
+ "NISTXML-gMonth-maxInclusive-2-2.xml",
+ "NISTXML-gMonth-maxInclusive-2-1.xml",
+ "NISTXML-gMonth-maxInclusive-1-1.xml",
+ "NISTXML-gMonth-maxExclusive-5-5.xml",
+ "NISTXML-gMonth-maxExclusive-5-4.xml",
+ "NISTXML-gMonth-maxExclusive-5-3.xml",
+ "NISTXML-gMonth-maxExclusive-5-2.xml",
+ "NISTXML-gMonth-maxExclusive-5-1.xml",
+ "NISTXML-gMonth-maxExclusive-4-5.xml",
+ "NISTXML-gMonth-maxExclusive-4-4.xml",
+ "NISTXML-gMonth-maxExclusive-4-3.xml",
+ "NISTXML-gMonth-maxExclusive-4-2.xml",
+ "NISTXML-gMonth-maxExclusive-4-1.xml",
+ "NISTXML-gMonth-maxExclusive-3-5.xml",
+ "NISTXML-gMonth-maxExclusive-3-4.xml",
+ "NISTXML-gMonth-maxExclusive-3-3.xml",
+ "NISTXML-gMonth-maxExclusive-3-2.xml",
+ "NISTXML-gMonth-maxExclusive-3-1.xml",
+ "NISTXML-gMonth-maxExclusive-2-5.xml",
+ "NISTXML-gMonth-maxExclusive-2-4.xml",
+ "NISTXML-gMonth-maxExclusive-2-3.xml",
+ "NISTXML-gMonth-maxExclusive-2-2.xml",
+ "NISTXML-gMonth-maxExclusive-2-1.xml",
+ "NISTXML-gMonth-maxExclusive-1-1.xml",
+ "NISTXML-gMonth-minInclusive-5-1.xml",
+ "NISTXML-gMonth-minInclusive-4-5.xml",
+ "NISTXML-gMonth-minInclusive-4-4.xml",
+ "NISTXML-gMonth-minInclusive-4-3.xml",
+ "NISTXML-gMonth-minInclusive-4-2.xml",
+ "NISTXML-gMonth-minInclusive-4-1.xml",
+ "NISTXML-gMonth-minInclusive-3-5.xml",
+ "NISTXML-gMonth-minInclusive-3-4.xml",
+ "NISTXML-gMonth-minInclusive-3-3.xml",
+ "NISTXML-gMonth-minInclusive-3-2.xml",
+ "NISTXML-gMonth-minInclusive-3-1.xml",
+ "NISTXML-gMonth-minInclusive-2-5.xml",
+ "NISTXML-gMonth-minInclusive-2-4.xml",
+ "NISTXML-gMonth-minInclusive-2-3.xml",
+ "NISTXML-gMonth-minInclusive-2-2.xml",
+ "NISTXML-gMonth-minInclusive-2-1.xml",
+ "NISTXML-gMonth-minInclusive-1-5.xml",
+ "NISTXML-gMonth-minInclusive-1-4.xml",
+ "NISTXML-gMonth-minInclusive-1-3.xml",
+ "NISTXML-gMonth-minInclusive-1-2.xml",
+ "NISTXML-gMonth-minInclusive-1-1.xml",
+ "NISTXML-gMonth-minExclusive-5-1.xml",
+ "NISTXML-gMonth-minExclusive-4-5.xml",
+ "NISTXML-gMonth-minExclusive-4-4.xml",
+ "NISTXML-gMonth-minExclusive-4-3.xml",
+ "NISTXML-gMonth-minExclusive-4-2.xml",
+ "NISTXML-gMonth-minExclusive-4-1.xml",
+ "NISTXML-gMonth-minExclusive-3-5.xml",
+ "NISTXML-gMonth-minExclusive-3-4.xml",
+ "NISTXML-gMonth-minExclusive-3-3.xml",
+ "NISTXML-gMonth-minExclusive-3-2.xml",
+ "NISTXML-gMonth-minExclusive-3-1.xml",
+ "NISTXML-gMonth-minExclusive-2-5.xml",
+ "NISTXML-gMonth-minExclusive-2-4.xml",
+ "NISTXML-gMonth-minExclusive-2-3.xml",
+ "NISTXML-gMonth-minExclusive-2-2.xml",
+ "NISTXML-gMonth-minExclusive-2-1.xml",
+ "NISTXML-gMonth-minExclusive-1-5.xml",
+ "NISTXML-gMonth-minExclusive-1-4.xml",
+ "NISTXML-gMonth-minExclusive-1-3.xml",
+ "NISTXML-gMonth-minExclusive-1-2.xml",
+ "NISTXML-gMonth-minExclusive-1-1.xml"],[]}}.
+{'NISTSchema-gMonthDay',{["NISTXML-gMonthDay-maxInclusive-5-5.xml",
+ "NISTXML-gMonthDay-maxInclusive-5-4.xml",
+ "NISTXML-gMonthDay-maxInclusive-5-3.xml",
+ "NISTXML-gMonthDay-maxInclusive-5-2.xml",
+ "NISTXML-gMonthDay-maxInclusive-5-1.xml",
+ "NISTXML-gMonthDay-maxInclusive-4-5.xml",
+ "NISTXML-gMonthDay-maxInclusive-4-4.xml",
+ "NISTXML-gMonthDay-maxInclusive-4-3.xml",
+ "NISTXML-gMonthDay-maxInclusive-4-2.xml",
+ "NISTXML-gMonthDay-maxInclusive-4-1.xml",
+ "NISTXML-gMonthDay-maxInclusive-3-5.xml",
+ "NISTXML-gMonthDay-maxInclusive-3-4.xml",
+ "NISTXML-gMonthDay-maxInclusive-3-3.xml",
+ "NISTXML-gMonthDay-maxInclusive-3-2.xml",
+ "NISTXML-gMonthDay-maxInclusive-3-1.xml",
+ "NISTXML-gMonthDay-maxInclusive-2-5.xml",
+ "NISTXML-gMonthDay-maxInclusive-2-4.xml",
+ "NISTXML-gMonthDay-maxInclusive-2-3.xml",
+ "NISTXML-gMonthDay-maxInclusive-2-2.xml",
+ "NISTXML-gMonthDay-maxInclusive-2-1.xml",
+ "NISTXML-gMonthDay-maxInclusive-1-1.xml",
+ "NISTXML-gMonthDay-maxExclusive-5-5.xml",
+ "NISTXML-gMonthDay-maxExclusive-5-4.xml",
+ "NISTXML-gMonthDay-maxExclusive-5-3.xml",
+ "NISTXML-gMonthDay-maxExclusive-5-2.xml",
+ "NISTXML-gMonthDay-maxExclusive-5-1.xml",
+ "NISTXML-gMonthDay-maxExclusive-4-5.xml",
+ "NISTXML-gMonthDay-maxExclusive-4-4.xml",
+ "NISTXML-gMonthDay-maxExclusive-4-3.xml",
+ "NISTXML-gMonthDay-maxExclusive-4-2.xml",
+ "NISTXML-gMonthDay-maxExclusive-4-1.xml",
+ "NISTXML-gMonthDay-maxExclusive-3-5.xml",
+ "NISTXML-gMonthDay-maxExclusive-3-4.xml",
+ "NISTXML-gMonthDay-maxExclusive-3-3.xml",
+ "NISTXML-gMonthDay-maxExclusive-3-2.xml",
+ "NISTXML-gMonthDay-maxExclusive-3-1.xml",
+ "NISTXML-gMonthDay-maxExclusive-2-5.xml",
+ "NISTXML-gMonthDay-maxExclusive-2-4.xml",
+ "NISTXML-gMonthDay-maxExclusive-2-3.xml",
+ "NISTXML-gMonthDay-maxExclusive-2-2.xml",
+ "NISTXML-gMonthDay-maxExclusive-2-1.xml",
+ "NISTXML-gMonthDay-maxExclusive-1-1.xml",
+ "NISTXML-gMonthDay-minInclusive-5-1.xml",
+ "NISTXML-gMonthDay-minInclusive-4-5.xml",
+ "NISTXML-gMonthDay-minInclusive-4-4.xml",
+ "NISTXML-gMonthDay-minInclusive-4-3.xml",
+ "NISTXML-gMonthDay-minInclusive-4-2.xml",
+ "NISTXML-gMonthDay-minInclusive-4-1.xml",
+ "NISTXML-gMonthDay-minInclusive-3-5.xml",
+ "NISTXML-gMonthDay-minInclusive-3-4.xml",
+ "NISTXML-gMonthDay-minInclusive-3-3.xml",
+ "NISTXML-gMonthDay-minInclusive-3-2.xml",
+ "NISTXML-gMonthDay-minInclusive-3-1.xml",
+ "NISTXML-gMonthDay-minInclusive-2-5.xml",
+ "NISTXML-gMonthDay-minInclusive-2-4.xml",
+ "NISTXML-gMonthDay-minInclusive-2-3.xml",
+ "NISTXML-gMonthDay-minInclusive-2-2.xml",
+ "NISTXML-gMonthDay-minInclusive-2-1.xml",
+ "NISTXML-gMonthDay-minInclusive-1-5.xml",
+ "NISTXML-gMonthDay-minInclusive-1-4.xml",
+ "NISTXML-gMonthDay-minInclusive-1-3.xml",
+ "NISTXML-gMonthDay-minInclusive-1-2.xml",
+ "NISTXML-gMonthDay-minInclusive-1-1.xml",
+ "NISTXML-gMonthDay-minExclusive-5-1.xml",
+ "NISTXML-gMonthDay-minExclusive-4-5.xml",
+ "NISTXML-gMonthDay-minExclusive-4-4.xml",
+ "NISTXML-gMonthDay-minExclusive-4-3.xml",
+ "NISTXML-gMonthDay-minExclusive-4-2.xml",
+ "NISTXML-gMonthDay-minExclusive-4-1.xml",
+ "NISTXML-gMonthDay-minExclusive-3-5.xml",
+ "NISTXML-gMonthDay-minExclusive-3-4.xml",
+ "NISTXML-gMonthDay-minExclusive-3-3.xml",
+ "NISTXML-gMonthDay-minExclusive-3-2.xml",
+ "NISTXML-gMonthDay-minExclusive-3-1.xml",
+ "NISTXML-gMonthDay-minExclusive-2-5.xml",
+ "NISTXML-gMonthDay-minExclusive-2-4.xml",
+ "NISTXML-gMonthDay-minExclusive-2-3.xml",
+ "NISTXML-gMonthDay-minExclusive-2-2.xml",
+ "NISTXML-gMonthDay-minExclusive-2-1.xml",
+ "NISTXML-gMonthDay-minExclusive-1-5.xml",
+ "NISTXML-gMonthDay-minExclusive-1-4.xml",
+ "NISTXML-gMonthDay-minExclusive-1-3.xml",
+ "NISTXML-gMonthDay-minExclusive-1-2.xml",
+ "NISTXML-gMonthDay-minExclusive-1-1.xml"],[]}}.
+{'NISTSchema-gYear-',{["NISTXML-gYear-maxInclusive-5-5.xml",
+ "NISTXML-gYear-maxInclusive-5-4.xml",
+ "NISTXML-gYear-maxInclusive-5-3.xml",
+ "NISTXML-gYear-maxInclusive-5-2.xml",
+ "NISTXML-gYear-maxInclusive-5-1.xml",
+ "NISTXML-gYear-maxInclusive-4-5.xml",
+ "NISTXML-gYear-maxInclusive-4-4.xml",
+ "NISTXML-gYear-maxInclusive-4-3.xml",
+ "NISTXML-gYear-maxInclusive-4-2.xml",
+ "NISTXML-gYear-maxInclusive-4-1.xml",
+ "NISTXML-gYear-maxInclusive-3-5.xml",
+ "NISTXML-gYear-maxInclusive-3-4.xml",
+ "NISTXML-gYear-maxInclusive-3-3.xml",
+ "NISTXML-gYear-maxInclusive-3-2.xml",
+ "NISTXML-gYear-maxInclusive-3-1.xml",
+ "NISTXML-gYear-maxInclusive-2-1.xml",
+ "NISTXML-gYear-maxInclusive-1-1.xml",
+ "NISTXML-gYear-maxExclusive-5-5.xml",
+ "NISTXML-gYear-maxExclusive-5-4.xml",
+ "NISTXML-gYear-maxExclusive-5-3.xml",
+ "NISTXML-gYear-maxExclusive-5-2.xml",
+ "NISTXML-gYear-maxExclusive-5-1.xml",
+ "NISTXML-gYear-maxExclusive-4-5.xml",
+ "NISTXML-gYear-maxExclusive-4-4.xml",
+ "NISTXML-gYear-maxExclusive-4-3.xml",
+ "NISTXML-gYear-maxExclusive-4-2.xml",
+ "NISTXML-gYear-maxExclusive-4-1.xml",
+ "NISTXML-gYear-maxExclusive-3-5.xml",
+ "NISTXML-gYear-maxExclusive-3-4.xml",
+ "NISTXML-gYear-maxExclusive-3-3.xml",
+ "NISTXML-gYear-maxExclusive-3-2.xml",
+ "NISTXML-gYear-maxExclusive-3-1.xml",
+ "NISTXML-gYear-maxExclusive-2-5.xml",
+ "NISTXML-gYear-maxExclusive-2-4.xml",
+ "NISTXML-gYear-maxExclusive-2-3.xml",
+ "NISTXML-gYear-maxExclusive-2-2.xml",
+ "NISTXML-gYear-maxExclusive-2-1.xml",
+ "NISTXML-gYear-maxExclusive-1-1.xml",
+ "NISTXML-gYear-minInclusive-5-1.xml",
+ "NISTXML-gYear-minInclusive-4-5.xml",
+ "NISTXML-gYear-minInclusive-4-4.xml",
+ "NISTXML-gYear-minInclusive-4-3.xml",
+ "NISTXML-gYear-minInclusive-4-2.xml",
+ "NISTXML-gYear-minInclusive-4-1.xml",
+ "NISTXML-gYear-minInclusive-3-5.xml",
+ "NISTXML-gYear-minInclusive-3-4.xml",
+ "NISTXML-gYear-minInclusive-3-3.xml",
+ "NISTXML-gYear-minInclusive-3-2.xml",
+ "NISTXML-gYear-minInclusive-3-1.xml",
+ "NISTXML-gYear-minInclusive-2-5.xml",
+ "NISTXML-gYear-minInclusive-2-4.xml",
+ "NISTXML-gYear-minInclusive-2-3.xml",
+ "NISTXML-gYear-minInclusive-2-2.xml",
+ "NISTXML-gYear-minInclusive-2-1.xml",
+ "NISTXML-gYear-minInclusive-1-5.xml",
+ "NISTXML-gYear-minInclusive-1-4.xml",
+ "NISTXML-gYear-minInclusive-1-3.xml",
+ "NISTXML-gYear-minInclusive-1-2.xml",
+ "NISTXML-gYear-minInclusive-1-1.xml",
+ "NISTXML-gYear-minExclusive-5-1.xml",
+ "NISTXML-gYear-minExclusive-4-5.xml",
+ "NISTXML-gYear-minExclusive-4-4.xml",
+ "NISTXML-gYear-minExclusive-4-3.xml",
+ "NISTXML-gYear-minExclusive-4-2.xml",
+ "NISTXML-gYear-minExclusive-4-1.xml",
+ "NISTXML-gYear-minExclusive-3-5.xml",
+ "NISTXML-gYear-minExclusive-3-4.xml",
+ "NISTXML-gYear-minExclusive-3-3.xml",
+ "NISTXML-gYear-minExclusive-3-2.xml",
+ "NISTXML-gYear-minExclusive-3-1.xml",
+ "NISTXML-gYear-minExclusive-2-5.xml",
+ "NISTXML-gYear-minExclusive-2-4.xml",
+ "NISTXML-gYear-minExclusive-2-3.xml",
+ "NISTXML-gYear-minExclusive-2-2.xml",
+ "NISTXML-gYear-minExclusive-2-1.xml",
+ "NISTXML-gYear-minExclusive-1-5.xml",
+ "NISTXML-gYear-minExclusive-1-4.xml",
+ "NISTXML-gYear-minExclusive-1-3.xml",
+ "NISTXML-gYear-minExclusive-1-2.xml",
+ "NISTXML-gYear-minExclusive-1-1.xml"],[]}}.
+{'NISTSchema-gYearMonth',{["NISTXML-gYearMonth-maxInclusive-5-5.xml",
+ "NISTXML-gYearMonth-maxInclusive-5-4.xml",
+ "NISTXML-gYearMonth-maxInclusive-5-3.xml",
+ "NISTXML-gYearMonth-maxInclusive-5-2.xml",
+ "NISTXML-gYearMonth-maxInclusive-5-1.xml",
+ "NISTXML-gYearMonth-maxInclusive-4-5.xml",
+ "NISTXML-gYearMonth-maxInclusive-4-4.xml",
+ "NISTXML-gYearMonth-maxInclusive-4-3.xml",
+ "NISTXML-gYearMonth-maxInclusive-4-2.xml",
+ "NISTXML-gYearMonth-maxInclusive-4-1.xml",
+ "NISTXML-gYearMonth-maxInclusive-3-5.xml",
+ "NISTXML-gYearMonth-maxInclusive-3-4.xml",
+ "NISTXML-gYearMonth-maxInclusive-3-3.xml",
+ "NISTXML-gYearMonth-maxInclusive-3-2.xml",
+ "NISTXML-gYearMonth-maxInclusive-3-1.xml",
+ "NISTXML-gYearMonth-maxInclusive-2-5.xml",
+ "NISTXML-gYearMonth-maxInclusive-2-4.xml",
+ "NISTXML-gYearMonth-maxInclusive-2-3.xml",
+ "NISTXML-gYearMonth-maxInclusive-2-2.xml",
+ "NISTXML-gYearMonth-maxInclusive-2-1.xml",
+ "NISTXML-gYearMonth-maxInclusive-1-1.xml",
+ "NISTXML-gYearMonth-maxExclusive-5-5.xml",
+ "NISTXML-gYearMonth-maxExclusive-5-4.xml",
+ "NISTXML-gYearMonth-maxExclusive-5-3.xml",
+ "NISTXML-gYearMonth-maxExclusive-5-2.xml",
+ "NISTXML-gYearMonth-maxExclusive-5-1.xml",
+ "NISTXML-gYearMonth-maxExclusive-4-5.xml",
+ "NISTXML-gYearMonth-maxExclusive-4-4.xml",
+ "NISTXML-gYearMonth-maxExclusive-4-3.xml",
+ "NISTXML-gYearMonth-maxExclusive-4-2.xml",
+ "NISTXML-gYearMonth-maxExclusive-4-1.xml",
+ "NISTXML-gYearMonth-maxExclusive-3-5.xml",
+ "NISTXML-gYearMonth-maxExclusive-3-4.xml",
+ "NISTXML-gYearMonth-maxExclusive-3-3.xml",
+ "NISTXML-gYearMonth-maxExclusive-3-2.xml",
+ "NISTXML-gYearMonth-maxExclusive-3-1.xml",
+ "NISTXML-gYearMonth-maxExclusive-2-5.xml",
+ "NISTXML-gYearMonth-maxExclusive-2-4.xml",
+ "NISTXML-gYearMonth-maxExclusive-2-3.xml",
+ "NISTXML-gYearMonth-maxExclusive-2-2.xml",
+ "NISTXML-gYearMonth-maxExclusive-2-1.xml",
+ "NISTXML-gYearMonth-maxExclusive-1-1.xml",
+ "NISTXML-gYearMonth-minInclusive-5-1.xml",
+ "NISTXML-gYearMonth-minInclusive-4-5.xml",
+ "NISTXML-gYearMonth-minInclusive-4-4.xml",
+ "NISTXML-gYearMonth-minInclusive-4-3.xml",
+ "NISTXML-gYearMonth-minInclusive-4-2.xml",
+ "NISTXML-gYearMonth-minInclusive-4-1.xml",
+ "NISTXML-gYearMonth-minInclusive-3-5.xml",
+ "NISTXML-gYearMonth-minInclusive-3-4.xml",
+ "NISTXML-gYearMonth-minInclusive-3-3.xml",
+ "NISTXML-gYearMonth-minInclusive-3-2.xml",
+ "NISTXML-gYearMonth-minInclusive-3-1.xml",
+ "NISTXML-gYearMonth-minInclusive-2-5.xml",
+ "NISTXML-gYearMonth-minInclusive-2-4.xml",
+ "NISTXML-gYearMonth-minInclusive-2-3.xml",
+ "NISTXML-gYearMonth-minInclusive-2-2.xml",
+ "NISTXML-gYearMonth-minInclusive-2-1.xml",
+ "NISTXML-gYearMonth-minInclusive-1-5.xml",
+ "NISTXML-gYearMonth-minInclusive-1-4.xml",
+ "NISTXML-gYearMonth-minInclusive-1-3.xml",
+ "NISTXML-gYearMonth-minInclusive-1-2.xml",
+ "NISTXML-gYearMonth-minInclusive-1-1.xml",
+ "NISTXML-gYearMonth-minExclusive-5-1.xml",
+ "NISTXML-gYearMonth-minExclusive-4-5.xml",
+ "NISTXML-gYearMonth-minExclusive-4-4.xml",
+ "NISTXML-gYearMonth-minExclusive-4-3.xml",
+ "NISTXML-gYearMonth-minExclusive-4-2.xml",
+ "NISTXML-gYearMonth-minExclusive-4-1.xml",
+ "NISTXML-gYearMonth-minExclusive-3-5.xml",
+ "NISTXML-gYearMonth-minExclusive-3-4.xml",
+ "NISTXML-gYearMonth-minExclusive-3-3.xml",
+ "NISTXML-gYearMonth-minExclusive-3-2.xml",
+ "NISTXML-gYearMonth-minExclusive-3-1.xml",
+ "NISTXML-gYearMonth-minExclusive-2-5.xml",
+ "NISTXML-gYearMonth-minExclusive-2-4.xml",
+ "NISTXML-gYearMonth-minExclusive-2-3.xml",
+ "NISTXML-gYearMonth-minExclusive-2-2.xml",
+ "NISTXML-gYearMonth-minExclusive-2-1.xml",
+ "NISTXML-gYearMonth-minExclusive-1-5.xml",
+ "NISTXML-gYearMonth-minExclusive-1-4.xml",
+ "NISTXML-gYearMonth-minExclusive-1-3.xml",
+ "NISTXML-gYearMonth-minExclusive-1-2.xml",
+ "NISTXML-gYearMonth-minExclusive-1-1.xml"],[]}}.
+{'NISTSchema-hexBinary',{["NISTXML-hexBinary-length-5-5.xml",
+ "NISTXML-hexBinary-length-5-4.xml",
+ "NISTXML-hexBinary-length-5-3.xml",
+ "NISTXML-hexBinary-length-5-2.xml",
+ "NISTXML-hexBinary-length-5-1.xml",
+ "NISTXML-hexBinary-length-4-5.xml",
+ "NISTXML-hexBinary-length-4-4.xml",
+ "NISTXML-hexBinary-length-4-3.xml",
+ "NISTXML-hexBinary-length-4-2.xml",
+ "NISTXML-hexBinary-length-4-1.xml",
+ "NISTXML-hexBinary-length-3-5.xml",
+ "NISTXML-hexBinary-length-3-4.xml",
+ "NISTXML-hexBinary-length-3-3.xml",
+ "NISTXML-hexBinary-length-3-2.xml",
+ "NISTXML-hexBinary-length-3-1.xml",
+ "NISTXML-hexBinary-length-2-5.xml",
+ "NISTXML-hexBinary-length-2-4.xml",
+ "NISTXML-hexBinary-length-2-3.xml",
+ "NISTXML-hexBinary-length-2-2.xml",
+ "NISTXML-hexBinary-length-2-1.xml",
+ "NISTXML-hexBinary-length-1-5.xml",
+ "NISTXML-hexBinary-length-1-4.xml",
+ "NISTXML-hexBinary-length-1-3.xml",
+ "NISTXML-hexBinary-length-1-2.xml",
+ "NISTXML-hexBinary-length-1-1.xml",
+ "NISTXML-hexBinary-maxLength-5-5.xml",
+ "NISTXML-hexBinary-maxLength-5-4.xml",
+ "NISTXML-hexBinary-maxLength-4-5.xml",
+ "NISTXML-hexBinary-maxLength-4-4.xml",
+ "NISTXML-hexBinary-maxLength-3-5.xml",
+ "NISTXML-hexBinary-maxLength-3-4.xml",
+ "NISTXML-hexBinary-maxLength-2-5.xml",
+ "NISTXML-hexBinary-maxLength-2-4.xml",
+ "NISTXML-hexBinary-maxLength-2-3.xml",
+ "NISTXML-hexBinary-maxLength-1-5.xml",
+ "NISTXML-hexBinary-maxLength-1-4.xml",
+ "NISTXML-hexBinary-maxLength-1-3.xml",
+ "NISTXML-hexBinary-maxLength-1-2.xml",
+ "NISTXML-hexBinary-maxLength-1-1.xml"],[]}}.
+{'NISTSchema-negativeInteger',{["NISTXML-negativeInteger-totalDigits-5-5.xml",
+ "NISTXML-negativeInteger-totalDigits-4-5.xml",
+ "NISTXML-negativeInteger-totalDigits-3-5.xml",
+ "NISTXML-negativeInteger-totalDigits-2-5.xml",
+ "NISTXML-negativeInteger-totalDigits-1-5.xml",
+ "NISTXML-negativeInteger-totalDigits-1-4.xml",
+ "NISTXML-negativeInteger-totalDigits-1-3.xml",
+ "NISTXML-negativeInteger-totalDigits-1-2.xml",
+ "NISTXML-negativeInteger-totalDigits-1-1.xml"],[]}}.
+{'NISTSchema-nonPositiveInteger',{["NISTXML-nonPositiveInteger-totalDigits-5-5.xml",
+ "NISTXML-nonPositiveInteger-totalDigits-4-5.xml",
+ "NISTXML-nonPositiveInteger-totalDigits-3-5.xml",
+ "NISTXML-nonPositiveInteger-totalDigits-2-5.xml",
+ "NISTXML-nonPositiveInteger-totalDigits-1-5.xml",
+ "NISTXML-nonPositiveInteger-totalDigits-1-4.xml",
+ "NISTXML-nonPositiveInteger-totalDigits-1-3.xml",
+ "NISTXML-nonPositiveInteger-totalDigits-1-2.xml",
+ "NISTXML-nonPositiveInteger-totalDigits-1-1.xml"],[]}}.
+{'NISTSchema-normalizedString',{["NISTXML-normalizedString-length-1-1.xml",
+ "NISTXML-normalizedString-maxLength-5-5.xml",
+ "NISTXML-normalizedString-maxLength-5-4.xml",
+ "NISTXML-normalizedString-maxLength-5-3.xml",
+ "NISTXML-normalizedString-maxLength-5-2.xml",
+ "NISTXML-normalizedString-maxLength-5-1.xml",
+ "NISTXML-normalizedString-maxLength-4-5.xml",
+ "NISTXML-normalizedString-maxLength-4-4.xml",
+ "NISTXML-normalizedString-maxLength-4-3.xml",
+ "NISTXML-normalizedString-maxLength-4-2.xml",
+ "NISTXML-normalizedString-maxLength-4-1.xml",
+ "NISTXML-normalizedString-maxLength-3-5.xml",
+ "NISTXML-normalizedString-maxLength-3-4.xml",
+ "NISTXML-normalizedString-maxLength-3-3.xml",
+ "NISTXML-normalizedString-maxLength-3-2.xml",
+ "NISTXML-normalizedString-maxLength-3-1.xml",
+ "NISTXML-normalizedString-maxLength-2-5.xml",
+ "NISTXML-normalizedString-maxLength-2-4.xml",
+ "NISTXML-normalizedString-maxLength-2-3.xml",
+ "NISTXML-normalizedString-maxLength-2-2.xml",
+ "NISTXML-normalizedString-maxLength-2-1.xml",
+ "NISTXML-normalizedString-maxLength-1-1.xml"],[]}}.
+{'NISTSchema-string',{["NISTXML-string-length-1-1.xml",
+ "NISTXML-string-maxLength-5-5.xml",
+ "NISTXML-string-maxLength-5-4.xml",
+ "NISTXML-string-maxLength-5-3.xml",
+ "NISTXML-string-maxLength-5-2.xml",
+ "NISTXML-string-maxLength-5-1.xml",
+ "NISTXML-string-maxLength-4-5.xml",
+ "NISTXML-string-maxLength-4-4.xml",
+ "NISTXML-string-maxLength-4-3.xml",
+ "NISTXML-string-maxLength-4-2.xml",
+ "NISTXML-string-maxLength-4-1.xml",
+ "NISTXML-string-maxLength-3-5.xml",
+ "NISTXML-string-maxLength-3-4.xml",
+ "NISTXML-string-maxLength-3-3.xml",
+ "NISTXML-string-maxLength-3-2.xml",
+ "NISTXML-string-maxLength-3-1.xml",
+ "NISTXML-string-maxLength-2-5.xml",
+ "NISTXML-string-maxLength-2-4.xml",
+ "NISTXML-string-maxLength-2-3.xml",
+ "NISTXML-string-maxLength-2-2.xml",
+ "NISTXML-string-maxLength-2-1.xml",
+ "NISTXML-string-maxLength-1-1.xml"],[]}}.
+{'NISTSchema-time',{["NISTXML-time-maxInclusive-5-5.xml",
+ "NISTXML-time-maxInclusive-5-4.xml",
+ "NISTXML-time-maxInclusive-5-3.xml",
+ "NISTXML-time-maxInclusive-5-2.xml",
+ "NISTXML-time-maxInclusive-5-1.xml",
+ "NISTXML-time-maxInclusive-4-5.xml",
+ "NISTXML-time-maxInclusive-4-4.xml",
+ "NISTXML-time-maxInclusive-4-3.xml",
+ "NISTXML-time-maxInclusive-4-2.xml",
+ "NISTXML-time-maxInclusive-4-1.xml",
+ "NISTXML-time-maxInclusive-3-5.xml",
+ "NISTXML-time-maxInclusive-3-4.xml",
+ "NISTXML-time-maxInclusive-3-3.xml",
+ "NISTXML-time-maxInclusive-3-2.xml",
+ "NISTXML-time-maxInclusive-3-1.xml",
+ "NISTXML-time-maxInclusive-2-5.xml",
+ "NISTXML-time-maxInclusive-2-4.xml",
+ "NISTXML-time-maxInclusive-2-3.xml",
+ "NISTXML-time-maxInclusive-2-2.xml",
+ "NISTXML-time-maxInclusive-2-1.xml",
+ "NISTXML-time-maxInclusive-1-1.xml",
+ "NISTXML-time-maxExclusive-5-5.xml",
+ "NISTXML-time-maxExclusive-5-4.xml",
+ "NISTXML-time-maxExclusive-5-3.xml",
+ "NISTXML-time-maxExclusive-5-2.xml",
+ "NISTXML-time-maxExclusive-5-1.xml",
+ "NISTXML-time-maxExclusive-4-5.xml",
+ "NISTXML-time-maxExclusive-4-4.xml",
+ "NISTXML-time-maxExclusive-4-3.xml",
+ "NISTXML-time-maxExclusive-4-2.xml",
+ "NISTXML-time-maxExclusive-4-1.xml",
+ "NISTXML-time-maxExclusive-3-5.xml",
+ "NISTXML-time-maxExclusive-3-4.xml",
+ "NISTXML-time-maxExclusive-3-3.xml",
+ "NISTXML-time-maxExclusive-3-2.xml",
+ "NISTXML-time-maxExclusive-3-1.xml",
+ "NISTXML-time-maxExclusive-2-5.xml",
+ "NISTXML-time-maxExclusive-2-4.xml",
+ "NISTXML-time-maxExclusive-2-3.xml",
+ "NISTXML-time-maxExclusive-2-2.xml",
+ "NISTXML-time-maxExclusive-2-1.xml",
+ "NISTXML-time-maxExclusive-1-1.xml",
+ "NISTXML-time-minInclusive-5-1.xml",
+ "NISTXML-time-minInclusive-4-5.xml",
+ "NISTXML-time-minInclusive-4-4.xml",
+ "NISTXML-time-minInclusive-4-3.xml",
+ "NISTXML-time-minInclusive-4-2.xml",
+ "NISTXML-time-minInclusive-4-1.xml",
+ "NISTXML-time-minInclusive-3-5.xml",
+ "NISTXML-time-minInclusive-3-4.xml",
+ "NISTXML-time-minInclusive-3-3.xml",
+ "NISTXML-time-minInclusive-3-2.xml",
+ "NISTXML-time-minInclusive-3-1.xml",
+ "NISTXML-time-minInclusive-2-5.xml",
+ "NISTXML-time-minInclusive-2-4.xml",
+ "NISTXML-time-minInclusive-2-3.xml",
+ "NISTXML-time-minInclusive-2-2.xml",
+ "NISTXML-time-minInclusive-2-1.xml",
+ "NISTXML-time-minInclusive-1-5.xml",
+ "NISTXML-time-minInclusive-1-4.xml",
+ "NISTXML-time-minInclusive-1-3.xml",
+ "NISTXML-time-minInclusive-1-2.xml",
+ "NISTXML-time-minInclusive-1-1.xml",
+ "NISTXML-time-minExclusive-5-1.xml",
+ "NISTXML-time-minExclusive-4-5.xml",
+ "NISTXML-time-minExclusive-4-4.xml",
+ "NISTXML-time-minExclusive-4-3.xml",
+ "NISTXML-time-minExclusive-4-2.xml",
+ "NISTXML-time-minExclusive-4-1.xml",
+ "NISTXML-time-minExclusive-3-5.xml",
+ "NISTXML-time-minExclusive-3-4.xml",
+ "NISTXML-time-minExclusive-3-3.xml",
+ "NISTXML-time-minExclusive-3-2.xml",
+ "NISTXML-time-minExclusive-3-1.xml",
+ "NISTXML-time-minExclusive-2-5.xml",
+ "NISTXML-time-minExclusive-2-4.xml",
+ "NISTXML-time-minExclusive-2-3.xml",
+ "NISTXML-time-minExclusive-2-2.xml",
+ "NISTXML-time-minExclusive-2-1.xml",
+ "NISTXML-time-minExclusive-1-5.xml",
+ "NISTXML-time-minExclusive-1-4.xml",
+ "NISTXML-time-minExclusive-1-3.xml",
+ "NISTXML-time-minExclusive-1-2.xml",
+ "NISTXML-time-minExclusive-1-1.xml"],[]}}.
+{'NISTSchema-token',{["NISTXML-token-length-1-1.xml",
+ "NISTXML-token-minLength-1-5.xml",
+ "NISTXML-token-minLength-1-4.xml",
+ "NISTXML-token-minLength-1-3.xml",
+ "NISTXML-token-minLength-1-2.xml",
+ "NISTXML-token-minLength-1-1.xml",
+ "NISTXML-token-maxLength-5-5.xml",
+ "NISTXML-token-maxLength-5-4.xml",
+ "NISTXML-token-maxLength-5-3.xml",
+ "NISTXML-token-maxLength-5-2.xml",
+ "NISTXML-token-maxLength-5-1.xml",
+ "NISTXML-token-maxLength-4-5.xml",
+ "NISTXML-token-maxLength-4-4.xml",
+ "NISTXML-token-maxLength-4-3.xml",
+ "NISTXML-token-maxLength-4-2.xml",
+ "NISTXML-token-maxLength-4-1.xml",
+ "NISTXML-token-maxLength-3-5.xml",
+ "NISTXML-token-maxLength-3-4.xml",
+ "NISTXML-token-maxLength-3-3.xml",
+ "NISTXML-token-maxLength-3-2.xml",
+ "NISTXML-token-maxLength-3-1.xml",
+ "NISTXML-token-maxLength-2-5.xml",
+ "NISTXML-token-maxLength-2-4.xml",
+ "NISTXML-token-maxLength-2-3.xml",
+ "NISTXML-token-maxLength-2-2.xml",
+ "NISTXML-token-maxLength-2-1.xml",
+ "NISTXML-token-maxLength-1-1.xml"],[]}}.
diff --git a/lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE_data/nisttest.tar.gz b/lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE_data/nisttest.tar.gz
new file mode 100644
index 0000000000..03d575c268
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE_data/nisttest.tar.gz
Binary files differ
diff --git a/lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE_data/w3c-copyright-19990405.html b/lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE_data/w3c-copyright-19990405.html
new file mode 100644
index 0000000000..5c89ffd95e
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_NIST2002-01-16_SUITE_data/w3c-copyright-19990405.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html><head>
+
+
+ <meta http-equiv="Content-Type" content="text/html"><title>DOCUMENT NOTICE</title>
+
+ <link rel="stylesheet" type="text/css" href="copyright-documents-19990405_files/base.css"></head><body bgcolor="#ffffff" text="#000000">
+<h1>W3C<sup>�</sup> DOCUMENT NOTICE AND LICENSE</h1>
+
+<h3>Copyright � 1994-2002 <a href="http://www.w3.org/">World Wide Web
+Consortium</a>, (<a href="http://www.lcs.mit.edu/">Massachusetts Institute of
+Technology</a>, <a href="http://www.inria.fr/">Institut National de Recherche
+en Informatique et en Automatique</a>, <a href="http://www.keio.ac.jp/">Keio
+University</a>). All Rights Reserved.<br>
+http://www.w3.org/Consortium/Legal/</h3>
+
+<p>Public documents on the W3C site are provided by the copyright holders
+under the following license. The software or Document Type Definitions (DTDs)
+associated with W3C specifications are governed by the <a href="http://www.w3.org/Consortium/Legal/copyright-software.html"> Software
+Notice</a>. By using and/or copying this document, or the W3C document from
+which this statement is linked, you (the licensee) agree that you have read,
+understood, and will comply with the following terms and conditions:</p>
+
+<p>Permission to use, copy, and distribute the contents of this document, or
+the W3C document from which this statement is linked, in any medium for any
+purpose and without fee or royalty is hereby granted, provided that you
+include the following on <i>ALL</i> copies of the document, or portions
+thereof, that you use:</p>
+<ol>
+ <li>A link or URL to the original W3C document.</li>
+ <li>The pre-existing copyright notice of the original author, or if it
+ doesn't exist, a notice of the form: "Copyright � [$date-of-document] <a href="http://www.w3.org/">World Wide Web Consortium</a>, (<a href="http://www.lcs.mit.edu/">Massachusetts Institute of Technology</a>,
+ <a href="http://www.inria.fr/"> Institut National de Recherche en
+ Informatique et en Automatique</a>, <a href="http://www.keio.ac.jp/">Keio
+ University</a>). All Rights Reserved.
+ http://www.w3.org/Consortium/Legal/" (Hypertext is preferred, but a
+ textual representation is permitted.)</li>
+ <li><em>If it exists</em>, the STATUS of the W3C document.</li>
+</ol>
+
+<p>When space permits, inclusion of the full text of this <b> NOTICE</b>
+should be provided. We request that authorship attribution be provided in any
+software, documents, or other items or products that you create pursuant to
+the implementation of the contents of this document, or any portion
+thereof.</p>
+
+<p>No right to create modifications or derivatives of W3C documents is
+granted pursuant to this license. However, if additional requirements
+(documented in the <a href="http://www.w3.org/Consortium/Legal/IPR-FAQ.html">Copyright FAQ</a>) are satisfied,
+the right to create modifications or derivatives is&nbsp;sometimes granted by the
+W3C to individuals complying with those requirements.</p>
+
+<p>THIS DOCUMENT IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO
+REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED
+TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
+NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE DOCUMENT ARE SUITABLE
+FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF SUCH CONTENTS WILL NOT
+INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.</p>
+
+<p>COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE DOCUMENT OR THE
+PERFORMANCE OR IMPLEMENTATION OF THE CONTENTS THEREOF.</p>
+
+<p>The name and trademarks of copyright holders may NOT be used in
+advertising or publicity pertaining to this document or its contents without
+specific, written prior permission. Title to copyright in this document will
+at all times remain with copyright holders.</p>
+
+<p>----------------------------------------------------------------------------</p>
+
+<p>This formulation of W3C's notice and license became active on April 05
+1999 so as to account for the treatment of DTDs, schema's and bindings. See
+the <a href="http://www.w3.org/Consortium/Legal/copyright-documents-19990218.html"> older formulation</a> for
+the policy prior to this date. Please see our <a href="http://www.w3.org/Consortium/Legal/IPR-FAQ.html">Copyright FAQ</a> for common questions about using
+materials from our site, including specific terms and conditions for packages
+like libwww, Amaya, and Jigsaw. Other questions about this notice can be
+directed to <a href="mailto:[email protected]">[email protected]</a>.</p>
+<address>
+ <a href="http://w3.org/Help/Webmaster.html">webmaster</a><br>
+ (last updated by reagle on 1999/04/99.)
+</address>
+</body></html> \ No newline at end of file
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE.erl b/lib/xmerl/test/xmerl_xsd_SUITE.erl
new file mode 100644
index 0000000000..421fa48054
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE.erl
@@ -0,0 +1,1153 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 ASN.1 application
+
+-module(xmerl_xsd_SUITE).
+
+-compile(export_all).
+%%-export([Function/Arity, ...]).
+
+-include_lib("test_server/include/test_server.hrl").
+%%-include("xmerl.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
+
+-import(xmerl_xsd_type,[check_simpleType/3]).
+
+all() ->
+ [{group, type_tests}, {group, facets},
+ {group, misc_block_tests}, {group, validation_tests},
+ {group, ticket_tests}].
+
+groups() ->
+ [{type_tests, [],
+ [{group, primitive_datatypes},
+ {group, derived_datatypes}]},
+ {validation_tests, [],
+ [{group, xmlSchemaPrimerExamples},
+ {group, miscXMLexamples}]},
+ {primitive_datatypes, [],
+ [string, boolean, decimal, float, double, duration,
+ dateTime, time, date, gYearMonth, gYear, gMonthDay,
+ gDay, gMonth, hexBinary, base64Binary, anyURI, 'QName',
+ 'NOTATION']},
+ {derived_datatypes, [],
+ [normalizedString, token, language, 'NMTOKEN',
+ 'NMTOKENS', 'Name', 'NCName', 'ID', 'IDREF', 'IDREFS',
+ 'ENTITY', 'ENTITIES', integer, nonPositiveInteger,
+ negativeInteger, long, int, short, byte,
+ nonNegativeInteger, unsignedLong, unsignedInt,
+ unsignedShort, unsignedByte, positiveInteger]},
+ {xmlSchemaPrimerExamples, [],
+ [po, po1, po2, ipo, ipo_redefine, '4Q99']},
+ {miscXMLexamples, [],
+ [small, complexType1, model_group_all,
+ substitutionGroup, attributeGroup, test_key1, sis1,
+ sis2, state2file_file2state, union]},
+ {ticket_tests, [],
+ [ticket_6910, ticket_7165, ticket_7190, ticket_7288,
+ ticket_7736, ticket_8599, ticket_9410]},
+ {facets, [],
+ [length, minLength, maxLength, pattern, enumeration,
+ whiteSpace, maxInclusive, maxExclusive, minExclusive,
+ minInclusive, totalDigits, fractionDigits]},
+ {misc_block_tests, [],
+ [compare_dateTime, compare_duration]}].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+init_per_testcase(_TestCase,Config) ->
+ {ok, _} =
+ file:read_file_info(filename:join([?config(priv_dir,Config)])),
+ code:add_patha(?config(priv_dir,Config)),
+ Dog=test_server:timetrap({minutes,10}),
+ [{watchdog, Dog}|Config].
+
+end_per_testcase(_Func,Config) ->
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+
+string(suite) -> [];
+string(_Config) ->
+ %% #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
+ Str = [16#9,16#A,16#D,16#20,16#D7FF,16#E000,16#FFFD,16#10000,
+ 16#10FFFF],
+ ?line {ok,_} = check_simpleType(string,Str,dummy).
+
+boolean(suite) -> [];
+boolean(_Config) ->
+ ?line {ok,_} = check_simpleType(boolean,"1",dummy),
+ ?line {ok,_} = check_simpleType(boolean,"0",dummy),
+ ?line {ok,_} = check_simpleType(boolean,"true",dummy),
+ ?line {ok,_} = check_simpleType(boolean,"false",dummy),
+ ?line {error,_Reason} = check_simpleType(boolean,"gurka",dummy).
+
+decimal(suite) -> [];
+decimal(_Config) ->
+ ?line {ok,_} = check_simpleType(decimal,"-1.23",dummy),
+ ?line {ok,_} = check_simpleType(decimal,"12678967.543233",dummy),
+ ?line {ok,_} = check_simpleType(decimal,"+100000.00",dummy),
+ ?line {ok,_} = check_simpleType(decimal,"210",dummy).
+
+float(suite) -> [];
+float(_Config) ->
+ %% -1E4, 1267.43233E12, 12.78e-2, 12 , -0, 0 , INF, -INF, NaN
+ ?line {ok,_} = check_simpleType(float,"-1E4",dummy),
+ ?line {ok,_} = check_simpleType(float,"1267.43233E12",dummy),
+ ?line {ok,_} = check_simpleType(float,"12.78e-2",dummy),
+ ?line {ok,_} = check_simpleType(float,"12",dummy),
+ ?line {ok,_} = check_simpleType(float,"-0",dummy),
+ ?line {ok,_} = check_simpleType(float,"0",dummy),
+ ?line {ok,_} = check_simpleType(float,"INF",dummy),
+ ?line {ok,_} = check_simpleType(float,"-INF",dummy),
+ ?line {ok,_} = check_simpleType(float,"NaN",dummy).
+
+
+double(suite) -> [];
+double(_Config) ->
+ %% -1E4, 1267.43233E12, 12.78e-2, 12 , -0, 0 , INF, -INF, NaN
+ ?line {ok,_} = check_simpleType(double,"-1E4",dummy),
+ ?line {ok,_} = check_simpleType(double,"1267.43233E12",dummy),
+ ?line {ok,_} = check_simpleType(double,"12.78e-2",dummy),
+ ?line {ok,_} = check_simpleType(double,"12",dummy),
+ ?line {ok,_} = check_simpleType(double,"-0",dummy),
+ ?line {ok,_} = check_simpleType(double,"0",dummy),
+ ?line {ok,_} = check_simpleType(double,"INF",dummy),
+ ?line {ok,_} = check_simpleType(double,"-INF",dummy),
+ ?line {ok,_} = check_simpleType(double,"NaN",dummy).
+
+
+duration(suite) -> [];
+duration(_Config) ->
+ %% allowed: P1Y2M3DT10H30M -P120D P1347Y P1347M P1Y2MT2H
+ %% P0Y1347M P0Y1347M0D -P1347M
+ %% not allowed: P-1347M P1Y2MT
+ ?line {ok,_} = check_simpleType(duration,"P1Y2M3DT10H30M",dummy),
+ ?line {ok,_} = check_simpleType(duration,"-P120D",dummy),
+ ?line {ok,_} = check_simpleType(duration,"P1347Y",dummy),
+ ?line {ok,_} = check_simpleType(duration,"P1347M",dummy),
+ ?line {ok,_} = check_simpleType(duration,"P1Y2MT2H",dummy),
+ ?line {ok,_} = check_simpleType(duration,"P0Y1347M",dummy),
+ ?line {ok,_} = check_simpleType(duration,"P0Y1347M0D",dummy),
+ ?line {ok,_} = check_simpleType(duration,"-P1347M",dummy),
+
+ ?line {error,_} = check_simpleType(duration,"P-1347M",dummy),
+ ?line {error,_} = check_simpleType(duration,"P1Y2MT",dummy).
+
+%% '-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?
+dateTime(suite) -> [];
+dateTime(_Config) ->
+ %% 2002-10-10T12:00:00-05:00
+ DT1 = "2002-10-10T12:00:00-05:00",
+ ?line {ok,_} = check_simpleType(dateTime,DT1,dummy),
+ DT2 = "2002-10-10T17:00:00Z",
+ ?line {ok,_} = check_simpleType(dateTime,DT2,dummy),
+ %% plus sign prohibited
+ DT3 = "+2002-10-10T17:00:00Z",
+ ?line {error,_Reason3} = check_simpleType(dateTime,DT3,dummy),
+ %% leading zeros when year are more than four digits prohibited
+ DT4 = "002002-10-10T17:00:00Z",
+ ?line {error,_Reason4} = check_simpleType(dateTime,DT4,dummy),
+ DT5 = "1953-12-31T12:10:10.10+12:00",
+ ?line {ok,_} = check_simpleType(dateTime,DT5,dummy).
+
+time(suite) -> [];
+time(_Config) ->
+ %% hh:mm:ss.sss with optional following time zone indicator.
+ T1 = "13:20:00-05:00",
+ ?line {ok,_} = check_simpleType(time,T1,dummy),
+ %% canonical repr. of midnight
+ T2 = "00:00:00",
+ ?line {ok,_} = check_simpleType(time,T2,dummy),
+ T3 = "12:34:56",
+ ?line {ok,_} = check_simpleType(time,T3,dummy),
+ T4 = "12:34:56.552",
+ ?line {ok,_} = check_simpleType(time,T4,dummy),
+ T5 = "12:34:56.552Z",
+ ?line {ok,_} = check_simpleType(time,T5,dummy).
+
+date(suite) -> [];
+date(_Config) ->
+ %% '-'? yyyy '-' mm '-' dd zzzzzz?
+ %% is
+ D1 = "2002-10-10+13:00",
+ ?line {ok,_} = check_simpleType(date,D1,dummy),
+ D2 = "2002-10-09-11:00",
+ ?line {ok,_} = check_simpleType(date,D2,dummy),
+
+ D12 = "+2002-13-09-11:00",
+ ?line {error,_Reason12} = check_simpleType(date,D12,dummy),
+ D13 = "2002-13-09-11:00",
+ ?line {error,_Reason13} = check_simpleType(date,D13,dummy),
+ D14 = "2002-12-39-11:00",
+ ?line {error,_Reason14} = check_simpleType(date,D14,dummy).
+
+gYearMonth(suite) -> [];
+gYearMonth(_Config) ->
+ %% '-'? yyyy '-' mm zzzzzz?
+ GYM1 = "1955-10",
+ ?line {ok,_} = check_simpleType(gYearMonth,GYM1,dummy),
+ GYM2 = "-1955-10",
+ ?line {ok,_} = check_simpleType(gYearMonth,GYM2,dummy),
+ GYM3 = "1955-10Z",
+ ?line {ok,_} = check_simpleType(gYearMonth,GYM3,dummy),
+ GYM4 = "0055-10+10:00",
+ ?line {ok,_} = check_simpleType(gYearMonth,GYM4,dummy),
+ GYM5 = "0955-10Z",
+ ?line {ok,_} = check_simpleType(gYearMonth,GYM5,dummy),
+ GYM6 = "-11955-01",
+ ?line {ok,_} = check_simpleType(gYearMonth,GYM6,dummy),
+
+ ?line {error,_} = check_simpleType(gYearMonth,"+2000-10",dummy),
+ ?line {error,_} = check_simpleType(gYearMonth,"2000-00",dummy),
+ ?line {error,_} = check_simpleType(gYearMonth,"2000-10+10:70",dummy).
+
+gYear(suite) -> [];
+gYear(_Config) ->
+ %% '-'? yyyy zzzzzz?
+ ?line {ok,_} = check_simpleType(gYear,"2000",dummy),
+ ?line {ok,_} = check_simpleType(gYear,"2000-11:30",dummy),
+ ?line {ok,_} = check_simpleType(gYear,"-2000",dummy),
+ ?line {error,_} = check_simpleType(gYear,"0000",dummy).
+
+gMonthDay(suite) -> [];
+gMonthDay(_Config) ->
+ %% mm '-' dd zzzzzz?
+ ?line {ok,_} = check_simpleType(gMonthDay,"--05-03",dummy),
+ ?line {ok,_} = check_simpleType(gMonthDay,"--05-03Z",dummy),
+ ?line {error,_} = check_simpleType(gMonthDay,"05-00",dummy),
+ ?line {error,_} = check_simpleType(gMonthDay,"00-03",dummy),
+ ?line {error,_} = check_simpleType(gMonthDay,"-05-03",dummy).
+
+gDay(suite) -> [];
+gDay(_Config) ->
+ %% dd zzzzzz?
+ ?line {ok,_} = check_simpleType(gDay,"---05",dummy),
+ ?line {ok,_} = check_simpleType(gDay,"---30+03:00",dummy),
+ ?line {error,_} = check_simpleType(gDay,"-30+03:00",dummy),
+ ?line {error,_} = check_simpleType(gDay,"---00+03:00",dummy),
+ ?line {error,_} = check_simpleType(gDay,"---40+03:00",dummy),
+ ?line {error,_} = check_simpleType(gDay,"05",dummy).
+
+gMonth(suite) -> [];
+gMonth(_Config) ->
+ %% mm zzzzzz?
+ ?line {ok,_} = check_simpleType(gMonth,"--05",dummy),
+ ?line {ok,_} = check_simpleType(gMonth,"--10+03:00",dummy),
+ ?line {error,_} = check_simpleType(gMonth,"-10+03:00",dummy),
+ ?line {error,_} = check_simpleType(gMonth,"00+03:00",dummy),
+ ?line {error,_} = check_simpleType(gMonth,"14",dummy),
+ ?line {error,_} = check_simpleType(gMonth,"05",dummy).
+
+
+hexBinary(suite) -> [];
+hexBinary(_Config) ->
+ %% an even number of hexadecimal digits ([0-9a-fA-F]).
+ ?line {ok,_} = check_simpleType(hexBinary,"05",dummy),
+ ?line {ok,_} = check_simpleType(hexBinary,"aF",dummy),
+ ?line {ok,_} = check_simpleType(hexBinary,
+ "0123456789abcdefABCDEF",dummy),
+ ?line {error,_} = check_simpleType(hexBinary,
+ "0123456789absdefABCDEF",dummy),
+ ?line {error,_} = check_simpleType(hexBinary,"aF5",dummy),
+ ?line {error,_} = check_simpleType(hexBinary,"aFG",dummy).
+
+base64Binary(suite) -> [];
+base64Binary(_Config) ->
+ %% a-z, A-Z, 0-9, the plus sign (+), the forward slash (/) and the
+ %% equal sign (=), together with the characters defined in [XML
+ %% 1.0 (Second Edition)] as white space.(16#9, 16#A, 16#D, 16#20)
+ ?line {ok,_} = check_simpleType(base64Binary,"05+/AA==",dummy),
+ ?line {ok,_} = check_simpleType(base64Binary,"05+/AA= =",dummy),
+ ?line {ok,_} = check_simpleType(base64Binary,"05+/A A= =",dummy),
+ ?line {ok,_} = check_simpleType(base64Binary,"05+/ AA= =",dummy),
+ ?line {error,_} = check_simpleType(base64Binary,"05+/AA== ",dummy),
+ B64B1 = "AbCd GhZz 09w=",
+ ?line {ok,_} = check_simpleType(base64Binary,B64B1,dummy),
+ B64B2 = "AbCd GhZ9 0z8 =",
+ ?line {ok,_} = check_simpleType(base64Binary,B64B2,dummy),
+ ?line {ok,_} = check_simpleType(base64Binary,"0z8 =",dummy),
+ ErrB641 = "AbCd GZ9 0z8 =",
+ ?line {error,_} = check_simpleType(base64Binary,ErrB641,dummy).
+
+anyURI(suite) -> [];
+anyURI(_Config) ->
+ URI1 = "ftp://ftp.is.co.za/rfc/rfc1808.txt",
+ URI2 = "gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles",
+ URI3 = "http://www.math.uio.no/faq/compression-faq/part1.html",
+ URI4 = "mailto:[email protected]",
+ URI5 = "news:comp.infosystems.www.servers.unix",
+ URI6 = "telnet://melvyl.ucop.edu/",
+ ?line ok=ok_loop(anyURI,[URI1,URI2,URI3,URI4,URI5,URI6]).
+
+
+'QName'(suite) -> [];
+'QName'(_Config) ->
+ %% QName ::= (Prefix ':')? LocalPart
+ %% Prefix ::= NCName
+ %% LocalPart ::= NCName
+ ?line {ok,_} = check_simpleType('QName',"abc:def",dummy),
+ ?line {ok,_} = check_simpleType('QName',"abc",dummy),
+ ?line {ok,_} = check_simpleType('QName',"abc:def:ijk",dummy).
+
+'NOTATION'(suite) -> [];
+'NOTATION'(_Config) ->
+ ?line {ok,_} = check_simpleType('NOTATION',"abc:def",dummy),
+ ?line {ok,_} = check_simpleType('NOTATION',"abc",dummy),
+ ?line {ok,_} = check_simpleType('NOTATION',"abc:def:ijk",dummy).
+
+normalizedString(suite) -> [];
+normalizedString(_Config) ->
+ %% not contain the carriage return (#xD), line feed (#xA) nor tab
+ %% (#x9) characters.
+ NStr1 = "this string is ok with extra space between characters",
+ NotNStr1 = "this string is not normalized \t",
+ NotNStr2 = "neither is this \n string",
+ NotNStr3 = "or this \r string",
+ ?line {ok,_} = check_simpleType(normalizedString,NStr1,dummy),
+ ?line ok=error_loop(normalizedString,[NotNStr1,NotNStr2,NotNStr3]).
+
+token(suite) -> [];
+token(_Config) ->
+ %% not contain the carriage return (#xD), line feed (#xA) nor tab
+ %% (#x9) characters, that have no leading or trailing spaces
+ %% (#x20) and that have no internal sequences of two or more
+ %% spaces.
+ T1 = "this string is tokenized with only single space between characters",
+ NotT1 = "this string is not ok with extra space between characters",
+ NotT2 = " neither leading space",
+ NotT3 = "nor trailing space ",
+ NotT4 = "tabs not \t allowed",
+ NotT5 = "newlines not allowed\n",
+ NotT6 = "or \r (carriage return)",
+ ?line {ok,_} = check_simpleType(token,T1,dummy),
+ ?line ok=error_loop(token,[NotT1,NotT2,NotT3,NotT4,NotT5,NotT6]).
+
+language(suite) -> [];
+language(_Config) ->
+ %% strings that conform to the pattern
+ %% [a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*
+ L = "Abra-cadabra-123",
+ NotL1 = "Abra123-cadabra!",
+ NotL2 = "Abra-",
+ NotL3 = "Abracadabra",
+ NotL4 = "Abra-cadabrrra",
+ ?line {ok,_} = check_simpleType(language,L,dummy),
+ ?line ok=error_loop(language,[NotL1,NotL2,NotL3,NotL4]).
+
+'NMTOKEN'(suite) -> [];
+'NMTOKEN'(_Config) ->
+ N = "name:withoutspace",
+ NotN1 = "name with space",
+ NotN2 = "namewith#strang/chars)",
+ ?line {ok,_} = check_simpleType('NMTOKEN',N,dummy),
+ ?line {error,_} = check_simpleType('NMTOKEN',NotN1,dummy),
+ ?line {error,_} = check_simpleType('NMTOKEN',NotN2,dummy).
+
+'NMTOKENS'(suite) -> [];
+'NMTOKENS'(_Config) ->
+ N1 = "name1 name:2 name:three",
+ NotN1 = "name na%me",
+ ?line {ok,_} = check_simpleType('NMTOKENS',N1,dummy),
+ ?line {error,_} = check_simpleType('NMTOKENS',NotN1,dummy).
+
+'Name'(suite) -> [];
+'Name'(_Config) ->
+ ?line {ok,_} = check_simpleType('Name',"_valid_Name",dummy).
+
+'NCName'(suite) -> [];
+'NCName'(_Config) ->
+ ?line {ok,_} = check_simpleType('NCName',"_valid_Name",dummy).
+
+'ID'(suite) -> [];
+'ID'(_Config) ->
+ ?line {ok,_} = check_simpleType('ID',"_valid_Name",dummy).
+
+'IDREF'(suite) -> [];
+'IDREF'(_Config) ->
+ ?line {ok,_} = check_simpleType('IDREF',"_valid_Name",dummy).
+
+'IDREFS'(suite) -> [];
+'IDREFS'(_Config) ->
+ ?line {ok,_} = check_simpleType('IDREFS',"_valid_Name Name2",dummy).
+
+'ENTITY'(suite) -> [];
+'ENTITY'(_Config) ->
+ ?line {ok,_} = check_simpleType('ENTITY',"_valid_Name",dummy).
+
+'ENTITIES'(suite) -> [];
+'ENTITIES'(_Config) ->
+ ?line {ok,_} = check_simpleType('ENTITIES',"name name3",dummy).
+
+integer(suite) -> [];
+integer(_Config) ->
+ IntList = ["-1", "0", "12678967543233", "+100000"],
+ ?line ok = ok_loop(integer,IntList),
+ ?line {error,_} = check_simpleType(integer,"1.3",dummy).
+
+nonPositiveInteger(suite) -> [];
+nonPositiveInteger(_Config) ->
+ NPIList = ["0", "-12678967543233", "-100000"],
+ ?line ok = ok_loop(nonPositiveInteger,NPIList),
+ ?line {error,_} = check_simpleType(nonPositiveInteger,"1",dummy).
+
+negativeInteger(suite) -> [];
+negativeInteger(_Config) ->
+ NIList = ["-1", "-12678967543233", "-100000"],
+ ?line ok = ok_loop(negativeInteger,NIList),
+ ?line {error,_} = check_simpleType(negativeInteger,"1",dummy),
+ ?line {error,_} = check_simpleType(negativeInteger,"0",dummy).
+
+long(suite) -> [];
+long(_Config) ->
+ L = ["9223372036854775807","-9223372036854775808","-1", "0",
+ "12678967543233", "+100000"],
+ ?line ok = ok_loop(long,L),
+ Err = ["9223372036854775808","-9223372036854775809"],
+ ?line ok = error_loop(long,Err).
+
+int(suite) -> [];
+int(_Config) ->
+ L = ["2147483647", "-2147483648", "-1", "0", "126789675", "+100000"],
+ ?line ok = ok_loop(int,L),
+ Err = ["2147483648", "-2147483649"],
+ ?line ok = error_loop(int,Err).
+
+short(suite) -> [];
+short(_Config) ->
+ L = ["32767", "-32768", "-1", "0", "12678", "+10000"],
+ ?line ok = ok_loop(short,L),
+ Err = ["32768", "-32769"],
+ ?line ok = error_loop(short,Err).
+
+byte(suite) -> [];
+byte(_Config) ->
+ L = ["-1", "0", "126", "+100", "127", "-128"],
+ ?line ok = ok_loop(byte,L),
+ Err = ["128", "-129"],
+ ?line ok = error_loop(byte,Err).
+
+nonNegativeInteger(suite) -> [];
+nonNegativeInteger(_Config) ->
+ L = ["1", "0", "12678967543233", "+100000"],
+ ?line ok = ok_loop(nonNegativeInteger,L),
+ ?line {error,_} = check_simpleType(nonNegativeInteger,"-1",dummy).
+
+unsignedLong(suite) -> [];
+unsignedLong(_Config) ->
+ L = ["0", "12678967543233", "100000", "18446744073709551615"],
+ ?line ok = ok_loop(unsignedLong,L),
+ Err = ["-1","18446744073709551616"],
+ ?line ok = error_loop(unsignedLong,Err).
+
+unsignedInt(suite) -> [];
+unsignedInt(_Config) ->
+ L = ["4294967295", "0", "1267896754", "100000"],
+ ?line ok = ok_loop(unsignedInt,L),
+ Err = ["-1","4294967296"],
+ ?line ok = error_loop(unsignedInt,Err).
+
+unsignedShort(suite) -> [];
+unsignedShort(_Config) ->
+ L = ["65535", "0", "12678", "10000"],
+ ?line ok = ok_loop(unsignedShort,L),
+ Err = ["-1","65536"],
+ ?line ok = error_loop(unsignedShort,Err).
+
+unsignedByte(suite) -> [];
+unsignedByte(_Config) ->
+ L = ["255", "0", "126", "100"],
+ ?line ok = ok_loop(unsignedByte,L),
+ Err = ["-1","256"],
+ ?line ok = error_loop(unsignedByte,Err).
+
+positiveInteger(suite) -> [];
+positiveInteger(_Config) ->
+ L = ["1", "12678967543233", "+100000"],
+ ?line ok = ok_loop(positiveInteger,L),
+ Err = ["-1","0"],
+ ?line ok = error_loop(positiveInteger,Err).
+
+
+
+ok_loop(_Type,[]) ->
+ ok;
+ok_loop(Type,[H|T]) ->
+ ?line {ok,_} = check_simpleType(Type,H,dummy),
+ ok_loop(Type,T).
+
+error_loop(_T,[]) ->
+ ok;
+error_loop(Type,[H|T]) ->
+ ?line {error,_} = check_simpleType(Type,H,dummy),
+ error_loop(Type,T).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Testing facets
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+length(suite) -> [];
+length(_Config) ->
+ ?line {ok,"string"} =
+ (xmerl_xsd_type:facet_fun(string,{length,"6"}))("string"),
+ ?line {error,{length,12,should_be,6}} =
+ (xmerl_xsd_type:facet_fun(string,{length,"6"}))("stringstring"),
+ ok.
+
+minLength(suite) -> [];
+minLength(_Config) ->
+ ?line {ok,"string"} =
+ (xmerl_xsd_type:facet_fun(string,{minLength,"6"}))("string"),
+ ?line {error,{minLength,3,should_at_least_be,6}} =
+ (xmerl_xsd_type:facet_fun(string,{minLength,"6"}))("str"),
+ ok.
+
+maxLength(suite) -> [];
+maxLength(_Config) ->
+ ?line {ok,"string"} =
+ (xmerl_xsd_type:facet_fun(string,{maxLength,"6"}))("string"),
+ ?line {error,{maxLength,12,should_not_be_more_than,6}} =
+ (xmerl_xsd_type:facet_fun(string,{maxLength,"6"}))("stringstring"),
+ ok.
+
+pattern(suite) -> [];
+pattern(_Config) ->
+ RE1 = "[a-z]{5}",
+ ?line {ok,"calle"} =
+ (xmerl_xsd_type:facet_fun(string,{pattern,RE1}))
+ ("calle"),
+ ?line {error,{pattern_mismatch,"cal",RE1}} =
+ (xmerl_xsd_type:facet_fun(string,{pattern,RE1}))
+ ("cal"),
+ RE2 = "[A-Z]{2}\\d\\s\\d[A-Z]{2}",
+ ?line {ok,"AY2 3BC"} =
+ (xmerl_xsd_type:facet_fun(string,{pattern,RE2}))
+ ("AY2 3BC"),
+ ?line {error,{pattern_mismatch,"AY23BC",RE2}} =
+ (xmerl_xsd_type:facet_fun(string,{pattern,RE2}))
+ ("AY23BC").
+
+enumeration(suite) -> [];
+enumeration(_Config) ->
+ ?line {ok,"tomat"} =
+ (xmerl_xsd_type:facet_fun(string,{enumeration,["gurka","tomat","sallad"]}))("tomat"),
+ ?line {error,{enumeration,"morot",should_be_one_of,["gurka","tomat","sallad"]}} =
+ (xmerl_xsd_type:facet_fun(string,{enumeration,["gurka","tomat","sallad"]}))("morot"),
+ ok.
+
+whiteSpace(suite) -> [];
+whiteSpace(_Config) ->
+ ?line {ok,"gur ka"} = (xmerl_xsd_type:facet_fun(string,{whiteSpace,"collapse"}))(" gur\tka "),
+ ?line {ok," gur ka "} = (xmerl_xsd_type:facet_fun(string,{whiteSpace,"replace"}))(" gur\nka\t"),
+ ?line {ok," gurk\na\t"} = (xmerl_xsd_type:facet_fun(string,{whiteSpace,"preserve"}))(" gurk\na\t"),
+ ok.
+
+maxInclusive(suite) -> [];
+maxInclusive(_Config) ->
+ ?line {error,{maxInclusive,"3",should_be_less_than_or_equal_with,"2"}} =
+ (xmerl_xsd_type:facet_fun(integer,{maxInclusive,"2"}))("3"),
+
+ ?line {error,{maxInclusive,"3",should_be_less_than_or_equal_with,"2"}} =
+ (xmerl_xsd_type:facet_fun(decimal,{maxInclusive,"2"}))("3"),
+ ?line {error,{maxInclusive,_,should_be_less_than_or_equal_with,_}} =
+ (xmerl_xsd_type:facet_fun(decimal,{maxInclusive,"2.234"}))("2.235"),
+ ?line {error,{maxInclusive,_,should_be_less_than_or_equal_with,_}} =
+ (xmerl_xsd_type:facet_fun(decimal,{maxInclusive,"-2.222"}))("-2.221"),
+
+ ?line {error,{maxInclusive,_,should_be_less_than_or_equal_with,_}} =
+ (xmerl_xsd_type:facet_fun(double,{maxInclusive,"2.333"}))("INF"),
+ ?line {error,{maxInclusive,_,should_be_less_than_or_equal_with,_}} =
+ (xmerl_xsd_type:facet_fun(double,{maxInclusive,"1E3"}))("1001"),
+
+ ?line {error,{maxInclusive,_,should_be_less_than_or_equal_with,_}} =
+ (xmerl_xsd_type:facet_fun(float,{maxInclusive,"-0.1"}))("-0"),
+ ?line {error,{maxInclusive,_,should_be_less_than_or_equal_with,_}} =
+ (xmerl_xsd_type:facet_fun(float,{maxInclusive,"0"}))("0.01"),
+
+ ?line {ok,"3"} = (xmerl_xsd_type:facet_fun(integer,{maxInclusive,"3"}))("3"),
+
+ ?line {ok,"+100000.00"} =
+ (xmerl_xsd_type:facet_fun(decimal,{maxInclusive,"1E6"}))("+100000.00"),
+ ?line {ok,"12678967.543222"} =
+ (xmerl_xsd_type:facet_fun(decimal,{maxInclusive,"12678967.543233"}))("12678967.543222"),
+
+ ?line {ok,"3.2E-11"} =
+ (xmerl_xsd_type:facet_fun(double,{maxInclusive,"2E-10"}))("3.2E-11"),
+ ?line {ok,"10E20"} =
+ (xmerl_xsd_type:facet_fun(double,{maxInclusive,"INF"}))("10E20"),
+ ?line {ok,"0.127"} =
+ (xmerl_xsd_type:facet_fun(double,{maxInclusive,"12.78e-2"}))("0.127"),
+
+ ?line {ok,"1267.43233E12"} = (xmerl_xsd_type:facet_fun(float,{maxInclusive,"1267.43233E12"}))("1267.43233E12"),
+ ?line {ok,"34E-26"} = (xmerl_xsd_type:facet_fun(float,{maxInclusive,"33E-25"}))("34E-26"),
+
+ ?line {ok,"2007-10-26T12:00:00+03:00"} =
+ (xmerl_xsd_type:facet_fun(dateTime,{maxInclusive,"2007-10-26T12:00:00+03:00"}))("2007-10-26T12:00:00+03:00"),
+ ?line {ok,"2007-10-26T11:00:00+03:00"} =
+ (xmerl_xsd_type:facet_fun(dateTime,{maxInclusive,"2007-10-26T12:00:00+03:00"}))("2007-10-26T11:00:00+03:00"),
+ ?line {error,{maxInclusive,_,should_be_less_than_or_equal_with,_}} =
+ (xmerl_xsd_type:facet_fun(dateTime,{maxInclusive,"2007-10-26T12:00:00+03:00"}))("2007-10-26T12:00:00"),
+
+ ?line {ok,"P1Y2M3DT10H30M"} =
+ (xmerl_xsd_type:facet_fun(duration,{maxInclusive,"P1Y2M4D"}))("P1Y2M3DT10H30M"),
+ ?line {error,{maxInclusive,_,should_be_less_than_or_equal_with,_}} =
+ (xmerl_xsd_type:facet_fun(duration,{maxInclusive,"P1Y2M3DT10H"}))("P1Y2M3DT10H30M"),
+ ok.
+
+maxExclusive(suite) -> [];
+maxExclusive(_Config) ->
+ ?line {error,{maxExclusive,"2",not_less_than,"2"}} =
+ (xmerl_xsd_type:facet_fun(integer,{maxExclusive,"2"}))("2"),
+ ?line {error,{maxExclusive,"-19999",not_less_than,"-20000"}} =
+ (xmerl_xsd_type:facet_fun(integer,{maxExclusive,"-20000"}))("-19999"),
+
+ ?line {error,{maxExclusive,"3.0000",not_less_than,"2.9999"}} =
+ (xmerl_xsd_type:facet_fun(decimal,{maxExclusive,"2.9999"}))("3.0000"),
+ ?line {error,{maxExclusive,_,not_less_than,_}} =
+ (xmerl_xsd_type:facet_fun(decimal,{maxExclusive,"2.234"}))("2.234"),
+ ?line {error,{maxExclusive,_,not_less_than,_}} =
+ (xmerl_xsd_type:facet_fun(decimal,{maxExclusive,"-2.22222222"}))("-2.22222222"),
+
+ ?line {error,{maxExclusive,_,not_less_than,_}} =
+ (xmerl_xsd_type:facet_fun(double,{maxExclusive,"2.333E23"}))("INF"),
+ ?line {error,{maxExclusive,_,not_less_than,_}} =
+ (xmerl_xsd_type:facet_fun(double,{maxExclusive,"1E3"}))("1000"),
+ ?line {error,{maxExclusive,_,not_less_than,_}} =
+ (xmerl_xsd_type:facet_fun(double,{maxExclusive,"1E-13"}))("0.999E-12"),
+
+ ?line {error,{maxExclusive,_,not_less_than,_}} =
+ (xmerl_xsd_type:facet_fun(float,{maxExclusive,"-0.1"}))("-0.01E1"),
+ ?line {error,{maxExclusive,_,not_less_than,_}} =
+ (xmerl_xsd_type:facet_fun(float,{maxExclusive,"-1E-1"}))("-0"),
+
+ ?line {ok,"-4"} = (xmerl_xsd_type:facet_fun(integer,{maxExclusive,"3"}))("-4"),
+
+ ?line {ok,"+100000.00"} =
+ (xmerl_xsd_type:facet_fun(decimal,{maxExclusive,"1E6"}))("+100000.00"),
+ %% must support 18 digits
+ ?line {ok,"12678967.5432323456"} =
+ (xmerl_xsd_type:facet_fun(decimal,{maxExclusive,"12678967.5432323457"}))("12678967.5432323456"),
+
+ ?line {ok,"3.2E-11"} =
+ (xmerl_xsd_type:facet_fun(double,{maxExclusive,"2E-10"}))("3.2E-11"),
+ ?line {ok,"10E20"} =
+ (xmerl_xsd_type:facet_fun(double,{maxExclusive,"INF"}))("10E20"),
+ ?line {ok,"0.127"} =
+ (xmerl_xsd_type:facet_fun(double,{maxExclusive,"12.78e-2"}))("0.127"),
+
+ ?line {ok,"1267.43233E11"} = (xmerl_xsd_type:facet_fun(float,{maxExclusive,"1267.43233E12"}))("1267.43233E11"),
+ ?line {ok,"34E-26"} = (xmerl_xsd_type:facet_fun(float,{maxExclusive,"33E-25"}))("34E-26"),
+
+ ?line {ok,"P1Y2M3DT10H30M"} = (xmerl_xsd_type:facet_fun(duration,{maxExclusive,"P1Y2M4D"}))("P1Y2M3DT10H30M"),
+
+ ?line {ok,"2006-09-06T19:17:45Z"} = (xmerl_xsd_type:facet_fun(dateTime,{maxExclusive,"2006-09-06T19:17:46Z"}))("2006-09-06T19:17:45Z"),
+ ok.
+
+minExclusive(suite) -> [];
+minExclusive(_Config) ->
+ ?line {error,{minExclusive,"2",not_greater_than,"2"}} =
+ (xmerl_xsd_type:facet_fun(integer,{minExclusive,"2"}))("2"),
+ ?line {error,{minExclusive,"-20001",not_greater_than,"-20000"}} =
+ (xmerl_xsd_type:facet_fun(integer,{minExclusive,"-20000"}))("-20001"),
+
+ ?line {error,{minExclusive,"2.9999",not_greater_than,"2.9999"}} =
+ (xmerl_xsd_type:facet_fun(decimal,{minExclusive,"2.9999"}))("2.9999"),
+ ?line {error,{minExclusive,_,not_greater_than,_}} =
+ (xmerl_xsd_type:facet_fun(decimal,{minExclusive,"-123456789.123456788"}))("-123456789.123456789"),
+ ?line {error,{minExclusive,_,not_greater_than,_}} =
+ (xmerl_xsd_type:facet_fun(decimal,{minExclusive,"-2.222222000"}))("-2.22222222"),
+
+ ?line {error,{minExclusive,_,not_greater_than,_}} =
+ (xmerl_xsd_type:facet_fun(double,{minExclusive,"INF"}))("2.333E23"),
+ ?line {error,{minExclusive,_,not_greater_than,_}} =
+ (xmerl_xsd_type:facet_fun(double,{minExclusive,"1E3"}))("1000"),
+ ?line {error,{minExclusive,_,not_greater_than,_}} =
+ (xmerl_xsd_type:facet_fun(double,{minExclusive,"1E-13"}))("0.999E-14"),
+
+ ?line {error,{minExclusive,_,not_greater_than,_}} =
+ (xmerl_xsd_type:facet_fun(float,{minExclusive,"-0.1"}))("-0.01E1"),
+ ?line {error,{minExclusive,_,not_greater_than,_}} =
+ (xmerl_xsd_type:facet_fun(float,{minExclusive,"-0"}))("-1E-1"),
+
+ ?line {ok,"4"} = (xmerl_xsd_type:facet_fun(integer,{minExclusive,"-3"}))("4"),
+
+ ?line {ok,"+1000001.00"} =
+ (xmerl_xsd_type:facet_fun(decimal,{minExclusive,"1E6"}))("+1000001.00"),
+ %% must support 18 digits
+ ?line {ok,"12678967.5432323456"} =
+ (xmerl_xsd_type:facet_fun(decimal,{minExclusive,"12678967.54323234555"}))("12678967.5432323456"),
+
+ ?line {ok,"3.2E-11"} =
+ (xmerl_xsd_type:facet_fun(double,{minExclusive,"2E-12"}))("3.2E-11"),
+ ?line {ok,"10E20"} =
+ (xmerl_xsd_type:facet_fun(double,{minExclusive,"-INF"}))("10E20"),
+ ?line {ok,"0.1279"} =
+ (xmerl_xsd_type:facet_fun(double,{minExclusive,"12.78e-2"}))("0.1279"),
+
+ ?line {ok,"126743.233E11"} = (xmerl_xsd_type:facet_fun(float,{minExclusive,"1267.43233E12"}))("126743.233E11"),
+ ?line {ok,"34E-26"} = (xmerl_xsd_type:facet_fun(float,{minExclusive,"33E-27"}))("34E-26"),
+
+ ?line {ok,"P1Y2M3DT10H30M"} = (xmerl_xsd_type:facet_fun(duration,{minExclusive,"P1Y2M3D"}))("P1Y2M3DT10H30M"),
+
+ ?line {ok,"2006-09-06T19:17:45Z"} = (xmerl_xsd_type:facet_fun(dateTime,{minExclusive,"2006-09-06T19:17:44Z"}))("2006-09-06T19:17:45Z"),
+ ok.
+
+minInclusive(suite) -> [];
+minInclusive(_Config) ->
+ ?line {error,{minInclusive,"1",not_greater_than_or_equal_with,"2"}} =
+ (xmerl_xsd_type:facet_fun(integer,{minInclusive,"2"}))("1"),
+ ?line {error,{minInclusive,"-20001",not_greater_than_or_equal_with,
+ "-20000"}} =
+ (xmerl_xsd_type:facet_fun(integer,{minInclusive,"-20000"}))("-20001"),
+
+ ?line {error,{minInclusive,"2.9999",not_greater_than_or_equal_with,
+ "2.99999"}} =
+ (xmerl_xsd_type:facet_fun(decimal,{minInclusive,"2.99999"}))("2.9999"),
+ ?line {error,{minInclusive,_,not_greater_than_or_equal_with,_}} =
+ (xmerl_xsd_type:facet_fun(decimal,{minInclusive,"-123456789.123456788"}))("-123456789.123456789"),
+ ?line {error,{minInclusive,_,not_greater_than_or_equal_with,_}} =
+ (xmerl_xsd_type:facet_fun(decimal,{minInclusive,"-2.222222000"}))("-2.22222222"),
+
+ ?line {error,{minInclusive,_,not_greater_than_or_equal_with,_}} =
+ (xmerl_xsd_type:facet_fun(double,{minInclusive,"2.333E23"}))("-INF"),
+ ?line {error,{minInclusive,_,not_greater_than_or_equal_with,_}} =
+ (xmerl_xsd_type:facet_fun(double,{minInclusive,"1E3"}))("100"),
+ ?line {error,{minInclusive,_,not_greater_than_or_equal_with,_}} =
+ (xmerl_xsd_type:facet_fun(double,{minInclusive,"1E-13"}))("0.999E-14"),
+
+ ?line {error,{minInclusive,_,not_greater_than_or_equal_with,_}} =
+ (xmerl_xsd_type:facet_fun(float,{minInclusive,"-0.1"}))("-0.1E1"),
+ ?line {error,{minInclusive,_,not_greater_than_or_equal_with,_}} =
+ (xmerl_xsd_type:facet_fun(float,{minInclusive,"-0"}))("-1E-1"),
+ ?line {error,_}=(xmerl_xsd_type:facet_fun(float,{minInclusive,"10E-10"}))("10E-11"),
+
+ ?line {ok,"4"} = (xmerl_xsd_type:facet_fun(integer,{minInclusive,"-3"}))("4"),
+
+ ?line {ok,"+1000000.00"} =
+ (xmerl_xsd_type:facet_fun(decimal,{minInclusive,"1E6"}))("+1000000.00"),
+ %% must support 18 digits
+ ?line {ok,"12678967.5432323456"} =
+ (xmerl_xsd_type:facet_fun(decimal,{minInclusive,"12678967.54323234555"}))("12678967.5432323456"),
+
+ ?line {ok,"3.2E-11"} =
+ (xmerl_xsd_type:facet_fun(double,{minInclusive,"2E-12"}))("3.2E-11"),
+ ?line {ok,"10E20"} =
+ (xmerl_xsd_type:facet_fun(double,{minInclusive,"-INF"}))("10E20"),
+ ?line {ok,"0.1279"} =
+ (xmerl_xsd_type:facet_fun(double,{minInclusive,"12.78e-2"}))("0.1279"),
+
+ ?line {ok,"126743.233E11"} = (xmerl_xsd_type:facet_fun(float,{minInclusive,"1267.43233E12"}))("126743.233E11"),
+ ?line {ok,"34E-26"} = (xmerl_xsd_type:facet_fun(float,{minInclusive,"33E-27"}))("34E-26"),
+ ?line {ok,"34E-26"} = (xmerl_xsd_type:facet_fun(float,{minInclusive,"340E-27"}))("34E-26"),
+
+ ?line {ok,"P1Y2M3DT10H30M"} = (xmerl_xsd_type:facet_fun(duration,{minInclusive,"P1Y2M3D"}))("P1Y2M3DT10H30M"),
+
+ ?line {ok,"2006-09-06T19:17:45Z"} = (xmerl_xsd_type:facet_fun(dateTime,{minInclusive,"2006-09-06T19:17:45Z"}))("2006-09-06T19:17:45Z"),
+ ok.
+
+totalDigits(suite) -> [];
+totalDigits(_Config) ->
+ ?line {error,{totalDigits,4,to_many_digits}} =
+ (xmerl_xsd_type:facet_fun(integer,{totalDigits,"3"}))("3456"),
+ ?line {error,{totalDigits,4,to_many_digits}} =
+ (xmerl_xsd_type:facet_fun(decimal,{totalDigits,"3"}))("00345.600"),
+
+ ?line {ok,"555"} =
+ (xmerl_xsd_type:facet_fun(integer,{totalDigits,"3"}))("555"),
+ ?line {ok,"555"} =
+ (xmerl_xsd_type:facet_fun(integer,{totalDigits,"7"}))("555"),
+ ?line {ok,"555.555"} =
+ (xmerl_xsd_type:facet_fun(decimal,{totalDigits,"7"}))("555.555"),
+ ?line {ok,"555.555000000"} =
+ (xmerl_xsd_type:facet_fun(decimal,{totalDigits,"7"}))("555.555000000"),
+ ok.
+
+fractionDigits(suite) -> [];
+fractionDigits(_Config) ->
+ ?line {error,{fractionDigits,3,to_many_digits_in,"555.555000000"}} =
+ (xmerl_xsd_type:facet_fun(decimal,{fractionDigits,"2"}))("555.555000000"),
+ ?line {error,{fractionDigits,6,to_many_digits_in,"555.555001"}} =
+ (xmerl_xsd_type:facet_fun(decimal,{fractionDigits,"5"}))("555.555001"),
+
+ ?line {ok,"555.55500"} =
+ (xmerl_xsd_type:facet_fun(decimal,{fractionDigits,"5"}))("555.55500"),
+ ?line {ok,"555"} =
+ (xmerl_xsd_type:facet_fun(decimal,{fractionDigits,"5"}))("555"),
+ ?line {ok,"555.000"} =
+ (xmerl_xsd_type:facet_fun(decimal,{fractionDigits,"0"}))("555.000"),
+
+ ?line {ok,"555"} =
+ (xmerl_xsd_type:facet_fun(integer,{fractionDigits,"0"}))("555"),
+ ok.
+
+%% some block testing of dateTime and duration comparisons
+compare_dateTime(suite) -> [];
+compare_dateTime(_Config) ->
+ %% comparison results according to table in section 3.2.7.4 of XML
+ %% Schema part 2
+ ?line lt = xmerl_xsd_type:compare_dateTime("2000-01-15T00:00:00",
+ "2000-02-15T00:00:00"),
+ ?line gt = xmerl_xsd_type:compare_dateTime("2000-02-15T00:00:00",
+ "2000-01-15T00:00:00"),
+
+ ?line lt = xmerl_xsd_type:compare_dateTime("2000-01-15T12:00:00",
+ "2000-01-16T12:00:00Z"),
+ ?line gt = xmerl_xsd_type:compare_dateTime("2000-01-16T12:00:00Z",
+ "2000-01-15T12:00:00"),
+
+ ?line indefinite = xmerl_xsd_type:compare_dateTime("2000-01-01T12:00:00",
+ "1999-12-31T23:00:00Z"),
+ ?line indefinite = xmerl_xsd_type:compare_dateTime("1999-12-31T23:00:00Z",
+ "2000-01-01T12:00:00"),
+
+ ?line indefinite = xmerl_xsd_type:compare_dateTime("2000-01-16T12:00:00",
+ "2000-01-16T12:00:00Z"),
+ ?line indefinite = xmerl_xsd_type:compare_dateTime("2000-01-16T12:00:00Z",
+ "2000-01-16T12:00:00"),
+
+ ?line indefinite = xmerl_xsd_type:compare_dateTime("2000-01-16T00:00:00",
+ "2000-01-16T12:00:00Z"),
+ ?line indefinite = xmerl_xsd_type:compare_dateTime("2000-01-16T12:00:00Z",
+ "2000-01-16T00:00:00"),
+
+ %% example in appendix E.1 in XML Schema part 2.
+ ?line {2001,4,17,19,23,17.3000,{pos,0,0}} =
+ xmerl_xsd_type:add_duration2dateTime("2000-01-12T12:13:14Z",
+ "P1Y3M5DT7H10M3.3S").
+
+compare_duration(suite) -> [];
+compare_duration(_Config) ->
+ %% order relations according to section 3.2.6.2 in XML Schema
+ %% part2.
+ ?line gt = xmerl_xsd_type:compare_durations("P1Y","P364D"),
+ ?line indefinite = xmerl_xsd_type:compare_durations("P1Y","P365D"),
+ ?line indefinite = xmerl_xsd_type:compare_durations("P1Y","P366D"),
+ ?line lt = xmerl_xsd_type:compare_durations("P1Y","P367D"),
+
+ ?line gt = xmerl_xsd_type:compare_durations("P1M","P27D"),
+ ?line indefinite = xmerl_xsd_type:compare_durations("P1M","P28D"),
+ ?line indefinite = xmerl_xsd_type:compare_durations("P1M","P29D"),
+ ?line indefinite = xmerl_xsd_type:compare_durations("P1M","P30D"),
+ ?line indefinite = xmerl_xsd_type:compare_durations("P1M","P31D"),
+ ?line lt = xmerl_xsd_type:compare_durations("P1M","P32D"),
+
+ ?line gt = xmerl_xsd_type:compare_durations("P5M","P149D"),
+ ?line indefinite = xmerl_xsd_type:compare_durations("P5M","P150D"),
+ ?line indefinite = xmerl_xsd_type:compare_durations("P5M","P151D"),
+ ?line indefinite = xmerl_xsd_type:compare_durations("P5M","P152D"),
+ ?line indefinite = xmerl_xsd_type:compare_durations("P5M","P153D"),
+ ?line lt = xmerl_xsd_type:compare_durations("P5M","P154D").
+
+
+po(suite) -> [];
+po(Config) ->
+ ?line {E,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "po.xml"]),[]),
+ ?line {E,_} = xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "po.xsd"]),E,[]).
+
+po1(suite) -> [];
+po1(Config) ->
+ ?line {E,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "po1.xml"]),[]),
+ ?line {E2,_} = xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "po1.xsd"]),E,[]),
+ ?line ok = xmerl_test_lib:cmp_element(E,E2).
+
+po2(suite) -> [];
+po2(Config) ->
+ ?line {E,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "po2.xml"]),[]),
+ ?line {E2,_} = xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "po1.xsd"]),E,[]),
+ ?line ok = xmerl_test_lib:cmp_element(E,E2).
+
+ipo(suite) -> [];
+ipo(Config) ->
+ ?line {E,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "ipo.xml"]),[]),
+ ?line {VE,_} = xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "ipo.xsd"]),E,[]),
+ ?line ok = xmerl_test_lib:cmp_element(E,VE).
+
+ipo_redefine(suite) -> [];
+ipo_redefine(Config) ->
+ ?line {E,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "ipo_redefine.xml"]),[]),
+ ?line {VE,_} = xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "ipo_redefine.xsd"]),E,[]),
+ ?line ok = xmerl_test_lib:cmp_element(E,VE).
+
+'4Q99'(suite) -> [];
+'4Q99'(Config) ->
+ ?line {E,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "4Q99.xml"]),[]),
+ %% the import in report.xsd lacks schemaLocation, so the imported
+ %% namespace definitions have to be loaded separately.
+ ?line {ok,S} =
+ xmerl_xsd:process_schema(filename:join([?config(data_dir,Config),
+ "ipo.xsd"])),
+ ?line {VE,_} = xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "report.xsd"]),E,[{state,S}]),
+ ?line ok = xmerl_test_lib:cmp_element(E,VE),
+
+ %% report2.xsd has an import element with a schemaLocation attribute
+ ?line {VE,_} = xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "report2.xsd"]),E,[]).
+
+small(suite) -> [];
+small(Config) ->
+ ?line {E=#xmlElement{},_} =
+ xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "small.xml"]),[]),
+ ?line {VE=#xmlElement{},_} =
+ xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "small.xsd"]),E,[]),
+ ?line #xmlElement{attributes=Atts,content=C} = VE,
+ ?line C = E#xmlElement.content,
+ %% The attribute orderStatus with default value was absent in small.xml
+
+ %% Test of validation "on the fly" when parsing XML.
+ ?line {VE,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "small.xml"]),
+ [{validation,schema},
+ {schemaLocation,[{"small",filename:join(?config(data_dir,Config),"small.xsd")}]}]),
+ ?line {VE,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "small.xml"]),
+ [{validation,schema}]),
+ ?line true = lists:keymember(orderStatus,#xmlAttribute.name,Atts).
+
+complexType1(suite) -> [];
+complexType1(Config) ->
+ ?line {E1=#xmlElement{},_} =
+ xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "complexTypes1.xml"]),[]),
+ ?line {VE1=#xmlElement{},_} =
+ xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "complexTypes.xsd"]),E1,[]),
+ ?line ok = xmerl_test_lib:cmp_element(E1,VE1),
+
+ ?line {E2=#xmlElement{},_} =
+ xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "complexTypes2.xml"]),[]),
+ ?line {VE2=#xmlElement{},_} =
+ xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "complexTypes.xsd"]),E2,[]),
+ ?line ok = xmerl_test_lib:cmp_element(E2,VE2).
+
+model_group_all(suite) -> [];
+model_group_all(Config) ->
+ ?line {E=#xmlElement{},_} =
+ xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "po1.xml"]),[]),
+ ?line {E,_} =
+ xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "po1_all.xsd"]),E,[]),
+
+ ?line {E1=#xmlElement{},_} =
+ xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "po1_all1.xml"]),[]),
+ ?line {E1,_} =
+ xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "po1_all.xsd"]),E1,[]),
+
+ ?line {E2=#xmlElement{},_} =
+ xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "po1_all2.xml"]),[]),
+ ?line {E2,_} =
+ xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "po1_all.xsd"]),E2,[]),
+
+ ?line {E3=#xmlElement{},_} =
+ xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "po1_all_err1.xml"]),[]),
+ ?line {error,_Reason1} =
+ xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "po1_all.xsd"]),E3,[]),
+
+
+ ?line {E4=#xmlElement{},_} =
+ xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "po1_all_err2.xml"]),[]),
+ ?line {error,_Reason2} =
+ xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "po1_all.xsd"]),E4,[]).
+
+substitutionGroup(suite) -> [];
+substitutionGroup(Config) ->
+ ?line {E,_} =
+ xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "ipo_substGroup.xml"]),[]),
+ ?line {E,_} =
+ xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "ipo_substGroup.xsd"]),E,[]).
+attributeGroup(suite) -> [];
+attributeGroup(Config) ->
+ ?line {E,_} =
+ xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "po_attrGroup.xml"]),[]),
+ ?line {E,_} =
+ xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "po_attrGroup.xsd"]),E,[]).
+test_key1(suite) -> [];
+test_key1(Config) ->
+ ?line {E,_} =
+ xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "vehicle2.xml"]),[]),
+ ?line {E,_} =
+ xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "vehicle.xsd"]),E,[]),
+
+ ?line {E2,_} =
+ xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "vehicle.xml"]),[]),
+ ?line {error,L2} =
+ xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "vehicle.xsd"]),E2,[]),
+ ?line 10 = erlang:length(L2),
+
+ ?line {E3 = #xmlElement{},_} =
+ xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "vehicle3.xml"]),[]),
+ ?line {E3 = #xmlElement{},_} =
+ xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "vehicle.xsd"]),E3,[]).
+
+sis1(suite) -> [];
+sis1(Config) ->
+ ?line {E,_} =
+ xmerl_scan:file(filename:join([?config(data_dir,Config),sis,
+ "instance.xml"]),[]),
+ ?line {#xmlElement{},_} =
+ xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),sis,
+ "IntegratedSite.xsd"]),E,[]).
+sis2(suite) -> [];
+sis2(Config) ->
+ ?line {BS_E,_} =
+ xmerl_scan:file(filename:join([?config(data_dir,Config),sis,
+ "bs_mim.xml"]),[]),
+ ?line {SW_E,_} =
+ xmerl_scan:file(filename:join([?config(data_dir,Config),sis,
+ "swm_mim.xml"]),[]),
+ ?line {HW_E,_} =
+ xmerl_scan:file(filename:join([?config(data_dir,Config),sis,
+ "hwm_mim.xml"]),[]),
+
+ ?line {#xmlElement{},_} =
+ xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),sis,
+ "mim.xsd"]),BS_E,[]),
+ ?line {#xmlElement{},_} =
+ xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),sis,
+ "mim.xsd"]),SW_E,[]),
+ ?line {#xmlElement{},_} =
+ xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),sis,
+ "mim.xsd"]),HW_E,[]).
+
+state2file_file2state(suite) -> [];
+state2file_file2state(Config) ->
+ ?line {E,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "po.xml"]),[]),
+ ?line {ok,S} = xmerl_xsd:process_schema(filename:join([?config(data_dir,Config),"po.xsd"])),
+ ?line {E,_} = xmerl_xsd:validate(E,S),
+ ?line ok = xmerl_xsd:state2file(S),
+ ?line {ok,S} = xmerl_xsd:file2state(filename:join([?config(data_dir,Config),"po.xss"])),
+ ?line {E,_} = xmerl_xsd:validate(E,S),
+
+ ?line ok = xmerl_xsd:state2file(S,filename:join([?config(data_dir,Config),"po_state"])),
+ ?line {ok,S} = xmerl_xsd:file2state(filename:join([?config(data_dir,Config),"po_state.xss"])),
+
+ ?line {E,_} = xmerl_xsd:validate(E,S).
+
+
+union(suite) -> [];
+union(Config) ->
+ ?line {E,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "instance.xml"])),
+
+ ?line {_E2 = #xmlElement{},_} = xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),"measCollec.xsd"]),E).
+
+
+ticket_6910(suite) -> [];
+ticket_6910(Config) ->
+ ?line {E,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),
+ sis,"dummy_action_mim.xml"])),
+ ?line {_E2 = #xmlElement{},_} =
+ xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ sis,"mim2.xsd"]),E).
+ticket_7165(suite) -> [];
+ticket_7165(Config) ->
+ %% The validation option seems not to work
+ ?line {E,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "ticket_7288.xml"]),
+ [{validation, schema}]),
+ %% The option xsdbase gave {error, enoent}.
+ ?line {ok,_} = xmerl_xsd:process_schema("CxDataType_Rel5.xsd", [{xsdbase, ?config(data_dir,Config)}]).
+
+
+
+ticket_7190(suite) -> [];
+ticket_7190(Config) ->
+ ?line {E,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),
+ "int.xml"])),
+ ?line {_E2 = #xmlElement{},_} =
+ xmerl_xsd:process_validate(filename:join([?config(data_dir,Config),
+ "simple_int.xsd"]),E).
+ticket_7288(suite) -> [];
+ticket_7288(Config) ->
+ %% The schema table in the state where deleted by xmerl_xsd:validate if there was an error.
+ ?line {E,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),"ticket_7288.xml"])),
+
+ ?line {ok,S} = xmerl_xsd:process_schema(filename:join([?config(data_dir,Config),"CxDataType_Rel5.xsd"])),
+
+ ?line {error, EL} = xmerl_xsd:validate(E, S),
+
+ ?line {error, EL} = xmerl_xsd:validate(E, S).
+
+ticket_7736(suite) -> [];
+ticket_7736(Config) ->
+ DataDir = ?config(data_dir,Config),
+ ?line {ok, State } =
+ xmerl_xsd:process_schema(filename:join([DataDir,"enum_bug.xsd"])),
+
+ ?line {Entity ,_} =
+ xmerl_scan:file(filename:join([DataDir,"enum_bug.xml"])),
+
+ ?line {#xmlElement{},_} = xmerl_xsd:validate(Entity, State).
+
+ticket_8599(suite) -> [];
+ticket_8599(Config) ->
+ ?line {E,_} = xmerl_scan:file(filename:join([?config(data_dir,Config),"ticket_8599.xml"])),
+
+ ?line {ok, S} = xmerl_xsd:process_schema(filename:join([?config(data_dir,Config),"ticket_8599.xsd"])),
+
+ ?line {{xmlElement,persons,persons,_,_,_,_,_,_,_,_,_},_GlobalState} = xmerl_xsd:validate(E, S).
+
+
+ticket_9410(suite) -> [];
+ticket_9410(Config) ->
+ file:set_cwd(filename:join([?config(data_dir,Config),".."])),
+ ?line {ok, _S} = xmerl_xsd:process_schema("xmerl_xsd_SUITE_data/small.xsd").
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/4Q99.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/4Q99.xml
new file mode 100644
index 0000000000..a0c4df72bd
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/4Q99.xml
@@ -0,0 +1,25 @@
+<purchaseReport
+ xmlns="http://www.example.com/Report"
+ period="P3M" periodEnding="1999-12-31">
+
+ <regions>
+ <zip code="95819">
+ <part number="872-AA" quantity="1"/>
+ <part number="926-AA" quantity="1"/>
+ <part number="833-AA" quantity="1"/>
+ <part number="455-BX" quantity="1"/>
+ </zip>
+ <zip code="63143">
+ <part number="455-BX" quantity="4"/>
+ </zip>
+ </regions>
+
+ <parts>
+ <part number="872-AA">Lawnmower</part>
+ <part number="926-AA">Baby Monitor</part>
+ <part number="833-AA">Lapis Necklace</part>
+ <part number="455-BX">Sturdy Shelves</part>
+ </parts>
+
+</purchaseReport>
+
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/CxDataType_Rel5.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/CxDataType_Rel5.xsd
new file mode 100644
index 0000000000..8a26fd1492
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/CxDataType_Rel5.xsd
@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
+ <xs:simpleType name="tPriority" final="list restriction">
+ <xs:restriction base="xs:int">
+ <xs:minInclusive value="0"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="tProfilePartIndicator" final="list restriction">
+ <xs:restriction base="xs:unsignedByte">
+ <xs:maxInclusive value="1"/>
+ <xs:enumeration value="0">
+ <xs:annotation>
+ <xs:documentation>
+ <label xml:lang="en">REGISTERED</label>
+ <definition xml:lang="en">iFC is part of the registered profile</definition>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="1">
+ <xs:annotation>
+ <xs:documentation>
+ <label xml:lang="en">UNREGISTERED</label>
+ <definition xml:lang="en">iFC is part of the unregistered profile</definition>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="tGroupID" final="list restriction">
+ <xs:restriction base="xs:int">
+ <xs:minInclusive value="0"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="tDefaultHandling" final="list restriction">
+ <xs:restriction base="xs:unsignedByte">
+ <xs:maxInclusive value="1"/>
+ <xs:enumeration value="0">
+ <xs:annotation>
+ <xs:documentation>
+ <label xml:lang="en">SESSION_CONTINUED</label>
+ <definition xml:lang="en">Session Continued</definition>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="1">
+ <xs:annotation>
+ <xs:documentation>
+ <label xml:lang="en">SESSION_TERMINATED</label>
+ <definition xml:lang="en">Session Terminated</definition>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="tDirectionOfRequest" final="list restriction">
+ <xs:restriction base="xs:unsignedByte">
+ <xs:maxInclusive value="3"/>
+ <xs:enumeration value="0">
+ <xs:annotation>
+ <xs:documentation>
+ <label xml:lang="en">ORIGINATING_SESSION</label>
+ <definition xml:lang="en">Originating Session</definition>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="1">
+ <xs:annotation>
+ <xs:documentation>
+ <label xml:lang="en">TERMINATING_REGISTERED</label>
+ <definition xml:lang="en">Terminating Session for registered user</definition>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ <xs:enumeration value="2">
+ <xs:annotation>
+ <xs:documentation>
+ <label xml:lang="en">TERMINATING_UNREGISTERED</label>
+ <definition xml:lang="en">Terminating Session for unregistered user</definition>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="tPrivateID" final="list restriction">
+ <xs:restriction base="xs:anyURI"/>
+ </xs:simpleType>
+ <xs:simpleType name="tSIP_URL" final="list restriction">
+ <xs:restriction base="xs:anyURI"/>
+ </xs:simpleType>
+ <xs:simpleType name="tTEL_URL" final="list restriction">
+ <xs:restriction base="xs:anyURI"/>
+ </xs:simpleType>
+ <xs:simpleType name="tIdentity" final="list restriction">
+ <xs:union memberTypes="tSIP_URL tTEL_URL"/>
+ </xs:simpleType>
+ <xs:simpleType name="tServiceInfo" final="list restriction">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="0"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="tString" final="list restriction">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="0"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="tBool">
+ <xs:restriction base="xs:boolean"/>
+ </xs:simpleType>
+ <xs:simpleType name="tSubscribedMediaProfileId" final="list restriction">
+ <xs:restriction base="xs:int">
+ <xs:minInclusive value="0"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="tExtension">
+ <xs:sequence>
+ <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tIMSSubscription">
+ <xs:sequence>
+ <xs:element name="PrivateID" type="tPrivateID"/>
+ <xs:element name="ServiceProfile" type="tServiceProfile" maxOccurs="unbounded"/>
+ <xs:element name="Extension" type="tExtension" minOccurs="0"/>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tServiceProfile">
+ <xs:sequence>
+ <xs:element name="PublicIdentity" type="tPublicIdentity" maxOccurs="unbounded"/>
+ <xs:element name="CoreNetworkServicesAuthorization" type="tCoreNetworkServicesAuthorization" minOccurs="0"/>
+ <xs:element name="InitialFilterCriteria" type="tInitialFilterCriteria" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Extension" type="tExtension" minOccurs="0"/>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tCoreNetworkServicesAuthorization">
+ <xs:sequence>
+ <xs:element name="SubscribedMediaProfileId" type="tSubscribedMediaProfileId" minOccurs="0"/>
+ <xs:element name="Extension" type="tExtension" minOccurs="0"/>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tInitialFilterCriteria">
+ <xs:sequence>
+ <xs:element name="Priority" type="tPriority"/>
+ <xs:element name="TriggerPoint" type="tTrigger" minOccurs="0"/>
+ <xs:element name="ApplicationServer" type="tApplicationServer"/>
+ <xs:element name="ProfilePartIndicator" type="tProfilePartIndicator" minOccurs="0"/>
+ <xs:element name="Extension" type="tExtension" minOccurs="0"/>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tTrigger">
+ <xs:sequence>
+ <xs:element name="ConditionTypeCNF" type="tBool"/>
+ <xs:element name="SPT" type="tSePoTri" maxOccurs="unbounded"/>
+ <xs:element name="Extension" type="tExtension" minOccurs="0"/>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tSePoTri">
+ <xs:sequence>
+ <xs:element name="ConditionNegated" type="tBool" default="0" minOccurs="0"/>
+ <xs:element name="Group" type="tGroupID" maxOccurs="unbounded"/>
+ <xs:choice>
+ <xs:element name="RequestURI" type="tString"/>
+ <xs:element name="Method" type="tString"/>
+ <xs:element name="SIPHeader" type="tHeader"/>
+ <xs:element name="SessionCase" type="tDirectionOfRequest"/>
+ <xs:element name="SessionDescription" type="tSessionDescription"/>
+ </xs:choice>
+ <xs:element name="Extension" type="tExtension" minOccurs="0"/>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tHeader">
+ <xs:sequence>
+ <xs:element name="Header" type="tString"/>
+ <xs:element name="Content" type="tString" minOccurs="0"/>
+ <xs:element name="Extension" type="tExtension" minOccurs="0"/>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tSessionDescription">
+ <xs:sequence>
+ <xs:element name="Line" type="tString"/>
+ <xs:element name="Content" type="tString" minOccurs="0"/>
+ <xs:element name="Extension" type="tExtension" minOccurs="0"/>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tApplicationServer">
+ <xs:sequence>
+ <xs:element name="ServerName" type="tSIP_URL"/>
+ <xs:element name="DefaultHandling" type="tDefaultHandling" minOccurs="0"/> <!-- the DefaultHandling element should not be sent by a Rel-5 HSS -->
+ <xs:element name="ServiceInfo" type="tServiceInfo" minOccurs="0"/>
+ <xs:element name="Extension" type="tExtension" minOccurs="0"/>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tPublicIdentity">
+ <xs:sequence>
+ <xs:element name="BarringIndication" type="tBool" default="0" minOccurs="0"/>
+ <xs:element name="Identity" type="tIdentity"/>
+ <xs:element name="Extension" type="tExtension" minOccurs="0"/>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="IMSSubscription" type="tIMSSubscription"/>
+</xs:schema>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/address.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/address.xsd
new file mode 100644
index 0000000000..147d1fe01e
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/address.xsd
@@ -0,0 +1,69 @@
+<schema targetNamespace="http://www.example.com/IPO"
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:ipo="http://www.example.com/IPO">
+
+ <annotation>
+ <documentation xml:lang="en">
+ Addresses for International Purchase order schema
+ Copyright 2000 Example.com. All rights reserved.
+ </documentation>
+ </annotation>
+
+ <complexType name="Address">
+ <sequence>
+ <element name="name" type="string"/>
+ <element name="street" type="string"/>
+ <element name="city" type="string"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="USAddress">
+ <complexContent>
+ <extension base="ipo:Address">
+ <sequence>
+ <element name="state" type="ipo:USState"/>
+ <element name="zip" type="positiveInteger"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="UKAddress">
+ <complexContent>
+ <extension base="ipo:Address">
+ <sequence>
+ <element name="postcode" type="ipo:UKPostcode"/>
+ </sequence>
+ <attribute name="exportCode" type="positiveInteger" fixed="1"/>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <!-- other Address derivations for more countries -->
+
+ <simpleType name="USState">
+ <restriction base="string">
+ <enumeration value="AK"/>
+ <enumeration value="AL"/>
+ <enumeration value="AR"/>
+ <enumeration value="PA"/>
+ <!-- and so on ... -->
+ </restriction>
+ </simpleType>
+
+ <!-- simple type definition for UKPostcode -->
+ <simpleType name="UKPostcode">
+ <restriction base="ipo:Postcode">
+ <pattern value="[A-Z]{2}\d\s\d[A-Z]{2}"/>
+ </restriction>
+ </simpleType>
+
+ <simpleType name="Postcode">
+ <restriction base="string">
+ <length value="7" fixed="true"/>
+ </restriction>
+ </simpleType>
+
+
+</schema>
+
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/complexTypes.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/complexTypes.xsd
new file mode 100644
index 0000000000..78140cda9b
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/complexTypes.xsd
@@ -0,0 +1,112 @@
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:po="http://www.example.com/ComplexTypes"
+ targetNamespace="http://www.example.com/ComplexTypes"
+ elementFormDefault="unqualified"
+ attributeFormDefault="unqualified">
+
+ <element name="purchaseOrder" type="po:PurchaseOrderType"/>
+
+ <element name="purchaseOrder2" type="po:PurchaseOrderType2"/>
+
+ <element name="comment" type="string"/>
+
+
+<complexType name="PurchaseOrderType2">
+ <sequence>
+ <choice>
+ <group ref="po:shipAndBill"/>
+ <element name="singleUSAddress" type="po:USAddress"/>
+ </choice>
+ <element ref="po:comment" minOccurs="0"/>
+ <element name="items" type="po:Items"/>
+ </sequence>
+ <attribute name="orderDate" type="date"/>
+</complexType>
+
+<group name="shipAndBill">
+ <sequence>
+ <element name="shipTo" type="po:USAddress"/>
+ <element name="billTo" type="po:USAddress"/>
+ </sequence>
+</group>
+
+
+
+ <complexType name="PurchaseOrderType">
+ <sequence>
+ <element name="shipTo" type="po:USAddress"/>
+ <element name="billTo" type="po:USAddress"/>
+ <element ref="po:comment" minOccurs="0"/>
+ <element name="items" type="po:Items"/>
+ </sequence>
+ <attribute name="orderDate" type="date"/>
+ </complexType>
+
+ <complexType name="USAddress">
+ <sequence>
+ <element name="name" type="string"/>
+ <element name="street" type="string"/>
+ <element name="city" type="string"/>
+ <element name="state" type="string"/>
+ <element name="zip" type="decimal"/>
+ <element name="contact" type="po:Contact" minOccurs="0"/>
+ </sequence>
+ <attribute name="country" type="NMTOKEN"
+ fixed="US"/>
+ </complexType>
+
+ <complexType name="Items">
+ <sequence>
+ <element name="item" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="productName" type="string"/>
+ <element name="quantity">
+ <simpleType>
+ <restriction base="positiveInteger">
+ <maxExclusive value="100"/>
+ </restriction>
+ </simpleType>
+ </element>
+ <element name="USPrice" type="decimal"/>
+ <element ref="po:comment" minOccurs="0"/>
+ <element name="shipDate" type="date" minOccurs="0"/>
+ </sequence>
+ <attribute name="partNum" type="po:SKU" use="required"/>
+ </complexType>
+ </element>
+ </sequence>
+ </complexType>
+
+ <complexType name="Contact">
+ <sequence>
+ <element name="phone" type="decimal"/>
+ <element name="mail" type="string" minOccurs="0"/>
+ <element name="e-mail" type="string"/>
+ <element name="cell-phone" type="decimal" minOccurs="0"/>
+ <element name="other" type="string" minOccurs="0"/>
+ <element name="prefCont" type="po:PreferredContact" minOccurs="0" maxOccurs="2"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="PreferredContact">
+ <choice>
+ <element name="phone" type="string"/>
+ <element name="mail" type="string"/>
+ <element name="e-mail" type="string"/>
+ <element name="cell-phone" type="string"/>
+ <element name="other" type="string"/>
+ </choice>
+ <attribute name="priority" type="NMTOKEN"
+ fixed="medium"/>
+ </complexType>
+
+ <!-- Stock Keeping Unit, a code for identifying products -->
+ <simpleType name="SKU">
+ <restriction base="string">
+ <pattern value="\d{3}-[A-Z]{2}"/>
+ </restriction>
+ </simpleType>
+
+</schema>
+
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/complexTypes1.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/complexTypes1.xml
new file mode 100644
index 0000000000..a46a562c37
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/complexTypes1.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<apo:purchaseOrder xmlns:apo="http://www.example.com/ComplexTypes"
+ orderDate="1999-10-20">
+ <shipTo country="US">
+ <name>Alice Smith</name>
+ <street>123 Maple Street</street>
+ <!-- etc. -->
+ <city>Mill Valley</city>
+ <state>CA</state>
+ <zip>90952</zip>
+ <contact>
+ <phone>081234567</phone>
+ <e-mail>[email protected]</e-mail>
+ <cell-phone>070122345</cell-phone>
+ <prefCont>
+ <cell-phone>070122345</cell-phone>
+ </prefCont>
+ </contact>
+ </shipTo>
+ <billTo country="US">
+ <name>Robert Smith</name>
+ <street>8 Oak Avenue</street>
+ <!-- etc. -->
+ <city>Old Town</city>
+ <state>PA</state>
+ <zip>95819</zip>
+ </billTo>
+ <apo:comment>Hurry, my lawn is going wild!</apo:comment>
+ <!-- etc. -->
+ <items>
+ <item partNum="872-AA">
+ <productName>Lawnmower</productName>
+ <quantity>1</quantity>
+ <USPrice>148.95</USPrice>
+ <comment>Confirm this is electric</comment>
+ </item>
+ <item partNum="926-AA">
+ <productName>Baby Monitor</productName>
+ <quantity>1</quantity>
+ <USPrice>39.98</USPrice>
+ <shipDate>1999-05-21</shipDate>
+ </item>
+ </items>
+</apo:purchaseOrder>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/complexTypes2.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/complexTypes2.xml
new file mode 100644
index 0000000000..80687b9c1c
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/complexTypes2.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<apo:purchaseOrder2 xmlns:apo="http://www.example.com/ComplexTypes"
+ orderDate="1999-10-20">
+ <shipTo country="US">
+ <name>Alice Smith</name>
+ <street>123 Maple Street</street>
+ <!-- etc. -->
+ <city>Mill Valley</city>
+ <state>CA</state>
+ <zip>90952</zip>
+ <contact>
+ <phone>081234567</phone>
+ <e-mail>[email protected]</e-mail>
+ <cell-phone>070122345</cell-phone>
+ <prefCont>
+ <cell-phone>070122345</cell-phone>
+ </prefCont>
+ </contact>
+ </shipTo>
+ <billTo country="US">
+ <name>Robert Smith</name>
+ <street>8 Oak Avenue</street>
+ <!-- etc. -->
+ <city>Old Town</city>
+ <state>PA</state>
+ <zip>95819</zip>
+ </billTo>
+ <apo:comment>Hurry, my lawn is going wild!</apo:comment>
+ <!-- etc. -->
+ <items>
+ <item partNum="872-AA">
+ <productName>Lawnmower</productName>
+ <quantity>1</quantity>
+ <USPrice>148.95</USPrice>
+ <comment>Confirm this is electric</comment>
+ </item>
+ <item partNum="926-AA">
+ <productName>Baby Monitor</productName>
+ <quantity>1</quantity>
+ <USPrice>39.98</USPrice>
+ <shipDate>1999-05-21</shipDate>
+ </item>
+ </items>
+</apo:purchaseOrder2>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/enum_bug.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/enum_bug.xml
new file mode 100644
index 0000000000..1a4b601c32
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/enum_bug.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<status/>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/enum_bug.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/enum_bug.xsd
new file mode 100644
index 0000000000..996e0d5b4d
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/enum_bug.xsd
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ elementFormDefault="qualified" attributeFormDefault="unqualified">
+
+ <xs:element name="status">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="status-type"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:simpleType name="status-type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="Valid" />
+ <xs:enumeration value="Invalid" />
+ <xs:enumeration value="" />
+ </xs:restriction>
+ </xs:simpleType>
+</xs:schema> \ No newline at end of file
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/gpx/clementine_loop.gpx b/lib/xmerl/test/xmerl_xsd_SUITE_data/gpx/clementine_loop.gpx
new file mode 100644
index 0000000000..f4e3185c56
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/gpx/clementine_loop.gpx
@@ -0,0 +1,3594 @@
+<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
+<gpx
+ version="1.0"
+ creator="ExpertGPS 1.2 - http://www.topografix.com"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="http://www.topografix.com/GPX/1/0"
+ xmlns:topografix="http://www.topografix.com/GPX/Private/TopoGrafix/0/2"
+ xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.topografix.com/GPX/Private/TopoGrafix/0/2 http://www.topografix.com/GPX/Private/TopoGrafix/0/2/topografix.xsd">
+<time>2003-02-05T19:17:02Z</time>
+<bounds minlat="38.625526" minlon="-121.516943" maxlat="38.937285" maxlon="-121.011830"/>
+<wpt lat="38.916370006" lon="-121.035340039">
+ <ele>182.775024</ele>
+ <time>2003-02-05T18:19:15Z</time>
+ <name>CLEMEN TR</name>
+ <desc>CLEMEN TR</desc>
+ <sym>Trail Head</sym>
+ <type>Trail Head</type>
+</wpt>
+<wpt lat="38.920639999" lon="-121.012300031">
+ <ele>313.993896</ele>
+ <time>2003-02-05T18:19:15Z</time>
+ <name>CONFL TR</name>
+ <desc>CONFL TR</desc>
+ <sym>Trail Head</sym>
+ <type>Trail Head</type>
+</wpt>
+<wpt lat="38.932889983" lon="-121.011829974">
+ <ele>437.041748</ele>
+ <time>2003-02-05T18:19:15Z</time>
+ <name>CULVERT TR</name>
+ <desc>CULVERT TR</desc>
+ <sym>Trail Head</sym>
+ <type>Trail Head</type>
+</wpt>
+<wpt lat="38.905900003" lon="-121.055939991">
+ <ele>371.912964</ele>
+ <time>2003-02-04T21:14:35Z</time>
+ <name>MANZANITA</name>
+ <desc>MANZANITA</desc>
+ <sym>Trail Head</sym>
+ <type>Trail Head</type>
+</wpt>
+<wpt lat="38.911470029" lon="-121.054369977">
+ <ele>405.318481</ele>
+ <time>2003-02-04T21:14:35Z</time>
+ <name>STAGECOACH</name>
+ <desc>STAGECOACH</desc>
+ <sym>Trail Head</sym>
+ <type>Trail Head</type>
+</wpt>
+<rte>
+ <name>SAC-CLEM</name>
+ <desc>Auto route from Sacramento to Clementine Loop trail head.</desc>
+ <number>1</number>
+ <topografix:color>ff0000</topografix:color>
+<rtept lat="38.625526432" lon="-121.516942989">
+ <time>2003-02-05T18:08:15Z</time>
+ <name>I-5</name>
+ <desc>I-5</desc>
+ <sym>Waypoint</sym>
+ <type>Waypoint</type>
+</rtept>
+<rtept lat="38.646984104" lon="-121.374807369">
+ <time>2003-02-05T18:08:15Z</time>
+ <name>I-80BUSRTE</name>
+ <desc>I-80BUSRTE</desc>
+ <sym>Waypoint</sym>
+ <type>Waypoint</type>
+</rtept>
+<rtept lat="38.917007450" lon="-121.062297832">
+ <time>2003-02-05T18:08:15Z</time>
+ <name>I-801</name>
+ <desc>I-801</desc>
+ <sym>Waypoint</sym>
+ <type>Waypoint</type>
+</rtept>
+<rtept lat="38.917522434" lon="-121.060409557">
+ <time>2003-02-05T18:08:15Z</time>
+ <name>LINCOLNWAY</name>
+ <desc>LINCOLNWAY</desc>
+ <sym>Waypoint</sym>
+ <type>Waypoint</type>
+</rtept>
+<rtept lat="38.915805820" lon="-121.061010372">
+ <time>2003-02-05T18:08:15Z</time>
+ <name>LINCOLNWY1</name>
+ <desc>LINCOLNWY1</desc>
+ <sym>Waypoint</sym>
+ <type>Waypoint</type>
+</rtept>
+<rtept lat="38.916149143" lon="-121.057147991">
+ <time>2003-02-05T18:08:15Z</time>
+ <name>RUSSELL RD</name>
+ <desc>RUSSELL RD</desc>
+ <sym>Waypoint</sym>
+ <type>Waypoint</type>
+</rtept>
+<rtept lat="38.911467012" lon="-121.054374419">
+ <time>2003-02-05T18:08:15Z</time>
+ <name>STAGECOACH</name>
+ <desc>STAGECOACH</desc>
+ <sym>Trail Head</sym>
+ <type>Trail Head</type>
+</rtept>
+</rte>
+<trk>
+ <name>CLEMENTINE</name>
+ <desc>Clementine Loop</desc>
+ <number>1</number>
+ <topografix:color>ff0000</topografix:color>
+<trkseg>
+<trkpt lat="38.919839863" lon="-121.020112049">
+ <ele>265.447754</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919796947" lon="-121.020240795">
+ <ele>264.967041</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919861320" lon="-121.020498287">
+ <ele>263.044434</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919990066" lon="-121.020798694">
+ <ele>263.525146</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919925693" lon="-121.021056187">
+ <ele>260.160522</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919904236" lon="-121.021163475">
+ <ele>260.160522</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919818405" lon="-121.021292221">
+ <ele>259.679932</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919646744" lon="-121.021614086">
+ <ele>259.199219</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919539455" lon="-121.021764290">
+ <ele>256.795898</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919432167" lon="-121.022086155">
+ <ele>255.834717</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919281963" lon="-121.022450935">
+ <ele>252.950684</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919281963" lon="-121.022515308">
+ <ele>253.431396</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919196132" lon="-121.022665512">
+ <ele>251.989380</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919131759" lon="-121.022837173">
+ <ele>251.027954</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918981556" lon="-121.023073208">
+ <ele>248.624756</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918895725" lon="-121.023223411">
+ <ele>248.624756</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918745521" lon="-121.023609649">
+ <ele>246.702148</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918681148" lon="-121.023845684">
+ <ele>244.298950</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918681148" lon="-121.024081718">
+ <ele>243.337524</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918681148" lon="-121.024210464">
+ <ele>242.856934</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918724064" lon="-121.024403583">
+ <ele>241.895630</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918745521" lon="-121.024703991">
+ <ele>239.492310</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918595318" lon="-121.024854194">
+ <ele>238.050415</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918337826" lon="-121.025025856">
+ <ele>236.608521</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918187622" lon="-121.025090229">
+ <ele>235.646973</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917994503" lon="-121.025326263">
+ <ele>234.205078</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917951587" lon="-121.025519382">
+ <ele>233.243774</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917908672" lon="-121.025691044">
+ <ele>232.282471</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917887214" lon="-121.025927078">
+ <ele>231.801758</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917651180" lon="-121.025991451">
+ <ele>230.840576</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917415146" lon="-121.025884163">
+ <ele>228.437256</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917114738" lon="-121.025691044">
+ <ele>226.514648</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916792873" lon="-121.025648128">
+ <ele>223.630737</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916192058" lon="-121.025819790">
+ <ele>219.785400</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915848736" lon="-121.025884163">
+ <ele>217.382202</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915677074" lon="-121.026034366">
+ <ele>215.459595</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915634159" lon="-121.026227485">
+ <ele>214.017578</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915634159" lon="-121.026356232">
+ <ele>214.017578</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915569786" lon="-121.026806843">
+ <ele>212.094971</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915462498" lon="-121.026914131">
+ <ele>210.172363</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915376667" lon="-121.027021419">
+ <ele>209.691772</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915140632" lon="-121.027686607">
+ <ele>206.807739</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915119175" lon="-121.027858269">
+ <ele>206.327148</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915054802" lon="-121.028094303">
+ <ele>204.404541</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915054802" lon="-121.028137218">
+ <ele>204.404541</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914990429" lon="-121.028373253">
+ <ele>201.520508</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914947513" lon="-121.028738033">
+ <ele>200.559204</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914861683" lon="-121.028931152">
+ <ele>199.597900</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914840225" lon="-121.029145729">
+ <ele>200.559204</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914797310" lon="-121.029253017">
+ <ele>201.039795</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914647106" lon="-121.029489052">
+ <ele>196.713989</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914625648" lon="-121.029531967">
+ <ele>196.713989</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914539818" lon="-121.029832374">
+ <ele>194.310791</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914518360" lon="-121.030004036">
+ <ele>192.868774</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914496902" lon="-121.030519020">
+ <ele>191.426758</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914368156" lon="-121.030626308">
+ <ele>189.984863</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914217953" lon="-121.030733597">
+ <ele>189.023560</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914024833" lon="-121.031162750">
+ <ele>184.697632</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913981918" lon="-121.031377327">
+ <ele>183.736206</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913939003" lon="-121.031699192">
+ <ele>183.255615</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913939003" lon="-121.031785023">
+ <ele>183.255615</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913831714" lon="-121.032021057">
+ <ele>182.775024</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913831714" lon="-121.032278549">
+ <ele>180.852417</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913788799" lon="-121.032471668">
+ <ele>178.929810</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913788799" lon="-121.032536041">
+ <ele>179.410400</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913681511" lon="-121.032857906">
+ <ele>177.487793</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913660053" lon="-121.033115398">
+ <ele>175.084595</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913660053" lon="-121.033244144">
+ <ele>174.603882</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913660053" lon="-121.033458721">
+ <ele>174.123169</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913702968" lon="-121.034145366">
+ <ele>172.200562</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913660053" lon="-121.034231197">
+ <ele>171.239258</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913767341" lon="-121.034510147">
+ <ele>173.642578</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913767341" lon="-121.034767639">
+ <ele>172.200562</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913831714" lon="-121.035046589">
+ <ele>168.835938</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913896087" lon="-121.035218250">
+ <ele>167.874634</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913960460" lon="-121.035454284">
+ <ele>167.394043</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914024833" lon="-121.035625946">
+ <ele>166.913330</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914260868" lon="-121.035776150">
+ <ele>165.952026</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914518360" lon="-121.035904896">
+ <ele>166.913330</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914818767" lon="-121.036012184">
+ <ele>166.913330</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914947513" lon="-121.036119472">
+ <ele>166.913330</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915119175" lon="-121.036248218">
+ <ele>167.874634</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915290836" lon="-121.036291134">
+ <ele>168.835938</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915441040" lon="-121.036076557">
+ <ele>170.758545</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915634159" lon="-121.035883438">
+ <ele>174.123169</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915784363" lon="-121.035690319">
+ <ele>174.123169</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916020397" lon="-121.035625946">
+ <ele>173.161987</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916256431" lon="-121.035647404">
+ <ele>172.200562</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916385177" lon="-121.035690319">
+ <ele>171.239258</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916814331" lon="-121.036269676">
+ <ele>169.316650</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916878704" lon="-121.036484253">
+ <ele>167.394043</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916964535" lon="-121.036548626">
+ <ele>166.913330</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917050365" lon="-121.036527168">
+ <ele>166.432617</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917458061" lon="-121.036398422">
+ <ele>166.432617</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917887214" lon="-121.036570083">
+ <ele>168.835938</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918037418" lon="-121.036698829">
+ <ele>171.719849</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918058876" lon="-121.036698829">
+ <ele>172.681274</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918144707" lon="-121.036720287">
+ <ele>174.603882</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918187622" lon="-121.036827576">
+ <ele>176.526489</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918316368" lon="-121.036977779">
+ <ele>180.371704</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918466572" lon="-121.037127983">
+ <ele>183.255615</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918530945" lon="-121.037299644">
+ <ele>186.620239</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918659691" lon="-121.037514221">
+ <ele>189.023560</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918766979" lon="-121.037707340">
+ <ele>191.907471</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918852810" lon="-121.037836086">
+ <ele>195.271973</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919067386" lon="-121.038050663">
+ <ele>197.194580</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919239048" lon="-121.038222324">
+ <ele>200.078613</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919346336" lon="-121.038393986">
+ <ele>202.481812</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919517998" lon="-121.038587105">
+ <ele>205.846558</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919539455" lon="-121.038630020">
+ <ele>206.327148</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919496540" lon="-121.038672935">
+ <ele>206.807739</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919260505" lon="-121.038544189">
+ <ele>210.652954</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918960098" lon="-121.038351070">
+ <ele>214.017578</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918402199" lon="-121.037986290">
+ <ele>217.382202</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918037418" lon="-121.037728798">
+ <ele>220.266113</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917565349" lon="-121.037685882">
+ <ele>223.630737</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917350773" lon="-121.038050663">
+ <ele>226.514648</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917329315" lon="-121.038329613">
+ <ele>228.917969</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917222027" lon="-121.038887512">
+ <ele>231.801758</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917243484" lon="-121.039402496">
+ <ele>235.166382</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917350773" lon="-121.039831650">
+ <ele>238.050415</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917651180" lon="-121.040067684">
+ <ele>241.414917</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917887214" lon="-121.040282261">
+ <ele>244.298950</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918294910" lon="-121.040647041">
+ <ele>245.260132</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918423656" lon="-121.041119110">
+ <ele>248.144165</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918659691" lon="-121.041462433">
+ <ele>251.508667</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918852810" lon="-121.041655552">
+ <ele>254.392700</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918809894" lon="-121.042191994">
+ <ele>256.795898</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918809894" lon="-121.042814266">
+ <ele>259.199219</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918509487" lon="-121.042964470">
+ <ele>261.602539</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918488029" lon="-121.042964470">
+ <ele>261.602539</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918101791" lon="-121.042792808">
+ <ele>264.486328</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917586807" lon="-121.042621147">
+ <ele>268.331665</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917329315" lon="-121.042792808">
+ <ele>270.254272</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917157654" lon="-121.043200504">
+ <ele>273.138306</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916878704" lon="-121.043479454">
+ <ele>276.022095</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916471008" lon="-121.043629658">
+ <ele>278.906128</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916428093" lon="-121.043608200">
+ <ele>279.867310</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916020397" lon="-121.043457996">
+ <ele>283.231934</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915805820" lon="-121.043694031">
+ <ele>286.115967</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915655617" lon="-121.044209015">
+ <ele>288.038574</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915419582" lon="-121.044316303">
+ <ele>290.922485</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915140632" lon="-121.044466507">
+ <ele>293.325684</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914818767" lon="-121.044230472">
+ <ele>294.287109</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914496902" lon="-121.044101726">
+ <ele>297.651611</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914217953" lon="-121.044230472">
+ <ele>301.016235</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913939003" lon="-121.044445049">
+ <ele>303.419556</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913810257" lon="-121.044552337">
+ <ele>304.861450</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913488392" lon="-121.044681084">
+ <ele>307.745483</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913187984" lon="-121.044681084">
+ <ele>308.706665</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912887577" lon="-121.044681084">
+ <ele>311.109985</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912565712" lon="-121.044788372">
+ <ele>313.513306</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912372593" lon="-121.045110237">
+ <ele>316.877930</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912265304" lon="-121.045281898">
+ <ele>316.877930</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912072185" lon="-121.045582306">
+ <ele>320.242432</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912007812" lon="-121.045925628">
+ <ele>322.165039</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912007812" lon="-121.046075832">
+ <ele>323.126465</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912072185" lon="-121.046547901">
+ <ele>325.529663</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912243847" lon="-121.046998512">
+ <ele>327.452271</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912158016" lon="-121.047277462">
+ <ele>330.816895</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911964897" lon="-121.047577869">
+ <ele>333.220215</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911771778" lon="-121.047964107">
+ <ele>335.623413</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911471371" lon="-121.048307430">
+ <ele>338.988037</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911235336" lon="-121.048650753">
+ <ele>342.352661</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911042217" lon="-121.049079906">
+ <ele>344.275269</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.910634521" lon="-121.049187195">
+ <ele>346.678467</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.910248283" lon="-121.049444687">
+ <ele>350.043213</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.910119537" lon="-121.049659263">
+ <ele>353.407715</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.910183910" lon="-121.050109875">
+ <ele>354.849609</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.910462860" lon="-121.050453197">
+ <ele>357.733643</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.910849098" lon="-121.050710689">
+ <ele>360.617432</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911213878" lon="-121.050882351">
+ <ele>363.501465</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911406997" lon="-121.051311504">
+ <ele>366.866089</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911664490" lon="-121.051590454">
+ <ele>370.230591</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912007812" lon="-121.051719200">
+ <ele>371.672607</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912007812" lon="-121.052105438">
+ <ele>373.595215</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912050728" lon="-121.052491676">
+ <ele>376.959839</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912351135" lon="-121.052856457">
+ <ele>379.363037</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912758831" lon="-121.052985203">
+ <ele>382.727783</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913059238" lon="-121.053135406">
+ <ele>385.130981</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913273815" lon="-121.053628933">
+ <ele>388.014893</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913273815" lon="-121.053843510">
+ <ele>388.976196</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913187984" lon="-121.053843510">
+ <ele>389.456787</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913037781" lon="-121.053822052">
+ <ele>390.418213</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912673000" lon="-121.053864967">
+ <ele>393.302002</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912308220" lon="-121.053972256">
+ <ele>396.186157</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911921982" lon="-121.054122459">
+ <ele>399.069946</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911664490" lon="-121.054143917">
+ <ele>400.031372</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911492828" lon="-121.054101002">
+ <ele>400.992554</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911342624" lon="-121.054251205">
+ <ele>403.876587</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911385540" lon="-121.054358494">
+ <ele>403.876587</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911385540" lon="-121.054379951">
+ <ele>403.395874</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911406997" lon="-121.054379951">
+ <ele>402.915161</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911492828" lon="-121.054487240">
+ <ele>402.915161</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911492828" lon="-121.054487240">
+ <ele>403.395874</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911492828" lon="-121.054508697">
+ <ele>403.395874</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911492828" lon="-121.054337036">
+ <ele>413.489746</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911514286" lon="-121.054379951">
+ <ele>413.489746</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911557201" lon="-121.055088054">
+ <ele>410.605591</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911535744" lon="-121.055431377">
+ <ele>408.202393</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911364082" lon="-121.055989277">
+ <ele>404.357178</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911256794" lon="-121.056354057">
+ <ele>400.511963</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911213878" lon="-121.056482803">
+ <ele>399.550659</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911085132" lon="-121.056633007">
+ <ele>397.147339</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.910484318" lon="-121.056268226">
+ <ele>394.744019</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.909926418" lon="-121.056118023">
+ <ele>391.379395</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.909754757" lon="-121.056096565">
+ <ele>390.418213</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.909540180" lon="-121.056182396">
+ <ele>389.937500</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.908746246" lon="-121.056311142">
+ <ele>386.572998</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.908681873" lon="-121.056311142">
+ <ele>386.572998</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.908295635" lon="-121.056311142">
+ <ele>386.092285</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.907995228" lon="-121.056418430">
+ <ele>387.534180</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.907845024" lon="-121.056461346">
+ <ele>386.572998</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.907630447" lon="-121.056418430">
+ <ele>387.053589</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.907480243" lon="-121.056289684">
+ <ele>387.053589</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.907458786" lon="-121.056203853">
+ <ele>386.092285</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.907394413" lon="-121.056182396">
+ <ele>386.092285</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.907115463" lon="-121.056096565">
+ <ele>383.208374</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906836513" lon="-121.056182396">
+ <ele>381.285767</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906729225" lon="-121.056289684">
+ <ele>379.843628</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906536106" lon="-121.056504261">
+ <ele>377.921021</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906321529" lon="-121.056504261">
+ <ele>376.479126</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906064037" lon="-121.056203853">
+ <ele>375.037231</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.905892376" lon="-121.055967819">
+ <ele>371.672607</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.905892376" lon="-121.055946361">
+ <ele>370.711304</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906021122" lon="-121.055667412">
+ <ele>366.866089</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906085495" lon="-121.055452835">
+ <ele>363.982056</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906128410" lon="-121.055152428">
+ <ele>360.617432</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906149868" lon="-121.055088054">
+ <ele>359.656250</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906214241" lon="-121.054852020">
+ <ele>358.214233</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906300072" lon="-121.054744732">
+ <ele>356.291626</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906364445" lon="-121.054658901">
+ <ele>354.849609</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906407360" lon="-121.054508697">
+ <ele>351.965820</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906385902" lon="-121.054465782">
+ <ele>351.485107</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906021122" lon="-121.054551613">
+ <ele>348.120605</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.905677799" lon="-121.054744732">
+ <ele>344.755859</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.905591968" lon="-121.054809105">
+ <ele>342.352661</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.905441765" lon="-121.054937851">
+ <ele>340.430054</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.905441765" lon="-121.054852020">
+ <ele>339.949341</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.905463222" lon="-121.054744732">
+ <ele>338.988037</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.905549053" lon="-121.054508697">
+ <ele>335.142822</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.905570511" lon="-121.054465782">
+ <ele>335.142822</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.905785087" lon="-121.054058086">
+ <ele>333.700806</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.905978206" lon="-121.053800594">
+ <ele>330.816895</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906149868" lon="-121.053628933">
+ <ele>330.336182</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906257156" lon="-121.053586017">
+ <ele>329.855469</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906385902" lon="-121.053521644">
+ <ele>329.855469</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906514648" lon="-121.053457271">
+ <ele>328.413574</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906879429" lon="-121.053543102">
+ <ele>325.529663</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906900886" lon="-121.053586017">
+ <ele>324.087646</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906965259" lon="-121.053714763">
+ <ele>322.165039</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.906965259" lon="-121.053714763">
+ <ele>322.165039</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.907008175" lon="-121.053671848">
+ <ele>322.645752</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.907158378" lon="-121.053435814">
+ <ele>326.490967</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.907244209" lon="-121.053199779">
+ <ele>329.855469</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.907544617" lon="-121.053071033">
+ <ele>327.932861</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.907630447" lon="-121.053071033">
+ <ele>327.452271</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.907673363" lon="-121.053028118">
+ <ele>326.010254</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.907802109" lon="-121.052920830">
+ <ele>324.087646</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.907887939" lon="-121.052792084">
+ <ele>322.645752</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.907930855" lon="-121.052598965">
+ <ele>322.645752</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.908317093" lon="-121.052105438">
+ <ele>322.165039</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.908445839" lon="-121.051869404">
+ <ele>322.645752</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.908252720" lon="-121.051461708">
+ <ele>323.607056</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.908274177" lon="-121.050968181">
+ <ele>321.684448</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.908381466" lon="-121.050839435">
+ <ele>320.242432</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.908424381" lon="-121.050817978">
+ <ele>319.761841</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.908531669" lon="-121.050710689">
+ <ele>315.916504</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.908574585" lon="-121.050689232">
+ <ele>315.916504</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.908638958" lon="-121.050646316">
+ <ele>313.513306</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.908789161" lon="-121.050581943">
+ <ele>313.513306</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.908917908" lon="-121.050496113">
+ <ele>315.435913</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.909025196" lon="-121.050453197">
+ <ele>316.397217</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.909432892" lon="-121.050367367">
+ <ele>317.358643</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.909540180" lon="-121.050324451">
+ <ele>317.358643</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.909540180" lon="-121.050260078">
+ <ele>320.242432</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.909175400" lon="-121.049852382">
+ <ele>321.203857</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.908746246" lon="-121.049251568">
+ <ele>323.126465</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.908531669" lon="-121.048629295">
+ <ele>323.126465</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.908660415" lon="-121.048393261">
+ <ele>321.684448</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.909196857" lon="-121.048264515">
+ <ele>318.800537</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.909239773" lon="-121.048264515">
+ <ele>318.800537</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.909325603" lon="-121.048157226">
+ <ele>317.358643</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.909304146" lon="-121.048028480">
+ <ele>319.281250</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.909218315" lon="-121.047513496">
+ <ele>320.242432</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.909282688" lon="-121.047449123">
+ <ele>321.684448</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.909497265" lon="-121.047427666">
+ <ele>321.684448</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.909733299" lon="-121.047492039">
+ <ele>321.203857</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.909883503" lon="-121.047427666">
+ <ele>321.684448</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.910076622" lon="-121.047492039">
+ <ele>321.684448</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.910441402" lon="-121.047942650">
+ <ele>320.242432</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.910548691" lon="-121.048092853">
+ <ele>321.203857</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.910784725" lon="-121.048221599">
+ <ele>320.723145</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.910870556" lon="-121.048264515">
+ <ele>319.281250</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.910956386" lon="-121.048049938">
+ <ele>319.761841</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911192421" lon="-121.047620785">
+ <ele>319.761841</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911535744" lon="-121.047556412">
+ <ele>320.242432</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911964897" lon="-121.047041427">
+ <ele>318.800537</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911921982" lon="-121.046805393">
+ <ele>319.761841</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911879066" lon="-121.046526443">
+ <ele>322.645752</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911879066" lon="-121.046226036">
+ <ele>322.645752</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911836151" lon="-121.045990002">
+ <ele>320.242432</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.911900524" lon="-121.045582306">
+ <ele>319.761841</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912179474" lon="-121.045217525">
+ <ele>319.761841</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912522796" lon="-121.044766914">
+ <ele>319.281250</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912694458" lon="-121.044616710">
+ <ele>318.319824</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912780289" lon="-121.044595253">
+ <ele>319.761841</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912801746" lon="-121.044616710">
+ <ele>319.761841</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.912844662" lon="-121.044616710">
+ <ele>319.761841</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913037781" lon="-121.044659626">
+ <ele>321.684448</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913209442" lon="-121.044638168">
+ <ele>320.723145</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913402561" lon="-121.044638168">
+ <ele>318.319824</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913681511" lon="-121.044638168">
+ <ele>316.877930</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.913810257" lon="-121.044573795">
+ <ele>316.397217</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914217953" lon="-121.044230472">
+ <ele>312.551880</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914282326" lon="-121.044187557">
+ <ele>312.551880</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.914561275" lon="-121.044101726">
+ <ele>309.668091</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915033344" lon="-121.044337761">
+ <ele>305.342163</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915076259" lon="-121.044380676">
+ <ele>305.342163</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915376667" lon="-121.044316303">
+ <ele>303.419556</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915634159" lon="-121.044187557">
+ <ele>301.496948</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915762905" lon="-121.043972980">
+ <ele>298.132324</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.915805820" lon="-121.043715488">
+ <ele>297.651611</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916277889" lon="-121.043415081">
+ <ele>293.806396</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916556839" lon="-121.043543827">
+ <ele>290.441895</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916728500" lon="-121.043608200">
+ <ele>288.038574</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916835789" lon="-121.043608200">
+ <ele>288.038574</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917093281" lon="-121.043457996">
+ <ele>286.115967</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917307857" lon="-121.042985927">
+ <ele>283.231934</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917350773" lon="-121.042921554">
+ <ele>282.751343</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917436603" lon="-121.042792808">
+ <ele>280.828735</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917694095" lon="-121.042685520">
+ <ele>278.425415</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917758468" lon="-121.042685520">
+ <ele>277.944702</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918402199" lon="-121.042814266">
+ <ele>273.138306</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918530945" lon="-121.042835724">
+ <ele>271.696289</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918724064" lon="-121.042900097">
+ <ele>270.254272</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918917183" lon="-121.042835724">
+ <ele>269.773682</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918981556" lon="-121.042449486">
+ <ele>268.331665</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918938640" lon="-121.041784298">
+ <ele>265.447754</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918766979" lon="-121.041526806">
+ <ele>262.563721</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918488029" lon="-121.041183483">
+ <ele>260.641113</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918359283" lon="-121.040732872">
+ <ele>257.757324</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918230537" lon="-121.040561210">
+ <ele>255.834717</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918015961" lon="-121.040346634">
+ <ele>255.834717</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917801384" lon="-121.040132057">
+ <ele>255.354004</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917522434" lon="-121.039938938">
+ <ele>251.027954</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917415146" lon="-121.039767277">
+ <ele>250.066772</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917372230" lon="-121.039574158">
+ <ele>248.624756</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917329315" lon="-121.038780224">
+ <ele>243.818237</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917393688" lon="-121.038479816">
+ <ele>242.376343</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917436603" lon="-121.038007747">
+ <ele>239.973022</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917586807" lon="-121.037685882">
+ <ele>237.089111</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917887214" lon="-121.037535679">
+ <ele>234.205078</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918037418" lon="-121.037535679">
+ <ele>233.724365</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918380741" lon="-121.037621509">
+ <ele>230.359863</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918809894" lon="-121.037879001">
+ <ele>226.995361</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918917183" lon="-121.037964832">
+ <ele>226.033936</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919045929" lon="-121.038050663">
+ <ele>224.592041</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919260505" lon="-121.038222324">
+ <ele>223.150146</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919367794" lon="-121.038308155">
+ <ele>221.708130</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919689659" lon="-121.038565647">
+ <ele>217.862793</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919732574" lon="-121.038608562">
+ <ele>217.862793</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919754032" lon="-121.038608562">
+ <ele>216.901489</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919668201" lon="-121.038479816">
+ <ele>215.459595</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919389252" lon="-121.038136494">
+ <ele>211.614380</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919346336" lon="-121.038093578">
+ <ele>211.614380</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919239048" lon="-121.037986290">
+ <ele>208.730347</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919003013" lon="-121.037707340">
+ <ele>204.885132</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918960098" lon="-121.037664425">
+ <ele>204.885132</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918766979" lon="-121.037428390">
+ <ele>200.559204</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918638233" lon="-121.037213814">
+ <ele>197.194580</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918509487" lon="-121.037020695">
+ <ele>192.868774</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918294910" lon="-121.036784660">
+ <ele>189.023560</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918230537" lon="-121.036741745">
+ <ele>187.581421</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917951587" lon="-121.036570083">
+ <ele>181.813599</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917887214" lon="-121.036527168">
+ <ele>181.813599</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917608265" lon="-121.036419880">
+ <ele>178.929810</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917415146" lon="-121.036376964">
+ <ele>178.449097</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917007450" lon="-121.036548626">
+ <ele>178.449097</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916857246" lon="-121.036398422">
+ <ele>178.929810</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916621212" lon="-121.035840523">
+ <ele>180.371704</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916363720" lon="-121.035647404">
+ <ele>181.333008</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916363720" lon="-121.035346996">
+ <ele>181.813599</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916578296" lon="-121.035218250">
+ <ele>181.333008</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.916943077" lon="-121.035089504">
+ <ele>180.371704</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.917222027" lon="-121.035068046">
+ <ele>179.410400</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918209080" lon="-121.035454284">
+ <ele>178.449097</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918488029" lon="-121.035625946">
+ <ele>177.968384</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.918745521" lon="-121.035969269">
+ <ele>177.968384</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919045929" lon="-121.036248218">
+ <ele>177.968384</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919346336" lon="-121.036655914">
+ <ele>178.449097</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920183185" lon="-121.037406933">
+ <ele>181.333008</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920912746" lon="-121.037750255">
+ <ele>183.255615</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.921277527" lon="-121.037836086">
+ <ele>185.178223</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.921492103" lon="-121.037921917">
+ <ele>184.216919</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.921599392" lon="-121.037964832">
+ <ele>185.658813</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.921685222" lon="-121.037964832">
+ <ele>184.216919</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.921921257" lon="-121.038007747">
+ <ele>187.581421</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922092918" lon="-121.038072120">
+ <ele>187.100830</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922178749" lon="-121.038115036">
+ <ele>187.100830</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922264580" lon="-121.038157951">
+ <ele>186.620239</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922607902" lon="-121.038222324">
+ <ele>186.620239</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923058513" lon="-121.038243782">
+ <ele>187.100830</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923144344" lon="-121.038243782">
+ <ele>187.100830</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923230175" lon="-121.038265240">
+ <ele>187.100830</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923444752" lon="-121.038372528">
+ <ele>184.216919</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923809532" lon="-121.038479816">
+ <ele>185.178223</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.924024109" lon="-121.038651478">
+ <ele>185.658813</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.924303058" lon="-121.038844597">
+ <ele>186.620239</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.924496177" lon="-121.038930427">
+ <ele>187.100830</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.924560551" lon="-121.038994800">
+ <ele>186.620239</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.924903873" lon="-121.039359581">
+ <ele>184.697632</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.925139908" lon="-121.039681446">
+ <ele>184.216919</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.925569061" lon="-121.040325176">
+ <ele>183.255615</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.925783638" lon="-121.040625583">
+ <ele>182.775024</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.925912384" lon="-121.040647041">
+ <ele>182.294312</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.926019672" lon="-121.040689956">
+ <ele>181.813599</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.926298622" lon="-121.040668499">
+ <ele>180.852417</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.926427368" lon="-121.040625583">
+ <ele>180.371704</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.927049640" lon="-121.040260803">
+ <ele>183.736206</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.927328590" lon="-121.039917480">
+ <ele>186.139526</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.927929405" lon="-121.039445412">
+ <ele>189.023560</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.928380016" lon="-121.039080631">
+ <ele>192.388184</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.928701881" lon="-121.038994800">
+ <ele>195.752686</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.928895000" lon="-121.038973343">
+ <ele>197.675293</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.929195408" lon="-121.038780224">
+ <ele>200.078613</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.929367069" lon="-121.038351070">
+ <ele>202.481812</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.929431442" lon="-121.038179409">
+ <ele>204.404541</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.929796222" lon="-121.038136494">
+ <ele>207.769165</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930096630" lon="-121.037943374">
+ <ele>210.652954</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930397037" lon="-121.037836086">
+ <ele>213.536987</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930675987" lon="-121.037836086">
+ <ele>214.978882</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931126598" lon="-121.037428390">
+ <ele>216.420776</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931362633" lon="-121.037170898">
+ <ele>219.785400</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931534294" lon="-121.036913406">
+ <ele>222.669434</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931877617" lon="-121.036441337">
+ <ele>226.033936</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932156566" lon="-121.036055099">
+ <ele>228.917969</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932392601" lon="-121.035690319">
+ <ele>231.801758</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932564262" lon="-121.035304081">
+ <ele>235.166382</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932650093" lon="-121.034939300">
+ <ele>237.569702</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932349685" lon="-121.034510147">
+ <ele>240.453735</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932178024" lon="-121.034166824">
+ <ele>243.337524</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931963447" lon="-121.033694755">
+ <ele>246.702148</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931727413" lon="-121.033265602">
+ <ele>249.586060</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931491379" lon="-121.032986652">
+ <ele>252.470093</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931405548" lon="-121.032664787">
+ <ele>255.354004</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931212429" lon="-121.032257091">
+ <ele>258.718506</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930976394" lon="-121.031892311">
+ <ele>262.563721</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931019310" lon="-121.031634819">
+ <ele>264.967041</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931405548" lon="-121.031270038">
+ <ele>265.928345</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931620125" lon="-121.030840885">
+ <ele>267.370361</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931598667" lon="-121.030218612">
+ <ele>269.773682</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931577209" lon="-121.029725086">
+ <ele>272.657593</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931427006" lon="-121.029338848">
+ <ele>275.541504</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931298260" lon="-121.028888237">
+ <ele>277.944702</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931233887" lon="-121.028695118">
+ <ele>279.867310</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931276802" lon="-121.028630745">
+ <ele>280.348022</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931598667" lon="-121.028373253">
+ <ele>283.231934</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931856159" lon="-121.028201591">
+ <ele>286.596680</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931984905" lon="-121.027858269">
+ <ele>288.999878</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932220939" lon="-121.027793896">
+ <ele>292.845093</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932414058" lon="-121.027643692">
+ <ele>296.209717</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932435516" lon="-121.027235996">
+ <ele>299.093506</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932456974" lon="-121.027064335">
+ <ele>299.093506</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932456974" lon="-121.026892673">
+ <ele>301.016235</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932671551" lon="-121.026592266">
+ <ele>301.496948</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932971958" lon="-121.026463520">
+ <ele>304.380859</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933186535" lon="-121.026098739">
+ <ele>306.784058</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933444027" lon="-121.025691044">
+ <ele>309.668091</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933658603" lon="-121.025347721">
+ <ele>313.032593</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933830265" lon="-121.024832737">
+ <ele>316.397217</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933701519" lon="-121.024210464">
+ <ele>319.281250</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933529857" lon="-121.024124634">
+ <ele>322.165039</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933293823" lon="-121.023824226">
+ <ele>323.607056</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933379654" lon="-121.023373615">
+ <ele>326.010254</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933551315" lon="-121.023008835">
+ <ele>328.894287</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933594230" lon="-121.022579681">
+ <ele>330.336182</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933765892" lon="-121.022322189">
+ <ele>333.700806</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933851723" lon="-121.021893036">
+ <ele>336.584839</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933701519" lon="-121.021549713">
+ <ele>338.507446</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933594230" lon="-121.021120560">
+ <ele>341.391235</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933615688" lon="-121.020584118">
+ <ele>344.755859</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933637146" lon="-121.020519745">
+ <ele>344.275269</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.934109215" lon="-121.020262253">
+ <ele>348.120605</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.934366707" lon="-121.020069134">
+ <ele>351.004395</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.934388164" lon="-121.020069134">
+ <ele>351.485107</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.934817318" lon="-121.019918930">
+ <ele>352.446411</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.935139183" lon="-121.019833099">
+ <ele>352.927002</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.935546879" lon="-121.019811642">
+ <ele>355.811035</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.935825828" lon="-121.019639980">
+ <ele>359.175537</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.935868744" lon="-121.019446861">
+ <ele>360.617432</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.935546879" lon="-121.018974792">
+ <ele>363.982056</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.935375217" lon="-121.018695843">
+ <ele>366.866089</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.935289387" lon="-121.018266689">
+ <ele>370.230591</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.935611252" lon="-121.018052112">
+ <ele>373.114624</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.936040405" lon="-121.017901909">
+ <ele>376.959839</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.936448101" lon="-121.017665874">
+ <ele>379.843628</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.936812881" lon="-121.017494213">
+ <ele>383.208374</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.937134746" lon="-121.017344009">
+ <ele>386.572998</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.937284950" lon="-121.016914856">
+ <ele>388.495605</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.937048916" lon="-121.016507160">
+ <ele>391.860107</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.936769966" lon="-121.016249668">
+ <ele>393.302002</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.936426643" lon="-121.016013634">
+ <ele>396.666748</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.936212066" lon="-121.015906345">
+ <ele>399.550659</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.935954574" lon="-121.015863430">
+ <ele>401.473267</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.935611252" lon="-121.015884888">
+ <ele>404.357178</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.935267929" lon="-121.015906345">
+ <ele>407.721802</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.935160641" lon="-121.015520107">
+ <ele>410.125000</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.935139183" lon="-121.015155327">
+ <ele>410.605591</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.934946064" lon="-121.014683258">
+ <ele>413.489746</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.934624199" lon="-121.014318477">
+ <ele>416.854248</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.934237961" lon="-121.013975155">
+ <ele>419.738159</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.934023384" lon="-121.013674747">
+ <ele>423.102783</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933744434" lon="-121.013417255">
+ <ele>425.986572</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933529857" lon="-121.013052475">
+ <ele>429.351318</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933358196" lon="-121.012730610">
+ <ele>432.235229</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933315281" lon="-121.012516033">
+ <ele>433.196533</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933079246" lon="-121.012172710">
+ <ele>435.599731</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932929043" lon="-121.011958134">
+ <ele>436.561157</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932843212" lon="-121.011893761">
+ <ele>437.041748</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932778839" lon="-121.011915218">
+ <ele>438.003052</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932821754" lon="-121.012279999">
+ <ele>440.886963</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932800297" lon="-121.012387287">
+ <ele>442.809570</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932886127" lon="-121.012709152">
+ <ele>446.174316</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933057789" lon="-121.012945186">
+ <ele>449.058105</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933165077" lon="-121.013181221">
+ <ele>452.903320</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933272365" lon="-121.013503086">
+ <ele>456.267944</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933336738" lon="-121.013782036">
+ <ele>457.229248</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933401111" lon="-121.014060985">
+ <ele>460.593872</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933529857" lon="-121.014511597">
+ <ele>463.958496</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933722976" lon="-121.014812004">
+ <ele>463.958496</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933787350" lon="-121.015348446">
+ <ele>460.113281</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933830265" lon="-121.015605938">
+ <ele>456.748535</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933830265" lon="-121.015648853">
+ <ele>456.267944</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933680061" lon="-121.015906345">
+ <ele>454.825928</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.933293823" lon="-121.016185295">
+ <ele>454.345337</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932864670" lon="-121.016292583">
+ <ele>456.267944</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932693008" lon="-121.016271126">
+ <ele>459.151855</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932456974" lon="-121.016249668">
+ <ele>462.516479</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932242397" lon="-121.016271126">
+ <ele>464.439087</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.932049278" lon="-121.016335499">
+ <ele>466.361694</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931705955" lon="-121.016421329">
+ <ele>469.245728</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931341175" lon="-121.016528618">
+ <ele>472.129517</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.931148056" lon="-121.016614448">
+ <ele>475.494141</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930869106" lon="-121.016807567">
+ <ele>478.378174</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930633072" lon="-121.017022144">
+ <ele>480.781494</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930482868" lon="-121.017236721">
+ <ele>482.704102</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930418495" lon="-121.017365467">
+ <ele>483.665283</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930397037" lon="-121.017386925">
+ <ele>483.184692</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930354122" lon="-121.017408382">
+ <ele>483.665283</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930461410" lon="-121.017322552">
+ <ele>484.626709</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930482868" lon="-121.017322552">
+ <ele>484.626709</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930439953" lon="-121.017365467">
+ <ele>485.587891</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930461410" lon="-121.017386925">
+ <ele>485.107300</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930439953" lon="-121.017344009">
+ <ele>486.068604</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930418495" lon="-121.017344009">
+ <ele>486.068604</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930439953" lon="-121.017344009">
+ <ele>487.029907</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930439953" lon="-121.017816078">
+ <ele>484.145996</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930439953" lon="-121.017966282">
+ <ele>482.704102</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930547241" lon="-121.018438351">
+ <ele>480.781494</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930547241" lon="-121.018738758">
+ <ele>478.858887</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930568699" lon="-121.018888962">
+ <ele>477.416870</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930611614" lon="-121.019232284">
+ <ele>474.052124</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930611614" lon="-121.019382488">
+ <ele>472.610229</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930418495" lon="-121.019489776">
+ <ele>471.648926</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930225376" lon="-121.019468319">
+ <ele>467.323120</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930053715" lon="-121.019425403">
+ <ele>463.958496</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.930010799" lon="-121.019403946">
+ <ele>463.477905</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.929882053" lon="-121.019232284">
+ <ele>461.074585</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.929839138" lon="-121.019039165">
+ <ele>458.190552</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.929817680" lon="-121.018974792">
+ <ele>458.190552</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.929517273" lon="-121.018867504">
+ <ele>454.825928</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.929216865" lon="-121.018846046">
+ <ele>451.942139</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.929066662" lon="-121.018824589">
+ <ele>450.500122</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.928852085" lon="-121.018888962">
+ <ele>447.616211</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.928530220" lon="-121.018888962">
+ <ele>443.290161</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.928251270" lon="-121.019017708">
+ <ele>440.886963</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.928229812" lon="-121.019039165">
+ <ele>439.925659</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.928143982" lon="-121.019039165">
+ <ele>439.444946</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.927843574" lon="-121.018781673">
+ <ele>435.599731</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.927800659" lon="-121.018695843">
+ <ele>434.638550</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.927457336" lon="-121.018266689">
+ <ele>435.119141</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.927307133" lon="-121.018159401">
+ <ele>432.235229</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.927221302" lon="-121.018095028">
+ <ele>429.831909</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.927071098" lon="-121.017944824">
+ <ele>427.428589</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.927028183" lon="-121.017515671">
+ <ele>426.467285</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.926877979" lon="-121.017236721">
+ <ele>423.102783</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.926856521" lon="-121.017193806">
+ <ele>423.102783</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.926835064" lon="-121.017150890">
+ <ele>422.622070</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.926770691" lon="-121.017065059">
+ <ele>422.141357</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.926577572" lon="-121.017000686">
+ <ele>418.776855</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.926448826" lon="-121.016936313">
+ <ele>416.854248</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.926405910" lon="-121.016936313">
+ <ele>415.412354</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.926277164" lon="-121.016893398">
+ <ele>413.970337</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.926212791" lon="-121.016850483">
+ <ele>413.009033</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.926062588" lon="-121.016657364">
+ <ele>411.086304</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.925912384" lon="-121.016464245">
+ <ele>408.202393</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.925526146" lon="-121.015841972">
+ <ele>404.837769</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.925354484" lon="-121.015670311">
+ <ele>404.357178</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.925182823" lon="-121.015734684">
+ <ele>401.953979</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.925075535" lon="-121.015670311">
+ <ele>400.031372</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.925032619" lon="-121.015584480">
+ <ele>399.550659</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.925011162" lon="-121.015455734">
+ <ele>400.992554</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.925011162" lon="-121.015434276">
+ <ele>401.473267</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.924946789" lon="-121.015219700">
+ <ele>401.473267</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.924689297" lon="-121.014940750">
+ <ele>401.473267</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.924582008" lon="-121.014661800">
+ <ele>401.473267</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.924496177" lon="-121.014297020">
+ <ele>400.992554</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.924367431" lon="-121.013889324">
+ <ele>398.589355</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.924367431" lon="-121.013610374">
+ <ele>394.263428</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.924345974" lon="-121.013481628">
+ <ele>393.782715</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.924367431" lon="-121.012837898">
+ <ele>395.224609</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.924303058" lon="-121.012601864">
+ <ele>395.224609</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.924152855" lon="-121.012709152">
+ <ele>390.898804</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.924131397" lon="-121.012730610">
+ <ele>390.418213</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.924024109" lon="-121.012902271">
+ <ele>386.572998</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923981193" lon="-121.012988102">
+ <ele>385.611572</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923916820" lon="-121.013138305">
+ <ele>383.208374</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923873905" lon="-121.013224136">
+ <ele>382.247070</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923788074" lon="-121.013438713">
+ <ele>379.363037</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923680786" lon="-121.013460171">
+ <ele>378.882446</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923380379" lon="-121.013395798">
+ <ele>376.959839</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923122886" lon="-121.013395798">
+ <ele>374.075806</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923079971" lon="-121.013438713">
+ <ele>375.517822</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923058513" lon="-121.013481628">
+ <ele>375.037231</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923015598" lon="-121.013546001">
+ <ele>375.517822</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922908310" lon="-121.013760578">
+ <ele>371.672607</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922886852" lon="-121.013760578">
+ <ele>371.192017</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922865394" lon="-121.013803493">
+ <ele>369.750000</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922865394" lon="-121.013867866">
+ <ele>368.788696</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922886852" lon="-121.014146816">
+ <ele>367.346802</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922886852" lon="-121.014211189">
+ <ele>366.385376</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922843937" lon="-121.014254104">
+ <ele>365.904785</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922822479" lon="-121.014382850">
+ <ele>363.501465</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922843937" lon="-121.014447223">
+ <ele>362.540039</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923015598" lon="-121.014812004">
+ <ele>362.059448</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923165802" lon="-121.015005123">
+ <ele>364.462769</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923251633" lon="-121.015176784">
+ <ele>363.982056</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923337463" lon="-121.015369903">
+ <ele>360.617432</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923358921" lon="-121.015434276">
+ <ele>360.136841</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923401836" lon="-121.015498649">
+ <ele>358.694824</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923316006" lon="-121.015584480">
+ <ele>354.369019</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923294548" lon="-121.015563022">
+ <ele>353.888428</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923273090" lon="-121.015541565">
+ <ele>353.888428</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.923079971" lon="-121.015455734">
+ <ele>350.523804</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922843937" lon="-121.015348446">
+ <ele>347.639771</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922822479" lon="-121.015326988">
+ <ele>347.639771</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922650818" lon="-121.015262615">
+ <ele>344.275269</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922371868" lon="-121.015133869">
+ <ele>340.910645</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922092918" lon="-121.015241157">
+ <ele>337.546021</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922071461" lon="-121.015241157">
+ <ele>337.546021</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922028545" lon="-121.015241157">
+ <ele>336.584839</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.921985630" lon="-121.015241157">
+ <ele>335.623413</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.921985630" lon="-121.015241157">
+ <ele>336.104126</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.921878341" lon="-121.015090954">
+ <ele>335.142822</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922007088" lon="-121.014704716">
+ <ele>333.700806</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.922050003" lon="-121.014361393">
+ <ele>335.142822</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.921985630" lon="-121.014254104">
+ <ele>335.142822</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.921449188" lon="-121.013653290">
+ <ele>331.778076</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.921363357" lon="-121.013481628">
+ <ele>330.816895</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.921213154" lon="-121.013073932">
+ <ele>326.490967</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920912746" lon="-121.012644779">
+ <ele>321.203857</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920762543" lon="-121.012473118">
+ <ele>317.358643</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920676712" lon="-121.012344372">
+ <ele>314.474487</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920633797" lon="-121.012301456">
+ <ele>313.513306</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920483593" lon="-121.012473118">
+ <ele>311.590698</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920204643" lon="-121.012923729">
+ <ele>307.745483</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920075897" lon="-121.013309967">
+ <ele>305.342163</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920183185" lon="-121.013739120">
+ <ele>301.496948</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920440677" lon="-121.014060985">
+ <ele>298.612915</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920483593" lon="-121.014125358">
+ <ele>298.132324</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920676712" lon="-121.014533054">
+ <ele>296.209717</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920762543" lon="-121.014640343">
+ <ele>294.767700</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920848373" lon="-121.014726173">
+ <ele>294.287109</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920869831" lon="-121.015069496">
+ <ele>292.364502</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920912746" lon="-121.015219700">
+ <ele>292.364502</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.921062950" lon="-121.015648853">
+ <ele>290.922485</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920977119" lon="-121.015713226">
+ <ele>290.922485</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920633797" lon="-121.015992176">
+ <ele>286.596680</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920612339" lon="-121.016013634">
+ <ele>286.596680</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920440677" lon="-121.016056549">
+ <ele>285.154663</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920183185" lon="-121.016421329">
+ <ele>283.712524</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920140270" lon="-121.016700279">
+ <ele>282.751343</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920140270" lon="-121.016871940">
+ <ele>281.309326</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920118812" lon="-121.017086517">
+ <ele>281.309326</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920204643" lon="-121.017301094">
+ <ele>280.348022</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920311931" lon="-121.017451298">
+ <ele>278.906128</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920376304" lon="-121.017580044">
+ <ele>278.906128</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920419220" lon="-121.017730247">
+ <ele>277.464111</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920311931" lon="-121.018116485">
+ <ele>276.022095</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920269016" lon="-121.018245231">
+ <ele>275.060913</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920226101" lon="-121.018502724">
+ <ele>274.580200</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.920011524" lon="-121.018824589">
+ <ele>271.696289</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919947151" lon="-121.019103538">
+ <ele>270.734985</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919882778" lon="-121.019639980">
+ <ele>267.850952</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+<trkpt lat="38.919925693" lon="-121.019876015">
+ <ele>267.370361</ele>
+ <time>2003-02-05T18:19:20Z</time>
+ <sym>Waypoint</sym>
+</trkpt>
+</trkseg>
+</trk>
+</gpx> \ No newline at end of file
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/gpx/gpx.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/gpx/gpx.xsd
new file mode 100644
index 0000000000..63d4640159
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/gpx/gpx.xsd
@@ -0,0 +1,227 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- GPX.xsd version 1.0 - For more information on GPX and this schema, visit http://www.topografix.com/gpx.asp -->
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:gpx="http://www.topografix.com/GPX/1/0" targetNamespace="http://www.topografix.com/GPX/1/0" elementFormDefault="qualified">
+
+<!-- Main GPX definition -->
+
+ <xsd:element name="gpx">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string" minOccurs="0"/> <!-- GPX file name -->
+ <xsd:element name="desc" type="xsd:string" minOccurs="0"/> <!-- GPX file description -->
+ <xsd:element name="author" type="xsd:string" minOccurs="0"/> <!-- GPX file author -->
+ <xsd:element name="email" type="gpx:emailType" minOccurs="0"/> <!-- GPX file author email -->
+ <xsd:element name="url" type="xsd:anyURI" minOccurs="0"/> <!-- GPX file URL -->
+ <xsd:element name="urlname" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="time" type="xsd:dateTime" minOccurs="0"/> <!-- GPX file creation time -->
+ <xsd:element name="keywords" type="xsd:string" minOccurs="0"/> <!-- GPX file keywords -->
+ <xsd:element name="bounds" type="gpx:boundsType" minOccurs="0"/> <!-- GPX file bounding rect -->
+ <xsd:element name="wpt" minOccurs="0" maxOccurs="unbounded">
+ <xsd:complexType>
+ <xsd:sequence> <!-- elements must appear in this order -->
+ <!-- Position info -->
+ <xsd:element name="ele" type="xsd:decimal" minOccurs="0"/>
+ <xsd:element name="time" type="xsd:dateTime" minOccurs="0"/>
+ <xsd:element name="magvar" type="gpx:degreesType" minOccurs="0"/>
+ <xsd:element name="geoidheight" type="xsd:decimal" minOccurs="0"/>
+
+ <!-- Description info -->
+ <xsd:element name="name" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="cmt" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="desc" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="src" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="url" type="xsd:anyURI" minOccurs="0"/>
+ <xsd:element name="urlname" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="sym" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="type" type="xsd:string" minOccurs="0"/>
+
+ <!-- Accuracy info -->
+ <xsd:element name="fix" type="gpx:fixType" minOccurs="0"/>
+ <xsd:element name="sat" type="xsd:nonNegativeInteger" minOccurs="0"/>
+ <xsd:element name="hdop" type="xsd:decimal" minOccurs="0"/>
+ <xsd:element name="vdop" type="xsd:decimal" minOccurs="0"/>
+ <xsd:element name="pdop" type="xsd:decimal" minOccurs="0"/>
+ <xsd:element name="ageofdgpsdata" type="xsd:decimal" minOccurs="0"/>
+ <xsd:element name="dgpsid" type="gpx:dgpsStationType" minOccurs="0"/>
+
+ <!-- you can add your own privately defined wpt elements at the end of the wpt -->
+ <xsd:any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="lat" type="gpx:latitudeType" use="required"/>
+ <xsd:attribute name="lon" type="gpx:longitudeType" use="required"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="rte" minOccurs="0" maxOccurs="unbounded">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="cmt" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="desc" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="src" type="xsd:string" minOccurs="0"/> <!-- the source of this data: "Garmin eTrex", "Map", etc -->
+ <xsd:element name="url" type="xsd:anyURI" minOccurs="0"/>
+ <xsd:element name="urlname" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="number" type="xsd:nonNegativeInteger" minOccurs="0"/> <!-- GPS track number -->
+ <!-- <xsd:element name="type" type="xsd:string" minOccurs="0"/> PROPOSED -->
+ <!-- you can add your own privately defined rte elements at the end of the rte -->
+ <xsd:any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="rtept" minOccurs="0" maxOccurs="unbounded">
+ <xsd:complexType>
+ <xsd:sequence> <!-- elements must appear in this order -->
+
+ <!-- Position info -->
+ <xsd:element name="ele" type="xsd:decimal" minOccurs="0"/>
+ <xsd:element name="time" type="xsd:dateTime" minOccurs="0"/>
+ <xsd:element name="magvar" type="gpx:degreesType" minOccurs="0"/>
+ <xsd:element name="geoidheight" type="xsd:decimal" minOccurs="0"/>
+
+ <!-- Description info -->
+ <xsd:element name="name" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="cmt" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="desc" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="src" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="url" type="xsd:anyURI" minOccurs="0"/>
+ <xsd:element name="urlname" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="sym" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="type" type="xsd:string" minOccurs="0"/>
+
+ <!-- Accuracy info -->
+ <xsd:element name="fix" type="gpx:fixType" minOccurs="0"/>
+ <xsd:element name="sat" type="xsd:nonNegativeInteger" minOccurs="0"/>
+ <xsd:element name="hdop" type="xsd:decimal" minOccurs="0"/>
+ <xsd:element name="vdop" type="xsd:decimal" minOccurs="0"/>
+ <xsd:element name="pdop" type="xsd:decimal" minOccurs="0"/>
+ <xsd:element name="ageofdgpsdata" type="xsd:decimal" minOccurs="0"/>
+ <xsd:element name="dgpsid" type="gpx:dgpsStationType" minOccurs="0"/>
+
+ <!-- you can add your own privately defined rtept elements at the end of the rtept -->
+ <xsd:any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="lat" type="gpx:latitudeType" use="required"/>
+ <xsd:attribute name="lon" type="gpx:longitudeType" use="required"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="trk" minOccurs="0" maxOccurs="unbounded">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="cmt" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="desc" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="src" type="xsd:string" minOccurs="0"/> <!-- the source of this data: "Garmin eTrex", "Map", etc -->
+ <xsd:element name="url" type="xsd:anyURI" minOccurs="0"/>
+ <xsd:element name="urlname" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="number" type="xsd:nonNegativeInteger" minOccurs="0"/> <!-- GPS track number -->
+ <!-- <xsd:element name="type" type="xsd:string" minOccurs="0"/> PROPOSED -->
+ <!-- you can add your own privately defined trk elements at the end of the trk -->
+ <xsd:any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="trkseg" minOccurs="0" maxOccurs="unbounded">
+ <xsd:complexType>
+ <xsd:sequence> <!-- elements must appear in this order -->
+ <xsd:element name="trkpt" minOccurs="0" maxOccurs="unbounded">
+ <xsd:complexType>
+ <xsd:sequence> <!-- elements must appear in this order -->
+
+ <!-- Position info -->
+ <xsd:element name="ele" type="xsd:decimal" minOccurs="0"/>
+ <xsd:element name="time" type="xsd:dateTime" minOccurs="0"/>
+ <xsd:element name="course" type="gpx:degreesType" minOccurs="0"/>
+ <xsd:element name="speed" type="xsd:decimal" minOccurs="0"/>
+ <xsd:element name="magvar" type="gpx:degreesType" minOccurs="0"/>
+ <xsd:element name="geoidheight" type="xsd:decimal" minOccurs="0"/>
+
+ <!-- Description info -->
+ <xsd:element name="name" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="cmt" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="desc" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="src" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="url" type="xsd:anyURI" minOccurs="0"/>
+ <xsd:element name="urlname" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="sym" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="type" type="xsd:string" minOccurs="0"/>
+
+ <!-- Accuracy info -->
+ <xsd:element name="fix" type="gpx:fixType" minOccurs="0"/>
+ <xsd:element name="sat" type="xsd:nonNegativeInteger" minOccurs="0"/>
+ <xsd:element name="hdop" type="xsd:decimal" minOccurs="0"/>
+ <xsd:element name="vdop" type="xsd:decimal" minOccurs="0"/>
+ <xsd:element name="pdop" type="xsd:decimal" minOccurs="0"/>
+ <xsd:element name="ageofdgpsdata" type="xsd:decimal" minOccurs="0"/>
+ <xsd:element name="dgpsid" type="gpx:dgpsStationType" minOccurs="0"/>
+
+ <!-- you can add your own privately defined trkpt elements at the end of the trkpt -->
+ <xsd:any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="lat" type="gpx:latitudeType" use="required"/>
+ <xsd:attribute name="lon" type="gpx:longitudeType" use="required"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <!-- you can add your own privately defined elements at the end of the GPX file -->
+ <xsd:any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="version" type="xsd:string" use="required" fixed="1.0"/> <!-- version 1.0 -->
+ <xsd:attribute name="creator" type="xsd:string" use="required"/>
+ </xsd:complexType>
+ </xsd:element>
+
+ <!-- Other types used by GPX -->
+
+ <xsd:simpleType name="latitudeType">
+ <xsd:restriction base="xsd:decimal">
+ <xsd:minInclusive value="-90.0"/>
+ <xsd:maxInclusive value="90.0"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="longitudeType">
+ <xsd:restriction base="xsd:decimal">
+ <xsd:minInclusive value="-180.0"/>
+ <xsd:maxInclusive value="180.0"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="degreesType"> <!-- for bearing, heading, course. Units are degrees, true -->
+ <xsd:restriction base="xsd:decimal">
+ <xsd:minInclusive value="0.0"/>
+ <xsd:maxInclusive value="360.0"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="fixType">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="none"/> <!-- none means GPS had no fix. To signify "the fix info is unknown, leave out the <fix> tag entirely -->
+ <xsd:enumeration value="2d"/>
+ <xsd:enumeration value="3d"/>
+ <xsd:enumeration value="dgps"/>
+ <xsd:enumeration value="pps"/> <!-- military signal used -->
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="dgpsStationType">
+ <xsd:restriction base="xsd:integer">
+ <xsd:minInclusive value="0"/>
+ <xsd:maxInclusive value="1023"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:complexType name="boundsType"> <!-- bounding rect for data in file -->
+ <xsd:attribute name="minlat" type="gpx:latitudeType" use="required"/>
+ <xsd:attribute name="minlon" type="gpx:longitudeType" use="required"/>
+ <xsd:attribute name="maxlat" type="gpx:latitudeType" use="required"/>
+ <xsd:attribute name="maxlon" type="gpx:longitudeType" use="required"/>
+ </xsd:complexType>
+
+ <xsd:simpleType name="emailType">
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="[\p{L}_]+(\.[\p{L}_]+)*@[\p{L}_]+(\.[\p{L}_]+)+"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+</xsd:schema> \ No newline at end of file
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/instance.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/instance.xml
new file mode 100644
index 0000000000..5bf398dd0d
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/instance.xml
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="MeasDataCollection.xsl"?>
+<measCollecFile xmlns="http://www.3gpp.org/ftp/specs/archive/32_series/32.435#measCollec">
+ <fileHeader fileFormatVersion="32.435 V7.2.0"
+ vendorName="Ericsson AB"
+ dnPrefix="STP43">
+ <fileSender localDn="bs=18"
+ elementType="SBG"/>
+ <measCollec beginTime="2007-09-20T14:05:00+00:00"/>
+ </fileHeader>
+ <measData>
+ <managedElement localDn="bs=18"
+ userLabel="OMMP"
+ swVersion="R6A"/>
+ <measInfo measInfoId="l">
+ <job jobId="1"/>
+ <granPeriod duration="PT300S" endTime="2007-09-20T14:10:00+00:00"/>
+ <repPeriod duration="PT300S"/>
+ <measType p="1">ethernetStatsTxFrames</measType>
+ <measType p="2">ethernetStatsTxOctets</measType>
+ <measType p="3">ethernetStatsRxFrames</measType>
+ <measType p="4">ethernetStatsRxOctets</measType>
+ <measType p="5">ethernetStatsBroadcastTx</measType>
+ <measType p="6">ethernetStatsBroadcastRx</measType>
+ <measType p="7">ethernetStatsTxPauseFrames</measType>
+ <measType p="8">ethernetStatsRxMacFrames</measType>
+ <measType p="9">ethernetStatsMulticastRx</measType>
+ <measType p="10">ethernetStatsRxDiscarded</measType>
+ <measType p="11">ethernetStatsRxErrors</measType>
+ <measType p="12">ethernetStatsTxDiscarded</measType>
+ <measValue measObjLdn="Mp.bsNo=18,MpBlade.subrack=0+slot=7,EthernetInterface.port=1">
+ <r p="1">139197852</r>
+ <r p="2">19584465702</r>
+ <r p="3">144651440</r>
+ <r p="4">20348020750</r>
+ <r p="5">30</r>
+ <r p="6">27509</r>
+ <r p="7">0</r>
+ <r p="8">0</r>
+ <r p="9">114575</r>
+ <r p="10">0</r>
+ <r p="11">8590076673</r>
+ <r p="12">0</r>
+ </measValue>
+ <measValue measObjLdn="Mp.bsNo=18,MpBlade.subrack=0+slot=7,EthernetInterface.port=2">
+ <r p="1">0</r>
+ <r p="2">0</r>
+ <r p="3">0</r>
+ <r p="4">0</r>
+ <r p="5">0</r>
+ <r p="6">0</r>
+ <r p="7">0</r>
+ <r p="8">0</r>
+ <r p="9">0</r>
+ <r p="10">0</r>
+ <r p="11">0</r>
+ <r p="12">0</r>
+ </measValue>
+ <measValue measObjLdn="Mp.bsNo=18,MpBlade.subrack=0+slot=9,EthernetInterface.port=1">
+ <r p="1">2282798</r>
+ <r p="2">146099072</r>
+ <r p="3">2424888</r>
+ <r p="4">155302856</r>
+ <r p="5">3</r>
+ <r p="6">27515</r>
+ <r p="7">0</r>
+ <r p="8">0</r>
+ <r p="9">114575</r>
+ <r p="10">0</r>
+ <r p="11">142081</r>
+ <r p="12">0</r>
+ </measValue>
+ <measValue measObjLdn="Mp.bsNo=18,MpBlade.subrack=0+slot=7,EthernetInterface.port=3">
+ <r p="1">0</r>
+ <r p="2">0</r>
+ <r p="3">0</r>
+ <r p="4">0</r>
+ <r p="5">0</r>
+ <r p="6">0</r>
+ <r p="7">0</r>
+ <r p="8">0</r>
+ <r p="9">0</r>
+ <r p="10">0</r>
+ <r p="11">0</r>
+ <r p="12">0</r>
+ </measValue>
+ <measValue measObjLdn="Mp.bsNo=18,MpBlade.subrack=0+slot=9,EthernetInterface.port=2">
+ <r p="1">0</r>
+ <r p="2">0</r>
+ <r p="3">0</r>
+ <r p="4">0</r>
+ <r p="5">0</r>
+ <r p="6">0</r>
+ <r p="7">0</r>
+ <r p="8">0</r>
+ <r p="9">0</r>
+ <r p="10">0</r>
+ <r p="11">0</r>
+ <r p="12">0</r>
+ </measValue>
+ <measValue measObjLdn="Mp.bsNo=18,MpBlade.subrack=0+slot=9,EthernetInterface.port=3">
+ <r p="1">0</r>
+ <r p="2">0</r>
+ <r p="3">0</r>
+ <r p="4">0</r>
+ <r p="5">0</r>
+ <r p="6">0</r>
+ <r p="7">0</r>
+ <r p="8">0</r>
+ <r p="9">0</r>
+ <r p="10">0</r>
+ <r p="11">0</r>
+ <r p="12">0</r>
+ </measValue>
+ <measValue measObjLdn="Mp.bsNo=18,MpBlade.subrack=0+slot=7,EthernetInterface.port=0">
+ <r p="1">139211625</r>
+ <r p="2">19586502972</r>
+ <r p="3">153860245</r>
+ <r p="4">21661061980</r>
+ <r p="5">30</r>
+ <r p="6">3</r>
+ <r p="7">0</r>
+ <r p="8">0</r>
+ <r p="9">68745</r>
+ <r p="10">0</r>
+ <r p="11">68745</r>
+ <r p="12">0</r>
+ </measValue>
+ <measValue measObjLdn="Mp.bsNo=18,MpBlade.subrack=0+slot=9,EthernetInterface.port=0">
+ <r p="1">2282798</r>
+ <r p="2">146099072</r>
+ <r p="3">2351552</r>
+ <r p="4">150499328</r>
+ <r p="5">3</r>
+ <r p="6">9</r>
+ <r p="7">0</r>
+ <r p="8">0</r>
+ <r p="9">68745</r>
+ <r p="10">0</r>
+ <r p="11">68745</r>
+ <r p="12">0</r>
+ </measValue>
+ </measInfo>
+ </measData>
+ <fileFooter>
+ <measCollec endTime="2007-09-20T14:10:00+00:00"/>
+ </fileFooter>
+</measCollecFile>
+
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/int.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/int.xml
new file mode 100644
index 0000000000..9654bc56ce
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/int.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<purchaseOrder>
+4
+</purchaseOrder>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/ipo.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/ipo.xml
new file mode 100644
index 0000000000..3771926dd2
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/ipo.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<ipo:purchaseOrder
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:ipo="http://www.example.com/IPO"
+ orderDate="1999-12-01">
+
+ <shipTo exportCode="1" xsi:type="ipo:UKAddress">
+ <name>Helen Zoe</name>
+ <street>47 Eden Street</street>
+ <city>Cambridge</city>
+ <postcode>CB1 1JR</postcode>
+ </shipTo>
+
+ <billTo xsi:type="ipo:USAddress">
+ <name>Robert Smith</name>
+ <street>8 Oak Avenue</street>
+ <city>Old Town</city>
+ <state>PA</state>
+ <zip>95819</zip>
+ </billTo>
+
+ <items>
+ <item partNum="833-AA">
+ <productName>Lapis necklace</productName>
+ <quantity>1</quantity>
+ <USPrice>99.95</USPrice>
+ <ipo:comment>Want this for the holidays!</ipo:comment>
+ <shipDate>1999-12-05</shipDate>
+ </item>
+ </items>
+</ipo:purchaseOrder>
+
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/ipo.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/ipo.xsd
new file mode 100644
index 0000000000..856c712e5a
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/ipo.xsd
@@ -0,0 +1,60 @@
+<schema targetNamespace="http://www.example.com/IPO"
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:ipo="http://www.example.com/IPO">
+
+ <annotation>
+ <documentation xml:lang="en">
+ International Purchase order schema for Example.com
+ Copyright 2000 Example.com. All rights reserved.
+ </documentation>
+ </annotation>
+
+ <!-- include address constructs -->
+ <include
+ schemaLocation="address.xsd"/>
+
+ <element name="purchaseOrder" type="ipo:PurchaseOrderType"/>
+
+ <element name="comment" type="string"/>
+
+ <complexType name="PurchaseOrderType">
+ <sequence>
+ <element name="shipTo" type="ipo:Address"/>
+ <element name="billTo" type="ipo:Address"/>
+ <element ref="ipo:comment" minOccurs="0"/>
+ <element name="items" type="ipo:Items"/>
+ </sequence>
+ <attribute name="orderDate" type="date"/>
+ </complexType>
+
+ <complexType name="Items">
+ <sequence>
+ <element name="item" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="productName" type="string"/>
+ <element name="quantity">
+ <simpleType>
+ <restriction base="positiveInteger">
+ <maxExclusive value="100"/>
+ </restriction>
+ </simpleType>
+ </element>
+ <element name="USPrice" type="decimal"/>
+ <element ref="ipo:comment" minOccurs="0"/>
+ <element name="shipDate" type="date" minOccurs="0"/>
+ </sequence>
+ <attribute name="partNum" type="ipo:SKU" use="required"/>
+ </complexType>
+ </element>
+ </sequence>
+ </complexType>
+
+ <simpleType name="SKU">
+ <restriction base="string">
+ <pattern value="\d{3}-[A-Z]{2}"/>
+ </restriction>
+ </simpleType>
+
+</schema>
+
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/ipo_redefine.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/ipo_redefine.xml
new file mode 100644
index 0000000000..3f39febc03
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/ipo_redefine.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<ipo:purchaseOrder
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:ipo="http://www.example.com/IPO"
+ orderDate="1999-12-01">
+
+ <shipTo exportCode="1" xsi:type="ipo:UKAddress">
+ <name>Helen Zoe</name>
+ <street>47 Eden Street</street>
+ <city>Cambridge</city>
+ <country>United Kingdom</country>
+ <postcode>CB1 1JR</postcode>
+ </shipTo>
+
+ <billTo xsi:type="ipo:USAddress">
+ <name>Robert Smith</name>
+ <street>8 Oak Avenue</street>
+ <city>Old Town</city>
+ <country>USA</country>
+ <state>PA</state>
+ <zip>95819</zip>
+ </billTo>
+
+ <items>
+ <item partNum="833-AA">
+ <productName>Lapis necklace</productName>
+ <quantity>1</quantity>
+ <USPrice>99.95</USPrice>
+ <ipo:comment>Want this for the holidays!</ipo:comment>
+ <shipDate>1999-12-05</shipDate>
+ </item>
+ </items>
+</ipo:purchaseOrder>
+
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/ipo_redefine.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/ipo_redefine.xsd
new file mode 100644
index 0000000000..ad5e4884fd
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/ipo_redefine.xsd
@@ -0,0 +1,73 @@
+<schema targetNamespace="http://www.example.com/IPO"
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:ipo="http://www.example.com/IPO">
+
+ <annotation>
+ <documentation xml:lang="en">
+ International Purchase order schema for Example.com
+ Copyright 2000 Example.com. All rights reserved.
+ </documentation>
+ </annotation>
+
+<!-- bring in address constructs -->
+ <redefine
+ schemaLocation="address.xsd">
+
+ <!-- redefinition of Address -->
+ <complexType name="Address">
+ <complexContent>
+ <extension base="ipo:Address">
+ <sequence>
+ <element name="country" type="string"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ </redefine>
+
+ <element name="purchaseOrder" type="ipo:PurchaseOrderType"/>
+
+ <element name="comment" type="string"/>
+
+ <complexType name="PurchaseOrderType">
+ <sequence>
+ <element name="shipTo" type="ipo:Address"/>
+ <element name="billTo" type="ipo:Address"/>
+ <element ref="ipo:comment" minOccurs="0"/>
+ <element name="items" type="ipo:Items"/>
+ </sequence>
+ <attribute name="orderDate" type="date"/>
+ </complexType>
+
+ <complexType name="Items">
+ <sequence>
+ <element name="item" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="productName" type="string"/>
+ <element name="quantity">
+ <simpleType>
+ <restriction base="positiveInteger">
+ <maxExclusive value="100"/>
+ </restriction>
+ </simpleType>
+ </element>
+ <element name="USPrice" type="decimal"/>
+ <element ref="ipo:comment" minOccurs="0"/>
+ <element name="shipDate" type="date" minOccurs="0"/>
+ </sequence>
+ <attribute name="partNum" type="ipo:SKU" use="required"/>
+ </complexType>
+ </element>
+ </sequence>
+ </complexType>
+
+ <simpleType name="SKU">
+ <restriction base="string">
+ <pattern value="\d{3}-[A-Z]{2}"/>
+ </restriction>
+ </simpleType>
+
+</schema>
+
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/ipo_substGroup.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/ipo_substGroup.xml
new file mode 100644
index 0000000000..a889153dae
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/ipo_substGroup.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<ipo:purchaseOrder
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:ipo="http://www.example.com/IPO"
+ orderDate="1999-12-01">
+
+ <shipTo exportCode="1" xsi:type="ipo:UKAddress">
+ <name>Helen Zoe</name>
+ <street>47 Eden Street</street>
+ <city>Cambridge</city>
+ <postcode>CB1 1JR</postcode>
+ </shipTo>
+
+ <billTo xsi:type="ipo:USAddress">
+ <name>Robert Smith</name>
+ <street>8 Oak Avenue</street>
+ <city>Old Town</city>
+ <state>PA</state>
+ <zip>95819</zip>
+ </billTo>
+
+ <items>
+ <item partNum="833-AA">
+ <productName>Lapis necklace</productName>
+ <quantity>1</quantity>
+ <USPrice>99.95</USPrice>
+ <ipo:shipComment>
+ Use gold wrap if possible
+ </ipo:shipComment>
+ <ipo:customerComment>
+ Want this for the holidays!
+ </ipo:customerComment>
+ <shipDate>1999-12-05</shipDate>
+ </item>
+ </items>
+</ipo:purchaseOrder>
+
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/ipo_substGroup.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/ipo_substGroup.xsd
new file mode 100644
index 0000000000..3899d0f5de
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/ipo_substGroup.xsd
@@ -0,0 +1,65 @@
+<schema targetNamespace="http://www.example.com/IPO"
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:ipo="http://www.example.com/IPO">
+
+ <annotation>
+ <documentation xml:lang="en">
+ International Purchase order schema for Example.com
+ Copyright 2000 Example.com. All rights reserved.
+ </documentation>
+ </annotation>
+
+ <!-- include address constructs -->
+ <include
+ schemaLocation="address.xsd"/>
+
+ <element name="purchaseOrder" type="ipo:PurchaseOrderType"/>
+
+ <element name="comment" type="string"/>
+
+ <element name="shipComment" type="string"
+ substitutionGroup="ipo:comment"/>
+ <element name="customerComment" type="string"
+ substitutionGroup="ipo:comment"/>
+
+ <complexType name="PurchaseOrderType">
+ <sequence>
+ <element name="shipTo" type="ipo:Address"/>
+ <element name="billTo" type="ipo:Address"/>
+ <element ref="ipo:comment" minOccurs="0"/>
+ <element name="items" type="ipo:Items"/>
+ </sequence>
+ <attribute name="orderDate" type="date"/>
+ </complexType>
+
+ <complexType name="Items">
+ <sequence>
+ <element name="item" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="productName" type="string"/>
+ <element name="quantity">
+ <simpleType>
+ <restriction base="positiveInteger">
+ <maxExclusive value="100"/>
+ </restriction>
+ </simpleType>
+ </element>
+ <element name="USPrice" type="decimal"/>
+ <element ref="ipo:comment" minOccurs="0" maxOccurs="unbounded"/>
+ <element name="shipDate" type="date" minOccurs="0"/>
+ </sequence>
+ <attribute name="partNum" type="ipo:SKU" use="required"/>
+ </complexType>
+ </element>
+ </sequence>
+ </complexType>
+
+ <simpleType name="SKU">
+ <restriction base="string">
+ <pattern value="\d{3}-[A-Z]{2}"/>
+ </restriction>
+ </simpleType>
+
+</schema>
+
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/measCollec.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/measCollec.xsd
new file mode 100644
index 0000000000..3e6614effd
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/measCollec.xsd
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ 3GPP TS 32.435 Performance Measurement XML file format definition
+ data file XML schema
+ measCollec.xsd
+-->
+
+<schema
+ targetNamespace=
+"http://www.3gpp.org/ftp/specs/archive/32_series/32.435#measCollec"
+ elementFormDefault="qualified"
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:mc=
+"http://www.3gpp.org/ftp/specs/archive/32_series/32.435#measCollec"
+>
+
+ <!-- Measurement collection data file root XML element -->
+
+ <element name="measCollecFile">
+ <complexType>
+ <sequence>
+ <element name="fileHeader">
+ <complexType>
+ <sequence>
+ <element name="fileSender">
+ <complexType>
+ <attribute name="localDn" type="string" use="optional"/>
+ <attribute name="elementType" type="string" use="optional"/>
+ </complexType>
+ </element>
+ <element name="measCollec">
+ <complexType>
+ <attribute name="beginTime" type="dateTime" use="required"/>
+ </complexType>
+ </element>
+ </sequence>
+ <attribute name="fileFormatVersion" type="string" use="required"/>
+ <attribute name="vendorName" type="string" use="optional"/>
+ <attribute name="dnPrefix" type="string" use="optional"/>
+ </complexType>
+ </element>
+ <element name="measData" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="managedElement">
+ <complexType>
+ <attribute name="localDn" type="string" use="optional"/>
+ <attribute name="userLabel" type="string" use="optional"/>
+ <attribute name="swVersion" type="string" use="optional"/>
+ </complexType>
+ </element>
+ <element name="measInfo" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="job" minOccurs="0">
+ <complexType>
+ <attribute name="jobId" type="string" use="required"/>
+ </complexType>
+ </element>
+ <element name="granPeriod">
+ <complexType>
+ <attribute
+ name="duration"
+ type="duration"
+ use="required"
+ />
+ <attribute
+ name="endTime"
+ type="dateTime"
+ use="required"
+ />
+ </complexType>
+ </element>
+ <element name="repPeriod" minOccurs="0">
+ <complexType>
+ <attribute name="duration"
+ type="duration" use="required"/>
+ </complexType>
+ </element>
+ <choice>
+ <element name="measTypes">
+ <simpleType>
+ <list itemType="Name"/>
+ </simpleType>
+ </element>
+ <element name="measType"
+ minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <simpleContent>
+ <extension base="Name">
+ <attribute name="p"
+ type="positiveInteger" use="required"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+ </element>
+ </choice>
+ <element name="measValue"
+ minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <choice>
+ <element name="measResults">
+ <simpleType>
+ <list itemType="mc:measResultType"/>
+ </simpleType>
+ </element>
+ <element name="r"
+ minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <simpleContent>
+ <extension base="mc:measResultType">
+ <attribute name="p" type="positiveInteger"
+ use="required"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+ </element>
+ </choice>
+ <element name="suspect" type="boolean" minOccurs="0"/>
+ </sequence>
+ <attribute name="measObjLdn"
+ type="string" use="required"/>
+ </complexType>
+ </element>
+ </sequence>
+ <attribute name="measInfoId"
+ type="string" use="required"/>
+ </complexType>
+ </element>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="fileFooter">
+ <complexType>
+ <sequence>
+ <element name="measCollec">
+ <complexType>
+ <attribute name="endTime" type="dateTime" use="required"/>
+ </complexType>
+ </element>
+ </sequence>
+ </complexType>
+ </element>
+ </sequence>
+ </complexType>
+ </element>
+
+ <simpleType name="measResultType">
+ <union memberTypes="float">
+ <simpleType>
+ <restriction base="string">
+ <enumeration value="NIL"/>
+ </restriction>
+ </simpleType>
+ </union>
+ </simpleType>
+
+</schema>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/mim.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/mim.xsd
new file mode 100755
index 0000000000..057344cde8
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/mim.xsd
@@ -0,0 +1,511 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
+ <!--
+
+ Copyright (c) Ericsson AB 2006 All rights reserved.
+
+ The information in this document is the property of Ericsson.
+
+ Except as specifically authorized in writing by Ericsson, the
+ receiver of this document shall keep the information contained
+ herein confidential and shall protect the same in whole or in
+ part from disclosure and dissemination to third parties.
+
+ Disclosure and disseminations to the receivers employees shall
+ only be made on a strict need to know basis.
+ -->
+ <!-- Common -->
+ <xs:element name="description" type="xs:string"/>
+ <xs:element name="applicationTag">
+ <xs:complexType>
+ <xs:group minOccurs="0" maxOccurs="unbounded" ref="anyElement"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:attributeGroup name="anyAttribute">
+ <xs:anyAttribute processContents="skip"/>
+ </xs:attributeGroup>
+ <xs:group name="anyElement">
+ <xs:sequence>
+ <xs:any processContents="skip"/>
+ </xs:sequence>
+ </xs:group>
+ <!-- Mim definition -->
+ <xs:element name="mim">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:group ref="namedStruct"/>
+ <xs:element ref="enum"/>
+ <xs:group ref="dataTypeDef"/>
+ <xs:element ref="exception"/>
+ </xs:choice>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="class"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="relationship"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <!-- MO class definition -->
+ <xs:element name="class">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="applicationTag"/>
+ <xs:choice>
+ <xs:sequence>
+ <xs:element ref="singleton"/>
+ <xs:element minOccurs="0" ref="systemCreated"/>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:group ref="namedStruct"/>
+ <xs:element ref="enum"/>
+ <xs:group ref="dataTypeDef"/>
+ </xs:choice>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="attribute"/>
+ </xs:sequence>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="systemCreated"/>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:group ref="namedStruct"/>
+ <xs:element ref="enum"/>
+ <xs:group ref="dataTypeDef"/>
+ </xs:choice>
+ <xs:element maxOccurs="unbounded" ref="attribute"/>
+ </xs:sequence>
+ </xs:choice>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="action"/>
+ <xs:element minOccurs="0" ref="notificationTypes"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[A-Z][A-Za-z0-9]*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="singleton">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="systemCreated">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="notificationTypes" type="xs:string"/>
+ <!-- Relations -->
+ <xs:element name="relationship">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="applicationTag"/>
+ <xs:element ref="containment"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="containment">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="parent"/>
+ <xs:element ref="child"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="parent" type="hasClass"/>
+ <xs:element name="child">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="hasClass">
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="cardinality"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="cardinality">
+ <xs:complexType>
+ <xs:choice>
+ <xs:element ref="min"/>
+ <xs:element ref="max"/>
+ <xs:sequence>
+ <xs:element ref="min"/>
+ <xs:element ref="max"/>
+ </xs:sequence>
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="hasClass">
+ <xs:sequence>
+ <xs:element ref="hasClass"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="hasClass">
+ <xs:complexType>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <!-- Data types -->
+ <xs:group name="type">
+ <xs:choice>
+ <xs:element ref="boolean"/>
+ <xs:element ref="float"/>
+ <xs:element ref="integer"/>
+ <xs:element ref="string"/>
+ <xs:group ref="struct"/>
+ <xs:element ref="enumRef"/>
+ <xs:element ref="structRef"/>
+ <xs:element ref="moRef"/>
+ </xs:choice>
+ </xs:group>
+ <!-- For attributes, parameters and exceptions -->
+ <xs:group name="dataType">
+ <xs:sequence>
+ <xs:element name="dataType">
+ <xs:complexType>
+ <xs:choice>
+ <xs:group ref="type"/>
+ <xs:element ref="sequence"/>
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:group>
+ <xs:group name="dataTypeDef">
+ <xs:sequence>
+ <xs:element name="dataType">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="applicationTag"/>
+ <xs:choice>
+ <xs:group ref="type"/>
+ <xs:element ref="sequence"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:group>
+ <xs:group name="dataTypeRef">
+ <xs:sequence>
+ <xs:element name="dataType">
+ <xs:complexType>
+ <xs:attribute name="name.ref" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:group>
+ <!-- For actions -->
+ <xs:element name="returnType">
+ <xs:complexType>
+ <xs:choice>
+ <xs:element ref="void"/>
+ <xs:group ref="type"/>
+ <xs:element ref="sequence"/>
+ <xs:group ref="dataTypeRef"/>
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+ <!-- Return data types -->
+ <xs:element name="void">
+ <xs:complexType/>
+ </xs:element>
+ <!-- Primitive data types -->
+ <xs:element name="boolean">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="defaultValue"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="float">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="range"/>
+ <xs:element minOccurs="0" ref="defaultValue"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="integer">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="range"/>
+ <xs:element minOccurs="0" ref="defaultValue"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="string">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="lengthRange"/>
+ <xs:element minOccurs="0" ref="validValues"/>
+ <xs:element minOccurs="0" ref="pattern"/>
+ <xs:element minOccurs="0" ref="defaultValue"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pattern" type="xs:string"/>
+ <xs:element name="validValues" type="xs:string"/>
+ <xs:element name="lengthRange">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="min"/>
+ <xs:sequence minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="min"/>
+ <xs:element ref="max"/>
+ </xs:sequence>
+ <xs:element minOccurs="0" ref="max"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="range">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="min"/>
+ <xs:sequence minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="min"/>
+ <xs:element ref="max"/>
+ </xs:sequence>
+ <xs:element minOccurs="0" ref="max"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="max" type="xs:string"/>
+ <xs:element name="min" type="xs:string"/>
+ <xs:element name="defaultValue" type="xs:string"/>
+ <!-- Enum data type -->
+ <xs:element name="enum">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="applicationTag"/>
+ <xs:element maxOccurs="unbounded" ref="enumMember"/>
+ <xs:element minOccurs="0" ref="defaultValue"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="enumMember">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="applicationTag"/>
+ <xs:element minOccurs="0" ref="value"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="enumRef">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="defaultValue"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="value" type="xs:string"/>
+ <!-- Struct data type -->
+ <xs:group name="namedStruct">
+ <xs:sequence>
+ <xs:element name="struct">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="applicationTag"/>
+ <xs:element maxOccurs="unbounded" ref="structMember"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:group>
+ <xs:group name="struct">
+ <xs:sequence>
+ <xs:element name="struct">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" ref="structMember"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:group>
+ <xs:element name="structMember">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="applicationTag"/>
+ <xs:choice>
+ <xs:group ref="type"/>
+ <xs:element ref="sequence"/>
+ <xs:group ref="dataTypeRef"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="structRef">
+ <xs:complexType>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <!-- Sequence data type -->
+ <xs:element name="sequence">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice>
+ <xs:group ref="type"/>
+ <xs:group ref="dataTypeRef"/>
+ </xs:choice>
+ <xs:element minOccurs="0" ref="minLength"/>
+ <xs:element minOccurs="0" ref="maxLength"/>
+ <xs:element minOccurs="0" ref="nonUnique"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="minLength" type="xs:string"/>
+ <xs:element name="maxLength" type="xs:string"/>
+ <xs:element name="nonUnique">
+ <xs:complexType/>
+ </xs:element>
+ <!-- MoRef data type -->
+ <xs:element name="moRef">
+ <xs:complexType>
+ <xs:attribute name="name" use="required">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="(/[A-Z][A-Za-z0-9]*)*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ <!-- Attribute -->
+ <xs:element name="attribute">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="applicationTag">
+ <xs:annotation>
+ <xs:documentation>Currently not used in IS.</xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:choice>
+ <xs:group ref="dataType"/>
+ <xs:group ref="dataTypeRef"/>
+ </xs:choice>
+ <xs:element minOccurs="0" ref="initialValue"/>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="noNotification"/>
+ <xs:element ref="restricted"/>
+ <xs:element ref="readOnly"/>
+ <xs:choice>
+ <xs:element ref="key"/>
+ <xs:choice>
+ <xs:element ref="local"/>
+ <xs:element ref="mandatory"/>
+ <xs:element ref="nonPersistent"/>
+ <xs:element ref="static"/>
+ <xs:element ref="undefined"/>
+ </xs:choice>
+ </xs:choice>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="name" use="required">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[a-z][a-zA-Z0-9]*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="initialValue" type="xs:string"/>
+ <xs:element name="key">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="local">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="mandatory">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="noNotification">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="nonPersistent">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="readOnly">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="restricted">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="static">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="undefined">
+ <xs:complexType/>
+ </xs:element>
+ <!-- Action -->
+ <xs:element name="action">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="applicationTag"/>
+ <xs:element ref="returnType"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="parameter"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="raisesException"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[a-z][a-zA-Z0-9]*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="parameter">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="applicationTag"/>
+ <xs:choice>
+ <xs:group ref="dataType"/>
+ <xs:group ref="dataTypeRef"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="exception">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="applicationTag"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="exceptionParameter"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="exceptionParameter">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="applicationTag"/>
+ <xs:choice>
+ <xs:group ref="dataType"/>
+ <xs:group ref="dataTypeRef"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="raisesException">
+ <xs:complexType>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/EricssonSpecificAttributes.5.1.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/EricssonSpecificAttributes.5.1.xsd
new file mode 100644
index 0000000000..3509d13da7
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/EricssonSpecificAttributes.5.1.xsd
@@ -0,0 +1,1531 @@
+<!--
+ Configuration data file vendor-specific XML schema
+ EricssonSpecificAttributes.5.1.xsd
+ Includes Transport.
+ -->
+<schema xmlns:es="EricssonSpecificAttributes.5.1.xsd" xmlns:xn="genericNrm.xsd" xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="EricssonSpecificAttributes.5.1.xsd" elementFormDefault="qualified" attributeFormDefault="unqualified">
+ <!-- EricssonSpecificAttributes version 5.0 vendor-specific data -->
+ <import namespace="genericNrm.xsd" schemaLocation="genericNrm.xsd"/>
+ <include schemaLocation="EricssonSpecificAttributes.5.1Tran.xsd"/>
+ <element name="vsDataAntennaBranch" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="branchName" minOccurs="0"/>
+ <element name="antennaType" minOccurs="0"/>
+ <element name="verticalAntennaTilt" minOccurs="0"/>
+ <element name="mechanicalAntennaTilt" minOccurs="0"/>
+ <element name="antennaSupervisionThreshold" minOccurs="0"/>
+ <element name="fqBandHighEdge" minOccurs="0"/>
+ <element name="fqBandLowEdge" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataAntFeederCable" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="ulAttenuation" minOccurs="0" maxOccurs="unbounded"/>
+ <element name="dlAttenuation" minOccurs="0" maxOccurs="unbounded"/>
+ <element name="objectBConnector" minOccurs="0"/>
+ <element name="connectedToObjectBRef" minOccurs="0"/>
+ <element name="electricalUlDelay" minOccurs="0"/>
+ <element name="electricalDlDelay" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataAreas" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData"/>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataCchFrameSynch" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="dto" minOccurs="0"/>
+ <element name="doStep" minOccurs="0"/>
+ <element name="toAWS" minOccurs="0"/>
+ <element name="toAWE" minOccurs="0"/>
+ <element name="toAE" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataChannelSwitching" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="dlRlcBufUpswitch" minOccurs="0"/>
+ <element name="ulRlcBufUpswitch" minOccurs="0"/>
+ <element name="downswitchThreshold" minOccurs="0"/>
+ <element name="downswitchTimerThreshold" minOccurs="0"/>
+ <element name="downswitchTimer" minOccurs="0"/>
+ <element name="dlRlcBufUpswitchMrab" minOccurs="0"/>
+ <element name="ulRlcBufUpswitchMrab" minOccurs="0"/>
+ <element name="upswitchTimer" minOccurs="0"/>
+ <element name="coverageTimer" minOccurs="0"/>
+ <element name="inactivityTimer" minOccurs="0"/>
+ <element name="downswitchPwrMargin" minOccurs="0"/>
+ <element name="reportHysteresis" minOccurs="0"/>
+ <element name="upswitchPwrMargin" minOccurs="0"/>
+ <element name="downswitchTimerUp" minOccurs="0"/>
+ <element name="downswitchTimerSp" minOccurs="0"/>
+ <element name="hsdschInactivityTimer" minOccurs="0"/>
+ <element name="bandwidthMarginUl" minOccurs="0"/>
+ <element name="upswitchTimerUl" minOccurs="0"/>
+ <element name="bandwidthMargin" minOccurs="0"/>
+ <element name="dlDownswitchBandwidthMargin" minOccurs="0"/>
+ <element name="dlThroughputAllowUpswitchThreshold" minOccurs="0"/>
+ <element name="dlThroughputDownswitchTimer" minOccurs="0"/>
+ <element name="inactivityTimerPch" minOccurs="0"/>
+ <element name="multiRabSp0Available" minOccurs="0"/>
+ <element name="multiRabUdi8Available" minOccurs="0"/>
+ <element name="ulThroughputAllowUpswitchThreshold" minOccurs="0"/>
+ <element name="ulThroughputDownswitchTimer" minOccurs="0"/>
+ <element name="ulDownswitchBandwidthMargin" minOccurs="0"/>
+ <element name="inactivityTimeMultiPsInteractive" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataDchFrameSynch" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="dto" minOccurs="0"/>
+ <element name="doStep" minOccurs="0"/>
+ <element name="toAWS" minOccurs="0"/>
+ <element name="toAWE" minOccurs="0"/>
+ <element name="toAE" minOccurs="0"/>
+ <element name="uto" minOccurs="0"/>
+ <element name="uoStep" minOccurs="0"/>
+ <element name="toAWEUl" minOccurs="0"/>
+ <element name="toAEUl" minOccurs="0"/>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="toAWSUl" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataAuxPlugInUnit" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData"/>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataEquipment" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData"/>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataPlmn" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="mcc" minOccurs="0"/>
+ <element name="mnc" minOccurs="0"/>
+ <element name="mncLength" minOccurs="0"/>
+ <element name="aliasPlmnIdentities" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="mcc" minOccurs="0"/>
+ <element name="mnc" minOccurs="0"/>
+ <element name="mncLength" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataExternalGsmCell" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="maxTxPowerUl" minOccurs="0"/>
+ <element name="qRxLevMin" minOccurs="0"/>
+ <element name="individualOffset" minOccurs="0"/>
+ <element name="parentSystem" minOccurs="0"/>
+ <element name="mncLength" minOccurs="0"/>
+ <element name="bandIndicator" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataExternalGsmPlmn" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="mcc" minOccurs="0"/>
+ <element name="mnc" minOccurs="0"/>
+ <element name="mncLength" minOccurs="0"/>
+ <element name="aliasPlmnIdentities" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="mcc" minOccurs="0"/>
+ <element name="mnc" minOccurs="0"/>
+ <element name="mncLength" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataExternalTma" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="dlAttenuation" minOccurs="0"/>
+ <element name="ulGain" minOccurs="0"/>
+ <element name="dlTrafficDelayA" minOccurs="0"/>
+ <element name="dlTrafficDelayB" minOccurs="0"/>
+ <element name="internalPower" minOccurs="0"/>
+ <element name="ulTrafficDelayA" minOccurs="0"/>
+ <element name="ulTrafficDelayB" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataExternalUtranCell" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="qQualMin" minOccurs="0"/>
+ <element name="qRxLevMin" minOccurs="0"/>
+ <element name="maxTxPowerUl" minOccurs="0"/>
+ <element name="individualOffset" minOccurs="0"/>
+ <element name="parentSystem" minOccurs="0"/>
+ <element name="mncLength" minOccurs="0"/>
+ <element name="agpsEnabled" minOccurs="0"/>
+ <element name="cellCapability" minOccurs="0">
+ <complexType>
+ <sequence>
+ <element name="hsdschSupport" minOccurs="0"/>
+ <element name="edchSupport" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataExternalUtranPlmn" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="mcc" minOccurs="0"/>
+ <element name="mnc" minOccurs="0"/>
+ <element name="mncLength" minOccurs="0"/>
+ <element name="reservedBy" minOccurs="0"/>
+ <element name="aliasPlmnIdentities" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="mcc" minOccurs="0"/>
+ <element name="mnc" minOccurs="0"/>
+ <element name="mncLength" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataFach" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="maxFach1Power" minOccurs="0"/>
+ <element name="maxFach2Power" minOccurs="0"/>
+ <element name="sccpchOffset" minOccurs="0"/>
+ <element name="pOffset1Fach" minOccurs="0"/>
+ <element name="pOffset3Fach" minOccurs="0"/>
+ <element name="administrativeState" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataGsmRelation" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="qOffset1sn" minOccurs="0"/>
+ <element name="mobilityRelationType" minOccurs="0"/>
+ <element name="selectionPriority" minOccurs="0"/>
+ <element name="externalGsmCellRef" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataHandover" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="maxActiveSet" minOccurs="0"/>
+ <element name="fddGsmHOSupp" minOccurs="0"/>
+ <element name="selHoSup" minOccurs="0"/>
+ <element name="timeReleaseIuPs" minOccurs="0"/>
+ <element name="gsmAmountPropRepeat" minOccurs="0"/>
+ <element name="gsmPropRepeatInterval" minOccurs="0"/>
+ <element name="ifhoPropRepeatInterval" minOccurs="0"/>
+ <element name="ifhoAmountPropRepeat" minOccurs="0"/>
+ <element name="fddIfhoSupp" minOccurs="0"/>
+ <element name="hoTypeDrncBand1" minOccurs="0"/>
+ <element name="hoTypeDrncBand2" minOccurs="0"/>
+ <element name="hoTypeDrncBand3" minOccurs="0"/>
+ <element name="hoTypeDrncBand4" minOccurs="0"/>
+ <element name="hoTypeDrncBand5" minOccurs="0"/>
+ <element name="hoTypeDrncBand6" minOccurs="0"/>
+ <element name="hoTypeDrncBand7" minOccurs="0"/>
+ <element name="hoTypeDrncBand8" minOccurs="0"/>
+ <element name="hoTypeDrncBand9" minOccurs="0"/>
+ <element name="hoTypeDrncBand10" minOccurs="0"/>
+ <element name="hoTypeDrncBand11" minOccurs="0"/>
+ <element name="hoTypeDrncBand12" minOccurs="0"/>
+ <element name="releaseConnOffset" minOccurs="0"/>
+ <element name="hoTypeDrncBand13" minOccurs="0"/>
+ <element name="hoTypeDrncBand14" minOccurs="0"/>
+ <element name="hoTypeDrncBand15" minOccurs="0"/>
+ <element name="hoTypeDrncBand16" minOccurs="0"/>
+ <element name="hoTypeDrncBand17" minOccurs="0"/>
+ <element name="maxGsmMonSubset" minOccurs="0"/>
+ <element name="maxIefMonSubset" minOccurs="0"/>
+ <element name="cnhhoSupp" minOccurs="0"/>
+ <element name="interFreqCnhhoPenaltyEcno" minOccurs="0"/>
+ <element name="interFreqCnhhoPenaltyRscp" minOccurs="0"/>
+ <element name="intraFreqCnhhoPenalty" minOccurs="0"/>
+ <element name="intraFreqCnhhoWeight" minOccurs="0"/>
+ <element name="serviceBasedHoSupport" minOccurs="0"/>
+ <element name="tmStopGsmMeas" minOccurs="0"/>
+ <element name="eulReservedHwBandwidthSchedDataNonServCell" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataIubLink" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="rbsId" minOccurs="0"/>
+ <element name="beMarginDlHw" minOccurs="0"/>
+ <element name="dlHwAdm" minOccurs="0"/>
+ <element name="ulHwAdm" minOccurs="0"/>
+ <element name="beMarginUlHw" minOccurs="0"/>
+ <element name="rncModuleRef" minOccurs="0"/>
+ <element name="preferredSubrackRef" minOccurs="0"/>
+ <element name="edchIubDynDelayLimit" minOccurs="0"/>
+ <element name="userPlaneTransportOption" minOccurs="0">
+ <complexType>
+ <sequence>
+ <element name="atm" minOccurs="0"/>
+ <element name="ipv4" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataIurLink" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="mcc" minOccurs="0"/>
+ <element name="mnc" minOccurs="0"/>
+ <element name="mncLength" minOccurs="0"/>
+ <element name="rncId" minOccurs="0"/>
+ <element name="aliasPlmnIdentities" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="mcc" minOccurs="0"/>
+ <element name="mnc" minOccurs="0"/>
+ <element name="mncLength" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="utranNetworkRef" minOccurs="0"/>
+ <element name="cellCapabilityControl" minOccurs="0">
+ <complexType>
+ <sequence>
+ <element name="hsdschSupport" minOccurs="0"/>
+ <element name="edchSupport" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="hspaPathlossThreshold" minOccurs="0"/>
+ <element name="userPlaneTransportOption" minOccurs="0">
+ <complexType>
+ <sequence>
+ <element name="atm" minOccurs="0"/>
+ <element name="ipv4" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataLocationArea" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="lac" minOccurs="0"/>
+ <element name="t3212" minOccurs="0"/>
+ <element name="att" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataMeContext" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="ipAddress" minOccurs="0"/>
+ <element name="neMIMversion" minOccurs="0"/>
+ <element name="rbsIubId" minOccurs="0"/>
+ <element name="bcrLastChange" minOccurs="0"/>
+ <element name="bctLastChange" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataNodeBFunction" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="toaeDch" minOccurs="0"/>
+ <element name="toaeCch" minOccurs="0"/>
+ <element name="fwdGuardPeriod" minOccurs="0"/>
+ <element name="bwdGuardPeriod" minOccurs="0"/>
+ <element name="tpcFilterLength" minOccurs="0"/>
+ <element name="branchDiffAbsTime" minOccurs="0"/>
+ <element name="branchDiffMeasTime" minOccurs="0"/>
+ <element name="countersAlarmThreshold" minOccurs="0"/>
+ <element name="maxNumberOfCounters" minOccurs="0"/>
+ <element name="steeredHsAllocation" minOccurs="0"/>
+ <element name="eulNoReschUsers" minOccurs="0"/>
+ <element name="eulTargetRate" minOccurs="0"/>
+ <element name="eulMaxShoRate" minOccurs="0"/>
+ <element name="supportOf16qam" minOccurs="0"/>
+ <element name="flexibleSchedulerOn" minOccurs="0"/>
+ <element name="eulReservedHwBandwidthSchedDataNonServCell" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataPaging" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="cnDrxCycleLengthCs" minOccurs="0"/>
+ <element name="cnDrxCycleLengthPs" minOccurs="0"/>
+ <element name="noOfPagingRecordTransm" minOccurs="0"/>
+ <element name="utranDrxCycleLength" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataPch" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="pchPower" minOccurs="0"/>
+ <element name="pichPower" minOccurs="0"/>
+ <element name="sccpchOffset" minOccurs="0"/>
+ <element name="administrativeState" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataPowerControl" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="cBackOff" minOccurs="0"/>
+ <element name="ulOuterLoopRegulator" minOccurs="0"/>
+ <element name="ulSirStep" minOccurs="0"/>
+ <element name="sirMin" minOccurs="0"/>
+ <element name="sirMax" minOccurs="0"/>
+ <element name="dlPcMethod" minOccurs="0"/>
+ <element name="cPO" minOccurs="0"/>
+ <element name="pO1" minOccurs="0"/>
+ <element name="pO2" minOccurs="0"/>
+ <element name="pO3" minOccurs="0"/>
+ <element name="ecNoPcpichDefault" minOccurs="0"/>
+ <element name="pcpichPowerDefault" minOccurs="0"/>
+ <element name="fixedPowerDl" minOccurs="0"/>
+ <element name="cNbifho" minOccurs="0"/>
+ <element name="fixedRefPower" minOccurs="0"/>
+ <element name="initShoPowerParam" minOccurs="0"/>
+ <element name="dlInitSirTarget" minOccurs="0"/>
+ <element name="ulInitSirTargetExtraHigh" minOccurs="0"/>
+ <element name="ulInitSirTargetHigh" minOccurs="0"/>
+ <element name="ulInitSirTargetLow" minOccurs="0"/>
+ <element name="ulInitSirTargetSrb" minOccurs="0"/>
+ <element name="transmissionTargetError" minOccurs="0"/>
+ <element name="ulInitSirTargetEdch" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataRach" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="scramblingCodeWordNo" minOccurs="0"/>
+ <element name="preambleSignatures" minOccurs="0"/>
+ <element name="subChannelNo" minOccurs="0"/>
+ <element name="aichTransmissionTiming" minOccurs="0"/>
+ <element name="aichPower" minOccurs="0"/>
+ <element name="powerOffsetP0" minOccurs="0"/>
+ <element name="powerOffsetPpm" minOccurs="0"/>
+ <element name="preambleRetransMax" minOccurs="0"/>
+ <element name="maxPreambleCycle" minOccurs="0"/>
+ <element name="constantValueCprach" minOccurs="0"/>
+ <element name="spreadingFactor" minOccurs="0"/>
+ <element name="administrativeState" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataRbsLocalCell" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="localCellId" minOccurs="0"/>
+ <element name="cellRange" minOccurs="0"/>
+ <element name="carrierRef" minOccurs="0"/>
+ <element name="dynamicHsPdschCodeAdditionOn" minOccurs="0"/>
+ <element name="hsCodeResourceId" minOccurs="0"/>
+ <element name="maxNumHsPdschCodes" minOccurs="0"/>
+ <element name="eulMaxRotCoverage" minOccurs="0"/>
+ <element name="eulMaxOwnUuLoad" minOccurs="0"/>
+ <element name="maxUserEHichERgchPowerDl" minOccurs="0"/>
+ <element name="eulMaxNoSchEDch" minOccurs="0"/>
+ <element name="eulMinMarginCoverage" minOccurs="0"/>
+ <element name="eulOptimalNoiseFloorLock" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="eulNoiseFloorLock" minOccurs="0"/>
+ <element name="eulOptimalNoiseFloorEstimate" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="eulSlidingWindowTime" minOccurs="0"/>
+ <element name="eulThermalLevelPrior" minOccurs="0"/>
+ <element name="eulNoERgchGroups" minOccurs="0"/>
+ <element name="maxEAgchPowerDl" minOccurs="0"/>
+ <element name="maxNumHsdpaUsers" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataRcs" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="dchRcLostT" minOccurs="0"/>
+ <element name="cchWaitCuT" minOccurs="0"/>
+ <element name="hsDschRcLostT" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataRetDevice" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="electricalAntennaTilt" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataRetDeviceSet" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="retType" minOccurs="0"/>
+ <element name="productNumber" minOccurs="0"/>
+ <element name="revState" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <!--element name="vsDataRetProfile" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element-->
+ <element name="vsDataRetuDeviceGroup" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData"/>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataRoutingArea" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="rac" minOccurs="0"/>
+ <element name="nmo" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataRrc" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="t305" minOccurs="0"/>
+ <element name="packetEstMode" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataSector" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="numberOfCarriers" minOccurs="0"/>
+ <element name="numberOfTxBranches" minOccurs="0"/>
+ <element name="outputPower" minOccurs="0"/>
+ <element name="latitude" minOccurs="0"/>
+ <element name="latHemisphere" minOccurs="0"/>
+ <element name="longitude" minOccurs="0"/>
+ <element name="longHemisphere" minOccurs="0"/>
+ <element name="geoDatum" minOccurs="0"/>
+ <element name="beamDirection" minOccurs="0"/>
+ <element name="height" minOccurs="0"/>
+ <element name="sectorAntennaRef" minOccurs="0"/>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="retDeviceRef" minOccurs="0"/>
+ <element name="maxInternalUlGainOn" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataSectorAntenna" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="antennaType" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataCarrier" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="cqiAdjustmentOn" minOccurs="0"/>
+ <element name="cqiErrors" minOccurs="0"/>
+ <element name="cqiErrorsAbsent" minOccurs="0"/>
+ <element name="hsPowerMargin" minOccurs="0"/>
+ <element name="hsScchMaxCodePower" minOccurs="0"/>
+ <element name="queueSelectAlgorithm" minOccurs="0"/>
+ <element name="frequencyPlane" minOccurs="0"/>
+ <element name="hsScchMinCodePower" minOccurs="0"/>
+ <element name="qualityCheckPower" minOccurs="0"/>
+ <element name="supportOf16qam" minOccurs="0"/>
+ <element name="airRateTypeSelector" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataServiceArea" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="sac" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataSid" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="updateCellReattsNo" minOccurs="0"/>
+ <element name="noOfMaxDrxCycles" minOccurs="0"/>
+ <element name="noOfMibValueTagRetrans" minOccurs="0"/>
+ <element name="sib1" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="sib1RepPeriod" minOccurs="0"/>
+ <element name="sib1StartPos" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="sib11" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="sib11RepPeriod" minOccurs="0"/>
+ <element name="sib11StartPos" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="sib12" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="sib12RepPeriod" minOccurs="0"/>
+ <element name="sib12StartPos" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="sib3" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="sib3RepPeriod" minOccurs="0"/>
+ <element name="sib3StartPos" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="sib5" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="sib5RepPeriod" minOccurs="0"/>
+ <element name="sib5StartPos" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="sib7" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="sib7RepPeriod" minOccurs="0"/>
+ <element name="sib7StartPos" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="sib7ExpirationTimeFactor" minOccurs="0"/>
+ <element name="sib2" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="sib2RepPeriod" minOccurs="0"/>
+ <element name="sib2StartPos" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataUeMeasControl" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="reportingRange1a" minOccurs="0"/>
+ <element name="reportingRange1b" minOccurs="0"/>
+ <element name="hysteresis1c" minOccurs="0"/>
+ <element name="hysteresis1d" minOccurs="0"/>
+ <element name="hysteresis2d" minOccurs="0"/>
+ <element name="hysteresis2f" minOccurs="0"/>
+ <element name="gsmThresh3a" minOccurs="0"/>
+ <element name="hysteresis3a" minOccurs="0"/>
+ <element name="measQuantity1" minOccurs="0"/>
+ <element name="ueTxPowerThresh6a" minOccurs="0"/>
+ <element name="ueTxPowerThresh6b" minOccurs="0"/>
+ <element name="usedFreqThresh2dEcnoDrnc" minOccurs="0"/>
+ <element name="usedFreqThresh2dRscpDrnc" minOccurs="0"/>
+ <element name="usedFreqRelThresh2fEcno" minOccurs="0"/>
+ <element name="usedFreqRelThresh2fRscp" minOccurs="0"/>
+ <element name="hyst4_2b" minOccurs="0"/>
+ <element name="nonUsedFreqThresh4_2bEcno" minOccurs="0"/>
+ <element name="nonUsedFreqThresh4_2bRscp" minOccurs="0"/>
+ <element name="timeToTrigger1a" minOccurs="0"/>
+ <element name="hysteresis1a" minOccurs="0"/>
+ <element name="timeToTrigger1b" minOccurs="0"/>
+ <element name="hysteresis1b" minOccurs="0"/>
+ <element name="timeToTrigger1c" minOccurs="0"/>
+ <element name="timeToTrigger1d" minOccurs="0"/>
+ <element name="timeToTrigger3a" minOccurs="0"/>
+ <element name="reportingInterval1a" minOccurs="0"/>
+ <element name="reportingInterval1c" minOccurs="0"/>
+ <element name="timeTrigg6a" minOccurs="0"/>
+ <element name="timeTrigg6b" minOccurs="0"/>
+ <element name="timeTrigg4_2b" minOccurs="0"/>
+ <element name="hsHysteresis1d" minOccurs="0"/>
+ <element name="hsQualityEstimate" minOccurs="0"/>
+ <element name="hsTimeToTrigger1d" minOccurs="0"/>
+ <element name="filterCoefficient1" minOccurs="0"/>
+ <element name="filterCoefficient2" minOccurs="0"/>
+ <element name="utranFilterCoefficient3" minOccurs="0"/>
+ <element name="gsmFilterCoefficient3" minOccurs="0"/>
+ <element name="filterCoeff6" minOccurs="0"/>
+ <element name="filterCoeff4_2b" minOccurs="0"/>
+ <element name="w1a" minOccurs="0"/>
+ <element name="w1b" minOccurs="0"/>
+ <element name="usedFreqW2d" minOccurs="0"/>
+ <element name="usedFreqW2f" minOccurs="0"/>
+ <element name="usedFreqW4_2b" minOccurs="0"/>
+ <element name="utranW3a" minOccurs="0"/>
+ <element name="nonUsedFreqW4_2b" minOccurs="0"/>
+ <element name="timeToTrigger2dEcno" minOccurs="0"/>
+ <element name="timeToTrigger2fEcno" minOccurs="0"/>
+ <element name="utranRelThresh3aEcno" minOccurs="0"/>
+ <element name="utranRelThresh3aRscp" minOccurs="0"/>
+ <element name="usedFreqRelThresh4_2bEcno" minOccurs="0"/>
+ <element name="usedFreqRelThresh4_2bRscp" minOccurs="0"/>
+ <element name="timeToTrigger2dRscp" minOccurs="0"/>
+ <element name="timeToTrigger2fRscp" minOccurs="0"/>
+ <element name="utranRelThreshRscp" minOccurs="0"/>
+ <element name="event1dRncThreshold" minOccurs="0"/>
+ <element name="event1dRncOffset" minOccurs="0"/>
+ <element name="timeToTrigger6d" minOccurs="0"/>
+ <element name="txPowerConnQualMonEnabled" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataUeRc" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="serviceOffset2dEcno" minOccurs="0"/>
+ <element name="serviceOffset2dRscp" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataUeRcTrCh" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="blerQualityTargetDl" minOccurs="0"/>
+ <element name="blerQualityTargetUl" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataUtranCell" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="tCell" minOccurs="0"/>
+ <element name="cellReserved" minOccurs="0"/>
+ <element name="treSelection" minOccurs="0"/>
+ <element name="qualMeasQuantity" minOccurs="0"/>
+ <element name="qHyst1" minOccurs="0"/>
+ <element name="qHyst2" minOccurs="0"/>
+ <element name="qQualMin" minOccurs="0"/>
+ <element name="qRxLevMin" minOccurs="0"/>
+ <element name="individualOffset" minOccurs="0"/>
+ <element name="pwrAdm" minOccurs="0"/>
+ <element name="pwrAdmOffset" minOccurs="0"/>
+ <element name="pwrOffset" minOccurs="0"/>
+ <element name="pwrHyst" minOccurs="0"/>
+ <element name="tmCongAction" minOccurs="0"/>
+ <element name="releaseAseDl" minOccurs="0"/>
+ <element name="aseDlAdm" minOccurs="0"/>
+ <element name="dlCodeAdm" minOccurs="0"/>
+ <element name="aseUlAdm" minOccurs="0"/>
+ <element name="sf8Adm" minOccurs="0"/>
+ <element name="sf32Adm" minOccurs="0"/>
+ <element name="aseUlAdmOffset" minOccurs="0"/>
+ <element name="minPwrRl" minOccurs="0"/>
+ <element name="maxRate" minOccurs="0"/>
+ <element name="interRate" minOccurs="0"/>
+ <element name="minimumRate" minOccurs="0"/>
+ <element name="maxPwrMax" minOccurs="0"/>
+ <element name="interPwrMax" minOccurs="0"/>
+ <element name="minPwrMax" minOccurs="0"/>
+ <element name="compModeAdm" minOccurs="0"/>
+ <element name="iFOffset" minOccurs="0"/>
+ <element name="iFHyst" minOccurs="0"/>
+ <element name="iFCong" minOccurs="0"/>
+ <element name="interFreqFddMeasIndicator" minOccurs="0"/>
+ <element name="sRatSearch" minOccurs="0"/>
+ <element name="sIntraSearch" minOccurs="0"/>
+ <element name="sInterSearch" minOccurs="0"/>
+ <element name="fachMeasOccaCycLenCoeff" minOccurs="0"/>
+ <element name="accessClassNBarred" minOccurs="0" maxOccurs="unbounded"/>
+ <element name="utranCellPosition" minOccurs="0" maxOccurs="unbounded"/>
+ <element name="maxTxPowerUl" minOccurs="0"/>
+ <element name="beMarginAseUl" minOccurs="0"/>
+ <element name="beMarginAseDl" minOccurs="0"/>
+ <element name="reservedBy" minOccurs="0" maxOccurs="unbounded"/>
+ <element name="sib1PlmnScopeValueTag" minOccurs="0"/>
+ <element name="sf16Adm" minOccurs="0"/>
+ <element name="beMarginDlPwr" minOccurs="0"/>
+ <element name="beMarginDlCode" minOccurs="0"/>
+ <element name="hoType" minOccurs="0"/>
+ <element name="usedFreqThresh2dEcno" minOccurs="0"/>
+ <element name="usedFreqThresh2dRscp" minOccurs="0"/>
+ <element name="administrativeState" minOccurs="0"/>
+ <element name="loadSharingGsmThreshold" minOccurs="0"/>
+ <element name="loadSharingGsmFraction" minOccurs="0"/>
+ <element name="snDirectedRetryTarget" minOccurs="0"/>
+ <element name="nInSyncInd" minOccurs="0"/>
+ <element name="rlFailureT" minOccurs="0"/>
+ <element name="nOutSyncInd" minOccurs="0"/>
+ <element name="sf4AdmUl" minOccurs="0"/>
+ <element name="hardIfhoCorr" minOccurs="0"/>
+ <element name="hsdpaUsersAdm" minOccurs="0"/>
+ <element name="loadSharingMargin" minOccurs="0"/>
+ <element name="releaseAseDlGhs" minOccurs="0"/>
+ <element name="tmCongActionGhs" minOccurs="0"/>
+ <element name="tmInitialGhs" minOccurs="0"/>
+ <element name="sf4UlPathlossThreshold" minOccurs="0"/>
+ <element name="ulPathlossCheckEnabled" minOccurs="0"/>
+ <element name="sHcsRat" minOccurs="0"/>
+ <element name="sf16gAdm" minOccurs="0"/>
+ <element name="releaseAseDlNg" minOccurs="0"/>
+ <element name="tmCongActionNg" minOccurs="0"/>
+ <element name="tmInitialG" minOccurs="0"/>
+ <element name="sf16AdmUl" minOccurs="0"/>
+ <element name="sf8AdmUl" minOccurs="0"/>
+ <element name="sf8gAdmUl" minOccurs="0"/>
+ <element name="iubLinkRef" minOccurs="0"/>
+ <element name="eulNonServingCellUsersAdm" minOccurs="0"/>
+ <element name="eulServingCellUsersAdm" minOccurs="0"/>
+ <element name="agpsEnabled" minOccurs="0"/>
+ <element name="codeLoadThresholdDlSf128" minOccurs="0"/>
+ <element name="pwrLoadThresholdDlSpeech" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="amr12200" minOccurs="0"/>
+ <element name="amr7950" minOccurs="0"/>
+ <element name="amr5900" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="aseLoadThresholdUlSpeech" minOccurs="0">
+ <complexType>
+ <sequence>
+ <element name="amr12200" minOccurs="0"/>
+ <element name="amr7950" minOccurs="0"/>
+ <element name="amr5900" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="accessClassesBarredCs" minOccurs="0" maxOccurs="unbounded"/>
+ <element name="accessClassesBarredPs" minOccurs="0" maxOccurs="unbounded"/>
+ <element name="rateSelectionPsInteractive" minOccurs="0">
+ <complexType>
+ <sequence>
+ <element name="channelType" minOccurs="0"/>
+ <element name="ulPrefRate" minOccurs="0"/>
+ <element name="dlPrefRate" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="hcsUsage" minOccurs="0">
+ <complexType>
+ <sequence>
+ <element name="idleMode" minOccurs="0"/>
+ <element name="connectedMode" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="hcsSib3Config" minOccurs="0">
+ <complexType>
+ <sequence>
+ <element name="sSearchHcs" minOccurs="0"/>
+ <element name="hcsPrio" minOccurs="0"/>
+ <element name="qHcs" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataUtranRelation" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="qOffset1sn" minOccurs="0"/>
+ <element name="qOffset2sn" minOccurs="0"/>
+ <element name="loadSharingCandidate" minOccurs="0"/>
+ <element name="selectionPriority" minOccurs="0"/>
+ <element name="frequencyRelationType" minOccurs="0"/>
+ <element name="hcsSib11Config" minOccurs="0">
+ <complexType>
+ <sequence>
+ <element name="hcsPrio" minOccurs="0"/>
+ <element name="qHcs" minOccurs="0"/>
+ <element name="penaltyTime" minOccurs="0"/>
+ <element name="temporaryOffset1" minOccurs="0"/>
+ <element name="temporaryOffset2" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataRncFunction" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="mncLength" minOccurs="0"/>
+ <element name="emergencyCallRedirect" minOccurs="0"/>
+ <element name="loadSharingDirRetryEnabled" minOccurs="0"/>
+ <element name="hsCellChangeAllowed" minOccurs="0"/>
+ <element name="hsOnlyBestCell" minOccurs="0"/>
+ <element name="aliasPlmnIdentities" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="mcc" minOccurs="0"/>
+ <element name="mnc" minOccurs="0"/>
+ <element name="mncLength" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="counterAlarmCeaseLimit" minOccurs="0"/>
+ <element name="counterAlarmThreshold" minOccurs="0"/>
+ <element name="counterWarningAlarmCeaseLimit" minOccurs="0"/>
+ <element name="ctrFileSize" minOccurs="0"/>
+ <element name="gpehDataLevel" minOccurs="0"/>
+ <element name="gpehFileSize" minOccurs="0"/>
+ <element name="loadSharingRrcEnabled" minOccurs="0"/>
+ <element name="uetrFileSize" minOccurs="0"/>
+ <element name="networkResourceIdentifierLengthCs" minOccurs="0"/>
+ <element name="networkResourceIdentifierLengthPs" minOccurs="0"/>
+ <element name="hsToDchTrigger" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="servHsChangeInterRnc" minOccurs="0"/>
+ <element name="servHsChangeIntraRnc" minOccurs="0"/>
+ <element name="changeOfBestCellIntraRnc" minOccurs="0"/>
+ <element name="poorQualityDetected" minOccurs="0"/>
+ <element name="changeOfBestCellInterRnc" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="harqTransmUlTti10Max" minOccurs="0" maxOccurs="unbounded"/>
+ <element name="ecLocationAttemptUmts" minOccurs="0"/>
+ <element name="ecCnSbhoRequestIgnore" minOccurs="0"/>
+ <element name="ecCnPriorityLevel" minOccurs="0"/>
+ <element name="ecSbhoTimer" minOccurs="0"/>
+ <element name="primaryCnOperatorRef" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataUeRcEdchFlow" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="harqTransmUlMax" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataSecurityHandling" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="ciphering" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataRabHandling" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="psStreamingInactivityTimer" minOccurs="0"/>
+ <element name="activeQueueMgmt" minOccurs="0"/>
+ <element name="dscpValuePsStreaming" minOccurs="0"/>
+ <element name="psStreaming128" minOccurs="0"/>
+ <element name="state128_128Supported" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataSubrack" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData"/>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataSlot" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData"/>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataPlugInUnit" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="administrativeState" minOccurs="0"/>
+ <element name="allowedSeqRestarts" minOccurs="0"/>
+ <element name="piuGroupNumber" minOccurs="0"/>
+ <element name="piuType" minOccurs="0"/>
+ <element name="productType" minOccurs="0"/>
+ <element name="userLabel" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <!--element name="vsDataGigaBitEthernet" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element-->
+ <element name="vsDataUePositioning" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="enabledPositioningFeatures" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataGpsReceiver" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="administrativeState" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataAgpsPositioning" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="altitudeDirection" minOccurs="0"/>
+ <element name="altitude" minOccurs="0"/>
+ <element name="uncertaintyAltitude" minOccurs="0"/>
+ <element name="confidence" minOccurs="0"/>
+ <element name="polygonRadiusFactor" minOccurs="0"/>
+ <element name="utranRnsPosition" minOccurs="0">
+ <complexType>
+ <sequence>
+ <element name="latitudeSign" minOccurs="0"/>
+ <element name="latitude" minOccurs="0"/>
+ <element name="longitude" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="utranRnsUncertaintyRadius" minOccurs="0"/>
+ <element name="utranRnsConfidence" minOccurs="0"/>
+ <element name="elevationThreshold" minOccurs="0"/>
+ <element name="ueMeasurementReportCriteria" minOccurs="0">
+ <complexType>
+ <sequence>
+ <element name="reportingAmount" minOccurs="0"/>
+ <element name="reportingInterval" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataIubDataStreams" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="maxHsRate" minOccurs="0"/>
+ <element name="maxEDchRate" minOccurs="0"/>
+ <element name="hsDataFrameDelayThreshold" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataTxDeviceGroup" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="loadHs" minOccurs="0"/>
+ <element name="numHsCodeResources" minOccurs="0"/>
+ <element name="numEulResources" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataHsdsch" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="administrativeState" minOccurs="0"/>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="numHsPdschCodes" minOccurs="0"/>
+ <element name="deltaAck1" minOccurs="0"/>
+ <element name="deltaNack1" minOccurs="0"/>
+ <element name="deltaAck2" minOccurs="0"/>
+ <element name="deltaNack2" minOccurs="0"/>
+ <element name="deltaCqi1" minOccurs="0"/>
+ <element name="deltaCqi2" minOccurs="0"/>
+ <element name="initialCqiRepetitionFactor" minOccurs="0"/>
+ <element name="initialAckNackRepetitionFactor" minOccurs="0"/>
+ <element name="cqiFeedbackCycle" minOccurs="0"/>
+ <element name="hsMeasurementPowerOffset" minOccurs="0"/>
+ <element name="codeThresholdPdu656" minOccurs="0"/>
+ <element name="numHsScchCodes" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataCoverageRelation" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="utranCellRef" minOccurs="0"/>
+ <element name="coverageIndicator" minOccurs="0"/>
+ <element name="hsPathlossThreshold" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataUeRcRab" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="fcState" minOccurs="0"/>
+ <element name="trBearerQosClass" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataUeRcRrc" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="trBearerQosClass" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataUeRabType" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="trBearerQosClass" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataUra" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="uraIdentity" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataLicensing" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData"/>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataRncFeature" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="featureState" minOccurs="0"/>
+ <element name="licenseState" minOccurs="0"/>
+ <element name="serviceState" minOccurs="0"/>
+ <element name="keyId" minOccurs="0"/>
+ <element name="isLicenseControlled" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataEul" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="administrativeState" minOccurs="0"/>
+ <element name="numEagchCodes" minOccurs="0"/>
+ <element name="numEhichErgchCodes" minOccurs="0"/>
+ <element name="eulMaxTargetRtwp" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataSystemFunctions" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData"/>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataIubEdch" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="edchDataFrameDelayThreshold" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataWcdmaCarrier" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="defaultHoType" minOccurs="0"/>
+ <element name="freqBand" minOccurs="0"/>
+ <element name="sib5bisEnabled" minOccurs="0"/>
+ <element name="uarfcnDl" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataUtranNetwork" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="aliasPlmnIdentities" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="mcc" minOccurs="0"/>
+ <element name="mnc" minOccurs="0"/>
+ <element name="mncLength" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="plmnIdentity" minOccurs="0">
+ <complexType>
+ <sequence>
+ <element name="mcc" minOccurs="0"/>
+ <element name="mnc" minOccurs="0"/>
+ <element name="mncLength" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataCnOperator" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="plmnIdentity" minOccurs="0">
+ <complexType>
+ <sequence>
+ <element name="mcc" minOccurs="0"/>
+ <element name="mnc" minOccurs="0"/>
+ <element name="mncLength" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ <element name="iphoNetworkRefsUtran" minOccurs="0"/>
+ <element name="iphoNetworkRefsGsm" minOccurs="0"/>
+ <element name="equivalentPlmnIdentities" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="mcc" minOccurs="0"/>
+ <element name="mnc" minOccurs="0"/>
+ <element name="mncLength" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ </element>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataRbsSynchronization" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="plugInUnitRef1" minOccurs="0"/>
+ <element name="plugInUnitRef2" minOccurs="0"/>
+ <element name="timDeviceRef1" minOccurs="0"/>
+ <element name="timDeviceRef2" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataUeRcPhyChEdch" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="eulHarqRv" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="vsDataPmService" substitutionGroup="xn:vsData">
+ <complexType>
+ <complexContent>
+ <extension base="xn:vsData">
+ <sequence>
+ <element name="minorAlarmCeasingDelta" minOccurs="0"/>
+ <element name="warningAlarmLimitPercent" minOccurs="0"/>
+ <element name="warningAlarmCeasingDelta" minOccurs="0"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+</schema>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/EricssonSpecificAttributes.5.1Tran.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/EricssonSpecificAttributes.5.1Tran.xsd
new file mode 100644
index 0000000000..33e00bab48
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/EricssonSpecificAttributes.5.1Tran.xsd
@@ -0,0 +1,2164 @@
+<!--
+ Configuration data file vendor-specific XML schema
+ EricssonSpecificAttributes.5.1Tran.xsd Implementation of BCT I/face.Requires BCR/Bulk CM General installed
+ For use with ONLY with EricssonSpecificAttributes.5.1.xsd
+ NB!! See EricssonSpecificAttributes.5.1.xsd
+ Use Namespace for EricssonSpecificAttributes.5.1.xsd in all files which conform to this schema
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xn="genericNrm.xsd" elementFormDefault="qualified" attributeFormDefault="unqualified">
+ <!-- EricssonSpecificAttributes version 5.1 vendor-specific data -->
+ <xs:import namespace="genericNrm.xsd" schemaLocation="genericNrm.xsd"/>
+ <xs:element name="vsDataAal0TpVccTp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="alarmReport" minOccurs="0"/>
+ <xs:element name="continuityCheck" minOccurs="0"/>
+ <xs:element name="nomPmBlkSize" minOccurs="0"/>
+ <xs:element name="processorId" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="vclTpId" minOccurs="0"/>
+ <xs:element name="counterMode" minOccurs="0"/>
+ <xs:element name="counterActivation" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataAal1TpVccTp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="nomPmBlockSize" minOccurs="0"/>
+ <xs:element name="ds0BundleId" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="vclTpId" minOccurs="0"/>
+ <xs:element name="counterMode" minOccurs="0"/>
+ <xs:element name="partialFill" minOccurs="0"/>
+ <xs:element name="alarmReport" minOccurs="0"/>
+ <xs:element name="cdvt" minOccurs="0"/>
+ <xs:element name="continuityCheck" minOccurs="0"/>
+ <xs:element name="counterActivation" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataAal2Ap" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="aal2QoSCodePointProfileId" minOccurs="0"/>
+ <xs:element name="rpuId" minOccurs="0"/>
+ <xs:element name="secondarySigLinkId" minOccurs="0"/>
+ <xs:element name="sigLinkId" minOccurs="0"/>
+ <xs:element name="timerErq" minOccurs="0"/>
+ <xs:element name="timerRel" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="allocationMode" minOccurs="0"/>
+ <xs:element name="reallocate" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataAtmConfService" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="reallocateAllAal2Aps" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataAal2PathDistributionUnit" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="rpuId" minOccurs="0"/>
+ <xs:element name="aal2PathVccTpList" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="addPath" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="aal2PathVccTpId" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="removePath" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="aal2PathList" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataAal2PathVccTp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="aal2PathOwner" minOccurs="0"/>
+ <xs:element name="alarmReport" minOccurs="0"/>
+ <xs:element name="nomPmBlocksize" minOccurs="0"/>
+ <xs:element name="timerCu" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="administrativeState" minOccurs="0"/>
+ <xs:element name="continuityCheck" minOccurs="0"/>
+ <xs:element name="aal2PathId" minOccurs="0"/>
+ <xs:element name="vclTpId" minOccurs="0"/>
+ <xs:element name="aal2QoSAvailableProfiles" minOccurs="0"/>
+ <xs:element name="aal2QoSProfileId" minOccurs="0"/>
+ <xs:element name="counterMode" minOccurs="0"/>
+ <xs:element name="counterActivation" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataAal2RoutingCase" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="numberDirection" minOccurs="0"/>
+ <xs:element name="routeList" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="routePriorityList" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="addAal2ApToRc" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="priority" minOccurs="0"/>
+ <xs:element name="route" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="removeAal2ApFromRc" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="route" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataAal2Sp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="a2ea" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataAal5TpVccTp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="alarmReport" minOccurs="0"/>
+ <xs:element name="continuityCheck" minOccurs="0"/>
+ <xs:element name="fromUserMaxSduSize" minOccurs="0"/>
+ <xs:element name="nomPmBlkSize" minOccurs="0"/>
+ <xs:element name="processorId" minOccurs="0"/>
+ <xs:element name="toUserMaxSduSize" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="vclTpId" minOccurs="0"/>
+ <xs:element name="counterMode" minOccurs="0"/>
+ <xs:element name="counterActivation" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataAtmCrossConnection" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="vclTpAId" minOccurs="0"/>
+ <xs:element name="vclTpBId" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataAtmTrafficDescriptor" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="egressAtmMcr" minOccurs="0"/>
+ <xs:element name="egressAtmPcr" minOccurs="0"/>
+ <xs:element name="egressAtmQos" minOccurs="0"/>
+ <xs:element name="ingressAtmMcr" minOccurs="0"/>
+ <xs:element name="ingressAtmPcr" minOccurs="0"/>
+ <xs:element name="ingressAtmQos" minOccurs="0"/>
+ <xs:element name="serviceCategory" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="packetDiscard" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataAtmPort" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="uses" minOccurs="0"/>
+ <xs:element name="hecCorrectionMode" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataTransportNetwork" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataUniSaalProfile" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="profileData" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="congestionAbatement" minOccurs="0"/>
+ <xs:element name="congestionOnSet" minOccurs="0"/>
+ <xs:element name="initialCredit" minOccurs="0"/>
+ <xs:element name="maxCC" minOccurs="0"/>
+ <xs:element name="maxPD" minOccurs="0"/>
+ <xs:element name="maxStat" minOccurs="0"/>
+ <xs:element name="timerCC" minOccurs="0"/>
+ <xs:element name="timerIdle" minOccurs="0"/>
+ <xs:element name="timerKeepAlive" minOccurs="0"/>
+ <xs:element name="timerNoResponse" minOccurs="0"/>
+ <xs:element name="timerPoll" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataUniSaalTp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="aal5TpVccTpId" minOccurs="0"/>
+ <xs:element name="maxSduSize" minOccurs="0"/>
+ <xs:element name="uniSaalProfileId" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataVclTp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="atmTrafficDescriptorId" minOccurs="0"/>
+ <xs:element name="externalVci" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataVpcTp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="alarmReport" minOccurs="0"/>
+ <xs:element name="continuityCheck" minOccurs="0"/>
+ <xs:element name="nomPmBlkSize" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="counterMode" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataVplTp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="atmTrafficDescriptor" minOccurs="0"/>
+ <xs:element name="externalVpi" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataIub" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="rbsId" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataNbapCommon" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="l2EstablishReqRetryT" minOccurs="0"/>
+ <xs:element name="activeUniSaalTpRef" minOccurs="0"/>
+ <xs:element name="standbyUniSaalTpRef" minOccurs="0"/>
+ <xs:element name="auditRetransmissionT" minOccurs="0"/>
+ <xs:element name="l2EstablishSupervisionT" minOccurs="0"/>
+ <xs:element name="l3EstablishSupervisionT" minOccurs="0"/>
+ <xs:element name="uniSaalTpRef1" minOccurs="0"/>
+ <xs:element name="uniSaalTpRef2" minOccurs="0"/>
+ <xs:element name="administrativeState" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataNbapDedicated" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="l2EstablishReqRetryT" minOccurs="0"/>
+ <xs:element name="activeUniSaalTpRef" minOccurs="0"/>
+ <xs:element name="standbyUniSaalTpRef" minOccurs="0"/>
+ <xs:element name="l2EstablishSupervisionT" minOccurs="0"/>
+ <xs:element name="uniSaalTpRef1" minOccurs="0"/>
+ <xs:element name="uniSaalTpRef2" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="administrativeState" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataNodeSynch" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="noOfSamples" minOccurs="0"/>
+ <xs:element name="supervisionIntervalT" minOccurs="0"/>
+ <xs:element name="phaseDiffThreshold" minOccurs="0"/>
+ <xs:element name="phaseMeasurement" minOccurs="0"/>
+ <xs:element name="accuracy" minOccurs="0"/>
+ <xs:element name="timeStamp" minOccurs="0"/>
+ <xs:element name="sampleIntervalInt" minOccurs="0"/>
+ <xs:element name="fixedWindowSizeInt" minOccurs="0"/>
+ <xs:element name="sampleIntervalSup" minOccurs="0"/>
+ <xs:element name="fixedWindowSizeSup" minOccurs="0"/>
+ <xs:element name="slidingWindowSize" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataNodeSynchTp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="nodeSynchRef" minOccurs="0"/>
+ <xs:element name="aal0TpRef1" minOccurs="0"/>
+ <xs:element name="aal0TpRef2" minOccurs="0"/>
+ <xs:element name="aal0TpRef3" minOccurs="0"/>
+ <xs:element name="aal0TpRef4" minOccurs="0"/>
+ <xs:element name="timDeviceRef" minOccurs="0"/>
+ <xs:element name="aal0TpRefs" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="administrativeState" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataAal2QosCodePointProfile" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="qualityOfServiceCodePointA" minOccurs="0"/>
+ <xs:element name="qualityOfServiceCodePointB" minOccurs="0"/>
+ <xs:element name="qualityOfServiceCodePointC" minOccurs="0"/>
+ <xs:element name="qualityOfServiceCodePointD" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataAal2QosProfile" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="profileClassA" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="boundOnProbOfDelay" minOccurs="0"/>
+ <xs:element name="boundOnProbOfLoss" minOccurs="0"/>
+ <xs:element name="boundOnNodeDelay" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="profileClassB" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="boundOnProbOfDelay" minOccurs="0"/>
+ <xs:element name="boundOnProbOfLoss" minOccurs="0"/>
+ <xs:element name="boundOnNodeDelay" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="profileClassC" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="boundOnProbOfDelay" minOccurs="0"/>
+ <xs:element name="boundOnProbOfLoss" minOccurs="0"/>
+ <xs:element name="boundOnNodeDelay" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="profileClassD" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="boundOnProbOfDelay" minOccurs="0"/>
+ <xs:element name="boundOnProbOfLoss" minOccurs="0"/>
+ <xs:element name="boundOnNodeDelay" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataMtp3bAp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="routeSetId" minOccurs="0"/>
+ <xs:element name="serviceInd" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataMtp3bSlItu" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="autoStartLink" minOccurs="0"/>
+ <xs:element name="linkCongestLevel" minOccurs="0"/>
+ <xs:element name="linkState" minOccurs="0"/>
+ <xs:element name="prioBeforeSio" minOccurs="0"/>
+ <xs:element name="signLinkCode" minOccurs="0"/>
+ <xs:element name="tpId" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="deactivate" minOccurs="0"/>
+ <xs:element name="activate" minOccurs="0"/>
+ <xs:element name="emergencyActivate" minOccurs="0"/>
+ <xs:element name="localInhibit" minOccurs="0"/>
+ <xs:element name="localUninhibit" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataMtp3bSls" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="cLinkAnsi" minOccurs="0"/>
+ <xs:element name="mtp3bSrsId" minOccurs="0"/>
+ <xs:element name="periodicLinkTestFlag" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="deactivateLinkSet" minOccurs="0"/>
+ <xs:element name="activateLinkSet" minOccurs="0"/>
+ <xs:element name="emergencyActivateLinkSet" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataMtp3bSlTtc" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="autoStartLink" minOccurs="0"/>
+ <xs:element name="linkCongestLevel" minOccurs="0"/>
+ <xs:element name="linkState" minOccurs="0"/>
+ <xs:element name="signLinkCode" minOccurs="0"/>
+ <xs:element name="tpId" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="prioBeforeSio" minOccurs="0"/>
+ <xs:element name="deactivate" minOccurs="0"/>
+ <xs:element name="activate" minOccurs="0"/>
+ <xs:element name="emergencyActivate" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataMtp3bSpItu" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="m3uaNoOfAttempsOfDauds" minOccurs="0"/>
+ <xs:element name="sendSltmBefLink" minOccurs="0"/>
+ <xs:element name="signallingPointCode" minOccurs="0"/>
+ <xs:element name="maxSizeChangeBuf" minOccurs="0"/>
+ <xs:element name="maxSizeReroutBuf" minOccurs="0"/>
+ <xs:element name="sioSpare" minOccurs="0"/>
+ <xs:element name="spPriority" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="prioCb" minOccurs="0"/>
+ <xs:element name="prioCo" minOccurs="0"/>
+ <xs:element name="prioEc" minOccurs="0"/>
+ <xs:element name="prioLink" minOccurs="0"/>
+ <xs:element name="prioRst" minOccurs="0"/>
+ <xs:element name="prioSlt" minOccurs="0"/>
+ <xs:element name="prioTfc" minOccurs="0"/>
+ <xs:element name="prioTra" minOccurs="0"/>
+ <xs:element name="prioUpu" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="networkInd" minOccurs="0"/>
+ <xs:element name="transFrHandler" minOccurs="0"/>
+ <xs:element name="nodeBehaviour" minOccurs="0"/>
+ <xs:element name="spTimer" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="timerT1" minOccurs="0"/>
+ <xs:element name="timerT2" minOccurs="0"/>
+ <xs:element name="timerT3" minOccurs="0"/>
+ <xs:element name="timerTBsnt" minOccurs="0"/>
+ <xs:element name="timerT4" minOccurs="0"/>
+ <xs:element name="timerT5" minOccurs="0"/>
+ <xs:element name="timerTRetrieval" minOccurs="0"/>
+ <xs:element name="timerT6" minOccurs="0"/>
+ <xs:element name="timerT8" minOccurs="0"/>
+ <xs:element name="timerT10" minOccurs="0"/>
+ <xs:element name="timerT12" minOccurs="0"/>
+ <xs:element name="timerT13" minOccurs="0"/>
+ <xs:element name="timerT14" minOccurs="0"/>
+ <xs:element name="timerTStart" minOccurs="0"/>
+ <xs:element name="timerT17" minOccurs="0"/>
+ <xs:element name="timerT18" minOccurs="0"/>
+ <xs:element name="timerT19" minOccurs="0"/>
+ <xs:element name="timerSltm" minOccurs="0"/>
+ <xs:element name="timerSlta" minOccurs="0"/>
+ <xs:element name="timerT20" minOccurs="0"/>
+ <xs:element name="timerT21" minOccurs="0"/>
+ <xs:element name="timerT22" minOccurs="0"/>
+ <xs:element name="timerT23" minOccurs="0"/>
+ <xs:element name="timerTc" minOccurs="0"/>
+ <xs:element name="timerM3uaTack" minOccurs="0"/>
+ <xs:element name="timerM3uaPeriodicAudit" minOccurs="0"/>
+ <xs:element name="timerM3uaT1" minOccurs="0"/>
+ <xs:element name="timerM3uaT3" minOccurs="0"/>
+ <xs:element name="timerM3uaT42" minOccurs="0"/>
+ <xs:element name="timerT15" minOccurs="0"/>
+ <xs:element name="timerM3uaT6" minOccurs="0"/>
+ <xs:element name="timerM3uaT41" minOccurs="0"/>
+ <xs:element name="timerM3uaTc" minOccurs="0"/>
+ <xs:element name="timerM3uaT8" minOccurs="0"/>
+ <xs:element name="timerM3uaT40" minOccurs="0"/>
+ <xs:element name="timerT16" minOccurs="0"/>
+ <xs:element name="timerTDlack" minOccurs="0"/>
+ <xs:element name="timerM3uaTassocack" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="noOfAttempsOfAssociationEstablishment" minOccurs="0"/>
+ <xs:element name="resendTfcInterval" minOccurs="0"/>
+ <xs:element name="statusIndInterval" minOccurs="0"/>
+ <xs:element name="testPatternSltm" minOccurs="0"/>
+ <xs:element name="version" minOccurs="0"/>
+ <xs:element name="noOfCongestLevelForNI" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="routeSetCongestTestFlag" minOccurs="0"/>
+ <xs:element name="rpuId" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataMtp3bSpTtc" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="maxSizeChangeBuf" minOccurs="0"/>
+ <xs:element name="maxSizeReroutBuf" minOccurs="0"/>
+ <xs:element name="signallingPointCode" minOccurs="0"/>
+ <xs:element name="spPriority" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="prioCo" minOccurs="0"/>
+ <xs:element name="prioCb" minOccurs="0"/>
+ <xs:element name="prioEc" minOccurs="0"/>
+ <xs:element name="prioRst" minOccurs="0"/>
+ <xs:element name="prioTfa" minOccurs="0"/>
+ <xs:element name="prioRt" minOccurs="0"/>
+ <xs:element name="prioTfc" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="networkInd" minOccurs="0"/>
+ <xs:element name="spTimer" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="timerT1" minOccurs="0"/>
+ <xs:element name="timerT2" minOccurs="0"/>
+ <xs:element name="timerT3" minOccurs="0"/>
+ <xs:element name="timerT4" minOccurs="0"/>
+ <xs:element name="timerT6" minOccurs="0"/>
+ <xs:element name="timerT8" minOccurs="0"/>
+ <xs:element name="timerT10" minOccurs="0"/>
+ <xs:element name="timerT17" minOccurs="0"/>
+ <xs:element name="timerSrt" minOccurs="0"/>
+ <xs:element name="timerTBsnt" minOccurs="0"/>
+ <xs:element name="timerTRetrieval" minOccurs="0"/>
+ <xs:element name="timerTStart" minOccurs="0"/>
+ <xs:element name="timerTc" minOccurs="0"/>
+ <xs:element name="timerT15" minOccurs="0"/>
+ <xs:element name="timerT16" minOccurs="0"/>
+ <xs:element name="timerTDlack" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="statusIndInterval" minOccurs="0"/>
+ <xs:element name="nodeBehaviour" minOccurs="0"/>
+ <xs:element name="noOfCongestLevelForNI" minOccurs="0"/>
+ <xs:element name="testPatternSltm" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="resendTfcInterval" minOccurs="0"/>
+ <xs:element name="routeSetCongestTestFlag" minOccurs="0"/>
+ <xs:element name="rpuId" minOccurs="0"/>
+ <xs:element name="m3uaNoOfAttempsOfDauds" minOccurs="0"/>
+ <xs:element name="noOfAttempsOfAssociationEstablishment" minOccurs="0"/>
+ <xs:element name="spTimerM3ua" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="timerM3uaPeriodicAudit" minOccurs="0"/>
+ <xs:element name="timerM3uaT1" minOccurs="0"/>
+ <xs:element name="timerM3uaT3" minOccurs="0"/>
+ <xs:element name="timerM3uaT40" minOccurs="0"/>
+ <xs:element name="timerM3uaT41" minOccurs="0"/>
+ <xs:element name="timerM3uaT42" minOccurs="0"/>
+ <xs:element name="timerM3uaT6" minOccurs="0"/>
+ <xs:element name="timerM3uaT8" minOccurs="0"/>
+ <xs:element name="timerM3uaTack" minOccurs="0"/>
+ <xs:element name="timerM3uaTassocack" minOccurs="0"/>
+ <xs:element name="timerM3uaTc" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataMtp3bSr" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="linkSetM3uId" minOccurs="0"/>
+ <xs:element name="priority" minOccurs="0"/>
+ <xs:element name="routeType" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="linkSetId" minOccurs="0"/>
+ <xs:element name="blockSignalingRoute" minOccurs="0"/>
+ <xs:element name="deBlockSignalingRoute" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataMtp3bSrs" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="autoReroute" minOccurs="0"/>
+ <xs:element name="destPointCode" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataNniSaalProfile" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="profileData" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="congestionLevel1Abatement" minOccurs="0"/>
+ <xs:element name="maxStat" minOccurs="0"/>
+ <xs:element name="timerPoll" minOccurs="0"/>
+ <xs:element name="timerRepeatSrec" minOccurs="0"/>
+ <xs:element name="mps" minOccurs="0"/>
+ <xs:element name="congestionLevel1OnSet" minOccurs="0"/>
+ <xs:element name="congestionLevel2OnSet" minOccurs="0"/>
+ <xs:element name="nrOfPDUsDuringProving" minOccurs="0"/>
+ <xs:element name="timerT1" minOccurs="0"/>
+ <xs:element name="timerT2" minOccurs="0"/>
+ <xs:element name="timerT3" minOccurs="0"/>
+ <xs:element name="timerCC" minOccurs="0"/>
+ <xs:element name="congestionLevel3OnSet" minOccurs="0"/>
+ <xs:element name="initialCredit" minOccurs="0"/>
+ <xs:element name="timerIdle" minOccurs="0"/>
+ <xs:element name="timerKeepAlive" minOccurs="0"/>
+ <xs:element name="maxCC" minOccurs="0"/>
+ <xs:element name="maxNRP" minOccurs="0"/>
+ <xs:element name="timerNoCredit" minOccurs="0"/>
+ <xs:element name="maxPD" minOccurs="0"/>
+ <xs:element name="timerNoResponse" minOccurs="0"/>
+ <xs:element name="congestionLevel2Abatement" minOccurs="0"/>
+ <xs:element name="congestionLevel3Abatement" minOccurs="0"/>
+ <xs:element name="discardMessagesLevel1" minOccurs="0"/>
+ <xs:element name="discardMessagesLevel2" minOccurs="0"/>
+ <xs:element name="discardMessagesLevel3" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataNniSaalTp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="aal5TpVccTpId" minOccurs="0"/>
+ <xs:element name="maxSduSize" minOccurs="0"/>
+ <xs:element name="nniSaalProfileId" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataSccpApLocal" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="maxConn" minOccurs="0"/>
+ <xs:element name="ssN" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="useS1" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataSccpApRemote" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="mtp3bApId" minOccurs="0"/>
+ <xs:element name="ssN" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataSccpEntitySet" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="routeIds" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="newSubSystemNumber" minOccurs="0"/>
+ <xs:element name="sharingMode" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="newGlobalTitle" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="indicator" minOccurs="0"/>
+ <xs:element name="natureOfAddress" minOccurs="0"/>
+ <xs:element name="numberingPlan" minOccurs="0"/>
+ <xs:element name="translationType" minOccurs="0"/>
+ <xs:element name="addressInformation" minOccurs="0"/>
+ <xs:element name="encodingScheme" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataSccpGlobalTitle" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="addressInformation" minOccurs="0"/>
+ <xs:element name="encodingScheme" minOccurs="0"/>
+ <xs:element name="gtIndicator" minOccurs="0"/>
+ <xs:element name="natureOfAddress" minOccurs="0"/>
+ <xs:element name="numberingPlan" minOccurs="0"/>
+ <xs:element name="sccpEntitySetId" minOccurs="0"/>
+ <xs:element name="translationType" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataSccpScrc" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataSccpSp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="accountDateFileOutput" minOccurs="0"/>
+ <xs:element name="accountPeriodFileOutput" minOccurs="0"/>
+ <xs:element name="accountTimeFileOutput" minOccurs="0"/>
+ <xs:element name="hopCounterSclc" minOccurs="0"/>
+ <xs:element name="hopCounterScoc" minOccurs="0"/>
+ <xs:element name="lowerConnThres" minOccurs="0"/>
+ <xs:element name="maxRelayedConn" minOccurs="0"/>
+ <xs:element name="mtp3bSpId" minOccurs="0"/>
+ <xs:element name="prioGeneral" minOccurs="0"/>
+ <xs:element name="prioIT" minOccurs="0"/>
+ <xs:element name="prioRLSD" minOccurs="0"/>
+ <xs:element name="prioSST" minOccurs="0"/>
+ <xs:element name="smiValue" minOccurs="0"/>
+ <xs:element name="swapUDTPointer" minOccurs="0"/>
+ <xs:element name="tCong" minOccurs="0"/>
+ <xs:element name="tGuard" minOccurs="0"/>
+ <xs:element name="tIar" minOccurs="0"/>
+ <xs:element name="tIas" minOccurs="0"/>
+ <xs:element name="tReass" minOccurs="0"/>
+ <xs:element name="tRel" minOccurs="0"/>
+ <xs:element name="tStatInfo" minOccurs="0"/>
+ <xs:element name="tconnEst" minOccurs="0"/>
+ <xs:element name="tconnResp" minOccurs="0"/>
+ <xs:element name="upperConnThres" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="useSCMG" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="sendSST" minOccurs="0"/>
+ <xs:element name="sendSSA" minOccurs="0"/>
+ <xs:element name="sendSSP" minOccurs="0"/>
+ <xs:element name="useSST" minOccurs="0"/>
+ <xs:element name="allowRemoteBroadcast" minOccurs="0"/>
+ <xs:element name="initiateTimerTcon" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataRnsap" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="preferredAddressing" minOccurs="0"/>
+ <xs:element name="sccpDisabledT" minOccurs="0"/>
+ <xs:element name="userOutOfServiceT" minOccurs="0"/>
+ <xs:element name="localSccpApRef" minOccurs="0"/>
+ <xs:element name="sccpGlobalTitleRef" minOccurs="0"/>
+ <xs:element name="remoteSccpApRef" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataMtp3bSlChina" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="autoStartLink" minOccurs="0"/>
+ <xs:element name="linkCongestLevel" minOccurs="0"/>
+ <xs:element name="linkState" minOccurs="0"/>
+ <xs:element name="prioBeforeSio" minOccurs="0"/>
+ <xs:element name="signLinkCode" minOccurs="0"/>
+ <xs:element name="tpId" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="deactivate" minOccurs="0"/>
+ <xs:element name="activate" minOccurs="0"/>
+ <xs:element name="emergencyActivate" minOccurs="0"/>
+ <xs:element name="localInhibit" minOccurs="0"/>
+ <xs:element name="localUninhibit" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataMtp3bSpChina" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="m3uaNoOfAttempsOfDauds" minOccurs="0"/>
+ <xs:element name="routeSetCongestTestFlag" minOccurs="0"/>
+ <xs:element name="maxSizeChangeBuf" minOccurs="0"/>
+ <xs:element name="rpuId" minOccurs="0"/>
+ <xs:element name="sendSltmBefLink" minOccurs="0"/>
+ <xs:element name="maxSizeReroutBuf" minOccurs="0"/>
+ <xs:element name="networkInd" minOccurs="0"/>
+ <xs:element name="signallingPointCode" minOccurs="0"/>
+ <xs:element name="sioSpare" minOccurs="0"/>
+ <xs:element name="nodeBehaviour" minOccurs="0"/>
+ <xs:element name="noOfAttempsOfAssociationEstablishment" minOccurs="0"/>
+ <xs:element name="spPriority" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="prioCb" minOccurs="0"/>
+ <xs:element name="prioCo" minOccurs="0"/>
+ <xs:element name="prioEc" minOccurs="0"/>
+ <xs:element name="prioLink" minOccurs="0"/>
+ <xs:element name="prioRst" minOccurs="0"/>
+ <xs:element name="prioSlt" minOccurs="0"/>
+ <xs:element name="prioTfc" minOccurs="0"/>
+ <xs:element name="prioTra" minOccurs="0"/>
+ <xs:element name="prioUpu" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="statusIndInterval" minOccurs="0"/>
+ <xs:element name="noOfCongestLevelForNI" minOccurs="0"/>
+ <xs:element name="resendTfcInterval" minOccurs="0"/>
+ <xs:element name="testPatternSltm" minOccurs="0"/>
+ <xs:element name="transFrHandler" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="version" minOccurs="0"/>
+ <xs:element name="spTimer" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="timerM3uaPeriodicAudit" minOccurs="0"/>
+ <xs:element name="timerM3uaT1" minOccurs="0"/>
+ <xs:element name="timerM3uaT3" minOccurs="0"/>
+ <xs:element name="timerM3uaT40" minOccurs="0"/>
+ <xs:element name="timerM3uaT41" minOccurs="0"/>
+ <xs:element name="timerM3uaT42" minOccurs="0"/>
+ <xs:element name="timerM3uaT6" minOccurs="0"/>
+ <xs:element name="timerM3uaT8" minOccurs="0"/>
+ <xs:element name="timerM3uaTack" minOccurs="0"/>
+ <xs:element name="timerM3uaTassocack" minOccurs="0"/>
+ <xs:element name="timerM3uaTc" minOccurs="0"/>
+ <xs:element name="timerSlta" minOccurs="0"/>
+ <xs:element name="timerSltm" minOccurs="0"/>
+ <xs:element name="timerT1" minOccurs="0"/>
+ <xs:element name="timerT10" minOccurs="0"/>
+ <xs:element name="timerT12" minOccurs="0"/>
+ <xs:element name="timerT13" minOccurs="0"/>
+ <xs:element name="timerT14" minOccurs="0"/>
+ <xs:element name="timerT15" minOccurs="0"/>
+ <xs:element name="timerT16" minOccurs="0"/>
+ <xs:element name="timerT17" minOccurs="0"/>
+ <xs:element name="timerT18" minOccurs="0"/>
+ <xs:element name="timerT19" minOccurs="0"/>
+ <xs:element name="timerT2" minOccurs="0"/>
+ <xs:element name="timerT20" minOccurs="0"/>
+ <xs:element name="timerT21" minOccurs="0"/>
+ <xs:element name="timerT22" minOccurs="0"/>
+ <xs:element name="timerT23" minOccurs="0"/>
+ <xs:element name="timerT3" minOccurs="0"/>
+ <xs:element name="timerT4" minOccurs="0"/>
+ <xs:element name="timerT5" minOccurs="0"/>
+ <xs:element name="timerT6" minOccurs="0"/>
+ <xs:element name="timerT8" minOccurs="0"/>
+ <xs:element name="timerTBsnt" minOccurs="0"/>
+ <xs:element name="timerTDlack" minOccurs="0"/>
+ <xs:element name="timerTRetrieval" minOccurs="0"/>
+ <xs:element name="timerTStart" minOccurs="0"/>
+ <xs:element name="timerTc" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataRanap" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="preferredAddressing" minOccurs="0"/>
+ <xs:element name="sccpDisabledT" minOccurs="0"/>
+ <xs:element name="cnDomainInd" minOccurs="0"/>
+ <xs:element name="noOfResetSendings" minOccurs="0"/>
+ <xs:element name="userOutOfServiceT" minOccurs="0"/>
+ <xs:element name="localSccpApRef" minOccurs="0"/>
+ <xs:element name="sccpGlobalTitleRef" minOccurs="0"/>
+ <xs:element name="remoteSccpApRef" minOccurs="0"/>
+ <xs:element name="resetResendT" minOccurs="0"/>
+ <xs:element name="resetAckGuardT" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="cnId" minOccurs="0"/>
+ <xs:element name="cnPlmnIdentity" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="mcc" minOccurs="0"/>
+ <xs:element name="mnc" minOccurs="0"/>
+ <xs:element name="mncLength" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="networkResourceIdentifier" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="relativeCapacity" minOccurs="0"/>
+ <xs:element name="packetDataRouterRef" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="cnOperatorRef" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataMtp3bSlAnsi" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="autoStartLink" minOccurs="0"/>
+ <xs:element name="linkCongestLevel" minOccurs="0"/>
+ <xs:element name="linkState" minOccurs="0"/>
+ <xs:element name="signLinkCode" minOccurs="0"/>
+ <xs:element name="tpId" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="deactivate" minOccurs="0"/>
+ <xs:element name="activate" minOccurs="0"/>
+ <xs:element name="emergencyActivate" minOccurs="0"/>
+ <xs:element name="localInhibit" minOccurs="0"/>
+ <xs:element name="localUninhibit" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataMtp3bSpAnsi" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="m3uaNoOfAttempsOfDauds" minOccurs="0"/>
+ <xs:element name="maxSizeChangeBuf" minOccurs="0"/>
+ <xs:element name="maxSizeReroutBuf" minOccurs="0"/>
+ <xs:element name="networkInd" minOccurs="0"/>
+ <xs:element name="noOfAttempsOfAssociationEstablishment" minOccurs="0"/>
+ <xs:element name="noOfCongestLevelForNI" minOccurs="0"/>
+ <xs:element name="nodeBehaviour" minOccurs="0"/>
+ <xs:element name="resendTfcInterval" minOccurs="0"/>
+ <xs:element name="routeSetCongestTestFlag" minOccurs="0"/>
+ <xs:element name="rpuId" minOccurs="0"/>
+ <xs:element name="sendSltmBefLink" minOccurs="0"/>
+ <xs:element name="signallingPointCode" minOccurs="0"/>
+ <xs:element name="statusIndInterval" minOccurs="0"/>
+ <xs:element name="sioSpare" minOccurs="0"/>
+ <xs:element name="testPatternSltm" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="spPriority" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="prioCb" minOccurs="0"/>
+ <xs:element name="prioCo" minOccurs="0"/>
+ <xs:element name="prioEc" minOccurs="0"/>
+ <xs:element name="prioLink" minOccurs="0"/>
+ <xs:element name="prioRst" minOccurs="0"/>
+ <xs:element name="prioSlt" minOccurs="0"/>
+ <xs:element name="prioTfc" minOccurs="0"/>
+ <xs:element name="prioTra" minOccurs="0"/>
+ <xs:element name="prioUpu" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="spTimer" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="timerM3uaPeriodicAudit" minOccurs="0"/>
+ <xs:element name="timerM3uaT1" minOccurs="0"/>
+ <xs:element name="timerM3uaT3" minOccurs="0"/>
+ <xs:element name="timerM3uaT40" minOccurs="0"/>
+ <xs:element name="timerM3uaT41" minOccurs="0"/>
+ <xs:element name="timerM3uaT42" minOccurs="0"/>
+ <xs:element name="timerM3uaT6" minOccurs="0"/>
+ <xs:element name="timerM3uaT8" minOccurs="0"/>
+ <xs:element name="timerM3uaTack" minOccurs="0"/>
+ <xs:element name="timerM3uaTassocack" minOccurs="0"/>
+ <xs:element name="timerM3uaTc" minOccurs="0"/>
+ <xs:element name="timerSlta" minOccurs="0"/>
+ <xs:element name="timerSltm" minOccurs="0"/>
+ <xs:element name="timerT1" minOccurs="0"/>
+ <xs:element name="timerT10" minOccurs="0"/>
+ <xs:element name="timerT12" minOccurs="0"/>
+ <xs:element name="timerT13" minOccurs="0"/>
+ <xs:element name="timerT14" minOccurs="0"/>
+ <xs:element name="timerT15" minOccurs="0"/>
+ <xs:element name="timerT16" minOccurs="0"/>
+ <xs:element name="timerT17" minOccurs="0"/>
+ <xs:element name="timerT2" minOccurs="0"/>
+ <xs:element name="timerT20" minOccurs="0"/>
+ <xs:element name="timerT21" minOccurs="0"/>
+ <xs:element name="timerT22" minOccurs="0"/>
+ <xs:element name="timerT23" minOccurs="0"/>
+ <xs:element name="timerT25" minOccurs="0"/>
+ <xs:element name="timerT26" minOccurs="0"/>
+ <xs:element name="timerT27" minOccurs="0"/>
+ <xs:element name="timerT28" minOccurs="0"/>
+ <xs:element name="timerT29" minOccurs="0"/>
+ <xs:element name="timerT3" minOccurs="0"/>
+ <xs:element name="timerT30" minOccurs="0"/>
+ <xs:element name="timerT31" minOccurs="0"/>
+ <xs:element name="timerT4" minOccurs="0"/>
+ <xs:element name="timerT5" minOccurs="0"/>
+ <xs:element name="timerT6" minOccurs="0"/>
+ <xs:element name="timerT8" minOccurs="0"/>
+ <xs:element name="timerTBsnt" minOccurs="0"/>
+ <xs:element name="timerTDlack" minOccurs="0"/>
+ <xs:element name="timerTRetrieval" minOccurs="0"/>
+ <xs:element name="timerTStart" minOccurs="0"/>
+ <xs:element name="timerTc" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="transFrHandler" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataPacketDataRouter" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="rncIpAddress" minOccurs="0"/>
+ <xs:element name="cnIuLinkIpAddress" minOccurs="0"/>
+ <xs:element name="timeToLive" minOccurs="0"/>
+ <xs:element name="pdrDeviceRef" minOccurs="0"/>
+ <xs:element name="aal5TpRef" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="administrativeState" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataIpAtmLink" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="interfaceName" minOccurs="0"/>
+ <xs:element name="ipAddress" minOccurs="0"/>
+ <xs:element name="metric" minOccurs="0"/>
+ <xs:element name="monitor" minOccurs="0"/>
+ <xs:element name="monitorInterval" minOccurs="0"/>
+ <xs:element name="monitorRetries" minOccurs="0"/>
+ <xs:element name="mtuSize" minOccurs="0"/>
+ <xs:element name="subnetMask" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="Aal5TpVccTpIdList" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="aal5TpVccTpSelectionMode" minOccurs="0"/>
+ <xs:element name="aal5TpVccTpId" minOccurs="0"/>
+ <xs:element name="assignIpAddress" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ipAddress" minOccurs="0"/>
+ <xs:element name="subnetMask" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataIpRoutingTable" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="indexOfDeletableStaticRoutes" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="addStaticRoute" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ipAddress" minOccurs="0"/>
+ <xs:element name="subnetMask" minOccurs="0"/>
+ <xs:element name="hopIpAddress" minOccurs="0"/>
+ <xs:element name="routeMetric" minOccurs="0"/>
+ <xs:element name="redistribute" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="deleteStaticRoute" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="routingTableEntry" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="active" minOccurs="0"/>
+ <xs:element name="destinationIpAddr" minOccurs="0"/>
+ <xs:element name="destinationNetworkMask" minOccurs="0"/>
+ <xs:element name="interfaceName" minOccurs="0"/>
+ <xs:element name="nextHopIpAddr" minOccurs="0"/>
+ <xs:element name="redistribute" minOccurs="0"/>
+ <xs:element name="routeMetric" minOccurs="0"/>
+ <xs:element name="routeType" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataIp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="dnsServer" minOccurs="0"/>
+ <xs:element name="isRecursiveSearch" minOccurs="0"/>
+ <xs:element name="isSubDomainName" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="retransInterval" minOccurs="0"/>
+ <xs:element name="noOfRetrans" minOccurs="0"/>
+ <xs:element name="isDefDomainName" minOccurs="0"/>
+ <xs:element name="defDomainName" minOccurs="0"/>
+ <xs:element name="useHostFile" minOccurs="0"/>
+ <xs:element name="dscp" minOccurs="0"/>
+ <xs:element name="icmpRedirect" minOccurs="0"/>
+ <xs:element name="udpChecksumState" minOccurs="0"/>
+ <xs:element name="connectionAttemptTimer" minOccurs="0"/>
+ <xs:element name="maxRetransmissionAttempts" minOccurs="0"/>
+ <xs:element name="workingMode" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataIpSystem" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataIpOam" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataOspf" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="ipMo" minOccurs="0"/>
+ <xs:element name="ospfASBdrRtrStatus" minOccurs="0"/>
+ <xs:element name="ospfAreaBdrRtrStatus" minOccurs="0"/>
+ <xs:element name="ospfRouterId" minOccurs="0"/>
+ <xs:element name="recoverTopoDb" minOccurs="0"/>
+ <xs:element name="topoDbStoreInterv" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="administrativeState" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataOspfArea" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="areaId" minOccurs="0"/>
+ <xs:element name="areaLsaChecksum" minOccurs="0"/>
+ <xs:element name="importExternalLsa" minOccurs="0"/>
+ <xs:element name="sendAreaSummary" minOccurs="0"/>
+ <xs:element name="stubArea" minOccurs="0"/>
+ <xs:element name="stubAreaMetric" minOccurs="0"/>
+ <xs:element name="stubAreaMetricType" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="range0" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ipAddress" minOccurs="0"/>
+ <xs:element name="subnetMask" minOccurs="0"/>
+ <xs:element name="advertise" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="range1" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ipAddress" minOccurs="0"/>
+ <xs:element name="subnetMask" minOccurs="0"/>
+ <xs:element name="advertise" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="range2" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ipAddress" minOccurs="0"/>
+ <xs:element name="subnetMask" minOccurs="0"/>
+ <xs:element name="advertise" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="addAreaRange" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="rangeIndex" minOccurs="0"/>
+ <xs:element name="range" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ipAddress" minOccurs="0"/>
+ <xs:element name="subnetMask" minOccurs="0"/>
+ <xs:element name="advertise" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="deleteAreaRange" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="rangeIndex" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataOspfInterface" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="helloInterval" minOccurs="0"/>
+ <xs:element name="interfacePriority" minOccurs="0"/>
+ <xs:element name="interfaceTransitDelay" minOccurs="0"/>
+ <xs:element name="lsaTransmissionInterval" minOccurs="0"/>
+ <xs:element name="ospfAreaRelated" minOccurs="0"/>
+ <xs:element name="relatedLink" minOccurs="0"/>
+ <xs:element name="routerDeadInterval" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataRncModule" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataTnApplication" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData"/>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataVirtualPath" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="vplTpARef" minOccurs="0"/>
+ <xs:element name="vplTpBRef" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataM3uAssociation" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="mtp3bSrsId" minOccurs="0"/>
+ <xs:element name="sctpId" minOccurs="0"/>
+ <xs:element name="dscp" minOccurs="0"/>
+ <xs:element name="associationState" minOccurs="0"/>
+ <xs:element name="localIpMask" minOccurs="0"/>
+ <xs:element name="autoStartAssociation" minOccurs="0"/>
+ <xs:element name="remotePortNumber" minOccurs="0"/>
+ <xs:element name="remoteIpAddress1" minOccurs="0"/>
+ <xs:element name="remoteIpAddress2" minOccurs="0"/>
+ <xs:element name="localPortNumber" minOccurs="0"/>
+ <xs:element name="role" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataSccpAccountingCriteria" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="usageType" minOccurs="0"/>
+ <xs:element name="ssN" minOccurs="0"/>
+ <xs:element name="countType" minOccurs="0"/>
+ <xs:element name="globalTitleId" minOccurs="0"/>
+ <xs:element name="pointerId" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataSccpPolicing" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="originatingMtp3bSpc" minOccurs="0"/>
+ <xs:element name="destinationMtp3bSpc" minOccurs="0"/>
+ <xs:element name="originatingSccpSpId" minOccurs="0"/>
+ <xs:element name="originatingSccpSsn" minOccurs="0"/>
+ <xs:element name="destinationSccpSpId" minOccurs="0"/>
+ <xs:element name="destinationSccpSsn" minOccurs="0"/>
+ <xs:element name="policingGlobalTitle" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="indicator" minOccurs="0"/>
+ <xs:element name="natureOfAddress" minOccurs="0"/>
+ <xs:element name="numberingPlan" minOccurs="0"/>
+ <xs:element name="translationType" minOccurs="0"/>
+ <xs:element name="addressInformation" minOccurs="0"/>
+ <xs:element name="encodingScheme" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="discardOrReturnServiceMsg" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataSctp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="numberOfAssociations" minOccurs="0"/>
+ <xs:element name="ipAccessHostGpbId" minOccurs="0"/>
+ <xs:element name="minimumRto" minOccurs="0"/>
+ <xs:element name="maximumRto" minOccurs="0"/>
+ <xs:element name="initialRto" minOccurs="0"/>
+ <xs:element name="rtoAlphaIndex" minOccurs="0"/>
+ <xs:element name="rtoBetaIndex" minOccurs="0"/>
+ <xs:element name="validCookieLife" minOccurs="0"/>
+ <xs:element name="allowedIncrementCookieLife" minOccurs="0"/>
+ <xs:element name="keyChangePeriod" minOccurs="0"/>
+ <xs:element name="associationMaxRtx" minOccurs="0"/>
+ <xs:element name="pathMaxRtx" minOccurs="0"/>
+ <xs:element name="maxInitialRtrAtt" minOccurs="0"/>
+ <xs:element name="maxShutDownRtrAtt" minOccurs="0"/>
+ <xs:element name="heartbeatInterval" minOccurs="0"/>
+ <xs:element name="heartbeatStatus" minOccurs="0"/>
+ <xs:element name="maxIncomingStream" minOccurs="0"/>
+ <xs:element name="maxOutgoingStream" minOccurs="0"/>
+ <xs:element name="maxUserDataSize" minOccurs="0"/>
+ <xs:element name="mBuffer" minOccurs="0"/>
+ <xs:element name="nThreshold" minOccurs="0"/>
+ <xs:element name="tSack" minOccurs="0"/>
+ <xs:element name="maxDataSizeIp" minOccurs="0"/>
+ <xs:element name="initialAdRecWin" minOccurs="0"/>
+ <xs:element name="intervalOobPkts" minOccurs="0"/>
+ <xs:element name="intervalLostUser" minOccurs="0"/>
+ <xs:element name="maxBurst" minOccurs="0"/>
+ <xs:element name="nPercentage" minOccurs="0"/>
+ <xs:element name="bundlingActivated" minOccurs="0"/>
+ <xs:element name="bundlingTimer" minOccurs="0"/>
+ <xs:element name="rpuId" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataEthernetLink" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="ipAddress" minOccurs="0"/>
+ <xs:element name="subnetMask" minOccurs="0"/>
+ <xs:element name="broadcastAddress" minOccurs="0"/>
+ <xs:element name="macAddress" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="mtuSize" minOccurs="0"/>
+ <xs:element name="metric" minOccurs="0"/>
+ <xs:element name="interfaceName" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="assignIpAddress" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ipAddress" minOccurs="0"/>
+ <xs:element name="subnetMask" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataImaGroup" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="physicalPortList" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="requiredNumberOfLinks" minOccurs="0"/>
+ <xs:element name="activeLinks" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataImaLink" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="uses" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataIpAccessHostGpb" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="administrativeState" minOccurs="0"/>
+ <xs:element name="generalProcessorUnitId" minOccurs="0"/>
+ <xs:element name="autoConfig" minOccurs="0"/>
+ <xs:element name="autoConfigIdentity" minOccurs="0"/>
+ <xs:element name="autoConfigIdentity2" minOccurs="0"/>
+ <xs:element name="ipAddress1" minOccurs="0"/>
+ <xs:element name="ipAddress2" minOccurs="0"/>
+ <xs:element name="ipDefaultTtl" minOccurs="0"/>
+ <xs:element name="ipReasmTimeout" minOccurs="0"/>
+ <xs:element name="interface1" minOccurs="0"/>
+ <xs:element name="interface2" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataIpAccessAutoConfig" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="networkPrefixLength" minOccurs="0"/>
+ <xs:element name="nrOfUnusedAdresses" minOccurs="0"/>
+ <xs:element name="totalNrOfAddresses" minOccurs="0"/>
+ <xs:element name="minIpAddress" minOccurs="0"/>
+ <xs:element name="maxIpAddress" minOccurs="0"/>
+ <xs:element name="subnet" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataIpInterface" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="vid" minOccurs="0"/>
+ <xs:element name="vLan" minOccurs="0"/>
+ <xs:element name="rps" minOccurs="0"/>
+ <xs:element name="mtu" minOccurs="0"/>
+ <xs:element name="networkPrefixLength" minOccurs="0"/>
+ <xs:element name="defaultRouter0" minOccurs="0"/>
+ <xs:element name="defaultRouter1" minOccurs="0"/>
+ <xs:element name="defaultRouter2" minOccurs="0"/>
+ <xs:element name="defaultRouterPingInterval" minOccurs="0"/>
+ <xs:element name="maxWaitForPingReply" minOccurs="0"/>
+ <xs:element name="maxNoOfFailedPings" minOccurs="0"/>
+ <xs:element name="noOfPingsBeforeOk" minOccurs="0"/>
+ <xs:element name="switchBackTimer" minOccurs="0"/>
+ <xs:element name="ownIpAddressActive" minOccurs="0"/>
+ <xs:element name="ownIpAddressPassive" minOccurs="0"/>
+ <xs:element name="subnet" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataIpAccessHostSpb" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="administrativeState" minOccurs="0"/>
+ <xs:element name="autoConfig" minOccurs="0"/>
+ <xs:element name="autoConfigIdentity" minOccurs="0"/>
+ <xs:element name="autoConfigIdentity2" minOccurs="0"/>
+ <xs:element name="interface2" minOccurs="0"/>
+ <xs:element name="spmId" minOccurs="0"/>
+ <xs:element name="ipAddress" minOccurs="0"/>
+ <xs:element name="ipAddress2" minOccurs="0"/>
+ <xs:element name="ipDefaultTtl" minOccurs="0"/>
+ <xs:element name="ipInterface" minOccurs="0"/>
+ <xs:element name="ipReasmTimeout" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataIpEthPacketDataRouter" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="administrativeState" minOccurs="0"/>
+ <xs:element name="pdrDeviceRef" minOccurs="0"/>
+ <xs:element name="ipAccessHostSpbRef" minOccurs="0"/>
+ <xs:element name="ipAddressSelection" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataSwManagement" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData"/>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataReliableProgramUniter" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataSpDevicePool" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData"/>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataPdrDevice" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataExchangeTerminal" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="description" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="aal2LayerDescription" minOccurs="0"/>
+ <xs:element name="atmLayerDescription" minOccurs="0"/>
+ <xs:element name="etType" minOccurs="0"/>
+ <xs:element name="physicalLayerDescription" minOccurs="0"/>
+ <xs:element name="tdmSupport" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataCbu" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataGeneralProcessorUnit" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataVc4Ttp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="pathTraceFormat" minOccurs="0"/>
+ <xs:element name="transmittedPathTrace" minOccurs="0"/>
+ <xs:element name="expectedPathTrace" minOccurs="0"/>
+ <xs:element name="timConsequentAction" minOccurs="0"/>
+ <xs:element name="vcDegThreshold" minOccurs="0"/>
+ <xs:element name="vcDegM" minOccurs="0"/>
+ <xs:element name="auAisReporting" minOccurs="0"/>
+ <xs:element name="vcRdiReporting" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataVc12Ttp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="transmittedPathTrace" minOccurs="0"/>
+ <xs:element name="expectedPathTrace" minOccurs="0"/>
+ <xs:element name="timConsequentAction" minOccurs="0"/>
+ <xs:element name="vcDegThreshold" minOccurs="0"/>
+ <xs:element name="vcDegM" minOccurs="0"/>
+ <xs:element name="tuAisReporting" minOccurs="0"/>
+ <xs:element name="vcRdiReporting" minOccurs="0"/>
+ <xs:element name="administrativeState" minOccurs="0"/>
+ <xs:element name="shutDownTimeout" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataE1Ttp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="degDegThr" minOccurs="0"/>
+ <xs:element name="degDegM" minOccurs="0"/>
+ <xs:element name="aisReporting" minOccurs="0"/>
+ <xs:element name="rdiReporting" minOccurs="0"/>
+ <xs:element name="crc4Mode" minOccurs="0"/>
+ <xs:element name="idlePattern" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataSts1SpeTtp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="aisPReporting" minOccurs="0"/>
+ <xs:element name="rdiPReporting" minOccurs="0"/>
+ <xs:element name="timConsequentAction" minOccurs="0"/>
+ <xs:element name="expectedPathTrace" minOccurs="0"/>
+ <xs:element name="transmittedPathTrace" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataVt15Ttp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="administrativeState" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="aisVreporting" minOccurs="0"/>
+ <xs:element name="rdiVreporting" minOccurs="0"/>
+ <xs:element name="shutDownTimer" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataSts3CspeTtp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="aisPReporting" minOccurs="0"/>
+ <xs:element name="rdiPReporting" minOccurs="0"/>
+ <xs:element name="timConsequentAction" minOccurs="0"/>
+ <xs:element name="expectedPathTrace" minOccurs="0"/>
+ <xs:element name="transmittedPathTrace" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataT1Ttp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="aisReporting" minOccurs="0"/>
+ <xs:element name="rdiReporting" minOccurs="0"/>
+ <xs:element name="idlePattern" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataIuLink" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="packetDataRouterRef" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataE1PhysPathTerm" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="administrativeState" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="lineNo" minOccurs="0"/>
+ <xs:element name="loopback" minOccurs="0"/>
+ <xs:element name="crc4Mode" minOccurs="0"/>
+ <xs:element name="idlePattern" minOccurs="0"/>
+ <xs:element name="degDegThr" minOccurs="0"/>
+ <xs:element name="degDegM" minOccurs="0"/>
+ <xs:element name="rdiReporting" minOccurs="0"/>
+ <xs:element name="aisReporting" minOccurs="0"/>
+ <xs:element name="shutDownTimeout" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataJ1PhysPathTerm" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="administrativeState" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="lineNo" minOccurs="0"/>
+ <xs:element name="loopback" minOccurs="0"/>
+ <xs:element name="idlePattern" minOccurs="0"/>
+ <xs:element name="physicalLineType" minOccurs="0"/>
+ <xs:element name="degThreshold" minOccurs="0"/>
+ <xs:element name="rdiReporting" minOccurs="0"/>
+ <xs:element name="aisReporting" minOccurs="0"/>
+ <xs:element name="shutDownTimeout" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataT1PhysPathTerm" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="administrativeState" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="lineNo" minOccurs="0"/>
+ <xs:element name="loopback" minOccurs="0"/>
+ <xs:element name="rdiReporting" minOccurs="0"/>
+ <xs:element name="aisReporting" minOccurs="0"/>
+ <xs:element name="shutDownTimeout" minOccurs="0"/>
+ <xs:element name="idlePattern" minOccurs="0"/>
+ <xs:element name="transmissionMode" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataDs0Bundle" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="listOfTimeSlots" minOccurs="0"/>
+ <xs:element name="tdmMode" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataT3PhysPathTerm" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="administrativeState" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="shutDownTimeout" minOccurs="0"/>
+ <xs:element name="lineNo" minOccurs="0"/>
+ <xs:element name="loopback" minOccurs="0"/>
+ <xs:element name="rdiReporting" minOccurs="0"/>
+ <xs:element name="aisReporting" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataE3PhysPathTerm" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="administrativeState" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="shutDownTimeout" minOccurs="0"/>
+ <xs:element name="lineNo" minOccurs="0"/>
+ <xs:element name="loopback" minOccurs="0"/>
+ <xs:element name="idlePattern" minOccurs="0"/>
+ <xs:element name="degDegThr" minOccurs="0"/>
+ <xs:element name="degDegM" minOccurs="0"/>
+ <xs:element name="rdiReporting" minOccurs="0"/>
+ <xs:element name="aisReporting" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataOs155SpiTtp" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="administrativeState" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="lineNo" minOccurs="0"/>
+ <xs:element name="standardMode" minOccurs="0"/>
+ <xs:element name="shutDownTimeout" minOccurs="0"/>
+ <xs:element name="muxMode" minOccurs="0"/>
+ <xs:element name="msDegThreshold" minOccurs="0"/>
+ <xs:element name="msDegM" minOccurs="0"/>
+ <xs:element name="msRdiReporting" minOccurs="0"/>
+ <xs:element name="msAisReporting" minOccurs="0"/>
+ <xs:element name="loopBack" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataEtMfg" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataGigaBitEthernet" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="administrativeState" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="dscpPbitMap" minOccurs="0"/>
+ <xs:element name="autoNegotiation" minOccurs="0"/>
+ <xs:element name="frameFormat" minOccurs="0"/>
+ <xs:element name="primaryLink" minOccurs="0"/>
+ <xs:element name="protectiveMode" minOccurs="0"/>
+ <xs:element name="msDegM" minOccurs="0"/>
+ <xs:element name="shutDownTimeout" minOccurs="0"/>
+ <xs:element name="statePropagationDelay" minOccurs="0"/>
+ <xs:element name="switchBackTimer" minOccurs="0"/>
+ <xs:element name="setDscpPbit" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="dscp" minOccurs="0"/>
+ <xs:element name="pbit" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataFastEthernet" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="administrativeState" minOccurs="0"/>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="defaultRouter" minOccurs="0"/>
+ <xs:element name="mtu" minOccurs="0"/>
+ <xs:element name="networkPrefixLength" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataMediumAccessUnit" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="connectorLabel" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vsDataMspg" substitutionGroup="xn:vsData">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="xn:vsData">
+ <xs:sequence>
+ <xs:element name="userLabel" minOccurs="0"/>
+ <xs:element name="degCauseMsp" minOccurs="0"/>
+ <xs:element name="os155SpiStandbyId" minOccurs="0"/>
+ <xs:element name="os155SpiWorkingId" minOccurs="0"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/ImportExportMap.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/ImportExportMap.xsd
new file mode 100644
index 0000000000..acbafd42e6
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/ImportExportMap.xsd
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- edited with XML Spy v4.1 U (http://www.xmlspy.com) by Graham Coster (Ericsson Expertise Ireland) -->
+<!--W3C Schema generated by XML Spy v4.1 U (http://www.xmlspy.com)-->
+<xs:schema xmlns="ImportExportMap.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="ImportExportMap.xsd" elementFormDefault="qualified">
+ <xs:element name="AttributeMap">
+ <xs:complexType>
+ <xs:attribute name="internalName" type="xs:string" use="required"/>
+ <xs:attribute name="externalName" type="xs:string" use="required"/>
+ <xs:attribute name="structAttributeType" type="xs:string" use="optional"/>
+ <xs:attribute name="mapRequired" type="xs:boolean" use="optional" default="false"/>
+ <xs:attribute name="restricted" type="xs:boolean" use="optional" default="false"/>
+ <xs:attribute name="actionUpdated" type="xs:boolean" use="optional" default="false"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ActionMap">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ActionAttribute" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="actionName" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ActionAttribute">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ChildMoTypes">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="MoType" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="FileMimMap">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="MoMap" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="fileType" type="xs:string" use="required"/>
+ <xs:attribute name="fileVersion" type="xs:string" use="required"/>
+ <xs:attribute name="ranosMOMType" type="xs:string" use="required"/>
+ <xs:attribute name="ranosMOMVersion" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="MoMap">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ValidCommands"/>
+ <xs:element ref="AttributeMap" maxOccurs="unbounded"/>
+ <xs:element ref="ActionMap" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element ref="ChildMoTypes" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="fileRoot" type="xs:boolean" use="required"/>
+ <xs:attribute name="externalType" type="xs:string" use="required"/>
+ <xs:attribute name="internalType" type="xs:string" use="required"/>
+ <xs:attribute name="nameSpace" type="xs:string" use="required"/>
+ <xs:attribute name="rt" type="xs:string" use="required"/>
+ <xs:attribute name="overrideFBKDelete" type="xs:boolean" use="optional" default="false"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="MoType">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="rt" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ValidCommands">
+ <xs:complexType>
+ <xs:attribute name="create" type="xs:boolean" use="required"/>
+ <xs:attribute name="update" type="xs:boolean" use="required"/>
+ <xs:attribute name="delete" type="xs:boolean" use="required"/>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/configData.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/configData.xsd
new file mode 100644
index 0000000000..f07e7c8d3d
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/configData.xsd
@@ -0,0 +1,41 @@
+<!--
+ 3GPP TS 32.615 v4.5 Bulk CM IRP
+ Configuration data file base XML schema
+ configData.xsd
+ -->
+<schema targetNamespace="configData.xsd" xmlns:bc="configData.xsd" xmlns:xn="genericNrm.xsd" xmlns:es="EricssonSpecificAttributes.5.1.xsd" xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
+ <!-- Configuration data file root XML element -->
+ <import namespace="genericNrm.xsd" schemaLocation="genericNrm.xsd"/>
+ <import namespace="EricssonSpecificAttributes.5.1.xsd" schemaLocation="EricssonSpecificAttributes.5.1.xsd"/>
+ <element name="bulkCmConfigDataFile">
+ <complexType>
+ <sequence>
+ <element name="fileHeader">
+ <complexType>
+ <attribute name="fileFormatVersion" type="string" use="required"/>
+ <attribute name="senderName" type="string" use="optional"/>
+ <attribute name="vendorName" type="string" use="optional"/>
+ </complexType>
+ </element>
+ <element name="configData" maxOccurs="unbounded">
+ <complexType>
+ <choice>
+ <element ref="xn:SubNetwork"/>
+ <element ref="xn:MeContext"/>
+ <!--
+ <element ref="xn:ManagedElement"/>
+ Not Possible at this level in Ericsson Model
+ -->
+ </choice>
+ <attribute name="dnPrefix" type="string" use="optional"/>
+ </complexType>
+ </element>
+ <element name="fileFooter">
+ <complexType>
+ <attribute name="dateTime" type="dateTime" use="required"/>
+ </complexType>
+ </element>
+ </sequence>
+ </complexType>
+ </element>
+</schema>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/genericNrm.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/genericNrm.xsd
new file mode 100644
index 0000000000..9c672cda8c
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/genericNrm.xsd
@@ -0,0 +1,230 @@
+<!--
+ 3GPP TS 32.615 v4.5 Bulk CM IRP
+ Configuration data file Generic Network Resources IRP NRM XML schema
+ -->
+<schema targetNamespace="genericNrm.xsd" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:un="utranNrm.xsd" xmlns:gn="geranNrm.xsd" xmlns:xn="genericNrm.xsd" elementFormDefault="qualified" attributeFormDefault="unqualified">
+
+ <import namespace="geranNrm.xsd" schemaLocation="geranNrm.xsd"/>
+ <import namespace="utranNrm.xsd" schemaLocation="utranNrm.xsd"/>
+
+ <!-- Abstract base type for all NRM class associated XML elements -->
+ <complexType name="NrmClassXmlType" abstract="true">
+ <attribute name="id" type="string" use="required"/>
+ <attribute name="modifier" use="optional">
+ <simpleType>
+ <restriction base="string">
+ <enumeration value="create"/>
+ <enumeration value="delete"/>
+ <enumeration value="update"/>
+ </restriction>
+ </simpleType>
+ </attribute>
+ </complexType>
+
+ <!-- Generic Network Resources IRP NRM class associated XML elements -->
+ <element name="SubNetwork">
+ <complexType>
+ <complexContent>
+ <extension base="xn:NrmClassXmlType">
+ <sequence>
+ <element name="attributes" minOccurs="0">
+ <complexType>
+ <all>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="userDefinedNetworkType" minOccurs="0"/>
+ </all>
+ </complexType>
+ </element>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element ref="xn:SubNetwork"/>
+ <element ref="xn:ManagedElement"/>
+ <element ref="xn:MeContext"/>
+ <element ref="xn:ManagementNode"/>
+ <element ref="xn:IRPAgent"/>
+ <element ref="un:ExternalUtranCell"/>
+ <element ref="gn:ExternalGsmCell"/>
+ <element ref="xn:VsDataContainer"/>
+ </choice>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+
+ <element name="ManagedElement">
+ <complexType>
+ <complexContent>
+ <extension base="xn:NrmClassXmlType">
+ <sequence>
+ <element name="attributes" minOccurs="0">
+ <complexType>
+ <all>
+ <element name="managedElementType" minOccurs="0"/>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="vendorName" minOccurs="0"/>
+ <element name="userDefinedState" minOccurs="0"/>
+ <element name="locationName" minOccurs="0"/>
+ <element name="swVersion" minOccurs="0"/>
+ <element name="managedBy" minOccurs="0"/>
+ </all>
+ </complexType>
+ </element>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element ref="un:RncFunction"/>
+ <element ref="un:NodeBFunction"/>
+ <element ref="xn:VsDataContainer"/>
+ </choice>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+
+ <element name="MeContext">
+ <complexType>
+ <complexContent>
+ <extension base="xn:NrmClassXmlType">
+ <sequence>
+ <element name="attributes" minOccurs="0">
+ <complexType>
+ </complexType>
+ </element>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element ref="xn:ManagedElement"/>
+ <element ref="xn:VsDataContainer"/>
+ </choice>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+
+ <element name="ManagementNode">
+ <complexType>
+ <complexContent>
+ <extension base="xn:NrmClassXmlType">
+ <sequence>
+ <element name="attributes" minOccurs="0">
+ <complexType>
+ <all>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="vendorName" minOccurs="0"/>
+ <element name="userDefinedState" minOccurs="0"/>
+ <element name="locationName" minOccurs="0"/>
+ <element name="manages" minOccurs="0"/>
+ <element name="swVersion" minOccurs="0"/>
+ </all>
+ </complexType>
+ </element>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element ref="xn:IRPAgent"/>
+ </choice>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+
+ <element name="IRPAgent">
+ <complexType>
+ <complexContent>
+ <extension base="xn:NrmClassXmlType">
+ <sequence>
+ <element name="attributes" minOccurs="0">
+ <complexType>
+ <all>
+ <element name="systemDN" minOccurs="0"/>
+ </all>
+ </complexType>
+ </element>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element ref="xn:NotificationIRP"/>
+ <element ref="xn:AlarmIRP"/>
+ <element ref="xn:BulkCmIRP"/>
+ </choice>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+
+ <element name="NotificationIRP">
+ <complexType>
+ <complexContent>
+ <extension base="xn:NrmClassXmlType">
+ <sequence>
+ <element name="attributes" minOccurs="0">
+ <complexType>
+ <all>
+ <element name="irpVersion" minOccurs="0"/>
+ </all>
+ </complexType>
+ </element>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+
+ <element name="AlarmIRP">
+ <complexType>
+ <complexContent>
+ <extension base="xn:NrmClassXmlType">
+ <sequence>
+ <element name="attributes" minOccurs="0">
+ <complexType>
+ <all>
+ <element name="irpVersion" minOccurs="0"/>
+ </all>
+ </complexType>
+ </element>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+
+ <element name="BulkCmIRP">
+ <complexType>
+ <complexContent>
+ <extension base="xn:NrmClassXmlType">
+ <sequence>
+ <element name="attributes" minOccurs="0">
+ <complexType>
+ <all>
+ <element name="irpVersion" minOccurs="0"/>
+ </all>
+ </complexType>
+ </element>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+
+ <element name="VsDataContainer">
+ <complexType>
+ <complexContent>
+ <extension base="xn:NrmClassXmlType">
+ <sequence>
+ <element name="attributes" minOccurs="0">
+ <complexType>
+ <all>
+ <element name="vsDataType" minOccurs="0"/>
+ <element name="vsDataFormatVersion" minOccurs="0"/>
+ <element ref="xn:vsData" minOccurs="0"/>
+ </all>
+ </complexType>
+ </element>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element ref="xn:VsDataContainer"/>
+ </choice>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <complexType name="vsData" abstract="true"/>
+ <!-- VsDataContainer NRM class vsData attribute associated empty XML element -->
+ <element name="vsData" type="xn:vsData" abstract="true"/>
+</schema>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/geranNrm.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/geranNrm.xsd
new file mode 100644
index 0000000000..b226eb2f4b
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/geranNrm.xsd
@@ -0,0 +1,63 @@
+<!--
+ 3GPP TS 32.615 v4.5 Bulk CM IRP
+ Configuration data file UTRAN Network Resources IRP NRM XML schema
+ To be used with WEGA Bucket 2.1 onwards
+-->
+<schema targetNamespace="geranNrm.xsd" xmlns:gn="geranNrm.xsd" xmlns:un="utranNrm.xsd" xmlns:xn="genericNrm.xsd" xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
+ <!-- GERAN Network Resources IRP NRM class associated XML elements -->
+ <import namespace="genericNrm.xsd" schemaLocation="genericNrm.xsd"/>
+ <import namespace="utranNrm.xsd" schemaLocation="utranNrm.xsd"/>
+ <element name="GsmRelation">
+ <complexType>
+ <complexContent>
+ <extension base="xn:NrmClassXmlType">
+ <sequence>
+ <element name="attributes" minOccurs="0">
+ <complexType>
+ <all><!--
+ <element name="relationType" minOccurs="0"/>
+ -->
+ <element name="adjacentCell" minOccurs="0"/>
+ </all>
+ </complexType>
+ </element>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element ref="xn:VsDataContainer"/>
+ </choice>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="ExternalGsmCell">
+ <complexType>
+ <complexContent>
+ <extension base="xn:NrmClassXmlType">
+ <sequence>
+ <element name="attributes" minOccurs="0">
+ <complexType>
+ <all>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="cellIdentity" minOccurs="0"/>
+ <element name="bcchFrequency" minOccurs="0"/>
+ <element name="ncc" minOccurs="0"/>
+ <element name="bcc" minOccurs="0"/>
+ <element name="lac" minOccurs="0"/>
+ <element name="mcc" minOccurs="0"/>
+ <element name="mnc" minOccurs="0"/>
+ <!--
+ <element name="rac" minOccurs="0"/>
+ <element name="racc" minOccurs="0"/>
+ -->
+ </all>
+ </complexType>
+ </element>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element ref="xn:VsDataContainer"/>
+ </choice>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+</schema>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/rnc.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/rnc.xml
new file mode 100644
index 0000000000..b6ca8b4fb1
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/rnc.xml
@@ -0,0 +1,23763 @@
+<?xml version="1.0" encoding="utf-8"?>
+<bulkCmConfigDataFile xmlns="configData.xsd" xmlns:xn="genericNrm.xsd" xmlns:gn="geranNrm.xsd" xmlns:un="utranNrm.xsd" xmlns:es="EricssonSpecificAttributes.5.1.xsd">
+ <fileHeader fileFormatVersion="32.615 V4.5" senderName="DC=a1.companyNN.com,SubNetwork=1,IRPAgent=1" vendorName="Company NN"/>
+ <configData dnPrefix="DC=a0.companyNN.com">
+<xn:SubNetwork id="WEOSSRC1_ROOT_MO_R">
+<xn:SubNetwork id="RNC33">
+<xn:MeContext id="SRNC001">
+
+
+<xn:ManagedElement id="1">
+<xn:attributes>
+
+<xn:userLabel>/proj/netsimproj/public/ftp/simulations/WRAN/R5/Standard/E/V2</xn:userLabel>
+</xn:attributes>
+
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSwManagement</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSwManagement />
+</xn:attributes>
+<xn:VsDataContainer id="scc_adm" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="scc_server" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="aal2ap13" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="sw_inst" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="spas_res" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="inet" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="ospf" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="aal05_ncc" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="aal_cc" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="phy_e1_mp" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="phy_stm1_mp" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="atmmp" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="aal2mp" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="aal2_adm" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="aal2ncc" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="aal0d_adm" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="aal0s_adm" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="aal5d_adm" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="aal5s_adm" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="usaal_adm" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="nsaal_adm" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="equip_mp" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="nss_mp" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="ip_util" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="spp_mp" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="http" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="jvm" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="ans_aal2rh_1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="ans_aal2disncc_12_1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="ans_aal2cpsrc_12_1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="ans_aal2ap_12_1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RncRpuCenDh" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RncRpuCenRh" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RncRpuDh" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RncRpuFro" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RncRpuCenOm" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RncRpuUe" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RncRpuModOm" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RncRpuRanap" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RncRpuRnsap" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RncRpuCenRnh" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RncRpuCell" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataReliableProgramUniter</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataReliableProgramUniter>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataReliableProgramUniter>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataTransportNetwork</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataTransportNetwork>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataTransportNetwork>
+</xn:attributes><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2Sp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataAal2Sp>
+
+<es:a2ea> </es:a2ea>
+<es:userLabel> </es:userLabel>
+</es:vsDataAal2Sp></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2Sp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal2Sp>
+
+<es:a2ea> </es:a2ea>
+<es:userLabel> </es:userLabel>
+</es:vsDataAal2Sp>
+</xn:attributes><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2Ap</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataAal2Ap>
+
+<es:aal2QoSCodePointProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal2QosCodePointProfile=1</es:aal2QoSCodePointProfileId>
+<es:rpuId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataSwManagement=1,vsDataReliableProgramUniter=ans_aal2ap_12_1</es:rpuId>
+<es:secondarySigLinkId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b4qb</es:secondarySigLinkId>
+<es:sigLinkId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b4qa</es:sigLinkId>
+<es:timerErq>5000</es:timerErq>
+<es:timerRel>2000</es:timerRel>
+<es:userLabel> </es:userLabel>
+<es:allocationMode>0</es:allocationMode>
+</es:vsDataAal2Ap></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2Ap</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal2Ap>
+
+<es:aal2QoSCodePointProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal2QosCodePointProfile=1</es:aal2QoSCodePointProfileId>
+<es:rpuId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataSwManagement=1,vsDataReliableProgramUniter=ans_aal2ap_12_1</es:rpuId>
+<es:secondarySigLinkId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b4qb</es:secondarySigLinkId>
+<es:sigLinkId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b4qa</es:sigLinkId>
+<es:timerErq>5000</es:timerErq>
+<es:timerRel>2000</es:timerRel>
+<es:userLabel> </es:userLabel>
+<es:allocationMode>0</es:allocationMode>
+</es:vsDataAal2Ap>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2PathDistributionUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal2PathDistributionUnit>
+
+<es:userLabel> </es:userLabel>
+<es:rpuId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataSwManagement=1,vsDataReliableProgramUniter=ans_aal2cpsrc_12_1</es:rpuId>
+
+<es:aal2PathVccTpList>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal2PathVccTp=b1a1</es:aal2PathVccTpList>
+</es:vsDataAal2PathDistributionUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer><xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2Ap</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataAal2Ap>
+
+<es:aal2QoSCodePointProfileId>0</es:aal2QoSCodePointProfileId>
+<es:rpuId>0</es:rpuId>
+<es:secondarySigLinkId>0</es:secondarySigLinkId>
+<es:sigLinkId>0</es:sigLinkId>
+<es:timerErq>5000</es:timerErq>
+<es:timerRel>2000</es:timerRel>
+<es:userLabel> </es:userLabel>
+<es:allocationMode>0</es:allocationMode>
+</es:vsDataAal2Ap></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2Ap</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal2Ap>
+
+<es:aal2QoSCodePointProfileId>0</es:aal2QoSCodePointProfileId>
+<es:rpuId>0</es:rpuId>
+<es:secondarySigLinkId>0</es:secondarySigLinkId>
+<es:sigLinkId>0</es:sigLinkId>
+<es:timerErq>5000</es:timerErq>
+<es:timerRel>2000</es:timerRel>
+<es:userLabel> </es:userLabel>
+<es:allocationMode>0</es:allocationMode>
+</es:vsDataAal2Ap>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2PathDistributionUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal2PathDistributionUnit>
+
+<es:userLabel> </es:userLabel>
+<es:rpuId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataSwManagement=1,vsDataReliableProgramUniter=ans_aal2cpsrc_12_1</es:rpuId>
+
+<es:aal2PathVccTpList>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal2PathVccTp=b2a1</es:aal2PathVccTpList>
+</es:vsDataAal2PathDistributionUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer><xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2Ap</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataAal2Ap>
+
+<es:aal2QoSCodePointProfileId>0</es:aal2QoSCodePointProfileId>
+<es:rpuId>0</es:rpuId>
+<es:secondarySigLinkId>0</es:secondarySigLinkId>
+<es:sigLinkId>0</es:sigLinkId>
+<es:timerErq>5000</es:timerErq>
+<es:timerRel>2000</es:timerRel>
+<es:userLabel> </es:userLabel>
+<es:allocationMode>0</es:allocationMode>
+</es:vsDataAal2Ap></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2Ap</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal2Ap>
+
+<es:aal2QoSCodePointProfileId>0</es:aal2QoSCodePointProfileId>
+<es:rpuId>0</es:rpuId>
+<es:secondarySigLinkId>0</es:secondarySigLinkId>
+<es:sigLinkId>0</es:sigLinkId>
+<es:timerErq>5000</es:timerErq>
+<es:timerRel>2000</es:timerRel>
+<es:userLabel> </es:userLabel>
+<es:allocationMode>0</es:allocationMode>
+</es:vsDataAal2Ap>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2PathDistributionUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal2PathDistributionUnit>
+
+<es:userLabel> </es:userLabel>
+<es:rpuId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataSwManagement=1,vsDataReliableProgramUniter=ans_aal2cpsrc_12_1</es:rpuId>
+
+<es:aal2PathVccTpList>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal2PathVccTp=b3a1</es:aal2PathVccTpList>
+</es:vsDataAal2PathDistributionUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer><xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2Ap</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataAal2Ap>
+
+<es:aal2QoSCodePointProfileId>0</es:aal2QoSCodePointProfileId>
+<es:rpuId>0</es:rpuId>
+<es:secondarySigLinkId>0</es:secondarySigLinkId>
+<es:sigLinkId>0</es:sigLinkId>
+<es:timerErq>5000</es:timerErq>
+<es:timerRel>2000</es:timerRel>
+<es:userLabel> </es:userLabel>
+<es:allocationMode>0</es:allocationMode>
+</es:vsDataAal2Ap></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2Ap</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal2Ap>
+
+<es:aal2QoSCodePointProfileId>0</es:aal2QoSCodePointProfileId>
+<es:rpuId>0</es:rpuId>
+<es:secondarySigLinkId>0</es:secondarySigLinkId>
+<es:sigLinkId>0</es:sigLinkId>
+<es:timerErq>5000</es:timerErq>
+<es:timerRel>2000</es:timerRel>
+<es:userLabel> </es:userLabel>
+<es:allocationMode>0</es:allocationMode>
+</es:vsDataAal2Ap>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2PathDistributionUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal2PathDistributionUnit>
+
+<es:userLabel> </es:userLabel>
+<es:rpuId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataSwManagement=1,vsDataReliableProgramUniter=ans_aal2cpsrc_12_1</es:rpuId>
+
+<es:aal2PathVccTpList>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal2PathVccTp=b4a1</es:aal2PathVccTpList>
+</es:vsDataAal2PathDistributionUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+</xn:VsDataContainer><xn:VsDataContainer id="MS-24-1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=1,vsDataPlugInUnit=1,vsDataExchangeTerminal=ET-M4,vsDataOs155SpiTtp=1,vsDataSts3CspeTtp=1</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-24-1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=1,vsDataPlugInUnit=1,vsDataExchangeTerminal=ET-M4,vsDataOs155SpiTtp=1,vsDataSts3CspeTtp=1</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes><xn:VsDataContainer id="Vp1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVplTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataVplTp>
+
+<es:atmTrafficDescriptor>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptor>
+<es:externalVpi>1</es:externalVpi>
+<es:userLabel> </es:userLabel>
+</es:vsDataVplTp></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="Vp1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVplTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVplTp>
+
+<es:atmTrafficDescriptor>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptor>
+<es:externalVpi>1</es:externalVpi>
+<es:userLabel> </es:userLabel>
+</es:vsDataVplTp>
+</xn:attributes><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVpcTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataVpcTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:userLabel> </es:userLabel>
+<es:counterMode>0</es:counterMode>
+</es:vsDataVpcTp></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVpcTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVpcTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:userLabel> </es:userLabel>
+<es:counterMode>0</es:counterMode>
+</es:vsDataVpcTp>
+</xn:attributes>
+<xn:VsDataContainer id="vc34" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptorId>
+<es:externalVci>34</es:externalVci>
+<es:userLabel>used by Aal0 b1sa (NodeSynchTp1)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc35" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptorId>
+<es:externalVci>35</es:externalVci>
+<es:userLabel>used by Aal0 b1sb (NodeSynchTp2)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc36" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>36</es:externalVci>
+<es:userLabel>used by Aal5 b1ca (Nbap Common)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc37" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>37</es:externalVci>
+<es:userLabel>used by Aal5 b1da (Nbap Dedicated)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc38" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>38</es:externalVci>
+<es:userLabel>used by Aal5 b1qa (Aal2 signalling)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc39" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>39</es:externalVci>
+<es:userLabel>used by Aal2 b1a1 (Aal2Path)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc43" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C2P4000</es:atmTrafficDescriptorId>
+<es:externalVci>43</es:externalVci>
+<es:userLabel>used by Aal5 b1cb (Nbap Common)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc44" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>44</es:externalVci>
+<es:userLabel>used by Aal5 b1db (Nbap Dedicated)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc45" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>45</es:externalVci>
+<es:userLabel>used by Aal5 b1qb (Aal2 signalling)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc32-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>45</es:externalVci>
+<es:userLabel>used by Aal5 b1-x1 (IpAtmLink)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc33-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>33</es:externalVci>
+<es:userLabel>used by Aal5 b1-x2 (IpAtmLink)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc34-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptorId>
+<es:externalVci>340</es:externalVci>
+<es:userLabel>used by Aal0 b1sa-x (NodeSynchTp1)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc35-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptorId>
+<es:externalVci>350</es:externalVci>
+<es:userLabel>used by Aal0 b1sb-x (NodeSyncT2p)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+</xn:VsDataContainer><xn:VsDataContainer id="Vp2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVplTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataVplTp>
+
+<es:atmTrafficDescriptor>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptor>
+<es:externalVpi>2</es:externalVpi>
+<es:userLabel> </es:userLabel>
+</es:vsDataVplTp></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="Vp2" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVplTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVplTp>
+
+<es:atmTrafficDescriptor>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptor>
+<es:externalVpi>2</es:externalVpi>
+<es:userLabel> </es:userLabel>
+</es:vsDataVplTp>
+</xn:attributes><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVpcTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataVpcTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:userLabel> </es:userLabel>
+<es:counterMode>0</es:counterMode>
+</es:vsDataVpcTp></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVpcTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVpcTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:userLabel> </es:userLabel>
+<es:counterMode>0</es:counterMode>
+</es:vsDataVpcTp>
+</xn:attributes>
+<xn:VsDataContainer id="vc34" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptorId>
+<es:externalVci>34</es:externalVci>
+<es:userLabel>used by Aal0 b2sa (NodeSynchTp1)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc35" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptorId>
+<es:externalVci>35</es:externalVci>
+<es:userLabel>used by Aal0 b2sb (NodeSynchTp2)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc36" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>36</es:externalVci>
+<es:userLabel>used by Aal5 b2ca (Nbap Common)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc37" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>37</es:externalVci>
+<es:userLabel>used by Aal5 b2da (Nbap Dedicated)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc38" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>38</es:externalVci>
+<es:userLabel>used by Aal5 b2qa (Aal2 signalling)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc39" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>39</es:externalVci>
+<es:userLabel>used by Aal2 b2a1 (Aal2Path)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc43" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C2P4000</es:atmTrafficDescriptorId>
+<es:externalVci>43</es:externalVci>
+<es:userLabel>used by Aal5 b2cb (Nbap Common)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc44" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>44</es:externalVci>
+<es:userLabel>used by Aal5 b2db (Nbap Dedicated)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc45" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>45</es:externalVci>
+<es:userLabel>used by Aal5 b2qb (Aal2 signalling)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc32-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>45</es:externalVci>
+<es:userLabel>used by Aal5 b2-x1 (IpAtmLink)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc33-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>33</es:externalVci>
+<es:userLabel>used by Aal5 b2-x2 (IpAtmLink)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc34-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptorId>
+<es:externalVci>340</es:externalVci>
+<es:userLabel>used by Aal0 b2sa-x (NodeSynchTp1)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc35-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptorId>
+<es:externalVci>350</es:externalVci>
+<es:userLabel>used by Aal0 b2sb-x (NodeSyncT2p)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+</xn:VsDataContainer><xn:VsDataContainer id="Vp3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVplTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataVplTp>
+
+<es:atmTrafficDescriptor>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptor>
+<es:externalVpi>3</es:externalVpi>
+<es:userLabel> </es:userLabel>
+</es:vsDataVplTp></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="Vp3" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVplTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVplTp>
+
+<es:atmTrafficDescriptor>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptor>
+<es:externalVpi>3</es:externalVpi>
+<es:userLabel> </es:userLabel>
+</es:vsDataVplTp>
+</xn:attributes><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVpcTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataVpcTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:userLabel> </es:userLabel>
+<es:counterMode>0</es:counterMode>
+</es:vsDataVpcTp></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVpcTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVpcTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:userLabel> </es:userLabel>
+<es:counterMode>0</es:counterMode>
+</es:vsDataVpcTp>
+</xn:attributes>
+<xn:VsDataContainer id="vc34" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptorId>
+<es:externalVci>34</es:externalVci>
+<es:userLabel>used by Aal0 b3sa (NodeSynchTp1)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc35" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptorId>
+<es:externalVci>35</es:externalVci>
+<es:userLabel>used by Aal0 b3sb (NodeSynchTp2)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc36" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>36</es:externalVci>
+<es:userLabel>used by Aal5 b3ca (Nbap Common)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc37" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>37</es:externalVci>
+<es:userLabel>used by Aal5 b3da (Nbap Dedicated)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc38" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>38</es:externalVci>
+<es:userLabel>used by Aal5 b3qa (Aal2 signalling)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc39" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>39</es:externalVci>
+<es:userLabel>used by Aal2 b3a1 (Aal2Path)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc43" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C2P4000</es:atmTrafficDescriptorId>
+<es:externalVci>43</es:externalVci>
+<es:userLabel>used by Aal5 b3cb (Nbap Common)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc44" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>44</es:externalVci>
+<es:userLabel>used by Aal5 b3db (Nbap Dedicated)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc45" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>45</es:externalVci>
+<es:userLabel>used by Aal5 b3qb (Aal2 signalling)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc32-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>45</es:externalVci>
+<es:userLabel>used by Aal5 b3-x1 (IpAtmLink)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc33-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>33</es:externalVci>
+<es:userLabel>used by Aal5 b3-x2 (IpAtmLink)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc34-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptorId>
+<es:externalVci>340</es:externalVci>
+<es:userLabel>used by Aal0 b3sa-x (NodeSynchTp1)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc35-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptorId>
+<es:externalVci>350</es:externalVci>
+<es:userLabel>used by Aal0 b3sb-x (NodeSyncT2p)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+</xn:VsDataContainer><xn:VsDataContainer id="Vp4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVplTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataVplTp>
+
+<es:atmTrafficDescriptor>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptor>
+<es:externalVpi>4</es:externalVpi>
+<es:userLabel> </es:userLabel>
+</es:vsDataVplTp></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="Vp4" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVplTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVplTp>
+
+<es:atmTrafficDescriptor>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptor>
+<es:externalVpi>4</es:externalVpi>
+<es:userLabel> </es:userLabel>
+</es:vsDataVplTp>
+</xn:attributes><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVpcTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataVpcTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:userLabel> </es:userLabel>
+<es:counterMode>0</es:counterMode>
+</es:vsDataVpcTp></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVpcTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVpcTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:userLabel> </es:userLabel>
+<es:counterMode>0</es:counterMode>
+</es:vsDataVpcTp>
+</xn:attributes>
+<xn:VsDataContainer id="vc34" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptorId>
+<es:externalVci>34</es:externalVci>
+<es:userLabel>used by Aal0 b4sa (NodeSynchTp1)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc35" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptorId>
+<es:externalVci>35</es:externalVci>
+<es:userLabel>used by Aal0 b4sb (NodeSynchTp2)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc36" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>36</es:externalVci>
+<es:userLabel>used by Aal5 b4ca (Nbap Common)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc37" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>37</es:externalVci>
+<es:userLabel>used by Aal5 b4da (Nbap Dedicated)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc38" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>38</es:externalVci>
+<es:userLabel>used by Aal5 b4qa (Aal2 signalling)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc39" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>39</es:externalVci>
+<es:userLabel>used by Aal2 b4a1 (Aal2Path)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc43" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C2P4000</es:atmTrafficDescriptorId>
+<es:externalVci>43</es:externalVci>
+<es:userLabel>used by Aal5 b4cb (Nbap Common)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc44" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>44</es:externalVci>
+<es:userLabel>used by Aal5 b4db (Nbap Dedicated)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc45" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>45</es:externalVci>
+<es:userLabel>used by Aal5 b4qb (Aal2 signalling)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc32-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>45</es:externalVci>
+<es:userLabel>used by Aal5 b4-x1 (IpAtmLink)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc33-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=U3P1000M80</es:atmTrafficDescriptorId>
+<es:externalVci>33</es:externalVci>
+<es:userLabel>used by Aal5 b4-x2 (IpAtmLink)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc34-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptorId>
+<es:externalVci>340</es:externalVci>
+<es:userLabel>used by Aal0 b4sa-x (NodeSynchTp1)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="vc35-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataVclTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVclTp>
+
+<es:atmTrafficDescriptorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmTrafficDescriptor=C1P4528</es:atmTrafficDescriptorId>
+<es:externalVci>350</es:externalVci>
+<es:userLabel>used by Aal0 b4sb-x (NodeSyncT2p)</es:userLabel>
+</es:vsDataVclTp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-24-2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-24-3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-24-4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-24-5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-24-6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-24-7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-24-8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-25-1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-25-2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-25-3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-25-4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-25-5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-25-6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-25-7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-25-8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-26-1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-26-2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-26-3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-26-4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-26-5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-26-6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-26-7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-26-8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-27-1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-27-2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-27-3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-27-4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-27-5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-27-6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-27-7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS-27-8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmPort</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmPort>
+
+<es:userLabel> </es:userLabel>
+<es:uses>0</es:uses>
+<es:hecCorrectionMode>true</es:hecCorrectionMode>
+</es:vsDataAtmPort>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="ta1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataMspg</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataMspg>
+
+<es:userLabel> </es:userLabel>
+<es:degCauseMsp>false</es:degCauseMsp>
+<es:os155SpiStandbyId>0</es:os155SpiStandbyId>
+<es:os155SpiWorkingId>0</es:os155SpiWorkingId>
+</es:vsDataMspg>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="C1P4528" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmTrafficDescriptor</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmTrafficDescriptor>
+
+<es:egressAtmMcr>0</es:egressAtmMcr>
+<es:egressAtmPcr>0</es:egressAtmPcr>
+<es:egressAtmQos>1</es:egressAtmQos>
+<es:ingressAtmMcr>0</es:ingressAtmMcr>
+<es:ingressAtmPcr>0</es:ingressAtmPcr>
+<es:ingressAtmQos>1</es:ingressAtmQos>
+<es:serviceCategory>1</es:serviceCategory>
+<es:userLabel> </es:userLabel>
+<es:packetDiscard>false</es:packetDiscard>
+</es:vsDataAtmTrafficDescriptor>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="C1P5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmTrafficDescriptor</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmTrafficDescriptor>
+
+<es:egressAtmMcr>0</es:egressAtmMcr>
+<es:egressAtmPcr>0</es:egressAtmPcr>
+<es:egressAtmQos>1</es:egressAtmQos>
+<es:ingressAtmMcr>0</es:ingressAtmMcr>
+<es:ingressAtmPcr>0</es:ingressAtmPcr>
+<es:ingressAtmQos>1</es:ingressAtmQos>
+<es:serviceCategory>1</es:serviceCategory>
+<es:userLabel> </es:userLabel>
+<es:packetDiscard>false</es:packetDiscard>
+</es:vsDataAtmTrafficDescriptor>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="C2P4000" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmTrafficDescriptor</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmTrafficDescriptor>
+
+<es:egressAtmMcr>0</es:egressAtmMcr>
+<es:egressAtmPcr>0</es:egressAtmPcr>
+<es:egressAtmQos>1</es:egressAtmQos>
+<es:ingressAtmMcr>0</es:ingressAtmMcr>
+<es:ingressAtmPcr>0</es:ingressAtmPcr>
+<es:ingressAtmQos>1</es:ingressAtmQos>
+<es:serviceCategory>1</es:serviceCategory>
+<es:userLabel> </es:userLabel>
+<es:packetDiscard>false</es:packetDiscard>
+</es:vsDataAtmTrafficDescriptor>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="U3P1000M80" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAtmTrafficDescriptor</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAtmTrafficDescriptor>
+
+<es:egressAtmMcr>0</es:egressAtmMcr>
+<es:egressAtmPcr>0</es:egressAtmPcr>
+<es:egressAtmQos>1</es:egressAtmQos>
+<es:ingressAtmMcr>0</es:ingressAtmMcr>
+<es:ingressAtmPcr>0</es:ingressAtmPcr>
+<es:ingressAtmQos>1</es:ingressAtmQos>
+<es:serviceCategory>1</es:serviceCategory>
+<es:userLabel> </es:userLabel>
+<es:packetDiscard>false</es:packetDiscard>
+</es:vsDataAtmTrafficDescriptor>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b1da" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp1,vsDataVpcTp=1,vsDataVclTp=vc37</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b1ca" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp1,vsDataVpcTp=1,vsDataVclTp=vc36</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b1db" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp1,vsDataVpcTp=1,vsDataVclTp=vc44</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b1cb" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp1,vsDataVpcTp=1,vsDataVclTp=vc43</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b1-x1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp1,vsDataVpcTp=1,vsDataVclTp=vc32-x</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b1-x2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp1,vsDataVpcTp=1,vsDataVclTp=vc33-x</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b2da" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp2,vsDataVpcTp=1,vsDataVclTp=vc37</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b2ca" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp2,vsDataVpcTp=1,vsDataVclTp=vc36</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b2db" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp2,vsDataVpcTp=1,vsDataVclTp=vc44</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b2cb" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp2,vsDataVpcTp=1,vsDataVclTp=vc43</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b2-x1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp2,vsDataVpcTp=1,vsDataVclTp=vc32-x</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b2-x2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp2,vsDataVpcTp=1,vsDataVclTp=vc33-x</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b3da" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp3,vsDataVpcTp=1,vsDataVclTp=vc37</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b3ca" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp3,vsDataVpcTp=1,vsDataVclTp=vc36</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b3db" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp3,vsDataVpcTp=1,vsDataVclTp=vc44</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b3cb" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp3,vsDataVpcTp=1,vsDataVclTp=vc43</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b3-x1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp3,vsDataVpcTp=1,vsDataVclTp=vc32-x</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b3-x2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp3,vsDataVpcTp=1,vsDataVclTp=vc33-x</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b4da" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp4,vsDataVpcTp=1,vsDataVclTp=vc37</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b4ca" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp4,vsDataVpcTp=1,vsDataVclTp=vc36</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b4db" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp4,vsDataVpcTp=1,vsDataVclTp=vc44</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b4cb" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp4,vsDataVpcTp=1,vsDataVclTp=vc43</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b4-x1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp4,vsDataVpcTp=1,vsDataVclTp=vc32-x</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b4-x2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal5TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal5TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:fromUserMaxSduSize>1</es:fromUserMaxSduSize>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=24,vsDataPlugInUnit=1</es:processorId>
+<es:toUserMaxSduSize>1</es:toUserMaxSduSize>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp4,vsDataVpcTp=1,vsDataVclTp=vc33-x</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal5TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalProfile</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalProfile>
+
+<es:userLabel> </es:userLabel>
+<es:profileData>
+<es:congestionAbatement>60</es:congestionAbatement>
+<es:congestionOnSet>70</es:congestionOnSet>
+<es:initialCredit>250</es:initialCredit>
+<es:maxCC>4</es:maxCC>
+<es:maxPD>25</es:maxPD>
+<es:maxStat>67</es:maxStat>
+<es:timerCC>1000</es:timerCC>
+<es:timerIdle>15000</es:timerIdle>
+<es:timerKeepAlive>2000</es:timerKeepAlive>
+<es:timerNoResponse>7000</es:timerNoResponse>
+<es:timerPoll>750</es:timerPoll></es:profileData>
+</es:vsDataUniSaalProfile>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalProfile</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalProfile>
+
+<es:userLabel> </es:userLabel>
+<es:profileData>
+<es:congestionAbatement>60</es:congestionAbatement>
+<es:congestionOnSet>70</es:congestionOnSet>
+<es:initialCredit>250</es:initialCredit>
+<es:maxCC>4</es:maxCC>
+<es:maxPD>25</es:maxPD>
+<es:maxStat>67</es:maxStat>
+<es:timerCC>1000</es:timerCC>
+<es:timerIdle>15000</es:timerIdle>
+<es:timerKeepAlive>2000</es:timerKeepAlive>
+<es:timerNoResponse>7000</es:timerNoResponse>
+<es:timerPoll>750</es:timerPoll></es:profileData>
+</es:vsDataUniSaalProfile>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalProfile</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalProfile>
+
+<es:userLabel> </es:userLabel>
+<es:profileData>
+<es:congestionAbatement>60</es:congestionAbatement>
+<es:congestionOnSet>70</es:congestionOnSet>
+<es:initialCredit>250</es:initialCredit>
+<es:maxCC>4</es:maxCC>
+<es:maxPD>25</es:maxPD>
+<es:maxStat>67</es:maxStat>
+<es:timerCC>1000</es:timerCC>
+<es:timerIdle>15000</es:timerIdle>
+<es:timerKeepAlive>2000</es:timerKeepAlive>
+<es:timerNoResponse>7000</es:timerNoResponse>
+<es:timerPoll>750</es:timerPoll></es:profileData>
+</es:vsDataUniSaalProfile>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b1da" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b1da</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalProfile=1</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b1ca" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b1ca</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalProfile=1</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b1db" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b1db</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalProfile=1</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b1cb" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b1cb</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalProfile=1</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b1qa" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>0</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>0</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b1qb" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>0</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>0</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b2da" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b2da</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalProfile=1</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b2ca" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b2ca</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalProfile=1</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b2db" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b2db</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalProfile=1</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b2cb" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b2cb</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalProfile=1</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b2qa" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>0</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>0</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b2qb" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>0</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>0</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b3da" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b3da</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalProfile=1</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b3ca" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b3ca</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalProfile=1</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b3db" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b3db</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalProfile=1</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b3cb" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b3cb</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalProfile=1</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b3qa" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>0</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>0</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b3qb" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>0</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>0</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b4da" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b4da</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalProfile=1</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b4ca" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b4ca</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalProfile=1</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b4db" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b4db</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalProfile=1</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b4cb" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b4cb</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalProfile=1</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b4qa" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>0</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>0</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b4qb" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUniSaalTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUniSaalTp>
+
+<es:aal5TpVccTpId>0</es:aal5TpVccTpId>
+<es:maxSduSize>128</es:maxSduSize>
+<es:uniSaalProfileId>0</es:uniSaalProfileId>
+<es:userLabel> </es:userLabel>
+</es:vsDataUniSaalTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b1sa" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal0TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal0TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=4,vsDataPlugInUnit=1</es:processorId>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp1,vsDataVpcTp=1,vsDataVclTp=vc34</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal0TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b1sb" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal0TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal0TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=4,vsDataPlugInUnit=1</es:processorId>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp1,vsDataVpcTp=1,vsDataVclTp=vc35</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal0TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b1sa-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal0TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal0TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=4,vsDataPlugInUnit=1</es:processorId>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp1,vsDataVpcTp=1,vsDataVclTp=vc34-x</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal0TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b1sb-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal0TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal0TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=4,vsDataPlugInUnit=1</es:processorId>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp1,vsDataVpcTp=1,vsDataVclTp=vc35-x</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal0TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b2sa" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal0TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal0TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=4,vsDataPlugInUnit=1</es:processorId>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp2,vsDataVpcTp=1,vsDataVclTp=vc34</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal0TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b2sb" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal0TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal0TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=4,vsDataPlugInUnit=1</es:processorId>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp2,vsDataVpcTp=1,vsDataVclTp=vc35</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal0TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b2sa-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal0TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal0TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=4,vsDataPlugInUnit=1</es:processorId>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp2,vsDataVpcTp=1,vsDataVclTp=vc34-x</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal0TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b2sb-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal0TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal0TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=4,vsDataPlugInUnit=1</es:processorId>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp2,vsDataVpcTp=1,vsDataVclTp=vc35-x</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal0TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b3sa" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal0TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal0TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=4,vsDataPlugInUnit=1</es:processorId>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp3,vsDataVpcTp=1,vsDataVclTp=vc34</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal0TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b3sb" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal0TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal0TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=4,vsDataPlugInUnit=1</es:processorId>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp3,vsDataVpcTp=1,vsDataVclTp=vc35</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal0TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b3sa-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal0TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal0TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=4,vsDataPlugInUnit=1</es:processorId>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp3,vsDataVpcTp=1,vsDataVclTp=vc34-x</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal0TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b3sb-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal0TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal0TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=4,vsDataPlugInUnit=1</es:processorId>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp3,vsDataVpcTp=1,vsDataVclTp=vc35-x</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal0TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b4sa" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal0TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal0TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=4,vsDataPlugInUnit=1</es:processorId>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp4,vsDataVpcTp=1,vsDataVclTp=vc34</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal0TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b4sb" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal0TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal0TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=4,vsDataPlugInUnit=1</es:processorId>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp4,vsDataVpcTp=1,vsDataVclTp=vc35</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal0TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b4sa-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal0TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal0TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=4,vsDataPlugInUnit=1</es:processorId>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp4,vsDataVpcTp=1,vsDataVclTp=vc34-x</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal0TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b4sb-x" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal0TpVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal0TpVccTp>
+
+<es:alarmReport>2</es:alarmReport>
+<es:continuityCheck>false</es:continuityCheck>
+<es:nomPmBlkSize>1024</es:nomPmBlkSize>
+<es:processorId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataEquipment=1,vsDataSubrack=MS,vsDataSlot=4,vsDataPlugInUnit=1</es:processorId>
+<es:userLabel> </es:userLabel>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp4,vsDataVpcTp=1,vsDataVclTp=vc35-x</es:vclTpId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal0TpVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b1a1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2PathVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal2PathVccTp>
+
+<es:aal2PathOwner>true</es:aal2PathOwner>
+<es:alarmReport>2</es:alarmReport>
+<es:nomPmBlocksize>1024</es:nomPmBlocksize>
+<es:timerCu>10</es:timerCu>
+<es:userLabel> </es:userLabel>
+<es:administrativeState>1</es:administrativeState>
+<es:continuityCheck>false</es:continuityCheck>
+<es:aal2PathId>1</es:aal2PathId>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp1,vsDataVpcTp=1,vsDataVclTp=vc39</es:vclTpId>
+<es:aal2QoSAvailableProfiles>15</es:aal2QoSAvailableProfiles>
+<es:aal2QoSProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal2QosProfile=1</es:aal2QoSProfileId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal2PathVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b2a1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2PathVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal2PathVccTp>
+
+<es:aal2PathOwner>true</es:aal2PathOwner>
+<es:alarmReport>2</es:alarmReport>
+<es:nomPmBlocksize>1024</es:nomPmBlocksize>
+<es:timerCu>10</es:timerCu>
+<es:userLabel> </es:userLabel>
+<es:administrativeState>1</es:administrativeState>
+<es:continuityCheck>false</es:continuityCheck>
+<es:aal2PathId>1</es:aal2PathId>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp2,vsDataVpcTp=1,vsDataVclTp=vc39</es:vclTpId>
+<es:aal2QoSAvailableProfiles>15</es:aal2QoSAvailableProfiles>
+<es:aal2QoSProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal2QosProfile=1</es:aal2QoSProfileId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal2PathVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b3a1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2PathVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal2PathVccTp>
+
+<es:aal2PathOwner>true</es:aal2PathOwner>
+<es:alarmReport>2</es:alarmReport>
+<es:nomPmBlocksize>1024</es:nomPmBlocksize>
+<es:timerCu>10</es:timerCu>
+<es:userLabel> </es:userLabel>
+<es:administrativeState>1</es:administrativeState>
+<es:continuityCheck>false</es:continuityCheck>
+<es:aal2PathId>1</es:aal2PathId>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp3,vsDataVpcTp=1,vsDataVclTp=vc39</es:vclTpId>
+<es:aal2QoSAvailableProfiles>15</es:aal2QoSAvailableProfiles>
+<es:aal2QoSProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal2QosProfile=1</es:aal2QoSProfileId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal2PathVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="b4a1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2PathVccTp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal2PathVccTp>
+
+<es:aal2PathOwner>true</es:aal2PathOwner>
+<es:alarmReport>2</es:alarmReport>
+<es:nomPmBlocksize>1024</es:nomPmBlocksize>
+<es:timerCu>10</es:timerCu>
+<es:userLabel> </es:userLabel>
+<es:administrativeState>1</es:administrativeState>
+<es:continuityCheck>false</es:continuityCheck>
+<es:aal2PathId>1</es:aal2PathId>
+<es:vclTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAtmPort=MS-24-1,vsDataVplTp=Vp4,vsDataVpcTp=1,vsDataVclTp=vc39</es:vclTpId>
+<es:aal2QoSAvailableProfiles>15</es:aal2QoSAvailableProfiles>
+<es:aal2QoSProfileId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal2QosProfile=1</es:aal2QoSProfileId>
+<es:counterMode>6</es:counterMode>
+<es:counterActivation>false</es:counterActivation>
+</es:vsDataAal2PathVccTp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2QosProfile</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal2QosProfile>
+
+<es:profileClassA>
+<es:boundOnProbOfDelay>500000</es:boundOnProbOfDelay>
+<es:boundOnProbOfLoss>500000</es:boundOnProbOfLoss>
+<es:boundOnNodeDelay>5000</es:boundOnNodeDelay></es:profileClassA>
+<es:profileClassB>
+<es:boundOnProbOfDelay>500000</es:boundOnProbOfDelay>
+<es:boundOnProbOfLoss>500000</es:boundOnProbOfLoss>
+<es:boundOnNodeDelay>15000</es:boundOnNodeDelay></es:profileClassB>
+<es:profileClassC>
+<es:boundOnProbOfDelay>1000000000</es:boundOnProbOfDelay>
+<es:boundOnProbOfLoss>1000000000</es:boundOnProbOfLoss>
+<es:boundOnNodeDelay>25000</es:boundOnNodeDelay></es:profileClassC>
+<es:profileClassD>
+<es:boundOnProbOfDelay>1000000000</es:boundOnProbOfDelay>
+<es:boundOnProbOfLoss>1000000000</es:boundOnProbOfLoss>
+<es:boundOnNodeDelay>50000</es:boundOnNodeDelay></es:profileClassD>
+<es:userLabel> </es:userLabel>
+</es:vsDataAal2QosProfile>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2QosCodePointProfile</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal2QosCodePointProfile>
+
+<es:userLabel> </es:userLabel>
+<es:qualityOfServiceCodePointA>0</es:qualityOfServiceCodePointA>
+<es:qualityOfServiceCodePointB>0</es:qualityOfServiceCodePointB>
+<es:qualityOfServiceCodePointC>0</es:qualityOfServiceCodePointC>
+<es:qualityOfServiceCodePointD>0</es:qualityOfServiceCodePointD>
+</es:vsDataAal2QosCodePointProfile>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataAal2RoutingCase</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataAal2RoutingCase>
+
+<es:userLabel> </es:userLabel>
+<es:numberDirection> </es:numberDirection>
+<es:routeList></es:routeList>
+<es:routePriorityList></es:routePriorityList>
+</es:vsDataAal2RoutingCase>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataIpSystem</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIpSystem>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataIpSystem>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataEquipment</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataEquipment />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSpDevicePool</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSpDevicePool />
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSpDevicePool</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSpDevicePool />
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSpDevicePool</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSpDevicePool />
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="MS" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSubrack</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSubrack />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes><xn:VsDataContainer id="ET-M4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataExchangeTerminal</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataExchangeTerminal>
+
+
+<es:userLabel> </es:userLabel>
+</es:vsDataExchangeTerminal></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="ET-M4" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataExchangeTerminal</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataExchangeTerminal>
+
+
+<es:userLabel> </es:userLabel>
+</es:vsDataExchangeTerminal>
+</xn:attributes><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataOs155SpiTtp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataOs155SpiTtp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:lineNo>1</es:lineNo>
+<es:standardMode>0</es:standardMode>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+<es:muxMode>0</es:muxMode>
+<es:msDegThreshold>30</es:msDegThreshold>
+<es:msDegM>7</es:msDegM>
+<es:msRdiReporting>false</es:msRdiReporting>
+<es:msAisReporting>false</es:msAisReporting>
+<es:loopBack>0</es:loopBack>
+</es:vsDataOs155SpiTtp></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataOs155SpiTtp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataOs155SpiTtp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:lineNo>1</es:lineNo>
+<es:standardMode>0</es:standardMode>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+<es:muxMode>0</es:muxMode>
+<es:msDegThreshold>30</es:msDegThreshold>
+<es:msDegM>7</es:msDegM>
+<es:msRdiReporting>false</es:msRdiReporting>
+<es:msAisReporting>false</es:msAisReporting>
+<es:loopBack>0</es:loopBack>
+</es:vsDataOs155SpiTtp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc4Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc4Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:pathTraceFormat>16</es:pathTraceFormat>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:auAisReporting>false</es:auAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+</es:vsDataVc4Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="11" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="12" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="13" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="14" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="15" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="16" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="17" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="18" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="19" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="20" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="21" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="22" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="23" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="24" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="25" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="26" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="27" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="28" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="29" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="30" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="31" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="32" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="33" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="34" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="35" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="36" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="37" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="38" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="39" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="40" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="41" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="42" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="43" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="44" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="45" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="46" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="47" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="48" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="49" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="50" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="51" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="52" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="53" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="54" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="55" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="56" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="57" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="58" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="59" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="60" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="61" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="62" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="63" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVc12Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVc12Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:vcDegThreshold>30</es:vcDegThreshold>
+<es:vcDegM>7</es:vcDegM>
+<es:tuAisReporting>false</es:tuAisReporting>
+<es:vcRdiReporting>false</es:vcRdiReporting>
+<es:administrativeState>0</es:administrativeState>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataVc12Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataE1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSts3CspeTtp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataSts3CspeTtp>
+
+<es:userLabel> </es:userLabel>
+<es:aisPReporting>false</es:aisPReporting>
+<es:rdiPReporting>false</es:rdiPReporting>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+</es:vsDataSts3CspeTtp>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSts1SpeTtp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataSts1SpeTtp>
+
+<es:userLabel> </es:userLabel>
+<es:aisPReporting>false</es:aisPReporting>
+<es:rdiPReporting>false</es:rdiPReporting>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+</es:vsDataSts1SpeTtp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="11" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="12" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="13" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="14" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="15" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="16" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="17" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="18" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="19" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="20" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="21" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="22" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="23" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="24" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="25" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="26" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="27" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="28" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSts1SpeTtp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataSts1SpeTtp>
+
+<es:userLabel> </es:userLabel>
+<es:aisPReporting>false</es:aisPReporting>
+<es:rdiPReporting>false</es:rdiPReporting>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+</es:vsDataSts1SpeTtp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="11" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="12" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="13" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="14" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="15" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="16" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="17" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="18" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="19" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="20" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="21" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="22" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="23" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="24" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="25" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="26" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="27" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="28" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSts1SpeTtp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataSts1SpeTtp>
+
+<es:userLabel> </es:userLabel>
+<es:aisPReporting>false</es:aisPReporting>
+<es:rdiPReporting>false</es:rdiPReporting>
+<es:timConsequentAction>false</es:timConsequentAction>
+<es:expectedPathTrace> </es:expectedPathTrace>
+<es:transmittedPathTrace> </es:transmittedPathTrace>
+</es:vsDataSts1SpeTtp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="11" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="12" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="13" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="14" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="15" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="16" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="17" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="18" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="19" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="20" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="21" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="22" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="23" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="24" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="25" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="26" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="27" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="28" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataVt15Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataVt15Ttp>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:aisVreporting>false</es:aisVreporting>
+<es:rdiVreporting>false</es:rdiVreporting>
+<es:shutDownTimer>1800</es:shutDownTimer>
+</es:vsDataVt15Ttp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataT1Ttp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1Ttp>
+
+<es:userLabel> </es:userLabel>
+<es:aisReporting>false</es:aisReporting>
+<es:rdiReporting>false</es:rdiReporting>
+<es:idlePattern>0</es:idlePattern>
+</es:vsDataT1Ttp>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="ta1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataE3PhysPathTerm</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE3PhysPathTerm>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+<es:lineNo>1</es:lineNo>
+<es:loopback>0</es:loopback>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:rdiReporting>false</es:rdiReporting>
+<es:aisReporting>false</es:aisReporting>
+</es:vsDataE3PhysPathTerm>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="ta1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataT3PhysPathTerm</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT3PhysPathTerm>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+<es:lineNo>1</es:lineNo>
+<es:loopback>0</es:loopback>
+<es:rdiReporting>false</es:rdiReporting>
+<es:aisReporting>false</es:aisReporting>
+</es:vsDataT3PhysPathTerm>
+</xn:attributes>
+</xn:VsDataContainer><xn:VsDataContainer id="ta1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataE1PhysPathTerm</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataE1PhysPathTerm>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:lineNo>1</es:lineNo>
+<es:loopback>0</es:loopback>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:rdiReporting>false</es:rdiReporting>
+<es:aisReporting>false</es:aisReporting>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataE1PhysPathTerm></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="ta1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataE1PhysPathTerm</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataE1PhysPathTerm>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:lineNo>1</es:lineNo>
+<es:loopback>0</es:loopback>
+<es:crc4Mode>1</es:crc4Mode>
+<es:idlePattern>0</es:idlePattern>
+<es:degDegThr>30</es:degDegThr>
+<es:degDegM>7</es:degDegM>
+<es:rdiReporting>false</es:rdiReporting>
+<es:aisReporting>false</es:aisReporting>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataE1PhysPathTerm>
+</xn:attributes>
+<xn:VsDataContainer id="ta1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataDs0Bundle</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataDs0Bundle>
+
+<es:userLabel> </es:userLabel>
+<es:listOfTimeSlots></es:listOfTimeSlots>
+<es:tdmMode>true</es:tdmMode>
+</es:vsDataDs0Bundle>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="ta1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataJ1PhysPathTerm</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataJ1PhysPathTerm>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:lineNo>1</es:lineNo>
+<es:loopback>0</es:loopback>
+<es:idlePattern>0</es:idlePattern>
+<es:physicalLineType>0</es:physicalLineType>
+<es:degThreshold>6</es:degThreshold>
+<es:rdiReporting>false</es:rdiReporting>
+<es:aisReporting>false</es:aisReporting>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+</es:vsDataJ1PhysPathTerm>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="ta1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataT1PhysPathTerm</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataT1PhysPathTerm>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:lineNo>1</es:lineNo>
+<es:loopback>0</es:loopback>
+<es:rdiReporting>false</es:rdiReporting>
+<es:aisReporting>false</es:aisReporting>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+<es:idlePattern>0</es:idlePattern>
+<es:transmissionMode>0</es:transmissionMode>
+</es:vsDataT1PhysPathTerm>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer><xn:VsDataContainer id="ta1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataEtMfg</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataEtMfg>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataEtMfg></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="ta1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataEtMfg</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataEtMfg>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataEtMfg>
+</xn:attributes>
+<xn:VsDataContainer id="ta1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGigaBitEthernet</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGigaBitEthernet>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:dscpPbitMap></es:dscpPbitMap>
+<es:autoNegotiation>true</es:autoNegotiation>
+<es:frameFormat>0</es:frameFormat>
+<es:primaryLink>0</es:primaryLink>
+<es:protectiveMode>true</es:protectiveMode>
+<es:shutDownTimeout>1800</es:shutDownTimeout>
+<es:statePropagationDelay>25</es:statePropagationDelay>
+<es:switchBackTimer>30</es:switchBackTimer>
+</es:vsDataGigaBitEthernet>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer><xn:VsDataContainer id="ta1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGeneralProcessorUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataGeneralProcessorUnit>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataGeneralProcessorUnit></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="ta1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataGeneralProcessorUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGeneralProcessorUnit>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataGeneralProcessorUnit>
+</xn:attributes>
+<xn:VsDataContainer id="ta1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataFastEthernet</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataFastEthernet>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel> </es:userLabel>
+<es:defaultRouter> </es:defaultRouter>
+<es:mtu>1500</es:mtu>
+<es:networkPrefixLength>0</es:networkPrefixLength>
+</es:vsDataFastEthernet>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="ta1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataMediumAccessUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataMediumAccessUnit>
+
+<es:userLabel> </es:userLabel>
+<es:connectorLabel>Eth</es:connectorLabel>
+</es:vsDataMediumAccessUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="11" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="12" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="13" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="14" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="15" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="16" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="17" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="18" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="19" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="20" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="21" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="22" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="23" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="24" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="25" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="26" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="27" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="28" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSlot</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSlot />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPlugInUnit</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPlugInUnit>
+
+<es:administrativeState>0</es:administrativeState>
+<es:allowedSeqRestarts>3</es:allowedSeqRestarts>
+<es:piuGroupNumber>0</es:piuGroupNumber>
+<es:piuType>0</es:piuType>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataPlugInUnit>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSystemFunctions</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataSystemFunctions />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataPmService</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPmService>
+
+<es:minorAlarmCeasingDelta>5</es:minorAlarmCeasingDelta>
+<es:warningAlarmLimitPercent>80</es:warningAlarmLimitPercent>
+<es:warningAlarmCeasingDelta>5</es:warningAlarmCeasingDelta>
+</es:vsDataPmService>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataLicensing</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataLicensing />
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataRncFeature</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataRncFeature>
+
+<es:featureState>0</es:featureState>
+
+
+
+
+</es:vsDataRncFeature>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataIpOam</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIpOam>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataIpOam>
+</xn:attributes><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataIp>
+
+<es:dnsServer>127.0.0.1</es:dnsServer>
+<es:isRecursiveSearch>true</es:isRecursiveSearch>
+<es:isSubDomainName>true</es:isSubDomainName>
+<es:userLabel> </es:userLabel>
+<es:retransInterval>4</es:retransInterval>
+<es:noOfRetrans>5</es:noOfRetrans>
+<es:isDefDomainName>false</es:isDefDomainName>
+<es:defDomainName> </es:defDomainName>
+<es:useHostFile>true</es:useHostFile>
+<es:dscp>0</es:dscp>
+<es:icmpRedirect>true</es:icmpRedirect>
+<es:udpChecksumState>1</es:udpChecksumState>
+<es:connectionAttemptTimer>75</es:connectionAttemptTimer>
+<es:maxRetransmissionAttempts>10</es:maxRetransmissionAttempts>
+<es:workingMode>0</es:workingMode>
+</es:vsDataIp></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataIp</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIp>
+
+<es:dnsServer>127.0.0.1</es:dnsServer>
+<es:isRecursiveSearch>true</es:isRecursiveSearch>
+<es:isSubDomainName>true</es:isSubDomainName>
+<es:userLabel> </es:userLabel>
+<es:retransInterval>4</es:retransInterval>
+<es:noOfRetrans>5</es:noOfRetrans>
+<es:isDefDomainName>false</es:isDefDomainName>
+<es:defDomainName> </es:defDomainName>
+<es:useHostFile>true</es:useHostFile>
+<es:dscp>0</es:dscp>
+<es:icmpRedirect>true</es:icmpRedirect>
+<es:udpChecksumState>1</es:udpChecksumState>
+<es:connectionAttemptTimer>75</es:connectionAttemptTimer>
+<es:maxRetransmissionAttempts>10</es:maxRetransmissionAttempts>
+<es:workingMode>0</es:workingMode>
+</es:vsDataIp>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataIpRoutingTable</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIpRoutingTable>
+
+
+<es:userLabel> </es:userLabel>
+</es:vsDataIpRoutingTable>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataEthernetLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataEthernetLink>
+
+<es:ipAddress> </es:ipAddress>
+<es:subnetMask> </es:subnetMask>
+<es:broadcastAddress> </es:broadcastAddress>
+
+
+<es:metric>1</es:metric>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataEthernetLink>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIpAtmLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIpAtmLink>
+
+
+<es:ipAddress> </es:ipAddress>
+<es:metric>1</es:metric>
+<es:monitor>true</es:monitor>
+<es:monitorInterval>10</es:monitorInterval>
+<es:monitorRetries>10</es:monitorRetries>
+<es:mtuSize>1500</es:mtuSize>
+<es:subnetMask> </es:subnetMask>
+<es:userLabel> </es:userLabel>
+<es:aal5TpVccTpId>0</es:aal5TpVccTpId>
+</es:vsDataIpAtmLink>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1-1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIpAtmLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIpAtmLink>
+
+
+<es:ipAddress> </es:ipAddress>
+<es:metric>1</es:metric>
+<es:monitor>true</es:monitor>
+<es:monitorInterval>10</es:monitorInterval>
+<es:monitorRetries>10</es:monitorRetries>
+<es:mtuSize>1500</es:mtuSize>
+<es:subnetMask> </es:subnetMask>
+<es:userLabel> </es:userLabel>
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b1-x1</es:aal5TpVccTpId>
+</es:vsDataIpAtmLink>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1-2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIpAtmLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIpAtmLink>
+
+
+<es:ipAddress> </es:ipAddress>
+<es:metric>1</es:metric>
+<es:monitor>true</es:monitor>
+<es:monitorInterval>10</es:monitorInterval>
+<es:monitorRetries>10</es:monitorRetries>
+<es:mtuSize>1500</es:mtuSize>
+<es:subnetMask> </es:subnetMask>
+<es:userLabel> </es:userLabel>
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b1-x2</es:aal5TpVccTpId>
+</es:vsDataIpAtmLink>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2-1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIpAtmLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIpAtmLink>
+
+
+<es:ipAddress> </es:ipAddress>
+<es:metric>1</es:metric>
+<es:monitor>true</es:monitor>
+<es:monitorInterval>10</es:monitorInterval>
+<es:monitorRetries>10</es:monitorRetries>
+<es:mtuSize>1500</es:mtuSize>
+<es:subnetMask> </es:subnetMask>
+<es:userLabel> </es:userLabel>
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b2-x1</es:aal5TpVccTpId>
+</es:vsDataIpAtmLink>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2-2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIpAtmLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIpAtmLink>
+
+
+<es:ipAddress> </es:ipAddress>
+<es:metric>1</es:metric>
+<es:monitor>true</es:monitor>
+<es:monitorInterval>10</es:monitorInterval>
+<es:monitorRetries>10</es:monitorRetries>
+<es:mtuSize>1500</es:mtuSize>
+<es:subnetMask> </es:subnetMask>
+<es:userLabel> </es:userLabel>
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b2-x2</es:aal5TpVccTpId>
+</es:vsDataIpAtmLink>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3-1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIpAtmLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIpAtmLink>
+
+
+<es:ipAddress> </es:ipAddress>
+<es:metric>1</es:metric>
+<es:monitor>true</es:monitor>
+<es:monitorInterval>10</es:monitorInterval>
+<es:monitorRetries>10</es:monitorRetries>
+<es:mtuSize>1500</es:mtuSize>
+<es:subnetMask> </es:subnetMask>
+<es:userLabel> </es:userLabel>
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b3-x1</es:aal5TpVccTpId>
+</es:vsDataIpAtmLink>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3-2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIpAtmLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIpAtmLink>
+
+
+<es:ipAddress> </es:ipAddress>
+<es:metric>1</es:metric>
+<es:monitor>true</es:monitor>
+<es:monitorInterval>10</es:monitorInterval>
+<es:monitorRetries>10</es:monitorRetries>
+<es:mtuSize>1500</es:mtuSize>
+<es:subnetMask> </es:subnetMask>
+<es:userLabel> </es:userLabel>
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b3-x2</es:aal5TpVccTpId>
+</es:vsDataIpAtmLink>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4-1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIpAtmLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIpAtmLink>
+
+
+<es:ipAddress> </es:ipAddress>
+<es:metric>1</es:metric>
+<es:monitor>true</es:monitor>
+<es:monitorInterval>10</es:monitorInterval>
+<es:monitorRetries>10</es:monitorRetries>
+<es:mtuSize>1500</es:mtuSize>
+<es:subnetMask> </es:subnetMask>
+<es:userLabel> </es:userLabel>
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b4-x1</es:aal5TpVccTpId>
+</es:vsDataIpAtmLink>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4-2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIpAtmLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIpAtmLink>
+
+
+<es:ipAddress> </es:ipAddress>
+<es:metric>1</es:metric>
+<es:monitor>true</es:monitor>
+<es:monitorInterval>10</es:monitorInterval>
+<es:monitorRetries>10</es:monitorRetries>
+<es:mtuSize>1500</es:mtuSize>
+<es:subnetMask> </es:subnetMask>
+<es:userLabel> </es:userLabel>
+<es:aal5TpVccTpId>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataAal5TpVccTp=b4-x2</es:aal5TpVccTpId>
+</es:vsDataIpAtmLink>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataOspf</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataOspf>
+
+<es:ipMo>0</es:ipMo>
+<es:ospfASBdrRtrStatus>false</es:ospfASBdrRtrStatus>
+
+<es:ospfRouterId> </es:ospfRouterId>
+<es:recoverTopoDb>true</es:recoverTopoDb>
+<es:topoDbStoreInterv>60</es:topoDbStoreInterv>
+<es:userLabel> </es:userLabel>
+<es:administrativeState>0</es:administrativeState>
+</es:vsDataOspf></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataOspf</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataOspf>
+
+<es:ipMo>0</es:ipMo>
+<es:ospfASBdrRtrStatus>false</es:ospfASBdrRtrStatus>
+
+<es:ospfRouterId> </es:ospfRouterId>
+<es:recoverTopoDb>true</es:recoverTopoDb>
+<es:topoDbStoreInterv>60</es:topoDbStoreInterv>
+<es:userLabel> </es:userLabel>
+<es:administrativeState>0</es:administrativeState>
+</es:vsDataOspf>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataOspfInterface</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataOspfInterface>
+
+<es:helloInterval>10</es:helloInterval>
+<es:interfacePriority>1</es:interfacePriority>
+<es:interfaceTransitDelay>1</es:interfaceTransitDelay>
+<es:lsaTransmissionInterval>5</es:lsaTransmissionInterval>
+<es:ospfAreaRelated>0</es:ospfAreaRelated>
+<es:relatedLink>0</es:relatedLink>
+<es:routerDeadInterval>40</es:routerDeadInterval>
+<es:userLabel> </es:userLabel>
+</es:vsDataOspfInterface>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataOspfArea</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataOspfArea>
+
+<es:areaId> </es:areaId>
+
+<es:importExternalLsa>true</es:importExternalLsa>
+<es:sendAreaSummary>false</es:sendAreaSummary>
+<es:stubArea>false</es:stubArea>
+<es:stubAreaMetric>1</es:stubAreaMetric>
+<es:stubAreaMetricType>0</es:stubAreaMetricType>
+<es:userLabel> </es:userLabel>
+<es:range0>
+<es:ipAddress></es:ipAddress>
+<es:subnetMask></es:subnetMask>
+<es:advertise>true</es:advertise></es:range0>
+
+
+</es:vsDataOspfArea>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<un:RncFunction id="1" modifier="update">
+<un:attributes>
+
+<un:userLabel>/proj/netsimproj/public/ftp/simulations/WRAN/R5/Standard/E/V2</un:userLabel>
+<un:mcc>353</un:mcc>
+<un:mnc>77</un:mnc>
+<un:rncId>1</un:rncId>
+</un:attributes>
+
+<un:IubLink id="1" modifier="create">
+<un:attributes>
+
+</un:attributes>
+</un:IubLink>
+
+<un:IubLink id="1" modifier="update">
+
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataIubLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIubLink>
+
+<es:rbsId>1</es:rbsId>
+<es:dlHwAdm>100</es:dlHwAdm>
+<es:ulHwAdm>100</es:ulHwAdm>
+
+<es:preferredSubrackRef>0</es:preferredSubrackRef>
+<es:userPlaneTransportOption>
+<es:atm>0</es:atm>
+<es:ipv4>0</es:ipv4></es:userPlaneTransportOption>
+</es:vsDataIubLink>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataNodeSynch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataNodeSynch>
+
+<es:userLabel> </es:userLabel>
+<es:phaseDiffThreshold>100</es:phaseDiffThreshold>
+
+
+<es:sampleIntervalSup>10</es:sampleIntervalSup>
+<es:fixedWindowSizeSup>10</es:fixedWindowSizeSup>
+<es:slidingWindowSize>100</es:slidingWindowSize>
+</es:vsDataNodeSynch>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataNbapCommon</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataNbapCommon>
+
+<es:userLabel> </es:userLabel>
+<es:l2EstablishReqRetryT>5</es:l2EstablishReqRetryT>
+<es:activeUniSaalTpRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b1ca</es:activeUniSaalTpRef>
+<es:standbyUniSaalTpRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b1cb</es:standbyUniSaalTpRef>
+<es:administrativeState>0</es:administrativeState>
+</es:vsDataNbapCommon>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataNbapDedicated</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataNbapDedicated>
+
+<es:l2EstablishReqRetryT>5</es:l2EstablishReqRetryT>
+<es:activeUniSaalTpRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b1da</es:activeUniSaalTpRef>
+<es:standbyUniSaalTpRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b1db</es:standbyUniSaalTpRef>
+<es:userLabel> </es:userLabel>
+<es:administrativeState>0</es:administrativeState>
+</es:vsDataNbapDedicated>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIubEdch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIubEdch>
+
+<es:edchDataFrameDelayThreshold>60</es:edchDataFrameDelayThreshold>
+</es:vsDataIubEdch>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer></un:IubLink>
+<un:IubLink id="2" modifier="create">
+<un:attributes>
+
+</un:attributes>
+</un:IubLink>
+
+<un:IubLink id="2" modifier="update">
+
+<xn:VsDataContainer id="2" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataIubLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIubLink>
+
+<es:rbsId>2</es:rbsId>
+<es:dlHwAdm>100</es:dlHwAdm>
+<es:ulHwAdm>100</es:ulHwAdm>
+
+<es:preferredSubrackRef>0</es:preferredSubrackRef>
+<es:userPlaneTransportOption>
+<es:atm>0</es:atm>
+<es:ipv4>0</es:ipv4></es:userPlaneTransportOption>
+</es:vsDataIubLink>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataNodeSynch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataNodeSynch>
+
+<es:userLabel> </es:userLabel>
+<es:phaseDiffThreshold>100</es:phaseDiffThreshold>
+
+
+<es:sampleIntervalSup>10</es:sampleIntervalSup>
+<es:fixedWindowSizeSup>10</es:fixedWindowSizeSup>
+<es:slidingWindowSize>100</es:slidingWindowSize>
+</es:vsDataNodeSynch>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataNbapCommon</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataNbapCommon>
+
+<es:userLabel> </es:userLabel>
+<es:l2EstablishReqRetryT>5</es:l2EstablishReqRetryT>
+<es:activeUniSaalTpRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b2ca</es:activeUniSaalTpRef>
+<es:standbyUniSaalTpRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b2cb</es:standbyUniSaalTpRef>
+<es:administrativeState>0</es:administrativeState>
+</es:vsDataNbapCommon>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataNbapDedicated</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataNbapDedicated>
+
+<es:l2EstablishReqRetryT>5</es:l2EstablishReqRetryT>
+<es:activeUniSaalTpRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b2da</es:activeUniSaalTpRef>
+<es:standbyUniSaalTpRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b2db</es:standbyUniSaalTpRef>
+<es:userLabel> </es:userLabel>
+<es:administrativeState>0</es:administrativeState>
+</es:vsDataNbapDedicated>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIubEdch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIubEdch>
+
+<es:edchDataFrameDelayThreshold>60</es:edchDataFrameDelayThreshold>
+</es:vsDataIubEdch>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer></un:IubLink>
+<un:IubLink id="3" modifier="create">
+<un:attributes>
+
+</un:attributes>
+</un:IubLink>
+
+<un:IubLink id="3" modifier="update">
+
+<xn:VsDataContainer id="3" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataIubLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIubLink>
+
+<es:rbsId>3</es:rbsId>
+<es:dlHwAdm>100</es:dlHwAdm>
+<es:ulHwAdm>100</es:ulHwAdm>
+
+<es:preferredSubrackRef>0</es:preferredSubrackRef>
+<es:userPlaneTransportOption>
+<es:atm>0</es:atm>
+<es:ipv4>0</es:ipv4></es:userPlaneTransportOption>
+</es:vsDataIubLink>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataNodeSynch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataNodeSynch>
+
+<es:userLabel> </es:userLabel>
+<es:phaseDiffThreshold>100</es:phaseDiffThreshold>
+
+
+<es:sampleIntervalSup>10</es:sampleIntervalSup>
+<es:fixedWindowSizeSup>10</es:fixedWindowSizeSup>
+<es:slidingWindowSize>100</es:slidingWindowSize>
+</es:vsDataNodeSynch>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataNbapCommon</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataNbapCommon>
+
+<es:userLabel> </es:userLabel>
+<es:l2EstablishReqRetryT>5</es:l2EstablishReqRetryT>
+<es:activeUniSaalTpRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b3ca</es:activeUniSaalTpRef>
+<es:standbyUniSaalTpRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b3cb</es:standbyUniSaalTpRef>
+<es:administrativeState>0</es:administrativeState>
+</es:vsDataNbapCommon>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataNbapDedicated</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataNbapDedicated>
+
+<es:l2EstablishReqRetryT>5</es:l2EstablishReqRetryT>
+<es:activeUniSaalTpRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b3da</es:activeUniSaalTpRef>
+<es:standbyUniSaalTpRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b3db</es:standbyUniSaalTpRef>
+<es:userLabel> </es:userLabel>
+<es:administrativeState>0</es:administrativeState>
+</es:vsDataNbapDedicated>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIubEdch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIubEdch>
+
+<es:edchDataFrameDelayThreshold>60</es:edchDataFrameDelayThreshold>
+</es:vsDataIubEdch>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer></un:IubLink>
+<un:IubLink id="4" modifier="create">
+<un:attributes>
+
+</un:attributes>
+</un:IubLink>
+
+<un:IubLink id="4" modifier="update">
+
+<xn:VsDataContainer id="4" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataIubLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIubLink>
+
+<es:rbsId>4</es:rbsId>
+<es:dlHwAdm>100</es:dlHwAdm>
+<es:ulHwAdm>100</es:ulHwAdm>
+
+<es:preferredSubrackRef>0</es:preferredSubrackRef>
+<es:userPlaneTransportOption>
+<es:atm>0</es:atm>
+<es:ipv4>0</es:ipv4></es:userPlaneTransportOption>
+</es:vsDataIubLink>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataNodeSynch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataNodeSynch>
+
+<es:userLabel> </es:userLabel>
+<es:phaseDiffThreshold>100</es:phaseDiffThreshold>
+
+
+<es:sampleIntervalSup>10</es:sampleIntervalSup>
+<es:fixedWindowSizeSup>10</es:fixedWindowSizeSup>
+<es:slidingWindowSize>100</es:slidingWindowSize>
+</es:vsDataNodeSynch>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataNbapCommon</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataNbapCommon>
+
+<es:userLabel> </es:userLabel>
+<es:l2EstablishReqRetryT>5</es:l2EstablishReqRetryT>
+<es:activeUniSaalTpRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b4ca</es:activeUniSaalTpRef>
+<es:standbyUniSaalTpRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b4cb</es:standbyUniSaalTpRef>
+<es:administrativeState>0</es:administrativeState>
+</es:vsDataNbapCommon>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataNbapDedicated</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataNbapDedicated>
+
+<es:l2EstablishReqRetryT>5</es:l2EstablishReqRetryT>
+<es:activeUniSaalTpRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b4da</es:activeUniSaalTpRef>
+<es:standbyUniSaalTpRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,vsDataTransportNetwork=1,vsDataUniSaalTp=b4db</es:standbyUniSaalTpRef>
+<es:userLabel> </es:userLabel>
+<es:administrativeState>0</es:administrativeState>
+</es:vsDataNbapDedicated>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIubEdch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIubEdch>
+
+<es:edchDataFrameDelayThreshold>60</es:edchDataFrameDelayThreshold>
+</es:vsDataIubEdch>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer></un:IubLink>
+<un:UtranCell id="RNC01-1-1" modifier="create">
+<un:attributes>
+
+<un:userLabel>RNC01-1-1</un:userLabel>
+<un:cId>1</un:cId>
+<un:localCellId>1</un:localCellId>
+<un:uarfcnUl>12</un:uarfcnUl>
+<un:uarfcnDl>5</un:uarfcnDl>
+<un:primaryScramblingCode>1</un:primaryScramblingCode>
+<un:primaryCpichPower>300</un:primaryCpichPower>
+<un:maximumTransmissionPower>400</un:maximumTransmissionPower>
+<un:primarySchPower>-18</un:primarySchPower>
+<un:secondarySchPower>-35</un:secondarySchPower>
+<un:bchPower>-31</un:bchPower>
+<un:utranCellIubLink>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=1</un:utranCellIubLink>
+<un:lac>3417</un:lac>
+<un:rac>3418</un:rac>
+<un:sac>3419</un:sac>
+</un:attributes>
+</un:UtranCell>
+
+<un:UtranCell id="RNC01-1-1" modifier="update">
+
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>1</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>2</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>3</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>4</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>5</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>6</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>7</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>8</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>9</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>10</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="11" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>11</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="12" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>12</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="13" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>13</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="14" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>14</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="15" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>15</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="16" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>16</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="17" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>17</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="18" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>18</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="19" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>19</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="20" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>20</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="21" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>21</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="22" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>22</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="23" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>23</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="24" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>24</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="25" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>25</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="26" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>26</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="27" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>27</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="28" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>28</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="29" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>29</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="30" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>30</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>31</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=1</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>32</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=2</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>33</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=3</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>34</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=4</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>35</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=5</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>36</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=6</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>37</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=7</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>38</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=8</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>39</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=9</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>40</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50101</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RNC01-1-1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranCell</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranCell>
+
+<es:tCell>1</es:tCell>
+<es:cellReserved>1</es:cellReserved>
+<es:treSelection>2</es:treSelection>
+<es:qualMeasQuantity>2</es:qualMeasQuantity>
+<es:qHyst1>4</es:qHyst1>
+<es:qHyst2>4</es:qHyst2>
+<es:qQualMin>-24</es:qQualMin>
+<es:qRxLevMin>-115</es:qRxLevMin>
+<es:individualOffset>0</es:individualOffset>
+<es:pwrAdm>75</es:pwrAdm>
+<es:pwrOffset>5</es:pwrOffset>
+<es:pwrHyst>300</es:pwrHyst>
+<es:tmCongAction>2000</es:tmCongAction>
+<es:releaseAseDl>1</es:releaseAseDl>
+<es:aseDlAdm>240</es:aseDlAdm>
+<es:dlCodeAdm>80</es:dlCodeAdm>
+<es:aseUlAdm>160</es:aseUlAdm>
+<es:sf8Adm>8</es:sf8Adm>
+<es:sf32Adm>32</es:sf32Adm>
+<es:minPwrRl>-150</es:minPwrRl>
+<es:maxRate>40690</es:maxRate>
+<es:interRate>7760</es:interRate>
+<es:minimumRate>1590</es:minimumRate>
+<es:maxPwrMax>48</es:maxPwrMax>
+<es:interPwrMax>38</es:interPwrMax>
+<es:minPwrMax>0</es:minPwrMax>
+<es:compModeAdm>15</es:compModeAdm>
+<es:iFHyst>6000</es:iFHyst>
+<es:iFCong>621</es:iFCong>
+<es:interFreqFddMeasIndicator>0</es:interFreqFddMeasIndicator>
+<es:sRatSearch>4</es:sRatSearch>
+<es:sIntraSearch>0</es:sIntraSearch>
+<es:sInterSearch>0</es:sInterSearch>
+<es:fachMeasOccaCycLenCoeff>0</es:fachMeasOccaCycLenCoeff>
+
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:utranCellPosition></es:utranCellPosition>
+<es:maxTxPowerUl>24</es:maxTxPowerUl>
+
+<es:sib1PlmnScopeValueTag>0</es:sib1PlmnScopeValueTag>
+<es:sf16Adm>16</es:sf16Adm>
+<es:hoType>1</es:hoType>
+<es:usedFreqThresh2dEcno>-12</es:usedFreqThresh2dEcno>
+<es:usedFreqThresh2dRscp>-97</es:usedFreqThresh2dRscp>
+<es:administrativeState>0</es:administrativeState>
+<es:loadSharingGsmThreshold>75</es:loadSharingGsmThreshold>
+<es:loadSharingGsmFraction>100</es:loadSharingGsmFraction>
+<es:nInSyncInd>3</es:nInSyncInd>
+<es:rlFailureT>10</es:rlFailureT>
+<es:nOutSyncInd>10</es:nOutSyncInd>
+<es:sf4AdmUl>0</es:sf4AdmUl>
+<es:hardIfhoCorr>3</es:hardIfhoCorr>
+<es:hsdpaUsersAdm>10</es:hsdpaUsersAdm>
+<es:loadSharingMargin>0</es:loadSharingMargin>
+<es:sHcsRat>-105</es:sHcsRat>
+<es:sf16gAdm>16</es:sf16gAdm>
+<es:releaseAseDlNg>3</es:releaseAseDlNg>
+<es:tmCongActionNg>800</es:tmCongActionNg>
+<es:tmInitialG>3000</es:tmInitialG>
+<es:sf16AdmUl>16</es:sf16AdmUl>
+<es:sf8AdmUl>8</es:sf8AdmUl>
+<es:sf8gAdmUl>0</es:sf8gAdmUl>
+<es:iubLinkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=1</es:iubLinkRef>
+<es:eulNonServingCellUsersAdm>100</es:eulNonServingCellUsersAdm>
+<es:eulServingCellUsersAdm>32</es:eulServingCellUsersAdm>
+<es:agpsEnabled>1</es:agpsEnabled>
+<es:codeLoadThresholdDlSf128>100</es:codeLoadThresholdDlSf128>
+<es:pwrLoadThresholdDlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:pwrLoadThresholdDlSpeech>
+<es:aseLoadThresholdUlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:aseLoadThresholdUlSpeech>
+
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:rateSelectionPsInteractive>
+<es:channelType>0</es:channelType>
+<es:ulPrefRate>64</es:ulPrefRate>
+<es:dlPrefRate>64</es:dlPrefRate></es:rateSelectionPsInteractive>
+<es:hcsUsage>
+<es:idleMode>0</es:idleMode>
+<es:connectedMode>0</es:connectedMode></es:hcsUsage>
+<es:hcsSib3Config>
+<es:sSearchHcs>-105</es:sSearchHcs>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs></es:hcsSib3Config>
+</es:vsDataUtranCell>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataFach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataFach>
+
+<es:userLabel>Fach-1-1</es:userLabel>
+<es:maxFach1Power>18</es:maxFach1Power>
+<es:maxFach2Power>15</es:maxFach2Power>
+<es:sccpchOffset>0</es:sccpchOffset>
+<es:pOffset1Fach>0</es:pOffset1Fach>
+<es:pOffset3Fach>0</es:pOffset3Fach>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataFach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataRach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataRach>
+
+<es:userLabel>Rach-1-1</es:userLabel>
+<es:scramblingCodeWordNo>0</es:scramblingCodeWordNo>
+<es:preambleSignatures>65535</es:preambleSignatures>
+<es:subChannelNo>4095</es:subChannelNo>
+<es:aichTransmissionTiming>4</es:aichTransmissionTiming>
+<es:aichPower>-6</es:aichPower>
+<es:powerOffsetP0>3</es:powerOffsetP0>
+<es:powerOffsetPpm>-4</es:powerOffsetPpm>
+<es:preambleRetransMax>5</es:preambleRetransMax>
+<es:maxPreambleCycle>4</es:maxPreambleCycle>
+<es:constantValueCprach>-27</es:constantValueCprach>
+<es:spreadingFactor>64</es:spreadingFactor>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataRach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPch>
+
+<es:userLabel>Pch-1-1</es:userLabel>
+<es:pchPower>-4</es:pchPower>
+<es:pichPower>-7</es:pichPower>
+<es:sccpchOffset>20</es:sccpchOffset>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataPch>
+</xn:attributes>
+</xn:VsDataContainer><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-1-1</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-1-1</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataEul</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataEul>
+
+<es:userLabel>Eul-1-1</es:userLabel>
+<es:administrativeState>0</es:administrativeState>
+<es:numEagchCodes>1</es:numEagchCodes>
+<es:numEhichErgchCodes>1</es:numEhichErgchCodes>
+<es:eulMaxTargetRtwp>-499</es:eulMaxTargetRtwp>
+</es:vsDataEul>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataCoverageRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataCoverageRelation>
+
+<es:utranCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,UtranCell=RNC01-1-2</es:utranCellRef>
+<es:coverageIndicator>1</es:coverageIndicator>
+<es:hsPathlossThreshold>170</es:hsPathlossThreshold>
+</es:vsDataCoverageRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer></un:UtranCell>
+<un:UtranCell id="RNC01-1-2" modifier="create">
+<un:attributes>
+
+<un:userLabel>RNC01-1-2</un:userLabel>
+<un:cId>2</un:cId>
+<un:localCellId>2</un:localCellId>
+<un:uarfcnUl>12</un:uarfcnUl>
+<un:uarfcnDl>5</un:uarfcnDl>
+<un:primaryScramblingCode>2</un:primaryScramblingCode>
+<un:primaryCpichPower>300</un:primaryCpichPower>
+<un:maximumTransmissionPower>400</un:maximumTransmissionPower>
+<un:primarySchPower>-18</un:primarySchPower>
+<un:secondarySchPower>-35</un:secondarySchPower>
+<un:bchPower>-31</un:bchPower>
+<un:utranCellIubLink>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=1</un:utranCellIubLink>
+<un:lac>3417</un:lac>
+<un:rac>3418</un:rac>
+<un:sac>3420</un:sac>
+</un:attributes>
+</un:UtranCell>
+
+<un:UtranCell id="RNC01-1-2" modifier="update">
+
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>1</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>2</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>3</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>4</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>5</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>6</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>7</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>8</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>9</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>10</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="11" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>11</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="12" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>12</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="13" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>13</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="14" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>14</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="15" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>15</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="16" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>16</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="17" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>17</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="18" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>18</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="19" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>19</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="20" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>20</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="21" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>21</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="22" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>22</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="23" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>23</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="24" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>24</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="25" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>25</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="26" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>26</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="27" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>27</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="28" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>28</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="29" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>29</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="30" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>30</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>31</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50102</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>32</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50103</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>33</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=1</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>34</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=2</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>35</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=3</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>36</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=4</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>37</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=5</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>38</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=6</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>39</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=7</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>40</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=8</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RNC01-1-2" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranCell</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranCell>
+
+<es:tCell>2</es:tCell>
+<es:cellReserved>1</es:cellReserved>
+<es:treSelection>2</es:treSelection>
+<es:qualMeasQuantity>2</es:qualMeasQuantity>
+<es:qHyst1>4</es:qHyst1>
+<es:qHyst2>4</es:qHyst2>
+<es:qQualMin>-24</es:qQualMin>
+<es:qRxLevMin>-115</es:qRxLevMin>
+<es:individualOffset>0</es:individualOffset>
+<es:pwrAdm>75</es:pwrAdm>
+<es:pwrOffset>5</es:pwrOffset>
+<es:pwrHyst>300</es:pwrHyst>
+<es:tmCongAction>2000</es:tmCongAction>
+<es:releaseAseDl>1</es:releaseAseDl>
+<es:aseDlAdm>240</es:aseDlAdm>
+<es:dlCodeAdm>80</es:dlCodeAdm>
+<es:aseUlAdm>160</es:aseUlAdm>
+<es:sf8Adm>8</es:sf8Adm>
+<es:sf32Adm>32</es:sf32Adm>
+<es:minPwrRl>-150</es:minPwrRl>
+<es:maxRate>40690</es:maxRate>
+<es:interRate>7760</es:interRate>
+<es:minimumRate>1590</es:minimumRate>
+<es:maxPwrMax>48</es:maxPwrMax>
+<es:interPwrMax>38</es:interPwrMax>
+<es:minPwrMax>0</es:minPwrMax>
+<es:compModeAdm>15</es:compModeAdm>
+<es:iFHyst>6000</es:iFHyst>
+<es:iFCong>621</es:iFCong>
+<es:interFreqFddMeasIndicator>0</es:interFreqFddMeasIndicator>
+<es:sRatSearch>4</es:sRatSearch>
+<es:sIntraSearch>0</es:sIntraSearch>
+<es:sInterSearch>0</es:sInterSearch>
+<es:fachMeasOccaCycLenCoeff>0</es:fachMeasOccaCycLenCoeff>
+
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:utranCellPosition></es:utranCellPosition>
+<es:maxTxPowerUl>24</es:maxTxPowerUl>
+
+<es:sib1PlmnScopeValueTag>0</es:sib1PlmnScopeValueTag>
+<es:sf16Adm>16</es:sf16Adm>
+<es:hoType>1</es:hoType>
+<es:usedFreqThresh2dEcno>-12</es:usedFreqThresh2dEcno>
+<es:usedFreqThresh2dRscp>-97</es:usedFreqThresh2dRscp>
+<es:administrativeState>0</es:administrativeState>
+<es:loadSharingGsmThreshold>75</es:loadSharingGsmThreshold>
+<es:loadSharingGsmFraction>100</es:loadSharingGsmFraction>
+<es:nInSyncInd>3</es:nInSyncInd>
+<es:rlFailureT>10</es:rlFailureT>
+<es:nOutSyncInd>10</es:nOutSyncInd>
+<es:sf4AdmUl>0</es:sf4AdmUl>
+<es:hardIfhoCorr>3</es:hardIfhoCorr>
+<es:hsdpaUsersAdm>10</es:hsdpaUsersAdm>
+<es:loadSharingMargin>0</es:loadSharingMargin>
+<es:sHcsRat>-105</es:sHcsRat>
+<es:sf16gAdm>16</es:sf16gAdm>
+<es:releaseAseDlNg>3</es:releaseAseDlNg>
+<es:tmCongActionNg>800</es:tmCongActionNg>
+<es:tmInitialG>3000</es:tmInitialG>
+<es:sf16AdmUl>16</es:sf16AdmUl>
+<es:sf8AdmUl>8</es:sf8AdmUl>
+<es:sf8gAdmUl>0</es:sf8gAdmUl>
+<es:iubLinkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=1</es:iubLinkRef>
+<es:eulNonServingCellUsersAdm>100</es:eulNonServingCellUsersAdm>
+<es:eulServingCellUsersAdm>32</es:eulServingCellUsersAdm>
+<es:agpsEnabled>1</es:agpsEnabled>
+<es:codeLoadThresholdDlSf128>100</es:codeLoadThresholdDlSf128>
+<es:pwrLoadThresholdDlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:pwrLoadThresholdDlSpeech>
+<es:aseLoadThresholdUlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:aseLoadThresholdUlSpeech>
+
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:rateSelectionPsInteractive>
+<es:channelType>0</es:channelType>
+<es:ulPrefRate>64</es:ulPrefRate>
+<es:dlPrefRate>64</es:dlPrefRate></es:rateSelectionPsInteractive>
+<es:hcsUsage>
+<es:idleMode>0</es:idleMode>
+<es:connectedMode>0</es:connectedMode></es:hcsUsage>
+<es:hcsSib3Config>
+<es:sSearchHcs>-105</es:sSearchHcs>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs></es:hcsSib3Config>
+</es:vsDataUtranCell>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataFach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataFach>
+
+<es:userLabel>Fach-1-2</es:userLabel>
+<es:maxFach1Power>18</es:maxFach1Power>
+<es:maxFach2Power>15</es:maxFach2Power>
+<es:sccpchOffset>0</es:sccpchOffset>
+<es:pOffset1Fach>0</es:pOffset1Fach>
+<es:pOffset3Fach>0</es:pOffset3Fach>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataFach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataRach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataRach>
+
+<es:userLabel>Rach-1-2</es:userLabel>
+<es:scramblingCodeWordNo>0</es:scramblingCodeWordNo>
+<es:preambleSignatures>65535</es:preambleSignatures>
+<es:subChannelNo>4095</es:subChannelNo>
+<es:aichTransmissionTiming>4</es:aichTransmissionTiming>
+<es:aichPower>-6</es:aichPower>
+<es:powerOffsetP0>3</es:powerOffsetP0>
+<es:powerOffsetPpm>-4</es:powerOffsetPpm>
+<es:preambleRetransMax>5</es:preambleRetransMax>
+<es:maxPreambleCycle>4</es:maxPreambleCycle>
+<es:constantValueCprach>-27</es:constantValueCprach>
+<es:spreadingFactor>64</es:spreadingFactor>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataRach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPch>
+
+<es:userLabel>Pch-1-2</es:userLabel>
+<es:pchPower>-4</es:pchPower>
+<es:pichPower>-7</es:pichPower>
+<es:sccpchOffset>20</es:sccpchOffset>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataPch>
+</xn:attributes>
+</xn:VsDataContainer><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-1-2</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-1-2</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataEul</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataEul>
+
+<es:userLabel>Eul-1-2</es:userLabel>
+<es:administrativeState>0</es:administrativeState>
+<es:numEagchCodes>1</es:numEagchCodes>
+<es:numEhichErgchCodes>1</es:numEhichErgchCodes>
+<es:eulMaxTargetRtwp>-499</es:eulMaxTargetRtwp>
+</es:vsDataEul>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataCoverageRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataCoverageRelation>
+
+<es:utranCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,UtranCell=RNC01-1-3</es:utranCellRef>
+<es:coverageIndicator>1</es:coverageIndicator>
+<es:hsPathlossThreshold>170</es:hsPathlossThreshold>
+</es:vsDataCoverageRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer></un:UtranCell>
+<un:UtranCell id="RNC01-1-3" modifier="create">
+<un:attributes>
+
+<un:userLabel>RNC01-1-3</un:userLabel>
+<un:cId>3</un:cId>
+<un:localCellId>3</un:localCellId>
+<un:uarfcnUl>12</un:uarfcnUl>
+<un:uarfcnDl>5</un:uarfcnDl>
+<un:primaryScramblingCode>3</un:primaryScramblingCode>
+<un:primaryCpichPower>300</un:primaryCpichPower>
+<un:maximumTransmissionPower>400</un:maximumTransmissionPower>
+<un:primarySchPower>-18</un:primarySchPower>
+<un:secondarySchPower>-35</un:secondarySchPower>
+<un:bchPower>-31</un:bchPower>
+<un:utranCellIubLink>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=1</un:utranCellIubLink>
+<un:lac>3417</un:lac>
+<un:rac>3418</un:rac>
+<un:sac>3421</un:sac>
+</un:attributes>
+</un:UtranCell>
+
+<un:UtranCell id="RNC01-1-3" modifier="update">
+
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>1</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>2</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>3</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>4</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>5</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>6</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>7</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>8</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>9</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>10</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="11" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>11</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="12" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>12</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="13" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>13</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="14" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>14</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="15" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>15</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="16" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>16</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="17" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>17</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="18" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>18</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="19" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>19</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="20" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>20</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="21" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>21</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="22" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>22</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="23" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>23</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="24" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>24</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="25" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>25</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="26" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>26</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="27" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>27</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="28" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>28</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="29" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>29</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="30" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>30</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>31</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=9</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>32</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50101</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>33</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50102</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>34</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50103</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>35</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=1</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>36</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=2</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>37</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=3</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>38</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=4</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>39</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=5</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>40</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=6</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RNC01-1-3" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranCell</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranCell>
+
+<es:tCell>3</es:tCell>
+<es:cellReserved>1</es:cellReserved>
+<es:treSelection>2</es:treSelection>
+<es:qualMeasQuantity>2</es:qualMeasQuantity>
+<es:qHyst1>4</es:qHyst1>
+<es:qHyst2>4</es:qHyst2>
+<es:qQualMin>-24</es:qQualMin>
+<es:qRxLevMin>-115</es:qRxLevMin>
+<es:individualOffset>0</es:individualOffset>
+<es:pwrAdm>75</es:pwrAdm>
+<es:pwrOffset>5</es:pwrOffset>
+<es:pwrHyst>300</es:pwrHyst>
+<es:tmCongAction>2000</es:tmCongAction>
+<es:releaseAseDl>1</es:releaseAseDl>
+<es:aseDlAdm>240</es:aseDlAdm>
+<es:dlCodeAdm>80</es:dlCodeAdm>
+<es:aseUlAdm>160</es:aseUlAdm>
+<es:sf8Adm>8</es:sf8Adm>
+<es:sf32Adm>32</es:sf32Adm>
+<es:minPwrRl>-150</es:minPwrRl>
+<es:maxRate>40690</es:maxRate>
+<es:interRate>7760</es:interRate>
+<es:minimumRate>1590</es:minimumRate>
+<es:maxPwrMax>48</es:maxPwrMax>
+<es:interPwrMax>38</es:interPwrMax>
+<es:minPwrMax>0</es:minPwrMax>
+<es:compModeAdm>15</es:compModeAdm>
+<es:iFHyst>6000</es:iFHyst>
+<es:iFCong>621</es:iFCong>
+<es:interFreqFddMeasIndicator>0</es:interFreqFddMeasIndicator>
+<es:sRatSearch>4</es:sRatSearch>
+<es:sIntraSearch>0</es:sIntraSearch>
+<es:sInterSearch>0</es:sInterSearch>
+<es:fachMeasOccaCycLenCoeff>0</es:fachMeasOccaCycLenCoeff>
+
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:utranCellPosition></es:utranCellPosition>
+<es:maxTxPowerUl>24</es:maxTxPowerUl>
+
+<es:sib1PlmnScopeValueTag>0</es:sib1PlmnScopeValueTag>
+<es:sf16Adm>16</es:sf16Adm>
+<es:hoType>1</es:hoType>
+<es:usedFreqThresh2dEcno>-12</es:usedFreqThresh2dEcno>
+<es:usedFreqThresh2dRscp>-97</es:usedFreqThresh2dRscp>
+<es:administrativeState>0</es:administrativeState>
+<es:loadSharingGsmThreshold>75</es:loadSharingGsmThreshold>
+<es:loadSharingGsmFraction>100</es:loadSharingGsmFraction>
+<es:nInSyncInd>3</es:nInSyncInd>
+<es:rlFailureT>10</es:rlFailureT>
+<es:nOutSyncInd>10</es:nOutSyncInd>
+<es:sf4AdmUl>0</es:sf4AdmUl>
+<es:hardIfhoCorr>3</es:hardIfhoCorr>
+<es:hsdpaUsersAdm>10</es:hsdpaUsersAdm>
+<es:loadSharingMargin>0</es:loadSharingMargin>
+<es:sHcsRat>-105</es:sHcsRat>
+<es:sf16gAdm>16</es:sf16gAdm>
+<es:releaseAseDlNg>3</es:releaseAseDlNg>
+<es:tmCongActionNg>800</es:tmCongActionNg>
+<es:tmInitialG>3000</es:tmInitialG>
+<es:sf16AdmUl>16</es:sf16AdmUl>
+<es:sf8AdmUl>8</es:sf8AdmUl>
+<es:sf8gAdmUl>0</es:sf8gAdmUl>
+<es:iubLinkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=1</es:iubLinkRef>
+<es:eulNonServingCellUsersAdm>100</es:eulNonServingCellUsersAdm>
+<es:eulServingCellUsersAdm>32</es:eulServingCellUsersAdm>
+<es:agpsEnabled>1</es:agpsEnabled>
+<es:codeLoadThresholdDlSf128>100</es:codeLoadThresholdDlSf128>
+<es:pwrLoadThresholdDlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:pwrLoadThresholdDlSpeech>
+<es:aseLoadThresholdUlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:aseLoadThresholdUlSpeech>
+
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:rateSelectionPsInteractive>
+<es:channelType>0</es:channelType>
+<es:ulPrefRate>64</es:ulPrefRate>
+<es:dlPrefRate>64</es:dlPrefRate></es:rateSelectionPsInteractive>
+<es:hcsUsage>
+<es:idleMode>0</es:idleMode>
+<es:connectedMode>0</es:connectedMode></es:hcsUsage>
+<es:hcsSib3Config>
+<es:sSearchHcs>-105</es:sSearchHcs>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs></es:hcsSib3Config>
+</es:vsDataUtranCell>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataFach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataFach>
+
+<es:userLabel>Fach-1-3</es:userLabel>
+<es:maxFach1Power>18</es:maxFach1Power>
+<es:maxFach2Power>15</es:maxFach2Power>
+<es:sccpchOffset>0</es:sccpchOffset>
+<es:pOffset1Fach>0</es:pOffset1Fach>
+<es:pOffset3Fach>0</es:pOffset3Fach>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataFach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataRach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataRach>
+
+<es:userLabel>Rach-1-3</es:userLabel>
+<es:scramblingCodeWordNo>0</es:scramblingCodeWordNo>
+<es:preambleSignatures>65535</es:preambleSignatures>
+<es:subChannelNo>4095</es:subChannelNo>
+<es:aichTransmissionTiming>4</es:aichTransmissionTiming>
+<es:aichPower>-6</es:aichPower>
+<es:powerOffsetP0>3</es:powerOffsetP0>
+<es:powerOffsetPpm>-4</es:powerOffsetPpm>
+<es:preambleRetransMax>5</es:preambleRetransMax>
+<es:maxPreambleCycle>4</es:maxPreambleCycle>
+<es:constantValueCprach>-27</es:constantValueCprach>
+<es:spreadingFactor>64</es:spreadingFactor>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataRach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPch>
+
+<es:userLabel>Pch-1-3</es:userLabel>
+<es:pchPower>-4</es:pchPower>
+<es:pichPower>-7</es:pichPower>
+<es:sccpchOffset>20</es:sccpchOffset>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataPch>
+</xn:attributes>
+</xn:VsDataContainer><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-1-3</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-1-3</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataEul</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataEul>
+
+<es:userLabel>Eul-1-3</es:userLabel>
+<es:administrativeState>0</es:administrativeState>
+<es:numEagchCodes>1</es:numEagchCodes>
+<es:numEhichErgchCodes>1</es:numEhichErgchCodes>
+<es:eulMaxTargetRtwp>-499</es:eulMaxTargetRtwp>
+</es:vsDataEul>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataCoverageRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataCoverageRelation>
+
+<es:utranCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,UtranCell=RNC01-1-1</es:utranCellRef>
+<es:coverageIndicator>1</es:coverageIndicator>
+<es:hsPathlossThreshold>170</es:hsPathlossThreshold>
+</es:vsDataCoverageRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer></un:UtranCell>
+<un:UtranCell id="RNC01-2-1" modifier="create">
+<un:attributes>
+
+<un:userLabel>RNC01-2-1</un:userLabel>
+<un:cId>4</un:cId>
+<un:localCellId>1</un:localCellId>
+<un:uarfcnUl>12</un:uarfcnUl>
+<un:uarfcnDl>6</un:uarfcnDl>
+<un:primaryScramblingCode>4</un:primaryScramblingCode>
+<un:primaryCpichPower>300</un:primaryCpichPower>
+<un:maximumTransmissionPower>400</un:maximumTransmissionPower>
+<un:primarySchPower>-18</un:primarySchPower>
+<un:secondarySchPower>-35</un:secondarySchPower>
+<un:bchPower>-31</un:bchPower>
+<un:utranCellIubLink>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=2</un:utranCellIubLink>
+<un:lac>3422</un:lac>
+<un:rac>3423</un:rac>
+<un:sac>3424</un:sac>
+</un:attributes>
+</un:UtranCell>
+
+<un:UtranCell id="RNC01-2-1" modifier="update">
+
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>1</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>2</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>3</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>4</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>5</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>6</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>7</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>8</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>9</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>10</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="11" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>11</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="12" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>12</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="13" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>13</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="14" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>14</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="15" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>15</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="16" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>16</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="17" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>17</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="18" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>18</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="19" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>19</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="20" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>20</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="21" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>21</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="22" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>22</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="23" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>23</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="24" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>24</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="25" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>25</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="26" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>26</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="27" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>27</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="28" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>28</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="29" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>29</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="30" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>30</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>31</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=7</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>32</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=8</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>33</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=9</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>34</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50101</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>35</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50102</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>36</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50103</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>37</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=1</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>38</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=2</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>39</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=3</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>40</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=4</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RNC01-2-1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranCell</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranCell>
+
+<es:tCell>1</es:tCell>
+<es:cellReserved>1</es:cellReserved>
+<es:treSelection>2</es:treSelection>
+<es:qualMeasQuantity>2</es:qualMeasQuantity>
+<es:qHyst1>4</es:qHyst1>
+<es:qHyst2>4</es:qHyst2>
+<es:qQualMin>-24</es:qQualMin>
+<es:qRxLevMin>-115</es:qRxLevMin>
+<es:individualOffset>0</es:individualOffset>
+<es:pwrAdm>75</es:pwrAdm>
+<es:pwrOffset>5</es:pwrOffset>
+<es:pwrHyst>300</es:pwrHyst>
+<es:tmCongAction>2000</es:tmCongAction>
+<es:releaseAseDl>1</es:releaseAseDl>
+<es:aseDlAdm>240</es:aseDlAdm>
+<es:dlCodeAdm>80</es:dlCodeAdm>
+<es:aseUlAdm>160</es:aseUlAdm>
+<es:sf8Adm>8</es:sf8Adm>
+<es:sf32Adm>32</es:sf32Adm>
+<es:minPwrRl>-150</es:minPwrRl>
+<es:maxRate>40690</es:maxRate>
+<es:interRate>7760</es:interRate>
+<es:minimumRate>1590</es:minimumRate>
+<es:maxPwrMax>48</es:maxPwrMax>
+<es:interPwrMax>38</es:interPwrMax>
+<es:minPwrMax>0</es:minPwrMax>
+<es:compModeAdm>15</es:compModeAdm>
+<es:iFHyst>6000</es:iFHyst>
+<es:iFCong>621</es:iFCong>
+<es:interFreqFddMeasIndicator>0</es:interFreqFddMeasIndicator>
+<es:sRatSearch>4</es:sRatSearch>
+<es:sIntraSearch>0</es:sIntraSearch>
+<es:sInterSearch>0</es:sInterSearch>
+<es:fachMeasOccaCycLenCoeff>0</es:fachMeasOccaCycLenCoeff>
+
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:utranCellPosition></es:utranCellPosition>
+<es:maxTxPowerUl>24</es:maxTxPowerUl>
+
+<es:sib1PlmnScopeValueTag>0</es:sib1PlmnScopeValueTag>
+<es:sf16Adm>16</es:sf16Adm>
+<es:hoType>1</es:hoType>
+<es:usedFreqThresh2dEcno>-12</es:usedFreqThresh2dEcno>
+<es:usedFreqThresh2dRscp>-97</es:usedFreqThresh2dRscp>
+<es:administrativeState>0</es:administrativeState>
+<es:loadSharingGsmThreshold>75</es:loadSharingGsmThreshold>
+<es:loadSharingGsmFraction>100</es:loadSharingGsmFraction>
+<es:nInSyncInd>3</es:nInSyncInd>
+<es:rlFailureT>10</es:rlFailureT>
+<es:nOutSyncInd>10</es:nOutSyncInd>
+<es:sf4AdmUl>0</es:sf4AdmUl>
+<es:hardIfhoCorr>3</es:hardIfhoCorr>
+<es:hsdpaUsersAdm>10</es:hsdpaUsersAdm>
+<es:loadSharingMargin>0</es:loadSharingMargin>
+<es:sHcsRat>-105</es:sHcsRat>
+<es:sf16gAdm>16</es:sf16gAdm>
+<es:releaseAseDlNg>3</es:releaseAseDlNg>
+<es:tmCongActionNg>800</es:tmCongActionNg>
+<es:tmInitialG>3000</es:tmInitialG>
+<es:sf16AdmUl>16</es:sf16AdmUl>
+<es:sf8AdmUl>8</es:sf8AdmUl>
+<es:sf8gAdmUl>0</es:sf8gAdmUl>
+<es:iubLinkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=2</es:iubLinkRef>
+<es:eulNonServingCellUsersAdm>100</es:eulNonServingCellUsersAdm>
+<es:eulServingCellUsersAdm>32</es:eulServingCellUsersAdm>
+<es:agpsEnabled>1</es:agpsEnabled>
+<es:codeLoadThresholdDlSf128>100</es:codeLoadThresholdDlSf128>
+<es:pwrLoadThresholdDlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:pwrLoadThresholdDlSpeech>
+<es:aseLoadThresholdUlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:aseLoadThresholdUlSpeech>
+
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:rateSelectionPsInteractive>
+<es:channelType>0</es:channelType>
+<es:ulPrefRate>64</es:ulPrefRate>
+<es:dlPrefRate>64</es:dlPrefRate></es:rateSelectionPsInteractive>
+<es:hcsUsage>
+<es:idleMode>0</es:idleMode>
+<es:connectedMode>0</es:connectedMode></es:hcsUsage>
+<es:hcsSib3Config>
+<es:sSearchHcs>-105</es:sSearchHcs>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs></es:hcsSib3Config>
+</es:vsDataUtranCell>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataFach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataFach>
+
+<es:userLabel>Fach-2-1</es:userLabel>
+<es:maxFach1Power>18</es:maxFach1Power>
+<es:maxFach2Power>15</es:maxFach2Power>
+<es:sccpchOffset>0</es:sccpchOffset>
+<es:pOffset1Fach>0</es:pOffset1Fach>
+<es:pOffset3Fach>0</es:pOffset3Fach>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataFach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataRach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataRach>
+
+<es:userLabel>Rach-2-1</es:userLabel>
+<es:scramblingCodeWordNo>0</es:scramblingCodeWordNo>
+<es:preambleSignatures>65535</es:preambleSignatures>
+<es:subChannelNo>4095</es:subChannelNo>
+<es:aichTransmissionTiming>4</es:aichTransmissionTiming>
+<es:aichPower>-6</es:aichPower>
+<es:powerOffsetP0>3</es:powerOffsetP0>
+<es:powerOffsetPpm>-4</es:powerOffsetPpm>
+<es:preambleRetransMax>5</es:preambleRetransMax>
+<es:maxPreambleCycle>4</es:maxPreambleCycle>
+<es:constantValueCprach>-27</es:constantValueCprach>
+<es:spreadingFactor>64</es:spreadingFactor>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataRach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPch>
+
+<es:userLabel>Pch-2-1</es:userLabel>
+<es:pchPower>-4</es:pchPower>
+<es:pichPower>-7</es:pichPower>
+<es:sccpchOffset>20</es:sccpchOffset>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataPch>
+</xn:attributes>
+</xn:VsDataContainer><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-2-1</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-2-1</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataEul</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataEul>
+
+<es:userLabel>Eul-2-1</es:userLabel>
+<es:administrativeState>0</es:administrativeState>
+<es:numEagchCodes>1</es:numEagchCodes>
+<es:numEhichErgchCodes>1</es:numEhichErgchCodes>
+<es:eulMaxTargetRtwp>-499</es:eulMaxTargetRtwp>
+</es:vsDataEul>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataCoverageRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataCoverageRelation>
+
+<es:utranCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,UtranCell=RNC01-2-2</es:utranCellRef>
+<es:coverageIndicator>1</es:coverageIndicator>
+<es:hsPathlossThreshold>170</es:hsPathlossThreshold>
+</es:vsDataCoverageRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer></un:UtranCell>
+<un:UtranCell id="RNC01-2-2" modifier="create">
+<un:attributes>
+
+<un:userLabel>RNC01-2-2</un:userLabel>
+<un:cId>5</un:cId>
+<un:localCellId>2</un:localCellId>
+<un:uarfcnUl>12</un:uarfcnUl>
+<un:uarfcnDl>6</un:uarfcnDl>
+<un:primaryScramblingCode>5</un:primaryScramblingCode>
+<un:primaryCpichPower>300</un:primaryCpichPower>
+<un:maximumTransmissionPower>400</un:maximumTransmissionPower>
+<un:primarySchPower>-18</un:primarySchPower>
+<un:secondarySchPower>-35</un:secondarySchPower>
+<un:bchPower>-31</un:bchPower>
+<un:utranCellIubLink>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=2</un:utranCellIubLink>
+<un:lac>3422</un:lac>
+<un:rac>3423</un:rac>
+<un:sac>3425</un:sac>
+</un:attributes>
+</un:UtranCell>
+
+<un:UtranCell id="RNC01-2-2" modifier="update">
+
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>1</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>2</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>3</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>4</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>5</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>6</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>7</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>8</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>9</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>10</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="11" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>11</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="12" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>12</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="13" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>13</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="14" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>14</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="15" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>15</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="16" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>16</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="17" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>17</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="18" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>18</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="19" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>19</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="20" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>20</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="21" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>21</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="22" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>22</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="23" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>23</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="24" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>24</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="25" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>25</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="26" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>26</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="27" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>27</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="28" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>28</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="29" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>29</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="30" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>30</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>31</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=5</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>32</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=6</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>33</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=7</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>34</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=8</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>35</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=9</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>36</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50101</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>37</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50102</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>38</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50103</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>39</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=1</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>40</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=2</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RNC01-2-2" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranCell</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranCell>
+
+<es:tCell>2</es:tCell>
+<es:cellReserved>1</es:cellReserved>
+<es:treSelection>2</es:treSelection>
+<es:qualMeasQuantity>2</es:qualMeasQuantity>
+<es:qHyst1>4</es:qHyst1>
+<es:qHyst2>4</es:qHyst2>
+<es:qQualMin>-24</es:qQualMin>
+<es:qRxLevMin>-115</es:qRxLevMin>
+<es:individualOffset>0</es:individualOffset>
+<es:pwrAdm>75</es:pwrAdm>
+<es:pwrOffset>5</es:pwrOffset>
+<es:pwrHyst>300</es:pwrHyst>
+<es:tmCongAction>2000</es:tmCongAction>
+<es:releaseAseDl>1</es:releaseAseDl>
+<es:aseDlAdm>240</es:aseDlAdm>
+<es:dlCodeAdm>80</es:dlCodeAdm>
+<es:aseUlAdm>160</es:aseUlAdm>
+<es:sf8Adm>8</es:sf8Adm>
+<es:sf32Adm>32</es:sf32Adm>
+<es:minPwrRl>-150</es:minPwrRl>
+<es:maxRate>40690</es:maxRate>
+<es:interRate>7760</es:interRate>
+<es:minimumRate>1590</es:minimumRate>
+<es:maxPwrMax>48</es:maxPwrMax>
+<es:interPwrMax>38</es:interPwrMax>
+<es:minPwrMax>0</es:minPwrMax>
+<es:compModeAdm>15</es:compModeAdm>
+<es:iFHyst>6000</es:iFHyst>
+<es:iFCong>621</es:iFCong>
+<es:interFreqFddMeasIndicator>0</es:interFreqFddMeasIndicator>
+<es:sRatSearch>4</es:sRatSearch>
+<es:sIntraSearch>0</es:sIntraSearch>
+<es:sInterSearch>0</es:sInterSearch>
+<es:fachMeasOccaCycLenCoeff>0</es:fachMeasOccaCycLenCoeff>
+
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:utranCellPosition></es:utranCellPosition>
+<es:maxTxPowerUl>24</es:maxTxPowerUl>
+
+<es:sib1PlmnScopeValueTag>0</es:sib1PlmnScopeValueTag>
+<es:sf16Adm>16</es:sf16Adm>
+<es:hoType>1</es:hoType>
+<es:usedFreqThresh2dEcno>-12</es:usedFreqThresh2dEcno>
+<es:usedFreqThresh2dRscp>-97</es:usedFreqThresh2dRscp>
+<es:administrativeState>0</es:administrativeState>
+<es:loadSharingGsmThreshold>75</es:loadSharingGsmThreshold>
+<es:loadSharingGsmFraction>100</es:loadSharingGsmFraction>
+<es:nInSyncInd>3</es:nInSyncInd>
+<es:rlFailureT>10</es:rlFailureT>
+<es:nOutSyncInd>10</es:nOutSyncInd>
+<es:sf4AdmUl>0</es:sf4AdmUl>
+<es:hardIfhoCorr>3</es:hardIfhoCorr>
+<es:hsdpaUsersAdm>10</es:hsdpaUsersAdm>
+<es:loadSharingMargin>0</es:loadSharingMargin>
+<es:sHcsRat>-105</es:sHcsRat>
+<es:sf16gAdm>16</es:sf16gAdm>
+<es:releaseAseDlNg>3</es:releaseAseDlNg>
+<es:tmCongActionNg>800</es:tmCongActionNg>
+<es:tmInitialG>3000</es:tmInitialG>
+<es:sf16AdmUl>16</es:sf16AdmUl>
+<es:sf8AdmUl>8</es:sf8AdmUl>
+<es:sf8gAdmUl>0</es:sf8gAdmUl>
+<es:iubLinkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=2</es:iubLinkRef>
+<es:eulNonServingCellUsersAdm>100</es:eulNonServingCellUsersAdm>
+<es:eulServingCellUsersAdm>32</es:eulServingCellUsersAdm>
+<es:agpsEnabled>1</es:agpsEnabled>
+<es:codeLoadThresholdDlSf128>100</es:codeLoadThresholdDlSf128>
+<es:pwrLoadThresholdDlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:pwrLoadThresholdDlSpeech>
+<es:aseLoadThresholdUlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:aseLoadThresholdUlSpeech>
+
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:rateSelectionPsInteractive>
+<es:channelType>0</es:channelType>
+<es:ulPrefRate>64</es:ulPrefRate>
+<es:dlPrefRate>64</es:dlPrefRate></es:rateSelectionPsInteractive>
+<es:hcsUsage>
+<es:idleMode>0</es:idleMode>
+<es:connectedMode>0</es:connectedMode></es:hcsUsage>
+<es:hcsSib3Config>
+<es:sSearchHcs>-105</es:sSearchHcs>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs></es:hcsSib3Config>
+</es:vsDataUtranCell>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataFach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataFach>
+
+<es:userLabel>Fach-2-2</es:userLabel>
+<es:maxFach1Power>18</es:maxFach1Power>
+<es:maxFach2Power>15</es:maxFach2Power>
+<es:sccpchOffset>0</es:sccpchOffset>
+<es:pOffset1Fach>0</es:pOffset1Fach>
+<es:pOffset3Fach>0</es:pOffset3Fach>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataFach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataRach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataRach>
+
+<es:userLabel>Rach-2-2</es:userLabel>
+<es:scramblingCodeWordNo>0</es:scramblingCodeWordNo>
+<es:preambleSignatures>65535</es:preambleSignatures>
+<es:subChannelNo>4095</es:subChannelNo>
+<es:aichTransmissionTiming>4</es:aichTransmissionTiming>
+<es:aichPower>-6</es:aichPower>
+<es:powerOffsetP0>3</es:powerOffsetP0>
+<es:powerOffsetPpm>-4</es:powerOffsetPpm>
+<es:preambleRetransMax>5</es:preambleRetransMax>
+<es:maxPreambleCycle>4</es:maxPreambleCycle>
+<es:constantValueCprach>-27</es:constantValueCprach>
+<es:spreadingFactor>64</es:spreadingFactor>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataRach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPch>
+
+<es:userLabel>Pch-2-2</es:userLabel>
+<es:pchPower>-4</es:pchPower>
+<es:pichPower>-7</es:pichPower>
+<es:sccpchOffset>20</es:sccpchOffset>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataPch>
+</xn:attributes>
+</xn:VsDataContainer><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-2-2</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-2-2</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataEul</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataEul>
+
+<es:userLabel>Eul-2-2</es:userLabel>
+<es:administrativeState>0</es:administrativeState>
+<es:numEagchCodes>1</es:numEagchCodes>
+<es:numEhichErgchCodes>1</es:numEhichErgchCodes>
+<es:eulMaxTargetRtwp>-499</es:eulMaxTargetRtwp>
+</es:vsDataEul>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataCoverageRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataCoverageRelation>
+
+<es:utranCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,UtranCell=RNC01-2-3</es:utranCellRef>
+<es:coverageIndicator>1</es:coverageIndicator>
+<es:hsPathlossThreshold>170</es:hsPathlossThreshold>
+</es:vsDataCoverageRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer></un:UtranCell>
+<un:UtranCell id="RNC01-2-3" modifier="create">
+<un:attributes>
+
+<un:userLabel>RNC01-2-3</un:userLabel>
+<un:cId>6</un:cId>
+<un:localCellId>3</un:localCellId>
+<un:uarfcnUl>12</un:uarfcnUl>
+<un:uarfcnDl>6</un:uarfcnDl>
+<un:primaryScramblingCode>6</un:primaryScramblingCode>
+<un:primaryCpichPower>300</un:primaryCpichPower>
+<un:maximumTransmissionPower>400</un:maximumTransmissionPower>
+<un:primarySchPower>-18</un:primarySchPower>
+<un:secondarySchPower>-35</un:secondarySchPower>
+<un:bchPower>-31</un:bchPower>
+<un:utranCellIubLink>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=2</un:utranCellIubLink>
+<un:lac>3422</un:lac>
+<un:rac>3423</un:rac>
+<un:sac>3426</un:sac>
+</un:attributes>
+</un:UtranCell>
+
+<un:UtranCell id="RNC01-2-3" modifier="update">
+
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>1</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>2</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>3</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>4</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>5</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>6</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>7</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>8</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>9</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>10</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="11" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>11</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="12" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>12</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="13" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>13</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="14" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>14</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="15" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>15</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="16" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>16</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="17" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>17</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="18" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>18</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="19" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>19</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="20" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>20</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="21" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>21</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="22" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>22</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="23" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>23</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="24" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>24</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="25" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>25</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="26" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>26</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="27" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>27</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="28" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>28</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="29" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>29</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="30" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>30</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>31</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=3</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>32</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=4</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>33</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=5</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>34</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=6</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>35</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=7</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>36</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=8</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>37</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=9</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>38</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50101</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>39</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50102</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>40</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50103</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RNC01-2-3" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranCell</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranCell>
+
+<es:tCell>3</es:tCell>
+<es:cellReserved>1</es:cellReserved>
+<es:treSelection>2</es:treSelection>
+<es:qualMeasQuantity>2</es:qualMeasQuantity>
+<es:qHyst1>4</es:qHyst1>
+<es:qHyst2>4</es:qHyst2>
+<es:qQualMin>-24</es:qQualMin>
+<es:qRxLevMin>-115</es:qRxLevMin>
+<es:individualOffset>0</es:individualOffset>
+<es:pwrAdm>75</es:pwrAdm>
+<es:pwrOffset>5</es:pwrOffset>
+<es:pwrHyst>300</es:pwrHyst>
+<es:tmCongAction>2000</es:tmCongAction>
+<es:releaseAseDl>1</es:releaseAseDl>
+<es:aseDlAdm>240</es:aseDlAdm>
+<es:dlCodeAdm>80</es:dlCodeAdm>
+<es:aseUlAdm>160</es:aseUlAdm>
+<es:sf8Adm>8</es:sf8Adm>
+<es:sf32Adm>32</es:sf32Adm>
+<es:minPwrRl>-150</es:minPwrRl>
+<es:maxRate>40690</es:maxRate>
+<es:interRate>7760</es:interRate>
+<es:minimumRate>1590</es:minimumRate>
+<es:maxPwrMax>48</es:maxPwrMax>
+<es:interPwrMax>38</es:interPwrMax>
+<es:minPwrMax>0</es:minPwrMax>
+<es:compModeAdm>15</es:compModeAdm>
+<es:iFHyst>6000</es:iFHyst>
+<es:iFCong>621</es:iFCong>
+<es:interFreqFddMeasIndicator>0</es:interFreqFddMeasIndicator>
+<es:sRatSearch>4</es:sRatSearch>
+<es:sIntraSearch>0</es:sIntraSearch>
+<es:sInterSearch>0</es:sInterSearch>
+<es:fachMeasOccaCycLenCoeff>0</es:fachMeasOccaCycLenCoeff>
+
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:utranCellPosition></es:utranCellPosition>
+<es:maxTxPowerUl>24</es:maxTxPowerUl>
+
+<es:sib1PlmnScopeValueTag>0</es:sib1PlmnScopeValueTag>
+<es:sf16Adm>16</es:sf16Adm>
+<es:hoType>1</es:hoType>
+<es:usedFreqThresh2dEcno>-12</es:usedFreqThresh2dEcno>
+<es:usedFreqThresh2dRscp>-97</es:usedFreqThresh2dRscp>
+<es:administrativeState>0</es:administrativeState>
+<es:loadSharingGsmThreshold>75</es:loadSharingGsmThreshold>
+<es:loadSharingGsmFraction>100</es:loadSharingGsmFraction>
+<es:nInSyncInd>3</es:nInSyncInd>
+<es:rlFailureT>10</es:rlFailureT>
+<es:nOutSyncInd>10</es:nOutSyncInd>
+<es:sf4AdmUl>0</es:sf4AdmUl>
+<es:hardIfhoCorr>3</es:hardIfhoCorr>
+<es:hsdpaUsersAdm>10</es:hsdpaUsersAdm>
+<es:loadSharingMargin>0</es:loadSharingMargin>
+<es:sHcsRat>-105</es:sHcsRat>
+<es:sf16gAdm>16</es:sf16gAdm>
+<es:releaseAseDlNg>3</es:releaseAseDlNg>
+<es:tmCongActionNg>800</es:tmCongActionNg>
+<es:tmInitialG>3000</es:tmInitialG>
+<es:sf16AdmUl>16</es:sf16AdmUl>
+<es:sf8AdmUl>8</es:sf8AdmUl>
+<es:sf8gAdmUl>0</es:sf8gAdmUl>
+<es:iubLinkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=2</es:iubLinkRef>
+<es:eulNonServingCellUsersAdm>100</es:eulNonServingCellUsersAdm>
+<es:eulServingCellUsersAdm>32</es:eulServingCellUsersAdm>
+<es:agpsEnabled>1</es:agpsEnabled>
+<es:codeLoadThresholdDlSf128>100</es:codeLoadThresholdDlSf128>
+<es:pwrLoadThresholdDlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:pwrLoadThresholdDlSpeech>
+<es:aseLoadThresholdUlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:aseLoadThresholdUlSpeech>
+
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:rateSelectionPsInteractive>
+<es:channelType>0</es:channelType>
+<es:ulPrefRate>64</es:ulPrefRate>
+<es:dlPrefRate>64</es:dlPrefRate></es:rateSelectionPsInteractive>
+<es:hcsUsage>
+<es:idleMode>0</es:idleMode>
+<es:connectedMode>0</es:connectedMode></es:hcsUsage>
+<es:hcsSib3Config>
+<es:sSearchHcs>-105</es:sSearchHcs>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs></es:hcsSib3Config>
+</es:vsDataUtranCell>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataFach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataFach>
+
+<es:userLabel>Fach-2-3</es:userLabel>
+<es:maxFach1Power>18</es:maxFach1Power>
+<es:maxFach2Power>15</es:maxFach2Power>
+<es:sccpchOffset>0</es:sccpchOffset>
+<es:pOffset1Fach>0</es:pOffset1Fach>
+<es:pOffset3Fach>0</es:pOffset3Fach>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataFach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataRach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataRach>
+
+<es:userLabel>Rach-2-3</es:userLabel>
+<es:scramblingCodeWordNo>0</es:scramblingCodeWordNo>
+<es:preambleSignatures>65535</es:preambleSignatures>
+<es:subChannelNo>4095</es:subChannelNo>
+<es:aichTransmissionTiming>4</es:aichTransmissionTiming>
+<es:aichPower>-6</es:aichPower>
+<es:powerOffsetP0>3</es:powerOffsetP0>
+<es:powerOffsetPpm>-4</es:powerOffsetPpm>
+<es:preambleRetransMax>5</es:preambleRetransMax>
+<es:maxPreambleCycle>4</es:maxPreambleCycle>
+<es:constantValueCprach>-27</es:constantValueCprach>
+<es:spreadingFactor>64</es:spreadingFactor>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataRach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPch>
+
+<es:userLabel>Pch-2-3</es:userLabel>
+<es:pchPower>-4</es:pchPower>
+<es:pichPower>-7</es:pichPower>
+<es:sccpchOffset>20</es:sccpchOffset>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataPch>
+</xn:attributes>
+</xn:VsDataContainer><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-2-3</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-2-3</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataEul</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataEul>
+
+<es:userLabel>Eul-2-3</es:userLabel>
+<es:administrativeState>0</es:administrativeState>
+<es:numEagchCodes>1</es:numEagchCodes>
+<es:numEhichErgchCodes>1</es:numEhichErgchCodes>
+<es:eulMaxTargetRtwp>-499</es:eulMaxTargetRtwp>
+</es:vsDataEul>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataCoverageRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataCoverageRelation>
+
+<es:utranCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,UtranCell=RNC01-2-1</es:utranCellRef>
+<es:coverageIndicator>1</es:coverageIndicator>
+<es:hsPathlossThreshold>170</es:hsPathlossThreshold>
+</es:vsDataCoverageRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer></un:UtranCell>
+<un:UtranCell id="RNC01-3-1" modifier="create">
+<un:attributes>
+
+<un:userLabel>RNC01-3-1</un:userLabel>
+<un:cId>7</un:cId>
+<un:localCellId>1</un:localCellId>
+<un:uarfcnUl>12</un:uarfcnUl>
+<un:uarfcnDl>7</un:uarfcnDl>
+<un:primaryScramblingCode>7</un:primaryScramblingCode>
+<un:primaryCpichPower>300</un:primaryCpichPower>
+<un:maximumTransmissionPower>400</un:maximumTransmissionPower>
+<un:primarySchPower>-18</un:primarySchPower>
+<un:secondarySchPower>-35</un:secondarySchPower>
+<un:bchPower>-31</un:bchPower>
+<un:utranCellIubLink>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=3</un:utranCellIubLink>
+<un:lac>3427</un:lac>
+<un:rac>3428</un:rac>
+<un:sac>3429</un:sac>
+</un:attributes>
+</un:UtranCell>
+
+<un:UtranCell id="RNC01-3-1" modifier="update">
+
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>1</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>2</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>3</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>4</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>5</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>6</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>7</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>8</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>9</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>10</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="11" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>11</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="12" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>12</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="13" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>13</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="14" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>14</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="15" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>15</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="16" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>16</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="17" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>17</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="18" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>18</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="19" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>19</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="20" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>20</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="21" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>21</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="22" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>22</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="23" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>23</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="24" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>24</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="25" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>25</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="26" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>26</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="27" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>27</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="28" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>28</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="29" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>29</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="30" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>30</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>31</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=1</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>32</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=2</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>33</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=3</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>34</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=4</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>35</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=5</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>36</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=6</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>37</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=7</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>38</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=8</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>39</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=9</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>40</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50101</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RNC01-3-1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranCell</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranCell>
+
+<es:tCell>1</es:tCell>
+<es:cellReserved>1</es:cellReserved>
+<es:treSelection>2</es:treSelection>
+<es:qualMeasQuantity>2</es:qualMeasQuantity>
+<es:qHyst1>4</es:qHyst1>
+<es:qHyst2>4</es:qHyst2>
+<es:qQualMin>-24</es:qQualMin>
+<es:qRxLevMin>-115</es:qRxLevMin>
+<es:individualOffset>0</es:individualOffset>
+<es:pwrAdm>75</es:pwrAdm>
+<es:pwrOffset>5</es:pwrOffset>
+<es:pwrHyst>300</es:pwrHyst>
+<es:tmCongAction>2000</es:tmCongAction>
+<es:releaseAseDl>1</es:releaseAseDl>
+<es:aseDlAdm>240</es:aseDlAdm>
+<es:dlCodeAdm>80</es:dlCodeAdm>
+<es:aseUlAdm>160</es:aseUlAdm>
+<es:sf8Adm>8</es:sf8Adm>
+<es:sf32Adm>32</es:sf32Adm>
+<es:minPwrRl>-150</es:minPwrRl>
+<es:maxRate>40690</es:maxRate>
+<es:interRate>7760</es:interRate>
+<es:minimumRate>1590</es:minimumRate>
+<es:maxPwrMax>48</es:maxPwrMax>
+<es:interPwrMax>38</es:interPwrMax>
+<es:minPwrMax>0</es:minPwrMax>
+<es:compModeAdm>15</es:compModeAdm>
+<es:iFHyst>6000</es:iFHyst>
+<es:iFCong>621</es:iFCong>
+<es:interFreqFddMeasIndicator>0</es:interFreqFddMeasIndicator>
+<es:sRatSearch>4</es:sRatSearch>
+<es:sIntraSearch>0</es:sIntraSearch>
+<es:sInterSearch>0</es:sInterSearch>
+<es:fachMeasOccaCycLenCoeff>0</es:fachMeasOccaCycLenCoeff>
+
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:utranCellPosition></es:utranCellPosition>
+<es:maxTxPowerUl>24</es:maxTxPowerUl>
+
+<es:sib1PlmnScopeValueTag>0</es:sib1PlmnScopeValueTag>
+<es:sf16Adm>16</es:sf16Adm>
+<es:hoType>1</es:hoType>
+<es:usedFreqThresh2dEcno>-12</es:usedFreqThresh2dEcno>
+<es:usedFreqThresh2dRscp>-97</es:usedFreqThresh2dRscp>
+<es:administrativeState>0</es:administrativeState>
+<es:loadSharingGsmThreshold>75</es:loadSharingGsmThreshold>
+<es:loadSharingGsmFraction>100</es:loadSharingGsmFraction>
+<es:nInSyncInd>3</es:nInSyncInd>
+<es:rlFailureT>10</es:rlFailureT>
+<es:nOutSyncInd>10</es:nOutSyncInd>
+<es:sf4AdmUl>0</es:sf4AdmUl>
+<es:hardIfhoCorr>3</es:hardIfhoCorr>
+<es:hsdpaUsersAdm>10</es:hsdpaUsersAdm>
+<es:loadSharingMargin>0</es:loadSharingMargin>
+<es:sHcsRat>-105</es:sHcsRat>
+<es:sf16gAdm>16</es:sf16gAdm>
+<es:releaseAseDlNg>3</es:releaseAseDlNg>
+<es:tmCongActionNg>800</es:tmCongActionNg>
+<es:tmInitialG>3000</es:tmInitialG>
+<es:sf16AdmUl>16</es:sf16AdmUl>
+<es:sf8AdmUl>8</es:sf8AdmUl>
+<es:sf8gAdmUl>0</es:sf8gAdmUl>
+<es:iubLinkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=3</es:iubLinkRef>
+<es:eulNonServingCellUsersAdm>100</es:eulNonServingCellUsersAdm>
+<es:eulServingCellUsersAdm>32</es:eulServingCellUsersAdm>
+<es:agpsEnabled>1</es:agpsEnabled>
+<es:codeLoadThresholdDlSf128>100</es:codeLoadThresholdDlSf128>
+<es:pwrLoadThresholdDlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:pwrLoadThresholdDlSpeech>
+<es:aseLoadThresholdUlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:aseLoadThresholdUlSpeech>
+
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:rateSelectionPsInteractive>
+<es:channelType>0</es:channelType>
+<es:ulPrefRate>64</es:ulPrefRate>
+<es:dlPrefRate>64</es:dlPrefRate></es:rateSelectionPsInteractive>
+<es:hcsUsage>
+<es:idleMode>0</es:idleMode>
+<es:connectedMode>0</es:connectedMode></es:hcsUsage>
+<es:hcsSib3Config>
+<es:sSearchHcs>-105</es:sSearchHcs>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs></es:hcsSib3Config>
+</es:vsDataUtranCell>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataFach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataFach>
+
+<es:userLabel>Fach-3-1</es:userLabel>
+<es:maxFach1Power>18</es:maxFach1Power>
+<es:maxFach2Power>15</es:maxFach2Power>
+<es:sccpchOffset>0</es:sccpchOffset>
+<es:pOffset1Fach>0</es:pOffset1Fach>
+<es:pOffset3Fach>0</es:pOffset3Fach>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataFach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataRach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataRach>
+
+<es:userLabel>Rach-3-1</es:userLabel>
+<es:scramblingCodeWordNo>0</es:scramblingCodeWordNo>
+<es:preambleSignatures>65535</es:preambleSignatures>
+<es:subChannelNo>4095</es:subChannelNo>
+<es:aichTransmissionTiming>4</es:aichTransmissionTiming>
+<es:aichPower>-6</es:aichPower>
+<es:powerOffsetP0>3</es:powerOffsetP0>
+<es:powerOffsetPpm>-4</es:powerOffsetPpm>
+<es:preambleRetransMax>5</es:preambleRetransMax>
+<es:maxPreambleCycle>4</es:maxPreambleCycle>
+<es:constantValueCprach>-27</es:constantValueCprach>
+<es:spreadingFactor>64</es:spreadingFactor>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataRach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPch>
+
+<es:userLabel>Pch-3-1</es:userLabel>
+<es:pchPower>-4</es:pchPower>
+<es:pichPower>-7</es:pichPower>
+<es:sccpchOffset>20</es:sccpchOffset>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataPch>
+</xn:attributes>
+</xn:VsDataContainer><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-3-1</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-3-1</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataEul</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataEul>
+
+<es:userLabel>Eul-3-1</es:userLabel>
+<es:administrativeState>0</es:administrativeState>
+<es:numEagchCodes>1</es:numEagchCodes>
+<es:numEhichErgchCodes>1</es:numEhichErgchCodes>
+<es:eulMaxTargetRtwp>-499</es:eulMaxTargetRtwp>
+</es:vsDataEul>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataCoverageRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataCoverageRelation>
+
+<es:utranCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,UtranCell=RNC01-3-2</es:utranCellRef>
+<es:coverageIndicator>1</es:coverageIndicator>
+<es:hsPathlossThreshold>170</es:hsPathlossThreshold>
+</es:vsDataCoverageRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer></un:UtranCell>
+<un:UtranCell id="RNC01-3-2" modifier="create">
+<un:attributes>
+
+<un:userLabel>RNC01-3-2</un:userLabel>
+<un:cId>8</un:cId>
+<un:localCellId>2</un:localCellId>
+<un:uarfcnUl>12</un:uarfcnUl>
+<un:uarfcnDl>7</un:uarfcnDl>
+<un:primaryScramblingCode>8</un:primaryScramblingCode>
+<un:primaryCpichPower>300</un:primaryCpichPower>
+<un:maximumTransmissionPower>400</un:maximumTransmissionPower>
+<un:primarySchPower>-18</un:primarySchPower>
+<un:secondarySchPower>-35</un:secondarySchPower>
+<un:bchPower>-31</un:bchPower>
+<un:utranCellIubLink>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=3</un:utranCellIubLink>
+<un:lac>3427</un:lac>
+<un:rac>3428</un:rac>
+<un:sac>3430</un:sac>
+</un:attributes>
+</un:UtranCell>
+
+<un:UtranCell id="RNC01-3-2" modifier="update">
+
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>1</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>2</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>3</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>4</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>5</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>6</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>7</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>8</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>9</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>10</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="11" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>11</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="12" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>12</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="13" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>13</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="14" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>14</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="15" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>15</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="16" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>16</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="17" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>17</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="18" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>18</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="19" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>19</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="20" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>20</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="21" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>21</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="22" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>22</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="23" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>23</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="24" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>24</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="25" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>25</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="26" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>26</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="27" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>27</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="28" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>28</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="29" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>29</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="30" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>30</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>31</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50102</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>32</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50103</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>33</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=1</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>34</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=2</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>35</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=3</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>36</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=4</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>37</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=5</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>38</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=6</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>39</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=7</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>40</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=8</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RNC01-3-2" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranCell</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranCell>
+
+<es:tCell>2</es:tCell>
+<es:cellReserved>1</es:cellReserved>
+<es:treSelection>2</es:treSelection>
+<es:qualMeasQuantity>2</es:qualMeasQuantity>
+<es:qHyst1>4</es:qHyst1>
+<es:qHyst2>4</es:qHyst2>
+<es:qQualMin>-24</es:qQualMin>
+<es:qRxLevMin>-115</es:qRxLevMin>
+<es:individualOffset>0</es:individualOffset>
+<es:pwrAdm>75</es:pwrAdm>
+<es:pwrOffset>5</es:pwrOffset>
+<es:pwrHyst>300</es:pwrHyst>
+<es:tmCongAction>2000</es:tmCongAction>
+<es:releaseAseDl>1</es:releaseAseDl>
+<es:aseDlAdm>240</es:aseDlAdm>
+<es:dlCodeAdm>80</es:dlCodeAdm>
+<es:aseUlAdm>160</es:aseUlAdm>
+<es:sf8Adm>8</es:sf8Adm>
+<es:sf32Adm>32</es:sf32Adm>
+<es:minPwrRl>-150</es:minPwrRl>
+<es:maxRate>40690</es:maxRate>
+<es:interRate>7760</es:interRate>
+<es:minimumRate>1590</es:minimumRate>
+<es:maxPwrMax>48</es:maxPwrMax>
+<es:interPwrMax>38</es:interPwrMax>
+<es:minPwrMax>0</es:minPwrMax>
+<es:compModeAdm>15</es:compModeAdm>
+<es:iFHyst>6000</es:iFHyst>
+<es:iFCong>621</es:iFCong>
+<es:interFreqFddMeasIndicator>0</es:interFreqFddMeasIndicator>
+<es:sRatSearch>4</es:sRatSearch>
+<es:sIntraSearch>0</es:sIntraSearch>
+<es:sInterSearch>0</es:sInterSearch>
+<es:fachMeasOccaCycLenCoeff>0</es:fachMeasOccaCycLenCoeff>
+
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:utranCellPosition></es:utranCellPosition>
+<es:maxTxPowerUl>24</es:maxTxPowerUl>
+
+<es:sib1PlmnScopeValueTag>0</es:sib1PlmnScopeValueTag>
+<es:sf16Adm>16</es:sf16Adm>
+<es:hoType>1</es:hoType>
+<es:usedFreqThresh2dEcno>-12</es:usedFreqThresh2dEcno>
+<es:usedFreqThresh2dRscp>-97</es:usedFreqThresh2dRscp>
+<es:administrativeState>0</es:administrativeState>
+<es:loadSharingGsmThreshold>75</es:loadSharingGsmThreshold>
+<es:loadSharingGsmFraction>100</es:loadSharingGsmFraction>
+<es:nInSyncInd>3</es:nInSyncInd>
+<es:rlFailureT>10</es:rlFailureT>
+<es:nOutSyncInd>10</es:nOutSyncInd>
+<es:sf4AdmUl>0</es:sf4AdmUl>
+<es:hardIfhoCorr>3</es:hardIfhoCorr>
+<es:hsdpaUsersAdm>10</es:hsdpaUsersAdm>
+<es:loadSharingMargin>0</es:loadSharingMargin>
+<es:sHcsRat>-105</es:sHcsRat>
+<es:sf16gAdm>16</es:sf16gAdm>
+<es:releaseAseDlNg>3</es:releaseAseDlNg>
+<es:tmCongActionNg>800</es:tmCongActionNg>
+<es:tmInitialG>3000</es:tmInitialG>
+<es:sf16AdmUl>16</es:sf16AdmUl>
+<es:sf8AdmUl>8</es:sf8AdmUl>
+<es:sf8gAdmUl>0</es:sf8gAdmUl>
+<es:iubLinkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=3</es:iubLinkRef>
+<es:eulNonServingCellUsersAdm>100</es:eulNonServingCellUsersAdm>
+<es:eulServingCellUsersAdm>32</es:eulServingCellUsersAdm>
+<es:agpsEnabled>1</es:agpsEnabled>
+<es:codeLoadThresholdDlSf128>100</es:codeLoadThresholdDlSf128>
+<es:pwrLoadThresholdDlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:pwrLoadThresholdDlSpeech>
+<es:aseLoadThresholdUlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:aseLoadThresholdUlSpeech>
+
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:rateSelectionPsInteractive>
+<es:channelType>0</es:channelType>
+<es:ulPrefRate>64</es:ulPrefRate>
+<es:dlPrefRate>64</es:dlPrefRate></es:rateSelectionPsInteractive>
+<es:hcsUsage>
+<es:idleMode>0</es:idleMode>
+<es:connectedMode>0</es:connectedMode></es:hcsUsage>
+<es:hcsSib3Config>
+<es:sSearchHcs>-105</es:sSearchHcs>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs></es:hcsSib3Config>
+</es:vsDataUtranCell>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataFach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataFach>
+
+<es:userLabel>Fach-3-2</es:userLabel>
+<es:maxFach1Power>18</es:maxFach1Power>
+<es:maxFach2Power>15</es:maxFach2Power>
+<es:sccpchOffset>0</es:sccpchOffset>
+<es:pOffset1Fach>0</es:pOffset1Fach>
+<es:pOffset3Fach>0</es:pOffset3Fach>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataFach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataRach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataRach>
+
+<es:userLabel>Rach-3-2</es:userLabel>
+<es:scramblingCodeWordNo>0</es:scramblingCodeWordNo>
+<es:preambleSignatures>65535</es:preambleSignatures>
+<es:subChannelNo>4095</es:subChannelNo>
+<es:aichTransmissionTiming>4</es:aichTransmissionTiming>
+<es:aichPower>-6</es:aichPower>
+<es:powerOffsetP0>3</es:powerOffsetP0>
+<es:powerOffsetPpm>-4</es:powerOffsetPpm>
+<es:preambleRetransMax>5</es:preambleRetransMax>
+<es:maxPreambleCycle>4</es:maxPreambleCycle>
+<es:constantValueCprach>-27</es:constantValueCprach>
+<es:spreadingFactor>64</es:spreadingFactor>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataRach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPch>
+
+<es:userLabel>Pch-3-2</es:userLabel>
+<es:pchPower>-4</es:pchPower>
+<es:pichPower>-7</es:pichPower>
+<es:sccpchOffset>20</es:sccpchOffset>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataPch>
+</xn:attributes>
+</xn:VsDataContainer><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-3-2</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-3-2</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataEul</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataEul>
+
+<es:userLabel>Eul-3-2</es:userLabel>
+<es:administrativeState>0</es:administrativeState>
+<es:numEagchCodes>1</es:numEagchCodes>
+<es:numEhichErgchCodes>1</es:numEhichErgchCodes>
+<es:eulMaxTargetRtwp>-499</es:eulMaxTargetRtwp>
+</es:vsDataEul>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataCoverageRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataCoverageRelation>
+
+<es:utranCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,UtranCell=RNC01-3-3</es:utranCellRef>
+<es:coverageIndicator>1</es:coverageIndicator>
+<es:hsPathlossThreshold>170</es:hsPathlossThreshold>
+</es:vsDataCoverageRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer></un:UtranCell>
+<un:UtranCell id="RNC01-3-3" modifier="create">
+<un:attributes>
+
+<un:userLabel>RNC01-3-3</un:userLabel>
+<un:cId>9</un:cId>
+<un:localCellId>3</un:localCellId>
+<un:uarfcnUl>12</un:uarfcnUl>
+<un:uarfcnDl>7</un:uarfcnDl>
+<un:primaryScramblingCode>9</un:primaryScramblingCode>
+<un:primaryCpichPower>300</un:primaryCpichPower>
+<un:maximumTransmissionPower>400</un:maximumTransmissionPower>
+<un:primarySchPower>-18</un:primarySchPower>
+<un:secondarySchPower>-35</un:secondarySchPower>
+<un:bchPower>-31</un:bchPower>
+<un:utranCellIubLink>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=3</un:utranCellIubLink>
+<un:lac>3427</un:lac>
+<un:rac>3428</un:rac>
+<un:sac>3431</un:sac>
+</un:attributes>
+</un:UtranCell>
+
+<un:UtranCell id="RNC01-3-3" modifier="update">
+
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>1</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>2</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>3</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>4</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>5</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>6</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>7</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>8</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>9</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>10</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="11" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>11</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="12" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>12</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="13" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>13</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="14" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>14</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="15" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>15</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="16" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>16</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="17" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>17</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="18" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>18</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="19" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>19</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="20" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>20</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="21" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>21</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="22" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>22</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="23" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>23</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="24" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>24</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="25" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>25</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="26" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>26</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="27" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>27</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="28" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>28</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="29" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>29</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="30" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>30</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>31</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=9</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>32</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50101</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>33</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50102</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>34</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50103</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>35</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=1</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>36</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=2</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>37</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=3</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>38</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=4</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>39</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=5</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>40</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=6</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RNC01-3-3" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranCell</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranCell>
+
+<es:tCell>3</es:tCell>
+<es:cellReserved>1</es:cellReserved>
+<es:treSelection>2</es:treSelection>
+<es:qualMeasQuantity>2</es:qualMeasQuantity>
+<es:qHyst1>4</es:qHyst1>
+<es:qHyst2>4</es:qHyst2>
+<es:qQualMin>-24</es:qQualMin>
+<es:qRxLevMin>-115</es:qRxLevMin>
+<es:individualOffset>0</es:individualOffset>
+<es:pwrAdm>75</es:pwrAdm>
+<es:pwrOffset>5</es:pwrOffset>
+<es:pwrHyst>300</es:pwrHyst>
+<es:tmCongAction>2000</es:tmCongAction>
+<es:releaseAseDl>1</es:releaseAseDl>
+<es:aseDlAdm>240</es:aseDlAdm>
+<es:dlCodeAdm>80</es:dlCodeAdm>
+<es:aseUlAdm>160</es:aseUlAdm>
+<es:sf8Adm>8</es:sf8Adm>
+<es:sf32Adm>32</es:sf32Adm>
+<es:minPwrRl>-150</es:minPwrRl>
+<es:maxRate>40690</es:maxRate>
+<es:interRate>7760</es:interRate>
+<es:minimumRate>1590</es:minimumRate>
+<es:maxPwrMax>48</es:maxPwrMax>
+<es:interPwrMax>38</es:interPwrMax>
+<es:minPwrMax>0</es:minPwrMax>
+<es:compModeAdm>15</es:compModeAdm>
+<es:iFHyst>6000</es:iFHyst>
+<es:iFCong>621</es:iFCong>
+<es:interFreqFddMeasIndicator>0</es:interFreqFddMeasIndicator>
+<es:sRatSearch>4</es:sRatSearch>
+<es:sIntraSearch>0</es:sIntraSearch>
+<es:sInterSearch>0</es:sInterSearch>
+<es:fachMeasOccaCycLenCoeff>0</es:fachMeasOccaCycLenCoeff>
+
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:utranCellPosition></es:utranCellPosition>
+<es:maxTxPowerUl>24</es:maxTxPowerUl>
+
+<es:sib1PlmnScopeValueTag>0</es:sib1PlmnScopeValueTag>
+<es:sf16Adm>16</es:sf16Adm>
+<es:hoType>1</es:hoType>
+<es:usedFreqThresh2dEcno>-12</es:usedFreqThresh2dEcno>
+<es:usedFreqThresh2dRscp>-97</es:usedFreqThresh2dRscp>
+<es:administrativeState>0</es:administrativeState>
+<es:loadSharingGsmThreshold>75</es:loadSharingGsmThreshold>
+<es:loadSharingGsmFraction>100</es:loadSharingGsmFraction>
+<es:nInSyncInd>3</es:nInSyncInd>
+<es:rlFailureT>10</es:rlFailureT>
+<es:nOutSyncInd>10</es:nOutSyncInd>
+<es:sf4AdmUl>0</es:sf4AdmUl>
+<es:hardIfhoCorr>3</es:hardIfhoCorr>
+<es:hsdpaUsersAdm>10</es:hsdpaUsersAdm>
+<es:loadSharingMargin>0</es:loadSharingMargin>
+<es:sHcsRat>-105</es:sHcsRat>
+<es:sf16gAdm>16</es:sf16gAdm>
+<es:releaseAseDlNg>3</es:releaseAseDlNg>
+<es:tmCongActionNg>800</es:tmCongActionNg>
+<es:tmInitialG>3000</es:tmInitialG>
+<es:sf16AdmUl>16</es:sf16AdmUl>
+<es:sf8AdmUl>8</es:sf8AdmUl>
+<es:sf8gAdmUl>0</es:sf8gAdmUl>
+<es:iubLinkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=3</es:iubLinkRef>
+<es:eulNonServingCellUsersAdm>100</es:eulNonServingCellUsersAdm>
+<es:eulServingCellUsersAdm>32</es:eulServingCellUsersAdm>
+<es:agpsEnabled>1</es:agpsEnabled>
+<es:codeLoadThresholdDlSf128>100</es:codeLoadThresholdDlSf128>
+<es:pwrLoadThresholdDlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:pwrLoadThresholdDlSpeech>
+<es:aseLoadThresholdUlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:aseLoadThresholdUlSpeech>
+
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:rateSelectionPsInteractive>
+<es:channelType>0</es:channelType>
+<es:ulPrefRate>64</es:ulPrefRate>
+<es:dlPrefRate>64</es:dlPrefRate></es:rateSelectionPsInteractive>
+<es:hcsUsage>
+<es:idleMode>0</es:idleMode>
+<es:connectedMode>0</es:connectedMode></es:hcsUsage>
+<es:hcsSib3Config>
+<es:sSearchHcs>-105</es:sSearchHcs>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs></es:hcsSib3Config>
+</es:vsDataUtranCell>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataFach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataFach>
+
+<es:userLabel>Fach-3-3</es:userLabel>
+<es:maxFach1Power>18</es:maxFach1Power>
+<es:maxFach2Power>15</es:maxFach2Power>
+<es:sccpchOffset>0</es:sccpchOffset>
+<es:pOffset1Fach>0</es:pOffset1Fach>
+<es:pOffset3Fach>0</es:pOffset3Fach>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataFach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataRach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataRach>
+
+<es:userLabel>Rach-3-3</es:userLabel>
+<es:scramblingCodeWordNo>0</es:scramblingCodeWordNo>
+<es:preambleSignatures>65535</es:preambleSignatures>
+<es:subChannelNo>4095</es:subChannelNo>
+<es:aichTransmissionTiming>4</es:aichTransmissionTiming>
+<es:aichPower>-6</es:aichPower>
+<es:powerOffsetP0>3</es:powerOffsetP0>
+<es:powerOffsetPpm>-4</es:powerOffsetPpm>
+<es:preambleRetransMax>5</es:preambleRetransMax>
+<es:maxPreambleCycle>4</es:maxPreambleCycle>
+<es:constantValueCprach>-27</es:constantValueCprach>
+<es:spreadingFactor>64</es:spreadingFactor>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataRach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPch>
+
+<es:userLabel>Pch-3-3</es:userLabel>
+<es:pchPower>-4</es:pchPower>
+<es:pichPower>-7</es:pichPower>
+<es:sccpchOffset>20</es:sccpchOffset>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataPch>
+</xn:attributes>
+</xn:VsDataContainer><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-3-3</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-3-3</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataEul</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataEul>
+
+<es:userLabel>Eul-3-3</es:userLabel>
+<es:administrativeState>0</es:administrativeState>
+<es:numEagchCodes>1</es:numEagchCodes>
+<es:numEhichErgchCodes>1</es:numEhichErgchCodes>
+<es:eulMaxTargetRtwp>-499</es:eulMaxTargetRtwp>
+</es:vsDataEul>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataCoverageRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataCoverageRelation>
+
+<es:utranCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,UtranCell=RNC01-3-1</es:utranCellRef>
+<es:coverageIndicator>1</es:coverageIndicator>
+<es:hsPathlossThreshold>170</es:hsPathlossThreshold>
+</es:vsDataCoverageRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer></un:UtranCell>
+<un:UtranCell id="RNC01-4-1" modifier="create">
+<un:attributes>
+
+<un:userLabel>RNC01-4-1</un:userLabel>
+<un:cId>10</un:cId>
+<un:localCellId>1</un:localCellId>
+<un:uarfcnUl>12</un:uarfcnUl>
+<un:uarfcnDl>8</un:uarfcnDl>
+<un:primaryScramblingCode>10</un:primaryScramblingCode>
+<un:primaryCpichPower>300</un:primaryCpichPower>
+<un:maximumTransmissionPower>400</un:maximumTransmissionPower>
+<un:primarySchPower>-18</un:primarySchPower>
+<un:secondarySchPower>-35</un:secondarySchPower>
+<un:bchPower>-31</un:bchPower>
+<un:utranCellIubLink>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=4</un:utranCellIubLink>
+<un:lac>3432</un:lac>
+<un:rac>3433</un:rac>
+<un:sac>3434</un:sac>
+</un:attributes>
+</un:UtranCell>
+
+<un:UtranCell id="RNC01-4-1" modifier="update">
+
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>1</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>2</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>3</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>4</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>5</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>6</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>7</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>8</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>9</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>10</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="11" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>11</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="12" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>12</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="13" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>13</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="14" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>14</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="15" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>15</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="16" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>16</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="17" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>17</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="18" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>18</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="19" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>19</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="20" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>20</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="21" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>21</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="22" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>22</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="23" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>23</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="24" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>24</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="25" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>25</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="26" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>26</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="27" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>27</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="28" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>28</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="29" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>29</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="30" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>30</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>31</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=7</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>32</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=8</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>33</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=9</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>34</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50101</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>35</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50102</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>36</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50103</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>37</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=1</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>38</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=2</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>39</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=3</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>40</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=4</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RNC01-4-1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranCell</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranCell>
+
+<es:tCell>1</es:tCell>
+<es:cellReserved>1</es:cellReserved>
+<es:treSelection>2</es:treSelection>
+<es:qualMeasQuantity>2</es:qualMeasQuantity>
+<es:qHyst1>4</es:qHyst1>
+<es:qHyst2>4</es:qHyst2>
+<es:qQualMin>-24</es:qQualMin>
+<es:qRxLevMin>-115</es:qRxLevMin>
+<es:individualOffset>0</es:individualOffset>
+<es:pwrAdm>75</es:pwrAdm>
+<es:pwrOffset>5</es:pwrOffset>
+<es:pwrHyst>300</es:pwrHyst>
+<es:tmCongAction>2000</es:tmCongAction>
+<es:releaseAseDl>1</es:releaseAseDl>
+<es:aseDlAdm>240</es:aseDlAdm>
+<es:dlCodeAdm>80</es:dlCodeAdm>
+<es:aseUlAdm>160</es:aseUlAdm>
+<es:sf8Adm>8</es:sf8Adm>
+<es:sf32Adm>32</es:sf32Adm>
+<es:minPwrRl>-150</es:minPwrRl>
+<es:maxRate>40690</es:maxRate>
+<es:interRate>7760</es:interRate>
+<es:minimumRate>1590</es:minimumRate>
+<es:maxPwrMax>48</es:maxPwrMax>
+<es:interPwrMax>38</es:interPwrMax>
+<es:minPwrMax>0</es:minPwrMax>
+<es:compModeAdm>15</es:compModeAdm>
+<es:iFHyst>6000</es:iFHyst>
+<es:iFCong>621</es:iFCong>
+<es:interFreqFddMeasIndicator>0</es:interFreqFddMeasIndicator>
+<es:sRatSearch>4</es:sRatSearch>
+<es:sIntraSearch>0</es:sIntraSearch>
+<es:sInterSearch>0</es:sInterSearch>
+<es:fachMeasOccaCycLenCoeff>0</es:fachMeasOccaCycLenCoeff>
+
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:utranCellPosition></es:utranCellPosition>
+<es:maxTxPowerUl>24</es:maxTxPowerUl>
+
+<es:sib1PlmnScopeValueTag>0</es:sib1PlmnScopeValueTag>
+<es:sf16Adm>16</es:sf16Adm>
+<es:hoType>1</es:hoType>
+<es:usedFreqThresh2dEcno>-12</es:usedFreqThresh2dEcno>
+<es:usedFreqThresh2dRscp>-97</es:usedFreqThresh2dRscp>
+<es:administrativeState>0</es:administrativeState>
+<es:loadSharingGsmThreshold>75</es:loadSharingGsmThreshold>
+<es:loadSharingGsmFraction>100</es:loadSharingGsmFraction>
+<es:nInSyncInd>3</es:nInSyncInd>
+<es:rlFailureT>10</es:rlFailureT>
+<es:nOutSyncInd>10</es:nOutSyncInd>
+<es:sf4AdmUl>0</es:sf4AdmUl>
+<es:hardIfhoCorr>3</es:hardIfhoCorr>
+<es:hsdpaUsersAdm>10</es:hsdpaUsersAdm>
+<es:loadSharingMargin>0</es:loadSharingMargin>
+<es:sHcsRat>-105</es:sHcsRat>
+<es:sf16gAdm>16</es:sf16gAdm>
+<es:releaseAseDlNg>3</es:releaseAseDlNg>
+<es:tmCongActionNg>800</es:tmCongActionNg>
+<es:tmInitialG>3000</es:tmInitialG>
+<es:sf16AdmUl>16</es:sf16AdmUl>
+<es:sf8AdmUl>8</es:sf8AdmUl>
+<es:sf8gAdmUl>0</es:sf8gAdmUl>
+<es:iubLinkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=4</es:iubLinkRef>
+<es:eulNonServingCellUsersAdm>100</es:eulNonServingCellUsersAdm>
+<es:eulServingCellUsersAdm>32</es:eulServingCellUsersAdm>
+<es:agpsEnabled>1</es:agpsEnabled>
+<es:codeLoadThresholdDlSf128>100</es:codeLoadThresholdDlSf128>
+<es:pwrLoadThresholdDlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:pwrLoadThresholdDlSpeech>
+<es:aseLoadThresholdUlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:aseLoadThresholdUlSpeech>
+
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:rateSelectionPsInteractive>
+<es:channelType>0</es:channelType>
+<es:ulPrefRate>64</es:ulPrefRate>
+<es:dlPrefRate>64</es:dlPrefRate></es:rateSelectionPsInteractive>
+<es:hcsUsage>
+<es:idleMode>0</es:idleMode>
+<es:connectedMode>0</es:connectedMode></es:hcsUsage>
+<es:hcsSib3Config>
+<es:sSearchHcs>-105</es:sSearchHcs>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs></es:hcsSib3Config>
+</es:vsDataUtranCell>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataFach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataFach>
+
+<es:userLabel>Fach-4-1</es:userLabel>
+<es:maxFach1Power>18</es:maxFach1Power>
+<es:maxFach2Power>15</es:maxFach2Power>
+<es:sccpchOffset>0</es:sccpchOffset>
+<es:pOffset1Fach>0</es:pOffset1Fach>
+<es:pOffset3Fach>0</es:pOffset3Fach>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataFach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataRach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataRach>
+
+<es:userLabel>Rach-4-1</es:userLabel>
+<es:scramblingCodeWordNo>0</es:scramblingCodeWordNo>
+<es:preambleSignatures>65535</es:preambleSignatures>
+<es:subChannelNo>4095</es:subChannelNo>
+<es:aichTransmissionTiming>4</es:aichTransmissionTiming>
+<es:aichPower>-6</es:aichPower>
+<es:powerOffsetP0>3</es:powerOffsetP0>
+<es:powerOffsetPpm>-4</es:powerOffsetPpm>
+<es:preambleRetransMax>5</es:preambleRetransMax>
+<es:maxPreambleCycle>4</es:maxPreambleCycle>
+<es:constantValueCprach>-27</es:constantValueCprach>
+<es:spreadingFactor>64</es:spreadingFactor>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataRach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPch>
+
+<es:userLabel>Pch-4-1</es:userLabel>
+<es:pchPower>-4</es:pchPower>
+<es:pichPower>-7</es:pichPower>
+<es:sccpchOffset>20</es:sccpchOffset>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataPch>
+</xn:attributes>
+</xn:VsDataContainer><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-4-1</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-4-1</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataEul</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataEul>
+
+<es:userLabel>Eul-4-1</es:userLabel>
+<es:administrativeState>0</es:administrativeState>
+<es:numEagchCodes>1</es:numEagchCodes>
+<es:numEhichErgchCodes>1</es:numEhichErgchCodes>
+<es:eulMaxTargetRtwp>-499</es:eulMaxTargetRtwp>
+</es:vsDataEul>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataCoverageRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataCoverageRelation>
+
+<es:utranCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,UtranCell=RNC01-4-2</es:utranCellRef>
+<es:coverageIndicator>1</es:coverageIndicator>
+<es:hsPathlossThreshold>170</es:hsPathlossThreshold>
+</es:vsDataCoverageRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer></un:UtranCell>
+<un:UtranCell id="RNC01-4-2" modifier="create">
+<un:attributes>
+
+<un:userLabel>RNC01-4-2</un:userLabel>
+<un:cId>11</un:cId>
+<un:localCellId>2</un:localCellId>
+<un:uarfcnUl>12</un:uarfcnUl>
+<un:uarfcnDl>8</un:uarfcnDl>
+<un:primaryScramblingCode>11</un:primaryScramblingCode>
+<un:primaryCpichPower>300</un:primaryCpichPower>
+<un:maximumTransmissionPower>400</un:maximumTransmissionPower>
+<un:primarySchPower>-18</un:primarySchPower>
+<un:secondarySchPower>-35</un:secondarySchPower>
+<un:bchPower>-31</un:bchPower>
+<un:utranCellIubLink>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=4</un:utranCellIubLink>
+<un:lac>3432</un:lac>
+<un:rac>3433</un:rac>
+<un:sac>3435</un:sac>
+</un:attributes>
+</un:UtranCell>
+
+<un:UtranCell id="RNC01-4-2" modifier="update">
+
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>1</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>2</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>3</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>4</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>5</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>6</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>7</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>8</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>9</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>10</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="11" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>11</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="12" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>12</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="13" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>13</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="14" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>14</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="15" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>15</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="16" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>16</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="17" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>17</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="18" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>18</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="19" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>19</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="20" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>20</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="21" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>21</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="22" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>22</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="23" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>23</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="24" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>24</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="25" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>25</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="26" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>26</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="27" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>27</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="28" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>28</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="29" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>29</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="30" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>30</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>31</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=5</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>32</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=6</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>33</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=7</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>34</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=8</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>35</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=9</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>36</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50101</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>37</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50102</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>38</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50103</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>39</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=1</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>40</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=2</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RNC01-4-2" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranCell</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranCell>
+
+<es:tCell>2</es:tCell>
+<es:cellReserved>1</es:cellReserved>
+<es:treSelection>2</es:treSelection>
+<es:qualMeasQuantity>2</es:qualMeasQuantity>
+<es:qHyst1>4</es:qHyst1>
+<es:qHyst2>4</es:qHyst2>
+<es:qQualMin>-24</es:qQualMin>
+<es:qRxLevMin>-115</es:qRxLevMin>
+<es:individualOffset>0</es:individualOffset>
+<es:pwrAdm>75</es:pwrAdm>
+<es:pwrOffset>5</es:pwrOffset>
+<es:pwrHyst>300</es:pwrHyst>
+<es:tmCongAction>2000</es:tmCongAction>
+<es:releaseAseDl>1</es:releaseAseDl>
+<es:aseDlAdm>240</es:aseDlAdm>
+<es:dlCodeAdm>80</es:dlCodeAdm>
+<es:aseUlAdm>160</es:aseUlAdm>
+<es:sf8Adm>8</es:sf8Adm>
+<es:sf32Adm>32</es:sf32Adm>
+<es:minPwrRl>-150</es:minPwrRl>
+<es:maxRate>40690</es:maxRate>
+<es:interRate>7760</es:interRate>
+<es:minimumRate>1590</es:minimumRate>
+<es:maxPwrMax>48</es:maxPwrMax>
+<es:interPwrMax>38</es:interPwrMax>
+<es:minPwrMax>0</es:minPwrMax>
+<es:compModeAdm>15</es:compModeAdm>
+<es:iFHyst>6000</es:iFHyst>
+<es:iFCong>621</es:iFCong>
+<es:interFreqFddMeasIndicator>0</es:interFreqFddMeasIndicator>
+<es:sRatSearch>4</es:sRatSearch>
+<es:sIntraSearch>0</es:sIntraSearch>
+<es:sInterSearch>0</es:sInterSearch>
+<es:fachMeasOccaCycLenCoeff>0</es:fachMeasOccaCycLenCoeff>
+
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:utranCellPosition></es:utranCellPosition>
+<es:maxTxPowerUl>24</es:maxTxPowerUl>
+
+<es:sib1PlmnScopeValueTag>0</es:sib1PlmnScopeValueTag>
+<es:sf16Adm>16</es:sf16Adm>
+<es:hoType>1</es:hoType>
+<es:usedFreqThresh2dEcno>-12</es:usedFreqThresh2dEcno>
+<es:usedFreqThresh2dRscp>-97</es:usedFreqThresh2dRscp>
+<es:administrativeState>0</es:administrativeState>
+<es:loadSharingGsmThreshold>75</es:loadSharingGsmThreshold>
+<es:loadSharingGsmFraction>100</es:loadSharingGsmFraction>
+<es:nInSyncInd>3</es:nInSyncInd>
+<es:rlFailureT>10</es:rlFailureT>
+<es:nOutSyncInd>10</es:nOutSyncInd>
+<es:sf4AdmUl>0</es:sf4AdmUl>
+<es:hardIfhoCorr>3</es:hardIfhoCorr>
+<es:hsdpaUsersAdm>10</es:hsdpaUsersAdm>
+<es:loadSharingMargin>0</es:loadSharingMargin>
+<es:sHcsRat>-105</es:sHcsRat>
+<es:sf16gAdm>16</es:sf16gAdm>
+<es:releaseAseDlNg>3</es:releaseAseDlNg>
+<es:tmCongActionNg>800</es:tmCongActionNg>
+<es:tmInitialG>3000</es:tmInitialG>
+<es:sf16AdmUl>16</es:sf16AdmUl>
+<es:sf8AdmUl>8</es:sf8AdmUl>
+<es:sf8gAdmUl>0</es:sf8gAdmUl>
+<es:iubLinkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=4</es:iubLinkRef>
+<es:eulNonServingCellUsersAdm>100</es:eulNonServingCellUsersAdm>
+<es:eulServingCellUsersAdm>32</es:eulServingCellUsersAdm>
+<es:agpsEnabled>1</es:agpsEnabled>
+<es:codeLoadThresholdDlSf128>100</es:codeLoadThresholdDlSf128>
+<es:pwrLoadThresholdDlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:pwrLoadThresholdDlSpeech>
+<es:aseLoadThresholdUlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:aseLoadThresholdUlSpeech>
+
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:rateSelectionPsInteractive>
+<es:channelType>0</es:channelType>
+<es:ulPrefRate>64</es:ulPrefRate>
+<es:dlPrefRate>64</es:dlPrefRate></es:rateSelectionPsInteractive>
+<es:hcsUsage>
+<es:idleMode>0</es:idleMode>
+<es:connectedMode>0</es:connectedMode></es:hcsUsage>
+<es:hcsSib3Config>
+<es:sSearchHcs>-105</es:sSearchHcs>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs></es:hcsSib3Config>
+</es:vsDataUtranCell>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataFach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataFach>
+
+<es:userLabel>Fach-4-2</es:userLabel>
+<es:maxFach1Power>18</es:maxFach1Power>
+<es:maxFach2Power>15</es:maxFach2Power>
+<es:sccpchOffset>0</es:sccpchOffset>
+<es:pOffset1Fach>0</es:pOffset1Fach>
+<es:pOffset3Fach>0</es:pOffset3Fach>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataFach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataRach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataRach>
+
+<es:userLabel>Rach-4-2</es:userLabel>
+<es:scramblingCodeWordNo>0</es:scramblingCodeWordNo>
+<es:preambleSignatures>65535</es:preambleSignatures>
+<es:subChannelNo>4095</es:subChannelNo>
+<es:aichTransmissionTiming>4</es:aichTransmissionTiming>
+<es:aichPower>-6</es:aichPower>
+<es:powerOffsetP0>3</es:powerOffsetP0>
+<es:powerOffsetPpm>-4</es:powerOffsetPpm>
+<es:preambleRetransMax>5</es:preambleRetransMax>
+<es:maxPreambleCycle>4</es:maxPreambleCycle>
+<es:constantValueCprach>-27</es:constantValueCprach>
+<es:spreadingFactor>64</es:spreadingFactor>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataRach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPch>
+
+<es:userLabel>Pch-4-2</es:userLabel>
+<es:pchPower>-4</es:pchPower>
+<es:pichPower>-7</es:pichPower>
+<es:sccpchOffset>20</es:sccpchOffset>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataPch>
+</xn:attributes>
+</xn:VsDataContainer><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-4-2</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-4-2</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataEul</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataEul>
+
+<es:userLabel>Eul-4-2</es:userLabel>
+<es:administrativeState>0</es:administrativeState>
+<es:numEagchCodes>1</es:numEagchCodes>
+<es:numEhichErgchCodes>1</es:numEhichErgchCodes>
+<es:eulMaxTargetRtwp>-499</es:eulMaxTargetRtwp>
+</es:vsDataEul>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataCoverageRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataCoverageRelation>
+
+<es:utranCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,UtranCell=RNC01-4-3</es:utranCellRef>
+<es:coverageIndicator>1</es:coverageIndicator>
+<es:hsPathlossThreshold>170</es:hsPathlossThreshold>
+</es:vsDataCoverageRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer></un:UtranCell>
+<un:UtranCell id="RNC01-4-3" modifier="create">
+<un:attributes>
+
+<un:userLabel>RNC01-4-3</un:userLabel>
+<un:cId>12</un:cId>
+<un:localCellId>3</un:localCellId>
+<un:uarfcnUl>12</un:uarfcnUl>
+<un:uarfcnDl>8</un:uarfcnDl>
+<un:primaryScramblingCode>12</un:primaryScramblingCode>
+<un:primaryCpichPower>300</un:primaryCpichPower>
+<un:maximumTransmissionPower>400</un:maximumTransmissionPower>
+<un:primarySchPower>-18</un:primarySchPower>
+<un:secondarySchPower>-35</un:secondarySchPower>
+<un:bchPower>-31</un:bchPower>
+<un:utranCellIubLink>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=4</un:utranCellIubLink>
+<un:lac>3432</un:lac>
+<un:rac>3433</un:rac>
+<un:sac>3436</un:sac>
+</un:attributes>
+</un:UtranCell>
+
+<un:UtranCell id="RNC01-4-3" modifier="update">
+
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>1</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>2</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>3</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>4</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>5</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>6</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>7</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>8</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>9</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>10</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="11" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>11</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="12" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>12</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="13" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>13</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="14" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>14</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="15" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>15</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="16" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>16</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="17" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>17</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="18" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>18</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="19" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>19</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="20" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>20</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="21" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>21</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="22" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>22</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="23" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>23</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="24" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>24</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="25" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>25</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="26" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>26</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="27" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>27</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="28" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>28</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="29" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>29</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="30" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranRelation>
+
+<es:qOffset1sn>0</es:qOffset1sn>
+<es:qOffset2sn>0</es:qOffset2sn>
+<es:loadSharingCandidate>0</es:loadSharingCandidate>
+<es:selectionPriority>30</es:selectionPriority>
+
+<es:hcsSib11Config>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs>
+<es:penaltyTime>0</es:penaltyTime>
+<es:temporaryOffset1>0</es:temporaryOffset1>
+<es:temporaryOffset2>0</es:temporaryOffset2></es:hcsSib11Config>
+</es:vsDataUtranRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>31</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=3</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>32</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=4</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>33</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=5</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>34</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=6</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>35</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=7</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>36</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=8</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>37</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=9</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>38</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50101</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>39</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50102</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataGsmRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataGsmRelation>
+
+<es:qOffset1sn>7</es:qOffset1sn>
+<es:mobilityRelationType>0</es:mobilityRelationType>
+<es:selectionPriority>40</es:selectionPriority>
+<es:externalGsmCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,ExternalGsmNetwork=84,ExternalGsmCell=50103</es:externalGsmCellRef>
+</es:vsDataGsmRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="RNC01-4-3" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranCell</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranCell>
+
+<es:tCell>3</es:tCell>
+<es:cellReserved>1</es:cellReserved>
+<es:treSelection>2</es:treSelection>
+<es:qualMeasQuantity>2</es:qualMeasQuantity>
+<es:qHyst1>4</es:qHyst1>
+<es:qHyst2>4</es:qHyst2>
+<es:qQualMin>-24</es:qQualMin>
+<es:qRxLevMin>-115</es:qRxLevMin>
+<es:individualOffset>0</es:individualOffset>
+<es:pwrAdm>75</es:pwrAdm>
+<es:pwrOffset>5</es:pwrOffset>
+<es:pwrHyst>300</es:pwrHyst>
+<es:tmCongAction>2000</es:tmCongAction>
+<es:releaseAseDl>1</es:releaseAseDl>
+<es:aseDlAdm>240</es:aseDlAdm>
+<es:dlCodeAdm>80</es:dlCodeAdm>
+<es:aseUlAdm>160</es:aseUlAdm>
+<es:sf8Adm>8</es:sf8Adm>
+<es:sf32Adm>32</es:sf32Adm>
+<es:minPwrRl>-150</es:minPwrRl>
+<es:maxRate>40690</es:maxRate>
+<es:interRate>7760</es:interRate>
+<es:minimumRate>1590</es:minimumRate>
+<es:maxPwrMax>48</es:maxPwrMax>
+<es:interPwrMax>38</es:interPwrMax>
+<es:minPwrMax>0</es:minPwrMax>
+<es:compModeAdm>15</es:compModeAdm>
+<es:iFHyst>6000</es:iFHyst>
+<es:iFCong>621</es:iFCong>
+<es:interFreqFddMeasIndicator>0</es:interFreqFddMeasIndicator>
+<es:sRatSearch>4</es:sRatSearch>
+<es:sIntraSearch>0</es:sIntraSearch>
+<es:sInterSearch>0</es:sInterSearch>
+<es:fachMeasOccaCycLenCoeff>0</es:fachMeasOccaCycLenCoeff>
+
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:accessClassNBarred>0</es:accessClassNBarred>
+<es:accessClassNBarred>1</es:accessClassNBarred>
+<es:utranCellPosition></es:utranCellPosition>
+<es:maxTxPowerUl>24</es:maxTxPowerUl>
+
+<es:sib1PlmnScopeValueTag>0</es:sib1PlmnScopeValueTag>
+<es:sf16Adm>16</es:sf16Adm>
+<es:hoType>1</es:hoType>
+<es:usedFreqThresh2dEcno>-12</es:usedFreqThresh2dEcno>
+<es:usedFreqThresh2dRscp>-97</es:usedFreqThresh2dRscp>
+<es:administrativeState>0</es:administrativeState>
+<es:loadSharingGsmThreshold>75</es:loadSharingGsmThreshold>
+<es:loadSharingGsmFraction>100</es:loadSharingGsmFraction>
+<es:nInSyncInd>3</es:nInSyncInd>
+<es:rlFailureT>10</es:rlFailureT>
+<es:nOutSyncInd>10</es:nOutSyncInd>
+<es:sf4AdmUl>0</es:sf4AdmUl>
+<es:hardIfhoCorr>3</es:hardIfhoCorr>
+<es:hsdpaUsersAdm>10</es:hsdpaUsersAdm>
+<es:loadSharingMargin>0</es:loadSharingMargin>
+<es:sHcsRat>-105</es:sHcsRat>
+<es:sf16gAdm>16</es:sf16gAdm>
+<es:releaseAseDlNg>3</es:releaseAseDlNg>
+<es:tmCongActionNg>800</es:tmCongActionNg>
+<es:tmInitialG>3000</es:tmInitialG>
+<es:sf16AdmUl>16</es:sf16AdmUl>
+<es:sf8AdmUl>8</es:sf8AdmUl>
+<es:sf8gAdmUl>0</es:sf8gAdmUl>
+<es:iubLinkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,IubLink=4</es:iubLinkRef>
+<es:eulNonServingCellUsersAdm>100</es:eulNonServingCellUsersAdm>
+<es:eulServingCellUsersAdm>32</es:eulServingCellUsersAdm>
+<es:agpsEnabled>1</es:agpsEnabled>
+<es:codeLoadThresholdDlSf128>100</es:codeLoadThresholdDlSf128>
+<es:pwrLoadThresholdDlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:pwrLoadThresholdDlSpeech>
+<es:aseLoadThresholdUlSpeech>
+<es:amr12200>100</es:amr12200>
+<es:amr7950>100</es:amr7950>
+<es:amr5900>100</es:amr5900></es:aseLoadThresholdUlSpeech>
+
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>0</es:accessClassesBarredCs>
+<es:accessClassesBarredCs>1</es:accessClassesBarredCs>
+
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>0</es:accessClassesBarredPs>
+<es:accessClassesBarredPs>1</es:accessClassesBarredPs>
+<es:rateSelectionPsInteractive>
+<es:channelType>0</es:channelType>
+<es:ulPrefRate>64</es:ulPrefRate>
+<es:dlPrefRate>64</es:dlPrefRate></es:rateSelectionPsInteractive>
+<es:hcsUsage>
+<es:idleMode>0</es:idleMode>
+<es:connectedMode>0</es:connectedMode></es:hcsUsage>
+<es:hcsSib3Config>
+<es:sSearchHcs>-105</es:sSearchHcs>
+<es:hcsPrio>0</es:hcsPrio>
+<es:qHcs>0</es:qHcs></es:hcsSib3Config>
+</es:vsDataUtranCell>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataFach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataFach>
+
+<es:userLabel>Fach-4-3</es:userLabel>
+<es:maxFach1Power>18</es:maxFach1Power>
+<es:maxFach2Power>15</es:maxFach2Power>
+<es:sccpchOffset>0</es:sccpchOffset>
+<es:pOffset1Fach>0</es:pOffset1Fach>
+<es:pOffset3Fach>0</es:pOffset3Fach>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataFach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataRach</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataRach>
+
+<es:userLabel>Rach-4-3</es:userLabel>
+<es:scramblingCodeWordNo>0</es:scramblingCodeWordNo>
+<es:preambleSignatures>65535</es:preambleSignatures>
+<es:subChannelNo>4095</es:subChannelNo>
+<es:aichTransmissionTiming>4</es:aichTransmissionTiming>
+<es:aichPower>-6</es:aichPower>
+<es:powerOffsetP0>3</es:powerOffsetP0>
+<es:powerOffsetPpm>-4</es:powerOffsetPpm>
+<es:preambleRetransMax>5</es:preambleRetransMax>
+<es:maxPreambleCycle>4</es:maxPreambleCycle>
+<es:constantValueCprach>-27</es:constantValueCprach>
+<es:spreadingFactor>64</es:spreadingFactor>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataRach>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataPch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPch>
+
+<es:userLabel>Pch-4-3</es:userLabel>
+<es:pchPower>-4</es:pchPower>
+<es:pichPower>-7</es:pichPower>
+<es:sccpchOffset>20</es:sccpchOffset>
+<es:administrativeState>1</es:administrativeState>
+</es:vsDataPch>
+</xn:attributes>
+</xn:VsDataContainer><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-4-3</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataHsdsch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataHsdsch>
+
+<es:administrativeState>0</es:administrativeState>
+<es:userLabel>Hsdsch-4-3</es:userLabel>
+<es:numHsPdschCodes>5</es:numHsPdschCodes>
+<es:deltaAck1>4</es:deltaAck1>
+<es:deltaNack1>4</es:deltaNack1>
+<es:deltaAck2>8</es:deltaAck2>
+<es:deltaNack2>8</es:deltaNack2>
+<es:deltaCqi1>4</es:deltaCqi1>
+<es:deltaCqi2>8</es:deltaCqi2>
+<es:initialCqiRepetitionFactor>1</es:initialCqiRepetitionFactor>
+<es:initialAckNackRepetitionFactor>1</es:initialAckNackRepetitionFactor>
+<es:cqiFeedbackCycle>8</es:cqiFeedbackCycle>
+<es:hsMeasurementPowerOffset>0</es:hsMeasurementPowerOffset>
+<es:codeThresholdPdu656>6</es:codeThresholdPdu656>
+<es:numHsScchCodes>1</es:numHsScchCodes>
+</es:vsDataHsdsch>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataEul</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataEul>
+
+<es:userLabel>Eul-4-3</es:userLabel>
+<es:administrativeState>0</es:administrativeState>
+<es:numEagchCodes>1</es:numEagchCodes>
+<es:numEhichErgchCodes>1</es:numEhichErgchCodes>
+<es:eulMaxTargetRtwp>-499</es:eulMaxTargetRtwp>
+</es:vsDataEul>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataCoverageRelation</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataCoverageRelation>
+
+<es:utranCellRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,UtranCell=RNC01-4-1</es:utranCellRef>
+<es:coverageIndicator>1</es:coverageIndicator>
+<es:hsPathlossThreshold>170</es:hsPathlossThreshold>
+</es:vsDataCoverageRelation>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer></un:UtranCell>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataRncFunction</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataRncFunction>
+
+<es:mncLength>2</es:mncLength>
+<es:emergencyCallRedirect>0</es:emergencyCallRedirect>
+<es:loadSharingDirRetryEnabled>0</es:loadSharingDirRetryEnabled>
+<es:hsCellChangeAllowed>0</es:hsCellChangeAllowed>
+<es:hsOnlyBestCell>1</es:hsOnlyBestCell>
+
+<es:aliasPlmnIdentities>
+<es:mcc>353</es:mcc>
+<es:mnc>77</es:mnc>
+<es:mncLength>2</es:mncLength></es:aliasPlmnIdentities>
+<es:counterAlarmCeaseLimit>95</es:counterAlarmCeaseLimit>
+<es:counterAlarmThreshold>80</es:counterAlarmThreshold>
+<es:counterWarningAlarmCeaseLimit>5</es:counterWarningAlarmCeaseLimit>
+<es:ctrFileSize>5000</es:ctrFileSize>
+<es:gpehDataLevel>0</es:gpehDataLevel>
+<es:gpehFileSize>15000</es:gpehFileSize>
+<es:loadSharingRrcEnabled>0</es:loadSharingRrcEnabled>
+<es:uetrFileSize>275</es:uetrFileSize>
+<es:networkResourceIdentifierLengthCs>0</es:networkResourceIdentifierLengthCs>
+<es:networkResourceIdentifierLengthPs>0</es:networkResourceIdentifierLengthPs>
+<es:hsToDchTrigger>
+<es:servHsChangeInterRnc>0</es:servHsChangeInterRnc>
+<es:servHsChangeIntraRnc>0</es:servHsChangeIntraRnc>
+<es:changeOfBestCellIntraRnc>0</es:changeOfBestCellIntraRnc>
+<es:poorQualityDetected>0</es:poorQualityDetected>
+<es:changeOfBestCellInterRnc>0</es:changeOfBestCellInterRnc></es:hsToDchTrigger>
+<es:ecLocationAttemptUmts>0</es:ecLocationAttemptUmts>
+<es:ecCnSbhoRequestIgnore>0</es:ecCnSbhoRequestIgnore>
+<es:ecCnPriorityLevel>7</es:ecCnPriorityLevel>
+<es:ecSbhoTimer>6</es:ecSbhoTimer>
+<es:primaryCnOperatorRef>0</es:primaryCnOperatorRef>
+</es:vsDataRncFunction>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataUePositioning</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUePositioning>
+
+<es:enabledPositioningFeatures>0</es:enabledPositioningFeatures>
+</es:vsDataUePositioning>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataUeMeasControl</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUeMeasControl>
+
+<es:userLabel> </es:userLabel>
+<es:reportingRange1a>6</es:reportingRange1a>
+<es:reportingRange1b>10</es:reportingRange1b>
+<es:hysteresis1c>2</es:hysteresis1c>
+<es:hysteresis1d>15</es:hysteresis1d>
+<es:hysteresis2d>0</es:hysteresis2d>
+<es:hysteresis2f>0</es:hysteresis2f>
+<es:gsmThresh3a>-102</es:gsmThresh3a>
+<es:hysteresis3a>0</es:hysteresis3a>
+<es:measQuantity1>2</es:measQuantity1>
+<es:ueTxPowerThresh6a>21</es:ueTxPowerThresh6a>
+<es:ueTxPowerThresh6b>18</es:ueTxPowerThresh6b>
+<es:usedFreqThresh2dEcnoDrnc>-12</es:usedFreqThresh2dEcnoDrnc>
+<es:usedFreqThresh2dRscpDrnc>-97</es:usedFreqThresh2dRscpDrnc>
+<es:usedFreqRelThresh2fEcno>1</es:usedFreqRelThresh2fEcno>
+<es:usedFreqRelThresh2fRscp>3</es:usedFreqRelThresh2fRscp>
+<es:hyst4_2b>10</es:hyst4_2b>
+<es:nonUsedFreqThresh4_2bEcno>-11</es:nonUsedFreqThresh4_2bEcno>
+<es:nonUsedFreqThresh4_2bRscp>-94</es:nonUsedFreqThresh4_2bRscp>
+<es:timeToTrigger1a>11</es:timeToTrigger1a>
+<es:hysteresis1a>0</es:hysteresis1a>
+<es:timeToTrigger1b>12</es:timeToTrigger1b>
+<es:hysteresis1b>0</es:hysteresis1b>
+<es:timeToTrigger1c>11</es:timeToTrigger1c>
+<es:timeToTrigger1d>14</es:timeToTrigger1d>
+<es:timeToTrigger3a>6</es:timeToTrigger3a>
+<es:reportingInterval1a>3</es:reportingInterval1a>
+<es:reportingInterval1c>3</es:reportingInterval1c>
+<es:timeTrigg6a>320</es:timeTrigg6a>
+<es:timeTrigg6b>1280</es:timeTrigg6b>
+<es:timeTrigg4_2b>100</es:timeTrigg4_2b>
+<es:hsHysteresis1d>10</es:hsHysteresis1d>
+<es:hsQualityEstimate>1</es:hsQualityEstimate>
+<es:hsTimeToTrigger1d>640</es:hsTimeToTrigger1d>
+<es:filterCoefficient1>2</es:filterCoefficient1>
+<es:filterCoefficient2>2</es:filterCoefficient2>
+<es:utranFilterCoefficient3>2</es:utranFilterCoefficient3>
+<es:gsmFilterCoefficient3>1</es:gsmFilterCoefficient3>
+<es:filterCoeff6>19</es:filterCoeff6>
+<es:filterCoeff4_2b>2</es:filterCoeff4_2b>
+<es:w1a>0</es:w1a>
+<es:w1b>0</es:w1b>
+<es:usedFreqW2d>0</es:usedFreqW2d>
+<es:usedFreqW2f>0</es:usedFreqW2f>
+<es:usedFreqW4_2b>0</es:usedFreqW4_2b>
+<es:utranW3a>0</es:utranW3a>
+<es:nonUsedFreqW4_2b>0</es:nonUsedFreqW4_2b>
+<es:timeToTrigger2dEcno>320</es:timeToTrigger2dEcno>
+<es:timeToTrigger2fEcno>1280</es:timeToTrigger2fEcno>
+<es:utranRelThresh3aEcno>-1</es:utranRelThresh3aEcno>
+<es:utranRelThresh3aRscp>-3</es:utranRelThresh3aRscp>
+<es:usedFreqRelThresh4_2bEcno>-1</es:usedFreqRelThresh4_2bEcno>
+<es:usedFreqRelThresh4_2bRscp>-3</es:usedFreqRelThresh4_2bRscp>
+<es:timeToTrigger2dRscp>320</es:timeToTrigger2dRscp>
+<es:timeToTrigger2fRscp>1280</es:timeToTrigger2fRscp>
+<es:utranRelThreshRscp>5</es:utranRelThreshRscp>
+<es:event1dRncThreshold>4</es:event1dRncThreshold>
+<es:event1dRncOffset>0</es:event1dRncOffset>
+<es:timeToTrigger6d>320</es:timeToTrigger6d>
+<es:txPowerConnQualMonEnabled>1</es:txPowerConnQualMonEnabled>
+</es:vsDataUeMeasControl>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSid</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataSid>
+
+<es:updateCellReattsNo>5</es:updateCellReattsNo>
+<es:noOfMaxDrxCycles>1</es:noOfMaxDrxCycles>
+<es:noOfMibValueTagRetrans>0</es:noOfMibValueTagRetrans>
+<es:sib1>
+<es:sib1RepPeriod>32</es:sib1RepPeriod>
+<es:sib1StartPos>4</es:sib1StartPos></es:sib1>
+<es:sib11>
+<es:sib11RepPeriod>128</es:sib11RepPeriod>
+<es:sib11StartPos>20</es:sib11StartPos></es:sib11>
+<es:sib12>
+<es:sib12RepPeriod>32</es:sib12RepPeriod>
+<es:sib12StartPos>14</es:sib12StartPos></es:sib12>
+<es:sib3>
+<es:sib3RepPeriod>16</es:sib3RepPeriod>
+<es:sib3StartPos>2</es:sib3StartPos></es:sib3>
+<es:sib5>
+<es:sib5RepPeriod>32</es:sib5RepPeriod>
+<es:sib5StartPos>6</es:sib5StartPos></es:sib5>
+<es:sib7>
+<es:sib7RepPeriod>16</es:sib7RepPeriod>
+<es:sib7StartPos>2</es:sib7StartPos></es:sib7>
+<es:sib7ExpirationTimeFactor>1</es:sib7ExpirationTimeFactor>
+<es:sib2>
+<es:sib2RepPeriod>128</es:sib2RepPeriod>
+<es:sib2StartPos>118</es:sib2StartPos></es:sib2>
+</es:vsDataSid>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataSecurityHandling</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataSecurityHandling>
+
+<es:ciphering>1</es:ciphering>
+</es:vsDataSecurityHandling>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataRrc</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataRrc>
+
+<es:t305>3</es:t305>
+</es:vsDataRrc>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataRcs</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataRcs>
+
+<es:dchRcLostT>50</es:dchRcLostT>
+<es:cchWaitCuT>9</es:cchWaitCuT>
+<es:hsDschRcLostT>100</es:hsDschRcLostT>
+</es:vsDataRcs>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataRabHandling</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataRabHandling>
+
+<es:psStreamingInactivityTimer>30</es:psStreamingInactivityTimer>
+<es:activeQueueMgmt>0</es:activeQueueMgmt>
+<es:dscpValuePsStreaming>18</es:dscpValuePsStreaming>
+<es:state128_128Supported>0</es:state128_128Supported>
+</es:vsDataRabHandling>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataPowerControl</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPowerControl>
+
+<es:cBackOff>0</es:cBackOff>
+<es:ulOuterLoopRegulator>1</es:ulOuterLoopRegulator>
+<es:ulSirStep>10</es:ulSirStep>
+<es:sirMin>-82</es:sirMin>
+<es:sirMax>100</es:sirMax>
+<es:dlPcMethod>3</es:dlPcMethod>
+<es:cPO>0</es:cPO>
+<es:pO1>0</es:pO1>
+<es:pO2>12</es:pO2>
+<es:pO3>12</es:pO3>
+<es:ecNoPcpichDefault>-16</es:ecNoPcpichDefault>
+<es:pcpichPowerDefault>33</es:pcpichPowerDefault>
+<es:fixedPowerDl>65</es:fixedPowerDl>
+<es:cNbifho>10</es:cNbifho>
+<es:fixedRefPower>65</es:fixedRefPower>
+<es:initShoPowerParam>-2</es:initShoPowerParam>
+<es:dlInitSirTarget>41</es:dlInitSirTarget>
+<es:ulInitSirTargetExtraHigh>92</es:ulInitSirTargetExtraHigh>
+<es:ulInitSirTargetHigh>82</es:ulInitSirTargetHigh>
+<es:ulInitSirTargetLow>49</es:ulInitSirTargetLow>
+<es:ulInitSirTargetSrb>57</es:ulInitSirTargetSrb>
+<es:transmissionTargetError>10</es:transmissionTargetError>
+<es:ulInitSirTargetEdch>70</es:ulInitSirTargetEdch>
+</es:vsDataPowerControl>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataPaging</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataPaging>
+
+<es:cnDrxCycleLengthCs>6</es:cnDrxCycleLengthCs>
+<es:cnDrxCycleLengthPs>7</es:cnDrxCycleLengthPs>
+<es:noOfPagingRecordTransm>2</es:noOfPagingRecordTransm>
+<es:utranDrxCycleLength>5</es:utranDrxCycleLength>
+</es:vsDataPaging>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataHandover</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataHandover>
+
+<es:maxActiveSet>3</es:maxActiveSet>
+<es:fddGsmHOSupp>0</es:fddGsmHOSupp>
+<es:selHoSup>0</es:selHoSup>
+<es:timeReleaseIuPs>10</es:timeReleaseIuPs>
+<es:gsmAmountPropRepeat>4</es:gsmAmountPropRepeat>
+<es:gsmPropRepeatInterval>5</es:gsmPropRepeatInterval>
+<es:ifhoPropRepeatInterval>5</es:ifhoPropRepeatInterval>
+<es:ifhoAmountPropRepeat>4</es:ifhoAmountPropRepeat>
+<es:fddIfhoSupp>0</es:fddIfhoSupp>
+<es:releaseConnOffset>120</es:releaseConnOffset>
+<es:maxGsmMonSubset>32</es:maxGsmMonSubset>
+<es:maxIefMonSubset>32</es:maxIefMonSubset>
+<es:cnhhoSupp>0</es:cnhhoSupp>
+<es:interFreqCnhhoPenaltyEcno>30</es:interFreqCnhhoPenaltyEcno>
+<es:interFreqCnhhoPenaltyRscp>30</es:interFreqCnhhoPenaltyRscp>
+<es:intraFreqCnhhoPenalty>30</es:intraFreqCnhhoPenalty>
+<es:intraFreqCnhhoWeight>0</es:intraFreqCnhhoWeight>
+<es:tmStopGsmMeas>20</es:tmStopGsmMeas>
+<es:eulReservedHwBandwidthSchedDataNonServCell>128</es:eulReservedHwBandwidthSchedDataNonServCell>
+</es:vsDataHandover>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataChannelSwitching</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataChannelSwitching>
+
+<es:dlRlcBufUpswitch>500</es:dlRlcBufUpswitch>
+<es:ulRlcBufUpswitch>256</es:ulRlcBufUpswitch>
+<es:downswitchThreshold>0</es:downswitchThreshold>
+<es:downswitchTimerThreshold>0</es:downswitchTimerThreshold>
+<es:downswitchTimer>10</es:downswitchTimer>
+<es:dlRlcBufUpswitchMrab>0</es:dlRlcBufUpswitchMrab>
+<es:ulRlcBufUpswitchMrab>8</es:ulRlcBufUpswitchMrab>
+<es:upswitchTimer>5</es:upswitchTimer>
+<es:coverageTimer>10</es:coverageTimer>
+<es:inactivityTimer>120</es:inactivityTimer>
+<es:downswitchPwrMargin>2</es:downswitchPwrMargin>
+<es:reportHysteresis>6</es:reportHysteresis>
+<es:upswitchPwrMargin>6</es:upswitchPwrMargin>
+<es:downswitchTimerUp>60</es:downswitchTimerUp>
+<es:downswitchTimerSp>2</es:downswitchTimerSp>
+<es:hsdschInactivityTimer>2</es:hsdschInactivityTimer>
+<es:bandwidthMarginUl>0</es:bandwidthMarginUl>
+<es:upswitchTimerUl>5</es:upswitchTimerUl>
+<es:bandwidthMargin>90</es:bandwidthMargin>
+<es:dlDownswitchBandwidthMargin>0</es:dlDownswitchBandwidthMargin>
+<es:dlThroughputAllowUpswitchThreshold>0</es:dlThroughputAllowUpswitchThreshold>
+<es:dlThroughputDownswitchTimer>20</es:dlThroughputDownswitchTimer>
+<es:inactivityTimerPch>30</es:inactivityTimerPch>
+<es:ulThroughputAllowUpswitchThreshold>0</es:ulThroughputAllowUpswitchThreshold>
+<es:ulThroughputDownswitchTimer>20</es:ulThroughputDownswitchTimer>
+<es:ulDownswitchBandwidthMargin>0</es:ulDownswitchBandwidthMargin>
+<es:inactivityTimeMultiPsInteractive>50</es:inactivityTimeMultiPsInteractive>
+</es:vsDataChannelSwitching>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataCchFrameSynch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataCchFrameSynch>
+
+<es:dto>10</es:dto>
+<es:doStep>1</es:doStep>
+<es:toAWS>30</es:toAWS>
+<es:toAWE>2</es:toAWE>
+<es:toAE>195</es:toAE>
+</es:vsDataCchFrameSynch>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataDchFrameSynch</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataDchFrameSynch>
+
+<es:dto>10</es:dto>
+<es:doStep>1</es:doStep>
+<es:toAWS>30</es:toAWS>
+<es:toAWE>2</es:toAWE>
+<es:toAE>195</es:toAE>
+<es:uto>10</es:uto>
+<es:uoStep>1</es:uoStep>
+<es:toAWEUl>2</es:toAWEUl>
+<es:toAEUl>95</es:toAEUl>
+<es:userLabel> </es:userLabel>
+<es:toAWSUl>40</es:toAWSUl>
+</es:vsDataDchFrameSynch>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataRncModule</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataRncModule>
+
+<es:userLabel> </es:userLabel>
+</es:vsDataRncModule>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUtranNetwork</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUtranNetwork>
+
+<es:userLabel> </es:userLabel>
+<es:aliasPlmnIdentities></es:aliasPlmnIdentities>
+<es:plmnIdentity>
+<es:mcc>353</es:mcc>
+<es:mnc>77</es:mnc>
+<es:mncLength>2</es:mncLength></es:plmnIdentity>
+</es:vsDataUtranNetwork>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIurLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIurLink>
+
+<es:userLabel> </es:userLabel>
+<es:mcc>353</es:mcc>
+<es:mnc>77</es:mnc>
+<es:mncLength>2</es:mncLength>
+<es:rncId>2</es:rncId>
+<es:aliasPlmnIdentities></es:aliasPlmnIdentities>
+<es:utranNetworkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,vsDataUtranNetwork=1</es:utranNetworkRef>
+<es:cellCapabilityControl>
+<es:hsdschSupport>0</es:hsdschSupport>
+<es:edchSupport>0</es:edchSupport></es:cellCapabilityControl>
+<es:hspaPathlossThreshold>170</es:hspaPathlossThreshold>
+<es:userPlaneTransportOption>
+<es:atm>0</es:atm>
+<es:ipv4>0</es:ipv4></es:userPlaneTransportOption>
+</es:vsDataIurLink>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIurLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIurLink>
+
+<es:userLabel> </es:userLabel>
+<es:mcc>353</es:mcc>
+<es:mnc>77</es:mnc>
+<es:mncLength>2</es:mncLength>
+<es:rncId>3</es:rncId>
+<es:aliasPlmnIdentities></es:aliasPlmnIdentities>
+<es:utranNetworkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,vsDataUtranNetwork=1</es:utranNetworkRef>
+<es:cellCapabilityControl>
+<es:hsdschSupport>0</es:hsdschSupport>
+<es:edchSupport>0</es:edchSupport></es:cellCapabilityControl>
+<es:hspaPathlossThreshold>170</es:hspaPathlossThreshold>
+<es:userPlaneTransportOption>
+<es:atm>0</es:atm>
+<es:ipv4>0</es:ipv4></es:userPlaneTransportOption>
+</es:vsDataIurLink>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIurLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIurLink>
+
+<es:userLabel> </es:userLabel>
+<es:mcc>353</es:mcc>
+<es:mnc>77</es:mnc>
+<es:mncLength>2</es:mncLength>
+<es:rncId>4</es:rncId>
+<es:aliasPlmnIdentities></es:aliasPlmnIdentities>
+<es:utranNetworkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,vsDataUtranNetwork=1</es:utranNetworkRef>
+<es:cellCapabilityControl>
+<es:hsdschSupport>0</es:hsdschSupport>
+<es:edchSupport>0</es:edchSupport></es:cellCapabilityControl>
+<es:hspaPathlossThreshold>170</es:hspaPathlossThreshold>
+<es:userPlaneTransportOption>
+<es:atm>0</es:atm>
+<es:ipv4>0</es:ipv4></es:userPlaneTransportOption>
+</es:vsDataIurLink>
+</xn:attributes>
+</xn:VsDataContainer><xn:VsDataContainer id="96" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIurLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataIurLink>
+
+<es:userLabel> </es:userLabel>
+<es:mcc>353</es:mcc>
+<es:mnc>96</es:mnc>
+<es:mncLength>2</es:mncLength>
+<es:rncId>96</es:rncId>
+<es:aliasPlmnIdentities></es:aliasPlmnIdentities>
+<es:utranNetworkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,vsDataUtranNetwork=1</es:utranNetworkRef>
+<es:cellCapabilityControl>
+<es:hsdschSupport>0</es:hsdschSupport>
+<es:edchSupport>0</es:edchSupport></es:cellCapabilityControl>
+<es:hspaPathlossThreshold>170</es:hspaPathlossThreshold>
+<es:userPlaneTransportOption>
+<es:atm>0</es:atm>
+<es:ipv4>0</es:ipv4></es:userPlaneTransportOption>
+</es:vsDataIurLink></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="96" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataIurLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIurLink>
+
+<es:userLabel> </es:userLabel>
+<es:mcc>353</es:mcc>
+<es:mnc>96</es:mnc>
+<es:mncLength>2</es:mncLength>
+<es:rncId>96</es:rncId>
+<es:aliasPlmnIdentities></es:aliasPlmnIdentities>
+<es:utranNetworkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,vsDataUtranNetwork=1</es:utranNetworkRef>
+<es:cellCapabilityControl>
+<es:hsdschSupport>0</es:hsdschSupport>
+<es:edchSupport>0</es:edchSupport></es:cellCapabilityControl>
+<es:hspaPathlossThreshold>170</es:hspaPathlossThreshold>
+<es:userPlaneTransportOption>
+<es:atm>0</es:atm>
+<es:ipv4>0</es:ipv4></es:userPlaneTransportOption>
+</es:vsDataIurLink>
+</xn:attributes>
+</xn:VsDataContainer><xn:VsDataContainer id="97" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIurLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataIurLink>
+
+<es:userLabel> </es:userLabel>
+<es:mcc>353</es:mcc>
+<es:mnc>97</es:mnc>
+<es:mncLength>2</es:mncLength>
+<es:rncId>97</es:rncId>
+<es:aliasPlmnIdentities></es:aliasPlmnIdentities>
+<es:utranNetworkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,vsDataUtranNetwork=1</es:utranNetworkRef>
+<es:cellCapabilityControl>
+<es:hsdschSupport>0</es:hsdschSupport>
+<es:edchSupport>0</es:edchSupport></es:cellCapabilityControl>
+<es:hspaPathlossThreshold>170</es:hspaPathlossThreshold>
+<es:userPlaneTransportOption>
+<es:atm>0</es:atm>
+<es:ipv4>0</es:ipv4></es:userPlaneTransportOption>
+</es:vsDataIurLink></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="97" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataIurLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIurLink>
+
+<es:userLabel> </es:userLabel>
+<es:mcc>353</es:mcc>
+<es:mnc>97</es:mnc>
+<es:mncLength>2</es:mncLength>
+<es:rncId>97</es:rncId>
+<es:aliasPlmnIdentities></es:aliasPlmnIdentities>
+<es:utranNetworkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,vsDataUtranNetwork=1</es:utranNetworkRef>
+<es:cellCapabilityControl>
+<es:hsdschSupport>0</es:hsdschSupport>
+<es:edchSupport>0</es:edchSupport></es:cellCapabilityControl>
+<es:hspaPathlossThreshold>170</es:hspaPathlossThreshold>
+<es:userPlaneTransportOption>
+<es:atm>0</es:atm>
+<es:ipv4>0</es:ipv4></es:userPlaneTransportOption>
+</es:vsDataIurLink>
+</xn:attributes>
+</xn:VsDataContainer><xn:VsDataContainer id="98" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIurLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataIurLink>
+
+<es:userLabel> </es:userLabel>
+<es:mcc>353</es:mcc>
+<es:mnc>98</es:mnc>
+<es:mncLength>2</es:mncLength>
+<es:rncId>98</es:rncId>
+<es:aliasPlmnIdentities></es:aliasPlmnIdentities>
+<es:utranNetworkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,vsDataUtranNetwork=1</es:utranNetworkRef>
+<es:cellCapabilityControl>
+<es:hsdschSupport>0</es:hsdschSupport>
+<es:edchSupport>0</es:edchSupport></es:cellCapabilityControl>
+<es:hspaPathlossThreshold>170</es:hspaPathlossThreshold>
+<es:userPlaneTransportOption>
+<es:atm>0</es:atm>
+<es:ipv4>0</es:ipv4></es:userPlaneTransportOption>
+</es:vsDataIurLink></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="98" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataIurLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIurLink>
+
+<es:userLabel> </es:userLabel>
+<es:mcc>353</es:mcc>
+<es:mnc>98</es:mnc>
+<es:mncLength>2</es:mncLength>
+<es:rncId>98</es:rncId>
+<es:aliasPlmnIdentities></es:aliasPlmnIdentities>
+<es:utranNetworkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,vsDataUtranNetwork=1</es:utranNetworkRef>
+<es:cellCapabilityControl>
+<es:hsdschSupport>0</es:hsdschSupport>
+<es:edchSupport>0</es:edchSupport></es:cellCapabilityControl>
+<es:hspaPathlossThreshold>170</es:hspaPathlossThreshold>
+<es:userPlaneTransportOption>
+<es:atm>0</es:atm>
+<es:ipv4>0</es:ipv4></es:userPlaneTransportOption>
+</es:vsDataIurLink>
+</xn:attributes>
+</xn:VsDataContainer><xn:VsDataContainer id="99" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataIurLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataIurLink>
+
+<es:userLabel> </es:userLabel>
+<es:mcc>353</es:mcc>
+<es:mnc>99</es:mnc>
+<es:mncLength>2</es:mncLength>
+<es:rncId>99</es:rncId>
+<es:aliasPlmnIdentities></es:aliasPlmnIdentities>
+<es:utranNetworkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,vsDataUtranNetwork=1</es:utranNetworkRef>
+<es:cellCapabilityControl>
+<es:hsdschSupport>0</es:hsdschSupport>
+<es:edchSupport>0</es:edchSupport></es:cellCapabilityControl>
+<es:hspaPathlossThreshold>170</es:hspaPathlossThreshold>
+<es:userPlaneTransportOption>
+<es:atm>0</es:atm>
+<es:ipv4>0</es:ipv4></es:userPlaneTransportOption>
+</es:vsDataIurLink></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="99" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataIurLink</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataIurLink>
+
+<es:userLabel> </es:userLabel>
+<es:mcc>353</es:mcc>
+<es:mnc>99</es:mnc>
+<es:mncLength>2</es:mncLength>
+<es:rncId>99</es:rncId>
+<es:aliasPlmnIdentities></es:aliasPlmnIdentities>
+<es:utranNetworkRef>SubNetwork=WEOSSRC1_ROOT_MO_R,SubNetwork=RNC33,MeContext=SRNC001,ManagedElement=1,RncFunction=1,vsDataUtranNetwork=1</es:utranNetworkRef>
+<es:cellCapabilityControl>
+<es:hsdschSupport>0</es:hsdschSupport>
+<es:edchSupport>0</es:edchSupport></es:cellCapabilityControl>
+<es:hspaPathlossThreshold>170</es:hspaPathlossThreshold>
+<es:userPlaneTransportOption>
+<es:atm>0</es:atm>
+<es:ipv4>0</es:ipv4></es:userPlaneTransportOption>
+</es:vsDataIurLink>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUra</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUra>
+
+<es:userLabel>Ura1</es:userLabel>
+<es:uraIdentity>1</es:uraIdentity>
+</es:vsDataUra>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUra</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUra>
+
+<es:userLabel>Ura2</es:userLabel>
+<es:uraIdentity>2</es:uraIdentity>
+</es:vsDataUra>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUra</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUra>
+
+<es:userLabel>Ura3</es:userLabel>
+<es:uraIdentity>3</es:uraIdentity>
+</es:vsDataUra>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUra</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUra>
+
+<es:userLabel>Ura4</es:userLabel>
+<es:uraIdentity>4</es:uraIdentity>
+</es:vsDataUra>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="5" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUra</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUra>
+
+<es:userLabel>Ura5</es:userLabel>
+<es:uraIdentity>5</es:uraIdentity>
+</es:vsDataUra>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="6" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUra</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUra>
+
+<es:userLabel>Ura6</es:userLabel>
+<es:uraIdentity>6</es:uraIdentity>
+</es:vsDataUra>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="7" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUra</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUra>
+
+<es:userLabel>Ura7</es:userLabel>
+<es:uraIdentity>7</es:uraIdentity>
+</es:vsDataUra>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="8" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUra</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUra>
+
+<es:userLabel>Ura8</es:userLabel>
+<es:uraIdentity>8</es:uraIdentity>
+</es:vsDataUra>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="9" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUra</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUra>
+
+<es:userLabel>Ura9</es:userLabel>
+<es:uraIdentity>9</es:uraIdentity>
+</es:vsDataUra>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="10" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUra</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUra>
+
+<es:userLabel>Ura10</es:userLabel>
+<es:uraIdentity>10</es:uraIdentity>
+</es:vsDataUra>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataCnOperator</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataCnOperator>
+
+<es:userLabel> </es:userLabel>
+<es:plmnIdentity>
+<es:mcc>1</es:mcc>
+<es:mnc>1</es:mnc>
+<es:mncLength>2</es:mncLength></es:plmnIdentity>
+<es:iphoNetworkRefsUtran></es:iphoNetworkRefsUtran>
+<es:iphoNetworkRefsGsm></es:iphoNetworkRefsGsm>
+<es:equivalentPlmnIdentities></es:equivalentPlmnIdentities>
+</es:vsDataCnOperator>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataWcdmaCarrier</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataWcdmaCarrier>
+
+<es:userLabel> </es:userLabel>
+<es:defaultHoType>1</es:defaultHoType>
+<es:freqBand>0</es:freqBand>
+<es:sib5bisEnabled>0</es:sib5bisEnabled>
+<es:uarfcnDl>0</es:uarfcnDl>
+</es:vsDataWcdmaCarrier>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataCnOperator</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataCnOperator>
+
+<es:userLabel> </es:userLabel>
+<es:plmnIdentity>
+<es:mcc>1</es:mcc>
+<es:mnc>1</es:mnc>
+<es:mncLength>2</es:mncLength></es:plmnIdentity>
+<es:iphoNetworkRefsUtran></es:iphoNetworkRefsUtran>
+<es:iphoNetworkRefsGsm></es:iphoNetworkRefsGsm>
+<es:equivalentPlmnIdentities></es:equivalentPlmnIdentities>
+</es:vsDataCnOperator>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="2" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataWcdmaCarrier</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataWcdmaCarrier>
+
+<es:userLabel> </es:userLabel>
+<es:defaultHoType>1</es:defaultHoType>
+<es:freqBand>0</es:freqBand>
+<es:sib5bisEnabled>0</es:sib5bisEnabled>
+<es:uarfcnDl>0</es:uarfcnDl>
+</es:vsDataWcdmaCarrier>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataCnOperator</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataCnOperator>
+
+<es:userLabel> </es:userLabel>
+<es:plmnIdentity>
+<es:mcc>1</es:mcc>
+<es:mnc>1</es:mnc>
+<es:mncLength>2</es:mncLength></es:plmnIdentity>
+<es:iphoNetworkRefsUtran></es:iphoNetworkRefsUtran>
+<es:iphoNetworkRefsGsm></es:iphoNetworkRefsGsm>
+<es:equivalentPlmnIdentities></es:equivalentPlmnIdentities>
+</es:vsDataCnOperator>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="3" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataWcdmaCarrier</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataWcdmaCarrier>
+
+<es:userLabel> </es:userLabel>
+<es:defaultHoType>1</es:defaultHoType>
+<es:freqBand>0</es:freqBand>
+<es:sib5bisEnabled>0</es:sib5bisEnabled>
+<es:uarfcnDl>0</es:uarfcnDl>
+</es:vsDataWcdmaCarrier>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataCnOperator</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataCnOperator>
+
+<es:userLabel> </es:userLabel>
+<es:plmnIdentity>
+<es:mcc>1</es:mcc>
+<es:mnc>1</es:mnc>
+<es:mncLength>2</es:mncLength></es:plmnIdentity>
+<es:iphoNetworkRefsUtran></es:iphoNetworkRefsUtran>
+<es:iphoNetworkRefsGsm></es:iphoNetworkRefsGsm>
+<es:equivalentPlmnIdentities></es:equivalentPlmnIdentities>
+</es:vsDataCnOperator>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="4" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataWcdmaCarrier</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataWcdmaCarrier>
+
+<es:userLabel> </es:userLabel>
+<es:defaultHoType>1</es:defaultHoType>
+<es:freqBand>0</es:freqBand>
+<es:sib5bisEnabled>0</es:sib5bisEnabled>
+<es:uarfcnDl>0</es:uarfcnDl>
+</es:vsDataWcdmaCarrier>
+</xn:attributes>
+</xn:VsDataContainer><xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUeRc</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+<es:vsDataUeRc>
+
+<es:userLabel> </es:userLabel>
+<es:serviceOffset2dEcno>0</es:serviceOffset2dEcno>
+<es:serviceOffset2dRscp>0</es:serviceOffset2dRscp>
+</es:vsDataUeRc></xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="update">
+<xn:attributes>
+<xn:vsDataType>vsDataUeRc</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUeRc>
+
+<es:userLabel> </es:userLabel>
+<es:serviceOffset2dEcno>0</es:serviceOffset2dEcno>
+<es:serviceOffset2dRscp>0</es:serviceOffset2dRscp>
+</es:vsDataUeRc>
+</xn:attributes>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUeRcTrCh</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUeRcTrCh>
+
+<es:blerQualityTargetDl>-63</es:blerQualityTargetDl>
+<es:blerQualityTargetUl>-63</es:blerQualityTargetUl>
+</es:vsDataUeRcTrCh>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUeRcRab</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUeRcRab>
+
+<es:fcState>0</es:fcState>
+<es:trBearerQosClass>0</es:trBearerQosClass>
+</es:vsDataUeRcRab>
+</xn:attributes>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUeRcRrc</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUeRcRrc>
+
+<es:trBearerQosClass>0</es:trBearerQosClass>
+</es:vsDataUeRcRrc>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+<xn:VsDataContainer id="1" modifier="create">
+<xn:attributes>
+<xn:vsDataType>vsDataUeRabType</xn:vsDataType>
+<xn:vsDataFormatVersion>EricssonSpecificAttributes.5.1</xn:vsDataFormatVersion>
+
+<es:vsDataUeRabType>
+
+<es:trBearerQosClass>0</es:trBearerQosClass>
+</es:vsDataUeRabType>
+</xn:attributes>
+</xn:VsDataContainer>
+</xn:VsDataContainer>
+</un:RncFunction>
+</xn:ManagedElement></xn:MeContext>
+</xn:SubNetwork>
+</xn:SubNetwork>
+</configData>
+ <fileFooter dateTime="2001-05-07T12:00:00+02:00"></fileFooter>
+</bulkCmConfigDataFile> \ No newline at end of file
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/utranNrm.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/utranNrm.xsd
new file mode 100644
index 0000000000..1d411b31dd
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/netsim/utranNrm.xsd
@@ -0,0 +1,174 @@
+<!--
+ 3GPP TS 32.615 v4.5 Bulk CM IRP
+ Configuration data file UTRAN Network Resources IRP NRM XML schema
+ To be used with WEGA Bucket 2.1 onwards
+-->
+<schema xmlns:gn="geranNrm.xsd" xmlns:un="utranNrm.xsd" xmlns:xn="genericNrm.xsd" xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="utranNrm.xsd" elementFormDefault="qualified" attributeFormDefault="unqualified">
+ <!-- UTRAN Network Resources IRP NRM class associated XML elements -->
+ <import namespace="genericNrm.xsd" schemaLocation="genericNrm.xsd"/>
+ <import namespace="geranNrm.xsd" schemaLocation="geranNrm.xsd"/>
+ <element name="RncFunction">
+ <complexType>
+ <complexContent>
+ <extension base="xn:NrmClassXmlType">
+ <sequence>
+ <element name="attributes" minOccurs="0">
+ <complexType>
+ <all>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="mcc" minOccurs="0"/>
+ <element name="mnc" minOccurs="0"/>
+ <element name="rncId" minOccurs="0"/>
+ <!--
+ <element name="mncLength" minOccurs="0"/>
+ -->
+ </all>
+ </complexType>
+ </element>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element ref="un:UtranCell"/>
+ <element ref="un:IubLink"/>
+ <element ref="xn:VsDataContainer"/>
+ </choice>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="NodeBFunction">
+ <complexType>
+ <complexContent>
+ <extension base="xn:NrmClassXmlType">
+ <sequence>
+ <element name="attributes" minOccurs="0">
+ <complexType>
+ <all>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="nodeBFunctionIubLink" minOccurs="0"/>
+ </all>
+ </complexType>
+ </element>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element ref="xn:VsDataContainer"/>
+ </choice>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="UtranCell">
+ <complexType>
+ <complexContent>
+ <extension base="xn:NrmClassXmlType">
+ <sequence>
+ <element name="attributes" minOccurs="0">
+ <complexType>
+ <all>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="cId" minOccurs="0"/>
+ <element name="localCellId" minOccurs="0"/>
+ <element name="uarfcnUl" minOccurs="0"/>
+ <element name="uarfcnDl" minOccurs="0"/>
+ <element name="primaryScramblingCode" minOccurs="0"/>
+ <element name="primaryCpichPower" minOccurs="0"/>
+ <element name="maximumTransmissionPower" minOccurs="0"/>
+ <element name="primarySchPower" minOccurs="0"/>
+ <element name="secondarySchPower" minOccurs="0"/>
+ <element name="bchPower" minOccurs="0"/>
+ <element name="lac" minOccurs="0"/>
+ <element name="rac" minOccurs="0"/>
+ <element name="sac" minOccurs="0"/>
+ <element name="utranCellIubLink" minOccurs="0"/>
+ <element name="uraList" minOccurs="0"/>
+ <!-- 3.1
+ <element name="ura" minOccurs="0"/>
+ -->
+ </all>
+ </complexType>
+ </element>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element ref="un:UtranRelation"/>
+ <element ref="gn:GsmRelation"/>
+ <element ref="xn:VsDataContainer"/>
+ </choice>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="IubLink">
+ <complexType>
+ <complexContent>
+ <extension base="xn:NrmClassXmlType">
+ <sequence>
+ <element name="attributes" minOccurs="0">
+ <complexType>
+ <all>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="iubLinkUtranCell" minOccurs="0"/>
+ <element name="iubLinkNodeBFunction" minOccurs="0"/>
+ </all>
+ </complexType>
+ </element>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element ref="xn:VsDataContainer"/>
+ </choice>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="UtranRelation">
+ <complexType>
+ <complexContent>
+ <extension base="xn:NrmClassXmlType">
+ <sequence>
+ <element name="attributes" minOccurs="0">
+ <complexType>
+ <all>
+ <element name="adjacentCell" minOccurs="0"/>
+ <!--
+ <element name="relationType" minOccurs="0"/>
+ -->
+ </all>
+ </complexType>
+ </element>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element ref="xn:VsDataContainer"/>
+ </choice>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <element name="ExternalUtranCell">
+ <complexType>
+ <complexContent>
+ <extension base="xn:NrmClassXmlType">
+ <sequence>
+ <element name="attributes" minOccurs="0">
+ <complexType>
+ <all>
+ <element name="userLabel" minOccurs="0"/>
+ <element name="cId" minOccurs="0"/>
+ <element name="mcc" minOccurs="0"/>
+ <element name="mnc" minOccurs="0"/>
+ <element name="rncId" minOccurs="0"/>
+ <element name="uarfcnUl" minOccurs="0"/>
+ <element name="uarfcnDl" minOccurs="0"/>
+ <element name="primaryScramblingCode" minOccurs="0"/>
+ <element name="primaryCpichPower" minOccurs="0"/>
+ <element name="lac" minOccurs="0"/>
+ <element name="rac" minOccurs="0"/>
+ </all>
+ </complexType>
+ </element>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element ref="xn:VsDataContainer"/>
+ </choice>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+</schema>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/po.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/po.xml
new file mode 100644
index 0000000000..28a44c410d
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/po.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<purchaseOrder orderDate="1999-10-20">
+ <shipTo country="US">
+ <name>Alice Smith</name>
+ <street>123 Maple Street</street>
+ <city>Mill Valley</city>
+ <state>CA</state>
+ <zip>90952</zip>
+ </shipTo>
+ <billTo country="US">
+ <name>Robert Smith</name>
+ <street>8 Oak Avenue</street>
+ <city>Old Town</city>
+ <state>PA</state>
+ <zip>95819</zip>
+ </billTo>
+ <comment>Hurry, my lawn is going wild!</comment>
+ <items>
+ <item partNum="872-AA">
+ <productName>Lawnmower</productName>
+ <quantity>1</quantity>
+ <USPrice>148.95</USPrice>
+ <comment>Confirm this is electric</comment>
+ </item>
+ <item partNum="926-AA">
+ <productName>Baby Monitor</productName>
+ <quantity>1</quantity>
+ <USPrice>39.98</USPrice>
+ <shipDate>1999-05-21</shipDate>
+ </item>
+ </items>
+</purchaseOrder>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/po.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/po.xsd
new file mode 100644
index 0000000000..995dd00152
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/po.xsd
@@ -0,0 +1,67 @@
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Purchase order schema for Example.com.
+ Copyright 2000 Example.com. All rights reserved.
+ </xsd:documentation>
+ </xsd:annotation>
+
+ <xsd:element name="purchaseOrder" type="PurchaseOrderType"/>
+
+ <xsd:element name="comment" type="xsd:string"/>
+
+ <xsd:complexType name="PurchaseOrderType">
+ <xsd:sequence>
+ <xsd:element name="shipTo" type="USAddress"/>
+ <xsd:element name="billTo" type="USAddress"/>
+ <xsd:element ref="comment" minOccurs="0"/>
+ <xsd:element name="items" type="Items"/>
+ </xsd:sequence>
+ <xsd:attribute name="orderDate" type="xsd:date"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="USAddress">
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string"/>
+ <xsd:element name="street" type="xsd:string"/>
+ <xsd:element name="city" type="xsd:string"/>
+ <xsd:element name="state" type="xsd:string"/>
+ <xsd:element name="zip" type="xsd:decimal"/>
+ </xsd:sequence>
+ <xsd:attribute name="country" type="xsd:NMTOKEN"
+ fixed="US"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="Items">
+ <xsd:sequence>
+ <xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="productName" type="xsd:string"/>
+ <xsd:element name="quantity">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:positiveInteger">
+ <xsd:maxExclusive value="100"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+ <xsd:element name="USPrice" type="xsd:decimal"/>
+ <xsd:element ref="comment" minOccurs="0"/>
+ <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
+ </xsd:sequence>
+ <xsd:attribute name="partNum" type="SKU" use="required"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <!-- Stock Keeping Unit, a code for identifying products -->
+ <xsd:simpleType name="SKU">
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="\d{3}-[A-Z]{2}"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+</xsd:schema>
+
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/po1.tab b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1.tab
new file mode 100644
index 0000000000..fa3fcdaa09
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1.tab
@@ -0,0 +1,424 @@
+[{{element,{name,['USAddress'],'http://www.example.com/PO1'}},
+ {schema_element,{name,['USAddress'],'http://www.example.com/PO1'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['USAddress'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{productName,[anonymous,item,'Items'],'http://www.example.com/PO1'}},
+ {schema_element,{productName,[anonymous,item,'Items'],
+ 'http://www.example.com/PO1'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,item,'Items'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{schema,"po1.xsd"},
+ {schema,unqualified,
+ unqualified,
+ 'http://www.example.com/PO1',
+ [],
+ [],
+ [{element,{{purchaseOrder,[],'http://www.example.com/PO1'},{1,1}}},
+ {element,{{comment,[],'http://www.example.com/PO1'},{1,1}}}]}},
+ {{simpleType,{'_xmerl_no_name_',[quantity,anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'}},
+ {schema_simple_type,{'_xmerl_no_name_',
+ [quantity,anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'},
+ [quantity,anonymous,item,'Items'],
+ {positiveInteger,[],'http://www.w3.org/2001/XMLSchema'},
+ false,
+ [],
+ [{maxExclusive,"100"}],
+ atomic,
+ [{restriction,{{positiveInteger,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'},
+ [{maxExclusive,"100"}]}}]}},
+ {{element,{street,['USAddress'],'http://www.example.com/PO1'}},
+ {schema_element,{street,['USAddress'],'http://www.example.com/PO1'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['USAddress'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{shipTo,['PurchaseOrderType'],'http://www.example.com/PO1'}},
+ {schema_element,{shipTo,['PurchaseOrderType'],'http://www.example.com/PO1'},
+ [{simple_or_complex_Type,
+ {'USAddress',[],'http://www.example.com/PO1'}}],
+ false,
+ undefined,
+ [],
+ ['PurchaseOrderType'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{complexType,{'PurchaseOrderType',[],'http://www.example.com/PO1'}},
+ {schema_complex_type,{'PurchaseOrderType',[],'http://www.example.com/PO1'},
+ undefined,
+ false,
+ ['PurchaseOrderType'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{orderDate,
+ ['PurchaseOrderType'],
+ 'http://www.example.com/PO1'}}],
+ [{sequence,{[{element,
+ {{shipTo,
+ ['PurchaseOrderType'],
+ 'http://www.example.com/PO1'},
+ {1,1}}},
+ {element,
+ {{billTo,
+ ['PurchaseOrderType'],
+ 'http://www.example.com/PO1'},
+ {1,1}}},
+ {element,
+ {{comment,
+ [],
+ 'http://www.example.com/PO1'},
+ {0,1}}},
+ {element,
+ {{items,
+ ['PurchaseOrderType'],
+ 'http://www.example.com/PO1'},
+ {1,1}}}],
+ {1,1}}}],
+ undefined}},
+ {{simpleType,{'SKU',[],'http://www.example.com/PO1'}},
+ {schema_simple_type,{'SKU',[],'http://www.example.com/PO1'},
+ [],
+ {string,[],'http://www.w3.org/2001/XMLSchema'},
+ false,
+ [],
+ [{pattern,"\\d{3}-[A-Z]{2}"}],
+ atomic,
+ [{restriction,{{string,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'},
+ [{pattern,"\\d{3}-[A-Z]{2}"}]}}]}},
+ {{element,{city,['USAddress'],'http://www.example.com/PO1'}},
+ {schema_element,{city,['USAddress'],'http://www.example.com/PO1'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['USAddress'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{quantity,[anonymous,item,'Items'],'http://www.example.com/PO1'}},
+ {schema_element,{quantity,[anonymous,item,'Items'],
+ 'http://www.example.com/PO1'},
+ [{simpleType,{'_xmerl_no_name_',
+ [quantity,anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,item,'Items'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{attribute,{orderDate,['PurchaseOrderType'],'http://www.example.com/PO1'}},
+ {schema_attribute,{orderDate,['PurchaseOrderType'],
+ 'http://www.example.com/PO1'},
+ [{simpleType,{date,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ ['PurchaseOrderType'],
+ optional,
+ undefined,
+ undefined,
+ undefined}},
+ {{element,{state,['USAddress'],'http://www.example.com/PO1'}},
+ {schema_element,{state,['USAddress'],'http://www.example.com/PO1'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['USAddress'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{comment,[],'http://www.example.com/PO1'}},
+ {schema_element,{comment,[],'http://www.example.com/PO1'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{complexType,{'USAddress',[],'http://www.example.com/PO1'}},
+ {schema_complex_type,{'USAddress',[],'http://www.example.com/PO1'},
+ undefined,
+ false,
+ ['USAddress'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{country,
+ ['USAddress'],
+ 'http://www.example.com/PO1'}}],
+ [{sequence,{[{element,
+ {{name,
+ ['USAddress'],
+ 'http://www.example.com/PO1'},
+ {1,1}}},
+ {element,
+ {{street,
+ ['USAddress'],
+ 'http://www.example.com/PO1'},
+ {1,1}}},
+ {element,
+ {{city,
+ ['USAddress'],
+ 'http://www.example.com/PO1'},
+ {1,1}}},
+ {element,
+ {{state,
+ ['USAddress'],
+ 'http://www.example.com/PO1'},
+ {1,1}}},
+ {element,
+ {{zip,
+ ['USAddress'],
+ 'http://www.example.com/PO1'},
+ {1,1}}}],
+ {1,1}}}],
+ undefined}},
+ {{element,{purchaseOrder,[],'http://www.example.com/PO1'}},
+ {schema_element,{purchaseOrder,[],'http://www.example.com/PO1'},
+ [{simple_or_complex_Type,
+ {'PurchaseOrderType',[],'http://www.example.com/PO1'}}],
+ false,
+ undefined,
+ [],
+ [],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{billTo,['PurchaseOrderType'],'http://www.example.com/PO1'}},
+ {schema_element,{billTo,['PurchaseOrderType'],'http://www.example.com/PO1'},
+ [{simple_or_complex_Type,
+ {'USAddress',[],'http://www.example.com/PO1'}}],
+ false,
+ undefined,
+ [],
+ ['PurchaseOrderType'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{items,['PurchaseOrderType'],'http://www.example.com/PO1'}},
+ {schema_element,{items,['PurchaseOrderType'],'http://www.example.com/PO1'},
+ [{simple_or_complex_Type,
+ {'Items',[],'http://www.example.com/PO1'}}],
+ false,
+ undefined,
+ [],
+ ['PurchaseOrderType'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{complexType,{'Items',[],'http://www.example.com/PO1'}},
+ {schema_complex_type,{'Items',[],'http://www.example.com/PO1'},
+ undefined,
+ false,
+ ['Items'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [],
+ [{sequence,{[{element,
+ {{item,
+ ['Items'],
+ 'http://www.example.com/PO1'},
+ {0,unbounded}}}],
+ {1,1}}}],
+ undefined}},
+ {{element,{item,['Items'],'http://www.example.com/PO1'}},
+ {schema_element,{item,['Items'],'http://www.example.com/PO1'},
+ [{complexType,{'_xmerl_no_name_',
+ [anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['Items'],
+ undefined,
+ {0,unbounded},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{attribute,{partNum,[anonymous,item,'Items'],'http://www.example.com/PO1'}},
+ {schema_attribute,{partNum,[anonymous,item,'Items'],
+ 'http://www.example.com/PO1'},
+ [{simpleType,{'SKU',[],'http://www.example.com/PO1'}}],
+ false,
+ [anonymous,item,'Items'],
+ required,
+ undefined,
+ undefined,
+ undefined}},
+ {{complexType,{'_xmerl_no_name_',[anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'}},
+ {schema_complex_type,{'_xmerl_no_name_',
+ [anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'},
+ undefined,
+ false,
+ [anonymous,item,'Items'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{partNum,
+ [anonymous,item,'Items'],
+ 'http://www.example.com/PO1'}}],
+ [{sequence,{[{element,
+ {{productName,
+ [anonymous,item,'Items'],
+ 'http://www.example.com/PO1'},
+ {1,1}}},
+ {element,
+ {{quantity,
+ [anonymous,item,'Items'],
+ 'http://www.example.com/PO1'},
+ {1,1}}},
+ {element,
+ {{'USPrice',
+ [anonymous,item,'Items'],
+ 'http://www.example.com/PO1'},
+ {1,1}}},
+ {element,
+ {{comment,
+ [],
+ 'http://www.example.com/PO1'},
+ {0,1}}},
+ {element,
+ {{shipDate,
+ [anonymous,item,'Items'],
+ 'http://www.example.com/PO1'},
+ {0,1}}}],
+ {1,1}}}],
+ undefined}},
+ {{attribute,{country,['USAddress'],'http://www.example.com/PO1'}},
+ {schema_attribute,{country,['USAddress'],'http://www.example.com/PO1'},
+ [{simpleType,{'NMTOKEN',
+ [],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ ['USAddress'],
+ optional,
+ undefined,
+ "US",
+ undefined}},
+ {{element,{'USPrice',[anonymous,item,'Items'],'http://www.example.com/PO1'}},
+ {schema_element,{'USPrice',[anonymous,item,'Items'],
+ 'http://www.example.com/PO1'},
+ [{simpleType,{decimal,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,item,'Items'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{shipDate,[anonymous,item,'Items'],'http://www.example.com/PO1'}},
+ {schema_element,{shipDate,[anonymous,item,'Items'],
+ 'http://www.example.com/PO1'},
+ [{simpleType,{date,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,item,'Items'],
+ undefined,
+ {0,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{zip,['USAddress'],'http://www.example.com/PO1'}},
+ {schema_element,{zip,['USAddress'],'http://www.example.com/PO1'},
+ [{simpleType,{decimal,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['USAddress'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}}]
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/po1.tab2 b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1.tab2
new file mode 100644
index 0000000000..fa3fcdaa09
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1.tab2
@@ -0,0 +1,424 @@
+[{{element,{name,['USAddress'],'http://www.example.com/PO1'}},
+ {schema_element,{name,['USAddress'],'http://www.example.com/PO1'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['USAddress'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{productName,[anonymous,item,'Items'],'http://www.example.com/PO1'}},
+ {schema_element,{productName,[anonymous,item,'Items'],
+ 'http://www.example.com/PO1'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,item,'Items'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{schema,"po1.xsd"},
+ {schema,unqualified,
+ unqualified,
+ 'http://www.example.com/PO1',
+ [],
+ [],
+ [{element,{{purchaseOrder,[],'http://www.example.com/PO1'},{1,1}}},
+ {element,{{comment,[],'http://www.example.com/PO1'},{1,1}}}]}},
+ {{simpleType,{'_xmerl_no_name_',[quantity,anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'}},
+ {schema_simple_type,{'_xmerl_no_name_',
+ [quantity,anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'},
+ [quantity,anonymous,item,'Items'],
+ {positiveInteger,[],'http://www.w3.org/2001/XMLSchema'},
+ false,
+ [],
+ [{maxExclusive,"100"}],
+ atomic,
+ [{restriction,{{positiveInteger,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'},
+ [{maxExclusive,"100"}]}}]}},
+ {{element,{street,['USAddress'],'http://www.example.com/PO1'}},
+ {schema_element,{street,['USAddress'],'http://www.example.com/PO1'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['USAddress'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{shipTo,['PurchaseOrderType'],'http://www.example.com/PO1'}},
+ {schema_element,{shipTo,['PurchaseOrderType'],'http://www.example.com/PO1'},
+ [{simple_or_complex_Type,
+ {'USAddress',[],'http://www.example.com/PO1'}}],
+ false,
+ undefined,
+ [],
+ ['PurchaseOrderType'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{complexType,{'PurchaseOrderType',[],'http://www.example.com/PO1'}},
+ {schema_complex_type,{'PurchaseOrderType',[],'http://www.example.com/PO1'},
+ undefined,
+ false,
+ ['PurchaseOrderType'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{orderDate,
+ ['PurchaseOrderType'],
+ 'http://www.example.com/PO1'}}],
+ [{sequence,{[{element,
+ {{shipTo,
+ ['PurchaseOrderType'],
+ 'http://www.example.com/PO1'},
+ {1,1}}},
+ {element,
+ {{billTo,
+ ['PurchaseOrderType'],
+ 'http://www.example.com/PO1'},
+ {1,1}}},
+ {element,
+ {{comment,
+ [],
+ 'http://www.example.com/PO1'},
+ {0,1}}},
+ {element,
+ {{items,
+ ['PurchaseOrderType'],
+ 'http://www.example.com/PO1'},
+ {1,1}}}],
+ {1,1}}}],
+ undefined}},
+ {{simpleType,{'SKU',[],'http://www.example.com/PO1'}},
+ {schema_simple_type,{'SKU',[],'http://www.example.com/PO1'},
+ [],
+ {string,[],'http://www.w3.org/2001/XMLSchema'},
+ false,
+ [],
+ [{pattern,"\\d{3}-[A-Z]{2}"}],
+ atomic,
+ [{restriction,{{string,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'},
+ [{pattern,"\\d{3}-[A-Z]{2}"}]}}]}},
+ {{element,{city,['USAddress'],'http://www.example.com/PO1'}},
+ {schema_element,{city,['USAddress'],'http://www.example.com/PO1'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['USAddress'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{quantity,[anonymous,item,'Items'],'http://www.example.com/PO1'}},
+ {schema_element,{quantity,[anonymous,item,'Items'],
+ 'http://www.example.com/PO1'},
+ [{simpleType,{'_xmerl_no_name_',
+ [quantity,anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,item,'Items'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{attribute,{orderDate,['PurchaseOrderType'],'http://www.example.com/PO1'}},
+ {schema_attribute,{orderDate,['PurchaseOrderType'],
+ 'http://www.example.com/PO1'},
+ [{simpleType,{date,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ ['PurchaseOrderType'],
+ optional,
+ undefined,
+ undefined,
+ undefined}},
+ {{element,{state,['USAddress'],'http://www.example.com/PO1'}},
+ {schema_element,{state,['USAddress'],'http://www.example.com/PO1'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['USAddress'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{comment,[],'http://www.example.com/PO1'}},
+ {schema_element,{comment,[],'http://www.example.com/PO1'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{complexType,{'USAddress',[],'http://www.example.com/PO1'}},
+ {schema_complex_type,{'USAddress',[],'http://www.example.com/PO1'},
+ undefined,
+ false,
+ ['USAddress'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{country,
+ ['USAddress'],
+ 'http://www.example.com/PO1'}}],
+ [{sequence,{[{element,
+ {{name,
+ ['USAddress'],
+ 'http://www.example.com/PO1'},
+ {1,1}}},
+ {element,
+ {{street,
+ ['USAddress'],
+ 'http://www.example.com/PO1'},
+ {1,1}}},
+ {element,
+ {{city,
+ ['USAddress'],
+ 'http://www.example.com/PO1'},
+ {1,1}}},
+ {element,
+ {{state,
+ ['USAddress'],
+ 'http://www.example.com/PO1'},
+ {1,1}}},
+ {element,
+ {{zip,
+ ['USAddress'],
+ 'http://www.example.com/PO1'},
+ {1,1}}}],
+ {1,1}}}],
+ undefined}},
+ {{element,{purchaseOrder,[],'http://www.example.com/PO1'}},
+ {schema_element,{purchaseOrder,[],'http://www.example.com/PO1'},
+ [{simple_or_complex_Type,
+ {'PurchaseOrderType',[],'http://www.example.com/PO1'}}],
+ false,
+ undefined,
+ [],
+ [],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{billTo,['PurchaseOrderType'],'http://www.example.com/PO1'}},
+ {schema_element,{billTo,['PurchaseOrderType'],'http://www.example.com/PO1'},
+ [{simple_or_complex_Type,
+ {'USAddress',[],'http://www.example.com/PO1'}}],
+ false,
+ undefined,
+ [],
+ ['PurchaseOrderType'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{items,['PurchaseOrderType'],'http://www.example.com/PO1'}},
+ {schema_element,{items,['PurchaseOrderType'],'http://www.example.com/PO1'},
+ [{simple_or_complex_Type,
+ {'Items',[],'http://www.example.com/PO1'}}],
+ false,
+ undefined,
+ [],
+ ['PurchaseOrderType'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{complexType,{'Items',[],'http://www.example.com/PO1'}},
+ {schema_complex_type,{'Items',[],'http://www.example.com/PO1'},
+ undefined,
+ false,
+ ['Items'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [],
+ [{sequence,{[{element,
+ {{item,
+ ['Items'],
+ 'http://www.example.com/PO1'},
+ {0,unbounded}}}],
+ {1,1}}}],
+ undefined}},
+ {{element,{item,['Items'],'http://www.example.com/PO1'}},
+ {schema_element,{item,['Items'],'http://www.example.com/PO1'},
+ [{complexType,{'_xmerl_no_name_',
+ [anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['Items'],
+ undefined,
+ {0,unbounded},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{attribute,{partNum,[anonymous,item,'Items'],'http://www.example.com/PO1'}},
+ {schema_attribute,{partNum,[anonymous,item,'Items'],
+ 'http://www.example.com/PO1'},
+ [{simpleType,{'SKU',[],'http://www.example.com/PO1'}}],
+ false,
+ [anonymous,item,'Items'],
+ required,
+ undefined,
+ undefined,
+ undefined}},
+ {{complexType,{'_xmerl_no_name_',[anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'}},
+ {schema_complex_type,{'_xmerl_no_name_',
+ [anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'},
+ undefined,
+ false,
+ [anonymous,item,'Items'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{partNum,
+ [anonymous,item,'Items'],
+ 'http://www.example.com/PO1'}}],
+ [{sequence,{[{element,
+ {{productName,
+ [anonymous,item,'Items'],
+ 'http://www.example.com/PO1'},
+ {1,1}}},
+ {element,
+ {{quantity,
+ [anonymous,item,'Items'],
+ 'http://www.example.com/PO1'},
+ {1,1}}},
+ {element,
+ {{'USPrice',
+ [anonymous,item,'Items'],
+ 'http://www.example.com/PO1'},
+ {1,1}}},
+ {element,
+ {{comment,
+ [],
+ 'http://www.example.com/PO1'},
+ {0,1}}},
+ {element,
+ {{shipDate,
+ [anonymous,item,'Items'],
+ 'http://www.example.com/PO1'},
+ {0,1}}}],
+ {1,1}}}],
+ undefined}},
+ {{attribute,{country,['USAddress'],'http://www.example.com/PO1'}},
+ {schema_attribute,{country,['USAddress'],'http://www.example.com/PO1'},
+ [{simpleType,{'NMTOKEN',
+ [],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ ['USAddress'],
+ optional,
+ undefined,
+ "US",
+ undefined}},
+ {{element,{'USPrice',[anonymous,item,'Items'],'http://www.example.com/PO1'}},
+ {schema_element,{'USPrice',[anonymous,item,'Items'],
+ 'http://www.example.com/PO1'},
+ [{simpleType,{decimal,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,item,'Items'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{shipDate,[anonymous,item,'Items'],'http://www.example.com/PO1'}},
+ {schema_element,{shipDate,[anonymous,item,'Items'],
+ 'http://www.example.com/PO1'},
+ [{simpleType,{date,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,item,'Items'],
+ undefined,
+ {0,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{zip,['USAddress'],'http://www.example.com/PO1'}},
+ {schema_element,{zip,['USAddress'],'http://www.example.com/PO1'},
+ [{simpleType,{decimal,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['USAddress'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}}]
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/po1.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1.xml
new file mode 100644
index 0000000000..c77701b5a2
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<apo:purchaseOrder xmlns:apo="http://www.example.com/PO1"
+ orderDate="1999-10-20">
+ <shipTo country="US">
+ <name>Alice Smith</name>
+ <street>123 Maple Street</street>
+ <!-- etc. -->
+ <city>Mill Valley</city>
+ <state>CA</state>
+ <zip>90952</zip>
+ </shipTo>
+ <billTo country="US">
+ <name>Robert Smith</name>
+ <street>8 Oak Avenue</street>
+ <!-- etc. -->
+ <city>Old Town</city>
+ <state>PA</state>
+ <zip>95819</zip>
+ </billTo>
+ <apo:comment>Hurry, my lawn is going wild!</apo:comment>
+ <!-- etc. -->
+ <items>
+ <item partNum="872-AA">
+ <productName>Lawnmower</productName>
+ <quantity>1</quantity>
+ <USPrice>148.95</USPrice>
+ <comment>Confirm this is electric</comment>
+ </item>
+ <item partNum="926-AA">
+ <productName>Baby Monitor</productName>
+ <quantity>1</quantity>
+ <USPrice>39.98</USPrice>
+ <shipDate>1999-05-21</shipDate>
+ </item>
+ </items>
+</apo:purchaseOrder>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/po1.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1.xsd
new file mode 100644
index 0000000000..bc4dae27b5
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1.xsd
@@ -0,0 +1,64 @@
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:po="http://www.example.com/PO1"
+ targetNamespace="http://www.example.com/PO1"
+ elementFormDefault="unqualified"
+ attributeFormDefault="unqualified">
+
+ <element name="purchaseOrder" type="po:PurchaseOrderType"/>
+
+ <element name="comment" type="string"/>
+
+ <complexType name="PurchaseOrderType">
+ <sequence>
+ <element name="shipTo" type="po:USAddress"/>
+ <element name="billTo" type="po:USAddress"/>
+ <element ref="po:comment" minOccurs="0"/>
+ <element name="items" type="po:Items"/>
+ </sequence>
+ <attribute name="orderDate" type="date"/>
+ </complexType>
+
+ <complexType name="USAddress">
+ <sequence>
+ <element name="name" type="string"/>
+ <element name="street" type="string"/>
+ <element name="city" type="string"/>
+ <element name="state" type="string"/>
+ <element name="zip" type="decimal"/>
+ </sequence>
+ <attribute name="country" type="NMTOKEN"
+ fixed="US"/>
+ </complexType>
+
+ <complexType name="Items">
+ <sequence>
+ <element name="item" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="productName" type="string"/>
+ <element name="quantity">
+ <simpleType>
+ <restriction base="positiveInteger">
+ <maxExclusive value="100"/>
+ </restriction>
+ </simpleType>
+ </element>
+ <element name="USPrice" type="decimal"/>
+ <element ref="po:comment" minOccurs="0"/>
+ <element name="shipDate" type="date" minOccurs="0"/>
+ </sequence>
+ <attribute name="partNum" type="po:SKU" use="required"/>
+ </complexType>
+ </element>
+ </sequence>
+ </complexType>
+
+ <!-- Stock Keeping Unit, a code for identifying products -->
+ <simpleType name="SKU">
+ <restriction base="string">
+ <pattern value="\d{3}-[A-Z]{2}"/>
+ </restriction>
+ </simpleType>
+
+</schema>
+
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all.xsd
new file mode 100644
index 0000000000..7383c7f8f6
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all.xsd
@@ -0,0 +1,65 @@
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:po="http://www.example.com/PO1"
+ targetNamespace="http://www.example.com/PO1"
+ elementFormDefault="unqualified"
+ attributeFormDefault="unqualified">
+
+ <element name="purchaseOrder" type="po:PurchaseOrderType"/>
+
+ <element name="comment" type="string"/>
+
+
+ <complexType name="PurchaseOrderType">
+ <all>
+ <element name="shipTo" type="po:USAddress"/>
+ <element name="billTo" type="po:USAddress"/>
+ <element ref="po:comment" minOccurs="0"/>
+ <element name="items" type="po:Items"/>
+ </all>
+ <attribute name="orderDate" type="date"/>
+ </complexType>
+
+ <complexType name="USAddress">
+ <sequence>
+ <element name="name" type="string"/>
+ <element name="street" type="string"/>
+ <element name="city" type="string"/>
+ <element name="state" type="string"/>
+ <element name="zip" type="decimal"/>
+ </sequence>
+ <attribute name="country" type="NMTOKEN"
+ fixed="US"/>
+ </complexType>
+
+ <complexType name="Items">
+ <sequence>
+ <element name="item" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="productName" type="string"/>
+ <element name="quantity">
+ <simpleType>
+ <restriction base="positiveInteger">
+ <maxExclusive value="100"/>
+ </restriction>
+ </simpleType>
+ </element>
+ <element name="USPrice" type="decimal"/>
+ <element ref="po:comment" minOccurs="0"/>
+ <element name="shipDate" type="date" minOccurs="0"/>
+ </sequence>
+ <attribute name="partNum" type="po:SKU" use="required"/>
+ </complexType>
+ </element>
+ </sequence>
+ </complexType>
+
+ <!-- Stock Keeping Unit, a code for identifying products -->
+ <simpleType name="SKU">
+ <restriction base="string">
+ <pattern value="\d{3}-[A-Z]{2}"/>
+ </restriction>
+ </simpleType>
+
+</schema>
+
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all1.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all1.xml
new file mode 100644
index 0000000000..a5ae223d65
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all1.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<apo:purchaseOrder xmlns:apo="http://www.example.com/PO1"
+ orderDate="1999-10-20">
+ <billTo country="US">
+ <name>Robert Smith</name>
+ <street>8 Oak Avenue</street>
+ <!-- etc. -->
+ <city>Old Town</city>
+ <state>PA</state>
+ <zip>95819</zip>
+ </billTo>
+ <apo:comment>Hurry, my lawn is going wild!</apo:comment>
+ <shipTo country="US">
+ <name>Alice Smith</name>
+ <street>123 Maple Street</street>
+ <!-- etc. -->
+ <city>Mill Valley</city>
+ <state>CA</state>
+ <zip>90952</zip>
+ </shipTo>
+ <!-- etc. -->
+ <items>
+ <item partNum="872-AA">
+ <productName>Lawnmower</productName>
+ <quantity>1</quantity>
+ <USPrice>148.95</USPrice>
+ <comment>Confirm this is electric</comment>
+ </item>
+ <item partNum="926-AA">
+ <productName>Baby Monitor</productName>
+ <quantity>1</quantity>
+ <USPrice>39.98</USPrice>
+ <shipDate>1999-05-21</shipDate>
+ </item>
+ </items>
+</apo:purchaseOrder>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all2.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all2.xml
new file mode 100644
index 0000000000..2c40c8c686
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all2.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<apo:purchaseOrder xmlns:apo="http://www.example.com/PO1"
+ orderDate="1999-10-20">
+ <billTo country="US">
+ <name>Robert Smith</name>
+ <street>8 Oak Avenue</street>
+ <!-- etc. -->
+ <city>Old Town</city>
+ <state>PA</state>
+ <zip>95819</zip>
+ </billTo>
+ <shipTo country="US">
+ <name>Alice Smith</name>
+ <street>123 Maple Street</street>
+ <!-- etc. -->
+ <city>Mill Valley</city>
+ <state>CA</state>
+ <zip>90952</zip>
+ </shipTo>
+ <!-- etc. -->
+ <items>
+ <item partNum="872-AA">
+ <productName>Lawnmower</productName>
+ <quantity>1</quantity>
+ <USPrice>148.95</USPrice>
+ <comment>Confirm this is electric</comment>
+ </item>
+ <item partNum="926-AA">
+ <productName>Baby Monitor</productName>
+ <quantity>1</quantity>
+ <USPrice>39.98</USPrice>
+ <shipDate>1999-05-21</shipDate>
+ </item>
+ </items>
+</apo:purchaseOrder>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all_err1.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all_err1.xml
new file mode 100644
index 0000000000..98d82e4642
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all_err1.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<apo:purchaseOrder xmlns:apo="http://www.example.com/PO1"
+ orderDate="1999-10-20">
+ <billTo country="US">
+ <name>Robert Smith</name>
+ <street>8 Oak Avenue</street>
+ <!-- etc. -->
+ <city>Old Town</city>
+ <state>PA</state>
+ <zip>95819</zip>
+ </billTo>
+ <apo:comment>Hurry, my lawn is going wild!</apo:comment>
+ <shipTo country="US">
+ <name>Alice Smith</name>
+ <street>123 Maple Street</street>
+ <!-- etc. -->
+ <city>Mill Valley</city>
+ <state>CA</state>
+ <zip>90952</zip>
+ </shipTo>
+ <apo:comment>Hurry, my lawn is going wild!</apo:comment>
+ <!-- etc. -->
+ <items>
+ <item partNum="872-AA">
+ <productName>Lawnmower</productName>
+ <quantity>1</quantity>
+ <USPrice>148.95</USPrice>
+ <comment>Confirm this is electric</comment>
+ </item>
+ <item partNum="926-AA">
+ <productName>Baby Monitor</productName>
+ <quantity>1</quantity>
+ <USPrice>39.98</USPrice>
+ <shipDate>1999-05-21</shipDate>
+ </item>
+ </items>
+</apo:purchaseOrder>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all_err2.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all_err2.xml
new file mode 100644
index 0000000000..e4cc3f362e
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1_all_err2.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<apo:purchaseOrder xmlns:apo="http://www.example.com/PO1"
+ orderDate="1999-10-20">
+ <billTo country="US">
+ <name>Robert Smith</name>
+ <street>8 Oak Avenue</street>
+ <!-- etc. -->
+ <city>Old Town</city>
+ <state>PA</state>
+ <zip>95819</zip>
+ </billTo>
+ <apo:comment>Hurry, my lawn is going wild!</apo:comment>
+ <!-- etc. -->
+ <items>
+ <item partNum="872-AA">
+ <productName>Lawnmower</productName>
+ <quantity>1</quantity>
+ <USPrice>148.95</USPrice>
+ <comment>Confirm this is electric</comment>
+ </item>
+ <item partNum="926-AA">
+ <productName>Baby Monitor</productName>
+ <quantity>1</quantity>
+ <USPrice>39.98</USPrice>
+ <shipDate>1999-05-21</shipDate>
+ </item>
+ </items>
+</apo:purchaseOrder>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/po1_global.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1_global.xsd
new file mode 100644
index 0000000000..04a4baa0d2
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/po1_global.xsd
@@ -0,0 +1,86 @@
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:po="http://www.example.com/PO1"
+ targetNamespace="http://www.example.com/PO1">
+
+<!-- validates po2.xml -->
+
+ <element name="purchaseOrder" type="po:PurchaseOrderType"/>
+
+ <element name="shipTo" type="po:USAddress"/>
+ <element name="billTo" type="po:USAddress"/>
+ <element name="comment" type="string"/>
+
+ <element name="name" type="string"/>
+ <element name="street" type="string"/>
+
+ <element name="items" type="po:Items"/>
+
+ <attribute name="orderDate" type="date"/>
+
+ <element name="city" type="string"/>
+ <element name="state" type="string"/>
+ <element name="zip" type="decimal"/>
+
+ <attribute name="country" type="NMTOKEN" fixed="US"/>
+
+ <element name="item" type="po:Item"/>
+
+ <element name="productName" type="string"/>
+ <element name="quantity" type="ps:Quantity"/>
+ <element name="USPrice" type="decimal"/>
+ <element name="shipDate" type="date"/>
+
+ <attribute name="partNum" type="po:SKU" use="required"/>
+
+ <complexType name="PurchaseOrderType">
+ <sequence>
+ <element ref="po:shipTo"/>
+ <element ref="po:billTo"/>
+ <element ref="po:comment" minOccurs="0"/>
+ <element ref="po:items"/>
+ </sequence>
+ <attribute ref="po:orderDate"/>
+ </complexType>
+
+ <complexType name="USAddress">
+ <sequence>
+ <element ref="po:name"/>
+ <element ref="po:street"/>
+ <element ref="po:city"/>
+ <element ref="po:state"/>
+ <element ref="po:zip"/>
+ </sequence>
+ <attribute ref="po:country"/>
+ </complexType>
+
+ <complexType name="Items">
+ <sequence>
+ <element ref="po:item" minOccurs="0" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="Item">
+ <sequence>
+ <element ref="po:productName"/>
+ <element ref="po:quantity"/>
+ <element ref="po:USPrice"/>
+ <element ref="po:comment" minOccurs="0"/>
+ <element ref="po:shipDate" minOccurs="0"/>
+ </sequence>
+ <attribute ref="po:partNum"/>
+ </complexType>
+
+ <simpleType name="Quantity">
+ <restriction base="positiveInteger">
+ <maxExclusive value="100"/>
+ </restriction>
+ </simpleType>
+
+ <!-- Stock Keeping Unit, a code for identifying products -->
+ <simpleType name="SKU">
+ <restriction base="string">
+ <pattern value="\d{3}-[A-Z]{2}"/>
+ </restriction>
+ </simpleType>
+
+</schema>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/po2.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/po2.xml
new file mode 100644
index 0000000000..c1077b7572
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/po2.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<purchaseOrder xmlns="http://www.example.com/PO1"
+ orderDate="1999-10-20">
+ <shipTo country="US">
+ <name>Alice Smith</name>
+ <street>123 Maple Street</street>
+ <!-- etc. -->
+ <city>Mill Valley</city>
+ <state>CA</state>
+ <zip>90952</zip>
+ </shipTo>
+ <billTo country="US">
+ <name>Robert Smith</name>
+ <street>8 Oak Avenue</street>
+ <!-- etc. -->
+ <city>Old Town</city>
+ <state>PA</state>
+ <zip>95819</zip>
+ </billTo>
+ <comment>Hurry, my lawn is going wild!</comment>
+ <!-- etc. -->
+ <items>
+ <item partNum="872-AA">
+ <productName>Lawnmower</productName>
+ <quantity>1</quantity>
+ <USPrice>148.95</USPrice>
+ <comment>Confirm this is electric</comment>
+ </item>
+ <item partNum="926-AA">
+ <productName>Baby Monitor</productName>
+ <quantity>1</quantity>
+ <USPrice>39.98</USPrice>
+ <shipDate>1999-05-21</shipDate>
+ </item>
+ </items>
+</purchaseOrder>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/po_attrGroup.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/po_attrGroup.xml
new file mode 100644
index 0000000000..5e49a4a889
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/po_attrGroup.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<purchaseOrder orderDate="1999-10-20">
+ <shipTo country="US">
+ <name>Alice Smith</name>
+ <street>123 Maple Street</street>
+ <city>Mill Valley</city>
+ <state>CA</state>
+ <zip>90952</zip>
+ </shipTo>
+ <billTo country="US">
+ <name>Robert Smith</name>
+ <street>8 Oak Avenue</street>
+ <city>Old Town</city>
+ <state>PA</state>
+ <zip>95819</zip>
+ </billTo>
+ <comment>Hurry, my lawn is going wild!</comment>
+ <items>
+ <item partNum="872-AA" weightKg="25.5" shipBy="any">
+ <productName>Lawnmower</productName>
+ <quantity>1</quantity>
+ <USPrice>148.95</USPrice>
+ <comment>Confirm this is electric</comment>
+ </item>
+ <item partNum="926-AA" weightKg="0.5" shipBy="air">
+ <productName>Baby Monitor</productName>
+ <quantity>1</quantity>
+ <USPrice>39.98</USPrice>
+ <shipDate>1999-05-21</shipDate>
+ </item>
+ </items>
+</purchaseOrder>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/po_attrGroup.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/po_attrGroup.xsd
new file mode 100644
index 0000000000..734f65e0e0
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/po_attrGroup.xsd
@@ -0,0 +1,81 @@
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Purchase order schema for Example.com.
+ Copyright 2000 Example.com. All rights reserved.
+ </xsd:documentation>
+ </xsd:annotation>
+
+ <xsd:element name="purchaseOrder" type="PurchaseOrderType"/>
+
+ <xsd:element name="comment" type="xsd:string"/>
+
+ <xsd:complexType name="PurchaseOrderType">
+ <xsd:sequence>
+ <xsd:element name="shipTo" type="USAddress"/>
+ <xsd:element name="billTo" type="USAddress"/>
+ <xsd:element ref="comment" minOccurs="0"/>
+ <xsd:element name="items" type="Items"/>
+ </xsd:sequence>
+ <xsd:attribute name="orderDate" type="xsd:date"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="USAddress">
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string"/>
+ <xsd:element name="street" type="xsd:string"/>
+ <xsd:element name="city" type="xsd:string"/>
+ <xsd:element name="state" type="xsd:string"/>
+ <xsd:element name="zip" type="xsd:decimal"/>
+ </xsd:sequence>
+ <xsd:attribute name="country" type="xsd:NMTOKEN"
+ fixed="US"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="Items">
+ <xsd:sequence>
+ <xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="productName" type="xsd:string"/>
+ <xsd:element name="quantity">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:positiveInteger">
+ <xsd:maxExclusive value="100"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+ <xsd:element name="USPrice" type="xsd:decimal"/>
+ <xsd:element ref="comment" minOccurs="0"/>
+ <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="ItemDelivery"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <!-- Stock Keeping Unit, a code for identifying products -->
+ <xsd:simpleType name="SKU">
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="\d{3}-[A-Z]{2}"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:attributeGroup name="ItemDelivery">
+ <xsd:attribute name="partNum" type="SKU" use="required"/>
+ <xsd:attribute name="weightKg" type="xsd:decimal"/>
+ <xsd:attribute name="shipBy">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="air"/>
+ <xsd:enumeration value="land"/>
+ <xsd:enumeration value="any"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ </xsd:attributeGroup>
+
+</xsd:schema>
+
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/report.tab b/lib/xmerl/test/xmerl_xsd_SUITE_data/report.tab
new file mode 100644
index 0000000000..f5c10e2683
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/report.tab
@@ -0,0 +1,850 @@
+[{{complexType,{'RegionsType',[],'http://www.example.com/Report'}},
+ {schema_complex_type,{'RegionsType',[],'http://www.example.com/Report'},
+ undefined,
+ false,
+ ['RegionsType'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [],
+ [{sequence,{[{element,
+ {{zip,
+ ['RegionsType'],
+ 'http://www.example.com/Report'},
+ {1,unbounded}}}],
+ {1,1}}}],
+ undefined}},
+ {{complexType,{'PurchaseOrderType',[],'http://www.example.com/IPO'}},
+ {schema_complex_type,{'PurchaseOrderType',[],'http://www.example.com/IPO'},
+ undefined,
+ false,
+ ['PurchaseOrderType'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{orderDate,
+ ['PurchaseOrderType'],
+ 'http://www.example.com/IPO'}}],
+ [{sequence,{[{element,
+ {{shipTo,
+ ['PurchaseOrderType'],
+ 'http://www.example.com/IPO'},
+ {1,1}}},
+ {element,
+ {{billTo,
+ ['PurchaseOrderType'],
+ 'http://www.example.com/IPO'},
+ {1,1}}},
+ {element,
+ {{comment,
+ [],
+ 'http://www.example.com/IPO'},
+ {0,1}}},
+ {element,
+ {{items,
+ ['PurchaseOrderType'],
+ 'http://www.example.com/IPO'},
+ {1,1}}}],
+ {1,1}}}],
+ undefined}},
+ {{element,{parts,[anonymous,purchaseReport],'http://www.example.com/Report'}},
+ {schema_element,{parts,[anonymous,purchaseReport],
+ 'http://www.example.com/Report'},
+ [{simple_or_complex_Type,
+ {'PartsType',[],'http://www.example.com/Report'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,purchaseReport],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{item,['Items'],'http://www.example.com/IPO'}},
+ {schema_element,{item,['Items'],'http://www.example.com/IPO'},
+ [{complexType,{'_xmerl_no_name_',
+ [anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['Items'],
+ undefined,
+ {0,unbounded},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{part,[anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'}},
+ {schema_element,{part,[anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'},
+ [{complexType,{'_xmerl_no_name_',
+ [anonymous,
+ part,
+ anonymous,
+ zip,
+ 'RegionsType'],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,zip,'RegionsType'],
+ undefined,
+ {1,unbounded},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{attribute,{orderDate,['PurchaseOrderType'],'http://www.example.com/IPO'}},
+ {schema_attribute,{orderDate,['PurchaseOrderType'],
+ 'http://www.example.com/IPO'},
+ [{simpleType,{date,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ ['PurchaseOrderType'],
+ optional,
+ undefined,
+ undefined,
+ undefined}},
+ {{attribute,{number,[anonymous,part,anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'}},
+ {schema_attribute,{number,[anonymous,part,anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'},
+ [{simpleType,{'SKU',[],'http://www.example.com/IPO'}}],
+ false,
+ [anonymous,part,anonymous,zip,'RegionsType'],
+ optional,
+ undefined,
+ undefined,
+ undefined}},
+ {{simpleType,{'USState',[],'http://www.example.com/IPO'}},
+ {schema_simple_type,{'USState',[],'http://www.example.com/IPO'},
+ [],
+ {string,[],'http://www.w3.org/2001/XMLSchema'},
+ false,
+ [],
+ [{enumeration,["AK","AL","AR","PA"]}],
+ atomic,
+ [{restriction,{{string,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'},
+ [{enumeration,"AK"},
+ {enumeration,"AL"},
+ {enumeration,"AR"},
+ {enumeration,"PA"}]}}]}},
+ {{complexType,{'PartsType',[],'http://www.example.com/Report'}},
+ {schema_complex_type,{'PartsType',[],'http://www.example.com/Report'},
+ undefined,
+ false,
+ ['PartsType'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [],
+ [{sequence,{[{element,
+ {{part,
+ ['PartsType'],
+ 'http://www.example.com/Report'},
+ {1,unbounded}}}],
+ {1,1}}}],
+ undefined}},
+ {{attribute,{partNum,[anonymous,item,'Items'],'http://www.example.com/IPO'}},
+ {schema_attribute,{partNum,[anonymous,item,'Items'],
+ 'http://www.example.com/IPO'},
+ [{simpleType,{'SKU',[],'http://www.example.com/IPO'}}],
+ false,
+ [anonymous,item,'Items'],
+ required,
+ undefined,
+ undefined,
+ undefined}},
+ {{element,{shipTo,['PurchaseOrderType'],'http://www.example.com/IPO'}},
+ {schema_element,{shipTo,['PurchaseOrderType'],'http://www.example.com/IPO'},
+ [{simple_or_complex_Type,
+ {'Address',[],'http://www.example.com/IPO'}}],
+ false,
+ undefined,
+ [],
+ ['PurchaseOrderType'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{complexType,{'_xmerl_no_name_',[anonymous,purchaseReport],
+ 'http://www.w3.org/2001/XMLSchema'}},
+ {schema_complex_type,{'_xmerl_no_name_',
+ [anonymous,purchaseReport],
+ 'http://www.w3.org/2001/XMLSchema'},
+ undefined,
+ false,
+ [anonymous,purchaseReport],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{period,
+ [anonymous,purchaseReport],
+ 'http://www.example.com/Report'}},
+ {attribute,{periodEnding,
+ [anonymous,purchaseReport],
+ 'http://www.example.com/Report'}}],
+ [{sequence,{[{element,
+ {{regions,
+ [anonymous,purchaseReport],
+ 'http://www.example.com/Report'},
+ {1,1}}},
+ {element,
+ {{parts,
+ [anonymous,purchaseReport],
+ 'http://www.example.com/Report'},
+ {1,1}}}],
+ {1,1}}}],
+ undefined}},
+ {{simpleType,{'SKU',[],'http://www.example.com/IPO'}},
+ {schema_simple_type,{'SKU',[],'http://www.example.com/IPO'},
+ [],
+ {string,[],'http://www.w3.org/2001/XMLSchema'},
+ false,
+ [],
+ [{pattern,"\\d{3}-[A-Z]{2}"}],
+ atomic,
+ [{restriction,{{string,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'},
+ [{pattern,"\\d{3}-[A-Z]{2}"}]}}]}},
+ {{attribute,{number,[anonymous,part,'PartsType'],
+ 'http://www.example.com/Report'}},
+ {schema_attribute,{number,[anonymous,part,'PartsType'],
+ 'http://www.example.com/Report'},
+ [{simpleType,{'SKU',[],'http://www.example.com/IPO'}}],
+ false,
+ [anonymous,part,'PartsType'],
+ optional,
+ undefined,
+ undefined,
+ undefined}},
+ {{attribute,{period,[anonymous,purchaseReport],
+ 'http://www.example.com/Report'}},
+ {schema_attribute,{period,[anonymous,purchaseReport],
+ 'http://www.example.com/Report'},
+ [{simpleType,{duration,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ [anonymous,purchaseReport],
+ optional,
+ undefined,
+ undefined,
+ undefined}},
+ {{simpleType,{'_xmerl_no_name_',[quantity,anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'}},
+ {schema_simple_type,{'_xmerl_no_name_',
+ [quantity,anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'},
+ [quantity,anonymous,item,'Items'],
+ {positiveInteger,[],'http://www.w3.org/2001/XMLSchema'},
+ false,
+ [],
+ [{maxExclusive,"100"}],
+ atomic,
+ [{restriction,{{positiveInteger,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'},
+ [{maxExclusive,"100"}]}}]}},
+ {{element,{productName,[anonymous,item,'Items'],'http://www.example.com/IPO'}},
+ {schema_element,{productName,[anonymous,item,'Items'],
+ 'http://www.example.com/IPO'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,item,'Items'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{comment,[],'http://www.example.com/IPO'}},
+ {schema_element,{comment,[],'http://www.example.com/IPO'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{attribute,{periodEnding,[anonymous,purchaseReport],
+ 'http://www.example.com/Report'}},
+ {schema_attribute,{periodEnding,[anonymous,purchaseReport],
+ 'http://www.example.com/Report'},
+ [{simpleType,{date,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ [anonymous,purchaseReport],
+ optional,
+ undefined,
+ undefined,
+ undefined}},
+ {{complexType,{'Address',[],'http://www.example.com/IPO'}},
+ {schema_complex_type,{'Address',[],'http://www.example.com/IPO'},
+ undefined,
+ false,
+ ['Address'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [],
+ [{sequence,{[{element,
+ {{name,
+ ['Address'],
+ 'http://www.example.com/IPO'},
+ {1,1}}},
+ {element,
+ {{street,
+ ['Address'],
+ 'http://www.example.com/IPO'},
+ {1,1}}},
+ {element,
+ {{city,
+ ['Address'],
+ 'http://www.example.com/IPO'},
+ {1,1}}}],
+ {1,1}}}],
+ undefined}},
+ {{element,{purchaseOrder,[],'http://www.example.com/IPO'}},
+ {schema_element,{purchaseOrder,[],'http://www.example.com/IPO'},
+ [{simple_or_complex_Type,
+ {'PurchaseOrderType',[],'http://www.example.com/IPO'}}],
+ false,
+ undefined,
+ [],
+ [],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{complexType,{'_xmerl_no_name_',[anonymous,part,'PartsType'],
+ 'http://www.w3.org/2001/XMLSchema'}},
+ {schema_complex_type,{'_xmerl_no_name_',
+ [anonymous,part,'PartsType'],
+ 'http://www.w3.org/2001/XMLSchema'},
+ undefined,
+ false,
+ [anonymous,part,'PartsType'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{number,
+ [anonymous,part,'PartsType'],
+ 'http://www.example.com/Report'}}],
+ [{extension,{{string,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'},
+ []}}],
+ undefined}},
+ {{element,{zip,['RegionsType'],'http://www.example.com/Report'}},
+ {schema_element,{zip,['RegionsType'],'http://www.example.com/Report'},
+ [{complexType,{'_xmerl_no_name_',
+ [anonymous,zip,'RegionsType'],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['RegionsType'],
+ undefined,
+ {1,unbounded},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{state,['USAddress'],'http://www.example.com/IPO'}},
+ {schema_element,{state,['USAddress'],'http://www.example.com/IPO'},
+ [{simple_or_complex_Type,
+ {'USState',[],'http://www.example.com/IPO'}}],
+ false,
+ undefined,
+ [],
+ ['USAddress'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{items,['PurchaseOrderType'],'http://www.example.com/IPO'}},
+ {schema_element,{items,['PurchaseOrderType'],'http://www.example.com/IPO'},
+ [{simple_or_complex_Type,
+ {'Items',[],'http://www.example.com/IPO'}}],
+ false,
+ undefined,
+ [],
+ ['PurchaseOrderType'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{simpleType,{'UKPostcode',[],'http://www.example.com/IPO'}},
+ {schema_simple_type,{'UKPostcode',[],'http://www.example.com/IPO'},
+ [],
+ {'Postcode',[],'http://www.example.com/IPO'},
+ false,
+ [],
+ [{pattern,"[A-Z]{2}\\d\\s\\d[A-Z]{2}"}],
+ atomic,
+ [{restriction,{{'Postcode',
+ [],
+ 'http://www.example.com/IPO'},
+ [{pattern,"[A-Z]{2}\\d\\s\\d[A-Z]{2}"}]}}]}},
+ {{complexType,{'Items',[],'http://www.example.com/IPO'}},
+ {schema_complex_type,{'Items',[],'http://www.example.com/IPO'},
+ undefined,
+ false,
+ ['Items'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [],
+ [{sequence,{[{element,
+ {{item,
+ ['Items'],
+ 'http://www.example.com/IPO'},
+ {0,unbounded}}}],
+ {1,1}}}],
+ undefined}},
+ {{element,{quantity,[anonymous,item,'Items'],'http://www.example.com/IPO'}},
+ {schema_element,{quantity,[anonymous,item,'Items'],
+ 'http://www.example.com/IPO'},
+ [{simpleType,{'_xmerl_no_name_',
+ [quantity,anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,item,'Items'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{attribute,{code,[anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'}},
+ {schema_attribute,{code,[anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'},
+ [{simpleType,{positiveInteger,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ [anonymous,zip,'RegionsType'],
+ optional,
+ undefined,
+ undefined,
+ undefined}},
+ {{element,{purchaseReport,[],'http://www.example.com/Report'}},
+ {schema_element,{purchaseReport,[],'http://www.example.com/Report'},
+ [{complexType,{'_xmerl_no_name_',
+ [anonymous,purchaseReport],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [{unique,{unique,{dummy1,
+ [purchaseReport],
+ 'http://www.example.com/Report'},
+ {selector,"r:regions/r:zip"},
+ [{field,"@code"}]}}],
+ [],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{street,['Address'],'http://www.example.com/IPO'}},
+ {schema_element,{street,['Address'],'http://www.example.com/IPO'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['Address'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{zip,['USAddress'],'http://www.example.com/IPO'}},
+ {schema_element,{zip,['USAddress'],'http://www.example.com/IPO'},
+ [{simpleType,{positiveInteger,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['USAddress'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{regions,[anonymous,purchaseReport],
+ 'http://www.example.com/Report'}},
+ {schema_element,{regions,[anonymous,purchaseReport],
+ 'http://www.example.com/Report'},
+ [{simple_or_complex_Type,
+ {'RegionsType',[],'http://www.example.com/Report'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,purchaseReport],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{part,['PartsType'],'http://www.example.com/Report'}},
+ {schema_element,{part,['PartsType'],'http://www.example.com/Report'},
+ [{complexType,{'_xmerl_no_name_',
+ [anonymous,part,'PartsType'],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['PartsType'],
+ undefined,
+ {1,unbounded},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{city,['Address'],'http://www.example.com/IPO'}},
+ {schema_element,{city,['Address'],'http://www.example.com/IPO'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['Address'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{complexType,{'USAddress',[],'http://www.example.com/IPO'}},
+ {schema_complex_type,{'USAddress',[],'http://www.example.com/IPO'},
+ undefined,
+ false,
+ ['USAddress'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [],
+ [{extension,{{'Address',
+ [],
+ 'http://www.example.com/IPO'},
+ [{sequence,
+ {[{element,
+ {{state,
+ ['USAddress'],
+ 'http://www.example.com/IPO'},
+ {1,1}}},
+ {element,
+ {{zip,
+ ['USAddress'],
+ 'http://www.example.com/IPO'},
+ {1,1}}}],
+ {1,1}}}]}}],
+ undefined}},
+ {{complexType,{'_xmerl_no_name_',[anonymous,part,anonymous,zip,'RegionsType'],
+ 'http://www.w3.org/2001/XMLSchema'}},
+ {schema_complex_type,{'_xmerl_no_name_',
+ [anonymous,part,anonymous,zip,'RegionsType'],
+ 'http://www.w3.org/2001/XMLSchema'},
+ undefined,
+ false,
+ [anonymous,part,anonymous,zip,'RegionsType'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{number,
+ [anonymous,
+ part,
+ anonymous,
+ zip,
+ 'RegionsType'],
+ 'http://www.example.com/Report'}},
+ {attribute,{quantity,
+ [anonymous,
+ part,
+ anonymous,
+ zip,
+ 'RegionsType'],
+ 'http://www.example.com/Report'}}],
+ [{restriction,{{anyType,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'},
+ []}}],
+ undefined}},
+ {{element,{billTo,['PurchaseOrderType'],'http://www.example.com/IPO'}},
+ {schema_element,{billTo,['PurchaseOrderType'],'http://www.example.com/IPO'},
+ [{simple_or_complex_Type,
+ {'Address',[],'http://www.example.com/IPO'}}],
+ false,
+ undefined,
+ [],
+ ['PurchaseOrderType'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{postcode,['UKAddress'],'http://www.example.com/IPO'}},
+ {schema_element,{postcode,['UKAddress'],'http://www.example.com/IPO'},
+ [{simple_or_complex_Type,
+ {'UKPostcode',[],'http://www.example.com/IPO'}}],
+ false,
+ undefined,
+ [],
+ ['UKAddress'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{schema,"report.xsd"},
+ {schema,qualified,
+ unqualified,
+ 'http://www.example.com/Report',
+ [],
+ [],
+ [{element,{{purchaseReport,[],'http://www.example.com/Report'},
+ {1,1}}}]}},
+ {{complexType,{'_xmerl_no_name_',[anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'}},
+ {schema_complex_type,{'_xmerl_no_name_',
+ [anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'},
+ undefined,
+ false,
+ [anonymous,item,'Items'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{partNum,
+ [anonymous,item,'Items'],
+ 'http://www.example.com/IPO'}}],
+ [{sequence,{[{element,
+ {{productName,
+ [anonymous,item,'Items'],
+ 'http://www.example.com/IPO'},
+ {1,1}}},
+ {element,
+ {{quantity,
+ [anonymous,item,'Items'],
+ 'http://www.example.com/IPO'},
+ {1,1}}},
+ {element,
+ {{'USPrice',
+ [anonymous,item,'Items'],
+ 'http://www.example.com/IPO'},
+ {1,1}}},
+ {element,
+ {{comment,
+ [],
+ 'http://www.example.com/IPO'},
+ {0,1}}},
+ {element,
+ {{shipDate,
+ [anonymous,item,'Items'],
+ 'http://www.example.com/IPO'},
+ {0,1}}}],
+ {1,1}}}],
+ undefined}},
+ {{simpleType,{'Postcode',[],'http://www.example.com/IPO'}},
+ {schema_simple_type,{'Postcode',[],'http://www.example.com/IPO'},
+ [],
+ {string,[],'http://www.w3.org/2001/XMLSchema'},
+ false,
+ [],
+ [{length,"7"}],
+ atomic,
+ [{restriction,{{string,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'},
+ [{length,"7"}]}}]}},
+ {{element,{'USPrice',[anonymous,item,'Items'],'http://www.example.com/IPO'}},
+ {schema_element,{'USPrice',[anonymous,item,'Items'],
+ 'http://www.example.com/IPO'},
+ [{simpleType,{decimal,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,item,'Items'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{schema,"ipo.xsd"},
+ {schema,unqualified,
+ unqualified,
+ 'http://www.example.com/IPO',
+ [],
+ [],
+ [{element,{{purchaseOrder,[],'http://www.example.com/IPO'},{1,1}}},
+ {element,{{comment,[],'http://www.example.com/IPO'},{1,1}}}]}},
+ {{attribute,{quantity,[anonymous,part,anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'}},
+ {schema_attribute,{quantity,[anonymous,part,anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'},
+ [{simpleType,{positiveInteger,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ [anonymous,part,anonymous,zip,'RegionsType'],
+ optional,
+ undefined,
+ undefined,
+ undefined}},
+ {{element,{shipDate,[anonymous,item,'Items'],'http://www.example.com/IPO'}},
+ {schema_element,{shipDate,[anonymous,item,'Items'],
+ 'http://www.example.com/IPO'},
+ [{simpleType,{date,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,item,'Items'],
+ undefined,
+ {0,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{attribute,{exportCode,['UKAddress'],'http://www.example.com/IPO'}},
+ {schema_attribute,{exportCode,['UKAddress'],'http://www.example.com/IPO'},
+ [{simpleType,{positiveInteger,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ ['UKAddress'],
+ optional,
+ undefined,
+ "1",
+ undefined}},
+ {{element,{name,['Address'],'http://www.example.com/IPO'}},
+ {schema_element,{name,['Address'],'http://www.example.com/IPO'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['Address'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{complexType,{'_xmerl_no_name_',[anonymous,zip,'RegionsType'],
+ 'http://www.w3.org/2001/XMLSchema'}},
+ {schema_complex_type,{'_xmerl_no_name_',
+ [anonymous,zip,'RegionsType'],
+ 'http://www.w3.org/2001/XMLSchema'},
+ undefined,
+ false,
+ [anonymous,zip,'RegionsType'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{code,
+ [anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'}}],
+ [{sequence,{[{element,
+ {{part,
+ [anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'},
+ {1,unbounded}}}],
+ {1,1}}}],
+ undefined}},
+ {{complexType,{'UKAddress',[],'http://www.example.com/IPO'}},
+ {schema_complex_type,{'UKAddress',[],'http://www.example.com/IPO'},
+ undefined,
+ false,
+ ['UKAddress'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{exportCode,
+ ['UKAddress'],
+ 'http://www.example.com/IPO'}}],
+ [{extension,{{'Address',
+ [],
+ 'http://www.example.com/IPO'},
+ [{sequence,
+ {[{element,
+ {{postcode,
+ ['UKAddress'],
+ 'http://www.example.com/IPO'},
+ {1,1}}}],
+ {1,1}}}]}}],
+ undefined}}]
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/report.tab2 b/lib/xmerl/test/xmerl_xsd_SUITE_data/report.tab2
new file mode 100644
index 0000000000..f5c10e2683
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/report.tab2
@@ -0,0 +1,850 @@
+[{{complexType,{'RegionsType',[],'http://www.example.com/Report'}},
+ {schema_complex_type,{'RegionsType',[],'http://www.example.com/Report'},
+ undefined,
+ false,
+ ['RegionsType'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [],
+ [{sequence,{[{element,
+ {{zip,
+ ['RegionsType'],
+ 'http://www.example.com/Report'},
+ {1,unbounded}}}],
+ {1,1}}}],
+ undefined}},
+ {{complexType,{'PurchaseOrderType',[],'http://www.example.com/IPO'}},
+ {schema_complex_type,{'PurchaseOrderType',[],'http://www.example.com/IPO'},
+ undefined,
+ false,
+ ['PurchaseOrderType'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{orderDate,
+ ['PurchaseOrderType'],
+ 'http://www.example.com/IPO'}}],
+ [{sequence,{[{element,
+ {{shipTo,
+ ['PurchaseOrderType'],
+ 'http://www.example.com/IPO'},
+ {1,1}}},
+ {element,
+ {{billTo,
+ ['PurchaseOrderType'],
+ 'http://www.example.com/IPO'},
+ {1,1}}},
+ {element,
+ {{comment,
+ [],
+ 'http://www.example.com/IPO'},
+ {0,1}}},
+ {element,
+ {{items,
+ ['PurchaseOrderType'],
+ 'http://www.example.com/IPO'},
+ {1,1}}}],
+ {1,1}}}],
+ undefined}},
+ {{element,{parts,[anonymous,purchaseReport],'http://www.example.com/Report'}},
+ {schema_element,{parts,[anonymous,purchaseReport],
+ 'http://www.example.com/Report'},
+ [{simple_or_complex_Type,
+ {'PartsType',[],'http://www.example.com/Report'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,purchaseReport],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{item,['Items'],'http://www.example.com/IPO'}},
+ {schema_element,{item,['Items'],'http://www.example.com/IPO'},
+ [{complexType,{'_xmerl_no_name_',
+ [anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['Items'],
+ undefined,
+ {0,unbounded},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{part,[anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'}},
+ {schema_element,{part,[anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'},
+ [{complexType,{'_xmerl_no_name_',
+ [anonymous,
+ part,
+ anonymous,
+ zip,
+ 'RegionsType'],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,zip,'RegionsType'],
+ undefined,
+ {1,unbounded},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{attribute,{orderDate,['PurchaseOrderType'],'http://www.example.com/IPO'}},
+ {schema_attribute,{orderDate,['PurchaseOrderType'],
+ 'http://www.example.com/IPO'},
+ [{simpleType,{date,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ ['PurchaseOrderType'],
+ optional,
+ undefined,
+ undefined,
+ undefined}},
+ {{attribute,{number,[anonymous,part,anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'}},
+ {schema_attribute,{number,[anonymous,part,anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'},
+ [{simpleType,{'SKU',[],'http://www.example.com/IPO'}}],
+ false,
+ [anonymous,part,anonymous,zip,'RegionsType'],
+ optional,
+ undefined,
+ undefined,
+ undefined}},
+ {{simpleType,{'USState',[],'http://www.example.com/IPO'}},
+ {schema_simple_type,{'USState',[],'http://www.example.com/IPO'},
+ [],
+ {string,[],'http://www.w3.org/2001/XMLSchema'},
+ false,
+ [],
+ [{enumeration,["AK","AL","AR","PA"]}],
+ atomic,
+ [{restriction,{{string,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'},
+ [{enumeration,"AK"},
+ {enumeration,"AL"},
+ {enumeration,"AR"},
+ {enumeration,"PA"}]}}]}},
+ {{complexType,{'PartsType',[],'http://www.example.com/Report'}},
+ {schema_complex_type,{'PartsType',[],'http://www.example.com/Report'},
+ undefined,
+ false,
+ ['PartsType'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [],
+ [{sequence,{[{element,
+ {{part,
+ ['PartsType'],
+ 'http://www.example.com/Report'},
+ {1,unbounded}}}],
+ {1,1}}}],
+ undefined}},
+ {{attribute,{partNum,[anonymous,item,'Items'],'http://www.example.com/IPO'}},
+ {schema_attribute,{partNum,[anonymous,item,'Items'],
+ 'http://www.example.com/IPO'},
+ [{simpleType,{'SKU',[],'http://www.example.com/IPO'}}],
+ false,
+ [anonymous,item,'Items'],
+ required,
+ undefined,
+ undefined,
+ undefined}},
+ {{element,{shipTo,['PurchaseOrderType'],'http://www.example.com/IPO'}},
+ {schema_element,{shipTo,['PurchaseOrderType'],'http://www.example.com/IPO'},
+ [{simple_or_complex_Type,
+ {'Address',[],'http://www.example.com/IPO'}}],
+ false,
+ undefined,
+ [],
+ ['PurchaseOrderType'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{complexType,{'_xmerl_no_name_',[anonymous,purchaseReport],
+ 'http://www.w3.org/2001/XMLSchema'}},
+ {schema_complex_type,{'_xmerl_no_name_',
+ [anonymous,purchaseReport],
+ 'http://www.w3.org/2001/XMLSchema'},
+ undefined,
+ false,
+ [anonymous,purchaseReport],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{period,
+ [anonymous,purchaseReport],
+ 'http://www.example.com/Report'}},
+ {attribute,{periodEnding,
+ [anonymous,purchaseReport],
+ 'http://www.example.com/Report'}}],
+ [{sequence,{[{element,
+ {{regions,
+ [anonymous,purchaseReport],
+ 'http://www.example.com/Report'},
+ {1,1}}},
+ {element,
+ {{parts,
+ [anonymous,purchaseReport],
+ 'http://www.example.com/Report'},
+ {1,1}}}],
+ {1,1}}}],
+ undefined}},
+ {{simpleType,{'SKU',[],'http://www.example.com/IPO'}},
+ {schema_simple_type,{'SKU',[],'http://www.example.com/IPO'},
+ [],
+ {string,[],'http://www.w3.org/2001/XMLSchema'},
+ false,
+ [],
+ [{pattern,"\\d{3}-[A-Z]{2}"}],
+ atomic,
+ [{restriction,{{string,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'},
+ [{pattern,"\\d{3}-[A-Z]{2}"}]}}]}},
+ {{attribute,{number,[anonymous,part,'PartsType'],
+ 'http://www.example.com/Report'}},
+ {schema_attribute,{number,[anonymous,part,'PartsType'],
+ 'http://www.example.com/Report'},
+ [{simpleType,{'SKU',[],'http://www.example.com/IPO'}}],
+ false,
+ [anonymous,part,'PartsType'],
+ optional,
+ undefined,
+ undefined,
+ undefined}},
+ {{attribute,{period,[anonymous,purchaseReport],
+ 'http://www.example.com/Report'}},
+ {schema_attribute,{period,[anonymous,purchaseReport],
+ 'http://www.example.com/Report'},
+ [{simpleType,{duration,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ [anonymous,purchaseReport],
+ optional,
+ undefined,
+ undefined,
+ undefined}},
+ {{simpleType,{'_xmerl_no_name_',[quantity,anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'}},
+ {schema_simple_type,{'_xmerl_no_name_',
+ [quantity,anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'},
+ [quantity,anonymous,item,'Items'],
+ {positiveInteger,[],'http://www.w3.org/2001/XMLSchema'},
+ false,
+ [],
+ [{maxExclusive,"100"}],
+ atomic,
+ [{restriction,{{positiveInteger,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'},
+ [{maxExclusive,"100"}]}}]}},
+ {{element,{productName,[anonymous,item,'Items'],'http://www.example.com/IPO'}},
+ {schema_element,{productName,[anonymous,item,'Items'],
+ 'http://www.example.com/IPO'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,item,'Items'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{comment,[],'http://www.example.com/IPO'}},
+ {schema_element,{comment,[],'http://www.example.com/IPO'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{attribute,{periodEnding,[anonymous,purchaseReport],
+ 'http://www.example.com/Report'}},
+ {schema_attribute,{periodEnding,[anonymous,purchaseReport],
+ 'http://www.example.com/Report'},
+ [{simpleType,{date,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ [anonymous,purchaseReport],
+ optional,
+ undefined,
+ undefined,
+ undefined}},
+ {{complexType,{'Address',[],'http://www.example.com/IPO'}},
+ {schema_complex_type,{'Address',[],'http://www.example.com/IPO'},
+ undefined,
+ false,
+ ['Address'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [],
+ [{sequence,{[{element,
+ {{name,
+ ['Address'],
+ 'http://www.example.com/IPO'},
+ {1,1}}},
+ {element,
+ {{street,
+ ['Address'],
+ 'http://www.example.com/IPO'},
+ {1,1}}},
+ {element,
+ {{city,
+ ['Address'],
+ 'http://www.example.com/IPO'},
+ {1,1}}}],
+ {1,1}}}],
+ undefined}},
+ {{element,{purchaseOrder,[],'http://www.example.com/IPO'}},
+ {schema_element,{purchaseOrder,[],'http://www.example.com/IPO'},
+ [{simple_or_complex_Type,
+ {'PurchaseOrderType',[],'http://www.example.com/IPO'}}],
+ false,
+ undefined,
+ [],
+ [],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{complexType,{'_xmerl_no_name_',[anonymous,part,'PartsType'],
+ 'http://www.w3.org/2001/XMLSchema'}},
+ {schema_complex_type,{'_xmerl_no_name_',
+ [anonymous,part,'PartsType'],
+ 'http://www.w3.org/2001/XMLSchema'},
+ undefined,
+ false,
+ [anonymous,part,'PartsType'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{number,
+ [anonymous,part,'PartsType'],
+ 'http://www.example.com/Report'}}],
+ [{extension,{{string,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'},
+ []}}],
+ undefined}},
+ {{element,{zip,['RegionsType'],'http://www.example.com/Report'}},
+ {schema_element,{zip,['RegionsType'],'http://www.example.com/Report'},
+ [{complexType,{'_xmerl_no_name_',
+ [anonymous,zip,'RegionsType'],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['RegionsType'],
+ undefined,
+ {1,unbounded},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{state,['USAddress'],'http://www.example.com/IPO'}},
+ {schema_element,{state,['USAddress'],'http://www.example.com/IPO'},
+ [{simple_or_complex_Type,
+ {'USState',[],'http://www.example.com/IPO'}}],
+ false,
+ undefined,
+ [],
+ ['USAddress'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{items,['PurchaseOrderType'],'http://www.example.com/IPO'}},
+ {schema_element,{items,['PurchaseOrderType'],'http://www.example.com/IPO'},
+ [{simple_or_complex_Type,
+ {'Items',[],'http://www.example.com/IPO'}}],
+ false,
+ undefined,
+ [],
+ ['PurchaseOrderType'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{simpleType,{'UKPostcode',[],'http://www.example.com/IPO'}},
+ {schema_simple_type,{'UKPostcode',[],'http://www.example.com/IPO'},
+ [],
+ {'Postcode',[],'http://www.example.com/IPO'},
+ false,
+ [],
+ [{pattern,"[A-Z]{2}\\d\\s\\d[A-Z]{2}"}],
+ atomic,
+ [{restriction,{{'Postcode',
+ [],
+ 'http://www.example.com/IPO'},
+ [{pattern,"[A-Z]{2}\\d\\s\\d[A-Z]{2}"}]}}]}},
+ {{complexType,{'Items',[],'http://www.example.com/IPO'}},
+ {schema_complex_type,{'Items',[],'http://www.example.com/IPO'},
+ undefined,
+ false,
+ ['Items'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [],
+ [{sequence,{[{element,
+ {{item,
+ ['Items'],
+ 'http://www.example.com/IPO'},
+ {0,unbounded}}}],
+ {1,1}}}],
+ undefined}},
+ {{element,{quantity,[anonymous,item,'Items'],'http://www.example.com/IPO'}},
+ {schema_element,{quantity,[anonymous,item,'Items'],
+ 'http://www.example.com/IPO'},
+ [{simpleType,{'_xmerl_no_name_',
+ [quantity,anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,item,'Items'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{attribute,{code,[anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'}},
+ {schema_attribute,{code,[anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'},
+ [{simpleType,{positiveInteger,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ [anonymous,zip,'RegionsType'],
+ optional,
+ undefined,
+ undefined,
+ undefined}},
+ {{element,{purchaseReport,[],'http://www.example.com/Report'}},
+ {schema_element,{purchaseReport,[],'http://www.example.com/Report'},
+ [{complexType,{'_xmerl_no_name_',
+ [anonymous,purchaseReport],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [{unique,{unique,{dummy1,
+ [purchaseReport],
+ 'http://www.example.com/Report'},
+ {selector,"r:regions/r:zip"},
+ [{field,"@code"}]}}],
+ [],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{street,['Address'],'http://www.example.com/IPO'}},
+ {schema_element,{street,['Address'],'http://www.example.com/IPO'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['Address'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{zip,['USAddress'],'http://www.example.com/IPO'}},
+ {schema_element,{zip,['USAddress'],'http://www.example.com/IPO'},
+ [{simpleType,{positiveInteger,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['USAddress'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{regions,[anonymous,purchaseReport],
+ 'http://www.example.com/Report'}},
+ {schema_element,{regions,[anonymous,purchaseReport],
+ 'http://www.example.com/Report'},
+ [{simple_or_complex_Type,
+ {'RegionsType',[],'http://www.example.com/Report'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,purchaseReport],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{part,['PartsType'],'http://www.example.com/Report'}},
+ {schema_element,{part,['PartsType'],'http://www.example.com/Report'},
+ [{complexType,{'_xmerl_no_name_',
+ [anonymous,part,'PartsType'],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['PartsType'],
+ undefined,
+ {1,unbounded},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{city,['Address'],'http://www.example.com/IPO'}},
+ {schema_element,{city,['Address'],'http://www.example.com/IPO'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['Address'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{complexType,{'USAddress',[],'http://www.example.com/IPO'}},
+ {schema_complex_type,{'USAddress',[],'http://www.example.com/IPO'},
+ undefined,
+ false,
+ ['USAddress'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [],
+ [{extension,{{'Address',
+ [],
+ 'http://www.example.com/IPO'},
+ [{sequence,
+ {[{element,
+ {{state,
+ ['USAddress'],
+ 'http://www.example.com/IPO'},
+ {1,1}}},
+ {element,
+ {{zip,
+ ['USAddress'],
+ 'http://www.example.com/IPO'},
+ {1,1}}}],
+ {1,1}}}]}}],
+ undefined}},
+ {{complexType,{'_xmerl_no_name_',[anonymous,part,anonymous,zip,'RegionsType'],
+ 'http://www.w3.org/2001/XMLSchema'}},
+ {schema_complex_type,{'_xmerl_no_name_',
+ [anonymous,part,anonymous,zip,'RegionsType'],
+ 'http://www.w3.org/2001/XMLSchema'},
+ undefined,
+ false,
+ [anonymous,part,anonymous,zip,'RegionsType'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{number,
+ [anonymous,
+ part,
+ anonymous,
+ zip,
+ 'RegionsType'],
+ 'http://www.example.com/Report'}},
+ {attribute,{quantity,
+ [anonymous,
+ part,
+ anonymous,
+ zip,
+ 'RegionsType'],
+ 'http://www.example.com/Report'}}],
+ [{restriction,{{anyType,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'},
+ []}}],
+ undefined}},
+ {{element,{billTo,['PurchaseOrderType'],'http://www.example.com/IPO'}},
+ {schema_element,{billTo,['PurchaseOrderType'],'http://www.example.com/IPO'},
+ [{simple_or_complex_Type,
+ {'Address',[],'http://www.example.com/IPO'}}],
+ false,
+ undefined,
+ [],
+ ['PurchaseOrderType'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{element,{postcode,['UKAddress'],'http://www.example.com/IPO'}},
+ {schema_element,{postcode,['UKAddress'],'http://www.example.com/IPO'},
+ [{simple_or_complex_Type,
+ {'UKPostcode',[],'http://www.example.com/IPO'}}],
+ false,
+ undefined,
+ [],
+ ['UKAddress'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{schema,"report.xsd"},
+ {schema,qualified,
+ unqualified,
+ 'http://www.example.com/Report',
+ [],
+ [],
+ [{element,{{purchaseReport,[],'http://www.example.com/Report'},
+ {1,1}}}]}},
+ {{complexType,{'_xmerl_no_name_',[anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'}},
+ {schema_complex_type,{'_xmerl_no_name_',
+ [anonymous,item,'Items'],
+ 'http://www.w3.org/2001/XMLSchema'},
+ undefined,
+ false,
+ [anonymous,item,'Items'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{partNum,
+ [anonymous,item,'Items'],
+ 'http://www.example.com/IPO'}}],
+ [{sequence,{[{element,
+ {{productName,
+ [anonymous,item,'Items'],
+ 'http://www.example.com/IPO'},
+ {1,1}}},
+ {element,
+ {{quantity,
+ [anonymous,item,'Items'],
+ 'http://www.example.com/IPO'},
+ {1,1}}},
+ {element,
+ {{'USPrice',
+ [anonymous,item,'Items'],
+ 'http://www.example.com/IPO'},
+ {1,1}}},
+ {element,
+ {{comment,
+ [],
+ 'http://www.example.com/IPO'},
+ {0,1}}},
+ {element,
+ {{shipDate,
+ [anonymous,item,'Items'],
+ 'http://www.example.com/IPO'},
+ {0,1}}}],
+ {1,1}}}],
+ undefined}},
+ {{simpleType,{'Postcode',[],'http://www.example.com/IPO'}},
+ {schema_simple_type,{'Postcode',[],'http://www.example.com/IPO'},
+ [],
+ {string,[],'http://www.w3.org/2001/XMLSchema'},
+ false,
+ [],
+ [{length,"7"}],
+ atomic,
+ [{restriction,{{string,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'},
+ [{length,"7"}]}}]}},
+ {{element,{'USPrice',[anonymous,item,'Items'],'http://www.example.com/IPO'}},
+ {schema_element,{'USPrice',[anonymous,item,'Items'],
+ 'http://www.example.com/IPO'},
+ [{simpleType,{decimal,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,item,'Items'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{schema,"ipo.xsd"},
+ {schema,unqualified,
+ unqualified,
+ 'http://www.example.com/IPO',
+ [],
+ [],
+ [{element,{{purchaseOrder,[],'http://www.example.com/IPO'},{1,1}}},
+ {element,{{comment,[],'http://www.example.com/IPO'},{1,1}}}]}},
+ {{attribute,{quantity,[anonymous,part,anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'}},
+ {schema_attribute,{quantity,[anonymous,part,anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'},
+ [{simpleType,{positiveInteger,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ [anonymous,part,anonymous,zip,'RegionsType'],
+ optional,
+ undefined,
+ undefined,
+ undefined}},
+ {{element,{shipDate,[anonymous,item,'Items'],'http://www.example.com/IPO'}},
+ {schema_element,{shipDate,[anonymous,item,'Items'],
+ 'http://www.example.com/IPO'},
+ [{simpleType,{date,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ [anonymous,item,'Items'],
+ undefined,
+ {0,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{attribute,{exportCode,['UKAddress'],'http://www.example.com/IPO'}},
+ {schema_attribute,{exportCode,['UKAddress'],'http://www.example.com/IPO'},
+ [{simpleType,{positiveInteger,
+ [],
+ 'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ ['UKAddress'],
+ optional,
+ undefined,
+ "1",
+ undefined}},
+ {{element,{name,['Address'],'http://www.example.com/IPO'}},
+ {schema_element,{name,['Address'],'http://www.example.com/IPO'},
+ [{simpleType,{string,[],'http://www.w3.org/2001/XMLSchema'}}],
+ false,
+ undefined,
+ [],
+ ['Address'],
+ undefined,
+ {1,1},
+ undefined,
+ undefined,
+ false,
+ [],
+ []}},
+ {{complexType,{'_xmerl_no_name_',[anonymous,zip,'RegionsType'],
+ 'http://www.w3.org/2001/XMLSchema'}},
+ {schema_complex_type,{'_xmerl_no_name_',
+ [anonymous,zip,'RegionsType'],
+ 'http://www.w3.org/2001/XMLSchema'},
+ undefined,
+ false,
+ [anonymous,zip,'RegionsType'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{code,
+ [anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'}}],
+ [{sequence,{[{element,
+ {{part,
+ [anonymous,zip,'RegionsType'],
+ 'http://www.example.com/Report'},
+ {1,unbounded}}}],
+ {1,1}}}],
+ undefined}},
+ {{complexType,{'UKAddress',[],'http://www.example.com/IPO'}},
+ {schema_complex_type,{'UKAddress',[],'http://www.example.com/IPO'},
+ undefined,
+ false,
+ ['UKAddress'],
+ undefined,
+ [],
+ [],
+ false,
+ 'element-only',
+ [{attribute,{exportCode,
+ ['UKAddress'],
+ 'http://www.example.com/IPO'}}],
+ [{extension,{{'Address',
+ [],
+ 'http://www.example.com/IPO'},
+ [{sequence,
+ {[{element,
+ {{postcode,
+ ['UKAddress'],
+ 'http://www.example.com/IPO'},
+ {1,1}}}],
+ {1,1}}}]}}],
+ undefined}}]
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/report.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/report.xsd
new file mode 100644
index 0000000000..8db7b8219f
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/report.xsd
@@ -0,0 +1,82 @@
+<schema targetNamespace="http://www.example.com/Report"
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:r="http://www.example.com/Report"
+ xmlns:xipo="http://www.example.com/IPO"
+ elementFormDefault="qualified">
+
+ <!-- for SKU -->
+ <import namespace="http://www.example.com/IPO"/>
+
+ <annotation>
+ <documentation xml:lang="en">
+ Report schema for Example.com
+ Copyright 2000 Example.com. All rights reserved.
+ </documentation>
+ </annotation>
+
+ <element name="purchaseReport">
+ <complexType>
+ <sequence>
+ <element name="regions" type="r:RegionsType"/>
+
+ <element name="parts" type="r:PartsType"/>
+ </sequence>
+ <attribute name="period" type="duration"/>
+ <attribute name="periodEnding" type="date"/>
+ </complexType>
+
+ <unique name="dummy1">
+ <selector xpath="r:regions/r:zip"/>
+ <field xpath="@code"/>
+ </unique>
+
+ <key name="pNumKey">
+ <selector xpath="r:parts/r:part"/>
+ <field xpath="@number"/>
+ </key>
+
+ <keyref name="dummy2" refer="r:pNumKey">
+ <selector xpath="r:regions/r:zip/r:part"/>
+ <field xpath="@number"/>
+ </keyref>
+
+ </element>
+
+ <complexType name="RegionsType">
+ <sequence>
+ <element name="zip" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="part" maxOccurs="unbounded">
+ <complexType>
+ <complexContent>
+ <restriction base="anyType">
+ <attribute name="number" type="xipo:SKU"/>
+ <attribute name="quantity" type="positiveInteger"/>
+ </restriction>
+ </complexContent>
+ </complexType>
+ </element>
+ </sequence>
+ <attribute name="code" type="positiveInteger"/>
+ </complexType>
+ </element>
+ </sequence>
+ </complexType>
+
+ <complexType name="PartsType">
+ <sequence>
+ <element name="part" maxOccurs="unbounded">
+ <complexType>
+ <simpleContent>
+ <extension base="string">
+ <attribute name="number" type="xipo:SKU"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+ </element>
+ </sequence>
+ </complexType>
+
+</schema>
+
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/report2.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/report2.xsd
new file mode 100644
index 0000000000..a114cad4f2
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/report2.xsd
@@ -0,0 +1,82 @@
+<schema targetNamespace="http://www.example.com/Report"
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:r="http://www.example.com/Report"
+ xmlns:xipo="http://www.example.com/IPO"
+ elementFormDefault="qualified">
+
+ <!-- for SKU -->
+ <import namespace="http://www.example.com/IPO" schemaLocation="ipo.xsd"/>
+
+ <annotation>
+ <documentation xml:lang="en">
+ Report schema for Example.com
+ Copyright 2000 Example.com. All rights reserved.
+ </documentation>
+ </annotation>
+
+ <element name="purchaseReport">
+ <complexType>
+ <sequence>
+ <element name="regions" type="r:RegionsType"/>
+
+ <element name="parts" type="r:PartsType"/>
+ </sequence>
+ <attribute name="period" type="duration"/>
+ <attribute name="periodEnding" type="date"/>
+ </complexType>
+
+ <unique name="dummy1">
+ <selector xpath="r:regions/r:zip"/>
+ <field xpath="@code"/>
+ </unique>
+
+ <key name="pNumKey">
+ <selector xpath="r:parts/r:part"/>
+ <field xpath="@number"/>
+ </key>
+
+ <keyref name="dummy2" refer="r:pNumKey">
+ <selector xpath="r:regions/r:zip/r:part"/>
+ <field xpath="@number"/>
+ </keyref>
+
+ </element>
+
+ <complexType name="RegionsType">
+ <sequence>
+ <element name="zip" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="part" maxOccurs="unbounded">
+ <complexType>
+ <complexContent>
+ <restriction base="anyType">
+ <attribute name="number" type="xipo:SKU"/>
+ <attribute name="quantity" type="positiveInteger"/>
+ </restriction>
+ </complexContent>
+ </complexType>
+ </element>
+ </sequence>
+ <attribute name="code" type="positiveInteger"/>
+ </complexType>
+ </element>
+ </sequence>
+ </complexType>
+
+ <complexType name="PartsType">
+ <sequence>
+ <element name="part" maxOccurs="unbounded">
+ <complexType>
+ <simpleContent>
+ <extension base="string">
+ <attribute name="number" type="xipo:SKU"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+ </element>
+ </sequence>
+ </complexType>
+
+</schema>
+
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/simple_int.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/simple_int.xsd
new file mode 100644
index 0000000000..12f98421dc
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/simple_int.xsd
@@ -0,0 +1,13 @@
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Purchase order schema for Example.com.
+ Copyright 2000 Example.com. All rights reserved.
+ </xsd:documentation>
+ </xsd:annotation>
+
+ <xsd:element name="purchaseOrder" type="xsd:int"/>
+
+ <xsd:element name="comment" type="xsd:string"/>
+</xsd:schema>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/IntegratedSite.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/IntegratedSite.xsd
new file mode 100644
index 0000000000..e211b313c2
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/IntegratedSite.xsd
@@ -0,0 +1,5238 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.ericsson.com/is/isco/IntegratedSite" xmlns="http://www.ericsson.com/is/isco/IntegratedSite" xmlns:nc="http://www.ericsson.com/is/isco/nc" xmlns:IsTypes="http://www.ericsson.com/is/isco/IsTypes" xmlns:MainSwitch="http://www.ericsson.com/is/isco/MainSwitch_1" xmlns:MyBsModel="http://www.ericsson.com/is/isco/MyBsModel_1">
+ <xsd:annotation>
+ <xsd:appinfo>
+ <mim file="bs_mim.xml" version=""/>
+ <mim file="cpd_mim.xml" version=""/>
+ <mim file="hwm_mim.xml" version=""/>
+ <mim file="swm_mim.xml" version=""/>
+ <mim file="top_mim.xml" version=""/>
+ </xsd:appinfo>
+ </xsd:annotation>
+ <xsd:import schemaLocation="nc.xsd" namespace="http://www.ericsson.com/is/isco/nc"/>
+ <xsd:import schemaLocation="IsTypes.xsd" namespace="http://www.ericsson.com/is/isco/IsTypes"/>
+ <xsd:import schemaLocation="MainSwitch_1.xsd" namespace="http://www.ericsson.com/is/isco/MainSwitch_1"/>
+ <xsd:import schemaLocation="MyBsModel_1.xsd" namespace="http://www.ericsson.com/is/isco/MyBsModel_1"/>
+ <xsd:complexType name="JobData">
+ <xsd:annotation>
+ <xsd:documentation>
+ Data to specify a jobs progress, status etc during its execution.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="jobDateOrdered">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType0">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="jobStatus" type="JobStatus"/>
+ <xsd:element name="jobResult" type="JobResult"/>
+ <xsd:element name="jobInfo">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="jobProgress" type="Unsigned32"/>
+ <xsd:element name="jobLaststep" type="Unsigned32"/>
+ <xsd:element name="jobProgressReport">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ <xsd:complexType name="BladeUgSpecification">
+ <xsd:annotation>
+ <xsd:documentation>
+ Specification of a blade when an upgrade job is ordered for a
+ specific blade. This data always belongs to and is included in
+ an upgrade job for a blade system.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="ixBladeSubrack" type="Unsigned32"/>
+ <xsd:element name="ixBladeSlot" type="Unsigned32"/>
+ <xsd:element name="bladeSwgProdnr">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="bladeSwgVersion">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ <xsd:complexType name="FTPData">
+ <xsd:annotation>
+ <xsd:documentation>
+ Data to specify FTP server info, such as host, user,
+ password and path, to locate correct files or destination
+ for files.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="host">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="user">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="password">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="path">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ <xsd:complexType name="HwmKnockOutType">
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType3">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="HwmOperationalStateType">
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType4">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="SwgStatus">
+ <xsd:annotation>
+ <xsd:documentation>
+ Indicates status of software groups. A software group is
+ complete if all included load module containers have been
+ downloaded and unpacked correctly. A software group is inconsistent
+ if the checksums of the load module containers do not match the
+ information in the system information CXP, or if the XML
+ data could not be registered.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType5">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="HwmBusTypeType">
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType6">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="Unsigned32">
+ <xsd:annotation>
+ <xsd:documentation>
+ Datatype for an integer according to SNMPv2 definition of
+ unsigned32.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType7">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="JobResult">
+ <xsd:annotation>
+ <xsd:documentation>
+ Possible results of an action for a job.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType8">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="HwmAdministrativeStateType">
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType9">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="ContainerType">
+ <xsd:annotation>
+ <xsd:documentation>
+ Type of a load module container.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType10">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="MatchStrategy">
+ <xsd:annotation>
+ <xsd:documentation>
+ Interpretation of given filename and path.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType11">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="DownloadStrategy">
+ <xsd:annotation>
+ <xsd:documentation>
+ Interpretation according to existing files.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType12">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="JobStatus">
+ <xsd:annotation>
+ <xsd:documentation>
+ Indicator of job status.
+ A job should be started immediately, but could be postponed
+ if the total load on the system would become too high.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType13">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="HwmAvailabilityStatusType">
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType14">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="HwmSlotStateType">
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType15">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:element name="model">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="Is" minOccurs="0" maxOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation>
+ The top class - the forefather of all classes.
+
+ Key attributes: []
+
+ Possible children:
+ Hardware
+ Software
+ NetworkConfiguration
+ BladeSystems
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="Hardware" minOccurs="0" maxOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation>
+ Functional area Hardware Management
+
+ Key attributes: []
+
+ Possible children:
+ BladeType
+ Subrack
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="BladeType" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class describes a Blade.
+
+ Key attributes: [key]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="key">
+ <xsd:annotation>
+ <xsd:documentation>
+ The blade type number like CNA12801
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ The name of the Blade Type.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="width">
+ <xsd:annotation>
+ <xsd:documentation>
+ The width of the blade in number of slots.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="oneGLinks">
+ <xsd:annotation>
+ <xsd:documentation>
+ The 1G links used by the blade type , like 0,1, counted from
+ the leftmost backplane position.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="linkAggregates">
+ <xsd:annotation>
+ <xsd:documentation>
+ The 1G links used for link aggregation by the blade type , like 0-1,
+ counted from the leftmost backplane position.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="hasHwData">
+ <xsd:annotation>
+ <xsd:documentation>
+ True if possible to read product info via the maintenance bus.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isMxb">
+ <xsd:annotation>
+ <xsd:documentation>
+ True if this is a Main Switch blade type.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="availOneGSlots">
+ <xsd:annotation>
+ <xsd:documentation>
+ Only valid for main switch blades. A list of slots that have 1G link.
+ Could be a single slot or a range or a combination thereof.
+ E.g. 1-24, or 1,3-13,15-24.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="aggregateRanges">
+ <xsd:annotation>
+ <xsd:documentation>
+ Only valid for main switch blades. Specifies which slots can be used
+ for link aggregation. Ranges are specified in the form 1-12,13-24.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Subrack" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class describes the subrack.
+
+ Key attributes: [id]
+
+ Possible children:
+ Slot
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="id">
+ <xsd:annotation>
+ <xsd:documentation>
+ Identifies a certain subrack.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType16">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="type">
+ <xsd:annotation>
+ <xsd:documentation>
+ The type of subrack.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="userLabel">
+ <xsd:annotation>
+ <xsd:documentation>
+ A user friendly Subrack name.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="position">
+ <xsd:annotation>
+ <xsd:documentation>
+ The subrack position in the cabinet.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="cabinetPosition">
+ <xsd:annotation>
+ <xsd:documentation>
+ The cabinet position in the site.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="location">
+ <xsd:annotation>
+ <xsd:documentation>
+ The site location, e.g. the visiting address.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="availableOneGSlots">
+ <xsd:annotation>
+ <xsd:documentation>
+ Available slots for 1G switch links. Information taken from the type
+ of main switch blade that is created in the subrack.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="availableTenGSlots">
+ <xsd:annotation>
+ <xsd:documentation>
+ Available slots for 10G switch links. Information taken from the type
+ of main switch blade that is created in the subrack.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="aggregateSlots">
+ <xsd:annotation>
+ <xsd:documentation>
+ Links ranges for (1G) link aggregation. Information taken from the
+ type of main switch blade that is created in the subrack.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Slot" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ This table corresponds to slots, there is one row in the table
+ for each slot. The slots are grouped per subrack. A slot is
+ identified by subrack Id and slot number). The subrack Id for a slot
+ identifies in the subrackTable the subrack that the slot belongs
+ to.
+
+ Key attributes: [number]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="number">
+ <xsd:annotation>
+ <xsd:documentation>
+ The value of this object identifies the
+ slot position within the subrack.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType17">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="state" type="HwmSlotStateType">
+ <xsd:annotation>
+ <xsd:documentation>
+ See HwmSlotStateType description.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bladeSystem">
+ <xsd:annotation>
+ <xsd:documentation>
+ The value of this object identifies the Blade System that uses this
+ slot. An instances of this object will only have meaning in a
+ conceptual row if the value of hemSlotState instance is either
+ usedOccupied or usedEmpty in the same conceptual row,
+ i.e. there is an Blade System created using this slot. (If
+ no Blade System is using the slot, the value will be -1.)
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Software" minOccurs="0" maxOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation>
+ Top class of structure for SWM MOM.
+
+ Key attributes: []
+
+ Possible children:
+ Inventory
+ Jobs
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="Inventory" minOccurs="0" maxOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation>
+ Subclass to top class Software. Parent of
+ Inventory classes:
+ SoftwareDeliveryPackage,
+ SoftwareGroup,
+ LocalBackup,
+ Alarm.
+ Inventory actions:
+ DownloadFile
+ ImportBackup
+ Only system created data for info and overview,
+ sometimes as a result of an action called by the
+ operator.
+
+ Key attributes: []
+
+ Possible children:
+ Alarm
+ LocalBackup
+ SoftwareDeliveryPackage
+ SoftwareGroup
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="Alarm" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ MO of all alarms logged in the system that has not been
+ taken care of in a satisfactory way.
+
+ Key attributes: [alarmId]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="alarmId" type="Unsigned32"/>
+ <xsd:element minOccurs="0" name="faultyBladeSystem">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="faultCause">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="faultInfo">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="LocalBackup" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ All available backups locally stored.
+
+ Key attributes: [localBackupId]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="localBackupId" type="Unsigned32"/>
+ <xsd:element minOccurs="0" name="name">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bladeSystem">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="date">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType0">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="size" type="Unsigned32"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="SoftwareDeliveryPackage" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ MO for info about LoadModuleContainers, ie CXPs.
+
+ Key attributes: [ixProdNr,ixVersion]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="ixProdNr">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ixVersion">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="name">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="type" type="ContainerType"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="SoftwareGroup" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class reference to multiple MOs of class
+ SoftwareDeliveryPackage, ie the relationship between
+ CXPs and CXS.
+
+ Key attributes: [ixProdnr,ixVersion]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="ixProdnr">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ixVersion">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="name">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="systemProdNr">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="systemVersion">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="systemName">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="integratedSystemProdNr">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="integratedSystemVersion">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="integratedSystemName">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="relatedCXPs">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType18">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="status" type="SwgStatus"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Jobs" minOccurs="0" maxOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation>
+ Subclass to top class Software. Parent of
+ Jobs classes:
+ DownloadFile,
+ Upgrade,
+ Backup.
+ System created data through ordered job actions.
+
+ Key attributes: []
+
+ Possible children:
+ Backup
+ DownloadFile
+ Upgrade
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="Backup" minOccurs="0" maxOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation>
+ Subclass to class Jobs. Parent of
+ Jobs classes:
+ Create,
+ Restore
+ Import,
+ Export.System created data through ordered backup job actions.
+
+ Key attributes: []
+
+ Possible children:
+ Create
+ Export
+ Import
+ Restore
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="Create" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ This MO handles creation of backups of the system.
+
+ Key attributes: [backupJobId]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="backupJobId">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="jobData" type="JobData"/>
+ <xsd:element minOccurs="0" name="backupId" type="Unsigned32"/>
+ <xsd:element minOccurs="0" name="targetBladeSystem">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="backupName">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Export" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ This MO handles export of locally stored backup files to
+ the FTP server.
+
+ Key attributes: [exportJobId]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="exportJobId">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="jobData" type="JobData"/>
+ <xsd:element minOccurs="0" name="ftpData" type="FTPData"/>
+ <xsd:element minOccurs="0" name="backupId" type="Unsigned32"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Import" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ This MO handles import of backup files from the FTP server.
+ The backup file is stored locally, but not loaded into the system.
+
+ Key attributes: [importJobId]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="importJobId">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="jobData" type="JobData"/>
+ <xsd:element minOccurs="0" name="ftpData" type="FTPData"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Restore" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ This MO handles restore of backups of the system.
+
+ Key attributes: [restoreJobId]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="restoreJobId">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="jobData" type="JobData"/>
+ <xsd:element minOccurs="0" name="backupId" type="Unsigned32"/>
+ <xsd:element minOccurs="0" name="targetBladeSystem">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="backupName">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="DownloadFile" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ This MO contains information about requested, ongoing,
+ and completed software file download jobs. To start a
+ download job the operator calls an action Inventory class,
+ and a new instance of this MO is created.
+ For load regulating reasons a requested job may not start
+ immediately.
+
+ Key attributes: [downloadFileJobId]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="downloadFileJobId">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="jobData" type="JobData"/>
+ <xsd:element minOccurs="0" name="ftpData" type="FTPData"/>
+ <xsd:element minOccurs="0" name="matchStrategy" type="MatchStrategy"/>
+ <xsd:element minOccurs="0" name="downloadStrategy" type="DownloadStrategy"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Upgrade" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ This MO handles upgrade jobs towards the system. The operator
+ may specify a specific blade to run the upgrade on, instead of
+ running an upgrade on the entire blade system.
+
+ Key attributes: [upgradeJobId]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="upgradeJobId">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="jobData" type="JobData"/>
+ <xsd:element minOccurs="0" name="bladeSystem">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="selectedSwgProdNr">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="selectedSwgVersion">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="selectedCxrProdNr">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="selectedCxrVersion">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="MaxTime" type="Unsigned32">
+ <xsd:annotation>
+ <xsd:documentation>
+ The maximum time allowed for the SW Upgrade
+ job to finish. After this time, the job will be interrupted.
+ The value 0 means that MaxTime will be given the
+ timer value registered with the Blade System Software Group
+ Version. If no such value has been registered,
+ MaxTime will be given a system default timer value.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bladeUgSpecification" type="BladeUgSpecification"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="NetworkConfiguration" minOccurs="0" maxOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation>
+ The MO branch where the common Network resources are configured.
+
+ Key attributes: []
+
+ Possible children:
+ IsIpTrafficClass
+ IsLanTrafficClass
+ IsLogicalNetwork
+ IsVariables
+ IsVlan
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="IsIpTrafficClass" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ Key attributes: [name]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name if the IS IP Traffic Class.
+ Unique within the entire Integrated Site.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the IS IP Traffic Class.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="dscp">
+ <xsd:annotation>
+ <xsd:documentation>
+ DiffServ Code Point setting for this IS IP Traffic Class.
+ If there are two IS Ip Traffic Classes with the same DSCP, they
+ both must refer to an IS Lan Traffic Class with identical P-bit setting.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isLanTrafficClass">
+ <xsd:annotation>
+ <xsd:documentation>
+ Reference to a Managed Object of type ISLanTrafficClass.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType19">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="IsLanTrafficClass" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ An IS Lan Traffic Class may be shared between several Blade Systems.
+
+ Key attributes: [name]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name of the IS Lan Traffic Class.
+ Unique within the entire Integrated Site.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the IS Lan Traffic Class.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="pbits">
+ <xsd:annotation>
+ <xsd:documentation>
+ P-bit setting for this IS Lan Traffic Class.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType20">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="IsLogicalNetwork" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ An IS Logical Network contains one or more IS Subnets.
+ It may be shared between several Blade Systems.
+
+ Key attributes: [name]
+
+ Possible children:
+ IsSubnet
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name of the IS Logical Network.
+ Unique within the entire Integrated Site.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the IS logical network.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="IsSubnet" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ An IS Subnet contains one or more IS Subnet Segments.
+ It may be shared between several Blade Systems.
+
+ Key attributes: [name]
+
+ Possible children:
+ IsSubnetSegment
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name of the IS Subnet. Unique within the IS Logical Network.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the IS Subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="address" type="IsTypes:IpAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ IP network address of the IS Subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="mask">
+ <xsd:annotation>
+ <xsd:documentation>
+ Prefix length of the IP network address.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType21">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="broadcastAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ Broadcast address of the IS Subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isVlanId">
+ <xsd:annotation>
+ <xsd:documentation>
+ Identity of an IS VLAN.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="IsSubnetSegment" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ An IS Subnet Segment may be shared between several Blade Systems.
+
+ Key attributes: [name]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name of the IS Subnet Segment. Unique within the IS Subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the IS Subnet Segment.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="address" type="IsTypes:IpAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ IP network address of the IS Subnet Segment.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="mask">
+ <xsd:annotation>
+ <xsd:documentation>
+ Prefix length of the IP network address.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType21">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="routerAddress" type="IsTypes:IpAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ Router address for the IS Subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="dhcpEnabled">
+ <xsd:annotation>
+ <xsd:documentation>
+ Flag that controls wheter DHCP should be enabled or not for this
+ IS Subnet Segment.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="IsVariables" minOccurs="0" maxOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation>
+ Key attributes: []
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element minOccurs="0" name="updateMode">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType22">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="dataModelVersion">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="major">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="minor">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="rlspMarkerGenerateInterval">
+ <xsd:annotation>
+ <xsd:documentation>
+ The RLSP marker generate interval in microseconds.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType7">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="timezoneDstRule">
+ <xsd:annotation>
+ <xsd:documentation>
+ Daylight savings rule in posix standard format.
+ Better description to be supplied later........and a regular expression
+ which describes the valid string format.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="dnsDomain">
+ <xsd:annotation>
+ <xsd:documentation>
+ The dns domain used by IS in the DNS-server.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType23">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="notifyAfter">
+ <xsd:annotation>
+ <xsd:documentation>
+ Number of seconds from that a new network configuration has been
+ published until the Blade Systems will apply the changes.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="defaultDhcpLeaseTime">
+ <xsd:annotation>
+ <xsd:documentation>
+ The default DHCP Lease time in seconds.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="lifeTimeDhcpLeaseTime">
+ <xsd:annotation>
+ <xsd:documentation>
+ The lifetime of a DHCP lease in seconds.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="IsVlan" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ An IS Vlan may be shared between several Blade Systems.
+
+ Key attributes: [identity]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="identity">
+ <xsd:annotation>
+ <xsd:documentation>
+ Identity of the IS Vlan. Unique within the entire Integrated Site.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType24">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the IS Vlan.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BladeSystems" minOccurs="0" maxOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation>
+ The BladeSystems mountpoint - parent of all blade systems.
+
+ Key attributes: []
+
+ Possible children:
+ BladeSystemTemplate
+ Mxb
+ MyBsModel
+ Sis
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="Mxb" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class describes a Blade System. It will be cloned for each
+ new blade system type registered in the system. The new clone
+ will serve as a mountpoint for the blade system specific model.
+
+ Key attributes: [name]
+
+ Possible children:
+ Blade
+ BsIpTrafficClass
+ BsLanTrafficClass
+ BsLogicalNetwork
+ BsVlan
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ A user friendly Blade System name, must be set at creation and can be
+ changed when BS is locked.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="no">
+ <xsd:annotation>
+ <xsd:documentation>
+ An identifier for the BS. A new integer has to be used every time a new
+ BS is created. ??? Kvar ???
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="softwareGroupId">
+ <xsd:annotation>
+ <xsd:documentation>
+ The identity of the Software Group (SWG) that the BS implements.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="softwareGroupRevision">
+ <xsd:annotation>
+ <xsd:documentation>
+ The revision of the Software Group (SWG) that the BS implements.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="admState" type="HwmAdministrativeStateType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The administrative state of the Blade System.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="opState" type="HwmOperationalStateType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The operational state of the Blade System.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="availStatus" type="HwmAvailabilityStatusType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The availability status of the Blade System.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="locked">
+ <xsd:annotation>
+ <xsd:documentation>
+ eller s�tta admState ????????????
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the Blade System.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bsomAddress" type="IsTypes:IpAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ IP address of the Blade System OaM Master.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="Blade" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class describes a Blade.
+ A Blade is identified by the subrack and slot number.
+
+ Key attributes: [subrackId,slotNo]
+
+ Possible children:
+ LinkSap
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="subrackId">
+ <xsd:annotation>
+ <xsd:documentation>
+ A reference to the associated subrack (i.e. the value of 'subrackId'
+ for the associated subrack)
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType16">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="slotNo">
+ <xsd:annotation>
+ <xsd:documentation>
+ The slot number for this Blade within the subrack.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType17">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="slotLabel">
+ <xsd:annotation>
+ <xsd:documentation>
+ The slot label of the blade. Will only be set at creation of table row.
+ This should be used in alarms related to the slot to inform the
+ operator of what position in the subrack the blade is located in.
+ E.g. for GEM subracks it will be a string like X02 for slot 0
+ up to X80 for slot 25.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bsNo">
+ <xsd:annotation>
+ <xsd:documentation>
+ An identifier for the BS to which the blade belongs.
+ A value of 0 means that the blade is inserted in the subrack but it
+ has not been configured to any BS yet.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="type">
+ <xsd:annotation>
+ <xsd:documentation>
+ The type of the Blade defined by a string BladTypeIdAndRev.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="swgLowestId">
+ <xsd:annotation>
+ <xsd:documentation>
+ The SW group of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="swgLowestRev">
+ <xsd:annotation>
+ <xsd:documentation>
+ The SW group of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="swgActualId">
+ <xsd:annotation>
+ <xsd:documentation>
+ The SW group of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="swgActualRev">
+ <xsd:annotation>
+ <xsd:documentation>
+ The SW group of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bsom">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="knockOutType" type="HwmKnockOutType">
+ <xsd:annotation>
+ <xsd:documentation>
+ Set to protected if blade sholud no be knocked out before the
+ switch blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="userLabel">
+ <xsd:annotation>
+ <xsd:documentation>
+ A user friendly Blade name, always possible to set.
+ Default value indicates HwmBladeType and used slot.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="admState" type="HwmAdministrativeStateType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The administrative state of the Blade. The Blade is
+ unblocked by setting this object to unlocked and blocked
+ by setting it to locked. If the object already has the
+ desired value or the hwmBladeOpState has a transient OpState value
+ the set operation will be rejected. The set operation may be
+ rejected due to other reasons as well.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="opState" type="HwmOperationalStateType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The operational state of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="availState" type="HwmAvailabilityStatusType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The availability status of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="busType" type="HwmBusTypeType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The type of maintenance bus on the found Blade
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="prodNo">
+ <xsd:annotation>
+ <xsd:documentation>
+ The Product Number of the found Blade
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="prodRev">
+ <xsd:annotation>
+ <xsd:documentation>
+ The Product Revision of the found Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="serialNo">
+ <xsd:annotation>
+ <xsd:documentation>
+ The Serial Number of the found Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="prodName">
+ <xsd:annotation>
+ <xsd:documentation>
+ The Product Name of the found Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="vendor">
+ <xsd:annotation>
+ <xsd:documentation>
+ The Vendor name of the found Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="mfgDate">
+ <xsd:annotation>
+ <xsd:documentation>
+ The manufacturing date of the found Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="macAddressAggregate" type="IsTypes:MacAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ The aggregated MAC address of the found Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="macAddressLeft" type="IsTypes:MacAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ The left link MAC address of the found Blade. Only used by some blades
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="macAddressRight" type="IsTypes:MacAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ The right link MAC address of the found Blade. Only used by some blades
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="changeDate">
+ <xsd:annotation>
+ <xsd:documentation>
+ The date when the blade was last changed.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="lock">
+ <xsd:annotation>
+ <xsd:documentation>
+ Borde kanske varfa en �ndring av admstate.????
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ The name of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isbsAddress" type="IsTypes:IpAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ IP address on the ISBS subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isobAddress" type="IsTypes:IpAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ IP address on the ISOB subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="islctAddress" type="IsTypes:IpAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ IP address on the ISLCT subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="LinkSap" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ A Blade may have one or more resilient interfaces to the backplane. Such
+ interface is called Link Service Access Point and are automatically
+ created and deleted along with the hosting blade.
+
+ Key attributes: [id]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="id">
+ <xsd:annotation>
+ <xsd:documentation>
+ The id of a LinkSap is a number from 0 to X within the slot.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the Link Service Access Point.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsIpTrafficClass" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ Key attributes: [id]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="id">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isIpTrafficClassRef">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType25">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsLanTrafficClass" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ Key attributes: [id]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="id">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isLanTrafficClassRef">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType19">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsLogicalNetwork" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ Key attributes: [name]
+
+ Possible children:
+ BsSubnet
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name of the BS logical network. Unique within the Blade System.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the BS Logical Network.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="private">
+ <xsd:annotation>
+ <xsd:documentation>
+ Flag that shows whether the BS Logical Network is private for this
+ Blade System or if it may be shared among several Blade Systems.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isLogicalNetworkRef">
+ <xsd:annotation>
+ <xsd:documentation>
+ Reference to the corresponding IS Logical Network.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType26">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsSubnet" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ BS Subnets can either be created manually by the operator or they
+ can be automatically created from pre-registered network requirements
+ bundled with the Blade System software.
+ Regardless of how they are created,
+ each one needs to be mapped to both a BS VLan and an
+ IS Subnet before blades can be unlocked via the Hardware service.
+ Each BS Subnet contains one or more BS Subnet Segments.
+
+ Key attributes: [name]
+
+ Possible children:
+ BsSubnetSegment
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name of the BS Subnet. Unique within the BS Logical Network.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the BS Subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bsVlanRef">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType27">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isSubnetRef">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType28">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsSubnetSegment" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ BS Subnet Segments can either be created manually by you or they can
+ be automatically created from pre-registered network requirements
+ bundled with the Blade System software. Regardless of how they are created,
+ each one needs to be mapped to an IS Subnet Segment before the blades
+ can be unlocked via the Hardware service.
+ The mapping is done with the 'isSubnetSegmentRef' attribute.
+
+ Key attributes: [name]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name of the BS Subnet Segment. Unique within the BS Subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the BS Subnet Segment.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="numOfIpaddresses">
+ <xsd:annotation>
+ <xsd:documentation>
+ Number of required IP addresses in the IS Subnet Segment.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="dhcpEnabled">
+ <xsd:annotation>
+ <xsd:documentation>
+ Flag that controls whether the corresponding IS Subnet Segment is
+ required to have DHCP enabled or not.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="routerRequired">
+ <xsd:annotation>
+ <xsd:documentation>
+ Flag that controls whether the corresponding IS Subnet Segment is
+ required to have a router configured or not.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isSubnetSegmentRef">
+ <xsd:annotation>
+ <xsd:documentation>
+ The mapping to a corresponding IS Subnet Segment. The mapping here must
+ be done before the blades of the blade system can be unlocked.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType29">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsVlan" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ BS VLANs can either be created manually by the
+ operator or they can be automatically created from pre-registered
+ network requirements bundled with the Blade System software.
+ Regardless of how they are created, each one needs to be mapped to
+ an IS VLAN before the blades can be unlocked.
+
+ Key attributes: [name]
+
+ Possible children:
+ BsVlanSap
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name of the BS Vlan. Unique within the Blade System.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the BS Vlan.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isVlanRef">
+ <xsd:annotation>
+ <xsd:documentation>
+ The mapping to a corresponding IS Vlan. This mapping must be done before
+ the blades of the Blade System can be unlocked.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType30">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsVlanSap" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ BS VLAN Service Access Points can either be created manually by the
+ operator or they can be automatically created from pre-registered
+ network requirements bundled with the Blade System software.
+ Regardless of how they are created, each one needs to be mapped to
+ an Link SAP before the blades can be unlocked.
+
+ Key attributes: [name]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name of the BS VLAN SAP. Uniqie within the BS VLAN.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the BS VLAN SAP.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="static">
+ <xsd:annotation>
+ <xsd:documentation>
+ Flag which controls whether this BS VLAN SAP makes static or dynamic
+ use of the corresponding IS VLAN.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="protected">
+ <xsd:annotation>
+ <xsd:documentation>
+ Flag which controls whether this BS VLAN SAP should be
+ isolation protected or not.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="linkSapRef">
+ <xsd:annotation>
+ <xsd:documentation>
+ A mapping to the corresponding Link Service Access Point.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType31">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="MyBsModel" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class describes a Blade System. It will be cloned for each
+ new blade system type registered in the system. The new clone
+ will serve as a mountpoint for the blade system specific model.
+
+ Key attributes: [name]
+
+ Possible children:
+ Blade
+ BsIpTrafficClass
+ BsLanTrafficClass
+ BsLogicalNetwork
+ BsVlan
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ A user friendly Blade System name, must be set at creation and can be
+ changed when BS is locked.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="no">
+ <xsd:annotation>
+ <xsd:documentation>
+ An identifier for the BS. A new integer has to be used every time a new
+ BS is created. ??? Kvar ???
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="softwareGroupId">
+ <xsd:annotation>
+ <xsd:documentation>
+ The identity of the Software Group (SWG) that the BS implements.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="softwareGroupRevision">
+ <xsd:annotation>
+ <xsd:documentation>
+ The revision of the Software Group (SWG) that the BS implements.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="admState" type="HwmAdministrativeStateType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The administrative state of the Blade System.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="opState" type="HwmOperationalStateType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The operational state of the Blade System.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="availStatus" type="HwmAvailabilityStatusType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The availability status of the Blade System.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="locked">
+ <xsd:annotation>
+ <xsd:documentation>
+ eller s�tta admState ????????????
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the Blade System.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bsomAddress" type="IsTypes:IpAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ IP address of the Blade System OaM Master.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="Blade" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class describes a Blade.
+ A Blade is identified by the subrack and slot number.
+
+ Key attributes: [subrackId,slotNo]
+
+ Possible children:
+ LinkSap
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="subrackId">
+ <xsd:annotation>
+ <xsd:documentation>
+ A reference to the associated subrack (i.e. the value of 'subrackId'
+ for the associated subrack)
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType16">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="slotNo">
+ <xsd:annotation>
+ <xsd:documentation>
+ The slot number for this Blade within the subrack.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType17">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="slotLabel">
+ <xsd:annotation>
+ <xsd:documentation>
+ The slot label of the blade. Will only be set at creation of table row.
+ This should be used in alarms related to the slot to inform the
+ operator of what position in the subrack the blade is located in.
+ E.g. for GEM subracks it will be a string like X02 for slot 0
+ up to X80 for slot 25.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bsNo">
+ <xsd:annotation>
+ <xsd:documentation>
+ An identifier for the BS to which the blade belongs.
+ A value of 0 means that the blade is inserted in the subrack but it
+ has not been configured to any BS yet.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="type">
+ <xsd:annotation>
+ <xsd:documentation>
+ The type of the Blade defined by a string BladTypeIdAndRev.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="swgLowestId">
+ <xsd:annotation>
+ <xsd:documentation>
+ The SW group of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="swgLowestRev">
+ <xsd:annotation>
+ <xsd:documentation>
+ The SW group of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="swgActualId">
+ <xsd:annotation>
+ <xsd:documentation>
+ The SW group of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="swgActualRev">
+ <xsd:annotation>
+ <xsd:documentation>
+ The SW group of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bsom">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="knockOutType" type="HwmKnockOutType">
+ <xsd:annotation>
+ <xsd:documentation>
+ Set to protected if blade sholud no be knocked out before the
+ switch blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="userLabel">
+ <xsd:annotation>
+ <xsd:documentation>
+ A user friendly Blade name, always possible to set.
+ Default value indicates HwmBladeType and used slot.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="admState" type="HwmAdministrativeStateType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The administrative state of the Blade. The Blade is
+ unblocked by setting this object to unlocked and blocked
+ by setting it to locked. If the object already has the
+ desired value or the hwmBladeOpState has a transient OpState value
+ the set operation will be rejected. The set operation may be
+ rejected due to other reasons as well.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="opState" type="HwmOperationalStateType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The operational state of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="availState" type="HwmAvailabilityStatusType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The availability status of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="busType" type="HwmBusTypeType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The type of maintenance bus on the found Blade
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="prodNo">
+ <xsd:annotation>
+ <xsd:documentation>
+ The Product Number of the found Blade
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="prodRev">
+ <xsd:annotation>
+ <xsd:documentation>
+ The Product Revision of the found Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="serialNo">
+ <xsd:annotation>
+ <xsd:documentation>
+ The Serial Number of the found Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="prodName">
+ <xsd:annotation>
+ <xsd:documentation>
+ The Product Name of the found Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="vendor">
+ <xsd:annotation>
+ <xsd:documentation>
+ The Vendor name of the found Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="mfgDate">
+ <xsd:annotation>
+ <xsd:documentation>
+ The manufacturing date of the found Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="macAddressAggregate" type="IsTypes:MacAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ The aggregated MAC address of the found Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="macAddressLeft" type="IsTypes:MacAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ The left link MAC address of the found Blade. Only used by some blades
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="macAddressRight" type="IsTypes:MacAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ The right link MAC address of the found Blade. Only used by some blades
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="changeDate">
+ <xsd:annotation>
+ <xsd:documentation>
+ The date when the blade was last changed.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="lock">
+ <xsd:annotation>
+ <xsd:documentation>
+ Borde kanske varfa en �ndring av admstate.????
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ The name of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isbsAddress" type="IsTypes:IpAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ IP address on the ISBS subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isobAddress" type="IsTypes:IpAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ IP address on the ISOB subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="islctAddress" type="IsTypes:IpAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ IP address on the ISLCT subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="LinkSap" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ A Blade may have one or more resilient interfaces to the backplane. Such
+ interface is called Link Service Access Point and are automatically
+ created and deleted along with the hosting blade.
+
+ Key attributes: [id]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="id">
+ <xsd:annotation>
+ <xsd:documentation>
+ The id of a LinkSap is a number from 0 to X within the slot.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the Link Service Access Point.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsIpTrafficClass" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ Key attributes: [id]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="id">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isIpTrafficClassRef">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType25">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsLanTrafficClass" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ Key attributes: [id]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="id">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isLanTrafficClassRef">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType19">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsLogicalNetwork" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ Key attributes: [name]
+
+ Possible children:
+ BsSubnet
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name of the BS logical network. Unique within the Blade System.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the BS Logical Network.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="private">
+ <xsd:annotation>
+ <xsd:documentation>
+ Flag that shows whether the BS Logical Network is private for this
+ Blade System or if it may be shared among several Blade Systems.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isLogicalNetworkRef">
+ <xsd:annotation>
+ <xsd:documentation>
+ Reference to the corresponding IS Logical Network.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType26">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsSubnet" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ BS Subnets can either be created manually by the operator or they
+ can be automatically created from pre-registered network requirements
+ bundled with the Blade System software.
+ Regardless of how they are created,
+ each one needs to be mapped to both a BS VLan and an
+ IS Subnet before blades can be unlocked via the Hardware service.
+ Each BS Subnet contains one or more BS Subnet Segments.
+
+ Key attributes: [name]
+
+ Possible children:
+ BsSubnetSegment
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name of the BS Subnet. Unique within the BS Logical Network.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the BS Subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bsVlanRef">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType27">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isSubnetRef">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType28">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsSubnetSegment" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ BS Subnet Segments can either be created manually by you or they can
+ be automatically created from pre-registered network requirements
+ bundled with the Blade System software. Regardless of how they are created,
+ each one needs to be mapped to an IS Subnet Segment before the blades
+ can be unlocked via the Hardware service.
+ The mapping is done with the 'isSubnetSegmentRef' attribute.
+
+ Key attributes: [name]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name of the BS Subnet Segment. Unique within the BS Subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the BS Subnet Segment.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="numOfIpaddresses">
+ <xsd:annotation>
+ <xsd:documentation>
+ Number of required IP addresses in the IS Subnet Segment.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="dhcpEnabled">
+ <xsd:annotation>
+ <xsd:documentation>
+ Flag that controls whether the corresponding IS Subnet Segment is
+ required to have DHCP enabled or not.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="routerRequired">
+ <xsd:annotation>
+ <xsd:documentation>
+ Flag that controls whether the corresponding IS Subnet Segment is
+ required to have a router configured or not.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isSubnetSegmentRef">
+ <xsd:annotation>
+ <xsd:documentation>
+ The mapping to a corresponding IS Subnet Segment. The mapping here must
+ be done before the blades of the blade system can be unlocked.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType29">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsVlan" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ BS VLANs can either be created manually by the
+ operator or they can be automatically created from pre-registered
+ network requirements bundled with the Blade System software.
+ Regardless of how they are created, each one needs to be mapped to
+ an IS VLAN before the blades can be unlocked.
+
+ Key attributes: [name]
+
+ Possible children:
+ BsVlanSap
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name of the BS Vlan. Unique within the Blade System.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the BS Vlan.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isVlanRef">
+ <xsd:annotation>
+ <xsd:documentation>
+ The mapping to a corresponding IS Vlan. This mapping must be done before
+ the blades of the Blade System can be unlocked.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType30">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsVlanSap" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ BS VLAN Service Access Points can either be created manually by the
+ operator or they can be automatically created from pre-registered
+ network requirements bundled with the Blade System software.
+ Regardless of how they are created, each one needs to be mapped to
+ an Link SAP before the blades can be unlocked.
+
+ Key attributes: [name]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name of the BS VLAN SAP. Uniqie within the BS VLAN.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the BS VLAN SAP.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="static">
+ <xsd:annotation>
+ <xsd:documentation>
+ Flag which controls whether this BS VLAN SAP makes static or dynamic
+ use of the corresponding IS VLAN.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="protected">
+ <xsd:annotation>
+ <xsd:documentation>
+ Flag which controls whether this BS VLAN SAP should be
+ isolation protected or not.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="linkSapRef">
+ <xsd:annotation>
+ <xsd:documentation>
+ A mapping to the corresponding Link Service Access Point.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType31">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element ref="MyBsModel:model" minOccurs="0" maxOccurs="1"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Sis" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class describes a Blade System. It will be cloned for each
+ new blade system type registered in the system. The new clone
+ will serve as a mountpoint for the blade system specific model.
+
+ Key attributes: [name]
+
+ Possible children:
+ Blade
+ BsIpTrafficClass
+ BsLanTrafficClass
+ BsLogicalNetwork
+ BsVlan
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ A user friendly Blade System name, must be set at creation and can be
+ changed when BS is locked.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="no">
+ <xsd:annotation>
+ <xsd:documentation>
+ An identifier for the BS. A new integer has to be used every time a new
+ BS is created. ??? Kvar ???
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="softwareGroupId">
+ <xsd:annotation>
+ <xsd:documentation>
+ The identity of the Software Group (SWG) that the BS implements.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="softwareGroupRevision">
+ <xsd:annotation>
+ <xsd:documentation>
+ The revision of the Software Group (SWG) that the BS implements.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="admState" type="HwmAdministrativeStateType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The administrative state of the Blade System.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="opState" type="HwmOperationalStateType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The operational state of the Blade System.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="availStatus" type="HwmAvailabilityStatusType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The availability status of the Blade System.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="locked">
+ <xsd:annotation>
+ <xsd:documentation>
+ eller s�tta admState ????????????
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the Blade System.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bsomAddress" type="IsTypes:IpAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ IP address of the Blade System OaM Master.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="Blade" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class describes a Blade.
+ A Blade is identified by the subrack and slot number.
+
+ Key attributes: [subrackId,slotNo]
+
+ Possible children:
+ LinkSap
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="subrackId">
+ <xsd:annotation>
+ <xsd:documentation>
+ A reference to the associated subrack (i.e. the value of 'subrackId'
+ for the associated subrack)
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType16">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="slotNo">
+ <xsd:annotation>
+ <xsd:documentation>
+ The slot number for this Blade within the subrack.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType17">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="slotLabel">
+ <xsd:annotation>
+ <xsd:documentation>
+ The slot label of the blade. Will only be set at creation of table row.
+ This should be used in alarms related to the slot to inform the
+ operator of what position in the subrack the blade is located in.
+ E.g. for GEM subracks it will be a string like X02 for slot 0
+ up to X80 for slot 25.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bsNo">
+ <xsd:annotation>
+ <xsd:documentation>
+ An identifier for the BS to which the blade belongs.
+ A value of 0 means that the blade is inserted in the subrack but it
+ has not been configured to any BS yet.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="type">
+ <xsd:annotation>
+ <xsd:documentation>
+ The type of the Blade defined by a string BladTypeIdAndRev.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="swgLowestId">
+ <xsd:annotation>
+ <xsd:documentation>
+ The SW group of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="swgLowestRev">
+ <xsd:annotation>
+ <xsd:documentation>
+ The SW group of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="swgActualId">
+ <xsd:annotation>
+ <xsd:documentation>
+ The SW group of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="swgActualRev">
+ <xsd:annotation>
+ <xsd:documentation>
+ The SW group of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bsom">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="knockOutType" type="HwmKnockOutType">
+ <xsd:annotation>
+ <xsd:documentation>
+ Set to protected if blade sholud no be knocked out before the
+ switch blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="userLabel">
+ <xsd:annotation>
+ <xsd:documentation>
+ A user friendly Blade name, always possible to set.
+ Default value indicates HwmBladeType and used slot.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="admState" type="HwmAdministrativeStateType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The administrative state of the Blade. The Blade is
+ unblocked by setting this object to unlocked and blocked
+ by setting it to locked. If the object already has the
+ desired value or the hwmBladeOpState has a transient OpState value
+ the set operation will be rejected. The set operation may be
+ rejected due to other reasons as well.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="opState" type="HwmOperationalStateType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The operational state of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="availState" type="HwmAvailabilityStatusType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The availability status of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="busType" type="HwmBusTypeType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The type of maintenance bus on the found Blade
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="prodNo">
+ <xsd:annotation>
+ <xsd:documentation>
+ The Product Number of the found Blade
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="prodRev">
+ <xsd:annotation>
+ <xsd:documentation>
+ The Product Revision of the found Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="serialNo">
+ <xsd:annotation>
+ <xsd:documentation>
+ The Serial Number of the found Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="prodName">
+ <xsd:annotation>
+ <xsd:documentation>
+ The Product Name of the found Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="vendor">
+ <xsd:annotation>
+ <xsd:documentation>
+ The Vendor name of the found Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="mfgDate">
+ <xsd:annotation>
+ <xsd:documentation>
+ The manufacturing date of the found Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="macAddressAggregate" type="IsTypes:MacAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ The aggregated MAC address of the found Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="macAddressLeft" type="IsTypes:MacAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ The left link MAC address of the found Blade. Only used by some blades
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="macAddressRight" type="IsTypes:MacAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ The right link MAC address of the found Blade. Only used by some blades
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="changeDate">
+ <xsd:annotation>
+ <xsd:documentation>
+ The date when the blade was last changed.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="lock">
+ <xsd:annotation>
+ <xsd:documentation>
+ Borde kanske varfa en �ndring av admstate.????
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ The name of the Blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the blade.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isbsAddress" type="IsTypes:IpAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ IP address on the ISBS subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isobAddress" type="IsTypes:IpAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ IP address on the ISOB subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="islctAddress" type="IsTypes:IpAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ IP address on the ISLCT subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="LinkSap" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ A Blade may have one or more resilient interfaces to the backplane. Such
+ interface is called Link Service Access Point and are automatically
+ created and deleted along with the hosting blade.
+
+ Key attributes: [id]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="id">
+ <xsd:annotation>
+ <xsd:documentation>
+ The id of a LinkSap is a number from 0 to X within the slot.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the Link Service Access Point.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsIpTrafficClass" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ Key attributes: [id]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="id">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isIpTrafficClassRef">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType25">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsLanTrafficClass" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ Key attributes: [id]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="id">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isLanTrafficClassRef">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType19">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsLogicalNetwork" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ Key attributes: [name]
+
+ Possible children:
+ BsSubnet
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name of the BS logical network. Unique within the Blade System.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the BS Logical Network.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="private">
+ <xsd:annotation>
+ <xsd:documentation>
+ Flag that shows whether the BS Logical Network is private for this
+ Blade System or if it may be shared among several Blade Systems.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isLogicalNetworkRef">
+ <xsd:annotation>
+ <xsd:documentation>
+ Reference to the corresponding IS Logical Network.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType26">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsSubnet" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ BS Subnets can either be created manually by the operator or they
+ can be automatically created from pre-registered network requirements
+ bundled with the Blade System software.
+ Regardless of how they are created,
+ each one needs to be mapped to both a BS VLan and an
+ IS Subnet before blades can be unlocked via the Hardware service.
+ Each BS Subnet contains one or more BS Subnet Segments.
+
+ Key attributes: [name]
+
+ Possible children:
+ BsSubnetSegment
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name of the BS Subnet. Unique within the BS Logical Network.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the BS Subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bsVlanRef">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType27">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isSubnetRef">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType28">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsSubnetSegment" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ BS Subnet Segments can either be created manually by you or they can
+ be automatically created from pre-registered network requirements
+ bundled with the Blade System software. Regardless of how they are created,
+ each one needs to be mapped to an IS Subnet Segment before the blades
+ can be unlocked via the Hardware service.
+ The mapping is done with the 'isSubnetSegmentRef' attribute.
+
+ Key attributes: [name]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name of the BS Subnet Segment. Unique within the BS Subnet.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the BS Subnet Segment.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="numOfIpaddresses">
+ <xsd:annotation>
+ <xsd:documentation>
+ Number of required IP addresses in the IS Subnet Segment.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="dhcpEnabled">
+ <xsd:annotation>
+ <xsd:documentation>
+ Flag that controls whether the corresponding IS Subnet Segment is
+ required to have DHCP enabled or not.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="routerRequired">
+ <xsd:annotation>
+ <xsd:documentation>
+ Flag that controls whether the corresponding IS Subnet Segment is
+ required to have a router configured or not.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isSubnetSegmentRef">
+ <xsd:annotation>
+ <xsd:documentation>
+ The mapping to a corresponding IS Subnet Segment. The mapping here must
+ be done before the blades of the blade system can be unlocked.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType29">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsVlan" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ BS VLANs can either be created manually by the
+ operator or they can be automatically created from pre-registered
+ network requirements bundled with the Blade System software.
+ Regardless of how they are created, each one needs to be mapped to
+ an IS VLAN before the blades can be unlocked.
+
+ Key attributes: [name]
+
+ Possible children:
+ BsVlanSap
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name of the BS Vlan. Unique within the Blade System.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the BS Vlan.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="isVlanRef">
+ <xsd:annotation>
+ <xsd:documentation>
+ The mapping to a corresponding IS Vlan. This mapping must be done before
+ the blades of the Blade System can be unlocked.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType30">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="BsVlanSap" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ BS VLAN Service Access Points can either be created manually by the
+ operator or they can be automatically created from pre-registered
+ network requirements bundled with the Blade System software.
+ Regardless of how they are created, each one needs to be mapped to
+ an Link SAP before the blades can be unlocked.
+
+ Key attributes: [name]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name">
+ <xsd:annotation>
+ <xsd:documentation>
+ Name of the BS VLAN SAP. Uniqie within the BS VLAN.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Short description of the BS VLAN SAP.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="static">
+ <xsd:annotation>
+ <xsd:documentation>
+ Flag which controls whether this BS VLAN SAP makes static or dynamic
+ use of the corresponding IS VLAN.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="protected">
+ <xsd:annotation>
+ <xsd:documentation>
+ Flag which controls whether this BS VLAN SAP should be
+ isolation protected or not.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="linkSapRef">
+ <xsd:annotation>
+ <xsd:documentation>
+ A mapping to the corresponding Link Service Access Point.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType31">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element ref="MainSwitch:model" minOccurs="0" maxOccurs="1"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:simpleType name="ccsHelperType31">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:pattern value="((/IntegratedSite:model/)|((\.\./)+)|((\./)(\.\./)*)|())((([A-Z][a-zA-Z0-9]+:model)|([A-Z][a-zA-Z0-9]+(\[[a-z][a-zA-Z0-9]*='[^\]]+'\])*))/)*LinkSap\[id='[^\]]+'\]"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType30">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:pattern value="((/IntegratedSite:model/)|((\.\./)+)|((\./)(\.\./)*)|())((([A-Z][a-zA-Z0-9]+:model)|([A-Z][a-zA-Z0-9]+(\[[a-z][a-zA-Z0-9]*='[^\]]+'\])*))/)*IsVlan\[identity='[^\]]+'\]"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType29">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:pattern value="((/IntegratedSite:model/)|((\.\./)+)|((\./)(\.\./)*)|())((([A-Z][a-zA-Z0-9]+:model)|([A-Z][a-zA-Z0-9]+(\[[a-z][a-zA-Z0-9]*='[^\]]+'\])*))/)*IsSubnetSegment\[name='[^\]]+'\]"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType28">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:pattern value="((/IntegratedSite:model/)|((\.\./)+)|((\./)(\.\./)*)|())((([A-Z][a-zA-Z0-9]+:model)|([A-Z][a-zA-Z0-9]+(\[[a-z][a-zA-Z0-9]*='[^\]]+'\])*))/)*IsSubnet\[name='[^\]]+'\]"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType27">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:pattern value="((/IntegratedSite:model/)|((\.\./)+)|((\./)(\.\./)*)|())((([A-Z][a-zA-Z0-9]+:model)|([A-Z][a-zA-Z0-9]+(\[[a-z][a-zA-Z0-9]*='[^\]]+'\])*))/)*BsVlan\[name='[^\]]+'\]"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType26">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:pattern value="((/IntegratedSite:model/)|((\.\./)+)|((\./)(\.\./)*)|())((([A-Z][a-zA-Z0-9]+:model)|([A-Z][a-zA-Z0-9]+(\[[a-z][a-zA-Z0-9]*='[^\]]+'\])*))/)*IsLogicalNetwork\[name='[^\]]+'\]"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType25">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:pattern value="((/IntegratedSite:model/)|((\.\./)+)|((\./)(\.\./)*)|())((([A-Z][a-zA-Z0-9]+:model)|([A-Z][a-zA-Z0-9]+(\[[a-z][a-zA-Z0-9]*='[^\]]+'\])*))/)*IsIpTrafficClass\[name='[^\]]+'\]"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType24">
+ <xsd:restriction base="xsd:integer">
+ <xsd:minInclusive value="0"/>
+ <xsd:maxInclusive value="4096"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType23">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:pattern value="[a-zA-Z]+(.[a-zA-Z])*"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType22">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="unsafe"/>
+ <xsd:enumeration value="readOnly"/>
+ <xsd:enumeration value="safe"/>
+ <xsd:enumeration value="preliminary"/>
+ <xsd:enumeration value="prepare"/>
+ <xsd:enumeration value="publish"/>
+ <xsd:enumeration value="accept"/>
+ <xsd:enumeration value="reject"/>
+ <xsd:enumeration value="purge"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType21">
+ <xsd:restriction base="xsd:integer">
+ <xsd:minInclusive value="0"/>
+ <xsd:maxInclusive value="32"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType20">
+ <xsd:restriction base="xsd:integer">
+ <xsd:minInclusive value="0"/>
+ <xsd:maxInclusive value="7"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType19">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:pattern value="((/IntegratedSite:model/)|((\.\./)+)|((\./)(\.\./)*)|())((([A-Z][a-zA-Z0-9]+:model)|([A-Z][a-zA-Z0-9]+(\[[a-z][a-zA-Z0-9]*='[^\]]+'\])*))/)*IsLanTrafficClass\[name='[^\]]+'\]"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType18">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:pattern value="((/IntegratedSite:model/)|((\.\./)+)|((\./)(\.\./)*)|())((([A-Z][a-zA-Z0-9]+:model)|([A-Z][a-zA-Z0-9]+(\[[a-z][a-zA-Z0-9]*='[^\]]+'\])*))/)*SoftwareDeliveryPackage\[ixProdNr='[^\]]+'\]\[ixVersion='[^\]]+'\]"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType17">
+ <xsd:restriction base="xsd:integer">
+ <xsd:minInclusive value="0"/>
+ <xsd:maxInclusive value="25"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType16">
+ <xsd:restriction base="xsd:integer">
+ <xsd:minInclusive value="0"/>
+ <xsd:maxInclusive value="31"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType15">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="unsuedEmpty"/>
+ <xsd:enumeration value="usedEmpty"/>
+ <xsd:enumeration value="unusedOccupied"/>
+ <xsd:enumeration value="usedOccupied"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType14">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="available"/>
+ <xsd:enumeration value="failed"/>
+ <xsd:enumeration value="offLine"/>
+ <xsd:enumeration value="dependency"/>
+ <xsd:enumeration value="degraded"/>
+ <xsd:enumeration value="upgrading"/>
+ <xsd:enumeration value="startingUp"/>
+ <xsd:enumeration value="goingOffLine"/>
+ <xsd:enumeration value="notInstalled"/>
+ <xsd:enumeration value="powerOff"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType13">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="notStarted"/>
+ <xsd:enumeration value="ongoing"/>
+ <xsd:enumeration value="complete"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType12">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="onlyIfMissing"/>
+ <xsd:enumeration value="always"/>
+ <xsd:enumeration value="unknown"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType11">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="exact"/>
+ <xsd:enumeration value="prefix"/>
+ <xsd:enumeration value="unknown"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType10">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="bladeSystemInformation"/>
+ <xsd:enumeration value="bladeInformation"/>
+ <xsd:enumeration value="application"/>
+ <xsd:enumeration value="rootFileSystem"/>
+ <xsd:enumeration value="kernel"/>
+ <xsd:enumeration value="correction"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType9">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="locked"/>
+ <xsd:enumeration value="shuttingdown"/>
+ <xsd:enumeration value="unlocked"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType8">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="ok"/>
+ <xsd:enumeration value="inputError"/>
+ <xsd:enumeration value="executionError"/>
+ <xsd:enumeration value="unknown"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType7">
+ <xsd:restriction base="xsd:integer">
+ <xsd:minInclusive value="0"/>
+ <xsd:maxInclusive value="4294967295"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType6">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="ipmi"/>
+ <xsd:enumeration value="mbus"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType5">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="complete"/>
+ <xsd:enumeration value="incomplete"/>
+ <xsd:enumeration value="inconsistent"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType4">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="disabled"/>
+ <xsd:enumeration value="enabled"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType3">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="normal"/>
+ <xsd:enumeration value="protected"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType2">
+ <xsd:restriction base="xsd:boolean">
+ <xsd:pattern value="(true|false)"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType1">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType0">
+ <xsd:restriction base="xsd:dateTime">
+ <xsd:whiteSpace value="collapse"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+</xsd:schema>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/IsTypes.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/IsTypes.xsd
new file mode 100644
index 0000000000..a9607e4253
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/IsTypes.xsd
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.ericsson.com/is/isco/IsTypes" xmlns="http://www.ericsson.com/is/isco/IsTypes" xmlns:nc="http://www.ericsson.com/is/isco/nc">
+ <xsd:annotation>
+ <xsd:appinfo>
+ <mim file="types_mim.xml" version=""/>
+ </xsd:appinfo>
+ </xsd:annotation>
+ <xsd:import schemaLocation="nc.xsd" namespace="http://www.ericsson.com/is/isco/nc"/>
+ <xsd:complexType name="IpAddress">
+ <xsd:annotation>
+ <xsd:documentation>
+ An IPv4 address
+ in the form v1.v2.v3.v4 where v1 ... v4 is a
+ decimal number in the range 0 to 255.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType0">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="MacAddress">
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:simpleType name="ccsHelperType1">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:pattern value="[A-F0-9][A-F0-9]?:[A-F0-9][A-F0-9]?:[A-F0-9][A-F0-9]?:[A-F0-9][A-F0-9]?:[A-F0-9][A-F0-9]?:[A-F0-9][A-F0-9]?"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType0">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:pattern value="(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+</xsd:schema>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/MainSwitch_1.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/MainSwitch_1.xsd
new file mode 100644
index 0000000000..9c91d6efd6
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/MainSwitch_1.xsd
@@ -0,0 +1,1496 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.ericsson.com/is/isco/MainSwitch_1" xmlns="http://www.ericsson.com/is/isco/MainSwitch_1" xmlns:nc="http://www.ericsson.com/is/isco/nc">
+ <xsd:annotation>
+ <xsd:appinfo>
+ <mim file="mx_mim.xml" version=""/>
+ </xsd:appinfo>
+ </xsd:annotation>
+ <xsd:import schemaLocation="nc.xsd" namespace="http://www.ericsson.com/is/isco/nc"/>
+ <xsd:complexType name="SubrackNum">
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType0">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="LinkAggregationData">
+ <xsd:annotation>
+ <xsd:documentation>
+ Description of Link Aggregation Data
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="aggrPortActorPort">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="aggrPortOperState">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="item" type="LinkAggregationOperStateData" minOccurs="8" maxOccurs="8"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ifIndex">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="mode">
+ <xsd:annotation>
+ <xsd:documentation>
+ Port Channel Mode
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="configuredPorts">
+ <xsd:annotation>
+ <xsd:documentation>
+ Number of configured ports for this interface.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="activePorts">
+ <xsd:annotation>
+ <xsd:documentation>
+ Number of active ports for this interface.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="macSelectionPolicy">
+ <xsd:annotation>
+ <xsd:documentation>
+ MAC Selection Policy
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="linkSelectionPolicy">
+ <xsd:annotation>
+ <xsd:documentation>
+ Link Selection Policy
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType3">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="aggregatorMac">
+ <xsd:annotation>
+ <xsd:documentation>
+ MAC address of Aggregator
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType4">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="actorId">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType4">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="actorPrio">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="actorAdminKey">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="actorOperKey">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="partnerId">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType4">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="partnerPrio">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="partnerOperKey">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ <xsd:complexType name="PercentUsage">
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType5">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="BladeSlotLink">
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType6">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="CosQueueConfigurationData">
+ <xsd:annotation>
+ <xsd:documentation>
+ Description of COS configuration data
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="queue">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType7">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="buffer" type="PercentUsage">
+ <xsd:annotation>
+ <xsd:documentation>
+ Indicates allocated buffer in percent
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="scheduling">
+ <xsd:annotation>
+ <xsd:documentation>
+ Indicates if Sceduling is Weighted Round Robin (WRR) or Strict Priority
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType8">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="weight">
+ <xsd:annotation>
+ <xsd:documentation>
+ Indicates if Weight in case of WRR is High, Medium or Low
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType9">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ <xsd:complexType name="VlanData">
+ <xsd:annotation>
+ <xsd:documentation>
+ This struct describes Vlan data
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="vlanId">
+ <xsd:annotation>
+ <xsd:documentation>
+ Vlan Id
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType10">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="vlanType">
+ <xsd:annotation>
+ <xsd:documentation>
+ Type of Vlan
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType11">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="isolationStatus">
+ <xsd:annotation>
+ <xsd:documentation>
+ Isolation status
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType12">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ <xsd:complexType name="StatisticCounter">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="PbitQueue">
+ <xsd:sequence>
+ <xsd:element name="pbitKey">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType7">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="queueValue">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType7">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ <xsd:complexType name="LinkAggregationOperStateData">
+ <xsd:annotation>
+ <xsd:documentation>
+ Description of Link Aggregation Oper State Data
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="lacpActivity">
+ <xsd:annotation>
+ <xsd:documentation>
+ Indicates LACP activity
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType13">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="lacpTimeout">
+ <xsd:annotation>
+ <xsd:documentation>
+ Indicates if LACP timeout is long or short
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType14">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="aggregation">
+ <xsd:annotation>
+ <xsd:documentation>
+ Indicates if Individual or Aggregatable
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType15">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="syncronization">
+ <xsd:annotation>
+ <xsd:documentation>
+ Indicates if Syncronized or not
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType16">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="collecting">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType17">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="distributing">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType17">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="defaulted">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType17">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="expired">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType17">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ <xsd:complexType name="MxbSlot">
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType18">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="TresholdPercent">
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType19">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="PbitToQueueMapping">
+ <xsd:annotation>
+ <xsd:documentation>
+ Description of Pbit to queue mapping
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="bladeSlotLink" type="BladeSlotLink"/>
+ <xsd:element name="interface">
+ <xsd:annotation>
+ <xsd:documentation>
+ Interface number
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="pbitQueue">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="item" type="PbitQueue" minOccurs="8" maxOccurs="8"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ <xsd:complexType name="VlanIds">
+ <xsd:sequence>
+ <xsd:element name="vlanId">
+ <xsd:annotation>
+ <xsd:documentation>
+ Vlan Id
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType10">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ <xsd:element name="model">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="Vlan" minOccurs="0" maxOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation>
+ Administrative and Operative Vlans
+
+ Key attributes: []
+
+ Possible children:
+ VlanAdmin
+ VlanOper
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="VlanAdmin" minOccurs="0" maxOccurs="31">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class shows the Administrative configured Vlans
+
+ Key attributes: [subrackNum]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="subrackNum" type="SubrackNum"/>
+ <xsd:element minOccurs="0" name="numberOfDefinedVlans">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="vlanIds">
+ <xsd:annotation>
+ <xsd:documentation>
+ Information about defined Vlan Ids
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="item" type="VlanIds" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="VlanOper" minOccurs="0" maxOccurs="31">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class shows the Operative Vlans
+
+ Key attributes: [subrackNum]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="subrackNum" type="SubrackNum"/>
+ <xsd:element minOccurs="0" name="numberOfActiveVlans">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="vlanIds">
+ <xsd:annotation>
+ <xsd:documentation>
+ Information about operative Vlan Ids
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="item" type="VlanIds" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Cos" minOccurs="0" maxOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class describes the Class of Service function.
+
+ Key attributes: []
+
+ Possible children:
+ Pbit
+ Queue
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element minOccurs="0" name="administrativeQueueConfiguration">
+ <xsd:annotation>
+ <xsd:documentation>
+ Description of administrative Queue Configuration Data
+ to be applied for each subrack (or whole system?)
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="item" type="CosQueueConfigurationData" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="administrativePbitToQueueMapping">
+ <xsd:annotation>
+ <xsd:documentation>
+ Description of administrative Pbit to Queue mapping.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="item" type="PbitToQueueMapping" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="operationalQueueConfiguration">
+ <xsd:annotation>
+ <xsd:documentation>
+ Description operational Queue Configuration Data
+ to be applied for actual subrack and Mxb.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="item" type="CosQueueConfigurationData" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="operationalPbitToQueueMapping">
+ <xsd:annotation>
+ <xsd:documentation>
+ Description of operational Pbit to Queue mapping.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="item" type="PbitToQueueMapping" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Pbit" minOccurs="0" maxOccurs="8">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class is used to set the Pbit to queue table.
+
+ Key attributes: [bladeSlotLink]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="bladeSlotLink" type="BladeSlotLink"/>
+ <xsd:element minOccurs="0" name="pbitQueue">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="item" type="PbitQueue" minOccurs="8" maxOccurs="8"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Queue" minOccurs="0" maxOccurs="8">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class is used to set the Queue Data table.
+
+ Key attributes: [queueKey]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="queueKey">
+ <xsd:annotation>
+ <xsd:documentation>
+ Queue value 0 to 7.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType7">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="queueData">
+ <xsd:annotation>
+ <xsd:documentation>
+ Queue Configuration Data to be applied for the whole system.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="item" type="CosQueueConfigurationData" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="State" minOccurs="0" maxOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class describes data to be read for a Mxb.
+
+ Key attributes: []
+
+ Possible children:
+ StateBlade
+ StateLink
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="StateBlade" minOccurs="0" maxOccurs="64">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class describes data related to a specific Mxb.
+
+ Key attributes: [subrackNum,mxbSlot]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="subrackNum" type="SubrackNum"/>
+ <xsd:element name="mxbSlot" type="MxbSlot"/>
+ <xsd:element minOccurs="0" name="description">
+ <xsd:annotation>
+ <xsd:documentation>
+ Description of type of Mxb.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType4">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="ipAddress">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType4">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="upTime">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType4">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="remoteMxbHost">
+ <xsd:annotation>
+ <xsd:documentation>
+ Indicates if the other Mxb in the subrack is present or absent.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType4">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="executingSoftwareVersion">
+ <xsd:annotation>
+ <xsd:documentation>
+ Software version executing.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType4">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="flashLoadedSoftwareVersion">
+ <xsd:annotation>
+ <xsd:documentation>
+ Software version in flash memory.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType4">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="fallbackSoftwareVersion">
+ <xsd:annotation>
+ <xsd:documentation>
+ Fallback software version.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType4">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="ipmiFirmwareVersion">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType4">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bootLoaderVersion">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType4">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="hwVersion">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType4">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="StateLink" minOccurs="0" maxOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class describes actual state data for a specific link
+ related to the Mxb.
+
+ Key attributes: []
+
+ Possible children:
+ StateLa
+ StateVlan
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="StateLa" minOccurs="0" maxOccurs="1536">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class describes the state of the Blade Slot Links with
+ regards to Link Aggregation info.
+
+ Key attributes: [subrackNum,bladeSlotLink,mxbSlot]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="subrackNum" type="SubrackNum"/>
+ <xsd:element name="bladeSlotLink" type="BladeSlotLink"/>
+ <xsd:element name="mxbSlot" type="MxbSlot"/>
+ <xsd:element minOccurs="0" name="linkAggregationData">
+ <xsd:annotation>
+ <xsd:documentation>
+ Description of Link Aggregation info for
+ actual subrack, Mxb and Blade Slot Link.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="item" type="LinkAggregationData" minOccurs="16" maxOccurs="16"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="StateVlan" minOccurs="0" maxOccurs="768">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class describes the state of the Blade Slot Links with
+ regards to Vlan info.
+
+ Key attributes: [subrackNum,bladeSlotLink]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="subrackNum" type="SubrackNum"/>
+ <xsd:element name="bladeSlotLink" type="BladeSlotLink"/>
+ <xsd:element minOccurs="0" name="vlanData">
+ <xsd:annotation>
+ <xsd:documentation>
+ Description of Vlans for actual subrack and Blade Slot Link
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="item" type="VlanData" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Pm" minOccurs="0" maxOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class describes the Performance Monitoring function.
+
+ Key attributes: []
+
+ Possible children:
+ PmBladeMeasure
+ PmLink
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element minOccurs="0" name="cpuUpperTreshold" type="TresholdPercent">
+ <xsd:annotation>
+ <xsd:documentation>
+ Configuration of CPU upper treshold, i.e. when the CPU load
+ is rising and crosses this treshold then the PMON function
+ in ISS will raise a CPU alarm.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="cpuLowerTreshold" type="TresholdPercent">
+ <xsd:annotation>
+ <xsd:documentation>
+ CPU lower treshold, i.e. when the CPU load
+ is falling and crosses this treshold then the
+ PM function in ISS will cease the CPU alarm.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="cpuUsageSamplingPeriod">
+ <xsd:annotation>
+ <xsd:documentation>
+ The sampling period during which CPU usage is measured.
+ This period is given in seconds.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="memoryUpperTreshold">
+ <xsd:annotation>
+ <xsd:documentation>
+ Memory upper treshold, i.e. when the Memory usage
+ is rising and crosses this treshold then the PM
+ function in ISS will raise a Memory alarm.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="memoryLowerTreshold" type="TresholdPercent">
+ <xsd:annotation>
+ <xsd:documentation>
+ Memory lower treshold, i.e. when the Memory usage
+ is falling and crosses this treshold then the PM
+ function in ISS will cease the Memory alarm.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bandwidthUpperTreshold" type="TresholdPercent">
+ <xsd:annotation>
+ <xsd:documentation>
+ Bandwidth upper treshold, i.e. when the Bandwidth
+ usage is rising and crosses this treshold then the PM
+ function in ISS will raise a Bandwidth alarm.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bandwidthLowerTreshold" type="TresholdPercent">
+ <xsd:annotation>
+ <xsd:documentation>
+ Bandwidth lower treshold, i.e. when the Bandwidth usage
+ is falling and crosses this treshold then the PM function
+ in ISS will cease the Bandwidth alarm.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bandwidthUsageSamplingPeriod">
+ <xsd:annotation>
+ <xsd:documentation>
+ The sampling period during which Bandwidth usage is measured.
+ This period is given in minutes.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="PmBladeMeasure" minOccurs="0" maxOccurs="64">
+ <xsd:annotation>
+ <xsd:documentation>
+ Enabling monitoring of CPU and memory usage and reading
+ the corresponding values of utilisation in percent.
+
+ Key attributes: [subrackNum,mxbSlot]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="subrackNum" type="SubrackNum"/>
+ <xsd:element name="mxbSlot" type="MxbSlot"/>
+ <xsd:element name="typeOfMeasurement">
+ <xsd:annotation>
+ <xsd:documentation>
+ Type of measurement to be performed, i.e. CPU or Memory.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType20">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="status">
+ <xsd:annotation>
+ <xsd:documentation>
+ Start or stop performance measurement of a specific type
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType21">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="usage" type="PercentUsage">
+ <xsd:annotation>
+ <xsd:documentation>
+ This is the value of the usage in percent when
+ performing the measurement.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="memoryUsageBytes">
+ <xsd:annotation>
+ <xsd:documentation>
+ This is the value of Memory usage in bytes when
+ performing a Memory usage measurement.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="PmLink" minOccurs="0" maxOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation>
+ Performance Management Link related data.
+
+ Key attributes: []
+
+ Possible children:
+ PmBwMeasure
+ PmStatistics
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="PmBwMeasure" minOccurs="0" maxOccurs="1536">
+ <xsd:annotation>
+ <xsd:documentation>
+ Enabling monitoring Bandwidth usage and reading the
+ corresponding values of utilisation in percent.
+
+ Key attributes: [subrackNum,bladeSlotLink,mxbSlot]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="subrackNum" type="SubrackNum"/>
+ <xsd:element name="bladeSlotLink" type="BladeSlotLink"/>
+ <xsd:element name="mxbSlot" type="MxbSlot"/>
+ <xsd:element name="status">
+ <xsd:annotation>
+ <xsd:documentation>
+ Start or stop measuring of bandwidth utilisation.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType21">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="bandwidthUsage" type="PercentUsage">
+ <xsd:annotation>
+ <xsd:documentation>
+ This is the value of the average Bandwidth usage in percent
+ during the configured sampling period.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="PmStatistics" minOccurs="0" maxOccurs="1536">
+ <xsd:annotation>
+ <xsd:documentation>
+ This class describes the Performance
+ Monitoring Statistics; i.e. counters
+ for each backplane port on the Mxb,
+ the actual speed used on the port and
+ if the port operates in full or half duplex mode.
+
+ Key attributes: [subrackNum,bladeSlotLink,mxbSlot]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="subrackNum" type="SubrackNum"/>
+ <xsd:element name="bladeSlotLink" type="BladeSlotLink"/>
+ <xsd:element name="mxbSlot" type="MxbSlot"/>
+ <xsd:element minOccurs="0" name="inOctets" type="StatisticCounter">
+ <xsd:annotation>
+ <xsd:documentation>
+ Performance Monitoring counter for
+ received octets.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="inUnicastPackets" type="StatisticCounter">
+ <xsd:annotation>
+ <xsd:documentation>
+ Performance Monitoring counter for
+ received Unicast Packets
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="inMulticastPackets" type="StatisticCounter">
+ <xsd:annotation>
+ <xsd:documentation>
+ Performance Monitoring counter for
+ received Multicast Packets
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="inBroadcastPackets" type="StatisticCounter">
+ <xsd:annotation>
+ <xsd:documentation>
+ Performance Monitoring counter for
+ received Broadcast Packets
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="inOctetsDiscarded" type="StatisticCounter">
+ <xsd:annotation>
+ <xsd:documentation>
+ Performance Monitoring counter
+ for number of received discarded octets.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="inOctetsFaulty" type="StatisticCounter">
+ <xsd:annotation>
+ <xsd:documentation>
+ Performance Monitoring counter
+ for number of received faulty octets.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="inUnknownProtocol" type="StatisticCounter">
+ <xsd:annotation>
+ <xsd:documentation>
+ Performance Monitoring counter
+ for number of received Unknown Protocol packets.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="outOctets" type="StatisticCounter">
+ <xsd:annotation>
+ <xsd:documentation>
+ Performance Monitoring counter for
+ octets in send buffer.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="outUnicastPackets" type="StatisticCounter">
+ <xsd:annotation>
+ <xsd:documentation>
+ Performance Monitoring counter for
+ Unicast Packets in send buffer.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="outMulticastPackets" type="StatisticCounter">
+ <xsd:annotation>
+ <xsd:documentation>
+ Performance Monitoring counter for
+ Multicast Packets in send buffer.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="outBroadcastPackets" type="StatisticCounter">
+ <xsd:annotation>
+ <xsd:documentation>
+ Performance Monitoring counter for
+ Broadcast Packets in send buffer.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="framesOpcodePause" type="StatisticCounter">
+ <xsd:annotation>
+ <xsd:documentation>
+ Performance Monitoring counter for
+ Frames with Op code Pause
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="framesExceedingMaxFramesize" type="StatisticCounter">
+ <xsd:annotation>
+ <xsd:documentation>
+ Performance Monitoring counter for
+ Frames exceeding maximum frame size.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:simpleType name="ccsHelperType21">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="on"/>
+ <xsd:enumeration value="off"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType20">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="cpu"/>
+ <xsd:enumeration value="memory"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType19">
+ <xsd:restriction base="xsd:integer">
+ <xsd:minInclusive value="50"/>
+ <xsd:maxInclusive value="100"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType18">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="left"/>
+ <xsd:enumeration value="right"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType17">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="yes"/>
+ <xsd:enumeration value="no"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType16">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="inSync"/>
+ <xsd:enumeration value="outOfSync"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType15">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="individual"/>
+ <xsd:enumeration value="aggregatable"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType14">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="long"/>
+ <xsd:enumeration value="short"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType13">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="passive"/>
+ <xsd:enumeration value="active"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType12">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="protected"/>
+ <xsd:enumeration value="isolatable"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType11">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="static"/>
+ <xsd:enumeration value="dynamic"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType10">
+ <xsd:restriction base="xsd:integer">
+ <xsd:minInclusive value="1"/>
+ <xsd:maxInclusive value="4094"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType9">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="notUsed"/>
+ <xsd:enumeration value="high"/>
+ <xsd:enumeration value="medium"/>
+ <xsd:enumeration value="low"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType8">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="notUsed"/>
+ <xsd:enumeration value="wrr"/>
+ <xsd:enumeration value="strictpriority"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType7">
+ <xsd:restriction base="xsd:integer">
+ <xsd:minInclusive value="0"/>
+ <xsd:maxInclusive value="7"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType6">
+ <xsd:restriction base="xsd:integer">
+ <xsd:minInclusive value="1"/>
+ <xsd:maxInclusive value="24"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType5">
+ <xsd:restriction base="xsd:integer">
+ <xsd:minInclusive value="0"/>
+ <xsd:maxInclusive value="100"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType4">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType3">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="srcMAC"/>
+ <xsd:enumeration value="dstMAC"/>
+ <xsd:enumeration value="srcAndDstMAC"/>
+ <xsd:enumeration value="srcIP"/>
+ <xsd:enumeration value="dstIP"/>
+ <xsd:enumeration value="srcAndDstIP"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType2">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="dynamic"/>
+ <xsd:enumeration value="force"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType1">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="lacp"/>
+ <xsd:enumeration value="manual"/>
+ <xsd:enumeration value="disable"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType0">
+ <xsd:restriction base="xsd:integer">
+ <xsd:minInclusive value="0"/>
+ <xsd:maxInclusive value="31"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+</xsd:schema>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/MyBsModel_1.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/MyBsModel_1.xsd
new file mode 100644
index 0000000000..5ec3434a65
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/MyBsModel_1.xsd
@@ -0,0 +1,502 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.ericsson.com/is/isco/MyBsModel_1" xmlns="http://www.ericsson.com/is/isco/MyBsModel_1" xmlns:nc="http://www.ericsson.com/is/isco/nc" xmlns:IsTypes="http://www.ericsson.com/is/isco/IsTypes">
+ <xsd:annotation>
+ <xsd:appinfo>
+ <mim file="myTest_mim.xml" version="/main/R2A/10"/>
+ <mim file="other_mim.xml" version=""/>
+ </xsd:appinfo>
+ </xsd:annotation>
+ <xsd:import schemaLocation="nc.xsd" namespace="http://www.ericsson.com/is/isco/nc"/>
+ <xsd:import schemaLocation="IsTypes.xsd" namespace="http://www.ericsson.com/is/isco/IsTypes"/>
+ <xsd:complexType name="uselessStruct">
+ <xsd:sequence>
+ <xsd:element name="field1">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType4">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="field2" type="myInteger"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ <xsd:complexType name="myNamedStruct">
+ <xsd:annotation>
+ <xsd:documentation>
+ Struct description
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="counter">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType5">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="state" type="stateType"/>
+ <xsd:element name="dummyStructRef" type="uselessStruct"/>
+ <xsd:element name="dummySequence">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="item" type="uselessStruct" minOccurs="3" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="inlineStruct">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="a" type="InternalImport"/>
+ <xsd:element name="b">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType6">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="c">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType7">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ <xsd:complexType name="myInteger">
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType8">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="namedMoRefType">
+ <xsd:annotation>
+ <xsd:documentation>
+ A named type which is an MO Reference pointing to
+ * MyClass
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType9">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="stateType">
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType10">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="blippName">
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType11">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="yesNoEnum">
+ <xsd:annotation>
+ <xsd:documentation>
+ Enum which can be yes or no
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType12">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="uselessEnum">
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType13">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="InternalImport">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:integer">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="MyClass_SeqType3">
+ <xsd:sequence>
+ <xsd:element name="item" type="MyClass_InternalType" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ <xsd:complexType name="MyClass_myDateAndTimeType">
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType0">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="MyClass_SeqType2">
+ <xsd:sequence>
+ <xsd:element name="item" type="uselessStruct" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ <xsd:complexType name="MyClass_InternalType">
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType1">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="MyClass_classInternalEnum">
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType2">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="MyClass_SeqType1">
+ <xsd:sequence>
+ <xsd:element name="item" minOccurs="3" maxOccurs="3">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType3">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ <xsd:element name="model">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="Blipp" minOccurs="0" maxOccurs="2">
+ <xsd:annotation>
+ <xsd:documentation>
+ This is a class which can be assigned as an attribute of ChildClass.
+ Key attribute is 'id'.
+
+ Key attributes: [id]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="id" type="blippName"/>
+ <xsd:element minOccurs="0" name="truefalse" type="uselessEnum"/>
+ <xsd:element minOccurs="0" name="ipAddress" type="IsTypes:IpAddress"/>
+ <xsd:element minOccurs="0" name="macAddress" type="IsTypes:MacAddress"/>
+ <xsd:element minOccurs="0" name="moAttributeDeep">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType14">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="MyClass" minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ My Test Class
+ The class hierarky looks like this:
+
+ +==========+
+ |MountPoint|
+ +==========+
+ / \
+ / \
+ +=======+ +=======+
+ | Blipp | |MyClass|
+ +=======+ +=======+
+ |
+ |
+ +==========+
+ |ChildClass|
+ +==========+
+
+ Key attributes: [id1,id2]
+
+ Possible children:
+ ChildClass:
+ Definition of children under MyClass
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="id1">
+ <xsd:annotation>
+ <xsd:documentation>
+ Test class identifyer - part1
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType15">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="id2">
+ <xsd:annotation>
+ <xsd:documentation>
+ Test class identifyer - part2
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType16">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="date">
+ <xsd:annotation>
+ <xsd:documentation>
+ Date
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType17">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="date2" type="MyClass_myDateAndTimeType">
+ <xsd:annotation>
+ <xsd:documentation>
+ Date2 - named type
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="list">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="item" minOccurs="3" maxOccurs="3">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType3">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="list2" type="MyClass_SeqType2"/>
+ <xsd:element minOccurs="0" name="list3" type="MyClass_SeqType3"/>
+ <xsd:element minOccurs="0" name="yesNo" type="yesNoEnum"/>
+ <xsd:element minOccurs="0" name="commonStruct" type="myNamedStruct">
+ <xsd:annotation>
+ <xsd:documentation>
+ Attribute description.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="dummyInternal" type="MyClass_InternalType"/>
+ <xsd:element minOccurs="0" name="trueOrFalse">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType7">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ChildClass" minOccurs="0" maxOccurs="2">
+ <xsd:annotation>
+ <xsd:documentation>
+ Child of MyClass
+
+ Key attributes: [id]
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="id">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType18">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="moAttribute">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="ccsHelperType19">
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="moAttributeNamed" type="namedMoRefType"/>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute ref="nc:operation"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:simpleType name="ccsHelperType19">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:pattern value="((/IntegratedSite:model/)|((\.\./)+)|((\./)(\.\./)*)|())((([A-Z][a-zA-Z0-9]+:model)|([A-Z][a-zA-Z0-9]+(\[[a-z][a-zA-Z0-9]*='[^\]]+'\])*))/)*Blipp\[id='[^\]]+'\]"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType18">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:minLength value="1"/>
+ <xsd:maxLength value="20"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType17">
+ <xsd:restriction base="xsd:dateTime">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:minInclusive value="2006-03-08T00:00:00.567Z"/>
+ <xsd:maxInclusive value="2006-03-08T23:59:59Z"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType16">
+ <xsd:restriction base="xsd:integer">
+ <xsd:minInclusive value="1"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType15">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="Obj"/>
+ <xsd:enumeration value="MO"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType14">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:pattern value="((/IntegratedSite:model/)|((\.\./)+)|((\./)(\.\./)*)|())((([A-Z][a-zA-Z0-9]+:model)|([A-Z][a-zA-Z0-9]+(\[[a-z][a-zA-Z0-9]*='[^\]]+'\])*))/)*ChildClass\[id='[^\]]+'\]"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType13">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="true"/>
+ <xsd:enumeration value="false"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType12">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="yes"/>
+ <xsd:enumeration value="no"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType11">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="name1"/>
+ <xsd:enumeration value="name2"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType10">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="locked"/>
+ <xsd:enumeration value="active"/>
+ <xsd:enumeration value="idle"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType9">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:pattern value="((/IntegratedSite:model/)|((\.\./)+)|((\./)(\.\./)*)|())((([A-Z][a-zA-Z0-9]+:model)|([A-Z][a-zA-Z0-9]+(\[[a-z][a-zA-Z0-9]*='[^\]]+'\])*))/)*MyClass\[id1='[^\]]+'\]\[id2='[^\]]+'\]"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType8">
+ <xsd:restriction base="xsd:integer">
+ <xsd:minInclusive value="1"/>
+ <xsd:maxInclusive value="100"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType7">
+ <xsd:restriction base="xsd:boolean">
+ <xsd:pattern value="(true|false)"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType6">
+ <xsd:restriction base="xsd:float">
+ <xsd:minInclusive value="0.00"/>
+ <xsd:maxInclusive value="1.00"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType5">
+ <xsd:restriction base="xsd:integer">
+ <xsd:minInclusive value="0"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType4">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:maxLength value="20"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType3">
+ <xsd:restriction base="xsd:integer">
+ <xsd:minInclusive value="0"/>
+ <xsd:maxInclusive value="3"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType2">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="a"/>
+ <xsd:enumeration value="b"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType1">
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="hei"/>
+ <xsd:enumeration value="hopp"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ccsHelperType0">
+ <xsd:restriction base="xsd:dateTime">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:minInclusive value="2006-03-15T00:00:00.567Z"/>
+ <xsd:maxInclusive value="2006-03-15T23:59:59Z"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+</xsd:schema>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/bs_mim.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/bs_mim.xml
new file mode 100644
index 0000000000..8846c05878
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/bs_mim.xml
@@ -0,0 +1,1187 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+
+<!--
+
+Copyright (C) Ericsson AB 2006-2007 All rights reserved.
+
+The information in this document is the property of Ericsson.
+
+Except as specifically authorized in writing by Ericsson, the
+receiver of this document shall keep the information contained
+herein confidential and shall protext the same in whole or in part
+from disclosure and dissemination to third parties.
+
+Disclosure and disseminations to the receivers employees shall
+only be made on a strict need to know basis.
+
+-->
+
+
+<mim xmlns="http://www.ericsson.com/is/isco/mim/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ericsson.com/is/isco/mim/2.0 /vobs/isac/sis/OAM_CRA1190047_1/CCS_CNA113082/doc/15519/mim.xsd ">
+
+ <!--
+ DataType Definitions
+ -->
+ <dataType name="HwmAdministrativeState">
+ <description>
+ The administrative state of blades/blade systems.
+ Reflects what the administrator has done.
+ </description>
+ <string>
+ <validValues>
+ <value name="locked"/>
+ <value name="shuttingdown"/>
+ <value name="unlocked"/>
+ </validValues>
+ </string>
+ </dataType>
+
+ <dataType name="HwmOperationalState">
+ <description>
+ The operational state of blades/blade systems.
+ Reflects if the entity is on/off.
+ </description>
+ <string>
+ <validValues>
+ <value name="disabled"/>
+ <value name="enabled"/>
+ </validValues>
+ </string>
+ </dataType>
+
+ <dataType name="HwmAvailabilityStatus">
+ <description>
+ The availability state of blades/blade systems.
+ Reflects if the entity is useable or not.
+ </description>
+ <string>
+ <validValues>
+ <value name="available"/>
+ <value name="failed"/>
+ <value name="offLine"/>
+ <value name="dependency"/>
+ <value name="degraded"/>
+ <value name="upgrading"/>
+ <value name="startingUp"/>
+ <value name="goingOffLine"/>
+ <value name="notInstalled"/>
+ <value name="powerOff"/>
+ </validValues>
+ </string>
+ </dataType>
+
+ <dataType name="HwmKnockOutPreference">
+ <description>
+ </description>
+ <string>
+ <validValues>
+ <value name="normal"/>
+ <value name="protected"/>
+ </validValues>
+ </string>
+ </dataType>
+
+ <dataType name="HwmBusType">
+ <description>
+ The bus type used by a blade.
+ </description>
+ <string>
+ <validValues>
+ <value name="ipmi"/>
+ <value name="mbus"/>
+ </validValues>
+ </string>
+ </dataType>
+
+ <!--
+ Class Definitions
+ -->
+
+ <class name="BladeSystems">
+ <description>
+ Parent of all blade systems.
+ </description>
+ <singleton/>
+ <systemCreated/>
+ </class>
+
+ <class name="BladeSystem">
+ <description>
+ This class describes a Blade System.
+ It serves as a mountpoint for the blade system specific model.
+ </description>
+
+ <!-- Attributes from HWM -->
+
+ <attribute name="name">
+ <description>
+ A user friendly Blade System name, must be set at creation and can be
+ changed when BS is locked.
+ </description>
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+
+ <attribute name="no">
+ <description>
+ An identifier for the BS. A new integer has to be used every time a new
+ BS is created.
+ </description>
+ <dataType><integer/></dataType>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="type">
+ <description>
+ </description>
+ <dataType><string/></dataType>
+ <mandatory/>
+ <restricted/>
+ </attribute>
+
+ <attribute name="softwareGroupId">
+ <description>
+ The identity of the Software Group (SWG) that the BS implements.
+ </description>
+ <dataType><string/></dataType>
+ <restricted/>
+ <mandatory/>
+ </attribute>
+
+ <attribute name="softwareGroupRevision">
+ <description>
+ The revision of the Software Group (SWG) that the BS implements.
+ </description>
+ <dataType><string/></dataType>
+ <restricted/>
+ <mandatory/>
+ </attribute>
+
+ <attribute name="softwareCorrectionPackageId">
+ <description>
+ The identity of the correction package (CXR) applied to the SWG.
+ </description>
+ <dataType><string/></dataType>
+ </attribute>
+
+ <attribute name="softwareCorrectionPackageRevision">
+ <description>
+ The revision of the correction package (CXR) applied to the SWG
+ </description>
+ <dataType><string/></dataType>
+ </attribute>
+
+ <attribute name="admState">
+ <description>The administrative state of the Blade System.</description>
+ <dataType name.ref="HwmAdministrativeState"/>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="opState">
+ <description>The operational state of the Blade System.</description>
+ <dataType name.ref="HwmOperationalState"/>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="availStatus">
+ <description>The availability status of the Blade System.</description>
+ <dataType name.ref="HwmAvailabilityStatus"/>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="bsdName">
+ <description>
+ The identity of the Blade System domain the Blade system belongs to.
+ </description>
+ <dataType><string/></dataType>
+ </attribute>
+
+ <!-- Attributes from CPD -->
+
+ <attribute name="bsomAddress">
+ <description>
+ IP address of the Blade System OaM Master.
+ </description>
+ <dataType name.ref="IsTypes:IpAddress"/>
+ <readOnly/>
+ </attribute>
+
+ <action name="lock">
+ <description>
+ Locks the blade system. If the system already is locked the
+ action does nothing.
+ </description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+
+ <action name="unlock">
+ <description>
+ Unlocks the blade system. If the system already is unlocked the
+ action does nothing. This operation orders the blade system to be unlocked.
+ However the blade system may not be unlocked even if this order works.
+ See the operational state to figure out if the unlock succeded.
+ </description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+
+ <action name="shutdown">
+ <description>
+ Shuts down the blade system. If the system already is locked the
+ action does nothing.
+ </description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+
+ <action name="createBackup">
+ <description>
+ Action to create a backup file from the current
+ Blade System. It is stored locally on disk.
+ An instance of the MO class
+ Software/Jobs/Backup/Create is created as a log of this
+ action.
+ </description>
+ <returnType>
+ <dataType><string/></dataType><!-- return ok | {fault,Reason} ? -->
+ </returnType>
+ <parameter name="backupJobName">
+ <description>
+ A user specified backup creation job name
+ </description>
+ <dataType><string/></dataType>
+ <isOptional/>
+ </parameter>
+ </action>
+
+ <action name="restoreBackup">
+ <description>
+ Action to restore a backup into the current
+ Blade System. It is fetched from the local disk.
+ An instance of the MO class
+ Software/Jobs/Backup/Restore is created as a log of this
+ action.
+ </description>
+ <returnType>
+ <dataType><string/></dataType><!-- return ok | {fault,Reason} ? -->
+ </returnType>
+ <parameter name="backupId">
+ <description>
+ The IS site local backup identity
+ </description>
+ <dataType name.ref="IsTypes:Unsigned32">
+ </dataType>
+ </parameter>
+ <parameter name="restoreJobName">
+ <description>
+ A user specified backup restore job name
+ </description>
+ <dataType><string/></dataType>
+ <isOptional/>
+ </parameter>
+ </action>
+
+ <action name="upgrade">
+ <description>
+ Action to upgrade the current Blade System. Files
+ are fetched from the local disk storage.
+ An instance of the MO class
+ Software/Jobs/Upgrade is created as a log of this
+ action.
+ </description>
+ <returnType>
+ <dataType><string/></dataType><!-- return ok | {fault,Reason} ? -->
+ </returnType>
+ <parameter name="upgradeJobName">
+ <description>
+ A user specified ugrade job name
+ </description>
+ <dataType><string/></dataType>
+ <isOptional/>
+ </parameter>
+ <parameter name="swgProdNr">
+ <description>
+ The Ericsson product number of blade system software group
+ </description>
+ <dataType><string/></dataType>
+ <isOptional/>
+ </parameter>
+ <parameter name="swgRevision">
+ <description>
+ The Ericsson revision of blade system software group
+ </description>
+ <dataType><string/></dataType>
+ <isOptional/>
+ </parameter>
+ <parameter name="cxrProdNr">
+ <description>
+ The Ericsson product number of software correction package
+ </description>
+ <dataType><string/></dataType>
+ <isOptional/>
+ </parameter>
+ <parameter name="cxrProdRevision">
+ <description>
+ The Ericsson revision of software correction package
+ </description>
+ <dataType><string/></dataType>
+ <isOptional/>
+ </parameter>
+ <parameter name="bladeSwgProdNr">
+ <description>
+ The Ericsson product number of blade software group
+ </description>
+ <dataType><string/></dataType>
+ <isOptional/>
+ </parameter>
+ <parameter name="bladeSwgProdRevison">
+ <description>
+ The Ericsson revision of blade software group
+ </description>
+ <dataType><string/></dataType>
+ <isOptional/>
+ </parameter>
+ <parameter name="maxTime">
+ <description>
+ The maximum time allowed to finish the entire
+ software change procedure (minutes).
+ Default value depends on blade system software.
+ </description>
+ <dataType name.ref="IsTypes:Unsigned32">
+ </dataType>
+ <isOptional/>
+ </parameter>
+ </action>
+ </class>
+
+
+ <class name="Blade">
+ <description>
+ This class describes a Blade.
+ A Blade is identified by the subrack and slot number.
+ </description>
+
+ <!-- Attributes from HWM -->
+
+ <attribute name="subrackId">
+ <description>
+ A reference to the associated subrack (i.e. the value of 'subrackId'
+ for the associated subrack)
+ </description>
+ <dataType>
+ <integer><range><min>0</min><max>31</max></range></integer>
+ </dataType>
+ <key/>
+ </attribute>
+
+ <attribute name="slotNo">
+ <description>The slot number for this Blade within the subrack.</description>
+ <dataType>
+ <integer><range><min>0</min><max>25</max></range></integer>
+ </dataType>
+ <key/>
+ </attribute>
+
+ <attribute name="slotLabel">
+ <description>
+ The slot label of the blade. Will only be set at creation.
+ This should be used in alarms related to the slot to inform the
+ operator of what position in the subrack the blade is located in.
+ E.g. for GEM subracks it will be a string like X02 for slot 0
+ up to X80 for slot 25.
+ </description>
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="bsNo">
+ <description>
+ An identifier for the BS to which the blade belongs.
+ A value of 0 means that the blade is inserted in the subrack but it
+ has not been configured to any BS yet.
+ </description>
+ <dataType><integer/></dataType>
+ </attribute>
+
+ <attribute name="type">
+ <description>
+ The type of the Blade defined by a string BladeTypeId.
+ </description>
+ <dataType><string/></dataType>
+ <restricted/>
+ <mandatory/>
+ </attribute>
+
+ <attribute name="swgLowestId">
+ <description>The expectedregistered SW group id of the Blade.</description>
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="swgLowestRev">
+ <description>The registered SW group revision state of the Blade.</description>
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="swgActualId">
+ <description>The installed SW group id of the Blade.</description>
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="swgActualRev">
+ <description>The installed SW group revision state of the Blade.</description>
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="bsom">
+ <description>
+ Indicates if this blade is a BSOM candidate.
+ </description>
+ <dataType><boolean/></dataType>
+ </attribute>
+
+ <attribute name="knockOutPreference">
+ <description>
+ Set to protected if blade sholud no be knocked out before the
+ switch blade.
+ </description>
+ <dataType name.ref="HwmKnockOutPreference"/>
+ </attribute>
+
+ <attribute name="userLabel">
+ <description>
+ A user friendly Blade name, always possible to set.
+ Default value indicates HwmBladeType and used slot.
+ </description>
+ <dataType><string/></dataType>
+ </attribute>
+
+ <attribute name="admState">
+ <description>
+ The administrative state of the Blade.
+ </description>
+ <dataType name.ref="HwmAdministrativeState"/>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="opState">
+ <description>The operational state of the Blade.</description>
+ <dataType name.ref="HwmOperationalState"/>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="availStatus">
+ <description>The availability status of the Blade.</description>
+ <dataType name.ref="HwmAvailabilityStatus"/>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="busType">
+ <description>The type of maintenance bus on the found Blade</description>
+ <dataType name.ref="HwmBusType"/>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="prodNo">
+ <description>The Product Number of the found Blade</description>
+ <dataType><string/></dataType>
+ </attribute>
+
+ <attribute name="prodRev">
+ <description>The Product Revision of the found Blade.</description>
+ <dataType><string/></dataType>
+ </attribute>
+
+ <attribute name="serialNo">
+ <description>The Serial Number of the found Blade.</description>
+ <dataType><string/></dataType>
+ </attribute>
+
+ <attribute name="prodName">
+ <description>The Product Name of the found Blade.</description>
+ <dataType><string/></dataType>
+ </attribute>
+
+ <attribute name="vendor">
+ <description>The Vendor name of the found Blade.</description>
+ <dataType><string/></dataType>
+ </attribute>
+
+ <attribute name="mfgDate">
+ <description>The manufacturing date of the found Blade.</description>
+ <dataType><string/></dataType>
+ </attribute>
+
+ <attribute name="macAddressAggregate">
+ <description>The aggregated MAC address of the found Blade.</description>
+ <dataType name.ref="IsTypes:MacAddress"/>
+ </attribute>
+
+ <attribute name="macAddressLeft">
+ <description>
+ The left link MAC address of the found Blade. Only used by some blades
+ </description>
+ <dataType name.ref="IsTypes:MacAddress"/>
+ </attribute>
+
+ <attribute name="macAddressRight">
+ <description>
+ The right link MAC address of the found Blade. Only used by some blades
+ </description>
+ <dataType name.ref="IsTypes:MacAddress"/>
+ </attribute>
+
+ <attribute name="changeDate">
+ <description>The date when the blade was last changed.</description>
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+
+ <!-- Attributes from CPD -->
+
+ <attribute name="isbsAddress">
+ <description>
+ IP address on the ISBS subnet.
+ </description>
+ <dataType name.ref="IsTypes:IpAddress"/>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="isobAddress">
+ <description>
+ IP address on the ISOB subnet.
+ </description>
+ <dataType name.ref="IsTypes:IpAddress"/>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="islctAddress">
+ <description>
+ IP address on the ISLCT subnet.
+ </description>
+ <dataType name.ref="IsTypes:IpAddress"/>
+ <readOnly/>
+ </attribute>
+
+ <action name="lock">
+ <description>
+ Locks the blade. If the blade already is locked the
+ action does nothing. This operation orders the blade to be locked.
+ It may however take long time before it happens.
+ </description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+
+ <action name="unlock">
+ <description>
+ Unlocks the blade. If the blade already is unlocked the
+ action does nothing. This operation orders the blade to be unlocked.
+ However the blade may not be unlocked even if this order works.
+ See the operational state to figure out if the unlock succeded.
+ </description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+
+ <action name="shutdown">
+ <description>
+ Shuts down the blade. If the blade already is locked the
+ action does nothing.
+ </description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ <action name="upgrade">
+ <description>
+ Action to upgrade the current blade. Files
+ are fetched from the local disk storage.
+ An instance of the MO class
+ Software/Jobs/Upgrade is created as a log of this
+ action.
+ </description>
+ <returnType>
+ <dataType><string/></dataType><!-- return ok | {fault,Reason} ? -->
+ </returnType>
+ <parameter name="swgProdNr">
+ <dataType><string/></dataType>
+ </parameter>
+ <parameter name="swgRevision">
+ <dataType><string/></dataType>
+ </parameter>
+ <parameter name="maxTime">
+ <dataType name.ref="IsTypes:Unsigned32">
+ </dataType>
+ <isOptional/>
+ </parameter>
+ </action>
+ </class>
+
+ <class name="LinkSap">
+ <description>
+ A Blade may have one or more resilient interfaces
+ to the backplane. Such an interface is called a
+ Link Service Access Point (LSAP), which is the
+ point where you access layer 2. LSAPs are
+ automatically created and deleted along with the
+ hosting blade.
+ </description>
+ <systemCreated/>
+ <attribute name="id">
+ <description>
+ The id of a LinkSap is a number from 0 to X within the slot.
+ </description>
+ <dataType><integer/></dataType>
+ <key/><readOnly/>
+ </attribute>
+ </class>
+
+ <class name="BsNetworkConfiguration">
+ <description>
+ The MO branch where the Blade System specific
+ Network resources are mapped to blade system
+ network requirements to common Integrated Site
+ resources. This activity must be performed before
+ a new blade or blade system successfully can be
+ unlocked via the Hardware service. Some blade
+ system designers have partly pre-registered their
+ network requirements, while others demand that
+ you read the corresponding information from
+ separate Operation Procedure Instructions and
+ manually register the blade system network
+ requirements. The pre-registered network
+ requirements automates parts of the blade
+ system-specific configuration activity.
+
+ In an Integrated Site, the blade systems obtain
+ their actual network configuration dynamically in
+ runtime. When you change the network
+ configuration it will affect blade systems. In
+ order to minimize the disturbance of active blade
+ systems, the changes are normally applied in a
+ separate storage which not is visible to the
+ blade systems. In order to make use of the new
+ unpublished configuration, it must explicitly be
+ published by altering the updateMode. If the new
+ settings introduces severe problems the
+ configuration can be reverted to the old settings
+ by altering the updateMode.
+
+ The common Network configuration including
+ updateMode and its publish mechanism is specified
+ in a separate MIM called CPD MIM.
+ </description>
+ <singleton/>
+ <systemCreated/>
+ </class>
+
+ <class name="BsVlan">
+ <description>
+ A BS VLAN is mapped to one IS VLAN. A BS VLAN is
+ the requirement a Blade System have of an IS
+ VLAN. Different instances of a Blade System type
+ may call their BS VLANs the same thing but in the
+ end the IS Site Designer can choose to map them
+ to the same or different IS VLAN.
+
+ BS VLANs can either be created manually by the
+ operator or they can be automatically created
+ from pre-registered network requirements bundled
+ with the Blade System software. Regardless of
+ how they are created, each one needs to be
+ mapped to an IS VLAN before the blades can be
+ unlocked. The mapping is done with the
+ 'isVlanRef' attribute.
+
+ Different instances of a Blade System type may call
+ their BS VLANs the same thing but in the end the IS
+ Site Designer can choose to map them to the same or
+ different IS VLAN.
+ </description>
+ <attribute name="name">
+ <description>
+ Name of the BS VLAN. It is unique within the Blade System.
+ </description>
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+ <attribute name="description">
+ <description>
+ Short description of the BS VLAN.
+ </description>
+ <dataType><string/></dataType>
+ </attribute>
+ <attribute name="private">
+ <description>
+ Setting the private attribute to true, means
+ that the corresponding IS VLAN not can be
+ used by other Blade Systems. The IS VLAN is
+ private for this particular Blade System.
+ </description>
+ <dataType><boolean/></dataType>
+ </attribute>
+ <attribute name="isVlanRef">
+ <description>
+ The mapping to a corresponding IS VLAN. This
+ mapping must be done before the blades of the
+ Blade System can be unlocked.
+ </description>
+ <dataType><moRef name="IsVlan"/></dataType>
+ </attribute>
+ </class>
+
+ <class name="BsLogicalNetwork">
+ <description>
+ A BS Logical Network (BSLN) is associated to
+ one IS Logical Network. A BS Logical Network
+ is the requirement a Blade Systems have of an
+ IS Logical Network.
+
+ BS Logical Networks can either be created
+ manually by the operator or they can be
+ automatically created from pre-registered
+ network requirements bundled with the Blade
+ System software. Regardless of how they are
+ created, each one needs to be mapped to an IS
+ Logical Network before the blades can be
+ unlocked. The mapping is done with the
+ 'isLogicalNetworkRef' attribute.
+
+ Different instances of a Blade System type may call
+ their BS Logical Networks the same thing but in
+ the end the IS Site Designer can choose to map
+ them to the same or different IS Logical
+ Network.
+ </description>
+ <attribute name="name">
+ <description>
+ Name of the BS logical network. It is unique within the Blade System.
+ </description>
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+ <attribute name="description">
+ <description>
+ Short description of the BS Logical Network.
+ </description>
+ <dataType><string/></dataType>
+ </attribute>
+ <attribute name="private">
+ <description>
+ Flag that shows whether the BS Logical Network
+ is private for this Blade System or if it may
+ be shared among several Blade Systems.
+ </description>
+ <dataType><boolean/></dataType>
+ </attribute>
+ <attribute name="isLogicalNetworkRef">
+ <description>
+ Reference to the corresponding IS Logical Network.
+ </description>
+ <dataType><moRef name="IsLogicalNetwork"/></dataType>
+ </attribute>
+ </class>
+
+ <class name="BsSubnet">
+ <description>
+ A BS Subnet (BSSN) is associated to one IS
+ Subnet. A BS Subnet Network is the requirement a
+ Blade Systems have of an IS Subnet.
+
+ BS Subnets can either be created manually by the
+ operator or they can be automatically created
+ from pre-registered network requirements bundled
+ with the Blade System software. Regardless of
+ how they are created, each one needs to be
+ mapped to both a BS VLan and an IS Subnet before
+ blades can be unlocked via the Hardware service.
+ Each BS Subnet contains one or more BS Subnet
+ Segments. The mappings are done with the
+ 'bsVlanRef' and 'isSubnetRef' attributes.
+
+ Different instances of a Blade System type may
+ call their BS Subnets the same thing but in the
+ end the IS Site Designer can choose to map them
+ to the same or different IS Subnet.
+ </description>
+ <attribute name="name">
+ <description>
+ Name of the BS Subnet. It is unique within the BS Logical Network.
+ </description>
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+ <attribute name="description">
+ <description>
+ Short description of the BS Subnet.
+ </description>
+ <dataType><string><defaultValue>default</defaultValue></string></dataType>
+ </attribute>
+ <attribute name="bsVlanRef">
+ <description>
+ The mapping to a corresponding BS Vlan. This
+ mapping must be done before the blades of the
+ Blade System can be unlocked.
+ </description>
+ <dataType><moRef name="BsVlan"/></dataType>
+ </attribute>
+ <attribute name="isSubnetRef">
+ <description>
+ The mapping to a corresponding IS Subnet. This
+ mapping must be done before the blades of the
+ Blade System can be unlocked.
+ </description>
+ <dataType><moRef name="IsSubnet"/></dataType>
+ </attribute>
+ </class>
+
+ <class name="BsSubnetSegment">
+ <description>
+ A BS Subnet Segment (BSSNS) is associated to one
+ IS Subnet Segment. A BS Subnet Segment is the
+ requirement a Blade Systems have of an IS Subnet
+ Segment.
+
+ BS Subnet Segments can either be created manually
+ by you or they can be automatically created from
+ pre-registered network requirements bundled with
+ the Blade System software. Regardless of how they
+ are created, each one needs to be mapped to an IS
+ Subnet Segment before the blades can be unlocked
+ via the Hardware service. The mapping is done
+ with the 'isSubnetSegmentRef' attribute.
+
+ Different instances of a Blade System type may
+ call their BS Subnet Segments the same thing but
+ in the end the IS Site Designer can choose to
+ map them to the same or different IS Subnet
+ Segment.
+ </description>
+ <attribute name="name">
+ <description>
+ Name of the BS Subnet Segment. It is unique within the BS Subnet.
+ </description>
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+ <attribute name="description">
+ <description>
+ Short description of the BS Subnet Segment.
+ </description>
+ <dataType><string/></dataType>
+ </attribute>
+ <attribute name="numOfIpaddresses">
+ <description>
+ Number of required IP addresses in the IS Subnet Segment.
+ </description>
+ <dataType><integer/></dataType>
+ </attribute>
+ <attribute name="dhcpEnabled">
+ <description>
+ Flag that controls whether the corresponding IS
+ Subnet Segment is required to have DHCP enabled
+ or not.
+ </description>
+ <dataType><boolean/></dataType>
+ </attribute>
+ <attribute name="routerRequired">
+ <description>
+ Flag that controls whether the corresponding IS
+ Subnet Segment is required to have a router
+ configured or not.
+ </description>
+ <dataType><boolean/></dataType>
+ </attribute>
+ <attribute name="isSubnetSegmentRef">
+ <description>
+ The mapping to a corresponding IS Subnet
+ Segment. The mapping here must be done before
+ the blades of the blade system can be unlocked.
+ </description>
+ <dataType>
+ <moRef name="IsSubnetSegment"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="BsVlanSap">
+ <description>
+ There is a BS VLAN Service Access Point (BSVSAP)
+ for each Link Service Access Point that an IS
+ VLAN straddles. It is per BS VLAN Service Access
+ Point that certain VLAN properties, such as if it
+ is mandatory to enable isolation protection.
+
+ BS VLAN Service Access Points can either be
+ created manually by the operator or they can be
+ automatically created from pre-registered network
+ requirements bundled with the Blade System
+ software. Regardless of how they are created,
+ each one needs to be mapped to an Link SAP before
+ the blades can be unlocked. The mapping is done
+ with the 'linkSapRef' attribute.
+ </description>
+ <attribute name="name">
+ <description>
+ Name of the BS VLAN SAP. It is unique within the BS VLAN.
+ </description>
+ <dataType>
+ <string/>
+ </dataType>
+ <key/>
+ </attribute>
+ <attribute name="description">
+ <description>
+ Short description of the BS VLAN SAP.
+ </description>
+ <dataType>
+ <string/>
+ </dataType>
+ </attribute>
+ <attribute name="static">
+ <description>
+ Flag which controls whether this BS VLAN SAP
+ makes static or dynamic use of the
+ corresponding IS VLAN.
+ </description>
+ <dataType>
+ <boolean/>
+ </dataType>
+ </attribute>
+ <attribute name="protected">
+ <description>
+ Flag which controls whether this BS VLAN SAP should be
+ isolation protected or not.
+ </description>
+ <dataType>
+ <boolean/>
+ </dataType>
+ </attribute>
+ <attribute name="linkSapRef">
+ <description>
+ A mapping to the corresponding Link Service Access Point.
+ </description>
+ <dataType>
+ <moRef name="LinkSap"/>
+ </dataType>
+ </attribute>
+ </class>
+
+ <class name="BsIpTrafficClass">
+ <description>
+ A BS IP Traffic Class (BSIPTC) is the
+ requirement a Blade System have of an IS IP
+ Traffic Class.
+
+ BS IP Traffic Classes can either be created
+ manually by you or they can be automatically
+ created from pre-registered network requirements
+ bundled with the Blade System software. Regardless
+ of how they are created, each one needs to be
+ mapped to an IS IP Traffic Class before the blades
+ can be unlocked via the Hardware service. The
+ mapping is done with the 'isIpTrafficClassRef'
+ attribute.
+
+ Different instances of a Blade System type may
+ call their BS IP Traffic Classes the same thing but
+ in the end the IS Site Designer may choose to
+ map them to the same or different IS IP Traffic
+ Classes.
+ </description>
+ <attribute name="name">
+ <description>
+ The name of the BS IP Traffic Class. It is
+ unique within the Blade System.
+ </description>
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+ <attribute name="description">
+ <description>
+ A short description of The BS IP Traffic Class.
+ </description>
+ <dataType><string/></dataType>
+ </attribute>
+ <attribute name="isIpTrafficClassRef">
+ <description>
+ The mapping to a corresponding IS IP Traffic
+ Class. This mapping must be done before the
+ blades of the Blade System can be unlocked.
+ </description>
+ <dataType><moRef name="IsIpTrafficClass"/></dataType>
+ </attribute>
+ </class>
+
+ <class name="BsLanTrafficClass">
+ <description>
+ A BS LAN Traffic Class (BSLANTC) is the
+ requirement a Blade System have of an IS LAN
+ Traffic Class. Different instances of a Blade
+ System type may call their BS Traffic Classes
+ the same thing but in the end the IS Site
+ Designer may choose to map them to the same or
+ different IS LAN Traffic Classes.
+
+ BS LAN Traffic Classes can either be created
+ manually by you or they can be automatically
+ created from pre-registered network requirements
+ bundled with the Blade System software. Regardless
+ of how they are created, each one needs to be
+ mapped to an IS LAN Traffic Class before the blades
+ can be unlocked via the Hardware service. The
+ mapping is done with the 'isLanTrafficClassRef'
+ attribute.
+
+ Different instances of a Blade System type may
+ call their BS LAN Traffic Classes the same
+ thing but in the end the IS Site Designer may
+ choose to map them to the same or different IS
+ LAN Traffic Classes.
+ </description>
+ <attribute name="name">
+ <description>
+ Name of the BS IP Traffic Class. It is unique within the Blade System.
+ </description>
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+ <attribute name="description">
+ <description>
+ Short description of the BS IP Traffic Class.
+ </description>
+ <dataType><string/></dataType>
+ </attribute>
+ <attribute name="isLanTrafficClassRef">
+ <description>
+ The mapping to a corresponding IS LAN Traffic
+ Class. This mapping must be done before the
+ blades of the Blade System can be unlocked.
+ </description>
+ <dataType><moRef name="IsLanTrafficClass"/></dataType>
+ </attribute>
+ </class>
+
+
+ <!--
+ Relatonship Definitions
+ -->
+
+ <relationship name="BladeSystemsTop">
+ <containment>
+ <parent>
+ <hasClass name="top_mim:Is"/>
+ </parent>
+ <child>
+ <hasClass name="BladeSystems"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="BsMount">
+ <containment>
+ <parent>
+ <hasClass name="BladeSystems"/>
+ </parent>
+ <child>
+ <hasClass name="BladeSystem"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Blades">
+ <containment>
+ <parent>
+ <hasClass name="BladeSystem"/>
+ </parent>
+ <child>
+ <hasClass name="Blade"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="LinkSaps">
+ <containment>
+ <parent><hasClass name="Blade"/></parent>
+ <child><hasClass name="LinkSap"/></child>
+ </containment>
+ </relationship>
+
+ <relationship name="NcMount">
+ <containment>
+ <parent><hasClass name="BladeSystem"/></parent>
+ <child><hasClass name="BsNetworkConfiguration"/></child>
+ </containment>
+ </relationship>
+
+ <relationship name="BsVlans">
+ <containment>
+ <parent><hasClass name="BsNetworkConfiguration"/></parent>
+ <child>
+ <hasClass name="BsVlan"/>
+ <cardinality><min>1</min></cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="BsVlanSaps">
+ <containment>
+ <parent><hasClass name="BsVlan"/></parent>
+ <child>
+ <hasClass name="BsVlanSap"/>
+ <cardinality><min>1</min></cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="BsLogicalNetworks">
+ <containment>
+ <parent><hasClass name="BsNetworkConfiguration"/></parent>
+ <child><hasClass name="BsLogicalNetwork"/></child>
+ </containment>
+ </relationship>
+
+ <relationship name="BsSubnets">
+ <containment>
+ <parent><hasClass name="BsLogicalNetwork"/></parent>
+ <child>
+ <hasClass name="BsSubnet"/>
+ <cardinality><min>1</min></cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="BsSubnetSegments">
+ <containment>
+ <parent><hasClass name="BsSubnet"/></parent>
+ <child><hasClass name="BsSubnetSegment"/></child>
+ </containment>
+ </relationship>
+
+ <relationship name="BsIpTrafficClasses">
+ <containment>
+ <parent><hasClass name="BsNetworkConfiguration"/></parent>
+ <child><hasClass name="BsIpTrafficClass"/></child>
+ </containment>
+ </relationship>
+
+ <relationship name="BsLanTrafficClasses">
+ <containment>
+ <parent><hasClass name="BsNetworkConfiguration"/></parent>
+ <child><hasClass name="BsLanTrafficClass"/></child>
+ </containment>
+ </relationship>
+
+
+
+</mim>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/dummy_action_mim.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/dummy_action_mim.xml
new file mode 100644
index 0000000000..d691fe0b3f
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/dummy_action_mim.xml
@@ -0,0 +1,186 @@
+<mim xmlns="http://www.ericsson.com/is/isco/mim/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ericsson.com/is/isco/mim/2.0 /vobs/isac/sis/OAM_CRA1190047_1/CCS_CNA113082/doc/15519/mim.xsd ">
+ <exception name="dummyException">
+ <description>
+ Exception description
+ </description>
+ <exceptionParameter name="dummyExcPar1">
+ <description>
+ Exception parameter description
+ </description>
+ <dataType><integer/></dataType>
+ </exceptionParameter>
+ <exceptionParameter name="dummyExcPar2">
+ <description>
+ Exception parameter description
+ </description>
+ <dataType>
+ <integer/>
+ </dataType>
+ </exceptionParameter>
+ </exception>
+
+
+ <class name="DummyActions">
+ <singleton/>
+ <attribute name="dummy">
+ <dataType><integer/></dataType>
+ </attribute>
+ <action name="actNoParams">
+ <description>
+ Action with no parameters
+ </description>
+ <returnType>
+ <description>
+ Maybe strange to describe void, but here is a description anyway.
+ </description>
+ <void/>
+ </returnType>
+ </action>
+ <action name="actOneParam">
+ <description>
+ Action with one parameter
+ </description>
+ <returnType>
+ <dataType>
+ <string>
+ <validValues>
+ <value name="ok"/>
+ <value name="error"/>
+ </validValues>
+ </string>
+ </dataType>
+ </returnType>
+ <parameter name="a">
+ <dataType>
+ <integer>
+ <range>
+ <min>0</min>
+ <max>3</max>
+ </range>
+ </integer>
+ </dataType>
+ </parameter>
+ </action>
+ <action name="actManyParams">
+ <description>
+ Action with many parameters, even some optional
+ </description>
+ <returnType>
+ <dataType>
+ <integer>
+ <range>
+ <min>0</min>
+ <max>100</max>
+ </range>
+ </integer>
+ </dataType>
+ </returnType>
+ <parameter name="a">
+ <dataType>
+ <integer>
+ <range>
+ <min>0</min>
+ <max>3</max>
+ </range>
+ </integer>
+ </dataType>
+ </parameter>
+ <parameter name="b">
+ <dataType>
+ <integer>
+ <range>
+ <min>0</min>
+ <max>3</max>
+ </range>
+ </integer>
+ </dataType>
+ </parameter>
+ <parameter name="c">
+ <dataType>
+ <integer>
+ <range>
+ <min>0</min>
+ <max>3</max>
+ </range>
+ </integer>
+ </dataType>
+ <initialValue>0</initialValue>
+ <isOptional/>
+ </parameter>
+ <parameter name="d">
+ <description>parameterdescription</description>
+ <dataType>
+ <integer/>
+ </dataType>
+ <isOptional/>
+ </parameter>
+ </action>
+ <action name="actComplexParams">
+ <description>
+ Action with parameters with complex datatypes
+ </description>
+ <returnType>
+ <description>
+ Here is a description of the return value for this action.
+ </description>
+ <dataType>
+ <string>
+ <validValues>
+ <value name="siri"/>
+ <value name="sara"/>
+ </validValues>
+ </string>
+ </dataType>
+ </returnType>
+ <parameter name="dummyParameter">
+ <dataType><integer/></dataType>
+ </parameter>
+ <parameter name="structParameter">
+ <dataType>
+ <struct>
+ <structMember name="a">
+ <dataType><integer/></dataType>
+ </structMember>
+ <structMember name="b">
+ <dataType><integer/></dataType>
+ </structMember>
+ </struct>
+ </dataType>
+ </parameter>
+ <raisesException name="dummyException"/>
+ </action>
+ <action name="actComplexReturn">
+ <returnType>
+ <dataType>
+ <struct>
+ <structMember name="a">
+ <dataType><integer/></dataType>
+ </structMember>
+ <structMember name="b">
+ <dataType><integer/></dataType>
+ </structMember>
+ </struct>
+ </dataType>
+ </returnType>
+ </action>
+ <action name="actException">
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="dummyException"/>
+ </action>
+ </class>
+
+
+ <relationship name="Top">
+ <containment>
+ <parent>
+ <hasClass name="top_mim:Is"/>
+ </parent>
+ <child>
+ <hasClass name="DummyActions"/>
+ </child>
+ </containment>
+ </relationship>
+
+</mim> \ No newline at end of file
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/hwm_mim.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/hwm_mim.xml
new file mode 100644
index 0000000000..a7a18b0070
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/hwm_mim.xml
@@ -0,0 +1,631 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+
+<!--
+
+Copyright (C) Ericsson AB 2006-2007 All rights reserved.
+
+The information in this document is the property of Ericsson.
+
+Except as specifically authorized in writing by Ericsson, the
+receiver of this document shall keep the information contained
+herein confidential and shall protext the same in whole or in part
+from disclosure and dissemination to third parties.
+
+Disclosure and disseminations to the receivers employees shall
+only be made on a strict need to know basis.
+
+-->
+
+
+<mim xmlns="http://www.ericsson.com/is/isco/mim/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ericsson.com/is/isco/mim/2.0 /vobs/isac/sis/OAM_CRA1190047_1/CCS_CNA113082/doc/15519/mim.xsd ">
+
+ <!--
+ DataType Definitions
+ -->
+
+ <dataType name="HwmSlotState">
+ <description>
+ Information of how the slot is used.
+ </description>
+ <string>
+ <validValues>
+ <value name="unusedEmpty"/>
+ <value name="usedEmpty"/>
+ <value name="unusedOccupied"/>
+ <value name="usedOccupied"/>
+ </validValues>
+ </string>
+ </dataType>
+
+
+ <!--
+ Class Definitions
+ -->
+
+ <exception name="dummyException">
+ <exceptionParameter name="dummyExcPar1">
+ <dataType><integer/></dataType>
+ </exceptionParameter>
+ <exceptionParameter name="dummyExcPar2">
+ <dataType><integer/></dataType>
+ </exceptionParameter>
+ </exception>
+
+
+ <class name="Hardware">
+ <description>
+ The purpose of the Hardware Management function is to make it possible to maintain
+ the Hardware Inventory (HWI) for the Integrated Site and to present its content via ISM
+ or to a management system. And also to maintain the subracks usage.
+ </description>
+ <singleton/>
+ <systemCreated/>
+
+ <attribute name="activeSis">
+ <description>
+ The subrack,slot of the active om SIS. The format is "subrack.slot".
+ </description>
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+
+ <action name="actComplexParams">
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="structParameter">
+ <dataType>
+ <struct>
+ <structMember name="a">
+ <dataType><integer/></dataType>
+ </structMember>
+ <structMember name="b">
+ <dataType><integer/></dataType>
+ </structMember>
+ </struct>
+ </dataType>
+ </parameter>
+ </action>
+
+ <action name="actComplexReturn">
+ <returnType>
+ <dataType>
+ <struct>
+ <structMember name="a">
+ <dataType><integer/></dataType>
+ </structMember>
+ <structMember name="b">
+ <dataType><integer/></dataType>
+ </structMember>
+ </struct>
+ </dataType>
+ </returnType>
+ </action>
+
+ <action name="actException">
+ <returnType>
+ <void/>
+ </returnType>
+ <raisesException name="dummyException"/>
+ </action>
+
+ <action name="createInfraStructure">
+ <description>
+ Creates the base IS infrastructure.
+ This is noramlly done at factory.
+ </description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+
+ <action name="exportInventory">
+ <description>
+ Exports the Hardware Inventory via FTP.
+ This is an asyncrounous operation. The file exported
+ will have the following name format:
+ &lt;node&gt;.&lt;timestamp&gt;.HWI.xml.tar.gz
+ </description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="host">
+ <description>
+ The host to which the data should be sent to
+ </description>
+ <dataType><string/></dataType>
+ </parameter>
+ <parameter name="user">
+ <description>
+ The username on the host to be used during the FTP transfer.
+ </description>
+ <dataType><string/></dataType>
+ </parameter>
+ <parameter name="password">
+ <description>
+ The pasword of the user
+ </description>
+ <dataType><string/></dataType>
+ </parameter>
+ <parameter name="path">
+ <description>
+ The path were to put the file
+ </description>
+ <dataType><string/></dataType>
+ </parameter>
+ </action>
+
+ </class>
+
+ <class name="BladeType">
+ <description>
+ This class describes a Blade type.
+ </description>
+ <systemCreated/>
+
+ <attribute name="type">
+ <description>The blade type number like CNA12801</description>
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+
+ <attribute name="swgId">
+ <description>The blade software group index link CSX10138</description>
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+
+ <attribute name="swgRev">
+ <description>The blade software group revision</description>
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+
+ <attribute name="name">
+ <description>The name of the Blade Type.</description>
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="width">
+ <description>The width of the blade in number of slots.</description>
+ <dataType>
+ <integer/>
+ </dataType>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="oneGLinks">
+ <description>
+ The 1G links used by the blade type , like 0,1, counted from
+ the leftmost backplane position.
+ </description>
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="linkAggregates">
+ <description>
+ The 1G links used for link aggregation by the blade type , like 0-1,
+ counted from the leftmost backplane position.
+ </description>
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="hasHwData">
+ <description>
+ True if possible to read product info via the maintenance bus.
+ </description>
+ <dataType><boolean/></dataType>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="isMxb">
+ <description>True if this is a Main Switch blade type.</description>
+ <dataType><boolean/></dataType>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="availOneGSlots">
+ <description>
+ Only valid for main switch blades. A list of slots that have 1G link.
+ Could be a single slot or a range or a combination thereof.
+ E.g. 1-24, or 1,3-13,15-24.
+ </description>
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="aggregateRanges">
+ <description>
+ Only valid for main switch blades. Specifies which slots can be used
+ for link aggregation. Ranges are specified in the form 1-12,13-24.
+ </description>
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+
+ </class>
+
+
+ <class name="BladeSystemDomain">
+ <description>
+ This class describes a Blade system domain.
+ </description>
+ <systemCreated/>
+
+ <attribute name="name">
+ <description>The blade system domain name.</description>
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+
+ <attribute name="description">
+ <description>The description of the blade system domain.</description>
+ <dataType><string/></dataType>
+<!-- <key/> -->
+ </attribute>
+
+ </class>
+
+
+ <class name="Subrack">
+ <description>
+ This class describes the subrack.
+ </description>
+ <extension>
+ <callpoint id="Is_Hardware_Subrack" type="external"/>
+<!-- <validate id="Is_Hardware_Subrack" type="external" callOnce="true"/>-->
+ </extension>
+
+ <attribute name="id">
+ <description>Identifies a certain subrack.</description>
+ <dataType>
+ <integer><range><min>0</min><max>31</max></range></integer>
+ </dataType>
+ <key/>
+ </attribute>
+
+ <attribute name="type">
+ <description>The type of subrack.</description>
+ <dataType><string/></dataType>
+ </attribute>
+
+ <attribute name="userLabel">
+ <description>A user friendly Subrack name.</description>
+ <dataType><string/></dataType>
+ </attribute>
+
+ <attribute name="position">
+ <description>The subrack position in the cabinet.</description>
+ <dataType><string/></dataType>
+ </attribute>
+
+ <attribute name="cabinetPosition">
+ <description>The cabinet position in the site.</description>
+ <dataType><string/></dataType>
+ </attribute>
+
+ <attribute name="location">
+ <description>The site location, e.g. the visiting address.</description>
+ <dataType><string/></dataType>
+ </attribute>
+
+ <attribute name="availableOneGSlots">
+ <description>
+ Available slots for 1G switch links. Information taken from the type
+ of main switch blade that is created in the subrack.
+ </description>
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="availableTenGSlots">
+ <description>
+ Available slots for 10G switch links. Information taken from the type
+ of main switch blade that is created in the subrack.
+ </description>
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="aggregateSlots">
+ <description>
+ Links ranges for (1G) link aggregation. Information taken from the
+ type of main switch blade that is created in the subrack.
+ </description>
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="physicalAddrPlug0">
+ <description>
+ The value of the physical plug 0.
+ </description>
+ <dataType><integer/></dataType>
+ <mandatory/>
+ </attribute>
+
+ <attribute name="physicalAddrPlug1">
+ <description>
+ The value of the physical plug 1.
+ </description>
+ <dataType><integer/></dataType>
+ <mandatory/>
+ </attribute>
+
+ <attribute name="physicalAddrPlug3">
+ <description>
+ The value of the physical plug 3.
+ </description>
+ <dataType><integer/></dataType>
+ <mandatory/>
+ </attribute>
+
+ <attribute name="leftMxbBsSwgId">
+ <description>
+ The BS SWG Id of the left MXB in the subrack.
+ If not given the system will use the same as the
+ MXB in subrack 0. This might not be corect however.
+ </description>
+ <dataType><string/></dataType>
+ <restricted/>
+ </attribute>
+
+ <attribute name="leftMxbBsSwgRev">
+ <description>
+ The BS SWG Revision of the left MXB in the subrack.
+ If not given the system will use the same as the
+ MXB in subrack 0. This might not be corect however.
+ </description>
+ <dataType><string/></dataType>
+ <restricted/>
+ </attribute>
+
+ <attribute name="leftMxbBsCxrId">
+ <description>
+ The BS CXR Id (if any) of the left MXB in the subrack.
+ If not given the system will use the same as the
+ MXB in subrack 0. This might not be corect however.
+ </description>
+ <dataType><string/></dataType>
+ <restricted/>
+ </attribute>
+
+ <attribute name="leftMxbBsCxrRev">
+ <description>
+ The BS CXR Revision (if any) of the left MXB in the subrack.
+ If not given the system will use the same as the
+ MXB in subrack 0. This might not be corect however.
+ </description>
+ <dataType><string/></dataType>
+ <restricted/>
+ </attribute>
+
+ <attribute name="leftMxbBlSwgId">
+ <description>
+ The BL SWG Id of the left MXB in the subrack.
+ If not given the system will use the same as the
+ MXB in subrack 0. This might not be corect however.
+ </description>
+ <dataType><string/></dataType>
+ <restricted/>
+ </attribute>
+
+ <attribute name="leftMxbBlSwgRev">
+ <description>
+ The BL SWG Revision of the left MXB in the subrack.
+ If not given the system will use the same as the
+ MXB in subrack 0. This might not be corect however.
+ </description>
+ <dataType><string/></dataType>
+ <restricted/>
+ </attribute>
+
+ <attribute name="leftMxbBlCxrId">
+ <description>
+ The BL CXR Id (if any) of the left MXB in the subrack.
+ If not given the system will use the same as the
+ MXB in subrack 0. This might not be corect however.
+ </description>
+ <dataType><string/></dataType>
+ <restricted/>
+ </attribute>
+
+ <attribute name="leftMxbBlCxrRev">
+ <description>
+ The BL CXR Revision (if any) of the left MXB in the subrack.
+ If not given the system will use the same as the
+ MXB in subrack 0. This might not be corect however.
+ </description>
+ <dataType><string/></dataType>
+ <restricted/>
+ </attribute>
+
+ <attribute name="rightMxbBsSwgId">
+ <description>
+ The BS SWG Id of the right MXB in the subrack.
+ If not given the system will use the same as the
+ MXB in subrack 0. This might not be corect however.
+ </description>
+ <dataType><string/></dataType>
+ <restricted/>
+ </attribute>
+
+ <attribute name="rightMxbBsSwgRev">
+ <description>
+ The BS SWG Revision of the right MXB in the subrack.
+ If not given the system will use the same as the
+ MXB in subrack 0. This might not be corect however.
+ </description>
+ <dataType><string/></dataType>
+ <restricted/>
+ </attribute>
+
+ <attribute name="rightMxbBsCxrId">
+ <description>
+ The BS CXR Id (if any) of the right MXB in the subrack.
+ If not given the system will use the same as the
+ MXB in subrack 0. This might not be corect however.
+ </description>
+ <dataType><string/></dataType>
+ <restricted/>
+ </attribute>
+
+ <attribute name="rightMxbBsCxrRev">
+ <description>
+ The BS CXR Revision (if any) of the right MXB in the subrack.
+ If not given the system will use the same as the
+ MXB in subrack 0. This might not be corect however.
+ </description>
+ <dataType><string/></dataType>
+ <restricted/>
+ </attribute>
+
+ <attribute name="rightMxbBlSwgId">
+ <description>
+ The BL SWG Id of the right MXB in the subrack.
+ If not given the system will use the same as the
+ MXB in subrack 0. This might not be corect however.
+ </description>
+ <dataType><string/></dataType>
+ <restricted/>
+ </attribute>
+
+ <attribute name="rightMxbBlSwgRev">
+ <description>
+ The BL SWG Revision of the right MXB in the subrack.
+ If not given the system will use the same as the
+ MXB in subrack 0. This might not be corect however.
+ </description>
+ <dataType><string/></dataType>
+ <restricted/>
+ </attribute>
+
+ <attribute name="rightMxbBlCxrId">
+ <description>
+ The BL CXR Id (if any) of the right MXB in the subrack.
+ If not given the system will use the same as the
+ MXB in subrack 0. This might not be corect however.
+ </description>
+ <dataType><string/></dataType>
+ <restricted/>
+ </attribute>
+
+ <attribute name="rightMxbBlCxrRev">
+ <description>
+ The BL CXR Revision (if any) of the right MXB in the subrack.
+ If not given the system will use the same as the
+ MXB in subrack 0. This might not be corect however.
+ </description>
+ <dataType><string/></dataType>
+ <restricted/>
+ </attribute>
+ </class>
+
+ <class name="Slot">
+ <description>
+ This class corresponds to slots, there is one instance
+ for each slot. The slots are grouped per subrack. A slot is
+ identified by subrack Id and slot number). The subrack Id for a slot
+ identifies in the subrackTable the subrack that the slot belongs
+ to.
+ </description>
+ <systemCreated/>
+
+ <attribute name="number">
+ <description>
+ The value of this object identifies the
+ slot position within the subrack.
+ </description>
+ <dataType>
+ <integer><range><min>0</min><max>25</max></range></integer>
+ </dataType>
+ <key/>
+ </attribute>
+
+ <attribute name="state">
+ <description>
+ See HwmSlotState description.
+ </description>
+ <dataType name.ref="HwmSlotState"/>
+ <readOnly/>
+ </attribute>
+
+ <attribute name="bladeSystem">
+ <description>
+ The value of this object identifies the Blade System that uses this
+ slot. An instances of this object will only have meaning in a
+ conceptual row if the value of hwmSlotState instance is either
+ usedOccupied or usedEmpty in the same conceptual row,
+ i.e. there is an Blade System created using this slot. (If
+ no Blade System is using the slot, the value will be "-".)
+ </description>
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+
+ </class>
+
+
+ <!--
+ Relatonship Definitions
+ -->
+
+ <relationship name="HwmTop">
+ <containment>
+ <parent>
+ <hasClass name="top_mim:Is"/>
+ </parent>
+ <child>
+ <hasClass name="Hardware"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="BladeTypes">
+ <containment>
+ <parent>
+ <hasClass name="Hardware"/>
+ </parent>
+ <child>
+ <hasClass name="BladeType"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="BladeSystemDomains">
+ <containment>
+ <parent>
+ <hasClass name="Hardware"/>
+ </parent>
+ <child>
+ <hasClass name="BladeSystemDomain"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Subracks">
+ <containment>
+ <parent>
+ <hasClass name="Hardware"/>
+ </parent>
+ <child>
+ <hasClass name="Subrack"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Slots">
+ <containment>
+ <parent>
+ <hasClass name="Subrack"/>
+ </parent>
+ <child>
+ <hasClass name="Slot"/>
+ </child>
+ </containment>
+ </relationship>
+</mim>
+
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/instance.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/instance.xml
new file mode 100644
index 0000000000..e39152cada
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/instance.xml
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+
+<!-- Copyright (C) Ericsson AB 2006 All rights reserved. -->
+
+<!-- Integrated Site Managed Object Model. -->
+
+<!--
+ This is a template for the IntegratedSite model version 1,
+ which consists of the following mim files:
+ /vobs/isac/sis/OAM_CRA1190047_1/CPD_CNA11381/doc/19062/cpd_mim.xml
+ /vobs/isac/sis/OAM_CRA1190047_1/HWM_CNA11309/doc/19062/hwm_mim.xml
+ /vobs/isac/sis/OAM_CRA1190047_1/SCA_CNA113119/doc/19062/bs_mim.xml
+ /vobs/isac/sis/OAM_CRA1190047_1/SWM_CNA11315/doc/19062/swm_mim.xml
+ /vobs/isac/sis/OAM_CRA1190047_1/doc/19062/top_mim.xml
+
+-->
+<IntegratedSite:model xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:nc="http://www.ericsson.com/is/isco/nc" xmlns:IntegratedSite="http://www.ericsson.com/is/isco/IntegratedSite" xmlns:IsTypes="http://www.ericsson.com/is/isco/IsTypes" xmlns:MainSwitch="http://www.ericsson.com/is/isco/MainSwitch_1" xmlns:MyBsModel="http://www.ericsson.com/is/isco/MyBsModel_1" xsi:schemaLocation="http://www.ericsson.com/is/isco/IntegratedSite IntegratedSite.xsd">
+
+ <!--
+ The top class - the forefather of all classes.
+
+ Key attributes: []
+
+ Possible children:
+ BladeSystems
+ Hardware
+ NetworkConfiguration
+ Software
+ -->
+ <Is>
+
+
+ <!-- These three are just for verifying that the xml schema allows
+ the correct order of the child elements of the Is class -->
+<!--
+ <Hardware/>
+ <Software/>
+ <NetworkConfiguration/>
+-->
+
+ <!--
+ The BladeSystems mountpoint - parent of all blade systems.
+
+ Key attributes: []
+
+ Possible children:
+ BladeSystemTemplate
+ Mxb
+ MyBsModel
+ Sis
+ -->
+ <BladeSystems>
+
+ <!--
+ This class describes a Blade System. It will be cloned for each
+ new blade system type registered in the system. The new clone
+ will serve as a mountpoint for the blade system specific model.
+
+ Key attributes: [name]
+
+ Possible children:
+ Blade
+ BsIpTrafficClass
+ BsLanTrafficClass
+ BsLogicalNetwork
+ BsVlan
+ -->
+ <MyBsModel>
+ <!--
+ A user friendly Blade System name, must be set at creation and can be
+ changed when BS is locked.
+ -->
+ <name>bs_localhost_101</name>
+ <!--
+ An identifier for the BS. A new integer has to be used every time a new
+ BS is created. ??? Kvar ???
+ -->
+ <!--
+ The model for a blade system. Includes som mim files, which also uses
+ stuff from a sis model.
+ -->
+
+ <!--
+ This is a template for the MyBsModel model version 1,
+ which consists of the following mim files:
+ /vobs/isac/sis/OAM_CRA1190047_1/CCS_CNA113082/test/local_test/ccs_parser_SUITE_data/myTest_mim.xml, Version: /main/R2A/10
+ /vobs/isac/sis/OAM_CRA1190047_1/CCS_CNA113082/test/local_test/ccs_parser_SUITE_data/other_mim.xml
+
+ -->
+ <MyBsModel:model>
+
+ <!--
+ This is a class which can be assigned as an attribute of ChildClass.
+ Key attribute is 'id'.
+
+ Key attributes: [id]
+ -->
+ <Blipp nc:operation="replace">
+ <id>name1</id>
+ <truefalse>true</truefalse>
+ <ipAddress>
+ 10.11.12.13
+ </ipAddress>
+ <macAddress>AA:BB:CC:DD:EE:FF</macAddress>
+ <moAttributeDeep nc:operation="replace">
+ /IntegratedSite:model/Is/BladeSystems/MyBsModel[name='bs_localhost_101']/MyBsModel:model/MyClass[id1='Obj'][id2='1']/ChildClass[id='Obj2']
+ </moAttributeDeep>
+ </Blipp>
+
+ <Blipp>
+ <id>name2</id>
+ <truefalse>false</truefalse>
+ <ipAddress>20.21.22.23</ipAddress>
+ <macAddress>01:02:03:04:5:6</macAddress>
+ <moAttributeDeep>
+ MyClass[id1='Obj'][id2='1']/ChildClass[id='Obj3']
+ </moAttributeDeep>
+ </Blipp>
+
+ <!--
+ My Test Class
+ The class hierarky looks like this:
+
+ +==========+
+ |MountPoint|
+ +==========+
+ / \
+ / \
+ +=======+ +=======+
+ | Blipp | |MyClass|
+ +=======+ +=======+
+ |
+ |
+ +==========+
+ |ChildClass|
+ +==========+
+
+ Key attributes: [id1,id2]
+
+ Possible children:
+ ChildClass:
+ Definition of children under MyClass
+ -->
+ <MyClass>
+ <!-- Test class identifyer - part1 -->
+ <id1>Obj</id1>
+ <!-- Test class identifyer - part2 -->
+ <id2>1</id2>
+ <date>2006-03-08T03:00:00.9+03:00</date>
+ <date2>2006-03-15T22:59:58.99-01:00</date2>
+ <list>
+ <item>0</item>
+ <item>1</item>
+ <item nc:operation="delete">3</item>
+ </list>
+ <list2>
+ <item>
+ <!-- Struct: sis_model:uselessStruct -->
+ <field1>hei</field1>
+ <field2 nc:operation="replace">1</field2>
+ </item>
+ <item nc:operation="replace">
+ <!-- Struct: sis_model:uselessStruct -->
+ <field1>
+ hopp
+ </field1>
+ <field2>2</field2>
+ </item>
+ </list2>
+ <list3>
+ <item>hei</item>
+ <item>hopp</item>
+ </list3>
+ <yesNo>
+ yes
+ </yesNo>
+ <!-- Attribute description. -->
+ <commonStruct>
+ <!--
+ Struct: myNamedStruct
+ Struct description
+ -->
+ <counter>0</counter>
+ <state>locked</state>
+ <dummyStructRef>
+ <!-- Struct: sis_model:uselessStruct -->
+ <field1>hei</field1>
+ <field2>1</field2>
+ </dummyStructRef>
+ <dummySequence>
+ <item>
+ <field1>hopp</field1>
+ <field2>2</field2>
+ </item>
+ <item>
+ <field1>sa</field1>
+ <field2>3</field2>
+ </item>
+ <item>
+ <field1>sa</field1>
+ <field2>4</field2>
+ </item>
+ </dummySequence>
+ <inlineStruct>
+ <a>1</a>
+ <b>1.0</b>
+ <c>true</c>
+ </inlineStruct>
+ </commonStruct>
+ <dummyInternal>hei</dummyInternal>
+ <trueOrFalse>false</trueOrFalse>
+ <!--
+ Child of MyClass
+
+ Key attributes: [id]
+ -->
+ <ChildClass>
+ <id>Obj2</id>
+ <moAttribute>/IntegratedSite:model/Is/BladeSystems/MyBsModel[name='bs_localhost_101']/MyBsModel:model/Blipp[id='name1']</moAttribute>
+ <moAttributeNamed>
+ /IntegratedSite:model/Is/BladeSystems/MyBsModel[name='bs_localhost_101']/MyBsModel:model/MyClass[id1='Obj'][id2='1']
+ </moAttributeNamed>
+ </ChildClass>
+ <ChildClass>
+ <id>Obj3</id>
+ <moAttribute>../../Blipp[id='name2']</moAttribute>
+<!-- <moAttributeNamed>../MyClass[id1='Obj'][id2='1']</moAttributeNamed> -->
+ <moAttributeNamed>Dummy/MyClass[id1='Obj'][id2='1']</moAttributeNamed>
+ </ChildClass>
+ </MyClass>
+
+ </MyBsModel:model>
+ </MyBsModel>
+
+ </BladeSystems>
+<!--
+ <MainSwitch:model/>
+-->
+ </Is>
+</IntegratedSite:model>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/mim.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/mim.xsd
new file mode 100644
index 0000000000..e0534e8e14
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/mim.xsd
@@ -0,0 +1,486 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://www.ericsson.com/is/isco/mim/2.0" xmlns="http://www.ericsson.com/is/isco/mim/2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
+ <!--
+ ============================================================================
+ %CCaseFile: mim.xsd %
+ %CCaseRev: /main/P4B/1 %
+ %CCaseDate: 2007-05-29 %
+ %CCaseDocNo: 22/155 19-CNA 113 082 Ux %
+ %Rev: Error in Revision! %
+ Author: EAB/AUL/IS Siri Hansen
+
+ ============================================================================
+
+ Copyright (c) Ericsson AB 2006-2007 All rights reserved.
+
+ The information in this document is the property of Ericsson.
+
+ Except as specifically authorized in writing by Ericsson, the
+ receiver of this document shall keep the information contained
+ herein confidential and shall protect the same in whole or in
+ part from disclosure and dissemination to third parties.
+
+ Disclosure and disseminations to the receivers employees shall
+ only be made on a strict need to know basis.
+ -->
+ <!-- Common -->
+ <xs:element name="description" type="xs:string"/>
+ <xs:element name="extension">
+ <xs:complexType>
+ <xs:group minOccurs="0" maxOccurs="unbounded" ref="anyElement"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:attributeGroup name="anyAttribute">
+ <xs:anyAttribute processContents="skip"/>
+ </xs:attributeGroup>
+ <xs:group name="anyElement">
+ <xs:sequence>
+ <xs:any processContents="skip"/>
+ </xs:sequence>
+ </xs:group>
+ <!-- Mim definition -->
+ <xs:element name="mim">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="topClass"/>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:group ref="dataTypeDef"/>
+ <xs:element ref="exception"/>
+ </xs:choice>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="class"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="relationship"/>
+ </xs:sequence>
+ <xs:attribute name="version"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="topClass">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="sortPriority"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ <xs:attribute name="minOccurs"/>
+ <xs:attribute name="maxOccurs"/>
+ </xs:complexType>
+ </xs:element>
+ <!-- MO class definition -->
+ <xs:element name="class">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="default_access"/>
+ <xs:choice>
+ <xs:sequence>
+ <xs:element ref="singleton"/>
+ <xs:element minOccurs="0" ref="systemCreated"/>
+ <xs:element minOccurs="0" ref="readOnly"/>
+ <xs:group minOccurs="0" maxOccurs="unbounded" ref="dataTypeDef"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="attribute"/>
+ </xs:sequence>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="systemCreated"/>
+ <xs:element minOccurs="0" ref="readOnly"/>
+ <xs:group minOccurs="0" maxOccurs="unbounded" ref="dataTypeDef"/>
+ <xs:element maxOccurs="unbounded" ref="attribute"/>
+ </xs:sequence>
+ </xs:choice>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="action"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[A-Z][A-Za-z0-9]*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="singleton">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="systemCreated">
+ <xs:complexType/>
+ </xs:element>
+ <!-- Relations -->
+ <xs:element name="relationship">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:element ref="containment"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="containment">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="parent"/>
+ <xs:element ref="child"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="parent" type="hasClass"/>
+ <xs:element name="child">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="hasClass">
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="cardinality"/>
+ <xs:element minOccurs="0" ref="sortPriority"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="sortPriority" type="xs:int"/>
+ <xs:element name="cardinality" type="rangeType"/>
+ <xs:complexType name="hasClass">
+ <xs:sequence>
+ <xs:element ref="hasClass"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="hasClass">
+ <xs:complexType>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <!-- Data types -->
+ <xs:element name="simple_type" abstract="true" substitutionGroup="type"/>
+ <xs:element name="type" abstract="true"/>
+ <!-- For attributes, parameters and exceptions -->
+ <xs:group name="dataType">
+ <xs:sequence>
+ <xs:element name="dataType" nillable="true">
+ <xs:complexType>
+ <xs:choice>
+ <xs:element ref="type" minOccurs="0"/>
+ <xs:element ref="xs_list" minOccurs="0"/>
+ </xs:choice>
+ <xs:attribute name="name.ref" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:group>
+ <xs:group name="simpleDataType">
+ <xs:sequence>
+ <xs:element name="dataType" nillable="true">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="simple_type" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="name.ref" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:group>
+ <xs:group name="dataTypeDef">
+ <xs:sequence>
+ <xs:element name="dataType">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:choice>
+ <xs:element ref="type"/>
+ <xs:element ref="xs_list"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:group>
+ <!-- For actions -->
+ <xs:element name="returnType">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:choice>
+ <xs:element ref="void"/>
+ <xs:group ref="dataType"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <!-- Return data types -->
+ <xs:element name="void">
+ <xs:complexType/>
+ </xs:element>
+ <!-- Primitive data types -->
+ <xs:complexType name="stringRestrictionType">
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="lengthRange"/>
+ <xs:element minOccurs="0" ref="validValues"/>
+ <xs:element minOccurs="0" ref="pattern"/>
+ <xs:element minOccurs="0" ref="defaultValue"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="dateTimeRestrictionType">
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="range"/>
+ <xs:element minOccurs="0" ref="validValues"/>
+ <xs:element minOccurs="0" ref="pattern"/>
+ <xs:element minOccurs="0" ref="defaultValue"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="numRestrictionType">
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="range"/>
+ <xs:element minOccurs="0" ref="defaultValue"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="boolean" substitutionGroup="simple_type">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="defaultValue"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="dateTime" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="float" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="integer" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="string" type="stringRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="pattern" type="xs:string"/>
+ <xs:element name="validValues">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" ref="value"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="value">
+ <xs:complexType>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="lengthRange" type="rangeType"/>
+ <xs:element name="range" type="rangeType"/>
+ <xs:complexType name="rangeType">
+ <xs:sequence>
+ <xs:element name="min" type="xs:string" minOccurs="0"/>
+ <xs:element name="max" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="defaultValue" type="xs:string"/>
+ <!-- Struct data type -->
+ <xs:element name="struct" substitutionGroup="type">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" ref="structMember"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="structMember">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:group ref="dataType"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <!-- List data type -->
+ <xs:element name="xs_list">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:group ref="simpleDataType"/>
+ <xs:element minOccurs="0" ref="lengthRange"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <!-- MoRef data type -->
+ <xs:element name="moRef" substitutionGroup="simple_type">
+ <xs:complexType>
+ <xs:attribute name="name" use="required">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[A-Z][A-Za-z0-9]*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ <!-- Attribute -->
+ <xs:element name="attribute">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="default_access"/>
+ <xs:group ref="dataType"/>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="initialValue"/>
+ <xs:element ref="pmData"/>
+ <xs:choice>
+ <xs:choice>
+ <xs:element ref="key"/>
+ <xs:element ref="readOnly"/>
+ </xs:choice>
+ <xs:choice>
+ <xs:choice>
+ <xs:element ref="readOnly"/>
+ <xs:choice>
+ <xs:element ref="mandatory"/>
+ <xs:element ref="restricted"/>
+ </xs:choice>
+ </xs:choice>
+ <xs:element ref="nonPersistent"/>
+ </xs:choice>
+ </xs:choice>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="name" use="required">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[a-z][a-zA-Z0-9]*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="initialValue" type="xs:string"/>
+ <xs:element name="key">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="mandatory">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="nonPersistent">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="pmData">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="extension"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="readOnly">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="restricted">
+ <xs:complexType/>
+ </xs:element>
+ <!-- Action -->
+ <xs:element name="action">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="default_access"/>
+ <xs:element ref="returnType"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="parameter"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="raisesException"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[a-z][a-zA-Z0-9]*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="parameter">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:group ref="dataType"/>
+ <xs:element minOccurs="0" ref="initialValue"/>
+ <xs:element minOccurs="0" ref="isOptional"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="isOptional">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="exception">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="exceptionParameter"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="exceptionParameter">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:group ref="dataType"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="raisesException">
+ <xs:complexType>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- xs types, introduced in IS 2.0 -->
+ <xs:element name="xs_normalizedString" type="stringRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_token" type="stringRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_string" type="stringRestrictionType" substitutionGroup="simple_type"/>
+
+ <xs:element name="xs_base64Binary" type="stringRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_hexBinary" type="stringRestrictionType" substitutionGroup="simple_type"/>
+
+ <xs:element name="xs_integer" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_positiveInteger" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_negativeInteger" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_nonNegativeInteger" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_nonPositiveInteger" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_long" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_unsignedLong" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_int" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_unsignedInt" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_short" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_unsignedShort" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_byte" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_unsignedByte" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_decimal" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_float" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_double" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_boolean" type="numRestrictionType" substitutionGroup="simple_type"/>
+
+ <xs:element name="xs_duration" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_dateTime" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_date" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_time" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_gYear" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_gYearMonth" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_gMonth" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_gMonthDay" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_gDay" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+
+ <xs:element name="xs_QName" type="stringRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_Name" type="stringRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_NCName" type="stringRestrictionType" substitutionGroup="simple_type"/>
+
+ <xs:element name="xs_anyURI" type="stringRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_language" type="stringRestrictionType" substitutionGroup="simple_type"/>
+
+ <!-- Authorization information -->
+ <xs:element name="default_access">
+ <xs:complexType>
+ <xs:attribute name="role" type="xs:token" use="required"/>
+ <xs:attribute name="permissions" use="required">
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:pattern value="[rwx]{3}"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/mim2.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/mim2.xsd
new file mode 100644
index 0000000000..da6ff6bd7d
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/mim2.xsd
@@ -0,0 +1,506 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema targetNamespace="http://www.ericsson.com/is/isco/mim/2.0" xmlns="http://www.ericsson.com/is/isco/mim/2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
+ <!--
+ ============================================================================
+ %CCaseFile: mim.xsd %
+ %CCaseRev: /main/P4B/3 %
+ %CCaseDate: 2007-06-07 %
+ %CCaseDocNo: 22/155 19-CNA 113 082 Ux %
+ %Rev: Error in Revision! %
+ Author: EAB/AUL/IS Siri Hansen
+
+ ============================================================================
+
+ Copyright (c) Ericsson AB 2006-2007 All rights reserved.
+
+ The information in this document is the property of Ericsson.
+
+ Except as specifically authorized in writing by Ericsson, the
+ receiver of this document shall keep the information contained
+ herein confidential and shall protect the same in whole or in
+ part from disclosure and dissemination to third parties.
+
+ Disclosure and disseminations to the receivers employees shall
+ only be made on a strict need to know basis.
+ -->
+ <!-- Common -->
+ <xs:element name="description" type="xs:string"/>
+ <xs:element name="extension">
+ <xs:complexType>
+ <xs:group minOccurs="0" maxOccurs="unbounded" ref="anyElement"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:attributeGroup name="anyAttribute">
+ <xs:anyAttribute processContents="skip"/>
+ </xs:attributeGroup>
+ <xs:group name="anyElement">
+ <xs:sequence>
+ <xs:any processContents="skip"/>
+ </xs:sequence>
+ </xs:group>
+ <!-- Mim definition -->
+ <xs:element name="mim">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="topClass"/>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:group ref="dataTypeDef"/>
+ <xs:element ref="exception"/>
+ </xs:choice>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="class"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="relationship"/>
+ </xs:sequence>
+ <xs:attribute name="version"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="topClass">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="sortPriority"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ <xs:attribute name="minOccurs"/>
+ <xs:attribute name="maxOccurs"/>
+ </xs:complexType>
+ </xs:element>
+ <!-- MO class definition -->
+ <xs:element name="class">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="default_access"/>
+ <xs:choice>
+ <xs:sequence>
+ <xs:element ref="singleton"/>
+ <xs:element minOccurs="0" ref="systemCreated"/>
+ <xs:element minOccurs="0" ref="readOnly"/>
+ <xs:group minOccurs="0" maxOccurs="unbounded" ref="dataTypeDef"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="attribute"/>
+ </xs:sequence>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="systemCreated"/>
+ <xs:element minOccurs="0" ref="readOnly"/>
+ <xs:group minOccurs="0" maxOccurs="unbounded" ref="dataTypeDef"/>
+ <xs:element maxOccurs="unbounded" ref="attribute"/>
+ </xs:sequence>
+ </xs:choice>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="action"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[A-Z][A-Za-z0-9]*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="singleton">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="systemCreated">
+ <xs:complexType/>
+ </xs:element>
+ <!-- Relations -->
+ <xs:element name="relationship">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:element ref="containment"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="containment">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="parent"/>
+ <xs:element ref="child"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="parent" type="hasClass"/>
+ <xs:element name="child">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="hasClass">
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="cardinality"/>
+ <xs:element minOccurs="0" ref="sortPriority"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="sortPriority" type="xs:int"/>
+ <xs:element name="cardinality" type="rangeType"/>
+ <xs:complexType name="hasClass">
+ <xs:sequence>
+ <xs:element ref="hasClass"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="hasClass">
+ <xs:complexType>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <!-- Data types -->
+ <xs:element name="simple_type" abstract="true" substitutionGroup="type"/>
+ <xs:element name="type" abstract="true"/>
+ <!-- For attributes, parameters and exceptions -->
+ <xs:group name="dataType">
+ <xs:sequence>
+ <xs:element name="dataType" nillable="true">
+ <xs:complexType>
+ <xs:choice>
+ <xs:element ref="type" minOccurs="0"/>
+ <xs:element ref="xs_list" minOccurs="0"/>
+ </xs:choice>
+ <xs:attribute name="name.ref" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:group>
+ <xs:group name="simpleDataType">
+ <xs:sequence>
+ <xs:element name="dataType" nillable="true">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="simple_type" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="name.ref" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:group>
+ <xs:group name="dataTypeDef">
+ <xs:sequence>
+ <xs:element name="dataType">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:choice>
+ <xs:element ref="type"/>
+ <xs:element ref="xs_list"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:group>
+ <!-- For actions -->
+ <xs:element name="returnType">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:choice>
+ <xs:element ref="void"/>
+ <xs:group ref="dataType"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <!-- Return data types -->
+ <xs:element name="void">
+ <xs:complexType/>
+ </xs:element>
+ <!-- Primitive data types -->
+ <xs:complexType name="stringRestrictionType">
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="lengthRange"/>
+ <xs:element minOccurs="0" ref="validValues"/>
+ <xs:element minOccurs="0" ref="pattern"/>
+ <xs:element minOccurs="0" ref="defaultValue"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="dateTimeRestrictionType">
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="range"/>
+ <xs:element minOccurs="0" ref="validValues"/>
+ <xs:element minOccurs="0" ref="pattern"/>
+ <xs:element minOccurs="0" ref="defaultValue"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="numRestrictionType">
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="range"/>
+ <xs:element minOccurs="0" ref="defaultValue"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="boolean" substitutionGroup="simple_type">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="defaultValue"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="dateTime" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="float" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="integer" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="string" type="stringRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="pattern" type="xs:string"/>
+ <xs:element name="validValues">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" ref="value"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="value">
+ <xs:complexType>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="lengthRange" type="rangeType"/>
+ <xs:element name="range" type="rangeType"/>
+ <xs:complexType name="rangeType">
+ <xs:sequence>
+ <xs:element name="min" type="xs:string" minOccurs="0"/>
+ <xs:element name="max" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="defaultValue" type="xs:string"/>
+ <!-- Struct data type -->
+ <xs:element name="struct" substitutionGroup="type">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" ref="structMember"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="structMember">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:group ref="dataType"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <!-- List data type -->
+ <xs:element name="xs_list">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:group ref="simpleDataType"/>
+ <xs:element minOccurs="0" ref="lengthRange"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <!-- MoRef data type -->
+ <xs:element name="moRef" substitutionGroup="simple_type">
+ <xs:complexType>
+ <xs:attribute name="name" use="required">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[A-Z][A-Za-z0-9]*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ <!-- Attribute -->
+ <xs:element name="attribute">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="default_access"/>
+ <xs:group ref="dataType"/>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="initialValue"/>
+ <xs:element ref="pmData"/>
+ <xs:choice>
+ <xs:choice>
+ <xs:element ref="key"/>
+ <xs:element ref="readOnly"/>
+ </xs:choice>
+ <xs:choice>
+ <xs:choice>
+ <xs:element ref="readOnly"/>
+ <xs:choice>
+ <xs:element ref="mandatory"/>
+ <xs:element ref="restricted"/>
+ </xs:choice>
+ </xs:choice>
+ <xs:element ref="nonPersistent"/>
+ </xs:choice>
+ </xs:choice>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="name" use="required">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[a-z][a-zA-Z0-9]*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="initialValue" type="xs:string"/>
+ <xs:element name="key">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="mandatory">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="nonPersistent">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="pmData">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="readOnly">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="restricted">
+ <xs:complexType/>
+ </xs:element>
+ <!-- Action -->
+ <xs:element name="action">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="default_access"/>
+ <xs:element ref="returnType"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="parameter"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="raisesException"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[a-z][a-zA-Z0-9]*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="parameter">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:group ref="dataType"/>
+ <xs:element minOccurs="0" ref="initialValue"/>
+ <xs:element minOccurs="0" ref="isOptional"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="isOptional">
+ <xs:complexType/>
+ </xs:element>
+ <xs:element name="exception">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="exceptionParameter"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="exceptionParameter">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="description"/>
+ <xs:element minOccurs="0" ref="extension"/>
+ <xs:group ref="dataType"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="raisesException">
+ <xs:complexType>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- xs types, introduced in IS 2.0 -->
+ <xs:element name="xs_normalizedString" type="stringRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_token" type="stringRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_string" type="stringRestrictionType" substitutionGroup="simple_type"/>
+
+ <xs:element name="xs_base64Binary" type="stringRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_hexBinary" type="stringRestrictionType" substitutionGroup="simple_type"/>
+
+ <xs:element name="xs_integer" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_positiveInteger" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_negativeInteger" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_nonNegativeInteger" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_nonPositiveInteger" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_long" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_unsignedLong" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_int" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_unsignedInt" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_short" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_unsignedShort" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_byte" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_unsignedByte" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_decimal" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_float" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_double" type="numRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_boolean" substitutionGroup="simple_type">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="defaultValue"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="xs_duration" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_dateTime" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_date" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_time" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_gYear" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_gYearMonth" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_gMonth" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_gMonthDay" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_gDay" type="dateTimeRestrictionType" substitutionGroup="simple_type"/>
+
+ <xs:element name="xs_QName" type="stringRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_Name" type="stringRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_NCName" type="stringRestrictionType" substitutionGroup="simple_type"/>
+
+ <xs:element name="xs_anyURI" type="stringRestrictionType" substitutionGroup="simple_type"/>
+ <xs:element name="xs_language" type="stringRestrictionType" substitutionGroup="simple_type"/>
+
+ <!-- Password type -->
+ <!-- This is a string, which will not be visible in the CLI or in any logs. -->
+ <!-- The 'encrypt' attribute indicates if the string shall be sent encrypted -->
+ <!-- or in clear text to the blade system -->
+ <xs:element name="password" substitutionGroup="simple_type">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="lengthRange"/>
+ </xs:sequence>
+ <xs:attribute name="enrypt" type="xs:boolean" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- Authorization information -->
+ <xs:element name="default_access">
+ <xs:complexType>
+ <xs:attribute name="role" type="xs:token" use="required"/>
+ <xs:attribute name="permissions" use="required">
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:pattern value="[rwx]{3}"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/nc.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/nc.xsd
new file mode 100644
index 0000000000..60a320a61e
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/nc.xsd
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.ericsson.com/is/isco/nc" xmlns="http://www.ericsson.com/is/isco/nc">
+ <xsd:attribute name="operation">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:normalizedString">
+ <xsd:whiteSpace value="collapse"/>
+ <xsd:enumeration value="merge"/>
+ <xsd:enumeration value="create"/>
+ <xsd:enumeration value="replace"/>
+ <xsd:enumeration value="delete"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+</xsd:schema>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/swm_mim.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/swm_mim.xml
new file mode 100644
index 0000000000..90afcb2b68
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/sis/swm_mim.xml
@@ -0,0 +1,881 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+
+<!--
+
+Copyright (C) Ericsson AB 2006 All rights reserved.
+
+The information in this document is the property of Ericsson.
+
+Except as specifically authorized in writing by Ericsson, the
+receiver of this document shall keep the information contained
+herein confidential and shall protext the same in whole or in part
+from disclosure and dissemination to third parties.
+
+Disclosure and disseminations to the receivers employees shall
+only be made on a strict need to know basis.
+
+-->
+
+
+<!-- MIM file for SWM -->
+
+
+ <mim xmlns="http://www.ericsson.com/is/isco/mim/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ericsson.com/is/isco/mim/2.0 /vobs/isac/sis/OAM_CRA1190047_1/CCS_CNA113082/doc/15519/mim.xsd ">
+
+ <!--___ Data types ________________________________ -->
+
+ <dataType name="SwmMatchStrategy">
+ <description>
+ Interpretation of given filename and path .
+ </description>
+ <string>
+ <validValues>
+ <value name="exact"/>
+ <value name="prefix"/>
+ <value name="unknown"/>
+ </validValues>
+ <!--defaultValue>exact</defaultValue-->
+ </string>
+ </dataType>
+
+ <dataType name="SwmDownloadStrategy">
+ <description>
+ Interpretation according to existing files.
+ </description>
+ <string>
+ <validValues>
+ <value name="onlyIfMissing"/>
+ <value name="always"/>
+ <value name="unknown"/>
+ </validValues>
+ <!--defaultValue>onlyIfMissing</defaultValue-->
+ </string>
+ </dataType>
+
+ <dataType name="ContainerType">
+ <description>
+ Type of a load module container.
+ </description>
+ <string>
+ <validValues>
+ <value name="bladeSystemInformation"/>
+ <value name="bladeInformation"/>
+ <value name="application"/>
+ <value name="rootFileSystem"/>
+ <value name="kernel"/>
+ <value name="correction"/>
+ </validValues>
+ <!--defaultValue>bladeSystemInformation</defaultValue-->
+ </string>
+ </dataType>
+
+
+ <dataType name="SwgStatus">
+ <description>
+ Indicates status of software groups. A software group is
+ complete if all included load module containers have been
+ downloaded and unpacked correctly. A software group is inconsistent
+ if the checksums of the load module containers do not match the
+ information in the system information CXP, or if the XML
+ data could not be registered.
+ </description>
+ <string>
+ <validValues>
+ <value name="complete"/>
+ <value name="incomplete"/>
+ <value name="inconsistent"/>
+ </validValues>
+ <!--defaultValue>incomplete</defaultValue-->
+ </string>
+ </dataType>
+
+ <dataType name="JobData">
+ <description>
+ Data to specify job progress, during its execution.
+ </description>
+ <struct>
+ <structMember name="jobDateOrdered">
+ <dataType><dateTime/></dataType>
+ </structMember>
+ <structMember name="jobStatus">
+ <description>
+ Indicator of job status.
+ A job should be started immediately, but could be postponed
+ if the total load on the system would become too high.
+ </description>
+ <dataType>
+ <string>
+ <validValues>
+ <value name="notStarted"/>
+ <value name="ongoing"/>
+ <value name="complete"/>
+ </validValues>
+ <!--defaultValue>notStarted</defaultValue-->
+ </string>
+ </dataType>
+ </structMember>
+ <structMember name="jobResult">
+ <description>
+ Possible results of a job action.
+ </description>
+ <dataType>
+ <string>
+ <validValues>
+ <value name="ok"/>
+ <value name="inputError"/>
+ <value name="executionError"/>
+ <value name="unknown"/>
+ </validValues>
+ <!--defaultValue>ok</defaultValue-->
+ </string>
+ </dataType>
+ </structMember>
+ <structMember name="jobInfo">
+ <dataType><string/></dataType>
+ </structMember>
+ <structMember name="jobProgress">
+ <dataType name.ref="IsTypes:Unsigned32"/>
+ </structMember>
+ <structMember name="jobLastStep">
+ <dataType name.ref="IsTypes:Unsigned32"/>
+ </structMember>
+ <structMember name="jobProgressReport">
+ <dataType><boolean/></dataType>
+ </structMember>
+ </struct>
+ </dataType><!-- JobData -->
+
+ <dataType name="FTPData">
+ <description>
+ Data to specify FTP server info, such as host, user,
+ password and path, to locate correct files or destination
+ for files.
+ </description>
+ <struct>
+ <structMember name="host">
+ <dataType><string/></dataType>
+ </structMember>
+ <structMember name="user">
+ <dataType><string/></dataType>
+ </structMember>
+ <structMember name="password">
+ <dataType><string/></dataType>
+ </structMember>
+ <structMember name="path">
+ <description>
+ Absolute path including filename.
+ </description>
+ <dataType><string/></dataType>
+ </structMember>
+ </struct>
+ </dataType><!-- FTPData -->
+
+ <dataType name="BladeUgSpecification">
+ <description>
+ Specification of a blade when an upgrade job is ordered for a
+ specific blade. This data always belongs to and is included in
+ an upgrade job for a blade system.
+ </description>
+ <struct>
+ <structMember name="bladeSubrack">
+ <dataType name.ref="IsTypes:Unsigned32"/>
+ </structMember>
+ <structMember name="bladeSlot">
+ <dataType name.ref="IsTypes:Unsigned32"/>
+ </structMember>
+ <structMember name="bladeSwgProdNr">
+ <dataType><string/></dataType>
+ </structMember>
+ <structMember name="bladeSwgVersion">
+ <dataType><string/></dataType>
+ </structMember>
+ </struct>
+ </dataType> <!-- BladeUgSpecification -->
+
+ <!--___ CLASSes for tables (no STRUCTs) ________________ -->
+
+ <!-- Inventory Classes -->
+
+ <class name="SoftwareDeliveryPackage">
+ <description>
+ Container of files of data, or binary executables, needed to run the system.
+ </description>
+ <systemCreated/>
+ <readOnly/>
+ <attribute name="prodNr">
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+ <attribute name="version"> <dataType><string/></dataType>
+ <key/>
+ </attribute>
+ <attribute name="name">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="type">
+ <dataType name.ref="ContainerType">
+ </dataType>
+ <readOnly/>
+ </attribute>
+ <action name="delete">
+ <description>
+ Action to delete SoftwareDeliveryPackage.
+ </description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ </class> <!-- SoftwareDeliveryPackage -->
+
+ <class name="SoftwareGroup">
+ <description>
+ Contains one or more SoftwareDeliveryPackage.
+ </description>
+ <systemCreated/>
+ <readOnly/>
+ <attribute name="prodNr">
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+ <attribute name="version">
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+ <attribute name="name">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="systemProdNr">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="systemVersion">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="systemName">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="integratedSystemProdNr">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="integratedSystemVersion">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="integratedSystemName">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="relatedCXPs">
+ <dataType>
+ <xs_list>
+ <dataType>
+ <moRef name="SoftwareDeliveryPackage"/>
+ </dataType>
+ </xs_list>
+ </dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="status">
+ <dataType name.ref="SwgStatus">
+ </dataType>
+ <readOnly/>
+ </attribute>
+ <action name="delete">
+ <description>
+ Action to delete Software Group.
+ </description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ </class> <!-- SoftwareGroup -->
+
+ <class name="LocalBackup">
+ <description>
+ All available backups locally stored.
+ </description>
+ <systemCreated/>
+ <readOnly/>
+ <attribute name="backupId">
+ <dataType name.ref="IsTypes:Unsigned32">
+ </dataType>
+ <key/>
+ </attribute>
+ <attribute name="name">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="bladeSystem">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="date">
+ <dataType>
+ <dateTime/>
+ </dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="size">
+ <dataType name.ref="IsTypes:Unsigned32">
+ </dataType>
+ <readOnly/>
+ </attribute>
+ <action name="exportBackup">
+ <description>
+ Action to export backup file to FTP server from
+ local disk storage. An instance of the class
+ Software/Jobs/Backup/Export is created as a log of this
+ action.
+ </description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="jobId">
+ <dataType><string/></dataType>
+ </parameter>
+ <parameter name="host">
+ <dataType><string/></dataType>
+ </parameter>
+ <parameter name="user">
+ <dataType><string/></dataType>
+ </parameter>
+ <parameter name="password">
+ <dataType><string/></dataType>
+ </parameter>
+ <parameter name="path">
+ <description>
+ Absolute path including filename.
+ </description>
+ <dataType><string/></dataType>
+ </parameter>
+ </action>
+ <action name="delete">
+ <description>
+ Action to delete backup.
+ </description>
+ <returnType>
+ <void/>
+ </returnType>
+ </action>
+ </class> <!-- LocalBackup -->
+
+ <class name="Alarm">
+ <description>
+ Information and cause of all currently active software configuration alarms.
+ </description>
+ <systemCreated/>
+ <readOnly/>
+ <attribute name="id">
+ <dataType name.ref="IsTypes:Unsigned32"/>
+ <key/>
+ </attribute>
+ <attribute name="bladeSystem">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="cause">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="info">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ </class> <!-- Alarm -->
+
+
+ <!-- Jobs Classes -->
+
+ <class name="DownloadFile">
+ <description>
+ This MO contains information about requested, ongoing,
+ and completed software file download jobs. To start a
+ download job the operator calls an action Inventory class,
+ and a new instance of this MO is created.
+ For load regulating reasons a requested job may not start
+ immediately.
+ </description>
+ <systemCreated/>
+ <readOnly/>
+ <attribute name="jobId">
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+ <attribute name="jobData">
+ <dataType name.ref="JobData"/>
+ <readOnly/>
+ </attribute>
+ <attribute name="ftpData">
+ <dataType name.ref="FTPData"/>
+ <readOnly/>
+ </attribute>
+ <attribute name="matchStrategy">
+ <dataType name.ref="SwmMatchStrategy">
+ </dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="downloadStrategy">
+ <dataType name.ref="SwmDownloadStrategy">
+ </dataType>
+ <readOnly/>
+ </attribute>
+ </class><!-- DownloadFile -->
+
+ <class name="Upgrade">
+ <description>
+ This MO handles upgrade jobs towards the system. The operator
+ may specify a specific blade to run the upgrade on, instead of
+ running an upgrade on the entire blade system.
+ </description>
+ <systemCreated/>
+ <readOnly/>
+ <attribute name="jobId">
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+ <attribute name="jobData">
+ <dataType name.ref="JobData"/>
+ <readOnly/>
+ </attribute>
+ <attribute name="bladeSystem">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="swgProdNr">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="swgVersion">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="cxrProdNr">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="cxrVersion">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="maxTime">
+ <description>
+ The maximum time allowed for the SW Upgrade
+ job to finish. After this time, the job will be interrupted.
+ The value 0 means that MaxTime will be given the
+ timer value registered with the Blade System Software Group
+ Version. If no such value has been registered,
+ MaxTime will be given a system default timer value.
+ </description>
+ <dataType name.ref="IsTypes:Unsigned32">
+ </dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="bladeUgSpecification">
+ <dataType name.ref="BladeUgSpecification"/>
+ <readOnly/>
+ </attribute>
+ </class><!-- Upgrade -->
+
+
+
+ <!-- Backup Classes -->
+
+ <class name="Create">
+ <description>
+ This MO handles creation of backups of the system.
+ </description>
+ <systemCreated/>
+ <readOnly/>
+ <attribute name="jobId">
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+ <attribute name="jobData">
+ <dataType name.ref="JobData"/>
+ <readOnly/>
+ </attribute>
+ <attribute name="backupId">
+ <dataType name.ref="IsTypes:Unsigned32">
+ </dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="targetBladeSystem">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="backupName">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ </class><!-- Create -->
+
+ <class name="Restore">
+ <description>
+ This MO handles restore of backups of the system.
+ </description>
+ <systemCreated/>
+ <readOnly/>
+ <attribute name="jobId">
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+ <attribute name="jobData">
+ <dataType name.ref="JobData"/>
+ <readOnly/>
+ </attribute>
+ <attribute name="backupId">
+ <dataType name.ref="IsTypes:Unsigned32">
+ </dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="targetBladeSystem">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="backupName">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ </class><!-- Restore -->
+
+ <class name="Import">
+ <description>
+ This MO handles import of backup files from the FTP server.
+ The backup file is stored locally, but not loaded into the system.
+ </description>
+ <systemCreated/>
+ <readOnly/>
+ <attribute name="jobId">
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+ <attribute name="jobData">
+ <dataType name.ref="JobData"/>
+ <readOnly/>
+ </attribute>
+ <attribute name="ftpData">
+ <dataType name.ref="FTPData"/>
+ <readOnly/>
+ </attribute>
+ </class><!-- Import -->
+
+ <class name="Export">
+ <description>
+ This MO handles export of locally stored backup files to
+ the FTP server.
+ </description>
+ <systemCreated/>
+ <readOnly/>
+ <attribute name="jobId">
+ <dataType><string/></dataType>
+ <key/>
+ </attribute>
+ <attribute name="jobData">
+ <dataType name.ref="JobData"/>
+ <readOnly/>
+ </attribute>
+ <attribute name="ftpData">
+ <dataType name.ref="FTPData"/>
+ <readOnly/>
+ </attribute>
+ <attribute name="backupId">
+ <dataType name.ref="IsTypes:Unsigned32">
+ </dataType>
+ <readOnly/>
+ </attribute>
+ <attribute name="backupName">
+ <dataType><string/></dataType>
+ <readOnly/>
+ </attribute>
+ </class><!-- Export -->
+
+
+ <!--____ CLASSes for hierarchic relations __________________ -->
+
+ <class name="Software">
+ <description>
+ Describes the Software management service
+ in the Integrated Site services management functional area (MFA).
+ </description>
+ <singleton/>
+ </class> <!-- software -->
+
+ <class name="Inventory">
+ <description>
+ System created data for information and overview.
+ Some data is created as a result of an action called by the
+ operator.
+ </description>
+ <singleton/>
+ <action name="downloadFile">
+ <description>
+ Action to download file/s from FTP server to
+ local disk storage. An instance of the MO class
+ Software/Jobs/DownloadFile is created as a log of this
+ action.
+ </description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="jobId">
+ <dataType><string/></dataType>
+ </parameter>
+ <parameter name="host">
+ <dataType><string/></dataType>
+ </parameter>
+ <parameter name="user">
+ <dataType><string/></dataType>
+ </parameter>
+ <parameter name="password">
+ <dataType><string/></dataType>
+ </parameter>
+ <parameter name="path">
+ <description>
+ Absolute path including filename.
+ </description>
+ <dataType><string/></dataType>
+ </parameter>
+ <parameter name="matchStrategy">
+ <dataType name.ref="SwmMatchStrategy"></dataType>
+ </parameter>
+ <parameter name="downloadStrategy">
+ <dataType name.ref="SwmDownloadStrategy"></dataType>
+ </parameter>
+ </action>
+ <action name="importBackup">
+ <description>
+ Action to import backup file from FTP server to
+ to local disk storage. An instance of the MO class
+ Software/Jobs/Backup/Import is created as a log of this
+ action.
+ </description>
+ <returnType>
+ <void/>
+ </returnType>
+ <parameter name="jobId">
+ <dataType><string/></dataType>
+ </parameter>
+ <parameter name="host">
+ <dataType><string/></dataType>
+ </parameter>
+ <parameter name="user">
+ <dataType><string/></dataType>
+ </parameter>
+ <parameter name="password">
+ <dataType><string/></dataType>
+ </parameter>
+ <parameter name="path">
+ <description>
+ Absolute path including filename.
+ </description>
+ <dataType><string/></dataType>
+ </parameter>
+ </action>
+ </class> <!-- Inventory -->
+
+ <class name="Jobs">
+ <description>
+ Subclass to top class Software. Parent of
+ Jobs classes:
+ DownloadFile,
+ Upgrade,
+ Backup.
+ Contains system created data through ordered job actions.
+ </description>
+ <singleton/>
+ </class> <!-- Jobs -->
+
+ <class name="Backup">
+ <description>
+ Subclass to class Jobs. Parent of
+ Jobs classes:
+ Create,
+ Restore
+ Import,
+ Export.
+<!-- CreateAndExport,
+ ImportAndRestore.-->
+ Contains system created data through ordered backup job actions.
+ </description>
+ <singleton/>
+ </class> <!-- Backup -->
+
+
+ <!--____ RELATIONSHIPs ______________________________-->
+
+ <!-- Top Class Relations -->
+ <relationship name="SwmTop">
+ <containment>
+ <parent>
+ <hasClass name="top_mim:Is"/>
+ </parent>
+ <child>
+ <hasClass name="Software"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Software_to_Inventory">
+ <containment>
+ <parent>
+ <hasClass name="Software"/>
+ </parent>
+ <child>
+ <hasClass name="Inventory"/>
+ <cardinality>
+ <min>1</min>
+ <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Software_to_Jobs">
+ <containment>
+ <parent>
+ <hasClass name="Software"/>
+ </parent>
+ <child>
+ <hasClass name="Jobs"/>
+ <cardinality>
+ <min>1</min>
+ <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <!-- Inventory Class Relations -->
+ <relationship name="Inventory_to_SoftwareDeliveryPackage">
+ <containment>
+ <parent>
+ <hasClass name="Inventory"/>
+ </parent>
+ <child>
+ <hasClass name="SoftwareDeliveryPackage"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Inventory_to_SoftwareGroup">
+ <containment>
+ <parent>
+ <hasClass name="Inventory"/>
+ </parent>
+ <child>
+ <hasClass name="SoftwareGroup"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Inventory_to_LocalBackup">
+ <containment>
+ <parent>
+ <hasClass name="Inventory"/>
+ </parent>
+ <child>
+ <hasClass name="LocalBackup"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Inventory_to_Alarm">
+ <containment>
+ <parent>
+ <hasClass name="Inventory"/>
+ </parent>
+ <child>
+ <hasClass name="Alarm"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <!-- Jobs Class Relations -->
+ <relationship name="Jobs_to_DownloadFile">
+ <containment>
+ <parent>
+ <hasClass name="Jobs"/>
+ </parent>
+ <child>
+ <hasClass name="DownloadFile"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Jobs_to_Upgrade">
+ <containment>
+ <parent>
+ <hasClass name="Jobs"/>
+ </parent>
+ <child>
+ <hasClass name="Upgrade"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Jobs_to_Backup">
+ <containment>
+ <parent>
+ <hasClass name="Jobs"/>
+ </parent>
+ <child>
+ <hasClass name="Backup"/>
+ <cardinality>
+ <min>1</min>
+ <max>1</max>
+ </cardinality>
+ </child>
+ </containment>
+ </relationship>
+
+ <!-- Backup Class Relations -->
+ <relationship name="Backup_to_Create">
+ <containment>
+ <parent>
+ <hasClass name="Backup"/>
+ </parent>
+ <child>
+ <hasClass name="Create"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Backup_to_Restore">
+ <containment>
+ <parent>
+ <hasClass name="Backup"/>
+ </parent>
+ <child>
+ <hasClass name="Restore"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Backup_to_Import">
+ <containment>
+ <parent>
+ <hasClass name="Backup"/>
+ </parent>
+ <child>
+ <hasClass name="Import"/>
+ </child>
+ </containment>
+ </relationship>
+
+ <relationship name="Backup_to_Export">
+ <containment>
+ <parent>
+ <hasClass name="Backup"/>
+ </parent>
+ <child>
+ <hasClass name="Export"/>
+ </child>
+ </containment>
+ </relationship>
+ </mim>
+
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/small.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/small.xml
new file mode 100644
index 0000000000..b0358f467d
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/small.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<purchaseOrder
+ xmlns="small"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="small small.xsd"
+ orderDate="1999-10-20">
+This is the content of the element
+</purchaseOrder>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/small.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/small.xsd
new file mode 100644
index 0000000000..00d49db22d
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/small.xsd
@@ -0,0 +1,60 @@
+<xsd:schema
+ targetNamespace="small"
+ xmlns:sm="small"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Purchase order schema for Example.com.
+ Copyright 2000 Example.com. All rights reserved.
+ </xsd:documentation>
+ </xsd:annotation>
+
+ <xsd:element name="purchaseOrder" type="sm:PurchaseOrderType"/>
+
+ <xsd:element name="comment" type="xsd:string"/>
+
+ <xsd:complexType name="PurchaseOrderType" mixed="true">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="orderDate" type="xsd:date"/>
+ <xsd:attribute name="orderStatus" type="xsd:string" default="new"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+ <complexType name="own1">
+ <complexContent>
+ <restriction base="xsd:anyType">
+ <attribute name="number" type="xsd:integer"/>
+ <attribute name="quantity" type="xsd:positiveInteger"/>
+ </restriction>
+ </complexContent>
+ </complexType>
+
+ <complexType name="PartsType">
+ <sequence>
+ <element name="part" maxOccurs="unbounded">
+ <complexType>
+ <simpleContent>
+ <extension base="xsd:string">
+ <attribute name="number" type="xsd:integer"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+ </element>
+ </sequence>
+ </complexType>
+
+<simpleType name="listOfMyIntType">
+ <list itemType="xsd:integer"/>
+</simpleType>
+
+<simpleType name="SixUSStates">
+ <restriction base="sm:listOfMyIntType">
+ <length value="6"/>
+ </restriction>
+</simpleType>
+
+</xsd:schema>
+
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/ticket_7288.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/ticket_7288.xml
new file mode 100644
index 0000000000..9108e96bed
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/ticket_7288.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+ <IMSSubscription>
+ <PrivateID>[email protected]</PrivateID>
+ <ServiceProfile>
+ <PublicIdentity>
+ <BarringIndication>1</BarringIndication>
+ <Identity>sip:[email protected]</Identity>
+ </PublicIdentity>
+ <PublicIdentity>
+ <Identity>sip:[email protected]</Identity>
+ </PublicIdentity>
+ <InitialFilterCriteria>
+ <Priority>0</Priority>
+ <TriggerPoint>
+ <ConditionTypeCNF>1</ConditionTypeCNF>
+ <SPT>
+ <ConditionNegated>0</ConditionNegated>
+ <Group>0</Group>
+ <Method>INVITE</Method>
+ </SPT>
+ <SPT>
+ <ConditionNegated>0</ConditionNegated>
+ <Group>0</Group>
+ <Method>MESSAGE</Method>
+ </SPT>
+ <SPT>
+ <ConditionNegated>0</ConditionNegated>
+ <Group>0</Group>
+ <Method>SUBSCRIBE</Method>
+ </SPT>
+ <SPT>
+ <ConditionNegated>0</ConditionNegated>
+ <Group>1</Group>
+ <Method>INVITE</Method>
+ </SPT>
+ <SPT>
+ <ConditionNegated>0</ConditionNegated>
+ <Group>1</Group>
+ <Method>MESSAGE</Method>
+ </SPT>
+
+ <SPT>
+ <ConditionNegated>1</ConditionNegated>
+ <Group>1</Group>
+ <SIPHeader>
+ <Header>From</Header>
+ <Content>"joe"</Content>
+ </SIPHeader>
+ </SPT>
+ </TriggerPoint>
+ <ApplicationServer>
+ <ServerName>sip:[email protected]</ServerName>
+ </ApplicationServer>
+ </InitialFilterCriteria>
+ </ServiceProfile>
+ </IMSSubscription>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/ticket_8599.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/ticket_8599.xml
new file mode 100644
index 0000000000..1eacfc756e
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/ticket_8599.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+
+<persons>
+<person>lars thorsen</person>
+<person></person>
+</persons>
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/ticket_8599.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/ticket_8599.xsd
new file mode 100644
index 0000000000..977f043bb7
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/ticket_8599.xsd
@@ -0,0 +1,17 @@
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xs:element name="persons" type="p"/>
+
+ <xs:complexType name="p">
+ <xs:sequence>
+ <xs:element name="person" type="string" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+
+ <xs:simpleType name="string">
+ <xs:restriction base="xs:string">
+ </xs:restriction>
+ </xs:simpleType>
+
+</xs:schema> \ No newline at end of file
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/vehicle.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/vehicle.xml
new file mode 100644
index 0000000000..61aacbc8d0
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/vehicle.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0"?>
+<root>
+ <state>
+ <code>AL</code>
+ <vehicle plateNumber="1123" state="AL"/>
+ <vehicle plateNumber="1125" state="AK"/>
+ <vehicle plateNumber="1124" state="AL"/>
+ <vehicle plateNumber="1223" state="AL"/>
+ <vehicle plateNumber="1323" state="AL"/>
+ <vehicle plateNumber="1225" state="AS"/>
+ <vehicle plateNumber="1126" state="AZ"/>
+ <vehicle plateNumber="1127" state="AR"/>
+ <vehicle plateNumber="1128" state="FL"/>
+ <vehicle plateNumber="2341" state="FL"/>
+ <vehicle plateNumber="1129" state="FL"/>
+ <vehicle plateNumber="1133" state="FL"/>
+ <vehicle plateNumber="22123" state="MO"/>
+ <vehicle plateNumber="22124" state="MI"/>
+ <person>
+ <car regState="AL" regPlate="1123"/>
+ </person>
+ <person>
+ <car regState="AK" regPlate="1125"/>
+ </person>
+ <person>
+ <car regState="AL" regPlate="1124"/>
+ <car regState="AL" regPlate="1223"/>
+ </person>
+ <person>
+ <car regState="AL" regPlate="1323"/>
+ </person>
+ <person>
+ <car regState="AS" regPlate="1225"/>
+ </person>
+ <person>
+ <car regState="AZ" regPlate="1126"/>
+ </person>
+ <person>
+ <car regState="AR" regPlate="1127"/>
+ </person>
+ <person>
+ <car regState="FL" regPlate="2341"/>
+ </person>
+ <person>
+ <car regState="FL" regPlate="1128"/>
+ </person>
+ <person>
+ <car regState="FL" regPlate="1133"/>
+ </person>
+ <person>
+ <car regState="FL" regPlate="1129"/>
+ </person>
+ <person>
+ <car regState="MO" regPlate="22123"/>
+ </person>
+ <person>
+ <car regState="MI" regPlate="22124"/>
+ </person>
+ </state>
+ <state>
+ <code>CO</code>
+ <vehicle plateNumber="1123" state="AL"/>
+ <vehicle plateNumber="1120" state="AK"/>
+ <vehicle plateNumber="1124" state="AL"/>
+ <vehicle plateNumber="1221" state="AL"/>
+ <vehicle plateNumber="1323" state="AL"/>
+ <vehicle plateNumber="1223" state="AS"/>
+ <vehicle plateNumber="1126" state="AZ"/>
+ <vehicle plateNumber="1127" state="AR"/>
+ <vehicle plateNumber="1128" state="FL"/>
+ <vehicle plateNumber="2341" state="FL"/>
+ <vehicle plateNumber="1125" state="FL"/>
+ <vehicle plateNumber="1133" state="FL"/>
+ <vehicle plateNumber="22123" state="MO"/>
+ <vehicle plateNumber="22124" state="MI"/>
+ <person>
+ <car regState="AL" regPlate="1123"/>
+ </person>
+ <person>
+ <car regState="AK" regPlate="1120"/>
+ </person>
+ <person>
+ <car regState="AL" regPlate="1124"/>
+ </person>
+ <person>
+ <car regState="AL" regPlate="1221"/>
+ </person>
+ <person>
+ <car regState="AL" regPlate="1323"/>
+ </person>
+ <person>
+ <car regState="AS" regPlate="1223"/>
+ </person>
+ <person>
+ <car regState="AZ" regPlate="1126"/>
+ </person>
+ <person>
+ <car regState="AR" regPlate="1127"/>
+ </person>
+ <person>
+ <car regState="FL" regPlate="2341"/>
+ </person>
+ <person>
+ <car regState="FL" regPlate="1128"/>
+ </person>
+ <person>
+ <car regState="FL" regPlate="1133"/>
+ <car regState="FL" regPlate="1125"/>
+ </person>
+ <person>
+ <car regState="MO" regPlate="22123"/>
+ </person>
+ <person>
+ <car regState="MI" regPlate="22124"/>
+ </person>
+ </state>
+</root> \ No newline at end of file
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/vehicle.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/vehicle.xsd
new file mode 100644
index 0000000000..2e7c053497
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/vehicle.xsd
@@ -0,0 +1,82 @@
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xs:element name="vehicle">
+ <xs:complexType>
+ <xs:attribute name="plateNumber" type="xs:integer"/>
+ <xs:attribute name="state" type="twoLetterCode"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="state">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="code" type="twoLetterCode"/>
+ <xs:element ref="vehicle" maxOccurs="unbounded"/>
+ <xs:element ref="person" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:key name="reg"> <!-- vehicles are keyed by their plate within states -->
+ <xs:selector xpath=".//vehicle"/>
+ <xs:field xpath="@plateNumber"/>
+ </xs:key>
+ </xs:element>
+
+ <xs:element name="root">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="state" maxOccurs="51"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:key name="state"> <!-- states are keyed by their code -->
+ <xs:selector xpath=".//state"/>
+ <xs:field xpath="code"/>
+ </xs:key>
+
+ <xs:keyref name="vehicleState" refer="state">
+ <!-- every vehicle refers to its state -->
+ <xs:selector xpath=".//vehicle"/>
+ <xs:field xpath="@state"/>
+ </xs:keyref>
+
+ <xs:key name="regKey"> <!-- vehicles are keyed by a pair of state and plate -->
+ <xs:selector xpath=".//vehicle"/>
+ <xs:field xpath="@state"/>
+ <xs:field xpath="@plateNumber"/>
+ </xs:key>
+
+ <xs:keyref name="carRef" refer="regKey"> <!-- people's cars are a reference -->
+ <xs:selector xpath=".//car"/>
+ <xs:field xpath="@regState"/>
+ <xs:field xpath="@regPlate"/>
+ </xs:keyref>
+
+ </xs:element>
+
+ <xs:element name="person">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="car" maxOccurs="2">
+ <xs:complexType>
+ <xs:attribute name="regState" type="twoLetterCode"/>
+ <xs:attribute name="regPlate" type="xs:integer"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:simpleType name="twoLetterCode">
+ <xs:restriction base="xs:string">
+ <xs:maxLength value="2"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="threeLetterCode">
+ <xs:restriction base="xs:string">
+ <xs:maxLength value="3"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+</xs:schema> \ No newline at end of file
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/vehicle2.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/vehicle2.xml
new file mode 100644
index 0000000000..6b60c83e6a
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/vehicle2.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<root>
+ <state>
+ <code>AL</code>
+ <vehicle plateNumber="1123" state="AL"/>
+ <vehicle plateNumber="1121" state="AK"/>
+ <vehicle plateNumber="1124" state="AL"/>
+ <vehicle plateNumber="1221" state="AL"/>
+ <vehicle plateNumber="1122" state="AL"/>
+ <vehicle plateNumber="1225" state="AS"/>
+ <vehicle plateNumber="1126" state="AZ"/>
+ <vehicle plateNumber="1127" state="AR"/>
+ <vehicle plateNumber="1128" state="FL"/>
+ <vehicle plateNumber="2341" state="FL"/>
+ <vehicle plateNumber="1125" state="FL"/>
+ <vehicle plateNumber="1133" state="FL"/>
+ <vehicle plateNumber="22123" state="MO"/>
+ <vehicle plateNumber="22124" state="MI"/>
+ <person>
+ <car regState="AL" regPlate="1122"/>
+ </person>
+ <person>
+ <car regState="AK" regPlate="1121"/>
+ </person>
+ <person>
+ <car regState="AL" regPlate="1124"/>
+ <car regState="AL" regPlate="1221"/>
+ </person>
+ <person>
+ <car regState="AL" regPlate="1123"/>
+ </person>
+ <person>
+ <car regState="AS" regPlate="1225"/>
+ </person>
+ <person>
+ <car regState="AZ" regPlate="1126"/>
+ </person>
+ <person>
+ <car regState="AR" regPlate="1127"/>
+ </person>
+ <person>
+ <car regState="FL" regPlate="2341"/>
+ </person>
+ <person>
+ <car regState="FL" regPlate="1128"/>
+ </person>
+ <person>
+ <car regState="FL" regPlate="1133"/>
+ </person>
+ <person>
+ <car regState="FL" regPlate="1125"/>
+ </person>
+ <person>
+ <car regState="MO" regPlate="22123"/>
+ </person>
+ <person>
+ <car regState="MI" regPlate="22124"/>
+ </person>
+ </state>
+
+</root> \ No newline at end of file
diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/vehicle3.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/vehicle3.xml
new file mode 100644
index 0000000000..37536c7335
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/vehicle3.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0"?>
+<root>
+ <state>
+ <code>AL</code>
+ <vehicle plateNumber="1123" state="AL"/>
+ <vehicle plateNumber="1125" state="AK"/>
+ <vehicle plateNumber="1124" state="AL"/>
+ <vehicle plateNumber="1223" state="AL"/>
+ <vehicle plateNumber="1323" state="AL"/>
+ <vehicle plateNumber="1225" state="AS"/>
+ <vehicle plateNumber="1126" state="AZ"/>
+ <vehicle plateNumber="1127" state="AR"/>
+ <vehicle plateNumber="1128" state="FL"/>
+ <vehicle plateNumber="2341" state="FL"/>
+ <vehicle plateNumber="1129" state="FL"/>
+ <vehicle plateNumber="1133" state="FL"/>
+ <vehicle plateNumber="22123" state="MO"/>
+ <vehicle plateNumber="22124" state="MI"/>
+ <person>
+ <car regState="AL" regPlate="1123"/>
+ </person>
+ <person>
+ <car regState="AK" regPlate="1125"/>
+ </person>
+ <person>
+ <car regState="AL" regPlate="1124"/>
+ <car regState="AL" regPlate="1223"/>
+ </person>
+ <person>
+ <car regState="AL" regPlate="1323"/>
+ </person>
+ <person>
+ <car regState="AS" regPlate="1225"/>
+ </person>
+ <person>
+ <car regState="AZ" regPlate="1126"/>
+ </person>
+ <person>
+ <car regState="AR" regPlate="1127"/>
+ </person>
+ <person>
+ <car regState="FL" regPlate="2341"/>
+ </person>
+ <person>
+ <car regState="FL" regPlate="1128"/>
+ </person>
+ <person>
+ <car regState="FL" regPlate="1133"/>
+ </person>
+ <person>
+ <car regState="FL" regPlate="1129"/>
+ </person>
+ <person>
+ <car regState="MO" regPlate="22123"/>
+ </person>
+ <person>
+ <car regState="MI" regPlate="22124"/>
+ </person>
+ </state>
+ <state>
+ <code>CO</code>
+ <vehicle plateNumber="1123" state="CO"/>
+ <vehicle plateNumber="1120" state="AK"/>
+ <vehicle plateNumber="1124" state="CO"/>
+ <vehicle plateNumber="1221" state="AL"/>
+ <vehicle plateNumber="1323" state="CO"/>
+ <vehicle plateNumber="1223" state="AS"/>
+ <vehicle plateNumber="1126" state="CO"/>
+ <vehicle plateNumber="1127" state="CA"/>
+ <vehicle plateNumber="1128" state="DE"/>
+ <vehicle plateNumber="2341" state="DC"/>
+ <vehicle plateNumber="1125" state="FL"/>
+ <vehicle plateNumber="1133" state="GA"/>
+ <vehicle plateNumber="22123" state="GU"/>
+ <vehicle plateNumber="22124" state="HI"/>
+ <person>
+ <car regState="CO" regPlate="1123"/>
+ </person>
+ <person>
+ <car regState="AK" regPlate="1120"/>
+ </person>
+ <person>
+ <car regState="CO" regPlate="1124"/>
+ </person>
+ <person>
+ <car regState="AL" regPlate="1221"/>
+ </person>
+ <person>
+ <car regState="CO" regPlate="1323"/>
+ </person>
+ <person>
+ <car regState="AS" regPlate="1223"/>
+ </person>
+ <person>
+ <car regState="CO" regPlate="1126"/>
+ </person>
+ <person>
+ <car regState="CA" regPlate="1127"/>
+ </person>
+ <person>
+ <car regState="DC" regPlate="2341"/>
+ </person>
+ <person>
+ <car regState="DE" regPlate="1128"/>
+ </person>
+ <person>
+ <car regState="GA" regPlate="1133"/>
+ <car regState="FL" regPlate="1125"/>
+ </person>
+ <person>
+ <car regState="GU" regPlate="22123"/>
+ </person>
+ <person>
+ <car regState="HI" regPlate="22124"/>
+ </person>
+ </state>
+</root> \ No newline at end of file
diff --git a/lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE.erl b/lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE.erl
new file mode 100644
index 0000000000..e619390f65
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE.erl
@@ -0,0 +1,812 @@
+%%
+%% %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%
+%%
+%%
+%%% Purpose : Test suite for the xmerl application
+
+%% Do NOT edit this file. It is generated by the generate_xsd_suite module
+%% For more info read the comments in the header of that file.
+
+-module('xmerl_xsd_Sun2002-01-16_SUITE').
+
+-compile(export_all).
+
+-include_lib("test_server/include/test_server.hrl").
+-include_lib("xmerl/include/xmerl.hrl").
+-include_lib("xmerl/include/xmerl_xsd.hrl").
+
+
+all() ->
+ ['Sun-idc001.nogen', 'Sun-idc002.e', 'Sun-idc002b.e',
+ 'Sun-idc003.e', 'Sun-idc004.nogen', 'Sun-idc004a.e',
+ 'Sun-idc005.nogen', 'Sun-idc006.nogen', 'Sun-xsd001',
+ 'Sun-xsd002', 'Sun-xsd003-1.e', 'Sun-xsd003-2.e',
+ 'Sun-xsd003a', 'Sun-xsd003b', 'Sun-xsd004',
+ 'Sun-xsd005', 'Sun-xsd006', 'Sun-xsd008', 'Sun-xsd011',
+ 'Sun-xsd012', 'Sun-xsd013.e', 'Sun-xsd014.e',
+ 'Sun-xsd015.e', 'Sun-xsd016.e', 'Sun-xsd017.e',
+ 'Sun-xsd018.e', 'Sun-xsd019.e', 'Sun-xsd020.e',
+ 'Sun-xsd020-2.e', 'Sun-xsd020-3.e', 'Sun-xsd020-4.e',
+ 'Sun-xsd021', 'Sun-xsd022', 'Sun-xsd023.e',
+ 'Sun-xsiType1', 'Sun-xsiType-block-1',
+ 'Sun-xsiType-block-2', 'Sun-xsiType-block-3',
+ 'Sun-xsiType-block-4', 'Sun-type-and-subst-1'].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+
+%% initialization before the test suite
+init_per_suite(Config) ->
+ Dog=test_server:timetrap({minutes,10}),
+ xmerl_xsd_lib:unpack(Config,sun),
+ {ok,LogFile} = xmerl_xsd_lib:create_error_log_file(Config,sun),
+ test_server:timetrap_cancel(Dog),
+ [{suite,sun},{xmerl_error_log,LogFile}|Config].
+
+end_per_suite(Config) ->
+ xmerl_xsd_lib:rmdir(Config,sun),
+ xmerl_xsd_lib:close_error_log_file(Config),
+ ok.
+
+%% initialization before each testcase
+init_per_testcase(TestCase,Config) ->
+ Dog=test_server:timetrap({minutes,3}),
+ [{testcase,TestCase},{watchdog, Dog}|Config].
+
+%% clean up after each testcase
+end_per_testcase(_Func,Config) ->
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+%% ID Constranints. Very naive test of identity constraint
+'Sun-idc001.nogen'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/idc001.nogen.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/idc001.nogen.n00.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/idc001.nogen.v00.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/idc001.nogen.v01.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList3).
+
+%% ID Constranints. Reference to an undeclared key
+'Sun-idc002.e'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/idc002.e.xsd','./suntest/SunTestsAll',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,[]).
+
+%% ID Constranints. Reference to an undeclared key in an undeclared namespace
+'Sun-idc002b.e'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/idc002b.e.xsd','./suntest/SunTestsAll',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,[]).
+
+%% ID Constranints. Reference to non-key constraint.
+'Sun-idc003.e'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/idc003.e.xsd','./suntest/SunTestsAll',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,[]).
+
+%% ID Constranints.
+'Sun-idc004.nogen'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/idc004.nogen.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/idc004.nogen.n00.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/idc004.nogen.n01.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/idc004.nogen.n02.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/idc004.nogen.n03.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/idc004.nogen.v00.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList5).
+
+%% ID Constraints. Key/keyref field size mismatch.
+'Sun-idc004a.e'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/idc004a.e.xsd','./suntest/SunTestsAll',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,[]).
+
+%% ID Constraints. Very naive test of identity constraint.
+'Sun-idc005.nogen'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/idc005.nogen.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/idc005.nogen.n00.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/idc005.nogen.n01.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/idc005.nogen.v00.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList3).
+
+%% ID Constraints. XPath engine test: ".//a/*/b" and use of "." for both selector and field.
+'Sun-idc006.nogen'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/idc006.nogen.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/idc006.nogen.n00.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/idc006.nogen.n01.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/idc006.nogen.v00.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList3).
+
+%% - use of elementFormDefault="unqualified" - unusual minOccurs/maxOccurs (3 and 7 respectively) - complexType with simpleContent, and restriction. - simpleType within restriction.
+'Sun-xsd001'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd001.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd001.n00.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd001.n01.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd001.n02.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd001.n03.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd001.n04.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd001.n05.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd001.n06.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd001.n07.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd001.v00.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd001.v01.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList10 = [ITRes9|ITResList9],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd001.v02.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd001.v03.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList12).
+
+%% - use of elementFormDefault="unqualified" - use of elementFormDefault and form attribute. - implicit use of "ur-type" as the content model of element.
+'Sun-xsd002'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd002.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd002.n00.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd002.n01.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd002.n02.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd002.v00.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd002.v01.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList5).
+
+%% Element redefinition. Unable to redefine element.
+'Sun-xsd003-1.e'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd003-1.e.xsd','./suntest/SunTestsAll',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,[]).
+
+%% Element redefinition. Unable to redefine element.
+'Sun-xsd003-2.e'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd003-2.e.xsd','./suntest/SunTestsAll',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,[]).
+
+%% Element redefinition. Test without redefinition.
+'Sun-xsd003a'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd003a.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd003a.v00.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList1).
+
+%% Element redefinition. Test with redefinition with self-reference.
+'Sun-xsd003b'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd003b.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd003b.n00.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd003b.n01.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd003b.v00.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd003b.v01.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList4).
+
+%% Use of three different type of any element with different @namespace.
+'Sun-xsd004'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd004.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd004.n00.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd004.n01.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd004.n02.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd004.n03.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd004.n04.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd004.n05.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd004.n06.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd004.n07.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd004.n08.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd004.n09.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList10 = [ITRes9|ITResList9],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd004.n10.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd004.n11.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd004.n12.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd004.v00.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList14 = [ITRes13|ITResList13],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList14).
+
+%% Complex type derivation.
+'Sun-xsd005'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd005.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd005.n00.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd005.n01.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd005.n02.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd005.n03.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd005.n04.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd005.n05.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd005.n06.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd005.v00.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList8 = [ITRes7|ITResList7],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList8).
+
+%% minOccurs/maxOccurs. Various combinations.
+'Sun-xsd006'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd006.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd006.n00.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd006.n01.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd006.n02.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd006.n03.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd006.n04.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd006.n05.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd006.n06.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd006.n07.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd006.n08.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd006.n09.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList10 = [ITRes9|ITResList9],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd006.n10.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd006.v00.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList12 = [ITRes11|ITResList11],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList12).
+
+%% Abstract element and element substitution group.
+'Sun-xsd008'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd008.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd008.n00.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd008.n01.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd008.n02.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd008.v00.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList4).
+
+%% Nillable.
+'Sun-xsd011'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd011.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd011.n00.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd011.n01.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd011.n02.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd011.n03.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd011.n04.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd011.v00.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList6 = [ITRes5|ITResList5],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList6).
+
+%% Mixed content model.
+'Sun-xsd012'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd012.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd012.n00.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd012.v00.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList2).
+
+%% Reference to undeclared element.
+'Sun-xsd013.e'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd013.e.xsd','./suntest/SunTestsAll',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,[]).
+
+%% Reference to undeclared element.
+'Sun-xsd014.e'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd014.e.xsd','./suntest/SunTestsAll',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,[]).
+
+%% Reference to undeclared type (it may be simple or complex).
+'Sun-xsd015.e'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd015.e.xsd','./suntest/SunTestsAll',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,[]).
+
+%% Reference to undeclared type (it may be simple or complex).
+'Sun-xsd016.e'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd016.e.xsd','./suntest/SunTestsAll',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,[]).
+
+%% Reference to undeclared complex type.
+'Sun-xsd017.e'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd017.e.xsd','./suntest/SunTestsAll',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,[]).
+
+%% Reference to undeclared complex type.
+'Sun-xsd018.e'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd018.e.xsd','./suntest/SunTestsAll',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,[]).
+
+%% Reference to undeclared simple type.
+'Sun-xsd019.e'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd019.e.xsd','./suntest/SunTestsAll',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,[]).
+
+%% Reference to undeclared simple type.
+'Sun-xsd020.e'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd020.e.xsd','./suntest/SunTestsAll',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,[]).
+
+%% Reference to undeclared attribute.
+'Sun-xsd020-2.e'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd020-2.e.xsd','./suntest/SunTestsAll',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,[]).
+
+%% Reference to undeclared model group.
+'Sun-xsd020-3.e'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd020-3.e.xsd','./suntest/SunTestsAll',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,[]).
+
+%% Reference to undeclared attribute group.
+'Sun-xsd020-4.e'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd020-4.e.xsd','./suntest/SunTestsAll',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,[]).
+
+%% anyOtherAttribute.
+'Sun-xsd021'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd021.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd021.n00.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd021.n01.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd021.n02.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd021.n03.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd021.n04.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd021.n05.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd021.n06.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd021.n07.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd021.n08.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd021.n09.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList10 = [ITRes9|ITResList9],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd021.n10.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd021.n11.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd021.v00.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList13 = [ITRes12|ITResList12],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList13).
+
+%% Simple type. Various forms of forward reference to the simple type.
+'Sun-xsd022'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd022.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd022.n00.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsd022.v00.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList2).
+
+%% Simple type. Recursive definition.
+'Sun-xsd023.e'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,_} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsd023.e.xsd','./suntest/SunTestsAll',invalid),
+ STResList1 = [STRes0|STResList0],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,[]).
+
+%% Simple type.
+'Sun-xsiType1'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsiType1.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType1.v1.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType1.n1.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList2).
+
+%% Test block attribute (1) - use block="extension" at the B type. This should exclude all types that uses extension.
+'Sun-xsiType-block-1'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsiType-block-1.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-1.v1.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-1.n1.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-1.n2.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-1.n3.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-1.n4.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList5).
+
+%% Test block attribute (2) - use block="extension" as the blockDefault attribute. This should achieve the same result as the previous test case.
+'Sun-xsiType-block-2'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsiType-block-2.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-2.v1.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-2.n1.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-2.n2.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-2.n3.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-2.n4.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList5).
+
+%% Test block attribute (3) - use block="extension" for the child2 element. child2 has no block constraint. - see if @block for element is working as expected.
+'Sun-xsiType-block-3'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsiType-block-3.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-3.v1.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-3.n1.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-3.n2.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-3.n3.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-3.n4.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList5).
+
+%% Test block attribute (4) - use block="extension" for the child2 element. child2 has no block constraint. - use block="restriction" for the Dr type. - see if @block for element and @block for types interacts as expected.
+'Sun-xsiType-block-4'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/xsiType-block-4.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-4.v1.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-4.n1.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-4.n2.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-4.n3.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/xsiType-block-4.n4.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList5).
+
+%% No block attribute is specified. Just test that the substitution group and the type hierarchy is OK. The substitution group hierarchy mirrors the complex type hierarchy.
+'Sun-type-and-subst-1'(Config) when is_list(Config) ->
+ STResList0 = [],
+
+ ?line {STRes0,S0} = xmerl_xsd_lib:schema_test(Config,'./suntest/SunTestsAll/type-and-subst-1.xsd','./suntest/SunTestsAll',valid),
+ STResList1 = [STRes0|STResList0],
+ ITResList0 = [],
+ ?line ITRes0 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.v1.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList1 = [ITRes0|ITResList0],
+ ?line ITRes1 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.v2.xml','./suntest/SunTestsAll',valid,S0),
+ ITResList2 = [ITRes1|ITResList1],
+ ?line ITRes2 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n1.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList3 = [ITRes2|ITResList2],
+ ?line ITRes3 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n2.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList4 = [ITRes3|ITResList3],
+ ?line ITRes4 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n3.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList5 = [ITRes4|ITResList4],
+ ?line ITRes5 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n4.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList6 = [ITRes5|ITResList5],
+ ?line ITRes6 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n5.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList7 = [ITRes6|ITResList6],
+ ?line ITRes7 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n6.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList8 = [ITRes7|ITResList7],
+ ?line ITRes8 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n7.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList9 = [ITRes8|ITResList8],
+ ?line ITRes9 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n8.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList10 = [ITRes9|ITResList9],
+ ?line ITRes10 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n9.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList11 = [ITRes10|ITResList10],
+ ?line ITRes11 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n10.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList12 = [ITRes11|ITResList11],
+ ?line ITRes12 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n11.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList13 = [ITRes12|ITResList12],
+ ?line ITRes13 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n12.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList14 = [ITRes13|ITResList13],
+ ?line ITRes14 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n13.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList15 = [ITRes14|ITResList14],
+ ?line ITRes15 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n14.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList16 = [ITRes15|ITResList15],
+ ?line ITRes16 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n15.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList17 = [ITRes16|ITResList16],
+ ?line ITRes17 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n16.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList18 = [ITRes17|ITResList17],
+ ?line ITRes18 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n17.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList19 = [ITRes18|ITResList18],
+ ?line ITRes19 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n18.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList20 = [ITRes19|ITResList19],
+ ?line ITRes20 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n19.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList21 = [ITRes20|ITResList20],
+ ?line ITRes21 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n20.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList22 = [ITRes21|ITResList21],
+ ?line ITRes22 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n21.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList23 = [ITRes22|ITResList22],
+ ?line ITRes23 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n22.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList24 = [ITRes23|ITResList23],
+ ?line ITRes24 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n23.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList25 = [ITRes24|ITResList24],
+ ?line ITRes25 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n24.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList26 = [ITRes25|ITResList25],
+ ?line ITRes26 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n25.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList27 = [ITRes26|ITResList26],
+ ?line ITRes27 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n26.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList28 = [ITRes27|ITResList27],
+ ?line ITRes28 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n27.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList29 = [ITRes28|ITResList28],
+ ?line ITRes29 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n28.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList30 = [ITRes29|ITResList29],
+ ?line ITRes30 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n29.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList31 = [ITRes30|ITResList30],
+ ?line ITRes31 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n30.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList32 = [ITRes31|ITResList31],
+ ?line ITRes32 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n31.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList33 = [ITRes32|ITResList32],
+ ?line ITRes33 = xmerl_xsd_lib:instance_test(Config,'./suntest/SunTestsAll/type-and-subst-1.n32.xml','./suntest/SunTestsAll',invalid,S0),
+ ITResList34 = [ITRes33|ITResList33],
+
+
+ xmerl_xsd_lib:compare_test_results(Config,STResList1,ITResList34).
+
diff --git a/lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE_data/sun_failed_cases.log b/lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE_data/sun_failed_cases.log
new file mode 100644
index 0000000000..cf0403bdeb
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE_data/sun_failed_cases.log
@@ -0,0 +1,33 @@
+{'Sun-idc004.nogen',{["idc004.nogen.n02.xml", "idc004.nogen.n03.xml"],[]}}.
+{'Sun-idc006.nogen',{["idc006.nogen.n00.xml"],[]}}.
+{'Sun-xsd001',{["xsd001.n04.xml",
+ "xsd001.n05.xml",
+ "xsd001.n06.xml"],[]}}.
+{'Sun-xsd002',{["xsd002.v01.xml","xsd002.v00.xml"],[]}}.
+{'Sun-xsd003a',{["xsd003a.v00.xml"],[]}}.
+{'Sun-xsd003b',{["xsd003b.v01.xml"],[]}}.
+{'Sun-xsd004',{["xsd004.v00.xml",
+ "xsd004.n00.xml",
+ "xsd004.n05.xml",
+ "xsd004.n06.xml",
+ "xsd004.n07.xml",
+ "xsd004.n11.xml",
+ "xsd004.n12.xml"
+ ],[]}}.
+{'Sun-xsd005',{["xsd005.n05.xml"],[]}}.
+{'Sun-xsd008',{[],[]}}.
+{'Sun-xsd012',{["xsd012.v00.xml"],[]}}.
+{'Sun-xsd021',{["xsd021.v00.xml",
+ "xsd021.n03.xml",
+ "xsd021.n02.xml",
+ "xsd021.n06.xml",
+ "xsd021.n07.xml",
+ "xsd021.n01.xml",
+ "xsd021.n00.xml"],[]}}.
+{'Sun-xsd022',{["xsd022.v00.xml"],[]}}.
+{'Sun-xsiType1',{["xsiType1.v1.xml"],[]}}.
+{'Sun-xsiType-block-1',{["xsiType-block-1.n1.xml", "xsiType-block-1.v1.xml"],[]}}.
+{'Sun-xsiType-block-2',{["xsiType-block-2.n1.xml", "xsiType-block-2.v1.xml"],[]}}.
+{'Sun-xsiType-block-3',{["xsiType-block-3.n1.xml", "xsiType-block-3.v1.xml"],[]}}.
+{'Sun-xsiType-block-4',{["xsiType-block-4.n2.xml", "xsiType-block-4.v1.xml"],[]}}.
+{'Sun-type-and-subst-1',{["type-and-subst-1.v2.xml"],[]}}.
diff --git a/lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE_data/suntest.tar.gz b/lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE_data/suntest.tar.gz
new file mode 100644
index 0000000000..bb0de7848b
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE_data/suntest.tar.gz
Binary files differ
diff --git a/lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE_data/w3c-copyright-19990405.html b/lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE_data/w3c-copyright-19990405.html
new file mode 100644
index 0000000000..5c89ffd95e
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_Sun2002-01-16_SUITE_data/w3c-copyright-19990405.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html><head>
+
+
+ <meta http-equiv="Content-Type" content="text/html"><title>DOCUMENT NOTICE</title>
+
+ <link rel="stylesheet" type="text/css" href="copyright-documents-19990405_files/base.css"></head><body bgcolor="#ffffff" text="#000000">
+<h1>W3C<sup>�</sup> DOCUMENT NOTICE AND LICENSE</h1>
+
+<h3>Copyright � 1994-2002 <a href="http://www.w3.org/">World Wide Web
+Consortium</a>, (<a href="http://www.lcs.mit.edu/">Massachusetts Institute of
+Technology</a>, <a href="http://www.inria.fr/">Institut National de Recherche
+en Informatique et en Automatique</a>, <a href="http://www.keio.ac.jp/">Keio
+University</a>). All Rights Reserved.<br>
+http://www.w3.org/Consortium/Legal/</h3>
+
+<p>Public documents on the W3C site are provided by the copyright holders
+under the following license. The software or Document Type Definitions (DTDs)
+associated with W3C specifications are governed by the <a href="http://www.w3.org/Consortium/Legal/copyright-software.html"> Software
+Notice</a>. By using and/or copying this document, or the W3C document from
+which this statement is linked, you (the licensee) agree that you have read,
+understood, and will comply with the following terms and conditions:</p>
+
+<p>Permission to use, copy, and distribute the contents of this document, or
+the W3C document from which this statement is linked, in any medium for any
+purpose and without fee or royalty is hereby granted, provided that you
+include the following on <i>ALL</i> copies of the document, or portions
+thereof, that you use:</p>
+<ol>
+ <li>A link or URL to the original W3C document.</li>
+ <li>The pre-existing copyright notice of the original author, or if it
+ doesn't exist, a notice of the form: "Copyright � [$date-of-document] <a href="http://www.w3.org/">World Wide Web Consortium</a>, (<a href="http://www.lcs.mit.edu/">Massachusetts Institute of Technology</a>,
+ <a href="http://www.inria.fr/"> Institut National de Recherche en
+ Informatique et en Automatique</a>, <a href="http://www.keio.ac.jp/">Keio
+ University</a>). All Rights Reserved.
+ http://www.w3.org/Consortium/Legal/" (Hypertext is preferred, but a
+ textual representation is permitted.)</li>
+ <li><em>If it exists</em>, the STATUS of the W3C document.</li>
+</ol>
+
+<p>When space permits, inclusion of the full text of this <b> NOTICE</b>
+should be provided. We request that authorship attribution be provided in any
+software, documents, or other items or products that you create pursuant to
+the implementation of the contents of this document, or any portion
+thereof.</p>
+
+<p>No right to create modifications or derivatives of W3C documents is
+granted pursuant to this license. However, if additional requirements
+(documented in the <a href="http://www.w3.org/Consortium/Legal/IPR-FAQ.html">Copyright FAQ</a>) are satisfied,
+the right to create modifications or derivatives is&nbsp;sometimes granted by the
+W3C to individuals complying with those requirements.</p>
+
+<p>THIS DOCUMENT IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO
+REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED
+TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
+NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE DOCUMENT ARE SUITABLE
+FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF SUCH CONTENTS WILL NOT
+INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.</p>
+
+<p>COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE DOCUMENT OR THE
+PERFORMANCE OR IMPLEMENTATION OF THE CONTENTS THEREOF.</p>
+
+<p>The name and trademarks of copyright holders may NOT be used in
+advertising or publicity pertaining to this document or its contents without
+specific, written prior permission. Title to copyright in this document will
+at all times remain with copyright holders.</p>
+
+<p>----------------------------------------------------------------------------</p>
+
+<p>This formulation of W3C's notice and license became active on April 05
+1999 so as to account for the treatment of DTDs, schema's and bindings. See
+the <a href="http://www.w3.org/Consortium/Legal/copyright-documents-19990218.html"> older formulation</a> for
+the policy prior to this date. Please see our <a href="http://www.w3.org/Consortium/Legal/IPR-FAQ.html">Copyright FAQ</a> for common questions about using
+materials from our site, including specific terms and conditions for packages
+like libwww, Amaya, and Jigsaw. Other questions about this notice can be
+directed to <a href="mailto:[email protected]">[email protected]</a>.</p>
+<address>
+ <a href="http://w3.org/Help/Webmaster.html">webmaster</a><br>
+ (last updated by reagle on 1999/04/99.)
+</address>
+</body></html> \ No newline at end of file
diff --git a/lib/xmerl/test/xmerl_xsd_lib.erl b/lib/xmerl/test/xmerl_xsd_lib.erl
new file mode 100644
index 0000000000..e5c2d900ba
--- /dev/null
+++ b/lib/xmerl/test/xmerl_xsd_lib.erl
@@ -0,0 +1,321 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, 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 : Sub routines for test suite for the xmerl application,
+%%% xmerl_xsd module.
+%%%-------------------------------------------------------------------
+%%% @private
+%%% File : xmerl_xsd_lib.erl
+%%% Author : Bertil Karlsson <bertil@finrod>
+%%% Description :
+%%%
+%%% Created : 28 Apr 2006 by Bertil Karlsson <bertil@finrod>
+%%%-------------------------------------------------------------------
+-module(xmerl_xsd_lib).
+
+-compile(export_all).
+
+-include("test_server.hrl").
+-include("xmerl.hrl").
+-include("xmerl_xsd.hrl").
+-include_lib("kernel/include/file.hrl").
+
+
+compare_test_results(Config, ST, IT) ->
+ ResST=compare_schema_test_results(ST),
+ ResIT=compare_instance_test_results(IT),
+ io:format("compare_test_results:~n ST = ~p~n IT = ~p~n ResST = ~p~n ResIT = ~p~n",[ST, IT, ResST, ResIT]),
+ case process_reference_results(Config, ResST, ResIT) of
+ error ->
+ error;
+ Diff ->
+ return_results(Diff, ResST, ResIT, length(ST)+length(IT))
+ end.
+
+compare_schema_test_results(ST) ->
+ {[N||{N, false}<-ST], [N||{N, enoent}<-ST]}.
+compare_instance_test_results(IT) ->
+ {[N||{N, false}<-IT], [N||{N, enoent}<-IT]}.
+
+return_results({SkippedN, Diff},{STErrs, _},{ITErrs, _}, TotN) ->
+ NumErrs = length(STErrs ++ ITErrs),
+ case NumErrs == TotN of
+ true when TotN > 0 ->
+ ?line exit(all_tests_cases_failed);
+ _ ->
+ return_results2(Diff, TotN - NumErrs, SkippedN, TotN)
+ end.
+
+%% return_results2(Diff,{[],[]},{[],[]},TotN) ->
+%% {comment,io_lib:format("~p successful test cases.~n"++Diff,[TotN])};
+%% return_results2(Diff,{STErrs,[]},{ITErrs,[]},TotN) ->
+%% {comment,io_lib:format("Total number of test cases: ~p~nThe following ~p test cases failed: ~p~n"++Diff,[TotN,length(STErrs++ITErrs),STErrs++ITErrs])};
+%% return_results2(Diff,{STErrs,STOther},{ITErrs,ITOther},TotN) ->
+%% {comment,io_lib:format("Total number of test cases: ~p~nThe following ~p test cases failed: ~p~nThe following ~p test cases was malicious ~p~~n"++Diff,[TotN,length(STErrs++ITErrs),STErrs++ITErrs,length(STOther++ITOther),STOther++ITOther])}.
+
+return_results2(_, 0, 0, 0) ->
+ {comment,io_lib:format("This test case was empty.~n", [])};
+return_results2({[], [], [], []}, NumSucc, SkippedN, TotN) ->
+ {comment,io_lib:format("~p successful tests, ~p skipped tests of totally ~p test cases.~n",
+ [NumSucc, SkippedN, TotN])};
+return_results2({NewFail, NewSuccess, NewMal, NewNotMal}, NumSucc, SkippedN, TotN) ->
+ NFComm =
+ case NewFail of
+ [] -> "";
+ _ -> io_lib:format("These ~p tests are new failures: ~p~n",
+ [length(NewFail), NewFail])
+ end,
+ NSComm =
+ case NewSuccess of
+ [] -> "";
+ _ -> io_lib:format("These ~p skipped tests are new succeeding cases: ~p~n",
+ [length(NewSuccess), NewSuccess])
+ end,
+ NMComm =
+ case NewMal of
+ [] -> "";
+ _ -> io_lib:format("These ~p tests are now malicious: ~p~n",
+ [length(NewMal), NewMal])
+ end,
+ NNMComm =
+ case NewNotMal of
+ [] -> "";
+ _ -> io_lib:format("These ~p skipped tests were malicious, but succeeds now: ~p~n", [length(NewNotMal), NewNotMal])
+ end,
+ ct:comment(io_lib:format("~p successful tests, ~p skipped tests of totally ~p test cases. ~n" ++
+ NFComm ++ NSComm ++ NMComm ++ NNMComm, [NumSucc, SkippedN, TotN])),
+ [] = NewFail.
+
+%% return_results2(Diff,{STErrs,STOther},{ITErrs,ITOther},TotN) ->
+%% {comment,io_lib:format("Total number of test cases: ~p~n The following ~p test cases failed: ~p~nThe following ~p test cases was malicious ~p~~n",[TotN,length(STErrs++ITErrs),STErrs++ITErrs,length(STOther++ITOther),STOther++ITOther])}.
+
+
+process_reference_results(Config, {ErrsST, MalST}, {ErrsIT, MalIT}) ->
+ {RefFailed, RefMalicious} = xsd_reference_log(Config),
+io:format("A: ~p : ~p\n\n",[RefFailed, RefMalicious]),
+ AllErrs = ErrsST ++ ErrsIT,
+ AllMals = MalST ++ MalIT,
+ %% test cases failed now but succeeded in reference results.
+ NewFailures = [X||X<-AllErrs, lists:member(X, RefFailed) == false],
+ %% test cases succeeded now but failed in reference results.
+ NewSucceeds = [X||X<-RefFailed, lists:member(X, AllErrs) == false],
+ %% test cases malicious now but succeeded in reference results.
+ NewMalicious = [X||X<-AllMals, lists:member(X, RefMalicious) == false],
+ %% test cases succeeded now but malicious in reference results.
+ NewNotMal = [X||X<-RefMalicious, lists:member(X, AllMals) == false],
+ write_in_log(Config, AllErrs, AllMals),
+% io:format("process_reference_results:~n AllErrs = ~p~n NewFailures = ~p~n",[AllErrs,NewFailures]),
+ {length(RefFailed) + length(RefMalicious), {NewFailures, NewSucceeds, NewMalicious, NewNotMal}}.
+
+xsd_reference_log(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = ?config(suite, Config),
+ SuiteReferenceLog =
+ filename:join([DataDir, lists:concat([Suite, "_failed_cases.log"])]),
+io:format("B: ~p\n\n",[SuiteReferenceLog]),
+ case file:consult(SuiteReferenceLog) of
+ {ok,List} when is_list(List) ->
+io:format("C: ~p\n\n",[List]),
+ case lists:keysearch(?config(testcase, Config), 1, List) of
+ {value,{_, TCRefFails}} ->
+io:format("D: ~p\n\n",[TCRefFails]),
+ TCRefFails;
+ _ ->
+io:format("D: ~no result\n\n",[]),
+ {[], []}
+ end;
+ _ ->
+ {[], []}
+ end.
+
+write_in_log(_Config, [], []) ->
+ ok;
+write_in_log(Config, AllErrs, AllMals) ->
+ ?line LogFileName = ?config(xmerl_error_log, Config),
+ {ok,IO}=file:open(LogFileName, [append]),
+ ?line TestCase = ?config(testcase, Config),
+ io:format(IO,"{~p,{~p,~p}}.~n", [TestCase, AllErrs, AllMals]),
+ file:close(IO),
+ ok.
+
+schema_test(Config,FileName,XsdBase,Validity) ->
+ ModuleName = filename:basename(FileName),
+ DataDir = ?config(data_dir, Config),
+ case xmerl_xsd:process_schema(filename:join([DataDir, FileName]), [{xsdbase,filename:join([DataDir, XsdBase])}]) of
+ {error, enoent} ->
+ {{ModuleName, enoent},#xsd_state{}};
+ {Ok, S} ->
+ case Validity of
+ valid when Ok == ok ->
+%% io:format("schema_test1: Validity=valid,Ok=ok,S=~p~n",[S]),
+ {{ModuleName, S#xsd_state.errors == []}, S};
+ invalid when Ok == error -> %% S is in this case an error reason
+ {{ModuleName, no_internal_error(S)}, #xsd_state{}};
+ notKnown ->
+ {{ModuleName, true}, #xsd_state{}};
+ valid ->
+ io:format("schema_test2: Validity=valid,Ok=~p,S=~p~n", [Ok, S]),
+%% io:format("FileName: ~p~n",[FileName]),
+ {{ModuleName, false}, #xsd_state{}};
+ _ -> %% invalid Ok == ok
+ io:format("schema_test3: Validity=~p,Ok=~p,S=~p~n", [Validity, Ok, S]),
+ {{ModuleName, false}, S}
+ end
+ end.
+schema_test(Config, FileName, XsdBase, Validity, AccState) ->
+ ModuleName = filename:basename(FileName),
+ DataDir = ?config(data_dir, Config),
+ case xmerl_xsd:process_schema(filename:join([DataDir, FileName]),
+ [{xsdbase, filename:join([DataDir, XsdBase])}, AccState]) of
+ {error, enoent} ->
+ {{ModuleName, enoent}, AccState};
+ {Ok, S} ->
+ case Validity of
+ valid when Ok == ok ->
+ {{ModuleName, S#xsd_state.errors == []}, S};
+ invalid when Ok == error ->
+ {{ModuleName, no_internal_error(S)}, AccState};
+ notKnown ->
+ {{ModuleName, true}, AccState};
+ valid ->
+ {{ModuleName, false}, AccState};
+ _ ->
+ {{ModuleName, false}, S}
+ end
+ end.
+instance_test(Config, FileName, XMLBase, Validity, State) ->
+ ModuleName = filename:basename(FileName),
+ DataDir = ?config(data_dir, Config),
+ case xmerl_scan:file(filename:join([DataDir, FileName]),
+ [{xmlbase, filename:join([DataDir, XMLBase])}]) of
+ {error, enoent} ->
+ {ModuleName, enoent};
+ {E, _} ->
+ {VE, S2} = xmerl_xsd:validate(E, State),
+ case Validity of
+ valid when is_record(VE, xmlElement) ->
+ case S2#xsd_state.errors of
+ [] -> ok;
+ _ -> io:format("test case ~p failed.~nValidity: ~p~nValidation result:~p~n", [FileName, Validity, VE])
+ end,
+ {ModuleName, S2#xsd_state.errors == []};
+ invalid when VE == error ->
+ {ModuleName, no_internal_error(S2)};
+ notKnown ->
+ {ModuleName, true};
+ _ ->
+ io:format("test case ~p failed.~nValidity: ~p~nValidation result:~p~n", [FileName, Validity, VE]),
+ {ModuleName,false}
+ end
+ end.
+
+no_internal_error(R) ->
+ case lists:keymember(internal_error,1,R) of
+ true ->
+ false;
+ _ ->
+ true
+ end.
+
+unpack(Config, Suite) ->
+ TarFile = suite_tar(Suite),
+ ?line file:set_cwd(?config(data_dir, Config)),
+ ?line ok=erl_tar:extract(TarFile, [compressed]),
+ change_mode(filename:rootname(TarFile, ".tar.gz")).
+
+suite_tar(sun) ->
+ "suntest.tar.gz";
+suite_tar(msx) ->
+ "msxsdtest.tar.gz";
+suite_tar(nist) ->
+ "nisttest.tar.gz".
+
+change_mode(Files) ->
+ change_mode3(Files).
+change_mode2(Dir)->
+ ?line {ok, CWD} = file:get_cwd(),
+ ?line {ok, FileList} = file:list_dir(Dir),
+ ?line file:set_cwd(filename:join([CWD, Dir])),
+ change_mode3(FileList),
+ ?line file:set_cwd(CWD).
+change_mode3([]) ->
+ ok;
+change_mode3([F |Fs]) ->
+ case filelib:is_dir(F) of
+ true ->
+ chmod(F),
+ change_mode2(F);
+ _ ->
+ chmod(F)
+ end,
+ change_mode3(Fs).
+
+chmod(F) ->
+ case file:read_file_info(F) of
+ {ok, FileInfo} ->
+ Mode= FileInfo#file_info.mode,
+ file:write_file_info(F, FileInfo#file_info{mode=8#00777 bor Mode});
+ _ ->
+ ok
+ end.
+
+rmdir(Config, Suite) ->
+ ?line file:set_cwd(?config(data_dir, Config)),
+ SuiteDir = filename:rootname(suite_tar(Suite), ".tar.gz"),
+ ?line ok=rm_f_(SuiteDir).
+
+%% Dir is a directory
+rm_f_(Dir) ->
+ ?line {ok, CWD} = file:get_cwd(),
+ ?line {ok, FileList} = file:list_dir(Dir),
+ ?line file:set_cwd(filename:join([CWD, Dir])),
+ rm_files(FileList),
+ ?line file:set_cwd(CWD),
+ ? line ok = file:del_dir(Dir).
+
+rm_files([])->
+ ok;
+rm_files([F |Fs]) ->
+ case filelib:is_dir(F) of
+ true ->
+ rm_f_(F);
+ _ ->
+ io:format("rm_files: ~p~n", [F]),
+ ?line ok = file:delete(F)
+ end,
+ rm_files(Fs).
+
+create_error_log_file(Config, Suite) ->
+ ?line {{Y, M, D}, {H, Min, S}} = calendar:local_time(),
+ DTString=lists:concat([Y, "-", M,"-", D, "_", H, ".", Min, ".", S]),
+ FileName = lists:concat([Suite, "_", DTString, ".errorlog"]),
+%% ?line {ok,_IO} = file:open(filename:join([?config(priv_dir,Config),
+%% FileName]),[append]).
+
+%% ?line {ok,_IO} = file:open(FileName,[append]).
+ io:format("error log file: ~p~n", [filename:join([?config(priv_dir,Config), FileName])]),
+ {ok, filename:join([?config(priv_dir,Config), FileName])}.
+
+close_error_log_file(Config) ->
+ case lists:keysearch(xmerl_error_log, 1, Config) of
+ {value,{_, IO}} ->
+ file:close(IO);
+ _ ->
+ ok
+ end.
diff --git a/lib/xmerl/test/xmlconf.xml b/lib/xmerl/test/xmlconf.xml
new file mode 100644
index 0000000000..c015218e2e
--- /dev/null
+++ b/lib/xmerl/test/xmlconf.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0"?>
+<!--
+ @(#)conformance.xml 1.1 98/12/20
+ Original version copyright 1998 by Sun Microsystems, Inc.
+ All Rights Reserved.
+ Modifications copyright 1999 by OASIS.
+ Modifications copyright 2001 by OASIS.
+-->
+
+<?xml-stylesheet href="xmlconformance.xsl" type="text/xsl"?>
+
+<!DOCTYPE TESTSUITE SYSTEM "testcases.dtd" [
+
+ <!-- Sun-written testcases -->
+ <!ENTITY sun-valid SYSTEM "sun/sun-valid.xml">
+ <!ENTITY sun-invalid SYSTEM "sun/sun-invalid.xml">
+ <!ENTITY sun-not-wf SYSTEM "sun/sun-not-wf.xml">
+ <!ENTITY sun-error SYSTEM "sun/sun-error.xml">
+
+ <!-- James Clark "XMLTEST" -->
+ <!ENTITY jclark-xmltest SYSTEM "xmltest/xmltest.xml">
+
+ <!-- Fuji Xerox "Japanese Documents" -->
+ <!ENTITY xerox-japanese SYSTEM "japanese/japanese.xml">
+
+ <!-- NIST/OASIS test suite -->
+ <!ENTITY nist-oasis SYSTEM "oasis/oasis.xml">
+
+ <!-- IBM tests -->
+ <!ENTITY ibm-invalid SYSTEM "ibm/ibm_oasis_invalid.xml">
+ <!ENTITY ibm-not-wf SYSTEM "ibm/ibm_oasis_not-wf.xml">
+ <!ENTITY ibm-valid SYSTEM "ibm/ibm_oasis_valid.xml">
+]>
+
+<TESTSUITE PROFILE="XML 1.0 (2nd edition) W3C Conformance Test Suite, 6 October 2000">
+
+ &jclark-xmltest;
+ &xerox-japanese;
+
+<TESTCASES PROFILE="Sun Microsystems XML Tests" xml:base="sun/">
+ &sun-valid;
+ &sun-invalid;
+ &sun-not-wf;
+ &sun-error;
+</TESTCASES>
+
+ &nist-oasis;
+<TESTCASES PROFILE="IBM XML Tests" xml:base="ibm/">
+ &ibm-invalid;
+ &ibm-not-wf;
+ &ibm-valid;
+</TESTCASES>
+</TESTSUITE>
diff --git a/lib/xmerl/test/xmlconformance.msxsl b/lib/xmerl/test/xmlconformance.msxsl
new file mode 100644
index 0000000000..f33e647d25
--- /dev/null
+++ b/lib/xmerl/test/xmlconformance.msxsl
@@ -0,0 +1,527 @@
+<?xml version='1.0'?>
+<!--
+<<<<<<< conformance.msxsl
+ Original version copyright 1999 by Sun Microsystems, Inc.
+ All Rights Reserved.
+ Modifications copyright 1999 by OASIS.
+=======
+ XSL IE5 Stylesheet for documenting XML conformance tests.
+ Tested against IE5 5.00.2014.0216
+
+ 1999-06-05 20:10
+
+ XSL 12/16/1998 Stylesheet for documenting XML conformance tests.
+
+ This expects to be run on a document matching the DTD that Sun
+ defined and OASIS modified for merging collections of
+ self-descriptive XML tests.
+
+ Since all those collections will have (by design) the same test
+ architecture, this includes boilerplate describing that design,
+ to be used by all test documentation.
+
+ ISSUES:
+ - Sorting is a bit odd; section numbers can are like "3.3.3"
+ rather than straight numbers, so numeric sort can't work,
+ and yet neither does text sort (2.12 should be after 2.2).
+
+-->
+
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/TR/WD-xsl"
+ xmlns="http://www.w3.org/TR/WD-xhtml"
+ indent-result="yes"
+ >
+
+<!-- default behaviour - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<xsl:template><xsl:apply-templates/></xsl:template>
+<xsl:template match="textnode()"><xsl:value-of/></xsl:template>
+
+<!-- selective behaviour - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+
+ <!-- ROOT: write an HTML wrapper -->
+ <xsl:template match="/">
+ <xsl:apply-templates select="TESTSUITE"/>
+ </xsl:template>
+
+ <xsl:template match="TESTSUITE">
+ <!-- XHTML namespace -->
+ <html><head>
+ <xsl:comment>Generated by an XSL stylesheet.</xsl:comment>
+ <title> XML Conformance Tests </title>
+ <meta http-equiv="Content-Type"
+ content="text/html;charset=utf-8"/>
+ <style>
+ <xsl:comment>
+ BODY {
+ font-family: Lucida, Helvetica, Univers, sans-serif;
+ }
+ H1, H2, H3, H4 {
+ text-align: left;
+ color: #0066CC;
+ }
+ </xsl:comment>
+ </style>
+ <style>
+ <xsl:comment>
+ a:hover {
+ color: white;
+ background-color: blue;
+ }
+ </xsl:comment>
+ </style>
+ </head><body bgcolor='#ffffff'>
+ <center>
+ <table border="4" width="90%">
+ <tr >
+ <td>
+ <table>
+ <tr >
+ <td width="40%"><img src="files/a_oasis-logo.gif" width="350" height="125"/></td>
+ <td width="30%"/>
+ <td width="40%" align="right"><img src="files/top3.jpe" width="400" height="125"/></td>
+ </tr>
+ </table>
+ <center>
+ <table>
+ <tr>
+ <td ><b><font size="+2">A Joint Development Effort</font></b></td>
+ </tr>
+ </table>
+ </center>
+ </td>
+ </tr>
+ </table>
+ </center>
+ <p/>
+
+ <p/>
+ <h4>OASIS XML Conformance Subcommittee<br/>XML 1.0 Test Suite, Second Edition<br/>Working Draft<br/>15 March 2001</h4>
+ <dl>
+ <dt><b>This version:</b></dt>
+ <dd><ul>
+ <li><a href="http://www.oasis-open.org/committees/xml-conformance/suite-v1se/xmlconf-20010315.htm">
+ http://www.oasis-open.org/committees/xml-conformance/suite-v1se/xmlconf-20010315.htm</a>
+ (<a href="http://www.oasis-open.org/committees/xml-conformance/suite-v1se/xmlconf-20010315.xml">XML</a>)
+ </li>
+ </ul>
+ </dd>
+ <p/>
+ <dt><b>Current Version:</b></dt>
+ <dd>
+ <ul>
+ <li><a href="http://www.oasis-open.org/committees/xml-conformance/suite-v1se/xmlconf.xml">
+ http://www.oasis-open.org/committees/xml-conformance/suite-v1se/xmlconf.xml</a></li>
+ </ul>
+ </dd>
+ <p/>
+ <dt><b>Previous Version:</b></dt>
+ <dd>
+ <ul>
+ <li><a href="http://www.oasis-open.org/committees/xml-conformance/suite-v1/xmlconf-19990712.xml">
+ http://www.oasis-open.org/committees/xml-conformance/suite-v1/xmlconf-19990712.xml</a></li>
+ </ul>
+ </dd>
+ <p/>
+ <dt><b>Test Archive:</b></dt>
+ <dd><ul>
+ <li><a href="http://www.oasis-open.org/committees/xml-conformance/suite-v1se/xmlconf-20010315.tar.gz">http://www.oasis-open.org/committees/xml-conformance/suite-v1se/xmlconf-20010315.tar.gz</a>
+ </li>
+ </ul></dd>
+ <p/>
+ <dt><b>OASIS XML Conformance Technical Committee:</b></dt>
+ <dd><ul><li><a href="http://www.oasis-open.org/committees/xml-conformance/">http://www.oasis-open.org/committees/xml-conformance/</a>
+ </li></ul></dd>
+ <p/>
+ <dt><b>Comments:</b></dt>
+ <dd><ul><li>Mary Brady, NIST <a href="mailto:[email protected]">&lt;[email protected]&gt;</a>
+ </li></ul></dd>
+ <p/>
+ </dl>
+ <hr/>
+
+ <a name="contents"/>
+ <h2>Table of Contents</h2>
+ <ol >
+ <li><a href="#intro">Introduction</a></li>
+ <li><a href="#matrix">Test Matrix</a></li>
+ <ol >
+ <li ><a href="#binary">Binary Tests</a></li>
+ <li><a href="#output">Output Tests</a></li>
+ </ol>
+ <li><a href="#listings">Test Case Descriptions</a></li>
+ <ol >
+ <li><a href="#valid">Valid Documents</a></li>
+ <li><a href="#invalid">Invalid Documents</a></li>
+ <li><a href="#not-wf">Not-WF Documents</a></li>
+ <li><a href="#error">Optional Errors</a></li>
+ </ol>
+ <li><a href="#contrib">Contributors</a></li>
+ </ol>
+ <a name="intro"/>
+ <h2>1. Introduction </h2>
+ <p> The <i>OASIS</i> XML Conformance Subcommittee is concerned with
+ improving the quality of XML processors. The tests described in this
+ document provide a set of metrics to determine how well a
+ particular implementation conforms to the
+ <a href="http://www.w3.org/TR/REC-xml">W3C XML 1.0 (Second Edition) Recommendation </a>.
+ The XML Conformance Test Suite is intended
+ to complement the W3C XML 1.0 (Second Edition) Recommendation. All interpretations of
+ this Recommendation are subject to confirmation by the
+ <a href="http://www.w3.org/XML/Activity.html">W3C XML Coordination Group</a>.
+ </p>
+ <p>
+ Conformance tests can be used by developers, content creators, and
+ users alike to increase their level of confidence in product quality. In
+ circumstances where interoperability is necessary, these tests can also
+ be used to determine that differing implementations support the same set
+ of features. </p>
+
+ <p>This report provides supporting documentation for all of the tests
+ contributed by members of the <i>OASIS</i> XML Conformance Subcommittee.
+ Sources from which these tests have been collected
+ include: <em>
+ <xsl:for-each select="./TESTCASES">
+ <xsl:value-of select="@PROFILE"/>;
+ </xsl:for-each>
+ </em>. Although the tests came from a variety of sources, the actual test
+ descriptions and references back to the recommendation were in many instances
+ added by members of this subcommittee. It is anticipated that this report
+ will supplement the actual tests, which are available from
+ <a href="http://www.oasis-open.org/committees/xml-conformance/xml-test-suite.html">
+ http://www.oasis-open.org/committees/xml-conformance/xml-test-suite.html</a>.</p>
+
+ <p>Comments/suggestions should be
+ forwarded to the XML Conformance Subcommittee Chair, Mary Brady <a href="mailto:[email protected]">&lt;[email protected]&gt;</a>.</p>
+
+
+ <a name="matrix"/>
+ <h2>2. Test Matrix </h2>
+
+ <p> Two basic types of test are presented here. These are
+ respectively <em><a href="#binary">Binary Tests</a></em>
+ and <em><a href="#output">Output Tests</a></em>. </p>
+
+ <a name="binary"/>
+ <h3>2.1 Binary Tests </h3>
+
+ <p> <em>Binary</em> conformance tests are documents which
+ are grouped into one of four categories. Given a document
+ in a given category, each kind of XML parser must treat it
+ consistently and either accept it (a <em>positive test</em>)
+ or reject it (a <em>negative test</em>). It is in that sense
+ that the tests are termed "binary". The XML 1.0 (Second Edition) Recommendation
+ talks in terms of two types of XML processor:
+ <em>validating</em> ones, and <em>nonvalidating</em> ones.
+ There are two differences between these types of processors: </p>
+
+ <ol>
+ <li> Validating processors check special productions that
+ nonvalidating parsers don't, called <em>validity
+ constraints</em>. (Both must check a basic set of productions,
+ requiring XML documents to be <em>well formed</em>.) </li>
+
+ <li> Nonvalidating processors are permitted to not
+ include <em>external entities</em>, such as files with
+ text. Accordingly, they may not report errors which
+ would have been detected had those entities been read.</li>
+ </ol>
+
+ <p> There are two types of such entity, <em>parameter
+ entities</em> holding definitions which affect validation
+ and other processing; and <em>general entities</em> which
+ hold marked up text. It will be appreciated that there are
+ then five kinds of XML processor: validating processors,
+ and four kinds of nonvalidating processor based on the
+ combinations of external entity which they include.</p>
+
+ <center>
+ <table border="1" bgcolor="#ffffff" cellpadding="4">
+
+ <caption>
+ <b>Basic XML Parsing Test Matrix</b><br/>
+ Test Document Type v. Parser Type
+ </caption>
+
+ <tr bgcolor="#ffffcc">
+ <th widthH="5%" rowspan="2">&#160;</th>
+ <th widthH="20%" colspan="2">Nonvalidating</th>
+ <th widthH="5%" rowspan="2">Validating</th>
+ </tr>
+
+ <tr bgcolor="#ffffcc">
+ <th>External Entities<br/>Ignored (3 cases)</th>
+ <th>External Entities<br/>Read</th>
+ </tr>
+
+ <tr>
+ <th bgcolor="#ffffcc">Valid Documents</th>
+ <td align="center"><b>accept</b></td>
+ <td align="center"><b>accept</b></td>
+ <td align="center"><b>accept</b></td>
+ </tr>
+
+ <tr>
+ <th bgcolor="#ffffcc">Invalid Documents</th>
+ <td align="center"><b>accept</b></td>
+ <td align="center"><b>accept</b></td>
+ <td align="center">reject</td>
+ </tr>
+
+ <tr>
+ <th bgcolor="#ffffcc">Non-WF Documents</th>
+ <td align="center">reject</td>
+ <td align="center">reject</td>
+ <td align="center">reject</td>
+ </tr>
+
+ <tr>
+ <th bgcolor="#ffffcc">WF Errors tied<br/>
+ to External Entity</th>
+ <td align="center"><b>accept</b><br/>(varies)</td>
+ <td align="center">reject</td>
+ <td align="center">reject</td>
+ </tr>
+
+ <tr>
+ <th bgcolor="#ffffcc">Documents with<br/> Optional Errors</th>
+ <td align="center">(not specified)</td>
+ <td align="center">(not specified)</td>
+ <td align="center">(not specified)</td>
+ </tr>
+
+ </table>
+ </center>
+
+ <p> At this time, the XML community primarily uses parsers
+ which are in the rightmost two columns of this table, calling
+ them <em>Well Formed XML Parsers</em> (or "WF Parsers") and
+ <em>Validating XML Parsers</em>. A second test matrix
+ could be defined to address the variations in the types of
+ of XML processor which do not read all external entities.
+ That additional matrix is not provided here at this time. </p>
+
+
+ <a name="output"/>
+ <h3>2.2 Output Tests</h3>
+
+ <p> The XML 1.0 (Second Edition) Recommendation places a number of requirements
+ on XML processors, to ensure that they report information to
+ applications as needed. Such requirements are testable.
+ Validating processors are required to report slightly more
+ information than nonvalidating ones, so some tests will
+ require separate output files. Some of the information that
+ must be reported will not be reportable without reading all
+ the external entities in a particular test. Many of the tests for
+ valid documents are paired with an output file to ensure that
+ the XML processor provides the correct information. </p>
+
+ <p>The output of these tests is provided in two forms, as
+ described in <a href="sun/cxml.html">SUN Microsystems XML
+ Canonical Forms</a>. At present, the <em>James Clark</em>
+ collection provides corresponding output in <em>First XML
+ Canonical Form</em>, and the <em>SUN Microsystems</em>
+ collection provides corresponding output in <em>Second XML
+ Canonical Form</em>. When the <a href="http://www.w3.org/XML/">
+ W3C XML Group </a>finalizes its work on Canonical XML, these
+ output files will be updated.
+ </p>
+
+ <a name="listings"/>
+ <h2>3. Test Case Descriptions</h2>
+
+ <p> This section of this report contains descriptions of test
+ cases, each of which fits into the categories noted above.
+ Each test case includes a document of one of the types in the
+ binary test matrix above (e.g. valid or invalid documents).
+ </p>
+
+ <p> In some cases, an <a href="#output">output file </a>, as
+ described in Section 2.2, will also be associated with
+ a valid document, which is used for output testing. If such
+ a file exists, it will be noted at the end of the description
+ of the input document. </p>
+
+ <p> The description for each test case is presented as a two
+ part table. The right part describes what the test does.
+ This description is intended to have enough detail to evaluate
+ diagnostic messages. The left part includes: <ul>
+
+ <li> An entry describing the <em>Sections and/or Rules</em>
+ from the <a href="http://www.w3.org/TR/2000/REC-xml-20001006">
+ XML 1.0 (Second Edition) Recommendation</a> which this case excercises.</li>
+
+ <li> The unique <em>Test ID</em> within a given <em>Collection</em>
+ for this test. </li>
+
+ <li> The <em>Collection</em> from which this test originated.
+ Given the <em>Test ID</em> and the <em>Collection</em>, each
+ test can be uniquely identified. </li>
+
+ <li> Some tests may have a field identifying the kinds of
+ external <em>Entities</em> a nonvalidating processor must
+ include (parameter, general, or both) to be able to
+ detect any errors in that test case. </li>
+
+ </ul></p>
+
+ <p><em>Note that the output format of this report is subject
+ to change. Also, since XSL does not currently support the
+ type of sorting rule necessary to make section numbers like
+ 2.12 appear after 2.2, the ordering is not quite what is
+ desired.</em></p>
+
+ <a name="valid"/>
+ <h3>3.1 Valid XML Documents</h3>
+
+ <p> All conforming <em> XML 1.0 Processors </em> are
+ <b>required</b> to accept valid documents, reporting no
+ errors. In this section of this test report are found
+ descriptions of test cases which fit into this category. </p>
+
+ <xsl:apply-templates select=".// TEST [ @TYPE = 'valid' ]"
+ order-by="@SECTIONS"/>
+
+ <a name="invalid"/>
+ <h3>3.2 Invalid XML Documents</h3>
+
+ <p> All conforming XML 1.0 <em> Validating Processors </em>
+ are <b>required</b> to report recoverable errors in the case
+ of documents which are <em>Invalid</em>. Such errors are
+ violations of some <em>validity constraint (VC)</em>. </p>
+
+ <p> If a validating processor does not report an error when
+ given one of these test cases, or if the error reported is
+ a fatal error, it is not conformant. If the error reported
+ does not correspond to the problem listed in this test
+ description, that could also be a conformance problem; it
+ might instead be a faulty diagnostic. </p>
+
+ <p> All conforming XML 1.0 <em> Nonvalidating Processors </em>
+ should accept these documents, reporting no errors. </p>
+
+ <xsl:apply-templates select=".//TEST[@TYPE='invalid']"
+ order-by="@SECTIONS"/>
+
+ <a name="not-wf"/>
+ <h3>3.3 Documents that are Not Well Formed</h3>
+
+ <p> All conforming XML 1.0 Processors are <b>required</b> to
+ report fatal errors in the case of documents which are not
+ <em>Well Formed</em>. Such errors are basically of two types:
+ <em>(a)</em> the document violates the XML grammar; or else
+ <em>(b)</em> it violates a <em>well formedness constraint
+ (WFC)</em>. There is a single <em>exception to that
+ requirement</em>: nonvalidating processors which do not read
+ certain types of external entities are not required to detect
+ (and hence report) these errors. </p>
+
+ <p> If a processor does not report a fatal error when given
+ one of these test cases, it is not conformant. If the error
+ reported does not correspond to the problem listed in this
+ test description, that could also be a conformance problem;
+ it might instead be a faulty diagnostic. </p>
+
+ <xsl:apply-templates select=".// TEST [ @TYPE = 'not-wf' ]"
+ order-by="@SECTIONS"/>
+
+ <a name="error"/>
+ <h3>3.4 XML Documents with Optional Errors</h3>
+
+ <p> Conforming XML 1.0 Processors are permitted to ignore
+ certain errors, or to report them at user option. In this
+ section of this test report are found descriptions of
+ test cases which fit into this category. </p>
+
+ <p> Processor behavior on such test cases does not affect
+ conformance to the XML 1.0 (Second Edition) Recommendation, except as noted. </p>
+
+ <xsl:apply-templates select=".//TEST[@TYPE='error']"
+ order-by="@SECTIONS"/>
+
+ <a name="contrib"/>
+ <h3>4. Contributors (Non-normative)</h3>
+
+ <p> A team of volunteer members have participated in the
+ development of this work. Contributions have come from:
+ </p>
+ <ul>
+ <li>Murry Altheim, Sun Microsystems</li>
+ <li>Mary Brady, NIST</li>
+ <li>Tim Boland, NIST</li>
+ <li>David Brownell, Sun Microsystems</li>
+ <li>James Clark</li>
+ <li>Karin Donker, IBM</li>
+ <li>Irina Golfman, Inera Incorporated</li>
+ <li>Tony Graham, Mulberry Technologies</li>
+ <li>G. Ken Holman, Crane Softwrights Ltd</li>
+ <li>Alex Milowski, Veo Systems, Inc</li>
+ <li>Makota Murata, Fuji Xerox</li>
+ <li>Miles O'Reilly, Microstar Software, Ltd</li>
+ <li>Matt Timmermans, Microstar Software, Ltd</li>
+ <li>Richard Rivello, NIST</li>
+ <li>Lynne Rosenthal, NIST</li>
+ <li>Brian Schellar, Chrystal Software</li>
+ <li>Bill Smith, Sun Microsystems</li>
+ <li>Trevor Veary, Software AG</li>
+ <li>Eric Ye, IBM</li>
+ </ul>
+ <p>End</p>
+
+ </body></html>
+ </xsl:template>
+
+ <xsl:template match="TEST">
+ <table width="100%">
+ <tr valign="top">
+ <td width='40%'><table bgcolor='#eeeeff'
+ border='1' width='100%' height="100%">
+ <tr>
+ <td width='50%'><b>Sections [Rules]:</b></td>
+ <td bgcolor='#ffffcc'>
+ <xsl:value-of select="@SECTIONS"/></td>
+ </tr>
+ <tr valign="top">
+ <td width='50%'><b>Test ID:</b></td>
+ <td bgcolor='#ffffcc'>
+ <xsl:value-of select="@ID"/></td>
+ </tr>
+ <xsl:if test=".[not ( @ENTITIES = 'none')
+ and ( @TYPE = 'not-wf' )]">
+ <tr valign="top">
+ <td width='50%'><b>Entities:</b></td>
+ <td bgcolor='#ffffcc'><font color='blue'>
+ <xsl:value-of select="@ENTITIES"/>
+ </font></td>
+ </tr>
+ </xsl:if>
+ <xsl:if test="../@PROFILE">
+ <tr valign="top">
+ <td width='50%'><b>Collection:</b></td>
+ <td bgcolor='#ffffcc'>
+ <xsl:value-of select="../@PROFILE"/>
+ </td>
+ </tr>
+ </xsl:if>
+ </table></td>
+ <td bgcolor='#ccffff'>
+ <p><xsl:apply-templates/></p>
+ <xsl:if test="@OUTPUT | @OUTPUT3">
+ <p>There is an output test associated with this
+ input file.</p>
+ </xsl:if>
+ </td>
+ </tr>
+ </table>
+ </xsl:template>
+
+ <!-- XT takes 'B|EM' and xsl:copy, IE5b2 doesn't -->
+ <xsl:template match="EM">
+ <em><xsl:apply-templates/></em>
+ </xsl:template>
+ <xsl:template match="B">
+ <b><xsl:apply-templates/></b>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/lib/xmerl/test/xmlconformance.xsl b/lib/xmerl/test/xmlconformance.xsl
new file mode 100644
index 0000000000..fd1acb3d82
--- /dev/null
+++ b/lib/xmerl/test/xmlconformance.xsl
@@ -0,0 +1,498 @@
+<?xml version='1.0'?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<!--
+<<<<<<< conformance.xsl
+ Original version copyright 1999 by Sun Microsystems, Inc.
+ All Rights Reserved.
+ Modifications copyright 1999 by OASIS.
+ Modifications copyright 2001 by OASIS.
+ Modifications copyright 2002 by W3C.
+=======
+ XSL Stylesheet for documenting XML conformance tests.
+ Tested against LOTUS Xalan processor.
+>>>>>>> 1.3
+
+ XSL 2001-03-15 Stylesheet for documenting XML conformance tests.
+
+ This expects to be run on a document matching the DTD that Sun
+ defined for merging collections of self-descriptive XML tests.
+
+ Since all those collections will have (by design) the same test
+ architecture, this includes boilerplate describing that design,
+ to be used by all test documentation.
+
+ ISSUES:
+ - Sorting is a bit odd; section numbers can are like "3.3.3"
+ rather than straight numbers, so numeric sort can't work,
+ and yet neither does text sort (2.12 should be after 2.2).
+-->
+
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:output method="html" indent="yes"/>
+
+ <!-- ROOT: write an HTML wrapper -->
+ <xsl:template match="/TESTSUITE">
+ <!-- XHTML namespace -->
+
+ <html xmlns="http://www.w3.org/1999/xhtml"><head>
+ <title> XML Conformance Tests </title>
+ <meta http-equiv="Content-Type"
+ content="text/html;charset=utf-8"/>
+ <style type="text/css">
+
+ tr.premiere { background-color: #BEDCE6; }
+
+ th { text-align: left; vertical-align: top }
+
+ .editor { color: red; }
+
+ .countdown { color: white; background-color: red; }
+
+ blockquote, q { font-family: Arial, Helvetica, sans-serif; }
+
+ .quote { font-family: Arial, Helvetica, sans-serif; }
+
+ pre.quote { margin-left: 2.5em; }
+
+ ol.quote { font-family: Arial, Helvetica, sans-serif; margin-left: 3em; }
+
+ .diff-add { background-color: yellow; }
+
+ .diff-chg { background-color: lime; }
+
+ .diff-del { text-decoration: line-through; }
+
+ </style>
+
+ </head><body bgcolor='#ffffff'>
+ <p><a href="http://www.w3.org/"><img src="http://xw2k.sdct.itl.nist.gov/martinez/xmlts/2001/XML-Test-Suite/xmlconf/files/w3c_home.gif"
+
+ alt="W3C" height="48" width="72" border="0"/></a><a href="http://www.w3.org/Architecture/"
+
+ rel="in-domain"><img src="http://xw2k.sdct.itl.nist.gov/martinez/xmlts/2001/XML-Test-Suite/xmlconf/files/arquitecture.bmp" alt="Architecture Domain" border="0"/></a> <a
+
+ href="../" rel="in-area"> XML</a> | <a href="/Member/#confidential">Member-Confidential!</a></p>
+
+ <h1 align="center">XML 1.0 (Second Edition) errata 20020320,</h1>
+ <h1 align="center">W3C Conformance Test Suite 20020606</h1> <dl>
+
+
+ <dt><b>This version:</b></dt>
+ <dd><ul>
+ <li><p><a href="xmlconf-20020606.htm">
+ http://www.w3.org/XML/Test/xmlconf-20020606.htm</a>
+ (<a href="xmlconf-20020606.xml">XML</a>)</p>
+ </li>
+ </ul>
+ </dd>
+
+ <dt><b>Current Version:</b></dt>
+ <dd>
+ <ul>
+ <li><p><a href="xmlconf-20020606.xml">
+ http://www.w3.org/XML/Test/xmlconf-20020606.xml</a></p></li>
+ </ul>
+ </dd>
+
+ <dt><b>Previous Version:</b></dt>
+ <dd>
+ <ul>
+ <li><p><a href="http://www.oasis-open.org/committees/xml-conformance/suite-v1se/xmlconf-20010315.htm">
+ http://www.oasis-open.org/committees/xml-conformance/suite-v1se/xmlconf-20010315.htm</a>
+ (<a href="http://www.oasis-open.org/committees/xml-conformance/suite-v1se/xmlconf-20010315.xml">XML</a>)</p></li>
+ </ul>
+ </dd>
+
+ <dt><b>Test Archive:</b></dt>
+ <dd><ul>
+ <li><p><a href="xmlts20020606.zip">http://www.w3.org/XML/Test/xmlts20020606.zip</a>
+ </p></li>
+ <li><p><a href="xmlts20020606.tar">http://www.w3.org/XML/Test/xmlts20020606.tar</a>
+ </p></li>
+ </ul></dd>
+
+ <dt><b>W3C XML Core Working Group:</b></dt>
+ <dd><ul><li><p><a href="http://www.w3.org/XML/Group/Core">http://www.w3.org/XML/Group/Core</a>
+ </p></li></ul></dd>
+
+ <dt><b>Comments:</b></dt>
+ <dd><ul><li>Sandra I. Martinez, NIST <a href="mailto:[email protected]"> [email protected]</a>
+ </li></ul></dd>
+
+ </dl>
+
+ <a name="contents"/>
+ <h2>Table of Contents</h2>
+ <ol >
+ <li><a href="#intro">Introduction</a></li>
+ <li><a href="#matrix">Test Matrix</a></li>
+ <ol >
+ <li ><a href="#binary">Binary Tests</a></li>
+ <li><a href="#output">Output Tests</a></li>
+ </ol>
+ <li><a href="#listings">Test Case Descriptions</a></li>
+ <ol >
+ <li><a href="#valid">Valid Documents</a></li>
+ <li><a href="#invalid">Invalid Documents</a></li>
+ <li><a href="#not-wf">Not-WF Documents</a></li>
+ <li><a href="#error">Optional Errors</a></li>
+ </ol>
+ <li><a href="#contrib">Contributors</a></li>
+ </ol>
+ <a name="intro"/>
+ <h2>1. Introduction </h2>
+ <p>
+ The tests described in this document provide an initial set of metrics to determine how well a
+ particular implementation conforms to the
+ <a href="http://www.w3.org/TR/REC-xml">W3C XML 1.0 (Second Edition) Recommendation</a>.
+ The XML Conformance Test Suite is intended
+ to complement the W3C XML 1.0 (Second Edition) Recommendation. All interpretations
+ of this Recommendation are subject to confirmation by the
+ <a href="http://www.w3.org/XML/">
+ W3C XML Group </a>.
+ </p>
+ <p>
+ Conformance tests can be used by developers, content creators, and
+ users alike to increase their level of confidence in product quality. In
+ circumstances where interoperability is necessary, these tests can also
+ be used to determine that differing implementations support the same set
+ of features. </p>
+
+ <p>The XML Test Suite was transferred from OASIS to W3C and is being augmented to reflect the
+ current work of the W3C XML Core Working Group, including
+ <a href="http://www.w3.org/XML/Group/2002/02/xml10-test-suite-issues">resolved issues</a> related to the
+ Recommendation and published Errata. This report provides supporting documentation for all the tests included in
+ the test suite. Sources from which these tests have been collected
+ include: <em>
+ <xsl:for-each select="TESTCASES">
+ <xsl:value-of select="@PROFILE"/>
+ <xsl:text>; </xsl:text>
+ </xsl:for-each>
+ </em>. </p>
+
+ <a name="matrix"/>
+ <h2>2. Test Matrix </h2>
+
+ <p> Two basic types of test are presented here. These are
+ respectively <em><a href="#binary">Binary Tests</a></em>
+ and <em><a href="#output">Output Tests</a></em>. </p>
+
+ <a name="binary"/>
+ <h3>2.1 Binary Tests </h3>
+
+ <p> <em>Binary</em> conformance tests are documents which
+ are grouped into one of four categories. Given a document
+ in a given category, each kind of XML parser must treat it
+ consistently and either accept it (a <em>positive test</em>)
+ or reject it (a <em>negative test</em>). It is in that sense
+ that the tests are termed "binary". The XML 1.0 (Second Edition) Recommendation
+ talks in terms of two types of XML processor:
+ <em>validating</em> ones, and <em>nonvalidating</em> ones.
+ There are two differences between these types of processors: </p>
+
+ <ol>
+ <li> Validating processors check special productions that
+ nonvalidating parsers don't, called <em>validity
+ constraints</em>. (Both must check a basic set of productions,
+ requiring XML documents to be <em>well formed</em>.) </li>
+
+ <li> Nonvalidating processors are permitted to not
+ include <em>external entities</em>, such as files with
+ text. Accordingly, they may not report errors which
+ would have been detected had those entities been read.</li>
+ </ol>
+
+ <p> There are two types of such entity, <em>parameter
+ entities</em> holding definitions which affect validation
+ and other processing; and <em>general entities</em> which
+ hold marked up text. It will be appreciated that there are
+ then five kinds of XML processor: validating processors,
+ and four kinds of nonvalidating processor based on the
+ combinations of external entity which they include.</p>
+
+ <center>
+ <table border="1" bgcolor="#ffffff" cellpadding="4">
+
+ <caption>
+ <b>Basic XML Parsing Test Matrix</b><br/>
+ Test Document Type v. Parser Type
+ </caption>
+
+ <tr bgcolor="#ffffcc">
+ <th widthH="5%" rowspan="2"><xsl:text> </xsl:text></th>
+ <th widthH="20%" colspan="2">Nonvalidating</th>
+ <th widthH="5%" rowspan="2">Validating</th>
+ </tr>
+
+ <tr bgcolor="#ffffcc">
+ <th>External Entities<br/>Ignored (3 cases)</th>
+ <th>External Entities<br/>Read</th>
+ </tr>
+
+ <tr>
+ <th bgcolor="#ffffcc">Valid Documents</th>
+ <td align="center"><b>accept</b></td>
+ <td align="center"><b>accept</b></td>
+ <td align="center"><b>accept</b></td>
+ </tr>
+
+ <tr>
+ <th bgcolor="#ffffcc">Invalid Documents</th>
+ <td align="center"><b>accept</b></td>
+ <td align="center"><b>accept</b></td>
+ <td align="center">reject</td>
+ </tr>
+
+ <tr>
+ <th bgcolor="#ffffcc">Non-WF Documents</th>
+ <td align="center">reject</td>
+ <td align="center">reject</td>
+ <td align="center">reject</td>
+ </tr>
+
+ <tr>
+ <th bgcolor="#ffffcc">WF Errors tied<br/>
+ to External Entity</th>
+ <td align="center"><b>accept</b><br/>(varies)</td>
+ <td align="center">reject</td>
+ <td align="center">reject</td>
+ </tr>
+
+ <tr>
+ <th bgcolor="#ffffcc">Documents with<br/> Optional Errors</th>
+ <td align="center">(not specified)</td>
+ <td align="center">(not specified)</td>
+ <td align="center">(not specified)</td>
+ </tr>
+
+ </table>
+ </center>
+
+ <p> At this time, the XML community primarily uses parsers
+ which are in the rightmost two columns of this table, calling
+ them <em>Well Formed XML Parsers</em> (or "WF Parsers") and
+ <em>Validating XML Parsers</em>. A second test matrix
+ could be defined to address the variations in the types of
+ of XML processor which do not read all external entities.
+ That additional matrix is not provided here at this time. </p>
+
+
+ <a name="output"/>
+ <h3>2.2 Output Tests</h3>
+
+ <p> The XML 1.0 (Second Edition) Recommendation places a number of requirements
+ on XML processors, to ensure that they report information to
+ applications as needed. Such requirements are testable.
+ Validating processors are required to report slightly more
+ information than nonvalidating ones, so some tests will
+ require separate output files. Some of the information that
+ must be reported will not be reportable without reading all
+ the external entities in a particular test. Many of the tests for
+ valid documents are paired with an output file as the canonical
+ representation of the input file, to ensure that the XML
+ processor provides the correct information. </p>
+
+ <a name="listings"/>
+ <h2>3. Test Case Descriptions</h2>
+
+ <p> This section of this report contains descriptions of test
+ cases, each of which fits into the categories noted above.
+ Each test case includes a document of one of the types in the
+ binary test matrix above (e.g. valid or invalid documents).
+ </p>
+
+ <p> In some cases, an <a href="#output">output file </a>, as
+ described in Section 2.2, will also be associated with
+ a valid document, which is used for output testing. If such
+ a file exists, it will be noted at the end of the description
+ of the input document. </p>
+
+ <p> The description for each test case is presented as a two
+ part table. The right part describes what the test does.
+ This description is intended to have enough detail to evaluate
+ diagnostic messages. The left part includes: <ul>
+
+ <li> An entry describing the <em>Sections and/or Rules</em>
+ from the <a href="http://www.w3.org/TR/2000/REC-xml-20001006">
+ XML 1.0 (Second Edition) Recommendation</a> which this case excercises.</li>
+
+ <li> The unique <em>Test ID</em> within a given <em>Collection</em>
+ for this test. </li>
+
+ <li> The <em>Collection</em> from which this test originated.
+ Given the <em>Test ID</em> and the <em>Collection</em>, each
+ test can be uniquely identified.</li>
+
+ <li> Some tests may have a field identifying the kinds of
+ external <em>Entities</em> a nonvalidating processor must
+ include (parameter, general, or both) to be able to
+ detect any errors in that test case. </li>
+
+ </ul></p>
+
+ <a name="valid"/>
+ <h3>3.1 Valid XML Documents</h3>
+
+ <p> All conforming <em> XML 1.0 Processors </em> are
+ <b>required</b> to accept valid documents, reporting no
+ errors. In this section of this test report are found
+ descriptions of test cases which fit into this category. </p>
+
+ <xsl:apply-templates select="//TEST[@TYPE='valid']">
+ <xsl:sort select="@SECTIONS"/>
+ </xsl:apply-templates>
+
+ <a name="invalid"/>
+ <h3>3.2 Invalid XML Documents</h3>
+
+ <p> All conforming XML 1.0 <em> Validating Processors </em>
+ are <b>required</b> to report recoverable errors in the case
+ of documents which are <em>Invalid</em>. Such errors are
+ violations of some <em>validity constraint (VC)</em>. </p>
+
+ <p> If a validating processor does not report an error when
+ given one of these test cases, or if the error reported is
+ a fatal error, it is not conformant. If the error reported
+ does not correspond to the problem listed in this test
+ description, that could also be a conformance problem; it
+ might instead be a faulty diagnostic. </p>
+
+ <p> All conforming XML 1.0 <em> Nonvalidating Processors </em>
+ should accept these documents, reporting no errors. </p>
+
+ <xsl:apply-templates select="//TEST[@TYPE='invalid']">
+ <xsl:sort select="@SECTIONS"/>
+ </xsl:apply-templates>
+
+ <a name="not-wf"/>
+ <h3>3.3 Documents that are Not Well Formed</h3>
+
+ <p> All conforming XML 1.0 Processors are <b>required</b> to
+ report fatal errors in the case of documents which are not
+ <em>Well Formed</em>. Such errors are basically of two types:
+ <em>(a)</em> the document violates the XML grammar; or else
+ <em>(b)</em> it violates a <em>well formedness constraint
+ (WFC)</em>. There is a single <em>exception to that
+ requirement</em>: nonvalidating processors which do not read
+ certain types of external entities are not required to detect
+ (and hence report) these errors. </p>
+
+ <p> If a processor does not report a fatal error when given
+ one of these test cases, it is not conformant. If the error
+ reported does not correspond to the problem listed in this
+ test description, that could also be a conformance problem;
+ it might instead be a faulty diagnostic. </p>
+
+ <xsl:apply-templates select="//TEST[@TYPE='not-wf']">
+ <xsl:sort select="@SECTIONS"/>
+ </xsl:apply-templates>
+
+ <a name="error"/>
+ <h3>3.4 XML Documents with Optional Errors</h3>
+
+ <p> Conforming XML 1.0 Processors are permitted to ignore
+ certain errors, or to report them at user option. In this
+ section of this test report are found descriptions of
+ test cases which fit into this category. </p>
+
+ <p> Processor behavior on such test cases does not affect
+ conformance to the XML 1.0 (Second Edition) Recommendation, except as noted. </p>
+
+ <xsl:apply-templates select="//TEST[@TYPE='error']">
+ <xsl:sort select="@SECTIONS"/>
+ </xsl:apply-templates>
+
+ <a name="contrib"/>
+ <h3>4. Contributors (Non-normative)</h3>
+
+ <p> A team of volunteer members have participated in the
+ development of this work. Contributions have come from:
+ </p>
+ <ul>
+ <li>Murry Altheim, Sun Microsystems</li>
+ <li>Mary Brady, NIST</li>
+ <li>Tim Boland, NIST</li>
+ <li>David Brownell, Sun Microsystems</li>
+ <li>James Clark</li>
+ <li>Karin Donker, IBM</li>
+ <li>Irina Golfman, Inera Incorporated</li>
+ <li>Tony Graham, Mulberry Technologies</li>
+ <li>G. Ken Holman, Crane Softwrights Ltd</li>
+ <li>Alex Milowski, Veo Systems, Inc</li>
+ <li>Makota Murata, Fuji Xerox</li>
+ <li>Miles O'Reilly, Microstar Software, Ltd</li>
+ <li>Matt Timmermans, Microstar Software, Ltd</li>
+ <li>Richard Rivello, NIST</li>
+ <li>Lynne Rosenthal, NIST</li>
+ <li>Brian Schellar, Chrystal Software</li>
+ <li>Bill Smith, Sun Microsystems</li>
+ <li>Trevor Veary, Software AG</li>
+ <li>Richard Tobin, University of Edinburgh</li>
+ <li>Jonathan Marsh, Microsoft </li>
+ <li>Daniel Veillard, Imaq</li>
+ <li>Jonathan Marsh, Microsoft</li>
+ <li>Paul Grosso, Arbortext</li>
+
+ </ul>
+
+ <p>End</p>
+ </body></html>
+ </xsl:template>
+
+ <xsl:template match="TEST">
+ <table width="100%">
+ <tr valign="top">
+ <td width='40%'><table bgcolor='#eeeeff'
+ border='1' width='100%' height="100%">
+ <tr>
+ <td width='50%'><b>Sections [Rules]:</b></td>
+ <td bgcolor='#ffffcc'>
+ <xsl:value-of select="@SECTIONS"/></td>
+ </tr>
+ <tr valign="top">
+ <td width='50%'><b>Test ID:</b></td>
+ <td bgcolor='#ffffcc'>
+ <xsl:value-of select="@ID"/></td>
+ </tr>
+ <xsl:if test="not ( @ENTITIES = 'none')
+ and ( @TYPE = 'not-wf' )">
+ <tr valign="top">
+ <td width='50%'><b>Entities:</b></td>
+ <td bgcolor='#ffffcc'><font color='blue'>
+ <xsl:value-of select="@ENTITIES"/>
+ </font></td>
+ </tr>
+ </xsl:if>
+ <xsl:if test="../@PROFILE">
+ <tr valign="top">
+ <td width='50%'><b>Collection:</b></td>
+ <td bgcolor='#ffffcc'>
+ <xsl:value-of select="../@PROFILE"/>
+ </td>
+ </tr>
+ </xsl:if>
+ </table></td>
+ <td bgcolor='#ccffff'>
+ <p>
+ <xsl:apply-templates/></p>
+ <xsl:if test="@OUTPUT | @OUTPUT3">
+ <p>There is an output test associated with this
+ input file.</p>
+ </xsl:if>
+ </td>
+ </tr>
+ </table>
+ </xsl:template>
+
+ <!-- XT takes 'B|EM' and xsl:copy, IE5b2 doesn't -->
+ <xsl:template match="EM">
+ <em><xsl:apply-templates/></em>
+ </xsl:template>
+ <xsl:template match="B">
+ <b><xsl:apply-templates/></b>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/lib/xmerl/vsn.mk b/lib/xmerl/vsn.mk
index 280ff10efa..82df8fdeef 100644
--- a/lib/xmerl/vsn.mk
+++ b/lib/xmerl/vsn.mk
@@ -1 +1 @@
-XMERL_VSN = 1.2.8
+XMERL_VSN = 1.2.10